diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -454,13 +454,11 @@
 	return __ffs(tmp) + ofs;
 }
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
 #define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
 
-#include <asm-generic/bitops/minix.h>
-
 #endif /* __KERNEL__ */
 
 #endif /* _ALPHA_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,7 @@
 		struct page *page, unsigned long addr, int len);
 #endif
 
-/* This is used only in do_no_page and do_swap_page.  */
+/* This is used only in __do_fault and do_swap_page.  */
 #define flush_icache_page(vma, page) \
   flush_icache_user_range((vma), (page), 0, 0)
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/elf.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/elf.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/elf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/elf.h	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 
 #define ELF_PLAT_INIT(_r, load_addr)	_r->r0 = 0
 
-/* The registers are layed out in pt_regs for PAL and syscall
+/* The registers are laid out in pt_regs for PAL and syscall
    convenience.  Re-order them for the linear elf_gregset_t.  */
 
 struct pt_regs;
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/errno.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/errno.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/errno.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/errno.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,4 +122,6 @@
 
 #define	ERFKILL		138	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	139	/* Memory page has hardware error */
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/fcntl.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/fcntl.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/fcntl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/fcntl.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,8 @@
 #define __O_SYNC	020000000
 #define O_SYNC		(__O_SYNC|O_DSYNC)
 
+#define O_PATH		040000000
+
 #define F_GETLK		7
 #define F_SETLK		8
 #define F_SETLKW	9
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/futex.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 	:	"r" (uaddr), "r"(oparg)				\
 	:	"memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -81,21 +81,23 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	__asm__ __volatile__ (
 		__ASM_SMP_MB
-	"1:	ldl_l	%0,0(%2)\n"
-	"	cmpeq	%0,%3,%1\n"
-	"	beq	%1,3f\n"
-	"	mov	%4,%1\n"
-	"2:	stl_c	%1,0(%2)\n"
-	"	beq	%1,4f\n"
+	"1:	ldl_l	%1,0(%3)\n"
+	"	cmpeq	%1,%4,%2\n"
+	"	beq	%2,3f\n"
+	"	mov	%5,%2\n"
+	"2:	stl_c	%2,0(%3)\n"
+	"	beq	%2,4f\n"
 	"3:	.subsection 2\n"
 	"4:	br	1b\n"
 	"	.previous\n"
@@ -105,11 +107,12 @@
 	"	.long	2b-.\n"
 	"	lda	$31,3b-2b(%0)\n"
 	"	.previous\n"
-	:	"=&r"(prev), "=&r"(cmp)
+	:	"+r"(ret), "=&r"(prev), "=&r"(cmp)
 	:	"r"(uaddr), "r"((long)oldval), "r"(newval)
 	:	"memory");
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,6 +94,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,44 +13,13 @@
 #ifdef __KERNEL__
 
 #include <linux/compiler.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-struct rwsem_waiter;
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
 
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	long			count;
 #define RWSEM_UNLOCKED_VALUE		0x0000000000000000L
 #define RWSEM_ACTIVE_BIAS		0x0000000000000001L
 #define RWSEM_ACTIVE_MASK		0x00000000ffffffffL
 #define RWSEM_WAITING_BIAS		(-0x0000000100000000L)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-};
-
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	LIST_HEAD_INIT((name).wait_list) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
 
 static inline void __down_read(struct rw_semaphore *sem)
 {
@@ -250,10 +219,5 @@
 #endif
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ALPHA_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/types.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,16 +20,4 @@
 typedef unsigned int umode_t;
 
 #endif /* __ASSEMBLY__ */
-
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-typedef u64 dma_addr_t;
-typedef u64 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
 #endif /* _ALPHA_TYPES_H */
diff -druN linux-libre-2.6.38-gnu/arch/alpha/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/alpha/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/alpha/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -452,10 +452,14 @@
 #define __NR_fanotify_init		494
 #define __NR_fanotify_mark		495
 #define __NR_prlimit64			496
+#define __NR_name_to_handle_at		497
+#define __NR_open_by_handle_at		498
+#define __NR_clock_adjtime		499
+#define __NR_syncfs			500
 
 #ifdef __KERNEL__
 
-#define NR_SYSCALLS			497
+#define NR_SYSCALLS			501
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.38-gnu/arch/alpha/Kconfig linux-libre-2.6.39-gnu/arch/alpha/Kconfig
--- linux-libre-2.6.38-gnu/arch/alpha/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select AUTO_IRQ_AFFINITY if SMP
-	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select GENERIC_IRQ_SHOW
 	help
 	  The Alpha is a 64-bit general-purpose processor designed and
 	  marketed by the Digital Equipment Corporation of blessed memory,
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/core_lca.c linux-libre-2.6.39-gnu/arch/alpha/kernel/core_lca.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/core_lca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/core_lca.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,7 @@
 
 	local_irq_save(flags);
 
-	/* Reset status register to avoid loosing errors.  */
+	/* Reset status register to avoid losing errors.  */
 	stat0 = *(vulp)LCA_IOC_STAT0;
 	*(vulp)LCA_IOC_STAT0 = stat0;
 	mb();
@@ -170,7 +170,7 @@
 
 	local_irq_save(flags);	/* avoid getting hit by machine check */
 
-	/* Reset status register to avoid loosing errors.  */
+	/* Reset status register to avoid losing errors.  */
 	stat0 = *(vulp)LCA_IOC_STAT0;
 	*(vulp)LCA_IOC_STAT0 = stat0;
 	mb();
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/core_mcpcia.c linux-libre-2.6.39-gnu/arch/alpha/kernel/core_mcpcia.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/core_mcpcia.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/core_mcpcia.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 {
 	unsigned long flags;
 	unsigned long mid = MCPCIA_HOSE2MID(hose->index);
-	unsigned int stat0, value, temp, cpu;
+	unsigned int stat0, value, cpu;
 
 	cpu = smp_processor_id();
 
@@ -101,7 +101,7 @@
 	stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
 	*(vuip)MCPCIA_CAP_ERR(mid) = stat0;
 	mb();
-	temp = *(vuip)MCPCIA_CAP_ERR(mid);
+	*(vuip)MCPCIA_CAP_ERR(mid);
 	DBG_CFG(("conf_read: MCPCIA_CAP_ERR(%d) was 0x%x\n", mid, stat0));
 
 	mb();
@@ -136,7 +136,7 @@
 {
 	unsigned long flags;
 	unsigned long mid = MCPCIA_HOSE2MID(hose->index);
-	unsigned int stat0, temp, cpu;
+	unsigned int stat0, cpu;
 
 	cpu = smp_processor_id();
 
@@ -145,7 +145,7 @@
 	/* Reset status register to avoid losing errors.  */
 	stat0 = *(vuip)MCPCIA_CAP_ERR(mid);
 	*(vuip)MCPCIA_CAP_ERR(mid) = stat0; mb();
-	temp = *(vuip)MCPCIA_CAP_ERR(mid);
+	*(vuip)MCPCIA_CAP_ERR(mid);
 	DBG_CFG(("conf_write: MCPCIA CAP_ERR(%d) was 0x%x\n", mid, stat0));
 
 	draina();
@@ -157,7 +157,7 @@
 	*((vuip)addr) = value;
 	mb();
 	mb();  /* magic */
-	temp = *(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
+	*(vuip)MCPCIA_CAP_ERR(mid); /* read to force the write */
 	mcheck_expected(cpu) = 0;
 	mb();
 
@@ -572,12 +572,10 @@
 void
 mcpcia_machine_check(unsigned long vector, unsigned long la_ptr)
 {
-	struct el_common *mchk_header;
 	struct el_MCPCIA_uncorrected_frame_mcheck *mchk_logout;
 	unsigned int cpu = smp_processor_id();
 	int expected;
 
-	mchk_header = (struct el_common *)la_ptr;
 	mchk_logout = (struct el_MCPCIA_uncorrected_frame_mcheck *)la_ptr;
 	expected = mcheck_expected(cpu);
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/err_marvel.c linux-libre-2.6.39-gnu/arch/alpha/kernel/err_marvel.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/err_marvel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/err_marvel.c	2011-05-19 00:06:34.000000000 -0400
@@ -1027,7 +1027,7 @@
 	 * normal operation, dismiss them.
 	 *
 	 * Dismiss if:
-	 *	C_STAT		= 0x14 		(Error Reponse)
+	 *	C_STAT		= 0x14 		(Error Response)
 	 *	C_STS<3>	= 0    		(C_ADDR valid)
 	 *	C_ADDR<42>	= 1    		(I/O)
 	 *	C_ADDR<31:22>	= 111110xxb	(PCI Config space)
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/err_titan.c linux-libre-2.6.39-gnu/arch/alpha/kernel/err_titan.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/err_titan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/err_titan.c	2011-05-19 00:06:34.000000000 -0400
@@ -533,8 +533,6 @@
 static struct el_subpacket *
 el_process_regatta_subpacket(struct el_subpacket *header)
 {
-	int status;
-
 	if (header->class != EL_CLASS__REGATTA_FAMILY) {
 		printk("%s  ** Unexpected header CLASS %d TYPE %d, aborting\n",
 		       err_print_prefix,
@@ -551,7 +549,7 @@
 		printk("%s  ** Occurred on CPU %d:\n", 
 		       err_print_prefix,
 		       (int)header->by_type.regatta_frame.cpuid);
-		status = privateer_process_logout_frame((struct el_common *)
+		privateer_process_logout_frame((struct el_common *)
 			header->by_type.regatta_frame.data_start, 1);
 		break;
 	default:
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_alpha.c linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_alpha.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_alpha.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_alpha.c	2011-05-19 00:06:34.000000000 -0400
@@ -228,7 +228,7 @@
 void __init
 init_rtc_irq(void)
 {
-	set_irq_chip_and_handler_name(RTC_IRQ, &no_irq_chip,
+	irq_set_chip_and_handler_name(RTC_IRQ, &dummy_irq_chip,
 				      handle_simple_irq, "RTC");
 	setup_irq(RTC_IRQ, &timer_irqaction);
 }
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/irq.c linux-libre-2.6.39-gnu/arch/alpha/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,68 +67,21 @@
 }
 #endif /* CONFIG_SMP */
 
-int
-show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	int j;
-	int irq = *(loff_t *) v;
-	struct irqaction * action;
-	struct irq_desc *desc;
-	unsigned long flags;
 
 #ifdef CONFIG_SMP
-	if (irq == 0) {
-		seq_puts(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ", j);
-		seq_putc(p, '\n');
-	}
-#endif
-
-	if (irq < ACTUAL_NR_IRQS) {
-		desc = irq_to_desc(irq);
-
-		if (!desc)
-			return 0;
-
-		raw_spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
-		if (!action) 
-			goto unlock;
-		seq_printf(p, "%3d: ", irq);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(irq));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(irq, j));
-#endif
-		seq_printf(p, " %14s", get_irq_desc_chip(desc)->name);
-		seq_printf(p, "  %c%s",
-			(action->flags & IRQF_DISABLED)?'+':' ',
-			action->name);
-
-		for (action=action->next; action; action = action->next) {
-			seq_printf(p, ", %c%s",
-				  (action->flags & IRQF_DISABLED)?'+':' ',
-				   action->name);
-		}
-
-		seq_putc(p, '\n');
-unlock:
-		raw_spin_unlock_irqrestore(&desc->lock, flags);
-	} else if (irq == ACTUAL_NR_IRQS) {
-#ifdef CONFIG_SMP
-		seq_puts(p, "IPI: ");
-		for_each_online_cpu(j)
-			seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
-		seq_putc(p, '\n');
+	seq_puts(p, "IPI: ");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10lu ", cpu_data[j].ipi_count);
+	seq_putc(p, '\n');
 #endif
-		seq_puts(p, "PMI: ");
-		for_each_online_cpu(j)
-			seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j));
-		seq_puts(p, "          Performance Monitoring\n");
-		seq_printf(p, "ERR: %10lu\n", irq_err_count);
-	}
+	seq_puts(p, "PMI: ");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j));
+	seq_puts(p, "          Performance Monitoring\n");
+	seq_printf(p, "ERR: %10lu\n", irq_err_count);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_i8259.c linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_i8259.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_i8259.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_i8259.c	2011-05-19 00:06:34.000000000 -0400
@@ -92,7 +92,7 @@
 	outb(0xff, 0xA1);	/* mask all of 8259A-2 */
 
 	for (i = 0; i < 16; i++) {
-		set_irq_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &i8259a_irq_type, handle_level_irq);
 	}
 
 	setup_irq(2, &cascade);
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_pyxis.c linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_pyxis.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_pyxis.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_pyxis.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,7 @@
 	for (i = 16; i < 48; ++i) {
 		if ((ignore_mask >> i) & 1)
 			continue;
-		set_irq_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &pyxis_irq_type, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_srm.c linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_srm.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/irq_srm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/irq_srm.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
 	for (i = 16; i < max; ++i) {
 		if (i < 64 && ((ignore_mask >> i) & 1))
 			continue;
-		set_irq_chip_and_handler(i, &srm_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &srm_irq_type, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/Makefile linux-libre-2.6.39-gnu/arch/alpha/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 
 extra-y		:= head.o vmlinux.lds
 asflags-y	:= $(KBUILD_CFLAGS)
-ccflags-y	:= -Werror -Wno-sign-compare
+ccflags-y	:= -Wno-sign-compare
 
 obj-y    := entry.o traps.o process.o init_task.o osf_sys.o irq.o \
 	    irq_alpha.o signal.o setup.o ptrace.o time.o \
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/osf_sys.c linux-libre-2.6.39-gnu/arch/alpha/kernel/osf_sys.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/osf_sys.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/osf_sys.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,44 +230,24 @@
 	return copy_to_user(osf_stat, &tmp_stat, bufsiz) ? -EFAULT : 0;
 }
 
-static int
-do_osf_statfs(struct path *path, struct osf_statfs __user *buffer,
-	      unsigned long bufsiz)
+SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
+		struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
 	struct kstatfs linux_stat;
-	int error = vfs_statfs(path, &linux_stat);
+	int error = user_statfs(pathname, &linux_stat);
 	if (!error)
 		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
 	return error;	
 }
 
-SYSCALL_DEFINE3(osf_statfs, const char __user *, pathname,
-		struct osf_statfs __user *, buffer, unsigned long, bufsiz)
-{
-	struct path path;
-	int retval;
-
-	retval = user_path(pathname, &path);
-	if (!retval) {
-		retval = do_osf_statfs(&path, buffer, bufsiz);
-		path_put(&path);
-	}
-	return retval;
-}
-
 SYSCALL_DEFINE3(osf_fstatfs, unsigned long, fd,
 		struct osf_statfs __user *, buffer, unsigned long, bufsiz)
 {
-	struct file *file;
-	int retval;
-
-	retval = -EBADF;
-	file = fget(fd);
-	if (file) {
-		retval = do_osf_statfs(&file->f_path, buffer, bufsiz);
-		fput(file);
-	}
-	return retval;
+	struct kstatfs linux_stat;
+	int error = fd_statfs(fd, &linux_stat);
+	if (!error)
+		error = linux_to_osf_statfs(&linux_stat, buffer, bufsiz);
+	return error;
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/setup.c linux-libre-2.6.39-gnu/arch/alpha/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -1404,8 +1404,6 @@
 	case PCA56_CPU:
 	case PCA57_CPU:
 	  {
-		unsigned long cbox_config, size;
-
 		if (cpu_type == PCA56_CPU) {
 			L1I = CSHAPE(16*1024, 6, 1);
 			L1D = CSHAPE(8*1024, 5, 1);
@@ -1415,10 +1413,12 @@
 		}
 		L3 = -1;
 
+#if 0
+		unsigned long cbox_config, size;
+
 		cbox_config = *(vulp) phys_to_virt (0xfffff00008UL);
 		size = 512*1024 * (1 << ((cbox_config >> 12) & 3));
 
-#if 0
 		L2 = ((cbox_config >> 31) & 1 ? CSHAPE (size, 6, 1) : -1);
 #else
 		L2 = external_cache_probe(512*1024, 6);
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/smc37c93x.c linux-libre-2.6.39-gnu/arch/alpha/kernel/smc37c93x.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/smc37c93x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/smc37c93x.c	2011-05-19 00:06:34.000000000 -0400
@@ -79,7 +79,6 @@
 static unsigned long __init SMCConfigState(unsigned long baseAddr)
 {
 	unsigned char devId;
-	unsigned char devRev;
 
 	unsigned long configPort;
 	unsigned long indexPort;
@@ -100,7 +99,7 @@
 		devId = inb(dataPort);
 		if (devId == VALID_DEVICE_ID) {
 			outb(DEVICE_REV, indexPort);
-			devRev = inb(dataPort);
+			/* unsigned char devRev = */ inb(dataPort);
 			break;
 		}
 		else
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_alcor.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_alcor.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_alcor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_alcor.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,7 +125,7 @@
 		   on while IRQ probing.  */
 		if (i >= 16+20 && i <= 16+30)
 			continue;
-		set_irq_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &alcor_irq_type, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 	i8259a_irq_type.irq_ack = alcor_isa_mask_and_ack_irq;
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_cabriolet.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_cabriolet.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_cabriolet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_cabriolet.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,8 +105,8 @@
 		outb(0xff, 0x806);
 
 		for (i = 16; i < 35; ++i) {
-			set_irq_chip_and_handler(i, &cabriolet_irq_type,
-				handle_level_irq);
+			irq_set_chip_and_handler(i, &cabriolet_irq_type,
+						 handle_level_irq);
 			irq_set_status_flags(i, IRQ_LEVEL);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_dp264.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_dp264.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_dp264.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_dp264.c	2011-05-19 00:06:34.000000000 -0400
@@ -270,7 +270,7 @@
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
-		set_irq_chip_and_handler(i, ops, handle_level_irq);
+		irq_set_chip_and_handler(i, ops, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_eb64p.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_eb64p.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_eb64p.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_eb64p.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,7 @@
 	init_i8259a_irqs();
 
 	for (i = 16; i < 32; ++i) {
-		set_irq_chip_and_handler(i, &eb64p_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &eb64p_irq_type, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_eiger.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_eiger.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_eiger.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_eiger.c	2011-05-19 00:06:34.000000000 -0400
@@ -138,7 +138,7 @@
 	init_i8259a_irqs();
 
 	for (i = 16; i < 128; ++i) {
-		set_irq_chip_and_handler(i, &eiger_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &eiger_irq_type, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_jensen.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_jensen.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_jensen.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_jensen.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,11 +171,11 @@
 {
 	init_i8259a_irqs();
 
-	set_irq_chip_and_handler(1, &jensen_local_irq_type, handle_level_irq);
-	set_irq_chip_and_handler(4, &jensen_local_irq_type, handle_level_irq);
-	set_irq_chip_and_handler(3, &jensen_local_irq_type, handle_level_irq);
-	set_irq_chip_and_handler(7, &jensen_local_irq_type, handle_level_irq);
-	set_irq_chip_and_handler(9, &jensen_local_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(1, &jensen_local_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(4, &jensen_local_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(3, &jensen_local_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(7, &jensen_local_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(9, &jensen_local_irq_type, handle_level_irq);
 
 	common_init_isa_dma();
 }
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_marvel.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_marvel.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_marvel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_marvel.c	2011-05-19 00:06:34.000000000 -0400
@@ -276,7 +276,7 @@
 
 	/* Set up the lsi irqs.  */
 	for (i = 0; i < 128; ++i) {
-		set_irq_chip_and_handler(base + i, lsi_ops, handle_level_irq);
+		irq_set_chip_and_handler(base + i, lsi_ops, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
@@ -290,7 +290,7 @@
 
 	/* Set up the msi irqs.  */
 	for (i = 128; i < (128 + 512); ++i) {
-		set_irq_chip_and_handler(base + i, msi_ops, handle_level_irq);
+		irq_set_chip_and_handler(base + i, msi_ops, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
@@ -308,8 +308,8 @@
 
 	/* Reserve the legacy irqs.  */
 	for (i = 0; i < 16; ++i) {
-		set_irq_chip_and_handler(i, &marvel_legacy_irq_type,
-			handle_level_irq);
+		irq_set_chip_and_handler(i, &marvel_legacy_irq_type,
+					 handle_level_irq);
 	}
 
 	/* Init the io7 irqs.  */
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_mikasa.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_mikasa.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_mikasa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_mikasa.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,7 +98,8 @@
 	mikasa_update_irq_hw(0);
 
 	for (i = 16; i < 32; ++i) {
-		set_irq_chip_and_handler(i, &mikasa_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &mikasa_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_noritake.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_noritake.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_noritake.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_noritake.c	2011-05-19 00:06:34.000000000 -0400
@@ -127,7 +127,8 @@
 	outw(0, 0x54c);
 
 	for (i = 16; i < 48; ++i) {
-		set_irq_chip_and_handler(i, &noritake_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &noritake_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_rawhide.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_rawhide.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_rawhide.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_rawhide.c	2011-05-19 00:06:34.000000000 -0400
@@ -180,7 +180,8 @@
 	}
 
 	for (i = 16; i < 128; ++i) {
-		set_irq_chip_and_handler(i, &rawhide_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &rawhide_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_rx164.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_rx164.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_rx164.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_rx164.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 
 	rx164_update_irq_hw(0);
 	for (i = 16; i < 40; ++i) {
-		set_irq_chip_and_handler(i, &rx164_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &rx164_irq_type, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_sable.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_sable.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_sable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_sable.c	2011-05-19 00:06:34.000000000 -0400
@@ -518,8 +518,8 @@
 	long i;
 
 	for (i = 0; i < nr_of_irqs; ++i) {
-		set_irq_chip_and_handler(i, &sable_lynx_irq_type,
-			handle_level_irq);
+		irq_set_chip_and_handler(i, &sable_lynx_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_takara.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_takara.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_takara.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_takara.c	2011-05-19 00:06:34.000000000 -0400
@@ -138,7 +138,8 @@
 		takara_update_irq_hw(i, -1);
 
 	for (i = 16; i < 128; ++i) {
-		set_irq_chip_and_handler(i, &takara_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &takara_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/systbls.S linux-libre-2.6.39-gnu/arch/alpha/kernel/systbls.S
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/systbls.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/systbls.S	2011-05-19 00:06:34.000000000 -0400
@@ -498,23 +498,27 @@
 	.quad sys_ni_syscall			/* sys_timerfd */
 	.quad sys_eventfd
 	.quad sys_recvmmsg
-	.quad sys_fallocate				/* 480 */
+	.quad sys_fallocate			/* 480 */
 	.quad sys_timerfd_create
 	.quad sys_timerfd_settime
 	.quad sys_timerfd_gettime
 	.quad sys_signalfd4
-	.quad sys_eventfd2				/* 485 */
+	.quad sys_eventfd2			/* 485 */
 	.quad sys_epoll_create1
 	.quad sys_dup3
 	.quad sys_pipe2
 	.quad sys_inotify_init1
-	.quad sys_preadv				/* 490 */
+	.quad sys_preadv			/* 490 */
 	.quad sys_pwritev
 	.quad sys_rt_tgsigqueueinfo
 	.quad sys_perf_event_open
 	.quad sys_fanotify_init
-	.quad sys_fanotify_mark				/* 495 */
+	.quad sys_fanotify_mark			/* 495 */
 	.quad sys_prlimit64
+	.quad sys_name_to_handle_at
+	.quad sys_open_by_handle_at
+	.quad sys_clock_adjtime
+	.quad sys_syncfs			/* 500 */
 
 	.size sys_call_table, . - sys_call_table
 	.type sys_call_table, @object
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_titan.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_titan.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_titan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_titan.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,7 +179,7 @@
 {
 	long i;
 	for (i = imin; i <= imax; ++i) {
-		set_irq_chip_and_handler(i, ops, handle_level_irq);
+		irq_set_chip_and_handler(i, ops, handle_level_irq);
 		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_wildfire.c linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_wildfire.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/sys_wildfire.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/sys_wildfire.c	2011-05-19 00:06:34.000000000 -0400
@@ -156,7 +156,6 @@
 wildfire_init_irq_per_pca(int qbbno, int pcano)
 {
 	int i, irq_bias;
-	unsigned long io_bias;
 	static struct irqaction isa_enable = {
 		.handler	= no_action,
 		.name		= "isa_enable",
@@ -165,10 +164,12 @@
 	irq_bias = qbbno * (WILDFIRE_PCA_PER_QBB * WILDFIRE_IRQ_PER_PCA)
 		 + pcano * WILDFIRE_IRQ_PER_PCA;
 
+#if 0
+	unsigned long io_bias;
+
 	/* Only need the following for first PCI bus per PCA. */
 	io_bias = WILDFIRE_IO(qbbno, pcano<<1) - WILDFIRE_IO_BIAS;
 
-#if 0
 	outb(0, DMA1_RESET_REG + io_bias);
 	outb(0, DMA2_RESET_REG + io_bias);
 	outb(DMA_MODE_CASCADE, DMA2_MODE_REG + io_bias);
@@ -183,17 +184,17 @@
 	for (i = 0; i < 16; ++i) {
 		if (i == 2)
 			continue;
-		set_irq_chip_and_handler(i+irq_bias, &wildfire_irq_type,
-			handle_level_irq);
+		irq_set_chip_and_handler(i + irq_bias, &wildfire_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
 	}
 
-	set_irq_chip_and_handler(36+irq_bias, &wildfire_irq_type,
-		handle_level_irq);
+	irq_set_chip_and_handler(36 + irq_bias, &wildfire_irq_type,
+				 handle_level_irq);
 	irq_set_status_flags(36 + irq_bias, IRQ_LEVEL);
 	for (i = 40; i < 64; ++i) {
-		set_irq_chip_and_handler(i+irq_bias, &wildfire_irq_type,
-			handle_level_irq);
+		irq_set_chip_and_handler(i + irq_bias, &wildfire_irq_type,
+					 handle_level_irq);
 		irq_set_status_flags(i + irq_bias, IRQ_LEVEL);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/time.c linux-libre-2.6.39-gnu/arch/alpha/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -153,13 +153,14 @@
 		year += 100;
 
 	ts->tv_sec = mktime(year, mon, day, hour, min, sec);
+	ts->tv_nsec = 0;
 }
 
 
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 irqreturn_t timer_interrupt(int irq, void *dev)
 {
@@ -172,8 +173,6 @@
 	profile_tick(CPU_PROFILING);
 #endif
 
-	write_seqlock(&xtime_lock);
-
 	/*
 	 * Calculate how many ticks have passed since the last update,
 	 * including any previous partial leftover.  Save any resulting
@@ -187,9 +186,7 @@
 	nticks = delta >> FIX_SHIFT;
 
 	if (nticks)
-		do_timer(nticks);
-
-	write_sequnlock(&xtime_lock);
+		xtime_update(nticks);
 
 	if (test_irq_work_pending()) {
 		clear_irq_work_pending();
@@ -378,8 +375,7 @@
 
 static inline void register_rpcc_clocksource(long cycle_freq)
 {
-	clocksource_calc_mult_shift(&clocksource_rpcc, cycle_freq, 4);
-	clocksource_register(&clocksource_rpcc);
+	clocksource_register_hz(&clocksource_rpcc, cycle_freq);
 }
 #else /* !CONFIG_SMP */
 static inline void register_rpcc_clocksource(long cycle_freq)
diff -druN linux-libre-2.6.38-gnu/arch/alpha/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/alpha/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/alpha/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,6 @@
 #include <asm-generic/vmlinux.lds.h>
 #include <asm/thread_info.h>
+#include <asm/cache.h>
 #include <asm/page.h>
 
 OUTPUT_FORMAT("elf64-alpha")
@@ -38,7 +39,7 @@
 	__init_begin = ALIGN(PAGE_SIZE);
 	INIT_TEXT_SECTION(PAGE_SIZE)
 	INIT_DATA_SECTION(16)
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 	/* Align to THREAD_SIZE rather than PAGE_SIZE here so any padding page
 	   needed for the THREAD_SIZE aligned init_task gets freed after init */
 	. = ALIGN(THREAD_SIZE);
@@ -46,7 +47,7 @@
 	/* Freed after init ends here */
 
 	_data = .;
-	RW_DATA_SECTION(64, PAGE_SIZE, THREAD_SIZE)
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
 
 	.got : {
 		*(.got)
diff -druN linux-libre-2.6.38-gnu/arch/alpha/lib/ev67-strrchr.S linux-libre-2.6.39-gnu/arch/alpha/lib/ev67-strrchr.S
--- linux-libre-2.6.38-gnu/arch/alpha/lib/ev67-strrchr.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/lib/ev67-strrchr.S	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 $eos:
 	negq	t1, t4		# E : isolate first null byte match
 	and	t1, t4, t4	# E :
-	subq	t4, 1, t5	# E : build a mask of the bytes upto...
+	subq	t4, 1, t5	# E : build a mask of the bytes up to...
 	or	t4, t5, t4	# E : ... and including the null
 
 	and	t3, t4, t3	# E : mask out char matches after null
diff -druN linux-libre-2.6.38-gnu/arch/alpha/lib/fls.c linux-libre-2.6.39-gnu/arch/alpha/lib/fls.c
--- linux-libre-2.6.38-gnu/arch/alpha/lib/fls.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/lib/fls.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 #include <linux/bitops.h>
 
 /* This is fls(x)-1, except zero is held to zero.  This allows most
-   efficent input into extbl, plus it allows easy handling of fls(0)=0.  */
+   efficient input into extbl, plus it allows easy handling of fls(0)=0.  */
 
 const unsigned char __flsm1_tab[256] = 
 {
diff -druN linux-libre-2.6.38-gnu/arch/alpha/lib/strrchr.S linux-libre-2.6.39-gnu/arch/alpha/lib/strrchr.S
--- linux-libre-2.6.38-gnu/arch/alpha/lib/strrchr.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/lib/strrchr.S	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 $eos:
 	negq	t1, t4		# e0    : isolate first null byte match
 	and	t1, t4, t4	# e1    :
-	subq	t4, 1, t5	# e0    : build a mask of the bytes upto...
+	subq	t4, 1, t5	# e0    : build a mask of the bytes up to...
 	or	t4, t5, t4	# e1    : ... and including the null
 
 	and	t3, t4, t3	# e0    : mask out char matches after null
diff -druN linux-libre-2.6.38-gnu/arch/alpha/oprofile/op_model_ev67.c linux-libre-2.6.39-gnu/arch/alpha/oprofile/op_model_ev67.c
--- linux-libre-2.6.38-gnu/arch/alpha/oprofile/op_model_ev67.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/alpha/oprofile/op_model_ev67.c	2011-05-19 00:06:34.000000000 -0400
@@ -192,7 +192,7 @@
 		case TRAP_INVALID1:
 		case TRAP_INVALID2:
 		case TRAP_INVALID3:
-			/* Pipeline redirection ocurred. PMPC points
+			/* Pipeline redirection occurred. PMPC points
 			   to PALcode. Recognize ITB miss by PALcode
 			   offset address, and get actual PC from
 			   EXC_ADDR.  */
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/head.S linux-libre-2.6.39-gnu/arch/arm/boot/compressed/head.S
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -21,18 +21,10 @@
 
 #if defined(CONFIG_DEBUG_ICEDCC)
 
-#ifdef CONFIG_CPU_V6
-		.macro	loadsp, rb, tmp
-		.endm
-		.macro	writeb, ch, rb
-		mcr	p14, 0, \ch, c0, c5, 0
-		.endm
-#elif defined(CONFIG_CPU_V7)
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
 		.macro	loadsp, rb, tmp
 		.endm
 		.macro	writeb, ch, rb
-wait:		mrc	p14, 0, pc, c0, c1, 0
-		bcs	wait
 		mcr	p14, 0, \ch, c0, c5, 0
 		.endm
 #elif defined(CONFIG_CPU_XSCALE)
@@ -128,14 +120,14 @@
 		.arm				@ Always enter in ARM state
 start:
 		.type	start,#function
- THUMB(		adr	r12, BSYM(1f)	)
- THUMB(		bx	r12		)
- THUMB(		.rept	6		)
- ARM(		.rept	8		)
+		.rept	7
 		mov	r0, r0
 		.endr
+   ARM(		mov	r0, r0		)
+   ARM(		b	1f		)
+ THUMB(		adr	r12, BSYM(1f)	)
+ THUMB(		bx	r12		)
 
-		b	1f
 		.word	0x016f2818		@ Magic numbers to help the loader
 		.word	start			@ absolute load/run zImage address
 		.word	_edata			@ zImage end address
@@ -174,9 +166,7 @@
 		 */
 
 		.text
-		adr	r0, LC0
-		ldmia	r0, {r1, r2, r3, r5, r6, r11, ip}
-		ldr	sp, [r0, #28]
+
 #ifdef CONFIG_AUTO_ZRELADDR
 		@ determine final kernel image address
 		mov	r4, pc
@@ -185,35 +175,121 @@
 #else
 		ldr	r4, =zreladdr
 #endif
-		subs	r0, r0, r1		@ calculate the delta offset
 
-						@ if delta is zero, we are
-		beq	not_relocated		@ running at the address we
-						@ were linked at.
+		bl	cache_on
+
+restart:	adr	r0, LC0
+		ldmia	r0, {r1, r2, r3, r6, r9, r11, r12}
+		ldr	sp, [r0, #28]
 
 		/*
-		 * We're running at a different address.  We need to fix
-		 * up various pointers:
-		 *   r5 - zImage base address (_start)
-		 *   r6 - size of decompressed image
-		 *   r11 - GOT start
-		 *   ip - GOT end
+		 * We might be running at a different address.  We need
+		 * to fix up various pointers.
 		 */
-		add	r5, r5, r0
+		sub	r0, r0, r1		@ calculate the delta offset
+		add	r6, r6, r0		@ _edata
+
+#ifndef CONFIG_ZBOOT_ROM
+		/* malloc space is above the relocated stack (64k max) */
+		add	sp, sp, r0
+		add	r10, sp, #0x10000
+#else
+		/*
+		 * With ZBOOT_ROM the bss/stack is non relocatable,
+		 * but someone could still run this code from RAM,
+		 * in which case our reference is _edata.
+		 */
+		mov	r10, r6
+#endif
+
+/*
+ * Check to see if we will overwrite ourselves.
+ *   r4  = final kernel address
+ *   r9  = size of decompressed image
+ *   r10 = end of this image, including  bss/stack/malloc space if non XIP
+ * We basically want:
+ *   r4 - 16k page directory >= r10 -> OK
+ *   r4 + image length <= current position (pc) -> OK
+ */
+		add	r10, r10, #16384
+		cmp	r4, r10
+		bhs	wont_overwrite
+		add	r10, r4, r9
+   ARM(		cmp	r10, pc		)
+ THUMB(		mov	lr, pc		)
+ THUMB(		cmp	r10, lr		)
+		bls	wont_overwrite
+
+/*
+ * Relocate ourselves past the end of the decompressed kernel.
+ *   r6  = _edata
+ *   r10 = end of the decompressed kernel
+ * Because we always copy ahead, we need to do it from the end and go
+ * backward in case the source and destination overlap.
+ */
+		/*
+		 * Bump to the next 256-byte boundary with the size of
+		 * the relocation code added. This avoids overwriting
+		 * ourself when the offset is small.
+		 */
+		add	r10, r10, #((reloc_code_end - restart + 256) & ~255)
+		bic	r10, r10, #255
+
+		/* Get start of code we want to copy and align it down. */
+		adr	r5, restart
+		bic	r5, r5, #31
+
+		sub	r9, r6, r5		@ size to copy
+		add	r9, r9, #31		@ rounded up to a multiple
+		bic	r9, r9, #31		@ ... of 32 bytes
+		add	r6, r9, r5
+		add	r9, r9, r10
+
+1:		ldmdb	r6!, {r0 - r3, r10 - r12, lr}
+		cmp	r6, r5
+		stmdb	r9!, {r0 - r3, r10 - r12, lr}
+		bhi	1b
+
+		/* Preserve offset to relocated code. */
+		sub	r6, r9, r6
+
+#ifndef CONFIG_ZBOOT_ROM
+		/* cache_clean_flush may use the stack, so relocate it */
+		add	sp, sp, r6
+#endif
+
+		bl	cache_clean_flush
+
+		adr	r0, BSYM(restart)
+		add	r0, r0, r6
+		mov	pc, r0
+
+wont_overwrite:
+/*
+ * If delta is zero, we are running at the address we were linked at.
+ *   r0  = delta
+ *   r2  = BSS start
+ *   r3  = BSS end
+ *   r4  = kernel execution address
+ *   r7  = architecture ID
+ *   r8  = atags pointer
+ *   r11 = GOT start
+ *   r12 = GOT end
+ *   sp  = stack pointer
+ */
+		teq	r0, #0
+		beq	not_relocated
 		add	r11, r11, r0
-		add	ip, ip, r0
+		add	r12, r12, r0
 
 #ifndef CONFIG_ZBOOT_ROM
 		/*
 		 * If we're running fully PIC === CONFIG_ZBOOT_ROM = n,
 		 * we need to fix up pointers into the BSS region.
-		 *   r2 - BSS start
-		 *   r3 - BSS end
-		 *   sp - stack pointer
+		 * Note that the stack pointer has already been fixed up.
 		 */
 		add	r2, r2, r0
 		add	r3, r3, r0
-		add	sp, sp, r0
 
 		/*
 		 * Relocate all entries in the GOT table.
@@ -221,7 +297,7 @@
 1:		ldr	r1, [r11, #0]		@ relocate entries in the GOT
 		add	r1, r1, r0		@ table.  This fixes up the
 		str	r1, [r11], #4		@ C references.
-		cmp	r11, ip
+		cmp	r11, r12
 		blo	1b
 #else
 
@@ -234,7 +310,7 @@
 		cmphs	r3, r1			@ _end < entry
 		addlo	r1, r1, r0		@ table.  This fixes up the
 		str	r1, [r11], #4		@ C references.
-		cmp	r11, ip
+		cmp	r11, r12
 		blo	1b
 #endif
 
@@ -246,88 +322,35 @@
 		cmp	r2, r3
 		blo	1b
 
-		/*
-		 * The C runtime environment should now be setup
-		 * sufficiently.  Turn the cache on, set up some
-		 * pointers, and start decompressing.
-		 */
-		bl	cache_on
-
-		mov	r1, sp			@ malloc space above stack
-		add	r2, sp, #0x10000	@ 64k max
-
 /*
- * Check to see if we will overwrite ourselves.
- *   r4 = final kernel address
- *   r5 = start of this image
- *   r6 = size of decompressed image
- *   r2 = end of malloc space (and therefore this image)
- * We basically want:
- *   r4 >= r2 -> OK
- *   r4 + image length <= r5 -> OK
+ * The C runtime environment should now be setup sufficiently.
+ * Set up some pointers, and start decompressing.
+ *   r4  = kernel execution address
+ *   r7  = architecture ID
+ *   r8  = atags pointer
  */
-		cmp	r4, r2
-		bhs	wont_overwrite
-		add	r0, r4, r6
-		cmp	r0, r5
-		bls	wont_overwrite
-
-		mov	r5, r2			@ decompress after malloc space
-		mov	r0, r5
+		mov	r0, r4
+		mov	r1, sp			@ malloc space above stack
+		add	r2, sp, #0x10000	@ 64k max
 		mov	r3, r7
 		bl	decompress_kernel
-
-		add	r0, r0, #127 + 128	@ alignment + stack
-		bic	r0, r0, #127		@ align the kernel length
-/*
- * r0     = decompressed kernel length
- * r1-r3  = unused
- * r4     = kernel execution address
- * r5     = decompressed kernel start
- * r7     = architecture ID
- * r8     = atags pointer
- * r9-r12,r14 = corrupted
- */
-		add	r1, r5, r0		@ end of decompressed kernel
-		adr	r2, reloc_start
-		ldr	r3, LC1
-		add	r3, r2, r3
-1:		ldmia	r2!, {r9 - r12, r14}	@ copy relocation code
-		stmia	r1!, {r9 - r12, r14}
-		ldmia	r2!, {r9 - r12, r14}
-		stmia	r1!, {r9 - r12, r14}
-		cmp	r2, r3
-		blo	1b
-		mov	sp, r1
-		add	sp, sp, #128		@ relocate the stack
-
 		bl	cache_clean_flush
- ARM(		add	pc, r5, r0		) @ call relocation code
- THUMB(		add	r12, r5, r0		)
- THUMB(		mov	pc, r12			) @ call relocation code
-
-/*
- * We're not in danger of overwriting ourselves.  Do this the simple way.
- *
- * r4     = kernel execution address
- * r7     = architecture ID
- */
-wont_overwrite:	mov	r0, r4
-		mov	r3, r7
-		bl	decompress_kernel
-		b	call_kernel
+		bl	cache_off
+		mov	r0, #0			@ must be zero
+		mov	r1, r7			@ restore architecture number
+		mov	r2, r8			@ restore atags pointer
+		mov	pc, r4			@ call kernel
 
 		.align	2
 		.type	LC0, #object
 LC0:		.word	LC0			@ r1
 		.word	__bss_start		@ r2
 		.word	_end			@ r3
-		.word	_start			@ r5
-		.word	_image_size		@ r6
+		.word	_edata			@ r6
+		.word	_image_size		@ r9
 		.word	_got_start		@ r11
 		.word	_got_end		@ ip
 		.word	user_stack_end		@ sp
-LC1:		.word	reloc_end - reloc_start
 		.size	LC0, . - LC0
 
 #ifdef CONFIG_ARCH_RPC
@@ -353,7 +376,7 @@
  * On exit,
  *  r0, r1, r2, r3, r9, r10, r12 corrupted
  * This routine must preserve:
- *  r4, r5, r6, r7, r8
+ *  r4, r7, r8
  */
 		.align	5
 cache_on:	mov	r3, #8			@ cache_on function
@@ -551,43 +574,6 @@
 #endif
 
 /*
- * All code following this line is relocatable.  It is relocated by
- * the above code to the end of the decompressed kernel image and
- * executed there.  During this time, we have no stacks.
- *
- * r0     = decompressed kernel length
- * r1-r3  = unused
- * r4     = kernel execution address
- * r5     = decompressed kernel start
- * r7     = architecture ID
- * r8     = atags pointer
- * r9-r12,r14 = corrupted
- */
-		.align	5
-reloc_start:	add	r9, r5, r0
-		sub	r9, r9, #128		@ do not copy the stack
-		debug_reloc_start
-		mov	r1, r4
-1:
-		.rept	4
-		ldmia	r5!, {r0, r2, r3, r10 - r12, r14}	@ relocate kernel
-		stmia	r1!, {r0, r2, r3, r10 - r12, r14}
-		.endr
-
-		cmp	r5, r9
-		blo	1b
-		mov	sp, r1
-		add	sp, sp, #128		@ relocate the stack
-		debug_reloc_end
-
-call_kernel:	bl	cache_clean_flush
-		bl	cache_off
-		mov	r0, #0			@ must be zero
-		mov	r1, r7			@ restore architecture number
-		mov	r2, r8			@ restore atags pointer
-		mov	pc, r4			@ call kernel
-
-/*
  * Here follow the relocatable cache support functions for the
  * various processors.  This is a generic hook for locating an
  * entry and jumping to an instruction at the specified offset
@@ -791,7 +777,7 @@
  * On exit,
  *  r0, r1, r2, r3, r9, r12 corrupted
  * This routine must preserve:
- *  r4, r6, r7
+ *  r4, r7, r8
  */
 		.align	5
 cache_off:	mov	r3, #12			@ cache_off function
@@ -866,7 +852,7 @@
  * On exit,
  *  r1, r2, r3, r9, r10, r11, r12 corrupted
  * This routine must preserve:
- *  r0, r4, r5, r6, r7
+ *  r4, r6, r7, r8
  */
 		.align	5
 cache_clean_flush:
@@ -1088,7 +1074,7 @@
 #endif
 
 		.ltorg
-reloc_end:
+reloc_code_end:
 
 		.align
 		.section ".stack", "aw", %nobits
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/head-shmobile.S linux-libre-2.6.39-gnu/arch/arm/boot/compressed/head-shmobile.S
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/head-shmobile.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/head-shmobile.S	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,36 @@
 	/* load board-specific initialization code */
 #include <mach/zboot.h>
 
+#ifdef CONFIG_ZBOOT_ROM_MMCIF
+	/* Load image from MMC */
+	adr	sp, __tmp_stack + 128
+	ldr	r0, __image_start
+	ldr	r1, __image_end
+	subs	r1, r1, r0
+	ldr	r0, __load_base
+	bl	mmcif_loader
+
+	/* Jump to loaded code */
+	ldr	r0, __loaded
+	ldr	r1, __image_start
+	sub	r0, r0, r1
+	ldr	r1, __load_base
+	add	pc, r0, r1
+
+__image_start:
+	.long	_start
+__image_end:
+	.long	_got_end
+__load_base:
+	.long	CONFIG_MEMORY_START + 0x02000000 @ Load at 32Mb into SDRAM
+__loaded:
+	.long	__continue
+	.align
+__tmp_stack:
+	.space	128
+__continue:
+#endif /* CONFIG_ZBOOT_ROM_MMCIF */
+
 	b	1f
 __atags:@ tag #1
 	.long	12			@ tag->hdr.size = tag_size(tag_core);
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/head-vt8500.S linux-libre-2.6.39-gnu/arch/arm/boot/compressed/head-vt8500.S
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/head-vt8500.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/head-vt8500.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/arm/boot/compressed/head-vt8500.S
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * VIA VT8500 specific tweaks. This is merged into head.S by the linker.
+ *
+ */
+
+#include <linux/linkage.h>
+#include <asm/mach-types.h>
+
+		.section        ".start", "ax"
+
+__VT8500_start:
+	@ Compare the SCC ID register against a list of known values
+	ldr	r1, .SCCID
+	ldr	r3, [r1]
+
+	@ VT8500 override
+	ldr	r4, .VT8500SCC
+	cmp	r3, r4
+	ldreq	r7, .ID_BV07
+	beq	.Lendvt8500
+
+	@ WM8505 override
+	ldr	r4, .WM8505SCC
+	cmp	r3, r4
+	ldreq	r7, .ID_8505
+	beq	.Lendvt8500
+
+	@ Otherwise, leave the bootloader's machine id untouched
+
+.SCCID:
+	.word	0xd8120000
+.VT8500SCC:
+	.word	0x34000102
+.WM8505SCC:
+	.word	0x34260103
+
+.ID_BV07:
+	.word	MACH_TYPE_BV07
+.ID_8505:
+	.word	MACH_TYPE_WM8505_7IN_NETBOOK
+
+.Lendvt8500:
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/Makefile linux-libre-2.6.39-gnu/arch/arm/boot/compressed/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,9 +4,20 @@
 # create a compressed vmlinuz image from the original vmlinux
 #
 
+OBJS		=
+
+# Ensure that mmcif loader code appears early in the image
+# to minimise that number of bocks that have to be read in
+# order to load it.
+ifeq ($(CONFIG_ZBOOT_ROM_MMCIF),y)
+ifeq ($(CONFIG_ARCH_SH7372),y)
+OBJS		+= mmcif-sh7372.o
+endif
+endif
+
 AFLAGS_head.o += -DTEXT_OFFSET=$(TEXT_OFFSET)
 HEAD	= head.o
-OBJS	= misc.o decompress.o
+OBJS	+= misc.o decompress.o
 FONTC	= $(srctree)/drivers/video/console/font_acorn_8x8.c
 
 #
@@ -29,6 +40,10 @@
 OBJS		+= head-sa1100.o
 endif
 
+ifeq ($(CONFIG_ARCH_VT8500),y)
+OBJS		+= head-vt8500.o
+endif
+
 ifeq ($(CONFIG_CPU_XSCALE),y)
 OBJS		+= head-xscale.o
 endif
@@ -59,7 +74,7 @@
 ZBSSADDR	:= $(CONFIG_ZBOOT_ROM_BSS)
 else
 ZTEXTADDR	:= 0
-ZBSSADDR	:= ALIGN(4)
+ZBSSADDR	:= ALIGN(8)
 endif
 
 SEDFLAGS	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
@@ -80,12 +95,14 @@
 KBUILD_CFLAGS = $(subst -pg, , $(ORIG_CFLAGS))
 endif
 
-EXTRA_CFLAGS  := -fpic -fno-builtin
-EXTRA_AFLAGS  := -Wa,-march=all
+ccflags-y := -fpic -fno-builtin
+asflags-y := -Wa,-march=all
 
+# Provide size of uncompressed kernel to the decompressor via a linker symbol.
+LDFLAGS_vmlinux = --defsym _image_size=$(shell stat -c "%s" $(obj)/../Image)
 # Supply ZRELADDR to the decompressor via a linker symbol.
 ifneq ($(CONFIG_AUTO_ZRELADDR),y)
-LDFLAGS_vmlinux := --defsym zreladdr=$(ZRELADDR)
+LDFLAGS_vmlinux += --defsym zreladdr=$(ZRELADDR)
 endif
 ifeq ($(CONFIG_CPU_ENDIAN_BE8),y)
 LDFLAGS_vmlinux += --be8
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/misc.c linux-libre-2.6.39-gnu/arch/arm/boot/compressed/misc.c
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/misc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/misc.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 
 #ifdef CONFIG_DEBUG_ICEDCC
 
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
 
 static void icedcc_putc(int ch)
 {
@@ -52,16 +52,6 @@
 	asm("mcr p14, 0, %0, c0, c5, 0" : : "r" (ch));
 }
 
-#elif defined(CONFIG_CPU_V7)
-
-static void icedcc_putc(int ch)
-{
-	asm(
-	"wait:	mrc	p14, 0, pc, c0, c1, 0			\n\
-		bcs	wait					\n\
-		mcr     p14, 0, %0, c0, c5, 0			"
-	: : "r" (ch));
-}
 
 #elif defined(CONFIG_CPU_XSCALE)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/mmcif-sh7372.c linux-libre-2.6.39-gnu/arch/arm/boot/compressed/mmcif-sh7372.c
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/mmcif-sh7372.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/mmcif-sh7372.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ * sh7372 MMCIF loader
+ *
+ * Copyright (C) 2010 Magnus Damm
+ * Copyright (C) 2010 Simon Horman
+ *
+ * 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/mmc/sh_mmcif.h>
+#include <linux/mmc/boot.h>
+#include <mach/mmc.h>
+
+#define MMCIF_BASE      (void __iomem *)0xe6bd0000
+
+#define PORT84CR	(void __iomem *)0xe6050054
+#define PORT85CR	(void __iomem *)0xe6050055
+#define PORT86CR	(void __iomem *)0xe6050056
+#define PORT87CR	(void __iomem *)0xe6050057
+#define PORT88CR	(void __iomem *)0xe6050058
+#define PORT89CR	(void __iomem *)0xe6050059
+#define PORT90CR	(void __iomem *)0xe605005a
+#define PORT91CR	(void __iomem *)0xe605005b
+#define PORT92CR	(void __iomem *)0xe605005c
+#define PORT99CR	(void __iomem *)0xe6050063
+
+#define SMSTPCR3	(void __iomem *)0xe615013c
+
+/* SH7372 specific MMCIF loader
+ *
+ * loads the zImage from an MMC card starting from block 1.
+ *
+ * The image must be start with a vrl4 header and
+ * the zImage must start at offset 512 of the image. That is,
+ * at block 2 (=byte 1024) on the media
+ *
+ * Use the following line to write the vrl4 formated zImage
+ * to an MMC card
+ * # dd if=vrl4.out of=/dev/sdx bs=512 seek=1
+ */
+asmlinkage void mmcif_loader(unsigned char *buf, unsigned long len)
+{
+	mmc_init_progress();
+	mmc_update_progress(MMC_PROGRESS_ENTER);
+
+	/* Initialise MMC
+	 * registers: PORT84CR-PORT92CR
+	 *            (MMCD0_0-MMCD0_7,MMCCMD0 Control)
+	 * value: 0x04 - select function 4
+	 */
+	 __raw_writeb(0x04, PORT84CR);
+	 __raw_writeb(0x04, PORT85CR);
+	 __raw_writeb(0x04, PORT86CR);
+	 __raw_writeb(0x04, PORT87CR);
+	 __raw_writeb(0x04, PORT88CR);
+	 __raw_writeb(0x04, PORT89CR);
+	 __raw_writeb(0x04, PORT90CR);
+	 __raw_writeb(0x04, PORT91CR);
+	 __raw_writeb(0x04, PORT92CR);
+
+	/* Initialise MMC
+	 * registers: PORT99CR (MMCCLK0 Control)
+	 * value: 0x10 | 0x04 - enable output | select function 4
+	 */
+	__raw_writeb(0x14, PORT99CR);
+
+	/* Enable clock to MMC hardware block */
+	__raw_writel(__raw_readl(SMSTPCR3) & ~(1 << 12), SMSTPCR3);
+
+	mmc_update_progress(MMC_PROGRESS_INIT);
+
+	/* setup MMCIF hardware */
+	sh_mmcif_boot_init(MMCIF_BASE);
+
+	mmc_update_progress(MMC_PROGRESS_LOAD);
+
+	/* load kernel via MMCIF interface */
+	sh_mmcif_boot_do_read(MMCIF_BASE, 2, /* Kernel is at block 2 */
+			      (len + SH_MMCIF_BBS - 1) / SH_MMCIF_BBS, buf);
+
+
+	/* Disable clock to MMC hardware block */
+	__raw_writel(__raw_readl(SMSTPCR3) & (1 << 12), SMSTPCR3);
+
+	mmc_update_progress(MMC_PROGRESS_DONE);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/compressed/vmlinux.lds.in linux-libre-2.6.39-gnu/arch/arm/boot/compressed/vmlinux.lds.in
--- linux-libre-2.6.38-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/boot/compressed/vmlinux.lds.in	2011-05-19 00:06:34.000000000 -0400
@@ -43,9 +43,6 @@
 
   _etext = .;
 
-  /* Assume size of decompressed image is 4x the compressed image */
-  _image_size = (_etext - _text) * 4;
-
   _got_start = .;
   .got			: { *(.got) }
   _got_end = .;
@@ -57,6 +54,7 @@
   .bss			: { *(.bss) }
   _end = .;
 
+  . = ALIGN(8);		/* the stack must be 64-bit aligned */
   .stack		: { *(.stack) }
 
   .stab 0		: { *(.stab) }
diff -druN linux-libre-2.6.38-gnu/arch/arm/boot/Makefile linux-libre-2.6.39-gnu/arch/arm/boot/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/boot/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -99,6 +99,10 @@
 	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
 
+uinstall: $(obj)/uImage
+	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
+	$(obj)/uImage System.map "$(INSTALL_PATH)"
+
 zi:
 	$(CONFIG_SHELL) $(srctree)/$(src)/install.sh $(KERNELRELEASE) \
 	$(obj)/zImage System.map "$(INSTALL_PATH)"
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/gic.c linux-libre-2.6.39-gnu/arch/arm/common/gic.c
--- linux-libre-2.6.38-gnu/arch/arm/common/gic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/gic.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,6 +44,19 @@
 	void __iomem *cpu_base;
 };
 
+/*
+ * Supported arch specific GIC irq extension.
+ * Default make them NULL.
+ */
+struct irq_chip gic_arch_extn = {
+	.irq_ack	= NULL,
+	.irq_mask	= NULL,
+	.irq_unmask	= NULL,
+	.irq_retrigger	= NULL,
+	.irq_set_type	= NULL,
+	.irq_set_wake	= NULL,
+};
+
 #ifndef MAX_GIC_NR
 #define MAX_GIC_NR	1
 #endif
@@ -74,6 +87,8 @@
 static void gic_ack_irq(struct irq_data *d)
 {
 	spin_lock(&irq_controller_lock);
+	if (gic_arch_extn.irq_ack)
+		gic_arch_extn.irq_ack(d);
 	writel(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
 	spin_unlock(&irq_controller_lock);
 }
@@ -84,6 +99,8 @@
 
 	spin_lock(&irq_controller_lock);
 	writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
+	if (gic_arch_extn.irq_mask)
+		gic_arch_extn.irq_mask(d);
 	spin_unlock(&irq_controller_lock);
 }
 
@@ -92,6 +109,8 @@
 	u32 mask = 1 << (d->irq % 32);
 
 	spin_lock(&irq_controller_lock);
+	if (gic_arch_extn.irq_unmask)
+		gic_arch_extn.irq_unmask(d);
 	writel(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
 	spin_unlock(&irq_controller_lock);
 }
@@ -116,6 +135,9 @@
 
 	spin_lock(&irq_controller_lock);
 
+	if (gic_arch_extn.irq_set_type)
+		gic_arch_extn.irq_set_type(d, type);
+
 	val = readl(base + GIC_DIST_CONFIG + confoff);
 	if (type == IRQ_TYPE_LEVEL_HIGH)
 		val &= ~confmask;
@@ -141,36 +163,58 @@
 	return 0;
 }
 
+static int gic_retrigger(struct irq_data *d)
+{
+	if (gic_arch_extn.irq_retrigger)
+		return gic_arch_extn.irq_retrigger(d);
+
+	return -ENXIO;
+}
+
 #ifdef CONFIG_SMP
-static int
-gic_set_cpu(struct irq_data *d, const struct cpumask *mask_val, bool force)
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
+			    bool force)
 {
 	void __iomem *reg = gic_dist_base(d) + GIC_DIST_TARGET + (gic_irq(d) & ~3);
 	unsigned int shift = (d->irq % 4) * 8;
 	unsigned int cpu = cpumask_first(mask_val);
-	u32 val;
-	struct irq_desc *desc;
+	u32 val, mask, bit;
 
-	spin_lock(&irq_controller_lock);
-	desc = irq_to_desc(d->irq);
-	if (desc == NULL) {
-		spin_unlock(&irq_controller_lock);
+	if (cpu >= 8)
 		return -EINVAL;
-	}
+
+	mask = 0xff << shift;
+	bit = 1 << (cpu + shift);
+
+	spin_lock(&irq_controller_lock);
 	d->node = cpu;
-	val = readl(reg) & ~(0xff << shift);
-	val |= 1 << (cpu + shift);
-	writel(val, reg);
+	val = readl(reg) & ~mask;
+	writel(val | bit, reg);
 	spin_unlock(&irq_controller_lock);
 
 	return 0;
 }
 #endif
 
+#ifdef CONFIG_PM
+static int gic_set_wake(struct irq_data *d, unsigned int on)
+{
+	int ret = -ENXIO;
+
+	if (gic_arch_extn.irq_set_wake)
+		ret = gic_arch_extn.irq_set_wake(d, on);
+
+	return ret;
+}
+
+#else
+#define gic_set_wake	NULL
+#endif
+
 static void gic_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct gic_chip_data *chip_data = get_irq_data(irq);
-	struct irq_chip *chip = get_irq_chip(irq);
+	struct gic_chip_data *chip_data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
 	unsigned int cascade_irq, gic_irq;
 	unsigned long status;
 
@@ -202,18 +246,20 @@
 	.irq_mask		= gic_mask_irq,
 	.irq_unmask		= gic_unmask_irq,
 	.irq_set_type		= gic_set_type,
+	.irq_retrigger		= gic_retrigger,
 #ifdef CONFIG_SMP
-	.irq_set_affinity	= gic_set_cpu,
+	.irq_set_affinity	= gic_set_affinity,
 #endif
+	.irq_set_wake		= gic_set_wake,
 };
 
 void __init gic_cascade_irq(unsigned int gic_nr, unsigned int irq)
 {
 	if (gic_nr >= MAX_GIC_NR)
 		BUG();
-	if (set_irq_data(irq, &gic_data[gic_nr]) != 0)
+	if (irq_set_handler_data(irq, &gic_data[gic_nr]) != 0)
 		BUG();
-	set_irq_chained_handler(irq, gic_handle_cascade_irq);
+	irq_set_chained_handler(irq, gic_handle_cascade_irq);
 }
 
 static void __init gic_dist_init(struct gic_chip_data *gic,
@@ -273,9 +319,8 @@
 	 * Setup the Linux IRQ subsystem.
 	 */
 	for (i = irq_start; i < irq_limit; i++) {
-		set_irq_chip(i, &gic_chip);
-		set_irq_chip_data(i, gic);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &gic_chip, handle_level_irq);
+		irq_set_chip_data(i, gic);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
 
@@ -336,7 +381,7 @@
 	unsigned long flags;
 
 	local_irq_save(flags);
-	irq_to_desc(irq)->status |= IRQ_NOPROBE;
+	irq_set_status_flags(irq, IRQ_NOPROBE);
 	gic_unmask_irq(irq_get_irq_data(irq));
 	local_irq_restore(flags);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/it8152.c linux-libre-2.6.39-gnu/arch/arm/common/it8152.c
--- linux-libre-2.6.38-gnu/arch/arm/common/it8152.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/it8152.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,8 +88,8 @@
 	__raw_writel((0), IT8152_INTC_LDCNIRR);
 
 	for (irq = IT8152_IRQ(0); irq <= IT8152_LAST_IRQ; irq++) {
-		set_irq_chip(irq, &it8152_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &it8152_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/locomo.c linux-libre-2.6.39-gnu/arch/arm/common/locomo.c
--- linux-libre-2.6.38-gnu/arch/arm/common/locomo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/locomo.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,7 +140,7 @@
 
 static void locomo_handler(unsigned int irq, struct irq_desc *desc)
 {
-	struct locomo *lchip = get_irq_chip_data(irq);
+	struct locomo *lchip = irq_get_chip_data(irq);
 	int req, i;
 
 	/* Acknowledge the parent IRQ */
@@ -197,15 +197,14 @@
 	/*
 	 * Install handler for IRQ_LOCOMO_HW.
 	 */
-	set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
-	set_irq_chip_data(lchip->irq, lchip);
-	set_irq_chained_handler(lchip->irq, locomo_handler);
+	irq_set_irq_type(lchip->irq, IRQ_TYPE_EDGE_FALLING);
+	irq_set_chip_data(lchip->irq, lchip);
+	irq_set_chained_handler(lchip->irq, locomo_handler);
 
 	/* Install handlers for IRQ_LOCOMO_* */
 	for ( ; irq <= lchip->irq_base + 3; irq++) {
-		set_irq_chip(irq, &locomo_chip);
-		set_irq_chip_data(irq, lchip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &locomo_chip, handle_level_irq);
+		irq_set_chip_data(irq, lchip);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 }
@@ -476,8 +475,8 @@
 	device_for_each_child(lchip->dev, NULL, locomo_remove_child);
 
 	if (lchip->irq != NO_IRQ) {
-		set_irq_chained_handler(lchip->irq, NULL);
-		set_irq_data(lchip->irq, NULL);
+		irq_set_chained_handler(lchip->irq, NULL);
+		irq_set_handler_data(lchip->irq, NULL);
 	}
 
 	iounmap(lchip->base);
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/Makefile linux-libre-2.6.39-gnu/arch/arm/common/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/common/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -16,5 +16,4 @@
 obj-$(CONFIG_ARCH_IXP2000)	+= uengine.o
 obj-$(CONFIG_ARCH_IXP23XX)	+= uengine.o
 obj-$(CONFIG_PCI_HOST_ITE8152)  += it8152.o
-obj-$(CONFIG_COMMON_CLKDEV)	+= clkdev.o
 obj-$(CONFIG_ARM_TIMER_SP804)	+= timer-sp.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/pl330.c linux-libre-2.6.39-gnu/arch/arm/common/pl330.c
--- linux-libre-2.6.38-gnu/arch/arm/common/pl330.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/pl330.c	2011-05-19 00:06:34.000000000 -0400
@@ -1045,7 +1045,7 @@
 	unsigned lcnt0, lcnt1, ljmp0, ljmp1;
 	struct _arg_LPEND lpend;
 
-	/* Max iterations possibile in DMALP is 256 */
+	/* Max iterations possible in DMALP is 256 */
 	if (*bursts >= 256*256) {
 		lcnt1 = 256;
 		lcnt0 = 256;
@@ -1446,7 +1446,7 @@
 	}
 
 	for (ev = 0; ev < pi->pcfg.num_events; ev++) {
-		if (val & (1 << ev)) { /* Event occured */
+		if (val & (1 << ev)) { /* Event occurred */
 			struct pl330_thread *thrd;
 			u32 inten = readl(regs + INTEN);
 			int active;
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/sa1111.c linux-libre-2.6.39-gnu/arch/arm/common/sa1111.c
--- linux-libre-2.6.38-gnu/arch/arm/common/sa1111.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/sa1111.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,7 +202,7 @@
 sa1111_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	unsigned int stat0, stat1, i;
-	struct sa1111 *sachip = get_irq_data(irq);
+	struct sa1111 *sachip = irq_get_handler_data(irq);
 	void __iomem *mapbase = sachip->base + SA1111_INTC;
 
 	stat0 = sa1111_readl(mapbase + SA1111_INTSTATCLR0);
@@ -472,25 +472,25 @@
 	sa1111_writel(~0, irqbase + SA1111_INTSTATCLR1);
 
 	for (irq = IRQ_GPAIN0; irq <= SSPROR; irq++) {
-		set_irq_chip(irq, &sa1111_low_chip);
-		set_irq_chip_data(irq, sachip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &sa1111_low_chip,
+					 handle_edge_irq);
+		irq_set_chip_data(irq, sachip);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	for (irq = AUDXMTDMADONEA; irq <= IRQ_S1_BVD1_STSCHG; irq++) {
-		set_irq_chip(irq, &sa1111_high_chip);
-		set_irq_chip_data(irq, sachip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &sa1111_high_chip,
+					 handle_edge_irq);
+		irq_set_chip_data(irq, sachip);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	/*
 	 * Register SA1111 interrupt
 	 */
-	set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
-	set_irq_data(sachip->irq, sachip);
-	set_irq_chained_handler(sachip->irq, sa1111_irq_handler);
+	irq_set_irq_type(sachip->irq, IRQ_TYPE_EDGE_RISING);
+	irq_set_handler_data(sachip->irq, sachip);
+	irq_set_chained_handler(sachip->irq, sa1111_irq_handler);
 }
 
 /*
@@ -815,8 +815,8 @@
 	clk_disable(sachip->clk);
 
 	if (sachip->irq != NO_IRQ) {
-		set_irq_chained_handler(sachip->irq, NULL);
-		set_irq_data(sachip->irq, NULL);
+		irq_set_chained_handler(sachip->irq, NULL);
+		irq_set_handler_data(sachip->irq, NULL);
 
 		release_mem_region(sachip->phys + SA1111_INTC, 512);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/common/vic.c linux-libre-2.6.39-gnu/arch/arm/common/vic.c
--- linux-libre-2.6.38-gnu/arch/arm/common/vic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/common/vic.c	2011-05-19 00:06:34.000000000 -0400
@@ -305,9 +305,9 @@
 		if (vic_sources & (1 << i)) {
 			unsigned int irq = irq_start + i;
 
-			set_irq_chip(irq, &vic_chip);
-			set_irq_chip_data(irq, base);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &vic_chip,
+						 handle_level_irq);
+			irq_set_chip_data(irq, base);
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/at91x40_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/at91x40_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/at91x40_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/configs/at91x40_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,48 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_EMBEDDED=y
+# CONFIG_HOTPLUG is not set
+# CONFIG_ELF_CORE is not set
+# CONFIG_FUTEX is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+CONFIG_SLAB=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+# CONFIG_MMU is not set
+CONFIG_ARCH_AT91=y
+CONFIG_ARCH_AT91X40=y
+CONFIG_MACH_AT91EB01=y
+CONFIG_AT91_EARLY_USART0=y
+CONFIG_CPU_ARM7TDMI=y
+CONFIG_SET_MEM_PARAM=y
+CONFIG_DRAM_BASE=0x01000000
+CONFIG_DRAM_SIZE=0x00400000
+CONFIG_FLASH_MEM_BASE=0x01400000
+CONFIG_PROCESSOR_ID=0x14000040
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_BINFMT_FLAT=y
+# CONFIG_SUSPEND is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_ROM=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_ROMFS_FS=y
+# CONFIG_ENABLE_MUST_CHECK is not set
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/exynos4_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/exynos4_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/exynos4_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/configs/exynos4_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,70 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_KALLSYMS_ALL=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+CONFIG_ARCH_EXYNOS4=y
+CONFIG_S3C_LOWLEVEL_UART_PORT=1
+CONFIG_MACH_SMDKC210=y
+CONFIG_MACH_SMDKV310=y
+CONFIG_MACH_UNIVERSAL_C210=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x41000000,8M console=ttySAC1,115200 init=/linuxrc mem=256M"
+CONFIG_VFP=y
+CONFIG_NEON=y
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_BLK_DEV_RAM=y
+CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_CHR_DEV_SG=y
+CONFIG_INPUT_EVDEV=y
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_SAMSUNG=y
+CONFIG_SERIAL_SAMSUNG_CONSOLE=y
+CONFIG_HW_RANDOM=y
+CONFIG_I2C=y
+# CONFIG_HWMON is not set
+# CONFIG_MFD_SUPPORT is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+CONFIG_MSDOS_FS=y
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_TMPFS_POSIX_ACL=y
+CONFIG_CRAMFS=y
+CONFIG_ROMFS_FS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_BSD_DISKLABEL=y
+CONFIG_SOLARIS_X86_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ASCII=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_DEBUG_RT_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK=y
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_DEBUG_S3C_UART=1
+CONFIG_CRC_CCITT=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/kirkwood_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/kirkwood_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/kirkwood_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/kirkwood_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 CONFIG_MACH_NETSPACE_V2=y
 CONFIG_MACH_INETSPACE_V2=y
 CONFIG_MACH_NETSPACE_MAX_V2=y
+CONFIG_MACH_D2NET_V2=y
 CONFIG_MACH_NET2BIG_V2=y
 CONFIG_MACH_NET5BIG_V2=y
 CONFIG_MACH_T5325=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/lpd7a400_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/lpd7a400_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/lpd7a400_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/lpd7a400_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_LOG_BUF_SHIFT=14
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_EPOLL is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_LH7A40X=y
-CONFIG_MACH_LPD7A400=y
-CONFIG_PREEMPT=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_INPUT_MOUSEDEV is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_LH7A40X=y
-CONFIG_SERIAL_LH7A40X_CONSOLE=y
-CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/lpd7a404_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/lpd7a404_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/lpd7a404_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/lpd7a404_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_IKCONFIG=y
-CONFIG_LOG_BUF_SHIFT=16
-CONFIG_EXPERT=y
-# CONFIG_HOTPLUG is not set
-# CONFIG_EPOLL is not set
-CONFIG_SLAB=y
-# CONFIG_IOSCHED_DEADLINE is not set
-CONFIG_ARCH_LH7A40X=y
-CONFIG_MACH_LPD7A404=y
-CONFIG_PREEMPT=y
-CONFIG_DISCONTIGMEM_MANUAL=y
-CONFIG_ZBOOT_ROM_TEXT=0x0
-CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_FPE_NWFPE=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_PNP=y
-CONFIG_IP_PNP_DHCP=y
-CONFIG_IP_PNP_BOOTP=y
-CONFIG_IP_PNP_RARP=y
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_PHYSMAP=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_IDE=y
-CONFIG_SCSI=y
-# CONFIG_SCSI_PROC_FS is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_SMC91X=y
-# CONFIG_INPUT_MOUSEDEV_PSAUX is not set
-CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-CONFIG_INPUT_TOUCHSCREEN=y
-# CONFIG_SERIO is not set
-CONFIG_SERIAL_LH7A40X=y
-CONFIG_SERIAL_LH7A40X_CONSOLE=y
-CONFIG_FB=y
-# CONFIG_VGA_CONSOLE is not set
-CONFIG_SOUND=y
-CONFIG_SND=y
-CONFIG_SND_MIXER_OSS=y
-CONFIG_SND_PCM_OSS=y
-CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
-CONFIG_USB_MON=y
-CONFIG_USB_OHCI_HCD=y
-CONFIG_USB_STORAGE=y
-CONFIG_USB_STORAGE_DEBUG=y
-CONFIG_USB_STORAGE_DATAFAB=y
-CONFIG_USB_GADGET=y
-CONFIG_USB_ZERO=y
-CONFIG_EXT2_FS=y
-CONFIG_EXT3_FS=y
-CONFIG_INOTIFY=y
-CONFIG_VFAT_FS=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAGIC_SYSRQ=y
-CONFIG_DEBUG_KERNEL=y
-CONFIG_DEBUG_MUTEXES=y
-CONFIG_DEBUG_INFO=y
-CONFIG_DEBUG_USER=y
-CONFIG_DEBUG_ERRORS=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/mx51_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/mx51_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/mx51_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/mx51_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -110,7 +110,7 @@
 CONFIG_MMC_BLOCK=m
 CONFIG_MMC_SDHCI=m
 CONFIG_NEW_LEDS=y
-CONFIG_LEDS_CLASS=m
+CONFIG_LEDS_CLASS=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_EXT2_FS=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/omap2plus_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/omap2plus_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/omap2plus_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/omap2plus_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,7 @@
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
+CONFIG_NR_CPUS=2
 # CONFIG_LOCAL_TIMERS is not set
 CONFIG_AEABI=y
 CONFIG_LEDS=y
@@ -192,6 +193,17 @@
 CONFIG_FB_MODE_HELPERS=y
 CONFIG_FB_TILEBLITTING=y
 CONFIG_FB_OMAP_LCD_VGA=y
+CONFIG_OMAP2_DSS=m
+CONFIG_OMAP2_DSS_RFBI=y
+CONFIG_OMAP2_DSS_SDI=y
+CONFIG_OMAP2_DSS_DSI=y
+CONFIG_FB_OMAP2=m
+CONFIG_PANEL_GENERIC_DPI=m
+CONFIG_PANEL_SHARP_LS037V7DW01=m
+CONFIG_PANEL_NEC_NL8048HL11_01B=m
+CONFIG_PANEL_TAAL=m
+CONFIG_PANEL_TPO_TD043MTEA1=m
+CONFIG_PANEL_ACX565AKM=m
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_LCD_CLASS_DEVICE=y
 CONFIG_LCD_PLATFORM=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/s5p64x0_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/s5p64x0_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/s5p64x0_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/s5p64x0_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -10,6 +10,8 @@
 CONFIG_S3C_LOWLEVEL_UART_PORT=1
 CONFIG_MACH_SMDK6440=y
 CONFIG_MACH_SMDK6450=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_CPU_32v6K=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 rw ramdisk=8192 initrd=0x20800000,8M console=ttySAC1,115200 init=/linuxrc"
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/s5pv210_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/s5pv210_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/s5pv210_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/s5pv210_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,8 @@
 CONFIG_MACH_GONI=y
 CONFIG_MACH_SMDKC110=y
 CONFIG_MACH_SMDKV210=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_VMSPLIT_2G=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/tegra_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/tegra_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/tegra_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/configs/tegra_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,146 @@
+CONFIG_EXPERIMENTAL=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_CGROUPS=y
+CONFIG_CGROUP_DEBUG=y
+CONFIG_CGROUP_FREEZER=y
+CONFIG_CGROUP_CPUACCT=y
+CONFIG_RESOURCE_COUNTERS=y
+CONFIG_CGROUP_SCHED=y
+CONFIG_RT_GROUP_SCHED=y
+CONFIG_BLK_DEV_INITRD=y
+CONFIG_EMBEDDED=y
+# CONFIG_SYSCTL_SYSCALL is not set
+# CONFIG_ELF_CORE is not set
+CONFIG_SLAB=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+CONFIG_MODULE_FORCE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_TEGRA=y
+CONFIG_MACH_HARMONY=y
+CONFIG_MACH_KAEN=y
+CONFIG_MACH_PAZ00=y
+CONFIG_MACH_TRIMSLICE=y
+CONFIG_MACH_WARIO=y
+CONFIG_TEGRA_DEBUG_UARTD=y
+CONFIG_ARM_ERRATA_742230=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=2
+CONFIG_PREEMPT=y
+CONFIG_AEABI=y
+# CONFIG_OABI_COMPAT is not set
+CONFIG_HIGHMEM=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_VFP=y
+CONFIG_PM=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_NET_KEY=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+CONFIG_IP_PNP_RARP=y
+CONFIG_INET_ESP=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_IPV6=y
+CONFIG_IPV6_PRIVACY=y
+CONFIG_IPV6_ROUTER_PREF=y
+CONFIG_IPV6_OPTIMISTIC_DAD=y
+CONFIG_INET6_AH=y
+CONFIG_INET6_ESP=y
+CONFIG_INET6_IPCOMP=y
+CONFIG_IPV6_MIP6=y
+CONFIG_IPV6_TUNNEL=y
+CONFIG_IPV6_MULTIPLE_TABLES=y
+# CONFIG_WIRELESS is not set
+# CONFIG_FIRMWARE_IN_KERNEL is not set
+CONFIG_BLK_DEV_LOOP=y
+CONFIG_MISC_DEVICES=y
+CONFIG_AD525X_DPOT=y
+CONFIG_AD525X_DPOT_I2C=y
+CONFIG_ICS932S401=y
+CONFIG_APDS9802ALS=y
+CONFIG_ISL29003=y
+CONFIG_NETDEVICES=y
+CONFIG_DUMMY=y
+CONFIG_R8169=y
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+# CONFIG_DEVKMEM is not set
+CONFIG_SERIAL_8250=y
+CONFIG_SERIAL_8250_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+CONFIG_I2C=y
+# CONFIG_I2C_COMPAT is not set
+# CONFIG_I2C_HELPER_AUTO is not set
+CONFIG_I2C_TEGRA=y
+CONFIG_SENSORS_LM90=y
+CONFIG_MFD_TPS6586X=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_TPS6586X=y
+# CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_SDHCI=y
+CONFIG_MMC_SDHCI_PLTFM=y
+CONFIG_MMC_SDHCI_TEGRA=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_IIO=y
+CONFIG_SENSORS_ISL29018=y
+CONFIG_SENSORS_AK8975=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT2_FS_XATTR=y
+CONFIG_EXT2_FS_POSIX_ACL=y
+CONFIG_EXT2_FS_SECURITY=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+CONFIG_EXT3_FS_POSIX_ACL=y
+CONFIG_EXT3_FS_SECURITY=y
+# CONFIG_DNOTIFY is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_NFS_FS=y
+CONFIG_ROOT_NFS=y
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_EFI_PARTITION=y
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_PRINTK_TIME=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+CONFIG_SCHEDSTATS=y
+CONFIG_TIMER_STATS=y
+CONFIG_DEBUG_SLAB=y
+# CONFIG_DEBUG_PREEMPT is not set
+CONFIG_DEBUG_MUTEXES=y
+CONFIG_DEBUG_SPINLOCK_SLEEP=y
+CONFIG_DEBUG_INFO=y
+CONFIG_DEBUG_VM=y
+CONFIG_DEBUG_SG=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+CONFIG_CRYPTO_ECB=y
+CONFIG_CRYPTO_AES=y
+CONFIG_CRYPTO_ARC4=y
+CONFIG_CRYPTO_TWOFISH=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+CONFIG_CRC_CCITT=y
+CONFIG_CRC16=y
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/u8500_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/u8500_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/u8500_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/configs/u8500_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,6 @@
 CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_SYSFS_DEPRECATED_V2=y
 CONFIG_BLK_DEV_INITRD=y
 CONFIG_KALLSYMS_ALL=y
 CONFIG_MODULES=y
@@ -13,43 +12,89 @@
 CONFIG_UX500_SOC_DB8500=y
 CONFIG_MACH_U8500=y
 CONFIG_MACH_U5500=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_SMP=y
 CONFIG_NR_CPUS=2
+CONFIG_HOTPLUG_CPU=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_CMDLINE="root=/dev/ram0 console=ttyAMA2,115200n8"
+CONFIG_CPU_FREQ=y
+CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND=y
 CONFIG_VFP=y
 CONFIG_NEON=y
+CONFIG_NET=y
+CONFIG_PHONET=y
+CONFIG_PHONET_PIPECTRLR=y
+# CONFIG_WIRELESS is not set
+CONFIG_CAIF=y
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=65536
-# CONFIG_MISC_DEVICES is not set
+CONFIG_MISC_DEVICES=y
+CONFIG_AB8500_PWM=y
+CONFIG_SENSORS_BH1780=y
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
-# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_KEYBOARD_ATKBD is not set
+CONFIG_KEYBOARD_GPIO=y
+CONFIG_KEYBOARD_NOMADIK=y
+CONFIG_KEYBOARD_STMPE=y
+CONFIG_KEYBOARD_TC3589X=y
 # CONFIG_INPUT_MOUSE is not set
+CONFIG_INPUT_TOUCHSCREEN=y
+CONFIG_TOUCHSCREEN_BU21013=y
+CONFIG_INPUT_MISC=y
+CONFIG_INPUT_AB8500_PONKEY=y
 # CONFIG_SERIO is not set
 CONFIG_VT_HW_CONSOLE_BINDING=y
 CONFIG_SERIAL_AMBA_PL011=y
 CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
+CONFIG_HW_RANDOM=y
+CONFIG_HW_RANDOM_NOMADIK=y
+CONFIG_I2C=y
+CONFIG_I2C_NOMADIK=y
 CONFIG_SPI=y
 CONFIG_SPI_PL022=y
+CONFIG_GPIO_STMPE=y
+CONFIG_GPIO_TC3589X=y
 # CONFIG_HWMON is not set
-# CONFIG_VGA_CONSOLE is not set
+CONFIG_MFD_STMPE=y
+CONFIG_MFD_TC3589X=y
+CONFIG_AB8500_CORE=y
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_AB8500=y
 # CONFIG_HID_SUPPORT is not set
 # CONFIG_USB_SUPPORT is not set
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_LP5521=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_AB8500=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_DMADEVICES=y
+CONFIG_STE_DMA40=y
+CONFIG_STAGING=y
+# CONFIG_STAGING_EXCLUDE_BUILD is not set
+CONFIG_TOUCHSCREEN_SYNAPTICS_I2C_RMI4=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT2_FS_XATTR=y
 CONFIG_EXT2_FS_POSIX_ACL=y
 CONFIG_EXT2_FS_SECURITY=y
-CONFIG_INOTIFY=y
+CONFIG_EXT3_FS=y
+CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
 CONFIG_TMPFS_POSIX_ACL=y
 CONFIG_CONFIGFS_FS=m
 # CONFIG_MISC_FILESYSTEMS is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
 CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 # CONFIG_DEBUG_PREEMPT is not set
@@ -58,5 +103,3 @@
 # CONFIG_FTRACE is not set
 CONFIG_DEBUG_USER=y
 CONFIG_DEBUG_ERRORS=y
-CONFIG_CRC_T10DIF=m
-# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/arm/configs/vexpress_defconfig linux-libre-2.6.39-gnu/arch/arm/configs/vexpress_defconfig
--- linux-libre-2.6.38-gnu/arch/arm/configs/vexpress_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/configs/vexpress_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,140 @@
+CONFIG_EXPERIMENTAL=y
+# CONFIG_LOCALVERSION_AUTO is not set
+CONFIG_SYSVIPC=y
+CONFIG_IKCONFIG=y
+CONFIG_IKCONFIG_PROC=y
+CONFIG_LOG_BUF_SHIFT=14
+CONFIG_CGROUPS=y
+CONFIG_CPUSETS=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_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_PROFILING=y
+CONFIG_OPROFILE=y
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_LBDAF is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_ARCH_VEXPRESS=y
+CONFIG_ARCH_VEXPRESS_CA9X4=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_SMP=y
+CONFIG_VMSPLIT_2G=y
+CONFIG_HOTPLUG_CPU=y
+CONFIG_AEABI=y
+CONFIG_ZBOOT_ROM_TEXT=0x0
+CONFIG_ZBOOT_ROM_BSS=0x0
+CONFIG_CMDLINE="root=/dev/nfs nfsroot=10.1.69.3:/work/nfsroot ip=dhcp console=ttyAMA0 mem=128M"
+CONFIG_VFP=y
+CONFIG_NEON=y
+# CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=y
+CONFIG_IP_PNP=y
+CONFIG_IP_PNP_DHCP=y
+CONFIG_IP_PNP_BOOTP=y
+# CONFIG_INET_LRO is not set
+# CONFIG_IPV6 is not set
+# CONFIG_WIRELESS is not set
+CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CMDLINE_PARTS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_CFI=y
+CONFIG_MTD_CFI_INTELEXT=y
+CONFIG_MTD_CFI_AMDSTD=y
+CONFIG_MTD_ARM_INTEGRATOR=y
+CONFIG_MISC_DEVICES=y
+# CONFIG_SCSI_PROC_FS is not set
+CONFIG_BLK_DEV_SD=y
+# CONFIG_SCSI_LOWLEVEL is not set
+CONFIG_ATA=y
+# CONFIG_SATA_PMP is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_SMSC911X=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_WLAN is not set
+CONFIG_INPUT_EVDEV=y
+# CONFIG_SERIO_SERPORT is not set
+CONFIG_SERIO_AMBAKMI=y
+CONFIG_SERIAL_AMBA_PL011=y
+CONFIG_SERIAL_AMBA_PL011_CONSOLE=y
+CONFIG_LEGACY_PTY_COUNT=16
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+CONFIG_FB=y
+CONFIG_FB_ARMCLCD=y
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_LOGO=y
+# CONFIG_LOGO_LINUX_MONO is not set
+# CONFIG_LOGO_LINUX_VGA16 is not set
+CONFIG_SOUND=y
+CONFIG_SND=y
+CONFIG_SND_MIXER_OSS=y
+CONFIG_SND_PCM_OSS=y
+# CONFIG_SND_DRIVERS is not set
+CONFIG_SND_ARMAACI=y
+CONFIG_HID_DRAGONRISE=y
+CONFIG_HID_GYRATION=y
+CONFIG_HID_TWINHAN=y
+CONFIG_HID_NTRIG=y
+CONFIG_HID_PANTHERLORD=y
+CONFIG_HID_PETALYNX=y
+CONFIG_HID_SAMSUNG=y
+CONFIG_HID_SONY=y
+CONFIG_HID_SUNPLUS=y
+CONFIG_HID_GREENASIA=y
+CONFIG_HID_SMARTJOYPLUS=y
+CONFIG_HID_TOPSEED=y
+CONFIG_HID_THRUSTMASTER=y
+CONFIG_HID_ZEROPLUS=y
+CONFIG_USB=y
+CONFIG_USB_ANNOUNCE_NEW_DEVICES=y
+# CONFIG_USB_DEVICE_CLASS is not set
+CONFIG_USB_MON=y
+CONFIG_USB_ISP1760_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_ARMMMCI=y
+CONFIG_RTC_CLASS=y
+CONFIG_RTC_DRV_PL031=y
+CONFIG_EXT2_FS=y
+CONFIG_EXT3_FS=y
+# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
+# CONFIG_EXT3_FS_XATTR is not set
+CONFIG_VFAT_FS=y
+CONFIG_TMPFS=y
+CONFIG_JFFS2_FS=y
+CONFIG_CRAMFS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+# CONFIG_RPCSEC_GSS_KRB5 is not set
+CONFIG_NLS_CODEPAGE_437=y
+CONFIG_NLS_ISO8859_1=y
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_FS=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_DETECT_HUNG_TASK=y
+# CONFIG_SCHED_DEBUG is not set
+CONFIG_DEBUG_INFO=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_DEBUG_USER=y
+CONFIG_DEBUG_ERRORS=y
+CONFIG_DEBUG_LL=y
+CONFIG_EARLY_PRINTK=y
+# CONFIG_CRYPTO_ANSI_CPRNG is not set
+# CONFIG_CRYPTO_HW is not set
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/a.out-core.h linux-libre-2.6.39-gnu/arch/arm/include/asm/a.out-core.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/a.out-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/a.out-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,11 +32,7 @@
 	dump->u_dsize = (tsk->mm->brk - tsk->mm->start_data + PAGE_SIZE - 1) >> PAGE_SHIFT;
 	dump->u_ssize = 0;
 
-	dump->u_debugreg[0] = tsk->thread.debug.bp[0].address;
-	dump->u_debugreg[1] = tsk->thread.debug.bp[1].address;
-	dump->u_debugreg[2] = tsk->thread.debug.bp[0].insn.arm;
-	dump->u_debugreg[3] = tsk->thread.debug.bp[1].insn.arm;
-	dump->u_debugreg[4] = tsk->thread.debug.nsaved;
+	memset(dump->u_debugreg, 0, sizeof(dump->u_debugreg));
 
 	if (dump->start_stack < 0x04000000)
 		dump->u_ssize = (0x04000000 - dump->start_stack) >> PAGE_SHIFT;
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/arm/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -149,14 +149,18 @@
  */
 
 /*
+ * Native endian assembly bitops.  nr = 0 -> word 0 bit 0.
+ */
+extern void _set_bit(int nr, volatile unsigned long * p);
+extern void _clear_bit(int nr, volatile unsigned long * p);
+extern void _change_bit(int nr, volatile unsigned long * p);
+extern int _test_and_set_bit(int nr, volatile unsigned long * p);
+extern int _test_and_clear_bit(int nr, volatile unsigned long * p);
+extern int _test_and_change_bit(int nr, volatile unsigned long * p);
+
+/*
  * Little endian assembly bitops.  nr = 0 -> byte 0 bit 0.
  */
-extern void _set_bit_le(int nr, volatile unsigned long * p);
-extern void _clear_bit_le(int nr, volatile unsigned long * p);
-extern void _change_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_le(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_le(int nr, volatile unsigned long * p);
 extern int _find_first_zero_bit_le(const void * p, unsigned size);
 extern int _find_next_zero_bit_le(const void * p, int size, int offset);
 extern int _find_first_bit_le(const unsigned long *p, unsigned size);
@@ -165,12 +169,6 @@
 /*
  * Big endian assembly bitops.  nr = 0 -> byte 3 bit 0.
  */
-extern void _set_bit_be(int nr, volatile unsigned long * p);
-extern void _clear_bit_be(int nr, volatile unsigned long * p);
-extern void _change_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_set_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_clear_bit_be(int nr, volatile unsigned long * p);
-extern int _test_and_change_bit_be(int nr, volatile unsigned long * p);
 extern int _find_first_zero_bit_be(const void * p, unsigned size);
 extern int _find_next_zero_bit_be(const void * p, int size, int offset);
 extern int _find_first_bit_be(const unsigned long *p, unsigned size);
@@ -180,33 +178,26 @@
 /*
  * The __* form of bitops are non-atomic and may be reordered.
  */
-#define	ATOMIC_BITOP_LE(name,nr,p)		\
-	(__builtin_constant_p(nr) ?		\
-	 ____atomic_##name(nr, p) :		\
-	 _##name##_le(nr,p))
-
-#define	ATOMIC_BITOP_BE(name,nr,p)		\
-	(__builtin_constant_p(nr) ?		\
-	 ____atomic_##name(nr, p) :		\
-	 _##name##_be(nr,p))
+#define ATOMIC_BITOP(name,nr,p)			\
+	(__builtin_constant_p(nr) ? ____atomic_##name(nr, p) : _##name(nr,p))
 #else
-#define ATOMIC_BITOP_LE(name,nr,p)	_##name##_le(nr,p)
-#define ATOMIC_BITOP_BE(name,nr,p)	_##name##_be(nr,p)
+#define ATOMIC_BITOP(name,nr,p)		_##name(nr,p)
 #endif
 
-#define NONATOMIC_BITOP(name,nr,p)		\
-	(____nonatomic_##name(nr, p))
+/*
+ * Native endian atomic definitions.
+ */
+#define set_bit(nr,p)			ATOMIC_BITOP(set_bit,nr,p)
+#define clear_bit(nr,p)			ATOMIC_BITOP(clear_bit,nr,p)
+#define change_bit(nr,p)		ATOMIC_BITOP(change_bit,nr,p)
+#define test_and_set_bit(nr,p)		ATOMIC_BITOP(test_and_set_bit,nr,p)
+#define test_and_clear_bit(nr,p)	ATOMIC_BITOP(test_and_clear_bit,nr,p)
+#define test_and_change_bit(nr,p)	ATOMIC_BITOP(test_and_change_bit,nr,p)
 
 #ifndef __ARMEB__
 /*
  * These are the little endian, atomic definitions.
  */
-#define set_bit(nr,p)			ATOMIC_BITOP_LE(set_bit,nr,p)
-#define clear_bit(nr,p)			ATOMIC_BITOP_LE(clear_bit,nr,p)
-#define change_bit(nr,p)		ATOMIC_BITOP_LE(change_bit,nr,p)
-#define test_and_set_bit(nr,p)		ATOMIC_BITOP_LE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p)	ATOMIC_BITOP_LE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p)	ATOMIC_BITOP_LE(test_and_change_bit,nr,p)
 #define find_first_zero_bit(p,sz)	_find_first_zero_bit_le(p,sz)
 #define find_next_zero_bit(p,sz,off)	_find_next_zero_bit_le(p,sz,off)
 #define find_first_bit(p,sz)		_find_first_bit_le(p,sz)
@@ -215,16 +206,9 @@
 #define WORD_BITOFF_TO_LE(x)		((x))
 
 #else
-
 /*
  * These are the big endian, atomic definitions.
  */
-#define set_bit(nr,p)			ATOMIC_BITOP_BE(set_bit,nr,p)
-#define clear_bit(nr,p)			ATOMIC_BITOP_BE(clear_bit,nr,p)
-#define change_bit(nr,p)		ATOMIC_BITOP_BE(change_bit,nr,p)
-#define test_and_set_bit(nr,p)		ATOMIC_BITOP_BE(test_and_set_bit,nr,p)
-#define test_and_clear_bit(nr,p)	ATOMIC_BITOP_BE(test_and_clear_bit,nr,p)
-#define test_and_change_bit(nr,p)	ATOMIC_BITOP_BE(test_and_change_bit,nr,p)
 #define find_first_zero_bit(p,sz)	_find_first_zero_bit_be(p,sz)
 #define find_next_zero_bit(p,sz,off)	_find_next_zero_bit_be(p,sz,off)
 #define find_first_bit(p,sz)		_find_first_bit_be(p,sz)
@@ -303,41 +287,63 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 
-/*
- * Ext2 is defined to use little-endian byte ordering.
- * These do not need to be atomic.
- */
-#define ext2_set_bit(nr,p)			\
-		__test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define ext2_set_bit_atomic(lock,nr,p)          \
-                test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define ext2_clear_bit(nr,p)			\
-		__test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define ext2_clear_bit_atomic(lock,nr,p)        \
-                test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define ext2_test_bit(nr,p)			\
-		test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define ext2_find_first_zero_bit(p,sz)		\
-		_find_first_zero_bit_le(p,sz)
-#define ext2_find_next_zero_bit(p,sz,off)	\
-		_find_next_zero_bit_le(p,sz,off)
-#define ext2_find_next_bit(p, sz, off) \
-		_find_next_bit_le(p, sz, off)
+static inline void __set_bit_le(int nr, void *addr)
+{
+	__set_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline void __clear_bit_le(int nr, void *addr)
+{
+	__clear_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline int __test_and_set_bit_le(int nr, void *addr)
+{
+	return __test_and_set_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline int test_and_set_bit_le(int nr, void *addr)
+{
+	return test_and_set_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline int __test_and_clear_bit_le(int nr, void *addr)
+{
+	return __test_and_clear_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline int test_and_clear_bit_le(int nr, void *addr)
+{
+	return test_and_clear_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline int test_bit_le(int nr, const void *addr)
+{
+	return test_bit(WORD_BITOFF_TO_LE(nr), addr);
+}
+
+static inline int find_first_zero_bit_le(const void *p, unsigned size)
+{
+	return _find_first_zero_bit_le(p, size);
+}
+
+static inline int find_next_zero_bit_le(const void *p, int size, int offset)
+{
+	return _find_next_zero_bit_le(p, size, offset);
+}
+
+static inline int find_next_bit_le(const void *p, int size, int offset)
+{
+	return _find_next_bit_le(p, size, offset);
+}
 
 /*
- * Minix is defined to use little-endian byte ordering.
- * These do not need to be atomic.
+ * Ext2 is defined to use little-endian byte ordering.
  */
-#define minix_set_bit(nr,p)			\
-		__set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_bit(nr,p)			\
-		test_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_and_set_bit(nr,p)		\
-		__test_and_set_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_test_and_clear_bit(nr,p)		\
-		__test_and_clear_bit(WORD_BITOFF_TO_LE(nr), (unsigned long *)(p))
-#define minix_find_first_zero_bit(p,sz)		\
-		_find_first_zero_bit_le(p,sz)
+#define ext2_set_bit_atomic(lock, nr, p)	\
+		test_and_set_bit_le(nr, p)
+#define ext2_clear_bit_atomic(lock, nr, p)	\
+		test_and_clear_bit_le(nr, p)
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/arm/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
 
 #include <linux/mm.h>
 
-#include <asm/glue.h>
+#include <asm/glue-cache.h>
 #include <asm/shmparam.h>
 #include <asm/cachetype.h>
 #include <asm/outercache.h>
@@ -20,123 +20,6 @@
 #define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
 
 /*
- *	Cache Model
- *	===========
- */
-#undef _CACHE
-#undef MULTI_CACHE
-
-#if defined(CONFIG_CPU_CACHE_V3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_CACHE_V4)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v4
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
-    defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \
-    defined(CONFIG_CPU_ARM1026)
-# define MULTI_CACHE 1
-#endif
-
-#if defined(CONFIG_CPU_FA526)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE fa
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM926T)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm926
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM940T)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm940
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM946E)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE arm946
-# endif
-#endif
-
-#if defined(CONFIG_CPU_CACHE_V4WB)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE v4wb
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSCALE)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE xscale
-# endif
-#endif
-
-#if defined(CONFIG_CPU_XSC3)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE xsc3
-# endif
-#endif
-
-#if defined(CONFIG_CPU_MOHAWK)
-# ifdef _CACHE
-#  define MULTI_CACHE 1
-# else
-#  define _CACHE mohawk
-# endif
-#endif
-
-#if defined(CONFIG_CPU_FEROCEON)
-# define MULTI_CACHE 1
-#endif
-
-#if defined(CONFIG_CPU_V6)
-//# ifdef _CACHE
-#  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v6
-//# endif
-#endif
-
-#if defined(CONFIG_CPU_V7)
-//# ifdef _CACHE
-#  define MULTI_CACHE 1
-//# else
-//#  define _CACHE v7
-//# endif
-#endif
-
-#if !defined(_CACHE) && !defined(MULTI_CACHE)
-#error Unknown cache maintainence model
-#endif
-
-/*
  * This flag is used to indicate that the page pointed to by a pte is clean
  * and does not require cleaning before returning it to the user.
  */
@@ -249,19 +132,11 @@
  * visible to the CPU.
  */
 #define dmac_map_area			cpu_cache.dma_map_area
-#define dmac_unmap_area		cpu_cache.dma_unmap_area
+#define dmac_unmap_area			cpu_cache.dma_unmap_area
 #define dmac_flush_range		cpu_cache.dma_flush_range
 
 #else
 
-#define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
-#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
-#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
-#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
-#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
-#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
-#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
-
 extern void __cpuc_flush_icache_all(void);
 extern void __cpuc_flush_kern_all(void);
 extern void __cpuc_flush_user_all(void);
@@ -276,10 +151,6 @@
  * is visible to DMA, or data written by DMA to system memory is
  * visible to the CPU.
  */
-#define dmac_map_area			__glue(_CACHE,_dma_map_area)
-#define dmac_unmap_area		__glue(_CACHE,_dma_unmap_area)
-#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
-
 extern void dmac_map_area(const void *, size_t, int);
 extern void dmac_unmap_area(const void *, size_t, int);
 extern void dmac_flush_range(const void *, const void *);
@@ -316,7 +187,8 @@
  * Optimized __flush_icache_all for the common cases. Note that UP ARMv7
  * will fall through to use __flush_icache_all_generic.
  */
-#if (defined(CONFIG_CPU_V7) && defined(CONFIG_CPU_V6)) ||		\
+#if (defined(CONFIG_CPU_V7) && \
+     (defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K))) || \
 	defined(CONFIG_SMP_ON_UP)
 #define __flush_icache_preferred	__cpuc_flush_icache_all
 #elif __LINUX_ARM_ARCH__ >= 7 && defined(CONFIG_SMP)
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/cpu-multi32.h linux-libre-2.6.39-gnu/arch/arm/include/asm/cpu-multi32.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/cpu-multi32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/cpu-multi32.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/*
- *  arch/arm/include/asm/cpu-multi32.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 version 2 as
- * published by the Free Software Foundation.
- */
-#include <asm/page.h>
-
-struct mm_struct;
-
-/*
- * Don't change this structure - ASM code
- * relies on it.
- */
-extern struct processor {
-	/* MISC
-	 * get data abort address/flags
-	 */
-	void (*_data_abort)(unsigned long pc);
-	/*
-	 * Retrieve prefetch fault address
-	 */
-	unsigned long (*_prefetch_abort)(unsigned long lr);
-	/*
-	 * Set up any processor specifics
-	 */
-	void (*_proc_init)(void);
-	/*
-	 * Disable any processor specifics
-	 */
-	void (*_proc_fin)(void);
-	/*
-	 * Special stuff for a reset
-	 */
-	void (*reset)(unsigned long addr) __attribute__((noreturn));
-	/*
-	 * Idle the processor
-	 */
-	int (*_do_idle)(void);
-	/*
-	 * Processor architecture specific
-	 */
-	/*
-	 * clean a virtual address range from the
-	 * D-cache without flushing the cache.
-	 */
-	void (*dcache_clean_area)(void *addr, int size);
-
-	/*
-	 * Set the page table
-	 */
-	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
-	/*
-	 * Set a possibly extended PTE.  Non-extended PTEs should
-	 * ignore 'ext'.
-	 */
-	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
-} processor;
-
-#define cpu_proc_init()			processor._proc_init()
-#define cpu_proc_fin()			processor._proc_fin()
-#define cpu_reset(addr)			processor.reset(addr)
-#define cpu_do_idle()			processor._do_idle()
-#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
-#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
-#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/cpu-single.h linux-libre-2.6.39-gnu/arch/arm/include/asm/cpu-single.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/cpu-single.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/cpu-single.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,44 +0,0 @@
-/*
- *  arch/arm/include/asm/cpu-single.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 version 2 as
- * published by the Free Software Foundation.
- */
-/*
- * Single CPU
- */
-#ifdef __STDC__
-#define __catify_fn(name,x)	name##x
-#else
-#define __catify_fn(name,x)	name/**/x
-#endif
-#define __cpu_fn(name,x)	__catify_fn(name,x)
-
-/*
- * If we are supporting multiple CPUs, then we must use a table of
- * function pointers for this lot.  Otherwise, we can optimise the
- * table away.
- */
-#define cpu_proc_init			__cpu_fn(CPU_NAME,_proc_init)
-#define cpu_proc_fin			__cpu_fn(CPU_NAME,_proc_fin)
-#define cpu_reset			__cpu_fn(CPU_NAME,_reset)
-#define cpu_do_idle			__cpu_fn(CPU_NAME,_do_idle)
-#define cpu_dcache_clean_area		__cpu_fn(CPU_NAME,_dcache_clean_area)
-#define cpu_do_switch_mm		__cpu_fn(CPU_NAME,_switch_mm)
-#define cpu_set_pte_ext			__cpu_fn(CPU_NAME,_set_pte_ext)
-
-#include <asm/page.h>
-
-struct mm_struct;
-
-/* declare all the functions as extern */
-extern void cpu_proc_init(void);
-extern void cpu_proc_fin(void);
-extern int cpu_do_idle(void);
-extern void cpu_dcache_clean_area(void *, int);
-extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
-extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
-extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/cputype.h linux-libre-2.6.39-gnu/arch/arm/include/asm/cputype.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/cputype.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/cputype.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,7 @@
 #define __ASM_ARM_CPUTYPE_H
 
 #include <linux/stringify.h>
+#include <linux/kernel.h>
 
 #define CPUID_ID	0
 #define CPUID_CACHETYPE	1
@@ -23,6 +24,8 @@
 #define CPUID_EXT_ISAR4	"c2, 4"
 #define CPUID_EXT_ISAR5	"c2, 5"
 
+extern unsigned int processor_id;
+
 #ifdef CONFIG_CPU_CP15
 #define read_cpuid(reg)							\
 	({								\
@@ -43,7 +46,6 @@
 		__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.38-gnu/arch/arm/include/asm/fncpy.h linux-libre-2.6.39-gnu/arch/arm/include/asm/fncpy.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/fncpy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/fncpy.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * arch/arm/include/asm/fncpy.h - helper macros for function body copying
+ *
+ * Copyright (C) 2011 Linaro 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
+ */
+
+/*
+ * These macros are intended for use when there is a need to copy a low-level
+ * function body into special memory.
+ *
+ * For example, when reconfiguring the SDRAM controller, the code doing the
+ * reconfiguration may need to run from SRAM.
+ *
+ * NOTE: that the copied function body must be entirely self-contained and
+ * position-independent in order for this to work properly.
+ *
+ * NOTE: in order for embedded literals and data to get referenced correctly,
+ * the alignment of functions must be preserved when copying.  To ensure this,
+ * the source and destination addresses for fncpy() must be aligned to a
+ * multiple of 8 bytes: you will be get a BUG() if this condition is not met.
+ * You will typically need a ".align 3" directive in the assembler where the
+ * function to be copied is defined, and ensure that your allocator for the
+ * destination buffer returns 8-byte-aligned pointers.
+ *
+ * Typical usage example:
+ *
+ * extern int f(args);
+ * extern uint32_t size_of_f;
+ * int (*copied_f)(args);
+ * void *sram_buffer;
+ *
+ * copied_f = fncpy(sram_buffer, &f, size_of_f);
+ *
+ * ... later, call the function: ...
+ *
+ * copied_f(args);
+ *
+ * The size of the function to be copied can't be determined from C:
+ * this must be determined by other means, such as adding assmbler directives
+ * in the file where f is defined.
+ */
+
+#ifndef __ASM_FNCPY_H
+#define __ASM_FNCPY_H
+
+#include <linux/types.h>
+#include <linux/string.h>
+
+#include <asm/bug.h>
+#include <asm/cacheflush.h>
+
+/*
+ * Minimum alignment requirement for the source and destination addresses
+ * for function copying.
+ */
+#define FNCPY_ALIGN 8
+
+#define fncpy(dest_buf, funcp, size) ({					\
+	uintptr_t __funcp_address;					\
+	typeof(funcp) __result;						\
+									\
+	asm("" : "=r" (__funcp_address) : "0" (funcp));			\
+									\
+	/*								\
+	 * Ensure alignment of source and destination addresses,	\
+	 * disregarding the function's Thumb bit:			\
+	 */								\
+	BUG_ON((uintptr_t)(dest_buf) & (FNCPY_ALIGN - 1) ||		\
+		(__funcp_address & ~(uintptr_t)1 & (FNCPY_ALIGN - 1)));	\
+									\
+	memcpy(dest_buf, (void const *)(__funcp_address & ~1), size);	\
+	flush_icache_range((unsigned long)(dest_buf),			\
+		(unsigned long)(dest_buf) + (size));			\
+									\
+	asm("" : "=r" (__result)					\
+		: "0" ((uintptr_t)(dest_buf) | (__funcp_address & 1)));	\
+									\
+	__result;							\
+})
+
+#endif /* !__ASM_FNCPY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/fpstate.h linux-libre-2.6.39-gnu/arch/arm/include/asm/fpstate.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/fpstate.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/fpstate.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
  * VFP storage area has:
  *  - FPEXC, FPSCR, FPINST and FPINST2.
  *  - 16 or 32 double precision data registers
- *  - an implementation-dependant word of state for FLDMX/FSTMX (pre-ARMv6)
+ *  - an implementation-dependent word of state for FLDMX/FSTMX (pre-ARMv6)
  * 
  *  FPEXC will always be non-zero once the VFP has been used in this process.
  */
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/futex.h linux-libre-2.6.39-gnu/arch/arm/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 	: "cc", "memory")
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -46,7 +46,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();	/* implies preempt_disable() */
@@ -88,36 +88,35 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int val;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	pagefault_disable();	/* implies preempt_disable() */
-
 	__asm__ __volatile__("@futex_atomic_cmpxchg_inatomic\n"
-	"1:	" T(ldr) "	%0, [%3]\n"
-	"	teq	%0, %1\n"
+	"1:	" T(ldr) "	%1, [%4]\n"
+	"	teq	%1, %2\n"
 	"	it	eq	@ explicit IT needed for the 2b label\n"
-	"2:	" T(streq) "	%2, [%3]\n"
+	"2:	" T(streq) "	%3, [%4]\n"
 	"3:\n"
 	"	.pushsection __ex_table,\"a\"\n"
 	"	.align	3\n"
 	"	.long	1b, 4f, 2b, 4f\n"
 	"	.popsection\n"
 	"	.pushsection .fixup,\"ax\"\n"
-	"4:	mov	%0, %4\n"
+	"4:	mov	%0, %5\n"
 	"	b	3b\n"
 	"	.popsection"
-	: "=&r" (val)
+	: "+r" (ret), "=&r" (val)
 	: "r" (oldval), "r" (newval), "r" (uaddr), "Ir" (-EFAULT)
 	: "cc", "memory");
 
-	pagefault_enable();	/* subsumes preempt_enable() */
-
-	return val;
+	*uval = val;
+	return ret;
 }
 
 #endif /* !SMP */
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-cache.h linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-cache.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-cache.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-cache.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,146 @@
+/*
+ *  arch/arm/include/asm/glue-cache.h
+ *
+ *  Copyright (C) 1999-2002 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.
+ */
+#ifndef ASM_GLUE_CACHE_H
+#define ASM_GLUE_CACHE_H
+
+#include <asm/glue.h>
+
+/*
+ *	Cache Model
+ *	===========
+ */
+#undef _CACHE
+#undef MULTI_CACHE
+
+#if defined(CONFIG_CPU_CACHE_V3)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM920T) || defined(CONFIG_CPU_ARM922T) || \
+    defined(CONFIG_CPU_ARM925T) || defined(CONFIG_CPU_ARM1020) || \
+    defined(CONFIG_CPU_ARM1026)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_FA526)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE fa
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM926T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm926
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM940T)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm940
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM946E)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE arm946
+# endif
+#endif
+
+#if defined(CONFIG_CPU_CACHE_V4WB)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE v4wb
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSCALE)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xscale
+# endif
+#endif
+
+#if defined(CONFIG_CPU_XSC3)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE xsc3
+# endif
+#endif
+
+#if defined(CONFIG_CPU_MOHAWK)
+# ifdef _CACHE
+#  define MULTI_CACHE 1
+# else
+#  define _CACHE mohawk
+# endif
+#endif
+
+#if defined(CONFIG_CPU_FEROCEON)
+# define MULTI_CACHE 1
+#endif
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v6
+//# endif
+#endif
+
+#if defined(CONFIG_CPU_V7)
+//# ifdef _CACHE
+#  define MULTI_CACHE 1
+//# else
+//#  define _CACHE v7
+//# endif
+#endif
+
+#if !defined(_CACHE) && !defined(MULTI_CACHE)
+#error Unknown cache maintenance model
+#endif
+
+#ifndef MULTI_CACHE
+#define __cpuc_flush_icache_all		__glue(_CACHE,_flush_icache_all)
+#define __cpuc_flush_kern_all		__glue(_CACHE,_flush_kern_cache_all)
+#define __cpuc_flush_user_all		__glue(_CACHE,_flush_user_cache_all)
+#define __cpuc_flush_user_range		__glue(_CACHE,_flush_user_cache_range)
+#define __cpuc_coherent_kern_range	__glue(_CACHE,_coherent_kern_range)
+#define __cpuc_coherent_user_range	__glue(_CACHE,_coherent_user_range)
+#define __cpuc_flush_dcache_area	__glue(_CACHE,_flush_kern_dcache_area)
+
+#define dmac_map_area			__glue(_CACHE,_dma_map_area)
+#define dmac_unmap_area			__glue(_CACHE,_dma_unmap_area)
+#define dmac_flush_range		__glue(_CACHE,_dma_flush_range)
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-df.h linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-df.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-df.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-df.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ *  arch/arm/include/asm/glue-df.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000-2002 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.
+ */
+#ifndef ASM_GLUE_DF_H
+#define ASM_GLUE_DF_H
+
+#include <asm/glue.h>
+
+/*
+ *	Data Abort Model
+ *	================
+ *
+ *	We have the following to choose from:
+ *	  arm6          - ARM6 style
+ *	  arm7		- ARM7 style
+ *	  v4_early	- ARMv4 without Thumb early abort handler
+ *	  v4t_late	- ARMv4 with Thumb late abort handler
+ *	  v4t_early	- ARMv4 with Thumb early abort handler
+ *	  v5tej_early	- ARMv5 with Thumb and Java early abort handler
+ *	  xscale	- ARMv5 with Thumb with Xscale extensions
+ *	  v6_early	- ARMv6 generic early abort handler
+ *	  v7_early	- ARMv7 generic early abort handler
+ */
+#undef CPU_DABORT_HANDLER
+#undef MULTI_DABORT
+
+#if defined(CONFIG_CPU_ARM610)
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
+# endif
+#endif
+
+#if defined(CONFIG_CPU_ARM710)
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_LV4T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4t_late_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV4
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV4T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v4t_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV5TJ
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v5tj_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV5T
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v5t_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV6
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v6_early_abort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ABRT_EV7
+# ifdef CPU_DABORT_HANDLER
+#  define MULTI_DABORT 1
+# else
+#  define CPU_DABORT_HANDLER v7_early_abort
+# endif
+#endif
+
+#ifndef CPU_DABORT_HANDLER
+#error Unknown data abort handler type
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/glue.h linux-libre-2.6.39-gnu/arch/arm/include/asm/glue.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/glue.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/glue.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,12 +10,11 @@
  *
  *  This file provides the glue to stick the processor-specific bits
  *  into the kernel in an efficient manner.  The idea is to use branches
- *  when we're only targetting one class of TLB, or indirect calls
- *  when we're targetting multiple classes of TLBs.
+ *  when we're only targeting one class of TLB, or indirect calls
+ *  when we're targeting multiple classes of TLBs.
  */
 #ifdef __KERNEL__
 
-
 #ifdef __STDC__
 #define ____glue(name,fn)	name##fn
 #else
@@ -23,141 +22,4 @@
 #endif
 #define __glue(name,fn)		____glue(name,fn)
 
-
-
-/*
- *	Data Abort Model
- *	================
- *
- *	We have the following to choose from:
- *	  arm6          - ARM6 style
- *	  arm7		- ARM7 style
- *	  v4_early	- ARMv4 without Thumb early abort handler
- *	  v4t_late	- ARMv4 with Thumb late abort handler
- *	  v4t_early	- ARMv4 with Thumb early abort handler
- *	  v5tej_early	- ARMv5 with Thumb and Java early abort handler
- *	  xscale	- ARMv5 with Thumb with Xscale extensions
- *	  v6_early	- ARMv6 generic early abort handler
- *	  v7_early	- ARMv7 generic early abort handler
- */
-#undef CPU_DABORT_HANDLER
-#undef MULTI_DABORT
-
-#if defined(CONFIG_CPU_ARM610)
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER cpu_arm6_data_abort
-# endif
-#endif
-
-#if defined(CONFIG_CPU_ARM710)
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER cpu_arm7_data_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_LV4T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4t_late_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV4
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV4T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v4t_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV5TJ
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v5tj_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV5T
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v5t_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV6
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v6_early_abort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ABRT_EV7
-# ifdef CPU_DABORT_HANDLER
-#  define MULTI_DABORT 1
-# else
-#  define CPU_DABORT_HANDLER v7_early_abort
-# endif
-#endif
-
-#ifndef CPU_DABORT_HANDLER
-#error Unknown data abort handler type
-#endif
-
-/*
- *	Prefetch Abort Model
- *	================
- *
- *	We have the following to choose from:
- *	  legacy	- no IFSR, no IFAR
- *	  v6		- ARMv6: IFSR, no IFAR
- *	  v7		- ARMv7: IFSR and IFAR
- */
-
-#undef CPU_PABORT_HANDLER
-#undef MULTI_PABORT
-
-#ifdef CONFIG_CPU_PABRT_LEGACY
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER legacy_pabort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_PABRT_V6
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER v6_pabort
-# endif
-#endif
-
-#ifdef CONFIG_CPU_PABRT_V7
-# ifdef CPU_PABORT_HANDLER
-#  define MULTI_PABORT 1
-# else
-#  define CPU_PABORT_HANDLER v7_pabort
-# endif
-#endif
-
-#ifndef CPU_PABORT_HANDLER
-#error Unknown prefetch abort handler type
-#endif
-
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-pf.h linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-pf.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-pf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-pf.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ *  arch/arm/include/asm/glue-pf.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  Copyright (C) 2000-2002 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.
+ */
+#ifndef ASM_GLUE_PF_H
+#define ASM_GLUE_PF_H
+
+#include <asm/glue.h>
+
+/*
+ *	Prefetch Abort Model
+ *	================
+ *
+ *	We have the following to choose from:
+ *	  legacy	- no IFSR, no IFAR
+ *	  v6		- ARMv6: IFSR, no IFAR
+ *	  v7		- ARMv7: IFSR and IFAR
+ */
+
+#undef CPU_PABORT_HANDLER
+#undef MULTI_PABORT
+
+#ifdef CONFIG_CPU_PABRT_LEGACY
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER legacy_pabort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_PABRT_V6
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER v6_pabort
+# endif
+#endif
+
+#ifdef CONFIG_CPU_PABRT_V7
+# ifdef CPU_PABORT_HANDLER
+#  define MULTI_PABORT 1
+# else
+#  define CPU_PABORT_HANDLER v7_pabort
+# endif
+#endif
+
+#ifndef CPU_PABORT_HANDLER
+#error Unknown prefetch abort handler type
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-proc.h linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-proc.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/glue-proc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/glue-proc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,264 @@
+/*
+ *  arch/arm/include/asm/glue-proc.h
+ *
+ *  Copyright (C) 1997-1999 Russell King
+ *  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.
+ */
+#ifndef ASM_GLUE_PROC_H
+#define ASM_GLUE_PROC_H
+
+#include <asm/glue.h>
+
+/*
+ * Work out if we need multiple CPU support
+ */
+#undef MULTI_CPU
+#undef CPU_NAME
+
+/*
+ * CPU_NAME - the prefix for CPU related functions
+ */
+
+#ifdef CONFIG_CPU_ARM610
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm6
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM7TDMI
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm7tdmi
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM710
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm7
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM720T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm720
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM740T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm740
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM9TDMI
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm9tdmi
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM920T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm920
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM922T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm922
+# endif
+#endif
+
+#ifdef CONFIG_CPU_FA526
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_fa526
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM925T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm925
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM926T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm926
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM940T
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm940
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM946E
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm946
+# endif
+#endif
+
+#ifdef CONFIG_CPU_SA110
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_sa110
+# endif
+#endif
+
+#ifdef CONFIG_CPU_SA1100
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_sa1100
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1020
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1020
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1020E
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1020e
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1022
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1022
+# endif
+#endif
+
+#ifdef CONFIG_CPU_ARM1026
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_arm1026
+# endif
+#endif
+
+#ifdef CONFIG_CPU_XSCALE
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_xscale
+# endif
+#endif
+
+#ifdef CONFIG_CPU_XSC3
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_xsc3
+# endif
+#endif
+
+#ifdef CONFIG_CPU_MOHAWK
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_mohawk
+# endif
+#endif
+
+#ifdef CONFIG_CPU_FEROCEON
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_feroceon
+# endif
+#endif
+
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v6
+# endif
+#endif
+
+#ifdef CONFIG_CPU_V7
+# ifdef CPU_NAME
+#  undef  MULTI_CPU
+#  define MULTI_CPU
+# else
+#  define CPU_NAME cpu_v7
+# endif
+#endif
+
+#ifndef MULTI_CPU
+#define cpu_proc_init			__glue(CPU_NAME,_proc_init)
+#define cpu_proc_fin			__glue(CPU_NAME,_proc_fin)
+#define cpu_reset			__glue(CPU_NAME,_reset)
+#define cpu_do_idle			__glue(CPU_NAME,_do_idle)
+#define cpu_dcache_clean_area		__glue(CPU_NAME,_dcache_clean_area)
+#define cpu_do_switch_mm		__glue(CPU_NAME,_switch_mm)
+#define cpu_set_pte_ext			__glue(CPU_NAME,_set_pte_ext)
+#define cpu_suspend_size		__glue(CPU_NAME,_suspend_size)
+#define cpu_do_suspend			__glue(CPU_NAME,_do_suspend)
+#define cpu_do_resume			__glue(CPU_NAME,_do_resume)
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/hardware/gic.h linux-libre-2.6.39-gnu/arch/arm/include/asm/hardware/gic.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/hardware/gic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/hardware/gic.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 
 #ifndef __ASSEMBLY__
 extern void __iomem *gic_cpu_base_addr;
+extern struct irq_chip gic_arch_extn;
 
 void gic_init(unsigned int, unsigned int, void __iomem *, void __iomem *);
 void gic_secondary_init(unsigned int);
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/hardware/pl080.h linux-libre-2.6.39-gnu/arch/arm/include/asm/hardware/pl080.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/hardware/pl080.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/hardware/pl080.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,7 +16,7 @@
  * 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 Samsung defines are PL080S, and add an extra control register,
  * the ability to move more than 2^11 counts of data and some extra
  * OneNAND features.
 */
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/highmem.h linux-libre-2.6.39-gnu/arch/arm/include/asm/highmem.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/highmem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/highmem.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,11 +19,36 @@
 
 extern pte_t *pkmap_page_table;
 
+extern void *kmap_high(struct page *page);
+extern void kunmap_high(struct page *page);
+
+/*
+ * The reason for kmap_high_get() is to ensure that the currently kmap'd
+ * page usage count does not decrease to zero while we're using its
+ * existing virtual mapping in an atomic context.  With a VIVT cache this
+ * is essential to do, but with a VIPT cache this is only an optimization
+ * so not to pay the price of establishing a second mapping if an existing
+ * one can be used.  However, on platforms without hardware TLB maintenance
+ * broadcast, we simply cannot use ARCH_NEEDS_KMAP_HIGH_GET at all since
+ * the locking involved must also disable IRQs which is incompatible with
+ * the IPI mechanism used by global TLB operations.
+ */
 #define ARCH_NEEDS_KMAP_HIGH_GET
+#if defined(CONFIG_SMP) && defined(CONFIG_CPU_TLB_V6)
+#undef ARCH_NEEDS_KMAP_HIGH_GET
+#if defined(CONFIG_HIGHMEM) && defined(CONFIG_CPU_CACHE_VIVT)
+#error "The sum of features in your kernel config cannot be supported together"
+#endif
+#endif
 
-extern void *kmap_high(struct page *page);
+#ifdef ARCH_NEEDS_KMAP_HIGH_GET
 extern void *kmap_high_get(struct page *page);
-extern void kunmap_high(struct page *page);
+#else
+static inline void *kmap_high_get(struct page *page)
+{
+	return NULL;
+}
+#endif
 
 /*
  * The following functions are already defined by <linux/highmem.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/hw_irq.h linux-libre-2.6.39-gnu/arch/arm/include/asm/hw_irq.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/hw_irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/hw_irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,14 +10,6 @@
 	irq_err_count++;
 }
 
-/*
- * Obsolete inline function for calling irq descriptor handlers.
- */
-static inline void desc_handle_irq(unsigned int irq, struct irq_desc *desc)
-{
-	desc->handle_irq(irq, desc);
-}
-
 void set_irq_flags(unsigned int irq, unsigned int flags);
 
 #define IRQF_VALID	(1 << 0)
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/kexec.h linux-libre-2.6.39-gnu/arch/arm/include/asm/kexec.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/kexec.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/kexec.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,6 +50,9 @@
 	}
 }
 
+/* Function pointer to optional machine-specific reinitialization */
+extern void (*kexec_reinit)(void);
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* CONFIG_KEXEC */
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/kprobes.h linux-libre-2.6.39-gnu/arch/arm/include/asm/kprobes.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/kprobes.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/kprobes.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,10 +39,13 @@
 struct kprobe;
 typedef void (kprobe_insn_handler_t)(struct kprobe *, struct pt_regs *);
 
+typedef unsigned long (kprobe_check_cc)(unsigned long);
+
 /* Architecture specific copy of original instruction. */
 struct arch_specific_insn {
 	kprobe_opcode_t		*insn;
 	kprobe_insn_handler_t	*insn_handler;
+	kprobe_check_cc		*insn_check_cc;
 };
 
 struct prev_kprobe {
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/localtimer.h linux-libre-2.6.39-gnu/arch/arm/include/asm/localtimer.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/localtimer.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/localtimer.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,8 +44,14 @@
 /*
  * Setup a local timer interrupt for a CPU.
  */
-void local_timer_setup(struct clock_event_device *);
+int local_timer_setup(struct clock_event_device *);
+
+#else
 
+static inline int local_timer_setup(struct clock_event_device *evt)
+{
+	return -ENXIO;
+}
 #endif
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/mach/irq.h linux-libre-2.6.39-gnu/arch/arm/include/asm/mach/irq.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/mach/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/mach/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,4 +34,35 @@
 	raw_spin_unlock(&desc->lock);			\
 } while(0)
 
+#ifndef __ASSEMBLY__
+/*
+ * Entry/exit functions for chained handlers where the primary IRQ chip
+ * may implement either fasteoi or level-trigger flow control.
+ */
+static inline void chained_irq_enter(struct irq_chip *chip,
+				     struct irq_desc *desc)
+{
+	/* FastEOI controllers require no action on entry. */
+	if (chip->irq_eoi)
+		return;
+
+	if (chip->irq_mask_ack) {
+		chip->irq_mask_ack(&desc->irq_data);
+	} else {
+		chip->irq_mask(&desc->irq_data);
+		if (chip->irq_ack)
+			chip->irq_ack(&desc->irq_data);
+	}
+}
+
+static inline void chained_irq_exit(struct irq_chip *chip,
+				    struct irq_desc *desc)
+{
+	if (chip->irq_eoi)
+		chip->irq_eoi(&desc->irq_data);
+	else
+		chip->irq_unmask(&desc->irq_data);
+}
+#endif
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/mach/udc_pxa2xx.h linux-libre-2.6.39-gnu/arch/arm/include/asm/mach/udc_pxa2xx.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/mach/udc_pxa2xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/mach/udc_pxa2xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,8 +20,6 @@
 	 * VBUS IRQ and omit the methods above.  Store the GPIO number
 	 * here.  Note that sometimes the signals go through inverters...
 	 */
-	bool	gpio_vbus_inverted;
-	int	gpio_vbus;			/* high == vbus present */
 	bool	gpio_pullup_inverted;
 	int	gpio_pullup;			/* high == pullup activated */
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/memory.h linux-libre-2.6.39-gnu/arch/arm/include/asm/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <linux/compiler.h>
 #include <linux/const.h>
+#include <linux/types.h>
 #include <mach/memory.h>
 #include <asm/sizes.h>
 
@@ -133,20 +134,10 @@
 #endif
 
 /*
- * Physical vs virtual RAM address space conversion.  These are
- * private definitions which should NOT be used outside memory.h
- * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
- */
-#ifndef __virt_to_phys
-#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
-#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
-#endif
-
-/*
  * Convert a physical address to a Page Frame Number and back
  */
-#define	__phys_to_pfn(paddr)	((paddr) >> PAGE_SHIFT)
-#define	__pfn_to_phys(pfn)	((pfn) << PAGE_SHIFT)
+#define	__phys_to_pfn(paddr)	((unsigned long)((paddr) >> PAGE_SHIFT))
+#define	__pfn_to_phys(pfn)	((phys_addr_t)(pfn) << PAGE_SHIFT)
 
 /*
  * Convert a page to/from a physical address
@@ -157,6 +148,62 @@
 #ifndef __ASSEMBLY__
 
 /*
+ * Physical vs virtual RAM address space conversion.  These are
+ * private definitions which should NOT be used outside memory.h
+ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#ifndef __virt_to_phys
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+
+/*
+ * Constants used to force the right instruction encodings and shifts
+ * so that all we need to do is modify the 8-bit constant field.
+ */
+#define __PV_BITS_31_24	0x81000000
+#define __PV_BITS_23_16	0x00810000
+
+extern unsigned long __pv_phys_offset;
+#define PHYS_OFFSET __pv_phys_offset
+
+#define __pv_stub(from,to,instr,type)			\
+	__asm__("@ __pv_stub\n"				\
+	"1:	" instr "	%0, %1, %2\n"		\
+	"	.pushsection .pv_table,\"a\"\n"		\
+	"	.long	1b\n"				\
+	"	.popsection\n"				\
+	: "=r" (to)					\
+	: "r" (from), "I" (type))
+
+static inline unsigned long __virt_to_phys(unsigned long x)
+{
+	unsigned long t;
+	__pv_stub(x, t, "add", __PV_BITS_31_24);
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	__pv_stub(t, t, "add", __PV_BITS_23_16);
+#endif
+	return t;
+}
+
+static inline unsigned long __phys_to_virt(unsigned long x)
+{
+	unsigned long t;
+	__pv_stub(x, t, "sub", __PV_BITS_31_24);
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	__pv_stub(t, t, "sub", __PV_BITS_23_16);
+#endif
+	return t;
+}
+#else
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+#endif
+#endif
+
+#ifndef PHYS_OFFSET
+#define PHYS_OFFSET	PLAT_PHYS_OFFSET
+#endif
+
+/*
  * The DMA mask corresponding to the maximum bus address allocatable
  * using GFP_DMA.  The default here places no restriction on DMA
  * allocations.  This must be the smallest DMA mask in the system,
@@ -188,12 +235,12 @@
  * translation for translating DMA addresses.  Use the driver
  * DMA support - see dma-mapping.h.
  */
-static inline unsigned long virt_to_phys(const volatile void *x)
+static inline phys_addr_t virt_to_phys(const volatile void *x)
 {
 	return __virt_to_phys((unsigned long)(x));
 }
 
-static inline void *phys_to_virt(unsigned long x)
+static inline void *phys_to_virt(phys_addr_t x)
 {
 	return (void *)(__phys_to_virt((unsigned long)(x)));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/module.h linux-libre-2.6.39-gnu/arch/arm/include/asm/module.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/module.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/module.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,8 +25,31 @@
 };
 
 /*
- * Include the ARM architecture version.
+ * Add the ARM architecture version to the version magic string
  */
-#define MODULE_ARCH_VERMAGIC	"ARMv" __stringify(__LINUX_ARM_ARCH__) " "
+#define MODULE_ARCH_VERMAGIC_ARMVSN "ARMv" __stringify(__LINUX_ARM_ARCH__) " "
+
+/* Add __virt_to_phys patching state as well */
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+#define MODULE_ARCH_VERMAGIC_P2V "p2v16 "
+#else
+#define MODULE_ARCH_VERMAGIC_P2V "p2v8 "
+#endif
+#else
+#define MODULE_ARCH_VERMAGIC_P2V ""
+#endif
+
+/* Add instruction set architecture tag to distinguish ARM/Thumb kernels */
+#ifdef CONFIG_THUMB2_KERNEL
+#define MODULE_ARCH_VERMAGIC_ARMTHUMB "thumb2 "
+#else
+#define MODULE_ARCH_VERMAGIC_ARMTHUMB ""
+#endif
+
+#define MODULE_ARCH_VERMAGIC \
+	MODULE_ARCH_VERMAGIC_ARMVSN \
+	MODULE_ARCH_VERMAGIC_ARMTHUMB \
+	MODULE_ARCH_VERMAGIC_P2V
 
 #endif /* _ASM_ARM_MODULE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/outercache.h linux-libre-2.6.39-gnu/arch/arm/include/asm/outercache.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/outercache.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/outercache.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,8 @@
 #ifndef __ASM_OUTERCACHE_H
 #define __ASM_OUTERCACHE_H
 
+#include <linux/types.h>
+
 struct outer_cache_fns {
 	void (*inv_range)(unsigned long, unsigned long);
 	void (*clean_range)(unsigned long, unsigned long);
@@ -31,23 +33,24 @@
 #ifdef CONFIG_OUTER_CACHE_SYNC
 	void (*sync)(void);
 #endif
+	void (*set_debug)(unsigned long);
 };
 
 #ifdef CONFIG_OUTER_CACHE
 
 extern struct outer_cache_fns outer_cache;
 
-static inline void outer_inv_range(unsigned long start, unsigned long end)
+static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
 {
 	if (outer_cache.inv_range)
 		outer_cache.inv_range(start, end);
 }
-static inline void outer_clean_range(unsigned long start, unsigned long end)
+static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)
 {
 	if (outer_cache.clean_range)
 		outer_cache.clean_range(start, end);
 }
-static inline void outer_flush_range(unsigned long start, unsigned long end)
+static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
 {
 	if (outer_cache.flush_range)
 		outer_cache.flush_range(start, end);
@@ -73,11 +76,11 @@
 
 #else
 
-static inline void outer_inv_range(unsigned long start, unsigned long end)
+static inline void outer_inv_range(phys_addr_t start, phys_addr_t end)
 { }
-static inline void outer_clean_range(unsigned long start, unsigned long end)
+static inline void outer_clean_range(phys_addr_t start, phys_addr_t end)
 { }
-static inline void outer_flush_range(unsigned long start, unsigned long end)
+static inline void outer_flush_range(phys_addr_t start, phys_addr_t end)
 { }
 static inline void outer_flush_all(void) { }
 static inline void outer_inv_all(void) { }
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/arm/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -301,6 +301,7 @@
 #define pgd_present(pgd)	(1)
 #define pgd_clear(pgdp)		do { } while (0)
 #define set_pgd(pgd,pgdp)	do { } while (0)
+#define set_pud(pud,pudp)	do { } while (0)
 
 
 /* Find an entry in the second-level page table.. */
@@ -351,7 +352,7 @@
 #define pte_unmap(pte)			__pte_unmap(pte)
 
 #define pte_pfn(pte)		(pte_val(pte) >> PAGE_SHIFT)
-#define pfn_pte(pfn,prot)	__pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pte(pfn,prot)	__pte(__pfn_to_phys(pfn) | pgprot_val(prot))
 
 #define pte_page(pte)		pfn_to_page(pte_pfn(pte))
 #define mk_pte(page,prot)	pfn_pte(page_to_pfn(page), prot)
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/pmu.h linux-libre-2.6.39-gnu/arch/arm/include/asm/pmu.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/pmu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/pmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,11 +12,25 @@
 #ifndef __ARM_PMU_H__
 #define __ARM_PMU_H__
 
+#include <linux/interrupt.h>
+
 enum arm_pmu_type {
 	ARM_PMU_DEVICE_CPU	= 0,
 	ARM_NUM_PMU_DEVICES,
 };
 
+/*
+ * struct arm_pmu_platdata - ARM PMU platform data
+ *
+ * @handle_irq: an optional handler which will be called from the interrupt and
+ * passed the address of the low level handler, and can be used to implement
+ * any platform specific handling before or after calling it.
+ */
+struct arm_pmu_platdata {
+	irqreturn_t (*handle_irq)(int irq, void *dev,
+				  irq_handler_t pmu_handler);
+};
+
 #ifdef CONFIG_CPU_HAS_PMU
 
 /**
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/processor.h linux-libre-2.6.39-gnu/arch/arm/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,19 +29,7 @@
 #define STACK_TOP_MAX	TASK_SIZE
 #endif
 
-union debug_insn {
-	u32	arm;
-	u16	thumb;
-};
-
-struct debug_entry {
-	u32			address;
-	union debug_insn	insn;
-};
-
 struct debug_info {
-	int			nsaved;
-	struct debug_entry	bp[2];
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 	struct perf_event	*hbp[ARM_MAX_HBP_SLOTS];
 #endif
@@ -95,7 +83,7 @@
 
 unsigned long get_wchan(struct task_struct *p);
 
-#if __LINUX_ARM_ARCH__ == 6
+#if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327)
 #define cpu_relax()			smp_mb()
 #else
 #define cpu_relax()			barrier()
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/proc-fns.h linux-libre-2.6.39-gnu/arch/arm/include/asm/proc-fns.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/proc-fns.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/proc-fns.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,250 +13,86 @@
 
 #ifdef __KERNEL__
 
+#include <asm/glue-proc.h>
+#include <asm/page.h>
 
-/*
- * Work out if we need multiple CPU support
- */
-#undef MULTI_CPU
-#undef CPU_NAME
+#ifndef __ASSEMBLY__
+
+struct mm_struct;
 
 /*
- * CPU_NAME - the prefix for CPU related functions
+ * Don't change this structure - ASM code relies on it.
  */
+extern struct processor {
+	/* MISC
+	 * get data abort address/flags
+	 */
+	void (*_data_abort)(unsigned long pc);
+	/*
+	 * Retrieve prefetch fault address
+	 */
+	unsigned long (*_prefetch_abort)(unsigned long lr);
+	/*
+	 * Set up any processor specifics
+	 */
+	void (*_proc_init)(void);
+	/*
+	 * Disable any processor specifics
+	 */
+	void (*_proc_fin)(void);
+	/*
+	 * Special stuff for a reset
+	 */
+	void (*reset)(unsigned long addr) __attribute__((noreturn));
+	/*
+	 * Idle the processor
+	 */
+	int (*_do_idle)(void);
+	/*
+	 * Processor architecture specific
+	 */
+	/*
+	 * clean a virtual address range from the
+	 * D-cache without flushing the cache.
+	 */
+	void (*dcache_clean_area)(void *addr, int size);
 
-#ifdef CONFIG_CPU_ARM610
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm6
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM7TDMI
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm7tdmi
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM710
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm7
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM720T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm720
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM740T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm740
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM9TDMI
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm9tdmi
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM920T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm920
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM922T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm922
-# endif
-#endif
-
-#ifdef CONFIG_CPU_FA526
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_fa526
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM925T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm925
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM926T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm926
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM940T
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm940
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM946E
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm946
-# endif
-#endif
-
-#ifdef CONFIG_CPU_SA110
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_sa110
-# endif
-#endif
-
-#ifdef CONFIG_CPU_SA1100
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_sa1100
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1020
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1020
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1020E
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1020e
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1022
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1022
-# endif
-#endif
-
-#ifdef CONFIG_CPU_ARM1026
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_arm1026
-# endif
-#endif
-
-#ifdef CONFIG_CPU_XSCALE
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_xscale
-# endif
-#endif
-
-#ifdef CONFIG_CPU_XSC3
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_xsc3
-# endif
-#endif
-
-#ifdef CONFIG_CPU_MOHAWK
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_mohawk
-# endif
-#endif
-
-#ifdef CONFIG_CPU_FEROCEON
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_feroceon
-# endif
-#endif
-
-#ifdef CONFIG_CPU_V6
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v6
-# endif
-#endif
-
-#ifdef CONFIG_CPU_V7
-# ifdef CPU_NAME
-#  undef  MULTI_CPU
-#  define MULTI_CPU
-# else
-#  define CPU_NAME cpu_v7
-# endif
-#endif
+	/*
+	 * Set the page table
+	 */
+	void (*switch_mm)(unsigned long pgd_phys, struct mm_struct *mm);
+	/*
+	 * Set a possibly extended PTE.  Non-extended PTEs should
+	 * ignore 'ext'.
+	 */
+	void (*set_pte_ext)(pte_t *ptep, pte_t pte, unsigned int ext);
 
-#ifndef __ASSEMBLY__
+	/* Suspend/resume */
+	unsigned int suspend_size;
+	void (*do_suspend)(void *);
+	void (*do_resume)(void *);
+} processor;
 
 #ifndef MULTI_CPU
-#include <asm/cpu-single.h>
+extern void cpu_proc_init(void);
+extern void cpu_proc_fin(void);
+extern int cpu_do_idle(void);
+extern void cpu_dcache_clean_area(void *, int);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_set_pte_ext(pte_t *ptep, pte_t pte, unsigned int ext);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
 #else
-#include <asm/cpu-multi32.h>
+#define cpu_proc_init()			processor._proc_init()
+#define cpu_proc_fin()			processor._proc_fin()
+#define cpu_reset(addr)			processor.reset(addr)
+#define cpu_do_idle()			processor._do_idle()
+#define cpu_dcache_clean_area(addr,sz)	processor.dcache_clean_area(addr,sz)
+#define cpu_set_pte_ext(ptep,pte,ext)	processor.set_pte_ext(ptep,pte,ext)
+#define cpu_do_switch_mm(pgd,mm)	processor.switch_mm(pgd,mm)
 #endif
 
+extern void cpu_resume(void);
+
 #include <asm/memory.h>
 
 #ifdef CONFIG_MMU
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/arm/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -130,8 +130,6 @@
 
 #ifdef __KERNEL__
 
-#define arch_has_single_step()	(1)
-
 #define user_mode(regs)	\
 	(((regs)->ARM_cpsr & 0xf) == 0)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/setup.h linux-libre-2.6.39-gnu/arch/arm/include/asm/setup.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/setup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/setup.h	2011-05-19 00:06:34.000000000 -0400
@@ -192,14 +192,10 @@
 /*
  * Memory map description
  */
-#ifdef CONFIG_ARCH_LH7A40X
-# define NR_BANKS 16
-#else
-# define NR_BANKS 8
-#endif
+#define NR_BANKS 8
 
 struct membank {
-	unsigned long start;
+	phys_addr_t start;
 	unsigned long size;
 	unsigned int highmem;
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/smp_scu.h linux-libre-2.6.39-gnu/arch/arm/include/asm/smp_scu.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/smp_scu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/smp_scu.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,14 @@
 #ifndef __ASMARM_ARCH_SCU_H
 #define __ASMARM_ARCH_SCU_H
 
+#define SCU_PM_NORMAL	0
+#define SCU_PM_DORMANT	2
+#define SCU_PM_POWEROFF	3
+
+#ifndef __ASSEMBLER__
 unsigned int scu_get_core_count(void __iomem *);
 void scu_enable(void __iomem *);
+int scu_power_mode(void __iomem *, unsigned int);
+#endif
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/spinlock.h linux-libre-2.6.39-gnu/arch/arm/include/asm/spinlock.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/spinlock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/spinlock.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,17 +5,52 @@
 #error SMP not supported on pre-ARMv6 CPUs
 #endif
 
+/*
+ * sev and wfe are ARMv6K extensions.  Uniprocessor ARMv6 may not have the K
+ * extensions, so when running on UP, we have to patch these instructions away.
+ */
+#define ALT_SMP(smp, up)					\
+	"9998:	" smp "\n"					\
+	"	.pushsection \".alt.smp.init\", \"a\"\n"	\
+	"	.long	9998b\n"				\
+	"	" up "\n"					\
+	"	.popsection\n"
+
+#ifdef CONFIG_THUMB2_KERNEL
+#define SEV		ALT_SMP("sev.w", "nop.w")
+/*
+ * For Thumb-2, special care is needed to ensure that the conditional WFE
+ * instruction really does assemble to exactly 4 bytes (as required by
+ * the SMP_ON_UP fixup code).   By itself "wfene" might cause the
+ * assembler to insert a extra (16-bit) IT instruction, depending on the
+ * presence or absence of neighbouring conditional instructions.
+ *
+ * To avoid this unpredictableness, an approprite IT is inserted explicitly:
+ * the assembler won't change IT instructions which are explicitly present
+ * in the input.
+ */
+#define WFE(cond)	ALT_SMP(		\
+	"it " cond "\n\t"			\
+	"wfe" cond ".n",			\
+						\
+	"nop.w"					\
+)
+#else
+#define SEV		ALT_SMP("sev", "nop")
+#define WFE(cond)	ALT_SMP("wfe" cond, "nop")
+#endif
+
 static inline void dsb_sev(void)
 {
 #if __LINUX_ARM_ARCH__ >= 7
 	__asm__ __volatile__ (
 		"dsb\n"
-		"sev"
+		SEV
 	);
-#elif defined(CONFIG_CPU_32v6K)
+#else
 	__asm__ __volatile__ (
 		"mcr p15, 0, %0, c7, c10, 4\n"
-		"sev"
+		SEV
 		: : "r" (0)
 	);
 #endif
@@ -46,9 +81,7 @@
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
-#ifdef CONFIG_CPU_32v6K
-"	wfene\n"
-#endif
+	WFE("ne")
 "	strexeq	%0, %2, [%1]\n"
 "	teqeq	%0, #0\n"
 "	bne	1b"
@@ -107,9 +140,7 @@
 	__asm__ __volatile__(
 "1:	ldrex	%0, [%1]\n"
 "	teq	%0, #0\n"
-#ifdef CONFIG_CPU_32v6K
-"	wfene\n"
-#endif
+	WFE("ne")
 "	strexeq	%0, %2, [%1]\n"
 "	teq	%0, #0\n"
 "	bne	1b"
@@ -176,9 +207,7 @@
 "1:	ldrex	%0, [%2]\n"
 "	adds	%0, %0, #1\n"
 "	strexpl	%1, %0, [%2]\n"
-#ifdef CONFIG_CPU_32v6K
-"	wfemi\n"
-#endif
+	WFE("mi")
 "	rsbpls	%0, %1, #0\n"
 "	bmi	1b"
 	: "=&r" (tmp), "=&r" (tmp2)
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/system.h linux-libre-2.6.39-gnu/arch/arm/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -159,7 +159,7 @@
 #include <mach/barriers.h>
 #elif defined(CONFIG_ARM_DMA_MEM_BUFFERABLE) || defined(CONFIG_SMP)
 #define mb()		do { dsb(); outer_sync(); } while (0)
-#define rmb()		dmb()
+#define rmb()		dsb()
 #define wmb()		mb()
 #else
 #include <asm/memory.h>
@@ -249,7 +249,7 @@
  * cache totally.  This means that the cache becomes inconsistent, and,
  * since we use normal loads/stores as well, this is really bad.
  * Typically, this causes oopsen in filp_close, but could have other,
- * more disasterous effects.  There are two work-arounds:
+ * more disastrous effects.  There are two work-arounds:
  *  1. Disable interrupts and emulate the atomic swap
  *  2. Clean the cache, perform atomic swap, flush the cache
  *
@@ -347,6 +347,7 @@
 #include <asm-generic/cmpxchg-local.h>
 
 #if __LINUX_ARM_ARCH__ < 6
+/* min ARCH < ARMv6 */
 
 #ifdef CONFIG_SMP
 #error "SMP is not supported on this platform"
@@ -365,7 +366,7 @@
 #include <asm-generic/cmpxchg.h>
 #endif
 
-#else	/* __LINUX_ARM_ARCH__ >= 6 */
+#else	/* min ARCH >= ARMv6 */
 
 extern void __bad_cmpxchg(volatile void *ptr, int size);
 
@@ -379,7 +380,7 @@
 	unsigned long oldval, res;
 
 	switch (size) {
-#ifdef CONFIG_CPU_32v6K
+#ifndef CONFIG_CPU_V6	/* min ARCH >= ARMv6K */
 	case 1:
 		do {
 			asm volatile("@ __cmpxchg1\n"
@@ -404,7 +405,7 @@
 				: "memory", "cc");
 		} while (res);
 		break;
-#endif /* CONFIG_CPU_32v6K */
+#endif
 	case 4:
 		do {
 			asm volatile("@ __cmpxchg4\n"
@@ -450,12 +451,12 @@
 	unsigned long ret;
 
 	switch (size) {
-#ifndef CONFIG_CPU_32v6K
+#ifdef CONFIG_CPU_V6	/* min ARCH == ARMv6 */
 	case 1:
 	case 2:
 		ret = __cmpxchg_local_generic(ptr, old, new, size);
 		break;
-#endif	/* !CONFIG_CPU_32v6K */
+#endif
 	default:
 		ret = __cmpxchg(ptr, old, new, size);
 	}
@@ -469,7 +470,7 @@
 				       (unsigned long)(n),		\
 				       sizeof(*(ptr))))
 
-#ifdef CONFIG_CPU_32v6K
+#ifndef CONFIG_CPU_V6	/* min ARCH >= ARMv6K */
 
 /*
  * Note : ARMv7-M (currently unsupported by Linux) does not support
@@ -524,11 +525,11 @@
 					 (unsigned long long)(o),	\
 					 (unsigned long long)(n)))
 
-#else	/* !CONFIG_CPU_32v6K */
+#else /* min ARCH = ARMv6 */
 
 #define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
 
-#endif	/* CONFIG_CPU_32v6K */
+#endif
 
 #endif	/* __LINUX_ARM_ARCH__ >= 6 */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/thread_notify.h linux-libre-2.6.39-gnu/arch/arm/include/asm/thread_notify.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/thread_notify.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/thread_notify.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,7 @@
 #define THREAD_NOTIFY_FLUSH	0
 #define THREAD_NOTIFY_EXIT	1
 #define THREAD_NOTIFY_SWITCH	2
+#define THREAD_NOTIFY_COPY	3
 
 #endif
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/tls.h linux-libre-2.6.39-gnu/arch/arm/include/asm/tls.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/tls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/tls.h	2011-05-19 00:06:34.000000000 -0400
@@ -28,15 +28,14 @@
 #define tls_emu		1
 #define has_tls_reg		1
 #define set_tls		set_tls_none
-#elif __LINUX_ARM_ARCH__ >= 7 ||					\
-	(__LINUX_ARM_ARCH__ == 6 && defined(CONFIG_CPU_32v6K))
-#define tls_emu		0
-#define has_tls_reg		1
-#define set_tls		set_tls_v6k
-#elif __LINUX_ARM_ARCH__ == 6
+#elif defined(CONFIG_CPU_V6)
 #define tls_emu		0
 #define has_tls_reg		(elf_hwcap & HWCAP_TLS)
 #define set_tls		set_tls_v6
+#elif defined(CONFIG_CPU_32v6K)
+#define tls_emu		0
+#define has_tls_reg		1
+#define set_tls		set_tls_v6k
 #else
 #define tls_emu		0
 #define has_tls_reg		0
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/traps.h linux-libre-2.6.39-gnu/arch/arm/include/asm/traps.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/traps.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/traps.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 
 extern void __init early_trap_init(void);
 extern void dump_backtrace_entry(unsigned long where, unsigned long from, unsigned long frame);
+extern void ptrace_break(struct task_struct *tsk, struct pt_regs *regs);
 
 extern void *vectors_page;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/types.h linux-libre-2.6.39-gnu/arch/arm/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,15 +16,6 @@
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-typedef u32 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/ucontext.h linux-libre-2.6.39-gnu/arch/arm/include/asm/ucontext.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/ucontext.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/ucontext.h	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,7 @@
 #endif
 
 #ifdef CONFIG_IWMMXT
-/* iwmmxt_area is 0x98 bytes long, preceeded by 8 bytes of signature */
+/* iwmmxt_area is 0x98 bytes long, preceded by 8 bytes of signature */
 #define IWMMXT_MAGIC		0x12ef842a
 #define IWMMXT_STORAGE_SIZE	(IWMMXT_SIZE + 8)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/arm/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -396,6 +396,10 @@
 #define __NR_fanotify_init		(__NR_SYSCALL_BASE+367)
 #define __NR_fanotify_mark		(__NR_SYSCALL_BASE+368)
 #define __NR_prlimit64			(__NR_SYSCALL_BASE+369)
+#define __NR_name_to_handle_at		(__NR_SYSCALL_BASE+370)
+#define __NR_open_by_handle_at		(__NR_SYSCALL_BASE+371)
+#define __NR_clock_adjtime		(__NR_SYSCALL_BASE+372)
+#define __NR_syncfs			(__NR_SYSCALL_BASE+373)
 
 /*
  * The following SWIs are ARM private.
diff -druN linux-libre-2.6.38-gnu/arch/arm/include/asm/user.h linux-libre-2.6.39-gnu/arch/arm/include/asm/user.h
--- linux-libre-2.6.38-gnu/arch/arm/include/asm/user.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/include/asm/user.h	2011-05-19 00:06:34.000000000 -0400
@@ -71,7 +71,7 @@
 				/* the registers. */
   unsigned long magic;		/* To uniquely identify a core file */
   char u_comm[32];		/* User command that was responsible */
-  int u_debugreg[8];
+  int u_debugreg[8];		/* No longer used */
   struct user_fp u_fp;		/* FP state */
   struct user_fp_struct * u_fp0;/* Used by gdb to help find the values for */
   				/* the FP registers. */
diff -druN linux-libre-2.6.38-gnu/arch/arm/Kconfig linux-libre-2.6.39-gnu/arch/arm/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 	select HAVE_MEMBLOCK
 	select RTC_LIB
 	select SYS_SUPPORTS_APM_EMULATION
-	select GENERIC_ATOMIC64 if (!CPU_32v6K || !AEABI)
+	select GENERIC_ATOMIC64 if (CPU_V6 || !CPU_32v6K || !AEABI)
 	select HAVE_OPROFILE if (HAVE_PERF_EVENTS)
 	select HAVE_ARCH_KGDB
 	select HAVE_KPROBES if (!XIP_KERNEL && !THUMB2_KERNEL)
@@ -24,10 +24,11 @@
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_REGS_AND_STACK_ACCESS_API
-	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V7))
+	select HAVE_HW_BREAKPOINT if (PERF_EVENTS && (CPU_V6 || CPU_V6K || CPU_V7))
 	select HAVE_C_RECORDMCOUNT
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
+	select GENERIC_IRQ_SHOW
 	help
 	  The ARM series is a line of low-power-consumption RISC chip designs
 	  licensed by ARM Ltd and targeted at embedded applications and
@@ -63,6 +64,10 @@
 	depends on GENERIC_CLOCKEVENTS
 	default y if SMP
 
+config KTIME_SCALAR
+	bool
+	default y
+
 config HAVE_TCM
 	bool
 	select GENERIC_ALLOCATOR
@@ -178,11 +183,6 @@
 config ARCH_MTD_XIP
 	bool
 
-config ARM_L1_CACHE_SHIFT_6
-	bool
-	help
-	  Setting ARM L1 cache line size to 64 Bytes.
-
 config VECTORS_BASE
 	hex
 	default 0xffff0000 if MMU || CPU_HIGH_VECTOR
@@ -191,6 +191,22 @@
 	help
 	  The base address of exception vectors.
 
+config ARM_PATCH_PHYS_VIRT
+	bool "Patch physical to virtual translations at runtime (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	depends on !XIP_KERNEL && MMU
+	depends on !ARCH_REALVIEW || !SPARSEMEM
+	help
+	  Patch phys-to-virt translation functions at runtime according to
+	  the position of the kernel in system memory.
+
+	  This can only be used with non-XIP with MMU kernels where
+	  the base of physical memory is at a 16MB boundary.
+
+config ARM_PATCH_PHYS_VIRT_16BIT
+	def_bool y
+	depends on ARM_PATCH_PHYS_VIRT && ARCH_MSM
+
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
@@ -212,15 +228,6 @@
 	prompt "ARM system type"
 	default ARCH_VERSATILE
 
-config ARCH_AAEC2000
-	bool "Agilent AAEC-2000 based"
-	select CPU_ARM920T
-	select ARM_AMBA
-	select HAVE_CLK
-	select ARCH_USES_GETTIMEOFFSET
-	help
-	  This enables support for systems based on the Agilent AAEC-2000
-
 config ARCH_INTEGRATOR
 	bool "ARM Ltd. Integrator family"
 	select ARM_AMBA
@@ -229,6 +236,7 @@
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select PLAT_VERSATILE
+	select PLAT_VERSATILE_FPGA_IRQ
 	help
 	  Support for ARM's Integrator platform.
 
@@ -236,11 +244,11 @@
 	bool "ARM Ltd. RealView family"
 	select ARM_AMBA
 	select CLKDEV_LOOKUP
-	select HAVE_SCHED_CLOCK
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select PLAT_VERSATILE
+	select PLAT_VERSATILE_CLCD
 	select ARM_TIMER_SP804
 	select GPIO_PL061 if GPIOLIB
 	help
@@ -251,11 +259,12 @@
 	select ARM_AMBA
 	select ARM_VIC
 	select CLKDEV_LOOKUP
-	select HAVE_SCHED_CLOCK
 	select ICST
 	select GENERIC_CLOCKEVENTS
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select PLAT_VERSATILE
+	select PLAT_VERSATILE_CLCD
+	select PLAT_VERSATILE_FPGA_IRQ
 	select ARM_TIMER_SP804
 	help
 	  This enables support for ARM Ltd Versatile board.
@@ -268,9 +277,10 @@
 	select CLKDEV_LOOKUP
 	select GENERIC_CLOCKEVENTS
 	select HAVE_CLK
-	select HAVE_SCHED_CLOCK
+	select HAVE_PATA_PLATFORM
 	select ICST
 	select PLAT_VERSATILE
+	select PLAT_VERSATILE_CLCD
 	help
 	  This enables support for the ARM Ltd Versatile Express boards.
 
@@ -346,7 +356,7 @@
 	bool "FootBridge"
 	select CPU_SA110
 	select FOOTBRIDGE
-	select ARCH_USES_GETTIMEOFFSET
+	select GENERIC_CLOCKEVENTS
 	help
 	  Support for systems based on the DC21285 companion chip
 	  ("FootBridge"), such as the Simtec CATS and the Rebel NetWinder.
@@ -356,6 +366,7 @@
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
+	select HAVE_SCHED_CLOCK
 	help
 	  Support for Freescale MXC/iMX-based family of processors
 
@@ -457,6 +468,7 @@
 
 config ARCH_DOVE
 	bool "Marvell Dove"
+	select CPU_V6K
 	select PCI
 	select ARCH_REQUIRE_GPIOLIB
 	select GENERIC_CLOCKEVENTS
@@ -619,6 +631,7 @@
 	select HAVE_CLK
 	select GENERIC_CLOCKEVENTS
 	select ARCH_REQUIRE_GPIOLIB
+	select CLKDEV_LOOKUP
 	help
 	  Support for Qualcomm MSM/QSD based systems.  This runs on the
 	  apps processor of the MSM/QSD and depends on a shared memory
@@ -681,7 +694,7 @@
 	  the Samsung SMDK2410 development board (and derivatives).
 
 	  Note, the S3C2416 and the S3C2450 are so close that they even share
-	  the same SoC ID code. This means that there is no seperate machine
+	  the same SoC ID code. This means that there is no separate machine
 	  directory (no arch/arm/mach-s3c2450) as the S3C2416 was first.
 
 config ARCH_S3C64XX
@@ -715,7 +728,8 @@
 	select GENERIC_GPIO
 	select HAVE_CLK
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
-	select ARCH_USES_GETTIMEOFFSET
+	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	help
@@ -753,15 +767,16 @@
 	select HAVE_CLK
 	select ARM_L1_CACHE_SHIFT_6
 	select ARCH_HAS_CPUFREQ
-	select ARCH_USES_GETTIMEOFFSET
+	select GENERIC_CLOCKEVENTS
+	select HAVE_SCHED_CLOCK
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C_RTC if RTC_CLASS
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
 	  Samsung S5PV210/S5PC110 series based systems
 
-config ARCH_S5PV310
-	bool "Samsung S5PV310/S5PC210"
+config ARCH_EXYNOS4
+	bool "Samsung EXYNOS4"
 	select CPU_V7
 	select ARCH_SPARSEMEM_ENABLE
 	select GENERIC_GPIO
@@ -772,7 +787,7 @@
 	select HAVE_S3C2410_I2C if I2C
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	help
-	  Samsung S5PV310 series based systems
+	  Samsung EXYNOS4 series based systems
 
 config ARCH_SHARK
 	bool "Shark"
@@ -795,17 +810,6 @@
 	help
 	  Support for Telechips TCC ARM926-based systems.
 
-config ARCH_LH7A40X
-	bool "Sharp LH7A40X"
-	select CPU_ARM922T
-	select ARCH_SPARSEMEM_ENABLE if !LH7A40X_CONTIGMEM
-	select ARCH_USES_GETTIMEOFFSET
-	help
-	  Say Y here for systems based on one of the Sharp LH7A40X
-	  System on a Chip processors.  These CPUs include an ARM922T
-	  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
@@ -875,6 +879,16 @@
 	help
 	  Support for ST's SPEAr platform (SPEAr3xx, SPEAr6xx and SPEAr13xx).
 
+config ARCH_VT8500
+	bool "VIA/WonderMedia 85xx"
+	select CPU_ARM926T
+	select GENERIC_GPIO
+	select ARCH_HAS_CPUFREQ
+	select GENERIC_CLOCKEVENTS
+	select ARCH_REQUIRE_GPIOLIB
+	select HAVE_PWM
+	help
+	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
 endchoice
 
 #
@@ -882,8 +896,6 @@
 # Kconfigs may be included either alphabetically (according to the
 # plat- suffix) or along side the corresponding mach-* source.
 #
-source "arch/arm/mach-aaec2000/Kconfig"
-
 source "arch/arm/mach-at91/Kconfig"
 
 source "arch/arm/mach-bcmring/Kconfig"
@@ -922,8 +934,6 @@
 
 source "arch/arm/mach-ks8695/Kconfig"
 
-source "arch/arm/mach-lh7a40x/Kconfig"
-
 source "arch/arm/mach-loki/Kconfig"
 
 source "arch/arm/mach-lpc32xx/Kconfig"
@@ -991,7 +1001,7 @@
 
 source "arch/arm/mach-s5pv210/Kconfig"
 
-source "arch/arm/mach-s5pv310/Kconfig"
+source "arch/arm/mach-exynos4/Kconfig"
 
 source "arch/arm/mach-shmobile/Kconfig"
 
@@ -1006,6 +1016,9 @@
 source "arch/arm/mach-versatile/Kconfig"
 
 source "arch/arm/mach-vexpress/Kconfig"
+source "arch/arm/plat-versatile/Kconfig"
+
+source "arch/arm/mach-vt8500/Kconfig"
 
 source "arch/arm/mach-w90x900/Kconfig"
 
@@ -1048,7 +1061,7 @@
 	default y
 
 config CPU_HAS_PMU
-	depends on (CPU_V6 || CPU_V7 || XSCALE_PMU) && \
+	depends on (CPU_V6 || CPU_V6K || CPU_V7 || XSCALE_PMU) && \
 		   (!ARCH_OMAP3 || OMAP3_EMU)
 	default y
 	bool
@@ -1064,7 +1077,7 @@
 
 config ARM_ERRATA_411920
 	bool "ARM errata: Invalidation of the Instruction Cache operation can fail"
-	depends on CPU_V6
+	depends on CPU_V6 || CPU_V6K
 	help
 	  Invalidation of the Instruction Cache operation can
 	  fail. This erratum is present in 1136 (before r1p4), 1156 and 1176.
@@ -1140,7 +1153,7 @@
 
 config PL310_ERRATA_588369
 	bool "Clean & Invalidate maintenance operations do not invalidate clean lines"
-	depends on CACHE_L2X0 && ARCH_OMAP4
+	depends on CACHE_L2X0
 	help
 	   The PL310 L2 cache controller implements three types of Clean &
 	   Invalidate maintenance operations: by Physical Address
@@ -1149,8 +1162,7 @@
 	   clean operation followed immediately by an invalidate operation,
 	   both performing to the same memory location. This functionality
 	   is not correctly implemented in PL310 as clean lines are not
-	   invalidated as a result of these operations. Note that this errata
-	   uses Texas Instrument's secure monitor api.
+	   invalidated as a result of these operations.
 
 config ARM_ERRATA_720789
 	bool "ARM errata: TLBIASIDIS and TLBIMVAIS operations can broadcast a faulty ASID"
@@ -1164,6 +1176,17 @@
 	  tables. The workaround changes the TLB flushing routines to invalidate
 	  entries regardless of the ASID.
 
+config PL310_ERRATA_727915
+	bool "Background Clean & Invalidate by Way operation can cause data corruption"
+	depends on CACHE_L2X0
+	help
+	  PL310 implements the Clean & Invalidate by Way L2 cache maintenance
+	  operation (offset 0x7FC). This operation runs in background so that
+	  PL310 can handle normal accesses while it is in progress. Under very
+	  rare circumstances, due to this erratum, write data can be lost when
+	  PL310 treats a cacheable write transaction during a Clean &
+	  Invalidate by Way operation.
+
 config ARM_ERRATA_743622
 	bool "ARM errata: Faulty hazard checking in the Store Buffer may lead to data corruption"
 	depends on CPU_V7
@@ -1202,6 +1225,28 @@
 	  This has the same effect as the cache sync operation: store buffer
 	  drain and waiting for all buffers empty.
 
+config ARM_ERRATA_754322
+	bool "ARM errata: possible faulty MMU translations following an ASID switch"
+	depends on CPU_V7
+	help
+	  This option enables the workaround for the 754322 Cortex-A9 (r2p*,
+	  r3p*) erratum. A speculative memory access may cause a page table walk
+	  which starts prior to an ASID switch but completes afterwards. This
+	  can populate the micro-TLB with a stale entry which may be hit with
+	  the new ASID. This workaround places two dsb instructions in the mm
+	  switching code so that no page table walks can cross the ASID switch.
+
+config ARM_ERRATA_754327
+	bool "ARM errata: no automatic Store Buffer drain"
+	depends on CPU_V7 && SMP
+	help
+	  This option enables the workaround for the 754327 Cortex-A9 (prior to
+	  r2p0) erratum. The Store Buffer does not have any automatic draining
+	  mechanism and therefore a livelock may occur if an external agent
+	  continuously polls a memory location waiting to observe an update.
+	  This workaround defines cpu_relax() as smp_mb(), preventing correctly
+	  written polling loops from denying visibility of updates to memory.
+
 endmenu
 
 source "arch/arm/common/Kconfig"
@@ -1275,10 +1320,11 @@
 config SMP
 	bool "Symmetric Multi-Processing (EXPERIMENTAL)"
 	depends on EXPERIMENTAL
+	depends on CPU_V6K || CPU_V7
 	depends on GENERIC_CLOCKEVENTS
 	depends on REALVIEW_EB_ARM11MP || REALVIEW_EB_A9MP || \
 		 MACH_REALVIEW_PB11MP || MACH_REALVIEW_PBX || ARCH_OMAP4 || \
-		 ARCH_S5PV310 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
+		 ARCH_EXYNOS4 || ARCH_TEGRA || ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || \
 		 ARCH_MSM_SCORPIONMP || ARCH_SHMOBILE
 	select USE_GENERIC_SMP_HELPERS
 	select HAVE_ARM_SCU if !ARCH_MSM_SCORPIONMP
@@ -1366,7 +1412,7 @@
 	bool "Use local timer interrupts"
 	depends on SMP
 	default y
-	select HAVE_ARM_TWD if !ARCH_MSM_SCORPIONMP
+	select HAVE_ARM_TWD if (!ARCH_MSM_SCORPIONMP && !EXYNOS4_MCT)
 	help
 	  Enable support for local timers on SMP platforms, rather then the
 	  legacy IPI broadcast method.  Local timers allows the system
@@ -1378,7 +1424,7 @@
 config HZ
 	int
 	default 200 if ARCH_EBSA110 || ARCH_S3C2410 || ARCH_S5P64X0 || \
-		ARCH_S5P6442 || ARCH_S5PV210 || ARCH_S5PV310
+		ARCH_S5P6442 || ARCH_S5PV210 || ARCH_EXYNOS4
 	default OMAP_32K_TIMER_HZ if ARCH_OMAP && OMAP_32K_TIMER
 	default AT91_TIMER_HZ if ARCH_AT91
 	default SHMOBILE_TIMER_HZ if ARCH_SHMOBILE
@@ -1386,7 +1432,7 @@
 
 config THUMB2_KERNEL
 	bool "Compile the kernel in Thumb-2 mode (EXPERIMENTAL)"
-	depends on CPU_V7 && !CPU_V6 && EXPERIMENTAL
+	depends on CPU_V7 && !CPU_V6 && !CPU_V6K && EXPERIMENTAL
 	select AEABI
 	select ARM_ASM_UNIFIED
 	help
@@ -1396,6 +1442,37 @@
 
 	  If unsure, say N.
 
+config THUMB2_AVOID_R_ARM_THM_JUMP11
+	bool "Work around buggy Thumb-2 short branch relocations in gas"
+	depends on THUMB2_KERNEL && MODULES
+	default y
+	help
+	  Various binutils versions can resolve Thumb-2 branches to
+	  locally-defined, preemptible global symbols as short-range "b.n"
+	  branch instructions.
+
+	  This is a problem, because there's no guarantee the final
+	  destination of the symbol, or any candidate locations for a
+	  trampoline, are within range of the branch.  For this reason, the
+	  kernel does not support fixing up the R_ARM_THM_JUMP11 (102)
+	  relocation in modules at all, and it makes little sense to add
+	  support.
+
+	  The symptom is that the kernel fails with an "unsupported
+	  relocation" error when loading some modules.
+
+	  Until fixed tools are available, passing
+	  -fno-optimize-sibling-calls to gcc should prevent gcc generating
+	  code which hits this problem, at the cost of a bit of extra runtime
+	  stack usage in some cases.
+
+	  The problem is described in more detail at:
+	      https://bugs.launchpad.net/binutils-linaro/+bug/725126
+
+	  Only Thumb-2 kernels are affected.
+
+	  Unless you are sure your tools don't have this problem, say Y.
+
 config ARM_ASM_UNIFIED
 	bool
 
@@ -1463,7 +1540,6 @@
 config HIGHPTE
 	bool "Allocate 2nd-level pagetables from highmem"
 	depends on HIGHMEM
-	depends on !OUTER_CACHE
 
 config HW_PERF_EVENTS
 	bool "Enable hardware performance counter support for perf events"
@@ -1644,6 +1720,18 @@
 	  Say Y here if you intend to execute your compressed kernel image
 	  (zImage) directly from ROM or flash.  If unsure, say N.
 
+config ZBOOT_ROM_MMCIF
+	bool "Include MMCIF loader in zImage (EXPERIMENTAL)"
+	depends on ZBOOT_ROM && ARCH_SH7372 && EXPERIMENTAL
+	help
+	  Say Y here to include experimental MMCIF loading code in the
+	  ROM-able zImage. With this enabled it is possible to write the
+	  the ROM-able zImage kernel image to an MMC card and boot the
+	  kernel straight from the reset vector. At reset the processor
+	  Mask ROM will load the first part of the the ROM-able zImage
+	  which in turn loads the rest the kernel image to RAM using the
+	  MMCIF hardware block.
+
 config CMDLINE
 	string "Default kernel command string"
 	default ""
@@ -1877,7 +1965,7 @@
 
 config VFP
 	bool "VFP-format floating point maths"
-	depends on CPU_V6 || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
+	depends on CPU_V6 || CPU_V6K || CPU_ARM926T || CPU_V7 || CPU_FEROCEON
 	help
 	  Say Y to include VFP support code in the kernel. This is needed
 	  if your hardware includes a VFP unit.
@@ -1922,6 +2010,9 @@
 source "kernel/power/Kconfig"
 
 config ARCH_SUSPEND_POSSIBLE
+	depends on !ARCH_S5P64X0 && !ARCH_S5P6442
+	depends on CPU_ARM920T || CPU_ARM926T || CPU_SA1100 || \
+		CPU_V6 || CPU_V6K || CPU_V7 || CPU_XSC3 || CPU_XSCALE
 	def_bool y
 
 endmenu
diff -druN linux-libre-2.6.38-gnu/arch/arm/Kconfig.debug linux-libre-2.6.39-gnu/arch/arm/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/arm/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -63,17 +63,6 @@
 	      8 - SIGSEGV faults
 	     16 - SIGBUS faults
 
-config DEBUG_ERRORS
-	bool "Verbose kernel error messages"
-	depends on DEBUG_KERNEL
-	help
-	  This option controls verbose debugging information which can be
-	  printed when the kernel detects an internal error. This debugging
-	  information is useful to kernel hackers when tracking down problems,
-	  but mostly meaningless to other people. It's safe to say Y unless
-	  you are concerned with the code size or don't want to see these
-	  messages.
-
 config DEBUG_STACK_USAGE
 	bool "Enable stack utilization instrumentation"
 	depends on DEBUG_KERNEL
diff -druN linux-libre-2.6.38-gnu/arch/arm/Kconfig-nommu linux-libre-2.6.39-gnu/arch/arm/Kconfig-nommu
--- linux-libre-2.6.38-gnu/arch/arm/Kconfig-nommu	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/Kconfig-nommu	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 	  used instead of the auto-probing which utilizes the register.
 
 config REMAP_VECTORS_TO_RAM
-	bool 'Install vectors to the begining of RAM' if DRAM_BASE
+	bool 'Install vectors to the beginning of RAM' if DRAM_BASE
 	depends on DRAM_BASE
 	help
 	  The kernel needs to change the hardware exception vectors.
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/armksyms.c linux-libre-2.6.39-gnu/arch/arm/kernel/armksyms.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/armksyms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/armksyms.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,24 +140,18 @@
 #endif
 
 	/* bitops */
-EXPORT_SYMBOL(_set_bit_le);
-EXPORT_SYMBOL(_test_and_set_bit_le);
-EXPORT_SYMBOL(_clear_bit_le);
-EXPORT_SYMBOL(_test_and_clear_bit_le);
-EXPORT_SYMBOL(_change_bit_le);
-EXPORT_SYMBOL(_test_and_change_bit_le);
+EXPORT_SYMBOL(_set_bit);
+EXPORT_SYMBOL(_test_and_set_bit);
+EXPORT_SYMBOL(_clear_bit);
+EXPORT_SYMBOL(_test_and_clear_bit);
+EXPORT_SYMBOL(_change_bit);
+EXPORT_SYMBOL(_test_and_change_bit);
 EXPORT_SYMBOL(_find_first_zero_bit_le);
 EXPORT_SYMBOL(_find_next_zero_bit_le);
 EXPORT_SYMBOL(_find_first_bit_le);
 EXPORT_SYMBOL(_find_next_bit_le);
 
 #ifdef __ARMEB__
-EXPORT_SYMBOL(_set_bit_be);
-EXPORT_SYMBOL(_test_and_set_bit_be);
-EXPORT_SYMBOL(_clear_bit_be);
-EXPORT_SYMBOL(_test_and_clear_bit_be);
-EXPORT_SYMBOL(_change_bit_be);
-EXPORT_SYMBOL(_test_and_change_bit_be);
 EXPORT_SYMBOL(_find_first_zero_bit_be);
 EXPORT_SYMBOL(_find_next_zero_bit_be);
 EXPORT_SYMBOL(_find_first_bit_be);
@@ -170,3 +164,7 @@
 #endif
 EXPORT_SYMBOL(__gnu_mcount_nc);
 #endif
+
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+EXPORT_SYMBOL(__pv_phys_offset);
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/asm-offsets.c linux-libre-2.6.39-gnu/arch/arm/kernel/asm-offsets.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/asm-offsets.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/asm-offsets.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,9 @@
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+#include <asm/glue-df.h>
+#include <asm/glue-pf.h>
 #include <asm/mach/arch.h>
 #include <asm/thread_info.h>
 #include <asm/memory.h>
@@ -114,6 +117,14 @@
 #ifdef MULTI_PABORT
   DEFINE(PROCESSOR_PABT_FUNC,	offsetof(struct processor, _prefetch_abort));
 #endif
+#ifdef MULTI_CPU
+  DEFINE(CPU_SLEEP_SIZE,	offsetof(struct processor, suspend_size));
+  DEFINE(CPU_DO_SUSPEND,	offsetof(struct processor, do_suspend));
+  DEFINE(CPU_DO_RESUME,		offsetof(struct processor, do_resume));
+#endif
+#ifdef MULTI_CACHE
+  DEFINE(CACHE_FLUSH_KERN_ALL,	offsetof(struct cpu_cache_fns, flush_kern_all));
+#endif
   BLANK();
   DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
   DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/bios32.c linux-libre-2.6.39-gnu/arch/arm/kernel/bios32.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/bios32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/bios32.c	2011-05-19 00:06:34.000000000 -0400
@@ -159,31 +159,6 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_DEC, PCI_DEVICE_ID_DEC_21285, pci_fixup_dec21285);
 
 /*
- * Same as above. The PrPMC800 carrier board for the PrPMC1100 
- * card maps the host-bridge @ 00:01:00 for some reason and it
- * ends up getting scanned. Note that we only want to do this
- * fixup when we find the IXP4xx on a PrPMC system, which is why
- * we check the machine type. We could be running on a board
- * with an IXP4xx target device and we don't want to kill the
- * resources in that case.
- */
-static void __devinit pci_fixup_prpmc1100(struct pci_dev *dev)
-{
-	int i;
-
-	if (machine_is_prpmc1100()) {
-		dev->class &= 0xff;
-		dev->class |= PCI_CLASS_BRIDGE_HOST << 8;
-		for (i = 0; i < PCI_NUM_RESOURCES; i++) {
-			dev->resource[i].start = 0;
-			dev->resource[i].end   = 0;
-			dev->resource[i].flags = 0;
-		}
-	}
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IXP4XX, pci_fixup_prpmc1100);
-
-/*
  * PCI IDE controllers use non-standard I/O port decoding, respect it.
  */
 static void __devinit pci_fixup_ide_bases(struct pci_dev *dev)
@@ -583,6 +558,11 @@
 			 * Assign resources.
 			 */
 			pci_bus_assign_resources(bus);
+
+			/*
+			 * Enable bridges
+			 */
+			pci_enable_bridges(bus);
 		}
 
 		/*
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/calls.S linux-libre-2.6.39-gnu/arch/arm/kernel/calls.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/calls.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/calls.S	2011-05-19 00:06:34.000000000 -0400
@@ -379,6 +379,10 @@
 		CALL(sys_fanotify_init)
 		CALL(sys_fanotify_mark)
 		CALL(sys_prlimit64)
+/* 370 */	CALL(sys_name_to_handle_at)
+		CALL(sys_open_by_handle_at)
+		CALL(sys_clock_adjtime)
+		CALL(sys_syncfs)
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/crash_dump.c linux-libre-2.6.39-gnu/arch/arm/kernel/crash_dump.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/crash_dump.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/crash_dump.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,9 +18,6 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-/* stores the physical address of elf header of crash image */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
 /**
  * copy_oldmem_page() - copy one page from old kernel memory
  * @pfn: page frame number to be copied
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/debug.S linux-libre-2.6.39-gnu/arch/arm/kernel/debug.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/debug.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/debug.S	2011-05-19 00:06:34.000000000 -0400
@@ -25,7 +25,7 @@
 		.macro	addruart, rp, rv
 		.endm
 
-#if defined(CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K) || defined(CONFIG_CPU_V7)
 
 		.macro	senduart, rd, rx
 		mcr	p14, 0, \rd, c0, c5, 0
@@ -49,23 +49,6 @@
 1002:
 		.endm
 
-#elif defined(CONFIG_CPU_V7)
-
-		.macro	senduart, rd, rx
-		mcr	p14, 0, \rd, c0, c5, 0
-		.endm
-
-		.macro	busyuart, rd, rx
-busy:		mrc	p14, 0, pc, c0, c1, 0
-		bcs	busy
-		.endm
-
-		.macro	waituart, rd, rx
-wait:		mrc	p14, 0, pc, c0, c1, 0
-		bcs	wait
-
-		.endm
-
 #elif defined(CONFIG_CPU_XSCALE)
 
 		.macro	senduart, rd, rx
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/ecard.c linux-libre-2.6.39-gnu/arch/arm/kernel/ecard.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/ecard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/ecard.c	2011-05-19 00:06:34.000000000 -0400
@@ -1043,8 +1043,8 @@
 	 */
 	if (slot < 8) {
 		ec->irq = 32 + slot;
-		set_irq_chip(ec->irq, &ecard_chip);
-		set_irq_handler(ec->irq, handle_level_irq);
+		irq_set_chip_and_handler(ec->irq, &ecard_chip,
+					 handle_level_irq);
 		set_irq_flags(ec->irq, IRQF_VALID);
 	}
 
@@ -1103,7 +1103,7 @@
 
 	irqhw = ecard_probeirqhw();
 
-	set_irq_chained_handler(IRQ_EXPANSIONCARD,
+	irq_set_chained_handler(IRQ_EXPANSIONCARD,
 				irqhw ? ecard_irqexp_handler : ecard_irq_handler);
 
 	ecard_proc_init();
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/elf.c linux-libre-2.6.39-gnu/arch/arm/kernel/elf.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/elf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/elf.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,15 +40,22 @@
 void elf_set_personality(const struct elf32_hdr *x)
 {
 	unsigned int eflags = x->e_flags;
-	unsigned int personality = PER_LINUX_32BIT;
+	unsigned int personality = current->personality & ~PER_MASK;
+
+	/*
+	 * We only support Linux ELF executables, so always set the
+	 * personality to LINUX.
+	 */
+	personality |= PER_LINUX;
 
 	/*
 	 * APCS-26 is only valid for OABI executables
 	 */
-	if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN) {
-		if (eflags & EF_ARM_APCS_26)
-			personality = PER_LINUX;
-	}
+	if ((eflags & EF_ARM_EABI_MASK) == EF_ARM_EABI_UNKNOWN &&
+	    (eflags & EF_ARM_APCS_26))
+		personality &= ~ADDR_LIMIT_32BIT;
+	else
+		personality |= ADDR_LIMIT_32BIT;
 
 	set_personality(personality);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/entry-armv.S linux-libre-2.6.39-gnu/arch/arm/kernel/entry-armv.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/entry-armv.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/entry-armv.S	2011-05-19 00:06:34.000000000 -0400
@@ -16,7 +16,8 @@
  */
 
 #include <asm/memory.h>
-#include <asm/glue.h>
+#include <asm/glue-df.h>
+#include <asm/glue-pf.h>
 #include <asm/vfpmacros.h>
 #include <mach/entry-macro.S>
 #include <asm/thread_notify.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/entry-header.S linux-libre-2.6.39-gnu/arch/arm/kernel/entry-header.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/entry-header.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/entry-header.S	2011-05-19 00:06:34.000000000 -0400
@@ -76,13 +76,13 @@
 #ifndef CONFIG_THUMB2_KERNEL
 	.macro	svc_exit, rpsr
 	msr	spsr_cxsf, \rpsr
-#if defined(CONFIG_CPU_32v6K)
-	clrex					@ clear the exclusive monitor
-	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
-#elif defined (CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6)
 	ldr	r0, [sp]
 	strex	r1, r2, [sp]			@ clear the exclusive monitor
 	ldmib	sp, {r1 - pc}^			@ load r1 - pc, cpsr
+#elif defined(CONFIG_CPU_32v6K)
+	clrex					@ clear the exclusive monitor
+	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 #else
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 #endif
@@ -92,10 +92,10 @@
 	ldr	r1, [sp, #\offset + S_PSR]	@ get calling cpsr
 	ldr	lr, [sp, #\offset + S_PC]!	@ get pc
 	msr	spsr_cxsf, r1			@ save in spsr_svc
-#if defined(CONFIG_CPU_32v6K)
-	clrex					@ clear the exclusive monitor
-#elif defined (CONFIG_CPU_V6)
+#if defined(CONFIG_CPU_V6)
 	strex	r1, r2, [sp]			@ clear the exclusive monitor
+#elif defined(CONFIG_CPU_32v6K)
+	clrex					@ clear the exclusive monitor
 #endif
 	.if	\fast
 	ldmdb	sp, {r1 - lr}^			@ get calling r1 - lr
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/etm.c linux-libre-2.6.39-gnu/arch/arm/kernel/etm.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/etm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/etm.c	2011-05-19 00:06:34.000000000 -0400
@@ -338,7 +338,7 @@
 	.fops = &etb_fops,
 };
 
-static int __init etb_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit etb_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
 	int ret = 0;
@@ -530,7 +530,7 @@
 static struct kobj_attribute trace_mode_attr =
 	__ATTR(trace_mode, 0644, trace_mode_show, trace_mode_store);
 
-static int __init etm_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit etm_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct tracectx *t = &tracer;
 	int ret = 0;
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/head-common.S linux-libre-2.6.39-gnu/arch/arm/kernel/head-common.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/head-common.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/head-common.S	2011-05-19 00:06:34.000000000 -0400
@@ -25,83 +25,6 @@
  * machine ID for example).
  */
 	__HEAD
-__error_a:
-#ifdef CONFIG_DEBUG_LL
-	mov	r4, r1				@ preserve machine ID
-	adr	r0, str_a1
-	bl	printascii
-	mov	r0, r4
-	bl	printhex8
-	adr	r0, str_a2
-	bl	printascii
-	adr	r3, __lookup_machine_type_data
-	ldmia	r3, {r4, r5, r6}		@ get machine desc list
-	sub	r4, r3, r4			@ get offset between virt&phys
-	add	r5, r5, r4			@ convert virt addresses to
-	add	r6, r6, r4			@ physical address space
-1:	ldr	r0, [r5, #MACHINFO_TYPE]	@ get machine type
-	bl	printhex8
-	mov	r0, #'\t'
-	bl	printch
-	ldr     r0, [r5, #MACHINFO_NAME]	@ get machine name
-	add	r0, r0, r4
-	bl	printascii
-	mov	r0, #'\n'
-	bl	printch
-	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
-	cmp	r5, r6
-	blo	1b
-	adr	r0, str_a3
-	bl	printascii
-	b	__error
-ENDPROC(__error_a)
-
-str_a1:	.asciz	"\nError: unrecognized/unsupported machine ID (r1 = 0x"
-str_a2:	.asciz	").\n\nAvailable machine support:\n\nID (hex)\tNAME\n"
-str_a3:	.asciz	"\nPlease check your kernel config and/or bootloader.\n"
-	.align
-#else
-	b	__error
-#endif
-
-/*
- * Lookup machine architecture in the linker-build list of architectures.
- * Note that we can't use the absolute addresses for the __arch_info
- * lists since we aren't running with the MMU on (and therefore, we are
- * not in the correct address space).  We have to calculate the offset.
- *
- *  r1 = machine architecture number
- * Returns:
- *  r3, r4, r6 corrupted
- *  r5 = mach_info pointer in physical address space
- */
-__lookup_machine_type:
-	adr	r3, __lookup_machine_type_data
-	ldmia	r3, {r4, r5, r6}
-	sub	r3, r3, r4			@ get offset between virt&phys
-	add	r5, r5, r3			@ convert virt addresses to
-	add	r6, r6, r3			@ physical address space
-1:	ldr	r3, [r5, #MACHINFO_TYPE]	@ get machine type
-	teq	r3, r1				@ matches loader number?
-	beq	2f				@ found
-	add	r5, r5, #SIZEOF_MACHINE_DESC	@ next machine_desc
-	cmp	r5, r6
-	blo	1b
-	mov	r5, #0				@ unknown machine
-2:	mov	pc, lr
-ENDPROC(__lookup_machine_type)
-
-/*
- * Look in arch/arm/kernel/arch.[ch] for information about the
- * __arch_info structures.
- */
-	.align	2
-	.type	__lookup_machine_type_data, %object
-__lookup_machine_type_data:
-	.long	.
-	.long	__arch_info_begin
-	.long	__arch_info_end
-	.size	__lookup_machine_type_data, . - __lookup_machine_type_data
 
 /* Determine validity of the r2 atags pointer.  The heuristic requires
  * that the pointer be aligned, in the first 16k of physical RAM and
@@ -109,8 +32,6 @@
  * of this function may be more lenient with the physical address and
  * may also be able to move the ATAGS block if necessary.
  *
- * r8  = machinfo
- *
  * Returns:
  *  r2 either valid atags pointer, or zero
  *  r5, r6 corrupted
@@ -185,17 +106,6 @@
 	.size	__mmap_switched_data, . - __mmap_switched_data
 
 /*
- * This provides a C-API version of __lookup_machine_type
- */
-ENTRY(lookup_machine_type)
-	stmfd	sp!, {r4 - r6, lr}
-	mov	r1, r0
-	bl	__lookup_machine_type
-	mov	r0, r5
-	ldmfd	sp!, {r4 - r6, pc}
-ENDPROC(lookup_machine_type)
-
-/*
  * This provides a C-API version of __lookup_processor_type
  */
 ENTRY(lookup_processor_type)
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/head-nommu.S linux-libre-2.6.39-gnu/arch/arm/kernel/head-nommu.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/head-nommu.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/head-nommu.S	2011-05-19 00:06:34.000000000 -0400
@@ -44,9 +44,6 @@
 	bl	__lookup_processor_type		@ r5=procinfo r9=cpuid
 	movs	r10, r5				@ invalid processor (r5=0)?
 	beq	__error_p				@ yes, error 'p'
-	bl	__lookup_machine_type		@ r5=machinfo
-	movs	r8, r5				@ invalid machine (r5=0)?
-	beq	__error_a			@ yes, error 'a'
 
 	adr	lr, BSYM(__after_proc_init)	@ return (PIC) address
  ARM(	add	pc, r10, #PROCINFO_INITFUNC	)
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/head.S linux-libre-2.6.39-gnu/arch/arm/kernel/head.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -26,14 +26,6 @@
 #include <mach/debug-macro.S>
 #endif
 
-#if (PHYS_OFFSET & 0x001fffff)
-#error "PHYS_OFFSET must be at an even 2MiB boundary!"
-#endif
-
-#define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
-#define KERNEL_RAM_PADDR	(PHYS_OFFSET + TEXT_OFFSET)
-
-
 /*
  * swapper_pg_dir is the virtual address of the initial page table.
  * We place the page tables 16K below KERNEL_RAM_VADDR.  Therefore, we must
@@ -41,6 +33,7 @@
  * the least significant 16 bits to be 0x8000, but we could probably
  * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x4000.
  */
+#define KERNEL_RAM_VADDR	(PAGE_OFFSET + TEXT_OFFSET)
 #if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
 #error KERNEL_RAM_VADDR must start at 0xXXXX8000
 #endif
@@ -48,8 +41,8 @@
 	.globl	swapper_pg_dir
 	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x4000
 
-	.macro	pgtbl, rd
-	ldr	\rd, =(KERNEL_RAM_PADDR - 0x4000)
+	.macro	pgtbl, rd, phys
+	add	\rd, \phys, #TEXT_OFFSET - 0x4000
 	.endm
 
 #ifdef CONFIG_XIP_KERNEL
@@ -87,25 +80,33 @@
 	movs	r10, r5				@ invalid processor (r5=0)?
  THUMB( it	eq )		@ force fixup-able long branch encoding
 	beq	__error_p			@ yes, error 'p'
-	bl	__lookup_machine_type		@ r5=machinfo
-	movs	r8, r5				@ invalid machine (r5=0)?
- THUMB( it	eq )		@ force fixup-able long branch encoding
-	beq	__error_a			@ yes, error 'a'
+
+#ifndef CONFIG_XIP_KERNEL
+	adr	r3, 2f
+	ldmia	r3, {r4, r8}
+	sub	r4, r3, r4			@ (PHYS_OFFSET - PAGE_OFFSET)
+	add	r8, r8, r4			@ PHYS_OFFSET
+#else
+	ldr	r8, =PLAT_PHYS_OFFSET
+#endif
 
 	/*
 	 * r1 = machine no, r2 = atags,
-	 * r8 = machinfo, r9 = cpuid, r10 = procinfo
+	 * r8 = phys_offset, r9 = cpuid, r10 = procinfo
 	 */
 	bl	__vet_atags
 #ifdef CONFIG_SMP_ON_UP
 	bl	__fixup_smp
 #endif
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+	bl	__fixup_pv_table
+#endif
 	bl	__create_page_tables
 
 	/*
 	 * The following calls CPU specific code in a position independent
 	 * manner.  See arch/arm/mm/proc-*.S for details.  r10 = base of
-	 * xxx_proc_info structure selected by __lookup_machine_type
+	 * xxx_proc_info structure selected by __lookup_processor_type
 	 * above.  On return, the CPU will be ready for the MMU to be
 	 * turned on, and r0 will hold the CPU control register value.
 	 */
@@ -118,22 +119,24 @@
 1:	b	__enable_mmu
 ENDPROC(stext)
 	.ltorg
+#ifndef CONFIG_XIP_KERNEL
+2:	.long	.
+	.long	PAGE_OFFSET
+#endif
 
 /*
  * Setup the initial page tables.  We only setup the barest
  * amount which are required to get the kernel running, which
  * generally means mapping in the kernel code.
  *
- * r8  = machinfo
- * r9  = cpuid
- * r10 = procinfo
+ * r8 = phys_offset, r9 = cpuid, r10 = procinfo
  *
  * Returns:
  *  r0, r3, r5-r7 corrupted
  *  r4 = physical page table address
  */
 __create_page_tables:
-	pgtbl	r4				@ page table address
+	pgtbl	r4, r8				@ page table address
 
 	/*
 	 * Clear the 16K level 1 swapper page table
@@ -189,10 +192,8 @@
 	/*
 	 * Map some ram to cover our .data and .bss areas.
 	 */
-	orr	r3, r7, #(KERNEL_RAM_PADDR & 0xff000000)
-	.if	(KERNEL_RAM_PADDR & 0x00f00000)
-	orr	r3, r3, #(KERNEL_RAM_PADDR & 0x00f00000)
-	.endif
+	add	r3, r8, #TEXT_OFFSET
+	orr	r3, r3, r7
 	add	r0, r4,  #(KERNEL_RAM_VADDR & 0xff000000) >> 18
 	str	r3, [r0, #(KERNEL_RAM_VADDR & 0x00f00000) >> 18]!
 	ldr	r6, =(_end - 1)
@@ -205,14 +206,17 @@
 #endif
 
 	/*
-	 * Then map first 1MB of ram in case it contains our boot params.
+	 * Then map boot params address in r2 or
+	 * the first 1MB of ram if boot params address is not specified.
 	 */
-	add	r0, r4, #PAGE_OFFSET >> 18
-	orr	r6, r7, #(PHYS_OFFSET & 0xff000000)
-	.if	(PHYS_OFFSET & 0x00f00000)
-	orr	r6, r6, #(PHYS_OFFSET & 0x00f00000)
-	.endif
-	str	r6, [r0]
+	mov	r0, r2, lsr #20
+	movs	r0, r0, lsl #20
+	moveq	r0, r8
+	sub	r3, r0, r8
+	add	r3, r3, #PAGE_OFFSET
+	add	r3, r4, r3, lsr #18
+	orr	r6, r7, r0
+	str	r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
 #ifndef CONFIG_DEBUG_ICEDCC
@@ -457,4 +461,129 @@
 	ldmfd	sp!, {r4 - r6, pc}
 ENDPROC(fixup_smp)
 
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+
+/* __fixup_pv_table - patch the stub instructions with the delta between
+ * PHYS_OFFSET and PAGE_OFFSET, which is assumed to be 16MiB aligned and
+ * can be expressed by an immediate shifter operand. The stub instruction
+ * has a form of '(add|sub) rd, rn, #imm'.
+ */
+	__HEAD
+__fixup_pv_table:
+	adr	r0, 1f
+	ldmia	r0, {r3-r5, r7}
+	sub	r3, r0, r3	@ PHYS_OFFSET - PAGE_OFFSET
+	add	r4, r4, r3	@ adjust table start address
+	add	r5, r5, r3	@ adjust table end address
+	add	r7, r7, r3	@ adjust __pv_phys_offset address
+	str	r8, [r7]	@ save computed PHYS_OFFSET to __pv_phys_offset
+#ifndef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	mov	r6, r3, lsr #24	@ constant for add/sub instructions
+	teq	r3, r6, lsl #24 @ must be 16MiB aligned
+#else
+	mov	r6, r3, lsr #16	@ constant for add/sub instructions
+	teq	r3, r6, lsl #16	@ must be 64kiB aligned
+#endif
+THUMB(	it	ne		@ cross section branch )
+	bne	__error
+	str	r6, [r7, #4]	@ save to __pv_offset
+	b	__fixup_a_pv_table
+ENDPROC(__fixup_pv_table)
+
+	.align
+1:	.long	.
+	.long	__pv_table_begin
+	.long	__pv_table_end
+2:	.long	__pv_phys_offset
+
+	.text
+__fixup_a_pv_table:
+#ifdef CONFIG_THUMB2_KERNEL
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	lsls	r0, r6, #24
+	lsr	r6, #8
+	beq	1f
+	clz	r7, r0
+	lsr	r0, #24
+	lsl	r0, r7
+	bic	r0, 0x0080
+	lsrs	r7, #1
+	orrcs   r0, #0x0080
+	orr	r0, r0, r7, lsl #12
+#endif
+1:	lsls	r6, #24
+	beq	4f
+	clz	r7, r6
+	lsr	r6, #24
+	lsl	r6, r7
+	bic	r6, #0x0080
+	lsrs	r7, #1
+	orrcs	r6, #0x0080
+	orr	r6, r6, r7, lsl #12
+	orr	r6, #0x4000
+	b	4f
+2:	@ at this point the C flag is always clear
+	add     r7, r3
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	ldrh	ip, [r7]
+	tst	ip, 0x0400	@ the i bit tells us LS or MS byte
+	beq	3f
+	cmp	r0, #0		@ set C flag, and ...
+	biceq	ip, 0x0400	@ immediate zero value has a special encoding
+	streqh	ip, [r7]	@ that requires the i bit cleared
+#endif
+3:	ldrh	ip, [r7, #2]
+	and	ip, 0x8f00
+	orrcc	ip, r6	@ mask in offset bits 31-24
+	orrcs	ip, r0	@ mask in offset bits 23-16
+	strh	ip, [r7, #2]
+4:	cmp	r4, r5
+	ldrcc	r7, [r4], #4	@ use branch for delay slot
+	bcc	2b
+	bx	lr
+#else
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT_16BIT
+	and	r0, r6, #255	@ offset bits 23-16
+	mov	r6, r6, lsr #8	@ offset bits 31-24
+#else
+	mov	r0, #0		@ just in case...
+#endif
+	b	3f
+2:	ldr	ip, [r7, r3]
+	bic	ip, ip, #0x000000ff
+	tst	ip, #0x400	@ rotate shift tells us LS or MS byte
+	orrne	ip, ip, r6	@ mask in offset bits 31-24
+	orreq	ip, ip, r0	@ mask in offset bits 23-16
+	str	ip, [r7, r3]
+3:	cmp	r4, r5
+	ldrcc	r7, [r4], #4	@ use branch for delay slot
+	bcc	2b
+	mov	pc, lr
+#endif
+ENDPROC(__fixup_a_pv_table)
+
+ENTRY(fixup_pv_table)
+	stmfd	sp!, {r4 - r7, lr}
+	ldr	r2, 2f			@ get address of __pv_phys_offset
+	mov	r3, #0			@ no offset
+	mov	r4, r0			@ r0 = table start
+	add	r5, r0, r1		@ r1 = table size
+	ldr	r6, [r2, #4]		@ get __pv_offset
+	bl	__fixup_a_pv_table
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(fixup_pv_table)
+
+	.align
+2:	.long	__pv_phys_offset
+
+	.data
+	.globl	__pv_phys_offset
+	.type	__pv_phys_offset, %object
+__pv_phys_offset:
+	.long	0
+	.size	__pv_phys_offset, . - __pv_phys_offset
+__pv_offset:
+	.long	0
+#endif
+
 #include "head-common.S"
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/hw_breakpoint.c linux-libre-2.6.39-gnu/arch/arm/kernel/hw_breakpoint.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/hw_breakpoint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/hw_breakpoint.c	2011-05-19 00:06:34.000000000 -0400
@@ -238,8 +238,8 @@
 	ARM_DBG_READ(c1, 0, dscr);
 
 	/* Ensure that halting mode is disabled. */
-	if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN, "halting debug mode enabled."
-				"Unable to access hardware resources.")) {
+	if (WARN_ONCE(dscr & ARM_DSCR_HDBGEN,
+			"halting debug mode enabled. Unable to access hardware resources.\n")) {
 		ret = -EPERM;
 		goto out;
 	}
@@ -377,7 +377,7 @@
 		}
 	}
 
-	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot")) {
+	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n")) {
 		ret = -EBUSY;
 		goto out;
 	}
@@ -423,7 +423,7 @@
 		}
 	}
 
-	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot"))
+	if (WARN_ONCE(i == max_slots, "Can't find any breakpoint slot\n"))
 		return;
 
 	/* Reset the control register. */
@@ -635,7 +635,7 @@
 	if (WARN_ONCE(!bp->overflow_handler &&
 		(arch_check_bp_in_kernelspace(bp) || !core_has_mismatch_brps()
 		 || !bp->hw.bp_target),
-			"overflow handler required but none found")) {
+			"overflow handler required but none found\n")) {
 		ret = -EINVAL;
 	}
 out:
@@ -868,6 +868,13 @@
 		 */
 		asm volatile("mcr p14, 0, %0, c1, c0, 4" : : "r" (0));
 		isb();
+
+		/*
+		 * Clear any configured vector-catch events before
+		 * enabling monitor mode.
+		 */
+		asm volatile("mcr p14, 0, %0, c0, c7, 0" : : "r" (0));
+		isb();
 	}
 
 	if (enable_monitor_mode())
@@ -936,8 +943,8 @@
 	ARM_DBG_READ(c1, 0, dscr);
 	if (dscr & ARM_DSCR_HDBGEN) {
 		max_watchpoint_len = 4;
-		pr_warning("halting debug mode enabled. Assuming maximum "
-			   "watchpoint size of %u bytes.", max_watchpoint_len);
+		pr_warning("halting debug mode enabled. Assuming maximum watchpoint size of %u bytes.\n",
+			   max_watchpoint_len);
 	} else {
 		/* Work out the maximum supported watchpoint length. */
 		max_watchpoint_len = get_max_wp_len();
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/irq.c linux-libre-2.6.39-gnu/arch/arm/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,63 +51,18 @@
 
 unsigned long irq_err_count;
 
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, cpu;
-	struct irq_desc *desc;
-	struct irqaction * action;
-	unsigned long flags;
-	int prec, n;
-
-	for (prec = 3, n = 1000; prec < 10 && n <= nr_irqs; prec++)
-		n *= 10;
-
-#ifdef CONFIG_SMP
-	if (prec < 4)
-		prec = 4;
-#endif
-
-	if (i == 0) {
-		char cpuname[12];
-
-		seq_printf(p, "%*s ", prec, "");
-		for_each_present_cpu(cpu) {
-			sprintf(cpuname, "CPU%d", cpu);
-			seq_printf(p, " %10s", cpuname);
-		}
-		seq_putc(p, '\n');
-	}
-
-	if (i < nr_irqs) {
-		desc = irq_to_desc(i);
-		raw_spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
-		if (!action)
-			goto unlock;
-
-		seq_printf(p, "%*d: ", prec, i);
-		for_each_present_cpu(cpu)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-		seq_printf(p, " %10s", desc->irq_data.chip->name ? : "-");
-		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-unlock:
-		raw_spin_unlock_irqrestore(&desc->lock, flags);
-	} else if (i == nr_irqs) {
 #ifdef CONFIG_FIQ
-		show_fiq_list(p, prec);
+	show_fiq_list(p, prec);
 #endif
 #ifdef CONFIG_SMP
-		show_ipi_list(p, prec);
+	show_ipi_list(p, prec);
 #endif
 #ifdef CONFIG_LOCAL_TIMERS
-		show_local_irqs(p, prec);
+	show_local_irqs(p, prec);
 #endif
-		seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
-	}
+	seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
 	return 0;
 }
 
@@ -144,24 +99,21 @@
 
 void set_irq_flags(unsigned int irq, unsigned int iflags)
 {
-	struct irq_desc *desc;
-	unsigned long flags;
+	unsigned long clr = 0, set = IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
 
 	if (irq >= nr_irqs) {
 		printk(KERN_ERR "Trying to set irq flags for IRQ%d\n", irq);
 		return;
 	}
 
-	desc = irq_to_desc(irq);
-	raw_spin_lock_irqsave(&desc->lock, flags);
-	desc->status |= IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN;
 	if (iflags & IRQF_VALID)
-		desc->status &= ~IRQ_NOREQUEST;
+		clr |= IRQ_NOREQUEST;
 	if (iflags & IRQF_PROBE)
-		desc->status &= ~IRQ_NOPROBE;
+		clr |= IRQ_NOPROBE;
 	if (!(iflags & IRQF_NOAUTOEN))
-		desc->status &= ~IRQ_NOAUTOEN;
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
+		clr |= IRQ_NOAUTOEN;
+	/* Order is clear bits in "clr" then set bits in "set" */
+	irq_modify_status(irq, clr, set & ~clr);
 }
 
 void __init init_IRQ(void)
@@ -179,14 +131,21 @@
 
 #ifdef CONFIG_HOTPLUG_CPU
 
-static void route_irq(struct irq_desc *desc, unsigned int irq, unsigned int cpu)
+static bool migrate_one_irq(struct irq_data *d)
 {
-	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", irq, desc->irq_data.node, cpu);
+	unsigned int cpu = cpumask_any_and(d->affinity, cpu_online_mask);
+	bool ret = false;
 
-	raw_spin_lock_irq(&desc->lock);
-	desc->irq_data.chip->irq_set_affinity(&desc->irq_data,
-					      cpumask_of(cpu), false);
-	raw_spin_unlock_irq(&desc->lock);
+	if (cpu >= nr_cpu_ids) {
+		cpu = cpumask_any(cpu_online_mask);
+		ret = true;
+	}
+
+	pr_debug("IRQ%u: moving from cpu%u to cpu%u\n", d->irq, d->node, cpu);
+
+	d->chip->irq_set_affinity(d, cpumask_of(cpu), true);
+
+	return ret;
 }
 
 /*
@@ -198,25 +157,30 @@
 {
 	unsigned int i, cpu = smp_processor_id();
 	struct irq_desc *desc;
+	unsigned long flags;
+
+	local_irq_save(flags);
 
 	for_each_irq_desc(i, desc) {
 		struct irq_data *d = &desc->irq_data;
+		bool affinity_broken = false;
 
-		if (d->node == cpu) {
-			unsigned int newcpu = cpumask_any_and(d->affinity,
-							      cpu_online_mask);
-			if (newcpu >= nr_cpu_ids) {
-				if (printk_ratelimit())
-					printk(KERN_INFO "IRQ%u no longer affine to CPU%u\n",
-					       i, cpu);
+		raw_spin_lock(&desc->lock);
+		do {
+			if (desc->action == NULL)
+				break;
 
-				cpumask_setall(d->affinity);
-				newcpu = cpumask_any_and(d->affinity,
-							 cpu_online_mask);
-			}
+			if (d->node != cpu)
+				break;
 
-			route_irq(desc, i, newcpu);
-		}
+			affinity_broken = migrate_one_irq(d);
+		} while (0);
+		raw_spin_unlock(&desc->lock);
+
+		if (affinity_broken && printk_ratelimit())
+			pr_warning("IRQ%u no longer affine to CPU%u\n", i, cpu);
 	}
+
+	local_irq_restore(flags);
 }
 #endif /* CONFIG_HOTPLUG_CPU */
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/kprobes.c linux-libre-2.6.39-gnu/arch/arm/kernel/kprobes.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/kprobes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/kprobes.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,7 +134,8 @@
 				 struct kprobe_ctlblk *kcb)
 {
 	regs->ARM_pc += 4;
-	p->ainsn.insn_handler(p, regs);
+	if (p->ainsn.insn_check_cc(regs->ARM_cpsr))
+		p->ainsn.insn_handler(p, regs);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/kprobes-decode.c linux-libre-2.6.39-gnu/arch/arm/kernel/kprobes-decode.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/kprobes-decode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/kprobes-decode.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,9 +34,6 @@
  *
  *   *) If the PC is written to by the instruction, the
  *      instruction must be fully simulated in software.
- *      If it is a conditional instruction, the handler
- *      will use insn[0] to copy its condition code to
- *	set r0 to 1 and insn[1] to "mov pc, lr" to return.
  *
  *   *) Otherwise, a modified form of the instruction is
  *      directly executed.  Its handler calls the
@@ -68,13 +65,17 @@
 
 #define branch_displacement(insn) sign_extend(((insn) & 0xffffff) << 2, 25)
 
+#define is_r15(insn, bitpos) (((insn) & (0xf << bitpos)) == (0xf << bitpos))
+
+/*
+ * Test if load/store instructions writeback the address register.
+ * if P (bit 24) == 0 or W (bit 21) == 1
+ */
+#define is_writeback(insn) ((insn ^ 0x01000000) & 0x01200000)
+
 #define PSR_fs	(PSR_f|PSR_s)
 
 #define KPROBE_RETURN_INSTRUCTION	0xe1a0f00e	/* mov pc, lr */
-#define SET_R0_TRUE_INSTRUCTION		0xe3a00001	/* mov	r0, #1 */
-
-#define	truecc_insn(insn)	(((insn) & 0xf0000000) | \
-				 (SET_R0_TRUE_INSTRUCTION & 0x0fffffff))
 
 typedef long (insn_0arg_fn_t)(void);
 typedef long (insn_1arg_fn_t)(long);
@@ -419,14 +420,10 @@
 
 static void __kprobes simulate_bbl(struct kprobe *p, struct pt_regs *regs)
 {
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
 	long iaddr = (long)p->addr;
 	int disp  = branch_displacement(insn);
 
-	if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-		return;
-
 	if (insn & (1 << 24))
 		regs->ARM_lr = iaddr + 4;
 
@@ -446,14 +443,10 @@
 
 static void __kprobes simulate_blx2bx(struct kprobe *p, struct pt_regs *regs)
 {
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
 	int rm = insn & 0xf;
 	long rmv = regs->uregs[rm];
 
-	if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-		return;
-
 	if (insn & (1 << 5))
 		regs->ARM_lr = (long)p->addr + 4;
 
@@ -463,9 +456,16 @@
 		regs->ARM_cpsr |= PSR_T_BIT;
 }
 
+static void __kprobes simulate_mrs(struct kprobe *p, struct pt_regs *regs)
+{
+	kprobe_opcode_t insn = p->opcode;
+	int rd = (insn >> 12) & 0xf;
+	unsigned long mask = 0xf8ff03df; /* Mask out execution state */
+	regs->uregs[rd] = regs->ARM_cpsr & mask;
+}
+
 static void __kprobes simulate_ldm1stm1(struct kprobe *p, struct pt_regs *regs)
 {
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
 	int rn = (insn >> 16) & 0xf;
 	int lbit = insn & (1 << 20);
@@ -476,9 +476,6 @@
 	int reg_bit_vector;
 	int reg_count;
 
-	if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-		return;
-
 	reg_count = 0;
 	reg_bit_vector = insn & 0xffff;
 	while (reg_bit_vector) {
@@ -510,11 +507,6 @@
 
 static void __kprobes simulate_stm1_pc(struct kprobe *p, struct pt_regs *regs)
 {
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-
-	if (!insnslot_1arg_rflags(0, regs->ARM_cpsr, i_fn))
-		return;
-
 	regs->ARM_pc = (long)p->addr + str_pc_offset;
 	simulate_ldm1stm1(p, regs);
 	regs->ARM_pc = (long)p->addr + 4;
@@ -525,24 +517,16 @@
 	regs->uregs[12] = regs->uregs[13];
 }
 
-static void __kprobes emulate_ldcstc(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rn = (insn >> 16) & 0xf;
-	long rnv = regs->uregs[rn];
-
-	/* Save Rn in case of writeback. */
-	regs->uregs[rn] = insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
-}
-
 static void __kprobes emulate_ldrd(struct kprobe *p, struct pt_regs *regs)
 {
 	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
+	long ppc = (long)p->addr + 8;
 	int rd = (insn >> 12) & 0xf;
 	int rn = (insn >> 16) & 0xf;
 	int rm = insn & 0xf;  /* rm may be invalid, don't care. */
+	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
 
 	/* Not following the C calling convention here, so need asm(). */
 	__asm__ __volatile__ (
@@ -554,29 +538,36 @@
 		"str	r0, %[rn]	\n\t"	/* in case of writeback */
 		"str	r2, %[rd0]	\n\t"
 		"str	r3, %[rd1]	\n\t"
-		: [rn]  "+m" (regs->uregs[rn]),
+		: [rn]  "+m" (rnv),
 		  [rd0] "=m" (regs->uregs[rd]),
 		  [rd1] "=m" (regs->uregs[rd+1])
-		: [rm]   "m" (regs->uregs[rm]),
+		: [rm]   "m" (rmv),
 		  [cpsr] "r" (regs->ARM_cpsr),
 		  [i_fn] "r" (i_fn)
 		: "r0", "r1", "r2", "r3", "lr", "cc"
 	);
+	if (is_writeback(insn))
+		regs->uregs[rn] = rnv;
 }
 
 static void __kprobes emulate_strd(struct kprobe *p, struct pt_regs *regs)
 {
 	insn_4arg_fn_t *i_fn = (insn_4arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
+	long ppc = (long)p->addr + 8;
 	int rd = (insn >> 12) & 0xf;
 	int rn = (insn >> 16) & 0xf;
 	int rm  = insn & 0xf;
-	long rnv = regs->uregs[rn];
-	long rmv = regs->uregs[rm];  /* rm/rmv may be invalid, don't care. */
+	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+	/* rm/rmv may be invalid, don't care. */
+	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+	long rnv_wb;
 
-	regs->uregs[rn] = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
+	rnv_wb = insnslot_4arg_rflags(rnv, rmv, regs->uregs[rd],
 					       regs->uregs[rd+1],
 					       regs->ARM_cpsr, i_fn);
+	if (is_writeback(insn))
+		regs->uregs[rn] = rnv_wb;
 }
 
 static void __kprobes emulate_ldr(struct kprobe *p, struct pt_regs *regs)
@@ -594,7 +585,8 @@
 	long cpsr = regs->ARM_cpsr;
 
 	fnr.dr = insnslot_llret_3arg_rflags(rnv, 0, rmv, cpsr, i_fn);
-	regs->uregs[rn] = fnr.r0;  /* Save Rn in case of writeback. */
+	if (rn != 15)
+		regs->uregs[rn] = fnr.r0;  /* Save Rn in case of writeback. */
 	rdv = fnr.r1;
 
 	if (rd == 15) {
@@ -622,35 +614,11 @@
 	long rdv = (rd == 15) ? iaddr + str_pc_offset : regs->uregs[rd];
 	long rnv = (rn == 15) ? iaddr +  8 : regs->uregs[rn];
 	long rmv = regs->uregs[rm];  /* rm/rmv may be invalid, don't care. */
+	long rnv_wb;
 
-	/* Save Rn in case of writeback. */
-	regs->uregs[rn] =
-		insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
-}
-
-static void __kprobes emulate_mrrc(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_llret_0arg_fn_t *i_fn = (insn_llret_0arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	union reg_pair fnr;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-
-	fnr.dr = insnslot_llret_0arg_rflags(regs->ARM_cpsr, i_fn);
-	regs->uregs[rn] = fnr.r0;
-	regs->uregs[rd] = fnr.r1;
-}
-
-static void __kprobes emulate_mcrr(struct kprobe *p, struct pt_regs *regs)
-{
-	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-	int rn = (insn >> 16) & 0xf;
-	long rnv = regs->uregs[rn];
-	long rdv = regs->uregs[rd];
-
-	insnslot_2arg_rflags(rnv, rdv, regs->ARM_cpsr, i_fn);
+	rnv_wb = insnslot_3arg_rflags(rnv, rdv, rmv, regs->ARM_cpsr, i_fn);
+	if (rn != 15)
+		regs->uregs[rn] = rnv_wb;  /* Save Rn in case of writeback. */
 }
 
 static void __kprobes emulate_sat(struct kprobe *p, struct pt_regs *regs)
@@ -686,32 +654,32 @@
 	insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_rd12(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes emulate_nop(struct kprobe *p, struct pt_regs *regs)
 {
-	insn_0arg_fn_t *i_fn = (insn_0arg_fn_t *)&p->ainsn.insn[0];
-	kprobe_opcode_t insn = p->opcode;
-	int rd = (insn >> 12) & 0xf;
-
-	regs->uregs[rd] = insnslot_0arg_rflags(regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_ird12(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+emulate_rd12_modify(struct kprobe *p, struct pt_regs *regs)
 {
 	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
-	int ird = (insn >> 12) & 0xf;
+	int rd = (insn >> 12) & 0xf;
+	long rdv = regs->uregs[rd];
 
-	insnslot_1arg_rflags(regs->uregs[ird], regs->ARM_cpsr, i_fn);
+	regs->uregs[rd] = insnslot_1arg_rflags(rdv, regs->ARM_cpsr, i_fn);
 }
 
-static void __kprobes emulate_rn16(struct kprobe *p, struct pt_regs *regs)
+static void __kprobes
+emulate_rd12rn0_modify(struct kprobe *p, struct pt_regs *regs)
 {
-	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
+	insn_2arg_fn_t *i_fn = (insn_2arg_fn_t *)&p->ainsn.insn[0];
 	kprobe_opcode_t insn = p->opcode;
-	int rn = (insn >> 16) & 0xf;
+	int rd = (insn >> 12) & 0xf;
+	int rn = insn & 0xf;
+	long rdv = regs->uregs[rd];
 	long rnv = regs->uregs[rn];
 
-	insnslot_1arg_rflags(rnv, regs->ARM_cpsr, i_fn);
+	regs->uregs[rd] = insnslot_2arg_rflags(rdv, rnv, regs->ARM_cpsr, i_fn);
 }
 
 static void __kprobes emulate_rd12rm0(struct kprobe *p, struct pt_regs *regs)
@@ -817,6 +785,17 @@
 }
 
 static void __kprobes
+emulate_alu_tests_imm(struct kprobe *p, struct pt_regs *regs)
+{
+	insn_1arg_fn_t *i_fn = (insn_1arg_fn_t *)&p->ainsn.insn[0];
+	kprobe_opcode_t insn = p->opcode;
+	int rn = (insn >> 16) & 0xf;
+	long rnv = (rn == 15) ? (long)p->addr + 8 : regs->uregs[rn];
+
+	insnslot_1arg_rwflags(rnv, &regs->ARM_cpsr, i_fn);
+}
+
+static void __kprobes
 emulate_alu_rflags(struct kprobe *p, struct pt_regs *regs)
 {
 	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
@@ -852,14 +831,34 @@
 		insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
 }
 
+static void __kprobes
+emulate_alu_tests(struct kprobe *p, struct pt_regs *regs)
+{
+	insn_3arg_fn_t *i_fn = (insn_3arg_fn_t *)&p->ainsn.insn[0];
+	kprobe_opcode_t insn = p->opcode;
+	long ppc = (long)p->addr + 8;
+	int rn = (insn >> 16) & 0xf;
+	int rs = (insn >> 8) & 0xf;	/* rs/rsv may be invalid, don't care. */
+	int rm = insn & 0xf;
+	long rnv = (rn == 15) ? ppc : regs->uregs[rn];
+	long rmv = (rm == 15) ? ppc : regs->uregs[rm];
+	long rsv = regs->uregs[rs];
+
+	insnslot_3arg_rwflags(rnv, rmv, rsv, &regs->ARM_cpsr, i_fn);
+}
+
 static enum kprobe_insn __kprobes
 prep_emulate_ldr_str(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-	int ibit = (insn & (1 << 26)) ? 25 : 22;
+	int not_imm = (insn & (1 << 26)) ? (insn & (1 << 25))
+					 : (~insn & (1 << 22));
+
+	if (is_writeback(insn) && is_r15(insn, 16))
+		return INSN_REJECTED;	/* Writeback to PC */
 
 	insn &= 0xfff00fff;
 	insn |= 0x00001000;	/* Rn = r0, Rd = r1 */
-	if (insn & (1 << ibit)) {
+	if (not_imm) {
 		insn &= ~0xf;
 		insn |= 2;	/* Rm = r2 */
 	}
@@ -869,20 +868,40 @@
 }
 
 static enum kprobe_insn __kprobes
-prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+prep_emulate_rd12_modify(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-	insn &= 0xffff0ff0;	/* Rd = r0, Rm = r0 */
+	if (is_r15(insn, 12))
+		return INSN_REJECTED;	/* Rd is PC */
+
+	insn &= 0xffff0fff;	/* Rd = r0 */
 	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd12rm0;
+	asi->insn_handler = emulate_rd12_modify;
 	return INSN_GOOD;
 }
 
 static enum kprobe_insn __kprobes
-prep_emulate_rd12(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+prep_emulate_rd12rn0_modify(kprobe_opcode_t insn,
+			    struct arch_specific_insn *asi)
 {
-	insn &= 0xffff0fff;	/* Rd = r0 */
+	if (is_r15(insn, 12))
+		return INSN_REJECTED;	/* Rd is PC */
+
+	insn &= 0xffff0ff0;	/* Rd = r0 */
+	insn |= 0x00000001;	/* Rn = r1 */
 	asi->insn[0] = insn;
-	asi->insn_handler = emulate_rd12;
+	asi->insn_handler = emulate_rd12rn0_modify;
+	return INSN_GOOD;
+}
+
+static enum kprobe_insn __kprobes
+prep_emulate_rd12rm0(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+{
+	if (is_r15(insn, 12))
+		return INSN_REJECTED;	/* Rd is PC */
+
+	insn &= 0xffff0ff0;	/* Rd = r0, Rm = r0 */
+	asi->insn[0] = insn;
+	asi->insn_handler = emulate_rd12rm0;
 	return INSN_GOOD;
 }
 
@@ -890,6 +909,9 @@
 prep_emulate_rd12rn16rm0_wflags(kprobe_opcode_t insn,
 				struct arch_specific_insn *asi)
 {
+	if (is_r15(insn, 12))
+		return INSN_REJECTED;	/* Rd is PC */
+
 	insn &= 0xfff00ff0;	/* Rd = r0, Rn = r0 */
 	insn |= 0x00000001;	/* Rm = r1 */
 	asi->insn[0] = insn;
@@ -901,6 +923,9 @@
 prep_emulate_rd16rs8rm0_wflags(kprobe_opcode_t insn,
 			       struct arch_specific_insn *asi)
 {
+	if (is_r15(insn, 16))
+		return INSN_REJECTED;	/* Rd is PC */
+
 	insn &= 0xfff0f0f0;	/* Rd = r0, Rs = r0 */
 	insn |= 0x00000001;	/* Rm = r1          */
 	asi->insn[0] = insn;
@@ -912,6 +937,9 @@
 prep_emulate_rd16rn12rs8rm0_wflags(kprobe_opcode_t insn,
 				   struct arch_specific_insn *asi)
 {
+	if (is_r15(insn, 16))
+		return INSN_REJECTED;	/* Rd is PC */
+
 	insn &= 0xfff000f0;	/* Rd = r0, Rn = r0 */
 	insn |= 0x00000102;	/* Rs = r1, Rm = r2 */
 	asi->insn[0] = insn;
@@ -923,6 +951,9 @@
 prep_emulate_rdhi16rdlo12rs8rm0_wflags(kprobe_opcode_t insn,
 				       struct arch_specific_insn *asi)
 {
+	if (is_r15(insn, 16) || is_r15(insn, 12))
+		return INSN_REJECTED;	/* RdHi or RdLo is PC */
+
 	insn &= 0xfff000f0;	/* RdHi = r0, RdLo = r1 */
 	insn |= 0x00001203;	/* Rs = r2, Rm = r3 */
 	asi->insn[0] = insn;
@@ -943,20 +974,13 @@
 static enum kprobe_insn __kprobes
 space_1111(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
-	/* CPS mmod == 1 : 1111 0001 0000 xx10 xxxx xxxx xx0x xxxx */
-	/* RFE           : 1111 100x x0x1 xxxx xxxx 1010 xxxx xxxx */
-	/* SRS           : 1111 100x x1x0 1101 xxxx 0101 xxxx xxxx */
-	if ((insn & 0xfff30020) == 0xf1020000 ||
-	    (insn & 0xfe500f00) == 0xf8100a00 ||
-	    (insn & 0xfe5f0f00) == 0xf84d0500)
-		return INSN_REJECTED;
-
-	/* PLD : 1111 01x1 x101 xxxx xxxx xxxx xxxx xxxx : */
-	if ((insn & 0xfd700000) == 0xf4500000) {
-		insn &= 0xfff0ffff;	/* Rn = r0 */
-		asi->insn[0] = insn;
-		asi->insn_handler = emulate_rn16;
-		return INSN_GOOD;
+	/* memory hint : 1111 0100 x001 xxxx xxxx xxxx xxxx xxxx : */
+	/* PLDI        : 1111 0100 x101 xxxx xxxx xxxx xxxx xxxx : */
+	/* PLDW        : 1111 0101 x001 xxxx xxxx xxxx xxxx xxxx : */
+	/* PLD         : 1111 0101 x101 xxxx xxxx xxxx xxxx xxxx : */
+	if ((insn & 0xfe300000) == 0xf4100000) {
+		asi->insn_handler = emulate_nop;
+		return INSN_GOOD_NO_SLOT;
 	}
 
 	/* BLX(1) : 1111 101x xxxx xxxx xxxx xxxx xxxx xxxx : */
@@ -965,41 +989,22 @@
 		return INSN_GOOD_NO_SLOT;
 	}
 
-	/* SETEND : 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
-	/* CDP2   : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-	if ((insn & 0xffff00f0) == 0xf1010000 ||
-	    (insn & 0xff000010) == 0xfe000000) {
-		asi->insn[0] = insn;
-		asi->insn_handler = emulate_none;
-		return INSN_GOOD;
-	}
+	/* CPS   : 1111 0001 0000 xxx0 xxxx xxxx xx0x xxxx */
+	/* SETEND: 1111 0001 0000 0001 xxxx xxxx 0000 xxxx */
+
+	/* SRS   : 1111 100x x1x0 xxxx xxxx xxxx xxxx xxxx */
+	/* RFE   : 1111 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
 
+	/* Coprocessor instructions... */
 	/* MCRR2 : 1111 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
 	/* MRRC2 : 1111 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd != Rn) */
-	if ((insn & 0xffe00000) == 0xfc400000) {
-		insn &= 0xfff00fff;	/* Rn = r0 */
-		insn |= 0x00001000;	/* Rd = r1 */
-		asi->insn[0] = insn;
-		asi->insn_handler =
-			(insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
-		return INSN_GOOD;
-	}
-
-	/* LDC2 : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-	/* STC2 : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-	if ((insn & 0xfe000000) == 0xfc000000) {
-		insn &= 0xfff0ffff;      /* Rn = r0 */
-		asi->insn[0] = insn;
-		asi->insn_handler = emulate_ldcstc;
-		return INSN_GOOD;
-	}
+	/* LDC2  : 1111 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+	/* STC2  : 1111 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+	/* CDP2  : 1111 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+	/* MCR2  : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+	/* MRC2  : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
 
-	/* MCR2 : 1111 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-	/* MRC2 : 1111 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-	insn &= 0xffff0fff;	/* Rd = r0 */
-	asi->insn[0]      = insn;
-	asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
-	return INSN_GOOD;
+	return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1008,19 +1013,18 @@
 	/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx xxx0 xxxx */
 	if ((insn & 0x0f900010) == 0x01000000) {
 
-		/* BXJ  : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
-		/* MSR  : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
-		if ((insn & 0x0ff000f0) == 0x01200020 ||
-		    (insn & 0x0fb000f0) == 0x01200000)
-			return INSN_REJECTED;
-
-		/* MRS : cccc 0001 0x00 xxxx xxxx xxxx 0000 xxxx */
-		if ((insn & 0x0fb00010) == 0x01000000)
-			return prep_emulate_rd12(insn, asi);
+		/* MRS cpsr : cccc 0001 0000 xxxx xxxx xxxx 0000 xxxx */
+		if ((insn & 0x0ff000f0) == 0x01000000) {
+			if (is_r15(insn, 12))
+				return INSN_REJECTED;	/* Rd is PC */
+			asi->insn_handler = simulate_mrs;
+			return INSN_GOOD_NO_SLOT;
+		}
 
 		/* SMLALxy : cccc 0001 0100 xxxx xxxx xxxx 1xx0 xxxx */
 		if ((insn & 0x0ff00090) == 0x01400080)
-			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
+			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
+									asi);
 
 		/* SMULWy : cccc 0001 0010 xxxx xxxx xxxx 1x10 xxxx */
 		/* SMULxy : cccc 0001 0110 xxxx xxxx xxxx 1xx0 xxxx */
@@ -1029,24 +1033,29 @@
 			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
 
 		/* SMLAxy : cccc 0001 0000 xxxx xxxx xxxx 1xx0 xxxx : Q */
-		/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 0x00 xxxx : Q */
-		return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+		/* SMLAWy : cccc 0001 0010 xxxx xxxx xxxx 1x00 xxxx : Q */
+		if ((insn & 0x0ff00090) == 0x01000080 ||
+		    (insn & 0x0ff000b0) == 0x01200080)
+			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
 
+		/* BXJ      : cccc 0001 0010 xxxx xxxx xxxx 0010 xxxx */
+		/* MSR      : cccc 0001 0x10 xxxx xxxx xxxx 0000 xxxx */
+		/* MRS spsr : cccc 0001 0100 xxxx xxxx xxxx 0000 xxxx */
+
+		/* Other instruction encodings aren't yet defined */
+		return INSN_REJECTED;
 	}
 
 	/* cccc 0001 0xx0 xxxx xxxx xxxx xxxx 0xx1 xxxx */
 	else if ((insn & 0x0f900090) == 0x01000010) {
 
-		/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-		if ((insn & 0xfff000f0) == 0xe1200070)
-			return INSN_REJECTED;
-
 		/* BLX(2) : cccc 0001 0010 xxxx xxxx xxxx 0011 xxxx */
 		/* BX     : cccc 0001 0010 xxxx xxxx xxxx 0001 xxxx */
 		if ((insn & 0x0ff000d0) == 0x01200010) {
-			asi->insn[0] = truecc_insn(insn);
+			if ((insn & 0x0ff000ff) == 0x0120003f)
+				return INSN_REJECTED; /* BLX pc */
 			asi->insn_handler = simulate_blx2bx;
-			return INSN_GOOD;
+			return INSN_GOOD_NO_SLOT;
 		}
 
 		/* CLZ : cccc 0001 0110 xxxx xxxx xxxx 0001 xxxx */
@@ -1057,17 +1066,27 @@
 		/* QSUB    : cccc 0001 0010 xxxx xxxx xxxx 0101 xxxx :Q */
 		/* QDADD   : cccc 0001 0100 xxxx xxxx xxxx 0101 xxxx :Q */
 		/* QDSUB   : cccc 0001 0110 xxxx xxxx xxxx 0101 xxxx :Q */
-		return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+		if ((insn & 0x0f9000f0) == 0x01000050)
+			return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+
+		/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
+		/* SMC  : cccc 0001 0110 xxxx xxxx xxxx 0111 xxxx */
+
+		/* Other instruction encodings aren't yet defined */
+		return INSN_REJECTED;
 	}
 
 	/* cccc 0000 xxxx xxxx xxxx xxxx xxxx 1001 xxxx */
-	else if ((insn & 0x0f000090) == 0x00000090) {
+	else if ((insn & 0x0f0000f0) == 0x00000090) {
 
 		/* MUL    : cccc 0000 0000 xxxx xxxx xxxx 1001 xxxx :   */
 		/* MULS   : cccc 0000 0001 xxxx xxxx xxxx 1001 xxxx :cc */
 		/* MLA    : cccc 0000 0010 xxxx xxxx xxxx 1001 xxxx :   */
 		/* MLAS   : cccc 0000 0011 xxxx xxxx xxxx 1001 xxxx :cc */
 		/* UMAAL  : cccc 0000 0100 xxxx xxxx xxxx 1001 xxxx :   */
+		/* undef  : cccc 0000 0101 xxxx xxxx xxxx 1001 xxxx :   */
+		/* MLS    : cccc 0000 0110 xxxx xxxx xxxx 1001 xxxx :   */
+		/* undef  : cccc 0000 0111 xxxx xxxx xxxx 1001 xxxx :   */
 		/* UMULL  : cccc 0000 1000 xxxx xxxx xxxx 1001 xxxx :   */
 		/* UMULLS : cccc 0000 1001 xxxx xxxx xxxx 1001 xxxx :cc */
 		/* UMLAL  : cccc 0000 1010 xxxx xxxx xxxx 1001 xxxx :   */
@@ -1076,13 +1095,15 @@
 		/* SMULLS : cccc 0000 1101 xxxx xxxx xxxx 1001 xxxx :cc */
 		/* SMLAL  : cccc 0000 1110 xxxx xxxx xxxx 1001 xxxx :   */
 		/* SMLALS : cccc 0000 1111 xxxx xxxx xxxx 1001 xxxx :cc */
-		if ((insn & 0x0fe000f0) == 0x00000090) {
-		       return prep_emulate_rd16rs8rm0_wflags(insn, asi);
-		} else if  ((insn & 0x0fe000f0) == 0x00200090) {
-		       return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-		} else {
-		       return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
-		}
+		if ((insn & 0x00d00000) == 0x00500000)
+			return INSN_REJECTED;
+		else if ((insn & 0x00e00000) == 0x00000000)
+			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+		else if ((insn & 0x00a00000) == 0x00200000)
+			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+		else
+			return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn,
+									asi);
 	}
 
 	/* cccc 000x xxxx xxxx xxxx xxxx xxxx 1xx1 xxxx */
@@ -1090,23 +1111,45 @@
 
 		/* SWP   : cccc 0001 0000 xxxx xxxx xxxx 1001 xxxx */
 		/* SWPB  : cccc 0001 0100 xxxx xxxx xxxx 1001 xxxx */
-		/* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
-		/* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
+		/* ???   : cccc 0001 0x01 xxxx xxxx xxxx 1001 xxxx */
+		/* ???   : cccc 0001 0x10 xxxx xxxx xxxx 1001 xxxx */
+		/* ???   : cccc 0001 0x11 xxxx xxxx xxxx 1001 xxxx */
 		/* STREX : cccc 0001 1000 xxxx xxxx xxxx 1001 xxxx */
 		/* LDREX : cccc 0001 1001 xxxx xxxx xxxx 1001 xxxx */
+		/* STREXD: cccc 0001 1010 xxxx xxxx xxxx 1001 xxxx */
+		/* LDREXD: cccc 0001 1011 xxxx xxxx xxxx 1001 xxxx */
+		/* STREXB: cccc 0001 1100 xxxx xxxx xxxx 1001 xxxx */
+		/* LDREXB: cccc 0001 1101 xxxx xxxx xxxx 1001 xxxx */
+		/* STREXH: cccc 0001 1110 xxxx xxxx xxxx 1001 xxxx */
+		/* LDREXH: cccc 0001 1111 xxxx xxxx xxxx 1001 xxxx */
+
+		/* LDRD  : cccc 000x xxx0 xxxx xxxx xxxx 1101 xxxx */
+		/* STRD  : cccc 000x xxx0 xxxx xxxx xxxx 1111 xxxx */
 		/* LDRH  : cccc 000x xxx1 xxxx xxxx xxxx 1011 xxxx */
 		/* STRH  : cccc 000x xxx0 xxxx xxxx xxxx 1011 xxxx */
 		/* LDRSB : cccc 000x xxx1 xxxx xxxx xxxx 1101 xxxx */
 		/* LDRSH : cccc 000x xxx1 xxxx xxxx xxxx 1111 xxxx */
-		if ((insn & 0x0fb000f0) == 0x01000090) {
-			/* SWP/SWPB */
-			return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+		if ((insn & 0x0f0000f0) == 0x01000090) {
+			if ((insn & 0x0fb000f0) == 0x01000090) {
+				/* SWP/SWPB */
+				return prep_emulate_rd12rn16rm0_wflags(insn,
+									asi);
+			} else {
+				/* STREX/LDREX variants and unallocaed space */
+				return INSN_REJECTED;
+			}
+
 		} else if ((insn & 0x0e1000d0) == 0x00000d0) {
 			/* STRD/LDRD */
+			if ((insn & 0x0000e000) == 0x0000e000)
+				return INSN_REJECTED;	/* Rd is LR or PC */
+			if (is_writeback(insn) && is_r15(insn, 16))
+				return INSN_REJECTED;	/* Writeback to PC */
+
 			insn &= 0xfff00fff;
 			insn |= 0x00002000;	/* Rn = r0, Rd = r2 */
-			if (insn & (1 << 22)) {
-				/* I bit */
+			if (!(insn & (1 << 22))) {
+				/* Register index */
 				insn &= ~0xf;
 				insn |= 1;	/* Rm = r1 */
 			}
@@ -1116,6 +1159,9 @@
 			return INSN_GOOD;
 		}
 
+		/* LDRH/STRH/LDRSB/LDRSH */
+		if (is_r15(insn, 12))
+			return INSN_REJECTED;	/* Rd is PC */
 		return prep_emulate_ldr_str(insn, asi);
 	}
 
@@ -1123,7 +1169,7 @@
 
 	/*
 	 * ALU op with S bit and Rd == 15 :
-	 * 	cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
+	 *	cccc 000x xxx1 xxxx 1111 xxxx xxxx xxxx
 	 */
 	if ((insn & 0x0e10f000) == 0x0010f000)
 		return INSN_REJECTED;
@@ -1152,22 +1198,61 @@
 		insn |= 0x00000200;     /* Rs = r2 */
 	}
 	asi->insn[0] = insn;
-	asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
+
+	if ((insn & 0x0f900000) == 0x01100000) {
+		/*
+		 * TST : cccc 0001 0001 xxxx xxxx xxxx xxxx xxxx
+		 * TEQ : cccc 0001 0011 xxxx xxxx xxxx xxxx xxxx
+		 * CMP : cccc 0001 0101 xxxx xxxx xxxx xxxx xxxx
+		 * CMN : cccc 0001 0111 xxxx xxxx xxxx xxxx xxxx
+		 */
+		asi->insn_handler = emulate_alu_tests;
+	} else {
+		/* ALU ops which write to Rd */
+		asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
 				emulate_alu_rwflags : emulate_alu_rflags;
+	}
 	return INSN_GOOD;
 }
 
 static enum kprobe_insn __kprobes
 space_cccc_001x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	/* MOVW  : cccc 0011 0000 xxxx xxxx xxxx xxxx xxxx */
+	/* MOVT  : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx */
+	if ((insn & 0x0fb00000) == 0x03000000)
+		return prep_emulate_rd12_modify(insn, asi);
+
+	/* hints : cccc 0011 0010 0000 xxxx xxxx xxxx xxxx */
+	if ((insn & 0x0fff0000) == 0x03200000) {
+		unsigned op2 = insn & 0x000000ff;
+		if (op2 == 0x01 || op2 == 0x04) {
+			/* YIELD : cccc 0011 0010 0000 xxxx xxxx 0000 0001 */
+			/* SEV   : cccc 0011 0010 0000 xxxx xxxx 0000 0100 */
+			asi->insn[0] = insn;
+			asi->insn_handler = emulate_none;
+			return INSN_GOOD;
+		} else if (op2 <= 0x03) {
+			/* NOP   : cccc 0011 0010 0000 xxxx xxxx 0000 0000 */
+			/* WFE   : cccc 0011 0010 0000 xxxx xxxx 0000 0010 */
+			/* WFI   : cccc 0011 0010 0000 xxxx xxxx 0000 0011 */
+			/*
+			 * We make WFE and WFI true NOPs to avoid stalls due
+			 * to missing events whilst processing the probe.
+			 */
+			asi->insn_handler = emulate_nop;
+			return INSN_GOOD_NO_SLOT;
+		}
+		/* For DBG and unallocated hints it's safest to reject them */
+		return INSN_REJECTED;
+	}
+
 	/*
 	 * MSR   : cccc 0011 0x10 xxxx xxxx xxxx xxxx xxxx
-	 * Undef : cccc 0011 0100 xxxx xxxx xxxx xxxx xxxx
 	 * ALU op with S bit and Rd == 15 :
 	 *	   cccc 001x xxx1 xxxx 1111 xxxx xxxx xxxx
 	 */
 	if ((insn & 0x0fb00000) == 0x03200000 ||	/* MSR */
-	    (insn & 0x0ff00000) == 0x03400000 ||	/* Undef */
 	    (insn & 0x0e10f000) == 0x0210f000)		/* ALU s-bit, R15  */
 		return INSN_REJECTED;
 
@@ -1178,10 +1263,22 @@
 	 * *S (bit 20) updates condition codes
 	 * ADC/SBC/RSC reads the C flag
 	 */
-	insn &= 0xffff0fff;	/* Rd = r0 */
+	insn &= 0xfff00fff;	/* Rn = r0 and Rd = r0 */
 	asi->insn[0] = insn;
-	asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
+
+	if ((insn & 0x0f900000) == 0x03100000) {
+		/*
+		 * TST : cccc 0011 0001 xxxx xxxx xxxx xxxx xxxx
+		 * TEQ : cccc 0011 0011 xxxx xxxx xxxx xxxx xxxx
+		 * CMP : cccc 0011 0101 xxxx xxxx xxxx xxxx xxxx
+		 * CMN : cccc 0011 0111 xxxx xxxx xxxx xxxx xxxx
+		 */
+		asi->insn_handler = emulate_alu_tests_imm;
+	} else {
+		/* ALU ops which write to Rd */
+		asi->insn_handler = (insn & (1 << 20)) ?  /* S-bit */
 			emulate_alu_imm_rwflags : emulate_alu_imm_rflags;
+	}
 	return INSN_GOOD;
 }
 
@@ -1190,6 +1287,8 @@
 {
 	/* SEL : cccc 0110 1000 xxxx xxxx xxxx 1011 xxxx GE: !!! */
 	if ((insn & 0x0ff000f0) == 0x068000b0) {
+		if (is_r15(insn, 12))
+			return INSN_REJECTED;	/* Rd is PC */
 		insn &= 0xfff00ff0;	/* Rd = r0, Rn = r0 */
 		insn |= 0x00000001;	/* Rm = r1 */
 		asi->insn[0] = insn;
@@ -1203,6 +1302,8 @@
 	/* USAT16 : cccc 0110 1110 xxxx xxxx xxxx 0011 xxxx :Q */
 	if ((insn & 0x0fa00030) == 0x06a00010 ||
 	    (insn & 0x0fb000f0) == 0x06a00030) {
+		if (is_r15(insn, 12))
+			return INSN_REJECTED;	/* Rd is PC */
 		insn &= 0xffff0ff0;	/* Rd = r0, Rm = r0 */
 		asi->insn[0] = insn;
 		asi->insn_handler = emulate_sat;
@@ -1211,57 +1312,101 @@
 
 	/* REV    : cccc 0110 1011 xxxx xxxx xxxx 0011 xxxx */
 	/* REV16  : cccc 0110 1011 xxxx xxxx xxxx 1011 xxxx */
+	/* RBIT   : cccc 0110 1111 xxxx xxxx xxxx 0011 xxxx */
 	/* REVSH  : cccc 0110 1111 xxxx xxxx xxxx 1011 xxxx */
 	if ((insn & 0x0ff00070) == 0x06b00030 ||
-	    (insn & 0x0ff000f0) == 0x06f000b0)
+	    (insn & 0x0ff00070) == 0x06f00030)
 		return prep_emulate_rd12rm0(insn, asi);
 
+	/* ???       : cccc 0110 0000 xxxx xxxx xxxx xxx1 xxxx :   */
 	/* SADD16    : cccc 0110 0001 xxxx xxxx xxxx 0001 xxxx :GE */
 	/* SADDSUBX  : cccc 0110 0001 xxxx xxxx xxxx 0011 xxxx :GE */
 	/* SSUBADDX  : cccc 0110 0001 xxxx xxxx xxxx 0101 xxxx :GE */
 	/* SSUB16    : cccc 0110 0001 xxxx xxxx xxxx 0111 xxxx :GE */
 	/* SADD8     : cccc 0110 0001 xxxx xxxx xxxx 1001 xxxx :GE */
+	/* ???       : cccc 0110 0001 xxxx xxxx xxxx 1011 xxxx :   */
+	/* ???       : cccc 0110 0001 xxxx xxxx xxxx 1101 xxxx :   */
 	/* SSUB8     : cccc 0110 0001 xxxx xxxx xxxx 1111 xxxx :GE */
 	/* QADD16    : cccc 0110 0010 xxxx xxxx xxxx 0001 xxxx :   */
 	/* QADDSUBX  : cccc 0110 0010 xxxx xxxx xxxx 0011 xxxx :   */
 	/* QSUBADDX  : cccc 0110 0010 xxxx xxxx xxxx 0101 xxxx :   */
 	/* QSUB16    : cccc 0110 0010 xxxx xxxx xxxx 0111 xxxx :   */
 	/* QADD8     : cccc 0110 0010 xxxx xxxx xxxx 1001 xxxx :   */
+	/* ???       : cccc 0110 0010 xxxx xxxx xxxx 1011 xxxx :   */
+	/* ???       : cccc 0110 0010 xxxx xxxx xxxx 1101 xxxx :   */
 	/* QSUB8     : cccc 0110 0010 xxxx xxxx xxxx 1111 xxxx :   */
 	/* SHADD16   : cccc 0110 0011 xxxx xxxx xxxx 0001 xxxx :   */
 	/* SHADDSUBX : cccc 0110 0011 xxxx xxxx xxxx 0011 xxxx :   */
 	/* SHSUBADDX : cccc 0110 0011 xxxx xxxx xxxx 0101 xxxx :   */
 	/* SHSUB16   : cccc 0110 0011 xxxx xxxx xxxx 0111 xxxx :   */
 	/* SHADD8    : cccc 0110 0011 xxxx xxxx xxxx 1001 xxxx :   */
+	/* ???       : cccc 0110 0011 xxxx xxxx xxxx 1011 xxxx :   */
+	/* ???       : cccc 0110 0011 xxxx xxxx xxxx 1101 xxxx :   */
 	/* SHSUB8    : cccc 0110 0011 xxxx xxxx xxxx 1111 xxxx :   */
+	/* ???       : cccc 0110 0100 xxxx xxxx xxxx xxx1 xxxx :   */
 	/* UADD16    : cccc 0110 0101 xxxx xxxx xxxx 0001 xxxx :GE */
 	/* UADDSUBX  : cccc 0110 0101 xxxx xxxx xxxx 0011 xxxx :GE */
 	/* USUBADDX  : cccc 0110 0101 xxxx xxxx xxxx 0101 xxxx :GE */
 	/* USUB16    : cccc 0110 0101 xxxx xxxx xxxx 0111 xxxx :GE */
 	/* UADD8     : cccc 0110 0101 xxxx xxxx xxxx 1001 xxxx :GE */
+	/* ???       : cccc 0110 0101 xxxx xxxx xxxx 1011 xxxx :   */
+	/* ???       : cccc 0110 0101 xxxx xxxx xxxx 1101 xxxx :   */
 	/* USUB8     : cccc 0110 0101 xxxx xxxx xxxx 1111 xxxx :GE */
 	/* UQADD16   : cccc 0110 0110 xxxx xxxx xxxx 0001 xxxx :   */
 	/* UQADDSUBX : cccc 0110 0110 xxxx xxxx xxxx 0011 xxxx :   */
 	/* UQSUBADDX : cccc 0110 0110 xxxx xxxx xxxx 0101 xxxx :   */
 	/* UQSUB16   : cccc 0110 0110 xxxx xxxx xxxx 0111 xxxx :   */
 	/* UQADD8    : cccc 0110 0110 xxxx xxxx xxxx 1001 xxxx :   */
+	/* ???       : cccc 0110 0110 xxxx xxxx xxxx 1011 xxxx :   */
+	/* ???       : cccc 0110 0110 xxxx xxxx xxxx 1101 xxxx :   */
 	/* UQSUB8    : cccc 0110 0110 xxxx xxxx xxxx 1111 xxxx :   */
 	/* UHADD16   : cccc 0110 0111 xxxx xxxx xxxx 0001 xxxx :   */
 	/* UHADDSUBX : cccc 0110 0111 xxxx xxxx xxxx 0011 xxxx :   */
 	/* UHSUBADDX : cccc 0110 0111 xxxx xxxx xxxx 0101 xxxx :   */
 	/* UHSUB16   : cccc 0110 0111 xxxx xxxx xxxx 0111 xxxx :   */
 	/* UHADD8    : cccc 0110 0111 xxxx xxxx xxxx 1001 xxxx :   */
+	/* ???       : cccc 0110 0111 xxxx xxxx xxxx 1011 xxxx :   */
+	/* ???       : cccc 0110 0111 xxxx xxxx xxxx 1101 xxxx :   */
 	/* UHSUB8    : cccc 0110 0111 xxxx xxxx xxxx 1111 xxxx :   */
+	if ((insn & 0x0f800010) == 0x06000010) {
+		if ((insn & 0x00300000) == 0x00000000 ||
+		    (insn & 0x000000e0) == 0x000000a0 ||
+		    (insn & 0x000000e0) == 0x000000c0)
+			return INSN_REJECTED;	/* Unallocated space */
+		return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+	}
+
 	/* PKHBT     : cccc 0110 1000 xxxx xxxx xxxx x001 xxxx :   */
 	/* PKHTB     : cccc 0110 1000 xxxx xxxx xxxx x101 xxxx :   */
+	if ((insn & 0x0ff00030) == 0x06800010)
+		return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+
 	/* SXTAB16   : cccc 0110 1000 xxxx xxxx xxxx 0111 xxxx :   */
-	/* SXTB      : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
+	/* SXTB16    : cccc 0110 1000 1111 xxxx xxxx 0111 xxxx :   */
+	/* ???       : cccc 0110 1001 xxxx xxxx xxxx 0111 xxxx :   */
 	/* SXTAB     : cccc 0110 1010 xxxx xxxx xxxx 0111 xxxx :   */
+	/* SXTB      : cccc 0110 1010 1111 xxxx xxxx 0111 xxxx :   */
 	/* SXTAH     : cccc 0110 1011 xxxx xxxx xxxx 0111 xxxx :   */
+	/* SXTH      : cccc 0110 1011 1111 xxxx xxxx 0111 xxxx :   */
 	/* UXTAB16   : cccc 0110 1100 xxxx xxxx xxxx 0111 xxxx :   */
+	/* UXTB16    : cccc 0110 1100 1111 xxxx xxxx 0111 xxxx :   */
+	/* ???       : cccc 0110 1101 xxxx xxxx xxxx 0111 xxxx :   */
 	/* UXTAB     : cccc 0110 1110 xxxx xxxx xxxx 0111 xxxx :   */
+	/* UXTB      : cccc 0110 1110 1111 xxxx xxxx 0111 xxxx :   */
 	/* UXTAH     : cccc 0110 1111 xxxx xxxx xxxx 0111 xxxx :   */
-	return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+	/* UXTH      : cccc 0110 1111 1111 xxxx xxxx 0111 xxxx :   */
+	if ((insn & 0x0f8000f0) == 0x06800070) {
+		if ((insn & 0x00300000) == 0x00100000)
+			return INSN_REJECTED;	/* Unallocated space */
+
+		if ((insn & 0x000f0000) == 0x000f0000)
+			return prep_emulate_rd12rm0(insn, asi);
+		else
+			return prep_emulate_rd12rn16rm0_wflags(insn, asi);
+	}
+
+	/* Other instruction encodings aren't yet defined */
+	return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1271,29 +1416,49 @@
 	if ((insn & 0x0ff000f0) == 0x03f000f0)
 		return INSN_REJECTED;
 
-	/* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx */
-	/* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx */
-	if ((insn & 0x0ff000f0) == 0x07800010)
-		 return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
-
 	/* SMLALD : cccc 0111 0100 xxxx xxxx xxxx 00x1 xxxx */
 	/* SMLSLD : cccc 0111 0100 xxxx xxxx xxxx 01x1 xxxx */
 	if ((insn & 0x0ff00090) == 0x07400010)
 		return prep_emulate_rdhi16rdlo12rs8rm0_wflags(insn, asi);
 
 	/* SMLAD  : cccc 0111 0000 xxxx xxxx xxxx 00x1 xxxx :Q */
+	/* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
 	/* SMLSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :Q */
+	/* SMUSD  : cccc 0111 0000 xxxx 1111 xxxx 01x1 xxxx :  */
 	/* SMMLA  : cccc 0111 0101 xxxx xxxx xxxx 00x1 xxxx :  */
-	/* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
+	/* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
+	/* USADA8 : cccc 0111 1000 xxxx xxxx xxxx 0001 xxxx :  */
+	/* USAD8  : cccc 0111 1000 xxxx 1111 xxxx 0001 xxxx :  */
 	if ((insn & 0x0ff00090) == 0x07000010 ||
 	    (insn & 0x0ff000d0) == 0x07500010 ||
-	    (insn & 0x0ff000d0) == 0x075000d0)
+	    (insn & 0x0ff000f0) == 0x07800010) {
+
+		if ((insn & 0x0000f000) == 0x0000f000)
+			return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+		else
+			return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
+	}
+
+	/* SMMLS  : cccc 0111 0101 xxxx xxxx xxxx 11x1 xxxx :  */
+	if ((insn & 0x0ff000d0) == 0x075000d0)
 		return prep_emulate_rd16rn12rs8rm0_wflags(insn, asi);
 
-	/* SMUSD  : cccc 0111 0000 xxxx xxxx xxxx 01x1 xxxx :  */
-	/* SMUAD  : cccc 0111 0000 xxxx 1111 xxxx 00x1 xxxx :Q */
-	/* SMMUL  : cccc 0111 0101 xxxx 1111 xxxx 00x1 xxxx :  */
-	return prep_emulate_rd16rs8rm0_wflags(insn, asi);
+	/* SBFX   : cccc 0111 101x xxxx xxxx xxxx x101 xxxx :  */
+	/* UBFX   : cccc 0111 111x xxxx xxxx xxxx x101 xxxx :  */
+	if ((insn & 0x0fa00070) == 0x07a00050)
+		return prep_emulate_rd12rm0(insn, asi);
+
+	/* BFI    : cccc 0111 110x xxxx xxxx xxxx x001 xxxx :  */
+	/* BFC    : cccc 0111 110x xxxx xxxx xxxx x001 1111 :  */
+	if ((insn & 0x0fe00070) == 0x07c00010) {
+
+		if ((insn & 0x0000000f) == 0x0000000f)
+			return prep_emulate_rd12_modify(insn, asi);
+		else
+			return prep_emulate_rd12rn0_modify(insn, asi);
+	}
+
+	return INSN_REJECTED;
 }
 
 static enum kprobe_insn __kprobes
@@ -1307,6 +1472,10 @@
 	/* STRB  : cccc 01xx x1x0 xxxx xxxx xxxx xxxx xxxx */
 	/* STRBT : cccc 01x0 x110 xxxx xxxx xxxx xxxx xxxx */
 	/* STRT  : cccc 01x0 x010 xxxx xxxx xxxx xxxx xxxx */
+
+	if ((insn & 0x00500000) == 0x00500000 && is_r15(insn, 12))
+		return INSN_REJECTED;	/* LDRB into PC */
+
 	return prep_emulate_ldr_str(insn, asi);
 }
 
@@ -1321,10 +1490,9 @@
 
 	/* LDM(1) : cccc 100x x0x1 xxxx xxxx xxxx xxxx xxxx */
 	/* STM(1) : cccc 100x x0x0 xxxx xxxx xxxx xxxx xxxx */
-	asi->insn[0] = truecc_insn(insn);
 	asi->insn_handler = ((insn & 0x108000) == 0x008000) ? /* STM & R15 */
 				simulate_stm1_pc : simulate_ldm1stm1;
-	return INSN_GOOD;
+	return INSN_GOOD_NO_SLOT;
 }
 
 static enum kprobe_insn __kprobes
@@ -1332,58 +1500,117 @@
 {
 	/* B  : cccc 1010 xxxx xxxx xxxx xxxx xxxx xxxx */
 	/* BL : cccc 1011 xxxx xxxx xxxx xxxx xxxx xxxx */
-	asi->insn[0] = truecc_insn(insn);
 	asi->insn_handler = simulate_bbl;
-	return INSN_GOOD;
+	return INSN_GOOD_NO_SLOT;
 }
 
 static enum kprobe_insn __kprobes
-space_cccc_1100_010x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+space_cccc_11xx(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	/* Coprocessor instructions... */
 	/* MCRR : cccc 1100 0100 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
 	/* MRRC : cccc 1100 0101 xxxx xxxx xxxx xxxx xxxx : (Rd!=Rn) */
-	insn &= 0xfff00fff;
-	insn |= 0x00001000;	/* Rn = r0, Rd = r1 */
-	asi->insn[0] = insn;
-	asi->insn_handler = (insn & (1 << 20)) ? emulate_mrrc : emulate_mcrr;
-	return INSN_GOOD;
+	/* LDC  : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
+	/* STC  : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
+	/* CDP  : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
+	/* MCR  : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
+	/* MRC  : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
+
+	/* SVC  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
+
+	return INSN_REJECTED;
 }
 
-static enum kprobe_insn __kprobes
-space_cccc_110x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+static unsigned long __kprobes __check_eq(unsigned long cpsr)
 {
-	/* LDC : cccc 110x xxx1 xxxx xxxx xxxx xxxx xxxx */
-	/* STC : cccc 110x xxx0 xxxx xxxx xxxx xxxx xxxx */
-	insn &= 0xfff0ffff;	/* Rn = r0 */
-	asi->insn[0] = insn;
-	asi->insn_handler = emulate_ldcstc;
-	return INSN_GOOD;
+	return cpsr & PSR_Z_BIT;
 }
 
-static enum kprobe_insn __kprobes
-space_cccc_111x(kprobe_opcode_t insn, struct arch_specific_insn *asi)
+static unsigned long __kprobes __check_ne(unsigned long cpsr)
 {
-	/* BKPT : 1110 0001 0010 xxxx xxxx xxxx 0111 xxxx */
-	/* SWI  : cccc 1111 xxxx xxxx xxxx xxxx xxxx xxxx */
-	if ((insn & 0xfff000f0) == 0xe1200070 ||
-	    (insn & 0x0f000000) == 0x0f000000)
-		return INSN_REJECTED;
+	return (~cpsr) & PSR_Z_BIT;
+}
 
-	/* CDP : cccc 1110 xxxx xxxx xxxx xxxx xxx0 xxxx */
-	if ((insn & 0x0f000010) == 0x0e000000) {
-		asi->insn[0] = insn;
-		asi->insn_handler = emulate_none;
-		return INSN_GOOD;
-	}
+static unsigned long __kprobes __check_cs(unsigned long cpsr)
+{
+	return cpsr & PSR_C_BIT;
+}
 
-	/* MCR : cccc 1110 xxx0 xxxx xxxx xxxx xxx1 xxxx */
-	/* MRC : cccc 1110 xxx1 xxxx xxxx xxxx xxx1 xxxx */
-	insn &= 0xffff0fff;	/* Rd = r0 */
-	asi->insn[0] = insn;
-	asi->insn_handler = (insn & (1 << 20)) ? emulate_rd12 : emulate_ird12;
-	return INSN_GOOD;
+static unsigned long __kprobes __check_cc(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_mi(unsigned long cpsr)
+{
+	return cpsr & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_pl(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_vs(unsigned long cpsr)
+{
+	return cpsr & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_vc(unsigned long cpsr)
+{
+	return (~cpsr) & PSR_V_BIT;
+}
+
+static unsigned long __kprobes __check_hi(unsigned long cpsr)
+{
+	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+	return cpsr & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ls(unsigned long cpsr)
+{
+	cpsr &= ~(cpsr >> 1); /* PSR_C_BIT &= ~PSR_Z_BIT */
+	return (~cpsr) & PSR_C_BIT;
+}
+
+static unsigned long __kprobes __check_ge(unsigned long cpsr)
+{
+	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	return (~cpsr) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_lt(unsigned long cpsr)
+{
+	cpsr ^= (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	return cpsr & PSR_N_BIT;
 }
 
+static unsigned long __kprobes __check_gt(unsigned long cpsr)
+{
+	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
+	return (~temp) & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_le(unsigned long cpsr)
+{
+	unsigned long temp = cpsr ^ (cpsr << 3); /* PSR_N_BIT ^= PSR_V_BIT */
+	temp |= (cpsr << 1);			 /* PSR_N_BIT |= PSR_Z_BIT */
+	return temp & PSR_N_BIT;
+}
+
+static unsigned long __kprobes __check_al(unsigned long cpsr)
+{
+	return true;
+}
+
+static kprobe_check_cc * const condition_checks[16] = {
+	&__check_eq, &__check_ne, &__check_cs, &__check_cc,
+	&__check_mi, &__check_pl, &__check_vs, &__check_vc,
+	&__check_hi, &__check_ls, &__check_ge, &__check_lt,
+	&__check_gt, &__check_le, &__check_al, &__check_al
+};
+
 /* Return:
  *   INSN_REJECTED     If instruction is one not allowed to kprobe,
  *   INSN_GOOD         If instruction is supported and uses instruction slot,
@@ -1399,133 +1626,45 @@
 enum kprobe_insn __kprobes
 arm_kprobe_decode_insn(kprobe_opcode_t insn, struct arch_specific_insn *asi)
 {
+	asi->insn_check_cc = condition_checks[insn>>28];
 	asi->insn[1] = KPROBE_RETURN_INSTRUCTION;
 
-	if ((insn & 0xf0000000) == 0xf0000000) {
+	if ((insn & 0xf0000000) == 0xf0000000)
 
 		return space_1111(insn, asi);
 
-	} else if ((insn & 0x0e000000) == 0x00000000) {
+	else if ((insn & 0x0e000000) == 0x00000000)
 
 		return space_cccc_000x(insn, asi);
 
-	} else if ((insn & 0x0e000000) == 0x02000000) {
+	else if ((insn & 0x0e000000) == 0x02000000)
 
 		return space_cccc_001x(insn, asi);
 
-	} else if ((insn & 0x0f000010) == 0x06000010) {
+	else if ((insn & 0x0f000010) == 0x06000010)
 
 		return space_cccc_0110__1(insn, asi);
 
-	} else if ((insn & 0x0f000010) == 0x07000010) {
+	else if ((insn & 0x0f000010) == 0x07000010)
 
 		return space_cccc_0111__1(insn, asi);
 
-	} else if ((insn & 0x0c000000) == 0x04000000) {
+	else if ((insn & 0x0c000000) == 0x04000000)
 
 		return space_cccc_01xx(insn, asi);
 
-	} else if ((insn & 0x0e000000) == 0x08000000) {
+	else if ((insn & 0x0e000000) == 0x08000000)
 
 		return space_cccc_100x(insn, asi);
 
-	} else if ((insn & 0x0e000000) == 0x0a000000) {
+	else if ((insn & 0x0e000000) == 0x0a000000)
 
 		return space_cccc_101x(insn, asi);
 
-	} else if ((insn & 0x0fe00000) == 0x0c400000) {
-
-		return space_cccc_1100_010x(insn, asi);
-
-	} else if ((insn & 0x0e000000) == 0x0c000000) {
-
-		return space_cccc_110x(insn, asi);
-
-	}
-
-	return space_cccc_111x(insn, asi);
+	return space_cccc_11xx(insn, asi);
 }
 
 void __init arm_kprobe_decode_init(void)
 {
 	find_str_pc_offset();
 }
-
-
-/*
- * All ARM instructions listed below.
- *
- * Instructions and their general purpose registers are given.
- * If a particular register may not use R15, it is prefixed with a "!".
- * If marked with a "*" means the value returned by reading R15
- * is implementation defined.
- *
- * ADC/ADD/AND/BIC/CMN/CMP/EOR/MOV/MVN/ORR/RSB/RSC/SBC/SUB/TEQ
- *     TST: Rd, Rn, Rm, !Rs
- * BX: Rm
- * BLX(2): !Rm
- * BX: Rm (R15 legal, but discouraged)
- * BXJ: !Rm,
- * CLZ: !Rd, !Rm
- * CPY: Rd, Rm
- * LDC/2,STC/2 immediate offset & unindex: Rn
- * LDC/2,STC/2 immediate pre/post-indexed: !Rn
- * LDM(1/3): !Rn, register_list
- * LDM(2): !Rn, !register_list
- * LDR,STR,PLD immediate offset: Rd, Rn
- * LDR,STR,PLD register offset: Rd, Rn, !Rm
- * LDR,STR,PLD scaled register offset: Rd, !Rn, !Rm
- * LDR,STR immediate pre/post-indexed: Rd, !Rn
- * LDR,STR register pre/post-indexed: Rd, !Rn, !Rm
- * LDR,STR scaled register pre/post-indexed: Rd, !Rn, !Rm
- * LDRB,STRB immediate offset: !Rd, Rn
- * LDRB,STRB register offset: !Rd, Rn, !Rm
- * LDRB,STRB scaled register offset: !Rd, !Rn, !Rm
- * LDRB,STRB immediate pre/post-indexed: !Rd, !Rn
- * LDRB,STRB register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRB,STRB scaled register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRT,LDRBT,STRBT immediate pre/post-indexed: !Rd, !Rn
- * LDRT,LDRBT,STRBT register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRT,LDRBT,STRBT scaled register pre/post-indexed: !Rd, !Rn, !Rm
- * LDRH/SH/SB/D,STRH/SH/SB/D immediate offset: !Rd, Rn
- * LDRH/SH/SB/D,STRH/SH/SB/D register offset: !Rd, Rn, !Rm
- * LDRH/SH/SB/D,STRH/SH/SB/D immediate pre/post-indexed: !Rd, !Rn
- * LDRH/SH/SB/D,STRH/SH/SB/D register pre/post-indexed: !Rd, !Rn, !Rm
- * LDREX: !Rd, !Rn
- * MCR/2: !Rd
- * MCRR/2,MRRC/2: !Rd, !Rn
- * MLA: !Rd, !Rn, !Rm, !Rs
- * MOV: Rd
- * MRC/2: !Rd (if Rd==15, only changes cond codes, not the register)
- * MRS,MSR: !Rd
- * MUL: !Rd, !Rm, !Rs
- * PKH{BT,TB}: !Rd, !Rn, !Rm
- * QDADD,[U]QADD/16/8/SUBX: !Rd, !Rm, !Rn
- * QDSUB,[U]QSUB/16/8/ADDX: !Rd, !Rm, !Rn
- * REV/16/SH: !Rd, !Rm
- * RFE: !Rn
- * {S,U}[H]ADD{16,8,SUBX},{S,U}[H]SUB{16,8,ADDX}: !Rd, !Rn, !Rm
- * SEL: !Rd, !Rn, !Rm
- * SMLA<x><y>,SMLA{D,W<y>},SMLSD,SMML{A,S}: !Rd, !Rn, !Rm, !Rs
- * SMLAL<x><y>,SMLA{D,LD},SMLSLD,SMMULL,SMULW<y>: !RdHi, !RdLo, !Rm, !Rs
- * SMMUL,SMUAD,SMUL<x><y>,SMUSD: !Rd, !Rm, !Rs
- * SSAT/16: !Rd, !Rm
- * STM(1/2): !Rn, register_list* (R15 in reg list not recommended)
- * STRT immediate pre/post-indexed: Rd*, !Rn
- * STRT register pre/post-indexed: Rd*, !Rn, !Rm
- * STRT scaled register pre/post-indexed: Rd*, !Rn, !Rm
- * STREX: !Rd, !Rn, !Rm
- * SWP/B: !Rd, !Rn, !Rm
- * {S,U}XTA{B,B16,H}: !Rd, !Rn, !Rm
- * {S,U}XT{B,B16,H}: !Rd, !Rm
- * UM{AA,LA,UL}L: !RdHi, !RdLo, !Rm, !Rs
- * USA{D8,A8,T,T16}: !Rd, !Rm, !Rs
- *
- * May transfer control by writing R15 (possible mode changes or alternate
- * mode accesses marked by "*"):
- * ALU op (* with s-bit), B, BL, BKPT, BLX(1/2), BX, BXJ, CPS*, CPY,
- * LDM(1), LDM(2/3)*, LDR, MOV, RFE*, SWI*
- *
- * Instructions that do not take general registers, nor transfer control:
- * CDP/2, SETEND, SRS*
- */
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/machine_kexec.c linux-libre-2.6.39-gnu/arch/arm/kernel/machine_kexec.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/machine_kexec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/machine_kexec.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,6 +75,11 @@
 	printk(KERN_INFO "Loading crashdump kernel...\n");
 }
 
+/*
+ * Function pointer to optional machine-specific reinitialization
+ */
+void (*kexec_reinit)(void);
+
 void machine_kexec(struct kimage *image)
 {
 	unsigned long page_list;
@@ -104,6 +109,8 @@
 			   (unsigned long) reboot_code_buffer + KEXEC_CONTROL_PAGE_SIZE);
 	printk(KERN_INFO "Bye!\n");
 
+	if (kexec_reinit)
+		kexec_reinit();
 	local_irq_disable();
 	local_fiq_disable();
 	setup_mm_for_reboot(0); /* mode is not used, so just pass 0*/
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/Makefile linux-libre-2.6.39-gnu/arch/arm/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 obj-$(CONFIG_ARTHUR)		+= arthur.o
 obj-$(CONFIG_ISA_DMA)		+= dma-isa.o
 obj-$(CONFIG_PCI)		+= bios32.o isa.o
+obj-$(CONFIG_PM_SLEEP)		+= sleep.o
 obj-$(CONFIG_HAVE_SCHED_CLOCK)	+= sched_clock.o
 obj-$(CONFIG_SMP)		+= smp.o smp_tlb.o
 obj-$(CONFIG_HAVE_ARM_SCU)	+= smp_scu.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/module.c linux-libre-2.6.39-gnu/arch/arm/kernel/module.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/module.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,6 +76,7 @@
 	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
 		unsigned long loc;
 		Elf32_Sym *sym;
+		const char *symname;
 		s32 offset;
 #ifdef CONFIG_THUMB2_KERNEL
 		u32 upper, lower, sign, j1, j2;
@@ -83,18 +84,18 @@
 
 		offset = ELF32_R_SYM(rel->r_info);
 		if (offset < 0 || offset > (symsec->sh_size / sizeof(Elf32_Sym))) {
-			printk(KERN_ERR "%s: bad relocation, section %d reloc %d\n",
+			pr_err("%s: section %u reloc %u: bad relocation sym offset\n",
 				module->name, relindex, i);
 			return -ENOEXEC;
 		}
 
 		sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
+		symname = strtab + sym->st_name;
 
 		if (rel->r_offset < 0 || rel->r_offset > dstsec->sh_size - sizeof(u32)) {
-			printk(KERN_ERR "%s: out of bounds relocation, "
-				"section %d reloc %d offset %d size %d\n",
-				module->name, relindex, i, rel->r_offset,
-				dstsec->sh_size);
+			pr_err("%s: section %u reloc %u sym '%s': out of bounds relocation, offset %d size %u\n",
+			       module->name, relindex, i, symname,
+			       rel->r_offset, dstsec->sh_size);
 			return -ENOEXEC;
 		}
 
@@ -120,10 +121,10 @@
 			if (offset & 3 ||
 			    offset <= (s32)0xfe000000 ||
 			    offset >= (s32)0x02000000) {
-				printk(KERN_ERR
-				       "%s: relocation out of range, section "
-				       "%d reloc %d sym '%s'\n", module->name,
-				       relindex, i, strtab + sym->st_name);
+				pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
+				       module->name, relindex, i, symname,
+				       ELF32_R_TYPE(rel->r_info), loc,
+				       sym->st_value);
 				return -ENOEXEC;
 			}
 
@@ -196,10 +197,10 @@
 			if (!(offset & 1) ||
 			    offset <= (s32)0xff000000 ||
 			    offset >= (s32)0x01000000) {
-				printk(KERN_ERR
-				       "%s: relocation out of range, section "
-				       "%d reloc %d sym '%s'\n", module->name,
-				       relindex, i, strtab + sym->st_name);
+				pr_err("%s: section %u reloc %u sym '%s': relocation %u out of range (%#lx -> %#x)\n",
+				       module->name, relindex, i, symname,
+				       ELF32_R_TYPE(rel->r_info), loc,
+				       sym->st_value);
 				return -ENOEXEC;
 			}
 
@@ -282,12 +283,13 @@
 	return NULL;
 }
 
+extern void fixup_pv_table(const void *, unsigned long);
 extern void fixup_smp(const void *, unsigned long);
 
 int module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
 		    struct module *mod)
 {
-	const Elf_Shdr * __maybe_unused s = NULL;
+	const Elf_Shdr *s = NULL;
 #ifdef CONFIG_ARM_UNWIND
 	const char *secstrs = (void *)hdr + sechdrs[hdr->e_shstrndx].sh_offset;
 	const Elf_Shdr *sechdrs_end = sechdrs + hdr->e_shnum;
@@ -332,6 +334,11 @@
 					         maps[i].txt_sec->sh_addr,
 					         maps[i].txt_sec->sh_size);
 #endif
+#ifdef CONFIG_ARM_PATCH_PHYS_VIRT
+	s = find_mod_section(hdr, sechdrs, ".pv_table");
+	if (s)
+		fixup_pv_table((void *)s->sh_addr, s->sh_size);
+#endif
 	s = find_mod_section(hdr, sechdrs, ".alt.smp.init");
 	if (s && !is_smp())
 		fixup_smp((void *)s->sh_addr, s->sh_size);
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event.c linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event.c	2011-05-19 00:06:34.000000000 -0400
@@ -79,6 +79,7 @@
 	void		(*write_counter)(int idx, u32 val);
 	void		(*start)(void);
 	void		(*stop)(void);
+	void		(*reset)(void *);
 	const unsigned	(*cache_map)[PERF_COUNT_HW_CACHE_MAX]
 				    [PERF_COUNT_HW_CACHE_OP_MAX]
 				    [PERF_COUNT_HW_CACHE_RESULT_MAX];
@@ -204,11 +205,9 @@
 static u64
 armpmu_event_update(struct perf_event *event,
 		    struct hw_perf_event *hwc,
-		    int idx)
+		    int idx, int overflow)
 {
-	int shift = 64 - 32;
-	s64 prev_raw_count, new_raw_count;
-	u64 delta;
+	u64 delta, prev_raw_count, new_raw_count;
 
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
@@ -218,8 +217,13 @@
 			     new_raw_count) != prev_raw_count)
 		goto again;
 
-	delta = (new_raw_count << shift) - (prev_raw_count << shift);
-	delta >>= shift;
+	new_raw_count &= armpmu->max_period;
+	prev_raw_count &= armpmu->max_period;
+
+	if (overflow)
+		delta = armpmu->max_period - prev_raw_count + new_raw_count + 1;
+	else
+		delta = new_raw_count - prev_raw_count;
 
 	local64_add(delta, &event->count);
 	local64_sub(delta, &hwc->period_left);
@@ -236,7 +240,7 @@
 	if (hwc->idx < 0)
 		return;
 
-	armpmu_event_update(event, hwc, hwc->idx);
+	armpmu_event_update(event, hwc, hwc->idx, 0);
 }
 
 static void
@@ -254,7 +258,7 @@
 	if (!(hwc->state & PERF_HES_STOPPED)) {
 		armpmu->disable(hwc, hwc->idx);
 		barrier(); /* why? */
-		armpmu_event_update(event, hwc, hwc->idx);
+		armpmu_event_update(event, hwc, hwc->idx, 0);
 		hwc->state |= PERF_HES_STOPPED | PERF_HES_UPTODATE;
 	}
 }
@@ -377,9 +381,18 @@
 	return 0;
 }
 
+static irqreturn_t armpmu_platform_irq(int irq, void *dev)
+{
+	struct arm_pmu_platdata *plat = dev_get_platdata(&pmu_device->dev);
+
+	return plat->handle_irq(irq, dev, armpmu->handle_irq);
+}
+
 static int
 armpmu_reserve_hardware(void)
 {
+	struct arm_pmu_platdata *plat;
+	irq_handler_t handle_irq;
 	int i, err = -ENODEV, irq;
 
 	pmu_device = reserve_pmu(ARM_PMU_DEVICE_CPU);
@@ -390,6 +403,12 @@
 
 	init_pmu(ARM_PMU_DEVICE_CPU);
 
+	plat = dev_get_platdata(&pmu_device->dev);
+	if (plat && plat->handle_irq)
+		handle_irq = armpmu_platform_irq;
+	else
+		handle_irq = armpmu->handle_irq;
+
 	if (pmu_device->num_resources < 1) {
 		pr_err("no irqs for PMUs defined\n");
 		return -ENODEV;
@@ -400,7 +419,7 @@
 		if (irq < 0)
 			continue;
 
-		err = request_irq(irq, armpmu->handle_irq,
+		err = request_irq(irq, handle_irq,
 				  IRQF_DISABLED | IRQF_NOBALANCING,
 				  "armpmu", NULL);
 		if (err) {
@@ -609,6 +628,19 @@
 #include "perf_event_v6.c"
 #include "perf_event_v7.c"
 
+/*
+ * Ensure the PMU has sane values out of reset.
+ * This requires SMP to be available, so exists as a separate initcall.
+ */
+static int __init
+armpmu_reset(void)
+{
+	if (armpmu && armpmu->reset)
+		return on_each_cpu(armpmu->reset, NULL, 1);
+	return 0;
+}
+arch_initcall(armpmu_reset);
+
 static int __init
 init_hw_perf_events(void)
 {
@@ -714,7 +746,8 @@
 
 	tail = (struct frame_tail __user *)regs->ARM_fp - 1;
 
-	while (tail && !((unsigned long)tail & 0x3))
+	while ((entry->nr < PERF_MAX_STACK_DEPTH) &&
+	       tail && !((unsigned long)tail & 0x3))
 		tail = user_backtrace(tail, entry);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event_v6.c linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event_v6.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event_v6.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event_v6.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
  * enable the interrupt.
  */
 
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 enum armv6_perf_types {
 	ARMV6_PERFCTR_ICACHE_MISS	    = 0x0,
 	ARMV6_PERFCTR_IBUF_STALL	    = 0x1,
@@ -474,7 +474,7 @@
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event, hwc, idx, 1);
 		data.period = event->hw.last_period;
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
@@ -669,4 +669,4 @@
 {
 	return NULL;
 }
-#endif	/* CONFIG_CPU_V6 */
+#endif	/* CONFIG_CPU_V6 || CONFIG_CPU_V6K */
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event_v7.c linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event_v7.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event_v7.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event_v7.c	2011-05-19 00:06:34.000000000 -0400
@@ -466,6 +466,7 @@
 static inline void armv7_pmnc_write(unsigned long val)
 {
 	val &= ARMV7_PMNC_MASK;
+	isb();
 	asm volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(val));
 }
 
@@ -502,6 +503,7 @@
 
 	val = (idx - ARMV7_EVENT_CNT_TO_CNTx) & ARMV7_SELECT_MASK;
 	asm volatile("mcr p15, 0, %0, c9, c12, 5" : : "r" (val));
+	isb();
 
 	return idx;
 }
@@ -780,7 +782,7 @@
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event, hwc, idx, 1);
 		data.period = event->hw.last_period;
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
@@ -847,6 +849,18 @@
 	}
 }
 
+static void armv7pmu_reset(void *info)
+{
+	u32 idx, nb_cnt = armpmu->num_events;
+
+	/* The counter and interrupt enable registers are unknown at reset. */
+	for (idx = 1; idx < nb_cnt; ++idx)
+		armv7pmu_disable_event(NULL, idx);
+
+	/* Initialize & Reset PMNC: C and P bits */
+	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
+}
+
 static struct arm_pmu armv7pmu = {
 	.handle_irq		= armv7pmu_handle_irq,
 	.enable			= armv7pmu_enable_event,
@@ -856,17 +870,15 @@
 	.get_event_idx		= armv7pmu_get_event_idx,
 	.start			= armv7pmu_start,
 	.stop			= armv7pmu_stop,
+	.reset			= armv7pmu_reset,
 	.raw_event_mask		= 0xFF,
 	.max_period		= (1LLU << 32) - 1,
 };
 
-static u32 __init armv7_reset_read_pmnc(void)
+static u32 __init armv7_read_num_pmnc_events(void)
 {
 	u32 nb_cnt;
 
-	/* Initialize & Reset PMNC: C and P bits */
-	armv7_pmnc_write(ARMV7_PMNC_P | ARMV7_PMNC_C);
-
 	/* Read the nb of CNTx counters supported from PMNC */
 	nb_cnt = (armv7_pmnc_read() >> ARMV7_PMNC_N_SHIFT) & ARMV7_PMNC_N_MASK;
 
@@ -880,7 +892,7 @@
 	armv7pmu.name		= "ARMv7 Cortex-A8";
 	armv7pmu.cache_map	= &armv7_a8_perf_cache_map;
 	armv7pmu.event_map	= &armv7_a8_perf_map;
-	armv7pmu.num_events	= armv7_reset_read_pmnc();
+	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 
@@ -890,7 +902,7 @@
 	armv7pmu.name		= "ARMv7 Cortex-A9";
 	armv7pmu.cache_map	= &armv7_a9_perf_cache_map;
 	armv7pmu.event_map	= &armv7_a9_perf_map;
-	armv7pmu.num_events	= armv7_reset_read_pmnc();
+	armv7pmu.num_events	= armv7_read_num_pmnc_events();
 	return &armv7pmu;
 }
 #else
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event_xscale.c linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event_xscale.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/perf_event_xscale.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/perf_event_xscale.c	2011-05-19 00:06:34.000000000 -0400
@@ -246,7 +246,7 @@
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event, hwc, idx, 1);
 		data.period = event->hw.last_period;
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
@@ -578,7 +578,7 @@
 			continue;
 
 		hwc = &event->hw;
-		armpmu_event_update(event, hwc, idx);
+		armpmu_event_update(event, hwc, idx, 1);
 		data.period = event->hw.last_period;
 		if (!armpmu_event_set_period(event, hwc, idx))
 			continue;
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/process.c linux-libre-2.6.39-gnu/arch/arm/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -372,6 +372,8 @@
 	if (clone_flags & CLONE_SETTLS)
 		thread->tp_value = regs->ARM_r3;
 
+	thread_notify(THREAD_NOTIFY_COPY, thread);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/arm/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,8 +26,6 @@
 #include <asm/system.h>
 #include <asm/traps.h>
 
-#include "ptrace.h"
-
 #define REG_PC	15
 #define REG_PSR	16
 /*
@@ -184,389 +182,12 @@
 	return ret;
 }
 
-static inline int
-read_u32(struct task_struct *task, unsigned long addr, u32 *res)
-{
-	int ret;
-
-	ret = access_process_vm(task, addr, res, sizeof(*res), 0);
-
-	return ret == sizeof(*res) ? 0 : -EIO;
-}
-
-static inline int
-read_instr(struct task_struct *task, unsigned long addr, u32 *res)
-{
-	int ret;
-
-	if (addr & 1) {
-		u16 val;
-		ret = access_process_vm(task, addr & ~1, &val, sizeof(val), 0);
-		ret = ret == sizeof(val) ? 0 : -EIO;
-		*res = val;
-	} else {
-		u32 val;
-		ret = access_process_vm(task, addr & ~3, &val, sizeof(val), 0);
-		ret = ret == sizeof(val) ? 0 : -EIO;
-		*res = val;
-	}
-	return ret;
-}
-
-/*
- * Get value of register `rn' (in the instruction)
- */
-static unsigned long
-ptrace_getrn(struct task_struct *child, unsigned long insn)
-{
-	unsigned int reg = (insn >> 16) & 15;
-	unsigned long val;
-
-	val = get_user_reg(child, reg);
-	if (reg == 15)
-		val += 8;
-
-	return val;
-}
-
-/*
- * Get value of operand 2 (in an ALU instruction)
- */
-static unsigned long
-ptrace_getaluop2(struct task_struct *child, unsigned long insn)
-{
-	unsigned long val;
-	int shift;
-	int type;
-
-	if (insn & 1 << 25) {
-		val = insn & 255;
-		shift = (insn >> 8) & 15;
-		type = 3;
-	} else {
-		val = get_user_reg (child, insn & 15);
-
-		if (insn & (1 << 4))
-			shift = (int)get_user_reg (child, (insn >> 8) & 15);
-		else
-			shift = (insn >> 7) & 31;
-
-		type = (insn >> 5) & 3;
-	}
-
-	switch (type) {
-	case 0:	val <<= shift;	break;
-	case 1:	val >>= shift;	break;
-	case 2:
-		val = (((signed long)val) >> shift);
-		break;
-	case 3:
- 		val = (val >> shift) | (val << (32 - shift));
-		break;
-	}
-	return val;
-}
-
-/*
- * Get value of operand 2 (in a LDR instruction)
- */
-static unsigned long
-ptrace_getldrop2(struct task_struct *child, unsigned long insn)
-{
-	unsigned long val;
-	int shift;
-	int type;
-
-	val = get_user_reg(child, insn & 15);
-	shift = (insn >> 7) & 31;
-	type = (insn >> 5) & 3;
-
-	switch (type) {
-	case 0:	val <<= shift;	break;
-	case 1:	val >>= shift;	break;
-	case 2:
-		val = (((signed long)val) >> shift);
-		break;
-	case 3:
- 		val = (val >> shift) | (val << (32 - shift));
-		break;
-	}
-	return val;
-}
-
-#define OP_MASK	0x01e00000
-#define OP_AND	0x00000000
-#define OP_EOR	0x00200000
-#define OP_SUB	0x00400000
-#define OP_RSB	0x00600000
-#define OP_ADD	0x00800000
-#define OP_ADC	0x00a00000
-#define OP_SBC	0x00c00000
-#define OP_RSC	0x00e00000
-#define OP_ORR	0x01800000
-#define OP_MOV	0x01a00000
-#define OP_BIC	0x01c00000
-#define OP_MVN	0x01e00000
-
-static unsigned long
-get_branch_address(struct task_struct *child, unsigned long pc, unsigned long insn)
-{
-	u32 alt = 0;
-
-	switch (insn & 0x0e000000) {
-	case 0x00000000:
-	case 0x02000000: {
-		/*
-		 * data processing
-		 */
-		long aluop1, aluop2, ccbit;
-
-	        if ((insn & 0x0fffffd0) == 0x012fff10) {
-		        /*
-			 * bx or blx
-			 */
-			alt = get_user_reg(child, insn & 15);
-			break;
-		}
-
-
-		if ((insn & 0xf000) != 0xf000)
-			break;
-
-		aluop1 = ptrace_getrn(child, insn);
-		aluop2 = ptrace_getaluop2(child, insn);
-		ccbit  = get_user_reg(child, REG_PSR) & PSR_C_BIT ? 1 : 0;
-
-		switch (insn & OP_MASK) {
-		case OP_AND: alt = aluop1 & aluop2;		break;
-		case OP_EOR: alt = aluop1 ^ aluop2;		break;
-		case OP_SUB: alt = aluop1 - aluop2;		break;
-		case OP_RSB: alt = aluop2 - aluop1;		break;
-		case OP_ADD: alt = aluop1 + aluop2;		break;
-		case OP_ADC: alt = aluop1 + aluop2 + ccbit;	break;
-		case OP_SBC: alt = aluop1 - aluop2 + ccbit;	break;
-		case OP_RSC: alt = aluop2 - aluop1 + ccbit;	break;
-		case OP_ORR: alt = aluop1 | aluop2;		break;
-		case OP_MOV: alt = aluop2;			break;
-		case OP_BIC: alt = aluop1 & ~aluop2;		break;
-		case OP_MVN: alt = ~aluop2;			break;
-		}
-		break;
-	}
-
-	case 0x04000000:
-	case 0x06000000:
-		/*
-		 * ldr
-		 */
-		if ((insn & 0x0010f000) == 0x0010f000) {
-			unsigned long base;
-
-			base = ptrace_getrn(child, insn);
-			if (insn & 1 << 24) {
-				long aluop2;
-
-				if (insn & 0x02000000)
-					aluop2 = ptrace_getldrop2(child, insn);
-				else
-					aluop2 = insn & 0xfff;
-
-				if (insn & 1 << 23)
-					base += aluop2;
-				else
-					base -= aluop2;
-			}
-			read_u32(child, base, &alt);
-		}
-		break;
-
-	case 0x08000000:
-		/*
-		 * ldm
-		 */
-		if ((insn & 0x00108000) == 0x00108000) {
-			unsigned long base;
-			unsigned int nr_regs;
-
-			if (insn & (1 << 23)) {
-				nr_regs = hweight16(insn & 65535) << 2;
-
-				if (!(insn & (1 << 24)))
-					nr_regs -= 4;
-			} else {
-				if (insn & (1 << 24))
-					nr_regs = -4;
-				else
-					nr_regs = 0;
-			}
-
-			base = ptrace_getrn(child, insn);
-
-			read_u32(child, base + nr_regs, &alt);
-			break;
-		}
-		break;
-
-	case 0x0a000000: {
-		/*
-		 * bl or b
-		 */
-		signed long displ;
-		/* It's a branch/branch link: instead of trying to
-		 * figure out whether the branch will be taken or not,
-		 * we'll put a breakpoint at both locations.  This is
-		 * simpler, more reliable, and probably not a whole lot
-		 * slower than the alternative approach of emulating the
-		 * branch.
-		 */
-		displ = (insn & 0x00ffffff) << 8;
-		displ = (displ >> 6) + 8;
-		if (displ != 0 && displ != 4)
-			alt = pc + displ;
-	    }
-	    break;
-	}
-
-	return alt;
-}
-
-static int
-swap_insn(struct task_struct *task, unsigned long addr,
-	  void *old_insn, void *new_insn, int size)
-{
-	int ret;
-
-	ret = access_process_vm(task, addr, old_insn, size, 0);
-	if (ret == size)
-		ret = access_process_vm(task, addr, new_insn, size, 1);
-	return ret;
-}
-
-static void
-add_breakpoint(struct task_struct *task, struct debug_info *dbg, unsigned long addr)
-{
-	int nr = dbg->nsaved;
-
-	if (nr < 2) {
-		u32 new_insn = BREAKINST_ARM;
-		int res;
-
-		res = swap_insn(task, addr, &dbg->bp[nr].insn, &new_insn, 4);
-
-		if (res == 4) {
-			dbg->bp[nr].address = addr;
-			dbg->nsaved += 1;
-		}
-	} else
-		printk(KERN_ERR "ptrace: too many breakpoints\n");
-}
-
-/*
- * Clear one breakpoint in the user program.  We copy what the hardware
- * does and use bit 0 of the address to indicate whether this is a Thumb
- * breakpoint or an ARM breakpoint.
- */
-static void clear_breakpoint(struct task_struct *task, struct debug_entry *bp)
-{
-	unsigned long addr = bp->address;
-	union debug_insn old_insn;
-	int ret;
-
-	if (addr & 1) {
-		ret = swap_insn(task, addr & ~1, &old_insn.thumb,
-				&bp->insn.thumb, 2);
-
-		if (ret != 2 || old_insn.thumb != BREAKINST_THUMB)
-			printk(KERN_ERR "%s:%d: corrupted Thumb breakpoint at "
-				"0x%08lx (0x%04x)\n", task->comm,
-				task_pid_nr(task), addr, old_insn.thumb);
-	} else {
-		ret = swap_insn(task, addr & ~3, &old_insn.arm,
-				&bp->insn.arm, 4);
-
-		if (ret != 4 || old_insn.arm != BREAKINST_ARM)
-			printk(KERN_ERR "%s:%d: corrupted ARM breakpoint at "
-				"0x%08lx (0x%08x)\n", task->comm,
-				task_pid_nr(task), addr, old_insn.arm);
-	}
-}
-
-void ptrace_set_bpt(struct task_struct *child)
-{
-	struct pt_regs *regs;
-	unsigned long pc;
-	u32 insn;
-	int res;
-
-	regs = task_pt_regs(child);
-	pc = instruction_pointer(regs);
-
-	if (thumb_mode(regs)) {
-		printk(KERN_WARNING "ptrace: can't handle thumb mode\n");
-		return;
-	}
-
-	res = read_instr(child, pc, &insn);
-	if (!res) {
-		struct debug_info *dbg = &child->thread.debug;
-		unsigned long alt;
-
-		dbg->nsaved = 0;
-
-		alt = get_branch_address(child, pc, insn);
-		if (alt)
-			add_breakpoint(child, dbg, alt);
-
-		/*
-		 * Note that we ignore the result of setting the above
-		 * breakpoint since it may fail.  When it does, this is
-		 * not so much an error, but a forewarning that we may
-		 * be receiving a prefetch abort shortly.
-		 *
-		 * If we don't set this breakpoint here, then we can
-		 * lose control of the thread during single stepping.
-		 */
-		if (!alt || predicate(insn) != PREDICATE_ALWAYS)
-			add_breakpoint(child, dbg, pc + 4);
-	}
-}
-
-/*
- * Ensure no single-step breakpoint is pending.  Returns non-zero
- * value if child was being single-stepped.
- */
-void ptrace_cancel_bpt(struct task_struct *child)
-{
-	int i, nsaved = child->thread.debug.nsaved;
-
-	child->thread.debug.nsaved = 0;
-
-	if (nsaved > 2) {
-		printk("ptrace_cancel_bpt: bogus nsaved: %d!\n", nsaved);
-		nsaved = 2;
-	}
-
-	for (i = 0; i < nsaved; i++)
-		clear_breakpoint(child, &child->thread.debug.bp[i]);
-}
-
-void user_disable_single_step(struct task_struct *task)
-{
-	task->ptrace &= ~PT_SINGLESTEP;
-	ptrace_cancel_bpt(task);
-}
-
-void user_enable_single_step(struct task_struct *task)
-{
-	task->ptrace |= PT_SINGLESTEP;
-}
-
 /*
  * Called by kernel/ptrace.c when detaching..
  */
 void ptrace_disable(struct task_struct *child)
 {
-	user_disable_single_step(child);
+	/* Nothing to do. */
 }
 
 /*
@@ -576,8 +197,6 @@
 {
 	siginfo_t info;
 
-	ptrace_cancel_bpt(tsk);
-
 	info.si_signo = SIGTRAP;
 	info.si_errno = 0;
 	info.si_code  = TRAP_BRKPT;
@@ -1148,12 +767,20 @@
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
 		case PTRACE_GETHBPREGS:
+			if (ptrace_get_breakpoints(child) < 0)
+				return -ESRCH;
+
 			ret = ptrace_gethbpregs(child, addr,
 						(unsigned long __user *)data);
+			ptrace_put_breakpoints(child);
 			break;
 		case PTRACE_SETHBPREGS:
+			if (ptrace_get_breakpoints(child) < 0)
+				return -ESRCH;
+
 			ret = ptrace_sethbpregs(child, addr,
 						(unsigned long __user *)data);
+			ptrace_put_breakpoints(child);
 			break;
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/ptrace.h linux-libre-2.6.39-gnu/arch/arm/kernel/ptrace.h
--- linux-libre-2.6.38-gnu/arch/arm/kernel/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/ptrace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/*
- *  linux/arch/arm/kernel/ptrace.h
- *
- *  Copyright (C) 2000-2003 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/ptrace.h>
-
-extern void ptrace_cancel_bpt(struct task_struct *);
-extern void ptrace_set_bpt(struct task_struct *);
-extern void ptrace_break(struct task_struct *, struct pt_regs *);
-
-/*
- * Send SIGTRAP if we're single-stepping
- */
-static inline void single_step_trap(struct task_struct *task)
-{
-	if (task->ptrace & PT_SINGLESTEP) {
-		ptrace_cancel_bpt(task);
-		send_sig(SIGTRAP, task, 1);
-	}
-}
-
-static inline void single_step_clear(struct task_struct *task)
-{
-	if (task->ptrace & PT_SINGLESTEP)
-		ptrace_cancel_bpt(task);
-}
-
-static inline void single_step_set(struct task_struct *task)
-{
-	if (task->ptrace & PT_SINGLESTEP)
-		ptrace_set_bpt(task);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/return_address.c linux-libre-2.6.39-gnu/arch/arm/kernel/return_address.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/return_address.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/return_address.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
  * the Free Software Foundation.
  */
 #include <linux/module.h>
+#include <linux/ftrace.h>
 
 #if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
 #include <linux/sched.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/setup.c linux-libre-2.6.39-gnu/arch/arm/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -308,7 +308,22 @@
  * already provide the required functionality.
  */
 extern struct proc_info_list *lookup_processor_type(unsigned int);
-extern struct machine_desc *lookup_machine_type(unsigned int);
+
+static void __init early_print(const char *str, ...)
+{
+	extern void printascii(const char *);
+	char buf[256];
+	va_list ap;
+
+	va_start(ap, str);
+	vsnprintf(buf, sizeof(buf), str, ap);
+	va_end(ap);
+
+#ifdef CONFIG_DEBUG_LL
+	printascii(buf);
+#endif
+	printk("%s", buf);
+}
 
 static void __init feat_v6_fixup(void)
 {
@@ -426,30 +441,38 @@
 
 static struct machine_desc * __init setup_machine(unsigned int nr)
 {
-	struct machine_desc *list;
+	extern struct machine_desc __arch_info_begin[], __arch_info_end[];
+	struct machine_desc *p;
 
 	/*
 	 * locate machine in the list of supported machines.
 	 */
-	list = lookup_machine_type(nr);
-	if (!list) {
-		printk("Machine configuration botched (nr %d), unable "
-		       "to continue.\n", nr);
-		while (1);
-	}
+	for (p = __arch_info_begin; p < __arch_info_end; p++)
+		if (nr == p->nr) {
+			printk("Machine: %s\n", p->name);
+			return p;
+		}
 
-	printk("Machine: %s\n", list->name);
+	early_print("\n"
+		"Error: unrecognized/unsupported machine ID (r1 = 0x%08x).\n\n"
+		"Available machine support:\n\nID (hex)\tNAME\n", nr);
 
-	return list;
+	for (p = __arch_info_begin; p < __arch_info_end; p++)
+		early_print("%08x\t%s\n", p->nr, p->name);
+
+	early_print("\nPlease check your kernel config and/or bootloader.\n");
+
+	while (true)
+		/* can't use cpu_relax() here as it may require MMU setup */;
 }
 
-static int __init arm_add_memory(unsigned long start, unsigned long size)
+static int __init arm_add_memory(phys_addr_t start, unsigned long size)
 {
 	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
 
 	if (meminfo.nr_banks >= NR_BANKS) {
 		printk(KERN_CRIT "NR_BANKS too low, "
-			"ignoring memory at %#lx\n", start);
+			"ignoring memory at 0x%08llx\n", (long long)start);
 		return -EINVAL;
 	}
 
@@ -479,7 +502,8 @@
 static int __init early_mem(char *p)
 {
 	static int usermem __initdata = 0;
-	unsigned long size, start;
+	unsigned long size;
+	phys_addr_t start;
 	char *endp;
 
 	/*
@@ -703,7 +727,7 @@
 	{ tag_size(tag_core), ATAG_CORE },
 	{ 1, PAGE_SIZE, 0xff },
 	{ tag_size(tag_mem32), ATAG_MEM },
-	{ MEM_SIZE, PHYS_OFFSET },
+	{ MEM_SIZE },
 	{ 0, ATAG_NONE }
 };
 
@@ -765,30 +789,6 @@
 static inline void reserve_crashkernel(void) {}
 #endif /* CONFIG_KEXEC */
 
-/*
- * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
- * is_kdump_kernel() to determine if we are booting after a panic. Hence
- * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
- */
-
-#ifdef CONFIG_CRASH_DUMP
-/*
- * elfcorehdr= specifies the location of elf core header stored by the crashed
- * kernel. This option will be passed by kexec loader to the capture kernel.
- */
-static int __init setup_elfcorehdr(char *arg)
-{
-	char *end;
-
-	if (!arg)
-		return -EINVAL;
-
-	elfcorehdr_addr = memparse(arg, &end);
-	return end > arg ? 0 : -EINVAL;
-}
-early_param("elfcorehdr", setup_elfcorehdr);
-#endif /* CONFIG_CRASH_DUMP */
-
 static void __init squash_mem_tags(struct tag *tag)
 {
 	for (; tag->hdr.size; tag = tag_next(tag))
@@ -802,6 +802,8 @@
 	struct machine_desc *mdesc;
 	char *from = default_command_line;
 
+	init_tags.mem.start = PHYS_OFFSET;
+
 	unwind_init();
 
 	setup_processor();
@@ -814,8 +816,25 @@
 
 	if (__atags_pointer)
 		tags = phys_to_virt(__atags_pointer);
-	else if (mdesc->boot_params)
-		tags = phys_to_virt(mdesc->boot_params);
+	else if (mdesc->boot_params) {
+#ifdef CONFIG_MMU
+		/*
+		 * We still are executing with a minimal MMU mapping created
+		 * with the presumption that the machine default for this
+		 * is located in the first MB of RAM.  Anything else will
+		 * fault and silently hang the kernel at this point.
+		 */
+		if (mdesc->boot_params < PHYS_OFFSET ||
+		    mdesc->boot_params >= PHYS_OFFSET + SZ_1M) {
+			printk(KERN_WARNING
+			       "Default boot params at physical 0x%08lx out of reach\n",
+			       mdesc->boot_params);
+		} else
+#endif
+		{
+			tags = phys_to_virt(mdesc->boot_params);
+		}
+	}
 
 #if defined(CONFIG_DEPRECATED_PARAM_STRUCT)
 	/*
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/signal.c linux-libre-2.6.39-gnu/arch/arm/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,6 @@
 #include <asm/unistd.h>
 #include <asm/vfp.h>
 
-#include "ptrace.h"
 #include "signal.h"
 
 #define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
@@ -348,8 +347,6 @@
 	if (restore_sigframe(regs, frame))
 		goto badframe;
 
-	single_step_trap(current);
-
 	return regs->ARM_r0;
 
 badframe:
@@ -383,8 +380,6 @@
 	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->ARM_sp) == -EFAULT)
 		goto badframe;
 
-	single_step_trap(current);
-
 	return regs->ARM_r0;
 
 badframe:
@@ -602,19 +597,13 @@
 	return err;
 }
 
-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;
-}
-
 /*
  * OK, we're invoking a handler
  */	
 static int
 handle_signal(unsigned long sig, struct k_sigaction *ka,
 	      siginfo_t *info, sigset_t *oldset,
-	      struct pt_regs * regs, int syscall)
+	      struct pt_regs * regs)
 {
 	struct thread_info *thread = current_thread_info();
 	struct task_struct *tsk = current;
@@ -622,26 +611,6 @@
 	int ret;
 
 	/*
-	 * If we were from a system call, check for system call restarting...
-	 */
-	if (syscall) {
-		switch (regs->ARM_r0) {
-		case -ERESTART_RESTARTBLOCK:
-		case -ERESTARTNOHAND:
-			regs->ARM_r0 = -EINTR;
-			break;
-		case -ERESTARTSYS:
-			if (!(ka->sa.sa_flags & SA_RESTART)) {
-				regs->ARM_r0 = -EINTR;
-				break;
-			}
-			/* fallthrough */
-		case -ERESTARTNOINTR:
-			setup_syscall_restart(regs);
-		}
-	}
-
-	/*
 	 * translate the signal
 	 */
 	if (usig < 32 && thread->exec_domain && thread->exec_domain->signal_invmap)
@@ -690,6 +659,7 @@
  */
 static void do_signal(struct pt_regs *regs, int syscall)
 {
+	unsigned int retval = 0, continue_addr = 0, restart_addr = 0;
 	struct k_sigaction ka;
 	siginfo_t info;
 	int signr;
@@ -703,20 +673,61 @@
 	if (!user_mode(regs))
 		return;
 
+	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall) {
+		continue_addr = regs->ARM_pc;
+		restart_addr = continue_addr - (thumb_mode(regs) ? 2 : 4);
+		retval = regs->ARM_r0;
+
+		/*
+		 * Prepare for system call restart.  We do this here so that a
+		 * debugger will see the already changed PSW.
+		 */
+		switch (retval) {
+		case -ERESTARTNOHAND:
+		case -ERESTARTSYS:
+		case -ERESTARTNOINTR:
+			regs->ARM_r0 = regs->ARM_ORIG_r0;
+			regs->ARM_pc = restart_addr;
+			break;
+		case -ERESTART_RESTARTBLOCK:
+			regs->ARM_r0 = -EINTR;
+			break;
+		}
+	}
+
 	if (try_to_freeze())
 		goto no_signal;
 
-	single_step_clear(current);
-
+	/*
+	 * Get the signal to deliver.  When running under ptrace, at this
+	 * point the debugger may change all our registers ...
+	 */
 	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
 	if (signr > 0) {
 		sigset_t *oldset;
 
+		/*
+		 * Depending on the signal settings we may need to revert the
+		 * decision to restart the system call.  But skip this if a
+		 * debugger has chosen to restart at a different PC.
+		 */
+		if (regs->ARM_pc == restart_addr) {
+			if (retval == -ERESTARTNOHAND
+			    || (retval == -ERESTARTSYS
+				&& !(ka.sa.sa_flags & SA_RESTART))) {
+				regs->ARM_r0 = -EINTR;
+				regs->ARM_pc = continue_addr;
+			}
+		}
+
 		if (test_thread_flag(TIF_RESTORE_SIGMASK))
 			oldset = &current->saved_sigmask;
 		else
 			oldset = &current->blocked;
-		if (handle_signal(signr, &ka, &info, oldset, regs, syscall) == 0) {
+		if (handle_signal(signr, &ka, &info, oldset, regs) == 0) {
 			/*
 			 * A signal was successfully delivered; the saved
 			 * sigmask will have been stored in the signal frame,
@@ -726,16 +737,18 @@
 			if (test_thread_flag(TIF_RESTORE_SIGMASK))
 				clear_thread_flag(TIF_RESTORE_SIGMASK);
 		}
-		single_step_set(current);
 		return;
 	}
 
  no_signal:
-	/*
-	 * No signal to deliver to the process - restart the syscall.
-	 */
 	if (syscall) {
-		if (regs->ARM_r0 == -ERESTART_RESTARTBLOCK) {
+		/*
+		 * Handle restarting a different system call.  As above,
+		 * if a debugger has chosen to restart at a different PC,
+		 * ignore the restart.
+		 */
+		if (retval == -ERESTART_RESTARTBLOCK
+		    && regs->ARM_pc == continue_addr) {
 			if (thumb_mode(regs)) {
 				regs->ARM_r7 = __NR_restart_syscall - __NR_SYSCALL_BASE;
 				regs->ARM_pc -= 2;
@@ -758,11 +771,6 @@
 #endif
 			}
 		}
-		if (regs->ARM_r0 == -ERESTARTNOHAND ||
-		    regs->ARM_r0 == -ERESTARTSYS ||
-		    regs->ARM_r0 == -ERESTARTNOINTR) {
-			setup_syscall_restart(regs);
-		}
 
 		/* If there's no signal to deliver, we just put the saved sigmask
 		 * back.
@@ -772,7 +780,6 @@
 			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
 		}
 	}
-	single_step_set(current);
 }
 
 asmlinkage void
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/sleep.S linux-libre-2.6.39-gnu/arch/arm/kernel/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,142 @@
+#include <linux/linkage.h>
+#include <linux/threads.h>
+#include <asm/asm-offsets.h>
+#include <asm/assembler.h>
+#include <asm/glue-cache.h>
+#include <asm/glue-proc.h>
+#include <asm/system.h>
+	.text
+
+/*
+ * Save CPU state for a suspend
+ *  r1 = v:p offset
+ *  r3 = virtual return function
+ * Note: sp is decremented to allocate space for CPU state on stack
+ * r0-r3,r9,r10,lr corrupted
+ */
+ENTRY(cpu_suspend)
+	mov	r9, lr
+#ifdef MULTI_CPU
+	ldr	r10, =processor
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, [r10, #CPU_SLEEP_SIZE] @ size of CPU sleep state
+	ldr	ip, [r10, #CPU_DO_RESUME] @ virtual resume function
+	sub	sp, sp, r0		@ allocate CPU state on stack
+	mov	r0, sp			@ save pointer
+	add	ip, ip, r1		@ convert resume fn to phys
+	stmfd	sp!, {r1, r2, r3, ip}	@ save v:p, virt SP, retfn, phys resume fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+#ifdef CONFIG_SMP
+	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
+	ALT_UP(mov lr, #0)
+	and	lr, lr, #15
+	str	r2, [r3, lr, lsl #2]	@ save phys SP
+#else
+	str	r2, [r3]		@ save phys SP
+#endif
+	mov	lr, pc
+	ldr	pc, [r10, #CPU_DO_SUSPEND] @ save CPU state
+#else
+	mov	r2, sp			@ current virtual SP
+	ldr	r0, =cpu_suspend_size
+	sub	sp, sp, r0		@ allocate CPU state on stack
+	mov	r0, sp			@ save pointer
+	stmfd	sp!, {r1, r2, r3}	@ save v:p, virt SP, return fn
+	ldr	r3, =sleep_save_sp
+	add	r2, sp, r1		@ convert SP to phys
+#ifdef CONFIG_SMP
+	ALT_SMP(mrc p15, 0, lr, c0, c0, 5)
+	ALT_UP(mov lr, #0)
+	and	lr, lr, #15
+	str	r2, [r3, lr, lsl #2]	@ save phys SP
+#else
+	str	r2, [r3]		@ save phys SP
+#endif
+	bl	cpu_do_suspend
+#endif
+
+	@ flush data cache
+#ifdef MULTI_CACHE
+	ldr	r10, =cpu_cache
+	mov	lr, r9
+	ldr	pc, [r10, #CACHE_FLUSH_KERN_ALL]
+#else
+	mov	lr, r9
+	b	__cpuc_flush_kern_all
+#endif
+ENDPROC(cpu_suspend)
+	.ltorg
+
+/*
+ * r0 = control register value
+ * r1 = v:p offset (preserved by cpu_do_resume)
+ * r2 = phys page table base
+ * r3 = L1 section flags
+ */
+ENTRY(cpu_resume_mmu)
+	adr	r4, cpu_resume_turn_mmu_on
+	mov	r4, r4, lsr #20
+	orr	r3, r3, r4, lsl #20
+	ldr	r5, [r2, r4, lsl #2]	@ save old mapping
+	str	r3, [r2, r4, lsl #2]	@ setup 1:1 mapping for mmu code
+	sub	r2, r2, r1
+	ldr	r3, =cpu_resume_after_mmu
+	bic	r1, r0, #CR_C		@ ensure D-cache is disabled
+	b	cpu_resume_turn_mmu_on
+ENDPROC(cpu_resume_mmu)
+	.ltorg
+	.align	5
+cpu_resume_turn_mmu_on:
+	mcr	p15, 0, r1, c1, c0, 0	@ turn on MMU, I-cache, etc
+	mrc	p15, 0, r1, c0, c0, 0	@ read id reg
+	mov	r1, r1
+	mov	r1, r1
+	mov	pc, r3			@ jump to virtual address
+ENDPROC(cpu_resume_turn_mmu_on)
+cpu_resume_after_mmu:
+	str	r5, [r2, r4, lsl #2]	@ restore old mapping
+	mcr	p15, 0, r0, c1, c0, 0	@ turn on D-cache
+	mov	pc, lr
+ENDPROC(cpu_resume_after_mmu)
+
+/*
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+	.data
+	.align
+ENTRY(cpu_resume)
+#ifdef CONFIG_SMP
+	adr	r0, sleep_save_sp
+	ALT_SMP(mrc p15, 0, r1, c0, c0, 5)
+	ALT_UP(mov r1, #0)
+	and	r1, r1, #15
+	ldr	r0, [r0, r1, lsl #2]	@ stack phys addr
+#else
+	ldr	r0, sleep_save_sp	@ stack phys addr
+#endif
+	setmode	PSR_I_BIT | PSR_F_BIT | SVC_MODE, r1  @ set SVC, irqs off
+#ifdef MULTI_CPU
+	@ load v:p, stack, return fn, resume fn
+  ARM(	ldmia	r0!, {r1, sp, lr, pc}	)
+THUMB(	ldmia	r0!, {r1, r2, r3, r4}	)
+THUMB(	mov	sp, r2			)
+THUMB(	mov	lr, r3			)
+THUMB(	bx	r4			)
+#else
+	@ load v:p, stack, return fn
+  ARM(	ldmia	r0!, {r1, sp, lr}	)
+THUMB(	ldmia	r0!, {r1, r2, lr}	)
+THUMB(	mov	sp, r2			)
+	b	cpu_do_resume
+#endif
+ENDPROC(cpu_resume)
+
+sleep_save_sp:
+	.rept	CONFIG_NR_CPUS
+	.long	0				@ preserve stack phys ptr here
+	.endr
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/smp.c linux-libre-2.6.39-gnu/arch/arm/kernel/smp.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -474,13 +474,12 @@
 #define smp_timer_broadcast	NULL
 #endif
 
-#ifndef CONFIG_LOCAL_TIMERS
 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)
+static void __cpuinit broadcast_timer_setup(struct clock_event_device *evt)
 {
 	evt->name	= "dummy_timer";
 	evt->features	= CLOCK_EVT_FEAT_ONESHOT |
@@ -492,7 +491,6 @@
 
 	clockevents_register_device(evt);
 }
-#endif
 
 void __cpuinit percpu_timer_setup(void)
 {
@@ -502,7 +500,8 @@
 	evt->cpumask = cpumask_of(cpu);
 	evt->broadcast = smp_timer_broadcast;
 
-	local_timer_setup(evt);
+	if (local_timer_setup(evt))
+		broadcast_timer_setup(evt);
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/smp_scu.c linux-libre-2.6.39-gnu/arch/arm/kernel/smp_scu.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/smp_scu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/smp_scu.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,3 +50,26 @@
 	 */
 	flush_cache_all();
 }
+
+/*
+ * Set the executing CPUs power mode as defined.  This will be in
+ * preparation for it executing a WFI instruction.
+ *
+ * This function must be called with preemption disabled, and as it
+ * has the side effect of disabling coherency, caches must have been
+ * flushed.  Interrupts must also have been disabled.
+ */
+int scu_power_mode(void __iomem *scu_base, unsigned int mode)
+{
+	unsigned int val;
+	int cpu = smp_processor_id();
+
+	if (mode > 3 || mode == 1 || cpu > 3)
+		return -EINVAL;
+
+	val = __raw_readb(scu_base + SCU_CPU_STATUS + cpu) & ~0x03;
+	val |= mode;
+	__raw_writeb(val, scu_base + SCU_CPU_STATUS + cpu);
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/swp_emulate.c linux-libre-2.6.39-gnu/arch/arm/kernel/swp_emulate.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/swp_emulate.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/swp_emulate.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,7 +158,7 @@
 
 	if (res == 0) {
 		/*
-		 * Barrier also required between aquiring a lock for a
+		 * Barrier also required between acquiring a lock for a
 		 * protected resource and accessing the resource. Inserted for
 		 * same reason as above.
 		 */
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/sys_oabi-compat.c linux-libre-2.6.39-gnu/arch/arm/kernel/sys_oabi-compat.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/sys_oabi-compat.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/sys_oabi-compat.c	2011-05-19 00:06:34.000000000 -0400
@@ -311,7 +311,7 @@
 	long err;
 	int i;
 
-	if (nsops < 1)
+	if (nsops < 1 || nsops > SEMOPM)
 		return -EINVAL;
 	sops = kmalloc(sizeof(*sops) * nsops, GFP_KERNEL);
 	if (!sops)
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/tcm.c linux-libre-2.6.39-gnu/arch/arm/kernel/tcm.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/tcm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/tcm.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 #include <linux/string.h> /* memcpy */
 #include <asm/cputype.h>
 #include <asm/mach/map.h>
-#include <mach/memory.h>
+#include <asm/memory.h>
 #include "tcm.h"
 
 static struct gen_pool *tcm_pool;
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/time.c linux-libre-2.6.39-gnu/arch/arm/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,9 +107,7 @@
 {
 	profile_tick(CPU_PROFILING);
 	do_leds();
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/traps.c linux-libre-2.6.39-gnu/arch/arm/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/arm/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/kexec.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <asm/atomic.h>
 #include <asm/cacheflush.h>
@@ -32,7 +33,6 @@
 #include <asm/unwind.h>
 #include <asm/tls.h>
 
-#include "ptrace.h"
 #include "signal.h"
 
 static const char *handler[]= { "prefetch abort", "data abort", "address exception", "interrupt" };
@@ -256,7 +256,7 @@
 	return ret;
 }
 
-DEFINE_SPINLOCK(die_lock);
+static DEFINE_SPINLOCK(die_lock);
 
 /*
  * This function is protected against re-entrancy.
@@ -410,8 +410,7 @@
 	struct thread_info *thread = current_thread_info();
 	siginfo_t info;
 
-	if (current->personality != PER_LINUX &&
-	    current->personality != PER_LINUX_32BIT &&
+	if ((current->personality & PER_MASK) != PER_LINUX &&
 	    thread->exec_domain->handler) {
 		thread->exec_domain->handler(n, regs);
 		return regs->ARM_r0;
@@ -712,17 +711,17 @@
 
 void __pte_error(const char *file, int line, pte_t pte)
 {
-	printk("%s:%d: bad pte %08lx.\n", file, line, pte_val(pte));
+	printk("%s:%d: bad pte %08llx.\n", file, line, (long long)pte_val(pte));
 }
 
 void __pmd_error(const char *file, int line, pmd_t pmd)
 {
-	printk("%s:%d: bad pmd %08lx.\n", file, line, pmd_val(pmd));
+	printk("%s:%d: bad pmd %08llx.\n", file, line, (long long)pmd_val(pmd));
 }
 
 void __pgd_error(const char *file, int line, pgd_t pgd)
 {
-	printk("%s:%d: bad pgd %08lx.\n", file, line, pgd_val(pgd));
+	printk("%s:%d: bad pgd %08llx.\n", file, line, (long long)pgd_val(pgd));
 }
 
 asmlinkage void __div0(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/arm/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/arm/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -64,6 +64,10 @@
 		__smpalt_end = .;
 #endif
 
+		__pv_table_begin = .;
+			*(.pv_table)
+		__pv_table_end = .;
+
 		INIT_SETUP(16)
 
 		INIT_CALLS
@@ -78,7 +82,7 @@
 #endif
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(32, PAGE_SIZE)
 
 #ifndef CONFIG_XIP_KERNEL
 	. = ALIGN(PAGE_SIZE);
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/bitops.h linux-libre-2.6.39-gnu/arch/arm/lib/bitops.h
--- linux-libre-2.6.38-gnu/arch/arm/lib/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,44 +1,52 @@
-
-#if __LINUX_ARM_ARCH__ >= 6 && defined(CONFIG_CPU_32v6K)
+#if __LINUX_ARM_ARCH__ >= 6
 	.macro	bitop, instr
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
-	and	r3, r0, #7		@ Get bit offset
-	add	r1, r1, r0, lsr #3	@ Get byte offset
+	and	r3, r0, #31		@ Get bit offset
+	mov	r0, r0, lsr #5
+	add	r1, r1, r0, lsl #2	@ Get word offset
 	mov	r3, r2, lsl r3
-1:	ldrexb	r2, [r1]
+1:	ldrex	r2, [r1]
 	\instr	r2, r2, r3
-	strexb	r0, r2, [r1]
+	strex	r0, r2, [r1]
 	cmp	r0, #0
 	bne	1b
-	mov	pc, lr
+	bx	lr
 	.endm
 
 	.macro	testop, instr, store
-	and	r3, r0, #7		@ Get bit offset
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
 	mov	r2, #1
-	add	r1, r1, r0, lsr #3	@ Get byte offset
+	and	r3, r0, #31		@ Get bit offset
+	mov	r0, r0, lsr #5
+	add	r1, r1, r0, lsl #2	@ Get word offset
 	mov	r3, r2, lsl r3		@ create mask
 	smp_dmb
-1:	ldrexb	r2, [r1]
+1:	ldrex	r2, [r1]
 	ands	r0, r2, r3		@ save old value of bit
-	\instr	r2, r2, r3			@ toggle bit
-	strexb	ip, r2, [r1]
+	\instr	r2, r2, r3		@ toggle bit
+	strex	ip, r2, [r1]
 	cmp	ip, #0
 	bne	1b
 	smp_dmb
 	cmp	r0, #0
 	movne	r0, #1
-2:	mov	pc, lr
+2:	bx	lr
 	.endm
 #else
 	.macro	bitop, instr
-	and	r2, r0, #7
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
+	and	r2, r0, #31
+	mov	r0, r0, lsr #5
 	mov	r3, #1
 	mov	r3, r3, lsl r2
 	save_and_disable_irqs ip
-	ldrb	r2, [r1, r0, lsr #3]
+	ldr	r2, [r1, r0, lsl #2]
 	\instr	r2, r2, r3
-	strb	r2, [r1, r0, lsr #3]
+	str	r2, [r1, r0, lsl #2]
 	restore_irqs ip
 	mov	pc, lr
 	.endm
@@ -52,11 +60,13 @@
  * to avoid dirtying the data cache.
  */
 	.macro	testop, instr, store
-	add	r1, r1, r0, lsr #3
-	and	r3, r0, #7
-	mov	r0, #1
+	ands	ip, r1, #3
+	strneb	r1, [ip]		@ assert word-aligned
+	and	r3, r0, #31
+	mov	r0, r0, lsr #5
 	save_and_disable_irqs ip
-	ldrb	r2, [r1]
+	ldr	r2, [r1, r0, lsl #2]!
+	mov	r0, #1
 	tst	r2, r0, lsl r3
 	\instr	r2, r2, r0, lsl r3
 	\store	r2, [r1]
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/changebit.S linux-libre-2.6.39-gnu/arch/arm/lib/changebit.S
--- linux-libre-2.6.38-gnu/arch/arm/lib/changebit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/changebit.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,12 +12,6 @@
 #include "bitops.h"
                 .text
 
-/* Purpose  : Function to change a bit
- * Prototype: int change_bit(int bit, void *addr)
- */
-ENTRY(_change_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_change_bit_le)
+ENTRY(_change_bit)
 	bitop	eor
-ENDPROC(_change_bit_be)
-ENDPROC(_change_bit_le)
+ENDPROC(_change_bit)
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/clearbit.S linux-libre-2.6.39-gnu/arch/arm/lib/clearbit.S
--- linux-libre-2.6.38-gnu/arch/arm/lib/clearbit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/clearbit.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,13 +12,6 @@
 #include "bitops.h"
                 .text
 
-/*
- * Purpose  : Function to clear a bit
- * Prototype: int clear_bit(int bit, void *addr)
- */
-ENTRY(_clear_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_clear_bit_le)
+ENTRY(_clear_bit)
 	bitop	bic
-ENDPROC(_clear_bit_be)
-ENDPROC(_clear_bit_le)
+ENDPROC(_clear_bit)
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/setbit.S linux-libre-2.6.39-gnu/arch/arm/lib/setbit.S
--- linux-libre-2.6.38-gnu/arch/arm/lib/setbit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/setbit.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,13 +12,6 @@
 #include "bitops.h"
 		.text
 
-/*
- * Purpose  : Function to set a bit
- * Prototype: int set_bit(int bit, void *addr)
- */
-ENTRY(_set_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_set_bit_le)
+ENTRY(_set_bit)
 	bitop	orr
-ENDPROC(_set_bit_be)
-ENDPROC(_set_bit_le)
+ENDPROC(_set_bit)
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/testchangebit.S linux-libre-2.6.39-gnu/arch/arm/lib/testchangebit.S
--- linux-libre-2.6.38-gnu/arch/arm/lib/testchangebit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/testchangebit.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,9 +12,6 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_change_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_test_and_change_bit_le)
-	testop	eor, strb
-ENDPROC(_test_and_change_bit_be)
-ENDPROC(_test_and_change_bit_le)
+ENTRY(_test_and_change_bit)
+	testop	eor, str
+ENDPROC(_test_and_change_bit)
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/testclearbit.S linux-libre-2.6.39-gnu/arch/arm/lib/testclearbit.S
--- linux-libre-2.6.38-gnu/arch/arm/lib/testclearbit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/testclearbit.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,9 +12,6 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_clear_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_test_and_clear_bit_le)
-	testop	bicne, strneb
-ENDPROC(_test_and_clear_bit_be)
-ENDPROC(_test_and_clear_bit_le)
+ENTRY(_test_and_clear_bit)
+	testop	bicne, strne
+ENDPROC(_test_and_clear_bit)
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/testsetbit.S linux-libre-2.6.39-gnu/arch/arm/lib/testsetbit.S
--- linux-libre-2.6.38-gnu/arch/arm/lib/testsetbit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/testsetbit.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,9 +12,6 @@
 #include "bitops.h"
                 .text
 
-ENTRY(_test_and_set_bit_be)
-		eor	r0, r0, #0x18		@ big endian byte ordering
-ENTRY(_test_and_set_bit_le)
-	testop	orreq, streqb
-ENDPROC(_test_and_set_bit_be)
-ENDPROC(_test_and_set_bit_le)
+ENTRY(_test_and_set_bit)
+	testop	orreq, streq
+ENDPROC(_test_and_set_bit)
diff -druN linux-libre-2.6.38-gnu/arch/arm/lib/uaccess_with_memcpy.c linux-libre-2.6.39-gnu/arch/arm/lib/uaccess_with_memcpy.c
--- linux-libre-2.6.38-gnu/arch/arm/lib/uaccess_with_memcpy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/lib/uaccess_with_memcpy.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,13 +27,18 @@
 	pgd_t *pgd;
 	pmd_t *pmd;
 	pte_t *pte;
+	pud_t *pud;
 	spinlock_t *ptl;
 
 	pgd = pgd_offset(current->mm, addr);
 	if (unlikely(pgd_none(*pgd) || pgd_bad(*pgd)))
 		return 0;
 
-	pmd = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	if (unlikely(pud_none(*pud) || pud_bad(*pud)))
+		return 0;
+
+	pmd = pmd_offset(pud, addr);
 	if (unlikely(pmd_none(*pmd) || pmd_bad(*pmd)))
 		return 0;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/aaed2000.c linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/aaed2000.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/aaed2000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/aaed2000.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,102 +0,0 @@
-/*
- *  linux/arch/arm/mach-aaec2000/aaed2000.c
- *
- *  Support for the Agilent AAED-2000 Development Platform.
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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/device.h>
-#include <linux/major.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/memory.h>
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-#include <asm/irq.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <mach/aaed2000.h>
-
-#include "core.h"
-
-static void aaed2000_clcd_disable(struct clcd_fb *fb)
-{
-	AAED_EXT_GPIO &= ~AAED_EGPIO_LCD_PWR_EN;
-}
-
-static void aaed2000_clcd_enable(struct clcd_fb *fb)
-{
-	AAED_EXT_GPIO |= AAED_EGPIO_LCD_PWR_EN;
-}
-
-struct aaec2000_clcd_info clcd_info = {
-	.enable = aaed2000_clcd_enable,
-	.disable = aaed2000_clcd_disable,
-	.panel = {
-		.mode	= {
-			.name		= "Sharp",
-			.refresh	= 60,
-			.xres		= 640,
-			.yres		= 480,
-			.pixclock	= 39721,
-			.left_margin	= 20,
-			.right_margin	= 44,
-			.upper_margin	= 21,
-			.lower_margin	= 34,
-			.hsync_len	= 96,
-			.vsync_len	= 2,
-			.sync		= 0,
-			.vmode	= FB_VMODE_NONINTERLACED,
-		},
-		.width	= -1,
-		.height	= -1,
-		.tim2	= TIM2_IVS | TIM2_IHS,
-		.cntl	= CNTL_LCDTFT,
-		.bpp	= 16,
-	},
-};
-
-static void __init aaed2000_init_irq(void)
-{
-	aaec2000_init_irq();
-}
-
-static void __init aaed2000_init(void)
-{
-	aaec2000_set_clcd_plat_data(&clcd_info);
-}
-
-static struct map_desc aaed2000_io_desc[] __initdata = {
-	{
-		.virtual	= EXT_GPIO_VBASE,
-		.pfn            = __phys_to_pfn(EXT_GPIO_PBASE),
-		.length         = EXT_GPIO_LENGTH,
-		.type           = MT_DEVICE
-	},
-};
-
-static void __init aaed2000_map_io(void)
-{
-	aaec2000_map_io();
-	iotable_init(aaed2000_io_desc, ARRAY_SIZE(aaed2000_io_desc));
-}
-
-MACHINE_START(AAED2000, "Agilent AAED-2000 Development Platform")
-	/* Maintainer: Nicolas Bellido Y Ortega */
-	.map_io		= aaed2000_map_io,
-	.init_irq	= aaed2000_init_irq,
-	.timer		= &aaec2000_timer,
-	.init_machine	= aaed2000_init,
-MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/core.c linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/core.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,298 +0,0 @@
-/*
- *  linux/arch/arm/mach-aaec2000/core.c
- *
- *  Code common to all AAEC-2000 machines
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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/platform_device.h>
-#include <linux/list.h>
-#include <linux/errno.h>
-#include <linux/dma-mapping.h>
-#include <linux/interrupt.h>
-#include <linux/timex.h>
-#include <linux/signal.h>
-#include <linux/clk.h>
-#include <linux/gfp.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/sizes.h>
-
-#include <asm/mach/flash.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
-
-#include "core.h"
-
-/*
- * Common I/O mapping:
- *
- * Static virtual address mappings are as follow:
- *
- * 0xf8000000-0xf8001ffff: Devices connected to APB bus
- * 0xf8002000-0xf8003ffff: Devices connected to AHB bus
- *
- * Below 0xe8000000 is reserved for vm allocation.
- *
- * The machine specific code must provide the extra mapping beside the
- * default mapping provided here.
- */
-static struct map_desc standard_io_desc[] __initdata = {
-	{
-		.virtual	= VIO_APB_BASE,
-		.pfn		= __phys_to_pfn(PIO_APB_BASE),
-		.length		= IO_APB_LENGTH,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= VIO_AHB_BASE,
-		.pfn		= __phys_to_pfn(PIO_AHB_BASE),
-		.length		= IO_AHB_LENGTH,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init aaec2000_map_io(void)
-{
-	iotable_init(standard_io_desc, ARRAY_SIZE(standard_io_desc));
-}
-
-/*
- * Interrupt handling routines
- */
-static void aaec2000_int_ack(struct irq_data *d)
-{
-	IRQ_INTSR = 1 << d->irq;
-}
-
-static void aaec2000_int_mask(struct irq_data *d)
-{
-	IRQ_INTENC |= (1 << d->irq);
-}
-
-static void aaec2000_int_unmask(struct irq_data *d)
-{
-	IRQ_INTENS |= (1 << d->irq);
-}
-
-static struct irq_chip aaec2000_irq_chip = {
-	.irq_ack	= aaec2000_int_ack,
-	.irq_mask	= aaec2000_int_mask,
-	.irq_unmask	= aaec2000_int_unmask,
-};
-
-void __init aaec2000_init_irq(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_handler(i, handle_level_irq);
-		set_irq_chip(i, &aaec2000_irq_chip);
-		set_irq_flags(i, IRQF_VALID);
-	}
-
-	/* Disable all interrupts */
-	IRQ_INTENC = 0xffffffff;
-
-	/* Clear any pending interrupts */
-	IRQ_INTSR = IRQ_INTSR;
-}
-
-/*
- * Time keeping
- */
-/* IRQs are disabled before entering here from do_gettimeofday() */
-static unsigned long aaec2000_gettimeoffset(void)
-{
-	unsigned long ticks_to_match, elapsed, usec;
-
-	/* Get ticks before next timer match */
-	ticks_to_match = TIMER1_LOAD - TIMER1_VAL;
-
-	/* We need elapsed ticks since last match */
-	elapsed = LATCH - ticks_to_match;
-
-	/* Now, convert them to usec */
-	usec = (unsigned long)(elapsed * (tick_nsec / 1000))/LATCH;
-
-	return usec;
-}
-
-/* We enter here with IRQs enabled */
-static irqreturn_t
-aaec2000_timer_interrupt(int irq, void *dev_id)
-{
-	/* TODO: Check timer accuracy */
-	timer_tick();
-	TIMER1_CLEAR = 1;
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction aaec2000_timer_irq = {
-	.name		= "AAEC-2000 Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= aaec2000_timer_interrupt,
-};
-
-static void __init aaec2000_timer_init(void)
-{
-	/* Disable timer 1 */
-	TIMER1_CTRL = 0;
-
-	/* We have somehow to generate a 100Hz clock.
-	 * We then use the 508KHz timer in periodic mode.
-	 */
-	TIMER1_LOAD = LATCH;
-	TIMER1_CLEAR = 1; /* Clear interrupt */
-
-	setup_irq(INT_TMR1_OFL, &aaec2000_timer_irq);
-
-	TIMER1_CTRL = TIMER_CTRL_ENABLE |
-	                TIMER_CTRL_PERIODIC |
-	                TIMER_CTRL_CLKSEL_508K;
-}
-
-struct sys_timer aaec2000_timer = {
-	.init		= aaec2000_timer_init,
-	.offset		= aaec2000_gettimeoffset,
-};
-
-static struct clcd_panel mach_clcd_panel;
-
-static int aaec2000_clcd_setup(struct clcd_fb *fb)
-{
-	dma_addr_t dma;
-
-	fb->panel = &mach_clcd_panel;
-
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, SZ_1M,
-			&dma, GFP_KERNEL);
-
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
-	}
-
-	fb->fb.fix.smem_start = dma;
-	fb->fb.fix.smem_len = SZ_1M;
-
-	return 0;
-}
-
-static int aaec2000_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-			fb->fb.screen_base,
-			fb->fb.fix.smem_start,
-			fb->fb.fix.smem_len);
-}
-
-static void aaec2000_clcd_remove(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-			fb->fb.screen_base, fb->fb.fix.smem_start);
-}
-
-static struct clcd_board clcd_plat_data = {
-	.name	= "AAEC-2000",
-	.check	= clcdfb_check,
-	.decode	= clcdfb_decode,
-	.setup	= aaec2000_clcd_setup,
-	.mmap	= aaec2000_clcd_mmap,
-	.remove	= aaec2000_clcd_remove,
-};
-
-static struct amba_device clcd_device = {
-	.dev		= {
-		.init_name		= "mb:16",
-		.coherent_dma_mask	= ~0,
-		.platform_data		= &clcd_plat_data,
-	},
-	.res		= {
-		.start			= AAEC_CLCD_PHYS,
-		.end			= AAEC_CLCD_PHYS + SZ_4K - 1,
-		.flags			= IORESOURCE_MEM,
-	},
-	.irq		= { INT_LCD, NO_IRQ },
-	.periphid	= 0x41110,
-};
-
-static struct amba_device *amba_devs[] __initdata = {
-	&clcd_device,
-};
-
-void clk_disable(struct clk *clk)
-{
-}
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return 0;
-}
-
-int clk_enable(struct clk *clk)
-{
-	return 0;
-}
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	return dev && strcmp(dev_name(dev), "mb:16") == 0 ? NULL : ERR_PTR(-ENOENT);
-}
-
-void clk_put(struct clk *clk)
-{
-}
-
-void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *clcd)
-{
-	clcd_plat_data.enable = clcd->enable;
-	clcd_plat_data.disable = clcd->disable;
-	memcpy(&mach_clcd_panel, &clcd->panel, sizeof(struct clcd_panel));
-}
-
-static struct flash_platform_data aaec2000_flash_data = {
-	.map_name	= "cfi_probe",
-	.width		= 4,
-};
-
-static struct resource aaec2000_flash_resource = {
-	.start		= AAEC_FLASH_BASE,
-	.end		= AAEC_FLASH_BASE + AAEC_FLASH_SIZE,
-	.flags		= IORESOURCE_MEM,
-};
-
-static struct platform_device aaec2000_flash_device = {
-	.name		= "armflash",
-	.id		= 0,
-	.dev		= {
-		.platform_data	= &aaec2000_flash_data,
-	},
-	.num_resources	= 1,
-	.resource	= &aaec2000_flash_resource,
-};
-
-static int __init aaec2000_init(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		amba_device_register(d, &iomem_resource);
-	}
-
-	platform_device_register(&aaec2000_flash_device);
-
-	return 0;
-};
-arch_initcall(aaec2000_init);
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/core.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/core.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/core.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- *  linux/arch/arm/mach-aaec2000/core.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-struct sys_timer;
-
-extern struct sys_timer aaec2000_timer;
-extern void __init aaec2000_map_io(void);
-extern void __init aaec2000_init_irq(void);
-
-struct aaec2000_clcd_info {
-	struct clcd_panel panel;
-	void (*disable)(struct clcd_fb *);
-	void (*enable)(struct clcd_fb *);
-};
-
-extern void __init aaec2000_set_clcd_plat_data(struct aaec2000_clcd_info *);
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/aaec2000.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/aaec2000.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/aaec2000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/aaec2000.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,207 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/aaec2000.h
- *
- *  AAEC-2000 registers definition
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_AAEC2000_H
-#define __ASM_ARCH_AAEC2000_H
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#error You must include hardware.h not this file
-#endif /* __ASM_ARCH_HARDWARE_H */
-
-/* Chip selects */
-#define AAEC_CS0	0x00000000
-#define AAEC_CS1	0x10000000
-#define AAEC_CS2	0x20000000
-#define AAEC_CS3	0x30000000
-
-/* Flash */
-#define AAEC_FLASH_BASE	AAEC_CS0
-#define AAEC_FLASH_SIZE	SZ_64M
-
-/* Interrupt controller */
-#define IRQ_BASE	__REG(0x80000500)
-#define IRQ_INTSR	__REG(0x80000500)	/* Int Status Register */
-#define IRQ_INTRSR	__REG(0x80000504)	/* Int Raw (unmasked) Status */
-#define IRQ_INTENS	__REG(0x80000508)	/* Int Enable Set */
-#define IRQ_INTENC	__REG(0x8000050c)	/* Int Enable Clear */
-
-/* UART 1 */
-#define UART1_BASE	__REG(0x80000600)
-#define UART1_DR	__REG(0x80000600) /* Data/FIFO Register */
-#define UART1_LCR	__REG(0x80000604) /* Link Control Register */
-#define UART1_BRCR	__REG(0x80000608) /* Baud Rate Control Register */
-#define UART1_CR	__REG(0x8000060c) /* Control Register */
-#define UART1_SR	__REG(0x80000610) /* Status Register */
-#define UART1_INT	__REG(0x80000614) /* Interrupt Status Register */
-#define UART1_INTM	__REG(0x80000618) /* Interrupt Mask Register */
-#define UART1_INTRES	__REG(0x8000061c) /* Int Result (masked status) Register */
-
-/* UART 2 */
-#define UART2_BASE	__REG(0x80000700)
-#define UART2_DR	__REG(0x80000700) /* Data/FIFO Register */
-#define UART2_LCR	__REG(0x80000704) /* Link Control Register */
-#define UART2_BRCR	__REG(0x80000708) /* Baud Rate Control Register */
-#define UART2_CR	__REG(0x8000070c) /* Control Register */
-#define UART2_SR	__REG(0x80000710) /* Status Register */
-#define UART2_INT	__REG(0x80000714) /* Interrupt Status Register */
-#define UART2_INTM	__REG(0x80000718) /* Interrupt Mask Register */
-#define UART2_INTRES	__REG(0x8000071c) /* Int Result (masked status) Register */
-
-/* UART 3 */
-#define UART3_BASE	__REG(0x80000800)
-#define UART3_DR	__REG(0x80000800) /* Data/FIFO Register */
-#define UART3_LCR	__REG(0x80000804) /* Link Control Register */
-#define UART3_BRCR	__REG(0x80000808) /* Baud Rate Control Register */
-#define UART3_CR	__REG(0x8000080c) /* Control Register */
-#define UART3_SR	__REG(0x80000810) /* Status Register */
-#define UART3_INT	__REG(0x80000814) /* Interrupt Status Register */
-#define UART3_INTM	__REG(0x80000818) /* Interrupt Mask Register */
-#define UART3_INTRES	__REG(0x8000081c) /* Int Result (masked status) Register */
-
-/* These are used in some places */
-#define _UART1_BASE __PREG(UART1_BASE)
-#define _UART2_BASE __PREG(UART2_BASE)
-#define _UART3_BASE __PREG(UART3_BASE)
-
-/* UART Registers Offsets */
-#define UART_DR		0x00
-#define UART_LCR	0x04
-#define UART_BRCR	0x08
-#define UART_CR		0x0c
-#define UART_SR		0x10
-#define UART_INT	0x14
-#define UART_INTM	0x18
-#define UART_INTRES	0x1c
-
-/* UART_LCR Bitmask */
-#define UART_LCR_BRK	(1 << 0) /* Send Break */
-#define UART_LCR_PEN	(1 << 1) /* Parity Enable */
-#define UART_LCR_EP	(1 << 2) /* Even/Odd Parity */
-#define UART_LCR_S2	(1 << 3) /* One/Two Stop bits */
-#define UART_LCR_FIFO	(1 << 4) /* FIFO Enable */
-#define UART_LCR_WL5	(0 << 5) /* Word Length - 5 bits */
-#define UART_LCR_WL6	(1 << 5) /* Word Length - 6 bits */
-#define UART_LCR_WL7	(1 << 6) /* Word Length - 7 bits */
-#define UART_LCR_WL8	(1 << 7) /* Word Length - 8 bits */
-
-/* UART_CR Bitmask */
-#define UART_CR_EN	(1 << 0) /* UART Enable */
-#define UART_CR_SIR	(1 << 1) /* IrDA SIR Enable */
-#define UART_CR_SIRLP	(1 << 2) /* Low Power IrDA Enable */
-#define UART_CR_RXP	(1 << 3) /* Receive Pin Polarity */
-#define UART_CR_TXP	(1 << 4) /* Transmit Pin Polarity */
-#define UART_CR_MXP	(1 << 5) /* Modem Pin Polarity */
-#define UART_CR_LOOP	(1 << 6) /* Loopback Mode */
-
-/* UART_SR Bitmask */
-#define UART_SR_CTS	(1 << 0) /* Clear To Send Status */
-#define UART_SR_DSR	(1 << 1) /* Data Set Ready Status */
-#define UART_SR_DCD	(1 << 2) /* Data Carrier Detect Status */
-#define UART_SR_TxBSY	(1 << 3) /* Transmitter Busy Status */
-#define UART_SR_RxFE	(1 << 4) /* Receive FIFO Empty Status */
-#define UART_SR_TxFF	(1 << 5) /* Transmit FIFO Full Status */
-#define UART_SR_RxFF	(1 << 6) /* Receive FIFO Full Status */
-#define UART_SR_TxFE	(1 << 7) /* Transmit FIFO Empty Status */
-
-/* UART_INT Bitmask */
-#define UART_INT_RIS	(1 << 0) /* Rx Interrupt */
-#define UART_INT_TIS	(1 << 1) /* Tx Interrupt */
-#define UART_INT_MIS	(1 << 2) /* Modem Interrupt */
-#define UART_INT_RTIS	(1 << 3) /* Receive Timeout Interrupt */
-
-/* Timer 1 */
-#define TIMER1_BASE	__REG(0x80000c00)
-#define TIMER1_LOAD	__REG(0x80000c00)	/* Timer 1 Load Register */
-#define TIMER1_VAL	__REG(0x80000c04)	/* Timer 1 Value Register */
-#define TIMER1_CTRL	__REG(0x80000c08)	/* Timer 1 Control Register */
-#define TIMER1_CLEAR	__REG(0x80000c0c)	/* Timer 1 Clear Register */
-
-/* Timer 2 */
-#define TIMER2_BASE	__REG(0x80000d00)
-#define TIMER2_LOAD	__REG(0x80000d00)	/* Timer 2 Load Register */
-#define TIMER2_VAL	__REG(0x80000d04)	/* Timer 2 Value Register */
-#define TIMER2_CTRL	__REG(0x80000d08)	/* Timer 2 Control Register */
-#define TIMER2_CLEAR	__REG(0x80000d0c)	/* Timer 2 Clear Register */
-
-/* Timer 3 */
-#define TIMER3_BASE	__REG(0x80000e00)
-#define TIMER3_LOAD	__REG(0x80000e00)	/* Timer 3 Load Register */
-#define TIMER3_VAL	__REG(0x80000e04)	/* Timer 3 Value Register */
-#define TIMER3_CTRL	__REG(0x80000e08)	/* Timer 3 Control Register */
-#define TIMER3_CLEAR	__REG(0x80000e0c)	/* Timer 3 Clear Register */
-
-/* Timer Control register bits */
-#define TIMER_CTRL_ENABLE	(1 << 7) /* Enable (Start Timer) */
-#define TIMER_CTRL_PERIODIC	(1 << 6) /* Periodic Running Mode */
-#define TIMER_CTRL_FREE_RUNNING (0 << 6) /* Normal Running Mode */
-#define TIMER_CTRL_CLKSEL_508K	(1 << 3) /* 508KHz Clock select (Timer 1, 2) */
-#define TIMER_CTRL_CLKSEL_2K	(0 << 3) /* 2KHz Clock Select (Timer 1, 2) */
-
-/* Power and State Control */
-#define POWER_BASE	__REG(0x80000400)
-#define POWER_PWRSR	__REG(0x80000400) /* Power Status Register */
-#define POWER_PWRCNT	__REG(0x80000404) /* Power/Clock control */
-#define POWER_HALT	__REG(0x80000408) /* Power Idle Mode */
-#define POWER_STDBY	__REG(0x8000040c) /* Power Standby Mode */
-#define POWER_BLEOI	__REG(0x80000410) /* Battery Low End of Interrupt */
-#define POWER_MCEOI	__REG(0x80000414) /* Media Changed EoI */
-#define POWER_TEOI	__REG(0x80000418) /* Tick EoI */
-#define POWER_STFCLR	__REG(0x8000041c) /* NbFlg, RSTFlg, PFFlg, CLDFlg Clear */
-#define POWER_CLKSET	__REG(0x80000420) /* Clock Speed Control */
-
-/* GPIO Registers */
-#define AAEC_GPIO_PHYS	0x80000e00
-
-#define AAEC_GPIO_PADR		__REG(AAEC_GPIO_PHYS + 0x00)
-#define AAEC_GPIO_PBDR		__REG(AAEC_GPIO_PHYS + 0x04)
-#define AAEC_GPIO_PCDR		__REG(AAEC_GPIO_PHYS + 0x08)
-#define AAEC_GPIO_PDDR		__REG(AAEC_GPIO_PHYS + 0x0c)
-#define AAEC_GPIO_PADDR		__REG(AAEC_GPIO_PHYS + 0x10)
-#define AAEC_GPIO_PBDDR		__REG(AAEC_GPIO_PHYS + 0x14)
-#define AAEC_GPIO_PCDDR		__REG(AAEC_GPIO_PHYS + 0x18)
-#define AAEC_GPIO_PDDDR		__REG(AAEC_GPIO_PHYS + 0x1c)
-#define AAEC_GPIO_PEDR		__REG(AAEC_GPIO_PHYS + 0x20)
-#define AAEC_GPIO_PEDDR		__REG(AAEC_GPIO_PHYS + 0x24)
-#define AAEC_GPIO_KSCAN		__REG(AAEC_GPIO_PHYS + 0x28)
-#define AAEC_GPIO_PINMUX	__REG(AAEC_GPIO_PHYS + 0x2c)
-#define AAEC_GPIO_PFDR		__REG(AAEC_GPIO_PHYS + 0x30)
-#define AAEC_GPIO_PFDDR		__REG(AAEC_GPIO_PHYS + 0x34)
-#define AAEC_GPIO_PGDR		__REG(AAEC_GPIO_PHYS + 0x38)
-#define AAEC_GPIO_PGDDR		__REG(AAEC_GPIO_PHYS + 0x3c)
-#define AAEC_GPIO_PHDR		__REG(AAEC_GPIO_PHYS + 0x40)
-#define AAEC_GPIO_PHDDR		__REG(AAEC_GPIO_PHYS + 0x44)
-#define AAEC_GPIO_RAZ		__REG(AAEC_GPIO_PHYS + 0x48)
-#define AAEC_GPIO_INTTYPE1	__REG(AAEC_GPIO_PHYS + 0x4c)
-#define AAEC_GPIO_INTTYPE2	__REG(AAEC_GPIO_PHYS + 0x50)
-#define AAEC_GPIO_FEOI		__REG(AAEC_GPIO_PHYS + 0x54)
-#define AAEC_GPIO_INTEN		__REG(AAEC_GPIO_PHYS + 0x58)
-#define AAEC_GPIO_INTSTATUS	__REG(AAEC_GPIO_PHYS + 0x5c)
-#define AAEC_GPIO_RAWINTSTATUS	__REG(AAEC_GPIO_PHYS + 0x60)
-#define AAEC_GPIO_DB		__REG(AAEC_GPIO_PHYS + 0x64)
-#define AAEC_GPIO_PAPINDR	__REG(AAEC_GPIO_PHYS + 0x68)
-#define AAEC_GPIO_PBPINDR	__REG(AAEC_GPIO_PHYS + 0x6c)
-#define AAEC_GPIO_PCPINDR	__REG(AAEC_GPIO_PHYS + 0x70)
-#define AAEC_GPIO_PDPINDR	__REG(AAEC_GPIO_PHYS + 0x74)
-#define AAEC_GPIO_PEPINDR	__REG(AAEC_GPIO_PHYS + 0x78)
-#define AAEC_GPIO_PFPINDR	__REG(AAEC_GPIO_PHYS + 0x7c)
-#define AAEC_GPIO_PGPINDR	__REG(AAEC_GPIO_PHYS + 0x80)
-#define AAEC_GPIO_PHPINDR	__REG(AAEC_GPIO_PHYS + 0x84)
-
-#define AAEC_GPIO_PINMUX_PE0CON		(1 << 0)
-#define AAEC_GPIO_PINMUX_PD0CON		(1 << 1)
-#define AAEC_GPIO_PINMUX_CODECON	(1 << 2)
-#define AAEC_GPIO_PINMUX_UART3CON	(1 << 3)
-
-/* LCD Controller */
-#define AAEC_CLCD_PHYS	0x80003000
-
-#endif /* __ARM_ARCH_AAEC2000_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/aaed2000.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/aaed2000.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/aaed2000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/aaed2000.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/aaed2000.h
- *
- *  AAED-2000 specific bits definition
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_AAED2000_H
-#define __ASM_ARCH_AAED2000_H
-
-/* External GPIOs. */
-
-#define EXT_GPIO_PBASE	AAEC_CS3
-#define EXT_GPIO_VBASE	0xf8100000
-#define EXT_GPIO_LENGTH	0x00001000
-
-#define __ext_gpio_p2v(x)	((x) - EXT_GPIO_PBASE + EXT_GPIO_VBASE)
-#define __ext_gpio_v2p(x)	((x) + EXT_GPIO_PBASE - EXT_GPIO_VBASE)
-
-#define __EXT_GPIO_REG(x)	(*((volatile u32 *)__ext_gpio_p2v(x)))
-#define __EXT_GPIO_PREG(x)	(__ext_gpio_v2p((u32)&(x)))
-
-#define AAED_EXT_GPIO	__EXT_GPIO_REG(EXT_GPIO_PBASE)
-
-#define AAED_EGPIO_KBD_SCAN	0x00003fff /* Keyboard scan data */
-#define AAED_EGPIO_PWR_INT	0x00008fff /* Smart battery charger interrupt */
-#define AAED_EGPIO_SWITCHED	0x000f0000 /* DIP Switches */
-#define AAED_EGPIO_USB_VBUS	0x00400000 /* USB Vbus sense */
-#define AAED_EGPIO_LCD_PWR_EN	0x02000000 /* LCD and backlight PWR enable */
-#define AAED_EGPIO_nLED0	0x20000000 /* LED 0 */
-#define AAED_EGPIO_nLED1	0x20000000 /* LED 1 */
-#define AAED_EGPIO_nLED2	0x20000000 /* LED 2 */
-
-
-#endif /* __ARM_ARCH_AAED2000_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*  arch/arm/mach-aaec2000/include/mach/debug-macro.S
- *
- *  Debugging macro include header
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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 "hardware.h"
-		.macro	addruart, rp, rv
-		mov	\rp, 0x00000800
-		orr	\rv, \rp, #io_p2v(0x80000000)	@ virtual
-		orr	\rp, \rp, #0x80000000		@ physical
-		.endm
-
-		.macro	senduart,rd,rx
-		str	\rd, [\rx, #0]
-		.endm
-
-		.macro	busyuart,rd,rx
-1002:		ldr	\rd, [\rx, #0x10]
-		tst	\rd, #(1 << 7)
-		beq	1002b
-		.endm
-
-		.macro	waituart,rd,rx
-#if 0
-1001:		ldr	\rd, [\rx, #0x10]
-		tst	\rd, #(1 << 5)
-		beq	1001b
-#endif
-		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/entry-macro.S
- *
- *  Low-level IRQ helper for aaec-2000 based platforms
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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 <mach/irqs.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
-		mov	r4, #0xf8000000
-		add	r4, r4, #0x00000500
-		mov	\base, r4
-		ldr	\irqstat, [\base, #0]
-		cmp	\irqstat, #0
-		bne	1001f
-		ldr	\irqnr, =NR_IRQS+1
-		b       1003f
-1001:		mov	\irqnr, #0
-1002:		ands	\tmp, \irqstat, #1
-		mov	\irqstat, \irqstat, LSR #1
-		add	\irqnr, \irqnr, #1
-		beq	1002b
-		sub	\irqnr, \irqnr, #1
-1003:
-		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/hardware.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>
-#include <mach/aaec2000.h>
-
-/* The kernel is loaded at physical address 0xf8000000.
- * We map the IO space a bit after
- */
-#define PIO_APB_BASE	0x80000000
-#define VIO_APB_BASE	0xf8000000
-#define IO_APB_LENGTH	0x2000
-#define PIO_AHB_BASE	0x80002000
-#define VIO_AHB_BASE	0xf8002000
-#define IO_AHB_LENGTH	0x2000
-
-#define VIO_BASE    VIO_APB_BASE
-#define PIO_BASE    PIO_APB_BASE
-
-#define io_p2v(x) ( (x) - PIO_BASE + VIO_BASE )
-#define io_v2p(x) ( (x) + PIO_BASE - VIO_BASE )
-
-#ifndef __ASSEMBLY__
-
-#include <asm/types.h>
-
-/* FIXME: Is it needed to optimize this a la pxa ?? */
-#define __REG(x)    (*((volatile u32 *)io_p2v(x)))
-#define __PREG(x)   (io_v2p((u32)&(x)))
-
-#else /* __ASSEMBLY__ */
-
-#define __REG(x)    io_p2v(x)
-#define __PREG(x)   io_v2p(x)
-
-#endif
-
-#include "aaec2000.h"
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/io.h
- *
- *  Copied from asm/arch/sa1100/io.h
- */
-#ifndef __ASM_ARM_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/*
- * We don't actually have real ISA nor PCI buses, but there is so many
- * drivers out there that might just work if we fake them...
- */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/irqs.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-
-#define INT_GPIOF0_FIQ	0  /* External GPIO Port F O Fast Interrupt Input */
-#define INT_BL_FIQ	1  /* Battery Low Fast Interrupt */
-#define INT_WE_FIQ	2  /* Watchdog Expired Fast Interrupt */
-#define INT_MV_FIQ	3  /* Media Changed Interrupt */
-#define INT_SC		4  /* Sound Codec Interrupt */
-#define INT_GPIO1	5  /* GPIO Port F Configurable Int 1 */
-#define INT_GPIO2	6  /* GPIO Port F Configurable Int 2 */
-#define INT_GPIO3	7  /* GPIO Port F Configurable Int 3 */
-#define INT_TMR1_OFL	8  /* Timer 1 Overflow Interrupt */
-#define INT_TMR2_OFL	9  /* Timer 2 Overflow Interrupt */
-#define INT_RTC_CM	10 /* RTC Compare Match Interrupt */
-#define INT_TICK	11 /* 64Hz Tick Interrupt */
-#define INT_UART1	12 /* UART1 Interrupt */
-#define INT_UART2	13 /* UART2 & Modem State Changed Interrupt */
-#define INT_LCD		14 /* LCD Interrupt */
-#define INT_SSI		15 /* SSI End of Transfer Interrupt */
-#define INT_UART3	16 /* UART3 Interrupt */
-#define INT_SCI		17 /* SCI Interrupt */
-#define INT_AAC		18 /* Advanced Audio Codec Interrupt */
-#define INT_MMC		19 /* MMC Interrupt */
-#define INT_USB		20 /* USB Interrupt */
-#define INT_DMA		21 /* DMA Interrupt */
-#define INT_TMR3_UOFL	22 /* Timer 3 Underflow Interrupt */
-#define INT_GPIO4	23 /* GPIO Port F Configurable Int 4 */
-#define INT_GPIO5	24 /* GPIO Port F Configurable Int 4 */
-#define INT_GPIO6	25 /* GPIO Port F Configurable Int 4 */
-#define INT_GPIO7	26 /* GPIO Port F Configurable Int 4 */
-#define INT_BMI		27 /* BMI Interrupt */
-
-#define NR_IRQS		(INT_BMI + 1)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/memory.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-
-#define PHYS_OFFSET	UL(0xf0000000)
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/*
- *  arch/arm/mach-aaed2000/include/mach/system.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle();
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset(0);
-}
-
-#endif /* __ASM_ARCH_SYSTEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/timex.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/timex.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/timex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/timex.h
- *
- *  AAEC-2000 Architecture timex specification
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_TIMEX_H
-#define __ASM_ARCH_TIMEX_H
-
-#define CLOCK_TICK_RATE		508000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,46 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/uncompress.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H
-
-#include "hardware.h"
-
-#define UART(x)         (*(volatile unsigned long *)(serial_port + (x)))
-
-static void putc(int c)
-{
-	unsigned long serial_port;
-        do {
-		serial_port = _UART3_BASE;
-		if (UART(UART_CR) & UART_CR_EN) break;
-		serial_port = _UART1_BASE;
-		if (UART(UART_CR) & UART_CR_EN) break;
-		serial_port = _UART2_BASE;
-		if (UART(UART_CR) & UART_CR_EN) break;
-		return;
-	} while (0);
-
-	/* wait for space in the UART's transmitter */
-	while ((UART(UART_SR) & UART_SR_TxFF))
-		barrier();
-
-	/* send the character out. */
-	UART(UART_DR) = c;
-}
-
-static inline void flush(void)
-{
-}
-
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
-
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/vmalloc.h linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/vmalloc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/include/mach/vmalloc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-/*
- *  arch/arm/mach-aaec2000/include/mach/vmalloc.h
- *
- *  Copyright (c) 2005 Nicolas Bellido Y Ortega
- *
- *  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_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H
-
-#define VMALLOC_END		0xd0000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-if ARCH_AAEC2000
-
-menu "Agilent AAEC-2000 Implementations"
-
-config MACH_AAED2000
-	bool "Agilent AAED-2000 Development Platform"
-	select CPU_ARM920T
-
-endmenu
-
-endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,9 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Common support (must be linked before board specific support)
-obj-y += core.o
-
-# Specific board support
-obj-$(CONFIG_MACH_AAED2000) += aaed2000.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/Makefile.boot linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/Makefile.boot
--- linux-libre-2.6.38-gnu/arch/arm/mach-aaec2000/Makefile.boot	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-aaec2000/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-	zreladdr-y := 0xf0008000
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/at91cap9_devices.c linux-libre-2.6.39-gnu/arch/arm/mach-at91/at91cap9_devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/at91cap9_devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/at91cap9_devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -72,7 +72,7 @@
 		return;
 
 	if (cpu_is_at91cap9_revB())
-		set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_irq_type(AT91CAP9_ID_UHP, IRQ_TYPE_LEVEL_HIGH);
 
 	/* Enable VBus control for UHP ports */
 	for (i = 0; i < data->ports; i++) {
@@ -157,7 +157,7 @@
 void __init at91_add_device_usba(struct usba_platform_data *data)
 {
 	if (cpu_is_at91cap9_revB()) {
-		set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_irq_type(AT91CAP9_ID_UDPHS, IRQ_TYPE_LEVEL_HIGH);
 		at91_sys_write(AT91_MATRIX_UDPHS, AT91_MATRIX_SELECT_UDPHS |
 						  AT91_MATRIX_UDPHS_BYPASS_LOCK);
 	}
@@ -861,7 +861,7 @@
 		return;
 
 	if (cpu_is_at91cap9_revB())
-		set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_irq_type(AT91CAP9_ID_LCDC, IRQ_TYPE_LEVEL_HIGH);
 
 	at91_set_A_periph(AT91_PIN_PC1, 0);	/* LCDHSYNC */
 	at91_set_A_periph(AT91_PIN_PC2, 0);	/* LCDDOTCK */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/board-carmeva.c linux-libre-2.6.39-gnu/arch/arm/mach-at91/board-carmeva.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/board-carmeva.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/board-carmeva.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
 	.pullup_pin	= AT91_PIN_PD9,
 };
 
-/* FIXME: user dependant */
+/* FIXME: user dependent */
 // static struct at91_cf_data __initdata carmeva_cf_data = {
 //	.det_pin	= AT91_PIN_PB0,
 //	.rst_pin	= AT91_PIN_PC5,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/board-eb01.c linux-libre-2.6.39-gnu/arch/arm/mach-at91/board-eb01.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/board-eb01.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/board-eb01.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,11 @@
 #include <mach/board.h>
 #include "generic.h"
 
+static void __init at91eb01_init_irq(void)
+{
+	at91x40_init_interrupts(NULL);
+}
+
 static void __init at91eb01_map_io(void)
 {
 	at91x40_initialize(40000000);
@@ -38,7 +43,7 @@
 MACHINE_START(AT91EB01, "Atmel AT91 EB01")
 	/* Maintainer: Greg Ungerer <gerg@snapgear.com> */
 	.timer		= &at91x40_timer,
-	.init_irq	= at91x40_init_interrupts,
+	.init_irq	= at91eb01_init_irq,
 	.map_io		= at91eb01_map_io,
 MACHINE_END
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/board-snapper9260.c linux-libre-2.6.39-gnu/arch/arm/mach-at91/board-snapper9260.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/board-snapper9260.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/board-snapper9260.c	2011-05-19 00:06:34.000000000 -0400
@@ -153,6 +153,7 @@
 	{
 		/* RTC */
 		I2C_BOARD_INFO("isl1208", 0x6f),
+		.irq = gpio_to_irq(AT91_PIN_PA31),
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-at91/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -287,7 +287,7 @@
 	else
 		wakeups[bank] &= ~mask;
 
-	set_irq_wake(gpio_chip[bank].bank->id, state);
+	irq_set_irq_wake(gpio_chip[bank].bank->id, state);
 
 	return 0;
 }
@@ -375,6 +375,7 @@
 
 static struct irq_chip gpio_irqchip = {
 	.name		= "GPIO",
+	.irq_disable	= gpio_irq_mask,
 	.irq_mask	= gpio_irq_mask,
 	.irq_unmask	= gpio_irq_unmask,
 	.irq_set_type	= gpio_irq_type,
@@ -384,16 +385,14 @@
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
 	unsigned	pin;
-	struct irq_desc	*gpio;
-	struct at91_gpio_chip *at91_gpio;
-	void __iomem	*pio;
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct irq_chip *chip = irq_data_get_irq_chip(idata);
+	struct at91_gpio_chip *at91_gpio = irq_data_get_irq_chip_data(idata);
+	void __iomem	*pio = at91_gpio->regbase;
 	u32		isr;
 
-	at91_gpio = get_irq_chip_data(irq);
-	pio = at91_gpio->regbase;
-
 	/* temporarily mask (level sensitive) parent IRQ */
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
+	chip->irq_ack(idata);
 	for (;;) {
 		/* Reading ISR acks pending (edge triggered) GPIO interrupts.
 		 * When there none are pending, we're finished unless we need
@@ -409,27 +408,15 @@
 		}
 
 		pin = at91_gpio->chip.base;
-		gpio = &irq_desc[pin];
 
 		while (isr) {
-			if (isr & 1) {
-				if (unlikely(gpio->depth)) {
-					/*
-					 * The core ARM interrupt handler lazily disables IRQs so
-					 * another IRQ must be generated before it actually gets
-					 * here to be disabled on the GPIO controller.
-					 */
-					gpio_irq_mask(irq_get_irq_data(pin));
-				}
-				else
-					generic_handle_irq(pin);
-			}
+			if (isr & 1)
+				generic_handle_irq(pin);
 			pin++;
-			gpio++;
 			isr >>= 1;
 		}
 	}
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
+	chip->irq_unmask(idata);
 	/* now it may re-trigger */
 }
 
@@ -518,14 +505,14 @@
 		__raw_writel(~0, this->regbase + PIO_IDR);
 
 		for (i = 0, pin = this->chip.base; i < 32; i++, pin++) {
-			lockdep_set_class(&irq_desc[pin].lock, &gpio_lock_class);
+			irq_set_lockdep_class(pin, &gpio_lock_class);
 
 			/*
 			 * Can use the "simple" and not "edge" handler since it's
 			 * shorter, and the AIC handles interrupts sanely.
 			 */
-			set_irq_chip(pin, &gpio_irqchip);
-			set_irq_handler(pin, handle_simple_irq);
+			irq_set_chip_and_handler(pin, &gpio_irqchip,
+						 handle_simple_irq);
 			set_irq_flags(pin, IRQF_VALID);
 		}
 
@@ -536,8 +523,8 @@
 		if (prev && prev->next == this)
 			continue;
 
-		set_irq_chip_data(id, this);
-		set_irq_chained_handler(id, gpio_irq_handler);
+		irq_set_chip_data(id, this);
+		irq_set_chained_handler(id, gpio_irq_handler);
 	}
 	pr_info("AT91: %d gpio irqs in %d banks\n", pin - PIN_BASE, gpio_banks);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/at572d940hf.h linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/at572d940hf.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/at572d940hf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/at572d940hf.h	2011-05-19 00:06:34.000000000 -0400
@@ -89,7 +89,7 @@
 /*
  * System Peripherals (offset from AT91_BASE_SYS)
  */
-#define AT91_SDRAMC	(0xffffea00 - AT91_BASE_SYS)
+#define AT91_SDRAMC0	(0xffffea00 - AT91_BASE_SYS)
 #define AT91_SMC	(0xffffec00 - AT91_BASE_SYS)
 #define AT91_MATRIX	(0xffffee00 - AT91_BASE_SYS)
 #define AT91_AIC	(0xfffff000 - AT91_BASE_SYS)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/at91_mci.h linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/at91_mci.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/at91_mci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/at91_mci.h	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,7 @@
 #define		AT91_MCI_RDIRE		(1 << 17)	/* Response Direction Error */
 #define		AT91_MCI_RCRCE		(1 << 18)	/* Response CRC Error */
 #define		AT91_MCI_RENDE		(1 << 19)	/* Response End Bit Error */
-#define		AT91_MCI_RTOE		(1 << 20)	/* Reponse Time-out Error */
+#define		AT91_MCI_RTOE		(1 << 20)	/* Response Time-out Error */
 #define		AT91_MCI_DCRCE		(1 << 21)	/* Data CRC Error */
 #define		AT91_MCI_DTOE		(1 << 22)	/* Data Time-out Error */
 #define		AT91_MCI_OVRE		(1 << 30)	/* Overrun */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/cpu.h linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/cpu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/cpu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/cpu.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #define ARCH_ID_AT91SAM9G45	0x819b05a0
 #define ARCH_ID_AT91SAM9G45MRL	0x819b05a2	/* aka 9G45-ES2 & non ES lots */
 #define ARCH_ID_AT91SAM9G45ES	0x819b05a1	/* 9G45-ES (Engineering Sample) */
+#define ARCH_ID_AT91SAM9X5	0x819a05a0
 #define ARCH_ID_AT91CAP9	0x039A03A0
 
 #define ARCH_ID_AT91SAM9XE128	0x329973a0
@@ -55,6 +56,12 @@
 #define ARCH_EXID_AT91SAM9G46	0x00000003
 #define ARCH_EXID_AT91SAM9G45	0x00000004
 
+#define ARCH_EXID_AT91SAM9G15	0x00000000
+#define ARCH_EXID_AT91SAM9G35	0x00000001
+#define ARCH_EXID_AT91SAM9X35	0x00000002
+#define ARCH_EXID_AT91SAM9G25	0x00000003
+#define ARCH_EXID_AT91SAM9X25	0x00000004
+
 static inline unsigned long at91_exid_identify(void)
 {
 	return at91_sys_read(AT91_DBGU_EXID);
@@ -143,6 +150,27 @@
 #define cpu_is_at91sam9m11()	(0)
 #endif
 
+#ifdef CONFIG_ARCH_AT91SAM9X5
+#define cpu_is_at91sam9x5()	(at91_cpu_identify() == ARCH_ID_AT91SAM9X5)
+#define cpu_is_at91sam9g15()	(cpu_is_at91sam9x5() && \
+				(at91_exid_identify() == ARCH_EXID_AT91SAM9G15))
+#define cpu_is_at91sam9g35()	(cpu_is_at91sam9x5() && \
+				(at91_exid_identify() == ARCH_EXID_AT91SAM9G35))
+#define cpu_is_at91sam9x35()	(cpu_is_at91sam9x5() && \
+				(at91_exid_identify() == ARCH_EXID_AT91SAM9X35))
+#define cpu_is_at91sam9g25()	(cpu_is_at91sam9x5() && \
+				(at91_exid_identify() == ARCH_EXID_AT91SAM9G25))
+#define cpu_is_at91sam9x25()	(cpu_is_at91sam9x5() && \
+				(at91_exid_identify() == ARCH_EXID_AT91SAM9X25))
+#else
+#define cpu_is_at91sam9x5()	(0)
+#define cpu_is_at91sam9g15()	(0)
+#define cpu_is_at91sam9g35()	(0)
+#define cpu_is_at91sam9x35()	(0)
+#define cpu_is_at91sam9g25()	(0)
+#define cpu_is_at91sam9x25()	(0)
+#endif
+
 #ifdef CONFIG_ARCH_AT91CAP9
 #define cpu_is_at91cap9()	(at91_cpu_identify() == ARCH_ID_AT91CAP9)
 #define cpu_is_at91cap9_revB()	(at91cap9_rev_identify() == ARCH_REVISION_CAP9_B)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -208,7 +208,7 @@
 
 /*-------------------------------------------------------------------------*/
 
-/* wrappers for "new style" GPIO calls. the old AT91-specfic ones should
+/* wrappers for "new style" GPIO calls. the old AT91-specific ones should
  * eventually be removed (along with this errno.h inclusion), and the
  * gpio request/free calls should probably be implemented.
  */
@@ -220,15 +220,8 @@
 #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;
-}
+#define gpio_to_irq(gpio) (gpio)
+#define irq_to_gpio(irq)  (irq)
 
 #endif	/* __ASSEMBLY__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,6 @@
 
 #include <mach/hardware.h>
 
-#define PHYS_OFFSET	(AT91_SDRAM_BASE)
+#define PLAT_PHYS_OFFSET	(AT91_SDRAM_BASE)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-at91/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -143,8 +143,7 @@
 		/* Active Low interrupt, with the specified priority */
 		at91_sys_write(AT91_AIC_SMR(i), AT91_AIC_SRCTYPE_LOW | priority[i]);
 
-		set_irq_chip(i, &at91_aic_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &at91_aic_chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 
 		/* Perform 8 End Of Interrupt Command to make sure AIC will not Lock out nIRQ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-at91/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-at91/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-at91/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-at91/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -83,6 +83,7 @@
 	select CPU_ARM926T
 	select GENERIC_CLOCKEVENTS
 	select HAVE_FB_ATMEL
+	select HAVE_NET_MACB
 
 config ARCH_AT572D940HF
 	bool "AT572D940HF"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/csp/dmac/dmacHw_extra.c	2011-05-19 00:06:34.000000000 -0400
@@ -551,7 +551,7 @@
 
 /****************************************************************************/
 /**
-*  @brief   Check the existance of pending descriptor
+*  @brief   Check the existence of pending descriptor
 *
 *  This function confirmes if there is any pending descriptor in the chain
 *  to program the channel
@@ -775,7 +775,7 @@
 /**
 *  @brief   Read data DMAed to memory
 *
-*  This function will read data that has been DMAed to memory while transfering from:
+*  This function will read data that has been DMAed to memory while transferring from:
 *          - Memory to memory
 *          - Peripheral to memory
 *
@@ -941,7 +941,7 @@
 /**
 *  @brief   Sets channel specific user data
 *
-*  This function associates user data to a specif DMA channel
+*  This function associates user data to a specific DMA channel
 *
 */
 /****************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/dma.c linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -629,7 +629,7 @@
 *   Configures a DMA channel.
 *
 *   @return
-*       >= 0    - Initialization was successfull.
+*       >= 0    - Initialization was successful.
 *
 *       -EBUSY  - Device is currently being used.
 *       -ENODEV - Device handed in is invalid.
@@ -673,7 +673,7 @@
 /**
 *   Initializes all of the data structures associated with the DMA.
 *   @return
-*       >= 0    - Initialization was successfull.
+*       >= 0    - Initialization was successful.
 *
 *       -EBUSY  - Device is currently being used.
 *       -ENODEV - Device handed in is invalid.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/csp/dmacHw.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/csp/dmacHw.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/csp/dmacHw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/csp/dmacHw.h	2011-05-19 00:06:34.000000000 -0400
@@ -362,7 +362,7 @@
 /**
 *  @brief   Read data DMA transferred to memory
 *
-*  This function will read data that has been DMAed to memory while transfering from:
+*  This function will read data that has been DMAed to memory while transferring from:
 *          - Memory to memory
 *          - Peripheral to memory
 *
@@ -446,7 +446,7 @@
 
 /****************************************************************************/
 /**
-*  @brief   Check the existance of pending descriptor
+*  @brief   Check the existence of pending descriptor
 *
 *  This function confirmes if there is any pending descriptor in the chain
 *  to program the channel
@@ -542,7 +542,7 @@
 /**
 *  @brief   Sets channel specific user data
 *
-*  This function associates user data to a specif DMA channel
+*  This function associates user data to a specific DMA channel
 *
 */
 /****************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -180,7 +180,7 @@
 
 #define chipcHw_XTAL_FREQ_Hz                    25000000	/* Reference clock frequency in Hz */
 
-/* Programable pin defines */
+/* Programmable pin defines */
 #define chipcHw_PIN_GPIO(n)                     ((((n) >= 0) && ((n) < (chipcHw_GPIO_COUNT))) ? (n) : 0xFFFFFFFF)
 									     /* GPIO pin 0 - 60 */
 #define chipcHw_PIN_UARTTXD                     (chipcHw_GPIO_COUNT + 0)	/* UART Transmit */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/csp/chipcHw_inline.h	2011-05-19 00:06:34.000000000 -0400
@@ -832,7 +832,7 @@
 
 /****************************************************************************/
 /**
-*  @brief   Lower layer funtion to enable/disable a clock of a certain device
+*  @brief   Lower layer function to enable/disable a clock of a certain device
 *
 *  This function enables/disables a core clock
 *
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/csp/intcHw_reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -109,9 +109,9 @@
 #define INTCHW_INTC0_DMA0C0               (1<<INTCHW_INTC0_DMA0C0_BITNUM)
 
 /* INTC1 - interrupt controller 1 */
-#define INTCHW_INTC1_DDRVPMP_BITNUM       27	/* DDR and VPM PLL clock phase relationship interupt (Not for A0) */
+#define INTCHW_INTC1_DDRVPMP_BITNUM       27	/* DDR and VPM PLL clock phase relationship interrupt (Not for A0) */
 #define INTCHW_INTC1_DDRVPMT_BITNUM       26	/* DDR and VPM HW phase align timeout interrupt (Not for A0) */
-#define INTCHW_INTC1_DDRP_BITNUM          26	/* DDR and PLL clock phase relationship interupt (For A0 only)) */
+#define INTCHW_INTC1_DDRP_BITNUM          26	/* DDR and PLL clock phase relationship interrupt (For A0 only)) */
 #define INTCHW_INTC1_RTC2_BITNUM          25	/* Real time clock tamper interrupt */
 #define INTCHW_INTC1_VDEC_BITNUM          24	/* Hantro Video Decoder interrupt */
 /* Bits 13-23 are non-secure versions of the corresponding secure bits in SINTC bits 0-10. */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
  *  *_SIZE  is the size of the region
  *  *_BASE  is the virtual address
  */
-#define RAM_START               PHYS_OFFSET
+#define RAM_START               PLAT_PHYS_OFFSET
 
 #define RAM_SIZE                (CFG_GLOBAL_RAM_SIZE-CFG_GLOBAL_RAM_SIZE_RESERVED)
 #define RAM_BASE                PAGE_OFFSET
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
  * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
  */
 
-#define PHYS_OFFSET CFG_GLOBAL_RAM_BASE
+#define PLAT_PHYS_OFFSET CFG_GLOBAL_RAM_BASE
 
 /*
  * Maximum DMA memory allowed is 14M
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/reg_umi.h linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/reg_umi.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/include/mach/reg_umi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/include/mach/reg_umi.h	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 /* REG_UMI_FLASH0/1/2_TCR, REG_UMI_SRAM0/1_TCR bits */
 /* Enable wait pin during burst write or read */
 #define REG_UMI_TCR_WAITEN              0x80000000
-/* Enable mem ctrlr to work iwth ext mem of lower freq than AHB clk */
+/* Enable mem ctrlr to work with ext mem of lower freq than AHB clk */
 #define REG_UMI_TCR_LOWFREQ             0x40000000
 /* 1=synch write, 0=async write */
 #define REG_UMI_TCR_MEMTYPE_SYNCWRITE   0x20000000
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-bcmring/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-bcmring/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,11 +93,11 @@
 	unsigned int i;
 	for (i = 0; i < 32; i++) {
 		unsigned int irq = irq_start + i;
-		set_irq_chip(irq, chip);
-		set_irq_chip_data(irq, base);
+		irq_set_chip(irq, chip);
+		irq_set_chip_data(irq, base);
 
 		if (vic_sources & (1 << i)) {
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_handler(irq, handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
 	}
@@ -119,9 +119,9 @@
 
 	/* special cases */
 	if (INTCHW_INTC1_GPIO0 & IRQ_INTC1_VALID_MASK) {
-		set_irq_handler(IRQ_GPIO0, handle_simple_irq);
+		irq_set_handler(IRQ_GPIO0, handle_simple_irq);
 	}
 	if (INTCHW_INTC1_GPIO1 & IRQ_INTC1_VALID_MASK) {
-		set_irq_handler(IRQ_GPIO1, handle_simple_irq);
+		irq_set_handler(IRQ_GPIO1, handle_simple_irq);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-clps711x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-clps711x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-clps711x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-clps711x/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0xc0000000)
+#define PLAT_PHYS_OFFSET	UL(0xc0000000)
 
 #if !defined(CONFIG_ARCH_CDB89712) && !defined (CONFIG_ARCH_AUTCPU12)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-clps711x/include/mach/time.h linux-libre-2.6.39-gnu/arch/arm/mach-clps711x/include/mach/time.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-clps711x/include/mach/time.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-clps711x/include/mach/time.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 {
 	struct pt_regs *regs = get_irq_regs();
 	do_leds();
-	do_timer(1);
+	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(regs));
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-clps711x/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-clps711x/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-clps711x/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-clps711x/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,13 +112,13 @@
 
 	for (i = 0; i < NR_IRQS; i++) {
 	        if (INT1_IRQS & (1 << i)) {
-	        	set_irq_handler(i, handle_level_irq);
-	        	set_irq_chip(i, &int1_chip);
+	        	irq_set_chip_and_handler(i, &int1_chip,
+						 handle_level_irq);
 	        	set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 		}
 		if (INT2_IRQS & (1 << i)) {
-			set_irq_handler(i, handle_level_irq);
-			set_irq_chip(i, &int2_chip);
+			irq_set_chip_and_handler(i, &int2_chip,
+						 handle_level_irq);
 			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 		}			
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-cns3xxx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #define __phys_to_bus(x)	((x) + PHYS_OFFSET)
 #define __bus_to_phys(x)	((x) - PHYS_OFFSET)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-da830-evm.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-da830-evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-da830-evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-da830-evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,8 @@
 #include <linux/i2c/at24.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -30,6 +32,7 @@
 #include <mach/da8xx.h>
 #include <mach/usb.h>
 #include <mach/aemif.h>
+#include <mach/spi.h>
 
 #define DA830_EVM_PHY_ID		""
 /*
@@ -534,6 +537,64 @@
 	},
 };
 
+static struct mtd_partition da830evm_spiflash_part[] = {
+	[0] = {
+		.name = "DSP-UBL",
+		.offset = 0,
+		.size = SZ_8K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[1] = {
+		.name = "ARM-UBL",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_16K + SZ_8K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[2] = {
+		.name = "U-Boot",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_256K - SZ_32K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[3] = {
+		.name = "U-Boot-Environment",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_16K,
+		.mask_flags = 0,
+	},
+	[4] = {
+		.name = "Kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = MTDPART_SIZ_FULL,
+		.mask_flags = 0,
+	},
+};
+
+static struct flash_platform_data da830evm_spiflash_data = {
+	.name		= "m25p80",
+	.parts		= da830evm_spiflash_part,
+	.nr_parts	= ARRAY_SIZE(da830evm_spiflash_part),
+	.type		= "w25x32",
+};
+
+static struct davinci_spi_config da830evm_spiflash_cfg = {
+	.io_type	= SPI_IO_TYPE_DMA,
+	.c2tdelay	= 8,
+	.t2cdelay	= 8,
+};
+
+static struct spi_board_info da830evm_spi_info[] = {
+	{
+		.modalias		= "m25p80",
+		.platform_data		= &da830evm_spiflash_data,
+		.controller_data	= &da830evm_spiflash_cfg,
+		.mode			= SPI_MODE_0,
+		.max_speed_hz		= 30000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+	},
+};
+
 static __init void da830_evm_init(void)
 {
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
@@ -590,6 +651,12 @@
 	ret = da8xx_register_rtc();
 	if (ret)
 		pr_warning("da830_evm_init: rtc setup failed: %d\n", ret);
+
+	ret = da8xx_register_spi(0, da830evm_spi_info,
+				 ARRAY_SIZE(da830evm_spi_info));
+	if (ret)
+		pr_warning("da830_evm_init: spi 0 registration failed: %d\n",
+			   ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-da850-evm.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-da850-evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-da850-evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-da850-evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,8 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/tps6507x.h>
 #include <linux/input/tps6507x-ts.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -38,6 +40,7 @@
 #include <mach/nand.h>
 #include <mach/mux.h>
 #include <mach/aemif.h>
+#include <mach/spi.h>
 
 #define DA850_EVM_PHY_ID		"0:00"
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
@@ -48,6 +51,70 @@
 
 #define DA850_MII_MDIO_CLKEN_PIN	GPIO_TO_PIN(2, 6)
 
+static struct mtd_partition da850evm_spiflash_part[] = {
+	[0] = {
+		.name = "UBL",
+		.offset = 0,
+		.size = SZ_64K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[1] = {
+		.name = "U-Boot",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_512K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[2] = {
+		.name = "U-Boot-Env",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_64K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+	[3] = {
+		.name = "Kernel",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_2M + SZ_512K,
+		.mask_flags = 0,
+	},
+	[4] = {
+		.name = "Filesystem",
+		.offset = MTDPART_OFS_APPEND,
+		.size = SZ_4M,
+		.mask_flags = 0,
+	},
+	[5] = {
+		.name = "MAC-Address",
+		.offset = SZ_8M - SZ_64K,
+		.size = SZ_64K,
+		.mask_flags = MTD_WRITEABLE,
+	},
+};
+
+static struct flash_platform_data da850evm_spiflash_data = {
+	.name		= "m25p80",
+	.parts		= da850evm_spiflash_part,
+	.nr_parts	= ARRAY_SIZE(da850evm_spiflash_part),
+	.type		= "m25p64",
+};
+
+static struct davinci_spi_config da850evm_spiflash_cfg = {
+	.io_type	= SPI_IO_TYPE_DMA,
+	.c2tdelay	= 8,
+	.t2cdelay	= 8,
+};
+
+static struct spi_board_info da850evm_spi_info[] = {
+	{
+		.modalias		= "m25p80",
+		.platform_data		= &da850evm_spiflash_data,
+		.controller_data	= &da850evm_spiflash_cfg,
+		.mode			= SPI_MODE_0,
+		.max_speed_hz		= 30000000,
+		.bus_num		= 1,
+		.chip_select		= 0,
+	},
+};
+
 static struct mtd_partition da850_evm_norflash_partition[] = {
 	{
 		.name           = "bootloaders + env",
@@ -231,8 +298,6 @@
 	-1
 };
 
-static u32 ui_card_detected;
-
 #if defined(CONFIG_MMC_DAVINCI) || \
     defined(CONFIG_MMC_DAVINCI_MODULE)
 #define HAS_MMC 1
@@ -244,7 +309,7 @@
 {
 	int ret = 0;
 
-	if (ui_card_detected & !HAS_MMC) {
+	if (!HAS_MMC) {
 		ret = davinci_cfg_reg_list(da850_evm_nand_pins);
 		if (ret)
 			pr_warning("da850_evm_init: nand mux setup failed: "
@@ -394,7 +459,6 @@
 		goto exp_setup_keys_fail;
 	}
 
-	ui_card_detected = 1;
 	pr_info("DA850/OMAP-L138 EVM UI card detected\n");
 
 	da850_evm_setup_nor_nand();
@@ -664,6 +728,13 @@
 	.rxnumevt	= 1,
 };
 
+static const short da850_evm_mcasp_pins[] __initconst = {
+	DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
+	DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE,
+	DA850_AXR_11, DA850_AXR_12,
+	-1
+};
+
 static int da850_evm_mmc_get_ro(int index)
 {
 	return gpio_get_value(DA850_MMCSD_WP_PIN);
@@ -683,6 +754,13 @@
 	.version	= MMC_CTLR_VERSION_2,
 };
 
+static const short da850_evm_mmcsd0_pins[] __initconst = {
+	DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
+	DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
+	DA850_GPIO4_0, DA850_GPIO4_1,
+	-1
+};
+
 static void da850_panel_power_ctrl(int val)
 {
 	/* lcd backlight */
@@ -1070,7 +1148,7 @@
 				ret);
 
 	if (HAS_MMC) {
-		ret = davinci_cfg_reg_list(da850_mmcsd0_pins);
+		ret = davinci_cfg_reg_list(da850_evm_mmcsd0_pins);
 		if (ret)
 			pr_warning("da850_evm_init: mmcsd0 mux setup failed:"
 					" %d\n", ret);
@@ -1106,7 +1184,7 @@
 	__raw_writel(0, IO_ADDRESS(DA8XX_UART1_BASE) + 0x30);
 	__raw_writel(0, IO_ADDRESS(DA8XX_UART0_BASE) + 0x30);
 
-	ret = davinci_cfg_reg_list(da850_mcasp_pins);
+	ret = davinci_cfg_reg_list(da850_evm_mcasp_pins);
 	if (ret)
 		pr_warning("da850_evm_init: mcasp mux setup failed: %d\n",
 				ret);
@@ -1153,6 +1231,12 @@
 	if (ret)
 		pr_warning("da850_evm_init: suspend registration failed: %d\n",
 				ret);
+
+	ret = da8xx_register_spi(1, da850evm_spi_info,
+				 ARRAY_SIZE(da850evm_spi_info));
+	if (ret)
+		pr_warning("da850_evm_init: spi 1 registration failed: %d\n",
+				ret);
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-dm644x-evm.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-dm644x-evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-dm644x-evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -440,11 +440,6 @@
 	gpio_request(gpio + 7, "nCF_SEL");
 	gpio_direction_output(gpio + 7, 1);
 
-	/* irlml6401 switches over 1A, in under 8 msec;
-	 * now it can be managed by nDRV_VBUS ...
-	 */
-	davinci_setup_usb(1000, 8);
-
 	return 0;
 }
 
@@ -705,6 +700,9 @@
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 
+	/* irlml6401 switches over 1A, in under 8 msec */
+	davinci_setup_usb(1000, 8);
+
 	soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-mityomapl138.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-mityomapl138.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-mityomapl138.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-mityomapl138.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,8 @@
 #include <linux/i2c.h>
 #include <linux/i2c/at24.h>
 #include <linux/etherdevice.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/flash.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -25,8 +27,9 @@
 #include <mach/da8xx.h>
 #include <mach/nand.h>
 #include <mach/mux.h>
+#include <mach/spi.h>
 
-#define MITYOMAPL138_PHY_ID		"0:03"
+#define MITYOMAPL138_PHY_ID		""
 
 #define FACTORY_CONFIG_MAGIC	0x012C0138
 #define FACTORY_CONFIG_VERSION	0x00010001
@@ -44,38 +47,109 @@
 
 static struct factory_config factory_config;
 
+struct part_no_info {
+	const char	*part_no;	/* part number string of interest */
+	int		max_freq;	/* khz */
+};
+
+static struct part_no_info mityomapl138_pn_info[] = {
+	{
+		.part_no	= "L138-C",
+		.max_freq	= 300000,
+	},
+	{
+		.part_no	= "L138-D",
+		.max_freq	= 375000,
+	},
+	{
+		.part_no	= "L138-F",
+		.max_freq	= 456000,
+	},
+	{
+		.part_no	= "1808-C",
+		.max_freq	= 300000,
+	},
+	{
+		.part_no	= "1808-D",
+		.max_freq	= 375000,
+	},
+	{
+		.part_no	= "1808-F",
+		.max_freq	= 456000,
+	},
+	{
+		.part_no	= "1810-D",
+		.max_freq	= 375000,
+	},
+};
+
+#ifdef CONFIG_CPU_FREQ
+static void mityomapl138_cpufreq_init(const char *partnum)
+{
+	int i, ret;
+
+	for (i = 0; partnum && i < ARRAY_SIZE(mityomapl138_pn_info); i++) {
+		/*
+		 * the part number has additional characters beyond what is
+		 * stored in the table.  This information is not needed for
+		 * determining the speed grade, and would require several
+		 * more table entries.  Only check the first N characters
+		 * for a match.
+		 */
+		if (!strncmp(partnum, mityomapl138_pn_info[i].part_no,
+			     strlen(mityomapl138_pn_info[i].part_no))) {
+			da850_max_speed = mityomapl138_pn_info[i].max_freq;
+			break;
+		}
+	}
+
+	ret = da850_register_cpufreq("pll0_sysclk3");
+	if (ret)
+		pr_warning("cpufreq registration failed: %d\n", ret);
+}
+#else
+static void mityomapl138_cpufreq_init(const char *partnum) { }
+#endif
+
 static void read_factory_config(struct memory_accessor *a, void *context)
 {
 	int ret;
+	const char *partnum = NULL;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
 	if (ret != sizeof(struct factory_config)) {
 		pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n",
 				ret);
-		return;
+		goto bad_config;
 	}
 
 	if (factory_config.magic != FACTORY_CONFIG_MAGIC) {
 		pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n",
 				factory_config.magic);
-		return;
+		goto bad_config;
 	}
 
 	if (factory_config.version != FACTORY_CONFIG_VERSION) {
 		pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n",
 				factory_config.version);
-		return;
+		goto bad_config;
 	}
 
 	pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac);
-	pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum);
 	if (is_valid_ether_addr(factory_config.mac))
 		memcpy(soc_info->emac_pdata->mac_addr,
 			factory_config.mac, ETH_ALEN);
 	else
 		pr_warning("MityOMAPL138: Invalid MAC found "
 				"in factory config block\n");
+
+	partnum = factory_config.partnum;
+	pr_info("MityOMAPL138: Part Number = %s\n", partnum);
+
+bad_config:
+	/* default maximum speed is valid for all platforms */
+	mityomapl138_cpufreq_init(partnum);
 }
 
 static struct at24_platform_data mityomapl138_fd_chip = {
@@ -223,6 +297,82 @@
 }
 
 /*
+ * SPI Devices:
+ *	SPI1_CS0: 8M Flash ST-M25P64-VME6G
+ */
+static struct mtd_partition spi_flash_partitions[] = {
+	[0] = {
+		.name		= "ubl",
+		.offset		= 0,
+		.size		= SZ_64K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[1] = {
+		.name		= "u-boot",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_512K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[2] = {
+		.name		= "u-boot-env",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_64K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[3] = {
+		.name		= "periph-config",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_64K,
+		.mask_flags	= MTD_WRITEABLE,
+	},
+	[4] = {
+		.name		= "reserved",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_256K + SZ_64K,
+	},
+	[5] = {
+		.name		= "kernel",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M + SZ_1M,
+	},
+	[6] = {
+		.name		= "fpga",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= SZ_2M,
+	},
+	[7] = {
+		.name		= "spare",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+	},
+};
+
+static struct flash_platform_data mityomapl138_spi_flash_data = {
+	.name		= "m25p80",
+	.parts		= spi_flash_partitions,
+	.nr_parts	= ARRAY_SIZE(spi_flash_partitions),
+	.type		= "m24p64",
+};
+
+static struct davinci_spi_config spi_eprom_config = {
+	.io_type	= SPI_IO_TYPE_DMA,
+	.c2tdelay	= 8,
+	.t2cdelay	= 8,
+};
+
+static struct spi_board_info mityomapl138_spi_flash_info[] = {
+	{
+		.modalias		= "m25p80",
+		.platform_data		= &mityomapl138_spi_flash_data,
+		.controller_data	= &spi_eprom_config,
+		.mode			= SPI_MODE_0,
+		.max_speed_hz		= 30000000,
+		.bus_num		= 1,
+		.chip_select		= 0,
+	},
+};
+
+/*
  * MityDSP-L138 includes a 256 MByte large-page NAND flash
  * (128K blocks).
  */
@@ -264,7 +414,7 @@
 
 static struct platform_device mityomapl138_nandflash_device = {
 	.name		= "davinci_nand",
-	.id		= 0,
+	.id		= 1,
 	.dev		= {
 		.platform_data	= &mityomapl138_nandflash_data,
 	},
@@ -377,16 +527,17 @@
 
 	mityomapl138_setup_nand();
 
+	ret = da8xx_register_spi(1, mityomapl138_spi_flash_info,
+			       ARRAY_SIZE(mityomapl138_spi_flash_info));
+	if (ret)
+		pr_warning("spi 1 registration failed: %d\n", ret);
+
 	mityomapl138_config_emac();
 
 	ret = da8xx_register_rtc();
 	if (ret)
 		pr_warning("rtc setup failed: %d\n", ret);
 
-	ret = da850_register_cpufreq("pll0_sysclk3");
-	if (ret)
-		pr_warning("cpufreq registration failed: %d\n", ret);
-
 	ret = da8xx_register_cpuidle();
 	if (ret)
 		pr_warning("cpuidle registration failed: %d\n", ret);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-neuros-osd2.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-neuros-osd2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-neuros-osd2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-neuros-osd2.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
  * DM644X-EVM board. It has:
  * 	DM6446M02 module with 256MB NAND, 256MB RAM, TLV320AIC32 AIC,
  * 	USB, Ethernet, SD/MMC, UART, THS8200, TVP7000 for video.
- * 	Additionaly realtime clock, IR remote control receiver,
+ * 	Additionally realtime clock, IR remote control receiver,
  * 	IR Blaster based on MSP430 (firmware although is different
  * 	from used in DM644X-EVM), internal ATA-6 3.5â€� HDD drive
  * 	with PATA interface, two muxed red-green leds.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-omapl138-hawk.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,279 @@
 
 #include <mach/cp_intc.h>
 #include <mach/da8xx.h>
+#include <mach/mux.h>
+
+#define HAWKBOARD_PHY_ID		"0:07"
+#define DA850_HAWK_MMCSD_CD_PIN		GPIO_TO_PIN(3, 12)
+#define DA850_HAWK_MMCSD_WP_PIN		GPIO_TO_PIN(3, 13)
+
+#define DA850_USB1_VBUS_PIN		GPIO_TO_PIN(2, 4)
+#define DA850_USB1_OC_PIN		GPIO_TO_PIN(6, 13)
+
+static short omapl138_hawk_mii_pins[] __initdata = {
+	DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
+	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
+	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
+	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
+	DA850_MDIO_D,
+	-1
+};
+
+static __init void omapl138_hawk_config_emac(void)
+{
+	void __iomem *cfgchip3 = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
+	int ret;
+	u32 val;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	val = __raw_readl(cfgchip3);
+	val &= ~BIT(8);
+	ret = davinci_cfg_reg_list(omapl138_hawk_mii_pins);
+	if (ret) {
+		pr_warning("%s: cpgmac/mii mux setup failed: %d\n",
+			__func__, ret);
+		return;
+	}
+
+	/* configure the CFGCHIP3 register for MII */
+	__raw_writel(val, cfgchip3);
+	pr_info("EMAC: MII PHY configured\n");
+
+	soc_info->emac_pdata->phy_id = HAWKBOARD_PHY_ID;
+
+	ret = da8xx_register_emac();
+	if (ret)
+		pr_warning("%s: emac registration failed: %d\n",
+			__func__, ret);
+}
+
+/*
+ * The following EDMA channels/slots are not being used by drivers (for
+ * example: Timer, GPIO, UART events etc) on da850/omap-l138 EVM/Hawkboard,
+ * hence they are being reserved for codecs on the DSP side.
+ */
+static const s16 da850_dma0_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 8,  6},
+	{24,  4},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da850_dma0_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 8,  6},
+	{24,  4},
+	{30, 50},
+	{-1, -1}
+};
+
+static const s16 da850_dma1_rsv_chans[][2] = {
+	/* (offset, number) */
+	{ 0, 28},
+	{30,  2},
+	{-1, -1}
+};
+
+static const s16 da850_dma1_rsv_slots[][2] = {
+	/* (offset, number) */
+	{ 0, 28},
+	{30, 90},
+	{-1, -1}
+};
+
+static struct edma_rsv_info da850_edma_cc0_rsv = {
+	.rsv_chans	= da850_dma0_rsv_chans,
+	.rsv_slots	= da850_dma0_rsv_slots,
+};
+
+static struct edma_rsv_info da850_edma_cc1_rsv = {
+	.rsv_chans	= da850_dma1_rsv_chans,
+	.rsv_slots	= da850_dma1_rsv_slots,
+};
+
+static struct edma_rsv_info *da850_edma_rsv[2] = {
+	&da850_edma_cc0_rsv,
+	&da850_edma_cc1_rsv,
+};
+
+static const short hawk_mmcsd0_pins[] = {
+	DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
+	DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
+	DA850_GPIO3_12, DA850_GPIO3_13,
+	-1
+};
+
+static int da850_hawk_mmc_get_ro(int index)
+{
+	return gpio_get_value(DA850_HAWK_MMCSD_WP_PIN);
+}
+
+static int da850_hawk_mmc_get_cd(int index)
+{
+	return !gpio_get_value(DA850_HAWK_MMCSD_CD_PIN);
+}
+
+static struct davinci_mmc_config da850_mmc_config = {
+	.get_ro		= da850_hawk_mmc_get_ro,
+	.get_cd		= da850_hawk_mmc_get_cd,
+	.wires		= 4,
+	.max_freq	= 50000000,
+	.caps		= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+	.version	= MMC_CTLR_VERSION_2,
+};
+
+static __init void omapl138_hawk_mmc_init(void)
+{
+	int ret;
+
+	ret = davinci_cfg_reg_list(hawk_mmcsd0_pins);
+	if (ret) {
+		pr_warning("%s: MMC/SD0 mux setup failed: %d\n",
+			__func__, ret);
+		return;
+	}
+
+	ret = gpio_request_one(DA850_HAWK_MMCSD_CD_PIN,
+			GPIOF_DIR_IN, "MMC CD");
+	if (ret < 0) {
+		pr_warning("%s: can not open GPIO %d\n",
+			__func__, DA850_HAWK_MMCSD_CD_PIN);
+		return;
+	}
+
+	ret = gpio_request_one(DA850_HAWK_MMCSD_WP_PIN,
+			GPIOF_DIR_IN, "MMC WP");
+	if (ret < 0) {
+		pr_warning("%s: can not open GPIO %d\n",
+			__func__, DA850_HAWK_MMCSD_WP_PIN);
+		goto mmc_setup_wp_fail;
+	}
+
+	ret = da8xx_register_mmcsd0(&da850_mmc_config);
+	if (ret) {
+		pr_warning("%s: MMC/SD0 registration failed: %d\n",
+			__func__, ret);
+		goto mmc_setup_mmcsd_fail;
+	}
+
+	return;
+
+mmc_setup_mmcsd_fail:
+	gpio_free(DA850_HAWK_MMCSD_WP_PIN);
+mmc_setup_wp_fail:
+	gpio_free(DA850_HAWK_MMCSD_CD_PIN);
+}
+
+static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id);
+static da8xx_ocic_handler_t hawk_usb_ocic_handler;
+
+static const short da850_hawk_usb11_pins[] = {
+	DA850_GPIO2_4, DA850_GPIO6_13,
+	-1
+};
+
+static int hawk_usb_set_power(unsigned port, int on)
+{
+	gpio_set_value(DA850_USB1_VBUS_PIN, on);
+	return 0;
+}
+
+static int hawk_usb_get_power(unsigned port)
+{
+	return gpio_get_value(DA850_USB1_VBUS_PIN);
+}
+
+static int hawk_usb_get_oci(unsigned port)
+{
+	return !gpio_get_value(DA850_USB1_OC_PIN);
+}
+
+static int hawk_usb_ocic_notify(da8xx_ocic_handler_t handler)
+{
+	int irq         = gpio_to_irq(DA850_USB1_OC_PIN);
+	int error       = 0;
+
+	if (handler != NULL) {
+		hawk_usb_ocic_handler = handler;
+
+		error = request_irq(irq, omapl138_hawk_usb_ocic_irq,
+					IRQF_DISABLED | IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING,
+					"OHCI over-current indicator", NULL);
+		if (error)
+			pr_err("%s: could not request IRQ to watch "
+				"over-current indicator changes\n", __func__);
+	} else {
+		free_irq(irq, NULL);
+	}
+	return error;
+}
+
+static struct da8xx_ohci_root_hub omapl138_hawk_usb11_pdata = {
+	.set_power      = hawk_usb_set_power,
+	.get_power      = hawk_usb_get_power,
+	.get_oci        = hawk_usb_get_oci,
+	.ocic_notify    = hawk_usb_ocic_notify,
+	/* TPS2087 switch @ 5V */
+	.potpgt         = (3 + 1) / 2,  /* 3 ms max */
+};
+
+static irqreturn_t omapl138_hawk_usb_ocic_irq(int irq, void *dev_id)
+{
+	hawk_usb_ocic_handler(&omapl138_hawk_usb11_pdata, 1);
+	return IRQ_HANDLED;
+}
+
+static __init void omapl138_hawk_usb_init(void)
+{
+	int ret;
+	u32 cfgchip2;
+
+	ret = davinci_cfg_reg_list(da850_hawk_usb11_pins);
+	if (ret) {
+		pr_warning("%s: USB 1.1 PinMux setup failed: %d\n",
+			__func__, ret);
+		return;
+	}
+
+	/* Setup the Ref. clock frequency for the HAWK at 24 MHz. */
+
+	cfgchip2 = __raw_readl(DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+	cfgchip2 &= ~CFGCHIP2_REFFREQ;
+	cfgchip2 |=  CFGCHIP2_REFFREQ_24MHZ;
+	__raw_writel(cfgchip2, DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP2_REG));
+
+	ret = gpio_request_one(DA850_USB1_VBUS_PIN,
+			GPIOF_DIR_OUT, "USB1 VBUS");
+	if (ret < 0) {
+		pr_err("%s: failed to request GPIO for USB 1.1 port "
+			"power control: %d\n", __func__, ret);
+		return;
+	}
+
+	ret = gpio_request_one(DA850_USB1_OC_PIN,
+			GPIOF_DIR_IN, "USB1 OC");
+	if (ret < 0) {
+		pr_err("%s: failed to request GPIO for USB 1.1 port "
+			"over-current indicator: %d\n", __func__, ret);
+		goto usb11_setup_oc_fail;
+	}
+
+	ret = da8xx_register_usb11(&omapl138_hawk_usb11_pdata);
+	if (ret) {
+		pr_warning("%s: USB 1.1 registration failed: %d\n",
+			__func__, ret);
+		goto usb11_setup_fail;
+	}
+
+	return;
+
+usb11_setup_fail:
+	gpio_free(DA850_USB1_OC_PIN);
+usb11_setup_oc_fail:
+	gpio_free(DA850_USB1_VBUS_PIN);
+}
 
 static struct davinci_uart_config omapl138_hawk_uart_config __initdata = {
 	.enabled_uarts = 0x7,
@@ -30,6 +303,17 @@
 
 	davinci_serial_init(&omapl138_hawk_uart_config);
 
+	omapl138_hawk_config_emac();
+
+	ret = da850_register_edma(da850_edma_rsv);
+	if (ret)
+		pr_warning("%s: EDMA registration failed: %d\n",
+			__func__, ret);
+
+	omapl138_hawk_mmc_init();
+
+	omapl138_hawk_usb_init();
+
 	ret = da8xx_register_watchdog();
 	if (ret)
 		pr_warning("omapl138_hawk_init: "
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/board-tnetv107x-evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/spi/spi.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
@@ -37,6 +38,7 @@
 
 #define EVM_MMC_WP_GPIO		21
 #define EVM_MMC_CD_GPIO		24
+#define EVM_SPI_CS_GPIO		54
 
 static int initialize_gpio(int gpio, char *desc)
 {
@@ -99,6 +101,12 @@
 	-1
 };
 
+static const short ssp_pins[] __initdata = {
+	TNETV107X_SSP0_0, TNETV107X_SSP0_1, TNETV107X_SSP0_2,
+	TNETV107X_SSP1_0, TNETV107X_SSP1_1, TNETV107X_SSP1_2,
+	TNETV107X_SSP1_3, -1
+};
+
 static struct mtd_partition nand_partitions[] = {
 	/* bootloader (U-Boot, etc) in first 12 sectors */
 	{
@@ -196,19 +204,68 @@
 	.no_autorepeat	= 0,
 };
 
+static void spi_select_device(int cs)
+{
+	static int gpio;
+
+	if (!gpio) {
+		int ret;
+		ret = gpio_request(EVM_SPI_CS_GPIO, "spi chipsel");
+		if (ret < 0) {
+			pr_err("cannot open spi chipsel gpio\n");
+			gpio = -ENOSYS;
+			return;
+		} else {
+			gpio = EVM_SPI_CS_GPIO;
+			gpio_direction_output(gpio, 0);
+		}
+	}
+
+	if (gpio < 0)
+		return;
+
+	return gpio_set_value(gpio, cs ? 1 : 0);
+}
+
+static struct ti_ssp_spi_data spi_master_data = {
+	.num_cs	= 2,
+	.select	= spi_select_device,
+	.iosel	= SSP_PIN_SEL(0, SSP_CLOCK)	| SSP_PIN_SEL(1, SSP_DATA) |
+		  SSP_PIN_SEL(2, SSP_CHIPSEL)	| SSP_PIN_SEL(3, SSP_IN)   |
+		  SSP_INPUT_SEL(3),
+};
+
+static struct ti_ssp_data ssp_config = {
+	.out_clock	= 250 * 1000,
+	.dev_data	= {
+		[1] = {
+			.dev_name = "ti-ssp-spi",
+			.pdata = &spi_master_data,
+			.pdata_size = sizeof(spi_master_data),
+		},
+	},
+};
+
 static struct tnetv107x_device_info evm_device_info __initconst = {
 	.serial_config		= &serial_config,
 	.mmc_config[1]		= &mmc_config,	/* controller 1 */
 	.nand_config[0]		= &nand_config,	/* chip select 0 */
 	.keypad_config		= &keypad_config,
+	.ssp_config		= &ssp_config,
+};
+
+static struct spi_board_info spi_info[] __initconst = {
 };
 
 static __init void tnetv107x_evm_board_init(void)
 {
 	davinci_cfg_reg_list(sdio1_pins);
 	davinci_cfg_reg_list(uart1_pins);
+	davinci_cfg_reg_list(ssp_pins);
 
 	tnetv107x_devices_init(&evm_device_info);
+
+	spi_register_board_info(spi_info, ARRAY_SIZE(spi_info));
 }
 
 #ifdef CONFIG_SERIAL_8250_CONSOLE
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/cp_intc.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/cp_intc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/cp_intc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/cp_intc.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,9 +167,9 @@
 
 	/* Set up genirq dispatching for cp_intc */
 	for (i = 0; i < num_irq; i++) {
-		set_irq_chip(i, &cp_intc_irq_chip);
+		irq_set_chip(i, &cp_intc_irq_chip);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-		set_irq_handler(i, handle_edge_irq);
+		irq_set_handler(i, handle_edge_irq);
 	}
 
 	/* Enable global interrupt */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/cpufreq.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 	/*
 	 * Time measurement across the target() function yields ~1500-1800us
 	 * time taken with no drivers on notification list.
-	 * Setting the latency to 2000 us to accomodate addition of drivers
+	 * Setting the latency to 2000 us to accommodate addition of drivers
 	 * to pre/post change notification list.
 	 */
 	policy->cpuinfo.transition_latency = 2000 * 1000;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/da830.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/da830.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/da830.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/da830.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,7 +148,7 @@
 static struct clk dmax_clk = {
 	.name		= "dmax",
 	.parent		= &pll0_sysclk2,
-	.lpsc		= DA8XX_LPSC0_DMAX,
+	.lpsc		= DA8XX_LPSC0_PRUSS,
 	.flags		= ALWAYS_ENABLED,
 };
 
@@ -397,8 +397,8 @@
 	CLK(NULL,		"uart0",	&uart0_clk),
 	CLK(NULL,		"uart1",	&uart1_clk),
 	CLK(NULL,		"uart2",	&uart2_clk),
-	CLK("dm_spi.0",		NULL,		&spi0_clk),
-	CLK("dm_spi.1",		NULL,		&spi1_clk),
+	CLK("spi_davinci.0",	NULL,		&spi0_clk),
+	CLK("spi_davinci.1",	NULL,		&spi1_clk),
 	CLK(NULL,		"ecap0",	&ecap0_clk),
 	CLK(NULL,		"ecap1",	&ecap1_clk),
 	CLK(NULL,		"ecap2",	&ecap2_clk),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/da850.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/da850.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/da850.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/da850.c	2011-05-19 00:06:34.000000000 -0400
@@ -345,6 +345,34 @@
 	.flags		= ALWAYS_ENABLED,
 };
 
+static struct clk usb11_clk = {
+	.name		= "usb11",
+	.parent		= &pll0_sysclk4,
+	.lpsc		= DA8XX_LPSC1_USB11,
+	.gpsc		= 1,
+};
+
+static struct clk usb20_clk = {
+	.name		= "usb20",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC1_USB20,
+	.gpsc		= 1,
+};
+
+static struct clk spi0_clk = {
+	.name		= "spi0",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC0_SPI0,
+};
+
+static struct clk spi1_clk = {
+	.name		= "spi1",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA8XX_LPSC1_SPI1,
+	.gpsc		= 1,
+	.flags		= DA850_CLK_ASYNC3,
+};
+
 static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"ref",		&ref_clk),
 	CLK(NULL,		"pll0",		&pll0_clk),
@@ -387,6 +415,10 @@
 	CLK("davinci_mmc.0",	NULL,		&mmcsd0_clk),
 	CLK("davinci_mmc.1",	NULL,		&mmcsd1_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
+	CLK(NULL,		"usb11",	&usb11_clk),
+	CLK(NULL,		"usb20",	&usb20_clk),
+	CLK("spi_davinci.0",	NULL,		&spi0_clk),
+	CLK("spi_davinci.1",	NULL,		&spi1_clk),
 	CLK(NULL,		NULL,		NULL),
 };
 
@@ -543,30 +575,19 @@
 	MUX_CFG(DA850, EMA_WAIT_1,	6,	24,	15,	1,	false)
 	MUX_CFG(DA850, NEMA_CS_2,	7,	0,	15,	1,	false)
 	/* GPIO function */
+	MUX_CFG(DA850, GPIO2_4,		6,	12,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_6,		6,	4,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_8,		5,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO2_15,	5,	0,	15,	8,	false)
+	MUX_CFG(DA850, GPIO3_12,	7,	12,	15,	8,	false)
+	MUX_CFG(DA850, GPIO3_13,	7,	8,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_0,		10,	28,	15,	8,	false)
 	MUX_CFG(DA850, GPIO4_1,		10,	24,	15,	8,	false)
+	MUX_CFG(DA850, GPIO6_13,	13,	8,	15,	8,	false)
 	MUX_CFG(DA850, RTC_ALARM,	0,	28,	15,	2,	false)
 #endif
 };
 
-const short da850_uart0_pins[] __initdata = {
-	DA850_NUART0_CTS, DA850_NUART0_RTS, DA850_UART0_RXD, DA850_UART0_TXD,
-	-1
-};
-
-const short da850_uart1_pins[] __initdata = {
-	DA850_UART1_RXD, DA850_UART1_TXD,
-	-1
-};
-
-const short da850_uart2_pins[] __initdata = {
-	DA850_UART2_RXD, DA850_UART2_TXD,
-	-1
-};
-
 const short da850_i2c0_pins[] __initdata = {
 	DA850_I2C0_SDA, DA850_I2C0_SCL,
 	-1
@@ -577,24 +598,6 @@
 	-1
 };
 
-const short da850_cpgmac_pins[] __initdata = {
-	DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
-	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
-	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
-	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
-	DA850_MDIO_D, DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
-	DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER,
-	DA850_RMII_MHZ_50_CLK,
-	-1
-};
-
-const short da850_mcasp_pins[] __initdata = {
-	DA850_AHCLKX, DA850_ACLKX, DA850_AFSX,
-	DA850_AHCLKR, DA850_ACLKR, DA850_AFSR, DA850_AMUTE,
-	DA850_AXR_11, DA850_AXR_12,
-	-1
-};
-
 const short da850_lcdcntl_pins[] __initdata = {
 	DA850_LCD_D_0, DA850_LCD_D_1, DA850_LCD_D_2, DA850_LCD_D_3,
 	DA850_LCD_D_4, DA850_LCD_D_5, DA850_LCD_D_6, DA850_LCD_D_7,
@@ -604,29 +607,6 @@
 	-1
 };
 
-const short da850_mmcsd0_pins[] __initdata = {
-	DA850_MMCSD0_DAT_0, DA850_MMCSD0_DAT_1, DA850_MMCSD0_DAT_2,
-	DA850_MMCSD0_DAT_3, DA850_MMCSD0_CLK, DA850_MMCSD0_CMD,
-	DA850_GPIO4_0, DA850_GPIO4_1,
-	-1
-};
-
-const short da850_emif25_pins[] __initdata = {
-	DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
-	DA850_NEMA_CS_3, DA850_NEMA_CS_4, DA850_NEMA_WE, DA850_NEMA_OE,
-	DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
-	DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
-	DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
-	DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
-	DA850_EMA_A_0, DA850_EMA_A_1, DA850_EMA_A_2, DA850_EMA_A_3,
-	DA850_EMA_A_4, DA850_EMA_A_5, DA850_EMA_A_6, DA850_EMA_A_7,
-	DA850_EMA_A_8, DA850_EMA_A_9, DA850_EMA_A_10, DA850_EMA_A_11,
-	DA850_EMA_A_12, DA850_EMA_A_13, DA850_EMA_A_14, DA850_EMA_A_15,
-	DA850_EMA_A_16, DA850_EMA_A_17, DA850_EMA_A_18, DA850_EMA_A_19,
-	DA850_EMA_A_20, DA850_EMA_A_21, DA850_EMA_A_22, DA850_EMA_A_23,
-	-1
-};
-
 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 static u8 da850_default_priorities[DA850_N_CP_INTC_IRQ] = {
 	[IRQ_DA8XX_COMMTX]		= 7,
@@ -764,6 +744,13 @@
 		.cpu_id		= DAVINCI_CPU_ID_DA850,
 		.name		= "da850/omap-l138",
 	},
+	{
+		.variant	= 0x1,
+		.part_no	= 0xb7d1,
+		.manufacturer	= 0x017,	/* 0x02f >> 1 */
+		.cpu_id		= DAVINCI_CPU_ID_DA850,
+		.name		= "da850/omap-l138/am18x",
+	},
 };
 
 static struct davinci_timer_instance da850_timer_instance[4] = {
@@ -1136,7 +1123,7 @@
 	 * This helps keeping the peripherals on this domain insulated
 	 * from CPU frequency changes caused by DVFS. The firmware sets
 	 * both PLL0 and PLL1 to the same frequency so, there should not
-	 * be any noticible change even in non-DVFS use cases.
+	 * be any noticeable change even in non-DVFS use cases.
 	 */
 	da850_set_async3_src(1);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/devices-da8xx.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/devices-da8xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/devices-da8xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/devices-da8xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,12 +38,24 @@
 #define DA8XX_EMAC_MDIO_BASE		0x01e24000
 #define DA8XX_GPIO_BASE			0x01e26000
 #define DA8XX_I2C1_BASE			0x01e28000
+#define DA8XX_SPI0_BASE			0x01c41000
+#define DA830_SPI1_BASE			0x01e12000
+#define DA850_SPI1_BASE			0x01f0e000
 
 #define DA8XX_EMAC_CTRL_REG_OFFSET	0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET	0x2000
 #define DA8XX_EMAC_RAM_OFFSET		0x0000
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 
+#define DA8XX_DMA_SPI0_RX	EDMA_CTLR_CHAN(0, 14)
+#define DA8XX_DMA_SPI0_TX	EDMA_CTLR_CHAN(0, 15)
+#define DA8XX_DMA_MMCSD0_RX	EDMA_CTLR_CHAN(0, 16)
+#define DA8XX_DMA_MMCSD0_TX	EDMA_CTLR_CHAN(0, 17)
+#define DA8XX_DMA_SPI1_RX	EDMA_CTLR_CHAN(0, 18)
+#define DA8XX_DMA_SPI1_TX	EDMA_CTLR_CHAN(0, 19)
+#define DA850_DMA_MMCSD1_RX	EDMA_CTLR_CHAN(1, 28)
+#define DA850_DMA_MMCSD1_TX	EDMA_CTLR_CHAN(1, 29)
+
 void __iomem *da8xx_syscfg0_base;
 void __iomem *da8xx_syscfg1_base;
 
@@ -573,13 +585,13 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	{		/* DMA RX */
-		.start	= EDMA_CTLR_CHAN(0, 16),
-		.end	= EDMA_CTLR_CHAN(0, 16),
+		.start	= DA8XX_DMA_MMCSD0_RX,
+		.end	= DA8XX_DMA_MMCSD0_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 	{		/* DMA TX */
-		.start	= EDMA_CTLR_CHAN(0, 17),
-		.end	= EDMA_CTLR_CHAN(0, 17),
+		.start	= DA8XX_DMA_MMCSD0_TX,
+		.end	= DA8XX_DMA_MMCSD0_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
@@ -610,13 +622,13 @@
 		.flags	= IORESOURCE_IRQ,
 	},
 	{		/* DMA RX */
-		.start	= EDMA_CTLR_CHAN(1, 28),
-		.end	= EDMA_CTLR_CHAN(1, 28),
+		.start	= DA850_DMA_MMCSD1_RX,
+		.end	= DA850_DMA_MMCSD1_RX,
 		.flags	= IORESOURCE_DMA,
 	},
 	{		/* DMA TX */
-		.start	= EDMA_CTLR_CHAN(1, 29),
-		.end	= EDMA_CTLR_CHAN(1, 29),
+		.start	= DA850_DMA_MMCSD1_TX,
+		.end	= DA850_DMA_MMCSD1_TX,
 		.flags	= IORESOURCE_DMA,
 	},
 };
@@ -725,3 +737,106 @@
 
 	return platform_device_register(&da8xx_cpuidle_device);
 }
+
+static struct resource da8xx_spi0_resources[] = {
+	[0] = {
+		.start	= DA8XX_SPI0_BASE,
+		.end	= DA8XX_SPI0_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DA8XX_SPINT0,
+		.end	= IRQ_DA8XX_SPINT0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= DA8XX_DMA_SPI0_RX,
+		.end	= DA8XX_DMA_SPI0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DA8XX_DMA_SPI0_TX,
+		.end	= DA8XX_DMA_SPI0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource da8xx_spi1_resources[] = {
+	[0] = {
+		.start	= DA830_SPI1_BASE,
+		.end	= DA830_SPI1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_DA8XX_SPINT1,
+		.end	= IRQ_DA8XX_SPINT1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= DA8XX_DMA_SPI1_RX,
+		.end	= DA8XX_DMA_SPI1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DA8XX_DMA_SPI1_TX,
+		.end	= DA8XX_DMA_SPI1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct davinci_spi_platform_data da8xx_spi_pdata[] = {
+	[0] = {
+		.version	= SPI_VERSION_2,
+		.intr_line	= 1,
+		.dma_event_q	= EVENTQ_0,
+	},
+	[1] = {
+		.version	= SPI_VERSION_2,
+		.intr_line	= 1,
+		.dma_event_q	= EVENTQ_0,
+	},
+};
+
+static struct platform_device da8xx_spi_device[] = {
+	[0] = {
+		.name		= "spi_davinci",
+		.id		= 0,
+		.num_resources	= ARRAY_SIZE(da8xx_spi0_resources),
+		.resource	= da8xx_spi0_resources,
+		.dev		= {
+			.platform_data = &da8xx_spi_pdata[0],
+		},
+	},
+	[1] = {
+		.name		= "spi_davinci",
+		.id		= 1,
+		.num_resources	= ARRAY_SIZE(da8xx_spi1_resources),
+		.resource	= da8xx_spi1_resources,
+		.dev		= {
+			.platform_data = &da8xx_spi_pdata[1],
+		},
+	},
+};
+
+int __init da8xx_register_spi(int instance, struct spi_board_info *info,
+			      unsigned len)
+{
+	int ret;
+
+	if (instance < 0 || instance > 1)
+		return -EINVAL;
+
+	ret = spi_register_board_info(info, len);
+	if (ret)
+		pr_warning("%s: failed to register board info for spi %d :"
+			   " %d\n", __func__, instance, ret);
+
+	da8xx_spi_pdata[instance].num_chipselect = len;
+
+	if (instance == 1 && cpu_is_davinci_da850()) {
+		da8xx_spi1_resources[0].start = DA850_SPI1_BASE;
+		da8xx_spi1_resources[0].end = DA850_SPI1_BASE + SZ_4K - 1;
+	}
+
+	return platform_device_register(&da8xx_spi_device[instance]);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/devices-tnetv107x.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/devices-tnetv107x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/devices-tnetv107x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/devices-tnetv107x.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,7 @@
 #define TNETV107X_SDIO0_BASE			0x08088700
 #define TNETV107X_SDIO1_BASE			0x08088800
 #define TNETV107X_KEYPAD_BASE			0x08088a00
+#define TNETV107X_SSP_BASE			0x08088c00
 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE		0x08200000
 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE	0x30000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE	0x40000000
@@ -342,6 +343,25 @@
 	.resource	= tsc_resources,
 };
 
+static struct resource ssp_resources[] = {
+	{
+		.start	= TNETV107X_SSP_BASE,
+		.end	= TNETV107X_SSP_BASE + 0x1ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_TNETV107X_SSP,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device ssp_device = {
+	.name		= "ti-ssp",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(ssp_resources),
+	.resource	= ssp_resources,
+};
+
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
 	int i, error;
@@ -380,4 +400,9 @@
 		keypad_device.dev.platform_data = info->keypad_config;
 		platform_device_register(&keypad_device);
 	}
+
+	if (info->ssp_config) {
+		ssp_device.dev.platform_data = info->ssp_config;
+		platform_device_register(&ssp_device);
+	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/dm355.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/dm355.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/dm355.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/dm355.c	2011-05-19 00:06:34.000000000 -0400
@@ -314,7 +314,7 @@
 	.name = "timer2",
 	.parent = &pll1_aux_clk,
 	.lpsc = DAVINCI_LPSC_TIMER2,
-	.usecount = 1,              /* REVISIT: why cant' this be disabled? */
+	.usecount = 1,              /* REVISIT: why can't this be disabled? */
 };
 
 static struct clk timer3_clk = {
@@ -403,16 +403,13 @@
 		.start = 16,
 		.flags = IORESOURCE_DMA,
 	},
-	{
-		.start = EVENTQ_1,
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct davinci_spi_platform_data dm355_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
 	.cshold_bug	= true,
+	.dma_event_q	= EVENTQ_1,
 };
 static struct platform_device dm355_spi0_device = {
 	.name = "spi_davinci",
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/dm365.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/dm365.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/dm365.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/dm365.c	2011-05-19 00:06:34.000000000 -0400
@@ -625,6 +625,7 @@
 static struct davinci_spi_platform_data dm365_spi0_pdata = {
 	.version 	= SPI_VERSION_1,
 	.num_chipselect = 2,
+	.dma_event_q	= EVENTQ_3,
 };
 
 static struct resource dm365_spi0_resources[] = {
@@ -645,10 +646,6 @@
 		.start = 16,
 		.flags = IORESOURCE_DMA,
 	},
-	{
-		.start = EVENTQ_3,
-		.flags = IORESOURCE_DMA,
-	},
 };
 
 static struct platform_device dm365_spi0_device = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/dm644x.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/dm644x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/dm644x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/dm644x.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,7 +274,7 @@
 	.name = "timer2",
 	.parent = &pll1_aux_clk,
 	.lpsc = DAVINCI_LPSC_TIMER2,
-	.usecount = 1,              /* REVISIT: why cant' this be disabled? */
+	.usecount = 1,              /* REVISIT: why can't this be disabled? */
 };
 
 static struct clk_lookup dm644x_clks[] = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 {
 	struct davinci_gpio_regs __iomem *g;
 
-	g = (__force struct davinci_gpio_regs __iomem *)get_irq_chip_data(irq);
+	g = (__force struct davinci_gpio_regs __iomem *)irq_get_chip_data(irq);
 
 	return g;
 }
@@ -208,7 +208,7 @@
 static void gpio_irq_disable(struct irq_data *d)
 {
 	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_data(d);
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
 	__raw_writel(mask, &g->clr_falling);
 	__raw_writel(mask, &g->clr_rising);
@@ -217,8 +217,8 @@
 static void gpio_irq_enable(struct irq_data *d)
 {
 	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_data(d);
-	unsigned status = irq_desc[d->irq].status;
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
+	unsigned status = irqd_get_trigger_type(d);
 
 	status &= IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING;
 	if (!status)
@@ -233,21 +233,11 @@
 static int gpio_irq_type(struct irq_data *d, unsigned trigger)
 {
 	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_data(d);
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
 
-	irq_desc[d->irq].status &= ~IRQ_TYPE_SENSE_MASK;
-	irq_desc[d->irq].status |= trigger;
-
-	/* don't enable the IRQ if it's currently disabled */
-	if (irq_desc[d->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;
 }
 
@@ -256,6 +246,7 @@
 	.irq_enable	= gpio_irq_enable,
 	.irq_disable	= gpio_irq_disable,
 	.irq_set_type	= gpio_irq_type,
+	.flags		= IRQCHIP_SET_TYPE_MASKED,
 };
 
 static void
@@ -285,7 +276,7 @@
 			status >>= 16;
 
 		/* now demux them to the right lowlevel handler */
-		n = (int)get_irq_data(irq);
+		n = (int)irq_get_handler_data(irq);
 		while (status) {
 			res = ffs(status);
 			n += res;
@@ -323,7 +314,7 @@
 static int gpio_irq_type_unbanked(struct irq_data *d, unsigned trigger)
 {
 	struct davinci_gpio_regs __iomem *g = irq2regs(d->irq);
-	u32 mask = (u32) irq_data_get_irq_data(d);
+	u32 mask = (u32) irq_data_get_irq_handler_data(d);
 
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
@@ -395,7 +386,7 @@
 
 		/* AINTC handles mask/unmask; GPIO handles triggering */
 		irq = bank_irq;
-		gpio_irqchip_unbanked = *get_irq_desc_chip(irq_to_desc(irq));
+		gpio_irqchip_unbanked = *irq_get_chip(irq);
 		gpio_irqchip_unbanked.name = "GPIO-AINTC";
 		gpio_irqchip_unbanked.irq_set_type = gpio_irq_type_unbanked;
 
@@ -406,10 +397,10 @@
 
 		/* set the direct IRQs up to use that irqchip */
 		for (gpio = 0; gpio < soc_info->gpio_unbanked; gpio++, irq++) {
-			set_irq_chip(irq, &gpio_irqchip_unbanked);
-			set_irq_data(irq, (void *) __gpio_mask(gpio));
-			set_irq_chip_data(irq, (__force void *) g);
-			irq_desc[irq].status |= IRQ_TYPE_EDGE_BOTH;
+			irq_set_chip(irq, &gpio_irqchip_unbanked);
+			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
+			irq_set_chip_data(irq, (__force void *)g);
+			irq_set_status_flags(irq, IRQ_TYPE_EDGE_BOTH);
 		}
 
 		goto done;
@@ -430,15 +421,15 @@
 		__raw_writel(~0, &g->clr_rising);
 
 		/* set up all irqs in this bank */
-		set_irq_chained_handler(bank_irq, gpio_irq_handler);
-		set_irq_chip_data(bank_irq, (__force void *) g);
-		set_irq_data(bank_irq, (void *) irq);
+		irq_set_chained_handler(bank_irq, gpio_irq_handler);
+		irq_set_chip_data(bank_irq, (__force void *)g);
+		irq_set_handler_data(bank_irq, (void *)irq);
 
 		for (i = 0; i < 16 && gpio < ngpio; i++, irq++, gpio++) {
-			set_irq_chip(irq, &gpio_irqchip);
-			set_irq_chip_data(irq, (__force void *) g);
-			set_irq_data(irq, (void *) __gpio_mask(gpio));
-			set_irq_handler(irq, handle_simple_irq);
+			irq_set_chip(irq, &gpio_irqchip);
+			irq_set_chip_data(irq, (__force void *)g);
+			irq_set_handler_data(irq, (void *)__gpio_mask(gpio));
+			irq_set_handler(irq, handle_simple_irq);
 			set_irq_flags(irq, IRQF_VALID);
 		}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/cputype.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/cputype.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/cputype.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/cputype.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * Author: Kevin Hilman, Deep Root Systems, LLC
  *
  * Defines the cpu_is_*() macros for runtime detection of DaVinci
- * device type.  In addtion, if support for a given device is not
+ * device type.  In addition, if support for a given device is not
  * compiled in to the kernel, the macros return 0 so that
  * resulting code can be optimized out.
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/da8xx.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/da8xx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/da8xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/da8xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/davinci_emac.h>
+#include <linux/spi/spi.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -23,6 +24,7 @@
 #include <mach/mmc.h>
 #include <mach/usb.h>
 #include <mach/pm.h>
+#include <mach/spi.h>
 
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
@@ -77,6 +79,7 @@
 int da830_register_edma(struct edma_rsv_info *rsv);
 int da850_register_edma(struct edma_rsv_info *rsv[2]);
 int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
+int da8xx_register_spi(int instance, struct spi_board_info *info, unsigned len);
 int da8xx_register_watchdog(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
@@ -95,6 +98,7 @@
 extern struct emac_platform_data da8xx_emac_pdata;
 extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata;
 extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata;
+extern struct davinci_spi_platform_data da8xx_spi_pdata[];
 
 extern struct platform_device da8xx_wdt_device;
 
@@ -123,15 +127,8 @@
 extern const short da830_eqep0_pins[];
 extern const short da830_eqep1_pins[];
 
-extern const short da850_uart0_pins[];
-extern const short da850_uart1_pins[];
-extern const short da850_uart2_pins[];
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
-extern const short da850_cpgmac_pins[];
-extern const short da850_mcasp_pins[];
 extern const short da850_lcdcntl_pins[];
-extern const short da850_mmcsd0_pins[];
-extern const short da850_emif25_pins[];
 
 #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,9 @@
 
 #define UART_SHIFT	2
 
+#define davinci_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define davinci_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 davinci_uart_phys:	.word	0
 davinci_uart_virt:	.word	0
@@ -34,7 +37,7 @@
 		/* Use davinci_uart_phys/virt if already configured */
 10:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(davinci_uart_phys)
+		ldreq	\rp, =davinci_uart_v2p(davinci_uart_phys)
 		ldrne	\rp, =davinci_uart_phys
 		add	\rv, \rp, #4		@ davinci_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -48,18 +51,18 @@
 		tst	\rp, #1			@ MMU enabled?
 
 		/* Copy uart phys address from decompressor uart info */
-		ldreq	\rv, =__virt_to_phys(davinci_uart_phys)
+		ldreq	\rv, =davinci_uart_v2p(davinci_uart_phys)
 		ldrne	\rv, =davinci_uart_phys
 		ldreq	\rp, =DAVINCI_UART_INFO
-		ldrne	\rp, =__phys_to_virt(DAVINCI_UART_INFO)
+		ldrne	\rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
 		ldr	\rp, [\rp, #0]
 		str	\rp, [\rv]
 
 		/* Copy uart virt address from decompressor uart info */
-		ldreq	\rv, =__virt_to_phys(davinci_uart_virt)
+		ldreq	\rv, =davinci_uart_v2p(davinci_uart_virt)
 		ldrne	\rv, =davinci_uart_virt
 		ldreq	\rp, =DAVINCI_UART_INFO
-		ldrne	\rp, =__phys_to_virt(DAVINCI_UART_INFO)
+		ldrne	\rp, =davinci_uart_p2v(DAVINCI_UART_INFO)
 		ldr	\rp, [\rp, #4]
 		str	\rp, [\rv]
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/edma.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/edma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/edma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/edma.h	2011-05-19 00:06:34.000000000 -0400
@@ -151,42 +151,6 @@
 #define DA830_DMACH2EVENT_MAP1		0x00000000u
 #define DA830_EDMA_ARM_OWN		0x30FFCCFFu
 
-/* DA830 specific EDMA3 Events Information */
-enum DA830_edma_ch {
-	DA830_DMACH_MCASP0_RX,
-	DA830_DMACH_MCASP0_TX,
-	DA830_DMACH_MCASP1_RX,
-	DA830_DMACH_MCASP1_TX,
-	DA830_DMACH_MCASP2_RX,
-	DA830_DMACH_MCASP2_TX,
-	DA830_DMACH_GPIO_BNK0INT,
-	DA830_DMACH_GPIO_BNK1INT,
-	DA830_DMACH_UART0_RX,
-	DA830_DMACH_UART0_TX,
-	DA830_DMACH_TMR64P0_EVTOUT12,
-	DA830_DMACH_TMR64P0_EVTOUT34,
-	DA830_DMACH_UART1_RX,
-	DA830_DMACH_UART1_TX,
-	DA830_DMACH_SPI0_RX,
-	DA830_DMACH_SPI0_TX,
-	DA830_DMACH_MMCSD_RX,
-	DA830_DMACH_MMCSD_TX,
-	DA830_DMACH_SPI1_RX,
-	DA830_DMACH_SPI1_TX,
-	DA830_DMACH_DMAX_EVTOUT6,
-	DA830_DMACH_DMAX_EVTOUT7,
-	DA830_DMACH_GPIO_BNK2INT,
-	DA830_DMACH_GPIO_BNK3INT,
-	DA830_DMACH_I2C0_RX,
-	DA830_DMACH_I2C0_TX,
-	DA830_DMACH_I2C1_RX,
-	DA830_DMACH_I2C1_TX,
-	DA830_DMACH_GPIO_BNK4INT,
-	DA830_DMACH_GPIO_BNK5INT,
-	DA830_DMACH_UART2_RX,
-	DA830_DMACH_UART2_TX
-};
-
 /*ch_status paramater of callback function possible values*/
 #define DMA_COMPLETE 1
 #define DMA_CC_ERROR 2
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,9 +26,9 @@
 #if defined(CONFIG_ARCH_DAVINCI_DA8XX) && defined(CONFIG_ARCH_DAVINCI_DMx)
 #error Cannot enable DaVinci and DA8XX platforms concurrently
 #elif defined(CONFIG_ARCH_DAVINCI_DA8XX)
-#define PHYS_OFFSET DA8XX_DDR_BASE
+#define PLAT_PHYS_OFFSET DA8XX_DDR_BASE
 #else
-#define PHYS_OFFSET DAVINCI_DDR_BASE
+#define PLAT_PHYS_OFFSET DAVINCI_DDR_BASE
 #endif
 
 #define DDR2_SDRCR_OFFSET	0xc
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/mux.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/mux.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/mux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/mux.h	2011-05-19 00:06:34.000000000 -0400
@@ -908,11 +908,15 @@
 	DA850_NEMA_CS_2,
 
 	/* GPIO function */
+	DA850_GPIO2_4,
 	DA850_GPIO2_6,
 	DA850_GPIO2_8,
 	DA850_GPIO2_15,
+	DA850_GPIO3_12,
+	DA850_GPIO3_13,
 	DA850_GPIO4_0,
 	DA850_GPIO4_1,
+	DA850_GPIO6_13,
 	DA850_RTC_ALARM,
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/psc.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/psc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/psc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/psc.h	2011-05-19 00:06:34.000000000 -0400
@@ -150,7 +150,7 @@
 #define DA8XX_LPSC0_SCR0_SS		10
 #define DA8XX_LPSC0_SCR1_SS		11
 #define DA8XX_LPSC0_SCR2_SS		12
-#define DA8XX_LPSC0_DMAX		13
+#define DA8XX_LPSC0_PRUSS		13
 #define DA8XX_LPSC0_ARM			14
 #define DA8XX_LPSC0_GEM			15
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/serial.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/serial.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/serial.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/serial.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
  *
  * This area sits just below the page tables (see arch/arm/kernel/head.S).
  */
-#define DAVINCI_UART_INFO	(PHYS_OFFSET + 0x3ff8)
+#define DAVINCI_UART_INFO	(PLAT_PHYS_OFFSET + 0x3ff8)
 
 #define DAVINCI_UART0_BASE	(IO_PHYS + 0x20000)
 #define DAVINCI_UART1_BASE	(IO_PHYS + 0x20400)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/spi.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/spi.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/spi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/spi.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,8 @@
 #ifndef __ARCH_ARM_DAVINCI_SPI_H
 #define __ARCH_ARM_DAVINCI_SPI_H
 
+#include <mach/edma.h>
+
 #define SPI_INTERN_CS	0xFF
 
 enum {
@@ -39,13 +41,16 @@
  *		to populate if all chip-selects are internal.
  * @cshold_bug:	set this to true if the SPI controller on your chip requires
  *		a write to CSHOLD bit in between transfers (like in DM355).
+ * @dma_event_q: DMA event queue to use if SPI_IO_TYPE_DMA is used for any
+ *		device on the bus.
  */
 struct davinci_spi_platform_data {
-	u8	version;
-	u8	num_chipselect;
-	u8	intr_line;
-	u8	*chip_sel;
-	bool	cshold_bug;
+	u8			version;
+	u8			num_chipselect;
+	u8			intr_line;
+	u8			*chip_sel;
+	bool			cshold_bug;
+	enum dma_event_q	dma_event_q;
 };
 
 /**
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/tnetv107x.h linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/tnetv107x.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/include/mach/tnetv107x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/include/mach/tnetv107x.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 
 #include <linux/serial_8250.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/mfd/ti_ssp.h>
 
 #include <mach/mmc.h>
 #include <mach/nand.h>
@@ -44,6 +45,7 @@
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
 	struct davinci_nand_pdata	*nand_config[4]; /* 4 chipsels */
 	struct matrix_keypad_platform_data *keypad_config;
+	struct ti_ssp_data		*ssp_config;
 };
 
 extern struct platform_device tnetv107x_wdt_device;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -154,11 +154,11 @@
 
 	/* set up genirq dispatch for ARM INTC */
 	for (i = 0; i < davinci_soc_info.intc_irq_num; i++) {
-		set_irq_chip(i, &davinci_irq_chip_0);
+		irq_set_chip(i, &davinci_irq_chip_0);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 		if (i != IRQ_TINT1_TINT34)
-			set_irq_handler(i, handle_edge_irq);
+			irq_set_handler(i, handle_edge_irq);
 		else
-			set_irq_handler(i, handle_level_irq);
+			irq_set_handler(i, handle_level_irq);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-davinci/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -63,6 +63,7 @@
 	depends on ARCH_DAVINCI_DM644x
 	select MISC_DEVICES
 	select EEPROM_AT24
+	select I2C
 	help
 	  Configure this option to specify the whether the board used
 	  for development is a DM644x EVM
@@ -72,6 +73,7 @@
 	depends on ARCH_DAVINCI_DM644x
 	select MISC_DEVICES
 	select EEPROM_AT24
+	select I2C
 	help
 	  Say Y here to select the Lyrtech Small Form Factor
 	  Software Defined Radio (SFFSDR) board.
@@ -105,6 +107,7 @@
 	select MACH_DAVINCI_DM6467TEVM
 	select MISC_DEVICES
 	select EEPROM_AT24
+	select I2C
 	help
 	  Configure this option to specify the whether the board used
 	  for development is a DM6467 EVM
@@ -118,6 +121,7 @@
 	depends on ARCH_DAVINCI_DM365
 	select MISC_DEVICES
 	select EEPROM_AT24
+	select I2C
 	help
 	  Configure this option to specify whether the board used
 	  for development is a DM365 EVM
@@ -129,6 +133,7 @@
 	select GPIO_PCF857X
 	select MISC_DEVICES
 	select EEPROM_AT24
+	select I2C
 	help
 	  Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
@@ -205,6 +210,7 @@
 	depends on ARCH_DAVINCI_DA850
 	select MISC_DEVICES
 	select EEPROM_AT24
+	select I2C
 	help
 	  Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
 	  System on Module.  Information on this SoM may be found at
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-davinci/tnetv107x.c linux-libre-2.6.39-gnu/arch/arm/mach-davinci/tnetv107x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-davinci/tnetv107x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-davinci/tnetv107x.c	2011-05-19 00:06:34.000000000 -0400
@@ -278,7 +278,7 @@
 	CLK(NULL,		"timer1",		&clk_timer1),
 	CLK("tnetv107x_wdt.0",	NULL,			&clk_wdt_arm),
 	CLK(NULL,		"clk_wdt_dsp",		&clk_wdt_dsp),
-	CLK("ti-ssp.0",		NULL,			&clk_ssp),
+	CLK("ti-ssp",		NULL,			&clk_ssp),
 	CLK(NULL,		"clk_tdm0",		&clk_tdm0),
 	CLK(NULL,		"clk_vlynq",		&clk_vlynq),
 	CLK(NULL,		"clk_mcdma",		&clk_mcdma),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/cm-a510.c linux-libre-2.6.39-gnu/arch/arm/mach-dove/cm-a510.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/cm-a510.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/cm-a510.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,6 +90,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= cm_a510_init,
 	.map_io		= dove_map_io,
+	.init_early	= dove_init_early,
 	.init_irq	= dove_init_irq,
 	.timer		= &dove_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/common.c linux-libre-2.6.39-gnu/arch/arm/mach-dove/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -532,6 +532,11 @@
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init dove_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 static int get_tclk(void)
 {
 	/* use DOVE_RESET_SAMPLE_HI/LO to detect tclk */
@@ -540,7 +545,8 @@
 
 static void dove_timer_init(void)
 {
-	orion_time_init(IRQ_DOVE_BRIDGE, get_tclk());
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_DOVE_BRIDGE, get_tclk());
 }
 
 struct sys_timer dove_timer = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/common.h linux-libre-2.6.39-gnu/arch/arm/mach-dove/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
  */
 void dove_map_io(void);
 void dove_init(void);
+void dove_init_early(void);
 void dove_init_irq(void);
 void dove_setup_cpu_mbus(void);
 void dove_ge00_init(struct mv643xx_eth_platform_data *eth_data);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/dove-db-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-dove/dove-db-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/dove-db-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/dove-db-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,6 +97,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= dove_db_init,
 	.map_io		= dove_map_io,
+	.init_early	= dove_init_early,
 	.init_irq	= dove_init_irq,
 	.timer		= &dove_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/bridge-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/bridge-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/bridge-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/bridge-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,10 +26,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define  SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define  BRIDGE_INT_TIMER0	0x0002
-#define  BRIDGE_INT_TIMER1	0x0004
 #define  BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/dove.h linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/dove.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/dove.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/dove.h	2011-05-19 00:06:34.000000000 -0400
@@ -130,12 +130,13 @@
 #define DOVE_PMU_MPP_GENERAL_CTRL (DOVE_MPP_VIRT_BASE + 0x10)
 #define DOVE_RESET_SAMPLE_LO	(DOVE_MPP_VIRT_BASE | 0x014)
 #define DOVE_RESET_SAMPLE_HI	(DOVE_MPP_VIRT_BASE | 0x018)
-#define DOVE_GPIO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO_LO_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0400)
+#define DOVE_GPIO_HI_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xd0420)
 #define DOVE_GPIO2_VIRT_BASE    (DOVE_SB_REGS_VIRT_BASE | 0xe8400)
 #define DOVE_MPP_GENERAL_VIRT_BASE	(DOVE_SB_REGS_VIRT_BASE | 0xe803c)
 #define  DOVE_AU1_SPDIFO_GPIO_EN	(1 << 1)
 #define  DOVE_NAND_GPIO_EN		(1 << 0)
-#define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_VIRT_BASE + 0x40)
+#define DOVE_MPP_CTRL4_VIRT_BASE	(DOVE_GPIO_LO_VIRT_BASE + 0x40)
 #define  DOVE_SPI_GPIO_SEL		(1 << 5)
 #define  DOVE_UART1_GPIO_SEL		(1 << 4)
 #define  DOVE_AU1_GPIO_SEL		(1 << 3)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,46 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <asm/errno.h>
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define GPIO_MAX	72
-
-#define GPIO_BASE_LO		(DOVE_GPIO_VIRT_BASE + 0x00)
-#define GPIO_BASE_HI		(DOVE_GPIO_VIRT_BASE + 0x20)
-
-#define GPIO_BASE(pin)		((pin < 32) ? GPIO_BASE_LO :		\
-				 ((pin < 64) ? GPIO_BASE_HI :		\
-				  DOVE_GPIO2_VIRT_BASE))
-
-#define GPIO_OUT(pin)		(GPIO_BASE(pin) + 0x00)
-#define GPIO_IO_CONF(pin)	(GPIO_BASE(pin) + 0x04)
-#define GPIO_BLINK_EN(pin)	(GPIO_BASE(pin) + 0x08)
-#define GPIO_IN_POL(pin)	(GPIO_BASE(pin) + 0x0c)
-#define GPIO_DATA_IN(pin)	(GPIO_BASE(pin) + 0x10)
-#define GPIO_EDGE_CAUSE(pin)	(GPIO_BASE(pin) + 0x14)
-#define GPIO_EDGE_MASK(pin)	(GPIO_BASE(pin) + 0x18)
-#define GPIO_LEVEL_MASK(pin)	(GPIO_BASE(pin) + 0x1c)
-
-static inline int gpio_to_irq(int pin)
-{
-	if (pin < NR_GPIO_IRQS)
-		return pin + IRQ_DOVE_GPIO_START;
-
-	return -EINVAL;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	if (IRQ_DOVE_GPIO_START < irq && irq < NR_IRQS)
-		return irq - IRQ_DOVE_GPIO_START;
-
-	return -EINVAL;
-}
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -92,10 +92,5 @@
 
 #define NR_IRQS			(IRQ_DOVE_PMU_START + NR_PMU_IRQS)
 
-/* Required for compatability with PXA AC97 driver.	*/
-#define IRQ_AC97		IRQ_DOVE_AC97
-/* Required for compatability with PXA DMA driver.	*/
-#define IRQ_DMA			IRQ_DOVE_PDMA
-/* Required for compatability with PXA NAND driver 	*/
-#define IRQ_NAND		IRQ_DOVE_NAND
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-dove/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,8 +86,7 @@
 		if (!(cause & (1 << irq)))
 			continue;
 		irq = pmu_to_irq(irq);
-		desc = irq_desc + irq;
-		desc_handle_irq(irq, desc);
+		generic_handle_irq(irq);
 	}
 }
 
@@ -99,11 +98,21 @@
 	orion_irq_init(32, (void __iomem *)(IRQ_VIRT_BASE + IRQ_MASK_HIGH_OFF));
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts.
+	 * Initialize gpiolib for GPIOs 0-71.
 	 */
-	writel(0, GPIO_LEVEL_MASK(0));
-	writel(0, GPIO_EDGE_MASK(0));
-	writel(0, GPIO_EDGE_CAUSE(0));
+	orion_gpio_init(0, 32, DOVE_GPIO_LO_VIRT_BASE, 0,
+			IRQ_DOVE_GPIO_START);
+	irq_set_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler);
+
+	orion_gpio_init(32, 32, DOVE_GPIO_HI_VIRT_BASE, 0,
+			IRQ_DOVE_GPIO_START + 32);
+	irq_set_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
+
+	orion_gpio_init(64, 8, DOVE_GPIO2_VIRT_BASE, 0,
+			IRQ_DOVE_GPIO_START + 64);
 
 	/*
 	 * Mask and clear PMU interrupts
@@ -111,23 +120,10 @@
 	writel(0, PMU_INTERRUPT_MASK);
 	writel(0, PMU_INTERRUPT_CAUSE);
 
-	for (i = IRQ_DOVE_GPIO_START; i < IRQ_DOVE_PMU_START; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_chained_handler(IRQ_DOVE_GPIO_0_7, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_GPIO_8_15, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_GPIO_16_23, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_GPIO_24_31, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_DOVE_HIGH_GPIO, gpio_irq_handler);
-
 	for (i = IRQ_DOVE_PMU_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &pmu_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
+		irq_set_chip_and_handler(i, &pmu_irq_chip, handle_level_irq);
+		irq_set_status_flags(i, IRQ_LEVEL);
 		set_irq_flags(i, IRQF_VALID);
 	}
-	set_irq_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
+	irq_set_chained_handler(IRQ_DOVE_PMU, pmu_irq_handler);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-dove/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
 	  Say 'Y' here if you want your kernel to support the
 	  Marvell DB-MV88AP510 Development Board.
 
- config MACH_CM_A510
+config MACH_CM_A510
 	bool "CompuLab CM-A510 Board"
 	help
 	  Say 'Y' here if you want your kernel to support the
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-dove/mpp.c linux-libre-2.6.39-gnu/arch/arm/mach-dove/mpp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-dove/mpp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-dove/mpp.c	2011-05-19 00:06:34.000000000 -0400
@@ -147,9 +147,6 @@
 	u32 pmu_sig_ctrl[PMU_SIG_REGS];
 	int i;
 
-	/* Initialize gpiolib. */
-	orion_gpio_init();
-
 	for (i = 0; i < MPP_NR_REGS; i++)
 		mpp_ctrl[i] = readl(MPP_CTRL(i));
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ebsa110/core.c linux-libre-2.6.39-gnu/arch/arm/mach-ebsa110/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ebsa110/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ebsa110/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,8 +66,8 @@
 	local_irq_restore(flags);
 
 	for (irq = 0; irq < NR_IRQS; irq++) {
-		set_irq_chip(irq, &ebsa110_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &ebsa110_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ebsa110/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ebsa110/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ebsa110/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ebsa110/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 /*
  * Cache flushing area - SRAM
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/edb93xx.c linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/edb93xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/edb93xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/edb93xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,8 +30,13 @@
 #include <linux/gpio.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
+#include <linux/spi/spi.h>
+
+#include <sound/cs4271.h>
 
 #include <mach/hardware.h>
+#include <mach/fb.h>
+#include <mach/ep93xx_spi.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -93,6 +98,83 @@
 
 
 /*************************************************************************
+ * EDB93xx SPI peripheral handling
+ *************************************************************************/
+static struct cs4271_platform_data edb93xx_cs4271_data = {
+	.gpio_nreset	= -EINVAL,	/* filled in later */
+};
+
+static int edb93xx_cs4271_hw_setup(struct spi_device *spi)
+{
+	return gpio_request_one(EP93XX_GPIO_LINE_EGPIO6,
+				GPIOF_OUT_INIT_HIGH, spi->modalias);
+}
+
+static void edb93xx_cs4271_hw_cleanup(struct spi_device *spi)
+{
+	gpio_free(EP93XX_GPIO_LINE_EGPIO6);
+}
+
+static void edb93xx_cs4271_hw_cs_control(struct spi_device *spi, int value)
+{
+	gpio_set_value(EP93XX_GPIO_LINE_EGPIO6, value);
+}
+
+static struct ep93xx_spi_chip_ops edb93xx_cs4271_hw = {
+	.setup		= edb93xx_cs4271_hw_setup,
+	.cleanup	= edb93xx_cs4271_hw_cleanup,
+	.cs_control	= edb93xx_cs4271_hw_cs_control,
+};
+
+static struct spi_board_info edb93xx_spi_board_info[] __initdata = {
+	{
+		.modalias		= "cs4271",
+		.platform_data		= &edb93xx_cs4271_data,
+		.controller_data	= &edb93xx_cs4271_hw,
+		.max_speed_hz		= 6000000,
+		.bus_num		= 0,
+		.chip_select		= 0,
+		.mode			= SPI_MODE_3,
+	},
+};
+
+static struct ep93xx_spi_info edb93xx_spi_info __initdata = {
+	.num_chipselect	= ARRAY_SIZE(edb93xx_spi_board_info),
+};
+
+static void __init edb93xx_register_spi(void)
+{
+	if (machine_is_edb9301() || machine_is_edb9302())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO1;
+	else if (machine_is_edb9302a() || machine_is_edb9307a())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_H(2);
+	else if (machine_is_edb9315a())
+		edb93xx_cs4271_data.gpio_nreset = EP93XX_GPIO_LINE_EGPIO14;
+
+	ep93xx_register_spi(&edb93xx_spi_info, edb93xx_spi_board_info,
+			    ARRAY_SIZE(edb93xx_spi_board_info));
+}
+
+
+/*************************************************************************
+ * EDB93xx I2S
+ *************************************************************************/
+static int __init edb93xx_has_audio(void)
+{
+	return (machine_is_edb9301() || machine_is_edb9302() ||
+		machine_is_edb9302a() || machine_is_edb9307a() ||
+		machine_is_edb9315a());
+}
+
+static void __init edb93xx_register_i2s(void)
+{
+	if (edb93xx_has_audio()) {
+		ep93xx_register_i2s();
+	}
+}
+
+
+/*************************************************************************
  * EDB93xx pwm
  *************************************************************************/
 static void __init edb93xx_register_pwm(void)
@@ -111,13 +193,47 @@
 }
 
 
+/*************************************************************************
+ * EDB93xx framebuffer
+ *************************************************************************/
+static struct ep93xxfb_mach_info __initdata edb93xxfb_info = {
+	.num_modes	= EP93XXFB_USE_MODEDB,
+	.bpp		= 16,
+	.flags		= 0,
+};
+
+static int __init edb93xx_has_fb(void)
+{
+	/* These platforms have an ep93xx with video capability */
+	return machine_is_edb9307() || machine_is_edb9307a() ||
+	       machine_is_edb9312() || machine_is_edb9315() ||
+	       machine_is_edb9315a();
+}
+
+static void __init edb93xx_register_fb(void)
+{
+	if (!edb93xx_has_fb())
+		return;
+
+	if (machine_is_edb9307a() || machine_is_edb9315a())
+		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN0;
+	else
+		edb93xxfb_info.flags |= EP93XXFB_USE_SDCSN3;
+
+	ep93xx_register_fb(&edb93xxfb_info);
+}
+
+
 static void __init edb93xx_init_machine(void)
 {
 	ep93xx_init_devices();
 	edb93xx_register_flash();
 	ep93xx_register_eth(&edb93xx_eth_data, 1);
 	edb93xx_register_i2c();
+	edb93xx_register_spi();
+	edb93xx_register_i2s();
 	edb93xx_register_pwm();
+	edb93xx_register_fb();
 }
 
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
 	gpio_int_unmasked[line >> 3] &= ~(1 << (line & 7));
 }
 
-void ep93xx_gpio_int_debounce(unsigned int irq, int enable)
+static void ep93xx_gpio_int_debounce(unsigned int irq, bool enable)
 {
 	int line = irq_to_gpio(irq);
 	int port = line >> 3;
@@ -75,7 +75,6 @@
 	__raw_writeb(gpio_int_debounce[port],
 		EP93XX_GPIO_REG(int_debounce_register_offset[port]));
 }
-EXPORT_SYMBOL(ep93xx_gpio_int_debounce);
 
 static void ep93xx_gpio_ab_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
@@ -102,7 +101,7 @@
 static void ep93xx_gpio_f_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
 	/*
-	 * map discontiguous hw irq range to continous sw irq range:
+	 * map discontiguous hw irq range to continuous sw irq range:
 	 *
 	 *  IRQ_EP93XX_GPIO{0..7}MUX -> gpio_to_irq(EP93XX_GPIO_LINE_F({0..7})
 	 */
@@ -118,7 +117,7 @@
 	int port = line >> 3;
 	int port_mask = 1 << (line & 7);
 
-	if ((irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 		ep93xx_gpio_update_int_params(port);
 	}
@@ -132,7 +131,7 @@
 	int port = line >> 3;
 	int port_mask = 1 << (line & 7);
 
-	if ((irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH)
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH)
 		gpio_int_type2[port] ^= port_mask; /* switch edge direction */
 
 	gpio_int_unmasked[port] &= ~port_mask;
@@ -166,10 +165,10 @@
  */
 static int ep93xx_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
-	struct irq_desc *desc = irq_desc + d->irq;
 	const int gpio = irq_to_gpio(d->irq);
 	const int port = gpio >> 3;
 	const int port_mask = 1 << (gpio & 7);
+	irq_flow_handler_t handler;
 
 	gpio_direction_input(gpio);
 
@@ -177,22 +176,22 @@
 	case IRQ_TYPE_EDGE_RISING:
 		gpio_int_type1[port] |= port_mask;
 		gpio_int_type2[port] |= port_mask;
-		desc->handle_irq = handle_edge_irq;
+		handler = handle_edge_irq;
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 		gpio_int_type1[port] |= port_mask;
 		gpio_int_type2[port] &= ~port_mask;
-		desc->handle_irq = handle_edge_irq;
+		handler = handle_edge_irq;
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
 		gpio_int_type1[port] &= ~port_mask;
 		gpio_int_type2[port] |= port_mask;
-		desc->handle_irq = handle_level_irq;
+		handler = handle_level_irq;
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
 		gpio_int_type1[port] &= ~port_mask;
 		gpio_int_type2[port] &= ~port_mask;
-		desc->handle_irq = handle_level_irq;
+		handler = handle_level_irq;
 		break;
 	case IRQ_TYPE_EDGE_BOTH:
 		gpio_int_type1[port] |= port_mask;
@@ -201,17 +200,16 @@
 			gpio_int_type2[port] &= ~port_mask; /* falling */
 		else
 			gpio_int_type2[port] |= port_mask; /* rising */
-		desc->handle_irq = handle_edge_irq;
+		handler = handle_edge_irq;
 		break;
 	default:
 		pr_err("failed to set irq type %d for gpio %d\n", type, gpio);
 		return -EINVAL;
 	}
 
-	gpio_int_enabled[port] |= port_mask;
+	__irq_set_handler_locked(d->irq, handler);
 
-	desc->status &= ~IRQ_TYPE_SENSE_MASK;
-	desc->status |= type & IRQ_TYPE_SENSE_MASK;
+	gpio_int_enabled[port] |= port_mask;
 
 	ep93xx_gpio_update_int_params(port);
 
@@ -233,20 +231,29 @@
 
 	for (gpio_irq = gpio_to_irq(0);
 	     gpio_irq <= gpio_to_irq(EP93XX_GPIO_LINE_MAX_IRQ); ++gpio_irq) {
-		set_irq_chip(gpio_irq, &ep93xx_gpio_irq_chip);
-		set_irq_handler(gpio_irq, handle_level_irq);
+		irq_set_chip_and_handler(gpio_irq, &ep93xx_gpio_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(gpio_irq, IRQF_VALID);
 	}
 
-	set_irq_chained_handler(IRQ_EP93XX_GPIO_AB, ep93xx_gpio_ab_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO0MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO1MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO2MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO3MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO4MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO5MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO6MUX, ep93xx_gpio_f_irq_handler);
-	set_irq_chained_handler(IRQ_EP93XX_GPIO7MUX, ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO_AB,
+				ep93xx_gpio_ab_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO0MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO1MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO2MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO3MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO4MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO5MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO6MUX,
+				ep93xx_gpio_f_irq_handler);
+	irq_set_chained_handler(IRQ_EP93XX_GPIO7MUX,
+				ep93xx_gpio_f_irq_handler);
 }
 
 
@@ -335,6 +342,20 @@
 	local_irq_restore(flags);
 }
 
+static int ep93xx_gpio_set_debounce(struct gpio_chip *chip,
+				    unsigned offset, unsigned debounce)
+{
+	int gpio = chip->base + offset;
+	int irq = gpio_to_irq(gpio);
+
+	if (irq < 0)
+		return -EINVAL;
+
+	ep93xx_gpio_int_debounce(irq, debounce ? true : false);
+
+	return 0;
+}
+
 static void ep93xx_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
 {
 	struct ep93xx_gpio_chip *ep93xx_chip = to_ep93xx_gpio_chip(chip);
@@ -347,52 +368,14 @@
 	gpio = ep93xx_chip->chip.base;
 	for (i = 0; i < chip->ngpio; i++, gpio++) {
 		int is_out = data_dir_reg & (1 << i);
+		int irq = gpio_to_irq(gpio);
 
-		seq_printf(s, " %s%d gpio-%-3d (%-12s) %s %s",
+		seq_printf(s, " %s%d gpio-%-3d (%-12s) %s %s %s\n",
 				chip->label, i, gpio,
 				gpiochip_is_requested(chip, i) ? : "",
 				is_out ? "out" : "in ",
-				(data_reg & (1 << i)) ? "hi" : "lo");
-
-		if (!is_out) {
-			int irq = gpio_to_irq(gpio);
-			struct irq_desc *desc = irq_desc + irq;
-
-			if (irq >= 0 && desc->action) {
-				char *trigger;
-
-				switch (desc->status & IRQ_TYPE_SENSE_MASK) {
-				case IRQ_TYPE_NONE:
-					trigger = "(default)";
-					break;
-				case IRQ_TYPE_EDGE_FALLING:
-					trigger = "edge-falling";
-					break;
-				case IRQ_TYPE_EDGE_RISING:
-					trigger = "edge-rising";
-					break;
-				case IRQ_TYPE_EDGE_BOTH:
-					trigger = "edge-both";
-					break;
-				case IRQ_TYPE_LEVEL_HIGH:
-					trigger = "level-high";
-					break;
-				case IRQ_TYPE_LEVEL_LOW:
-					trigger = "level-low";
-					break;
-				default:
-					trigger = "?trigger?";
-					break;
-				}
-
-				seq_printf(s, " irq-%d %s%s",
-						irq, trigger,
-						(desc->status & IRQ_WAKEUP)
-							? " wakeup" : "");
-			}
-		}
-
-		seq_printf(s, "\n");
+				(data_reg & (1<<  i)) ? "hi" : "lo",
+				(!is_out && irq>= 0) ? "(interrupt)" : "");
 	}
 }
 
@@ -434,6 +417,18 @@
 				 EP93XX_SYSCON_DEVCFG_GONIDE |
 				 EP93XX_SYSCON_DEVCFG_HONIDE);
 
-	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++)
-		gpiochip_add(&ep93xx_gpio_banks[i].chip);
+	for (i = 0; i < ARRAY_SIZE(ep93xx_gpio_banks); i++) {
+		struct gpio_chip *chip = &ep93xx_gpio_banks[i].chip;
+
+		/*
+		 * Ports A, B, and F support input debouncing when
+		 * used as interrupts.
+		 */
+		if (!strcmp(chip->label, "A") ||
+		    !strcmp(chip->label, "B") ||
+		    !strcmp(chip->label, "F"))
+			chip->set_debounce = ep93xx_gpio_set_debounce;
+
+		gpiochip_add(chip);
+	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -99,8 +99,6 @@
 /* maximum value for irq capable line identifiers */
 #define EP93XX_GPIO_LINE_MAX_IRQ	EP93XX_GPIO_LINE_F(7)
 
-extern void ep93xx_gpio_int_debounce(unsigned int irq, int enable);
-
 /* new generic GPIO API - see Documentation/gpio.txt */
 
 #include <asm-generic/gpio.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ep93xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ep93xx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,15 +6,15 @@
 #define __ASM_ARCH_MEMORY_H
 
 #if defined(CONFIG_EP93XX_SDCE3_SYNC_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 #elif defined(CONFIG_EP93XX_SDCE0_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xc0000000)
+#define PLAT_PHYS_OFFSET		UL(0xc0000000)
 #elif defined(CONFIG_EP93XX_SDCE1_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xd0000000)
+#define PLAT_PHYS_OFFSET		UL(0xd0000000)
 #elif defined(CONFIG_EP93XX_SDCE2_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xe0000000)
+#define PLAT_PHYS_OFFSET		UL(0xe0000000)
 #elif defined(CONFIG_EP93XX_SDCE3_ASYNC_PHYS_OFFSET)
-#define PHYS_OFFSET		UL(0xf0000000)
+#define PLAT_PHYS_OFFSET		UL(0xf0000000)
 #else
 #error "Kconfig bug: No EP93xx PHYS_OFFSET set"
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1216 @@
+/* linux/arch/arm/mach-exynos4/clock.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Clock 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/err.h>
+#include <linux/io.h>
+
+#include <plat/cpu-freq.h>
+#include <plat/clock.h>
+#include <plat/cpu.h>
+#include <plat/pll.h>
+#include <plat/s5p-clock.h>
+#include <plat/clock-clksrc.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/sysmmu.h>
+
+static struct clk clk_sclk_hdmi27m = {
+	.name		= "sclk_hdmi27m",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+static struct clk clk_sclk_hdmiphy = {
+	.name		= "sclk_hdmiphy",
+	.id		= -1,
+};
+
+static struct clk clk_sclk_usbphy0 = {
+	.name		= "sclk_usbphy0",
+	.id		= -1,
+	.rate		= 27000000,
+};
+
+static struct clk clk_sclk_usbphy1 = {
+	.name		= "sclk_usbphy1",
+	.id		= -1,
+};
+
+static int exynos4_clksrc_mask_top_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
+}
+
+static int exynos4_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
+}
+
+static int exynos4_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
+}
+
+static int exynos4_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
+}
+
+static int exynos4_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
+}
+
+static int exynos4_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
+}
+
+static int exynos4_clk_ip_mfc_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_MFC, clk, enable);
+}
+
+static int exynos4_clk_ip_cam_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
+}
+
+static int exynos4_clk_ip_tv_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_TV, clk, enable);
+}
+
+static int exynos4_clk_ip_image_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
+}
+
+static int exynos4_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
+}
+
+static int exynos4_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
+}
+
+static int exynos4_clk_ip_fsys_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
+}
+
+static int exynos4_clk_ip_peril_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
+}
+
+static int exynos4_clk_ip_perir_ctrl(struct clk *clk, int enable)
+{
+	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
+}
+
+/* Core list of CMU_CPU side */
+
+static struct clksrc_clk clk_mout_apll = {
+	.clk	= {
+		.name		= "mout_apll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_apll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_apll = {
+	.clk	= {
+		.name		= "sclk_apll",
+		.id		= -1,
+		.parent		= &clk_mout_apll.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
+};
+
+static struct clksrc_clk clk_mout_epll = {
+	.clk	= {
+		.name		= "mout_epll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_epll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_mout_mpll = {
+	.clk = {
+		.name		= "mout_mpll",
+		.id		= -1,
+	},
+	.sources	= &clk_src_mpll,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
+};
+
+static struct clk *clkset_moutcore_list[] = {
+	[0] = &clk_mout_apll.clk,
+	[1] = &clk_mout_mpll.clk,
+};
+
+static struct clksrc_sources clkset_moutcore = {
+	.sources	= clkset_moutcore_list,
+	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
+};
+
+static struct clksrc_clk clk_moutcore = {
+	.clk	= {
+		.name		= "moutcore",
+		.id		= -1,
+	},
+	.sources	= &clkset_moutcore,
+	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
+};
+
+static struct clksrc_clk clk_coreclk = {
+	.clk	= {
+		.name		= "core_clk",
+		.id		= -1,
+		.parent		= &clk_moutcore.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_armclk = {
+	.clk	= {
+		.name		= "armclk",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+};
+
+static struct clksrc_clk clk_aclk_corem0 = {
+	.clk	= {
+		.name		= "aclk_corem0",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cores = {
+	.clk	= {
+		.name		= "aclk_cores",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corem1 = {
+	.clk	= {
+		.name		= "aclk_corem1",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_periphclk = {
+	.clk	= {
+		.name		= "periphclk",
+		.id		= -1,
+		.parent		= &clk_coreclk.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
+};
+
+/* Core list of CMU_CORE side */
+
+static struct clk *clkset_corebus_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_corebus = {
+	.sources	= clkset_corebus_list,
+	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
+};
+
+static struct clksrc_clk clk_mout_corebus = {
+	.clk	= {
+		.name		= "mout_corebus",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_corebus,
+	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
+};
+
+static struct clksrc_clk clk_sclk_dmc = {
+	.clk	= {
+		.name		= "sclk_dmc",
+		.id		= -1,
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_cored = {
+	.clk	= {
+		.name		= "aclk_cored",
+		.id		= -1,
+		.parent		= &clk_sclk_dmc.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_corep = {
+	.clk	= {
+		.name		= "aclk_corep",
+		.id		= -1,
+		.parent		= &clk_aclk_cored.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_acp = {
+	.clk	= {
+		.name		= "aclk_acp",
+		.id		= -1,
+		.parent		= &clk_mout_corebus.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_pclk_acp = {
+	.clk	= {
+		.name		= "pclk_acp",
+		.id		= -1,
+		.parent		= &clk_aclk_acp.clk,
+	},
+	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
+};
+
+/* Core list of CMU_TOP side */
+
+static struct clk *clkset_aclk_top_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_aclk = {
+	.sources	= clkset_aclk_top_list,
+	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
+};
+
+static struct clksrc_clk clk_aclk_200 = {
+	.clk	= {
+		.name		= "aclk_200",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_100 = {
+	.clk	= {
+		.name		= "aclk_100",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
+};
+
+static struct clksrc_clk clk_aclk_160 = {
+	.clk	= {
+		.name		= "aclk_160",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
+};
+
+static struct clksrc_clk clk_aclk_133 = {
+	.clk	= {
+		.name		= "aclk_133",
+		.id		= -1,
+	},
+	.sources	= &clkset_aclk,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
+	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
+};
+
+static struct clk *clkset_vpllsrc_list[] = {
+	[0] = &clk_fin_vpll,
+	[1] = &clk_sclk_hdmi27m,
+};
+
+static struct clksrc_sources clkset_vpllsrc = {
+	.sources	= clkset_vpllsrc_list,
+	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
+};
+
+static struct clksrc_clk clk_vpllsrc = {
+	.clk	= {
+		.name		= "vpll_src",
+		.id		= -1,
+		.enable		= exynos4_clksrc_mask_top_ctrl,
+		.ctrlbit	= (1 << 0),
+	},
+	.sources	= &clkset_vpllsrc,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_sclk_vpll_list[] = {
+	[0] = &clk_vpllsrc.clk,
+	[1] = &clk_fout_vpll,
+};
+
+static struct clksrc_sources clkset_sclk_vpll = {
+	.sources	= clkset_sclk_vpll_list,
+	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
+};
+
+static struct clksrc_clk clk_sclk_vpll = {
+	.clk	= {
+		.name		= "sclk_vpll",
+		.id		= -1,
+	},
+	.sources	= &clkset_sclk_vpll,
+	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
+};
+
+static struct clk init_clocks_off[] = {
+	{
+		.name		= "timers",
+		.id		= -1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1<<24),
+	}, {
+		.name		= "csis",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "csis",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "fimc",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "fimc",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "fimc",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "fimc",
+		.id		= 3,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "fimd",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "fimd",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "sataphy",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "hsmmc",
+		.id		= 0,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "hsmmc",
+		.id		= 1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "hsmmc",
+		.id		= 2,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "hsmmc",
+		.id		= 3,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "hsmmc",
+		.id		= 4,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "sata",
+		.id		= -1,
+		.parent		= &clk_aclk_133.clk,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "pdma",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "pdma",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "adc",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "keypad",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "rtc",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 15),
+	}, {
+		.name		= "watchdog",
+		.id		= -1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_perir_ctrl,
+		.ctrlbit	= (1 << 14),
+	}, {
+		.name		= "usbhost",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_fsys_ctrl ,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "otg",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "spi",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 16),
+	}, {
+		.name		= "spi",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 17),
+	}, {
+		.name		= "spi",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "iis",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 19),
+	}, {
+		.name		= "iis",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 20),
+	}, {
+		.name		= "iis",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 21),
+	}, {
+		.name		= "ac97",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 27),
+	}, {
+		.name		= "fimg2d",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "i2c",
+		.id		= 0,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 6),
+	}, {
+		.name		= "i2c",
+		.id		= 1,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "i2c",
+		.id		= 2,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "i2c",
+		.id		= 3,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "i2c",
+		.id		= 4,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "i2c",
+		.id		= 5,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "i2c",
+		.id		= 6,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 12),
+	}, {
+		.name		= "i2c",
+		.id		= 7,
+		.parent		= &clk_aclk_100.clk,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 13),
+	}, {
+		.name		= "SYSMMU_MDMA",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 5),
+	}, {
+		.name		= "SYSMMU_FIMC0",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 7),
+	}, {
+		.name		= "SYSMMU_FIMC1",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 8),
+	}, {
+		.name		= "SYSMMU_FIMC2",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 9),
+	}, {
+		.name		= "SYSMMU_FIMC3",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 10),
+	}, {
+		.name		= "SYSMMU_JPEG",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_cam_ctrl,
+		.ctrlbit	= (1 << 11),
+	}, {
+		.name		= "SYSMMU_FIMD0",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_lcd0_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_FIMD1",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_lcd1_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_PCIe",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_fsys_ctrl,
+		.ctrlbit	= (1 << 18),
+	}, {
+		.name		= "SYSMMU_G2D",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "SYSMMU_ROTATOR",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_image_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_TV",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_tv_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "SYSMMU_MFC_L",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "SYSMMU_MFC_R",
+		.id		= -1,
+		.enable		= exynos4_clk_ip_mfc_ctrl,
+		.ctrlbit	= (1 << 2),
+	}
+};
+
+static struct clk init_clocks[] = {
+	{
+		.name		= "uart",
+		.id		= 0,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 0),
+	}, {
+		.name		= "uart",
+		.id		= 1,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 1),
+	}, {
+		.name		= "uart",
+		.id		= 2,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 2),
+	}, {
+		.name		= "uart",
+		.id		= 3,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 3),
+	}, {
+		.name		= "uart",
+		.id		= 4,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 4),
+	}, {
+		.name		= "uart",
+		.id		= 5,
+		.enable		= exynos4_clk_ip_peril_ctrl,
+		.ctrlbit	= (1 << 5),
+	}
+};
+
+static struct clk *clkset_group_list[] = {
+	[0] = &clk_ext_xtal_mux,
+	[1] = &clk_xusbxti,
+	[2] = &clk_sclk_hdmi27m,
+	[3] = &clk_sclk_usbphy0,
+	[4] = &clk_sclk_usbphy1,
+	[5] = &clk_sclk_hdmiphy,
+	[6] = &clk_mout_mpll.clk,
+	[7] = &clk_mout_epll.clk,
+	[8] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_group = {
+	.sources	= clkset_group_list,
+	.nr_sources	= ARRAY_SIZE(clkset_group_list),
+};
+
+static struct clk *clkset_mout_g2d0_list[] = {
+	[0] = &clk_mout_mpll.clk,
+	[1] = &clk_sclk_apll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d0 = {
+	.sources	= clkset_mout_g2d0_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d0_list),
+};
+
+static struct clksrc_clk clk_mout_g2d0 = {
+	.clk	= {
+		.name		= "mout_g2d0",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_g2d0,
+	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d1_list[] = {
+	[0] = &clk_mout_epll.clk,
+	[1] = &clk_sclk_vpll.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d1 = {
+	.sources	= clkset_mout_g2d1_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d1_list),
+};
+
+static struct clksrc_clk clk_mout_g2d1 = {
+	.clk	= {
+		.name		= "mout_g2d1",
+		.id		= -1,
+	},
+	.sources	= &clkset_mout_g2d1,
+	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
+};
+
+static struct clk *clkset_mout_g2d_list[] = {
+	[0] = &clk_mout_g2d0.clk,
+	[1] = &clk_mout_g2d1.clk,
+};
+
+static struct clksrc_sources clkset_mout_g2d = {
+	.sources	= clkset_mout_g2d_list,
+	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
+};
+
+static struct clksrc_clk clk_dout_mmc0 = {
+	.clk		= {
+		.name		= "dout_mmc0",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc1 = {
+	.clk		= {
+		.name		= "dout_mmc1",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc2 = {
+	.clk		= {
+		.name		= "dout_mmc2",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc3 = {
+	.clk		= {
+		.name		= "dout_mmc3",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
+};
+
+static struct clksrc_clk clk_dout_mmc4 = {
+	.clk		= {
+		.name		= "dout_mmc4",
+		.id		= -1,
+	},
+	.sources = &clkset_group,
+	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
+	.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
+};
+
+static struct clksrc_clk clksrcs[] = {
+	{
+		.clk	= {
+			.name		= "uclk1",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 2,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "uclk1",
+			.id		= 3,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_pwm",
+			.id		= -1,
+			.enable		= exynos4_clksrc_mask_peril0_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_csis",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 28),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_cam",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 2,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimc",
+			.id		= 3,
+			.enable		= exynos4_clksrc_mask_cam_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_lcd0_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimd",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_lcd1_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_sata",
+			.id		= -1,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_mout_corebus,
+		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 0,
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 1,
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 20),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_spi",
+			.id		= 2,
+			.enable		= exynos4_clksrc_mask_peril1_ctrl,
+			.ctrlbit	= (1 << 24),
+		},
+		.sources = &clkset_group,
+		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
+		.reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_fimg2d",
+			.id		= -1,
+		},
+		.sources = &clkset_mout_g2d,
+		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
+		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 0,
+			.parent		= &clk_dout_mmc0.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 0),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 1,
+			.parent         = &clk_dout_mmc1.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 4),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 2,
+			.parent         = &clk_dout_mmc2.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 8),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 3,
+			.parent         = &clk_dout_mmc3.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 12),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
+	}, {
+		.clk		= {
+			.name		= "sclk_mmc",
+			.id		= 4,
+			.parent         = &clk_dout_mmc4.clk,
+			.enable		= exynos4_clksrc_mask_fsys_ctrl,
+			.ctrlbit	= (1 << 16),
+		},
+		.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
+	}
+};
+
+/* Clock initialization code */
+static struct clksrc_clk *sysclks[] = {
+	&clk_mout_apll,
+	&clk_sclk_apll,
+	&clk_mout_epll,
+	&clk_mout_mpll,
+	&clk_moutcore,
+	&clk_coreclk,
+	&clk_armclk,
+	&clk_aclk_corem0,
+	&clk_aclk_cores,
+	&clk_aclk_corem1,
+	&clk_periphclk,
+	&clk_mout_corebus,
+	&clk_sclk_dmc,
+	&clk_aclk_cored,
+	&clk_aclk_corep,
+	&clk_aclk_acp,
+	&clk_pclk_acp,
+	&clk_vpllsrc,
+	&clk_sclk_vpll,
+	&clk_aclk_200,
+	&clk_aclk_100,
+	&clk_aclk_160,
+	&clk_aclk_133,
+	&clk_dout_mmc0,
+	&clk_dout_mmc1,
+	&clk_dout_mmc2,
+	&clk_dout_mmc3,
+	&clk_dout_mmc4,
+};
+
+static int xtal_rate;
+
+static unsigned long exynos4_fout_apll_get_rate(struct clk *clk)
+{
+	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
+}
+
+static struct clk_ops exynos4_fout_apll_ops = {
+	.get_rate = exynos4_fout_apll_get_rate,
+};
+
+void __init_or_cpufreq exynos4_setup_clocks(void)
+{
+	struct clk *xtal_clk;
+	unsigned long apll;
+	unsigned long mpll;
+	unsigned long epll;
+	unsigned long vpll;
+	unsigned long vpllsrc;
+	unsigned long xtal;
+	unsigned long armclk;
+	unsigned long sclk_dmc;
+	unsigned long aclk_200;
+	unsigned long aclk_100;
+	unsigned long aclk_160;
+	unsigned long aclk_133;
+	unsigned int ptr;
+
+	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
+
+	xtal_clk = clk_get(NULL, "xtal");
+	BUG_ON(IS_ERR(xtal_clk));
+
+	xtal = clk_get_rate(xtal_clk);
+
+	xtal_rate = xtal;
+
+	clk_put(xtal_clk);
+
+	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
+
+	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
+	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
+	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
+				__raw_readl(S5P_EPLL_CON1), pll_4600);
+
+	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
+	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
+				__raw_readl(S5P_VPLL_CON1), pll_4650);
+
+	clk_fout_apll.ops = &exynos4_fout_apll_ops;
+	clk_fout_mpll.rate = mpll;
+	clk_fout_epll.rate = epll;
+	clk_fout_vpll.rate = vpll;
+
+	printk(KERN_INFO "EXYNOS4: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
+			apll, mpll, epll, vpll);
+
+	armclk = clk_get_rate(&clk_armclk.clk);
+	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
+
+	aclk_200 = clk_get_rate(&clk_aclk_200.clk);
+	aclk_100 = clk_get_rate(&clk_aclk_100.clk);
+	aclk_160 = clk_get_rate(&clk_aclk_160.clk);
+	aclk_133 = clk_get_rate(&clk_aclk_133.clk);
+
+	printk(KERN_INFO "EXYNOS4: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
+			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
+			armclk, sclk_dmc, aclk_200,
+			aclk_100, aclk_160, aclk_133);
+
+	clk_f.rate = armclk;
+	clk_h.rate = sclk_dmc;
+	clk_p.rate = aclk_100;
+
+	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
+		s3c_set_clksrc(&clksrcs[ptr], true);
+}
+
+static struct clk *clks[] __initdata = {
+	/* Nothing here yet */
+};
+
+void __init exynos4_register_clocks(void)
+{
+	int ptr;
+
+	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
+
+	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
+		s3c_register_clksrc(sysclks[ptr], 1);
+
+	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
+	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
+
+	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
+
+	s3c_pwmclk_init();
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/cpu.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/cpu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/cpu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,215 @@
+/* linux/arch/arm/mach-exynos4/cpu.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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/sched.h>
+#include <linux/sysdev.h>
+
+#include <asm/mach/map.h>
+#include <asm/mach/irq.h>
+
+#include <asm/proc-fns.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+#include <plat/exynos4.h>
+#include <plat/sdhci.h>
+#include <plat/devs.h>
+#include <plat/fimc-core.h>
+
+#include <mach/regs-irq.h>
+
+extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
+			 unsigned int irq_start);
+extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
+
+/* Initial IO mappings */
+static struct map_desc exynos4_iodesc[] __initdata = {
+	{
+		.virtual	= (unsigned long)S5P_VA_SYSTIMER,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSTIMER),
+		.length		= SZ_4K,
+		.type	 	= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_SYSRAM,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SYSRAM),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_CMU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_CMU),
+		.length		= SZ_128K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_PMU,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_PMU),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_COMBINER),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_COREPERI),
+		.length		= SZ_8K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_L2CC,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_L2CC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO1,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO1),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO2,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO2),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_GPIO3,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_GPIO3),
+		.length		= SZ_256,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_DMC0,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_DMC0),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S3C_VA_UART,
+		.pfn		= __phys_to_pfn(S3C_PA_UART),
+		.length		= SZ_512K,
+		.type		= MT_DEVICE,
+	}, {
+		.virtual	= (unsigned long)S5P_VA_SROMC,
+		.pfn		= __phys_to_pfn(EXYNOS4_PA_SROMC),
+		.length		= SZ_4K,
+		.type		= MT_DEVICE,
+	},
+};
+
+static void exynos4_idle(void)
+{
+	if (!need_resched())
+		cpu_do_idle();
+
+	local_irq_enable();
+}
+
+/*
+ * exynos4_map_io
+ *
+ * register the standard cpu IO areas
+ */
+void __init exynos4_map_io(void)
+{
+	iotable_init(exynos4_iodesc, ARRAY_SIZE(exynos4_iodesc));
+
+	/* initialize device information early */
+	exynos4_default_sdhci0();
+	exynos4_default_sdhci1();
+	exynos4_default_sdhci2();
+	exynos4_default_sdhci3();
+
+	s3c_fimc_setname(0, "exynos4-fimc");
+	s3c_fimc_setname(1, "exynos4-fimc");
+	s3c_fimc_setname(2, "exynos4-fimc");
+	s3c_fimc_setname(3, "exynos4-fimc");
+}
+
+void __init exynos4_init_clocks(int xtal)
+{
+	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
+
+	s3c24xx_register_baseclocks(xtal);
+	s5p_register_clocks(xtal);
+	exynos4_register_clocks();
+	exynos4_setup_clocks();
+}
+
+void __init exynos4_init_irq(void)
+{
+	int irq;
+
+	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
+
+	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
+
+		/*
+		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
+		 * connected to the interrupt combiner. These irqs
+		 * should be initialized to support cascade interrupt.
+		 */
+		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
+			continue;
+
+		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
+				COMBINER_IRQ(irq, 0));
+		combiner_cascade_irq(irq, IRQ_SPI(irq));
+	}
+
+	/* The parameters of s5p_init_irq() are for VIC init.
+	 * Theses parameters should be NULL and 0 because EXYNOS4
+	 * uses GIC instead of VIC.
+	 */
+	s5p_init_irq(NULL, 0);
+}
+
+struct sysdev_class exynos4_sysclass = {
+	.name	= "exynos4-core",
+};
+
+static struct sys_device exynos4_sysdev = {
+	.cls	= &exynos4_sysclass,
+};
+
+static int __init exynos4_core_init(void)
+{
+	return sysdev_class_register(&exynos4_sysclass);
+}
+
+core_initcall(exynos4_core_init);
+
+#ifdef CONFIG_CACHE_L2X0
+static int __init exynos4_l2x0_cache_init(void)
+{
+	/* TAG, Data Latency Control: 2cycle */
+	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
+	__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
+
+	/* L2X0 Prefetch Control */
+	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
+
+	/* L2X0 Power Control */
+	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
+		     S5P_VA_L2CC + L2X0_POWER_CTRL);
+
+	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
+
+	return 0;
+}
+
+early_initcall(exynos4_l2x0_cache_init);
+#endif
+
+int __init exynos4_init(void)
+{
+	printk(KERN_INFO "EXYNOS4: Initializing architecture\n");
+
+	/* set idle function */
+	pm_idle = exynos4_idle;
+
+	return sysdev_register(&exynos4_sysdev);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/cpufreq.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,569 @@
+/* linux/arch/arm/mach-exynos4/cpufreq.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - CPU frequency scaling 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/types.h>
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+
+#include <mach/map.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-mem.h>
+
+#include <plat/clock.h>
+#include <plat/pm.h>
+
+static struct clk *cpu_clk;
+static struct clk *moutcore;
+static struct clk *mout_mpll;
+static struct clk *mout_apll;
+
+static struct regulator *arm_regulator;
+static struct regulator *int_regulator;
+
+static struct cpufreq_freqs freqs;
+static unsigned int memtype;
+
+enum exynos4_memory_type {
+	DDR2 = 4,
+	LPDDR2,
+	DDR3,
+};
+
+enum cpufreq_level_index {
+	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+};
+
+static struct cpufreq_frequency_table exynos4_freq_table[] = {
+	{L0, 1000*1000},
+	{L1, 800*1000},
+	{L2, 400*1000},
+	{L3, 100*1000},
+	{0, CPUFREQ_TABLE_END},
+};
+
+static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
+	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
+	 */
+
+	/* ARM L0: 1000MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L1: 800MHz */
+	{ 0, 3, 7, 3, 3, 0, 1 },
+
+	/* ARM L2: 400MHz */
+	{ 0, 1, 3, 1, 3, 0, 1 },
+
+	/* ARM L3: 100MHz */
+	{ 0, 0, 1, 0, 3, 1, 1 },
+};
+
+static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVCOPY, DIVHPM }
+	 */
+
+	 /* ARM L0: 1000MHz */
+	{ 3, 0 },
+
+	/* ARM L1: 800MHz */
+	{ 3, 0 },
+
+	/* ARM L2: 400MHz */
+	{ 3, 0 },
+
+	/* ARM L3: 100MHz */
+	{ 3, 0 },
+};
+
+static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
+	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
+	 */
+
+	/* DMC L0: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L1: 400MHz */
+	{ 3, 1, 1, 1, 1, 1, 3, 1 },
+
+	/* DMC L2: 266.7MHz */
+	{ 7, 1, 1, 2, 1, 1, 3, 1 },
+
+	/* DMC L3: 200MHz */
+	{ 7, 1, 1, 3, 1, 1, 3, 1 },
+};
+
+static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
+	 */
+
+	/* ACLK200 L0: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L1: 200MHz */
+	{ 3, 7, 4, 5, 1 },
+
+	/* ACLK200 L2: 160MHz */
+	{ 4, 7, 5, 7, 1 },
+
+	/* ACLK200 L3: 133.3MHz */
+	{ 5, 7, 7, 7, 1 },
+};
+
+static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
+	/*
+	 * Clock divider value for following
+	 * { DIVGDL/R, DIVGPL/R }
+	 */
+
+	/* ACLK_GDL/R L0: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L1: 200MHz */
+	{ 3, 1 },
+
+	/* ACLK_GDL/R L2: 160MHz */
+	{ 4, 1 },
+
+	/* ACLK_GDL/R L3: 133.3MHz */
+	{ 5, 1 },
+};
+
+struct cpufreq_voltage_table {
+	unsigned int	index;		/* any */
+	unsigned int	arm_volt;	/* uV */
+	unsigned int	int_volt;
+};
+
+static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
+	{
+		.index		= L0,
+		.arm_volt	= 1200000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L1,
+		.arm_volt	= 1100000,
+		.int_volt	= 1100000,
+	}, {
+		.index		= L2,
+		.arm_volt	= 1000000,
+		.int_volt	= 1000000,
+	}, {
+		.index		= L3,
+		.arm_volt	= 900000,
+		.int_volt	= 1000000,
+	},
+};
+
+static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
+	/* APLL FOUT L0: 1000MHz */
+	((250 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L1: 800MHz */
+	((200 << 16) | (6 << 8) | 1),
+
+	/* APLL FOUT L2 : 400MHz */
+	((200 << 16) | (6 << 8) | 2),
+
+	/* APLL FOUT L3: 100MHz */
+	((200 << 16) | (6 << 8) | 4),
+};
+
+int exynos4_verify_speed(struct cpufreq_policy *policy)
+{
+	return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
+}
+
+unsigned int exynos4_getspeed(unsigned int cpu)
+{
+	return clk_get_rate(cpu_clk) / 1000;
+}
+
+void exynos4_set_clkdiv(unsigned int div_index)
+{
+	unsigned int tmp;
+
+	/* Change Divider - CPU0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU);
+
+	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
+		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
+		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+		S5P_CLKDIV_CPU0_APLL_MASK);
+
+	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
+	} while (tmp & 0x1111111);
+
+	/* Change Divider - CPU1 */
+
+	tmp = __raw_readl(S5P_CLKDIV_CPU1);
+
+	tmp &= ~((0x7 << 4) | 0x7);
+
+	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
+		(clkdiv_cpu1[div_index][1] << 0));
+
+	__raw_writel(tmp, S5P_CLKDIV_CPU1);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
+	} while (tmp & 0x11);
+
+	/* Change Divider - DMC0 */
+
+	tmp = __raw_readl(S5P_CLKDIV_DMC0);
+
+	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
+		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
+		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
+		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
+
+	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
+		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
+		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
+		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
+		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
+		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
+		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
+		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_DMC0);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
+	} while (tmp & 0x11111111);
+
+	/* Change Divider - TOP */
+
+	tmp = __raw_readl(S5P_CLKDIV_TOP);
+
+	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
+		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
+		S5P_CLKDIV_TOP_ONENAND_MASK);
+
+	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
+		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
+		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
+		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
+		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_TOP);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
+	} while (tmp & 0x11111);
+
+	/* Change Divider - LEFTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
+	} while (tmp & 0x11);
+
+	/* Change Divider - RIGHTBUS */
+
+	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
+
+	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
+
+	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
+		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
+
+	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
+
+	do {
+		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
+	} while (tmp & 0x11);
+}
+
+static void exynos4_set_apll(unsigned int index)
+{
+	unsigned int tmp;
+
+	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
+	clk_set_parent(moutcore, mout_mpll);
+
+	do {
+		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
+			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
+		tmp &= 0x7;
+	} while (tmp != 0x2);
+
+	/* 2. Set APLL Lock time */
+	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
+
+	/* 3. Change PLL PMS values */
+	tmp = __raw_readl(S5P_APLL_CON0);
+	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
+	tmp |= exynos4_apll_pms_table[index];
+	__raw_writel(tmp, S5P_APLL_CON0);
+
+	/* 4. wait_lock_time */
+	do {
+		tmp = __raw_readl(S5P_APLL_CON0);
+	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
+
+	/* 5. MUX_CORE_SEL = APLL */
+	clk_set_parent(moutcore, mout_apll);
+
+	do {
+		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
+		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
+	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
+}
+
+static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index)
+{
+	unsigned int tmp;
+
+	if (old_index > new_index) {
+		/* The frequency changing to L0 needs to change apll */
+		if (freqs.new == exynos4_freq_table[L0].frequency) {
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+
+			/* 2. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+		} else {
+			/* 1. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+
+			/* 2. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+		}
+	}
+
+	else if (old_index < new_index) {
+		/* The frequency changing from L0 needs to change apll */
+		if (freqs.old == exynos4_freq_table[L0].frequency) {
+			/* 1. Change the apll m,p,s value */
+			exynos4_set_apll(new_index);
+
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+		} else {
+			/* 1. Change just s value in apll m,p,s value */
+			tmp = __raw_readl(S5P_APLL_CON0);
+			tmp &= ~(0x7 << 0);
+			tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+			__raw_writel(tmp, S5P_APLL_CON0);
+
+			/* 2. Change the system clock divider values */
+			exynos4_set_clkdiv(new_index);
+		}
+	}
+}
+
+static int exynos4_target(struct cpufreq_policy *policy,
+			  unsigned int target_freq,
+			  unsigned int relation)
+{
+	unsigned int index, old_index;
+	unsigned int arm_volt, int_volt;
+
+	freqs.old = exynos4_getspeed(policy->cpu);
+
+	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
+					   freqs.old, relation, &old_index))
+		return -EINVAL;
+
+	if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
+					   target_freq, relation, &index))
+		return -EINVAL;
+
+	freqs.new = exynos4_freq_table[index].frequency;
+	freqs.cpu = policy->cpu;
+
+	if (freqs.new == freqs.old)
+		return 0;
+
+	/* get the voltage value */
+	arm_volt = exynos4_volt_table[index].arm_volt;
+	int_volt = exynos4_volt_table[index].int_volt;
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	/* control regulator */
+	if (freqs.new > freqs.old) {
+		/* Voltage up */
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+	}
+
+	/* Clock Configuration Procedure */
+	exynos4_set_frequency(old_index, index);
+
+	/* control regulator */
+	if (freqs.new < freqs.old) {
+		/* Voltage down */
+		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
+		regulator_set_voltage(int_regulator, int_volt, int_volt);
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+
+static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
+{
+	return 0;
+}
+#endif
+
+static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+	policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
+
+	cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
+
+	/* set the transition latency value */
+	policy->cpuinfo.transition_latency = 100000;
+
+	/*
+	 * EXYNOS4 multi-core processors has 2 cores
+	 * that the frequency cannot be set independently.
+	 * Each cpu is bound to the same speed.
+	 * So the affected cpu is all of the cpus.
+	 */
+	cpumask_setall(policy->cpus);
+
+	return cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
+}
+
+static struct cpufreq_driver exynos4_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= exynos4_verify_speed,
+	.target		= exynos4_target,
+	.get		= exynos4_getspeed,
+	.init		= exynos4_cpufreq_cpu_init,
+	.name		= "exynos4_cpufreq",
+#ifdef CONFIG_PM
+	.suspend	= exynos4_cpufreq_suspend,
+	.resume		= exynos4_cpufreq_resume,
+#endif
+};
+
+static int __init exynos4_cpufreq_init(void)
+{
+	cpu_clk = clk_get(NULL, "armclk");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	moutcore = clk_get(NULL, "moutcore");
+	if (IS_ERR(moutcore))
+		goto out;
+
+	mout_mpll = clk_get(NULL, "mout_mpll");
+	if (IS_ERR(mout_mpll))
+		goto out;
+
+	mout_apll = clk_get(NULL, "mout_apll");
+	if (IS_ERR(mout_apll))
+		goto out;
+
+	arm_regulator = regulator_get(NULL, "vdd_arm");
+	if (IS_ERR(arm_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
+		goto out;
+	}
+
+	int_regulator = regulator_get(NULL, "vdd_int");
+	if (IS_ERR(int_regulator)) {
+		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
+		goto out;
+	}
+
+	/*
+	 * Check DRAM type.
+	 * Because DVFS level is different according to DRAM type.
+	 */
+	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
+	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
+	memtype &= S5P_DMC0_MEMTYPE_MASK;
+
+	if ((memtype < DDR2) && (memtype > DDR3)) {
+		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
+		goto out;
+	} else {
+		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
+	}
+
+	return cpufreq_register_driver(&exynos4_driver);
+
+out:
+	if (!IS_ERR(cpu_clk))
+		clk_put(cpu_clk);
+
+	if (!IS_ERR(moutcore))
+		clk_put(moutcore);
+
+	if (!IS_ERR(mout_mpll))
+		clk_put(mout_mpll);
+
+	if (!IS_ERR(mout_apll))
+		clk_put(mout_apll);
+
+	if (!IS_ERR(arm_regulator))
+		regulator_put(arm_regulator);
+
+	if (!IS_ERR(int_regulator))
+		regulator_put(int_regulator);
+
+	printk(KERN_ERR "%s: failed initialization\n", __func__);
+
+	return -EINVAL;
+}
+late_initcall(exynos4_cpufreq_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-ahci.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-ahci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-ahci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-ahci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,263 @@
+/* linux/arch/arm/mach-exynos4/dev-ahci.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - AHCI 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/clk.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/ahci_platform.h>
+
+#include <plat/cpu.h>
+
+#include <mach/irqs.h>
+#include <mach/map.h>
+#include <mach/regs-pmu.h>
+
+/* PHY Control Register */
+#define SATA_CTRL0		0x0
+/* PHY Link Control Register */
+#define SATA_CTRL1		0x4
+/* PHY Status Register */
+#define SATA_PHY_STATUS		0x8
+
+#define SATA_CTRL0_RX_DATA_VALID(x)	(x << 27)
+#define SATA_CTRL0_SPEED_MODE		(1 << 26)
+#define SATA_CTRL0_M_PHY_CAL		(1 << 19)
+#define SATA_CTRL0_PHY_CMU_RST_N	(1 << 10)
+#define SATA_CTRL0_M_PHY_LN_RST_N	(1 << 9)
+#define SATA_CTRL0_PHY_POR_N		(1 << 8)
+
+#define SATA_CTRL1_RST_PMALIVE_N	(1 << 8)
+#define SATA_CTRL1_RST_RXOOB_N		(1 << 7)
+#define SATA_CTRL1_RST_RX_N		(1 << 6)
+#define SATA_CTRL1_RST_TX_N		(1 << 5)
+
+#define SATA_PHY_STATUS_CMU_OK		(1 << 18)
+#define SATA_PHY_STATUS_LANE_OK		(1 << 16)
+
+#define LANE0		0x200
+#define COM_LANE	0xA00
+
+#define HOST_PORTS_IMPL	0xC
+#define SCLK_SATA_FREQ	(67 * MHZ)
+
+static void __iomem *phy_base, *phy_ctrl;
+
+struct phy_reg {
+	u8	reg;
+	u8	val;
+};
+
+/* SATA PHY setup */
+static const struct phy_reg exynos4_sataphy_cmu[] = {
+	{ 0x00, 0x06 }, { 0x02, 0x80 }, { 0x22, 0xa0 }, { 0x23, 0x42 },
+	{ 0x2e, 0x04 }, { 0x2f, 0x50 }, { 0x30, 0x70 }, { 0x31, 0x02 },
+	{ 0x32, 0x25 }, { 0x33, 0x40 }, { 0x34, 0x01 }, { 0x35, 0x40 },
+	{ 0x61, 0x2e }, { 0x63, 0x5e }, { 0x65, 0x42 }, { 0x66, 0xd1 },
+	{ 0x67, 0x20 }, { 0x68, 0x28 }, { 0x69, 0x78 }, { 0x6a, 0x04 },
+	{ 0x6b, 0xc8 }, { 0x6c, 0x06 },
+};
+
+static const struct phy_reg exynos4_sataphy_lane[] = {
+	{ 0x00, 0x02 }, { 0x05, 0x10 }, { 0x06, 0x84 }, { 0x07, 0x04 },
+	{ 0x08, 0xe0 }, { 0x10, 0x23 }, { 0x13, 0x05 }, { 0x14, 0x30 },
+	{ 0x15, 0x00 }, { 0x17, 0x70 }, { 0x18, 0xf2 }, { 0x19, 0x1e },
+	{ 0x1a, 0x18 }, { 0x1b, 0x0d }, { 0x1c, 0x08 }, { 0x50, 0x60 },
+	{ 0x51, 0x0f },
+};
+
+static const struct phy_reg exynos4_sataphy_comlane[] = {
+	{ 0x01, 0x20 }, { 0x03, 0x40 }, { 0x04, 0x3c }, { 0x05, 0x7d },
+	{ 0x06, 0x1d }, { 0x07, 0xcf }, { 0x08, 0x05 }, { 0x09, 0x63 },
+	{ 0x0a, 0x29 }, { 0x0b, 0xc4 }, { 0x0c, 0x01 }, { 0x0d, 0x03 },
+	{ 0x0e, 0x28 }, { 0x0f, 0x98 }, { 0x10, 0x19 }, { 0x13, 0x80 },
+	{ 0x14, 0xf0 }, { 0x15, 0xd0 }, { 0x39, 0xa0 }, { 0x3a, 0xa0 },
+	{ 0x3b, 0xa0 }, { 0x3c, 0xa0 }, { 0x3d, 0xa0 }, { 0x3e, 0xa0 },
+	{ 0x3f, 0xa0 }, { 0x40, 0x42 }, { 0x42, 0x80 }, { 0x43, 0x58 },
+	{ 0x45, 0x44 }, { 0x46, 0x5c }, { 0x47, 0x86 }, { 0x48, 0x8d },
+	{ 0x49, 0xd0 }, { 0x4a, 0x09 }, { 0x4b, 0x90 }, { 0x4c, 0x07 },
+	{ 0x4d, 0x40 }, { 0x51, 0x20 }, { 0x52, 0x32 }, { 0x7f, 0xd8 },
+	{ 0x80, 0x1a }, { 0x81, 0xff }, { 0x82, 0x11 }, { 0x83, 0x00 },
+	{ 0x87, 0xf0 }, { 0x87, 0xff }, { 0x87, 0xff }, { 0x87, 0xff },
+	{ 0x87, 0xff }, { 0x8c, 0x1c }, { 0x8d, 0xc2 }, { 0x8e, 0xc3 },
+	{ 0x8f, 0x3f }, { 0x90, 0x0a }, { 0x96, 0xf8 },
+};
+
+static int wait_for_phy_ready(void __iomem *reg, unsigned long bit)
+{
+	unsigned long timeout;
+
+	/* wait for maximum of 3 sec */
+	timeout = jiffies + msecs_to_jiffies(3000);
+	while (!(__raw_readl(reg) & bit)) {
+		if (time_after(jiffies, timeout))
+			return -1;
+		cpu_relax();
+	}
+	return 0;
+}
+
+static int ahci_phy_init(void __iomem *mmio)
+{
+	int i, ctrl0;
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_cmu); i++)
+		__raw_writeb(exynos4_sataphy_cmu[i].val,
+		phy_base + (exynos4_sataphy_cmu[i].reg * 4));
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_lane); i++)
+		__raw_writeb(exynos4_sataphy_lane[i].val,
+		phy_base + (LANE0 + exynos4_sataphy_lane[i].reg) * 4);
+
+	for (i = 0; i < ARRAY_SIZE(exynos4_sataphy_comlane); i++)
+		__raw_writeb(exynos4_sataphy_comlane[i].val,
+		phy_base + (COM_LANE + exynos4_sataphy_comlane[i].reg) * 4);
+
+	__raw_writeb(0x07, phy_base);
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_PHY_CMU_RST_N;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
+				SATA_PHY_STATUS_CMU_OK) < 0) {
+		printk(KERN_ERR "PHY CMU not ready\n");
+		return -EBUSY;
+	}
+
+	__raw_writeb(0x03, phy_base + (COM_LANE * 4));
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_M_PHY_LN_RST_N;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	if (wait_for_phy_ready(phy_ctrl + SATA_PHY_STATUS,
+				SATA_PHY_STATUS_LANE_OK) < 0) {
+		printk(KERN_ERR "PHY LANE not ready\n");
+		return -EBUSY;
+	}
+
+	ctrl0 = __raw_readl(phy_ctrl + SATA_CTRL0);
+	ctrl0 |= SATA_CTRL0_M_PHY_CAL;
+	__raw_writel(ctrl0, phy_ctrl + SATA_CTRL0);
+
+	return 0;
+}
+
+static int exynos4_ahci_init(struct device *dev, void __iomem *mmio)
+{
+	struct clk *clk_sata, *clk_sataphy, *clk_sclk_sata;
+	int val, ret;
+
+	phy_base = ioremap(EXYNOS4_PA_SATAPHY, SZ_64K);
+	if (!phy_base) {
+		dev_err(dev, "failed to allocate memory for SATA PHY\n");
+		return -ENOMEM;
+	}
+
+	phy_ctrl = ioremap(EXYNOS4_PA_SATAPHY_CTRL, SZ_16);
+	if (!phy_ctrl) {
+		dev_err(dev, "failed to allocate memory for SATA PHY CTRL\n");
+		ret = -ENOMEM;
+		goto err1;
+	}
+
+	clk_sata = clk_get(dev, "sata");
+	if (IS_ERR(clk_sata)) {
+		dev_err(dev, "failed to get sata clock\n");
+		ret = PTR_ERR(clk_sata);
+		clk_sata = NULL;
+		goto err2;
+
+	}
+	clk_enable(clk_sata);
+
+	clk_sataphy = clk_get(dev, "sataphy");
+	if (IS_ERR(clk_sataphy)) {
+		dev_err(dev, "failed to get sataphy clock\n");
+		ret = PTR_ERR(clk_sataphy);
+		clk_sataphy = NULL;
+		goto err3;
+	}
+	clk_enable(clk_sataphy);
+
+	clk_sclk_sata = clk_get(dev, "sclk_sata");
+	if (IS_ERR(clk_sclk_sata)) {
+		dev_err(dev, "failed to get sclk_sata\n");
+		ret = PTR_ERR(clk_sclk_sata);
+		clk_sclk_sata = NULL;
+		goto err4;
+	}
+	clk_enable(clk_sclk_sata);
+	clk_set_rate(clk_sclk_sata, SCLK_SATA_FREQ);
+
+	__raw_writel(S5P_PMU_SATA_PHY_CONTROL_EN, S5P_PMU_SATA_PHY_CONTROL);
+
+	/* Enable PHY link control */
+	val = SATA_CTRL1_RST_PMALIVE_N | SATA_CTRL1_RST_RXOOB_N |
+			SATA_CTRL1_RST_RX_N | SATA_CTRL1_RST_TX_N;
+	__raw_writel(val, phy_ctrl + SATA_CTRL1);
+
+	/* Set communication speed as 3Gbps and enable PHY power */
+	val = SATA_CTRL0_RX_DATA_VALID(3) | SATA_CTRL0_SPEED_MODE |
+			SATA_CTRL0_PHY_POR_N;
+	__raw_writel(val, phy_ctrl + SATA_CTRL0);
+
+	/* Port0 is available */
+	__raw_writel(0x1, mmio + HOST_PORTS_IMPL);
+
+	return ahci_phy_init(mmio);
+
+err4:
+	clk_disable(clk_sataphy);
+	clk_put(clk_sataphy);
+err3:
+	clk_disable(clk_sata);
+	clk_put(clk_sata);
+err2:
+	iounmap(phy_ctrl);
+err1:
+	iounmap(phy_base);
+
+	return ret;
+}
+
+static struct ahci_platform_data exynos4_ahci_pdata = {
+	.init = exynos4_ahci_init,
+};
+
+static struct resource exynos4_ahci_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SATA,
+		.end	= EXYNOS4_PA_SATA + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SATA,
+		.end	= IRQ_SATA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 exynos4_ahci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ahci = {
+	.name		= "ahci",
+	.id		= -1,
+	.resource	= exynos4_ahci_resource,
+	.num_resources	= ARRAY_SIZE(exynos4_ahci_resource),
+	.dev		= {
+		.platform_data		= &exynos4_ahci_pdata,
+		.dma_mask		= &exynos4_ahci_dmamask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-audio.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-audio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-audio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,367 @@
+/* linux/arch/arm/mach-exynos4/dev-audio.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2010 Samsung Electronics Co. Ltd
+ *	Jaswinder Singh <jassi.brar@samsung.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 <linux/dma-mapping.h>
+#include <linux/gpio.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/audio.h>
+
+#include <mach/map.h>
+#include <mach/dma.h>
+#include <mach/irqs.h>
+
+static const char *rclksrc[] = {
+	[0] = "busclk",
+	[1] = "i2sclk",
+};
+
+static int exynos4_cfg_i2s(struct platform_device *pdev)
+{
+	/* configure GPIO for i2s port */
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 7, S3C_GPIO_SFN(2));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(2));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(4));
+		break;
+	default:
+		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata i2sv5_pdata = {
+	.cfg_gpio = exynos4_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
+					 | QUIRK_NEED_RSTCLR,
+			.src_clk = rclksrc,
+		},
+	},
+};
+
+static struct resource exynos4_i2s0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S0,
+		.end	= EXYNOS4_PA_I2S0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S0_TX,
+		.end	= DMACH_I2S0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S0_RX,
+		.end	= DMACH_I2S0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DMACH_I2S0S_TX,
+		.end	= DMACH_I2S0S_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s0 = {
+	.name = "samsung-i2s",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(exynos4_i2s0_resource),
+	.resource = exynos4_i2s0_resource,
+	.dev = {
+		.platform_data = &i2sv5_pdata,
+	},
+};
+
+static const char *rclksrc_v3[] = {
+	[0] = "sclk_i2s",
+	[1] = "no_such_clock",
+};
+
+static struct s3c_audio_pdata i2sv3_pdata = {
+	.cfg_gpio = exynos4_cfg_i2s,
+	.type = {
+		.i2s = {
+			.quirks = QUIRK_NO_MUXPSR,
+			.src_clk = rclksrc_v3,
+		},
+	},
+};
+
+static struct resource exynos4_i2s1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S1,
+		.end	= EXYNOS4_PA_I2S1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S1_TX,
+		.end	= DMACH_I2S1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S1_RX,
+		.end	= DMACH_I2S1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s1 = {
+	.name = "samsung-i2s",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(exynos4_i2s1_resource),
+	.resource = exynos4_i2s1_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+static struct resource exynos4_i2s2_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_I2S2,
+		.end	= EXYNOS4_PA_I2S2 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_I2S2_TX,
+		.end	= DMACH_I2S2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_I2S2_RX,
+		.end	= DMACH_I2S2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_i2s2 = {
+	.name = "samsung-i2s",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(exynos4_i2s2_resource),
+	.resource = exynos4_i2s2_resource,
+	.dev = {
+		.platform_data = &i2sv3_pdata,
+	},
+};
+
+/* PCM Controller platform_devices */
+
+static int exynos4_pcm_cfg_gpio(struct platform_device *pdev)
+{
+	switch (pdev->id) {
+	case 0:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPZ(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 1:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(3));
+		break;
+	case 2:
+		s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 5, S3C_GPIO_SFN(3));
+		break;
+	default:
+		printk(KERN_DEBUG "Invalid PCM Controller number!");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static struct s3c_audio_pdata s3c_pcm_pdata = {
+	.cfg_gpio = exynos4_pcm_cfg_gpio,
+};
+
+static struct resource exynos4_pcm0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM0,
+		.end	= EXYNOS4_PA_PCM0 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM0_TX,
+		.end	= DMACH_PCM0_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM0_RX,
+		.end	= DMACH_PCM0_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm0 = {
+	.name = "samsung-pcm",
+	.id = 0,
+	.num_resources = ARRAY_SIZE(exynos4_pcm0_resource),
+	.resource = exynos4_pcm0_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource exynos4_pcm1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM1,
+		.end	= EXYNOS4_PA_PCM1 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM1_TX,
+		.end	= DMACH_PCM1_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM1_RX,
+		.end	= DMACH_PCM1_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm1 = {
+	.name = "samsung-pcm",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(exynos4_pcm1_resource),
+	.resource = exynos4_pcm1_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+static struct resource exynos4_pcm2_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PCM2,
+		.end	= EXYNOS4_PA_PCM2 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_PCM2_TX,
+		.end	= DMACH_PCM2_TX,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_PCM2_RX,
+		.end	= DMACH_PCM2_RX,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device exynos4_device_pcm2 = {
+	.name = "samsung-pcm",
+	.id = 2,
+	.num_resources = ARRAY_SIZE(exynos4_pcm2_resource),
+	.resource = exynos4_pcm2_resource,
+	.dev = {
+		.platform_data = &s3c_pcm_pdata,
+	},
+};
+
+/* AC97 Controller platform devices */
+
+static int exynos4_ac97_cfg_gpio(struct platform_device *pdev)
+{
+	return s3c_gpio_cfgpin_range(EXYNOS4_GPC0(0), 5, S3C_GPIO_SFN(4));
+}
+
+static struct resource exynos4_ac97_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_AC97,
+		.end	= EXYNOS4_PA_AC97 + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_AC97_PCMOUT,
+		.end	= DMACH_AC97_PCMOUT,
+		.flags	= IORESOURCE_DMA,
+	},
+	[2] = {
+		.start	= DMACH_AC97_PCMIN,
+		.end	= DMACH_AC97_PCMIN,
+		.flags	= IORESOURCE_DMA,
+	},
+	[3] = {
+		.start	= DMACH_AC97_MICIN,
+		.end	= DMACH_AC97_MICIN,
+		.flags	= IORESOURCE_DMA,
+	},
+	[4] = {
+		.start	= IRQ_AC97,
+		.end	= IRQ_AC97,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_audio_pdata s3c_ac97_pdata = {
+	.cfg_gpio = exynos4_ac97_cfg_gpio,
+};
+
+static u64 exynos4_ac97_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_ac97 = {
+	.name = "samsung-ac97",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(exynos4_ac97_resource),
+	.resource = exynos4_ac97_resource,
+	.dev = {
+		.platform_data = &s3c_ac97_pdata,
+		.dma_mask = &exynos4_ac97_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+/* S/PDIF Controller platform_device */
+
+static int exynos4_spdif_cfg_gpio(struct platform_device *pdev)
+{
+	s3c_gpio_cfgpin_range(EXYNOS4_GPC1(0), 2, S3C_GPIO_SFN(3));
+
+	return 0;
+}
+
+static struct resource exynos4_spdif_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SPDIF,
+		.end	= EXYNOS4_PA_SPDIF + 0x100 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= DMACH_SPDIF,
+		.end	= DMACH_SPDIF,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct s3c_audio_pdata samsung_spdif_pdata = {
+	.cfg_gpio = exynos4_spdif_cfg_gpio,
+};
+
+static u64 exynos4_spdif_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device exynos4_device_spdif = {
+	.name = "samsung-spdif",
+	.id = -1,
+	.num_resources = ARRAY_SIZE(exynos4_spdif_resource),
+	.resource = exynos4_spdif_resource,
+	.dev = {
+		.platform_data = &samsung_spdif_pdata,
+		.dma_mask = &exynos4_spdif_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-pd.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-pd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-pd.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,139 @@
+/* linux/arch/arm/mach-exynos4/dev-pd.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Power Domain 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/io.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+
+#include <mach/regs-pmu.h>
+
+#include <plat/pd.h>
+
+static int exynos4_pd_enable(struct device *dev)
+{
+	struct samsung_pd_info *pdata =  dev->platform_data;
+	u32 timeout;
+
+	__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
+
+	/* Wait max 1ms */
+	timeout = 10;
+	while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
+		!= S5P_INT_LOCAL_PWR_EN) {
+		if (timeout == 0) {
+			printk(KERN_ERR "Power domain %s enable failed.\n",
+				dev_name(dev));
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		udelay(100);
+	}
+
+	return 0;
+}
+
+static int exynos4_pd_disable(struct device *dev)
+{
+	struct samsung_pd_info *pdata =  dev->platform_data;
+	u32 timeout;
+
+	__raw_writel(0, pdata->base);
+
+	/* Wait max 1ms */
+	timeout = 10;
+	while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
+		if (timeout == 0) {
+			printk(KERN_ERR "Power domain %s disable failed.\n",
+				dev_name(dev));
+			return -ETIMEDOUT;
+		}
+		timeout--;
+		udelay(100);
+	}
+
+	return 0;
+}
+
+struct platform_device exynos4_device_pd[] = {
+	{
+		.name		= "samsung-pd",
+		.id		= 0,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_MFC_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 1,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_G3D_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 2,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_LCD0_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 3,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_LCD1_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 4,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_TV_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 5,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_CAM_CONF,
+			},
+		},
+	}, {
+		.name		= "samsung-pd",
+		.id		= 6,
+		.dev = {
+			.platform_data = &(struct samsung_pd_info) {
+				.enable		= exynos4_pd_enable,
+				.disable	= exynos4_pd_disable,
+				.base		= S5P_PMU_GPS_CONF,
+			},
+		},
+	},
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-sysmmu.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-sysmmu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dev-sysmmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,232 @@
+/* linux/arch/arm/mach-exynos4/dev-sysmmu.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - System MMU 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/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+#include <mach/sysmmu.h>
+#include <plat/s5p-clock.h>
+
+/* These names must be equal to the clock names in mach-exynos4/clock.c */
+const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM] = {
+	"SYSMMU_MDMA"	,
+	"SYSMMU_SSS"	,
+	"SYSMMU_FIMC0"	,
+	"SYSMMU_FIMC1"	,
+	"SYSMMU_FIMC2"	,
+	"SYSMMU_FIMC3"	,
+	"SYSMMU_JPEG"	,
+	"SYSMMU_FIMD0"	,
+	"SYSMMU_FIMD1"	,
+	"SYSMMU_PCIe"	,
+	"SYSMMU_G2D"	,
+	"SYSMMU_ROTATOR",
+	"SYSMMU_MDMA2"	,
+	"SYSMMU_TV"	,
+	"SYSMMU_MFC_L"	,
+	"SYSMMU_MFC_R"	,
+};
+
+static struct resource exynos4_sysmmu_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SYSMMU_MDMA,
+		.end	= EXYNOS4_PA_SYSMMU_MDMA + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SYSMMU_MDMA0_0,
+		.end	= IRQ_SYSMMU_MDMA0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= EXYNOS4_PA_SYSMMU_SSS,
+		.end	= EXYNOS4_PA_SYSMMU_SSS + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = {
+		.start	= IRQ_SYSMMU_SSS_0,
+		.end	= IRQ_SYSMMU_SSS_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[4] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC0,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC0 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[5] = {
+		.start	= IRQ_SYSMMU_FIMC0_0,
+		.end	= IRQ_SYSMMU_FIMC0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[6] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC1,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC1 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[7] = {
+		.start	= IRQ_SYSMMU_FIMC1_0,
+		.end	= IRQ_SYSMMU_FIMC1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[8] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC2,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC2 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[9] = {
+		.start	= IRQ_SYSMMU_FIMC2_0,
+		.end	= IRQ_SYSMMU_FIMC2_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[10] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMC3,
+		.end	= EXYNOS4_PA_SYSMMU_FIMC3 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[11] = {
+		.start	= IRQ_SYSMMU_FIMC3_0,
+		.end	= IRQ_SYSMMU_FIMC3_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[12] = {
+		.start	= EXYNOS4_PA_SYSMMU_JPEG,
+		.end	= EXYNOS4_PA_SYSMMU_JPEG + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[13] = {
+		.start	= IRQ_SYSMMU_JPEG_0,
+		.end	= IRQ_SYSMMU_JPEG_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[14] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMD0,
+		.end	= EXYNOS4_PA_SYSMMU_FIMD0 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[15] = {
+		.start	= IRQ_SYSMMU_LCD0_M0_0,
+		.end	= IRQ_SYSMMU_LCD0_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[16] = {
+		.start	= EXYNOS4_PA_SYSMMU_FIMD1,
+		.end	= EXYNOS4_PA_SYSMMU_FIMD1 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[17] = {
+		.start	= IRQ_SYSMMU_LCD1_M1_0,
+		.end	= IRQ_SYSMMU_LCD1_M1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[18] = {
+		.start	= EXYNOS4_PA_SYSMMU_PCIe,
+		.end	= EXYNOS4_PA_SYSMMU_PCIe + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[19] = {
+		.start	= IRQ_SYSMMU_PCIE_0,
+		.end	= IRQ_SYSMMU_PCIE_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[20] = {
+		.start	= EXYNOS4_PA_SYSMMU_G2D,
+		.end	= EXYNOS4_PA_SYSMMU_G2D + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[21] = {
+		.start	= IRQ_SYSMMU_2D_0,
+		.end	= IRQ_SYSMMU_2D_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[22] = {
+		.start	= EXYNOS4_PA_SYSMMU_ROTATOR,
+		.end	= EXYNOS4_PA_SYSMMU_ROTATOR + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[23] = {
+		.start	= IRQ_SYSMMU_ROTATOR_0,
+		.end	= IRQ_SYSMMU_ROTATOR_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[24] = {
+		.start	= EXYNOS4_PA_SYSMMU_MDMA2,
+		.end	= EXYNOS4_PA_SYSMMU_MDMA2 + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[25] = {
+		.start	= IRQ_SYSMMU_MDMA1_0,
+		.end	= IRQ_SYSMMU_MDMA1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[26] = {
+		.start	= EXYNOS4_PA_SYSMMU_TV,
+		.end	= EXYNOS4_PA_SYSMMU_TV + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[27] = {
+		.start	= IRQ_SYSMMU_TV_M0_0,
+		.end	= IRQ_SYSMMU_TV_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[28] = {
+		.start	= EXYNOS4_PA_SYSMMU_MFC_L,
+		.end	= EXYNOS4_PA_SYSMMU_MFC_L + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[29] = {
+		.start	= IRQ_SYSMMU_MFC_M0_0,
+		.end	= IRQ_SYSMMU_MFC_M0_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[30] = {
+		.start	= EXYNOS4_PA_SYSMMU_MFC_R,
+		.end	= EXYNOS4_PA_SYSMMU_MFC_R + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[31] = {
+		.start	= IRQ_SYSMMU_MFC_M1_0,
+		.end	= IRQ_SYSMMU_MFC_M1_0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device exynos4_device_sysmmu = {
+	.name		= "s5p-sysmmu",
+	.id		= 32,
+	.num_resources	= ARRAY_SIZE(exynos4_sysmmu_resource),
+	.resource	= exynos4_sysmmu_resource,
+};
+EXPORT_SYMBOL(exynos4_device_sysmmu);
+
+static struct clk *sysmmu_clk[S5P_SYSMMU_TOTAL_IPNUM];
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips)
+{
+	sysmmu_clk[ips] = clk_get(dev, sysmmu_ips_name[ips]);
+	if (IS_ERR(sysmmu_clk[ips]))
+		sysmmu_clk[ips] = NULL;
+	else
+		clk_put(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_enable(sysmmu_ips ips)
+{
+	if (sysmmu_clk[ips])
+		clk_enable(sysmmu_clk[ips]);
+}
+
+void sysmmu_clk_disable(sysmmu_ips ips)
+{
+	if (sysmmu_clk[ips])
+		clk_disable(sysmmu_clk[ips]);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dma.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,172 @@
+/* linux/arch/arm/mach-exynos4/dma.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.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/platform_device.h>
+#include <linux/dma-mapping.h>
+
+#include <plat/devs.h>
+#include <plat/irqs.h>
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#include <plat/s3c-pl330-pdata.h>
+
+static u64 dma_dmamask = DMA_BIT_MASK(32);
+
+static struct resource exynos4_pdma0_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PDMA0,
+		.end	= EXYNOS4_PA_PDMA0 + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PDMA0,
+		.end	= IRQ_PDMA0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata exynos4_pdma0_pdata = {
+	.peri = {
+		[0] = DMACH_PCM0_RX,
+		[1] = DMACH_PCM0_TX,
+		[2] = DMACH_PCM2_RX,
+		[3] = DMACH_PCM2_TX,
+		[4] = DMACH_MSM_REQ0,
+		[5] = DMACH_MSM_REQ2,
+		[6] = DMACH_SPI0_RX,
+		[7] = DMACH_SPI0_TX,
+		[8] = DMACH_SPI2_RX,
+		[9] = DMACH_SPI2_TX,
+		[10] = DMACH_I2S0S_TX,
+		[11] = DMACH_I2S0_RX,
+		[12] = DMACH_I2S0_TX,
+		[13] = DMACH_I2S2_RX,
+		[14] = DMACH_I2S2_TX,
+		[15] = DMACH_UART0_RX,
+		[16] = DMACH_UART0_TX,
+		[17] = DMACH_UART2_RX,
+		[18] = DMACH_UART2_TX,
+		[19] = DMACH_UART4_RX,
+		[20] = DMACH_UART4_TX,
+		[21] = DMACH_SLIMBUS0_RX,
+		[22] = DMACH_SLIMBUS0_TX,
+		[23] = DMACH_SLIMBUS2_RX,
+		[24] = DMACH_SLIMBUS2_TX,
+		[25] = DMACH_SLIMBUS4_RX,
+		[26] = DMACH_SLIMBUS4_TX,
+		[27] = DMACH_AC97_MICIN,
+		[28] = DMACH_AC97_PCMIN,
+		[29] = DMACH_AC97_PCMOUT,
+		[30] = DMACH_MAX,
+		[31] = DMACH_MAX,
+	},
+};
+
+static struct platform_device exynos4_device_pdma0 = {
+	.name		= "s3c-pl330",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(exynos4_pdma0_resource),
+	.resource	= exynos4_pdma0_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma0_pdata,
+	},
+};
+
+static struct resource exynos4_pdma1_resource[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_PDMA1,
+		.end	= EXYNOS4_PA_PDMA1 + SZ_4K,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_PDMA1,
+		.end	= IRQ_PDMA1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct s3c_pl330_platdata exynos4_pdma1_pdata = {
+	.peri = {
+		[0] = DMACH_PCM0_RX,
+		[1] = DMACH_PCM0_TX,
+		[2] = DMACH_PCM1_RX,
+		[3] = DMACH_PCM1_TX,
+		[4] = DMACH_MSM_REQ1,
+		[5] = DMACH_MSM_REQ3,
+		[6] = DMACH_SPI1_RX,
+		[7] = DMACH_SPI1_TX,
+		[8] = DMACH_I2S0S_TX,
+		[9] = DMACH_I2S0_RX,
+		[10] = DMACH_I2S0_TX,
+		[11] = DMACH_I2S1_RX,
+		[12] = DMACH_I2S1_TX,
+		[13] = DMACH_UART0_RX,
+		[14] = DMACH_UART0_TX,
+		[15] = DMACH_UART1_RX,
+		[16] = DMACH_UART1_TX,
+		[17] = DMACH_UART3_RX,
+		[18] = DMACH_UART3_TX,
+		[19] = DMACH_SLIMBUS1_RX,
+		[20] = DMACH_SLIMBUS1_TX,
+		[21] = DMACH_SLIMBUS3_RX,
+		[22] = DMACH_SLIMBUS3_TX,
+		[23] = DMACH_SLIMBUS5_RX,
+		[24] = DMACH_SLIMBUS5_TX,
+		[25] = DMACH_SLIMBUS0AUX_RX,
+		[26] = DMACH_SLIMBUS0AUX_TX,
+		[27] = DMACH_SPDIF,
+		[28] = DMACH_MAX,
+		[29] = DMACH_MAX,
+		[30] = DMACH_MAX,
+		[31] = DMACH_MAX,
+	},
+};
+
+static struct platform_device exynos4_device_pdma1 = {
+	.name		= "s3c-pl330",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(exynos4_pdma1_resource),
+	.resource	= exynos4_pdma1_resource,
+	.dev		= {
+		.dma_mask = &dma_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.platform_data = &exynos4_pdma1_pdata,
+	},
+};
+
+static struct platform_device *exynos4_dmacs[] __initdata = {
+	&exynos4_device_pdma0,
+	&exynos4_device_pdma1,
+};
+
+static int __init exynos4_dma_init(void)
+{
+	platform_add_devices(exynos4_dmacs, ARRAY_SIZE(exynos4_dmacs));
+
+	return 0;
+}
+arch_initcall(exynos4_dma_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/gpiolib.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/gpiolib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/gpiolib.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,365 @@
+/* linux/arch/arm/mach-exynos4/gpiolib.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIOlib 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/irq.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+
+#include <mach/map.h>
+
+#include <plat/gpio-core.h>
+#include <plat/gpio-cfg.h>
+#include <plat/gpio-cfg-helpers.h>
+
+static struct s3c_gpio_cfg gpio_cfg = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+static struct s3c_gpio_cfg gpio_cfg_noint = {
+	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
+	.set_pull	= s3c_gpio_setpull_updown,
+	.get_pull	= s3c_gpio_getpull_updown,
+};
+
+/*
+ * Following are the gpio banks in v310.
+ *
+ * The 'config' member when left to NULL, is initialized to the default
+ * structure gpio_cfg in the init function below.
+ *
+ * The 'base' member is also initialized in the init function below.
+ * Note: The initialization of 'base' member of s3c_gpio_chip structure
+ * uses the above macro and depends on the banks being listed in order here.
+ */
+static struct s3c_gpio_chip exynos4_gpio_part1_4bit[] = {
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPA0(0),
+			.ngpio	= EXYNOS4_GPIO_A0_NR,
+			.label	= "GPA0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPA1(0),
+			.ngpio	= EXYNOS4_GPIO_A1_NR,
+			.label	= "GPA1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPB(0),
+			.ngpio	= EXYNOS4_GPIO_B_NR,
+			.label	= "GPB",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPC0(0),
+			.ngpio	= EXYNOS4_GPIO_C0_NR,
+			.label	= "GPC0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPC1(0),
+			.ngpio	= EXYNOS4_GPIO_C1_NR,
+			.label	= "GPC1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPD0(0),
+			.ngpio	= EXYNOS4_GPIO_D0_NR,
+			.label	= "GPD0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPD1(0),
+			.ngpio	= EXYNOS4_GPIO_D1_NR,
+			.label	= "GPD1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE0(0),
+			.ngpio	= EXYNOS4_GPIO_E0_NR,
+			.label	= "GPE0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE1(0),
+			.ngpio	= EXYNOS4_GPIO_E1_NR,
+			.label	= "GPE1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE2(0),
+			.ngpio	= EXYNOS4_GPIO_E2_NR,
+			.label	= "GPE2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE3(0),
+			.ngpio	= EXYNOS4_GPIO_E3_NR,
+			.label	= "GPE3",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPE4(0),
+			.ngpio	= EXYNOS4_GPIO_E4_NR,
+			.label	= "GPE4",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF0(0),
+			.ngpio	= EXYNOS4_GPIO_F0_NR,
+			.label	= "GPF0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF1(0),
+			.ngpio	= EXYNOS4_GPIO_F1_NR,
+			.label	= "GPF1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF2(0),
+			.ngpio	= EXYNOS4_GPIO_F2_NR,
+			.label	= "GPF2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPF3(0),
+			.ngpio	= EXYNOS4_GPIO_F3_NR,
+			.label	= "GPF3",
+		},
+	},
+};
+
+static struct s3c_gpio_chip exynos4_gpio_part2_4bit[] = {
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPJ0(0),
+			.ngpio	= EXYNOS4_GPIO_J0_NR,
+			.label	= "GPJ0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPJ1(0),
+			.ngpio	= EXYNOS4_GPIO_J1_NR,
+			.label	= "GPJ1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK0(0),
+			.ngpio	= EXYNOS4_GPIO_K0_NR,
+			.label	= "GPK0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK1(0),
+			.ngpio	= EXYNOS4_GPIO_K1_NR,
+			.label	= "GPK1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK2(0),
+			.ngpio	= EXYNOS4_GPIO_K2_NR,
+			.label	= "GPK2",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPK3(0),
+			.ngpio	= EXYNOS4_GPIO_K3_NR,
+			.label	= "GPK3",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL0(0),
+			.ngpio	= EXYNOS4_GPIO_L0_NR,
+			.label	= "GPL0",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL1(0),
+			.ngpio	= EXYNOS4_GPIO_L1_NR,
+			.label	= "GPL1",
+		},
+	}, {
+		.chip	= {
+			.base	= EXYNOS4_GPL2(0),
+			.ngpio	= EXYNOS4_GPIO_L2_NR,
+			.label	= "GPL2",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY0(0),
+			.ngpio	= EXYNOS4_GPIO_Y0_NR,
+			.label	= "GPY0",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY1(0),
+			.ngpio	= EXYNOS4_GPIO_Y1_NR,
+			.label	= "GPY1",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY2(0),
+			.ngpio	= EXYNOS4_GPIO_Y2_NR,
+			.label	= "GPY2",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY3(0),
+			.ngpio	= EXYNOS4_GPIO_Y3_NR,
+			.label	= "GPY3",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY4(0),
+			.ngpio	= EXYNOS4_GPIO_Y4_NR,
+			.label	= "GPY4",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY5(0),
+			.ngpio	= EXYNOS4_GPIO_Y5_NR,
+			.label	= "GPY5",
+		},
+	}, {
+		.config	= &gpio_cfg_noint,
+		.chip	= {
+			.base	= EXYNOS4_GPY6(0),
+			.ngpio	= EXYNOS4_GPIO_Y6_NR,
+			.label	= "GPY6",
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC00),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(0),
+		.chip	= {
+			.base	= EXYNOS4_GPX0(0),
+			.ngpio	= EXYNOS4_GPIO_X0_NR,
+			.label	= "GPX0",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC20),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(8),
+		.chip	= {
+			.base	= EXYNOS4_GPX1(0),
+			.ngpio	= EXYNOS4_GPIO_X1_NR,
+			.label	= "GPX1",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC40),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(16),
+		.chip	= {
+			.base	= EXYNOS4_GPX2(0),
+			.ngpio	= EXYNOS4_GPIO_X2_NR,
+			.label	= "GPX2",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	}, {
+		.base	= (S5P_VA_GPIO2 + 0xC60),
+		.config	= &gpio_cfg_noint,
+		.irq_base = IRQ_EINT(24),
+		.chip	= {
+			.base	= EXYNOS4_GPX3(0),
+			.ngpio	= EXYNOS4_GPIO_X3_NR,
+			.label	= "GPX3",
+			.to_irq	= samsung_gpiolib_to_irq,
+		},
+	},
+};
+
+static struct s3c_gpio_chip exynos4_gpio_part3_4bit[] = {
+	{
+		.chip	= {
+			.base	= EXYNOS4_GPZ(0),
+			.ngpio	= EXYNOS4_GPIO_Z_NR,
+			.label	= "GPZ",
+		},
+	},
+};
+
+static __init int exynos4_gpiolib_init(void)
+{
+	struct s3c_gpio_chip *chip;
+	int i;
+	int group = 0;
+	int nr_chips;
+
+	/* GPIO part 1 */
+
+	chip = exynos4_gpio_part1_4bit;
+	nr_chips = ARRAY_SIZE(exynos4_gpio_part1_4bit);
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL) {
+			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
+		if (chip->base == NULL)
+			chip->base = S5P_VA_GPIO1 + (i) * 0x20;
+	}
+
+	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part1_4bit, nr_chips);
+
+	/* GPIO part 2 */
+
+	chip = exynos4_gpio_part2_4bit;
+	nr_chips = ARRAY_SIZE(exynos4_gpio_part2_4bit);
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL) {
+			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
+		if (chip->base == NULL)
+			chip->base = S5P_VA_GPIO2 + (i) * 0x20;
+	}
+
+	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part2_4bit, nr_chips);
+
+	/* GPIO part 3 */
+
+	chip = exynos4_gpio_part3_4bit;
+	nr_chips = ARRAY_SIZE(exynos4_gpio_part3_4bit);
+
+	for (i = 0; i < nr_chips; i++, chip++) {
+		if (chip->config == NULL) {
+			chip->config = &gpio_cfg;
+			/* Assign the GPIO interrupt group */
+			chip->group = group++;
+		}
+		if (chip->base == NULL)
+			chip->base = S5P_VA_GPIO3 + (i) * 0x20;
+	}
+
+	samsung_gpiolib_add_4bit_chips(exynos4_gpio_part3_4bit, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIO_XA, 0, IRQ_GPIO1_NR_GROUPS);
+	s5p_register_gpioint_bank(IRQ_GPIO_XB, IRQ_GPIO1_NR_GROUPS, IRQ_GPIO2_NR_GROUPS);
+
+	return 0;
+}
+core_initcall(exynos4_gpiolib_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/headsmp.S linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/headsmp.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ *  linux/arch/arm/mach-exynos4/headsmp.S
+ *
+ *  Cloned from linux/arch/arm/mach-realview/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  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/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * exynos4 specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(exynos4_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+1:	.long	.
+	.long	pen_release
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/hotplug.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/hotplug.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/hotplug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/hotplug.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,130 @@
+/* linux arch/arm/mach-exynos4/hotplug.c
+ *
+ *  Cloned from linux/arch/arm/mach-realview/hotplug.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/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+
+extern volatile int pen_release;
+
+static inline void cpu_enter_lowpower(void)
+{
+	unsigned int v;
+
+	flush_cache_all();
+	asm volatile(
+	"	mcr	p15, 0, %1, c7, c5, 0\n"
+	"	mcr	p15, 0, %1, c7, c10, 4\n"
+	/*
+	 * Turn off coherency
+	 */
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	bic	%0, %0, %3\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	"	mrc	p15, 0, %0, c1, c0, 0\n"
+	"	bic	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	  : "=&r" (v)
+	  : "r" (0), "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void cpu_leave_lowpower(void)
+{
+	unsigned int v;
+
+	asm volatile(
+	"mrc	p15, 0, %0, c1, c0, 0\n"
+	"	orr	%0, %0, %1\n"
+	"	mcr	p15, 0, %0, c1, c0, 0\n"
+	"	mrc	p15, 0, %0, c1, c0, 1\n"
+	"	orr	%0, %0, %2\n"
+	"	mcr	p15, 0, %0, c1, c0, 1\n"
+	  : "=&r" (v)
+	  : "Ir" (CR_C), "Ir" (0x40)
+	  : "cc");
+}
+
+static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
+{
+	/*
+	 * there is no power-control hardware on this platform, so all
+	 * we can do is put the core into WFI; this is safe as the calling
+	 * code will have already disabled interrupts
+	 */
+	for (;;) {
+		/*
+		 * here's the WFI
+		 */
+		asm(".word	0xe320f003\n"
+		    :
+		    :
+		    : "memory", "cc");
+
+		if (pen_release == cpu) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+
+		/*
+		 * Getting here, means that we have come out of WFI without
+		 * having been woken up - this shouldn't happen
+		 *
+		 * Just note it happening - when we're woken, we can report
+		 * its occurrence.
+		 */
+		(*spurious)++;
+	}
+}
+
+int platform_cpu_kill(unsigned int cpu)
+{
+	return 1;
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void platform_cpu_die(unsigned int cpu)
+{
+	int spurious = 0;
+
+	/*
+	 * we're ready for shutdown now, so do it
+	 */
+	cpu_enter_lowpower();
+	platform_do_lowpower(cpu, &spurious);
+
+	/*
+	 * bring this CPU back into the world of cache
+	 * coherency, and then restore interrupts
+	 */
+	cpu_leave_lowpower();
+
+	if (spurious)
+		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
+}
+
+int platform_cpu_disable(unsigned int cpu)
+{
+	/*
+	 * we don't allow CPU 0 to be shutdown (it is still too special
+	 * e.g. clock tick interrupts)
+	 */
+	return cpu == 0 ? -EPERM : 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,35 @@
+/* linux/arch/arm/mach-exynos4/include/mach/debug-macro.S
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
+ *
+ * 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.
+*/
+
+/* pull in the relevant register and map files. */
+
+#include <mach/map.h>
+
+	/* note, for the boot process to work we have to keep the UART
+	 * virtual address aligned to an 1MiB boundary for the L1
+	 * mapping the head code makes. We keep the UART virtual address
+	 * aligned and add in the offset when we load the value here.
+	 */
+
+	.macro addruart, rp, rv
+		ldr	\rp, = S3C_PA_UART
+		ldr	\rv, = S3C_VA_UART
+#if CONFIG_DEBUG_S3C_UART != 0
+		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
+#endif
+	.endm
+
+#define fifo_full fifo_full_s5pv210
+#define fifo_level fifo_level_s5pv210
+
+#include <plat/debug-macro.S>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/dma.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright (C) 2010 Samsung Electronics Co. Ltd.
+ *	Jaswinder Singh <jassi.brar@samsung.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 __MACH_DMA_H
+#define __MACH_DMA_H
+
+/* This platform uses the common S3C DMA API driver for PL330 */
+#include <plat/s3c-dma-pl330.h>
+
+#endif /* __MACH_DMA_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/entry-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,84 @@
+/* arch/arm/mach-exynos4/include/mach/entry-macro.S
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for EXYNOS4 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>
+#include <asm/hardware/gic.h>
+
+		.macro	disable_fiq
+		.endm
+
+		.macro  get_irqnr_preamble, base, tmp
+		ldr	\base, =gic_cpu_base_addr
+		ldr	\base, [\base]
+		.endm
+
+		.macro  arch_ret_to_user, tmp1, tmp2
+		.endm
+
+		/*
+		 * 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     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
+
+		ldr	\tmp, =1021
+
+		bic     \irqnr, \irqstat, #0x1c00
+
+		cmp     \irqnr, #29
+		cmpcc	\irqnr, \irqnr
+		cmpne	\irqnr, \tmp
+		cmpcs	\irqnr, \irqnr
+		addne	\irqnr, \irqnr, #32
+
+		.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
+		strcc	\irqstat, [\base, #GIC_CPU_EOI]
+		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
+		moveq	\tmp, #1
+		streq	\irqstat, [\base, #GIC_CPU_EOI]
+		cmp	\tmp, #0
+		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,156 @@
+/* linux/arch/arm/mach-exynos4/include/mach/gpio.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIO lib 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.
+*/
+
+#ifndef __ASM_ARCH_GPIO_H
+#define __ASM_ARCH_GPIO_H __FILE__
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
+
+/* Practically, GPIO banks up to GPZ are the configurable gpio banks */
+
+/* GPIO bank sizes */
+#define EXYNOS4_GPIO_A0_NR	(8)
+#define EXYNOS4_GPIO_A1_NR	(6)
+#define EXYNOS4_GPIO_B_NR	(8)
+#define EXYNOS4_GPIO_C0_NR	(5)
+#define EXYNOS4_GPIO_C1_NR	(5)
+#define EXYNOS4_GPIO_D0_NR	(4)
+#define EXYNOS4_GPIO_D1_NR	(4)
+#define EXYNOS4_GPIO_E0_NR	(5)
+#define EXYNOS4_GPIO_E1_NR	(8)
+#define EXYNOS4_GPIO_E2_NR	(6)
+#define EXYNOS4_GPIO_E3_NR	(8)
+#define EXYNOS4_GPIO_E4_NR	(8)
+#define EXYNOS4_GPIO_F0_NR	(8)
+#define EXYNOS4_GPIO_F1_NR	(8)
+#define EXYNOS4_GPIO_F2_NR	(8)
+#define EXYNOS4_GPIO_F3_NR	(6)
+#define EXYNOS4_GPIO_J0_NR	(8)
+#define EXYNOS4_GPIO_J1_NR	(5)
+#define EXYNOS4_GPIO_K0_NR	(7)
+#define EXYNOS4_GPIO_K1_NR	(7)
+#define EXYNOS4_GPIO_K2_NR	(7)
+#define EXYNOS4_GPIO_K3_NR	(7)
+#define EXYNOS4_GPIO_L0_NR	(8)
+#define EXYNOS4_GPIO_L1_NR	(3)
+#define EXYNOS4_GPIO_L2_NR	(8)
+#define EXYNOS4_GPIO_X0_NR	(8)
+#define EXYNOS4_GPIO_X1_NR	(8)
+#define EXYNOS4_GPIO_X2_NR	(8)
+#define EXYNOS4_GPIO_X3_NR	(8)
+#define EXYNOS4_GPIO_Y0_NR	(6)
+#define EXYNOS4_GPIO_Y1_NR	(4)
+#define EXYNOS4_GPIO_Y2_NR	(6)
+#define EXYNOS4_GPIO_Y3_NR	(8)
+#define EXYNOS4_GPIO_Y4_NR	(8)
+#define EXYNOS4_GPIO_Y5_NR	(8)
+#define EXYNOS4_GPIO_Y6_NR	(8)
+#define EXYNOS4_GPIO_Z_NR	(7)
+
+/* GPIO bank numbers */
+
+#define EXYNOS4_GPIO_NEXT(__gpio) \
+	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
+
+enum s5p_gpio_number {
+	EXYNOS4_GPIO_A0_START	= 0,
+	EXYNOS4_GPIO_A1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A0),
+	EXYNOS4_GPIO_B_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_A1),
+	EXYNOS4_GPIO_C0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_B),
+	EXYNOS4_GPIO_C1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C0),
+	EXYNOS4_GPIO_D0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_C1),
+	EXYNOS4_GPIO_D1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D0),
+	EXYNOS4_GPIO_E0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_D1),
+	EXYNOS4_GPIO_E1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E0),
+	EXYNOS4_GPIO_E2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E1),
+	EXYNOS4_GPIO_E3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E2),
+	EXYNOS4_GPIO_E4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E3),
+	EXYNOS4_GPIO_F0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_E4),
+	EXYNOS4_GPIO_F1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F0),
+	EXYNOS4_GPIO_F2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F1),
+	EXYNOS4_GPIO_F3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F2),
+	EXYNOS4_GPIO_J0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_F3),
+	EXYNOS4_GPIO_J1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J0),
+	EXYNOS4_GPIO_K0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_J1),
+	EXYNOS4_GPIO_K1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K0),
+	EXYNOS4_GPIO_K2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K1),
+	EXYNOS4_GPIO_K3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K2),
+	EXYNOS4_GPIO_L0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_K3),
+	EXYNOS4_GPIO_L1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L0),
+	EXYNOS4_GPIO_L2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L1),
+	EXYNOS4_GPIO_X0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_L2),
+	EXYNOS4_GPIO_X1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X0),
+	EXYNOS4_GPIO_X2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X1),
+	EXYNOS4_GPIO_X3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X2),
+	EXYNOS4_GPIO_Y0_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_X3),
+	EXYNOS4_GPIO_Y1_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y0),
+	EXYNOS4_GPIO_Y2_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y1),
+	EXYNOS4_GPIO_Y3_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y2),
+	EXYNOS4_GPIO_Y4_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y3),
+	EXYNOS4_GPIO_Y5_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y4),
+	EXYNOS4_GPIO_Y6_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y5),
+	EXYNOS4_GPIO_Z_START	= EXYNOS4_GPIO_NEXT(EXYNOS4_GPIO_Y6),
+};
+
+/* EXYNOS4 GPIO number definitions */
+#define EXYNOS4_GPA0(_nr)	(EXYNOS4_GPIO_A0_START + (_nr))
+#define EXYNOS4_GPA1(_nr)	(EXYNOS4_GPIO_A1_START + (_nr))
+#define EXYNOS4_GPB(_nr)	(EXYNOS4_GPIO_B_START + (_nr))
+#define EXYNOS4_GPC0(_nr)	(EXYNOS4_GPIO_C0_START + (_nr))
+#define EXYNOS4_GPC1(_nr)	(EXYNOS4_GPIO_C1_START + (_nr))
+#define EXYNOS4_GPD0(_nr)	(EXYNOS4_GPIO_D0_START + (_nr))
+#define EXYNOS4_GPD1(_nr)	(EXYNOS4_GPIO_D1_START + (_nr))
+#define EXYNOS4_GPE0(_nr)	(EXYNOS4_GPIO_E0_START + (_nr))
+#define EXYNOS4_GPE1(_nr)	(EXYNOS4_GPIO_E1_START + (_nr))
+#define EXYNOS4_GPE2(_nr)	(EXYNOS4_GPIO_E2_START + (_nr))
+#define EXYNOS4_GPE3(_nr)	(EXYNOS4_GPIO_E3_START + (_nr))
+#define EXYNOS4_GPE4(_nr)	(EXYNOS4_GPIO_E4_START + (_nr))
+#define EXYNOS4_GPF0(_nr)	(EXYNOS4_GPIO_F0_START + (_nr))
+#define EXYNOS4_GPF1(_nr)	(EXYNOS4_GPIO_F1_START + (_nr))
+#define EXYNOS4_GPF2(_nr)	(EXYNOS4_GPIO_F2_START + (_nr))
+#define EXYNOS4_GPF3(_nr)	(EXYNOS4_GPIO_F3_START + (_nr))
+#define EXYNOS4_GPJ0(_nr)	(EXYNOS4_GPIO_J0_START + (_nr))
+#define EXYNOS4_GPJ1(_nr)	(EXYNOS4_GPIO_J1_START + (_nr))
+#define EXYNOS4_GPK0(_nr)	(EXYNOS4_GPIO_K0_START + (_nr))
+#define EXYNOS4_GPK1(_nr)	(EXYNOS4_GPIO_K1_START + (_nr))
+#define EXYNOS4_GPK2(_nr)	(EXYNOS4_GPIO_K2_START + (_nr))
+#define EXYNOS4_GPK3(_nr)	(EXYNOS4_GPIO_K3_START + (_nr))
+#define EXYNOS4_GPL0(_nr)	(EXYNOS4_GPIO_L0_START + (_nr))
+#define EXYNOS4_GPL1(_nr)	(EXYNOS4_GPIO_L1_START + (_nr))
+#define EXYNOS4_GPL2(_nr)	(EXYNOS4_GPIO_L2_START + (_nr))
+#define EXYNOS4_GPX0(_nr)	(EXYNOS4_GPIO_X0_START + (_nr))
+#define EXYNOS4_GPX1(_nr)	(EXYNOS4_GPIO_X1_START + (_nr))
+#define EXYNOS4_GPX2(_nr)	(EXYNOS4_GPIO_X2_START + (_nr))
+#define EXYNOS4_GPX3(_nr)	(EXYNOS4_GPIO_X3_START + (_nr))
+#define EXYNOS4_GPY0(_nr)	(EXYNOS4_GPIO_Y0_START + (_nr))
+#define EXYNOS4_GPY1(_nr)	(EXYNOS4_GPIO_Y1_START + (_nr))
+#define EXYNOS4_GPY2(_nr)	(EXYNOS4_GPIO_Y2_START + (_nr))
+#define EXYNOS4_GPY3(_nr)	(EXYNOS4_GPIO_Y3_START + (_nr))
+#define EXYNOS4_GPY4(_nr)	(EXYNOS4_GPIO_Y4_START + (_nr))
+#define EXYNOS4_GPY5(_nr)	(EXYNOS4_GPIO_Y5_START + (_nr))
+#define EXYNOS4_GPY6(_nr)	(EXYNOS4_GPIO_Y6_START + (_nr))
+#define EXYNOS4_GPZ(_nr)	(EXYNOS4_GPIO_Z_START + (_nr))
+
+/* the end of the EXYNOS4 specific gpios */
+#define EXYNOS4_GPIO_END	(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) + 1)
+#define S3C_GPIO_END		EXYNOS4_GPIO_END
+
+/* define the number of gpios we need to the one after the GPZ() range */
+#define ARCH_NR_GPIOS		(EXYNOS4_GPZ(EXYNOS4_GPIO_Z_NR) +	\
+				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
+
+#include <asm-generic/gpio.h>
+
+#endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+/* linux/arch/arm/mach-exynos4/include/mach/hardware.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Hardware 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.
+*/
+
+#ifndef __ASM_ARCH_HARDWARE_H
+#define __ASM_ARCH_HARDWARE_H __FILE__
+
+/* currently nothing here, placeholder */
+
+#endif /* __ASM_ARCH_HARDWARE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-exynos4/include/mach/io.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/io.h
+ *
+ * Default IO routines for EXYNOS4
+ *
+ * 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_ARCH_IO_H
+#define __ASM_ARM_ARCH_IO_H __FILE__
+
+/* No current ISA/PCI bus support. */
+#define __io(a)		__typesafe_io(a)
+#define __mem_pci(a)	(a)
+
+#define IO_SPACE_LIMIT (0xFFFFFFFF)
+
+#endif /* __ASM_ARM_ARCH_IO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,160 @@
+/* linux/arch/arm/mach-exynos4/include/mach/irqs.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ 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.
+*/
+
+#ifndef __ASM_ARCH_IRQS_H
+#define __ASM_ARCH_IRQS_H __FILE__
+
+#include <plat/irqs.h>
+
+/* PPI: Private Peripheral Interrupt */
+
+#define IRQ_PPI(x)		S5P_IRQ(x+16)
+
+#define IRQ_LOCALTIMER		IRQ_PPI(13)
+
+/* SPI: Shared Peripheral Interrupt */
+
+#define IRQ_SPI(x)		S5P_IRQ(x+32)
+
+#define IRQ_MCT1		IRQ_SPI(35)
+
+#define IRQ_EINT0		IRQ_SPI(40)
+#define IRQ_EINT1		IRQ_SPI(41)
+#define IRQ_EINT2		IRQ_SPI(42)
+#define IRQ_EINT3		IRQ_SPI(43)
+#define IRQ_USB_HSOTG		IRQ_SPI(44)
+#define IRQ_USB_HOST		IRQ_SPI(45)
+#define IRQ_MODEM_IF		IRQ_SPI(46)
+#define IRQ_ROTATOR		IRQ_SPI(47)
+#define IRQ_JPEG		IRQ_SPI(48)
+#define IRQ_2D			IRQ_SPI(49)
+#define IRQ_PCIE		IRQ_SPI(50)
+#define IRQ_MCT0		IRQ_SPI(51)
+#define IRQ_MFC			IRQ_SPI(52)
+#define IRQ_AUDIO_SS		IRQ_SPI(54)
+#define IRQ_AC97		IRQ_SPI(55)
+#define IRQ_SPDIF		IRQ_SPI(56)
+#define IRQ_KEYPAD		IRQ_SPI(57)
+#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(58)
+#define IRQ_SLIMBUS		IRQ_SPI(59)
+#define IRQ_PMU			IRQ_SPI(60)
+#define IRQ_TSI			IRQ_SPI(61)
+#define IRQ_SATA		IRQ_SPI(62)
+#define IRQ_GPS			IRQ_SPI(63)
+
+#define MAX_IRQ_IN_COMBINER	8
+#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
+#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
+
+#define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
+#define IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
+#define IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
+#define IRQ_SYSMMU_FIMC1_0	COMBINER_IRQ(4, 3)
+#define IRQ_SYSMMU_FIMC2_0	COMBINER_IRQ(4, 4)
+#define IRQ_SYSMMU_FIMC3_0	COMBINER_IRQ(4, 5)
+#define IRQ_SYSMMU_JPEG_0	COMBINER_IRQ(4, 6)
+#define IRQ_SYSMMU_2D_0		COMBINER_IRQ(4, 7)
+
+#define IRQ_SYSMMU_ROTATOR_0	COMBINER_IRQ(5, 0)
+#define IRQ_SYSMMU_MDMA1_0	COMBINER_IRQ(5, 1)
+#define IRQ_SYSMMU_LCD0_M0_0	COMBINER_IRQ(5, 2)
+#define IRQ_SYSMMU_LCD1_M1_0	COMBINER_IRQ(5, 3)
+#define IRQ_SYSMMU_TV_M0_0	COMBINER_IRQ(5, 4)
+#define IRQ_SYSMMU_MFC_M0_0	COMBINER_IRQ(5, 5)
+#define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
+#define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
+
+#define IRQ_PDMA0		COMBINER_IRQ(21, 0)
+#define IRQ_PDMA1		COMBINER_IRQ(21, 1)
+
+#define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
+#define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
+#define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
+#define IRQ_TIMER3_VIC		COMBINER_IRQ(22, 3)
+#define IRQ_TIMER4_VIC		COMBINER_IRQ(22, 4)
+
+#define IRQ_RTC_ALARM		COMBINER_IRQ(23, 0)
+#define IRQ_RTC_TIC		COMBINER_IRQ(23, 1)
+
+#define IRQ_GPIO_XB		COMBINER_IRQ(24, 0)
+#define IRQ_GPIO_XA		COMBINER_IRQ(24, 1)
+
+#define IRQ_UART0		COMBINER_IRQ(26, 0)
+#define IRQ_UART1		COMBINER_IRQ(26, 1)
+#define IRQ_UART2		COMBINER_IRQ(26, 2)
+#define IRQ_UART3		COMBINER_IRQ(26, 3)
+#define IRQ_UART4		COMBINER_IRQ(26, 4)
+
+#define IRQ_IIC			COMBINER_IRQ(27, 0)
+#define IRQ_IIC1		COMBINER_IRQ(27, 1)
+#define IRQ_IIC2		COMBINER_IRQ(27, 2)
+#define IRQ_IIC3		COMBINER_IRQ(27, 3)
+#define IRQ_IIC4		COMBINER_IRQ(27, 4)
+#define IRQ_IIC5		COMBINER_IRQ(27, 5)
+#define IRQ_IIC6		COMBINER_IRQ(27, 6)
+#define IRQ_IIC7		COMBINER_IRQ(27, 7)
+
+#define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
+#define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
+#define IRQ_HSMMC2		COMBINER_IRQ(29, 2)
+#define IRQ_HSMMC3		COMBINER_IRQ(29, 3)
+
+#define IRQ_MIPI_CSIS0		COMBINER_IRQ(30, 0)
+#define IRQ_MIPI_CSIS1		COMBINER_IRQ(30, 1)
+
+#define IRQ_FIMC0		COMBINER_IRQ(32, 0)
+#define IRQ_FIMC1		COMBINER_IRQ(32, 1)
+#define IRQ_FIMC2		COMBINER_IRQ(33, 0)
+#define IRQ_FIMC3		COMBINER_IRQ(33, 1)
+
+#define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
+
+#define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
+
+#define IRQ_EINT4		COMBINER_IRQ(37, 0)
+#define IRQ_EINT5		COMBINER_IRQ(37, 1)
+#define IRQ_EINT6		COMBINER_IRQ(37, 2)
+#define IRQ_EINT7		COMBINER_IRQ(37, 3)
+#define IRQ_EINT8		COMBINER_IRQ(38, 0)
+
+#define IRQ_EINT9		COMBINER_IRQ(38, 1)
+#define IRQ_EINT10		COMBINER_IRQ(38, 2)
+#define IRQ_EINT11		COMBINER_IRQ(38, 3)
+#define IRQ_EINT12		COMBINER_IRQ(38, 4)
+#define IRQ_EINT13		COMBINER_IRQ(38, 5)
+#define IRQ_EINT14		COMBINER_IRQ(38, 6)
+#define IRQ_EINT15		COMBINER_IRQ(38, 7)
+
+#define IRQ_EINT16_31		COMBINER_IRQ(39, 0)
+
+#define IRQ_MCT_L0		COMBINER_IRQ(51, 0)
+
+#define IRQ_WDT			COMBINER_IRQ(53, 0)
+#define IRQ_MCT_G0		COMBINER_IRQ(53, 4)
+
+#define MAX_COMBINER_NR		54
+
+#define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
+
+#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
+#define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
+
+/* optional GPIO interrupts */
+#define S5P_GPIOINT_BASE	(S5P_IRQ_EINT_BASE + 32)
+#define IRQ_GPIO1_NR_GROUPS	16
+#define IRQ_GPIO2_NR_GROUPS	9
+#define IRQ_GPIO_END		(S5P_GPIOINT_BASE + S5P_GPIOINT_COUNT)
+
+/* Set the default NR_IRQS */
+#define NR_IRQS			(IRQ_GPIO_END)
+
+#endif /* __ASM_ARCH_IRQS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/map.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/map.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/map.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,162 @@
+/* linux/arch/arm/mach-exynos4/include/mach/map.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * EXYNOS4 - Memory map 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.
+*/
+
+#ifndef __ASM_ARCH_MAP_H
+#define __ASM_ARCH_MAP_H __FILE__
+
+#include <plat/map-base.h>
+
+/*
+ * EXYNOS4 UART offset is 0x10000 but the older S5P SoCs are 0x400.
+ * So need to define it, and here is to avoid redefinition warning.
+ */
+#define S3C_UART_OFFSET			(0x10000)
+
+#include <plat/map-s5p.h>
+
+#define EXYNOS4_PA_SYSRAM		0x02020000
+
+#define EXYNOS4_PA_FIMC0		0x11800000
+#define EXYNOS4_PA_FIMC1		0x11810000
+#define EXYNOS4_PA_FIMC2		0x11820000
+#define EXYNOS4_PA_FIMC3		0x11830000
+
+#define EXYNOS4_PA_I2S0			0x03830000
+#define EXYNOS4_PA_I2S1			0xE3100000
+#define EXYNOS4_PA_I2S2			0xE2A00000
+
+#define EXYNOS4_PA_PCM0			0x03840000
+#define EXYNOS4_PA_PCM1			0x13980000
+#define EXYNOS4_PA_PCM2			0x13990000
+
+#define EXYNOS4_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
+
+#define EXYNOS4_PA_ONENAND		0x0C000000
+#define EXYNOS4_PA_ONENAND_DMA		0x0C600000
+
+#define EXYNOS4_PA_CHIPID		0x10000000
+
+#define EXYNOS4_PA_SYSCON		0x10010000
+#define EXYNOS4_PA_PMU			0x10020000
+#define EXYNOS4_PA_CMU			0x10030000
+
+#define EXYNOS4_PA_SYSTIMER		0x10050000
+#define EXYNOS4_PA_WATCHDOG		0x10060000
+#define EXYNOS4_PA_RTC			0x10070000
+
+#define EXYNOS4_PA_KEYPAD		0x100A0000
+
+#define EXYNOS4_PA_DMC0			0x10400000
+
+#define EXYNOS4_PA_COMBINER		0x10448000
+
+#define EXYNOS4_PA_COREPERI		0x10500000
+#define EXYNOS4_PA_GIC_CPU		0x10500100
+#define EXYNOS4_PA_TWD			0x10500600
+#define EXYNOS4_PA_GIC_DIST		0x10501000
+#define EXYNOS4_PA_L2CC			0x10502000
+
+#define EXYNOS4_PA_MDMA			0x10810000
+#define EXYNOS4_PA_PDMA0		0x12680000
+#define EXYNOS4_PA_PDMA1		0x12690000
+
+#define EXYNOS4_PA_SYSMMU_MDMA		0x10A40000
+#define EXYNOS4_PA_SYSMMU_SSS		0x10A50000
+#define EXYNOS4_PA_SYSMMU_FIMC0		0x11A20000
+#define EXYNOS4_PA_SYSMMU_FIMC1		0x11A30000
+#define EXYNOS4_PA_SYSMMU_FIMC2		0x11A40000
+#define EXYNOS4_PA_SYSMMU_FIMC3		0x11A50000
+#define EXYNOS4_PA_SYSMMU_JPEG		0x11A60000
+#define EXYNOS4_PA_SYSMMU_FIMD0		0x11E20000
+#define EXYNOS4_PA_SYSMMU_FIMD1		0x12220000
+#define EXYNOS4_PA_SYSMMU_PCIe		0x12620000
+#define EXYNOS4_PA_SYSMMU_G2D		0x12A20000
+#define EXYNOS4_PA_SYSMMU_ROTATOR	0x12A30000
+#define EXYNOS4_PA_SYSMMU_MDMA2		0x12A40000
+#define EXYNOS4_PA_SYSMMU_TV		0x12E20000
+#define EXYNOS4_PA_SYSMMU_MFC_L		0x13620000
+#define EXYNOS4_PA_SYSMMU_MFC_R		0x13630000
+
+#define EXYNOS4_PA_GPIO1		0x11400000
+#define EXYNOS4_PA_GPIO2		0x11000000
+#define EXYNOS4_PA_GPIO3		0x03860000
+
+#define EXYNOS4_PA_MIPI_CSIS0		0x11880000
+#define EXYNOS4_PA_MIPI_CSIS1		0x11890000
+
+#define EXYNOS4_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
+
+#define EXYNOS4_PA_SATA			0x12560000
+#define EXYNOS4_PA_SATAPHY		0x125D0000
+#define EXYNOS4_PA_SATAPHY_CTRL		0x126B0000
+
+#define EXYNOS4_PA_SROMC		0x12570000
+
+#define EXYNOS4_PA_UART			0x13800000
+
+#define EXYNOS4_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
+
+#define EXYNOS4_PA_AC97			0x139A0000
+
+#define EXYNOS4_PA_SPDIF		0x139B0000
+
+#define EXYNOS4_PA_TIMER		0x139D0000
+
+#define EXYNOS4_PA_SDRAM		0x40000000
+
+/* Compatibiltiy Defines */
+
+#define S3C_PA_HSMMC0			EXYNOS4_PA_HSMMC(0)
+#define S3C_PA_HSMMC1			EXYNOS4_PA_HSMMC(1)
+#define S3C_PA_HSMMC2			EXYNOS4_PA_HSMMC(2)
+#define S3C_PA_HSMMC3			EXYNOS4_PA_HSMMC(3)
+#define S3C_PA_IIC			EXYNOS4_PA_IIC(0)
+#define S3C_PA_IIC1			EXYNOS4_PA_IIC(1)
+#define S3C_PA_IIC2			EXYNOS4_PA_IIC(2)
+#define S3C_PA_IIC3			EXYNOS4_PA_IIC(3)
+#define S3C_PA_IIC4			EXYNOS4_PA_IIC(4)
+#define S3C_PA_IIC5			EXYNOS4_PA_IIC(5)
+#define S3C_PA_IIC6			EXYNOS4_PA_IIC(6)
+#define S3C_PA_IIC7			EXYNOS4_PA_IIC(7)
+#define S3C_PA_RTC			EXYNOS4_PA_RTC
+#define S3C_PA_WDT			EXYNOS4_PA_WATCHDOG
+
+#define S5P_PA_CHIPID			EXYNOS4_PA_CHIPID
+#define S5P_PA_FIMC0			EXYNOS4_PA_FIMC0
+#define S5P_PA_FIMC1			EXYNOS4_PA_FIMC1
+#define S5P_PA_FIMC2			EXYNOS4_PA_FIMC2
+#define S5P_PA_FIMC3			EXYNOS4_PA_FIMC3
+#define S5P_PA_MIPI_CSIS0		EXYNOS4_PA_MIPI_CSIS0
+#define S5P_PA_MIPI_CSIS1		EXYNOS4_PA_MIPI_CSIS1
+#define S5P_PA_ONENAND			EXYNOS4_PA_ONENAND
+#define S5P_PA_ONENAND_DMA		EXYNOS4_PA_ONENAND_DMA
+#define S5P_PA_SDRAM			EXYNOS4_PA_SDRAM
+#define S5P_PA_SROMC			EXYNOS4_PA_SROMC
+#define S5P_PA_SYSCON			EXYNOS4_PA_SYSCON
+#define S5P_PA_TIMER			EXYNOS4_PA_TIMER
+
+#define SAMSUNG_PA_KEYPAD		EXYNOS4_PA_KEYPAD
+
+/* UART */
+
+#define S3C_PA_UART			EXYNOS4_PA_UART
+
+#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
+#define S5P_PA_UART0			S5P_PA_UART(0)
+#define S5P_PA_UART1			S5P_PA_UART(1)
+#define S5P_PA_UART2			S5P_PA_UART(2)
+#define S5P_PA_UART3			S5P_PA_UART(3)
+#define S5P_PA_UART4			S5P_PA_UART(4)
+
+#define S5P_SZ_UART			SZ_256
+
+#endif /* __ASM_ARCH_MAP_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/memory.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Memory 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.
+*/
+
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H __FILE__
+
+#define PLAT_PHYS_OFFSET		UL(0x40000000)
+
+/* Maximum of 256MiB in one bank */
+#define MAX_PHYSMEM_BITS	32
+#define SECTION_SIZE_BITS	28
+
+#endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/pm-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pm-core.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/mach-s3c2410/include/mach/pm-core.h,
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * EXYNOS4210 - PM core support for arch/arm/plat-s5p/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 <mach/regs-pmu.h>
+
+static inline void s3c_pm_debug_init_uart(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_prepare_irqs(void)
+{
+	unsigned int tmp;
+	tmp = __raw_readl(S5P_WAKEUP_MASK);
+	tmp &= ~(1 << 31);
+	__raw_writel(tmp, S5P_WAKEUP_MASK);
+
+	__raw_writel(s3c_irqwake_intmask, S5P_WAKEUP_MASK);
+	__raw_writel(s3c_irqwake_eintmask, S5P_EINT_WAKEUP_MASK);
+}
+
+static inline void s3c_pm_arch_stop_clocks(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_show_resume_irqs(void)
+{
+	/* nothing here yet */
+}
+
+static inline void s3c_pm_arch_update_uart(void __iomem *regs,
+					   struct pm_uart_save *save)
+{
+	/* nothing here yet */
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/pwm-clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,70 @@
+/* linux/arch/arm/mach-exynos4/include/mach/pwm-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2008 Openmoko, Inc.
+ * Copyright 2008 Simtec Electronics
+ *      Ben Dooks <ben@simtec.co.uk>
+ *      http://armlinux.simtec.co.uk/
+ *
+ * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
+ *
+ * EXYNOS4 - pwm clock and timer 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.
+*/
+
+#ifndef __ASM_ARCH_PWMCLK_H
+#define __ASM_ARCH_PWMCLK_H __FILE__
+
+/**
+ * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
+ * @tcfg: The timer TCFG1 register bits shifted down to 0.
+ *
+ * Return true if the given configuration from TCFG1 is a TCLK instead
+ * any of the TDIV clocks.
+ */
+static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
+{
+	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
+}
+
+/**
+ * tcfg_to_divisor() - convert tcfg1 setting to a divisor
+ * @tcfg1: The tcfg1 setting, shifted down.
+ *
+ * Get the divisor value for the given tcfg1 setting. We assume the
+ * caller has already checked to see if this is not a TCLK source.
+ */
+static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
+{
+	return 1 << tcfg1;
+}
+
+/**
+ * pwm_tdiv_has_div1() - does the tdiv setting have a /1
+ *
+ * Return true if we have a /1 in the tdiv setting.
+ */
+static inline unsigned int pwm_tdiv_has_div1(void)
+{
+	return 1;
+}
+
+/**
+ * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
+ * @div: The divisor to calculate the bit information for.
+ *
+ * Turn a divisor into the necessary bit field for TCFG1.
+ */
+static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
+{
+	return ilog2(div);
+}
+
+#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
+
+#endif /* __ASM_ARCH_PWMCLK_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,180 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-clock.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Clock 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_CLOCK_H
+#define __ASM_ARCH_REGS_CLOCK_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
+
+#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
+#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
+#define S5P_CLKGATE_IP_LEFTBUS		S5P_CLKREG(0x04800)
+
+#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
+#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
+#define S5P_CLKGATE_IP_RIGHTBUS		S5P_CLKREG(0x08800)
+
+#define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
+#define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
+#define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
+#define S5P_VPLL_CON1			S5P_CLKREG(0x0C124)
+
+#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
+#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
+#define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
+#define S5P_CLKSRC_MFC			S5P_CLKREG(0x0C228)
+#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
+#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
+#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
+#define S5P_CLKSRC_MAUDIO		S5P_CLKREG(0x0C23C)
+#define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
+#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
+#define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
+
+#define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
+#define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
+#define S5P_CLKDIV_TV			S5P_CLKREG(0x0C524)
+#define S5P_CLKDIV_MFC			S5P_CLKREG(0x0C528)
+#define S5P_CLKDIV_G3D			S5P_CLKREG(0x0C52C)
+#define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
+#define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
+#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
+#define S5P_CLKDIV_MAUDIO		S5P_CLKREG(0x0C53C)
+#define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
+#define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
+#define S5P_CLKDIV_FSYS2		S5P_CLKREG(0x0C548)
+#define S5P_CLKDIV_FSYS3		S5P_CLKREG(0x0C54C)
+#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x0C550)
+#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x0C554)
+#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x0C558)
+#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
+#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
+#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
+
+#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
+#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
+#define S5P_CLKSRC_MASK_TV		S5P_CLKREG(0x0C324)
+#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
+#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
+#define S5P_CLKSRC_MASK_MAUDIO		S5P_CLKREG(0x0C33C)
+#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
+#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
+#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
+
+#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
+
+#define S5P_CLKGATE_SCLKCAM		S5P_CLKREG(0x0C820)
+#define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
+#define S5P_CLKGATE_IP_TV		S5P_CLKREG(0x0C924)
+#define S5P_CLKGATE_IP_MFC		S5P_CLKREG(0x0C928)
+#define S5P_CLKGATE_IP_G3D		S5P_CLKREG(0x0C92C)
+#define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
+#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
+#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
+#define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
+#define S5P_CLKGATE_IP_GPS		S5P_CLKREG(0x0C94C)
+#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
+#define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
+#define S5P_CLKGATE_BLOCK		S5P_CLKREG(0x0C970)
+
+#define S5P_CLKSRC_MASK_DMC		S5P_CLKREG(0x10300)
+#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
+#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
+#define S5P_CLKDIV_DMC1			S5P_CLKREG(0x10504)
+#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
+#define S5P_CLKGATE_IP_DMC		S5P_CLKREG(0x10900)
+
+#define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
+#define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
+#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
+#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
+#define S5P_MPLL_CON0			S5P_CLKREG(0x14108)
+#define S5P_MPLL_CON1			S5P_CLKREG(0x1410C)
+
+#define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
+#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
+
+#define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
+#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
+#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
+#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
+
+#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
+#define S5P_CLKGATE_IP_CPU		S5P_CLKREG(0x14900)
+
+#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
+
+#define S5P_APLLCON0_ENABLE_SHIFT	(31)
+#define S5P_APLLCON0_LOCKED_SHIFT	(29)
+#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
+#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
+
+#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
+#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
+
+#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
+#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
+#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
+#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
+#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
+#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
+#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
+#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
+#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
+#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
+#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
+#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
+#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
+
+#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
+#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
+#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
+#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
+#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
+#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
+#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
+#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
+#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
+#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
+#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
+#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
+#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
+#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
+#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
+
+#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
+#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
+#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
+#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
+#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
+#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
+#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
+#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
+
+#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
+#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
+#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
+#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
+
+/* Compatibility defines and inclusion */
+
+#include <mach/regs-pmu.h>
+
+#define S5P_EPLL_CON			S5P_EPLL_CON0
+
+#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,42 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-gpio.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - GPIO (including EINT) 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_GPIO_H
+#define __ASM_ARCH_REGS_GPIO_H __FILE__
+
+#include <mach/map.h>
+#include <mach/irqs.h>
+
+#define EXYNOS4_EINT40CON		(S5P_VA_GPIO2 + 0xE00)
+#define S5P_EINT_CON(x)			(EXYNOS4_EINT40CON + ((x) * 0x4))
+
+#define EXYNOS4_EINT40FLTCON0		(S5P_VA_GPIO2 + 0xE80)
+#define S5P_EINT_FLTCON(x)		(EXYNOS4_EINT40FLTCON0 + ((x) * 0x4))
+
+#define EXYNOS4_EINT40MASK		(S5P_VA_GPIO2 + 0xF00)
+#define S5P_EINT_MASK(x)		(EXYNOS4_EINT40MASK + ((x) * 0x4))
+
+#define EXYNOS4_EINT40PEND		(S5P_VA_GPIO2 + 0xF40)
+#define S5P_EINT_PEND(x)		(EXYNOS4_EINT40PEND + ((x) * 0x4))
+
+#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
+
+#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
+
+#define EINT_MODE			S3C_GPIO_SFN(0xf)
+
+#define EINT_GPIO_0(x)			EXYNOS4_GPX0(x)
+#define EINT_GPIO_1(x)			EXYNOS4_GPX1(x)
+#define EINT_GPIO_2(x)			EXYNOS4_GPX2(x)
+#define EINT_GPIO_3(x)			EXYNOS4_GPX3(x)
+
+#endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-irq.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_IRQ_H
+#define __ASM_ARCH_REGS_IRQ_H __FILE__
+
+#include <asm/hardware/gic.h>
+#include <mach/map.h>
+
+#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-mct.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,52 @@
+/* arch/arm/mach-exynos4/include/mach/regs-mct.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 MCT configutation
+ *
+ * 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_REGS_MCT_H
+#define __ASM_ARCH_REGS_MCT_H __FILE__
+
+#include <mach/map.h>
+
+#define EXYNOS4_MCTREG(x)		(S5P_VA_SYSTIMER + (x))
+
+#define EXYNOS4_MCT_G_CNT_L		EXYNOS4_MCTREG(0x100)
+#define EXYNOS4_MCT_G_CNT_U		EXYNOS4_MCTREG(0x104)
+#define EXYNOS4_MCT_G_CNT_WSTAT		EXYNOS4_MCTREG(0x110)
+
+#define EXYNOS4_MCT_G_COMP0_L		EXYNOS4_MCTREG(0x200)
+#define EXYNOS4_MCT_G_COMP0_U		EXYNOS4_MCTREG(0x204)
+#define EXYNOS4_MCT_G_COMP0_ADD_INCR	EXYNOS4_MCTREG(0x208)
+
+#define EXYNOS4_MCT_G_TCON		EXYNOS4_MCTREG(0x240)
+
+#define EXYNOS4_MCT_G_INT_CSTAT		EXYNOS4_MCTREG(0x244)
+#define EXYNOS4_MCT_G_INT_ENB		EXYNOS4_MCTREG(0x248)
+#define EXYNOS4_MCT_G_WSTAT		EXYNOS4_MCTREG(0x24C)
+
+#define EXYNOS4_MCT_L0_BASE		EXYNOS4_MCTREG(0x300)
+#define EXYNOS4_MCT_L1_BASE		EXYNOS4_MCTREG(0x400)
+
+#define MCT_L_TCNTB_OFFSET		(0x00)
+#define MCT_L_ICNTB_OFFSET		(0x08)
+#define MCT_L_TCON_OFFSET		(0x20)
+#define MCT_L_INT_CSTAT_OFFSET		(0x30)
+#define MCT_L_INT_ENB_OFFSET		(0x34)
+#define MCT_L_WSTAT_OFFSET		(0x40)
+
+#define MCT_G_TCON_START		(1 << 8)
+#define MCT_G_TCON_COMP0_AUTO_INC	(1 << 1)
+#define MCT_G_TCON_COMP0_ENABLE		(1 << 0)
+
+#define MCT_L_TCON_INTERVAL_MODE	(1 << 2)
+#define MCT_L_TCON_INT_START		(1 << 1)
+#define MCT_L_TCON_TIMER_START		(1 << 0)
+
+#endif /* __ASM_ARCH_REGS_MCT_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-mem.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-mem.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - SROMC and DMC 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.
+*/
+
+#ifndef __ASM_ARCH_REGS_MEM_H
+#define __ASM_ARCH_REGS_MEM_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_DMC0_MEMCON_OFFSET		0x04
+
+#define S5P_DMC0_MEMTYPE_SHIFT		8
+#define S5P_DMC0_MEMTYPE_MASK		0xF
+
+#endif /* __ASM_ARCH_REGS_MEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-pmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,162 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-pmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - Power management unit definition
+ *
+ * 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_REGS_PMU_H
+#define __ASM_ARCH_REGS_PMU_H __FILE__
+
+#include <mach/map.h>
+
+#define S5P_PMUREG(x)				(S5P_VA_PMU + (x))
+
+#define S5P_CENTRAL_SEQ_CONFIGURATION		S5P_PMUREG(0x0200)
+
+#define S5P_CENTRAL_LOWPWR_CFG			(1 << 16)
+
+#define S5P_CENTRAL_SEQ_OPTION			S5P_PMUREG(0x0208)
+
+#define S5P_USE_STANDBY_WFI0			(1 << 16)
+#define S5P_USE_STANDBY_WFI1			(1 << 17)
+#define S5P_USE_STANDBY_WFE0			(1 << 24)
+#define S5P_USE_STANDBY_WFE1			(1 << 25)
+#define S5P_USE_MASK				((0x3 << 16) | (0x3 << 24))
+
+#define S5P_WAKEUP_STAT				S5P_PMUREG(0x0600)
+#define S5P_EINT_WAKEUP_MASK			S5P_PMUREG(0x0604)
+#define S5P_WAKEUP_MASK				S5P_PMUREG(0x0608)
+
+#define S5P_MIPI_DPHY_CONTROL(n)		S5P_PMUREG(0x0710 + (n) * 4)
+#define S5P_MIPI_DPHY_ENABLE			(1 << 0)
+#define S5P_MIPI_DPHY_SRESETN			(1 << 1)
+#define S5P_MIPI_DPHY_MRESETN			(1 << 2)
+
+#define S5P_PMU_SATA_PHY_CONTROL		S5P_PMUREG(0x0720)
+#define S5P_INFORM0				S5P_PMUREG(0x0800)
+#define S5P_INFORM1				S5P_PMUREG(0x0804)
+#define S5P_INFORM2				S5P_PMUREG(0x0808)
+#define S5P_INFORM3				S5P_PMUREG(0x080C)
+#define S5P_INFORM4				S5P_PMUREG(0x0810)
+#define S5P_INFORM5				S5P_PMUREG(0x0814)
+#define S5P_INFORM6				S5P_PMUREG(0x0818)
+#define S5P_INFORM7				S5P_PMUREG(0x081C)
+
+#define S5P_ARM_CORE0_LOWPWR			S5P_PMUREG(0x1000)
+#define S5P_DIS_IRQ_CORE0			S5P_PMUREG(0x1004)
+#define S5P_DIS_IRQ_CENTRAL0			S5P_PMUREG(0x1008)
+#define S5P_ARM_CORE1_LOWPWR			S5P_PMUREG(0x1010)
+#define S5P_DIS_IRQ_CORE1			S5P_PMUREG(0x1014)
+#define S5P_DIS_IRQ_CENTRAL1			S5P_PMUREG(0x1018)
+#define S5P_ARM_COMMON_LOWPWR			S5P_PMUREG(0x1080)
+#define S5P_L2_0_LOWPWR				S5P_PMUREG(0x10C0)
+#define S5P_L2_1_LOWPWR				S5P_PMUREG(0x10C4)
+#define S5P_CMU_ACLKSTOP_LOWPWR			S5P_PMUREG(0x1100)
+#define S5P_CMU_SCLKSTOP_LOWPWR			S5P_PMUREG(0x1104)
+#define S5P_CMU_RESET_LOWPWR			S5P_PMUREG(0x110C)
+#define S5P_APLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1120)
+#define S5P_MPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1124)
+#define S5P_VPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x1128)
+#define S5P_EPLL_SYSCLK_LOWPWR			S5P_PMUREG(0x112C)
+#define S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	S5P_PMUREG(0x1138)
+#define S5P_CMU_RESET_GPSALIVE_LOWPWR		S5P_PMUREG(0x113C)
+#define S5P_CMU_CLKSTOP_CAM_LOWPWR		S5P_PMUREG(0x1140)
+#define S5P_CMU_CLKSTOP_TV_LOWPWR		S5P_PMUREG(0x1144)
+#define S5P_CMU_CLKSTOP_MFC_LOWPWR		S5P_PMUREG(0x1148)
+#define S5P_CMU_CLKSTOP_G3D_LOWPWR		S5P_PMUREG(0x114C)
+#define S5P_CMU_CLKSTOP_LCD0_LOWPWR		S5P_PMUREG(0x1150)
+#define S5P_CMU_CLKSTOP_LCD1_LOWPWR		S5P_PMUREG(0x1154)
+#define S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		S5P_PMUREG(0x1158)
+#define S5P_CMU_CLKSTOP_GPS_LOWPWR		S5P_PMUREG(0x115C)
+#define S5P_CMU_RESET_CAM_LOWPWR		S5P_PMUREG(0x1160)
+#define S5P_CMU_RESET_TV_LOWPWR			S5P_PMUREG(0x1164)
+#define S5P_CMU_RESET_MFC_LOWPWR		S5P_PMUREG(0x1168)
+#define S5P_CMU_RESET_G3D_LOWPWR		S5P_PMUREG(0x116C)
+#define S5P_CMU_RESET_LCD0_LOWPWR		S5P_PMUREG(0x1170)
+#define S5P_CMU_RESET_LCD1_LOWPWR		S5P_PMUREG(0x1174)
+#define S5P_CMU_RESET_MAUDIO_LOWPWR		S5P_PMUREG(0x1178)
+#define S5P_CMU_RESET_GPS_LOWPWR		S5P_PMUREG(0x117C)
+#define S5P_TOP_BUS_LOWPWR			S5P_PMUREG(0x1180)
+#define S5P_TOP_RETENTION_LOWPWR		S5P_PMUREG(0x1184)
+#define S5P_TOP_PWR_LOWPWR			S5P_PMUREG(0x1188)
+#define S5P_LOGIC_RESET_LOWPWR			S5P_PMUREG(0x11A0)
+#define S5P_ONENAND_MEM_LOWPWR			S5P_PMUREG(0x11C0)
+#define S5P_MODIMIF_MEM_LOWPWR			S5P_PMUREG(0x11C4)
+#define S5P_G2D_ACP_MEM_LOWPWR			S5P_PMUREG(0x11C8)
+#define S5P_USBOTG_MEM_LOWPWR			S5P_PMUREG(0x11CC)
+#define S5P_HSMMC_MEM_LOWPWR			S5P_PMUREG(0x11D0)
+#define S5P_CSSYS_MEM_LOWPWR			S5P_PMUREG(0x11D4)
+#define S5P_SECSS_MEM_LOWPWR			S5P_PMUREG(0x11D8)
+#define S5P_PCIE_MEM_LOWPWR			S5P_PMUREG(0x11E0)
+#define S5P_SATA_MEM_LOWPWR			S5P_PMUREG(0x11E4)
+#define S5P_PAD_RETENTION_DRAM_LOWPWR		S5P_PMUREG(0x1200)
+#define S5P_PAD_RETENTION_MAUDIO_LOWPWR		S5P_PMUREG(0x1204)
+#define S5P_PAD_RETENTION_GPIO_LOWPWR		S5P_PMUREG(0x1220)
+#define S5P_PAD_RETENTION_UART_LOWPWR		S5P_PMUREG(0x1224)
+#define S5P_PAD_RETENTION_MMCA_LOWPWR		S5P_PMUREG(0x1228)
+#define S5P_PAD_RETENTION_MMCB_LOWPWR		S5P_PMUREG(0x122C)
+#define S5P_PAD_RETENTION_EBIA_LOWPWR		S5P_PMUREG(0x1230)
+#define S5P_PAD_RETENTION_EBIB_LOWPWR		S5P_PMUREG(0x1234)
+#define S5P_PAD_RETENTION_ISOLATION_LOWPWR	S5P_PMUREG(0x1240)
+#define S5P_PAD_RETENTION_ALV_SEL_LOWPWR	S5P_PMUREG(0x1260)
+#define S5P_XUSBXTI_LOWPWR			S5P_PMUREG(0x1280)
+#define S5P_XXTI_LOWPWR				S5P_PMUREG(0x1284)
+#define S5P_EXT_REGULATOR_LOWPWR		S5P_PMUREG(0x12C0)
+#define S5P_GPIO_MODE_LOWPWR			S5P_PMUREG(0x1300)
+#define S5P_GPIO_MODE_MAUDIO_LOWPWR		S5P_PMUREG(0x1340)
+#define S5P_CAM_LOWPWR				S5P_PMUREG(0x1380)
+#define S5P_TV_LOWPWR				S5P_PMUREG(0x1384)
+#define S5P_MFC_LOWPWR				S5P_PMUREG(0x1388)
+#define S5P_G3D_LOWPWR				S5P_PMUREG(0x138C)
+#define S5P_LCD0_LOWPWR				S5P_PMUREG(0x1390)
+#define S5P_LCD1_LOWPWR				S5P_PMUREG(0x1394)
+#define S5P_MAUDIO_LOWPWR			S5P_PMUREG(0x1398)
+#define S5P_GPS_LOWPWR				S5P_PMUREG(0x139C)
+#define S5P_GPS_ALIVE_LOWPWR			S5P_PMUREG(0x13A0)
+
+#define S5P_ARM_CORE0_CONFIGURATION		S5P_PMUREG(0x2000)
+#define S5P_ARM_CORE0_OPTION			S5P_PMUREG(0x2008)
+#define S5P_ARM_CORE1_CONFIGURATION		S5P_PMUREG(0x2080)
+#define S5P_ARM_CORE1_STATUS			S5P_PMUREG(0x2084)
+#define S5P_ARM_CORE1_OPTION			S5P_PMUREG(0x2088)
+
+#define S5P_ARM_COMMON_OPTION			S5P_PMUREG(0x2408)
+#define S5P_TOP_PWR_OPTION			S5P_PMUREG(0x2C48)
+#define S5P_CAM_OPTION				S5P_PMUREG(0x3C08)
+#define S5P_TV_OPTION				S5P_PMUREG(0x3C28)
+#define S5P_MFC_OPTION				S5P_PMUREG(0x3C48)
+#define S5P_G3D_OPTION				S5P_PMUREG(0x3C68)
+#define S5P_LCD0_OPTION				S5P_PMUREG(0x3C88)
+#define S5P_LCD1_OPTION				S5P_PMUREG(0x3CA8)
+#define S5P_MAUDIO_OPTION			S5P_PMUREG(0x3CC8)
+#define S5P_GPS_OPTION				S5P_PMUREG(0x3CE8)
+#define S5P_GPS_ALIVE_OPTION			S5P_PMUREG(0x3D08)
+
+#define S5P_PAD_RET_MAUDIO_OPTION		S5P_PMUREG(0x3028)
+#define S5P_PAD_RET_GPIO_OPTION			S5P_PMUREG(0x3108)
+#define S5P_PAD_RET_UART_OPTION			S5P_PMUREG(0x3128)
+#define S5P_PAD_RET_MMCA_OPTION			S5P_PMUREG(0x3148)
+#define S5P_PAD_RET_MMCB_OPTION			S5P_PMUREG(0x3168)
+#define S5P_PAD_RET_EBIA_OPTION			S5P_PMUREG(0x3188)
+#define S5P_PAD_RET_EBIB_OPTION			S5P_PMUREG(0x31A8)
+
+#define S5P_PMU_CAM_CONF			S5P_PMUREG(0x3C00)
+#define S5P_PMU_TV_CONF				S5P_PMUREG(0x3C20)
+#define S5P_PMU_MFC_CONF			S5P_PMUREG(0x3C40)
+#define S5P_PMU_G3D_CONF			S5P_PMUREG(0x3C60)
+#define S5P_PMU_LCD0_CONF			S5P_PMUREG(0x3C80)
+#define S5P_PMU_LCD1_CONF			S5P_PMUREG(0x3CA0)
+#define S5P_PMU_GPS_CONF			S5P_PMUREG(0x3CE0)
+
+#define S5P_PMU_SATA_PHY_CONTROL_EN		0x1
+#define S5P_INT_LOCAL_PWR_EN			0x7
+
+#define S5P_CHECK_SLEEP				0x00000BAD
+
+#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/* linux/arch/arm/mach-exynos4/include/mach/regs-sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - System MMU register
+ *
+ * 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_REGS_SYSMMU_H
+#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
+
+#define S5P_MMU_CTRL			0x000
+#define S5P_MMU_CFG			0x004
+#define S5P_MMU_STATUS			0x008
+#define S5P_MMU_FLUSH			0x00C
+#define S5P_PT_BASE_ADDR		0x014
+#define S5P_INT_STATUS			0x018
+#define S5P_INT_CLEAR			0x01C
+#define S5P_PAGE_FAULT_ADDR		0x024
+#define S5P_AW_FAULT_ADDR		0x028
+#define S5P_AR_FAULT_ADDR		0x02C
+#define S5P_DEFAULT_SLAVE_ADDR		0x030
+
+#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/smp.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/smp.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/smp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/smp.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,19 @@
+/* linux/arch/arm/mach-exynos4/include/mach/smp.h
+ *
+ * Cloned from arch/arm/mach-realview/include/mach/smp.h
+*/
+
+#ifndef ASM_ARCH_SMP_H
+#define ASM_ARCH_SMP_H __FILE__
+
+#include <asm/hardware/gic.h>
+
+/*
+ * We use IRQ1 as the IPI
+ */
+static inline void smp_cross_call(const struct cpumask *mask, int ipi)
+{
+	gic_raise_softirq(mask, ipi);
+}
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/sysmmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,46 @@
+/* linux/arch/arm/mach-exynos4/include/mach/sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung sysmmu driver for EXYNOS4
+ *
+ * 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_ARCH_SYSMMU_H
+#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
+
+enum exynos4_sysmmu_ips {
+	SYSMMU_MDMA,
+	SYSMMU_SSS,
+	SYSMMU_FIMC0,
+	SYSMMU_FIMC1,
+	SYSMMU_FIMC2,
+	SYSMMU_FIMC3,
+	SYSMMU_JPEG,
+	SYSMMU_FIMD0,
+	SYSMMU_FIMD1,
+	SYSMMU_PCIe,
+	SYSMMU_G2D,
+	SYSMMU_ROTATOR,
+	SYSMMU_MDMA2,
+	SYSMMU_TV,
+	SYSMMU_MFC_L,
+	SYSMMU_MFC_R,
+	EXYNOS4_SYSMMU_TOTAL_IPNUM,
+};
+
+#define S5P_SYSMMU_TOTAL_IPNUM		EXYNOS4_SYSMMU_TOTAL_IPNUM
+
+extern const char *sysmmu_ips_name[EXYNOS4_SYSMMU_TOTAL_IPNUM];
+
+typedef enum exynos4_sysmmu_ips sysmmu_ips;
+
+void sysmmu_clk_init(struct device *dev, sysmmu_ips ips);
+void sysmmu_clk_enable(sysmmu_ips ips);
+void sysmmu_clk_disable(sysmmu_ips ips);
+
+#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/system.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - system support header
+ *
+ * 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_SYSTEM_H
+#define __ASM_ARCH_SYSTEM_H __FILE__
+
+#include <plat/system-reset.h>
+
+static void arch_idle(void)
+{
+	/* nothing here yet */
+}
+#endif /* __ASM_ARCH_SYSTEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/timex.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/timex.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/timex.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29 @@
+/* linux/arch/arm/mach-exynos4/include/mach/timex.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2003-2010 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>
+ *
+ * Based on arch/arm/mach-s5p6442/include/mach/timex.h
+ *
+ * EXYNOS4 - time parameters
+ *
+ * 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_TIMEX_H
+#define __ASM_ARCH_TIMEX_H __FILE__
+
+/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
+ * a variable is useless. It seems as long as we make our timers an
+ * exact multiple of HZ, any value that makes a 1->1 correspondence
+ * for the time conversion functions to/from jiffies is acceptable.
+*/
+
+#define CLOCK_TICK_RATE 12000000
+
+#endif /* __ASM_ARCH_TIMEX_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,30 @@
+/* linux/arch/arm/mach-exynos4/include/mach/uncompress.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - uncompress 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.
+*/
+
+#ifndef __ASM_ARCH_UNCOMPRESS_H
+#define __ASM_ARCH_UNCOMPRESS_H __FILE__
+
+#include <mach/map.h>
+#include <plat/uncompress.h>
+
+static void arch_detect_cpu(void)
+{
+	/* we do not need to do any cpu detection here at the moment. */
+
+	/*
+	 * For preventing FIFO overrun or infinite loop of UART console,
+	 * fifo_max should be the minimum fifo size of all of the UART channels
+	 */
+	fifo_mask = S5PV210_UFSTAT_TXMASK;
+	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
+}
+#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/include/mach/vmalloc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/* linux/arch/arm/mach-exynos4/include/mach/vmalloc.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
+ *
+ * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
+ *
+ * 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.
+ *
+ * EXYNOS4 vmalloc definition
+*/
+
+#ifndef __ASM_ARCH_VMALLOC_H
+#define __ASM_ARCH_VMALLOC_H __FILE__
+
+#define VMALLOC_END	0xF6000000UL
+
+#endif /* __ASM_ARCH_VMALLOC_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/init.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/init.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,41 @@
+/* linux/arch/arm/mach-exynos4/init.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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/serial_core.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/regs-serial.h>
+
+static struct s3c24xx_uart_clksrc exynos4_serial_clocks[] = {
+	[0] = {
+		.name		= "uclk1",
+		.divisor	= 1,
+		.min_baud	= 0,
+		.max_baud	= 0,
+	},
+};
+
+/* uart registration process */
+void __init exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
+{
+	struct s3c2410_uartcfg *tcfg = cfg;
+	u32 ucnt;
+
+	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
+		if (!tcfg->clocks) {
+			tcfg->has_fracval = 1;
+			tcfg->clocks = exynos4_serial_clocks;
+			tcfg->clocks_size = ARRAY_SIZE(exynos4_serial_clocks);
+		}
+	}
+
+	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/irq-combiner.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/irq-combiner.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/irq-combiner.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/irq-combiner.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,126 @@
+/* linux/arch/arm/mach-exynos4/irq-combiner.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Based on arch/arm/common/gic.c
+ *
+ * IRQ COMBINER 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/io.h>
+
+#include <asm/mach/irq.h>
+
+#define COMBINER_ENABLE_SET	0x0
+#define COMBINER_ENABLE_CLEAR	0x4
+#define COMBINER_INT_STATUS	0xC
+
+static DEFINE_SPINLOCK(irq_controller_lock);
+
+struct combiner_chip_data {
+	unsigned int irq_offset;
+	unsigned int irq_mask;
+	void __iomem *base;
+};
+
+static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
+
+static inline void __iomem *combiner_base(struct irq_data *data)
+{
+	struct combiner_chip_data *combiner_data =
+		irq_data_get_irq_chip_data(data);
+
+	return combiner_data->base;
+}
+
+static void combiner_mask_irq(struct irq_data *data)
+{
+	u32 mask = 1 << (data->irq % 32);
+
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
+}
+
+static void combiner_unmask_irq(struct irq_data *data)
+{
+	u32 mask = 1 << (data->irq % 32);
+
+	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
+}
+
+static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
+{
+	struct combiner_chip_data *chip_data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+	unsigned int cascade_irq, combiner_irq;
+	unsigned long status;
+
+	/* primary controller ack'ing */
+	chip->irq_ack(&desc->irq_data);
+
+	spin_lock(&irq_controller_lock);
+	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
+	spin_unlock(&irq_controller_lock);
+	status &= chip_data->irq_mask;
+
+	if (status == 0)
+		goto out;
+
+	combiner_irq = __ffs(status);
+
+	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
+	if (unlikely(cascade_irq >= NR_IRQS))
+		do_bad_IRQ(cascade_irq, desc);
+	else
+		generic_handle_irq(cascade_irq);
+
+ out:
+	/* primary controller unmasking */
+	chip->irq_unmask(&desc->irq_data);
+}
+
+static struct irq_chip combiner_chip = {
+	.name		= "COMBINER",
+	.irq_mask	= combiner_mask_irq,
+	.irq_unmask	= combiner_unmask_irq,
+};
+
+void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
+{
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+	if (irq_set_handler_data(irq, &combiner_data[combiner_nr]) != 0)
+		BUG();
+	irq_set_chained_handler(irq, combiner_handle_cascade_irq);
+}
+
+void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
+			  unsigned int irq_start)
+{
+	unsigned int i;
+
+	if (combiner_nr >= MAX_COMBINER_NR)
+		BUG();
+
+	combiner_data[combiner_nr].base = base;
+	combiner_data[combiner_nr].irq_offset = irq_start;
+	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
+
+	/* Disable all interrupts */
+
+	__raw_writel(combiner_data[combiner_nr].irq_mask,
+		     base + COMBINER_ENABLE_CLEAR);
+
+	/* Setup the Linux IRQ subsystem */
+
+	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
+				+ MAX_IRQ_IN_COMBINER; i++) {
+		irq_set_chip_and_handler(i, &combiner_chip, handle_level_irq);
+		irq_set_chip_data(i, &combiner_data[combiner_nr]);
+		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/irq-eint.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/irq-eint.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/irq-eint.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/irq-eint.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,230 @@
+/* linux/arch/arm/mach-exynos4/irq-eint.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - IRQ EINT 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/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/sysdev.h>
+#include <linux/gpio.h>
+
+#include <plat/pm.h>
+#include <plat/cpu.h>
+#include <plat/gpio-cfg.h>
+
+#include <mach/regs-gpio.h>
+
+static DEFINE_SPINLOCK(eint_lock);
+
+static unsigned int eint0_15_data[16];
+
+static unsigned int exynos4_get_irq_nr(unsigned int number)
+{
+	u32 ret = 0;
+
+	switch (number) {
+	case 0 ... 3:
+		ret = (number + IRQ_EINT0);
+		break;
+	case 4 ... 7:
+		ret = (number + (IRQ_EINT4 - 4));
+		break;
+	case 8 ... 15:
+		ret = (number + (IRQ_EINT8 - 8));
+		break;
+	default:
+		printk(KERN_ERR "number available : %d\n", number);
+	}
+
+	return ret;
+}
+
+static inline void exynos4_irq_eint_mask(struct irq_data *data)
+{
+	u32 mask;
+
+	spin_lock(&eint_lock);
+	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	mask |= eint_irq_to_bit(data->irq);
+	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+}
+
+static void exynos4_irq_eint_unmask(struct irq_data *data)
+{
+	u32 mask;
+
+	spin_lock(&eint_lock);
+	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	mask &= ~(eint_irq_to_bit(data->irq));
+	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+}
+
+static inline void exynos4_irq_eint_ack(struct irq_data *data)
+{
+	__raw_writel(eint_irq_to_bit(data->irq),
+		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
+}
+
+static void exynos4_irq_eint_maskack(struct irq_data *data)
+{
+	exynos4_irq_eint_mask(data);
+	exynos4_irq_eint_ack(data);
+}
+
+static int exynos4_irq_eint_set_type(struct irq_data *data, unsigned int type)
+{
+	int offs = EINT_OFFSET(data->irq);
+	int shift;
+	u32 ctrl, mask;
+	u32 newvalue = 0;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
+		break;
+
+	case IRQ_TYPE_EDGE_FALLING:
+		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
+		break;
+
+	case IRQ_TYPE_EDGE_BOTH:
+		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
+		break;
+
+	case IRQ_TYPE_LEVEL_LOW:
+		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
+		break;
+
+	case IRQ_TYPE_LEVEL_HIGH:
+		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
+		break;
+
+	default:
+		printk(KERN_ERR "No such irq type %d", type);
+		return -EINVAL;
+	}
+
+	shift = (offs & 0x7) * 4;
+	mask = 0x7 << shift;
+
+	spin_lock(&eint_lock);
+	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
+	ctrl &= ~mask;
+	ctrl |= newvalue << shift;
+	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
+	spin_unlock(&eint_lock);
+
+	switch (offs) {
+	case 0 ... 7:
+		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
+		break;
+	case 8 ... 15:
+		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
+		break;
+	case 16 ... 23:
+		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
+		break;
+	case 24 ... 31:
+		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
+		break;
+	default:
+		printk(KERN_ERR "No such irq number %d", offs);
+	}
+
+	return 0;
+}
+
+static struct irq_chip exynos4_irq_eint = {
+	.name		= "exynos4-eint",
+	.irq_mask	= exynos4_irq_eint_mask,
+	.irq_unmask	= exynos4_irq_eint_unmask,
+	.irq_mask_ack	= exynos4_irq_eint_maskack,
+	.irq_ack	= exynos4_irq_eint_ack,
+	.irq_set_type	= exynos4_irq_eint_set_type,
+#ifdef CONFIG_PM
+	.irq_set_wake	= s3c_irqext_wake,
+#endif
+};
+
+/* exynos4_irq_demux_eint
+ *
+ * This function demuxes the IRQ from from EINTs 16 to 31.
+ * It is designed to be inlined into the specific handler
+ * s5p_irq_demux_eintX_Y.
+ *
+ * Each EINT pend/mask registers handle eight of them.
+ */
+static inline void exynos4_irq_demux_eint(unsigned int start)
+{
+	unsigned int irq;
+
+	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
+	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
+
+	status &= ~mask;
+	status &= 0xff;
+
+	while (status) {
+		irq = fls(status) - 1;
+		generic_handle_irq(irq + start);
+		status &= ~(1 << irq);
+	}
+}
+
+static void exynos4_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
+{
+	exynos4_irq_demux_eint(IRQ_EINT(16));
+	exynos4_irq_demux_eint(IRQ_EINT(24));
+}
+
+static void exynos4_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
+{
+	u32 *irq_data = irq_get_handler_data(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
+
+	chip->irq_mask(&desc->irq_data);
+
+	if (chip->irq_ack)
+		chip->irq_ack(&desc->irq_data);
+
+	generic_handle_irq(*irq_data);
+
+	chip->irq_unmask(&desc->irq_data);
+}
+
+int __init exynos4_init_irq_eint(void)
+{
+	int irq;
+
+	for (irq = 0 ; irq <= 31 ; irq++) {
+		irq_set_chip_and_handler(IRQ_EINT(irq), &exynos4_irq_eint,
+					 handle_level_irq);
+		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
+	}
+
+	irq_set_chained_handler(IRQ_EINT16_31, exynos4_irq_demux_eint16_31);
+
+	for (irq = 0 ; irq <= 15 ; irq++) {
+		eint0_15_data[irq] = IRQ_EINT(irq);
+
+		irq_set_handler_data(exynos4_get_irq_nr(irq),
+				     &eint0_15_data[irq]);
+		irq_set_chained_handler(exynos4_get_irq_nr(irq),
+					exynos4_irq_eint0_15);
+	}
+
+	return 0;
+}
+
+arch_initcall(exynos4_init_irq_eint);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,200 @@
+# arch/arm/mach-exynos4/Kconfig
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+# Configuration options for the EXYNOS4
+
+if ARCH_EXYNOS4
+
+config CPU_EXYNOS4210
+	bool
+	select S3C_PL330_DMA
+	help
+	  Enable EXYNOS4210 CPU support
+
+config EXYNOS4_MCT
+	bool "Kernel timer support by MCT"
+	help
+	  Use MCT (Multi Core Timer) as kernel timers
+
+config EXYNOS4_DEV_AHCI
+	bool
+	help
+	  Compile in platform device definitions for AHCI
+
+config EXYNOS4_DEV_PD
+	bool
+	help
+	  Compile in platform device definitions for Power Domain
+
+config EXYNOS4_DEV_SYSMMU
+	bool
+	help
+	  Common setup code for SYSTEM MMU in EXYNOS4
+
+config EXYNOS4_SETUP_I2C1
+	bool
+	help
+	  Common setup code for i2c bus 1.
+
+config EXYNOS4_SETUP_I2C2
+	bool
+	help
+	  Common setup code for i2c bus 2.
+
+config EXYNOS4_SETUP_I2C3
+	bool
+	help
+	  Common setup code for i2c bus 3.
+
+config EXYNOS4_SETUP_I2C4
+	bool
+	help
+	  Common setup code for i2c bus 4.
+
+config EXYNOS4_SETUP_I2C5
+	bool
+	help
+	  Common setup code for i2c bus 5.
+
+config EXYNOS4_SETUP_I2C6
+	bool
+	help
+	  Common setup code for i2c bus 6.
+
+config EXYNOS4_SETUP_I2C7
+	bool
+	help
+	  Common setup code for i2c bus 7.
+
+config EXYNOS4_SETUP_KEYPAD
+	bool
+	help
+	  Common setup code for keypad.
+
+config EXYNOS4_SETUP_SDHCI
+	bool
+	select EXYNOS4_SETUP_SDHCI_GPIO
+	help
+	  Internal helper functions for EXYNOS4 based SDHCI systems.
+
+config EXYNOS4_SETUP_SDHCI_GPIO
+	bool
+	help
+	  Common setup code for SDHCI gpio.
+
+config EXYNOS4_SETUP_FIMC
+	bool
+	help
+	  Common setup code for the camera interfaces.
+
+# machine support
+
+menu "EXYNOS4 Machines"
+
+config MACH_SMDKC210
+	bool "SMDKC210"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_I2C1
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDKC210
+
+config MACH_SMDKV310
+	bool "SMDKV310"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_I2C1
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC1
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select SAMSUNG_DEV_KEYPAD
+	select EXYNOS4_DEV_PD
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_KEYPAD
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung SMDKV310
+
+config MACH_ARMLEX4210
+	bool "ARMLEX4210"
+	select CPU_EXYNOS4210
+	select S3C_DEV_RTC
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select EXYNOS4_DEV_AHCI
+	select EXYNOS4_DEV_SYSMMU
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung ARMLEX4210 based on EXYNOS4210
+
+config MACH_UNIVERSAL_C210
+	bool "Mobile UNIVERSAL_C210 Board"
+	select CPU_EXYNOS4210
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C5
+	select S5P_DEV_ONENAND
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	help
+	  Machine support for Samsung Mobile Universal S5PC210 Reference
+	  Board.
+
+config MACH_NURI
+	bool "Mobile NURI Board"
+	select CPU_EXYNOS4210
+	select S3C_DEV_WDT
+	select S3C_DEV_HSMMC
+	select S3C_DEV_HSMMC2
+	select S3C_DEV_HSMMC3
+	select S3C_DEV_I2C1
+	select S3C_DEV_I2C5
+	select EXYNOS4_SETUP_I2C1
+	select EXYNOS4_SETUP_I2C5
+	select EXYNOS4_SETUP_SDHCI
+	select SAMSUNG_DEV_PWM
+	help
+	  Machine support for Samsung Mobile NURI Board.
+
+endmenu
+
+comment "Configuration for HSMMC bus width"
+
+menu "Use 8-bit bus width"
+
+config EXYNOS4_SDHCI_CH0_8BIT
+	bool "Channel 0 with 8-bit bus"
+	help
+	  Support HSMMC Channel 0 8-bit bus.
+	  If selected, Channel 1 is disabled.
+
+config EXYNOS4_SDHCI_CH2_8BIT
+	bool "Channel 2 with 8-bit bus"
+	help
+	  Support HSMMC Channel 2 8-bit bus.
+	  If selected, Channel 3 is disabled.
+
+endmenu
+
+endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/localtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/* linux/arch/arm/mach-exynos4/localtimer.c
+ *
+ * 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/clockchips.h>
+
+#include <asm/irq.h>
+#include <asm/localtimer.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = IRQ_LOCALTIMER;
+	twd_timer_setup(evt);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-armlex4210.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-armlex4210.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-armlex4210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-armlex4210.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,215 @@
+/* linux/arch/arm/mach-exynos4/mach-armlex4210.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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/gpio.h>
+#include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/smsc911x.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/exynos4.h>
+#include <plat/gpio-cfg.h>
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define ARMLEX4210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define ARMLEX4210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define ARMLEX4210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg armlex4210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= ARMLEX4210_UCON_DEFAULT,
+		.ulcon		= ARMLEX4210_ULCON_DEFAULT,
+		.ufcon		= ARMLEX4210_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPX2(5),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+	.max_width		= 4,
+};
+
+static struct s3c_sdhci_platdata armlex4210_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+	.max_width		= 4,
+};
+
+static void __init armlex4210_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&armlex4210_hsmmc0_pdata);
+	s3c_sdhci2_set_platdata(&armlex4210_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&armlex4210_hsmmc3_pdata);
+}
+
+static void __init armlex4210_wlan_init(void)
+{
+	/* enable */
+	s3c_gpio_cfgpin(EXYNOS4_GPX2(0), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX2(0), S3C_GPIO_PULL_UP);
+
+	/* reset */
+	s3c_gpio_cfgpin(EXYNOS4_GPX1(6), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX1(6), S3C_GPIO_PULL_UP);
+
+	/* wakeup */
+	s3c_gpio_cfgpin(EXYNOS4_GPX1(5), S3C_GPIO_SFN(0xf));
+	s3c_gpio_setpull(EXYNOS4_GPX1(5), S3C_GPIO_PULL_UP);
+}
+
+static struct resource armlex4210_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(3),
+		.end	= EXYNOS4_PA_SROM_BANK(3) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(27),
+		.end	= IRQ_EINT(27),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_HIGH,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_config = {
+	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
+	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
+	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
+	.phy_interface	= PHY_INTERFACE_MODE_MII,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device armlex4210_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(armlex4210_smsc911x_resources),
+	.resource	= armlex4210_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static struct platform_device *armlex4210_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&armlex4210_smsc911x,
+	&exynos4_device_ahci,
+};
+
+static void __init armlex4210_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(0 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__ADDRMODE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init armlex4210_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(armlex4210_uartcfgs,
+			   ARRAY_SIZE(armlex4210_uartcfgs));
+}
+
+static void __init armlex4210_machine_init(void)
+{
+	armlex4210_smsc911x_init();
+
+	armlex4210_sdhci_init();
+
+	armlex4210_wlan_init();
+
+	platform_add_devices(armlex4210_devices,
+			     ARRAY_SIZE(armlex4210_devices));
+}
+
+MACHINE_START(ARMLEX4210, "ARMLEX4210")
+	/* Maintainer: Alim Akhtar <alim.akhtar@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= armlex4210_map_io,
+	.init_machine	= armlex4210_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-nuri.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-nuri.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-nuri.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-nuri.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,305 @@
+/*
+ * linux/arch/arm/mach-exynos4/mach-nuri.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., 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/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/mmc/host.h>
+#include <linux/fb.h>
+#include <linux/pwm_backlight.h>
+
+#include <video/platform_lcd.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define NURI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define NURI_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define NURI_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+enum fixed_regulator_id {
+	FIXED_REG_ID_MMC = 0,
+};
+
+static struct s3c2410_uartcfg nuri_uartcfgs[] __initdata = {
+	{
+		.hwport		= 0,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 1,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 2,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+	{
+		.hwport		= 3,
+		.ucon		= NURI_UCON_DEFAULT,
+		.ulcon		= NURI_ULCON_DEFAULT,
+		.ufcon		= NURI_UFCON_DEFAULT,
+	},
+};
+
+/* eMMC */
+static struct s3c_sdhci_platdata nuri_hsmmc0_data __initdata = {
+	.max_width		= 8,
+	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE | MMC_CAP_ERASE),
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply emmc_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+	REGULATOR_SUPPLY("vmmc", "dw_mmc"),
+};
+
+static struct regulator_init_data emmc_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "VMEM_VDD_2.8V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(emmc_supplies),
+	.consumer_supplies	= emmc_supplies,
+};
+
+static struct fixed_voltage_config emmc_fixed_voltage_config = {
+	.supply_name		= "MASSMEMORY_EN (inverted)",
+	.microvolts		= 2800000,
+	.gpio			= EXYNOS4_GPL1(1),
+	.enable_high		= false,
+	.init_data		= &emmc_fixed_voltage_init_data,
+};
+
+static struct platform_device emmc_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= FIXED_REG_ID_MMC,
+	.dev			= {
+		.platform_data	= &emmc_fixed_voltage_config,
+	},
+};
+
+/* SD */
+static struct s3c_sdhci_platdata nuri_hsmmc2_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.ext_cd_gpio		= EXYNOS4_GPX3(3),	/* XEINT_27 */
+	.ext_cd_gpio_invert	= 1,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* WLAN */
+static struct s3c_sdhci_platdata nuri_hsmmc3_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED,
+	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static void __init nuri_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&nuri_hsmmc0_data);
+	s3c_sdhci2_set_platdata(&nuri_hsmmc2_data);
+	s3c_sdhci3_set_platdata(&nuri_hsmmc3_data);
+}
+
+/* GPIO KEYS */
+static struct gpio_keys_button nuri_gpio_keys_tables[] = {
+	{
+		.code			= KEY_VOLUMEUP,
+		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
+		.desc			= "gpio-keys: KEY_VOLUMEUP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_VOLUMEDOWN,
+		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
+		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_POWER,
+		.gpio			= EXYNOS4_GPX2(7),	/* XEINT23 */
+		.desc			= "gpio-keys: KEY_POWER",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.wakeup			= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data nuri_gpio_keys_data = {
+	.buttons		= nuri_gpio_keys_tables,
+	.nbuttons		= ARRAY_SIZE(nuri_gpio_keys_tables),
+};
+
+static struct platform_device nuri_gpio_keys = {
+	.name			= "gpio-keys",
+	.dev			= {
+		.platform_data	= &nuri_gpio_keys_data,
+	},
+};
+
+static void nuri_lcd_power_on(struct plat_lcd_data *pd, unsigned int power)
+{
+	int gpio = EXYNOS4_GPE1(5);
+
+	gpio_request(gpio, "LVDS_nSHDN");
+	gpio_direction_output(gpio, power);
+	gpio_free(gpio);
+}
+
+static int nuri_bl_init(struct device *dev)
+{
+	int ret, gpio = EXYNOS4_GPE2(3);
+
+	ret = gpio_request(gpio, "LCD_LDO_EN");
+	if (!ret)
+		gpio_direction_output(gpio, 0);
+
+	return ret;
+}
+
+static int nuri_bl_notify(struct device *dev, int brightness)
+{
+	if (brightness < 1)
+		brightness = 0;
+
+	gpio_set_value(EXYNOS4_GPE2(3), 1);
+
+	return brightness;
+}
+
+static void nuri_bl_exit(struct device *dev)
+{
+	gpio_free(EXYNOS4_GPE2(3));
+}
+
+/* nuri pwm backlight */
+static struct platform_pwm_backlight_data nuri_backlight_data = {
+	.pwm_id			= 0,
+	.pwm_period_ns		= 30000,
+	.max_brightness		= 100,
+	.dft_brightness		= 50,
+	.init			= nuri_bl_init,
+	.notify			= nuri_bl_notify,
+	.exit			= nuri_bl_exit,
+};
+
+static struct platform_device nuri_backlight_device = {
+	.name			= "pwm-backlight",
+	.id			= -1,
+	.dev			= {
+		.parent		= &s3c_device_timer[0].dev,
+		.platform_data	= &nuri_backlight_data,
+	},
+};
+
+static struct plat_lcd_data nuri_lcd_platform_data = {
+	.set_power		= nuri_lcd_power_on,
+};
+
+static struct platform_device nuri_lcd_device = {
+	.name			= "platform-lcd",
+	.id			= -1,
+	.dev			= {
+		.platform_data	= &nuri_lcd_platform_data,
+	},
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+/* GPIO I2C 5 (PMIC) */
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	/* max8997, To be updated */
+};
+
+static struct platform_device *nuri_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&emmc_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_wdt,
+	&s3c_device_timer[0],
+
+	/* NURI Devices */
+	&nuri_gpio_keys,
+	&nuri_lcd_device,
+	&nuri_backlight_device,
+};
+
+static void __init nuri_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(nuri_uartcfgs, ARRAY_SIZE(nuri_uartcfgs));
+}
+
+static void __init nuri_machine_init(void)
+{
+	nuri_sdhci_init();
+
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+
+	/* Last */
+	platform_add_devices(nuri_devices, ARRAY_SIZE(nuri_devices));
+}
+
+MACHINE_START(NURI, "NURI")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= nuri_map_io,
+	.init_machine	= nuri_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-smdkc210.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-smdkc210.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-smdkc210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-smdkc210.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,223 @@
+/* linux/arch/arm/mach-exynos4/mach-smdkc210.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDKC210_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDKC210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDKC210_UCON_DEFAULT,
+		.ulcon		= SMDKC210_ULCON_DEFAULT,
+		.ufcon		= SMDKC210_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct resource smdkc210_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(1),
+		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(5),
+		.end	= IRQ_EINT(5),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_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,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device smdkc210_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smdkc210_smsc911x_resources),
+	.resource	= smdkc210_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{I2C_BOARD_INFO("wm8994", 0x1a),},
+};
+
+static struct platform_device *smdkc210_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c1,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_ac97,
+	&exynos4_device_i2s0,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&smdkc210_smsc911x,
+};
+
+static void __init smdkc210_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init smdkc210_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
+}
+
+static void __init smdkc210_machine_init(void)
+{
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	smdkc210_smsc911x_init();
+
+	s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
+	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
+
+	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
+}
+
+MACHINE_START(SMDKC210, "SMDKC210")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkc210_map_io,
+	.init_machine	= smdkc210_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-smdkv310.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-smdkv310.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-smdkv310.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-smdkv310.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,248 @@
+/* linux/arch/arm/mach-exynos4/mach-smdkv310.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.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/serial_core.h>
+#include <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/platform_device.h>
+#include <linux/smsc911x.h>
+#include <linux/io.h>
+#include <linux/i2c.h>
+#include <linux/input.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/regs-srom.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/keypad.h>
+#include <plat/sdhci.h>
+#include <plat/iic.h>
+#include <plat/pd.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG4 |	\
+				 S5PV210_UFCON_RXTRIG4)
+
+static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.flags		= 0,
+		.ucon		= SMDKV310_UCON_DEFAULT,
+		.ulcon		= SMDKV310_ULCON_DEFAULT,
+		.ufcon		= SMDKV310_UFCON_DEFAULT,
+	},
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH0_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK0(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+#ifdef CONFIG_EXYNOS4_SDHCI_CH2_8BIT
+	.max_width		= 8,
+	.host_caps		= MMC_CAP_8_BIT_DATA,
+#endif
+};
+
+static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.ext_cd_gpio		= EXYNOS4_GPK2(2),
+	.ext_cd_gpio_invert	= 1,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct resource smdkv310_smsc911x_resources[] = {
+	[0] = {
+		.start	= EXYNOS4_PA_SROM_BANK(1),
+		.end	= EXYNOS4_PA_SROM_BANK(1) + SZ_64K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_EINT(5),
+		.end	= IRQ_EINT(5),
+		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
+	},
+};
+
+static struct smsc911x_platform_config smsc9215_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,
+	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
+};
+
+static struct platform_device smdkv310_smsc911x = {
+	.name		= "smsc911x",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(smdkv310_smsc911x_resources),
+	.resource	= smdkv310_smsc911x_resources,
+	.dev		= {
+		.platform_data	= &smsc9215_config,
+	},
+};
+
+static uint32_t smdkv310_keymap[] __initdata = {
+	/* KEY(row, col, keycode) */
+	KEY(0, 3, KEY_1), KEY(0, 4, KEY_2), KEY(0, 5, KEY_3),
+	KEY(0, 6, KEY_4), KEY(0, 7, KEY_5),
+	KEY(1, 3, KEY_A), KEY(1, 4, KEY_B), KEY(1, 5, KEY_C),
+	KEY(1, 6, KEY_D), KEY(1, 7, KEY_E)
+};
+
+static struct matrix_keymap_data smdkv310_keymap_data __initdata = {
+	.keymap		= smdkv310_keymap,
+	.keymap_size	= ARRAY_SIZE(smdkv310_keymap),
+};
+
+static struct samsung_keypad_platdata smdkv310_keypad_data __initdata = {
+	.keymap_data	= &smdkv310_keymap_data,
+	.rows		= 2,
+	.cols		= 8,
+};
+
+static struct i2c_board_info i2c_devs1[] __initdata = {
+	{I2C_BOARD_INFO("wm8994", 0x1a),},
+};
+
+static struct platform_device *smdkv310_devices[] __initdata = {
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc1,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c1,
+	&s3c_device_rtc,
+	&s3c_device_wdt,
+	&exynos4_device_ac97,
+	&exynos4_device_i2s0,
+	&samsung_device_keypad,
+	&exynos4_device_pd[PD_MFC],
+	&exynos4_device_pd[PD_G3D],
+	&exynos4_device_pd[PD_LCD0],
+	&exynos4_device_pd[PD_LCD1],
+	&exynos4_device_pd[PD_CAM],
+	&exynos4_device_pd[PD_TV],
+	&exynos4_device_pd[PD_GPS],
+	&exynos4_device_sysmmu,
+	&samsung_asoc_dma,
+	&smdkv310_smsc911x,
+};
+
+static void __init smdkv310_smsc911x_init(void)
+{
+	u32 cs1;
+
+	/* configure nCS1 width to 16 bits */
+	cs1 = __raw_readl(S5P_SROM_BW) &
+		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
+	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
+		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
+		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
+		S5P_SROM_BW__NCS1__SHIFT;
+	__raw_writel(cs1, S5P_SROM_BW);
+
+	/* set timing for nCS1 suitable for ethernet chip */
+	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
+		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
+		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
+		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
+		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
+}
+
+static void __init smdkv310_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
+}
+
+static void __init smdkv310_machine_init(void)
+{
+	s3c_i2c1_set_platdata(NULL);
+	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
+
+	smdkv310_smsc911x_init();
+
+	s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
+	s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
+	s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
+	s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
+
+	samsung_keypad_set_platdata(&smdkv310_keypad_data);
+
+	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
+}
+
+MACHINE_START(SMDKV310, "SMDKV310")
+	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
+	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= smdkv310_map_io,
+	.init_machine	= smdkv310_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-universal_c210.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-universal_c210.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mach-universal_c210.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mach-universal_c210.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,650 @@
+/* linux/arch/arm/mach-exynos4/mach-universal_c210.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., 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/platform_device.h>
+#include <linux/serial_core.h>
+#include <linux/input.h>
+#include <linux/i2c.h>
+#include <linux/gpio_keys.h>
+#include <linux/gpio.h>
+#include <linux/mfd/max8998.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/regulator/max8952.h>
+#include <linux/mmc/host.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include <plat/regs-serial.h>
+#include <plat/exynos4.h>
+#include <plat/cpu.h>
+#include <plat/devs.h>
+#include <plat/iic.h>
+#include <plat/sdhci.h>
+
+#include <mach/map.h>
+
+/* Following are default values for UCON, ULCON and UFCON UART registers */
+#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
+				 S3C2410_UCON_RXILEVEL |	\
+				 S3C2410_UCON_TXIRQMODE |	\
+				 S3C2410_UCON_RXIRQMODE |	\
+				 S3C2410_UCON_RXFIFO_TOI |	\
+				 S3C2443_UCON_RXERR_IRQEN)
+
+#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
+
+#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
+				 S5PV210_UFCON_TXTRIG256 |	\
+				 S5PV210_UFCON_RXTRIG256)
+
+static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
+	[0] = {
+		.hwport		= 0,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[1] = {
+		.hwport		= 1,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[2] = {
+		.hwport		= 2,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+	[3] = {
+		.hwport		= 3,
+		.ucon		= UNIVERSAL_UCON_DEFAULT,
+		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
+		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
+	},
+};
+
+static struct regulator_consumer_supply max8952_consumer =
+	REGULATOR_SUPPLY("vddarm", NULL);
+
+static struct max8952_platform_data universal_max8952_pdata __initdata = {
+	.gpio_vid0	= EXYNOS4_GPX0(3),
+	.gpio_vid1	= EXYNOS4_GPX0(4),
+	.gpio_en	= -1, /* Not controllable, set "Always High" */
+	.default_mode	= 0, /* vid0 = 0, vid1 = 0 */
+	.dvs_mode	= { 48, 32, 28, 18 }, /* 1.25, 1.20, 1.05, 0.95V */
+	.sync_freq	= 0, /* default: fastest */
+	.ramp_speed	= 0, /* default: fastest */
+
+	.reg_data	= {
+		.constraints	= {
+			.name		= "VARM_1.2V",
+			.min_uV		= 770000,
+			.max_uV		= 1400000,
+			.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE,
+			.always_on	= 1,
+			.boot_on	= 1,
+		},
+		.num_consumer_supplies	= 1,
+		.consumer_supplies	= &max8952_consumer,
+	},
+};
+
+static struct regulator_consumer_supply lp3974_buck1_consumer =
+	REGULATOR_SUPPLY("vddint", NULL);
+
+static struct regulator_consumer_supply lp3974_buck2_consumer =
+	REGULATOR_SUPPLY("vddg3d", NULL);
+
+static struct regulator_init_data lp3974_buck1_data = {
+	.constraints	= {
+		.name		= "VINT_1.1V",
+		.min_uV		= 750000,
+		.max_uV		= 1500000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck1_consumer,
+};
+
+static struct regulator_init_data lp3974_buck2_data = {
+	.constraints	= {
+		.name		= "VG3D_1.1V",
+		.min_uV		= 750000,
+		.max_uV		= 1500000,
+		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &lp3974_buck2_consumer,
+};
+
+static struct regulator_init_data lp3974_buck3_data = {
+	.constraints	= {
+		.name		= "VCC_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_buck4_data = {
+	.constraints	= {
+		.name		= "VMEM_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.apply_uV	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo2_data = {
+	.constraints	= {
+		.name		= "VALIVE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo3_data = {
+	.constraints	= {
+		.name		= "VUSB+MIPI_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo4_data = {
+	.constraints	= {
+		.name		= "VADC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo5_data = {
+	.constraints	= {
+		.name		= "VTF_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo6_data = {
+	.constraints	= {
+		.name		= "LDO6",
+		.min_uV		= 2000000,
+		.max_uV		= 2000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo7_data = {
+	.constraints	= {
+		.name		= "VLCD+VMIPI_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo8_data = {
+	.constraints	= {
+		.name		= "VUSB+VDAC_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo9_data = {
+	.constraints	= {
+		.name		= "VCC_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo10_data = {
+	.constraints	= {
+		.name		= "VPLL_1.1V",
+		.min_uV		= 1100000,
+		.max_uV		= 1100000,
+		.boot_on	= 1,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo11_data = {
+	.constraints	= {
+		.name		= "CAM_AF_3.3V",
+		.min_uV		= 3300000,
+		.max_uV		= 3300000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo12_data = {
+	.constraints	= {
+		.name		= "PS_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo13_data = {
+	.constraints	= {
+		.name		= "VHIC_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo14_data = {
+	.constraints	= {
+		.name		= "CAM_I_HOST_1.8V",
+		.min_uV		= 1800000,
+		.max_uV		= 1800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo15_data = {
+	.constraints	= {
+		.name		= "CAM_S_DIG+FM33_CORE_1.2V",
+		.min_uV		= 1200000,
+		.max_uV		= 1200000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo16_data = {
+	.constraints	= {
+		.name		= "CAM_S_ANA_2.8V",
+		.min_uV		= 2800000,
+		.max_uV		= 2800000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_ldo17_data = {
+	.constraints	= {
+		.name		= "VCC_3.0V_LCD",
+		.min_uV		= 3000000,
+		.max_uV		= 3000000,
+		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.boot_on	= 1,
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_32khz_ap_data = {
+	.constraints	= {
+		.name		= "32KHz AP",
+		.always_on	= 1,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_32khz_cp_data = {
+	.constraints	= {
+		.name		= "32KHz CP",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_vichg_data = {
+	.constraints	= {
+		.name		= "VICHG",
+		.state_mem	= {
+			.disabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_esafeout1_data = {
+	.constraints	= {
+		.name		= "SAFEOUT1",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct regulator_init_data lp3974_esafeout2_data = {
+	.constraints	= {
+		.name		= "SAFEOUT2",
+		.boot_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+		.state_mem	= {
+			.enabled	= 1,
+		},
+	},
+};
+
+static struct max8998_regulator_data lp3974_regulators[] = {
+	{ MAX8998_LDO2,  &lp3974_ldo2_data },
+	{ MAX8998_LDO3,  &lp3974_ldo3_data },
+	{ MAX8998_LDO4,  &lp3974_ldo4_data },
+	{ MAX8998_LDO5,  &lp3974_ldo5_data },
+	{ MAX8998_LDO6,  &lp3974_ldo6_data },
+	{ MAX8998_LDO7,  &lp3974_ldo7_data },
+	{ MAX8998_LDO8,  &lp3974_ldo8_data },
+	{ MAX8998_LDO9,  &lp3974_ldo9_data },
+	{ MAX8998_LDO10, &lp3974_ldo10_data },
+	{ MAX8998_LDO11, &lp3974_ldo11_data },
+	{ MAX8998_LDO12, &lp3974_ldo12_data },
+	{ MAX8998_LDO13, &lp3974_ldo13_data },
+	{ MAX8998_LDO14, &lp3974_ldo14_data },
+	{ MAX8998_LDO15, &lp3974_ldo15_data },
+	{ MAX8998_LDO16, &lp3974_ldo16_data },
+	{ MAX8998_LDO17, &lp3974_ldo17_data },
+	{ MAX8998_BUCK1, &lp3974_buck1_data },
+	{ MAX8998_BUCK2, &lp3974_buck2_data },
+	{ MAX8998_BUCK3, &lp3974_buck3_data },
+	{ MAX8998_BUCK4, &lp3974_buck4_data },
+	{ MAX8998_EN32KHZ_AP, &lp3974_32khz_ap_data },
+	{ MAX8998_EN32KHZ_CP, &lp3974_32khz_cp_data },
+	{ MAX8998_ENVICHG, &lp3974_vichg_data },
+	{ MAX8998_ESAFEOUT1, &lp3974_esafeout1_data },
+	{ MAX8998_ESAFEOUT2, &lp3974_esafeout2_data },
+};
+
+static struct max8998_platform_data universal_lp3974_pdata = {
+	.num_regulators		= ARRAY_SIZE(lp3974_regulators),
+	.regulators		= lp3974_regulators,
+	.buck1_voltage1		= 1100000,	/* INT */
+	.buck1_voltage2		= 1000000,
+	.buck1_voltage3		= 1100000,
+	.buck1_voltage4		= 1000000,
+	.buck1_set1		= EXYNOS4_GPX0(5),
+	.buck1_set2		= EXYNOS4_GPX0(6),
+	.buck2_voltage1		= 1200000,	/* G3D */
+	.buck2_voltage2		= 1100000,
+	.buck1_default_idx	= 0,
+	.buck2_set3		= EXYNOS4_GPE2(0),
+	.buck2_default_idx	= 0,
+	.wakeup			= true,
+};
+
+/* GPIO I2C 5 (PMIC) */
+static struct i2c_board_info i2c5_devs[] __initdata = {
+	{
+		I2C_BOARD_INFO("max8952", 0xC0 >> 1),
+		.platform_data	= &universal_max8952_pdata,
+	}, {
+		I2C_BOARD_INFO("lp3974", 0xCC >> 1),
+		.platform_data	= &universal_lp3974_pdata,
+	},
+};
+
+/* GPIO KEYS */
+static struct gpio_keys_button universal_gpio_keys_tables[] = {
+	{
+		.code			= KEY_VOLUMEUP,
+		.gpio			= EXYNOS4_GPX2(0),	/* XEINT16 */
+		.desc			= "gpio-keys: KEY_VOLUMEUP",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_VOLUMEDOWN,
+		.gpio			= EXYNOS4_GPX2(1),	/* XEINT17 */
+		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_CONFIG,
+		.gpio			= EXYNOS4_GPX2(2),	/* XEINT18 */
+		.desc			= "gpio-keys: KEY_CONFIG",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_CAMERA,
+		.gpio			= EXYNOS4_GPX2(3),	/* XEINT19 */
+		.desc			= "gpio-keys: KEY_CAMERA",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	}, {
+		.code			= KEY_OK,
+		.gpio			= EXYNOS4_GPX3(5),	/* XEINT29 */
+		.desc			= "gpio-keys: KEY_OK",
+		.type			= EV_KEY,
+		.active_low		= 1,
+		.debounce_interval	= 1,
+	},
+};
+
+static struct gpio_keys_platform_data universal_gpio_keys_data = {
+	.buttons	= universal_gpio_keys_tables,
+	.nbuttons	= ARRAY_SIZE(universal_gpio_keys_tables),
+};
+
+static struct platform_device universal_gpio_keys = {
+	.name			= "gpio-keys",
+	.dev			= {
+		.platform_data	= &universal_gpio_keys_data,
+	},
+};
+
+/* eMMC */
+static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
+	.max_width		= 8,
+	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE),
+	.cd_type		= S3C_SDHCI_CD_PERMANENT,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+static struct regulator_consumer_supply mmc0_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
+};
+
+static struct regulator_init_data mmc0_fixed_voltage_init_data = {
+	.constraints		= {
+		.name		= "VMEM_VDD_2.8V",
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= ARRAY_SIZE(mmc0_supplies),
+	.consumer_supplies	= mmc0_supplies,
+};
+
+static struct fixed_voltage_config mmc0_fixed_voltage_config = {
+	.supply_name		= "MASSMEMORY_EN",
+	.microvolts		= 2800000,
+	.gpio			= EXYNOS4_GPE1(3),
+	.enable_high		= true,
+	.init_data		= &mmc0_fixed_voltage_init_data,
+};
+
+static struct platform_device mmc0_fixed_voltage = {
+	.name			= "reg-fixed-voltage",
+	.id			= 0,
+	.dev			= {
+		.platform_data	= &mmc0_fixed_voltage_config,
+	},
+};
+
+/* SD */
+static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.ext_cd_gpio		= EXYNOS4_GPX3(4),      /* XEINT_28 */
+	.ext_cd_gpio_invert	= 1,
+	.cd_type		= S3C_SDHCI_CD_GPIO,
+	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
+};
+
+/* WiFi */
+static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
+	.max_width		= 4,
+	.host_caps		= MMC_CAP_4_BIT_DATA |
+				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
+				MMC_CAP_DISABLE,
+	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
+};
+
+static void __init universal_sdhci_init(void)
+{
+	s3c_sdhci0_set_platdata(&universal_hsmmc0_data);
+	s3c_sdhci2_set_platdata(&universal_hsmmc2_data);
+	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
+}
+
+/* I2C0 */
+static struct i2c_board_info i2c0_devs[] __initdata = {
+	/* Camera, To be updated */
+};
+
+/* I2C1 */
+static struct i2c_board_info i2c1_devs[] __initdata = {
+	/* Gyro, To be updated */
+};
+
+static struct platform_device *universal_devices[] __initdata = {
+	/* Samsung Platform Devices */
+	&mmc0_fixed_voltage,
+	&s3c_device_hsmmc0,
+	&s3c_device_hsmmc2,
+	&s3c_device_hsmmc3,
+	&s3c_device_i2c5,
+
+	/* Universal Devices */
+	&universal_gpio_keys,
+	&s5p_device_onenand,
+};
+
+static void __init universal_map_io(void)
+{
+	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
+	s3c24xx_init_clocks(24000000);
+	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
+}
+
+static void __init universal_machine_init(void)
+{
+	universal_sdhci_init();
+
+	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
+	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
+
+	s3c_i2c5_set_platdata(NULL);
+	i2c_register_board_info(5, i2c5_devs, ARRAY_SIZE(i2c5_devs));
+
+	/* Last */
+	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
+}
+
+MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
+	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
+	.boot_params	= S5P_PA_SDRAM + 0x100,
+	.init_irq	= exynos4_init_irq,
+	.map_io		= universal_map_io,
+	.init_machine	= universal_machine_init,
+	.timer		= &exynos4_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,56 @@
+# arch/arm/mach-exynos4/Makefile
+#
+# Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+#		http://www.samsung.com/
+#
+# Licensed under GPLv2
+
+obj-y				:=
+obj-m				:=
+obj-n				:=
+obj-				:=
+
+# Core support for EXYNOS4 system
+
+obj-$(CONFIG_CPU_EXYNOS4210)	+= cpu.o init.o clock.o irq-combiner.o
+obj-$(CONFIG_CPU_EXYNOS4210)	+= setup-i2c0.o gpiolib.o irq-eint.o dma.o
+obj-$(CONFIG_PM)		+= pm.o sleep.o
+obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
+
+obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
+
+ifeq ($(CONFIG_EXYNOS4_MCT),y)
+obj-y				+= mct.o
+else
+obj-y				+= time.o
+obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
+endif
+
+obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
+
+# machine support
+
+obj-$(CONFIG_MACH_SMDKC210)		+= mach-smdkc210.o
+obj-$(CONFIG_MACH_SMDKV310)		+= mach-smdkv310.o
+obj-$(CONFIG_MACH_ARMLEX4210)		+= mach-armlex4210.o
+obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
+obj-$(CONFIG_MACH_NURI)			+= mach-nuri.o
+
+# device support
+
+obj-y					+= dev-audio.o
+obj-$(CONFIG_EXYNOS4_DEV_AHCI)		+= dev-ahci.o
+obj-$(CONFIG_EXYNOS4_DEV_PD)		+= dev-pd.o
+obj-$(CONFIG_EXYNOS4_DEV_SYSMMU)	+= dev-sysmmu.o
+
+obj-$(CONFIG_EXYNOS4_SETUP_FIMC)	+= setup-fimc.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C1)	+= setup-i2c1.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C2)	+= setup-i2c2.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C3)	+= setup-i2c3.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C4)	+= setup-i2c4.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C5)	+= setup-i2c5.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C6)	+= setup-i2c6.o
+obj-$(CONFIG_EXYNOS4_SETUP_I2C7)	+= setup-i2c7.o
+obj-$(CONFIG_EXYNOS4_SETUP_KEYPAD)	+= setup-keypad.o
+obj-$(CONFIG_EXYNOS4_SETUP_SDHCI)	+= setup-sdhci.o
+obj-$(CONFIG_EXYNOS4_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/Makefile.boot linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/Makefile.boot
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/Makefile.boot	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2 @@
+   zreladdr-y	:= 0x40008000
+params_phys-y	:= 0x40000100
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mct.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mct.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/mct.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/mct.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,421 @@
+/* linux/arch/arm/mach-exynos4/mct.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 MCT(Multi-Core Timer) 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/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/percpu.h>
+
+#include <mach/map.h>
+#include <mach/regs-mct.h>
+#include <asm/mach/time.h>
+
+static unsigned long clk_cnt_per_tick;
+static unsigned long clk_rate;
+
+struct mct_clock_event_device {
+	struct clock_event_device *evt;
+	void __iomem *base;
+};
+
+struct mct_clock_event_device mct_tick[2];
+
+static void exynos4_mct_write(unsigned int value, void *addr)
+{
+	void __iomem *stat_addr;
+	u32 mask;
+	u32 i;
+
+	__raw_writel(value, addr);
+
+	switch ((u32) addr) {
+	case (u32) EXYNOS4_MCT_G_TCON:
+		stat_addr = EXYNOS4_MCT_G_WSTAT;
+		mask = 1 << 16;		/* G_TCON write status */
+		break;
+	case (u32) EXYNOS4_MCT_G_COMP0_L:
+		stat_addr = EXYNOS4_MCT_G_WSTAT;
+		mask = 1 << 0;		/* G_COMP0_L write status */
+		break;
+	case (u32) EXYNOS4_MCT_G_COMP0_U:
+		stat_addr = EXYNOS4_MCT_G_WSTAT;
+		mask = 1 << 1;		/* G_COMP0_U write status */
+		break;
+	case (u32) EXYNOS4_MCT_G_COMP0_ADD_INCR:
+		stat_addr = EXYNOS4_MCT_G_WSTAT;
+		mask = 1 << 2;		/* G_COMP0_ADD_INCR write status */
+		break;
+	case (u32) EXYNOS4_MCT_G_CNT_L:
+		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+		mask = 1 << 0;		/* G_CNT_L write status */
+		break;
+	case (u32) EXYNOS4_MCT_G_CNT_U:
+		stat_addr = EXYNOS4_MCT_G_CNT_WSTAT;
+		mask = 1 << 1;		/* G_CNT_U write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCON_OFFSET):
+		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 3;		/* L0_TCON write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCON_OFFSET):
+		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 3;		/* L1_TCON write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_TCNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 0;		/* L0_TCNTB write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_TCNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 0;		/* L1_TCNTB write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L0_BASE + MCT_L_ICNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L0_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 1;		/* L0_ICNTB write status */
+		break;
+	case (u32)(EXYNOS4_MCT_L1_BASE + MCT_L_ICNTB_OFFSET):
+		stat_addr = EXYNOS4_MCT_L1_BASE + MCT_L_WSTAT_OFFSET;
+		mask = 1 << 1;		/* L1_ICNTB write status */
+		break;
+	default:
+		return;
+	}
+
+	/* Wait maximum 1 ms until written values are applied */
+	for (i = 0; i < loops_per_jiffy / 1000 * HZ; i++)
+		if (__raw_readl(stat_addr) & mask) {
+			__raw_writel(mask, stat_addr);
+			return;
+		}
+
+	panic("MCT hangs after writing %d (addr:0x%08x)\n", value, (u32)addr);
+}
+
+/* Clocksource handling */
+static void exynos4_mct_frc_start(u32 hi, u32 lo)
+{
+	u32 reg;
+
+	exynos4_mct_write(lo, EXYNOS4_MCT_G_CNT_L);
+	exynos4_mct_write(hi, EXYNOS4_MCT_G_CNT_U);
+
+	reg = __raw_readl(EXYNOS4_MCT_G_TCON);
+	reg |= MCT_G_TCON_START;
+	exynos4_mct_write(reg, EXYNOS4_MCT_G_TCON);
+}
+
+static cycle_t exynos4_frc_read(struct clocksource *cs)
+{
+	unsigned int lo, hi;
+	u32 hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+
+	do {
+		hi = hi2;
+		lo = __raw_readl(EXYNOS4_MCT_G_CNT_L);
+		hi2 = __raw_readl(EXYNOS4_MCT_G_CNT_U);
+	} while (hi != hi2);
+
+	return ((cycle_t)hi << 32) | lo;
+}
+
+struct clocksource mct_frc = {
+	.name		= "mct-frc",
+	.rating		= 400,
+	.read		= exynos4_frc_read,
+	.mask		= CLOCKSOURCE_MASK(64),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init exynos4_clocksource_init(void)
+{
+	exynos4_mct_frc_start(0, 0);
+
+	if (clocksource_register_hz(&mct_frc, clk_rate))
+		panic("%s: can't register clocksource\n", mct_frc.name);
+}
+
+static void exynos4_mct_comp0_stop(void)
+{
+	unsigned int tcon;
+
+	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+	tcon &= ~(MCT_G_TCON_COMP0_ENABLE | MCT_G_TCON_COMP0_AUTO_INC);
+
+	exynos4_mct_write(tcon, EXYNOS4_MCT_G_TCON);
+	exynos4_mct_write(0, EXYNOS4_MCT_G_INT_ENB);
+}
+
+static void exynos4_mct_comp0_start(enum clock_event_mode mode,
+				    unsigned long cycles)
+{
+	unsigned int tcon;
+	cycle_t comp_cycle;
+
+	tcon = __raw_readl(EXYNOS4_MCT_G_TCON);
+
+	if (mode == CLOCK_EVT_MODE_PERIODIC) {
+		tcon |= MCT_G_TCON_COMP0_AUTO_INC;
+		exynos4_mct_write(cycles, EXYNOS4_MCT_G_COMP0_ADD_INCR);
+	}
+
+	comp_cycle = exynos4_frc_read(&mct_frc) + cycles;
+	exynos4_mct_write((u32)comp_cycle, EXYNOS4_MCT_G_COMP0_L);
+	exynos4_mct_write((u32)(comp_cycle >> 32), EXYNOS4_MCT_G_COMP0_U);
+
+	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_ENB);
+
+	tcon |= MCT_G_TCON_COMP0_ENABLE;
+	exynos4_mct_write(tcon , EXYNOS4_MCT_G_TCON);
+}
+
+static int exynos4_comp_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	exynos4_mct_comp0_start(evt->mode, cycles);
+
+	return 0;
+}
+
+static void exynos4_comp_set_mode(enum clock_event_mode mode,
+				  struct clock_event_device *evt)
+{
+	exynos4_mct_comp0_stop();
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_mct_comp0_start(mode, clk_cnt_per_tick);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device mct_comp_device = {
+	.name		= "mct-comp",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 250,
+	.set_next_event	= exynos4_comp_set_next_event,
+	.set_mode	= exynos4_comp_set_mode,
+};
+
+static irqreturn_t exynos4_mct_comp_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	exynos4_mct_write(0x1, EXYNOS4_MCT_G_INT_CSTAT);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mct_comp_event_irq = {
+	.name		= "mct_comp_irq",
+	.flags		= IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= exynos4_mct_comp_isr,
+	.dev_id		= &mct_comp_device,
+};
+
+static void exynos4_clockevent_init(void)
+{
+	clk_cnt_per_tick = clk_rate / 2	/ HZ;
+
+	clockevents_calc_mult_shift(&mct_comp_device, clk_rate / 2, 5);
+	mct_comp_device.max_delta_ns =
+		clockevent_delta2ns(0xffffffff, &mct_comp_device);
+	mct_comp_device.min_delta_ns =
+		clockevent_delta2ns(0xf, &mct_comp_device);
+	mct_comp_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&mct_comp_device);
+
+	setup_irq(IRQ_MCT_G0, &mct_comp_event_irq);
+}
+
+#ifdef CONFIG_LOCAL_TIMERS
+/* Clock event handling */
+static void exynos4_mct_tick_stop(struct mct_clock_event_device *mevt)
+{
+	unsigned long tmp;
+	unsigned long mask = MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START;
+	void __iomem *addr = mevt->base + MCT_L_TCON_OFFSET;
+
+	tmp = __raw_readl(addr);
+	if (tmp & mask) {
+		tmp &= ~mask;
+		exynos4_mct_write(tmp, addr);
+	}
+}
+
+static void exynos4_mct_tick_start(unsigned long cycles,
+				   struct mct_clock_event_device *mevt)
+{
+	unsigned long tmp;
+
+	exynos4_mct_tick_stop(mevt);
+
+	tmp = (1 << 31) | cycles;	/* MCT_L_UPDATE_ICNTB */
+
+	/* update interrupt count buffer */
+	exynos4_mct_write(tmp, mevt->base + MCT_L_ICNTB_OFFSET);
+
+	/* enable MCT tick interrupt */
+	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_ENB_OFFSET);
+
+	tmp = __raw_readl(mevt->base + MCT_L_TCON_OFFSET);
+	tmp |= MCT_L_TCON_INT_START | MCT_L_TCON_TIMER_START |
+	       MCT_L_TCON_INTERVAL_MODE;
+	exynos4_mct_write(tmp, mevt->base + MCT_L_TCON_OFFSET);
+}
+
+static int exynos4_tick_set_next_event(unsigned long cycles,
+				       struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
+
+	exynos4_mct_tick_start(cycles, mevt);
+
+	return 0;
+}
+
+static inline void exynos4_tick_set_mode(enum clock_event_mode mode,
+					 struct clock_event_device *evt)
+{
+	struct mct_clock_event_device *mevt = &mct_tick[smp_processor_id()];
+
+	exynos4_mct_tick_stop(mevt);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_mct_tick_start(clk_cnt_per_tick, mevt);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static irqreturn_t exynos4_mct_tick_isr(int irq, void *dev_id)
+{
+	struct mct_clock_event_device *mevt = dev_id;
+	struct clock_event_device *evt = mevt->evt;
+
+	/*
+	 * This is for supporting oneshot mode.
+	 * Mct would generate interrupt periodically
+	 * without explicit stopping.
+	 */
+	if (evt->mode != CLOCK_EVT_MODE_PERIODIC)
+		exynos4_mct_tick_stop(mevt);
+
+	/* Clear the MCT tick interrupt */
+	exynos4_mct_write(0x1, mevt->base + MCT_L_INT_CSTAT_OFFSET);
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mct_tick0_event_irq = {
+	.name		= "mct_tick0_irq",
+	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
+	.handler	= exynos4_mct_tick_isr,
+};
+
+static struct irqaction mct_tick1_event_irq = {
+	.name		= "mct_tick1_irq",
+	.flags		= IRQF_TIMER | IRQF_NOBALANCING,
+	.handler	= exynos4_mct_tick_isr,
+};
+
+static void exynos4_mct_tick_init(struct clock_event_device *evt)
+{
+	unsigned int cpu = smp_processor_id();
+
+	mct_tick[cpu].evt = evt;
+
+	if (cpu == 0) {
+		mct_tick[cpu].base = EXYNOS4_MCT_L0_BASE;
+		evt->name = "mct_tick0";
+	} else {
+		mct_tick[cpu].base = EXYNOS4_MCT_L1_BASE;
+		evt->name = "mct_tick1";
+	}
+
+	evt->cpumask = cpumask_of(cpu);
+	evt->set_next_event = exynos4_tick_set_next_event;
+	evt->set_mode = exynos4_tick_set_mode;
+	evt->features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT;
+	evt->rating = 450;
+
+	clockevents_calc_mult_shift(evt, clk_rate / 2, 5);
+	evt->max_delta_ns =
+		clockevent_delta2ns(0x7fffffff, evt);
+	evt->min_delta_ns =
+		clockevent_delta2ns(0xf, evt);
+
+	clockevents_register_device(evt);
+
+	exynos4_mct_write(0x1, mct_tick[cpu].base + MCT_L_TCNTB_OFFSET);
+
+	if (cpu == 0) {
+		mct_tick0_event_irq.dev_id = &mct_tick[cpu];
+		setup_irq(IRQ_MCT_L0, &mct_tick0_event_irq);
+	} else {
+		mct_tick1_event_irq.dev_id = &mct_tick[cpu];
+		irq_set_affinity(IRQ_MCT1, cpumask_of(1));
+		setup_irq(IRQ_MCT_L1, &mct_tick1_event_irq);
+	}
+}
+
+/* Setup the local clock events for a CPU */
+void __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	exynos4_mct_tick_init(evt);
+}
+
+int local_timer_ack(void)
+{
+	return 0;
+}
+
+#endif /* CONFIG_LOCAL_TIMERS */
+
+static void __init exynos4_timer_resources(void)
+{
+	struct clk *mct_clk;
+	mct_clk = clk_get(NULL, "xtal");
+
+	clk_rate = clk_get_rate(mct_clk);
+}
+
+static void __init exynos4_timer_init(void)
+{
+	exynos4_timer_resources();
+	exynos4_clocksource_init();
+	exynos4_clockevent_init();
+}
+
+struct sys_timer exynos4_timer = {
+	.init		= exynos4_timer_init,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/platsmp.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/platsmp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/platsmp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,172 @@
+/* linux/arch/arm/mach-exynos4/platsmp.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Cloned from linux/arch/arm/mach-vexpress/platsmp.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/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_scu.h>
+#include <asm/unified.h>
+
+#include <mach/hardware.h>
+#include <mach/regs-clock.h>
+
+extern void exynos4_secondary_startup(void);
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+
+volatile int __cpuinitdata pen_release = -1;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static void __iomem *scu_base_addr(void)
+{
+	return (void __iomem *)(S5P_VA_SCU);
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * 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_secondary_init(0);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * 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);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	smp_cross_call(cpumask_of(cpu), 1);
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+/*
+ * 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)
+{
+	void __iomem *scu_base = scu_base_addr();
+	unsigned int i, ncores;
+
+	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
+
+	/* sanity check */
+	if (ncores > NR_CPUS) {
+		printk(KERN_WARNING
+		       "EXYNOS4: no. of cores (%d) greater than configured "
+		       "maximum of %d - clipping\n",
+		       ncores, NR_CPUS);
+		ncores = NR_CPUS;
+	}
+
+	for (i = 0; i < ncores; i++)
+		set_cpu_possible(i, true);
+}
+
+void __init platform_smp_prepare_cpus(unsigned int max_cpus)
+{
+	int i;
+
+	/*
+	 * 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);
+
+	scu_enable(scu_base_addr());
+
+	/*
+	 * Write the address of secondary startup into the
+	 * system-wide flags register. The boot monitor waits
+	 * until it receives a soft interrupt, and then the
+	 * secondary CPU branches to this address.
+	 */
+	__raw_writel(BSYM(virt_to_phys(exynos4_secondary_startup)), S5P_VA_SYSRAM);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/pm.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,420 @@
+/* linux/arch/arm/mach-exynos4/pm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 - Power Management support
+ *
+ * Based on arch/arm/mach-s3c2410/pm.c
+ * Copyright (c) 2006 Simtec Electronics
+ *	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.
+*/
+
+#include <linux/init.h>
+#include <linux/suspend.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include <plat/cpu.h>
+#include <plat/pm.h>
+
+#include <mach/regs-irq.h>
+#include <mach/regs-gpio.h>
+#include <mach/regs-clock.h>
+#include <mach/regs-pmu.h>
+#include <mach/pm-core.h>
+
+static struct sleep_save exynos4_sleep[] = {
+	{ .reg = S5P_ARM_CORE0_LOWPWR			, .val = 0x2, },
+	{ .reg = S5P_DIS_IRQ_CORE0			, .val = 0x0, },
+	{ .reg = S5P_DIS_IRQ_CENTRAL0			, .val = 0x0, },
+	{ .reg = S5P_ARM_CORE1_LOWPWR			, .val = 0x2, },
+	{ .reg = S5P_DIS_IRQ_CORE1			, .val = 0x0, },
+	{ .reg = S5P_DIS_IRQ_CENTRAL1			, .val = 0x0, },
+	{ .reg = S5P_ARM_COMMON_LOWPWR			, .val = 0x2, },
+	{ .reg = S5P_L2_0_LOWPWR			, .val = 0x3, },
+	{ .reg = S5P_L2_1_LOWPWR			, .val = 0x3, },
+	{ .reg = S5P_CMU_ACLKSTOP_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_SCLKSTOP_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_APLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_MPLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_VPLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_EPLL_SYSCLK_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_GPS_ALIVE_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_GPSALIVE_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_CAM_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_TV_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_MFC_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_G3D_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_LCD0_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_LCD1_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_MAUDIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_CLKSTOP_GPS_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_CAM_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_TV_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_MFC_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_G3D_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_LCD0_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_LCD1_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_MAUDIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CMU_RESET_GPS_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_TOP_BUS_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_TOP_RETENTION_LOWPWR		, .val = 0x1, },
+	{ .reg = S5P_TOP_PWR_LOWPWR			, .val = 0x3, },
+	{ .reg = S5P_LOGIC_RESET_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_ONENAND_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_MODIMIF_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_G2D_ACP_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_USBOTG_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_HSMMC_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_CSSYS_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_SECSS_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_PCIE_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_SATA_MEM_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_DRAM_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_MAUDIO_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_GPIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_UART_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_MMCA_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_MMCB_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_EBIA_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_EBIB_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_ISOLATION_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_PAD_RETENTION_ALV_SEL_LOWPWR	, .val = 0x0, },
+	{ .reg = S5P_XUSBXTI_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_XXTI_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_EXT_REGULATOR_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_GPIO_MODE_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_GPIO_MODE_MAUDIO_LOWPWR		, .val = 0x0, },
+	{ .reg = S5P_CAM_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_TV_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_MFC_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_G3D_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_LCD0_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_LCD1_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_MAUDIO_LOWPWR			, .val = 0x0, },
+	{ .reg = S5P_GPS_LOWPWR				, .val = 0x0, },
+	{ .reg = S5P_GPS_ALIVE_LOWPWR			, .val = 0x0, },
+};
+
+static struct sleep_save exynos4_set_clksrc[] = {
+	{ .reg = S5P_CLKSRC_MASK_TOP			, .val = 0x00000001, },
+	{ .reg = S5P_CLKSRC_MASK_CAM			, .val = 0x11111111, },
+	{ .reg = S5P_CLKSRC_MASK_TV			, .val = 0x00000111, },
+	{ .reg = S5P_CLKSRC_MASK_LCD0			, .val = 0x00001111, },
+	{ .reg = S5P_CLKSRC_MASK_LCD1			, .val = 0x00001111, },
+	{ .reg = S5P_CLKSRC_MASK_MAUDIO			, .val = 0x00000001, },
+	{ .reg = S5P_CLKSRC_MASK_FSYS			, .val = 0x01011111, },
+	{ .reg = S5P_CLKSRC_MASK_PERIL0			, .val = 0x01111111, },
+	{ .reg = S5P_CLKSRC_MASK_PERIL1			, .val = 0x01110111, },
+	{ .reg = S5P_CLKSRC_MASK_DMC			, .val = 0x00010000, },
+};
+
+static struct sleep_save exynos4_core_save[] = {
+	/* CMU side */
+	SAVE_ITEM(S5P_CLKDIV_LEFTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_LEFTBUS),
+	SAVE_ITEM(S5P_CLKDIV_RIGHTBUS),
+	SAVE_ITEM(S5P_CLKGATE_IP_RIGHTBUS),
+	SAVE_ITEM(S5P_EPLL_CON0),
+	SAVE_ITEM(S5P_EPLL_CON1),
+	SAVE_ITEM(S5P_VPLL_CON0),
+	SAVE_ITEM(S5P_VPLL_CON1),
+	SAVE_ITEM(S5P_CLKSRC_TOP0),
+	SAVE_ITEM(S5P_CLKSRC_TOP1),
+	SAVE_ITEM(S5P_CLKSRC_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MFC),
+	SAVE_ITEM(S5P_CLKSRC_IMAGE),
+	SAVE_ITEM(S5P_CLKSRC_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_CAM),
+	SAVE_ITEM(S5P_CLKDIV_TV),
+	SAVE_ITEM(S5P_CLKDIV_MFC),
+	SAVE_ITEM(S5P_CLKDIV_G3D),
+	SAVE_ITEM(S5P_CLKDIV_IMAGE),
+	SAVE_ITEM(S5P_CLKDIV_LCD0),
+	SAVE_ITEM(S5P_CLKDIV_LCD1),
+	SAVE_ITEM(S5P_CLKDIV_MAUDIO),
+	SAVE_ITEM(S5P_CLKDIV_FSYS0),
+	SAVE_ITEM(S5P_CLKDIV_FSYS1),
+	SAVE_ITEM(S5P_CLKDIV_FSYS2),
+	SAVE_ITEM(S5P_CLKDIV_FSYS3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL0),
+	SAVE_ITEM(S5P_CLKDIV_PERIL1),
+	SAVE_ITEM(S5P_CLKDIV_PERIL2),
+	SAVE_ITEM(S5P_CLKDIV_PERIL3),
+	SAVE_ITEM(S5P_CLKDIV_PERIL4),
+	SAVE_ITEM(S5P_CLKDIV_PERIL5),
+	SAVE_ITEM(S5P_CLKDIV_TOP),
+	SAVE_ITEM(S5P_CLKSRC_MASK_CAM),
+	SAVE_ITEM(S5P_CLKSRC_MASK_TV),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_LCD1),
+	SAVE_ITEM(S5P_CLKSRC_MASK_MAUDIO),
+	SAVE_ITEM(S5P_CLKSRC_MASK_FSYS),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL0),
+	SAVE_ITEM(S5P_CLKSRC_MASK_PERIL1),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_CAM),
+	SAVE_ITEM(S5P_CLKGATE_IP_TV),
+	SAVE_ITEM(S5P_CLKGATE_IP_MFC),
+	SAVE_ITEM(S5P_CLKGATE_IP_G3D),
+	SAVE_ITEM(S5P_CLKGATE_IP_IMAGE),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD0),
+	SAVE_ITEM(S5P_CLKGATE_IP_LCD1),
+	SAVE_ITEM(S5P_CLKGATE_IP_FSYS),
+	SAVE_ITEM(S5P_CLKGATE_IP_GPS),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIL),
+	SAVE_ITEM(S5P_CLKGATE_IP_PERIR),
+	SAVE_ITEM(S5P_CLKGATE_BLOCK),
+	SAVE_ITEM(S5P_CLKSRC_MASK_DMC),
+	SAVE_ITEM(S5P_CLKSRC_DMC),
+	SAVE_ITEM(S5P_CLKDIV_DMC0),
+	SAVE_ITEM(S5P_CLKDIV_DMC1),
+	SAVE_ITEM(S5P_CLKGATE_IP_DMC),
+	SAVE_ITEM(S5P_CLKSRC_CPU),
+	SAVE_ITEM(S5P_CLKDIV_CPU),
+	SAVE_ITEM(S5P_CLKGATE_SCLKCPU),
+	SAVE_ITEM(S5P_CLKGATE_IP_CPU),
+	/* GIC side */
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x000),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x004),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x008),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x00C),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x014),
+	SAVE_ITEM(S5P_VA_GIC_CPU + 0x018),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x000),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x004),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x100),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x104),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x108),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x300),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x304),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x308),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x400),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x404),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x408),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x40C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x410),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x414),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x418),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x41C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x420),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x424),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x428),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x42C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x430),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x434),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x438),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x43C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x440),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x444),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x448),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x44C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x450),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x454),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x458),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x45C),
+
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x800),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x804),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x808),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x80C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x810),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x814),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x818),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x81C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x820),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x824),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x828),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x82C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x830),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x834),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x838),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x83C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x840),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x844),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x848),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x84C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x850),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x854),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x858),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0x85C),
+
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC00),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC04),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC08),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC0C),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC10),
+	SAVE_ITEM(S5P_VA_GIC_DIST + 0xC14),
+
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x000),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x010),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x020),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x030),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x040),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x050),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x060),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x070),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x080),
+	SAVE_ITEM(S5P_VA_COMBINER_BASE + 0x090),
+};
+
+static struct sleep_save exynos4_l2cc_save[] = {
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_PREFETCH_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_POWER_CTRL),
+	SAVE_ITEM(S5P_VA_L2CC + L2X0_AUX_CTRL),
+};
+
+void exynos4_cpu_suspend(void)
+{
+	unsigned long tmp;
+	unsigned long mask = 0xFFFFFFFF;
+
+	/* Setting Central Sequence Register for power down mode */
+
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
+	tmp &= ~(S5P_CENTRAL_LOWPWR_CFG);
+	__raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
+
+	/* Setting Central Sequence option Register */
+
+	tmp = __raw_readl(S5P_CENTRAL_SEQ_OPTION);
+	tmp &= ~(S5P_USE_MASK);
+	tmp |= S5P_USE_STANDBY_WFI0;
+	__raw_writel(tmp, S5P_CENTRAL_SEQ_OPTION);
+
+	/* Clear all interrupt pending to avoid early wakeup */
+
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x280));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x284));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x288));
+
+	/* Disable all interrupt */
+
+	__raw_writel(0x0, (S5P_VA_GIC_CPU + 0x000));
+	__raw_writel(0x0, (S5P_VA_GIC_DIST + 0x000));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x184));
+	__raw_writel(mask, (S5P_VA_GIC_DIST + 0x188));
+
+	outer_flush_all();
+
+	/* issue the standby signal into the pm unit. */
+	cpu_do_idle();
+
+	/* we should never get past here */
+	panic("sleep resumed to originator?");
+}
+
+static void exynos4_pm_prepare(void)
+{
+	u32 tmp;
+
+	s3c_pm_do_save(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+	s3c_pm_do_save(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+
+	tmp = __raw_readl(S5P_INFORM1);
+
+	/* Set value of power down register for sleep mode */
+
+	s3c_pm_do_restore_core(exynos4_sleep, ARRAY_SIZE(exynos4_sleep));
+	__raw_writel(S5P_CHECK_SLEEP, S5P_INFORM1);
+
+	/* ensure at least INFORM0 has the resume address */
+
+	__raw_writel(virt_to_phys(s3c_cpu_resume), S5P_INFORM0);
+
+	/* Before enter central sequence mode, clock src register have to set */
+
+	s3c_pm_do_restore_core(exynos4_set_clksrc, ARRAY_SIZE(exynos4_set_clksrc));
+
+}
+
+static int exynos4_pm_add(struct sys_device *sysdev)
+{
+	pm_cpu_prep = exynos4_pm_prepare;
+	pm_cpu_sleep = exynos4_cpu_suspend;
+
+	return 0;
+}
+
+/* This function copy from linux/arch/arm/kernel/smp_scu.c */
+
+void exynos4_scu_enable(void __iomem *scu_base)
+{
+	u32 scu_ctrl;
+
+	scu_ctrl = __raw_readl(scu_base);
+	/* already enabled? */
+	if (scu_ctrl & 1)
+		return;
+
+	scu_ctrl |= 1;
+	__raw_writel(scu_ctrl, scu_base);
+
+	/*
+	 * Ensure that the data accessed by CPU0 before the SCU was
+	 * initialised is visible to the other CPUs.
+	 */
+	flush_cache_all();
+}
+
+static int exynos4_pm_resume(struct sys_device *dev)
+{
+	/* For release retention */
+
+	__raw_writel((1 << 28), S5P_PAD_RET_MAUDIO_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_GPIO_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_UART_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_MMCA_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_MMCB_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_EBIA_OPTION);
+	__raw_writel((1 << 28), S5P_PAD_RET_EBIB_OPTION);
+
+	s3c_pm_do_restore_core(exynos4_core_save, ARRAY_SIZE(exynos4_core_save));
+
+	exynos4_scu_enable(S5P_VA_SCU);
+
+#ifdef CONFIG_CACHE_L2X0
+	s3c_pm_do_restore_core(exynos4_l2cc_save, ARRAY_SIZE(exynos4_l2cc_save));
+	outer_inv_all();
+	/* enable L2X0*/
+	writel_relaxed(1, S5P_VA_L2CC + L2X0_CTRL);
+#endif
+
+	return 0;
+}
+
+static struct sysdev_driver exynos4_pm_driver = {
+	.add		= exynos4_pm_add,
+	.resume		= exynos4_pm_resume,
+};
+
+static __init int exynos4_pm_drvinit(void)
+{
+	unsigned int tmp;
+
+	s3c_pm_init();
+
+	/* All wakeup disable */
+
+	tmp = __raw_readl(S5P_WAKEUP_MASK);
+	tmp |= ((0xFF << 8) | (0x1F << 1));
+	__raw_writel(tmp, S5P_WAKEUP_MASK);
+
+	return sysdev_driver_register(&exynos4_sysclass, &exynos4_pm_driver);
+}
+arch_initcall(exynos4_pm_drvinit);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-fimc.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-fimc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-fimc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * Exynos4 camera interface GPIO configuration.
+ *
+ * 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 <plat/gpio-cfg.h>
+#include <plat/camport.h>
+
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id)
+{
+	u32 gpio8, gpio5;
+	u32 sfn;
+	int ret;
+
+	switch (id) {
+	case S5P_CAMPORT_A:
+		gpio8 = EXYNOS4_GPJ0(0); /* PCLK, VSYNC, HREF, DATA[0:4] */
+		gpio5 = EXYNOS4_GPJ1(0); /* DATA[5:7], CLKOUT, FIELD */
+		sfn = S3C_GPIO_SFN(2);
+		break;
+
+	case S5P_CAMPORT_B:
+		gpio8 = EXYNOS4_GPE0(0); /* DATA[0:7] */
+		gpio5 = EXYNOS4_GPE1(0); /* PCLK, VSYNC, HREF, CLKOUT, FIELD */
+		sfn = S3C_GPIO_SFN(3);
+		break;
+
+	default:
+		WARN(1, "Wrong camport id: %d\n", id);
+		return -EINVAL;
+	}
+
+	ret = s3c_gpio_cfgall_range(gpio8, 8, sfn, S3C_GPIO_PULL_UP);
+	if (ret)
+		return ret;
+
+	return s3c_gpio_cfgall_range(gpio5, 5, sfn, S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c0.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c0.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c0.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c0.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * I2C0 GPIO configuration.
+ *
+ * Based on plat-s3c64xx/setup-i2c0.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.
+*/
+
+struct platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c0_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD1(0), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c1.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c1.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c1.c
+ *
+ * Copyright (C) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C1 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c1_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD1(2), 2,
+			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c2.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c2.c
+ *
+ * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C2 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c2_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPA0(6), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c3.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c3.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c3.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c3.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C3 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c3_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPA1(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c4.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c4.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c4.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c4.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c4.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C4 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c4_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPB(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c5.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c5.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c5.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c5.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c5.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C5 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c5_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPB(6), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c6.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c6.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c6.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c6.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c6.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C6 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c6_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPC1(3), 2,
+			      S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c7.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c7.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-i2c7.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-i2c7.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/arm/mach-exynos4/setup-i2c7.c
+ *
+ * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ *
+ * I2C7 GPIO configuration.
+ *
+ * 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 platform_device; /* don't need the contents */
+
+#include <linux/gpio.h>
+#include <plat/iic.h>
+#include <plat/gpio-cfg.h>
+
+void s3c_i2c7_cfg_gpio(struct platform_device *dev)
+{
+	s3c_gpio_cfgall_range(EXYNOS4_GPD0(2), 2,
+			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-keypad.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-keypad.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-keypad.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-keypad.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,35 @@
+/* linux/arch/arm/mach-exynos4/setup-keypad.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * GPIO configuration for Exynos4 KeyPad device
+ *
+ * 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 <plat/gpio-cfg.h>
+
+void samsung_keypad_cfg_gpio(unsigned int rows, unsigned int cols)
+{
+	/* Keypads can be of various combinations, Just making sure */
+
+	if (rows > 8) {
+		/* Set all the necessary GPX2 pins: KP_ROW[0~7] */
+		s3c_gpio_cfgrange_nopull(EXYNOS4_GPX2(0), 8, S3C_GPIO_SFN(3));
+
+		/* Set all the necessary GPX3 pins: KP_ROW[8~] */
+		s3c_gpio_cfgrange_nopull(EXYNOS4_GPX3(0), (rows - 8),
+					 S3C_GPIO_SFN(3));
+	} else {
+		/* Set all the necessary GPX2 pins: KP_ROW[x] */
+		s3c_gpio_cfgrange_nopull(EXYNOS4_GPX2(0), rows,
+					 S3C_GPIO_SFN(3));
+	}
+
+	/* Set all the necessary GPX1 pins to special-function 3: KP_COL[x] */
+	s3c_gpio_cfgrange_nopull(EXYNOS4_GPX1(0), cols, S3C_GPIO_SFN(3));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-sdhci.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-sdhci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-sdhci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,69 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - 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>
+
+/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
+
+char *exynos4_hsmmc_clksrcs[4] = {
+	[0] = NULL,
+	[1] = NULL,
+	[2] = "sclk_mmc",	/* mmc_bus */
+	[3] = NULL,
+};
+
+void exynos4_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
+				  struct mmc_ios *ios, struct mmc_card *card)
+{
+	u32 ctrl2, ctrl3;
+
+	/* don't need to alter anything according to card-type */
+
+	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
+
+	/* select base clock source to HCLK */
+
+	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
+
+	/*
+	 * clear async mode, enable conflict mask, rx feedback ctrl, SD
+	 * clk hold and no use debounce count
+	 */
+
+	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
+		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
+		  S3C_SDHCI_CTRL2_ENFBCLKRX |
+		  S3C_SDHCI_CTRL2_DFCNT_NONE |
+		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
+
+	/* Tx and Rx feedback clock delay control */
+
+	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);
+
+	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
+	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/setup-sdhci-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,152 @@
+/* linux/arch/arm/mach-exynos4/setup-sdhci-gpio.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 - 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 <linux/gpio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/card.h>
+
+#include <plat/gpio-cfg.h>
+#include <plat/regs-sdhci.h>
+#include <plat/sdhci.h>
+
+void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK0[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK0(0); gpio < EXYNOS4_GPK0(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	switch (width) {
+	case 8:
+		for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+			/* Data pin GPK1[3:6] to special-function 3 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	case 4:
+		for (gpio = EXYNOS4_GPK0(3); gpio <= EXYNOS4_GPK0(6); gpio++) {
+			/* Data pin GPK0[3:6] to special-function 2 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	default:
+		break;
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK0(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK0(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK1[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK1(0); gpio < EXYNOS4_GPK1(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	for (gpio = EXYNOS4_GPK1(3); gpio <= EXYNOS4_GPK1(6); gpio++) {
+		/* Data pin GPK1[3:6] to special-function 2 */
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK1(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK1(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK2[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK2(0); gpio < EXYNOS4_GPK2(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	switch (width) {
+	case 8:
+		for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
+			/* Data pin GPK3[3:6] to special-function 3 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	case 4:
+		for (gpio = EXYNOS4_GPK2(3); gpio <= EXYNOS4_GPK2(6); gpio++) {
+			/* Data pin GPK2[3:6] to special-function 2 */
+			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+		}
+	default:
+		break;
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK2(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK2(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
+
+void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
+{
+	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
+	unsigned int gpio;
+
+	/* Set all the necessary GPK3[0:1] pins to special-function 2 */
+	for (gpio = EXYNOS4_GPK3(0); gpio < EXYNOS4_GPK3(2); gpio++) {
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	for (gpio = EXYNOS4_GPK3(3); gpio <= EXYNOS4_GPK3(6); gpio++) {
+		/* Data pin GPK3[3:6] to special-function 2 */
+		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+
+	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
+		s3c_gpio_cfgpin(EXYNOS4_GPK3(2), S3C_GPIO_SFN(2));
+		s3c_gpio_setpull(EXYNOS4_GPK3(2), S3C_GPIO_PULL_UP);
+		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/sleep.S linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,76 @@
+/* linux/arch/arm/mach-exynos4/sleep.S
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4210 power Manager (Suspend-To-RAM) support
+ * Based on S3C2410 sleep code by:
+ *	Ben Dooks, (c) 2004 Simtec Electronics
+ *
+ * Based on PXA/SA1100 sleep code by:
+ *	Nicolas Pitre, (c) 2002 Monta Vista Software Inc
+ *	Cliff Brake, (c) 2001
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <asm/memory.h>
+
+	.text
+
+	/*
+	 * s3c_cpu_save
+	 *
+	 * entry:
+	 *	r1 = v:p offset
+	 */
+
+ENTRY(s3c_cpu_save)
+
+	stmfd	sp!, { r3 - r12, lr }
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
+
+	ldr	r0, =pm_cpu_sleep
+	ldr	r0, [ r0 ]
+	mov	pc, r0
+
+resume_with_mmu:
+	ldmfd	sp!, { r3 - r12, pc }
+
+	.ltorg
+
+	/*
+	 * sleep magic, to allow the bootloader to check for an valid
+	 * image to resume to. Must be the first word before the
+	 * s3c_cpu_resume entry.
+	 */
+
+	.word	0x2bedf00d
+
+	/*
+	 * s3c_cpu_resume
+	 *
+	 * resume code entry for bootloader to call
+	 *
+	 * we must put this code here in the data segment as we have no
+	 * other way of restoring the stack pointer after sleep, and we
+	 * must not write to the code segment (code is read-only)
+	 */
+
+ENTRY(s3c_cpu_resume)
+	b	cpu_resume
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/time.c linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/time.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-exynos4/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-exynos4/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,299 @@
+/* linux/arch/arm/mach-exynos4/time.c
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * EXYNOS4 (and compatible) HRT support
+ * PWM 2/4 is used for this feature
+ *
+ * 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/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+
+#include <mach/map.h>
+#include <plat/regs-timer.h>
+#include <asm/mach/time.h>
+
+static unsigned long clock_count_per_tick;
+
+static struct clk *tin2;
+static struct clk *tin4;
+static struct clk *tdiv2;
+static struct clk *tdiv4;
+static struct clk *timerclk;
+
+static void exynos4_pwm_stop(unsigned int pwm_id)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (pwm_id) {
+	case 2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+	case 4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+	default:
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void exynos4_pwm_init(unsigned int pwm_id, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	/* timers reload after counting zero, so reduce the count by 1 */
+	tcnt--;
+
+	/* ensure timer is stopped... */
+	switch (pwm_id) {
+	case 2:
+		tcon &= ~(0xf<<12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+
+		__raw_writel(tcnt, S3C2410_TCNTB(2));
+		__raw_writel(tcnt, S3C2410_TCMPB(2));
+		__raw_writel(tcon, S3C2410_TCON);
+
+		break;
+	case 4:
+		tcon &= ~(7<<20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+
+		__raw_writel(tcnt, S3C2410_TCNTB(4));
+		__raw_writel(tcnt, S3C2410_TCMPB(4));
+		__raw_writel(tcon, S3C2410_TCON);
+
+		break;
+	default:
+		break;
+	}
+}
+
+static inline void exynos4_pwm_start(unsigned int pwm_id, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (pwm_id) {
+	case 2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+	case 4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+	default:
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int exynos4_pwm_set_next_event(unsigned long cycles,
+					struct clock_event_device *evt)
+{
+	exynos4_pwm_init(2, cycles);
+	exynos4_pwm_start(2, 0);
+	return 0;
+}
+
+static void exynos4_pwm_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	exynos4_pwm_stop(2);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		exynos4_pwm_init(2, clock_count_per_tick);
+		exynos4_pwm_start(2, 1);
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+}
+
+static struct clock_event_device pwm_event_device = {
+	.name		= "pwm_timer2",
+	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.shift		= 32,
+	.set_next_event	= exynos4_pwm_set_next_event,
+	.set_mode	= exynos4_pwm_set_mode,
+};
+
+irqreturn_t exynos4_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = &pwm_event_device;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction exynos4_clock_event_irq = {
+	.name		= "pwm_timer2_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= exynos4_clock_event_isr,
+};
+
+static void __init exynos4_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	/* configure clock tick */
+
+	tscaler = clk_get_parent(tdiv2);
+
+	clk_set_rate(tscaler, pclk / 2);
+	clk_set_rate(tdiv2, pclk / 2);
+	clk_set_parent(tin2, tdiv2);
+
+	clock_rate = clk_get_rate(tin2);
+
+	clock_count_per_tick = clock_rate / HZ;
+
+	pwm_event_device.mult =
+		div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
+	pwm_event_device.max_delta_ns =
+		clockevent_delta2ns(-1, &pwm_event_device);
+	pwm_event_device.min_delta_ns =
+		clockevent_delta2ns(1, &pwm_event_device);
+
+	pwm_event_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&pwm_event_device);
+
+	setup_irq(IRQ_TIMER2, &exynos4_clock_event_irq);
+}
+
+static cycle_t exynos4_pwm4_read(struct clocksource *cs)
+{
+	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
+}
+
+static void exynos4_pwm4_resume(struct clocksource *cs)
+{
+	unsigned long pclk;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv4, pclk / 2);
+	clk_set_parent(tin4, tdiv4);
+
+	exynos4_pwm_init(4, ~0);
+	exynos4_pwm_start(4, 1);
+}
+
+struct clocksource pwm_clocksource = {
+	.name		= "pwm_timer4",
+	.rating		= 250,
+	.read		= exynos4_pwm4_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
+#ifdef CONFIG_PM
+	.resume		= exynos4_pwm4_resume,
+#endif
+};
+
+static void __init exynos4_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv4, pclk / 2);
+	clk_set_parent(tin4, tdiv4);
+
+	clock_rate = clk_get_rate(tin4);
+
+	exynos4_pwm_init(4, ~0);
+	exynos4_pwm_start(4, 1);
+
+	if (clocksource_register_hz(&pwm_clocksource, clock_rate))
+		panic("%s: can't register clocksource\n", pwm_clocksource.name);
+}
+
+static void __init exynos4_timer_resources(void)
+{
+	struct platform_device tmpdev;
+
+	tmpdev.dev.bus = &platform_bus_type;
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for system timer");
+
+	clk_enable(timerclk);
+
+	tmpdev.id = 2;
+	tin2 = clk_get(&tmpdev.dev, "pwm-tin");
+	if (IS_ERR(tin2))
+		panic("failed to get pwm-tin2 clock for system timer");
+
+	tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
+	if (IS_ERR(tdiv2))
+		panic("failed to get pwm-tdiv2 clock for system timer");
+	clk_enable(tin2);
+
+	tmpdev.id = 4;
+	tin4 = clk_get(&tmpdev.dev, "pwm-tin");
+	if (IS_ERR(tin4))
+		panic("failed to get pwm-tin4 clock for system timer");
+
+	tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
+	if (IS_ERR(tdiv4))
+		panic("failed to get pwm-tdiv4 clock for system timer");
+
+	clk_enable(tin4);
+}
+
+static void __init exynos4_timer_init(void)
+{
+#ifdef CONFIG_LOCAL_TIMERS
+	twd_base = S5P_VA_TWD;
+#endif
+
+	exynos4_timer_resources();
+	exynos4_clockevent_init();
+	exynos4_clocksource_init();
+}
+
+struct sys_timer exynos4_timer = {
+	.init		= exynos4_timer_init,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/common.c linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,8 +102,7 @@
 	*CSR_FIQ_DISABLE = -1;
 
 	for (irq = _DC21285_IRQ(0); irq < _DC21285_IRQ(20); irq++) {
-		set_irq_chip(irq, &fb_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &fb_chip, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/dc21285-timer.c linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/dc21285-timer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/dc21285-timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/dc21285-timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,10 +4,11 @@
  *  Copyright (C) 1998 Russell King.
  *  Copyright (C) 1998 Phil Blundell
  */
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
-#include <linux/spinlock.h>
 
 #include <asm/irq.h>
 
@@ -16,32 +17,76 @@
 
 #include "common.h"
 
-/*
- * Footbridge timer 1 support.
- */
-static unsigned long timer1_latch;
+static cycle_t cksrc_dc21285_read(struct clocksource *cs)
+{
+	return cs->mask - *CSR_TIMER2_VALUE;
+}
 
-static unsigned long timer1_gettimeoffset (void)
+static int cksrc_dc21285_enable(struct clocksource *cs)
 {
-	unsigned long value = timer1_latch - *CSR_TIMER1_VALUE;
+	*CSR_TIMER2_LOAD = cs->mask;
+	*CSR_TIMER2_CLR = 0;
+	*CSR_TIMER2_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_DIV16;
+	return 0;
+}
 
-	return ((tick_nsec / 1000) * value) / timer1_latch;
+static void cksrc_dc21285_disable(struct clocksource *cs)
+{
+	*CSR_TIMER2_CNTL = 0;
 }
 
-static irqreturn_t
-timer1_interrupt(int irq, void *dev_id)
+static struct clocksource cksrc_dc21285 = {
+	.name		= "dc21285_timer2",
+	.rating		= 200,
+	.read		= cksrc_dc21285_read,
+	.enable		= cksrc_dc21285_enable,
+	.disable	= cksrc_dc21285_disable,
+	.mask		= CLOCKSOURCE_MASK(24),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void ckevt_dc21285_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *c)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		*CSR_TIMER1_CLR = 0;
+		*CSR_TIMER1_LOAD = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+		*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD |
+				   TIMER_CNTL_DIV16;
+		break;
+
+	default:
+		*CSR_TIMER1_CNTL = 0;
+		break;
+	}
+}
+
+static struct clock_event_device ckevt_dc21285 = {
+	.name		= "dc21285_timer1",
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.rating		= 200,
+	.irq		= IRQ_TIMER1,
+	.set_mode	= ckevt_dc21285_set_mode,
+};
+
+static irqreturn_t timer1_interrupt(int irq, void *dev_id)
 {
+	struct clock_event_device *ce = dev_id;
+
 	*CSR_TIMER1_CLR = 0;
 
-	timer_tick();
+	ce->event_handler(ce);
 
 	return IRQ_HANDLED;
 }
 
 static struct irqaction footbridge_timer_irq = {
-	.name		= "Timer1 timer tick",
+	.name		= "dc21285_timer1",
 	.handler	= timer1_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.dev_id		= &ckevt_dc21285,
 };
 
 /*
@@ -49,16 +94,19 @@
  */
 static void __init footbridge_timer_init(void)
 {
-	timer1_latch = (mem_fclk_21285 + 8 * HZ) / (16 * HZ);
+	struct clock_event_device *ce = &ckevt_dc21285;
 
-	*CSR_TIMER1_CLR  = 0;
-	*CSR_TIMER1_LOAD = timer1_latch;
-	*CSR_TIMER1_CNTL = TIMER_CNTL_ENABLE | TIMER_CNTL_AUTORELOAD | TIMER_CNTL_DIV16;
+	clocksource_register_hz(&cksrc_dc21285, (mem_fclk_21285 + 8) / 16);
 
-	setup_irq(IRQ_TIMER1, &footbridge_timer_irq);
+	setup_irq(ce->irq, &footbridge_timer_irq);
+
+	clockevents_calc_mult_shift(ce, mem_fclk_21285, 5);
+	ce->max_delta_ns = clockevent_delta2ns(0xffffff, ce);
+	ce->min_delta_ns = clockevent_delta2ns(0x000004, ce);
+
+	clockevents_register_device(ce);
 }
 
 struct sys_timer footbridge_timer = {
 	.init		= footbridge_timer_init,
-	.offset		= timer1_gettimeoffset,
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,26 +23,33 @@
  * 0xf9000000	0x50000000	1MB	Cache flush
  * 0xf0000000	0x80000000	16MB	ISA memory
  */
+
+#ifdef CONFIG_MMU
+#define MMU_IO(a, b)	(a)
+#else
+#define MMU_IO(a, b)	(b)
+#endif
+
 #define XBUS_SIZE		0x00100000
-#define XBUS_BASE		0xff800000
+#define XBUS_BASE		MMU_IO(0xff800000, 0x40000000)
 
 #define ARMCSR_SIZE		0x00100000
-#define ARMCSR_BASE		0xfe000000
+#define ARMCSR_BASE		MMU_IO(0xfe000000, 0x42000000)
 
 #define WFLUSH_SIZE		0x00100000
-#define WFLUSH_BASE		0xfd000000
+#define WFLUSH_BASE		MMU_IO(0xfd000000, 0x78000000)
 
 #define PCIIACK_SIZE		0x00100000
-#define PCIIACK_BASE		0xfc000000
+#define PCIIACK_BASE		MMU_IO(0xfc000000, 0x79000000)
 
 #define PCICFG1_SIZE		0x01000000
-#define PCICFG1_BASE		0xfb000000
+#define PCICFG1_BASE		MMU_IO(0xfb000000, 0x7a000000)
 
 #define PCICFG0_SIZE		0x01000000
-#define PCICFG0_BASE		0xfa000000
+#define PCICFG0_BASE		MMU_IO(0xfa000000, 0x7b000000)
 
 #define PCIMEM_SIZE		0x01000000
-#define PCIMEM_BASE		0xf0000000
+#define PCIMEM_BASE		MMU_IO(0xf0000000, 0x80000000)
 
 #define XBUS_LEDS		((volatile unsigned char *)(XBUS_BASE + 0x12000))
 #define XBUS_LED_AMBER		(1 << 0)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/include/mach/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,8 +14,14 @@
 #ifndef __ASM_ARM_ARCH_IO_H
 #define __ASM_ARM_ARCH_IO_H
 
-#define PCIO_SIZE		0x00100000
-#define PCIO_BASE		0xff000000
+#ifdef CONFIG_MMU
+#define MMU_IO(a, b)	(a)
+#else
+#define MMU_IO(a, b)	(b)
+#endif
+
+#define PCIO_SIZE       0x00100000
+#define PCIO_BASE       MMU_IO(0xff000000, 0x7c000000)
 
 #define IO_SPACE_LIMIT 0xffff
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #define FLUSH_BASE_PHYS		0x50000000
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/isa-irq.c linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/isa-irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/isa-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/isa-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,14 +151,14 @@
 
 	if (host_irq != (unsigned int)-1) {
 		for (irq = _ISA_IRQ(0); irq < _ISA_IRQ(8); irq++) {
-			set_irq_chip(irq, &isa_lo_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &isa_lo_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
 
 		for (irq = _ISA_IRQ(8); irq < _ISA_IRQ(16); irq++) {
-			set_irq_chip(irq, &isa_hi_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &isa_hi_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
 
@@ -166,7 +166,7 @@
 		request_resource(&ioport_resource, &pic2_resource);
 		setup_irq(IRQ_ISA_CASCADE, &irq_cascade);
 
-		set_irq_chained_handler(host_irq, isa_irq_handler);
+		irq_set_chained_handler(host_irq, isa_irq_handler);
 
 		/*
 		 * On the NetWinder, don't automatically
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/isa-timer.c linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/isa-timer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-footbridge/isa-timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-footbridge/isa-timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,10 +4,13 @@
  *  Copyright (C) 1998 Russell King.
  *  Copyright (C) 1998 Phil Blundell
  */
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/timex.h>
 
 #include <asm/irq.h>
 
@@ -15,77 +18,115 @@
 
 #include "common.h"
 
-/*
- * ISA timer tick support
- */
-#define mSEC_10_from_14 ((14318180 + 100) / 200)
+#define PIT_MODE	0x43
+#define PIT_CH0		0x40
 
-static unsigned long isa_gettimeoffset(void)
+#define PIT_LATCH	((PIT_TICK_RATE + HZ / 2) / HZ)
+
+static cycle_t pit_read(struct clocksource *cs)
 {
+	unsigned long flags;
+	static int old_count;
+	static u32 old_jifs;
 	int count;
+	u32 jifs;
 
-	static int count_p = (mSEC_10_from_14/6);    /* for the first call after boot */
-	static unsigned long jiffies_p = 0;
+	raw_local_irq_save(flags);
 
-	/*
-	 * cache volatile jiffies temporarily; we have IRQs turned off. 
-	 */
-	unsigned long jiffies_t;
+	jifs = jiffies;
+	outb_p(0x00, PIT_MODE);		/* latch the count */
+	count = inb_p(PIT_CH0);		/* read the latched count */
+	count |= inb_p(PIT_CH0) << 8;
 
-	/* timer count may underflow right here */
-	outb_p(0x00, 0x43);	/* latch the count ASAP */
+	if (count > old_count && jifs == old_jifs)
+		count = old_count;
 
-	count = inb_p(0x40);	/* read the latched count */
+	old_count = count;
+	old_jifs = jifs;
 
-	/*
-	 * We do this guaranteed double memory access instead of a _p 
-	 * postfix in the previous port access. Wheee, hackady hack
-	 */
- 	jiffies_t = jiffies;
+	raw_local_irq_restore(flags);
 
-	count |= inb_p(0x40) << 8;
+	count = (PIT_LATCH - 1) - count;
 
-	/* Detect timer underflows.  If we haven't had a timer tick since 
-	   the last time we were called, and time is apparently going
-	   backwards, the counter must have wrapped during this routine. */
-	if ((jiffies_t == jiffies_p) && (count > count_p))
-		count -= (mSEC_10_from_14/6);
-	else
-		jiffies_p = jiffies_t;
+	return (cycle_t)(jifs * PIT_LATCH) + count;
+}
 
-	count_p = count;
+static struct clocksource pit_cs = {
+	.name		= "pit",
+	.rating		= 110,
+	.read		= pit_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+};
 
-	count = (((mSEC_10_from_14/6)-1) - count) * (tick_nsec / 1000);
-	count = (count + (mSEC_10_from_14/6)/2) / (mSEC_10_from_14/6);
+static void pit_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *evt)
+{
+	unsigned long flags;
 
-	return count;
+	raw_local_irq_save(flags);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		outb_p(0x34, PIT_MODE);
+		outb_p(PIT_LATCH & 0xff, PIT_CH0);
+		outb_p(PIT_LATCH >> 8, PIT_CH0);
+		break;
+
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+		outb_p(0x30, PIT_MODE);
+		outb_p(0, PIT_CH0);
+		outb_p(0, PIT_CH0);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_RESUME:
+		break;
+	}
+	local_irq_restore(flags);
 }
 
-static irqreturn_t
-isa_timer_interrupt(int irq, void *dev_id)
+static int pit_set_next_event(unsigned long delta,
+	struct clock_event_device *evt)
 {
-	timer_tick();
+	return 0;
+}
+
+static struct clock_event_device pit_ce = {
+	.name		= "pit",
+	.features	= CLOCK_EVT_FEAT_PERIODIC,
+	.set_mode	= pit_set_mode,
+	.set_next_event	= pit_set_next_event,
+	.shift		= 32,
+};
+
+static irqreturn_t pit_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ce = dev_id;
+	ce->event_handler(ce);
 	return IRQ_HANDLED;
 }
 
-static struct irqaction isa_timer_irq = {
-	.name		= "ISA timer tick",
-	.handler	= isa_timer_interrupt,
+static struct irqaction pit_timer_irq = {
+	.name		= "pit",
+	.handler	= pit_timer_interrupt,
 	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.dev_id		= &pit_ce,
 };
 
 static void __init isa_timer_init(void)
 {
-	/* enable PIT timer */
-	/* set for periodic (4) and LSB/MSB write (0x30) */
-	outb(0x34, 0x43);
-	outb((mSEC_10_from_14/6) & 0xFF, 0x40);
-	outb((mSEC_10_from_14/6) >> 8, 0x40);
+	pit_ce.cpumask = cpumask_of(smp_processor_id());
+	pit_ce.mult = div_sc(PIT_TICK_RATE, NSEC_PER_SEC, pit_ce.shift);
+	pit_ce.max_delta_ns = clockevent_delta2ns(0x7fff, &pit_ce);
+	pit_ce.min_delta_ns = clockevent_delta2ns(0x000f, &pit_ce);
 
-	setup_irq(IRQ_ISA_TIMER, &isa_timer_irq);
+	clocksource_register_hz(&pit_cs, PIT_TICK_RATE);
+
+	setup_irq(pit_ce.irq, &pit_timer_irq);
+	clockevents_register_device(&pit_ce);
 }
 
 struct sys_timer isa_timer = {
 	.init		= isa_timer_init,
-	.offset		= isa_gettimeoffset,
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-nas4220b.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-nas4220b.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-nas4220b.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-nas4220b.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,6 +98,7 @@
 	platform_register_pflash(SZ_16M, NULL, 0);
 	platform_device_register(&ib4220b_led_device);
 	platform_device_register(&ib4220b_key_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(NAS4220B, "Raidsonic NAS IB-4220-B")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-rut1xx.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-rut1xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-rut1xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-rut1xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,6 +82,7 @@
 	platform_register_pflash(SZ_8M, NULL, 0);
 	platform_device_register(&rut1xx_leds);
 	platform_device_register(&rut1xx_keys_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(RUT100, "Teltonika RUT100")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-wbd111.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-wbd111.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-wbd111.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-wbd111.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,6 +130,7 @@
 				 wbd111_num_partitions);
 	platform_device_register(&wbd111_leds_device);
 	platform_device_register(&wbd111_keys_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(WBD111, "Wiliboard WBD-111")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-wbd222.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-wbd222.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/board-wbd222.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/board-wbd222.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,6 +130,7 @@
 		wbd222_num_partitions);
 	platform_device_register(&wbd222_leds_device);
 	platform_device_register(&wbd222_keys_device);
+	platform_register_rtc();
 }
 
 MACHINE_START(WBD222, "Wiliboard WBD-222")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/common.h linux-libre-2.6.39-gnu/arch/arm/mach-gemini/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 extern void gemini_init_irq(void);
 extern void gemini_timer_init(void);
 extern void gemini_gpio_init(void);
+extern void platform_register_rtc(void);
 
 /* Common platform devices registration functions */
 extern int platform_register_uart(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,3 +90,29 @@
 
 	return platform_device_register(&pflash_device);
 }
+
+static struct resource gemini_rtc_resources[] = {
+	[0] = {
+		.start  = GEMINI_RTC_BASE,
+		.end    = GEMINI_RTC_BASE + 0x24,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = IRQ_RTC,
+		.end    = IRQ_RTC,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device gemini_rtc_device = {
+	.name		= "rtc-gemini",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(gemini_rtc_resources),
+	.resource	= gemini_rtc_resources,
+};
+
+int __init platform_register_rtc(void)
+{
+	return platform_device_register(&gemini_rtc_device);
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -127,8 +127,8 @@
 
 static void gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
+	unsigned int port = (unsigned int)irq_desc_get_handler_data(desc);
 	unsigned int gpio_irq_no, irq_stat;
-	unsigned int port = (unsigned int)get_irq_data(irq);
 
 	irq_stat = __raw_readl(GPIO_BASE(port) + GPIO_INT_STAT);
 
@@ -138,9 +138,7 @@
 		if ((irq_stat & 1) == 0)
 			continue;
 
-		BUG_ON(!(irq_desc[gpio_irq_no].handle_irq));
-		irq_desc[gpio_irq_no].handle_irq(gpio_irq_no,
-				&irq_desc[gpio_irq_no]);
+		generic_handle_irq(gpio_irq_no);
 	}
 }
 
@@ -219,13 +217,13 @@
 
 		for (j = GPIO_IRQ_BASE + i * 32;
 		     j < GPIO_IRQ_BASE + (i + 1) * 32; j++) {
-			set_irq_chip(j, &gpio_irq_chip);
-			set_irq_handler(j, handle_edge_irq);
+			irq_set_chip_and_handler(j, &gpio_irq_chip,
+						 handle_edge_irq);
 			set_irq_flags(j, IRQF_VALID);
 		}
 
-		set_irq_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
-		set_irq_data(IRQ_GPIO(i), (void *)i);
+		irq_set_chained_handler(IRQ_GPIO(i), gpio_irq_handler);
+		irq_set_handler_data(IRQ_GPIO(i), (void *)i);
 	}
 
 	BUG_ON(gpiochip_add(&gemini_gpio_chip));
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-gemini/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,9 +11,9 @@
 #define __MACH_MEMORY_H
 
 #ifdef CONFIG_GEMINI_MEM_SWAP
-# define PHYS_OFFSET	UL(0x00000000)
+# define PLAT_PHYS_OFFSET	UL(0x00000000)
 #else
-# define PHYS_OFFSET	UL(0x10000000)
+# define PLAT_PHYS_OFFSET	UL(0x10000000)
 #endif
 
 #endif /* __MACH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-gemini/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-gemini/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-gemini/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-gemini/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,13 +81,13 @@
 	request_resource(&iomem_resource, &irq_resource);
 
 	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_chip(i, &gemini_irq_chip);
+		irq_set_chip(i, &gemini_irq_chip);
 		if((i >= IRQ_TIMER1 && i <= IRQ_TIMER3) || (i >= IRQ_SERIRQ0 && i <= IRQ_SERIRQ1)) {
-			set_irq_handler(i, handle_edge_irq);
+			irq_set_handler(i, handle_edge_irq);
 			mode |= 1 << i;
 			level |= 1 << i;
 		} else {			
-			set_irq_handler(i, handle_level_irq);
+			irq_set_handler(i, handle_level_irq);
 		}
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-h720x/common.c linux-libre-2.6.39-gnu/arch/arm/mach-h720x/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-h720x/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-h720x/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -199,29 +199,29 @@
 
 	/* Initialize global IRQ's, fast path */
 	for (irq = 0; irq < NR_GLBL_IRQS; irq++) {
-		set_irq_chip(irq, &h720x_global_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &h720x_global_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	/* Initialize multiplexed IRQ's, slow path */
 	for (irq = IRQ_CHAINED_GPIOA(0) ; irq <= IRQ_CHAINED_GPIOD(31); irq++) {
-		set_irq_chip(irq, &h720x_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &h720x_gpio_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID );
 	}
-	set_irq_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
-	set_irq_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
-	set_irq_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
-	set_irq_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
+	irq_set_chained_handler(IRQ_GPIOA, h720x_gpioa_demux_handler);
+	irq_set_chained_handler(IRQ_GPIOB, h720x_gpiob_demux_handler);
+	irq_set_chained_handler(IRQ_GPIOC, h720x_gpioc_demux_handler);
+	irq_set_chained_handler(IRQ_GPIOD, h720x_gpiod_demux_handler);
 
 #ifdef CONFIG_CPU_H7202
 	for (irq = IRQ_CHAINED_GPIOE(0) ; irq <= IRQ_CHAINED_GPIOE(31); irq++) {
-		set_irq_chip(irq, &h720x_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &h720x_gpio_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID );
 	}
-	set_irq_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
+	irq_set_chained_handler(IRQ_GPIOE, h720x_gpioe_demux_handler);
 #endif
 
 	/* Enable multiplexed irq's */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-h720x/cpu-h7202.c linux-libre-2.6.39-gnu/arch/arm/mach-h720x/cpu-h7202.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-h720x/cpu-h7202.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-h720x/cpu-h7202.c	2011-05-19 00:06:34.000000000 -0400
@@ -141,13 +141,18 @@
 /*
  * mask multiplexed timer IRQs
  */
-static void inline mask_timerx_irq(struct irq_data *d)
+static void inline __mask_timerx_irq(unsigned int irq)
 {
 	unsigned int bit;
-	bit = 2 << ((d->irq == IRQ_TIMER64B) ? 4 : (d->irq - IRQ_TIMER1));
+	bit = 2 << ((irq == IRQ_TIMER64B) ? 4 : (irq - IRQ_TIMER1));
 	CPU_REG (TIMER_VIRT, TIMER_TOPCTRL) &= ~bit;
 }
 
+static void inline mask_timerx_irq(struct irq_data *d)
+{
+	__mask_timerx_irq(d->irq);
+}
+
 /*
  * unmask multiplexed timer IRQs
  */
@@ -196,12 +201,12 @@
 
 	for (irq = IRQ_TIMER1;
 	                  irq < IRQ_CHAINED_TIMERX(NR_TIMERX_IRQS); irq++) {
-		mask_timerx_irq(irq);
-		set_irq_chip(irq, &h7202_timerx_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		__mask_timerx_irq(irq);
+		irq_set_chip_and_handler(irq, &h7202_timerx_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID );
 	}
-	set_irq_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
+	irq_set_chained_handler(IRQ_TIMERX, h7202_timerx_demux_handler);
 
 	h720x_init_irq();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-h720x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-h720x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-h720x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-h720x/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x40000000)
+#define PLAT_PHYS_OFFSET	UL(0x40000000)
 /*
  * This is the maximum DMA address that can be DMAd to.
  * There should not be more than (0xd0000000 - 0xc0000000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/clock-imx1.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/clock-imx1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/clock-imx1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/clock-imx1.c	2011-05-19 00:06:34.000000000 -0400
@@ -592,6 +592,7 @@
 	_REGISTER_CLOCK("imx-uart.2", NULL, uart_clk)
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c_clk)
 	_REGISTER_CLOCK("imx1-cspi.0", NULL, spi_clk)
+	_REGISTER_CLOCK("imx1-cspi.1", NULL, spi_clk)
 	_REGISTER_CLOCK("imx-mmc.0", NULL, sdhc_clk)
 	_REGISTER_CLOCK("imx-fb.0", NULL, lcdc_clk)
 	_REGISTER_CLOCK(NULL, "mshc", mshc_clk)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/clock-imx25.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/clock-imx25.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/clock-imx25.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/clock-imx25.c	2011-05-19 00:06:34.000000000 -0400
@@ -228,6 +228,7 @@
 DEFINE_CLOCK(esdhc2_ahb_clk, 0, CCM_CGCR0, 22, get_rate_esdhc2,	 NULL, NULL);
 DEFINE_CLOCK(esdhc2_per_clk, 0, CCM_CGCR0,  4, get_rate_esdhc2,	 NULL,
 		&esdhc2_ahb_clk);
+DEFINE_CLOCK(sdma_ahb_clk, 0, CCM_CGCR0, 26, NULL,	 NULL, NULL);
 DEFINE_CLOCK(fec_ahb_clk, 0, CCM_CGCR0, 23, NULL,	 NULL, NULL);
 DEFINE_CLOCK(lcdc_ahb_clk, 0, CCM_CGCR0, 24, NULL,	 NULL, NULL);
 DEFINE_CLOCK(lcdc_per_clk, 0, CCM_CGCR0,  7, NULL,	 NULL, &lcdc_ahb_clk);
@@ -253,6 +254,7 @@
 DEFINE_CLOCK(wdt_clk,    0, CCM_CGCR2, 19, get_rate_ipg, NULL,  NULL);
 DEFINE_CLOCK(ssi1_clk,  0, CCM_CGCR2, 11, get_rate_ssi1, NULL, &ssi1_per_clk);
 DEFINE_CLOCK(ssi2_clk,  1, CCM_CGCR2, 12, get_rate_ssi2, NULL, &ssi2_per_clk);
+DEFINE_CLOCK(sdma_clk, 0, CCM_CGCR2,  6, get_rate_ipg, NULL, &sdma_ahb_clk);
 DEFINE_CLOCK(esdhc1_clk,  0, CCM_CGCR1, 13, get_rate_esdhc1, NULL,
 		&esdhc1_per_clk);
 DEFINE_CLOCK(esdhc2_clk,  1, CCM_CGCR1, 14, get_rate_esdhc2, NULL,
@@ -304,6 +306,7 @@
 	_REGISTER_CLOCK(NULL, "audmux", audmux_clk)
 	_REGISTER_CLOCK("flexcan.0", NULL, can1_clk)
 	_REGISTER_CLOCK("flexcan.1", NULL, can2_clk)
+	_REGISTER_CLOCK("imx-sdma", NULL, sdma_clk)
 };
 
 int __init mx25_clocks_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/devices-imx1.h linux-libre-2.6.39-gnu/arch/arm/mach-imx/devices-imx1.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/devices-imx1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/devices-imx1.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,10 @@
 #include <mach/mx1.h>
 #include <mach/devices-common.h>
 
+extern const struct imx_imx_fb_data imx1_imx_fb_data __initconst;
+#define imx1_add_imx_fb(pdata) \
+    imx_add_imx_fb(&imx1_imx_fb_data, pdata)
+
 extern const struct imx_imx_i2c_data imx1_imx_i2c_data __initconst;
 #define imx1_add_imx_i2c(pdata)		\
 	imx_add_imx_i2c(&imx1_imx_i2c_data, pdata)
@@ -18,3 +22,10 @@
 	imx_add_imx_uart_3irq(&imx1_imx_uart_data[id], pdata)
 #define imx1_add_imx_uart0(pdata)	imx1_add_imx_uart(0, pdata)
 #define imx1_add_imx_uart1(pdata)	imx1_add_imx_uart(1, pdata)
+
+extern const struct imx_spi_imx_data imx1_cspi_data[] __initconst;
+#define imx1_add_cspi(id, pdata)   \
+	imx_add_spi_imx(&imx1_cspi_data[id], pdata)
+
+#define imx1_add_spi_imx0(pdata) imx1_add_cspi(0, pdata)
+#define imx1_add_spi_imx1(pdata) imx1_add_cspi(1, pdata)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/devices-imx25.h linux-libre-2.6.39-gnu/arch/arm/mach-imx/devices-imx25.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/devices-imx25.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/devices-imx25.h	2011-05-19 00:06:34.000000000 -0400
@@ -81,7 +81,11 @@
 
 extern const struct imx_spi_imx_data imx25_cspi_data[] __initconst;
 #define imx25_add_spi_imx(id, pdata)	\
-	imx_add_spi_imx(&imx25_spi_imx_data[id], pdata)
+	imx_add_spi_imx(&imx25_cspi_data[id], pdata)
 #define imx25_add_spi_imx0(pdata)	imx25_add_spi_imx(0, pdata)
 #define imx25_add_spi_imx1(pdata)	imx25_add_spi_imx(1, pdata)
 #define imx25_add_spi_imx2(pdata)	imx25_add_spi_imx(2, pdata)
+
+extern struct imx_mxc_pwm_data imx25_mxc_pwm_data[] __initconst;
+#define imx25_add_mxc_pwm(id)	\
+	imx_add_mxc_pwm(&imx25_mxc_pwm_data[id])
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/dma-v1.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/dma-v1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/dma-v1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/dma-v1.c	2011-05-19 00:06:34.000000000 -0400
@@ -699,7 +699,7 @@
 		local_irq_restore(flags);
 		return -EBUSY;
 	}
-	memset(imxdma, 0, sizeof(imxdma));
+	memset(imxdma, 0, sizeof(*imxdma));
 	imxdma->name = name;
 	local_irq_restore(flags); /* request_irq() can block */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/ehci-imx25.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/ehci-imx25.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/ehci-imx25.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/ehci-imx25.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX25_OTG_SIC_SHIFT	29
+#define MX25_OTG_SIC_MASK	(0x3 << MX25_OTG_SIC_SHIFT)
+#define MX25_OTG_PM_BIT		(1 << 24)
+
+#define MX25_H1_SIC_SHIFT	21
+#define MX25_H1_SIC_MASK	(0x3 << MX25_H1_SIC_SHIFT)
+#define MX25_H1_PM_BIT		(1 << 8)
+#define MX25_H1_IPPUE_UP_BIT	(1 << 7)
+#define MX25_H1_IPPUE_DOWN_BIT	(1 << 6)
+#define MX25_H1_TLL_BIT		(1 << 5)
+#define MX25_H1_USBTE_BIT	(1 << 4)
+
+int mx25_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX25_OTG_SIC_MASK | MX25_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX25_OTG_PM_BIT;
+
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX25_H1_SIC_MASK | MX25_H1_PM_BIT | MX25_H1_TLL_BIT |
+			MX25_H1_USBTE_BIT | MX25_H1_IPPUE_DOWN_BIT | MX25_H1_IPPUE_UP_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX25_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX25_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX25_H1_TLL_BIT;
+
+		if (flags & MXC_EHCI_INTERNAL_PHY)
+			v |= MX25_H1_USBTE_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_DOWN)
+			v |= MX25_H1_IPPUE_DOWN_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_UP)
+			v |= MX25_H1_IPPUE_UP_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/ehci-imx27.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/ehci-imx27.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/ehci-imx27.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/ehci-imx27.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX27_OTG_SIC_SHIFT	29
+#define MX27_OTG_SIC_MASK	(0x3 << MX27_OTG_SIC_SHIFT)
+#define MX27_OTG_PM_BIT		(1 << 24)
+
+#define MX27_H2_SIC_SHIFT	21
+#define MX27_H2_SIC_MASK	(0x3 << MX27_H2_SIC_SHIFT)
+#define MX27_H2_PM_BIT		(1 << 16)
+#define MX27_H2_DT_BIT		(1 << 5)
+
+#define MX27_H1_SIC_SHIFT	13
+#define MX27_H1_SIC_MASK	(0x3 << MX27_H1_SIC_SHIFT)
+#define MX27_H1_PM_BIT		(1 << 8)
+#define MX27_H1_DT_BIT		(1 << 4)
+
+int mx27_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX27_OTG_SIC_MASK | MX27_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX27_OTG_PM_BIT;
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX27_H1_SIC_MASK | MX27_H1_PM_BIT | MX27_H1_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX27_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX27_H1_DT_BIT;
+
+		break;
+	case 2:	/* H2 port */
+		v &= ~(MX27_H2_SIC_MASK | MX27_H2_PM_BIT | MX27_H2_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX27_H2_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX27_H2_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX27_H2_DT_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/eukrea_mbimx27-baseboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -249,7 +249,7 @@
 
 #define ADS7846_PENDOWN (GPIO_PORTD | 25)
 
-static void ads7846_dev_init(void)
+static void __maybe_unused ads7846_dev_init(void)
 {
 	if (gpio_request(ADS7846_PENDOWN, "ADS7846 pendown") < 0) {
 		printk(KERN_ERR "can't get ads746 pen down GPIO\n");
@@ -268,7 +268,8 @@
 	.keep_vref_on		= 1,
 };
 
-static struct spi_board_info eukrea_mbimx27_spi_board_info[] __initdata = {
+static struct spi_board_info __maybe_unused
+		eukrea_mbimx27_spi_board_info[] __initdata = {
 	[0] = {
 		.modalias	= "ads7846",
 		.bus_num	= 0,
@@ -357,13 +358,11 @@
 	ads7846_dev_init();
 #endif
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	/* SPI_CS0 init */
 	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_OUT);
 	imx27_add_spi_imx0(&eukrea_mbimx27_spi0_data);
 	spi_register_board_info(eukrea_mbimx27_spi_board_info,
 			ARRAY_SIZE(eukrea_mbimx27_spi_board_info));
-#endif
 
 	/* Leds configuration */
 	mxc_gpio_mode(GPIO_PORTF | 16 | GPIO_GPIO | GPIO_OUT);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/eukrea_mbimxsd25-baseboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 #include <mach/mx25.h>
 #include <mach/imx-uart.h>
 #include <mach/audmux.h>
+#include <mach/esdhc.h>
 
 #include "devices-imx25.h"
 
@@ -242,6 +243,11 @@
 	.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
 };
 
+static struct esdhc_platform_data sd1_pdata = {
+	.cd_gpio = GPIO_SD1CD,
+	.wp_gpio = -EINVAL,
+};
+
 /*
  * system init for baseboard usage. Will be called by cpuimx25 init.
  *
@@ -275,7 +281,7 @@
 	imx25_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
 
 	imx25_add_flexcan1(NULL);
-	imx25_add_sdhci_esdhc_imx(0, NULL);
+	imx25_add_sdhci_esdhc_imx(0, &sd1_pdata);
 
 	gpio_request(GPIO_LED1, "LED1");
 	gpio_direction_output(GPIO_LED1, 1);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-imx/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -100,6 +100,7 @@
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMXDI_RTC
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_FB
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
@@ -238,6 +239,7 @@
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -253,6 +255,7 @@
 	bool "Vista Silicon i.MX27 Visstrim_m10"
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_MMC
 	select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -265,6 +268,7 @@
 	bool "LogicPD MX27 LITEKIT platform"
 	select SOC_IMX27
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_SSI
 	help
 	  Include support for MX27 LITEKIT platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -300,4 +304,13 @@
 	  Include support for i-MXT (aka td60) platform. This
 	  includes specific configurations for the module and its peripherals.
 
+config MACH_IMX27IPCAM
+	bool "IMX27 IPCAM platform"
+	select SOC_IMX27
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_UART
+	help
+	  Include support for IMX27 IPCAM platform. This includes specific
+	  configurations for the board and its peripherals.
+
 endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-cpuimx27.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-cpuimx27.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-cpuimx27.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-cpuimx27.c	2011-05-19 00:06:34.000000000 -0400
@@ -209,17 +209,25 @@
 };
 #endif
 
-#if defined(CONFIG_USB_ULPI)
+static int eukrea_cpuimx27_otg_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= eukrea_cpuimx27_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int eukrea_cpuimx27_usbh2_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init	= eukrea_cpuimx27_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -273,21 +281,19 @@
 	platform_device_register(&serial_device);
 #endif
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx27_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx27_add_mxc_ehci_otg(&otg_pdata);
+	} else {
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 	}
 
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
-	if (!otg_mode_host)
-		imx27_add_fsl_usb2_udc(&otg_device_pdata);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 #ifdef CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD
 	eukrea_mbimx27_baseboard_init();
@@ -304,9 +310,10 @@
 };
 
 MACHINE_START(CPUIMX27, "EUKREA CPUIMX27")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = eukrea_cpuimx27_init,
-	.timer          = &eukrea_cpuimx27_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &eukrea_cpuimx27_timer,
+	.init_machine = eukrea_cpuimx27_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-eukrea_cpuimx25.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,15 +84,25 @@
 	},
 };
 
+static int eukrea_cpuimx25_otg_init(struct platform_device *pdev)
+{
+	return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static const struct mxc_usbh_platform_data otg_pdata __initconst = {
+	.init	= eukrea_cpuimx25_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int eukrea_cpuimx25_usbh2_init(struct platform_device *pdev)
+{
+	return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
+}
+
 static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.init	= eukrea_cpuimx25_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
 };
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
@@ -153,9 +163,10 @@
 
 MACHINE_START(EUKREA_CPUIMX25, "Eukrea CPUIMX25")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params    = MX25_PHYS_OFFSET + 0x100,
-	.map_io         = mx25_map_io,
-	.init_irq       = mx25_init_irq,
-	.init_machine   = eukrea_cpuimx25_init,
-	.timer          = &eukrea_cpuimx25_timer,
+	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.map_io = mx25_map_io,
+	.init_early = imx25_init_early,
+	.init_irq = mx25_init_irq,
+	.timer = &eukrea_cpuimx25_timer,
+	.init_machine = eukrea_cpuimx25_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-imx27ipcam.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-imx27ipcam.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-imx27ipcam.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-imx27ipcam.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+
+#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/iomux-mx27.h>
+
+#include "devices-imx27.h"
+
+static const int mx27ipcam_pins[] __initconst = {
+	/* UART1 */
+	PE12_PF_UART1_TXD,
+	PE13_PF_UART1_RXD,
+	/* 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 void __init mx27ipcam_init(void)
+{
+	mxc_gpio_setup_multiple_pins(mx27ipcam_pins, ARRAY_SIZE(mx27ipcam_pins),
+		"mx27ipcam");
+
+	imx27_add_imx_uart0(NULL);
+	imx27_add_fec(NULL);
+	imx27_add_imx2_wdt(NULL);
+}
+
+static void __init mx27ipcam_timer_init(void)
+{
+	mx27_clocks_init(25000000);
+}
+
+static struct sys_timer mx27ipcam_timer = {
+	.init	= mx27ipcam_timer_init,
+};
+
+MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
+	/* maintainer: Freescale Semiconductor, Inc. */
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27ipcam_timer,
+	.init_machine = mx27ipcam_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-imx27lite.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-imx27lite.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-imx27lite.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-imx27lite.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,9 +75,10 @@
 };
 
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27lite_init,
-	.timer          = &mx27lite_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27lite_timer,
+	.init_machine = mx27lite_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-imx27_visstrim_m10.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
@@ -66,6 +67,11 @@
 	PD15_AOUT_FEC_COL,
 	PD16_AIN_FEC_TX_ER,
 	PF23_AIN_FEC_TX_EN,
+	/* SSI1 */
+	PC20_PF_SSI1_FS,
+	PC21_PF_SSI1_RXD,
+	PC22_PF_SSI1_TXD,
+	PC23_PF_SSI1_CLK,
 	/* SDHC1 */
 	PE18_PF_SD1_D0,
 	PE19_PF_SD1_D1,
@@ -204,20 +210,30 @@
 		I2C_BOARD_INFO("pca9555", 0x20),
 		.platform_data = &visstrim_m10_pca9555_pdata,
 	},
+	{
+		I2C_BOARD_INFO("tlv320aic32x4", 0x18),
+	}
 };
 
 /* USB OTG */
 static int otg_phy_init(struct platform_device *pdev)
 {
 	gpio_set_value(OTG_PHY_CS_GPIO, 0);
-	return 0;
+
+	mdelay(10);
+
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
 }
 
 static const struct mxc_usbh_platform_data
 visstrim_m10_usbotg_pdata __initconst = {
 	.init = otg_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
+};
+
+/* SSI */
+static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = {
+	.flags			= IMX_SSI_DMA | IMX_SSI_SYN,
 };
 
 static void __init visstrim_m10_board_init(void)
@@ -229,6 +245,7 @@
 	if (ret)
 		pr_err("Failed to setup pins (%d)\n", ret);
 
+	imx27_add_imx_ssi(0, &visstrim_m10_ssi_pdata);
 	imx27_add_imx_uart0(&uart_pdata);
 
 	i2c_register_board_info(0, visstrim_m10_i2c_devices,
@@ -251,9 +268,10 @@
 };
 
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = visstrim_m10_board_init,
-	.timer          = &visstrim_m10_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &visstrim_m10_timer,
+	.init_machine = visstrim_m10_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx1ads.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx1ads.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx1ads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx1ads.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,17 +144,19 @@
 
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
-	.boot_params	= MX1_PHYS_OFFSET + 0x100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &mx1ads_timer,
-	.init_machine	= mx1ads_init,
+	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.map_io = mx1_map_io,
+	.init_early = imx1_init_early,
+	.init_irq = mx1_init_irq,
+	.timer = &mx1ads_timer,
+	.init_machine = mx1ads_init,
 MACHINE_END
 
 MACHINE_START(MXLADS, "Freescale MXLADS")
-	.boot_params	= MX1_PHYS_OFFSET + 0x100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &mx1ads_timer,
-	.init_machine	= mx1ads_init,
+	.boot_params = MX1_PHYS_OFFSET + 0x100,
+	.map_io = mx1_map_io,
+	.init_early = imx1_init_early,
+	.init_irq = mx1_init_irq,
+	.timer = &mx1ads_timer,
+	.init_machine = mx1ads_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx21ads.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx21ads.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx21ads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx21ads.c	2011-05-19 00:06:34.000000000 -0400
@@ -304,9 +304,10 @@
 
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX21_PHYS_OFFSET + 0x100,
-	.map_io         = mx21ads_map_io,
-	.init_irq       = mx21_init_irq,
-	.init_machine   = mx21ads_board_init,
-	.timer          = &mx21ads_timer,
+	.boot_params = MX21_PHYS_OFFSET + 0x100,
+	.map_io = mx21ads_map_io,
+	.init_early = imx21_init_early,
+	.init_irq = mx21_init_irq,
+	.timer = &mx21ads_timer,
+	.init_machine = mx21ads_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx25_3ds.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx25_3ds.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx25_3ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx25_3ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -103,14 +103,18 @@
 	MX25_PAD_SD1_DATA1__SD1_DATA1,
 	MX25_PAD_SD1_DATA2__SD1_DATA2,
 	MX25_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* I2C1 */
+	MX25_PAD_I2C1_CLK__I2C1_CLK,
+	MX25_PAD_I2C1_DAT__I2C1_DAT,
 };
 
 static const struct fec_platform_data mx25_fec_pdata __initconst = {
 	.phy    = PHY_INTERFACE_MODE_RMII,
 };
 
-#define FEC_ENABLE_GPIO		35
-#define FEC_RESET_B_GPIO	104
+#define FEC_ENABLE_GPIO		IMX_GPIO_NR(2, 3)
+#define FEC_RESET_B_GPIO	IMX_GPIO_NR(4, 8)
 
 static void __init mx25pdk_fec_reset(void)
 {
@@ -185,9 +189,14 @@
 	.keymap_size	= ARRAY_SIZE(mx25pdk_keymap),
 };
 
+static int mx25pdk_usbh2_init(struct platform_device *pdev)
+{
+	return mx25_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
 static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.init	= mx25pdk_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
@@ -195,6 +204,10 @@
 	.phy_mode       = FSL_USB2_PHY_UTMI,
 };
 
+static const struct imxi2c_platform_data mx25_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
+
 static void __init mx25pdk_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx25pdk_pads,
@@ -213,6 +226,7 @@
 	imx25_add_imx_keypad(&mx25pdk_keymap_data);
 
 	imx25_add_sdhci_esdhc_imx(0, NULL);
+	imx25_add_imx_i2c0(&mx25_3ds_i2c0_data);
 }
 
 static void __init mx25pdk_timer_init(void)
@@ -226,10 +240,10 @@
 
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX25_PHYS_OFFSET + 0x100,
-	.map_io         = mx25_map_io,
-	.init_irq       = mx25_init_irq,
-	.init_machine   = mx25pdk_init,
-	.timer          = &mx25pdk_timer,
+	.boot_params = MX25_PHYS_OFFSET + 0x100,
+	.map_io = mx25_map_io,
+	.init_early = imx25_init_early,
+	.init_irq = mx25_init_irq,
+	.timer = &mx25pdk_timer,
+	.init_machine = mx25pdk_init,
 MACHINE_END
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx27_3ds.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx27_3ds.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx27_3ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx27_3ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,6 +98,9 @@
 	PD22_PF_CSPI2_SCLK,
 	PD23_PF_CSPI2_MISO,
 	PD24_PF_CSPI2_MOSI,
+	/* I2C1 */
+	PD17_PF_I2C_DATA,
+	PD18_PF_I2C_CLK,
 };
 
 static const struct imxuart_platform_data uart_pdata __initconst = {
@@ -159,13 +162,15 @@
 	return 0;
 }
 
-#if defined(CONFIG_USB_ULPI)
+static int mx27_3ds_otg_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
 
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= mx27_3ds_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -216,7 +221,7 @@
 	.consumer_supplies = vgen_consumers,
 };
 
-static struct mc13783_regulator_init_data mx27_3ds_regulators[] = {
+static struct mc13xxx_regulator_init_data mx27_3ds_regulators[] = {
 	{
 		.id = MC13783_REG_VMMC1,
 		.init_data = &vmmc1_init,
@@ -227,9 +232,12 @@
 };
 
 /* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.regulators = mx27_3ds_regulators,
-	.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
+static struct mc13xxx_platform_data mc13783_pdata = {
+	.regulators = {
+		.regulators = mx27_3ds_regulators,
+		.num_regulators = ARRAY_SIZE(mx27_3ds_regulators),
+
+	},
 	.flags  = MC13783_USE_REGULATOR,
 };
 
@@ -253,6 +261,9 @@
 	},
 };
 
+static const struct imxi2c_platform_data mx27_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
 
 static void __init mx27pdk_init(void)
 {
@@ -265,14 +276,15 @@
 	imx27_add_mxc_mmc(0, &sdhc1_pdata);
 	imx27_add_imx2_wdt(NULL);
 	otg_phy_init();
-#if defined(CONFIG_USB_ULPI)
+
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
 
-		imx27_add_mxc_ehci_otg(&otg_pdata);
+		if (otg_pdata.otg)
+			imx27_add_mxc_ehci_otg(&otg_pdata);
 	}
-#endif
+
 	if (!otg_mode_host)
 		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 
@@ -282,6 +294,7 @@
 
 	if (mxc_expio_init(MX27_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		pr_warn("Init of the debugboard failed, all devices on the debugboard are unusable.\n");
+	imx27_add_imx_i2c(0, &mx27_3ds_i2c0_data);
 }
 
 static void __init mx27pdk_timer_init(void)
@@ -295,9 +308,10 @@
 
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27pdk_init,
-	.timer          = &mx27pdk_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27pdk_timer,
+	.init_machine = mx27pdk_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx27ads.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx27ads.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mx27ads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mx27ads.c	2011-05-19 00:06:34.000000000 -0400
@@ -344,9 +344,10 @@
 
 MACHINE_START(MX27ADS, "Freescale i.MX27ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27ads_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = mx27ads_board_init,
-	.timer          = &mx27ads_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27ads_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mx27ads_timer,
+	.init_machine = mx27ads_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mxt_td60.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mxt_td60.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-mxt_td60.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-mxt_td60.c	2011-05-19 00:06:34.000000000 -0400
@@ -266,10 +266,10 @@
 
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	/* maintainer: Maxtrack Industrial */
-	.boot_params	= MX27_PHYS_OFFSET + 0x100,
-	.map_io		= mx27_map_io,
-	.init_irq	= mx27_init_irq,
-	.init_machine	= mxt_td60_board_init,
-	.timer		= &mxt_td60_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &mxt_td60_timer,
+	.init_machine = mxt_td60_board_init,
 MACHINE_END
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-pca100.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-pca100.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-pca100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-pca100.c	2011-05-19 00:06:34.000000000 -0400
@@ -187,7 +187,6 @@
 	}
 };
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 static struct spi_eeprom at25320 = {
 	.name		= "at25320an",
 	.byte_len	= 4096,
@@ -211,7 +210,6 @@
 	.chipselect	= pca100_spi_cs,
 	.num_chipselect = ARRAY_SIZE(pca100_spi_cs),
 };
-#endif
 
 static void pca100_ac97_warm_reset(struct snd_ac97 *ac97)
 {
@@ -269,31 +267,33 @@
 	.exit = pca100_sdhc2_exit,
 };
 
-#if defined(CONFIG_USB_ULPI)
 static int otg_phy_init(struct platform_device *pdev)
 {
 	gpio_set_value(OTG_PHY_CS_GPIO, 0);
-	return 0;
+
+	mdelay(10);
+
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
 }
 
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
 	.init	= otg_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
 static int usbh2_phy_init(struct platform_device *pdev)
 {
 	gpio_set_value(USBH2_PHY_CS_GPIO, 0);
-	return 0;
+
+	mdelay(10);
+
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
 }
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_phy_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -389,36 +389,33 @@
 
 	imx27_add_imx_i2c(1, &pca100_i2c1_data);
 
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	mxc_gpio_mode(GPIO_PORTD | 28 | GPIO_GPIO | GPIO_IN);
 	mxc_gpio_mode(GPIO_PORTD | 27 | GPIO_GPIO | GPIO_IN);
 	spi_register_board_info(pca100_spi_board_info,
 				ARRAY_SIZE(pca100_spi_board_info));
 	imx27_add_spi_imx0(&pca100_spi0_data);
-#endif
 
 	gpio_request(OTG_PHY_CS_GPIO, "usb-otg-cs");
 	gpio_direction_output(OTG_PHY_CS_GPIO, 1);
 	gpio_request(USBH2_PHY_CS_GPIO, "usb-host2-cs");
 	gpio_direction_output(USBH2_PHY_CS_GPIO, 1);
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
 
-		imx27_add_mxc_ehci_otg(&otg_pdata);
+		if (otg_pdata.otg)
+			imx27_add_mxc_ehci_otg(&otg_pdata);
+	} else {
+		gpio_set_value(OTG_PHY_CS_GPIO, 0);
+		imx27_add_fsl_usb2_udc(&otg_device_pdata);
 	}
 
 	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
 				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
-	if (!otg_mode_host) {
-		gpio_set_value(OTG_PHY_CS_GPIO, 0);
-		imx27_add_fsl_usb2_udc(&otg_device_pdata);
-	}
+	if (usbh2_pdata.otg)
+		imx27_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 	imx27_add_imx_fb(&pca100_fb_data);
 
@@ -437,10 +434,10 @@
 };
 
 MACHINE_START(PCA100, "phyCARD-i.MX27")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = pca100_init,
-	.timer          = &pca100_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.init_machine = pca100_init,
+	.timer = &pca100_timer,
 MACHINE_END
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-pcm038.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-pcm038.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-pcm038.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-pcm038.c	2011-05-19 00:06:34.000000000 -0400
@@ -252,7 +252,7 @@
 	.consumer_supplies = cam_consumers,
 };
 
-static struct mc13783_regulator_init_data pcm038_regulators[] = {
+static struct mc13xxx_regulator_init_data pcm038_regulators[] = {
 	{
 		.id = MC13783_REG_VCAM,
 		.init_data = &cam_data,
@@ -262,9 +262,11 @@
 	},
 };
 
-static struct mc13783_platform_data pcm038_pmic = {
-	.regulators = pcm038_regulators,
-	.num_regulators = ARRAY_SIZE(pcm038_regulators),
+static struct mc13xxx_platform_data pcm038_pmic = {
+	.regulators = {
+		.regulators = pcm038_regulators,
+		.num_regulators = ARRAY_SIZE(pcm038_regulators),
+	},
 	.flags = MC13783_USE_ADC | MC13783_USE_REGULATOR |
 		 MC13783_USE_TOUCHSCREEN,
 };
@@ -281,9 +283,15 @@
 	}
 };
 
+static int pcm038_usbh2_init(struct platform_device *pdev)
+{
+	return mx27_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static const struct mxc_usbh_platform_data usbh2_pdata __initconst = {
+	.init	= pcm038_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
 static void __init pcm038_init(void)
@@ -340,9 +348,10 @@
 };
 
 MACHINE_START(PCM038, "phyCORE-i.MX27")
-	.boot_params    = MX27_PHYS_OFFSET + 0x100,
-	.map_io         = mx27_map_io,
-	.init_irq       = mx27_init_irq,
-	.init_machine   = pcm038_init,
-	.timer          = &pcm038_timer,
+	.boot_params = MX27_PHYS_OFFSET + 0x100,
+	.map_io = mx27_map_io,
+	.init_early = imx27_init_early,
+	.init_irq = mx27_init_irq,
+	.timer = &pcm038_timer,
+	.init_machine = pcm038_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-scb9328.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-scb9328.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mach-scb9328.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mach-scb9328.c	2011-05-19 00:06:34.000000000 -0400
@@ -145,10 +145,11 @@
 };
 
 MACHINE_START(SCB9328, "Synertronixx scb9328")
-    /* Sascha Hauer */
-	.boot_params	= 0x08000100,
-	.map_io		= mx1_map_io,
-	.init_irq	= mx1_init_irq,
-	.timer		= &scb9328_timer,
-	.init_machine	= scb9328_init,
+	/* Sascha Hauer */
+	.boot_params = 0x08000100,
+	.map_io = mx1_map_io,
+	.init_early = imx1_init_early,
+	.init_irq = mx1_init_irq,
+	.timer = &scb9328_timer,
+	.init_machine = scb9328_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-imx/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,10 +9,10 @@
 obj-$(CONFIG_ARCH_MX1) += clock-imx1.o mm-imx1.o
 obj-$(CONFIG_MACH_MX21) += clock-imx21.o mm-imx21.o
 
-obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o
+obj-$(CONFIG_ARCH_MX25) += clock-imx25.o mm-imx25.o ehci-imx25.o
 
 obj-$(CONFIG_MACH_MX27) += cpu-imx27.o pm-imx27.o
-obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o
+obj-$(CONFIG_MACH_MX27) += clock-imx27.o mm-imx27.o ehci-imx27.o
 
 # Support for CMOS sensor interface
 obj-$(CONFIG_MX1_VIDEO)	+= mx1-camera-fiq.o mx1-camera-fiq-ksym.o
@@ -36,3 +36,4 @@
 obj-$(CONFIG_MACH_EUKREA_MBIMX27_BASEBOARD) += eukrea_mbimx27-baseboard.o
 obj-$(CONFIG_MACH_PCA100) += mach-pca100.o
 obj-$(CONFIG_MACH_MXT_TD60) += mach-mxt_td60.o
+obj-$(CONFIG_MACH_IMX27IPCAM) += mach-imx27ipcam.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx1.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx1.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,9 @@
 
 #include <mach/common.h>
 #include <mach/hardware.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/iomux-v1.h>
 
 static struct map_desc imx_io_desc[] __initdata = {
 	imx_map_entry(MX1, IO, MT_DEVICE),
@@ -30,16 +33,26 @@
 
 void __init mx1_map_io(void)
 {
+	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
+}
+
+void __init imx1_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX1);
 	mxc_arch_reset_init(MX1_IO_ADDRESS(MX1_WDT_BASE_ADDR));
-
-	iotable_init(imx_io_desc, ARRAY_SIZE(imx_io_desc));
+	imx_iomuxv1_init(MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR),
+			MX1_NUM_GPIO_PORT);
 }
 
-int imx1_register_gpios(void);
+static struct mxc_gpio_port imx1_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
+};
 
 void __init mx1_init_irq(void)
 {
 	mxc_init_irq(MX1_IO_ADDRESS(MX1_AVIC_BASE_ADDR));
-	imx1_register_gpios();
+	mxc_gpio_init(imx1_gpio_ports,	ARRAY_SIZE(imx1_gpio_ports));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx21.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx21.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx21.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx21.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,9 @@
 #include <mach/common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/iomux-v1.h>
 
 /* MX21 memory map definition */
 static struct map_desc imx21_io_desc[] __initdata = {
@@ -56,16 +59,28 @@
  */
 void __init mx21_map_io(void)
 {
+	iotable_init(imx21_io_desc, ARRAY_SIZE(imx21_io_desc));
+}
+
+void __init imx21_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX21);
 	mxc_arch_reset_init(MX21_IO_ADDRESS(MX21_WDOG_BASE_ADDR));
-
-	iotable_init(imx21_io_desc, ARRAY_SIZE(imx21_io_desc));
+	imx_iomuxv1_init(MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR),
+			MX21_NUM_GPIO_PORT);
 }
 
-int imx21_register_gpios(void);
+static struct mxc_gpio_port imx21_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
+	DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
+	DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
+	DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
+	DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
+	DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
+};
 
 void __init mx21_init_irq(void)
 {
 	mxc_init_irq(MX21_IO_ADDRESS(MX21_AVIC_BASE_ADDR));
-	imx21_register_gpios();
+	mxc_gpio_init(imx21_gpio_ports,	ARRAY_SIZE(imx21_gpio_ports));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx25.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx25.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx25.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx25.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,8 @@
 #include <mach/hardware.h>
 #include <mach/mx25.h>
 #include <mach/iomux-v3.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
 
 /*
  * This table defines static virtual address mappings for I/O regions.
@@ -45,18 +47,26 @@
  */
 void __init mx25_map_io(void)
 {
+	iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
+}
+
+void __init imx25_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX25);
 	mxc_iomux_v3_init(MX25_IO_ADDRESS(MX25_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX25_IO_ADDRESS(MX25_WDOG_BASE_ADDR));
-
-	iotable_init(mx25_io_desc, ARRAY_SIZE(mx25_io_desc));
 }
 
-int imx25_register_gpios(void);
+static struct mxc_gpio_port imx25_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
+};
 
 void __init mx25_init_irq(void)
 {
 	mxc_init_irq(MX25_IO_ADDRESS(MX25_AVIC_BASE_ADDR));
-	imx25_register_gpios();
+	mxc_gpio_init(imx25_gpio_ports,	ARRAY_SIZE(imx25_gpio_ports));
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx27.c linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx27.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-imx/mm-imx27.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-imx/mm-imx27.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,9 @@
 #include <mach/common.h>
 #include <asm/pgtable.h>
 #include <asm/mach/map.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+#include <mach/iomux-v1.h>
 
 /* MX27 memory map definition */
 static struct map_desc imx27_io_desc[] __initdata = {
@@ -56,16 +59,28 @@
  */
 void __init mx27_map_io(void)
 {
+	iotable_init(imx27_io_desc, ARRAY_SIZE(imx27_io_desc));
+}
+
+void __init imx27_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX27);
 	mxc_arch_reset_init(MX27_IO_ADDRESS(MX27_WDOG_BASE_ADDR));
-
-	iotable_init(imx27_io_desc, ARRAY_SIZE(imx27_io_desc));
+	imx_iomuxv1_init(MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR),
+			MX27_NUM_GPIO_PORT);
 }
 
-int imx27_register_gpios(void);
+static struct mxc_gpio_port imx27_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
+	DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
+	DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
+	DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
+	DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
+	DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
+};
 
 void __init mx27_init_irq(void)
 {
 	mxc_init_irq(MX27_IO_ADDRESS(MX27_AVIC_BASE_ADDR));
-	imx27_register_gpios();
+	mxc_gpio_init(imx27_gpio_ports,	ARRAY_SIZE(imx27_gpio_ports));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/common.h linux-libre-2.6.39-gnu/arch/arm/mach-integrator/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -1 +1,2 @@
+void integrator_init_early(void);
 void integrator_reserve(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/core.c linux-libre-2.6.39-gnu/arch/arm/mach-integrator/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,12 +144,15 @@
 	}
 };
 
+void __init integrator_init_early(void)
+{
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
+
 static int __init integrator_init(void)
 {
 	int i;
 
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
 		struct amba_device *d = amba_devs[i];
 		amba_device_register(d, &iomem_resource);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/impd1.c linux-libre-2.6.39-gnu/arch/arm/mach-integrator/impd1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/impd1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/impd1.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,6 +121,7 @@
 	.height		= -1,
 	.tim2		= TIM2_BCD | TIM2_IPC,
 	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551,
 	.connector	= IMPD1_CTRL_DISP_VGA,
 	.bpp		= 16,
 	.grayscale	= 0,
@@ -149,6 +150,7 @@
 	.tim2		= TIM2_BCD,
 	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
 	.connector	= IMPD1_CTRL_DISP_VGA,
+	.caps		= CLCD_CAP_5551,
 	.bpp		= 16,
 	.grayscale	= 0,
 };
@@ -175,6 +177,7 @@
 	.height		= -1,
 	.tim2		= TIM2_BCD,
 	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551,
 	.fixedtimings	= 1,
 	.connector	= IMPD1_CTRL_DISP_LCD,
 	.bpp		= 16,
@@ -206,6 +209,7 @@
 	.height		= -1,
 	.tim2		= TIM2_BCD,
 	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551,
 	.fixedtimings	= 1,
 	.connector	= IMPD1_CTRL_DISP_LCD,
 	.bpp		= 16,
@@ -279,6 +283,7 @@
 
 static struct clcd_board impd1_clcd_data = {
 	.name		= "IM-PD/1",
+	.caps		= CLCD_CAP_5551 | CLCD_CAP_888,
 	.check		= clcdfb_check,
 	.decode		= clcdfb_decode,
 	.disable	= impd1fb_clcd_disable,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/include/mach/cm.h linux-libre-2.6.39-gnu/arch/arm/mach-integrator/include/mach/cm.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/include/mach/cm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/include/mach/cm.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,9 +24,9 @@
 #define CM_CTRL_LCDBIASDN		(1 << 10)
 #define CM_CTRL_LCDMUXSEL_MASK		(7 << 11)
 #define CM_CTRL_LCDMUXSEL_GENLCD	(1 << 11)
-#define CM_CTRL_LCDMUXSEL_VGA_16BPP	(2 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA565_TFT555	(2 << 11)
 #define CM_CTRL_LCDMUXSEL_SHARPLCD	(3 << 11)
-#define CM_CTRL_LCDMUXSEL_VGA_8421BPP	(4 << 11)
+#define CM_CTRL_LCDMUXSEL_VGA555_TFT555	(4 << 11)
 #define CM_CTRL_LCDEN0			(1 << 14)
 #define CM_CTRL_LCDEN1			(1 << 15)
 #define CM_CTRL_STATIC1			(1 << 16)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-integrator/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #define BUS_OFFSET	UL(0x80000000)
 #define __virt_to_bus(x)	((x) - PAGE_OFFSET + BUS_OFFSET)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/integrator_ap.c linux-libre-2.6.39-gnu/arch/arm/mach-integrator/integrator_ap.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/integrator_ap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/integrator_ap.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,6 +48,8 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
+#include <plat/fpga-irq.h>
+
 #include "common.h"
 
 /* 
@@ -57,10 +59,10 @@
  * Setup a VA for the Integrator interrupt controller (for header #0,
  * just for now).
  */
-#define VA_IC_BASE	IO_ADDRESS(INTEGRATOR_IC_BASE) 
-#define VA_SC_BASE	IO_ADDRESS(INTEGRATOR_SC_BASE)
-#define VA_EBI_BASE	IO_ADDRESS(INTEGRATOR_EBI_BASE)
-#define VA_CMIC_BASE	IO_ADDRESS(INTEGRATOR_HDR_IC)
+#define VA_IC_BASE	__io_address(INTEGRATOR_IC_BASE)
+#define VA_SC_BASE	__io_address(INTEGRATOR_SC_BASE)
+#define VA_EBI_BASE	__io_address(INTEGRATOR_EBI_BASE)
+#define VA_CMIC_BASE	__io_address(INTEGRATOR_HDR_IC)
 
 /*
  * Logical      Physical
@@ -156,27 +158,14 @@
 
 #define INTEGRATOR_SC_VALID_INT	0x003fffff
 
-static void sc_mask_irq(struct irq_data *d)
-{
-	writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_CLEAR);
-}
-
-static void sc_unmask_irq(struct irq_data *d)
-{
-	writel(1 << d->irq, VA_IC_BASE + IRQ_ENABLE_SET);
-}
-
-static struct irq_chip sc_chip = {
-	.name		= "SC",
-	.irq_ack	= sc_mask_irq,
-	.irq_mask	= sc_mask_irq,
-	.irq_unmask	= sc_unmask_irq,
+static struct fpga_irq_data sc_irq_data = {
+	.base		= VA_IC_BASE,
+	.irq_start	= 0,
+	.chip.name	= "SC",
 };
 
 static void __init ap_init_irq(void)
 {
-	unsigned int i;
-
 	/* Disable all interrupts initially. */
 	/* Do the core module ones */
 	writel(-1, VA_CMIC_BASE + IRQ_ENABLE_CLEAR);
@@ -185,13 +174,7 @@
 	writel(-1, VA_IC_BASE + IRQ_ENABLE_CLEAR);
 	writel(-1, VA_IC_BASE + FIQ_ENABLE_CLEAR);
 
-	for (i = 0; i < NR_IRQS; i++) {
-		if (((1 << i) & INTEGRATOR_SC_VALID_INT) != 0) {
-			set_irq_chip(i, &sc_chip);
-			set_irq_handler(i, handle_level_irq);
-			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-		}
-	}
+	fpga_irq_init(-1, INTEGRATOR_SC_VALID_INT, &sc_irq_data);
 }
 
 #ifdef CONFIG_PM
@@ -282,7 +265,7 @@
 
 static void ap_flash_set_vpp(int on)
 {
-	unsigned long reg = on ? SC_CTRLS : SC_CTRLC;
+	void __iomem *reg = on ? SC_CTRLS : SC_CTRLC;
 
 	writel(INTEGRATOR_SC_CTRL_nFLVPPEN, reg);
 }
@@ -499,8 +482,9 @@
 MACHINE_START(INTEGRATOR, "ARM-Integrator")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.boot_params	= 0x00000100,
-	.map_io		= ap_map_io,
 	.reserve	= integrator_reserve,
+	.map_io		= ap_map_io,
+	.init_early	= integrator_init_early,
 	.init_irq	= ap_init_irq,
 	.timer		= &ap_timer,
 	.init_machine	= ap_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/integrator_cp.c linux-libre-2.6.39-gnu/arch/arm/mach-integrator/integrator_cp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/integrator_cp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/integrator_cp.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,10 @@
 
 #include <asm/hardware/timer-sp.h>
 
+#include <plat/clcd.h>
+#include <plat/fpga-irq.h>
+#include <plat/sched_clock.h>
+
 #include "common.h"
 
 #define INTCP_PA_FLASH_BASE		0x24000000
@@ -49,9 +53,9 @@
 
 #define INTCP_PA_CLCD_BASE		0xc0000000
 
-#define INTCP_VA_CIC_BASE		IO_ADDRESS(INTEGRATOR_HDR_BASE + 0x40)
-#define INTCP_VA_PIC_BASE		IO_ADDRESS(INTEGRATOR_IC_BASE)
-#define INTCP_VA_SIC_BASE		IO_ADDRESS(INTEGRATOR_CP_SIC_BASE)
+#define INTCP_VA_CIC_BASE		__io_address(INTEGRATOR_HDR_BASE + 0x40)
+#define INTCP_VA_PIC_BASE		__io_address(INTEGRATOR_IC_BASE)
+#define INTCP_VA_SIC_BASE		__io_address(INTEGRATOR_CP_SIC_BASE)
 
 #define INTCP_ETH_SIZE			0x10
 
@@ -139,129 +143,48 @@
 	iotable_init(intcp_io_desc, ARRAY_SIZE(intcp_io_desc));
 }
 
-#define cic_writel	__raw_writel
-#define cic_readl	__raw_readl
-#define pic_writel	__raw_writel
-#define pic_readl	__raw_readl
-#define sic_writel	__raw_writel
-#define sic_readl	__raw_readl
-
-static void cic_mask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_CIC_START;
-	cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
-}
-
-static void cic_unmask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_CIC_START;
-	cic_writel(1 << irq, INTCP_VA_CIC_BASE + IRQ_ENABLE_SET);
-}
-
-static struct irq_chip cic_chip = {
-	.name		= "CIC",
-	.irq_ack	= cic_mask_irq,
-	.irq_mask	= cic_mask_irq,
-	.irq_unmask	= cic_unmask_irq,
+static struct fpga_irq_data cic_irq_data = {
+	.base		= INTCP_VA_CIC_BASE,
+	.irq_start	= IRQ_CIC_START,
+	.chip.name	= "CIC",
 };
 
-static void pic_mask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_PIC_START;
-	pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
-}
-
-static void pic_unmask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_PIC_START;
-	pic_writel(1 << irq, INTCP_VA_PIC_BASE + IRQ_ENABLE_SET);
-}
-
-static struct irq_chip pic_chip = {
-	.name		= "PIC",
-	.irq_ack	= pic_mask_irq,
-	.irq_mask	= pic_mask_irq,
-	.irq_unmask	= pic_unmask_irq,
+static struct fpga_irq_data pic_irq_data = {
+	.base		= INTCP_VA_PIC_BASE,
+	.irq_start	= IRQ_PIC_START,
+	.chip.name	= "PIC",
 };
 
-static void sic_mask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_SIC_START;
-	sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
-}
-
-static void sic_unmask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_SIC_START;
-	sic_writel(1 << irq, INTCP_VA_SIC_BASE + IRQ_ENABLE_SET);
-}
-
-static struct irq_chip sic_chip = {
-	.name		= "SIC",
-	.irq_ack	= sic_mask_irq,
-	.irq_mask	= sic_mask_irq,
-	.irq_unmask	= sic_unmask_irq,
+static struct fpga_irq_data sic_irq_data = {
+	.base		= INTCP_VA_SIC_BASE,
+	.irq_start	= IRQ_SIC_START,
+	.chip.name	= "SIC",
 };
 
-static void
-sic_handle_irq(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned long status = sic_readl(INTCP_VA_SIC_BASE + IRQ_STATUS);
-
-	if (status == 0) {
-		do_bad_IRQ(irq, desc);
-		return;
-	}
-
-	do {
-		irq = ffs(status) - 1;
-		status &= ~(1 << irq);
-
-		irq += IRQ_SIC_START;
-
-		generic_handle_irq(irq);
-	} while (status);
-}
-
 static void __init intcp_init_irq(void)
 {
-	unsigned int i;
+	u32 pic_mask, sic_mask;
+
+	pic_mask = ~((~0u) << (11 - IRQ_PIC_START));
+	pic_mask |= (~((~0u) << (29 - 22))) << 22;
+	sic_mask = ~((~0u) << (1 + IRQ_SIC_END - IRQ_SIC_START));
 
 	/*
 	 * Disable all interrupt sources
 	 */
-	pic_writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
-	pic_writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
-
-	for (i = IRQ_PIC_START; i <= IRQ_PIC_END; i++) {
-		if (i == 11)
-			i = 22;
-		if (i == 29)
-			break;
-		set_irq_chip(i, &pic_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-
-	cic_writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
-	cic_writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
-
-	for (i = IRQ_CIC_START; i <= IRQ_CIC_END; i++) {
-		set_irq_chip(i, &cic_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
+	writel(0xffffffff, INTCP_VA_PIC_BASE + IRQ_ENABLE_CLEAR);
+	writel(0xffffffff, INTCP_VA_PIC_BASE + FIQ_ENABLE_CLEAR);
+	writel(0xffffffff, INTCP_VA_CIC_BASE + IRQ_ENABLE_CLEAR);
+	writel(0xffffffff, INTCP_VA_CIC_BASE + FIQ_ENABLE_CLEAR);
+	writel(sic_mask, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
+	writel(sic_mask, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
 
-	sic_writel(0x00000fff, INTCP_VA_SIC_BASE + IRQ_ENABLE_CLEAR);
-	sic_writel(0x00000fff, INTCP_VA_SIC_BASE + FIQ_ENABLE_CLEAR);
+	fpga_irq_init(-1, pic_mask, &pic_irq_data);
 
-	for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
-		set_irq_chip(i, &sic_chip);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
+	fpga_irq_init(-1, ~((~0u) << (1 + IRQ_CIC_END - IRQ_CIC_START)),
+		&cic_irq_data);
 
-	set_irq_chained_handler(IRQ_CP_CPPLDINT, sic_handle_irq);
+	fpga_irq_init(IRQ_CP_CPPLDINT, sic_mask, &sic_irq_data);
 }
 
 /*
@@ -449,43 +372,21 @@
 /*
  * CLCD support
  */
-static struct clcd_panel vga = {
-	.mode		= {
-		.name		= "VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 39721,
-		.left_margin	= 40,
-		.right_margin	= 24,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 96,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-	.grayscale	= 0,
-};
-
 /*
  * Ensure VGA is selected.
  */
 static void cp_clcd_enable(struct clcd_fb *fb)
 {
-	u32 val;
+	struct fb_var_screeninfo *var = &fb->fb.var;
+	u32 val = CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
 
-	if (fb->fb.var.bits_per_pixel <= 8)
-		val = CM_CTRL_LCDMUXSEL_VGA_8421BPP;
+	if (var->bits_per_pixel <= 8 ||
+	    (var->bits_per_pixel == 16 && var->green.length == 5))
+		/* Pseudocolor, RGB555, BGR555 */
+		val |= CM_CTRL_LCDMUXSEL_VGA555_TFT555;
 	else if (fb->fb.var.bits_per_pixel <= 16)
-		val = CM_CTRL_LCDMUXSEL_VGA_16BPP
-			| CM_CTRL_LCDEN0 | CM_CTRL_LCDEN1
-			| CM_CTRL_STATIC1 | CM_CTRL_STATIC2;
+		/* truecolor RGB565 */
+		val |= CM_CTRL_LCDMUXSEL_VGA565_TFT555;
 	else
 		val = 0; /* no idea for this, don't trust the docs */
 
@@ -498,49 +399,24 @@
 		   CM_CTRL_n24BITEN, val);
 }
 
-static unsigned long framesize = SZ_1M;
-
 static int cp_clcd_setup(struct clcd_fb *fb)
 {
-	dma_addr_t dma;
-
-	fb->panel = &vga;
-
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-						    &dma, GFP_KERNEL);
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
-	}
-
-	fb->fb.fix.smem_start	= dma;
-	fb->fb.fix.smem_len	= framesize;
-
-	return 0;
-}
-
-static int cp_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-				     fb->fb.screen_base,
-				     fb->fb.fix.smem_start,
-				     fb->fb.fix.smem_len);
-}
+	fb->panel = versatile_clcd_get_panel("VGA");
+	if (!fb->panel)
+		return -EINVAL;
 
-static void cp_clcd_remove(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-			      fb->fb.screen_base, fb->fb.fix.smem_start);
+	return versatile_clcd_setup_dma(fb, SZ_1M);
 }
 
 static struct clcd_board clcd_data = {
 	.name		= "Integrator/CP",
+	.caps		= CLCD_CAP_5551 | CLCD_CAP_RGB565 | CLCD_CAP_888,
 	.check		= clcdfb_check,
 	.decode		= clcdfb_decode,
 	.enable		= cp_clcd_enable,
 	.setup		= cp_clcd_setup,
-	.mmap		= cp_clcd_mmap,
-	.remove		= cp_clcd_remove,
+	.mmap		= versatile_clcd_mmap_dma,
+	.remove		= versatile_clcd_remove_dma,
 };
 
 static struct amba_device clcd_device = {
@@ -565,11 +441,23 @@
 	&clcd_device,
 };
 
+#define REFCOUNTER (__io_address(INTEGRATOR_HDR_BASE) + 0x28)
+
+static void __init intcp_init_early(void)
+{
+	clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
+
+	integrator_init_early();
+
+#ifdef CONFIG_PLAT_VERSATILE_SCHED_CLOCK
+	versatile_sched_clock_init(REFCOUNTER, 24000000);
+#endif
+}
+
 static void __init intcp_init(void)
 {
 	int i;
 
-	clkdev_add_table(cp_lookups, ARRAY_SIZE(cp_lookups));
 	platform_add_devices(intcp_devs, ARRAY_SIZE(intcp_devs));
 
 	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
@@ -599,8 +487,9 @@
 MACHINE_START(CINTEGRATOR, "ARM-IntegratorCP")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.boot_params	= 0x00000100,
-	.map_io		= intcp_map_io,
 	.reserve	= integrator_reserve,
+	.map_io		= intcp_map_io,
+	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq,
 	.timer		= &cp_timer,
 	.init_machine	= intcp_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-integrator/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-integrator/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-integrator/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-integrator/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 	bool "Support Integrator/CP platform"
 	select ARCH_CINTEGRATOR
 	select ARM_TIMER_SP804
+	select PLAT_VERSATILE_CLCD
 	help
 	  Include support for the ARM(R) Integrator CP platform.
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #ifndef __ASSEMBLY__
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -224,15 +224,15 @@
 
 	for(i = 0; i <= IRQ_IOP13XX_HPI; i++) {
 		if (i < 32)
-			set_irq_chip(i, &iop13xx_irqchip1);
+			irq_set_chip(i, &iop13xx_irqchip1);
 		else if (i < 64)
-			set_irq_chip(i, &iop13xx_irqchip2);
+			irq_set_chip(i, &iop13xx_irqchip2);
 		else if (i < 96)
-			set_irq_chip(i, &iop13xx_irqchip3);
+			irq_set_chip(i, &iop13xx_irqchip3);
 		else
-			set_irq_chip(i, &iop13xx_irqchip4);
+			irq_set_chip(i, &iop13xx_irqchip4);
 
-		set_irq_handler(i, handle_level_irq);
+		irq_set_handler(i, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/msi.c linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/msi.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,7 @@
 
 void __init iop13xx_msi_init(void)
 {
-	set_irq_chained_handler(IRQ_IOP13XX_INBD_MSI, iop13xx_msi_handler);
+	irq_set_chained_handler(IRQ_IOP13XX_INBD_MSI, iop13xx_msi_handler);
 }
 
 /*
@@ -178,7 +178,7 @@
 	if (irq < 0)
 		return irq;
 
-	set_irq_msi(irq, desc);
+	irq_set_msi_desc(irq, desc);
 
 	msg.address_hi = 0x0;
 	msg.address_lo = IOP13XX_MU_MIMR_PCI;
@@ -187,7 +187,7 @@
 	msg.data = (id << IOP13XX_MU_MIMR_CORE_SELECT) | (irq & 0x7f);
 
 	write_msi_msg(irq, &msg);
-	set_irq_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq);
+	irq_set_chip_and_handler(irq, &iop13xx_msi_chip, handle_simple_irq);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/pci.c linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop13xx/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop13xx/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,7 +225,7 @@
 /* This routine checks the status of the last configuration cycle.  If an error
  * was detected it returns >0, else it returns a 0.  The errors being checked
  * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
+ * errors occur during a config cycle where there is no device, like during
  * the discovery stage.
  */
 static int iop13xx_atux_pci_status(int clear)
@@ -332,7 +332,7 @@
 /* This routine checks the status of the last configuration cycle.  If an error
  * was detected it returns >0, else it returns a 0.  The errors being checked
  * are parity, master abort, target abort (master and target).  These types of
- * errors occure during a config cycle where there is no device, like during
+ * errors occur during a config cycle where there is no device, like during
  * the discovery stage.
  */
 static int iop13xx_atue_pci_status(int clear)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop32x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-iop32x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop32x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop32x/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0xa0000000)
+#define PLAT_PHYS_OFFSET	UL(0xa0000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop32x/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-iop32x/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop32x/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop32x/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,8 +68,7 @@
 		*IOP3XX_PCIIRSR = 0x0f;
 
 	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_chip(i, &ext_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &ext_chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop33x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-iop33x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop33x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop33x/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-iop33x/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-iop33x/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-iop33x/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-iop33x/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,8 +110,9 @@
 		*IOP3XX_PCIIRSR = 0x0f;
 
 	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_chip(i, (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i,
+					 (i < 32) ? &iop33x_irqchip1 : &iop33x_irqchip2,
+					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/core.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -476,8 +476,8 @@
 	 */
 	for (irq = IRQ_IXP2000_SOFT_INT; irq <= IRQ_IXP2000_THDB3; irq++) {
 		if ((1 << irq) & IXP2000_VALID_IRQ_MASK) {
-			set_irq_chip(irq, &ixp2000_irq_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &ixp2000_irq_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID);
 		} else set_irq_flags(irq, 0);
 	}
@@ -485,21 +485,21 @@
 	for (irq = IRQ_IXP2000_DRAM0_MIN_ERR; irq <= IRQ_IXP2000_SP_INT; irq++) {
 		if((1 << (irq - IRQ_IXP2000_DRAM0_MIN_ERR)) &
 				IXP2000_VALID_ERR_IRQ_MASK) {
-			set_irq_chip(irq, &ixp2000_err_irq_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &ixp2000_err_irq_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID);
 		}
 		else
 			set_irq_flags(irq, 0);
 	}
-	set_irq_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
+	irq_set_chained_handler(IRQ_IXP2000_ERRSUM, ixp2000_err_irq_handler);
 
 	for (irq = IRQ_IXP2000_GPIO0; irq <= IRQ_IXP2000_GPIO7; irq++) {
-		set_irq_chip(irq, &ixp2000_GPIO_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &ixp2000_GPIO_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
-	set_irq_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
+	irq_set_chained_handler(IRQ_IXP2000_GPIO, ixp2000_GPIO_irq_handler);
 
 	/*
 	 * Enable PCI irqs.  The actual PCI[AB] decoding is done in
@@ -508,8 +508,8 @@
 	 */
 	ixp2000_reg_write(IXP2000_IRQ_ENABLE_SET, (1 << IRQ_IXP2000_PCI));
 	for (irq = IRQ_IXP2000_PCIA; irq <= IRQ_IXP2000_PCIB; irq++) {
-		set_irq_chip(irq, &ixp2000_pci_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &ixp2000_pci_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #include <mach/ixp2000-regs.h>
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/ixdp2x00.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/ixdp2x00.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/ixdp2x00.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/ixdp2x00.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,13 +158,13 @@
 	*board_irq_mask = 0xffffffff;
 
 	for(irq = IXP2000_BOARD_IRQ(0); irq < IXP2000_BOARD_IRQ(board_irq_count); irq++) {
-		set_irq_chip(irq, &ixdp2x00_cpld_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &ixdp2x00_cpld_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
 	/* Hook into PCI interrupt */
-	set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
+	irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x00_irq_handler);
 }
 
 /*************************************************************************
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/ixdp2x01.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/ixdp2x01.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp2000/ixdp2x01.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp2000/ixdp2x01.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,8 +115,8 @@
 
 	for (irq = NR_IXP2000_IRQS; irq < NR_IXDP2X01_IRQS; irq++) {
 		if (irq & valid_irq_mask) {
-			set_irq_chip(irq, &ixdp2x01_irq_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &ixdp2x01_irq_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, IRQF_VALID);
 		} else {
 			set_irq_flags(irq, 0);
@@ -124,7 +124,7 @@
 	}
 
 	/* Hook into PCI interrupts */
-	set_irq_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler);
+	irq_set_chained_handler(IRQ_IXP2000_PCIB, ixdp2x01_irq_handler);
 }
 
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/core.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -289,12 +289,12 @@
 {
 	switch (type) {
 	case IXP23XX_IRQ_LEVEL:
-		set_irq_chip(irq, &ixp23xx_irq_level_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &ixp23xx_irq_level_chip,
+					 handle_level_irq);
 		break;
 	case IXP23XX_IRQ_EDGE:
-		set_irq_chip(irq, &ixp23xx_irq_edge_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &ixp23xx_irq_edge_chip,
+					 handle_edge_irq);
 		break;
 	}
 	set_irq_flags(irq, IRQF_VALID);
@@ -324,12 +324,12 @@
 	}
 
 	for (irq = IRQ_IXP23XX_INTA; irq <= IRQ_IXP23XX_INTB; irq++) {
-		set_irq_chip(irq, &ixp23xx_pci_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &ixp23xx_pci_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	set_irq_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
+	irq_set_chained_handler(IRQ_IXP23XX_PCI_INT_RPH, pci_handler);
 }
 
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		(0x00000000)
+#define PLAT_PHYS_OFFSET		(0x00000000)
 
 #define IXP23XX_PCI_SDRAM_OFFSET (*((volatile int *)IXP23XX_PCI_SDRAM_BAR) & 0xfffffff0)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/ixdp2351.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/ixdp2351.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/ixdp2351.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/ixdp2351.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,8 +136,8 @@
 	     irq++) {
 		if (IXDP2351_INTA_IRQ_MASK(irq) & IXDP2351_INTA_IRQ_VALID) {
 			set_irq_flags(irq, IRQF_VALID);
-			set_irq_handler(irq, handle_level_irq);
-			set_irq_chip(irq, &ixdp2351_inta_chip);
+			irq_set_chip_and_handler(irq, &ixdp2351_inta_chip,
+						 handle_level_irq);
 		}
 	}
 
@@ -147,13 +147,13 @@
 	     irq++) {
 		if (IXDP2351_INTB_IRQ_MASK(irq) & IXDP2351_INTB_IRQ_VALID) {
 			set_irq_flags(irq, IRQF_VALID);
-			set_irq_handler(irq, handle_level_irq);
-			set_irq_chip(irq, &ixdp2351_intb_chip);
+			irq_set_chip_and_handler(irq, &ixdp2351_intb_chip,
+						 handle_level_irq);
 		}
 	}
 
-	set_irq_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler);
-	set_irq_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler);
+	irq_set_chained_handler(IRQ_IXP23XX_INTA, ixdp2351_inta_handler);
+	irq_set_chained_handler(IRQ_IXP23XX_INTB, ixdp2351_intb_handler);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/roadrunner.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/roadrunner.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp23xx/roadrunner.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp23xx/roadrunner.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,8 +110,8 @@
 
 static void __init roadrunner_pci_preinit(void)
 {
-	set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_ROADRUNNER_PCI_INTC, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_ROADRUNNER_PCI_INTD, IRQ_TYPE_LEVEL_LOW);
 
 	ixp23xx_pci_preinit();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/avila-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/avila-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/avila-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/avila-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,10 +39,10 @@
 
 void __init avila_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/common.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -252,8 +252,8 @@
 
         /* Default to all level triggered */
 	for(i = 0; i < NR_IRQS; i++) {
-		set_irq_chip(i, &ixp4xx_irq_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &ixp4xx_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/coyote-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/coyote-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/coyote-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/coyote-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,8 +32,8 @@
 
 void __init coyote_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT0_INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(SLOT1_INTA), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/dsmg600-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/dsmg600-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/dsmg600-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/dsmg600-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,12 +35,12 @@
 
 void __init dsmg600_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTF), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/fsg-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/fsg-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/fsg-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/fsg-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,9 +32,9 @@
 
 void __init fsg_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/gateway7001-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/gateway7001-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/gateway7001-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/gateway7001-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,8 +29,8 @@
 
 void __init gateway7001_pci_preinit(void)
 {
-	set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO10, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO11, IRQ_TYPE_LEVEL_LOW);
 
 	ixp4xx_pci_preinit();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/goramo_mlr.c	2011-05-19 00:06:34.000000000 -0400
@@ -420,8 +420,8 @@
 	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(IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH);
-	set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS0_DCD_N), IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_HSS1_DCD_N), IRQ_TYPE_EDGE_BOTH);
 
 	set_control(CONTROL_HSS0_DTR_N, 1);
 	set_control(CONTROL_HSS1_DTR_N, 1);
@@ -441,10 +441,10 @@
 #ifdef CONFIG_PCI
 static void __init gmlr_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_ETHB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_NEC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(GPIO_IRQ_MPCI), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/gtwx5715-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/gtwx5715-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/gtwx5715-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/gtwx5715-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,8 +43,8 @@
  */
 void __init gtwx5715_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/ixdp425-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/ixdp425-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/ixdp425-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/ixdp425-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,10 +36,10 @@
 
 void __init ixdp425_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/ixdpg425-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/ixdpg425-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/ixdpg425-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/ixdpg425-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,8 +25,8 @@
 
 void __init ixdpg425_pci_preinit(void)
 {
-	set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO6, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO7, IRQ_TYPE_LEVEL_LOW);
 
 	ixp4xx_pci_preinit();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/nas100d-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/nas100d-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/nas100d-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/nas100d-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,11 +33,11 @@
 
 void __init nas100d_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTD), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTE), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/nslu2-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/nslu2-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/nslu2-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/nslu2-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,9 +32,9 @@
 
 void __init nslu2_pci_preinit(void)
 {
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTC), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/vulcan-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/vulcan-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/vulcan-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/vulcan-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,8 +38,8 @@
 	pr_info("Vulcan PCI: limiting CardBus memory size to %dMB\n",
 		(int)(pci_cardbus_mem_size >> 20));
 #endif
-	set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTA), IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IXP4XX_GPIO_IRQ(INTB), IRQ_TYPE_LEVEL_LOW);
 	ixp4xx_pci_preinit();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/wg302v2-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/wg302v2-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ixp4xx/wg302v2-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ixp4xx/wg302v2-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,8 +29,8 @@
 
 void __init wg302v2_pci_preinit(void)
 {
-	set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
-	set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO8, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ_IXP4XX_GPIO9, IRQ_TYPE_LEVEL_LOW);
 
 	ixp4xx_pci_preinit();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/common.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include <net/dsa.h>
 #include <asm/page.h>
 #include <asm/timex.h>
+#include <asm/kexec.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <mach/kirkwood.h>
@@ -846,9 +847,14 @@
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init kirkwood_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 int kirkwood_tclk;
 
-int __init kirkwood_find_tclk(void)
+static int __init kirkwood_find_tclk(void)
 {
 	u32 dev, rev;
 
@@ -864,7 +870,9 @@
 static void __init kirkwood_timer_init(void)
 {
 	kirkwood_tclk = kirkwood_find_tclk();
-	orion_time_init(IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
+
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
 struct sys_timer kirkwood_timer = {
@@ -1003,6 +1011,10 @@
 	kirkwood_xor0_init();
 	kirkwood_xor1_init();
 	kirkwood_crypto_init();
+
+#ifdef CONFIG_KEXEC 
+	kexec_reinit = kirkwood_enable_pcie;
+#endif
 }
 
 static int __init kirkwood_clock_gate(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/common.h linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,11 +27,13 @@
  */
 void kirkwood_map_io(void);
 void kirkwood_init(void);
+void kirkwood_init_early(void);
 void kirkwood_init_irq(void);
 
 extern struct mbus_dram_target_info kirkwood_mbus_dram_info;
 void kirkwood_setup_cpu_mbus(void);
 
+void kirkwood_enable_pcie(void);
 void kirkwood_pcie_id(u32 *dev, u32 *rev);
 
 void kirkwood_ehci_init(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/d2net_v2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -224,6 +224,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/db88f6281-bp-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,6 +100,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= db88f6281_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/dockstar-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/dockstar-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/dockstar-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/dockstar-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,6 +105,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= dockstar_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/guruplug-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/guruplug-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/guruplug-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/guruplug-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -124,6 +124,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= guruplug_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/bridge-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,9 +29,6 @@
 #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
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,33 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define GPIO_MAX		50
-#define GPIO_OFF(pin)		(((pin) >> 5) ? 0x0140 : 0x0100)
-#define GPIO_OUT(pin)		(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x00)
-#define GPIO_IO_CONF(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x04)
-#define GPIO_BLINK_EN(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x08)
-#define GPIO_IN_POL(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x0c)
-#define GPIO_DATA_IN(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x10)
-#define GPIO_EDGE_CAUSE(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x14)
-#define GPIO_EDGE_MASK(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x18)
-#define GPIO_LEVEL_MASK(pin)	(DEV_BUS_VIRT_BASE + GPIO_OFF(pin) + 0x1c)
-
-static inline int gpio_to_irq(int pin)
-{
-	return pin + IRQ_KIRKWOOD_GPIO_START;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	return irq - IRQ_KIRKWOOD_GPIO_START;
-}
-
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/kirkwood.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,6 +69,8 @@
 #define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE | 0x10000)
 #define  SAMPLE_AT_RESET	(DEV_BUS_VIRT_BASE | 0x0030)
 #define  DEVICE_ID		(DEV_BUS_VIRT_BASE | 0x0034)
+#define  GPIO_LOW_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x0100)
+#define  GPIO_HIGH_VIRT_BASE	(DEV_BUS_VIRT_BASE | 0x0140)
 #define  RTC_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0300)
 #define  SPI_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x0600)
 #define  I2C_PHYS_BASE		(DEV_BUS_PHYS_BASE | 0x1000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,32 +27,23 @@
 
 void __init kirkwood_init_irq(void)
 {
-	int i;
-
 	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));
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts.
+	 * Initialize gpiolib for GPIOs 0-49.
 	 */
-	writel(0, GPIO_LEVEL_MASK(0));
-	writel(0, GPIO_EDGE_MASK(0));
-	writel(0, GPIO_EDGE_CAUSE(0));
-	writel(0, GPIO_LEVEL_MASK(32));
-	writel(0, GPIO_EDGE_MASK(32));
-	writel(0, GPIO_EDGE_CAUSE(32));
+	orion_gpio_init(0, 32, GPIO_LOW_VIRT_BASE, 0,
+			IRQ_KIRKWOOD_GPIO_START);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
 
-	for (i = IRQ_KIRKWOOD_GPIO_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_0_7, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_8_15, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_16_23, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_LOW_24_31, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23, gpio_irq_handler);
+	orion_gpio_init(32, 18, GPIO_HIGH_VIRT_BASE, 0,
+			IRQ_KIRKWOOD_GPIO_START + 32);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_0_7, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_8_15, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_KIRKWOOD_GPIO_HIGH_16_23,
+				gpio_irq_handler);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/mpp.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/mpp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/mpp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/mpp.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,9 +49,6 @@
 	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.38-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -166,6 +166,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= mv88f6281gtw_ge_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/netspace_v2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -261,6 +261,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -271,6 +272,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -281,6 +283,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= netspace_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/netxbig_v2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -402,6 +402,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -412,6 +413,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= netxbig_v2_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/openrd-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/openrd-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/openrd-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/openrd-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -217,6 +217,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -228,6 +229,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -239,6 +241,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= openrd_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/pcie.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/pcie.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/pcie.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/pcie.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,8 +18,16 @@
 #include <mach/bridge-regs.h>
 #include "common.h"
 
+void kirkwood_enable_pcie(void)
+{
+	u32 curr = readl(CLOCK_GATING_CTRL);
+	if (!(curr & CGC_PEX0))
+		writel(curr | CGC_PEX0, CLOCK_GATING_CTRL);
+}
+
 void __init kirkwood_pcie_id(u32 *dev, u32 *rev)
 {
+	kirkwood_enable_pcie();
 	*dev = orion_pcie_dev_id((void __iomem *)PCIE_VIRT_BASE);
 	*rev = orion_pcie_rev((void __iomem *)PCIE_VIRT_BASE);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,6 +82,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6192_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/rd88f6281-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,6 +118,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6281_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/sheevaplug-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,12 @@
 
 static struct gpio_led sheevaplug_led_pins[] = {
 	{
+		.name			= "plug:red:misc",
+		.default_trigger	= "none",
+		.gpio			= 46,
+		.active_low		= 1,
+	},
+	{
 		.name			= "plug:green:health",
 		.default_trigger	= "default-on",
 		.gpio			= 49,
@@ -80,6 +86,7 @@
 
 static unsigned int sheevaplug_mpp_config[] __initdata = {
 	MPP29_GPIO,	/* USB Power Enable */
+	MPP46_GPIO,	/* LED Red */
 	MPP49_GPIO,	/* LED */
 	0
 };
@@ -134,6 +141,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
@@ -144,6 +152,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= sheevaplug_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/t5325-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/t5325-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/t5325-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/t5325-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
+#include <sound/alc5623.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/kirkwood.h>
@@ -134,6 +135,7 @@
 	MPP33_GE1_TXCTL,
 	MPP39_AU_I2SBCLK,
 	MPP40_AU_I2SDO,
+	MPP43_AU_I2SDI,
 	MPP41_AU_I2SLRCLK,
 	MPP42_AU_I2SMCLK,
 	MPP45_GPIO,		/* Power button */
@@ -141,6 +143,18 @@
 	0
 };
 
+static struct alc5623_platform_data alc5621_data = {
+	.add_ctrl = 0x3700,
+	.jack_det_ctrl = 0x4810,
+};
+
+static struct i2c_board_info i2c_board_info[] __initdata = {
+	{
+		I2C_BOARD_INFO("alc5621", 0x1a),
+		.platform_data = &alc5621_data,
+	},
+};
+
 #define HP_T5325_GPIO_POWER_OFF		48
 
 static void hp_t5325_power_off(void)
@@ -166,6 +180,9 @@
 	kirkwood_ehci_init();
 	platform_device_register(&hp_t5325_button_device);
 
+	i2c_register_board_info(0, i2c_board_info, ARRAY_SIZE(i2c_board_info));
+	kirkwood_audio_init();
+
 	if (gpio_request(HP_T5325_GPIO_POWER_OFF, "power-off") == 0 &&
 	    gpio_direction_output(HP_T5325_GPIO_POWER_OFF, 0) == 0)
 		pm_power_off = hp_t5325_power_off;
@@ -187,6 +204,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= hp_t5325_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/ts219-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/ts219-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/ts219-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,6 +135,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts219_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/ts41x-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/ts41x-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/ts41x-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/ts41x-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -154,6 +154,8 @@
 static int __init ts41x_pci_init(void)
 {
 	if (machine_is_ts41x()) {
+		u32 dev, rev;
+
 		/*
 		 * Without this explicit reset, the PCIe SATA controller
 		 * (Marvell 88sx7042/sata_mv) is known to stop working
@@ -161,7 +163,11 @@
 		 */
 		orion_pcie_reset((void __iomem *)PCIE_VIRT_BASE);
 
-		kirkwood_pcie_init(KW_PCIE0);
+		kirkwood_pcie_id(&dev, &rev);
+		if (dev == MV88F6282_DEV_ID)
+			kirkwood_pcie_init(KW_PCIE1 | KW_PCIE0);
+		else
+			kirkwood_pcie_init(KW_PCIE0);
 	}
 
    return 0;
@@ -173,6 +179,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts41x_init,
 	.map_io		= kirkwood_map_io,
+	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
 	.timer		= &kirkwood_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/tsx1x-common.c linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/tsx1x-common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-kirkwood/tsx1x-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-kirkwood/tsx1x-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 
 /****************************************************************************
  * 16 MiB NOR flash. The struct mtd_partition is not in the same order as the
- *     partitions on the device because we want to keep compatability with
+ *     partitions on the device because we want to keep compatibility with
  *     the QNAP firmware.
  * Layout as used by QNAP:
  *  0x00000000-0x00080000 : "U-Boot"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ks8695/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-ks8695/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ks8695/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ks8695/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,7 +80,7 @@
 	local_irq_restore(flags);
 
 	/* Set IRQ triggering type */
-	set_irq_type(gpio_irq[pin], type);
+	irq_set_irq_type(gpio_irq[pin], type);
 
 	/* enable interrupt mode */
 	ks8695_gpio_mode(pin, 0);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ks8695/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ks8695/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ks8695/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ks8695/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
 /*
  * Physical SRAM offset.
  */
-#define PHYS_OFFSET		KS8695_SDRAM_PA
+#define PLAT_PHYS_OFFSET		KS8695_SDRAM_PA
 
 #ifndef __ASSEMBLY__
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ks8695/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-ks8695/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ks8695/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ks8695/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,12 +115,12 @@
 	}
 
 	if (level_triggered) {
-		set_irq_chip(d->irq, &ks8695_irq_level_chip);
-		set_irq_handler(d->irq, handle_level_irq);
+		irq_set_chip_and_handler(d->irq, &ks8695_irq_level_chip,
+					 handle_level_irq);
 	}
 	else {
-		set_irq_chip(d->irq, &ks8695_irq_edge_chip);
-		set_irq_handler(d->irq, handle_edge_irq);
+		irq_set_chip_and_handler(d->irq, &ks8695_irq_edge_chip,
+					 handle_edge_irq);
 	}
 
 	__raw_writel(ctrl, KS8695_GPIO_VA + KS8695_IOPC);
@@ -158,16 +158,18 @@
 			case KS8695_IRQ_UART_RX:
 			case KS8695_IRQ_COMM_TX:
 			case KS8695_IRQ_COMM_RX:
-				set_irq_chip(irq, &ks8695_irq_level_chip);
-				set_irq_handler(irq, handle_level_irq);
+				irq_set_chip_and_handler(irq,
+							 &ks8695_irq_level_chip,
+							 handle_level_irq);
 				break;
 
 			/* Edge-triggered interrupts */
 			default:
 				/* clear pending bit */
 				ks8695_irq_ack(irq_get_irq_data(irq));
-				set_irq_chip(irq, &ks8695_irq_edge_chip);
-				set_irq_handler(irq, handle_edge_irq);
+				irq_set_chip_and_handler(irq,
+							 &ks8695_irq_edge_chip,
+							 handle_edge_irq);
 		}
 
 		set_irq_flags(irq, IRQF_VALID);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/arch-kev7a400.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/arch-kev7a400.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/arch-kev7a400.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/arch-kev7a400.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,118 +0,0 @@
-/* arch/arm/mach-lh7a40x/arch-kev7a400.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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/tty.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-      /* This function calls the board specific IRQ initialization function. */
-
-static struct map_desc kev7a400_io_desc[] __initdata = {
-	{
-		.virtual	= IO_VIRT,
-		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	}, {
-		.virtual	= CPLD_VIRT,
-		.pfn		= __phys_to_pfn(CPLD_PHYS),
-		.length		= CPLD_SIZE,
-		.type		= MT_DEVICE
-	}
-};
-
-void __init kev7a400_map_io(void)
-{
-	iotable_init (kev7a400_io_desc, ARRAY_SIZE (kev7a400_io_desc));
-}
-
-static u16 CPLD_IRQ_mask;	/* Mask for CPLD IRQs, 1 == unmasked */
-
-static void kev7a400_ack_cpld_irq(struct irq_data *d)
-{
-	CPLD_CL_INT = 1 << (d->irq - IRQ_KEV7A400_CPLD);
-}
-
-static void kev7a400_mask_cpld_irq(struct irq_data *d)
-{
-	CPLD_IRQ_mask &= ~(1 << (d->irq - IRQ_KEV7A400_CPLD));
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static void kev7a400_unmask_cpld_irq(struct irq_data *d)
-{
-	CPLD_IRQ_mask |= 1 << (d->irq - IRQ_KEV7A400_CPLD);
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static struct irq_chip kev7a400_cpld_chip = {
-	.name		= "CPLD",
-	.irq_ack	= kev7a400_ack_cpld_irq,
-	.irq_mask	= kev7a400_mask_cpld_irq,
-	.irq_unmask	= kev7a400_unmask_cpld_irq,
-};
-
-
-static void kev7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	u32 mask = CPLD_LATCHED_INTS;
-	irq = IRQ_KEV7A400_CPLD;
-	for (; mask; mask >>= 1, ++irq)
-		if (mask & 1)
-			generic_handle_irq(irq);
-}
-
-void __init lh7a40x_init_board_irq (void)
-{
-	int irq;
-
-	for (irq = IRQ_KEV7A400_CPLD;
-	     irq < IRQ_KEV7A400_CPLD + NR_IRQ_BOARD; ++irq) {
-		set_irq_chip (irq, &kev7a400_cpld_chip);
-		set_irq_handler (irq, handle_edge_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-	set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
-
-		/* Clear all CPLD interrupts */
-	CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
-
-	GPIO_GPIOINTEN = 0;		/* Disable all GPIO interrupts */
-	barrier();
-
-#if 0
-	GPIO_INTTYPE1
-		= (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
-	GPIO_INTTYPE2 = 0;		/* Falling edge & low-level */
-	GPIO_GPIOFEOI = 0xff;		/* Clear all GPIO interrupts */
-	GPIO_GPIOINTEN = 0xff;		/* Enable all GPIO interrupts */
-
-	init_FIQ();
-#endif
-}
-
-MACHINE_START (KEV7A400, "Sharp KEV7a400")
-	/* Maintainer: Marc Singer */
-	.boot_params	= 0xc0000100,
-	.map_io		= kev7a400_map_io,
-	.init_irq	= lh7a400_init_irq,
-	.timer		= &lh7a40x_timer,
-MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/arch-lpd7a40x.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/arch-lpd7a40x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/arch-lpd7a40x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,422 +0,0 @@
-/* arch/arm/mach-lh7a40x/arch-lpd7a40x.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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/tty.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <mach/hardware.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/map.h>
-
-#include "common.h"
-
-#define CPLD_INT_NETHERNET	(1<<0)
-#define CPLD_INTMASK_ETHERNET	(1<<2)
-#if defined (CONFIG_MACH_LPD7A400)
-# define CPLD_INT_NTOUCH		(1<<1)
-# define CPLD_INTMASK_TOUCH	(1<<3)
-# define CPLD_INT_PEN		(1<<4)
-# define CPLD_INTMASK_PEN	(1<<4)
-# define CPLD_INT_PIRQ		(1<<4)
-#endif
-#define CPLD_INTMASK_CPLD	(1<<7)
-#define CPLD_INT_CPLD		(1<<6)
-
-#define CPLD_CONTROL_SWINT		(1<<7) /* Disable all CPLD IRQs */
-#define CPLD_CONTROL_OCMSK		(1<<6) /* Mask USB1 connect IRQ */
-#define CPLD_CONTROL_PDRV		(1<<5) /* PCC_nDRV high */
-#define CPLD_CONTROL_USB1C		(1<<4) /* USB1 connect IRQ active */
-#define CPLD_CONTROL_USB1P		(1<<3) /* USB1 power disable */
-#define CPLD_CONTROL_AWKP		(1<<2) /* Auto-wakeup disabled  */
-#define CPLD_CONTROL_LCD_ENABLE		(1<<1) /* LCD Vee enable */
-#define CPLD_CONTROL_WRLAN_NENABLE	(1<<0) /* SMC91x power disable */
-
-
-static struct resource smc91x_resources[] = {
-	[0] = {
-		.start	= CPLD00_PHYS,
-		.end	= CPLD00_PHYS + CPLD00_SIZE - 1, /* Only needs 16B */
-		.flags	= IORESOURCE_MEM,
-	},
-
-	[1] = {
-		.start	= IRQ_LPD7A40X_ETH_INT,
-		.end	= IRQ_LPD7A40X_ETH_INT,
-		.flags	= IORESOURCE_IRQ,
-	},
-
-};
-
-static struct platform_device smc91x_device = {
-	.name		= "smc91x",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(smc91x_resources),
-	.resource	= smc91x_resources,
-};
-
-static struct resource lh7a40x_usbclient_resources[] = {
-	[0] = {
-		.start	= USB_PHYS,
-		.end	= (USB_PHYS + PAGE_SIZE),
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USB,
-		.end	= IRQ_USB,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 lh7a40x_usbclient_dma_mask = 0xffffffffUL;
-
-static struct platform_device lh7a40x_usbclient_device = {
-//	.name		= "lh7a40x_udc",
-	.name		= "lh7-udc",
-	.id		= 0,
-	.dev		= {
-		.dma_mask = &lh7a40x_usbclient_dma_mask,
-		.coherent_dma_mask = 0xffffffffUL,
-	},
-	.num_resources	= ARRAY_SIZE (lh7a40x_usbclient_resources),
-	.resource	= lh7a40x_usbclient_resources,
-};
-
-#if defined (CONFIG_ARCH_LH7A404)
-
-static struct resource lh7a404_usbhost_resources [] = {
-	[0] = {
-		.start	= USBH_PHYS,
-		.end	= (USBH_PHYS + 0xFF),
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_USHINTR,
-		.end	= IRQ_USHINTR,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static u64 lh7a404_usbhost_dma_mask = 0xffffffffUL;
-
-static struct platform_device lh7a404_usbhost_device = {
-	.name		= "lh7a404-ohci",
-	.id		= 0,
-	.dev		= {
-		.dma_mask = &lh7a404_usbhost_dma_mask,
-		.coherent_dma_mask = 0xffffffffUL,
-	},
-	.num_resources	= ARRAY_SIZE (lh7a404_usbhost_resources),
-	.resource	= lh7a404_usbhost_resources,
-};
-
-#endif
-
-static struct platform_device* lpd7a40x_devs[] __initdata = {
-	&smc91x_device,
-	&lh7a40x_usbclient_device,
-#if defined (CONFIG_ARCH_LH7A404)
-	&lh7a404_usbhost_device,
-#endif
-};
-
-extern void lpd7a400_map_io (void);
-
-static void __init lpd7a40x_init (void)
-{
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_CONTROL |= 0
-		| CPLD_CONTROL_SWINT /* Disable software interrupt */
-		| CPLD_CONTROL_OCMSK; /* Mask USB1 connection IRQ */
-	CPLD_CONTROL &= ~(0
-			  | CPLD_CONTROL_LCD_ENABLE	/* Disable LCD */
-			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
-		);
-#endif
-
-#if defined (CONFIG_MACH_LPD7A404)
-	CPLD_CONTROL &= ~(0
-			  | CPLD_CONTROL_WRLAN_NENABLE	/* Enable SMC91x */
-		);
-#endif
-
-	platform_add_devices (lpd7a40x_devs, ARRAY_SIZE (lpd7a40x_devs));
-#if defined (CONFIG_FB_ARMCLCD)
-        lh7a40x_clcd_init ();
-#endif
-}
-
-static void lh7a40x_ack_cpld_irq(struct irq_data *d)
-{
-	/* CPLD doesn't have ack capability, but some devices may */
-
-#if defined (CPLD_INTMASK_TOUCH)
-	/* The touch control *must* mask the interrupt because the
-	 * interrupt bit is read by the driver to determine if the pen
-	 * is still down. */
-	if (d->irq == IRQ_TOUCH)
-		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
-#endif
-}
-
-static void lh7a40x_mask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS |= CPLD_INTMASK_ETHERNET;
-		break;
-#if defined (IRQ_TOUCH)
-	case IRQ_TOUCH:
-		CPLD_INTERRUPTS |= CPLD_INTMASK_TOUCH;
-		break;
-#endif
-	}
-}
-
-static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS &= ~CPLD_INTMASK_ETHERNET;
-		break;
-#if defined (IRQ_TOUCH)
-	case IRQ_TOUCH:
-		CPLD_INTERRUPTS &= ~CPLD_INTMASK_TOUCH;
-		break;
-#endif
-	}
-}
-
-static struct irq_chip lpd7a40x_cpld_chip = {
-	.name		= "CPLD",
-	.irq_ack	= lh7a40x_ack_cpld_irq,
-	.irq_mask	= lh7a40x_mask_cpld_irq,
-	.irq_unmask	= lh7a40x_unmask_cpld_irq,
-};
-
-static void lpd7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int mask = CPLD_INTERRUPTS;
-
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-	if ((mask & (1<<0)) == 0)	/* WLAN */
-		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
-
-#if defined (IRQ_TOUCH)
-	if ((mask & (1<<1)) == 0)	/* Touch */
-		generic_handle_irq(IRQ_TOUCH);
-#endif
-
-	/* Level-triggered need this */
-	desc->irq_data.chip->irq_unmask(&desc->irq_data);
-}
-
-
-void __init lh7a40x_init_board_irq (void)
-{
-	int irq;
-
-		/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
-		                 PF7 supports the CPLD.
-		   Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
-		                 PF3 supports the CPLD.
-		   (Some) LPD7A404 prerelease boards report a version
-		   number of 0x16, but we force an override since the
-		   hardware is of the newer variety.
-		*/
-
-	unsigned char cpld_version = CPLD_REVISION;
-	int pinCPLD = (cpld_version == 0x28) ? 7 : 3;
-
-#if defined CONFIG_MACH_LPD7A404
-	cpld_version = 0x34;	/* Coerce LPD7A404 to RevB */
-#endif
-
-		/* First, configure user controlled GPIOF interrupts  */
-
-	GPIO_PFDD	&= ~0x0f; /* PF0-3 are inputs */
-	GPIO_INTTYPE1	&= ~0x0f; /* PF0-3 are level triggered */
-	GPIO_INTTYPE2	&= ~0x0f; /* PF0-3 are active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
-
-		/* Then, configure CPLD interrupt */
-
-			/* Disable all CPLD interrupts */
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_INTERRUPTS	= CPLD_INTMASK_TOUCH | CPLD_INTMASK_PEN
-		| CPLD_INTMASK_ETHERNET;
-	/* *** FIXME: don't know why we need 7 and 4. 7 is way wrong
-               and 4 is uncefined. */
-	// (1<<7)|(1<<4)|(1<<3)|(1<<2);
-#endif
-#if defined (CONFIG_MACH_LPD7A404)
-	CPLD_INTERRUPTS	= CPLD_INTMASK_ETHERNET;
-	/* *** FIXME: don't know why we need 6 and 5, neither is defined. */
-	// (1<<6)|(1<<5)|(1<<3);
-#endif
-	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
-	GPIO_INTTYPE1	&= ~(1 << pinCPLD); /* Level triggered */
-	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
-
-		/* Cascade CPLD interrupts */
-
-	for (irq = IRQ_BOARD_START;
-	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
-		set_irq_chip (irq, &lpd7a40x_cpld_chip);
-		set_irq_handler (irq, handle_level_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler ((cpld_version == 0x28)
-				 ? IRQ_CPLD_V28
-				 : IRQ_CPLD_V34,
-				 lpd7a40x_cpld_handler);
-}
-
-static struct map_desc lpd7a40x_io_desc[] __initdata = {
-	{
-		.virtual	= IO_VIRT,
-		.pfn		= __phys_to_pfn(IO_PHYS),
-		.length		= IO_SIZE,
-		.type		= MT_DEVICE
-	},
-	{	/* Mapping added to work around chip select problems */
-		.virtual	= IOBARRIER_VIRT,
-		.pfn		= __phys_to_pfn(IOBARRIER_PHYS),
-		.length		= IOBARRIER_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CF_VIRT,
-		.pfn		= __phys_to_pfn(CF_PHYS),
-		.length		= CF_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD02_VIRT,
-		.pfn		= __phys_to_pfn(CPLD02_PHYS),
-		.length		= CPLD02_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD06_VIRT,
-		.pfn		= __phys_to_pfn(CPLD06_PHYS),
-		.length		= CPLD06_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD08_VIRT,
-		.pfn		= __phys_to_pfn(CPLD08_PHYS),
-		.length		= CPLD08_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD08_VIRT,
-		.pfn		= __phys_to_pfn(CPLD08_PHYS),
-		.length		= CPLD08_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD0A_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0A_PHYS),
-		.length		= CPLD0A_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD0C_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0C_PHYS),
-		.length		= CPLD0C_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD0E_VIRT,
-		.pfn		= __phys_to_pfn(CPLD0E_PHYS),
-		.length		= CPLD0E_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD10_VIRT,
-		.pfn		= __phys_to_pfn(CPLD10_PHYS),
-		.length		= CPLD10_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD12_VIRT,
-		.pfn		= __phys_to_pfn(CPLD12_PHYS),
-		.length		= CPLD12_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD14_VIRT,
-		.pfn		= __phys_to_pfn(CPLD14_PHYS),
-		.length		= CPLD14_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD16_VIRT,
-		.pfn		= __phys_to_pfn(CPLD16_PHYS),
-		.length		= CPLD16_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD18_VIRT,
-		.pfn		= __phys_to_pfn(CPLD18_PHYS),
-		.length		= CPLD18_SIZE,
-		.type		= MT_DEVICE
-	},
-	{
-		.virtual	= CPLD1A_VIRT,
-		.pfn		= __phys_to_pfn(CPLD1A_PHYS),
-		.length		= CPLD1A_SIZE,
-		.type		= MT_DEVICE
-	},
-};
-
-void __init
-lpd7a40x_map_io(void)
-{
-	iotable_init (lpd7a40x_io_desc, ARRAY_SIZE (lpd7a40x_io_desc));
-}
-
-#ifdef CONFIG_MACH_LPD7A400
-
-MACHINE_START (LPD7A400, "Logic Product Development LPD7A400-10")
-	/* Maintainer: Marc Singer */
-	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a40x_map_io,
-	.init_irq	= lh7a400_init_irq,
-	.timer		= &lh7a40x_timer,
-	.init_machine	= lpd7a40x_init,
-MACHINE_END
-
-#endif
-
-#ifdef CONFIG_MACH_LPD7A404
-
-MACHINE_START (LPD7A404, "Logic Product Development LPD7A404-10")
-	/* Maintainer: Marc Singer */
-	.boot_params	= 0xc0000100,
-	.map_io		= lpd7a40x_map_io,
-	.init_irq	= lh7a404_init_irq,
-	.timer		= &lh7a40x_timer,
-	.init_machine	= lpd7a40x_init,
-MACHINE_END
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/clcd.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/clcd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/clcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/clcd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,241 +0,0 @@
-/*
- *  arch/arm/mach-lh7a40x/clcd.c
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  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/gfp.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/sysdev.h>
-#include <linux/interrupt.h>
-
-//#include <linux/module.h>
-//#include <linux/time.h>
-
-//#include <asm/mach/time.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-
-#include <asm/system.h>
-#include <mach/hardware.h>
-#include <linux/amba/bus.h>
-#include <linux/amba/clcd.h>
-
-#define HRTFTC_HRSETUP		__REG(HRTFTC_PHYS + 0x00)
-#define HRTFTC_HRCON		__REG(HRTFTC_PHYS + 0x04)
-#define HRTFTC_HRTIMING1	__REG(HRTFTC_PHYS + 0x08)
-#define HRTFTC_HRTIMING2	__REG(HRTFTC_PHYS + 0x0c)
-
-#define ALI_SETUP		__REG(ALI_PHYS + 0x00)
-#define ALI_CONTROL		__REG(ALI_PHYS + 0x04)
-#define ALI_TIMING1		__REG(ALI_PHYS + 0x08)
-#define ALI_TIMING2		__REG(ALI_PHYS + 0x0c)
-
-#include "lcd-panel.h"
-
-static void lh7a40x_clcd_disable (struct clcd_fb *fb)
-{
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_CONTROL &= ~(1<<1);	/* Disable LCD Vee */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A404)
-	GPIO_PCD  &= ~(1<<3);		/* Disable LCD Vee */
-#endif
-
-#if defined (CONFIG_ARCH_LH7A400)
-	HRTFTC_HRSETUP &= ~(1<<13);	/* Disable HRTFT controller */
-#endif
-
-#if defined (CONFIG_ARCH_LH7A404)
-	ALI_SETUP &= ~(1<<13);		/* Disable ALI */
-#endif
-}
-
-static void lh7a40x_clcd_enable (struct clcd_fb *fb)
-{
-	struct clcd_panel_extra* extra
-		= (struct clcd_panel_extra*) fb->board_data;
-
-#if defined (CONFIG_MACH_LPD7A400)
-	CPLD_CONTROL |= (1<<1);		/* Enable LCD Vee */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A404)
-	GPIO_PCDD &= ~(1<<3);		/* Enable LCD Vee */
-	GPIO_PCD  |=  (1<<3);
-#endif
-
-#if defined (CONFIG_ARCH_LH7A400)
-
-	if (extra) {
-		HRTFTC_HRSETUP
-			= (1 << 13)
-			| ((fb->fb.var.xres - 1) << 4)
-			| 0xc
-			| (extra->hrmode ? 1 : 0);
-		HRTFTC_HRCON
-			= ((extra->clsen ? 1 : 0) << 1)
-			| ((extra->spsen ? 1 : 0) << 0);
-		HRTFTC_HRTIMING1
-			= (extra->pcdel << 8)
-			| (extra->revdel << 4)
-			| (extra->lpdel << 0);
-		HRTFTC_HRTIMING2
-			= (extra->spldel << 9)
-			| (extra->pc2del << 0);
-	}
-	else
-		HRTFTC_HRSETUP
-			= (1 << 13)
-			| 0xc;
-#endif
-
-#if defined (CONFIG_ARCH_LH7A404)
-
-	if (extra) {
-		ALI_SETUP
-			= (1 << 13)
-			| ((fb->fb.var.xres - 1) << 4)
-			| 0xc
-			| (extra->hrmode ? 1 : 0);
-		ALI_CONTROL
-			= ((extra->clsen ? 1 : 0) << 1)
-			| ((extra->spsen ? 1 : 0) << 0);
-		ALI_TIMING1
-			= (extra->pcdel << 8)
-			| (extra->revdel << 4)
-			| (extra->lpdel << 0);
-		ALI_TIMING2
-			= (extra->spldel << 9)
-			| (extra->pc2del << 0);
-	}
-	else
-		ALI_SETUP
-			= (1 << 13)
-			| 0xc;
-#endif
-
-}
-
-#define FRAMESIZE(s) (((s) + PAGE_SIZE - 1)&PAGE_MASK)
-
-static int lh7a40x_clcd_setup (struct clcd_fb *fb)
-{
-	dma_addr_t dma;
-	u32 len = FRAMESIZE (lcd_panel.mode.xres*lcd_panel.mode.yres
-			     *(lcd_panel.bpp/8));
-
-	fb->panel = &lcd_panel;
-
-		/* Enforce the sync polarity defaults */
-	if (!(fb->panel->tim2 & TIM2_IHS))
-		fb->fb.var.sync |= FB_SYNC_HOR_HIGH_ACT;
-	if (!(fb->panel->tim2 & TIM2_IVS))
-		fb->fb.var.sync |= FB_SYNC_VERT_HIGH_ACT;
-
-#if defined (HAS_LCD_PANEL_EXTRA)
-	fb->board_data = &lcd_panel_extra;
-#endif
-
-	fb->fb.screen_base
-		= dma_alloc_writecombine (&fb->dev->dev, len,
-					  &dma, GFP_KERNEL);
-	printk ("CLCD: LCD setup fb virt 0x%p phys 0x%p l %x io 0x%p \n",
-		fb->fb.screen_base, (void*) dma, len,
-		(void*) io_p2v (CLCDC_PHYS));
-	printk ("CLCD: pixclock %d\n", lcd_panel.mode.pixclock);
-
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
-	}
-
-#if defined (USE_RGB555)
-	fb->fb.var.green.length = 5; /* Panel uses RGB 5:5:5 */
-#endif
-
-	fb->fb.fix.smem_start = dma;
-	fb->fb.fix.smem_len = len;
-
-		/* Drive PE4 high to prevent CPLD crash */
-	GPIO_PEDD |= (1<<4);
-	GPIO_PED  |= (1<<4);
-
-	GPIO_PINMUX |= (1<<1) | (1<<0); /* LCDVD[15:4] */
-
-//	fb->fb.fbops->fb_check_var (&fb->fb.var, &fb->fb);
-//	fb->fb.fbops->fb_set_par (&fb->fb);
-
-	return 0;
-}
-
-static int lh7a40x_clcd_mmap (struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-				     fb->fb.screen_base,
-				     fb->fb.fix.smem_start,
-				     fb->fb.fix.smem_len);
-}
-
-static void lh7a40x_clcd_remove (struct clcd_fb *fb)
-{
-	dma_free_writecombine (&fb->dev->dev, fb->fb.fix.smem_len,
-			       fb->fb.screen_base, fb->fb.fix.smem_start);
-}
-
-static struct clcd_board clcd_platform_data = {
-	.name		= "lh7a40x FB",
-	.check		= clcdfb_check,
-	.decode		= clcdfb_decode,
-	.enable		= lh7a40x_clcd_enable,
-	.setup		= lh7a40x_clcd_setup,
-	.mmap		= lh7a40x_clcd_mmap,
-	.remove		= lh7a40x_clcd_remove,
-	.disable	= lh7a40x_clcd_disable,
-};
-
-#define IRQ_CLCDC (IRQ_LCDINTR)
-
-#define AMBA_DEVICE(name,busid,base,plat,pid)			\
-static struct amba_device name##_device = {			\
-	.dev = {						\
-		.coherent_dma_mask = ~0,			\
-		.init_name = busid,				\
-		.platform_data = plat,				\
-		},						\
-	.res = {						\
-		.start	= base##_PHYS,				\
-		.end	= (base##_PHYS) + (4*1024) - 1,		\
-		.flags	= IORESOURCE_MEM,			\
-		},						\
-	.dma_mask	= ~0,					\
-	.irq		= { IRQ_##base, },			\
-	/* .dma		= base##_DMA,*/				\
-	.periphid = pid,					\
-}
-
-AMBA_DEVICE(clcd,  "cldc-lh7a40x",  CLCDC,     &clcd_platform_data, 0x41110);
-
-static struct amba_device *amba_devs[] __initdata = {
-	&clcd_device,
-};
-
-void __init lh7a40x_clcd_init (void)
-{
-	int i;
-	int result;
-	printk ("CLCD: registering amba devices\n");
-	for (i = 0; i < ARRAY_SIZE(amba_devs); i++) {
-		struct amba_device *d = amba_devs[i];
-		result = amba_device_register(d, &iomem_resource);
-		printk ("  %d -> %d\n", i ,result);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/clocks.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/clocks.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/clocks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/clocks.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,108 +0,0 @@
-/* arch/arm/mach-lh7a40x/clocks.c
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  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 <mach/hardware.h>
-#include <mach/clocks.h>
-#include <linux/err.h>
-#include <linux/device.h>
-#include <linux/string.h>
-
-struct module;
-
-struct clk {
-	struct list_head node;
-	unsigned long rate;
-	struct module *owner;
-	const char *name;
-};
-
-/* ----- */
-
-#define MAINDIV1(c)	(((c) >>  7) & 0x0f)
-#define MAINDIV2(c)	(((c) >> 11) & 0x1f)
-#define PS(c)		(((c) >> 18) & 0x03)
-#define PREDIV(c)	(((c) >>  2) & 0x1f)
-#define HCLKDIV(c)	(((c) >>  0) & 0x02)
-#define PCLKDIV(c)	(((c) >> 16) & 0x03)
-
-unsigned int fclkfreq_get (void)
-{
-	unsigned int clkset = CSC_CLKSET;
-	unsigned int gclk
-		= XTAL_IN
-		/ (1 << PS(clkset))
-		* (MAINDIV1(clkset) + 2)
-		/ (PREDIV(clkset)   + 2)
-		* (MAINDIV2(clkset) + 2)
-		;
-	return gclk;
-}
-
-unsigned int hclkfreq_get (void)
-{
-	unsigned int clkset = CSC_CLKSET;
-	unsigned int hclk = fclkfreq_get () / (HCLKDIV(clkset) + 1);
-
-	return hclk;
-}
-
-unsigned int pclkfreq_get (void)
-{
-	unsigned int clkset = CSC_CLKSET;
-	int pclkdiv = PCLKDIV(clkset);
-	unsigned int pclk;
-	if (pclkdiv == 0x3)
-		pclkdiv = 0x2;
-	pclk = hclkfreq_get () / (1 << pclkdiv);
-
-	return pclk;
-}
-
-/* ----- */
-
-struct clk *clk_get (struct device *dev, const char *id)
-{
-	return dev && strcmp(dev_name(dev), "cldc-lh7a40x") == 0
-		 ? NULL : ERR_PTR(-ENOENT);
-}
-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 0;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-long clk_round_rate (struct clk *clk, unsigned long rate)
-{
-	return rate;
-}
-EXPORT_SYMBOL(clk_round_rate);
-
-int clk_set_rate (struct clk *clk, unsigned long rate)
-{
-	return -EIO;
-}
-EXPORT_SYMBOL(clk_set_rate);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/common.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/common.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/* arch/arm/mach-lh7a40x/common.h
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  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 sys_timer lh7a40x_timer;
-
-extern void lh7a400_init_irq (void);
-extern void lh7a404_init_irq (void);
-extern void lh7a40x_clcd_init (void);
-extern void lh7a40x_init_board_irq (void);
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/clocks.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/clocks.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/clocks.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/clocks.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/clocks.h
- *
- *  Copyright (C) 2004 Marc Singer
- *
- *  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_CLOCKS_H
-#define __ASM_ARCH_CLOCKS_H
-
-unsigned int fclkfreq_get (void);
-unsigned int hclkfreq_get (void);
-unsigned int pclkfreq_get (void);
-
-#endif  /* _ASM_ARCH_CLOCKS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/constants.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/constants.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/constants.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/constants.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/constants.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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_CONSTANTS_H
-#define __ASM_ARCH_CONSTANTS_H
-
-
-/* Addressing constants */
-
-	/* SoC CPU IO addressing */
-#define IO_PHYS			(0x80000000)
-#define IO_VIRT			(0xf8000000)
-#define IO_SIZE			(0x0000B000)
-
-#ifdef CONFIG_MACH_KEV7A400
-# define CPLD_PHYS		(0x20000000)
-# define CPLD_VIRT		(0xf2000000)
-# define CPLD_SIZE		PAGE_SIZE
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-
-# define IOBARRIER_PHYS		0x10000000 /* Second bank, fastest timing */
-# define IOBARRIER_VIRT		0xf0000000
-# define IOBARRIER_SIZE		PAGE_SIZE
-
-# define CF_PHYS		0x60200000
-# define CF_VIRT		0xf6020000
-# define CF_SIZE		(8*1024)
-
-	/* The IO mappings for the LPD CPLD are, unfortunately, sparse.  */
-# define CPLDX_PHYS(x)		(0x70000000 | ((x) << 20))
-# define CPLDX_VIRT(x)		(0xf7000000 | ((x) << 16))
-# define CPLD00_PHYS		CPLDX_PHYS (0x00) /* Wired LAN */
-# define CPLD00_VIRT		CPLDX_VIRT (0x00)
-# define CPLD00_SIZE		PAGE_SIZE
-# define CPLD02_PHYS		CPLDX_PHYS (0x02)
-# define CPLD02_VIRT		CPLDX_VIRT (0x02)
-# define CPLD02_SIZE		PAGE_SIZE
-# define CPLD06_PHYS		CPLDX_PHYS (0x06)
-# define CPLD06_VIRT		CPLDX_VIRT (0x06)
-# define CPLD06_SIZE		PAGE_SIZE
-# define CPLD08_PHYS		CPLDX_PHYS (0x08)
-# define CPLD08_VIRT		CPLDX_VIRT (0x08)
-# define CPLD08_SIZE		PAGE_SIZE
-# define CPLD0A_PHYS		CPLDX_PHYS (0x0a)
-# define CPLD0A_VIRT		CPLDX_VIRT (0x0a)
-# define CPLD0A_SIZE		PAGE_SIZE
-# define CPLD0C_PHYS		CPLDX_PHYS (0x0c)
-# define CPLD0C_VIRT		CPLDX_VIRT (0x0c)
-# define CPLD0C_SIZE		PAGE_SIZE
-# define CPLD0E_PHYS		CPLDX_PHYS (0x0e)
-# define CPLD0E_VIRT		CPLDX_VIRT (0x0e)
-# define CPLD0E_SIZE		PAGE_SIZE
-# define CPLD10_PHYS		CPLDX_PHYS (0x10)
-# define CPLD10_VIRT		CPLDX_VIRT (0x10)
-# define CPLD10_SIZE		PAGE_SIZE
-# define CPLD12_PHYS		CPLDX_PHYS (0x12)
-# define CPLD12_VIRT		CPLDX_VIRT (0x12)
-# define CPLD12_SIZE		PAGE_SIZE
-# define CPLD14_PHYS		CPLDX_PHYS (0x14)
-# define CPLD14_VIRT		CPLDX_VIRT (0x14)
-# define CPLD14_SIZE		PAGE_SIZE
-# define CPLD16_PHYS		CPLDX_PHYS (0x16)
-# define CPLD16_VIRT		CPLDX_VIRT (0x16)
-# define CPLD16_SIZE		PAGE_SIZE
-# define CPLD18_PHYS		CPLDX_PHYS (0x18)
-# define CPLD18_VIRT		CPLDX_VIRT (0x18)
-# define CPLD18_SIZE		PAGE_SIZE
-# define CPLD1A_PHYS		CPLDX_PHYS (0x1a)
-# define CPLD1A_VIRT		CPLDX_VIRT (0x1a)
-# define CPLD1A_SIZE		PAGE_SIZE
-#endif
-
-	/* Timing constants */
-
-#define	XTAL_IN			14745600	/* 14.7456 MHz crystal */
-#define PLL_CLOCK		(XTAL_IN * 21)	/* 309 MHz PLL clock */
-#define MAX_HCLK_KHZ		100000		/* HCLK max limit ~100MHz */
-#define HCLK			(99993600)
-//#define HCLK			(119808000)
-
-#endif /* __ASM_ARCH_CONSTANTS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,37 +0,0 @@
-/* arch/arm/mach-lh7a40x/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.
- *
-*/
-
-	@ It is not known if this will be appropriate for every 40x
-	@ board.
-
-		.macro  addruart, rp, rv
-		mov     \rp, #0x00000700        @ offset from base
-		orr     \rv, \rp, #0xf8000000   @ virtual base
-		orr     \rp, \rp, #0x80000000   @ physical base
-		.endm
-
-		.macro  senduart,rd,rx
-		strb    \rd, [\rx]              @ DATA
-		.endm
-
-		.macro  busyuart,rd,rx          @ spin while busy
-1001:		ldr     \rd, [\rx, #0x10]       @ STATUS
-		tst     \rd, #1 << 3            @ BUSY (TX FIFO not empty)
-		bne     1001b                   @ yes, spin
-		.endm
-
-		.macro  waituart,rd,rx          @ wait for Tx FIFO room
-1001:		ldrb    \rd, [\rx, #0x10]       @ STATUS
-		tst     \rd, #1 << 5            @ TXFF (TX FIFO full)
-		bne     1001b                   @ yes, spin
-		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/dma.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/dma.h
- *
- *  Copyright (C) 2005 Marc Singer
- *
- *  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.
- *
- */
-
-typedef enum {
-	DMA_M2M0	= 0,
-	DMA_M2M1	= 1,
-	DMA_M2P0	= 2,	/* Tx */
-	DMA_M2P1	= 3,	/* Rx */
-	DMA_M2P2	= 4,	/* Tx */
-	DMA_M2P3	= 5,	/* Rx */
-	DMA_M2P4	= 6,	/* Tx - AC97 */
-	DMA_M2P5	= 7,	/* Rx - AC97 */
-	DMA_M2P6	= 8,	/* Tx */
-	DMA_M2P7	= 9,	/* Rx */
-} dma_device_t;
-
-#define DMA_LENGTH_MAX		((64*1024) - 4) /* bytes */
-
-#define DMAC_GCA		__REG(DMAC_PHYS + 0x2b80)
-#define DMAC_GIR		__REG(DMAC_PHYS + 0x2bc0)
-
-#define DMAC_GIR_MMI1		(1<<11)
-#define DMAC_GIR_MMI0		(1<<10)
-#define DMAC_GIR_MPI8		(1<<9)
-#define DMAC_GIR_MPI9		(1<<8)
-#define DMAC_GIR_MPI6		(1<<7)
-#define DMAC_GIR_MPI7		(1<<6)
-#define DMAC_GIR_MPI4		(1<<5)
-#define DMAC_GIR_MPI5		(1<<4)
-#define DMAC_GIR_MPI2		(1<<3)
-#define DMAC_GIR_MPI3		(1<<2)
-#define DMAC_GIR_MPI0		(1<<1)
-#define DMAC_GIR_MPI1		(1<<0)
-
-#define DMAC_M2P0		0x0000
-#define DMAC_M2P1		0x0040
-#define DMAC_M2P2		0x0080
-#define DMAC_M2P3		0x00c0
-#define DMAC_M2P4		0x0240
-#define DMAC_M2P5		0x0200
-#define DMAC_M2P6		0x02c0
-#define DMAC_M2P7		0x0280
-#define DMAC_M2P8		0x0340
-#define DMAC_M2P9		0x0300
-#define DMAC_M2M0		0x0100
-#define DMAC_M2M1		0x0140
-
-#define DMAC_P_PCONTROL(c)	__REG(DMAC_PHYS + (c) + 0x00)
-#define DMAC_P_PINTERRUPT(c)	__REG(DMAC_PHYS + (c) + 0x04)
-#define DMAC_P_PPALLOC(c)	__REG(DMAC_PHYS + (c) + 0x08)
-#define DMAC_P_PSTATUS(c)	__REG(DMAC_PHYS + (c) + 0x0c)
-#define DMAC_P_REMAIN(c)	__REG(DMAC_PHYS + (c) + 0x14)
-#define DMAC_P_MAXCNT0(c)	__REG(DMAC_PHYS + (c) + 0x20)
-#define DMAC_P_BASE0(c)		__REG(DMAC_PHYS + (c) + 0x24)
-#define DMAC_P_CURRENT0(c)	__REG(DMAC_PHYS + (c) + 0x28)
-#define DMAC_P_MAXCNT1(c)	__REG(DMAC_PHYS + (c) + 0x30)
-#define DMAC_P_BASE1(c)		__REG(DMAC_PHYS + (c) + 0x34)
-#define DMAC_P_CURRENT1(c)	__REG(DMAC_PHYS + (c) + 0x38)
-
-#define DMAC_PCONTROL_ENABLE	(1<<4)
-
-#define DMAC_PORT_USB		0
-#define DMAC_PORT_SDMMC		1
-#define DMAC_PORT_AC97_1	2
-#define DMAC_PORT_AC97_2	3
-#define DMAC_PORT_AC97_3	4
-#define DMAC_PORT_UART1		6
-#define DMAC_PORT_UART2		7
-#define DMAC_PORT_UART3		8
-
-#define DMAC_PSTATUS_CURRSTATE_SHIFT	4
-#define DMAC_PSTATUS_CURRSTATE_MASK	0x3
-
-#define DMAC_PSTATUS_NEXTBUF	 (1<<6)
-#define DMAC_PSTATUS_STALLRINT	 (1<<0)
-
-#define DMAC_INT_CHE		 (1<<3)
-#define DMAC_INT_NFB		 (1<<1)
-#define DMAC_INT_STALL		 (1<<0)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,149 +0,0 @@
-/*
- * arch/arm/mach-lh7a40x/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for LH7A40x 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>
-#include <mach/irqs.h>
-
-/* In order to allow there to be support for both of the processor
-   classes at the same time, we make a hack here that isn't very
-   pretty.  At startup, the link pointed to with the
-   branch_irq_lh7a400 symbol is replaced with a NOP when the CPU is
-   detected as a lh7a404.
-
-   *** FIXME: we should clean this up so that there is only one
-	      implementation for each CPU's design.
-
-*/
-
-#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-
-		.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
-
-branch_irq_lh7a400: b 1000f
-
-@ Implementation of the LH7A404 get_irqnr_and_base.
-
-		mov	\irqnr, #0			@ VIC1 irq base
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		add	\base, \base, #0x8000
-		ldr	\tmp, [\base, #0x0030]		@ VIC1_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		tst	\tmp, #VA_VIC1DEFAULT		@ Default vectored VIC1
-		ldrne	\irqstat, [\base, #0]		@ VIC1_IRQSTATUS
-		bne	1001f
-		add	\base, \base, #(0xa000 - 0x8000)
-		ldr	\tmp, [\base, #0x0030]		@ VIC2_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		ldr	\irqstat, [\base, #0]		@ VIC2_IRQSTATUS
-		mov	\irqnr, #32			@ VIC2 irq base
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1002:		and	\irqnr, \tmp, #0x3f		@ Mask for valid bits
-1008:		movs	\irqstat, #1			@ Force !Z
-		str	\tmp, [\base, #0x0030]		@ Clear vector
-		b	1009f
-
-@ Implementation of the LH7A400 get_irqnr_and_base.
-
-1000:		mov	\irqnr, #0
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		ldr	\irqstat, [\base, #0x500]	@ PIC INTSR
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1008:		movs	\irqstat, #1			@ Force !Z
-
-1009:
-               .endm
-
-
-
-#elif defined (CONFIG_ARCH_LH7A400)
-		.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
-		mov	\irqnr, #0
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		ldr	\irqstat, [\base, #0x500]	@ PIC INTSR
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1008:		movs	\irqstat, #1			@ Force !Z
-1009:
-               .endm
-
-#elif defined(CONFIG_ARCH_LH7A404)
-
-		.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
-		mov	\irqnr, #0			@ VIC1 irq base
-		mov	\base, #io_p2v(0x80000000)	@ APB registers
-		add	\base, \base, #0x8000
-		ldr	\tmp, [\base, #0x0030]		@ VIC1_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		tst	\tmp, #VA_VIC1DEFAULT		@ Default vectored VIC1
-		ldrne	\irqstat, [\base, #0]		@ VIC1_IRQSTATUS
-		bne	1001f
-		add	\base, \base, #(0xa000 - 0x8000)
-		ldr	\tmp, [\base, #0x0030]		@ VIC2_VECTADDR
-		tst	\tmp, #VA_VECTORED		@ Direct vectored
-		bne	1002f
-		ldr	\irqstat, [\base, #0]		@ VIC2_IRQSTATUS
-		mov	\irqnr, #32			@ VIC2 irq base
-
-1001:		movs	\irqstat, \irqstat, lsr #1	@ Shift into carry
-		bcs	1008f				@ Bit set; irq found
-		add	\irqnr, \irqnr, #1
-		bne	1001b				@ Until no bits
-		b	1009f				@ Nothing?  Hmm.
-1002:		and	\irqnr, \tmp, #0x3f		@ Mask for valid bits
-1008:		movs	\irqstat, #1			@ Force !Z
-		str	\tmp, [\base, #0x0030]		@ Clear vector
-1009:
-               .endm
-#endif
-
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/hardware.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  [ Substantially cribbed from arch/arm/mach-pxa/include/mach/hardware.h ]
- *
- *  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_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H
-
-#include <asm/sizes.h>		/* Added for the sake of amba-clcd driver */
-
-#define io_p2v(x) (0xf0000000 | (((x) & 0xfff00000) >> 4) | ((x) & 0x0000ffff))
-#define io_v2p(x) (             (((x) & 0x0fff0000) << 4) | ((x) & 0x0000ffff))
-
-#ifdef __ASSEMBLY__
-
-# define __REG(x)	io_p2v(x)
-# define __PREG(x)	io_v2p(x)
-
-#else
-
-# if 0
-#  define __REG(x)	(*((volatile u32 *)io_p2v(x)))
-# else
-/*
- * This __REG() version gives the same results as the one above,  except
- * that we are fooling gcc somehow so it generates far better and smaller
- * assembly code for access to contiguous registers.  It's a shame that gcc
- * doesn't guess this by itself.
- */
-#include <asm/types.h>
-typedef struct { volatile u32 offset[4096]; } __regbase;
-# define __REGP(x)	((__regbase *)((x)&~4095))->offset[((x)&4095)>>2]
-# define __REG(x)	__REGP(io_p2v(x))
-typedef struct { volatile u16 offset[4096]; } __regbase16;
-# define __REGP16(x)	((__regbase16 *)((x)&~4095))->offset[((x)&4095)>>1]
-# define __REG16(x)	__REGP16(io_p2v(x))
-typedef struct { volatile u8 offset[4096]; } __regbase8;
-# define __REGP8(x)	((__regbase8 *)((x)&~4095))->offset[(x)&4095]
-# define __REG8(x)	__REGP8(io_p2v(x))
-#endif
-
-/* Let's kick gcc's ass again... */
-# define __REG2(x,y)	\
-	( __builtin_constant_p(y) ? (__REG((x) + (y))) \
-				  : (*(volatile u32 *)((u32)&__REG(x) + (y))) )
-
-# define __PREG(x)	(io_v2p((u32)&(x)))
-
-#endif
-
-#define MASK_AND_SET(v,m,s)	(v) = ((v)&~(m))|(s)
-
-#include "registers.h"
-
-#endif  /* _ASM_ARCH_HARDWARE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/io.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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_IO_H
-#define __ASM_ARCH_IO_H
-
-#define IO_SPACE_LIMIT 0xffffffff
-
-/* No ISA or PCI bus on this machine. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#endif /* __ASM_ARCH_IO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,200 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/irqs.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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.
- *
- */
-
-/* It is to be seen whether or not we can build a kernel for more than
- * one board.  For the time being, these macros assume that we cannot.
- * Thus, it is OK to ifdef machine/board specific IRQ assignments.
- */
-
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H
-
-
-#define FIQ_START	80
-
-#if defined (CONFIG_ARCH_LH7A400)
-
-  /* FIQs */
-
-# define IRQ_GPIO0FIQ	0	/* GPIO External FIQ Interrupt on F0 */
-# define IRQ_BLINT	1	/* Battery Low */
-# define IRQ_WEINT	2	/* Watchdog Timer, WDT overflow	*/
-# define IRQ_MCINT	3	/* Media Change, MEDCHG pin rising */
-
-  /* IRQs */
-
-# define IRQ_CSINT	4	/* Audio Codec (ACI) */
-# define IRQ_GPIO1INTR	5	/* GPIO External IRQ Interrupt on F1 */
-# define IRQ_GPIO2INTR	6	/* GPIO External IRQ Interrupt on F2 */
-# define IRQ_GPIO3INTR	7	/* GPIO External IRQ Interrupt on F3 */
-# define IRQ_T1UI	8	/* Timer 1 underflow */
-# define IRQ_T2UI	9	/* Timer 2 underflow */
-# define IRQ_RTCMI	10
-# define IRQ_TINTR	11	/* Clock State Controller 64 Hz tick (CSC) */
-# define IRQ_UART1INTR	12
-# define IRQ_UART2INTR	13
-# define IRQ_LCDINTR	14
-# define IRQ_SSIEOT	15	/* Synchronous Serial Interface (SSI) */
-# define IRQ_UART3INTR	16
-# define IRQ_SCIINTR	17	/* Smart Card Interface (SCI) */
-# define IRQ_AACINTR	18	/* Advanced Audio Codec (AAC) */
-# define IRQ_MMCINTR	19	/* Multimedia Card (MMC) */
-# define IRQ_USBINTR	20
-# define IRQ_DMAINTR	21
-# define IRQ_T3UI	22	/* Timer 3 underflow */
-# define IRQ_GPIO4INTR	23	/* GPIO External IRQ Interrupt on F4 */
-# define IRQ_GPIO5INTR	24	/* GPIO External IRQ Interrupt on F5 */
-# define IRQ_GPIO6INTR	25	/* GPIO External IRQ Interrupt on F6 */
-# define IRQ_GPIO7INTR	26	/* GPIO External IRQ Interrupt on F7 */
-# define IRQ_BMIINTR	27	/* Battery Monitor Interface (BMI) */
-
-# define NR_IRQ_CPU	28	/* IRQs directly recognized by CPU */
-
-	/* Given IRQ, return GPIO interrupt number 0-7 */
-# define IRQ_TO_GPIO(i)  ((i) \
-	- (((i) > IRQ_GPIO3INTR) ? IRQ_GPIO4INTR - IRQ_GPIO3INTR - 1 : 0)\
-	- (((i) > IRQ_GPIO0INTR) ? IRQ_GPIO1INTR - IRQ_GPIO0INTR - 1 : 0))
-
-#endif
-
-#if defined (CONFIG_ARCH_LH7A404)
-
-# define IRQ_BROWN	0	/* Brownout */
-# define IRQ_WDTINTR	1	/* Watchdog Timer */
-# define IRQ_COMMRX	2	/* ARM Comm Rx for Debug */
-# define IRQ_COMMTX	3	/* ARM Comm Tx for Debug */
-# define IRQ_T1UI	4	/* Timer 1 underflow */
-# define IRQ_T2UI	5	/* Timer 2 underflow */
-# define IRQ_CSINT	6	/* Codec Interrupt (shared by AAC on 404) */
-# define IRQ_DMAM2P0	7	/* -- DMA Memory to Peripheral */
-# define IRQ_DMAM2P1	8
-# define IRQ_DMAM2P2	9
-# define IRQ_DMAM2P3	10
-# define IRQ_DMAM2P4	11
-# define IRQ_DMAM2P5	12
-# define IRQ_DMAM2P6	13
-# define IRQ_DMAM2P7	14
-# define IRQ_DMAM2P8	15
-# define IRQ_DMAM2P9	16
-# define IRQ_DMAM2M0	17	/* -- DMA Memory to Memory */
-# define IRQ_DMAM2M1	18
-# define IRQ_GPIO0INTR	19	/* -- GPIOF Interrupt */
-# define IRQ_GPIO1INTR	20
-# define IRQ_GPIO2INTR	21
-# define IRQ_GPIO3INTR	22
-# define IRQ_SOFT_V1_23	23	/* -- Unassigned */
-# define IRQ_SOFT_V1_24	24
-# define IRQ_SOFT_V1_25	25
-# define IRQ_SOFT_V1_26	26
-# define IRQ_SOFT_V1_27	27
-# define IRQ_SOFT_V1_28	28
-# define IRQ_SOFT_V1_29	29
-# define IRQ_SOFT_V1_30	30
-# define IRQ_SOFT_V1_31	31
-
-# define IRQ_BLINT	32	/* Battery Low */
-# define IRQ_BMIINTR	33	/* Battery Monitor */
-# define IRQ_MCINTR	34	/* Media Change */
-# define IRQ_TINTR	35	/* 64Hz Tick */
-# define IRQ_WEINT	36	/* Watchdog Expired */
-# define IRQ_RTCMI	37	/* Real-time Clock Match */
-# define IRQ_UART1INTR	38	/* UART1 Interrupt (including error) */
-# define IRQ_UART1ERR	39	/* UART1 Error */
-# define IRQ_UART2INTR	40	/* UART2 Interrupt (including error) */
-# define IRQ_UART2ERR	41	/* UART2 Error */
-# define IRQ_UART3INTR	42	/* UART3 Interrupt (including error) */
-# define IRQ_UART3ERR	43	/* UART3 Error */
-# define IRQ_SCIINTR	44	/* Smart Card */
-# define IRQ_TSCINTR	45	/* Touchscreen */
-# define IRQ_KMIINTR	46	/* Keyboard/Mouse (PS/2) */
-# define IRQ_GPIO4INTR	47	/* -- GPIOF Interrupt */
-# define IRQ_GPIO5INTR	48
-# define IRQ_GPIO6INTR	49
-# define IRQ_GPIO7INTR	50
-# define IRQ_T3UI	51	/* Timer 3 underflow */
-# define IRQ_LCDINTR	52	/* LCD Controller */
-# define IRQ_SSPINTR	53	/* Synchronous Serial Port */
-# define IRQ_SDINTR	54	/* Secure Digital Port (MMC) */
-# define IRQ_USBINTR	55	/* USB Device Port */
-# define IRQ_USHINTR	56	/* USB Host Port */
-# define IRQ_SOFT_V2_25	57	/* -- Unassigned */
-# define IRQ_SOFT_V2_26	58
-# define IRQ_SOFT_V2_27	59
-# define IRQ_SOFT_V2_28	60
-# define IRQ_SOFT_V2_29	61
-# define IRQ_SOFT_V2_30	62
-# define IRQ_SOFT_V2_31	63
-
-# define NR_IRQ_CPU	64	/* IRQs directly recognized by CPU */
-
-	/* Given IRQ, return GPIO interrupt number 0-7 */
-# define IRQ_TO_GPIO(i)  ((i) \
-	- (((i) > IRQ_GPIO3INTR) ? IRQ_GPIO4INTR - IRQ_GPIO3INTR - 1 : 0)\
-	- IRQ_GPIO0INTR)
-
-			/* Vector Address constants */
-# define VA_VECTORED	0x100	/* Set for vectored interrupt */
-# define VA_VIC1DEFAULT	0x200	/* Set as default VECTADDR for VIC1 */
-# define VA_VIC2DEFAULT	0x400	/* Set as default VECTADDR for VIC2 */
-
-#endif
-
-  /* IRQ aliases */
-
-#if !defined (IRQ_GPIO0INTR)
-# define IRQ_GPIO0INTR	IRQ_GPIO0FIQ
-#endif
-#define IRQ_TICK	IRQ_TINTR
-#define IRQ_PCC1_RDY	IRQ_GPIO6INTR	/* PCCard 1 ready */
-#define IRQ_PCC2_RDY	IRQ_GPIO7INTR	/* PCCard 2 ready */
-#define IRQ_USB		IRQ_USBINTR	/* USB device */
-
-#ifdef CONFIG_MACH_KEV7A400
-# define IRQ_TS		IRQ_GPIOFIQ	/* Touchscreen */
-# define IRQ_CPLD	IRQ_GPIO1INTR	/* CPLD cascade */
-# define IRQ_PCC1_CD	IRQ_GPIO_F2	/* PCCard 1 card detect */
-# define IRQ_PCC2_CD	IRQ_GPIO_F3	/* PCCard 2 card detect */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-# define IRQ_CPLD_V28	IRQ_GPIO7INTR	/* CPLD cascade through GPIO_PF7 */
-# define IRQ_CPLD_V34	IRQ_GPIO3INTR	/* CPLD cascade through GPIO_PF3 */
-#endif
-
-  /* System specific IRQs */
-
-#define IRQ_BOARD_START NR_IRQ_CPU
-
-#ifdef CONFIG_MACH_KEV7A400
-# define IRQ_KEV7A400_CPLD	IRQ_BOARD_START
-# define NR_IRQ_BOARD		5
-# define IRQ_KEV7A400_MMC_CD	IRQ_KEV7A400_CPLD + 0	/* MMC Card Detect */
-# define IRQ_KEV7A400_RI2	IRQ_KEV7A400_CPLD + 1	/* Ring Indicator 2 */
-# define IRQ_KEV7A400_IDE_CF	IRQ_KEV7A400_CPLD + 2	/* Compact Flash (?) */
-# define IRQ_KEV7A400_ETH_INT	IRQ_KEV7A400_CPLD + 3	/* Ethernet chip */
-# define IRQ_KEV7A400_INT	IRQ_KEV7A400_CPLD + 4
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-# define IRQ_LPD7A40X_CPLD	IRQ_BOARD_START
-# define NR_IRQ_BOARD		2
-# define IRQ_LPD7A40X_ETH_INT	IRQ_LPD7A40X_CPLD + 0	/* Ethernet chip */
-# define IRQ_LPD7A400_TS	IRQ_LPD7A40X_CPLD + 1	/* Touch screen */
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400)
-# define IRQ_TOUCH		IRQ_LPD7A400_TS
-#endif
-
-#define NR_IRQS		(NR_IRQ_CPU + NR_IRQ_BOARD)
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/memory.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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.
- *
- *
- *  Refer to <file:Documentation/arm/Sharp-LH/SDRAM> for more information.
- *
- */
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H
-
-/*
- * Physical DRAM offset.
- */
-#define PHYS_OFFSET	UL(0xc0000000)
-
-/*
- * Sparsemem version of the above
- */
-#define MAX_PHYSMEM_BITS	32
-#define SECTION_SIZE_BITS	24
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/registers.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/registers.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/registers.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/registers.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,224 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/registers.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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 <mach/constants.h>
-
-#ifndef __ASM_ARCH_REGISTERS_H
-#define __ASM_ARCH_REGISTERS_H
-
-
-	/* Physical register base addresses */
-
-#define AC97C_PHYS	(0x80000000)	/* AC97 Controller */
-#define MMC_PHYS	(0x80000100)	/* Multimedia Card Controller */
-#define USB_PHYS	(0x80000200)	/* USB Client */
-#define SCI_PHYS	(0x80000300)	/* Secure Card Interface */
-#define CSC_PHYS	(0x80000400)	/* Clock/State Controller  */
-#define INTC_PHYS	(0x80000500)	/* Interrupt Controller */
-#define UART1_PHYS	(0x80000600)	/* UART1 Controller */
-#define SIR_PHYS	(0x80000600)	/* IR Controller, same are UART1 */
-#define UART2_PHYS	(0x80000700)	/* UART2 Controller */
-#define UART3_PHYS	(0x80000800)	/* UART3 Controller */
-#define DCDC_PHYS	(0x80000900)	/* DC to DC Controller */
-#define ACI_PHYS	(0x80000a00)	/* Audio Codec Interface */
-#define SSP_PHYS	(0x80000b00)	/* Synchronous ... */
-#define TIMER_PHYS	(0x80000c00)	/* Timer Controller */
-#define RTC_PHYS	(0x80000d00)	/* Real-time Clock */
-#define GPIO_PHYS	(0x80000e00)	/* General Purpose IO */
-#define BMI_PHYS	(0x80000f00)	/* Battery Monitor Interface */
-#define HRTFTC_PHYS	(0x80001000)	/* High-res TFT Controller (LH7A400) */
-#define ALI_PHYS	(0x80001000)	/* Advanced LCD Interface (LH7A404) */
-#define WDT_PHYS	(0x80001400)	/* Watchdog Timer */
-#define SMC_PHYS	(0x80002000)	/* Static Memory Controller */
-#define SDRC_PHYS	(0x80002400)	/* SDRAM Controller */
-#define DMAC_PHYS	(0x80002800)	/* DMA Controller */
-#define CLCDC_PHYS	(0x80003000)	/* Color LCD Controller */
-
-	/* Physical registers of the LH7A404 */
-
-#define ADC_PHYS	(0x80001300)	/* A/D & Touchscreen Controller */
-#define VIC1_PHYS	(0x80008000)	/* Vectored Interrupt Controller 1 */
-#define USBH_PHYS	(0x80009000)	/* USB OHCI host controller */
-#define VIC2_PHYS	(0x8000a000)	/* Vectored Interrupt Controller 2 */
-
-/*#define KBD_PHYS	(0x80000e00) */
-/*#define LCDICP_PHYS	(0x80001000) */
-
-
-	/* Clock/State Controller register */
-
-#define CSC_PWRSR	__REG(CSC_PHYS + 0x00) /* Reset register & ID */
-#define CSC_PWRCNT	__REG(CSC_PHYS + 0x04) /* Power control */
-#define CSC_CLKSET	__REG(CSC_PHYS + 0x20) /* Clock speed control */
-#define CSC_USBDRESET	__REG(CSC_PHYS + 0x4c) /* USB Device resets */
-
-#define CSC_PWRCNT_USBH_EN	(1<<28)	/* USB Host power enable */
-#define CSC_PWRCNT_DMAC_M2M1_EN	(1<<27)
-#define CSC_PWRCNT_DMAC_M2M0_EN	(1<<26)
-#define CSC_PWRCNT_DMAC_M2P8_EN	(1<<25)
-#define CSC_PWRCNT_DMAC_M2P9_EN	(1<<24)
-#define CSC_PWRCNT_DMAC_M2P6_EN	(1<<23)
-#define CSC_PWRCNT_DMAC_M2P7_EN	(1<<22)
-#define CSC_PWRCNT_DMAC_M2P4_EN	(1<<21)
-#define CSC_PWRCNT_DMAC_M2P5_EN	(1<<20)
-#define CSC_PWRCNT_DMAC_M2P2_EN	(1<<19)
-#define CSC_PWRCNT_DMAC_M2P3_EN	(1<<18)
-#define CSC_PWRCNT_DMAC_M2P0_EN	(1<<17)
-#define CSC_PWRCNT_DMAC_M2P1_EN	(1<<16)
-
-#define CSC_PWRSR_CHIPMAN_SHIFT	(24)
-#define CSC_PWRSR_CHIPMAN_MASK	(0xff)
-#define CSC_PWRSR_CHIPID_SHIFT	(16)
-#define CSC_PWRSR_CHIPID_MASK	(0xff)
-
-#define CSC_USBDRESET_APBRESETREG	(1<<1)
-#define CSC_USBDRESET_IORESETREG	(1<<0)
-
-	/* Interrupt Controller registers */
-
-#define INTC_INTSR	__REG(INTC_PHYS + 0x00)	/* Status */
-#define INTC_INTRSR	__REG(INTC_PHYS + 0x04)	/* Raw Status */
-#define INTC_INTENS	__REG(INTC_PHYS + 0x08)	/* Enable Set */
-#define INTC_INTENC	__REG(INTC_PHYS + 0x0c)	/* Enable Clear */
-
-
-	/* Vectored Interrupted Controller registers */
-
-#define VIC1_IRQSTATUS	__REG(VIC1_PHYS + 0x00)
-#define VIC1_FIQSTATUS	__REG(VIC1_PHYS + 0x04)
-#define VIC1_RAWINTR	__REG(VIC1_PHYS + 0x08)
-#define VIC1_INTSEL	__REG(VIC1_PHYS + 0x0c)
-#define VIC1_INTEN	__REG(VIC1_PHYS + 0x10)
-#define VIC1_INTENCLR	__REG(VIC1_PHYS + 0x14)
-#define VIC1_SOFTINT	__REG(VIC1_PHYS + 0x18)
-#define VIC1_SOFTINTCLR	__REG(VIC1_PHYS + 0x1c)
-#define VIC1_PROTECT	__REG(VIC1_PHYS + 0x20)
-#define VIC1_VECTADDR	__REG(VIC1_PHYS + 0x30)
-#define VIC1_NVADDR	__REG(VIC1_PHYS + 0x34)
-#define VIC1_VAD0	__REG(VIC1_PHYS + 0x100)
-#define VIC1_VECTCNTL0	__REG(VIC1_PHYS + 0x200)
-#define VIC2_IRQSTATUS	__REG(VIC2_PHYS + 0x00)
-#define VIC2_FIQSTATUS	__REG(VIC2_PHYS + 0x04)
-#define VIC2_RAWINTR	__REG(VIC2_PHYS + 0x08)
-#define VIC2_INTSEL	__REG(VIC2_PHYS + 0x0c)
-#define VIC2_INTEN	__REG(VIC2_PHYS + 0x10)
-#define VIC2_INTENCLR	__REG(VIC2_PHYS + 0x14)
-#define VIC2_SOFTINT	__REG(VIC2_PHYS + 0x18)
-#define VIC2_SOFTINTCLR	__REG(VIC2_PHYS + 0x1c)
-#define VIC2_PROTECT	__REG(VIC2_PHYS + 0x20)
-#define VIC2_VECTADDR	__REG(VIC2_PHYS + 0x30)
-#define VIC2_NVADDR	__REG(VIC2_PHYS + 0x34)
-#define VIC2_VAD0	__REG(VIC2_PHYS + 0x100)
-#define VIC2_VECTCNTL0	__REG(VIC2_PHYS + 0x200)
-
-#define VIC_CNTL_ENABLE	(0x20)
-
-	/* USB Host registers (Open HCI compatible) */
-
-#define USBH_CMDSTATUS	__REG(USBH_PHYS + 0x08)
-
-
-	/* GPIO registers */
-
-#define GPIO_INTTYPE1	__REG(GPIO_PHYS + 0x4c)	/* Interrupt Type 1 (Edge) */
-#define GPIO_INTTYPE2	__REG(GPIO_PHYS + 0x50)	/* Interrupt Type 2 */
-#define GPIO_GPIOFEOI	__REG(GPIO_PHYS + 0x54)	/* GPIO End-of-Interrupt */
-#define GPIO_GPIOINTEN	__REG(GPIO_PHYS + 0x58)	/* GPIO Interrupt Enable */
-#define GPIO_INTSTATUS	__REG(GPIO_PHYS + 0x5c)	/* GPIO Interrupt Status */
-#define GPIO_PINMUX	__REG(GPIO_PHYS + 0x2c)
-#define GPIO_PADD	__REG(GPIO_PHYS + 0x10)
-#define GPIO_PAD	__REG(GPIO_PHYS + 0x00)
-#define GPIO_PCD	__REG(GPIO_PHYS + 0x08)
-#define GPIO_PCDD	__REG(GPIO_PHYS + 0x18)
-#define GPIO_PEDD	__REG(GPIO_PHYS + 0x24)
-#define GPIO_PED	__REG(GPIO_PHYS + 0x20)
-
-
-	/* Static Memory Controller registers */
-
-#define SMC_BCR0	__REG(SMC_PHYS + 0x00)	/* Bank 0 Configuration */
-#define SMC_BCR1	__REG(SMC_PHYS + 0x04)	/* Bank 1 Configuration */
-#define SMC_BCR2	__REG(SMC_PHYS + 0x08)	/* Bank 2 Configuration */
-#define SMC_BCR3	__REG(SMC_PHYS + 0x0C)	/* Bank 3 Configuration */
-#define SMC_BCR6	__REG(SMC_PHYS + 0x18)	/* Bank 6 Configuration */
-#define SMC_BCR7	__REG(SMC_PHYS + 0x1c)	/* Bank 7 Configuration */
-
-
-#ifdef CONFIG_MACH_KEV7A400
-# define CPLD_RD_OPT_DIP_SW	__REG16(CPLD_PHYS + 0x00) /* Read Option SW */
-# define CPLD_WR_IO_BRD_CTL	__REG16(CPLD_PHYS + 0x00) /* Write Control */
-# define CPLD_RD_PB_KEYS	__REG16(CPLD_PHYS + 0x02) /* Read Btn Keys */
-# define CPLD_LATCHED_INTS	__REG16(CPLD_PHYS + 0x04) /* Read INTR stat. */
-# define CPLD_CL_INT		__REG16(CPLD_PHYS + 0x04) /* Clear INTR stat */
-# define CPLD_BOOT_MMC_STATUS	__REG16(CPLD_PHYS + 0x06) /* R/O */
-# define CPLD_RD_KPD_ROW_SENSE	__REG16(CPLD_PHYS + 0x08)
-# define CPLD_WR_PB_INT_MASK	__REG16(CPLD_PHYS + 0x08)
-# define CPLD_RD_BRD_DISP_SW	__REG16(CPLD_PHYS + 0x0a)
-# define CPLD_WR_EXT_INT_MASK	__REG16(CPLD_PHYS + 0x0a)
-# define CPLD_LCD_PWR_CNTL	__REG16(CPLD_PHYS + 0x0c)
-# define CPLD_SEVEN_SEG		__REG16(CPLD_PHYS + 0x0e) /* 7 seg. LED mask */
-
-#endif
-
-#if defined (CONFIG_MACH_LPD7A400) || defined (CONFIG_MACH_LPD7A404)
-
-# define CPLD_CONTROL		__REG16(CPLD02_PHYS)
-# define CPLD_SPI_DATA		__REG16(CPLD06_PHYS)
-# define CPLD_SPI_CONTROL	__REG16(CPLD08_PHYS)
-# define CPLD_SPI_EEPROM	__REG16(CPLD0A_PHYS)
-# define CPLD_INTERRUPTS	__REG16(CPLD0C_PHYS) /* IRQ mask/status */
-# define CPLD_BOOT_MODE		__REG16(CPLD0E_PHYS)
-# define CPLD_FLASH		__REG16(CPLD10_PHYS)
-# define CPLD_POWER_MGMT	__REG16(CPLD12_PHYS)
-# define CPLD_REVISION		__REG16(CPLD14_PHYS)
-# define CPLD_GPIO_EXT		__REG16(CPLD16_PHYS)
-# define CPLD_GPIO_DATA		__REG16(CPLD18_PHYS)
-# define CPLD_GPIO_DIR		__REG16(CPLD1A_PHYS)
-
-#endif
-
-	/* Timer registers */
-
-#define TIMER_LOAD1	__REG(TIMER_PHYS + 0x00) /* Timer 1 initial value */
-#define TIMER_VALUE1	__REG(TIMER_PHYS + 0x04) /* Timer 1 current value */
-#define TIMER_CONTROL1	__REG(TIMER_PHYS + 0x08) /* Timer 1 control word */
-#define TIMER_EOI1	__REG(TIMER_PHYS + 0x0c) /* Timer 1 interrupt clear */
-
-#define TIMER_LOAD2	__REG(TIMER_PHYS + 0x20) /* Timer 2 initial value */
-#define TIMER_VALUE2	__REG(TIMER_PHYS + 0x24) /* Timer 2 current value */
-#define TIMER_CONTROL2	__REG(TIMER_PHYS + 0x28) /* Timer 2 control word */
-#define TIMER_EOI2	__REG(TIMER_PHYS + 0x2c) /* Timer 2 interrupt clear */
-
-#define TIMER_BUZZCON	__REG(TIMER_PHYS + 0x40) /* Buzzer configuration */
-
-#define TIMER_LOAD3	__REG(TIMER_PHYS + 0x80) /* Timer 3 initial value */
-#define TIMER_VALUE3	__REG(TIMER_PHYS + 0x84) /* Timer 3 current value */
-#define TIMER_CONTROL3	__REG(TIMER_PHYS + 0x88) /* Timer 3 control word */
-#define TIMER_EOI3	__REG(TIMER_PHYS + 0x8c) /* Timer 3 interrupt clear */
-
-#define TIMER_C_ENABLE		(1<<7)
-#define TIMER_C_PERIODIC	(1<<6)
-#define TIMER_C_FREERUNNING	(0)
-#define TIMER_C_2KHZ		(0x00)		/* 1.986 kHz */
-#define TIMER_C_508KHZ		(0x08)
-
-	/* GPIO registers */
-
-#define GPIO_PFDD		__REG(GPIO_PHYS + 0x34)	/* PF direction */
-#define GPIO_INTTYPE1		__REG(GPIO_PHYS + 0x4c)	/* IRQ edge or lvl  */
-#define GPIO_INTTYPE2		__REG(GPIO_PHYS + 0x50)	/* IRQ activ hi/lo */
-#define GPIO_GPIOFEOI		__REG(GPIO_PHYS + 0x54)	/* GPIOF end of IRQ */
-#define GPIO_GPIOFINTEN		__REG(GPIO_PHYS + 0x58)	/* GPIOF IRQ enable */
-#define GPIO_INTSTATUS		__REG(GPIO_PHYS + 0x5c)	/* GPIOF IRQ latch */
-#define GPIO_RAWINTSTATUS	__REG(GPIO_PHYS + 0x60)	/* GPIOF IRQ raw */
-
-
-#endif  /* _ASM_ARCH_REGISTERS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/ssp.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/ssp.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/ssp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/ssp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* ssp.h
-
-   written by Marc Singer
-   6 Dec 2004
-
-   Copyright (C) 2004 Marc Singer
-
-   -----------
-   DESCRIPTION
-   -----------
-
-   This SSP header is available throughout the kernel, for this
-   machine/architecture, because drivers that use it may be dispersed.
-
-   This file was cloned from the 7952x implementation.  It would be
-   better to share them, but we're taking an easier approach for the
-   time being.
-
-*/
-
-#if !defined (__SSP_H__)
-#    define   __SSP_H__
-
-/* ----- Includes */
-
-/* ----- Types */
-
-struct ssp_driver {
-	int  (*init)		(void);
-	void (*exit)		(void);
-	void (*acquire)		(void);
-	void (*release)		(void);
-	int  (*configure)	(int device, int mode, int speed,
-				 int frame_size_write, int frame_size_read);
-	void (*chip_select)	(int enable);
-	void (*set_callbacks)   (void* handle,
-				 irqreturn_t (*callback_tx)(void*),
-				 irqreturn_t (*callback_rx)(void*));
-	void (*enable)		(void);
-	void (*disable)		(void);
-//	int  (*save_state)	(void*);
-//	void (*restore_state)	(void*);
-	int  (*read)		(void);
-	int  (*write)		(u16 data);
-	int  (*write_read)	(u16 data);
-	void (*flush)		(void);
-	void (*write_async)	(void* pv, size_t cb);
-	size_t (*write_pos)	(void);
-};
-
-	/* These modes are only available on the LH79524 */
-#define SSP_MODE_SPI		(1)
-#define SSP_MODE_SSI		(2)
-#define SSP_MODE_MICROWIRE	(3)
-#define SSP_MODE_I2S		(4)
-
-	/* CPLD SPI devices */
-#define DEVICE_EEPROM	0	/* Configuration eeprom */
-#define DEVICE_MAC	1	/* MAC eeprom (LPD79524) */
-#define DEVICE_CODEC	2	/* Audio codec */
-#define DEVICE_TOUCH	3	/* Touch screen (LPD79520) */
-
-/* ----- Globals */
-
-/* ----- Prototypes */
-
-//extern struct ssp_driver lh79520_i2s_driver;
-extern struct ssp_driver lh7a400_cpld_ssp_driver;
-
-#endif  /* __SSP_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/system.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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.
- *
- */
-
-static inline void arch_idle(void)
-{
-	cpu_do_idle ();
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	cpu_reset (0);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/timex.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/timex.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/timex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/timex.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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 <mach/constants.h>
-
-#define CLOCK_TICK_RATE		(PLL_CLOCK/6/16)
-
-/*
-#define CLOCK_TICK_RATE		3686400
-*/
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/uncompress.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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 <mach/registers.h>
-
-#ifndef UART_R_DATA
-# define UART_R_DATA	(0x00)
-#endif
-#ifndef UART_R_STATUS
-# define UART_R_STATUS	(0x10)
-#endif
-#define nTxRdy		(0x20)	/* Not TxReady (literally Tx FIFO full) */
-
-	/* Access UART with physical addresses before MMU is setup */
-#define UART_STATUS (*(volatile unsigned long*) (UART2_PHYS + UART_R_STATUS))
-#define UART_DATA   (*(volatile unsigned long*) (UART2_PHYS + UART_R_DATA))
-
-static inline void putc(int ch)
-{
-	while (UART_STATUS & nTxRdy)
-		barrier();
-	UART_DATA = ch;
-}
-
-static inline void flush(void)
-{
-}
-
-	/* NULL functions; we don't presently need them */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/vmalloc.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/vmalloc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/include/mach/vmalloc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-/* arch/arm/mach-lh7a40x/include/mach/vmalloc.h
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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 VMALLOC_END       (0xe8000000UL)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-kev7a400.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-kev7a400.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-kev7a400.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-kev7a400.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,93 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-kev7a400.c
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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>
-#include <linux/init.h>
-
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <asm/mach/hardware.h>
-#include <asm/mach/irqs.h>
-
-#include "common.h"
-
-  /* KEV7a400 CPLD IRQ handling */
-
-static u16 CPLD_IRQ_mask;	/* Mask for CPLD IRQs, 1 == unmasked */
-
-static void
-lh7a400_ack_cpld_irq (u32 irq)
-{
-	CPLD_CL_INT = 1 << (irq - IRQ_KEV7A400_CPLD);
-}
-
-static void
-lh7a400_mask_cpld_irq (u32 irq)
-{
-	CPLD_IRQ_mask &= ~(1 << (irq - IRQ_KEV7A400_CPLD));
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static void
-lh7a400_unmask_cpld_irq (u32 irq)
-{
-	CPLD_IRQ_mask |= 1 << (irq - IRQ_KEV7A400_CPLD);
-	CPLD_WR_PB_INT_MASK = CPLD_IRQ_mask;
-}
-
-static struct
-irq_chip lh7a400_cpld_chip = {
-	.name	= "CPLD",
-	.ack	= lh7a400_ack_cpld_irq,
-	.mask	= lh7a400_mask_cpld_irq,
-	.unmask	= lh7a400_unmask_cpld_irq,
-};
-
-static void
-lh7a400_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	u32 mask = CPLD_LATCHED_INTS;
-	irq = IRQ_KEV_7A400_CPLD;
-	for (; mask; mask >>= 1, ++irq) {
-		if (mask & 1)
-			desc[irq].handle (irq, desc);
-	}
-}
-
-  /* IRQ initialization */
-
-void __init
-lh7a400_init_board_irq (void)
-{
-	int irq;
-
-	for (irq = IRQ_KEV7A400_CPLD;
-	     irq < IRQ_KEV7A400_CPLD + NR_IRQ_KEV7A400_CPLD; ++irq) {
-		set_irq_chip (irq, &lh7a400_cpld_chip);
-		set_irq_handler (irq, handle_edge_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-	set_irq_chained_handler (IRQ_CPLD, kev7a400_cpld_handler);
-
-		/* Clear all CPLD interrupts */
-	CPLD_CL_INT = 0xff; /* CPLD_INTR_MMC_CD | CPLD_INTR_ETH_INT; */
-
-    /* *** FIXME CF enabled in ide-probe.c */
-
-	GPIO_GPIOINTEN = 0;		/* Disable all GPIO interrupts */
-	barrier();
-	GPIO_INTTYPE1
-		= (GPIO_INTR_PCC1_CD | GPIO_INTR_PCC1_CD); /* Edge trig. */
-	GPIO_INTTYPE2 = 0;		/* Falling edge & low-level */
-	GPIO_GPIOFEOI = 0xff;		/* Clear all GPIO interrupts */
-	GPIO_GPIOINTEN = 0xff;		/* Enable all GPIO interrupts */
-
-	init_FIQ();
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-lh7a400.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-lh7a400.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-lh7a400.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-lh7a400.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-lh7a400.c
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *
- *  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/module.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <mach/irqs.h>
-
-#include "common.h"
-
-  /* CPU IRQ handling */
-
-static void lh7a400_mask_irq(struct irq_data *d)
-{
-	INTC_INTENC = (1 << d->irq);
-}
-
-static void lh7a400_unmask_irq(struct irq_data *d)
-{
-	INTC_INTENS = (1 << d->irq);
-}
-
-static void lh7a400_ack_gpio_irq(struct irq_data *d)
-{
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
-	INTC_INTENC = (1 << d->irq);
-}
-
-static struct irq_chip lh7a400_internal_chip = {
-	.name		= "MPU",
-	.irq_ack	= lh7a400_mask_irq, /* Level triggering -> mask is ack */
-	.irq_mask	= lh7a400_mask_irq,
-	.irq_unmask	= lh7a400_unmask_irq,
-};
-
-static struct irq_chip lh7a400_gpio_chip = {
-	.name		= "GPIO",
-	.irq_ack	= lh7a400_ack_gpio_irq,
-	.irq_mask	= lh7a400_mask_irq,
-	.irq_unmask	= lh7a400_unmask_irq,
-};
-
-
-  /* IRQ initialization */
-
-void __init lh7a400_init_irq (void)
-{
-	int irq;
-
-	INTC_INTENC = 0xffffffff;	/* Disable all interrupts */
-	GPIO_GPIOFINTEN = 0x00;		/* Disable all GPIOF interrupts */
-	barrier ();
-
-	for (irq = 0; irq < NR_IRQS; ++irq) {
-		switch (irq) {
-		case IRQ_GPIO0INTR:
-		case IRQ_GPIO1INTR:
-		case IRQ_GPIO2INTR:
-		case IRQ_GPIO3INTR:
-		case IRQ_GPIO4INTR:
-		case IRQ_GPIO5INTR:
-		case IRQ_GPIO6INTR:
-		case IRQ_GPIO7INTR:
-			set_irq_chip (irq, &lh7a400_gpio_chip);
-			set_irq_handler (irq, handle_level_irq); /* OK default */
-			break;
-		default:
-			set_irq_chip (irq, &lh7a400_internal_chip);
-			set_irq_handler (irq, handle_level_irq);
-		}
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	lh7a40x_init_board_irq ();
-
-/* *** FIXME: the LH7a400 does use FIQ interrupts in some cases.  For
-   the time being, these are not initialized. */
-
-/*	init_FIQ(); */
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-lh7a404.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-lh7a404.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-lh7a404.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-lh7a404.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,175 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-lh7a404.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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/module.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <mach/irqs.h>
-
-#include "common.h"
-
-#define USE_PRIORITIES
-
-/* See Documentation/arm/Sharp-LH/VectoredInterruptController for more
- * information on using the vectored interrupt controller's
- * prioritizing feature. */
-
-static unsigned char irq_pri_vic1[] = {
-#if defined (USE_PRIORITIES)
-	IRQ_GPIO3INTR,			/* CPLD */
-	IRQ_DMAM2P4, IRQ_DMAM2P5,	/* AC97 */
-#endif
-};
-static unsigned char irq_pri_vic2[] = {
-#if defined (USE_PRIORITIES)
-	IRQ_T3UI,			/* Timer */
-	IRQ_GPIO7INTR,			/* CPLD */
-	IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR,
-	IRQ_LCDINTR,			/* LCD */
-	IRQ_TSCINTR,			/* ADC/Touchscreen */
-#endif
-};
-
-  /* CPU IRQ handling */
-
-static void lh7a404_vic1_mask_irq(struct irq_data *d)
-{
-	VIC1_INTENCLR = (1 << d->irq);
-}
-
-static void lh7a404_vic1_unmask_irq(struct irq_data *d)
-{
-	VIC1_INTEN = (1 << d->irq);
-}
-
-static void lh7a404_vic2_mask_irq(struct irq_data *d)
-{
-	VIC2_INTENCLR = (1 << (d->irq - 32));
-}
-
-static void lh7a404_vic2_unmask_irq(struct irq_data *d)
-{
-	VIC2_INTEN = (1 << (d->irq - 32));
-}
-
-static void lh7a404_vic1_ack_gpio_irq(struct irq_data *d)
-{
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
-	VIC1_INTENCLR = (1 << d->irq);
-}
-
-static void lh7a404_vic2_ack_gpio_irq(struct irq_data *d)
-{
-	GPIO_GPIOFEOI = (1 << IRQ_TO_GPIO (d->irq));
-	VIC2_INTENCLR = (1 << d->irq);
-}
-
-static struct irq_chip lh7a404_vic1_chip = {
-	.name		= "VIC1",
-	.irq_ack	= lh7a404_vic1_mask_irq, /* Because level-triggered */
-	.irq_mask	= lh7a404_vic1_mask_irq,
-	.irq_unmask	= lh7a404_vic1_unmask_irq,
-};
-
-static struct irq_chip lh7a404_vic2_chip = {
-	.name		= "VIC2",
-	.irq_ack	= lh7a404_vic2_mask_irq, /* Because level-triggered */
-	.irq_mask	= lh7a404_vic2_mask_irq,
-	.irq_unmask	= lh7a404_vic2_unmask_irq,
-};
-
-static struct irq_chip lh7a404_gpio_vic1_chip = {
-	.name		= "GPIO-VIC1",
-	.irq_ack	= lh7a404_vic1_ack_gpio_irq,
-	.irq_mask	= lh7a404_vic1_mask_irq,
-	.irq_unmask	= lh7a404_vic1_unmask_irq,
-};
-
-static struct irq_chip lh7a404_gpio_vic2_chip = {
-	.name		= "GPIO-VIC2",
-	.irq_ack	= lh7a404_vic2_ack_gpio_irq,
-	.irq_mask	= lh7a404_vic2_mask_irq,
-	.irq_unmask	= lh7a404_vic2_unmask_irq,
-};
-
-  /* IRQ initialization */
-
-#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-extern void* branch_irq_lh7a400;
-#endif
-
-void __init lh7a404_init_irq (void)
-{
-	int irq;
-
-#if defined (CONFIG_ARCH_LH7A400) && defined (CONFIG_ARCH_LH7A404)
-#define NOP 0xe1a00000			/* mov r0, r0 */
-	branch_irq_lh7a400 = NOP;
-#endif
-
-	VIC1_INTENCLR = 0xffffffff;
-	VIC2_INTENCLR = 0xffffffff;
-	VIC1_INTSEL = 0;		/* All IRQs */
-	VIC2_INTSEL = 0;		/* All IRQs */
-	VIC1_NVADDR = VA_VIC1DEFAULT;
-	VIC2_NVADDR = VA_VIC2DEFAULT;
-	VIC1_VECTADDR = 0;
-	VIC2_VECTADDR = 0;
-
-	GPIO_GPIOFINTEN = 0x00;		/* Disable all GPIOF interrupts */
-	barrier ();
-
-		/* Install prioritized interrupts, if there are any. */
-		/* The | 0x20*/
-	for (irq = 0; irq < 16; ++irq) {
-		(&VIC1_VAD0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic1))
-			? (irq_pri_vic1[irq] | VA_VECTORED) : 0;
-		(&VIC1_VECTCNTL0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic1))
-			? (irq_pri_vic1[irq] | VIC_CNTL_ENABLE) : 0;
-		(&VIC2_VAD0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic2))
-			? (irq_pri_vic2[irq] | VA_VECTORED) : 0;
-		(&VIC2_VECTCNTL0)[irq]
-			= (irq < ARRAY_SIZE (irq_pri_vic2))
-			? (irq_pri_vic2[irq] | VIC_CNTL_ENABLE) : 0;
-	}
-
-	for (irq = 0; irq < NR_IRQS; ++irq) {
-		switch (irq) {
-		case IRQ_GPIO0INTR:
-		case IRQ_GPIO1INTR:
-		case IRQ_GPIO2INTR:
-		case IRQ_GPIO3INTR:
-		case IRQ_GPIO4INTR:
-		case IRQ_GPIO5INTR:
-		case IRQ_GPIO6INTR:
-		case IRQ_GPIO7INTR:
-			set_irq_chip (irq, irq < 32
-				      ? &lh7a404_gpio_vic1_chip
-				      : &lh7a404_gpio_vic2_chip);
-			set_irq_handler (irq, handle_level_irq); /* OK default */
-			break;
-		default:
-			set_irq_chip (irq, irq < 32
-				      ? &lh7a404_vic1_chip
-				      : &lh7a404_vic2_chip);
-			set_irq_handler (irq, handle_level_irq);
-		}
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	lh7a40x_init_board_irq ();
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-lpd7a40x.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-lpd7a40x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/irq-lpd7a40x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/irq-lpd7a40x.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,128 +0,0 @@
-/* arch/arm/mach-lh7a40x/irq-lpd7a40x.c
- *
- *  Copyright (C) 2004 Coastal Environmental Systems
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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/module.h>
-#include <linux/interrupt.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/mach/irq.h>
-#include <mach/irqs.h>
-
-#include "common.h"
-
-static void lh7a40x_ack_cpld_irq(struct irq_data *d)
-{
-	/* CPLD doesn't have ack capability */
-}
-
-static void lh7a40x_mask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x4;
-		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS | 0x8;
-		break;
-	}
-}
-
-static void lh7a40x_unmask_cpld_irq(struct irq_data *d)
-{
-	switch (d->irq) {
-	case IRQ_LPD7A40X_ETH_INT:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x4;
-		break;
-	case IRQ_LPD7A400_TS:
-		CPLD_INTERRUPTS = CPLD_INTERRUPTS & ~ 0x8;
-		break;
-	}
-}
-
-static struct irq_chip lh7a40x_cpld_chip = {
-	.name		= "CPLD",
-	.irq_ack	= lh7a40x_ack_cpld_irq,
-	.irq_mask	= lh7a40x_mask_cpld_irq,
-	.irq_unmask	= lh7a40x_unmask_cpld_irq,
-};
-
-static void lh7a40x_cpld_handler (unsigned int irq, struct irq_desc *desc)
-{
-	unsigned int mask = CPLD_INTERRUPTS;
-
-	desc->irq_data.chip->ack (irq);
-
-	if ((mask & 0x1) == 0)	/* WLAN */
-		generic_handle_irq(IRQ_LPD7A40X_ETH_INT);
-
-	if ((mask & 0x2) == 0)	/* Touch */
-		generic_handle_irq(IRQ_LPD7A400_TS);
-
-	desc->irq_data.chip->unmask (irq); /* Level-triggered need this */
-}
-
-
-  /* IRQ initialization */
-
-void __init lh7a40x_init_board_irq (void)
-{
-	int irq;
-
-		/* Rev A (v2.8): PF0, PF1, PF2, and PF3 are available IRQs.
-		                 PF7 supports the CPLD.
-		   Rev B (v3.4): PF0, PF1, and PF2 are available IRQs.
-		                 PF3 supports the CPLD.
-		   (Some) LPD7A404 prerelease boards report a version
-		   number of 0x16, but we force an override since the
-		   hardware is of the newer variety.
-		*/
-
-	unsigned char cpld_version = CPLD_REVISION;
-	int pinCPLD;
-
-#if defined CONFIG_MACH_LPD7A404
-	cpld_version = 0x34;	/* Override, for now */
-#endif
-	pinCPLD = (cpld_version == 0x28) ? 7 : 3;
-
-		/* First, configure user controlled GPIOF interrupts  */
-
-	GPIO_PFDD	&= ~0x0f; /* PF0-3 are inputs */
-	GPIO_INTTYPE1	&= ~0x0f; /* PF0-3 are level triggered */
-	GPIO_INTTYPE2	&= ~0x0f; /* PF0-3 are active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  0x0f; /* Enable PF0, PF1, PF2, and PF3 IRQs */
-
-		/* Then, configure CPLD interrupt */
-
-	CPLD_INTERRUPTS	=   0x0c; /* Disable all CPLD interrupts */
-	GPIO_PFDD	&= ~(1 << pinCPLD); /* Make input */
-	GPIO_INTTYPE1	|=  (1 << pinCPLD); /* Edge triggered */
-	GPIO_INTTYPE2	&= ~(1 << pinCPLD); /* Active low */
-	barrier ();
-	GPIO_GPIOFINTEN |=  (1 << pinCPLD); /* Enable */
-
-		/* Cascade CPLD interrupts */
-
-	for (irq = IRQ_BOARD_START;
-	     irq < IRQ_BOARD_START + NR_IRQ_BOARD; ++irq) {
-		set_irq_chip (irq, &lh7a40x_cpld_chip);
-		set_irq_handler (irq, handle_edge_irq);
-		set_irq_flags (irq, IRQF_VALID);
-	}
-
-	set_irq_chained_handler ((cpld_version == 0x28)
-				 ? IRQ_CPLD_V28
-				 : IRQ_CPLD_V34,
-				 lh7a40x_cpld_handler);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-if ARCH_LH7A40X
-
-menu "LH7A40X Implementations"
-
-config MACH_KEV7A400
-	bool "KEV7A400"
-	select ARCH_LH7A400
-	help
-	  Say Y here if you are using the Sharp KEV7A400 development
-	  board.  This hardware is discontinued, so I'd be very
-	  surprised if you wanted this option.
-
-config MACH_LPD7A400
-	bool "LPD7A400 Card Engine"
-	select ARCH_LH7A400
-#	select IDE_POLL
-#	select HAS_TOUCHSCREEN_ADS7843_LH7
-	help
-	  Say Y here if you are using Logic Product Development's
-	  LPD7A400 CardEngine.  For the time being, the LPD7A400 and
-	  LPD7A404 options are mutually exclusive.
-
-config MACH_LPD7A404
-	bool "LPD7A404 Card Engine"
-	select ARCH_LH7A404
-#	select IDE_POLL
-#	select HAS_TOUCHSCREEN_ADC_LH7
-	help
-	  Say Y here if you are using Logic Product Development's
-	  LPD7A404 CardEngine. For the time being, the LPD7A400 and
-	  LPD7A404 options are mutually exclusive.
-
-config ARCH_LH7A400
-	bool
-
-config ARCH_LH7A404
-	bool
-
-config LPD7A40X_CPLD_SSP
-	bool
-
-config LH7A40X_CONTIGMEM
-	bool "Disable NUMA/SparseMEM Support"
-	help
-	  Say Y here if your bootloader sets the SROMLL bit(s) in
-	  the SDRAM controller, organizing memory as a contiguous
-	  array.  This option will disable sparse memory support
-          and force the kernel to manage all memory in one node.
-
-	  Setting this option incorrectly may prevent the kernel
-	  from booting.  It is OK to leave it N.
-
-	  For more information, consult
-	    <file:Documentation/arm/Sharp-LH/SDRAM>.
-
-config LH7A40X_ONE_BANK_PER_NODE
-	bool "Optimize NUMA Node Tables for Size"
-	depends on !LH7A40X_CONTIGMEM
-	help
-	  Say Y here to produce compact memory node tables.  By
-	  default pairs of adjacent physical RAM banks are managed
-	  together in a single node, incurring some wasted overhead
-	  in the node tables, however also maintaining compatibility
-	  with systems where physical memory is truly contiguous.
-
-	  Setting this option incorrectly may prevent the kernel from
-	  booting.  It is OK to leave it N.
-
-	  For more information, consult
-	    <file:Documentation/arm/Sharp-LH/SDRAM>.
-
-endmenu
-
-endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/lcd-panel.h linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/lcd-panel.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/lcd-panel.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/lcd-panel.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,345 +0,0 @@
-/* lcd-panel.h
-
-   written by Marc Singer
-   18 Jul 2005
-
-   Copyright (C) 2005 Marc Singer
-
-   -----------
-   DESCRIPTION
-   -----------
-
-   Only one panel may be defined at a time.
-
-   The pixel clock is calculated to be no greater than the target.
-
-   Each timing value is accompanied by a specification comment.
-
-     UNITS/MIN/TYP/MAX
-
-   Most of the units will be in clocks.
-
-   USE_RGB555
-
-     Define this macro to configure the AMBA LCD controller to use an
-     RGB555 encoding for the pels instead of the normal RGB565.
-
-   LPD9520, LPD79524, LPD7A400, LPD7A404-10, LPD7A404-11
-
-     These boards are best approximated by 555 for all panels.  Some
-     can use an extra low-order bit of blue in bit 16 of the color
-     value, but we don't have a way to communicate this non-linear
-     mapping to the kernel.
-
-*/
-
-#if !defined (__LCD_PANEL_H__)
-#    define   __LCD_PANEL_H__
-
-#if defined (MACH_LPD79520)\
- || defined (MACH_LPD79524)\
- || defined (MACH_LPD7A400)\
- || defined (MACH_LPD7A404)
-# define USE_RGB555
-#endif
-
-struct clcd_panel_extra {
-	unsigned int hrmode;
-	unsigned int clsen;
-	unsigned int spsen;
-	unsigned int pcdel;
-	unsigned int revdel;
-	unsigned int lpdel;
-	unsigned int spldel;
-	unsigned int pc2del;
-};
-
-#define NS_TO_CLOCK(ns,c)	((((ns)*((c)/1000) + (1000000 - 1))/1000000))
-#define CLOCK_TO_DIV(e,c)	(((c) + (e) - 1)/(e))
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ035Q7DB02_HRTFT
-
-	/* Logic Product Development LCD 3.5" QVGA HRTFT -10 */
-	/* Sharp PN LQ035Q7DB02 w/HRTFT controller chip */
-
-#define PIX_CLOCK_TARGET	(6800000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "3.5in QVGA (LQ035Q7DB02)",
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 16,
-		.right_margin	= 21,
-		.upper_margin	= 8,			// line/8/8/8
-		.lower_margin	= 5,
-		.hsync_len	= 61,
-		.vsync_len	= NS_TO_CLOCK (60, PIX_CLOCK),
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IPC | (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#define HAS_LCD_PANEL_EXTRA
-
-static struct clcd_panel_extra lcd_panel_extra = {
-	.hrmode = 1,
-	.clsen = 1,
-	.spsen = 1,
-	.pcdel = 8,
-	.revdel = 7,
-	.lpdel = 13,
-	.spldel = 77,
-	.pc2del = 208,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ057Q3DC02
-
-	/* Logic Product Development LCD 5.7" QVGA -10 */
-	/* Sharp PN LQ057Q3DC02 */
-	/* QVGA mode, V/Q=LOW */
-
-/* From Sharp on 2006.1.3.  I believe some of the values are incorrect
- * based on the datasheet.
-
-    Timing0	TIMING1		TIMING2		CONTROL
-    0x140A0C4C	0x080504EF	0x013F380D	0x00000829
-    HBP= 20	VBP=  8		BCD=  0
-    HFP= 10	VFP=  5		CPL=319
-    HSW= 12	VSW=  1		IOE=  0
-    PPL= 19	LPP=239		IPC=  1
-				IHS=  1
-				IVS=  1
-				ACB=  0
-				CSEL= 0
-				PCD= 13
-
- */
-
-/* The full horizontal cycle (Th) is clock/360/400/450. */
-/* The full vertical   cycle (Tv) is line/251/262/280. */
-
-#define PIX_CLOCK_TARGET	(6300000) /* -/6.3/7 MHz */
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "5.7in QVGA (LQ057Q3DC02)",
-		.xres		= 320,
-		.yres		= 240,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 11,
-		.right_margin	= 400-11-320-2,
-		.upper_margin	= 7,			// line/7/7/7
-		.lower_margin	= 262-7-240-2,
-		.hsync_len	= 2,			// clk/2/96/200
-		.vsync_len	= 2,			// line/2/-/34
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ64D343
-
-	/* Logic Product Development LCD 6.4" VGA -10 */
-	/* Sharp PN LQ64D343 */
-
-/* The full horizontal cycle (Th) is clock/750/800/900. */
-/* The full vertical   cycle (Tv) is line/515/525/560. */
-
-#define PIX_CLOCK_TARGET	(28330000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "6.4in QVGA (LQ64D343)",
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 32,
-		.right_margin	= 800-32-640-96,
-		.upper_margin	= 32,			// line/34/34/34
-		.lower_margin	= 540-32-480-2,
-		.hsync_len	= 96,			// clk/2/96/200
-		.vsync_len	= 2,			// line/2/-/34
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ10D368
-
-	/* Logic Product Development LCD 10.4" VGA -10 */
-	/* Sharp PN LQ10D368 */
-
-#define PIX_CLOCK_TARGET	(28330000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "10.4in VGA (LQ10D368)",
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 21,
-		.right_margin	= 15,
-		.upper_margin	= 34,
-		.lower_margin	= 5,
-		.hsync_len	= 96,
-		.vsync_len	= 16,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_SHARP_LQ121S1DG41
-
-	/* Logic Product Development LCD 12.1" SVGA -10 */
-	/* Sharp PN LQ121S1DG41, was LQ121S1DG31 */
-
-/* Note that with a 99993900 Hz HCLK, it is not possible to hit the
- * target clock frequency range of 35MHz to 42MHz. */
-
-/* If the target pixel clock is substantially lower than the panel
- * spec, this is done to prevent the LCD display from glitching when
- * the CPU is under load.  A pixel clock higher than 25MHz
- * (empirically determined) will compete with the CPU for bus cycles
- * for the Ethernet chip.  However, even a pixel clock of 10MHz
- * competes with Compact Flash interface during some operations
- * (fdisk, e2fsck).  And, at that speed the display may have a visible
- * flicker. */
-
-/* The full horizontal cycle (Th) is clock/832/1056/1395. */
-
-#define PIX_CLOCK_TARGET	(20000000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "12.1in SVGA (LQ121S1DG41)",
-		.xres		= 800,
-		.yres		= 600,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 89,		// ns/5/-/(1/PIX_CLOCK)-10
-		.right_margin	= 1056-800-89-128,
-		.upper_margin	= 23,		// line/23/23/23
-		.lower_margin	= 44,
-		.hsync_len	= 128,		// clk/2/128/200
-		.vsync_len	= 4,		// line/2/4/6
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#if defined CONFIG_FB_ARMCLCD_HITACHI
-
-	/* Hitachi*/
-	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
-
-#define PIX_CLOCK_TARGET	(49000000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "Hitachi 800x480",
-		.xres		= 800,
-		.yres		= 480,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 88,
-		.right_margin	= 40,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 128,
-		.vsync_len	= 2,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-
-#if defined CONFIG_FB_ARMCLCD_AUO_A070VW01_WIDE
-
-	/* AU Optotronics  A070VW01 7.0 Wide Screen color Display*/
-	/* Submitted by Michele Da Rold <michele.darold@ecsproject.com> */
-
-#define PIX_CLOCK_TARGET	(10000000)
-#define PIX_CLOCK_DIVIDER	CLOCK_TO_DIV (PIX_CLOCK_TARGET, HCLK)
-#define PIX_CLOCK		(HCLK/PIX_CLOCK_DIVIDER)
-
-static struct clcd_panel lcd_panel = {
-	.mode	= {
-		.name		= "7.0in Wide (A070VW01)",
-		.xres		= 480,
-		.yres		= 234,
-		.pixclock	= PIX_CLOCK,
-		.left_margin	= 30,
-		.right_margin	= 25,
-		.upper_margin	= 14,
-		.lower_margin	= 12,
-		.hsync_len	= 100,
-		.vsync_len	= 1,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IPC | TIM2_IHS | TIM2_IVS
-			| (PIX_CLOCK_DIVIDER - 2),
-	.cntl		= CNTL_LCDTFT | CNTL_WATERMARK,
-	.bpp		= 16,
-};
-
-#endif
-
-#undef NS_TO_CLOCK
-#undef CLOCK_TO_DIV
-
-#endif  /* __LCD_PANEL_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-# Object file lists.
-
-obj-y				:= time.o clocks.o
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-obj-$(CONFIG_MACH_KEV7A400)	+= arch-kev7a400.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A400)	+= arch-lpd7a40x.o irq-lh7a400.o
-obj-$(CONFIG_MACH_LPD7A404)	+= arch-lpd7a40x.o irq-lh7a404.o
-obj-$(CONFIG_LPD7A40X_CPLD_SSP)	+= ssp-cpld.o
-obj-$(CONFIG_FB_ARMCLCD)	+= clcd.o
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/Makefile.boot linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/Makefile.boot
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/Makefile.boot	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,4 +0,0 @@
-   zreladdr-y	:= 0xc0008000
-params_phys-y	:= 0xc0000100
-initrd_phys-y	:= 0xc4000000
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/ssp-cpld.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/ssp-cpld.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/ssp-cpld.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/ssp-cpld.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,343 +0,0 @@
-/* arch/arm/mach-lh7a40x/ssp-cpld.c
- *
- *  Copyright (C) 2004,2005 Marc Singer
- *
- *  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.
- *
- * SSP/SPI driver for the CardEngine CPLD.
- *
- */
-
-/* NOTES
-   -----
-
-   o *** This driver is cribbed from the 7952x implementation.
-	 Some comments may not apply.
-
-   o This driver contains sufficient logic to control either the
-     serial EEPROMs or the audio codec.  It is included in the kernel
-     to support the codec.  The EEPROMs are really the responsibility
-     of the boot loader and should probably be left alone.
-
-   o The code must be augmented to cope with multiple, simultaneous
-     clients.
-     o The audio codec writes to the codec chip whenever playback
-       starts.
-     o The touchscreen driver writes to the ads chip every time it
-       samples.
-     o The audio codec must write 16 bits, but the touch chip writes
-       are 8 bits long.
-     o We need to be able to keep these configurations separate while
-       simultaneously active.
-
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-//#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-//#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <mach/hardware.h>
-
-#include <mach/ssp.h>
-
-//#define TALK
-
-#if defined (TALK)
-#define PRINTK(f...)		printk (f)
-#else
-#define PRINTK(f...)		do {} while (0)
-#endif
-
-#if defined (CONFIG_ARCH_LH7A400)
-# define CPLD_SPID		__REGP16(CPLD06_VIRT) /* SPI data */
-# define CPLD_SPIC		__REGP16(CPLD08_VIRT) /* SPI control */
-# define CPLD_SPIC_CS_CODEC	(1<<0)
-# define CPLD_SPIC_CS_TOUCH	(1<<1)
-# define CPLD_SPIC_WRITE	(0<<2)
-# define CPLD_SPIC_READ		(1<<2)
-# define CPLD_SPIC_DONE		(1<<3) /* r/o */
-# define CPLD_SPIC_LOAD		(1<<4)
-# define CPLD_SPIC_START	(1<<4)
-# define CPLD_SPIC_LOADED	(1<<5) /* r/o */
-#endif
-
-#define CPLD_SPI		__REGP16(CPLD0A_VIRT) /* SPI operation */
-#define CPLD_SPI_CS_EEPROM	(1<<3)
-#define CPLD_SPI_SCLK		(1<<2)
-#define CPLD_SPI_TX_SHIFT	(1)
-#define CPLD_SPI_TX		(1<<CPLD_SPI_TX_SHIFT)
-#define CPLD_SPI_RX_SHIFT	(0)
-#define CPLD_SPI_RX		(1<<CPLD_SPI_RX_SHIFT)
-
-/* *** FIXME: these timing values are substantially larger than the
-   *** chip requires. We may implement an nsleep () function. */
-#define T_SKH	1		/* Clock time high (us) */
-#define T_SKL	1		/* Clock time low (us) */
-#define T_CS	1		/* Minimum chip select low time (us)  */
-#define T_CSS	1		/* Minimum chip select setup time (us)  */
-#define T_DIS	1		/* Data setup time (us) */
-
-	 /* EEPROM SPI bits */
-#define P_START		(1<<9)
-#define P_WRITE		(1<<7)
-#define P_READ		(2<<7)
-#define P_ERASE		(3<<7)
-#define P_EWDS		(0<<7)
-#define P_WRAL		(0<<7)
-#define P_ERAL		(0<<7)
-#define P_EWEN		(0<<7)
-#define P_A_EWDS	(0<<5)
-#define P_A_WRAL	(1<<5)
-#define P_A_ERAL	(2<<5)
-#define P_A_EWEN	(3<<5)
-
-struct ssp_configuration {
-	int device;
-	int mode;
-	int speed;
-	int frame_size_write;
-	int frame_size_read;
-};
-
-static struct ssp_configuration ssp_configuration;
-static spinlock_t ssp_lock;
-
-static void enable_cs (void)
-{
-	switch (ssp_configuration.device) {
-	case DEVICE_EEPROM:
-		CPLD_SPI |= CPLD_SPI_CS_EEPROM;
-		break;
-	}
-	udelay (T_CSS);
-}
-
-static void disable_cs (void)
-{
-	switch (ssp_configuration.device) {
-	case DEVICE_EEPROM:
-		CPLD_SPI &= ~CPLD_SPI_CS_EEPROM;
-		break;
-	}
-	udelay (T_CS);
-}
-
-static void pulse_clock (void)
-{
-	CPLD_SPI |=  CPLD_SPI_SCLK;
-	udelay (T_SKH);
-	CPLD_SPI &= ~CPLD_SPI_SCLK;
-	udelay (T_SKL);
-}
-
-
-/* execute_spi_command
-
-   sends an spi command to a device.  It first sends cwrite bits from
-   v.  If cread is greater than zero it will read cread bits
-   (discarding the leading 0 bit) and return them.  If cread is less
-   than zero it will check for completetion status and return 0 on
-   success or -1 on timeout.  If cread is zero it does nothing other
-   than sending the command.
-
-   On the LPD7A400, we can only read or write multiples of 8 bits on
-   the codec and the touch screen device.  Here, we round up.
-
-*/
-
-static int execute_spi_command (int v, int cwrite, int cread)
-{
-	unsigned long l = 0;
-
-#if defined (CONFIG_MACH_LPD7A400)
-	/* The codec and touch devices cannot be bit-banged.  Instead,
-	 * the CPLD provides an eight-bit shift register and a crude
-	 * interface.  */
-	if (   ssp_configuration.device == DEVICE_CODEC
-	    || ssp_configuration.device == DEVICE_TOUCH) {
-		int select = 0;
-
-		PRINTK ("spi(%d %d.%d) 0x%04x",
-			ssp_configuration.device, cwrite, cread,
-			v);
-#if defined (TALK)
-		if (ssp_configuration.device == DEVICE_CODEC)
-			PRINTK (" 0x%03x -> %2d", v & 0x1ff, (v >> 9) & 0x7f);
-#endif
-		PRINTK ("\n");
-
-		if (ssp_configuration.device == DEVICE_CODEC)
-			select = CPLD_SPIC_CS_CODEC;
-		if (ssp_configuration.device == DEVICE_TOUCH)
-			select = CPLD_SPIC_CS_TOUCH;
-		if (cwrite) {
-			for (cwrite = (cwrite + 7)/8; cwrite-- > 0; ) {
-				CPLD_SPID = (v >> (8*cwrite)) & 0xff;
-				CPLD_SPIC = select | CPLD_SPIC_LOAD;
-				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
-					;
-				CPLD_SPIC = select;
-				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
-					;
-			}
-			v = 0;
-		}
-		if (cread) {
-			mdelay (2);	/* *** FIXME: required by ads7843? */
-			v = 0;
-			for (cread = (cread + 7)/8; cread-- > 0;) {
-				CPLD_SPID = 0;
-				CPLD_SPIC = select | CPLD_SPIC_READ
-					| CPLD_SPIC_START;
-				while (!(CPLD_SPIC & CPLD_SPIC_LOADED))
-					;
-				CPLD_SPIC = select | CPLD_SPIC_READ;
-				while (!(CPLD_SPIC & CPLD_SPIC_DONE))
-					;
-				v = (v << 8) | CPLD_SPID;
-			}
-		}
-		return v;
-	}
-#endif
-
-	PRINTK ("spi(%d) 0x%04x -> 0x%x\r\n", ssp_configuration.device,
-		v & 0x1ff, (v >> 9) & 0x7f);
-
-	enable_cs ();
-
-	v <<= CPLD_SPI_TX_SHIFT; /* Correction for position of SPI_TX bit */
-	while (cwrite--) {
-		CPLD_SPI
-			= (CPLD_SPI & ~CPLD_SPI_TX)
-			| ((v >> cwrite) & CPLD_SPI_TX);
-		udelay (T_DIS);
-		pulse_clock ();
-	}
-
-	if (cread < 0) {
-		int delay = 10;
-		disable_cs ();
-		udelay (1);
-		enable_cs ();
-
-		l = -1;
-		do {
-			if (CPLD_SPI & CPLD_SPI_RX) {
-				l = 0;
-				break;
-			}
-		} while (udelay (1), --delay);
-	}
-	else
-	/* We pulse the clock before the data to skip the leading zero. */
-		while (cread-- > 0) {
-			pulse_clock ();
-			l = (l<<1)
-				| (((CPLD_SPI & CPLD_SPI_RX)
-				    >> CPLD_SPI_RX_SHIFT) & 0x1);
-		}
-
-	disable_cs ();
-	return l;
-}
-
-static int ssp_init (void)
-{
-	spin_lock_init (&ssp_lock);
-	memset (&ssp_configuration, 0, sizeof (ssp_configuration));
-	return 0;
-}
-
-
-/* ssp_chip_select
-
-   drops the chip select line for the CPLD shift-register controlled
-   devices.  It doesn't enable chip
-
-*/
-
-static void ssp_chip_select (int enable)
-{
-#if defined (CONFIG_MACH_LPD7A400)
-	int select;
-
-	if (ssp_configuration.device == DEVICE_CODEC)
-		select = CPLD_SPIC_CS_CODEC;
-	else if (ssp_configuration.device == DEVICE_TOUCH)
-		select = CPLD_SPIC_CS_TOUCH;
-	else
-		return;
-
-	if (enable)
-		CPLD_SPIC = select;
-	else
-		CPLD_SPIC = 0;
-#endif
-}
-
-static void ssp_acquire (void)
-{
-	spin_lock (&ssp_lock);
-}
-
-static void ssp_release (void)
-{
-	ssp_chip_select (0);	/* just in case */
-	spin_unlock (&ssp_lock);
-}
-
-static int ssp_configure (int device, int mode, int speed,
-			   int frame_size_write, int frame_size_read)
-{
-	ssp_configuration.device		= device;
-	ssp_configuration.mode			= mode;
-	ssp_configuration.speed			= speed;
-	ssp_configuration.frame_size_write	= frame_size_write;
-	ssp_configuration.frame_size_read	= frame_size_read;
-
-	return 0;
-}
-
-static int ssp_read (void)
-{
-	return execute_spi_command (0, 0, ssp_configuration.frame_size_read);
-}
-
-static int ssp_write (u16 data)
-{
-	execute_spi_command (data, ssp_configuration.frame_size_write, 0);
-	return 0;
-}
-
-static int ssp_write_read (u16 data)
-{
-	return execute_spi_command (data, ssp_configuration.frame_size_write,
-				    ssp_configuration.frame_size_read);
-}
-
-struct ssp_driver lh7a40x_cpld_ssp_driver = {
-	.init		= ssp_init,
-	.acquire	= ssp_acquire,
-	.release	= ssp_release,
-	.configure	= ssp_configure,
-	.chip_select	= ssp_chip_select,
-	.read		= ssp_read,
-	.write		= ssp_write,
-	.write_read	= ssp_write_read,
-};
-
-
-MODULE_AUTHOR("Marc Singer");
-MODULE_DESCRIPTION("LPD7A40X CPLD SPI driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/time.c linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/time.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lh7a40x/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lh7a40x/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,71 +0,0 @@
-/*
- *  arch/arm/mach-lh7a40x/time.c
- *
- *  Copyright (C) 2004 Logic Product Development
- *
- *  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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/time.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <asm/irq.h>
-#include <asm/leds.h>
-
-#include <asm/mach/time.h>
-#include "common.h"
-
-#if HZ < 100
-# define TIMER_CONTROL	TIMER_CONTROL2
-# define TIMER_LOAD	TIMER_LOAD2
-# define TIMER_CONSTANT	(508469/HZ)
-# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC | TIMER_C_508KHZ)
-# define TIMER_EOI	TIMER_EOI2
-# define TIMER_IRQ	IRQ_T2UI
-#else
-# define TIMER_CONTROL	TIMER_CONTROL3
-# define TIMER_LOAD	TIMER_LOAD3
-# define TIMER_CONSTANT	(3686400/HZ)
-# define TIMER_MODE	(TIMER_C_ENABLE | TIMER_C_PERIODIC)
-# define TIMER_EOI	TIMER_EOI3
-# define TIMER_IRQ	IRQ_T3UI
-#endif
-
-static irqreturn_t
-lh7a40x_timer_interrupt(int irq, void *dev_id)
-{
-	TIMER_EOI = 0;
-	timer_tick();
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction lh7a40x_timer_irq = {
-	.name		= "LHA740x Timer Tick",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= lh7a40x_timer_interrupt,
-};
-
-static void __init lh7a40x_timer_init (void)
-{
-				/* Stop/disable all timers */
-	TIMER_CONTROL1 = 0;
-	TIMER_CONTROL2 = 0;
-	TIMER_CONTROL3 = 0;
-
-	setup_irq (TIMER_IRQ, &lh7a40x_timer_irq);
-
-	TIMER_LOAD = TIMER_CONSTANT;
-	TIMER_CONTROL = TIMER_MODE;
-}
-
-struct sys_timer lh7a40x_timer = {
-	.init		= &lh7a40x_timer_init,
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-loki/common.c linux-libre-2.6.39-gnu/arch/arm/mach-loki/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-loki/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-loki/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 #include <asm/timex.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <mach/bridge-regs.h>
 #include <mach/loki.h>
 #include <plat/orion_nand.h>
 #include <plat/time.h>
@@ -290,9 +291,15 @@
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init loki_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 static void loki_timer_init(void)
 {
-	orion_time_init(IRQ_LOKI_BRIDGE, LOKI_TCLK);
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_LOKI_BRIDGE, LOKI_TCLK);
 }
 
 struct sys_timer loki_timer = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-loki/common.h linux-libre-2.6.39-gnu/arch/arm/mach-loki/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-loki/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-loki/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
  */
 void loki_map_io(void);
 void loki_init(void);
+void loki_init_early(void);
 void loki_init_irq(void);
 
 extern struct mbus_dram_target_info loki_mbus_dram_info;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-loki/include/mach/bridge-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-loki/include/mach/bridge-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-loki/include/mach/bridge-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-loki/include/mach/bridge-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,11 +17,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	0x0004
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-loki/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-loki/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-loki/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-loki/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-loki/lb88rc8480-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-loki/lb88rc8480-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-loki/lb88rc8480-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-loki/lb88rc8480-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,6 +93,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= lb88rc8480_init,
 	.map_io		= loki_map_io,
+	.init_early	= loki_init_early,
 	.init_irq	= loki_init_irq,
 	.timer		= &loki_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lpc32xx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,6 @@
 /*
  * Physical DRAM offset of bank 0
  */
-#define PHYS_OFFSET	UL(0x80000000)
+#define PLAT_PHYS_OFFSET	UL(0x80000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lpc32xx/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-lpc32xx/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lpc32xx/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lpc32xx/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
 	}
 
 	/* Ok to use the level handler for all types */
-	set_irq_handler(d->irq, handle_level_irq);
+	irq_set_handler(d->irq, handle_level_irq);
 
 	return 0;
 }
@@ -390,8 +390,8 @@
 
 	/* Configure supported IRQ's */
 	for (i = 0; i < NR_IRQS; i++) {
-		set_irq_chip(i, &lpc32xx_irq_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &lpc32xx_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
@@ -406,8 +406,8 @@
 	__raw_writel(0, LPC32XX_INTC_MASK(LPC32XX_SIC2_BASE));
 
 	/* MIC SUBIRQx interrupts will route handling to the chain handlers */
-	set_irq_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
-	set_irq_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
+	irq_set_chained_handler(IRQ_LPC32XX_SUB1IRQ, lpc32xx_sic1_handler);
+	irq_set_chained_handler(IRQ_LPC32XX_SUB2IRQ, lpc32xx_sic2_handler);
 
 	/* Initially disable all wake events */
 	__raw_writel(0, LPC32XX_CLKPWR_P01_ER);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-lpc32xx/pm.c linux-libre-2.6.39-gnu/arch/arm/mach-lpc32xx/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-lpc32xx/pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-lpc32xx/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
  * DRAM clocking and refresh are slightly different for systems with DDR
  * DRAM or regular SDRAM devices. If SDRAM is used in the system, the
  * SDRAM will still be accessible in direct-run mode. In DDR based systems,
- * a transistion to direct-run mode will stop all DDR accesses (no clocks).
+ * a transition to direct-run mode will stop all DDR accesses (no clocks).
  * Because of this, the code to switch power modes and the code to enter
  * and exit DRAM self-refresh modes must not be executed in DRAM. A small
  * section of IRAM is used instead for this.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,7 @@
 #define BANK_OFF(n)	(((n) < 3) ? (n) << 2 : 0x100 + (((n) - 3) << 2))
 #define GPIO_REG(x)	(*((volatile u32 *)(GPIO_REGS_VIRT + (x))))
 
-#define NR_BUILTIN_GPIO	(192)
+#define NR_BUILTIN_GPIO		IRQ_GPIO_NUM
 
 #define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	(IRQ_GPIO_START + (gpio))
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,6 @@
 #ifndef __ASM_MACH_MEMORY_H
 #define __ASM_MACH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif /* __ASM_MACH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/mfp-pxa168.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,15 @@
 #define MFP_DRIVE_MEDIUM	(0x2 << 13)
 #define MFP_DRIVE_FAST		(0x3 << 13)
 
+#undef MFP_CFG
+#undef MFP_CFG_DRV
+
+#define MFP_CFG(pin, af)		\
+	(MFP_LPM_INPUT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_MEDIUM)
+
+#define MFP_CFG_DRV(pin, af, drv)	\
+	(MFP_LPM_INPUT | MFP_PIN(MFP_PIN_##pin) | MFP_##af | MFP_DRIVE_##drv)
+
 /* GPIO */
 #define GPIO0_GPIO		MFP_CFG(GPIO0, AF5)
 #define GPIO1_GPIO		MFP_CFG(GPIO1, AF5)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/mmp2.h linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/mmp2.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/mmp2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/mmp2.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,8 +11,8 @@
 extern void mmp2_clear_pmic_int(void);
 
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/i2c.h>
 
 extern struct pxa_device_desc mmp2_device_uart1;
 extern struct pxa_device_desc mmp2_device_uart2;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/pxa168.h linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/pxa168.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/pxa168.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/pxa168.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,8 +8,8 @@
 extern void pxa168_clear_keypad_wakeup(void);
 
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 #include <video/pxa168fb.h>
 #include <plat/pxa27x_keypad.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/pxa910.h linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/pxa910.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/include/mach/pxa910.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/include/mach/pxa910.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,8 +7,8 @@
 extern void __init pxa910_init_irq(void);
 
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <mach/devices.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 extern struct pxa_device_desc pxa910_device_uart1;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/irq-mmp2.c linux-libre-2.6.39-gnu/arch/arm/mach-mmp/irq-mmp2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/irq-mmp2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/irq-mmp2.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,9 +110,9 @@
 		if (chip->irq_ack)
 			chip->irq_ack(d);
 
-		set_irq_chip(irq, chip);
+		irq_set_chip(irq, chip);
 		set_irq_flags(irq, IRQF_VALID);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_handler(irq, handle_level_irq);
 	}
 }
 
@@ -122,7 +122,7 @@
 
 	for (irq = 0; irq < IRQ_MMP2_MUX_BASE; irq++) {
 		icu_mask_irq(irq_get_irq_data(irq));
-		set_irq_chip(irq, &icu_irq_chip);
+		irq_set_chip(irq, &icu_irq_chip);
 		set_irq_flags(irq, IRQF_VALID);
 
 		switch (irq) {
@@ -133,7 +133,7 @@
 		case IRQ_MMP2_SSP_MUX:
 			break;
 		default:
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_handler(irq, handle_level_irq);
 			break;
 		}
 	}
@@ -149,9 +149,9 @@
 	init_mux_irq(&misc_irq_chip, IRQ_MMP2_MISC_BASE, 15);
 	init_mux_irq(&ssp_irq_chip, IRQ_MMP2_SSP_BASE, 2);
 
-	set_irq_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
-	set_irq_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
-	set_irq_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
-	set_irq_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
-	set_irq_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
+	irq_set_chained_handler(IRQ_MMP2_PMIC_MUX, pmic_irq_demux);
+	irq_set_chained_handler(IRQ_MMP2_RTC_MUX, rtc_irq_demux);
+	irq_set_chained_handler(IRQ_MMP2_TWSI_MUX, twsi_irq_demux);
+	irq_set_chained_handler(IRQ_MMP2_MISC_MUX, misc_irq_demux);
+	irq_set_chained_handler(IRQ_MMP2_SSP_MUX, ssp_irq_demux);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/irq-pxa168.c linux-libre-2.6.39-gnu/arch/arm/mach-mmp/irq-pxa168.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/irq-pxa168.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/irq-pxa168.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,8 +48,7 @@
 
 	for (irq = 0; irq < 64; irq++) {
 		icu_mask_irq(irq_get_irq_data(irq));
-		set_irq_chip(irq, &icu_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &icu_irq_chip, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mmp/time.c linux-libre-2.6.39-gnu/arch/arm/mach-mmp/time.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mmp/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mmp/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
  *   2008-04-11: Jason Chagas <Jason.chagas@marvell.com>
  *   2008-10-08: Bin Yang <bin.yang@marvell.com>
  *
- * The timers module actually includes three timers, each timer with upto
+ * The timers module actually includes three timers, each timer with up to
  * three match comparators. Timer #0 is used here in free-running mode as
  * the clock source, and match comparator #1 used as clock event device.
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/acpuclock-arm11.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/acpuclock-arm11.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/acpuclock-arm11.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/acpuclock-arm11.c	2011-05-19 00:06:34.000000000 -0400
@@ -343,7 +343,7 @@
 		}
 	}
 
-	/* Set wait states for CPU inbetween frequency changes */
+	/* Set wait states for CPU between frequency changes */
 	reg_clkctl = readl(A11S_CLK_CNTL_ADDR);
 	reg_clkctl |= (100 << 16); /* set WT_ST_CNT */
 	writel(reg_clkctl, A11S_CLK_CNTL_ADDR);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-halibut.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-halibut.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-halibut.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-halibut.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,8 +93,6 @@
 }
 
 MACHINE_START(HALIBUT, "Halibut Board (QCT SURF7200A)")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
 	.boot_params	= 0x10000100,
 	.fixup		= halibut_fixup,
 	.map_io		= halibut_map_io,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-mahimahi.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-mahimahi.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-mahimahi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-mahimahi.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,8 +74,6 @@
 extern struct sys_timer msm_timer;
 
 MACHINE_START(MAHIMAHI, "mahimahi")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
 	.boot_params	= 0x20000100,
 	.fixup		= mahimahi_fixup,
 	.map_io		= mahimahi_map_io,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm7x27.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm7x27.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm7x27.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm7x27.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,9 +130,7 @@
 }
 
 MACHINE_START(MSM7X27_SURF, "QCT MSM7x27 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -140,9 +138,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X27_FFA, "QCT MSM7x27 FFA")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -150,9 +146,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X25_SURF, "QCT MSM7x25 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
@@ -160,9 +154,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X25_FFA, "QCT MSM7x25 FFA")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 	.map_io		= msm7x2x_map_io,
 	.init_irq	= msm7x2x_init_irq,
 	.init_machine	= msm7x2x_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm7x30.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm7x30.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm7x30.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm7x30.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,19 +23,21 @@
 #include <linux/io.h>
 #include <linux/smsc911x.h>
 #include <linux/usb/msm_hsusb.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
+#include <asm/memory.h>
 #include <asm/setup.h>
 
 #include <mach/gpio.h>
 #include <mach/board.h>
-#include <mach/memory.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
 
 #include <mach/vreg.h>
 #include "devices.h"
+#include "gpiomux.h"
 #include "proc_comm.h"
 
 extern struct sys_timer msm_timer;
@@ -52,6 +54,27 @@
 	.otg_control		= OTG_PHY_CONTROL,
 };
 
+struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
+#ifdef CONFIG_SERIAL_MSM_CONSOLE
+	[49] = { /* UART2 RFR */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+	[50] = { /* UART2 CTS */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+	[51] = { /* UART2 RX */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+	[52] = { /* UART2 TX */
+		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
+			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
+	},
+#endif
+};
+
 static struct platform_device *devices[] __initdata = {
 #if defined(CONFIG_SERIAL_MSM) || defined(CONFIG_MSM_SERIAL_DEBUGGER)
         &msm_device_uart2,
@@ -83,9 +106,7 @@
 }
 
 MACHINE_START(MSM7X30_SURF, "QCT MSM7X30 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -93,9 +114,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
@@ -103,9 +122,7 @@
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = msm7x30_map_io,
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm8960.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm8960.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm8960.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm8960.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,91 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only 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/platform_device.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/clkdev.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/hardware/gic.h>
+
+#include <mach/board.h>
+#include <mach/msm_iomap.h>
+
+#include "devices.h"
+
+static void __init msm8960_map_io(void)
+{
+	msm_map_msm8960_io();
+}
+
+static void __init msm8960_init_irq(void)
+{
+	unsigned int i;
+	gic_init(0, GIC_PPI_START, MSM_QGIC_DIST_BASE,
+		 (void *)MSM_QGIC_CPU_BASE);
+
+	/* Edge trigger PPIs except AVS_SVICINT and AVS_SVICINTSWDONE */
+	writel(0xFFFFD7FF, MSM_QGIC_DIST_BASE + GIC_DIST_CONFIG + 4);
+
+	if (machine_is_msm8960_rumi3())
+		writel(0x0000FFFF, MSM_QGIC_DIST_BASE + GIC_DIST_ENABLE_SET);
+
+	/* FIXME: Not installing AVS_SVICINT and AVS_SVICINTSWDONE yet
+	 * as they are configured as level, which does not play nice with
+	 * handle_percpu_irq.
+	 */
+	for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
+		if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
+			irq_set_handler(i, handle_percpu_irq);
+	}
+}
+
+static struct platform_device *sim_devices[] __initdata = {
+	&msm8960_device_uart_gsbi2,
+};
+
+static struct platform_device *rumi3_devices[] __initdata = {
+	&msm8960_device_uart_gsbi5,
+};
+
+static void __init msm8960_sim_init(void)
+{
+	platform_add_devices(sim_devices, ARRAY_SIZE(sim_devices));
+}
+
+static void __init msm8960_rumi3_init(void)
+{
+	platform_add_devices(rumi3_devices, ARRAY_SIZE(rumi3_devices));
+}
+
+MACHINE_START(MSM8960_SIM, "QCT MSM8960 SIMULATOR")
+	.map_io = msm8960_map_io,
+	.init_irq = msm8960_init_irq,
+	.timer = &msm_timer,
+	.init_machine = msm8960_sim_init,
+MACHINE_END
+
+MACHINE_START(MSM8960_RUMI3, "QCT MSM8960 RUMI3")
+	.map_io = msm8960_map_io,
+	.init_irq = msm8960_init_irq,
+	.timer = &msm_timer,
+	.init_machine = msm8960_rumi3_init,
+MACHINE_END
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm8x60.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm8x60.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-msm8x60.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-msm8x60.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,10 +28,6 @@
 #include <mach/board.h>
 #include <mach/msm_iomap.h>
 
-unsigned long clk_get_max_axi_khz(void)
-{
-	return 0;
-}
 
 static void __init msm8x60_map_io(void)
 {
@@ -60,7 +56,7 @@
 	 */
 	for (i = GIC_PPI_START; i < GIC_SPI_START; i++) {
 		if (i != AVS_SVICINT && i != AVS_SVICINTSWDONE)
-			set_irq_handler(i, handle_percpu_irq);
+			irq_set_handler(i, handle_percpu_irq);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-qsd8x50.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-qsd8x50.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-qsd8x50.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-qsd8x50.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2009, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2009-2011, Code Aurora Forum. 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 and
@@ -21,6 +21,8 @@
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/usb/msm_hsusb.h>
+#include <linux/err.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -31,6 +33,8 @@
 #include <mach/irqs.h>
 #include <mach/sirc.h>
 #include <mach/gpio.h>
+#include <mach/vreg.h>
+#include <mach/mmc.h>
 
 #include "devices.h"
 
@@ -95,6 +99,78 @@
 	&msm_device_hsusb_host,
 };
 
+static struct msm_mmc_gpio sdc1_gpio_cfg[] = {
+	{51, "sdc1_dat_3"},
+	{52, "sdc1_dat_2"},
+	{53, "sdc1_dat_1"},
+	{54, "sdc1_dat_0"},
+	{55, "sdc1_cmd"},
+	{56, "sdc1_clk"}
+};
+
+static struct vreg *vreg_mmc;
+static unsigned long vreg_sts;
+
+static uint32_t msm_sdcc_setup_power(struct device *dv, unsigned int vdd)
+{
+	int rc = 0;
+	struct platform_device *pdev;
+
+	pdev = container_of(dv, struct platform_device, dev);
+
+	if (vdd == 0) {
+		if (!vreg_sts)
+			return 0;
+
+		clear_bit(pdev->id, &vreg_sts);
+
+		if (!vreg_sts) {
+			rc = vreg_disable(vreg_mmc);
+			if (rc)
+				pr_err("vreg_mmc disable failed for slot "
+						"%d: %d\n", pdev->id, rc);
+		}
+		return 0;
+	}
+
+	if (!vreg_sts) {
+		rc = vreg_set_level(vreg_mmc, 2900);
+		if (rc)
+			pr_err("vreg_mmc set level failed for slot %d: %d\n",
+					pdev->id, rc);
+		rc = vreg_enable(vreg_mmc);
+		if (rc)
+			pr_err("vreg_mmc enable failed for slot %d: %d\n",
+					pdev->id, rc);
+	}
+	set_bit(pdev->id, &vreg_sts);
+	return 0;
+}
+
+static struct msm_mmc_gpio_data sdc1_gpio = {
+	.gpio = sdc1_gpio_cfg,
+	.size = ARRAY_SIZE(sdc1_gpio_cfg),
+};
+
+static struct msm_mmc_platform_data qsd8x50_sdc1_data = {
+	.ocr_mask	= MMC_VDD_27_28 | MMC_VDD_28_29,
+	.translate_vdd	= msm_sdcc_setup_power,
+	.gpio_data = &sdc1_gpio,
+};
+
+static void __init qsd8x50_init_mmc(void)
+{
+	vreg_mmc = vreg_get(NULL, "gp5");
+
+	if (IS_ERR(vreg_mmc)) {
+		pr_err("vreg get for vreg_mmc failed (%ld)\n",
+				PTR_ERR(vreg_mmc));
+		return;
+	}
+
+	msm_add_sdcc(1, &qsd8x50_sdc1_data, 0, 0);
+}
+
 static void __init qsd8x50_map_io(void)
 {
 	msm_map_qsd8x50_io();
@@ -113,12 +189,11 @@
 	msm_device_hsusb.dev.parent = &msm_device_otg.dev;
 	msm_device_hsusb_host.dev.parent = &msm_device_otg.dev;
 	platform_add_devices(devices, ARRAY_SIZE(devices));
+	qsd8x50_init_mmc();
 }
 
 MACHINE_START(QSD8X50_SURF, "QCT QSD8X50 SURF")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
@@ -126,9 +201,7 @@
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params = PHYS_OFFSET + 0x100,
+	.boot_params = PLAT_PHYS_OFFSET + 0x100,
 	.map_io = qsd8x50_map_io,
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-sapphire.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-sapphire.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-sapphire.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-sapphire.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,9 +105,7 @@
 
 MACHINE_START(SAPPHIRE, "sapphire")
 /* Maintainer: Brian Swetland <swetland@google.com> */
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
-	.boot_params    = PHYS_OFFSET + 0x100,
+	.boot_params    = PLAT_PHYS_OFFSET + 0x100,
 	.fixup          = sapphire_fixup,
 	.map_io         = sapphire_map_io,
 	.init_irq       = sapphire_init_irq,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-trout.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-trout.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-trout.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-trout.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/clkdev.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -92,8 +93,6 @@
 }
 
 MACHINE_START(TROUT, "HTC Dream")
-#ifdef CONFIG_MSM_DEBUG_UART
-#endif
 	.boot_params	= 0x10000100,
 	.fixup		= trout_fixup,
 	.map_io		= trout_map_io,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-trout-gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-trout-gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-trout-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-trout-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,8 +74,6 @@
 
 static int trout_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
 {
-	struct msm_gpio_chip *msm_gpio = to_msm_gpio_chip(chip);
-
 	return TROUT_GPIO_TO_INT(offset + chip->base);
 }
 
@@ -216,17 +214,17 @@
 {
 	int i;
 	for(i = TROUT_INT_START; i <= TROUT_INT_END; i++) {
-		set_irq_chip(i, &trout_gpio_irq_chip);
-		set_irq_handler(i, handle_edge_irq);
+		irq_set_chip_and_handler(i, &trout_gpio_irq_chip,
+					 handle_edge_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(msm_gpio_banks); i++)
 		gpiochip_add(&msm_gpio_banks[i].chip);
 
-	set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
-	set_irq_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
-	set_irq_wake(MSM_GPIO_TO_INT(17), 1);
+	irq_set_irq_type(MSM_GPIO_TO_INT(17), IRQF_TRIGGER_HIGH);
+	irq_set_chained_handler(MSM_GPIO_TO_INT(17), trout_gpio_irq_handler);
+	irq_set_irq_wake(MSM_GPIO_TO_INT(17), 1);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-trout-mmc.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-trout-mmc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/board-trout-mmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/board-trout-mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -174,7 +174,7 @@
 	if (IS_ERR(vreg_sdslot))
 		return PTR_ERR(vreg_sdslot);
 
-	set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1);
+	irq_set_irq_wake(TROUT_GPIO_TO_INT(TROUT_GPIO_SDMC_CD_N), 1);
 
 	if (!opt_disable_sdcard)
 		msm_add_sdcc(2, &trout_sdslot_data,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-7x30.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-7x30.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-7x30.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-7x30.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_7X30_H
@@ -147,22 +130,26 @@
 extern int internal_pwr_rail_ctl_auto(unsigned rail_id, bool enable);
 
 #define CLK_7X30(clk_name, clk_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = L_7X30_##clk_id, \
-	.remote_id = P_##clk_id, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	.dbg_name = #clk_id, \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &(struct clk){ \
+		.id = L_7X30_##clk_id, \
+		.remote_id = P_##clk_id, \
+		.flags = clk_flags, \
+		.dbg_name = #clk_id, \
+	}, \
 	}
 
 #define CLK_7X30S(clk_name, l_id, r_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = L_7X30_##l_id, \
-	.remote_id = P_##r_id, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	.dbg_name = #l_id, \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &(struct clk){ \
+		.id = L_7X30_##l_id, \
+		.remote_id = P_##r_id, \
+		.flags = clk_flags, \
+		.dbg_name = #l_id, \
+		.ops = &clk_ops_pcom, \
+	}, \
 	}
 
 #endif
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,74 +15,32 @@
  */
 
 #include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
 #include <linux/list.h>
 #include <linux/err.h>
-#include <linux/clk.h>
 #include <linux/spinlock.h>
-#include <linux/debugfs.h>
-#include <linux/ctype.h>
 #include <linux/pm_qos_params.h>
-#include <mach/clk.h>
+#include <linux/mutex.h>
+#include <linux/clk.h>
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/clkdev.h>
 
 #include "clock.h"
-#include "proc_comm.h"
-#include "clock-7x30.h"
 
 static DEFINE_MUTEX(clocks_mutex);
 static DEFINE_SPINLOCK(clocks_lock);
 static LIST_HEAD(clocks);
-struct clk *msm_clocks;
-unsigned msm_num_clocks;
-
-/*
- * Bitmap of enabled clocks, excluding ACPU which is always
- * enabled
- */
-static DECLARE_BITMAP(clock_map_enabled, NR_CLKS);
-static DEFINE_SPINLOCK(clock_map_lock);
 
 /*
  * Standard clock functions defined in include/linux/clk.h
  */
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	struct clk *clk;
-
-	mutex_lock(&clocks_mutex);
-
-	list_for_each_entry(clk, &clocks, list)
-		if (!strcmp(id, clk->name) && clk->dev == dev)
-			goto found_it;
-
-	list_for_each_entry(clk, &clocks, list)
-		if (!strcmp(id, clk->name) && clk->dev == NULL)
-			goto found_it;
-
-	clk = ERR_PTR(-ENOENT);
-found_it:
-	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)
 {
 	unsigned long flags;
 	spin_lock_irqsave(&clocks_lock, flags);
 	clk->count++;
-	if (clk->count == 1) {
+	if (clk->count == 1)
 		clk->ops->enable(clk->id);
-		spin_lock(&clock_map_lock);
-		clock_map_enabled[BIT_WORD(clk->id)] |= BIT_MASK(clk->id);
-		spin_unlock(&clock_map_lock);
-	}
 	spin_unlock_irqrestore(&clocks_lock, flags);
 	return 0;
 }
@@ -94,20 +52,14 @@
 	spin_lock_irqsave(&clocks_lock, flags);
 	BUG_ON(clk->count == 0);
 	clk->count--;
-	if (clk->count == 0) {
+	if (clk->count == 0)
 		clk->ops->disable(clk->id);
-		spin_lock(&clock_map_lock);
-		clock_map_enabled[BIT_WORD(clk->id)] &= ~BIT_MASK(clk->id);
-		spin_unlock(&clock_map_lock);
-	}
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
 int clk_reset(struct clk *clk, enum clk_reset_action action)
 {
-	if (!clk->ops->reset)
-		clk->ops->reset = &pc_clk_reset;
 	return clk->ops->reset(clk->remote_id, action);
 }
 EXPORT_SYMBOL(clk_reset);
@@ -184,25 +136,14 @@
  */
 static struct clk *ebi1_clk;
 
-static void __init set_clock_ops(struct clk *clk)
-{
-	if (!clk->ops) {
-		clk->ops = &clk_ops_pcom;
-		clk->id = clk->remote_id;
-	}
-}
-
-void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks)
+void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks)
 {
 	unsigned n;
 
-	spin_lock_init(&clocks_lock);
 	mutex_lock(&clocks_mutex);
-	msm_clocks = clock_tbl;
-	msm_num_clocks = num_clocks;
-	for (n = 0; n < msm_num_clocks; n++) {
-		set_clock_ops(&msm_clocks[n]);
-		list_add_tail(&msm_clocks[n].list, &clocks);
+	for (n = 0; n < num_clocks; n++) {
+		clkdev_add(&clock_tbl[n]);
+		list_add_tail(&clock_tbl[n].clk->list, &clocks);
 	}
 	mutex_unlock(&clocks_mutex);
 
@@ -211,115 +152,6 @@
 
 }
 
-#if defined(CONFIG_DEBUG_FS)
-static struct clk *msm_clock_get_nth(unsigned index)
-{
-	if (index < msm_num_clocks)
-		return msm_clocks + index;
-	else
-		return 0;
-}
-
-static int clock_debug_rate_set(void *data, u64 val)
-{
-	struct clk *clock = data;
-	int ret;
-
-	/* Only increases to max rate will succeed, but that's actually good
-	 * for debugging purposes. So we don't check for error. */
-	if (clock->flags & CLK_MAX)
-		clk_set_max_rate(clock, val);
-	if (clock->flags & CLK_MIN)
-		ret = clk_set_min_rate(clock, val);
-	else
-		ret = clk_set_rate(clock, val);
-	if (ret != 0)
-		printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
-			(clock->flags & CLK_MIN) ? "_min" : "", ret);
-	return ret;
-}
-
-static int clock_debug_rate_get(void *data, u64 *val)
-{
-	struct clk *clock = data;
-	*val = clk_get_rate(clock);
-	return 0;
-}
-
-static int clock_debug_enable_set(void *data, u64 val)
-{
-	struct clk *clock = data;
-	int rc = 0;
-
-	if (val)
-		rc = clock->ops->enable(clock->id);
-	else
-		clock->ops->disable(clock->id);
-
-	return rc;
-}
-
-static int clock_debug_enable_get(void *data, u64 *val)
-{
-	struct clk *clock = data;
-
-	*val = clock->ops->is_enabled(clock->id);
-
-	return 0;
-}
-
-static int clock_debug_local_get(void *data, u64 *val)
-{
-	struct clk *clock = data;
-
-	*val = clock->ops != &clk_ops_pcom;
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
-			clock_debug_rate_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
-			clock_debug_enable_set, "%llu\n");
-DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
-			NULL, "%llu\n");
-
-static int __init clock_debug_init(void)
-{
-	struct dentry *dent_rate, *dent_enable, *dent_local;
-	struct clk *clock;
-	unsigned n = 0;
-	char temp[50], *ptr;
-
-	dent_rate = debugfs_create_dir("clk_rate", 0);
-	if (IS_ERR(dent_rate))
-		return PTR_ERR(dent_rate);
-
-	dent_enable = debugfs_create_dir("clk_enable", 0);
-	if (IS_ERR(dent_enable))
-		return PTR_ERR(dent_enable);
-
-	dent_local = debugfs_create_dir("clk_local", NULL);
-	if (IS_ERR(dent_local))
-		return PTR_ERR(dent_local);
-
-	while ((clock = msm_clock_get_nth(n++)) != 0) {
-		strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
-		for (ptr = temp; *ptr; ptr++)
-			*ptr = tolower(*ptr);
-		debugfs_create_file(temp, 0644, dent_rate,
-				    clock, &clock_rate_fops);
-		debugfs_create_file(temp, 0644, dent_enable,
-				    clock, &clock_enable_fops);
-		debugfs_create_file(temp, S_IRUGO, dent_local,
-				    clock, &clock_local_fops);
-	}
-	return 0;
-}
-
-device_initcall(clock_debug_init);
-#endif
-
 /* The bootloader and/or AMSS may have left various clocks enabled.
  * Disable any clocks that belong to us (CLKFLAG_AUTO_OFF) but have
  * not been explicitly enabled by a clk_enable() call.
@@ -330,8 +162,10 @@
 	struct clk *clk;
 	unsigned count = 0;
 
+	clock_debug_init();
 	mutex_lock(&clocks_mutex);
 	list_for_each_entry(clk, &clocks, list) {
+		clock_debug_add(clk);
 		if (clk->flags & CLKFLAG_AUTO_OFF) {
 			spin_lock_irqsave(&clocks_lock, flags);
 			if (!clk->count) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-debug.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-debug.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-debug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2007-2010, Code Aurora Forum. All rights reserved.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/module.h>
+#include <linux/ctype.h>
+#include <linux/debugfs.h>
+#include <linux/clk.h>
+#include "clock.h"
+
+static int clock_debug_rate_set(void *data, u64 val)
+{
+	struct clk *clock = data;
+	int ret;
+
+	/* Only increases to max rate will succeed, but that's actually good
+	 * for debugging purposes so we don't check for error. */
+	if (clock->flags & CLK_MAX)
+		clk_set_max_rate(clock, val);
+	if (clock->flags & CLK_MIN)
+		ret = clk_set_min_rate(clock, val);
+	else
+		ret = clk_set_rate(clock, val);
+	if (ret != 0)
+		printk(KERN_ERR "clk_set%s_rate failed (%d)\n",
+			(clock->flags & CLK_MIN) ? "_min" : "", ret);
+	return ret;
+}
+
+static int clock_debug_rate_get(void *data, u64 *val)
+{
+	struct clk *clock = data;
+	*val = clk_get_rate(clock);
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_rate_fops, clock_debug_rate_get,
+			clock_debug_rate_set, "%llu\n");
+
+static int clock_debug_enable_set(void *data, u64 val)
+{
+	struct clk *clock = data;
+	int rc = 0;
+
+	if (val)
+		rc = clock->ops->enable(clock->id);
+	else
+		clock->ops->disable(clock->id);
+
+	return rc;
+}
+
+static int clock_debug_enable_get(void *data, u64 *val)
+{
+	struct clk *clock = data;
+
+	*val = clock->ops->is_enabled(clock->id);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_enable_fops, clock_debug_enable_get,
+			clock_debug_enable_set, "%llu\n");
+
+static int clock_debug_local_get(void *data, u64 *val)
+{
+	struct clk *clock = data;
+
+	*val = clock->ops->is_local(clock->id);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(clock_local_fops, clock_debug_local_get,
+			NULL, "%llu\n");
+
+static struct dentry *debugfs_base;
+
+int __init clock_debug_init(void)
+{
+	debugfs_base = debugfs_create_dir("clk", NULL);
+	if (!debugfs_base)
+		return -ENOMEM;
+	return 0;
+}
+
+int __init clock_debug_add(struct clk *clock)
+{
+	char temp[50], *ptr;
+	struct dentry *clk_dir;
+
+	if (!debugfs_base)
+		return -ENOMEM;
+
+	strncpy(temp, clock->dbg_name, ARRAY_SIZE(temp)-1);
+	for (ptr = temp; *ptr; ptr++)
+		*ptr = tolower(*ptr);
+
+	clk_dir = debugfs_create_dir(temp, debugfs_base);
+	if (!clk_dir)
+		return -ENOMEM;
+
+	if (!debugfs_create_file("rate", S_IRUGO | S_IWUSR, clk_dir,
+				clock, &clock_rate_fops))
+		goto error;
+
+	if (!debugfs_create_file("enable", S_IRUGO | S_IWUSR, clk_dir,
+				clock, &clock_enable_fops))
+		goto error;
+
+	if (!debugfs_create_file("is_local", S_IRUGO, clk_dir, clock,
+				&clock_local_fops))
+		goto error;
+	return 0;
+error:
+	debugfs_remove_recursive(clk_dir);
+	return -ENOMEM;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-dummy.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-dummy.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-dummy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-dummy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,54 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 and
- * only 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/clk.h>
-#include <linux/err.h>
-#include <linux/module.h>
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	return ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(clk_get);
-
-int clk_enable(struct clk *clk)
-{
-	return -ENOENT;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_get_rate);
-
-int clk_set_rate(struct clk *clk, unsigned long rate)
-{
-	return -ENOENT;
-}
-EXPORT_SYMBOL(clk_set_rate);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,12 +17,10 @@
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_H
 #define __ARCH_ARM_MACH_MSM_CLOCK_H
 
+#include <linux/init.h>
 #include <linux/list.h>
 #include <mach/clk.h>
 
-#include "clock-pcom.h"
-#include "clock-7x30.h"
-
 #define CLKFLAG_INVERT			0x00000001
 #define CLKFLAG_NOINVERT		0x00000002
 #define CLKFLAG_NONEST			0x00000004
@@ -45,6 +43,7 @@
 	unsigned (*get_rate)(unsigned id);
 	unsigned (*is_enabled)(unsigned id);
 	long (*round_rate)(unsigned id, unsigned rate);
+	bool (*is_local)(unsigned id);
 };
 
 struct clk {
@@ -52,58 +51,22 @@
 	uint32_t remote_id;
 	uint32_t count;
 	uint32_t flags;
-	const char *name;
 	struct clk_ops *ops;
 	const char *dbg_name;
 	struct list_head list;
-	struct device *dev;
 };
 
-#define A11S_CLK_CNTL_ADDR		(MSM_CSR_BASE + 0x100)
-#define A11S_CLK_SEL_ADDR		(MSM_CSR_BASE + 0x104)
-#define A11S_VDD_SVS_PLEVEL_ADDR	(MSM_CSR_BASE + 0x124)
-
-#ifdef CONFIG_DEBUG_FS
-#define CLOCK_DBG_NAME(x) .dbg_name = x,
-#else
-#define CLOCK_DBG_NAME(x)
-#endif
-
-#define CLOCK(clk_name, clk_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = clk_id, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	 CLOCK_DBG_NAME(#clk_id) \
-	}
-
 #define OFF CLKFLAG_AUTO_OFF
 #define CLK_MIN CLKFLAG_MIN
 #define CLK_MAX CLKFLAG_MAX
 #define CLK_MINMAX (CLK_MIN | CLK_MAX)
-#define NR_CLKS	P_NR_CLKS
-
-enum {
-	PLL_0 = 0,
-	PLL_1,
-	PLL_2,
-	PLL_3,
-	PLL_4,
-	PLL_5,
-	PLL_6,
-	NUM_PLL
-};
-
-enum clkvote_client {
-	CLKVOTE_ACPUCLK = 0,
-	CLKVOTE_PMQOS,
-	CLKVOTE_MAX,
-};
-
-int msm_clock_require_tcxo(unsigned long *reason, int nbits);
-int msm_clock_get_name(uint32_t id, char *name, uint32_t size);
-int ebi1_clk_set_min_rate(enum clkvote_client client, unsigned long rate);
-unsigned long clk_get_max_axi_khz(void);
 
+#ifdef CONFIG_DEBUG_FS
+int __init clock_debug_init(void);
+int __init clock_debug_add(struct clk *clock);
+#else
+static inline int __init clock_debug_init(void) { return 0; }
+static inline int __init clock_debug_add(struct clk *clock) { return 0; }
 #endif
 
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-pcom.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-pcom.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-pcom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-pcom.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 
 #include "proc_comm.h"
 #include "clock.h"
+#include "clock-pcom.h"
 
 /*
  * glue for the proc_comm interface
@@ -116,6 +117,11 @@
 	return rate;
 }
 
+static bool pc_clk_is_local(unsigned id)
+{
+	return false;
+}
+
 struct clk_ops clk_ops_pcom = {
 	.enable = pc_clk_enable,
 	.disable = pc_clk_disable,
@@ -128,4 +134,5 @@
 	.get_rate = pc_clk_get_rate,
 	.is_enabled = pc_clk_is_enabled,
 	.round_rate = pc_clk_round_rate,
+	.is_local = pc_clk_is_local,
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-pcom.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-pcom.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/clock-pcom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/clock-pcom.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 
 #ifndef __ARCH_ARM_MACH_MSM_CLOCK_PCOM_H
@@ -132,8 +115,10 @@
 #define P_CSI1_P_CLK		97
 #define P_GSBI_CLK		98
 #define P_GSBI_P_CLK		99
+#define P_CE_CLK		100 /* Crypto engine */
+#define P_CODEC_SSBI_CLK	101
 
-#define P_NR_CLKS		100
+#define P_NR_CLKS		102
 
 struct clk_ops;
 extern struct clk_ops clk_ops_pcom;
@@ -141,13 +126,15 @@
 int pc_clk_reset(unsigned id, enum clk_reset_action action);
 
 #define CLK_PCOM(clk_name, clk_id, clk_dev, clk_flags) {	\
-	.name = clk_name, \
-	.id = P_##clk_id, \
-	.remote_id = P_##clk_id, \
-	.ops = &clk_ops_pcom, \
-	.flags = clk_flags, \
-	.dev = clk_dev, \
-	.dbg_name = #clk_id, \
+	.con_id = clk_name, \
+	.dev_id = clk_dev, \
+	.clk = &(struct clk){ \
+		.id = P_##clk_id, \
+		.remote_id = P_##clk_id, \
+		.ops = &clk_ops_pcom, \
+		.flags = clk_flags, \
+		.dbg_name = #clk_id, \
+	}, \
 	}
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,12 +16,17 @@
 #ifndef __ARCH_ARM_MACH_MSM_DEVICES_H
 #define __ARCH_ARM_MACH_MSM_DEVICES_H
 
+#include <linux/clkdev.h>
+
 #include "clock.h"
 
 extern struct platform_device msm_device_uart1;
 extern struct platform_device msm_device_uart2;
 extern struct platform_device msm_device_uart3;
 
+extern struct platform_device msm8960_device_uart_gsbi2;
+extern struct platform_device msm8960_device_uart_gsbi5;
+
 extern struct platform_device msm_device_sdc1;
 extern struct platform_device msm_device_sdc2;
 extern struct platform_device msm_device_sdc3;
@@ -41,13 +46,13 @@
 extern struct platform_device msm_device_mddi1;
 extern struct platform_device msm_device_mdp;
 
-extern struct clk msm_clocks_7x01a[];
+extern struct clk_lookup msm_clocks_7x01a[];
 extern unsigned msm_num_clocks_7x01a;
 
-extern struct clk msm_clocks_7x30[];
+extern struct clk_lookup msm_clocks_7x30[];
 extern unsigned msm_num_clocks_7x30;
 
-extern struct clk msm_clocks_8x50[];
+extern struct clk_lookup msm_clocks_8x50[];
 extern unsigned msm_num_clocks_8x50;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-iommu.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-iommu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-iommu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-iommu.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,911 @@
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
+ * only 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/platform_device.h>
+#include <linux/bootmem.h>
+#include <mach/irqs.h>
+#include <mach/iommu.h>
+
+static struct resource msm_iommu_jpegd_resources[] = {
+	{
+		.start = 0x07300000,
+		.end   = 0x07300000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+		.end   = SMMU_JPEGD_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vpe_resources[] = {
+	{
+		.start = 0x07400000,
+		.end   = 0x07400000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VPE_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VPE_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_mdp0_resources[] = {
+	{
+		.start = 0x07500000,
+		.end   = 0x07500000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_MDP0_CB_SC_SECURE_IRQ,
+		.end   = SMMU_MDP0_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_mdp1_resources[] = {
+	{
+		.start = 0x07600000,
+		.end   = 0x07600000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_MDP1_CB_SC_SECURE_IRQ,
+		.end   = SMMU_MDP1_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_rot_resources[] = {
+	{
+		.start = 0x07700000,
+		.end   = 0x07700000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_ROT_CB_SC_SECURE_IRQ,
+		.end   = SMMU_ROT_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_ijpeg_resources[] = {
+	{
+		.start = 0x07800000,
+		.end   = 0x07800000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+		.end   = SMMU_IJPEG_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vfe_resources[] = {
+	{
+		.start = 0x07900000,
+		.end   = 0x07900000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VFE_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VFE_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vcodec_a_resources[] = {
+	{
+		.start = 0x07A00000,
+		.end   = 0x07A00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_vcodec_b_resources[] = {
+	{
+		.start = 0x07B00000,
+		.end   = 0x07B00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+		.end   = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_gfx3d_resources[] = {
+	{
+		.start = 0x07C00000,
+		.end   = 0x07C00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX3D_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_gfx2d0_resources[] = {
+	{
+		.start = 0x07D00000,
+		.end   = 0x07D00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msm_iommu_gfx2d1_resources[] = {
+	{
+		.start = 0x07E00000,
+		.end   = 0x07E00000 + SZ_1M - 1,
+		.name  = "physbase",
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.name = "nonsecure_irq",
+		.start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
+		.end   = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.name = "secure_irq",
+		.start = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
+		.end   = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device msm_root_iommu_dev = {
+	.name = "msm_iommu",
+	.id = -1,
+};
+
+static struct msm_iommu_dev jpegd_iommu = {
+	.name = "jpegd",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vpe_iommu = {
+	.name = "vpe",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev mdp0_iommu = {
+	.name = "mdp0",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev mdp1_iommu = {
+	.name = "mdp1",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev rot_iommu = {
+	.name = "rot",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev ijpeg_iommu = {
+	.name = "ijpeg",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vfe_iommu = {
+	.name = "vfe",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vcodec_a_iommu = {
+	.name = "vcodec_a",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev vcodec_b_iommu = {
+	.name = "vcodec_b",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev gfx3d_iommu = {
+	.name = "gfx3d",
+	.ncb = 3,
+};
+
+static struct msm_iommu_dev gfx2d0_iommu = {
+	.name = "gfx2d0",
+	.ncb = 2,
+};
+
+static struct msm_iommu_dev gfx2d1_iommu = {
+	.name = "gfx2d1",
+	.ncb = 2,
+};
+
+static struct platform_device msm_device_iommu_jpegd = {
+	.name = "msm_iommu",
+	.id = 0,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
+	.resource = msm_iommu_jpegd_resources,
+};
+
+static struct platform_device msm_device_iommu_vpe = {
+	.name = "msm_iommu",
+	.id = 1,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
+	.resource = msm_iommu_vpe_resources,
+};
+
+static struct platform_device msm_device_iommu_mdp0 = {
+	.name = "msm_iommu",
+	.id = 2,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
+	.resource = msm_iommu_mdp0_resources,
+};
+
+static struct platform_device msm_device_iommu_mdp1 = {
+	.name = "msm_iommu",
+	.id = 3,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
+	.resource = msm_iommu_mdp1_resources,
+};
+
+static struct platform_device msm_device_iommu_rot = {
+	.name = "msm_iommu",
+	.id = 4,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
+	.resource = msm_iommu_rot_resources,
+};
+
+static struct platform_device msm_device_iommu_ijpeg = {
+	.name = "msm_iommu",
+	.id = 5,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
+	.resource = msm_iommu_ijpeg_resources,
+};
+
+static struct platform_device msm_device_iommu_vfe = {
+	.name = "msm_iommu",
+	.id = 6,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
+	.resource = msm_iommu_vfe_resources,
+};
+
+static struct platform_device msm_device_iommu_vcodec_a = {
+	.name = "msm_iommu",
+	.id = 7,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
+	.resource = msm_iommu_vcodec_a_resources,
+};
+
+static struct platform_device msm_device_iommu_vcodec_b = {
+	.name = "msm_iommu",
+	.id = 8,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
+	.resource = msm_iommu_vcodec_b_resources,
+};
+
+static struct platform_device msm_device_iommu_gfx3d = {
+	.name = "msm_iommu",
+	.id = 9,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
+	.resource = msm_iommu_gfx3d_resources,
+};
+
+static struct platform_device msm_device_iommu_gfx2d0 = {
+	.name = "msm_iommu",
+	.id = 10,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
+	.resource = msm_iommu_gfx2d0_resources,
+};
+
+struct platform_device msm_device_iommu_gfx2d1 = {
+	.name = "msm_iommu",
+	.id = 11,
+	.dev = {
+		.parent = &msm_root_iommu_dev.dev,
+	},
+	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
+	.resource = msm_iommu_gfx2d1_resources,
+};
+
+static struct msm_iommu_ctx_dev jpegd_src_ctx = {
+	.name = "jpegd_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
+	.name = "jpegd_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_src_ctx = {
+	.name = "vpe_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev vpe_dst_ctx = {
+	.name = "vpe_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
+	.name = "mdp_vg1",
+	.num = 0,
+	.mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
+	.name = "mdp_rgb1",
+	.num = 1,
+	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
+	.name = "mdp_vg2",
+	.num = 0,
+	.mids = {0, 2, -1}
+};
+
+static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
+	.name = "mdp_rgb2",
+	.num = 1,
+	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_src_ctx = {
+	.name = "rot_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev rot_dst_ctx = {
+	.name = "rot_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
+	.name = "ijpeg_src",
+	.num = 0,
+	.mids = {0, -1}
+};
+
+static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
+	.name = "ijpeg_dst",
+	.num = 1,
+	.mids = {1, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
+	.name = "vfe_imgwr",
+	.num = 0,
+	.mids = {2, 3, 4, 5, 6, 7, 8, -1}
+};
+
+static struct msm_iommu_ctx_dev vfe_misc_ctx = {
+	.name = "vfe_misc",
+	.num = 1,
+	.mids = {0, 1, 9, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
+	.name = "vcodec_a_stream",
+	.num = 0,
+	.mids = {2, 5, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
+	.name = "vcodec_a_mm1",
+	.num = 1,
+	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
+	.name = "vcodec_b_mm2",
+	.num = 0,
+	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_user_ctx = {
+	.name = "gfx3d_user",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx3d_priv_ctx = {
+	.name = "gfx3d_priv",
+	.num = 1,
+	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
+		 31, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
+	.name = "gfx2d0_2d0",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
+	.name = "gfx2d1_2d1",
+	.num = 0,
+	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
+};
+
+static struct platform_device msm_device_jpegd_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 0,
+	.dev = {
+		.parent = &msm_device_iommu_jpegd.dev,
+	},
+};
+
+static struct platform_device msm_device_jpegd_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 1,
+	.dev = {
+		.parent = &msm_device_iommu_jpegd.dev,
+	},
+};
+
+static struct platform_device msm_device_vpe_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 2,
+	.dev = {
+		.parent = &msm_device_iommu_vpe.dev,
+	},
+};
+
+static struct platform_device msm_device_vpe_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 3,
+	.dev = {
+		.parent = &msm_device_iommu_vpe.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_vg1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 4,
+	.dev = {
+		.parent = &msm_device_iommu_mdp0.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_rgb1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 5,
+	.dev = {
+		.parent = &msm_device_iommu_mdp0.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_vg2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 6,
+	.dev = {
+		.parent = &msm_device_iommu_mdp1.dev,
+	},
+};
+
+static struct platform_device msm_device_mdp_rgb2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 7,
+	.dev = {
+		.parent = &msm_device_iommu_mdp1.dev,
+	},
+};
+
+static struct platform_device msm_device_rot_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 8,
+	.dev = {
+		.parent = &msm_device_iommu_rot.dev,
+	},
+};
+
+static struct platform_device msm_device_rot_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 9,
+	.dev = {
+		.parent = &msm_device_iommu_rot.dev,
+	},
+};
+
+static struct platform_device msm_device_ijpeg_src_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 10,
+	.dev = {
+		.parent = &msm_device_iommu_ijpeg.dev,
+	},
+};
+
+static struct platform_device msm_device_ijpeg_dst_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 11,
+	.dev = {
+		.parent = &msm_device_iommu_ijpeg.dev,
+	},
+};
+
+static struct platform_device msm_device_vfe_imgwr_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 12,
+	.dev = {
+		.parent = &msm_device_iommu_vfe.dev,
+	},
+};
+
+static struct platform_device msm_device_vfe_misc_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 13,
+	.dev = {
+		.parent = &msm_device_iommu_vfe.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_a_stream_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 14,
+	.dev = {
+		.parent = &msm_device_iommu_vcodec_a.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_a_mm1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 15,
+	.dev = {
+		.parent = &msm_device_iommu_vcodec_a.dev,
+	},
+};
+
+static struct platform_device msm_device_vcodec_b_mm2_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 16,
+	.dev = {
+		.parent = &msm_device_iommu_vcodec_b.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_user_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 17,
+	.dev = {
+		.parent = &msm_device_iommu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx3d_priv_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 18,
+	.dev = {
+		.parent = &msm_device_iommu_gfx3d.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx2d0_2d0_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 19,
+	.dev = {
+		.parent = &msm_device_iommu_gfx2d0.dev,
+	},
+};
+
+static struct platform_device msm_device_gfx2d1_2d1_ctx = {
+	.name = "msm_iommu_ctx",
+	.id = 20,
+	.dev = {
+		.parent = &msm_device_iommu_gfx2d1.dev,
+	},
+};
+
+static struct platform_device *msm_iommu_devs[] = {
+	&msm_device_iommu_jpegd,
+	&msm_device_iommu_vpe,
+	&msm_device_iommu_mdp0,
+	&msm_device_iommu_mdp1,
+	&msm_device_iommu_rot,
+	&msm_device_iommu_ijpeg,
+	&msm_device_iommu_vfe,
+	&msm_device_iommu_vcodec_a,
+	&msm_device_iommu_vcodec_b,
+	&msm_device_iommu_gfx3d,
+	&msm_device_iommu_gfx2d0,
+	&msm_device_iommu_gfx2d1,
+};
+
+static struct msm_iommu_dev *msm_iommu_data[] = {
+	&jpegd_iommu,
+	&vpe_iommu,
+	&mdp0_iommu,
+	&mdp1_iommu,
+	&rot_iommu,
+	&ijpeg_iommu,
+	&vfe_iommu,
+	&vcodec_a_iommu,
+	&vcodec_b_iommu,
+	&gfx3d_iommu,
+	&gfx2d0_iommu,
+	&gfx2d1_iommu,
+};
+
+static struct platform_device *msm_iommu_ctx_devs[] = {
+	&msm_device_jpegd_src_ctx,
+	&msm_device_jpegd_dst_ctx,
+	&msm_device_vpe_src_ctx,
+	&msm_device_vpe_dst_ctx,
+	&msm_device_mdp_vg1_ctx,
+	&msm_device_mdp_rgb1_ctx,
+	&msm_device_mdp_vg2_ctx,
+	&msm_device_mdp_rgb2_ctx,
+	&msm_device_rot_src_ctx,
+	&msm_device_rot_dst_ctx,
+	&msm_device_ijpeg_src_ctx,
+	&msm_device_ijpeg_dst_ctx,
+	&msm_device_vfe_imgwr_ctx,
+	&msm_device_vfe_misc_ctx,
+	&msm_device_vcodec_a_stream_ctx,
+	&msm_device_vcodec_a_mm1_ctx,
+	&msm_device_vcodec_b_mm2_ctx,
+	&msm_device_gfx3d_user_ctx,
+	&msm_device_gfx3d_priv_ctx,
+	&msm_device_gfx2d0_2d0_ctx,
+	&msm_device_gfx2d1_2d1_ctx,
+};
+
+static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
+	&jpegd_src_ctx,
+	&jpegd_dst_ctx,
+	&vpe_src_ctx,
+	&vpe_dst_ctx,
+	&mdp_vg1_ctx,
+	&mdp_rgb1_ctx,
+	&mdp_vg2_ctx,
+	&mdp_rgb2_ctx,
+	&rot_src_ctx,
+	&rot_dst_ctx,
+	&ijpeg_src_ctx,
+	&ijpeg_dst_ctx,
+	&vfe_imgwr_ctx,
+	&vfe_misc_ctx,
+	&vcodec_a_stream_ctx,
+	&vcodec_a_mm1_ctx,
+	&vcodec_b_mm2_ctx,
+	&gfx3d_user_ctx,
+	&gfx3d_priv_ctx,
+	&gfx2d0_2d0_ctx,
+	&gfx2d1_2d1_ctx,
+};
+
+static int __init msm8x60_iommu_init(void)
+{
+	int ret, i;
+
+	ret = platform_device_register(&msm_root_iommu_dev);
+	if (ret != 0) {
+		pr_err("Failed to register root IOMMU device!\n");
+		goto failure;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
+		ret = platform_device_add_data(msm_iommu_devs[i],
+					       msm_iommu_data[i],
+					       sizeof(struct msm_iommu_dev));
+		if (ret != 0) {
+			pr_err("platform_device_add_data failed, "
+			       "i = %d\n", i);
+			goto failure_unwind;
+		}
+
+		ret = platform_device_register(msm_iommu_devs[i]);
+
+		if (ret != 0) {
+			pr_err("platform_device_register iommu failed, "
+			       "i = %d\n", i);
+			goto failure_unwind;
+		}
+	}
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
+		ret = platform_device_add_data(msm_iommu_ctx_devs[i],
+					       msm_iommu_ctx_data[i],
+					       sizeof(*msm_iommu_ctx_devs[i]));
+		if (ret != 0) {
+			pr_err("platform_device_add_data iommu failed, "
+			       "i = %d\n", i);
+			goto failure_unwind2;
+		}
+
+		ret = platform_device_register(msm_iommu_ctx_devs[i]);
+		if (ret != 0) {
+			pr_err("platform_device_register ctx failed, "
+			       "i = %d\n", i);
+			goto failure_unwind2;
+		}
+	}
+	return 0;
+
+failure_unwind2:
+	while (--i >= 0)
+		platform_device_unregister(msm_iommu_ctx_devs[i]);
+failure_unwind:
+	while (--i >= 0)
+		platform_device_unregister(msm_iommu_devs[i]);
+
+	platform_device_unregister(&msm_root_iommu_dev);
+failure:
+	return ret;
+}
+
+static void __exit msm8x60_iommu_exit(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
+		platform_device_unregister(msm_iommu_ctx_devs[i]);
+
+	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
+		platform_device_unregister(msm_iommu_devs[i]);
+
+	platform_device_unregister(&msm_root_iommu_dev);
+}
+
+subsys_initcall(msm8x60_iommu_init);
+module_exit(msm8x60_iommu_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm7x00.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm7x00.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm7x00.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm7x00.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
+#include <linux/clkdev.h>
 
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
@@ -24,8 +25,8 @@
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
 
-
 #include "clock.h"
+#include "clock-pcom.h"
 #include <mach/mmc.h>
 
 static struct resource resources_uart1[] = {
@@ -38,6 +39,7 @@
 		.start	= MSM_UART1_PHYS,
 		.end	= MSM_UART1_PHYS + MSM_UART1_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -51,6 +53,7 @@
 		.start	= MSM_UART2_PHYS,
 		.end	= MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -64,6 +67,7 @@
 		.start	= MSM_UART3_PHYS,
 		.end	= MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -414,7 +418,7 @@
 	.resource = resources_mdp,
 };
 
-struct clk msm_clocks_7x01a[] = {
+struct clk_lookup msm_clocks_7x01a[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, 0),
@@ -423,7 +427,7 @@
 	CLK_PCOM("emdh_clk",	EMDH_CLK,	NULL, OFF),
 	CLK_PCOM("gp_clk",		GP_CLK,		NULL, 0),
 	CLK_PCOM("grp_clk",	GRP_3D_CLK,	NULL, OFF),
-	CLK_PCOM("i2c_clk",	I2C_CLK,	&msm_device_i2c.dev, 0),
+	CLK_PCOM("i2c_clk",	I2C_CLK,	"msm_i2c.0", 0),
 	CLK_PCOM("icodec_rx_clk",	ICODEC_RX_CLK,	NULL, 0),
 	CLK_PCOM("icodec_tx_clk",	ICODEC_TX_CLK,	NULL, 0),
 	CLK_PCOM("imem_clk",	IMEM_CLK,	NULL, OFF),
@@ -433,25 +437,25 @@
 	CLK_PCOM("pcm_clk",	PCM_CLK,	NULL, 0),
 	CLK_PCOM("mddi_clk",	PMDH_CLK,	NULL, OFF | CLK_MINMAX),
 	CLK_PCOM("sdac_clk",	SDAC_CLK,	NULL, OFF),
-	CLK_PCOM("sdc_clk",	SDC1_CLK,	&msm_device_sdc1.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	&msm_device_sdc1.dev, OFF),
-	CLK_PCOM("sdc_clk",	SDC2_CLK,	&msm_device_sdc2.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC2_P_CLK,	&msm_device_sdc2.dev, OFF),
-	CLK_PCOM("sdc_clk",	SDC3_CLK,	&msm_device_sdc3.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC3_P_CLK,	&msm_device_sdc3.dev, OFF),
-	CLK_PCOM("sdc_clk",	SDC4_CLK,	&msm_device_sdc4.dev, OFF),
-	CLK_PCOM("sdc_pclk",	SDC4_P_CLK,	&msm_device_sdc4.dev, OFF),
+	CLK_PCOM("sdc_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_pclk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_clk",	SDC3_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_pclk",	SDC3_P_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_clk",	SDC4_CLK,	"msm_sdcc.4", OFF),
+	CLK_PCOM("sdc_pclk",	SDC4_P_CLK,	"msm_sdcc.4", OFF),
 	CLK_PCOM("tsif_clk",	TSIF_CLK,	NULL, 0),
 	CLK_PCOM("tsif_ref_clk",	TSIF_REF_CLK,	NULL, 0),
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
-	CLK_PCOM("uart_clk",	UART1_CLK,	&msm_device_uart1.dev, OFF),
-	CLK_PCOM("uart_clk",	UART2_CLK,	&msm_device_uart2.dev, 0),
-	CLK_PCOM("uart_clk",	UART3_CLK,	&msm_device_uart3.dev, OFF),
+	CLK_PCOM("uart_clk",	UART1_CLK,	"msm_serial.0", OFF),
+	CLK_PCOM("uart_clk",	UART2_CLK,	"msm_serial.1", 0),
+	CLK_PCOM("uart_clk",	UART3_CLK,	"msm_serial.2", OFF),
 	CLK_PCOM("uart1dm_clk",	UART1DM_CLK,	NULL, OFF),
 	CLK_PCOM("uart2dm_clk",	UART2DM_CLK,	NULL, 0),
-	CLK_PCOM("usb_hs_clk",	USB_HS_CLK,	&msm_device_hsusb.dev, OFF),
-	CLK_PCOM("usb_hs_pclk",	USB_HS_P_CLK,	&msm_device_hsusb.dev, OFF),
+	CLK_PCOM("usb_hs_clk",	USB_HS_CLK,	"msm_hsusb", OFF),
+	CLK_PCOM("usb_hs_pclk",	USB_HS_P_CLK,	"msm_hsusb", OFF),
 	CLK_PCOM("usb_otg_clk",	USB_OTG_CLK,	NULL, 0),
 	CLK_PCOM("vdc_clk",	VDC_CLK,	NULL, OFF ),
 	CLK_PCOM("vfe_clk",	VFE_CLK,	NULL, OFF),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm7x30.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm7x30.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm7x30.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm7x30.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 
 #include <linux/dma-mapping.h>
+#include <linux/clkdev.h>
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
@@ -28,6 +29,7 @@
 #include <asm/mach/flash.h>
 
 #include "clock-pcom.h"
+#include "clock-7x30.h"
 
 #include <mach/mmc.h>
 
@@ -41,6 +43,7 @@
 		.start	= MSM_UART2_PHYS,
 		.end	= MSM_UART2_PHYS + MSM_UART2_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -127,11 +130,13 @@
 	},
 };
 
-struct clk msm_clocks_7x30[] = {
+struct clk_lookup msm_clocks_7x30[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
 	CLK_PCOM("adsp_clk",	ADSP_CLK,	NULL, 0),
 	CLK_PCOM("cam_m_clk",	CAM_M_CLK,	NULL, 0),
 	CLK_PCOM("camif_pad_pclk",	CAMIF_PAD_P_CLK,	NULL, OFF),
+	CLK_PCOM("ce_clk",	CE_CLK,	NULL, 0),
+	CLK_PCOM("codec_ssbi_clk",	CODEC_SSBI_CLK,	NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, CLK_MIN),
 	CLK_PCOM("ecodec_clk",	ECODEC_CLK,	NULL, 0),
 	CLK_PCOM("emdh_clk",	EMDH_CLK,	NULL, OFF | CLK_MINMAX),
@@ -177,7 +182,7 @@
 	CLK_7X30S("tv_src_clk",	TV_CLK, 	TV_ENC_CLK,	NULL, 0),
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
-	CLK_PCOM("uart_clk",	UART2_CLK,	&msm_device_uart2.dev, 0),
+	CLK_PCOM("uart_clk",	UART2_CLK,	"msm_serial.1", 0),
 	CLK_PCOM("usb_phy_clk",	USB_PHY_CLK,	NULL, 0),
 	CLK_PCOM("usb_hs_clk",		USB_HS_CLK,		NULL, OFF),
 	CLK_PCOM("usb_hs_pclk",		USB_HS_P_CLK,		NULL, OFF),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm8960.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm8960.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm8960.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm8960.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,85 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only 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/platform_device.h>
+
+#include <linux/dma-mapping.h>
+#include <mach/irqs-8960.h>
+#include <mach/board.h>
+
+#include "devices.h"
+
+#define MSM_GSBI2_PHYS		0x16100000
+#define MSM_UART2DM_PHYS	(MSM_GSBI2_PHYS + 0x40000)
+
+#define MSM_GSBI5_PHYS		0x16400000
+#define MSM_UART5DM_PHYS	(MSM_GSBI5_PHYS + 0x40000)
+
+static struct resource resources_uart_gsbi2[] = {
+	{
+		.start	= GSBI2_UARTDM_IRQ,
+		.end	= GSBI2_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART2DM_PHYS,
+		.end	= MSM_UART2DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uart_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI2_PHYS,
+		.end	= MSM_GSBI2_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_uart_gsbi2 = {
+	.name	= "msm_serial",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart_gsbi2),
+	.resource	= resources_uart_gsbi2,
+};
+
+static struct resource resources_uart_gsbi5[] = {
+	{
+		.start	= GSBI5_UARTDM_IRQ,
+		.end	= GSBI5_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_UART5DM_PHYS,
+		.end	= MSM_UART5DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uart_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MSM_GSBI5_PHYS,
+		.end	= MSM_GSBI5_PHYS + PAGE_SIZE - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device msm8960_device_uart_gsbi5 = {
+	.name	= "msm_serial",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(resources_uart_gsbi5),
+	.resource	= resources_uart_gsbi5,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm8x60-iommu.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm8x60-iommu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-msm8x60-iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-msm8x60-iommu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,906 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 and
- * only 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/platform_device.h>
-#include <linux/bootmem.h>
-
-#include <mach/msm_iomap-8x60.h>
-#include <mach/irqs-8x60.h>
-#include <mach/iommu.h>
-
-static struct resource msm_iommu_jpegd_resources[] = {
-	{
-		.start = MSM_IOMMU_JPEGD_PHYS,
-		.end   = MSM_IOMMU_JPEGD_PHYS + MSM_IOMMU_JPEGD_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_JPEGD_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_JPEGD_CB_SC_SECURE_IRQ,
-		.end   = SMMU_JPEGD_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vpe_resources[] = {
-	{
-		.start = MSM_IOMMU_VPE_PHYS,
-		.end   = MSM_IOMMU_VPE_PHYS + MSM_IOMMU_VPE_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VPE_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VPE_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VPE_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_mdp0_resources[] = {
-	{
-		.start = MSM_IOMMU_MDP0_PHYS,
-		.end   = MSM_IOMMU_MDP0_PHYS + MSM_IOMMU_MDP0_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_MDP0_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_MDP0_CB_SC_SECURE_IRQ,
-		.end   = SMMU_MDP0_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_mdp1_resources[] = {
-	{
-		.start = MSM_IOMMU_MDP1_PHYS,
-		.end   = MSM_IOMMU_MDP1_PHYS + MSM_IOMMU_MDP1_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_MDP1_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_MDP1_CB_SC_SECURE_IRQ,
-		.end   = SMMU_MDP1_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_rot_resources[] = {
-	{
-		.start = MSM_IOMMU_ROT_PHYS,
-		.end   = MSM_IOMMU_ROT_PHYS + MSM_IOMMU_ROT_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_ROT_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_ROT_CB_SC_SECURE_IRQ,
-		.end   = SMMU_ROT_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_ijpeg_resources[] = {
-	{
-		.start = MSM_IOMMU_IJPEG_PHYS,
-		.end   = MSM_IOMMU_IJPEG_PHYS + MSM_IOMMU_IJPEG_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_IJPEG_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_IJPEG_CB_SC_SECURE_IRQ,
-		.end   = SMMU_IJPEG_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vfe_resources[] = {
-	{
-		.start = MSM_IOMMU_VFE_PHYS,
-		.end   = MSM_IOMMU_VFE_PHYS + MSM_IOMMU_VFE_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VFE_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VFE_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VFE_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vcodec_a_resources[] = {
-	{
-		.start = MSM_IOMMU_VCODEC_A_PHYS,
-		.end   = MSM_IOMMU_VCODEC_A_PHYS + MSM_IOMMU_VCODEC_A_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VCODEC_A_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_vcodec_b_resources[] = {
-	{
-		.start = MSM_IOMMU_VCODEC_B_PHYS,
-		.end   = MSM_IOMMU_VCODEC_B_PHYS + MSM_IOMMU_VCODEC_B_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
-		.end   = SMMU_VCODEC_B_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx3d_resources[] = {
-	{
-		.start = MSM_IOMMU_GFX3D_PHYS,
-		.end   = MSM_IOMMU_GFX3D_PHYS + MSM_IOMMU_GFX3D_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX3D_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX3D_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX3D_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx2d0_resources[] = {
-	{
-		.start = MSM_IOMMU_GFX2D0_PHYS,
-		.end   = MSM_IOMMU_GFX2D0_PHYS + MSM_IOMMU_GFX2D0_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX2D0_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct resource msm_iommu_gfx2d1_resources[] = {
-	{
-		.start = MSM_IOMMU_GFX2D1_PHYS,
-		.end   = MSM_IOMMU_GFX2D1_PHYS + MSM_IOMMU_GFX2D1_SIZE - 1,
-		.name  = "physbase",
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.name = "nonsecure_irq",
-		.start = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
-		.end   = SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-	{
-		.name = "secure_irq",
-		.start = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
-		.end   = SMMU_GFX2D1_CB_SC_SECURE_IRQ,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device msm_root_iommu_dev = {
-	.name = "msm_iommu",
-	.id = -1,
-};
-
-static struct msm_iommu_dev jpegd_iommu = {
-	.name = "jpegd",
-	.clk_rate = -1
-};
-
-static struct msm_iommu_dev vpe_iommu = {
-	.name = "vpe"
-};
-
-static struct msm_iommu_dev mdp0_iommu = {
-	.name = "mdp0"
-};
-
-static struct msm_iommu_dev mdp1_iommu = {
-	.name = "mdp1"
-};
-
-static struct msm_iommu_dev rot_iommu = {
-	.name = "rot"
-};
-
-static struct msm_iommu_dev ijpeg_iommu = {
-	.name = "ijpeg"
-};
-
-static struct msm_iommu_dev vfe_iommu = {
-	.name = "vfe",
-	.clk_rate = -1
-};
-
-static struct msm_iommu_dev vcodec_a_iommu = {
-	.name = "vcodec_a"
-};
-
-static struct msm_iommu_dev vcodec_b_iommu = {
-	.name = "vcodec_b"
-};
-
-static struct msm_iommu_dev gfx3d_iommu = {
-	.name = "gfx3d",
-	.clk_rate = 27000000
-};
-
-static struct msm_iommu_dev gfx2d0_iommu = {
-	.name = "gfx2d0",
-	.clk_rate = 27000000
-};
-
-static struct msm_iommu_dev gfx2d1_iommu = {
-	.name = "gfx2d1",
-	.clk_rate = 27000000
-};
-
-static struct platform_device msm_device_iommu_jpegd = {
-	.name = "msm_iommu",
-	.id = 0,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_jpegd_resources),
-	.resource = msm_iommu_jpegd_resources,
-};
-
-static struct platform_device msm_device_iommu_vpe = {
-	.name = "msm_iommu",
-	.id = 1,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vpe_resources),
-	.resource = msm_iommu_vpe_resources,
-};
-
-static struct platform_device msm_device_iommu_mdp0 = {
-	.name = "msm_iommu",
-	.id = 2,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_mdp0_resources),
-	.resource = msm_iommu_mdp0_resources,
-};
-
-static struct platform_device msm_device_iommu_mdp1 = {
-	.name = "msm_iommu",
-	.id = 3,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_mdp1_resources),
-	.resource = msm_iommu_mdp1_resources,
-};
-
-static struct platform_device msm_device_iommu_rot = {
-	.name = "msm_iommu",
-	.id = 4,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_rot_resources),
-	.resource = msm_iommu_rot_resources,
-};
-
-static struct platform_device msm_device_iommu_ijpeg = {
-	.name = "msm_iommu",
-	.id = 5,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_ijpeg_resources),
-	.resource = msm_iommu_ijpeg_resources,
-};
-
-static struct platform_device msm_device_iommu_vfe = {
-	.name = "msm_iommu",
-	.id = 6,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vfe_resources),
-	.resource = msm_iommu_vfe_resources,
-};
-
-static struct platform_device msm_device_iommu_vcodec_a = {
-	.name = "msm_iommu",
-	.id = 7,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_a_resources),
-	.resource = msm_iommu_vcodec_a_resources,
-};
-
-static struct platform_device msm_device_iommu_vcodec_b = {
-	.name = "msm_iommu",
-	.id = 8,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_vcodec_b_resources),
-	.resource = msm_iommu_vcodec_b_resources,
-};
-
-static struct platform_device msm_device_iommu_gfx3d = {
-	.name = "msm_iommu",
-	.id = 9,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx3d_resources),
-	.resource = msm_iommu_gfx3d_resources,
-};
-
-static struct platform_device msm_device_iommu_gfx2d0 = {
-	.name = "msm_iommu",
-	.id = 10,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d0_resources),
-	.resource = msm_iommu_gfx2d0_resources,
-};
-
-struct platform_device msm_device_iommu_gfx2d1 = {
-	.name = "msm_iommu",
-	.id = 11,
-	.dev = {
-		.parent = &msm_root_iommu_dev.dev,
-	},
-	.num_resources = ARRAY_SIZE(msm_iommu_gfx2d1_resources),
-	.resource = msm_iommu_gfx2d1_resources,
-};
-
-static struct msm_iommu_ctx_dev jpegd_src_ctx = {
-	.name = "jpegd_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev jpegd_dst_ctx = {
-	.name = "jpegd_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev vpe_src_ctx = {
-	.name = "vpe_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev vpe_dst_ctx = {
-	.name = "vpe_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_vg1_ctx = {
-	.name = "mdp_vg1",
-	.num = 0,
-	.mids = {0, 2, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_rgb1_ctx = {
-	.name = "mdp_rgb1",
-	.num = 1,
-	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_vg2_ctx = {
-	.name = "mdp_vg2",
-	.num = 0,
-	.mids = {0, 2, -1}
-};
-
-static struct msm_iommu_ctx_dev mdp_rgb2_ctx = {
-	.name = "mdp_rgb2",
-	.num = 1,
-	.mids = {1, 3, 4, 5, 6, 7, 8, 9, 10, -1}
-};
-
-static struct msm_iommu_ctx_dev rot_src_ctx = {
-	.name = "rot_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev rot_dst_ctx = {
-	.name = "rot_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev ijpeg_src_ctx = {
-	.name = "ijpeg_src",
-	.num = 0,
-	.mids = {0, -1}
-};
-
-static struct msm_iommu_ctx_dev ijpeg_dst_ctx = {
-	.name = "ijpeg_dst",
-	.num = 1,
-	.mids = {1, -1}
-};
-
-static struct msm_iommu_ctx_dev vfe_imgwr_ctx = {
-	.name = "vfe_imgwr",
-	.num = 0,
-	.mids = {2, 3, 4, 5, 6, 7, 8, -1}
-};
-
-static struct msm_iommu_ctx_dev vfe_misc_ctx = {
-	.name = "vfe_misc",
-	.num = 1,
-	.mids = {0, 1, 9, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_a_stream_ctx = {
-	.name = "vcodec_a_stream",
-	.num = 0,
-	.mids = {2, 5, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_a_mm1_ctx = {
-	.name = "vcodec_a_mm1",
-	.num = 1,
-	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev vcodec_b_mm2_ctx = {
-	.name = "vcodec_b_mm2",
-	.num = 0,
-	.mids = {0, 1, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_user_ctx = {
-	.name = "gfx3d_user",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx3d_priv_ctx = {
-	.name = "gfx3d_priv",
-	.num = 1,
-	.mids = {16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
-		 31, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d0_2d0_ctx = {
-	.name = "gfx2d0_2d0",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct msm_iommu_ctx_dev gfx2d1_2d1_ctx = {
-	.name = "gfx2d1_2d1",
-	.num = 0,
-	.mids = {0, 1, 2, 3, 4, 5, 6, 7, -1}
-};
-
-static struct platform_device msm_device_jpegd_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 0,
-	.dev = {
-		.parent = &msm_device_iommu_jpegd.dev,
-	},
-};
-
-static struct platform_device msm_device_jpegd_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 1,
-	.dev = {
-		.parent = &msm_device_iommu_jpegd.dev,
-	},
-};
-
-static struct platform_device msm_device_vpe_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 2,
-	.dev = {
-		.parent = &msm_device_iommu_vpe.dev,
-	},
-};
-
-static struct platform_device msm_device_vpe_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 3,
-	.dev = {
-		.parent = &msm_device_iommu_vpe.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_vg1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 4,
-	.dev = {
-		.parent = &msm_device_iommu_mdp0.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_rgb1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 5,
-	.dev = {
-		.parent = &msm_device_iommu_mdp0.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_vg2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 6,
-	.dev = {
-		.parent = &msm_device_iommu_mdp1.dev,
-	},
-};
-
-static struct platform_device msm_device_mdp_rgb2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 7,
-	.dev = {
-		.parent = &msm_device_iommu_mdp1.dev,
-	},
-};
-
-static struct platform_device msm_device_rot_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 8,
-	.dev = {
-		.parent = &msm_device_iommu_rot.dev,
-	},
-};
-
-static struct platform_device msm_device_rot_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 9,
-	.dev = {
-		.parent = &msm_device_iommu_rot.dev,
-	},
-};
-
-static struct platform_device msm_device_ijpeg_src_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 10,
-	.dev = {
-		.parent = &msm_device_iommu_ijpeg.dev,
-	},
-};
-
-static struct platform_device msm_device_ijpeg_dst_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 11,
-	.dev = {
-		.parent = &msm_device_iommu_ijpeg.dev,
-	},
-};
-
-static struct platform_device msm_device_vfe_imgwr_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 12,
-	.dev = {
-		.parent = &msm_device_iommu_vfe.dev,
-	},
-};
-
-static struct platform_device msm_device_vfe_misc_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 13,
-	.dev = {
-		.parent = &msm_device_iommu_vfe.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_a_stream_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 14,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_a.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_a_mm1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 15,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_a.dev,
-	},
-};
-
-static struct platform_device msm_device_vcodec_b_mm2_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 16,
-	.dev = {
-		.parent = &msm_device_iommu_vcodec_b.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx3d_user_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 17,
-	.dev = {
-		.parent = &msm_device_iommu_gfx3d.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx3d_priv_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 18,
-	.dev = {
-		.parent = &msm_device_iommu_gfx3d.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d0_2d0_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 19,
-	.dev = {
-		.parent = &msm_device_iommu_gfx2d0.dev,
-	},
-};
-
-static struct platform_device msm_device_gfx2d1_2d1_ctx = {
-	.name = "msm_iommu_ctx",
-	.id = 20,
-	.dev = {
-		.parent = &msm_device_iommu_gfx2d1.dev,
-	},
-};
-
-static struct platform_device *msm_iommu_devs[] = {
-	&msm_device_iommu_jpegd,
-	&msm_device_iommu_vpe,
-	&msm_device_iommu_mdp0,
-	&msm_device_iommu_mdp1,
-	&msm_device_iommu_rot,
-	&msm_device_iommu_ijpeg,
-	&msm_device_iommu_vfe,
-	&msm_device_iommu_vcodec_a,
-	&msm_device_iommu_vcodec_b,
-	&msm_device_iommu_gfx3d,
-	&msm_device_iommu_gfx2d0,
-	&msm_device_iommu_gfx2d1,
-};
-
-static struct msm_iommu_dev *msm_iommu_data[] = {
-	&jpegd_iommu,
-	&vpe_iommu,
-	&mdp0_iommu,
-	&mdp1_iommu,
-	&rot_iommu,
-	&ijpeg_iommu,
-	&vfe_iommu,
-	&vcodec_a_iommu,
-	&vcodec_b_iommu,
-	&gfx3d_iommu,
-	&gfx2d0_iommu,
-	&gfx2d1_iommu,
-};
-
-static struct platform_device *msm_iommu_ctx_devs[] = {
-	&msm_device_jpegd_src_ctx,
-	&msm_device_jpegd_dst_ctx,
-	&msm_device_vpe_src_ctx,
-	&msm_device_vpe_dst_ctx,
-	&msm_device_mdp_vg1_ctx,
-	&msm_device_mdp_rgb1_ctx,
-	&msm_device_mdp_vg2_ctx,
-	&msm_device_mdp_rgb2_ctx,
-	&msm_device_rot_src_ctx,
-	&msm_device_rot_dst_ctx,
-	&msm_device_ijpeg_src_ctx,
-	&msm_device_ijpeg_dst_ctx,
-	&msm_device_vfe_imgwr_ctx,
-	&msm_device_vfe_misc_ctx,
-	&msm_device_vcodec_a_stream_ctx,
-	&msm_device_vcodec_a_mm1_ctx,
-	&msm_device_vcodec_b_mm2_ctx,
-	&msm_device_gfx3d_user_ctx,
-	&msm_device_gfx3d_priv_ctx,
-	&msm_device_gfx2d0_2d0_ctx,
-	&msm_device_gfx2d1_2d1_ctx,
-};
-
-static struct msm_iommu_ctx_dev *msm_iommu_ctx_data[] = {
-	&jpegd_src_ctx,
-	&jpegd_dst_ctx,
-	&vpe_src_ctx,
-	&vpe_dst_ctx,
-	&mdp_vg1_ctx,
-	&mdp_rgb1_ctx,
-	&mdp_vg2_ctx,
-	&mdp_rgb2_ctx,
-	&rot_src_ctx,
-	&rot_dst_ctx,
-	&ijpeg_src_ctx,
-	&ijpeg_dst_ctx,
-	&vfe_imgwr_ctx,
-	&vfe_misc_ctx,
-	&vcodec_a_stream_ctx,
-	&vcodec_a_mm1_ctx,
-	&vcodec_b_mm2_ctx,
-	&gfx3d_user_ctx,
-	&gfx3d_priv_ctx,
-	&gfx2d0_2d0_ctx,
-	&gfx2d1_2d1_ctx,
-};
-
-static int __init msm8x60_iommu_init(void)
-{
-	int ret, i;
-
-	ret = platform_device_register(&msm_root_iommu_dev);
-	if (ret != 0) {
-		pr_err("Failed to register root IOMMU device!\n");
-		goto failure;
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_devs[i],
-					       msm_iommu_data[i],
-					       sizeof(struct msm_iommu_dev));
-		if (ret != 0) {
-			pr_err("platform_device_add_data failed, "
-			       "i = %d\n", i);
-			goto failure_unwind;
-		}
-
-		ret = platform_device_register(msm_iommu_devs[i]);
-
-		if (ret != 0) {
-			pr_err("platform_device_register iommu failed, "
-			       "i = %d\n", i);
-			goto failure_unwind;
-		}
-	}
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++) {
-		ret = platform_device_add_data(msm_iommu_ctx_devs[i],
-					       msm_iommu_ctx_data[i],
-					       sizeof(*msm_iommu_ctx_devs[i]));
-		if (ret != 0) {
-			pr_err("platform_device_add_data iommu failed, "
-			       "i = %d\n", i);
-			goto failure_unwind2;
-		}
-
-		ret = platform_device_register(msm_iommu_ctx_devs[i]);
-		if (ret != 0) {
-			pr_err("platform_device_register ctx failed, "
-			       "i = %d\n", i);
-			goto failure_unwind2;
-		}
-	}
-	return 0;
-
-failure_unwind2:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
-failure_unwind:
-	while (--i >= 0)
-		platform_device_unregister(msm_iommu_devs[i]);
-
-	platform_device_unregister(&msm_root_iommu_dev);
-failure:
-	return ret;
-}
-
-static void __exit msm8x60_iommu_exit(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_ctx_devs); i++)
-		platform_device_unregister(msm_iommu_ctx_devs[i]);
-
-	for (i = 0; i < ARRAY_SIZE(msm_iommu_devs); ++i)
-		platform_device_unregister(msm_iommu_devs[i]);
-
-	platform_device_unregister(&msm_root_iommu_dev);
-}
-
-subsys_initcall(msm8x60_iommu_init);
-module_exit(msm8x60_iommu_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-qsd8x50.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-qsd8x50.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/devices-qsd8x50.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/devices-qsd8x50.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2008 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -15,8 +15,9 @@
 
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
-
+#include <linux/clkdev.h>
 #include <linux/dma-mapping.h>
+
 #include <mach/irqs.h>
 #include <mach/msm_iomap.h>
 #include <mach/dma.h>
@@ -27,6 +28,7 @@
 #include <asm/mach/flash.h>
 
 #include <mach/mmc.h>
+#include "clock-pcom.h"
 
 static struct resource resources_uart3[] = {
 	{
@@ -38,6 +40,7 @@
 		.start	= MSM_UART3_PHYS,
 		.end	= MSM_UART3_PHYS + MSM_UART3_SIZE - 1,
 		.flags	= IORESOURCE_MEM,
+		.name  = "uart_resource"
 	},
 };
 
@@ -124,14 +127,204 @@
 	},
 };
 
-struct clk msm_clocks_8x50[] = {
+static struct resource resources_sdc1[] = {
+	{
+		.start	= MSM_SDC1_PHYS,
+		.end	= MSM_SDC1_PHYS + MSM_SDC1_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC1_0,
+		.end	= INT_SDC1_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+	{
+		.start	= INT_SDC1_1,
+		.end	= INT_SDC1_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource resources_sdc2[] = {
+	{
+		.start	= MSM_SDC2_PHYS,
+		.end	= MSM_SDC2_PHYS + MSM_SDC2_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC2_0,
+		.end	= INT_SDC2_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+		{
+		.start	= INT_SDC2_1,
+		.end	= INT_SDC2_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource resources_sdc3[] = {
+	{
+		.start	= MSM_SDC3_PHYS,
+		.end	= MSM_SDC3_PHYS + MSM_SDC3_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC3_0,
+		.end	= INT_SDC3_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+		{
+		.start	= INT_SDC3_1,
+		.end	= INT_SDC3_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct resource resources_sdc4[] = {
+	{
+		.start	= MSM_SDC4_PHYS,
+		.end	= MSM_SDC4_PHYS + MSM_SDC4_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= INT_SDC4_0,
+		.end	= INT_SDC4_0,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "cmd_irq",
+	},
+		{
+		.start	= INT_SDC4_1,
+		.end	= INT_SDC4_1,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "pio_irq",
+	},
+	{
+		.flags	= IORESOURCE_IRQ | IORESOURCE_DISABLED,
+		.name	= "status_irq"
+	},
+	{
+		.start	= 8,
+		.end	= 8,
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+struct platform_device msm_device_sdc1 = {
+	.name		= "msm_sdcc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(resources_sdc1),
+	.resource	= resources_sdc1,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_sdc2 = {
+	.name		= "msm_sdcc",
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(resources_sdc2),
+	.resource	= resources_sdc2,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_sdc3 = {
+	.name		= "msm_sdcc",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(resources_sdc3),
+	.resource	= resources_sdc3,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device msm_device_sdc4 = {
+	.name		= "msm_sdcc",
+	.id		= 4,
+	.num_resources	= ARRAY_SIZE(resources_sdc4),
+	.resource	= resources_sdc4,
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+static struct platform_device *msm_sdcc_devices[] __initdata = {
+	&msm_device_sdc1,
+	&msm_device_sdc2,
+	&msm_device_sdc3,
+	&msm_device_sdc4,
+};
+
+int __init msm_add_sdcc(unsigned int controller,
+			struct msm_mmc_platform_data *plat,
+			unsigned int stat_irq, unsigned long stat_irq_flags)
+{
+	struct platform_device	*pdev;
+	struct resource *res;
+
+	if (controller < 1 || controller > 4)
+		return -EINVAL;
+
+	pdev = msm_sdcc_devices[controller-1];
+	pdev->dev.platform_data = plat;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "status_irq");
+	if (!res)
+		return -EINVAL;
+	else if (stat_irq) {
+		res->start = res->end = stat_irq;
+		res->flags &= ~IORESOURCE_DISABLED;
+		res->flags |= stat_irq_flags;
+	}
+
+	return platform_device_register(pdev);
+}
+
+struct clk_lookup msm_clocks_8x50[] = {
 	CLK_PCOM("adm_clk",	ADM_CLK,	NULL, 0),
+	CLK_PCOM("ce_clk",	CE_CLK,		NULL, 0),
 	CLK_PCOM("ebi1_clk",	EBI1_CLK,	NULL, CLK_MIN),
 	CLK_PCOM("ebi2_clk",	EBI2_CLK,	NULL, 0),
 	CLK_PCOM("ecodec_clk",	ECODEC_CLK,	NULL, 0),
 	CLK_PCOM("emdh_clk",	EMDH_CLK,	NULL, OFF | CLK_MINMAX),
 	CLK_PCOM("gp_clk",	GP_CLK,		NULL, 0),
 	CLK_PCOM("grp_clk",	GRP_3D_CLK,	NULL, 0),
+	CLK_PCOM("i2c_clk",	I2C_CLK,	NULL, 0),
 	CLK_PCOM("icodec_rx_clk",	ICODEC_RX_CLK,	NULL, 0),
 	CLK_PCOM("icodec_tx_clk",	ICODEC_TX_CLK,	NULL, 0),
 	CLK_PCOM("imem_clk",	IMEM_CLK,	NULL, OFF),
@@ -144,12 +337,24 @@
 	CLK_PCOM("pbus_clk",	PBUS_CLK,	NULL, CLK_MIN),
 	CLK_PCOM("pcm_clk",	PCM_CLK,	NULL, 0),
 	CLK_PCOM("sdac_clk",	SDAC_CLK,	NULL, OFF),
+	CLK_PCOM("sdc_clk",	SDC1_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_pclk",	SDC1_P_CLK,	"msm_sdcc.1", OFF),
+	CLK_PCOM("sdc_clk",	SDC2_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_pclk",	SDC2_P_CLK,	"msm_sdcc.2", OFF),
+	CLK_PCOM("sdc_clk",	SDC3_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_pclk",	SDC3_P_CLK,	"msm_sdcc.3", OFF),
+	CLK_PCOM("sdc_clk",	SDC4_CLK,	"msm_sdcc.4", OFF),
+	CLK_PCOM("sdc_pclk",	SDC4_P_CLK,	"msm_sdcc.4", OFF),
 	CLK_PCOM("spi_clk",	SPI_CLK,	NULL, 0),
 	CLK_PCOM("tsif_clk",	TSIF_CLK,	NULL, 0),
 	CLK_PCOM("tsif_ref_clk",	TSIF_REF_CLK,	NULL, 0),
 	CLK_PCOM("tv_dac_clk",	TV_DAC_CLK,	NULL, 0),
 	CLK_PCOM("tv_enc_clk",	TV_ENC_CLK,	NULL, 0),
-	CLK_PCOM("uart_clk",	UART3_CLK,	&msm_device_uart3.dev, OFF),
+	CLK_PCOM("uart_clk",	UART1_CLK,	NULL, OFF),
+	CLK_PCOM("uart_clk",	UART2_CLK,	NULL, 0),
+	CLK_PCOM("uart_clk",	UART3_CLK,	"msm_serial.2", OFF),
+	CLK_PCOM("uartdm_clk",	UART1DM_CLK,	NULL, OFF),
+	CLK_PCOM("uartdm_clk",	UART2DM_CLK,	NULL, 0),
 	CLK_PCOM("usb_hs_clk",	USB_HS_CLK,	NULL, OFF),
 	CLK_PCOM("usb_hs_pclk",	USB_HS_P_CLK,	NULL, OFF),
 	CLK_PCOM("usb_otg_clk",	USB_OTG_CLK,	NULL, 0),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -293,10 +293,10 @@
 	val = readl(msm_chip->regs.int_edge);
 	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
 		writel(val | mask, msm_chip->regs.int_edge);
-		irq_desc[d->irq].handle_irq = handle_edge_irq;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	} else {
 		writel(val & ~mask, msm_chip->regs.int_edge);
-		irq_desc[d->irq].handle_irq = handle_level_irq;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	}
 	if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
 		msm_chip->both_edge_detect |= mask;
@@ -354,9 +354,9 @@
 			msm_gpio_chips[j].chip.base +
 			msm_gpio_chips[j].chip.ngpio)
 			j++;
-		set_irq_chip_data(i, &msm_gpio_chips[j]);
-		set_irq_chip(i, &msm_gpio_irq_chip);
-		set_irq_handler(i, handle_edge_irq);
+		irq_set_chip_data(i, &msm_gpio_chips[j]);
+		irq_set_chip_and_handler(i, &msm_gpio_irq_chip,
+					 handle_edge_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
@@ -366,10 +366,10 @@
 		gpiochip_add(&msm_gpio_chips[i].chip);
 	}
 
-	set_irq_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
-	set_irq_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
-	set_irq_wake(INT_GPIO_GROUP1, 1);
-	set_irq_wake(INT_GPIO_GROUP2, 2);
+	irq_set_chained_handler(INT_GPIO_GROUP1, msm_gpio_irq_handler);
+	irq_set_chained_handler(INT_GPIO_GROUP2, msm_gpio_irq_handler);
+	irq_set_irq_wake(INT_GPIO_GROUP1, 1);
+	irq_set_irq_wake(INT_GPIO_GROUP2, 2);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpiomux-7x30.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpiomux-7x30.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpiomux-7x30.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpiomux-7x30.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,38 +0,0 @@
-/* Copyright (c) 2010, Code Aurora Forum. 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 and
- * only 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 "gpiomux.h"
-
-struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
-#ifdef CONFIG_SERIAL_MSM_CONSOLE
-	[49] = { /* UART2 RFR */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-	[50] = { /* UART2 CTS */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-	[51] = { /* UART2 RX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-	[52] = { /* UART2 TX */
-		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
-			     GPIOMUX_FUNC_2 | GPIOMUX_VALID,
-	},
-#endif
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpiomux-8x50.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpiomux-8x50.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpiomux-8x50.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpiomux-8x50.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,19 @@
  */
 #include "gpiomux.h"
 
+#if defined(CONFIG_MMC_MSM) || defined(CONFIG_MMC_MSM_MODULE)
+	#define SDCC_DAT_0_3_CMD_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_UP\
+					| GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
+	#define SDCC_CLK_ACTV_CFG (GPIOMUX_VALID | GPIOMUX_PULL_NONE\
+					| GPIOMUX_FUNC_1 | GPIOMUX_DRV_8MA)
+#else
+	#define SDCC_DAT_0_3_CMD_ACTV_CFG 0
+	#define SDCC_CLK_ACTV_CFG 0
+#endif
+
+#define SDC1_SUSPEND_CONFIG (GPIOMUX_VALID | GPIOMUX_PULL_DOWN\
+				| GPIOMUX_FUNC_GPIO | GPIOMUX_DRV_2MA)
+
 struct msm_gpiomux_config msm_gpiomux_configs[GPIOMUX_NGPIOS] = {
 	[86] = { /* UART3 RX */
 		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
@@ -25,4 +38,14 @@
 		.suspended = GPIOMUX_DRV_2MA | GPIOMUX_PULL_DOWN |
 			     GPIOMUX_FUNC_1 | GPIOMUX_VALID,
 	},
+	/* SDC1 data[3:0] & CMD */
+	[51 ... 55] = {
+		.active = SDCC_DAT_0_3_CMD_ACTV_CFG,
+		.suspended = SDC1_SUSPEND_CONFIG
+	},
+	/* SDC1 CLK */
+	[56] = {
+		.active = SDCC_CLK_ACTV_CFG,
+		.suspended = SDC1_SUSPEND_CONFIG
+	},
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpio-v2.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpio-v2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/gpio-v2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/gpio-v2.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,18 +230,18 @@
 	       val, val2);
 }
 
-static void msm_gpio_irq_ack(unsigned int irq)
+static void msm_gpio_irq_ack(struct irq_data *d)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 
 	writel(BIT(INTR_STATUS), GPIO_INTR_STATUS(gpio));
 	if (test_bit(gpio, msm_gpio.dual_edge_irqs))
 		msm_gpio_update_dual_edge_pos(gpio);
 }
 
-static void msm_gpio_irq_mask(unsigned int irq)
+static void msm_gpio_irq_mask(struct irq_data *d)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 	unsigned long irq_flags;
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -251,9 +251,9 @@
 	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
 
-static void msm_gpio_irq_unmask(unsigned int irq)
+static void msm_gpio_irq_unmask(struct irq_data *d)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 	unsigned long irq_flags;
 
 	spin_lock_irqsave(&tlmm_lock, irq_flags);
@@ -263,9 +263,9 @@
 	spin_unlock_irqrestore(&tlmm_lock, irq_flags);
 }
 
-static int msm_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int msm_gpio_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 	unsigned long irq_flags;
 	uint32_t bits;
 
@@ -275,14 +275,14 @@
 
 	if (flow_type & IRQ_TYPE_EDGE_BOTH) {
 		bits |= BIT(INTR_DECT_CTL);
-		irq_desc[irq].handle_irq = handle_edge_irq;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 		if ((flow_type & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH)
 			__set_bit(gpio, msm_gpio.dual_edge_irqs);
 		else
 			__clear_bit(gpio, msm_gpio.dual_edge_irqs);
 	} else {
 		bits &= ~BIT(INTR_DECT_CTL);
-		irq_desc[irq].handle_irq = handle_level_irq;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 		__clear_bit(gpio, msm_gpio.dual_edge_irqs);
 	}
 
@@ -309,6 +309,7 @@
  */
 static void msm_summary_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_data *data = irq_desc_get_irq_data(desc);
 	unsigned long i;
 
 	for (i = find_first_bit(msm_gpio.enabled_irqs, NR_GPIO_IRQS);
@@ -318,21 +319,21 @@
 			generic_handle_irq(msm_gpio_to_irq(&msm_gpio.gpio_chip,
 							   i));
 	}
-	desc->chip->ack(irq);
+	data->chip->irq_ack(data);
 }
 
-static int msm_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+static int msm_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, irq);
+	int gpio = msm_irq_to_gpio(&msm_gpio.gpio_chip, d->irq);
 
 	if (on) {
 		if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
-			set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1);
+			irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 1);
 		set_bit(gpio, msm_gpio.wake_irqs);
 	} else {
 		clear_bit(gpio, msm_gpio.wake_irqs);
 		if (bitmap_empty(msm_gpio.wake_irqs, NR_GPIO_IRQS))
-			set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0);
+			irq_set_irq_wake(TLMM_SCSS_SUMMARY_IRQ, 0);
 	}
 
 	return 0;
@@ -340,11 +341,11 @@
 
 static struct irq_chip msm_gpio_irq_chip = {
 	.name		= "msmgpio",
-	.mask		= msm_gpio_irq_mask,
-	.unmask		= msm_gpio_irq_unmask,
-	.ack		= msm_gpio_irq_ack,
-	.set_type	= msm_gpio_irq_set_type,
-	.set_wake	= msm_gpio_irq_set_wake,
+	.irq_mask	= msm_gpio_irq_mask,
+	.irq_unmask	= msm_gpio_irq_unmask,
+	.irq_ack	= msm_gpio_irq_ack,
+	.irq_set_type	= msm_gpio_irq_set_type,
+	.irq_set_wake	= msm_gpio_irq_set_wake,
 };
 
 static int __devinit msm_gpio_probe(struct platform_device *dev)
@@ -361,12 +362,12 @@
 
 	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
 		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
-		set_irq_chip(irq, &msm_gpio_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	set_irq_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
+	irq_set_chained_handler(TLMM_SCSS_SUMMARY_IRQ,
 				msm_summary_irq_handler);
 	return 0;
 }
@@ -378,7 +379,7 @@
 	if (ret < 0)
 		return ret;
 
-	set_irq_handler(TLMM_SCSS_SUMMARY_IRQ, NULL);
+	irq_set_handler(TLMM_SCSS_SUMMARY_IRQ, NULL);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/headsmp.S linux-libre-2.6.39-gnu/arch/arm/mach-msm/headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/headsmp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/headsmp.S	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
-	__INIT
+	__CPUINIT
 
 /*
  * MSM specific entry point for secondary CPUs.  This provides
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/board.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/board.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/board.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/board.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 	unsigned long wait_for_irq_khz;
 };
 
-struct clk;
+struct clk_lookup;
 
 extern struct sys_timer msm_timer;
 
@@ -41,7 +41,7 @@
 void __init msm_map_common_io(void);
 void __init msm_init_irq(void);
 void __init msm_init_gpio(void);
-void __init msm_clock_init(struct clk *clock_tbl, unsigned num_clocks);
+void __init msm_clock_init(struct clk_lookup *clock_tbl, unsigned num_clocks);
 void __init msm_acpu_clock_init(struct msm_acpu_clock_platform_data *);
 int __init msm_add_sdcc(unsigned int controller,
 			struct msm_mmc_platform_data *plat,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/clkdev.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/clkdev.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/clkdev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/clkdev.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,19 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only 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.
+ */
+#ifndef __ASM_ARCH_MSM_CLKDEV_H
+#define __ASM_ARCH_MSM_CLKDEV_H
+
+struct clk;
+
+static inline int __clk_get(struct clk *clk) { return 1; }
+static inline void __clk_put(struct clk *clk) { }
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/clk.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/clk.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/clk.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/clk.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 #ifndef __MACH_CLK_H
 #define __MACH_CLK_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/cpu.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/cpu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/cpu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/cpu.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,54 @@
+/* Copyright (c) 2011, Code Aurora Forum. 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 and
+ * only 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 __ARCH_ARM_MACH_MSM_CPU_H__
+#define __ARCH_ARM_MACH_MSM_CPU_H__
+
+/* TODO: For now, only one CPU can be compiled at a time. */
+
+#define cpu_is_msm7x01()	0
+#define cpu_is_msm7x30()	0
+#define cpu_is_qsd8x50()	0
+#define cpu_is_msm8x60()	0
+#define cpu_is_msm8960()	0
+
+#ifdef CONFIG_ARCH_MSM7X00A
+# undef cpu_is_msm7x01
+# define cpu_is_msm7x01()	1
+#endif
+
+#ifdef CONFIG_ARCH_MSM7X30
+# undef cpu_is_msm7x30
+# define cpu_is_msm7x30()	1
+#endif
+
+#ifdef CONFIG_ARCH_QSD8X50
+# undef cpu_is_qsd8x50
+# define cpu_is_qsd8x50()	1
+#endif
+
+#ifdef CONFIG_ARCH_MSM8X60
+# undef cpu_is_msm8x60
+# define cpu_is_msm8x60()	1
+#endif
+
+#ifdef CONFIG_ARCH_MSM8960
+# undef cpu_is_msm8960
+# define cpu_is_msm8960()	1
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 void msm_map_qsd8x50_io(void);
 void msm_map_msm7x30_io(void);
 void msm_map_msm8x60_io(void);
+void msm_map_msm8960_io(void);
 
 extern unsigned int msm_shared_ram_phys;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/iommu.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/iommu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/iommu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/iommu.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
@@ -19,6 +19,7 @@
 #define MSM_IOMMU_H
 
 #include <linux/interrupt.h>
+#include <linux/clk.h>
 
 /* Sharability attributes of MSM IOMMU mappings */
 #define MSM_IOMMU_ATTR_NON_SH		0x0
@@ -44,14 +45,11 @@
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
  * name		Human-readable name given to this IOMMU HW instance
- * clk_rate	Rate to set for this IOMMU's clock, if applicable to this
- *		particular IOMMU. 0 means don't set a rate.
- *		-1 means it is an AXI clock with no valid rate
- *
+ * ncb		Number of context banks present on this IOMMU HW instance
  */
 struct msm_iommu_dev {
 	const char *name;
-	int clk_rate;
+	int ncb;
 };
 
 /**
@@ -73,14 +71,20 @@
 /**
  * struct msm_iommu_drvdata - A single IOMMU hardware instance
  * @base:	IOMMU config port base address (VA)
+ * @ncb		The number of contexts on this IOMMU
  * @irq:	Interrupt number
-  *
+ * @clk:	The bus clock for this IOMMU hardware instance
+ * @pclk:	The clock for the IOMMU bus interconnect
+ *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
  */
 struct msm_iommu_drvdata {
 	void __iomem *base;
 	int irq;
+	int ncb;
+	struct clk *clk;
+	struct clk *pclk;
 };
 
 /**
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/iommu_hw-8xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
@@ -68,6 +68,7 @@
 #define FL_CACHEABLE		(1 << 3)
 #define FL_TEX0			(1 << 12)
 #define FL_OFFSET(va)		(((va) & 0xFFF00000) >> 20)
+#define FL_NG			(1 << 17)
 
 /* Second-level page table bits */
 #define SL_BASE_MASK_LARGE	0xFFFF0000
@@ -81,6 +82,7 @@
 #define SL_CACHEABLE		(1 << 3)
 #define SL_TEX0			(1 << 6)
 #define SL_OFFSET(va)		(((va) & 0xFF000) >> 12)
+#define SL_NG			(1 << 11)
 
 /* Memory type and cache policy attributes */
 #define MT_SO			0
@@ -623,20 +625,6 @@
 #define SET_INDEX(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PSR, INDEX, v)
 
 
-/* V2Pxx UW UR PW PR */
-#define SET_V2PUW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX, v)
-#define SET_V2PUW_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA, v)
-
-#define SET_V2PUR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX, v)
-#define SET_V2PUR_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA, v)
-
-#define SET_V2PPW_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX, v)
-#define SET_V2PPW_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA, v)
-
-#define SET_V2PPR_INDEX(b, c, v) SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX, v)
-#define SET_V2PPR_VA(b, c, v)	 SET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA, v)
-
-
 /* Context Register getters */
 /* ACTLR */
 #define GET_CFERE(b, c)	        GET_CONTEXT_FIELD(b, c, ACTLR, CFERE)
@@ -824,20 +812,6 @@
 #define GET_INDEX(b, c)		GET_CONTEXT_FIELD(b, c, V2PSR, INDEX)
 
 
-/* V2Pxx UW UR PW PR */
-#define GET_V2PUW_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_INDEX)
-#define GET_V2PUW_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PUW, V2Pxx_VA)
-
-#define GET_V2PUR_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_INDEX)
-#define GET_V2PUR_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PUR, V2Pxx_VA)
-
-#define GET_V2PPW_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_INDEX)
-#define GET_V2PPW_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PPW, V2Pxx_VA)
-
-#define GET_V2PPR_INDEX(b, c)	GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_INDEX)
-#define GET_V2PPR_VA(b, c)	GET_CONTEXT_FIELD(b, c, V2PPR, V2Pxx_VA)
-
-
 /* Global Registers */
 #define M2VCBR_N	(0xFF000)
 #define CBACR_N		(0xFF800)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs-7x30.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs-7x30.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs-7x30.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs-7x30.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,30 +1,13 @@
 /* Copyright (c) 2009, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 
 #ifndef __ASM_ARCH_MSM_IRQS_7X30_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs-8960.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs-8960.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs-8960.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs-8960.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,277 @@
+/* Copyright (c) 2011 Code Aurora Forum. 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 and
+ * only 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.
+ */
+
+#ifndef __ASM_ARCH_MSM_IRQS_8960_H
+#define __ASM_ARCH_MSM_IRQS_8960_H
+
+/* MSM ACPU Interrupt Numbers */
+
+/* 0-15:  STI/SGI (software triggered/generated interrupts)
+   16-31: PPI (private peripheral interrupts)
+   32+:   SPI (shared peripheral interrupts) */
+
+#define GIC_PPI_START 16
+#define GIC_SPI_START 32
+
+#define INT_VGIC				(GIC_PPI_START + 0)
+#define INT_DEBUG_TIMER_EXP			(GIC_PPI_START + 1)
+#define INT_GP_TIMER_EXP			(GIC_PPI_START + 2)
+#define INT_GP_TIMER2_EXP			(GIC_PPI_START + 3)
+#define WDT0_ACCSCSSNBARK_INT			(GIC_PPI_START + 4)
+#define WDT1_ACCSCSSNBARK_INT			(GIC_PPI_START + 5)
+#define AVS_SVICINT				(GIC_PPI_START + 6)
+#define AVS_SVICINTSWDONE			(GIC_PPI_START + 7)
+#define CPU_DBGCPUXCOMMRXFULL			(GIC_PPI_START + 8)
+#define CPU_DBGCPUXCOMMTXEMPTY			(GIC_PPI_START + 9)
+#define CPU_SICCPUXPERFMONIRPTREQ		(GIC_PPI_START + 10)
+#define SC_AVSCPUXDOWN				(GIC_PPI_START + 11)
+#define SC_AVSCPUXUP				(GIC_PPI_START + 12)
+#define SC_SICCPUXACGIRPTREQ			(GIC_PPI_START + 13)
+#define SC_SICCPUXEXTFAULTIRPTREQ		(GIC_PPI_START + 14)
+/* PPI 15 is unused */
+
+#define SC_SICMPUIRPTREQ			(GIC_SPI_START + 0)
+#define SC_SICL2IRPTREQ				(GIC_SPI_START + 1)
+#define SC_SICL2PERFMONIRPTREQ			(GIC_SPI_START + 2)
+#define SC_SICAGCIRPTREQ			(GIC_SPI_START + 3)
+#define TLMM_APCC_DIR_CONN_IRQ_0		(GIC_SPI_START + 4)
+#define TLMM_APCC_DIR_CONN_IRQ_1		(GIC_SPI_START + 5)
+#define TLMM_APCC_DIR_CONN_IRQ_2		(GIC_SPI_START + 6)
+#define TLMM_APCC_DIR_CONN_IRQ_3		(GIC_SPI_START + 7)
+#define TLMM_APCC_DIR_CONN_IRQ_4		(GIC_SPI_START + 8)
+#define TLMM_APCC_DIR_CONN_IRQ_5		(GIC_SPI_START + 9)
+#define TLMM_APCC_DIR_CONN_IRQ_6		(GIC_SPI_START + 10)
+#define TLMM_APCC_DIR_CONN_IRQ_7		(GIC_SPI_START + 11)
+#define TLMM_APCC_DIR_CONN_IRQ_8		(GIC_SPI_START + 12)
+#define TLMM_APCC_DIR_CONN_IRQ_9		(GIC_SPI_START + 13)
+#define PM8921_SEC_IRQ_103			(GIC_SPI_START + 14)
+#define PM8018_SEC_IRQ_106			(GIC_SPI_START + 15)
+#define TLMM_APCC_SUMMARY_IRQ			(GIC_SPI_START + 16)
+#define SPDM_RT_1_IRQ				(GIC_SPI_START + 17)
+#define SPDM_DIAG_IRQ				(GIC_SPI_START + 18)
+#define RPM_APCC_CPU0_GP_HIGH_IRQ		(GIC_SPI_START + 19)
+#define RPM_APCC_CPU0_GP_MEDIUM_IRQ		(GIC_SPI_START + 20)
+#define RPM_APCC_CPU0_GP_LOW_IRQ		(GIC_SPI_START + 21)
+#define RPM_APCC_CPU0_WAKE_UP_IRQ		(GIC_SPI_START + 22)
+#define RPM_APCC_CPU1_GP_HIGH_IRQ		(GIC_SPI_START + 23)
+#define RPM_APCC_CPU1_GP_MEDIUM_IRQ		(GIC_SPI_START + 24)
+#define RPM_APCC_CPU1_GP_LOW_IRQ		(GIC_SPI_START + 25)
+#define RPM_APCC_CPU1_WAKE_UP_IRQ		(GIC_SPI_START + 26)
+#define SSBI2_2_SC_CPU0_SECURE_IRQ		(GIC_SPI_START + 27)
+#define SSBI2_2_SC_CPU0_NON_SECURE_IRQ		(GIC_SPI_START + 28)
+#define SSBI2_1_SC_CPU0_SECURE_IRQ		(GIC_SPI_START + 29)
+#define SSBI2_1_SC_CPU0_NON_SECURE_IRQ		(GIC_SPI_START + 30)
+#define MSMC_SC_SEC_CE_IRQ			(GIC_SPI_START + 31)
+#define MSMC_SC_PRI_CE_IRQ			(GIC_SPI_START + 32)
+#define SLIMBUS0_CORE_EE1_IRQ			(GIC_SPI_START + 33)
+#define SLIMBUS0_BAM_EE1_IRQ			(GIC_SPI_START + 34)
+#define Q6FW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 35)
+#define Q6SW_WDOG_EXPIRED_IRQ			(GIC_SPI_START + 36)
+#define MSS_TO_APPS_IRQ_0			(GIC_SPI_START + 37)
+#define MSS_TO_APPS_IRQ_1			(GIC_SPI_START + 38)
+#define MSS_TO_APPS_IRQ_2			(GIC_SPI_START + 39)
+#define MSS_TO_APPS_IRQ_3			(GIC_SPI_START + 40)
+#define MSS_TO_APPS_IRQ_4			(GIC_SPI_START + 41)
+#define MSS_TO_APPS_IRQ_5			(GIC_SPI_START + 42)
+#define MSS_TO_APPS_IRQ_6			(GIC_SPI_START + 43)
+#define MSS_TO_APPS_IRQ_7			(GIC_SPI_START + 44)
+#define MSS_TO_APPS_IRQ_8			(GIC_SPI_START + 45)
+#define MSS_TO_APPS_IRQ_9			(GIC_SPI_START + 46)
+#define VPE_IRQ					(GIC_SPI_START + 47)
+#define VFE_IRQ					(GIC_SPI_START + 48)
+#define VCODEC_IRQ				(GIC_SPI_START + 49)
+#define TV_ENC_IRQ				(GIC_SPI_START + 50)
+#define SMMU_VPE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 51)
+#define SMMU_VPE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 52)
+#define SMMU_VFE_CB_SC_SECURE_IRQ		(GIC_SPI_START + 53)
+#define SMMU_VFE_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 54)
+#define SMMU_VCODEC_B_CB_SC_SECURE_IRQ		(GIC_SPI_START + 55)
+#define SMMU_VCODEC_B_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 56)
+#define SMMU_VCODEC_A_CB_SC_SECURE_IRQ		(GIC_SPI_START + 57)
+#define SMMU_VCODEC_A_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 58)
+#define SMMU_ROT_CB_SC_SECURE_IRQ		(GIC_SPI_START + 59)
+#define SMMU_ROT_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 60)
+#define SMMU_MDP1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 61)
+#define SMMU_MDP1_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 62)
+#define SMMU_MDP0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 63)
+#define SMMU_MDP0_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 64)
+#define SMMU_JPEGD_CB_SC_SECURE_IRQ		(GIC_SPI_START + 65)
+#define SMMU_JPEGD_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 66)
+#define SMMU_IJPEG_CB_SC_SECURE_IRQ		(GIC_SPI_START + 67)
+#define SMMU_IJPEG_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 68)
+#define SMMU_GFX3D_CB_SC_SECURE_IRQ		(GIC_SPI_START + 69)
+#define SMMU_GFX3D_CB_SC_NON_SECURE_IRQ		(GIC_SPI_START + 70)
+#define SMMU_GFX2D0_CB_SC_SECURE_IRQ		(GIC_SPI_START + 71)
+#define SMMU_GFX2D0_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 72)
+#define ROT_IRQ					(GIC_SPI_START + 73)
+#define MMSS_FABRIC_IRQ				(GIC_SPI_START + 74)
+#define MDP_IRQ					(GIC_SPI_START + 75)
+#define JPEGD_IRQ				(GIC_SPI_START + 76)
+#define JPEG_IRQ				(GIC_SPI_START + 77)
+#define MMSS_IMEM_IRQ				(GIC_SPI_START + 78)
+#define HDMI_IRQ				(GIC_SPI_START + 79)
+#define GFX3D_IRQ				(GIC_SPI_START + 80)
+#define GFX2D0_IRQ				(GIC_SPI_START + 81)
+#define DSI1_IRQ				(GIC_SPI_START + 82)
+#define CSI_1_IRQ				(GIC_SPI_START + 83)
+#define CSI_0_IRQ				(GIC_SPI_START + 84)
+#define LPASS_SCSS_AUDIO_IF_OUT0_IRQ		(GIC_SPI_START + 85)
+#define LPASS_SCSS_MIDI_IRQ			(GIC_SPI_START + 86)
+#define LPASS_Q6SS_WDOG_EXPIRED			(GIC_SPI_START + 87)
+#define LPASS_SCSS_GP_LOW_IRQ			(GIC_SPI_START + 88)
+#define LPASS_SCSS_GP_MEDIUM_IRQ		(GIC_SPI_START + 89)
+#define LPASS_SCSS_GP_HIGH_IRQ			(GIC_SPI_START + 90)
+#define TOP_IMEM_IRQ				(GIC_SPI_START + 91)
+#define FABRIC_SYS_IRQ				(GIC_SPI_START + 92)
+#define FABRIC_APPS_IRQ				(GIC_SPI_START + 93)
+#define USB1_HS_BAM_IRQ				(GIC_SPI_START + 94)
+#define SDC4_BAM_IRQ				(GIC_SPI_START + 95)
+#define SDC3_BAM_IRQ				(GIC_SPI_START + 96)
+#define SDC2_BAM_IRQ				(GIC_SPI_START + 97)
+#define SDC1_BAM_IRQ				(GIC_SPI_START + 98)
+#define FABRIC_SPS_IRQ				(GIC_SPI_START + 99)
+#define USB1_HS_IRQ				(GIC_SPI_START + 100)
+#define SDC4_IRQ_0				(GIC_SPI_START + 101)
+#define SDC3_IRQ_0				(GIC_SPI_START + 102)
+#define SDC2_IRQ_0				(GIC_SPI_START + 103)
+#define SDC1_IRQ_0				(GIC_SPI_START + 104)
+#define SPS_BAM_DMA_IRQ				(GIC_SPI_START + 105)
+#define SPS_SEC_VIOL_IRQ			(GIC_SPI_START + 106)
+#define SPS_MTI_0				(GIC_SPI_START + 107)
+#define SPS_MTI_1				(GIC_SPI_START + 108)
+#define SPS_MTI_2				(GIC_SPI_START + 109)
+#define SPS_MTI_3				(GIC_SPI_START + 110)
+#define SPS_MTI_4				(GIC_SPI_START + 111)
+#define SPS_MTI_5				(GIC_SPI_START + 112)
+#define SPS_MTI_6				(GIC_SPI_START + 113)
+#define SPS_MTI_7				(GIC_SPI_START + 114)
+#define SPS_MTI_8				(GIC_SPI_START + 115)
+#define SPS_MTI_9				(GIC_SPI_START + 116)
+#define SPS_MTI_10				(GIC_SPI_START + 117)
+#define SPS_MTI_11				(GIC_SPI_START + 118)
+#define SPS_MTI_12				(GIC_SPI_START + 119)
+#define SPS_MTI_13				(GIC_SPI_START + 120)
+#define SPS_MTI_14				(GIC_SPI_START + 121)
+#define SPS_MTI_15				(GIC_SPI_START + 122)
+#define SPS_MTI_16				(GIC_SPI_START + 123)
+#define SPS_MTI_17				(GIC_SPI_START + 124)
+#define SPS_MTI_18				(GIC_SPI_START + 125)
+#define SPS_MTI_19				(GIC_SPI_START + 126)
+#define SPS_MTI_20				(GIC_SPI_START + 127)
+#define SPS_MTI_21				(GIC_SPI_START + 128)
+#define SPS_MTI_22				(GIC_SPI_START + 129)
+#define SPS_MTI_23				(GIC_SPI_START + 130)
+#define SPS_MTI_24				(GIC_SPI_START + 131)
+#define SPS_MTI_25				(GIC_SPI_START + 132)
+#define SPS_MTI_26				(GIC_SPI_START + 133)
+#define SPS_MTI_27				(GIC_SPI_START + 134)
+#define SPS_MTI_28				(GIC_SPI_START + 135)
+#define SPS_MTI_29				(GIC_SPI_START + 136)
+#define SPS_MTI_30				(GIC_SPI_START + 137)
+#define SPS_MTI_31				(GIC_SPI_START + 138)
+#define CSIPHY_4LN_IRQ				(GIC_SPI_START + 139)
+#define CSIPHY_2LN_IRQ				(GIC_SPI_START + 140)
+#define USB2_IRQ				(GIC_SPI_START + 141)
+#define USB1_IRQ				(GIC_SPI_START + 142)
+#define TSSC_SSBI_IRQ				(GIC_SPI_START + 143)
+#define TSSC_SAMPLE_IRQ				(GIC_SPI_START + 144)
+#define TSSC_PENUP_IRQ				(GIC_SPI_START + 145)
+#define GSBI1_UARTDM_IRQ			(GIC_SPI_START + 146)
+#define GSBI1_QUP_IRQ				(GIC_SPI_START + 147)
+#define GSBI2_UARTDM_IRQ			(GIC_SPI_START + 148)
+#define GSBI2_QUP_IRQ			        (GIC_SPI_START + 149)
+#define GSBI3_UARTDM_IRQ			(GIC_SPI_START + 150)
+#define GSBI3_QUP_IRQ				(GIC_SPI_START + 151)
+#define GSBI4_UARTDM_IRQ			(GIC_SPI_START + 152)
+#define GSBI4_QUP_IRQ				(GIC_SPI_START + 153)
+#define GSBI5_UARTDM_IRQ			(GIC_SPI_START + 154)
+#define GSBI5_QUP_IRQ				(GIC_SPI_START + 155)
+#define GSBI6_UARTDM_IRQ			(GIC_SPI_START + 156)
+#define GSBI6_QUP_IRQ				(GIC_SPI_START + 157)
+#define GSBI7_UARTDM_IRQ			(GIC_SPI_START + 158)
+#define GSBI7_QUP_IRQ				(GIC_SPI_START + 159)
+#define GSBI8_UARTDM_IRQ			(GIC_SPI_START + 160)
+#define GSBI8_QUP_IRQ				(GIC_SPI_START + 161)
+#define TSIF_TSPP_IRQ				(GIC_SPI_START + 162)
+#define TSIF_BAM_IRQ				(GIC_SPI_START + 163)
+#define TSIF2_IRQ				(GIC_SPI_START + 164)
+#define TSIF1_IRQ				(GIC_SPI_START + 165)
+#define DSI2_IRQ				(GIC_SPI_START + 166)
+#define ISPIF_IRQ				(GIC_SPI_START + 167)
+#define MSMC_SC_SEC_TMR_IRQ			(GIC_SPI_START + 168)
+#define MSMC_SC_SEC_WDOG_BARK_IRQ		(GIC_SPI_START + 169)
+#define INT_ADM0_SCSS_0_IRQ			(GIC_SPI_START + 170)
+#define INT_ADM0_SCSS_1_IRQ			(GIC_SPI_START + 171)
+#define INT_ADM0_SCSS_2_IRQ			(GIC_SPI_START + 172)
+#define INT_ADM0_SCSS_3_IRQ			(GIC_SPI_START + 173)
+#define CC_SCSS_WDT1CPU1BITEEXPIRED		(GIC_SPI_START + 174)
+#define CC_SCSS_WDT1CPU0BITEEXPIRED		(GIC_SPI_START + 175)
+#define CC_SCSS_WDT0CPU1BITEEXPIRED		(GIC_SPI_START + 176)
+#define CC_SCSS_WDT0CPU0BITEEXPIRED		(GIC_SPI_START + 177)
+#define TSENS_UPPER_LOWER_INT			(GIC_SPI_START + 178)
+#define SSBI2_2_SC_CPU1_SECURE_INT		(GIC_SPI_START + 179)
+#define SSBI2_2_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 180)
+#define SSBI2_1_SC_CPU1_SECURE_INT		(GIC_SPI_START + 181)
+#define SSBI2_1_SC_CPU1_NON_SECURE_INT		(GIC_SPI_START + 182)
+#define XPU_SUMMARY_IRQ				(GIC_SPI_START + 183)
+#define BUS_EXCEPTION_SUMMARY_IRQ		(GIC_SPI_START + 184)
+#define HSDDRX_EBI1CH0_IRQ			(GIC_SPI_START + 185)
+#define HSDDRX_EBI1CH1_IRQ			(GIC_SPI_START + 186)
+#define SDC5_BAM_IRQ				(GIC_SPI_START + 187)
+#define SDC5_IRQ_0				(GIC_SPI_START + 188)
+#define GSBI9_UARTDM_IRQ			(GIC_SPI_START + 189)
+#define GSBI9_QUP_IRQ				(GIC_SPI_START + 190)
+#define GSBI10_UARTDM_IRQ			(GIC_SPI_START + 191)
+#define GSBI10_QUP_IRQ				(GIC_SPI_START + 192)
+#define GSBI11_UARTDM_IRQ			(GIC_SPI_START + 193)
+#define GSBI11_QUP_IRQ				(GIC_SPI_START + 194)
+#define GSBI12_UARTDM_IRQ			(GIC_SPI_START + 195)
+#define GSBI12_QUP_IRQ				(GIC_SPI_START + 196)
+#define RIVA_APSS_LTECOEX_IRQ			(GIC_SPI_START + 197)
+#define RIVA_APSS_SPARE_IRQ			(GIC_SPI_START + 198)
+#define RIVA_APSS_WDOG_BITE_RESET_RDY_IRQ	(GIC_SPI_START + 199)
+#define RIVA_ASS_RESET_DONE_IRQ			(GIC_SPI_START + 200)
+#define RIVA_APSS_ASIC_IRQ			(GIC_SPI_START + 201)
+#define RIVA_APPS_WLAN_RX_DATA_AVAIL_IRQ	(GIC_SPI_START + 202)
+#define RIVA_APPS_WLAN_DATA_XFER_DONE_IRQ	(GIC_SPI_START + 203)
+#define RIVA_APPS_WLAM_SMSM_IRQ			(GIC_SPI_START + 204)
+#define RIVA_APPS_LOG_CTRL_IRQ			(GIC_SPI_START + 205)
+#define RIVA_APPS_FM_CTRL_IRQ			(GIC_SPI_START + 206)
+#define RIVA_APPS_HCI_IRQ			(GIC_SPI_START + 207)
+#define RIVA_APPS_WLAN_CTRL_IRQ			(GIC_SPI_START + 208)
+#define A2_BAM_IRQ				(GIC_SPI_START + 209)
+#define SMMU_GFX2D1_CB_SC_SECURE_IRQ		(GIC_SPI_START + 210)
+#define SMMU_GFX2D1_CB_SC_NON_SECURE_IRQ	(GIC_SPI_START + 211)
+#define GFX2D1_IRQ				(GIC_SPI_START + 212)
+#define PPSS_WDOG_TIMER_IRQ			(GIC_SPI_START + 213)
+#define SPS_SLIMBUS_CORE_EE0_IRQ		(GIC_SPI_START + 214)
+#define SPS_SLIMBUS_BAM_EE0_IRQ			(GIC_SPI_START + 215)
+#define QDSS_ETB_IRQ				(GIC_SPI_START + 216)
+#define QDSS_CTI2KPSS_CPU1_IRQ			(GIC_SPI_START + 217)
+#define QDSS_CTI2KPSS_CPU0_IRQ			(GIC_SPI_START + 218)
+#define TLMM_APCC_DIR_CONN_IRQ_16		(GIC_SPI_START + 219)
+#define TLMM_APCC_DIR_CONN_IRQ_17		(GIC_SPI_START + 220)
+#define TLMM_APCC_DIR_CONN_IRQ_18		(GIC_SPI_START + 221)
+#define TLMM_APCC_DIR_CONN_IRQ_19		(GIC_SPI_START + 222)
+#define TLMM_APCC_DIR_CONN_IRQ_20		(GIC_SPI_START + 223)
+#define TLMM_APCC_DIR_CONN_IRQ_21		(GIC_SPI_START + 224)
+#define PM8921_SEC_IRQ_104			(GIC_SPI_START + 225)
+#define PM8018_SEC_IRQ_107			(GIC_SPI_START + 226)
+
+/* For now, use the maximum number of interrupts until a pending GIC issue
+ * is sorted out */
+#define NR_MSM_IRQS 1020
+#define NR_BOARD_IRQS 0
+#define NR_GPIO_IRQS 0
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs-8x50.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs-8x50.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs-8x50.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs-8x50.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,30 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 
 #ifndef __ASM_ARCH_MSM_IRQS_8XXX_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,9 @@
 #include "sirc.h"
 #elif defined(CONFIG_ARCH_MSM8X60)
 #include "irqs-8x60.h"
+#elif defined(CONFIG_ARCH_MSM8960)
+/* TODO: Make these not generic. */
+#include "irqs-8960.h"
 #elif defined(CONFIG_ARCH_MSM_ARM11)
 #include "irqs-7x00.h"
 #else
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,15 +18,17 @@
 
 /* physical offset of RAM */
 #if defined(CONFIG_ARCH_QSD8X50) && defined(CONFIG_MSM_SOC_REV_A)
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 #elif defined(CONFIG_ARCH_QSD8X50)
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #elif defined(CONFIG_ARCH_MSM7X30)
-#define PHYS_OFFSET		UL(0x00200000)
+#define PLAT_PHYS_OFFSET		UL(0x00200000)
 #elif defined(CONFIG_ARCH_MSM8X60)
-#define PHYS_OFFSET		UL(0x40200000)
+#define PLAT_PHYS_OFFSET		UL(0x40200000)
+#elif defined(CONFIG_ARCH_MSM8960)
+#define PLAT_PHYS_OFFSET		UL(0x40200000)
 #else
-#define PHYS_OFFSET		UL(0x10000000)
+#define PLAT_PHYS_OFFSET		UL(0x10000000)
 #endif
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/mmc.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/mmc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/mmc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/mmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,12 +15,23 @@
 	int num_funcs;
 };
 
+struct msm_mmc_gpio {
+	unsigned no;
+	const char *name;
+};
+
+struct msm_mmc_gpio_data {
+	struct msm_mmc_gpio *gpio;
+	u8 size;
+};
+
 struct msm_mmc_platform_data {
 	unsigned int ocr_mask;			/* available voltages */
 	u32 (*translate_vdd)(struct device *, unsigned int);
 	unsigned int (*status)(struct device *);
 	struct embedded_sdio_data *embedded_sdio;
 	int (*register_status_notify)(void (*callback)(int card_present, void *dev_id), void *dev_id);
+	struct msm_mmc_gpio_data *gpio_data;
 };
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x00.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,7 @@
 /* arch/arm/mach-msm/include/mach/msm_iomap.h
  *
  * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -47,13 +48,8 @@
 #define MSM_VIC_PHYS          0xC0000000
 #define MSM_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xE0001000)
-#define MSM_CSR_PHYS          0xC0100000
-#define MSM_CSR_SIZE          SZ_4K
-
-#define MSM_GPT_PHYS          MSM_CSR_PHYS
-#define MSM_GPT_BASE          MSM_CSR_BASE
-#define MSM_GPT_SIZE          SZ_4K
+#define MSM7X00_CSR_PHYS      0xC0100000
+#define MSM7X00_CSR_SIZE      SZ_4K
 
 #define MSM_DMOV_BASE         IOMEM(0xE0002000)
 #define MSM_DMOV_PHYS         0xA9700000
@@ -130,10 +126,4 @@
 #define MSM_AD5_SIZE          (SZ_1M*13)
 
 
-#if defined(CONFIG_ARCH_MSM7X30)
-#define MSM_GCC_BASE          IOMEM(0xF8009000)
-#define MSM_GCC_PHYS          0xC0182000
-#define MSM_GCC_SIZE          SZ_4K
-#endif
-
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-7x30.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -39,16 +39,8 @@
 #define MSM_VIC_PHYS          0xC0080000
 #define MSM_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xE0001000)
-#define MSM_CSR_PHYS          0xC0100000
-#define MSM_CSR_SIZE          SZ_4K
-
-#define MSM_TMR_PHYS          MSM_CSR_PHYS
-#define MSM_TMR_BASE          MSM_CSR_BASE
-#define MSM_TMR_SIZE          SZ_4K
-
-#define MSM_GPT_BASE 	      (MSM_TMR_BASE + 0x4)
-#define MSM_DGT_BASE 	      (MSM_TMR_BASE + 0x24)
+#define MSM7X30_CSR_PHYS      0xC0100000
+#define MSM7X30_CSR_SIZE      SZ_4K
 
 #define MSM_DMOV_BASE         IOMEM(0xE0002000)
 #define MSM_DMOV_PHYS         0xAC400000
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8960.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8960.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8960.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8960.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2007 Google, Inc.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+ * Author: Brian Swetland <swetland@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ *
+ * The MSM peripherals are spread all over across 768MB of physical
+ * space, which makes just having a simple IO_ADDRESS macro to slide
+ * them into the right virtual location rough.  Instead, we will
+ * provide a master phys->virt mapping for peripherals here.
+ *
+ */
+
+#ifndef __ASM_ARCH_MSM_IOMAP_8960_H
+#define __ASM_ARCH_MSM_IOMAP_8960_H
+
+/* Physical base address and size of peripherals.
+ * Ordered by the virtual base addresses they will be mapped at.
+ *
+ * If you add or remove entries here, you'll want to edit the
+ * msm_io_desc array in arch/arm/mach-msm/io.c to reflect your
+ * changes.
+ *
+ */
+
+
+#define MSM8960_QGIC_DIST_PHYS	0x02000000
+#define MSM8960_QGIC_DIST_SIZE	SZ_4K
+
+#define MSM8960_QGIC_CPU_PHYS	0x02002000
+#define MSM8960_QGIC_CPU_SIZE	SZ_4K
+
+#define MSM8960_TMR_PHYS	0x0200A000
+#define MSM8960_TMR_SIZE	SZ_4K
+
+#define MSM8960_TMR0_PHYS	0x0208A000
+#define MSM8960_TMR0_SIZE	SZ_4K
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x50.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011 Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -39,16 +39,8 @@
 #define MSM_VIC_PHYS          0xAC000000
 #define MSM_VIC_SIZE          SZ_4K
 
-#define MSM_CSR_BASE          IOMEM(0xE0001000)
-#define MSM_CSR_PHYS          0xAC100000
-#define MSM_CSR_SIZE          SZ_4K
-
-#define MSM_TMR_PHYS          MSM_CSR_PHYS
-#define MSM_TMR_BASE          MSM_CSR_BASE
-#define MSM_TMR_SIZE          SZ_4K
-
-#define MSM_GPT_BASE          MSM_TMR_BASE
-#define MSM_DGT_BASE          (MSM_TMR_BASE + 0x10)
+#define QSD8X50_CSR_PHYS      0xAC100000
+#define QSD8X50_CSR_SIZE      SZ_4K
 
 #define MSM_DMOV_BASE         IOMEM(0xE0002000)
 #define MSM_DMOV_PHYS         0xA9700000
@@ -132,16 +124,16 @@
 #define MSM_UART2DM_PHYS      0xA0900000
 
 
-#define MSM_SDC1_PHYS          0xA0400000
+#define MSM_SDC1_PHYS          0xA0300000
 #define MSM_SDC1_SIZE          SZ_4K
 
-#define MSM_SDC2_PHYS          0xA0500000
+#define MSM_SDC2_PHYS          0xA0400000
 #define MSM_SDC2_SIZE          SZ_4K
 
-#define MSM_SDC3_PHYS          0xA0600000
+#define MSM_SDC3_PHYS          0xA0500000
 #define MSM_SDC3_SIZE           SZ_4K
 
-#define MSM_SDC4_PHYS          0xA0700000
+#define MSM_SDC4_PHYS          0xA0600000
 #define MSM_SDC4_SIZE          SZ_4K
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap-8x60.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -35,13 +35,11 @@
  *
  */
 
-#define MSM_QGIC_DIST_BASE	IOMEM(0xF0000000)
-#define MSM_QGIC_DIST_PHYS	0x02080000
-#define MSM_QGIC_DIST_SIZE	SZ_4K
+#define MSM8X60_QGIC_DIST_PHYS	0x02080000
+#define MSM8X60_QGIC_DIST_SIZE	SZ_4K
 
-#define MSM_QGIC_CPU_BASE	IOMEM(0xF0001000)
-#define MSM_QGIC_CPU_PHYS	0x02081000
-#define MSM_QGIC_CPU_SIZE	SZ_4K
+#define MSM8X60_QGIC_CPU_PHYS	0x02081000
+#define MSM8X60_QGIC_CPU_SIZE	SZ_4K
 
 #define MSM_ACC_BASE		IOMEM(0xF0002000)
 #define MSM_ACC_PHYS		0x02001000
@@ -58,51 +56,10 @@
 #define MSM_SHARED_RAM_BASE	IOMEM(0xF0100000)
 #define MSM_SHARED_RAM_SIZE	SZ_1M
 
-#define MSM_TMR_BASE		IOMEM(0xF0200000)
-#define MSM_TMR_PHYS		0x02000000
-#define MSM_TMR_SIZE		SZ_4K
-
-#define MSM_TMR0_BASE		IOMEM(0xF0201000)
-#define MSM_TMR0_PHYS		0x02040000
-#define MSM_TMR0_SIZE		SZ_4K
-
-#define MSM_GPT_BASE		(MSM_TMR_BASE + 0x4)
-#define MSM_DGT_BASE		(MSM_TMR_BASE + 0x24)
-
-#define MSM_IOMMU_JPEGD_PHYS	0x07300000
-#define MSM_IOMMU_JPEGD_SIZE	SZ_1M
-
-#define MSM_IOMMU_VPE_PHYS	0x07400000
-#define MSM_IOMMU_VPE_SIZE	SZ_1M
-
-#define MSM_IOMMU_MDP0_PHYS	0x07500000
-#define MSM_IOMMU_MDP0_SIZE	SZ_1M
-
-#define MSM_IOMMU_MDP1_PHYS	0x07600000
-#define MSM_IOMMU_MDP1_SIZE	SZ_1M
-
-#define MSM_IOMMU_ROT_PHYS	0x07700000
-#define MSM_IOMMU_ROT_SIZE	SZ_1M
-
-#define MSM_IOMMU_IJPEG_PHYS	0x07800000
-#define MSM_IOMMU_IJPEG_SIZE	SZ_1M
-
-#define MSM_IOMMU_VFE_PHYS	0x07900000
-#define MSM_IOMMU_VFE_SIZE	SZ_1M
-
-#define MSM_IOMMU_VCODEC_A_PHYS	0x07A00000
-#define MSM_IOMMU_VCODEC_A_SIZE	SZ_1M
-
-#define MSM_IOMMU_VCODEC_B_PHYS	0x07B00000
-#define MSM_IOMMU_VCODEC_B_SIZE	SZ_1M
-
-#define MSM_IOMMU_GFX3D_PHYS	0x07C00000
-#define MSM_IOMMU_GFX3D_SIZE	SZ_1M
-
-#define MSM_IOMMU_GFX2D0_PHYS	0x07D00000
-#define MSM_IOMMU_GFX2D0_SIZE	SZ_1M
+#define MSM8X60_TMR_PHYS	0x02000000
+#define MSM8X60_TMR_SIZE	SZ_4K
 
-#define MSM_IOMMU_GFX2D1_PHYS	0x07E00000
-#define MSM_IOMMU_GFX2D1_SIZE	SZ_1M
+#define MSM8X60_TMR0_PHYS	0x02040000
+#define MSM8X60_TMR0_SIZE	SZ_4K
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/msm_iomap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/msm_iomap.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -53,6 +53,13 @@
 #include "msm_iomap-7x00.h"
 #endif
 
+#include "msm_iomap-8960.h"
 
+/* Virtual addressses shared across all MSM targets. */
+#define MSM_CSR_BASE		IOMEM(0xE0001000)
+#define MSM_QGIC_DIST_BASE	IOMEM(0xF0000000)
+#define MSM_QGIC_CPU_BASE	IOMEM(0xF0001000)
+#define MSM_TMR_BASE		IOMEM(0xF0200000)
+#define MSM_TMR0_BASE		IOMEM(0xF0201000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/sirc.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/sirc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/sirc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/sirc.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,30 +1,13 @@
 /* Copyright (c) 2008-2009, Code Aurora Forum. 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 Code Aurora Forum, Inc. 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 "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 
 #ifndef __ASM_ARCH_MSM_SIRC_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/smp.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/smp.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/include/mach/smp.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,29 +1,13 @@
 /* Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora 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, FITNESS FOR A PARTICULAR PURPOSE AND
- * NON-INFRINGEMENT 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.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only 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.
  */
 
 #ifndef __ASM_ARCH_MSM_SMP_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/io.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/io.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/io.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  * MSM7K, QSD io support
  *
  * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
  * Author: Brian Swetland <swetland@google.com>
  *
  * This software is licensed under the terms of the GNU General Public
@@ -28,19 +28,20 @@
 
 #include <mach/board.h>
 
-#define MSM_DEVICE(name) { \
+#define MSM_CHIP_DEVICE(name, chip) {			      \
 		.virtual = (unsigned long) MSM_##name##_BASE, \
-		.pfn = __phys_to_pfn(MSM_##name##_PHYS), \
-		.length = MSM_##name##_SIZE, \
+		.pfn = __phys_to_pfn(chip##_##name##_PHYS), \
+		.length = chip##_##name##_SIZE, \
 		.type = MT_DEVICE_NONSHARED, \
 	 }
 
+#define MSM_DEVICE(name) MSM_CHIP_DEVICE(name, MSM)
+
 #if defined(CONFIG_ARCH_MSM7X00A) || defined(CONFIG_ARCH_MSM7X27) \
 	|| defined(CONFIG_ARCH_MSM7X25)
 static struct map_desc msm_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(GPT),
+	MSM_CHIP_DEVICE(CSR, MSM7X00),
 	MSM_DEVICE(DMOV),
 	MSM_DEVICE(GPIO1),
 	MSM_DEVICE(GPIO2),
@@ -73,8 +74,7 @@
 #ifdef CONFIG_ARCH_QSD8X50
 static struct map_desc qsd8x50_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(TMR),
+	MSM_CHIP_DEVICE(CSR, QSD8X50),
 	MSM_DEVICE(DMOV),
 	MSM_DEVICE(GPIO1),
 	MSM_DEVICE(GPIO2),
@@ -102,10 +102,10 @@
 
 #ifdef CONFIG_ARCH_MSM8X60
 static struct map_desc msm8x60_io_desc[] __initdata = {
-	MSM_DEVICE(QGIC_DIST),
-	MSM_DEVICE(QGIC_CPU),
-	MSM_DEVICE(TMR),
-	MSM_DEVICE(TMR0),
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8X60),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8X60),
+	MSM_CHIP_DEVICE(TMR, MSM8X60),
+	MSM_CHIP_DEVICE(TMR0, MSM8X60),
 	MSM_DEVICE(ACC),
 	MSM_DEVICE(GCC),
 };
@@ -116,11 +116,24 @@
 }
 #endif /* CONFIG_ARCH_MSM8X60 */
 
+#ifdef CONFIG_ARCH_MSM8960
+static struct map_desc msm8960_io_desc[] __initdata = {
+	MSM_CHIP_DEVICE(QGIC_DIST, MSM8960),
+	MSM_CHIP_DEVICE(QGIC_CPU, MSM8960),
+	MSM_CHIP_DEVICE(TMR, MSM8960),
+	MSM_CHIP_DEVICE(TMR0, MSM8960),
+};
+
+void __init msm_map_msm8960_io(void)
+{
+	iotable_init(msm8960_io_desc, ARRAY_SIZE(msm8960_io_desc));
+}
+#endif /* CONFIG_ARCH_MSM8960 */
+
 #ifdef CONFIG_ARCH_MSM7X30
 static struct map_desc msm7x30_io_desc[] __initdata = {
 	MSM_DEVICE(VIC),
-	MSM_DEVICE(CSR),
-	MSM_DEVICE(TMR),
+	MSM_CHIP_DEVICE(CSR, MSM7X30),
 	MSM_DEVICE(DMOV),
 	MSM_DEVICE(GPIO1),
 	MSM_DEVICE(GPIO2),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/iommu.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/iommu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/iommu.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
@@ -26,6 +26,7 @@
 #include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/iommu.h>
+#include <linux/clk.h>
 
 #include <asm/cacheflush.h>
 #include <asm/sizes.h>
@@ -50,6 +51,30 @@
 	struct list_head list_attached;
 };
 
+static int __enable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+	int ret;
+
+	ret = clk_enable(drvdata->pclk);
+	if (ret)
+		goto fail;
+
+	if (drvdata->clk) {
+		ret = clk_enable(drvdata->clk);
+		if (ret)
+			clk_disable(drvdata->pclk);
+	}
+fail:
+	return ret;
+}
+
+static void __disable_clocks(struct msm_iommu_drvdata *drvdata)
+{
+	if (drvdata->clk)
+		clk_disable(drvdata->clk);
+	clk_disable(drvdata->pclk);
+}
+
 static int __flush_iotlb(struct iommu_domain *domain)
 {
 	struct msm_priv *priv = domain->priv;
@@ -77,9 +102,16 @@
 			BUG();
 
 		iommu_drvdata = dev_get_drvdata(ctx_drvdata->pdev->dev.parent);
+		BUG_ON(!iommu_drvdata);
+
+		ret = __enable_clocks(iommu_drvdata);
+		if (ret)
+			goto fail;
+
 		SET_CTX_TLBIALL(iommu_drvdata->base, ctx_drvdata->num, 0);
+		__disable_clocks(iommu_drvdata);
 	}
-
+fail:
 	return ret;
 }
 
@@ -105,7 +137,6 @@
 	SET_TLBLKCR(base, ctx, 0);
 	SET_PRRR(base, ctx, 0);
 	SET_NMRR(base, ctx, 0);
-	SET_CONTEXTIDR(base, ctx, 0);
 }
 
 static void __program_context(void __iomem *base, int ctx, phys_addr_t pgtable)
@@ -265,9 +296,14 @@
 			goto fail;
 		}
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
 	__program_context(iommu_drvdata->base, ctx_dev->num,
 			  __pa(priv->pgtable));
 
+	__disable_clocks(iommu_drvdata);
 	list_add(&(ctx_drvdata->attached_elm), &priv->list_attached);
 	ret = __flush_iotlb(domain);
 
@@ -303,7 +339,12 @@
 	if (ret)
 		goto fail;
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
 	__reset_context(iommu_drvdata->base, ctx_dev->num);
+	__disable_clocks(iommu_drvdata);
 	list_del_init(&ctx_drvdata->attached_elm);
 
 fail:
@@ -376,11 +417,11 @@
 		for (i = 0; i < 16; i++)
 			*(fl_pte+i) = (pa & 0xFF000000) | FL_SUPERSECTION |
 				  FL_AP_READ | FL_AP_WRITE | FL_TYPE_SECT |
-				  FL_SHARED | pgprot;
+				  FL_SHARED | FL_NG | pgprot;
 	}
 
 	if (len == SZ_1M)
-		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE |
+		*fl_pte = (pa & 0xFFF00000) | FL_AP_READ | FL_AP_WRITE | FL_NG |
 					    FL_TYPE_SECT | FL_SHARED | pgprot;
 
 	/* Need a 2nd level table */
@@ -405,7 +446,7 @@
 
 
 	if (len == SZ_4K)
-		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 |
+		*sl_pte = (pa & SL_BASE_MASK_SMALL) | SL_AP0 | SL_AP1 | SL_NG |
 					  SL_SHARED | SL_TYPE_SMALL | pgprot;
 
 	if (len == SZ_64K) {
@@ -413,7 +454,7 @@
 
 		for (i = 0; i < 16; i++)
 			*(sl_pte+i) = (pa & SL_BASE_MASK_LARGE) | SL_AP0 |
-				SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
+			    SL_NG | SL_AP1 | SL_SHARED | SL_TYPE_LARGE | pgprot;
 	}
 
 	ret = __flush_iotlb(domain);
@@ -532,9 +573,13 @@
 	base = iommu_drvdata->base;
 	ctx = ctx_drvdata->num;
 
+	ret = __enable_clocks(iommu_drvdata);
+	if (ret)
+		goto fail;
+
 	/* Invalidate context TLB */
 	SET_CTX_TLBIALL(base, ctx, 0);
-	SET_V2PPR_VA(base, ctx, va >> V2Pxx_VA_SHIFT);
+	SET_V2PPR(base, ctx, va & V2Pxx_VA);
 
 	par = GET_PAR(base, ctx);
 
@@ -547,6 +592,7 @@
 	if (GET_FAULT(base, ctx))
 		ret = 0;
 
+	__disable_clocks(iommu_drvdata);
 fail:
 	spin_unlock_irqrestore(&msm_iommu_lock, flags);
 	return ret;
@@ -590,7 +636,7 @@
 	struct msm_iommu_drvdata *drvdata = dev_id;
 	void __iomem *base;
 	unsigned int fsr;
-	int ncb, i;
+	int i, ret;
 
 	spin_lock(&msm_iommu_lock);
 
@@ -604,8 +650,11 @@
 	pr_err("Unexpected IOMMU page fault!\n");
 	pr_err("base = %08x\n", (unsigned int) base);
 
-	ncb = GET_NCB(base)+1;
-	for (i = 0; i < ncb; i++) {
+	ret = __enable_clocks(drvdata);
+	if (ret)
+		goto fail;
+
+	for (i = 0; i < drvdata->ncb; i++) {
 		fsr = GET_FSR(base, i);
 		if (fsr) {
 			pr_err("Fault occurred in context %d.\n", i);
@@ -614,6 +663,7 @@
 			SET_FSR(base, i, 0x4000000F);
 		}
 	}
+	__disable_clocks(drvdata);
 fail:
 	spin_unlock(&msm_iommu_lock);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/iommu_dev.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/iommu_dev.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/iommu_dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/iommu_dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2010-2011, Code Aurora Forum. 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 and
@@ -29,6 +29,7 @@
 
 #include <mach/iommu_hw-8xxx.h>
 #include <mach/iommu.h>
+#include <mach/clk.h>
 
 struct iommu_ctx_iter_data {
 	/* input */
@@ -84,9 +85,9 @@
 }
 EXPORT_SYMBOL(msm_iommu_get_ctx);
 
-static void msm_iommu_reset(void __iomem *base)
+static void msm_iommu_reset(void __iomem *base, int ncb)
 {
-	int ctx, ncb;
+	int ctx;
 
 	SET_RPUE(base, 0);
 	SET_RPUEIE(base, 0);
@@ -99,7 +100,6 @@
 	SET_GLOBAL_TLBIALL(base, 0);
 	SET_RPU_ACR(base, 0);
 	SET_TLBLKCRWE(base, 1);
-	ncb = GET_NCB(base)+1;
 
 	for (ctx = 0; ctx < ncb; ctx++) {
 		SET_BPRCOSH(base, ctx, 0);
@@ -130,117 +130,140 @@
 {
 	struct resource *r, *r2;
 	struct clk *iommu_clk;
+	struct clk *iommu_pclk;
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_dev *iommu_dev = pdev->dev.platform_data;
 	void __iomem *regs_base;
 	resource_size_t	len;
-	int ret = 0, ncb, nm2v, irq;
+	int ret, irq, par;
 
-	if (pdev->id != -1) {
-		drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
+	if (pdev->id == -1) {
+		msm_iommu_root_dev = pdev;
+		return 0;
+	}
 
-		if (!drvdata) {
-			ret = -ENOMEM;
-			goto fail;
-		}
+	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
 
-		if (!iommu_dev) {
-			ret = -ENODEV;
-			goto fail;
-		}
+	if (!drvdata) {
+		ret = -ENOMEM;
+		goto fail;
+	}
 
-		if (iommu_dev->clk_rate != 0) {
-			iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+	if (!iommu_dev) {
+		ret = -ENODEV;
+		goto fail;
+	}
 
-			if (IS_ERR(iommu_clk)) {
-				ret = -ENODEV;
-				goto fail;
-			}
+	iommu_pclk = clk_get(NULL, "smmu_pclk");
+	if (IS_ERR(iommu_pclk)) {
+		ret = -ENODEV;
+		goto fail;
+	}
 
-			if (iommu_dev->clk_rate > 0) {
-				ret = clk_set_rate(iommu_clk,
-							iommu_dev->clk_rate);
-				if (ret) {
-					clk_put(iommu_clk);
-					goto fail;
-				}
-			}
+	ret = clk_enable(iommu_pclk);
+	if (ret)
+		goto fail_enable;
 
-			ret = clk_enable(iommu_clk);
-			if (ret) {
-				clk_put(iommu_clk);
-				goto fail;
-			}
+	iommu_clk = clk_get(&pdev->dev, "iommu_clk");
+
+	if (!IS_ERR(iommu_clk))	{
+		if (clk_get_rate(iommu_clk) == 0)
+			clk_set_min_rate(iommu_clk, 1);
+
+		ret = clk_enable(iommu_clk);
+		if (ret) {
 			clk_put(iommu_clk);
+			goto fail_pclk;
 		}
+	} else
+		iommu_clk = NULL;
 
-		r = platform_get_resource_byname(pdev, IORESOURCE_MEM,
-						 "physbase");
-		if (!r) {
-			ret = -ENODEV;
-			goto fail;
-		}
+	r = platform_get_resource_byname(pdev, IORESOURCE_MEM, "physbase");
 
-		len = r->end - r->start + 1;
+	if (!r) {
+		ret = -ENODEV;
+		goto fail_clk;
+	}
 
-		r2 = request_mem_region(r->start, len, r->name);
-		if (!r2) {
-			pr_err("Could not request memory region: "
-			"start=%p, len=%d\n", (void *) r->start, len);
-			ret = -EBUSY;
-			goto fail;
-		}
+	len = resource_size(r);
 
-		regs_base = ioremap(r2->start, len);
+	r2 = request_mem_region(r->start, len, r->name);
+	if (!r2) {
+		pr_err("Could not request memory region: start=%p, len=%d\n",
+							(void *) r->start, len);
+		ret = -EBUSY;
+		goto fail_clk;
+	}
 
-		if (!regs_base) {
-			pr_err("Could not ioremap: start=%p, len=%d\n",
-				 (void *) r2->start, len);
-			ret = -EBUSY;
-			goto fail_mem;
-		}
+	regs_base = ioremap(r2->start, len);
 
-		irq = platform_get_irq_byname(pdev, "secure_irq");
-		if (irq < 0) {
-			ret = -ENODEV;
-			goto fail_io;
-		}
+	if (!regs_base) {
+		pr_err("Could not ioremap: start=%p, len=%d\n",
+			 (void *) r2->start, len);
+		ret = -EBUSY;
+		goto fail_mem;
+	}
 
-		mb();
+	irq = platform_get_irq_byname(pdev, "secure_irq");
+	if (irq < 0) {
+		ret = -ENODEV;
+		goto fail_io;
+	}
 
-		if (GET_IDR(regs_base) == 0) {
-			pr_err("Invalid IDR value detected\n");
-			ret = -ENODEV;
-			goto fail_io;
-		}
+	msm_iommu_reset(regs_base, iommu_dev->ncb);
 
-		ret = request_irq(irq, msm_iommu_fault_handler, 0,
-				"msm_iommu_secure_irpt_handler", drvdata);
-		if (ret) {
-			pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
-			goto fail_io;
-		}
+	SET_M(regs_base, 0, 1);
+	SET_PAR(regs_base, 0, 0);
+	SET_V2PCFG(regs_base, 0, 1);
+	SET_V2PPR(regs_base, 0, 0);
+	par = GET_PAR(regs_base, 0);
+	SET_V2PCFG(regs_base, 0, 0);
+	SET_M(regs_base, 0, 0);
 
-		msm_iommu_reset(regs_base);
-		drvdata->base = regs_base;
-		drvdata->irq = irq;
+	if (!par) {
+		pr_err("%s: Invalid PAR value detected\n", iommu_dev->name);
+		ret = -ENODEV;
+		goto fail_io;
+	}
 
-		nm2v = GET_NM2VCBMT((unsigned long) regs_base);
-		ncb = GET_NCB((unsigned long) regs_base);
+	ret = request_irq(irq, msm_iommu_fault_handler, 0,
+			"msm_iommu_secure_irpt_handler", drvdata);
+	if (ret) {
+		pr_err("Request IRQ %d failed with ret=%d\n", irq, ret);
+		goto fail_io;
+	}
 
-		pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
-			iommu_dev->name, regs_base, irq, ncb+1);
 
-		platform_set_drvdata(pdev, drvdata);
-	} else
-		msm_iommu_root_dev = pdev;
+	drvdata->pclk = iommu_pclk;
+	drvdata->clk = iommu_clk;
+	drvdata->base = regs_base;
+	drvdata->irq = irq;
+	drvdata->ncb = iommu_dev->ncb;
 
-	return 0;
+	pr_info("device %s mapped at %p, irq %d with %d ctx banks\n",
+		iommu_dev->name, regs_base, irq, iommu_dev->ncb);
+
+	platform_set_drvdata(pdev, drvdata);
+
+	if (iommu_clk)
+		clk_disable(iommu_clk);
+
+	clk_disable(iommu_pclk);
 
+	return 0;
 fail_io:
 	iounmap(regs_base);
 fail_mem:
 	release_mem_region(r->start, len);
+fail_clk:
+	if (iommu_clk) {
+		clk_disable(iommu_clk);
+		clk_put(iommu_clk);
+	}
+fail_pclk:
+	clk_disable(iommu_pclk);
+fail_enable:
+	clk_put(iommu_pclk);
 fail:
 	kfree(drvdata);
 	return ret;
@@ -252,7 +275,10 @@
 
 	drv = platform_get_drvdata(pdev);
 	if (drv) {
-		memset(drv, 0, sizeof(struct msm_iommu_drvdata));
+		if (drv->clk)
+			clk_put(drv->clk);
+		clk_put(drv->pclk);
+		memset(drv, 0, sizeof(*drv));
 		kfree(drv);
 		platform_set_drvdata(pdev, NULL);
 	}
@@ -264,7 +290,7 @@
 	struct msm_iommu_ctx_dev *c = pdev->dev.platform_data;
 	struct msm_iommu_drvdata *drvdata;
 	struct msm_iommu_ctx_drvdata *ctx_drvdata = NULL;
-	int i, ret = 0;
+	int i, ret;
 	if (!c || !pdev->dev.parent) {
 		ret = -EINVAL;
 		goto fail;
@@ -288,6 +314,18 @@
 	INIT_LIST_HEAD(&ctx_drvdata->attached_elm);
 	platform_set_drvdata(pdev, ctx_drvdata);
 
+	ret = clk_enable(drvdata->pclk);
+	if (ret)
+		goto fail;
+
+	if (drvdata->clk) {
+		ret = clk_enable(drvdata->clk);
+		if (ret) {
+			clk_disable(drvdata->pclk);
+			goto fail;
+		}
+	}
+
 	/* Program the M2V tables for this context */
 	for (i = 0; i < MAX_NUM_MIDS; i++) {
 		int mid = c->mids[i];
@@ -297,21 +335,27 @@
 		SET_M2VCBR_N(drvdata->base, mid, 0);
 		SET_CBACR_N(drvdata->base, c->num, 0);
 
-		/* Set VMID = MID */
-		SET_VMID(drvdata->base, mid, mid);
+		/* Set VMID = 0 */
+		SET_VMID(drvdata->base, mid, 0);
 
 		/* Set the context number for that MID to this context */
 		SET_CBNDX(drvdata->base, mid, c->num);
 
-		/* Set MID associated with this context bank */
-		SET_CBVMID(drvdata->base, c->num, mid);
+		/* Set MID associated with this context bank to 0*/
+		SET_CBVMID(drvdata->base, c->num, 0);
+
+		/* Set the ASID for TLB tagging for this context */
+		SET_CONTEXTIDR_ASID(drvdata->base, c->num, c->num);
 
 		/* Set security bit override to be Non-secure */
 		SET_NSCFG(drvdata->base, mid, 3);
 	}
 
-	pr_info("context device %s with bank index %d\n", c->name, c->num);
+	if (drvdata->clk)
+		clk_disable(drvdata->clk);
+	clk_disable(drvdata->pclk);
 
+	dev_info(&pdev->dev, "context %s using bank %d\n", c->name, c->num);
 	return 0;
 fail:
 	kfree(ctx_drvdata);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,11 +100,11 @@
 
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 		writel(readl(treg) | b, treg);
-		irq_desc[d->irq].handle_irq = handle_edge_irq;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	}
 	if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
 		writel(readl(treg) & (~b), treg);
-		irq_desc[d->irq].handle_irq = handle_level_irq;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	}
 	return 0;
 }
@@ -145,8 +145,7 @@
 	writel(1, VIC_INT_MASTEREN);
 
 	for (n = 0; n < NR_MSM_IRQS; n++) {
-		set_irq_chip(n, &msm_irq_chip);
-		set_irq_handler(n, handle_level_irq);
+		irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
 		set_irq_flags(n, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/irq-vic.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/irq-vic.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/irq-vic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/irq-vic.c	2011-05-19 00:06:34.000000000 -0400
@@ -313,11 +313,11 @@
 	type = msm_irq_shadow_reg[index].int_type;
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 		type |= b;
-		irq_desc[d->irq].handle_irq = handle_edge_irq;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	}
 	if (flow_type & (IRQF_TRIGGER_HIGH | IRQF_TRIGGER_LOW)) {
 		type &= ~b;
-		irq_desc[d->irq].handle_irq = handle_level_irq;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	}
 	writel(type, treg);
 	msm_irq_shadow_reg[index].int_type = type;
@@ -357,8 +357,7 @@
 	writel(3, VIC_INT_MASTEREN);
 
 	for (n = 0; n < NR_MSM_IRQS; n++) {
-		set_irq_chip(n, &msm_irq_chip);
-		set_irq_handler(n, handle_level_irq);
+		irq_set_chip_and_handler(n, &msm_irq_chip, handle_level_irq);
 		set_irq_flags(n, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-msm/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,16 @@
 	select CPU_V7
 	select MSM_V2_TLMM
 	select MSM_GPIOMUX
-	select IOMMU_API
+	select MSM_SCM if SMP
+
+config ARCH_MSM8960
+	bool "MSM8960"
+	select ARCH_MSM_SCORPIONMP
+	select MACH_MSM8960_SIM if (!MACH_MSM8960_RUMI3)
+	select ARM_GIC
+	select CPU_V7
+	select MSM_V2_TLMM
+	select MSM_GPIOMUX
 	select MSM_SCM if SMP
 
 endchoice
@@ -125,11 +134,35 @@
 	help
 	  Support for the Qualcomm MSM8x60 FFA eval board.
 
+config MACH_MSM8960_SIM
+	depends on ARCH_MSM8960
+	bool "MSM8960 Simulator"
+	help
+	  Support for the Qualcomm MSM8960 simulator.
+
+config MACH_MSM8960_RUMI3
+	depends on ARCH_MSM8960
+	bool "MSM8960 RUMI3"
+	help
+	  Support for the Qualcomm MSM8960 RUMI3 emulator.
+
 endmenu
 
+config MSM_IOMMU
+	bool "MSM IOMMU Support"
+	depends on ARCH_MSM8X60 || ARCH_MSM8960
+	select IOMMU_API
+	default n
+	help
+	  Support for the IOMMUs found on certain Qualcomm SOCs.
+	  These IOMMUs allow virtualization of the address space used by most
+	  cores within the multimedia subsystem.
+
+	  If unsure, say N here.
+
 config IOMMU_PGTABLES_L2
 	def_bool y
-	depends on ARCH_MSM8X60 && MMU && SMP && CPU_DCACHE_DISABLE=n
+	depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
 
 config MSM_DEBUG_UART
 	int
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-msm/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,21 +1,16 @@
 obj-y += io.o idle.o timer.o
-ifndef CONFIG_ARCH_MSM8X60
-obj-y += acpuclock-arm11.o
-obj-y += dma.o
-endif
+obj-y += clock.o
+obj-$(CONFIG_DEBUG_FS) += clock-debug.o
 
-ifdef CONFIG_MSM_VIC
-obj-y += irq-vic.o
-else
-ifndef CONFIG_ARCH_MSM8X60
-obj-y += irq.o
-endif
-endif
+obj-$(CONFIG_MSM_VIC) += irq-vic.o
+obj-$(CONFIG_MSM_IOMMU) += iommu.o iommu_dev.o devices-iommu.o
+
+obj-$(CONFIG_ARCH_MSM7X00A) += dma.o irq.o acpuclock-arm11.o
+obj-$(CONFIG_ARCH_MSM7X30) += dma.o
+obj-$(CONFIG_ARCH_QSD8X50) += dma.o sirc.o
 
-obj-$(CONFIG_ARCH_MSM8X60) += clock-dummy.o iommu.o iommu_dev.o devices-msm8x60-iommu.o
 obj-$(CONFIG_MSM_PROC_COMM) += proc_comm.o clock-pcom.o vreg.o
-obj-$(CONFIG_MSM_PROC_COMM) += clock.o
-obj-$(CONFIG_ARCH_QSD8X50) += sirc.o
+
 obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o
 obj-$(CONFIG_MSM_SMD) += last_radio_log.o
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
@@ -29,12 +24,16 @@
 obj-$(CONFIG_ARCH_MSM7X30) += board-msm7x30.o devices-msm7x30.o
 obj-$(CONFIG_ARCH_QSD8X50) += board-qsd8x50.o devices-qsd8x50.o
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60.o
+obj-$(CONFIG_ARCH_MSM8960) += board-msm8960.o devices-msm8960.o
 
-obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
+obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_QSD8X50) += gpiomux-8x50.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM8X60) += gpiomux-8x60.o gpiomux-v2.o gpiomux.o
 ifdef CONFIG_MSM_V2_TLMM
+ifndef CONFIG_ARCH_MSM8960
+# TODO: TLMM Mapping issues need to be resolved
 obj-y	+= gpio-v2.o
+endif
 else
 obj-y	+= gpio.o
 endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/scm-boot.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/scm-boot.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/scm-boot.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/scm-boot.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,29 +1,13 @@
 /* Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora Forum, Inc. nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 #ifndef __MACH_SCM_BOOT_H
 #define __MACH_SCM_BOOT_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/scm.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/scm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/scm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/scm.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
  * @id: command to be executed
  * @buf: buffer returned from scm_get_command_buffer()
  *
- * An SCM command is layed out in memory as follows:
+ * An SCM command is laid out in memory as follows:
  *
  *	------------------- <--- struct scm_command
  *	| command header  |
@@ -174,15 +174,18 @@
 	register u32 r0 asm("r0") = 1;
 	register u32 r1 asm("r1") = (u32)&context_id;
 	register u32 r2 asm("r2") = cmd_addr;
-	asm(
-		__asmeq("%0", "r0")
-		__asmeq("%1", "r0")
-		__asmeq("%2", "r1")
-		__asmeq("%3", "r2")
-		"smc	#0	@ switch to secure world\n"
-		: "=r" (r0)
-		: "r" (r0), "r" (r1), "r" (r2)
-		: "r3");
+	do {
+		asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r0")
+			__asmeq("%2", "r1")
+			__asmeq("%3", "r2")
+			"smc	#0	@ switch to secure world\n"
+			: "=r" (r0)
+			: "r" (r0), "r" (r1), "r" (r2)
+			: "r3");
+	} while (r0 == SCM_INTERRUPTED);
+
 	return r0;
 }
 
@@ -197,13 +200,9 @@
 	 * side in the buffer.
 	 */
 	flush_cache_all();
-	do {
-		ret = smc(cmd_addr);
-		if (ret < 0) {
-			ret = scm_remap_error(ret);
-			break;
-		}
-	} while (ret == SCM_INTERRUPTED);
+	ret = smc(cmd_addr);
+	if (ret < 0)
+		ret = scm_remap_error(ret);
 
 	return ret;
 }
@@ -264,21 +263,28 @@
 {
 	int context_id;
 	static u32 version = -1;
-	register u32 r0 asm("r0") = 0x1 << 8;
-	register u32 r1 asm("r1") = (u32)&context_id;
+	register u32 r0 asm("r0");
+	register u32 r1 asm("r1");
 
 	if (version != -1)
 		return version;
 
 	mutex_lock(&scm_lock);
-	asm(
-		__asmeq("%0", "r1")
-		__asmeq("%1", "r0")
-		__asmeq("%2", "r1")
-		"smc	#0	@ switch to secure world\n"
-		: "=r" (r1)
-		: "r" (r0), "r" (r1)
-		: "r2", "r3");
+
+	r0 = 0x1 << 8;
+	r1 = (u32)&context_id;
+	do {
+		asm volatile(
+			__asmeq("%0", "r0")
+			__asmeq("%1", "r1")
+			__asmeq("%2", "r0")
+			__asmeq("%3", "r1")
+			"smc	#0	@ switch to secure world\n"
+			: "=r" (r0), "=r" (r1)
+			: "r" (r0), "r" (r1)
+			: "r2", "r3");
+	} while (r0 == SCM_INTERRUPTED);
+
 	version = r1;
 	mutex_unlock(&scm_lock);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/scm.h linux-libre-2.6.39-gnu/arch/arm/mach-msm/scm.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/scm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/scm.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,29 +1,13 @@
 /* Copyright (c) 2010, Code Aurora Forum. 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 Code Aurora Forum, Inc. nor the names of its
- *       contributors may be used to endorse or promote products derived
- *       from this software without specific prior written permission.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
  *
- * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
- * 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.
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
  */
 #ifndef __MACH_SCM_H
 #define __MACH_SCM_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/sirc.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/sirc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/sirc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/sirc.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,10 +105,10 @@
 	val = readl(sirc_regs.int_type);
 	if (flow_type & (IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING)) {
 		val |= mask;
-		irq_desc[d->irq].handle_irq = handle_edge_irq;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	} else {
 		val &= ~mask;
-		irq_desc[d->irq].handle_irq = handle_level_irq;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	}
 
 	writel(val, sirc_regs.int_type);
@@ -158,15 +158,14 @@
 	wake_enable = 0;
 
 	for (i = FIRST_SIRC_IRQ; i < LAST_SIRC_IRQ; i++) {
-		set_irq_chip(i, &sirc_irq_chip);
-		set_irq_handler(i, handle_edge_irq);
+		irq_set_chip_and_handler(i, &sirc_irq_chip, handle_edge_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(sirc_reg_table); i++) {
-		set_irq_chained_handler(sirc_reg_table[i].cascade_irq,
+		irq_set_chained_handler(sirc_reg_table[i].cascade_irq,
 					sirc_irq_handler);
-		set_irq_wake(sirc_reg_table[i].cascade_irq, 1);
+		irq_set_irq_wake(sirc_reg_table[i].cascade_irq, 1);
 	}
 	return;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-msm/timer.c linux-libre-2.6.39-gnu/arch/arm/mach-msm/timer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-msm/timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-msm/timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,10 +24,7 @@
 
 #include <asm/mach/time.h>
 #include <mach/msm_iomap.h>
-
-#ifndef MSM_DGT_BASE
-#define MSM_DGT_BASE (MSM_GPT_BASE + 0x10)
-#endif
+#include <mach/cpu.h>
 
 #define TIMER_MATCH_VAL         0x0000
 #define TIMER_COUNT_VAL         0x0004
@@ -52,18 +49,14 @@
 	GLOBAL_TIMER = 1,
 };
 
-#ifdef MSM_TMR0_BASE
-#define MSM_TMR_GLOBAL		(MSM_TMR0_BASE - MSM_TMR_BASE)
-#else
-#define MSM_TMR_GLOBAL		0
-#endif
-
 #define MSM_GLOBAL_TIMER MSM_CLOCK_DGT
 
+/* TODO: Remove these ifdefs */
 #if defined(CONFIG_ARCH_QSD8X50)
 #define DGT_HZ (19200000 / 4) /* 19.2 MHz / 4 by default */
 #define MSM_DGT_SHIFT (0)
-#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60)
+#elif defined(CONFIG_ARCH_MSM7X30) || defined(CONFIG_ARCH_MSM8X60) || \
+				      defined(CONFIG_ARCH_MSM8960)
 #define DGT_HZ (24576000 / 4) /* 24.576 MHz (LPXO) / 4 by default */
 #define MSM_DGT_SHIFT (0)
 #else
@@ -177,11 +170,7 @@
 			.dev_id  = &msm_clocks[0].clockevent,
 			.irq     = INT_GP_TIMER_EXP
 		},
-		.regbase = MSM_GPT_BASE,
 		.freq = GPT_HZ,
-		.local_counter = MSM_GPT_BASE + TIMER_COUNT_VAL,
-		.global_counter = MSM_GPT_BASE + TIMER_COUNT_VAL +
-			MSM_TMR_GLOBAL,
 	},
 	[MSM_CLOCK_DGT] = {
 		.clockevent = {
@@ -206,12 +195,8 @@
 			.dev_id  = &msm_clocks[1].clockevent,
 			.irq     = INT_DEBUG_TIMER_EXP
 		},
-		.regbase = MSM_DGT_BASE,
 		.freq = DGT_HZ >> MSM_DGT_SHIFT,
 		.shift = MSM_DGT_SHIFT,
-		.local_counter = MSM_DGT_BASE + TIMER_COUNT_VAL,
-		.global_counter = MSM_DGT_BASE + TIMER_COUNT_VAL +
-			MSM_TMR_GLOBAL,
 	}
 };
 
@@ -219,6 +204,25 @@
 {
 	int i;
 	int res;
+	int global_offset = 0;
+
+	if (cpu_is_msm7x01()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+	} else if (cpu_is_msm7x30()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE + 0x04;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x24;
+	} else if (cpu_is_qsd8x50()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_CSR_BASE;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_CSR_BASE + 0x10;
+	} else if (cpu_is_msm8x60() || cpu_is_msm8960()) {
+		msm_clocks[MSM_CLOCK_GPT].regbase = MSM_TMR_BASE + 0x04;
+		msm_clocks[MSM_CLOCK_DGT].regbase = MSM_TMR_BASE + 0x24;
+
+		/* Use CPU0's timer as the global timer. */
+		global_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
+	} else
+		BUG();
 
 #ifdef CONFIG_ARCH_MSM_SCORPIONMP
 	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
@@ -228,6 +232,10 @@
 		struct msm_clock *clock = &msm_clocks[i];
 		struct clock_event_device *ce = &clock->clockevent;
 		struct clocksource *cs = &clock->clocksource;
+
+		clock->local_counter = clock->regbase + TIMER_COUNT_VAL;
+		clock->global_counter = clock->local_counter + global_offset;
+
 		writel(0, clock->regbase + TIMER_ENABLE);
 		writel(0, clock->regbase + TIMER_CLEAR);
 		writel(~0, clock->regbase + TIMER_MATCH_VAL);
@@ -255,13 +263,13 @@
 }
 
 #ifdef CONFIG_SMP
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	struct msm_clock *clock = &msm_clocks[MSM_GLOBAL_TIMER];
 
 	/* Use existing clock_event for cpu 0 */
 	if (!smp_processor_id())
-		return;
+		return 0;
 
 	writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 
@@ -287,6 +295,7 @@
 	gic_enable_ppi(clock->irq.irq);
 
 	clockevents_register_device(evt);
+	return 0;
 }
 
 inline int local_timer_ack(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,6 +148,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= wxl_init,
 	.map_io		= mv78xx0_map_io,
+	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
 	.timer		= &mv78xx0_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/common.c linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -818,9 +818,15 @@
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init mv78xx0_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 static void mv78xx0_timer_init(void)
 {
-	orion_time_init(IRQ_MV78XX0_TIMER_1, get_tclk());
+	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_MV78XX0_TIMER_1, get_tclk());
 }
 
 struct sys_timer mv78xx0_timer = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/common.h linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 int mv78xx0_core_index(void);
 void mv78xx0_map_io(void);
 void mv78xx0_init(void);
+void mv78xx0_init_early(void);
 void mv78xx0_init_irq(void);
 
 extern struct mbus_dram_target_info mv78xx0_mbus_dram_info;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/db78x00-bp-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,6 +96,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= db78x00_init,
 	.map_io		= mv78xx0_map_io,
+	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
 	.timer		= &mv78xx0_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/bridge-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,10 +20,6 @@
 #define SYSTEM_SOFT_RESET	(BRIDGE_VIRT_BASE | 0x010c)
 #define SOFT_RESET		0x00000001
 
-#define BRIDGE_CAUSE		(BRIDGE_VIRT_BASE | 0x0110)
-#define BRIDGE_MASK		(BRIDGE_VIRT_BASE | 0x0114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define IRQ_VIRT_BASE		(BRIDGE_VIRT_BASE | 0x0200)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,35 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-extern int mv78xx0_core_index(void);
-
-#define GPIO_MAX		32
-#define GPIO_OUT(pin)		(DEV_BUS_VIRT_BASE + 0x0100)
-#define GPIO_IO_CONF(pin)	(DEV_BUS_VIRT_BASE + 0x0104)
-#define GPIO_BLINK_EN(pin)	(DEV_BUS_VIRT_BASE + 0x0108)
-#define GPIO_IN_POL(pin)	(DEV_BUS_VIRT_BASE + 0x010c)
-#define GPIO_DATA_IN(pin)	(DEV_BUS_VIRT_BASE + 0x0110)
-#define GPIO_EDGE_CAUSE(pin)	(DEV_BUS_VIRT_BASE + 0x0114)
-#define GPIO_MASK_OFF		(mv78xx0_core_index() ? 0x18 : 0)
-#define GPIO_EDGE_MASK(pin)	(DEV_BUS_VIRT_BASE + 0x0118 + GPIO_MASK_OFF)
-#define GPIO_LEVEL_MASK(pin)	(DEV_BUS_VIRT_BASE + 0x011c + GPIO_MASK_OFF)
-
-static inline int gpio_to_irq(int pin)
-{
-	return pin + IRQ_MV78XX0_GPIO_START;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	return irq - IRQ_MV78XX0_GPIO_START;
-}
-
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/include/mach/mv78xx0.h	2011-05-19 00:06:34.000000000 -0400
@@ -71,6 +71,7 @@
 #define DEV_BUS_VIRT_BASE	(MV78XX0_REGS_VIRT_BASE | 0x10000)
 #define  SAMPLE_AT_RESET_LOW	(DEV_BUS_VIRT_BASE | 0x0030)
 #define  SAMPLE_AT_RESET_HIGH	(DEV_BUS_VIRT_BASE | 0x0034)
+#define  GPIO_VIRT_BASE		(DEV_BUS_VIRT_BASE | 0x0100)
 #define  I2C_0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x1000)
 #define  I2C_1_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x1100)
 #define  UART0_PHYS_BASE	(DEV_BUS_PHYS_BASE | 0x2000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,30 +26,20 @@
 
 void __init mv78xx0_init_irq(void)
 {
-	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));
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts.
+	 * Initialize gpiolib for GPIOs 0-31.  (The GPIO interrupt mask
+	 * registers for core #1 are at an offset of 0x18 from those of
+	 * core #0.)
 	 */
-	writel(0, GPIO_LEVEL_MASK(0));
-	writel(0, GPIO_EDGE_MASK(0));
-	writel(0, GPIO_EDGE_CAUSE(0));
-
-	for (i = IRQ_MV78XX0_GPIO_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler);
+	orion_gpio_init(0, 32, GPIO_VIRT_BASE,
+			mv78xx0_core_index() ? 0x18 : 0,
+			IRQ_MV78XX0_GPIO_START);
+	irq_set_chained_handler(IRQ_MV78XX0_GPIO_0_7, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_MV78XX0_GPIO_8_15, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_MV78XX0_GPIO_16_23, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_MV78XX0_GPIO_24_31, gpio_irq_handler);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/mpp.c linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/mpp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/mpp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/mpp.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,9 +44,6 @@
 	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.38-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,6 +81,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd78x00_masa_init,
 	.map_io		= mv78xx0_map_io,
+	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
 	.timer		= &mv78xx0_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/devices-imx35.h linux-libre-2.6.39-gnu/arch/arm/mach-mx3/devices-imx35.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/devices-imx35.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/devices-imx35.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 #define imx35_add_imx_i2c2(pdata)	imx35_add_imx_i2c(2, pdata)
 
 extern const struct imx_imx_keypad_data imx35_imx_keypad_data __initconst;
-#define imx31_add_imx_keypad(pdata)	\
+#define imx35_add_imx_keypad(pdata)	\
 	imx_add_imx_keypad(&imx35_imx_keypad_data, pdata)
 
 extern const struct imx_imx_ssi_data imx35_imx_ssi_data[] __initconst;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/ehci-imx31.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/ehci-imx31.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/ehci-imx31.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/ehci-imx31.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX31_OTG_SIC_SHIFT	29
+#define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT)
+#define MX31_OTG_PM_BIT		(1 << 24)
+
+#define MX31_H2_SIC_SHIFT	21
+#define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT)
+#define MX31_H2_PM_BIT		(1 << 16)
+#define MX31_H2_DT_BIT		(1 << 5)
+
+#define MX31_H1_SIC_SHIFT	13
+#define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT)
+#define MX31_H1_PM_BIT		(1 << 8)
+#define MX31_H1_DT_BIT		(1 << 4)
+
+int mx31_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX31_OTG_PM_BIT;
+
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX31_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX31_H1_DT_BIT;
+
+		break;
+	case 2:	/* H2 port */
+		v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX31_H2_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX31_H2_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX31_H2_DT_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/ehci-imx35.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/ehci-imx35.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/ehci-imx35.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/ehci-imx35.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define USBCTRL_OTGBASE_OFFSET	0x600
+
+#define MX35_OTG_SIC_SHIFT	29
+#define MX35_OTG_SIC_MASK	(0x3 << MX35_OTG_SIC_SHIFT)
+#define MX35_OTG_PM_BIT		(1 << 24)
+
+#define MX35_H1_SIC_SHIFT	21
+#define MX35_H1_SIC_MASK	(0x3 << MX35_H1_SIC_SHIFT)
+#define MX35_H1_PM_BIT		(1 << 8)
+#define MX35_H1_IPPUE_UP_BIT	(1 << 7)
+#define MX35_H1_IPPUE_DOWN_BIT	(1 << 6)
+#define MX35_H1_TLL_BIT		(1 << 5)
+#define MX35_H1_USBTE_BIT	(1 << 4)
+
+int mx35_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+
+	v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	switch (port) {
+	case 0:	/* OTG port */
+		v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_OTG_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX35_OTG_PM_BIT;
+
+		break;
+	case 1: /* H1 port */
+		v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
+			MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
+		v |= (flags & MXC_EHCI_INTERFACE_MASK) << MX35_H1_SIC_SHIFT;
+
+		if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
+			v |= MX35_H1_PM_BIT;
+
+		if (!(flags & MXC_EHCI_TTL_ENABLED))
+			v |= MX35_H1_TLL_BIT;
+
+		if (flags & MXC_EHCI_INTERNAL_PHY)
+			v |= MX35_H1_USBTE_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_DOWN)
+			v |= MX35_H1_IPPUE_DOWN_BIT;
+
+		if (flags & MXC_EHCI_IPPUE_UP)
+			v |= MX35_H1_IPPUE_UP_BIT;
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR + USBCTRL_OTGBASE_OFFSET));
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/eukrea_mbimxsd-baseboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,7 @@
 #include <mach/ipu.h>
 #include <mach/mx3fb.h>
 #include <mach/audmux.h>
+#include <mach/esdhc.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -163,11 +164,14 @@
 	MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
 	MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
 	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* SD1 CD */
+	MX35_PAD_LD18__GPIO3_24,
 };
 
-#define GPIO_LED1	(2 * 32 + 29)
-#define GPIO_SWITCH1	(2 * 32 + 25)
-#define GPIO_LCDPWR	(4)
+#define GPIO_LED1	IMX_GPIO_NR(3, 29)
+#define GPIO_SWITCH1	IMX_GPIO_NR(3, 25)
+#define GPIO_LCDPWR	IMX_GPIO_NR(1, 4)
+#define GPIO_SD1CD	IMX_GPIO_NR(3, 24)
 
 static void eukrea_mbimxsd_lcd_power_set(struct plat_lcd_data *pd,
 				   unsigned int power)
@@ -254,6 +258,11 @@
 	.flags = IMX_SSI_SYN | IMX_SSI_NET | IMX_SSI_USE_I2S_SLAVE,
 };
 
+static struct esdhc_platform_data sd1_pdata = {
+	.cd_gpio = GPIO_SD1CD,
+	.wp_gpio = -EINVAL,
+};
+
 /*
  * system init for baseboard usage. Will be called by cpuimx35 init.
  *
@@ -289,7 +298,7 @@
 	imx35_add_imx_ssi(0, &eukrea_mbimxsd_ssi_pdata);
 
 	imx35_add_flexcan1(NULL);
-	imx35_add_sdhci_esdhc_imx(0, NULL);
+	imx35_add_sdhci_esdhc_imx(0, &sd1_pdata);
 
 	gpio_request(GPIO_LED1, "LED1");
 	gpio_direction_output(GPIO_LED1, 1);
@@ -301,7 +310,6 @@
 
 	gpio_request(GPIO_LCDPWR, "LCDPWR");
 	gpio_direction_output(GPIO_LCDPWR, 1);
-	gpio_free(GPIO_LCDPWR);
 
 	i2c_register_board_info(0, eukrea_mbimxsd_i2c_devices,
 				ARRAY_SIZE(eukrea_mbimxsd_i2c_devices));
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/iomux-imx31.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/iomux-imx31.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/iomux-imx31.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/iomux-imx31.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
  * 	- reserves the pin so that it is not claimed by another driver
  * 	- setups the iomux according to the configuration
  */
-int mxc_iomux_alloc_pin(const unsigned int pin, const char *label)
+int mxc_iomux_alloc_pin(unsigned int pin, const char *label)
 {
 	unsigned pad = pin & IOMUX_PADNUM_MASK;
 
@@ -118,10 +118,10 @@
 }
 EXPORT_SYMBOL(mxc_iomux_alloc_pin);
 
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 	int ret = -EINVAL;
 
@@ -139,7 +139,7 @@
 }
 EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
 
-void mxc_iomux_release_pin(const unsigned int pin)
+void mxc_iomux_release_pin(unsigned int pin)
 {
 	unsigned pad = pin & IOMUX_PADNUM_MASK;
 
@@ -148,9 +148,9 @@
 }
 EXPORT_SYMBOL(mxc_iomux_release_pin);
 
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 
 	for (i = 0; i < count; i++) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-mx3/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -94,6 +94,7 @@
 	select MXC_DEBUG_BOARD
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
@@ -183,6 +184,7 @@
 	select MXC_DEBUG_BOARD
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
 	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_MXC_EHCI
 	select IMX_HAVE_PLATFORM_MXC_NAND
@@ -199,6 +201,15 @@
 	  Include support for KZM-ARM11-01. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_BUG
+	bool "Support Buglabs BUGBase platform"
+	select SOC_IMX31
+	select IMX_HAVE_PLATFORM_IMX_UART
+	default y
+	help
+	  Include support for BUGBase 1.3 platform. This includes specific
+	  configurations for the board and its peripherals.
+
 config MACH_EUKREA_CPUIMX35
 	bool "Support Eukrea CPUIMX35 Platform"
 	select SOC_IMX35
@@ -229,4 +240,18 @@
 
 endchoice
 
+config MACH_VPR200
+	bool "Support VPR200 platform"
+	select SOC_IMX35
+	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_IMX_I2C
+	select IMX_HAVE_PLATFORM_MXC_EHCI
+	select IMX_HAVE_PLATFORM_MXC_NAND
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	help
+	  Include support for VPR200 platform. This includes specific
+	  configurations for the board and its peripherals.
+
 endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-armadillo5x0.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-armadillo5x0.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-armadillo5x0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-armadillo5x0.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,6 @@
 };
 
 /* USB */
-#if defined(CONFIG_USB_ULPI)
 
 #define OTG_RESET IOMUX_TO_GPIO(MX31_PIN_STXD4)
 #define USBH2_RESET IOMUX_TO_GPIO(MX31_PIN_SCK6)
@@ -176,8 +175,10 @@
 	gpio_set_value(OTG_RESET, 0/*LOW*/);
 	mdelay(5);
 	gpio_set_value(OTG_RESET, 1/*HIGH*/);
+	mdelay(10);
 
-	return 0;
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_DIFF_UNI);
 
 otg_free_reset:
 	gpio_free(OTG_RESET);
@@ -233,8 +234,10 @@
 	gpio_set_value(USBH2_RESET, 0/*LOW*/);
 	mdelay(5);
 	gpio_set_value(USBH2_RESET, 1/*HIGH*/);
+	mdelay(10);
 
-	return 0;
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_DIFF_UNI);
 
 h2_free_reset:
 	gpio_free(USBH2_RESET);
@@ -246,15 +249,12 @@
 static struct mxc_usbh_platform_data usbotg_pdata __initdata = {
 	.init	= usbotg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif /* CONFIG_USB_ULPI */
 
 /* RTC over I2C*/
 #define ARMADILLO5X0_RTC_GPIO	IOMUX_TO_GPIO(MX31_PIN_SRXD4)
@@ -547,15 +547,15 @@
 	i2c_register_board_info(1, &armadillo5x0_i2c_rtc, 1);
 
 	/* USB */
-#if defined(CONFIG_USB_ULPI)
-	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
 
-	imx31_add_mxc_ehci_otg(&usbotg_pdata);
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
+	usbotg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbotg_pdata.otg)
+		imx31_add_mxc_ehci_otg(&usbotg_pdata);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 }
 
 static void __init armadillo5x0_timer_init(void)
@@ -569,9 +569,10 @@
 
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	/* Maintainer: Alberto Panizzo  */
-	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
-	.map_io		= mx31_map_io,
-	.init_irq	= mx31_init_irq,
-	.timer		= &armadillo5x0_timer,
-	.init_machine	= armadillo5x0_init,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &armadillo5x0_timer,
+	.init_machine = armadillo5x0_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-bug.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-bug.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-bug.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-bug.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,66 @@
+/*
+ * Copyright (C) 2000 Deep Blue Solutions Ltd
+ * Copyright (C) 2002 Shane Nay (shane@minirl.com)
+ * Copyright 2005-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2011 Denis 'GNUtoo' Carikli <GNUtoo@no-log.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+
+#include <mach/iomux-mx3.h>
+#include <mach/imx-uart.h>
+#include <mach/hardware.h>
+#include <mach/common.h>
+
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach-types.h>
+
+#include "devices-imx31.h"
+
+static const struct imxuart_platform_data uart_pdata __initconst = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+static const unsigned int bug_pins[] __initconst = {
+	MX31_PIN_PC_RST__CTS5,
+	MX31_PIN_PC_VS2__RTS5,
+	MX31_PIN_PC_BVD2__TXD5,
+	MX31_PIN_PC_BVD1__RXD5,
+};
+
+static void __init bug_board_init(void)
+{
+	mxc_iomux_setup_multiple_pins(bug_pins,
+				      ARRAY_SIZE(bug_pins), "uart-4");
+	imx31_add_imx_uart4(&uart_pdata);
+}
+
+static void __init bug_timer_init(void)
+{
+	mx31_clocks_init(26000000);
+}
+
+static struct sys_timer bug_timer = {
+	.init = bug_timer_init,
+};
+
+MACHINE_START(BUG, "BugLabs BUGBase")
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &bug_timer,
+	.init_machine = bug_board_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-cpuimx35.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-cpuimx35.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-cpuimx35.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-cpuimx35.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
 	.x_plate_ohms		= 180,
 };
 
-#define TSC2007_IRQGPIO		(2 * 32 + 2)
+#define TSC2007_IRQGPIO		IMX_GPIO_NR(3, 2)
 static struct i2c_board_info eukrea_cpuimx35_i2c_devices[] = {
 	{
 		I2C_BOARD_INFO("pcf8563", 0x51),
@@ -111,15 +111,25 @@
 	.flash_bbt	= 1,
 };
 
+static int eukrea_cpuimx35_otg_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static const struct mxc_usbh_platform_data otg_pdata __initconst = {
+	.init	= eukrea_cpuimx35_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int eukrea_cpuimx35_usbh1_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
+}
+
 static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
+	.init	= eukrea_cpuimx35_usbh1_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
 };
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
@@ -146,7 +156,7 @@
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init eukrea_cpuimx35_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx35_pads,
 			ARRAY_SIZE(eukrea_cpuimx35_pads));
@@ -184,9 +194,10 @@
 
 MACHINE_START(EUKREA_CPUIMX35, "Eukrea CPUIMX35")
 	/* Maintainer: Eukrea Electromatique */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &eukrea_cpuimx35_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &eukrea_cpuimx35_timer,
+	.init_machine = eukrea_cpuimx35_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-kzm_arm11_01.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-kzm_arm11_01.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-kzm_arm11_01.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-kzm_arm11_01.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
+#include <asm/memory.h>
 #include <asm/setup.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/irq.h>
@@ -36,7 +37,6 @@
 #include <mach/clock.h>
 #include <mach/common.h>
 #include <mach/iomux-mx3.h>
-#include <mach/memory.h>
 
 #include "devices-imx31.h"
 #include "devices.h"
@@ -266,17 +266,14 @@
 }
 
 static struct sys_timer kzm_timer = {
-	.init   = kzm_timer_init,
+	.init = kzm_timer_init,
 };
 
-/*
- * The following uses standard kernel macros define in arch.h in order to
- * initialize __mach_desc_KZM_ARM11_01 data structure.
- */
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = kzm_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = kzm_board_init,
-	.timer          = &kzm_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = kzm_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &kzm_timer,
+	.init_machine = kzm_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31_3ds.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31_3ds.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31_3ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31_3ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,9 +21,13 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/mc13783.h>
 #include <linux/spi/spi.h>
+#include <linux/spi/l4f00242t03.h>
 #include <linux/regulator/machine.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
+#include <linux/memblock.h>
+
+#include <media/soc_camera.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -35,6 +39,10 @@
 #include <mach/iomux-mx3.h>
 #include <mach/3ds_debugboard.h>
 #include <mach/ulpi.h>
+#include <mach/mmc.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+#include <mach/mx3_camera.h>
 
 #include "devices-imx31.h"
 #include "devices.h"
@@ -42,10 +50,6 @@
 /* CPLD IRQ line for external uart, external ethernet etc */
 #define EXPIO_PARENT_INT	IOMUX_TO_IRQ(MX31_PIN_GPIO1_1)
 
-/*
- * This file contains the board-specific initialization routines.
- */
-
 static int mx31_3ds_pins[] = {
 	/* UART1 */
 	MX31_PIN_CTS1__CTS1,
@@ -53,6 +57,12 @@
 	MX31_PIN_TXD1__TXD1,
 	MX31_PIN_RXD1__RXD1,
 	IOMUX_MODE(MX31_PIN_GPIO1_1, IOMUX_CONFIG_GPIO),
+	/*SPI0*/
+	MX31_PIN_CSPI1_SCLK__SCLK,
+	MX31_PIN_CSPI1_MOSI__MOSI,
+	MX31_PIN_CSPI1_MISO__MISO,
+	MX31_PIN_CSPI1_SPI_RDY__SPI_RDY,
+	MX31_PIN_CSPI1_SS2__SS2, /* CS for LCD */
 	/* SPI 1 */
 	MX31_PIN_CSPI2_SCLK__SCLK,
 	MX31_PIN_CSPI2_MOSI__MOSI,
@@ -100,6 +110,252 @@
 	IOMUX_MODE(MX31_PIN_PC_RW_B, IOMUX_CONFIG_ALT1),
 	/* USB Host2 reset */
 	IOMUX_MODE(MX31_PIN_USB_BYP, IOMUX_CONFIG_GPIO),
+	/* I2C1 */
+	MX31_PIN_I2C_CLK__I2C1_SCL,
+	MX31_PIN_I2C_DAT__I2C1_SDA,
+	/* 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_GPIO3_1__GPIO3_1, /* Card detect */
+	MX31_PIN_GPIO3_0__GPIO3_0, /* OE */
+	/* 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_CONTRAST__CONTRAST,
+	/* CSI */
+	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_CSI_D5__GPIO3_5, /* CMOS PWDN */
+	IOMUX_MODE(MX31_PIN_RI_DTE1, IOMUX_CONFIG_GPIO), /* CMOS reset */
+};
+
+/*
+ * Camera support
+ */
+static phys_addr_t mx3_camera_base __initdata;
+#define MX31_3DS_CAMERA_BUF_SIZE SZ_8M
+
+#define MX31_3DS_GPIO_CAMERA_PW IOMUX_TO_GPIO(MX31_PIN_CSI_D5)
+#define MX31_3DS_GPIO_CAMERA_RST IOMUX_TO_GPIO(MX31_PIN_RI_DTE1)
+
+static struct gpio mx31_3ds_camera_gpios[] = {
+	{ MX31_3DS_GPIO_CAMERA_PW, GPIOF_OUT_INIT_HIGH, "camera-power" },
+	{ MX31_3DS_GPIO_CAMERA_RST, GPIOF_OUT_INIT_HIGH, "camera-reset" },
+};
+
+static int __init mx31_3ds_camera_alloc_dma(void)
+{
+	int dma;
+
+	if (!mx3_camera_base)
+		return -ENOMEM;
+
+	dma = dma_declare_coherent_memory(&mx3_camera.dev,
+					mx3_camera_base, mx3_camera_base,
+					MX31_3DS_CAMERA_BUF_SIZE,
+					DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+
+	if (!(dma & DMA_MEMORY_MAP))
+		return -ENOMEM;
+
+	return 0;
+}
+
+static int mx31_3ds_camera_power(struct device *dev, int on)
+{
+	/* enable or disable the camera */
+	pr_debug("%s: %s the camera\n", __func__, on ? "ENABLE" : "DISABLE");
+	gpio_set_value(MX31_3DS_GPIO_CAMERA_PW, on ? 0 : 1);
+
+	if (!on)
+		goto out;
+
+	/* If enabled, give a reset impulse */
+	gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 0);
+	msleep(20);
+	gpio_set_value(MX31_3DS_GPIO_CAMERA_RST, 1);
+	msleep(100);
+
+out:
+	return 0;
+}
+
+static struct i2c_board_info mx31_3ds_i2c_camera = {
+	I2C_BOARD_INFO("ov2640", 0x30),
+};
+
+static struct regulator_bulk_data mx31_3ds_camera_regs[] = {
+	{ .supply = "cmos_vcore" },
+	{ .supply = "cmos_2v8" },
+};
+
+static struct soc_camera_link iclink_ov2640 = {
+	.bus_id		= 0,
+	.board_info	= &mx31_3ds_i2c_camera,
+	.i2c_adapter_id	= 0,
+	.power		= mx31_3ds_camera_power,
+	.regulators	= mx31_3ds_camera_regs,
+	.num_regulators	= ARRAY_SIZE(mx31_3ds_camera_regs),
+};
+
+static struct platform_device mx31_3ds_ov2640 = {
+	.name	= "soc-camera-pdrv",
+	.id	= 0,
+	.dev	= {
+		.platform_data = &iclink_ov2640,
+	},
+};
+
+struct mx3_camera_pdata mx31_3ds_camera_pdata = {
+	.dma_dev	= &mx3_ipu.dev,
+	.flags		= MX3_CAMERA_DATAWIDTH_10,
+	.mclk_10khz	= 2600,
+};
+
+/*
+ * FB support
+ */
+static const struct fb_videomode fb_modedb[] = {
+	{	/* 480x640 @ 60 Hz */
+		.name		= "Epson-VGA",
+		.refresh	= 60,
+		.xres		= 480,
+		.yres		= 640,
+		.pixclock	= 41701,
+		.left_margin	= 20,
+		.right_margin	= 41,
+		.upper_margin	= 10,
+		.lower_margin	= 5,
+		.hsync_len	= 20,
+		.vsync_len	= 10,
+		.sync		= FB_SYNC_OE_ACT_HIGH | FB_SYNC_CLK_INVERT,
+		.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		= "Epson-VGA",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+/* LCD */
+static struct l4f00242t03_pdata mx31_3ds_l4f00242t03_pdata = {
+	.reset_gpio		= IOMUX_TO_GPIO(MX31_PIN_LCS1),
+	.data_enable_gpio	= IOMUX_TO_GPIO(MX31_PIN_SER_RS),
+	.core_supply		= "lcd_2v8",
+	.io_supply		= "vdd_lcdio",
+};
+
+/*
+ * Support for SD card slot in personality board
+ */
+#define MX31_3DS_GPIO_SDHC1_CD IOMUX_TO_GPIO(MX31_PIN_GPIO3_1)
+#define MX31_3DS_GPIO_SDHC1_BE IOMUX_TO_GPIO(MX31_PIN_GPIO3_0)
+
+static struct gpio mx31_3ds_sdhc1_gpios[] = {
+	{ MX31_3DS_GPIO_SDHC1_CD, GPIOF_IN, "sdhc1-card-detect" },
+	{ MX31_3DS_GPIO_SDHC1_BE, GPIOF_OUT_INIT_LOW, "sdhc1-bus-en" },
+};
+
+static int mx31_3ds_sdhc1_init(struct device *dev,
+			       irq_handler_t detect_irq,
+			       void *data)
+{
+	int ret;
+
+	ret = gpio_request_array(mx31_3ds_sdhc1_gpios,
+				 ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
+	if (ret) {
+		pr_warning("Unable to request the SD/MMC GPIOs.\n");
+		return ret;
+	}
+
+	ret = request_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1),
+			  detect_irq, IRQF_DISABLED |
+			  IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+			  "sdhc1-detect", data);
+	if (ret) {
+		pr_warning("Unable to request the SD/MMC card-detect IRQ.\n");
+		goto gpio_free;
+	}
+
+	return 0;
+
+gpio_free:
+	gpio_free_array(mx31_3ds_sdhc1_gpios,
+			ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
+	return ret;
+}
+
+static void mx31_3ds_sdhc1_exit(struct device *dev, void *data)
+{
+	free_irq(IOMUX_TO_IRQ(MX31_PIN_GPIO3_1), data);
+	gpio_free_array(mx31_3ds_sdhc1_gpios,
+			 ARRAY_SIZE(mx31_3ds_sdhc1_gpios));
+}
+
+static void mx31_3ds_sdhc1_setpower(struct device *dev, unsigned int vdd)
+{
+	/*
+	 * While the voltage stuff is done by the driver, activate the
+	 * Buffer Enable Pin only if there is a card in slot to fix the card
+	 * voltage issue caused by bi-directional chip TXB0108 on 3Stack.
+	 * Done here because at this stage we have for sure a debounced value
+	 * of the presence of the card, showed by the value of vdd.
+	 * 7 == ilog2(MMC_VDD_165_195)
+	 */
+	if (vdd > 7)
+		gpio_set_value(MX31_3DS_GPIO_SDHC1_BE, 1);
+	else
+		gpio_set_value(MX31_3DS_GPIO_SDHC1_BE, 0);
+}
+
+static struct imxmmc_platform_data sdhc1_pdata = {
+	.init		= mx31_3ds_sdhc1_init,
+	.exit		= mx31_3ds_sdhc1_exit,
+	.setpower	= mx31_3ds_sdhc1_setpower,
 };
 
 /*
@@ -138,7 +394,71 @@
 	}
 };
 
-static struct mc13783_regulator_init_data mx31_3ds_regulators[] = {
+static struct regulator_consumer_supply vmmc2_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "mxc-mmc.0"),
+};
+
+static struct regulator_init_data vmmc2_init = {
+	.constraints = {
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vmmc2_consumers),
+	.consumer_supplies = vmmc2_consumers,
+};
+
+static struct regulator_consumer_supply vmmc1_consumers[] = {
+	REGULATOR_SUPPLY("lcd_2v8", NULL),
+	REGULATOR_SUPPLY("cmos_2v8", "soc-camera-pdrv.0"),
+};
+
+static struct regulator_init_data vmmc1_init = {
+	.constraints = {
+		.min_uV = 2800000,
+		.max_uV = 2800000,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vmmc1_consumers),
+	.consumer_supplies = vmmc1_consumers,
+};
+
+static struct regulator_consumer_supply vgen_consumers[] = {
+	REGULATOR_SUPPLY("vdd_lcdio", NULL),
+};
+
+static struct regulator_init_data vgen_init = {
+	.constraints = {
+		.min_uV = 1800000,
+		.max_uV = 1800000,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vgen_consumers),
+	.consumer_supplies = vgen_consumers,
+};
+
+static struct regulator_consumer_supply vvib_consumers[] = {
+	REGULATOR_SUPPLY("cmos_vcore", "soc-camera-pdrv.0"),
+};
+
+static struct regulator_init_data vvib_init = {
+	.constraints = {
+		.min_uV = 1300000,
+		.max_uV = 1300000,
+		.apply_uV = 1,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+				  REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vvib_consumers),
+	.consumer_supplies = vvib_consumers,
+};
+
+static struct mc13xxx_regulator_init_data mx31_3ds_regulators[] = {
 	{
 		.id = MC13783_REG_PWGT1SPI, /* Power Gate for ARM core. */
 		.init_data = &pwgtx_init,
@@ -152,17 +472,40 @@
 	}, {
 		.id = MC13783_REG_GPO3, /* Turn on 3.3V */
 		.init_data = &gpo_init,
+	}, {
+		.id = MC13783_REG_VMMC2, /* Power MMC/SD, WiFi/Bluetooth. */
+		.init_data = &vmmc2_init,
+	}, {
+		.id = MC13783_REG_VMMC1, /* Power LCD, CMOS, FM, GPS, Accel. */
+		.init_data = &vmmc1_init,
+	}, {
+		.id = MC13783_REG_VGEN,  /* Power LCD */
+		.init_data = &vgen_init,
+	}, {
+		.id = MC13783_REG_VVIB,  /* Power CMOS */
+		.init_data = &vvib_init,
 	},
 };
 
 /* MC13783 */
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.regulators = mx31_3ds_regulators,
-	.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
+static struct mc13xxx_platform_data mc13783_pdata = {
+	.regulators = {
+		.regulators = mx31_3ds_regulators,
+		.num_regulators = ARRAY_SIZE(mx31_3ds_regulators),
+	},
 	.flags  = MC13783_USE_REGULATOR | MC13783_USE_TOUCHSCREEN,
 };
 
 /* SPI */
+static int spi0_internal_chipselect[] = {
+	MXC_SPI_CS(2),
+};
+
+static const struct spi_imx_master spi0_pdata __initconst = {
+	.chipselect	= spi0_internal_chipselect,
+	.num_chipselect	= ARRAY_SIZE(spi0_internal_chipselect),
+};
+
 static int spi1_internal_chipselect[] = {
 	MXC_SPI_CS(0),
 	MXC_SPI_CS(2),
@@ -182,6 +525,12 @@
 		.platform_data	= &mc13783_pdata,
 		.irq		= IOMUX_TO_IRQ(MX31_PIN_GPIO1_3),
 		.mode = SPI_CS_HIGH,
+	}, {
+		.modalias	= "l4f00242t03",
+		.max_speed_hz	= 5000000,
+		.bus_num	= 0,
+		.chip_select	= 0, /* SS2 */
+		.platform_data	= &mx31_3ds_l4f00242t03_pdata,
 	},
 };
 
@@ -245,6 +594,11 @@
 	return err;
 }
 
+static int mx31_3ds_otg_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
+
 static int mx31_3ds_host2_init(struct platform_device *pdev)
 {
 	int err;
@@ -276,25 +630,25 @@
 
 	mdelay(1);
 	gpio_set_value(USBH2_RST_B, 1);
-	return 0;
+
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
 
 usbotg_free_reset:
 	gpio_free(USBH2_RST_B);
 	return err;
 }
 
-#if defined(CONFIG_USB_ULPI)
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= mx31_3ds_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init = mx31_3ds_host2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
-#endif
 
 static const struct fsl_usb2_platform_data usbotg_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -320,19 +674,18 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-/*
- * Set up static virtual mappings.
- */
-static void __init mx31_3ds_map_io(void)
-{
-	mx31_map_io();
-}
+static const struct imxi2c_platform_data mx31_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
 
-/*!
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
+static struct platform_device *devices[] __initdata = {
+	&mx31_3ds_ov2640,
+};
+
+static void __init mx31_3ds_init(void)
 {
+	int ret;
+
 	mxc_iomux_setup_multiple_pins(mx31_3ds_pins, ARRAY_SIZE(mx31_3ds_pins),
 				      "mx31_3ds");
 
@@ -343,20 +696,22 @@
 	spi_register_board_info(mx31_3ds_spi_devs,
 						ARRAY_SIZE(mx31_3ds_spi_devs));
 
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
 	imx31_add_imx_keypad(&mx31_3ds_keymap_data);
 
 	mx31_3ds_usbotg_init();
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx31_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx31_add_mxc_ehci_otg(&otg_pdata);
 	}
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+
 	if (!otg_mode_host)
 		imx31_add_fsl_usb2_udc(&usbotg_pdata);
 
@@ -364,6 +719,26 @@
 		printk(KERN_WARNING "Init of the debug board failed, all "
 				    "devices on the debug board are unusable.\n");
 	imx31_add_imx2_wdt(NULL);
+	imx31_add_imx_i2c0(&mx31_3ds_i2c0_data);
+	imx31_add_mxc_mmc(0, &sdhc1_pdata);
+
+	imx31_add_spi_imx0(&spi0_pdata);
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	/* CSI */
+	/* Camera power: default - off */
+	ret = gpio_request_array(mx31_3ds_camera_gpios,
+				 ARRAY_SIZE(mx31_3ds_camera_gpios));
+	if (ret) {
+		pr_err("Failed to request camera gpios");
+		iclink_ov2640.power = NULL;
+	}
+
+	if (!mx31_3ds_camera_alloc_dma())
+		mxc_register_device(&mx3_camera, &mx31_3ds_camera_pdata);
+	else
+		pr_err("Failed to allocate dma memory for camera");
 }
 
 static void __init mx31_3ds_timer_init(void)
@@ -375,15 +750,22 @@
 	.init	= mx31_3ds_timer_init,
 };
 
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_MX31_3DS data structure.
- */
+static void __init mx31_3ds_reserve(void)
+{
+	/* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
+	mx3_camera_base = memblock_alloc(MX31_3DS_CAMERA_BUF_SIZE,
+					 MX31_3DS_CAMERA_BUF_SIZE);
+	memblock_free(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
+	memblock_remove(mx3_camera_base, MX31_3DS_CAMERA_BUF_SIZE);
+}
+
 MACHINE_START(MX31_3DS, "Freescale MX31PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_3ds_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31_3ds_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31_3ds_timer,
+	.init_machine = mx31_3ds_init,
+	.reserve = mx31_3ds_reserve,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31ads.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31ads.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31ads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31ads.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,12 +69,8 @@
 #define EXPIO_INT_XUART_INTB	(MXC_EXP_IO_BASE + 11)
 
 #define MXC_MAX_EXP_IO_LINES	16
-/*
- * This file contains the board-specific initialization routines.
- */
 
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
-/*!
+/*
  * The serial port definition structure.
  */
 static struct plat_serial8250_port serial_platform_data[] = {
@@ -110,14 +106,7 @@
 {
 	return platform_device_register(&serial_device);
 }
-#else
-static inline int mxc_init_extuart(void)
-{
-	return 0;
-}
-#endif
 
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -134,11 +123,6 @@
 	mxc_iomux_setup_multiple_pins(uart_pins, ARRAY_SIZE(uart_pins), "uart-0");
 	imx31_add_imx_uart0(&uart_pdata);
 }
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* !SERIAL_IMX */
 
 static void mx31ads_expio_irq_handler(u32 irq, struct irq_desc *desc)
 {
@@ -160,7 +144,7 @@
 
 /*
  * Disable an expio pin's interrupt by setting the bit in the imr.
- * @param irq           an expio virtual irq number
+ * @param d	an expio virtual irq description
  */
 static void expio_mask_irq(struct irq_data *d)
 {
@@ -172,7 +156,7 @@
 
 /*
  * Acknowledge an expanded io pin's interrupt by clearing the bit in the isr.
- * @param irq           an expanded io virtual irq number
+ * @param d	an expio virtual irq description
  */
 static void expio_ack_irq(struct irq_data *d)
 {
@@ -183,7 +167,7 @@
 
 /*
  * Enable a expio pin's interrupt by clearing the bit in the imr.
- * @param irq           a expio virtual irq number
+ * @param d	an expio virtual irq description
  */
 static void expio_unmask_irq(struct irq_data *d)
 {
@@ -215,12 +199,11 @@
 	__raw_writew(0xFFFF, PBC_INTSTATUS_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);
+		irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
-	set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
-	set_irq_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
+	irq_set_irq_type(EXPIO_PARENT_INT, IRQ_TYPE_LEVEL_HIGH);
+	irq_set_chained_handler(EXPIO_PARENT_INT, mx31ads_expio_irq_handler);
 }
 
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
@@ -476,7 +459,6 @@
 };
 #endif
 
-#if defined(CONFIG_I2C_IMX) || defined(CONFIG_I2C_IMX_MODULE)
 static struct i2c_board_info __initdata mx31ads_i2c1_devices[] = {
 #ifdef CONFIG_MACH_MX31ADS_WM1133_EV1
 	{
@@ -497,11 +479,6 @@
 
 	imx31_add_imx_i2c1(NULL);
 }
-#else
-static void mxc_init_i2c(void)
-{
-}
-#endif
 
 static unsigned int ssi_pins[] = {
 	MX31_PIN_SFS5__SFS5,
@@ -516,9 +493,7 @@
 	mxc_iomux_setup_multiple_pins(ssi_pins, ARRAY_SIZE(ssi_pins), "ssi");
 }
 
-/*!
- * This structure defines static mappings for the i.MX31ADS board.
- */
+/* static mappings */
 static struct map_desc mx31ads_io_desc[] __initdata = {
 	{
 		.virtual	= MX31_CS4_BASE_ADDR_VIRT,
@@ -528,9 +503,6 @@
 	},
 };
 
-/*!
- * Set up static virtual mappings.
- */
 static void __init mx31ads_map_io(void)
 {
 	mx31_map_io();
@@ -543,10 +515,7 @@
 	mx31ads_init_expio();
 }
 
-/*!
- * Board specific initialization.
- */
-static void __init mxc_board_init(void)
+static void __init mx31ads_init(void)
 {
 	mxc_init_extuart();
 	mxc_init_imx_uart();
@@ -563,15 +532,12 @@
 	.init	= mx31ads_timer_init,
 };
 
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_MX31ADS data structure.
- */
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31ads_map_io,
-	.init_irq       = mx31ads_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31ads_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31ads_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31ads_init_irq,
+	.timer = &mx31ads_timer,
+	.init_machine = mx31ads_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31lilly.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31lilly.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31lilly.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31lilly.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/smsc911x.h>
@@ -110,55 +111,9 @@
 
 /* USB */
 
-#if defined(CONFIG_USB_ULPI)
-
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
-static int usbotg_init(struct platform_device *pdev)
-{
-	unsigned int 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,
-	};
-
-	mxc_iomux_setup_multiple_pins(pins, ARRAY_SIZE(pins), "USB OTG");
-
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA0, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA1, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA2, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA3, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA4, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA5, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA6, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DATA7, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_CLK, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_DIR, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_NXT, USB_PAD_CFG);
-	mxc_iomux_set_pad(MX31_PIN_USBOTG_STP, USB_PAD_CFG);
-
-	mxc_iomux_set_gpr(MUX_PGP_USB_4WIRE, true);
-	mxc_iomux_set_gpr(MUX_PGP_USB_COMMON, true);
-
-	/* chip select */
-	mxc_iomux_alloc_pin(IOMUX_MODE(MX31_PIN_DTR_DCE2, IOMUX_CONFIG_GPIO),
-				"USBOTG_CS");
-	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), "USBH1 CS");
-	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE2), 0);
-
-	return 0;
-}
-
 static int usbh1_init(struct platform_device *pdev)
 {
 	int pins[] = {
@@ -183,7 +138,10 @@
 
 	mxc_iomux_set_gpr(MUX_PGP_USB_SUSPEND, true);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_SINGLE_UNI);
 }
 
 static int usbh2_init(struct platform_device *pdev)
@@ -220,41 +178,30 @@
 	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
 	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
 
-	return 0;
-}
+	mdelay(10);
 
-static struct mxc_usbh_platform_data usbotg_pdata = {
-	.init	= usbotg_init,
-	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
-};
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
 
 static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
 	.init	= usbh1_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init	= usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static void lilly1131_usb_init(void)
 {
-	usbotg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
 	imx31_add_mxc_ehci_hs(1, &usbh1_pdata);
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-}
 
-#else
-static inline void lilly1131_usb_init(void) {}
-#endif /* CONFIG_USB_ULPI */
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
+}
 
 /* SPI */
 
@@ -274,8 +221,8 @@
 	.num_chipselect = ARRAY_SIZE(spi_internal_chipselect),
 };
 
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.flags = MC13783_USE_RTC | MC13783_USE_TOUCHSCREEN,
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
+	.flags = MC13XXX_USE_RTC | MC13XXX_USE_TOUCHSCREEN,
 };
 
 static struct spi_board_info mc13783_dev __initdata = {
@@ -347,10 +294,10 @@
 };
 
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
-	.boot_params	= MX3x_PHYS_OFFSET + 0x100,
-	.map_io		= mx31_map_io,
-	.init_irq	= mx31_init_irq,
-	.init_machine	= mx31lilly_board_init,
-	.timer		= &mx31lilly_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31lilly_timer,
+	.init_machine = mx31lilly_board_init,
 MACHINE_END
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31lite.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31lite.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31lite.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31lite.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/mtd/physmap.h>
+#include <linux/delay.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -111,9 +112,9 @@
 	.num_chipselect	= ARRAY_SIZE(spi_internal_chipselect),
 };
 
-static struct mc13783_platform_data mc13783_pdata __initdata = {
-	.flags  = MC13783_USE_RTC |
-		  MC13783_USE_REGULATOR,
+static struct mc13xxx_platform_data mc13783_pdata __initdata = {
+	.flags  = MC13XXX_USE_RTC |
+		  MC13XXX_USE_REGULATOR,
 };
 
 static struct spi_board_info mc13783_spi_dev __initdata = {
@@ -129,7 +130,6 @@
  * USB
  */
 
-#if defined(CONFIG_USB_ULPI)
 #define USB_PAD_CFG (PAD_CTL_DRV_MAX | PAD_CTL_SRE_FAST | PAD_CTL_HYS_CMOS | \
 			PAD_CTL_ODE_CMOS | PAD_CTL_100K_PU)
 
@@ -167,15 +167,15 @@
 	gpio_request(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), "USBH2 CS");
 	gpio_direction_output(IOMUX_TO_GPIO(MX31_PIN_DTR_DCE1), 0);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
 }
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
 	.init   = usbh2_init,
 	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags  = MXC_EHCI_POWER_PINS_ENABLED,
 };
-#endif
 
 /*
  * NOR flash
@@ -227,7 +227,7 @@
 static int mx31lite_baseboard;
 core_param(mx31lite_baseboard, mx31lite_baseboard, int, 0444);
 
-static void __init mxc_board_init(void)
+static void __init mx31lite_init(void)
 {
 	int ret;
 
@@ -252,13 +252,11 @@
 	imx31_add_spi_imx1(&spi1_pdata);
 	spi_register_board_info(&mc13783_spi_dev, 1);
 
-#if defined(CONFIG_USB_ULPI)
 	/* USB */
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 
 	/* SMSC9117 IRQ pin */
 	ret = gpio_request(IOMUX_TO_GPIO(MX31_PIN_SFS6), "sms9117-irq");
@@ -281,9 +279,10 @@
 
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	/* Maintainer: Freescale Semiconductor, Inc. */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31lite_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31lite_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31lite_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31lite_timer,
+	.init_machine = mx31lite_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31moboard.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31moboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx31moboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx31moboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,7 +214,7 @@
 	.consumer_supplies = cam_consumers,
 };
 
-static struct mc13783_regulator_init_data moboard_regulators[] = {
+static struct mc13xxx_regulator_init_data moboard_regulators[] = {
 	{
 		.id = MC13783_REG_VMMC1,
 		.init_data = &sdhc_vreg_data,
@@ -267,12 +267,14 @@
 	.tc2_period = MC13783_LED_PERIOD_10MS,
 };
 
-static struct mc13783_platform_data moboard_pmic = {
-	.regulators = moboard_regulators,
-	.num_regulators = ARRAY_SIZE(moboard_regulators),
+static struct mc13xxx_platform_data moboard_pmic = {
+	.regulators = {
+		.regulators = moboard_regulators,
+		.num_regulators = ARRAY_SIZE(moboard_regulators),
+	},
 	.leds = &moboard_leds,
-	.flags = MC13783_USE_REGULATOR | MC13783_USE_RTC |
-		MC13783_USE_ADC | MC13783_USE_LED,
+	.flags = MC13XXX_USE_REGULATOR | MC13XXX_USE_RTC |
+		MC13XXX_USE_ADC | MC13XXX_USE_LED,
 };
 
 static struct spi_board_info moboard_spi_board_info[] __initdata = {
@@ -400,19 +402,24 @@
 	mdelay(1);
 }
 
-#if defined(CONFIG_USB_ULPI)
+static int moboard_usbh2_init_hw(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
 
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init	= moboard_usbh2_init_hw,
 	.portsc	= MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static int __init moboard_usbh2_init(void)
 {
 	struct platform_device *pdev;
 
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (!usbh2_pdata.otg)
+		return -ENODEV;
 
 	pdev = imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 	if (IS_ERR(pdev))
@@ -420,10 +427,6 @@
 
 	return 0;
 }
-#else
-static inline int moboard_usbh2_init(void) { return 0; }
-#endif
-
 
 static struct gpio_led mx31moboard_leds[] = {
 	{
@@ -503,7 +506,7 @@
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx31moboard_init(void)
 {
 	mxc_iomux_setup_multiple_pins(moboard_pins, ARRAY_SIZE(moboard_pins),
 		"moboard");
@@ -564,10 +567,10 @@
 
 MACHINE_START(MX31MOBOARD, "EPFL Mobots mx31moboard")
 	/* Maintainer: Valentin Longchamp, EPFL Mobots group */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx31moboard_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &mx31moboard_timer,
+	.init_machine = mx31moboard_init,
 MACHINE_END
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx35_3ds.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx35_3ds.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-mx35_3ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-mx35_3ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,24 +118,42 @@
 	MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
 	MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
 	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* I2C1 */
+	MX35_PAD_I2C1_CLK__I2C1_SCL,
+	MX35_PAD_I2C1_DAT__I2C1_SDA,
 };
 
+static int mx35_3ds_otg_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
 /* OTG config */
 static const struct fsl_usb2_platform_data usb_otg_pdata __initconst = {
 	.operating_mode	= FSL_USB2_DR_DEVICE,
 	.phy_mode	= FSL_USB2_PHY_UTMI_WIDE,
+	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
+/*
+ * ENGCM09152 also requires a hardware change.
+ * Please check the MX35 Chip Errata document for details.
+ */
 };
 
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= mx35_3ds_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
+static int mx35_3ds_usbh_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			  MXC_EHCI_INTERNAL_PHY);
+}
+
 /* USB HOST config */
 static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
+	.init		= mx35_3ds_usbh_init,
 	.portsc		= MXC_EHCI_MODE_SERIAL,
-	.flags		= MXC_EHCI_INTERFACE_SINGLE_UNI |
-			  MXC_EHCI_INTERNAL_PHY,
 };
 
 static int otg_mode_host;
@@ -153,10 +171,14 @@
 }
 __setup("otg_mode=", mx35_3ds_otg_mode);
 
+static const struct imxi2c_platform_data mx35_3ds_i2c0_data __initconst = {
+	.bitrate = 100000,
+};
+
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx35_3ds_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx35pdk_pads, ARRAY_SIZE(mx35pdk_pads));
 
@@ -180,6 +202,7 @@
 	if (mxc_expio_init(MX35_CS5_BASE_ADDR, EXPIO_PARENT_INT))
 		pr_warn("Init of the debugboard failed, all "
 				"devices on the debugboard are unusable.\n");
+	imx35_add_imx_i2c0(&mx35_3ds_i2c0_data);
 }
 
 static void __init mx35pdk_timer_init(void)
@@ -193,9 +216,10 @@
 
 MACHINE_START(MX35_3DS, "Freescale MX35PDK")
 	/* Maintainer: Freescale Semiconductor, Inc */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &mx35pdk_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &mx35pdk_timer,
+	.init_machine = mx35_3ds_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-pcm037.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-pcm037.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-pcm037.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-pcm037.c	2011-05-19 00:06:34.000000000 -0400
@@ -533,17 +533,25 @@
 	.num_resources = ARRAY_SIZE(pcm970_sja1000_resources),
 };
 
-#if defined(CONFIG_USB_ULPI)
+static int pcm037_otg_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= pcm037_otg_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int pcm037_usbh2_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data usbh2_pdata __initdata = {
+	.init	= pcm037_usbh2_init,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -568,7 +576,7 @@
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init pcm037_init(void)
 {
 	int ret;
 
@@ -646,19 +654,18 @@
 
 	platform_device_register(&pcm970_sja1000);
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx31_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx31_add_mxc_ehci_otg(&otg_pdata);
 	}
 
-	usbh2_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	usbh2_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT);
+	if (usbh2_pdata.otg)
+		imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
 
-	imx31_add_mxc_ehci_hs(2, &usbh2_pdata);
-#endif
 	if (!otg_mode_host)
 		imx31_add_fsl_usb2_udc(&otg_device_pdata);
 
@@ -675,9 +682,10 @@
 
 MACHINE_START(PCM037, "Phytec Phycore pcm037")
 	/* Maintainer: Pengutronix */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &pcm037_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &pcm037_timer,
+	.init_machine = pcm037_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-pcm037_eet.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-pcm037_eet.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-pcm037_eet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-pcm037_eet.c	2011-05-19 00:06:34.000000000 -0400
@@ -180,9 +180,7 @@
 
 	/* SPI */
 	spi_register_board_info(pcm037_spi_dev, ARRAY_SIZE(pcm037_spi_dev));
-#if defined(CONFIG_SPI_IMX) || defined(CONFIG_SPI_IMX_MODULE)
 	imx31_add_spi_imx0(&pcm037_spi1_pdata);
-#endif
 
 	platform_device_register(&pcm037_gpio_keys_device);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-pcm043.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-pcm043.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-pcm043.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-pcm043.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 #include <mach/mx3fb.h>
 #include <mach/ulpi.h>
 #include <mach/audmux.h>
+#include <mach/esdhc.h>
 
 #include "devices-imx35.h"
 #include "devices.h"
@@ -115,7 +116,6 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-#if defined CONFIG_I2C_IMX || defined CONFIG_I2C_IMX_MODULE
 static const struct imxi2c_platform_data pcm043_i2c0_data __initconst = {
 	.bitrate = 50000,
 };
@@ -134,7 +134,6 @@
 		I2C_BOARD_INFO("pcf8563", 0x51),
 	}
 };
-#endif
 
 static struct platform_device *devices[] __initdata = {
 	&pcm043_flash,
@@ -219,11 +218,15 @@
 	MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
 	MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
 	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+	MX35_PAD_ATA_DATA10__GPIO2_23, /* WriteProtect */
+	MX35_PAD_ATA_DATA11__GPIO2_24, /* CardDetect */
 };
 
-#define AC97_GPIO_TXFS	(1 * 32 + 31)
-#define AC97_GPIO_TXD	(1 * 32 + 28)
-#define AC97_GPIO_RESET	(1 * 32 + 0)
+#define AC97_GPIO_TXFS	IMX_GPIO_NR(2, 31)
+#define AC97_GPIO_TXD	IMX_GPIO_NR(2, 28)
+#define AC97_GPIO_RESET	IMX_GPIO_NR(2, 0)
+#define SD1_GPIO_WP	IMX_GPIO_NR(2, 23)
+#define SD1_GPIO_CD	IMX_GPIO_NR(2, 24)
 
 static void pcm043_ac97_warm_reset(struct snd_ac97 *ac97)
 {
@@ -307,18 +310,26 @@
 	.hw_ecc = 1,
 };
 
-#if defined(CONFIG_USB_ULPI)
+static int pcm043_otg_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_DIFF_UNI);
+}
+
 static struct mxc_usbh_platform_data otg_pdata __initdata = {
+	.init	= pcm043_otg_init,
 	.portsc	= MXC_EHCI_MODE_UTMI,
-	.flags	= MXC_EHCI_INTERFACE_DIFF_UNI,
 };
 
+static int pcm043_usbh1_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id, MXC_EHCI_INTERFACE_SINGLE_UNI |
+			MXC_EHCI_INTERNAL_PHY | MXC_EHCI_IPPUE_DOWN);
+}
+
 static const struct mxc_usbh_platform_data usbh1_pdata __initconst = {
+	.init	= pcm043_usbh1_init,
 	.portsc	= MXC_EHCI_MODE_SERIAL,
-	.flags	= MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY |
-		  MXC_EHCI_IPPUE_DOWN,
 };
-#endif
 
 static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
 	.operating_mode = FSL_USB2_DR_DEVICE,
@@ -340,10 +351,15 @@
 }
 __setup("otg_mode=", pcm043_otg_mode);
 
+static struct esdhc_platform_data sd1_pdata = {
+	.wp_gpio = SD1_GPIO_WP,
+	.cd_gpio = SD1_GPIO_CD,
+};
+
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init pcm043_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(pcm043_pads, ARRAY_SIZE(pcm043_pads));
 
@@ -369,31 +385,27 @@
 
 	imx35_add_imx_uart1(&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));
 
 	imx35_add_imx_i2c0(&pcm043_i2c0_data);
-#endif
 
 	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
 	mxc_register_device(&mx3_fb, &mx3fb_pdata);
 
-#if defined(CONFIG_USB_ULPI)
 	if (otg_mode_host) {
-		otg_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-				ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
-
-		imx35_add_mxc_ehci_otg(&otg_pdata);
+		otg_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+				ULPI_OTG_DRVVBUS_EXT);
+		if (otg_pdata.otg)
+			imx35_add_mxc_ehci_otg(&otg_pdata);
 	}
-
 	imx35_add_mxc_ehci_hs(&usbh1_pdata);
-#endif
+
 	if (!otg_mode_host)
 		imx35_add_fsl_usb2_udc(&otg_device_pdata);
 
 	imx35_add_flexcan1(NULL);
-	imx35_add_sdhci_esdhc_imx(0, NULL);
+	imx35_add_sdhci_esdhc_imx(0, &sd1_pdata);
 }
 
 static void __init pcm043_timer_init(void)
@@ -407,10 +419,10 @@
 
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	/* Maintainer: Pengutronix */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx35_map_io,
-	.init_irq       = mx35_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &pcm043_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &pcm043_timer,
+	.init_machine = pcm043_init,
 MACHINE_END
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-qong.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-qong.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-qong.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-qong.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,10 +54,6 @@
 
 #define QONG_FPGA_IRQ		IOMUX_TO_IRQ(MX31_PIN_DTR_DCE1)
 
-/*
- * This file contains the board-specific initialization routines.
- */
-
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
@@ -247,7 +243,7 @@
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init qong_init(void)
 {
 	mxc_init_imx_uart();
 	qong_init_nor_mtd();
@@ -263,16 +259,12 @@
 	.init	= qong_timer_init,
 };
 
-/*
- * The following uses standard kernel macros defined in arch.h in order to
- * initialize __mach_desc_QONG data structure.
- */
-
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	/* Maintainer: DENX Software Engineering GmbH */
-	.boot_params    = MX3x_PHYS_OFFSET + 0x100,
-	.map_io         = mx31_map_io,
-	.init_irq       = mx31_init_irq,
-	.init_machine   = mxc_board_init,
-	.timer          = &qong_timer,
+	.boot_params = MX3x_PHYS_OFFSET + 0x100,
+	.map_io = mx31_map_io,
+	.init_early = imx31_init_early,
+	.init_irq = mx31_init_irq,
+	.timer = &qong_timer,
+	.init_machine = qong_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-vpr200.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-vpr200.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mach-vpr200.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mach-vpr200.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,333 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Marc Kleine-Budde, Pengutronix
+ * Copyright 2010 Creative Product Design
+ *
+ * Derived from mx35 3stack.
+ * Original 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.
+ */
+
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.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 <mach/hardware.h>
+#include <mach/common.h>
+#include <mach/iomux-mx35.h>
+#include <mach/irqs.h>
+#include <mach/ipu.h>
+#include <mach/mx3fb.h>
+
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/mfd/mc13xxx.h>
+#include <linux/gpio_keys.h>
+
+#include "devices-imx35.h"
+#include "devices.h"
+
+#define GPIO_LCDPWR	IMX_GPIO_NR(1, 2)
+#define GPIO_PMIC_INT	IMX_GPIO_NR(2, 0)
+
+#define GPIO_BUTTON1	IMX_GPIO_NR(1, 4)
+#define GPIO_BUTTON2	IMX_GPIO_NR(1, 5)
+#define GPIO_BUTTON3	IMX_GPIO_NR(1, 7)
+#define GPIO_BUTTON4	IMX_GPIO_NR(1, 8)
+#define GPIO_BUTTON5	IMX_GPIO_NR(1, 9)
+#define GPIO_BUTTON6	IMX_GPIO_NR(1, 10)
+#define GPIO_BUTTON7	IMX_GPIO_NR(1, 11)
+#define GPIO_BUTTON8	IMX_GPIO_NR(1, 12)
+
+static const struct fb_videomode fb_modedb[] = {
+	{
+		/* 800x480 @ 60 Hz */
+		.name		= "PT0708048",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= KHZ2PICOS(33260),
+		.left_margin	= 50,
+		.right_margin	= 156,
+		.upper_margin	= 10,
+		.lower_margin	= 10,
+		.hsync_len	= 1,	/* note: DE only display */
+		.vsync_len	= 1,	/* note: DE only display */
+		.sync		= FB_SYNC_CLK_IDLE_EN | FB_SYNC_OE_ACT_HIGH,
+		.vmode		= FB_VMODE_NONINTERLACED,
+		.flag		= 0,
+	}, {
+		/* 800x480 @ 60 Hz */
+		.name		= "CTP-CLAA070LC0ACW",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= KHZ2PICOS(27000),
+		.left_margin	= 50,
+		.right_margin	= 50,	/* whole line should have 900 clocks */
+		.upper_margin	= 10,
+		.lower_margin	= 10,	/* whole frame should have 500 lines */
+		.hsync_len	= 1,	/* note: DE only display */
+		.vsync_len	= 1,	/* note: DE only display */
+		.sync		= FB_SYNC_CLK_IDLE_EN | 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		= "PT0708048",
+	.mode		= fb_modedb,
+	.num_modes	= ARRAY_SIZE(fb_modedb),
+};
+
+static struct physmap_flash_data vpr200_flash_data = {
+	.width  = 2,
+};
+
+static struct resource vpr200_flash_resource = {
+	.start	= MX35_CS0_BASE_ADDR,
+	.end	= MX35_CS0_BASE_ADDR + SZ_64M - 1,
+	.flags	= IORESOURCE_MEM,
+};
+
+static struct platform_device vpr200_flash = {
+	.name	= "physmap-flash",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &vpr200_flash_data,
+	},
+	.resource = &vpr200_flash_resource,
+	.num_resources = 1,
+};
+
+static const struct mxc_nand_platform_data
+		vpr200_nand_board_info __initconst = {
+	.width = 1,
+	.hw_ecc = 1,
+	.flash_bbt = 1,
+};
+
+#define VPR_KEY_DEBOUNCE	500
+static struct gpio_keys_button vpr200_gpio_keys_table[] = {
+	{KEY_F2, GPIO_BUTTON1, 1, "vpr-keys: F2", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F3, GPIO_BUTTON2, 1, "vpr-keys: F3", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F4, GPIO_BUTTON3, 1, "vpr-keys: F4", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F5, GPIO_BUTTON4, 1, "vpr-keys: F5", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F6, GPIO_BUTTON5, 1, "vpr-keys: F6", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F7, GPIO_BUTTON6, 1, "vpr-keys: F7", 0, VPR_KEY_DEBOUNCE},
+	{KEY_F8, GPIO_BUTTON7, 1, "vpr-keys: F8", 1, VPR_KEY_DEBOUNCE},
+	{KEY_F9, GPIO_BUTTON8, 1, "vpr-keys: F9", 1, VPR_KEY_DEBOUNCE},
+};
+
+static struct gpio_keys_platform_data vpr200_gpio_keys_data = {
+	.buttons = vpr200_gpio_keys_table,
+	.nbuttons = ARRAY_SIZE(vpr200_gpio_keys_table),
+};
+
+static struct platform_device vpr200_device_gpiokeys = {
+	.name = "gpio-keys",
+	.dev = {
+		.platform_data = &vpr200_gpio_keys_data,
+	}
+};
+
+static struct mc13xxx_platform_data vpr200_pmic = {
+	.flags = MC13XXX_USE_ADC | MC13XXX_USE_TOUCHSCREEN,
+};
+
+static const struct imxi2c_platform_data vpr200_i2c0_data __initconst = {
+	.bitrate = 50000,
+};
+
+static struct at24_platform_data vpr200_eeprom = {
+	.byte_len = 2048 / 8,
+	.page_size = 1,
+};
+
+static struct i2c_board_info vpr200_i2c_devices[] = {
+	{
+		I2C_BOARD_INFO("at24", 0x50), /* E0=0, E1=0, E2=0 */
+		.platform_data = &vpr200_eeprom,
+	}, {
+		I2C_BOARD_INFO("mc13892", 0x08),
+		.platform_data = &vpr200_pmic,
+		.irq = gpio_to_irq(GPIO_PMIC_INT),
+	}
+};
+
+static iomux_v3_cfg_t vpr200_pads[] = {
+	/* UART1 */
+	MX35_PAD_TXD1__UART1_TXD_MUX,
+	MX35_PAD_RXD1__UART1_RXD_MUX,
+	/* UART3 */
+	MX35_PAD_ATA_DATA10__UART3_RXD_MUX,
+	MX35_PAD_ATA_DATA11__UART3_TXD_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,
+	/* 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_FPSHIFT__IPU_DISPB_D3_CLK,
+	MX35_PAD_D3_DRDY__IPU_DISPB_D3_DRDY,
+	MX35_PAD_CONTRAST__IPU_DISPB_CONTR,
+	/* LCD Enable */
+	MX35_PAD_D3_VSYNC__GPIO1_2,
+	/* USBOTG */
+	MX35_PAD_USBOTG_PWR__USB_TOP_USBOTG_PWR,
+	MX35_PAD_USBOTG_OC__USB_TOP_USBOTG_OC,
+	/* SDCARD */
+	MX35_PAD_SD1_CMD__ESDHC1_CMD,
+	MX35_PAD_SD1_CLK__ESDHC1_CLK,
+	MX35_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX35_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX35_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX35_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* PMIC */
+	MX35_PAD_GPIO2_0__GPIO2_0,
+	/* GPIO keys */
+	MX35_PAD_SCKR__GPIO1_4,
+	MX35_PAD_COMPARE__GPIO1_5,
+	MX35_PAD_SCKT__GPIO1_7,
+	MX35_PAD_FST__GPIO1_8,
+	MX35_PAD_HCKT__GPIO1_9,
+	MX35_PAD_TX5_RX0__GPIO1_10,
+	MX35_PAD_TX4_RX1__GPIO1_11,
+	MX35_PAD_TX3_RX2__GPIO1_12,
+};
+
+/* USB Device config */
+static const struct fsl_usb2_platform_data otg_device_pdata __initconst = {
+	.operating_mode	= FSL_USB2_DR_DEVICE,
+	.phy_mode	= FSL_USB2_PHY_UTMI,
+	.workaround	= FLS_USB2_WORKAROUND_ENGCM09152,
+};
+
+static int vpr200_usbh_init(struct platform_device *pdev)
+{
+	return mx35_initialize_usb_hw(pdev->id,
+			MXC_EHCI_INTERFACE_SINGLE_UNI | MXC_EHCI_INTERNAL_PHY);
+}
+
+/* USB HOST config */
+static const struct mxc_usbh_platform_data usb_host_pdata __initconst = {
+	.init = vpr200_usbh_init,
+	.portsc = MXC_EHCI_MODE_SERIAL,
+};
+
+static struct platform_device *devices[] __initdata = {
+	&vpr200_flash,
+	&vpr200_device_gpiokeys,
+};
+
+/*
+ * Board specific initialization.
+ */
+static void __init vpr200_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(vpr200_pads, ARRAY_SIZE(vpr200_pads));
+
+	imx35_add_fec(NULL);
+	imx35_add_imx2_wdt(NULL);
+
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+
+	if (0 != gpio_request(GPIO_LCDPWR, "LCDPWR"))
+		printk(KERN_WARNING "vpr200: Couldn't get LCDPWR gpio\n");
+	else
+		gpio_direction_output(GPIO_LCDPWR, 0);
+
+	if (0 != gpio_request(GPIO_PMIC_INT, "PMIC_INT"))
+		printk(KERN_WARNING "vpr200: Couldn't get PMIC_INT gpio\n");
+	else
+		gpio_direction_input(GPIO_PMIC_INT);
+
+	imx35_add_imx_uart0(NULL);
+	imx35_add_imx_uart2(NULL);
+
+	mxc_register_device(&mx3_ipu, &mx3_ipu_data);
+	mxc_register_device(&mx3_fb, &mx3fb_pdata);
+
+	imx35_add_fsl_usb2_udc(&otg_device_pdata);
+	imx35_add_mxc_ehci_hs(&usb_host_pdata);
+
+	imx35_add_mxc_nand(&vpr200_nand_board_info);
+	imx35_add_sdhci_esdhc_imx(0, NULL);
+
+	i2c_register_board_info(0, vpr200_i2c_devices,
+			ARRAY_SIZE(vpr200_i2c_devices));
+
+	imx35_add_imx_i2c0(&vpr200_i2c0_data);
+}
+
+static void __init vpr200_timer_init(void)
+{
+	mx35_clocks_init();
+}
+
+struct sys_timer vpr200_timer = {
+	.init	= vpr200_timer_init,
+};
+
+MACHINE_START(VPR200, "VPR200")
+	/* Maintainer: Creative Product Design */
+	.map_io = mx35_map_io,
+	.init_early = imx35_init_early,
+	.init_irq = mx35_init_irq,
+	.timer = &vpr200_timer,
+	.init_machine = vpr200_board_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-mx3/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,8 +5,8 @@
 # Object file lists.
 
 obj-y				:= mm.o devices.o cpu.o
-obj-$(CONFIG_SOC_IMX31)		+= clock-imx31.o iomux-imx31.o
-obj-$(CONFIG_SOC_IMX35)		+= clock-imx35.o
+obj-$(CONFIG_SOC_IMX31)		+= clock-imx31.o iomux-imx31.o ehci-imx31.o
+obj-$(CONFIG_SOC_IMX35)		+= clock-imx35.o ehci-imx35.o
 obj-$(CONFIG_MACH_MX31ADS)	+= mach-mx31ads.o
 obj-$(CONFIG_MACH_MX31LILLY)	+= mach-mx31lilly.o mx31lilly-db.o
 obj-$(CONFIG_MACH_MX31LITE)	+= mach-mx31lite.o mx31lite-db.o
@@ -20,5 +20,7 @@
 obj-$(CONFIG_MACH_ARMADILLO5X0) += mach-armadillo5x0.o
 obj-$(CONFIG_MACH_MX35_3DS)	+= mach-mx35_3ds.o
 obj-$(CONFIG_MACH_KZM_ARM11_01)	+= mach-kzm_arm11_01.o
+obj-$(CONFIG_MACH_BUG)		+= mach-bug.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX35)	+= mach-cpuimx35.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD)	+= eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MACH_VPR200)	+= mach-vpr200.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mm.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,14 +27,8 @@
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-v3.h>
-
-/*!
- * @file mm.c
- *
- * @brief This file creates static virtual to physical mappings, common to all MX3 boards.
- *
- * @ingroup Memory
- */
+#include <mach/gpio.h>
+#include <mach/irqs.h>
 
 #ifdef CONFIG_SOC_IMX31
 static struct map_desc mx31_io_desc[] __initdata = {
@@ -52,17 +46,25 @@
  */
 void __init mx31_map_io(void)
 {
+	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
+}
+
+void __init imx31_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX31);
 	mxc_arch_reset_init(MX31_IO_ADDRESS(MX31_WDOG_BASE_ADDR));
-
-	iotable_init(mx31_io_desc, ARRAY_SIZE(mx31_io_desc));
 }
 
-int imx31_register_gpios(void);
+static struct mxc_gpio_port imx31_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
+};
+
 void __init mx31_init_irq(void)
 {
 	mxc_init_irq(MX31_IO_ADDRESS(MX31_AVIC_BASE_ADDR));
-	imx31_register_gpios();
+	mxc_gpio_init(imx31_gpio_ports,	ARRAY_SIZE(imx31_gpio_ports));
 }
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
@@ -77,18 +79,26 @@
 
 void __init mx35_map_io(void)
 {
+	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
+}
+
+void __init imx35_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX35);
 	mxc_iomux_v3_init(MX35_IO_ADDRESS(MX35_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX35_IO_ADDRESS(MX35_WDOG_BASE_ADDR));
-
-	iotable_init(mx35_io_desc, ARRAY_SIZE(mx35_io_desc));
 }
 
-int imx35_register_gpios(void);
+static struct mxc_gpio_port imx35_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
+	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
+};
+
 void __init mx35_init_irq(void)
 {
 	mxc_init_irq(MX35_IO_ADDRESS(MX35_AVIC_BASE_ADDR));
-	imx35_register_gpios();
+	mxc_gpio_init(imx35_gpio_ports,	ARRAY_SIZE(imx35_gpio_ports));
 }
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
@@ -129,4 +139,3 @@
 
 arch_initcall(mxc_init_l2x0);
 #endif
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mx31moboard-devboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/gpio.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/types.h>
@@ -149,7 +150,10 @@
 	mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
 	mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_SINGLE_UNI);
 }
 
 #define USBH1_VBUSEN_B	IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
@@ -187,7 +191,6 @@
 static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 	.init	= devboard_usbh1_hw_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
 static int __init devboard_usbh1_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mx31moboard-marxbot.c	2011-05-19 00:06:34.000000000 -0400
@@ -265,7 +265,10 @@
 	mxc_iomux_set_pad(MX31_PIN_CSPI1_SPI_RDY, USB_PAD_CFG);
 	mxc_iomux_set_pad(MX31_PIN_SFS6, USB_PAD_CFG);
 
-	return 0;
+	mdelay(10);
+
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_INTERFACE_SINGLE_UNI);
 }
 
 #define USBH1_VBUSEN_B	IOMUX_TO_GPIO(MX31_PIN_NFRE_B)
@@ -303,7 +306,6 @@
 static struct mxc_usbh_platform_data usbh1_pdata __initdata = {
 	.init	= marxbot_usbh1_hw_init,
 	.portsc	= MXC_EHCI_MODE_UTMI | MXC_EHCI_SERIAL,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_INTERFACE_SINGLE_UNI,
 };
 
 static int __init marxbot_usbh1_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mx31moboard-smartbot.c linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mx31moboard-smartbot.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx3/mx31moboard-smartbot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx3/mx31moboard-smartbot.c	2011-05-19 00:06:34.000000000 -0400
@@ -123,17 +123,24 @@
 
 #if defined(CONFIG_USB_ULPI)
 
+static int smartbot_otg_init(struct platform_device *pdev)
+{
+	return mx31_initialize_usb_hw(pdev->id, MXC_EHCI_POWER_PINS_ENABLED);
+}
+
 static struct mxc_usbh_platform_data otg_host_pdata __initdata = {
+	.init	= smartbot_otg_init,
 	.portsc = MXC_EHCI_MODE_ULPI | MXC_EHCI_UTMI_8BIT,
-	.flags	= MXC_EHCI_POWER_PINS_ENABLED,
 };
 
 static int __init smartbot_otg_host_init(void)
 {
 	struct platform_device *pdev;
 
-	otg_host_pdata.otg = otg_ulpi_create(&mxc_ulpi_access_ops,
-			ULPI_OTG_DRVVBUS | ULPI_OTG_DRVVBUS_EXT);
+	otg_host_pdata.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+		ULPI_OTG_DRVVBUS_EXT);
+	if (!otg_host_pdata.otg)
+		return -ENODEV;
 
 	pdev = imx31_add_mxc_ehci_otg(&otg_host_pdata);
 	if (IS_ERR(pdev))
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-cpuimx51.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-cpuimx51.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-cpuimx51.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-cpuimx51.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,6 @@
 #define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
 #define	MX51_USB_PLL_DIV_24_MHZ		0x02
 
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.mapbase = (unsigned long)(MX51_CS1_BASE_ADDR + 0x400000),
@@ -105,12 +104,9 @@
 		.platform_data = serial_platform_data,
 	},
 };
-#endif
 
 static struct platform_device *devices[] __initdata = {
-#if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	&serial_device,
-#endif
 };
 
 static iomux_v3_cfg_t eukrea_cpuimx51_pads[] = {
@@ -188,7 +184,10 @@
 	v |= MX51_USB_PLL_DIV_19_2_MHZ;
 	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
 }
 
 static int initialize_usbh1_port(struct platform_device *pdev)
@@ -206,13 +205,16 @@
 	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
 	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data dr_utmi_config = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static struct fsl_usb2_platform_data usb_pdata = {
@@ -223,7 +225,6 @@
 static struct mxc_usbh_platform_data usbh1_config = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
 };
 
 static int otg_mode_host;
@@ -298,7 +299,8 @@
 	/* Maintainer: Eric BÃ©nard <eric@eukrea.com> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = eukrea_cpuimx51_init,
 	.timer = &mxc_timer,
+	.init_machine = eukrea_cpuimx51_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-cpuimx51sd.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,7 @@
 
 #include "devices-imx51.h"
 #include "devices.h"
+#include "cpu_op-mx51.h"
 
 #define USBH1_RST		IMX_GPIO_NR(2, 28)
 #define ETH_RST			IMX_GPIO_NR(2, 31)
@@ -109,7 +110,7 @@
 
 	/* Touchscreen */
 	/* IRQ */
-	_MX51_PAD_CSI1_D8__GPIO3_12 | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+	_MX51_PAD_GPIO_NAND__GPIO_NAND | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
 			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
 			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
@@ -118,15 +119,9 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static int ts_get_pendown_state(void)
-{
-	return gpio_get_value(TSC2007_IRQGPIO) ? 0 : 1;
-}
-
 static struct tsc2007_platform_data tsc2007_info = {
 	.model			= 2007,
 	.x_plate_ohms		= 180,
-	.get_pendown_state	= ts_get_pendown_state,
 };
 
 static struct i2c_board_info eukrea_cpuimx51sd_i2c_devices[] = {
@@ -167,7 +162,10 @@
 	v |= MX51_USB_PLL_DIV_19_2_MHZ;
 	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
 }
 
 static int initialize_usbh1_port(struct platform_device *pdev)
@@ -186,13 +184,16 @@
 	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
 			usbother_base + MX51_USB_CTRL_1_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data dr_utmi_config = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static struct fsl_usb2_platform_data usb_pdata = {
@@ -203,7 +204,6 @@
 static struct mxc_usbh_platform_data usbh1_config = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
 };
 
 static int otg_mode_host;
@@ -242,7 +242,7 @@
 static struct spi_board_info cpuimx51sd_spi_device[] = {
 	{
 		.modalias        = "mcp2515",
-		.max_speed_hz    = 6500000,
+		.max_speed_hz    = 10000000,
 		.bus_num         = 0,
 		.mode		= SPI_MODE_0,
 		.chip_select     = 0,
@@ -269,6 +269,10 @@
 	mxc_iomux_v3_setup_multiple_pads(eukrea_cpuimx51sd_pads,
 					ARRAY_SIZE(eukrea_cpuimx51sd_pads));
 
+#if defined(CONFIG_CPU_FREQ_IMX)
+	get_cpu_op = mx51_get_cpu_op;
+#endif
+
 	imx51_add_imx_uart(0, &uart_pdata);
 	imx51_add_mxc_nand(&eukrea_cpuimx51sd_nand_board_info);
 
@@ -329,7 +333,8 @@
 	/* Maintainer: Eric BÃ©nard <eric@eukrea.com> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = eukrea_cpuimx51sd_init,
 	.timer = &mxc_timer,
+	.init_machine = eukrea_cpuimx51sd_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx50_rdp.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx50_rdp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx50_rdp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx50_rdp.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,10 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-#include "devices-mx50.h"
+#include "devices-imx50.h"
+
+#define FEC_EN		IMX_GPIO_NR(6, 23)
+#define FEC_RESET_B	IMX_GPIO_NR(4, 12)
 
 static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
 	/* SD1 */
@@ -102,7 +105,7 @@
 	MX50_PAD_I2C3_SCL__USBOTG_OC,
 
 	MX50_PAD_SSI_RXC__FEC_MDIO,
-	MX50_PAD_SSI_RXC__FEC_MDIO,
+	MX50_PAD_SSI_RXFS__FEC_MDC,
 	MX50_PAD_DISP_D0__FEC_TXCLK,
 	MX50_PAD_DISP_D1__FEC_RX_ER,
 	MX50_PAD_DISP_D2__FEC_RX_DV,
@@ -111,7 +114,6 @@
 	MX50_PAD_DISP_D5__FEC_TX_EN,
 	MX50_PAD_DISP_D6__FEC_TXD1,
 	MX50_PAD_DISP_D7__FEC_TXD0,
-	MX50_PAD_SSI_RXFS__FEC_MDC,
 	MX50_PAD_I2C3_SDA__GPIO_6_23,
 	MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
 
@@ -168,6 +170,24 @@
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
+static const struct fec_platform_data fec_data __initconst = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static inline void mx50_rdp_fec_reset(void)
+{
+	gpio_request(FEC_EN, "fec-en");
+	gpio_direction_output(FEC_EN, 0);
+	gpio_request(FEC_RESET_B, "fec-reset_b");
+	gpio_direction_output(FEC_RESET_B, 0);
+	msleep(1);
+	gpio_set_value(FEC_RESET_B, 1);
+}
+
+static const struct imxi2c_platform_data i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
 /*
  * Board specific initialization.
  */
@@ -178,6 +198,11 @@
 
 	imx50_add_imx_uart(0, &uart_pdata);
 	imx50_add_imx_uart(1, &uart_pdata);
+	mx50_rdp_fec_reset();
+	imx50_add_fec(&fec_data);
+	imx50_add_imx_i2c(0, &i2c_data);
+	imx50_add_imx_i2c(1, &i2c_data);
+	imx50_add_imx_i2c(2, &i2c_data);
 }
 
 static void __init mx50_rdp_timer_init(void)
@@ -191,7 +216,8 @@
 
 MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
 	.map_io = mx50_map_io,
+	.init_early = imx50_init_early,
 	.init_irq = mx50_init_irq,
-	.init_machine = mx50_rdp_board_init,
 	.timer = &mx50_rdp_timer,
+	.init_machine = mx50_rdp_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_3ds.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_3ds.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_3ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_3ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,24 +71,10 @@
 };
 
 /* Serial ports */
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static inline void mxc_init_imx_uart(void)
-{
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* SERIAL_IMX */
-
-#if defined(CONFIG_KEYBOARD_IMX) || defined(CONFIG_KEYBOARD_IMX_MODULE)
 static int mx51_3ds_board_keymap[] = {
 	KEY(0, 0, KEY_1),
 	KEY(0, 1, KEY_2),
@@ -124,16 +110,6 @@
 	.keymap_size	= ARRAY_SIZE(mx51_3ds_board_keymap),
 };
 
-static void mxc_init_keypad(void)
-{
-	imx51_add_imx_keypad(&mx51_3ds_map_data);
-}
-#else
-static inline void mxc_init_keypad(void)
-{
-}
-#endif
-
 static int mx51_3ds_spi2_cs[] = {
 	MXC_SPI_CS(0),
 	MX51_3DS_ECSPI2_CS,
@@ -157,11 +133,14 @@
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx51_3ds_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
 					ARRAY_SIZE(mx51_3ds_pads));
-	mxc_init_imx_uart();
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_imx_uart(1, &uart_pdata);
+	imx51_add_imx_uart(2, &uart_pdata);
 
 	imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
 	spi_register_board_info(mx51_3ds_spi_nor_device,
@@ -172,7 +151,8 @@
 				    "devices on the board are unusable.\n");
 
 	imx51_add_sdhci_esdhc_imx(0, NULL);
-	mxc_init_keypad();
+	imx51_add_imx_keypad(&mx51_3ds_map_data);
+	imx51_add_imx2_wdt(0, NULL);
 }
 
 static void __init mx51_3ds_timer_init(void)
@@ -180,15 +160,16 @@
 	mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= mx51_3ds_timer_init,
+static struct sys_timer mx51_3ds_timer = {
+	.init = mx51_3ds_timer_init,
 };
 
 MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = mxc_board_init,
-	.timer = &mxc_timer,
+	.timer = &mx51_3ds_timer,
+	.init_machine = mx51_3ds_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_babbage.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_babbage.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_babbage.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_babbage.c	2011-05-19 00:06:34.000000000 -0400
@@ -161,23 +161,10 @@
 };
 
 /* Serial ports */
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
 static const struct imxuart_platform_data uart_pdata __initconst = {
 	.flags = IMXUART_HAVE_RTSCTS,
 };
 
-static inline void mxc_init_imx_uart(void)
-{
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* SERIAL_IMX */
-
 static const struct imxi2c_platform_data babbage_i2c_data __initconst = {
 	.bitrate = 100000,
 };
@@ -241,13 +228,12 @@
 	int ret;
 
 	/* reset FEC PHY */
-	ret = gpio_request(BABBAGE_FEC_PHY_RESET, "fec-phy-reset");
+	ret = gpio_request_one(BABBAGE_FEC_PHY_RESET,
+					GPIOF_OUT_INIT_LOW, "fec-phy-reset");
 	if (ret) {
 		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
 		return;
 	}
-	gpio_direction_output(BABBAGE_FEC_PHY_RESET, 0);
-	gpio_set_value(BABBAGE_FEC_PHY_RESET, 0);
 	msleep(1);
 	gpio_set_value(BABBAGE_FEC_PHY_RESET, 1);
 }
@@ -272,7 +258,10 @@
 	v |= MX51_USB_PLL_DIV_19_2_MHZ;
 	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_INTERNAL_PHY);
 }
 
 static int initialize_usbh1_port(struct platform_device *pdev)
@@ -290,13 +279,16 @@
 	v = __raw_readl(usbother_base + MX51_USB_CTRL_1_OFFSET);
 	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN, usbother_base + MX51_USB_CTRL_1_OFFSET);
 	iounmap(usb_base);
-	return 0;
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(1, MXC_EHCI_POWER_PINS_ENABLED |
+			MXC_EHCI_ITC_NO_THRESHOLD);
 }
 
 static struct mxc_usbh_platform_data dr_utmi_config = {
 	.init		= initialize_otg_port,
 	.portsc	= MXC_EHCI_UTMI_16BIT,
-	.flags	= MXC_EHCI_INTERNAL_PHY,
 };
 
 static struct fsl_usb2_platform_data usb_pdata = {
@@ -307,7 +299,6 @@
 static struct mxc_usbh_platform_data usbh1_config = {
 	.init		= initialize_usbh1_port,
 	.portsc	= MXC_EHCI_MODE_ULPI,
-	.flags	= (MXC_EHCI_POWER_PINS_ENABLED | MXC_EHCI_ITC_NO_THRESHOLD),
 };
 
 static int otg_mode_host;
@@ -349,7 +340,7 @@
 /*
  * Board specific initialization.
  */
-static void __init mxc_board_init(void)
+static void __init mx51_babbage_init(void)
 {
 	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
 	iomux_v3_cfg_t power_key = _MX51_PAD_EIM_A27__GPIO2_21 |
@@ -360,7 +351,11 @@
 #endif
 	mxc_iomux_v3_setup_multiple_pads(mx51babbage_pads,
 					ARRAY_SIZE(mx51babbage_pads));
-	mxc_init_imx_uart();
+
+	imx51_add_imx_uart(0, &uart_pdata);
+	imx51_add_imx_uart(1, &uart_pdata);
+	imx51_add_imx_uart(2, &uart_pdata);
+
 	babbage_fec_reset();
 	imx51_add_fec(NULL);
 
@@ -399,15 +394,16 @@
 	mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= mx51_babbage_timer_init,
+static struct sys_timer mx51_babbage_timer = {
+	.init = mx51_babbage_timer_init,
 };
 
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine = mxc_board_init,
-	.timer = &mxc_timer,
+	.timer = &mx51_babbage_timer,
+	.init_machine = mx51_babbage_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_efikamx.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,9 @@
 #include <linux/fsl_devices.h>
 #include <linux/spi/flash.h>
 #include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
 
 #include <mach/common.h>
 #include <mach/hardware.h>
@@ -40,8 +43,7 @@
 
 #include "devices-imx51.h"
 #include "devices.h"
-
-#define	MX51_USB_PLL_DIV_24_MHZ	0x01
+#include "efika.h"
 
 #define EFIKAMX_PCBID0		IMX_GPIO_NR(3, 16)
 #define EFIKAMX_PCBID1		IMX_GPIO_NR(3, 17)
@@ -53,13 +55,14 @@
 
 #define EFIKAMX_POWER_KEY	IMX_GPIO_NR(2, 31)
 
-#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
-#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
-
 /* board 1.1 doesn't have same reset gpio */
 #define EFIKAMX_RESET1_1	IMX_GPIO_NR(3, 2)
 #define EFIKAMX_RESET		IMX_GPIO_NR(1, 4)
 
+#define EFIKAMX_POWEROFF	IMX_GPIO_NR(4, 13)
+
+#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
+
 /* the pci ids pin have pull up. they're driven low according to board id */
 #define MX51_PAD_PCBID0	IOMUX_PAD(0x518, 0x130, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
 #define MX51_PAD_PCBID1	IOMUX_PAD(0x51C, 0x134, 3, 0x0,   0, PAD_CTL_PUS_100K_UP)
@@ -67,38 +70,11 @@
 #define MX51_PAD_PWRKEY	IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
 
 static iomux_v3_cfg_t mx51efikamx_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
 	/* board id */
 	MX51_PAD_PCBID0,
 	MX51_PAD_PCBID1,
 	MX51_PAD_PCBID2,
 
-	/* SD 1 */
-	MX51_PAD_SD1_CMD__SD1_CMD,
-	MX51_PAD_SD1_CLK__SD1_CLK,
-	MX51_PAD_SD1_DATA0__SD1_DATA0,
-	MX51_PAD_SD1_DATA1__SD1_DATA1,
-	MX51_PAD_SD1_DATA2__SD1_DATA2,
-	MX51_PAD_SD1_DATA3__SD1_DATA3,
-
-	/* SD 2 */
-	MX51_PAD_SD2_CMD__SD2_CMD,
-	MX51_PAD_SD2_CLK__SD2_CLK,
-	MX51_PAD_SD2_DATA0__SD2_DATA0,
-	MX51_PAD_SD2_DATA1__SD2_DATA1,
-	MX51_PAD_SD2_DATA2__SD2_DATA2,
-	MX51_PAD_SD2_DATA3__SD2_DATA3,
-
-	/* SD/MMC WP/CD */
-	MX51_PAD_GPIO1_0__SD1_CD,
-	MX51_PAD_GPIO1_1__SD1_WP,
-	MX51_PAD_GPIO1_7__SD2_WP,
-	MX51_PAD_GPIO1_8__SD2_CD,
-
 	/* leds */
 	MX51_PAD_CSI1_D9__GPIO3_13,
 	MX51_PAD_CSI1_VSYNC__GPIO3_14,
@@ -107,64 +83,12 @@
 	/* power key */
 	MX51_PAD_PWRKEY,
 
-	/* spi */
-	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
-	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
-	MX51_PAD_CSPI1_SS0__GPIO4_24,
-	MX51_PAD_CSPI1_SS1__GPIO4_25,
-	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
-	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
-
 	/* reset */
 	MX51_PAD_DI1_PIN13__GPIO3_2,
 	MX51_PAD_GPIO1_4__GPIO1_4,
-};
-
-/* Serial ports */
-#if defined(CONFIG_SERIAL_IMX) || defined(CONFIG_SERIAL_IMX_MODULE)
-static const struct imxuart_platform_data uart_pdata = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static inline void mxc_init_imx_uart(void)
-{
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-}
-#else /* !SERIAL_IMX */
-static inline void mxc_init_imx_uart(void)
-{
-}
-#endif /* SERIAL_IMX */
 
-/* This function is board specific as the bit mask for the plldiv will also
- * be different for other Freescale SoCs, thus a common bitmask is not
- * possible and cannot get place in /plat-mxc/ehci.c.
- */
-static int initialize_otg_port(struct platform_device *pdev)
-{
-	u32 v;
-	void __iomem *usb_base;
-	void __iomem *usbother_base;
-	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
-	if (!usb_base)
-		return -ENOMEM;
-	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
-
-	/* Set the PHY clock to 19.2MHz */
-	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
-	v |= MX51_USB_PLL_DIV_24_MHZ;
-	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
-	iounmap(usb_base);
-	return 0;
-}
-
-static struct mxc_usbh_platform_data dr_utmi_config = {
-	.init   = initialize_otg_port,
-	.portsc = MXC_EHCI_UTMI_16BIT,
-	.flags  = MXC_EHCI_INTERNAL_PHY,
+	/* power off */
+	MX51_PAD_CSI2_VSYNC__GPIO4_13,
 };
 
 /*   PCBID2  PCBID1 PCBID0  STATE
@@ -265,47 +189,6 @@
 	.nbuttons = ARRAY_SIZE(mx51_efikamx_powerkey),
 };
 
-static struct mtd_partition mx51_efikamx_spi_nor_partitions[] = {
-	{
-	 .name = "u-boot",
-	 .offset = 0,
-	 .size = SZ_256K,
-	},
-	{
-	  .name = "config",
-	  .offset = MTDPART_OFS_APPEND,
-	  .size = SZ_64K,
-	},
-};
-
-static struct flash_platform_data mx51_efikamx_spi_flash_data = {
-	.name		= "spi_flash",
-	.parts		= mx51_efikamx_spi_nor_partitions,
-	.nr_parts	= ARRAY_SIZE(mx51_efikamx_spi_nor_partitions),
-	.type		= "sst25vf032b",
-};
-
-static struct spi_board_info mx51_efikamx_spi_board_info[] __initdata = {
-	{
-		.modalias = "m25p80",
-		.max_speed_hz = 25000000,
-		.bus_num = 0,
-		.chip_select = 1,
-		.platform_data = &mx51_efikamx_spi_flash_data,
-		.irq = -1,
-	},
-};
-
-static int mx51_efikamx_spi_cs[] = {
-	EFIKAMX_SPI_CS0,
-	EFIKAMX_SPI_CS1,
-};
-
-static const struct spi_imx_master mx51_efikamx_spi_pdata __initconst = {
-	.chipselect     = mx51_efikamx_spi_cs,
-	.num_chipselect = ARRAY_SIZE(mx51_efikamx_spi_cs),
-};
-
 void mx51_efikamx_reset(void)
 {
 	if (system_rev == 0x11)
@@ -314,14 +197,53 @@
 		gpio_direction_output(EFIKAMX_RESET, 0);
 }
 
-static void __init mxc_board_init(void)
+static struct regulator *pwgt1, *pwgt2, *coincell;
+
+static void mx51_efikamx_power_off(void)
+{
+	if (!IS_ERR(coincell))
+		regulator_disable(coincell);
+
+	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+		regulator_disable(pwgt2);
+		regulator_disable(pwgt1);
+	}
+	gpio_direction_output(EFIKAMX_POWEROFF, 1);
+}
+
+static int __init mx51_efikamx_power_init(void)
+{
+	if (machine_is_mx51_efikamx()) {
+		pwgt1 = regulator_get(NULL, "pwgt1");
+		pwgt2 = regulator_get(NULL, "pwgt2");
+		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+			regulator_enable(pwgt1);
+			regulator_enable(pwgt2);
+		}
+		gpio_request(EFIKAMX_POWEROFF, "poweroff");
+		pm_power_off = mx51_efikamx_power_off;
+
+		/* enable coincell charger. maybe need a small power driver ? */
+		coincell = regulator_get(NULL, "coincell");
+		if (!IS_ERR(coincell)) {
+			regulator_set_voltage(coincell, 3000000, 3000000);
+			regulator_enable(coincell);
+		}
+
+		regulator_has_full_constraints();
+	}
+
+	return 0;
+}
+late_initcall(mx51_efikamx_power_init);
+
+static void __init mx51_efikamx_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx51efikamx_pads,
 					ARRAY_SIZE(mx51efikamx_pads));
+	efika_board_common_init();
+
 	mx51_efikamx_board_id();
-	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
-	mxc_init_imx_uart();
-	imx51_add_sdhci_esdhc_imx(0, NULL);
 
 	/* on < 1.2 boards both SD controllers are used */
 	if (system_rev < 0x12) {
@@ -332,10 +254,6 @@
 	platform_device_register(&mx51_efikamx_leds_device);
 	imx51_add_gpio_keys(&mx51_efikamx_powerkey_data);
 
-	spi_register_board_info(mx51_efikamx_spi_board_info,
-		ARRAY_SIZE(mx51_efikamx_spi_board_info));
-	imx51_add_ecspi(0, &mx51_efikamx_spi_pdata);
-
 	if (system_rev == 0x11) {
 		gpio_request(EFIKAMX_RESET1_1, "reset");
 		gpio_direction_output(EFIKAMX_RESET1_1, 1);
@@ -343,6 +261,20 @@
 		gpio_request(EFIKAMX_RESET, "reset");
 		gpio_direction_output(EFIKAMX_RESET, 1);
 	}
+
+	/*
+	 * enable wifi by default only on mx
+	 * sb and mx have same wlan pin but the value to enable it are
+	 * different :/
+	 */
+	gpio_request(EFIKA_WLAN_EN, "wlan_en");
+	gpio_direction_output(EFIKA_WLAN_EN, 0);
+	msleep(10);
+
+	gpio_request(EFIKA_WLAN_RESET, "wlan_rst");
+	gpio_direction_output(EFIKA_WLAN_RESET, 0);
+	msleep(10);
+	gpio_set_value(EFIKA_WLAN_RESET, 1);
 }
 
 static void __init mx51_efikamx_timer_init(void)
@@ -350,15 +282,16 @@
 	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= mx51_efikamx_timer_init,
+static struct sys_timer mx51_efikamx_timer = {
+	.init = mx51_efikamx_timer_init,
 };
 
 MACHINE_START(MX51_EFIKAMX, "Genesi EfikaMX nettop")
 	/* Maintainer: Amit Kucheria <amit.kucheria@linaro.org> */
 	.boot_params = MX51_PHYS_OFFSET + 0x100,
 	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
-	.init_machine =  mxc_board_init,
-	.timer = &mxc_timer,
+	.timer = &mx51_efikamx_timer,
+	.init_machine = mx51_efikamx_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx51_efikasb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,283 @@
+/*
+ * Copyright (C) Arnaud Patard <arnaud.patard@rtp-net.org>
+ *
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, 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/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_ehci.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+#include "efika.h"
+
+#define EFIKASB_USBH2_STP	IMX_GPIO_NR(2, 20)
+#define EFIKASB_GREEN_LED	IMX_GPIO_NR(1, 3)
+#define EFIKASB_WHITE_LED	IMX_GPIO_NR(2, 25)
+#define EFIKASB_PCBID0		IMX_GPIO_NR(2, 28)
+#define EFIKASB_PCBID1		IMX_GPIO_NR(2, 29)
+#define EFIKASB_PWRKEY		IMX_GPIO_NR(2, 31)
+#define EFIKASB_LID		IMX_GPIO_NR(3, 14)
+#define EFIKASB_POWEROFF	IMX_GPIO_NR(4, 13)
+#define EFIKASB_RFKILL		IMX_GPIO_NR(3, 1)
+
+#define MX51_PAD_PWRKEY IOMUX_PAD(0x48c, 0x0f8, 1, 0x0,   0, PAD_CTL_PUS_100K_UP | PAD_CTL_PKE)
+
+static iomux_v3_cfg_t mx51efikasb_pads[] = {
+	/* USB HOST2 */
+	MX51_PAD_EIM_D16__USBH2_DATA0,
+	MX51_PAD_EIM_D17__USBH2_DATA1,
+	MX51_PAD_EIM_D18__USBH2_DATA2,
+	MX51_PAD_EIM_D19__USBH2_DATA3,
+	MX51_PAD_EIM_D20__USBH2_DATA4,
+	MX51_PAD_EIM_D21__USBH2_DATA5,
+	MX51_PAD_EIM_D22__USBH2_DATA6,
+	MX51_PAD_EIM_D23__USBH2_DATA7,
+	MX51_PAD_EIM_A24__USBH2_CLK,
+	MX51_PAD_EIM_A25__USBH2_DIR,
+	MX51_PAD_EIM_A26__USBH2_STP,
+	MX51_PAD_EIM_A27__USBH2_NXT,
+
+	/* leds */
+	MX51_PAD_EIM_CS0__GPIO2_25,
+	MX51_PAD_GPIO1_3__GPIO1_3,
+
+	/* pcb id */
+	MX51_PAD_EIM_CS3__GPIO2_28,
+	MX51_PAD_EIM_CS4__GPIO2_29,
+
+	/* lid */
+	MX51_PAD_CSI1_VSYNC__GPIO3_14,
+
+	/* power key*/
+	MX51_PAD_PWRKEY,
+
+	/* wifi/bt button */
+	MX51_PAD_DI1_PIN12__GPIO3_1,
+
+	/* power off */
+	MX51_PAD_CSI2_VSYNC__GPIO4_13,
+
+	/* wdog reset */
+	MX51_PAD_GPIO1_4__WDOG1_WDOG_B,
+
+	/* BT */
+	MX51_PAD_EIM_A17__GPIO2_11,
+};
+
+static int initialize_usbh2_port(struct platform_device *pdev)
+{
+	iomux_v3_cfg_t usbh2stp = MX51_PAD_EIM_A26__USBH2_STP;
+	iomux_v3_cfg_t usbh2gpio = MX51_PAD_EIM_A26__GPIO2_20;
+
+	mxc_iomux_v3_setup_pad(usbh2gpio);
+	gpio_request(EFIKASB_USBH2_STP, "usbh2_stp");
+	gpio_direction_output(EFIKASB_USBH2_STP, 0);
+	msleep(1);
+	gpio_set_value(EFIKASB_USBH2_STP, 1);
+	msleep(1);
+
+	gpio_free(EFIKASB_USBH2_STP);
+	mxc_iomux_v3_setup_pad(usbh2stp);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh2_config = {
+	.init   = initialize_usbh2_port,
+	.portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void __init mx51_efikasb_usb(void)
+{
+	usbh2_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+	if (usbh2_config.otg)
+		mxc_register_device(&mxc_usbh2_device, &usbh2_config);
+}
+
+static struct gpio_led mx51_efikasb_leds[] = {
+	{
+		.name = "efikasb:green",
+		.default_trigger = "default-on",
+		.gpio = EFIKASB_GREEN_LED,
+		.active_low = 1,
+	},
+	{
+		.name = "efikasb:white",
+		.default_trigger = "caps",
+		.gpio = EFIKASB_WHITE_LED,
+	},
+};
+
+static struct gpio_led_platform_data mx51_efikasb_leds_data = {
+	.leds = mx51_efikasb_leds,
+	.num_leds = ARRAY_SIZE(mx51_efikasb_leds),
+};
+
+static struct platform_device mx51_efikasb_leds_device = {
+	.name = "leds-gpio",
+	.id = -1,
+	.dev = {
+		.platform_data = &mx51_efikasb_leds_data,
+	},
+};
+
+static struct gpio_keys_button mx51_efikasb_keys[] = {
+	{
+		.code = KEY_POWER,
+		.gpio = EFIKASB_PWRKEY,
+		.type = EV_PWR,
+		.desc = "Power Button",
+		.wakeup = 1,
+		.debounce_interval = 10, /* ms */
+	},
+	{
+		.code = SW_LID,
+		.gpio = EFIKASB_LID,
+		.type = EV_SW,
+		.desc = "Lid Switch",
+	},
+	{
+		/* SW_RFKILLALL vs KEY_RFKILL ? */
+		.code = SW_RFKILL_ALL,
+		.gpio = EFIKASB_RFKILL,
+		.type = EV_SW,
+		.desc = "rfkill",
+	},
+};
+
+static const struct gpio_keys_platform_data mx51_efikasb_keys_data __initconst = {
+	.buttons = mx51_efikasb_keys,
+	.nbuttons = ARRAY_SIZE(mx51_efikasb_keys),
+};
+
+static struct regulator *pwgt1, *pwgt2;
+
+static void mx51_efikasb_power_off(void)
+{
+	gpio_set_value(EFIKA_USB_PHY_RESET, 0);
+
+	if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+		regulator_disable(pwgt2);
+		regulator_disable(pwgt1);
+	}
+	gpio_direction_output(EFIKASB_POWEROFF, 1);
+}
+
+static int __init mx51_efikasb_power_init(void)
+{
+	if (machine_is_mx51_efikasb()) {
+		pwgt1 = regulator_get(NULL, "pwgt1");
+		pwgt2 = regulator_get(NULL, "pwgt2");
+		if (!IS_ERR(pwgt1) && !IS_ERR(pwgt2)) {
+			regulator_enable(pwgt1);
+			regulator_enable(pwgt2);
+		}
+		gpio_request(EFIKASB_POWEROFF, "poweroff");
+		pm_power_off = mx51_efikasb_power_off;
+
+		regulator_has_full_constraints();
+	}
+
+	return 0;
+}
+late_initcall(mx51_efikasb_power_init);
+
+/* 01     R1.3 board
+   10     R2.0 board */
+static void __init mx51_efikasb_board_id(void)
+{
+	int id;
+
+	gpio_request(EFIKASB_PCBID0, "pcb id0");
+	gpio_direction_input(EFIKASB_PCBID0);
+	gpio_request(EFIKASB_PCBID1, "pcb id1");
+	gpio_direction_input(EFIKASB_PCBID1);
+
+	id = gpio_get_value(EFIKASB_PCBID0);
+	id |= gpio_get_value(EFIKASB_PCBID1) << 1;
+
+	switch (id) {
+	default:
+		break;
+	case 1:
+		system_rev = 0x13;
+		break;
+	case 2:
+		system_rev = 0x20;
+		break;
+	}
+}
+
+static void __init efikasb_board_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51efikasb_pads,
+					ARRAY_SIZE(mx51efikasb_pads));
+	efika_board_common_init();
+
+	mx51_efikasb_board_id();
+	mx51_efikasb_usb();
+	imx51_add_sdhci_esdhc_imx(1, NULL);
+
+	platform_device_register(&mx51_efikasb_leds_device);
+	imx51_add_gpio_keys(&mx51_efikasb_keys_data);
+
+}
+
+static void __init mx51_efikasb_timer_init(void)
+{
+	mx51_clocks_init(32768, 24000000, 22579200, 24576000);
+}
+
+static struct sys_timer mx51_efikasb_timer = {
+	.init	= mx51_efikasb_timer_init,
+};
+
+MACHINE_START(MX51_EFIKASB, "Genesi Efika Smartbook")
+	.boot_params = MX51_PHYS_OFFSET + 0x100,
+	.map_io = mx51_map_io,
+	.init_early = imx51_init_early,
+	.init_irq = mx51_init_irq,
+	.init_machine =  efikasb_board_init,
+	.timer = &mx51_efikasb_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx53_evk.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx53_evk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx53_evk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx53_evk.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010-2011 Freescale Semiconductor, Inc. All Rights Reserved.
  * Copyright (C) 2010 Yong Shen. <Yong.Shen@linaro.org>
  */
 
@@ -34,7 +34,7 @@
 #include <mach/imx-uart.h>
 #include <mach/iomux-mx53.h>
 
-#define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
+#define MX53_EVK_FEC_PHY_RST	IMX_GPIO_NR(7, 6)
 #define EVK_ECSPI1_CS0		IMX_GPIO_NR(2, 30)
 #define EVK_ECSPI1_CS1		IMX_GPIO_NR(3, 19)
 
@@ -42,28 +42,24 @@
 #include "devices-imx53.h"
 
 static iomux_v3_cfg_t mx53_evk_pads[] = {
-	MX53_PAD_CSI0_D10__UART1_TXD,
-	MX53_PAD_CSI0_D11__UART1_RXD,
-	MX53_PAD_ATA_DIOW__UART1_TXD,
-	MX53_PAD_ATA_DMACK__UART1_RXD,
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
 
-	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
-	MX53_PAD_ATA_DMARQ__UART2_TXD,
-	MX53_PAD_ATA_DIOR__UART2_RTS,
-	MX53_PAD_ATA_INTRQ__UART2_CTS,
+	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
+	MX53_PAD_PATA_DIOR__UART2_RTS,
+	MX53_PAD_PATA_INTRQ__UART2_CTS,
 
-	MX53_PAD_ATA_CS_0__UART3_TXD,
-	MX53_PAD_ATA_CS_1__UART3_RXD,
-	MX53_PAD_ATA_DA_1__UART3_CTS,
-	MX53_PAD_ATA_DA_2__UART3_RTS,
+	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
 
-	MX53_PAD_EIM_D16__CSPI1_SCLK,
-	MX53_PAD_EIM_D17__CSPI1_MISO,
-	MX53_PAD_EIM_D18__CSPI1_MOSI,
+	MX53_PAD_EIM_D16__ECSPI1_SCLK,
+	MX53_PAD_EIM_D17__ECSPI1_MISO,
+	MX53_PAD_EIM_D18__ECSPI1_MOSI,
 
 	/* ecspi chip select lines */
-	MX53_PAD_EIM_EB2__GPIO_2_30,
-	MX53_PAD_EIM_D19__GPIO_3_19,
+	MX53_PAD_EIM_EB2__GPIO2_30,
+	MX53_PAD_EIM_D19__GPIO3_19,
 };
 
 static const struct imxuart_platform_data mx53_evk_uart_pdata __initconst = {
@@ -72,9 +68,9 @@
 
 static inline void mx53_evk_init_uart(void)
 {
-	imx53_add_imx_uart(0, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(0, NULL);
 	imx53_add_imx_uart(1, &mx53_evk_uart_pdata);
-	imx53_add_imx_uart(2, &mx53_evk_uart_pdata);
+	imx53_add_imx_uart(2, NULL);
 }
 
 static const struct imxi2c_platform_data mx53_evk_i2c_data __initconst = {
@@ -86,15 +82,14 @@
 	int ret;
 
 	/* reset FEC PHY */
-	ret = gpio_request(SMD_FEC_PHY_RST, "fec-phy-reset");
+	ret = gpio_request_one(MX53_EVK_FEC_PHY_RST, GPIOF_OUT_INIT_LOW,
+							"fec-phy-reset");
 	if (ret) {
 		printk(KERN_ERR"failed to get GPIO_FEC_PHY_RESET: %d\n", ret);
 		return;
 	}
-	gpio_direction_output(SMD_FEC_PHY_RST, 0);
-	gpio_set_value(SMD_FEC_PHY_RST, 0);
 	msleep(1);
-	gpio_set_value(SMD_FEC_PHY_RST, 1);
+	gpio_set_value(MX53_EVK_FEC_PHY_RST, 1);
 }
 
 static struct fec_platform_data mx53_evk_fec_pdata = {
@@ -139,6 +134,7 @@
 	spi_register_board_info(mx53_evk_spi_board_info,
 		ARRAY_SIZE(mx53_evk_spi_board_info));
 	imx53_add_ecspi(0, &mx53_evk_spi_data);
+	imx53_add_imx2_wdt(0, NULL);
 }
 
 static void __init mx53_evk_timer_init(void)
@@ -152,7 +148,8 @@
 
 MACHINE_START(MX53_EVK, "Freescale MX53 EVK Board")
 	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
-	.init_machine = mx53_evk_board_init,
 	.timer = &mx53_evk_timer,
+	.init_machine = mx53_evk_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx53_loco.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx53_loco.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx53_loco.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx53_loco.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,36 +36,174 @@
 #include "crm_regs.h"
 #include "devices-imx53.h"
 
+#define MX53_LOCO_POWER			IMX_GPIO_NR(1, 8)
+#define MX53_LOCO_UI1			IMX_GPIO_NR(2, 14)
+#define MX53_LOCO_UI2			IMX_GPIO_NR(2, 15)
 #define LOCO_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
 
 static iomux_v3_cfg_t mx53_loco_pads[] = {
-	MX53_PAD_CSI0_D10__UART1_TXD,
-	MX53_PAD_CSI0_D11__UART1_RXD,
-	MX53_PAD_ATA_DIOW__UART1_TXD,
-	MX53_PAD_ATA_DMACK__UART1_RXD,
+	/* FEC */
+	MX53_PAD_FEC_MDC__FEC_MDC,
+	MX53_PAD_FEC_MDIO__FEC_MDIO,
+	MX53_PAD_FEC_REF_CLK__FEC_TX_CLK,
+	MX53_PAD_FEC_RX_ER__FEC_RX_ER,
+	MX53_PAD_FEC_CRS_DV__FEC_RX_DV,
+	MX53_PAD_FEC_RXD1__FEC_RDATA_1,
+	MX53_PAD_FEC_RXD0__FEC_RDATA_0,
+	MX53_PAD_FEC_TX_EN__FEC_TX_EN,
+	MX53_PAD_FEC_TXD1__FEC_TDATA_1,
+	MX53_PAD_FEC_TXD0__FEC_TDATA_0,
+	/* FEC_nRST */
+	MX53_PAD_PATA_DA_0__GPIO7_6,
+	/* FEC_nINT */
+	MX53_PAD_PATA_DATA4__GPIO2_4,
+	/* AUDMUX5 */
+	MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC,
+	MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD,
+	MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS,
+	MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD,
+	/* I2C2 */
+	MX53_PAD_KEY_COL3__I2C2_SCL,
+	MX53_PAD_KEY_ROW3__I2C2_SDA,
+	/* SD1 */
+	MX53_PAD_SD1_CMD__ESDHC1_CMD,
+	MX53_PAD_SD1_CLK__ESDHC1_CLK,
+	MX53_PAD_SD1_DATA0__ESDHC1_DAT0,
+	MX53_PAD_SD1_DATA1__ESDHC1_DAT1,
+	MX53_PAD_SD1_DATA2__ESDHC1_DAT2,
+	MX53_PAD_SD1_DATA3__ESDHC1_DAT3,
+	/* SD3 */
+	MX53_PAD_PATA_DATA8__ESDHC3_DAT0,
+	MX53_PAD_PATA_DATA9__ESDHC3_DAT1,
+	MX53_PAD_PATA_DATA10__ESDHC3_DAT2,
+	MX53_PAD_PATA_DATA11__ESDHC3_DAT3,
+	MX53_PAD_PATA_DATA0__ESDHC3_DAT4,
+	MX53_PAD_PATA_DATA1__ESDHC3_DAT5,
+	MX53_PAD_PATA_DATA2__ESDHC3_DAT6,
+	MX53_PAD_PATA_DATA3__ESDHC3_DAT7,
+	MX53_PAD_PATA_IORDY__ESDHC3_CLK,
+	MX53_PAD_PATA_RESET_B__ESDHC3_CMD,
+	/* SD3_CD */
+	MX53_PAD_EIM_DA11__GPIO3_11,
+	/* SD3_WP */
+	MX53_PAD_EIM_DA12__GPIO3_12,
+	/* VGA */
+	MX53_PAD_EIM_OE__IPU_DI1_PIN7,
+	MX53_PAD_EIM_RW__IPU_DI1_PIN8,
+	/* DISPLB */
+	MX53_PAD_EIM_D20__IPU_SER_DISP0_CS,
+	MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK,
+	MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN,
+	MX53_PAD_EIM_D23__IPU_DI0_D0_CS,
+	/* DISP0_POWER_EN */
+	MX53_PAD_EIM_D24__GPIO3_24,
+	/* DISP0 DET INT */
+	MX53_PAD_EIM_D31__GPIO3_31,
+	/* LVDS */
+	MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3,
+	MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK,
+	MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2,
+	MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1,
+	MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0,
+	MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3,
+	MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2,
+	MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK,
+	MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1,
+	MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
+	/* UART1 */
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
+	/* CSI0 */
+	MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12,
+	MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13,
+	MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14,
+	MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15,
+	MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16,
+	MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17,
+	MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18,
+	MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19,
+	MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC,
+	MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC,
+	MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK,
+	/* DISPLAY */
+	MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK,
+	MX53_PAD_DI0_PIN15__IPU_DI0_PIN15,
+	MX53_PAD_DI0_PIN2__IPU_DI0_PIN2,
+	MX53_PAD_DI0_PIN3__IPU_DI0_PIN3,
+	MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0,
+	MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1,
+	MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2,
+	MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3,
+	MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4,
+	MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5,
+	MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6,
+	MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7,
+	MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8,
+	MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9,
+	MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10,
+	MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11,
+	MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12,
+	MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13,
+	MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14,
+	MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15,
+	MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16,
+	MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17,
+	MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18,
+	MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19,
+	MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20,
+	MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21,
+	MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22,
+	MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23,
+	/* Audio CLK*/
+	MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK,
+	/* PWM */
+	MX53_PAD_GPIO_1__PWM2_PWMO,
+	/* SPDIF */
+	MX53_PAD_GPIO_7__SPDIF_PLOCK,
+	MX53_PAD_GPIO_17__SPDIF_OUT1,
+	/* GPIO */
+	MX53_PAD_PATA_DA_1__GPIO7_7,
+	MX53_PAD_PATA_DA_2__GPIO7_8,
+	MX53_PAD_PATA_DATA5__GPIO2_5,
+	MX53_PAD_PATA_DATA6__GPIO2_6,
+	MX53_PAD_PATA_DATA14__GPIO2_14,
+	MX53_PAD_PATA_DATA15__GPIO2_15,
+	MX53_PAD_PATA_INTRQ__GPIO7_2,
+	MX53_PAD_EIM_WAIT__GPIO5_0,
+	MX53_PAD_NANDF_WP_B__GPIO6_9,
+	MX53_PAD_NANDF_RB0__GPIO6_10,
+	MX53_PAD_NANDF_CS1__GPIO6_14,
+	MX53_PAD_NANDF_CS2__GPIO6_15,
+	MX53_PAD_NANDF_CS3__GPIO6_16,
+	MX53_PAD_GPIO_5__GPIO1_5,
+	MX53_PAD_GPIO_16__GPIO7_11,
+	MX53_PAD_GPIO_8__GPIO1_8,
+};
 
-	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
-	MX53_PAD_ATA_DMARQ__UART2_TXD,
-	MX53_PAD_ATA_DIOR__UART2_RTS,
-	MX53_PAD_ATA_INTRQ__UART2_CTS,
+#define GPIO_BUTTON(gpio_num, ev_code, act_low, descr, wake)	\
+{								\
+	.gpio		= gpio_num,				\
+	.type		= EV_KEY,				\
+	.code		= ev_code,				\
+	.active_low	= act_low,				\
+	.desc		= "btn " descr,				\
+	.wakeup		= wake,					\
+}
 
-	MX53_PAD_ATA_CS_0__UART3_TXD,
-	MX53_PAD_ATA_CS_1__UART3_RXD,
-	MX53_PAD_ATA_DA_1__UART3_CTS,
-	MX53_PAD_ATA_DA_2__UART3_RTS,
+static struct gpio_keys_button loco_buttons[] = {
+	GPIO_BUTTON(MX53_LOCO_POWER, KEY_POWER, 1, "power", 0),
+	GPIO_BUTTON(MX53_LOCO_UI1, KEY_VOLUMEUP, 1, "volume-up", 0),
+	GPIO_BUTTON(MX53_LOCO_UI2, KEY_VOLUMEDOWN, 1, "volume-down", 0),
 };
 
-static const struct imxuart_platform_data mx53_loco_uart_data __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
+static const struct gpio_keys_platform_data loco_button_data __initconst = {
+	.buttons        = loco_buttons,
+	.nbuttons       = ARRAY_SIZE(loco_buttons),
 };
 
-static inline void mx53_loco_init_uart(void)
-{
-	imx53_add_imx_uart(0, &mx53_loco_uart_data);
-	imx53_add_imx_uart(1, &mx53_loco_uart_data);
-	imx53_add_imx_uart(2, &mx53_loco_uart_data);
-}
-
 static inline void mx53_loco_fec_reset(void)
 {
 	int ret;
@@ -85,13 +223,23 @@
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
+static const struct imxi2c_platform_data mx53_loco_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
 static void __init mx53_loco_board_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx53_loco_pads,
 					ARRAY_SIZE(mx53_loco_pads));
-	mx53_loco_init_uart();
+	imx53_add_imx_uart(0, NULL);
 	mx53_loco_fec_reset();
 	imx53_add_fec(&mx53_loco_fec_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(0, &mx53_loco_i2c_data);
+	imx53_add_imx_i2c(1, &mx53_loco_i2c_data);
+	imx53_add_sdhci_esdhc_imx(0, NULL);
+	imx53_add_sdhci_esdhc_imx(2, NULL);
+	imx_add_gpio_keys(&loco_button_data);
 }
 
 static void __init mx53_loco_timer_init(void)
@@ -105,7 +253,8 @@
 
 MACHINE_START(MX53_LOCO, "Freescale MX53 LOCO Board")
 	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
-	.init_machine = mx53_loco_board_init,
 	.timer = &mx53_loco_timer,
+	.init_machine = mx53_loco_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx53_smd.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx53_smd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/board-mx53_smd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/board-mx53_smd.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,20 +39,19 @@
 #define SMD_FEC_PHY_RST		IMX_GPIO_NR(7, 6)
 
 static iomux_v3_cfg_t mx53_smd_pads[] = {
-	MX53_PAD_CSI0_D10__UART1_TXD,
-	MX53_PAD_CSI0_D11__UART1_RXD,
-	MX53_PAD_ATA_DIOW__UART1_TXD,
-	MX53_PAD_ATA_DMACK__UART1_RXD,
+	MX53_PAD_CSI0_DAT10__UART1_TXD_MUX,
+	MX53_PAD_CSI0_DAT11__UART1_RXD_MUX,
 
-	MX53_PAD_ATA_BUFFER_EN__UART2_RXD,
-	MX53_PAD_ATA_DMARQ__UART2_TXD,
-	MX53_PAD_ATA_DIOR__UART2_RTS,
-	MX53_PAD_ATA_INTRQ__UART2_CTS,
+	MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX,
+	MX53_PAD_PATA_DMARQ__UART2_TXD_MUX,
 
-	MX53_PAD_ATA_CS_0__UART3_TXD,
-	MX53_PAD_ATA_CS_1__UART3_RXD,
-	MX53_PAD_ATA_DA_1__UART3_CTS,
-	MX53_PAD_ATA_DA_2__UART3_RTS,
+	MX53_PAD_PATA_CS_0__UART3_TXD_MUX,
+	MX53_PAD_PATA_CS_1__UART3_RXD_MUX,
+	MX53_PAD_PATA_DA_1__UART3_CTS,
+	MX53_PAD_PATA_DA_2__UART3_RTS,
+	/* I2C1 */
+	MX53_PAD_CSI0_DAT8__I2C1_SDA,
+	MX53_PAD_CSI0_DAT9__I2C1_SCL,
 };
 
 static const struct imxuart_platform_data mx53_smd_uart_data __initconst = {
@@ -61,8 +60,8 @@
 
 static inline void mx53_smd_init_uart(void)
 {
-	imx53_add_imx_uart(0, &mx53_smd_uart_data);
-	imx53_add_imx_uart(1, &mx53_smd_uart_data);
+	imx53_add_imx_uart(0, NULL);
+	imx53_add_imx_uart(1, NULL);
 	imx53_add_imx_uart(2, &mx53_smd_uart_data);
 }
 
@@ -85,6 +84,10 @@
 	.phy = PHY_INTERFACE_MODE_RMII,
 };
 
+static const struct imxi2c_platform_data mx53_smd_i2c_data __initconst = {
+	.bitrate = 100000,
+};
+
 static void __init mx53_smd_board_init(void)
 {
 	mxc_iomux_v3_setup_multiple_pads(mx53_smd_pads,
@@ -92,6 +95,8 @@
 	mx53_smd_init_uart();
 	mx53_smd_fec_reset();
 	imx53_add_fec(&mx53_smd_fec_data);
+	imx53_add_imx2_wdt(0, NULL);
+	imx53_add_imx_i2c(0, &mx53_smd_i2c_data);
 }
 
 static void __init mx53_smd_timer_init(void)
@@ -105,7 +110,8 @@
 
 MACHINE_START(MX53_SMD, "Freescale MX53 SMD Board")
 	.map_io = mx53_map_io,
+	.init_early = imx53_init_early,
 	.init_irq = mx53_init_irq,
-	.init_machine = mx53_smd_board_init,
 	.timer = &mx53_smd_timer,
+	.init_machine = mx53_smd_board_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/clock-mx51-mx53.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,9 @@
 static struct clk emi_fast_clk;
 static struct clk ipu_clk;
 static struct clk mipi_hsc1_clk;
+static struct clk esdhc1_clk;
+static struct clk esdhc2_clk;
+static struct clk esdhc3_mx53_clk;
 
 #define MAX_DPLL_WAIT_TRIES	1000 /* 1000 * udelay(1) = 1ms */
 
@@ -862,13 +865,16 @@
 	.disable = _clk_ccgr_disable_inwait,
 };
 
-static struct clk gpt_32k_clk = {
-	.id = 0,
-	.parent = &ckil_clk,
+static struct clk gpc_dvfs_clk = {
+	.enable_reg = MXC_CCM_CCGR5,
+	.enable_shift = MXC_CCM_CCGRx_CG12_OFFSET,
+	.enable = _clk_ccgr_enable,
+	.disable = _clk_ccgr_disable,
 };
 
-static struct clk kpp_clk = {
+static struct clk gpt_32k_clk = {
 	.id = 0,
+	.parent = &ckil_clk,
 };
 
 static struct clk dummy_clk = {
@@ -1147,10 +1153,80 @@
 CLK_SET_PARENT(esdhc1, 1, ESDHC1_MSHC1)
 CLK_SET_RATE(esdhc1, 1, ESDHC1_MSHC1)
 
+/* mx51 specific */
 CLK_GET_RATE(esdhc2, 1, ESDHC2_MSHC2)
 CLK_SET_PARENT(esdhc2, 1, ESDHC2_MSHC2)
 CLK_SET_RATE(esdhc2, 1, ESDHC2_MSHC2)
 
+static int clk_esdhc3_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+	else if (parent == &esdhc2_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC3_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+static int clk_esdhc4_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else if (parent == &esdhc2_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+/* mx53 specific */
+static int clk_esdhc2_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+	else if (parent == &esdhc3_mx53_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
+CLK_GET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_PARENT(esdhc3_mx53, 1, ESDHC3_MX53)
+CLK_SET_RATE(esdhc3_mx53, 1, ESDHC3_MX53)
+
+static int clk_esdhc4_mx53_set_parent(struct clk *clk, struct clk *parent)
+{
+	u32 reg;
+
+	reg = __raw_readl(MXC_CCM_CSCMR1);
+	if (parent == &esdhc1_clk)
+		reg &= ~MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else if (parent == &esdhc3_mx53_clk)
+		reg |= MXC_CCM_CSCMR1_ESDHC4_CLK_SEL;
+	else
+		return -EINVAL;
+	__raw_writel(reg, MXC_CCM_CSCMR1);
+
+	return 0;
+}
+
 #define DEFINE_CLOCK_FULL(name, i, er, es, gr, sr, e, d, p, s)		\
 	static struct clk name = {					\
 		.id		= i,					\
@@ -1255,9 +1331,62 @@
 	clk_esdhc1, &pll2_sw_clk, &esdhc1_ipg_clk);
 DEFINE_CLOCK_FULL(esdhc2_ipg_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG2_OFFSET,
 	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc3_ipg_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG4_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+DEFINE_CLOCK_FULL(esdhc4_ipg_clk, 3, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG6_OFFSET,
+	NULL,  NULL, _clk_max_enable, _clk_max_disable, &ipg_clk, NULL);
+
+/* mx51 specific */
 DEFINE_CLOCK_MAX(esdhc2_clk, 1, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG3_OFFSET,
 	clk_esdhc2, &pll2_sw_clk, &esdhc2_ipg_clk);
 
+static struct clk esdhc3_clk = {
+	.id = 2,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc3_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG5_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc3_ipg_clk,
+};
+static struct clk esdhc4_clk = {
+	.id = 3,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc4_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc4_ipg_clk,
+};
+
+/* mx53 specific */
+static struct clk esdhc2_mx53_clk = {
+	.id = 2,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc2_mx53_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG3_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc3_ipg_clk,
+};
+
+DEFINE_CLOCK_MAX(esdhc3_mx53_clk, 2, MXC_CCM_CCGR3, MXC_CCM_CCGRx_CG5_OFFSET,
+	clk_esdhc3_mx53, &pll2_sw_clk, &esdhc2_ipg_clk);
+
+static struct clk esdhc4_mx53_clk = {
+	.id = 3,
+	.parent = &esdhc1_clk,
+	.set_parent = clk_esdhc4_mx53_set_parent,
+	.enable_reg = MXC_CCM_CCGR3,
+	.enable_shift = MXC_CCM_CCGRx_CG7_OFFSET,
+	.enable  = _clk_max_enable,
+	.disable = _clk_max_disable,
+	.secondary = &esdhc4_ipg_clk,
+};
+
 DEFINE_CLOCK(mipi_esc_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG5_OFFSET, NULL, NULL, NULL, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc2_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG4_OFFSET, NULL, NULL, &mipi_esc_clk, &pll2_sw_clk);
 DEFINE_CLOCK(mipi_hsc1_clk, 0, MXC_CCM_CCGR4, MXC_CCM_CCGRx_CG3_OFFSET, NULL, NULL, &mipi_hsc2_clk, &pll2_sw_clk);
@@ -1302,7 +1431,7 @@
 	_REGISTER_CLOCK("mxc-ehci.2", "usb_ahb", usb_ahb_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb", usboh3_clk)
 	_REGISTER_CLOCK("fsl-usb2-udc", "usb_ahb", ahb_clk)
-	_REGISTER_CLOCK("imx-keypad", NULL, kpp_clk)
+	_REGISTER_CLOCK("imx-keypad", NULL, dummy_clk)
 	_REGISTER_CLOCK("mxc_nand", NULL, nfc_clk)
 	_REGISTER_CLOCK("imx-ssi.0", NULL, ssi1_clk)
 	_REGISTER_CLOCK("imx-ssi.1", NULL, ssi2_clk)
@@ -1316,6 +1445,8 @@
 	_REGISTER_CLOCK("imx51-cspi.0", NULL, cspi_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_clk)
 	_REGISTER_CLOCK(NULL, "cpu_clk", cpu_clk)
 	_REGISTER_CLOCK(NULL, "iim_clk", iim_clk)
 	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
@@ -1324,6 +1455,7 @@
 	_REGISTER_CLOCK("imx-ipuv3", NULL, ipu_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di0", ipu_di0_clk)
 	_REGISTER_CLOCK("imx-ipuv3", "di1", ipu_di1_clk)
+	_REGISTER_CLOCK(NULL, "gpc_dvfs", gpc_dvfs_clk)
 };
 
 static struct clk_lookup mx53_lookups[] = {
@@ -1336,10 +1468,14 @@
 	_REGISTER_CLOCK("imx-i2c.0", NULL, i2c1_clk)
 	_REGISTER_CLOCK("imx-i2c.1", NULL, i2c2_clk)
 	_REGISTER_CLOCK("sdhci-esdhc-imx.0", NULL, esdhc1_clk)
-	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.1", NULL, esdhc2_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.2", NULL, esdhc3_mx53_clk)
+	_REGISTER_CLOCK("sdhci-esdhc-imx.3", NULL, esdhc4_mx53_clk)
 	_REGISTER_CLOCK("imx53-ecspi.0", NULL, ecspi1_clk)
 	_REGISTER_CLOCK("imx53-ecspi.1", NULL, ecspi2_clk)
 	_REGISTER_CLOCK("imx53-cspi.0", NULL, cspi_clk)
+	_REGISTER_CLOCK("imx2-wdt.0", NULL, dummy_clk)
+	_REGISTER_CLOCK("imx2-wdt.1", NULL, dummy_clk)
 };
 
 static void clk_tree_init(void)
@@ -1383,6 +1519,7 @@
 	clk_enable(&iim_clk);
 	mx51_revision();
 	clk_disable(&iim_clk);
+	mx51_display_revision();
 
 	/* move usb_phy_clk to 24MHz */
 	clk_set_parent(&usb_phy1_clk, &osc_clk);
@@ -1427,6 +1564,14 @@
 	mx53_revision();
 	clk_disable(&iim_clk);
 
+	/* Set SDHC parents to be PLL2 */
+	clk_set_parent(&esdhc1_clk, &pll2_sw_clk);
+	clk_set_parent(&esdhc3_mx53_clk, &pll2_sw_clk);
+
+	/* set SDHC root clock as 200MHZ*/
+	clk_set_rate(&esdhc1_clk, 200000000);
+	clk_set_rate(&esdhc3_mx53_clk, 200000000);
+
 	/* System timer */
 	mxc_timer_init(&gpt_clk, MX53_IO_ADDRESS(MX53_GPT1_BASE_ADDR),
 		MX53_INT_GPT);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/cpu.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/cpu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 static int cpu_silicon_rev = -1;
 
 #define IIM_SREV 0x24
+#define MX50_HW_ADADIG_DIGPROG	0xB0
 
 static int get_mx51_srev(void)
 {
@@ -51,6 +52,26 @@
 }
 EXPORT_SYMBOL(mx51_revision);
 
+void mx51_display_revision(void)
+{
+	int rev;
+	char *srev;
+	rev = mx51_revision();
+
+	switch (rev) {
+	case IMX_CHIP_REVISION_2_0:
+		srev = IMX_CHIP_REVISION_2_0_STRING;
+		break;
+	case IMX_CHIP_REVISION_3_0:
+		srev = IMX_CHIP_REVISION_3_0_STRING;
+		break;
+	default:
+		srev = IMX_CHIP_REVISION_UNKNOWN_STRING;
+	}
+	printk(KERN_INFO "CPU identified as i.MX51, silicon rev %s\n", srev);
+}
+EXPORT_SYMBOL(mx51_display_revision);
+
 #ifdef CONFIG_NEON
 
 /*
@@ -78,11 +99,16 @@
 	void __iomem *iim_base = MX51_IO_ADDRESS(MX53_IIM_BASE_ADDR);
 	u32 rev = readl(iim_base + IIM_SREV) & 0xff;
 
-	if (rev == 0x0)
+	switch (rev) {
+	case 0x0:
 		return IMX_CHIP_REVISION_1_0;
-	else if (rev == 0x10)
+	case 0x2:
 		return IMX_CHIP_REVISION_2_0;
-	return 0;
+	case 0x3:
+		return IMX_CHIP_REVISION_2_1;
+	default:
+		return IMX_CHIP_REVISION_UNKNOWN;
+	}
 }
 
 /*
@@ -102,6 +128,44 @@
 }
 EXPORT_SYMBOL(mx53_revision);
 
+static int get_mx50_srev(void)
+{
+	void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
+	u32 rev;
+
+	if (!anatop) {
+		cpu_silicon_rev = -EINVAL;
+		return 0;
+	}
+
+	rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
+	rev &= 0xff;
+
+	iounmap(anatop);
+	if (rev == 0x0)
+		return IMX_CHIP_REVISION_1_0;
+	else if (rev == 0x1)
+		return IMX_CHIP_REVISION_1_1;
+	return 0;
+}
+
+/*
+ * Returns:
+ *	the silicon revision of the cpu
+ *	-EINVAL - not a mx50
+ */
+int mx50_revision(void)
+{
+	if (!cpu_is_mx50())
+		return -EINVAL;
+
+	if (cpu_silicon_rev == -1)
+		cpu_silicon_rev = get_mx50_srev();
+
+	return cpu_silicon_rev;
+}
+EXPORT_SYMBOL(mx50_revision);
+
 static int __init post_cpu_init(void)
 {
 	unsigned int reg;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/crm_regs.h linux-libre-2.6.39-gnu/arch/arm/mach-mx5/crm_regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/crm_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/crm_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -217,9 +217,12 @@
 #define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_OFFSET	(20)
 #define MXC_CCM_CSCMR1_ESDHC1_MSHC1_CLK_SEL_MASK	(0x3 << 20)
 #define MXC_CCM_CSCMR1_ESDHC3_CLK_SEL			(0x1 << 19)
+#define MXC_CCM_CSCMR1_ESDHC2_MSHC2_MX53_CLK_SEL	(0x1 << 19)
 #define MXC_CCM_CSCMR1_ESDHC4_CLK_SEL			(0x1 << 18)
 #define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_OFFSET	(16)
 #define MXC_CCM_CSCMR1_ESDHC2_MSHC2_CLK_SEL_MASK	(0x3 << 16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_OFFSET	(16)
+#define MXC_CCM_CSCMR1_ESDHC3_MX53_CLK_SEL_MASK		(0x3 << 16)
 #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_OFFSET		(14)
 #define MXC_CCM_CSCMR1_SSI1_CLK_SEL_MASK		(0x3 << 14)
 #define MXC_CCM_CSCMR1_SSI2_CLK_SEL_OFFSET		(12)
@@ -271,6 +274,10 @@
 #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PRED_MASK	(0x7 << 22)
 #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_OFFSET	(19)
 #define MXC_CCM_CSCDR1_ESDHC2_MSHC2_CLK_PODF_MASK	(0x7 << 19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_OFFSET	(22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PRED_MASK	(0x7 << 22)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_OFFSET	(19)
+#define MXC_CCM_CSCDR1_ESDHC3_MX53_CLK_PODF_MASK	(0x7 << 19)
 #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_OFFSET	(16)
 #define MXC_CCM_CSCDR1_ESDHC1_MSHC1_CLK_PRED_MASK	(0x7 << 16)
 #define MXC_CCM_CSCDR1_PGC_CLK_PODF_OFFSET		(14)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/devices-imx50.h linux-libre-2.6.39-gnu/arch/arm/mach-mx5/devices-imx50.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/devices-imx50.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/devices-imx50.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2010 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <mach/mx50.h>
+#include <mach/devices-common.h>
+
+extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst;
+#define imx50_add_imx_uart(id, pdata)	\
+	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
+
+extern const struct imx_fec_data imx50_fec_data __initconst;
+#define imx50_add_fec(pdata)	\
+	imx_add_fec(&imx50_fec_data, pdata)
+
+extern const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst;
+#define imx50_add_imx_i2c(id, pdata)	\
+	imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/devices-imx53.h linux-libre-2.6.39-gnu/arch/arm/mach-mx5/devices-imx53.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/devices-imx53.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/devices-imx53.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,3 +29,7 @@
 extern const struct imx_spi_imx_data imx53_ecspi_data[] __initconst;
 #define imx53_add_ecspi(id, pdata)	\
 	imx_add_spi_imx(&imx53_ecspi_data[id], pdata)
+
+extern const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst;
+#define imx53_add_imx2_wdt(id, pdata)	\
+	imx_add_imx2_wdt(&imx53_imx2_wdt_data[id])
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/devices-mx50.h linux-libre-2.6.39-gnu/arch/arm/mach-mx5/devices-mx50.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/devices-mx50.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/devices-mx50.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <mach/mx50.h>
-#include <mach/devices-common.h>
-
-extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst;
-#define imx50_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/efika.h linux-libre-2.6.39-gnu/arch/arm/mach-mx5/efika.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/efika.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/efika.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+#ifndef _EFIKA_H
+#define _EFIKA_H
+
+#define EFIKA_WLAN_EN		IMX_GPIO_NR(2, 16)
+#define EFIKA_WLAN_RESET	IMX_GPIO_NR(2, 10)
+#define EFIKA_USB_PHY_RESET	IMX_GPIO_NR(2, 9)
+
+void __init efika_board_common_init(void);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/ehci.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/ehci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/ehci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/ehci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
+ * Copyright (C) 2010 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/mxc_ehci.h>
+
+#define MXC_OTG_OFFSET			0
+#define MXC_H1_OFFSET			0x200
+#define MXC_H2_OFFSET			0x400
+
+/* USB_CTRL */
+#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
+#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
+#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
+#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
+#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)		/* HOST1 power mask */
+
+/* USB_PHY_CTRL_FUNC */
+#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
+#define MXC_H1_OC_DIS_BIT		(1 << 5)	/* UH1 Disable Overcurrent Event */
+
+/* USBH2CTRL */
+#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
+#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
+#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
+
+#define MXC_USBCMD_OFFSET		0x140
+
+/* USBCMD */
+#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
+
+int mx51_initialize_usb_hw(int port, unsigned int flags)
+{
+	unsigned int v;
+	void __iomem *usb_base;
+	void __iomem *usbotg_base;
+	void __iomem *usbother_base;
+	int ret = 0;
+
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base) {
+		printk(KERN_ERR "%s(): ioremap failed\n", __func__);
+		return -ENOMEM;
+	}
+
+	switch (port) {
+	case 0:	/* OTG port */
+		usbotg_base = usb_base + MXC_OTG_OFFSET;
+		break;
+	case 1:	/* Host 1 port */
+		usbotg_base = usb_base + MXC_H1_OFFSET;
+		break;
+	case 2: /* Host 2 port */
+		usbotg_base = usb_base + MXC_H2_OFFSET;
+		break;
+	default:
+		printk(KERN_ERR"%s no such port %d\n", __func__, port);
+		ret = -ENOENT;
+		goto error;
+	}
+	usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
+
+	switch (port) {
+	case 0:	/*OTG port */
+		if (flags & MXC_EHCI_INTERNAL_PHY) {
+			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
+				/* OC/USBPWR is not used */
+				v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
+			} else {
+				/* OC/USBPWR is used */
+				v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
+			}
+			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+			if (flags & MXC_EHCI_WAKEUP_ENABLED)
+				v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
+			else
+				v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
+			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+				v |= MXC_OTG_UCTRL_OPM_BIT;
+			else
+				v &= ~MXC_OTG_UCTRL_OPM_BIT;
+			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+		}
+		break;
+	case 1:	/* Host 1 */
+		/*Host ULPI */
+		v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
+		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+			/* HOST1 wakeup/ULPI intr enable */
+			v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+		} else {
+			/* HOST1 wakeup/ULPI intr disable */
+			v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
+		}
+
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+		else
+			v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
+		__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
+
+		v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
+		else
+			v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
+		__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
+
+		v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
+		if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
+			/* Interrupt Threshold Control:Immediate (no threshold) */
+			v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
+		__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
+		break;
+	case 2: /* Host 2 ULPI */
+		v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
+		if (flags & MXC_EHCI_WAKEUP_ENABLED) {
+			/* HOST1 wakeup/ULPI intr enable */
+			v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+		} else {
+			/* HOST1 wakeup/ULPI intr disable */
+			v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
+		}
+
+		if (flags & MXC_EHCI_POWER_PINS_ENABLED)
+			v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+		else
+			v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
+		__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
+		break;
+	}
+
+error:
+	iounmap(usb_base);
+	return ret;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/eukrea_mbimx51-baseboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -212,7 +212,7 @@
 
 	gpio_request(MBIMX51_TSC2007_GPIO, "tsc2007_irq");
 	gpio_direction_input(MBIMX51_TSC2007_GPIO);
-	set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
+	irq_set_irq_type(MBIMX51_TSC2007_IRQ, IRQF_TRIGGER_FALLING);
 	i2c_register_board_info(1, mbimx51_i2c_devices,
 				ARRAY_SIZE(mbimx51_i2c_devices));
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/eukrea_mbimxsd-baseboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,6 +67,10 @@
 	MX51_PAD_SD1_DATA1__SD1_DATA1,
 	MX51_PAD_SD1_DATA2__SD1_DATA2,
 	MX51_PAD_SD1_DATA3__SD1_DATA3,
+	/* SD1 CD */
+	_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(PAD_CTL_PUS_22K_UP |
+			PAD_CTL_PKE | PAD_CTL_SRE_FAST |
+			PAD_CTL_DSE_HIGH | PAD_CTL_PUE | PAD_CTL_HYS),
 };
 
 #define GPIO_LED1	IMX_GPIO_NR(3, 30)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-mx5/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,6 @@
 if ARCH_MX5
-# ARCH_MX51 and ARCH_MX50 are left for compatibility
+# ARCH_MX50/51/53 are left to mark places where prevent multi-soc in single
+# image. So for most time, SOC_IMX50/51/53 should be used.
 
 config ARCH_MX50
 	bool
@@ -50,6 +51,7 @@
 config MACH_MX51_3DS
 	bool "Support MX51PDK (3DS)"
 	select SOC_IMX51
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_KEYPAD
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
@@ -112,19 +114,32 @@
 
 endchoice
 
-config MACH_MX51_EFIKAMX
-	bool "Support MX51 Genesi Efika MX nettop"
+config MX51_EFIKA_COMMON
+	bool
 	select SOC_IMX51
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select MXC_ULPI if USB_ULPI
+
+config MACH_MX51_EFIKAMX
+	bool "Support MX51 Genesi Efika MX nettop"
+	select MX51_EFIKA_COMMON
 	help
 	  Include support for Genesi Efika MX nettop. This includes specific
 	  configurations for the board and its peripherals.
 
+config MACH_MX51_EFIKASB
+	bool "Support MX51 Genesi Efika Smartbook"
+	select MX51_EFIKA_COMMON
+	help
+	  Include support for Genesi Efika Smartbook. This includes specific
+	  configurations for the board and its peripherals.
+
 config MACH_MX53_EVK
 	bool "Support MX53 EVK platforms"
 	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
@@ -136,6 +151,8 @@
 config MACH_MX53_SMD
 	bool "Support MX53 SMD platforms"
 	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
 	help
 	  Include support for MX53 SMD platform. This includes specific
@@ -144,7 +161,11 @@
 config MACH_MX53_LOCO
 	bool "Support MX53 LOCO platforms"
 	select SOC_IMX53
+	select IMX_HAVE_PLATFORM_IMX2_WDT
+	select IMX_HAVE_PLATFORM_IMX_I2C
 	select IMX_HAVE_PLATFORM_IMX_UART
+	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
+	select IMX_HAVE_PLATFORM_GPIO_KEYS
 	help
 	  Include support for MX53 LOCO platform. This includes specific
 	  configurations for the board and its peripherals.
@@ -157,6 +178,7 @@
 	select IMX_HAVE_PLATFORM_IMX_UART
 	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
 	select IMX_HAVE_PLATFORM_SPI_IMX
+	select IMX_HAVE_PLATFORM_FEC
 	help
 	  Include support for MX50 reference design platform (RDP) board. This
 	  includes specific configurations for the board and its peripherals.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-mx5/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
 #
 
 # Object file lists.
-obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o
+obj-y   := cpu.o mm.o clock-mx51-mx53.o devices.o ehci.o system.o
 obj-$(CONFIG_SOC_IMX50) += mm-mx50.o
 
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpu_op-mx51.o
@@ -16,5 +16,7 @@
 obj-$(CONFIG_MACH_EUKREA_MBIMX51_BASEBOARD) += eukrea_mbimx51-baseboard.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += board-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd-baseboard.o
+obj-$(CONFIG_MX51_EFIKA_COMMON) += mx51_efika.o
 obj-$(CONFIG_MACH_MX51_EFIKAMX) += board-mx51_efikamx.o
+obj-$(CONFIG_MACH_MX51_EFIKASB) += board-mx51_efikasb.o
 obj-$(CONFIG_MACH_MX50_RDP) += board-mx50_rdp.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/mm.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/mm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/mm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,18 +47,26 @@
  */
 void __init mx51_map_io(void)
 {
+	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
+}
+
+void __init imx51_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX51);
 	mxc_iomux_v3_init(MX51_IO_ADDRESS(MX51_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX51_IO_ADDRESS(MX51_WDOG1_BASE_ADDR));
-	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
 }
 
 void __init mx53_map_io(void)
 {
+	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+}
+
+void __init imx53_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX53);
 	mxc_iomux_v3_init(MX53_IO_ADDRESS(MX53_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG_BASE_ADDR));
-	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
+	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
 int imx51_register_gpios(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/mm-mx50.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/mm-mx50.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/mm-mx50.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/mm-mx50.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,8 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/iomux-v3.h>
+#include <mach/gpio.h>
+#include <mach/irqs.h>
 
 /*
  * Define the MX50 memory map.
@@ -44,16 +46,27 @@
  */
 void __init mx50_map_io(void)
 {
+	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
+}
+
+void __init imx50_init_early(void)
+{
 	mxc_set_cpu_type(MXC_CPU_MX50);
 	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
 	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
 }
 
-int imx50_register_gpios(void);
+static struct mxc_gpio_port imx50_gpio_ports[] = {
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
+};
 
 void __init mx50_init_irq(void)
 {
 	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-	imx50_register_gpios();
+	mxc_gpio_init(imx50_gpio_ports,	ARRAY_SIZE(imx50_gpio_ports));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/mx51_efika.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/mx51_efika.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/mx51_efika.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/mx51_efika.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,637 @@
+/*
+ * based on code from the following
+ * Copyright 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright 2009-2010 Pegatron Corporation. All Rights Reserved.
+ * Copyright 2009-2010 Genesi USA, 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/platform_device.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/input.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/fsl_devices.h>
+#include <linux/spi/flash.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/mc13892.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/common.h>
+#include <mach/hardware.h>
+#include <mach/iomux-mx51.h>
+#include <mach/i2c.h>
+#include <mach/mxc_ehci.h>
+
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <mach/ulpi.h>
+
+#include <asm/irq.h>
+#include <asm/setup.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include "devices-imx51.h"
+#include "devices.h"
+#include "efika.h"
+#include "cpu_op-mx51.h"
+
+#define MX51_USB_CTRL_1_OFFSET          0x10
+#define MX51_USB_CTRL_UH1_EXT_CLK_EN    (1 << 25)
+#define	MX51_USB_PLL_DIV_19_2_MHZ	0x01
+
+#define EFIKAMX_USB_HUB_RESET	IMX_GPIO_NR(1, 5)
+#define EFIKAMX_USBH1_STP	IMX_GPIO_NR(1, 27)
+
+#define EFIKAMX_SPI_CS0		IMX_GPIO_NR(4, 24)
+#define EFIKAMX_SPI_CS1		IMX_GPIO_NR(4, 25)
+
+#define EFIKAMX_PMIC		IMX_GPIO_NR(1, 6)
+
+static iomux_v3_cfg_t mx51efika_pads[] = {
+	/* UART1 */
+	MX51_PAD_UART1_RXD__UART1_RXD,
+	MX51_PAD_UART1_TXD__UART1_TXD,
+	MX51_PAD_UART1_RTS__UART1_RTS,
+	MX51_PAD_UART1_CTS__UART1_CTS,
+
+	/* SD 1 */
+	MX51_PAD_SD1_CMD__SD1_CMD,
+	MX51_PAD_SD1_CLK__SD1_CLK,
+	MX51_PAD_SD1_DATA0__SD1_DATA0,
+	MX51_PAD_SD1_DATA1__SD1_DATA1,
+	MX51_PAD_SD1_DATA2__SD1_DATA2,
+	MX51_PAD_SD1_DATA3__SD1_DATA3,
+
+	/* SD 2 */
+	MX51_PAD_SD2_CMD__SD2_CMD,
+	MX51_PAD_SD2_CLK__SD2_CLK,
+	MX51_PAD_SD2_DATA0__SD2_DATA0,
+	MX51_PAD_SD2_DATA1__SD2_DATA1,
+	MX51_PAD_SD2_DATA2__SD2_DATA2,
+	MX51_PAD_SD2_DATA3__SD2_DATA3,
+
+	/* SD/MMC WP/CD */
+	MX51_PAD_GPIO1_0__SD1_CD,
+	MX51_PAD_GPIO1_1__SD1_WP,
+	MX51_PAD_GPIO1_7__SD2_WP,
+	MX51_PAD_GPIO1_8__SD2_CD,
+
+	/* spi */
+	MX51_PAD_CSPI1_MOSI__ECSPI1_MOSI,
+	MX51_PAD_CSPI1_MISO__ECSPI1_MISO,
+	MX51_PAD_CSPI1_SS0__GPIO4_24,
+	MX51_PAD_CSPI1_SS1__GPIO4_25,
+	MX51_PAD_CSPI1_RDY__ECSPI1_RDY,
+	MX51_PAD_CSPI1_SCLK__ECSPI1_SCLK,
+	MX51_PAD_GPIO1_6__GPIO1_6,
+
+	/* USB HOST1 */
+	MX51_PAD_USBH1_CLK__USBH1_CLK,
+	MX51_PAD_USBH1_DIR__USBH1_DIR,
+	MX51_PAD_USBH1_NXT__USBH1_NXT,
+	MX51_PAD_USBH1_DATA0__USBH1_DATA0,
+	MX51_PAD_USBH1_DATA1__USBH1_DATA1,
+	MX51_PAD_USBH1_DATA2__USBH1_DATA2,
+	MX51_PAD_USBH1_DATA3__USBH1_DATA3,
+	MX51_PAD_USBH1_DATA4__USBH1_DATA4,
+	MX51_PAD_USBH1_DATA5__USBH1_DATA5,
+	MX51_PAD_USBH1_DATA6__USBH1_DATA6,
+	MX51_PAD_USBH1_DATA7__USBH1_DATA7,
+
+	/* USB HUB RESET */
+	MX51_PAD_GPIO1_5__GPIO1_5,
+
+	/* WLAN */
+	MX51_PAD_EIM_A22__GPIO2_16,
+	MX51_PAD_EIM_A16__GPIO2_10,
+
+	/* USB PHY RESET */
+	MX51_PAD_EIM_D27__GPIO2_9,
+};
+
+/* Serial ports */
+static const struct imxuart_platform_data uart_pdata = {
+	.flags = IMXUART_HAVE_RTSCTS,
+};
+
+/* This function is board specific as the bit mask for the plldiv will also
+ * be different for other Freescale SoCs, thus a common bitmask is not
+ * possible and cannot get place in /plat-mxc/ehci.c.
+ */
+static int initialize_otg_port(struct platform_device *pdev)
+{
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *usbother_base;
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	if (!usb_base)
+		return -ENOMEM;
+	usbother_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+	/* Set the PHY clock to 19.2MHz */
+	v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	v &= ~MX5_USB_UTMI_PHYCTRL1_PLLDIV_MASK;
+	v |= MX51_USB_PLL_DIV_19_2_MHZ;
+	__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC2_OFFSET);
+	iounmap(usb_base);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(pdev->id, MXC_EHCI_INTERNAL_PHY);
+}
+
+static struct mxc_usbh_platform_data dr_utmi_config = {
+	.init   = initialize_otg_port,
+	.portsc = MXC_EHCI_UTMI_16BIT,
+};
+
+static int initialize_usbh1_port(struct platform_device *pdev)
+{
+	iomux_v3_cfg_t usbh1stp = MX51_PAD_USBH1_STP__USBH1_STP;
+	iomux_v3_cfg_t usbh1gpio = MX51_PAD_USBH1_STP__GPIO1_27;
+	u32 v;
+	void __iomem *usb_base;
+	void __iomem *socregs_base;
+
+	mxc_iomux_v3_setup_pad(usbh1gpio);
+	gpio_request(EFIKAMX_USBH1_STP, "usbh1_stp");
+	gpio_direction_output(EFIKAMX_USBH1_STP, 0);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USBH1_STP, 1);
+	msleep(1);
+
+	usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
+	socregs_base = (void __iomem *)(usb_base + MX5_USBOTHER_REGS_OFFSET);
+
+	/* The clock for the USBH1 ULPI port will come externally */
+	/* from the PHY. */
+	v = __raw_readl(socregs_base + MX51_USB_CTRL_1_OFFSET);
+	__raw_writel(v | MX51_USB_CTRL_UH1_EXT_CLK_EN,
+			socregs_base + MX51_USB_CTRL_1_OFFSET);
+
+	iounmap(usb_base);
+
+	gpio_free(EFIKAMX_USBH1_STP);
+	mxc_iomux_v3_setup_pad(usbh1stp);
+
+	mdelay(10);
+
+	return mx51_initialize_usb_hw(0, MXC_EHCI_ITC_NO_THRESHOLD);
+}
+
+static struct mxc_usbh_platform_data usbh1_config = {
+	.init   = initialize_usbh1_port,
+	.portsc = MXC_EHCI_MODE_ULPI,
+};
+
+static void mx51_efika_hubreset(void)
+{
+	gpio_request(EFIKAMX_USB_HUB_RESET, "usb_hub_rst");
+	gpio_direction_output(EFIKAMX_USB_HUB_RESET, 1);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USB_HUB_RESET, 0);
+	msleep(1);
+	gpio_set_value(EFIKAMX_USB_HUB_RESET, 1);
+}
+
+static void __init mx51_efika_usb(void)
+{
+	mx51_efika_hubreset();
+
+	/* pulling it low, means no USB at all... */
+	gpio_request(EFIKA_USB_PHY_RESET, "usb_phy_reset");
+	gpio_direction_output(EFIKA_USB_PHY_RESET, 0);
+	msleep(1);
+	gpio_set_value(EFIKA_USB_PHY_RESET, 1);
+
+	usbh1_config.otg = imx_otg_ulpi_create(ULPI_OTG_DRVVBUS |
+			ULPI_OTG_DRVVBUS_EXT | ULPI_OTG_EXTVBUSIND);
+
+	mxc_register_device(&mxc_usbdr_host_device, &dr_utmi_config);
+	if (usbh1_config.otg)
+		mxc_register_device(&mxc_usbh1_device, &usbh1_config);
+}
+
+static struct mtd_partition mx51_efika_spi_nor_partitions[] = {
+	{
+	 .name = "u-boot",
+	 .offset = 0,
+	 .size = SZ_256K,
+	},
+	{
+	  .name = "config",
+	  .offset = MTDPART_OFS_APPEND,
+	  .size = SZ_64K,
+	},
+};
+
+static struct flash_platform_data mx51_efika_spi_flash_data = {
+	.name		= "spi_flash",
+	.parts		= mx51_efika_spi_nor_partitions,
+	.nr_parts	= ARRAY_SIZE(mx51_efika_spi_nor_partitions),
+	.type		= "sst25vf032b",
+};
+
+static struct regulator_consumer_supply sw1_consumers[] = {
+	{
+		.supply = "cpu_vcc",
+	}
+};
+
+static struct regulator_consumer_supply vdig_consumers[] = {
+	/* sgtl5000 */
+	REGULATOR_SUPPLY("VDDA", "1-000a"),
+	REGULATOR_SUPPLY("VDDD", "1-000a"),
+};
+
+static struct regulator_consumer_supply vvideo_consumers[] = {
+	/* sgtl5000 */
+	REGULATOR_SUPPLY("VDDIO", "1-000a"),
+};
+
+static struct regulator_consumer_supply vsd_consumers[] = {
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.0"),
+	REGULATOR_SUPPLY("vmmc", "sdhci-esdhc-imx.1"),
+};
+
+static struct regulator_consumer_supply pwgt1_consumer[] = {
+	{
+		.supply = "pwgt1",
+	}
+};
+
+static struct regulator_consumer_supply pwgt2_consumer[] = {
+	{
+		.supply = "pwgt2",
+	}
+};
+
+static struct regulator_consumer_supply coincell_consumer[] = {
+	{
+		.supply = "coincell",
+	}
+};
+
+static struct regulator_init_data sw1_init = {
+	.constraints = {
+		.name = "SW1",
+		.min_uV = 600000,
+		.max_uV = 1375000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.valid_modes_mask = 0,
+		.always_on = 1,
+		.boot_on = 1,
+		.state_mem = {
+			.uV = 850000,
+			.mode = REGULATOR_MODE_NORMAL,
+			.enabled = 1,
+		},
+	},
+	.num_consumer_supplies = ARRAY_SIZE(sw1_consumers),
+	.consumer_supplies = sw1_consumers,
+};
+
+static struct regulator_init_data sw2_init = {
+	.constraints = {
+		.name = "SW2",
+		.min_uV = 900000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+		.state_mem = {
+			.uV = 950000,
+			.mode = REGULATOR_MODE_NORMAL,
+			.enabled = 1,
+		},
+	}
+};
+
+static struct regulator_init_data sw3_init = {
+	.constraints = {
+		.name = "SW3",
+		.min_uV = 1100000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data sw4_init = {
+	.constraints = {
+		.name = "SW4",
+		.min_uV = 1100000,
+		.max_uV = 1850000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.always_on = 1,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data viohi_init = {
+	.constraints = {
+		.name = "VIOHI",
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vusb_init = {
+	.constraints = {
+		.name = "VUSB",
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data swbst_init = {
+	.constraints = {
+		.name = "SWBST",
+	}
+};
+
+static struct regulator_init_data vdig_init = {
+	.constraints = {
+		.name = "VDIG",
+		.min_uV = 1050000,
+		.max_uV = 1800000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vdig_consumers),
+	.consumer_supplies = vdig_consumers,
+};
+
+static struct regulator_init_data vpll_init = {
+	.constraints = {
+		.name = "VPLL",
+		.min_uV = 1050000,
+		.max_uV = 1800000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vusb2_init = {
+	.constraints = {
+		.name = "VUSB2",
+		.min_uV = 2400000,
+		.max_uV = 2775000,
+		.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vvideo_init = {
+	.constraints = {
+		.name = "VVIDEO",
+		.min_uV = 2775000,
+		.max_uV = 2775000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.apply_uV = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vvideo_consumers),
+	.consumer_supplies = vvideo_consumers,
+};
+
+static struct regulator_init_data vaudio_init = {
+	.constraints = {
+		.name = "VAUDIO",
+		.min_uV = 2300000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data vsd_init = {
+	.constraints = {
+		.name = "VSD",
+		.min_uV = 1800000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE,
+		.boot_on = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(vsd_consumers),
+	.consumer_supplies = vsd_consumers,
+};
+
+static struct regulator_init_data vcam_init = {
+	.constraints = {
+		.name = "VCAM",
+		.min_uV = 2500000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE |
+			REGULATOR_CHANGE_MODE | REGULATOR_CHANGE_STATUS,
+		.valid_modes_mask = REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL,
+		.boot_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen1_init = {
+	.constraints = {
+		.name = "VGEN1",
+		.min_uV = 1200000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen2_init = {
+	.constraints = {
+		.name = "VGEN2",
+		.min_uV = 1200000,
+		.max_uV = 3150000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data vgen3_init = {
+	.constraints = {
+		.name = "VGEN3",
+		.min_uV = 1800000,
+		.max_uV = 2900000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+		.boot_on = 1,
+		.always_on = 1,
+	}
+};
+
+static struct regulator_init_data gpo1_init = {
+	.constraints = {
+		.name = "GPO1",
+	}
+};
+
+static struct regulator_init_data gpo2_init = {
+	.constraints = {
+		.name = "GPO2",
+	}
+};
+
+static struct regulator_init_data gpo3_init = {
+	.constraints = {
+		.name = "GPO3",
+	}
+};
+
+static struct regulator_init_data gpo4_init = {
+	.constraints = {
+		.name = "GPO4",
+	}
+};
+
+static struct regulator_init_data pwgt1_init = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on        = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(pwgt1_consumer),
+	.consumer_supplies = pwgt1_consumer,
+};
+
+static struct regulator_init_data pwgt2_init = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+		.boot_on        = 1,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(pwgt2_consumer),
+	.consumer_supplies = pwgt2_consumer,
+};
+
+static struct regulator_init_data vcoincell_init = {
+	.constraints = {
+		.name = "COINCELL",
+		.min_uV = 3000000,
+		.max_uV = 3000000,
+		.valid_ops_mask =
+			REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(coincell_consumer),
+	.consumer_supplies = coincell_consumer,
+};
+
+static struct mc13xxx_regulator_init_data mx51_efika_regulators[] = {
+	{ .id = MC13892_SW1,		.init_data =  &sw1_init },
+	{ .id = MC13892_SW2,		.init_data =  &sw2_init },
+	{ .id = MC13892_SW3,		.init_data =  &sw3_init },
+	{ .id = MC13892_SW4,		.init_data =  &sw4_init },
+	{ .id = MC13892_SWBST,		.init_data =  &swbst_init },
+	{ .id = MC13892_VIOHI,		.init_data =  &viohi_init },
+	{ .id = MC13892_VPLL,		.init_data =  &vpll_init },
+	{ .id = MC13892_VDIG,		.init_data =  &vdig_init },
+	{ .id = MC13892_VSD,		.init_data =  &vsd_init },
+	{ .id = MC13892_VUSB2,		.init_data =  &vusb2_init },
+	{ .id = MC13892_VVIDEO,		.init_data =  &vvideo_init },
+	{ .id = MC13892_VAUDIO,		.init_data =  &vaudio_init },
+	{ .id = MC13892_VCAM,		.init_data =  &vcam_init },
+	{ .id = MC13892_VGEN1,		.init_data =  &vgen1_init },
+	{ .id = MC13892_VGEN2,		.init_data =  &vgen2_init },
+	{ .id = MC13892_VGEN3,		.init_data =  &vgen3_init },
+	{ .id = MC13892_VUSB,		.init_data =  &vusb_init },
+	{ .id = MC13892_GPO1,		.init_data =  &gpo1_init },
+	{ .id = MC13892_GPO2,		.init_data =  &gpo2_init },
+	{ .id = MC13892_GPO3,		.init_data =  &gpo3_init },
+	{ .id = MC13892_GPO4,		.init_data =  &gpo4_init },
+	{ .id = MC13892_PWGT1SPI,	.init_data = &pwgt1_init },
+	{ .id = MC13892_PWGT2SPI,	.init_data = &pwgt2_init },
+	{ .id = MC13892_VCOINCELL,	.init_data = &vcoincell_init },
+};
+
+static struct mc13xxx_platform_data mx51_efika_mc13892_data = {
+	.flags = MC13XXX_USE_RTC | MC13XXX_USE_REGULATOR,
+	.regulators = {
+		.num_regulators = ARRAY_SIZE(mx51_efika_regulators),
+		.regulators = mx51_efika_regulators,
+	},
+};
+
+static struct spi_board_info mx51_efika_spi_board_info[] __initdata = {
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &mx51_efika_spi_flash_data,
+		.irq = -1,
+	},
+	{
+		.modalias = "mc13892",
+		.max_speed_hz = 1000000,
+		.bus_num = 0,
+		.chip_select = 0,
+		.platform_data = &mx51_efika_mc13892_data,
+		.irq = gpio_to_irq(EFIKAMX_PMIC),
+	},
+};
+
+static int mx51_efika_spi_cs[] = {
+	EFIKAMX_SPI_CS0,
+	EFIKAMX_SPI_CS1,
+};
+
+static const struct spi_imx_master mx51_efika_spi_pdata __initconst = {
+	.chipselect     = mx51_efika_spi_cs,
+	.num_chipselect = ARRAY_SIZE(mx51_efika_spi_cs),
+};
+
+void __init efika_board_common_init(void)
+{
+	mxc_iomux_v3_setup_multiple_pads(mx51efika_pads,
+					ARRAY_SIZE(mx51efika_pads));
+	imx51_add_imx_uart(0, &uart_pdata);
+	mx51_efika_usb();
+	imx51_add_sdhci_esdhc_imx(0, NULL);
+
+	/* FIXME: comes from original code. check this. */
+	if (mx51_revision() < IMX_CHIP_REVISION_2_0)
+		sw2_init.constraints.state_mem.uV = 1100000;
+	else if (mx51_revision() == IMX_CHIP_REVISION_2_0) {
+		sw2_init.constraints.state_mem.uV = 1250000;
+		sw1_init.constraints.state_mem.uV = 1000000;
+	}
+	if (machine_is_mx51_efikasb())
+		vgen1_init.constraints.max_uV = 1200000;
+
+	gpio_request(EFIKAMX_PMIC, "pmic irq");
+	gpio_direction_input(EFIKAMX_PMIC);
+	spi_register_board_info(mx51_efika_spi_board_info,
+		ARRAY_SIZE(mx51_efika_spi_board_info));
+	imx51_add_ecspi(0, &mx51_efika_spi_pdata);
+
+#if defined(CONFIG_CPU_FREQ_IMX)
+	get_cpu_op = mx51_get_cpu_op;
+#endif
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mx5/system.c linux-libre-2.6.39-gnu/arch/arm/mach-mx5/system.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mx5/system.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mx5/system.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2011 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
+ */
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+#include "crm_regs.h"
+
+/* set cpu low power mode before WFI instruction. This function is called
+  * mx5 because it can be used for mx50, mx51, and mx53.*/
+void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
+{
+	u32 plat_lpc, arm_srpgcr, ccm_clpcr;
+	u32 empgc0, empgc1;
+	int stop_mode = 0;
+
+	/* always allow platform to issue a deep sleep mode request */
+	plat_lpc = __raw_readl(MXC_CORTEXA8_PLAT_LPC) &
+	    ~(MXC_CORTEXA8_PLAT_LPC_DSM);
+	ccm_clpcr = __raw_readl(MXC_CCM_CLPCR) & ~(MXC_CCM_CLPCR_LPM_MASK);
+	arm_srpgcr = __raw_readl(MXC_SRPG_ARM_SRPGCR) & ~(MXC_SRPGCR_PCR);
+	empgc0 = __raw_readl(MXC_SRPG_EMPGC0_SRPGCR) & ~(MXC_SRPGCR_PCR);
+	empgc1 = __raw_readl(MXC_SRPG_EMPGC1_SRPGCR) & ~(MXC_SRPGCR_PCR);
+
+	switch (mode) {
+	case WAIT_CLOCKED:
+		break;
+	case WAIT_UNCLOCKED:
+		ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+		break;
+	case WAIT_UNCLOCKED_POWER_OFF:
+	case STOP_POWER_OFF:
+		plat_lpc |= MXC_CORTEXA8_PLAT_LPC_DSM
+			    | MXC_CORTEXA8_PLAT_LPC_DBG_DSM;
+		if (mode == WAIT_UNCLOCKED_POWER_OFF) {
+			ccm_clpcr |= 0x1 << MXC_CCM_CLPCR_LPM_OFFSET;
+			ccm_clpcr &= ~MXC_CCM_CLPCR_VSTBY;
+			ccm_clpcr &= ~MXC_CCM_CLPCR_SBYOS;
+			stop_mode = 0;
+		} else {
+			ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+			ccm_clpcr |= 0x3 << MXC_CCM_CLPCR_STBY_COUNT_OFFSET;
+			ccm_clpcr |= MXC_CCM_CLPCR_VSTBY;
+			ccm_clpcr |= MXC_CCM_CLPCR_SBYOS;
+			stop_mode = 1;
+		}
+		arm_srpgcr |= MXC_SRPGCR_PCR;
+
+		if (tzic_enable_wake(1) != 0)
+			return;
+		break;
+	case STOP_POWER_ON:
+		ccm_clpcr |= 0x2 << MXC_CCM_CLPCR_LPM_OFFSET;
+		break;
+	default:
+		printk(KERN_WARNING "UNKNOWN cpu power mode: %d\n", mode);
+		return;
+	}
+
+	__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
+	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
+	__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
+
+	/* Enable NEON SRPG for all but MX50TO1.0. */
+	if (mx50_revision() != IMX_CHIP_REVISION_1_0)
+		__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+
+	if (stop_mode) {
+		empgc0 |= MXC_SRPGCR_PCR;
+		empgc1 |= MXC_SRPGCR_PCR;
+
+		__raw_writel(empgc0, MXC_SRPG_EMPGC0_SRPGCR);
+		__raw_writel(empgc1, MXC_SRPG_EMPGC1_SRPGCR);
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxc91231/iomux.c linux-libre-2.6.39-gnu/arch/arm/mach-mxc91231/iomux.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxc91231/iomux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxc91231/iomux.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 /*
  * set the mode for a IOMUX pin.
  */
-int mxc_iomux_mode(const unsigned int pin_mode)
+int mxc_iomux_mode(unsigned int pin_mode)
 {
 	u32 side, field, l, mode, ret = 0;
 	void __iomem *reg;
@@ -114,7 +114,7 @@
  * 	- reserves the pin so that it is not claimed by another driver
  * 	- setups the iomux according to the configuration
  */
-int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label)
+int mxc_iomux_alloc_pin(unsigned int pin_mode, const char *label)
 {
 	unsigned pad = PIN_GLOBAL_NUM(pin_mode);
 	if (pad >= (PIN_MAX + 1)) {
@@ -134,10 +134,10 @@
 }
 EXPORT_SYMBOL(mxc_iomux_alloc_pin);
 
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 	int ret = -EINVAL;
 
@@ -155,7 +155,7 @@
 }
 EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
 
-void mxc_iomux_release_pin(const unsigned int pin_mode)
+void mxc_iomux_release_pin(unsigned int pin_mode)
 {
 	unsigned pad = PIN_GLOBAL_NUM(pin_mode);
 
@@ -164,9 +164,9 @@
 }
 EXPORT_SYMBOL(mxc_iomux_release_pin);
 
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count)
 {
-	unsigned int *p = pin_list;
+	const unsigned int *p = pin_list;
 	int i;
 
 	for (i = 0; i < count; i++) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxc91231/magx-zn5.c linux-libre-2.6.39-gnu/arch/arm/mach-mxc91231/magx-zn5.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxc91231/magx-zn5.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxc91231/magx-zn5.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,9 +53,10 @@
 };
 
 MACHINE_START(MAGX_ZN5, "Motorola Zn5")
-	.boot_params	= MXC91231_PHYS_OFFSET + 0x100,
-	.map_io		= mxc91231_map_io,
-	.init_irq	= mxc91231_init_irq,
-	.timer		= &zn5_timer,
-	.init_machine	= zn5_init,
+	.boot_params = MXC91231_PHYS_OFFSET + 0x100,
+	.map_io = mxc91231_map_io,
+	.init_early = mxc91231_init_early,
+	.init_irq = mxc91231_init_irq,
+	.timer = &zn5_timer,
+	.init_machine = zn5_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxc91231/mm.c linux-libre-2.6.39-gnu/arch/arm/mach-mxc91231/mm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxc91231/mm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxc91231/mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,11 +45,14 @@
  */
 void __init mxc91231_map_io(void)
 {
-	mxc_set_cpu_type(MXC_CPU_MXC91231);
-
 	iotable_init(mxc91231_io_desc, ARRAY_SIZE(mxc91231_io_desc));
 }
 
+void __init mxc91231_init_early(void)
+{
+	mxc_set_cpu_type(MXC_CPU_MXC91231);
+}
+
 int mxc91231_register_gpios(void);
 
 void __init mxc91231_init_irq(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/clock-mx23.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/clock-mx23.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/clock-mx23.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/clock-mx23.c	2011-05-19 00:06:34.000000000 -0400
@@ -442,11 +442,18 @@
 	_REGISTER_CLOCK("duart", "apb_pclk", xbus_clk)
 	/* for amba-pl011 driver */
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
-	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
 	_REGISTER_CLOCK(NULL, "usb", usb_clk)
 	_REGISTER_CLOCK(NULL, "audio", audio_clk)
-	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
+	_REGISTER_CLOCK("imx23-fb", NULL, lcdif_clk)
 };
 
 static int clk_misc_init(void)
@@ -514,6 +521,15 @@
 	__raw_writel(BM_CLKCTRL_CPU_INTERRUPT_WAIT,
 			CLKCTRL_BASE_ADDR + HW_CLKCTRL_CPU_SET);
 
+	/*
+	 * 480 MHz seems too high to be ssp clock source directly,
+	 * so set frac to get a 288 MHz ref_io.
+	 */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+	reg &= ~BM_CLKCTRL_FRAC_IOFRAC;
+	reg |= 30 << BP_CLKCTRL_FRAC_IOFRAC;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC);
+
 	return 0;
 }
 
@@ -521,6 +537,12 @@
 {
 	clk_misc_init();
 
+	/*
+	 * source ssp clock from ref_io than ref_xtal,
+	 * as ref_xtal only provides 24 MHz as maximum.
+	 */
+	clk_set_parent(&ssp_clk, &ref_io_clk);
+
 	clk_enable(&cpu_clk);
 	clk_enable(&hbus_clk);
 	clk_enable(&xbus_clk);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/clock-mx28.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/clock-mx28.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/clock-mx28.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/clock-mx28.c	2011-05-19 00:06:34.000000000 -0400
@@ -295,11 +295,11 @@
 	unsigned long diff, parent_rate, calc_rate;			\
 	int i;								\
 									\
-	parent_rate = clk_get_rate(clk->parent);			\
 	div_max = BM_CLKCTRL_##dr##_DIV >> BP_CLKCTRL_##dr##_DIV;	\
 	bm_busy = BM_CLKCTRL_##dr##_BUSY;				\
 									\
 	if (clk->parent == &ref_xtal_clk) {				\
+		parent_rate = clk_get_rate(clk->parent);		\
 		div = DIV_ROUND_UP(parent_rate, rate);			\
 		if (clk == &cpu_clk) {					\
 			div_max = BM_CLKCTRL_CPU_DIV_XTAL >>		\
@@ -309,6 +309,11 @@
 		if (div == 0 || div > div_max)				\
 			return -EINVAL;					\
 	} else {							\
+		/*							\
+		 * hack alert: this block modifies clk->parent, too,	\
+		 * so the base to use it the grand parent.		\
+		 */							\
+		parent_rate = clk_get_rate(clk->parent->parent);	\
 		rate >>= PARENT_RATE_SHIFT;				\
 		parent_rate >>= PARENT_RATE_SHIFT;			\
 		diff = parent_rate;					\
@@ -609,17 +614,32 @@
 	_REGISTER_CLOCK("duart", NULL, uart_clk)
 	_REGISTER_CLOCK("imx28-fec.0", NULL, fec_clk)
 	_REGISTER_CLOCK("imx28-fec.1", NULL, fec_clk)
+	_REGISTER_CLOCK("mxs-auart.0", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.1", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.2", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.3", NULL, uart_clk)
+	_REGISTER_CLOCK("mxs-auart.4", NULL, uart_clk)
 	_REGISTER_CLOCK("rtc", NULL, rtc_clk)
 	_REGISTER_CLOCK("pll2", NULL, pll2_clk)
-	_REGISTER_CLOCK(NULL, "hclk", hbus_clk)
-	_REGISTER_CLOCK(NULL, "xclk", xbus_clk)
-	_REGISTER_CLOCK(NULL, "can0", can0_clk)
-	_REGISTER_CLOCK(NULL, "can1", can1_clk)
+	_REGISTER_CLOCK("mxs-dma-apbh", NULL, hbus_clk)
+	_REGISTER_CLOCK("mxs-dma-apbx", NULL, xbus_clk)
+	_REGISTER_CLOCK("mxs-mmc.0", NULL, ssp0_clk)
+	_REGISTER_CLOCK("mxs-mmc.1", NULL, ssp1_clk)
+	_REGISTER_CLOCK("flexcan.0", NULL, can0_clk)
+	_REGISTER_CLOCK("flexcan.1", NULL, can1_clk)
 	_REGISTER_CLOCK(NULL, "usb0", usb0_clk)
 	_REGISTER_CLOCK(NULL, "usb1", usb1_clk)
-	_REGISTER_CLOCK(NULL, "pwm", pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.0", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.1", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.2", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.3", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.4", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.5", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.6", NULL, pwm_clk)
+	_REGISTER_CLOCK("mxs-pwm.7", NULL, pwm_clk)
 	_REGISTER_CLOCK(NULL, "lradc", lradc_clk)
 	_REGISTER_CLOCK(NULL, "spdif", spdif_clk)
+	_REGISTER_CLOCK("imx28-fb", NULL, lcdif_clk)
 };
 
 static int clk_misc_init(void)
@@ -724,6 +744,15 @@
 	reg |= BM_CLKCTRL_ENET_CLK_OUT_EN;
 	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_ENET);
 
+	/*
+	 * 480 MHz seems too high to be ssp clock source directly,
+	 * so set frac0 to get a 288 MHz ref_io0.
+	 */
+	reg = __raw_readl(CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
+	reg &= ~BM_CLKCTRL_FRAC0_IO0FRAC;
+	reg |= 30 << BP_CLKCTRL_FRAC0_IO0FRAC;
+	__raw_writel(reg, CLKCTRL_BASE_ADDR + HW_CLKCTRL_FRAC0);
+
 	return 0;
 }
 
@@ -731,12 +760,21 @@
 {
 	clk_misc_init();
 
+	/*
+	 * source ssp clock from ref_io0 than ref_xtal,
+	 * as ref_xtal only provides 24 MHz as maximum.
+	 */
+	clk_set_parent(&ssp0_clk, &ref_io0_clk);
+	clk_set_parent(&ssp1_clk, &ref_io0_clk);
+
 	clk_enable(&cpu_clk);
 	clk_enable(&hbus_clk);
 	clk_enable(&xbus_clk);
 	clk_enable(&emi_clk);
 	clk_enable(&uart_clk);
 
+	clk_set_parent(&lcdif_clk, &ref_pix_clk);
+
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
 	mxs_timer_init(&clk32k_clk, MX28_INT_TIMER0);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -2,5 +2,24 @@
 	bool
 	select ARM_AMBA
 
+config MXS_HAVE_PLATFORM_AUART
+	bool
+
 config MXS_HAVE_PLATFORM_FEC
 	bool
+
+config MXS_HAVE_PLATFORM_FLEXCAN
+	select HAVE_CAN_FLEXCAN if CAN
+	bool
+
+config MXS_HAVE_PLATFORM_MXS_I2C
+	bool
+
+config MXS_HAVE_PLATFORM_MXS_MMC
+	bool
+
+config MXS_HAVE_PLATFORM_MXS_PWM
+	bool
+
+config MXS_HAVE_PLATFORM_MXSFB
+	bool
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,2 +1,9 @@
 obj-$(CONFIG_MXS_HAVE_AMBA_DUART) += amba-duart.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_AUART) += platform-auart.o
+obj-y += platform-dma.o
 obj-$(CONFIG_MXS_HAVE_PLATFORM_FEC) += platform-fec.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_FLEXCAN) += platform-flexcan.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_I2C) += platform-mxs-i2c.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_MMC) += platform-mxs-mmc.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXS_PWM) += platform-mxs-pwm.o
+obj-$(CONFIG_MXS_HAVE_PLATFORM_MXSFB) += platform-mxsfb.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-auart.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-auart.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-auart.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-auart.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Sascha Hauer <s.hauer@pengutronix.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 <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_auart_data_entry_single(soc, _id, hwid)			\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _AUART ## hwid ## _BASE_ADDR,		\
+		.irq = soc ## _INT_AUART ## hwid,			\
+	}
+
+#define mxs_auart_data_entry(soc, _id, hwid)				\
+	[_id] = mxs_auart_data_entry_single(soc, _id, hwid)
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_auart_data mx23_auart_data[] __initconst = {
+#define mx23_auart_data_entry(_id, hwid)				\
+	mxs_auart_data_entry(MX23, _id, hwid)
+	mx23_auart_data_entry(0, 1),
+	mx23_auart_data_entry(1, 2),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_auart_data mx28_auart_data[] __initconst = {
+#define mx28_auart_data_entry(_id)					\
+	mxs_auart_data_entry(MX28, _id, _id)
+	mx28_auart_data_entry(0),
+	mx28_auart_data_entry(1),
+	mx28_auart_data_entry(2),
+	mx28_auart_data_entry(3),
+	mx28_auart_data_entry(4),
+};
+#endif
+
+struct platform_device *__init mxs_add_auart(
+		const struct mxs_auart_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device_dmamask("mxs-auart", data->id,
+					res, ARRAY_SIZE(res), NULL, 0,
+					DMA_BIT_MASK(32));
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-dma.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2011 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.
+ */
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+static struct platform_device *__init mxs_add_dma(const char *devid,
+						resource_size_t base)
+{
+	struct resource res[] = {
+		{
+			.start = base,
+			.end = base + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}
+	};
+
+	return mxs_add_platform_device_dmamask(devid, -1,
+				res, ARRAY_SIZE(res), NULL, 0,
+				DMA_BIT_MASK(32));
+}
+
+static int __init mxs_add_mxs_dma(void)
+{
+	char *apbh = "mxs-dma-apbh";
+	char *apbx = "mxs-dma-apbx";
+
+	if (cpu_is_mx23()) {
+		mxs_add_dma(apbh, MX23_APBH_DMA_BASE_ADDR);
+		mxs_add_dma(apbx, MX23_APBX_DMA_BASE_ADDR);
+	}
+
+	if (cpu_is_mx28()) {
+		mxs_add_dma(apbh, MX28_APBH_DMA_BASE_ADDR);
+		mxs_add_dma(apbx, MX28_APBX_DMA_BASE_ADDR);
+	}
+
+	return 0;
+}
+arch_initcall(mxs_add_mxs_dma);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-fec.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-fec.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-fec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-fec.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 		},
 	};
 
-	return mxs_add_platform_device("imx28-fec", data->id,
-			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+	return mxs_add_platform_device_dmamask("imx28-fec", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata),
+			DMA_BIT_MASK(32));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-flexcan.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-flexcan.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-flexcan.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-flexcan.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2010, 2011 Pengutronix,
+ *                          Marc Kleine-Budde <kernel@pengutronix.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 <asm/sizes.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_flexcan_data_entry_single(soc, _id, _hwid, _size)		\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _CAN ## _hwid ## _BASE_ADDR,		\
+		.iosize = _size,					\
+		.irq = soc ## _INT_CAN ## _hwid,			\
+	}
+
+#define mxs_flexcan_data_entry(soc, _id, _hwid, _size)			\
+	[_id] = mxs_flexcan_data_entry_single(soc, _id, _hwid, _size)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_flexcan_data mx28_flexcan_data[] __initconst = {
+#define mx28_flexcan_data_entry(_id, _hwid)				\
+	mxs_flexcan_data_entry_single(MX28, _id, _hwid, SZ_8K)
+	mx28_flexcan_data_entry(0, 0),
+	mx28_flexcan_data_entry(1, 1),
+};
+#endif /* ifdef CONFIG_SOC_IMX28 */
+
+struct platform_device *__init mxs_add_flexcan(
+		const struct mxs_flexcan_data *data,
+		const struct flexcan_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + data->iosize - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->irq,
+			.end = data->irq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("flexcan", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxsfb.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxsfb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxsfb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxsfb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2011 Pengutronix, Sascha Hauer <s.hauer@pengutronix.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 <asm/sizes.h>
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+#include <mach/mxsfb.h>
+
+#ifdef CONFIG_SOC_IMX23
+struct platform_device *__init mx23_add_mxsfb(
+		const struct mxsfb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX23_LCDIF_BASE_ADDR,
+			.end = MX23_LCDIF_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return mxs_add_platform_device_dmamask("imx23-fb", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+#endif /* ifdef CONFIG_SOC_IMX23 */
+
+#ifdef CONFIG_SOC_IMX28
+struct platform_device *__init mx28_add_mxsfb(
+		const struct mxsfb_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start = MX28_LCDIF_BASE_ADDR,
+			.end = MX28_LCDIF_BASE_ADDR + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		},
+	};
+
+	return mxs_add_platform_device_dmamask("imx28-fb", -1,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata), DMA_BIT_MASK(32));
+}
+#endif /* ifdef CONFIG_SOC_IMX28 */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxs-i2c.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxs-i2c.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxs-i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxs-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2011 Pengutronix
+ * Wolfram Sang <w.sang@pengutronix.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 <asm/sizes.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_i2c_data_entry_single(soc, _id)				\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _I2C ## _id ## _BASE_ADDR,		\
+		.errirq = soc ## _INT_I2C ## _id ## _ERROR,		\
+		.dmairq = soc ## _INT_I2C ## _id ## _DMA,		\
+	}
+
+#define mxs_i2c_data_entry(soc, _id)					\
+	[_id] = mxs_i2c_data_entry_single(soc, _id)
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_i2c_data mx28_mxs_i2c_data[] __initconst = {
+	mxs_i2c_data_entry(MX28, 0),
+	mxs_i2c_data_entry(MX28, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_mxs_i2c(const struct mxs_i2c_data *data)
+{
+	struct resource res[] = {
+		{
+			.start = data->iobase,
+			.end = data->iobase + SZ_8K - 1,
+			.flags = IORESOURCE_MEM,
+		}, {
+			.start = data->errirq,
+			.end = data->errirq,
+			.flags = IORESOURCE_IRQ,
+		}, {
+			.start = data->dmairq,
+			.end = data->dmairq,
+			.flags = IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-i2c", data->id, res,
+					ARRAY_SIZE(res), NULL, 0);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxs-mmc.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxs-mmc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxs-mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxs-mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
+ *
+ * Copyright 2011 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.
+ */
+
+#include <linux/compiler.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <mach/mx23.h>
+#include <mach/mx28.h>
+#include <mach/devices-common.h>
+
+#define mxs_mxs_mmc_data_entry_single(soc, _id, hwid)			\
+	{								\
+		.id = _id,						\
+		.iobase = soc ## _SSP ## hwid ## _BASE_ADDR,		\
+		.dma = soc ## _DMA_SSP ## hwid,				\
+		.irq_err = soc ## _INT_SSP ## hwid ## _ERROR,		\
+		.irq_dma = soc ## _INT_SSP ## hwid ## _DMA,		\
+	}
+
+#define mxs_mxs_mmc_data_entry(soc, _id, hwid)				\
+	[_id] = mxs_mxs_mmc_data_entry_single(soc, _id, hwid)
+
+
+#ifdef CONFIG_SOC_IMX23
+const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst = {
+	mxs_mxs_mmc_data_entry(MX23, 0, 1),
+	mxs_mxs_mmc_data_entry(MX23, 1, 2),
+};
+#endif
+
+#ifdef CONFIG_SOC_IMX28
+const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst = {
+	mxs_mxs_mmc_data_entry(MX28, 0, 0),
+	mxs_mxs_mmc_data_entry(MX28, 1, 1),
+};
+#endif
+
+struct platform_device *__init mxs_add_mxs_mmc(
+		const struct mxs_mxs_mmc_data *data,
+		const struct mxs_mmc_platform_data *pdata)
+{
+	struct resource res[] = {
+		{
+			.start	= data->iobase,
+			.end	= data->iobase + SZ_8K - 1,
+			.flags	= IORESOURCE_MEM,
+		}, {
+			.start	= data->dma,
+			.end	= data->dma,
+			.flags	= IORESOURCE_DMA,
+		}, {
+			.start	= data->irq_err,
+			.end	= data->irq_err,
+			.flags	= IORESOURCE_IRQ,
+		}, {
+			.start	= data->irq_dma,
+			.end	= data->irq_dma,
+			.flags	= IORESOURCE_IRQ,
+		},
+	};
+
+	return mxs_add_platform_device("mxs-mmc", data->id,
+			res, ARRAY_SIZE(res), pdata, sizeof(*pdata));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxs-pwm.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxs-pwm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices/platform-mxs-pwm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices/platform-mxs-pwm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ * Sascha Hauer <s.hauer@pengutronix.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 <asm/sizes.h>
+#include <mach/devices-common.h>
+
+struct platform_device *__init mxs_add_mxs_pwm(resource_size_t iobase, int id)
+{
+	struct resource res = {
+		.flags = IORESOURCE_MEM,
+	};
+
+	res.start = iobase + 0x10 + 0x20 * id;
+	res.end = res.start + 0x1f;
+
+	return mxs_add_platform_device("mxs-pwm", id, &res, 1, NULL, 0);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,6 +66,8 @@
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		if (dmamask)
+			kfree(pdev->dev.dma_mask);
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices-mx23.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices-mx23.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices-mx23.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices-mx23.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,22 @@
  */
 #include <mach/mx23.h>
 #include <mach/devices-common.h>
+#include <mach/mxsfb.h>
 
 extern const struct amba_device mx23_duart_device __initconst;
 #define mx23_add_duart() \
 	mxs_add_duart(&mx23_duart_device)
+
+extern const struct mxs_auart_data mx23_auart_data[] __initconst;
+#define mx23_add_auart(id)	mxs_add_auart(&mx23_auart_data[id])
+#define mx23_add_auart0()		mx23_add_auart(0)
+#define mx23_add_auart1()		mx23_add_auart(1)
+
+extern const struct mxs_mxs_mmc_data mx23_mxs_mmc_data[] __initconst;
+#define mx23_add_mxs_mmc(id, pdata) \
+	mxs_add_mxs_mmc(&mx23_mxs_mmc_data[id], pdata)
+
+#define mx23_add_mxs_pwm(id)		mxs_add_mxs_pwm(MX23_PWM_BASE_ADDR, id)
+
+struct platform_device *__init mx23_add_mxsfb(
+		const struct mxsfb_platform_data *pdata);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices-mx28.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices-mx28.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/devices-mx28.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/devices-mx28.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,11 +10,38 @@
  */
 #include <mach/mx28.h>
 #include <mach/devices-common.h>
+#include <mach/mxsfb.h>
 
 extern const struct amba_device mx28_duart_device __initconst;
 #define mx28_add_duart() \
 	mxs_add_duart(&mx28_duart_device)
 
+extern const struct mxs_auart_data mx28_auart_data[] __initconst;
+#define mx28_add_auart(id)	mxs_add_auart(&mx28_auart_data[id])
+#define mx28_add_auart0()		mx28_add_auart(0)
+#define mx28_add_auart1()		mx28_add_auart(1)
+#define mx28_add_auart2()		mx28_add_auart(2)
+#define mx28_add_auart3()		mx28_add_auart(3)
+#define mx28_add_auart4()		mx28_add_auart(4)
+
 extern const struct mxs_fec_data mx28_fec_data[] __initconst;
 #define mx28_add_fec(id, pdata) \
 	mxs_add_fec(&mx28_fec_data[id], pdata)
+
+extern const struct mxs_flexcan_data mx28_flexcan_data[] __initconst;
+#define mx28_add_flexcan(id, pdata)	\
+	mxs_add_flexcan(&mx28_flexcan_data[id], pdata)
+#define mx28_add_flexcan0(pdata)	mx28_add_flexcan(0, pdata)
+#define mx28_add_flexcan1(pdata)	mx28_add_flexcan(1, pdata)
+
+extern const struct mxs_i2c_data mx28_mxs_i2c_data[] __initconst;
+#define mx28_add_mxs_i2c(id)		mxs_add_mxs_i2c(&mx28_mxs_i2c_data[id])
+
+extern const struct mxs_mxs_mmc_data mx28_mxs_mmc_data[] __initconst;
+#define mx28_add_mxs_mmc(id, pdata) \
+	mxs_add_mxs_mmc(&mx28_mxs_mmc_data[id], pdata)
+
+#define mx28_add_mxs_pwm(id)		mxs_add_mxs_pwm(MX28_PWM_BASE_ADDR, id)
+
+struct platform_device *__init mx28_add_mxsfb(
+		const struct mxsfb_platform_data *pdata);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,29 +68,29 @@
 	}
 }
 
-static void mxs_gpio_ack_irq(u32 irq)
+static void mxs_gpio_ack_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	clear_gpio_irqstatus(&mxs_gpio_ports[gpio / 32], gpio & 0x1f);
 }
 
-static void mxs_gpio_mask_irq(u32 irq)
+static void mxs_gpio_mask_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 0);
 }
 
-static void mxs_gpio_unmask_irq(u32 irq)
+static void mxs_gpio_unmask_irq(struct irq_data *d)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	set_gpio_irqenable(&mxs_gpio_ports[gpio / 32], gpio & 0x1f, 1);
 }
 
 static int mxs_gpio_get(struct gpio_chip *chip, unsigned offset);
 
-static int mxs_gpio_set_irq_type(u32 irq, u32 type)
+static int mxs_gpio_set_irq_type(struct irq_data *d, unsigned int type)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	u32 pin_mask = 1 << (gpio & 31);
 	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
 	void __iomem *pin_addr;
@@ -136,7 +136,7 @@
 static void mxs_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
 	u32 irq_stat;
-	struct mxs_gpio_port *port = (struct mxs_gpio_port *)get_irq_data(irq);
+	struct mxs_gpio_port *port = (struct mxs_gpio_port *)irq_get_handler_data(irq);
 	u32 gpio_irq_no_base = port->virtual_irq_start;
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -160,9 +160,9 @@
  * @param  enable       enable as wake-up if equal to non-zero
  * @return       This function returns 0 on success.
  */
-static int mxs_gpio_set_wake_irq(u32 irq, u32 enable)
+static int mxs_gpio_set_wake_irq(struct irq_data *d, unsigned int enable)
 {
-	u32 gpio = irq_to_gpio(irq);
+	u32 gpio = irq_to_gpio(d->irq);
 	u32 gpio_idx = gpio & 0x1f;
 	struct mxs_gpio_port *port = &mxs_gpio_ports[gpio / 32];
 
@@ -182,11 +182,12 @@
 }
 
 static struct irq_chip gpio_irq_chip = {
-	.ack = mxs_gpio_ack_irq,
-	.mask = mxs_gpio_mask_irq,
-	.unmask = mxs_gpio_unmask_irq,
-	.set_type = mxs_gpio_set_irq_type,
-	.set_wake = mxs_gpio_set_wake_irq,
+	.name = "mxs gpio",
+	.irq_ack = mxs_gpio_ack_irq,
+	.irq_mask = mxs_gpio_mask_irq,
+	.irq_unmask = mxs_gpio_unmask_irq,
+	.irq_set_type = mxs_gpio_set_irq_type,
+	.irq_set_wake = mxs_gpio_set_wake_irq,
 };
 
 static void mxs_set_gpio_direction(struct gpio_chip *chip, unsigned offset,
@@ -264,14 +265,14 @@
 
 		for (j = port[i].virtual_irq_start;
 			j < port[i].virtual_irq_start + 32; j++) {
-			set_irq_chip(j, &gpio_irq_chip);
-			set_irq_handler(j, handle_level_irq);
+			irq_set_chip_and_handler(j, &gpio_irq_chip,
+						 handle_level_irq);
 			set_irq_flags(j, IRQF_VALID);
 		}
 
 		/* setup one handler for each entry */
-		set_irq_chained_handler(port[i].irq, mxs_gpio_irq_handler);
-		set_irq_data(port[i].irq, &port[i]);
+		irq_set_chained_handler(port[i].irq, mxs_gpio_irq_handler);
+		irq_set_handler_data(port[i].irq, &port[i]);
 
 		/* register gpio chip */
 		port[i].chip.direction_input = mxs_gpio_direction_input;
@@ -289,39 +290,42 @@
 	return 0;
 }
 
-#define DEFINE_MXS_GPIO_PORT(soc, _id)					\
+#define MX23_GPIO_BASE	MX23_IO_ADDRESS(MX23_PINCTRL_BASE_ADDR)
+#define MX28_GPIO_BASE	MX28_IO_ADDRESS(MX28_PINCTRL_BASE_ADDR)
+
+#define DEFINE_MXS_GPIO_PORT(_base, _irq, _id)				\
 	{								\
 		.chip.label = "gpio-" #_id,				\
 		.id = _id,						\
-		.irq = soc ## _INT_GPIO ## _id,				\
-		.base = soc ## _IO_ADDRESS(				\
-				soc ## _PINCTRL ## _BASE_ADDR),		\
+		.irq = _irq,						\
+		.base = _base,						\
 		.virtual_irq_start = MXS_GPIO_IRQ_START + (_id) * 32,	\
 	}
 
-#define DEFINE_REGISTER_FUNCTION(prefix)				\
-int __init prefix ## _register_gpios(void)				\
-{									\
-	return mxs_gpio_init(prefix ## _gpio_ports,			\
-			ARRAY_SIZE(prefix ## _gpio_ports));		\
-}
-
 #ifdef CONFIG_SOC_IMX23
 static struct mxs_gpio_port mx23_gpio_ports[] = {
-	DEFINE_MXS_GPIO_PORT(MX23, 0),
-	DEFINE_MXS_GPIO_PORT(MX23, 1),
-	DEFINE_MXS_GPIO_PORT(MX23, 2),
+	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO0, 0),
+	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO1, 1),
+	DEFINE_MXS_GPIO_PORT(MX23_GPIO_BASE, MX23_INT_GPIO2, 2),
 };
-DEFINE_REGISTER_FUNCTION(mx23)
+
+int __init mx23_register_gpios(void)
+{
+	return mxs_gpio_init(mx23_gpio_ports, ARRAY_SIZE(mx23_gpio_ports));
+}
 #endif
 
 #ifdef CONFIG_SOC_IMX28
 static struct mxs_gpio_port mx28_gpio_ports[] = {
-	DEFINE_MXS_GPIO_PORT(MX28, 0),
-	DEFINE_MXS_GPIO_PORT(MX28, 1),
-	DEFINE_MXS_GPIO_PORT(MX28, 2),
-	DEFINE_MXS_GPIO_PORT(MX28, 3),
-	DEFINE_MXS_GPIO_PORT(MX28, 4),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO0, 0),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO1, 1),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO2, 2),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO3, 3),
+	DEFINE_MXS_GPIO_PORT(MX28_GPIO_BASE, MX28_INT_GPIO4, 4),
 };
-DEFINE_REGISTER_FUNCTION(mx28)
+
+int __init mx28_register_gpios(void)
+{
+	return mxs_gpio_init(mx28_gpio_ports, ARRAY_SIZE(mx28_gpio_ports));
+}
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/icoll.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/icoll.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/icoll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/icoll.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 
 static void __iomem *icoll_base = MXS_IO_ADDRESS(MXS_ICOLL_BASE_ADDR);
 
-static void icoll_ack_irq(unsigned int irq)
+static void icoll_ack_irq(struct irq_data *d)
 {
 	/*
 	 * The Interrupt Collector is able to prioritize irqs.
@@ -45,22 +45,22 @@
 			icoll_base + HW_ICOLL_LEVELACK);
 }
 
-static void icoll_mask_irq(unsigned int irq)
+static void icoll_mask_irq(struct irq_data *d)
 {
 	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_CLR(irq));
+			icoll_base + HW_ICOLL_INTERRUPTn_CLR(d->irq));
 }
 
-static void icoll_unmask_irq(unsigned int irq)
+static void icoll_unmask_irq(struct irq_data *d)
 {
 	__raw_writel(BM_ICOLL_INTERRUPTn_ENABLE,
-			icoll_base + HW_ICOLL_INTERRUPTn_SET(irq));
+			icoll_base + HW_ICOLL_INTERRUPTn_SET(d->irq));
 }
 
 static struct irq_chip mxs_icoll_chip = {
-	.ack = icoll_ack_irq,
-	.mask = icoll_mask_irq,
-	.unmask = icoll_unmask_irq,
+	.irq_ack = icoll_ack_irq,
+	.irq_mask = icoll_mask_irq,
+	.irq_unmask = icoll_unmask_irq,
 };
 
 void __init icoll_init_irq(void)
@@ -74,8 +74,7 @@
 	mxs_reset_block(icoll_base + HW_ICOLL_CTRL);
 
 	for (i = 0; i < MXS_INTERNAL_IRQS; i++) {
-		set_irq_chip(i, &mxs_icoll_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &mxs_icoll_chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/common.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 
 struct clk;
 
+extern const u32 *mxs_get_ocotp(void);
 extern int mxs_reset_block(void __iomem *);
 extern void mxs_timer_init(struct clk *, int);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/devices-common.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/devices-common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/devices-common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/devices-common.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,16 @@
 /* duart */
 int __init mxs_add_duart(const struct amba_device *dev);
 
+/* auart */
+struct mxs_auart_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init mxs_add_auart(
+		const struct mxs_auart_data *data);
+
 /* fec */
 #include <linux/fec.h>
 struct mxs_fec_data {
@@ -41,3 +51,41 @@
 struct platform_device *__init mxs_add_fec(
 		const struct mxs_fec_data *data,
 		const struct fec_platform_data *pdata);
+
+/* flexcan */
+#include <linux/can/platform/flexcan.h>
+struct mxs_flexcan_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t iosize;
+	resource_size_t irq;
+};
+struct platform_device *__init mxs_add_flexcan(
+		const struct mxs_flexcan_data *data,
+		const struct flexcan_platform_data *pdata);
+
+/* i2c */
+struct mxs_i2c_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t errirq;
+	resource_size_t dmairq;
+};
+struct platform_device * __init mxs_add_mxs_i2c(const struct mxs_i2c_data *data);
+
+/* mmc */
+#include <mach/mmc.h>
+struct mxs_mxs_mmc_data {
+	int id;
+	resource_size_t iobase;
+	resource_size_t dma;
+	resource_size_t irq_err;
+	resource_size_t irq_dma;
+};
+struct platform_device *__init mxs_add_mxs_mmc(
+		const struct mxs_mxs_mmc_data *data,
+		const struct mxs_mmc_platform_data *pdata);
+
+/* pwm */
+struct platform_device *__init mxs_add_mxs_pwm(
+		resource_size_t iobase, int id);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/dma.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2011 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 __MACH_MXS_DMA_H__
+#define __MACH_MXS_DMA_H__
+
+struct mxs_dma_data {
+	int chan_irq;
+};
+
+static inline int mxs_dma_is_apbh(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbh");
+}
+
+static inline int mxs_dma_is_apbx(struct dma_chan *chan)
+{
+	return !strcmp(dev_name(chan->device->dev), "mxs-dma-apbx");
+}
+
+#endif /* __MACH_MXS_DMA_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/iomux.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/iomux.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/iomux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/iomux.h	2011-05-19 00:06:34.000000000 -0400
@@ -91,6 +91,9 @@
 #define MXS_PAD_PULLUP	((PAD_PULLUP << MXS_PAD_PULL_SHIFT) | \
 					MXS_PAD_PULL_VALID_MASK)
 
+/* generic pad control used in most cases */
+#define MXS_PAD_CTRL	(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL)
+
 #define MXS_IOMUX_PAD(_bank, _pin, _muxsel, _ma, _vol, _pull)		\
 		(((iomux_cfg_t)(_bank) << MXS_PAD_BANK_SHIFT) |		\
 		((iomux_cfg_t)(_pin) << MXS_PAD_PIN_SHIFT) |		\
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/iomux-mx23.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/iomux-mx23.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/iomux-mx23.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/iomux-mx23.h	2011-05-19 00:06:34.000000000 -0400
@@ -254,102 +254,102 @@
 #define MX23_PAD_ROTARYB__GPMI_CE3N		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_2)
 
 /* MUXSEL_GPIO */
-#define MX23_PAD_GPMI_D00__GPO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D01__GPO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D02__GPO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D03__GPO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D04__GPO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D05__GPO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D06__GPO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D07__GPO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D08__GPO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D09__GPO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D10__GPO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D11__GPO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D12__GPO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D13__GPO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D14__GPO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_D15__GPO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CLE__GPO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_ALE__GPO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE2N__GPO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY0__GPO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY1__GPO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY2__GPO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDY3__GPO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WPN__GPO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_WRN__GPO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_RDN__GPO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_CTS__GPO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RTS__GPO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_RX__GPO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_AUART1_TX__GPO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SCL__GPO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_I2C_SDA__GPO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D00__GPIO_0_0		MXS_IOMUX_PAD_NAKED(0,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D01__GPIO_0_1		MXS_IOMUX_PAD_NAKED(0,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D02__GPIO_0_2		MXS_IOMUX_PAD_NAKED(0,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D03__GPIO_0_3		MXS_IOMUX_PAD_NAKED(0,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D04__GPIO_0_4		MXS_IOMUX_PAD_NAKED(0,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D05__GPIO_0_5		MXS_IOMUX_PAD_NAKED(0,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D06__GPIO_0_6		MXS_IOMUX_PAD_NAKED(0,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D07__GPIO_0_7		MXS_IOMUX_PAD_NAKED(0,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D08__GPIO_0_8		MXS_IOMUX_PAD_NAKED(0,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D09__GPIO_0_9		MXS_IOMUX_PAD_NAKED(0,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D10__GPIO_0_10		MXS_IOMUX_PAD_NAKED(0, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D11__GPIO_0_11		MXS_IOMUX_PAD_NAKED(0, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D12__GPIO_0_12		MXS_IOMUX_PAD_NAKED(0, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D13__GPIO_0_13		MXS_IOMUX_PAD_NAKED(0, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D14__GPIO_0_14		MXS_IOMUX_PAD_NAKED(0, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_D15__GPIO_0_15		MXS_IOMUX_PAD_NAKED(0, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CLE__GPIO_0_16		MXS_IOMUX_PAD_NAKED(0, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_ALE__GPIO_0_17		MXS_IOMUX_PAD_NAKED(0, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE2N__GPIO_0_18		MXS_IOMUX_PAD_NAKED(0, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY0__GPIO_0_19		MXS_IOMUX_PAD_NAKED(0, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY1__GPIO_0_20		MXS_IOMUX_PAD_NAKED(0, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY2__GPIO_0_21		MXS_IOMUX_PAD_NAKED(0, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDY3__GPIO_0_22		MXS_IOMUX_PAD_NAKED(0, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WPN__GPIO_0_23		MXS_IOMUX_PAD_NAKED(0, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_WRN__GPIO_0_24		MXS_IOMUX_PAD_NAKED(0, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_RDN__GPIO_0_25		MXS_IOMUX_PAD_NAKED(0, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_CTS__GPIO_0_26		MXS_IOMUX_PAD_NAKED(0, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RTS__GPIO_0_27		MXS_IOMUX_PAD_NAKED(0, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_RX__GPIO_0_28		MXS_IOMUX_PAD_NAKED(0, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_AUART1_TX__GPIO_0_29		MXS_IOMUX_PAD_NAKED(0, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SCL__GPIO_0_30		MXS_IOMUX_PAD_NAKED(0, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_I2C_SDA__GPIO_0_31		MXS_IOMUX_PAD_NAKED(0, 31, PAD_MUXSEL_GPIO)
 
-#define MX23_PAD_LCD_D00__GPO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D01__GPO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D02__GPO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D03__GPO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D04__GPO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D05__GPO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D06__GPO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D07__GPO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D08__GPO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D09__GPO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D10__GPO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D11__GPO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D12__GPO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D13__GPO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D14__GPO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D15__GPO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D16__GPO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_D17__GPO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RESET__GPO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_RS__GPO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_WR__GPO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_CS__GPO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_DOTCK__GPO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_ENABLE__GPO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_HSYNC__GPO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_LCD_VSYNC__GPO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM0__GPO_1_26			MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM1__GPO_1_27			MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM2__GPO_1_28			MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM3__GPO_1_29			MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_PWM4__GPO_1_30			MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D00__GPIO_1_0		MXS_IOMUX_PAD_NAKED(1,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D01__GPIO_1_1		MXS_IOMUX_PAD_NAKED(1,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D02__GPIO_1_2		MXS_IOMUX_PAD_NAKED(1,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D03__GPIO_1_3		MXS_IOMUX_PAD_NAKED(1,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D04__GPIO_1_4		MXS_IOMUX_PAD_NAKED(1,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D05__GPIO_1_5		MXS_IOMUX_PAD_NAKED(1,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D06__GPIO_1_6		MXS_IOMUX_PAD_NAKED(1,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D07__GPIO_1_7		MXS_IOMUX_PAD_NAKED(1,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D08__GPIO_1_8		MXS_IOMUX_PAD_NAKED(1,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D09__GPIO_1_9		MXS_IOMUX_PAD_NAKED(1,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D10__GPIO_1_10		MXS_IOMUX_PAD_NAKED(1, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D11__GPIO_1_11		MXS_IOMUX_PAD_NAKED(1, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D12__GPIO_1_12		MXS_IOMUX_PAD_NAKED(1, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D13__GPIO_1_13		MXS_IOMUX_PAD_NAKED(1, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D14__GPIO_1_14		MXS_IOMUX_PAD_NAKED(1, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D15__GPIO_1_15		MXS_IOMUX_PAD_NAKED(1, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D16__GPIO_1_16		MXS_IOMUX_PAD_NAKED(1, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_D17__GPIO_1_17		MXS_IOMUX_PAD_NAKED(1, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RESET__GPIO_1_18		MXS_IOMUX_PAD_NAKED(1, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_RS__GPIO_1_19		MXS_IOMUX_PAD_NAKED(1, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_WR__GPIO_1_20		MXS_IOMUX_PAD_NAKED(1, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_CS__GPIO_1_21		MXS_IOMUX_PAD_NAKED(1, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_DOTCK__GPIO_1_22		MXS_IOMUX_PAD_NAKED(1, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_ENABLE__GPIO_1_23		MXS_IOMUX_PAD_NAKED(1, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_HSYNC__GPIO_1_24		MXS_IOMUX_PAD_NAKED(1, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_LCD_VSYNC__GPIO_1_25		MXS_IOMUX_PAD_NAKED(1, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM0__GPIO_1_26		MXS_IOMUX_PAD_NAKED(1, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM1__GPIO_1_27		MXS_IOMUX_PAD_NAKED(1, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM2__GPIO_1_28		MXS_IOMUX_PAD_NAKED(1, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM3__GPIO_1_29		MXS_IOMUX_PAD_NAKED(1, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_PWM4__GPIO_1_30		MXS_IOMUX_PAD_NAKED(1, 30, PAD_MUXSEL_GPIO)
 
-#define MX23_PAD_SSP1_CMD__GPO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DETECT__GPO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA0__GPO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA1__GPO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA2__GPO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_DATA3__GPO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
-#define MX23_PAD_SSP1_SCK__GPO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYA__GPO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
-#define MX23_PAD_ROTARYB__GPO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A00__GPO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A01__GPO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A02__GPO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A03__GPO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A04__GPO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A05__GPO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A06__GPO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A07__GPO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A08__GPO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A09__GPO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A10__GPO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A11__GPO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_A12__GPO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA0__GPO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_BA1__GPO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CASN__GPO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE0N__GPO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CE1N__GPO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE1N__GPO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
-#define MX23_PAD_GPMI_CE0N__GPO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_CKE__GPO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_RASN__GPO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
-#define MX23_PAD_EMI_WEN__GPO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_CMD__GPIO_2_0		MXS_IOMUX_PAD_NAKED(2,  0, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DETECT__GPIO_2_1		MXS_IOMUX_PAD_NAKED(2,  1, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA0__GPIO_2_2		MXS_IOMUX_PAD_NAKED(2,  2, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA1__GPIO_2_3		MXS_IOMUX_PAD_NAKED(2,  3, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA2__GPIO_2_4		MXS_IOMUX_PAD_NAKED(2,  4, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_DATA3__GPIO_2_5		MXS_IOMUX_PAD_NAKED(2,  5, PAD_MUXSEL_GPIO)
+#define MX23_PAD_SSP1_SCK__GPIO_2_6		MXS_IOMUX_PAD_NAKED(2,  6, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYA__GPIO_2_7		MXS_IOMUX_PAD_NAKED(2,  7, PAD_MUXSEL_GPIO)
+#define MX23_PAD_ROTARYB__GPIO_2_8		MXS_IOMUX_PAD_NAKED(2,  8, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A00__GPIO_2_9		MXS_IOMUX_PAD_NAKED(2,  9, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A01__GPIO_2_10		MXS_IOMUX_PAD_NAKED(2, 10, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A02__GPIO_2_11		MXS_IOMUX_PAD_NAKED(2, 11, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A03__GPIO_2_12		MXS_IOMUX_PAD_NAKED(2, 12, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A04__GPIO_2_13		MXS_IOMUX_PAD_NAKED(2, 13, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A05__GPIO_2_14		MXS_IOMUX_PAD_NAKED(2, 14, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A06__GPIO_2_15		MXS_IOMUX_PAD_NAKED(2, 15, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A07__GPIO_2_16		MXS_IOMUX_PAD_NAKED(2, 16, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A08__GPIO_2_17		MXS_IOMUX_PAD_NAKED(2, 17, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A09__GPIO_2_18		MXS_IOMUX_PAD_NAKED(2, 18, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A10__GPIO_2_19		MXS_IOMUX_PAD_NAKED(2, 19, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A11__GPIO_2_20		MXS_IOMUX_PAD_NAKED(2, 20, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_A12__GPIO_2_21		MXS_IOMUX_PAD_NAKED(2, 21, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA0__GPIO_2_22		MXS_IOMUX_PAD_NAKED(2, 22, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_BA1__GPIO_2_23		MXS_IOMUX_PAD_NAKED(2, 23, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CASN__GPIO_2_24		MXS_IOMUX_PAD_NAKED(2, 24, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE0N__GPIO_2_25		MXS_IOMUX_PAD_NAKED(2, 25, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CE1N__GPIO_2_26		MXS_IOMUX_PAD_NAKED(2, 26, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE1N__GPIO_2_27		MXS_IOMUX_PAD_NAKED(2, 27, PAD_MUXSEL_GPIO)
+#define MX23_PAD_GPMI_CE0N__GPIO_2_28		MXS_IOMUX_PAD_NAKED(2, 28, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_CKE__GPIO_2_29		MXS_IOMUX_PAD_NAKED(2, 29, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_RASN__GPIO_2_30		MXS_IOMUX_PAD_NAKED(2, 30, PAD_MUXSEL_GPIO)
+#define MX23_PAD_EMI_WEN__GPIO_2_31		MXS_IOMUX_PAD_NAKED(2, 31, PAD_MUXSEL_GPIO)
 
 #endif /* __MACH_IOMUX_MX23_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mmc.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mmc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * Copyright 2011 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 __MACH_MXS_MMC_H__
+#define __MACH_MXS_MMC_H__
+
+struct mxs_mmc_platform_data {
+	int wp_gpio;	/* write protect pin */
+	unsigned int flags;
+#define SLOTF_4_BIT_CAPABLE	(1 << 0)
+#define SLOTF_8_BIT_CAPABLE	(1 << 1)
+};
+#endif /* __MACH_MXS_MMC_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mx23.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mx23.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mx23.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mx23.h	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 #define MX23_INT_USB_WAKEUP		12
 #define MX23_INT_GPMI_DMA		13
 #define MX23_INT_SSP1_DMA		14
-#define MX23_INT_SSP_ERROR		15
+#define MX23_INT_SSP1_ERROR		15
 #define MX23_INT_GPIO0			16
 #define MX23_INT_GPIO1			17
 #define MX23_INT_GPIO2			18
@@ -101,9 +101,9 @@
 #define MX23_INT_SSP2_DMA		20
 #define MX23_INT_ECC8_IRQ		21
 #define MX23_INT_RTC_ALARM		22
-#define MX23_INT_UARTAPP_TX_DMA		23
-#define MX23_INT_UARTAPP_INTERNAL	24
-#define MX23_INT_UARTAPP_RX_DMA		25
+#define MX23_INT_AUART1_TX_DMA		23
+#define MX23_INT_AUART1			24
+#define MX23_INT_AUART1_RX_DMA		25
 #define MX23_INT_I2C_DMA		26
 #define MX23_INT_I2C_ERROR		27
 #define MX23_INT_TIMER0			28
@@ -135,11 +135,35 @@
 #define MX23_INT_DCP			54
 #define MX23_INT_BCH			56
 #define MX23_INT_PXP			57
-#define MX23_INT_UARTAPP2_TX_DMA	58
-#define MX23_INT_UARTAPP2_INTERNAL	59
-#define MX23_INT_UARTAPP2_RX_DMA	60
+#define MX23_INT_AUART2_TX_DMA		58
+#define MX23_INT_AUART2			59
+#define MX23_INT_AUART2_RX_DMA		60
 #define MX23_INT_VDAC_DETECT		61
 #define MX23_INT_VDD5V_DROOP		64
 #define MX23_INT_DCDC4P2_BO		65
 
+/*
+ * APBH DMA
+ */
+#define MX23_DMA_SSP1			1
+#define MX23_DMA_SSP2			2
+#define MX23_DMA_GPMI0			4
+#define MX23_DMA_GPMI1			5
+#define MX23_DMA_GPMI2			6
+#define MX23_DMA_GPMI3			7
+
+/*
+ * APBX DMA
+ */
+#define MX23_DMA_ADC			0
+#define MX23_DMA_DAC			1
+#define MX23_DMA_SPDIF			2
+#define MX23_DMA_I2C			3
+#define MX23_DMA_SAIF0			4
+#define MX23_DMA_UART0_RX		6
+#define MX23_DMA_UART0_TX		7
+#define MX23_DMA_UART1_RX		8
+#define MX23_DMA_UART1_TX		9
+#define MX23_DMA_SAIF1			10
+
 #endif /* __MACH_MX23_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mx28.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mx28.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mx28.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mx28.h	2011-05-19 00:06:34.000000000 -0400
@@ -163,10 +163,10 @@
 #define MX28_INT_USB0			93
 #define MX28_INT_USB1_WAKEUP		94
 #define MX28_INT_USB0_WAKEUP		95
-#define MX28_INT_SSP0			96
-#define MX28_INT_SSP1			97
-#define MX28_INT_SSP2			98
-#define MX28_INT_SSP3			99
+#define MX28_INT_SSP0_ERROR		96
+#define MX28_INT_SSP1_ERROR		97
+#define MX28_INT_SSP2_ERROR		98
+#define MX28_INT_SSP3_ERROR		99
 #define MX28_INT_ENET_SWI		100
 #define MX28_INT_ENET_MAC0		101
 #define MX28_INT_ENET_MAC1		102
@@ -185,4 +185,41 @@
 #define MX28_INT_GPIO1			126
 #define MX28_INT_GPIO0			127
 
+/*
+ * APBH DMA
+ */
+#define MX28_DMA_SSP0			0
+#define MX28_DMA_SSP1			1
+#define MX28_DMA_SSP2			2
+#define MX28_DMA_SSP3			3
+#define MX28_DMA_GPMI0			4
+#define MX28_DMA_GPMI1			5
+#define MX28_DMA_GPMI2			6
+#define MX28_DMA_GPMI3			7
+#define MX28_DMA_GPMI4			8
+#define MX28_DMA_GPMI5			9
+#define MX28_DMA_GPMI6			10
+#define MX28_DMA_GPMI7			11
+#define MX28_DMA_HSADC			12
+#define MX28_DMA_LCDIF			13
+
+/*
+ * APBX DMA
+ */
+#define MX28_DMA_AUART4_RX		0
+#define MX28_DMA_AUART4_TX		1
+#define MX28_DMA_SPDIF_TX		2
+#define MX28_DMA_SAIF0			4
+#define MX28_DMA_SAIF1			5
+#define MX28_DMA_I2C0			6
+#define MX28_DMA_I2C1			7
+#define MX28_DMA_AUART0_RX		8
+#define MX28_DMA_AUART0_TX		9
+#define MX28_DMA_AUART1_RX		10
+#define MX28_DMA_AUART1_TX		11
+#define MX28_DMA_AUART2_RX		12
+#define MX28_DMA_AUART2_TX		13
+#define MX28_DMA_AUART3_RX		14
+#define MX28_DMA_AUART3_TX		15
+
 #endif /* __MACH_MX28_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mxsfb.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mxsfb.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mxsfb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mxsfb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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_FB_H
+#define __MACH_FB_H
+
+#include <linux/fb.h>
+
+#define STMLCDIF_8BIT 1	/** pixel data bus to the display is of 8 bit width */
+#define STMLCDIF_16BIT 0 /** pixel data bus to the display is of 16 bit width */
+#define STMLCDIF_18BIT 2 /** pixel data bus to the display is of 18 bit width */
+#define STMLCDIF_24BIT 3 /** pixel data bus to the display is of 24 bit width */
+
+#define FB_SYNC_DATA_ENABLE_HIGH_ACT	(1 << 6)
+#define FB_SYNC_DOTCLK_FAILING_ACT	(1 << 7) /* failing/negtive edge sampling */
+
+struct mxsfb_platform_data {
+	struct fb_videomode *mode_list;
+	unsigned mode_count;
+
+	unsigned default_bpp;
+
+	unsigned dotclk_delay;	/* refer manual HW_LCDIF_VDCTRL4 register */
+	unsigned ld_intf_width;	/* refer STMLCDIF_* macros */
+
+	unsigned fb_size;	/* Size of the video memory. If zero a
+				 * default will be used
+				 */
+	unsigned long fb_phys;	/* physical address for the video memory. If
+				 * zero the framebuffer memory will be dynamically
+				 * allocated. If specified,fb_size must also be specified.
+				 * fb_phys must be unused by Linux.
+				 */
+};
+
+#endif /* __MACH_FB_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mxs.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mxs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/mxs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/mxs.h	2011-05-19 00:06:34.000000000 -0400
@@ -28,8 +28,13 @@
 /*
  * MXS CPU types
  */
-#define cpu_is_mx23()		(machine_is_mx23evk())
-#define cpu_is_mx28()		(machine_is_mx28evk())
+#define cpu_is_mx23()		(					\
+		machine_is_mx23evk() ||					\
+		0)
+#define cpu_is_mx28()		(					\
+		machine_is_mx28evk() ||					\
+		machine_is_tx28() ||					\
+		0)
 
 /*
  * IO addresses common to MXS-based
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -63,6 +63,7 @@
 		mxs_duart_base = MX23_DUART_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX28EVK:
+	case MACH_TYPE_TX28:
 		mxs_duart_base = MX28_DUART_BASE_ADDR;
 		break;
 	default:
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-mxs/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -2,13 +2,18 @@
 
 source "arch/arm/mach-mxs/devices/Kconfig"
 
+config MXS_OCOTP
+	bool
+
 config SOC_IMX23
 	bool
 	select CPU_ARM926T
+	select HAVE_PWM
 
 config SOC_IMX28
 	bool
 	select CPU_ARM926T
+	select HAVE_PWM
 
 comment "MXS platforms:"
 
@@ -16,6 +21,9 @@
 	bool "Support MX23EVK Platform"
 	select SOC_IMX23
 	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_MXSFB
 	default y
 	help
 	  Include support for MX23EVK platform. This includes specific
@@ -25,10 +33,28 @@
 	bool "Support MX28EVK Platform"
 	select SOC_IMX28
 	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
 	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_FLEXCAN
+	select MXS_HAVE_PLATFORM_MXS_MMC
+	select MXS_HAVE_PLATFORM_MXSFB
+	select MXS_OCOTP
 	default y
 	help
 	  Include support for MX28EVK platform. This includes specific
 	  configurations for the board and its peripherals.
 
+config MODULE_TX28
+	bool
+	select SOC_IMX28
+	select MXS_HAVE_AMBA_DUART
+	select MXS_HAVE_PLATFORM_AUART
+	select MXS_HAVE_PLATFORM_FEC
+	select MXS_HAVE_PLATFORM_MXS_I2C
+	select MXS_HAVE_PLATFORM_MXS_PWM
+
+config MACH_TX28
+	bool "Ka-Ro TX28 module"
+	select MODULE_TX28
+
 endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/mach-mx23evk.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/mach-mx23evk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/mach-mx23evk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/mach-mx23evk.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,17 +26,147 @@
 
 #include "devices-mx23.h"
 
+#define MX23EVK_LCD_ENABLE	MXS_GPIO_NR(1, 18)
+#define MX23EVK_BL_ENABLE	MXS_GPIO_NR(1, 28)
+#define MX23EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(1, 30)
+#define MX23EVK_MMC0_SLOT_POWER		MXS_GPIO_NR(1, 29)
+
 static const iomux_cfg_t mx23evk_pads[] __initconst = {
 	/* duart */
-	MX23_PAD_PWM0__DUART_RX | MXS_PAD_4MA,
-	MX23_PAD_PWM1__DUART_TX | MXS_PAD_4MA,
+	MX23_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
+	MX23_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
+
+	/* auart */
+	MX23_PAD_AUART1_RX__AUART1_RX | MXS_PAD_CTRL,
+	MX23_PAD_AUART1_TX__AUART1_TX | MXS_PAD_CTRL,
+	MX23_PAD_AUART1_CTS__AUART1_CTS | MXS_PAD_CTRL,
+	MX23_PAD_AUART1_RTS__AUART1_RTS | MXS_PAD_CTRL,
+
+	/* mxsfb (lcdif) */
+	MX23_PAD_LCD_D00__LCD_D00 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D01__LCD_D01 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D02__LCD_D02 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D03__LCD_D03 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D04__LCD_D04 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D05__LCD_D05 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D06__LCD_D06 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D07__LCD_D07 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D08__LCD_D08 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D09__LCD_D09 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D08__LCD_D18 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D09__LCD_D19 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D10__LCD_D20 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D11__LCD_D21 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D12__LCD_D22 | MXS_PAD_CTRL,
+	MX23_PAD_GPMI_D13__LCD_D23 | MXS_PAD_CTRL,
+	MX23_PAD_LCD_VSYNC__LCD_VSYNC | MXS_PAD_CTRL,
+	MX23_PAD_LCD_HSYNC__LCD_HSYNC | MXS_PAD_CTRL,
+	MX23_PAD_LCD_DOTCK__LCD_DOTCK | MXS_PAD_CTRL,
+	MX23_PAD_LCD_ENABLE__LCD_ENABLE | MXS_PAD_CTRL,
+	/* LCD panel enable */
+	MX23_PAD_LCD_RESET__GPIO_1_18 | MXS_PAD_CTRL,
+	/* backlight control */
+	MX23_PAD_PWM2__GPIO_1_28 | MXS_PAD_CTRL,
+
+	/* mmc */
+	MX23_PAD_SSP1_DATA0__SSP1_DATA0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DATA1__SSP1_DATA1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DATA2__SSP1_DATA2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DATA3__SSP1_DATA3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D08__SSP1_DATA4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D09__SSP1_DATA5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D10__SSP1_DATA6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_GPMI_D11__SSP1_DATA7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_CMD__SSP1_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX23_PAD_SSP1_DETECT__SSP1_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX23_PAD_SSP1_SCK__SSP1_SCK |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX23_PAD_PWM4__GPIO_1_30 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX23_PAD_PWM3__GPIO_1_29 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+};
+
+/* mxsfb (lcdif) */
+static struct fb_videomode mx23evk_video_modes[] = {
+	{
+		.name		= "Samsung-LMS430HF02",
+		.refresh	= 60,
+		.xres		= 480,
+		.yres		= 272,
+		.pixclock	= 108096, /* picosecond (9.2 MHz) */
+		.left_margin	= 15,
+		.right_margin	= 8,
+		.upper_margin	= 12,
+		.lower_margin	= 4,
+		.hsync_len	= 1,
+		.vsync_len	= 1,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
+				  FB_SYNC_DOTCLK_FAILING_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data mx23evk_mxsfb_pdata __initconst = {
+	.mode_list	= mx23evk_video_modes,
+	.mode_count	= ARRAY_SIZE(mx23evk_video_modes),
+	.default_bpp	= 32,
+	.ld_intf_width	= STMLCDIF_24BIT,
+};
+
+static struct mxs_mmc_platform_data mx23evk_mmc_pdata __initdata = {
+	.wp_gpio = MX23EVK_MMC0_WRITE_PROTECT,
+	.flags = SLOTF_8_BIT_CAPABLE,
 };
 
 static void __init mx23evk_init(void)
 {
+	int ret;
+
 	mxs_iomux_setup_multiple_pads(mx23evk_pads, ARRAY_SIZE(mx23evk_pads));
 
 	mx23_add_duart();
+	mx23_add_auart0();
+
+	/* power on mmc slot by writing 0 to the gpio */
+	ret = gpio_request_one(MX23EVK_MMC0_SLOT_POWER, GPIOF_DIR_OUT,
+			       "mmc0-slot-power");
+	if (ret)
+		pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
+	mx23_add_mxs_mmc(0, &mx23evk_mmc_pdata);
+
+	ret = gpio_request_one(MX23EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	if (ret)
+		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+	else
+		gpio_set_value(MX23EVK_LCD_ENABLE, 1);
+
+	ret = gpio_request_one(MX23EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
+	if (ret)
+		pr_warn("failed to request gpio bl-enable: %d\n", ret);
+	else
+		gpio_set_value(MX23EVK_BL_ENABLE, 1);
+
+	mx23_add_mxsfb(&mx23evk_mxsfb_pdata);
 }
 
 static void __init mx23evk_timer_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/mach-mx28evk.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/mach-mx28evk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/mach-mx28evk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/mach-mx28evk.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,53 +28,156 @@
 #include "devices-mx28.h"
 #include "gpio.h"
 
+#define MX28EVK_FLEXCAN_SWITCH	MXS_GPIO_NR(2, 13)
 #define MX28EVK_FEC_PHY_POWER	MXS_GPIO_NR(2, 15)
+#define MX28EVK_BL_ENABLE	MXS_GPIO_NR(3, 18)
+#define MX28EVK_LCD_ENABLE	MXS_GPIO_NR(3, 30)
 #define MX28EVK_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
 
+#define MX28EVK_MMC0_WRITE_PROTECT	MXS_GPIO_NR(2, 12)
+#define MX28EVK_MMC1_WRITE_PROTECT	MXS_GPIO_NR(0, 28)
+#define MX28EVK_MMC0_SLOT_POWER		MXS_GPIO_NR(3, 28)
+#define MX28EVK_MMC1_SLOT_POWER		MXS_GPIO_NR(3, 29)
+
 static const iomux_cfg_t mx28evk_pads[] __initconst = {
 	/* duart */
-	MX28_PAD_PWM0__DUART_RX |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	MX28_PAD_PWM1__DUART_TX |
-		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_PWM0__DUART_RX | MXS_PAD_CTRL,
+	MX28_PAD_PWM1__DUART_TX | MXS_PAD_CTRL,
+
+	/* auart0 */
+	MX28_PAD_AUART0_RX__AUART0_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_TX__AUART0_TX | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_CTS__AUART0_CTS | MXS_PAD_CTRL,
+	MX28_PAD_AUART0_RTS__AUART0_RTS | MXS_PAD_CTRL,
+	/* auart3 */
+	MX28_PAD_AUART3_RX__AUART3_RX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_TX__AUART3_TX | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_CTS__AUART3_CTS | MXS_PAD_CTRL,
+	MX28_PAD_AUART3_RTS__AUART3_RTS | MXS_PAD_CTRL,
 
+#define MXS_PAD_FEC	(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP)
 	/* fec0 */
-	MX28_PAD_ENET0_MDC__ENET0_MDC |
+	MX28_PAD_ENET0_MDC__ENET0_MDC | MXS_PAD_FEC,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | MXS_PAD_FEC,
+	/* fec1 */
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_COL__ENET1_TX_EN | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0 | MXS_PAD_FEC,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1 | MXS_PAD_FEC,
+	/* phy power line */
+	MX28_PAD_SSP1_DATA3__GPIO_2_15 | MXS_PAD_CTRL,
+	/* phy reset line */
+	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 | MXS_PAD_CTRL,
+
+	/* flexcan0 */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+	/* flexcan1 */
+	MX28_PAD_GPMI_CE2N__CAN1_TX,
+	MX28_PAD_GPMI_CE3N__CAN1_RX,
+	/* transceiver power control */
+	MX28_PAD_SSP1_CMD__GPIO_2_13,
+
+	/* mxsfb (lcdif) */
+	MX28_PAD_LCD_D00__LCD_D0 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D01__LCD_D1 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D02__LCD_D2 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D03__LCD_D3 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D04__LCD_D4 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D05__LCD_D5 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D06__LCD_D6 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D07__LCD_D7 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D08__LCD_D8 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D09__LCD_D9 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D10__LCD_D10 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D11__LCD_D11 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D12__LCD_D12 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D13__LCD_D13 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D14__LCD_D14 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D15__LCD_D15 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D16__LCD_D16 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D17__LCD_D17 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D18__LCD_D18 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D19__LCD_D19 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D20__LCD_D20 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D21__LCD_D21 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D22__LCD_D22 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_D23__LCD_D23 | MXS_PAD_CTRL,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | MXS_PAD_CTRL,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | MXS_PAD_CTRL,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | MXS_PAD_CTRL,
+	MX28_PAD_LCD_CS__LCD_ENABLE | MXS_PAD_CTRL,
+	/* LCD panel enable */
+	MX28_PAD_LCD_RESET__GPIO_3_30 | MXS_PAD_CTRL,
+	/* backlight control */
+	MX28_PAD_PWM2__GPIO_3_18 | MXS_PAD_CTRL,
+	/* mmc0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_MDIO__ENET0_MDIO |
+	MX28_PAD_SSP0_DATA1__SSP0_D1 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN |
+	MX28_PAD_SSP0_DATA2__SSP0_D2 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD0__ENET0_RXD0 |
+	MX28_PAD_SSP0_DATA3__SSP0_D3 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD1__ENET0_RXD1 |
+	MX28_PAD_SSP0_DATA4__SSP0_D4 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN |
+	MX28_PAD_SSP0_DATA5__SSP0_D5 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD0__ENET0_TXD0 |
+	MX28_PAD_SSP0_DATA6__SSP0_D6 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD1__ENET0_TXD1 |
+	MX28_PAD_SSP0_DATA7__SSP0_D7 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET_CLK__CLKCTRL_ENET |
+	MX28_PAD_SSP0_CMD__SSP0_CMD |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	/* fec1 */
-	MX28_PAD_ENET0_CRS__ENET1_RX_EN |
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX28_PAD_SSP1_SCK__GPIO_2_12 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* slot power enable */
+	MX28_PAD_PWM3__GPIO_3_28 |
+		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+
+	/* mmc1 */
+	MX28_PAD_GPMI_D00__SSP1_D0 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD2__ENET1_RXD0 |
+	MX28_PAD_GPMI_D01__SSP1_D1 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_RXD3__ENET1_RXD1 |
+	MX28_PAD_GPMI_D02__SSP1_D2 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_COL__ENET1_TX_EN |
+	MX28_PAD_GPMI_D03__SSP1_D3 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD2__ENET1_TXD0 |
+	MX28_PAD_GPMI_D04__SSP1_D4 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	MX28_PAD_ENET0_TXD3__ENET1_TXD1 |
+	MX28_PAD_GPMI_D05__SSP1_D5 |
 		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
-	/* phy power line */
-	MX28_PAD_SSP1_DATA3__GPIO_2_15 |
+	MX28_PAD_GPMI_D06__SSP1_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_D07__SSP1_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY1__SSP1_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_GPMI_RDY0__SSP1_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_GPMI_WRN__SSP1_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	/* write protect */
+	MX28_PAD_GPMI_RESETN__GPIO_0_28 |
 		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
-	/* phy reset line */
-	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
+	/* slot power enable */
+	MX28_PAD_PWM4__GPIO_3_29 |
 		(MXS_PAD_4MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
 };
 
@@ -119,7 +222,7 @@
 	gpio_set_value(MX28EVK_FEC_PHY_RESET, 1);
 }
 
-static struct fec_platform_data mx28_fec_pdata[] = {
+static struct fec_platform_data mx28_fec_pdata[] __initdata = {
 	{
 		/* fec0 */
 		.phy = PHY_INTERFACE_MODE_RMII,
@@ -129,15 +232,160 @@
 	},
 };
 
+static int __init mx28evk_fec_get_mac(void)
+{
+	int i;
+	u32 val;
+	const u32 *ocotp = mxs_get_ocotp();
+
+	if (!ocotp)
+		goto error;
+
+	/*
+	 * OCOTP only stores the last 4 octets for each mac address,
+	 * so hard-code Freescale OUI (00:04:9f) here.
+	 */
+	for (i = 0; i < 2; i++) {
+		val = ocotp[i * 4];
+		mx28_fec_pdata[i].mac[0] = 0x00;
+		mx28_fec_pdata[i].mac[1] = 0x04;
+		mx28_fec_pdata[i].mac[2] = 0x9f;
+		mx28_fec_pdata[i].mac[3] = (val >> 16) & 0xff;
+		mx28_fec_pdata[i].mac[4] = (val >> 8) & 0xff;
+		mx28_fec_pdata[i].mac[5] = (val >> 0) & 0xff;
+	}
+
+	return 0;
+
+error:
+	pr_err("%s: timeout when reading fec mac from OCOTP\n", __func__);
+	return -ETIMEDOUT;
+}
+
+/*
+ * MX28EVK_FLEXCAN_SWITCH is shared between both flexcan controllers
+ */
+static int flexcan0_en, flexcan1_en;
+
+static void mx28evk_flexcan_switch(void)
+{
+	if (flexcan0_en || flexcan1_en)
+		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 1);
+	else
+		gpio_set_value(MX28EVK_FLEXCAN_SWITCH, 0);
+}
+
+static void mx28evk_flexcan0_switch(int enable)
+{
+	flexcan0_en = enable;
+	mx28evk_flexcan_switch();
+}
+
+static void mx28evk_flexcan1_switch(int enable)
+{
+	flexcan1_en = enable;
+	mx28evk_flexcan_switch();
+}
+
+static const struct flexcan_platform_data
+		mx28evk_flexcan_pdata[] __initconst = {
+	{
+		.transceiver_switch = mx28evk_flexcan0_switch,
+	}, {
+		.transceiver_switch = mx28evk_flexcan1_switch,
+	}
+};
+
+/* mxsfb (lcdif) */
+static struct fb_videomode mx28evk_video_modes[] = {
+	{
+		.name		= "Seiko-43WVF1G",
+		.refresh	= 60,
+		.xres		= 800,
+		.yres		= 480,
+		.pixclock	= 29851, /* picosecond (33.5 MHz) */
+		.left_margin	= 89,
+		.right_margin	= 164,
+		.upper_margin	= 23,
+		.lower_margin	= 10,
+		.hsync_len	= 10,
+		.vsync_len	= 10,
+		.sync		= FB_SYNC_DATA_ENABLE_HIGH_ACT |
+				  FB_SYNC_DOTCLK_FAILING_ACT,
+	},
+};
+
+static const struct mxsfb_platform_data mx28evk_mxsfb_pdata __initconst = {
+	.mode_list	= mx28evk_video_modes,
+	.mode_count	= ARRAY_SIZE(mx28evk_video_modes),
+	.default_bpp	= 32,
+	.ld_intf_width	= STMLCDIF_24BIT,
+};
+
+static struct mxs_mmc_platform_data mx28evk_mmc_pdata[] __initdata = {
+	{
+		/* mmc0 */
+		.wp_gpio = MX28EVK_MMC0_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	}, {
+		/* mmc1 */
+		.wp_gpio = MX28EVK_MMC1_WRITE_PROTECT,
+		.flags = SLOTF_8_BIT_CAPABLE,
+	},
+};
+
 static void __init mx28evk_init(void)
 {
+	int ret;
+
 	mxs_iomux_setup_multiple_pads(mx28evk_pads, ARRAY_SIZE(mx28evk_pads));
 
 	mx28_add_duart();
+	mx28_add_auart0();
+	mx28_add_auart3();
+
+	if (mx28evk_fec_get_mac())
+		pr_warn("%s: failed on fec mac setup\n", __func__);
 
 	mx28evk_fec_reset();
 	mx28_add_fec(0, &mx28_fec_pdata[0]);
 	mx28_add_fec(1, &mx28_fec_pdata[1]);
+
+	ret = gpio_request_one(MX28EVK_FLEXCAN_SWITCH, GPIOF_DIR_OUT,
+				"flexcan-switch");
+	if (ret) {
+		pr_err("failed to request gpio flexcan-switch: %d\n", ret);
+	} else {
+		mx28_add_flexcan(0, &mx28evk_flexcan_pdata[0]);
+		mx28_add_flexcan(1, &mx28evk_flexcan_pdata[1]);
+	}
+
+	ret = gpio_request_one(MX28EVK_LCD_ENABLE, GPIOF_DIR_OUT, "lcd-enable");
+	if (ret)
+		pr_warn("failed to request gpio lcd-enable: %d\n", ret);
+	else
+		gpio_set_value(MX28EVK_LCD_ENABLE, 1);
+
+	ret = gpio_request_one(MX28EVK_BL_ENABLE, GPIOF_DIR_OUT, "bl-enable");
+	if (ret)
+		pr_warn("failed to request gpio bl-enable: %d\n", ret);
+	else
+		gpio_set_value(MX28EVK_BL_ENABLE, 1);
+
+	mx28_add_mxsfb(&mx28evk_mxsfb_pdata);
+
+	/* power on mmc slot by writing 0 to the gpio */
+	ret = gpio_request_one(MX28EVK_MMC0_SLOT_POWER, GPIOF_DIR_OUT,
+			       "mmc0-slot-power");
+	if (ret)
+		pr_warn("failed to request gpio mmc0-slot-power: %d\n", ret);
+	mx28_add_mxs_mmc(0, &mx28evk_mmc_pdata[0]);
+
+	ret = gpio_request_one(MX28EVK_MMC1_SLOT_POWER, GPIOF_DIR_OUT,
+			       "mmc1-slot-power");
+	if (ret)
+		pr_warn("failed to request gpio mmc1-slot-power: %d\n", ret);
+	mx28_add_mxs_mmc(1, &mx28evk_mmc_pdata[1]);
 }
 
 static void __init mx28evk_timer_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/mach-tx28.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/mach-tx28.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/mach-tx28.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/mach-tx28.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,183 @@
+/*
+ * Copyright (C) 2010 <LW@KARO-electronics.de>
+ *
+ * based on: mach-mx28_evk.c
+ * Copyright 2010 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
+ */
+#include <linux/kernel.h>
+#include <linux/gpio.h>
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_gpio.h>
+#include <linux/i2c.h>
+
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+
+#include <mach/common.h>
+#include <mach/iomux-mx28.h>
+
+#include "devices-mx28.h"
+#include "module-tx28.h"
+
+#define TX28_STK5_GPIO_LED		MXS_GPIO_NR(4, 10)
+
+static const iomux_cfg_t tx28_stk5v3_pads[] __initconst = {
+	/* LED */
+	MX28_PAD_ENET0_RXD3__GPIO_4_10 |
+		MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_NOPULL,
+
+	/* framebuffer */
+#define LCD_MODE (MXS_PAD_3V3 | MXS_PAD_4MA)
+	MX28_PAD_LCD_D00__LCD_D0 | LCD_MODE,
+	MX28_PAD_LCD_D01__LCD_D1 | LCD_MODE,
+	MX28_PAD_LCD_D02__LCD_D2 | LCD_MODE,
+	MX28_PAD_LCD_D03__LCD_D3 | LCD_MODE,
+	MX28_PAD_LCD_D04__LCD_D4 | LCD_MODE,
+	MX28_PAD_LCD_D05__LCD_D5 | LCD_MODE,
+	MX28_PAD_LCD_D06__LCD_D6 | LCD_MODE,
+	MX28_PAD_LCD_D07__LCD_D7 | LCD_MODE,
+	MX28_PAD_LCD_D08__LCD_D8 | LCD_MODE,
+	MX28_PAD_LCD_D09__LCD_D9 | LCD_MODE,
+	MX28_PAD_LCD_D10__LCD_D10 | LCD_MODE,
+	MX28_PAD_LCD_D11__LCD_D11 | LCD_MODE,
+	MX28_PAD_LCD_D12__LCD_D12 | LCD_MODE,
+	MX28_PAD_LCD_D13__LCD_D13 | LCD_MODE,
+	MX28_PAD_LCD_D14__LCD_D14 | LCD_MODE,
+	MX28_PAD_LCD_D15__LCD_D15 | LCD_MODE,
+	MX28_PAD_LCD_D16__LCD_D16 | LCD_MODE,
+	MX28_PAD_LCD_D17__LCD_D17 | LCD_MODE,
+	MX28_PAD_LCD_D18__LCD_D18 | LCD_MODE,
+	MX28_PAD_LCD_D19__LCD_D19 | LCD_MODE,
+	MX28_PAD_LCD_D20__LCD_D20 | LCD_MODE,
+	MX28_PAD_LCD_D21__LCD_D21 | LCD_MODE,
+	MX28_PAD_LCD_D22__LCD_D22 | LCD_MODE,
+	MX28_PAD_LCD_D23__LCD_D23 | LCD_MODE,
+	MX28_PAD_LCD_RD_E__LCD_VSYNC | LCD_MODE,
+	MX28_PAD_LCD_WR_RWN__LCD_HSYNC | LCD_MODE,
+	MX28_PAD_LCD_RS__LCD_DOTCLK | LCD_MODE,
+	MX28_PAD_LCD_CS__LCD_CS | LCD_MODE,
+	MX28_PAD_LCD_VSYNC__LCD_VSYNC | LCD_MODE,
+	MX28_PAD_LCD_HSYNC__LCD_HSYNC | LCD_MODE,
+	MX28_PAD_LCD_DOTCLK__LCD_DOTCLK | LCD_MODE,
+	MX28_PAD_LCD_ENABLE__GPIO_1_31 | LCD_MODE,
+	MX28_PAD_LCD_RESET__GPIO_3_30 | LCD_MODE,
+	MX28_PAD_PWM0__PWM_0 | LCD_MODE,
+
+	/* UART1 */
+	MX28_PAD_AUART0_CTS__DUART_RX,
+	MX28_PAD_AUART0_RTS__DUART_TX,
+	MX28_PAD_AUART0_TX__DUART_RTS,
+	MX28_PAD_AUART0_RX__DUART_CTS,
+
+	/* UART2 */
+	MX28_PAD_AUART1_RX__AUART1_RX,
+	MX28_PAD_AUART1_TX__AUART1_TX,
+	MX28_PAD_AUART1_RTS__AUART1_RTS,
+	MX28_PAD_AUART1_CTS__AUART1_CTS,
+
+	/* CAN */
+	MX28_PAD_GPMI_RDY2__CAN0_TX,
+	MX28_PAD_GPMI_RDY3__CAN0_RX,
+
+	/* I2C */
+	MX28_PAD_I2C0_SCL__I2C0_SCL,
+	MX28_PAD_I2C0_SDA__I2C0_SDA,
+
+	/* TSC2007 */
+	MX28_PAD_SAIF0_MCLK__GPIO_3_20 | MXS_PAD_3V3 | MXS_PAD_4MA | MXS_PAD_PULLUP,
+
+	/* MMC0 */
+	MX28_PAD_SSP0_DATA0__SSP0_D0 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA1__SSP0_D1 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA2__SSP0_D2 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA3__SSP0_D3 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA4__SSP0_D4 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA5__SSP0_D5 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA6__SSP0_D6 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DATA7__SSP0_D7 |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_CMD__SSP0_CMD |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_PULLUP),
+	MX28_PAD_SSP0_DETECT__SSP0_CARD_DETECT |
+		(MXS_PAD_8MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+	MX28_PAD_SSP0_SCK__SSP0_SCK |
+		(MXS_PAD_12MA | MXS_PAD_3V3 | MXS_PAD_NOPULL),
+};
+
+static struct gpio_led tx28_stk5v3_leds[] = {
+	{
+		.name = "GPIO-LED",
+		.default_trigger = "heartbeat",
+		.gpio = TX28_STK5_GPIO_LED,
+	},
+};
+
+static const struct gpio_led_platform_data tx28_stk5v3_led_data __initconst = {
+	.leds = tx28_stk5v3_leds,
+	.num_leds = ARRAY_SIZE(tx28_stk5v3_leds),
+};
+
+static struct spi_board_info tx28_spi_board_info[] = {
+	{
+		.modalias = "spidev",
+		.max_speed_hz = 20000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.controller_data = (void *)SPI_GPIO_NO_CHIPSELECT,
+		.mode = SPI_MODE_0,
+	},
+};
+
+static struct i2c_board_info tx28_stk5v3_i2c_boardinfo[] __initdata = {
+	{
+		I2C_BOARD_INFO("ds1339", 0x68),
+	},
+};
+
+static void __init tx28_stk5v3_init(void)
+{
+	mxs_iomux_setup_multiple_pads(tx28_stk5v3_pads,
+			ARRAY_SIZE(tx28_stk5v3_pads));
+
+	mx28_add_duart(); /* UART1 */
+	mx28_add_auart(1); /* UART2 */
+
+	tx28_add_fec0();
+	/* spi via ssp will be added when available */
+	spi_register_board_info(tx28_spi_board_info,
+			ARRAY_SIZE(tx28_spi_board_info));
+	mxs_add_platform_device("leds-gpio", 0, NULL, 0,
+			&tx28_stk5v3_led_data, sizeof(tx28_stk5v3_led_data));
+	mx28_add_mxs_i2c(0);
+	i2c_register_board_info(0, tx28_stk5v3_i2c_boardinfo,
+			ARRAY_SIZE(tx28_stk5v3_i2c_boardinfo));
+}
+
+static void __init tx28_timer_init(void)
+{
+	mx28_clocks_init();
+}
+
+static struct sys_timer tx28_timer = {
+	.init = tx28_timer_init,
+};
+
+MACHINE_START(TX28, "Ka-Ro electronics TX28 module")
+	.map_io = mx28_map_io,
+	.init_irq = mx28_init_irq,
+	.init_machine = tx28_stk5v3_init,
+	.timer = &tx28_timer,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-mxs/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,10 +1,15 @@
 # Common support
 obj-y := clock.o devices.o gpio.o icoll.o iomux.o system.o timer.o
 
+obj-$(CONFIG_MXS_OCOTP) += ocotp.o
+obj-$(CONFIG_PM) += pm.o
+
 obj-$(CONFIG_SOC_IMX23) += clock-mx23.o mm-mx23.o
 obj-$(CONFIG_SOC_IMX28) += clock-mx28.o mm-mx28.o
 
 obj-$(CONFIG_MACH_MX23EVK) += mach-mx23evk.o
 obj-$(CONFIG_MACH_MX28EVK) += mach-mx28evk.o
+obj-$(CONFIG_MODULE_TX28) += module-tx28.o
+obj-$(CONFIG_MACH_TX28)    += mach-tx28.o
 
 obj-y += devices/
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/module-tx28.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/module-tx28.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/module-tx28.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/module-tx28.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) 2010 <LW@KARO-electronics.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/delay.h>
+#include <linux/fec.h>
+#include <linux/gpio.h>
+
+#include <mach/iomux-mx28.h>
+#include "../devices-mx28.h"
+
+#include "module-tx28.h"
+
+#define TX28_FEC_PHY_POWER	MXS_GPIO_NR(3, 29)
+#define TX28_FEC_PHY_RESET	MXS_GPIO_NR(4, 13)
+
+static const iomux_cfg_t tx28_fec_gpio_pads[] __initconst = {
+	/* PHY POWER */
+	MX28_PAD_PWM4__GPIO_3_29 |
+		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
+	/* PHY RESET */
+	MX28_PAD_ENET0_RX_CLK__GPIO_4_13 |
+		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
+	/* Mode strap pins 0-2 */
+	MX28_PAD_ENET0_RXD0__GPIO_4_3 |
+		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
+	MX28_PAD_ENET0_RXD1__GPIO_4_4 |
+		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
+	MX28_PAD_ENET0_RX_EN__GPIO_4_2 |
+		MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3,
+	/* nINT */
+	MX28_PAD_ENET0_TX_CLK__GPIO_4_5 |
+		MXS_PAD_4MA | MXS_PAD_NOPULL | MXS_PAD_3V3,
+
+	MX28_PAD_ENET0_MDC__GPIO_4_0,
+	MX28_PAD_ENET0_MDIO__GPIO_4_1,
+	MX28_PAD_ENET0_TX_EN__GPIO_4_6,
+	MX28_PAD_ENET0_TXD0__GPIO_4_7,
+	MX28_PAD_ENET0_TXD1__GPIO_4_8,
+	MX28_PAD_ENET_CLK__GPIO_4_16,
+};
+
+#define FEC_MODE (MXS_PAD_8MA | MXS_PAD_PULLUP | MXS_PAD_3V3)
+static const iomux_cfg_t tx28_fec0_pads[] __initconst = {
+	MX28_PAD_ENET0_MDC__ENET0_MDC | FEC_MODE,
+	MX28_PAD_ENET0_MDIO__ENET0_MDIO | FEC_MODE,
+	MX28_PAD_ENET0_RX_EN__ENET0_RX_EN | FEC_MODE,
+	MX28_PAD_ENET0_RXD0__ENET0_RXD0 | FEC_MODE,
+	MX28_PAD_ENET0_RXD1__ENET0_RXD1 | FEC_MODE,
+	MX28_PAD_ENET0_TX_EN__ENET0_TX_EN | FEC_MODE,
+	MX28_PAD_ENET0_TXD0__ENET0_TXD0 | FEC_MODE,
+	MX28_PAD_ENET0_TXD1__ENET0_TXD1 | FEC_MODE,
+	MX28_PAD_ENET_CLK__CLKCTRL_ENET | FEC_MODE,
+};
+
+static const iomux_cfg_t tx28_fec1_pads[] __initconst = {
+	MX28_PAD_ENET0_RXD2__ENET1_RXD0,
+	MX28_PAD_ENET0_RXD3__ENET1_RXD1,
+	MX28_PAD_ENET0_TXD2__ENET1_TXD0,
+	MX28_PAD_ENET0_TXD3__ENET1_TXD1,
+	MX28_PAD_ENET0_COL__ENET1_TX_EN,
+	MX28_PAD_ENET0_CRS__ENET1_RX_EN,
+};
+
+static struct fec_platform_data tx28_fec0_data = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+static struct fec_platform_data tx28_fec1_data = {
+	.phy = PHY_INTERFACE_MODE_RMII,
+};
+
+int __init tx28_add_fec0(void)
+{
+	int i, ret;
+
+	pr_debug("%s: Switching FEC PHY power off\n", __func__);
+	ret = mxs_iomux_setup_multiple_pads(tx28_fec_gpio_pads,
+			ARRAY_SIZE(tx28_fec_gpio_pads));
+	for (i = 0; i < ARRAY_SIZE(tx28_fec_gpio_pads); i++) {
+		unsigned int gpio = MXS_GPIO_NR(PAD_BANK(tx28_fec_gpio_pads[i]),
+			PAD_PIN(tx28_fec_gpio_pads[i]));
+
+		ret = gpio_request(gpio, "FEC");
+		if (ret) {
+			pr_err("Failed to request GPIO_%d_%d: %d\n",
+				PAD_BANK(tx28_fec_gpio_pads[i]),
+				PAD_PIN(tx28_fec_gpio_pads[i]), ret);
+			goto free_gpios;
+		}
+		ret = gpio_direction_output(gpio, 0);
+		if (ret) {
+			pr_err("Failed to set direction of GPIO_%d_%d to output: %d\n",
+					gpio / 32 + 1, gpio % 32, ret);
+			goto free_gpios;
+		}
+	}
+
+	/* Power up fec phy */
+	pr_debug("%s: Switching FEC PHY power on\n", __func__);
+	ret = gpio_direction_output(TX28_FEC_PHY_POWER, 1);
+	if (ret) {
+		pr_err("Failed to power on PHY: %d\n", ret);
+		goto free_gpios;
+	}
+	mdelay(26); /* 25ms according to data sheet */
+
+	/* nINT */
+	gpio_direction_input(MXS_GPIO_NR(4, 5));
+	/* Mode strap pins */
+	gpio_direction_output(MXS_GPIO_NR(4, 2), 1);
+	gpio_direction_output(MXS_GPIO_NR(4, 3), 1);
+	gpio_direction_output(MXS_GPIO_NR(4, 4), 1);
+
+	udelay(100); /* minimum assertion time for nRST */
+
+	pr_debug("%s: Deasserting FEC PHY RESET\n", __func__);
+	gpio_set_value(TX28_FEC_PHY_RESET, 1);
+
+	ret = mxs_iomux_setup_multiple_pads(tx28_fec0_pads,
+			ARRAY_SIZE(tx28_fec0_pads));
+	if (ret) {
+		pr_debug("%s: mxs_iomux_setup_multiple_pads() failed with rc: %d\n",
+				__func__, ret);
+		goto free_gpios;
+	}
+	pr_debug("%s: Registering FEC0 device\n", __func__);
+	mx28_add_fec(0, &tx28_fec0_data);
+	return 0;
+
+free_gpios:
+	while (--i >= 0) {
+		unsigned int gpio = MXS_GPIO_NR(PAD_BANK(tx28_fec_gpio_pads[i]),
+			PAD_PIN(tx28_fec_gpio_pads[i]));
+
+		gpio_free(gpio);
+	}
+
+	return ret;
+}
+
+int __init tx28_add_fec1(void)
+{
+	int ret;
+
+	ret = mxs_iomux_setup_multiple_pads(tx28_fec1_pads,
+			ARRAY_SIZE(tx28_fec1_pads));
+	if (ret) {
+		pr_debug("%s: mxs_iomux_setup_multiple_pads() failed with rc: %d\n",
+				__func__, ret);
+		return ret;
+	}
+	pr_debug("%s: Registering FEC1 device\n", __func__);
+	mx28_add_fec(1, &tx28_fec1_data);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/module-tx28.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/module-tx28.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/module-tx28.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/module-tx28.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+/*
+ * Copyright (C) 2010 Pengutronix
+ *   Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.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.
+ */
+int __init tx28_add_fec0(void);
+int __init tx28_add_fec1(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/ocotp.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/ocotp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/ocotp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/ocotp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,90 @@
+/*
+ * Copyright 2010 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.
+ */
+
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+#include <mach/mxs.h>
+
+#define OCOTP_WORD_OFFSET		0x20
+#define OCOTP_WORD_COUNT		0x20
+
+#define BM_OCOTP_CTRL_BUSY		(1 << 8)
+#define BM_OCOTP_CTRL_ERROR		(1 << 9)
+#define BM_OCOTP_CTRL_RD_BANK_OPEN	(1 << 12)
+
+static DEFINE_MUTEX(ocotp_mutex);
+static u32 ocotp_words[OCOTP_WORD_COUNT];
+
+const u32 *mxs_get_ocotp(void)
+{
+	void __iomem *ocotp_base = MXS_IO_ADDRESS(MXS_OCOTP_BASE_ADDR);
+	int timeout = 0x400;
+	size_t i;
+	static int once = 0;
+
+	if (once)
+		return ocotp_words;
+
+	mutex_lock(&ocotp_mutex);
+
+	/*
+	 * clk_enable(hbus_clk) for ocotp can be skipped
+	 * as it must be on when system is running.
+	 */
+
+	/* try to clear ERROR bit */
+	__mxs_clrl(BM_OCOTP_CTRL_ERROR, ocotp_base);
+
+	/* check both BUSY and ERROR cleared */
+	while ((__raw_readl(ocotp_base) &
+		(BM_OCOTP_CTRL_BUSY | BM_OCOTP_CTRL_ERROR)) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		goto error_unlock;
+
+	/* open OCOTP banks for read */
+	__mxs_setl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
+
+	/* approximately wait 32 hclk cycles */
+	udelay(1);
+
+	/* poll BUSY bit becoming cleared */
+	timeout = 0x400;
+	while ((__raw_readl(ocotp_base) & BM_OCOTP_CTRL_BUSY) && --timeout)
+		cpu_relax();
+
+	if (unlikely(!timeout))
+		goto error_unlock;
+
+	for (i = 0; i < OCOTP_WORD_COUNT; i++)
+		ocotp_words[i] = __raw_readl(ocotp_base + OCOTP_WORD_OFFSET +
+						i * 0x10);
+
+	/* close banks for power saving */
+	__mxs_clrl(BM_OCOTP_CTRL_RD_BANK_OPEN, ocotp_base);
+
+	once = 1;
+
+	mutex_unlock(&ocotp_mutex);
+
+	return ocotp_words;
+
+error_unlock:
+	mutex_unlock(&ocotp_mutex);
+	pr_err("%s: timeout in reading OCOTP\n", __func__);
+	return NULL;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/pm.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/suspend.h>
+#include <linux/io.h>
+#include <mach/system.h>
+
+static int mxs_suspend_enter(suspend_state_t state)
+{
+	switch (state) {
+	case PM_SUSPEND_MEM:
+		arch_idle();
+		break;
+
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static struct platform_suspend_ops mxs_suspend_ops = {
+	.enter = mxs_suspend_enter,
+	.valid = suspend_valid_only_mem,
+};
+
+static int __init mxs_pm_init(void)
+{
+	suspend_set_ops(&mxs_suspend_ops);
+	return 0;
+}
+device_initcall(mxs_pm_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/regs-clkctrl-mx23.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/regs-clkctrl-mx23.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/regs-clkctrl-mx23.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/regs-clkctrl-mx23.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,10 +33,6 @@
 #define HW_CLKCTRL_PLLCTRL0_CLR	(0x00000008)
 #define HW_CLKCTRL_PLLCTRL0_TOG	(0x0000000c)
 
-#define BP_CLKCTRL_PLLCTRL0_RSRVD6	30
-#define BM_CLKCTRL_PLLCTRL0_RSRVD6	0xC0000000
-#define BF_CLKCTRL_PLLCTRL0_RSRVD6(v) \
-		(((v) << 30) & BM_CLKCTRL_PLLCTRL0_RSRVD6)
 #define BP_CLKCTRL_PLLCTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLLCTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLLCTRL0_LFR_SEL(v)  \
@@ -45,10 +41,6 @@
 #define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLLCTRL0_LFR_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLLCTRL0_LFR_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLLCTRL0_RSRVD5	26
-#define BM_CLKCTRL_PLLCTRL0_RSRVD5	0x0C000000
-#define BF_CLKCTRL_PLLCTRL0_RSRVD5(v)  \
-		(((v) << 26) & BM_CLKCTRL_PLLCTRL0_RSRVD5)
 #define BP_CLKCTRL_PLLCTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLLCTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLLCTRL0_CP_SEL(v)  \
@@ -57,10 +49,6 @@
 #define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLLCTRL0_CP_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLLCTRL0_CP_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLLCTRL0_RSRVD4	22
-#define BM_CLKCTRL_PLLCTRL0_RSRVD4	0x00C00000
-#define BF_CLKCTRL_PLLCTRL0_RSRVD4(v)  \
-		(((v) << 22) & BM_CLKCTRL_PLLCTRL0_RSRVD4)
 #define BP_CLKCTRL_PLLCTRL0_DIV_SEL	20
 #define BM_CLKCTRL_PLLCTRL0_DIV_SEL	0x00300000
 #define BF_CLKCTRL_PLLCTRL0_DIV_SEL(v)  \
@@ -69,23 +57,13 @@
 #define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWER     0x1
 #define BV_CLKCTRL_PLLCTRL0_DIV_SEL__LOWEST    0x2
 #define BV_CLKCTRL_PLLCTRL0_DIV_SEL__UNDEFINED 0x3
-#define BM_CLKCTRL_PLLCTRL0_RSRVD3	0x00080000
 #define BM_CLKCTRL_PLLCTRL0_EN_USB_CLKS	0x00040000
-#define BM_CLKCTRL_PLLCTRL0_RSRVD2	0x00020000
 #define BM_CLKCTRL_PLLCTRL0_POWER	0x00010000
-#define BP_CLKCTRL_PLLCTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLLCTRL0_RSRVD1	0x0000FFFF
-#define BF_CLKCTRL_PLLCTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLLCTRL0_RSRVD1)
 
 #define HW_CLKCTRL_PLLCTRL1	(0x00000010)
 
 #define BM_CLKCTRL_PLLCTRL1_LOCK	0x80000000
 #define BM_CLKCTRL_PLLCTRL1_FORCE_LOCK	0x40000000
-#define BP_CLKCTRL_PLLCTRL1_RSRVD1	16
-#define BM_CLKCTRL_PLLCTRL1_RSRVD1	0x3FFF0000
-#define BF_CLKCTRL_PLLCTRL1_RSRVD1(v)  \
-		(((v) << 16) & BM_CLKCTRL_PLLCTRL1_RSRVD1)
 #define BP_CLKCTRL_PLLCTRL1_LOCK_COUNT	0
 #define BM_CLKCTRL_PLLCTRL1_LOCK_COUNT	0x0000FFFF
 #define BF_CLKCTRL_PLLCTRL1_LOCK_COUNT(v)  \
@@ -96,29 +74,15 @@
 #define HW_CLKCTRL_CPU_CLR	(0x00000028)
 #define HW_CLKCTRL_CPU_TOG	(0x0000002c)
 
-#define BP_CLKCTRL_CPU_RSRVD5	30
-#define BM_CLKCTRL_CPU_RSRVD5	0xC0000000
-#define BF_CLKCTRL_CPU_RSRVD5(v) \
-		(((v) << 30) & BM_CLKCTRL_CPU_RSRVD5)
 #define BM_CLKCTRL_CPU_BUSY_REF_XTAL	0x20000000
 #define BM_CLKCTRL_CPU_BUSY_REF_CPU	0x10000000
-#define BM_CLKCTRL_CPU_RSRVD4	0x08000000
 #define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN	0x04000000
 #define BP_CLKCTRL_CPU_DIV_XTAL	16
 #define BM_CLKCTRL_CPU_DIV_XTAL	0x03FF0000
 #define BF_CLKCTRL_CPU_DIV_XTAL(v)  \
 		(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
-#define BP_CLKCTRL_CPU_RSRVD3	13
-#define BM_CLKCTRL_CPU_RSRVD3	0x0000E000
-#define BF_CLKCTRL_CPU_RSRVD3(v)  \
-		(((v) << 13) & BM_CLKCTRL_CPU_RSRVD3)
 #define BM_CLKCTRL_CPU_INTERRUPT_WAIT	0x00001000
-#define BM_CLKCTRL_CPU_RSRVD2	0x00000800
 #define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN	0x00000400
-#define BP_CLKCTRL_CPU_RSRVD1	6
-#define BM_CLKCTRL_CPU_RSRVD1	0x000003C0
-#define BF_CLKCTRL_CPU_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_CPU_RSRVD1)
 #define BP_CLKCTRL_CPU_DIV_CPU	0
 #define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
 #define BF_CLKCTRL_CPU_DIV_CPU(v)  \
@@ -129,10 +93,6 @@
 #define HW_CLKCTRL_HBUS_CLR	(0x00000038)
 #define HW_CLKCTRL_HBUS_TOG	(0x0000003c)
 
-#define BP_CLKCTRL_HBUS_RSRVD4	30
-#define BM_CLKCTRL_HBUS_RSRVD4	0xC0000000
-#define BF_CLKCTRL_HBUS_RSRVD4(v) \
-		(((v) << 30) & BM_CLKCTRL_HBUS_RSRVD4)
 #define BM_CLKCTRL_HBUS_BUSY	0x20000000
 #define BM_CLKCTRL_HBUS_DCP_AS_ENABLE	0x10000000
 #define BM_CLKCTRL_HBUS_PXP_AS_ENABLE	0x08000000
@@ -143,7 +103,6 @@
 #define BM_CLKCTRL_HBUS_CPU_DATA_AS_ENABLE	0x00400000
 #define BM_CLKCTRL_HBUS_CPU_INSTR_AS_ENABLE	0x00200000
 #define BM_CLKCTRL_HBUS_AUTO_SLOW_MODE	0x00100000
-#define BM_CLKCTRL_HBUS_RSRVD2	0x00080000
 #define BP_CLKCTRL_HBUS_SLOW_DIV	16
 #define BM_CLKCTRL_HBUS_SLOW_DIV	0x00070000
 #define BF_CLKCTRL_HBUS_SLOW_DIV(v)  \
@@ -154,10 +113,6 @@
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY8  0x3
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
-#define BP_CLKCTRL_HBUS_RSRVD1	6
-#define BM_CLKCTRL_HBUS_RSRVD1	0x0000FFC0
-#define BF_CLKCTRL_HBUS_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_HBUS_RSRVD1)
 #define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
 #define BP_CLKCTRL_HBUS_DIV	0
 #define BM_CLKCTRL_HBUS_DIV	0x0000001F
@@ -167,10 +122,6 @@
 #define HW_CLKCTRL_XBUS	(0x00000040)
 
 #define BM_CLKCTRL_XBUS_BUSY	0x80000000
-#define BP_CLKCTRL_XBUS_RSRVD1	11
-#define BM_CLKCTRL_XBUS_RSRVD1	0x7FFFF800
-#define BF_CLKCTRL_XBUS_RSRVD1(v)  \
-		(((v) << 11) & BM_CLKCTRL_XBUS_RSRVD1)
 #define BM_CLKCTRL_XBUS_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_XBUS_DIV	0
 #define BM_CLKCTRL_XBUS_DIV	0x000003FF
@@ -192,10 +143,6 @@
 #define BM_CLKCTRL_XTAL_DIGCTRL_CLK1M_GATE	0x08000000
 #define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	26
 #define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	0x04000000
-#define BP_CLKCTRL_XTAL_RSRVD1	2
-#define BM_CLKCTRL_XTAL_RSRVD1	0x03FFFFFC
-#define BF_CLKCTRL_XTAL_RSRVD1(v)  \
-		(((v) << 2) & BM_CLKCTRL_XTAL_RSRVD1)
 #define BP_CLKCTRL_XTAL_DIV_UART	0
 #define BM_CLKCTRL_XTAL_DIV_UART	0x00000003
 #define BF_CLKCTRL_XTAL_DIV_UART(v)  \
@@ -205,12 +152,7 @@
 
 #define BP_CLKCTRL_PIX_CLKGATE	31
 #define BM_CLKCTRL_PIX_CLKGATE	0x80000000
-#define BM_CLKCTRL_PIX_RSRVD2	0x40000000
 #define BM_CLKCTRL_PIX_BUSY	0x20000000
-#define BP_CLKCTRL_PIX_RSRVD1	13
-#define BM_CLKCTRL_PIX_RSRVD1	0x1FFFE000
-#define BF_CLKCTRL_PIX_RSRVD1(v)  \
-		(((v) << 13) & BM_CLKCTRL_PIX_RSRVD1)
 #define BM_CLKCTRL_PIX_DIV_FRAC_EN	0x00001000
 #define BP_CLKCTRL_PIX_DIV	0
 #define BM_CLKCTRL_PIX_DIV	0x00000FFF
@@ -221,12 +163,7 @@
 
 #define BP_CLKCTRL_SSP_CLKGATE	31
 #define BM_CLKCTRL_SSP_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP_BUSY	0x20000000
-#define BP_CLKCTRL_SSP_RSRVD1	10
-#define BM_CLKCTRL_SSP_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP_RSRVD1)
 #define BM_CLKCTRL_SSP_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP_DIV	0
 #define BM_CLKCTRL_SSP_DIV	0x000001FF
@@ -237,12 +174,7 @@
 
 #define BP_CLKCTRL_GPMI_CLKGATE	31
 #define BM_CLKCTRL_GPMI_CLKGATE	0x80000000
-#define BM_CLKCTRL_GPMI_RSRVD2	0x40000000
 #define BM_CLKCTRL_GPMI_BUSY	0x20000000
-#define BP_CLKCTRL_GPMI_RSRVD1	11
-#define BM_CLKCTRL_GPMI_RSRVD1	0x1FFFF800
-#define BF_CLKCTRL_GPMI_RSRVD1(v)  \
-		(((v) << 11) & BM_CLKCTRL_GPMI_RSRVD1)
 #define BM_CLKCTRL_GPMI_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_GPMI_DIV	0
 #define BM_CLKCTRL_GPMI_DIV	0x000003FF
@@ -252,10 +184,6 @@
 #define HW_CLKCTRL_SPDIF	(0x00000090)
 
 #define BM_CLKCTRL_SPDIF_CLKGATE	0x80000000
-#define BP_CLKCTRL_SPDIF_RSRVD	0
-#define BM_CLKCTRL_SPDIF_RSRVD	0x7FFFFFFF
-#define BF_CLKCTRL_SPDIF_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_SPDIF_RSRVD)
 
 #define HW_CLKCTRL_EMI	(0x000000a0)
 
@@ -266,24 +194,12 @@
 #define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
 #define BM_CLKCTRL_EMI_BUSY_REF_CPU	0x08000000
 #define BM_CLKCTRL_EMI_BUSY_SYNC_MODE	0x04000000
-#define BP_CLKCTRL_EMI_RSRVD3	18
-#define BM_CLKCTRL_EMI_RSRVD3	0x03FC0000
-#define BF_CLKCTRL_EMI_RSRVD3(v)  \
-		(((v) << 18) & BM_CLKCTRL_EMI_RSRVD3)
 #define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
 #define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
-#define BP_CLKCTRL_EMI_RSRVD2	12
-#define BM_CLKCTRL_EMI_RSRVD2	0x0000F000
-#define BF_CLKCTRL_EMI_RSRVD2(v)  \
-		(((v) << 12) & BM_CLKCTRL_EMI_RSRVD2)
 #define BP_CLKCTRL_EMI_DIV_XTAL	8
 #define BM_CLKCTRL_EMI_DIV_XTAL	0x00000F00
 #define BF_CLKCTRL_EMI_DIV_XTAL(v)  \
 		(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
-#define BP_CLKCTRL_EMI_RSRVD1	6
-#define BM_CLKCTRL_EMI_RSRVD1	0x000000C0
-#define BF_CLKCTRL_EMI_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_EMI_RSRVD1)
 #define BP_CLKCTRL_EMI_DIV_EMI	0
 #define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
 #define BF_CLKCTRL_EMI_DIV_EMI(v)  \
@@ -292,22 +208,13 @@
 #define HW_CLKCTRL_IR	(0x000000b0)
 
 #define BM_CLKCTRL_IR_CLKGATE	0x80000000
-#define BM_CLKCTRL_IR_RSRVD3	0x40000000
 #define BM_CLKCTRL_IR_AUTO_DIV	0x20000000
 #define BM_CLKCTRL_IR_IR_BUSY	0x10000000
 #define BM_CLKCTRL_IR_IROV_BUSY	0x08000000
-#define BP_CLKCTRL_IR_RSRVD2	25
-#define BM_CLKCTRL_IR_RSRVD2	0x06000000
-#define BF_CLKCTRL_IR_RSRVD2(v)  \
-		(((v) << 25) & BM_CLKCTRL_IR_RSRVD2)
 #define BP_CLKCTRL_IR_IROV_DIV	16
 #define BM_CLKCTRL_IR_IROV_DIV	0x01FF0000
 #define BF_CLKCTRL_IR_IROV_DIV(v)  \
 		(((v) << 16) & BM_CLKCTRL_IR_IROV_DIV)
-#define BP_CLKCTRL_IR_RSRVD1	10
-#define BM_CLKCTRL_IR_RSRVD1	0x0000FC00
-#define BF_CLKCTRL_IR_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_IR_RSRVD1)
 #define BP_CLKCTRL_IR_IR_DIV	0
 #define BM_CLKCTRL_IR_IR_DIV	0x000003FF
 #define BF_CLKCTRL_IR_IR_DIV(v)  \
@@ -316,12 +223,7 @@
 #define HW_CLKCTRL_SAIF	(0x000000c0)
 
 #define BM_CLKCTRL_SAIF_CLKGATE	0x80000000
-#define BM_CLKCTRL_SAIF_RSRVD2	0x40000000
 #define BM_CLKCTRL_SAIF_BUSY	0x20000000
-#define BP_CLKCTRL_SAIF_RSRVD1	17
-#define BM_CLKCTRL_SAIF_RSRVD1	0x1FFE0000
-#define BF_CLKCTRL_SAIF_RSRVD1(v)  \
-		(((v) << 17) & BM_CLKCTRL_SAIF_RSRVD1)
 #define BM_CLKCTRL_SAIF_DIV_FRAC_EN	0x00010000
 #define BP_CLKCTRL_SAIF_DIV	0
 #define BM_CLKCTRL_SAIF_DIV	0x0000FFFF
@@ -332,20 +234,11 @@
 
 #define BM_CLKCTRL_TV_CLK_TV108M_GATE	0x80000000
 #define BM_CLKCTRL_TV_CLK_TV_GATE	0x40000000
-#define BP_CLKCTRL_TV_RSRVD	0
-#define BM_CLKCTRL_TV_RSRVD	0x3FFFFFFF
-#define BF_CLKCTRL_TV_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_TV_RSRVD)
 
 #define HW_CLKCTRL_ETM	(0x000000e0)
 
 #define BM_CLKCTRL_ETM_CLKGATE	0x80000000
-#define BM_CLKCTRL_ETM_RSRVD2	0x40000000
 #define BM_CLKCTRL_ETM_BUSY	0x20000000
-#define BP_CLKCTRL_ETM_RSRVD1	7
-#define BM_CLKCTRL_ETM_RSRVD1	0x1FFFFF80
-#define BF_CLKCTRL_ETM_RSRVD1(v)  \
-		(((v) << 7) & BM_CLKCTRL_ETM_RSRVD1)
 #define BM_CLKCTRL_ETM_DIV_FRAC_EN	0x00000040
 #define BP_CLKCTRL_ETM_DIV	0
 #define BM_CLKCTRL_ETM_DIV	0x0000003F
@@ -393,36 +286,23 @@
 
 #define BM_CLKCTRL_FRAC1_CLKGATEVID	0x80000000
 #define BM_CLKCTRL_FRAC1_VID_STABLE	0x40000000
-#define BP_CLKCTRL_FRAC1_RSRVD1	0
-#define BM_CLKCTRL_FRAC1_RSRVD1	0x3FFFFFFF
-#define BF_CLKCTRL_FRAC1_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_FRAC1_RSRVD1)
 
 #define HW_CLKCTRL_CLKSEQ	(0x00000110)
 #define HW_CLKCTRL_CLKSEQ_SET	(0x00000114)
 #define HW_CLKCTRL_CLKSEQ_CLR	(0x00000118)
 #define HW_CLKCTRL_CLKSEQ_TOG	(0x0000011c)
 
-#define BP_CLKCTRL_CLKSEQ_RSRVD1	9
-#define BM_CLKCTRL_CLKSEQ_RSRVD1	0xFFFFFE00
-#define BF_CLKCTRL_CLKSEQ_RSRVD1(v) \
-		(((v) << 9) & BM_CLKCTRL_CLKSEQ_RSRVD1)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_ETM	0x00000100
 #define BM_CLKCTRL_CLKSEQ_BYPASS_CPU	0x00000080
 #define BM_CLKCTRL_CLKSEQ_BYPASS_EMI	0x00000040
 #define BM_CLKCTRL_CLKSEQ_BYPASS_SSP	0x00000020
 #define BM_CLKCTRL_CLKSEQ_BYPASS_GPMI	0x00000010
 #define BM_CLKCTRL_CLKSEQ_BYPASS_IR	0x00000008
-#define BM_CLKCTRL_CLKSEQ_RSRVD0	0x00000004
 #define BM_CLKCTRL_CLKSEQ_BYPASS_PIX	0x00000002
 #define BM_CLKCTRL_CLKSEQ_BYPASS_SAIF	0x00000001
 
 #define HW_CLKCTRL_RESET	(0x00000120)
 
-#define BP_CLKCTRL_RESET_RSRVD	2
-#define BM_CLKCTRL_RESET_RSRVD	0xFFFFFFFC
-#define BF_CLKCTRL_RESET_RSRVD(v) \
-		(((v) << 2) & BM_CLKCTRL_RESET_RSRVD)
 #define BM_CLKCTRL_RESET_CHIP	0x00000002
 #define BM_CLKCTRL_RESET_DIG	0x00000001
 
@@ -432,10 +312,6 @@
 #define BM_CLKCTRL_STATUS_CPU_LIMIT	0xC0000000
 #define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
 		(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
-#define BP_CLKCTRL_STATUS_RSRVD	0
-#define BM_CLKCTRL_STATUS_RSRVD	0x3FFFFFFF
-#define BF_CLKCTRL_STATUS_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_STATUS_RSRVD)
 
 #define HW_CLKCTRL_VERSION	(0x00000140)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/regs-clkctrl-mx28.h linux-libre-2.6.39-gnu/arch/arm/mach-mxs/regs-clkctrl-mx28.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/regs-clkctrl-mx28.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/regs-clkctrl-mx28.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,10 +31,6 @@
 #define HW_CLKCTRL_PLL0CTRL0_CLR	(0x00000008)
 #define HW_CLKCTRL_PLL0CTRL0_TOG	(0x0000000c)
 
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD6	30
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD6	0xC0000000
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD6(v) \
-		(((v) << 30) & BM_CLKCTRL_PLL0CTRL0_RSRVD6)
 #define BP_CLKCTRL_PLL0CTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLL0CTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLL0CTRL0_LFR_SEL(v)  \
@@ -43,10 +39,6 @@
 #define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL0CTRL0_LFR_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD5	26
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD5	0x0C000000
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD5(v)  \
-		(((v) << 26) & BM_CLKCTRL_PLL0CTRL0_RSRVD5)
 #define BP_CLKCTRL_PLL0CTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLL0CTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLL0CTRL0_CP_SEL(v)  \
@@ -55,10 +47,6 @@
 #define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL0CTRL0_CP_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL0CTRL0_CP_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD4	22
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD4	0x00C00000
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD4(v)  \
-		(((v) << 22) & BM_CLKCTRL_PLL0CTRL0_RSRVD4)
 #define BP_CLKCTRL_PLL0CTRL0_DIV_SEL	20
 #define BM_CLKCTRL_PLL0CTRL0_DIV_SEL	0x00300000
 #define BF_CLKCTRL_PLL0CTRL0_DIV_SEL(v)  \
@@ -67,22 +55,13 @@
 #define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWER     0x1
 #define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__LOWEST    0x2
 #define BV_CLKCTRL_PLL0CTRL0_DIV_SEL__UNDEFINED 0x3
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD3	0x00080000
 #define BM_CLKCTRL_PLL0CTRL0_EN_USB_CLKS	0x00040000
 #define BM_CLKCTRL_PLL0CTRL0_POWER	0x00020000
-#define BP_CLKCTRL_PLL0CTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLL0CTRL0_RSRVD1	0x0001FFFF
-#define BF_CLKCTRL_PLL0CTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLL0CTRL0_RSRVD1)
 
 #define HW_CLKCTRL_PLL0CTRL1	(0x00000010)
 
 #define BM_CLKCTRL_PLL0CTRL1_LOCK	0x80000000
 #define BM_CLKCTRL_PLL0CTRL1_FORCE_LOCK	0x40000000
-#define BP_CLKCTRL_PLL0CTRL1_RSRVD1	16
-#define BM_CLKCTRL_PLL0CTRL1_RSRVD1	0x3FFF0000
-#define BF_CLKCTRL_PLL0CTRL1_RSRVD1(v)  \
-		(((v) << 16) & BM_CLKCTRL_PLL0CTRL1_RSRVD1)
 #define BP_CLKCTRL_PLL0CTRL1_LOCK_COUNT	0
 #define BM_CLKCTRL_PLL0CTRL1_LOCK_COUNT	0x0000FFFF
 #define BF_CLKCTRL_PLL0CTRL1_LOCK_COUNT(v)  \
@@ -94,7 +73,6 @@
 #define HW_CLKCTRL_PLL1CTRL0_TOG	(0x0000002c)
 
 #define BM_CLKCTRL_PLL1CTRL0_CLKGATEEMI	0x80000000
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD6	0x40000000
 #define BP_CLKCTRL_PLL1CTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLL1CTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLL1CTRL0_LFR_SEL(v)  \
@@ -103,10 +81,6 @@
 #define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL1CTRL0_LFR_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL1CTRL0_RSRVD5	26
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD5	0x0C000000
-#define BF_CLKCTRL_PLL1CTRL0_RSRVD5(v)  \
-		(((v) << 26) & BM_CLKCTRL_PLL1CTRL0_RSRVD5)
 #define BP_CLKCTRL_PLL1CTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLL1CTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLL1CTRL0_CP_SEL(v)  \
@@ -115,10 +89,6 @@
 #define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_2   0x1
 #define BV_CLKCTRL_PLL1CTRL0_CP_SEL__TIMES_05  0x2
 #define BV_CLKCTRL_PLL1CTRL0_CP_SEL__UNDEFINED 0x3
-#define BP_CLKCTRL_PLL1CTRL0_RSRVD4	22
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD4	0x00C00000
-#define BF_CLKCTRL_PLL1CTRL0_RSRVD4(v)  \
-		(((v) << 22) & BM_CLKCTRL_PLL1CTRL0_RSRVD4)
 #define BP_CLKCTRL_PLL1CTRL0_DIV_SEL	20
 #define BM_CLKCTRL_PLL1CTRL0_DIV_SEL	0x00300000
 #define BF_CLKCTRL_PLL1CTRL0_DIV_SEL(v)  \
@@ -127,22 +97,13 @@
 #define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWER     0x1
 #define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__LOWEST    0x2
 #define BV_CLKCTRL_PLL1CTRL0_DIV_SEL__UNDEFINED 0x3
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD3	0x00080000
 #define BM_CLKCTRL_PLL1CTRL0_EN_USB_CLKS	0x00040000
 #define BM_CLKCTRL_PLL1CTRL0_POWER	0x00020000
-#define BP_CLKCTRL_PLL1CTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLL1CTRL0_RSRVD1	0x0001FFFF
-#define BF_CLKCTRL_PLL1CTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLL1CTRL0_RSRVD1)
 
 #define HW_CLKCTRL_PLL1CTRL1	(0x00000030)
 
 #define BM_CLKCTRL_PLL1CTRL1_LOCK	0x80000000
 #define BM_CLKCTRL_PLL1CTRL1_FORCE_LOCK	0x40000000
-#define BP_CLKCTRL_PLL1CTRL1_RSRVD1	16
-#define BM_CLKCTRL_PLL1CTRL1_RSRVD1	0x3FFF0000
-#define BF_CLKCTRL_PLL1CTRL1_RSRVD1(v)  \
-		(((v) << 16) & BM_CLKCTRL_PLL1CTRL1_RSRVD1)
 #define BP_CLKCTRL_PLL1CTRL1_LOCK_COUNT	0
 #define BM_CLKCTRL_PLL1CTRL1_LOCK_COUNT	0x0000FFFF
 #define BF_CLKCTRL_PLL1CTRL1_LOCK_COUNT(v)  \
@@ -154,51 +115,31 @@
 #define HW_CLKCTRL_PLL2CTRL0_TOG	(0x0000004c)
 
 #define BM_CLKCTRL_PLL2CTRL0_CLKGATE	0x80000000
-#define BM_CLKCTRL_PLL2CTRL0_RSRVD3	0x40000000
 #define BP_CLKCTRL_PLL2CTRL0_LFR_SEL	28
 #define BM_CLKCTRL_PLL2CTRL0_LFR_SEL	0x30000000
 #define BF_CLKCTRL_PLL2CTRL0_LFR_SEL(v)  \
 		(((v) << 28) & BM_CLKCTRL_PLL2CTRL0_LFR_SEL)
-#define BM_CLKCTRL_PLL2CTRL0_RSRVD2	0x08000000
 #define BM_CLKCTRL_PLL2CTRL0_HOLD_RING_OFF_B	0x04000000
 #define BP_CLKCTRL_PLL2CTRL0_CP_SEL	24
 #define BM_CLKCTRL_PLL2CTRL0_CP_SEL	0x03000000
 #define BF_CLKCTRL_PLL2CTRL0_CP_SEL(v)  \
 		(((v) << 24) & BM_CLKCTRL_PLL2CTRL0_CP_SEL)
 #define BM_CLKCTRL_PLL2CTRL0_POWER	0x00800000
-#define BP_CLKCTRL_PLL2CTRL0_RSRVD1	0
-#define BM_CLKCTRL_PLL2CTRL0_RSRVD1	0x007FFFFF
-#define BF_CLKCTRL_PLL2CTRL0_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_PLL2CTRL0_RSRVD1)
 
 #define HW_CLKCTRL_CPU	(0x00000050)
 #define HW_CLKCTRL_CPU_SET	(0x00000054)
 #define HW_CLKCTRL_CPU_CLR	(0x00000058)
 #define HW_CLKCTRL_CPU_TOG	(0x0000005c)
 
-#define BP_CLKCTRL_CPU_RSRVD5	30
-#define BM_CLKCTRL_CPU_RSRVD5	0xC0000000
-#define BF_CLKCTRL_CPU_RSRVD5(v) \
-		(((v) << 30) & BM_CLKCTRL_CPU_RSRVD5)
 #define BM_CLKCTRL_CPU_BUSY_REF_XTAL	0x20000000
 #define BM_CLKCTRL_CPU_BUSY_REF_CPU	0x10000000
-#define BM_CLKCTRL_CPU_RSRVD4	0x08000000
 #define BM_CLKCTRL_CPU_DIV_XTAL_FRAC_EN	0x04000000
 #define BP_CLKCTRL_CPU_DIV_XTAL	16
 #define BM_CLKCTRL_CPU_DIV_XTAL	0x03FF0000
 #define BF_CLKCTRL_CPU_DIV_XTAL(v)  \
 		(((v) << 16) & BM_CLKCTRL_CPU_DIV_XTAL)
-#define BP_CLKCTRL_CPU_RSRVD3	13
-#define BM_CLKCTRL_CPU_RSRVD3	0x0000E000
-#define BF_CLKCTRL_CPU_RSRVD3(v)  \
-		(((v) << 13) & BM_CLKCTRL_CPU_RSRVD3)
 #define BM_CLKCTRL_CPU_INTERRUPT_WAIT	0x00001000
-#define BM_CLKCTRL_CPU_RSRVD2	0x00000800
 #define BM_CLKCTRL_CPU_DIV_CPU_FRAC_EN	0x00000400
-#define BP_CLKCTRL_CPU_RSRVD1	6
-#define BM_CLKCTRL_CPU_RSRVD1	0x000003C0
-#define BF_CLKCTRL_CPU_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_CPU_RSRVD1)
 #define BP_CLKCTRL_CPU_DIV_CPU	0
 #define BM_CLKCTRL_CPU_DIV_CPU	0x0000003F
 #define BF_CLKCTRL_CPU_DIV_CPU(v)  \
@@ -212,7 +153,6 @@
 #define BM_CLKCTRL_HBUS_ASM_BUSY	0x80000000
 #define BM_CLKCTRL_HBUS_DCP_AS_ENABLE	0x40000000
 #define BM_CLKCTRL_HBUS_PXP_AS_ENABLE	0x20000000
-#define BM_CLKCTRL_HBUS_RSRVD2	0x10000000
 #define BM_CLKCTRL_HBUS_ASM_EMIPORT_AS_ENABLE	0x08000000
 #define BM_CLKCTRL_HBUS_APBHDMA_AS_ENABLE	0x04000000
 #define BM_CLKCTRL_HBUS_APBXDMA_AS_ENABLE	0x02000000
@@ -232,10 +172,6 @@
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY8  0x3
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY16 0x4
 #define BV_CLKCTRL_HBUS_SLOW_DIV__BY32 0x5
-#define BP_CLKCTRL_HBUS_RSRVD1	6
-#define BM_CLKCTRL_HBUS_RSRVD1	0x0000FFC0
-#define BF_CLKCTRL_HBUS_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_HBUS_RSRVD1)
 #define BM_CLKCTRL_HBUS_DIV_FRAC_EN	0x00000020
 #define BP_CLKCTRL_HBUS_DIV	0
 #define BM_CLKCTRL_HBUS_DIV	0x0000001F
@@ -245,10 +181,6 @@
 #define HW_CLKCTRL_XBUS	(0x00000070)
 
 #define BM_CLKCTRL_XBUS_BUSY	0x80000000
-#define BP_CLKCTRL_XBUS_RSRVD1	12
-#define BM_CLKCTRL_XBUS_RSRVD1	0x7FFFF000
-#define BF_CLKCTRL_XBUS_RSRVD1(v)  \
-		(((v) << 12) & BM_CLKCTRL_XBUS_RSRVD1)
 #define BM_CLKCTRL_XBUS_AUTO_CLEAR_DIV_ENABLE	0x00000800
 #define BM_CLKCTRL_XBUS_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_XBUS_DIV	0
@@ -263,19 +195,10 @@
 
 #define BP_CLKCTRL_XTAL_UART_CLK_GATE	31
 #define BM_CLKCTRL_XTAL_UART_CLK_GATE	0x80000000
-#define BM_CLKCTRL_XTAL_RSRVD3	0x40000000
 #define BP_CLKCTRL_XTAL_PWM_CLK24M_GATE	29
 #define BM_CLKCTRL_XTAL_PWM_CLK24M_GATE	0x20000000
-#define BP_CLKCTRL_XTAL_RSRVD2	27
-#define BM_CLKCTRL_XTAL_RSRVD2	0x18000000
-#define BF_CLKCTRL_XTAL_RSRVD2(v)  \
-		(((v) << 27) & BM_CLKCTRL_XTAL_RSRVD2)
 #define BP_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	26
 #define BM_CLKCTRL_XTAL_TIMROT_CLK32K_GATE	0x04000000
-#define BP_CLKCTRL_XTAL_RSRVD1	2
-#define BM_CLKCTRL_XTAL_RSRVD1	0x03FFFFFC
-#define BF_CLKCTRL_XTAL_RSRVD1(v)  \
-		(((v) << 2) & BM_CLKCTRL_XTAL_RSRVD1)
 #define BP_CLKCTRL_XTAL_DIV_UART	0
 #define BM_CLKCTRL_XTAL_DIV_UART	0x00000003
 #define BF_CLKCTRL_XTAL_DIV_UART(v)  \
@@ -285,12 +208,7 @@
 
 #define BP_CLKCTRL_SSP0_CLKGATE	31
 #define BM_CLKCTRL_SSP0_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP0_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP0_BUSY	0x20000000
-#define BP_CLKCTRL_SSP0_RSRVD1	10
-#define BM_CLKCTRL_SSP0_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP0_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP0_RSRVD1)
 #define BM_CLKCTRL_SSP0_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP0_DIV	0
 #define BM_CLKCTRL_SSP0_DIV	0x000001FF
@@ -301,12 +219,7 @@
 
 #define BP_CLKCTRL_SSP1_CLKGATE	31
 #define BM_CLKCTRL_SSP1_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP1_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP1_BUSY	0x20000000
-#define BP_CLKCTRL_SSP1_RSRVD1	10
-#define BM_CLKCTRL_SSP1_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP1_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP1_RSRVD1)
 #define BM_CLKCTRL_SSP1_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP1_DIV	0
 #define BM_CLKCTRL_SSP1_DIV	0x000001FF
@@ -317,12 +230,7 @@
 
 #define BP_CLKCTRL_SSP2_CLKGATE	31
 #define BM_CLKCTRL_SSP2_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP2_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP2_BUSY	0x20000000
-#define BP_CLKCTRL_SSP2_RSRVD1	10
-#define BM_CLKCTRL_SSP2_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP2_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP2_RSRVD1)
 #define BM_CLKCTRL_SSP2_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP2_DIV	0
 #define BM_CLKCTRL_SSP2_DIV	0x000001FF
@@ -333,12 +241,7 @@
 
 #define BP_CLKCTRL_SSP3_CLKGATE	31
 #define BM_CLKCTRL_SSP3_CLKGATE	0x80000000
-#define BM_CLKCTRL_SSP3_RSRVD2	0x40000000
 #define BM_CLKCTRL_SSP3_BUSY	0x20000000
-#define BP_CLKCTRL_SSP3_RSRVD1	10
-#define BM_CLKCTRL_SSP3_RSRVD1	0x1FFFFC00
-#define BF_CLKCTRL_SSP3_RSRVD1(v)  \
-		(((v) << 10) & BM_CLKCTRL_SSP3_RSRVD1)
 #define BM_CLKCTRL_SSP3_DIV_FRAC_EN	0x00000200
 #define BP_CLKCTRL_SSP3_DIV	0
 #define BM_CLKCTRL_SSP3_DIV	0x000001FF
@@ -349,12 +252,7 @@
 
 #define BP_CLKCTRL_GPMI_CLKGATE	31
 #define BM_CLKCTRL_GPMI_CLKGATE	0x80000000
-#define BM_CLKCTRL_GPMI_RSRVD2	0x40000000
 #define BM_CLKCTRL_GPMI_BUSY	0x20000000
-#define BP_CLKCTRL_GPMI_RSRVD1	11
-#define BM_CLKCTRL_GPMI_RSRVD1	0x1FFFF800
-#define BF_CLKCTRL_GPMI_RSRVD1(v)  \
-		(((v) << 11) & BM_CLKCTRL_GPMI_RSRVD1)
 #define BM_CLKCTRL_GPMI_DIV_FRAC_EN	0x00000400
 #define BP_CLKCTRL_GPMI_DIV	0
 #define BM_CLKCTRL_GPMI_DIV	0x000003FF
@@ -365,10 +263,6 @@
 
 #define BP_CLKCTRL_SPDIF_CLKGATE	31
 #define BM_CLKCTRL_SPDIF_CLKGATE	0x80000000
-#define BP_CLKCTRL_SPDIF_RSRVD	0
-#define BM_CLKCTRL_SPDIF_RSRVD	0x7FFFFFFF
-#define BF_CLKCTRL_SPDIF_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_SPDIF_RSRVD)
 
 #define HW_CLKCTRL_EMI	(0x000000f0)
 
@@ -379,24 +273,12 @@
 #define BM_CLKCTRL_EMI_BUSY_REF_EMI	0x10000000
 #define BM_CLKCTRL_EMI_BUSY_REF_CPU	0x08000000
 #define BM_CLKCTRL_EMI_BUSY_SYNC_MODE	0x04000000
-#define BP_CLKCTRL_EMI_RSRVD3	18
-#define BM_CLKCTRL_EMI_RSRVD3	0x03FC0000
-#define BF_CLKCTRL_EMI_RSRVD3(v)  \
-		(((v) << 18) & BM_CLKCTRL_EMI_RSRVD3)
 #define BM_CLKCTRL_EMI_BUSY_DCC_RESYNC	0x00020000
 #define BM_CLKCTRL_EMI_DCC_RESYNC_ENABLE	0x00010000
-#define BP_CLKCTRL_EMI_RSRVD2	12
-#define BM_CLKCTRL_EMI_RSRVD2	0x0000F000
-#define BF_CLKCTRL_EMI_RSRVD2(v)  \
-		(((v) << 12) & BM_CLKCTRL_EMI_RSRVD2)
 #define BP_CLKCTRL_EMI_DIV_XTAL	8
 #define BM_CLKCTRL_EMI_DIV_XTAL	0x00000F00
 #define BF_CLKCTRL_EMI_DIV_XTAL(v)  \
 		(((v) << 8) & BM_CLKCTRL_EMI_DIV_XTAL)
-#define BP_CLKCTRL_EMI_RSRVD1	6
-#define BM_CLKCTRL_EMI_RSRVD1	0x000000C0
-#define BF_CLKCTRL_EMI_RSRVD1(v)  \
-		(((v) << 6) & BM_CLKCTRL_EMI_RSRVD1)
 #define BP_CLKCTRL_EMI_DIV_EMI	0
 #define BM_CLKCTRL_EMI_DIV_EMI	0x0000003F
 #define BF_CLKCTRL_EMI_DIV_EMI(v)  \
@@ -406,12 +288,7 @@
 
 #define BP_CLKCTRL_SAIF0_CLKGATE	31
 #define BM_CLKCTRL_SAIF0_CLKGATE	0x80000000
-#define BM_CLKCTRL_SAIF0_RSRVD2	0x40000000
 #define BM_CLKCTRL_SAIF0_BUSY	0x20000000
-#define BP_CLKCTRL_SAIF0_RSRVD1	17
-#define BM_CLKCTRL_SAIF0_RSRVD1	0x1FFE0000
-#define BF_CLKCTRL_SAIF0_RSRVD1(v)  \
-		(((v) << 17) & BM_CLKCTRL_SAIF0_RSRVD1)
 #define BM_CLKCTRL_SAIF0_DIV_FRAC_EN	0x00010000
 #define BP_CLKCTRL_SAIF0_DIV	0
 #define BM_CLKCTRL_SAIF0_DIV	0x0000FFFF
@@ -422,12 +299,7 @@
 
 #define BP_CLKCTRL_SAIF1_CLKGATE	31
 #define BM_CLKCTRL_SAIF1_CLKGATE	0x80000000
-#define BM_CLKCTRL_SAIF1_RSRVD2	0x40000000
 #define BM_CLKCTRL_SAIF1_BUSY	0x20000000
-#define BP_CLKCTRL_SAIF1_RSRVD1	17
-#define BM_CLKCTRL_SAIF1_RSRVD1	0x1FFE0000
-#define BF_CLKCTRL_SAIF1_RSRVD1(v)  \
-		(((v) << 17) & BM_CLKCTRL_SAIF1_RSRVD1)
 #define BM_CLKCTRL_SAIF1_DIV_FRAC_EN	0x00010000
 #define BP_CLKCTRL_SAIF1_DIV	0
 #define BM_CLKCTRL_SAIF1_DIV	0x0000FFFF
@@ -438,12 +310,7 @@
 
 #define BP_CLKCTRL_DIS_LCDIF_CLKGATE	31
 #define BM_CLKCTRL_DIS_LCDIF_CLKGATE	0x80000000
-#define BM_CLKCTRL_DIS_LCDIF_RSRVD2	0x40000000
 #define BM_CLKCTRL_DIS_LCDIF_BUSY	0x20000000
-#define BP_CLKCTRL_DIS_LCDIF_RSRVD1	14
-#define BM_CLKCTRL_DIS_LCDIF_RSRVD1	0x1FFFC000
-#define BF_CLKCTRL_DIS_LCDIF_RSRVD1(v)  \
-		(((v) << 14) & BM_CLKCTRL_DIS_LCDIF_RSRVD1)
 #define BM_CLKCTRL_DIS_LCDIF_DIV_FRAC_EN	0x00002000
 #define BP_CLKCTRL_DIS_LCDIF_DIV	0
 #define BM_CLKCTRL_DIS_LCDIF_DIV	0x00001FFF
@@ -453,12 +320,7 @@
 #define HW_CLKCTRL_ETM	(0x00000130)
 
 #define BM_CLKCTRL_ETM_CLKGATE	0x80000000
-#define BM_CLKCTRL_ETM_RSRVD2	0x40000000
 #define BM_CLKCTRL_ETM_BUSY	0x20000000
-#define BP_CLKCTRL_ETM_RSRVD1	8
-#define BM_CLKCTRL_ETM_RSRVD1	0x1FFFFF00
-#define BF_CLKCTRL_ETM_RSRVD1(v)  \
-		(((v) << 8) & BM_CLKCTRL_ETM_RSRVD1)
 #define BM_CLKCTRL_ETM_DIV_FRAC_EN	0x00000080
 #define BP_CLKCTRL_ETM_DIV	0
 #define BM_CLKCTRL_ETM_DIV	0x0000007F
@@ -471,7 +333,6 @@
 #define BP_CLKCTRL_ENET_DISABLE	30
 #define BM_CLKCTRL_ENET_DISABLE	0x40000000
 #define BM_CLKCTRL_ENET_STATUS	0x20000000
-#define BM_CLKCTRL_ENET_RSRVD1	0x10000000
 #define BM_CLKCTRL_ENET_BUSY_TIME	0x08000000
 #define BP_CLKCTRL_ENET_DIV_TIME	21
 #define BM_CLKCTRL_ENET_DIV_TIME	0x07E00000
@@ -493,37 +354,23 @@
 #define BM_CLKCTRL_ENET_CLK_OUT_EN	0x00040000
 #define BM_CLKCTRL_ENET_RESET_BY_SW_CHIP	0x00020000
 #define BM_CLKCTRL_ENET_RESET_BY_SW	0x00010000
-#define BP_CLKCTRL_ENET_RSRVD0	0
-#define BM_CLKCTRL_ENET_RSRVD0	0x0000FFFF
-#define BF_CLKCTRL_ENET_RSRVD0(v)  \
-		(((v) << 0) & BM_CLKCTRL_ENET_RSRVD0)
 
 #define HW_CLKCTRL_HSADC	(0x00000150)
 
-#define BM_CLKCTRL_HSADC_RSRVD2	0x80000000
 #define BM_CLKCTRL_HSADC_RESETB	0x40000000
 #define BP_CLKCTRL_HSADC_FREQDIV	28
 #define BM_CLKCTRL_HSADC_FREQDIV	0x30000000
 #define BF_CLKCTRL_HSADC_FREQDIV(v)  \
 		(((v) << 28) & BM_CLKCTRL_HSADC_FREQDIV)
-#define BP_CLKCTRL_HSADC_RSRVD1	0
-#define BM_CLKCTRL_HSADC_RSRVD1	0x0FFFFFFF
-#define BF_CLKCTRL_HSADC_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_HSADC_RSRVD1)
 
 #define HW_CLKCTRL_FLEXCAN	(0x00000160)
 
-#define BM_CLKCTRL_FLEXCAN_RSRVD2	0x80000000
 #define BP_CLKCTRL_FLEXCAN_STOP_CAN0	30
 #define BM_CLKCTRL_FLEXCAN_STOP_CAN0	0x40000000
 #define BM_CLKCTRL_FLEXCAN_CAN0_STATUS	0x20000000
 #define BP_CLKCTRL_FLEXCAN_STOP_CAN1	28
 #define BM_CLKCTRL_FLEXCAN_STOP_CAN1	0x10000000
 #define BM_CLKCTRL_FLEXCAN_CAN1_STATUS	0x08000000
-#define BP_CLKCTRL_FLEXCAN_RSRVD1	0
-#define BM_CLKCTRL_FLEXCAN_RSRVD1	0x07FFFFFF
-#define BF_CLKCTRL_FLEXCAN_RSRVD1(v)  \
-		(((v) << 0) & BM_CLKCTRL_FLEXCAN_RSRVD1)
 
 #define HW_CLKCTRL_FRAC0	(0x000001b0)
 #define HW_CLKCTRL_FRAC0_SET	(0x000001b4)
@@ -564,10 +411,6 @@
 #define HW_CLKCTRL_FRAC1_CLR	(0x000001c8)
 #define HW_CLKCTRL_FRAC1_TOG	(0x000001cc)
 
-#define BP_CLKCTRL_FRAC1_RSRVD2	24
-#define BM_CLKCTRL_FRAC1_RSRVD2	0xFF000000
-#define BF_CLKCTRL_FRAC1_RSRVD2(v) \
-		(((v) << 24) & BM_CLKCTRL_FRAC1_RSRVD2)
 #define BP_CLKCTRL_FRAC1_CLKGATEGPMI	23
 #define BM_CLKCTRL_FRAC1_CLKGATEGPMI	0x00800000
 #define BM_CLKCTRL_FRAC1_GPMI_STABLE	0x00400000
@@ -595,22 +438,10 @@
 #define HW_CLKCTRL_CLKSEQ_CLR	(0x000001d8)
 #define HW_CLKCTRL_CLKSEQ_TOG	(0x000001dc)
 
-#define BP_CLKCTRL_CLKSEQ_RSRVD0	19
-#define BM_CLKCTRL_CLKSEQ_RSRVD0	0xFFF80000
-#define BF_CLKCTRL_CLKSEQ_RSRVD0(v) \
-		(((v) << 19) & BM_CLKCTRL_CLKSEQ_RSRVD0)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_CPU	0x00040000
-#define BP_CLKCTRL_CLKSEQ_RSRVD1	15
-#define BM_CLKCTRL_CLKSEQ_RSRVD1	0x00038000
-#define BF_CLKCTRL_CLKSEQ_RSRVD1(v)  \
-		(((v) << 15) & BM_CLKCTRL_CLKSEQ_RSRVD1)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF	0x00004000
 #define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__BYPASS 0x1
 #define BV_CLKCTRL_CLKSEQ_BYPASS_DIS_LCDIF__PFD    0x0
-#define BP_CLKCTRL_CLKSEQ_RSRVD2	9
-#define BM_CLKCTRL_CLKSEQ_RSRVD2	0x00003E00
-#define BF_CLKCTRL_CLKSEQ_RSRVD2(v)  \
-		(((v) << 9) & BM_CLKCTRL_CLKSEQ_RSRVD2)
 #define BM_CLKCTRL_CLKSEQ_BYPASS_ETM	0x00000100
 #define BM_CLKCTRL_CLKSEQ_BYPASS_EMI	0x00000080
 #define BM_CLKCTRL_CLKSEQ_BYPASS_SSP3	0x00000040
@@ -623,10 +454,6 @@
 
 #define HW_CLKCTRL_RESET	(0x000001e0)
 
-#define BP_CLKCTRL_RESET_RSRVD	6
-#define BM_CLKCTRL_RESET_RSRVD	0xFFFFFFC0
-#define BF_CLKCTRL_RESET_RSRVD(v) \
-		(((v) << 6) & BM_CLKCTRL_RESET_RSRVD)
 #define BM_CLKCTRL_RESET_WDOG_POR_DISABLE	0x00000020
 #define BM_CLKCTRL_RESET_EXTERNAL_RESET_ENABLE	0x00000010
 #define BM_CLKCTRL_RESET_THERMAL_RESET_ENABLE	0x00000008
@@ -640,10 +467,6 @@
 #define BM_CLKCTRL_STATUS_CPU_LIMIT	0xC0000000
 #define BF_CLKCTRL_STATUS_CPU_LIMIT(v) \
 		(((v) << 30) & BM_CLKCTRL_STATUS_CPU_LIMIT)
-#define BP_CLKCTRL_STATUS_RSRVD	0
-#define BM_CLKCTRL_STATUS_RSRVD	0x3FFFFFFF
-#define BF_CLKCTRL_STATUS_RSRVD(v)  \
-		(((v) << 0) & BM_CLKCTRL_STATUS_RSRVD)
 
 #define HW_CLKCTRL_VERSION	(0x00000200)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-mxs/system.c linux-libre-2.6.39-gnu/arch/arm/mach-mxs/system.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-mxs/system.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-mxs/system.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/module.h>
 
 #include <asm/proc-fns.h>
 #include <asm/system.h>
@@ -135,3 +136,4 @@
 	pr_err("%s(%p): module reset timeout\n", __func__, reset_addr);
 	return -ETIMEDOUT;
 }
+EXPORT_SYMBOL(mxs_reset_block);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-netx/generic.c linux-libre-2.6.39-gnu/arch/arm/mach-netx/generic.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-netx/generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-netx/generic.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,13 +171,13 @@
 	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);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &netx_hif_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
 	writel(NETX_DPMAS_INT_EN_GLB_EN, NETX_DPMAS_INT_EN);
-	set_irq_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
+	irq_set_chained_handler(NETX_IRQ_HIF, netx_hif_demux_handler);
 }
 
 static int __init netx_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-netx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-netx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-netx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-netx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET UL(0x80000000)
+#define PLAT_PHYS_OFFSET UL(0x80000000)
 
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-nomadik/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-nomadik/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-nomadik/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-nomadik/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/board-a9m9750dev.c linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/board-a9m9750dev.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/board-a9m9750dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/board-a9m9750dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,8 +107,8 @@
 				__func__);
 
 	for (i = FPGA_IRQ(0); i <= FPGA_IRQ(7); ++i) {
-		set_irq_chip(i, &a9m9750dev_fpga_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &a9m9750dev_fpga_chip,
+					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
@@ -118,8 +118,8 @@
 	REGSET(eic, SYS_EIC, LVEDG, LEVEL);
 	__raw_writel(eic, SYS_EIC(2));
 
-	set_irq_chained_handler(IRQ_NS9XXX_EXT2,
-			a9m9750dev_fpga_demux_handler);
+	irq_set_chained_handler(IRQ_NS9XXX_EXT2,
+				a9m9750dev_fpga_demux_handler);
 }
 
 void __init board_a9m9750dev_init_machine(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/include/mach/board.h linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/include/mach/board.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/include/mach/board.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/include/mach/board.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,12 +14,10 @@
 #include <asm/mach-types.h>
 
 #define board_is_a9m9750dev()	(0			\
-		|| machine_is_cc9p9360dev()		\
 		|| machine_is_cc9p9750dev()		\
 		)
 
 #define board_is_a9mvali()	(0			\
-		|| machine_is_cc9p9360val() 		\
 		|| machine_is_cc9p9750val()		\
 		)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,6 @@
 #define NS9XXX_CS2STAT_LENGTH	UL(0x1000)
 #define NS9XXX_CS3STAT_LENGTH	UL(0x1000)
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/include/mach/module.h linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/include/mach/module.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/include/mach/module.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/include/mach/module.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,6 @@
 		)
 
 #define module_is_cc9c()	(0			\
-		|| machine_is_cc9c()			\
 		)
 
 #define module_is_cc9p9210()	(0			\
@@ -32,21 +31,17 @@
 		)
 
 #define module_is_cc9p9360()	(0			\
-		|| machine_is_a9m9360()			\
 		|| machine_is_cc9p9360dev()		\
 		|| machine_is_cc9p9360js()		\
-		|| machine_is_cc9p9360val()		\
 		)
 
 #define module_is_cc9p9750()	(0			\
 		|| machine_is_a9m9750()			\
-		|| machine_is_cc9p9750dev()		\
 		|| machine_is_cc9p9750js()		\
 		|| machine_is_cc9p9750val()		\
 		)
 
 #define module_is_ccw9c()	(0			\
-		|| machine_is_ccw9c()			\
 		)
 
 #define module_is_inc20otter()	(0			\
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ns9xxx/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ns9xxx/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,17 +31,11 @@
 	__raw_writel(ic, SYS_IC(prio / 4));
 }
 
-static void ns9xxx_ack_irq(struct irq_data *d)
+static void ns9xxx_eoi_irq(struct irq_data *d)
 {
 	__raw_writel(0, SYS_ISRADDR);
 }
 
-static void ns9xxx_maskack_irq(struct irq_data *d)
-{
-	ns9xxx_mask_irq(d);
-	ns9xxx_ack_irq(d);
-}
-
 static void ns9xxx_unmask_irq(struct irq_data *d)
 {
 	/* XXX: better use cpp symbols */
@@ -52,56 +46,11 @@
 }
 
 static struct irq_chip ns9xxx_chip = {
-	.irq_ack	= ns9xxx_ack_irq,
+	.irq_eoi	= ns9xxx_eoi_irq,
 	.irq_mask	= ns9xxx_mask_irq,
-	.irq_mask_ack	= ns9xxx_maskack_irq,
 	.irq_unmask	= ns9xxx_unmask_irq,
 };
 
-#if 0
-#define handle_irq handle_level_irq
-#else
-static void handle_prio_irq(unsigned int irq, struct irq_desc *desc)
-{
-	struct irqaction *action;
-	irqreturn_t action_ret;
-
-	raw_spin_lock(&desc->lock);
-
-	BUG_ON(desc->status & IRQ_INPROGRESS);
-
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-	kstat_incr_irqs_this_cpu(irq, desc);
-
-	action = desc->action;
-	if (unlikely(!action || (desc->status & IRQ_DISABLED)))
-		goto out_mask;
-
-	desc->status |= IRQ_INPROGRESS;
-	raw_spin_unlock(&desc->lock);
-
-	action_ret = handle_IRQ_event(irq, action);
-
-	/* XXX: There is no direct way to access noirqdebug, so check
-	 * unconditionally for spurious irqs...
-	 * Maybe this function should go to kernel/irq/chip.c? */
-	note_interrupt(irq, desc, action_ret);
-
-	raw_spin_lock(&desc->lock);
-	desc->status &= ~IRQ_INPROGRESS;
-
-	if (desc->status & IRQ_DISABLED)
-out_mask:
-		desc->irq_data.chip->irq_mask(&desc->irq_data);
-
-	/* ack unconditionally to unmask lower prio irqs */
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-	raw_spin_unlock(&desc->lock);
-}
-#define handle_irq handle_prio_irq
-#endif
-
 void __init ns9xxx_init_irq(void)
 {
 	int i;
@@ -118,8 +67,8 @@
 		__raw_writel(prio2irq(i), SYS_IVA(i));
 
 	for (i = 0; i <= 31; ++i) {
-		set_irq_chip(i, &ns9xxx_chip);
-		set_irq_handler(i, handle_irq);
+		irq_set_chip_and_handler(i, &ns9xxx_chip, handle_fasteoi_irq);
 		set_irq_flags(i, IRQF_VALID);
+		irq_set_status_flags(i, IRQ_LEVEL);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-nuc93x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-nuc93x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-nuc93x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-nuc93x/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-nuc93x/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-nuc93x/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-nuc93x/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-nuc93x/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,8 +59,8 @@
 	__raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
 
 	for (irqno = IRQ_WDT; irqno <= NR_IRQS; irqno++) {
-		set_irq_chip(irqno, &nuc93x_irq_chip);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &nuc93x_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S linux-libre-2.6.39-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/ams-delta-fiq-handler.S	2011-05-19 00:06:34.000000000 -0400
@@ -79,7 +79,7 @@
 
 
 /*
- * Register useage
+ * Register usage
  * r8  - temporary
  * r9  - the driver buffer
  * r10 - temporary
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-ams-delta.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-ams-delta.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-ams-delta.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-ams-delta.c	2011-05-19 00:06:34.000000000 -0400
@@ -165,7 +165,7 @@
 	}
 };
 
-static struct omap_lcd_config ams_delta_lcd_config __initdata = {
+static struct omap_lcd_config ams_delta_lcd_config = {
 	.ctrl_name	= "internal",
 };
 
@@ -175,7 +175,7 @@
 	.pins[0]	= 2,
 };
 
-static struct omap_board_config_kernel ams_delta_config[] = {
+static struct omap_board_config_kernel ams_delta_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&ams_delta_lcd_config },
 };
 
@@ -208,14 +208,14 @@
 	.keymap_size	= ARRAY_SIZE(ams_delta_keymap),
 };
 
-static struct omap_kp_platform_data ams_delta_kp_data = {
+static struct omap_kp_platform_data ams_delta_kp_data __initdata = {
 	.rows		= 8,
 	.cols		= 8,
 	.keymap_data	= &ams_delta_keymap_data,
 	.delay		= 9,
 };
 
-static struct platform_device ams_delta_kp_device = {
+static struct platform_device ams_delta_kp_device __initdata = {
 	.name		= "omap-keypad",
 	.id		= -1,
 	.dev		= {
@@ -225,12 +225,12 @@
 	.resource	= ams_delta_kp_resources,
 };
 
-static struct platform_device ams_delta_lcd_device = {
+static struct platform_device ams_delta_lcd_device __initdata = {
 	.name	= "lcd_ams_delta",
 	.id	= -1,
 };
 
-static struct platform_device ams_delta_led_device = {
+static struct platform_device ams_delta_led_device __initdata = {
 	.name	= "ams-delta-led",
 	.id	= -1
 };
@@ -259,7 +259,7 @@
 #define ams_delta_camera_power	NULL
 #endif
 
-static struct soc_camera_link __initdata ams_delta_iclink = {
+static struct soc_camera_link ams_delta_iclink = {
 	.bus_id         = 0,	/* OMAP1 SoC camera bus */
 	.i2c_adapter_id = 1,
 	.board_info     = &ams_delta_camera_board_info[0],
@@ -267,7 +267,7 @@
 	.power		= ams_delta_camera_power,
 };
 
-static struct platform_device ams_delta_camera_device = {
+static struct platform_device ams_delta_camera_device __initdata = {
 	.name   = "soc-camera-pdrv",
 	.id     = 0,
 	.dev    = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-fsample.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-fsample.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-fsample.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-fsample.c	2011-05-19 00:06:34.000000000 -0400
@@ -287,11 +287,11 @@
 	&lcd_device,
 };
 
-static struct omap_lcd_config fsample_lcd_config __initdata = {
+static struct omap_lcd_config fsample_lcd_config = {
 	.ctrl_name	= "internal",
 };
 
-static struct omap_board_config_kernel fsample_config[] = {
+static struct omap_board_config_kernel fsample_config[] __initdata = {
 	{ OMAP_TAG_LCD,		&fsample_lcd_config },
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-h2.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-h2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-h2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-h2.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,7 +202,7 @@
 
 static const char *h2_part_probes[] = { "cmdlinepart", NULL };
 
-struct platform_nand_data h2_nand_platdata = {
+static struct platform_nand_data h2_nand_platdata = {
 	.chip	= {
 		.nr_chips		= 1,
 		.chip_offset		= 0,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-h3.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-h3.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-h3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-h3.c	2011-05-19 00:06:34.000000000 -0400
@@ -204,7 +204,7 @@
 
 static const char *part_probes[] = { "cmdlinepart", NULL };
 
-struct platform_nand_data nand_platdata = {
+static struct platform_nand_data nand_platdata = {
 	.chip	= {
 		.nr_chips		= 1,
 		.chip_offset		= 0,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-htcherald.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-htcherald.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-htcherald.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-htcherald.c	2011-05-19 00:06:34.000000000 -0400
@@ -331,7 +331,7 @@
 	},
 };
 
-struct htcpld_chip_platform_data htcpld_chips[] = {
+static struct htcpld_chip_platform_data htcpld_chips[] = {
 	[0] = {
 		.addr		= 0x03,
 		.reset		= 0x04,
@@ -366,7 +366,7 @@
 	},
 };
 
-struct htcpld_core_platform_data htcpld_pfdata = {
+static struct htcpld_core_platform_data htcpld_pfdata = {
 	.int_reset_gpio_hi = HTCPLD_GPIO_INT_RESET_HI,
 	.int_reset_gpio_lo = HTCPLD_GPIO_INT_RESET_LO,
 	.i2c_adapter_id	   = 1,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-innovator.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-innovator.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-innovator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-innovator.c	2011-05-19 00:06:34.000000000 -0400
@@ -365,7 +365,7 @@
 
 static struct omap_mmc_platform_data *mmc_data[OMAP16XX_NR_MMC];
 
-void __init innovator_mmc_init(void)
+static void __init innovator_mmc_init(void)
 {
 	mmc_data[0] = &mmc1_data;
 	omap1_init_mmc(mmc_data, OMAP15XX_NR_MMC);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-nokia770.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-nokia770.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-nokia770.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-nokia770.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,7 @@
 	.shutdown = mipid_shutdown,
 };
 
-static void mipid_dev_init(void)
+static void __init mipid_dev_init(void)
 {
 	const struct omap_lcd_config *conf;
 
@@ -126,7 +126,7 @@
 	}
 }
 
-static void ads7846_dev_init(void)
+static void __init ads7846_dev_init(void)
 {
 	if (gpio_request(ADS7846_PENDOWN_GPIO, "ADS7846 pendown") < 0)
 		printk(KERN_ERR "can't get ads7846 pen down GPIO\n");
@@ -170,7 +170,7 @@
 	.te_connected		= 1,
 };
 
-static void hwa742_dev_init(void)
+static void __init hwa742_dev_init(void)
 {
 	clk_add_alias("hwa_sys_ck", NULL, "bclk", NULL);
 	omapfb_set_ctrl_platform_data(&nokia770_hwa742_platform_data);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-osk.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-osk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-osk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-osk.c	2011-05-19 00:06:34.000000000 -0400
@@ -276,7 +276,7 @@
 		return;
 	}
 	/* the CF I/O IRQ is really active-low */
-	set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
+	irq_set_irq_type(gpio_to_irq(62), IRQ_TYPE_EDGE_FALLING);
 }
 
 static void __init osk_init_irq(void)
@@ -482,7 +482,7 @@
 	omap_cfg_reg(P20_1610_GPIO4);	/* PENIRQ */
 	gpio_request(4, "ts_int");
 	gpio_direction_input(4);
-	set_irq_type(gpio_to_irq(4), IRQ_TYPE_EDGE_FALLING);
+	irq_set_irq_type(gpio_to_irq(4), IRQ_TYPE_EDGE_FALLING);
 
 	spi_register_board_info(mistral_boardinfo,
 			ARRAY_SIZE(mistral_boardinfo));
@@ -500,7 +500,7 @@
 		int irq = gpio_to_irq(OMAP_MPUIO(2));
 
 		gpio_direction_input(OMAP_MPUIO(2));
-		set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+		irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
 #ifdef	CONFIG_PM
 		/* share the IRQ in case someone wants to use the
 		 * button for more than wakeup from system sleep.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-palmte.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-palmte.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-palmte.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-palmte.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,19 +230,6 @@
 	},
 };
 
-static void palmte_headphones_detect(void *data, int state)
-{
-	if (state) {
-		/* Headphones connected, disable speaker */
-		gpio_set_value(PALMTE_SPEAKER_GPIO, 0);
-		printk(KERN_INFO "PM: speaker off\n");
-	} else {
-		/* Headphones unplugged, re-enable speaker */
-		gpio_set_value(PALMTE_SPEAKER_GPIO, 1);
-		printk(KERN_INFO "PM: speaker on\n");
-	}
-}
-
 static void __init palmte_misc_gpio_setup(void)
 {
 	/* Set TSC2102 PINTDAV pin as input (used by TSC2102 driver) */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-palmz71.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-palmz71.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-palmz71.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-palmz71.c	2011-05-19 00:06:34.000000000 -0400
@@ -256,12 +256,12 @@
 {
 	if (gpio_get_value(PALMZ71_USBDETECT_GPIO)) {
 		printk(KERN_INFO "PM: Power cable connected\n");
-		set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
-				IRQ_TYPE_EDGE_FALLING);
+		irq_set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+				 IRQ_TYPE_EDGE_FALLING);
 	} else {
 		printk(KERN_INFO "PM: Power cable disconnected\n");
-		set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
-				IRQ_TYPE_EDGE_RISING);
+		irq_set_irq_type(gpio_to_irq(PALMZ71_USBDETECT_GPIO),
+				 IRQ_TYPE_EDGE_RISING);
 	}
 	return IRQ_HANDLED;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-sx1.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-sx1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-sx1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-sx1.c	2011-05-19 00:06:34.000000000 -0400
@@ -399,7 +399,7 @@
 	sx1_mmc_init();
 
 	/* turn on USB power */
-	/* sx1_setusbpower(1); cant do it here because i2c is not ready */
+	/* sx1_setusbpower(1); can't do it here because i2c is not ready */
 	gpio_request(1, "A_IRDA_OFF");
 	gpio_request(11, "A_SWITCH");
 	gpio_request(15, "A_USB_ON");
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-voiceblue.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-voiceblue.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/board-voiceblue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/board-voiceblue.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,10 +26,12 @@
 #include <linux/smc91x.h>
 
 #include <mach/hardware.h>
+#include <mach/system.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
+#include <plat/board-voiceblue.h>
 #include <plat/common.h>
 #include <mach/gpio.h>
 #include <plat/flash.h>
@@ -163,52 +165,6 @@
 	omap_init_irq();
 }
 
-static void __init voiceblue_init(void)
-{
-	/* mux pins for uarts */
-	omap_cfg_reg(UART1_TX);
-	omap_cfg_reg(UART1_RTS);
-	omap_cfg_reg(UART2_TX);
-	omap_cfg_reg(UART2_RTS);
-	omap_cfg_reg(UART3_TX);
-	omap_cfg_reg(UART3_RX);
-
-	/* Watchdog */
-	gpio_request(0, "Watchdog");
-	/* smc91x reset */
-	gpio_request(7, "SMC91x reset");
-	gpio_direction_output(7, 1);
-	udelay(2);	/* wait at least 100ns */
-	gpio_set_value(7, 0);
-	mdelay(50);	/* 50ms until PHY ready */
-	/* smc91x interrupt pin */
-	gpio_request(8, "SMC91x irq");
-	/* 16C554 reset*/
-	gpio_request(6, "16C554 reset");
-	gpio_direction_output(6, 0);
-	/* 16C554 interrupt pins */
-	gpio_request(12, "16C554 irq");
-	gpio_request(13, "16C554 irq");
-	gpio_request(14, "16C554 irq");
-	gpio_request(15, "16C554 irq");
-	set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
-
-	platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
-	omap_board_config = voiceblue_config;
-	omap_board_config_size = ARRAY_SIZE(voiceblue_config);
-	omap_serial_init();
-	omap1_usb_init(&voiceblue_usb_config);
-	omap_register_i2c_bus(1, 100, NULL, 0);
-
-	/* There is a good chance board is going up, so enable power LED
-	 * (it is connected through invertor) */
-	omap_writeb(0x00, OMAP_LPG1_LCR);
-	omap_writeb(0x00, OMAP_LPG1_PMR);	/* Disable clock */
-}
-
 static void __init voiceblue_map_io(void)
 {
 	omap1_map_common_io();
@@ -275,8 +231,17 @@
 	gpio_set_value(0, wdt_gpio_state);
 }
 
-void voiceblue_reset(void)
+static void voiceblue_reset(char mode, const char *cmd)
 {
+	/*
+	 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
+	 * "Global Software Reset Affects Traffic Controller Frequency".
+	 */
+	if (cpu_is_omap5912()) {
+		omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL);
+		omap_writew(0x8, ARM_RSTCT1);
+	}
+
 	set_bit(MACHINE_REBOOT, &machine_state);
 	voiceblue_wdt_enable();
 	while (1) ;
@@ -286,6 +251,54 @@
 EXPORT_SYMBOL(voiceblue_wdt_disable);
 EXPORT_SYMBOL(voiceblue_wdt_ping);
 
+static void __init voiceblue_init(void)
+{
+	/* mux pins for uarts */
+	omap_cfg_reg(UART1_TX);
+	omap_cfg_reg(UART1_RTS);
+	omap_cfg_reg(UART2_TX);
+	omap_cfg_reg(UART2_RTS);
+	omap_cfg_reg(UART3_TX);
+	omap_cfg_reg(UART3_RX);
+
+	/* Watchdog */
+	gpio_request(0, "Watchdog");
+	/* smc91x reset */
+	gpio_request(7, "SMC91x reset");
+	gpio_direction_output(7, 1);
+	udelay(2);	/* wait at least 100ns */
+	gpio_set_value(7, 0);
+	mdelay(50);	/* 50ms until PHY ready */
+	/* smc91x interrupt pin */
+	gpio_request(8, "SMC91x irq");
+	/* 16C554 reset*/
+	gpio_request(6, "16C554 reset");
+	gpio_direction_output(6, 0);
+	/* 16C554 interrupt pins */
+	gpio_request(12, "16C554 irq");
+	gpio_request(13, "16C554 irq");
+	gpio_request(14, "16C554 irq");
+	gpio_request(15, "16C554 irq");
+	irq_set_irq_type(gpio_to_irq(12), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(14), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(15), IRQ_TYPE_EDGE_RISING);
+
+	platform_add_devices(voiceblue_devices, ARRAY_SIZE(voiceblue_devices));
+	omap_board_config = voiceblue_config;
+	omap_board_config_size = ARRAY_SIZE(voiceblue_config);
+	omap_serial_init();
+	omap1_usb_init(&voiceblue_usb_config);
+	omap_register_i2c_bus(1, 100, NULL, 0);
+
+	/* There is a good chance board is going up, so enable power LED
+	 * (it is connected through invertor) */
+	omap_writeb(0x00, OMAP_LPG1_LCR);
+	omap_writeb(0x00, OMAP_LPG1_PMR);	/* Disable clock */
+
+	arch_reset = voiceblue_reset;
+}
+
 MACHINE_START(VOICEBLUE, "VoiceBlue OMAP5910")
 	/* Maintainer: Ladislav Michl <michl@2n.cz> */
 	.boot_params	= 0x10000100,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -281,7 +281,7 @@
  * Claiming GPIOs, and setting their direction and initial values, is the
  * responsibility of the device drivers.  So is responding to probe().
  *
- * Board-specific knowlege like creating devices or pin setup is to be
+ * Board-specific knowledge like creating devices or pin setup is to be
  * kept out of drivers as much as possible.  In particular, pin setup
  * may be handled by the boot loader, and drivers should expect it will
  * normally have been done by the time they're probed.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/fpga.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/fpga.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/fpga.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/fpga.c	2011-05-19 00:06:34.000000000 -0400
@@ -156,17 +156,17 @@
 			 * The touchscreen interrupt is level-sensitive, so
 			 * we'll use the regular mask_ack routine for it.
 			 */
-			set_irq_chip(i, &omap_fpga_irq_ack);
+			irq_set_chip(i, &omap_fpga_irq_ack);
 		}
 		else {
 			/*
 			 * All FPGA interrupts except the touchscreen are
 			 * edge-sensitive, so we won't mask them.
 			 */
-			set_irq_chip(i, &omap_fpga_irq);
+			irq_set_chip(i, &omap_fpga_irq);
 		}
 
-		set_irq_handler(i, handle_edge_irq);
+		irq_set_handler(i, handle_edge_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
@@ -183,6 +183,6 @@
 		return;
 	}
 	gpio_direction_input(13);
-	set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
-	set_irq_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
+	irq_set_irq_type(gpio_to_irq(13), IRQ_TYPE_EDGE_RISING);
+	irq_set_chained_handler(OMAP1510_INT_FPGA, innovator_fpga_IRQ_demux);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h linux-libre-2.6.39-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/include/mach/ams-delta-fiq.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #endif
 
 /*
- * These are the offsets from the begining of the fiq_buffer. They are put here
+ * These are the offsets from the beginning of the fiq_buffer. They are put here
  * since the buffer and header need to be accessed by drivers servicing devices
  * which generate GPIO interrupts - e.g. keyboard, modem, hook switch.
  */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/include/mach/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,9 @@
 
 #include <plat/serial.h>
 
+#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 omap_uart_phys:	.word	0x0
 omap_uart_virt:	.word	0x0
@@ -33,7 +36,7 @@
 		/* Use omap_uart_phys/virt if already configured */
 9:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rp, =omap_uart_phys	@ MMU enabled
 		add	\rv, \rp, #4		@ omap_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -46,7 +49,7 @@
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =__phys_to_virt(OMAP_UART_INFO)	@ MMU enabled
+		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
 		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
@@ -73,7 +76,7 @@
 98:		add	\rp, \rp, #0xff000000	@ phys base
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		sub	\rp, \rp, #0xff000000	@ phys base
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,8 +230,8 @@
 			irq_trigger = irq_banks[i].trigger_map >> IRQ_BIT(j);
 			omap_irq_set_cfg(j, 0, 0, irq_trigger);
 
-			set_irq_chip(j, &omap_irq_chip);
-			set_irq_handler(j, handle_level_irq);
+			irq_set_chip_and_handler(j, &omap_irq_chip,
+						 handle_level_irq);
 			set_irq_flags(j, IRQF_VALID);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-omap1/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 
 # Common support
 obj-y := io.o id.o sram.o time.o irq.o mux.o flash.o serial.o devices.o dma.o
-obj-y += clock.o clock_data.o opp_data.o
+obj-y += clock.o clock_data.o opp_data.o reset.o
 
 obj-$(CONFIG_OMAP_MCBSP) += mcbsp.o
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/mcbsp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/mcbsp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/mcbsp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/mcbsp.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,6 +10,7 @@
  *
  * Multichannel mode not supported.
  */
+#include <linux/ioport.h>
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/clk.h>
@@ -78,100 +79,294 @@
 };
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+struct resource omap7xx_mcbsp_res[][6] = {
+	{
+		{
+			.start = OMAP7XX_MCBSP1_BASE,
+			.end   = OMAP7XX_MCBSP1_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_7XX_McBSP1RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_7XX_McBSP1TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP1_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP1_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP7XX_MCBSP2_BASE,
+			.end   = OMAP7XX_MCBSP2_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_7XX_McBSP2RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_7XX_McBSP2TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP3_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP3_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+};
+
+#define omap7xx_mcbsp_res_0		omap7xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap7xx_mcbsp_pdata[] = {
 	{
-		.phys_base	= OMAP7XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
-		.rx_irq		= INT_7XX_McBSP1RX,
-		.tx_irq		= INT_7XX_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP7XX_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
-		.rx_irq		= INT_7XX_McBSP2RX,
-		.tx_irq		= INT_7XX_McBSP2TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 };
-#define OMAP7XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap7xx_mcbsp_pdata)
-#define OMAP7XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
+#define OMAP7XX_MCBSP_RES_SZ		ARRAY_SIZE(omap7xx_mcbsp_res[1])
+#define OMAP7XX_MCBSP_COUNT		ARRAY_SIZE(omap7xx_mcbsp_res)
 #else
+#define omap7xx_mcbsp_res_0		NULL
 #define omap7xx_mcbsp_pdata		NULL
-#define OMAP7XX_MCBSP_PDATA_SZ		0
-#define OMAP7XX_MCBSP_REG_NUM		0
+#define OMAP7XX_MCBSP_RES_SZ		0
+#define OMAP7XX_MCBSP_COUNT		0
 #endif
 
 #ifdef CONFIG_ARCH_OMAP15XX
+struct resource omap15xx_mcbsp_res[][6] = {
+	{
+		{
+			.start = OMAP1510_MCBSP1_BASE,
+			.end   = OMAP1510_MCBSP1_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP1RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP1TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP1_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP1_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1510_MCBSP2_BASE,
+			.end   = OMAP1510_MCBSP2_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_1510_SPI_RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_1510_SPI_TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP2_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP2_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1510_MCBSP3_BASE,
+			.end   = OMAP1510_MCBSP3_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP3RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP3TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP3_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP3_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+};
+
+#define omap15xx_mcbsp_res_0		omap15xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap15xx_mcbsp_pdata[] = {
 	{
-		.phys_base	= OMAP1510_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
-		.rx_irq		= INT_McBSP1RX,
-		.tx_irq		= INT_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1510_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
-		.rx_irq		= INT_1510_SPI_RX,
-		.tx_irq		= INT_1510_SPI_TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1510_MCBSP3_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
-		.rx_irq		= INT_McBSP3RX,
-		.tx_irq		= INT_McBSP3TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 };
-#define OMAP15XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap15xx_mcbsp_pdata)
-#define OMAP15XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
+#define OMAP15XX_MCBSP_RES_SZ		ARRAY_SIZE(omap15xx_mcbsp_res[1])
+#define OMAP15XX_MCBSP_COUNT		ARRAY_SIZE(omap15xx_mcbsp_res)
 #else
+#define omap15xx_mcbsp_res_0		NULL
 #define omap15xx_mcbsp_pdata		NULL
-#define OMAP15XX_MCBSP_PDATA_SZ		0
-#define OMAP15XX_MCBSP_REG_NUM		0
+#define OMAP15XX_MCBSP_RES_SZ		0
+#define OMAP15XX_MCBSP_COUNT		0
 #endif
 
 #ifdef CONFIG_ARCH_OMAP16XX
+struct resource omap16xx_mcbsp_res[][6] = {
+	{
+		{
+			.start = OMAP1610_MCBSP1_BASE,
+			.end   = OMAP1610_MCBSP1_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP1RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP1TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP1_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP1_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1610_MCBSP2_BASE,
+			.end   = OMAP1610_MCBSP2_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_1610_McBSP2_RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_1610_McBSP2_TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP2_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP2_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+	{
+		{
+			.start = OMAP1610_MCBSP3_BASE,
+			.end   = OMAP1610_MCBSP3_BASE + SZ_256,
+			.flags = IORESOURCE_MEM,
+		},
+		{
+			.name  = "rx",
+			.start = INT_McBSP3RX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "tx",
+			.start = INT_McBSP3TX,
+			.flags = IORESOURCE_IRQ,
+		},
+		{
+			.name  = "rx",
+			.start = OMAP_DMA_MCBSP3_RX,
+			.flags = IORESOURCE_DMA,
+		},
+		{
+			.name  = "tx",
+			.start = OMAP_DMA_MCBSP3_TX,
+			.flags = IORESOURCE_DMA,
+		},
+	},
+};
+
+#define omap16xx_mcbsp_res_0		omap16xx_mcbsp_res[0]
+
 static struct omap_mcbsp_platform_data omap16xx_mcbsp_pdata[] = {
 	{
-		.phys_base	= OMAP1610_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP1_TX,
-		.rx_irq		= INT_McBSP1RX,
-		.tx_irq		= INT_McBSP1TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1610_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP2_TX,
-		.rx_irq		= INT_1610_McBSP2_RX,
-		.tx_irq		= INT_1610_McBSP2_TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 	{
-		.phys_base	= OMAP1610_MCBSP3_BASE,
-		.dma_rx_sync	= OMAP_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP_DMA_MCBSP3_TX,
-		.rx_irq		= INT_McBSP3RX,
-		.tx_irq		= INT_McBSP3TX,
 		.ops		= &omap1_mcbsp_ops,
 	},
 };
-#define OMAP16XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap16xx_mcbsp_pdata)
-#define OMAP16XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_XCERH / sizeof(u16) + 1)
+#define OMAP16XX_MCBSP_RES_SZ		ARRAY_SIZE(omap16xx_mcbsp_res[1])
+#define OMAP16XX_MCBSP_COUNT		ARRAY_SIZE(omap16xx_mcbsp_res)
 #else
+#define omap16xx_mcbsp_res_0		NULL
 #define omap16xx_mcbsp_pdata		NULL
-#define OMAP16XX_MCBSP_PDATA_SZ		0
-#define OMAP16XX_MCBSP_REG_NUM		0
+#define OMAP16XX_MCBSP_RES_SZ		0
+#define OMAP16XX_MCBSP_COUNT		0
 #endif
 
 static int __init omap1_mcbsp_init(void)
@@ -179,16 +374,12 @@
 	if (!cpu_class_is_omap1())
 		return -ENODEV;
 
-	if (cpu_is_omap7xx()) {
-		omap_mcbsp_count = OMAP7XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP7XX_MCBSP_REG_NUM * sizeof(u16);
-	} else if (cpu_is_omap15xx()) {
-		omap_mcbsp_count = OMAP15XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP15XX_MCBSP_REG_NUM * sizeof(u16);
-	} else if (cpu_is_omap16xx()) {
-		omap_mcbsp_count = OMAP16XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP16XX_MCBSP_REG_NUM * sizeof(u16);
-	}
+	if (cpu_is_omap7xx())
+		omap_mcbsp_count = OMAP7XX_MCBSP_COUNT;
+	else if (cpu_is_omap15xx())
+		omap_mcbsp_count = OMAP15XX_MCBSP_COUNT;
+	else if (cpu_is_omap16xx())
+		omap_mcbsp_count = OMAP16XX_MCBSP_COUNT;
 
 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
 								GFP_KERNEL);
@@ -196,16 +387,22 @@
 		return -ENOMEM;
 
 	if (cpu_is_omap7xx())
-		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_pdata,
-						OMAP7XX_MCBSP_PDATA_SZ);
+		omap_mcbsp_register_board_cfg(omap7xx_mcbsp_res_0,
+					OMAP7XX_MCBSP_RES_SZ,
+					omap7xx_mcbsp_pdata,
+					OMAP7XX_MCBSP_COUNT);
 
 	if (cpu_is_omap15xx())
-		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_pdata,
-						OMAP15XX_MCBSP_PDATA_SZ);
+		omap_mcbsp_register_board_cfg(omap15xx_mcbsp_res_0,
+					OMAP15XX_MCBSP_RES_SZ,
+					omap15xx_mcbsp_pdata,
+					OMAP15XX_MCBSP_COUNT);
 
 	if (cpu_is_omap16xx())
-		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_pdata,
-						OMAP16XX_MCBSP_PDATA_SZ);
+		omap_mcbsp_register_board_cfg(omap16xx_mcbsp_res_0,
+					OMAP16XX_MCBSP_RES_SZ,
+					omap16xx_mcbsp_pdata,
+					OMAP16XX_MCBSP_COUNT);
 
 	return omap_mcbsp_init();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/pm.h linux-libre-2.6.39-gnu/arch/arm/mach-omap1/pm.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/pm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/pm.h	2011-05-19 00:06:34.000000000 -0400
@@ -123,9 +123,9 @@
 extern void omap1_pm_idle(void);
 extern void omap1_pm_suspend(void);
 
-extern void omap7xx_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 omap7xx_cpu_suspend(unsigned long, unsigned long);
+extern void omap1510_cpu_suspend(unsigned long, unsigned long);
+extern void omap1610_cpu_suspend(unsigned long, unsigned long);
 extern void omap7xx_idle_loop_suspend(void);
 extern void omap1510_idle_loop_suspend(void);
 extern void omap1610_idle_loop_suspend(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/reset.c linux-libre-2.6.39-gnu/arch/arm/mach-omap1/reset.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/reset.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/reset.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * OMAP1 reset support
+ */
+#include <linux/kernel.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/system.h>
+#include <plat/prcm.h>
+
+void omap1_arch_reset(char mode, const char *cmd)
+{
+	/*
+	 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
+	 * "Global Software Reset Affects Traffic Controller Frequency".
+	 */
+	if (cpu_is_omap5912()) {
+		omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4), DPLL_CTL);
+		omap_writew(0x8, ARM_RSTCT1);
+	}
+
+	omap_writew(1, ARM_RSTCT1);
+}
+
+void (*arch_reset)(char, const char *) = omap1_arch_reset;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/sleep.S linux-libre-2.6.39-gnu/arch/arm/mach-omap1/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/sleep.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,7 @@
  */
 
 #if defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+	.align	3
 ENTRY(omap7xx_cpu_suspend)
 
 	@ save registers on stack
@@ -137,6 +138,7 @@
 #endif /* CONFIG_ARCH_OMAP730 || CONFIG_ARCH_OMAP850 */
 
 #ifdef CONFIG_ARCH_OMAP15XX
+	.align	3
 ENTRY(omap1510_cpu_suspend)
 
 	@ save registers on stack
@@ -211,6 +213,7 @@
 #endif /* CONFIG_ARCH_OMAP15XX */
 
 #if defined(CONFIG_ARCH_OMAP16XX)
+	.align	3
 ENTRY(omap1610_cpu_suspend)
 
 	@ save registers on stack
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap1/sram.S linux-libre-2.6.39-gnu/arch/arm/mach-omap1/sram.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap1/sram.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap1/sram.S	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 /*
  * Reprograms ULPD and CKCTL.
  */
+	.align	3
 ENTRY(omap1_sram_reprogram_clock)
 	stmfd	sp!, {r0 - r12, lr}		@ save registers on stack
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-2430sdp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-2430sdp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-2430sdp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-2430sdp.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/mmc/host.h>
 #include <linux/delay.h>
 #include <linux/i2c/twl.h>
+#include <linux/regulator/machine.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
@@ -139,15 +140,31 @@
 	{OMAP_TAG_LCD, &sdp2430_lcd_config},
 };
 
-static void __init omap_2430sdp_init_irq(void)
+static void __init omap_2430sdp_init_early(void)
 {
-	omap_board_config = sdp2430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
+static struct regulator_consumer_supply sdp2430_vmmc1_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+/* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
+static struct regulator_init_data sdp2430_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	= ARRAY_SIZE(sdp2430_vmmc1_supplies),
+	.consumer_supplies	= &sdp2430_vmmc1_supplies[0],
+};
+
 static struct twl4030_gpio_platform_data sdp2430_gpio_data = {
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
@@ -160,6 +177,7 @@
 
 	/* platform_data for children goes here */
 	.gpio		= &sdp2430_gpio_data,
+	.vmmc1		= &sdp2430_vmmc1,
 };
 
 static struct i2c_board_info __initdata sdp2430_i2c_boardinfo[] = {
@@ -226,6 +244,9 @@
 
 	omap2430_mux_init(board_mux, OMAP_PACKAGE_ZAC);
 
+	omap_board_config = sdp2430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp2430_config);
+
 	omap2430_i2c_init();
 
 	platform_add_devices(sdp2430_devices, ARRAY_SIZE(sdp2430_devices));
@@ -253,9 +274,10 @@
 MACHINE_START(OMAP_2430SDP, "OMAP2430 sdp2430 board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_2430sdp_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_2430sdp_init_irq,
+	.map_io		= omap_2430sdp_map_io,
+	.init_early	= omap_2430sdp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_2430sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-3430sdp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-3430sdp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-3430sdp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-3430sdp.c	2011-05-19 00:06:34.000000000 -0400
@@ -307,34 +307,13 @@
 	.default_device	= &sdp3430_lcd_device,
 };
 
-static struct platform_device sdp3430_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &sdp3430_dss_data,
-	},
-};
-
-static struct regulator_consumer_supply sdp3430_vdda_dac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &sdp3430_dss_device.dev,
-};
-
-static struct platform_device *sdp3430_devices[] __initdata = {
-	&sdp3430_dss_device,
-};
-
 static struct omap_board_config_kernel sdp3430_config[] __initdata = {
 };
 
-static void __init omap_3430sdp_init_irq(void)
+static void __init omap_3430sdp_init_early(void)
 {
-	omap_board_config = sdp3430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
-	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(hyb18m512160af6_sdrc_params, NULL);
-	omap_init_irq();
 }
 
 static int sdp3430_batt_table[] = {
@@ -370,18 +349,6 @@
 	{}	/* Terminator */
 };
 
-static struct regulator_consumer_supply sdp3430_vmmc1_supply = {
-	.supply			= "vmmc",
-};
-
-static struct regulator_consumer_supply sdp3430_vsim_supply = {
-	.supply			= "vmmc_aux",
-};
-
-static struct regulator_consumer_supply sdp3430_vmmc2_supply = {
-	.supply			= "vmmc",
-};
-
 static int sdp3430_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
@@ -392,13 +359,6 @@
 	mmc[1].gpio_cd = gpio + 1;
 	omap2_hsmmc_init(mmc);
 
-	/* link regulators to MMC adapters ... we "know" the
-	 * regulators will be set up only *after* we return.
-	 */
-	sdp3430_vmmc1_supply.dev = mmc[0].dev;
-	sdp3430_vsim_supply.dev = mmc[0].dev;
-	sdp3430_vmmc2_supply.dev = mmc[1].dev;
-
 	/* gpio + 7 is "sub_lcd_en_bkl" (output/PWM1) */
 	gpio_request(gpio + 7, "sub_lcd_en_bkl");
 	gpio_direction_output(gpio + 7, 0);
@@ -427,6 +387,35 @@
 	.irq_line	= 1,
 };
 
+/* regulator consumer mappings */
+
+/* ads7846 on SPI */
+static struct regulator_consumer_supply sdp3430_vaux3_supplies[] = {
+	REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
+
+static struct regulator_consumer_supply sdp3430_vdda_dac_supplies[] = {
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
+static struct regulator_consumer_supply sdp3430_vmmc1_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0"),
+};
+
+static struct regulator_consumer_supply sdp3430_vsim_supplies[] = {
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.0"),
+};
+
+static struct regulator_consumer_supply sdp3430_vmmc2_supplies[] = {
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
+};
+
 /*
  * Apply all the fixed voltages since most versions of U-Boot
  * don't bother with that initialization.
@@ -469,6 +458,8 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies		= ARRAY_SIZE(sdp3430_vaux3_supplies),
+	.consumer_supplies		= sdp3430_vaux3_supplies,
 };
 
 /* VAUX4 for OMAP VDD_CSI2 (camera) */
@@ -495,8 +486,8 @@
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vmmc1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vmmc1_supplies),
+	.consumer_supplies	= sdp3430_vmmc1_supplies,
 };
 
 /* VMMC2 for MMC2 card */
@@ -510,8 +501,8 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vmmc2_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vmmc2_supplies),
+	.consumer_supplies	= sdp3430_vmmc2_supplies,
 };
 
 /* VSIM for OMAP VDD_MMC1A (i/o for DAT4..DAT7) */
@@ -525,8 +516,8 @@
 					| REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vsim_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vsim_supplies),
+	.consumer_supplies	= sdp3430_vsim_supplies,
 };
 
 /* VDAC for DSS driving S-Video */
@@ -540,16 +531,8 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &sdp3430_vdda_dac_supply,
-};
-
-/* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply sdp3430_vpll2_supplies[] = {
-	{
-		.supply		= "vdds_dsi",
-		.dev		= &sdp3430_dss_device.dev,
-	}
+	.num_consumer_supplies	= ARRAY_SIZE(sdp3430_vdda_dac_supplies),
+	.consumer_supplies	= sdp3430_vdda_dac_supplies,
 };
 
 static struct regulator_init_data sdp3430_vpll2 = {
@@ -567,9 +550,7 @@
 	.consumer_supplies	= sdp3430_vpll2_supplies,
 };
 
-static struct twl4030_codec_audio_data sdp3430_audio = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data sdp3430_audio;
 
 static struct twl4030_codec_data sdp3430_codec = {
 	.audio_mclk = 26000000,
@@ -653,11 +634,11 @@
 		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 57,
@@ -669,6 +650,106 @@
 static struct omap_board_mux board_mux[] __initdata = {
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial1_pads[] __initdata = {
+	/*
+	 * Note that off output enable is an active low
+	 * signal. So setting this means pin is a
+	 * input enabled in off mode
+	 */
+	OMAP_MUX_STATIC("uart1_cts.uart1_cts",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart1_rts.uart1_rts",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart1_rx.uart1_rx",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart1_tx.uart1_tx",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+			 OMAP_PIN_INPUT_PULLUP |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+			 OMAP_PIN_INPUT_PULLDOWN |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+			 OMAP_PIN_INPUT |
+			 OMAP_PIN_OFF_INPUT_PULLDOWN |
+			 OMAP_OFFOUT_EN |
+			 OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+			 OMAP_PIN_OUTPUT |
+			 OMAP_OFF_EN |
+			 OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial1_data = {
+	.id		= 0,
+	.pads		= serial1_pads,
+	.pads_cnt	= ARRAY_SIZE(serial1_pads),
+};
+
+static struct omap_board_data serial2_data = {
+	.id		= 1,
+	.pads		= serial2_pads,
+	.pads_cnt	= ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data = {
+	.id		= 2,
+	.pads		= serial3_pads,
+	.pads_cnt	= ARRAY_SIZE(serial3_pads),
+};
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init_port(&serial1_data);
+	omap_serial_init_port(&serial2_data);
+	omap_serial_init_port(&serial3_data);
+}
+#else
+#define board_mux	NULL
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
 #endif
 
 /*
@@ -800,8 +881,11 @@
 static void __init omap_3430sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = sdp3430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp3430_config);
+	omap3_pm_init_cpuidle(omap3_cpuidle_params_table);
 	omap3430_i2c_init();
-	platform_add_devices(sdp3430_devices, ARRAY_SIZE(sdp3430_devices));
+	omap_display_init(&sdp3430_dss_data);
 	if (omap_rev() > OMAP3430_REV_ES1_0)
 		ts_gpio = SDP3430_TS_GPIO_IRQ_SDPV2;
 	else
@@ -810,21 +894,22 @@
 	spi_register_board_info(sdp3430_spi_board_info,
 				ARRAY_SIZE(sdp3430_spi_board_info));
 	ads7846_dev_init();
-	omap_serial_init();
+	board_serial_init();
 	usb_musb_init(&musb_board_data);
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_3430);
+	board_flash_init(sdp_flash_partitions, chip_sel_3430, 0);
 	sdp3430_display_init();
 	enable_board_wakeup_source();
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(OMAP_3430SDP, "OMAP3430 3430SDP board")
 	/* Maintainer: Syed Khasim - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_3430sdp_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_3430sdp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_3430sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-3630sdp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-3630sdp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-3630sdp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-3630sdp.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -54,11 +55,11 @@
 		OMAP_WAKEUP_EN | OMAP_PIN_INPUT_PULLUP);
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 126,
@@ -69,14 +70,11 @@
 static struct omap_board_config_kernel sdp_config[] __initdata = {
 };
 
-static void __init omap_sdp_init_irq(void)
+static void __init omap_sdp_init_early(void)
 {
-	omap_board_config = sdp_config;
-	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
 				  h8mbx00u0mer0em_sdrc_params);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -206,19 +204,22 @@
 static void __init omap_sdp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
+	omap_board_config = sdp_config;
+	omap_board_config_size = ARRAY_SIZE(sdp_config);
 	zoom_peripherals_init();
 	zoom_display_init();
 	board_smc91x_init();
-	board_flash_init(sdp_flash_partitions, chip_sel_sdp);
+	board_flash_init(sdp_flash_partitions, chip_sel_sdp, NAND_BUSWIDTH_16);
 	enable_board_wakeup_source();
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(OMAP_3630SDP, "OMAP 3630SDP board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_sdp_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_sdp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-4430sdp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-4430sdp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-4430sdp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-4430sdp.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,8 @@
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include <plat/omap4-keypad.h>
+#include <plat/display.h>
 
 #include "mux.h"
 #include "hsmmc.h"
@@ -44,10 +46,95 @@
 #define ETH_KS8851_IRQ			34
 #define ETH_KS8851_POWER_ON		48
 #define ETH_KS8851_QUART		138
-#define OMAP4SDP_MDM_PWR_EN_GPIO	157
 #define OMAP4_SFH7741_SENSOR_OUTPUT_GPIO	184
 #define OMAP4_SFH7741_ENABLE_GPIO		188
+#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+
+static const int sdp4430_keymap[] = {
+	KEY(0, 0, KEY_E),
+	KEY(0, 1, KEY_R),
+	KEY(0, 2, KEY_T),
+	KEY(0, 3, KEY_HOME),
+	KEY(0, 4, KEY_F5),
+	KEY(0, 5, KEY_UNKNOWN),
+	KEY(0, 6, KEY_I),
+	KEY(0, 7, KEY_LEFTSHIFT),
+
+	KEY(1, 0, KEY_D),
+	KEY(1, 1, KEY_F),
+	KEY(1, 2, KEY_G),
+	KEY(1, 3, KEY_SEND),
+	KEY(1, 4, KEY_F6),
+	KEY(1, 5, KEY_UNKNOWN),
+	KEY(1, 6, KEY_K),
+	KEY(1, 7, KEY_ENTER),
+
+	KEY(2, 0, KEY_X),
+	KEY(2, 1, KEY_C),
+	KEY(2, 2, KEY_V),
+	KEY(2, 3, KEY_END),
+	KEY(2, 4, KEY_F7),
+	KEY(2, 5, KEY_UNKNOWN),
+	KEY(2, 6, KEY_DOT),
+	KEY(2, 7, KEY_CAPSLOCK),
+
+	KEY(3, 0, KEY_Z),
+	KEY(3, 1, KEY_KPPLUS),
+	KEY(3, 2, KEY_B),
+	KEY(3, 3, KEY_F1),
+	KEY(3, 4, KEY_F8),
+	KEY(3, 5, KEY_UNKNOWN),
+	KEY(3, 6, KEY_O),
+	KEY(3, 7, KEY_SPACE),
+
+	KEY(4, 0, KEY_W),
+	KEY(4, 1, KEY_Y),
+	KEY(4, 2, KEY_U),
+	KEY(4, 3, KEY_F2),
+	KEY(4, 4, KEY_VOLUMEUP),
+	KEY(4, 5, KEY_UNKNOWN),
+	KEY(4, 6, KEY_L),
+	KEY(4, 7, KEY_LEFT),
+
+	KEY(5, 0, KEY_S),
+	KEY(5, 1, KEY_H),
+	KEY(5, 2, KEY_J),
+	KEY(5, 3, KEY_F3),
+	KEY(5, 4, KEY_F9),
+	KEY(5, 5, KEY_VOLUMEDOWN),
+	KEY(5, 6, KEY_M),
+	KEY(5, 7, KEY_RIGHT),
+
+	KEY(6, 0, KEY_Q),
+	KEY(6, 1, KEY_A),
+	KEY(6, 2, KEY_N),
+	KEY(6, 3, KEY_BACK),
+	KEY(6, 4, KEY_BACKSPACE),
+	KEY(6, 5, KEY_UNKNOWN),
+	KEY(6, 6, KEY_P),
+	KEY(6, 7, KEY_UP),
+
+	KEY(7, 0, KEY_PROG1),
+	KEY(7, 1, KEY_PROG2),
+	KEY(7, 2, KEY_PROG3),
+	KEY(7, 3, KEY_PROG4),
+	KEY(7, 4, KEY_F4),
+	KEY(7, 5, KEY_UNKNOWN),
+	KEY(7, 6, KEY_OK),
+	KEY(7, 7, KEY_DOWN),
+};
 
+static struct matrix_keymap_data sdp4430_keymap_data = {
+	.keymap			= sdp4430_keymap,
+	.keymap_size		= ARRAY_SIZE(sdp4430_keymap),
+};
+
+static struct omap4_keypad_platform_data sdp4430_keypad_data = {
+	.keymap_data		= &sdp4430_keymap_data,
+	.rows			= 8,
+	.cols			= 8,
+};
 static struct gpio_led sdp4430_gpio_leds[] = {
 	{
 		.name	= "omap4:green:debug0",
@@ -239,28 +326,15 @@
 	{ OMAP_TAG_LCD,		&sdp4430_lcd_config },
 };
 
-static void __init omap_4430sdp_init_irq(void)
+static void __init omap_4430sdp_init_early(void)
 {
-	omap_board_config = sdp4430_config;
-	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(1);
 #endif
-	gic_init_irq();
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0]	= EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1]	= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2]	= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.phy_reset	= false,
-	.reset_gpio_port[0]  = -EINVAL,
-	.reset_gpio_port[1]  = -EINVAL,
-	.reset_gpio_port[2]  = -EINVAL,
-};
-
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_UTMI,
 	.mode			= MUSB_OTG,
@@ -272,15 +346,11 @@
 	.phy_exit	= omap4430_phy_exit,
 	.phy_power	= omap4430_phy_power,
 	.phy_set_clock	= omap4430_phy_set_clk,
+	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct omap2_hsmmc_info mmc[] = {
 	{
-		.mmc		= 1,
-		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
-		.gpio_wp	= -EINVAL,
-	},
-	{
 		.mmc		= 2,
 		.caps		=  MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 		.gpio_cd	= -EINVAL,
@@ -288,19 +358,24 @@
 		.nonremovable   = true,
 		.ocr_mask	= MMC_VDD_29_30,
 	},
+	{
+		.mmc		= 1,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+		.gpio_wp	= -EINVAL,
+	},
 	{}	/* Terminator */
 };
 
 static struct regulator_consumer_supply sdp4430_vaux_supply[] = {
 	{
 		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.1",
+		.dev_name = "omap_hsmmc.1",
 	},
 };
 static struct regulator_consumer_supply sdp4430_vmmc_supply[] = {
 	{
 		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.0",
+		.dev_name = "omap_hsmmc.0",
 	},
 };
 
@@ -434,7 +509,6 @@
 	.constraints = {
 		.min_uV			= 2100000,
 		.max_uV			= 2100000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -446,7 +520,6 @@
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -458,7 +531,6 @@
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -478,6 +550,12 @@
 	},
 };
 
+static struct regulator_init_data sdp4430_clk32kg = {
+	.constraints = {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+	},
+};
+
 static struct twl4030_platform_data sdp4430_twldata = {
 	.irq_base	= TWL6030_IRQ_BASE,
 	.irq_end	= TWL6030_IRQ_END,
@@ -493,6 +571,7 @@
 	.vaux1		= &sdp4430_vaux1,
 	.vaux2		= &sdp4430_vaux2,
 	.vaux3		= &sdp4430_vaux3,
+	.clk32kg	= &sdp4430_clk32kg,
 	.usb		= &omap4_usbphy_data
 };
 
@@ -552,14 +631,151 @@
 	}
 }
 
+static void sdp4430_hdmi_mux_init(void)
+{
+	/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
+	omap_mux_init_signal("hdmi_hpd",
+			OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("hdmi_cec",
+			OMAP_PIN_INPUT_PULLUP);
+	/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
+	omap_mux_init_signal("hdmi_ddc_scl",
+			OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("hdmi_ddc_sda",
+			OMAP_PIN_INPUT_PULLUP);
+}
+
+static int sdp4430_panel_enable_hdmi(struct omap_dss_device *dssdev)
+{
+	int status;
+
+	status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH,
+							"hdmi_gpio_hpd");
+	if (status) {
+		pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD);
+		return status;
+	}
+	status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH,
+							"hdmi_gpio_ls_oe");
+	if (status) {
+		pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE);
+		goto error1;
+	}
+
+	return 0;
+
+error1:
+	gpio_free(HDMI_GPIO_HPD);
+
+	return status;
+}
+
+static void sdp4430_panel_disable_hdmi(struct omap_dss_device *dssdev)
+{
+	gpio_free(HDMI_GPIO_LS_OE);
+	gpio_free(HDMI_GPIO_HPD);
+}
+
+static struct omap_dss_device sdp4430_hdmi_device = {
+	.name = "hdmi",
+	.driver_name = "hdmi_panel",
+	.type = OMAP_DISPLAY_TYPE_HDMI,
+	.platform_enable = sdp4430_panel_enable_hdmi,
+	.platform_disable = sdp4430_panel_disable_hdmi,
+	.channel = OMAP_DSS_CHANNEL_DIGIT,
+};
+
+static struct omap_dss_device *sdp4430_dss_devices[] = {
+	&sdp4430_hdmi_device,
+};
+
+static struct omap_dss_board_info sdp4430_dss_data = {
+	.num_devices	= ARRAY_SIZE(sdp4430_dss_devices),
+	.devices	= sdp4430_dss_devices,
+	.default_device	= &sdp4430_hdmi_device,
+};
+
+void omap_4430sdp_display_init(void)
+{
+	sdp4430_hdmi_mux_init();
+	omap_display_init(&sdp4430_dss_data);
+}
+
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	OMAP4_MUX(USBB2_ULPITLL_CLK, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial4_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart4_rx.uart4_rx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart4_tx.uart4_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial2_data = {
+	.id		= 1,
+	.pads		= serial2_pads,
+	.pads_cnt	= ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data = {
+	.id		= 2,
+	.pads		= serial3_pads,
+	.pads_cnt	= ARRAY_SIZE(serial3_pads),
+};
+
+static struct omap_board_data serial4_data = {
+	.id		= 3,
+	.pads		= serial4_pads,
+	.pads_cnt	= ARRAY_SIZE(serial4_pads),
+};
+
+static inline void board_serial_init(void)
+{
+	struct omap_board_data bdata;
+	bdata.flags	= 0;
+	bdata.pads	= NULL;
+	bdata.pads_cnt	= 0;
+	bdata.id	= 0;
+	/* pass dummy data for UART1 */
+	omap_serial_init_port(&bdata);
+
+	omap_serial_init_port(&serial2_data);
+	omap_serial_init_port(&serial3_data);
+	omap_serial_init_port(&serial4_data);
+}
 #else
 #define board_mux	NULL
-#endif
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
+ #endif
 
 static void __init omap_4430sdp_init(void)
 {
@@ -570,20 +786,15 @@
 		package = OMAP_PACKAGE_CBL;
 	omap4_mux_init(board_mux, package);
 
+	omap_board_config = sdp4430_config;
+	omap_board_config_size = ARRAY_SIZE(sdp4430_config);
+
 	omap4_i2c_init();
 	omap_sfh7741prox_init();
 	platform_add_devices(sdp4430_devices, ARRAY_SIZE(sdp4430_devices));
-	omap_serial_init();
+	board_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
 
-	/* Power on the ULPI PHY */
-	status = gpio_request(OMAP4SDP_MDM_PWR_EN_GPIO, "USBB1 PHY VMDM_3V3");
-	if (status)
-		pr_err("%s: Could not get USBB1 PHY GPIO\n", __func__);
-	else
-		gpio_direction_output(OMAP4SDP_MDM_PWR_EN_GPIO, 1);
-
-	usb_ehci_init(&ehci_pdata);
 	usb_musb_init(&musb_board_data);
 
 	status = omap_ethernet_init();
@@ -594,6 +805,12 @@
 		spi_register_board_info(sdp4430_spi_board_info,
 				ARRAY_SIZE(sdp4430_spi_board_info));
 	}
+
+	status = omap4_keyboard_init(&sdp4430_keypad_data);
+	if (status)
+		pr_err("Keypad initialization failed: %d\n", status);
+
+	omap_4430sdp_display_init();
 }
 
 static void __init omap_4430sdp_map_io(void)
@@ -605,9 +822,10 @@
 MACHINE_START(OMAP_4430SDP, "OMAP4430 4430SDP board")
 	/* Maintainer: Santosh Shilimkar - Texas Instruments Inc */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_4430sdp_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_4430sdp_init_irq,
+	.map_io		= omap_4430sdp_map_io,
+	.init_early	= omap_4430sdp_init_early,
+	.init_irq	= gic_init_irq,
 	.init_machine	= omap_4430sdp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-am3517crane.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-am3517crane.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-am3517crane.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-am3517crane.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,20 +49,16 @@
 #define board_mux	NULL
 #endif
 
-static void __init am3517_crane_init_irq(void)
+static void __init am3517_crane_init_early(void)
 {
-	omap_board_config = am3517_crane_config;
-	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
-
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = GPIO_USB_NRESET,
@@ -77,6 +73,9 @@
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
 
+	omap_board_config = am3517_crane_config;
+	omap_board_config_size = ARRAY_SIZE(am3517_crane_config);
+
 	/* Configure GPIO for EHCI port */
 	if (omap_mux_init_gpio(GPIO_USB_NRESET, OMAP_PIN_OUTPUT)) {
 		pr_err("Can not configure mux for GPIO_USB_NRESET %d\n",
@@ -103,14 +102,15 @@
 		return;
 	}
 
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(CRANEBOARD, "AM3517/05 CRANEBOARD")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= am3517_crane_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= am3517_crane_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= am3517_crane_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-am3517evm.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-am3517evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-am3517evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-am3517evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -200,6 +200,9 @@
 };
 static struct i2c_board_info __initdata am3517evm_i2c2_boardinfo[] = {
 	{
+		I2C_BOARD_INFO("tlv320aic23", 0x1A),
+	},
+	{
 		I2C_BOARD_INFO("tca6416", 0x21),
 		.platform_data = &am3517evm_gpio_expander_info_0,
 	},
@@ -378,37 +381,23 @@
 	.default_device	= &am3517_evm_lcd_device,
 };
 
-static struct platform_device am3517_evm_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data	= &am3517_evm_dss_data,
-	},
-};
-
 /*
  * Board initialization
  */
-static struct omap_board_config_kernel am3517_evm_config[] __initdata = {
-};
-
-static struct platform_device *am3517_evm_devices[] __initdata = {
-	&am3517_evm_dss_device,
-};
-
-static void __init am3517_evm_init_irq(void)
+static void __init am3517_evm_init_early(void)
 {
-	omap_board_config = am3517_evm_config;
-	omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type         = MUSB_INTERFACE_ULPI,
 	.mode                   = MUSB_OTG,
 	.power                  = 500,
+	.set_phy_power		= am35x_musb_phy_power,
+	.clear_irq		= am35x_musb_clear_irq,
+	.set_mode		= am35x_musb_set_mode,
+	.reset			= am35x_musb_reset,
 };
 
 static __init void am3517_evm_musb_init(void)
@@ -430,15 +419,15 @@
 	usb_musb_init(&musb_board_data);
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
 #if defined(CONFIG_PANEL_SHARP_LQ043T1DG01) || \
 		defined(CONFIG_PANEL_SHARP_LQ043T1DG01_MODULE)
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
 #else
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
 #endif
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 57,
@@ -490,19 +479,22 @@
 	platform_device_register(&am3517_hecc_device);
 }
 
+static struct omap_board_config_kernel am3517_evm_config[] __initdata = {
+};
+
 static void __init am3517_evm_init(void)
 {
+	omap_board_config = am3517_evm_config;
+	omap_board_config_size = ARRAY_SIZE(am3517_evm_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 
 	am3517_evm_i2c_init();
-	platform_add_devices(am3517_evm_devices,
-				ARRAY_SIZE(am3517_evm_devices));
-
+	omap_display_init(&am3517_evm_dss_data);
 	omap_serial_init();
 
 	/* Configure GPIO for EHCI port */
 	omap_mux_init_gpio(57, OMAP_PIN_OUTPUT);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	am3517_evm_hecc_init(&am3517_evm_hecc_pdata);
 	/* DSS */
 	am3517_evm_display_init();
@@ -521,9 +513,10 @@
 
 MACHINE_START(OMAP3517EVM, "OMAP3517/AM3517 EVM")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= am3517_evm_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= am3517_evm_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= am3517_evm_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-apollon.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-apollon.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-apollon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-apollon.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,13 +274,10 @@
 	{ OMAP_TAG_LCD,		&apollon_lcd_config },
 };
 
-static void __init omap_apollon_init_irq(void)
+static void __init omap_apollon_init_early(void)
 {
-	omap_board_config = apollon_config;
-	omap_board_config_size = ARRAY_SIZE(apollon_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static void __init apollon_led_init(void)
@@ -320,6 +317,8 @@
 	u32 v;
 
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAC);
+	omap_board_config = apollon_config;
+	omap_board_config_size = ARRAY_SIZE(apollon_config);
 
 	apollon_init_smc91x();
 	apollon_led_init();
@@ -355,9 +354,10 @@
 MACHINE_START(OMAP_APOLLON, "OMAP24xx Apollon")
 	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_apollon_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_apollon_init_irq,
+	.map_io		= omap_apollon_map_io,
+	.init_early	= omap_apollon_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_apollon_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-cm-t3517.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-cm-t3517.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-cm-t3517.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-cm-t3517.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,10 +167,10 @@
 #define HSUSB2_RESET_GPIO	(147)
 #define USB_HUB_RESET_GPIO	(152)
 
-static struct ehci_hcd_omap_platform_data cm_t3517_ehci_pdata __initdata = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data cm_t3517_ehci_pdata __initdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = HSUSB1_RESET_GPIO,
@@ -192,7 +192,7 @@
 		msleep(1);
 	}
 
-	usb_ehci_init(&cm_t3517_ehci_pdata);
+	usbhs_init(&cm_t3517_ehci_pdata);
 
 	return 0;
 }
@@ -254,16 +254,13 @@
 static struct omap_board_config_kernel cm_t3517_config[] __initdata = {
 };
 
-static void __init cm_t3517_init_irq(void)
+static void __init cm_t3517_init_early(void)
 {
-	omap_board_config = cm_t3517_config;
-	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
-
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
+#ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* GPIO186 - Green LED */
 	OMAP3_MUX(SYS_CLKOUT2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
@@ -289,11 +286,14 @@
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#endif
 
 static void __init cm_t3517_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	omap_serial_init();
+	omap_board_config = cm_t3517_config;
+	omap_board_config_size = ARRAY_SIZE(cm_t3517_config);
 	cm_t3517_init_leds();
 	cm_t3517_init_nand();
 	cm_t3517_init_rtc();
@@ -303,9 +303,10 @@
 
 MACHINE_START(CM_T3517, "Compulab CM-T3517")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve        = omap_reserve,
-	.init_irq	= cm_t3517_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= cm_t3517_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= cm_t3517_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-cm-t35.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-cm-t35.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-cm-t35.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-cm-t35.c	2011-05-19 00:06:34.000000000 -0400
@@ -401,14 +401,6 @@
 	.default_device	= &cm_t35_dvi_device,
 };
 
-static struct platform_device cm_t35_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &cm_t35_dss_data,
-	},
-};
-
 static struct omap2_mcspi_device_config tdo24m_mcspi_config = {
 	.turbo_mode	= 0,
 	.single_channel	= 1,	/* 0: slave, 1: master */
@@ -468,7 +460,7 @@
 	msleep(50);
 	gpio_set_value(lcd_en_gpio, 1);
 
-	err = platform_device_register(&cm_t35_dss_device);
+	err = omap_display_init(&cm_t35_dss_data);
 	if (err) {
 		pr_err("CM-T35: failed to register DSS device\n");
 		goto err_dev_reg;
@@ -495,15 +487,11 @@
 	.supply			= "vmmc_aux",
 };
 
-static struct regulator_consumer_supply cm_t35_vdac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &cm_t35_dss_device.dev,
-};
+static struct regulator_consumer_supply cm_t35_vdac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
-static struct regulator_consumer_supply cm_t35_vdvi_supply = {
-	.supply		= "vdvi",
-	.dev		= &cm_t35_dss_device.dev,
-};
+static struct regulator_consumer_supply cm_t35_vdvi_supply =
+	REGULATOR_SUPPLY("vdvi", "omapdss");
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
 static struct regulator_init_data cm_t35_vmmc1 = {
@@ -605,10 +593,10 @@
 	{}	/* Terminator */
 };
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data usbhs_bdata __initdata = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = OMAP_MAX_GPIO_LINES + 6,
@@ -680,20 +668,14 @@
 			      ARRAY_SIZE(cm_t35_i2c_boardinfo));
 }
 
-static struct omap_board_config_kernel cm_t35_config[] __initdata = {
-};
-
-static void __init cm_t35_init_irq(void)
+static void __init cm_t35_init_early(void)
 {
-	omap_board_config = cm_t35_config;
-	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
-
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 			     mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
 }
 
+#ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for CM-T35 ethernet */
 	OMAP3_MUX(GPMC_NCS5, OMAP_MUX_MODE0),
@@ -791,6 +773,7 @@
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#endif
 
 static struct omap_musb_board_data musb_board_data = {
 	.interface_type		= MUSB_INTERFACE_ULPI,
@@ -798,8 +781,13 @@
 	.power			= 100,
 };
 
+static struct omap_board_config_kernel cm_t35_config[] __initdata = {
+};
+
 static void __init cm_t35_init(void)
 {
+	omap_board_config = cm_t35_config;
+	omap_board_config_size = ARRAY_SIZE(cm_t35_config);
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
 	omap_serial_init();
 	cm_t35_init_i2c();
@@ -810,14 +798,15 @@
 	cm_t35_init_display();
 
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 }
 
 MACHINE_START(CM_T35, "Compulab CM-T35")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= cm_t35_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= cm_t35_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= cm_t35_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-devkit8000.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-devkit8000.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-devkit8000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-devkit8000.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,7 +140,7 @@
 }
 
 static struct regulator_consumer_supply devkit8000_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 
 /* ads7846 on SPI */
@@ -195,16 +195,8 @@
 	.default_device = &devkit8000_lcd_device,
 };
 
-static struct platform_device devkit8000_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &devkit8000_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply devkit8000_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss");
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static uint32_t board_keymap[] = {
 	KEY(0, 0, KEY_1),
@@ -285,8 +277,10 @@
 	.setup		= devkit8000_twl_gpio_setup,
 };
 
-static struct regulator_consumer_supply devkit8000_vpll1_supply =
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply devkit8000_vpll1_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 /* VMMC1 for MMC1 pins CMD, CLK, DAT0..DAT3 (20 mA, plus card == max 220 mA) */
 static struct regulator_init_data devkit8000_vmmc1 = {
@@ -327,8 +321,8 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &devkit8000_vpll1_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(devkit8000_vpll1_supplies),
+	.consumer_supplies	= devkit8000_vpll1_supplies,
 };
 
 /* VAUX4 for ads7846 and nubs */
@@ -350,9 +344,7 @@
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data devkit8000_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data devkit8000_audio_data;
 
 static struct twl4030_codec_data devkit8000_codec_data = {
 	.audio_mclk = 26000000,
@@ -456,11 +448,15 @@
 };
 
 
-static void __init devkit8000_init_irq(void)
+static void __init devkit8000_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
+}
+
+static void __init devkit8000_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -575,7 +571,6 @@
 }
 
 static struct platform_device *devkit8000_devices[] __initdata = {
-	&devkit8000_dss_device,
 	&leds_gpio,
 	&keys_gpio,
 	&omap_dm9000_dev,
@@ -620,11 +615,11 @@
 	.power			= 100,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -632,6 +627,7 @@
 	.reset_gpio_port[2]  = -EINVAL
 };
 
+#ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* nCS and IRQ for Devkit8000 ethernet */
 	OMAP3_MUX(GPMC_NCS6, OMAP_MUX_MODE0),
@@ -785,6 +781,7 @@
 
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#endif
 
 static void __init devkit8000_init(void)
 {
@@ -797,13 +794,14 @@
 	platform_add_devices(devkit8000_devices,
 			ARRAY_SIZE(devkit8000_devices));
 
+	omap_display_init(&devkit8000_dss_data);
 	spi_register_board_info(devkit8000_spi_board_info,
 	ARRAY_SIZE(devkit8000_spi_board_info));
 
 	devkit8000_ads7846_init();
 
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	devkit8000_flash_init();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -813,8 +811,9 @@
 
 MACHINE_START(DEVKIT8000, "OMAP3 Devkit8000")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= devkit8000_init_early,
 	.init_irq	= devkit8000_init_irq,
 	.init_machine	= devkit8000_init,
 	.timer		= &omap_timer,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-flash.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-flash.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-flash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * board-sdp-flash.c
+ * board-flash.c
  * Modified from mach-omap2/board-3430sdp-flash.c
  *
  * Copyright (C) 2009 Nokia Corporation
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/mtd/physmap.h>
 #include <linux/io.h>
+#include <plat/irqs.h>
 
 #include <plat/gpmc.h>
 #include <plat/nand.h>
@@ -73,11 +74,11 @@
 					+ FLASH_SIZE_SDPV1 - 1;
 	}
 	if (err < 0) {
-		printk(KERN_ERR "NOR: Can't request GPMC CS\n");
+		pr_err("NOR: Can't request GPMC CS\n");
 		return;
 	}
 	if (platform_device_register(&board_nor_device) < 0)
-		printk(KERN_ERR	"Unable to register NOR device\n");
+		pr_err("Unable to register NOR device\n");
 }
 
 #if defined(CONFIG_MTD_ONENAND_OMAP2) || \
@@ -139,17 +140,21 @@
 };
 
 void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
+__init board_nand_init(struct mtd_partition *nand_parts,
+			u8 nr_parts, u8 cs, int nand_type)
 {
 	board_nand_data.cs		= cs;
 	board_nand_data.parts		= nand_parts;
-	board_nand_data.nr_parts		= nr_parts;
+	board_nand_data.nr_parts	= nr_parts;
+	board_nand_data.devsize		= nand_type;
 
+	board_nand_data.ecc_opt = OMAP_ECC_HAMMING_CODE_DEFAULT;
+	board_nand_data.gpmc_irq = OMAP_GPMC_IRQ_BASE + cs;
 	gpmc_nand_init(&board_nand_data);
 }
 #else
 void
-__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs)
+__init board_nand_init(struct mtd_partition *nand_parts, u8 nr_parts, u8 cs, int nand_type)
 {
 }
 #endif /* CONFIG_MTD_NAND_OMAP2 || CONFIG_MTD_NAND_OMAP2_MODULE */
@@ -189,12 +194,12 @@
 }
 
 /**
- * sdp3430_flash_init - Identify devices connected to GPMC and register.
+ * board_flash_init - Identify devices connected to GPMC and register.
  *
  * @return - void.
  */
 void board_flash_init(struct flash_partitions partition_info[],
-					char chip_sel_board[][GPMC_CS_NUM])
+			char chip_sel_board[][GPMC_CS_NUM], int nand_type)
 {
 	u8		cs = 0;
 	u8		norcs = GPMC_CS_NUM + 1;
@@ -208,7 +213,7 @@
 	 */
 	idx = get_gpmc0_type();
 	if (idx >= MAX_SUPPORTED_GPMC_CONFIG) {
-		printk(KERN_ERR "%s: Invalid chip select: %d\n", __func__, cs);
+		pr_err("%s: Invalid chip select: %d\n", __func__, cs);
 		return;
 	}
 	config_sel = (unsigned char *)(chip_sel_board[idx]);
@@ -232,23 +237,20 @@
 	}
 
 	if (norcs > GPMC_CS_NUM)
-		printk(KERN_INFO "NOR: Unable to find configuration "
-				"in GPMC\n");
+		pr_err("NOR: Unable to find configuration in GPMC\n");
 	else
 		board_nor_init(partition_info[0].parts,
 				partition_info[0].nr_parts, norcs);
 
 	if (onenandcs > GPMC_CS_NUM)
-		printk(KERN_INFO "OneNAND: Unable to find configuration "
-				"in GPMC\n");
+		pr_err("OneNAND: Unable to find configuration in GPMC\n");
 	else
 		board_onenand_init(partition_info[1].parts,
 					partition_info[1].nr_parts, onenandcs);
 
 	if (nandcs > GPMC_CS_NUM)
-		printk(KERN_INFO "NAND: Unable to find configuration "
-				"in GPMC\n");
+		pr_err("NAND: Unable to find configuration in GPMC\n");
 	else
 		board_nand_init(partition_info[2].parts,
-				partition_info[2].nr_parts, nandcs);
+			partition_info[2].nr_parts, nandcs, nand_type);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-flash.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-flash.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-flash.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-flash.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,6 @@
 };
 
 extern void board_flash_init(struct flash_partitions [],
-				char chip_sel[][GPMC_CS_NUM]);
+				char chip_sel[][GPMC_CS_NUM], int nand_type);
 extern void board_nand_init(struct mtd_partition *nand_parts,
-					u8 nr_parts, u8 cs);
+					u8 nr_parts, u8 cs, int nand_type);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-generic.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-generic.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-generic.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,18 +33,17 @@
 static struct omap_board_config_kernel generic_config[] = {
 };
 
-static void __init omap_generic_init_irq(void)
+static void __init omap_generic_init_early(void)
 {
-	omap_board_config = generic_config;
-	omap_board_config_size = ARRAY_SIZE(generic_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static void __init omap_generic_init(void)
 {
 	omap_serial_init();
+	omap_board_config = generic_config;
+	omap_board_config_size = ARRAY_SIZE(generic_config);
 }
 
 static void __init omap_generic_map_io(void)
@@ -68,9 +67,10 @@
 MACHINE_START(OMAP_GENERIC, "Generic OMAP24xx")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_generic_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_generic_init_irq,
+	.map_io		= omap_generic_map_io,
+	.init_early	= omap_generic_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_generic_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-h4.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-h4.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-h4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-h4.c	2011-05-19 00:06:34.000000000 -0400
@@ -290,14 +290,15 @@
 	{ OMAP_TAG_LCD,		&h4_lcd_config },
 };
 
-static void __init omap_h4_init_irq(void)
+static void __init omap_h4_init_early(void)
 {
-	omap_board_config = h4_config;
-	omap_board_config_size = ARRAY_SIZE(h4_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
+}
+
+static void __init omap_h4_init_irq(void)
+{
 	omap_init_irq();
-	h4_init_flash();
 }
 
 static struct at24_platform_data m24c01 = {
@@ -330,6 +331,9 @@
 {
 	omap2420_mux_init(board_mux, OMAP_PACKAGE_ZAF);
 
+	omap_board_config = h4_config;
+	omap_board_config_size = ARRAY_SIZE(h4_config);
+
 	/*
 	 * Make sure the serial ports are muxed on at this point.
 	 * You have to mux them off in device drivers later on
@@ -367,6 +371,7 @@
 	platform_add_devices(h4_devices, ARRAY_SIZE(h4_devices));
 	omap2_usbfs_init(&h4_usb_config);
 	omap_serial_init();
+	h4_init_flash();
 }
 
 static void __init omap_h4_map_io(void)
@@ -378,8 +383,9 @@
 MACHINE_START(OMAP_H4, "OMAP2420 H4 board")
 	/* Maintainer: Paul Mundt <paul.mundt@nokia.com> */
 	.boot_params	= 0x80000100,
-	.map_io		= omap_h4_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap_h4_map_io,
+	.init_early	= omap_h4_init_early,
 	.init_irq	= omap_h4_init_irq,
 	.init_machine	= omap_h4_init,
 	.timer		= &omap_timer,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-igep0020.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-igep0020.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-igep0020.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-igep0020.c	2011-05-19 00:06:34.000000000 -0400
@@ -250,7 +250,7 @@
 #endif
 
 static struct regulator_consumer_supply igep2_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep2_vmmc1 = {
@@ -268,7 +268,7 @@
 };
 
 static struct regulator_consumer_supply igep2_vio_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
 
 static struct regulator_init_data igep2_vio = {
 	.constraints = {
@@ -286,7 +286,7 @@
 };
 
 static struct regulator_consumer_supply igep2_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_init_data igep2_vmmc2 = {
 	.constraints		= {
@@ -485,17 +485,9 @@
 	.default_device	= &igep2_dvi_device,
 };
 
-static struct platform_device igep2_dss_device = {
-	.name	= "omapdss",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &igep2_dss_data,
-	},
-};
-
-static struct regulator_consumer_supply igep2_vpll2_supply = {
-	.supply	= "vdds_dsi",
-	.dev	= &igep2_dss_device.dev,
+static struct regulator_consumer_supply igep2_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
 };
 
 static struct regulator_init_data igep2_vpll2 = {
@@ -509,8 +501,8 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &igep2_vpll2_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(igep2_vpll2_supplies),
+	.consumer_supplies	= igep2_vpll2_supplies,
 };
 
 static void __init igep2_display_init(void)
@@ -521,21 +513,17 @@
 }
 
 static struct platform_device *igep2_devices[] __initdata = {
-	&igep2_dss_device,
 	&igep2_vwlan_device,
 };
 
-static void __init igep2_init_irq(void)
+static void __init igep2_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(m65kxxxxam_sdrc_params,
 				  m65kxxxxam_sdrc_params);
-	omap_init_irq();
 }
 
-static struct twl4030_codec_audio_data igep2_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data igep2_audio_data;
 
 static struct twl4030_codec_data igep2_codec_data = {
 	.audio_mclk = 26000000,
@@ -627,10 +615,10 @@
 	.power			= 100,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset = true,
 	.reset_gpio_port[0] = IGEP2_GPIO_USBH_NRESET,
@@ -697,9 +685,10 @@
 	/* Register I2C busses and drivers */
 	igep2_i2c_init();
 	platform_add_devices(igep2_devices, ARRAY_SIZE(igep2_devices));
+	omap_display_init(&igep2_dss_data);
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 
 	igep2_flash_init();
 	igep2_leds_init();
@@ -707,7 +696,7 @@
 	igep2_init_smsc911x();
 
 	/*
-	 * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+	 * WLAN-BT combo module from MuRata which has a Marvell WLAN
 	 * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
 	 */
 	igep2_wlan_bt_init();
@@ -716,9 +705,10 @@
 
 MACHINE_START(IGEP0020, "IGEP v2 board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= igep2_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= igep2_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= igep2_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-igep0030.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-igep0030.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-igep0030.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-igep0030.c	2011-05-19 00:06:34.000000000 -0400
@@ -142,7 +142,7 @@
 #endif
 
 static struct regulator_consumer_supply igep3_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
 static struct regulator_init_data igep3_vmmc1 = {
@@ -160,7 +160,7 @@
 };
 
 static struct regulator_consumer_supply igep3_vio_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
 
 static struct regulator_init_data igep3_vio = {
 	.constraints = {
@@ -178,7 +178,7 @@
 };
 
 static struct regulator_consumer_supply igep3_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_init_data igep3_vmmc2 = {
 	.constraints	= {
@@ -331,12 +331,11 @@
 	&igep3_vwlan_device,
 };
 
-static void __init igep3_init_irq(void)
+static void __init igep3_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(m65kxxxxam_sdrc_params,
 				  m65kxxxxam_sdrc_params);
-	omap_init_irq();
 }
 
 static struct twl4030_platform_data igep3_twl4030_pdata = {
@@ -408,10 +407,10 @@
 void __init igep3_wifi_bt_init(void) {}
 #endif
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset = true,
 	.reset_gpio_port[0] = -EINVAL,
@@ -435,13 +434,13 @@
 	platform_add_devices(igep3_devices, ARRAY_SIZE(igep3_devices));
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 
 	igep3_flash_init();
 	igep3_leds_init();
 
 	/*
-	 * WLAN-BT combo module from MuRata wich has a Marvell WLAN
+	 * WLAN-BT combo module from MuRata which has a Marvell WLAN
 	 * (88W8686) + CSR Bluetooth chipset. Uses SDIO interface.
 	 */
 	igep3_wifi_bt_init();
@@ -452,7 +451,8 @@
 	.boot_params	= 0x80000100,
 	.reserve	= omap_reserve,
 	.map_io		= omap3_map_io,
-	.init_irq	= igep3_init_irq,
+	.init_early	= igep3_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= igep3_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-ldp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-ldp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-ldp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-ldp.c	2011-05-19 00:06:34.000000000 -0400
@@ -288,13 +288,10 @@
 	{ OMAP_TAG_LCD,		&ldp_lcd_config },
 };
 
-static void __init omap_ldp_init_irq(void)
+static void __init omap_ldp_init_early(void)
 {
-	omap_board_config = ldp_config;
-	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 static struct twl4030_usb_data ldp_usb_data = {
@@ -330,6 +327,26 @@
 	.consumer_supplies	= &ldp_vmmc1_supply,
 };
 
+/* ads7846 on SPI */
+static struct regulator_consumer_supply ldp_vaux1_supplies[] = {
+	REGULATOR_SUPPLY("vcc", "spi1.0"),
+};
+
+/* VAUX1 */
+static struct regulator_init_data ldp_vaux1 = {
+	.constraints = {
+		.min_uV			= 3000000,
+		.max_uV			= 3000000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies		= ARRAY_SIZE(ldp_vaux1_supplies),
+	.consumer_supplies		= ldp_vaux1_supplies,
+};
+
 static struct twl4030_platform_data ldp_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
 	.irq_end	= TWL4030_IRQ_END,
@@ -338,6 +355,7 @@
 	.madc		= &ldp_madc_data,
 	.usb		= &ldp_usb_data,
 	.vmmc1		= &ldp_vmmc1,
+	.vaux1		= &ldp_vaux1,
 	.gpio		= &ldp_gpio_data,
 	.keypad		= &ldp_kp_twl4030_data,
 };
@@ -423,6 +441,8 @@
 static void __init omap_ldp_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = ldp_config;
+	omap_board_config_size = ARRAY_SIZE(ldp_config);
 	ldp_init_smsc911x();
 	omap_i2c_init();
 	platform_add_devices(ldp_devices, ARRAY_SIZE(ldp_devices));
@@ -434,7 +454,7 @@
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
 	board_nand_init(ldp_nand_partitions,
-		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS);
+		ARRAY_SIZE(ldp_nand_partitions), ZOOM_NAND_CS, 0);
 
 	omap2_hsmmc_init(mmc);
 	/* link regulators to MMC adapters */
@@ -443,9 +463,10 @@
 
 MACHINE_START(OMAP_LDP, "OMAP LDP board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_ldp_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_ldp_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_ldp_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-n8x0.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-n8x0.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-n8x0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-n8x0.c	2011-05-19 00:06:34.000000000 -0400
@@ -536,7 +536,7 @@
 	}
 
 	mmc_data[0] = &mmc1_data;
-	omap2_init_mmc(mmc_data, OMAP24XX_NR_MMC);
+	omap242x_init_mmc(mmc_data);
 }
 #else
 
@@ -628,11 +628,10 @@
 	omap242x_map_common_io();
 }
 
-static void __init n8x0_init_irq(void)
+static void __init n8x0_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -703,27 +702,30 @@
 
 MACHINE_START(NOKIA_N800, "Nokia N800")
 	.boot_params	= 0x80000100,
-	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= n8x0_init_irq,
+	.map_io		= n8x0_map_io,
+	.init_early	= n8x0_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810, "Nokia N810")
 	.boot_params	= 0x80000100,
-	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= n8x0_init_irq,
+	.map_io		= n8x0_map_io,
+	.init_early	= n8x0_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap_timer,
 MACHINE_END
 
 MACHINE_START(NOKIA_N810_WIMAX, "Nokia N810 WiMAX")
 	.boot_params	= 0x80000100,
-	.map_io		= n8x0_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= n8x0_init_irq,
+	.map_io		= n8x0_map_io,
+	.init_early	= n8x0_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= n8x0_init_machine,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3beagle.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3beagle.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3beagle.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3beagle.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/gpio.h>
 #include <linux/input.h>
 #include <linux/gpio_keys.h>
+#include <linux/opp.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -45,10 +46,12 @@
 #include <plat/gpmc.h>
 #include <plat/nand.h>
 #include <plat/usb.h>
+#include <plat/omap_device.h>
 
 #include "mux.h"
 #include "hsmmc.h"
 #include "timer-gp.h"
+#include "pm.h"
 
 #define NAND_BLOCK_SIZE		SZ_128K
 
@@ -228,19 +231,13 @@
 	.default_device = &beagle_dvi_device,
 };
 
-static struct platform_device beagle_dss_device = {
-	.name          = "omapdss",
-	.id            = -1,
-	.dev            = {
-		.platform_data = &beagle_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply beagle_vdac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss");
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
-static struct regulator_consumer_supply beagle_vdvi_supply =
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply beagle_vdvi_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static void __init beagle_display_init(void)
 {
@@ -427,17 +424,15 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &beagle_vdvi_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(beagle_vdvi_supplies),
+	.consumer_supplies	= beagle_vdvi_supplies,
 };
 
 static struct twl4030_usb_data beagle_usb_data = {
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data beagle_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data beagle_audio_data;
 
 static struct twl4030_codec_data beagle_codec_data = {
 	.audio_mclk = 26000000,
@@ -536,11 +531,15 @@
 	},
 };
 
-static void __init omap3_beagle_init_irq(void)
+static void __init omap3_beagle_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
+}
+
+static void __init omap3_beagle_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -550,7 +549,6 @@
 static struct platform_device *omap3_beagle_devices[] __initdata = {
 	&leds_gpio,
 	&keys_gpio,
-	&beagle_dss_device,
 };
 
 static void __init omap3beagle_flash_init(void)
@@ -586,11 +584,11 @@
 	}
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -610,6 +608,52 @@
 	.power			= 100,
 };
 
+static void __init beagle_opp_init(void)
+{
+	int r = 0;
+
+	/* Initialize the omap3 opp table */
+	if (omap3_opp_init()) {
+		pr_err("%s: opp default init failed\n", __func__);
+		return;
+	}
+
+	/* Custom OPP enabled for XM */
+	if (omap3_beagle_get_rev() == OMAP3BEAGLE_BOARD_XM) {
+		struct omap_hwmod *mh = omap_hwmod_lookup("mpu");
+		struct omap_hwmod *dh = omap_hwmod_lookup("iva");
+		struct device *dev;
+
+		if (!mh || !dh) {
+			pr_err("%s: Aiee.. no mpu/dsp devices? %p %p\n",
+				__func__, mh, dh);
+			return;
+		}
+		/* Enable MPU 1GHz and lower opps */
+		dev = &mh->od->pdev.dev;
+		r = opp_enable(dev, 800000000);
+		/* TODO: MPU 1GHz needs SR and ABB */
+
+		/* Enable IVA 800MHz and lower opps */
+		dev = &dh->od->pdev.dev;
+		r |= opp_enable(dev, 660000000);
+		/* TODO: DSP 800MHz needs SR and ABB */
+		if (r) {
+			pr_err("%s: failed to enable higher opp %d\n",
+				__func__, r);
+			/*
+			 * Cleanup - disable the higher freqs - we dont care
+			 * about the results
+			 */
+			dev = &mh->od->pdev.dev;
+			opp_disable(dev, 800000000);
+			dev = &dh->od->pdev.dev;
+			opp_disable(dev, 660000000);
+		}
+	}
+	return;
+}
+
 static void __init omap3_beagle_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
@@ -617,6 +661,7 @@
 	omap3_beagle_i2c_init();
 	platform_add_devices(omap3_beagle_devices,
 			ARRAY_SIZE(omap3_beagle_devices));
+	omap_display_init(&beagle_dss_data);
 	omap_serial_init();
 
 	omap_mux_init_gpio(170, OMAP_PIN_INPUT);
@@ -625,7 +670,7 @@
 	gpio_direction_output(170, true);
 
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	omap3beagle_flash_init();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -633,13 +678,15 @@
 	omap_mux_init_signal("sdrc_cke1", OMAP_PIN_OUTPUT);
 
 	beagle_display_init();
+	beagle_opp_init();
 }
 
 MACHINE_START(OMAP3_BEAGLE, "OMAP3 Beagle Board")
 	/* Maintainer: Syed Mohammed Khasim - http://beagleboard.org */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3_beagle_init_early,
 	.init_irq	= omap3_beagle_init_irq,
 	.init_machine	= omap3_beagle_init,
 	.timer		= &omap_timer,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3evm.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,8 @@
 #include <linux/usb/otg.h>
 #include <linux/smsc911x.h>
 
+#include <linux/wl12xx.h>
+#include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
 #include <linux/mmc/host.h>
 
@@ -58,6 +60,13 @@
 #define OMAP3EVM_ETHR_ID_REV	0x50
 #define OMAP3EVM_ETHR_GPIO_IRQ	176
 #define OMAP3EVM_SMSC911X_CS	5
+/*
+ * Eth Reset signal
+ *	64 = Generation 1 (<=RevD)
+ *	7 = Generation 2 (>=RevE)
+ */
+#define OMAP3EVM_GEN1_ETHR_GPIO_RST	64
+#define OMAP3EVM_GEN2_ETHR_GPIO_RST	7
 
 static u8 omap3_evm_version;
 
@@ -124,10 +133,15 @@
 
 static inline void __init omap3evm_init_smsc911x(void)
 {
-	int eth_cs;
+	int eth_cs, eth_rst;
 	struct clk *l3ck;
 	unsigned int rate;
 
+	if (get_omap3_evm_rev() == OMAP3EVM_BOARD_GEN_1)
+		eth_rst = OMAP3EVM_GEN1_ETHR_GPIO_RST;
+	else
+		eth_rst = OMAP3EVM_GEN2_ETHR_GPIO_RST;
+
 	eth_cs = OMAP3EVM_SMSC911X_CS;
 
 	l3ck = clk_get(NULL, "l3_ck");
@@ -136,6 +150,27 @@
 	else
 		rate = clk_get_rate(l3ck);
 
+	/* Configure ethernet controller reset gpio */
+	if (cpu_is_omap3430()) {
+		if (gpio_request(eth_rst, "SMSC911x gpio") < 0) {
+			pr_err(KERN_ERR "Failed to request %d for smsc911x\n",
+					eth_rst);
+			return;
+		}
+
+		if (gpio_direction_output(eth_rst, 1) < 0) {
+			pr_err(KERN_ERR "Failed to set direction of %d for" \
+					" smsc911x\n", eth_rst);
+			return;
+		}
+		/* reset pulse to ethernet controller*/
+		usleep_range(150, 220);
+		gpio_set_value(eth_rst, 0);
+		usleep_range(150, 220);
+		gpio_set_value(eth_rst, 1);
+		usleep_range(1, 2);
+	}
+
 	if (gpio_request(OMAP3EVM_ETHR_GPIO_IRQ, "SMSC911x irq") < 0) {
 		printk(KERN_ERR "Failed to request GPIO%d for smsc911x IRQ\n",
 			OMAP3EVM_ETHR_GPIO_IRQ);
@@ -235,9 +270,9 @@
 	gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 0);
 
 	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
 	else
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
 
 	lcd_enabled = 1;
 	return 0;
@@ -248,9 +283,9 @@
 	gpio_set_value(OMAP3EVM_LCD_PANEL_ENVDD, 1);
 
 	if (get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2)
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 1);
 	else
-		gpio_set_value(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
+		gpio_set_value_cansleep(OMAP3EVM_LCD_PANEL_BKLIGHT_GPIO, 0);
 
 	lcd_enabled = 0;
 }
@@ -289,7 +324,7 @@
 		return -EINVAL;
 	}
 
-	gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 1);
+	gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 1);
 
 	dvi_enabled = 1;
 	return 0;
@@ -297,7 +332,7 @@
 
 static void omap3_evm_disable_dvi(struct omap_dss_device *dssdev)
 {
-	gpio_set_value(OMAP3EVM_DVI_PANEL_EN_GPIO, 0);
+	gpio_set_value_cansleep(OMAP3EVM_DVI_PANEL_EN_GPIO, 0);
 
 	dvi_enabled = 0;
 }
@@ -328,14 +363,6 @@
 	.default_device	= &omap3_evm_lcd_device,
 };
 
-static struct platform_device omap3_evm_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &omap3_evm_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply omap3evm_vmmc1_supply = {
 	.supply			= "vmmc",
 };
@@ -381,6 +408,16 @@
 		.gpio_cd	= -EINVAL,
 		.gpio_wp	= 63,
 	},
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	{
+		.name		= "wl1271",
+		.mmc		= 2,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.nonremovable	= true,
+	},
+#endif
 	{}	/* Terminator */
 };
 
@@ -411,6 +448,8 @@
 static int omap3evm_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
+	int r;
+
 	/* gpio + 0 is "mmc0_cd" (input/IRQ) */
 	omap_mux_init_gpio(63, OMAP_PIN_INPUT);
 	mmc[0].gpio_cd = gpio + 0;
@@ -426,8 +465,12 @@
 	 */
 
 	/* TWL4030_GPIO_MAX + 0 == ledA, LCD Backlight control */
-	gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL");
-	gpio_direction_output(gpio + TWL4030_GPIO_MAX, 0);
+	r = gpio_request(gpio + TWL4030_GPIO_MAX, "EN_LCD_BKL");
+	if (!r)
+		r = gpio_direction_output(gpio + TWL4030_GPIO_MAX,
+			(get_omap3_evm_rev() >= OMAP3EVM_BOARD_GEN_2) ? 1 : 0);
+	if (r)
+		printk(KERN_ERR "failed to get/set lcd_bkl gpio\n");
 
 	/* gpio + 7 == DVI Enable */
 	gpio_request(gpio + 7, "EN_DVI");
@@ -491,19 +534,15 @@
 	.irq_line	= 1,
 };
 
-static struct twl4030_codec_audio_data omap3evm_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data omap3evm_audio_data;
 
 static struct twl4030_codec_data omap3evm_codec_data = {
 	.audio_mclk = 26000000,
 	.audio = &omap3evm_audio_data,
 };
 
-static struct regulator_consumer_supply omap3_evm_vdda_dac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &omap3_evm_dss_device.dev,
-};
+static struct regulator_consumer_supply omap3_evm_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 /* VDAC for DSS driving S-Video */
 static struct regulator_init_data omap3_evm_vdac = {
@@ -521,8 +560,10 @@
 };
 
 /* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_evm_vpll2_supply =
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply omap3_evm_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static struct regulator_init_data omap3_evm_vpll2 = {
 	.constraints = {
@@ -534,9 +575,69 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(omap3_evm_vpll2_supplies),
+	.consumer_supplies	= omap3_evm_vpll2_supplies,
+};
+
+/* ads7846 on SPI */
+static struct regulator_consumer_supply omap3evm_vio_supply =
+	REGULATOR_SUPPLY("vcc", "spi1.0");
+
+/* VIO for ads7846 */
+static struct regulator_init_data omap3evm_vio = {
+	.constraints = {
+		.min_uV			= 1800000,
+		.max_uV			= 1800000,
+		.apply_uV		= true,
+		.valid_modes_mask	= REGULATOR_MODE_NORMAL
+					| REGULATOR_MODE_STANDBY,
+		.valid_ops_mask		= REGULATOR_CHANGE_MODE
+					| REGULATOR_CHANGE_STATUS,
+	},
 	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3_evm_vpll2_supply,
+	.consumer_supplies	= &omap3evm_vio_supply,
+};
+
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+
+#define OMAP3EVM_WLAN_PMENA_GPIO	(150)
+#define OMAP3EVM_WLAN_IRQ_GPIO		(149)
+
+static struct regulator_consumer_supply omap3evm_vmmc2_supply =
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
+
+/* VMMC2 for driving the WL12xx module */
+static struct regulator_init_data omap3evm_vmmc2 = {
+	.constraints = {
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies = &omap3evm_vmmc2_supply,
+};
+
+static struct fixed_voltage_config omap3evm_vwlan = {
+	.supply_name		= "vwl1271",
+	.microvolts		= 1800000, /* 1.80V */
+	.gpio			= OMAP3EVM_WLAN_PMENA_GPIO,
+	.startup_delay		= 70000, /* 70ms */
+	.enable_high		= 1,
+	.enabled_at_boot	= 0,
+	.init_data		= &omap3evm_vmmc2,
+};
+
+static struct platform_device omap3evm_wlan_regulator = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &omap3evm_vwlan,
+	},
+};
+
+struct wl12xx_platform_data omap3evm_wlan_data __initdata = {
+	.irq = OMAP_GPIO_IRQ(OMAP3EVM_WLAN_IRQ_GPIO),
+	.board_ref_clock = WL12XX_REFCLOCK_38, /* 38.4 MHz */
 };
+#endif
 
 static struct twl4030_platform_data omap3evm_twldata = {
 	.irq_base	= TWL4030_IRQ_BASE,
@@ -550,6 +651,7 @@
 	.codec		= &omap3evm_codec_data,
 	.vdac		= &omap3_evm_vdac,
 	.vpll2		= &omap3_evm_vpll2,
+	.vio		= &omap3evm_vio,
 };
 
 static struct i2c_board_info __initdata omap3evm_i2c_boardinfo[] = {
@@ -625,24 +727,17 @@
 static struct omap_board_config_kernel omap3_evm_config[] __initdata = {
 };
 
-static void __init omap3_evm_init_irq(void)
+static void __init omap3_evm_init_early(void)
 {
-	omap_board_config = omap3_evm_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
-	omap_init_irq();
 }
 
-static struct platform_device *omap3_evm_devices[] __initdata = {
-	&omap3_evm_dss_device,
-};
-
-static struct ehci_hcd_omap_platform_data ehci_pdata __initdata = {
+static struct usbhs_omap_board_data usbhs_bdata __initdata = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	/* PHY reset GPIO will be runtime programmed based on EVM version */
@@ -652,14 +747,76 @@
 };
 
 #ifdef CONFIG_OMAP_MUX
-static struct omap_board_mux board_mux[] __initdata = {
+static struct omap_board_mux omap35x_board_mux[] __initdata = {
 	OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
 				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
 				OMAP_PIN_OFF_WAKEUPENABLE),
 	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
-				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW),
+				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+				OMAP_PIN_OFF_WAKEUPENABLE),
+	OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(GPMC_WAIT2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_NONE),
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	/* WLAN IRQ - GPIO 149 */
+	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+
+	/* WLAN POWER ENABLE - GPIO 150 */
+	OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+	/* MMC2 SDIO pin muxes for WL12xx */
+	OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+#endif
+	{ .reg_offset = OMAP_MUX_TERMINATOR },
+};
+
+static struct omap_board_mux omap36x_board_mux[] __initdata = {
+	OMAP3_MUX(SYS_NIRQ, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+				OMAP_PIN_OFF_WAKEUPENABLE),
+	OMAP3_MUX(MCSPI1_CS1, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP |
+				OMAP_PIN_OFF_INPUT_PULLUP | OMAP_PIN_OFF_OUTPUT_LOW |
+				OMAP_PIN_OFF_WAKEUPENABLE),
+	/* AM/DM37x EVM: DSS data bus muxed with sys_boot */
+	OMAP3_MUX(DSS_DATA18, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA19, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA21, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA22, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(DSS_DATA23, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT0, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT1, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT3, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT4, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT5, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+	OMAP3_MUX(SYS_BOOT6, OMAP_MUX_MODE3 | OMAP_PIN_OFF_NONE),
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	/* WLAN IRQ - GPIO 149 */
+	OMAP3_MUX(UART1_RTS, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
+
+	/* WLAN POWER ENABLE - GPIO 150 */
+	OMAP3_MUX(UART1_CTS, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
+
+	/* MMC2 SDIO pin muxes for WL12xx */
+	OMAP3_MUX(SDMMC2_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(SDMMC2_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+#endif
+
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+#else
+#define omap35x_board_mux	NULL
+#define omap36x_board_mux	NULL
 #endif
 
 static struct omap_musb_board_data musb_board_data = {
@@ -671,11 +828,18 @@
 static void __init omap3_evm_init(void)
 {
 	omap3_evm_get_revision();
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+
+	if (cpu_is_omap3630())
+		omap3_mux_init(omap36x_board_mux, OMAP_PACKAGE_CBB);
+	else
+		omap3_mux_init(omap35x_board_mux, OMAP_PACKAGE_CBB);
+
+	omap_board_config = omap3_evm_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_evm_config);
 
 	omap3_evm_i2c_init();
 
-	platform_add_devices(omap3_evm_devices, ARRAY_SIZE(omap3_evm_devices));
+	omap_display_init(&omap3_evm_dss_data);
 
 	spi_register_board_info(omap3evm_spi_board_info,
 				ARRAY_SIZE(omap3evm_spi_board_info));
@@ -700,7 +864,7 @@
 
 		/* setup EHCI phy reset config */
 		omap_mux_init_gpio(21, OMAP_PIN_INPUT_PULLUP);
-		ehci_pdata.reset_gpio_port[1] = 21;
+		usbhs_bdata.reset_gpio_port[1] = 21;
 
 		/* EVM REV >= E can supply 500mA with EXTVBUS programming */
 		musb_board_data.power = 500;
@@ -708,21 +872,29 @@
 	} else {
 		/* setup EHCI phy reset on MDC */
 		omap_mux_init_gpio(135, OMAP_PIN_OUTPUT);
-		ehci_pdata.reset_gpio_port[1] = 135;
+		usbhs_bdata.reset_gpio_port[1] = 135;
 	}
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	ads7846_dev_init();
 	omap3evm_init_smsc911x();
 	omap3_evm_display_init();
+
+#ifdef CONFIG_WL12XX_PLATFORM_DATA
+	/* WL12xx WLAN Init */
+	if (wl12xx_set_platform_data(&omap3evm_wlan_data))
+		pr_err("error setting wl12xx data\n");
+	platform_device_register(&omap3evm_wlan_regulator);
+#endif
 }
 
 MACHINE_START(OMAP3EVM, "OMAP3 EVM")
 	/* Maintainer: Syed Mohammed Khasim - Texas Instruments */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap3_evm_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3_evm_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3_evm_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3logic.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3logic.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3logic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3logic.c	2011-05-19 00:06:34.000000000 -0400
@@ -195,11 +195,10 @@
 	gpmc_smsc911x_init(&board_smsc911x_data);
 }
 
-static void __init omap3logic_init_irq(void)
+static void __init omap3logic_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -225,7 +224,8 @@
 MACHINE_START(OMAP3_TORPEDO, "Logic OMAP3 Torpedo board")
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
-	.init_irq	= omap3logic_init_irq,
+	.init_early	= omap3logic_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap_timer,
 MACHINE_END
@@ -233,7 +233,8 @@
 MACHINE_START(OMAP3530_LV_SOM, "OMAP Logic 3530 LV SOM board")
 	.boot_params	= 0x80000100,
 	.map_io		= omap3_map_io,
-	.init_irq	= omap3logic_init_irq,
+	.init_early	= omap3logic_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3logic_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3pandora.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3pandora.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3pandora.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3pandora.c	2011-05-19 00:06:34.000000000 -0400
@@ -253,14 +253,6 @@
 	.default_device	= &pandora_lcd_device,
 };
 
-static struct platform_device pandora_dss_device = {
-	.name		= "omapdss",
-	.id		= -1,
-	.dev		= {
-		.platform_data = &pandora_dss_data,
-	},
-};
-
 static void pandora_wl1251_init_card(struct mmc_card *card)
 {
 	/*
@@ -341,20 +333,21 @@
 };
 
 static struct regulator_consumer_supply pandora_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 static struct regulator_consumer_supply pandora_vmmc2_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_consumer_supply pandora_vmmc3_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.2");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.2");
 
 static struct regulator_consumer_supply pandora_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss");
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static struct regulator_consumer_supply pandora_vdds_supplies[] = {
 	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
 	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
 };
 
 static struct regulator_consumer_supply pandora_vcc_lcd_supply =
@@ -524,9 +517,7 @@
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data omap3pandora_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data omap3pandora_audio_data;
 
 static struct twl4030_codec_data omap3pandora_codec_data = {
 	.audio_mclk = 26000000,
@@ -634,12 +625,11 @@
 	}
 };
 
-static void __init omap3pandora_init_irq(void)
+static void __init omap3pandora_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
 }
 
 static void __init pandora_wl1251_init(void)
@@ -677,15 +667,14 @@
 static struct platform_device *omap3pandora_devices[] __initdata = {
 	&pandora_leds_gpio,
 	&pandora_keys_gpio,
-	&pandora_dss_device,
 	&pandora_vwlan_device,
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = 16,
@@ -712,11 +701,12 @@
 	pandora_wl1251_init();
 	platform_add_devices(omap3pandora_devices,
 			ARRAY_SIZE(omap3pandora_devices));
+	omap_display_init(&pandora_dss_data);
 	omap_serial_init();
 	spi_register_board_info(omap3pandora_spi_board_info,
 			ARRAY_SIZE(omap3pandora_spi_board_info));
 	omap3pandora_ads7846_init();
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	usb_musb_init(&musb_board_data);
 	gpmc_nand_init(&pandora_nand_data);
 
@@ -727,9 +717,10 @@
 
 MACHINE_START(OMAP3_PANDORA, "Pandora Handheld Console")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap3pandora_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3pandora_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap3pandora_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3stalker.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3stalker.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3stalker.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3stalker.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,14 +240,6 @@
 	.default_device	= &omap3_stalker_dvi_device,
 };
 
-static struct platform_device omap3_stalker_dss_device = {
-	.name	= "omapdss",
-	.id	= -1,
-	.dev	= {
-		.platform_data	= &omap3_stalker_dss_data,
-	},
-};
-
 static struct regulator_consumer_supply omap3stalker_vmmc1_supply = {
 	.supply		= "vmmc",
 };
@@ -439,19 +431,15 @@
 	.irq_line	= 1,
 };
 
-static struct twl4030_codec_audio_data omap3stalker_audio_data = {
-	.audio_mclk	= 26000000,
-};
+static struct twl4030_codec_audio_data omap3stalker_audio_data;
 
 static struct twl4030_codec_data omap3stalker_codec_data = {
 	.audio_mclk	= 26000000,
 	.audio		= &omap3stalker_audio_data,
 };
 
-static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply = {
-	.supply		= "vdda_dac",
-	.dev		= &omap3_stalker_dss_device.dev,
-};
+static struct regulator_consumer_supply omap3_stalker_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 /* VDAC for DSS driving S-Video */
 static struct regulator_init_data omap3_stalker_vdac = {
@@ -469,9 +457,9 @@
 };
 
 /* VPLL2 for digital video outputs */
-static struct regulator_consumer_supply omap3_stalker_vpll2_supply = {
-	.supply		= "vdds_dsi",
-	.dev		= &omap3_stalker_lcd_device.dev,
+static struct regulator_consumer_supply omap3_stalker_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
 };
 
 static struct regulator_init_data omap3_stalker_vpll2 = {
@@ -485,8 +473,8 @@
 		.valid_ops_mask		= REGULATOR_CHANGE_MODE
 		| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= 1,
-	.consumer_supplies	= &omap3_stalker_vpll2_supply,
+	.num_consumer_supplies	= ARRAY_SIZE(omap3_stalker_vpll2_supplies),
+	.consumer_supplies	= omap3_stalker_vpll2_supplies,
 };
 
 static struct twl4030_platform_data omap3stalker_twldata = {
@@ -591,12 +579,14 @@
 static struct omap_board_config_kernel omap3_stalker_config[] __initdata = {
 };
 
-static void __init omap3_stalker_init_irq(void)
+static void __init omap3_stalker_init_early(void)
 {
-	omap_board_config = omap3_stalker_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params, NULL);
+}
+
+static void __init omap3_stalker_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -604,14 +594,13 @@
 }
 
 static struct platform_device *omap3_stalker_devices[] __initdata = {
-	&omap3_stalker_dss_device,
 	&keys_gpio,
 };
 
-static struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset = true,
 	.reset_gpio_port[0] = -EINVAL,
@@ -638,18 +627,21 @@
 static void __init omap3_stalker_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CUS);
+	omap_board_config = omap3_stalker_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_stalker_config);
 
 	omap3_stalker_i2c_init();
 
 	platform_add_devices(omap3_stalker_devices,
 			     ARRAY_SIZE(omap3_stalker_devices));
 
+	omap_display_init(&omap3_stalker_dss_data);
 	spi_register_board_info(omap3stalker_spi_board_info,
 				ARRAY_SIZE(omap3stalker_spi_board_info));
 
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	ads7846_dev_init();
 
 	omap_mux_init_gpio(21, OMAP_PIN_OUTPUT);
@@ -666,6 +658,7 @@
 	/* Maintainer: Jason Lam -lzg@ema-tech.com */
 	.boot_params		= 0x80000100,
 	.map_io			= omap3_map_io,
+	.init_early		= omap3_stalker_init_early,
 	.init_irq		= omap3_stalker_init_irq,
 	.init_machine		= omap3_stalker_init,
 	.timer			= &omap_timer,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3touchbook.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3touchbook.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap3touchbook.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap3touchbook.c	2011-05-19 00:06:34.000000000 -0400
@@ -252,9 +252,7 @@
 	.usb_mode	= T2_USB_MODE_ULPI,
 };
 
-static struct twl4030_codec_audio_data touchbook_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data touchbook_audio_data;
 
 static struct twl4030_codec_data touchbook_codec_data = {
 	.audio_mclk = 26000000,
@@ -415,14 +413,15 @@
 };
 #endif
 
-static void __init omap3_touchbook_init_irq(void)
+static void __init omap3_touchbook_init_early(void)
 {
-	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
-	omap_board_config = omap3_touchbook_config;
-	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
+}
+
+static void __init omap3_touchbook_init_irq(void)
+{
 	omap_init_irq();
 #ifdef CONFIG_OMAP_32K_TIMER
 	omap2_gp_clockevent_set_gptimer(12);
@@ -468,11 +467,11 @@
 	}
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
 
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
@@ -510,6 +509,10 @@
 
 static void __init omap3_touchbook_init(void)
 {
+	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = omap3_touchbook_config;
+	omap_board_config_size = ARRAY_SIZE(omap3_touchbook_config);
+
 	pm_power_off = omap3_touchbook_poweroff;
 
 	omap3_touchbook_i2c_init();
@@ -527,7 +530,7 @@
 				ARRAY_SIZE(omap3_ads7846_spi_board_info));
 	omap3_ads7846_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 	omap3touchbook_flash_init();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
@@ -538,8 +541,9 @@
 MACHINE_START(TOUCHBOOK, "OMAP3 touchbook Board")
 	/* Maintainer: Gregoire Gentil - http://www.alwaysinnovating.com */
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
+	.map_io		= omap3_map_io,
+	.init_early	= omap3_touchbook_init_early,
 	.init_irq	= omap3_touchbook_init_irq,
 	.init_machine	= omap3_touchbook_init,
 	.timer		= &omap_timer,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap4panda.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap4panda.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-omap4panda.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-omap4panda.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,17 +26,21 @@
 #include <linux/usb/otg.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/wl12xx.h>
 
 #include <mach/hardware.h>
 #include <mach/omap4-common.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+#include <plat/display.h>
 
 #include <plat/board.h>
 #include <plat/common.h>
 #include <plat/usb.h>
 #include <plat/mmc.h>
+#include <plat/panel-generic-dpi.h>
 #include "timer-gp.h"
 
 #include "hsmmc.h"
@@ -45,6 +49,20 @@
 
 #define GPIO_HUB_POWER		1
 #define GPIO_HUB_NRESET		62
+#define GPIO_WIFI_PMENA		43
+#define GPIO_WIFI_IRQ		53
+#define HDMI_GPIO_HPD 60 /* Hot plug pin for HDMI */
+#define HDMI_GPIO_LS_OE 41 /* Level shifter for HDMI */
+
+/* wl127x BT, FM, GPS connectivity chip */
+static int wl1271_gpios[] = {46, -1, -1};
+static struct platform_device wl1271_device = {
+	.name	= "kim",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &wl1271_gpios,
+	},
+};
 
 static struct gpio_led gpio_leds[] = {
 	{
@@ -74,19 +92,19 @@
 
 static struct platform_device *panda_devices[] __initdata = {
 	&leds_gpio,
+	&wl1271_device,
 };
 
-static void __init omap4_panda_init_irq(void)
+static void __init omap4_panda_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(NULL, NULL);
-	gic_init_irq();
 }
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[1] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.phy_reset  = false,
 	.reset_gpio_port[0]  = -EINVAL,
 	.reset_gpio_port[1]  = -EINVAL,
@@ -128,7 +146,7 @@
 	gpio_set_value(GPIO_HUB_NRESET, 0);
 	gpio_set_value(GPIO_HUB_NRESET, 1);
 
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
 
 	/* enable power to hub */
 	gpio_set_value(GPIO_HUB_POWER, 1);
@@ -153,6 +171,7 @@
 	.phy_exit	= omap4430_phy_exit,
 	.phy_power	= omap4430_phy_power,
 	.phy_set_clock	= omap4430_phy_set_clk,
+	.phy_suspend	= omap4430_phy_suspend,
 };
 
 static struct omap2_hsmmc_info mmc[] = {
@@ -162,16 +181,62 @@
 		.gpio_wp	= -EINVAL,
 		.gpio_cd	= -EINVAL,
 	},
+	{
+		.name		= "wl1271",
+		.mmc		= 5,
+		.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_POWER_OFF_CARD,
+		.gpio_wp	= -EINVAL,
+		.gpio_cd	= -EINVAL,
+		.ocr_mask	= MMC_VDD_165_195,
+		.nonremovable	= true,
+	},
 	{}	/* Terminator */
 };
 
 static struct regulator_consumer_supply omap4_panda_vmmc_supply[] = {
 	{
 		.supply = "vmmc",
-		.dev_name = "mmci-omap-hs.0",
+		.dev_name = "omap_hsmmc.0",
+	},
+};
+
+static struct regulator_consumer_supply omap4_panda_vmmc5_supply = {
+	.supply = "vmmc",
+	.dev_name = "omap_hsmmc.4",
+};
+
+static struct regulator_init_data panda_vmmc5 = {
+	.constraints = {
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = 1,
+	.consumer_supplies = &omap4_panda_vmmc5_supply,
+};
+
+static struct fixed_voltage_config panda_vwlan = {
+	.supply_name = "vwl1271",
+	.microvolts = 1800000, /* 1.8V */
+	.gpio = GPIO_WIFI_PMENA,
+	.startup_delay = 70000, /* 70msec */
+	.enable_high = 1,
+	.enabled_at_boot = 0,
+	.init_data = &panda_vmmc5,
+};
+
+static struct platform_device omap_vwlan_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &panda_vwlan,
 	},
 };
 
+struct wl12xx_platform_data omap_panda_wlan_data  __initdata = {
+	.irq = OMAP_GPIO_IRQ(GPIO_WIFI_IRQ),
+	/* PANDA ref clock is 38.4 MHz */
+	.board_ref_clock = 2,
+};
+
 static int omap4_twl6030_hsmmc_late_init(struct device *dev)
 {
 	int ret = 0;
@@ -220,19 +285,6 @@
 	return 0;
 }
 
-static struct regulator_init_data omap4_panda_vaux1 = {
-	.constraints = {
-		.min_uV			= 1000000,
-		.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,
-	},
-};
-
 static struct regulator_init_data omap4_panda_vaux2 = {
 	.constraints = {
 		.min_uV			= 1200000,
@@ -288,24 +340,10 @@
 	},
 };
 
-static struct regulator_init_data omap4_panda_vusim = {
-	.constraints = {
-		.min_uV			= 1200000,
-		.max_uV			= 2900000,
-		.apply_uV		= true,
-		.valid_modes_mask	= REGULATOR_MODE_NORMAL
-					| REGULATOR_MODE_STANDBY,
-		.valid_ops_mask	 = REGULATOR_CHANGE_VOLTAGE
-					| REGULATOR_CHANGE_MODE
-					| REGULATOR_CHANGE_STATUS,
-	},
-};
-
 static struct regulator_init_data omap4_panda_vana = {
 	.constraints = {
 		.min_uV			= 2100000,
 		.max_uV			= 2100000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -317,7 +355,6 @@
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -329,7 +366,6 @@
 	.constraints = {
 		.min_uV			= 1800000,
 		.max_uV			= 1800000,
-		.apply_uV		= true,
 		.valid_modes_mask	= REGULATOR_MODE_NORMAL
 					| REGULATOR_MODE_STANDBY,
 		.valid_ops_mask	 = REGULATOR_CHANGE_MODE
@@ -349,6 +385,12 @@
 	},
 };
 
+static struct regulator_init_data omap4_panda_clk32kg = {
+	.constraints = {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+	},
+};
+
 static struct twl4030_platform_data omap4_panda_twldata = {
 	.irq_base	= TWL6030_IRQ_BASE,
 	.irq_end	= TWL6030_IRQ_END,
@@ -356,14 +398,13 @@
 	/* Regulators */
 	.vmmc		= &omap4_panda_vmmc,
 	.vpp		= &omap4_panda_vpp,
-	.vusim		= &omap4_panda_vusim,
 	.vana		= &omap4_panda_vana,
 	.vcxio		= &omap4_panda_vcxio,
 	.vdac		= &omap4_panda_vdac,
 	.vusb		= &omap4_panda_vusb,
-	.vaux1		= &omap4_panda_vaux1,
 	.vaux2		= &omap4_panda_vaux2,
 	.vaux3		= &omap4_panda_vaux3,
+	.clk32kg	= &omap4_panda_clk32kg,
 	.usb		= &omap4_usbphy_data,
 };
 
@@ -375,6 +416,17 @@
 		.platform_data = &omap4_panda_twldata,
 	},
 };
+
+/*
+ * Display monitor features are burnt in their EEPROM as EDID data. The EEPROM
+ * is connected as I2C slave device, and can be accessed at address 0x50
+ */
+static struct i2c_board_info __initdata panda_i2c_eeprom[] = {
+	{
+		I2C_BOARD_INFO("eeprom", 0x50),
+	},
+};
+
 static int __init omap4_panda_i2c_init(void)
 {
 	/*
@@ -384,19 +436,284 @@
 	omap_register_i2c_bus(1, 400, omap4_panda_i2c_boardinfo,
 			ARRAY_SIZE(omap4_panda_i2c_boardinfo));
 	omap_register_i2c_bus(2, 400, NULL, 0);
-	omap_register_i2c_bus(3, 400, NULL, 0);
+	/*
+	 * Bus 3 is attached to the DVI port where devices like the pico DLP
+	 * projector don't work reliably with 400kHz
+	 */
+	omap_register_i2c_bus(3, 100, panda_i2c_eeprom,
+					ARRAY_SIZE(panda_i2c_eeprom));
 	omap_register_i2c_bus(4, 400, NULL, 0);
 	return 0;
 }
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+	/* WLAN IRQ - GPIO 53 */
+	OMAP4_MUX(GPMC_NCS3, OMAP_MUX_MODE3 | OMAP_PIN_INPUT),
+	/* WLAN POWER ENABLE - GPIO 43 */
+	OMAP4_MUX(GPMC_A19, OMAP_MUX_MODE3 | OMAP_PIN_OUTPUT),
+	/* WLAN SDIO: MMC5 CMD */
+	OMAP4_MUX(SDMMC5_CMD, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 CLK */
+	OMAP4_MUX(SDMMC5_CLK, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* WLAN SDIO: MMC5 DAT[0-3] */
+	OMAP4_MUX(SDMMC5_DAT0, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT1, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT2, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	OMAP4_MUX(SDMMC5_DAT3, OMAP_MUX_MODE0 | OMAP_PIN_INPUT_PULLUP),
+	/* gpio 0 - TFP410 PD */
+	OMAP4_MUX(KPD_COL1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE3),
+	/* dispc2_data23 */
+	OMAP4_MUX(USBB2_ULPITLL_STP, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data22 */
+	OMAP4_MUX(USBB2_ULPITLL_DIR, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data21 */
+	OMAP4_MUX(USBB2_ULPITLL_NXT, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data20 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT0, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data19 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT1, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data18 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT2, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data15 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data14 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data13 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data12 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data11 */
+	OMAP4_MUX(USBB2_ULPITLL_DAT7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data10 */
+	OMAP4_MUX(DPM_EMU3, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data9 */
+	OMAP4_MUX(DPM_EMU4, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data16 */
+	OMAP4_MUX(DPM_EMU5, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data17 */
+	OMAP4_MUX(DPM_EMU6, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_hsync */
+	OMAP4_MUX(DPM_EMU7, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_pclk */
+	OMAP4_MUX(DPM_EMU8, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_vsync */
+	OMAP4_MUX(DPM_EMU9, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_de */
+	OMAP4_MUX(DPM_EMU10, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data8 */
+	OMAP4_MUX(DPM_EMU11, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data7 */
+	OMAP4_MUX(DPM_EMU12, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data6 */
+	OMAP4_MUX(DPM_EMU13, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data5 */
+	OMAP4_MUX(DPM_EMU14, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data4 */
+	OMAP4_MUX(DPM_EMU15, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data3 */
+	OMAP4_MUX(DPM_EMU16, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data2 */
+	OMAP4_MUX(DPM_EMU17, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data1 */
+	OMAP4_MUX(DPM_EMU18, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
+	/* dispc2_data0 */
+	OMAP4_MUX(DPM_EMU19, OMAP_PIN_OUTPUT | OMAP_MUX_MODE5),
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
+
+static struct omap_device_pad serial2_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart2_cts.uart2_cts",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rts.uart2_rts",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_rx.uart2_rx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart2_tx.uart2_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial3_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart3_cts_rctx.uart3_cts_rctx",
+			 OMAP_PIN_INPUT_PULLUP | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rts_sd.uart3_rts_sd",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_rx_irrx.uart3_rx_irrx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart3_tx_irtx.uart3_tx_irtx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_device_pad serial4_pads[] __initdata = {
+	OMAP_MUX_STATIC("uart4_rx.uart4_rx",
+			 OMAP_PIN_INPUT | OMAP_MUX_MODE0),
+	OMAP_MUX_STATIC("uart4_tx.uart4_tx",
+			 OMAP_PIN_OUTPUT | OMAP_MUX_MODE0),
+};
+
+static struct omap_board_data serial2_data = {
+	.id             = 1,
+	.pads           = serial2_pads,
+	.pads_cnt       = ARRAY_SIZE(serial2_pads),
+};
+
+static struct omap_board_data serial3_data = {
+	.id             = 2,
+	.pads           = serial3_pads,
+	.pads_cnt       = ARRAY_SIZE(serial3_pads),
+};
+
+static struct omap_board_data serial4_data = {
+	.id             = 3,
+	.pads           = serial4_pads,
+	.pads_cnt       = ARRAY_SIZE(serial4_pads),
+};
+
+static inline void board_serial_init(void)
+{
+	struct omap_board_data bdata;
+	bdata.flags     = 0;
+	bdata.pads      = NULL;
+	bdata.pads_cnt  = 0;
+	bdata.id        = 0;
+	/* pass dummy data for UART1 */
+	omap_serial_init_port(&bdata);
+
+	omap_serial_init_port(&serial2_data);
+	omap_serial_init_port(&serial3_data);
+	omap_serial_init_port(&serial4_data);
+}
 #else
 #define board_mux	NULL
+
+static inline void board_serial_init(void)
+{
+	omap_serial_init();
+}
 #endif
 
+/* Display DVI */
+#define PANDA_DVI_TFP410_POWER_DOWN_GPIO	0
+
+static int omap4_panda_enable_dvi(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(dssdev->reset_gpio, 1);
+	return 0;
+}
+
+static void omap4_panda_disable_dvi(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(dssdev->reset_gpio, 0);
+}
+
+/* Using generic display panel */
+static struct panel_generic_dpi_data omap4_dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= omap4_panda_enable_dvi,
+	.platform_disable	= omap4_panda_disable_dvi,
+};
+
+struct omap_dss_device omap4_panda_dvi_device = {
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.name			= "dvi",
+	.driver_name		= "generic_dpi_panel",
+	.data			= &omap4_dvi_panel,
+	.phy.dpi.data_lines	= 24,
+	.reset_gpio		= PANDA_DVI_TFP410_POWER_DOWN_GPIO,
+	.channel		= OMAP_DSS_CHANNEL_LCD2,
+};
+
+int __init omap4_panda_dvi_init(void)
+{
+	int r;
+
+	/* Requesting TFP410 DVI GPIO and disabling it, at bootup */
+	r = gpio_request_one(omap4_panda_dvi_device.reset_gpio,
+				GPIOF_OUT_INIT_LOW, "DVI PD");
+	if (r)
+		pr_err("Failed to get DVI powerdown GPIO\n");
+
+	return r;
+}
+
+
+static void omap4_panda_hdmi_mux_init(void)
+{
+	/* PAD0_HDMI_HPD_PAD1_HDMI_CEC */
+	omap_mux_init_signal("hdmi_hpd",
+			OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("hdmi_cec",
+			OMAP_PIN_INPUT_PULLUP);
+	/* PAD0_HDMI_DDC_SCL_PAD1_HDMI_DDC_SDA */
+	omap_mux_init_signal("hdmi_ddc_scl",
+			OMAP_PIN_INPUT_PULLUP);
+	omap_mux_init_signal("hdmi_ddc_sda",
+			OMAP_PIN_INPUT_PULLUP);
+}
+
+static int omap4_panda_panel_enable_hdmi(struct omap_dss_device *dssdev)
+{
+	int status;
+
+	status = gpio_request_one(HDMI_GPIO_HPD, GPIOF_OUT_INIT_HIGH,
+							"hdmi_gpio_hpd");
+	if (status) {
+		pr_err("Cannot request GPIO %d\n", HDMI_GPIO_HPD);
+		return status;
+	}
+	status = gpio_request_one(HDMI_GPIO_LS_OE, GPIOF_OUT_INIT_HIGH,
+							"hdmi_gpio_ls_oe");
+	if (status) {
+		pr_err("Cannot request GPIO %d\n", HDMI_GPIO_LS_OE);
+		goto error1;
+	}
+
+	return 0;
+
+error1:
+	gpio_free(HDMI_GPIO_HPD);
+
+	return status;
+}
+
+static void omap4_panda_panel_disable_hdmi(struct omap_dss_device *dssdev)
+{
+	gpio_free(HDMI_GPIO_LS_OE);
+	gpio_free(HDMI_GPIO_HPD);
+}
+
+static struct omap_dss_device  omap4_panda_hdmi_device = {
+	.name = "hdmi",
+	.driver_name = "hdmi_panel",
+	.type = OMAP_DISPLAY_TYPE_HDMI,
+	.platform_enable = omap4_panda_panel_enable_hdmi,
+	.platform_disable = omap4_panda_panel_disable_hdmi,
+	.channel = OMAP_DSS_CHANNEL_DIGIT,
+};
+
+static struct omap_dss_device *omap4_panda_dss_devices[] = {
+	&omap4_panda_dvi_device,
+	&omap4_panda_hdmi_device,
+};
+
+static struct omap_dss_board_info omap4_panda_dss_data = {
+	.num_devices	= ARRAY_SIZE(omap4_panda_dss_devices),
+	.devices	= omap4_panda_dss_devices,
+	.default_device	= &omap4_panda_dvi_device,
+};
+
+void omap4_panda_display_init(void)
+{
+	int r;
+
+	r = omap4_panda_dvi_init();
+	if (r)
+		pr_err("error initializing panda DVI\n");
+
+	omap4_panda_hdmi_mux_init();
+	omap_display_init(&omap4_panda_dss_data);
+}
+
 static void __init omap4_panda_init(void)
 {
 	int package = OMAP_PACKAGE_CBS;
@@ -405,12 +722,17 @@
 		package = OMAP_PACKAGE_CBL;
 	omap4_mux_init(board_mux, package);
 
+	if (wl12xx_set_platform_data(&omap_panda_wlan_data))
+		pr_err("error setting wl12xx data\n");
+
 	omap4_panda_i2c_init();
 	platform_add_devices(panda_devices, ARRAY_SIZE(panda_devices));
-	omap_serial_init();
+	platform_device_register(&omap_vwlan_device);
+	board_serial_init();
 	omap4_twl6030_hsmmc_init(mmc);
 	omap4_ehci_init();
 	usb_musb_init(&musb_board_data);
+	omap4_panda_display_init();
 }
 
 static void __init omap4_panda_map_io(void)
@@ -424,7 +746,8 @@
 	.boot_params	= 0x80000100,
 	.reserve	= omap_reserve,
 	.map_io		= omap4_panda_map_io,
-	.init_irq	= omap4_panda_init_irq,
+	.init_early	= omap4_panda_init_early,
+	.init_irq	= gic_init_irq,
 	.init_machine	= omap4_panda_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-overo.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-overo.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-overo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-overo.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,8 @@
 #include <linux/platform_device.h>
 #include <linux/i2c/twl.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/fixed.h>
+#include <linux/spi/spi.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -41,10 +43,14 @@
 
 #include <plat/board.h>
 #include <plat/common.h>
+#include <plat/display.h>
+#include <plat/panel-generic-dpi.h>
 #include <mach/gpio.h>
 #include <plat/gpmc.h>
 #include <mach/hardware.h>
 #include <plat/nand.h>
+#include <plat/mcspi.h>
+#include <plat/mux.h>
 #include <plat/usb.h>
 
 #include "mux.h"
@@ -68,8 +74,6 @@
 #if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
 	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
 
-#include <plat/mcspi.h>
-#include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 
 static struct omap2_mcspi_device_config ads7846_mcspi_config = {
@@ -94,16 +98,32 @@
 	.keep_vref_on		= 1,
 };
 
-static struct spi_board_info overo_spi_board_info[] __initdata = {
-	{
-		.modalias		= "ads7846",
-		.bus_num		= 1,
-		.chip_select		= 0,
-		.max_speed_hz		= 1500000,
-		.controller_data	= &ads7846_mcspi_config,
-		.irq			= OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
-		.platform_data		= &ads7846_config,
-	}
+/* fixed regulator for ads7846 */
+static struct regulator_consumer_supply ads7846_supply =
+	REGULATOR_SUPPLY("vcc", "spi1.0");
+
+static struct regulator_init_data vads7846_regulator = {
+	.constraints = {
+		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &ads7846_supply,
+};
+
+static struct fixed_voltage_config vads7846 = {
+	.supply_name		= "vads7846",
+	.microvolts		= 3300000, /* 3.3V */
+	.gpio			= -EINVAL,
+	.startup_delay		= 0,
+	.init_data		= &vads7846_regulator,
+};
+
+static struct platform_device vads7846_device = {
+	.name		= "reg-fixed-voltage",
+	.id		= 1,
+	.dev = {
+		.platform_data = &vads7846,
+	},
 };
 
 static void __init overo_ads7846_init(void)
@@ -116,8 +136,7 @@
 		return;
 	}
 
-	spi_register_board_info(overo_spi_board_info,
-			ARRAY_SIZE(overo_spi_board_info));
+	platform_device_register(&vads7846_device);
 }
 
 #else
@@ -233,6 +252,137 @@
 static inline void __init overo_init_smsc911x(void) { return; }
 #endif
 
+/* DSS */
+static int lcd_enabled;
+static int dvi_enabled;
+
+#define OVERO_GPIO_LCD_EN 144
+#define OVERO_GPIO_LCD_BL 145
+
+static void __init overo_display_init(void)
+{
+	if ((gpio_request(OVERO_GPIO_LCD_EN, "OVERO_GPIO_LCD_EN") == 0) &&
+	    (gpio_direction_output(OVERO_GPIO_LCD_EN, 1) == 0))
+		gpio_export(OVERO_GPIO_LCD_EN, 0);
+	else
+		printk(KERN_ERR "could not obtain gpio for "
+					"OVERO_GPIO_LCD_EN\n");
+
+	if ((gpio_request(OVERO_GPIO_LCD_BL, "OVERO_GPIO_LCD_BL") == 0) &&
+	    (gpio_direction_output(OVERO_GPIO_LCD_BL, 1) == 0))
+		gpio_export(OVERO_GPIO_LCD_BL, 0);
+	else
+		printk(KERN_ERR "could not obtain gpio for "
+					"OVERO_GPIO_LCD_BL\n");
+}
+
+static int overo_panel_enable_dvi(struct omap_dss_device *dssdev)
+{
+	if (lcd_enabled) {
+		printk(KERN_ERR "cannot enable DVI, LCD is enabled\n");
+		return -EINVAL;
+	}
+	dvi_enabled = 1;
+
+	return 0;
+}
+
+static void overo_panel_disable_dvi(struct omap_dss_device *dssdev)
+{
+	dvi_enabled = 0;
+}
+
+static struct panel_generic_dpi_data dvi_panel = {
+	.name			= "generic",
+	.platform_enable	= overo_panel_enable_dvi,
+	.platform_disable	= overo_panel_disable_dvi,
+};
+
+static struct omap_dss_device overo_dvi_device = {
+	.name			= "dvi",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &dvi_panel,
+	.phy.dpi.data_lines	= 24,
+};
+
+static struct omap_dss_device overo_tv_device = {
+	.name = "tv",
+	.driver_name = "venc",
+	.type = OMAP_DISPLAY_TYPE_VENC,
+	.phy.venc.type = OMAP_DSS_VENC_TYPE_SVIDEO,
+};
+
+static int overo_panel_enable_lcd(struct omap_dss_device *dssdev)
+{
+	if (dvi_enabled) {
+		printk(KERN_ERR "cannot enable LCD, DVI is enabled\n");
+		return -EINVAL;
+	}
+
+	gpio_set_value(OVERO_GPIO_LCD_EN, 1);
+	gpio_set_value(OVERO_GPIO_LCD_BL, 1);
+	lcd_enabled = 1;
+	return 0;
+}
+
+static void overo_panel_disable_lcd(struct omap_dss_device *dssdev)
+{
+	gpio_set_value(OVERO_GPIO_LCD_EN, 0);
+	gpio_set_value(OVERO_GPIO_LCD_BL, 0);
+	lcd_enabled = 0;
+}
+
+static struct panel_generic_dpi_data lcd43_panel = {
+	.name			= "samsung_lte430wq_f0c",
+	.platform_enable	= overo_panel_enable_lcd,
+	.platform_disable	= overo_panel_disable_lcd,
+};
+
+static struct omap_dss_device overo_lcd43_device = {
+	.name			= "lcd43",
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.driver_name		= "generic_dpi_panel",
+	.data			= &lcd43_panel,
+	.phy.dpi.data_lines	= 24,
+};
+
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+	defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+static struct omap_dss_device overo_lcd35_device = {
+	.type			= OMAP_DISPLAY_TYPE_DPI,
+	.name			= "lcd35",
+	.driver_name		= "lgphilips_lb035q02_panel",
+	.phy.dpi.data_lines	= 24,
+	.platform_enable	= overo_panel_enable_lcd,
+	.platform_disable	= overo_panel_disable_lcd,
+};
+#endif
+
+static struct omap_dss_device *overo_dss_devices[] = {
+	&overo_dvi_device,
+	&overo_tv_device,
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+	defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+	&overo_lcd35_device,
+#endif
+	&overo_lcd43_device,
+};
+
+static struct omap_dss_board_info overo_dss_data = {
+	.num_devices	= ARRAY_SIZE(overo_dss_devices),
+	.devices	= overo_dss_devices,
+	.default_device	= &overo_dvi_device,
+};
+
+static struct regulator_consumer_supply overo_vdda_dac_supply =
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
+
+static struct regulator_consumer_supply overo_vdds_dsi_supply[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
+
 static struct mtd_partition overo_nand_partitions[] = {
 	{
 		.name           = "xloader",
@@ -323,6 +473,93 @@
 	.supply			= "vmmc",
 };
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+#include <linux/leds.h>
+
+static struct gpio_led gpio_leds[] = {
+	{
+		.name			= "overo:red:gpio21",
+		.default_trigger	= "heartbeat",
+		.gpio			= 21,
+		.active_low		= true,
+	},
+	{
+		.name			= "overo:blue:gpio22",
+		.default_trigger	= "none",
+		.gpio			= 22,
+		.active_low		= true,
+	},
+	{
+		.name			= "overo:blue:COM",
+		.default_trigger	= "mmc0",
+		.gpio			= -EINVAL,	/* gets replaced */
+		.active_low		= true,
+	},
+};
+
+static struct gpio_led_platform_data gpio_leds_pdata = {
+	.leds		= gpio_leds,
+	.num_leds	= ARRAY_SIZE(gpio_leds),
+};
+
+static struct platform_device gpio_leds_device = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_leds_pdata,
+	},
+};
+
+static void __init overo_init_led(void)
+{
+	platform_device_register(&gpio_leds_device);
+}
+
+#else
+static inline void __init overo_init_led(void) { return; }
+#endif
+
+#if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
+static struct gpio_keys_button gpio_buttons[] = {
+	{
+		.code			= BTN_0,
+		.gpio			= 23,
+		.desc			= "button0",
+		.wakeup			= 1,
+	},
+	{
+		.code			= BTN_1,
+		.gpio			= 14,
+		.desc			= "button1",
+		.wakeup			= 1,
+	},
+};
+
+static struct gpio_keys_platform_data gpio_keys_pdata = {
+	.buttons	= gpio_buttons,
+	.nbuttons	= ARRAY_SIZE(gpio_buttons),
+};
+
+static struct platform_device gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gpio_keys_pdata,
+	},
+};
+
+static void __init overo_init_keys(void)
+{
+	platform_device_register(&gpio_keys_device);
+}
+
+#else
+static inline void __init overo_init_keys(void) { return; }
+#endif
+
 static int overo_twl_gpio_setup(struct device *dev,
 		unsigned gpio, unsigned ngpio)
 {
@@ -330,6 +567,11 @@
 
 	overo_vmmc1_supply.dev = mmc[0].dev;
 
+#if defined(CONFIG_LEDS_GPIO) || defined(CONFIG_LEDS_GPIO_MODULE)
+	/* TWL4030_GPIO_MAX + 1 == ledB, PMU_STAT (out, active low LED) */
+	gpio_leds[2].gpio = gpio + TWL4030_GPIO_MAX + 1;
+#endif
+
 	return 0;
 }
 
@@ -337,6 +579,7 @@
 	.gpio_base	= OMAP_MAX_GPIO_LINES,
 	.irq_base	= TWL4030_GPIO_IRQ_BASE,
 	.irq_end	= TWL4030_GPIO_IRQ_END,
+	.use_leds	= true,
 	.setup		= overo_twl_gpio_setup,
 };
 
@@ -358,17 +601,42 @@
 	.consumer_supplies	= &overo_vmmc1_supply,
 };
 
-static struct twl4030_codec_audio_data overo_audio_data = {
-	.audio_mclk = 26000000,
+/* VDAC for DSS driving S-Video (8 mA unloaded, max 65 mA) */
+static struct regulator_init_data overo_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	= &overo_vdda_dac_supply,
+};
+
+/* VPLL2 for digital video outputs */
+static struct regulator_init_data overo_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	= ARRAY_SIZE(overo_vdds_dsi_supply),
+	.consumer_supplies	= overo_vdds_dsi_supply,
 };
 
+static struct twl4030_codec_audio_data overo_audio_data;
+
 static struct twl4030_codec_data overo_codec_data = {
 	.audio_mclk = 26000000,
 	.audio = &overo_audio_data,
 };
 
-/* 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,
@@ -376,6 +644,8 @@
 	.usb		= &overo_usb_data,
 	.codec		= &overo_codec_data,
 	.vmmc1		= &overo_vmmc1,
+	.vdac		= &overo_vdac,
+	.vpll2		= &overo_vpll2,
 };
 
 static struct i2c_board_info __initdata overo_i2c_boardinfo[] = {
@@ -396,38 +666,50 @@
 	return 0;
 }
 
-static struct platform_device overo_lcd_device = {
-	.name		= "overo_lcd",
-	.id		= -1,
-};
-
-static struct omap_lcd_config overo_lcd_config __initdata = {
-	.ctrl_name	= "internal",
+static struct spi_board_info overo_spi_board_info[] __initdata = {
+#if defined(CONFIG_TOUCHSCREEN_ADS7846) || \
+	defined(CONFIG_TOUCHSCREEN_ADS7846_MODULE)
+	{
+		.modalias		= "ads7846",
+		.bus_num		= 1,
+		.chip_select		= 0,
+		.max_speed_hz		= 1500000,
+		.controller_data	= &ads7846_mcspi_config,
+		.irq			= OMAP_GPIO_IRQ(OVERO_GPIO_PENDOWN),
+		.platform_data		= &ads7846_config,
+	},
+#endif
+#if defined(CONFIG_PANEL_LGPHILIPS_LB035Q02) || \
+	defined(CONFIG_PANEL_LGPHILIPS_LB035Q02_MODULE)
+	{
+		.modalias		= "lgphilips_lb035q02_panel-spi",
+		.bus_num		= 1,
+		.chip_select		= 1,
+		.max_speed_hz		= 500000,
+		.mode			= SPI_MODE_3,
+	},
+#endif
 };
 
-static struct omap_board_config_kernel overo_config[] __initdata = {
-	{ OMAP_TAG_LCD,		&overo_lcd_config },
-};
+static int __init overo_spi_init(void)
+{
+	overo_ads7846_init();
+	spi_register_board_info(overo_spi_board_info,
+			ARRAY_SIZE(overo_spi_board_info));
+	return 0;
+}
 
-static void __init overo_init_irq(void)
+static void __init overo_init_early(void)
 {
-	omap_board_config = overo_config;
-	omap_board_config_size = ARRAY_SIZE(overo_config);
 	omap2_init_common_infrastructure();
 	omap2_init_common_devices(mt46h32m32lf6_sdrc_params,
 				  mt46h32m32lf6_sdrc_params);
-	omap_init_irq();
 }
 
-static struct platform_device *overo_devices[] __initdata = {
-	&overo_lcd_device,
-};
-
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1] = EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2] = EHCI_HCD_OMAP_MODE_UNKNOWN,
-
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0] = OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1] = OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2] = OMAP_USBHS_PORT_MODE_UNUSED,
 	.phy_reset  = true,
 	.reset_gpio_port[0]  = -EINVAL,
 	.reset_gpio_port[1]  = OVERO_GPIO_USBH_NRESET,
@@ -450,13 +732,17 @@
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
 	overo_i2c_init();
-	platform_add_devices(overo_devices, ARRAY_SIZE(overo_devices));
+	omap_display_init(&overo_dss_data);
 	omap_serial_init();
 	overo_flash_init();
 	usb_musb_init(&musb_board_data);
-	usb_ehci_init(&ehci_pdata);
+	usbhs_init(&usbhs_bdata);
+	overo_spi_init();
 	overo_ads7846_init();
 	overo_init_smsc911x();
+	overo_display_init();
+	overo_init_led();
+	overo_init_keys();
 
 	/* Ensure SDRC pins are mux'd for self-refresh */
 	omap_mux_init_signal("sdrc_cke0", OMAP_PIN_OUTPUT);
@@ -501,9 +787,10 @@
 
 MACHINE_START(OVERO, "Gumstix Overo")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= overo_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= overo_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= overo_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rm680.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rm680.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rm680.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rm680.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 #include "sdram-nokia.h"
 
 static struct regulator_consumer_supply rm680_vemmc_consumers[] = {
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"),
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
 
 /* Fixed regulator for internal eMMC */
@@ -138,14 +138,13 @@
 	omap2_hsmmc_init(mmc);
 }
 
-static void __init rm680_init_irq(void)
+static void __init rm680_init_early(void)
 {
 	struct omap_sdrc_params *sdrc_params;
 
 	omap2_init_common_infrastructure();
 	sdrc_params = nokia_get_sdram_timings();
 	omap2_init_common_devices(sdrc_params, sdrc_params);
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
@@ -176,9 +175,10 @@
 
 MACHINE_START(NOKIA_RM680, "Nokia RM-680 board")
 	.boot_params	= 0x80000100,
-	.map_io		= rm680_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= rm680_init_irq,
+	.map_io		= rm680_map_io,
+	.init_early	= rm680_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= rm680_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rx51.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rx51.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rx51.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rx51.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,17 +98,13 @@
 	{ OMAP_TAG_LCD,		&rx51_lcd_config },
 };
 
-static void __init rx51_init_irq(void)
+static void __init rx51_init_early(void)
 {
 	struct omap_sdrc_params *sdrc_params;
 
-	omap_board_config = rx51_config;
-	omap_board_config_size = ARRAY_SIZE(rx51_config);
-	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	omap2_init_common_infrastructure();
 	sdrc_params = nokia_get_sdram_timings();
 	omap2_init_common_devices(sdrc_params, sdrc_params);
-	omap_init_irq();
 }
 
 extern void __init rx51_peripherals_init(void);
@@ -128,6 +124,9 @@
 static void __init rx51_init(void)
 {
 	omap3_mux_init(board_mux, OMAP_PACKAGE_CBB);
+	omap_board_config = rx51_config;
+	omap_board_config_size = ARRAY_SIZE(rx51_config);
+	omap3_pm_init_cpuidle(rx51_cpuidle_params);
 	omap_serial_init();
 	usb_musb_init(&musb_board_data);
 	rx51_peripherals_init();
@@ -142,16 +141,22 @@
 static void __init rx51_map_io(void)
 {
 	omap2_set_globals_3xxx();
-	rx51_video_mem_init();
 	omap34xx_map_common_io();
 }
 
+static void __init rx51_reserve(void)
+{
+	rx51_video_mem_init();
+	omap_reserve();
+}
+
 MACHINE_START(NOKIA_RX51, "Nokia RX-51 board")
 	/* Maintainer: Lauri Leukkunen <lauri.leukkunen@nokia.com> */
 	.boot_params	= 0x80000100,
+	.reserve	= rx51_reserve,
 	.map_io		= rx51_map_io,
-	.reserve	= omap_reserve,
-	.init_irq	= rx51_init_irq,
+	.init_early	= rx51_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= rx51_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rx51-peripherals.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,8 @@
 
 #include <sound/tlv320aic3x.h>
 #include <sound/tpa6130a2-plat.h>
+#include <media/radio-si4713.h>
+#include <media/si4713.h>
 
 #include <../drivers/staging/iio/light/tsl2563.h>
 
@@ -47,6 +49,8 @@
 
 #define RX51_WL1251_POWER_GPIO		87
 #define RX51_WL1251_IRQ_GPIO		42
+#define RX51_FMTX_RESET_GPIO		163
+#define RX51_FMTX_IRQ			53
 
 /* list all spi devices here */
 enum {
@@ -331,13 +335,13 @@
 };
 
 static struct regulator_consumer_supply rx51_vmmc1_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.0");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.0");
 
 static struct regulator_consumer_supply rx51_vaux3_supply =
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1");
 
 static struct regulator_consumer_supply rx51_vsim_supply =
-	REGULATOR_SUPPLY("vmmc_aux", "mmci-omap-hs.1");
+	REGULATOR_SUPPLY("vmmc_aux", "omap_hsmmc.1");
 
 static struct regulator_consumer_supply rx51_vmmc2_supplies[] = {
 	/* tlv320aic3x analog supplies */
@@ -348,7 +352,7 @@
 	/* tpa6130a2 */
 	REGULATOR_SUPPLY("Vdd", "2-0060"),
 	/* Keep vmmc as last item. It is not iterated for newer boards */
-	REGULATOR_SUPPLY("vmmc", "mmci-omap-hs.1"),
+	REGULATOR_SUPPLY("vmmc", "omap_hsmmc.1"),
 };
 
 static struct regulator_consumer_supply rx51_vio_supplies[] = {
@@ -357,14 +361,18 @@
 	REGULATOR_SUPPLY("DVDD", "2-0018"),
 	REGULATOR_SUPPLY("IOVDD", "2-0019"),
 	REGULATOR_SUPPLY("DVDD", "2-0019"),
+	/* Si4713 IO supply */
+	REGULATOR_SUPPLY("vio", "2-0063"),
 };
 
 static struct regulator_consumer_supply rx51_vaux1_consumers[] = {
 	REGULATOR_SUPPLY("vdds_sdi", "omapdss"),
+	/* Si4713 supply */
+	REGULATOR_SUPPLY("vdd", "2-0063"),
 };
 
 static struct regulator_consumer_supply rx51_vdac_supply[] = {
-	REGULATOR_SUPPLY("vdda_dac", "omapdss"),
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc"),
 };
 
 static struct regulator_init_data rx51_vaux1 = {
@@ -511,6 +519,41 @@
 	.consumer_supplies	= rx51_vio_supplies,
 };
 
+static struct si4713_platform_data rx51_si4713_i2c_data __initdata_or_module = {
+	.gpio_reset	= RX51_FMTX_RESET_GPIO,
+};
+
+static struct i2c_board_info rx51_si4713_board_info __initdata_or_module = {
+	I2C_BOARD_INFO("si4713", SI4713_I2C_ADDR_BUSEN_HIGH),
+	.platform_data	= &rx51_si4713_i2c_data,
+};
+
+static struct radio_si4713_platform_data rx51_si4713_data __initdata_or_module = {
+	.i2c_bus	= 2,
+	.subdev_board_info = &rx51_si4713_board_info,
+};
+
+static struct platform_device rx51_si4713_dev __initdata_or_module = {
+	.name	= "radio-si4713",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &rx51_si4713_data,
+	},
+};
+
+static __init void rx51_init_si4713(void)
+{
+	int err;
+
+	err = gpio_request_one(RX51_FMTX_IRQ, GPIOF_DIR_IN, "si4713 irq");
+	if (err) {
+		printk(KERN_ERR "Cannot request si4713 irq gpio. %d\n", err);
+		return;
+	}
+	rx51_si4713_board_info.irq = gpio_to_irq(RX51_FMTX_IRQ);
+	platform_device_register(&rx51_si4713_dev);
+}
+
 static int rx51_twlgpio_setup(struct device *dev, unsigned gpio, unsigned n)
 {
 	/* FIXME this gpio setup is just a placeholder for now */
@@ -699,6 +742,14 @@
 	.resource_config = twl4030_rconfig,
 };
 
+struct twl4030_codec_vibra_data rx51_vibra_data __initdata = {
+	.coexist	= 0,
+};
+
+struct twl4030_codec_data rx51_codec_data __initdata = {
+	.audio_mclk	= 26000000,
+	.vibra		= &rx51_vibra_data,
+};
 
 static struct twl4030_platform_data rx51_twldata __initdata = {
 	.irq_base		= TWL4030_IRQ_BASE,
@@ -710,6 +761,7 @@
 	.madc			= &rx51_madc_data,
 	.usb			= &rx51_usb_data,
 	.power			= &rx51_t2scripts_data,
+	.codec			= &rx51_codec_data,
 
 	.vaux1			= &rx51_vaux1,
 	.vaux2			= &rx51_vaux2,
@@ -921,6 +973,7 @@
 	board_smc91x_init();
 	rx51_add_gpio_keys();
 	rx51_init_wl1251();
+	rx51_init_si4713();
 	spi_register_board_info(rx51_peripherals_spi_board_info,
 				ARRAY_SIZE(rx51_peripherals_spi_board_info));
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rx51-video.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rx51-video.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-rx51-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-rx51-video.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,18 +66,6 @@
 	.default_device	= &rx51_lcd_device,
 };
 
-struct platform_device rx51_display_device = {
-	.name	= "omapdss",
-	.id	= -1,
-	.dev	= {
-		.platform_data = &rx51_dss_board_info,
-	},
-};
-
-static struct platform_device *rx51_video_devices[] __initdata = {
-	&rx51_display_device,
-};
-
 static int __init rx51_video_init(void)
 {
 	if (!machine_is_nokia_rx51())
@@ -95,8 +83,7 @@
 
 	gpio_direction_output(RX51_LCD_RESET_GPIO, 1);
 
-	platform_add_devices(rx51_video_devices,
-				ARRAY_SIZE(rx51_video_devices));
+	omap_display_init(&rx51_dss_board_info);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-ti8168evm.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-ti8168evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-ti8168evm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-ti8168evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Code for TI8168 EVM.
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc. - 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 <mach/hardware.h>
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+
+#include <plat/irqs.h>
+#include <plat/board.h>
+#include <plat/common.h>
+
+static struct omap_board_config_kernel ti8168_evm_config[] __initdata = {
+};
+
+static void __init ti8168_init_early(void)
+{
+	omap2_init_common_infrastructure();
+	omap2_init_common_devices(NULL, NULL);
+}
+
+static void __init ti8168_evm_init_irq(void)
+{
+	omap_init_irq();
+}
+
+static void __init ti8168_evm_init(void)
+{
+	omap_serial_init();
+	omap_board_config = ti8168_evm_config;
+	omap_board_config_size = ARRAY_SIZE(ti8168_evm_config);
+}
+
+static void __init ti8168_evm_map_io(void)
+{
+	omap2_set_globals_ti816x();
+	omapti816x_map_common_io();
+}
+
+MACHINE_START(TI8168EVM, "ti8168evm")
+	/* Maintainer: Texas Instruments */
+	.boot_params	= 0x80000100,
+	.map_io		= ti8168_evm_map_io,
+	.init_early	= ti8168_init_early,
+	.init_irq	= ti8168_evm_init_irq,
+	.timer		= &omap_timer,
+	.init_machine	= ti8168_evm_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-zoom.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-zoom.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-zoom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-zoom.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/input.h>
 #include <linux/gpio.h>
 #include <linux/i2c/twl.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -33,7 +34,7 @@
 
 #define ZOOM3_EHCI_RESET_GPIO		64
 
-static void __init omap_zoom_init_irq(void)
+static void __init omap_zoom_init_early(void)
 {
 	omap2_init_common_infrastructure();
 	if (machine_is_omap_zoom2())
@@ -42,14 +43,12 @@
 	else if (machine_is_omap_zoom3())
 		omap2_init_common_devices(h8mbx00u0mer0em_sdrc_params,
 					  h8mbx00u0mer0em_sdrc_params);
-
-	omap_init_irq();
 }
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
 	/* WLAN IRQ - GPIO 162 */
-	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT_PULLUP),
+	OMAP3_MUX(MCBSP1_CLKX, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
 	/* WLAN POWER ENABLE - GPIO 101 */
 	OMAP3_MUX(CAM_D2, OMAP_MUX_MODE4 | OMAP_PIN_OUTPUT),
 	/* WLAN SDIO: MMC3 CMD */
@@ -106,10 +105,10 @@
 	},
 };
 
-static const struct ehci_hcd_omap_platform_data ehci_pdata __initconst = {
-	.port_mode[0]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
-	.port_mode[1]		= EHCI_HCD_OMAP_MODE_PHY,
-	.port_mode[2]		= EHCI_HCD_OMAP_MODE_UNKNOWN,
+static const struct usbhs_omap_board_data usbhs_bdata __initconst = {
+	.port_mode[0]		= OMAP_USBHS_PORT_MODE_UNUSED,
+	.port_mode[1]		= OMAP_EHCI_PORT_MODE_PHY,
+	.port_mode[2]		= OMAP_USBHS_PORT_MODE_UNUSED,
 	.phy_reset		= true,
 	.reset_gpio_port[0]	= -EINVAL,
 	.reset_gpio_port[1]	= ZOOM3_EHCI_RESET_GPIO,
@@ -123,11 +122,11 @@
 	} else if (machine_is_omap_zoom3()) {
 		omap3_mux_init(board_mux, OMAP_PACKAGE_CBP);
 		omap_mux_init_gpio(ZOOM3_EHCI_RESET_GPIO, OMAP_PIN_OUTPUT);
-		usb_ehci_init(&ehci_pdata);
+		usbhs_init(&usbhs_bdata);
 	}
 
-	board_nand_init(zoom_nand_partitions,
-			ARRAY_SIZE(zoom_nand_partitions), ZOOM_NAND_CS);
+	board_nand_init(zoom_nand_partitions, ARRAY_SIZE(zoom_nand_partitions),
+						ZOOM_NAND_CS, NAND_BUSWIDTH_16);
 	zoom_debugboard_init();
 	zoom_peripherals_init();
 	zoom_display_init();
@@ -135,18 +134,20 @@
 
 MACHINE_START(OMAP_ZOOM2, "OMAP Zoom2 board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_zoom_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_zoom_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap_timer,
 MACHINE_END
 
 MACHINE_START(OMAP_ZOOM3, "OMAP Zoom3 board")
 	.boot_params	= 0x80000100,
-	.map_io		= omap3_map_io,
 	.reserve	= omap_reserve,
-	.init_irq	= omap_zoom_init_irq,
+	.map_io		= omap3_map_io,
+	.init_early	= omap_zoom_init_early,
+	.init_irq	= omap_init_irq,
 	.init_machine	= omap_zoom_init,
 	.timer		= &omap_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-zoom-display.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-zoom-display.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-zoom-display.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-zoom-display.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,14 +130,6 @@
 	.default_device		= &zoom_lcd_device,
 };
 
-static struct platform_device zoom_dss_device = {
-	.name				= "omapdss",
-	.id				= -1,
-	.dev				= {
-		.platform_data		= &zoom_dss_data,
-	},
-};
-
 static struct omap2_mcspi_device_config dss_lcd_mcspi_config = {
 	.turbo_mode		= 1,
 	.single_channel	= 1,  /* 0: slave, 1: master */
@@ -153,14 +145,9 @@
 	},
 };
 
-static struct platform_device *zoom_display_devices[] __initdata = {
-	&zoom_dss_device,
-};
-
 void __init zoom_display_init(void)
 {
-	platform_add_devices(zoom_display_devices,
-				ARRAY_SIZE(zoom_display_devices));
+	omap_display_init(&zoom_dss_data);
 	spi_register_board_info(nec_8048_spi_board_info,
 				ARRAY_SIZE(nec_8048_spi_board_info));
 	zoom_lcd_panel_init();
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-zoom-peripherals.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-zoom-peripherals.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/board-zoom-peripherals.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/board-zoom-peripherals.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,7 @@
 
 static struct regulator_consumer_supply zoom_vmmc3_supply = {
 	.supply		= "vmmc",
-	.dev_name	= "mmci-omap-hs.2",
+	.dev_name	= "omap_hsmmc.2",
 };
 
 /* VMMC1 for OMAP VDD_MMC1 (i/o) and MMC1 card */
@@ -226,11 +226,13 @@
 	{}      /* Terminator */
 };
 
-static struct regulator_consumer_supply zoom_vpll2_supply =
-	REGULATOR_SUPPLY("vdds_dsi", "omapdss");
+static struct regulator_consumer_supply zoom_vpll2_supplies[] = {
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss"),
+	REGULATOR_SUPPLY("vdds_dsi", "omapdss_dsi1"),
+};
 
 static struct regulator_consumer_supply zoom_vdda_dac_supply =
-	REGULATOR_SUPPLY("vdda_dac", "omapdss");
+	REGULATOR_SUPPLY("vdda_dac", "omapdss_venc");
 
 static struct regulator_init_data zoom_vpll2 = {
 	.constraints = {
@@ -241,8 +243,8 @@
 		.valid_ops_mask         = REGULATOR_CHANGE_MODE
 					| REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies		= 1,
-	.consumer_supplies		= &zoom_vpll2_supply,
+	.num_consumer_supplies		= ARRAY_SIZE(zoom_vpll2_supplies),
+	.consumer_supplies		= zoom_vpll2_supplies,
 };
 
 static struct regulator_init_data zoom_vdac = {
@@ -322,9 +324,7 @@
 	.irq_line	= 1,
 };
 
-static struct twl4030_codec_audio_data zoom_audio_data = {
-	.audio_mclk = 26000000,
-};
+static struct twl4030_codec_audio_data zoom_audio_data;
 
 static struct twl4030_codec_data zoom_codec_data = {
 	.audio_mclk = 26000000,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt2xxx_apll.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt2xxx_apll.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt2xxx_apll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt2xxx_apll.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,6 +78,26 @@
 	return omap2_clk_apll_enable(clk, OMAP24XX_ST_54M_APLL_MASK);
 }
 
+static void _apll96_allow_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll96_auto_low_power_stop();
+}
+
+static void _apll96_deny_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll96_disable_autoidle();
+}
+
+static void _apll54_allow_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll54_auto_low_power_stop();
+}
+
+static void _apll54_deny_idle(struct clk *clk)
+{
+	omap2xxx_cm_set_apll54_disable_autoidle();
+}
+
 /* Stop APLL */
 static void omap2_clk_apll_disable(struct clk *clk)
 {
@@ -93,11 +113,15 @@
 const struct clkops clkops_apll96 = {
 	.enable		= omap2_clk_apll96_enable,
 	.disable	= omap2_clk_apll_disable,
+	.allow_idle	= _apll96_allow_idle,
+	.deny_idle	= _apll96_deny_idle,
 };
 
 const struct clkops clkops_apll54 = {
 	.enable		= omap2_clk_apll54_enable,
 	.disable	= omap2_clk_apll_disable,
+	.allow_idle	= _apll54_allow_idle,
+	.deny_idle	= _apll54_deny_idle,
 };
 
 /* Public functions */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt2xxx_dpll.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt2xxx_dpll.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt2xxx_dpll.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt2xxx_dpll.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * OMAP2-specific DPLL control functions
+ *
+ * Copyright (C) 2011 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+
+#include "clock.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+
+/* Private functions */
+
+/**
+ * _allow_idle - enable DPLL autoidle bits
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Enable DPLL automatic idle control.  The DPLL will enter low-power
+ * stop when its downstream clocks are gated.  No return value.
+ * REVISIT: DPLL can optionally enter low-power bypass by writing 0x1
+ * instead.  Add some mechanism to optionally enter this mode.
+ */
+static void _allow_idle(struct clk *clk)
+{
+	if (!clk || !clk->dpll_data)
+		return;
+
+	omap2xxx_cm_set_dpll_auto_low_power_stop();
+}
+
+/**
+ * _deny_idle - prevent DPLL from automatically idling
+ * @clk: struct clk * of the DPLL to operate on
+ *
+ * Disable DPLL automatic idle control.  No return value.
+ */
+static void _deny_idle(struct clk *clk)
+{
+	if (!clk || !clk->dpll_data)
+		return;
+
+	omap2xxx_cm_set_dpll_disable_autoidle();
+}
+
+
+/* Public data */
+
+const struct clkops clkops_omap2xxx_dpll_ops = {
+	.allow_idle	= _allow_idle,
+	.deny_idle	= _deny_idle,
+};
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt2xxx_osc.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,13 @@
 #include "prm2xxx_3xxx.h"
 #include "prm-regbits-24xx.h"
 
+/*
+ * XXX This does not actually enable the osc_ck, since the osc_ck must
+ * be running for this function to be called.  Instead, this function
+ * is used to disable an autoidle mode on the osc_ck.  The existing
+ * clk_enable/clk_disable()-based usecounting for osc_ck should be
+ * replaced with autoidle-based usecounting.
+ */
 static int omap2_enable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
@@ -41,6 +48,13 @@
 	return 0;
 }
 
+/*
+ * XXX This does not actually disable the osc_ck, since doing so would
+ * immediately halt the system.  Instead, this function is used to
+ * enable an autoidle mode on the osc_ck.  The existing
+ * clk_enable/clk_disable()-based usecounting for osc_ck should be
+ * replaced with autoidle-based usecounting.
+ */
 static void omap2_disable_osc_ck(struct clk *clk)
 {
 	u32 pcc;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt34xx_dpll3m2.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt34xx_dpll3m2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt34xx_dpll3m2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt34xx_dpll3m2.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,6 +115,7 @@
 				  sdrc_cs0->rfr_ctrl, sdrc_cs0->actim_ctrla,
 				  sdrc_cs0->actim_ctrlb, sdrc_cs0->mr,
 				  0, 0, 0, 0);
+	clk->rate = rate;
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt_clksel.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt_clksel.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt_clksel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt_clksel.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 				u32 *field_val)
 {
 	const struct clksel *clks;
-	const struct clksel_rate *clkr, *max_clkr;
+	const struct clksel_rate *clkr, *max_clkr = NULL;
 	u8 max_div = 0;
 
 	clks = _get_clksel_by_parent(clk, src_clk);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt_dpll.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt_dpll.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt_dpll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt_dpll.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,12 +178,11 @@
 	if (!dd)
 		return;
 
-	/* Return bypass rate if DPLL is bypassed */
 	v = __raw_readl(dd->control_reg);
 	v &= dd->enable_mask;
 	v >>= __ffs(dd->enable_mask);
 
-	/* Reparent in case the dpll is in bypass */
+	/* Reparent the struct clk in case the dpll is in bypass */
 	if (cpu_is_omap24xx()) {
 		if (v == OMAP2XXX_EN_DPLL_LPBYPASS ||
 		    v == OMAP2XXX_EN_DPLL_FRBYPASS)
@@ -260,50 +259,22 @@
 /* DPLL rate rounding code */
 
 /**
- * omap2_dpll_set_rate_tolerance: set the error tolerance during rate rounding
- * @clk: struct clk * of the DPLL
- * @tolerance: maximum rate error tolerance
- *
- * Set the maximum DPLL rate error tolerance for the rate rounding
- * algorithm.  The rate tolerance is an attempt to balance DPLL power
- * saving (the least divider value "n") vs. rate fidelity (the least
- * difference between the desired DPLL target rate and the rounded
- * rate out of the algorithm).  So, increasing the tolerance is likely
- * to decrease DPLL power consumption and increase DPLL rate error.
- * Returns -EINVAL if provided a null clock ptr or a clk that is not a
- * DPLL; or 0 upon success.
- */
-int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance)
-{
-	if (!clk || !clk->dpll_data)
-		return -EINVAL;
-
-	clk->dpll_data->rate_tolerance = tolerance;
-
-	return 0;
-}
-
-/**
  * omap2_dpll_round_rate - round a target rate for an OMAP DPLL
  * @clk: struct clk * for a DPLL
  * @target_rate: desired DPLL clock rate
  *
- * Given a DPLL, a desired target rate, and a rate tolerance, round
- * the target rate to a possible, programmable rate for this DPLL.
- * Rate tolerance is assumed to be set by the caller before this
- * function is called.  Attempts to select the minimum possible n
- * within the tolerance to reduce power consumption.  Stores the
- * computed (m, n) in the DPLL's dpll_data structure so set_rate()
- * will not need to call this (expensive) function again.  Returns ~0
- * if the target rate cannot be rounded, either because the rate is
- * too low or because the rate tolerance is set too tightly; or the
- * rounded rate upon success.
+ * Given a DPLL and a desired target rate, round the target rate to a
+ * possible, programmable rate for this DPLL.  Attempts to select the
+ * minimum possible n.  Stores the computed (m, n) in the DPLL's
+ * dpll_data structure so set_rate() will not need to call this
+ * (expensive) function again.  Returns ~0 if the target rate cannot
+ * be rounded, or the rounded rate upon success.
  */
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate)
 {
-	int m, n, r, e, scaled_max_m;
-	unsigned long scaled_rt_rp, new_rate;
-	int min_e = -1, min_e_m = -1, min_e_n = -1;
+	int m, n, r, scaled_max_m;
+	unsigned long scaled_rt_rp;
+	unsigned long new_rate = 0;
 	struct dpll_data *dd;
 
 	if (!clk || !clk->dpll_data)
@@ -311,8 +282,8 @@
 
 	dd = clk->dpll_data;
 
-	pr_debug("clock: starting DPLL round_rate for clock %s, target rate "
-		 "%ld\n", clk->name, target_rate);
+	pr_debug("clock: %s: starting DPLL round_rate, target rate %ld\n",
+		 clk->name, target_rate);
 
 	scaled_rt_rp = target_rate / (dd->clk_ref->rate / DPLL_SCALE_FACTOR);
 	scaled_max_m = dd->max_multiplier * DPLL_SCALE_FACTOR;
@@ -347,39 +318,23 @@
 		if (r == DPLL_MULT_UNDERFLOW)
 			continue;
 
-		e = target_rate - new_rate;
-		pr_debug("clock: n = %d: m = %d: rate error is %d "
-			 "(new_rate = %ld)\n", n, m, e, new_rate);
-
-		if (min_e == -1 ||
-		    min_e >= (int)(abs(e) - dd->rate_tolerance)) {
-			min_e = e;
-			min_e_m = m;
-			min_e_n = n;
-
-			pr_debug("clock: found new least error %d\n", min_e);
+		pr_debug("clock: %s: m = %d: n = %d: new_rate = %ld\n",
+			 clk->name, m, n, new_rate);
 
-			/* We found good settings -- bail out now */
-			if (min_e <= dd->rate_tolerance)
-				break;
+		if (target_rate == new_rate) {
+			dd->last_rounded_m = m;
+			dd->last_rounded_n = n;
+			dd->last_rounded_rate = target_rate;
+			break;
 		}
 	}
 
-	if (min_e < 0) {
-		pr_debug("clock: error: target rate or tolerance too low\n");
+	if (target_rate != new_rate) {
+		pr_debug("clock: %s: cannot round to rate %ld\n", clk->name,
+			 target_rate);
 		return ~0;
 	}
 
-	dd->last_rounded_m = min_e_m;
-	dd->last_rounded_n = min_e_n;
-	dd->last_rounded_rate = _dpll_compute_new_rate(dd->clk_ref->rate,
-						       min_e_m,  min_e_n);
-
-	pr_debug("clock: final least error: e = %d, m = %d, n = %d\n",
-		 min_e, min_e_m, min_e_n);
-	pr_debug("clock: final rate: %ld  (target rate: %ld)\n",
-		 dd->last_rounded_rate, target_rate);
-
-	return dd->last_rounded_rate;
+	return target_rate;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt_iclk.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt_iclk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clkt_iclk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clkt_iclk.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ * OMAP2/3 interface clock control
+ *
+ * Copyright (C) 2011 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.
+ */
+#undef DEBUG
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+
+#include <plat/clock.h>
+#include <plat/prcm.h>
+
+#include "clock.h"
+#include "clock2xxx.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+
+/* Private functions */
+
+/* XXX */
+void omap2_clkt_iclk_allow_idle(struct clk *clk)
+{
+	u32 v, r;
+
+	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+	v = __raw_readl((__force void __iomem *)r);
+	v |= (1 << clk->enable_bit);
+	__raw_writel(v, (__force void __iomem *)r);
+}
+
+/* XXX */
+void omap2_clkt_iclk_deny_idle(struct clk *clk)
+{
+	u32 v, r;
+
+	r = ((__force u32)clk->enable_reg ^ (CM_AUTOIDLE ^ CM_ICLKEN));
+
+	v = __raw_readl((__force void __iomem *)r);
+	v &= ~(1 << clk->enable_bit);
+	__raw_writel(v, (__force void __iomem *)r);
+}
+
+/* Public data */
+
+const struct clkops clkops_omap2_iclk_dflt_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,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_iclk_dflt = {
+	.enable		= omap2_dflt_clk_enable,
+	.disable	= omap2_dflt_clk_disable,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_iclk_idle_only = {
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
+const struct clkops clkops_omap2_mdmclk_dflt_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,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock2420_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock2420_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock2420_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock2420_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,12 +1,12 @@
 /*
- *  linux/arch/arm/mach-omap2/clock2420_data.c
+ * OMAP2420 clock data
  *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2010 Nokia Corporation
+ * Copyright (C) 2005-2009 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
  *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
+ * Contacts:
+ * 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 version 2 as
@@ -34,18 +34,15 @@
 /*
  * 2420 clock tree.
  *
- * NOTE:In many cases here we are assigning a 'default' parent.	In many
- *	cases the parent is selectable.	The get/set parent calls will also
- *	switch sources.
- *
- *	Many some clocks say always_enabled, but they can be auto idled for
- *	power savings. They will always be available upon clock request.
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
  *
  *	Several sources are given initial rates which may be wrong, this will
  *	be fixed up in the init func.
  *
  *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most periferals have dependencies on multiple clock
+ *	noteworthy that most peripherals have dependencies on multiple clock
  *	domains. Many get their interface clocks from the L4 domain, but get
  *	functional clocks from fixed sources or other core domain derived
  *	clocks.
@@ -55,7 +52,7 @@
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.ops		= &clkops_null,
-	.rate		= 32000,
+	.rate		= 32768,
 	.clkdm_name	= "wkup_clkdm",
 };
 
@@ -116,7 +113,6 @@
 	.max_multiplier		= 1023,
 	.min_divider		= 1,
 	.max_divider		= 16,
-	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 /*
@@ -125,7 +121,7 @@
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2xxx_dpll_ops,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
 	.clkdm_name	= "wkup_clkdm",
@@ -455,36 +451,22 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* DSP interface clock */
-static const struct clksel_rate dsp_irate_ick_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_irate_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
 	{ .parent = NULL }
 };
 
-/* This clock does not exist as such in the TRM. */
-static struct clk dsp_irate_ick = {
-	.name		= "dsp_irate_ick",
-	.ops		= &clkops_null,
-	.parent		= &dsp_fck,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_irate_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
-/* 2420 only */
 static struct clk dsp_ick = {
 	.name		= "dsp_ick",	 /* apparently ipi and isp */
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_irate_ick,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &dsp_fck,
+	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2420_EN_DSP_IPI_SHIFT,	      /* for ipi */
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /*
@@ -579,7 +561,7 @@
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -661,7 +643,7 @@
  */
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -716,6 +698,7 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
 	.ops		= &clkops_omap2_dflt_wait,
@@ -763,7 +746,7 @@
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -825,6 +808,14 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk wu_l4_ick = {
+	.name		= "wu_l4_ick",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
+	.clkdm_name	= "wkup_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /*
  * CORE power domain ICLK & FCLK defines.
  * Many of the these can have more than one possible parent. Entries
@@ -845,9 +836,9 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -871,7 +862,7 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -895,7 +886,7 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -919,7 +910,7 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -943,7 +934,7 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -967,7 +958,7 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -991,8 +982,9 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1014,7 +1006,7 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1038,7 +1030,7 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1062,7 +1054,7 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1086,7 +1078,7 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1110,7 +1102,7 @@
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1134,7 +1126,7 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1174,7 +1166,7 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1198,7 +1190,7 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1218,7 +1210,7 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1238,7 +1230,7 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1258,7 +1250,7 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1278,7 +1270,7 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1298,9 +1290,9 @@
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1318,9 +1310,9 @@
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1338,10 +1330,10 @@
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1349,9 +1341,9 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1359,10 +1351,10 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1370,7 +1362,7 @@
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1395,7 +1387,7 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1405,7 +1397,7 @@
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1425,7 +1417,7 @@
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1445,7 +1437,7 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1465,7 +1457,7 @@
 
 static struct clk mmc_ick = {
 	.name		= "mmc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1485,7 +1477,7 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1505,7 +1497,7 @@
 
 static struct clk eac_ick = {
 	.name		= "eac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1525,7 +1517,7 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1545,7 +1537,7 @@
 
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1565,7 +1557,7 @@
 
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1583,12 +1575,18 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
+	.ops		= &clkops_omap2_iclk_idle_only,
 	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1600,17 +1598,38 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
+	.recalc		= &followparent_recalc,
+};
+
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
+static struct clk sdrc_ick = {
+	.name		= "sdrc_ick",
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
+	.flags		= ENABLE_ON_INIT,
+	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk vlynq_ick = {
 	.name		= "vlynq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1659,7 +1678,7 @@
 
 static struct clk des_ick = {
 	.name		= "des_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1669,7 +1688,7 @@
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1679,7 +1698,7 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1689,7 +1708,7 @@
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1699,7 +1718,7 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1777,7 +1796,6 @@
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_242X),
 	/* dsp domain clocks */
 	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_242X),
-	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_242X),
 	CLK(NULL,	"dsp_ick",	&dsp_ick,	CK_242X),
 	CLK(NULL,	"iva1_ifck",	&iva1_ifck,	CK_242X),
 	CLK(NULL,	"iva1_mpu_int_ifck", &iva1_mpu_int_ifck, CK_242X),
@@ -1786,10 +1804,10 @@
 	CLK(NULL,	"gfx_2d_fck",	&gfx_2d_fck,	CK_242X),
 	CLK(NULL,	"gfx_ick",	&gfx_ick,	CK_242X),
 	/* DSS domain clocks */
-	CLK("omapdss",	"ick",		&dss_ick,	CK_242X),
-	CLK("omapdss",	"dss1_fck",	&dss1_fck,	CK_242X),
-	CLK("omapdss",	"dss2_fck",	&dss2_fck,	CK_242X),
-	CLK("omapdss",	"tv_fck",	&dss_54m_fck,	CK_242X),
+	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_242X),
+	CLK("omapdss_dss",	"fck",		&dss1_fck,	CK_242X),
+	CLK("omapdss_dss",	"sys_clk",	&dss2_fck,	CK_242X),
+	CLK("omapdss_dss",	"tv_clk",	&dss_54m_fck,	CK_242X),
 	/* L3 domain clocks */
 	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_242X),
 	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_242X),
@@ -1797,6 +1815,7 @@
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_242X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_242X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_242X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -1869,6 +1888,7 @@
 	CLK(NULL,	"gpmc_fck",	&gpmc_fck,	CK_242X),
 	CLK(NULL,	"sdma_fck",	&sdma_fck,	CK_242X),
 	CLK(NULL,	"sdma_ick",	&sdma_ick,	CK_242X),
+	CLK(NULL,	"sdrc_ick",	&sdrc_ick,	CK_242X),
 	CLK(NULL,	"vlynq_ick",	&vlynq_ick,	CK_242X),
 	CLK(NULL,	"vlynq_fck",	&vlynq_fck,	CK_242X),
 	CLK(NULL,	"des_ick",	&des_ick,	CK_242X),
@@ -1913,6 +1933,9 @@
 		omap2_init_clk_clkdm(c->lk.clk);
 	}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock2430_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock2430_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock2430_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock2430_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,12 +1,12 @@
 /*
- *  linux/arch/arm/mach-omap2/clock2430_data.c
+ * OMAP2430 clock data
  *
- *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2010 Nokia Corporation
+ * Copyright (C) 2005-2009 Texas Instruments, Inc.
+ * Copyright (C) 2004-2011 Nokia Corporation
  *
- *  Contacts:
- *  Richard Woodruff <r-woodruff2@ti.com>
- *  Paul Walmsley
+ * Contacts:
+ * 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 version 2 as
@@ -34,18 +34,15 @@
 /*
  * 2430 clock tree.
  *
- * NOTE:In many cases here we are assigning a 'default' parent.	In many
- *	cases the parent is selectable.	The get/set parent calls will also
- *	switch sources.
- *
- *	Many some clocks say always_enabled, but they can be auto idled for
- *	power savings. They will always be available upon clock request.
+ * NOTE:In many cases here we are assigning a 'default' parent. In
+ *	many cases the parent is selectable. The set parent calls will
+ *	also switch sources.
  *
  *	Several sources are given initial rates which may be wrong, this will
  *	be fixed up in the init func.
  *
  *	Things are broadly separated below by clock domains. It is
- *	noteworthy that most periferals have dependencies on multiple clock
+ *	noteworthy that most peripherals have dependencies on multiple clock
  *	domains. Many get their interface clocks from the L4 domain, but get
  *	functional clocks from fixed sources or other core domain derived
  *	clocks.
@@ -55,7 +52,7 @@
 static struct clk func_32k_ck = {
 	.name		= "func_32k_ck",
 	.ops		= &clkops_null,
-	.rate		= 32000,
+	.rate		= 32768,
 	.clkdm_name	= "wkup_clkdm",
 };
 
@@ -116,7 +113,6 @@
 	.max_multiplier		= 1023,
 	.min_divider		= 1,
 	.max_divider		= 16,
-	.rate_tolerance		= DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 /*
@@ -125,7 +121,7 @@
  */
 static struct clk dpll_ck = {
 	.name		= "dpll_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap2xxx_dpll_ops,
 	.parent		= &sys_ck,		/* Can be func_32k also */
 	.dpll_data	= &dpll_dd,
 	.clkdm_name	= "wkup_clkdm",
@@ -434,37 +430,23 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
-/* DSP interface clock */
-static const struct clksel_rate dsp_irate_ick_rates[] = {
-	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
-	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
-	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
-	{ .div = 0 },
-};
-
-static const struct clksel dsp_irate_ick_clksel[] = {
-	{ .parent = &dsp_fck, .rates = dsp_irate_ick_rates },
+static const struct clksel dsp_ick_clksel[] = {
+	{ .parent = &dsp_fck, .rates = dsp_ick_rates },
 	{ .parent = NULL }
 };
 
-/* This clock does not exist as such in the TRM. */
-static struct clk dsp_irate_ick = {
-	.name		= "dsp_irate_ick",
-	.ops		= &clkops_null,
-	.parent		= &dsp_fck,
-	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
-	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
-	.clksel		= dsp_irate_ick_clksel,
-	.recalc		= &omap2_clksel_recalc,
-};
-
 /* 2430 only - EN_DSP controls both dsp fclk and iclk on 2430 */
 static struct clk iva2_1_ick = {
 	.name		= "iva2_1_ick",
 	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &dsp_irate_ick,
+	.parent		= &dsp_fck,
+	.clkdm_name	= "dsp_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_FCLKEN),
 	.enable_bit	= OMAP24XX_CM_FCLKEN_DSP_EN_DSP_SHIFT,
+	.clksel_reg	= OMAP_CM_REGADDR(OMAP24XX_DSP_MOD, CM_CLKSEL),
+	.clksel_mask	= OMAP24XX_CLKSEL_DSP_IF_MASK,
+	.clksel		= dsp_ick_clksel,
+	.recalc		= &omap2_clksel_recalc,
 };
 
 /*
@@ -525,7 +507,7 @@
 /* It is unclear from TRM whether usb_l4_ick is really in L3 or L4 clkdm */
 static struct clk usb_l4_ick = {	/* FS-USB interface clock */
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -606,7 +588,7 @@
  */
 static struct clk ssi_l4_ick = {
 	.name		= "ssi_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -661,6 +643,7 @@
 	.recalc		= &omap2_clksel_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk gfx_ick = {
 	.name		= "gfx_ick",		/* From l3 */
 	.ops		= &clkops_omap2_dflt_wait,
@@ -693,7 +676,7 @@
 
 static struct clk mdm_ick = {		/* used both as a ick and fck */
 	.name		= "mdm_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_ck,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_ICLKEN),
@@ -706,7 +689,7 @@
 
 static struct clk mdm_osc_ck = {
 	.name		= "mdm_osc_ck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_mdmclk_dflt_wait,
 	.parent		= &osc_ck,
 	.clkdm_name	= "mdm_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(OMAP2430_MDM_MOD, CM_FCLKEN),
@@ -751,7 +734,7 @@
 
 static struct clk dss_ick = {		/* Enables both L3,L4 ICLK's */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,	/* really both l3 and l4 */
 	.clkdm_name	= "dss_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -813,6 +796,14 @@
 	.recalc		= &followparent_recalc,
 };
 
+static struct clk wu_l4_ick = {
+	.name		= "wu_l4_ick",
+	.ops		= &clkops_null,
+	.parent		= &sys_ck,
+	.clkdm_name	= "wkup_clkdm",
+	.recalc		= &followparent_recalc,
+};
+
 /*
  * CORE power domain ICLK & FCLK defines.
  * Many of the these can have more than one possible parent. Entries
@@ -833,9 +824,9 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -859,7 +850,7 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -883,7 +874,7 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -907,7 +898,7 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -931,7 +922,7 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -955,7 +946,7 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -979,8 +970,9 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP24XX_EN_GPT7_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1002,7 +994,7 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1026,7 +1018,7 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1050,7 +1042,7 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1074,7 +1066,7 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1098,7 +1090,7 @@
 
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1122,7 +1114,7 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1162,7 +1154,7 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1186,7 +1178,7 @@
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1210,7 +1202,7 @@
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1234,7 +1226,7 @@
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1258,7 +1250,7 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1278,7 +1270,7 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1298,7 +1290,7 @@
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1318,7 +1310,7 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1338,7 +1330,7 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1358,7 +1350,7 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1378,9 +1370,9 @@
 
 static struct clk gpios_ick = {
 	.name		= "gpios_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_GPIOS_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1398,9 +1390,9 @@
 
 static struct clk mpu_wdt_ick = {
 	.name		= "mpu_wdt_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_MPU_WDT_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1418,10 +1410,10 @@
 
 static struct clk sync_32k_ick = {
 	.name		= "sync_32k_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_32KSYNC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1429,9 +1421,9 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_WDT1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1439,10 +1431,10 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP24XX_EN_OMAPCTRL_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1450,9 +1442,9 @@
 
 static struct clk icr_ick = {
 	.name		= "icr_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
-	.clkdm_name	= "core_l4_clkdm",
+	.ops		= &clkops_omap2_iclk_dflt_wait,
+	.parent		= &wu_l4_ick,
+	.clkdm_name	= "wkup_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP2430_EN_ICR_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1460,7 +1452,7 @@
 
 static struct clk cam_ick = {
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1485,7 +1477,7 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1495,7 +1487,7 @@
 
 static struct clk wdt4_ick = {
 	.name		= "wdt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1515,7 +1507,7 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1535,7 +1527,7 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1555,7 +1547,7 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1579,7 +1571,7 @@
  */
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1603,7 +1595,7 @@
  */
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -1621,12 +1613,18 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk gpmc_fck = {
 	.name		= "gpmc_fck",
-	.ops		= &clkops_null, /* RMK: missing? */
+	.ops		= &clkops_omap2_iclk_idle_only,
 	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_GPMC_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1638,20 +1636,26 @@
 	.recalc		= &followparent_recalc,
 };
 
+/*
+ * The enable_reg/enable_bit in this clock is only used for CM_AUTOIDLE
+ * accesses derived from this data.
+ */
 static struct clk sdma_ick = {
 	.name		= "sdma_ick",
-	.ops		= &clkops_null, /* RMK: missing? */
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
+	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
+	.enable_bit	= OMAP24XX_AUTO_SDMA_SHIFT,
 	.recalc		= &followparent_recalc,
 };
 
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
-	.parent		= &l4_ck,
+	.ops		= &clkops_omap2_iclk_idle_only,
+	.parent		= &core_l3_ck,
 	.flags		= ENABLE_ON_INIT,
-	.clkdm_name	= "core_l4_clkdm",
+	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP2430_EN_SDRC_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1659,7 +1663,7 @@
 
 static struct clk des_ick = {
 	.name		= "des_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1669,7 +1673,7 @@
 
 static struct clk sha_ick = {
 	.name		= "sha_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1679,7 +1683,7 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1689,7 +1693,7 @@
 
 static struct clk aes_ick = {
 	.name		= "aes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1699,7 +1703,7 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_ICLKEN4),
@@ -1719,7 +1723,7 @@
 
 static struct clk usbhs_ick = {
 	.name		= "usbhs_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l3_ck,
 	.clkdm_name	= "core_l3_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1729,7 +1733,7 @@
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1741,7 +1745,7 @@
 	.name		= "mmchs1_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
-	.clkdm_name	= "core_l3_clkdm",
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS1_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1749,7 +1753,7 @@
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1761,6 +1765,7 @@
 	.name		= "mmchs2_fck",
 	.ops		= &clkops_omap2_dflt_wait,
 	.parent		= &func_96m_ck,
+	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, OMAP24XX_CM_FCLKEN2),
 	.enable_bit	= OMAP2430_EN_MMCHS2_SHIFT,
 	.recalc		= &followparent_recalc,
@@ -1768,7 +1773,7 @@
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1788,7 +1793,7 @@
 
 static struct clk mdm_intc_ick = {
 	.name		= "mdm_intc_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ck,
 	.clkdm_name	= "core_l4_clkdm",
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
@@ -1880,7 +1885,6 @@
 	CLK(NULL,	"mpu_ck",	&mpu_ck,	CK_243X),
 	/* dsp domain clocks */
 	CLK(NULL,	"dsp_fck",	&dsp_fck,	CK_243X),
-	CLK(NULL,	"dsp_irate_ick", &dsp_irate_ick, CK_243X),
 	CLK(NULL,	"iva2_1_ick",	&iva2_1_ick,	CK_243X),
 	/* GFX domain clocks */
 	CLK(NULL,	"gfx_3d_fck",	&gfx_3d_fck,	CK_243X),
@@ -1890,10 +1894,10 @@
 	CLK(NULL,	"mdm_ick",	&mdm_ick,	CK_243X),
 	CLK(NULL,	"mdm_osc_ck",	&mdm_osc_ck,	CK_243X),
 	/* DSS domain clocks */
-	CLK("omapdss",	"ick",		&dss_ick,	CK_243X),
-	CLK("omapdss",	"dss1_fck",	&dss1_fck,	CK_243X),
-	CLK("omapdss",	"dss2_fck",	&dss2_fck,	CK_243X),
-	CLK("omapdss",	"tv_fck",	&dss_54m_fck,	CK_243X),
+	CLK("omapdss_dss",	"ick",		&dss_ick,	CK_243X),
+	CLK("omapdss_dss",	"fck",		&dss1_fck,	CK_243X),
+	CLK("omapdss_dss",	"sys_clk",	&dss2_fck,	CK_243X),
+	CLK("omapdss_dss",	"tv_clk",	&dss_54m_fck,	CK_243X),
 	/* L3 domain clocks */
 	CLK(NULL,	"core_l3_ck",	&core_l3_ck,	CK_243X),
 	CLK(NULL,	"ssi_fck",	&ssi_ssr_sst_fck, CK_243X),
@@ -1901,6 +1905,7 @@
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X),
+	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_243X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -1984,15 +1989,15 @@
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_243X),
 	CLK(NULL,	"usb_fck",	&usb_fck,	CK_243X),
 	CLK("musb-omap2430",	"ick",	&usbhs_ick,	CK_243X),
-	CLK("mmci-omap-hs.0", "ick",	&mmchs1_ick,	CK_243X),
-	CLK("mmci-omap-hs.0", "fck",	&mmchs1_fck,	CK_243X),
-	CLK("mmci-omap-hs.1", "ick",	&mmchs2_ick,	CK_243X),
-	CLK("mmci-omap-hs.1", "fck",	&mmchs2_fck,	CK_243X),
+	CLK("omap_hsmmc.0", "ick",	&mmchs1_ick,	CK_243X),
+	CLK("omap_hsmmc.0", "fck",	&mmchs1_fck,	CK_243X),
+	CLK("omap_hsmmc.1", "ick",	&mmchs2_ick,	CK_243X),
+	CLK("omap_hsmmc.1", "fck",	&mmchs2_fck,	CK_243X),
 	CLK(NULL,	"gpio5_ick",	&gpio5_ick,	CK_243X),
 	CLK(NULL,	"gpio5_fck",	&gpio5_fck,	CK_243X),
 	CLK(NULL,	"mdm_intc_ick",	&mdm_intc_ick,	CK_243X),
-	CLK("mmci-omap-hs.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
-	CLK("mmci-omap-hs.1", "mmchsdb_fck", 	&mmchsdb2_fck,	CK_243X),
+	CLK("omap_hsmmc.0", "mmchsdb_fck",	&mmchsdb1_fck,	CK_243X),
+	CLK("omap_hsmmc.1", "mmchsdb_fck",	&mmchsdb2_fck,	CK_243X),
 };
 
 /*
@@ -2028,6 +2033,9 @@
 		omap2_init_clk_clkdm(c->lk.clk);
 	}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	/* Check the MPU rate set by bootloader */
 	clkrate = omap2xxx_clk_get_core_rate(&dpll_ck);
 	for (prcm = rate_table; prcm->mpu_speed; prcm++) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock2xxx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock2xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock2xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock2xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,16 +20,16 @@
 u32 omap2xxx_get_sysclkdiv(void);
 void omap2xxx_clk_prepare_for_reboot(void);
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 int omap2420_clk_init(void);
 #else
-#define omap2420_clk_init()	0
+#define omap2420_clk_init()	do { } while(0)
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 int omap2430_clk_init(void);
 #else
-#define omap2430_clk_init()	0
+#define omap2430_clk_init()	do { } while(0)
 #endif
 
 extern void __iomem *prcm_clksrc_ctrl, *cm_idlest_pll;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock34xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock34xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock34xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock34xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP3-specific clock framework functions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley
  * Jouni HÃ¶gander
@@ -59,6 +59,15 @@
 	.find_companion = omap2_clk_dflt_find_companion,
 };
 
+const struct clkops clkops_omap3430es2_iclk_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,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
 /**
  * omap3430es2_clk_dss_usbhost_find_idlest - CM_IDLEST info for DSS, USBHOST
  * @clk: struct clk * being enabled
@@ -94,6 +103,15 @@
 	.find_companion = omap2_clk_dflt_find_companion,
 };
 
+const struct clkops clkops_omap3430es2_iclk_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,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
+
 /**
  * omap3430es2_clk_hsotgusb_find_idlest - return CM_IDLEST info for HSOTGUSB
  * @clk: struct clk * being enabled
@@ -124,3 +142,12 @@
 	.find_idlest	= omap3430es2_clk_hsotgusb_find_idlest,
 	.find_companion = omap2_clk_dflt_find_companion,
 };
+
+const struct clkops clkops_omap3430es2_iclk_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,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock34xx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock34xx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock34xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock34xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,14 +2,17 @@
  * OMAP34xx clock function prototypes and macros
  *
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  */
 
 #ifndef __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 #define __ARCH_ARM_MACH_OMAP2_CLOCK34XX_H
 
 extern const struct clkops clkops_omap3430es2_ssi_wait;
+extern const struct clkops clkops_omap3430es2_iclk_ssi_wait;
 extern const struct clkops clkops_omap3430es2_hsotgusb_wait;
+extern const struct clkops clkops_omap3430es2_iclk_hsotgusb_wait;
 extern const struct clkops clkops_omap3430es2_dss_usbhost_wait;
+extern const struct clkops clkops_omap3430es2_iclk_dss_usbhost_wait;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock3517.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock3517.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock3517.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock3517.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP3517/3505-specific clock framework functions
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
  *
  * Ranjith Lohithakshan
  * Paul Walmsley
@@ -119,6 +119,8 @@
 	.disable	= omap2_dflt_clk_disable,
 	.find_idlest	= am35xx_clk_ipss_find_idlest,
 	.find_companion	= omap2_clk_dflt_find_companion,
+	.allow_idle	= omap2_clkt_iclk_allow_idle,
+	.deny_idle	= omap2_clkt_iclk_deny_idle,
 };
 
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock3xxx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock3xxx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock3xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock3xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,9 +65,6 @@
 	clk_set_rate(dpll5_clk, DPLL5_FREQ_FOR_USBHOST);
 	clk_enable(dpll5_clk);
 
-	/* Enable autoidle to allow it to enter low power bypass */
-	omap3_dpll_allow_idle(dpll5_clk);
-
 	/* Program dpll5_m2_clk divider for no division */
 	dpll5_m2_clk = clk_get(NULL, "dpll5_m2_ck");
 	clk_enable(dpll5_m2_clk);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP3 clock data
  *
  * Copyright (C) 2007-2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
  * With many device clock fixes by Kevin Hilman and Jouni HÃ¶gander
@@ -291,12 +291,11 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll1_ck = {
 	.name		= "dpll1_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_noncore_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll1_dd,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -364,7 +363,6 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll2_ck = {
@@ -424,12 +422,11 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll3_ck = {
 	.name		= "dpll3_ck",
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_core_dpll_ops,
 	.parent		= &sys_ck,
 	.dpll_data	= &dpll3_dd,
 	.round_rate	= &omap2_dpll_round_rate,
@@ -583,7 +580,6 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct dpll_data dpll4_dd_3630 __initdata = {
@@ -607,7 +603,6 @@
 	.max_multiplier = OMAP3630_MAX_JTYPE_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE,
 	.flags		= DPLL_J_TYPE
 };
 
@@ -939,7 +934,6 @@
 	.max_multiplier = OMAP3_MAX_DPLL_MULT,
 	.min_divider	= 1,
 	.max_divider	= OMAP3_MAX_DPLL_DIV,
-	.rate_tolerance = DEFAULT_DPLL_RATE_TOLERANCE
 };
 
 static struct clk dpll5_ck = {
@@ -1205,7 +1199,10 @@
 	{ .parent = NULL }
 };
 
-/* Virtual parent clock for gfx_l3_ick and gfx_l3_fck */
+/*
+ * Virtual parent clock for gfx_l3_ick and gfx_l3_fck
+ * This interface clock does not have a CM_AUTOIDLE bit
+ */
 static struct clk gfx_l3_ck = {
 	.name		= "gfx_l3_ck",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1304,6 +1301,7 @@
 	.round_rate	= &omap2_clksel_round_rate
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk sgx_ick = {
 	.name		= "sgx_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1328,7 +1326,7 @@
 
 static struct clk modem_fck = {
 	.name		= "modem_fck",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_mdmclk_dflt_wait,
 	.parent		= &sys_ck,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_FCLKEN1),
 	.enable_bit	= OMAP3430_EN_MODEM_SHIFT,
@@ -1338,7 +1336,7 @@
 
 static struct clk sad2d_ick = {
 	.name		= "sad2d_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SAD2D_SHIFT,
@@ -1348,7 +1346,7 @@
 
 static struct clk mad2d_ick = {
 	.name		= "mad2d_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430_EN_MAD2D_SHIFT,
@@ -1718,7 +1716,7 @@
 
 static struct clk hsotgusb_ick_3430es1 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1728,7 +1726,7 @@
 
 static struct clk hsotgusb_ick_3430es2 = {
 	.name		= "hsotgusb_ick",
-	.ops		= &clkops_omap3430es2_hsotgusb_wait,
+	.ops		= &clkops_omap3430es2_iclk_hsotgusb_wait,
 	.parent		= &core_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HSOTGUSB_SHIFT,
@@ -1736,6 +1734,7 @@
 	.recalc		= &followparent_recalc,
 };
 
+/* This interface clock does not have a CM_AUTOIDLE bit */
 static struct clk sdrc_ick = {
 	.name		= "sdrc_ick",
 	.ops		= &clkops_omap2_dflt_wait,
@@ -1767,7 +1766,7 @@
 
 static struct clk pka_ick = {
 	.name		= "pka_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l3_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_PKA_SHIFT,
@@ -1786,7 +1785,7 @@
 
 static struct clk usbtll_ick = {
 	.name		= "usbtll_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN3),
 	.enable_bit	= OMAP3430ES2_EN_USBTLL_SHIFT,
@@ -1796,7 +1795,7 @@
 
 static struct clk mmchs3_ick = {
 	.name		= "mmchs3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES2_EN_MMC3_SHIFT,
@@ -1807,7 +1806,7 @@
 /* Intersystem Communication Registers - chassis mode only */
 static struct clk icr_ick = {
 	.name		= "icr_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_ICR_SHIFT,
@@ -1817,7 +1816,7 @@
 
 static struct clk aes2_ick = {
 	.name		= "aes2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_AES2_SHIFT,
@@ -1827,7 +1826,7 @@
 
 static struct clk sha12_ick = {
 	.name		= "sha12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SHA12_SHIFT,
@@ -1837,7 +1836,7 @@
 
 static struct clk des2_ick = {
 	.name		= "des2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_DES2_SHIFT,
@@ -1847,7 +1846,7 @@
 
 static struct clk mmchs2_ick = {
 	.name		= "mmchs2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC2_SHIFT,
@@ -1857,7 +1856,7 @@
 
 static struct clk mmchs1_ick = {
 	.name		= "mmchs1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MMC1_SHIFT,
@@ -1867,7 +1866,7 @@
 
 static struct clk mspro_ick = {
 	.name		= "mspro_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MSPRO_SHIFT,
@@ -1877,7 +1876,7 @@
 
 static struct clk hdq_ick = {
 	.name		= "hdq_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_HDQ_SHIFT,
@@ -1887,7 +1886,7 @@
 
 static struct clk mcspi4_ick = {
 	.name		= "mcspi4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI4_SHIFT,
@@ -1897,7 +1896,7 @@
 
 static struct clk mcspi3_ick = {
 	.name		= "mcspi3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI3_SHIFT,
@@ -1907,7 +1906,7 @@
 
 static struct clk mcspi2_ick = {
 	.name		= "mcspi2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI2_SHIFT,
@@ -1917,7 +1916,7 @@
 
 static struct clk mcspi1_ick = {
 	.name		= "mcspi1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCSPI1_SHIFT,
@@ -1927,7 +1926,7 @@
 
 static struct clk i2c3_ick = {
 	.name		= "i2c3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C3_SHIFT,
@@ -1937,7 +1936,7 @@
 
 static struct clk i2c2_ick = {
 	.name		= "i2c2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C2_SHIFT,
@@ -1947,7 +1946,7 @@
 
 static struct clk i2c1_ick = {
 	.name		= "i2c1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_I2C1_SHIFT,
@@ -1957,7 +1956,7 @@
 
 static struct clk uart2_ick = {
 	.name		= "uart2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART2_SHIFT,
@@ -1967,7 +1966,7 @@
 
 static struct clk uart1_ick = {
 	.name		= "uart1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_UART1_SHIFT,
@@ -1977,7 +1976,7 @@
 
 static struct clk gpt11_ick = {
 	.name		= "gpt11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT11_SHIFT,
@@ -1987,7 +1986,7 @@
 
 static struct clk gpt10_ick = {
 	.name		= "gpt10_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_GPT10_SHIFT,
@@ -1997,7 +1996,7 @@
 
 static struct clk mcbsp5_ick = {
 	.name		= "mcbsp5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP5_SHIFT,
@@ -2007,7 +2006,7 @@
 
 static struct clk mcbsp1_ick = {
 	.name		= "mcbsp1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MCBSP1_SHIFT,
@@ -2017,7 +2016,7 @@
 
 static struct clk fac_ick = {
 	.name		= "fac_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430ES1_EN_FAC_SHIFT,
@@ -2027,7 +2026,7 @@
 
 static struct clk mailboxes_ick = {
 	.name		= "mailboxes_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_MAILBOXES_SHIFT,
@@ -2037,7 +2036,7 @@
 
 static struct clk omapctrl_ick = {
 	.name		= "omapctrl_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_OMAPCTRL_SHIFT,
@@ -2057,7 +2056,7 @@
 
 static struct clk ssi_ick_3430es1 = {
 	.name		= "ssi_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
@@ -2067,7 +2066,7 @@
 
 static struct clk ssi_ick_3430es2 = {
 	.name		= "ssi_ick",
-	.ops		= &clkops_omap3430es2_ssi_wait,
+	.ops		= &clkops_omap3430es2_iclk_ssi_wait,
 	.parent		= &ssi_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= OMAP3430_EN_SSI_SHIFT,
@@ -2085,7 +2084,7 @@
 
 static struct clk usb_l4_ick = {
 	.name		= "usb_l4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &l4_ick,
 	.init		= &omap2_init_clksel_parent,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
@@ -2107,7 +2106,7 @@
 
 static struct clk aes1_ick = {
 	.name		= "aes1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_AES1_SHIFT,
@@ -2116,7 +2115,7 @@
 
 static struct clk rng_ick = {
 	.name		= "rng_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_RNG_SHIFT,
@@ -2125,7 +2124,7 @@
 
 static struct clk sha11_ick = {
 	.name		= "sha11_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_SHA11_SHIFT,
@@ -2134,7 +2133,7 @@
 
 static struct clk des1_ick = {
 	.name		= "des1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &security_l4_ick2,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN2),
 	.enable_bit	= OMAP3430_EN_DES1_SHIFT,
@@ -2195,7 +2194,7 @@
 static struct clk dss_ick_3430es1 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
@@ -2206,7 +2205,7 @@
 static struct clk dss_ick_3430es2 = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "dss_ick",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_DSS_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_CM_ICLKEN_DSS_EN_DSS_SHIFT,
@@ -2229,7 +2228,7 @@
 static struct clk cam_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "cam_ick",
-	.ops		= &clkops_omap2_dflt,
+	.ops		= &clkops_omap2_iclk_dflt,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_CAM_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_CAM_SHIFT,
@@ -2272,7 +2271,7 @@
 static struct clk usbhost_ick = {
 	/* Handles both L3 and L4 clocks */
 	.name		= "usbhost_ick",
-	.ops		= &clkops_omap3430es2_dss_usbhost_wait,
+	.ops		= &clkops_omap3430es2_iclk_dss_usbhost_wait,
 	.parent		= &l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430ES2_USBHOST_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USBHOST_SHIFT,
@@ -2372,7 +2371,7 @@
 /* Never specifically named in the TRM, so we have to infer a likely name */
 static struct clk usim_ick = {
 	.name		= "usim_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430ES2_EN_USIMOCP_SHIFT,
@@ -2382,7 +2381,7 @@
 
 static struct clk wdt2_ick = {
 	.name		= "wdt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT2_SHIFT,
@@ -2392,7 +2391,7 @@
 
 static struct clk wdt1_ick = {
 	.name		= "wdt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT1_SHIFT,
@@ -2402,7 +2401,7 @@
 
 static struct clk gpio1_ick = {
 	.name		= "gpio1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO1_SHIFT,
@@ -2412,7 +2411,7 @@
 
 static struct clk omap_32ksync_ick = {
 	.name		= "omap_32ksync_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_32KSYNC_SHIFT,
@@ -2423,7 +2422,7 @@
 /* XXX This clock no longer exists in 3430 TRM rev F */
 static struct clk gpt12_ick = {
 	.name		= "gpt12_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT12_SHIFT,
@@ -2433,7 +2432,7 @@
 
 static struct clk gpt1_ick = {
 	.name		= "gpt1_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &wkup_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(WKUP_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT1_SHIFT,
@@ -2663,7 +2662,7 @@
 
 static struct clk gpio6_ick = {
 	.name		= "gpio6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO6_SHIFT,
@@ -2673,7 +2672,7 @@
 
 static struct clk gpio5_ick = {
 	.name		= "gpio5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO5_SHIFT,
@@ -2683,7 +2682,7 @@
 
 static struct clk gpio4_ick = {
 	.name		= "gpio4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO4_SHIFT,
@@ -2693,7 +2692,7 @@
 
 static struct clk gpio3_ick = {
 	.name		= "gpio3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO3_SHIFT,
@@ -2703,7 +2702,7 @@
 
 static struct clk gpio2_ick = {
 	.name		= "gpio2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPIO2_SHIFT,
@@ -2713,7 +2712,7 @@
 
 static struct clk wdt3_ick = {
 	.name		= "wdt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_WDT3_SHIFT,
@@ -2723,7 +2722,7 @@
 
 static struct clk uart3_ick = {
 	.name		= "uart3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_UART3_SHIFT,
@@ -2733,7 +2732,7 @@
 
 static struct clk uart4_ick = {
 	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3630_EN_UART4_SHIFT,
@@ -2743,7 +2742,7 @@
 
 static struct clk gpt9_ick = {
 	.name		= "gpt9_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT9_SHIFT,
@@ -2753,7 +2752,7 @@
 
 static struct clk gpt8_ick = {
 	.name		= "gpt8_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT8_SHIFT,
@@ -2763,7 +2762,7 @@
 
 static struct clk gpt7_ick = {
 	.name		= "gpt7_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT7_SHIFT,
@@ -2773,7 +2772,7 @@
 
 static struct clk gpt6_ick = {
 	.name		= "gpt6_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT6_SHIFT,
@@ -2783,7 +2782,7 @@
 
 static struct clk gpt5_ick = {
 	.name		= "gpt5_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT5_SHIFT,
@@ -2793,7 +2792,7 @@
 
 static struct clk gpt4_ick = {
 	.name		= "gpt4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT4_SHIFT,
@@ -2803,7 +2802,7 @@
 
 static struct clk gpt3_ick = {
 	.name		= "gpt3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT3_SHIFT,
@@ -2813,7 +2812,7 @@
 
 static struct clk gpt2_ick = {
 	.name		= "gpt2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_GPT2_SHIFT,
@@ -2823,7 +2822,7 @@
 
 static struct clk mcbsp2_ick = {
 	.name		= "mcbsp2_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP2_SHIFT,
@@ -2833,7 +2832,7 @@
 
 static struct clk mcbsp3_ick = {
 	.name		= "mcbsp3_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP3_SHIFT,
@@ -2843,7 +2842,7 @@
 
 static struct clk mcbsp4_ick = {
 	.name		= "mcbsp4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &per_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(OMAP3430_PER_MOD, CM_ICLKEN),
 	.enable_bit	= OMAP3430_EN_MCBSP4_SHIFT,
@@ -3186,7 +3185,7 @@
  */
 static struct clk uart4_ick_am35xx = {
 	.name		= "uart4_ick",
-	.ops		= &clkops_omap2_dflt_wait,
+	.ops		= &clkops_omap2_iclk_dflt_wait,
 	.parent		= &core_l4_ick,
 	.enable_reg	= OMAP_CM_REGADDR(CORE_MOD, CM_ICLKEN1),
 	.enable_bit	= AM35XX_EN_UART4_SHIFT,
@@ -3286,14 +3285,14 @@
 	CLK(NULL,	"cpefuse_fck",	&cpefuse_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"ts_fck",	&ts_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"usbtll_fck",	&usbtll_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK("omap-mcbsp.1",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK("omap-mcbsp.5",	"prcm_fck",	&core_96m_fck,	CK_3XXX),
 	CLK(NULL,	"core_96m_fck",	&core_96m_fck,	CK_3XXX),
-	CLK("mmci-omap-hs.2",	"fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("mmci-omap-hs.1",	"fck",	&mmchs2_fck,	CK_3XXX),
+	CLK("omap_hsmmc.2",	"fck",	&mmchs3_fck,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omap_hsmmc.1",	"fck",	&mmchs2_fck,	CK_3XXX),
 	CLK(NULL,	"mspro_fck",	&mspro_fck,	CK_34XX | CK_36XX),
-	CLK("mmci-omap-hs.0",	"fck",	&mmchs1_fck,	CK_3XXX),
+	CLK("omap_hsmmc.0",	"fck",	&mmchs1_fck,	CK_3XXX),
 	CLK("omap_i2c.3", "fck",	&i2c3_fck,	CK_3XXX),
 	CLK("omap_i2c.2", "fck",	&i2c2_fck,	CK_3XXX),
 	CLK("omap_i2c.1", "fck",	&i2c1_fck,	CK_3XXX),
@@ -3322,14 +3321,14 @@
 	CLK(NULL,	"pka_ick",	&pka_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"core_l4_ick",	&core_l4_ick,	CK_3XXX),
 	CLK(NULL,	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("mmci-omap-hs.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"usbtll_ick",	&usbtll_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omap_hsmmc.2",	"ick",	&mmchs3_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"icr_ick",	&icr_ick,	CK_34XX | CK_36XX),
 	CLK("omap-aes",	"ick",	&aes2_ick,	CK_34XX | CK_36XX),
 	CLK("omap-sham",	"ick",	&sha12_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"des2_ick",	&des2_ick,	CK_34XX | CK_36XX),
-	CLK("mmci-omap-hs.1",	"ick",	&mmchs2_ick,	CK_3XXX),
-	CLK("mmci-omap-hs.0",	"ick",	&mmchs1_ick,	CK_3XXX),
+	CLK("omap_hsmmc.1",	"ick",	&mmchs2_ick,	CK_3XXX),
+	CLK("omap_hsmmc.0",	"ick",	&mmchs1_ick,	CK_3XXX),
 	CLK(NULL,	"mspro_ick",	&mspro_ick,	CK_34XX | CK_36XX),
 	CLK("omap_hdq.0", "ick",	&hdq_ick,	CK_3XXX),
 	CLK("omap2_mcspi.4", "ick",	&mcspi4_ick,	CK_3XXX),
@@ -3357,22 +3356,31 @@
 	CLK("omap_rng",	"ick",		&rng_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"sha11_ick",	&sha11_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"des1_ick",	&des1_ick,	CK_34XX | CK_36XX),
-	CLK("omapdss",	"dss1_fck",	&dss1_alwon_fck_3430es1, CK_3430ES1),
-	CLK("omapdss",	"dss1_fck",	&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("omapdss",	"tv_fck",	&dss_tv_fck,	CK_3XXX),
-	CLK("omapdss",	"video_fck",	&dss_96m_fck,	CK_3XXX),
-	CLK("omapdss",	"dss2_fck",	&dss2_alwon_fck, CK_3XXX),
-	CLK("omapdss",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
-	CLK("omapdss",	"ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omapdss_dss",	"fck",		&dss1_alwon_fck_3430es1, CK_3430ES1),
+	CLK("omapdss_dss",	"fck",		&dss1_alwon_fck_3430es2, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("omapdss_dss",	"tv_clk",	&dss_tv_fck,	CK_3XXX),
+	CLK("omapdss_dss",	"video_clk",	&dss_96m_fck,	CK_3XXX),
+	CLK("omapdss_dss",	"sys_clk",	&dss2_alwon_fck, CK_3XXX),
+	CLK("omapdss_dss",	"ick",		&dss_ick_3430es1,	CK_3430ES1),
+	CLK("omapdss_dss",	"ick",		&dss_ick_3430es2,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"cam_mclk",	&cam_mclk,	CK_34XX | CK_36XX),
 	CLK(NULL,	"cam_ick",	&cam_ick,	CK_34XX | CK_36XX),
 	CLK(NULL,	"csi2_96m_fck",	&csi2_96m_fck,	CK_34XX | CK_36XX),
 	CLK(NULL,	"usbhost_120m_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"hs_fck", &usbhost_120m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_48m_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"fs_fck", &usbhost_48m_fck, CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
 	CLK(NULL,	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
-	CLK("ehci-omap.0",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"usbhost_ick",	&usbhost_ick,	CK_3430ES2PLUS | CK_AM35XX | CK_36XX),
+	CLK("usbhs-omap.0",	"utmi_p1_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"utmi_p2_gfclk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"xclk60mhsp1_ck",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"xclk60mhsp2_ck",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_host_hs_utmi_p1_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_host_hs_utmi_p2_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_tll_hs_usb_ch0_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"usb_tll_hs_usb_ch1_clk",	&dummy_ck,	CK_3XXX),
+	CLK("usbhs-omap.0",	"init_60m_fclk",	&dummy_ck,	CK_3XXX),
 	CLK(NULL,	"usim_fck",	&usim_fck,	CK_3430ES2PLUS | CK_36XX),
 	CLK(NULL,	"gpt1_fck",	&gpt1_fck,	CK_3XXX),
 	CLK(NULL,	"wkup_32k_fck",	&wkup_32k_fck,	CK_3XXX),
@@ -3471,6 +3479,9 @@
 	} else if (cpu_is_omap3630()) {
 		cpu_mask = (RATE_IN_34XX | RATE_IN_36XX);
 		cpu_clkflg = CK_36XX;
+	} else if (cpu_is_ti816x()) {
+		cpu_mask = RATE_IN_TI816X;
+		cpu_clkflg = CK_TI816X;
 	} else if (cpu_is_omap34xx()) {
 		if (omap_rev() == OMAP3430_REV_ES1_0) {
 			cpu_mask = RATE_IN_3430ES1;
@@ -3535,6 +3546,9 @@
 			omap2_init_clk_clkdm(c->lk.clk);
 		}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	recalculate_root_clocks();
 
 	pr_info("Clocking rate (Crystal/Core/MPU): %ld.%01ld/%ld/%ld MHz\n",
@@ -3548,9 +3562,10 @@
 	clk_enable_init_clocks();
 
 	/*
-	 * Lock DPLL5 and put it in autoidle.
+	 * Lock DPLL5 -- here only until other device init code can
+	 * handle this
 	 */
-	if (omap_rev() >= OMAP3430_REV_ES2_0)
+	if (!cpu_is_ti816x() && (omap_rev() >= OMAP3430_REV_ES2_0))
 		omap3_clk_lock_dpll5();
 
 	/* Avoid sleeping during omap3_core_dpll_m2_set_rate() */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock44xx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -278,8 +278,10 @@
 static struct clk dpll_abe_x2_ck = {
 	.name		= "dpll_abe_x2_ck",
 	.parent		= &dpll_abe_ck,
-	.ops		= &clkops_null,
+	.flags		= CLOCK_CLKOUTX2,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 };
 
 static const struct clksel_rate div31_1to31_rates[] = {
@@ -328,7 +330,7 @@
 	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -395,7 +397,7 @@
 	.clksel		= dpll_abe_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M3_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -443,13 +445,14 @@
 	.parent		= &sys_clkin_ck,
 	.dpll_data	= &dpll_core_dd,
 	.init		= &omap2_init_dpll_parent,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap3_core_dpll_ops,
 	.recalc		= &omap3_dpll_recalc,
 };
 
 static struct clk dpll_core_x2_ck = {
 	.name		= "dpll_core_x2_ck",
 	.parent		= &dpll_core_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -465,7 +468,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -495,7 +498,7 @@
 	.clksel		= dpll_core_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_CORE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -515,7 +518,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -581,7 +584,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -606,7 +609,7 @@
 	.clksel		= dpll_abe_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_ABE,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -632,7 +635,7 @@
 	.clksel		= dpll_core_m6x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_CORE,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -689,6 +692,7 @@
 static struct clk dpll_iva_x2_ck = {
 	.name		= "dpll_iva_x2_ck",
 	.parent		= &dpll_iva_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -704,7 +708,7 @@
 	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -716,7 +720,7 @@
 	.clksel		= dpll_iva_m4x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_IVA,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -764,7 +768,7 @@
 	.clksel		= dpll_mpu_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_MPU,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -837,7 +841,7 @@
 	.clksel		= dpll_per_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -846,8 +850,10 @@
 static struct clk dpll_per_x2_ck = {
 	.name		= "dpll_per_x2_ck",
 	.parent		= &dpll_per_ck,
-	.ops		= &clkops_null,
+	.flags		= CLOCK_CLKOUTX2,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap3_clkoutx2_recalc,
+	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 };
 
 static const struct clksel dpll_per_m2x2_div[] = {
@@ -861,7 +867,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_PER,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -887,7 +893,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M4_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT1_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -899,7 +905,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M5_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT2_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -911,7 +917,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M6_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT3_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -923,7 +929,7 @@
 	.clksel		= dpll_per_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M7_DPLL_PER,
 	.clksel_mask	= OMAP4430_HSDIVIDER_CLKOUT4_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -964,6 +970,7 @@
 static struct clk dpll_unipro_x2_ck = {
 	.name		= "dpll_unipro_x2_ck",
 	.parent		= &dpll_unipro_ck,
+	.flags		= CLOCK_CLKOUTX2,
 	.ops		= &clkops_null,
 	.recalc		= &omap3_clkoutx2_recalc,
 };
@@ -979,7 +986,7 @@
 	.clksel		= dpll_unipro_m2x2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_UNIPRO,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -1028,7 +1035,8 @@
 static struct clk dpll_usb_clkdcoldo_ck = {
 	.name		= "dpll_usb_clkdcoldo_ck",
 	.parent		= &dpll_usb_ck,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
+	.clksel_reg	= OMAP4430_CM_CLKDCOLDO_DPLL_USB,
 	.recalc		= &followparent_recalc,
 };
 
@@ -1043,7 +1051,7 @@
 	.clksel		= dpll_usb_m2_div,
 	.clksel_reg	= OMAP4430_CM_DIV_M2_DPLL_USB,
 	.clksel_mask	= OMAP4430_DPLL_CLKOUT_DIV_0_6_MASK,
-	.ops		= &clkops_null,
+	.ops		= &clkops_omap4_dpllmx_ops,
 	.recalc		= &omap2_clksel_recalc,
 	.round_rate	= &omap2_clksel_round_rate,
 	.set_rate	= &omap2_clksel_set_rate,
@@ -3106,11 +3114,11 @@
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
 	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
 	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
-	CLK(NULL,	"dss_sys_clk",			&dss_sys_clk,	CK_443X),
-	CLK(NULL,	"dss_tv_clk",			&dss_tv_clk,	CK_443X),
-	CLK(NULL,	"dss_dss_clk",			&dss_dss_clk,	CK_443X),
-	CLK(NULL,	"dss_48mhz_clk",		&dss_48mhz_clk,	CK_443X),
-	CLK(NULL,	"dss_fck",			&dss_fck,	CK_443X),
+	CLK("omapdss_dss",	"sys_clk",			&dss_sys_clk,	CK_443X),
+	CLK("omapdss_dss",	"tv_clk",			&dss_tv_clk,	CK_443X),
+	CLK("omapdss_dss",	"video_clk",			&dss_48mhz_clk,	CK_443X),
+	CLK("omapdss_dss",	"fck",				&dss_dss_clk,	CK_443X),
+	CLK("omapdss_dss",	"ick",				&dss_fck,	CK_443X),
 	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
 	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
 	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
@@ -3158,11 +3166,11 @@
 	CLK("omap2_mcspi.2",	"fck",				&mcspi2_fck,	CK_443X),
 	CLK("omap2_mcspi.3",	"fck",				&mcspi3_fck,	CK_443X),
 	CLK("omap2_mcspi.4",	"fck",				&mcspi4_fck,	CK_443X),
-	CLK("mmci-omap-hs.0",	"fck",				&mmc1_fck,	CK_443X),
-	CLK("mmci-omap-hs.1",	"fck",				&mmc2_fck,	CK_443X),
-	CLK("mmci-omap-hs.2",	"fck",				&mmc3_fck,	CK_443X),
-	CLK("mmci-omap-hs.3",	"fck",				&mmc4_fck,	CK_443X),
-	CLK("mmci-omap-hs.4",	"fck",				&mmc5_fck,	CK_443X),
+	CLK("omap_hsmmc.0",	"fck",				&mmc1_fck,	CK_443X),
+	CLK("omap_hsmmc.1",	"fck",				&mmc2_fck,	CK_443X),
+	CLK("omap_hsmmc.2",	"fck",				&mmc3_fck,	CK_443X),
+	CLK("omap_hsmmc.3",	"fck",				&mmc4_fck,	CK_443X),
+	CLK("omap_hsmmc.4",	"fck",				&mmc5_fck,	CK_443X),
 	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
 	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
 	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
@@ -3197,7 +3205,7 @@
 	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
 	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
 	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
-	CLK("ehci-omap.0",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
+	CLK("usbhs-omap.0",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_utmi_p1_clk",	&usb_host_hs_utmi_p1_clk,	CK_443X),
 	CLK(NULL,	"utmi_p2_gfclk",		&utmi_p2_gfclk,	CK_443X),
@@ -3209,8 +3217,8 @@
 	CLK(NULL,	"usb_host_hs_hsic480m_p2_clk",	&usb_host_hs_hsic480m_p2_clk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_func48mclk",	&usb_host_hs_func48mclk,	CK_443X),
 	CLK(NULL,	"usb_host_hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK("ehci-omap.0",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
-	CLK("ehci-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
+	CLK("usbhs-omap.0",	"hs_fck",		&usb_host_hs_fck,	CK_443X),
+	CLK("usbhs-omap.0",	"usbhost_ick",		&dummy_ck,		CK_443X),
 	CLK(NULL,	"otg_60m_gfclk",		&otg_60m_gfclk,	CK_443X),
 	CLK(NULL,	"usb_otg_hs_xclk",		&usb_otg_hs_xclk,	CK_443X),
 	CLK("musb-omap2430",	"ick",				&usb_otg_hs_ick,	CK_443X),
@@ -3219,8 +3227,8 @@
 	CLK(NULL,	"usb_tll_hs_usb_ch0_clk",	&usb_tll_hs_usb_ch0_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_usb_ch1_clk",	&usb_tll_hs_usb_ch1_clk,	CK_443X),
 	CLK(NULL,	"usb_tll_hs_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("ehci-omap.0",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
-	CLK("ehci-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
+	CLK("usbhs-omap.0",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
+	CLK("usbhs-omap.0",	"usbtll_fck",		&dummy_ck,	CK_443X),
 	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
 	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
 	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
@@ -3245,11 +3253,11 @@
 	CLK("omap_i2c.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_i2c.3",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap_i2c.4",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.0",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.1",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.2",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.3",	"ick",				&dummy_ck,	CK_443X),
-	CLK("mmci-omap-hs.4",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.0",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.1",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.2",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.3",	"ick",				&dummy_ck,	CK_443X),
+	CLK("omap_hsmmc.4",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.1",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.2",	"ick",				&dummy_ck,	CK_443X),
 	CLK("omap-mcbsp.3",	"ick",				&dummy_ck,	CK_443X),
@@ -3301,6 +3309,9 @@
 			omap2_init_clk_clkdm(c->lk.clk);
 		}
 
+	/* Disable autoidle on all clocks; let the PM code enable it later */
+	omap_clk_disable_autoidle_all();
+
 	recalculate_root_clocks();
 
 	/*
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,9 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/bitops.h>
+#include <trace/events/power.h>
 
+#include <asm/cpu.h>
 #include <plat/clock.h>
 #include "clockdomain.h"
 #include <plat/cpu.h>
@@ -261,10 +263,13 @@
 
 	pr_debug("clock: %s: disabling in hardware\n", clk->name);
 
-	clk->ops->disable(clk);
+	if (clk->ops && clk->ops->disable) {
+		trace_clock_disable(clk->name, 0, smp_processor_id());
+		clk->ops->disable(clk);
+	}
 
 	if (clk->clkdm)
-		omap2_clkdm_clk_disable(clk->clkdm, clk);
+		clkdm_clk_disable(clk->clkdm, clk);
 
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
@@ -304,7 +309,7 @@
 	}
 
 	if (clk->clkdm) {
-		ret = omap2_clkdm_clk_enable(clk->clkdm, clk);
+		ret = clkdm_clk_enable(clk->clkdm, clk);
 		if (ret) {
 			WARN(1, "clock: %s: could not enable clockdomain %s: "
 			     "%d\n", clk->name, clk->clkdm->name, ret);
@@ -312,17 +317,21 @@
 		}
 	}
 
-	ret = clk->ops->enable(clk);
-	if (ret) {
-		WARN(1, "clock: %s: could not enable: %d\n", clk->name, ret);
-		goto oce_err3;
+	if (clk->ops && clk->ops->enable) {
+		trace_clock_enable(clk->name, 1, smp_processor_id());
+		ret = clk->ops->enable(clk);
+		if (ret) {
+			WARN(1, "clock: %s: could not enable: %d\n",
+			     clk->name, ret);
+			goto oce_err3;
+		}
 	}
 
 	return 0;
 
 oce_err3:
 	if (clk->clkdm)
-		omap2_clkdm_clk_disable(clk->clkdm, clk);
+		clkdm_clk_disable(clk->clkdm, clk);
 oce_err2:
 	if (clk->parent)
 		omap2_clk_disable(clk->parent);
@@ -349,8 +358,10 @@
 	pr_debug("clock: set_rate for clock %s to rate %ld\n", clk->name, rate);
 
 	/* dpll_ck, core_ck, virt_prcm_set; plus all clksel clocks */
-	if (clk->set_rate)
+	if (clk->set_rate) {
+		trace_clock_set_rate(clk->name, rate, smp_processor_id());
 		ret = clk->set_rate(clk, rate);
+	}
 
 	return ret;
 }
@@ -373,10 +384,16 @@
 const struct clkops clkops_omap3_noncore_dpll_ops = {
 	.enable		= omap3_noncore_dpll_enable,
 	.disable	= omap3_noncore_dpll_disable,
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
 };
 
-#endif
+const struct clkops clkops_omap3_core_dpll_ops = {
+	.allow_idle	= omap3_dpll_allow_idle,
+	.deny_idle	= omap3_dpll_deny_idle,
+};
 
+#endif
 
 /*
  * OMAP2+ clock reset and init functions
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock_common_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock_common_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock_common_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock_common_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,3 +37,9 @@
 	{ .div = 0 }
 };
 
+const struct clksel_rate dsp_ick_rates[] = {
+	{ .div = 1, .val = 1, .flags = RATE_IN_24XX },
+	{ .div = 2, .val = 2, .flags = RATE_IN_24XX },
+	{ .div = 3, .val = 3, .flags = RATE_IN_243X },
+	{ .div = 0 },
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain2xxx_3xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,274 @@
+/*
+ * OMAP2 and OMAP3 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@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/types.h>
+#include <plat/prcm.h>
+#include "prm.h"
+#include "prm2xxx_3xxx.h"
+#include "cm.h"
+#include "cm2xxx_3xxx.h"
+#include "cm-regbits-24xx.h"
+#include "cm-regbits-34xx.h"
+#include "prm-regbits-24xx.h"
+#include "clockdomain.h"
+
+static int omap2_clkdm_add_wkdep(struct clockdomain *clkdm1,
+						struct clockdomain *clkdm2)
+{
+	omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+static int omap2_clkdm_del_wkdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	return 0;
+}
+
+static int omap2_clkdm_read_wkdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				PM_WKDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				 PM_WKDEP);
+	return 0;
+}
+
+static int omap3_clkdm_add_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3_clkdm_del_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
+				clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap3_clkdm_read_sleepdep(struct clockdomain *clkdm1,
+						 struct clockdomain *clkdm2)
+{
+	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP, (1 << clkdm2->dep_bit));
+}
+
+static int omap3_clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		/* PRM accesses are slow, so minimize them */
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->sleepdep_usecount, 0);
+	}
+	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
+				OMAP3430_CM_SLEEPDEP);
+	return 0;
+}
+
+static int omap2_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				clkdm->pwrdm.ptr->prcm_offs,
+				OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
+				clkdm->pwrdm.ptr->prcm_offs,
+				OMAP2_PM_PWSTCTRL);
+	return 0;
+}
+
+static void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
+static void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+static void _enable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+					       clkdm->clktrctrl_mask);
+}
+
+static void _disable_hwsup(struct clockdomain *clkdm)
+{
+	if (cpu_is_omap24xx())
+		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+	else if (cpu_is_omap34xx())
+		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+						clkdm->clktrctrl_mask);
+}
+
+
+static int omap2_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		_disable_hwsup(clkdm);
+		_clkdm_add_autodeps(clkdm);
+		_enable_hwsup(clkdm);
+	} else {
+		clkdm_wakeup(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap2_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	if (!clkdm->clktrctrl_mask)
+		return 0;
+
+	hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (hwsup) {
+		/* Disable HW transitions when we are changing deps */
+		_disable_hwsup(clkdm);
+		_clkdm_del_autodeps(clkdm);
+		_enable_hwsup(clkdm);
+	} else {
+		clkdm_sleep(clkdm);
+	}
+
+	return 0;
+}
+
+static int omap3_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static int omap3_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+	return 0;
+}
+
+static void omap3_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_add_autodeps(clkdm);
+
+	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+}
+
+static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+				clkdm->clktrctrl_mask);
+
+	if (atomic_read(&clkdm->usecount) > 0)
+		_clkdm_del_autodeps(clkdm);
+}
+
+struct clkdm_ops omap2_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_sleep		= omap2_clkdm_sleep,
+	.clkdm_wakeup		= omap2_clkdm_wakeup,
+	.clkdm_allow_idle	= omap2_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap2_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
+};
+
+struct clkdm_ops omap3_clkdm_operations = {
+	.clkdm_add_wkdep	= omap2_clkdm_add_wkdep,
+	.clkdm_del_wkdep	= omap2_clkdm_del_wkdep,
+	.clkdm_read_wkdep	= omap2_clkdm_read_wkdep,
+	.clkdm_clear_all_wkdeps	= omap2_clkdm_clear_all_wkdeps,
+	.clkdm_add_sleepdep	= omap3_clkdm_add_sleepdep,
+	.clkdm_del_sleepdep	= omap3_clkdm_del_sleepdep,
+	.clkdm_read_sleepdep	= omap3_clkdm_read_sleepdep,
+	.clkdm_clear_all_sleepdeps	= omap3_clkdm_clear_all_sleepdeps,
+	.clkdm_sleep		= omap3_clkdm_sleep,
+	.clkdm_wakeup		= omap3_clkdm_wakeup,
+	.clkdm_allow_idle	= omap3_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap3_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap2_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap2_clkdm_clk_disable,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain44xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain44xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain44xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,137 @@
+/*
+ * OMAP4 clockdomain control
+ *
+ * Copyright (C) 2008-2010 Texas Instruments, Inc.
+ * Copyright (C) 2008-2010 Nokia Corporation
+ *
+ * Derived from mach-omap2/clockdomain.c written by Paul Walmsley
+ * Rajendra Nayak <rnayak@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 "clockdomain.h"
+#include "cminst44xx.h"
+#include "cm44xx.h"
+
+static int omap4_clkdm_add_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_set_inst_reg_bits((1 << clkdm2->dep_bit),
+					clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_del_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	omap4_cminst_clear_inst_reg_bits((1 << clkdm2->dep_bit),
+					clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_read_wkup_sleep_dep(struct clockdomain *clkdm1,
+					struct clockdomain *clkdm2)
+{
+	return omap4_cminst_read_inst_reg_bits(clkdm1->prcm_partition,
+					clkdm1->cm_inst, clkdm1->clkdm_offs +
+					OMAP4_CM_STATICDEP,
+					(1 << clkdm2->dep_bit));
+}
+
+static int omap4_clkdm_clear_all_wkup_sleep_deps(struct clockdomain *clkdm)
+{
+	struct clkdm_dep *cd;
+	u32 mask = 0;
+
+	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (!cd->clkdm)
+			continue; /* only happens if data is erroneous */
+
+		mask |= 1 << cd->clkdm->dep_bit;
+		atomic_set(&cd->wkdep_usecount, 0);
+	}
+
+	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs +
+					OMAP4_CM_STATICDEP);
+	return 0;
+}
+
+static int omap4_clkdm_sleep(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static int omap4_clkdm_wakeup(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+	return 0;
+}
+
+static void omap4_clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static void omap4_clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+}
+
+static int omap4_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup)
+		clkdm_wakeup(clkdm);
+
+	return 0;
+}
+
+static int omap4_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+	bool hwsup = false;
+
+	hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
+					clkdm->cm_inst, clkdm->clkdm_offs);
+
+	if (!hwsup)
+		clkdm_sleep(clkdm);
+
+	return 0;
+}
+
+struct clkdm_ops omap4_clkdm_operations = {
+	.clkdm_add_wkdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_wkdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_wkdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_wkdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_add_sleepdep	= omap4_clkdm_add_wkup_sleep_dep,
+	.clkdm_del_sleepdep	= omap4_clkdm_del_wkup_sleep_dep,
+	.clkdm_read_sleepdep	= omap4_clkdm_read_wkup_sleep_dep,
+	.clkdm_clear_all_sleepdeps	= omap4_clkdm_clear_all_wkup_sleep_deps,
+	.clkdm_sleep		= omap4_clkdm_sleep,
+	.clkdm_wakeup		= omap4_clkdm_wakeup,
+	.clkdm_allow_idle	= omap4_clkdm_allow_idle,
+	.clkdm_deny_idle	= omap4_clkdm_deny_idle,
+	.clkdm_clk_enable	= omap4_clkdm_clk_enable,
+	.clkdm_clk_disable	= omap4_clkdm_clk_disable,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,17 +26,8 @@
 
 #include <linux/bitops.h>
 
-#include "prm2xxx_3xxx.h"
-#include "prm-regbits-24xx.h"
-#include "cm2xxx_3xxx.h"
-#include "cm-regbits-24xx.h"
-#include "cminst44xx.h"
-#include "prcm44xx.h"
-
 #include <plat/clock.h>
-#include "powerdomain.h"
 #include "clockdomain.h"
-#include <plat/prcm.h>
 
 /* clkdm_list contains all registered struct clockdomains */
 static LIST_HEAD(clkdm_list);
@@ -44,6 +35,7 @@
 /* array of clockdomain deps to be added/removed when clkdm in hwsup mode */
 static struct clkdm_autodep *autodeps;
 
+static struct clkdm_ops *arch_clkdm;
 
 /* Private functions */
 
@@ -177,11 +169,11 @@
  * XXX autodeps are deprecated and should be removed at the earliest
  * opportunity
  */
-static void _clkdm_add_autodeps(struct clockdomain *clkdm)
+void _clkdm_add_autodeps(struct clockdomain *clkdm)
 {
 	struct clkdm_autodep *autodep;
 
-	if (!autodeps)
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
@@ -211,11 +203,11 @@
  * XXX autodeps are deprecated and should be removed at the earliest
  * opportunity
  */
-static void _clkdm_del_autodeps(struct clockdomain *clkdm)
+void _clkdm_del_autodeps(struct clockdomain *clkdm)
 {
 	struct clkdm_autodep *autodep;
 
-	if (!autodeps)
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
 		return;
 
 	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
@@ -235,55 +227,29 @@
 }
 
 /**
- * _enable_hwsup - place a clockdomain into hardware-supervised idle
- * @clkdm: struct clockdomain *
- *
- * Place the clockdomain into hardware-supervised idle mode.  No return
- * value.
- *
- * XXX Should this return an error if the clockdomain does not support
- * hardware-supervised idle mode?
- */
-static void _enable_hwsup(struct clockdomain *clkdm)
-{
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	else if (cpu_is_omap44xx())
-		return omap4_cminst_clkdm_enable_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-	else
-		BUG();
-}
-
-/**
- * _disable_hwsup - place a clockdomain into software-supervised idle
- * @clkdm: struct clockdomain *
+ * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
+ * @clkdm: clockdomain that we are resolving dependencies for
+ * @clkdm_deps: ptr to array of struct clkdm_deps to resolve
  *
- * Place the clockdomain @clkdm into software-supervised idle mode.
+ * Iterates through @clkdm_deps, looking up the struct clockdomain named by
+ * clkdm_name and storing the clockdomain pointer in the struct clkdm_dep.
  * No return value.
- *
- * XXX Should this return an error if the clockdomain does not support
- * software-supervised idle mode?
  */
-static void _disable_hwsup(struct clockdomain *clkdm)
+static void _resolve_clkdm_deps(struct clockdomain *clkdm,
+				struct clkdm_dep *clkdm_deps)
 {
-	if (cpu_is_omap24xx())
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap34xx())
-		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-	else if (cpu_is_omap44xx())
-		return omap4_cminst_clkdm_disable_hwsup(clkdm->prcm_partition,
-							clkdm->cm_inst,
-							clkdm->clkdm_offs);
-	else
-		BUG();
+	struct clkdm_dep *cd;
+
+	for (cd = clkdm_deps; cd && cd->clkdm_name; cd++) {
+		if (!omap_chip_is(cd->omap_chip))
+			continue;
+		if (cd->clkdm)
+			continue;
+		cd->clkdm = _clkdm_lookup(cd->clkdm_name);
+
+		WARN(!cd->clkdm, "clockdomain: %s: could not find clkdm %s while resolving dependencies - should never happen",
+		     clkdm->name, cd->clkdm_name);
+	}
 }
 
 /* Public functions */
@@ -292,6 +258,7 @@
  * clkdm_init - set up the clockdomain layer
  * @clkdms: optional pointer to an array of clockdomains to register
  * @init_autodeps: optional pointer to an array of autodeps to register
+ * @custom_funcs: func pointers for arch specific implementations
  *
  * Set up internal state.  If a pointer to an array of clockdomains
  * @clkdms was supplied, loop through the list of clockdomains,
@@ -300,12 +267,18 @@
  * @init_autodeps was provided, register those.  No return value.
  */
 void clkdm_init(struct clockdomain **clkdms,
-		struct clkdm_autodep *init_autodeps)
+		struct clkdm_autodep *init_autodeps,
+		struct clkdm_ops *custom_funcs)
 {
 	struct clockdomain **c = NULL;
 	struct clockdomain *clkdm;
 	struct clkdm_autodep *autodep = NULL;
 
+	if (!custom_funcs)
+		WARN(1, "No custom clkdm functions registered\n");
+	else
+		arch_clkdm = custom_funcs;
+
 	if (clkdms)
 		for (c = clkdms; *c; c++)
 			_clkdm_register(*c);
@@ -321,11 +294,14 @@
 	 */
 	list_for_each_entry(clkdm, &clkdm_list, node) {
 		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap2_clkdm_wakeup(clkdm);
+			clkdm_wakeup(clkdm);
 		else if (clkdm->flags & CLKDM_CAN_DISABLE_AUTO)
-			omap2_clkdm_deny_idle(clkdm);
+			clkdm_deny_idle(clkdm);
 
+		_resolve_clkdm_deps(clkdm, clkdm->wkdep_srcs);
 		clkdm_clear_all_wkdeps(clkdm);
+
+		_resolve_clkdm_deps(clkdm, clkdm->sleepdep_srcs);
 		clkdm_clear_all_sleepdeps(clkdm);
 	}
 }
@@ -422,32 +398,32 @@
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
 		pr_debug("clockdomain: hardware will wake up %s when %s wakes "
 			 "up\n", clkdm1->name, clkdm2->name);
 
-		omap2_prm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				     clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -463,32 +439,32 @@
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
 		pr_debug("clockdomain: hardware will no longer wake up %s "
 			 "after %s wakes up\n", clkdm1->name, clkdm2->name);
 
-		omap2_prm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				       clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP);
+		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -508,26 +484,26 @@
 int clkdm_read_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s/%s: %s: not yet implemented\n",
-		       clkdm1->name, clkdm2->name, __func__);
-		return -EINVAL;
-	}
-
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_read_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear wake up of "
 			 "%s when %s wakes up\n", clkdm1->name, clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	/* XXX It's faster to return the atomic wkdep_usecount */
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs, PM_WKDEP,
-				       (1 << clkdm2->dep_bit));
+	return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
 }
 
 /**
@@ -542,33 +518,13 @@
  */
 int clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 {
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!cpu_is_omap24xx() && !cpu_is_omap34xx()) {
-		pr_err("clockdomain: %s: %s: not yet implemented\n",
-		       clkdm->name, __func__);
-		return -EINVAL;
-	}
-
 	if (!clkdm)
 		return -EINVAL;
 
-	for (cd = clkdm->wkdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
-
-		if (!cd->clkdm && cd->clkdm_name)
-			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs, PM_WKDEP);
+	if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_wkdeps)
+		return -EINVAL;
 
-	return 0;
+	return arch_clkdm->clkdm_clear_all_wkdeps(clkdm);
 }
 
 /**
@@ -586,31 +542,33 @@
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
 		pr_debug("clockdomain: will prevent %s from sleeping if %s "
 			 "is active\n", clkdm1->name, clkdm2->name);
 
-		omap2_cm_set_mod_reg_bits((1 << clkdm2->dep_bit),
-				    clkdm1->pwrdm.ptr->prcm_offs,
-				    OMAP3430_CM_SLEEPDEP);
+		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -628,19 +586,23 @@
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
@@ -648,12 +610,10 @@
 			 "sleeping if %s is active\n", clkdm1->name,
 			 clkdm2->name);
 
-		omap2_cm_clear_mod_reg_bits((1 << clkdm2->dep_bit),
-				      clkdm1->pwrdm.ptr->prcm_offs,
-				      OMAP3430_CM_SLEEPDEP);
+		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
 	}
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -675,25 +635,27 @@
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
+	int ret = 0;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
-	if (IS_ERR(cd)) {
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_read_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
 		pr_debug("clockdomain: hardware cannot set/clear sleep "
 			 "dependency affecting %s from %s\n", clkdm1->name,
 			 clkdm2->name);
-		return PTR_ERR(cd);
+		return ret;
 	}
 
 	/* XXX It's faster to return the atomic sleepdep_usecount */
-	return omap2_prm_read_mod_bits_shift(clkdm1->pwrdm.ptr->prcm_offs,
-				       OMAP3430_CM_SLEEPDEP,
-				       (1 << clkdm2->dep_bit));
+	return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
 }
 
 /**
@@ -708,35 +670,17 @@
  */
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm)
 {
-	struct clkdm_dep *cd;
-	u32 mask = 0;
-
-	if (!cpu_is_omap34xx())
-		return -EINVAL;
-
 	if (!clkdm)
 		return -EINVAL;
 
-	for (cd = clkdm->sleepdep_srcs; cd && cd->clkdm_name; cd++) {
-		if (!omap_chip_is(cd->omap_chip))
-			continue;
-
-		if (!cd->clkdm && cd->clkdm_name)
-			cd->clkdm = _clkdm_lookup(cd->clkdm_name);
-
-		/* PRM accesses are slow, so minimize them */
-		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
-	}
-
-	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
-			       OMAP3430_CM_SLEEPDEP);
+	if (!arch_clkdm || !arch_clkdm->clkdm_clear_all_sleepdeps)
+		return -EINVAL;
 
-	return 0;
+	return arch_clkdm->clkdm_clear_all_sleepdeps(clkdm);
 }
 
 /**
- * omap2_clkdm_sleep - force clockdomain sleep transition
+ * clkdm_sleep - force clockdomain sleep transition
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a sleep transition on the specified
@@ -744,7 +688,7 @@
  * clockdomain does not support software-initiated sleep; 0 upon
  * success.
  */
-int omap2_clkdm_sleep(struct clockdomain *clkdm)
+int clkdm_sleep(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return -EINVAL;
@@ -755,33 +699,16 @@
 		return -EINVAL;
 	}
 
-	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
-
-	if (cpu_is_omap24xx()) {
-
-		omap2_cm_set_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-			    clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	} else if (cpu_is_omap34xx()) {
-
-		omap3xxx_cm_clkdm_force_sleep(clkdm->pwrdm.ptr->prcm_offs,
-					      clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		omap4_cminst_clkdm_force_sleep(clkdm->prcm_partition,
-					       clkdm->cm_inst,
-					       clkdm->clkdm_offs);
+	if (!arch_clkdm || !arch_clkdm->clkdm_sleep)
+		return -EINVAL;
 
-	} else {
-		BUG();
-	};
+	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-	return 0;
+	return arch_clkdm->clkdm_sleep(clkdm);
 }
 
 /**
- * omap2_clkdm_wakeup - force clockdomain wakeup transition
+ * clkdm_wakeup - force clockdomain wakeup transition
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a wakeup transition on the specified
@@ -789,7 +716,7 @@
  * clockdomain does not support software-controlled wakeup; 0 upon
  * success.
  */
-int omap2_clkdm_wakeup(struct clockdomain *clkdm)
+int clkdm_wakeup(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return -EINVAL;
@@ -800,33 +727,16 @@
 		return -EINVAL;
 	}
 
-	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
-
-	if (cpu_is_omap24xx()) {
-
-		omap2_cm_clear_mod_reg_bits(OMAP24XX_FORCESTATE_MASK,
-			      clkdm->pwrdm.ptr->prcm_offs, OMAP2_PM_PWSTCTRL);
-
-	} else if (cpu_is_omap34xx()) {
-
-		omap3xxx_cm_clkdm_force_wakeup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		omap4_cminst_clkdm_force_wakeup(clkdm->prcm_partition,
-						clkdm->cm_inst,
-						clkdm->clkdm_offs);
+	if (!arch_clkdm || !arch_clkdm->clkdm_wakeup)
+		return -EINVAL;
 
-	} else {
-		BUG();
-	};
+	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-	return 0;
+	return arch_clkdm->clkdm_wakeup(clkdm);
 }
 
 /**
- * omap2_clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * clkdm_allow_idle - enable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
  * Allow the hardware to automatically switch the clockdomain @clkdm into
@@ -835,7 +745,7 @@
  * framework, wkdep/sleepdep autodependencies are added; this is so
  * device drivers can read and write to the device.  No return value.
  */
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm)
+void clkdm_allow_idle(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return;
@@ -846,27 +756,18 @@
 		return;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_allow_idle)
+		return;
+
 	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	/*
-	 * XXX This should be removed once TI adds wakeup/sleep
-	 * dependency code and data for OMAP4.
-	 */
-	if (cpu_is_omap44xx()) {
-		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
-	} else {
-		if (atomic_read(&clkdm->usecount) > 0)
-			_clkdm_add_autodeps(clkdm);
-	}
-
-	_enable_hwsup(clkdm);
-
+	arch_clkdm->clkdm_allow_idle(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
 }
 
 /**
- * omap2_clkdm_deny_idle - disable hwsup idle transitions for clkdm
+ * clkdm_deny_idle - disable hwsup idle transitions for clkdm
  * @clkdm: struct clockdomain *
  *
  * Prevent the hardware from automatically switching the clockdomain
@@ -874,7 +775,7 @@
  * downstream clocks enabled in the clock framework, wkdep/sleepdep
  * autodependencies are removed.  No return value.
  */
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm)
+void clkdm_deny_idle(struct clockdomain *clkdm)
 {
 	if (!clkdm)
 		return;
@@ -885,28 +786,20 @@
 		return;
 	}
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_deny_idle)
+		return;
+
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	_disable_hwsup(clkdm);
-
-	/*
-	 * XXX This should be removed once TI adds wakeup/sleep
-	 * dependency code and data for OMAP4.
-	 */
-	if (cpu_is_omap44xx()) {
-		pr_err("clockdomain: %s: OMAP4 wakeup/sleep dependency support: not yet implemented\n", clkdm->name);
-	} else {
-		if (atomic_read(&clkdm->usecount) > 0)
-			_clkdm_del_autodeps(clkdm);
-	}
+	arch_clkdm->clkdm_deny_idle(clkdm);
 }
 
 
 /* Clockdomain-to-clock framework interface code */
 
 /**
- * omap2_clkdm_clk_enable - add an enabled downstream clock to this clkdm
+ * clkdm_clk_enable - add an enabled downstream clock to this clkdm
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the enabled downstream clock
  *
@@ -919,10 +812,8 @@
  * by on-chip processors.  Returns -EINVAL if passed null pointers;
  * returns 0 upon success or if the clockdomain is in hwsup idle mode.
  */
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
+int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk)
 {
-	bool hwsup = false;
-
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
 	 * downstream clocks for debugging purposes?
@@ -931,6 +822,9 @@
 	if (!clkdm || !clk)
 		return -EINVAL;
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_clk_enable)
+		return -EINVAL;
+
 	if (atomic_inc_return(&clkdm->usecount) > 1)
 		return 0;
 
@@ -939,31 +833,7 @@
 	pr_debug("clockdomain: clkdm %s: clk %s now enabled\n", clkdm->name,
 		 clk->name);
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-
-		if (!clkdm->clktrctrl_mask)
-			return 0;
-
-		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						   clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-
-	}
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_add_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		omap2_clkdm_wakeup(clkdm);
-	}
-
+	arch_clkdm->clkdm_clk_enable(clkdm);
 	pwrdm_wait_transition(clkdm->pwrdm.ptr);
 	pwrdm_clkdm_state_switch(clkdm);
 
@@ -971,7 +841,7 @@
 }
 
 /**
- * omap2_clkdm_clk_disable - remove an enabled downstream clock from this clkdm
+ * clkdm_clk_disable - remove an enabled downstream clock from this clkdm
  * @clkdm: struct clockdomain *
  * @clk: struct clk * of the disabled downstream clock
  *
@@ -984,10 +854,8 @@
  * is enabled; or returns 0 upon success or if the clockdomain is in
  * hwsup idle mode.
  */
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
+int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-	bool hwsup = false;
-
 	/*
 	 * XXX Rewrite this code to maintain a list of enabled
 	 * downstream clocks for debugging purposes?
@@ -996,6 +864,9 @@
 	if (!clkdm || !clk)
 		return -EINVAL;
 
+	if (!arch_clkdm || !arch_clkdm->clkdm_clk_disable)
+		return -EINVAL;
+
 #ifdef DEBUG
 	if (atomic_read(&clkdm->usecount) == 0) {
 		WARN_ON(1); /* underflow */
@@ -1011,31 +882,7 @@
 	pr_debug("clockdomain: clkdm %s: clk %s now disabled\n", clkdm->name,
 		 clk->name);
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
-
-		if (!clkdm->clktrctrl_mask)
-			return 0;
-
-		hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						   clkdm->clktrctrl_mask);
-
-	} else if (cpu_is_omap44xx()) {
-
-		hwsup = omap4_cminst_is_clkdm_in_hwsup(clkdm->prcm_partition,
-						       clkdm->cm_inst,
-						       clkdm->clkdm_offs);
-
-	}
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		_disable_hwsup(clkdm);
-		_clkdm_del_autodeps(clkdm);
-		_enable_hwsup(clkdm);
-	} else {
-		omap2_clkdm_sleep(clkdm);
-	}
-
+	arch_clkdm->clkdm_clk_disable(clkdm);
 	pwrdm_clkdm_state_switch(clkdm);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomain.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomain.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * OMAP2/3 clockdomain framework functions
  *
  * Copyright (C) 2008 Texas Instruments, Inc.
- * Copyright (C) 2008-2010 Nokia Corporation
+ * Copyright (C) 2008-2011 Nokia Corporation
  *
  * Paul Walmsley
  *
@@ -22,11 +22,19 @@
 #include <plat/clock.h>
 #include <plat/cpu.h>
 
-/* Clockdomain capability flags */
+/*
+ * Clockdomain flags
+ *
+ * XXX Document CLKDM_CAN_* flags
+ *
+ * CLKDM_NO_AUTODEPS: Prevent "autodeps" from being added/removed from this
+ *     clockdomain.  (Currently, this applies to OMAP3 clockdomains only.)
+ */
 #define CLKDM_CAN_FORCE_SLEEP			(1 << 0)
 #define CLKDM_CAN_FORCE_WAKEUP			(1 << 1)
 #define CLKDM_CAN_ENABLE_AUTO			(1 << 2)
 #define CLKDM_CAN_DISABLE_AUTO			(1 << 3)
+#define CLKDM_NO_AUTODEPS			(1 << 4)
 
 #define CLKDM_CAN_HWSUP		(CLKDM_CAN_ENABLE_AUTO | CLKDM_CAN_DISABLE_AUTO)
 #define CLKDM_CAN_SWSUP		(CLKDM_CAN_FORCE_SLEEP | CLKDM_CAN_FORCE_WAKEUP)
@@ -116,7 +124,42 @@
 	struct list_head node;
 };
 
-void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps);
+/**
+ * struct clkdm_ops - Arch specific function implementations
+ * @clkdm_add_wkdep: Add a wakeup dependency between clk domains
+ * @clkdm_del_wkdep: Delete a wakeup dependency between clk domains
+ * @clkdm_read_wkdep: Read wakeup dependency state between clk domains
+ * @clkdm_clear_all_wkdeps: Remove all wakeup dependencies from the clk domain
+ * @clkdm_add_sleepdep: Add a sleep dependency between clk domains
+ * @clkdm_del_sleepdep: Delete a sleep dependency between clk domains
+ * @clkdm_read_sleepdep: Read sleep dependency state between clk domains
+ * @clkdm_clear_all_sleepdeps: Remove all sleep dependencies from the clk domain
+ * @clkdm_sleep: Force a clockdomain to sleep
+ * @clkdm_wakeup: Force a clockdomain to wakeup
+ * @clkdm_allow_idle: Enable hw supervised idle transitions for clock domain
+ * @clkdm_deny_idle: Disable hw supervised idle transitions for clock domain
+ * @clkdm_clk_enable: Put the clkdm in right state for a clock enable
+ * @clkdm_clk_disable: Put the clkdm in right state for a clock disable
+ */
+struct clkdm_ops {
+	int	(*clkdm_add_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_del_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_read_wkdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_clear_all_wkdeps)(struct clockdomain *clkdm);
+	int	(*clkdm_add_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_del_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_read_sleepdep)(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
+	int	(*clkdm_clear_all_sleepdeps)(struct clockdomain *clkdm);
+	int	(*clkdm_sleep)(struct clockdomain *clkdm);
+	int	(*clkdm_wakeup)(struct clockdomain *clkdm);
+	void	(*clkdm_allow_idle)(struct clockdomain *clkdm);
+	void	(*clkdm_deny_idle)(struct clockdomain *clkdm);
+	int	(*clkdm_clk_enable)(struct clockdomain *clkdm);
+	int	(*clkdm_clk_disable)(struct clockdomain *clkdm);
+};
+
+void clkdm_init(struct clockdomain **clkdms, struct clkdm_autodep *autodeps,
+			struct clkdm_ops *custom_funcs);
 struct clockdomain *clkdm_lookup(const char *name);
 
 int clkdm_for_each(int (*fn)(struct clockdomain *clkdm, void *user),
@@ -132,16 +175,23 @@
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
-void omap2_clkdm_allow_idle(struct clockdomain *clkdm);
-void omap2_clkdm_deny_idle(struct clockdomain *clkdm);
+void clkdm_allow_idle(struct clockdomain *clkdm);
+void clkdm_deny_idle(struct clockdomain *clkdm);
 
-int omap2_clkdm_wakeup(struct clockdomain *clkdm);
-int omap2_clkdm_sleep(struct clockdomain *clkdm);
+int clkdm_wakeup(struct clockdomain *clkdm);
+int clkdm_sleep(struct clockdomain *clkdm);
 
-int omap2_clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
-int omap2_clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
+int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk);
 
-extern void __init omap2_clockdomains_init(void);
+extern void __init omap2xxx_clockdomains_init(void);
+extern void __init omap3xxx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
+extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
+extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
+
+extern struct clkdm_ops omap2_clkdm_operations;
+extern struct clkdm_ops omap3_clkdm_operations;
+extern struct clkdm_ops omap4_clkdm_operations;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomains2xxx_3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,6 +89,8 @@
 
 /* 24XX-specific possible dependencies */
 
+#ifdef CONFIG_ARCH_OMAP2
+
 /* Wakeup dependency source arrays */
 
 /* 2420/2430 PM_WKDEP_DSP: CORE, MPU, WKUP */
@@ -168,10 +170,11 @@
 	{ NULL },
 };
 
+#endif /* CONFIG_ARCH_OMAP2 */
 
 /* 2430-specific possible wakeup dependencies */
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 
 /* 2430 PM_WKDEP_MDM: CORE, MPU, WKUP */
 static struct clkdm_dep mdm_2430_wkdeps[] = {
@@ -194,7 +197,7 @@
 	{ NULL },
 };
 
-#endif /* CONFIG_ARCH_OMAP2430 */
+#endif /* CONFIG_SOC_OMAP2430 */
 
 
 /* OMAP3-specific possible dependencies */
@@ -450,7 +453,7 @@
  * 2420-only clockdomains
  */
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 
 static struct clockdomain mpu_2420_clkdm = {
 	.name		= "mpu_clkdm",
@@ -514,14 +517,14 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
-#endif   /* CONFIG_ARCH_OMAP2420 */
+#endif   /* CONFIG_SOC_OMAP2420 */
 
 
 /*
  * 2430-only clockdomains
  */
 
-#if defined(CONFIG_ARCH_OMAP2430)
+#if defined(CONFIG_SOC_OMAP2430)
 
 static struct clockdomain mpu_2430_clkdm = {
 	.name		= "mpu_clkdm",
@@ -600,7 +603,7 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
-#endif    /* CONFIG_ARCH_OMAP2430 */
+#endif    /* CONFIG_SOC_OMAP2430 */
 
 
 /*
@@ -811,7 +814,7 @@
 	&cm_clkdm,
 	&prm_clkdm,
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 	&mpu_2420_clkdm,
 	&iva1_2420_clkdm,
 	&dsp_2420_clkdm,
@@ -821,7 +824,7 @@
 	&dss_2420_clkdm,
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 	&mpu_2430_clkdm,
 	&mdm_clkdm,
 	&dsp_2430_clkdm,
@@ -854,7 +857,12 @@
 	NULL,
 };
 
-void __init omap2_clockdomains_init(void)
+void __init omap2xxx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap2, clkdm_autodeps);
+	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap2_clkdm_operations);
+}
+
+void __init omap3xxx_clockdomains_init(void)
+{
+	clkdm_init(clockdomains_omap2, clkdm_autodeps, &omap3_clkdm_operations);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clockdomains44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,11 +18,6 @@
  * published by the Free Software Foundation.
  */
 
-/*
- * To-Do List
- * -> Populate the Sleep/Wakeup dependencies for the domains
- */
-
 #include <linux/kernel.h>
 #include <linux/io.h>
 
@@ -35,6 +30,355 @@
 #include "prcm44xx.h"
 #include "prcm_mpu44xx.h"
 
+/* Static Dependencies for OMAP4 Clock Domains */
+
+static struct clkdm_dep ducati_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_gfx_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "tesla_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep iss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep ivahd_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_d2d_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_dma_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ducati_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_dss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_gfx_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l3_init_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep l4_secure_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep mpuss_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ducati_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_dss_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_gfx_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_secure_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "tesla_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
+
+static struct clkdm_dep tesla_wkup_sleep_deps[] = {
+	{
+		.clkdm_name	 = "abe_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "ivahd_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_1_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_2_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_emif_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l3_init_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_cfg_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_per_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{
+		.clkdm_name	 = "l4_wkup_clkdm",
+		.omap_chip	 = OMAP_CHIP_INIT(CHIP_IS_OMAP4430)
+	},
+	{ NULL },
+};
 
 static struct clockdomain l4_cefuse_44xx_clkdm = {
 	.name		  = "l4_cefuse_clkdm",
@@ -52,6 +396,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L4CFG_CDOFFS,
+	.dep_bit	  = OMAP4430_L4CFG_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -62,6 +407,9 @@
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_TESLA_INST,
 	.clkdm_offs	  = OMAP4430_CM1_TESLA_TESLA_CDOFFS,
+	.dep_bit	  = OMAP4430_TESLA_STATDEP_SHIFT,
+	.wkdep_srcs	  = tesla_wkup_sleep_deps,
+	.sleepdep_srcs	  = tesla_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -72,6 +420,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_GFX_INST,
 	.clkdm_offs	  = OMAP4430_CM2_GFX_GFX_CDOFFS,
+	.dep_bit	  = OMAP4430_GFX_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_gfx_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_gfx_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -82,6 +433,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_IVAHD_INST,
 	.clkdm_offs	  = OMAP4430_CM2_IVAHD_IVAHD_CDOFFS,
+	.dep_bit	  = OMAP4430_IVAHD_STATDEP_SHIFT,
+	.wkdep_srcs	  = ivahd_wkup_sleep_deps,
+	.sleepdep_srcs	  = ivahd_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -92,6 +446,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4SEC_CDOFFS,
+	.dep_bit	  = OMAP4430_L4SEC_STATDEP_SHIFT,
+	.wkdep_srcs	  = l4_secure_wkup_sleep_deps,
+	.sleepdep_srcs	  = l4_secure_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -102,6 +459,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L4PER_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L4PER_L4PER_CDOFFS,
+	.dep_bit	  = OMAP4430_L4PER_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -112,6 +470,7 @@
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_ABE_INST,
 	.clkdm_offs	  = OMAP4430_CM1_ABE_ABE_CDOFFS,
+	.dep_bit	  = OMAP4430_ABE_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -131,6 +490,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_L3INIT_INST,
 	.clkdm_offs	  = OMAP4430_CM2_L3INIT_L3INIT_CDOFFS,
+	.dep_bit	  = OMAP4430_L3INIT_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_init_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_init_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -141,6 +503,8 @@
 	.prcm_partition	  = OMAP4430_CM1_PARTITION,
 	.cm_inst	  = OMAP4430_CM1_MPU_INST,
 	.clkdm_offs	  = OMAP4430_CM1_MPU_MPU_CDOFFS,
+	.wkdep_srcs	  = mpuss_wkup_sleep_deps,
+	.sleepdep_srcs	  = mpuss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -150,7 +514,7 @@
 	.pwrdm		  = { .name = "cpu0_pwrdm" },
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU0_INST,
-	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -160,7 +524,7 @@
 	.pwrdm		  = { .name = "cpu1_pwrdm" },
 	.prcm_partition	  = OMAP4430_PRCM_MPU_PARTITION,
 	.cm_inst	  = OMAP4430_PRCM_MPU_CPU1_INST,
-	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS,
+	.clkdm_offs	  = OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -171,6 +535,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_MEMIF_CDOFFS,
+	.dep_bit	  = OMAP4430_MEMIF_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -191,6 +556,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_DUCATI_CDOFFS,
+	.dep_bit	  = OMAP4430_DUCATI_STATDEP_SHIFT,
+	.wkdep_srcs	  = ducati_wkup_sleep_deps,
+	.sleepdep_srcs	  = ducati_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -201,6 +569,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_2_CDOFFS,
+	.dep_bit	  = OMAP4430_L3_2_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -211,6 +580,7 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_L3_1_CDOFFS,
+	.dep_bit	  = OMAP4430_L3_1_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -221,6 +591,8 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_D2D_CDOFFS,
+	.wkdep_srcs	  = l3_d2d_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_d2d_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -231,6 +603,8 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CAM_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CAM_CAM_CDOFFS,
+	.wkdep_srcs	  = iss_wkup_sleep_deps,
+	.sleepdep_srcs	  = iss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -241,6 +615,9 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_DSS_INST,
 	.clkdm_offs	  = OMAP4430_CM2_DSS_DSS_CDOFFS,
+	.dep_bit	  = OMAP4430_DSS_STATDEP_SHIFT,
+	.wkdep_srcs	  = l3_dss_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_dss_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_HWSUP_SWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -251,6 +628,7 @@
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.cm_inst	  = OMAP4430_PRM_WKUP_CM_INST,
 	.clkdm_offs	  = OMAP4430_PRM_WKUP_CM_WKUP_CDOFFS,
+	.dep_bit	  = OMAP4430_L4WKUP_STATDEP_SHIFT,
 	.flags		  = CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -271,6 +649,8 @@
 	.prcm_partition	  = OMAP4430_CM2_PARTITION,
 	.cm_inst	  = OMAP4430_CM2_CORE_INST,
 	.clkdm_offs	  = OMAP4430_CM2_CORE_SDMA_CDOFFS,
+	.wkdep_srcs	  = l3_dma_wkup_sleep_deps,
+	.sleepdep_srcs	  = l3_dma_wkup_sleep_deps,
 	.flags		  = CLKDM_CAN_FORCE_WAKEUP | CLKDM_CAN_HWSUP,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 };
@@ -305,5 +685,5 @@
 
 void __init omap44xx_clockdomains_init(void)
 {
-	clkdm_init(clockdomains_omap44xx, NULL);
+	clkdm_init(clockdomains_omap44xx, NULL, &omap4_clkdm_operations);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  *  linux/arch/arm/mach-omap2/clock.h
  *
  *  Copyright (C) 2005-2009 Texas Instruments, Inc.
- *  Copyright (C) 2004-2009 Nokia Corporation
+ *  Copyright (C) 2004-2011 Nokia Corporation
  *
  *  Contacts:
  *  Richard Woodruff <r-woodruff2@ti.com>
@@ -18,9 +18,6 @@
 
 #include <plat/clock.h>
 
-/* The maximum error between a target DPLL rate and the rounded rate in Hz */
-#define DEFAULT_DPLL_RATE_TOLERANCE	50000
-
 /* CM_CLKSEL2_PLL.CORE_CLK_SRC bits (2XXX) */
 #define CORE_CLK_SRC_32K		0x0
 #define CORE_CLK_SRC_DPLL		0x1
@@ -55,7 +52,6 @@
 long omap2_clk_round_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clk_set_parent(struct clk *clk, struct clk *new_parent);
-int omap2_dpll_set_rate_tolerance(struct clk *clk, unsigned int tolerance);
 long omap2_dpll_round_rate(struct clk *clk, unsigned long target_rate);
 unsigned long omap3_dpll_recalc(struct clk *clk);
 unsigned long omap3_clkoutx2_recalc(struct clk *clk);
@@ -65,6 +61,9 @@
 int omap3_noncore_dpll_set_rate(struct clk *clk, unsigned long rate);
 int omap3_noncore_dpll_enable(struct clk *clk);
 void omap3_noncore_dpll_disable(struct clk *clk);
+int omap4_dpllmx_gatectrl_read(struct clk *clk);
+void omap4_dpllmx_allow_gatectrl(struct clk *clk);
+void omap4_dpllmx_deny_gatectrl(struct clk *clk);
 
 #ifdef CONFIG_OMAP_RESET_CLOCKS
 void omap2_clk_disable_unused(struct clk *clk);
@@ -83,6 +82,10 @@
 int omap2_clksel_set_rate(struct clk *clk, unsigned long rate);
 int omap2_clksel_set_parent(struct clk *clk, struct clk *new_parent);
 
+/* clkt_iclk.c public functions */
+extern void omap2_clkt_iclk_allow_idle(struct clk *clk);
+extern void omap2_clkt_iclk_deny_idle(struct clk *clk);
+
 u32 omap2_get_dpll_rate(struct clk *clk);
 void omap2_init_dpll_parent(struct clk *clk);
 
@@ -136,6 +139,7 @@
 extern const struct clksel_rate gpt_32k_rates[];
 extern const struct clksel_rate gpt_sys_rates[];
 extern const struct clksel_rate gfx_l3_rates[];
+extern const struct clksel_rate dsp_ick_rates[];
 
 #if defined(CONFIG_ARCH_OMAP2) && defined(CONFIG_CPU_FREQ)
 extern void omap2_clk_init_cpufreq_table(struct cpufreq_frequency_table **table);
@@ -145,6 +149,13 @@
 #define omap2_clk_exit_cpufreq_table	0
 #endif
 
+extern const struct clkops clkops_omap2_iclk_dflt_wait;
+extern const struct clkops clkops_omap2_iclk_dflt;
+extern const struct clkops clkops_omap2_iclk_idle_only;
+extern const struct clkops clkops_omap2_mdmclk_dflt_wait;
+extern const struct clkops clkops_omap2xxx_dpll_ops;
 extern const struct clkops clkops_omap3_noncore_dpll_ops;
+extern const struct clkops clkops_omap3_core_dpll_ops;
+extern const struct clkops clkops_omap4_dpllmx_ops;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,14 @@
 #include "cm-regbits-24xx.h"
 #include "cm-regbits-34xx.h"
 
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for DPLLs */
+#define DPLL_AUTOIDLE_DISABLE				0x0
+#define OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
+/* CM_AUTOIDLE_PLL.AUTO_* bit values for APLLs (OMAP2xxx only) */
+#define OMAP2XXX_APLL_AUTOIDLE_DISABLE			0x0
+#define OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP		0x3
+
 static const u8 cm_idlest_offs[] = {
 	CM_IDLEST1, CM_IDLEST2, OMAP2430_CM_IDLEST3
 };
@@ -125,6 +133,67 @@
 	_write_clktrctrl(OMAP34XX_CLKSTCTRL_FORCE_WAKEUP, module, mask);
 }
 
+/*
+ * DPLL autoidle control
+ */
+
+static void _omap2xxx_set_dpll_autoidle(u8 m)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~OMAP24XX_AUTO_DPLL_MASK;
+	v |= m << OMAP24XX_AUTO_DPLL_SHIFT;
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_dpll_disable_autoidle(void)
+{
+	_omap2xxx_set_dpll_autoidle(OMAP2XXX_DPLL_AUTOIDLE_LOW_POWER_STOP);
+}
+
+void omap2xxx_cm_set_dpll_auto_low_power_stop(void)
+{
+	_omap2xxx_set_dpll_autoidle(DPLL_AUTOIDLE_DISABLE);
+}
+
+/*
+ * APLL autoidle control
+ */
+
+static void _omap2xxx_set_apll_autoidle(u8 m, u32 mask)
+{
+	u32 v;
+
+	v = omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
+	v &= ~mask;
+	v |= m << __ffs(mask);
+	omap2_cm_write_mod_reg(v, PLL_MOD, CM_AUTOIDLE);
+}
+
+void omap2xxx_cm_set_apll54_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll54_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_54M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_disable_autoidle(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_LOW_POWER_STOP,
+				    OMAP24XX_AUTO_96M_MASK);
+}
+
+void omap2xxx_cm_set_apll96_auto_low_power_stop(void)
+{
+	_omap2xxx_set_apll_autoidle(OMAP2XXX_APLL_AUTOIDLE_DISABLE,
+				    OMAP24XX_AUTO_96M_MASK);
+}
 
 /*
  *
@@ -178,6 +247,7 @@
 	u32 per_cm_clksel;
 	u32 emu_cm_clksel;
 	u32 emu_cm_clkstctrl;
+	u32 pll_cm_autoidle;
 	u32 pll_cm_autoidle2;
 	u32 pll_cm_clksel4;
 	u32 pll_cm_clksel5;
@@ -250,6 +320,15 @@
 		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, CM_CLKSEL1);
 	cm_context.emu_cm_clkstctrl =
 		omap2_cm_read_mod_reg(OMAP3430_EMU_MOD, OMAP2_CM_CLKSTCTRL);
+	/*
+	 * As per erratum i671, ROM code does not respect the PER DPLL
+	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+	 * In this case, even though this register has been saved in
+	 * scratchpad contents, we need to restore AUTO_PERIPH_DPLL
+	 * by ourselves. So, we need to save it anyway.
+	 */
+	cm_context.pll_cm_autoidle =
+		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE);
 	cm_context.pll_cm_autoidle2 =
 		omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE2);
 	cm_context.pll_cm_clksel4 =
@@ -372,6 +451,13 @@
 			       CM_CLKSEL1);
 	omap2_cm_write_mod_reg(cm_context.emu_cm_clkstctrl, OMAP3430_EMU_MOD,
 			       OMAP2_CM_CLKSTCTRL);
+	/*
+	 * As per erratum i671, ROM code does not respect the PER DPLL
+	 * programming scheme if CM_AUTOIDLE_PLL.AUTO_PERIPH_DPLL == 1.
+	 * In this case, we need to restore AUTO_PERIPH_DPLL by ourselves.
+	 */
+	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle, PLL_MOD,
+			       CM_AUTOIDLE);
 	omap2_cm_write_mod_reg(cm_context.pll_cm_autoidle2, PLL_MOD,
 			       CM_AUTOIDLE2);
 	omap2_cm_write_mod_reg(cm_context.pll_cm_clksel4, PLL_MOD,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm2xxx_3xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,6 +122,14 @@
 extern void omap3xxx_cm_clkdm_force_sleep(s16 module, u32 mask);
 extern void omap3xxx_cm_clkdm_force_wakeup(s16 module, u32 mask);
 
+extern void omap2xxx_cm_set_dpll_disable_autoidle(void);
+extern void omap2xxx_cm_set_dpll_auto_low_power_stop(void);
+
+extern void omap2xxx_cm_set_apll54_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll54_auto_low_power_stop(void);
+extern void omap2xxx_cm_set_apll96_disable_autoidle(void);
+extern void omap2xxx_cm_set_apll96_auto_low_power_stop(void);
+
 #endif
 
 /* CM register bits shared between 24XX and 3430 */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm44xx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm44xx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm44xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm44xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include "cm.h"
 
 #define OMAP4_CM_CLKSTCTRL				0x0000
+#define OMAP4_CM_STATICDEP				0x0004
 
 /* Function prototypes */
 # ifndef __ASSEMBLER__
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cminst44xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cminst44xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cminst44xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cminst44xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,6 +73,27 @@
 	return v;
 }
 
+u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+{
+	return omap4_cminst_rmw_inst_reg_bits(bits, bits, part, inst, idx);
+}
+
+u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst, s16 idx)
+{
+	return omap4_cminst_rmw_inst_reg_bits(bits, 0x0, part, inst, idx);
+}
+
+u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx, u32 mask)
+{
+	u32 v;
+
+	v = omap4_cminst_read_inst_reg(part, inst, idx);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
 /*
  *
  */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cminst44xx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cminst44xx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cminst44xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cminst44xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,12 @@
 extern void omap4_cminst_write_inst_reg(u32 val, u8 part, s16 inst, u16 idx);
 extern u32 omap4_cminst_rmw_inst_reg_bits(u32 mask, u32 bits, u8 part,
 					   s16 inst, s16 idx);
+extern u32 omap4_cminst_set_inst_reg_bits(u32 bits, u8 part, s16 inst,
+					   s16 idx);
+extern u32 omap4_cminst_clear_inst_reg_bits(u32 bits, u8 part, s16 inst,
+					   s16 idx);
+extern u32 omap4_cminst_read_inst_reg_bits(u8 part, u16 inst, s16 idx,
+					   u32 mask);
 
 extern int omap4_cm_wait_module_ready(void __iomem *clkctrl_reg);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cm-regbits-24xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -210,8 +210,11 @@
 #define OMAP24XX_AUTO_USB_MASK				(1 << 0)
 
 /* CM_AUTOIDLE3_CORE */
+#define OMAP24XX_AUTO_SDRC_SHIFT			2
 #define OMAP24XX_AUTO_SDRC_MASK				(1 << 2)
+#define OMAP24XX_AUTO_GPMC_SHIFT			1
 #define OMAP24XX_AUTO_GPMC_MASK				(1 << 1)
+#define OMAP24XX_AUTO_SDMA_SHIFT			0
 #define OMAP24XX_AUTO_SDMA_MASK				(1 << 0)
 
 /* CM_AUTOIDLE4_CORE */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/common.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 
 static struct omap_globals omap242x_globals = {
 	.class	= OMAP242X_CLASS,
@@ -50,9 +50,6 @@
 	.ctrl	= OMAP242X_CTRL_BASE,
 	.prm	= OMAP2420_PRM_BASE,
 	.cm	= OMAP2420_CM_BASE,
-	.uart1_phys	= OMAP2_UART1_BASE,
-	.uart2_phys	= OMAP2_UART2_BASE,
-	.uart3_phys	= OMAP2_UART3_BASE,
 };
 
 void __init omap2_set_globals_242x(void)
@@ -61,7 +58,7 @@
 }
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2430)
+#if defined(CONFIG_SOC_OMAP2430)
 
 static struct omap_globals omap243x_globals = {
 	.class	= OMAP243X_CLASS,
@@ -71,9 +68,6 @@
 	.ctrl	= OMAP243X_CTRL_BASE,
 	.prm	= OMAP2430_PRM_BASE,
 	.cm	= OMAP2430_CM_BASE,
-	.uart1_phys	= OMAP2_UART1_BASE,
-	.uart2_phys	= OMAP2_UART2_BASE,
-	.uart3_phys	= OMAP2_UART3_BASE,
 };
 
 void __init omap2_set_globals_243x(void)
@@ -92,10 +86,6 @@
 	.ctrl	= OMAP343X_CTRL_BASE,
 	.prm	= OMAP3430_PRM_BASE,
 	.cm	= OMAP3430_CM_BASE,
-	.uart1_phys	= OMAP3_UART1_BASE,
-	.uart2_phys	= OMAP3_UART2_BASE,
-	.uart3_phys	= OMAP3_UART3_BASE,
-	.uart4_phys	= OMAP3_UART4_BASE,	/* Only on 3630 */
 };
 
 void __init omap2_set_globals_3xxx(void)
@@ -108,6 +98,27 @@
 	omap2_set_globals_3xxx();
 	omap34xx_map_common_io();
 }
+
+/*
+ * Adjust TAP register base such that omap3_check_revision accesses the correct
+ * TI816X register for checking device ID (it adds 0x204 to tap base while
+ * TI816X DEVICE ID register is at offset 0x600 from control base).
+ */
+#define TI816X_TAP_BASE		(TI816X_CTRL_BASE + \
+				TI816X_CONTROL_DEVICE_ID - 0x204)
+
+static struct omap_globals ti816x_globals = {
+	.class  = OMAP343X_CLASS,
+	.tap    = OMAP2_L4_IO_ADDRESS(TI816X_TAP_BASE),
+	.ctrl   = TI816X_CTRL_BASE,
+	.prm    = TI816X_PRCM_BASE,
+	.cm     = TI816X_PRCM_BASE,
+};
+
+void __init omap2_set_globals_ti816x(void)
+{
+	__omap2_set_globals(&ti816x_globals);
+}
 #endif
 
 #if defined(CONFIG_ARCH_OMAP4)
@@ -119,10 +130,6 @@
 	.prm	= OMAP4430_PRM_BASE,
 	.cm	= OMAP4430_CM_BASE,
 	.cm2	= OMAP4430_CM2_BASE,
-	.uart1_phys	= OMAP4_UART1_BASE,
-	.uart2_phys	= OMAP4_UART2_BASE,
-	.uart3_phys	= OMAP4_UART3_BASE,
-	.uart4_phys	= OMAP4_UART4_BASE,
 };
 
 void __init omap2_set_globals_443x(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/control.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/control.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/control.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/control.c	2011-05-19 00:06:34.000000000 -0400
@@ -316,8 +316,14 @@
 			omap2_cm_read_mod_reg(WKUP_MOD, CM_CLKSEL);
 	prcm_block_contents.cm_clken_pll =
 			omap2_cm_read_mod_reg(PLL_MOD, CM_CLKEN);
+	/*
+	 * As per erratum i671, ROM code does not respect the PER DPLL
+	 * programming scheme if CM_AUTOIDLE_PLL..AUTO_PERIPH_DPLL == 1.
+	 * Then,  in anycase, clear these bits to avoid extra latencies.
+	 */
 	prcm_block_contents.cm_autoidle_pll =
-			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_AUTOIDLE_PLL);
+			omap2_cm_read_mod_reg(PLL_MOD, CM_AUTOIDLE) &
+			~OMAP3430_AUTO_PERIPH_DPLL_MASK;
 	prcm_block_contents.cm_clksel1_pll =
 			omap2_cm_read_mod_reg(PLL_MOD, OMAP3430_CM_CLKSEL1_PLL);
 	prcm_block_contents.cm_clksel2_pll =
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/control.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/control.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/control.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/control.h	2011-05-19 00:06:34.000000000 -0400
@@ -52,6 +52,9 @@
 #define OMAP343X_CONTROL_PADCONFS_WKUP	0xa00
 #define OMAP343X_CONTROL_GENERAL_WKUP	0xa60
 
+/* TI816X spefic control submodules */
+#define TI816X_CONTROL_DEVCONF		0x600
+
 /* Control register offsets - read/write with omap_ctrl_{read,write}{bwl}() */
 
 #define OMAP2_CONTROL_SYSCONFIG		(OMAP2_CONTROL_INTERFACE + 0x10)
@@ -241,6 +244,9 @@
 #define OMAP3_PADCONF_SAD2D_MSTANDBY   0x250
 #define OMAP3_PADCONF_SAD2D_IDLEACK    0x254
 
+/* TI816X CONTROL_DEVCONF register offsets */
+#define TI816X_CONTROL_DEVICE_ID	(TI816X_CONTROL_DEVCONF + 0x000)
+
 /*
  * REVISIT: This list of registers is not comprehensive - there are more
  * that should be added.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cpuidle34xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cpuidle34xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/cpuidle34xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/cpuidle34xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,7 @@
 	u32 core_state;
 	u32 threshold;
 	u32 flags;
+	const char *desc;
 };
 
 struct omap3_processor_cx omap3_power_states[OMAP3_MAX_STATES];
@@ -99,14 +100,14 @@
 static int _cpuidle_allow_idle(struct powerdomain *pwrdm,
 				struct clockdomain *clkdm)
 {
-	omap2_clkdm_allow_idle(clkdm);
+	clkdm_allow_idle(clkdm);
 	return 0;
 }
 
 static int _cpuidle_deny_idle(struct powerdomain *pwrdm,
 				struct clockdomain *clkdm)
 {
-	omap2_clkdm_deny_idle(clkdm);
+	clkdm_deny_idle(clkdm);
 	return 0;
 }
 
@@ -296,8 +297,8 @@
 
 /**
  * omap3_cpuidle_update_states() - Update the cpuidle states
- * @mpu_deepest_state:	Enable states upto and including this for mpu domain
- * @core_deepest_state:	Enable states upto and including this for core domain
+ * @mpu_deepest_state:	Enable states up to and including this for mpu domain
+ * @core_deepest_state:	Enable states up to and including this for core domain
  *
  * This goes through the list of states available and enables and disables the
  * validity of C states based on deepest state that can be achieved for the
@@ -365,6 +366,7 @@
 	omap3_power_states[OMAP3_STATE_C1].mpu_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C1].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C1].flags = CPUIDLE_FLAG_TIME_VALID;
+	omap3_power_states[OMAP3_STATE_C1].desc = "MPU ON + CORE ON";
 
 	/* C2 . MPU WFI + Core inactive */
 	omap3_power_states[OMAP3_STATE_C2].valid =
@@ -380,6 +382,7 @@
 	omap3_power_states[OMAP3_STATE_C2].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C2].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C2].desc = "MPU ON + CORE ON";
 
 	/* C3 . MPU CSWR + Core inactive */
 	omap3_power_states[OMAP3_STATE_C3].valid =
@@ -395,6 +398,7 @@
 	omap3_power_states[OMAP3_STATE_C3].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C3].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C3].desc = "MPU RET + CORE ON";
 
 	/* C4 . MPU OFF + Core inactive */
 	omap3_power_states[OMAP3_STATE_C4].valid =
@@ -410,6 +414,7 @@
 	omap3_power_states[OMAP3_STATE_C4].core_state = PWRDM_POWER_ON;
 	omap3_power_states[OMAP3_STATE_C4].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C4].desc = "MPU OFF + CORE ON";
 
 	/* C5 . MPU CSWR + Core CSWR*/
 	omap3_power_states[OMAP3_STATE_C5].valid =
@@ -425,6 +430,7 @@
 	omap3_power_states[OMAP3_STATE_C5].core_state = PWRDM_POWER_RET;
 	omap3_power_states[OMAP3_STATE_C5].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C5].desc = "MPU RET + CORE RET";
 
 	/* C6 . MPU OFF + Core CSWR */
 	omap3_power_states[OMAP3_STATE_C6].valid =
@@ -440,6 +446,7 @@
 	omap3_power_states[OMAP3_STATE_C6].core_state = PWRDM_POWER_RET;
 	omap3_power_states[OMAP3_STATE_C6].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C6].desc = "MPU OFF + CORE RET";
 
 	/* C7 . MPU OFF + Core OFF */
 	omap3_power_states[OMAP3_STATE_C7].valid =
@@ -455,6 +462,7 @@
 	omap3_power_states[OMAP3_STATE_C7].core_state = PWRDM_POWER_OFF;
 	omap3_power_states[OMAP3_STATE_C7].flags = CPUIDLE_FLAG_TIME_VALID |
 				CPUIDLE_FLAG_CHECK_BM;
+	omap3_power_states[OMAP3_STATE_C7].desc = "MPU OFF + CORE OFF";
 
 	/*
 	 * Erratum i583: implementation for ES rev < Es1.2 on 3630. We cannot
@@ -464,7 +472,7 @@
 	if (IS_PM34XX_ERRATUM(PM_SDRC_WAKEUP_ERRATUM_i583)) {
 		omap3_power_states[OMAP3_STATE_C7].valid = 0;
 		cpuidle_params_table[OMAP3_STATE_C7].valid = 0;
-		WARN_ONCE(1, "%s: core off state C7 disabled due to i583\n",
+		pr_warn("%s: core off state C7 disabled due to i583\n",
 				__func__);
 	}
 }
@@ -512,6 +520,7 @@
 		if (cx->type == OMAP3_STATE_C1)
 			dev->safe_state = state;
 		sprintf(state->name, "C%d", count+1);
+		strncpy(state->desc, cx->desc, CPUIDLE_DESC_LEN);
 		count++;
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/slab.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
@@ -30,13 +31,79 @@
 #include <plat/dma.h>
 #include <plat/omap_hwmod.h>
 #include <plat/omap_device.h>
+#include <plat/omap4-keypad.h>
 
 #include "mux.h"
 #include "control.h"
+#include "devices.h"
+
+#define L3_MODULES_MAX_LEN 12
+#define L3_MODULES 3
+
+static int __init omap3_l3_init(void)
+{
+	int l;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	char oh_name[L3_MODULES_MAX_LEN];
+
+	/*
+	 * To avoid code running on other OMAPs in
+	 * multi-omap builds
+	 */
+	if (!(cpu_is_omap34xx()))
+		return -ENODEV;
+
+	l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main");
+
+	oh = omap_hwmod_lookup(oh_name);
+
+	if (!oh)
+		pr_err("could not look up %s\n", oh_name);
+
+	od = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
+							   NULL, 0, 0);
+
+	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+
+	return IS_ERR(od) ? PTR_ERR(od) : 0;
+}
+postcore_initcall(omap3_l3_init);
+
+static int __init omap4_l3_init(void)
+{
+	int l, i;
+	struct omap_hwmod *oh[3];
+	struct omap_device *od;
+	char oh_name[L3_MODULES_MAX_LEN];
+
+	/*
+	 * To avoid code running on other OMAPs in
+	 * multi-omap builds
+	 */
+	if (!(cpu_is_omap44xx()))
+		return -ENODEV;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		l = snprintf(oh_name, L3_MODULES_MAX_LEN, "l3_main_%d", i+1);
+
+		oh[i] = omap_hwmod_lookup(oh_name);
+		if (!(oh[i]))
+			pr_err("could not look up %s\n", oh_name);
+	}
+
+	od = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
+						     0, NULL, 0, 0);
+
+	WARN(IS_ERR(od), "could not build omap_device for %s\n", oh_name);
+
+	return PTR_ERR(od);
+}
+postcore_initcall(omap4_l3_init);
 
 #if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
 
-static struct resource cam_resources[] = {
+static struct resource omap2cam_resources[] = {
 	{
 		.start		= OMAP24XX_CAMERA_BASE,
 		.end		= OMAP24XX_CAMERA_BASE + 0xfff,
@@ -48,19 +115,13 @@
 	}
 };
 
-static struct platform_device omap_cam_device = {
+static struct platform_device omap2cam_device = {
 	.name		= "omap24xxcam",
 	.id		= -1,
-	.num_resources	= ARRAY_SIZE(cam_resources),
-	.resource	= cam_resources,
+	.num_resources	= ARRAY_SIZE(omap2cam_resources),
+	.resource	= omap2cam_resources,
 };
-
-static inline void omap_init_camera(void)
-{
-	platform_device_register(&omap_cam_device);
-}
-
-#elif defined(CONFIG_VIDEO_OMAP3) || defined(CONFIG_VIDEO_OMAP3_MODULE)
+#endif
 
 static struct resource omap3isp_resources[] = {
 	{
@@ -69,11 +130,6 @@
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= OMAP3430_ISP_CBUFF_BASE,
-		.end		= OMAP3430_ISP_CBUFF_END,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
 		.start		= OMAP3430_ISP_CCP2_BASE,
 		.end		= OMAP3430_ISP_CCP2_END,
 		.flags		= IORESOURCE_MEM,
@@ -109,13 +165,33 @@
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= OMAP3430_ISP_CSI2A_BASE,
-		.end		= OMAP3430_ISP_CSI2A_END,
+		.start		= OMAP3430_ISP_CSI2A_REGS1_BASE,
+		.end		= OMAP3430_ISP_CSI2A_REGS1_END,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
-		.start		= OMAP3430_ISP_CSI2PHY_BASE,
-		.end		= OMAP3430_ISP_CSI2PHY_END,
+		.start		= OMAP3430_ISP_CSIPHY2_BASE,
+		.end		= OMAP3430_ISP_CSIPHY2_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3630_ISP_CSI2A_REGS2_BASE,
+		.end		= OMAP3630_ISP_CSI2A_REGS2_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3630_ISP_CSI2C_REGS1_BASE,
+		.end		= OMAP3630_ISP_CSI2C_REGS1_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3630_ISP_CSIPHY1_BASE,
+		.end		= OMAP3630_ISP_CSIPHY1_END,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= OMAP3630_ISP_CSI2C_REGS2_BASE,
+		.end		= OMAP3630_ISP_CSI2C_REGS2_END,
 		.flags		= IORESOURCE_MEM,
 	},
 	{
@@ -131,106 +207,84 @@
 	.resource	= omap3isp_resources,
 };
 
-static inline void omap_init_camera(void)
+int omap3_init_camera(struct isp_platform_data *pdata)
 {
-	platform_device_register(&omap3isp_device);
+	omap3isp_device.dev.platform_data = pdata;
+	return platform_device_register(&omap3isp_device);
 }
-#else
+
 static inline void omap_init_camera(void)
 {
-}
+#if defined(CONFIG_VIDEO_OMAP2) || defined(CONFIG_VIDEO_OMAP2_MODULE)
+	if (cpu_is_omap24xx())
+		platform_device_register(&omap2cam_device);
 #endif
+}
 
-#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
-
-#define MBOX_REG_SIZE   0x120
-
-#ifdef CONFIG_ARCH_OMAP2
-static struct resource omap2_mbox_resources[] = {
-	{
-		.start		= OMAP24XX_MAILBOX_BASE,
-		.end		= OMAP24XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= INT_24XX_MAIL_U0_MPU,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "dsp",
-	},
+struct omap_device_pm_latency omap_keyboard_latency[] = {
 	{
-		.start		= INT_24XX_MAIL_U3_MPU,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "iva",
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
 };
-static int omap2_mbox_resources_sz = ARRAY_SIZE(omap2_mbox_resources);
-#else
-#define omap2_mbox_resources		NULL
-#define omap2_mbox_resources_sz		0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct resource omap3_mbox_resources[] = {
-	{
-		.start		= OMAP34XX_MAILBOX_BASE,
-		.end		= OMAP34XX_MAILBOX_BASE + MBOX_REG_SIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= INT_24XX_MAIL_U0_MPU,
-		.flags		= IORESOURCE_IRQ,
-		.name		= "dsp",
-	},
-};
-static int omap3_mbox_resources_sz = ARRAY_SIZE(omap3_mbox_resources);
-#else
-#define omap3_mbox_resources		NULL
-#define omap3_mbox_resources_sz		0
-#endif
+int __init omap4_keyboard_init(struct omap4_keypad_platform_data
+						*sdp4430_keypad_data)
+{
+	struct omap_device *od;
+	struct omap_hwmod *oh;
+	struct omap4_keypad_platform_data *keypad_data;
+	unsigned int id = -1;
+	char *oh_name = "kbd";
+	char *name = "omap4-keypad";
 
-#ifdef CONFIG_ARCH_OMAP4
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return -ENODEV;
+	}
 
-#define OMAP4_MBOX_REG_SIZE	0x130
-static struct resource omap4_mbox_resources[] = {
-	{
-		.start          = OMAP44XX_MAILBOX_BASE,
-		.end            = OMAP44XX_MAILBOX_BASE +
-					OMAP4_MBOX_REG_SIZE - 1,
-		.flags          = IORESOURCE_MEM,
-	},
-	{
-		.start          = OMAP44XX_IRQ_MAIL_U0,
-		.flags          = IORESOURCE_IRQ,
-		.name		= "mbox",
-	},
-};
-static int omap4_mbox_resources_sz = ARRAY_SIZE(omap4_mbox_resources);
-#else
-#define omap4_mbox_resources		NULL
-#define omap4_mbox_resources_sz		0
-#endif
+	keypad_data = sdp4430_keypad_data;
 
-static struct platform_device mbox_device = {
-	.name		= "omap-mailbox",
-	.id		= -1,
+	od = omap_device_build(name, id, oh, keypad_data,
+			sizeof(struct omap4_keypad_platform_data),
+			omap_keyboard_latency,
+			ARRAY_SIZE(omap_keyboard_latency), 0);
+
+	if (IS_ERR(od)) {
+		WARN(1, "Can't build omap_device for %s:%s.\n",
+						name, oh->name);
+		return PTR_ERR(od);
+	}
+
+	return 0;
+}
+
+#if defined(CONFIG_OMAP_MBOX_FWK) || defined(CONFIG_OMAP_MBOX_FWK_MODULE)
+static struct omap_device_pm_latency mbox_latencies[] = {
+	[0] = {
+		.activate_func = omap_device_enable_hwmods,
+		.deactivate_func = omap_device_idle_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
 };
 
 static inline void omap_init_mbox(void)
 {
-	if (cpu_is_omap24xx()) {
-		mbox_device.resource = omap2_mbox_resources;
-		mbox_device.num_resources = omap2_mbox_resources_sz;
-	} else if (cpu_is_omap34xx()) {
-		mbox_device.resource = omap3_mbox_resources;
-		mbox_device.num_resources = omap3_mbox_resources_sz;
-	} else if (cpu_is_omap44xx()) {
-		mbox_device.resource = omap4_mbox_resources;
-		mbox_device.num_resources = omap4_mbox_resources_sz;
-	} else {
-		pr_err("%s: platform not supported\n", __func__);
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+
+	oh = omap_hwmod_lookup("mailbox");
+	if (!oh) {
+		pr_err("%s: unable to find hwmod\n", __func__);
 		return;
 	}
-	platform_device_register(&mbox_device);
+
+	od = omap_device_build("omap-mailbox", -1, oh, NULL, 0,
+				mbox_latencies, ARRAY_SIZE(mbox_latencies), 0);
+	WARN(IS_ERR(od), "%s: could not build device, err %ld\n",
+						__func__, PTR_ERR(od));
 }
 #else
 static inline void omap_init_mbox(void) { }
@@ -279,163 +333,55 @@
 
 #include <plat/mcspi.h>
 
-#define OMAP2_MCSPI1_BASE		0x48098000
-#define OMAP2_MCSPI2_BASE		0x4809a000
-#define OMAP2_MCSPI3_BASE		0x480b8000
-#define OMAP2_MCSPI4_BASE		0x480ba000
-
-#define OMAP4_MCSPI1_BASE		0x48098100
-#define OMAP4_MCSPI2_BASE		0x4809a100
-#define OMAP4_MCSPI3_BASE		0x480b8100
-#define OMAP4_MCSPI4_BASE		0x480ba100
-
-static struct omap2_mcspi_platform_config omap2_mcspi1_config = {
-	.num_cs		= 4,
-};
-
-static struct resource omap2_mcspi1_resources[] = {
-	{
-		.start		= OMAP2_MCSPI1_BASE,
-		.end		= OMAP2_MCSPI1_BASE + 0xff,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi1 = {
-	.name		= "omap2_mcspi",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi1_resources),
-	.resource	= omap2_mcspi1_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi1_config,
-	},
-};
-
-static struct omap2_mcspi_platform_config omap2_mcspi2_config = {
-	.num_cs		= 2,
-};
-
-static struct resource omap2_mcspi2_resources[] = {
-	{
-		.start		= OMAP2_MCSPI2_BASE,
-		.end		= OMAP2_MCSPI2_BASE + 0xff,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi2 = {
-	.name		= "omap2_mcspi",
-	.id		= 2,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi2_resources),
-	.resource	= omap2_mcspi2_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi2_config,
-	},
-};
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-	defined(CONFIG_ARCH_OMAP4)
-static struct omap2_mcspi_platform_config omap2_mcspi3_config = {
-	.num_cs		= 2,
-};
-
-static struct resource omap2_mcspi3_resources[] = {
-	{
-	.start		= OMAP2_MCSPI3_BASE,
-	.end		= OMAP2_MCSPI3_BASE + 0xff,
-	.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi3 = {
-	.name		= "omap2_mcspi",
-	.id		= 3,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi3_resources),
-	.resource	= omap2_mcspi3_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi3_config,
-	},
-};
-#endif
-
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static struct omap2_mcspi_platform_config omap2_mcspi4_config = {
-	.num_cs		= 1,
-};
-
-static struct resource omap2_mcspi4_resources[] = {
-	{
-		.start		= OMAP2_MCSPI4_BASE,
-		.end		= OMAP2_MCSPI4_BASE + 0xff,
-		.flags		= IORESOURCE_MEM,
-	},
-};
-
-static struct platform_device omap2_mcspi4 = {
-	.name		= "omap2_mcspi",
-	.id		= 4,
-	.num_resources	= ARRAY_SIZE(omap2_mcspi4_resources),
-	.resource	= omap2_mcspi4_resources,
-	.dev		= {
-		.platform_data = &omap2_mcspi4_config,
+struct omap_device_pm_latency omap_mcspi_latency[] = {
+	[0] = {
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
 };
-#endif
 
-#ifdef CONFIG_ARCH_OMAP4
-static inline void omap4_mcspi_fixup(void)
-{
-	omap2_mcspi1_resources[0].start	= OMAP4_MCSPI1_BASE;
-	omap2_mcspi1_resources[0].end	= OMAP4_MCSPI1_BASE + 0xff;
-	omap2_mcspi2_resources[0].start	= OMAP4_MCSPI2_BASE;
-	omap2_mcspi2_resources[0].end	= OMAP4_MCSPI2_BASE + 0xff;
-	omap2_mcspi3_resources[0].start	= OMAP4_MCSPI3_BASE;
-	omap2_mcspi3_resources[0].end	= OMAP4_MCSPI3_BASE + 0xff;
-	omap2_mcspi4_resources[0].start	= OMAP4_MCSPI4_BASE;
-	omap2_mcspi4_resources[0].end	= OMAP4_MCSPI4_BASE + 0xff;
-}
-#else
-static inline void omap4_mcspi_fixup(void)
+static int omap_mcspi_init(struct omap_hwmod *oh, void *unused)
 {
-}
-#endif
+	struct omap_device *od;
+	char *name = "omap2_mcspi";
+	struct omap2_mcspi_platform_config *pdata;
+	static int spi_num;
+	struct omap2_mcspi_dev_attr *mcspi_attrib = oh->dev_attr;
 
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) || \
-	defined(CONFIG_ARCH_OMAP4)
-static inline void omap2_mcspi3_init(void)
-{
-	platform_device_register(&omap2_mcspi3);
-}
-#else
-static inline void omap2_mcspi3_init(void)
-{
-}
-#endif
+	pdata = kzalloc(sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("Memory allocation for McSPI device failed\n");
+		return -ENOMEM;
+	}
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static inline void omap2_mcspi4_init(void)
-{
-	platform_device_register(&omap2_mcspi4);
-}
-#else
-static inline void omap2_mcspi4_init(void)
-{
+	pdata->num_cs = mcspi_attrib->num_chipselect;
+	switch (oh->class->rev) {
+	case OMAP2_MCSPI_REV:
+	case OMAP3_MCSPI_REV:
+			pdata->regs_offset = 0;
+			break;
+	case OMAP4_MCSPI_REV:
+			pdata->regs_offset = OMAP4_MCSPI_REG_OFFSET;
+			break;
+	default:
+			pr_err("Invalid McSPI Revision value\n");
+			return -EINVAL;
+	}
+
+	spi_num++;
+	od = omap_device_build(name, spi_num, oh, pdata,
+				sizeof(*pdata),	omap_mcspi_latency,
+				ARRAY_SIZE(omap_mcspi_latency), 0);
+	WARN(IS_ERR(od), "Can't build omap_device for %s:%s\n",
+				name, oh->name);
+	kfree(pdata);
+	return 0;
 }
-#endif
 
 static void omap_init_mcspi(void)
 {
-	if (cpu_is_omap44xx())
-		omap4_mcspi_fixup();
-
-	platform_device_register(&omap2_mcspi1);
-	platform_device_register(&omap2_mcspi2);
-
-	if (cpu_is_omap2430() || cpu_is_omap343x() || cpu_is_omap44xx())
-		omap2_mcspi3_init();
-
-	if (cpu_is_omap343x() || cpu_is_omap44xx())
-		omap2_mcspi4_init();
+	omap_hwmod_for_each_by_class("mcspi", omap_mcspi_init, NULL);
 }
 
 #else
@@ -610,117 +556,10 @@
 
 /*-------------------------------------------------------------------------*/
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-
-#define MMCHS_SYSCONFIG			0x0010
-#define MMCHS_SYSCONFIG_SWRESET		(1 << 1)
-#define MMCHS_SYSSTATUS			0x0014
-#define MMCHS_SYSSTATUS_RESETDONE	(1 << 0)
-
-static struct platform_device dummy_pdev = {
-	.dev = {
-		.bus = &platform_bus_type,
-	},
-};
-
-/**
- * omap_hsmmc_reset() - Full reset of each HS-MMC controller
- *
- * Ensure that each MMC controller is fully reset.  Controllers
- * left in an unknown state (by bootloader) may prevent retention
- * or OFF-mode.  This is especially important in cases where the
- * MMC driver is not enabled, _or_ built as a module.
- *
- * In order for reset to work, interface, functional and debounce
- * clocks must be enabled.  The debounce clock comes from func_32k_clk
- * and is not under SW control, so we only enable i- and f-clocks.
- **/
-static void __init omap_hsmmc_reset(void)
-{
-	u32 i, nr_controllers;
-	struct clk *iclk, *fclk;
-
-	if (cpu_is_omap242x())
-		return;
-
-	nr_controllers = cpu_is_omap44xx() ? OMAP44XX_NR_MMC :
-		(cpu_is_omap34xx() ? OMAP34XX_NR_MMC : OMAP24XX_NR_MMC);
-
-	for (i = 0; i < nr_controllers; i++) {
-		u32 v, base = 0;
-		struct device *dev = &dummy_pdev.dev;
-
-		switch (i) {
-		case 0:
-			base = OMAP2_MMC1_BASE;
-			break;
-		case 1:
-			base = OMAP2_MMC2_BASE;
-			break;
-		case 2:
-			base = OMAP3_MMC3_BASE;
-			break;
-		case 3:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC4_BASE;
-			break;
-		case 4:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC5_BASE;
-			break;
-		}
-
-		if (cpu_is_omap44xx())
-			base += OMAP4_MMC_REG_OFFSET;
-
-		dummy_pdev.id = i;
-		dev_set_name(&dummy_pdev.dev, "mmci-omap-hs.%d", i);
-		iclk = clk_get(dev, "ick");
-		if (IS_ERR(iclk))
-			goto err1;
-		if (clk_enable(iclk))
-			goto err2;
-
-		fclk = clk_get(dev, "fck");
-		if (IS_ERR(fclk))
-			goto err3;
-		if (clk_enable(fclk))
-			goto err4;
-
-		omap_writel(MMCHS_SYSCONFIG_SWRESET, base + MMCHS_SYSCONFIG);
-		v = omap_readl(base + MMCHS_SYSSTATUS);
-		while (!(omap_readl(base + MMCHS_SYSSTATUS) &
-			 MMCHS_SYSSTATUS_RESETDONE))
-			cpu_relax();
-
-		clk_disable(fclk);
-		clk_put(fclk);
-		clk_disable(iclk);
-		clk_put(iclk);
-	}
-	return;
-
-err4:
-	clk_put(fclk);
-err3:
-	clk_disable(iclk);
-err2:
-	clk_put(iclk);
-err1:
-	printk(KERN_WARNING "%s: Unable to enable clocks for MMC%d, "
-			    "cannot reset.\n",  __func__, i);
-}
-#else
-static inline void omap_hsmmc_reset(void) {}
-#endif
-
-#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE) || \
-	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
+#if defined(CONFIG_MMC_OMAP) || defined(CONFIG_MMC_OMAP_MODULE)
 
-static inline void omap2_mmc_mux(struct omap_mmc_platform_data *mmc_controller,
-			int controller_nr)
+static inline void omap242x_mmc_mux(struct omap_mmc_platform_data
+							*mmc_controller)
 {
 	if ((mmc_controller->slots[0].switch_pin > 0) && \
 		(mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
@@ -731,163 +570,44 @@
 		omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
 					OMAP_PIN_INPUT_PULLUP);
 
-	if (cpu_is_omap2420() && controller_nr == 0) {
-		omap_mux_init_signal("sdmmc_cmd", 0);
-		omap_mux_init_signal("sdmmc_clki", 0);
-		omap_mux_init_signal("sdmmc_clko", 0);
-		omap_mux_init_signal("sdmmc_dat0", 0);
-		omap_mux_init_signal("sdmmc_dat_dir0", 0);
-		omap_mux_init_signal("sdmmc_cmd_dir", 0);
-		if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
-			omap_mux_init_signal("sdmmc_dat1", 0);
-			omap_mux_init_signal("sdmmc_dat2", 0);
-			omap_mux_init_signal("sdmmc_dat3", 0);
-			omap_mux_init_signal("sdmmc_dat_dir1", 0);
-			omap_mux_init_signal("sdmmc_dat_dir2", 0);
-			omap_mux_init_signal("sdmmc_dat_dir3", 0);
-		}
-
-		/*
-		 * Use internal loop-back in MMC/SDIO Module Input Clock
-		 * selection
-		 */
-		if (mmc_controller->slots[0].internal_clock) {
-			u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
-			v |= (1 << 24);
-			omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
-		}
+	omap_mux_init_signal("sdmmc_cmd", 0);
+	omap_mux_init_signal("sdmmc_clki", 0);
+	omap_mux_init_signal("sdmmc_clko", 0);
+	omap_mux_init_signal("sdmmc_dat0", 0);
+	omap_mux_init_signal("sdmmc_dat_dir0", 0);
+	omap_mux_init_signal("sdmmc_cmd_dir", 0);
+	if (mmc_controller->slots[0].caps & MMC_CAP_4_BIT_DATA) {
+		omap_mux_init_signal("sdmmc_dat1", 0);
+		omap_mux_init_signal("sdmmc_dat2", 0);
+		omap_mux_init_signal("sdmmc_dat3", 0);
+		omap_mux_init_signal("sdmmc_dat_dir1", 0);
+		omap_mux_init_signal("sdmmc_dat_dir2", 0);
+		omap_mux_init_signal("sdmmc_dat_dir3", 0);
 	}
 
-	if (cpu_is_omap34xx()) {
-		if (controller_nr == 0) {
-			omap_mux_init_signal("sdmmc1_clk",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc1_cmd",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc1_dat0",
-				OMAP_PIN_INPUT_PULLUP);
-			if (mmc_controller->slots[0].caps &
-				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
-				omap_mux_init_signal("sdmmc1_dat1",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat2",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat3",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-			if (mmc_controller->slots[0].caps &
-						MMC_CAP_8_BIT_DATA) {
-				omap_mux_init_signal("sdmmc1_dat4",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat5",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat6",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc1_dat7",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-		}
-		if (controller_nr == 1) {
-			/* MMC2 */
-			omap_mux_init_signal("sdmmc2_clk",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc2_cmd",
-				OMAP_PIN_INPUT_PULLUP);
-			omap_mux_init_signal("sdmmc2_dat0",
-				OMAP_PIN_INPUT_PULLUP);
-
-			/*
-			 * For 8 wire configurations, Lines DAT4, 5, 6 and 7 need to be muxed
-			 * in the board-*.c files
-			 */
-			if (mmc_controller->slots[0].caps &
-				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
-				omap_mux_init_signal("sdmmc2_dat1",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat2",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat3",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-			if (mmc_controller->slots[0].caps &
-							MMC_CAP_8_BIT_DATA) {
-				omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6",
-					OMAP_PIN_INPUT_PULLUP);
-				omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7",
-					OMAP_PIN_INPUT_PULLUP);
-			}
-		}
-
-		/*
-		 * For MMC3 the pins need to be muxed in the board-*.c files
-		 */
+	/*
+	 * Use internal loop-back in MMC/SDIO Module Input Clock
+	 * selection
+	 */
+	if (mmc_controller->slots[0].internal_clock) {
+		u32 v = omap_ctrl_readl(OMAP2_CONTROL_DEVCONF0);
+		v |= (1 << 24);
+		omap_ctrl_writel(v, OMAP2_CONTROL_DEVCONF0);
 	}
 }
 
-void __init omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
-			int nr_controllers)
+void __init omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
 {
-	int i;
-	char *name;
-
-	for (i = 0; i < nr_controllers; i++) {
-		unsigned long base, size;
-		unsigned int irq = 0;
-
-		if (!mmc_data[i])
-			continue;
-
-		omap2_mmc_mux(mmc_data[i], i);
+	char *name = "mmci-omap";
 
-		switch (i) {
-		case 0:
-			base = OMAP2_MMC1_BASE;
-			irq = INT_24XX_MMC_IRQ;
-			break;
-		case 1:
-			base = OMAP2_MMC2_BASE;
-			irq = INT_24XX_MMC2_IRQ;
-			break;
-		case 2:
-			if (!cpu_is_omap44xx() && !cpu_is_omap34xx())
-				return;
-			base = OMAP3_MMC3_BASE;
-			irq = INT_34XX_MMC3_IRQ;
-			break;
-		case 3:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC4_BASE;
-			irq = OMAP44XX_IRQ_MMC4;
-			break;
-		case 4:
-			if (!cpu_is_omap44xx())
-				return;
-			base = OMAP4_MMC5_BASE;
-			irq = OMAP44XX_IRQ_MMC5;
-			break;
-		default:
-			continue;
-		}
+	if (!mmc_data[0]) {
+		pr_err("%s fails: Incomplete platform data\n", __func__);
+		return;
+	}
 
-		if (cpu_is_omap2420()) {
-			size = OMAP2420_MMC_SIZE;
-			name = "mmci-omap";
-		} else if (cpu_is_omap44xx()) {
-			if (i < 3)
-				irq += OMAP44XX_IRQ_GIC_START;
-			size = OMAP4_HSMMC_SIZE;
-			name = "mmci-omap-hs";
-		} else {
-			size = OMAP3_HSMMC_SIZE;
-			name = "mmci-omap-hs";
-		}
-		omap_mmc_add(name, i, base, size, irq, mmc_data[i]);
-	};
+	omap242x_mmc_mux(mmc_data[0]);
+	omap_mmc_add(name, 0, OMAP2_MMC1_BASE, OMAP2420_MMC_SIZE,
+					INT_24XX_MMC_IRQ, mmc_data[0]);
 }
 
 #endif
@@ -895,7 +615,7 @@
 /*-------------------------------------------------------------------------*/
 
 #if defined(CONFIG_HDQ_MASTER_OMAP) || defined(CONFIG_HDQ_MASTER_OMAP_MODULE)
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3430)
+#if defined(CONFIG_SOC_OMAP2430) || defined(CONFIG_SOC_OMAP3430)
 #define OMAP_HDQ_BASE	0x480B2000
 #endif
 static struct resource omap_hdq_resources[] = {
@@ -961,7 +681,6 @@
 	 * please keep these calls, and their implementations above,
 	 * in alphabetical order so they're easier to sort through.
 	 */
-	omap_hsmmc_reset();
 	omap_init_audio();
 	omap_init_camera();
 	omap_init_mbox();
@@ -1006,7 +725,7 @@
 	od = omap_device_build(dev_name, id, oh, NULL, 0,
 				omap_wdt_latency,
 				ARRAY_SIZE(omap_wdt_latency), 0);
-	WARN(IS_ERR(od), "Cant build omap_device for %s:%s.\n",
+	WARN(IS_ERR(od), "Can't build omap_device for %s:%s.\n",
 				dev_name, oh->name);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/devices.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/devices.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/devices.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/devices.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,19 @@
+/*
+ * arch/arm/mach-omap2/devices.h
+ *
+ * OMAP2 platform device setup/initialization
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_MACH_OMAP_DEVICES_H
+#define __ARCH_ARM_MACH_OMAP_DEVICES_H
+
+struct isp_platform_data;
+
+int omap3_init_camera(struct isp_platform_data *pdata);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/display.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/display.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/display.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/display.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,125 @@
+/*
+ * OMAP2plus display device setup / initialization.
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Senthilvadivu Guruswamy
+ *	Sumit Semwal
+ *
+ * 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 "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/platform_device.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+
+#include <plat/display.h>
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+
+static struct platform_device omap_display_device = {
+	.name          = "omapdss",
+	.id            = -1,
+	.dev            = {
+		.platform_data = NULL,
+	},
+};
+
+static struct omap_device_pm_latency omap_dss_latency[] = {
+	[0] = {
+		.deactivate_func        = omap_device_idle_hwmods,
+		.activate_func          = omap_device_enable_hwmods,
+		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+};
+
+/* oh_core is used for getting opt-clocks */
+static struct omap_hwmod	*oh_core;
+
+static bool opt_clock_available(const char *clk_role)
+{
+	int i;
+
+	for (i = 0; i < oh_core->opt_clks_cnt; i++) {
+		if (!strcmp(oh_core->opt_clks[i].role, clk_role))
+			return true;
+	}
+	return false;
+}
+
+int __init omap_display_init(struct omap_dss_board_info *board_data)
+{
+	int r = 0;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	int i;
+	struct omap_display_platform_data pdata;
+
+	/*
+	 * omap: valid DSS hwmod names
+	 * omap2,3,4: dss_core, dss_dispc, dss_rfbi, dss_venc
+	 * omap3,4: dss_dsi1
+	 * omap4: dss_dsi2, dss_hdmi
+	 */
+	char *oh_name[] = { "dss_core", "dss_dispc", "dss_rfbi", "dss_venc",
+		"dss_dsi1", "dss_dsi2", "dss_hdmi" };
+	char *dev_name[] = { "omapdss_dss", "omapdss_dispc", "omapdss_rfbi",
+		"omapdss_venc", "omapdss_dsi1", "omapdss_dsi2",
+		"omapdss_hdmi" };
+	int oh_count;
+
+	memset(&pdata, 0, sizeof(pdata));
+
+	if (cpu_is_omap24xx())
+		oh_count = ARRAY_SIZE(oh_name) - 3;
+		/* last 3 hwmod dev in oh_name are not available for omap2 */
+	else if (cpu_is_omap44xx())
+		oh_count = ARRAY_SIZE(oh_name);
+	else
+		oh_count = ARRAY_SIZE(oh_name) - 2;
+		/* last 2 hwmod dev in oh_name are not available for omap3 */
+
+	/* opt_clks are always associated with dss hwmod */
+	oh_core = omap_hwmod_lookup("dss_core");
+	if (!oh_core) {
+		pr_err("Could not look up dss_core.\n");
+		return -ENODEV;
+	}
+
+	pdata.board_data = board_data;
+	pdata.board_data->get_last_off_on_transaction_id = NULL;
+	pdata.opt_clock_available = opt_clock_available;
+
+	for (i = 0; i < oh_count; i++) {
+		oh = omap_hwmod_lookup(oh_name[i]);
+		if (!oh) {
+			pr_err("Could not look up %s\n", oh_name[i]);
+			return -ENODEV;
+		}
+
+		od = omap_device_build(dev_name[i], -1, oh, &pdata,
+				sizeof(struct omap_display_platform_data),
+				omap_dss_latency,
+				ARRAY_SIZE(omap_dss_latency), 0);
+
+		if (WARN((IS_ERR(od)), "Could not build omap_device for %s\n",
+				oh_name[i]))
+			return -ENODEV;
+	}
+	omap_display_device.dev.platform_data = board_data;
+
+	r = platform_device_register(&omap_display_device);
+	if (r < 0)
+		printk(KERN_ERR "Unable to register OMAP-Display device\n");
+
+	return r;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/dma.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -262,7 +262,7 @@
 			omap2_dma_latency, ARRAY_SIZE(omap2_dma_latency), 0);
 	kfree(p);
 	if (IS_ERR(od)) {
-		pr_err("%s: Cant build omap_device for %s:%s.\n",
+		pr_err("%s: Can't build omap_device for %s:%s.\n",
 			__func__, name, oh->name);
 		return PTR_ERR(od);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/dpll44xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/dpll44xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/dpll44xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/dpll44xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * OMAP4-specific DPLL control functions
+ *
+ * Copyright (C) 2011 Texas Instruments, Inc.
+ * Rajendra Nayak
+ *
+ * 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/errno.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+
+#include <plat/cpu.h>
+#include <plat/clock.h>
+
+#include "clock.h"
+#include "cm-regbits-44xx.h"
+
+/* Supported only on OMAP4 */
+int omap4_dpllmx_gatectrl_read(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return -EINVAL;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	v &= mask;
+	v >>= __ffs(mask);
+
+	return v;
+}
+
+void omap4_dpllmx_allow_gatectrl(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	/* Clear the bit to allow gatectrl */
+	v &= ~mask;
+	__raw_writel(v, clk->clksel_reg);
+}
+
+void omap4_dpllmx_deny_gatectrl(struct clk *clk)
+{
+	u32 v;
+	u32 mask;
+
+	if (!clk || !clk->clksel_reg || !cpu_is_omap44xx())
+		return;
+
+	mask = clk->flags & CLOCK_CLKOUTX2 ?
+			OMAP4430_DPLL_CLKOUTX2_GATE_CTRL_MASK :
+			OMAP4430_DPLL_CLKOUT_GATE_CTRL_MASK;
+
+	v = __raw_readl(clk->clksel_reg);
+	/* Set the bit to deny gatectrl */
+	v |= mask;
+	__raw_writel(v, clk->clksel_reg);
+}
+
+const struct clkops clkops_omap4_dpllmx_ops = {
+	.allow_idle	= omap4_dpllmx_allow_gatectrl,
+	.deny_idle	= omap4_dpllmx_deny_gatectrl,
+};
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 	kfree(pdata);
 
 	if (IS_ERR(od)) {
-		WARN(1, "Cant build omap_device for %s:%s.\n",
+		WARN(1, "Can't build omap_device for %s:%s.\n",
 					name, oh->name);
 		return PTR_ERR(od);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpmc.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpmc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
  */
 #undef DEBUG
 
+#include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -22,6 +23,7 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/module.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach-types.h>
 #include <plat/gpmc.h>
@@ -58,7 +60,6 @@
 #define GPMC_CHUNK_SHIFT	24		/* 16 MB */
 #define GPMC_SECTION_SHIFT	28		/* 128 MB */
 
-#define PREFETCH_FIFOTHRESHOLD	(0x40 << 8)
 #define CS_NUM_SHIFT		24
 #define ENABLE_PREFETCH		(0x1 << 7)
 #define DMA_MPU_MODE		2
@@ -100,6 +101,8 @@
 
 static struct clk *gpmc_l3_clk;
 
+static irqreturn_t gpmc_handle_irq(int irq, void *dev);
+
 static void gpmc_write_reg(int idx, u32 val)
 {
 	__raw_writel(val, gpmc_base + idx);
@@ -497,6 +500,10 @@
 	u32 regval = 0;
 
 	switch (cmd) {
+	case GPMC_ENABLE_IRQ:
+		gpmc_write_reg(GPMC_IRQENABLE, wval);
+		break;
+
 	case GPMC_SET_IRQ_STATUS:
 		gpmc_write_reg(GPMC_IRQSTATUS, wval);
 		break;
@@ -598,15 +605,19 @@
 /**
  * gpmc_prefetch_enable - configures and starts prefetch transfer
  * @cs: cs (chip select) number
+ * @fifo_th: fifo threshold to be used for read/ write
  * @dma_mode: dma mode enable (1) or disable (0)
  * @u32_count: number of bytes to be transferred
  * @is_write: prefetch read(0) or write post(1) mode
  */
-int gpmc_prefetch_enable(int cs, int dma_mode,
+int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 				unsigned int u32_count, int is_write)
 {
 
-	if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
+	if (fifo_th > PREFETCH_FIFOTHRESHOLD_MAX) {
+		pr_err("gpmc: fifo threshold is not supported\n");
+		return -1;
+	} else if (!(gpmc_read_reg(GPMC_PREFETCH_CONTROL))) {
 		/* Set the amount of bytes to be prefetched */
 		gpmc_write_reg(GPMC_PREFETCH_CONFIG2, u32_count);
 
@@ -614,7 +625,7 @@
 		 * enable the engine. Set which cs is has requested for.
 		 */
 		gpmc_write_reg(GPMC_PREFETCH_CONFIG1, ((cs << CS_NUM_SHIFT) |
-					PREFETCH_FIFOTHRESHOLD |
+					PREFETCH_FIFOTHRESHOLD(fifo_th) |
 					ENABLE_PREFETCH |
 					(dma_mode << DMA_MPU_MODE) |
 					(0x1 & is_write)));
@@ -678,9 +689,11 @@
 	}
 }
 
-void __init gpmc_init(void)
+static int __init gpmc_init(void)
 {
-	u32 l;
+	u32 l, irq;
+	int cs, ret = -EINVAL;
+	int gpmc_irq;
 	char *ck = NULL;
 
 	if (cpu_is_omap24xx()) {
@@ -689,16 +702,19 @@
 			l = OMAP2420_GPMC_BASE;
 		else
 			l = OMAP34XX_GPMC_BASE;
+		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap34xx()) {
 		ck = "gpmc_fck";
 		l = OMAP34XX_GPMC_BASE;
+		gpmc_irq = INT_34XX_GPMC_IRQ;
 	} else if (cpu_is_omap44xx()) {
 		ck = "gpmc_ck";
 		l = OMAP44XX_GPMC_BASE;
+		gpmc_irq = OMAP44XX_IRQ_GPMC;
 	}
 
 	if (WARN_ON(!ck))
-		return;
+		return ret;
 
 	gpmc_l3_clk = clk_get(NULL, ck);
 	if (IS_ERR(gpmc_l3_clk)) {
@@ -723,6 +739,35 @@
 	l |= (0x02 << 3) | (1 << 0);
 	gpmc_write_reg(GPMC_SYSCONFIG, l);
 	gpmc_mem_init();
+
+	/* initalize the irq_chained */
+	irq = OMAP_GPMC_IRQ_BASE;
+	for (cs = 0; cs < GPMC_CS_NUM; cs++) {
+		irq_set_chip_and_handler(irq, &dummy_irq_chip,
+						handle_simple_irq);
+		set_irq_flags(irq, IRQF_VALID);
+		irq++;
+	}
+
+	ret = request_irq(gpmc_irq,
+			gpmc_handle_irq, IRQF_SHARED, "gpmc", gpmc_base);
+	if (ret)
+		pr_err("gpmc: irq-%d could not claim: err %d\n",
+						gpmc_irq, ret);
+	return ret;
+}
+postcore_initcall(gpmc_init);
+
+static irqreturn_t gpmc_handle_irq(int irq, void *dev)
+{
+	u8 cs;
+
+	/* check cs to invoke the irq */
+	cs = ((gpmc_read_reg(GPMC_PREFETCH_CONFIG1)) >> CS_NUM_SHIFT) & 0x7;
+	if (OMAP_GPMC_IRQ_BASE+cs <= OMAP_GPMC_IRQ_END)
+		generic_handle_irq(OMAP_GPMC_IRQ_BASE+cs);
+
+	return IRQ_HANDLED;
 }
 
 #ifdef CONFIG_ARCH_OMAP3
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpmc-nand.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpmc-nand.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpmc-nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpmc-nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/mtd/nand.h>
 
 #include <asm/mach/flash.h>
 
@@ -69,8 +70,10 @@
 	t.wr_cycle  = gpmc_round_ns_to_ticks(gpmc_nand_data->gpmc_t->wr_cycle);
 
 	/* Configure GPMC */
-	gpmc_cs_configure(gpmc_nand_data->cs,
-				GPMC_CONFIG_DEV_SIZE, gpmc_nand_data->devsize);
+	if (gpmc_nand_data->devsize == NAND_BUSWIDTH_16)
+		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 1);
+	else
+		gpmc_cs_configure(gpmc_nand_data->cs, GPMC_CONFIG_DEV_SIZE, 0);
 	gpmc_cs_configure(gpmc_nand_data->cs,
 			GPMC_CONFIG_DEV_TYPE, GPMC_DEVICETYPE_NAND);
 	err = gpmc_cs_set_timings(gpmc_nand_data->cs, &t);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpmc-onenand.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpmc-onenand.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/gpmc-onenand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/gpmc-onenand.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,7 @@
 }
 
 static void set_onenand_cfg(void __iomem *onenand_base, int latency,
-				int sync_read, int sync_write, int hf)
+				int sync_read, int sync_write, int hf, int vhf)
 {
 	u32 reg;
 
@@ -114,12 +114,57 @@
 		reg |= ONENAND_SYS_CFG1_HF;
 	else
 		reg &= ~ONENAND_SYS_CFG1_HF;
+	if (vhf)
+		reg |= ONENAND_SYS_CFG1_VHF;
+	else
+		reg &= ~ONENAND_SYS_CFG1_VHF;
 	writew(reg, onenand_base + ONENAND_REG_SYS_CFG1);
 }
 
+static int omap2_onenand_get_freq(struct omap_onenand_platform_data *cfg,
+				  void __iomem *onenand_base, bool *clk_dep)
+{
+	u16 ver = readw(onenand_base + ONENAND_REG_VERSION_ID);
+	int freq = 0;
+
+	if (cfg->get_freq) {
+		struct onenand_freq_info fi;
+
+		fi.maf_id = readw(onenand_base + ONENAND_REG_MANUFACTURER_ID);
+		fi.dev_id = readw(onenand_base + ONENAND_REG_DEVICE_ID);
+		fi.ver_id = ver;
+		freq = cfg->get_freq(&fi, clk_dep);
+		if (freq)
+			return freq;
+	}
+
+	switch ((ver >> 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;
+	}
+
+	return freq;
+}
+
 static int omap2_onenand_set_sync_mode(struct omap_onenand_platform_data *cfg,
 					void __iomem *onenand_base,
-					int freq)
+					int *freq_ptr)
 {
 	struct gpmc_timings t;
 	const int t_cer  = 15;
@@ -130,10 +175,11 @@
 	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 first_time = 0, hf = 0, vhf = 0, sync_read = 0, sync_write = 0;
 	int err, ticks_cez;
-	int cs = cfg->cs;
+	int cs = cfg->cs, freq = *freq_ptr;
 	u32 reg;
+	bool clk_dep = false;
 
 	if (cfg->flags & ONENAND_SYNC_READ) {
 		sync_read = 1;
@@ -148,27 +194,7 @@
 		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;
-		}
+		freq = omap2_onenand_get_freq(cfg, onenand_base, &clk_dep);
 		first_time = 1;
 	}
 
@@ -180,7 +206,7 @@
 		t_avdh  = 2;
 		t_ach   = 3;
 		t_aavdh = 6;
-		t_rdyo  = 9;
+		t_rdyo  = 6;
 		break;
 	case 83:
 		min_gpmc_clk_period = 12000; /* 83 MHz */
@@ -217,16 +243,36 @@
 	gpmc_clk_ns = gpmc_ticks_to_ns(div);
 	if (gpmc_clk_ns < 15) /* >66Mhz */
 		hf = 1;
-	if (hf)
+	if (gpmc_clk_ns < 12) /* >83Mhz */
+		vhf = 1;
+	if (vhf)
+		latency = 8;
+	else if (hf)
 		latency = 6;
 	else if (gpmc_clk_ns >= 25) /* 40 MHz*/
 		latency = 3;
 	else
 		latency = 4;
 
+	if (clk_dep) {
+		if (gpmc_clk_ns < 12) { /* >83Mhz */
+			t_ces   = 3;
+			t_avds  = 4;
+		} else if (gpmc_clk_ns < 15) { /* >66Mhz */
+			t_ces   = 5;
+			t_avds  = 4;
+		} else if (gpmc_clk_ns < 25) { /* >40Mhz */
+			t_ces   = 6;
+			t_avds  = 5;
+		} else {
+			t_ces   = 7;
+			t_avds  = 7;
+		}
+	}
+
 	if (first_time)
 		set_onenand_cfg(onenand_base, latency,
-					sync_read, sync_write, hf);
+					sync_read, sync_write, hf, vhf);
 
 	if (div == 1) {
 		reg = gpmc_cs_read_reg(cs, GPMC_CS_CONFIG2);
@@ -264,6 +310,9 @@
 	/* 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));
+	/* Force at least 1 clk between AVD High to OE Low */
+	if (t.oe_on <= t.adv_rd_off)
+		t.oe_on = t.adv_rd_off + gpmc_round_ns_to_ticks(1);
 	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;
@@ -317,18 +366,20 @@
 	if (err)
 		return err;
 
-	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf);
+	set_onenand_cfg(onenand_base, latency, sync_read, sync_write, hf, vhf);
+
+	*freq_ptr = freq;
 
 	return 0;
 }
 
-static int gpmc_onenand_setup(void __iomem *onenand_base, int freq)
+static int gpmc_onenand_setup(void __iomem *onenand_base, int *freq_ptr)
 {
 	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) {
+			freq_ptr) < 0) {
 		dev_err(dev, "Unable to set synchronous mode\n");
 		return -EINVAL;
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/hsmmc.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/hsmmc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/hsmmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/hsmmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,7 +16,10 @@
 #include <mach/hardware.h>
 #include <plat/mmc.h>
 #include <plat/omap-pm.h>
+#include <plat/mux.h>
+#include <plat/omap_device.h>
 
+#include "mux.h"
 #include "hsmmc.h"
 #include "control.h"
 
@@ -28,10 +31,6 @@
 
 #define HSMMC_NAME_LEN	9
 
-static struct hsmmc_controller {
-	char				name[HSMMC_NAME_LEN + 1];
-} hsmmc[OMAP34XX_NR_MMC];
-
 #if defined(CONFIG_ARCH_OMAP3) && defined(CONFIG_PM)
 
 static int hsmmc_get_context_loss(struct device *dev)
@@ -204,174 +203,312 @@
 	return 0;
 }
 
-static struct omap_mmc_platform_data *hsmmc_data[OMAP34XX_NR_MMC] __initdata;
-
-void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+static inline void omap_hsmmc_mux(struct omap_mmc_platform_data *mmc_controller,
+			int controller_nr)
 {
-	struct omap2_hsmmc_info *c;
-	int nr_hsmmc = ARRAY_SIZE(hsmmc_data);
-	int i;
-	u32 reg;
+	if ((mmc_controller->slots[0].switch_pin > 0) && \
+		(mmc_controller->slots[0].switch_pin < OMAP_MAX_GPIO_LINES))
+		omap_mux_init_gpio(mmc_controller->slots[0].switch_pin,
+					OMAP_PIN_INPUT_PULLUP);
+	if ((mmc_controller->slots[0].gpio_wp > 0) && \
+		(mmc_controller->slots[0].gpio_wp < OMAP_MAX_GPIO_LINES))
+		omap_mux_init_gpio(mmc_controller->slots[0].gpio_wp,
+					OMAP_PIN_INPUT_PULLUP);
+	if (cpu_is_omap34xx()) {
+		if (controller_nr == 0) {
+			omap_mux_init_signal("sdmmc1_clk",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc1_cmd",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc1_dat0",
+				OMAP_PIN_INPUT_PULLUP);
+			if (mmc_controller->slots[0].caps &
+				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
+				omap_mux_init_signal("sdmmc1_dat1",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat2",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat3",
+					OMAP_PIN_INPUT_PULLUP);
+			}
+			if (mmc_controller->slots[0].caps &
+						MMC_CAP_8_BIT_DATA) {
+				omap_mux_init_signal("sdmmc1_dat4",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat5",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat6",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc1_dat7",
+					OMAP_PIN_INPUT_PULLUP);
+			}
+		}
+		if (controller_nr == 1) {
+			/* MMC2 */
+			omap_mux_init_signal("sdmmc2_clk",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc2_cmd",
+				OMAP_PIN_INPUT_PULLUP);
+			omap_mux_init_signal("sdmmc2_dat0",
+				OMAP_PIN_INPUT_PULLUP);
 
-	if (!cpu_is_omap44xx()) {
-		if (cpu_is_omap2430()) {
-			control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
-			control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
-		} else {
-			control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
-			control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
+			/*
+			 * For 8 wire configurations, Lines DAT4, 5, 6 and 7
+			 * need to be muxed in the board-*.c files
+			 */
+			if (mmc_controller->slots[0].caps &
+				(MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA)) {
+				omap_mux_init_signal("sdmmc2_dat1",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat2",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat3",
+					OMAP_PIN_INPUT_PULLUP);
+			}
+			if (mmc_controller->slots[0].caps &
+							MMC_CAP_8_BIT_DATA) {
+				omap_mux_init_signal("sdmmc2_dat4.sdmmc2_dat4",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat5.sdmmc2_dat5",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat6.sdmmc2_dat6",
+					OMAP_PIN_INPUT_PULLUP);
+				omap_mux_init_signal("sdmmc2_dat7.sdmmc2_dat7",
+					OMAP_PIN_INPUT_PULLUP);
+			}
 		}
-	} else {
-		control_pbias_offset =
-			OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
-		control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
-		reg = omap4_ctrl_pad_readl(control_mmc1);
-		reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
-			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
-		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
-			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
-		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
-			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
-			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
-		omap4_ctrl_pad_writel(reg, control_mmc1);
-	}
 
-	for (c = controllers; c->mmc; c++) {
-		struct hsmmc_controller *hc = hsmmc + c->mmc - 1;
-		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
+		/*
+		 * For MMC3 the pins need to be muxed in the board-*.c files
+		 */
+	}
+}
 
-		if (!c->mmc || c->mmc > nr_hsmmc) {
-			pr_debug("MMC%d: no such controller\n", c->mmc);
-			continue;
-		}
-		if (mmc) {
-			pr_debug("MMC%d: already configured\n", c->mmc);
-			continue;
-		}
+static int __init omap_hsmmc_pdata_init(struct omap2_hsmmc_info *c,
+					struct omap_mmc_platform_data *mmc)
+{
+	char *hc_name;
 
-		mmc = kzalloc(sizeof(struct omap_mmc_platform_data),
-			      GFP_KERNEL);
-		if (!mmc) {
-			pr_err("Cannot allocate memory for mmc device!\n");
-			goto done;
-		}
+	hc_name = kzalloc(sizeof(char) * (HSMMC_NAME_LEN + 1), GFP_KERNEL);
+	if (!hc_name) {
+		pr_err("Cannot allocate memory for controller slot name\n");
+		kfree(hc_name);
+		return -ENOMEM;
+	}
 
-		if (c->name)
-			strncpy(hc->name, c->name, HSMMC_NAME_LEN);
-		else
-			snprintf(hc->name, ARRAY_SIZE(hc->name),
-				"mmc%islot%i", c->mmc, 1);
-		mmc->slots[0].name = hc->name;
-		mmc->nr_slots = 1;
-		mmc->slots[0].caps = c->caps;
-		mmc->slots[0].internal_clock = !c->ext_clock;
-		mmc->dma_mask = 0xffffffff;
-		if (cpu_is_omap44xx())
-			mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
-		else
-			mmc->reg_offset = 0;
+	if (c->name)
+		strncpy(hc_name, c->name, HSMMC_NAME_LEN);
+	else
+		snprintf(hc_name, (HSMMC_NAME_LEN + 1), "mmc%islot%i",
+								c->mmc, 1);
+	mmc->slots[0].name = hc_name;
+	mmc->nr_slots = 1;
+	mmc->slots[0].caps = c->caps;
+	mmc->slots[0].internal_clock = !c->ext_clock;
+	mmc->dma_mask = 0xffffffff;
+	if (cpu_is_omap44xx())
+		mmc->reg_offset = OMAP4_MMC_REG_OFFSET;
+	else
+		mmc->reg_offset = 0;
 
-		mmc->get_context_loss_count = hsmmc_get_context_loss;
+	mmc->get_context_loss_count = hsmmc_get_context_loss;
 
-		mmc->slots[0].switch_pin = c->gpio_cd;
-		mmc->slots[0].gpio_wp = c->gpio_wp;
+	mmc->slots[0].switch_pin = c->gpio_cd;
+	mmc->slots[0].gpio_wp = c->gpio_wp;
 
-		mmc->slots[0].remux = c->remux;
-		mmc->slots[0].init_card = c->init_card;
+	mmc->slots[0].remux = c->remux;
+	mmc->slots[0].init_card = c->init_card;
 
-		if (c->cover_only)
-			mmc->slots[0].cover = 1;
+	if (c->cover_only)
+		mmc->slots[0].cover = 1;
 
-		if (c->nonremovable)
-			mmc->slots[0].nonremovable = 1;
+	if (c->nonremovable)
+		mmc->slots[0].nonremovable = 1;
 
-		if (c->power_saving)
-			mmc->slots[0].power_saving = 1;
+	if (c->power_saving)
+		mmc->slots[0].power_saving = 1;
 
-		if (c->no_off)
-			mmc->slots[0].no_off = 1;
+	if (c->no_off)
+		mmc->slots[0].no_off = 1;
 
-		if (c->vcc_aux_disable_is_sleep)
-			mmc->slots[0].vcc_aux_disable_is_sleep = 1;
+	if (c->vcc_aux_disable_is_sleep)
+		mmc->slots[0].vcc_aux_disable_is_sleep = 1;
 
-		/* 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;
+	/*
+	 * 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;
 
-		if (cpu_is_omap3517() || cpu_is_omap3505())
-			mmc->slots[0].set_power = nop_mmc_set_power;
-		else
-			mmc->slots[0].features |= HSMMC_HAS_PBIAS;
+	if (cpu_is_omap3517() || cpu_is_omap3505())
+		mmc->slots[0].set_power = nop_mmc_set_power;
+	else
+		mmc->slots[0].features |= HSMMC_HAS_PBIAS;
 
-		if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
-			mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
+	if (cpu_is_omap44xx() && (omap_rev() > OMAP4430_REV_ES1_0))
+		mmc->slots[0].features |= HSMMC_HAS_UPDATED_RESET;
 
-		switch (c->mmc) {
-		case 1:
-			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
-				/* on-chip level shifting via PBIAS0/PBIAS1 */
-				if (cpu_is_omap44xx()) {
-					mmc->slots[0].before_set_reg =
+	switch (c->mmc) {
+	case 1:
+		if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
+			/* on-chip level shifting via PBIAS0/PBIAS1 */
+			if (cpu_is_omap44xx()) {
+				mmc->slots[0].before_set_reg =
 						omap4_hsmmc1_before_set_reg;
-					mmc->slots[0].after_set_reg =
+				mmc->slots[0].after_set_reg =
 						omap4_hsmmc1_after_set_reg;
-				} else {
-					mmc->slots[0].before_set_reg =
+			} else {
+				mmc->slots[0].before_set_reg =
 						omap_hsmmc1_before_set_reg;
-					mmc->slots[0].after_set_reg =
+				mmc->slots[0].after_set_reg =
 						omap_hsmmc1_after_set_reg;
-				}
 			}
+		}
 
-			/* Omap3630 HSMMC1 supports only 4-bit */
-			if (cpu_is_omap3630() &&
-					(c->caps & MMC_CAP_8_BIT_DATA)) {
-				c->caps &= ~MMC_CAP_8_BIT_DATA;
-				c->caps |= MMC_CAP_4_BIT_DATA;
-				mmc->slots[0].caps = c->caps;
-			}
-			break;
-		case 2:
-			if (c->ext_clock)
-				c->transceiver = 1;
-			if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
-				c->caps &= ~MMC_CAP_8_BIT_DATA;
-				c->caps |= MMC_CAP_4_BIT_DATA;
-			}
-			/* FALLTHROUGH */
-		case 3:
-			if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
-				/* off-chip level shifting, or none */
-				mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
-				mmc->slots[0].after_set_reg = NULL;
-			}
-			break;
-		default:
-			pr_err("MMC%d configuration not supported!\n", c->mmc);
-			kfree(mmc);
-			continue;
+		/* OMAP3630 HSMMC1 supports only 4-bit */
+		if (cpu_is_omap3630() &&
+				(c->caps & MMC_CAP_8_BIT_DATA)) {
+			c->caps &= ~MMC_CAP_8_BIT_DATA;
+			c->caps |= MMC_CAP_4_BIT_DATA;
+			mmc->slots[0].caps = c->caps;
 		}
-		hsmmc_data[c->mmc - 1] = mmc;
+		break;
+	case 2:
+		if (c->ext_clock)
+			c->transceiver = 1;
+		if (c->transceiver && (c->caps & MMC_CAP_8_BIT_DATA)) {
+			c->caps &= ~MMC_CAP_8_BIT_DATA;
+			c->caps |= MMC_CAP_4_BIT_DATA;
+		}
+		/* FALLTHROUGH */
+	case 3:
+		if (mmc->slots[0].features & HSMMC_HAS_PBIAS) {
+			/* off-chip level shifting, or none */
+			mmc->slots[0].before_set_reg = hsmmc23_before_set_reg;
+			mmc->slots[0].after_set_reg = NULL;
+		}
+		break;
+	case 4:
+	case 5:
+		mmc->slots[0].before_set_reg = NULL;
+		mmc->slots[0].after_set_reg = NULL;
+		break;
+	default:
+		pr_err("MMC%d configuration not supported!\n", c->mmc);
+		kfree(hc_name);
+		return -ENODEV;
 	}
+	return 0;
+}
 
-	omap2_init_mmc(hsmmc_data, OMAP34XX_NR_MMC);
+static struct omap_device_pm_latency omap_hsmmc_latency[] = {
+	[0] = {
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func	 = omap_device_enable_hwmods,
+		.flags		 = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	},
+	/*
+	 * XXX There should also be an entry here to power off/on the
+	 * MMC regulators/PBIAS cells, etc.
+	 */
+};
 
-	/* pass the device nodes back to board setup code */
-	for (c = controllers; c->mmc; c++) {
-		struct omap_mmc_platform_data *mmc = hsmmc_data[c->mmc - 1];
+#define MAX_OMAP_MMC_HWMOD_NAME_LEN		16
 
-		if (!c->mmc || c->mmc > nr_hsmmc)
-			continue;
-		c->dev = mmc->dev;
+void __init omap_init_hsmmc(struct omap2_hsmmc_info *hsmmcinfo, int ctrl_nr)
+{
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	struct omap_device_pm_latency *ohl;
+	char oh_name[MAX_OMAP_MMC_HWMOD_NAME_LEN];
+	struct omap_mmc_platform_data *mmc_data;
+	struct omap_mmc_dev_attr *mmc_dev_attr;
+	char *name;
+	int l;
+	int ohl_cnt = 0;
+
+	mmc_data = kzalloc(sizeof(struct omap_mmc_platform_data), GFP_KERNEL);
+	if (!mmc_data) {
+		pr_err("Cannot allocate memory for mmc device!\n");
+		goto done;
+	}
+
+	if (omap_hsmmc_pdata_init(hsmmcinfo, mmc_data) < 0) {
+		pr_err("%s fails!\n", __func__);
+		goto done;
+	}
+	omap_hsmmc_mux(mmc_data, (ctrl_nr - 1));
+
+	name = "omap_hsmmc";
+	ohl = omap_hsmmc_latency;
+	ohl_cnt = ARRAY_SIZE(omap_hsmmc_latency);
+
+	l = snprintf(oh_name, MAX_OMAP_MMC_HWMOD_NAME_LEN,
+		     "mmc%d", ctrl_nr);
+	WARN(l >= MAX_OMAP_MMC_HWMOD_NAME_LEN,
+	     "String buffer overflow in MMC%d device setup\n", ctrl_nr);
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		kfree(mmc_data->slots[0].name);
+		goto done;
 	}
 
+	if (oh->dev_attr != NULL) {
+		mmc_dev_attr = oh->dev_attr;
+		mmc_data->controller_flags = mmc_dev_attr->flags;
+	}
+
+	od = omap_device_build(name, ctrl_nr - 1, oh, mmc_data,
+		sizeof(struct omap_mmc_platform_data), ohl, ohl_cnt, false);
+	if (IS_ERR(od)) {
+		WARN(1, "Can't build omap_device for %s:%s.\n", name, oh->name);
+		kfree(mmc_data->slots[0].name);
+		goto done;
+	}
+	/*
+	 * return device handle to board setup code
+	 * required to populate for regulator framework structure
+	 */
+	hsmmcinfo->dev = &od->pdev.dev;
+
 done:
-	for (i = 0; i < nr_hsmmc; i++)
-		kfree(hsmmc_data[i]);
+	kfree(mmc_data);
+}
+
+void __init omap2_hsmmc_init(struct omap2_hsmmc_info *controllers)
+{
+	u32 reg;
+
+	if (!cpu_is_omap44xx()) {
+		if (cpu_is_omap2430()) {
+			control_pbias_offset = OMAP243X_CONTROL_PBIAS_LITE;
+			control_devconf1_offset = OMAP243X_CONTROL_DEVCONF1;
+		} else {
+			control_pbias_offset = OMAP343X_CONTROL_PBIAS_LITE;
+			control_devconf1_offset = OMAP343X_CONTROL_DEVCONF1;
+		}
+	} else {
+		control_pbias_offset =
+			OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_PBIASLITE;
+		control_mmc1 = OMAP4_CTRL_MODULE_PAD_CORE_CONTROL_MMC1;
+		reg = omap4_ctrl_pad_readl(control_mmc1);
+		reg |= (OMAP4_SDMMC1_PUSTRENGTH_GRP0_MASK |
+			OMAP4_SDMMC1_PUSTRENGTH_GRP1_MASK);
+		reg &= ~(OMAP4_SDMMC1_PUSTRENGTH_GRP2_MASK |
+			OMAP4_SDMMC1_PUSTRENGTH_GRP3_MASK);
+		reg |= (OMAP4_USBC1_DR0_SPEEDCTRL_MASK|
+			OMAP4_SDMMC1_DR1_SPEEDCTRL_MASK |
+			OMAP4_SDMMC1_DR2_SPEEDCTRL_MASK);
+		omap4_ctrl_pad_writel(reg, control_mmc1);
+	}
+
+	for (; controllers->mmc; controllers++)
+		omap_init_hsmmc(controllers, controllers->mmc);
+
 }
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/hwspinlock.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/hwspinlock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/hwspinlock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/hwspinlock.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * OMAP hardware spinlock device initialization
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Simon Que <sque@ti.com>
+ *          Hari Kanigeri <h-kanigeri2@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; 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/err.h>
+
+#include <plat/omap_hwmod.h>
+#include <plat/omap_device.h>
+
+struct omap_device_pm_latency omap_spinlock_latency[] = {
+	{
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
+	}
+};
+
+int __init hwspinlocks_init(void)
+{
+	int retval = 0;
+	struct omap_hwmod *oh;
+	struct omap_device *od;
+	const char *oh_name = "spinlock";
+	const char *dev_name = "omap_hwspinlock";
+
+	/*
+	 * Hwmod lookup will fail in case our platform doesn't support the
+	 * hardware spinlock module, so it is safe to run this initcall
+	 * on all omaps
+	 */
+	oh = omap_hwmod_lookup(oh_name);
+	if (oh == NULL)
+		return -EINVAL;
+
+	od = omap_device_build(dev_name, 0, oh, NULL, 0,
+				omap_spinlock_latency,
+				ARRAY_SIZE(omap_spinlock_latency), false);
+	if (IS_ERR(od)) {
+		pr_err("Can't build omap_device for %s:%s\n", dev_name,
+								oh_name);
+		retval = PTR_ERR(od);
+	}
+
+	return retval;
+}
+/* early board code might need to reserve specific hwspinlock instances */
+postcore_initcall(hwspinlocks_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/id.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/id.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/id.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/id.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  * Copyright (C) 2005 Nokia Corporation
  * Written by Tony Lindgren <tony@atomide.com>
  *
- * Copyright (C) 2009 Texas Instruments
+ * Copyright (C) 2009-11 Texas Instruments
  * Added OMAP4 support - Santosh Shilimkar <santosh.shilimkar@ti.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -84,6 +84,11 @@
 #define OMAP_TAP_DIE_ID_2	0x0220
 #define OMAP_TAP_DIE_ID_3	0x0224
 
+#define OMAP_TAP_DIE_ID_44XX_0	0x0200
+#define OMAP_TAP_DIE_ID_44XX_1	0x0208
+#define OMAP_TAP_DIE_ID_44XX_2	0x020c
+#define OMAP_TAP_DIE_ID_44XX_3	0x0210
+
 #define read_tap_reg(reg)	__raw_readl(tap_base  + (reg))
 
 struct omap_id {
@@ -107,6 +112,14 @@
 
 void omap_get_die_id(struct omap_die_id *odi)
 {
+	if (cpu_is_omap44xx()) {
+		odi->id_0 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_0);
+		odi->id_1 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_1);
+		odi->id_2 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_2);
+		odi->id_3 = read_tap_reg(OMAP_TAP_DIE_ID_44XX_3);
+
+		return;
+	}
 	odi->id_0 = read_tap_reg(OMAP_TAP_DIE_ID_0);
 	odi->id_1 = read_tap_reg(OMAP_TAP_DIE_ID_1);
 	odi->id_2 = read_tap_reg(OMAP_TAP_DIE_ID_2);
@@ -191,12 +204,19 @@
 	if (!cpu_is_omap3505() && !cpu_is_omap3517())
 		omap3_features |= OMAP3_HAS_IO_WAKEUP;
 
+	omap3_features |= OMAP3_HAS_SDRC;
+
 	/*
 	 * TODO: Get additional info (where applicable)
 	 *       e.g. Size of L2 cache.
 	 */
 }
 
+static void __init ti816x_check_features(void)
+{
+	omap3_features = OMAP3_HAS_NEON;
+}
+
 static void __init omap3_check_revision(void)
 {
 	u32 cpuid, idcode;
@@ -287,6 +307,20 @@
 			omap_chip.oc |= CHIP_IS_OMAP3630ES1_2;
 		}
 		break;
+	case 0xb81e:
+		omap_chip.oc = CHIP_IS_TI816X;
+
+		switch (rev) {
+		case 0:
+			omap_revision = TI8168_REV_ES1_0;
+			break;
+		case 1:
+			omap_revision = TI8168_REV_ES1_1;
+			break;
+		default:
+			omap_revision =  TI8168_REV_ES1_1;
+		}
+		break;
 	default:
 		/* Unknown default to latest silicon rev as default*/
 		omap_revision =  OMAP3630_REV_ES1_2;
@@ -307,7 +341,7 @@
 	 */
 	idcode = read_tap_reg(OMAP_TAP_IDCODE);
 	hawkeye = (idcode >> 12) & 0xffff;
-	rev = (idcode >> 28) & 0xff;
+	rev = (idcode >> 28) & 0xf;
 
 	/*
 	 * Few initial ES2.0 samples IDCODE is same as ES1.0
@@ -326,22 +360,31 @@
 			omap_chip.oc |= CHIP_IS_OMAP4430ES1;
 			break;
 		case 1:
+		default:
 			omap_revision = OMAP4430_REV_ES2_0;
 			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+		}
+		break;
+	case 0xb95c:
+		switch (rev) {
+		case 3:
+			omap_revision = OMAP4430_REV_ES2_1;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES2_1;
 			break;
+		case 4:
 		default:
-			omap_revision = OMAP4430_REV_ES2_0;
-			omap_chip.oc |= CHIP_IS_OMAP4430ES2;
-	}
-	break;
+			omap_revision = OMAP4430_REV_ES2_2;
+			omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
+		}
+		break;
 	default:
-		/* Unknown default to latest silicon rev as default*/
-		omap_revision = OMAP4430_REV_ES2_0;
-		omap_chip.oc |= CHIP_IS_OMAP4430ES2;
+		/* Unknown default to latest silicon rev as default */
+		omap_revision = OMAP4430_REV_ES2_2;
+		omap_chip.oc |= CHIP_IS_OMAP4430ES2_2;
 	}
 
-	pr_info("OMAP%04x ES%d.0\n",
-			omap_rev() >> 16, ((omap_rev() >> 12) & 0xf) + 1);
+	pr_info("OMAP%04x ES%d.%d\n", omap_rev() >> 16,
+		((omap_rev() >> 12) & 0xf), ((omap_rev() >> 8) & 0xf));
 }
 
 #define OMAP3_SHOW_FEATURE(feat)		\
@@ -372,6 +415,8 @@
 			/* Already set in omap3_check_revision() */
 			strcpy(cpu_name, "AM3505");
 		}
+	} else if (cpu_is_ti816x()) {
+		strcpy(cpu_name, "TI816X");
 	} else if (omap3_has_iva() && omap3_has_sgx()) {
 		/* OMAP3430, OMAP3525, OMAP3515, OMAP3503 devices */
 		strcpy(cpu_name, "OMAP3430/3530");
@@ -386,7 +431,7 @@
 		strcpy(cpu_name, "OMAP3503");
 	}
 
-	if (cpu_is_omap3630()) {
+	if (cpu_is_omap3630() || cpu_is_ti816x()) {
 		switch (rev) {
 		case OMAP_REVBITS_00:
 			strcpy(cpu_rev, "1.0");
@@ -462,7 +507,13 @@
 		omap24xx_check_revision();
 	} else if (cpu_is_omap34xx()) {
 		omap3_check_revision();
-		omap3_check_features();
+
+		/* TI816X doesn't have feature register */
+		if (!cpu_is_ti816x())
+			omap3_check_features();
+		else
+			ti816x_check_features();
+
 		omap3_cpuinfo();
 		return;
 	} else if (cpu_is_omap44xx()) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/include/mach/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,9 @@
 
 #define UART_OFFSET(addr)	((addr) & 0x00ffffff)
 
+#define omap_uart_v2p(x)	((x) - PAGE_OFFSET + PLAT_PHYS_OFFSET)
+#define omap_uart_p2v(x)	((x) - PLAT_PHYS_OFFSET + PAGE_OFFSET)
+
 		.pushsection .data
 omap_uart_phys:	.word	0
 omap_uart_virt:	.word	0
@@ -36,7 +39,7 @@
 		/* Use omap_uart_phys/virt if already configured */
 10:		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
-		ldreq	\rp, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rp, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rp, =omap_uart_phys	@ MMU enabled
 		add	\rv, \rp, #4		@ omap_uart_virt
 		ldr	\rp, [\rp, #0]
@@ -49,7 +52,7 @@
 		mrc	p15, 0, \rp, c1, c0
 		tst	\rp, #1			@ MMU enabled?
 		ldreq	\rp, =OMAP_UART_INFO	@ MMU not enabled
-		ldrne	\rp, =__phys_to_virt(OMAP_UART_INFO)	@ MMU enabled
+		ldrne	\rp, =omap_uart_p2v(OMAP_UART_INFO)	@ MMU enabled
 		ldr	\rp, [\rp, #0]
 
 		/* Select the UART to use based on the UART1 scratchpad value */
@@ -69,6 +72,12 @@
 		beq	34f			@ configure OMAP3UART4
 		cmp	\rp, #OMAP4UART4	@ only on 44xx
 		beq	44f			@ configure OMAP4UART4
+		cmp	\rp, #TI816XUART1	@ ti816x UART offsets different
+		beq	81f			@ configure UART1
+		cmp	\rp, #TI816XUART2	@ ti816x UART offsets different
+		beq	82f			@ configure UART2
+		cmp	\rp, #TI816XUART3	@ ti816x UART offsets different
+		beq	83f			@ configure UART3
 		cmp	\rp, #ZOOM_UART		@ only on zoom2/3
 		beq	95f			@ configure ZOOM_UART
 
@@ -91,10 +100,16 @@
 		b	98f
 44:		mov	\rp, #UART_OFFSET(OMAP4_UART4_BASE)
 		b	98f
+81:		mov	\rp, #UART_OFFSET(TI816X_UART1_BASE)
+		b	98f
+82:		mov	\rp, #UART_OFFSET(TI816X_UART2_BASE)
+		b	98f
+83:		mov	\rp, #UART_OFFSET(TI816X_UART3_BASE)
+		b	98f
 95:		ldr	\rp, =ZOOM_UART_BASE
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		ldr	\rp, =ZOOM_UART_VIRT
@@ -109,7 +124,7 @@
 98:		add	\rp, \rp, #0x48000000	@ phys base
 		mrc	p15, 0, \rv, c1, c0
 		tst	\rv, #1			@ MMU enabled?
-		ldreq	\rv, =__virt_to_phys(omap_uart_phys)	@ MMU not enabled
+		ldreq	\rv, =omap_uart_v2p(omap_uart_phys)	@ MMU disabled
 		ldrne	\rv, =omap_uart_phys	@ MMU enabled
 		str	\rp, [\rv, #0]
 		sub	\rp, \rp, #0x48000000	@ phys base
@@ -131,7 +146,7 @@
 		.macro	busyuart,rd,rx
 1001:		mrc	p15, 0, \rd, c1, c0
 		tst	\rd, #1			@ MMU enabled?
-		ldreq	\rd, =__virt_to_phys(omap_uart_lsr)	@ MMU not enabled
+		ldreq	\rd, =omap_uart_v2p(omap_uart_lsr)	@ MMU disabled
 		ldrne	\rd, =omap_uart_lsr	@ MMU enabled
 		ldr	\rd, [\rd, #0]
 		ldrb	\rd, [\rx, \rd]
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/include/mach/entry-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,14 @@
 		bne	9998f
 		ldr	\irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
 		cmp	\irqnr, #0x0
+		bne	9998f
+
+		/*
+		 * ti816x has additional IRQ pending register. Checking this
+		 * register on omap2 & omap3 has no effect (read as 0).
+		 */
+		ldr	\irqnr, [\base, #0xf8] /* IRQ pending reg 4 */
+		cmp	\irqnr, #0x0
 9998:
 		ldrne	\irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
 		and	\irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
@@ -133,6 +141,11 @@
 		bne	9999f
 		ldr	\irqnr, [\base, #0xd8] /* IRQ pending reg 3 */
 		cmp	\irqnr, #0x0
+#ifdef CONFIG_SOC_OMAPTI816X
+		bne	9999f
+		ldr	\irqnr, [\base, #0xf8] /* IRQ pending reg 4 */
+		cmp	\irqnr, #0x0
+#endif
 9999:
 		ldrne	\irqnr, [\base, #INTCPS_SIR_IRQ_OFFSET]
 		and	\irqnr, \irqnr, #ACTIVEIRQ_MASK /* Clear spurious bits */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/include/mach/omap4-common.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/include/mach/omap4-common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/include/mach/omap4-common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/include/mach/omap4-common.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,8 +17,12 @@
  * wfi used in low power code. Directly opcode is used instead
  * of instruction to avoid mulit-omap build break
  */
+#ifdef CONFIG_THUMB2_KERNEL
+#define do_wfi() __asm__ __volatile__ ("wfi" : : : "memory")
+#else
 #define do_wfi()			\
 		__asm__ __volatile__ (".word	0xe320f003" : : : "memory")
+#endif
 
 #ifdef CONFIG_CACHE_L2X0
 extern void __iomem *l2cache_base;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/io.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/io.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/io.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,6 @@
 
 #include <plat/sram.h>
 #include <plat/sdrc.h>
-#include <plat/gpmc.h>
 #include <plat/serial.h>
 
 #include "clock2xxx.h"
@@ -66,7 +65,7 @@
 	},
 };
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 static struct map_desc omap242x_io_desc[] __initdata = {
 	{
 		.virtual	= DSP_MEM_2420_VIRT,
@@ -90,7 +89,7 @@
 
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 static struct map_desc omap243x_io_desc[] __initdata = {
 	{
 		.virtual	= L4_WK_243X_VIRT,
@@ -175,6 +174,18 @@
 #endif
 };
 #endif
+
+#ifdef CONFIG_SOC_OMAPTI816X
+static struct map_desc omapti816x_io_desc[] __initdata = {
+	{
+		.virtual	= L4_34XX_VIRT,
+		.pfn		= __phys_to_pfn(L4_34XX_PHYS),
+		.length		= L4_34XX_SIZE,
+		.type		= MT_DEVICE
+	},
+};
+#endif
+
 #ifdef	CONFIG_ARCH_OMAP4
 static struct map_desc omap44xx_io_desc[] __initdata = {
 	{
@@ -241,7 +252,7 @@
 	omap_sram_init();
 }
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 void __init omap242x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
@@ -250,7 +261,7 @@
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 void __init omap243x_map_common_io(void)
 {
 	iotable_init(omap24xx_io_desc, ARRAY_SIZE(omap24xx_io_desc));
@@ -267,6 +278,14 @@
 }
 #endif
 
+#ifdef CONFIG_SOC_OMAPTI816X
+void __init omapti816x_map_common_io(void)
+{
+	iotable_init(omapti816x_io_desc, ARRAY_SIZE(omapti816x_io_desc));
+	_omap2_map_common_io();
+}
+#endif
+
 #ifdef CONFIG_ARCH_OMAP4
 void __init omap44xx_map_common_io(void)
 {
@@ -337,15 +356,15 @@
 
 	if (cpu_is_omap242x()) {
 		omap2xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap2xxx_clockdomains_init();
 		omap2420_hwmod_init();
 	} else if (cpu_is_omap243x()) {
 		omap2xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap2xxx_clockdomains_init();
 		omap2430_hwmod_init();
 	} else if (cpu_is_omap34xx()) {
 		omap3xxx_powerdomains_init();
-		omap2_clockdomains_init();
+		omap3xxx_clockdomains_init();
 		omap3xxx_hwmod_init();
 	} else if (cpu_is_omap44xx()) {
 		omap44xx_powerdomains_init();
@@ -398,15 +417,10 @@
 void __init omap2_init_common_devices(struct omap_sdrc_params *sdrc_cs0,
 				      struct omap_sdrc_params *sdrc_cs1)
 {
-	omap_serial_early_init();
-
-	omap_hwmod_late_init();
-
-	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+	if (cpu_is_omap24xx() || omap3_has_sdrc()) {
 		omap2_sdrc_init(sdrc_cs0, sdrc_cs1);
 		_omap2_init_reprogram_sdrc();
 	}
-	gpmc_init();
 
 	omap_irq_base_init();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/iommu2.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/iommu2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/iommu2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/iommu2.c	2011-05-19 00:06:34.000000000 -0400
@@ -145,35 +145,32 @@
 
 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",
-	};
+	u32 errs = 0;
 
 	stat = iommu_read_reg(obj, MMU_IRQSTATUS);
 	stat &= MMU_IRQ_MASK;
-	if (!stat)
+	if (!stat) {
+		*ra = 0;
 		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");
-
+	if (stat & MMU_IRQ_TLBMISS)
+		errs |= OMAP_IOMMU_ERR_TLB_MISS;
+	if (stat & MMU_IRQ_TRANSLATIONFAULT)
+		errs |= OMAP_IOMMU_ERR_TRANS_FAULT;
+	if (stat & MMU_IRQ_EMUMISS)
+		errs |= OMAP_IOMMU_ERR_EMU_MISS;
+	if (stat & MMU_IRQ_TABLEWALKFAULT)
+		errs |= OMAP_IOMMU_ERR_TBLWALK_FAULT;
+	if (stat & MMU_IRQ_MULTIHITFAULT)
+		errs |= OMAP_IOMMU_ERR_MULTIHIT_FAULT;
 	iommu_write_reg(obj, stat, MMU_IRQSTATUS);
 
-	return stat;
+	return errs;
 }
 
 static void omap2_tlb_read_cr(struct iommu *obj, struct cr_regs *cr)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,8 +61,6 @@
 	u32 mir[INTCPS_NR_MIR_REGS];
 };
 
-static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
-
 /* INTC bank register get/set */
 
 static void intc_bank_write_reg(u32 val, struct omap_irq_bank *bank, u16 reg)
@@ -110,7 +108,7 @@
 	unsigned int irq = d->irq;
 	int offset = irq & (~(IRQ_BITS_PER_REG - 1));
 
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
 		int spurious = 0;
 
 		/*
@@ -205,6 +203,9 @@
 
 		BUG_ON(!base);
 
+		if (cpu_is_ti816x())
+			bank->nr_irqs = 128;
+
 		/* Static mapping, never released */
 		bank->base_reg = ioremap(base, SZ_4K);
 		if (!bank->base_reg) {
@@ -222,13 +223,14 @@
 	       nr_of_irqs, nr_banks, nr_banks > 1 ? "s" : "");
 
 	for (i = 0; i < nr_of_irqs; i++) {
-		set_irq_chip(i, &omap_irq_chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &omap_irq_chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 }
 
 #ifdef CONFIG_ARCH_OMAP3
+static struct omap3_intc_regs intc_context[ARRAY_SIZE(irq_banks)];
+
 void omap_intc_save_context(void)
 {
 	int ind = 0, i = 0;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-omap2/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,9 @@
 	depends on ARCH_OMAP2PLUS
 	select CPU_V7
 	select ARM_GIC
+	select LOCAL_TIMERS if SMP
 	select PL310_ERRATA_588369
+	select PL310_ERRATA_727915
 	select ARM_ERRATA_720789
 	select ARCH_HAS_OPP
 	select PM_OPP if PM
@@ -53,25 +55,30 @@
 comment "OMAP Core Type"
 	depends on ARCH_OMAP2
 
-config ARCH_OMAP2420
+config SOC_OMAP2420
 	bool "OMAP2420 support"
 	depends on ARCH_OMAP2
 	default y
 	select OMAP_DM_TIMER
 	select ARCH_OMAP_OTG
 
-config ARCH_OMAP2430
+config SOC_OMAP2430
 	bool "OMAP2430 support"
 	depends on ARCH_OMAP2
 	default y
 	select ARCH_OMAP_OTG
 
-config ARCH_OMAP3430
+config SOC_OMAP3430
 	bool "OMAP3430 support"
 	depends on ARCH_OMAP3
 	default y
 	select ARCH_OMAP_OTG
 
+config SOC_OMAPTI816X
+	bool "TI816X support"
+	depends on ARCH_OMAP3
+	default y
+
 config OMAP_PACKAGE_ZAF
        bool
 
@@ -106,25 +113,25 @@
 
 config MACH_OMAP2_TUSB6010
 	bool
-	depends on ARCH_OMAP2 && ARCH_OMAP2420
+	depends on ARCH_OMAP2 && SOC_OMAP2420
 	default y if MACH_NOKIA_N8X0
 
 config MACH_OMAP_H4
 	bool "OMAP 2420 H4 board"
-	depends on ARCH_OMAP2420
+	depends on SOC_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAF
 	select OMAP_DEBUG_DEVICES
 
 config MACH_OMAP_APOLLON
 	bool "OMAP 2420 Apollon board"
-	depends on ARCH_OMAP2420
+	depends on SOC_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAC
 
 config MACH_OMAP_2430SDP
 	bool "OMAP 2430 SDP board"
-	depends on ARCH_OMAP2430
+	depends on SOC_OMAP2430
 	default y
 	select OMAP_PACKAGE_ZAC
 
@@ -219,7 +226,7 @@
 
 config MACH_NOKIA_N8X0
 	bool "Nokia N800/N810"
-	depends on ARCH_OMAP2420
+	depends on SOC_OMAP2420
 	default y
 	select OMAP_PACKAGE_ZAC
 	select MACH_NOKIA_N800
@@ -294,12 +301,18 @@
 	default y
 	select OMAP_PACKAGE_CBP
 
+config MACH_TI8168EVM
+	bool "TI8168 Evaluation Module"
+	depends on SOC_OMAPTI816X
+	default y
+
 config MACH_OMAP_4430SDP
 	bool "OMAP 4430 SDP board"
 	default y
 	depends on ARCH_OMAP4
 	select OMAP_PACKAGE_CBL
 	select OMAP_PACKAGE_CBS
+	select REGULATOR_FIXED_VOLTAGE
 
 config MACH_OMAP4_PANDA
 	bool "OMAP4 Panda Board"
@@ -307,6 +320,7 @@
 	depends on ARCH_OMAP4
 	select OMAP_PACKAGE_CBL
 	select OMAP_PACKAGE_CBS
+	select REGULATOR_FIXED_VOLTAGE
 
 config OMAP3_EMU
 	bool "OMAP3 debugging peripherals"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mailbox.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mailbox.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mailbox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mailbox.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,12 +14,11 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/pm_runtime.h>
 #include <plat/mailbox.h>
 #include <mach/irqs.h>
 
 #define MAILBOX_REVISION		0x000
-#define MAILBOX_SYSCONFIG		0x010
-#define MAILBOX_SYSSTATUS		0x014
 #define MAILBOX_MESSAGE(m)		(0x040 + 4 * (m))
 #define MAILBOX_FIFOSTATUS(m)		(0x080 + 4 * (m))
 #define MAILBOX_MSGSTATUS(m)		(0x0c0 + 4 * (m))
@@ -33,17 +32,6 @@
 #define MAILBOX_IRQ_NEWMSG(m)		(1 << (2 * (m)))
 #define MAILBOX_IRQ_NOTFULL(m)		(1 << (2 * (m) + 1))
 
-/* SYSCONFIG: register bit definition */
-#define AUTOIDLE	(1 << 0)
-#define SOFTRESET	(1 << 1)
-#define SMARTIDLE	(2 << 3)
-#define OMAP4_SOFTRESET	(1 << 0)
-#define OMAP4_NOIDLE	(1 << 2)
-#define OMAP4_SMARTIDLE	(2 << 2)
-
-/* SYSSTATUS: register bit definition */
-#define RESETDONE	(1 << 0)
-
 #define MBOX_REG_SIZE			0x120
 
 #define OMAP4_MBOX_REG_SIZE		0x130
@@ -70,8 +58,6 @@
 	unsigned long irqdisable;
 };
 
-static struct clk *mbox_ick_handle;
-
 static void omap2_mbox_enable_irq(struct omap_mbox *mbox,
 				  omap_mbox_type_t irq);
 
@@ -89,53 +75,13 @@
 static int omap2_mbox_startup(struct omap_mbox *mbox)
 {
 	u32 l;
-	unsigned long timeout;
-
-	mbox_ick_handle = clk_get(NULL, "mailboxes_ick");
-	if (IS_ERR(mbox_ick_handle)) {
-		printk(KERN_ERR "Could not get mailboxes_ick: %ld\n",
-			PTR_ERR(mbox_ick_handle));
-		return PTR_ERR(mbox_ick_handle);
-	}
-	clk_enable(mbox_ick_handle);
-
-	if (cpu_is_omap44xx()) {
-		mbox_write_reg(OMAP4_SOFTRESET, MAILBOX_SYSCONFIG);
-		timeout = jiffies + msecs_to_jiffies(20);
-		do {
-			l = mbox_read_reg(MAILBOX_SYSCONFIG);
-			if (!(l & OMAP4_SOFTRESET))
-				break;
-		} while (!time_after(jiffies, timeout));
-
-		if (l & OMAP4_SOFTRESET) {
-			pr_err("Can't take mailbox out of reset\n");
-			return -ENODEV;
-		}
-	} else {
-		mbox_write_reg(SOFTRESET, MAILBOX_SYSCONFIG);
-		timeout = jiffies + msecs_to_jiffies(20);
-		do {
-			l = mbox_read_reg(MAILBOX_SYSSTATUS);
-			if (l & RESETDONE)
-				break;
-		} while (!time_after(jiffies, timeout));
 
-		if (!(l & RESETDONE)) {
-			pr_err("Can't take mailbox out of reset\n");
-			return -ENODEV;
-		}
-	}
+	pm_runtime_enable(mbox->dev->parent);
+	pm_runtime_get_sync(mbox->dev->parent);
 
 	l = mbox_read_reg(MAILBOX_REVISION);
 	pr_debug("omap mailbox rev %d.%d\n", (l & 0xf0) >> 4, (l & 0x0f));
 
-	if (cpu_is_omap44xx())
-		l = OMAP4_SMARTIDLE;
-	else
-		l = SMARTIDLE | AUTOIDLE;
-	mbox_write_reg(l, MAILBOX_SYSCONFIG);
-
 	omap2_mbox_enable_irq(mbox, IRQ_RX);
 
 	return 0;
@@ -143,9 +89,8 @@
 
 static void omap2_mbox_shutdown(struct omap_mbox *mbox)
 {
-	clk_disable(mbox_ick_handle);
-	clk_put(mbox_ick_handle);
-	mbox_ick_handle = NULL;
+	pm_runtime_put_sync(mbox->dev->parent);
+	pm_runtime_disable(mbox->dev->parent);
 }
 
 /* Mailbox FIFO handle functions */
@@ -312,7 +257,7 @@
 struct omap_mbox *omap3_mboxes[] = { &mbox_dsp_info, NULL };
 #endif
 
-#if defined(CONFIG_ARCH_OMAP2420)
+#if defined(CONFIG_SOC_OMAP2420)
 /* IVA */
 static struct omap_mbox2_priv omap2_mbox_iva_priv = {
 	.tx_fifo = {
@@ -400,14 +345,14 @@
 	else if (cpu_is_omap34xx()) {
 		list = omap3_mboxes;
 
-		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+		list[0]->irq = platform_get_irq(pdev, 0);
 	}
 #endif
 #if defined(CONFIG_ARCH_OMAP2)
 	else if (cpu_is_omap2430()) {
 		list = omap2_mboxes;
 
-		list[0]->irq = platform_get_irq_byname(pdev, "dsp");
+		list[0]->irq = platform_get_irq(pdev, 0);
 	} else if (cpu_is_omap2420()) {
 		list = omap2_mboxes;
 
@@ -419,8 +364,7 @@
 	else if (cpu_is_omap44xx()) {
 		list = omap4_mboxes;
 
-		list[0]->irq = list[1]->irq =
-			platform_get_irq_byname(pdev, "mbox");
+		list[0]->irq = list[1]->irq = platform_get_irq(pdev, 0);
 	}
 #endif
 	else {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-omap2/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -31,8 +31,8 @@
 AFLAGS_omap44xx-smc.o			:=-Wa,-march=armv7-a$(plus_sec)
 
 # Functions loaded to SRAM
-obj-$(CONFIG_ARCH_OMAP2420)		+= sram242x.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= sram243x.o
+obj-$(CONFIG_SOC_OMAP2420)		+= sram242x.o
+obj-$(CONFIG_SOC_OMAP2430)		+= sram243x.o
 obj-$(CONFIG_ARCH_OMAP3)		+= sram34xx.o
 
 AFLAGS_sram242x.o			:=-Wa,-march=armv6
@@ -40,8 +40,8 @@
 AFLAGS_sram34xx.o			:=-Wa,-march=armv7-a
 
 # Pin multiplexing
-obj-$(CONFIG_ARCH_OMAP2420)		+= mux2420.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= mux2430.o
+obj-$(CONFIG_SOC_OMAP2420)		+= mux2420.o
+obj-$(CONFIG_SOC_OMAP2430)		+= mux2430.o
 obj-$(CONFIG_ARCH_OMAP3)		+= mux34xx.o
 obj-$(CONFIG_ARCH_OMAP4)		+= mux44xx.o
 
@@ -59,16 +59,16 @@
 # Power Management
 ifeq ($(CONFIG_PM),y)
 obj-$(CONFIG_ARCH_OMAP2)		+= pm24xx.o
-obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o voltage.o
-obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o voltage.o \
+obj-$(CONFIG_ARCH_OMAP2)		+= sleep24xx.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP3)		+= pm34xx.o sleep34xx.o \
 					   cpuidle34xx.o pm_bus.o
-obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o voltage.o pm_bus.o
+obj-$(CONFIG_ARCH_OMAP4)		+= pm44xx.o pm_bus.o
 obj-$(CONFIG_PM_DEBUG)			+= pm-debug.o
 obj-$(CONFIG_OMAP_SMARTREFLEX)          += sr_device.o smartreflex.o
 obj-$(CONFIG_OMAP_SMARTREFLEX_CLASS3)	+= smartreflex-class3.o
 
 AFLAGS_sleep24xx.o			:=-Wa,-march=armv6
-AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a
+AFLAGS_sleep34xx.o			:=-Wa,-march=armv7-a$(plus_sec)
 
 ifeq ($(CONFIG_PM_VERBOSE),y)
 CFLAGS_pm_bus.o				+= -DDEBUG
@@ -78,13 +78,25 @@
 
 # PRCM
 obj-$(CONFIG_ARCH_OMAP2)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
-obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o
+obj-$(CONFIG_ARCH_OMAP3)		+= prcm.o cm2xxx_3xxx.o prm2xxx_3xxx.o \
+					   vc3xxx_data.o vp3xxx_data.o
 # XXX The presence of cm2xxx_3xxx.o on the line below is temporary and
 # will be removed once the OMAP4 part of the codebase is converted to
 # use OMAP4-specific PRCM functions.
 obj-$(CONFIG_ARCH_OMAP4)		+= prcm.o cm2xxx_3xxx.o cminst44xx.o \
 					   cm44xx.o prcm_mpu44xx.o \
-					   prminst44xx.o
+					   prminst44xx.o vc44xx_data.o \
+					   vp44xx_data.o
+
+# OMAP voltage domains
+ifeq ($(CONFIG_PM),y)
+voltagedomain-common			:= voltage.o
+obj-$(CONFIG_ARCH_OMAP2)		+= $(voltagedomain-common)
+obj-$(CONFIG_ARCH_OMAP3)		+= $(voltagedomain-common) \
+					   voltagedomains3xxx_data.o
+obj-$(CONFIG_ARCH_OMAP4)		+= $(voltagedomain-common) \
+					   voltagedomains44xx_data.o
+endif
 
 # OMAP powerdomain framework
 powerdomain-common			+= powerdomain.o powerdomain-common.o
@@ -102,39 +114,49 @@
 
 # PRCM clockdomain control
 obj-$(CONFIG_ARCH_OMAP2)		+= clockdomain.o \
+					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= clockdomain.o \
+					   clockdomain2xxx_3xxx.o \
 					   clockdomains2xxx_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= clockdomain.o \
+					   clockdomain44xx.o \
 					   clockdomains44xx_data.o
+
 # Clock framework
 obj-$(CONFIG_ARCH_OMAP2)		+= $(clock-common) clock2xxx.o \
 					   clkt2xxx_sys.o \
 					   clkt2xxx_dpllcore.o \
 					   clkt2xxx_virt_prcm_set.o \
-					   clkt2xxx_apll.o clkt2xxx_osc.o
-obj-$(CONFIG_ARCH_OMAP2420)		+= clock2420_data.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= clock2430.o clock2430_data.o
+					   clkt2xxx_apll.o clkt2xxx_osc.o \
+					   clkt2xxx_dpll.o clkt_iclk.o
+obj-$(CONFIG_SOC_OMAP2420)		+= clock2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= clock2430.o clock2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= $(clock-common) clock3xxx.o \
 					   clock34xx.o clkt34xx_dpll3m2.o \
 					   clock3517.o clock36xx.o \
-					   dpll3xxx.o clock3xxx_data.o
+					   dpll3xxx.o clock3xxx_data.o \
+					   clkt_iclk.o
 obj-$(CONFIG_ARCH_OMAP4)		+= $(clock-common) clock44xx_data.o \
-					   dpll3xxx.o
+					   dpll3xxx.o dpll44xx.o
 
 # OMAP2 clock rate set data (old "OPP" data)
-obj-$(CONFIG_ARCH_OMAP2420)		+= opp2420_data.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= opp2430_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= opp2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= opp2430_data.o
 
 # hwmod data
-obj-$(CONFIG_ARCH_OMAP2420)		+= omap_hwmod_2420_data.o
-obj-$(CONFIG_ARCH_OMAP2430)		+= omap_hwmod_2430_data.o
+obj-$(CONFIG_SOC_OMAP2420)		+= omap_hwmod_2420_data.o
+obj-$(CONFIG_SOC_OMAP2430)		+= omap_hwmod_2430_data.o
 obj-$(CONFIG_ARCH_OMAP3)		+= omap_hwmod_3xxx_data.o
 obj-$(CONFIG_ARCH_OMAP4)		+= omap_hwmod_44xx_data.o
 
 # EMU peripherals
 obj-$(CONFIG_OMAP3_EMU)			+= emu.o
 
+# L3 interconnect
+obj-$(CONFIG_ARCH_OMAP3)		+= omap_l3_smx.o
+obj-$(CONFIG_ARCH_OMAP4)		+= omap_l3_noc.o
+
 obj-$(CONFIG_OMAP_MBOX_FWK)		+= mailbox_mach.o
 mailbox_mach-objs			:= mailbox.o
 
@@ -218,18 +240,20 @@
 					   hsmmc.o \
 					   omap_phy_internal.o
 
-obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o
+obj-$(CONFIG_MACH_OMAP3517EVM)		+= board-am3517evm.o \
+					   omap_phy_internal.o \
 
 obj-$(CONFIG_MACH_CRANEBOARD)		+= board-am3517crane.o
 
 obj-$(CONFIG_MACH_SBC3530)		+= board-omap3stalker.o \
 					   hsmmc.o
+obj-$(CONFIG_MACH_TI8168EVM)		+= board-ti8168evm.o
 # Platform specific device init code
 usbfs-$(CONFIG_ARCH_OMAP_OTG)		:= usb-fs.o
 obj-y					+= $(usbfs-m) $(usbfs-y)
 obj-y					+= usb-musb.o
 obj-$(CONFIG_MACH_OMAP2_TUSB6010)	+= usb-tusb6010.o
-obj-y					+= usb-ehci.o
+obj-y					+= usb-host.o
 
 onenand-$(CONFIG_MTD_ONENAND_OMAP2)	:= gpmc-onenand.o
 obj-y					+= $(onenand-m) $(onenand-y)
@@ -242,3 +266,7 @@
 
 smsc911x-$(CONFIG_SMSC911X)		:= gpmc-smsc911x.o
 obj-y					+= $(smsc911x-m) $(smsc911x-y)
+obj-$(CONFIG_ARCH_OMAP4)		+= hwspinlock.o
+
+disp-$(CONFIG_OMAP2_DSS)		:= display.o
+obj-y					+= $(disp-m) $(disp-y)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mcbsp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mcbsp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mcbsp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mcbsp.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,10 +22,11 @@
 #include <plat/dma.h>
 #include <plat/cpu.h>
 #include <plat/mcbsp.h>
+#include <plat/omap_device.h>
+#include <linux/pm_runtime.h>
 
 #include "control.h"
 
-
 /* McBSP internal signal muxing functions */
 
 void omap2_mcbsp1_mux_clkr_src(u8 mux)
@@ -83,7 +84,7 @@
 		return -EINVAL;
 	}
 
-	clk_disable(mcbsp->fclk);
+	pm_runtime_put_sync(mcbsp->dev);
 
 	r = clk_set_parent(mcbsp->fclk, fck_src);
 	if (IS_ERR_VALUE(r)) {
@@ -93,7 +94,7 @@
 		return -EINVAL;
 	}
 
-	clk_enable(mcbsp->fclk);
+	pm_runtime_get_sync(mcbsp->dev);
 
 	clk_put(fck_src);
 
@@ -101,196 +102,70 @@
 }
 EXPORT_SYMBOL(omap2_mcbsp_set_clks_src);
 
-
-/* Platform data */
-
-#ifdef CONFIG_ARCH_OMAP2420
-static struct omap_mcbsp_platform_data omap2420_mcbsp_pdata[] = {
-	{
-		.phys_base	= OMAP24XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
-		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-	},
+struct omap_device_pm_latency omap2_mcbsp_latency[] = {
 	{
-		.phys_base	= OMAP24XX_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
-		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
+		.deactivate_func = omap_device_idle_hwmods,
+		.activate_func   = omap_device_enable_hwmods,
+		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
 };
-#define OMAP2420_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2420_mcbsp_pdata)
-#define OMAP2420_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
-#else
-#define omap2420_mcbsp_pdata		NULL
-#define OMAP2420_MCBSP_PDATA_SZ		0
-#define OMAP2420_MCBSP_REG_NUM		0
-#endif
 
-#ifdef CONFIG_ARCH_OMAP2430
-static struct omap_mcbsp_platform_data omap2430_mcbsp_pdata[] = {
-	{
-		.phys_base	= OMAP24XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
-		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP24XX_MCBSP2_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
-		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP2430_MCBSP3_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
-		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP2430_MCBSP4_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
-		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
-	},
-	{
-		.phys_base	= OMAP2430_MCBSP5_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
-		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
-	},
-};
-#define OMAP2430_MCBSP_PDATA_SZ		ARRAY_SIZE(omap2430_mcbsp_pdata)
-#define OMAP2430_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
-#else
-#define omap2430_mcbsp_pdata		NULL
-#define OMAP2430_MCBSP_PDATA_SZ		0
-#define OMAP2430_MCBSP_REG_NUM		0
-#endif
+static int omap_init_mcbsp(struct omap_hwmod *oh, void *unused)
+{
+	int id, count = 1;
+	char *name = "omap-mcbsp";
+	struct omap_hwmod *oh_device[2];
+	struct omap_mcbsp_platform_data *pdata = NULL;
+	struct omap_device *od;
 
-#ifdef CONFIG_ARCH_OMAP3
-static struct omap_mcbsp_platform_data omap34xx_mcbsp_pdata[] = {
-	{
-		.phys_base	= OMAP34XX_MCBSP1_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP1_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP1_TX,
-		.rx_irq		= INT_24XX_MCBSP1_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP1_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP2_BASE,
-		.phys_base_st	= OMAP34XX_MCBSP2_ST_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP2_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP2_TX,
-		.rx_irq		= INT_24XX_MCBSP2_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP2_IRQ_TX,
-		.buffer_size	= 0x500, /* The FIFO has 1024 + 256 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP3_BASE,
-		.phys_base_st	= OMAP34XX_MCBSP3_ST_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP3_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP3_TX,
-		.rx_irq		= INT_24XX_MCBSP3_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP3_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP4_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP4_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP4_TX,
-		.rx_irq		= INT_24XX_MCBSP4_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP4_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-	{
-		.phys_base	= OMAP34XX_MCBSP5_BASE,
-		.dma_rx_sync	= OMAP24XX_DMA_MCBSP5_RX,
-		.dma_tx_sync	= OMAP24XX_DMA_MCBSP5_TX,
-		.rx_irq		= INT_24XX_MCBSP5_IRQ_RX,
-		.tx_irq		= INT_24XX_MCBSP5_IRQ_TX,
-		.buffer_size	= 0x80, /* The FIFO has 128 locations */
-	},
-};
-#define OMAP34XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap34xx_mcbsp_pdata)
-#define OMAP34XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
-#else
-#define omap34xx_mcbsp_pdata		NULL
-#define OMAP34XX_MCBSP_PDATA_SZ		0
-#define OMAP34XX_MCBSP_REG_NUM		0
-#endif
+	sscanf(oh->name, "mcbsp%d", &id);
 
-static struct omap_mcbsp_platform_data omap44xx_mcbsp_pdata[] = {
-	{
-		.phys_base      = OMAP44XX_MCBSP1_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP1_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP1_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP1,
-	},
-	{
-		.phys_base      = OMAP44XX_MCBSP2_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP2_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP2_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP2,
-	},
-	{
-		.phys_base      = OMAP44XX_MCBSP3_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP3_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP3_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP3,
-	},
-	{
-		.phys_base      = OMAP44XX_MCBSP4_BASE,
-		.dma_rx_sync    = OMAP44XX_DMA_MCBSP4_RX,
-		.dma_tx_sync    = OMAP44XX_DMA_MCBSP4_TX,
-		.tx_irq         = OMAP44XX_IRQ_MCBSP4,
-	},
-};
-#define OMAP44XX_MCBSP_PDATA_SZ		ARRAY_SIZE(omap44xx_mcbsp_pdata)
-#define OMAP44XX_MCBSP_REG_NUM		(OMAP_MCBSP_REG_RCCR / sizeof(u32) + 1)
+	pdata = kzalloc(sizeof(struct omap_mcbsp_platform_data), GFP_KERNEL);
+	if (!pdata) {
+		pr_err("%s: No memory for mcbsp\n", __func__);
+		return -ENOMEM;
+	}
+
+	pdata->mcbsp_config_type = oh->class->rev;
+
+	if (oh->class->rev == MCBSP_CONFIG_TYPE3) {
+		if (id == 2)
+			/* The FIFO has 1024 + 256 locations */
+			pdata->buffer_size = 0x500;
+		else
+			/* The FIFO has 128 locations */
+			pdata->buffer_size = 0x80;
+	}
+
+	oh_device[0] = oh;
+
+	if (oh->dev_attr) {
+		oh_device[1] = omap_hwmod_lookup((
+		(struct omap_mcbsp_dev_attr *)(oh->dev_attr))->sidetone);
+		count++;
+	}
+	od = omap_device_build_ss(name, id, oh_device, count, pdata,
+				sizeof(*pdata), omap2_mcbsp_latency,
+				ARRAY_SIZE(omap2_mcbsp_latency), false);
+	kfree(pdata);
+	if (IS_ERR(od))  {
+		pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
+					name, oh->name);
+		return PTR_ERR(od);
+	}
+	omap_mcbsp_count++;
+	return 0;
+}
 
 static int __init omap2_mcbsp_init(void)
 {
-	if (cpu_is_omap2420()) {
-		omap_mcbsp_count = OMAP2420_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP2420_MCBSP_REG_NUM * sizeof(u16);
-	} else if (cpu_is_omap2430()) {
-		omap_mcbsp_count = OMAP2430_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP2430_MCBSP_REG_NUM * sizeof(u32);
-	} else if (cpu_is_omap34xx()) {
-		omap_mcbsp_count = OMAP34XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP34XX_MCBSP_REG_NUM * sizeof(u32);
-	} else if (cpu_is_omap44xx()) {
-		omap_mcbsp_count = OMAP44XX_MCBSP_PDATA_SZ;
-		omap_mcbsp_cache_size = OMAP44XX_MCBSP_REG_NUM * sizeof(u32);
-	}
+	omap_hwmod_for_each_by_class("mcbsp", omap_init_mcbsp, NULL);
 
 	mcbsp_ptr = kzalloc(omap_mcbsp_count * sizeof(struct omap_mcbsp *),
 								GFP_KERNEL);
 	if (!mcbsp_ptr)
 		return -ENOMEM;
 
-	if (cpu_is_omap2420())
-		omap_mcbsp_register_board_cfg(omap2420_mcbsp_pdata,
-						OMAP2420_MCBSP_PDATA_SZ);
-	if (cpu_is_omap2430())
-		omap_mcbsp_register_board_cfg(omap2430_mcbsp_pdata,
-						OMAP2430_MCBSP_PDATA_SZ);
-	if (cpu_is_omap34xx())
-		omap_mcbsp_register_board_cfg(omap34xx_mcbsp_pdata,
-						OMAP34XX_MCBSP_PDATA_SZ);
-	if (cpu_is_omap44xx())
-		omap_mcbsp_register_board_cfg(omap44xx_mcbsp_pdata,
-						OMAP44XX_MCBSP_PDATA_SZ);
-
 	return omap_mcbsp_init();
 }
 arch_initcall(omap2_mcbsp_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux2430.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux2430.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux2430.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux2430.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
  * absolute addresses.  The name in the macro is the mode-0 name of
  * the pin.  NOTE: These registers are 8-bits wide.
  *
- * Note that these defines use SDMMC instead of MMC for compability
+ * Note that these defines use SDMMC instead of MMC for compatibility
  * with signal names used in 3630.
  */
 #define OMAP2430_CONTROL_PADCONF_GPMC_CLK_OFFSET		0x000
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux44xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux44xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux44xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux44xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -755,25 +755,9 @@
 #endif
 
 /*
- * Superset of all mux modes for omap4 ES2.0
+ * Signals different on ES2.0 compared to superset
  */
-static struct omap_mux __initdata omap4_es2_core_muxmodes[] = {
-	_OMAP4_MUXENTRY(GPMC_AD0, 0, "gpmc_ad0", "sdmmc2_dat0", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD1, 0, "gpmc_ad1", "sdmmc2_dat1", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD2, 0, "gpmc_ad2", "sdmmc2_dat2", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD3, 0, "gpmc_ad3", "sdmmc2_dat3", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD4, 0, "gpmc_ad4", "sdmmc2_dat4",
-			"sdmmc2_dir_dat0", NULL, NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD5, 0, "gpmc_ad5", "sdmmc2_dat5",
-			"sdmmc2_dir_dat1", NULL, NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD6, 0, "gpmc_ad6", "sdmmc2_dat6",
-			"sdmmc2_dir_cmd", NULL, NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_AD7, 0, "gpmc_ad7", "sdmmc2_dat7",
-			"sdmmc2_clk_fdbk", NULL, NULL, NULL, NULL, NULL),
+static struct omap_mux __initdata omap4_es2_core_subset[] = {
 	_OMAP4_MUXENTRY(GPMC_AD8, 32, "gpmc_ad8", "kpd_row0", "c2c_data15",
 			"gpio_32", NULL, "sdmmc1_dat0", NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_AD9, 33, "gpmc_ad9", "kpd_row1", "c2c_data14",
@@ -792,52 +776,15 @@
 			"gpio_39", NULL, "sdmmc1_dat7", NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_A16, 40, "gpmc_a16", "kpd_row4", "c2c_datain0",
 			"gpio_40", "venc_656_data0", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A17, 41, "gpmc_a17", "kpd_row5", "c2c_datain1",
-			"gpio_41", "venc_656_data1", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A18, 42, "gpmc_a18", "kpd_row6", "c2c_datain2",
-			"gpio_42", "venc_656_data2", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A19, 43, "gpmc_a19", "kpd_row7", "c2c_datain3",
-			"gpio_43", "venc_656_data3", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A20, 44, "gpmc_a20", "kpd_col4", "c2c_datain4",
-			"gpio_44", "venc_656_data4", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A21, 45, "gpmc_a21", "kpd_col5", "c2c_datain5",
-			"gpio_45", "venc_656_data5", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A22, 46, "gpmc_a22", "kpd_col6", "c2c_datain6",
-			"gpio_46", "venc_656_data6", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A23, 47, "gpmc_a23", "kpd_col7", "c2c_datain7",
-			"gpio_47", "venc_656_data7", NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(GPMC_A24, 48, "gpmc_a24", "kpd_col8", "c2c_clkout0",
 			"gpio_48", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_A25, 49, "gpmc_a25", NULL, "c2c_clkout1",
-			"gpio_49", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_NCS0, 50, "gpmc_ncs0", NULL, NULL, "gpio_50",
-			"sys_ndmareq0", NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NCS1, 51, "gpmc_ncs1", NULL, "c2c_dataout6",
-			"gpio_51", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(GPMC_NCS2, 52, "gpmc_ncs2", "kpd_row8",
 			"c2c_dataout7", "gpio_52", NULL, NULL, NULL,
 			"safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_NCS3, 53, "gpmc_ncs3", "gpmc_dir",
-			"c2c_dataout4", "gpio_53", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_NWP, 54, "gpmc_nwp", "dsi1_te0", NULL, "gpio_54",
-			"sys_ndmareq1", NULL, NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_CLK, 55, "gpmc_clk", NULL, NULL, "gpio_55",
 			"sys_ndmareq2", "sdmmc1_cmd", NULL, NULL),
 	_OMAP4_MUXENTRY(GPMC_NADV_ALE, 56, "gpmc_nadv_ale", "dsi1_te1", NULL,
 			"gpio_56", "sys_ndmareq3", "sdmmc1_clk", NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NOE, 0, "gpmc_noe", "sdmmc2_clk", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NWE, 0, "gpmc_nwe", "sdmmc2_cmd", NULL, NULL,
-			NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NBE0_CLE, 59, "gpmc_nbe0_cle", "dsi2_te0", NULL,
-			"gpio_59", NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_NBE1, 60, "gpmc_nbe1", NULL, "c2c_dataout5",
-			"gpio_60", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(GPMC_WAIT0, 61, "gpmc_wait0", "dsi2_te1", NULL,
-			"gpio_61", NULL, NULL, NULL, NULL),
-	_OMAP4_MUXENTRY(GPMC_WAIT1, 62, "gpmc_wait1", NULL, "c2c_dataout2",
-			"gpio_62", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(GPMC_WAIT2, 100, "gpmc_wait2", "usbc1_icusb_txen",
 			"c2c_dataout3", "gpio_100", "sys_ndmareq0", NULL,
 			NULL, "safe_mode"),
@@ -851,62 +798,6 @@
 	_OMAP4_MUXENTRY(GPMC_NCS7, 104, "gpmc_ncs7", "dsi2_te1",
 			"c2c_dataout1", "gpio_104", NULL, NULL, NULL,
 			"safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_HPD, 63, "hdmi_hpd", NULL, NULL, "gpio_63", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_CEC, 64, "hdmi_cec", NULL, NULL, "gpio_64", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_DDC_SCL, 65, "hdmi_ddc_scl", NULL, NULL,
-			"gpio_65", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDMI_DDC_SDA, 66, "hdmi_ddc_sda", NULL, NULL,
-			"gpio_66", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX0, 0, "csi21_dx0", NULL, NULL, "gpi_67", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY0, 0, "csi21_dy0", NULL, NULL, "gpi_68", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX1, 0, "csi21_dx1", NULL, NULL, "gpi_69", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY1, 0, "csi21_dy1", NULL, NULL, "gpi_70", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX2, 0, "csi21_dx2", NULL, NULL, "gpi_71", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY2, 0, "csi21_dy2", NULL, NULL, "gpi_72", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX3, 0, "csi21_dx3", NULL, NULL, "gpi_73", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY3, 0, "csi21_dy3", NULL, NULL, "gpi_74", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DX4, 0, "csi21_dx4", NULL, NULL, "gpi_75", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI21_DY4, 0, "csi21_dy4", NULL, NULL, "gpi_76", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DX0, 0, "csi22_dx0", NULL, NULL, "gpi_77", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DY0, 0, "csi22_dy0", NULL, NULL, "gpi_78", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DX1, 0, "csi22_dx1", NULL, NULL, "gpi_79", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CSI22_DY1, 0, "csi22_dy1", NULL, NULL, "gpi_80", NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CAM_SHUTTER, 81, "cam_shutter", NULL, NULL, "gpio_81",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CAM_STROBE, 82, "cam_strobe", NULL, NULL, "gpio_82",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(CAM_GLOBALRESET, 83, "cam_globalreset", NULL, NULL,
-			"gpio_83", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_CLK, 84, "usbb1_ulpitll_clk",
-			"hsi1_cawake", NULL, "gpio_84", "usbb1_ulpiphy_clk",
-			NULL, "hw_dbg20", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_STP, 85, "usbb1_ulpitll_stp",
-			"hsi1_cadata", "mcbsp4_clkr", "gpio_85",
-			"usbb1_ulpiphy_stp", "usbb1_mm_rxdp", "hw_dbg21",
-			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DIR, 86, "usbb1_ulpitll_dir",
-			"hsi1_caflag", "mcbsp4_fsr", "gpio_86",
-			"usbb1_ulpiphy_dir", NULL, "hw_dbg22", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_NXT, 87, "usbb1_ulpitll_nxt",
-			"hsi1_acready", "mcbsp4_fsx", "gpio_87",
-			"usbb1_ulpiphy_nxt", "usbb1_mm_rxdm", "hw_dbg23",
-			"safe_mode"),
 	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT0, 88, "usbb1_ulpitll_dat0",
 			"hsi1_acwake", "mcbsp4_clkx", "gpio_88",
 			"usbb1_ulpiphy_dat0", "usbb1_mm_txen", "hw_dbg24",
@@ -922,84 +813,6 @@
 	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT3, 91, "usbb1_ulpitll_dat3",
 			"hsi1_caready", NULL, "gpio_91", "usbb1_ulpiphy_dat3",
 			"usbb1_mm_rxrcv", "hw_dbg27", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT4, 92, "usbb1_ulpitll_dat4",
-			"dmtimer8_pwm_evt", "abe_mcbsp3_dr", "gpio_92",
-			"usbb1_ulpiphy_dat4", NULL, "hw_dbg28", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT5, 93, "usbb1_ulpitll_dat5",
-			"dmtimer9_pwm_evt", "abe_mcbsp3_dx", "gpio_93",
-			"usbb1_ulpiphy_dat5", NULL, "hw_dbg29", "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT6, 94, "usbb1_ulpitll_dat6",
-			"dmtimer10_pwm_evt", "abe_mcbsp3_clkx", "gpio_94",
-			"usbb1_ulpiphy_dat6", "abe_dmic_din3", "hw_dbg30",
-			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_ULPITLL_DAT7, 95, "usbb1_ulpitll_dat7",
-			"dmtimer11_pwm_evt", "abe_mcbsp3_fsx", "gpio_95",
-			"usbb1_ulpiphy_dat7", "abe_dmic_clk3", "hw_dbg31",
-			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_HSIC_DATA, 96, "usbb1_hsic_data", NULL, NULL,
-			"gpio_96", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB1_HSIC_STROBE, 97, "usbb1_hsic_strobe", NULL,
-			NULL, "gpio_97", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBC1_ICUSB_DP, 98, "usbc1_icusb_dp", NULL, NULL,
-			"gpio_98", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBC1_ICUSB_DM, 99, "usbc1_icusb_dm", NULL, NULL,
-			"gpio_99", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_CLK, 100, "sdmmc1_clk", NULL, "dpm_emu19",
-			"gpio_100", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_CMD, 101, "sdmmc1_cmd", NULL, "uart1_rx",
-			"gpio_101", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT0, 102, "sdmmc1_dat0", NULL, "dpm_emu18",
-			"gpio_102", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT1, 103, "sdmmc1_dat1", NULL, "dpm_emu17",
-			"gpio_103", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT2, 104, "sdmmc1_dat2", NULL, "dpm_emu16",
-			"gpio_104", "jtag_tms_tmsc", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT3, 105, "sdmmc1_dat3", NULL, "dpm_emu15",
-			"gpio_105", "jtag_tck", NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT4, 106, "sdmmc1_dat4", NULL, NULL,
-			"gpio_106", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT5, 107, "sdmmc1_dat5", NULL, NULL,
-			"gpio_107", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT6, 108, "sdmmc1_dat6", NULL, NULL,
-			"gpio_108", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SDMMC1_DAT7, 109, "sdmmc1_dat7", NULL, NULL,
-			"gpio_109", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_CLKX, 110, "abe_mcbsp2_clkx", "mcspi2_clk",
-			"abe_mcasp_ahclkx", "gpio_110", "usbb2_mm_rxdm",
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_DR, 111, "abe_mcbsp2_dr", "mcspi2_somi",
-			"abe_mcasp_axr", "gpio_111", "usbb2_mm_rxdp", NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_DX, 112, "abe_mcbsp2_dx", "mcspi2_simo",
-			"abe_mcasp_amute", "gpio_112", "usbb2_mm_rxrcv", NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP2_FSX, 113, "abe_mcbsp2_fsx", "mcspi2_cs0",
-			"abe_mcasp_afsx", "gpio_113", "usbb2_mm_txen", NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_CLKX, 114, "abe_mcbsp1_clkx",
-			"abe_slimbus1_clock", NULL, "gpio_114", NULL, NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_DR, 115, "abe_mcbsp1_dr",
-			"abe_slimbus1_data", NULL, "gpio_115", NULL, NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_DX, 116, "abe_mcbsp1_dx", "sdmmc3_dat2",
-			"abe_mcasp_aclkx", "gpio_116", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_MCBSP1_FSX, 117, "abe_mcbsp1_fsx", "sdmmc3_dat3",
-			"abe_mcasp_amutein", "gpio_117", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_UL_DATA, 0, "abe_pdm_ul_data",
-			"abe_mcbsp3_dr", NULL, NULL, NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_DL_DATA, 0, "abe_pdm_dl_data",
-			"abe_mcbsp3_dx", NULL, NULL, NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_FRAME, 0, "abe_pdm_frame", "abe_mcbsp3_clkx",
-			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_PDM_LB_CLK, 0, "abe_pdm_lb_clk", "abe_mcbsp3_fsx",
-			NULL, NULL, NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(ABE_CLKS, 118, "abe_clks", NULL, NULL, "gpio_118",
-			NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(ABE_DMIC_CLK1, 119, "abe_dmic_clk1", NULL, NULL,
 			"gpio_119", "usbb2_mm_txse0", "uart4_cts", NULL,
 			"safe_mode"),
@@ -1012,58 +825,6 @@
 	_OMAP4_MUXENTRY(ABE_DMIC_DIN3, 122, "abe_dmic_din3", "slimbus2_data",
 			"abe_dmic_clk2", "gpio_122", NULL, "dmtimer9_pwm_evt",
 			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_CTS, 123, "uart2_cts", "sdmmc3_clk", NULL,
-			"gpio_123", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_RTS, 124, "uart2_rts", "sdmmc3_cmd", NULL,
-			"gpio_124", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_RX, 125, "uart2_rx", "sdmmc3_dat0", NULL,
-			"gpio_125", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART2_TX, 126, "uart2_tx", "sdmmc3_dat1", NULL,
-			"gpio_126", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(HDQ_SIO, 127, "hdq_sio", "i2c3_sccb", "i2c2_sccb",
-			"gpio_127", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C1_SCL, 0, "i2c1_scl", NULL, NULL, NULL, NULL, NULL,
-			NULL, NULL),
-	_OMAP4_MUXENTRY(I2C1_SDA, 0, "i2c1_sda", NULL, NULL, NULL, NULL, NULL,
-			NULL, NULL),
-	_OMAP4_MUXENTRY(I2C2_SCL, 128, "i2c2_scl", "uart1_rx", NULL,
-			"gpio_128", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C2_SDA, 129, "i2c2_sda", "uart1_tx", NULL,
-			"gpio_129", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C3_SCL, 130, "i2c3_scl", NULL, NULL, "gpio_130",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C3_SDA, 131, "i2c3_sda", NULL, NULL, "gpio_131",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C4_SCL, 132, "i2c4_scl", NULL, NULL, "gpio_132",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(I2C4_SDA, 133, "i2c4_sda", NULL, NULL, "gpio_133",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CLK, 134, "mcspi1_clk", NULL, NULL, "gpio_134",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_SOMI, 135, "mcspi1_somi", NULL, NULL,
-			"gpio_135", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_SIMO, 136, "mcspi1_simo", NULL, NULL,
-			"gpio_136", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS0, 137, "mcspi1_cs0", NULL, NULL, "gpio_137",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS1, 138, "mcspi1_cs1", "uart1_rx", NULL,
-			"gpio_138", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS2, 139, "mcspi1_cs2", "uart1_cts",
-			"slimbus2_clock", "gpio_139", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(MCSPI1_CS3, 140, "mcspi1_cs3", "uart1_rts",
-			"slimbus2_data", "gpio_140", NULL, NULL, NULL,
-			"safe_mode"),
-	_OMAP4_MUXENTRY(UART3_CTS_RCTX, 141, "uart3_cts_rctx", "uart1_tx",
-			NULL, "gpio_141", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART3_RTS_SD, 142, "uart3_rts_sd", NULL, NULL,
-			"gpio_142", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART3_RX_IRRX, 143, "uart3_rx_irrx",
-			"dmtimer8_pwm_evt", NULL, "gpio_143", NULL, NULL,
-			NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(UART3_TX_IRTX, 144, "uart3_tx_irtx",
-			"dmtimer9_pwm_evt", NULL, "gpio_144", NULL, NULL,
-			NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(SDMMC5_CLK, 145, "sdmmc5_clk", "mcspi2_clk",
 			"usbc1_icusb_dp", "gpio_145", NULL, "sdmmc2_clk",
 			NULL, "safe_mode"),
@@ -1096,9 +857,6 @@
 			"gpio_155", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(UART4_TX, 156, "uart4_tx", "sdmmc4_dat1", "kpd_col8",
 			"gpio_156", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB2_ULPITLL_CLK, 157, "usbb2_ulpitll_clk",
-			"usbb2_ulpiphy_clk", "sdmmc4_cmd", "gpio_157",
-			"hsi2_cawake", NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(USBB2_ULPITLL_STP, 158, "usbb2_ulpitll_stp",
 			"usbb2_ulpiphy_stp", "sdmmc4_clk", "gpio_158",
 			"hsi2_cadata", "dispc2_data23", NULL, "safe_mode"),
@@ -1140,10 +898,6 @@
 			"usbb2_ulpiphy_dat7", "sdmmc3_clk", "gpio_168",
 			"mcspi3_clk", "dispc2_data11", "rfbi_data11",
 			"safe_mode"),
-	_OMAP4_MUXENTRY(USBB2_HSIC_DATA, 169, "usbb2_hsic_data", NULL, NULL,
-			"gpio_169", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBB2_HSIC_STROBE, 170, "usbb2_hsic_strobe", NULL,
-			NULL, "gpio_170", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(KPD_COL3, 171, "kpd_col3", "kpd_col0", NULL,
 			"gpio_171", NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(KPD_COL4, 172, "kpd_col4", "kpd_col1", NULL,
@@ -1168,36 +922,10 @@
 			NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(KPD_ROW2, 3, "kpd_row2", "kpd_row5", NULL, "gpio_3",
 			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(USBA0_OTG_CE, 0, "usba0_otg_ce", NULL, NULL, NULL,
-			NULL, NULL, NULL, NULL),
 	_OMAP4_MUXENTRY(USBA0_OTG_DP, 0, "usba0_otg_dp", "uart3_rx_irrx",
 			"uart2_rx", NULL, NULL, NULL, NULL, "safe_mode"),
 	_OMAP4_MUXENTRY(USBA0_OTG_DM, 0, "usba0_otg_dm", "uart3_tx_irtx",
 			"uart2_tx", NULL, NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(FREF_CLK1_OUT, 181, "fref_clk1_out", NULL, NULL,
-			"gpio_181", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(FREF_CLK2_OUT, 182, "fref_clk2_out", NULL, NULL,
-			"gpio_182", NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_NIRQ1, 0, "sys_nirq1", NULL, NULL, NULL, NULL,
-			NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_NIRQ2, 183, "sys_nirq2", NULL, NULL, "gpio_183",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT0, 184, "sys_boot0", NULL, NULL, "gpio_184",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT1, 185, "sys_boot1", NULL, NULL, "gpio_185",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT2, 186, "sys_boot2", NULL, NULL, "gpio_186",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT3, 187, "sys_boot3", NULL, NULL, "gpio_187",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT4, 188, "sys_boot4", NULL, NULL, "gpio_188",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(SYS_BOOT5, 189, "sys_boot5", NULL, NULL, "gpio_189",
-			NULL, NULL, NULL, "safe_mode"),
-	_OMAP4_MUXENTRY(DPM_EMU0, 11, "dpm_emu0", NULL, NULL, "gpio_11", NULL,
-			NULL, "hw_dbg0", "safe_mode"),
-	_OMAP4_MUXENTRY(DPM_EMU1, 12, "dpm_emu1", NULL, NULL, "gpio_12", NULL,
-			NULL, "hw_dbg1", "safe_mode"),
 	_OMAP4_MUXENTRY(DPM_EMU2, 13, "dpm_emu2", "usba0_ulpiphy_clk", NULL,
 			"gpio_13", NULL, "dispc2_fid", "hw_dbg2",
 			"safe_mode"),
@@ -1586,6 +1314,7 @@
 	struct omap_ball *package_balls_core;
 	struct omap_ball *package_balls_wkup = omap4_wkup_cbl_cbs_ball;
 	struct omap_mux *core_muxmodes;
+	struct omap_mux *core_subset = NULL;
 	int ret;
 
 	switch (flags & OMAP_PACKAGE_MASK) {
@@ -1597,7 +1326,8 @@
 	case OMAP_PACKAGE_CBS:
 		pr_debug("%s: OMAP4430 ES2.X -> OMAP_PACKAGE_CBS\n", __func__);
 		package_balls_core = omap4_core_cbs_ball;
-		core_muxmodes = omap4_es2_core_muxmodes;
+		core_muxmodes = omap4_core_muxmodes;
+		core_subset = omap4_es2_core_subset;
 		break;
 	default:
 		pr_err("%s: Unknown omap package, mux disabled\n", __func__);
@@ -1608,7 +1338,7 @@
 			    OMAP_MUX_GPIO_IN_MODE3,
 			    OMAP4_CTRL_MODULE_PAD_CORE_MUX_PBASE,
 			    OMAP4_CTRL_MODULE_PAD_CORE_MUX_SIZE,
-			    core_muxmodes, NULL, board_subset,
+			    core_muxmodes, core_subset, board_subset,
 			    package_balls_core);
 	if (ret)
 		return ret;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux.c	2011-05-19 00:06:34.000000000 -0400
@@ -258,7 +258,7 @@
 omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads)
 {
 	struct omap_hwmod_mux_info *hmux;
-	int i;
+	int i, nr_pads_dynamic = 0;
 
 	if (!bpads || nr_pads < 1)
 		return NULL;
@@ -302,9 +302,40 @@
 		pad->enable = bpad->enable;
 		pad->idle = bpad->idle;
 		pad->off = bpad->off;
+
+		if (pad->flags & OMAP_DEVICE_PAD_REMUX)
+			nr_pads_dynamic++;
+
 		pr_debug("%s: Initialized %s\n", __func__, pad->name);
 	}
 
+	if (!nr_pads_dynamic)
+		return hmux;
+
+	/*
+	 * Add pads that need dynamic muxing into a separate list
+	 */
+
+	hmux->nr_pads_dynamic = nr_pads_dynamic;
+	hmux->pads_dynamic = kzalloc(sizeof(struct omap_device_pad *) *
+					nr_pads_dynamic, GFP_KERNEL);
+	if (!hmux->pads_dynamic) {
+		pr_err("%s: Could not allocate dynamic pads\n", __func__);
+		return hmux;
+	}
+
+	nr_pads_dynamic = 0;
+	for (i = 0; i < hmux->nr_pads; i++) {
+		struct omap_device_pad *pad = &hmux->pads[i];
+
+		if (pad->flags & OMAP_DEVICE_PAD_REMUX) {
+			pr_debug("%s: pad %s tagged dynamic\n",
+					__func__, pad->name);
+			hmux->pads_dynamic[nr_pads_dynamic] = pad;
+			nr_pads_dynamic++;
+		}
+	}
+
 	return hmux;
 
 err3:
@@ -322,6 +353,36 @@
 {
 	int i;
 
+	/* Runtime idling of dynamic pads */
+	if (state == _HWMOD_STATE_IDLE && hmux->enabled) {
+		for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+			struct omap_device_pad *pad = hmux->pads_dynamic[i];
+			int val = -EINVAL;
+
+			val = pad->idle;
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+		}
+
+		return;
+	}
+
+	/* Runtime enabling of dynamic pads */
+	if ((state == _HWMOD_STATE_ENABLED) && hmux->pads_dynamic
+					&& hmux->enabled) {
+		for (i = 0; i < hmux->nr_pads_dynamic; i++) {
+			struct omap_device_pad *pad = hmux->pads_dynamic[i];
+			int val = -EINVAL;
+
+			val = pad->enable;
+			omap_mux_write(pad->partition, val,
+					pad->mux->reg_offset);
+		}
+
+		return;
+	}
+
+	/* Enabling or disabling of all pads */
 	for (i = 0; i < hmux->nr_pads; i++) {
 		struct omap_device_pad *pad = &hmux->pads[i];
 		int flags, val = -EINVAL;
@@ -330,31 +391,22 @@
 
 		switch (state) {
 		case _HWMOD_STATE_ENABLED:
-			if (flags & OMAP_DEVICE_PAD_ENABLED)
-				break;
-			flags |= OMAP_DEVICE_PAD_ENABLED;
 			val = pad->enable;
 			pr_debug("%s: Enabling %s %x\n", __func__,
 					pad->name, val);
 			break;
-		case _HWMOD_STATE_IDLE:
-			if (!(flags & OMAP_DEVICE_PAD_REMUX))
-				break;
-			flags &= ~OMAP_DEVICE_PAD_ENABLED;
-			val = pad->idle;
-			pr_debug("%s: Idling %s %x\n", __func__,
-					pad->name, val);
-			break;
 		case _HWMOD_STATE_DISABLED:
-		default:
 			/* Use safe mode unless OMAP_DEVICE_PAD_REMUX */
 			if (flags & OMAP_DEVICE_PAD_REMUX)
 				val = pad->off;
 			else
 				val = OMAP_MUX_MODE7;
-			flags &= ~OMAP_DEVICE_PAD_ENABLED;
 			pr_debug("%s: Disabling %s %x\n", __func__,
 					pad->name, val);
+			break;
+		default:
+			/* Nothing to be done */
+			break;
 		};
 
 		if (val >= 0) {
@@ -363,6 +415,11 @@
 			pad->flags = flags;
 		}
 	}
+
+	if (state == _HWMOD_STATE_ENABLED)
+		hmux->enabled = true;
+	else
+		hmux->enabled = false;
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -461,7 +518,7 @@
 			seq_printf(s, "/* %s */\n", m->muxnames[mode]);
 
 		/*
-		 * XXX: Might be revisited to support differences accross
+		 * XXX: Might be revisited to support differences across
 		 * same OMAP generation.
 		 */
 		seq_printf(s, "OMAP%d_MUX(%s, ", omap_gen, m0_def);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/mux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/mux.h	2011-05-19 00:06:34.000000000 -0400
@@ -159,7 +159,6 @@
 	u16	value;
 };
 
-#define OMAP_DEVICE_PAD_ENABLED		BIT(7)	/* Not needed for board-*.c */
 #define OMAP_DEVICE_PAD_REMUX		BIT(1)	/* Dynamically remux a pad,
 						   needs enable, idle and off
 						   values */
@@ -187,6 +186,12 @@
 
 struct omap_hwmod_mux_info;
 
+#define OMAP_MUX_STATIC(signal, mode)					\
+{									\
+	.name	= (signal),						\
+	.enable	= (mode),						\
+}
+
 #if defined(CONFIG_OMAP_MUX)
 
 /**
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap44xx-smc.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap44xx-smc.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap44xx-smc.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap44xx-smc.S	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 	dsb
 	smc	#0
 	ldmfd   sp!, {r2-r12, pc}
-END(omap_smc1)
+ENDPROC(omap_smc1)
 
 ENTRY(omap_modify_auxcoreboot0)
 	stmfd   sp!, {r1-r12, lr}
@@ -37,7 +37,7 @@
 	dsb
 	smc	#0
 	ldmfd   sp!, {r1-r12, pc}
-END(omap_modify_auxcoreboot0)
+ENDPROC(omap_modify_auxcoreboot0)
 
 ENTRY(omap_auxcoreboot_addr)
 	stmfd   sp!, {r2-r12, lr}
@@ -45,7 +45,7 @@
 	dsb
 	smc	#0
 	ldmfd   sp!, {r2-r12, pc}
-END(omap_auxcoreboot_addr)
+ENDPROC(omap_auxcoreboot_addr)
 
 ENTRY(omap_read_auxcoreboot0)
 	stmfd   sp!, {r2-r12, lr}
@@ -54,4 +54,4 @@
 	smc	#0
 	mov	r0, r0, lsr #9
 	ldmfd   sp!, {r2-r12, pc}
-END(omap_read_auxcoreboot0)
+ENDPROC(omap_read_auxcoreboot0)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap4-common.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap4-common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap4-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap4-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,6 +52,12 @@
 	omap_smc1(0x102, 0x0);
 }
 
+static void omap4_l2x0_set_debug(unsigned long val)
+{
+	/* Program PL310 L2 Cache controller debug register */
+	omap_smc1(0x100, val);
+}
+
 static int __init omap_l2_cache_init(void)
 {
 	u32 aux_ctrl = 0;
@@ -99,6 +105,7 @@
 	 * specific one
 	*/
 	outer_cache.disable = omap4_l2x0_disable;
+	outer_cache.set_debug = omap4_l2x0_set_debug;
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap-headsmp.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap-headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap-headsmp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap-headsmp.S	2011-05-19 00:06:34.000000000 -0400
@@ -45,5 +45,5 @@
 	 * should now contain the SVC stack for this core
 	 */
 	b	secondary_startup
-END(omap_secondary_startup)
+ENDPROC(omap_secondary_startup)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_2420_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,10 @@
 #include <plat/serial.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
+#include <plat/mcspi.h>
+#include <plat/dmtimer.h>
+#include <plat/l3_2xxx.h>
+#include <plat/l4_2xxx.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -38,12 +42,18 @@
 static struct omap_hwmod omap2420_iva_hwmod;
 static struct omap_hwmod omap2420_l3_main_hwmod;
 static struct omap_hwmod omap2420_l4_core_hwmod;
+static struct omap_hwmod omap2420_dss_core_hwmod;
+static struct omap_hwmod omap2420_dss_dispc_hwmod;
+static struct omap_hwmod omap2420_dss_rfbi_hwmod;
+static struct omap_hwmod omap2420_dss_venc_hwmod;
 static struct omap_hwmod omap2420_wd_timer2_hwmod;
 static struct omap_hwmod omap2420_gpio1_hwmod;
 static struct omap_hwmod omap2420_gpio2_hwmod;
 static struct omap_hwmod omap2420_gpio3_hwmod;
 static struct omap_hwmod omap2420_gpio4_hwmod;
 static struct omap_hwmod omap2420_dma_system_hwmod;
+static struct omap_hwmod omap2420_mcspi1_hwmod;
+static struct omap_hwmod omap2420_mcspi2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2420_l3_main__l4_core = {
@@ -64,6 +74,19 @@
 	&omap2420_mpu__l3_main,
 };
 
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap2420_dss__l3 = {
+	.master		= &omap2420_dss_core_hwmod,
+	.slave		= &omap2420_l3_main_hwmod,
+	.fw = {
+		.omap2 = {
+			.l3_perm_bit  = OMAP2_L3_CORE_FW_CONNID_DSS,
+			.flags	= OMAP_FIREWALL_L3,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Master interfaces on the L3 interconnect */
 static struct omap_hwmod_ocp_if *omap2420_l3_main_masters[] = {
 	&omap2420_l3_main__l4_core,
@@ -87,6 +110,44 @@
 static struct omap_hwmod omap2420_uart3_hwmod;
 static struct omap_hwmod omap2420_i2c1_hwmod;
 static struct omap_hwmod omap2420_i2c2_hwmod;
+static struct omap_hwmod omap2420_mcbsp1_hwmod;
+static struct omap_hwmod omap2420_mcbsp2_hwmod;
+
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_addr_space omap2420_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480980ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi1 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcspi1_hwmod,
+	.clk		= "mcspi1_ick",
+	.addr		= omap2420_mcspi1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcspi1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_addr_space omap2420_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcspi2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcspi2_hwmod,
+	.clk		= "mcspi2_ick",
+	.addr		= omap2420_mcspi2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcspi2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
 
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap2420_l4_core__l4_wkup = {
@@ -279,6 +340,625 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
 };
 
+/* Timer Common */
+static struct omap_hwmod_class_sysconfig omap2420_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_timer_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap2420_timer_sysc,
+	.rev = OMAP_TIMER_IP_VERSION_1,
+};
+
+/* timer1 */
+static struct omap_hwmod omap2420_timer1_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer1_addrs[] = {
+	{
+		.pa_start	= 0x48028000,
+		.pa_end		= 0x48028000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap2420_l4_wkup__timer1 = {
+	.master		= &omap2420_l4_wkup_hwmod,
+	.slave		= &omap2420_timer1_hwmod,
+	.clk		= "gpt1_ick",
+	.addr		= omap2420_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer1_slaves[] = {
+	&omap2420_l4_wkup__timer1,
+};
+
+/* timer1 hwmod */
+static struct omap_hwmod omap2420_timer1_hwmod = {
+	.name		= "timer1",
+	.mpu_irqs	= omap2420_timer1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer1_mpu_irqs),
+	.main_clk	= "gpt1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer1_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer2 */
+static struct omap_hwmod omap2420_timer2_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4802a000,
+		.pa_end		= 0x4802a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer2 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer2_hwmod,
+	.clk		= "gpt2_ick",
+	.addr		= omap2420_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer2 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer2_slaves[] = {
+	&omap2420_l4_core__timer2,
+};
+
+/* timer2 hwmod */
+static struct omap_hwmod omap2420_timer2_hwmod = {
+	.name		= "timer2",
+	.mpu_irqs	= omap2420_timer2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer2_mpu_irqs),
+	.main_clk	= "gpt2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT2_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer2_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer3 */
+static struct omap_hwmod omap2420_timer3_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer3_addrs[] = {
+	{
+		.pa_start	= 0x48078000,
+		.pa_end		= 0x48078000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer3 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer3 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer3_hwmod,
+	.clk		= "gpt3_ick",
+	.addr		= omap2420_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer3 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer3_slaves[] = {
+	&omap2420_l4_core__timer3,
+};
+
+/* timer3 hwmod */
+static struct omap_hwmod omap2420_timer3_hwmod = {
+	.name		= "timer3",
+	.mpu_irqs	= omap2420_timer3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer3_mpu_irqs),
+	.main_clk	= "gpt3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT3_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer3_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer4 */
+static struct omap_hwmod omap2420_timer4_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer4_addrs[] = {
+	{
+		.pa_start	= 0x4807a000,
+		.pa_end		= 0x4807a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer4 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer4 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer4_hwmod,
+	.clk		= "gpt4_ick",
+	.addr		= omap2420_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer4 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer4_slaves[] = {
+	&omap2420_l4_core__timer4,
+};
+
+/* timer4 hwmod */
+static struct omap_hwmod omap2420_timer4_hwmod = {
+	.name		= "timer4",
+	.mpu_irqs	= omap2420_timer4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer4_mpu_irqs),
+	.main_clk	= "gpt4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT4_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer4_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer5 */
+static struct omap_hwmod omap2420_timer5_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer5_addrs[] = {
+	{
+		.pa_start	= 0x4807c000,
+		.pa_end		= 0x4807c000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer5 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer5 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer5_hwmod,
+	.clk		= "gpt5_ick",
+	.addr		= omap2420_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer5 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer5_slaves[] = {
+	&omap2420_l4_core__timer5,
+};
+
+/* timer5 hwmod */
+static struct omap_hwmod omap2420_timer5_hwmod = {
+	.name		= "timer5",
+	.mpu_irqs	= omap2420_timer5_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer5_mpu_irqs),
+	.main_clk	= "gpt5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer5_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+
+/* timer6 */
+static struct omap_hwmod omap2420_timer6_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4807e000,
+		.pa_end		= 0x4807e000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer6 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer6 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer6_hwmod,
+	.clk		= "gpt6_ick",
+	.addr		= omap2420_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer6 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer6_slaves[] = {
+	&omap2420_l4_core__timer6,
+};
+
+/* timer6 hwmod */
+static struct omap_hwmod omap2420_timer6_hwmod = {
+	.name		= "timer6",
+	.mpu_irqs	= omap2420_timer6_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer6_mpu_irqs),
+	.main_clk	= "gpt6_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT6_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer6_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer7 */
+static struct omap_hwmod omap2420_timer7_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer7_addrs[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer7 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer7 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer7_hwmod,
+	.clk		= "gpt7_ick",
+	.addr		= omap2420_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer7_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer7 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer7_slaves[] = {
+	&omap2420_l4_core__timer7,
+};
+
+/* timer7 hwmod */
+static struct omap_hwmod omap2420_timer7_hwmod = {
+	.name		= "timer7",
+	.mpu_irqs	= omap2420_timer7_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer7_mpu_irqs),
+	.main_clk	= "gpt7_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT7_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer7_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer8 */
+static struct omap_hwmod omap2420_timer8_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer8_addrs[] = {
+	{
+		.pa_start	= 0x48082000,
+		.pa_end		= 0x48082000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer8 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer8 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer8_hwmod,
+	.clk		= "gpt8_ick",
+	.addr		= omap2420_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer8_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer8 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer8_slaves[] = {
+	&omap2420_l4_core__timer8,
+};
+
+/* timer8 hwmod */
+static struct omap_hwmod omap2420_timer8_hwmod = {
+	.name		= "timer8",
+	.mpu_irqs	= omap2420_timer8_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer8_mpu_irqs),
+	.main_clk	= "gpt8_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT8_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer8_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer9 */
+static struct omap_hwmod omap2420_timer9_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer9_addrs[] = {
+	{
+		.pa_start	= 0x48084000,
+		.pa_end		= 0x48084000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer9 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer9 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer9_hwmod,
+	.clk		= "gpt9_ick",
+	.addr		= omap2420_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer9_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer9 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer9_slaves[] = {
+	&omap2420_l4_core__timer9,
+};
+
+/* timer9 hwmod */
+static struct omap_hwmod omap2420_timer9_hwmod = {
+	.name		= "timer9",
+	.mpu_irqs	= omap2420_timer9_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer9_mpu_irqs),
+	.main_clk	= "gpt9_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT9_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer9_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer10 */
+static struct omap_hwmod omap2420_timer10_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer10_addrs[] = {
+	{
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer10 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer10_hwmod,
+	.clk		= "gpt10_ick",
+	.addr		= omap2420_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer10_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer10 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer10_slaves[] = {
+	&omap2420_l4_core__timer10,
+};
+
+/* timer10 hwmod */
+static struct omap_hwmod omap2420_timer10_hwmod = {
+	.name		= "timer10",
+	.mpu_irqs	= omap2420_timer10_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer10_mpu_irqs),
+	.main_clk	= "gpt10_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT10_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer10_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer11 */
+static struct omap_hwmod omap2420_timer11_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer11_addrs[] = {
+	{
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer11 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer11_hwmod,
+	.clk		= "gpt11_ick",
+	.addr		= omap2420_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer11_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer11 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer11_slaves[] = {
+	&omap2420_l4_core__timer11,
+};
+
+/* timer11 hwmod */
+static struct omap_hwmod omap2420_timer11_hwmod = {
+	.name		= "timer11",
+	.mpu_irqs	= omap2420_timer11_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer11_mpu_irqs),
+	.main_clk	= "gpt11_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT11_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer11_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
+/* timer12 */
+static struct omap_hwmod omap2420_timer12_hwmod;
+static struct omap_hwmod_irq_info omap2420_timer12_mpu_irqs[] = {
+	{ .irq = 48, },
+};
+
+static struct omap_hwmod_addr_space omap2420_timer12_addrs[] = {
+	{
+		.pa_start	= 0x4808a000,
+		.pa_end		= 0x4808a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__timer12 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_timer12_hwmod,
+	.clk		= "gpt12_ick",
+	.addr		= omap2420_timer12_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_timer12_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer12 slave port */
+static struct omap_hwmod_ocp_if *omap2420_timer12_slaves[] = {
+	&omap2420_l4_core__timer12,
+};
+
+/* timer12 hwmod */
+static struct omap_hwmod omap2420_timer12_hwmod = {
+	.name		= "timer12",
+	.mpu_irqs	= omap2420_timer12_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_timer12_mpu_irqs),
+	.main_clk	= "gpt12_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT12_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
+		},
+	},
+	.slaves		= omap2420_timer12_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_timer12_slaves),
+	.class		= &omap2420_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420)
+};
+
 /* l4_wkup -> wd_timer2 */
 static struct omap_hwmod_addr_space omap2420_wd_timer2_addrs[] = {
 	{
@@ -308,7 +988,7 @@
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -349,7 +1029,7 @@
 	.syss_offs	= 0x58,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -470,12 +1150,297 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
 };
 
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dss_hwmod_class = {
+	.name = "dss",
+	.sysc = &omap2420_dss_sysc,
+};
+
+static struct omap_hwmod_dma_info omap2420_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_masters[] = {
+	&omap2420_dss__l3,
+};
+
+static struct omap_hwmod_addr_space omap2420_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x480503FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2420_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_slaves[] = {
+	&omap2420_l4_core__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+	{ .role = "sys_clk", .clk = "dss2_fck" },
+};
+
+static struct omap_hwmod omap2420_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap2420_dss_hwmod_class,
+	.main_clk	= "dss1_fck", /* instead of dss_fck */
+	.sdma_reqs	= omap2420_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_dss_sdma_chs),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap2420_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_slaves),
+	.masters	= omap2420_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2420_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_dispc_hwmod_class = {
+	.name = "dispc",
+	.sysc = &omap2420_dispc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap2420_dispc_irqs[] = {
+	{ .irq = 25 },
+};
+
+static struct omap_hwmod_addr_space omap2420_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x480507FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss_dispc = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_dispc_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2420_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_dispc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_DISPC_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_dispc_slaves[] = {
+	&omap2420_l4_core__dss_dispc,
+};
+
+static struct omap_hwmod omap2420_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap2420_dispc_hwmod_class,
+	.mpu_irqs	= omap2420_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_dispc_irqs),
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.slaves		= omap2420_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_dispc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_rfbi_hwmod_class = {
+	.name = "rfbi",
+	.sysc = &omap2420_rfbi_sysc,
+};
+
+static struct omap_hwmod_addr_space omap2420_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050BFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss_rfbi = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_rfbi_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2420_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_CORE_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_rfbi_slaves[] = {
+	&omap2420_l4_core__dss_rfbi,
+};
+
+static struct omap_hwmod omap2420_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap2420_rfbi_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+		},
+	},
+	.slaves		= omap2420_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap2420_venc_hwmod_class = {
+	.name = "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod_addr_space omap2420_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap2420_l4_core__dss_venc = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_dss_venc_hwmod,
+	.clk		= "dss_54m_fck",
+	.addr		= omap2420_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_dss_venc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP2420_L4_CORE_FW_DSS_VENC_REGION,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.flags		= OCPIF_SWSUP_IDLE,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap2420_dss_venc_slaves[] = {
+	&omap2420_l4_core__dss_venc,
+};
+
+static struct omap_hwmod omap2420_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap2420_venc_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+		},
+	},
+	.slaves		= omap2420_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 /* I2C common */
 static struct omap_hwmod_class_sysconfig i2c_sysc = {
 	.rev_offs	= 0x00,
 	.sysc_offs	= 0x20,
 	.syss_offs	= 0x10,
-	.sysc_flags	= SYSC_HAS_SOFTRESET,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -647,7 +1612,8 @@
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -673,6 +1639,7 @@
 
 static struct omap_hwmod omap2420_gpio1_hwmod = {
 	.name		= "gpio1",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap242x_gpio1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio1_irqs),
 	.main_clk	= "gpios_fck",
@@ -703,6 +1670,7 @@
 
 static struct omap_hwmod omap2420_gpio2_hwmod = {
 	.name		= "gpio2",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap242x_gpio2_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio2_irqs),
 	.main_clk	= "gpios_fck",
@@ -733,6 +1701,7 @@
 
 static struct omap_hwmod omap2420_gpio3_hwmod = {
 	.name		= "gpio3",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap242x_gpio3_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio3_irqs),
 	.main_clk	= "gpios_fck",
@@ -763,6 +1732,7 @@
 
 static struct omap_hwmod omap2420_gpio4_hwmod = {
 	.name		= "gpio4",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap242x_gpio4_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap242x_gpio4_irqs),
 	.main_clk	= "gpios_fck",
@@ -789,7 +1759,7 @@
 	.syss_offs	= 0x0028,
 	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
 			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
@@ -816,7 +1786,7 @@
 static struct omap_hwmod_addr_space omap2420_dma_system_addrs[] = {
 	{
 		.pa_start	= 0x48056000,
-		.pa_end		= 0x4a0560ff,
+		.pa_end		= 0x48056fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
@@ -864,16 +1834,342 @@
 	.flags		= HWMOD_NO_IDLEST,
 };
 
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_mailbox_hwmod_class = {
+	.name = "mailbox",
+	.sysc = &omap2420_mailbox_sysc,
+};
+
+/* mailbox */
+static struct omap_hwmod omap2420_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap2420_mailbox_irqs[] = {
+	{ .name = "dsp", .irq = 26 },
+	{ .name = "iva", .irq = 34 },
+};
+
+static struct omap_hwmod_addr_space omap2420_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x480941ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap2420_l4_core__mailbox = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mailbox_hwmod,
+	.addr		= omap2420_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap2420_mailbox_slaves[] = {
+	&omap2420_l4_core__mailbox,
+};
+
+static struct omap_hwmod omap2420_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap2420_mailbox_hwmod_class,
+	.mpu_irqs	= omap2420_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mailbox_irqs),
+	.main_clk	= "mailboxes_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2420_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2420_mcspi_class = {
+	.name = "mcspi",
+	.sysc = &omap2420_mcspi_sysc,
+	.rev = OMAP2_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod_irq_info omap2420_mcspi1_mpu_irqs[] = {
+	{ .irq = 65 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_mcspi1_slaves[] = {
+	&omap2420_l4_core__mcspi1,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+	.num_chipselect = 4,
+};
+
+static struct omap_hwmod omap2420_mcspi1_hwmod = {
+	.name		= "mcspi1_hwmod",
+	.mpu_irqs	= omap2420_mcspi1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcspi1_mpu_irqs),
+	.sdma_reqs	= omap2420_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi1_slaves),
+	.class		= &omap2420_mcspi_class,
+	.dev_attr       = &omap_mcspi1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* mcspi2 */
+static struct omap_hwmod_irq_info omap2420_mcspi2_mpu_irqs[] = {
+	{ .irq = 66 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2420_mcspi2_slaves[] = {
+	&omap2420_l4_core__mcspi2,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap2420_mcspi2_hwmod = {
+	.name		= "mcspi2_hwmod",
+	.mpu_irqs	= omap2420_mcspi2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcspi2_mpu_irqs),
+	.sdma_reqs	= omap2420_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcspi2_slaves),
+	.class		= &omap2420_mcspi_class,
+	.dev_attr       = &omap_mcspi2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class omap2420_mcbsp_hwmod_class = {
+	.name = "mcbsp",
+};
+
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap2420_mcbsp1_irqs[] = {
+	{ .name = "tx", .irq = 59 },
+	{ .name = "rx", .irq = 60 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcbsp1_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
+};
+
+static struct omap_hwmod_addr_space omap2420_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp1 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcbsp1_hwmod,
+	.clk		= "mcbsp1_ick",
+	.addr		= omap2420_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcbsp1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap2420_mcbsp1_slaves[] = {
+	&omap2420_l4_core__mcbsp1,
+};
+
+static struct omap_hwmod omap2420_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap2420_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2420_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcbsp1_irqs),
+	.sdma_reqs	= omap2420_mcbsp1_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcbsp1_sdma_chs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCBSP1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap2420_mcbsp2_irqs[] = {
+	{ .name = "tx", .irq = 62 },
+	{ .name = "rx", .irq = 63 },
+};
+
+static struct omap_hwmod_dma_info omap2420_mcbsp2_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
+};
+
+static struct omap_hwmod_addr_space omap2420_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48076000,
+		.pa_end		= 0x480760ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap2420_l4_core__mcbsp2 = {
+	.master		= &omap2420_l4_core_hwmod,
+	.slave		= &omap2420_mcbsp2_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap2420_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2420_mcbsp2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap2420_mcbsp2_slaves[] = {
+	&omap2420_l4_core__mcbsp2,
+};
+
+static struct omap_hwmod omap2420_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap2420_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2420_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2420_mcbsp2_irqs),
+	.sdma_reqs	= omap2420_mcbsp2_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2420_mcbsp2_sdma_chs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCBSP2_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap2420_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2420_mcbsp2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2420),
+};
+
 static __initdata struct omap_hwmod *omap2420_hwmods[] = {
 	&omap2420_l3_main_hwmod,
 	&omap2420_l4_core_hwmod,
 	&omap2420_l4_wkup_hwmod,
 	&omap2420_mpu_hwmod,
 	&omap2420_iva_hwmod,
+
+	&omap2420_timer1_hwmod,
+	&omap2420_timer2_hwmod,
+	&omap2420_timer3_hwmod,
+	&omap2420_timer4_hwmod,
+	&omap2420_timer5_hwmod,
+	&omap2420_timer6_hwmod,
+	&omap2420_timer7_hwmod,
+	&omap2420_timer8_hwmod,
+	&omap2420_timer9_hwmod,
+	&omap2420_timer10_hwmod,
+	&omap2420_timer11_hwmod,
+	&omap2420_timer12_hwmod,
+
 	&omap2420_wd_timer2_hwmod,
 	&omap2420_uart1_hwmod,
 	&omap2420_uart2_hwmod,
 	&omap2420_uart3_hwmod,
+	/* dss class */
+	&omap2420_dss_core_hwmod,
+	&omap2420_dss_dispc_hwmod,
+	&omap2420_dss_rfbi_hwmod,
+	&omap2420_dss_venc_hwmod,
+	/* i2c class */
 	&omap2420_i2c1_hwmod,
 	&omap2420_i2c2_hwmod,
 
@@ -885,10 +2181,21 @@
 
 	/* dma_system class*/
 	&omap2420_dma_system_hwmod,
+
+	/* mailbox class */
+	&omap2420_mailbox_hwmod,
+
+	/* mcbsp class */
+	&omap2420_mcbsp1_hwmod,
+	&omap2420_mcbsp2_hwmod,
+
+	/* mcspi class */
+	&omap2420_mcspi1_hwmod,
+	&omap2420_mcspi2_hwmod,
 	NULL,
 };
 
 int __init omap2420_hwmod_init(void)
 {
-	return omap_hwmod_init(omap2420_hwmods);
+	return omap_hwmod_register(omap2420_hwmods);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_2430_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,11 @@
 #include <plat/serial.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
+#include <plat/mcbsp.h>
+#include <plat/mcspi.h>
+#include <plat/dmtimer.h>
+#include <plat/mmc.h>
+#include <plat/l3_2xxx.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -38,6 +43,10 @@
 static struct omap_hwmod omap2430_iva_hwmod;
 static struct omap_hwmod omap2430_l3_main_hwmod;
 static struct omap_hwmod omap2430_l4_core_hwmod;
+static struct omap_hwmod omap2430_dss_core_hwmod;
+static struct omap_hwmod omap2430_dss_dispc_hwmod;
+static struct omap_hwmod omap2430_dss_rfbi_hwmod;
+static struct omap_hwmod omap2430_dss_venc_hwmod;
 static struct omap_hwmod omap2430_wd_timer2_hwmod;
 static struct omap_hwmod omap2430_gpio1_hwmod;
 static struct omap_hwmod omap2430_gpio2_hwmod;
@@ -45,6 +54,16 @@
 static struct omap_hwmod omap2430_gpio4_hwmod;
 static struct omap_hwmod omap2430_gpio5_hwmod;
 static struct omap_hwmod omap2430_dma_system_hwmod;
+static struct omap_hwmod omap2430_mcbsp1_hwmod;
+static struct omap_hwmod omap2430_mcbsp2_hwmod;
+static struct omap_hwmod omap2430_mcbsp3_hwmod;
+static struct omap_hwmod omap2430_mcbsp4_hwmod;
+static struct omap_hwmod omap2430_mcbsp5_hwmod;
+static struct omap_hwmod omap2430_mcspi1_hwmod;
+static struct omap_hwmod omap2430_mcspi2_hwmod;
+static struct omap_hwmod omap2430_mcspi3_hwmod;
+static struct omap_hwmod omap2430_mmc1_hwmod;
+static struct omap_hwmod omap2430_mmc2_hwmod;
 
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap2430_l3_main__l4_core = {
@@ -65,6 +84,19 @@
 	&omap2430_mpu__l3_main,
 };
 
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap2430_dss__l3 = {
+	.master		= &omap2430_dss_core_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.fw = {
+		.omap2 = {
+			.l3_perm_bit  = OMAP2_L3_CORE_FW_CONNID_DSS,
+			.flags	= OMAP_FIREWALL_L3,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Master interfaces on the L3 interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l3_main_masters[] = {
 	&omap2430_l3_main__l4_core,
@@ -89,6 +121,16 @@
 static struct omap_hwmod omap2430_i2c1_hwmod;
 static struct omap_hwmod omap2430_i2c2_hwmod;
 
+static struct omap_hwmod omap2430_usbhsotg_hwmod;
+
+/* l3_core -> usbhsotg  interface */
+static struct omap_hwmod_ocp_if omap2430_usbhsotg__l3 = {
+	.master		= &omap2430_usbhsotg_hwmod,
+	.slave		= &omap2430_l3_main_hwmod,
+	.clk		= "core_l3_ck",
+	.user		= OCP_USER_MPU,
+};
+
 /* I2C IP block address space length (in bytes) */
 #define OMAP2_I2C_AS_LEN		128
 
@@ -189,6 +231,71 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/*
+* usbhsotg interface data
+*/
+static struct omap_hwmod_addr_space omap2430_usbhsotg_addrs[] = {
+	{
+		.pa_start	= OMAP243X_HS_BASE,
+		.pa_end		= OMAP243X_HS_BASE + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/*  l4_core ->usbhsotg  interface */
+static struct omap_hwmod_ocp_if omap2430_l4_core__usbhsotg = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_usbhsotg_hwmod,
+	.clk		= "usb_l4_ick",
+	.addr		= omap2430_usbhsotg_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_usbhsotg_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if *omap2430_usbhsotg_masters[] = {
+	&omap2430_usbhsotg__l3,
+};
+
+static struct omap_hwmod_ocp_if *omap2430_usbhsotg_slaves[] = {
+	&omap2430_l4_core__usbhsotg,
+};
+
+/* L4 CORE -> MMC1 interface */
+static struct omap_hwmod_addr_space omap2430_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mmc1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mmc1_hwmod,
+	.clk		= "mmchs1_ick",
+	.addr		= omap2430_mmc1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mmc1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L4 CORE -> MMC2 interface */
+static struct omap_hwmod_addr_space omap2430_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b41ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mmc2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mmc2_hwmod,
+	.addr		= omap2430_mmc2_addr_space,
+	.clk		= "mmchs2_ick",
+	.addr_cnt	= ARRAY_SIZE(omap2430_mmc2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_slaves[] = {
 	&omap2430_l3_main__l4_core,
@@ -197,6 +304,8 @@
 /* Master interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap2430_l4_core_masters[] = {
 	&omap2430_l4_core__l4_wkup,
+	&omap2430_l4_core__mmc1,
+	&omap2430_l4_core__mmc2,
 };
 
 /* L4 CORE */
@@ -223,6 +332,60 @@
 static struct omap_hwmod_ocp_if *omap2430_l4_wkup_masters[] = {
 };
 
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_addr_space omap2430_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480980ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcspi1_hwmod,
+	.clk		= "mcspi1_ick",
+	.addr		= omap2430_mcspi1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_addr_space omap2430_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcspi2_hwmod,
+	.clk		= "mcspi2_ick",
+	.addr		= omap2430_mcspi2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi3 interface */
+static struct omap_hwmod_addr_space omap2430_mcspi3_addr_space[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b80ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcspi3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcspi3_hwmod,
+	.clk		= "mcspi3_ick",
+	.addr		= omap2430_mcspi3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcspi3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* L4 WKUP */
 static struct omap_hwmod omap2430_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
@@ -278,6 +441,624 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
 };
 
+/* Timer Common */
+static struct omap_hwmod_class_sysconfig omap2430_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_timer_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap2430_timer_sysc,
+	.rev = OMAP_TIMER_IP_VERSION_1,
+};
+
+/* timer1 */
+static struct omap_hwmod omap2430_timer1_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer1_addrs[] = {
+	{
+		.pa_start	= 0x49018000,
+		.pa_end		= 0x49018000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap2430_l4_wkup__timer1 = {
+	.master		= &omap2430_l4_wkup_hwmod,
+	.slave		= &omap2430_timer1_hwmod,
+	.clk		= "gpt1_ick",
+	.addr		= omap2430_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer1_slaves[] = {
+	&omap2430_l4_wkup__timer1,
+};
+
+/* timer1 hwmod */
+static struct omap_hwmod omap2430_timer1_hwmod = {
+	.name		= "timer1",
+	.mpu_irqs	= omap2430_timer1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer1_mpu_irqs),
+	.main_clk	= "gpt1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer1_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer2 */
+static struct omap_hwmod omap2430_timer2_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer2_addrs[] = {
+	{
+		.pa_start	= 0x4802a000,
+		.pa_end		= 0x4802a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer2 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer2_hwmod,
+	.clk		= "gpt2_ick",
+	.addr		= omap2430_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer2 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer2_slaves[] = {
+	&omap2430_l4_core__timer2,
+};
+
+/* timer2 hwmod */
+static struct omap_hwmod omap2430_timer2_hwmod = {
+	.name		= "timer2",
+	.mpu_irqs	= omap2430_timer2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer2_mpu_irqs),
+	.main_clk	= "gpt2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT2_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer2_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer3 */
+static struct omap_hwmod omap2430_timer3_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer3_addrs[] = {
+	{
+		.pa_start	= 0x48078000,
+		.pa_end		= 0x48078000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer3 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer3_hwmod,
+	.clk		= "gpt3_ick",
+	.addr		= omap2430_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer3 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer3_slaves[] = {
+	&omap2430_l4_core__timer3,
+};
+
+/* timer3 hwmod */
+static struct omap_hwmod omap2430_timer3_hwmod = {
+	.name		= "timer3",
+	.mpu_irqs	= omap2430_timer3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer3_mpu_irqs),
+	.main_clk	= "gpt3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT3_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT3_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer3_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer4 */
+static struct omap_hwmod omap2430_timer4_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer4_addrs[] = {
+	{
+		.pa_start	= 0x4807a000,
+		.pa_end		= 0x4807a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer4 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer4 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer4_hwmod,
+	.clk		= "gpt4_ick",
+	.addr		= omap2430_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer4 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer4_slaves[] = {
+	&omap2430_l4_core__timer4,
+};
+
+/* timer4 hwmod */
+static struct omap_hwmod omap2430_timer4_hwmod = {
+	.name		= "timer4",
+	.mpu_irqs	= omap2430_timer4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer4_mpu_irqs),
+	.main_clk	= "gpt4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT4_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT4_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer4_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer5 */
+static struct omap_hwmod omap2430_timer5_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer5_addrs[] = {
+	{
+		.pa_start	= 0x4807c000,
+		.pa_end		= 0x4807c000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer5 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer5 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer5_hwmod,
+	.clk		= "gpt5_ick",
+	.addr		= omap2430_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer5 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer5_slaves[] = {
+	&omap2430_l4_core__timer5,
+};
+
+/* timer5 hwmod */
+static struct omap_hwmod omap2430_timer5_hwmod = {
+	.name		= "timer5",
+	.mpu_irqs	= omap2430_timer5_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer5_mpu_irqs),
+	.main_clk	= "gpt5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT5_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer5_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer6 */
+static struct omap_hwmod omap2430_timer6_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4807e000,
+		.pa_end		= 0x4807e000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer6 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer6 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer6_hwmod,
+	.clk		= "gpt6_ick",
+	.addr		= omap2430_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer6 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer6_slaves[] = {
+	&omap2430_l4_core__timer6,
+};
+
+/* timer6 hwmod */
+static struct omap_hwmod omap2430_timer6_hwmod = {
+	.name		= "timer6",
+	.mpu_irqs	= omap2430_timer6_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer6_mpu_irqs),
+	.main_clk	= "gpt6_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT6_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT6_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer6_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer7 */
+static struct omap_hwmod omap2430_timer7_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer7_addrs[] = {
+	{
+		.pa_start	= 0x48080000,
+		.pa_end		= 0x48080000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer7 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer7 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer7_hwmod,
+	.clk		= "gpt7_ick",
+	.addr		= omap2430_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer7_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer7 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer7_slaves[] = {
+	&omap2430_l4_core__timer7,
+};
+
+/* timer7 hwmod */
+static struct omap_hwmod omap2430_timer7_hwmod = {
+	.name		= "timer7",
+	.mpu_irqs	= omap2430_timer7_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer7_mpu_irqs),
+	.main_clk	= "gpt7_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT7_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT7_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer7_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer8 */
+static struct omap_hwmod omap2430_timer8_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer8_addrs[] = {
+	{
+		.pa_start	= 0x48082000,
+		.pa_end		= 0x48082000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer8 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer8 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer8_hwmod,
+	.clk		= "gpt8_ick",
+	.addr		= omap2430_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer8_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer8 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer8_slaves[] = {
+	&omap2430_l4_core__timer8,
+};
+
+/* timer8 hwmod */
+static struct omap_hwmod omap2430_timer8_hwmod = {
+	.name		= "timer8",
+	.mpu_irqs	= omap2430_timer8_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer8_mpu_irqs),
+	.main_clk	= "gpt8_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT8_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT8_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer8_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer9 */
+static struct omap_hwmod omap2430_timer9_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer9_addrs[] = {
+	{
+		.pa_start	= 0x48084000,
+		.pa_end		= 0x48084000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer9 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer9 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer9_hwmod,
+	.clk		= "gpt9_ick",
+	.addr		= omap2430_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer9_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer9 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer9_slaves[] = {
+	&omap2430_l4_core__timer9,
+};
+
+/* timer9 hwmod */
+static struct omap_hwmod omap2430_timer9_hwmod = {
+	.name		= "timer9",
+	.mpu_irqs	= omap2430_timer9_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer9_mpu_irqs),
+	.main_clk	= "gpt9_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT9_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT9_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer9_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer10 */
+static struct omap_hwmod omap2430_timer10_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer10_addrs[] = {
+	{
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer10 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer10_hwmod,
+	.clk		= "gpt10_ick",
+	.addr		= omap2430_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer10_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer10 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer10_slaves[] = {
+	&omap2430_l4_core__timer10,
+};
+
+/* timer10 hwmod */
+static struct omap_hwmod omap2430_timer10_hwmod = {
+	.name		= "timer10",
+	.mpu_irqs	= omap2430_timer10_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer10_mpu_irqs),
+	.main_clk	= "gpt10_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT10_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT10_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer10_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer11 */
+static struct omap_hwmod omap2430_timer11_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer11_addrs[] = {
+	{
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer11 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer11_hwmod,
+	.clk		= "gpt11_ick",
+	.addr		= omap2430_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer11_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer11 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer11_slaves[] = {
+	&omap2430_l4_core__timer11,
+};
+
+/* timer11 hwmod */
+static struct omap_hwmod omap2430_timer11_hwmod = {
+	.name		= "timer11",
+	.mpu_irqs	= omap2430_timer11_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer11_mpu_irqs),
+	.main_clk	= "gpt11_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT11_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT11_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer11_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/* timer12 */
+static struct omap_hwmod omap2430_timer12_hwmod;
+static struct omap_hwmod_irq_info omap2430_timer12_mpu_irqs[] = {
+	{ .irq = 48, },
+};
+
+static struct omap_hwmod_addr_space omap2430_timer12_addrs[] = {
+	{
+		.pa_start	= 0x4808a000,
+		.pa_end		= 0x4808a000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__timer12 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_timer12_hwmod,
+	.clk		= "gpt12_ick",
+	.addr		= omap2430_timer12_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_timer12_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer12 slave port */
+static struct omap_hwmod_ocp_if *omap2430_timer12_slaves[] = {
+	&omap2430_l4_core__timer12,
+};
+
+/* timer12 hwmod */
+static struct omap_hwmod omap2430_timer12_hwmod = {
+	.name		= "timer12",
+	.mpu_irqs	= omap2430_timer12_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_timer12_mpu_irqs),
+	.main_clk	= "gpt12_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_GPT12_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_GPT12_SHIFT,
+		},
+	},
+	.slaves		= omap2430_timer12_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_timer12_slaves),
+	.class		= &omap2430_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
 /* l4_wkup -> wd_timer2 */
 static struct omap_hwmod_addr_space omap2430_wd_timer2_addrs[] = {
 	{
@@ -307,7 +1088,7 @@
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
 
@@ -348,7 +1129,7 @@
 	.syss_offs	= 0x58,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -469,12 +1250,274 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 };
 
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dss_hwmod_class = {
+	.name = "dss",
+	.sysc = &omap2430_dss_sysc,
+};
+
+static struct omap_hwmod_dma_info omap2430_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_masters[] = {
+	&omap2430_dss__l3,
+};
+
+static struct omap_hwmod_addr_space omap2430_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x480503FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2430_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_slaves[] = {
+	&omap2430_l4_core__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_54m_fck" },
+	{ .role = "sys_clk", .clk = "dss2_fck" },
+};
+
+static struct omap_hwmod omap2430_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap2430_dss_hwmod_class,
+	.main_clk	= "dss1_fck", /* instead of dss_fck */
+	.sdma_reqs	= omap2430_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_dss_sdma_chs),
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap2430_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_slaves),
+	.masters	= omap2430_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_dispc_hwmod_class = {
+	.name = "dispc",
+	.sysc = &omap2430_dispc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap2430_dispc_irqs[] = {
+	{ .irq = 25 },
+};
+
+static struct omap_hwmod_addr_space omap2430_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x480507FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss_dispc = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_dispc_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2430_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_dispc_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_dispc_slaves[] = {
+	&omap2430_l4_core__dss_dispc,
+};
+
+static struct omap_hwmod omap2430_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap2430_dispc_hwmod_class,
+	.mpu_irqs	= omap2430_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_dispc_irqs),
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP24XX_ST_DSS_SHIFT,
+		},
+	},
+	.slaves		= omap2430_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_dispc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_rfbi_hwmod_class = {
+	.name = "rfbi",
+	.sysc = &omap2430_rfbi_sysc,
+};
+
+static struct omap_hwmod_addr_space omap2430_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050BFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss_rfbi = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_rfbi_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap2430_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_rfbi_slaves[] = {
+	&omap2430_l4_core__dss_rfbi,
+};
+
+static struct omap_hwmod omap2430_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap2430_rfbi_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+		},
+	},
+	.slaves		= omap2430_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap2430_venc_hwmod_class = {
+	.name = "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod_addr_space omap2430_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap2430_l4_core__dss_venc = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_dss_venc_hwmod,
+	.clk		= "dss_54m_fck",
+	.addr		= omap2430_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_dss_venc_addrs),
+	.flags		= OCPIF_SWSUP_IDLE,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap2430_dss_venc_slaves[] = {
+	&omap2430_l4_core__dss_venc,
+};
+
+static struct omap_hwmod omap2430_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap2430_venc_hwmod_class,
+	.main_clk	= "dss1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_DSS1_SHIFT,
+			.module_offs = CORE_MOD,
+		},
+	},
+	.slaves		= omap2430_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 /* I2C common */
 static struct omap_hwmod_class_sysconfig i2c_sysc = {
 	.rev_offs	= 0x00,
 	.sysc_offs	= 0x20,
 	.syss_offs	= 0x10,
-	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
 
@@ -516,7 +1559,7 @@
 			 * I2CHS IP's do not follow the usual pattern.
 			 * prcm_reg_id alone cannot be used to program
 			 * the iclk and fclk. Needs to be handled using
-			 * additonal flags when clk handling is moved
+			 * additional flags when clk handling is moved
 			 * to hwmod framework.
 			 */
 			.module_offs = CORE_MOD,
@@ -672,7 +1715,8 @@
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -698,6 +1742,7 @@
 
 static struct omap_hwmod omap2430_gpio1_hwmod = {
 	.name		= "gpio1",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap243x_gpio1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio1_irqs),
 	.main_clk	= "gpios_fck",
@@ -728,6 +1773,7 @@
 
 static struct omap_hwmod omap2430_gpio2_hwmod = {
 	.name		= "gpio2",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap243x_gpio2_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio2_irqs),
 	.main_clk	= "gpios_fck",
@@ -758,6 +1804,7 @@
 
 static struct omap_hwmod omap2430_gpio3_hwmod = {
 	.name		= "gpio3",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap243x_gpio3_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio3_irqs),
 	.main_clk	= "gpios_fck",
@@ -788,6 +1835,7 @@
 
 static struct omap_hwmod omap2430_gpio4_hwmod = {
 	.name		= "gpio4",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap243x_gpio4_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio4_irqs),
 	.main_clk	= "gpios_fck",
@@ -818,6 +1866,7 @@
 
 static struct omap_hwmod omap2430_gpio5_hwmod = {
 	.name		= "gpio5",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap243x_gpio5_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap243x_gpio5_irqs),
 	.main_clk	= "gpio5_fck",
@@ -844,7 +1893,7 @@
 	.syss_offs	= 0x0028,
 	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_MIDLEMODE |
 			   SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_EMUFREE |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
 };
@@ -871,7 +1920,7 @@
 static struct omap_hwmod_addr_space omap2430_dma_system_addrs[] = {
 	{
 		.pa_start	= 0x48056000,
-		.pa_end		= 0x4a0560ff,
+		.pa_end		= 0x48056fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
@@ -919,18 +1968,741 @@
 	.flags		= HWMOD_NO_IDLEST,
 };
 
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mailbox_hwmod_class = {
+	.name = "mailbox",
+	.sysc = &omap2430_mailbox_sysc,
+};
+
+/* mailbox */
+static struct omap_hwmod omap2430_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap2430_mailbox_irqs[] = {
+	{ .irq = 26 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x480941ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mailbox = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mailbox_hwmod,
+	.addr		= omap2430_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mailbox_slaves[] = {
+	&omap2430_l4_core__mailbox,
+};
+
+static struct omap_hwmod omap2430_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap2430_mailbox_hwmod_class,
+	.mpu_irqs	= omap2430_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mailbox_irqs),
+	.main_clk	= "mailboxes_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MAILBOXES_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MAILBOXES_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mcspi_class = {
+	.name = "mcspi",
+	.sysc = &omap2430_mcspi_sysc,
+	.rev = OMAP2_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod_irq_info omap2430_mcspi1_mpu_irqs[] = {
+	{ .irq = 65 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 }, /* DMA_SPI1_TX0 */
+	{ .name = "rx0", .dma_req = 36 }, /* DMA_SPI1_RX0 */
+	{ .name = "tx1", .dma_req = 37 }, /* DMA_SPI1_TX1 */
+	{ .name = "rx1", .dma_req = 38 }, /* DMA_SPI1_RX1 */
+	{ .name = "tx2", .dma_req = 39 }, /* DMA_SPI1_TX2 */
+	{ .name = "rx2", .dma_req = 40 }, /* DMA_SPI1_RX2 */
+	{ .name = "tx3", .dma_req = 41 }, /* DMA_SPI1_TX3 */
+	{ .name = "rx3", .dma_req = 42 }, /* DMA_SPI1_RX3 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mcspi1_slaves[] = {
+	&omap2430_l4_core__mcspi1,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+	.num_chipselect = 4,
+};
+
+static struct omap_hwmod omap2430_mcspi1_hwmod = {
+	.name		= "mcspi1_hwmod",
+	.mpu_irqs	= omap2430_mcspi1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi1_mpu_irqs),
+	.sdma_reqs	= omap2430_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi1_slaves),
+	.class		= &omap2430_mcspi_class,
+	.dev_attr       = &omap_mcspi1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcspi2 */
+static struct omap_hwmod_irq_info omap2430_mcspi2_mpu_irqs[] = {
+	{ .irq = 66 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 }, /* DMA_SPI2_TX0 */
+	{ .name = "rx0", .dma_req = 44 }, /* DMA_SPI2_RX0 */
+	{ .name = "tx1", .dma_req = 45 }, /* DMA_SPI2_TX1 */
+	{ .name = "rx1", .dma_req = 46 }, /* DMA_SPI2_RX1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mcspi2_slaves[] = {
+	&omap2430_l4_core__mcspi2,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap2430_mcspi2_hwmod = {
+	.name		= "mcspi2_hwmod",
+	.mpu_irqs	= omap2430_mcspi2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi2_mpu_irqs),
+	.sdma_reqs	= omap2430_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCSPI2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCSPI2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi2_slaves),
+	.class		= &omap2430_mcspi_class,
+	.dev_attr       = &omap_mcspi2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcspi3 */
+static struct omap_hwmod_irq_info omap2430_mcspi3_mpu_irqs[] = {
+	{ .irq = 91 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcspi3_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 15 }, /* DMA_SPI3_TX0 */
+	{ .name = "rx0", .dma_req = 16 }, /* DMA_SPI3_RX0 */
+	{ .name = "tx1", .dma_req = 23 }, /* DMA_SPI3_TX1 */
+	{ .name = "rx1", .dma_req = 24 }, /* DMA_SPI3_RX1 */
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mcspi3_slaves[] = {
+	&omap2430_l4_core__mcspi3,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap2430_mcspi3_hwmod = {
+	.name		= "mcspi3_hwmod",
+	.mpu_irqs	= omap2430_mcspi3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcspi3_mpu_irqs),
+	.sdma_reqs	= omap2430_mcspi3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcspi3_sdma_reqs),
+	.main_clk	= "mcspi3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit = OMAP2430_EN_MCSPI3_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCSPI3_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcspi3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcspi3_slaves),
+	.class		= &omap2430_mcspi_class,
+	.dev_attr       = &omap_mcspi3_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/*
+ * usbhsotg
+ */
+static struct omap_hwmod_class_sysconfig omap2430_usbhsotg_sysc = {
+	.rev_offs	= 0x0400,
+	.sysc_offs	= 0x0404,
+	.syss_offs	= 0x0408,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE|
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class usbotg_class = {
+	.name = "usbotg",
+	.sysc = &omap2430_usbhsotg_sysc,
+};
+
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info omap2430_usbhsotg_mpu_irqs[] = {
+
+	{ .name = "mc", .irq = 92 },
+	{ .name = "dma", .irq = 93 },
+};
+
+static struct omap_hwmod omap2430_usbhsotg_hwmod = {
+	.name		= "usb_otg_hs",
+	.mpu_irqs	= omap2430_usbhsotg_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_usbhsotg_mpu_irqs),
+	.main_clk	= "usbhs_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_USBHS_MASK,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP2430_ST_USBHS_SHIFT,
+		},
+	},
+	.masters	= omap2430_usbhsotg_masters,
+	.masters_cnt	= ARRAY_SIZE(omap2430_usbhsotg_masters),
+	.slaves		= omap2430_usbhsotg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_usbhsotg_slaves),
+	.class		= &usbotg_class,
+	/*
+	 * Erratum ID: i479  idle_req / idle_ack mechanism potentially
+	 * broken when autoidle is enabled
+	 * workaround is to disable the autoidle bit at module level.
+	 */
+	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
+				| HWMOD_SWSUP_MSTANDBY,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430)
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap2430_mcbsp_sysc = {
+	.rev_offs	= 0x007C,
+	.sysc_offs	= 0x008C,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mcbsp_hwmod_class = {
+	.name = "mcbsp",
+	.sysc = &omap2430_mcbsp_sysc,
+	.rev  = MCBSP_CONFIG_TYPE2,
+};
+
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap2430_mcbsp1_irqs[] = {
+	{ .name = "tx",		.irq = 59 },
+	{ .name = "rx",		.irq = 60 },
+	{ .name = "ovr",	.irq = 61 },
+	{ .name = "common",	.irq = 64 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcbsp1_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp1 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp1_hwmod,
+	.clk		= "mcbsp1_ick",
+	.addr		= omap2430_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp1_slaves[] = {
+	&omap2430_l4_core__mcbsp1,
+};
+
+static struct omap_hwmod omap2430_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp1_irqs),
+	.sdma_reqs	= omap2430_mcbsp1_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp1_sdma_chs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCBSP1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP1_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap2430_mcbsp2_irqs[] = {
+	{ .name = "tx",		.irq = 62 },
+	{ .name = "rx",		.irq = 63 },
+	{ .name = "common",	.irq = 16 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcbsp2_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48076000,
+		.pa_end		= 0x480760ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp2 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp2_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap2430_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp2_slaves[] = {
+	&omap2430_l4_core__mcbsp2,
+};
+
+static struct omap_hwmod omap2430_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp2_irqs),
+	.sdma_reqs	= omap2430_mcbsp2_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp2_sdma_chs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP24XX_EN_MCBSP2_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP24XX_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcbsp3 */
+static struct omap_hwmod_irq_info omap2430_mcbsp3_irqs[] = {
+	{ .name = "tx",		.irq = 89 },
+	{ .name = "rx",		.irq = 90 },
+	{ .name = "common",	.irq = 17 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcbsp3_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 18 },
+	{ .name = "tx", .dma_req = 17 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp3_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x4808C000,
+		.pa_end		= 0x4808C0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp3 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp3_hwmod,
+	.clk		= "mcbsp3_ick",
+	.addr		= omap2430_mcbsp3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp3 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp3_slaves[] = {
+	&omap2430_l4_core__mcbsp3,
+};
+
+static struct omap_hwmod omap2430_mcbsp3_hwmod = {
+	.name		= "mcbsp3",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp3_irqs),
+	.sdma_reqs	= omap2430_mcbsp3_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp3_sdma_chs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_MCBSP3_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCBSP3_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcbsp3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcbsp4 */
+static struct omap_hwmod_irq_info omap2430_mcbsp4_irqs[] = {
+	{ .name = "tx",		.irq = 54 },
+	{ .name = "rx",		.irq = 55 },
+	{ .name = "common",	.irq = 18 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcbsp4_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 20 },
+	{ .name = "tx", .dma_req = 19 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp4_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x4808E000,
+		.pa_end		= 0x4808E0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp4 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp4_hwmod,
+	.clk		= "mcbsp4_ick",
+	.addr		= omap2430_mcbsp4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp4 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp4_slaves[] = {
+	&omap2430_l4_core__mcbsp4,
+};
+
+static struct omap_hwmod omap2430_mcbsp4_hwmod = {
+	.name		= "mcbsp4",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp4_irqs),
+	.sdma_reqs	= omap2430_mcbsp4_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp4_sdma_chs),
+	.main_clk	= "mcbsp4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_MCBSP4_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCBSP4_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcbsp4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* mcbsp5 */
+static struct omap_hwmod_irq_info omap2430_mcbsp5_irqs[] = {
+	{ .name = "tx",		.irq = 81 },
+	{ .name = "rx",		.irq = 82 },
+	{ .name = "common",	.irq = 19 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mcbsp5_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 22 },
+	{ .name = "tx", .dma_req = 21 },
+};
+
+static struct omap_hwmod_addr_space omap2430_mcbsp5_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48096000,
+		.pa_end		= 0x480960ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp5 */
+static struct omap_hwmod_ocp_if omap2430_l4_core__mcbsp5 = {
+	.master		= &omap2430_l4_core_hwmod,
+	.slave		= &omap2430_mcbsp5_hwmod,
+	.clk		= "mcbsp5_ick",
+	.addr		= omap2430_mcbsp5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap2430_mcbsp5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp5 slave ports */
+static struct omap_hwmod_ocp_if *omap2430_mcbsp5_slaves[] = {
+	&omap2430_l4_core__mcbsp5,
+};
+
+static struct omap_hwmod omap2430_mcbsp5_hwmod = {
+	.name		= "mcbsp5",
+	.class		= &omap2430_mcbsp_hwmod_class,
+	.mpu_irqs	= omap2430_mcbsp5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mcbsp5_irqs),
+	.sdma_reqs	= omap2430_mcbsp5_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mcbsp5_sdma_chs),
+	.main_clk	= "mcbsp5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP2430_EN_MCBSP5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MCBSP5_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mcbsp5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mcbsp5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* MMC/SD/SDIO common */
+
+static struct omap_hwmod_class_sysconfig omap2430_mmc_sysc = {
+	.rev_offs	= 0x1fc,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap2430_mmc_class = {
+	.name = "mmc",
+	.sysc = &omap2430_mmc_sysc,
+};
+
+/* MMC/SD/SDIO1 */
+
+static struct omap_hwmod_irq_info omap2430_mmc1_mpu_irqs[] = {
+	{ .irq = 83 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mmc1_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 61 }, /* DMA_MMC1_TX */
+	{ .name = "rx",	.dma_req = 62 }, /* DMA_MMC1_RX */
+};
+
+static struct omap_hwmod_opt_clk omap2430_mmc1_opt_clks[] = {
+	{ .role = "dbck", .clk = "mmchsdb1_fck" },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mmc1_slaves[] = {
+	&omap2430_l4_core__mmc1,
+};
+
+static struct omap_mmc_dev_attr mmc1_dev_attr = {
+	.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod omap2430_mmc1_hwmod = {
+	.name		= "mmc1",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap2430_mmc1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mmc1_mpu_irqs),
+	.sdma_reqs	= omap2430_mmc1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mmc1_sdma_reqs),
+	.opt_clks	= omap2430_mmc1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap2430_mmc1_opt_clks),
+	.main_clk	= "mmchs1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit  = OMAP2430_EN_MMCHS1_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MMCHS1_SHIFT,
+		},
+	},
+	.dev_attr	= &mmc1_dev_attr,
+	.slaves		= omap2430_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc1_slaves),
+	.class		= &omap2430_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
+/* MMC/SD/SDIO2 */
+
+static struct omap_hwmod_irq_info omap2430_mmc2_mpu_irqs[] = {
+	{ .irq = 86 },
+};
+
+static struct omap_hwmod_dma_info omap2430_mmc2_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 47 }, /* DMA_MMC2_TX */
+	{ .name = "rx",	.dma_req = 48 }, /* DMA_MMC2_RX */
+};
+
+static struct omap_hwmod_opt_clk omap2430_mmc2_opt_clks[] = {
+	{ .role = "dbck", .clk = "mmchsdb2_fck" },
+};
+
+static struct omap_hwmod_ocp_if *omap2430_mmc2_slaves[] = {
+	&omap2430_l4_core__mmc2,
+};
+
+static struct omap_hwmod omap2430_mmc2_hwmod = {
+	.name		= "mmc2",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
+	.mpu_irqs	= omap2430_mmc2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap2430_mmc2_mpu_irqs),
+	.sdma_reqs	= omap2430_mmc2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap2430_mmc2_sdma_reqs),
+	.opt_clks	= omap2430_mmc2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap2430_mmc2_opt_clks),
+	.main_clk	= "mmchs2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 2,
+			.module_bit  = OMAP2430_EN_MMCHS2_SHIFT,
+			.idlest_reg_id = 2,
+			.idlest_idle_bit = OMAP2430_ST_MMCHS2_SHIFT,
+		},
+	},
+	.slaves		= omap2430_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap2430_mmc2_slaves),
+	.class		= &omap2430_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
+};
+
 static __initdata struct omap_hwmod *omap2430_hwmods[] = {
 	&omap2430_l3_main_hwmod,
 	&omap2430_l4_core_hwmod,
 	&omap2430_l4_wkup_hwmod,
 	&omap2430_mpu_hwmod,
 	&omap2430_iva_hwmod,
+
+	&omap2430_timer1_hwmod,
+	&omap2430_timer2_hwmod,
+	&omap2430_timer3_hwmod,
+	&omap2430_timer4_hwmod,
+	&omap2430_timer5_hwmod,
+	&omap2430_timer6_hwmod,
+	&omap2430_timer7_hwmod,
+	&omap2430_timer8_hwmod,
+	&omap2430_timer9_hwmod,
+	&omap2430_timer10_hwmod,
+	&omap2430_timer11_hwmod,
+	&omap2430_timer12_hwmod,
+
 	&omap2430_wd_timer2_hwmod,
 	&omap2430_uart1_hwmod,
 	&omap2430_uart2_hwmod,
 	&omap2430_uart3_hwmod,
+	/* dss class */
+	&omap2430_dss_core_hwmod,
+	&omap2430_dss_dispc_hwmod,
+	&omap2430_dss_rfbi_hwmod,
+	&omap2430_dss_venc_hwmod,
+	/* i2c class */
 	&omap2430_i2c1_hwmod,
 	&omap2430_i2c2_hwmod,
+	&omap2430_mmc1_hwmod,
+	&omap2430_mmc2_hwmod,
 
 	/* gpio class */
 	&omap2430_gpio1_hwmod,
@@ -941,10 +2713,29 @@
 
 	/* dma_system class*/
 	&omap2430_dma_system_hwmod,
+
+	/* mcbsp class */
+	&omap2430_mcbsp1_hwmod,
+	&omap2430_mcbsp2_hwmod,
+	&omap2430_mcbsp3_hwmod,
+	&omap2430_mcbsp4_hwmod,
+	&omap2430_mcbsp5_hwmod,
+
+	/* mailbox class */
+	&omap2430_mailbox_hwmod,
+
+	/* mcspi class */
+	&omap2430_mcspi1_hwmod,
+	&omap2430_mcspi2_hwmod,
+	&omap2430_mcspi3_hwmod,
+
+	/* usbotg class*/
+	&omap2430_usbhsotg_hwmod,
+
 	NULL,
 };
 
 int __init omap2430_hwmod_init(void)
 {
-	return omap_hwmod_init(omap2430_hwmods);
+	return omap_hwmod_register(omap2430_hwmods);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,16 +18,21 @@
 #include <plat/cpu.h>
 #include <plat/dma.h>
 #include <plat/serial.h>
+#include <plat/l3_3xxx.h>
 #include <plat/l4_3xxx.h>
 #include <plat/i2c.h>
 #include <plat/gpio.h>
-#include <plat/smartreflex.h>
+#include <plat/mmc.h>
+#include <plat/mcbsp.h>
+#include <plat/mcspi.h>
+#include <plat/dmtimer.h>
 
 #include "omap_hwmod_common_data.h"
 
 #include "prm-regbits-34xx.h"
 #include "cm-regbits-34xx.h"
 #include "wd_timer.h"
+#include <mach/am35xx.h>
 
 /*
  * OMAP3xxx hardware module integration data
@@ -44,6 +49,12 @@
 static struct omap_hwmod omap3xxx_l4_core_hwmod;
 static struct omap_hwmod omap3xxx_l4_per_hwmod;
 static struct omap_hwmod omap3xxx_wd_timer2_hwmod;
+static struct omap_hwmod omap3430es1_dss_core_hwmod;
+static struct omap_hwmod omap3xxx_dss_core_hwmod;
+static struct omap_hwmod omap3xxx_dss_dispc_hwmod;
+static struct omap_hwmod omap3xxx_dss_dsi1_hwmod;
+static struct omap_hwmod omap3xxx_dss_rfbi_hwmod;
+static struct omap_hwmod omap3xxx_dss_venc_hwmod;
 static struct omap_hwmod omap3xxx_i2c1_hwmod;
 static struct omap_hwmod omap3xxx_i2c2_hwmod;
 static struct omap_hwmod omap3xxx_i2c3_hwmod;
@@ -55,9 +66,25 @@
 static struct omap_hwmod omap3xxx_gpio6_hwmod;
 static struct omap_hwmod omap34xx_sr1_hwmod;
 static struct omap_hwmod omap34xx_sr2_hwmod;
+static struct omap_hwmod omap34xx_mcspi1;
+static struct omap_hwmod omap34xx_mcspi2;
+static struct omap_hwmod omap34xx_mcspi3;
+static struct omap_hwmod omap34xx_mcspi4;
+static struct omap_hwmod omap3xxx_mmc1_hwmod;
+static struct omap_hwmod omap3xxx_mmc2_hwmod;
+static struct omap_hwmod omap3xxx_mmc3_hwmod;
+static struct omap_hwmod am35xx_usbhsotg_hwmod;
 
 static struct omap_hwmod omap3xxx_dma_system_hwmod;
 
+static struct omap_hwmod omap3xxx_mcbsp1_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp2_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp3_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp4_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp5_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod;
+static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod;
+
 /* L3 -> L4_CORE interface */
 static struct omap_hwmod_ocp_if omap3xxx_l3_main__l4_core = {
 	.master	= &omap3xxx_l3_main_hwmod,
@@ -72,10 +99,26 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L3 taret configuration and error log registers */
+static struct omap_hwmod_irq_info omap3xxx_l3_main_irqs[] = {
+	{ .irq = INT_34XX_L3_DBG_IRQ },
+	{ .irq = INT_34XX_L3_APP_IRQ },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_l3_main_addrs[] = {
+	{
+		.pa_start       = 0x68000000,
+		.pa_end         = 0x6800ffff,
+		.flags          = ADDR_TYPE_RT,
+	},
+};
+
 /* MPU -> L3 interface */
 static struct omap_hwmod_ocp_if omap3xxx_mpu__l3_main = {
-	.master = &omap3xxx_mpu_hwmod,
-	.slave	= &omap3xxx_l3_main_hwmod,
+	.master   = &omap3xxx_mpu_hwmod,
+	.slave    = &omap3xxx_l3_main_hwmod,
+	.addr     = omap3xxx_l3_main_addrs,
+	.addr_cnt = ARRAY_SIZE(omap3xxx_l3_main_addrs),
 	.user	= OCP_USER_MPU,
 };
 
@@ -84,6 +127,19 @@
 	&omap3xxx_mpu__l3_main,
 };
 
+/* DSS -> l3 */
+static struct omap_hwmod_ocp_if omap3xxx_dss__l3 = {
+	.master		= &omap3xxx_dss_core_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.fw = {
+		.omap2 = {
+			.l3_perm_bit  = OMAP3_L3_CORE_FW_INIT_ID_DSS,
+			.flags	= OMAP_FIREWALL_L3,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* Master interfaces on the L3 interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l3_main_masters[] = {
 	&omap3xxx_l3_main__l4_core,
@@ -94,6 +150,8 @@
 static struct omap_hwmod omap3xxx_l3_main_hwmod = {
 	.name		= "l3_main",
 	.class		= &l3_hwmod_class,
+	.mpu_irqs       = omap3xxx_l3_main_irqs,
+	.mpu_irqs_cnt   = ARRAY_SIZE(omap3xxx_l3_main_irqs),
 	.masters	= omap3xxx_l3_main_masters,
 	.masters_cnt	= ARRAY_SIZE(omap3xxx_l3_main_masters),
 	.slaves		= omap3xxx_l3_main_slaves,
@@ -107,7 +165,23 @@
 static struct omap_hwmod omap3xxx_uart2_hwmod;
 static struct omap_hwmod omap3xxx_uart3_hwmod;
 static struct omap_hwmod omap3xxx_uart4_hwmod;
+static struct omap_hwmod omap3xxx_usbhsotg_hwmod;
 
+/* l3_core -> usbhsotg interface */
+static struct omap_hwmod_ocp_if omap3xxx_usbhsotg__l3 = {
+	.master		= &omap3xxx_usbhsotg_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU,
+};
+
+/* l3_core -> am35xx_usbhsotg interface */
+static struct omap_hwmod_ocp_if am35xx_usbhsotg__l3 = {
+	.master		= &am35xx_usbhsotg_hwmod,
+	.slave		= &omap3xxx_l3_main_hwmod,
+	.clk		= "core_l3_ick",
+	.user		= OCP_USER_MPU,
+};
 /* L4_CORE -> L4_WKUP interface */
 static struct omap_hwmod_ocp_if omap3xxx_l4_core__l4_wkup = {
 	.master	= &omap3xxx_l4_core_hwmod,
@@ -115,6 +189,63 @@
 	.user	= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* L4 CORE -> MMC1 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc1_addr_space[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mmc1_hwmod,
+	.clk		= "mmchs1_ick",
+	.addr		= omap3xxx_mmc1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.flags		= OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> MMC2 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc2_addr_space[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b41ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mmc2_hwmod,
+	.clk		= "mmchs2_ick",
+	.addr		= omap3xxx_mmc2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.flags		= OMAP_FIREWALL_L4
+};
+
+/* L4 CORE -> MMC3 interface */
+static struct omap_hwmod_addr_space omap3xxx_mmc3_addr_space[] = {
+	{
+		.pa_start	= 0x480ad000,
+		.pa_end		= 0x480ad1ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mmc3 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mmc3_hwmod,
+	.clk		= "mmchs3_ick",
+	.addr		= omap3xxx_mmc3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mmc3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+	.flags		= OMAP_FIREWALL_L4
+};
+
 /* L4 CORE -> UART1 interface */
 static struct omap_hwmod_addr_space omap3xxx_uart1_addr_space[] = {
 	{
@@ -301,29 +432,70 @@
 	.user		= OCP_USER_MPU,
 };
 
+/*
+* usbhsotg interface data
+*/
+
+static struct omap_hwmod_addr_space omap3xxx_usbhsotg_addrs[] = {
+	{
+		.pa_start	= OMAP34XX_HSUSB_OTG_BASE,
+		.pa_end		= OMAP34XX_HSUSB_OTG_BASE + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> usbhsotg  */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__usbhsotg = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_usbhsotg_hwmod,
+	.clk		= "l4_ick",
+	.addr		= omap3xxx_usbhsotg_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_usbhsotg_masters[] = {
+	&omap3xxx_usbhsotg__l3,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_usbhsotg_slaves[] = {
+	&omap3xxx_l4_core__usbhsotg,
+};
+
+static struct omap_hwmod_addr_space am35xx_usbhsotg_addrs[] = {
+	{
+		.pa_start	= AM35XX_IPSS_USBOTGSS_BASE,
+		.pa_end		= AM35XX_IPSS_USBOTGSS_BASE + SZ_4K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> usbhsotg  */
+static struct omap_hwmod_ocp_if am35xx_l4_core__usbhsotg = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &am35xx_usbhsotg_hwmod,
+	.clk		= "l4_ick",
+	.addr		= am35xx_usbhsotg_addrs,
+	.addr_cnt	= ARRAY_SIZE(am35xx_usbhsotg_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_ocp_if *am35xx_usbhsotg_masters[] = {
+	&am35xx_usbhsotg__l3,
+};
+
+static struct omap_hwmod_ocp_if *am35xx_usbhsotg_slaves[] = {
+	&am35xx_l4_core__usbhsotg,
+};
 /* Slave interfaces on the L4_CORE interconnect */
 static struct omap_hwmod_ocp_if *omap3xxx_l4_core_slaves[] = {
 	&omap3xxx_l3_main__l4_core,
-	&omap3_l4_core__sr1,
-	&omap3_l4_core__sr2,
-};
-
-/* Master interfaces on the L4_CORE interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_core_masters[] = {
-	&omap3xxx_l4_core__l4_wkup,
-	&omap3_l4_core__uart1,
-	&omap3_l4_core__uart2,
-	&omap3_l4_core__i2c1,
-	&omap3_l4_core__i2c2,
-	&omap3_l4_core__i2c3,
 };
 
 /* L4 CORE */
 static struct omap_hwmod omap3xxx_l4_core_hwmod = {
 	.name		= "l4_core",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_core_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_core_masters),
 	.slaves		= omap3xxx_l4_core_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_core_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -335,18 +507,10 @@
 	&omap3xxx_l3_main__l4_per,
 };
 
-/* Master interfaces on the L4_PER interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_per_masters[] = {
-	&omap3_l4_per__uart3,
-	&omap3_l4_per__uart4,
-};
-
 /* L4 PER */
 static struct omap_hwmod omap3xxx_l4_per_hwmod = {
 	.name		= "l4_per",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_per_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_per_masters),
 	.slaves		= omap3xxx_l4_per_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_per_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -358,16 +522,10 @@
 	&omap3xxx_l4_core__l4_wkup,
 };
 
-/* Master interfaces on the L4_WKUP interconnect */
-static struct omap_hwmod_ocp_if *omap3xxx_l4_wkup_masters[] = {
-};
-
 /* L4 WKUP */
 static struct omap_hwmod omap3xxx_l4_wkup_hwmod = {
 	.name		= "l4_wkup",
 	.class		= &l4_hwmod_class,
-	.masters	= omap3xxx_l4_wkup_masters,
-	.masters_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_masters),
 	.slaves		= omap3xxx_l4_wkup_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_l4_wkup_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
@@ -417,6 +575,640 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
 };
 
+/* timer class */
+static struct omap_hwmod_class_sysconfig omap3xxx_timer_1ms_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_timer_1ms_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap3xxx_timer_1ms_sysc,
+	.rev = OMAP_TIMER_IP_VERSION_1,
+};
+
+static struct omap_hwmod_class_sysconfig omap3xxx_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_timer_hwmod_class = {
+	.name = "timer",
+	.sysc = &omap3xxx_timer_sysc,
+	.rev =  OMAP_TIMER_IP_VERSION_1,
+};
+
+/* timer1 */
+static struct omap_hwmod omap3xxx_timer1_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer1_mpu_irqs[] = {
+	{ .irq = 37, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer1_addrs[] = {
+	{
+		.pa_start	= 0x48318000,
+		.pa_end		= 0x48318000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_wkup__timer1 = {
+	.master		= &omap3xxx_l4_wkup_hwmod,
+	.slave		= &omap3xxx_timer1_hwmod,
+	.clk		= "gpt1_ick",
+	.addr		= omap3xxx_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer1_slaves[] = {
+	&omap3xxx_l4_wkup__timer1,
+};
+
+/* timer1 hwmod */
+static struct omap_hwmod omap3xxx_timer1_hwmod = {
+	.name		= "timer1",
+	.mpu_irqs	= omap3xxx_timer1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer1_mpu_irqs),
+	.main_clk	= "gpt1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT1_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer1_slaves),
+	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer2 */
+static struct omap_hwmod omap3xxx_timer2_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer2_mpu_irqs[] = {
+	{ .irq = 38, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer2_addrs[] = {
+	{
+		.pa_start	= 0x49032000,
+		.pa_end		= 0x49032000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer2 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer2 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer2_hwmod,
+	.clk		= "gpt2_ick",
+	.addr		= omap3xxx_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer2 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer2_slaves[] = {
+	&omap3xxx_l4_per__timer2,
+};
+
+/* timer2 hwmod */
+static struct omap_hwmod omap3xxx_timer2_hwmod = {
+	.name		= "timer2",
+	.mpu_irqs	= omap3xxx_timer2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer2_mpu_irqs),
+	.main_clk	= "gpt2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer2_slaves),
+	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer3 */
+static struct omap_hwmod omap3xxx_timer3_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer3_mpu_irqs[] = {
+	{ .irq = 39, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer3_addrs[] = {
+	{
+		.pa_start	= 0x49034000,
+		.pa_end		= 0x49034000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer3 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer3_hwmod,
+	.clk		= "gpt3_ick",
+	.addr		= omap3xxx_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer3 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer3_slaves[] = {
+	&omap3xxx_l4_per__timer3,
+};
+
+/* timer3 hwmod */
+static struct omap_hwmod omap3xxx_timer3_hwmod = {
+	.name		= "timer3",
+	.mpu_irqs	= omap3xxx_timer3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer3_mpu_irqs),
+	.main_clk	= "gpt3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer3_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer4 */
+static struct omap_hwmod omap3xxx_timer4_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer4_mpu_irqs[] = {
+	{ .irq = 40, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer4_addrs[] = {
+	{
+		.pa_start	= 0x49036000,
+		.pa_end		= 0x49036000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer4 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer4_hwmod,
+	.clk		= "gpt4_ick",
+	.addr		= omap3xxx_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer4 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer4_slaves[] = {
+	&omap3xxx_l4_per__timer4,
+};
+
+/* timer4 hwmod */
+static struct omap_hwmod omap3xxx_timer4_hwmod = {
+	.name		= "timer4",
+	.mpu_irqs	= omap3xxx_timer4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer4_mpu_irqs),
+	.main_clk	= "gpt4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT4_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer4_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer5 */
+static struct omap_hwmod omap3xxx_timer5_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer5_mpu_irqs[] = {
+	{ .irq = 41, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer5_addrs[] = {
+	{
+		.pa_start	= 0x49038000,
+		.pa_end		= 0x49038000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer5 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer5 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer5_hwmod,
+	.clk		= "gpt5_ick",
+	.addr		= omap3xxx_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer5 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer5_slaves[] = {
+	&omap3xxx_l4_per__timer5,
+};
+
+/* timer5 hwmod */
+static struct omap_hwmod omap3xxx_timer5_hwmod = {
+	.name		= "timer5",
+	.mpu_irqs	= omap3xxx_timer5_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer5_mpu_irqs),
+	.main_clk	= "gpt5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT5_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT5_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer5_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer6 */
+static struct omap_hwmod omap3xxx_timer6_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer6_mpu_irqs[] = {
+	{ .irq = 42, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4903A000,
+		.pa_end		= 0x4903A000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer6 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer6 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer6_hwmod,
+	.clk		= "gpt6_ick",
+	.addr		= omap3xxx_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer6_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer6 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer6_slaves[] = {
+	&omap3xxx_l4_per__timer6,
+};
+
+/* timer6 hwmod */
+static struct omap_hwmod omap3xxx_timer6_hwmod = {
+	.name		= "timer6",
+	.mpu_irqs	= omap3xxx_timer6_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer6_mpu_irqs),
+	.main_clk	= "gpt6_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT6_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT6_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer6_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer7 */
+static struct omap_hwmod omap3xxx_timer7_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer7_mpu_irqs[] = {
+	{ .irq = 43, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer7_addrs[] = {
+	{
+		.pa_start	= 0x4903C000,
+		.pa_end		= 0x4903C000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer7 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer7 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer7_hwmod,
+	.clk		= "gpt7_ick",
+	.addr		= omap3xxx_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer7_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer7 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer7_slaves[] = {
+	&omap3xxx_l4_per__timer7,
+};
+
+/* timer7 hwmod */
+static struct omap_hwmod omap3xxx_timer7_hwmod = {
+	.name		= "timer7",
+	.mpu_irqs	= omap3xxx_timer7_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer7_mpu_irqs),
+	.main_clk	= "gpt7_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT7_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT7_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer7_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer8 */
+static struct omap_hwmod omap3xxx_timer8_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer8_mpu_irqs[] = {
+	{ .irq = 44, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer8_addrs[] = {
+	{
+		.pa_start	= 0x4903E000,
+		.pa_end		= 0x4903E000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer8 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer8 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer8_hwmod,
+	.clk		= "gpt8_ick",
+	.addr		= omap3xxx_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer8_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer8 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer8_slaves[] = {
+	&omap3xxx_l4_per__timer8,
+};
+
+/* timer8 hwmod */
+static struct omap_hwmod omap3xxx_timer8_hwmod = {
+	.name		= "timer8",
+	.mpu_irqs	= omap3xxx_timer8_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer8_mpu_irqs),
+	.main_clk	= "gpt8_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT8_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT8_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer8_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer9 */
+static struct omap_hwmod omap3xxx_timer9_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer9_mpu_irqs[] = {
+	{ .irq = 45, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer9_addrs[] = {
+	{
+		.pa_start	= 0x49040000,
+		.pa_end		= 0x49040000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer9 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__timer9 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_timer9_hwmod,
+	.clk		= "gpt9_ick",
+	.addr		= omap3xxx_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer9_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer9 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer9_slaves[] = {
+	&omap3xxx_l4_per__timer9,
+};
+
+/* timer9 hwmod */
+static struct omap_hwmod omap3xxx_timer9_hwmod = {
+	.name		= "timer9",
+	.mpu_irqs	= omap3xxx_timer9_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer9_mpu_irqs),
+	.main_clk	= "gpt9_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT9_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT9_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer9_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer10 */
+static struct omap_hwmod omap3xxx_timer10_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer10_mpu_irqs[] = {
+	{ .irq = 46, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer10_addrs[] = {
+	{
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x48086000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer10 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer10 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_timer10_hwmod,
+	.clk		= "gpt10_ick",
+	.addr		= omap3xxx_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer10_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer10 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer10_slaves[] = {
+	&omap3xxx_l4_core__timer10,
+};
+
+/* timer10 hwmod */
+static struct omap_hwmod omap3xxx_timer10_hwmod = {
+	.name		= "timer10",
+	.mpu_irqs	= omap3xxx_timer10_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer10_mpu_irqs),
+	.main_clk	= "gpt10_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT10_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT10_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer10_slaves),
+	.class		= &omap3xxx_timer_1ms_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer11 */
+static struct omap_hwmod omap3xxx_timer11_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer11_mpu_irqs[] = {
+	{ .irq = 47, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer11_addrs[] = {
+	{
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x48088000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer11 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer11 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_timer11_hwmod,
+	.clk		= "gpt11_ick",
+	.addr		= omap3xxx_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer11_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer11 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer11_slaves[] = {
+	&omap3xxx_l4_core__timer11,
+};
+
+/* timer11 hwmod */
+static struct omap_hwmod omap3xxx_timer11_hwmod = {
+	.name		= "timer11",
+	.mpu_irqs	= omap3xxx_timer11_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer11_mpu_irqs),
+	.main_clk	= "gpt11_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT11_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT11_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer11_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* timer12*/
+static struct omap_hwmod omap3xxx_timer12_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_timer12_mpu_irqs[] = {
+	{ .irq = 95, },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_timer12_addrs[] = {
+	{
+		.pa_start	= 0x48304000,
+		.pa_end		= 0x48304000 + SZ_1K - 1,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> timer12 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__timer12 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_timer12_hwmod,
+	.clk		= "gpt12_ick",
+	.addr		= omap3xxx_timer12_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_timer12_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer12 slave port */
+static struct omap_hwmod_ocp_if *omap3xxx_timer12_slaves[] = {
+	&omap3xxx_l4_core__timer12,
+};
+
+/* timer12 hwmod */
+static struct omap_hwmod omap3xxx_timer12_hwmod = {
+	.name		= "timer12",
+	.mpu_irqs	= omap3xxx_timer12_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_timer12_mpu_irqs),
+	.main_clk	= "gpt12_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_GPT12_SHIFT,
+			.module_offs = WKUP_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_GPT12_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_timer12_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_timer12_slaves),
+	.class		= &omap3xxx_timer_hwmod_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
 /* l4_wkup -> wd_timer2 */
 static struct omap_hwmod_addr_space omap3xxx_wd_timer2_addrs[] = {
 	{
@@ -447,7 +1239,8 @@
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_EMUFREE |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY),
+			   SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -459,7 +1252,7 @@
 	.syss_offs	= 0x10,
 	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -491,6 +1284,11 @@
 	.slaves		= omap3xxx_wd_timer2_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap3xxx_wd_timer2_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+	/*
+	 * XXX: Use software supervised mode, HW supervised smartidle seems to
+	 * block CORE power domain idle transitions. Maybe a HW bug in wdt2?
+	 */
+	.flags		= HWMOD_SWSUP_SIDLE,
 };
 
 /* UART common */
@@ -501,7 +1299,7 @@
 	.syss_offs	= 0x58,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE |
 			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
-			   SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -664,6 +1462,414 @@
 	.sysc = &i2c_sysc,
 };
 
+/*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dss_hwmod_class = {
+	.name = "dss",
+	.sysc = &omap3xxx_dss_sysc,
+};
+
+static struct omap_hwmod_dma_info omap3xxx_dss_sdma_chs[] = {
+	{ .name = "dispc", .dma_req = 5 },
+	{ .name = "dsi1", .dma_req = 74 },
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_masters[] = {
+	&omap3xxx_dss__l3,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_addrs[] = {
+	{
+		.pa_start	= 0x48050000,
+		.pa_end		= 0x480503FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss */
+static struct omap_hwmod_ocp_if omap3430es1_l4_core__dss = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3430es1_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_core_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_CORE_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap3430es1_dss_slaves[] = {
+	&omap3430es1_l4_core__dss,
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_dss_slaves[] = {
+	&omap3xxx_l4_core__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "tv_clk", .clk = "dss_tv_fck" },
+	{ .role = "video_clk", .clk = "dss_96m_fck" },
+	{ .role = "sys_clk", .clk = "dss2_alwon_fck" },
+};
+
+static struct omap_hwmod omap3430es1_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap3xxx_dss_hwmod_class,
+	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
+	.sdma_reqs	= omap3xxx_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
+
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+			.idlest_reg_id = 1,
+			.idlest_stdby_bit = OMAP3430ES1_ST_DSS_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap3430es1_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3430es1_dss_slaves),
+	.masters	= omap3xxx_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+static struct omap_hwmod omap3xxx_dss_core_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap3xxx_dss_hwmod_class,
+	.main_clk	= "dss1_alwon_fck", /* instead of dss_fck */
+	.sdma_reqs	= omap3xxx_dss_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_dss_sdma_chs),
+
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430ES2_ST_DSS_IDLE_SHIFT,
+			.idlest_stdby_bit = OMAP3430ES2_ST_DSS_STDBY_SHIFT,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap3xxx_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_slaves),
+	.masters	= omap3xxx_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2 |
+				CHIP_IS_OMAP3630ES1 | CHIP_GE_OMAP3630ES1_1),
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_dispc_hwmod_class = {
+	.name = "dispc",
+	.sysc = &omap3xxx_dispc_sysc,
+};
+
+static struct omap_hwmod_irq_info omap3xxx_dispc_irqs[] = {
+	{ .irq = 25 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48050400,
+		.pa_end		= 0x480507FF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dispc */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dispc = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_dispc_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DISPC_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_dispc_slaves[] = {
+	&omap3xxx_l4_core__dss_dispc,
+};
+
+static struct omap_hwmod omap3xxx_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap3xxx_dispc_hwmod_class,
+	.mpu_irqs	= omap3xxx_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dispc_irqs),
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dispc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'dsi' class
+ * display serial interface controller
+ */
+
+static struct omap_hwmod_class omap3xxx_dsi_hwmod_class = {
+	.name = "dsi",
+};
+
+static struct omap_hwmod_irq_info omap3xxx_dsi1_irqs[] = {
+	{ .irq = 25 },
+};
+
+/* dss_dsi1 */
+static struct omap_hwmod_addr_space omap3xxx_dss_dsi1_addrs[] = {
+	{
+		.pa_start	= 0x4804FC00,
+		.pa_end		= 0x4804FFFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_dsi1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_dsi1_hwmod,
+	.addr		= omap3xxx_dss_dsi1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_DSI_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_dsi1 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_dsi1_slaves[] = {
+	&omap3xxx_l4_core__dss_dsi1,
+};
+
+static struct omap_hwmod omap3xxx_dss_dsi1_hwmod = {
+	.name		= "dss_dsi1",
+	.class		= &omap3xxx_dsi_hwmod_class,
+	.mpu_irqs	= omap3xxx_dsi1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_dsi1_irqs),
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_dsi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_dsi1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_rfbi_hwmod_class = {
+	.name = "rfbi",
+	.sysc = &omap3xxx_rfbi_sysc,
+};
+
+static struct omap_hwmod_addr_space omap3xxx_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48050800,
+		.pa_end		= 0x48050BFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_rfbi = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_rfbi_hwmod,
+	.clk		= "dss_ick",
+	.addr		= omap3xxx_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_RFBI_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP ,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_rfbi_slaves[] = {
+	&omap3xxx_l4_core__dss_rfbi,
+};
+
+static struct omap_hwmod omap3xxx_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap3xxx_rfbi_hwmod_class,
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap3xxx_venc_hwmod_class = {
+	.name = "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod_addr_space omap3xxx_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48050C00,
+		.pa_end		= 0x48050FFF,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> dss_venc */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__dss_venc = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_dss_venc_hwmod,
+	.clk		= "dss_tv_fck",
+	.addr		= omap3xxx_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_addrs),
+	.fw = {
+		.omap2 = {
+			.l4_fw_region  = OMAP3_L4_CORE_FW_DSS_VENC_REGION,
+			.l4_prot_group = OMAP3_L4_CORE_FW_DSS_PROT_GROUP,
+			.flags	= OMAP_FIREWALL_L4,
+		}
+	},
+	.flags		= OCPIF_SWSUP_IDLE,
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_dss_venc_slaves[] = {
+	&omap3xxx_l4_core__dss_venc,
+};
+
+static struct omap_hwmod omap3xxx_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap3xxx_venc_hwmod_class,
+	.main_clk	= "dss1_alwon_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_DSS1_SHIFT,
+			.module_offs = OMAP3430_DSS_MOD,
+		},
+	},
+	.slaves		= omap3xxx_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES1 |
+				CHIP_GE_OMAP3430ES2 | CHIP_IS_OMAP3630ES1 |
+				CHIP_GE_OMAP3630ES1_1),
+	.flags		= HWMOD_NO_IDLEST,
+};
+
 /* I2C1 */
 
 static struct omap_i2c_dev_attr i2c1_dev_attr = {
@@ -902,7 +2108,8 @@
 	.sysc_offs	= 0x0010,
 	.syss_offs	= 0x0014,
 	.sysc_flags	= (SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
-			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
 	.sysc_fields    = &omap_hwmod_sysc_type1,
 };
@@ -934,6 +2141,7 @@
 
 static struct omap_hwmod omap3xxx_gpio1_hwmod = {
 	.name		= "gpio1",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio1_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio1_irqs),
 	.main_clk	= "gpio1_ick",
@@ -970,6 +2178,7 @@
 
 static struct omap_hwmod omap3xxx_gpio2_hwmod = {
 	.name		= "gpio2",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio2_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio2_irqs),
 	.main_clk	= "gpio2_ick",
@@ -1006,6 +2215,7 @@
 
 static struct omap_hwmod omap3xxx_gpio3_hwmod = {
 	.name		= "gpio3",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio3_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio3_irqs),
 	.main_clk	= "gpio3_ick",
@@ -1042,6 +2252,7 @@
 
 static struct omap_hwmod omap3xxx_gpio4_hwmod = {
 	.name		= "gpio4",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio4_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio4_irqs),
 	.main_clk	= "gpio4_ick",
@@ -1078,6 +2289,7 @@
 
 static struct omap_hwmod omap3xxx_gpio5_hwmod = {
 	.name		= "gpio5",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio5_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio5_irqs),
 	.main_clk	= "gpio5_ick",
@@ -1114,6 +2326,7 @@
 
 static struct omap_hwmod omap3xxx_gpio6_hwmod = {
 	.name		= "gpio6",
+	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap3xxx_gpio6_irqs,
 	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_gpio6_irqs),
 	.main_clk	= "gpio6_ick",
@@ -1156,7 +2369,8 @@
 	.syss_offs	= 0x0028,
 	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
 			   SYSC_HAS_MIDLEMODE | SYSC_HAS_CLOCKACTIVITY |
-			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE),
+			   SYSC_HAS_EMUFREE | SYSC_HAS_AUTOIDLE |
+			   SYSS_HAS_RESET_STATUS),
 	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
 			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
 	.sysc_fields	= &omap_hwmod_sysc_type1,
@@ -1178,7 +2392,7 @@
 static struct omap_hwmod_addr_space omap3xxx_dma_system_addrs[] = {
 	{
 		.pa_start	= 0x48056000,
-		.pa_end		= 0x4a0560ff,
+		.pa_end		= 0x48056fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
@@ -1227,6 +2441,437 @@
 	.flags		= HWMOD_NO_IDLEST,
 };
 
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sysc = {
+	.sysc_offs	= 0x008c,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+	.clockact	= 0x2,
+};
+
+static struct omap_hwmod_class omap3xxx_mcbsp_hwmod_class = {
+	.name = "mcbsp",
+	.sysc = &omap3xxx_mcbsp_sysc,
+	.rev  = MCBSP_CONFIG_TYPE3,
+};
+
+/* mcbsp1 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp1_irqs[] = {
+	{ .name = "irq", .irq = 16 },
+	{ .name = "tx", .irq = 59 },
+	{ .name = "rx", .irq = 60 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp1_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 32 },
+	{ .name = "tx", .dma_req = 31 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48074000,
+		.pa_end		= 0x480740ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mcbsp1_hwmod,
+	.clk		= "mcbsp1_ick",
+	.addr		= omap3xxx_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp1_slaves[] = {
+	&omap3xxx_l4_core__mcbsp1,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp1_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_sdma_chs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP1_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP1_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp2_irqs[] = {
+	{ .name = "irq", .irq = 17 },
+	{ .name = "tx", .irq = 62 },
+	{ .name = "rx", .irq = 63 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp2_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 34 },
+	{ .name = "tx", .dma_req = 33 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x49022000,
+		.pa_end		= 0x490220ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp2_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap3xxx_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_slaves[] = {
+	&omap3xxx_l4_per__mcbsp2,
+};
+
+static struct omap_mcbsp_dev_attr omap34xx_mcbsp2_dev_attr = {
+	.sidetone	= "mcbsp2_sidetone",
+};
+
+static struct omap_hwmod omap3xxx_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp2_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sdma_chs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_slaves),
+	.dev_attr	= &omap34xx_mcbsp2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp3 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp3_irqs[] = {
+	{ .name = "irq", .irq = 22 },
+	{ .name = "tx", .irq = 89 },
+	{ .name = "rx", .irq = 90 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp3_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 18 },
+	{ .name = "tx", .dma_req = 17 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp3_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x49024000,
+		.pa_end		= 0x490240ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp3_hwmod,
+	.clk		= "mcbsp3_ick",
+	.addr		= omap3xxx_mcbsp3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp3 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_slaves[] = {
+	&omap3xxx_l4_per__mcbsp3,
+};
+
+static struct omap_mcbsp_dev_attr omap34xx_mcbsp3_dev_attr = {
+	.sidetone       = "mcbsp3_sidetone",
+};
+
+static struct omap_hwmod omap3xxx_mcbsp3_hwmod = {
+	.name		= "mcbsp3",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp3_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sdma_chs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_slaves),
+	.dev_attr	= &omap34xx_mcbsp3_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp4 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp4_irqs[] = {
+	{ .name = "irq", .irq = 23 },
+	{ .name = "tx", .irq = 54 },
+	{ .name = "rx", .irq = 55 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp4_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 20 },
+	{ .name = "tx", .dma_req = 19 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp4_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x49026000,
+		.pa_end		= 0x490260ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp4 = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp4_hwmod,
+	.clk		= "mcbsp4_ick",
+	.addr		= omap3xxx_mcbsp4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp4 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp4_slaves[] = {
+	&omap3xxx_l4_per__mcbsp4,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp4_hwmod = {
+	.name		= "mcbsp4",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp4_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_sdma_chs),
+	.main_clk	= "mcbsp4_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP4_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP4_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp5 */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp5_irqs[] = {
+	{ .name = "irq", .irq = 27 },
+	{ .name = "tx", .irq = 81 },
+	{ .name = "rx", .irq = 82 },
+};
+
+static struct omap_hwmod_dma_info omap3xxx_mcbsp5_sdma_chs[] = {
+	{ .name = "rx", .dma_req = 22 },
+	{ .name = "tx", .dma_req = 21 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp5_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x48096000,
+		.pa_end		= 0x480960ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_core -> mcbsp5 */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mcbsp5 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mcbsp5_hwmod,
+	.clk		= "mcbsp5_ick",
+	.addr		= omap3xxx_mcbsp5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp5 slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp5_slaves[] = {
+	&omap3xxx_l4_core__mcbsp5,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp5_hwmod = {
+	.name		= "mcbsp5",
+	.class		= &omap3xxx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_irqs),
+	.sdma_reqs	= omap3xxx_mcbsp5_sdma_chs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_sdma_chs),
+	.main_clk	= "mcbsp5_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP5_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP5_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+/* 'mcbsp sidetone' class */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_mcbsp_sidetone_sysc = {
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= SYSC_HAS_AUTOIDLE,
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_mcbsp_sidetone_hwmod_class = {
+	.name = "mcbsp_sidetone",
+	.sysc = &omap3xxx_mcbsp_sidetone_sysc,
+};
+
+/* mcbsp2_sidetone */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp2_sidetone_irqs[] = {
+	{ .name = "irq", .irq = 4 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp2_sidetone_addrs[] = {
+	{
+		.name		= "sidetone",
+		.pa_start	= 0x49028000,
+		.pa_end		= 0x490280ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp2_sidetone */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp2_sidetone = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp2_sidetone_hwmod,
+	.clk		= "mcbsp2_ick",
+	.addr		= omap3xxx_mcbsp2_sidetone_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* mcbsp2_sidetone slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp2_sidetone_slaves[] = {
+	&omap3xxx_l4_per__mcbsp2_sidetone,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp2_sidetone_hwmod = {
+	.name		= "mcbsp2_sidetone",
+	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp2_sidetone_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_irqs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			 .module_bit = OMAP3430_EN_MCBSP2_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp2_sidetone_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp2_sidetone_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcbsp3_sidetone */
+static struct omap_hwmod_irq_info omap3xxx_mcbsp3_sidetone_irqs[] = {
+	{ .name = "irq", .irq = 5 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mcbsp3_sidetone_addrs[] = {
+	{
+		.name		= "sidetone",
+		.pa_start	= 0x4902A000,
+		.pa_end		= 0x4902A0ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp3_sidetone */
+static struct omap_hwmod_ocp_if omap3xxx_l4_per__mcbsp3_sidetone = {
+	.master		= &omap3xxx_l4_per_hwmod,
+	.slave		= &omap3xxx_mcbsp3_sidetone_hwmod,
+	.clk		= "mcbsp3_ick",
+	.addr		= omap3xxx_mcbsp3_sidetone_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* mcbsp3_sidetone slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mcbsp3_sidetone_slaves[] = {
+	&omap3xxx_l4_per__mcbsp3_sidetone,
+};
+
+static struct omap_hwmod omap3xxx_mcbsp3_sidetone_hwmod = {
+	.name		= "mcbsp3_sidetone",
+	.class		= &omap3xxx_mcbsp_sidetone_hwmod_class,
+	.mpu_irqs	= omap3xxx_mcbsp3_sidetone_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_irqs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCBSP3_SHIFT,
+			.module_offs = OMAP3430_PER_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCBSP3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mcbsp3_sidetone_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mcbsp3_sidetone_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+
 /* SR common */
 static struct omap_hwmod_sysc_fields omap34xx_sr_sysc_fields = {
 	.clkact_shift	= 20,
@@ -1356,18 +3001,617 @@
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3630ES1),
 };
 
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors
+ * using a queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap3xxx_mailbox_sysc = {
+	.rev_offs	= 0x000,
+	.sysc_offs	= 0x010,
+	.syss_offs	= 0x014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_SOFTRESET | SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap3xxx_mailbox_hwmod_class = {
+	.name = "mailbox",
+	.sysc = &omap3xxx_mailbox_sysc,
+};
+
+static struct omap_hwmod omap3xxx_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap3xxx_mailbox_irqs[] = {
+	{ .irq = 26 },
+};
+
+static struct omap_hwmod_addr_space omap3xxx_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x48094000,
+		.pa_end		= 0x480941ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+/* l4_core -> mailbox */
+static struct omap_hwmod_ocp_if omap3xxx_l4_core__mailbox = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap3xxx_mailbox_hwmod,
+	.addr		= omap3xxx_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap3xxx_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap3xxx_mailbox_slaves[] = {
+	&omap3xxx_l4_core__mailbox,
+};
+
+static struct omap_hwmod omap3xxx_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap3xxx_mailbox_hwmod_class,
+	.mpu_irqs	= omap3xxx_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_mailbox_irqs),
+	.main_clk	= "mailboxes_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MAILBOXES_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MAILBOXES_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* l4 core -> mcspi1 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi1_addr_space[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480980ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi1 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi1,
+	.clk		= "mcspi1_ick",
+	.addr		= omap34xx_mcspi1_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi1_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi2 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi2_addr_space[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi2 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi2,
+	.clk		= "mcspi2_ick",
+	.addr		= omap34xx_mcspi2_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi2_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi3 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi3_addr_space[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b80ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi3 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi3,
+	.clk		= "mcspi3_ick",
+	.addr		= omap34xx_mcspi3_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi3_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* l4 core -> mcspi4 interface */
+static struct omap_hwmod_addr_space omap34xx_mcspi4_addr_space[] = {
+	{
+		.pa_start	= 0x480ba000,
+		.pa_end		= 0x480ba0ff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
+static struct omap_hwmod_ocp_if omap34xx_l4_core__mcspi4 = {
+	.master		= &omap3xxx_l4_core_hwmod,
+	.slave		= &omap34xx_mcspi4,
+	.clk		= "mcspi4_ick",
+	.addr		= omap34xx_mcspi4_addr_space,
+	.addr_cnt	= ARRAY_SIZE(omap34xx_mcspi4_addr_space),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap34xx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+				SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+				SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap34xx_mcspi_class = {
+	.name = "mcspi",
+	.sysc = &omap34xx_mcspi_sysc,
+	.rev = OMAP3_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod_irq_info omap34xx_mcspi1_mpu_irqs[] = {
+	{ .name = "irq", .irq = 65 },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 35 },
+	{ .name = "rx0", .dma_req = 36 },
+	{ .name = "tx1", .dma_req = 37 },
+	{ .name = "rx1", .dma_req = 38 },
+	{ .name = "tx2", .dma_req = 39 },
+	{ .name = "rx2", .dma_req = 40 },
+	{ .name = "tx3", .dma_req = 41 },
+	{ .name = "rx3", .dma_req = 42 },
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_mcspi1_slaves[] = {
+	&omap34xx_l4_core__mcspi1,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi1_dev_attr = {
+	.num_chipselect = 4,
+};
+
+static struct omap_hwmod omap34xx_mcspi1 = {
+	.name		= "mcspi1",
+	.mpu_irqs	= omap34xx_mcspi1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCSPI1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI1_SHIFT,
+		},
+	},
+	.slaves		= omap34xx_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi1_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi1_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcspi2 */
+static struct omap_hwmod_irq_info omap34xx_mcspi2_mpu_irqs[] = {
+	{ .name = "irq", .irq = 66 },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 43 },
+	{ .name = "rx0", .dma_req = 44 },
+	{ .name = "tx1", .dma_req = 45 },
+	{ .name = "rx1", .dma_req = 46 },
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_mcspi2_slaves[] = {
+	&omap34xx_l4_core__mcspi2,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi2_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap34xx_mcspi2 = {
+	.name		= "mcspi2",
+	.mpu_irqs	= omap34xx_mcspi2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCSPI2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI2_SHIFT,
+		},
+	},
+	.slaves		= omap34xx_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi2_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi2_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* mcspi3 */
+static struct omap_hwmod_irq_info omap34xx_mcspi3_mpu_irqs[] = {
+	{ .name = "irq", .irq = 91 }, /* 91 */
+};
+
+static struct omap_hwmod_dma_info omap34xx_mcspi3_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 15 },
+	{ .name = "rx0", .dma_req = 16 },
+	{ .name = "tx1", .dma_req = 23 },
+	{ .name = "rx1", .dma_req = 24 },
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_mcspi3_slaves[] = {
+	&omap34xx_l4_core__mcspi3,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi3_dev_attr = {
+	.num_chipselect = 2,
+};
+
+static struct omap_hwmod omap34xx_mcspi3 = {
+	.name		= "mcspi3",
+	.mpu_irqs	= omap34xx_mcspi3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi3_sdma_reqs),
+	.main_clk	= "mcspi3_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCSPI3_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI3_SHIFT,
+		},
+	},
+	.slaves		= omap34xx_mcspi3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi3_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi3_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* SPI4 */
+static struct omap_hwmod_irq_info omap34xx_mcspi4_mpu_irqs[] = {
+	{ .name = "irq", .irq = INT_34XX_SPI4_IRQ }, /* 48 */
+};
+
+static struct omap_hwmod_dma_info omap34xx_mcspi4_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 70 }, /* DMA_SPI4_TX0 */
+	{ .name = "rx0", .dma_req = 71 }, /* DMA_SPI4_RX0 */
+};
+
+static struct omap_hwmod_ocp_if *omap34xx_mcspi4_slaves[] = {
+	&omap34xx_l4_core__mcspi4,
+};
+
+static struct omap2_mcspi_dev_attr omap_mcspi4_dev_attr = {
+	.num_chipselect = 1,
+};
+
+static struct omap_hwmod omap34xx_mcspi4 = {
+	.name		= "mcspi4",
+	.mpu_irqs	= omap34xx_mcspi4_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_mpu_irqs),
+	.sdma_reqs	= omap34xx_mcspi4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mcspi4_sdma_reqs),
+	.main_clk	= "mcspi4_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MCSPI4_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MCSPI4_SHIFT,
+		},
+	},
+	.slaves		= omap34xx_mcspi4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap34xx_mcspi4_slaves),
+	.class		= &omap34xx_mcspi_class,
+	.dev_attr       = &omap_mcspi4_dev_attr,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/*
+ * usbhsotg
+ */
+static struct omap_hwmod_class_sysconfig omap3xxx_usbhsotg_sysc = {
+	.rev_offs	= 0x0400,
+	.sysc_offs	= 0x0404,
+	.syss_offs	= 0x0408,
+	.sysc_flags	= (SYSC_HAS_SIDLEMODE | SYSC_HAS_MIDLEMODE|
+			  SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			  SYSC_HAS_AUTOIDLE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			  MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class usbotg_class = {
+	.name = "usbotg",
+	.sysc = &omap3xxx_usbhsotg_sysc,
+};
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info omap3xxx_usbhsotg_mpu_irqs[] = {
+
+	{ .name = "mc", .irq = 92 },
+	{ .name = "dma", .irq = 93 },
+};
+
+static struct omap_hwmod omap3xxx_usbhsotg_hwmod = {
+	.name		= "usb_otg_hs",
+	.mpu_irqs	= omap3xxx_usbhsotg_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_mpu_irqs),
+	.main_clk	= "hsotgusb_ick",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_HSOTGUSB_SHIFT,
+			.module_offs = CORE_MOD,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430ES2_ST_HSOTGUSB_IDLE_SHIFT,
+			.idlest_stdby_bit = OMAP3430ES2_ST_HSOTGUSB_STDBY_SHIFT
+		},
+	},
+	.masters	= omap3xxx_usbhsotg_masters,
+	.masters_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_masters),
+	.slaves		= omap3xxx_usbhsotg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_usbhsotg_slaves),
+	.class		= &usbotg_class,
+
+	/*
+	 * Erratum ID: i479  idle_req / idle_ack mechanism potentially
+	 * broken when autoidle is enabled
+	 * workaround is to disable the autoidle bit at module level.
+	 */
+	.flags		= HWMOD_NO_OCP_AUTOIDLE | HWMOD_SWSUP_SIDLE
+				| HWMOD_SWSUP_MSTANDBY,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430)
+};
+
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info am35xx_usbhsotg_mpu_irqs[] = {
+
+	{ .name = "mc", .irq = 71 },
+};
+
+static struct omap_hwmod_class am35xx_usbotg_class = {
+	.name = "am35xx_usbotg",
+	.sysc = NULL,
+};
+
+static struct omap_hwmod am35xx_usbhsotg_hwmod = {
+	.name		= "am35x_otg_hs",
+	.mpu_irqs	= am35xx_usbhsotg_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(am35xx_usbhsotg_mpu_irqs),
+	.main_clk	= NULL,
+	.prcm = {
+		.omap2 = {
+		},
+	},
+	.masters	= am35xx_usbhsotg_masters,
+	.masters_cnt	= ARRAY_SIZE(am35xx_usbhsotg_masters),
+	.slaves		= am35xx_usbhsotg_slaves,
+	.slaves_cnt	= ARRAY_SIZE(am35xx_usbhsotg_slaves),
+	.class		= &am35xx_usbotg_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430ES3_1)
+};
+
+/* MMC/SD/SDIO common */
+
+static struct omap_hwmod_class_sysconfig omap34xx_mmc_sysc = {
+	.rev_offs	= 0x1fc,
+	.sysc_offs	= 0x10,
+	.syss_offs	= 0x14,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SOFTRESET |
+			   SYSC_HAS_AUTOIDLE | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields    = &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap34xx_mmc_class = {
+	.name = "mmc",
+	.sysc = &omap34xx_mmc_sysc,
+};
+
+/* MMC/SD/SDIO1 */
+
+static struct omap_hwmod_irq_info omap34xx_mmc1_mpu_irqs[] = {
+	{ .irq = 83, },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mmc1_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 61, },
+	{ .name = "rx",	.dma_req = 62, },
+};
+
+static struct omap_hwmod_opt_clk omap34xx_mmc1_opt_clks[] = {
+	{ .role = "dbck", .clk = "omap_32k_fck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_mmc1_slaves[] = {
+	&omap3xxx_l4_core__mmc1,
+};
+
+static struct omap_mmc_dev_attr mmc1_dev_attr = {
+	.flags = OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod omap3xxx_mmc1_hwmod = {
+	.name		= "mmc1",
+	.mpu_irqs	= omap34xx_mmc1_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_mpu_irqs),
+	.sdma_reqs	= omap34xx_mmc1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc1_sdma_reqs),
+	.opt_clks	= omap34xx_mmc1_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc1_opt_clks),
+	.main_clk	= "mmchs1_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MMC1_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MMC1_SHIFT,
+		},
+	},
+	.dev_attr	= &mmc1_dev_attr,
+	.slaves		= omap3xxx_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc1_slaves),
+	.class		= &omap34xx_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* MMC/SD/SDIO2 */
+
+static struct omap_hwmod_irq_info omap34xx_mmc2_mpu_irqs[] = {
+	{ .irq = INT_24XX_MMC2_IRQ, },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mmc2_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 47, },
+	{ .name = "rx",	.dma_req = 48, },
+};
+
+static struct omap_hwmod_opt_clk omap34xx_mmc2_opt_clks[] = {
+	{ .role = "dbck", .clk = "omap_32k_fck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_mmc2_slaves[] = {
+	&omap3xxx_l4_core__mmc2,
+};
+
+static struct omap_hwmod omap3xxx_mmc2_hwmod = {
+	.name		= "mmc2",
+	.mpu_irqs	= omap34xx_mmc2_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_mpu_irqs),
+	.sdma_reqs	= omap34xx_mmc2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc2_sdma_reqs),
+	.opt_clks	= omap34xx_mmc2_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc2_opt_clks),
+	.main_clk	= "mmchs2_fck",
+	.prcm		= {
+		.omap2 = {
+			.module_offs = CORE_MOD,
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MMC2_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MMC2_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc2_slaves),
+	.class		= &omap34xx_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
+/* MMC/SD/SDIO3 */
+
+static struct omap_hwmod_irq_info omap34xx_mmc3_mpu_irqs[] = {
+	{ .irq = 94, },
+};
+
+static struct omap_hwmod_dma_info omap34xx_mmc3_sdma_reqs[] = {
+	{ .name = "tx",	.dma_req = 77, },
+	{ .name = "rx",	.dma_req = 78, },
+};
+
+static struct omap_hwmod_opt_clk omap34xx_mmc3_opt_clks[] = {
+	{ .role = "dbck", .clk = "omap_32k_fck", },
+};
+
+static struct omap_hwmod_ocp_if *omap3xxx_mmc3_slaves[] = {
+	&omap3xxx_l4_core__mmc3,
+};
+
+static struct omap_hwmod omap3xxx_mmc3_hwmod = {
+	.name		= "mmc3",
+	.mpu_irqs	= omap34xx_mmc3_mpu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_mpu_irqs),
+	.sdma_reqs	= omap34xx_mmc3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap34xx_mmc3_sdma_reqs),
+	.opt_clks	= omap34xx_mmc3_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(omap34xx_mmc3_opt_clks),
+	.main_clk	= "mmchs3_fck",
+	.prcm		= {
+		.omap2 = {
+			.prcm_reg_id = 1,
+			.module_bit = OMAP3430_EN_MMC3_SHIFT,
+			.idlest_reg_id = 1,
+			.idlest_idle_bit = OMAP3430_ST_MMC3_SHIFT,
+		},
+	},
+	.slaves		= omap3xxx_mmc3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap3xxx_mmc3_slaves),
+	.class		= &omap34xx_mmc_class,
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
+};
+
 static __initdata struct omap_hwmod *omap3xxx_hwmods[] = {
 	&omap3xxx_l3_main_hwmod,
 	&omap3xxx_l4_core_hwmod,
 	&omap3xxx_l4_per_hwmod,
 	&omap3xxx_l4_wkup_hwmod,
+	&omap3xxx_mmc1_hwmod,
+	&omap3xxx_mmc2_hwmod,
+	&omap3xxx_mmc3_hwmod,
 	&omap3xxx_mpu_hwmod,
 	&omap3xxx_iva_hwmod,
+
+	&omap3xxx_timer1_hwmod,
+	&omap3xxx_timer2_hwmod,
+	&omap3xxx_timer3_hwmod,
+	&omap3xxx_timer4_hwmod,
+	&omap3xxx_timer5_hwmod,
+	&omap3xxx_timer6_hwmod,
+	&omap3xxx_timer7_hwmod,
+	&omap3xxx_timer8_hwmod,
+	&omap3xxx_timer9_hwmod,
+	&omap3xxx_timer10_hwmod,
+	&omap3xxx_timer11_hwmod,
+	&omap3xxx_timer12_hwmod,
+
 	&omap3xxx_wd_timer2_hwmod,
 	&omap3xxx_uart1_hwmod,
 	&omap3xxx_uart2_hwmod,
 	&omap3xxx_uart3_hwmod,
 	&omap3xxx_uart4_hwmod,
+	/* dss class */
+	&omap3430es1_dss_core_hwmod,
+	&omap3xxx_dss_core_hwmod,
+	&omap3xxx_dss_dispc_hwmod,
+	&omap3xxx_dss_dsi1_hwmod,
+	&omap3xxx_dss_rfbi_hwmod,
+	&omap3xxx_dss_venc_hwmod,
+
+	/* i2c class */
 	&omap3xxx_i2c1_hwmod,
 	&omap3xxx_i2c2_hwmod,
 	&omap3xxx_i2c3_hwmod,
@@ -1387,10 +3631,35 @@
 
 	/* dma_system class*/
 	&omap3xxx_dma_system_hwmod,
+
+	/* mcbsp class */
+	&omap3xxx_mcbsp1_hwmod,
+	&omap3xxx_mcbsp2_hwmod,
+	&omap3xxx_mcbsp3_hwmod,
+	&omap3xxx_mcbsp4_hwmod,
+	&omap3xxx_mcbsp5_hwmod,
+	&omap3xxx_mcbsp2_sidetone_hwmod,
+	&omap3xxx_mcbsp3_sidetone_hwmod,
+
+	/* mailbox class */
+	&omap3xxx_mailbox_hwmod,
+
+	/* mcspi class */
+	&omap34xx_mcspi1,
+	&omap34xx_mcspi2,
+	&omap34xx_mcspi3,
+	&omap34xx_mcspi4,
+
+	/* usbotg class */
+	&omap3xxx_usbhsotg_hwmod,
+
+	/* usbotg for am35x */
+	&am35xx_usbhsotg_hwmod,
+
 	NULL,
 };
 
 int __init omap3xxx_hwmod_init(void)
 {
-	return omap_hwmod_init(omap3xxx_hwmods);
+	return omap_hwmod_register(omap3xxx_hwmods);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod_44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Hardware modules present on the OMAP44xx chips
  *
- * Copyright (C) 2009-2010 Texas Instruments, Inc.
+ * Copyright (C) 2009-2011 Texas Instruments, Inc.
  * Copyright (C) 2009-2010 Nokia Corporation
  *
  * Paul Walmsley
@@ -24,6 +24,9 @@
 #include <plat/cpu.h>
 #include <plat/gpio.h>
 #include <plat/dma.h>
+#include <plat/mcspi.h>
+#include <plat/mcbsp.h>
+#include <plat/mmc.h>
 
 #include "omap_hwmod_common_data.h"
 
@@ -40,10 +43,15 @@
 #define OMAP44XX_DMA_REQ_START  1
 
 /* Backward references (IPs with Bus Master capability) */
+static struct omap_hwmod omap44xx_aess_hwmod;
 static struct omap_hwmod omap44xx_dma_system_hwmod;
 static struct omap_hwmod omap44xx_dmm_hwmod;
 static struct omap_hwmod omap44xx_dsp_hwmod;
+static struct omap_hwmod omap44xx_dss_hwmod;
 static struct omap_hwmod omap44xx_emif_fw_hwmod;
+static struct omap_hwmod omap44xx_hsi_hwmod;
+static struct omap_hwmod omap44xx_ipu_hwmod;
+static struct omap_hwmod omap44xx_iss_hwmod;
 static struct omap_hwmod omap44xx_iva_hwmod;
 static struct omap_hwmod omap44xx_l3_instr_hwmod;
 static struct omap_hwmod omap44xx_l3_main_1_hwmod;
@@ -53,8 +61,11 @@
 static struct omap_hwmod omap44xx_l4_cfg_hwmod;
 static struct omap_hwmod omap44xx_l4_per_hwmod;
 static struct omap_hwmod omap44xx_l4_wkup_hwmod;
+static struct omap_hwmod omap44xx_mmc1_hwmod;
+static struct omap_hwmod omap44xx_mmc2_hwmod;
 static struct omap_hwmod omap44xx_mpu_hwmod;
 static struct omap_hwmod omap44xx_mpu_private_hwmod;
+static struct omap_hwmod omap44xx_usb_otg_hs_hwmod;
 
 /*
  * Interconnects omap_hwmod structures
@@ -213,6 +224,14 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* dss -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_dss__l3_main_1 = {
+	.master		= &omap44xx_dss_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_2 -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_2__l3_main_1 = {
 	.master		= &omap44xx_l3_main_2_hwmod,
@@ -229,25 +248,62 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* mmc1 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mmc1__l3_main_1 = {
+	.master		= &omap44xx_mmc1_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc2 -> l3_main_1 */
+static struct omap_hwmod_ocp_if omap44xx_mmc2__l3_main_1 = {
+	.master		= &omap44xx_mmc2_hwmod,
+	.slave		= &omap44xx_l3_main_1_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* L3 target configuration and error log registers */
+static struct omap_hwmod_irq_info omap44xx_l3_targ_irqs[] = {
+	{ .irq = 9  + OMAP44XX_IRQ_GIC_START },
+	{ .irq = 10 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_l3_main_1_addrs[] = {
+	{
+		.pa_start	= 0x44000000,
+		.pa_end		= 0x44000fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* mpu -> l3_main_1 */
 static struct omap_hwmod_ocp_if omap44xx_mpu__l3_main_1 = {
 	.master		= &omap44xx_mpu_hwmod,
 	.slave		= &omap44xx_l3_main_1_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
 /* l3_main_1 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_1_slaves[] = {
 	&omap44xx_dsp__l3_main_1,
+	&omap44xx_dss__l3_main_1,
 	&omap44xx_l3_main_2__l3_main_1,
 	&omap44xx_l4_cfg__l3_main_1,
+	&omap44xx_mmc1__l3_main_1,
+	&omap44xx_mmc2__l3_main_1,
 	&omap44xx_mpu__l3_main_1,
 };
 
 static struct omap_hwmod omap44xx_l3_main_1_hwmod = {
 	.name		= "l3_main_1",
 	.class		= &omap44xx_l3_hwmod_class,
+	.mpu_irqs	= omap44xx_l3_targ_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_l3_targ_irqs),
 	.slaves		= omap44xx_l3_main_1_slaves,
 	.slaves_cnt	= ARRAY_SIZE(omap44xx_l3_main_1_slaves),
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
@@ -262,6 +318,30 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* hsi -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_hsi__l3_main_2 = {
+	.master		= &omap44xx_hsi_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ipu -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_ipu__l3_main_2 = {
+	.master		= &omap44xx_ipu_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iss -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_iss__l3_main_2 = {
+	.master		= &omap44xx_iss_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* iva -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_iva__l3_main_2 = {
 	.master		= &omap44xx_iva_hwmod,
@@ -270,11 +350,21 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+static struct omap_hwmod_addr_space omap44xx_l3_main_2_addrs[] = {
+	{
+		.pa_start	= 0x44800000,
+		.pa_end		= 0x44801fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* l3_main_1 -> l3_main_2 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_2 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_l3_main_2_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_2_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -286,12 +376,24 @@
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
+/* usb_otg_hs -> l3_main_2 */
+static struct omap_hwmod_ocp_if omap44xx_usb_otg_hs__l3_main_2 = {
+	.master		= &omap44xx_usb_otg_hs_hwmod,
+	.slave		= &omap44xx_l3_main_2_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* l3_main_2 slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l3_main_2_slaves[] = {
 	&omap44xx_dma_system__l3_main_2,
+	&omap44xx_hsi__l3_main_2,
+	&omap44xx_ipu__l3_main_2,
+	&omap44xx_iss__l3_main_2,
 	&omap44xx_iva__l3_main_2,
 	&omap44xx_l3_main_1__l3_main_2,
 	&omap44xx_l4_cfg__l3_main_2,
+	&omap44xx_usb_otg_hs__l3_main_2,
 };
 
 static struct omap_hwmod omap44xx_l3_main_2_hwmod = {
@@ -303,11 +405,21 @@
 };
 
 /* l3_main_3 interface data */
+static struct omap_hwmod_addr_space omap44xx_l3_main_3_addrs[] = {
+	{
+		.pa_start	= 0x45000000,
+		.pa_end		= 0x45000fff,
+		.flags		= ADDR_TYPE_RT,
+	},
+};
+
 /* l3_main_1 -> l3_main_3 */
 static struct omap_hwmod_ocp_if omap44xx_l3_main_1__l3_main_3 = {
 	.master		= &omap44xx_l3_main_1_hwmod,
 	.slave		= &omap44xx_l3_main_3_hwmod,
 	.clk		= "l3_div_ck",
+	.addr		= omap44xx_l3_main_3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_l3_main_3_addrs),
 	.user		= OCP_USER_MPU | OCP_USER_SDMA,
 };
 
@@ -351,6 +463,14 @@
 };
 
 /* l4_abe interface data */
+/* aess -> l4_abe */
+static struct omap_hwmod_ocp_if omap44xx_aess__l4_abe = {
+	.master		= &omap44xx_aess_hwmod,
+	.slave		= &omap44xx_l4_abe_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
 /* dsp -> l4_abe */
 static struct omap_hwmod_ocp_if omap44xx_dsp__l4_abe = {
 	.master		= &omap44xx_dsp_hwmod,
@@ -377,6 +497,7 @@
 
 /* l4_abe slave ports */
 static struct omap_hwmod_ocp_if *omap44xx_l4_abe_slaves[] = {
+	&omap44xx_aess__l4_abe,
 	&omap44xx_dsp__l4_abe,
 	&omap44xx_l3_main_1__l4_abe,
 	&omap44xx_mpu__l4_abe,
@@ -494,26 +615,15 @@
  * - They still need to be validated with the driver
  *   properly adapted to omap_hwmod / omap_device
  *
- *  aess
- *  bandgap
  *  c2c
  *  c2c_target_fw
  *  cm_core
  *  cm_core_aon
- *  counter_32k
  *  ctrl_module_core
  *  ctrl_module_pad_core
  *  ctrl_module_pad_wkup
  *  ctrl_module_wkup
  *  debugss
- *  dmic
- *  dss
- *  dss_dispc
- *  dss_dsi1
- *  dss_dsi2
- *  dss_hdmi
- *  dss_rfbi
- *  dss_venc
  *  efuse_ctrl_cust
  *  efuse_ctrl_std
  *  elm
@@ -524,58 +634,211 @@
  *  gpu
  *  hdq1w
  *  hsi
- *  ipu
- *  iss
- *  kbd
- *  mailbox
- *  mcasp
- *  mcbsp1
- *  mcbsp2
- *  mcbsp3
- *  mcbsp4
- *  mcpdm
- *  mcspi1
- *  mcspi2
- *  mcspi3
- *  mcspi4
- *  mmc1
- *  mmc2
- *  mmc3
- *  mmc4
- *  mmc5
- *  mpu_c0
- *  mpu_c1
  *  ocmc_ram
  *  ocp2scp_usb_phy
  *  ocp_wp_noc
- *  prcm
  *  prcm_mpu
  *  prm
  *  scrm
  *  sl2if
  *  slimbus1
  *  slimbus2
- *  spinlock
- *  timer1
- *  timer10
- *  timer11
- *  timer2
- *  timer3
- *  timer4
- *  timer5
- *  timer6
- *  timer7
- *  timer8
- *  timer9
  *  usb_host_fs
  *  usb_host_hs
- *  usb_otg_hs
  *  usb_phy_cm
  *  usb_tll_hs
  *  usim
  */
 
 /*
+ * 'aess' class
+ * audio engine sub system
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_aess_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_aess_hwmod_class = {
+	.name	= "aess",
+	.sysc	= &omap44xx_aess_sysc,
+};
+
+/* aess */
+static struct omap_hwmod_irq_info omap44xx_aess_irqs[] = {
+	{ .irq = 99 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_aess_sdma_reqs[] = {
+	{ .name = "fifo0", .dma_req = 100 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo1", .dma_req = 101 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo2", .dma_req = 102 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo3", .dma_req = 103 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo4", .dma_req = 104 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo5", .dma_req = 105 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo6", .dma_req = 106 + OMAP44XX_DMA_REQ_START },
+	{ .name = "fifo7", .dma_req = 107 + OMAP44XX_DMA_REQ_START },
+};
+
+/* aess master ports */
+static struct omap_hwmod_ocp_if *omap44xx_aess_masters[] = {
+	&omap44xx_aess__l4_abe,
+};
+
+static struct omap_hwmod_addr_space omap44xx_aess_addrs[] = {
+	{
+		.pa_start	= 0x401f1000,
+		.pa_end		= 0x401f13ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> aess */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_aess_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_aess_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_aess_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_aess_dma_addrs[] = {
+	{
+		.pa_start	= 0x490f1000,
+		.pa_end		= 0x490f13ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> aess (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__aess_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_aess_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_aess_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_aess_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* aess slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_aess_slaves[] = {
+	&omap44xx_l4_abe__aess,
+	&omap44xx_l4_abe__aess_dma,
+};
+
+static struct omap_hwmod omap44xx_aess_hwmod = {
+	.name		= "aess",
+	.class		= &omap44xx_aess_hwmod_class,
+	.mpu_irqs	= omap44xx_aess_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_aess_irqs),
+	.sdma_reqs	= omap44xx_aess_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_aess_sdma_reqs),
+	.main_clk	= "aess_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_AESS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_aess_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_aess_slaves),
+	.masters	= omap44xx_aess_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_aess_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'bandgap' class
+ * bangap reference for ldo regulators
+ */
+
+static struct omap_hwmod_class omap44xx_bandgap_hwmod_class = {
+	.name	= "bandgap",
+};
+
+/* bandgap */
+static struct omap_hwmod_opt_clk bandgap_opt_clks[] = {
+	{ .role = "fclk", .clk = "bandgap_fclk" },
+};
+
+static struct omap_hwmod omap44xx_bandgap_hwmod = {
+	.name		= "bandgap",
+	.class		= &omap44xx_bandgap_hwmod_class,
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
+		},
+	},
+	.opt_clks	= bandgap_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(bandgap_opt_clks),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'counter' class
+ * 32-bit ordinary counter, clocked by the falling edge of the 32 khz clock
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_counter_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0004,
+	.sysc_flags	= SYSC_HAS_SIDLEMODE,
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_counter_hwmod_class = {
+	.name	= "counter",
+	.sysc	= &omap44xx_counter_sysc,
+};
+
+/* counter_32k */
+static struct omap_hwmod omap44xx_counter_32k_hwmod;
+static struct omap_hwmod_addr_space omap44xx_counter_32k_addrs[] = {
+	{
+		.pa_start	= 0x4a304000,
+		.pa_end		= 0x4a30401f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> counter_32k */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__counter_32k = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_counter_32k_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_counter_32k_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_counter_32k_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* counter_32k slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_counter_32k_slaves[] = {
+	&omap44xx_l4_wkup__counter_32k,
+};
+
+static struct omap_hwmod omap44xx_counter_32k_hwmod = {
+	.name		= "counter_32k",
+	.class		= &omap44xx_counter_hwmod_class,
+	.flags		= HWMOD_SWSUP_SIDLE,
+	.main_clk	= "sys_32k_ck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_SYNCTIMER_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_counter_32k_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_counter_32k_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'dma' class
  * dma controller for data exchange between memory to memory (i.e. internal or
  * external memory) and gp peripherals to memory or memory to gp peripherals
@@ -622,7 +885,7 @@
 static struct omap_hwmod_addr_space omap44xx_dma_system_addrs[] = {
 	{
 		.pa_start	= 0x4a056000,
-		.pa_end		= 0x4a0560ff,
+		.pa_end		= 0x4a056fff,
 		.flags		= ADDR_TYPE_RT
 	},
 };
@@ -662,6 +925,96 @@
 };
 
 /*
+ * 'dmic' class
+ * digital microphone controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dmic_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_dmic_hwmod_class = {
+	.name	= "dmic",
+	.sysc	= &omap44xx_dmic_sysc,
+};
+
+/* dmic */
+static struct omap_hwmod omap44xx_dmic_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dmic_irqs[] = {
+	{ .irq = 114 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dmic_sdma_reqs[] = {
+	{ .dma_req = 66 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmic_addrs[] = {
+	{
+		.pa_start	= 0x4012e000,
+		.pa_end		= 0x4012e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> dmic */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_dmic_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_dmic_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dmic_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dmic_dma_addrs[] = {
+	{
+		.pa_start	= 0x4902e000,
+		.pa_end		= 0x4902e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> dmic (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__dmic_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_dmic_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_dmic_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dmic_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* dmic slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dmic_slaves[] = {
+	&omap44xx_l4_abe__dmic,
+	&omap44xx_l4_abe__dmic_dma,
+};
+
+static struct omap_hwmod omap44xx_dmic_hwmod = {
+	.name		= "dmic",
+	.class		= &omap44xx_dmic_hwmod_class,
+	.mpu_irqs	= omap44xx_dmic_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dmic_irqs),
+	.sdma_reqs	= omap44xx_dmic_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dmic_sdma_reqs),
+	.main_clk	= "dmic_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_DMIC_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dmic_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dmic_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'dsp' class
  * dsp sub-system
  */
@@ -747,6 +1100,590 @@
 };
 
 /*
+ * 'dss' class
+ * display sub-system
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dss_sysc = {
+	.rev_offs	= 0x0000,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= SYSS_HAS_RESET_STATUS,
+};
+
+static struct omap_hwmod_class omap44xx_dss_hwmod_class = {
+	.name	= "dss",
+	.sysc	= &omap44xx_dss_sysc,
+};
+
+/* dss */
+/* dss master ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_masters[] = {
+	&omap44xx_dss__l3_main_1,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dma_addrs[] = {
+	{
+		.pa_start	= 0x58000000,
+		.pa_end		= 0x5800007f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_addrs[] = {
+	{
+		.pa_start	= 0x48040000,
+		.pa_end		= 0x4804007f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_slaves[] = {
+	&omap44xx_l3_main_2__dss,
+	&omap44xx_l4_per__dss,
+};
+
+static struct omap_hwmod_opt_clk dss_opt_clks[] = {
+	{ .role = "sys_clk", .clk = "dss_sys_clk" },
+	{ .role = "tv_clk", .clk = "dss_tv_clk" },
+	{ .role = "dss_clk", .clk = "dss_dss_clk" },
+	{ .role = "video_clk", .clk = "dss_48mhz_clk" },
+};
+
+static struct omap_hwmod omap44xx_dss_hwmod = {
+	.name		= "dss_core",
+	.class		= &omap44xx_dss_hwmod_class,
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.opt_clks	= dss_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(dss_opt_clks),
+	.slaves		= omap44xx_dss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_slaves),
+	.masters	= omap44xx_dss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_dss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'dispc' class
+ * display controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dispc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   MSTANDBY_FORCE | MSTANDBY_NO | MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_dispc_hwmod_class = {
+	.name	= "dispc",
+	.sysc	= &omap44xx_dispc_sysc,
+};
+
+/* dss_dispc */
+static struct omap_hwmod omap44xx_dss_dispc_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_dispc_irqs[] = {
+	{ .irq = 25 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_dispc_sdma_reqs[] = {
+	{ .dma_req = 5 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dispc_dma_addrs[] = {
+	{
+		.pa_start	= 0x58001000,
+		.pa_end		= 0x58001fff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_dispc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dispc = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_dispc_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dispc_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dispc_addrs[] = {
+	{
+		.pa_start	= 0x48041000,
+		.pa_end		= 0x48041fff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_dispc */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dispc = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_dispc_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_dispc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_dispc slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_dispc_slaves[] = {
+	&omap44xx_l3_main_2__dss_dispc,
+	&omap44xx_l4_per__dss_dispc,
+};
+
+static struct omap_hwmod omap44xx_dss_dispc_hwmod = {
+	.name		= "dss_dispc",
+	.class		= &omap44xx_dispc_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_dispc_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_irqs),
+	.sdma_reqs	= omap44xx_dss_dispc_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_sdma_reqs),
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_dispc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dispc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'dsi' class
+ * display serial interface controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_dsi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_dsi_hwmod_class = {
+	.name	= "dsi",
+	.sysc	= &omap44xx_dsi_sysc,
+};
+
+/* dss_dsi1 */
+static struct omap_hwmod omap44xx_dss_dsi1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_dsi1_irqs[] = {
+	{ .irq = 53 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_dsi1_sdma_reqs[] = {
+	{ .dma_req = 74 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi1_dma_addrs[] = {
+	{
+		.pa_start	= 0x58004000,
+		.pa_end		= 0x580041ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi1 = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_dsi1_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dsi1_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi1_addrs[] = {
+	{
+		.pa_start	= 0x48044000,
+		.pa_end		= 0x480441ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_dsi1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_dsi1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_dsi1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_dsi1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_dsi1_slaves[] = {
+	&omap44xx_l3_main_2__dss_dsi1,
+	&omap44xx_l4_per__dss_dsi1,
+};
+
+static struct omap_hwmod omap44xx_dss_dsi1_hwmod = {
+	.name		= "dss_dsi1",
+	.class		= &omap44xx_dsi_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_dsi1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_irqs),
+	.sdma_reqs	= omap44xx_dss_dsi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_sdma_reqs),
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_dsi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* dss_dsi2 */
+static struct omap_hwmod omap44xx_dss_dsi2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_dsi2_irqs[] = {
+	{ .irq = 84 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_dsi2_sdma_reqs[] = {
+	{ .dma_req = 83 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi2_dma_addrs[] = {
+	{
+		.pa_start	= 0x58005000,
+		.pa_end		= 0x580051ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_dsi2 */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_dsi2 = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_dsi2_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_dsi2_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_dsi2_addrs[] = {
+	{
+		.pa_start	= 0x48045000,
+		.pa_end		= 0x480451ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_dsi2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_dsi2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_dsi2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_dsi2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_dsi2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_dsi2_slaves[] = {
+	&omap44xx_l3_main_2__dss_dsi2,
+	&omap44xx_l4_per__dss_dsi2,
+};
+
+static struct omap_hwmod omap44xx_dss_dsi2_hwmod = {
+	.name		= "dss_dsi2",
+	.class		= &omap44xx_dsi_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_dsi2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_irqs),
+	.sdma_reqs	= omap44xx_dss_dsi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_sdma_reqs),
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_dsi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_dsi2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'hdmi' class
+ * hdmi controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_hdmi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_hdmi_hwmod_class = {
+	.name	= "hdmi",
+	.sysc	= &omap44xx_hdmi_sysc,
+};
+
+/* dss_hdmi */
+static struct omap_hwmod omap44xx_dss_hdmi_hwmod;
+static struct omap_hwmod_irq_info omap44xx_dss_hdmi_irqs[] = {
+	{ .irq = 101 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_dss_hdmi_sdma_reqs[] = {
+	{ .dma_req = 75 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_hdmi_dma_addrs[] = {
+	{
+		.pa_start	= 0x58006000,
+		.pa_end		= 0x58006fff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_hdmi */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_hdmi = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_hdmi_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_hdmi_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_hdmi_addrs[] = {
+	{
+		.pa_start	= 0x48046000,
+		.pa_end		= 0x48046fff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_hdmi */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_hdmi = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_hdmi_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_hdmi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_hdmi slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_hdmi_slaves[] = {
+	&omap44xx_l3_main_2__dss_hdmi,
+	&omap44xx_l4_per__dss_hdmi,
+};
+
+static struct omap_hwmod omap44xx_dss_hdmi_hwmod = {
+	.name		= "dss_hdmi",
+	.class		= &omap44xx_hdmi_hwmod_class,
+	.mpu_irqs	= omap44xx_dss_hdmi_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_irqs),
+	.sdma_reqs	= omap44xx_dss_hdmi_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_sdma_reqs),
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_hdmi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_hdmi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'rfbi' class
+ * remote frame buffer interface
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_rfbi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_rfbi_hwmod_class = {
+	.name	= "rfbi",
+	.sysc	= &omap44xx_rfbi_sysc,
+};
+
+/* dss_rfbi */
+static struct omap_hwmod omap44xx_dss_rfbi_hwmod;
+static struct omap_hwmod_dma_info omap44xx_dss_rfbi_sdma_reqs[] = {
+	{ .dma_req = 13 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_rfbi_dma_addrs[] = {
+	{
+		.pa_start	= 0x58002000,
+		.pa_end		= 0x580020ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_rfbi = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_rfbi_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_rfbi_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_rfbi_addrs[] = {
+	{
+		.pa_start	= 0x48042000,
+		.pa_end		= 0x480420ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_rfbi */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_rfbi = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_rfbi_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_rfbi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_rfbi slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_rfbi_slaves[] = {
+	&omap44xx_l3_main_2__dss_rfbi,
+	&omap44xx_l4_per__dss_rfbi,
+};
+
+static struct omap_hwmod omap44xx_dss_rfbi_hwmod = {
+	.name		= "dss_rfbi",
+	.class		= &omap44xx_rfbi_hwmod_class,
+	.sdma_reqs	= omap44xx_dss_rfbi_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_sdma_reqs),
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_rfbi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_rfbi_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'venc' class
+ * video encoder
+ */
+
+static struct omap_hwmod_class omap44xx_venc_hwmod_class = {
+	.name	= "venc",
+};
+
+/* dss_venc */
+static struct omap_hwmod omap44xx_dss_venc_hwmod;
+static struct omap_hwmod_addr_space omap44xx_dss_venc_dma_addrs[] = {
+	{
+		.pa_start	= 0x58003000,
+		.pa_end		= 0x580030ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> dss_venc */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__dss_venc = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_dss_venc_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_dss_venc_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+static struct omap_hwmod_addr_space omap44xx_dss_venc_addrs[] = {
+	{
+		.pa_start	= 0x48043000,
+		.pa_end		= 0x480430ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> dss_venc */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__dss_venc = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_dss_venc_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_dss_venc_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_dss_venc_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+/* dss_venc slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_dss_venc_slaves[] = {
+	&omap44xx_l3_main_2__dss_venc,
+	&omap44xx_l4_per__dss_venc,
+};
+
+static struct omap_hwmod omap44xx_dss_venc_hwmod = {
+	.name		= "dss_venc",
+	.class		= &omap44xx_venc_hwmod_class,
+	.main_clk	= "dss_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DSS_DSS_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_dss_venc_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_dss_venc_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'gpio' class
  * general purpose io module
  */
@@ -1093,6 +2030,83 @@
 };
 
 /*
+ * 'hsi' class
+ * mipi high-speed synchronous serial interface (multichannel and full-duplex
+ * serial if)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_hsi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_EMUFREE |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_hsi_hwmod_class = {
+	.name	= "hsi",
+	.sysc	= &omap44xx_hsi_sysc,
+};
+
+/* hsi */
+static struct omap_hwmod_irq_info omap44xx_hsi_irqs[] = {
+	{ .name = "mpu_p1", .irq = 67 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "mpu_p2", .irq = 68 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "mpu_dma", .irq = 71 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* hsi master ports */
+static struct omap_hwmod_ocp_if *omap44xx_hsi_masters[] = {
+	&omap44xx_hsi__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_hsi_addrs[] = {
+	{
+		.pa_start	= 0x4a058000,
+		.pa_end		= 0x4a05bfff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> hsi */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__hsi = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_hsi_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_hsi_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_hsi_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* hsi slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_hsi_slaves[] = {
+	&omap44xx_l4_cfg__hsi,
+};
+
+static struct omap_hwmod omap44xx_hsi_hwmod = {
+	.name		= "hsi",
+	.class		= &omap44xx_hsi_hwmod_class,
+	.mpu_irqs	= omap44xx_hsi_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_hsi_irqs),
+	.main_clk	= "hsi_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_HSI_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_hsi_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_hsi_slaves),
+	.masters	= omap44xx_hsi_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_hsi_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'i2c' class
  * multimaster high-speed i2c controller
  */
@@ -1326,6 +2340,188 @@
 };
 
 /*
+ * 'ipu' class
+ * imaging processor unit
+ */
+
+static struct omap_hwmod_class omap44xx_ipu_hwmod_class = {
+	.name	= "ipu",
+};
+
+/* ipu */
+static struct omap_hwmod_irq_info omap44xx_ipu_irqs[] = {
+	{ .irq = 100 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_rst_info omap44xx_ipu_c0_resets[] = {
+	{ .name = "cpu0", .rst_shift = 0 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_ipu_c1_resets[] = {
+	{ .name = "cpu1", .rst_shift = 1 },
+};
+
+static struct omap_hwmod_rst_info omap44xx_ipu_resets[] = {
+	{ .name = "mmu_cache", .rst_shift = 2 },
+};
+
+/* ipu master ports */
+static struct omap_hwmod_ocp_if *omap44xx_ipu_masters[] = {
+	&omap44xx_ipu__l3_main_2,
+};
+
+/* l3_main_2 -> ipu */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__ipu = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_ipu_hwmod,
+	.clk		= "l3_div_ck",
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* ipu slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_ipu_slaves[] = {
+	&omap44xx_l3_main_2__ipu,
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_ipu_c0_hwmod = {
+	.name		= "ipu_c0",
+	.class		= &omap44xx_ipu_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_ipu_c0_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_c0_resets),
+	.prcm		= {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* Pseudo hwmod for reset control purpose only */
+static struct omap_hwmod omap44xx_ipu_c1_hwmod = {
+	.name		= "ipu_c1",
+	.class		= &omap44xx_ipu_hwmod_class,
+	.flags		= HWMOD_INIT_NO_RESET,
+	.rst_lines	= omap44xx_ipu_c1_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_c1_resets),
+	.prcm		= {
+		.omap4 = {
+			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+		},
+	},
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+static struct omap_hwmod omap44xx_ipu_hwmod = {
+	.name		= "ipu",
+	.class		= &omap44xx_ipu_hwmod_class,
+	.mpu_irqs	= omap44xx_ipu_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_ipu_irqs),
+	.rst_lines	= omap44xx_ipu_resets,
+	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_ipu_resets),
+	.main_clk	= "ipu_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
+			.rstctrl_reg = OMAP4430_RM_DUCATI_RSTCTRL,
+		},
+	},
+	.slaves		= omap44xx_ipu_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_ipu_slaves),
+	.masters	= omap44xx_ipu_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_ipu_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'iss' class
+ * external images sensor pixel data processor
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_iss_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_MIDLEMODE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_iss_hwmod_class = {
+	.name	= "iss",
+	.sysc	= &omap44xx_iss_sysc,
+};
+
+/* iss */
+static struct omap_hwmod_irq_info omap44xx_iss_irqs[] = {
+	{ .irq = 24 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_iss_sdma_reqs[] = {
+	{ .name = "1", .dma_req = 8 + OMAP44XX_DMA_REQ_START },
+	{ .name = "2", .dma_req = 9 + OMAP44XX_DMA_REQ_START },
+	{ .name = "3", .dma_req = 11 + OMAP44XX_DMA_REQ_START },
+	{ .name = "4", .dma_req = 12 + OMAP44XX_DMA_REQ_START },
+};
+
+/* iss master ports */
+static struct omap_hwmod_ocp_if *omap44xx_iss_masters[] = {
+	&omap44xx_iss__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_iss_addrs[] = {
+	{
+		.pa_start	= 0x52000000,
+		.pa_end		= 0x520000ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l3_main_2 -> iss */
+static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
+	.master		= &omap44xx_l3_main_2_hwmod,
+	.slave		= &omap44xx_iss_hwmod,
+	.clk		= "l3_div_ck",
+	.addr		= omap44xx_iss_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_iss_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* iss slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_iss_slaves[] = {
+	&omap44xx_l3_main_2__iss,
+};
+
+static struct omap_hwmod_opt_clk iss_opt_clks[] = {
+	{ .role = "ctrlclk", .clk = "iss_ctrlclk" },
+};
+
+static struct omap_hwmod omap44xx_iss_hwmod = {
+	.name		= "iss",
+	.class		= &omap44xx_iss_hwmod_class,
+	.mpu_irqs	= omap44xx_iss_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_iss_irqs),
+	.sdma_reqs	= omap44xx_iss_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_iss_sdma_reqs),
+	.main_clk	= "iss_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_CAM_ISS_CLKCTRL,
+		},
+	},
+	.opt_clks	= iss_opt_clks,
+	.opt_clks_cnt	= ARRAY_SIZE(iss_opt_clks),
+	.slaves		= omap44xx_iss_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_iss_slaves),
+	.masters	= omap44xx_iss_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_iss_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'iva' class
  * multi-standard video encoder/decoder hardware accelerator
  */
@@ -1435,6 +2631,1084 @@
 };
 
 /*
+ * 'kbd' class
+ * keyboard controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_kbd_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_kbd_hwmod_class = {
+	.name	= "kbd",
+	.sysc	= &omap44xx_kbd_sysc,
+};
+
+/* kbd */
+static struct omap_hwmod omap44xx_kbd_hwmod;
+static struct omap_hwmod_irq_info omap44xx_kbd_irqs[] = {
+	{ .irq = 120 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_kbd_addrs[] = {
+	{
+		.pa_start	= 0x4a31c000,
+		.pa_end		= 0x4a31c07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> kbd */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__kbd = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_kbd_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_kbd_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_kbd_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* kbd slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_kbd_slaves[] = {
+	&omap44xx_l4_wkup__kbd,
+};
+
+static struct omap_hwmod omap44xx_kbd_hwmod = {
+	.name		= "kbd",
+	.class		= &omap44xx_kbd_hwmod_class,
+	.mpu_irqs	= omap44xx_kbd_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_kbd_irqs),
+	.main_clk	= "kbd_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_kbd_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_kbd_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mailbox' class
+ * mailbox module allowing communication between the on-chip processors using a
+ * queued mailbox-interrupt mechanism.
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mailbox_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mailbox_hwmod_class = {
+	.name	= "mailbox",
+	.sysc	= &omap44xx_mailbox_sysc,
+};
+
+/* mailbox */
+static struct omap_hwmod omap44xx_mailbox_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mailbox_irqs[] = {
+	{ .irq = 26 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mailbox_addrs[] = {
+	{
+		.pa_start	= 0x4a0f4000,
+		.pa_end		= 0x4a0f41ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> mailbox */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__mailbox = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_mailbox_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mailbox_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mailbox_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mailbox slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mailbox_slaves[] = {
+	&omap44xx_l4_cfg__mailbox,
+};
+
+static struct omap_hwmod omap44xx_mailbox_hwmod = {
+	.name		= "mailbox",
+	.class		= &omap44xx_mailbox_hwmod_class,
+	.mpu_irqs	= omap44xx_mailbox_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mailbox_irqs),
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4CFG_MAILBOX_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mailbox_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mailbox_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mcbsp' class
+ * multi channel buffered serial port controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcbsp_sysc = {
+	.sysc_offs	= 0x008c,
+	.sysc_flags	= (SYSC_HAS_CLOCKACTIVITY | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_mcbsp_hwmod_class = {
+	.name	= "mcbsp",
+	.sysc	= &omap44xx_mcbsp_sysc,
+	.rev	= MCBSP_CONFIG_TYPE4,
+};
+
+/* mcbsp1 */
+static struct omap_hwmod omap44xx_mcbsp1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp1_irqs[] = {
+	{ .irq = 17 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 32 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 33 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp1_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x40122000,
+		.pa_end		= 0x401220ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp1_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp1_dma_addrs[] = {
+	{
+		.name		= "dma",
+		.pa_start	= 0x49022000,
+		.pa_end		= 0x490220ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp1 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp1_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp1_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp1_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcbsp1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp1_slaves[] = {
+	&omap44xx_l4_abe__mcbsp1,
+	&omap44xx_l4_abe__mcbsp1_dma,
+};
+
+static struct omap_hwmod omap44xx_mcbsp1_hwmod = {
+	.name		= "mcbsp1",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_irqs),
+	.sdma_reqs	= omap44xx_mcbsp1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_sdma_reqs),
+	.main_clk	= "mcbsp1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcbsp2 */
+static struct omap_hwmod omap44xx_mcbsp2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp2_irqs[] = {
+	{ .irq = 22 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 16 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 17 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp2_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x40124000,
+		.pa_end		= 0x401240ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp2_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp2_dma_addrs[] = {
+	{
+		.name		= "dma",
+		.pa_start	= 0x49024000,
+		.pa_end		= 0x490240ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp2 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp2_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp2_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp2_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcbsp2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp2_slaves[] = {
+	&omap44xx_l4_abe__mcbsp2,
+	&omap44xx_l4_abe__mcbsp2_dma,
+};
+
+static struct omap_hwmod omap44xx_mcbsp2_hwmod = {
+	.name		= "mcbsp2",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_irqs),
+	.sdma_reqs	= omap44xx_mcbsp2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_sdma_reqs),
+	.main_clk	= "mcbsp2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcbsp3 */
+static struct omap_hwmod omap44xx_mcbsp3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp3_irqs[] = {
+	{ .irq = 23 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 18 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 19 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp3_addrs[] = {
+	{
+		.name		= "mpu",
+		.pa_start	= 0x40126000,
+		.pa_end		= 0x401260ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp3_dma_addrs[] = {
+	{
+		.name		= "dma",
+		.pa_start	= 0x49026000,
+		.pa_end		= 0x490260ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcbsp3 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcbsp3_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcbsp3_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcbsp3_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcbsp3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp3_slaves[] = {
+	&omap44xx_l4_abe__mcbsp3,
+	&omap44xx_l4_abe__mcbsp3_dma,
+};
+
+static struct omap_hwmod omap44xx_mcbsp3_hwmod = {
+	.name		= "mcbsp3",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_irqs),
+	.sdma_reqs	= omap44xx_mcbsp3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_sdma_reqs),
+	.main_clk	= "mcbsp3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcbsp4 */
+static struct omap_hwmod omap44xx_mcbsp4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcbsp4_irqs[] = {
+	{ .irq = 16 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcbsp4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 30 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 31 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcbsp4_addrs[] = {
+	{
+		.pa_start	= 0x48096000,
+		.pa_end		= 0x480960ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcbsp4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcbsp4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcbsp4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcbsp4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcbsp4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcbsp4_slaves[] = {
+	&omap44xx_l4_per__mcbsp4,
+};
+
+static struct omap_hwmod omap44xx_mcbsp4_hwmod = {
+	.name		= "mcbsp4",
+	.class		= &omap44xx_mcbsp_hwmod_class,
+	.mpu_irqs	= omap44xx_mcbsp4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_irqs),
+	.sdma_reqs	= omap44xx_mcbsp4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_sdma_reqs),
+	.main_clk	= "mcbsp4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcbsp4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcbsp4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mcpdm' class
+ * multi channel pdm controller (proprietary interface with phoenix power
+ * ic)
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcpdm_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mcpdm_hwmod_class = {
+	.name	= "mcpdm",
+	.sysc	= &omap44xx_mcpdm_sysc,
+};
+
+/* mcpdm */
+static struct omap_hwmod omap44xx_mcpdm_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcpdm_irqs[] = {
+	{ .irq = 112 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcpdm_sdma_reqs[] = {
+	{ .name = "up_link", .dma_req = 64 + OMAP44XX_DMA_REQ_START },
+	{ .name = "dn_link", .dma_req = 65 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcpdm_addrs[] = {
+	{
+		.pa_start	= 0x40132000,
+		.pa_end		= 0x4013207f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcpdm */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcpdm_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcpdm_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcpdm_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcpdm_dma_addrs[] = {
+	{
+		.pa_start	= 0x49032000,
+		.pa_end		= 0x4903207f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> mcpdm (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__mcpdm_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_mcpdm_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_mcpdm_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcpdm_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* mcpdm slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcpdm_slaves[] = {
+	&omap44xx_l4_abe__mcpdm,
+	&omap44xx_l4_abe__mcpdm_dma,
+};
+
+static struct omap_hwmod omap44xx_mcpdm_hwmod = {
+	.name		= "mcpdm",
+	.class		= &omap44xx_mcpdm_hwmod_class,
+	.mpu_irqs	= omap44xx_mcpdm_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcpdm_irqs),
+	.sdma_reqs	= omap44xx_mcpdm_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcpdm_sdma_reqs),
+	.main_clk	= "mcpdm_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_PDM_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mcpdm_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcpdm_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mcspi' class
+ * multichannel serial port interface (mcspi) / master/slave synchronous serial
+ * bus
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mcspi_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mcspi_hwmod_class = {
+	.name	= "mcspi",
+	.sysc	= &omap44xx_mcspi_sysc,
+	.rev	= OMAP4_MCSPI_REV,
+};
+
+/* mcspi1 */
+static struct omap_hwmod omap44xx_mcspi1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi1_irqs[] = {
+	{ .irq = 65 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi1_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 34 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 35 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx1", .dma_req = 36 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx1", .dma_req = 37 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx2", .dma_req = 38 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx2", .dma_req = 39 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx3", .dma_req = 40 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx3", .dma_req = 41 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi1_addrs[] = {
+	{
+		.pa_start	= 0x48098000,
+		.pa_end		= 0x480981ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi1_slaves[] = {
+	&omap44xx_l4_per__mcspi1,
+};
+
+/* mcspi1 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi1_dev_attr = {
+	.num_chipselect	= 4,
+};
+
+static struct omap_hwmod omap44xx_mcspi1_hwmod = {
+	.name		= "mcspi1",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi1_irqs),
+	.sdma_reqs	= omap44xx_mcspi1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi1_sdma_reqs),
+	.main_clk	= "mcspi1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi1_dev_attr,
+	.slaves		= omap44xx_mcspi1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcspi2 */
+static struct omap_hwmod omap44xx_mcspi2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi2_irqs[] = {
+	{ .irq = 66 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi2_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 42 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 43 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx1", .dma_req = 44 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx1", .dma_req = 45 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi2_addrs[] = {
+	{
+		.pa_start	= 0x4809a000,
+		.pa_end		= 0x4809a1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi2_slaves[] = {
+	&omap44xx_l4_per__mcspi2,
+};
+
+/* mcspi2 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi2_dev_attr = {
+	.num_chipselect	= 2,
+};
+
+static struct omap_hwmod omap44xx_mcspi2_hwmod = {
+	.name		= "mcspi2",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi2_irqs),
+	.sdma_reqs	= omap44xx_mcspi2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi2_sdma_reqs),
+	.main_clk	= "mcspi2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi2_dev_attr,
+	.slaves		= omap44xx_mcspi2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcspi3 */
+static struct omap_hwmod omap44xx_mcspi3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi3_irqs[] = {
+	{ .irq = 91 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi3_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 14 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 15 + OMAP44XX_DMA_REQ_START },
+	{ .name = "tx1", .dma_req = 22 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx1", .dma_req = 23 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi3_addrs[] = {
+	{
+		.pa_start	= 0x480b8000,
+		.pa_end		= 0x480b81ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi3_slaves[] = {
+	&omap44xx_l4_per__mcspi3,
+};
+
+/* mcspi3 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi3_dev_attr = {
+	.num_chipselect	= 2,
+};
+
+static struct omap_hwmod omap44xx_mcspi3_hwmod = {
+	.name		= "mcspi3",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi3_irqs),
+	.sdma_reqs	= omap44xx_mcspi3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi3_sdma_reqs),
+	.main_clk	= "mcspi3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi3_dev_attr,
+	.slaves		= omap44xx_mcspi3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mcspi4 */
+static struct omap_hwmod omap44xx_mcspi4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mcspi4_irqs[] = {
+	{ .irq = 48 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mcspi4_sdma_reqs[] = {
+	{ .name = "tx0", .dma_req = 69 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx0", .dma_req = 70 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mcspi4_addrs[] = {
+	{
+		.pa_start	= 0x480ba000,
+		.pa_end		= 0x480ba1ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mcspi4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mcspi4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mcspi4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mcspi4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mcspi4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mcspi4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mcspi4_slaves[] = {
+	&omap44xx_l4_per__mcspi4,
+};
+
+/* mcspi4 dev_attr */
+static struct omap2_mcspi_dev_attr mcspi4_dev_attr = {
+	.num_chipselect	= 1,
+};
+
+static struct omap_hwmod omap44xx_mcspi4_hwmod = {
+	.name		= "mcspi4",
+	.class		= &omap44xx_mcspi_hwmod_class,
+	.mpu_irqs	= omap44xx_mcspi4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mcspi4_irqs),
+	.sdma_reqs	= omap44xx_mcspi4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mcspi4_sdma_reqs),
+	.main_clk	= "mcspi4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mcspi4_dev_attr,
+	.slaves		= omap44xx_mcspi4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mcspi4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'mmc' class
+ * multimedia card high-speed/sd/sdio (mmc/sd/sdio) host controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_mmc_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_MIDLEMODE |
+			   SYSC_HAS_RESET_STATUS | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_mmc_hwmod_class = {
+	.name	= "mmc",
+	.sysc	= &omap44xx_mmc_sysc,
+};
+
+/* mmc1 */
+
+static struct omap_hwmod_irq_info omap44xx_mmc1_irqs[] = {
+	{ .irq = 83 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc1_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 60 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 61 + OMAP44XX_DMA_REQ_START },
+};
+
+/* mmc1 master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc1_masters[] = {
+	&omap44xx_mmc1__l3_main_1,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc1_addrs[] = {
+	{
+		.pa_start	= 0x4809c000,
+		.pa_end		= 0x4809c3ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc1 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc1_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc1_slaves[] = {
+	&omap44xx_l4_per__mmc1,
+};
+
+/* mmc1 dev_attr */
+static struct omap_mmc_dev_attr mmc1_dev_attr = {
+	.flags	= OMAP_HSMMC_SUPPORTS_DUAL_VOLT,
+};
+
+static struct omap_hwmod omap44xx_mmc1_hwmod = {
+	.name		= "mmc1",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc1_irqs),
+	.sdma_reqs	= omap44xx_mmc1_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc1_sdma_reqs),
+	.main_clk	= "mmc1_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
+		},
+	},
+	.dev_attr	= &mmc1_dev_attr,
+	.slaves		= omap44xx_mmc1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc1_slaves),
+	.masters	= omap44xx_mmc1_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc1_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc2 */
+static struct omap_hwmod_irq_info omap44xx_mmc2_irqs[] = {
+	{ .irq = 86 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc2_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 46 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 47 + OMAP44XX_DMA_REQ_START },
+};
+
+/* mmc2 master ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc2_masters[] = {
+	&omap44xx_mmc2__l3_main_1,
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc2_addrs[] = {
+	{
+		.pa_start	= 0x480b4000,
+		.pa_end		= 0x480b43ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc2_slaves[] = {
+	&omap44xx_l4_per__mmc2,
+};
+
+static struct omap_hwmod omap44xx_mmc2_hwmod = {
+	.name		= "mmc2",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc2_irqs),
+	.sdma_reqs	= omap44xx_mmc2_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc2_sdma_reqs),
+	.main_clk	= "mmc2_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc2_slaves),
+	.masters	= omap44xx_mmc2_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_mmc2_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc3 */
+static struct omap_hwmod omap44xx_mmc3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmc3_irqs[] = {
+	{ .irq = 94 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc3_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 76 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 77 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc3_addrs[] = {
+	{
+		.pa_start	= 0x480ad000,
+		.pa_end		= 0x480ad3ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc3_slaves[] = {
+	&omap44xx_l4_per__mmc3,
+};
+
+static struct omap_hwmod omap44xx_mmc3_hwmod = {
+	.name		= "mmc3",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc3_irqs),
+	.sdma_reqs	= omap44xx_mmc3_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc3_sdma_reqs),
+	.main_clk	= "mmc3_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc4 */
+static struct omap_hwmod omap44xx_mmc4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmc4_irqs[] = {
+	{ .irq = 96 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc4_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 56 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 57 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc4_addrs[] = {
+	{
+		.pa_start	= 0x480d1000,
+		.pa_end		= 0x480d13ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc4_slaves[] = {
+	&omap44xx_l4_per__mmc4,
+};
+
+static struct omap_hwmod omap44xx_mmc4_hwmod = {
+	.name		= "mmc4",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc4_irqs),
+	.sdma_reqs	= omap44xx_mmc4_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc4_sdma_reqs),
+	.main_clk	= "mmc4_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* mmc5 */
+static struct omap_hwmod omap44xx_mmc5_hwmod;
+static struct omap_hwmod_irq_info omap44xx_mmc5_irqs[] = {
+	{ .irq = 59 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_dma_info omap44xx_mmc5_sdma_reqs[] = {
+	{ .name = "tx", .dma_req = 58 + OMAP44XX_DMA_REQ_START },
+	{ .name = "rx", .dma_req = 59 + OMAP44XX_DMA_REQ_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_mmc5_addrs[] = {
+	{
+		.pa_start	= 0x480d5000,
+		.pa_end		= 0x480d53ff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> mmc5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__mmc5 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_mmc5_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_mmc5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_mmc5_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* mmc5 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_mmc5_slaves[] = {
+	&omap44xx_l4_per__mmc5,
+};
+
+static struct omap_hwmod omap44xx_mmc5_hwmod = {
+	.name		= "mmc5",
+	.class		= &omap44xx_mmc_hwmod_class,
+	.mpu_irqs	= omap44xx_mmc5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_mmc5_irqs),
+	.sdma_reqs	= omap44xx_mmc5_sdma_reqs,
+	.sdma_reqs_cnt	= ARRAY_SIZE(omap44xx_mmc5_sdma_reqs),
+	.main_clk	= "mmc5_fck",
+	.prcm		= {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_mmc5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_mmc5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'mpu' class
  * mpu sub-system
  */
@@ -1639,6 +3913,676 @@
 };
 
 /*
+ * 'spinlock' class
+ * spinlock provides hardware assistance for synchronizing the processes
+ * running on multiple processors
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_spinlock_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_ENAWAKEUP | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_spinlock_hwmod_class = {
+	.name	= "spinlock",
+	.sysc	= &omap44xx_spinlock_sysc,
+};
+
+/* spinlock */
+static struct omap_hwmod omap44xx_spinlock_hwmod;
+static struct omap_hwmod_addr_space omap44xx_spinlock_addrs[] = {
+	{
+		.pa_start	= 0x4a0f6000,
+		.pa_end		= 0x4a0f6fff,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> spinlock */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__spinlock = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_spinlock_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_spinlock_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_spinlock_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* spinlock slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_spinlock_slaves[] = {
+	&omap44xx_l4_cfg__spinlock,
+};
+
+static struct omap_hwmod omap44xx_spinlock_hwmod = {
+	.name		= "spinlock",
+	.class		= &omap44xx_spinlock_hwmod_class,
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4CFG_HW_SEM_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_spinlock_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_spinlock_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
+ * 'timer' class
+ * general purpose timer module with accurate 1ms tick
+ * This class contains several variants: ['timer_1ms', 'timer']
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_timer_1ms_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.syss_offs	= 0x0014,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_CLOCKACTIVITY |
+			   SYSC_HAS_EMUFREE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET |
+			   SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_timer_1ms_hwmod_class = {
+	.name	= "timer",
+	.sysc	= &omap44xx_timer_1ms_sysc,
+};
+
+static struct omap_hwmod_class_sysconfig omap44xx_timer_sysc = {
+	.rev_offs	= 0x0000,
+	.sysc_offs	= 0x0010,
+	.sysc_flags	= (SYSC_HAS_EMUFREE | SYSC_HAS_RESET_STATUS |
+			   SYSC_HAS_SIDLEMODE | SYSC_HAS_SOFTRESET),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP),
+	.sysc_fields	= &omap_hwmod_sysc_type2,
+};
+
+static struct omap_hwmod_class omap44xx_timer_hwmod_class = {
+	.name	= "timer",
+	.sysc	= &omap44xx_timer_sysc,
+};
+
+/* timer1 */
+static struct omap_hwmod omap44xx_timer1_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer1_irqs[] = {
+	{ .irq = 37 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer1_addrs[] = {
+	{
+		.pa_start	= 0x4a318000,
+		.pa_end		= 0x4a31807f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_wkup -> timer1 */
+static struct omap_hwmod_ocp_if omap44xx_l4_wkup__timer1 = {
+	.master		= &omap44xx_l4_wkup_hwmod,
+	.slave		= &omap44xx_timer1_hwmod,
+	.clk		= "l4_wkup_clk_mux_ck",
+	.addr		= omap44xx_timer1_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer1_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer1 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer1_slaves[] = {
+	&omap44xx_l4_wkup__timer1,
+};
+
+static struct omap_hwmod omap44xx_timer1_hwmod = {
+	.name		= "timer1",
+	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.mpu_irqs	= omap44xx_timer1_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer1_irqs),
+	.main_clk	= "timer1_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer1_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer1_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer2 */
+static struct omap_hwmod omap44xx_timer2_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer2_irqs[] = {
+	{ .irq = 38 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer2_addrs[] = {
+	{
+		.pa_start	= 0x48032000,
+		.pa_end		= 0x4803207f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer2 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer2 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer2_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_timer2_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer2_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer2 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer2_slaves[] = {
+	&omap44xx_l4_per__timer2,
+};
+
+static struct omap_hwmod omap44xx_timer2_hwmod = {
+	.name		= "timer2",
+	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.mpu_irqs	= omap44xx_timer2_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer2_irqs),
+	.main_clk	= "timer2_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer2_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer2_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer3 */
+static struct omap_hwmod omap44xx_timer3_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer3_irqs[] = {
+	{ .irq = 39 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer3_addrs[] = {
+	{
+		.pa_start	= 0x48034000,
+		.pa_end		= 0x4803407f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer3 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer3 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer3_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_timer3_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer3_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer3 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer3_slaves[] = {
+	&omap44xx_l4_per__timer3,
+};
+
+static struct omap_hwmod omap44xx_timer3_hwmod = {
+	.name		= "timer3",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer3_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer3_irqs),
+	.main_clk	= "timer3_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer3_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer3_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer4 */
+static struct omap_hwmod omap44xx_timer4_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer4_irqs[] = {
+	{ .irq = 40 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer4_addrs[] = {
+	{
+		.pa_start	= 0x48036000,
+		.pa_end		= 0x4803607f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer4 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer4 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer4_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_timer4_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer4_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer4 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer4_slaves[] = {
+	&omap44xx_l4_per__timer4,
+};
+
+static struct omap_hwmod omap44xx_timer4_hwmod = {
+	.name		= "timer4",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer4_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer4_irqs),
+	.main_clk	= "timer4_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer4_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer4_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer5 */
+static struct omap_hwmod omap44xx_timer5_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer5_irqs[] = {
+	{ .irq = 41 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer5_addrs[] = {
+	{
+		.pa_start	= 0x40138000,
+		.pa_end		= 0x4013807f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer5 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer5_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer5_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer5_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer5_dma_addrs[] = {
+	{
+		.pa_start	= 0x49038000,
+		.pa_end		= 0x4903807f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer5 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer5_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer5_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer5_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer5_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* timer5 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer5_slaves[] = {
+	&omap44xx_l4_abe__timer5,
+	&omap44xx_l4_abe__timer5_dma,
+};
+
+static struct omap_hwmod omap44xx_timer5_hwmod = {
+	.name		= "timer5",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer5_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer5_irqs),
+	.main_clk	= "timer5_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer5_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer5_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer6 */
+static struct omap_hwmod omap44xx_timer6_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer6_irqs[] = {
+	{ .irq = 42 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer6_addrs[] = {
+	{
+		.pa_start	= 0x4013a000,
+		.pa_end		= 0x4013a07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer6 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer6_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer6_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer6_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer6_dma_addrs[] = {
+	{
+		.pa_start	= 0x4903a000,
+		.pa_end		= 0x4903a07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer6 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer6_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer6_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer6_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer6_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* timer6 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer6_slaves[] = {
+	&omap44xx_l4_abe__timer6,
+	&omap44xx_l4_abe__timer6_dma,
+};
+
+static struct omap_hwmod omap44xx_timer6_hwmod = {
+	.name		= "timer6",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer6_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer6_irqs),
+	.main_clk	= "timer6_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer6_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer6_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer7 */
+static struct omap_hwmod omap44xx_timer7_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer7_irqs[] = {
+	{ .irq = 43 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer7_addrs[] = {
+	{
+		.pa_start	= 0x4013c000,
+		.pa_end		= 0x4013c07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer7 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer7_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer7_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer7_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer7_dma_addrs[] = {
+	{
+		.pa_start	= 0x4903c000,
+		.pa_end		= 0x4903c07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer7 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer7_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer7_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer7_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer7_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* timer7 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer7_slaves[] = {
+	&omap44xx_l4_abe__timer7,
+	&omap44xx_l4_abe__timer7_dma,
+};
+
+static struct omap_hwmod omap44xx_timer7_hwmod = {
+	.name		= "timer7",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer7_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer7_irqs),
+	.main_clk	= "timer7_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer7_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer7_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer8 */
+static struct omap_hwmod omap44xx_timer8_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer8_irqs[] = {
+	{ .irq = 44 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer8_addrs[] = {
+	{
+		.pa_start	= 0x4013e000,
+		.pa_end		= 0x4013e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer8 */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8 = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer8_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer8_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer8_addrs),
+	.user		= OCP_USER_MPU,
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer8_dma_addrs[] = {
+	{
+		.pa_start	= 0x4903e000,
+		.pa_end		= 0x4903e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_abe -> timer8 (dma) */
+static struct omap_hwmod_ocp_if omap44xx_l4_abe__timer8_dma = {
+	.master		= &omap44xx_l4_abe_hwmod,
+	.slave		= &omap44xx_timer8_hwmod,
+	.clk		= "ocp_abe_iclk",
+	.addr		= omap44xx_timer8_dma_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer8_dma_addrs),
+	.user		= OCP_USER_SDMA,
+};
+
+/* timer8 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer8_slaves[] = {
+	&omap44xx_l4_abe__timer8,
+	&omap44xx_l4_abe__timer8_dma,
+};
+
+static struct omap_hwmod omap44xx_timer8_hwmod = {
+	.name		= "timer8",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer8_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer8_irqs),
+	.main_clk	= "timer8_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer8_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer8_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer9 */
+static struct omap_hwmod omap44xx_timer9_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer9_irqs[] = {
+	{ .irq = 45 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer9_addrs[] = {
+	{
+		.pa_start	= 0x4803e000,
+		.pa_end		= 0x4803e07f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer9 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer9 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer9_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_timer9_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer9_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer9 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer9_slaves[] = {
+	&omap44xx_l4_per__timer9,
+};
+
+static struct omap_hwmod omap44xx_timer9_hwmod = {
+	.name		= "timer9",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer9_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer9_irqs),
+	.main_clk	= "timer9_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer9_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer9_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer10 */
+static struct omap_hwmod omap44xx_timer10_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer10_irqs[] = {
+	{ .irq = 46 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer10_addrs[] = {
+	{
+		.pa_start	= 0x48086000,
+		.pa_end		= 0x4808607f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer10 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer10 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer10_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_timer10_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer10_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer10 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer10_slaves[] = {
+	&omap44xx_l4_per__timer10,
+};
+
+static struct omap_hwmod omap44xx_timer10_hwmod = {
+	.name		= "timer10",
+	.class		= &omap44xx_timer_1ms_hwmod_class,
+	.mpu_irqs	= omap44xx_timer10_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer10_irqs),
+	.main_clk	= "timer10_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer10_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer10_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/* timer11 */
+static struct omap_hwmod omap44xx_timer11_hwmod;
+static struct omap_hwmod_irq_info omap44xx_timer11_irqs[] = {
+	{ .irq = 47 + OMAP44XX_IRQ_GIC_START },
+};
+
+static struct omap_hwmod_addr_space omap44xx_timer11_addrs[] = {
+	{
+		.pa_start	= 0x48088000,
+		.pa_end		= 0x4808807f,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_per -> timer11 */
+static struct omap_hwmod_ocp_if omap44xx_l4_per__timer11 = {
+	.master		= &omap44xx_l4_per_hwmod,
+	.slave		= &omap44xx_timer11_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_timer11_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_timer11_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* timer11 slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_timer11_slaves[] = {
+	&omap44xx_l4_per__timer11,
+};
+
+static struct omap_hwmod omap44xx_timer11_hwmod = {
+	.name		= "timer11",
+	.class		= &omap44xx_timer_hwmod_class,
+	.mpu_irqs	= omap44xx_timer11_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_timer11_irqs),
+	.main_clk	= "timer11_fck",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
+		},
+	},
+	.slaves		= omap44xx_timer11_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_timer11_slaves),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'uart' class
  * universal asynchronous receiver/transmitter (uart)
  */
@@ -1870,6 +4814,88 @@
 };
 
 /*
+ * 'usb_otg_hs' class
+ * high-speed on-the-go universal serial bus (usb_otg_hs) controller
+ */
+
+static struct omap_hwmod_class_sysconfig omap44xx_usb_otg_hs_sysc = {
+	.rev_offs	= 0x0400,
+	.sysc_offs	= 0x0404,
+	.syss_offs	= 0x0408,
+	.sysc_flags	= (SYSC_HAS_AUTOIDLE | SYSC_HAS_ENAWAKEUP |
+			   SYSC_HAS_MIDLEMODE | SYSC_HAS_SIDLEMODE |
+			   SYSC_HAS_SOFTRESET | SYSS_HAS_RESET_STATUS),
+	.idlemodes	= (SIDLE_FORCE | SIDLE_NO | SIDLE_SMART |
+			   SIDLE_SMART_WKUP | MSTANDBY_FORCE | MSTANDBY_NO |
+			   MSTANDBY_SMART),
+	.sysc_fields	= &omap_hwmod_sysc_type1,
+};
+
+static struct omap_hwmod_class omap44xx_usb_otg_hs_hwmod_class = {
+	.name = "usb_otg_hs",
+	.sysc = &omap44xx_usb_otg_hs_sysc,
+};
+
+/* usb_otg_hs */
+static struct omap_hwmod_irq_info omap44xx_usb_otg_hs_irqs[] = {
+	{ .name = "mc", .irq = 92 + OMAP44XX_IRQ_GIC_START },
+	{ .name = "dma", .irq = 93 + OMAP44XX_IRQ_GIC_START },
+};
+
+/* usb_otg_hs master ports */
+static struct omap_hwmod_ocp_if *omap44xx_usb_otg_hs_masters[] = {
+	&omap44xx_usb_otg_hs__l3_main_2,
+};
+
+static struct omap_hwmod_addr_space omap44xx_usb_otg_hs_addrs[] = {
+	{
+		.pa_start	= 0x4a0ab000,
+		.pa_end		= 0x4a0ab003,
+		.flags		= ADDR_TYPE_RT
+	},
+};
+
+/* l4_cfg -> usb_otg_hs */
+static struct omap_hwmod_ocp_if omap44xx_l4_cfg__usb_otg_hs = {
+	.master		= &omap44xx_l4_cfg_hwmod,
+	.slave		= &omap44xx_usb_otg_hs_hwmod,
+	.clk		= "l4_div_ck",
+	.addr		= omap44xx_usb_otg_hs_addrs,
+	.addr_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_addrs),
+	.user		= OCP_USER_MPU | OCP_USER_SDMA,
+};
+
+/* usb_otg_hs slave ports */
+static struct omap_hwmod_ocp_if *omap44xx_usb_otg_hs_slaves[] = {
+	&omap44xx_l4_cfg__usb_otg_hs,
+};
+
+static struct omap_hwmod_opt_clk usb_otg_hs_opt_clks[] = {
+	{ .role = "xclk", .clk = "usb_otg_hs_xclk" },
+};
+
+static struct omap_hwmod omap44xx_usb_otg_hs_hwmod = {
+	.name		= "usb_otg_hs",
+	.class		= &omap44xx_usb_otg_hs_hwmod_class,
+	.flags		= HWMOD_SWSUP_SIDLE | HWMOD_SWSUP_MSTANDBY,
+	.mpu_irqs	= omap44xx_usb_otg_hs_irqs,
+	.mpu_irqs_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_irqs),
+	.main_clk	= "usb_otg_hs_ick",
+	.prcm = {
+		.omap4 = {
+			.clkctrl_reg = OMAP4430_CM_L3INIT_USB_OTG_CLKCTRL,
+		},
+	},
+	.opt_clks	= usb_otg_hs_opt_clks,
+	.opt_clks_cnt = ARRAY_SIZE(usb_otg_hs_opt_clks),
+	.slaves		= omap44xx_usb_otg_hs_slaves,
+	.slaves_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_slaves),
+	.masters	= omap44xx_usb_otg_hs_masters,
+	.masters_cnt	= ARRAY_SIZE(omap44xx_usb_otg_hs_masters),
+	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
+};
+
+/*
  * 'wd_timer' class
  * 32-bit watchdog upward counter that generates a pulse on the reset pin on
  * overflow condition
@@ -2024,13 +5050,34 @@
 	/* mpu_bus class */
 	&omap44xx_mpu_private_hwmod,
 
+	/* aess class */
+/*	&omap44xx_aess_hwmod, */
+
+	/* bandgap class */
+	&omap44xx_bandgap_hwmod,
+
+	/* counter class */
+/*	&omap44xx_counter_32k_hwmod, */
+
 	/* dma class */
 	&omap44xx_dma_system_hwmod,
 
+	/* dmic class */
+	&omap44xx_dmic_hwmod,
+
 	/* dsp class */
 	&omap44xx_dsp_hwmod,
 	&omap44xx_dsp_c0_hwmod,
 
+	/* dss class */
+	&omap44xx_dss_hwmod,
+	&omap44xx_dss_dispc_hwmod,
+	&omap44xx_dss_dsi1_hwmod,
+	&omap44xx_dss_dsi2_hwmod,
+	&omap44xx_dss_hdmi_hwmod,
+	&omap44xx_dss_rfbi_hwmod,
+	&omap44xx_dss_venc_hwmod,
+
 	/* gpio class */
 	&omap44xx_gpio1_hwmod,
 	&omap44xx_gpio2_hwmod,
@@ -2039,17 +5086,56 @@
 	&omap44xx_gpio5_hwmod,
 	&omap44xx_gpio6_hwmod,
 
+	/* hsi class */
+/*	&omap44xx_hsi_hwmod, */
+
 	/* i2c class */
 	&omap44xx_i2c1_hwmod,
 	&omap44xx_i2c2_hwmod,
 	&omap44xx_i2c3_hwmod,
 	&omap44xx_i2c4_hwmod,
 
+	/* ipu class */
+	&omap44xx_ipu_hwmod,
+	&omap44xx_ipu_c0_hwmod,
+	&omap44xx_ipu_c1_hwmod,
+
+	/* iss class */
+/*	&omap44xx_iss_hwmod, */
+
 	/* iva class */
 	&omap44xx_iva_hwmod,
 	&omap44xx_iva_seq0_hwmod,
 	&omap44xx_iva_seq1_hwmod,
 
+	/* kbd class */
+/*	&omap44xx_kbd_hwmod, */
+
+	/* mailbox class */
+	&omap44xx_mailbox_hwmod,
+
+	/* mcbsp class */
+	&omap44xx_mcbsp1_hwmod,
+	&omap44xx_mcbsp2_hwmod,
+	&omap44xx_mcbsp3_hwmod,
+	&omap44xx_mcbsp4_hwmod,
+
+	/* mcpdm class */
+/*	&omap44xx_mcpdm_hwmod, */
+
+	/* mcspi class */
+	&omap44xx_mcspi1_hwmod,
+	&omap44xx_mcspi2_hwmod,
+	&omap44xx_mcspi3_hwmod,
+	&omap44xx_mcspi4_hwmod,
+
+	/* mmc class */
+	&omap44xx_mmc1_hwmod,
+	&omap44xx_mmc2_hwmod,
+	&omap44xx_mmc3_hwmod,
+	&omap44xx_mmc4_hwmod,
+	&omap44xx_mmc5_hwmod,
+
 	/* mpu class */
 	&omap44xx_mpu_hwmod,
 
@@ -2058,12 +5144,31 @@
 	&omap44xx_smartreflex_iva_hwmod,
 	&omap44xx_smartreflex_mpu_hwmod,
 
+	/* spinlock class */
+	&omap44xx_spinlock_hwmod,
+
+	/* timer class */
+	&omap44xx_timer1_hwmod,
+	&omap44xx_timer2_hwmod,
+	&omap44xx_timer3_hwmod,
+	&omap44xx_timer4_hwmod,
+	&omap44xx_timer5_hwmod,
+	&omap44xx_timer6_hwmod,
+	&omap44xx_timer7_hwmod,
+	&omap44xx_timer8_hwmod,
+	&omap44xx_timer9_hwmod,
+	&omap44xx_timer10_hwmod,
+	&omap44xx_timer11_hwmod,
+
 	/* uart class */
 	&omap44xx_uart1_hwmod,
 	&omap44xx_uart2_hwmod,
 	&omap44xx_uart3_hwmod,
 	&omap44xx_uart4_hwmod,
 
+	/* usb_otg_hs class */
+	&omap44xx_usb_otg_hs_hwmod,
+
 	/* wd_timer class */
 	&omap44xx_wd_timer2_hwmod,
 	&omap44xx_wd_timer3_hwmod,
@@ -2073,6 +5178,6 @@
 
 int __init omap44xx_hwmod_init(void)
 {
-	return omap_hwmod_init(omap44xx_hwmods);
+	return omap_hwmod_register(omap44xx_hwmods);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_hwmod.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_hwmod.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod implementation for OMAP2/3/4
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Paul Walmsley, BenoÃ®t Cousson, Kevin Hilman
  *
@@ -162,9 +162,6 @@
 /* mpu_oh: used to add/remove MPU initiator from sleepdep list */
 static struct omap_hwmod *mpu_oh;
 
-/* inited: 0 if omap_hwmod_init() has not yet been called; 1 otherwise */
-static u8 inited;
-
 
 /* Private functions */
 
@@ -373,7 +370,7 @@
 	}
 
 	autoidle_shift = oh->class->sysc->sysc_fields->autoidle_shift;
-	autoidle_mask = (0x3 << autoidle_shift);
+	autoidle_mask = (0x1 << autoidle_shift);
 
 	*v &= ~autoidle_mask;
 	*v |= autoidle << autoidle_shift;
@@ -460,14 +457,18 @@
  * will be accessed by a particular initiator (e.g., if a module will
  * be accessed by the IVA, there should be a sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
- * mode.  Returns -EINVAL upon error or passes along
- * clkdm_add_sleepdep() value upon success.
+ * mode.  If the clockdomain is marked as not needing autodeps, return
+ * 0 without doing anything.  Otherwise, returns -EINVAL upon error or
+ * passes along clkdm_add_sleepdep() value upon success.
  */
 static int _add_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
+	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+		return 0;
+
 	return clkdm_add_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
@@ -480,14 +481,18 @@
  * be accessed by a particular initiator (e.g., if a module will not
  * be accessed by the IVA, there should be no sleepdep between the IVA
  * initiator and the module).  Only applies to modules in smart-idle
- * mode.  Returns -EINVAL upon error or passes along
- * clkdm_del_sleepdep() value upon success.
+ * mode.  If the clockdomain is marked as not needing autodeps, return
+ * 0 without doing anything.  Returns -EINVAL upon error or passes
+ * along clkdm_del_sleepdep() value upon success.
  */
 static int _del_initiator_dep(struct omap_hwmod *oh, struct omap_hwmod *init_oh)
 {
 	if (!oh->_clk)
 		return -EINVAL;
 
+	if (oh->_clk->clkdm && oh->_clk->clkdm->flags & CLKDM_NO_AUTODEPS)
+		return 0;
+
 	return clkdm_del_sleepdep(oh->_clk->clkdm, init_oh->_clk->clkdm);
 }
 
@@ -904,18 +909,16 @@
  * @oh: struct omap_hwmod *
  * @data: not used; pass NULL
  *
- * Called by omap_hwmod_late_init() (after omap2_clk_init()).
- * Resolves all clock names embedded in the hwmod.  Returns -EINVAL if
- * the omap_hwmod has not yet been registered or if the clocks have
- * already been initialized, 0 on success, or a non-zero error on
- * failure.
+ * Called by omap_hwmod_setup_*() (after omap2_clk_init()).
+ * Resolves all clock names embedded in the hwmod.  Returns 0 on
+ * success, or a negative error code on failure.
  */
 static int _init_clocks(struct omap_hwmod *oh, void *data)
 {
 	int ret = 0;
 
-	if (!oh || (oh->_state != _HWMOD_STATE_REGISTERED))
-		return -EINVAL;
+	if (oh->_state != _HWMOD_STATE_REGISTERED)
+		return 0;
 
 	pr_debug("omap_hwmod: %s: looking up clocks\n", oh->name);
 
@@ -926,7 +929,7 @@
 	if (!ret)
 		oh->_state = _HWMOD_STATE_CLKS_INITED;
 
-	return 0;
+	return ret;
 }
 
 /**
@@ -972,25 +975,29 @@
 }
 
 /**
- * _lookup_hardreset - return the register bit shift for this hwmod/reset line
+ * _lookup_hardreset - fill register bit info for this hwmod/reset line
  * @oh: struct omap_hwmod *
  * @name: name of the reset line in the context of this hwmod
+ * @ohri: struct omap_hwmod_rst_info * that this function will fill in
  *
  * Return the bit position of the reset line that match the
  * input name. Return -ENOENT if not found.
  */
-static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name)
+static u8 _lookup_hardreset(struct omap_hwmod *oh, const char *name,
+			    struct omap_hwmod_rst_info *ohri)
 {
 	int i;
 
 	for (i = 0; i < oh->rst_lines_cnt; i++) {
 		const char *rst_line = oh->rst_lines[i].name;
 		if (!strcmp(rst_line, name)) {
-			u8 shift = oh->rst_lines[i].rst_shift;
-			pr_debug("omap_hwmod: %s: _lookup_hardreset: %s: %d\n",
-				 oh->name, rst_line, shift);
+			ohri->rst_shift = oh->rst_lines[i].rst_shift;
+			ohri->st_shift = oh->rst_lines[i].st_shift;
+			pr_debug("omap_hwmod: %s: %s: %s: rst %d st %d\n",
+				 oh->name, __func__, rst_line, ohri->rst_shift,
+				 ohri->st_shift);
 
-			return shift;
+			return 0;
 		}
 	}
 
@@ -1009,21 +1016,22 @@
  */
 static int _assert_hardreset(struct omap_hwmod *oh, const char *name)
 {
-	u8 shift;
+	struct omap_hwmod_rst_info ohri;
+	u8 ret;
 
 	if (!oh)
 		return -EINVAL;
 
-	shift = _lookup_hardreset(oh, name);
-	if (IS_ERR_VALUE(shift))
-		return shift;
+	ret = _lookup_hardreset(oh, name, &ohri);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (cpu_is_omap24xx() || cpu_is_omap34xx())
 		return omap2_prm_assert_hardreset(oh->prcm.omap2.module_offs,
-						  shift);
+						  ohri.rst_shift);
 	else if (cpu_is_omap44xx())
 		return omap4_prm_assert_hardreset(oh->prcm.omap4.rstctrl_reg,
-						  shift);
+						  ohri.rst_shift);
 	else
 		return -EINVAL;
 }
@@ -1040,29 +1048,34 @@
  */
 static int _deassert_hardreset(struct omap_hwmod *oh, const char *name)
 {
-	u8 shift;
-	int r;
+	struct omap_hwmod_rst_info ohri;
+	int ret;
 
 	if (!oh)
 		return -EINVAL;
 
-	shift = _lookup_hardreset(oh, name);
-	if (IS_ERR_VALUE(shift))
-		return shift;
+	ret = _lookup_hardreset(oh, name, &ohri);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
-	if (cpu_is_omap24xx() || cpu_is_omap34xx())
-		r = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
-						 shift);
-	else if (cpu_is_omap44xx())
-		r = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
-						 shift);
-	else
+	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
+		ret = omap2_prm_deassert_hardreset(oh->prcm.omap2.module_offs,
+						   ohri.rst_shift,
+						   ohri.st_shift);
+	} else if (cpu_is_omap44xx()) {
+		if (ohri.st_shift)
+			pr_err("omap_hwmod: %s: %s: hwmod data error: OMAP4 does not support st_shift\n",
+			       oh->name, name);
+		ret = omap4_prm_deassert_hardreset(oh->prcm.omap4.rstctrl_reg,
+						   ohri.rst_shift);
+	} else {
 		return -EINVAL;
+	}
 
-	if (r == -EBUSY)
+	if (ret == -EBUSY)
 		pr_warning("omap_hwmod: %s: failed to hardreset\n", oh->name);
 
-	return r;
+	return ret;
 }
 
 /**
@@ -1075,21 +1088,22 @@
  */
 static int _read_hardreset(struct omap_hwmod *oh, const char *name)
 {
-	u8 shift;
+	struct omap_hwmod_rst_info ohri;
+	u8 ret;
 
 	if (!oh)
 		return -EINVAL;
 
-	shift = _lookup_hardreset(oh, name);
-	if (IS_ERR_VALUE(shift))
-		return shift;
+	ret = _lookup_hardreset(oh, name, &ohri);
+	if (IS_ERR_VALUE(ret))
+		return ret;
 
 	if (cpu_is_omap24xx() || cpu_is_omap34xx()) {
 		return omap2_prm_is_hardreset_asserted(oh->prcm.omap2.module_offs,
-						       shift);
+						       ohri.st_shift);
 	} else if (cpu_is_omap44xx()) {
 		return omap4_prm_is_hardreset_asserted(oh->prcm.omap4.rstctrl_reg,
-						       shift);
+						       ohri.rst_shift);
 	} else {
 		return -EINVAL;
 	}
@@ -1230,7 +1244,9 @@
 		_deassert_hardreset(oh, oh->rst_lines[0].name);
 
 	/* Mux pins for device runtime if populated */
-	if (oh->mux)
+	if (oh->mux && (!oh->mux->enabled ||
+			((oh->_state == _HWMOD_STATE_IDLE) &&
+			 oh->mux->pads_dynamic)))
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_ENABLED);
 
 	_add_initiator_dep(oh, mpu_oh);
@@ -1279,7 +1295,7 @@
 	_disable_clocks(oh);
 
 	/* Mux pins for device idle if populated */
-	if (oh->mux)
+	if (oh->mux && oh->mux->pads_dynamic)
 		omap_hwmod_mux(oh->mux, _HWMOD_STATE_IDLE);
 
 	oh->_state = _HWMOD_STATE_IDLE;
@@ -1288,6 +1304,42 @@
 }
 
 /**
+ * omap_hwmod_set_ocp_autoidle - set the hwmod's OCP autoidle bit
+ * @oh: struct omap_hwmod *
+ * @autoidle: desired AUTOIDLE bitfield value (0 or 1)
+ *
+ * Sets the IP block's OCP autoidle bit in hardware, and updates our
+ * local copy. Intended to be used by drivers that require
+ * direct manipulation of the AUTOIDLE bits.
+ * Returns -EINVAL if @oh is null or is not in the ENABLED state, or passes
+ * along the return value from _set_module_autoidle().
+ *
+ * Any users of this function should be scrutinized carefully.
+ */
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle)
+{
+	u32 v;
+	int retval = 0;
+	unsigned long flags;
+
+	if (!oh || oh->_state != _HWMOD_STATE_ENABLED)
+		return -EINVAL;
+
+	spin_lock_irqsave(&oh->_lock, flags);
+
+	v = oh->_sysc_cache;
+
+	retval = _set_module_autoidle(oh, autoidle, &v);
+
+	if (!retval)
+		_write_sysconfig(v, oh);
+
+	spin_unlock_irqrestore(&oh->_lock, flags);
+
+	return retval;
+}
+
+/**
  * _shutdown - shutdown an omap_hwmod
  * @oh: struct omap_hwmod *
  *
@@ -1354,14 +1406,16 @@
  * @oh: struct omap_hwmod *
  *
  * Writes the CLOCKACTIVITY bits @clockact to the hwmod @oh
- * OCP_SYSCONFIG register.  Returns -EINVAL if the hwmod is in the
- * wrong state or returns 0.
+ * OCP_SYSCONFIG register.  Returns 0.
  */
 static int _setup(struct omap_hwmod *oh, void *data)
 {
 	int i, r;
 	u8 postsetup_state;
 
+	if (oh->_state != _HWMOD_STATE_CLKS_INITED)
+		return 0;
+
 	/* Set iclk autoidle mode */
 	if (oh->slaves_cnt > 0) {
 		for (i = 0; i < oh->slaves_cnt; i++) {
@@ -1455,7 +1509,7 @@
  */
 static int __init _register(struct omap_hwmod *oh)
 {
-	int ret, ms_id;
+	int ms_id;
 
 	if (!oh || !oh->name || !oh->class || !oh->class->name ||
 	    (oh->_state != _HWMOD_STATE_UNKNOWN))
@@ -1467,12 +1521,10 @@
 		return -EEXIST;
 
 	ms_id = _find_mpu_port_index(oh);
-	if (!IS_ERR_VALUE(ms_id)) {
+	if (!IS_ERR_VALUE(ms_id))
 		oh->_mpu_port_index = ms_id;
-		oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
-	} else {
+	else
 		oh->_int_flags |= _HWMOD_NO_MPU_PORT;
-	}
 
 	list_add_tail(&oh->node, &omap_hwmod_list);
 
@@ -1480,9 +1532,14 @@
 
 	oh->_state = _HWMOD_STATE_REGISTERED;
 
-	ret = 0;
+	/*
+	 * XXX Rather than doing a strcmp(), this should test a flag
+	 * set in the hwmod data, inserted by the autogenerator code.
+	 */
+	if (!strcmp(oh->name, MPU_INITIATOR_NAME))
+		mpu_oh = oh;
 
-	return ret;
+	return 0;
 }
 
 
@@ -1585,65 +1642,132 @@
 	return ret;
 }
 
-
 /**
- * omap_hwmod_init - init omap_hwmod code and register hwmods
+ * omap_hwmod_register - register an array of hwmods
  * @ohs: pointer to an array of omap_hwmods to register
  *
  * Intended to be called early in boot before the clock framework is
  * initialized.  If @ohs is not null, will register all omap_hwmods
- * listed in @ohs that are valid for this chip.  Returns -EINVAL if
- * omap_hwmod_init() has already been called or 0 otherwise.
+ * listed in @ohs that are valid for this chip.  Returns 0.
  */
-int __init omap_hwmod_init(struct omap_hwmod **ohs)
+int __init omap_hwmod_register(struct omap_hwmod **ohs)
+{
+	int r, i;
+
+	if (!ohs)
+		return 0;
+
+	i = 0;
+	do {
+		if (!omap_chip_is(ohs[i]->omap_chip))
+			continue;
+
+		r = _register(ohs[i]);
+		WARN(r, "omap_hwmod: %s: _register returned %d\n", ohs[i]->name,
+		     r);
+	} while (ohs[++i]);
+
+	return 0;
+}
+
+/*
+ * _populate_mpu_rt_base - populate the virtual address for a hwmod
+ *
+ * Must be called only from omap_hwmod_setup_*() so ioremap works properly.
+ * Assumes the caller takes care of locking if needed.
+ */
+static int __init _populate_mpu_rt_base(struct omap_hwmod *oh, void *data)
+{
+	if (oh->_state != _HWMOD_STATE_REGISTERED)
+		return 0;
+
+	if (oh->_int_flags & _HWMOD_NO_MPU_PORT)
+		return 0;
+
+	oh->_mpu_rt_va = _find_mpu_rt_base(oh, oh->_mpu_port_index);
+	if (!oh->_mpu_rt_va)
+		pr_warning("omap_hwmod: %s found no _mpu_rt_va for %s\n",
+				__func__, oh->name);
+
+	return 0;
+}
+
+/**
+ * omap_hwmod_setup_one - set up a single hwmod
+ * @oh_name: const char * name of the already-registered hwmod to set up
+ *
+ * Must be called after omap2_clk_init().  Resolves the struct clk
+ * names to struct clk pointers for each registered omap_hwmod.  Also
+ * calls _setup() on each hwmod.  Returns -EINVAL upon error or 0 upon
+ * success.
+ */
+int __init omap_hwmod_setup_one(const char *oh_name)
 {
 	struct omap_hwmod *oh;
 	int r;
 
-	if (inited)
+	pr_debug("omap_hwmod: %s: %s\n", oh_name, __func__);
+
+	if (!mpu_oh) {
+		pr_err("omap_hwmod: %s: cannot setup_one: MPU initiator hwmod %s not yet registered\n",
+		       oh_name, MPU_INITIATOR_NAME);
 		return -EINVAL;
+	}
 
-	inited = 1;
+	oh = _lookup(oh_name);
+	if (!oh) {
+		WARN(1, "omap_hwmod: %s: hwmod not yet registered\n", oh_name);
+		return -EINVAL;
+	}
 
-	if (!ohs)
-		return 0;
+	if (mpu_oh->_state == _HWMOD_STATE_REGISTERED && oh != mpu_oh)
+		omap_hwmod_setup_one(MPU_INITIATOR_NAME);
 
-	oh = *ohs;
-	while (oh) {
-		if (omap_chip_is(oh->omap_chip)) {
-			r = _register(oh);
-			WARN(r, "omap_hwmod: %s: _register returned "
-			     "%d\n", oh->name, r);
-		}
-		oh = *++ohs;
+	r = _populate_mpu_rt_base(oh, NULL);
+	if (IS_ERR_VALUE(r)) {
+		WARN(1, "omap_hwmod: %s: couldn't set mpu_rt_base\n", oh_name);
+		return -EINVAL;
+	}
+
+	r = _init_clocks(oh, NULL);
+	if (IS_ERR_VALUE(r)) {
+		WARN(1, "omap_hwmod: %s: couldn't init clocks\n", oh_name);
+		return -EINVAL;
 	}
 
+	_setup(oh, NULL);
+
 	return 0;
 }
 
 /**
- * omap_hwmod_late_init - do some post-clock framework initialization
+ * omap_hwmod_setup - do some post-clock framework initialization
  *
  * Must be called after omap2_clk_init().  Resolves the struct clk names
  * to struct clk pointers for each registered omap_hwmod.  Also calls
- * _setup() on each hwmod.  Returns 0.
+ * _setup() on each hwmod.  Returns 0 upon success.
  */
-int omap_hwmod_late_init(void)
+static int __init omap_hwmod_setup_all(void)
 {
 	int r;
 
-	/* XXX check return value */
-	r = omap_hwmod_for_each(_init_clocks, NULL);
-	WARN(r, "omap_hwmod: omap_hwmod_late_init(): _init_clocks failed\n");
+	if (!mpu_oh) {
+		pr_err("omap_hwmod: %s: MPU initiator hwmod %s not yet registered\n",
+		       __func__, MPU_INITIATOR_NAME);
+		return -EINVAL;
+	}
 
-	mpu_oh = omap_hwmod_lookup(MPU_INITIATOR_NAME);
-	WARN(!mpu_oh, "omap_hwmod: could not find MPU initiator hwmod %s\n",
-	     MPU_INITIATOR_NAME);
+	r = omap_hwmod_for_each(_populate_mpu_rt_base, NULL);
+
+	r = omap_hwmod_for_each(_init_clocks, NULL);
+	WARN(IS_ERR_VALUE(r),
+	     "omap_hwmod: %s: _init_clocks failed\n", __func__);
 
 	omap_hwmod_for_each(_setup, NULL);
 
 	return 0;
 }
+core_initcall(omap_hwmod_setup_all);
 
 /**
  * omap_hwmod_enable - enable an omap_hwmod
@@ -1862,6 +1986,7 @@
 		os = oh->slaves[i];
 
 		for (j = 0; j < os->addr_cnt; j++) {
+			(res + r)->name = (os->addr + j)->name;
 			(res + r)->start = (os->addr + j)->pa_start;
 			(res + r)->end = (os->addr + j)->pa_end;
 			(res + r)->flags = IORESOURCE_MEM;
@@ -2162,11 +2287,11 @@
  * @oh: struct omap_hwmod *
  * @state: state that _setup() should leave the hwmod in
  *
- * Sets the hwmod state that @oh will enter at the end of _setup() (called by
- * omap_hwmod_late_init()).  Only valid to call between calls to
- * omap_hwmod_init() and omap_hwmod_late_init().  Returns 0 upon success or
- * -EINVAL if there is a problem with the arguments or if the hwmod is
- * in the wrong state.
+ * Sets the hwmod state that @oh will enter at the end of _setup()
+ * (called by omap_hwmod_setup_*()).  Only valid to call between
+ * calling omap_hwmod_register() and omap_hwmod_setup_*().  Returns
+ * 0 upon success or -EINVAL if there is a problem with the arguments
+ * or if the hwmod is in the wrong state.
  */
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state)
 {
@@ -2218,3 +2343,29 @@
 
 	return ret;
 }
+
+/**
+ * omap_hwmod_no_setup_reset - prevent a hwmod from being reset upon setup
+ * @oh: struct omap_hwmod *
+ *
+ * Prevent the hwmod @oh from being reset during the setup process.
+ * Intended for use by board-*.c files on boards with devices that
+ * cannot tolerate being reset.  Must be called before the hwmod has
+ * been set up.  Returns 0 upon success or negative error code upon
+ * failure.
+ */
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh)
+{
+	if (!oh)
+		return -EINVAL;
+
+	if (oh->_state != _HWMOD_STATE_REGISTERED) {
+		pr_err("omap_hwmod: %s: cannot prevent setup reset; in wrong state\n",
+			oh->name);
+		return -EINVAL;
+	}
+
+	oh->flags |= HWMOD_INIT_NO_RESET;
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_noc.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_noc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_noc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_noc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,253 @@
+/*
+  * OMAP4XXX L3 Interconnect error handling driver
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	Sricharan <r.sricharan@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/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+
+#include "omap_l3_noc.h"
+
+/*
+ * Interrupt Handler for L3 error detection.
+ *	1) Identify the L3 clockdomain partition to which the error belongs to.
+ *	2) Identify the slave where the error information is logged
+ *	3) Print the logged information.
+ *	4) Add dump stack to provide kernel trace.
+ *
+ * Two Types of errors :
+ *	1) Custom errors in L3 :
+ *		Target like DMM/FW/EMIF generates SRESP=ERR error
+ *	2) Standard L3 error:
+ *		- Unsupported CMD.
+ *			L3 tries to access target while it is idle
+ *		- OCP disconnect.
+ *		- Address hole error:
+ *			If DSS/ISS/FDIF/USBHOSTFS access a target where they
+ *			do not have connectivity, the error is logged in
+ *			their default target which is DMM2.
+ *
+ *	On High Secure devices, firewall errors are possible and those
+ *	can be trapped as well. But the trapping is implemented as part
+ *	secure software and hence need not be implemented here.
+ */
+static irqreturn_t l3_interrupt_handler(int irq, void *_l3)
+{
+
+	struct omap4_l3		*l3 = _l3;
+	int inttype, i, j;
+	int err_src = 0;
+	u32 std_err_main_addr, std_err_main, err_reg;
+	u32 base, slave_addr, clear;
+	char *source_name;
+
+	/* Get the Type of interrupt */
+	if (irq == l3->app_irq)
+		inttype = L3_APPLICATION_ERROR;
+	else
+		inttype = L3_DEBUG_ERROR;
+
+	for (i = 0; i < L3_MODULES; i++) {
+		/*
+		 * Read the regerr register of the clock domain
+		 * to determine the source
+		 */
+		base = (u32)l3->l3_base[i];
+		err_reg =  readl(base + l3_flagmux[i] + (inttype << 3));
+
+		/* Get the corresponding error and analyse */
+		if (err_reg) {
+			/* Identify the source from control status register */
+			for (j = 0; !(err_reg & (1 << j)); j++)
+									;
+
+			err_src = j;
+			/* Read the stderrlog_main_source from clk domain */
+			std_err_main_addr = base + (*(l3_targ[i] + err_src));
+			std_err_main =  readl(std_err_main_addr);
+
+			switch ((std_err_main & CUSTOM_ERROR)) {
+			case STANDARD_ERROR:
+				source_name =
+				l3_targ_stderrlog_main_name[i][err_src];
+
+				slave_addr = std_err_main_addr +
+						L3_SLAVE_ADDRESS_OFFSET;
+				WARN(true, "L3 standard error: SOURCE:%s at address 0x%x\n",
+					source_name, readl(slave_addr));
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, std_err_main_addr);
+				break;
+
+			case CUSTOM_ERROR:
+				source_name =
+				l3_targ_stderrlog_main_name[i][err_src];
+
+				WARN(true, "CUSTOM SRESP error with SOURCE:%s\n",
+							source_name);
+				/* clear the std error log*/
+				clear = std_err_main | CLEAR_STDERR_LOG;
+				writel(clear, std_err_main_addr);
+				break;
+
+			default:
+				/* Nothing to be handled here as of now */
+				break;
+			}
+		/* Error found so break the for loop */
+		break;
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int __init omap4_l3_probe(struct platform_device *pdev)
+{
+	static struct omap4_l3		*l3;
+	struct resource		*res;
+	int			ret;
+	int			irq;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3)
+		ret = -ENOMEM;
+
+	platform_set_drvdata(pdev, l3);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 0\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+
+	l3->l3_base[0] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[0])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 1\n");
+		ret = -ENODEV;
+		goto err3;
+	}
+
+	l3->l3_base[1] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[1])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err4;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 2);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource 2\n");
+		ret = -ENODEV;
+		goto err5;
+	}
+
+	l3->l3_base[2] = ioremap(res->start, resource_size(res));
+	if (!(l3->l3_base[2])) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err6;
+	}
+
+	/*
+	 * Setup interrupt Handlers
+	 */
+	irq = platform_get_irq(pdev, 0);
+	ret = request_irq(irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-dbg-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+					 OMAP44XX_IRQ_L3_DBG);
+		goto err7;
+	}
+	l3->debug_irq = irq;
+
+	irq = platform_get_irq(pdev, 1);
+	ret = request_irq(irq,
+			l3_interrupt_handler,
+			IRQF_DISABLED, "l3-app-irq", l3);
+	if (ret) {
+		pr_crit("L3: request_irq failed to register for 0x%x\n",
+					 OMAP44XX_IRQ_L3_APP);
+		goto err8;
+	}
+	l3->app_irq = irq;
+
+	goto err0;
+err8:
+err7:
+	iounmap(l3->l3_base[2]);
+err6:
+err5:
+	iounmap(l3->l3_base[1]);
+err4:
+err3:
+	iounmap(l3->l3_base[0]);
+err2:
+err1:
+	kfree(l3);
+err0:
+	return ret;
+}
+
+static int __exit omap4_l3_remove(struct platform_device *pdev)
+{
+	struct omap4_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->l3_base[0]);
+	iounmap(l3->l3_base[1]);
+	iounmap(l3->l3_base[2]);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap4_l3_driver = {
+	.remove		= __exit_p(omap4_l3_remove),
+	.driver		= {
+	.name		= "omap_l3_noc",
+	},
+};
+
+static int __init omap4_l3_init(void)
+{
+	return platform_driver_probe(&omap4_l3_driver, omap4_l3_probe);
+}
+postcore_initcall_sync(omap4_l3_init);
+
+static void __exit omap4_l3_exit(void)
+{
+	platform_driver_unregister(&omap4_l3_driver);
+}
+module_exit(omap4_l3_exit);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_noc.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_noc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_noc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_noc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,132 @@
+ /*
+  * OMAP4XXX L3 Interconnect  error handling driver header
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	sricharan <r.sricharan@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
+  */
+#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/*
+ * L3 register offsets
+ */
+#define L3_MODULES			3
+#define CLEAR_STDERR_LOG		(1 << 31)
+#define CUSTOM_ERROR			0x2
+#define STANDARD_ERROR			0x0
+#define INBAND_ERROR			0x0
+#define EMIF_KERRLOG_OFFSET		0x10
+#define L3_SLAVE_ADDRESS_OFFSET		0x14
+#define LOGICAL_ADDR_ERRORLOG		0x4
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+u32 l3_flagmux[L3_MODULES] = {
+	0x50C,
+	0x100C,
+	0X020C
+};
+
+/*
+ * L3 Target standard Error register offsets
+ */
+u32 l3_targ_stderrlog_main_clk1[] = {
+	0x148, /* DMM1 */
+	0x248, /* DMM2 */
+	0x348, /* ABE */
+	0x448, /* L4CFG */
+	0x648  /* CLK2 PWR DISC */
+};
+
+u32 l3_targ_stderrlog_main_clk2[] = {
+	0x548,		/* CORTEX M3 */
+	0x348,		/* DSS */
+	0x148,		/* GPMC */
+	0x448,		/* ISS */
+	0x748,		/* IVAHD */
+	0xD48,		/* missing in TRM  corresponds to AES1*/
+	0x948,		/* L4 PER0*/
+	0x248,		/* OCMRAM */
+	0x148,		/* missing in TRM corresponds to GPMC sERROR*/
+	0x648,		/* SGX */
+	0x848,		/* SL2 */
+	0x1648,		/* C2C */
+	0x1148,		/* missing in TRM corresponds PWR DISC CLK1*/
+	0xF48,		/* missing in TRM corrsponds to SHA1*/
+	0xE48,		/* missing in TRM corresponds to AES2*/
+	0xC48,		/* L4 PER3 */
+	0xA48,		/* L4 PER1*/
+	0xB48		/* L4 PER2*/
+};
+
+u32 l3_targ_stderrlog_main_clk3[] = {
+	0x0148	/* EMUSS */
+};
+
+char *l3_targ_stderrlog_main_name[L3_MODULES][18] = {
+	{
+	"DMM1",
+	"DMM2",
+	"ABE",
+	"L4CFG",
+	"CLK2 PWR DISC",
+	},
+	{
+	"CORTEX M3" ,
+	"DSS ",
+	"GPMC ",
+	"ISS ",
+	"IVAHD ",
+	"AES1",
+	"L4 PER0",
+	"OCMRAM ",
+	"GPMC sERROR",
+	"SGX ",
+	"SL2 ",
+	"C2C ",
+	"PWR DISC CLK1",
+	"SHA1",
+	"AES2",
+	"L4 PER3",
+	"L4 PER1",
+	"L4 PER2",
+	},
+	{
+	"EMUSS",
+	},
+};
+
+u32 *l3_targ[L3_MODULES] = {
+	l3_targ_stderrlog_main_clk1,
+	l3_targ_stderrlog_main_clk2,
+	l3_targ_stderrlog_main_clk3,
+};
+
+struct omap4_l3 {
+	struct device	*dev;
+	struct clk	*ick;
+
+	/* memory base */
+	void __iomem *l3_base[4];
+
+	int		debug_irq;
+	int		app_irq;
+};
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_smx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_smx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_smx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_smx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,311 @@
+ /*
+  * OMAP3XXX L3 Interconnect Driver
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Felipe Balbi <balbi@ti.com>
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	Sricharan <r.sricharan@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/kernel.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include "omap_l3_smx.h"
+
+static inline u64 omap3_l3_readll(void __iomem *base, u16 reg)
+{
+	return __raw_readll(base + reg);
+}
+
+static inline void omap3_l3_writell(void __iomem *base, u16 reg, u64 value)
+{
+	__raw_writell(value, base + reg);
+}
+
+static inline enum omap3_l3_code omap3_l3_decode_error_code(u64 error)
+{
+	return (error & 0x0f000000) >> L3_ERROR_LOG_CODE;
+}
+
+static inline u32 omap3_l3_decode_addr(u64 error_addr)
+{
+	return error_addr & 0xffffffff;
+}
+
+static inline unsigned omap3_l3_decode_cmd(u64 error)
+{
+	return (error & 0x07) >> L3_ERROR_LOG_CMD;
+}
+
+static inline enum omap3_l3_initiator_id omap3_l3_decode_initid(u64 error)
+{
+	return (error & 0xff00) >> L3_ERROR_LOG_INITID;
+}
+
+static inline unsigned omap3_l3_decode_req_info(u64 error)
+{
+	return (error >> 32) & 0xffff;
+}
+
+static char *omap3_l3_code_string(u8 code)
+{
+	switch (code) {
+	case OMAP_L3_CODE_NOERROR:
+		return "No Error";
+	case OMAP_L3_CODE_UNSUP_CMD:
+		return "Unsupported Command";
+	case OMAP_L3_CODE_ADDR_HOLE:
+		return "Address Hole";
+	case OMAP_L3_CODE_PROTECT_VIOLATION:
+		return "Protection Violation";
+	case OMAP_L3_CODE_IN_BAND_ERR:
+		return "In-band Error";
+	case OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT:
+		return "Request Timeout Not Accepted";
+	case OMAP_L3_CODE_REQ_TOUT_NO_RESP:
+		return "Request Timeout, no response";
+	default:
+		return "UNKNOWN error";
+	}
+}
+
+static char *omap3_l3_initiator_string(u8 initid)
+{
+	switch (initid) {
+	case OMAP_L3_LCD:
+		return "LCD";
+	case OMAP_L3_SAD2D:
+		return "SAD2D";
+	case OMAP_L3_IA_MPU_SS_1:
+	case OMAP_L3_IA_MPU_SS_2:
+	case OMAP_L3_IA_MPU_SS_3:
+	case OMAP_L3_IA_MPU_SS_4:
+	case OMAP_L3_IA_MPU_SS_5:
+		return "MPU";
+	case OMAP_L3_IA_IVA_SS_1:
+	case OMAP_L3_IA_IVA_SS_2:
+	case OMAP_L3_IA_IVA_SS_3:
+		return "IVA_SS";
+	case OMAP_L3_IA_IVA_SS_DMA_1:
+	case OMAP_L3_IA_IVA_SS_DMA_2:
+	case OMAP_L3_IA_IVA_SS_DMA_3:
+	case OMAP_L3_IA_IVA_SS_DMA_4:
+	case OMAP_L3_IA_IVA_SS_DMA_5:
+	case OMAP_L3_IA_IVA_SS_DMA_6:
+		return "IVA_SS_DMA";
+	case OMAP_L3_IA_SGX:
+		return "SGX";
+	case OMAP_L3_IA_CAM_1:
+	case OMAP_L3_IA_CAM_2:
+	case OMAP_L3_IA_CAM_3:
+		return "CAM";
+	case OMAP_L3_IA_DAP:
+		return "DAP";
+	case OMAP_L3_SDMA_WR_1:
+	case OMAP_L3_SDMA_WR_2:
+		return "SDMA_WR";
+	case OMAP_L3_SDMA_RD_1:
+	case OMAP_L3_SDMA_RD_2:
+	case OMAP_L3_SDMA_RD_3:
+	case OMAP_L3_SDMA_RD_4:
+		return "SDMA_RD";
+	case OMAP_L3_USBOTG:
+		return "USB_OTG";
+	case OMAP_L3_USBHOST:
+		return "USB_HOST";
+	default:
+		return "UNKNOWN Initiator";
+	}
+}
+
+/**
+ * omap3_l3_block_irq - handles a register block's irq
+ * @l3: struct omap3_l3 *
+ * @base: register block base address
+ * @error: L3_ERROR_LOG register of our block
+ *
+ * Called in hard-irq context. Caller should take care of locking
+ *
+ * OMAP36xx TRM gives, on page 2001, Figure 9-10, the Typical Error
+ * Analysis Sequence, we are following that sequence here, please
+ * refer to that Figure for more information on the subject.
+ */
+static irqreturn_t omap3_l3_block_irq(struct omap3_l3 *l3,
+					u64 error, int error_addr)
+{
+	u8                      code = omap3_l3_decode_error_code(error);
+	u8                      initid = omap3_l3_decode_initid(error);
+	u8                      multi = error & L3_ERROR_LOG_MULTI;
+	u32			address = omap3_l3_decode_addr(error_addr);
+
+	WARN(true, "%s Error seen by %s %s at address %x\n",
+				 omap3_l3_code_string(code),
+			  omap3_l3_initiator_string(initid),
+			     multi ? "Multiple Errors" : "",
+						   address);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t omap3_l3_app_irq(int irq, void *_l3)
+{
+	struct omap3_l3         *l3 = _l3;
+
+	u64                     status, clear;
+	u64                     error;
+	u64			error_addr;
+	u64			err_source = 0;
+	void			__iomem *base;
+	int			int_type;
+
+	irqreturn_t             ret = IRQ_NONE;
+
+	if (irq == l3->app_irq)
+		int_type = L3_APPLICATION_ERROR;
+	else
+		int_type = L3_DEBUG_ERROR;
+
+	if (!int_type) {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_0);
+		/*
+		 * if we have a timeout error, there's nothing we can
+		 * do besides rebooting the board. So let's BUG on any
+		 * of such errors and handle the others. timeout error
+		 * is severe and not expected to occur.
+		 */
+		BUG_ON(status & L3_STATUS_0_TIMEOUT_MASK);
+	} else {
+		status = omap3_l3_readll(l3->rt, L3_SI_FLAG_STATUS_1);
+		/* No timeout error for debug sources */
+	}
+
+	/* identify the error source */
+	for (err_source = 0; !(status & (1 << err_source)); err_source++)
+									;
+
+	base = l3->rt + *(omap3_l3_bases[int_type] + err_source);
+	error = omap3_l3_readll(base, L3_ERROR_LOG);
+
+	if (error) {
+		error_addr = omap3_l3_readll(base, L3_ERROR_LOG_ADDR);
+
+		ret |= omap3_l3_block_irq(l3, error, error_addr);
+	}
+
+	/* Clear the status register */
+	clear = ((L3_AGENT_STATUS_CLEAR_IA << int_type) |
+		 (L3_AGENT_STATUS_CLEAR_TA));
+
+	omap3_l3_writell(base, L3_AGENT_STATUS, clear);
+
+	/* clear the error log register */
+	omap3_l3_writell(base, L3_ERROR_LOG, error);
+
+	return ret;
+}
+
+static int __init omap3_l3_probe(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3;
+	struct resource         *res;
+	int                     ret;
+
+	l3 = kzalloc(sizeof(*l3), GFP_KERNEL);
+	if (!l3) {
+		ret = -ENOMEM;
+		goto err0;
+	}
+
+	platform_set_drvdata(pdev, l3);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "couldn't find resource\n");
+		ret = -ENODEV;
+		goto err1;
+	}
+	l3->rt = ioremap(res->start, resource_size(res));
+	if (!(l3->rt)) {
+		dev_err(&pdev->dev, "ioremap failed\n");
+		ret = -ENOMEM;
+		goto err2;
+	}
+
+	l3->debug_irq = platform_get_irq(pdev, 0);
+	ret = request_irq(l3->debug_irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-debug-irq", l3);
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request debug irq\n");
+		goto err3;
+	}
+
+	l3->app_irq = platform_get_irq(pdev, 1);
+	ret = request_irq(l3->app_irq, omap3_l3_app_irq,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING,
+		"l3-app-irq", l3);
+
+	if (ret) {
+		dev_err(&pdev->dev, "couldn't request app irq\n");
+		goto err4;
+	}
+
+	goto err0;
+
+err4:
+err3:
+	iounmap(l3->rt);
+err2:
+err1:
+	kfree(l3);
+err0:
+	return ret;
+}
+
+static int __exit omap3_l3_remove(struct platform_device *pdev)
+{
+	struct omap3_l3         *l3 = platform_get_drvdata(pdev);
+
+	free_irq(l3->app_irq, l3);
+	free_irq(l3->debug_irq, l3);
+	iounmap(l3->rt);
+	kfree(l3);
+
+	return 0;
+}
+
+static struct platform_driver omap3_l3_driver = {
+	.remove         = __exit_p(omap3_l3_remove),
+	.driver         = {
+	.name   = "omap_l3_smx",
+	},
+};
+
+static int __init omap3_l3_init(void)
+{
+	return platform_driver_probe(&omap3_l3_driver, omap3_l3_probe);
+}
+postcore_initcall_sync(omap3_l3_init);
+
+static void __exit omap3_l3_exit(void)
+{
+	platform_driver_unregister(&omap3_l3_driver);
+}
+module_exit(omap3_l3_exit);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_smx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_smx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_l3_smx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_l3_smx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,338 @@
+ /*
+  * OMAP3XXX L3 Interconnect Driver header
+  *
+  * Copyright (C) 2011 Texas Corporation
+  *	Felipe Balbi <balbi@ti.com>
+  *	Santosh Shilimkar <santosh.shilimkar@ti.com>
+  *	sricharan <r.sricharan@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
+  */
+#ifndef __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+#define __ARCH_ARM_MACH_OMAP2_L3_INTERCONNECT_3XXX_H
+
+/* Register definitions. All 64-bit wide */
+#define L3_COMPONENT			0x000
+#define L3_CORE				0x018
+#define L3_AGENT_CONTROL		0x020
+#define L3_AGENT_STATUS			0x028
+#define L3_ERROR_LOG			0x058
+
+#define L3_ERROR_LOG_MULTI		(1 << 31)
+#define L3_ERROR_LOG_SECONDARY		(1 << 30)
+
+#define L3_ERROR_LOG_ADDR		0x060
+
+/* Register definitions for Sideband Interconnect */
+#define L3_SI_CONTROL			0x020
+#define L3_SI_FLAG_STATUS_0		0x510
+
+const u64 shift = 1;
+
+#define L3_STATUS_0_MPUIA_BRST		(shift << 0)
+#define L3_STATUS_0_MPUIA_RSP		(shift << 1)
+#define L3_STATUS_0_MPUIA_INBAND	(shift << 2)
+#define L3_STATUS_0_IVAIA_BRST		(shift << 6)
+#define L3_STATUS_0_IVAIA_RSP		(shift << 7)
+#define L3_STATUS_0_IVAIA_INBAND	(shift << 8)
+#define L3_STATUS_0_SGXIA_BRST		(shift << 9)
+#define L3_STATUS_0_SGXIA_RSP		(shift << 10)
+#define L3_STATUS_0_SGXIA_MERROR	(shift << 11)
+#define L3_STATUS_0_CAMIA_BRST		(shift << 12)
+#define L3_STATUS_0_CAMIA_RSP		(shift << 13)
+#define L3_STATUS_0_CAMIA_INBAND	(shift << 14)
+#define L3_STATUS_0_DISPIA_BRST		(shift << 15)
+#define L3_STATUS_0_DISPIA_RSP		(shift << 16)
+#define L3_STATUS_0_DMARDIA_BRST	(shift << 18)
+#define L3_STATUS_0_DMARDIA_RSP		(shift << 19)
+#define L3_STATUS_0_DMAWRIA_BRST	(shift << 21)
+#define L3_STATUS_0_DMAWRIA_RSP		(shift << 22)
+#define L3_STATUS_0_USBOTGIA_BRST	(shift << 24)
+#define L3_STATUS_0_USBOTGIA_RSP	(shift << 25)
+#define L3_STATUS_0_USBOTGIA_INBAND	(shift << 26)
+#define L3_STATUS_0_USBHOSTIA_BRST	(shift << 27)
+#define L3_STATUS_0_USBHOSTIA_INBAND	(shift << 28)
+#define L3_STATUS_0_SMSTA_REQ		(shift << 48)
+#define L3_STATUS_0_GPMCTA_REQ		(shift << 49)
+#define L3_STATUS_0_OCMRAMTA_REQ	(shift << 50)
+#define L3_STATUS_0_OCMROMTA_REQ	(shift << 51)
+#define L3_STATUS_0_IVATA_REQ		(shift << 54)
+#define L3_STATUS_0_SGXTA_REQ		(shift << 55)
+#define L3_STATUS_0_SGXTA_SERROR	(shift << 56)
+#define L3_STATUS_0_GPMCTA_SERROR	(shift << 57)
+#define L3_STATUS_0_L4CORETA_REQ	(shift << 58)
+#define L3_STATUS_0_L4PERTA_REQ		(shift << 59)
+#define L3_STATUS_0_L4EMUTA_REQ		(shift << 60)
+#define L3_STATUS_0_MAD2DTA_REQ		(shift << 61)
+
+#define L3_STATUS_0_TIMEOUT_MASK	(L3_STATUS_0_MPUIA_BRST         \
+					| L3_STATUS_0_MPUIA_RSP         \
+					| L3_STATUS_0_IVAIA_BRST        \
+					| L3_STATUS_0_IVAIA_RSP         \
+					| L3_STATUS_0_SGXIA_BRST        \
+					| L3_STATUS_0_SGXIA_RSP         \
+					| L3_STATUS_0_CAMIA_BRST        \
+					| L3_STATUS_0_CAMIA_RSP         \
+					| L3_STATUS_0_DISPIA_BRST       \
+					| L3_STATUS_0_DISPIA_RSP        \
+					| L3_STATUS_0_DMARDIA_BRST      \
+					| L3_STATUS_0_DMARDIA_RSP       \
+					| L3_STATUS_0_DMAWRIA_BRST      \
+					| L3_STATUS_0_DMAWRIA_RSP       \
+					| L3_STATUS_0_USBOTGIA_BRST     \
+					| L3_STATUS_0_USBOTGIA_RSP      \
+					| L3_STATUS_0_USBHOSTIA_BRST    \
+					| L3_STATUS_0_SMSTA_REQ         \
+					| L3_STATUS_0_GPMCTA_REQ        \
+					| L3_STATUS_0_OCMRAMTA_REQ      \
+					| L3_STATUS_0_OCMROMTA_REQ      \
+					| L3_STATUS_0_IVATA_REQ         \
+					| L3_STATUS_0_SGXTA_REQ         \
+					| L3_STATUS_0_L4CORETA_REQ      \
+					| L3_STATUS_0_L4PERTA_REQ       \
+					| L3_STATUS_0_L4EMUTA_REQ       \
+					| L3_STATUS_0_MAD2DTA_REQ)
+
+#define L3_SI_FLAG_STATUS_1		0x530
+
+#define L3_STATUS_1_MPU_DATAIA		(1 << 0)
+#define L3_STATUS_1_DAPIA0		(1 << 3)
+#define L3_STATUS_1_DAPIA1		(1 << 4)
+#define L3_STATUS_1_IVAIA		(1 << 6)
+
+#define L3_PM_ERROR_LOG			0x020
+#define L3_PM_CONTROL			0x028
+#define L3_PM_ERROR_CLEAR_SINGLE	0x030
+#define L3_PM_ERROR_CLEAR_MULTI		0x038
+#define L3_PM_REQ_INFO_PERMISSION(n)	(0x048 + (0x020 * n))
+#define L3_PM_READ_PERMISSION(n)	(0x050 + (0x020 * n))
+#define L3_PM_WRITE_PERMISSION(n)	(0x058 + (0x020 * n))
+#define L3_PM_ADDR_MATCH(n)		(0x060 + (0x020 * n))
+
+/* L3 error log bit fields. Common for IA and TA */
+#define L3_ERROR_LOG_CODE		24
+#define L3_ERROR_LOG_INITID		8
+#define L3_ERROR_LOG_CMD		0
+
+/* L3 agent status bit fields. */
+#define L3_AGENT_STATUS_CLEAR_IA	0x10000000
+#define L3_AGENT_STATUS_CLEAR_TA	0x01000000
+
+#define OMAP34xx_IRQ_L3_APP		10
+#define L3_APPLICATION_ERROR		0x0
+#define L3_DEBUG_ERROR			0x1
+
+enum omap3_l3_initiator_id {
+	/* LCD has 1 ID */
+	OMAP_L3_LCD	        = 29,
+	/* SAD2D has 1 ID */
+	OMAP_L3_SAD2D		= 28,
+	/* MPU has 5 IDs */
+	OMAP_L3_IA_MPU_SS_1     = 27,
+	OMAP_L3_IA_MPU_SS_2     = 26,
+	OMAP_L3_IA_MPU_SS_3     = 25,
+	OMAP_L3_IA_MPU_SS_4     = 24,
+	OMAP_L3_IA_MPU_SS_5     = 23,
+	/* IVA2.2 SS has 3 IDs*/
+	OMAP_L3_IA_IVA_SS_1     = 22,
+	OMAP_L3_IA_IVA_SS_2     = 21,
+	OMAP_L3_IA_IVA_SS_3     = 20,
+	/* IVA 2.2 SS DMA has 6 IDS */
+	OMAP_L3_IA_IVA_SS_DMA_1 = 19,
+	OMAP_L3_IA_IVA_SS_DMA_2 = 18,
+	OMAP_L3_IA_IVA_SS_DMA_3 = 17,
+	OMAP_L3_IA_IVA_SS_DMA_4 = 16,
+	OMAP_L3_IA_IVA_SS_DMA_5 = 15,
+	OMAP_L3_IA_IVA_SS_DMA_6 = 14,
+	/* SGX has 1 ID */
+	OMAP_L3_IA_SGX		= 13,
+	/* CAM has 3 ID */
+	OMAP_L3_IA_CAM_1	= 12,
+	OMAP_L3_IA_CAM_2	= 11,
+	OMAP_L3_IA_CAM_3	= 10,
+	/* DAP has 1 ID */
+	OMAP_L3_IA_DAP		= 9,
+	/* SDMA WR has 2 IDs */
+	OMAP_L3_SDMA_WR_1	= 8,
+	OMAP_L3_SDMA_WR_2	= 7,
+	/* SDMA RD has 4 IDs */
+	OMAP_L3_SDMA_RD_1	= 6,
+	OMAP_L3_SDMA_RD_2	= 5,
+	OMAP_L3_SDMA_RD_3	= 4,
+	OMAP_L3_SDMA_RD_4	= 3,
+	/* HSUSB OTG has 1 ID */
+	OMAP_L3_USBOTG		= 2,
+	/* HSUSB HOST has 1 ID */
+	OMAP_L3_USBHOST		= 1,
+};
+
+enum omap3_l3_code {
+	OMAP_L3_CODE_NOERROR = 0,
+	OMAP_L3_CODE_UNSUP_CMD = 1,
+	OMAP_L3_CODE_ADDR_HOLE = 2,
+	OMAP_L3_CODE_PROTECT_VIOLATION = 3,
+	OMAP_L3_CODE_IN_BAND_ERR = 4,
+	/* codes 5 and 6 are reserved */
+	OMAP_L3_CODE_REQ_TOUT_NOT_ACCEPT = 7,
+	OMAP_L3_CODE_REQ_TOUT_NO_RESP = 8,
+	/* codes 9 - 15 are also reserved */
+};
+
+struct omap3_l3 {
+	struct device   *dev;
+	struct clk      *ick;
+
+	/* memory base*/
+	void __iomem    *rt;
+
+	int             debug_irq;
+	int             app_irq;
+
+	/* true when and inband functional error occurs */
+	unsigned        inband:1;
+};
+
+/* offsets for l3 agents in order with the Flag status register */
+unsigned int __iomem omap3_l3_app_bases[] = {
+	/* MPU IA */
+	0x1400,
+	0x1400,
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	0x1800,
+	0x1800,
+	/* SGX IA */
+	0x1c00,
+	0x1c00,
+	/* RESERVED */
+	0,
+	/* CAMERA IA */
+	0x5800,
+	0x5800,
+	0x5800,
+	/* DISPLAY IA */
+	0x5400,
+	0x5400,
+	/* RESERVED */
+	0,
+	/*SDMA RD IA */
+	0x4c00,
+	0x4c00,
+	/* RESERVED */
+	0,
+	/* SDMA WR IA */
+	0x5000,
+	0x5000,
+	/* RESERVED */
+	0,
+	/* USB OTG IA */
+	0x4400,
+	0x4400,
+	0x4400,
+	/* USB HOST IA */
+	0x4000,
+	0x4000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	/* SAD2D IA */
+	0x3000,
+	0x3000,
+	0x3000,
+	/* RESERVED */
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	/* SMA TA */
+	0x2000,
+	/* GPMC TA */
+	0x2400,
+	/* OCM RAM TA */
+	0x2800,
+	/* OCM ROM TA */
+	0x2C00,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* IVA 2.2 TA */
+	0x6000,
+	/* SGX TA */
+	0x6400,
+	/* L4 EMU TA */
+	0x7000,
+	/* GPMC TA */
+	0x2400,
+	/* L4 CORE TA */
+	0x6800,
+	/* L4 PER TA */
+	0x6c00,
+	/* L4 EMU TA */
+	0x7000,
+	/* MAD2D TA */
+	0x3400,
+	/* RESERVED */
+	0,
+	0,
+};
+
+unsigned int __iomem omap3_l3_debug_bases[] = {
+	/* MPU DATA IA */
+	0x1400,
+	/* RESERVED */
+	0,
+	0,
+	/* DAP IA */
+	0x5c00,
+	0x5c00,
+	/* RESERVED */
+	0,
+	/* IVA 2.2 IA */
+	0x1800,
+	/* REST RESERVED */
+};
+
+u32 *omap3_l3_bases[] = {
+	omap3_l3_app_bases,
+	omap3_l3_debug_bases,
+};
+
+/*
+ * REVISIT define __raw_readll/__raw_writell here, but move them to
+ * <asm/io.h> at some point
+ */
+#define __raw_writell(v, a)	(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a) = (v))
+#define __raw_readll(a)		(__chk_io_ptr(a), \
+				*(volatile u64 __force *)(a))
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_opp_data.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_opp_data.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_opp_data.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_opp_data.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,8 @@
 
 #include <plat/omap_hwmod.h>
 
+#include "voltage.h"
+
 /*
  * *BIG FAT WARNING*:
  * USE the following ONLY in opp data initialization common to an SoC.
@@ -65,8 +67,30 @@
 	.u_volt		= _uv,					\
 }
 
+/*
+ * Initialization wrapper used to define SmartReflex process data
+ * XXX Is this needed?  Just use C99 initializers in data files?
+ */
+#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)  \
+{								       \
+	.volt_nominal	= _v_nom,				       \
+	.sr_efuse_offs	= _efuse_offs,				       \
+	.sr_errminlimit = _errminlimit,				       \
+	.vp_errgain	= _errgain				       \
+}
+
 /* Use this to initialize the default table */
 extern int __init omap_init_opp_table(struct omap_opp_def *opp_def,
 		u32 opp_def_size);
 
+
+extern struct omap_volt_data omap34xx_vddmpu_volt_data[];
+extern struct omap_volt_data omap34xx_vddcore_volt_data[];
+extern struct omap_volt_data omap36xx_vddmpu_volt_data[];
+extern struct omap_volt_data omap36xx_vddcore_volt_data[];
+
+extern struct omap_volt_data omap44xx_vdd_mpu_volt_data[];
+extern struct omap_volt_data omap44xx_vdd_iva_volt_data[];
+extern struct omap_volt_data omap44xx_vdd_core_volt_data[];
+
 #endif		/* __ARCH_ARM_MACH_OMAP2_OMAP_OPP_DATA_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_phy_internal.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_phy_internal.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_phy_internal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_phy_internal.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/usb.h>
 
 #include <plat/usb.h>
+#include "control.h"
 
 /* OMAP control module register for UTMI PHY */
 #define CONTROL_DEV_CONF		0x300
@@ -43,6 +44,7 @@
 
 static struct clk *phyclk, *clk48m, *clk32k;
 static void __iomem *ctrl_base;
+static int usbotghs_control;
 
 int omap4430_phy_init(struct device *dev)
 {
@@ -103,13 +105,6 @@
 int omap4430_phy_power(struct device *dev, int ID, int on)
 {
 	if (on) {
-		/* enabled the clocks */
-		omap4430_phy_set_clk(dev, 1);
-		/* power on the phy */
-		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
-			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
-			mdelay(200);
-		}
 		if (ID)
 			/* enable VBUS valid, IDDIG groung */
 			__raw_writel(AVALID | VBUSVALID, ctrl_base +
@@ -117,18 +112,39 @@
 		else
 			/*
 			 * Enable VBUS Valid, AValid and IDDIG
-			 * high impedence
+			 * high impedance
 			 */
 			__raw_writel(IDDIG | AVALID | VBUSVALID,
 						ctrl_base + USBOTGHS_CONTROL);
 	} else {
-		/* Enable session END and IDIG to high impedence. */
+		/* Enable session END and IDIG to high impedance. */
 		__raw_writel(SESSEND | IDDIG, ctrl_base +
 					USBOTGHS_CONTROL);
+	}
+	return 0;
+}
+
+int omap4430_phy_suspend(struct device *dev, int suspend)
+{
+	if (suspend) {
 		/* Disable the clocks */
 		omap4430_phy_set_clk(dev, 0);
 		/* Power down the phy */
 		__raw_writel(PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+
+		/* save the context */
+		usbotghs_control = __raw_readl(ctrl_base + USBOTGHS_CONTROL);
+	} else {
+		/* Enable the internel phy clcoks */
+		omap4430_phy_set_clk(dev, 1);
+		/* power on the phy */
+		if (__raw_readl(ctrl_base + CONTROL_DEV_CONF) & PHY_PD) {
+			__raw_writel(~PHY_PD, ctrl_base + CONTROL_DEV_CONF);
+			mdelay(200);
+		}
+
+		/* restore the context */
+		__raw_writel(usbotghs_control, ctrl_base + USBOTGHS_CONTROL);
 	}
 
 	return 0;
@@ -147,3 +163,95 @@
 
 	return 0;
 }
+
+void am35x_musb_reset(void)
+{
+	u32	regval;
+
+	/* Reset the musb interface */
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+
+	regval |= AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval &= ~AM35XX_USBOTGSS_SW_RST;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
+}
+
+void am35x_musb_phy_power(u8 on)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(100);
+	u32 devconf2;
+
+	if (on) {
+		/*
+		 * Start the on-chip PHY and its PLL.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
+		devconf2 |= CONF2_PHY_PLLON;
+
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+
+		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
+		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
+				& CONF2_PHYCLKGD)) {
+			cpu_relax();
+
+			if (time_after(jiffies, timeout)) {
+				pr_err(KERN_ERR "musb PHY clock good timed out\n");
+				break;
+			}
+		}
+	} else {
+		/*
+		 * Power down the on-chip PHY.
+		 */
+		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+		devconf2 &= ~CONF2_PHY_PLLON;
+		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
+		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+	}
+}
+
+void am35x_musb_clear_irq(void)
+{
+	u32 regval;
+
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval |= AM35XX_USBOTGSS_INT_CLR;
+	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
+	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
+}
+
+void am35x_musb_set_mode(u8 musb_mode)
+{
+	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
+
+	devconf2 &= ~CONF2_OTGMODE;
+	switch (musb_mode) {
+#ifdef	CONFIG_USB_MUSB_HDRC_HCD
+	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
+		devconf2 |= CONF2_FORCE_HOST;
+		break;
+#endif
+#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
+	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
+		devconf2 |= CONF2_FORCE_DEVICE;
+		break;
+#endif
+#ifdef	CONFIG_USB_MUSB_OTG
+	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
+		devconf2 |= CONF2_NO_OVERRIDE;
+		break;
+#endif
+	default:
+		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
+	}
+
+	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_twl.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_twl.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/omap_twl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/omap_twl.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
 #include <linux/kernel.h>
 #include <linux/i2c/twl.h>
 
-#include <plat/voltage.h>
+#include "voltage.h"
 
 #include "pm.h"
 
@@ -59,8 +59,15 @@
 
 static bool is_offset_valid;
 static u8 smps_offset;
+/*
+ * Flag to ensure Smartreflex bit in TWL
+ * being cleared in board file is not overwritten.
+ */
+static bool __initdata twl_sr_enable_autoinit;
 
+#define TWL4030_DCDC_GLOBAL_CFG        0x06
 #define REG_SMPS_OFFSET         0xE0
+#define SMARTREFLEX_ENABLE     BIT(3)
 
 static unsigned long twl4030_vsel_to_uv(const u8 vsel)
 {
@@ -269,6 +276,18 @@
 		omap3_core_volt_info.vp_vddmax = OMAP3630_VP2_VLIMITTO_VDDMAX;
 	}
 
+	/*
+	 * The smartreflex bit on twl4030 specifies if the setting of voltage
+	 * is done over the I2C_SR path. Since this setting is independent of
+	 * the actual usage of smartreflex AVS module, we enable TWL SR bit
+	 * by default irrespective of whether smartreflex AVS module is enabled
+	 * on the OMAP side or not. This is because without this bit enabled,
+	 * the voltage scaling through vp forceupdate/bypass mechanism of
+	 * voltage scaling will not function on TWL over I2C_SR.
+	 */
+	if (!twl_sr_enable_autoinit)
+		omap3_twl_set_sr_bit(true);
+
 	voltdm = omap_voltage_domain_lookup("mpu");
 	omap_voltage_register_pmic(voltdm, &omap3_mpu_volt_info);
 
@@ -277,3 +296,44 @@
 
 	return 0;
 }
+
+/**
+ * omap3_twl_set_sr_bit() - Set/Clear SR bit on TWL
+ * @enable: enable SR mode in twl or not
+ *
+ * If 'enable' is true, enables Smartreflex bit on TWL 4030 to make sure
+ * voltage scaling through OMAP SR works. Else, the smartreflex bit
+ * on twl4030 is cleared as there are platforms which use OMAP3 and T2 but
+ * use Synchronized Scaling Hardware Strategy (ENABLE_VMODE=1) and Direct
+ * Strategy Software Scaling Mode (ENABLE_VMODE=0), for setting the voltages,
+ * in those scenarios this bit is to be cleared (enable = false).
+ *
+ * Returns 0 on success, error is returned if I2C read/write fails.
+ */
+int __init omap3_twl_set_sr_bit(bool enable)
+{
+	u8 temp;
+	int ret;
+	if (twl_sr_enable_autoinit)
+		pr_warning("%s: unexpected multiple calls\n", __func__);
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_PM_RECEIVER, &temp,
+					TWL4030_DCDC_GLOBAL_CFG);
+	if (ret)
+		goto err;
+
+	if (enable)
+		temp |= SMARTREFLEX_ENABLE;
+	else
+		temp &= ~SMARTREFLEX_ENABLE;
+
+	ret = twl_i2c_write_u8(TWL4030_MODULE_PM_RECEIVER, temp,
+				TWL4030_DCDC_GLOBAL_CFG);
+	if (!ret) {
+		twl_sr_enable_autoinit = true;
+		return 0;
+	}
+err:
+	pr_err("%s: Error access to TWL4030 (%d)\n", __func__, ret);
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/opp2xxx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/opp2xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/opp2xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/opp2xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -418,7 +418,7 @@
 
 extern const struct prcm_config omap2420_rate_table[];
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 extern const struct prcm_config omap2430_rate_table[];
 #else
 #define omap2430_rate_table	NULL
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/opp3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/opp3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/opp3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/opp3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,8 +4,9 @@
  * Copyright (C) 2009-2010 Texas Instruments Incorporated - http://www.ti.com/
  *	Nishanth Menon
  *	Kevin Hilman
- * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2010-2011 Nokia Corporation.
  *      Eduardo Valentin
+ *      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
@@ -20,19 +21,83 @@
 
 #include <plat/cpu.h>
 
+#include "control.h"
 #include "omap_opp_data.h"
+#include "pm.h"
+
+/* 34xx */
+
+/* VDD1 */
+
+#define OMAP3430_VDD_MPU_OPP1_UV		975000
+#define OMAP3430_VDD_MPU_OPP2_UV		1075000
+#define OMAP3430_VDD_MPU_OPP3_UV		1200000
+#define OMAP3430_VDD_MPU_OPP4_UV		1270000
+#define OMAP3430_VDD_MPU_OPP5_UV		1350000
+
+struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+
+#define OMAP3430_VDD_CORE_OPP1_UV		975000
+#define OMAP3430_VDD_CORE_OPP2_UV		1050000
+#define OMAP3430_VDD_CORE_OPP3_UV		1150000
+
+struct omap_volt_data omap34xx_vddcore_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* 36xx */
+
+/* VDD1 */
+
+#define OMAP3630_VDD_MPU_OPP50_UV		1012500
+#define OMAP3630_VDD_MPU_OPP100_UV		1200000
+#define OMAP3630_VDD_MPU_OPP120_UV		1325000
+#define OMAP3630_VDD_MPU_OPP1G_UV		1375000
+
+struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* VDD2 */
+
+#define OMAP3630_VDD_CORE_OPP50_UV		1000000
+#define OMAP3630_VDD_CORE_OPP100_UV		1200000
+
+struct omap_volt_data omap36xx_vddcore_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+/* OPP data */
 
 static struct omap_opp_def __initdata omap34xx_opp_def_list[] = {
 	/* MPU OPP1 */
-	OPP_INITIALIZER("mpu", true, 125000000, 975000),
+	OPP_INITIALIZER("mpu", true, 125000000, OMAP3430_VDD_MPU_OPP1_UV),
 	/* MPU OPP2 */
-	OPP_INITIALIZER("mpu", true, 250000000, 1075000),
+	OPP_INITIALIZER("mpu", true, 250000000, OMAP3430_VDD_MPU_OPP2_UV),
 	/* MPU OPP3 */
-	OPP_INITIALIZER("mpu", true, 500000000, 1200000),
+	OPP_INITIALIZER("mpu", true, 500000000, OMAP3430_VDD_MPU_OPP3_UV),
 	/* MPU OPP4 */
-	OPP_INITIALIZER("mpu", true, 550000000, 1270000),
+	OPP_INITIALIZER("mpu", true, 550000000, OMAP3430_VDD_MPU_OPP4_UV),
 	/* MPU OPP5 */
-	OPP_INITIALIZER("mpu", true, 600000000, 1350000),
+	OPP_INITIALIZER("mpu", true, 600000000, OMAP3430_VDD_MPU_OPP5_UV),
 
 	/*
 	 * L3 OPP1 - 41.5 MHz is disabled because: The voltage for that OPP is
@@ -42,53 +107,53 @@
 	 * impact that frequency will do to the MPU and the whole system in
 	 * general.
 	 */
-	OPP_INITIALIZER("l3_main", false, 41500000, 975000),
+	OPP_INITIALIZER("l3_main", false, 41500000, OMAP3430_VDD_CORE_OPP1_UV),
 	/* L3 OPP2 */
-	OPP_INITIALIZER("l3_main", true, 83000000, 1050000),
+	OPP_INITIALIZER("l3_main", true, 83000000, OMAP3430_VDD_CORE_OPP2_UV),
 	/* L3 OPP3 */
-	OPP_INITIALIZER("l3_main", true, 166000000, 1150000),
+	OPP_INITIALIZER("l3_main", true, 166000000, OMAP3430_VDD_CORE_OPP3_UV),
 
 	/* DSP OPP1 */
-	OPP_INITIALIZER("iva", true, 90000000, 975000),
+	OPP_INITIALIZER("iva", true, 90000000, OMAP3430_VDD_MPU_OPP1_UV),
 	/* DSP OPP2 */
-	OPP_INITIALIZER("iva", true, 180000000, 1075000),
+	OPP_INITIALIZER("iva", true, 180000000, OMAP3430_VDD_MPU_OPP2_UV),
 	/* DSP OPP3 */
-	OPP_INITIALIZER("iva", true, 360000000, 1200000),
+	OPP_INITIALIZER("iva", true, 360000000, OMAP3430_VDD_MPU_OPP3_UV),
 	/* DSP OPP4 */
-	OPP_INITIALIZER("iva", true, 400000000, 1270000),
+	OPP_INITIALIZER("iva", true, 400000000, OMAP3430_VDD_MPU_OPP4_UV),
 	/* DSP OPP5 */
-	OPP_INITIALIZER("iva", true, 430000000, 1350000),
+	OPP_INITIALIZER("iva", true, 430000000, OMAP3430_VDD_MPU_OPP5_UV),
 };
 
 static struct omap_opp_def __initdata omap36xx_opp_def_list[] = {
 	/* MPU OPP1 - OPP50 */
-	OPP_INITIALIZER("mpu", true,  300000000, 1012500),
+	OPP_INITIALIZER("mpu", true,  300000000, OMAP3630_VDD_MPU_OPP50_UV),
 	/* MPU OPP2 - OPP100 */
-	OPP_INITIALIZER("mpu", true,  600000000, 1200000),
+	OPP_INITIALIZER("mpu", true,  600000000, OMAP3630_VDD_MPU_OPP100_UV),
 	/* MPU OPP3 - OPP-Turbo */
-	OPP_INITIALIZER("mpu", false, 800000000, 1325000),
+	OPP_INITIALIZER("mpu", false, 800000000, OMAP3630_VDD_MPU_OPP120_UV),
 	/* MPU OPP4 - OPP-SB */
-	OPP_INITIALIZER("mpu", false, 1000000000, 1375000),
+	OPP_INITIALIZER("mpu", false, 1000000000, OMAP3630_VDD_MPU_OPP1G_UV),
 
 	/* L3 OPP1 - OPP50 */
-	OPP_INITIALIZER("l3_main", true, 100000000, 1000000),
+	OPP_INITIALIZER("l3_main", true, 100000000, OMAP3630_VDD_CORE_OPP50_UV),
 	/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
-	OPP_INITIALIZER("l3_main", true, 200000000, 1200000),
+	OPP_INITIALIZER("l3_main", true, 200000000, OMAP3630_VDD_CORE_OPP100_UV),
 
 	/* DSP OPP1 - OPP50 */
-	OPP_INITIALIZER("iva", true,  260000000, 1012500),
+	OPP_INITIALIZER("iva", true,  260000000, OMAP3630_VDD_MPU_OPP50_UV),
 	/* DSP OPP2 - OPP100 */
-	OPP_INITIALIZER("iva", true,  520000000, 1200000),
+	OPP_INITIALIZER("iva", true,  520000000, OMAP3630_VDD_MPU_OPP100_UV),
 	/* DSP OPP3 - OPP-Turbo */
-	OPP_INITIALIZER("iva", false, 660000000, 1325000),
+	OPP_INITIALIZER("iva", false, 660000000, OMAP3630_VDD_MPU_OPP120_UV),
 	/* DSP OPP4 - OPP-SB */
-	OPP_INITIALIZER("iva", false, 800000000, 1375000),
+	OPP_INITIALIZER("iva", false, 800000000, OMAP3630_VDD_MPU_OPP1G_UV),
 };
 
 /**
  * omap3_opp_init() - initialize omap3 opp table
  */
-static int __init omap3_opp_init(void)
+int __init omap3_opp_init(void)
 {
 	int r = -ENODEV;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/opp4xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/opp4xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/opp4xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/opp4xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,8 +5,9 @@
  *	Nishanth Menon
  *	Kevin Hilman
  *	Thara Gopinath
- * Copyright (C) 2010 Nokia Corporation.
+ * Copyright (C) 2010-2011 Nokia Corporation.
  *      Eduardo Valentin
+ *      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
@@ -21,28 +22,75 @@
 
 #include <plat/cpu.h>
 
+#include "control.h"
 #include "omap_opp_data.h"
+#include "pm.h"
+
+/*
+ * Structures containing OMAP4430 voltage supported and various
+ * voltage dependent data for each VDD.
+ */
+
+#define OMAP4430_VDD_MPU_OPP50_UV		1025000
+#define OMAP4430_VDD_MPU_OPP100_UV		1200000
+#define OMAP4430_VDD_MPU_OPPTURBO_UV		1313000
+#define OMAP4430_VDD_MPU_OPPNITRO_UV		1375000
+
+struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4430_VDD_IVA_OPP50_UV		1013000
+#define OMAP4430_VDD_IVA_OPP100_UV		1188000
+#define OMAP4430_VDD_IVA_OPPTURBO_UV		1300000
+
+struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
+#define OMAP4430_VDD_CORE_OPP50_UV		1025000
+#define OMAP4430_VDD_CORE_OPP100_UV		1200000
+
+struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
+	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
+	VOLT_DATA_DEFINE(0, 0, 0, 0),
+};
+
 
 static struct omap_opp_def __initdata omap44xx_opp_def_list[] = {
 	/* MPU OPP1 - OPP50 */
-	OPP_INITIALIZER("mpu", true, 300000000, 1100000),
+	OPP_INITIALIZER("mpu", true, 300000000, OMAP4430_VDD_MPU_OPP50_UV),
 	/* MPU OPP2 - OPP100 */
-	OPP_INITIALIZER("mpu", true, 600000000, 1200000),
+	OPP_INITIALIZER("mpu", true, 600000000, OMAP4430_VDD_MPU_OPP100_UV),
 	/* MPU OPP3 - OPP-Turbo */
-	OPP_INITIALIZER("mpu", false, 800000000, 1260000),
+	OPP_INITIALIZER("mpu", true, 800000000, OMAP4430_VDD_MPU_OPPTURBO_UV),
 	/* MPU OPP4 - OPP-SB */
-	OPP_INITIALIZER("mpu", false, 1008000000, 1350000),
+	OPP_INITIALIZER("mpu", true, 1008000000, OMAP4430_VDD_MPU_OPPNITRO_UV),
 	/* L3 OPP1 - OPP50 */
-	OPP_INITIALIZER("l3_main_1", true, 100000000, 930000),
+	OPP_INITIALIZER("l3_main_1", true, 100000000, OMAP4430_VDD_CORE_OPP50_UV),
 	/* L3 OPP2 - OPP100, OPP-Turbo, OPP-SB */
-	OPP_INITIALIZER("l3_main_1", true, 200000000, 1100000),
-	/* TODO: add IVA, DSP, aess, fdif, gpu */
+	OPP_INITIALIZER("l3_main_1", true, 200000000, OMAP4430_VDD_CORE_OPP100_UV),
+	/* IVA OPP1 - OPP50 */
+	OPP_INITIALIZER("iva", true, 133000000, OMAP4430_VDD_IVA_OPP50_UV),
+	/* IVA OPP2 - OPP100 */
+	OPP_INITIALIZER("iva", true, 266100000, OMAP4430_VDD_IVA_OPP100_UV),
+	/* IVA OPP3 - OPP-Turbo */
+	OPP_INITIALIZER("iva", false, 332000000, OMAP4430_VDD_IVA_OPPTURBO_UV),
+	/* TODO: add DSP, aess, fdif, gpu */
 };
 
 /**
  * omap4_opp_init() - initialize omap4 opp table
  */
-static int __init omap4_opp_init(void)
+int __init omap4_opp_init(void)
 {
 	int r = -ENODEV;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm24xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm24xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm24xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm24xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -363,14 +363,11 @@
 /* XXX This function should be shareable between OMAP2xxx and OMAP3 */
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
-	clkdm_clear_all_wkdeps(clkdm);
-	clkdm_clear_all_sleepdeps(clkdm);
-
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
-		omap2_clkdm_allow_idle(clkdm);
+		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
 		 atomic_read(&clkdm->usecount) == 0)
-		omap2_clkdm_sleep(clkdm);
+		clkdm_sleep(clkdm);
 	return 0;
 }
 
@@ -379,7 +376,10 @@
 	int i, num_mem_banks;
 	struct powerdomain *pwrdm;
 
-	/* Enable autoidle */
+	/*
+	 * Enable autoidle
+	 * XXX This should be handled by hwmod code or PRCM init code
+	 */
 	omap2_prm_write_mod_reg(OMAP24XX_AUTOIDLE_MASK, OCP_MOD,
 			  OMAP2_PRCM_SYSCONFIG_OFFSET);
 
@@ -405,83 +405,16 @@
 
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	omap2_clkdm_sleep(dsp_clkdm);
+	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	omap2_clkdm_sleep(gfx_clkdm);
+	clkdm_sleep(gfx_clkdm);
 
-	/*
-	 * Clear clockdomain wakeup dependencies and enable
-	 * hardware-supervised idle for all clkdms
-	 */
+	/* Enable hardware-supervised idle for all clkdms */
 	clkdm_for_each(clkdms_setup, NULL);
 	clkdm_add_wkdep(mpu_clkdm, wkup_clkdm);
 
-	/* Enable clock autoidle for all domains */
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_CAM_MASK |
-			       OMAP24XX_AUTO_MAILBOXES_MASK |
-			       OMAP24XX_AUTO_WDT4_MASK |
-			       OMAP2420_AUTO_WDT3_MASK |
-			       OMAP24XX_AUTO_MSPRO_MASK |
-			       OMAP2420_AUTO_MMC_MASK |
-			       OMAP24XX_AUTO_FAC_MASK |
-			       OMAP2420_AUTO_EAC_MASK |
-			       OMAP24XX_AUTO_HDQ_MASK |
-			       OMAP24XX_AUTO_UART2_MASK |
-			       OMAP24XX_AUTO_UART1_MASK |
-			       OMAP24XX_AUTO_I2C2_MASK |
-			       OMAP24XX_AUTO_I2C1_MASK |
-			       OMAP24XX_AUTO_MCSPI2_MASK |
-			       OMAP24XX_AUTO_MCSPI1_MASK |
-			       OMAP24XX_AUTO_MCBSP2_MASK |
-			       OMAP24XX_AUTO_MCBSP1_MASK |
-			       OMAP24XX_AUTO_GPT12_MASK |
-			       OMAP24XX_AUTO_GPT11_MASK |
-			       OMAP24XX_AUTO_GPT10_MASK |
-			       OMAP24XX_AUTO_GPT9_MASK |
-			       OMAP24XX_AUTO_GPT8_MASK |
-			       OMAP24XX_AUTO_GPT7_MASK |
-			       OMAP24XX_AUTO_GPT6_MASK |
-			       OMAP24XX_AUTO_GPT5_MASK |
-			       OMAP24XX_AUTO_GPT4_MASK |
-			       OMAP24XX_AUTO_GPT3_MASK |
-			       OMAP24XX_AUTO_GPT2_MASK |
-			       OMAP2420_AUTO_VLYNQ_MASK |
-			       OMAP24XX_AUTO_DSS_MASK,
-			       CORE_MOD, CM_AUTOIDLE1);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_UART3_MASK |
-			       OMAP24XX_AUTO_SSI_MASK |
-			       OMAP24XX_AUTO_USB_MASK,
-			       CORE_MOD, CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_SDRC_MASK |
-			       OMAP24XX_AUTO_GPMC_MASK |
-			       OMAP24XX_AUTO_SDMA_MASK,
-			       CORE_MOD, CM_AUTOIDLE3);
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_PKA_MASK |
-			       OMAP24XX_AUTO_AES_MASK |
-			       OMAP24XX_AUTO_RNG_MASK |
-			       OMAP24XX_AUTO_SHA_MASK |
-			       OMAP24XX_AUTO_DES_MASK,
-			       CORE_MOD, OMAP24XX_CM_AUTOIDLE4);
-
-	omap2_cm_write_mod_reg(OMAP2420_AUTO_DSP_IPI_MASK, OMAP24XX_DSP_MOD,
-			       CM_AUTOIDLE);
-
-	/* Put DPLL and both APLLs into autoidle mode */
-	omap2_cm_write_mod_reg((0x03 << OMAP24XX_AUTO_DPLL_SHIFT) |
-			       (0x03 << OMAP24XX_AUTO_96M_SHIFT) |
-			       (0x03 << OMAP24XX_AUTO_54M_SHIFT),
-			       PLL_MOD, CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(OMAP24XX_AUTO_OMAPCTRL_MASK |
-			       OMAP24XX_AUTO_WDT1_MASK |
-			       OMAP24XX_AUTO_MPU_WDT_MASK |
-			       OMAP24XX_AUTO_GPIOS_MASK |
-			       OMAP24XX_AUTO_32KSYNC_MASK |
-			       OMAP24XX_AUTO_GPT1_MASK,
-			       WKUP_MOD, CM_AUTOIDLE);
-
 	/* REVISIT: Configure number of 32 kHz clock cycles for sys_clk
 	 * stabilisation */
 	omap2_prm_write_mod_reg(15 << OMAP_SETUP_TIME_SHIFT, OMAP24XX_GR_MOD,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm34xx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm34xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm34xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm34xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/console.h>
+#include <trace/events/power.h>
 
 #include <plat/sram.h>
 #include "clockdomain.h"
@@ -311,11 +312,6 @@
 	return IRQ_HANDLED;
 }
 
-static void restore_control_register(u32 val)
-{
-	__asm__ __volatile__ ("mcr p15, 0, %0, c1, c0, 0" : : "r" (val));
-}
-
 /* Function to restore the table entry that was modified for enabling MMU */
 static void restore_table_entry(void)
 {
@@ -337,7 +333,7 @@
 	control_reg_value = __raw_readl(scratchpad_address
 					+ OMAP343X_CONTROL_REG_VALUE_OFFSET);
 	/* This will enable caches and prediction */
-	restore_control_register(control_reg_value);
+	set_cr(control_reg_value);
 }
 
 void omap_sram_idle(void)
@@ -496,7 +492,7 @@
 
 	pwrdm_post_transition();
 
-	omap2_clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
+	clkdm_allow_idle(mpu_pwrdm->pwrdm_clkdms[0]);
 }
 
 int omap3_can_sleep(void)
@@ -519,8 +515,14 @@
 	if (omap_irq_pending() || need_resched())
 		goto out;
 
+	trace_power_start(POWER_CSTATE, 1, smp_processor_id());
+	trace_cpu_idle(1, smp_processor_id());
+
 	omap_sram_idle();
 
+	trace_power_end(smp_processor_id());
+	trace_cpu_idle(PWR_EVENT_EXIT, smp_processor_id());
+
 out:
 	local_fiq_enable();
 	local_irq_enable();
@@ -688,149 +690,15 @@
 
 static void __init prcm_setup_regs(void)
 {
-	u32 omap3630_auto_uart4_mask = cpu_is_omap3630() ?
-					OMAP3630_AUTO_UART4_MASK : 0;
 	u32 omap3630_en_uart4_mask = cpu_is_omap3630() ?
 					OMAP3630_EN_UART4_MASK : 0;
 	u32 omap3630_grpsel_uart4_mask = cpu_is_omap3630() ?
 					OMAP3630_GRPSEL_UART4_MASK : 0;
 
-
-	/* XXX Reset all wkdeps. This should be done when initializing
-	 * powerdomains */
-	omap2_prm_write_mod_reg(0, OMAP3430_IVA2_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, MPU_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_DSS_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_NEON_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_CAM_MOD, PM_WKDEP);
-	omap2_prm_write_mod_reg(0, OMAP3430_PER_MOD, PM_WKDEP);
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_prm_write_mod_reg(0, OMAP3430ES2_SGX_MOD, PM_WKDEP);
-		omap2_prm_write_mod_reg(0, OMAP3430ES2_USBHOST_MOD, PM_WKDEP);
-	} else
-		omap2_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
-	 */
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_MODEM_MASK |
-		OMAP3430ES2_AUTO_MMC3_MASK |
-		OMAP3430ES2_AUTO_ICR_MASK |
-		OMAP3430_AUTO_AES2_MASK |
-		OMAP3430_AUTO_SHA12_MASK |
-		OMAP3430_AUTO_DES2_MASK |
-		OMAP3430_AUTO_MMC2_MASK |
-		OMAP3430_AUTO_MMC1_MASK |
-		OMAP3430_AUTO_MSPRO_MASK |
-		OMAP3430_AUTO_HDQ_MASK |
-		OMAP3430_AUTO_MCSPI4_MASK |
-		OMAP3430_AUTO_MCSPI3_MASK |
-		OMAP3430_AUTO_MCSPI2_MASK |
-		OMAP3430_AUTO_MCSPI1_MASK |
-		OMAP3430_AUTO_I2C3_MASK |
-		OMAP3430_AUTO_I2C2_MASK |
-		OMAP3430_AUTO_I2C1_MASK |
-		OMAP3430_AUTO_UART2_MASK |
-		OMAP3430_AUTO_UART1_MASK |
-		OMAP3430_AUTO_GPT11_MASK |
-		OMAP3430_AUTO_GPT10_MASK |
-		OMAP3430_AUTO_MCBSP5_MASK |
-		OMAP3430_AUTO_MCBSP1_MASK |
-		OMAP3430ES1_AUTO_FAC_MASK | /* This is es1 only */
-		OMAP3430_AUTO_MAILBOXES_MASK |
-		OMAP3430_AUTO_OMAPCTRL_MASK |
-		OMAP3430ES1_AUTO_FSHOSTUSB_MASK |
-		OMAP3430_AUTO_HSOTGUSB_MASK |
-		OMAP3430_AUTO_SAD2D_MASK |
-		OMAP3430_AUTO_SSI_MASK,
-		CORE_MOD, CM_AUTOIDLE1);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_PKA_MASK |
-		OMAP3430_AUTO_AES1_MASK |
-		OMAP3430_AUTO_RNG_MASK |
-		OMAP3430_AUTO_SHA11_MASK |
-		OMAP3430_AUTO_DES1_MASK,
-		CORE_MOD, CM_AUTOIDLE2);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_cm_write_mod_reg(
-			OMAP3430_AUTO_MAD2D_MASK |
-			OMAP3430ES2_AUTO_USBTLL_MASK,
-			CORE_MOD, CM_AUTOIDLE3);
-	}
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_WDT2_MASK |
-		OMAP3430_AUTO_WDT1_MASK |
-		OMAP3430_AUTO_GPIO1_MASK |
-		OMAP3430_AUTO_32KSYNC_MASK |
-		OMAP3430_AUTO_GPT12_MASK |
-		OMAP3430_AUTO_GPT1_MASK,
-		WKUP_MOD, CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_DSS_MASK,
-		OMAP3430_DSS_MOD,
-		CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		OMAP3430_AUTO_CAM_MASK,
-		OMAP3430_CAM_MOD,
-		CM_AUTOIDLE);
-
-	omap2_cm_write_mod_reg(
-		omap3630_auto_uart4_mask |
-		OMAP3430_AUTO_GPIO6_MASK |
-		OMAP3430_AUTO_GPIO5_MASK |
-		OMAP3430_AUTO_GPIO4_MASK |
-		OMAP3430_AUTO_GPIO3_MASK |
-		OMAP3430_AUTO_GPIO2_MASK |
-		OMAP3430_AUTO_WDT3_MASK |
-		OMAP3430_AUTO_UART3_MASK |
-		OMAP3430_AUTO_GPT9_MASK |
-		OMAP3430_AUTO_GPT8_MASK |
-		OMAP3430_AUTO_GPT7_MASK |
-		OMAP3430_AUTO_GPT6_MASK |
-		OMAP3430_AUTO_GPT5_MASK |
-		OMAP3430_AUTO_GPT4_MASK |
-		OMAP3430_AUTO_GPT3_MASK |
-		OMAP3430_AUTO_GPT2_MASK |
-		OMAP3430_AUTO_MCBSP4_MASK |
-		OMAP3430_AUTO_MCBSP3_MASK |
-		OMAP3430_AUTO_MCBSP2_MASK,
-		OMAP3430_PER_MOD,
-		CM_AUTOIDLE);
-
-	if (omap_rev() > OMAP3430_REV_ES1_0) {
-		omap2_cm_write_mod_reg(
-			OMAP3430ES2_AUTO_USBHOST_MASK,
-			OMAP3430ES2_USBHOST_MOD,
-			CM_AUTOIDLE);
-	}
-
+	/* XXX This should be handled by hwmod code or SCM init code */
 	omap_ctrl_writel(OMAP3430_AUTOIDLE_MASK, OMAP2_CONTROL_SYSCONFIG);
 
 	/*
-	 * Set all plls to autoidle. This is needed until autoidle is
-	 * enabled by clockfw
-	 */
-	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_IVA2_DPLL_SHIFT,
-			 OMAP3430_IVA2_MOD, CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg(1 << OMAP3430_AUTO_MPU_DPLL_SHIFT,
-			 MPU_MOD,
-			 CM_AUTOIDLE2);
-	omap2_cm_write_mod_reg((1 << OMAP3430_AUTO_PERIPH_DPLL_SHIFT) |
-			 (1 << OMAP3430_AUTO_CORE_DPLL_SHIFT),
-			 PLL_MOD,
-			 CM_AUTOIDLE);
-	omap2_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.
@@ -928,8 +796,7 @@
 				pwrst->pwrdm == core_pwrdm &&
 				state == PWRDM_POWER_OFF) {
 			pwrst->next_state = PWRDM_POWER_RET;
-			WARN_ONCE(1,
-				"%s: Core OFF disabled due to errata i583\n",
+			pr_warn("%s: Core OFF disabled due to errata i583\n",
 				__func__);
 		} else {
 			pwrst->next_state = state;
@@ -990,10 +857,10 @@
 static int __init clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
 	if (clkdm->flags & CLKDM_CAN_ENABLE_AUTO)
-		omap2_clkdm_allow_idle(clkdm);
+		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
 		 atomic_read(&clkdm->usecount) == 0)
-		omap2_clkdm_sleep(clkdm);
+		clkdm_sleep(clkdm);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,8 +18,8 @@
 #include <plat/omap-pm.h>
 #include <plat/omap_device.h>
 #include <plat/common.h>
-#include <plat/voltage.h>
 
+#include "voltage.h"
 #include "powerdomain.h"
 #include "clockdomain.h"
 #include "pm.h"
@@ -83,10 +83,13 @@
 static void omap2_init_processor_devices(void)
 {
 	_init_omap_device("mpu", &mpu_dev);
-	_init_omap_device("iva", &iva_dev);
+	if (omap3_has_iva())
+		_init_omap_device("iva", &iva_dev);
+
 	if (cpu_is_omap44xx()) {
 		_init_omap_device("l3_main_1", &l3_dev);
 		_init_omap_device("dsp", &dsp_dev);
+		_init_omap_device("iva", &iva_dev);
 	} else {
 		_init_omap_device("l3_main", &l3_dev);
 	}
@@ -124,7 +127,7 @@
 			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
 			sleep_switch = LOWPOWERSTATE_SWITCH;
 		} else {
-			omap2_clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
 			pwrdm_wait_transition(pwrdm);
 			sleep_switch = FORCEWAKEUP_SWITCH;
 		}
@@ -140,9 +143,9 @@
 	switch (sleep_switch) {
 	case FORCEWAKEUP_SWITCH:
 		if (pwrdm->pwrdm_clkdms[0]->flags & CLKDM_CAN_ENABLE_AUTO)
-			omap2_clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
+			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
 		else
-			omap2_clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
+			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
 		break;
 	case LOWPOWERSTATE_SWITCH:
 		pwrdm_set_lowpwrstchange(pwrdm);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/pm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/pm.h	2011-05-19 00:06:34.000000000 -0400
@@ -92,7 +92,7 @@
 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 int save_secure_ram_context(u32 *addr);
 extern void omap3_save_scratchpad_contents(void);
 
 extern unsigned int omap24xx_idle_loop_suspend_sz;
@@ -127,6 +127,7 @@
 #ifdef CONFIG_TWL4030_CORE
 extern int omap3_twl_init(void);
 extern int omap4_twl_init(void);
+extern int omap3_twl_set_sr_bit(bool enable);
 #else
 static inline int omap3_twl_init(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomain.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomain.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomain.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomain.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP powerdomain control
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2009 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Written by Paul Walmsley
  * Added OMAP4 specific support by Abhijit Pagare <abhijitpagare@ti.com>
@@ -19,12 +19,15 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <trace/events/power.h>
+
 #include "cm2xxx_3xxx.h"
 #include "prcm44xx.h"
 #include "cm44xx.h"
 #include "prm2xxx_3xxx.h"
 #include "prm44xx.h"
 
+#include <asm/cpu.h>
 #include <plat/cpu.h>
 #include "powerdomain.h"
 #include "clockdomain.h"
@@ -32,6 +35,8 @@
 
 #include "pm.h"
 
+#define PWRDM_TRACE_STATES_FLAG	(1<<31)
+
 enum {
 	PWRDM_STATE_NOW = 0,
 	PWRDM_STATE_PREV,
@@ -130,8 +135,7 @@
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-	int prev;
-	int state;
+	int prev, state, trace_state = 0;
 
 	if (pwrdm == NULL)
 		return -EINVAL;
@@ -148,6 +152,17 @@
 			pwrdm->state_counter[prev]++;
 		if (prev == PWRDM_POWER_RET)
 			_update_logic_membank_counters(pwrdm);
+		/*
+		 * If the power domain did not hit the desired state,
+		 * generate a trace event with both the desired and hit states
+		 */
+		if (state != prev) {
+			trace_state = (PWRDM_TRACE_STATES_FLAG |
+				       ((state & OMAP_POWERSTATE_MASK) << 8) |
+				       ((prev & OMAP_POWERSTATE_MASK) << 0));
+			trace_power_domain_target(pwrdm->name, trace_state,
+						  smp_processor_id());
+		}
 		break;
 	default:
 		return -EINVAL;
@@ -181,7 +196,7 @@
 /**
  * pwrdm_init - set up the powerdomain layer
  * @pwrdm_list: array of struct powerdomain pointers to register
- * @custom_funcs: func pointers for arch specfic implementations
+ * @custom_funcs: func pointers for arch specific implementations
  *
  * Loop through the array of powerdomains @pwrdm_list, registering all
  * that are available on the current CPU. If pwrdm_list is supplied
@@ -406,8 +421,13 @@
 	pr_debug("powerdomain: setting next powerstate for %s to %0x\n",
 		 pwrdm->name, pwrst);
 
-	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst)
+	if (arch_pwrdm && arch_pwrdm->pwrdm_set_next_pwrst) {
+		/* Trace the pwrdm desired target state */
+		trace_power_domain_target(pwrdm->name, pwrst,
+					  smp_processor_id());
+		/* Program the pwrdm desired target state */
 		ret = arch_pwrdm->pwrdm_set_next_pwrst(pwrdm, pwrst);
+	}
 
 	return ret;
 }
@@ -938,3 +958,44 @@
 
 	return count;
 }
+
+/**
+ * pwrdm_can_ever_lose_context - can this powerdomain ever lose context?
+ * @pwrdm: struct powerdomain *
+ *
+ * Given a struct powerdomain * @pwrdm, returns 1 if the powerdomain
+ * can lose either memory or logic context or if @pwrdm is invalid, or
+ * returns 0 otherwise.  This function is not concerned with how the
+ * powerdomain registers are programmed (i.e., to go off or not); it's
+ * concerned with whether it's ever possible for this powerdomain to
+ * go off while some other part of the chip is active.  This function
+ * assumes that every powerdomain can go to either ON or INACTIVE.
+ */
+bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm)
+{
+	int i;
+
+	if (IS_ERR_OR_NULL(pwrdm)) {
+		pr_debug("powerdomain: %s: invalid powerdomain pointer\n",
+			 __func__);
+		return 1;
+	}
+
+	if (pwrdm->pwrsts & PWRSTS_OFF)
+		return 1;
+
+	if (pwrdm->pwrsts & PWRSTS_RET) {
+		if (pwrdm->pwrsts_logic_ret & PWRSTS_OFF)
+			return 1;
+
+		for (i = 0; i < pwrdm->banks; i++)
+			if (pwrdm->pwrsts_mem_ret[i] & PWRSTS_OFF)
+				return 1;
+	}
+
+	for (i = 0; i < pwrdm->banks; i++)
+		if (pwrdm->pwrsts_mem_on[i] & PWRSTS_OFF)
+			return 1;
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomain.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomain.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomain.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomain.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP2/3/4 powerdomain control
  *
  * Copyright (C) 2007-2008, 2010 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley
  *
@@ -34,17 +34,14 @@
 
 /* Powerdomain allowable state bitfields */
 #define PWRSTS_ON		(1 << PWRDM_POWER_ON)
+#define PWRSTS_INACTIVE		(1 << PWRDM_POWER_INACTIVE)
+#define PWRSTS_RET		(1 << PWRDM_POWER_RET)
 #define PWRSTS_OFF		(1 << PWRDM_POWER_OFF)
-#define PWRSTS_OFF_ON		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_ON))
 
-#define PWRSTS_OFF_RET		((1 << PWRDM_POWER_OFF) | \
-				 (1 << PWRDM_POWER_RET))
-
-#define PWRSTS_RET_ON		((1 << PWRDM_POWER_RET) | \
-				 (1 << PWRDM_POWER_ON))
-
-#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | (1 << PWRDM_POWER_ON))
+#define PWRSTS_OFF_ON		(PWRSTS_OFF | PWRSTS_ON)
+#define PWRSTS_OFF_RET		(PWRSTS_OFF | PWRSTS_RET)
+#define PWRSTS_RET_ON		(PWRSTS_RET | PWRSTS_ON)
+#define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
 
 /* Powerdomain flags */
@@ -124,7 +121,7 @@
 };
 
 /**
- * struct pwrdm_ops - Arch specfic function implementations
+ * struct pwrdm_ops - Arch specific function implementations
  * @pwrdm_set_next_pwrst: Set the target power state for a pd
  * @pwrdm_read_next_pwrst: Read the target power state set for a pd
  * @pwrdm_read_pwrst: Read the current power state of a pd
@@ -165,7 +162,6 @@
 	int	(*pwrdm_wait_transition)(struct powerdomain *pwrdm);
 };
 
-void pwrdm_fw_init(void);
 void pwrdm_init(struct powerdomain **pwrdm_list, struct pwrdm_ops *custom_funcs);
 
 struct powerdomain *pwrdm_lookup(const char *name);
@@ -212,6 +208,7 @@
 int pwrdm_post_transition(void);
 int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 u32 pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
+bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
 extern void omap2xxx_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP2/3 common powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
  *
@@ -62,13 +62,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX |
 					   CHIP_IS_OMAP3430ES1),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -76,4 +76,5 @@
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
 	.omap_chip	= OMAP_CHIP_INIT(CHIP_IS_OMAP24XX | CHIP_IS_OMAP3430),
+	.pwrsts		= PWRSTS_ON,
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains2xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP2XXX powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
  *
@@ -30,13 +30,13 @@
 	.prcm_offs	  = OMAP24XX_DSP_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP24XX),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
+		[0] = PWRSTS_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
 	},
 };
 
@@ -48,10 +48,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET,
+		[0] = PWRSTS_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
 	},
 };
 
@@ -78,7 +78,7 @@
  * 2430-specific powerdomains
  */
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 
 /* XXX 2430 KILLDOMAINWKUP bit?  No current users apparently */
 
@@ -87,17 +87,17 @@
 	.prcm_offs	  = OMAP2430_MDM_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP2430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
-#endif     /* CONFIG_ARCH_OMAP2430 */
+#endif     /* CONFIG_SOC_OMAP2430 */
 
 /* As powerdomains are added or removed above, this list must also be changed */
 static struct powerdomain *powerdomains_omap2xxx[] __initdata = {
@@ -111,7 +111,7 @@
 	&core_24xx_pwrdm,
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 	&mdm_pwrdm,
 #endif
 	NULL
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP3 powerdomain definitions
  *
  * Copyright (C) 2007-2008 Texas Instruments, Inc.
- * Copyright (C) 2007-2010 Nokia Corporation
+ * Copyright (C) 2007-2011 Nokia Corporation
  *
  * Paul Walmsley, Jouni HÃ¶gander
  *
@@ -47,10 +47,10 @@
 		[3] = PWRSTS_OFF_RET,
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,
-		[1] = PWRDM_POWER_ON,
+		[0] = PWRSTS_ON,
+		[1] = PWRSTS_ON,
 		[2] = PWRSTS_OFF_ON,
-		[3] = PWRDM_POWER_ON,
+		[3] = PWRSTS_ON,
 	},
 };
 
@@ -72,7 +72,7 @@
 
 /*
  * The USBTLL Save-and-Restore mechanism is broken on
- * 3430s upto ES3.0 and 3630ES1.0. Hence this feature
+ * 3430s up to ES3.0 and 3630ES1.0. Hence this feature
  * needs to be disabled on these chips.
  * Refer: 3430 errata ID i459 and 3630 errata ID i579
  *
@@ -128,13 +128,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_DSS_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -149,13 +149,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	/* XXX This is accurate for 3430 SGX, but what about GFX? */
 	.pwrsts		  = PWRSTS_OFF_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -164,13 +164,13 @@
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.prcm_offs	  = OMAP3430_CAM_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -182,10 +182,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
@@ -200,7 +200,7 @@
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP3430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 };
 
 static struct powerdomain usbhost_pwrdm = {
@@ -208,7 +208,7 @@
 	.prcm_offs	  = OMAP3430ES2_USBHOST_MOD,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_GE_OMAP3430ES2),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_RET,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	/*
 	 * REVISIT: Enabling usb host save and restore mechanism seems to
 	 * leave the usb host domain permanently in ACTIVE mode after
@@ -218,10 +218,10 @@
 	/*.flags	  = PWRDM_HAS_HDWR_SAR,*/ /* for USBHOST ctrlr only */
 	.banks		  = 1,
 	.pwrsts_mem_ret	  = {
-		[0] = PWRDM_POWER_RET, /* MEMRETSTATE */
+		[0] = PWRSTS_RET, /* MEMRETSTATE */
 	},
 	.pwrsts_mem_on	  = {
-		[0] = PWRDM_POWER_ON,  /* MEMONSTATE */
+		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/powerdomains44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * OMAP4 Power domains framework
  *
  * Copyright (C) 2009-2010 Texas Instruments, Inc.
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  *
  * Abhijit Pagare (abhijitpagare@ti.com)
  * Benoit Cousson (b-cousson@ti.com)
@@ -40,18 +40,18 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 5,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* core_nret_bank */
+		[0] = PWRSTS_OFF,	/* core_nret_bank */
 		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_RET,	/* core_other_bank */
+		[2] = PWRSTS_RET,	/* core_other_bank */
 		[3] = PWRSTS_OFF_RET,	/* ducati_l2ram */
 		[4] = PWRSTS_OFF_RET,	/* ducati_unicache */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* core_nret_bank */
+		[0] = PWRSTS_ON,	/* core_nret_bank */
 		[1] = PWRSTS_OFF_RET,	/* core_ocmram */
-		[2] = PWRDM_POWER_ON,	/* core_other_bank */
-		[3] = PWRDM_POWER_ON,	/* ducati_l2ram */
-		[4] = PWRDM_POWER_ON,	/* ducati_unicache */
+		[2] = PWRSTS_ON,	/* core_other_bank */
+		[3] = PWRSTS_ON,	/* ducati_l2ram */
+		[4] = PWRSTS_ON,	/* ducati_unicache */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -65,10 +65,10 @@
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* gfx_mem */
+		[0] = PWRSTS_OFF,	/* gfx_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* gfx_mem */
+		[0] = PWRSTS_ON,	/* gfx_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -80,15 +80,15 @@
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* aessmem */
-		[1] = PWRDM_POWER_OFF,	/* periphmem */
+		[0] = PWRSTS_RET,	/* aessmem */
+		[1] = PWRSTS_OFF,	/* periphmem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* aessmem */
-		[1] = PWRDM_POWER_ON,	/* periphmem */
+		[0] = PWRSTS_ON,	/* aessmem */
+		[1] = PWRSTS_ON,	/* periphmem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -103,10 +103,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* dss_mem */
+		[0] = PWRSTS_OFF,	/* dss_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* dss_mem */
+		[0] = PWRSTS_ON,	/* dss_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -121,14 +121,14 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_RET,	/* tesla_edma */
+		[0] = PWRSTS_RET,	/* tesla_edma */
 		[1] = PWRSTS_OFF_RET,	/* tesla_l1 */
 		[2] = PWRSTS_OFF_RET,	/* tesla_l2 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* tesla_edma */
-		[1] = PWRDM_POWER_ON,	/* tesla_l1 */
-		[2] = PWRDM_POWER_ON,	/* tesla_l2 */
+		[0] = PWRSTS_ON,	/* tesla_edma */
+		[1] = PWRSTS_ON,	/* tesla_l1 */
+		[2] = PWRSTS_ON,	/* tesla_l2 */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -142,10 +142,10 @@
 	.pwrsts		  = PWRSTS_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* wkup_bank */
+		[0] = PWRSTS_OFF,	/* wkup_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* wkup_bank */
+		[0] = PWRSTS_ON,	/* wkup_bank */
 	},
 };
 
@@ -162,7 +162,7 @@
 		[0] = PWRSTS_OFF_RET,	/* cpu0_l1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu0_l1 */
+		[0] = PWRSTS_ON,	/* cpu0_l1 */
 	},
 };
 
@@ -179,7 +179,7 @@
 		[0] = PWRSTS_OFF_RET,	/* cpu1_l1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cpu1_l1 */
+		[0] = PWRSTS_ON,	/* cpu1_l1 */
 	},
 };
 
@@ -192,10 +192,10 @@
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* emu_bank */
+		[0] = PWRSTS_OFF,	/* emu_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* emu_bank */
+		[0] = PWRSTS_ON,	/* emu_bank */
 	},
 };
 
@@ -211,12 +211,12 @@
 	.pwrsts_mem_ret	= {
 		[0] = PWRSTS_OFF_RET,	/* mpu_l1 */
 		[1] = PWRSTS_OFF_RET,	/* mpu_l2 */
-		[2] = PWRDM_POWER_RET,	/* mpu_ram */
+		[2] = PWRSTS_RET,	/* mpu_ram */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* mpu_l1 */
-		[1] = PWRDM_POWER_ON,	/* mpu_l2 */
-		[2] = PWRDM_POWER_ON,	/* mpu_ram */
+		[0] = PWRSTS_ON,	/* mpu_l1 */
+		[1] = PWRSTS_ON,	/* mpu_l2 */
+		[2] = PWRSTS_ON,	/* mpu_ram */
 	},
 };
 
@@ -227,19 +227,19 @@
 	.prcm_partition	  = OMAP4430_PRM_PARTITION,
 	.omap_chip	  = OMAP_CHIP_INIT(CHIP_IS_OMAP4430),
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
-	.pwrsts_logic_ret = PWRDM_POWER_OFF,
+	.pwrsts_logic_ret = PWRSTS_OFF,
 	.banks		  = 4,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* hwa_mem */
+		[0] = PWRSTS_OFF,	/* hwa_mem */
 		[1] = PWRSTS_OFF_RET,	/* sl2_mem */
 		[2] = PWRSTS_OFF_RET,	/* tcm1_mem */
 		[3] = PWRSTS_OFF_RET,	/* tcm2_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* hwa_mem */
-		[1] = PWRDM_POWER_ON,	/* sl2_mem */
-		[2] = PWRDM_POWER_ON,	/* tcm1_mem */
-		[3] = PWRDM_POWER_ON,	/* tcm2_mem */
+		[0] = PWRSTS_ON,	/* hwa_mem */
+		[1] = PWRSTS_ON,	/* sl2_mem */
+		[2] = PWRSTS_ON,	/* tcm1_mem */
+		[3] = PWRSTS_ON,	/* tcm2_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -253,10 +253,10 @@
 	.pwrsts		  = PWRSTS_OFF_ON,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* cam_mem */
+		[0] = PWRSTS_OFF,	/* cam_mem */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* cam_mem */
+		[0] = PWRSTS_ON,	/* cam_mem */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -271,10 +271,10 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 1,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* l3init_bank1 */
+		[0] = PWRSTS_OFF,	/* l3init_bank1 */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* l3init_bank1 */
+		[0] = PWRSTS_ON,	/* l3init_bank1 */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
@@ -289,12 +289,12 @@
 	.pwrsts_logic_ret = PWRSTS_OFF_RET,
 	.banks		  = 2,
 	.pwrsts_mem_ret	= {
-		[0] = PWRDM_POWER_OFF,	/* nonretained_bank */
-		[1] = PWRDM_POWER_RET,	/* retained_bank */
+		[0] = PWRSTS_OFF,	/* nonretained_bank */
+		[1] = PWRSTS_RET,	/* retained_bank */
 	},
 	.pwrsts_mem_on	= {
-		[0] = PWRDM_POWER_ON,	/* nonretained_bank */
-		[1] = PWRDM_POWER_ON,	/* retained_bank */
+		[0] = PWRSTS_ON,	/* nonretained_bank */
+		[1] = PWRSTS_ON,	/* retained_bank */
 	},
 	.flags		= PWRDM_HAS_LOWPOWERSTATECHANGE,
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prcm.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prcm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prcm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prcm.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 
+#include <mach/system.h>
 #include <plat/common.h>
 #include <plat/prcm.h>
 #include <plat/irqs.h>
@@ -57,7 +58,7 @@
 EXPORT_SYMBOL(omap_prcm_get_reset_sources);
 
 /* Resets clock rates and reboots the system. Only called from system.h */
-void omap_prcm_arch_reset(char mode, const char *cmd)
+static void omap_prcm_arch_reset(char mode, const char *cmd)
 {
 	s16 prcm_offs = 0;
 
@@ -108,6 +109,8 @@
 	omap2_prm_read_mod_reg(prcm_offs, OMAP2_RM_RSTCTRL); /* OCP barrier */
 }
 
+void (*arch_reset)(char, const char *) = omap_prcm_arch_reset;
+
 /**
  * omap2_cm_wait_idlest - wait for IDLEST bit to indicate module readiness
  * @reg: physical address of module IDLEST register
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prcm-common.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prcm-common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prcm-common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prcm-common.h	2011-05-19 00:06:34.000000000 -0400
@@ -121,6 +121,10 @@
 #define OMAP24XX_ST_MCSPI2_MASK				(1 << 18)
 #define OMAP24XX_ST_MCSPI1_SHIFT			17
 #define OMAP24XX_ST_MCSPI1_MASK				(1 << 17)
+#define OMAP24XX_ST_MCBSP2_SHIFT			16
+#define OMAP24XX_ST_MCBSP2_MASK				(1 << 16)
+#define OMAP24XX_ST_MCBSP1_SHIFT			15
+#define OMAP24XX_ST_MCBSP1_MASK				(1 << 15)
 #define OMAP24XX_ST_GPT12_SHIFT				14
 #define OMAP24XX_ST_GPT12_MASK				(1 << 14)
 #define OMAP24XX_ST_GPT11_SHIFT				13
@@ -191,6 +195,8 @@
 #define OMAP3430_AUTOIDLE_MASK				(1 << 0)
 
 /* CM_FCLKEN1_CORE, CM_ICLKEN1_CORE, PM_WKEN1_CORE shared bits */
+#define OMAP3430_EN_MMC3_MASK				(1 << 30)
+#define OMAP3430_EN_MMC3_SHIFT				30
 #define OMAP3430_EN_MMC2_MASK				(1 << 25)
 #define OMAP3430_EN_MMC2_SHIFT				25
 #define OMAP3430_EN_MMC1_MASK				(1 << 24)
@@ -231,6 +237,8 @@
 #define OMAP3430_EN_HSOTGUSB_SHIFT			4
 
 /* PM_WKST1_CORE, CM_IDLEST1_CORE shared bits */
+#define OMAP3430_ST_MMC3_SHIFT				30
+#define OMAP3430_ST_MMC3_MASK				(1 << 30)
 #define OMAP3430_ST_MMC2_SHIFT				25
 #define OMAP3430_ST_MMC2_MASK				(1 << 25)
 #define OMAP3430_ST_MMC1_SHIFT				24
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prcm_mpu44xx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prcm_mpu44xx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prcm_mpu44xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prcm_mpu44xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,8 +38,8 @@
 #define OMAP4430_PRCM_MPU_CPU1_INST		0x0800
 
 /* PRCM_MPU clockdomain register offsets (from instance start) */
-#define OMAP4430_PRCM_MPU_CPU0_MPU_CDOFFS	0x0018
-#define OMAP4430_PRCM_MPU_CPU1_MPU_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU0_CPU0_CDOFFS	0x0018
+#define OMAP4430_PRCM_MPU_CPU1_CPU1_CDOFFS	0x0018
 
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,8 @@
 /**
  * omap2_prm_deassert_hardreset - deassert a submodule hardreset line and wait
  * @prm_mod: PRM submodule base (e.g. CORE_MOD)
- * @shift: register bit shift corresponding to the reset line to deassert
+ * @rst_shift: register bit shift corresponding to the reset line to deassert
+ * @st_shift: register bit shift for the status of the deasserted submodule
  *
  * Some IPs like dsp or iva contain processors that require an HW
  * reset line to be asserted / deasserted in order to fully enable the
@@ -129,27 +130,28 @@
  * -EINVAL upon an argument error, -EEXIST if the submodule was already out
  * of reset, or -EBUSY if the submodule did not exit reset promptly.
  */
-int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift)
 {
-	u32 mask;
+	u32 rst, st;
 	int c;
 
 	if (!(cpu_is_omap24xx() || cpu_is_omap34xx()))
 		return -EINVAL;
 
-	mask = 1 << shift;
+	rst = 1 << rst_shift;
+	st = 1 << st_shift;
 
 	/* Check the current status to avoid de-asserting the line twice */
-	if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, mask) == 0)
+	if (omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTCTRL, rst) == 0)
 		return -EEXIST;
 
 	/* Clear the reset status by writing 1 to the status bit */
-	omap2_prm_rmw_mod_reg_bits(0xffffffff, mask, prm_mod, OMAP2_RM_RSTST);
+	omap2_prm_rmw_mod_reg_bits(0xffffffff, st, prm_mod, OMAP2_RM_RSTST);
 	/* de-assert the reset control line */
-	omap2_prm_rmw_mod_reg_bits(mask, 0, prm_mod, OMAP2_RM_RSTCTRL);
+	omap2_prm_rmw_mod_reg_bits(rst, 0, prm_mod, OMAP2_RM_RSTCTRL);
 	/* wait the status to be set */
 	omap_test_timeout(omap2_prm_read_mod_bits_shift(prm_mod, OMAP2_RM_RSTST,
-						  mask),
+						  st),
 			  MAX_MODULE_HARDRESET_WAIT, c);
 
 	return (c == MAX_MODULE_HARDRESET_WAIT) ? -EBUSY : 0;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/prm2xxx_3xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -282,7 +282,8 @@
 		"not suppose to be used on omap4\n");
 	return 0;
 }
-static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift)
+static inline int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift,
+						u8 st_shift)
 {
 	WARN(1, "prm: omap2xxx/omap3xxx specific function and "
 		"not suppose to be used on omap4\n");
@@ -300,7 +301,7 @@
 /* These omap2_ PRM functions apply to both OMAP2 and 3 */
 extern int omap2_prm_is_hardreset_asserted(s16 prm_mod, u8 shift);
 extern int omap2_prm_assert_hardreset(s16 prm_mod, u8 shift);
-extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 shift);
+extern int omap2_prm_deassert_hardreset(s16 prm_mod, u8 rst_shift, u8 st_shift);
 
 #endif	/* CONFIG_ARCH_OMAP4 */
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/serial.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/serial.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/serial.c	2011-05-19 00:06:34.000000000 -0400
@@ -486,7 +486,7 @@
 		mod_timer(&uart->timer, jiffies + uart->timeout);
 	omap_uart_smart_idle_enable(uart, 0);
 
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_omap34xx() && !cpu_is_ti816x()) {
 		u32 mod = (uart->num > 1) ? OMAP3430_PER_MOD : CORE_MOD;
 		u32 wk_mask = 0;
 		u32 padconf = 0;
@@ -655,7 +655,7 @@
 }
 #endif
 
-void __init omap_serial_early_init(void)
+static int __init omap_serial_early_init(void)
 {
 	int i = 0;
 
@@ -672,7 +672,7 @@
 
 		uart = kzalloc(sizeof(struct omap_uart_state), GFP_KERNEL);
 		if (WARN_ON(!uart))
-			return;
+			return -ENODEV;
 
 		uart->oh = oh;
 		uart->num = i++;
@@ -680,7 +680,7 @@
 		num_uarts++;
 
 		/*
-		 * NOTE: omap_hwmod_init() has not yet been called,
+		 * NOTE: omap_hwmod_setup*() has not yet been called,
 		 *       so no hwmod functions will work yet.
 		 */
 
@@ -691,7 +691,10 @@
 		 */
 		uart->oh->flags |= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET;
 	} while (1);
+
+	return 0;
 }
+core_initcall(omap_serial_early_init);
 
 /**
  * omap_serial_init_port() - initialize single serial port
@@ -759,13 +762,13 @@
 	p->private_data = uart;
 
 	/*
-	 * omap44xx: Never read empty UART fifo
+	 * omap44xx, ti816x: Never read empty UART fifo
 	 * omap3xxx: Never read empty UART fifo on UARTs
 	 * with IP rev >=0x52
 	 */
 	uart->regshift = p->regshift;
 	uart->membase = p->membase;
-	if (cpu_is_omap44xx())
+	if (cpu_is_omap44xx() || cpu_is_ti816x())
 		uart->errata |= UART_ERRATA_FIFO_FULL_ABORT;
 	else if ((serial_read_reg(uart, UART_OMAP_MVER) & 0xFF)
 			>= UART_OMAP_NO_EMPTY_FIFO_READ_IP_REV)
@@ -847,7 +850,7 @@
 	}
 
 	/* Enable the MDR1 errata for OMAP3 */
-	if (cpu_is_omap34xx())
+	if (cpu_is_omap34xx() && !cpu_is_ti816x())
 		uart->errata |= UART_ERRATA_i202_MDR1_ACCESS;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sleep24xx.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sleep24xx.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sleep24xx.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sleep24xx.S	2011-05-19 00:06:34.000000000 -0400
@@ -47,6 +47,7 @@
  * 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.
  */
+	.align	3
 ENTRY(omap24xx_idle_loop_suspend)
 	stmfd	sp!, {r0, lr}		@ save registers on stack
 	mov	r0, #0			@ clear for mcr setup
@@ -82,6 +83,7 @@
  * The DLL load value is not kept in RETENTION or OFF.	It needs to be restored
  * at wake
  */
+	.align	3
 ENTRY(omap24xx_cpu_suspend)
 	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
 	mov	r3, #0x0		@ clear for mcr call
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sleep34xx.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sleep34xx.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sleep34xx.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sleep34xx.S	2011-05-19 00:06:34.000000000 -0400
@@ -64,6 +64,11 @@
 #define SDRC_DLLA_STATUS_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_STATUS)
 #define SDRC_DLLA_CTRL_V	OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 
+/*
+ * This file needs be built unconditionally as ARM to interoperate correctly
+ * with non-Thumb-2-capable firmware.
+ */
+	.arm
 
 /*
  * API functions
@@ -82,6 +87,8 @@
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(get_restore_pointer)
+	.align
 ENTRY(get_restore_pointer_sz)
 	.word	. - get_restore_pointer
 
@@ -91,6 +98,8 @@
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore_3630
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(get_omap3630_restore_pointer)
+	.align
 ENTRY(get_omap3630_restore_pointer_sz)
 	.word	. - get_omap3630_restore_pointer
 
@@ -100,6 +109,8 @@
 	stmfd	sp!, {lr}	@ save registers on stack
 	adr	r0, restore_es3
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(get_es3_restore_pointer)
+	.align
 ENTRY(get_es3_restore_pointer_sz)
 	.word	. - get_es3_restore_pointer
 
@@ -113,11 +124,14 @@
 	stmfd	sp!, {lr}	@ save registers on stack
 	/* Setup so that we will disable and enable l2 */
 	mov	r1, #0x1
-	str	r1, l2dis_3630
+	adrl	r2, l2dis_3630	@ may be too distant for plain adr
+	str	r1, [r2]
 	ldmfd	sp!, {pc}	@ restore regs and return
+ENDPROC(enable_omap3630_toggle_l2_on_restore)
 
 	.text
 /* Function to call rom code to save secure ram context */
+	.align	3
 ENTRY(save_secure_ram_context)
 	stmfd	sp!, {r1-r12, lr}	@ save registers on stack
 	adr	r3, api_params		@ r3 points to parameters
@@ -131,20 +145,22 @@
 	mov	r1, #0			@ set task id for ROM code in r1
 	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 	nop
 	nop
 	nop
 	nop
 	ldmfd	sp!, {r1-r12, pc}
+	.align
 sram_phy_addr_mask:
 	.word	SRAM_BASE_P
 high_mask:
 	.word	0xffff
 api_params:
 	.word	0x4, 0x0, 0x0, 0x1, 0x1
+ENDPROC(save_secure_ram_context)
 ENTRY(save_secure_ram_context_sz)
 	.word	. - save_secure_ram_context
 
@@ -169,16 +185,17 @@
  *   depending on the low power mode (non-OFF vs OFF modes),
  *   cf. 'Resume path for xxx mode' comments.
  */
+	.align	3
 ENTRY(omap34xx_cpu_suspend)
 	stmfd	sp!, {r0-r12, lr}	@ save registers on stack
 
 	/*
-	 * r0 contains restore pointer in sdram
+	 * r0 contains CPU context save/restore pointer in sdram
 	 * r1 contains information about saving context:
 	 *   0 - No context lost
 	 *   1 - Only L1 and logic lost
-	 *   2 - Only L2 lost
-	 *   3 - Both L1 and L2 lost
+	 *   2 - Only L2 lost (Even L1 is retained we clean it along with L2)
+	 *   3 - Both L1 and L2 lost and logic lost
 	 */
 
 	/* Directly jump to WFI is the context save is not required */
@@ -199,89 +216,74 @@
 	beq	clean_caches
 
 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
+	mov	r4, sp			@ Store sp
+	mrs	r5, spsr		@ Store spsr
+	mov	r6, lr			@ Store lr
 	stmia	r8!, {r4-r6}
-	/*
-	 * Data aux fault status register, instruction aux fault status,
-	 * data 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
+
+	mrc	p15, 0, r4, c1, c0, 2	@ Coprocessor access control register
+	mrc	p15, 0, r5, c2, c0, 0	@ TTBR0
+	mrc	p15, 0, r6, c2, c0, 1	@ TTBR1
+	mrc	p15, 0, r7, c2, c0, 2	@ TTBCR
 	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, c3, c0, 0	@ Domain access Control Register
+	mrc	p15, 0, r5, c10, c2, 0	@ PRRR
+	mrc	p15, 0, r6, c10, c2, 1	@ NMRR
+	stmia	r8!,{r4-r6}
 
-	mrc	p15, 0, r4, c1, c0, 0
-	/* save control register */
+	mrc	p15, 0, r4, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
+	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
+	mrs	r7, cpsr		@ Store current cpsr
+	stmia	r8!, {r4-r7}
+
+	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	r1, #0x1 		@ Check whether L2 inval is required
-	beq	omap3_do_wfi
-
-clean_l2:
-	/*
 	 * jump out to kernel flush routine
 	 *  - reuse that code is better
 	 *  - it executes in a cached space so is faster than refetch per-block
 	 *  - should be faster and will change with kernel
 	 *  - 'might' have to copy address, load and jump to it
+	 * Flush all data from the L1 data cache before disabling
+	 * SCTLR.C bit.
 	 */
 	ldr	r1, kernel_flush
 	mov	lr, pc
 	bx	r1
 
+	/*
+	 * Clear the SCTLR.C bit to prevent further data cache
+	 * allocation. Clearing SCTLR.C would make all the data accesses
+	 * strongly ordered and would not hit the cache.
+	 */
+	mrc	p15, 0, r0, c1, c0, 0
+	bic	r0, r0, #(1 << 2)	@ Disable the C bit
+	mcr	p15, 0, r0, c1, c0, 0
+	isb
+
+	/*
+	 * Invalidate L1 data cache. Even though only invalidate is
+	 * necessary exported flush API is used here. Doing clean
+	 * on already clean cache would be almost NOP.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+	/*
+	 * The kernel doesn't interwork: v7_flush_dcache_all in particluar will
+	 * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
+	 * This sequence switches back to ARM.  Note that .align may insert a
+	 * nop: bx pc needs to be word-aligned in order to work.
+	 */
+ THUMB(	.thumb		)
+ THUMB(	.align		)
+ THUMB(	bx	pc	)
+ THUMB(	nop		)
+	.arm
+
 omap3_do_wfi:
 	ldr	r4, sdrc_power		@ read the SDRC_POWER register
 	ldr	r5, [r4]		@ read the contents of SDRC_POWER
@@ -289,9 +291,8 @@
 	str	r5, [r4]		@ write back to SDRC_POWER register
 
 	/* Data memory barrier and Data sync barrier */
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c10, 4
-	mcr	p15, 0, r1, c7, c10, 5
+	dsb
+	dmb
 
 /*
  * ===================================
@@ -317,6 +318,12 @@
 	nop
 	bl wait_sdrc_ok
 
+	mrc	p15, 0, r0, c1, c0, 0
+	tst	r0, #(1 << 2)		@ Check C bit enabled?
+	orreq	r0, r0, #(1 << 2)	@ Enable the C bit if cleared
+	mcreq	p15, 0, r0, c1, c0, 0
+	isb
+
 /*
  * ===================================
  * == Exit point from non-OFF modes ==
@@ -406,9 +413,9 @@
 	mov	r2, #4			@ set some flags in r2, r6
 	mov	r6, #0xff
 	adr	r3, l2_inv_api_params	@ r3 points to dummy parameters
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 	/* Write to Aux control register to set some bits */
 	mov	r0, #42			@ set service ID for PPA
 	mov	r12, r0			@ copy secure Service ID in r12
@@ -417,9 +424,9 @@
 	mov	r6, #0xff
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4, #0xBC]		@ r3 points to parameters
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 
 #ifdef CONFIG_OMAP3_L2_AUX_SECURE_SAVE_RESTORE
 	/* Restore L2 aux control register */
@@ -432,29 +439,30 @@
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4, #0xBC]
 	adds	r3, r3, #8		@ r3 points to parameters
-	mcr	p15, 0, r0, c7, c10, 4	@ data write barrier
-	mcr	p15, 0, r0, c7, c10, 5	@ data memory barrier
-	.word	0xE1600071		@ call SMI monitor (smi #1)
+	dsb				@ data write barrier
+	dmb				@ data memory barrier
+	smc	#1			@ call SMI monitor (smi #1)
 #endif
 	b	logic_l1_restore
 
+	.align
 l2_inv_api_params:
 	.word	0x1, 0x00
 l2_inv_gp:
 	/* Execute smi to invalidate L2 cache */
 	mov r12, #0x1			@ set up to invalidate L2
-	.word 0xE1600070		@ Call SMI monitor (smieq)
+	smc	#0			@ Call SMI monitor (smieq)
 	/* Write to Aux control register to set some bits */
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	ldr	r0, [r3,#4]
 	mov	r12, #0x3
-	.word	0xE1600070		@ Call SMI monitor (smieq)
+	smc	#0			@ Call SMI monitor (smieq)
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	ldr	r0, [r3,#12]
 	mov	r12, #0x2
-	.word	0xE1600070		@ Call SMI monitor (smieq)
+	smc	#0			@ Call SMI monitor (smieq)
 logic_l1_restore:
 	ldr	r1, l2dis_3630
 	cmp	r1, #0x1		@ Test if L2 re-enable needed on 3630
@@ -473,68 +481,29 @@
 	ldr	r4, scratchpad_base
 	ldr	r3, [r4,#0xBC]
 	adds	r3, r3, #16
-	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-r6}
+	mov	sp, r4			@ Restore sp
+	msr	spsr_cxsf, r5		@ Restore spsr
+	mov	lr, r6			@ Restore lr
 
-	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}
+	ldmia	r3!, {r4-r7}
+	mcr	p15, 0, r4, c1, c0, 2	@ Coprocessor access Control Register
+	mcr	p15, 0, r5, c2, c0, 0	@ TTBR0
+	mcr	p15, 0, r6, c2, c0, 1	@ TTBR1
+	mcr	p15, 0, r7, c2, c0, 2	@ TTBCR
 
-	/* 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-r6}
+	mcr	p15, 0, r4, c3, c0, 0	@ Domain access Control Register
+	mcr	p15, 0, r5, c10, c2, 0	@ PRRR
+	mcr	p15, 0, r6, c10, c2, 1	@ NMRR
 
-	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
+	ldmia	r3!,{r4-r7}
+	mcr	p15, 0, r4, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r5, c13, c0, 2	@ User r/w thread and process ID
+	mrc	p15, 0, r6, c12, c0, 0	@ Secure or NS vector base address
+	msr	cpsr, r7		@ store cpsr
 
 	/* Enabling MMU here */
 	mrc	p15, 0, r7, c2, c0, 2 	@ Read TTBRControl
@@ -592,12 +561,17 @@
 	ldr	r2, cache_pred_disable_mask
 	and	r4, r2
 	mcr	p15, 0, r4, c1, c0, 0
+	dsb
+	isb
+	ldr     r0, =restoremmu_on
+	bx      r0
 
 /*
  * ==============================
  * == Exit point from OFF mode ==
  * ==============================
  */
+restoremmu_on:
 	ldmfd	sp!, {r0-r12, pc}	@ restore regs and return
 
 
@@ -607,6 +581,7 @@
 
 /* This function implements the erratum ID i443 WA, applies to 34xx >= ES3.0 */
 	.text
+	.align	3
 ENTRY(es3_sdrc_fix)
 	ldr	r4, sdrc_syscfg		@ get config addr
 	ldr	r5, [r4]		@ get value
@@ -634,6 +609,7 @@
 	str	r5, [r4]		@ kick off refreshes
 	bx	lr
 
+	.align
 sdrc_syscfg:
 	.word	SDRC_SYSCONFIG_P
 sdrc_mr_0:
@@ -648,6 +624,7 @@
 	.word	SDRC_EMR2_1_P
 sdrc_manual_1:
 	.word	SDRC_MANUAL_1_P
+ENDPROC(es3_sdrc_fix)
 ENTRY(es3_sdrc_fix_sz)
 	.word	. - es3_sdrc_fix
 
@@ -682,6 +659,12 @@
 	bic	r5, r5, #0x40
 	str	r5, [r4]
 
+/*
+ * PC-relative stores lead to undefined behaviour in Thumb-2: use a r7 as a
+ * base instead.
+ * Be careful not to clobber r7 when maintaing this code.
+ */
+
 is_dll_in_lock_mode:
 	/* Is dll in lock mode? */
 	ldr	r4, sdrc_dlla_ctrl
@@ -689,10 +672,11 @@
 	tst	r5, #0x4
 	bxne	lr			@ Return if locked
 	/* wait till dll locks */
+	adr	r7, kick_counter
 wait_dll_lock_timed:
 	ldr	r4, wait_dll_lock_counter
 	add	r4, r4, #1
-	str	r4, wait_dll_lock_counter
+	str	r4, [r7, #wait_dll_lock_counter - kick_counter]
 	ldr	r4, sdrc_dlla_status
 	/* Wait 20uS for lock */
 	mov	r6, #8
@@ -718,9 +702,10 @@
 	dsb
 	ldr	r4, kick_counter
 	add	r4, r4, #1
-	str	r4, kick_counter
+	str	r4, [r7]		@ kick_counter
 	b	wait_dll_lock_timed
 
+	.align
 cm_idlest1_core:
 	.word	CM_IDLEST1_CORE_V
 cm_idlest_ckgen:
@@ -763,6 +748,7 @@
 	.word	0
 wait_dll_lock_counter:
 	.word	0
+ENDPROC(omap34xx_cpu_suspend)
 
 ENTRY(omap34xx_cpu_suspend_sz)
 	.word	. - omap34xx_cpu_suspend
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/smartreflex.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/smartreflex.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/smartreflex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/smartreflex.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,9 +26,9 @@
 #include <linux/pm_runtime.h>
 
 #include <plat/common.h>
-#include <plat/smartreflex.h>
 
 #include "pm.h"
+#include "smartreflex.h"
 
 #define SMARTREFLEX_NAME_LEN	16
 #define NVALUE_NAME_LEN		40
@@ -54,6 +54,7 @@
 	struct list_head		node;
 	struct omap_sr_nvalue_table	*nvalue_table;
 	struct voltagedomain		*voltdm;
+	struct dentry			*dbg_dir;
 };
 
 /* sr_list contains all the instances of smartreflex module */
@@ -246,7 +247,7 @@
  * driver register and sr device intializtion API's. Only one call
  * will ultimately succeed.
  *
- * Currenly this function registers interrrupt handler for a particular SR
+ * Currently this function registers interrrupt handler for a particular SR
  * if smartreflex class driver is already registered and has
  * requested for interrupts and the SR interrupt line in present.
  */
@@ -260,9 +261,11 @@
 	if (sr_class->class_type == SR_CLASS2 &&
 		sr_class->notify_flags && sr_info->irq) {
 
-		name = kzalloc(SMARTREFLEX_NAME_LEN + 1, GFP_KERNEL);
-		strcpy(name, "sr_");
-		strcat(name, sr_info->voltdm->name);
+		name = kasprintf(GFP_KERNEL, "sr_%s", sr_info->voltdm->name);
+		if (name == NULL) {
+			ret = -ENOMEM;
+			goto error;
+		}
 		ret = request_irq(sr_info->irq, sr_interrupt,
 				0, name, (void *)sr_info);
 		if (ret)
@@ -821,7 +824,7 @@
 	struct omap_sr *sr_info = kzalloc(sizeof(struct omap_sr), GFP_KERNEL);
 	struct omap_sr_data *pdata = pdev->dev.platform_data;
 	struct resource *mem, *irq;
-	struct dentry *vdd_dbg_dir, *dbg_dir, *nvalue_dir;
+	struct dentry *vdd_dbg_dir, *nvalue_dir;
 	struct omap_volt_data *volt_data;
 	int i, ret = 0;
 
@@ -896,24 +899,24 @@
 		goto err_release_region;
 	}
 
-	dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
-	if (IS_ERR(dbg_dir)) {
+	sr_info->dbg_dir = debugfs_create_dir("smartreflex", vdd_dbg_dir);
+	if (IS_ERR(sr_info->dbg_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory\n",
 			__func__);
-		ret = PTR_ERR(dbg_dir);
+		ret = PTR_ERR(sr_info->dbg_dir);
 		goto err_release_region;
 	}
 
-	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR, dbg_dir,
-				(void *)sr_info, &pm_sr_fops);
-	(void) debugfs_create_x32("errweight", S_IRUGO, dbg_dir,
+	(void) debugfs_create_file("autocomp", S_IRUGO | S_IWUSR,
+			sr_info->dbg_dir, (void *)sr_info, &pm_sr_fops);
+	(void) debugfs_create_x32("errweight", S_IRUGO, sr_info->dbg_dir,
 			&sr_info->err_weight);
-	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, dbg_dir,
+	(void) debugfs_create_x32("errmaxlimit", S_IRUGO, sr_info->dbg_dir,
 			&sr_info->err_maxlimit);
-	(void) debugfs_create_x32("errminlimit", S_IRUGO, dbg_dir,
+	(void) debugfs_create_x32("errminlimit", S_IRUGO, sr_info->dbg_dir,
 			&sr_info->err_minlimit);
 
-	nvalue_dir = debugfs_create_dir("nvalue", dbg_dir);
+	nvalue_dir = debugfs_create_dir("nvalue", sr_info->dbg_dir);
 	if (IS_ERR(nvalue_dir)) {
 		dev_err(&pdev->dev, "%s: Unable to create debugfs directory"
 			"for n-values\n", __func__);
@@ -970,6 +973,8 @@
 
 	if (sr_info->autocomp_active)
 		sr_stop_vddautocomp(sr_info);
+	if (sr_info->dbg_dir)
+		debugfs_remove_recursive(sr_info->dbg_dir);
 
 	list_del(&sr_info->node);
 	iounmap(sr_info->base);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/smartreflex-class3.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/smartreflex-class3.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/smartreflex-class3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/smartreflex-class3.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
  * published by the Free Software Foundation.
  */
 
-#include <plat/smartreflex.h>
+#include "smartreflex.h"
 
 static int sr_class3_enable(struct voltagedomain *voltdm)
 {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/smartreflex.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/smartreflex.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/smartreflex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/smartreflex.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,246 @@
+/*
+ * OMAP Smartreflex Defines and Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Lesly A M <x0080970@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_ARM_OMAP_SMARTREFLEX_H
+#define __ASM_ARM_OMAP_SMARTREFLEX_H
+
+#include <linux/platform_device.h>
+
+#include "voltage.h"
+
+/*
+ * Different Smartreflex IPs version. The v1 is the 65nm version used in
+ * OMAP3430. The v2 is the update for the 45nm version of the IP
+ * used in OMAP3630 and OMAP4430
+ */
+#define SR_TYPE_V1	1
+#define SR_TYPE_V2	2
+
+/* SMART REFLEX REG ADDRESS OFFSET */
+#define SRCONFIG		0x00
+#define SRSTATUS		0x04
+#define SENVAL			0x08
+#define SENMIN			0x0C
+#define SENMAX			0x10
+#define SENAVG			0x14
+#define AVGWEIGHT		0x18
+#define NVALUERECIPROCAL	0x1c
+#define SENERROR_V1		0x20
+#define ERRCONFIG_V1		0x24
+#define IRQ_EOI			0x20
+#define IRQSTATUS_RAW		0x24
+#define IRQSTATUS		0x28
+#define IRQENABLE_SET		0x2C
+#define IRQENABLE_CLR		0x30
+#define SENERROR_V2		0x34
+#define ERRCONFIG_V2		0x38
+
+/* Bit/Shift Positions */
+
+/* SRCONFIG */
+#define SRCONFIG_ACCUMDATA_SHIFT	22
+#define SRCONFIG_SRCLKLENGTH_SHIFT	12
+#define SRCONFIG_SENNENABLE_V1_SHIFT	5
+#define SRCONFIG_SENPENABLE_V1_SHIFT	3
+#define SRCONFIG_SENNENABLE_V2_SHIFT	1
+#define SRCONFIG_SENPENABLE_V2_SHIFT	0
+#define SRCONFIG_CLKCTRL_SHIFT		0
+
+#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
+
+#define SRCONFIG_SRENABLE		BIT(11)
+#define SRCONFIG_SENENABLE		BIT(10)
+#define SRCONFIG_ERRGEN_EN		BIT(9)
+#define SRCONFIG_MINMAXAVG_EN		BIT(8)
+#define SRCONFIG_DELAYCTRL		BIT(2)
+
+/* AVGWEIGHT */
+#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
+#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
+
+/* NVALUERECIPROCAL */
+#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
+#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
+#define NVALUERECIPROCAL_RNSENP_SHIFT	8
+#define NVALUERECIPROCAL_RNSENN_SHIFT	0
+
+/* ERRCONFIG */
+#define ERRCONFIG_ERRWEIGHT_SHIFT	16
+#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
+#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
+
+#define SR_ERRWEIGHT_MASK		(0x07 << 16)
+#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
+#define SR_ERRMINLIMIT_MASK		(0xff << 0)
+
+#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
+#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
+#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
+#define ERRCONFIG_MCUACCUMINTST		BIT(28)
+#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
+#define ERRCONFIG_MCUVALIDINTST		BIT(26)
+#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
+#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
+#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
+#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
+#define ERRCONFIG_MCUDISACKINTST	BIT(22)
+#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
+
+#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
+					ERRCONFIG_MCUACCUMINTST | \
+					ERRCONFIG_MCUVALIDINTST | \
+					ERRCONFIG_MCUBOUNDINTST | \
+					ERRCONFIG_MCUDISACKINTST)
+/* IRQSTATUS */
+#define IRQSTATUS_MCUACCUMINT		BIT(3)
+#define IRQSTATUS_MCVALIDINT		BIT(2)
+#define IRQSTATUS_MCBOUNDSINT		BIT(1)
+#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
+
+/* IRQENABLE_SET and IRQENABLE_CLEAR */
+#define IRQENABLE_MCUACCUMINT		BIT(3)
+#define IRQENABLE_MCUVALIDINT		BIT(2)
+#define IRQENABLE_MCUBOUNDSINT		BIT(1)
+#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
+
+/* Common Bit values */
+
+#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
+#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
+#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
+#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
+#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
+
+/*
+ * 3430 specific values. Maybe these should be passed from board file or
+ * pmic structures.
+ */
+#define OMAP3430_SR_ACCUMDATA		0x1f4
+
+#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
+#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
+
+#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
+#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
+
+#define OMAP3430_SR_ERRWEIGHT		0x04
+#define OMAP3430_SR_ERRMAXLIMIT		0x02
+
+/**
+ * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
+ *				pmic specific info to smartreflex driver
+ *
+ * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
+ */
+struct omap_sr_pmic_data {
+	void (*sr_pmic_init) (void);
+};
+
+#ifdef CONFIG_OMAP_SMARTREFLEX
+/*
+ * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
+ * The smartreflex class driver should pass the class type.
+ * Should be used to populate the class_type field of the
+ * omap_smartreflex_class_data structure.
+ */
+#define SR_CLASS1	0x1
+#define SR_CLASS2	0x2
+#define SR_CLASS3	0x3
+
+/**
+ * struct omap_sr_class_data - Smartreflex class driver info
+ *
+ * @enable:		API to enable a particular class smaartreflex.
+ * @disable:		API to disable a particular class smartreflex.
+ * @configure:		API to configure a particular class smartreflex.
+ * @notify:		API to notify the class driver about an event in SR.
+ *			Not needed for class3.
+ * @notify_flags:	specify the events to be notified to the class driver
+ * @class_type:		specify which smartreflex class.
+ *			Can be used by the SR driver to take any class
+ *			based decisions.
+ */
+struct omap_sr_class_data {
+	int (*enable)(struct voltagedomain *voltdm);
+	int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
+	int (*configure)(struct voltagedomain *voltdm);
+	int (*notify)(struct voltagedomain *voltdm, u32 status);
+	u8 notify_flags;
+	u8 class_type;
+};
+
+/**
+ * struct omap_sr_nvalue_table	- Smartreflex n-target value info
+ *
+ * @efuse_offs:	The offset of the efuse where n-target values are stored.
+ * @nvalue:	The n-target value.
+ */
+struct omap_sr_nvalue_table {
+	u32 efuse_offs;
+	u32 nvalue;
+};
+
+/**
+ * struct omap_sr_data - Smartreflex platform data.
+ *
+ * @ip_type:		Smartreflex IP type.
+ * @senp_mod:		SENPENABLE value for the sr
+ * @senn_mod:		SENNENABLE value for sr
+ * @nvalue_count:	Number of distinct nvalues in the nvalue table
+ * @enable_on_init:	whether this sr module needs to enabled at
+ *			boot up or not.
+ * @nvalue_table:	table containing the  efuse offsets and nvalues
+ *			corresponding to them.
+ * @voltdm:		Pointer to the voltage domain associated with the SR
+ */
+struct omap_sr_data {
+	int				ip_type;
+	u32				senp_mod;
+	u32				senn_mod;
+	int				nvalue_count;
+	bool				enable_on_init;
+	struct omap_sr_nvalue_table	*nvalue_table;
+	struct voltagedomain		*voltdm;
+};
+
+/* Smartreflex module enable/disable interface */
+void omap_sr_enable(struct voltagedomain *voltdm);
+void omap_sr_disable(struct voltagedomain *voltdm);
+void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
+
+/* API to register the pmic specific data with the smartreflex driver. */
+void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
+
+/* Smartreflex driver hooks to be called from Smartreflex class driver */
+int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
+void sr_disable(struct voltagedomain *voltdm);
+int sr_configure_errgen(struct voltagedomain *voltdm);
+int sr_configure_minmax(struct voltagedomain *voltdm);
+
+/* API to register the smartreflex class driver with the smartreflex driver */
+int sr_register_class(struct omap_sr_class_data *class_data);
+#else
+static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
+static inline void omap_sr_disable_reset_volt(
+		struct voltagedomain *voltdm) {}
+static inline void omap_sr_register_pmic(
+		struct omap_sr_pmic_data *pmic_data) {}
+#endif
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sram242x.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sram242x.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sram242x.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sram242x.S	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 
 	.text
 
+	.align	3
 ENTRY(omap242x_sram_ddr_init)
 	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
 
@@ -143,6 +144,7 @@
  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
  */
+	.align	3
 ENTRY(omap242x_sram_reprogram_sdrc)
 	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
 	mov	r3, #0x0		@ clear for mrc call
@@ -238,6 +240,7 @@
 /*
  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
  */
+	.align	3
 ENTRY(omap242x_sram_set_prcm)
 	stmfd	sp!, {r0-r12, lr}	@ regs to stack
 	adr	r4, pbegin		@ addr of preload start
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sram243x.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sram243x.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sram243x.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sram243x.S	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 
 	.text
 
+	.align	3
 ENTRY(omap243x_sram_ddr_init)
 	stmfd	sp!, {r0 - r12, lr}	@ save registers on stack
 
@@ -143,6 +144,7 @@
  * r0 = [PRCM_FULL | PRCM_HALF] r1 = SDRC_DLLA_CTRL value r2 = [DDR | SDR]
  * PRCM_FULL = 2, PRCM_HALF = 1, DDR = 1, SDR = 0
  */
+	.align	3
 ENTRY(omap243x_sram_reprogram_sdrc)
 	stmfd	sp!, {r0 - r10, lr}	@ save registers on stack
 	mov	r3, #0x0		@ clear for mrc call
@@ -238,6 +240,7 @@
 /*
  * Set dividers and pll. Also recalculate DLL value for DDR and unlock mode.
  */
+	.align	3
 ENTRY(omap243x_sram_set_prcm)
 	stmfd	sp!, {r0-r12, lr}	@ regs to stack
 	adr	r4, pbegin		@ addr of preload start
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sram34xx.S linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sram34xx.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sram34xx.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sram34xx.S	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,12 @@
 #include "sdrc.h"
 #include "cm2xxx_3xxx.h"
 
+/*
+ * This file needs be built unconditionally as ARM to interoperate correctly
+ * with non-Thumb-2-capable firmware.
+ */
+	.arm
+
 	.text
 
 /* r1 parameters */
@@ -111,29 +117,42 @@
  * since it will cause the ARM MMU to attempt to walk the page tables.
  * These crashes may be intermittent.
  */
+	.align	3
 ENTRY(omap3_sram_configure_core_dpll)
 	stmfd	sp!, {r1-r12, lr}	@ store regs to stack
 
 					@ pull the extra args off the stack
 					@  and store them in SRAM
+
+/*
+ * PC-relative stores are deprecated in ARMv7 and lead to undefined behaviour
+ * in Thumb-2: use a r7 as a base instead.
+ * Be careful not to clobber r7 when maintaing this file.
+ */
+ THUMB(	adr	r7, omap3_sram_configure_core_dpll			)
+	.macro strtext Rt:req, label:req
+ ARM(	str	\Rt, \label						)
+ THUMB(	str	\Rt, [r7, \label - omap3_sram_configure_core_dpll]	)
+	.endm
+
 	ldr	r4, [sp, #52]
-	str     r4, omap_sdrc_rfr_ctrl_0_val
+	strtext	r4, omap_sdrc_rfr_ctrl_0_val
 	ldr	r4, [sp, #56]
-	str     r4, omap_sdrc_actim_ctrl_a_0_val
+	strtext	r4, omap_sdrc_actim_ctrl_a_0_val
 	ldr	r4, [sp, #60]
-	str     r4, omap_sdrc_actim_ctrl_b_0_val
+	strtext	r4, omap_sdrc_actim_ctrl_b_0_val
 	ldr	r4, [sp, #64]
-	str     r4, omap_sdrc_mr_0_val
+	strtext	r4, omap_sdrc_mr_0_val
 	ldr	r4, [sp, #68]
-	str     r4, omap_sdrc_rfr_ctrl_1_val
+	strtext	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
+	strtext	r4, omap_sdrc_actim_ctrl_a_1_val
 	ldr	r4, [sp, #76]
-	str     r4, omap_sdrc_actim_ctrl_b_1_val
+	strtext	r4, omap_sdrc_actim_ctrl_b_1_val
 	ldr	r4, [sp, #80]
-	str     r4, omap_sdrc_mr_1_val
+	strtext	r4, omap_sdrc_mr_1_val
 skip_cs1_params:
 	mrc	p15, 0, r8, c1, c0, 0	@ read ctrl register
 	bic	r10, r8, #0x800		@ clear Z-bit, disable branch prediction
@@ -271,6 +290,7 @@
 	ldr	r12, [r11]		@ posted-write barrier for SDRC
 	bx	lr
 
+	.align
 omap3_sdrc_power:
 	.word OMAP34XX_SDRC_REGADDR(SDRC_POWER)
 omap3_cm_clksel1_pll:
@@ -319,6 +339,7 @@
 	.word OMAP34XX_SDRC_REGADDR(SDRC_DLLA_CTRL)
 core_m2_mask_val:
 	.word 0x07FFFFFF
+ENDPROC(omap3_sram_configure_core_dpll)
 
 ENTRY(omap3_sram_configure_core_dpll_sz)
 	.word	. - omap3_sram_configure_core_dpll
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sr_device.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sr_device.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/sr_device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/sr_device.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,9 +23,9 @@
 #include <linux/io.h>
 
 #include <plat/omap_device.h>
-#include <plat/smartreflex.h>
-#include <plat/voltage.h>
 
+#include "smartreflex.h"
+#include "voltage.h"
 #include "control.h"
 #include "pm.h"
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/timer-gp.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/timer-gp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/timer-gp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/timer-gp.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,10 +40,11 @@
 #include <plat/dmtimer.h>
 #include <asm/localtimer.h>
 #include <asm/sched_clock.h>
+#include <plat/common.h>
+#include <plat/omap_hwmod.h>
 
 #include "timer-gp.h"
 
-#include <plat/common.h>
 
 /* MAX_GPTIMER_ID: number of GPTIMERs on the chip */
 #define MAX_GPTIMER_ID		12
@@ -133,9 +134,13 @@
 {
 	u32 tick_rate;
 	int src;
+	char clockevent_hwmod_name[8]; /* 8 = sizeof("timerXX0") */
 
 	inited = 1;
 
+	sprintf(clockevent_hwmod_name, "timer%d", gptimer_id);
+	omap_hwmod_setup_one(clockevent_hwmod_name);
+
 	gptimer = omap_dm_timer_request_specific(gptimer_id);
 	BUG_ON(gptimer == NULL);
 	gptimer_wakeup = gptimer;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/timer-mpu.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/timer-mpu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/timer-mpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/timer-mpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,9 +26,14 @@
 /*
  * Setup the local clock events for a CPU.
  */
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
+	/* Local timers are not supprted on OMAP4430 ES1.0 */
+	if (omap_rev() == OMAP4430_REV_ES1_0)
+		return -ENXIO;
+
 	evt->irq = OMAP44XX_IRQ_LOCALTIMER;
 	twd_timer_setup(evt);
+	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/usb-ehci.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/usb-ehci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/usb-ehci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/usb-ehci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,522 +0,0 @@
-/*
- * linux/arch/arm/mach-omap2/usb-ehci.c
- *
- * This file will contain the board specific details for the
- * Synopsys EHCI host controller on OMAP3430
- *
- * Copyright (C) 2007 Texas Instruments
- * Author: Vikram Pandita <vikram.pandita@ti.com>
- *
- * Generalization 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 version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/types.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/platform_device.h>
-#include <linux/clk.h>
-#include <linux/dma-mapping.h>
-
-#include <asm/io.h>
-
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <plat/usb.h>
-
-#include "mux.h"
-
-#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_EHCI_HCD_MODULE)
-
-static struct resource ehci_resources[] = {
-	{
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.flags	= IORESOURCE_MEM,
-	},
-	{         /* general IRQ */
-		.flags   = IORESOURCE_IRQ,
-	}
-};
-
-static u64 ehci_dmamask = ~(u32)0;
-static struct platform_device ehci_device = {
-	.name           = "ehci-omap",
-	.id             = 0,
-	.dev = {
-		.dma_mask               = &ehci_dmamask,
-		.coherent_dma_mask      = 0xffffffff,
-		.platform_data          = NULL,
-	},
-	.num_resources  = ARRAY_SIZE(ehci_resources),
-	.resource       = ehci_resources,
-};
-
-/* MUX settings for EHCI pins */
-/*
- * setup_ehci_io_mux - initialize IO pad mux for USBHOST
- */
-static void setup_ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("hsusb1_stp", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb1_clk", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb1_dir", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_nxt", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data0", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data1", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data2", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data3", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data4", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data5", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data6", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_data7", OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("hsusb1_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb1_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb1_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	switch (port_mode[1]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("hsusb2_stp", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb2_clk", OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("hsusb2_dir", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_nxt", OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("hsusb2_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb2_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb2_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	switch (port_mode[2]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		printk(KERN_WARNING "Port3 can't be used in PHY mode\n");
-		break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("hsusb3_tll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("hsusb3_tll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("hsusb3_tll_data7",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-
-	return;
-}
-
-static void setup_4430ehci_io_mux(const enum ehci_hcd_omap_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("usbb1_ulpiphy_stp",
-			OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("usbb1_ulpiphy_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpiphy_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("usbb1_ulpitll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("usbb1_ulpitll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb1_ulpitll_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-	default:
-			break;
-	}
-	switch (port_mode[1]) {
-	case EHCI_HCD_OMAP_MODE_PHY:
-		omap_mux_init_signal("usbb2_ulpiphy_stp",
-			OMAP_PIN_OUTPUT);
-		omap_mux_init_signal("usbb2_ulpiphy_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpiphy_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_TLL:
-		omap_mux_init_signal("usbb2_ulpitll_stp",
-			OMAP_PIN_INPUT_PULLUP);
-		omap_mux_init_signal("usbb2_ulpitll_clk",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dir",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_nxt",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat1",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat2",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat3",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat4",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat5",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat6",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("usbb2_ulpitll_dat7",
-			OMAP_PIN_INPUT_PULLDOWN);
-			break;
-	case EHCI_HCD_OMAP_MODE_UNKNOWN:
-	default:
-			break;
-	}
-}
-
-void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
-{
-	platform_device_add_data(&ehci_device, pdata, sizeof(*pdata));
-
-	/* Setup Pin IO MUX for EHCI */
-	if (cpu_is_omap34xx()) {
-		ehci_resources[0].start	= OMAP34XX_EHCI_BASE;
-		ehci_resources[0].end	= OMAP34XX_EHCI_BASE + SZ_1K - 1;
-		ehci_resources[1].start	= OMAP34XX_UHH_CONFIG_BASE;
-		ehci_resources[1].end	= OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
-		ehci_resources[2].start	= OMAP34XX_USBTLL_BASE;
-		ehci_resources[2].end	= OMAP34XX_USBTLL_BASE + SZ_4K - 1;
-		ehci_resources[3].start = INT_34XX_EHCI_IRQ;
-		setup_ehci_io_mux(pdata->port_mode);
-	} else if (cpu_is_omap44xx()) {
-		ehci_resources[0].start	= OMAP44XX_HSUSB_EHCI_BASE;
-		ehci_resources[0].end	= OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
-		ehci_resources[1].start	= OMAP44XX_UHH_CONFIG_BASE;
-		ehci_resources[1].end	= OMAP44XX_UHH_CONFIG_BASE + SZ_2K - 1;
-		ehci_resources[2].start	= OMAP44XX_USBTLL_BASE;
-		ehci_resources[2].end	= OMAP44XX_USBTLL_BASE + SZ_4K - 1;
-		ehci_resources[3].start = OMAP44XX_IRQ_EHCI;
-		setup_4430ehci_io_mux(pdata->port_mode);
-	}
-
-	if (platform_device_register(&ehci_device) < 0) {
-		printk(KERN_ERR "Unable to register HS-USB (EHCI) device\n");
-		return;
-	}
-}
-
-#else
-
-void __init usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata)
-
-{
-}
-
-#endif /* CONFIG_USB_EHCI_HCD */
-
-#if defined(CONFIG_USB_OHCI_HCD) || defined(CONFIG_USB_OHCI_HCD_MODULE)
-
-static struct resource ohci_resources[] = {
-	{
-		.start	= OMAP34XX_OHCI_BASE,
-		.end	= OMAP34XX_OHCI_BASE + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= OMAP34XX_UHH_CONFIG_BASE,
-		.end	= OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{
-		.start	= OMAP34XX_USBTLL_BASE,
-		.end	= OMAP34XX_USBTLL_BASE + SZ_4K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	{	/* general IRQ */
-		.start	= INT_34XX_OHCI_IRQ,
-		.flags	= IORESOURCE_IRQ,
-	}
-};
-
-static u64 ohci_dmamask = DMA_BIT_MASK(32);
-
-static struct platform_device ohci_device = {
-	.name		= "ohci-omap3",
-	.id		= 0,
-	.dev = {
-		.dma_mask		= &ohci_dmamask,
-		.coherent_dma_mask	= 0xffffffff,
-	},
-	.num_resources	= ARRAY_SIZE(ohci_resources),
-	.resource	= ohci_resources,
-};
-
-static void setup_ohci_io_mux(const enum ohci_omap3_port_mode *port_mode)
-{
-	switch (port_mode[0]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm1_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm1_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm1_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm1_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm1_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm1_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	switch (port_mode[1]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm2_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm2_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm2_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm2_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm2_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm2_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-	switch (port_mode[2]) {
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
-		omap_mux_init_signal("mm3_rxdp",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm3_rxdm",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
-	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
-		omap_mux_init_signal("mm3_rxrcv",
-			OMAP_PIN_INPUT_PULLDOWN);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
-		omap_mux_init_signal("mm3_txen_n", OMAP_PIN_OUTPUT);
-		/* FALLTHROUGH */
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
-	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
-		omap_mux_init_signal("mm3_txse0",
-			OMAP_PIN_INPUT_PULLDOWN);
-		omap_mux_init_signal("mm3_txdat",
-			OMAP_PIN_INPUT_PULLDOWN);
-		break;
-	case OMAP_OHCI_PORT_MODE_UNUSED:
-		/* FALLTHROUGH */
-	default:
-		break;
-	}
-}
-
-void __init usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata)
-{
-	platform_device_add_data(&ohci_device, pdata, sizeof(*pdata));
-
-	/* Setup Pin IO MUX for OHCI */
-	if (cpu_is_omap34xx())
-		setup_ohci_io_mux(pdata->port_mode);
-
-	if (platform_device_register(&ohci_device) < 0) {
-		pr_err("Unable to register FS-USB (OHCI) device\n");
-		return;
-	}
-}
-
-#else
-
-void __init usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata)
-{
-}
-
-#endif /* CONFIG_USB_OHCI_HCD */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/usb-host.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/usb-host.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/usb-host.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/usb-host.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,574 @@
+/*
+ * usb-host.c - OMAP USB Host
+ *
+ * This file will contain the board specific details for the
+ * Synopsys EHCI/OHCI host controller on OMAP3430 and onwards
+ *
+ * Copyright (C) 2007-2011 Texas Instruments
+ * Author: Vikram Pandita <vikram.pandita@ti.com>
+ * Author: Keshava Munegowda <keshava_mgowda@ti.com>
+ *
+ * Generalization by:
+ * Felipe Balbi <balbi@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/types.h>
+#include <linux/errno.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/io.h>
+
+#include <mach/hardware.h>
+#include <mach/irqs.h>
+#include <plat/usb.h>
+
+#include "mux.h"
+
+#ifdef CONFIG_MFD_OMAP_USB_HOST
+
+#define OMAP_USBHS_DEVICE	"usbhs-omap"
+
+static struct resource usbhs_resources[] = {
+	{
+		.name	= "uhh",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "tll",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "ehci",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "ehci-irq",
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.name	= "ohci",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.name	= "ohci-irq",
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_device usbhs_device = {
+	.name		= OMAP_USBHS_DEVICE,
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(usbhs_resources),
+	.resource	= usbhs_resources,
+};
+
+static struct usbhs_omap_platform_data		usbhs_data;
+static struct ehci_hcd_omap_platform_data	ehci_data;
+static struct ohci_hcd_omap_platform_data	ohci_data;
+
+/* MUX settings for EHCI pins */
+/*
+ * setup_ehci_io_mux - initialize IO pad mux for USBHOST
+ */
+static void setup_ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("hsusb1_stp", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb1_clk", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb1_dir", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_nxt", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data0", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data1", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data2", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data3", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data4", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data5", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data6", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_data7", OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("hsusb1_tll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("hsusb1_tll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb1_tll_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	switch (port_mode[1]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("hsusb2_stp", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb2_clk", OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("hsusb2_dir", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_nxt", OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("hsusb2_tll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("hsusb2_tll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb2_tll_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	switch (port_mode[2]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		printk(KERN_WARNING "Port3 can't be used in PHY mode\n");
+		break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("hsusb3_tll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("hsusb3_tll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("hsusb3_tll_data7",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+
+	return;
+}
+
+static void setup_4430ehci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("usbb1_ulpiphy_stp",
+			OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("usbb1_ulpiphy_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpiphy_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("usbb1_ulpitll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("usbb1_ulpitll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_ulpitll_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+			break;
+	}
+	switch (port_mode[1]) {
+	case OMAP_EHCI_PORT_MODE_PHY:
+		omap_mux_init_signal("usbb2_ulpiphy_stp",
+			OMAP_PIN_OUTPUT);
+		omap_mux_init_signal("usbb2_ulpiphy_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpiphy_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_EHCI_PORT_MODE_TLL:
+		omap_mux_init_signal("usbb2_ulpitll_stp",
+			OMAP_PIN_INPUT_PULLUP);
+		omap_mux_init_signal("usbb2_ulpitll_clk",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dir",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_nxt",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat1",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat2",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat3",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat4",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat5",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat6",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_ulpitll_dat7",
+			OMAP_PIN_INPUT_PULLDOWN);
+			break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+			break;
+	}
+}
+
+static void setup_ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("mm1_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm1_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("mm1_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("mm1_txen_n", OMAP_PIN_OUTPUT);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("mm1_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm1_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+	switch (port_mode[1]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("mm2_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm2_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("mm2_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("mm2_txen_n", OMAP_PIN_OUTPUT);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("mm2_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm2_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+	switch (port_mode[2]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("mm3_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm3_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("mm3_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("mm3_txen_n", OMAP_PIN_OUTPUT);
+		/* FALLTHROUGH */
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("mm3_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("mm3_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+		/* FALLTHROUGH */
+	default:
+		break;
+	}
+}
+
+static void setup_4430ohci_io_mux(const enum usbhs_omap_port_mode *port_mode)
+{
+	switch (port_mode[0]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("usbb1_mm_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_mm_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("usbb1_mm_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("usbb1_mm_txen",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("usbb1_mm_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb1_mm_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+		break;
+	}
+
+	switch (port_mode[1]) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		omap_mux_init_signal("usbb2_mm_rxdp",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_mm_rxdm",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		omap_mux_init_signal("usbb2_mm_rxrcv",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		omap_mux_init_signal("usbb2_mm_txen",
+			OMAP_PIN_INPUT_PULLDOWN);
+
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		omap_mux_init_signal("usbb2_mm_txdat",
+			OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usbb2_mm_txse0",
+			OMAP_PIN_INPUT_PULLDOWN);
+		break;
+
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	default:
+		break;
+	}
+}
+
+void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
+{
+	int	i;
+
+	for (i = 0; i < OMAP3_HS_USB_PORTS; i++) {
+		usbhs_data.port_mode[i] = pdata->port_mode[i];
+		ohci_data.port_mode[i] = pdata->port_mode[i];
+		ehci_data.port_mode[i] = pdata->port_mode[i];
+		ehci_data.reset_gpio_port[i] = pdata->reset_gpio_port[i];
+		ehci_data.regulator[i] = pdata->regulator[i];
+	}
+	ehci_data.phy_reset = pdata->phy_reset;
+	ohci_data.es2_compatibility = pdata->es2_compatibility;
+	usbhs_data.ehci_data = &ehci_data;
+	usbhs_data.ohci_data = &ohci_data;
+
+	if (cpu_is_omap34xx()) {
+		usbhs_resources[0].start = OMAP34XX_UHH_CONFIG_BASE;
+		usbhs_resources[0].end = OMAP34XX_UHH_CONFIG_BASE + SZ_1K - 1;
+		usbhs_resources[1].start = OMAP34XX_USBTLL_BASE;
+		usbhs_resources[1].end = OMAP34XX_USBTLL_BASE + SZ_4K - 1;
+		usbhs_resources[2].start	= OMAP34XX_EHCI_BASE;
+		usbhs_resources[2].end	= OMAP34XX_EHCI_BASE + SZ_1K - 1;
+		usbhs_resources[3].start = INT_34XX_EHCI_IRQ;
+		usbhs_resources[4].start	= OMAP34XX_OHCI_BASE;
+		usbhs_resources[4].end	= OMAP34XX_OHCI_BASE + SZ_1K - 1;
+		usbhs_resources[5].start = INT_34XX_OHCI_IRQ;
+		setup_ehci_io_mux(pdata->port_mode);
+		setup_ohci_io_mux(pdata->port_mode);
+	} else if (cpu_is_omap44xx()) {
+		usbhs_resources[0].start = OMAP44XX_UHH_CONFIG_BASE;
+		usbhs_resources[0].end = OMAP44XX_UHH_CONFIG_BASE + SZ_1K - 1;
+		usbhs_resources[1].start = OMAP44XX_USBTLL_BASE;
+		usbhs_resources[1].end = OMAP44XX_USBTLL_BASE + SZ_4K - 1;
+		usbhs_resources[2].start = OMAP44XX_HSUSB_EHCI_BASE;
+		usbhs_resources[2].end = OMAP44XX_HSUSB_EHCI_BASE + SZ_1K - 1;
+		usbhs_resources[3].start = OMAP44XX_IRQ_EHCI;
+		usbhs_resources[4].start = OMAP44XX_HSUSB_OHCI_BASE;
+		usbhs_resources[4].end = OMAP44XX_HSUSB_OHCI_BASE + SZ_1K - 1;
+		usbhs_resources[5].start = OMAP44XX_IRQ_OHCI;
+		setup_4430ehci_io_mux(pdata->port_mode);
+		setup_4430ohci_io_mux(pdata->port_mode);
+	}
+
+	if (platform_device_add_data(&usbhs_device,
+				&usbhs_data, sizeof(usbhs_data)) < 0) {
+		printk(KERN_ERR "USBHS platform_device_add_data failed\n");
+		goto init_end;
+	}
+
+	if (platform_device_register(&usbhs_device) < 0)
+		printk(KERN_ERR "USBHS platform_device_register failed\n");
+
+init_end:
+	return;
+}
+
+#else
+
+void __init usbhs_init(const struct usbhs_omap_board_data *pdata)
+{
+}
+
+#endif
+
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/usb-musb.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/usb-musb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/usb-musb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/usb-musb.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,118 +30,11 @@
 #include <mach/irqs.h>
 #include <mach/am35xx.h>
 #include <plat/usb.h>
-#include "control.h"
+#include <plat/omap_device.h>
+#include "mux.h"
 
 #if defined(CONFIG_USB_MUSB_OMAP2PLUS) || defined (CONFIG_USB_MUSB_AM35X)
 
-static void am35x_musb_reset(void)
-{
-	u32	regval;
-
-	/* Reset the musb interface */
-	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-
-	regval |= AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
-
-	regval &= ~AM35XX_USBOTGSS_SW_RST;
-	omap_ctrl_writel(regval, AM35XX_CONTROL_IP_SW_RESET);
-
-	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
-}
-
-static void am35x_musb_phy_power(u8 on)
-{
-	unsigned long timeout = jiffies + msecs_to_jiffies(100);
-	u32 devconf2;
-
-	if (on) {
-		/*
-		 * Start the on-chip PHY and its PLL.
-		 */
-		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-		devconf2 &= ~(CONF2_RESET | CONF2_PHYPWRDN | CONF2_OTGPWRDN);
-		devconf2 |= CONF2_PHY_PLLON;
-
-		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-
-		pr_info(KERN_INFO "Waiting for PHY clock good...\n");
-		while (!(omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2)
-				& CONF2_PHYCLKGD)) {
-			cpu_relax();
-
-			if (time_after(jiffies, timeout)) {
-				pr_err(KERN_ERR "musb PHY clock good timed out\n");
-				break;
-			}
-		}
-	} else {
-		/*
-		 * Power down the on-chip PHY.
-		 */
-		devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-		devconf2 &= ~CONF2_PHY_PLLON;
-		devconf2 |=  CONF2_PHYPWRDN | CONF2_OTGPWRDN;
-		omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-	}
-}
-
-static void am35x_musb_clear_irq(void)
-{
-	u32 regval;
-
-	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-	regval |= AM35XX_USBOTGSS_INT_CLR;
-	omap_ctrl_writel(regval, AM35XX_CONTROL_LVL_INTR_CLEAR);
-	regval = omap_ctrl_readl(AM35XX_CONTROL_LVL_INTR_CLEAR);
-}
-
-static void am35x_musb_set_mode(u8 musb_mode)
-{
-	u32 devconf2 = omap_ctrl_readl(AM35XX_CONTROL_DEVCONF2);
-
-	devconf2 &= ~CONF2_OTGMODE;
-	switch (musb_mode) {
-#ifdef	CONFIG_USB_MUSB_HDRC_HCD
-	case MUSB_HOST:		/* Force VBUS valid, ID = 0 */
-		devconf2 |= CONF2_FORCE_HOST;
-		break;
-#endif
-#ifdef	CONFIG_USB_GADGET_MUSB_HDRC
-	case MUSB_PERIPHERAL:	/* Force VBUS valid, ID = 1 */
-		devconf2 |= CONF2_FORCE_DEVICE;
-		break;
-#endif
-#ifdef	CONFIG_USB_MUSB_OTG
-	case MUSB_OTG:		/* Don't override the VBUS/ID comparators */
-		devconf2 |= CONF2_NO_OVERRIDE;
-		break;
-#endif
-	default:
-		pr_info(KERN_INFO "Unsupported mode %u\n", musb_mode);
-	}
-
-	omap_ctrl_writel(devconf2, AM35XX_CONTROL_DEVCONF2);
-}
-
-static struct resource musb_resources[] = {
-	[0] = { /* start and end set dynamically */
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {	/* general IRQ */
-		.start	= INT_243X_HS_USB_MC,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "mc",
-	},
-	[2] = {	/* DMA IRQ */
-		.start	= INT_243X_HS_USB_DMA,
-		.flags	= IORESOURCE_IRQ,
-		.name	= "dma",
-	},
-};
-
 static struct musb_hdrc_config musb_config = {
 	.multipoint	= 1,
 	.dyn_fifo	= 1,
@@ -169,38 +62,65 @@
 
 static u64 musb_dmamask = DMA_BIT_MASK(32);
 
-static struct platform_device musb_device = {
-	.name		= "musb-omap2430",
-	.id		= -1,
-	.dev = {
-		.dma_mask		= &musb_dmamask,
-		.coherent_dma_mask	= DMA_BIT_MASK(32),
-		.platform_data		= &musb_plat,
+static struct omap_device_pm_latency omap_musb_latency[] = {
+	{
+		.deactivate_func	= omap_device_idle_hwmods,
+		.activate_func		= omap_device_enable_hwmods,
+		.flags			= OMAP_DEVICE_LATENCY_AUTO_ADJUST,
 	},
-	.num_resources	= ARRAY_SIZE(musb_resources),
-	.resource	= musb_resources,
 };
 
+static void usb_musb_mux_init(struct omap_musb_board_data *board_data)
+{
+	switch (board_data->interface_type) {
+	case MUSB_INTERFACE_UTMI:
+		omap_mux_init_signal("usba0_otg_dp", OMAP_PIN_INPUT);
+		omap_mux_init_signal("usba0_otg_dm", OMAP_PIN_INPUT);
+		break;
+	case MUSB_INTERFACE_ULPI:
+		omap_mux_init_signal("usba0_ulpiphy_clk",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_stp",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dir",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_nxt",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat0",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat1",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat2",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat3",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat4",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat5",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat6",
+						OMAP_PIN_INPUT_PULLDOWN);
+		omap_mux_init_signal("usba0_ulpiphy_dat7",
+						OMAP_PIN_INPUT_PULLDOWN);
+		break;
+	default:
+		break;
+	}
+}
+
 void __init usb_musb_init(struct omap_musb_board_data *board_data)
 {
-	if (cpu_is_omap243x()) {
-		musb_resources[0].start = OMAP243X_HS_BASE;
-	} else if (cpu_is_omap3517() || cpu_is_omap3505()) {
-		musb_device.name = "musb-am35x";
-		musb_resources[0].start = AM35XX_IPSS_USBOTGSS_BASE;
-		musb_resources[1].start = INT_35XX_USBOTG_IRQ;
-		board_data->set_phy_power = am35x_musb_phy_power;
-		board_data->clear_irq = am35x_musb_clear_irq;
-		board_data->set_mode = am35x_musb_set_mode;
-		board_data->reset = am35x_musb_reset;
-	} else if (cpu_is_omap34xx()) {
-		musb_resources[0].start = OMAP34XX_HSUSB_OTG_BASE;
+	struct omap_hwmod		*oh;
+	struct omap_device		*od;
+	struct platform_device		*pdev;
+	struct device			*dev;
+	int				bus_id = -1;
+	const char			*oh_name, *name;
+
+	if (cpu_is_omap3517() || cpu_is_omap3505()) {
 	} else if (cpu_is_omap44xx()) {
-		musb_resources[0].start = OMAP44XX_HSUSB_OTG_BASE;
-		musb_resources[1].start = OMAP44XX_IRQ_HS_USB_MC_N;
-		musb_resources[2].start = OMAP44XX_IRQ_HS_USB_DMA_N;
+		usb_musb_mux_init(board_data);
 	}
-	musb_resources[0].end = musb_resources[0].start + SZ_4K - 1;
 
 	/*
 	 * REVISIT: This line can be removed once all the platforms using
@@ -212,8 +132,38 @@
 	musb_plat.mode = board_data->mode;
 	musb_plat.extvbus = board_data->extvbus;
 
-	if (platform_device_register(&musb_device) < 0)
-		printk(KERN_ERR "Unable to register HS-USB (MUSB) device\n");
+	if (cpu_is_omap44xx())
+		omap4430_phy_init(dev);
+
+	if (cpu_is_omap3517() || cpu_is_omap3505()) {
+		oh_name = "am35x_otg_hs";
+		name = "musb-am35x";
+	} else {
+		oh_name = "usb_otg_hs";
+		name = "musb-omap2430";
+	}
+
+	oh = omap_hwmod_lookup(oh_name);
+	if (!oh) {
+		pr_err("Could not look up %s\n", oh_name);
+		return;
+	}
+
+	od = omap_device_build(name, bus_id, oh, &musb_plat,
+			       sizeof(musb_plat), omap_musb_latency,
+			       ARRAY_SIZE(omap_musb_latency), false);
+	if (IS_ERR(od)) {
+		pr_err("Could not build omap_device for %s %s\n",
+						name, oh_name);
+		return;
+	}
+
+	pdev = &od->pdev;
+	dev = &pdev->dev;
+	get_device(dev);
+	dev->dma_mask = &musb_dmamask;
+	dev->coherent_dma_mask = musb_dmamask;
+	put_device(dev);
 }
 
 #else
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vc3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vc3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vc3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vc3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * OMAP3 Voltage Controller (VC) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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.
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#include "vc.h"
+
+/*
+ * VC data common to 34xx/36xx chips
+ * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
+ */
+static struct omap_vc_common_data omap3_vc_common = {
+	.smps_sa_reg	 = OMAP3_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg	 = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET,
+	.bypass_val_reg	 = OMAP3_PRM_VC_BYPASS_VAL_OFFSET,
+	.data_shift	 = OMAP3430_DATA_SHIFT,
+	.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT,
+	.regaddr_shift	 = OMAP3430_REGADDR_SHIFT,
+	.valid		 = OMAP3430_VALID_MASK,
+	.cmd_on_shift	 = OMAP3430_VC_CMD_ON_SHIFT,
+	.cmd_on_mask	 = OMAP3430_VC_CMD_ON_MASK,
+	.cmd_onlp_shift	 = OMAP3430_VC_CMD_ONLP_SHIFT,
+	.cmd_ret_shift	 = OMAP3430_VC_CMD_RET_SHIFT,
+	.cmd_off_shift	 = OMAP3430_VC_CMD_OFF_SHIFT,
+};
+
+struct omap_vc_instance_data omap3_vc1_data = {
+	.vc_common = &omap3_vc_common,
+	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET,
+	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT,
+	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK,
+	.smps_volra_shift = OMAP3430_VOLRA0_SHIFT,
+	.smps_volra_mask = OMAP3430_VOLRA0_MASK,
+};
+
+struct omap_vc_instance_data omap3_vc2_data = {
+	.vc_common = &omap3_vc_common,
+	.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET,
+	.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT,
+	.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK,
+	.smps_volra_shift = OMAP3430_VOLRA1_SHIFT,
+	.smps_volra_mask = OMAP3430_VOLRA1_MASK,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vc44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vc44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vc44xx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vc44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,75 @@
+/*
+ * OMAP4 Voltage Controller (VC) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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.
+ */
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "voltage.h"
+
+#include "vc.h"
+
+/*
+ * VC data common to 44xx chips
+ * XXX This stuff presumably belongs in the vc3xxx.c or vc.c file.
+ */
+static const struct omap_vc_common_data omap4_vc_common = {
+	.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET,
+	.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET,
+	.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET,
+	.data_shift = OMAP4430_DATA_SHIFT,
+	.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT,
+	.regaddr_shift = OMAP4430_REGADDR_SHIFT,
+	.valid = OMAP4430_VALID_MASK,
+	.cmd_on_shift = OMAP4430_ON_SHIFT,
+	.cmd_on_mask = OMAP4430_ON_MASK,
+	.cmd_onlp_shift = OMAP4430_ONLP_SHIFT,
+	.cmd_ret_shift = OMAP4430_RET_SHIFT,
+	.cmd_off_shift = OMAP4430_OFF_SHIFT,
+};
+
+/* VC instance data for each controllable voltage line */
+struct omap_vc_instance_data omap4_vc_mpu_data = {
+	.vc_common = &omap4_vc_common,
+	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET,
+	.smps_sa_shift = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT,
+	.smps_sa_mask = OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK,
+	.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT,
+	.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK,
+};
+
+struct omap_vc_instance_data omap4_vc_iva_data = {
+	.vc_common = &omap4_vc_common,
+	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET,
+	.smps_sa_shift = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT,
+	.smps_sa_mask = OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK,
+	.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT,
+	.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK,
+};
+
+struct omap_vc_instance_data omap4_vc_core_data = {
+	.vc_common = &omap4_vc_common,
+	.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET,
+	.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT,
+	.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK,
+	.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT,
+	.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK,
+};
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vc.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,83 @@
+/*
+ * OMAP3/4 Voltage Controller (VC) structure and macro definitions
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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_VC_H
+#define __ARCH_ARM_MACH_OMAP2_VC_H
+
+#include <linux/kernel.h>
+
+/**
+ * struct omap_vc_common_data - per-VC register/bitfield data
+ * @cmd_on_mask: ON bitmask in PRM_VC_CMD_VAL* register
+ * @valid: VALID bitmask in PRM_VC_BYPASS_VAL register
+ * @smps_sa_reg: Offset of PRM_VC_SMPS_SA reg from PRM start
+ * @smps_volra_reg: Offset of PRM_VC_SMPS_VOL_RA reg from PRM start
+ * @bypass_val_reg: Offset of PRM_VC_BYPASS_VAL reg from PRM start
+ * @data_shift: DATA field shift in PRM_VC_BYPASS_VAL register
+ * @slaveaddr_shift: SLAVEADDR field shift in PRM_VC_BYPASS_VAL register
+ * @regaddr_shift: REGADDR field shift in PRM_VC_BYPASS_VAL register
+ * @cmd_on_shift: ON field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_onlp_shift: ONLP field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_ret_shift: RET field shift in PRM_VC_CMD_VAL_* register
+ * @cmd_off_shift: OFF field shift in PRM_VC_CMD_VAL_* register
+ *
+ * XXX One of cmd_on_mask and cmd_on_shift are not needed
+ * XXX VALID should probably be a shift, not a mask
+ */
+struct omap_vc_common_data {
+	u32 cmd_on_mask;
+	u32 valid;
+	u8 smps_sa_reg;
+	u8 smps_volra_reg;
+	u8 bypass_val_reg;
+	u8 data_shift;
+	u8 slaveaddr_shift;
+	u8 regaddr_shift;
+	u8 cmd_on_shift;
+	u8 cmd_onlp_shift;
+	u8 cmd_ret_shift;
+	u8 cmd_off_shift;
+};
+
+/**
+ * struct omap_vc_instance_data - VC per-instance data
+ * @vc_common: pointer to VC common data for this platform
+ * @smps_sa_mask: SA* bitmask in the PRM_VC_SMPS_SA register
+ * @smps_volra_mask: VOLRA* bitmask in the PRM_VC_VOL_RA register
+ * @smps_sa_shift: SA* field shift in the PRM_VC_SMPS_SA register
+ * @smps_volra_shift: VOLRA* field shift in the PRM_VC_VOL_RA register
+ *
+ * XXX It is not necessary to have both a *_mask and a *_shift -
+ *     remove one
+ */
+struct omap_vc_instance_data {
+	const struct omap_vc_common_data *vc_common;
+	u32 smps_sa_mask;
+	u32 smps_volra_mask;
+	u8 cmdval_reg;
+	u8 smps_sa_shift;
+	u8 smps_volra_shift;
+};
+
+extern struct omap_vc_instance_data omap3_vc1_data;
+extern struct omap_vc_instance_data omap3_vc2_data;
+
+extern struct omap_vc_instance_data omap4_vc_mpu_data;
+extern struct omap_vc_instance_data omap4_vc_iva_data;
+extern struct omap_vc_instance_data omap4_vc_core_data;
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltage.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltage.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltage.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltage.c	2011-05-19 00:06:34.000000000 -0400
@@ -7,8 +7,9 @@
  * Rajendra Nayak <rnayak@ti.com>
  * Lesly A M <x0080970@ti.com>
  *
- * Copyright (C) 2008 Nokia Corporation
+ * Copyright (C) 2008, 2011 Nokia Corporation
  * Kalle Jokiniemi
+ * Paul Walmsley
  *
  * Copyright (C) 2010 Texas Instruments, Inc.
  * Thara Gopinath <thara@ti.com>
@@ -26,7 +27,6 @@
 #include <linux/slab.h>
 
 #include <plat/common.h>
-#include <plat/voltage.h>
 
 #include "prm-regbits-34xx.h"
 #include "prm-regbits-44xx.h"
@@ -35,284 +35,30 @@
 #include "prminst44xx.h"
 #include "control.h"
 
-#define VP_IDLE_TIMEOUT		200
-#define VP_TRANXDONE_TIMEOUT	300
-#define VOLTAGE_DIR_SIZE	16
+#include "voltage.h"
 
-/* Voltage processor register offsets */
-struct vp_reg_offs {
-	u8 vpconfig;
-	u8 vstepmin;
-	u8 vstepmax;
-	u8 vlimitto;
-	u8 vstatus;
-	u8 voltage;
-};
+#include "vc.h"
+#include "vp.h"
 
-/* Voltage Processor bit field values, shifts and masks */
-struct vp_reg_val {
-	/* PRM module */
-	u16 prm_mod;
-	/* VPx_VPCONFIG */
-	u32 vpconfig_erroroffset;
-	u16 vpconfig_errorgain;
-	u32 vpconfig_errorgain_mask;
-	u8 vpconfig_errorgain_shift;
-	u32 vpconfig_initvoltage_mask;
-	u8 vpconfig_initvoltage_shift;
-	u32 vpconfig_timeouten;
-	u32 vpconfig_initvdd;
-	u32 vpconfig_forceupdate;
-	u32 vpconfig_vpenable;
-	/* VPx_VSTEPMIN */
-	u8 vstepmin_stepmin;
-	u16 vstepmin_smpswaittimemin;
-	u8 vstepmin_stepmin_shift;
-	u8 vstepmin_smpswaittimemin_shift;
-	/* VPx_VSTEPMAX */
-	u8 vstepmax_stepmax;
-	u16 vstepmax_smpswaittimemax;
-	u8 vstepmax_stepmax_shift;
-	u8 vstepmax_smpswaittimemax_shift;
-	/* VPx_VLIMITTO */
-	u8 vlimitto_vddmin;
-	u8 vlimitto_vddmax;
-	u16 vlimitto_timeout;
-	u8 vlimitto_vddmin_shift;
-	u8 vlimitto_vddmax_shift;
-	u8 vlimitto_timeout_shift;
-	/* PRM_IRQSTATUS*/
-	u32 tranxdone_status;
-};
+#define VOLTAGE_DIR_SIZE	16
 
-/* Voltage controller registers and offsets */
-struct vc_reg_info {
-	/* PRM module */
-	u16 prm_mod;
-	/* VC register offsets */
-	u8 smps_sa_reg;
-	u8 smps_volra_reg;
-	u8 bypass_val_reg;
-	u8 cmdval_reg;
-	u8 voltsetup_reg;
-	/*VC_SMPS_SA*/
-	u8 smps_sa_shift;
-	u32 smps_sa_mask;
-	/* VC_SMPS_VOL_RA */
-	u8 smps_volra_shift;
-	u32 smps_volra_mask;
-	/* VC_BYPASS_VAL */
-	u8 data_shift;
-	u8 slaveaddr_shift;
-	u8 regaddr_shift;
-	u32 valid;
-	/* VC_CMD_VAL */
-	u8 cmd_on_shift;
-	u8 cmd_onlp_shift;
-	u8 cmd_ret_shift;
-	u8 cmd_off_shift;
-	u32 cmd_on_mask;
-	/* PRM_VOLTSETUP */
-	u8 voltsetup_shift;
-	u32 voltsetup_mask;
-};
 
-/**
- * omap_vdd_info - Per Voltage Domain info
- *
- * @volt_data		: voltage table having the distinct voltages supported
- *			  by the domain and other associated per voltage data.
- * @pmic_info		: pmic specific parameters which should be populted by
- *			  the pmic drivers.
- * @vp_offs		: structure containing the offsets for various
- *			  vp registers
- * @vp_reg		: the register values, shifts, masks for various
- *			  vp registers
- * @vc_reg		: structure containing various various vc registers,
- *			  shifts, masks etc.
- * @voltdm		: pointer to the voltage domain structure
- * @debug_dir		: debug directory for this voltage domain.
- * @curr_volt		: current voltage for this vdd.
- * @ocp_mod		: The prm module for accessing the prm irqstatus reg.
- * @prm_irqst_reg	: prm irqstatus register.
- * @vp_enabled		: flag to keep track of whether vp is enabled or not
- * @volt_scale		: API to scale the voltage of the vdd.
- */
-struct omap_vdd_info {
-	struct omap_volt_data *volt_data;
-	struct omap_volt_pmic_info *pmic_info;
-	struct vp_reg_offs vp_offs;
-	struct vp_reg_val vp_reg;
-	struct vc_reg_info vc_reg;
-	struct voltagedomain voltdm;
-	struct dentry *debug_dir;
-	u32 curr_volt;
-	u16 ocp_mod;
-	u8 prm_irqst_reg;
-	bool vp_enabled;
-	u32 (*read_reg) (u16 mod, u8 offset);
-	void (*write_reg) (u32 val, u16 mod, u8 offset);
-	int (*volt_scale) (struct omap_vdd_info *vdd,
-		unsigned long target_volt);
-};
+static struct omap_vdd_info **vdd_info;
 
-static struct omap_vdd_info *vdd_info;
 /*
  * Number of scalable voltage domains.
  */
 static int nr_scalable_vdd;
 
-/* OMAP3 VDD sturctures */
-static struct omap_vdd_info omap3_vdd_info[] = {
-	{
-		.vp_offs = {
-			.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
-			.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
-			.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
-			.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "mpu",
-		},
-	},
-	{
-		.vp_offs = {
-			.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
-			.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
-			.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
-			.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "core",
-		},
-	},
-};
-
-#define OMAP3_NR_SCALABLE_VDD ARRAY_SIZE(omap3_vdd_info)
-
-/* OMAP4 VDD sturctures */
-static struct omap_vdd_info omap4_vdd_info[] = {
-	{
-		.vp_offs = {
-			.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
-			.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
-			.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
-			.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "mpu",
-		},
-	},
-	{
-		.vp_offs = {
-			.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
-			.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
-			.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
-			.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "iva",
-		},
-	},
-	{
-		.vp_offs = {
-			.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
-			.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
-			.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
-			.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
-			.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
-			.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
-		},
-		.voltdm = {
-			.name = "core",
-		},
-	},
-};
-
-#define OMAP4_NR_SCALABLE_VDD ARRAY_SIZE(omap4_vdd_info)
-
-/*
- * Structures containing OMAP3430/OMAP3630 voltage supported and various
- * voltage dependent data for each VDD.
- */
-#define VOLT_DATA_DEFINE(_v_nom, _efuse_offs, _errminlimit, _errgain)	\
-{									\
-	.volt_nominal	= _v_nom,					\
-	.sr_efuse_offs	= _efuse_offs,					\
-	.sr_errminlimit	= _errminlimit,					\
-	.vp_errgain	= _errgain					\
-}
-
-/* VDD1 */
-static struct omap_volt_data omap34xx_vddmpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP4_UV, OMAP343X_CONTROL_FUSE_OPP4_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_MPU_OPP5_UV, OMAP343X_CONTROL_FUSE_OPP5_VDD1, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap36xx_vddmpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD1, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD1, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP120_UV, OMAP3630_CONTROL_FUSE_OPP120_VDD1, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_MPU_OPP1G_UV, OMAP3630_CONTROL_FUSE_OPP1G_VDD1, 0xfa, 0x27),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-/* VDD2 */
-static struct omap_volt_data omap34xx_vddcore_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP1_UV, OMAP343X_CONTROL_FUSE_OPP1_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP2_UV, OMAP343X_CONTROL_FUSE_OPP2_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3430_VDD_CORE_OPP3_UV, OMAP343X_CONTROL_FUSE_OPP3_VDD2, 0xf9, 0x18),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap36xx_vddcore_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP50_UV, OMAP3630_CONTROL_FUSE_OPP50_VDD2, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP3630_VDD_CORE_OPP100_UV, OMAP3630_CONTROL_FUSE_OPP100_VDD2, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-/*
- * Structures containing OMAP4430 voltage supported and various
- * voltage dependent data for each VDD.
- */
-static struct omap_volt_data omap44xx_vdd_mpu_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP50_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPP100_UV, OMAP44XX_CONTROL_FUSE_MPU_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPTURBO, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_MPU_OPPNITRO_UV, OMAP44XX_CONTROL_FUSE_MPU_OPPNITRO, 0xfa, 0x27),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap44xx_vdd_iva_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP50_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPP100_UV, OMAP44XX_CONTROL_FUSE_IVA_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_IVA_OPPTURBO_UV, OMAP44XX_CONTROL_FUSE_IVA_OPPTURBO, 0xfa, 0x23),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
-
-static struct omap_volt_data omap44xx_vdd_core_volt_data[] = {
-	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP50_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP50, 0xf4, 0x0c),
-	VOLT_DATA_DEFINE(OMAP4430_VDD_CORE_OPP100_UV, OMAP44XX_CONTROL_FUSE_CORE_OPP100, 0xf9, 0x16),
-	VOLT_DATA_DEFINE(0, 0, 0, 0),
-};
+/* XXX document */
+static s16 prm_mod_offs;
+static s16 prm_irqst_ocp_mod_offs;
 
 static struct dentry *voltage_dir;
 
 /* Init function pointers */
-static void (*vc_init) (struct omap_vdd_info *vdd);
-static int (*vdd_data_configure) (struct omap_vdd_info *vdd);
+static int vp_forceupdate_scale_voltage(struct omap_vdd_info *vdd,
+					unsigned long target_volt);
 
 static u32 omap3_voltage_read_reg(u16 mod, u8 offset)
 {
@@ -335,6 +81,61 @@
 	omap4_prminst_write_inst_reg(val, OMAP4430_PRM_PARTITION, mod, offset);
 }
 
+static int __init _config_common_vdd_data(struct omap_vdd_info *vdd)
+{
+	char *sys_ck_name;
+	struct clk *sys_ck;
+	u32 sys_clk_speed, timeout_val, waittime;
+
+	/*
+	 * XXX Clockfw should handle this, or this should be in a
+	 * struct record
+	 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		sys_ck_name = "sys_ck";
+	else if (cpu_is_omap44xx())
+		sys_ck_name = "sys_clkin_ck";
+	else
+		return -EINVAL;
+
+	/*
+	 * Sys clk rate is require to calculate vp timeout value and
+	 * smpswaittimemin and smpswaittimemax.
+	 */
+	sys_ck = clk_get(NULL, sys_ck_name);
+	if (IS_ERR(sys_ck)) {
+		pr_warning("%s: Could not get the sys clk to calculate"
+			"various vdd_%s params\n", __func__, vdd->voltdm.name);
+		return -EINVAL;
+	}
+	sys_clk_speed = clk_get_rate(sys_ck);
+	clk_put(sys_ck);
+	/* Divide to avoid overflow */
+	sys_clk_speed /= 1000;
+
+	/* Generic voltage parameters */
+	vdd->volt_scale = vp_forceupdate_scale_voltage;
+	vdd->vp_enabled = false;
+
+	vdd->vp_rt_data.vpconfig_erroroffset =
+		(vdd->pmic_info->vp_erroroffset <<
+		 vdd->vp_data->vp_common->vpconfig_erroroffset_shift);
+
+	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
+	vdd->vp_rt_data.vlimitto_timeout = timeout_val;
+	vdd->vp_rt_data.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
+	vdd->vp_rt_data.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
+
+	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
+				sys_clk_speed) / 1000;
+	vdd->vp_rt_data.vstepmin_smpswaittimemin = waittime;
+	vdd->vp_rt_data.vstepmax_smpswaittimemax = waittime;
+	vdd->vp_rt_data.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
+	vdd->vp_rt_data.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
+
+	return 0;
+}
+
 /* Voltage debugfs support */
 static int vp_volt_debug_get(void *data, u64 *val)
 {
@@ -346,7 +147,7 @@
 		return -EINVAL;
 	}
 
-	vsel = vdd->read_reg(vdd->vp_reg.prm_mod, vdd->vp_offs.voltage);
+	vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
 	pr_notice("curr_vsel = %x\n", vsel);
 
 	if (!vdd->pmic_info->vsel_to_uv) {
@@ -379,7 +180,6 @@
 static void vp_latch_vsel(struct omap_vdd_info *vdd)
 {
 	u32 vpconfig;
-	u16 mod;
 	unsigned long uvdc;
 	char vsel;
 
@@ -396,30 +196,27 @@
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
 	vsel = vdd->pmic_info->uv_to_vsel(uvdc);
 
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig &= ~(vdd->vp_reg.vpconfig_initvoltage_mask |
-			vdd->vp_reg.vpconfig_initvdd);
-	vpconfig |= vsel << vdd->vp_reg.vpconfig_initvoltage_shift;
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvoltage_mask |
+			vdd->vp_data->vp_common->vpconfig_initvdd);
+	vpconfig |= vsel << vdd->vp_data->vp_common->vpconfig_initvoltage_shift;
 
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Trigger initVDD value copy to voltage processor */
-	vdd->write_reg((vpconfig | vdd->vp_reg.vpconfig_initvdd), mod,
-			vdd->vp_offs.vpconfig);
+	vdd->write_reg((vpconfig | vdd->vp_data->vp_common->vpconfig_initvdd),
+		       prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Clear initVDD copy trigger bit */
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 }
 
 /* Generic voltage init functions */
 static void __init vp_init(struct omap_vdd_info *vdd)
 {
 	u32 vp_val;
-	u16 mod;
 
 	if (!vdd->read_reg || !vdd->write_reg) {
 		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
@@ -427,33 +224,31 @@
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
-	vp_val = vdd->vp_reg.vpconfig_erroroffset |
-		(vdd->vp_reg.vpconfig_errorgain <<
-		vdd->vp_reg.vpconfig_errorgain_shift) |
-		vdd->vp_reg.vpconfig_timeouten;
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vpconfig);
+	vp_val = vdd->vp_rt_data.vpconfig_erroroffset |
+		(vdd->vp_rt_data.vpconfig_errorgain <<
+		vdd->vp_data->vp_common->vpconfig_errorgain_shift) |
+		vdd->vp_data->vp_common->vpconfig_timeouten;
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vpconfig);
 
-	vp_val = ((vdd->vp_reg.vstepmin_smpswaittimemin <<
-		vdd->vp_reg.vstepmin_smpswaittimemin_shift) |
-		(vdd->vp_reg.vstepmin_stepmin <<
-		vdd->vp_reg.vstepmin_stepmin_shift));
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmin);
+	vp_val = ((vdd->vp_rt_data.vstepmin_smpswaittimemin <<
+		vdd->vp_data->vp_common->vstepmin_smpswaittimemin_shift) |
+		(vdd->vp_rt_data.vstepmin_stepmin <<
+		vdd->vp_data->vp_common->vstepmin_stepmin_shift));
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmin);
 
-	vp_val = ((vdd->vp_reg.vstepmax_smpswaittimemax <<
-		vdd->vp_reg.vstepmax_smpswaittimemax_shift) |
-		(vdd->vp_reg.vstepmax_stepmax <<
-		vdd->vp_reg.vstepmax_stepmax_shift));
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vstepmax);
+	vp_val = ((vdd->vp_rt_data.vstepmax_smpswaittimemax <<
+		vdd->vp_data->vp_common->vstepmax_smpswaittimemax_shift) |
+		(vdd->vp_rt_data.vstepmax_stepmax <<
+		vdd->vp_data->vp_common->vstepmax_stepmax_shift));
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vstepmax);
 
-	vp_val = ((vdd->vp_reg.vlimitto_vddmax <<
-		vdd->vp_reg.vlimitto_vddmax_shift) |
-		(vdd->vp_reg.vlimitto_vddmin <<
-		vdd->vp_reg.vlimitto_vddmin_shift) |
-		(vdd->vp_reg.vlimitto_timeout <<
-		vdd->vp_reg.vlimitto_timeout_shift));
-	vdd->write_reg(vp_val, mod, vdd->vp_offs.vlimitto);
+	vp_val = ((vdd->vp_rt_data.vlimitto_vddmax <<
+		vdd->vp_data->vp_common->vlimitto_vddmax_shift) |
+		(vdd->vp_rt_data.vlimitto_vddmin <<
+		vdd->vp_data->vp_common->vlimitto_vddmin_shift) |
+		(vdd->vp_rt_data.vlimitto_timeout <<
+		vdd->vp_data->vp_common->vlimitto_timeout_shift));
+	vdd->write_reg(vp_val, prm_mod_offs, vdd->vp_data->vlimitto);
 }
 
 static void __init vdd_debugfs_init(struct omap_vdd_info *vdd)
@@ -480,23 +275,23 @@
 	}
 
 	(void) debugfs_create_x16("vp_errorgain", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vpconfig_errorgain));
+				&(vdd->vp_rt_data.vpconfig_errorgain));
 	(void) debugfs_create_x16("vp_smpswaittimemin", S_IRUGO,
 				vdd->debug_dir,
-				&(vdd->vp_reg.vstepmin_smpswaittimemin));
+				&(vdd->vp_rt_data.vstepmin_smpswaittimemin));
 	(void) debugfs_create_x8("vp_stepmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vstepmin_stepmin));
+				&(vdd->vp_rt_data.vstepmin_stepmin));
 	(void) debugfs_create_x16("vp_smpswaittimemax", S_IRUGO,
 				vdd->debug_dir,
-				&(vdd->vp_reg.vstepmax_smpswaittimemax));
+				&(vdd->vp_rt_data.vstepmax_smpswaittimemax));
 	(void) debugfs_create_x8("vp_stepmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vstepmax_stepmax));
+				&(vdd->vp_rt_data.vstepmax_stepmax));
 	(void) debugfs_create_x8("vp_vddmax", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vlimitto_vddmax));
+				&(vdd->vp_rt_data.vlimitto_vddmax));
 	(void) debugfs_create_x8("vp_vddmin", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vlimitto_vddmin));
+				&(vdd->vp_rt_data.vlimitto_vddmin));
 	(void) debugfs_create_x16("vp_timeout", S_IRUGO, vdd->debug_dir,
-				&(vdd->vp_reg.vlimitto_timeout));
+				&(vdd->vp_rt_data.vlimitto_timeout));
 	(void) debugfs_create_file("curr_vp_volt", S_IRUGO, vdd->debug_dir,
 				(void *) vdd, &vp_volt_debug_fops);
 	(void) debugfs_create_file("curr_nominal_volt", S_IRUGO,
@@ -509,8 +304,12 @@
 		unsigned long target_volt, u8 *target_vsel, u8 *current_vsel)
 {
 	struct omap_volt_data *volt_data;
+	const struct omap_vc_common_data *vc_common;
+	const struct omap_vp_common_data *vp_common;
 	u32 vc_cmdval, vp_errgain_val;
-	u16 vp_mod, vc_mod;
+
+	vc_common = vdd->vc_data->vc_common;
+	vp_common = vdd->vp_data->vp_common;
 
 	/* Check if suffiecient pmic info is available for this vdd */
 	if (!vdd->pmic_info) {
@@ -532,33 +331,30 @@
 		return -EINVAL;
 	}
 
-	vp_mod = vdd->vp_reg.prm_mod;
-	vc_mod = vdd->vc_reg.prm_mod;
-
 	/* Get volt_data corresponding to target_volt */
 	volt_data = omap_voltage_get_voltdata(&vdd->voltdm, target_volt);
 	if (IS_ERR(volt_data))
 		volt_data = NULL;
 
 	*target_vsel = vdd->pmic_info->uv_to_vsel(target_volt);
-	*current_vsel = vdd->read_reg(vp_mod, vdd->vp_offs.voltage);
+	*current_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
 
 	/* Setting the ON voltage to the new target voltage */
-	vc_cmdval = vdd->read_reg(vc_mod, vdd->vc_reg.cmdval_reg);
-	vc_cmdval &= ~vdd->vc_reg.cmd_on_mask;
-	vc_cmdval |= (*target_vsel << vdd->vc_reg.cmd_on_shift);
-	vdd->write_reg(vc_cmdval, vc_mod, vdd->vc_reg.cmdval_reg);
+	vc_cmdval = vdd->read_reg(prm_mod_offs, vdd->vc_data->cmdval_reg);
+	vc_cmdval &= ~vc_common->cmd_on_mask;
+	vc_cmdval |= (*target_vsel << vc_common->cmd_on_shift);
+	vdd->write_reg(vc_cmdval, prm_mod_offs, vdd->vc_data->cmdval_reg);
 
 	/* Setting vp errorgain based on the voltage */
 	if (volt_data) {
-		vp_errgain_val = vdd->read_reg(vp_mod,
-				vdd->vp_offs.vpconfig);
-		vdd->vp_reg.vpconfig_errorgain = volt_data->vp_errgain;
-		vp_errgain_val &= ~vdd->vp_reg.vpconfig_errorgain_mask;
-		vp_errgain_val |= vdd->vp_reg.vpconfig_errorgain <<
-				vdd->vp_reg.vpconfig_errorgain_shift;
-		vdd->write_reg(vp_errgain_val, vp_mod,
-				vdd->vp_offs.vpconfig);
+		vp_errgain_val = vdd->read_reg(prm_mod_offs,
+					       vdd->vp_data->vpconfig);
+		vdd->vp_rt_data.vpconfig_errorgain = volt_data->vp_errgain;
+		vp_errgain_val &= ~vp_common->vpconfig_errorgain_mask;
+		vp_errgain_val |= vdd->vp_rt_data.vpconfig_errorgain <<
+			vp_common->vpconfig_errorgain_shift;
+		vdd->write_reg(vp_errgain_val, prm_mod_offs,
+			       vdd->vp_data->vpconfig);
 	}
 
 	return 0;
@@ -584,7 +380,6 @@
 {
 	u32 loop_cnt = 0, retries_cnt = 0;
 	u32 vc_valid, vc_bypass_val_reg, vc_bypass_value;
-	u16 mod;
 	u8 target_vsel, current_vsel;
 	int ret;
 
@@ -592,20 +387,19 @@
 	if (ret)
 		return ret;
 
-	mod = vdd->vc_reg.prm_mod;
-
-	vc_valid = vdd->vc_reg.valid;
-	vc_bypass_val_reg = vdd->vc_reg.bypass_val_reg;
-	vc_bypass_value = (target_vsel << vdd->vc_reg.data_shift) |
+	vc_valid = vdd->vc_data->vc_common->valid;
+	vc_bypass_val_reg = vdd->vc_data->vc_common->bypass_val_reg;
+	vc_bypass_value = (target_vsel << vdd->vc_data->vc_common->data_shift) |
 			(vdd->pmic_info->pmic_reg <<
-			vdd->vc_reg.regaddr_shift) |
+			vdd->vc_data->vc_common->regaddr_shift) |
 			(vdd->pmic_info->i2c_slave_addr <<
-			vdd->vc_reg.slaveaddr_shift);
+			vdd->vc_data->vc_common->slaveaddr_shift);
 
-	vdd->write_reg(vc_bypass_value, mod, vc_bypass_val_reg);
-	vdd->write_reg(vc_bypass_value | vc_valid, mod, vc_bypass_val_reg);
+	vdd->write_reg(vc_bypass_value, prm_mod_offs, vc_bypass_val_reg);
+	vdd->write_reg(vc_bypass_value | vc_valid, prm_mod_offs,
+		       vc_bypass_val_reg);
 
-	vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg);
+	vc_bypass_value = vdd->read_reg(prm_mod_offs, vc_bypass_val_reg);
 	/*
 	 * Loop till the bypass command is acknowledged from the SMPS.
 	 * NOTE: This is legacy code. The loop count and retry count needs
@@ -624,7 +418,8 @@
 			loop_cnt = 0;
 			udelay(10);
 		}
-		vc_bypass_value = vdd->read_reg(mod, vc_bypass_val_reg);
+		vc_bypass_value = vdd->read_reg(prm_mod_offs,
+						vc_bypass_val_reg);
 	}
 
 	_post_volt_scale(vdd, target_volt, target_vsel, current_vsel);
@@ -636,7 +431,6 @@
 		unsigned long target_volt)
 {
 	u32 vpconfig;
-	u16 mod, ocp_mod;
 	u8 target_vsel, current_vsel, prm_irqst_reg;
 	int ret, timeout = 0;
 
@@ -644,20 +438,18 @@
 	if (ret)
 		return ret;
 
-	mod = vdd->vp_reg.prm_mod;
-	ocp_mod = vdd->ocp_mod;
-	prm_irqst_reg = vdd->prm_irqst_reg;
+	prm_irqst_reg = vdd->vp_data->prm_irqst_data->prm_irqst_reg;
 
 	/*
 	 * Clear all pending TransactionDone interrupt/status. Typical latency
 	 * is <3us
 	 */
 	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_reg.tranxdone_status,
-				ocp_mod, prm_irqst_reg);
-		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
-				vdd->vp_reg.tranxdone_status))
-				break;
+		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
+			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
+		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+		      vdd->vp_data->prm_irqst_data->tranxdone_status))
+			break;
 		udelay(1);
 	}
 	if (timeout >= VP_TRANXDONE_TIMEOUT) {
@@ -667,30 +459,30 @@
 	}
 
 	/* Configure for VP-Force Update */
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig &= ~(vdd->vp_reg.vpconfig_initvdd |
-			vdd->vp_reg.vpconfig_forceupdate |
-			vdd->vp_reg.vpconfig_initvoltage_mask);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig &= ~(vdd->vp_data->vp_common->vpconfig_initvdd |
+			vdd->vp_data->vp_common->vpconfig_forceupdate |
+			vdd->vp_data->vp_common->vpconfig_initvoltage_mask);
 	vpconfig |= ((target_vsel <<
-			vdd->vp_reg.vpconfig_initvoltage_shift));
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+			vdd->vp_data->vp_common->vpconfig_initvoltage_shift));
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Trigger initVDD value copy to voltage processor */
-	vpconfig |= vdd->vp_reg.vpconfig_initvdd;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig |= vdd->vp_data->vp_common->vpconfig_initvdd;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/* Force update of voltage */
-	vpconfig |= vdd->vp_reg.vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig |= vdd->vp_data->vp_common->vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/*
 	 * Wait for TransactionDone. Typical latency is <200us.
 	 * Depends on SMPSWAITTIMEMIN/MAX and voltage change
 	 */
 	timeout = 0;
-	omap_test_timeout((vdd->read_reg(ocp_mod, prm_irqst_reg) &
-			vdd->vp_reg.tranxdone_status),
-			VP_TRANXDONE_TIMEOUT, timeout);
+	omap_test_timeout((vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+			   vdd->vp_data->prm_irqst_data->tranxdone_status),
+			  VP_TRANXDONE_TIMEOUT, timeout);
 	if (timeout >= VP_TRANXDONE_TIMEOUT)
 		pr_err("%s: vdd_%s TRANXDONE timeout exceeded."
 			"TRANXDONE never got set after the voltage update\n",
@@ -704,11 +496,11 @@
 	 */
 	timeout = 0;
 	while (timeout++ < VP_TRANXDONE_TIMEOUT) {
-		vdd->write_reg(vdd->vp_reg.tranxdone_status,
-				ocp_mod, prm_irqst_reg);
-		if (!(vdd->read_reg(ocp_mod, prm_irqst_reg) &
-				vdd->vp_reg.tranxdone_status))
-				break;
+		vdd->write_reg(vdd->vp_data->prm_irqst_data->tranxdone_status,
+			       prm_irqst_ocp_mod_offs, prm_irqst_reg);
+		if (!(vdd->read_reg(prm_irqst_ocp_mod_offs, prm_irqst_reg) &
+		      vdd->vp_data->prm_irqst_data->tranxdone_status))
+			break;
 		udelay(1);
 	}
 
@@ -717,222 +509,95 @@
 			"to clear the TRANXDONE status\n",
 			__func__, vdd->voltdm.name);
 
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
 	/* Clear initVDD copy trigger bit */
-	vpconfig &= ~vdd->vp_reg.vpconfig_initvdd;;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_initvdd;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 	/* Clear force bit */
-	vpconfig &= ~vdd->vp_reg.vpconfig_forceupdate;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_forceupdate;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	return 0;
 }
 
-/* OMAP3 specific voltage init functions */
+static void __init omap3_vfsm_init(struct omap_vdd_info *vdd)
+{
+	/*
+	 * Voltage Manager FSM parameters init
+	 * XXX This data should be passed in from the board file
+	 */
+	vdd->write_reg(OMAP3_CLKSETUP, prm_mod_offs, OMAP3_PRM_CLKSETUP_OFFSET);
+	vdd->write_reg(OMAP3_VOLTOFFSET, prm_mod_offs,
+		       OMAP3_PRM_VOLTOFFSET_OFFSET);
+	vdd->write_reg(OMAP3_VOLTSETUP2, prm_mod_offs,
+		       OMAP3_PRM_VOLTSETUP2_OFFSET);
+}
 
-/*
- * Intializes the voltage controller registers with the PMIC and board
- * specific parameters and voltage setup times for OMAP3.
- */
 static void __init omap3_vc_init(struct omap_vdd_info *vdd)
 {
-	u32 vc_val;
-	u16 mod;
-	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
 	static bool is_initialized;
+	u8 on_vsel, onlp_vsel, ret_vsel, off_vsel;
+	u32 vc_val;
 
-	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
-		pr_err("%s: PMIC info requried to configure vc for"
-			"vdd_%s not populated.Hence cannot initialize vc\n",
-			__func__, vdd->voltdm.name);
-		return;
-	}
-
-	if (!vdd->read_reg || !vdd->write_reg) {
-		pr_err("%s: No read/write API for accessing vdd_%s regs\n",
-			__func__, vdd->voltdm.name);
+	if (is_initialized)
 		return;
-	}
-
-	mod = vdd->vc_reg.prm_mod;
-
-	/* Set up the SMPS_SA(i2c slave address in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
-	vc_val &= ~vdd->vc_reg.smps_sa_mask;
-	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
-
-	/* Setup the VOLRA(pmic reg addr) in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
-	vc_val &= ~vdd->vc_reg.smps_volra_mask;
-	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
-
-	/*Configure the setup times */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.voltsetup_reg);
-	vc_val &= ~vdd->vc_reg.voltsetup_mask;
-	vc_val |= vdd->pmic_info->volt_setup_time <<
-			vdd->vc_reg.voltsetup_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.voltsetup_reg);
 
 	/* Set up the on, inactive, retention and off voltage */
 	on_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->on_volt);
 	onlp_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->onlp_volt);
 	ret_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->ret_volt);
 	off_vsel = vdd->pmic_info->uv_to_vsel(vdd->pmic_info->off_volt);
-	vc_val	= ((on_vsel << vdd->vc_reg.cmd_on_shift) |
-		(onlp_vsel << vdd->vc_reg.cmd_onlp_shift) |
-		(ret_vsel << vdd->vc_reg.cmd_ret_shift) |
-		(off_vsel << vdd->vc_reg.cmd_off_shift));
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.cmdval_reg);
-
-	if (is_initialized)
-		return;
+	vc_val	= ((on_vsel << vdd->vc_data->vc_common->cmd_on_shift) |
+		(onlp_vsel << vdd->vc_data->vc_common->cmd_onlp_shift) |
+		(ret_vsel << vdd->vc_data->vc_common->cmd_ret_shift) |
+		(off_vsel << vdd->vc_data->vc_common->cmd_off_shift));
+	vdd->write_reg(vc_val, prm_mod_offs, vdd->vc_data->cmdval_reg);
 
-	/* Generic VC parameters init */
-	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, mod,
+	/*
+	 * Generic VC parameters init
+	 * XXX This data should be abstracted out
+	 */
+	vdd->write_reg(OMAP3430_CMD1_MASK | OMAP3430_RAV1_MASK, prm_mod_offs,
 			OMAP3_PRM_VC_CH_CONF_OFFSET);
-	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, mod,
+	vdd->write_reg(OMAP3430_MCODE_SHIFT | OMAP3430_HSEN_MASK, prm_mod_offs,
 			OMAP3_PRM_VC_I2C_CFG_OFFSET);
-	vdd->write_reg(OMAP3_CLKSETUP, mod, OMAP3_PRM_CLKSETUP_OFFSET);
-	vdd->write_reg(OMAP3_VOLTOFFSET, mod, OMAP3_PRM_VOLTOFFSET_OFFSET);
-	vdd->write_reg(OMAP3_VOLTSETUP2, mod, OMAP3_PRM_VOLTSETUP2_OFFSET);
+
+	omap3_vfsm_init(vdd);
+
 	is_initialized = true;
 }
 
-/* Sets up all the VDD related info for OMAP3 */
-static int __init omap3_vdd_data_configure(struct omap_vdd_info *vdd)
-{
-	struct clk *sys_ck;
-	u32 sys_clk_speed, timeout_val, waittime;
 
-	if (!vdd->pmic_info) {
-		pr_err("%s: PMIC info requried to configure vdd_%s not"
-			"populated.Hence cannot initialize vdd_%s\n",
-			__func__, vdd->voltdm.name, vdd->voltdm.name);
-		return -EINVAL;
-	}
-
-	if (!strcmp(vdd->voltdm.name, "mpu")) {
-		if (cpu_is_omap3630())
-			vdd->volt_data = omap36xx_vddmpu_volt_data;
-		else
-			vdd->volt_data = omap34xx_vddmpu_volt_data;
+/* OMAP4 specific voltage init functions */
+static void __init omap4_vc_init(struct omap_vdd_info *vdd)
+{
+	static bool is_initialized;
+	u32 vc_val;
 
-		vdd->vp_reg.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_0_OFFSET;
-		vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA0_SHIFT;
-		vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA0_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA0_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA0_MASK;
-		vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT;
-		vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK;
-	} else if (!strcmp(vdd->voltdm.name, "core")) {
-		if (cpu_is_omap3630())
-			vdd->volt_data = omap36xx_vddcore_volt_data;
-		else
-			vdd->volt_data = omap34xx_vddcore_volt_data;
+	if (is_initialized)
+		return;
 
-		vdd->vp_reg.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP3_PRM_VC_CMD_VAL_1_OFFSET;
-		vdd->vc_reg.smps_sa_shift = OMAP3430_PRM_VC_SMPS_SA_SA1_SHIFT;
-		vdd->vc_reg.smps_sa_mask = OMAP3430_PRM_VC_SMPS_SA_SA1_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP3430_VOLRA1_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP3430_VOLRA1_MASK;
-		vdd->vc_reg.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT;
-		vdd->vc_reg.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK;
-	} else {
-		pr_warning("%s: vdd_%s does not exisit in OMAP3\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
+	/* TODO: Configure setup times and CMD_VAL values*/
 
 	/*
-	 * Sys clk rate is require to calculate vp timeout value and
-	 * smpswaittimemin and smpswaittimemax.
+	 * Generic VC parameters init
+	 * XXX This data should be abstracted out
 	 */
-	sys_ck = clk_get(NULL, "sys_ck");
-	if (IS_ERR(sys_ck)) {
-		pr_warning("%s: Could not get the sys clk to calculate"
-			"various vdd_%s params\n", __func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
-	/* Divide to avoid overflow */
-	sys_clk_speed /= 1000;
-
-	/* Generic voltage parameters */
-	vdd->curr_volt = 1200000;
-	vdd->ocp_mod = OCP_MOD;
-	vdd->prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET;
-	vdd->read_reg = omap3_voltage_read_reg;
-	vdd->write_reg = omap3_voltage_write_reg;
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
-	vdd->vp_enabled = false;
-
-	/* VC parameters */
-	vdd->vc_reg.prm_mod = OMAP3430_GR_MOD;
-	vdd->vc_reg.smps_sa_reg = OMAP3_PRM_VC_SMPS_SA_OFFSET;
-	vdd->vc_reg.smps_volra_reg = OMAP3_PRM_VC_SMPS_VOL_RA_OFFSET;
-	vdd->vc_reg.bypass_val_reg = OMAP3_PRM_VC_BYPASS_VAL_OFFSET;
-	vdd->vc_reg.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET;
-	vdd->vc_reg.data_shift = OMAP3430_DATA_SHIFT;
-	vdd->vc_reg.slaveaddr_shift = OMAP3430_SLAVEADDR_SHIFT;
-	vdd->vc_reg.regaddr_shift = OMAP3430_REGADDR_SHIFT;
-	vdd->vc_reg.valid = OMAP3430_VALID_MASK;
-	vdd->vc_reg.cmd_on_shift = OMAP3430_VC_CMD_ON_SHIFT;
-	vdd->vc_reg.cmd_on_mask = OMAP3430_VC_CMD_ON_MASK;
-	vdd->vc_reg.cmd_onlp_shift = OMAP3430_VC_CMD_ONLP_SHIFT;
-	vdd->vc_reg.cmd_ret_shift = OMAP3430_VC_CMD_RET_SHIFT;
-	vdd->vc_reg.cmd_off_shift = OMAP3430_VC_CMD_OFF_SHIFT;
-
-	vdd->vp_reg.prm_mod = OMAP3430_GR_MOD;
-
-	/* VPCONFIG bit fields */
-	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
-				 OMAP3430_ERROROFFSET_SHIFT);
-	vdd->vp_reg.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK;
-	vdd->vp_reg.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK;
-	vdd->vp_reg.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK;
-	vdd->vp_reg.vpconfig_initvdd = OMAP3430_INITVDD_MASK;
-	vdd->vp_reg.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK;
-	vdd->vp_reg.vpconfig_vpenable = OMAP3430_VPENABLE_MASK;
-
-	/* VSTEPMIN VSTEPMAX bit fields */
-	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
-				sys_clk_speed) / 1000;
-	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
-	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
-	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
-	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
-				OMAP3430_SMPSWAITTIMEMIN_SHIFT;
-	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
-				OMAP3430_SMPSWAITTIMEMAX_SHIFT;
-	vdd->vp_reg.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT;
-	vdd->vp_reg.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT;
+	vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
+		  OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
+		  OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
+	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
 
-	/* VLIMITTO bit fields */
-	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
-	vdd->vp_reg.vlimitto_timeout = timeout_val;
-	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
-	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-	vdd->vp_reg.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT;
-	vdd->vp_reg.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT;
-	vdd->vp_reg.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT;
+	/* XXX These are magic numbers and do not belong! */
+	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
+	vdd->write_reg(vc_val, prm_mod_offs, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
 
-	return 0;
+	is_initialized = true;
 }
 
-/* OMAP4 specific voltage init functions */
-static void __init omap4_vc_init(struct omap_vdd_info *vdd)
+static void __init omap_vc_init(struct omap_vdd_info *vdd)
 {
 	u32 vc_val;
-	u16 mod;
-	static bool is_initialized;
 
 	if (!vdd->pmic_info || !vdd->pmic_info->uv_to_vsel) {
 		pr_err("%s: PMIC info requried to configure vc for"
@@ -947,173 +612,61 @@
 		return;
 	}
 
-	mod = vdd->vc_reg.prm_mod;
-
 	/* Set up the SMPS_SA(i2c slave address in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_sa_reg);
-	vc_val &= ~vdd->vc_reg.smps_sa_mask;
-	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_reg.smps_sa_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_sa_reg);
+	vc_val = vdd->read_reg(prm_mod_offs,
+			       vdd->vc_data->vc_common->smps_sa_reg);
+	vc_val &= ~vdd->vc_data->smps_sa_mask;
+	vc_val |= vdd->pmic_info->i2c_slave_addr << vdd->vc_data->smps_sa_shift;
+	vdd->write_reg(vc_val, prm_mod_offs,
+		       vdd->vc_data->vc_common->smps_sa_reg);
 
 	/* Setup the VOLRA(pmic reg addr) in VC */
-	vc_val = vdd->read_reg(mod, vdd->vc_reg.smps_volra_reg);
-	vc_val &= ~vdd->vc_reg.smps_volra_mask;
-	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_reg.smps_volra_shift;
-	vdd->write_reg(vc_val, mod, vdd->vc_reg.smps_volra_reg);
-
-	/* TODO: Configure setup times and CMD_VAL values*/
-
-	if (is_initialized)
-		return;
-
-	/* Generic VC parameters init */
-	vc_val = (OMAP4430_RAV_VDD_MPU_L_MASK | OMAP4430_CMD_VDD_MPU_L_MASK |
-		OMAP4430_RAV_VDD_IVA_L_MASK | OMAP4430_CMD_VDD_IVA_L_MASK |
-		OMAP4430_RAV_VDD_CORE_L_MASK | OMAP4430_CMD_VDD_CORE_L_MASK);
-	vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_CHANNEL_OFFSET);
+	vc_val = vdd->read_reg(prm_mod_offs,
+			       vdd->vc_data->vc_common->smps_volra_reg);
+	vc_val &= ~vdd->vc_data->smps_volra_mask;
+	vc_val |= vdd->pmic_info->pmic_reg << vdd->vc_data->smps_volra_shift;
+	vdd->write_reg(vc_val, prm_mod_offs,
+		       vdd->vc_data->vc_common->smps_volra_reg);
 
-	vc_val = (0x60 << OMAP4430_SCLL_SHIFT | 0x26 << OMAP4430_SCLH_SHIFT);
-	vdd->write_reg(vc_val, mod, OMAP4_PRM_VC_CFG_I2C_CLK_OFFSET);
+	/* Configure the setup times */
+	vc_val = vdd->read_reg(prm_mod_offs, vdd->vfsm->voltsetup_reg);
+	vc_val &= ~vdd->vfsm->voltsetup_mask;
+	vc_val |= vdd->pmic_info->volt_setup_time <<
+			vdd->vfsm->voltsetup_shift;
+	vdd->write_reg(vc_val, prm_mod_offs, vdd->vfsm->voltsetup_reg);
 
-	is_initialized = true;
+	if (cpu_is_omap34xx())
+		omap3_vc_init(vdd);
+	else if (cpu_is_omap44xx())
+		omap4_vc_init(vdd);
 }
 
-/* Sets up all the VDD related info for OMAP4 */
-static int __init omap4_vdd_data_configure(struct omap_vdd_info *vdd)
+static int __init omap_vdd_data_configure(struct omap_vdd_info *vdd)
 {
-	struct clk *sys_ck;
-	u32 sys_clk_speed, timeout_val, waittime;
+	int ret = -EINVAL;
 
 	if (!vdd->pmic_info) {
 		pr_err("%s: PMIC info requried to configure vdd_%s not"
 			"populated.Hence cannot initialize vdd_%s\n",
 			__func__, vdd->voltdm.name, vdd->voltdm.name);
-		return -EINVAL;
+		goto ovdc_out;
 	}
 
-	if (!strcmp(vdd->voltdm.name, "mpu")) {
-		vdd->volt_data = omap44xx_vdd_mpu_volt_data;
-		vdd->vp_reg.tranxdone_status =
-				OMAP4430_VP_MPU_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_MPU_L_OFFSET;
-		vdd->vc_reg.smps_sa_shift =
-				OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_SHIFT;
-		vdd->vc_reg.smps_sa_mask =
-				OMAP4430_SA_VDD_MPU_L_PRM_VC_SMPS_SA_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_MPU_L_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_MPU_L_MASK;
-		vdd->vc_reg.voltsetup_reg =
-				OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET;
-		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET;
-	} else if (!strcmp(vdd->voltdm.name, "core")) {
-		vdd->volt_data = omap44xx_vdd_core_volt_data;
-		vdd->vp_reg.tranxdone_status =
-				OMAP4430_VP_CORE_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg =
-				OMAP4_PRM_VC_VAL_CMD_VDD_CORE_L_OFFSET;
-		vdd->vc_reg.smps_sa_shift = OMAP4430_SA_VDD_CORE_L_0_6_SHIFT;
-		vdd->vc_reg.smps_sa_mask = OMAP4430_SA_VDD_CORE_L_0_6_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_CORE_L_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_CORE_L_MASK;
-		vdd->vc_reg.voltsetup_reg =
-				OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET;
-		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
-	} else if (!strcmp(vdd->voltdm.name, "iva")) {
-		vdd->volt_data = omap44xx_vdd_iva_volt_data;
-		vdd->vp_reg.tranxdone_status =
-				OMAP4430_VP_IVA_TRANXDONE_ST_MASK;
-		vdd->vc_reg.cmdval_reg = OMAP4_PRM_VC_VAL_CMD_VDD_IVA_L_OFFSET;
-		vdd->vc_reg.smps_sa_shift =
-				OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_SHIFT;
-		vdd->vc_reg.smps_sa_mask =
-				OMAP4430_SA_VDD_IVA_L_PRM_VC_SMPS_SA_MASK;
-		vdd->vc_reg.smps_volra_shift = OMAP4430_VOLRA_VDD_IVA_L_SHIFT;
-		vdd->vc_reg.smps_volra_mask = OMAP4430_VOLRA_VDD_IVA_L_MASK;
-		vdd->vc_reg.voltsetup_reg =
-				OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET;
-		vdd->prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET;
-	} else {
-		pr_warning("%s: vdd_%s does not exisit in OMAP4\n",
-			__func__, vdd->voltdm.name);
-		return -EINVAL;
-	}
+	if (IS_ERR_VALUE(_config_common_vdd_data(vdd)))
+		goto ovdc_out;
 
-	/*
-	 * Sys clk rate is require to calculate vp timeout value and
-	 * smpswaittimemin and smpswaittimemax.
-	 */
-	sys_ck = clk_get(NULL, "sys_clkin_ck");
-	if (IS_ERR(sys_ck)) {
-		pr_warning("%s: Could not get the sys clk to calculate"
-			"various vdd_%s params\n", __func__, vdd->voltdm.name);
-		return -EINVAL;
+	if (cpu_is_omap34xx()) {
+		vdd->read_reg = omap3_voltage_read_reg;
+		vdd->write_reg = omap3_voltage_write_reg;
+		ret = 0;
+	} else if (cpu_is_omap44xx()) {
+		vdd->read_reg = omap4_voltage_read_reg;
+		vdd->write_reg = omap4_voltage_write_reg;
+		ret = 0;
 	}
-	sys_clk_speed = clk_get_rate(sys_ck);
-	clk_put(sys_ck);
-	/* Divide to avoid overflow */
-	sys_clk_speed /= 1000;
-
-	/* Generic voltage parameters */
-	vdd->curr_volt = 1200000;
-	vdd->ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
-	vdd->read_reg = omap4_voltage_read_reg;
-	vdd->write_reg = omap4_voltage_write_reg;
-	vdd->volt_scale = vp_forceupdate_scale_voltage;
-	vdd->vp_enabled = false;
-
-	/* VC parameters */
-	vdd->vc_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
-	vdd->vc_reg.smps_sa_reg = OMAP4_PRM_VC_SMPS_SA_OFFSET;
-	vdd->vc_reg.smps_volra_reg = OMAP4_PRM_VC_VAL_SMPS_RA_VOL_OFFSET;
-	vdd->vc_reg.bypass_val_reg = OMAP4_PRM_VC_VAL_BYPASS_OFFSET;
-	vdd->vc_reg.data_shift = OMAP4430_DATA_SHIFT;
-	vdd->vc_reg.slaveaddr_shift = OMAP4430_SLAVEADDR_SHIFT;
-	vdd->vc_reg.regaddr_shift = OMAP4430_REGADDR_SHIFT;
-	vdd->vc_reg.valid = OMAP4430_VALID_MASK;
-	vdd->vc_reg.cmd_on_shift = OMAP4430_ON_SHIFT;
-	vdd->vc_reg.cmd_on_mask = OMAP4430_ON_MASK;
-	vdd->vc_reg.cmd_onlp_shift = OMAP4430_ONLP_SHIFT;
-	vdd->vc_reg.cmd_ret_shift = OMAP4430_RET_SHIFT;
-	vdd->vc_reg.cmd_off_shift = OMAP4430_OFF_SHIFT;
 
-	vdd->vp_reg.prm_mod = OMAP4430_PRM_DEVICE_INST;
-
-	/* VPCONFIG bit fields */
-	vdd->vp_reg.vpconfig_erroroffset = (vdd->pmic_info->vp_erroroffset <<
-				 OMAP4430_ERROROFFSET_SHIFT);
-	vdd->vp_reg.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK;
-	vdd->vp_reg.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT;
-	vdd->vp_reg.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK;
-	vdd->vp_reg.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK;
-	vdd->vp_reg.vpconfig_initvdd = OMAP4430_INITVDD_MASK;
-	vdd->vp_reg.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK;
-	vdd->vp_reg.vpconfig_vpenable = OMAP4430_VPENABLE_MASK;
-
-	/* VSTEPMIN VSTEPMAX bit fields */
-	waittime = ((vdd->pmic_info->step_size / vdd->pmic_info->slew_rate) *
-				sys_clk_speed) / 1000;
-	vdd->vp_reg.vstepmin_smpswaittimemin = waittime;
-	vdd->vp_reg.vstepmax_smpswaittimemax = waittime;
-	vdd->vp_reg.vstepmin_stepmin = vdd->pmic_info->vp_vstepmin;
-	vdd->vp_reg.vstepmax_stepmax = vdd->pmic_info->vp_vstepmax;
-	vdd->vp_reg.vstepmin_smpswaittimemin_shift =
-			OMAP4430_SMPSWAITTIMEMIN_SHIFT;
-	vdd->vp_reg.vstepmax_smpswaittimemax_shift =
-			OMAP4430_SMPSWAITTIMEMAX_SHIFT;
-	vdd->vp_reg.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT;
-	vdd->vp_reg.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT;
-
-	/* VLIMITTO bit fields */
-	timeout_val = (sys_clk_speed * vdd->pmic_info->vp_timeout_us) / 1000;
-	vdd->vp_reg.vlimitto_timeout = timeout_val;
-	vdd->vp_reg.vlimitto_vddmin = vdd->pmic_info->vp_vddmin;
-	vdd->vp_reg.vlimitto_vddmax = vdd->pmic_info->vp_vddmax;
-	vdd->vp_reg.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT;
-	vdd->vp_reg.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT;
-	vdd->vp_reg.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT;
-
-	return 0;
+ovdc_out:
+	return ret;
 }
 
 /* Public functions */
@@ -1161,8 +714,7 @@
 		return 0;
 	}
 
-	curr_vsel = vdd->read_reg(vdd->vp_reg.prm_mod,
-			vdd->vp_offs.voltage);
+	curr_vsel = vdd->read_reg(prm_mod_offs, vdd->vp_data->voltage);
 
 	if (!vdd->pmic_info || !vdd->pmic_info->vsel_to_uv) {
 		pr_warning("%s: PMIC function to convert vsel to voltage"
@@ -1184,7 +736,6 @@
 {
 	struct omap_vdd_info *vdd;
 	u32 vpconfig;
-	u16 mod;
 
 	if (!voltdm || IS_ERR(voltdm)) {
 		pr_warning("%s: VDD specified does not exist!\n", __func__);
@@ -1198,8 +749,6 @@
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
 	/* If VP is already enabled, do nothing. Return */
 	if (vdd->vp_enabled)
 		return;
@@ -1207,9 +756,9 @@
 	vp_latch_vsel(vdd);
 
 	/* Enable VP */
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig |= vdd->vp_reg.vpconfig_vpenable;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig |= vdd->vp_data->vp_common->vpconfig_vpenable;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 	vdd->vp_enabled = true;
 }
 
@@ -1224,7 +773,6 @@
 {
 	struct omap_vdd_info *vdd;
 	u32 vpconfig;
-	u16 mod;
 	int timeout;
 
 	if (!voltdm || IS_ERR(voltdm)) {
@@ -1239,8 +787,6 @@
 		return;
 	}
 
-	mod = vdd->vp_reg.prm_mod;
-
 	/* If VP is already disabled, do nothing. Return */
 	if (!vdd->vp_enabled) {
 		pr_warning("%s: Trying to disable VP for vdd_%s when"
@@ -1249,14 +795,14 @@
 	}
 
 	/* Disable VP */
-	vpconfig = vdd->read_reg(mod, vdd->vp_offs.vpconfig);
-	vpconfig &= ~vdd->vp_reg.vpconfig_vpenable;
-	vdd->write_reg(vpconfig, mod, vdd->vp_offs.vpconfig);
+	vpconfig = vdd->read_reg(prm_mod_offs, vdd->vp_data->vpconfig);
+	vpconfig &= ~vdd->vp_data->vp_common->vpconfig_vpenable;
+	vdd->write_reg(vpconfig, prm_mod_offs, vdd->vp_data->vpconfig);
 
 	/*
 	 * Wait for VP idle Typical latency is <2us. Maximum latency is ~100us
 	 */
-	omap_test_timeout((vdd->read_reg(mod, vdd->vp_offs.vstatus)),
+	omap_test_timeout((vdd->read_reg(prm_mod_offs, vdd->vp_data->vstatus)),
 				VP_IDLE_TIMEOUT, timeout);
 
 	if (timeout >= VP_IDLE_TIMEOUT)
@@ -1304,7 +850,7 @@
  * @voltdm:	pointer to the VDD whose voltage is to be reset.
  *
  * This API finds out the correct voltage the voltage domain is supposed
- * to be at and resets the voltage to that level. Should be used expecially
+ * to be at and resets the voltage to that level. Should be used especially
  * while disabling any voltage compensation modules.
  */
 void omap_voltage_reset(struct voltagedomain *voltdm)
@@ -1365,7 +911,7 @@
  * This API searches only through the non-compensated voltages int the
  * voltage table.
  * Returns pointer to the voltage table entry corresponding to volt on
- * sucess. Returns -ENODATA if no voltage table exisits for the passed voltage
+ * success. Returns -ENODATA if no voltage table exisits for the passed voltage
  * domain or if there is no matching entry.
  */
 struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
@@ -1509,8 +1055,8 @@
 	}
 
 	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (!(strcmp(name, vdd_info[i].voltdm.name)))
-			return &vdd_info[i].voltdm;
+		if (!(strcmp(name, vdd_info[i]->voltdm.name)))
+			return &vdd_info[i]->voltdm;
 	}
 
 	return ERR_PTR(-EINVAL);
@@ -1538,35 +1084,24 @@
 		pr_err("%s: Unable to create voltage debugfs main dir\n",
 			__func__);
 	for (i = 0; i < nr_scalable_vdd; i++) {
-		if (vdd_data_configure(&vdd_info[i]))
+		if (omap_vdd_data_configure(vdd_info[i]))
 			continue;
-		vc_init(&vdd_info[i]);
-		vp_init(&vdd_info[i]);
-		vdd_debugfs_init(&vdd_info[i]);
+		omap_vc_init(vdd_info[i]);
+		vp_init(vdd_info[i]);
+		vdd_debugfs_init(vdd_info[i]);
 	}
 
 	return 0;
 }
 
-/**
- * omap_voltage_early_init()- Volatage driver early init
- */
-static int __init omap_voltage_early_init(void)
+/* XXX document */
+int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_ocp_mod,
+				   struct omap_vdd_info *omap_vdd_array[],
+				   u8 omap_vdd_count)
 {
-	if (cpu_is_omap34xx()) {
-		vdd_info = omap3_vdd_info;
-		nr_scalable_vdd = OMAP3_NR_SCALABLE_VDD;
-		vc_init = omap3_vc_init;
-		vdd_data_configure = omap3_vdd_data_configure;
-	} else if (cpu_is_omap44xx()) {
-		vdd_info = omap4_vdd_info;
-		nr_scalable_vdd = OMAP4_NR_SCALABLE_VDD;
-		vc_init = omap4_vc_init;
-		vdd_data_configure = omap4_vdd_data_configure;
-	} else {
-		pr_warning("%s: voltage driver support not added\n", __func__);
-	}
-
+	prm_mod_offs = prm_mod;
+	prm_irqst_ocp_mod_offs = prm_irqst_ocp_mod;
+	vdd_info = omap_vdd_array;
+	nr_scalable_vdd = omap_vdd_count;
 	return 0;
 }
-core_initcall(omap_voltage_early_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltagedomains3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,95 @@
+/*
+ * OMAP3 voltage domain data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+#include <plat/cpu.h>
+
+#include "prm-regbits-34xx.h"
+#include "omap_opp_data.h"
+#include "voltage.h"
+#include "vc.h"
+#include "vp.h"
+
+/*
+ * VDD data
+ */
+
+static const struct omap_vfsm_instance_data omap3_vdd1_vfsm_data = {
+	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
+	.voltsetup_shift = OMAP3430_SETUP_TIME1_SHIFT,
+	.voltsetup_mask = OMAP3430_SETUP_TIME1_MASK,
+};
+
+static struct omap_vdd_info omap3_vdd1_info = {
+	.vp_data = &omap3_vp1_data,
+	.vc_data = &omap3_vc1_data,
+	.vfsm = &omap3_vdd1_vfsm_data,
+	.voltdm = {
+		.name = "mpu",
+	},
+};
+
+static const struct omap_vfsm_instance_data omap3_vdd2_vfsm_data = {
+	.voltsetup_reg = OMAP3_PRM_VOLTSETUP1_OFFSET,
+	.voltsetup_shift = OMAP3430_SETUP_TIME2_SHIFT,
+	.voltsetup_mask = OMAP3430_SETUP_TIME2_MASK,
+};
+
+static struct omap_vdd_info omap3_vdd2_info = {
+	.vp_data = &omap3_vp2_data,
+	.vc_data = &omap3_vc2_data,
+	.vfsm = &omap3_vdd2_vfsm_data,
+	.voltdm = {
+		.name = "core",
+	},
+};
+
+/* OMAP3 VDD structures */
+static struct omap_vdd_info *omap3_vdd_info[] = {
+	&omap3_vdd1_info,
+	&omap3_vdd2_info,
+};
+
+/* OMAP3 specific voltage init functions */
+static int __init omap3xxx_voltage_early_init(void)
+{
+	s16 prm_mod = OMAP3430_GR_MOD;
+	s16 prm_irqst_ocp_mod = OCP_MOD;
+
+	if (!cpu_is_omap34xx())
+		return 0;
+
+	/*
+	 * XXX Will depend on the process, validation, and binning
+	 * for the currently-running IC
+	 */
+	if (cpu_is_omap3630()) {
+		omap3_vdd1_info.volt_data = omap36xx_vddmpu_volt_data;
+		omap3_vdd2_info.volt_data = omap36xx_vddcore_volt_data;
+	} else {
+		omap3_vdd1_info.volt_data = omap34xx_vddmpu_volt_data;
+		omap3_vdd2_info.volt_data = omap34xx_vddcore_volt_data;
+	}
+
+	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
+				       omap3_vdd_info,
+				       ARRAY_SIZE(omap3_vdd_info));
+};
+core_initcall(omap3xxx_voltage_early_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltagedomains44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * OMAP3/OMAP4 Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2007 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ *
+ * Copyright (C) 2008 Nokia Corporation
+ * Kalle Jokiniemi
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ * Thara Gopinath <thara@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/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-44xx.h"
+#include "prm44xx.h"
+#include "prcm44xx.h"
+#include "prminst44xx.h"
+#include "voltage.h"
+#include "omap_opp_data.h"
+#include "vc.h"
+#include "vp.h"
+
+static const struct omap_vfsm_instance_data omap4_vdd_mpu_vfsm_data = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_MPU_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_mpu_info = {
+	.vp_data = &omap4_vp_mpu_data,
+	.vc_data = &omap4_vc_mpu_data,
+	.vfsm = &omap4_vdd_mpu_vfsm_data,
+	.voltdm = {
+		.name = "mpu",
+	},
+};
+
+static const struct omap_vfsm_instance_data omap4_vdd_iva_vfsm_data = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_IVA_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_iva_info = {
+	.vp_data = &omap4_vp_iva_data,
+	.vc_data = &omap4_vc_iva_data,
+	.vfsm = &omap4_vdd_iva_vfsm_data,
+	.voltdm = {
+		.name = "iva",
+	},
+};
+
+static const struct omap_vfsm_instance_data omap4_vdd_core_vfsm_data = {
+	.voltsetup_reg = OMAP4_PRM_VOLTSETUP_CORE_RET_SLEEP_OFFSET,
+};
+
+static struct omap_vdd_info omap4_vdd_core_info = {
+	.vp_data = &omap4_vp_core_data,
+	.vc_data = &omap4_vc_core_data,
+	.vfsm = &omap4_vdd_core_vfsm_data,
+	.voltdm = {
+		.name = "core",
+	},
+};
+
+/* OMAP4 VDD structures */
+static struct omap_vdd_info *omap4_vdd_info[] = {
+	&omap4_vdd_mpu_info,
+	&omap4_vdd_iva_info,
+	&omap4_vdd_core_info,
+};
+
+/* OMAP4 specific voltage init functions */
+static int __init omap44xx_voltage_early_init(void)
+{
+	s16 prm_mod = OMAP4430_PRM_DEVICE_INST;
+	s16 prm_irqst_ocp_mod = OMAP4430_PRM_OCP_SOCKET_INST;
+
+	if (!cpu_is_omap44xx())
+		return 0;
+
+	/*
+	 * XXX Will depend on the process, validation, and binning
+	 * for the currently-running IC
+	 */
+	omap4_vdd_mpu_info.volt_data = omap44xx_vdd_mpu_volt_data;
+	omap4_vdd_iva_info.volt_data = omap44xx_vdd_iva_volt_data;
+	omap4_vdd_core_info.volt_data = omap44xx_vdd_core_volt_data;
+
+	return omap_voltage_early_init(prm_mod, prm_irqst_ocp_mod,
+				       omap4_vdd_info,
+				       ARRAY_SIZE(omap4_vdd_info));
+};
+core_initcall(omap44xx_voltage_early_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltage.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltage.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/voltage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/voltage.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ * OMAP Voltage Management Routines
+ *
+ * Author: Thara Gopinath	<thara@ti.com>
+ *
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ * Thara Gopinath <thara@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 __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
+
+#include <linux/err.h>
+
+#include "vc.h"
+#include "vp.h"
+
+/* XXX document */
+#define VOLTSCALE_VPFORCEUPDATE		1
+#define VOLTSCALE_VCBYPASS		2
+
+/*
+ * OMAP3 GENERIC setup times. Revisit to see if these needs to be
+ * passed from board or PMIC file
+ */
+#define OMAP3_CLKSETUP		0xff
+#define OMAP3_VOLTOFFSET	0xff
+#define OMAP3_VOLTSETUP2	0xff
+
+/**
+ * struct omap_vfsm_instance_data - per-voltage manager FSM register/bitfield
+ * data
+ * @voltsetup_mask: SETUP_TIME* bitmask in the PRM_VOLTSETUP* register
+ * @voltsetup_reg: register offset of PRM_VOLTSETUP from PRM base
+ * @voltsetup_shift: SETUP_TIME* field shift in the PRM_VOLTSETUP* register
+ *
+ * XXX What about VOLTOFFSET/VOLTCTRL?
+ * XXX It is not necessary to have both a _mask and a _shift for the same
+ *     bitfield - remove one!
+ */
+struct omap_vfsm_instance_data {
+	u32 voltsetup_mask;
+	u8 voltsetup_reg;
+	u8 voltsetup_shift;
+};
+
+/**
+ * struct voltagedomain - omap voltage domain global structure.
+ * @name:	Name of the voltage domain which can be used as a unique
+ *		identifier.
+ */
+struct voltagedomain {
+	char *name;
+};
+
+/**
+ * struct omap_volt_data - Omap voltage specific data.
+ * @voltage_nominal:	The possible voltage value in uV
+ * @sr_efuse_offs:	The offset of the efuse register(from system
+ *			control module base address) from where to read
+ *			the n-target value for the smartreflex module.
+ * @sr_errminlimit:	Error min limit value for smartreflex. This value
+ *			differs at differnet opp and thus is linked
+ *			with voltage.
+ * @vp_errorgain:	Error gain value for the voltage processor. This
+ *			field also differs according to the voltage/opp.
+ */
+struct omap_volt_data {
+	u32	volt_nominal;
+	u32	sr_efuse_offs;
+	u8	sr_errminlimit;
+	u8	vp_errgain;
+};
+
+/**
+ * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
+ * @slew_rate:	PMIC slew rate (in uv/us)
+ * @step_size:	PMIC voltage step size (in uv)
+ * @vsel_to_uv:	PMIC API to convert vsel value to actual voltage in uV.
+ * @uv_to_vsel:	PMIC API to convert voltage in uV to vsel value.
+ */
+struct omap_volt_pmic_info {
+	int slew_rate;
+	int step_size;
+	u32 on_volt;
+	u32 onlp_volt;
+	u32 ret_volt;
+	u32 off_volt;
+	u16 volt_setup_time;
+	u8 vp_erroroffset;
+	u8 vp_vstepmin;
+	u8 vp_vstepmax;
+	u8 vp_vddmin;
+	u8 vp_vddmax;
+	u8 vp_timeout_us;
+	u8 i2c_slave_addr;
+	u8 pmic_reg;
+	unsigned long (*vsel_to_uv) (const u8 vsel);
+	u8 (*uv_to_vsel) (unsigned long uV);
+};
+
+/**
+ * omap_vdd_info - Per Voltage Domain info
+ *
+ * @volt_data		: voltage table having the distinct voltages supported
+ *			  by the domain and other associated per voltage data.
+ * @pmic_info		: pmic specific parameters which should be populted by
+ *			  the pmic drivers.
+ * @vp_data		: the register values, shifts, masks for various
+ *			  vp registers
+ * @vp_rt_data          : VP data derived at runtime, not predefined
+ * @vc_data		: structure containing various various vc registers,
+ *			  shifts, masks etc.
+ * @vfsm                : voltage manager FSM data
+ * @voltdm		: pointer to the voltage domain structure
+ * @debug_dir		: debug directory for this voltage domain.
+ * @curr_volt		: current voltage for this vdd.
+ * @vp_enabled		: flag to keep track of whether vp is enabled or not
+ * @volt_scale		: API to scale the voltage of the vdd.
+ */
+struct omap_vdd_info {
+	struct omap_volt_data *volt_data;
+	struct omap_volt_pmic_info *pmic_info;
+	struct omap_vp_instance_data *vp_data;
+	struct omap_vp_runtime_data vp_rt_data;
+	struct omap_vc_instance_data *vc_data;
+	const struct omap_vfsm_instance_data *vfsm;
+	struct voltagedomain voltdm;
+	struct dentry *debug_dir;
+	u32 curr_volt;
+	bool vp_enabled;
+	u32 (*read_reg) (u16 mod, u8 offset);
+	void (*write_reg) (u32 val, u16 mod, u8 offset);
+	int (*volt_scale) (struct omap_vdd_info *vdd,
+		unsigned long target_volt);
+};
+
+unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
+void omap_vp_enable(struct voltagedomain *voltdm);
+void omap_vp_disable(struct voltagedomain *voltdm);
+int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
+		unsigned long target_volt);
+void omap_voltage_reset(struct voltagedomain *voltdm);
+void omap_voltage_get_volttable(struct voltagedomain *voltdm,
+		struct omap_volt_data **volt_data);
+struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
+		unsigned long volt);
+unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
+struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
+int __init omap_voltage_early_init(s16 prm_mod, s16 prm_irqst_mod,
+				   struct omap_vdd_info *omap_vdd_array[],
+				   u8 omap_vdd_count);
+#ifdef CONFIG_PM
+int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info);
+void omap_change_voltscale_method(struct voltagedomain *voltdm,
+		int voltscale_method);
+/* API to get the voltagedomain pointer */
+struct voltagedomain *omap_voltage_domain_lookup(char *name);
+
+int omap_voltage_late_init(void);
+#else
+static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
+		struct omap_volt_pmic_info *pmic_info)
+{
+	return -EINVAL;
+}
+static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
+		int voltscale_method) {}
+static inline int omap_voltage_late_init(void)
+{
+	return -EINVAL;
+}
+static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
+{
+	return ERR_PTR(-EINVAL);
+}
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vp3xxx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vp3xxx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vp3xxx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vp3xxx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,82 @@
+/*
+ * OMAP3 Voltage Processor (VP) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm-regbits-34xx.h"
+#include "voltage.h"
+
+#include "vp.h"
+
+/*
+ * VP data common to 34xx/36xx chips
+ * XXX This stuff presumably belongs in the vp3xxx.c or vp.c file.
+ */
+static const struct omap_vp_common_data omap3_vp_common = {
+	.vpconfig_erroroffset_shift = OMAP3430_ERROROFFSET_SHIFT,
+	.vpconfig_errorgain_mask = OMAP3430_ERRORGAIN_MASK,
+	.vpconfig_errorgain_shift = OMAP3430_ERRORGAIN_SHIFT,
+	.vpconfig_initvoltage_shift = OMAP3430_INITVOLTAGE_SHIFT,
+	.vpconfig_initvoltage_mask = OMAP3430_INITVOLTAGE_MASK,
+	.vpconfig_timeouten = OMAP3430_TIMEOUTEN_MASK,
+	.vpconfig_initvdd = OMAP3430_INITVDD_MASK,
+	.vpconfig_forceupdate = OMAP3430_FORCEUPDATE_MASK,
+	.vpconfig_vpenable = OMAP3430_VPENABLE_MASK,
+	.vstepmin_smpswaittimemin_shift = OMAP3430_SMPSWAITTIMEMIN_SHIFT,
+	.vstepmax_smpswaittimemax_shift = OMAP3430_SMPSWAITTIMEMAX_SHIFT,
+	.vstepmin_stepmin_shift = OMAP3430_VSTEPMIN_SHIFT,
+	.vstepmax_stepmax_shift = OMAP3430_VSTEPMAX_SHIFT,
+	.vlimitto_vddmin_shift = OMAP3430_VDDMIN_SHIFT,
+	.vlimitto_vddmax_shift = OMAP3430_VDDMAX_SHIFT,
+	.vlimitto_timeout_shift = OMAP3430_TIMEOUT_SHIFT,
+};
+
+static const struct omap_vp_prm_irqst_data omap3_vp1_prm_irqst_data = {
+	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP3430_VP1_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap3_vp1_data = {
+	.vp_common = &omap3_vp_common,
+	.vpconfig = OMAP3_PRM_VP1_CONFIG_OFFSET,
+	.vstepmin = OMAP3_PRM_VP1_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP3_PRM_VP1_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP3_PRM_VP1_VLIMITTO_OFFSET,
+	.vstatus = OMAP3_PRM_VP1_STATUS_OFFSET,
+	.voltage = OMAP3_PRM_VP1_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap3_vp1_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap3_vp2_prm_irqst_data = {
+	.prm_irqst_reg = OMAP3_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP3430_VP2_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap3_vp2_data = {
+	.vp_common = &omap3_vp_common,
+	.vpconfig = OMAP3_PRM_VP2_CONFIG_OFFSET,
+	.vstepmin = OMAP3_PRM_VP2_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP3_PRM_VP2_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP3_PRM_VP2_VLIMITTO_OFFSET,
+	.vstatus = OMAP3_PRM_VP2_STATUS_OFFSET,
+	.voltage = OMAP3_PRM_VP2_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap3_vp2_prm_irqst_data,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vp44xx_data.c linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vp44xx_data.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vp44xx_data.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vp44xx_data.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * OMAP3 Voltage Processor (VP) data
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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.
+ */
+
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/init.h>
+
+#include <plat/common.h>
+
+#include "prm44xx.h"
+#include "prm-regbits-44xx.h"
+#include "voltage.h"
+
+#include "vp.h"
+
+/*
+ * VP data common to 44xx chips
+ * XXX This stuff presumably belongs in the vp44xx.c or vp.c file.
+ */
+static const struct omap_vp_common_data omap4_vp_common = {
+	.vpconfig_erroroffset_shift = OMAP4430_ERROROFFSET_SHIFT,
+	.vpconfig_errorgain_mask = OMAP4430_ERRORGAIN_MASK,
+	.vpconfig_errorgain_shift = OMAP4430_ERRORGAIN_SHIFT,
+	.vpconfig_initvoltage_shift = OMAP4430_INITVOLTAGE_SHIFT,
+	.vpconfig_initvoltage_mask = OMAP4430_INITVOLTAGE_MASK,
+	.vpconfig_timeouten = OMAP4430_TIMEOUTEN_MASK,
+	.vpconfig_initvdd = OMAP4430_INITVDD_MASK,
+	.vpconfig_forceupdate = OMAP4430_FORCEUPDATE_MASK,
+	.vpconfig_vpenable = OMAP4430_VPENABLE_MASK,
+	.vstepmin_smpswaittimemin_shift = OMAP4430_SMPSWAITTIMEMIN_SHIFT,
+	.vstepmax_smpswaittimemax_shift = OMAP4430_SMPSWAITTIMEMAX_SHIFT,
+	.vstepmin_stepmin_shift = OMAP4430_VSTEPMIN_SHIFT,
+	.vstepmax_stepmax_shift = OMAP4430_VSTEPMAX_SHIFT,
+	.vlimitto_vddmin_shift = OMAP4430_VDDMIN_SHIFT,
+	.vlimitto_vddmax_shift = OMAP4430_VDDMAX_SHIFT,
+	.vlimitto_timeout_shift = OMAP4430_TIMEOUT_SHIFT,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_mpu_prm_irqst_data = {
+	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_2_OFFSET,
+	.tranxdone_status = OMAP4430_VP_MPU_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_mpu_data = {
+	.vp_common = &omap4_vp_common,
+	.vpconfig = OMAP4_PRM_VP_MPU_CONFIG_OFFSET,
+	.vstepmin = OMAP4_PRM_VP_MPU_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP4_PRM_VP_MPU_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP4_PRM_VP_MPU_VLIMITTO_OFFSET,
+	.vstatus = OMAP4_PRM_VP_MPU_STATUS_OFFSET,
+	.voltage = OMAP4_PRM_VP_MPU_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap4_vp_mpu_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_iva_prm_irqst_data = {
+	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP4430_VP_IVA_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_iva_data = {
+	.vp_common = &omap4_vp_common,
+	.vpconfig = OMAP4_PRM_VP_IVA_CONFIG_OFFSET,
+	.vstepmin = OMAP4_PRM_VP_IVA_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP4_PRM_VP_IVA_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP4_PRM_VP_IVA_VLIMITTO_OFFSET,
+	.vstatus = OMAP4_PRM_VP_IVA_STATUS_OFFSET,
+	.voltage = OMAP4_PRM_VP_IVA_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap4_vp_iva_prm_irqst_data,
+};
+
+static const struct omap_vp_prm_irqst_data omap4_vp_core_prm_irqst_data = {
+	.prm_irqst_reg = OMAP4_PRM_IRQSTATUS_MPU_OFFSET,
+	.tranxdone_status = OMAP4430_VP_CORE_TRANXDONE_ST_MASK,
+};
+
+struct omap_vp_instance_data omap4_vp_core_data = {
+	.vp_common = &omap4_vp_common,
+	.vpconfig = OMAP4_PRM_VP_CORE_CONFIG_OFFSET,
+	.vstepmin = OMAP4_PRM_VP_CORE_VSTEPMIN_OFFSET,
+	.vstepmax = OMAP4_PRM_VP_CORE_VSTEPMAX_OFFSET,
+	.vlimitto = OMAP4_PRM_VP_CORE_VLIMITTO_OFFSET,
+	.vstatus = OMAP4_PRM_VP_CORE_STATUS_OFFSET,
+	.voltage = OMAP4_PRM_VP_CORE_VOLTAGE_OFFSET,
+	.prm_irqst_data = &omap4_vp_core_prm_irqst_data,
+};
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vp.h linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vp.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-omap2/vp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-omap2/vp.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,143 @@
+/*
+ * OMAP3/4 Voltage Processor (VP) structure and macro definitions
+ *
+ * Copyright (C) 2007, 2010 Texas Instruments, Inc.
+ * Rajendra Nayak <rnayak@ti.com>
+ * Lesly A M <x0080970@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Copyright (C) 2008, 2011 Nokia Corporation
+ * Kalle Jokiniemi
+ * 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_VP_H
+#define __ARCH_ARM_MACH_OMAP2_VP_H
+
+#include <linux/kernel.h>
+
+/* XXX document */
+#define VP_IDLE_TIMEOUT		200
+#define VP_TRANXDONE_TIMEOUT	300
+
+
+/**
+ * struct omap_vp_common_data - register data common to all VDDs
+ * @vpconfig_errorgain_mask: ERRORGAIN bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_initvoltage_mask: INITVOLTAGE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_timeouten_mask: TIMEOUT bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_initvdd: INITVDD bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_forceupdate: FORCEUPDATE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_vpenable: VPENABLE bitmask in the PRM_VP*_CONFIG reg
+ * @vpconfig_erroroffset_shift: ERROROFFSET field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_errorgain_shift: ERRORGAIN field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_initvoltage_shift: INITVOLTAGE field shift in PRM_VP*_CONFIG reg
+ * @vpconfig_stepmin_shift: VSTEPMIN field shift in the PRM_VP*_VSTEPMIN reg
+ * @vpconfig_smpswaittimemin_shift: SMPSWAITTIMEMIN field shift in PRM_VP*_VSTEPMIN reg
+ * @vpconfig_stepmax_shift: VSTEPMAX field shift in the PRM_VP*_VSTEPMAX reg
+ * @vpconfig_smpswaittimemax_shift: SMPSWAITTIMEMAX field shift in PRM_VP*_VSTEPMAX reg
+ * @vpconfig_vlimitto_vddmin_shift: VDDMIN field shift in PRM_VP*_VLIMITTO reg
+ * @vpconfig_vlimitto_vddmax_shift: VDDMAX field shift in PRM_VP*_VLIMITTO reg
+ * @vpconfig_vlimitto_timeout_shift: TIMEOUT field shift in PRM_VP*_VLIMITTO reg
+ *
+ * XXX It it not necessary to have both a mask and a shift for the same
+ *     bitfield - remove one
+ * XXX Many of these fields are wrongly named -- e.g., vpconfig_smps* -- fix!
+ */
+struct omap_vp_common_data {
+	u32 vpconfig_errorgain_mask;
+	u32 vpconfig_initvoltage_mask;
+	u32 vpconfig_timeouten;
+	u32 vpconfig_initvdd;
+	u32 vpconfig_forceupdate;
+	u32 vpconfig_vpenable;
+	u8 vpconfig_erroroffset_shift;
+	u8 vpconfig_errorgain_shift;
+	u8 vpconfig_initvoltage_shift;
+	u8 vstepmin_stepmin_shift;
+	u8 vstepmin_smpswaittimemin_shift;
+	u8 vstepmax_stepmax_shift;
+	u8 vstepmax_smpswaittimemax_shift;
+	u8 vlimitto_vddmin_shift;
+	u8 vlimitto_vddmax_shift;
+	u8 vlimitto_timeout_shift;
+};
+
+/**
+ * struct omap_vp_prm_irqst_data - PRM_IRQSTATUS_MPU.VP_TRANXDONE_ST data
+ * @prm_irqst_reg: reg offset for PRM_IRQSTATUS_MPU from top of PRM
+ * @tranxdone_status: VP_TRANXDONE_ST bitmask in PRM_IRQSTATUS_MPU reg
+ *
+ * XXX prm_irqst_reg does not belong here
+ * XXX Note that on OMAP3, VP_TRANXDONE interrupt may not work due to a
+ *     hardware bug
+ * XXX This structure is probably not needed
+ */
+struct omap_vp_prm_irqst_data {
+	u8 prm_irqst_reg;
+	u32 tranxdone_status;
+};
+
+/**
+ * struct omap_vp_instance_data - VP register offsets (per-VDD)
+ * @vp_common: pointer to struct omap_vp_common_data * for this SoC
+ * @prm_irqst_data: pointer to struct omap_vp_prm_irqst_data for this VDD
+ * @vpconfig: PRM_VP*_CONFIG reg offset from PRM start
+ * @vstepmin: PRM_VP*_VSTEPMIN reg offset from PRM start
+ * @vlimitto: PRM_VP*_VLIMITTO reg offset from PRM start
+ * @vstatus: PRM_VP*_VSTATUS reg offset from PRM start
+ * @voltage: PRM_VP*_VOLTAGE reg offset from PRM start
+ *
+ * XXX vp_common is probably not needed since it is per-SoC
+ */
+struct omap_vp_instance_data {
+	const struct omap_vp_common_data *vp_common;
+	const struct omap_vp_prm_irqst_data *prm_irqst_data;
+	u8 vpconfig;
+	u8 vstepmin;
+	u8 vstepmax;
+	u8 vlimitto;
+	u8 vstatus;
+	u8 voltage;
+};
+
+/**
+ * struct omap_vp_runtime_data - VP data populated at runtime by code
+ * @vpconfig_erroroffset: value of ERROROFFSET bitfield in PRM_VP*_CONFIG
+ * @vpconfig_errorgain: value of ERRORGAIN bitfield in PRM_VP*_CONFIG
+ * @vstepmin_smpswaittimemin: value of SMPSWAITTIMEMIN bitfield in PRM_VP*_VSTEPMIN
+ * @vstepmax_smpswaittimemax: value of SMPSWAITTIMEMAX bitfield in PRM_VP*_VSTEPMAX
+ * @vlimitto_timeout: value of TIMEOUT bitfield in PRM_VP*_VLIMITTO
+ * @vstepmin_stepmin: value of VSTEPMIN bitfield in PRM_VP*_VSTEPMIN
+ * @vstepmax_stepmax: value of VSTEPMAX bitfield in PRM_VP*_VSTEPMAX
+ * @vlimitto_vddmin: value of VDDMIN bitfield in PRM_VP*_VLIMITTO
+ * @vlimitto_vddmax: value of VDDMAX bitfield in PRM_VP*_VLIMITTO
+ *
+ * XXX Is this structure really needed?  Why not just program the
+ * device directly?  They are in PRM space, therefore in the WKUP
+ * powerdomain, so register contents should not be lost in off-mode.
+ * XXX Some of these fields are incorrectly named, e.g., vstep*
+ */
+struct omap_vp_runtime_data {
+	u32 vpconfig_erroroffset;
+	u16 vpconfig_errorgain;
+	u16 vstepmin_smpswaittimemin;
+	u16 vstepmax_smpswaittimemax;
+	u16 vlimitto_timeout;
+	u8 vstepmin_stepmin;
+	u8 vstepmax_stepmax;
+	u8 vlimitto_vddmin;
+	u8 vlimitto_vddmax;
+};
+
+extern struct omap_vp_instance_data omap3_vp1_data;
+extern struct omap_vp_instance_data omap3_vp2_data;
+
+extern struct omap_vp_instance_data omap4_vp_mpu_data;
+extern struct omap_vp_instance_data omap4_vp_iva_data;
+extern struct omap_vp_instance_data omap4_vp_core_data;
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/addr-map.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/addr-map.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/addr-map.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/addr-map.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 #include "common.h"
 
 /*
- * The Orion has fully programable address map. There's a separate address
+ * The Orion has fully programmable address map. There's a separate address
  * map for each of the device _master_ interfaces, e.g. CPU, PCI, PCIe, USB,
  * Gigabit Ethernet, DMA/XOR engines, etc. Each interface has its own
  * address decode windows that allow it to access any of the Orion resources.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/common.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
+#include <mach/bridge-regs.h>
 #include <mach/hardware.h>
 #include <mach/orion5x.h>
 #include <plat/ehci-orion.h>
@@ -599,6 +600,11 @@
 /*****************************************************************************
  * Time handling
  ****************************************************************************/
+void __init orion5x_init_early(void)
+{
+	orion_time_set_base(TIMER_VIRT_BASE);
+}
+
 int orion5x_tclk;
 
 int __init orion5x_find_tclk(void)
@@ -616,7 +622,9 @@
 static void orion5x_timer_init(void)
 {
 	orion5x_tclk = orion5x_find_tclk();
-	orion_time_init(IRQ_ORION5X_BRIDGE, orion5x_tclk);
+
+	orion_time_init(ORION5X_BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
+			IRQ_ORION5X_BRIDGE, orion5x_tclk);
 }
 
 struct sys_timer orion5x_timer = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/common.h linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
  * Basic Orion init functions used early by machine-setup.
  */
 void orion5x_map_io(void);
+void orion5x_init_early(void);
 void orion5x_init_irq(void);
 void orion5x_init(void);
 extern int orion5x_tclk;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/d2net-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/d2net-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/d2net-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/d2net-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -339,6 +339,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
@@ -350,6 +351,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= d2net_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/db88f5281-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/db88f5281-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/db88f5281-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/db88f5281-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -213,7 +213,7 @@
 	pin = DB88F5281_PCI_SLOT0_IRQ_PIN;
 	if (gpio_request(pin, "PCI Int1") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "db88f5281_pci_preinit faield to "
 					"set_irq_type pin %d\n", pin);
@@ -226,7 +226,7 @@
 	pin = DB88F5281_PCI_SLOT1_SLOT2_IRQ_PIN;
 	if (gpio_request(pin, "PCI Int2") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "db88f5281_pci_preinit faield "
 					"to set_irq_type pin %d\n", pin);
@@ -361,6 +361,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= db88f5281_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/dns323-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/dns323-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/dns323-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/dns323-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -733,6 +733,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= dns323_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/edmini_v2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -254,6 +254,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= edmini_v2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/bridge-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,14 +22,12 @@
 
 #define CPU_SOFT_RESET		(ORION5X_BRIDGE_VIRT_BASE | 0x10c)
 
+#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x110)
+
 #define POWER_MNG_CTRL_REG	(ORION5X_BRIDGE_VIRT_BASE | 0x11C)
 
-#define BRIDGE_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x110)
 #define WDT_INT_REQ		0x0008
 
-#define BRIDGE_MASK		(ORION5X_BRIDGE_VIRT_BASE | 0x114)
-#define BRIDGE_INT_TIMER0	0x0002
-#define BRIDGE_INT_TIMER1	0x0004
 #define BRIDGE_INT_TIMER1_CLR	(~0x0004)
 
 #define MAIN_IRQ_CAUSE		(ORION5X_BRIDGE_VIRT_BASE | 0x200)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,32 +6,4 @@
  * warranty of any kind, whether express or implied.
  */
 
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H
-
-#include <mach/irqs.h>
 #include <plat/gpio.h>
-#include <asm-generic/gpio.h>		/* cansleep wrappers */
-
-#define GPIO_MAX		32
-#define GPIO_OUT(pin)		ORION5X_DEV_BUS_REG(0x100)
-#define GPIO_IO_CONF(pin)	ORION5X_DEV_BUS_REG(0x104)
-#define GPIO_BLINK_EN(pin)	ORION5X_DEV_BUS_REG(0x108)
-#define GPIO_IN_POL(pin)	ORION5X_DEV_BUS_REG(0x10c)
-#define GPIO_DATA_IN(pin)	ORION5X_DEV_BUS_REG(0x110)
-#define GPIO_EDGE_CAUSE(pin)	ORION5X_DEV_BUS_REG(0x114)
-#define GPIO_EDGE_MASK(pin)	ORION5X_DEV_BUS_REG(0x118)
-#define GPIO_LEVEL_MASK(pin)	ORION5X_DEV_BUS_REG(0x11c)
-
-static inline int gpio_to_irq(int pin)
-{
-	return pin + IRQ_ORION5X_GPIO_START;
-}
-
-static inline int irq_to_gpio(int irq)
-{
-	return irq - IRQ_ORION5X_GPIO_START;
-}
-
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/include/mach/orion5x.h	2011-05-19 00:06:34.000000000 -0400
@@ -73,6 +73,7 @@
 #define ORION5X_DEV_BUS_PHYS_BASE	(ORION5X_REGS_PHYS_BASE | 0x10000)
 #define ORION5X_DEV_BUS_VIRT_BASE	(ORION5X_REGS_VIRT_BASE | 0x10000)
 #define ORION5X_DEV_BUS_REG(x)		(ORION5X_DEV_BUS_VIRT_BASE | (x))
+#define  GPIO_VIRT_BASE			ORION5X_DEV_BUS_REG(0x0100)
 #define  SPI_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x0600)
 #define  I2C_PHYS_BASE			(ORION5X_DEV_BUS_PHYS_BASE | 0x1000)
 #define  UART0_PHYS_BASE		(ORION5X_DEV_BUS_PHYS_BASE | 0x2000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,29 +28,14 @@
 
 void __init orion5x_init_irq(void)
 {
-	int i;
-
 	orion_irq_init(0, (void __iomem *)MAIN_IRQ_MASK);
 
 	/*
-	 * Mask and clear GPIO IRQ interrupts
-	 */
-	writel(0x0, GPIO_LEVEL_MASK(0));
-	writel(0x0, GPIO_EDGE_MASK(0));
-	writel(0x0, GPIO_EDGE_CAUSE(0));
-
-	/*
-	 * Register chained level handlers for GPIO IRQs by default.
-	 * User can use set_type() if he wants to use edge types handlers.
+	 * Initialize gpiolib for GPIOs 0-31.
 	 */
-	for (i = IRQ_ORION5X_GPIO_START; i < NR_IRQS; i++) {
-		set_irq_chip(i, &orion_gpio_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-		irq_desc[i].status |= IRQ_LEVEL;
-		set_irq_flags(i, IRQF_VALID);
-	}
-	set_irq_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
-	set_irq_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
+	orion_gpio_init(0, 32, GPIO_VIRT_BASE, 0, IRQ_ORION5X_GPIO_START);
+	irq_set_chained_handler(IRQ_ORION5X_GPIO_0_7, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_ORION5X_GPIO_8_15, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_ORION5X_GPIO_16_23, gpio_irq_handler);
+	irq_set_chained_handler(IRQ_ORION5X_GPIO_24_31, gpio_irq_handler);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/kurobox_pro-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -382,6 +382,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
@@ -394,6 +395,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= kurobox_pro_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ls-chl-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ls-chl-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ls-chl-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ls-chl-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -321,6 +321,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= lschl_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ls_hgl-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -268,6 +268,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= ls_hgl_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/lsmini-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/lsmini-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/lsmini-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/lsmini-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -270,6 +270,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= lsmini_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/mpp.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/mpp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/mpp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/mpp.c	2011-05-19 00:06:34.000000000 -0400
@@ -124,9 +124,6 @@
 	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();
-
 	for ( ; mode->mpp >= 0; mode++) {
 		u32 *reg;
 		int num_type;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/mss2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/mss2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/mss2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/mss2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -264,6 +264,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= mss2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/mv2120-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/mv2120-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/mv2120-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/mv2120-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -232,6 +232,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= mv2120_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/net2big-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/net2big-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/net2big-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/net2big-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -190,7 +190,7 @@
  * The power front LEDs (blue and red) and SATA red LEDs are controlled via a
  * single GPIO line and are compatible with the leds-gpio driver.
  *
- * The SATA blue LEDs have some hardware blink capabilities which are detailled
+ * The SATA blue LEDs have some hardware blink capabilities which are detailed
  * in the following array:
  *
  * SATAx blue LED | SATAx activity | LED state
@@ -422,6 +422,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= net2big_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -172,6 +172,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5181l_fxo_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -184,6 +184,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5181l_ge_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f5182-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,7 +148,7 @@
 	pin = RD88F5182_PCI_SLOT0_IRQ_A_PIN;
 	if (gpio_request(pin, "PCI IntA") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "rd88f5182_pci_preinit faield to "
 					"set_irq_type pin %d\n", pin);
@@ -161,7 +161,7 @@
 	pin = RD88F5182_PCI_SLOT0_IRQ_B_PIN;
 	if (gpio_request(pin, "PCI IntB") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "rd88f5182_pci_preinit faield to "
 					"set_irq_type pin %d\n", pin);
@@ -308,6 +308,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f5182_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -126,6 +126,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= rd88f6183ap_ge_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/terastation_pro2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 	pin = TSP2_PCI_SLOT0_IRQ_PIN;
 	if (gpio_request(pin, "PCI Int1") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "tsp2_pci_preinit failed "
 					"to set_irq_type pin %d\n", pin);
@@ -361,6 +361,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= tsp2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts209-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts209-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts209-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts209-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 
 /****************************************************************************
  * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
- *     partitions on the device because we want to keep compatability with
+ *     partitions on the device because we want to keep compatibility with
  *     existing QNAP firmware.
  *
  * Layout as used by QNAP:
@@ -117,7 +117,7 @@
 	pin = QNAP_TS209_PCI_SLOT0_IRQ_PIN;
 	if (gpio_request(pin, "PCI Int1") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "qnap_ts209_pci_preinit failed to "
 					"set_irq_type pin %d\n", pin);
@@ -131,7 +131,7 @@
 	pin = QNAP_TS209_PCI_SLOT1_IRQ_PIN;
 	if (gpio_request(pin, "PCI Int2") == 0) {
 		if (gpio_direction_input(pin) == 0) {
-			set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(gpio_to_irq(pin), IRQ_TYPE_LEVEL_LOW);
 		} else {
 			printk(KERN_ERR "qnap_ts209_pci_preinit failed "
 					"to set_irq_type pin %d\n", pin);
@@ -325,6 +325,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts209_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts409-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts409-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts409-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts409-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
 
 /****************************************************************************
  * 8MiB NOR flash. The struct mtd_partition is not in the same order as the
- *     partitions on the device because we want to keep compatability with
+ *     partitions on the device because we want to keep compatibility with
  *     existing QNAP firmware.
  *
  * Layout as used by QNAP:
@@ -314,6 +314,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= qnap_ts409_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts78xx-fpga.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,3 +1,4 @@
+#define TS7800_FPGA_MAGIC 0x00b480
 #define FPGAID(_magic, _rev) ((_magic << 8) + _rev)
 
 /*
@@ -6,11 +7,15 @@
  */
 enum fpga_ids {
 	/* Technologic Systems */
-	TS7800_REV_1	= FPGAID(0x00b480, 0x01),
-	TS7800_REV_2	= FPGAID(0x00b480, 0x02),
-	TS7800_REV_3	= FPGAID(0x00b480, 0x03),
-	TS7800_REV_4	= FPGAID(0x00b480, 0x04),
-	TS7800_REV_5	= FPGAID(0x00b480, 0x05),
+	TS7800_REV_1	= FPGAID(TS7800_FPGA_MAGIC, 0x01),
+	TS7800_REV_2	= FPGAID(TS7800_FPGA_MAGIC, 0x02),
+	TS7800_REV_3	= FPGAID(TS7800_FPGA_MAGIC, 0x03),
+	TS7800_REV_4	= FPGAID(TS7800_FPGA_MAGIC, 0x04),
+	TS7800_REV_5	= FPGAID(TS7800_FPGA_MAGIC, 0x05),
+	TS7800_REV_6	= FPGAID(TS7800_FPGA_MAGIC, 0x06),
+	TS7800_REV_7	= FPGAID(TS7800_FPGA_MAGIC, 0x07),
+	TS7800_REV_8	= FPGAID(TS7800_FPGA_MAGIC, 0x08),
+	TS7800_REV_9	= FPGAID(TS7800_FPGA_MAGIC, 0x09),
 
 	/* Unaffordable & Expensive */
 	UAE_DUMMY	= FPGAID(0xffffff, 0x01),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts78xx-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts78xx-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/ts78xx-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/ts78xx-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -191,6 +191,60 @@
 	return readb(TS_NAND_CTRL) & 0x20;
 }
 
+static void ts78xx_ts_nand_write_buf(struct mtd_info *mtd,
+			const uint8_t *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	void __iomem *io_base = chip->IO_ADDR_W;
+	unsigned long off = ((unsigned long)buf & 3);
+	int sz;
+
+	if (off) {
+		sz = min_t(int, 4 - off, len);
+		writesb(io_base, buf, sz);
+		buf += sz;
+		len -= sz;
+	}
+
+	sz = len >> 2;
+	if (sz) {
+		u32 *buf32 = (u32 *)buf;
+		writesl(io_base, buf32, sz);
+		buf += sz << 2;
+		len -= sz << 2;
+	}
+
+	if (len)
+		writesb(io_base, buf, len);
+}
+
+static void ts78xx_ts_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;
+	unsigned long off = ((unsigned long)buf & 3);
+	int sz;
+
+	if (off) {
+		sz = min_t(int, 4 - off, len);
+		readsb(io_base, buf, sz);
+		buf += sz;
+		len -= sz;
+	}
+
+	sz = len >> 2;
+	if (sz) {
+		u32 *buf32 = (u32 *)buf;
+		readsl(io_base, buf32, sz);
+		buf += sz << 2;
+		len -= sz << 2;
+	}
+
+	if (len)
+		readsb(io_base, buf, len);
+}
+
 const char *ts_nand_part_probes[] = { "cmdlinepart", NULL };
 
 static struct mtd_partition ts78xx_ts_nand_parts[] = {
@@ -233,6 +287,8 @@
 		 */
 		.cmd_ctrl		= ts78xx_ts_nand_cmd_ctrl,
 		.dev_ready		= ts78xx_ts_nand_dev_ready,
+		.write_buf		= ts78xx_ts_nand_write_buf,
+		.read_buf		= ts78xx_ts_nand_read_buf,
 	},
 };
 
@@ -334,14 +390,29 @@
 	case TS7800_REV_3:
 	case TS7800_REV_4:
 	case TS7800_REV_5:
+	case TS7800_REV_6:
+	case TS7800_REV_7:
+	case TS7800_REV_8:
+	case TS7800_REV_9:
 		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;
+		/* enable devices if magic matches */
+		switch ((ts78xx_fpga.id >> 8) & 0xffffff) {
+		case TS7800_FPGA_MAGIC:
+			pr_warning("TS-7800 FPGA: unrecognized revision 0x%.2x\n",
+					ts78xx_fpga.id & 0xff);
+			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;
+		}
 	}
 }
 
@@ -352,7 +423,7 @@
 	if (ts78xx_fpga.supports.ts_rtc.present == 1) {
 		tmp = ts78xx_ts_rtc_load();
 		if (tmp) {
-			printk(KERN_INFO "TS-78xx: RTC not registered\n");
+			pr_info("TS-78xx: RTC not registered\n");
 			ts78xx_fpga.supports.ts_rtc.present = 0;
 		}
 		ret |= tmp;
@@ -360,7 +431,7 @@
 	if (ts78xx_fpga.supports.ts_nand.present == 1) {
 		tmp = ts78xx_ts_nand_load();
 		if (tmp) {
-			printk(KERN_INFO "TS-78xx: NAND not registered\n");
+			pr_info("TS-78xx: NAND not registered\n");
 			ts78xx_fpga.supports.ts_nand.present = 0;
 		}
 		ret |= tmp;
@@ -368,7 +439,7 @@
 	if (ts78xx_fpga.supports.ts_rng.present == 1) {
 		tmp = ts78xx_ts_rng_load();
 		if (tmp) {
-			printk(KERN_INFO "TS-78xx: RNG not registered\n");
+			pr_info("TS-78xx: RNG not registered\n");
 			ts78xx_fpga.supports.ts_rng.present = 0;
 		}
 		ret |= tmp;
@@ -395,7 +466,7 @@
 {
 	ts78xx_fpga.id = readl(TS78XX_FPGA_REGS_VIRT_BASE);
 
-	printk(KERN_INFO "TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n",
+	pr_info("TS-78xx FPGA: magic=0x%.6x, rev=0x%.2x\n",
 			(ts78xx_fpga.id >> 8) & 0xffffff,
 			ts78xx_fpga.id & 0xff);
 
@@ -423,7 +494,7 @@
 	 * UrJTAG SVN since r1381 can be used to reprogram the FPGA
 	 */
 	if (ts78xx_fpga.id != fpga_id) {
-		printk(KERN_ERR	"TS-78xx FPGA: magic/rev mismatch\n"
+		pr_err("TS-78xx FPGA: magic/rev mismatch\n"
 			"TS-78xx FPGA: was 0x%.6x/%.2x but now 0x%.6x/%.2x\n",
 			(ts78xx_fpga.id >> 8) & 0xffffff, ts78xx_fpga.id & 0xff,
 			(fpga_id >> 8) & 0xffffff, fpga_id & 0xff);
@@ -454,7 +525,7 @@
 	int value, ret;
 
 	if (ts78xx_fpga.state < 0) {
-		printk(KERN_ERR "TS-78xx FPGA: borked, you must powercycle asap\n");
+		pr_err("TS-78xx FPGA: borked, you must powercycle asap\n");
 		return -EBUSY;
 	}
 
@@ -463,7 +534,7 @@
 	else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
 		value = 0;
 	else {
-		printk(KERN_ERR "ts78xx_fpga_store: Invalid value\n");
+		pr_err("ts78xx_fpga_store: Invalid value\n");
 		return -EINVAL;
 	}
 
@@ -545,7 +616,7 @@
 	ret = ts78xx_fpga_load();
 	ret = sysfs_create_file(power_kobj, &ts78xx_fpga_attr.attr);
 	if (ret)
-		printk(KERN_ERR "sysfs_create_file failed: %d\n", ret);
+		pr_err("sysfs_create_file failed: %d\n", ret);
 }
 
 MACHINE_START(TS78XX, "Technologic Systems TS-78xx SBC")
@@ -553,6 +624,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= ts78xx_init,
 	.map_io		= ts78xx_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/wnr854t-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/wnr854t-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/wnr854t-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/wnr854t-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -175,6 +175,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= wnr854t_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-orion5x/wrt350n-v2-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -263,6 +263,7 @@
 	.boot_params	= 0x00000100,
 	.init_machine	= wrt350n_v2_init,
 	.map_io		= orion5x_map_io,
+	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
 	.timer		= &orion5x_timer,
 	.fixup		= tag_fixup_mem32,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pnx4008/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-pnx4008/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pnx4008/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pnx4008/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x80000000)
+#define PLAT_PHYS_OFFSET	UL(0x80000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pnx4008/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-pnx4008/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pnx4008/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pnx4008/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,22 +58,22 @@
 	case IRQ_TYPE_EDGE_RISING:
 		__raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));	/*edge sensitive */
 		__raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));	/*rising edge */
-		set_irq_handler(d->irq, handle_edge_irq);
+		irq_set_handler(d->irq, handle_edge_irq);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
 		__raw_writel(__raw_readl(INTC_ATR(d->irq)) | INTC_BIT(d->irq), INTC_ATR(d->irq));	/*edge sensitive */
 		__raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));	/*falling edge */
-		set_irq_handler(d->irq, handle_edge_irq);
+		irq_set_handler(d->irq, handle_edge_irq);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
 		__raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));	/*level sensitive */
 		__raw_writel(__raw_readl(INTC_APR(d->irq)) & ~INTC_BIT(d->irq), INTC_APR(d->irq));	/*low level */
-		set_irq_handler(d->irq, handle_level_irq);
+		irq_set_handler(d->irq, handle_level_irq);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
 		__raw_writel(__raw_readl(INTC_ATR(d->irq)) & ~INTC_BIT(d->irq), INTC_ATR(d->irq));	/*level sensitive */
 		__raw_writel(__raw_readl(INTC_APR(d->irq)) | INTC_BIT(d->irq), INTC_APR(d->irq));	/* high level */
-		set_irq_handler(d->irq, handle_level_irq);
+		irq_set_handler(d->irq, handle_level_irq);
 		break;
 
 	/* IRQ_TYPE_EDGE_BOTH is not supported */
@@ -98,7 +98,7 @@
 	/* configure IRQ's */
 	for (i = 0; i < NR_IRQS; i++) {
 		set_irq_flags(i, IRQF_VALID);
-		set_irq_chip(i, &pnx4008_irq_chip);
+		irq_set_chip(i, &pnx4008_irq_chip);
 		pnx4008_set_irq_type(irq_get_irq_data(i), pnx4008_irq_type[i]);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/am200epd.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/am200epd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/am200epd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/am200epd.c	2011-05-19 00:06:34.000000000 -0400
@@ -128,8 +128,8 @@
 	return 0;
 
 err_req_gpio:
-	while (i > 0)
-		gpio_free(gpios[i--]);
+	while (--i >= 0)
+		gpio_free(gpios[i]);
 
 	return err;
 }
@@ -194,7 +194,7 @@
 };
 
 /* this gets called as part of our init. these steps must be done now so
- * that we can use set_pxa_fb_info */
+ * that we can use pxa_set_fb_info */
 static void __init am200_presetup_fb(void)
 {
 	int fw;
@@ -249,7 +249,7 @@
 	/* we divide since we told the LCD controller we're 16bpp */
 	am200_fb_info.modes->xres /= 2;
 
-	set_pxa_fb_info(&am200_fb_info);
+	pxa_set_fb_info(NULL, &am200_fb_info);
 
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/am300epd.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/am300epd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/am300epd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/am300epd.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,10 +125,7 @@
 		if (err) {
 			dev_err(&am300_device->dev, "failed requesting "
 				"gpio %d, err=%d\n", i, err);
-			while (i >= DB0_GPIO_PIN)
-				gpio_free(i--);
-			i = ARRAY_SIZE(gpios) - 1;
-			goto err_req_gpio;
+			goto err_req_gpio2;
 		}
 	}
 
@@ -159,9 +156,13 @@
 
 	return 0;
 
+err_req_gpio2:
+	while (--i >= DB0_GPIO_PIN)
+		gpio_free(i);
+	i = ARRAY_SIZE(gpios);
 err_req_gpio:
-	while (i > 0)
-		gpio_free(gpios[i--]);
+	while (--i >= 0)
+		gpio_free(gpios[i]);
 
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/balloon3.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/balloon3.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/balloon3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/balloon3.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/types.h>
 #include <linux/i2c/pcf857x.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/max1586.h>
@@ -51,8 +52,6 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
@@ -264,7 +263,7 @@
 	}
 
 	balloon3_lcd_screen.pxafb_backlight_power = balloon3_backlight_power;
-	set_pxa_fb_info(&balloon3_lcd_screen);
+	pxa_set_fb_info(NULL, &balloon3_lcd_screen);
 	return;
 
 err2:
@@ -528,13 +527,13 @@
 	pxa27x_init_irq();
 	/* setup extra Balloon3 irqs */
 	for (irq = BALLOON3_IRQ(0); irq <= BALLOON3_IRQ(7); irq++) {
-		set_irq_chip(irq, &balloon3_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &balloon3_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	set_irq_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
-	set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);
+	irq_set_chained_handler(BALLOON3_AUX_NIRQ, balloon3_irq_handler);
+	irq_set_irq_type(BALLOON3_AUX_NIRQ, IRQ_TYPE_EDGE_FALLING);
 
 	pr_debug("%s: chained handler installed - irq %d automatically "
 		"enabled\n", __func__, BALLOON3_AUX_NIRQ);
@@ -829,5 +828,5 @@
 	.init_irq	= balloon3_init_irq,
 	.timer		= &pxa_timer,
 	.init_machine	= balloon3_init,
-	.boot_params	= PHYS_OFFSET + 0x100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x100,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/cm-x2xx.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/cm-x2xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/cm-x2xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/cm-x2xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -379,7 +379,7 @@
 
 static void __init cmx2xx_init_display(void)
 {
-	set_pxa_fb_info(cmx2xx_display);
+	pxa_set_fb_info(NULL, cmx2xx_display);
 }
 #else
 static inline void cmx2xx_init_display(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/cm-x2xx-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -70,9 +70,10 @@
 
 	cmx2xx_it8152_irq_gpio = irq_gpio;
 
-	set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(irq_gpio), IRQ_TYPE_EDGE_RISING);
 
-	set_irq_chained_handler(gpio_to_irq(irq_gpio), cmx2xx_it8152_irq_demux);
+	irq_set_chained_handler(gpio_to_irq(irq_gpio),
+				cmx2xx_it8152_irq_demux);
 }
 
 #ifdef CONFIG_PM
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/cm-x300.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/cm-x300.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/cm-x300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/cm-x300.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <linux/mfd/da903x.h>
 #include <linux/regulator/machine.h>
@@ -48,7 +49,6 @@
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 #include <mach/audio.h>
 #include <mach/pxa3xx-u2d.h>
@@ -296,7 +296,7 @@
 
 static void __init cm_x300_init_lcd(void)
 {
-	set_pxa_fb_info(&cm_x300_lcd);
+	pxa_set_fb_info(NULL, &cm_x300_lcd);
 }
 #else
 static inline void cm_x300_init_lcd(void) {}
@@ -765,7 +765,7 @@
 {
 	pxa3xx_set_i2c_power_info(&cm_x300_pwr_i2c_info);
 	i2c_register_board_info(1, &cm_x300_pmic_info, 1);
-	set_irq_wake(IRQ_WAKEUP0, 1);
+	irq_set_irq_wake(IRQ_WAKEUP0, 1);
 }
 
 static void __init cm_x300_init_wi2wi(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/colibri-evalboard.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/colibri-evalboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/colibri-evalboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/colibri-evalboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #include <mach/hardware.h>
 #include <asm/mach/arch.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <mach/pxa27x.h>
 #include <mach/colibri.h>
@@ -27,8 +28,6 @@
 #include <mach/ohci.h>
 #include <mach/pxa27x-udc.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/colibri-pxa270-income.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/colibri-pxa270-income.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/colibri-pxa270-income.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/colibri-pxa270-income.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
 #include <linux/pwm_backlight.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/sysdev.h>
 
 #include <asm/irq.h>
@@ -33,8 +34,6 @@
 #include <mach/pxa27x-udc.h>
 #include <mach/pxafb.h>
 
-#include <plat/i2c.h>
-
 #include "devices.h"
 #include "generic.h"
 
@@ -176,7 +175,7 @@
 
 static void __init income_lcd_init(void)
 {
-	set_pxa_fb_info(&income_lcd_screen);
+	pxa_set_fb_info(NULL, &income_lcd_screen);
 }
 #else
 static inline void income_lcd_init(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/colibri-pxa3xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,7 +105,7 @@
 	lcd_bl_pin = bl_pin;
 	gpio_request(bl_pin, "lcd backlight");
 	gpio_direction_output(bl_pin, 0);
-	set_pxa_fb_info(&sharp_lq43_info);
+	pxa_set_fb_info(NULL, &sharp_lq43_info);
 }
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/corgi.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/corgi.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/corgi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/corgi.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/gpio.h>
 #include <linux/backlight.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/io.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -45,7 +46,6 @@
 #include <asm/mach/irq.h>
 
 #include <mach/pxa25x.h>
-#include <plat/i2c.h>
 #include <mach/irda.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
@@ -462,7 +462,6 @@
  * USB Device Controller
  */
 static struct pxa2xx_udc_mach_info udc_info __initdata = {
-	.gpio_vbus		= -1,
 	/* no connect GPIO; corgi can't tell connection status */
 	.gpio_pullup		= CORGI_GPIO_USB_PULLUP,
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/csb726.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/csb726.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/csb726.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/csb726.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,12 +17,12 @@
 #include <linux/mtd/partitions.h>
 #include <linux/sm501.h>
 #include <linux/smsc911x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <mach/csb726.h>
 #include <mach/mfp-pxa27x.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/ohci.h>
 #include <mach/pxa2xx-regs.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,6 +4,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/spi/pxa2xx_spi.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/pmu.h>
 #include <mach/udc.h>
@@ -16,7 +17,6 @@
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <mach/hardware.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "devices.h"
@@ -90,7 +90,6 @@
 
 static struct pxa2xx_udc_mach_info pxa_udc_info = {
 	.gpio_pullup = -1,
-	.gpio_vbus   = -1,
 };
 
 void __init pxa_set_udc_info(struct pxa2xx_udc_mach_info *info)
@@ -188,16 +187,12 @@
 	.resource	= pxafb_resources,
 };
 
-void __init set_pxa_fb_info(struct pxafb_mach_info *info)
+void __init pxa_set_fb_info(struct device *parent, struct pxafb_mach_info *info)
 {
+	pxa_device_fb.dev.parent = parent;
 	pxa_register_device(&pxa_device_fb, info);
 }
 
-void __init set_pxa_fb_parent(struct device *parent_dev)
-{
-	pxa_device_fb.dev.parent = parent_dev;
-}
-
 static struct resource pxa_resource_ffuart[] = {
 	{
 		.start	= 0x40100000,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/em-x270.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/em-x270.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/em-x270.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/em-x270.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/apm-emulation.h>
 #include <linux/i2c.h>
 #include <linux/i2c/pca953x.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/regulator/userspace-consumer.h>
 
 #include <media/soc_camera.h>
@@ -45,7 +46,6 @@
 #include <mach/ohci.h>
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
-#include <plat/i2c.h>
 #include <mach/camera.h>
 
 #include "generic.h"
@@ -689,7 +689,7 @@
 
 static void __init em_x270_init_lcd(void)
 {
-	set_pxa_fb_info(&em_x270_lcd);
+	pxa_set_fb_info(NULL, &em_x270_lcd);
 }
 #else
 static inline void em_x270_init_lcd(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/eseries.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/eseries.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/eseries.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/eseries.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/mfd/t7l66xb.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/partitions.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <video/w100fb.h>
 
@@ -51,12 +52,20 @@
 		mi->bank[0].size = (64*1024*1024);
 }
 
-struct pxa2xx_udc_mach_info e7xx_udc_mach_info = {
+struct gpio_vbus_mach_info e7xx_udc_info = {
 	.gpio_vbus   = GPIO_E7XX_USB_DISC,
 	.gpio_pullup = GPIO_E7XX_USB_PULLUP,
 	.gpio_pullup_inverted = 1
 };
 
+static struct platform_device e7xx_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &e7xx_udc_info,
+	},
+};
+
 struct pxaficp_platform_data e7xx_ficp_platform_data = {
 	.gpio_pwdown		= GPIO_E7XX_IR_OFF,
 	.transceiver_cap	= IR_SIRMODE | IR_OFF,
@@ -165,6 +174,7 @@
 
 static struct platform_device *e330_devices[] __initdata = {
 	&e330_tc6387xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e330_init(void)
@@ -175,7 +185,6 @@
 	eseries_register_clks();
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e330_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 }
 
 MACHINE_START(E330, "Toshiba e330")
@@ -214,6 +223,7 @@
 
 static struct platform_device *e350_devices[] __initdata = {
 	&e350_t7l66xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e350_init(void)
@@ -224,7 +234,6 @@
 	eseries_register_clks();
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e350_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 }
 
 MACHINE_START(E350, "Toshiba e350")
@@ -333,6 +342,7 @@
 
 static struct platform_device *e400_devices[] __initdata = {
 	&e400_t7l66xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e400_init(void)
@@ -344,9 +354,8 @@
 	/* Fixme - e400 may have a switched clock */
 	eseries_register_clks();
 	eseries_get_tmio_gpios();
-	set_pxa_fb_info(&e400_pxafb_mach_info);
+	pxa_set_fb_info(NULL, &e400_pxafb_mach_info);
 	platform_add_devices(ARRAY_AND_SIZE(e400_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 }
 
 MACHINE_START(E400, "Toshiba e400")
@@ -519,6 +528,7 @@
 static struct platform_device *e740_devices[] __initdata = {
 	&e740_fb_device,
 	&e740_t7l66xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e740_init(void)
@@ -532,7 +542,6 @@
 			"UDCCLK", &pxa25x_device_udc.dev),
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e740_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&e7xx_ficp_platform_data);
 }
@@ -711,6 +720,7 @@
 static struct platform_device *e750_devices[] __initdata = {
 	&e750_fb_device,
 	&e750_tc6393xb_device,
+	&e7xx_gpio_vbus,
 };
 
 static void __init e750_init(void)
@@ -723,7 +733,6 @@
 			"GPIO11_CLK", NULL),
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e750_devices));
-	pxa_set_udc_info(&e7xx_udc_mach_info);
 	pxa_set_ac97_info(NULL);
 	pxa_set_ficp_info(&e7xx_ficp_platform_data);
 }
@@ -873,12 +882,21 @@
 
 /* --------------------------- UDC definitions --------------------------- */
 
-static struct pxa2xx_udc_mach_info e800_udc_mach_info = {
+static struct gpio_vbus_mach_info e800_udc_info = {
 	.gpio_vbus   = GPIO_E800_USB_DISC,
 	.gpio_pullup = GPIO_E800_USB_PULLUP,
 	.gpio_pullup_inverted = 1
 };
 
+static struct platform_device e800_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &e800_udc_info,
+	},
+};
+
+
 /* ----------------- e800 tc6393xb parameters ------------------ */
 
 static struct tc6393xb_platform_data e800_tc6393xb_info = {
@@ -907,6 +925,7 @@
 static struct platform_device *e800_devices[] __initdata = {
 	&e800_fb_device,
 	&e800_tc6393xb_device,
+	&e800_gpio_vbus,
 };
 
 static void __init e800_init(void)
@@ -919,7 +938,6 @@
 			"GPIO11_CLK", NULL),
 	eseries_get_tmio_gpios();
 	platform_add_devices(ARRAY_AND_SIZE(e800_devices));
-	pxa_set_udc_info(&e800_udc_mach_info);
 	pxa_set_ac97_info(NULL);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/ezx.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/ezx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/ezx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/ezx.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/gpio.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds-lp3944.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <media/soc_camera.h>
 
@@ -30,7 +31,6 @@
 #include <mach/pxa27x.h>
 #include <mach/pxafb.h>
 #include <mach/ohci.h>
-#include <plat/i2c.h>
 #include <mach/hardware.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/camera.h>
@@ -783,7 +783,7 @@
 
 	pxa_set_i2c_info(NULL);
 
-	set_pxa_fb_info(&ezx_fb_info_1);
+	pxa_set_fb_info(NULL, &ezx_fb_info_1);
 
 	pxa_set_keypad_info(&a780_keypad_platform_data);
 
@@ -853,7 +853,7 @@
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(e680_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_1);
+	pxa_set_fb_info(NULL, &ezx_fb_info_1);
 
 	pxa_set_keypad_info(&e680_keypad_platform_data);
 
@@ -918,7 +918,7 @@
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(a1200_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&a1200_keypad_platform_data);
 
@@ -1103,7 +1103,7 @@
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(a910_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&a910_keypad_platform_data);
 
@@ -1173,7 +1173,7 @@
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(e6_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&e6_keypad_platform_data);
 
@@ -1212,7 +1212,7 @@
 	pxa_set_i2c_info(NULL);
 	i2c_register_board_info(0, ARRAY_AND_SIZE(e2_i2c_board_info));
 
-	set_pxa_fb_info(&ezx_fb_info_2);
+	pxa_set_fb_info(NULL, &ezx_fb_info_2);
 
 	pxa_set_keypad_info(&e2_keypad_platform_data);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/gumstix.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/gumstix.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/gumstix.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/gumstix.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/gpio.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/setup.h>
 #include <asm/memory.h>
@@ -106,14 +107,22 @@
 #endif
 
 #ifdef CONFIG_USB_GADGET_PXA25X
-static struct pxa2xx_udc_mach_info gumstix_udc_info __initdata = {
+static struct gpio_vbus_mach_info gumstix_udc_info = {
 	.gpio_vbus		= GPIO_GUMSTIX_USB_GPIOn,
 	.gpio_pullup		= GPIO_GUMSTIX_USB_GPIOx,
 };
 
+static struct platform_device gumstix_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &gumstix_udc_info,
+	},
+};
+
 static void __init gumstix_udc_init(void)
 {
-	pxa_set_udc_info(&gumstix_udc_info);
+	platform_device_register(&gumstix_gpio_vbus);
 }
 #else
 static void gumstix_udc_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/hx4700.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/hx4700.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/hx4700.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/hx4700.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,7 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -42,7 +43,6 @@
 
 #include <mach/pxa27x.h>
 #include <mach/hx4700.h>
-#include <plat/i2c.h>
 #include <mach/irda.h>
 
 #include <video/platform_lcd.h>
@@ -711,7 +711,7 @@
 static struct regulator_init_data bq24022_init_data = {
 	.constraints = {
 		.max_uA         = 500000,
-		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT|REGULATOR_CHANGE_STATUS,
 	},
 	.num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
 	.consumer_supplies      = bq24022_consumers,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/idp.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/idp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/idp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/idp.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 
 	platform_device_register(&smc91x_device);
 	//platform_device_register(&mst_audio_device);
-	set_pxa_fb_info(&sharp_lm8v31);
+	pxa_set_fb_info(NULL, &sharp_lm8v31);
 	pxa_set_mci_info(&idp_mci_platform_data);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -99,11 +99,24 @@
 #define GAFR(x)		GPIO_REG(0x54 + (((x) & 0x70) >> 2))
 
 
-#define NR_BUILTIN_GPIO 128
+#define NR_BUILTIN_GPIO		PXA_GPIO_IRQ_NUM
 
 #define gpio_to_bank(gpio)	((gpio) >> 5)
 #define gpio_to_irq(gpio)	IRQ_GPIO(gpio)
-#define irq_to_gpio(irq)	IRQ_TO_GPIO(irq)
+
+static inline int irq_to_gpio(unsigned int irq)
+{
+	int gpio;
+
+	if (irq == IRQ_GPIO0 || irq == IRQ_GPIO1)
+		return irq - IRQ_GPIO0;
+
+	gpio = irq - PXA_GPIO_IRQ_BASE;
+	if (gpio >= 2 && gpio < NR_BUILTIN_GPIO)
+		return gpio;
+
+	return -1;
+}
 
 #ifdef CONFIG_CPU_PXA26x
 /* GPIO86/87/88/89 on PXA26x have their direction bits in GPDR2 inverted,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -93,9 +93,6 @@
 #define GPIO_2_x_TO_IRQ(x)	(PXA_GPIO_IRQ_BASE + (x))
 #define IRQ_GPIO(x)	(((x) < 2) ? (IRQ_GPIO0 + (x)) : GPIO_2_x_TO_IRQ(x))
 
-#define IRQ_TO_GPIO_2_x(i)	((i) - PXA_GPIO_IRQ_BASE)
-#define IRQ_TO_GPIO(i)	(((i) < IRQ_GPIO(2)) ? ((i) - IRQ_GPIO0) : IRQ_TO_GPIO_2_x(i))
-
 /*
  * The following interrupts are for board specific purposes. Since
  * the kernel can only run on one machine at a time, we can re-use
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0xa0000000)
+#define PLAT_PHYS_OFFSET	UL(0xa0000000)
 
 #if !defined(__ASSEMBLY__) && defined(CONFIG_MACH_ARMCORE) && defined(CONFIG_PCI)
 void cmx2xx_pci_adjust_zones(unsigned long *size, unsigned long *holes);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/palmz72.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/palmz72.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/palmz72.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/palmz72.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,6 +44,11 @@
 #define GPIO_NR_PALMZ72_BT_POWER		17
 #define GPIO_NR_PALMZ72_BT_RESET		83
 
+/* Camera */
+#define GPIO_NR_PALMZ72_CAM_PWDN		56
+#define GPIO_NR_PALMZ72_CAM_RESET		57
+#define GPIO_NR_PALMZ72_CAM_POWER		91
+
 /** Initial values **/
 
 /* Battery */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/pm.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/pm.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/pm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/pm.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,9 +22,8 @@
 extern struct pxa_cpu_pm_fns *pxa_cpu_pm_fns;
 
 /* sleep.S */
-extern void pxa25x_cpu_suspend(unsigned int);
-extern void pxa27x_cpu_suspend(unsigned int);
-extern void pxa_cpu_resume(void);
+extern void pxa25x_cpu_suspend(unsigned int, long);
+extern void pxa27x_cpu_suspend(unsigned int, long);
 
 extern int pxa_pm_enter(suspend_state_t state);
 extern int pxa_pm_prepare(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/pxa3xx-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 #define PCMD(x)		__REG(0x40F50110 + ((x) << 2))
 
 /*
- * Slave Power Managment Unit
+ * Slave Power Management Unit
  */
 #define ASCR		__REG(0x40f40000)	/* Application Subsystem Power Status/Configuration */
 #define ARSR		__REG(0x40f40004)	/* Application Subsystem Reset Status */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/pxafb.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/pxafb.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/pxafb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/pxafb.h	2011-05-19 00:06:34.000000000 -0400
@@ -154,8 +154,8 @@
 	void (*pxafb_lcd_power)(int, struct fb_var_screeninfo *);
 	void (*smart_update)(struct fb_info *);
 };
-void set_pxa_fb_info(struct pxafb_mach_info *hard_pxa_fb_info);
-void set_pxa_fb_parent(struct device *parent_dev);
+
+void pxa_set_fb_info(struct device *, struct pxafb_mach_info *);
 unsigned long pxafb_get_hsync_time(struct device *dev);
 
 extern int pxafb_smart_queue(struct fb_info *info, uint16_t *cmds, int);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/z2.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/z2.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/z2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/z2.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,8 +25,7 @@
 #define	GPIO98_ZIPITZ2_LID_BUTTON	98
 
 /* Libertas GSPI8686 WiFi */
-#define	GPIO14_ZIPITZ2_WIFI_RESET	14
-#define	GPIO15_ZIPITZ2_WIFI_POWER	15
+#define	GPIO14_ZIPITZ2_WIFI_POWER	14
 #define	GPIO24_ZIPITZ2_WIFI_CS		24
 #define	GPIO36_ZIPITZ2_WIFI_IRQ		36
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/zeus.h linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/zeus.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/include/mach/zeus.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/include/mach/zeus.h	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 
 /*
  * CPLD registers:
- * Only 4 registers, but spreaded over a 32MB address space.
+ * Only 4 registers, but spread over a 32MB address space.
  * Be gentle, and remap that over 32kB...
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -137,9 +137,9 @@
 	GEDR0 = 0x3;
 
 	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO1; irq++) {
-		set_irq_chip(irq, &pxa_low_gpio_chip);
-		set_irq_chip_data(irq, irq_base(0));
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &pxa_low_gpio_chip,
+					 handle_edge_irq);
+		irq_set_chip_data(irq, irq_base(0));
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
@@ -165,9 +165,9 @@
 				__raw_writel(i | IPR_VALID, IRQ_BASE + IPR(i));
 
 			irq = PXA_IRQ(i);
-			set_irq_chip(irq, &pxa_internal_irq_chip);
-			set_irq_chip_data(irq, base);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &pxa_internal_irq_chip,
+						 handle_level_irq);
+			irq_set_chip_data(irq, base);
 			set_irq_flags(irq, IRQF_VALID);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/littleton.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/littleton.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/littleton.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/littleton.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/leds.h>
 #include <linux/mfd/da903x.h>
 #include <linux/i2c/max732x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -45,7 +46,6 @@
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
 #include <mach/littleton.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "generic.h"
@@ -185,7 +185,7 @@
 
 static void littleton_init_lcd(void)
 {
-	set_pxa_fb_info(&littleton_lcd_info);
+	pxa_set_fb_info(NULL, &littleton_lcd_info);
 }
 #else
 static inline void littleton_init_lcd(void) {};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/lpd270.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/lpd270.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/lpd270.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/lpd270.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,12 +149,12 @@
 
 	/* setup extra LogicPD PXA270 irqs */
 	for (irq = LPD270_IRQ(2); irq <= LPD270_IRQ(4); irq++) {
-		set_irq_chip(irq, &lpd270_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &lpd270_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
-	set_irq_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
-	set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
+	irq_set_chained_handler(IRQ_GPIO(0), lpd270_irq_handler);
+	irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 
@@ -480,7 +480,7 @@
 	pxa_set_ac97_info(NULL);
 
 	if (lpd270_lcd_to_use != NULL)
-		set_pxa_fb_info(lpd270_lcd_to_use);
+		pxa_set_fb_info(NULL, lpd270_lcd_to_use);
 
 	pxa_set_ohci_info(&lpd270_ohci_platform_data);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/lubbock.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/lubbock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/lubbock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/lubbock.c	2011-05-19 00:06:34.000000000 -0400
@@ -165,13 +165,13 @@
 
 	/* setup extra lubbock irqs */
 	for (irq = LUBBOCK_IRQ(0); irq <= LUBBOCK_LAST_IRQ; irq++) {
-		set_irq_chip(irq, &lubbock_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &lubbock_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	set_irq_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
-	set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
+	irq_set_chained_handler(IRQ_GPIO(0), lubbock_irq_handler);
+	irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 #ifdef CONFIG_PM
@@ -521,7 +521,7 @@
 
 	clk_add_alias("SA1111_CLK", NULL, "GPIO11_CLK", NULL);
 	pxa_set_udc_info(&udc_info);
-	set_pxa_fb_info(&sharp_lm8v31);
+	pxa_set_fb_info(NULL, &sharp_lm8v31);
 	pxa_set_mci_info(&lubbock_mci_platform_data);
 	pxa_set_ficp_info(&lubbock_ficp_platform_data);
 	pxa_set_ac97_info(NULL);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/magician.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/magician.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/magician.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/magician.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/regulator/bq24022.h>
 #include <linux/regulator/machine.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
@@ -36,7 +37,6 @@
 #include <mach/pxa27x.h>
 #include <mach/magician.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
@@ -599,7 +599,7 @@
 static struct regulator_init_data bq24022_init_data = {
 	.constraints = {
 		.max_uA         = 500000,
-		.valid_ops_mask = REGULATOR_CHANGE_CURRENT,
+		.valid_ops_mask = REGULATOR_CHANGE_CURRENT | REGULATOR_CHANGE_STATUS,
 	},
 	.num_consumer_supplies  = ARRAY_SIZE(bq24022_consumers),
 	.consumer_supplies      = bq24022_consumers,
@@ -757,7 +757,7 @@
 		gpio_direction_output(GPIO104_MAGICIAN_LCD_POWER_1, 0);
 		gpio_direction_output(GPIO105_MAGICIAN_LCD_POWER_2, 0);
 		gpio_direction_output(GPIO106_MAGICIAN_LCD_POWER_3, 0);
-		set_pxa_fb_info(lcd_select ? &samsung_info : &toppoly_info);
+		pxa_set_fb_info(NULL, lcd_select ? &samsung_info : &toppoly_info);
 	} else
 		pr_err("LCD detection: CPLD mapping failed\n");
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/mainstone.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/mainstone.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/mainstone.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/mainstone.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/pwm_backlight.h>
 #include <linux/smc91x.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -46,7 +47,6 @@
 #include <mach/mainstone.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/irda.h>
 #include <mach/ohci.h>
@@ -166,8 +166,8 @@
 
 	/* setup extra Mainstone irqs */
 	for(irq = MAINSTONE_IRQ(0); irq <= MAINSTONE_IRQ(15); irq++) {
-		set_irq_chip(irq, &mainstone_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &mainstone_irq_chip,
+					 handle_level_irq);
 		if (irq == MAINSTONE_IRQ(10) || irq == MAINSTONE_IRQ(14))
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE | IRQF_NOAUTOEN);
 		else
@@ -179,8 +179,8 @@
 	MST_INTMSKENA = 0;
 	MST_INTSETCLR = 0;
 
-	set_irq_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
-	set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
+	irq_set_chained_handler(IRQ_GPIO(0), mainstone_irq_handler);
+	irq_set_irq_type(IRQ_GPIO(0), IRQ_TYPE_EDGE_FALLING);
 }
 
 #ifdef CONFIG_PM
@@ -592,7 +592,7 @@
 	else
 		mainstone_pxafb_info.modes = &toshiba_ltm035a776c_mode;
 
-	set_pxa_fb_info(&mainstone_pxafb_info);
+	pxa_set_fb_info(NULL, &mainstone_pxafb_info);
 	mainstone_backlight_register();
 
 	pxa_set_mci_info(&mainstone_mci_platform_data);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/mioa701.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/mioa701.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/mioa701.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/mioa701.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 #include <linux/usb/gpio_vbus.h>
 #include <linux/regulator/max1586.h>
 #include <linux/slab.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -50,7 +51,6 @@
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
-#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <mach/audio.h>
 #include <media/soc_camera.h>
@@ -458,7 +458,7 @@
 /*
  * Suspend/Resume bootstrap management
  *
- * MIO A701 reboot sequence is highly ROM dependant. From the one dissassembled,
+ * MIO A701 reboot sequence is highly ROM dependent. From the one dissassembled,
  * this sequence is as follows :
  *   - disables interrupts
  *   - initialize SDRAM (self refresh RAM into active RAM)
@@ -795,7 +795,7 @@
 	pxa_set_stuart_info(NULL);
 	mio_gpio_request(ARRAY_AND_SIZE(global_gpios));
 	bootstrap_init();
-	set_pxa_fb_info(&mioa701_pxafb_info);
+	pxa_set_fb_info(NULL, &mioa701_pxafb_info);
 	pxa_set_mci_info(&mioa701_mci_info);
 	pxa_set_keypad_info(&mioa701_keypad_info);
 	pxa_set_udc_info(&mioa701_udc_info);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/mxm8x10.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/mxm8x10.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/mxm8x10.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/mxm8x10.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,8 +22,8 @@
 #include <linux/serial_8250.h>
 #include <linux/dm9000.h>
 #include <linux/gpio.h>
+#include <linux/i2c/pxa-i2c.h>
 
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include <mach/pxafb.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palm27x.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palm27x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palm27x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palm27x.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,7 @@
 /*
  * Common code for Palm LD, T5, TX, Z72
  *
- * Copyright (C) 2010
- * Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@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
@@ -22,6 +21,7 @@
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
 #include <linux/regulator/max1586.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -36,8 +36,6 @@
 #include <mach/palmasoc.h>
 #include <mach/palm27x.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
@@ -159,7 +157,7 @@
 		palm27x_lcd_screen.pxafb_lcd_power = palm27x_lcd_ctl;
 	}
 
-	set_pxa_fb_info(&palm27x_lcd_screen);
+	pxa_set_fb_info(NULL, &palm27x_lcd_screen);
 }
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palmtc.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palmtc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palmtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palmtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -507,7 +507,7 @@
 
 static void __init palmtc_lcd_init(void)
 {
-	set_pxa_fb_info(&palmtc_lcd_screen);
+	pxa_set_fb_info(NULL, &palmtc_lcd_screen);
 }
 #else
 static inline void palmtc_lcd_init(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palmte2.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palmte2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palmte2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palmte2.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,30 +136,14 @@
 /******************************************************************************
  * Backlight
  ******************************************************************************/
+static struct gpio palmte_bl_gpios[] = {
+	{ GPIO_NR_PALMTE2_BL_POWER, GPIOF_INIT_LOW, "Backlight power" },
+	{ GPIO_NR_PALMTE2_LCD_POWER, GPIOF_INIT_LOW, "LCD power" },
+};
+
 static int palmte2_backlight_init(struct device *dev)
 {
-	int ret;
-
-	ret = gpio_request(GPIO_NR_PALMTE2_BL_POWER, "BL POWER");
-	if (ret)
-		goto err;
-	ret = gpio_direction_output(GPIO_NR_PALMTE2_BL_POWER, 0);
-	if (ret)
-		goto err2;
-	ret = gpio_request(GPIO_NR_PALMTE2_LCD_POWER, "LCD POWER");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMTE2_LCD_POWER, 0);
-	if (ret)
-		goto err3;
-
-	return 0;
-err3:
-	gpio_free(GPIO_NR_PALMTE2_LCD_POWER);
-err2:
-	gpio_free(GPIO_NR_PALMTE2_BL_POWER);
-err:
-	return ret;
+	return gpio_request_array(ARRAY_AND_SIZE(palmte_bl_gpios));
 }
 
 static int palmte2_backlight_notify(struct device *dev, int brightness)
@@ -171,8 +155,7 @@
 
 static void palmte2_backlight_exit(struct device *dev)
 {
-	gpio_free(GPIO_NR_PALMTE2_BL_POWER);
-	gpio_free(GPIO_NR_PALMTE2_LCD_POWER);
+	gpio_free_array(ARRAY_AND_SIZE(palmte_bl_gpios));
 }
 
 static struct platform_pwm_backlight_data palmte2_backlight_data = {
@@ -363,7 +346,7 @@
 	pxa_set_btuart_info(NULL);
 	pxa_set_stuart_info(NULL);
 
-	set_pxa_fb_info(&palmte2_lcd_screen);
+	pxa_set_fb_info(NULL, &palmte2_lcd_screen);
 	pxa_set_mci_info(&palmte2_mci_platform_data);
 	palmte2_udc_init();
 	pxa_set_ac97_info(&palmte2_ac97_pdata);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palmz72.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palmz72.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/palmz72.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/palmz72.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/wm97xx.h>
 #include <linux/power_supply.h>
 #include <linux/usb/gpio_vbus.h>
+#include <linux/i2c-gpio.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -47,6 +48,9 @@
 #include <mach/palm27x.h>
 
 #include <mach/pm.h>
+#include <mach/camera.h>
+
+#include <media/soc_camera.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -103,6 +107,28 @@
 	GPIO22_GPIO,	/* LCD border color */
 	GPIO96_GPIO,	/* lcd power */
 
+	/* PXA Camera */
+	GPIO81_CIF_DD_0,
+	GPIO48_CIF_DD_5,
+	GPIO50_CIF_DD_3,
+	GPIO51_CIF_DD_2,
+	GPIO52_CIF_DD_4,
+	GPIO53_CIF_MCLK,
+	GPIO54_CIF_PCLK,
+	GPIO55_CIF_DD_1,
+	GPIO84_CIF_FV,
+	GPIO85_CIF_LV,
+	GPIO93_CIF_DD_6,
+	GPIO108_CIF_DD_7,
+
+	GPIO56_GPIO,	/* OV9640 Powerdown */
+	GPIO57_GPIO,	/* OV9640 Reset */
+	GPIO91_GPIO,	/* OV9640 Power */
+
+	/* I2C */
+	GPIO117_GPIO,	/* I2C_SCL */
+	GPIO118_GPIO,	/* I2C_SDA */
+
 	/* Misc. */
 	GPIO0_GPIO	| WAKEUP_ON_LEVEL_HIGH,	/* power detect */
 	GPIO88_GPIO,				/* green led */
@@ -212,7 +238,7 @@
 static int palmz72_pm_suspend(struct sys_device *dev, pm_message_t msg)
 {
 	/* setup the resume_info struct for the original bootloader */
-	palmz72_resume_info.resume_addr = (u32) pxa_cpu_resume;
+	palmz72_resume_info.resume_addr = (u32) cpu_resume;
 
 	/* Storing memory touched by ROM */
 	store_ptr = *PALMZ72_SAVE_DWORD;
@@ -254,6 +280,106 @@
 #endif
 
 /******************************************************************************
+ * SoC Camera
+ ******************************************************************************/
+#if defined(CONFIG_SOC_CAMERA_OV9640) || \
+	defined(CONFIG_SOC_CAMERA_OV9640_MODULE)
+static struct pxacamera_platform_data palmz72_pxacamera_platform_data = {
+	.flags		= PXA_CAMERA_MASTER | PXA_CAMERA_DATAWIDTH_8 |
+			PXA_CAMERA_PCLK_EN | PXA_CAMERA_MCLK_EN,
+	.mclk_10khz	= 2600,
+};
+
+/* Board I2C devices. */
+static struct i2c_board_info palmz72_i2c_device[] = {
+	{
+		I2C_BOARD_INFO("ov9640", 0x30),
+	}
+};
+
+static int palmz72_camera_power(struct device *dev, int power)
+{
+	gpio_set_value(GPIO_NR_PALMZ72_CAM_PWDN, !power);
+	mdelay(50);
+	return 0;
+}
+
+static int palmz72_camera_reset(struct device *dev)
+{
+	gpio_set_value(GPIO_NR_PALMZ72_CAM_RESET, 1);
+	mdelay(50);
+	gpio_set_value(GPIO_NR_PALMZ72_CAM_RESET, 0);
+	mdelay(50);
+	return 0;
+}
+
+static struct soc_camera_link palmz72_iclink = {
+	.bus_id		= 0, /* Match id in pxa27x_device_camera in device.c */
+	.board_info	= &palmz72_i2c_device[0],
+	.i2c_adapter_id	= 0,
+	.module_name	= "ov96xx",
+	.power		= &palmz72_camera_power,
+	.reset		= &palmz72_camera_reset,
+	.flags		= SOCAM_DATAWIDTH_8,
+};
+
+static struct i2c_gpio_platform_data palmz72_i2c_bus_data = {
+	.sda_pin	= 118,
+	.scl_pin	= 117,
+	.udelay		= 10,
+	.timeout	= 100,
+};
+
+static struct platform_device palmz72_i2c_bus_device = {
+	.name		= "i2c-gpio",
+	.id		= 0, /* we use this as a replacement for i2c-pxa */
+	.dev		= {
+		.platform_data	= &palmz72_i2c_bus_data,
+	}
+};
+
+static struct platform_device palmz72_camera = {
+	.name	= "soc-camera-pdrv",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &palmz72_iclink,
+	},
+};
+
+/* Here we request the camera GPIOs and configure them. We power up the camera
+ * module, deassert the reset pin, but put it into powerdown (low to no power
+ * consumption) mode. This allows us to later bring the module up fast. */
+static struct gpio palmz72_camera_gpios[] = {
+	{ GPIO_NR_PALMZ72_CAM_POWER,	GPIOF_INIT_HIGH,"Camera DVDD" },
+	{ GPIO_NR_PALMZ72_CAM_RESET,	GPIOF_INIT_LOW,	"Camera RESET" },
+	{ GPIO_NR_PALMZ72_CAM_PWDN,	GPIOF_INIT_LOW,	"Camera PWDN" },
+};
+
+static inline void __init palmz72_cam_gpio_init(void)
+{
+	int ret;
+
+	ret = gpio_request_array(ARRAY_AND_SIZE(palmz72_camera_gpios));
+	if (!ret)
+		gpio_free_array(ARRAY_AND_SIZE(palmz72_camera_gpios));
+	else
+		printk(KERN_ERR "Camera GPIO init failed!\n");
+
+	return;
+}
+
+static void __init palmz72_camera_init(void)
+{
+	palmz72_cam_gpio_init();
+	pxa_set_camera_info(&palmz72_pxacamera_platform_data);
+	platform_device_register(&palmz72_i2c_bus_device);
+	platform_device_register(&palmz72_camera);
+}
+#else
+static inline void palmz72_camera_init(void) {}
+#endif
+
+/******************************************************************************
  * Machine init
  ******************************************************************************/
 static void __init palmz72_init(void)
@@ -276,6 +402,7 @@
 	palm27x_pmic_init();
 	palmz72_kpc_init();
 	palmz72_leds_init();
+	palmz72_camera_init();
 }
 
 MACHINE_START(PALMZ72, "Palm Zire72")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pcm990-baseboard.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pcm990-baseboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pcm990-baseboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pcm990-baseboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,12 +23,12 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/pwm_backlight.h>
 
 #include <media/soc_camera.h>
 
 #include <asm/gpio.h>
-#include <plat/i2c.h>
 #include <mach/camera.h>
 #include <asm/mach/map.h>
 #include <mach/pxa27x.h>
@@ -281,16 +281,16 @@
 
 	/* setup extra PCM990 irqs */
 	for (irq = PCM027_IRQ(0); irq <= PCM027_IRQ(3); irq++) {
-		set_irq_chip(irq, &pcm990_irq_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &pcm990_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	PCM990_INTMSKENA = 0x00;	/* disable all Interrupts */
 	PCM990_INTSETCLR = 0xFF;
 
-	set_irq_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
-	set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
+	irq_set_chained_handler(PCM990_CTRL_INT_IRQ, pcm990_irq_handler);
+	irq_set_irq_type(PCM990_CTRL_INT_IRQ, PCM990_CTRL_INT_IRQ_EDGE);
 }
 
 static int pcm990_mci_init(struct device *dev, irq_handler_t mci_detect_int,
@@ -515,7 +515,7 @@
 	pcm990_init_irq();
 
 #ifndef CONFIG_PCM990_DISPLAY_NONE
-	set_pxa_fb_info(&pcm990_fbinfo);
+	pxa_set_fb_info(NULL, &pcm990_fbinfo);
 #endif
 	platform_device_register(&pcm990_backlight_device);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pm.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,11 +67,6 @@
 
 EXPORT_SYMBOL_GPL(pxa_pm_enter);
 
-unsigned long sleep_phys_sp(void *sp)
-{
-	return virt_to_phys(sp);
-}
-
 static int pxa_pm_valid(suspend_state_t state)
 {
 	if (pxa_cpu_pm_fns)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/poodle.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/poodle.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/poodle.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/poodle.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
 #include <linux/spi/pxa2xx_spi.h>
@@ -44,7 +45,6 @@
 #include <mach/irda.h>
 #include <mach/poodle.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 
 #include <asm/hardware/scoop.h>
 #include <asm/hardware/locomo.h>
@@ -445,8 +445,7 @@
 	if (ret)
 		pr_warning("poodle: Unable to register LoCoMo device\n");
 
-	set_pxa_fb_parent(&poodle_locomo_device.dev);
-	set_pxa_fb_info(&poodle_fb_info);
+	pxa_set_fb_info(&poodle_locomo_device.dev, &poodle_fb_info);
 	pxa_set_udc_info(&udc_info);
 	pxa_set_mci_info(&poodle_mci_platform_data);
 	pxa_set_ficp_info(&poodle_ficp_platform_data);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa25x.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa25x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa25x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa25x.c	2011-05-19 00:06:34.000000000 -0400
@@ -244,7 +244,7 @@
 
 	switch (state) {
 	case PM_SUSPEND_MEM:
-		pxa25x_cpu_suspend(PWRMODE_SLEEP);
+		pxa25x_cpu_suspend(PWRMODE_SLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 		break;
 	}
 }
@@ -252,7 +252,7 @@
 static int pxa25x_cpu_pm_prepare(void)
 {
 	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 	return 0;
 }
 
@@ -285,7 +285,7 @@
 
 static int pxa25x_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = IRQ_TO_GPIO(d->irq);
+	int gpio = irq_to_gpio(d->irq);
 	uint32_t mask = 0;
 
 	if (gpio >= 0 && gpio < 85)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa27x.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa27x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa27x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa27x.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/sysdev.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
@@ -32,8 +33,6 @@
 #include <mach/dma.h>
 #include <mach/smemc.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 #include "clock.h"
@@ -300,7 +299,7 @@
 		pxa_cpu_standby();
 		break;
 	case PM_SUSPEND_MEM:
-		pxa27x_cpu_suspend(pwrmode);
+		pxa27x_cpu_suspend(pwrmode, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 		break;
 	}
 }
@@ -313,7 +312,7 @@
 static int pxa27x_cpu_pm_prepare(void)
 {
 	/* set resume return address */
-	PSPR = virt_to_phys(pxa_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 	return 0;
 }
 
@@ -346,7 +345,7 @@
  */
 static int pxa27x_set_wake(struct irq_data *d, unsigned int on)
 {
-	int gpio = IRQ_TO_GPIO(d->irq);
+	int gpio = irq_to_gpio(d->irq);
 	uint32_t mask;
 
 	if (gpio >= 0 && gpio < 128)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa3xx.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa3xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa3xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa3xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach/map.h>
 #include <mach/hardware.h>
@@ -32,7 +33,6 @@
 #include <mach/dma.h>
 #include <mach/regs-intc.h>
 #include <mach/smemc.h>
-#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -142,8 +142,7 @@
 	volatile unsigned long *p = (volatile void *)0xc0000000;
 	unsigned long saved_data = *p;
 
-	extern void pxa3xx_cpu_suspend(void);
-	extern void pxa3xx_cpu_resume(void);
+	extern void pxa3xx_cpu_suspend(long);
 
 	/* resuming from D2 requires the HSIO2/BOOT/TPM clocks enabled */
 	CKENA |= (1 << CKEN_BOOT) | (1 << CKEN_TPM);
@@ -161,9 +160,9 @@
 	PSPR = 0x5c014000;
 
 	/* overwrite with the resume address */
-	*p = virt_to_phys(pxa3xx_cpu_resume);
+	*p = virt_to_phys(cpu_resume);
 
-	pxa3xx_cpu_suspend();
+	pxa3xx_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
 	*p = saved_data;
 
@@ -363,8 +362,8 @@
 	int irq;
 
 	for (irq = IRQ_WAKEUP0; irq <= IRQ_WAKEUP1; irq++) {
-		set_irq_chip(irq, &pxa_ext_wakeup_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &pxa_ext_wakeup_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa95x.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa95x.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/pxa95x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/pxa95x.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/init.h>
 #include <linux/pm.h>
 #include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sysdev.h>
@@ -27,7 +28,6 @@
 #include <mach/pm.h>
 #include <mach/dma.h>
 #include <mach/regs-intc.h>
-#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/raumfeld.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/raumfeld.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/raumfeld.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/raumfeld.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/sched.h>
 #include <linux/pwm_backlight.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_gpio.h>
 #include <linux/lis3lv02d.h>
@@ -53,7 +54,6 @@
 #include <mach/ohci.h>
 #include <mach/pxafb.h>
 #include <mach/mmc.h>
-#include <plat/i2c.h>
 #include <plat/pxa3xx_nand.h>
 
 #include "generic.h"
@@ -597,7 +597,7 @@
 {
 	int ret;
 
-	set_pxa_fb_info(&raumfeld_sharp_lcd_info);
+	pxa_set_fb_info(NULL, &raumfeld_sharp_lcd_info);
 
 	/* Earlier devices had the backlight regulator controlled
 	 * via PWM, later versions use another controller for that */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/saarb.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/saarb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/saarb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/saarb.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/mfd/88pm860x.h>
 
 #include <asm/mach-types.h>
@@ -24,8 +25,6 @@
 #include <mach/mfp-pxa930.h>
 #include <mach/gpio.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 
 #define SAARB_NR_IRQS	(IRQ_BOARD_START + 40)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/saar.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/saar.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/saar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/saar.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <linux/fb.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/smc91x.h>
 #include <linux/mfd/da903x.h>
 #include <linux/mtd/mtd.h>
@@ -31,7 +32,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa930.h>
-#include <plat/i2c.h>
 #include <mach/pxafb.h>
 
 #include "devices.h"
@@ -473,7 +473,7 @@
 
 static void __init saar_init_lcd(void)
 {
-	set_pxa_fb_info(&saar_lcd_info);
+	pxa_set_fb_info(NULL, &saar_lcd_info);
 }
 #else
 static inline void saar_init_lcd(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/sleep.S linux-libre-2.6.39-gnu/arch/arm/mach-pxa/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/sleep.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -22,133 +22,26 @@
 
 		.text
 
-pxa_cpu_save_cp:
-	@ get coprocessor registers
-	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
-	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mrc	p15, 0, r5, c13, c0, 0		@ PID
-	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
-	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
-
-	bic	r3, r3, #2			@ clear frequency change bit
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r10, sp
-	stmfd	sp!, {r3 - r10}
-
-	mov	pc, lr
-
-pxa_cpu_save_sp:
-	@ preserve phys address of stack
-	mov	r0, sp
-	str	lr, [sp, #-4]!
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-	ldr	pc, [sp], #4
-
 #ifdef CONFIG_PXA3xx
 /*
  * pxa3xx_cpu_suspend() - forces CPU into sleep state (S2D3C4)
  *
- * NOTE:  unfortunately, pxa_cpu_save_cp can not be reused here since
- * the auxiliary control register address is different between pxa3xx
- * and pxa{25x,27x}
+ * r0 = v:p offset
  */
-
 ENTRY(pxa3xx_cpu_suspend)
 
 #ifndef CONFIG_IWMMXT
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}	@ save registers on stack
-
-	mrc	p14, 0, r3, c6, c0, 0		@ clock configuration, for turbo mode
-	mrc	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mrc	p15, 0, r5, c13, c0, 0		@ PID
-	mrc 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
-	mrc 	p15, 0, r9, c1, c0, 0		@ control reg
-
-	bic	r3, r3, #2			@ clear frequency change bit
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r10, sp
-	stmfd	sp!, {r3 - r10}
-
-	@ store physical address of stack pointer
-	mov	r0, sp
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-
-	@ clean data cache
-	bl	xsc3_flush_kern_cache_all
+	mov	r1, r0
+	ldr	r3, =pxa_cpu_resume	@ resume function
+	bl	cpu_suspend
 
 	mov	r0, #0x06		@ S2D3C4 mode
 	mcr	p14, 0, r0, c7, c0, 0	@ enter sleep
 
 20:	b	20b			@ waiting for sleep
-
-	.data
-	.align 5
-/*
- * pxa3xx_cpu_resume
- */
-
-ENTRY(pxa3xx_cpu_resume)
-
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
-	msr	cpsr_c, r0
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
-	mcr	p15, 0, r1, c7, c10, 4		@ drain write (&fill) buffer
-	mcr	p15, 0, r1, c7, c5, 4		@ flush prefetch buffer
-	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
-
-	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r8, c1, c0, 1           @ auxiliary control reg
-
-	@ temporarily map resume_turn_on_mmu into the page table,
-	@ otherwise prefetch abort occurs after MMU is turned on
-	mov	r1, r7
-	bic	r1, r1, #0x00ff
-	bic	r1, r1, #0x3f00
-	ldr	r2, =0x542e
-
-	adr	r3, resume_turn_on_mmu
-	mov	r3, r3, lsr #20
-	orr	r4, r2, r3, lsl #20
-	ldr	r5, [r1, r3, lsl #2]
-	str     r4, [r1, r3, lsl #2]
-
-	@ Mapping page table address in the page table
-	mov	r6, r1, lsr #20
-	orr	r7, r2, r6, lsl #20
-	ldr	r8, [r1, r6, lsl #2]
-	str	r7, [r1, r6, lsl #2]
-
-	ldr	r2, =pxa3xx_resume_after_mmu	@ absolute virtual address
-	b	resume_turn_on_mmu		@ cache align execution
-
-	.text
-pxa3xx_resume_after_mmu:
-	/* restore the temporary mapping */
-	str	r5, [r1, r3, lsl #2]
-	str	r8, [r1, r6, lsl #2]
-	b	resume_after_mmu
-
 #endif /* CONFIG_PXA3xx */
 
 #ifdef CONFIG_PXA27x
@@ -158,28 +51,23 @@
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
+ * r1 = v:p offset
  */
-
 ENTRY(pxa27x_cpu_suspend)
 
 #ifndef CONFIG_IWMMXT
 	mra	r2, r3, acc0
 #endif
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-
-	bl	pxa_cpu_save_cp
-
-	mov	r5, r0				@ save sleep mode
-	bl	pxa_cpu_save_sp
-
-	@ clean data cache
-	bl	xscale_flush_kern_cache_all
+	mov	r4, r0				@ save sleep mode
+	ldr	r3, =pxa_cpu_resume		@ resume function
+	bl	cpu_suspend
 
 	@ Put the processor to sleep
 	@ (also workaround for sighting 28071)
 
 	@ prepare value for sleep mode
-	mov	r1, r5				@ sleep mode
+	mov	r1, r4				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -216,21 +104,16 @@
  * Forces CPU into sleep state.
  *
  * r0 = value for PWRMODE M field for desired sleep state
+ * r1 = v:p offset
  */
 
 ENTRY(pxa25x_cpu_suspend)
 	stmfd	sp!, {r2 - r12, lr}		@ save registers on stack
-
-	bl	pxa_cpu_save_cp
-
-	mov	r5, r0				@ save sleep mode
-	bl	pxa_cpu_save_sp
-
-	@ clean data cache
-	bl	xscale_flush_kern_cache_all
-
+	mov	r4, r0				@ save sleep mode
+	ldr	r3, =pxa_cpu_resume		@ resume function
+	bl	cpu_suspend
 	@ prepare value for sleep mode
-	mov	r1, r5				@ sleep mode
+	mov	r1, r4				@ sleep mode
 
 	@ prepare pointer to physical address 0 (virtual mapping in generic.c)
 	mov	r2, #UNCACHED_PHYS_0
@@ -317,53 +200,9 @@
  * pxa_cpu_resume()
  *
  * entry point from bootloader into kernel during resume
- *
- * Note: Yes, part of the following code is located into the .data section.
- *       This is to allow sleep_save_sp to be accessed with a relative load
- *       while we can't rely on any MMU translation.  We could have put
- *       sleep_save_sp in the .text section as well, but some setups might
- *       insist on it to be truly read-only.
  */
-
-	.data
 	.align 5
-ENTRY(pxa_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE	@ set SVC, irqs off
-	msr	cpsr_c, r0
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldr	r2, =resume_after_mmu		@ its absolute virtual address
-	ldmfd	r0, {r3 - r9, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0   	@ invalidate I & D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@ invalidate I & D caches, BTB
-
-	mcr	p14, 0, r3, c6, c0, 0		@ clock configuration, turbo mode.
-	mcr	p15, 0, r4, c15, c1, 0		@ CP access reg
-	mcr	p15, 0, r5, c13, c0, 0		@ PID
-	mcr 	p15, 0, r6, c3, c0, 0		@ domain ID
-	mcr 	p15, 0, r7, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r8, c1, c1, 0           @ auxiliary control reg
-	b	resume_turn_on_mmu		@ cache align execution
-
-	.align 5
-resume_turn_on_mmu:
-	mcr 	p15, 0, r9, c1, c0, 0		@ turn on MMU, caches, etc.
-
-	@ Let us ensure we jump to resume_after_mmu only when the mcr above
-	@ actually took effect.  They call it the "cpwait" operation.
-	mrc	p15, 0, r0, c2, c0, 0		@ queue a dependency on CP15
-	sub	pc, r2, r0, lsr #32		@ jump to virtual addr
-	nop
-	nop
-	nop
-
-sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
-
-	.text
-resume_after_mmu:
+pxa_cpu_resume:
 	ldmfd	sp!, {r2, r3}
 #ifndef CONFIG_IWMMXT
 	mar	acc0, r2, r3
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/spitz.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/spitz.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/spitz.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/spitz.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/gpio.h>
 #include <linux/leds.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -47,8 +48,6 @@
 #include <mach/sharpsl_pm.h>
 #include <mach/smemc.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
@@ -725,7 +724,7 @@
 
 static void __init spitz_lcd_init(void)
 {
-	set_pxa_fb_info(&spitz_pxafb_info);
+	pxa_set_fb_info(NULL, &spitz_pxafb_info);
 }
 #else
 static inline void spitz_lcd_init(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/stargate2.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/stargate2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/stargate2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/stargate2.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/mtd/plat-ram.h>
 #include <linux/mtd/partitions.h>
 
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/i2c/at24.h>
 #include <linux/smc91x.h>
@@ -43,7 +44,6 @@
 #include <asm/mach/flash.h>
 
 #include <mach/pxa27x.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/pxa27x-udc.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/tavorevb3.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/tavorevb3.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/tavorevb3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/tavorevb3.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/gpio.h>
 #include <linux/mfd/88pm860x.h>
 
@@ -23,8 +24,6 @@
 
 #include <mach/pxa930.h>
 
-#include <plat/i2c.h>
-
 #include "devices.h"
 #include "generic.h"
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/tavorevb.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/tavorevb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/tavorevb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/tavorevb.c	2011-05-19 00:06:34.000000000 -0400
@@ -466,7 +466,7 @@
 {
 	platform_device_register(&tavorevb_backlight_devices[0]);
 	platform_device_register(&tavorevb_backlight_devices[1]);
-	set_pxa_fb_info(&tavorevb_lcd_info);
+	pxa_set_fb_info(NULL, &tavorevb_lcd_info);
 }
 #else
 static inline void tavorevb_init_lcd(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/time.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/time.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,6 @@
 static struct clock_event_device ckevt_pxa_osmr0 = {
 	.name		= "osmr0",
 	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.shift		= 32,
 	.rating		= 200,
 	.set_next_event	= pxa_osmr0_set_next_event,
 	.set_mode	= pxa_osmr0_set_mode,
@@ -135,8 +134,8 @@
 
 	init_sched_clock(&cd, pxa_update_sched_clock, 32, clock_tick_rate);
 
-	ckevt_pxa_osmr0.mult =
-		div_sc(clock_tick_rate, NSEC_PER_SEC, ckevt_pxa_osmr0.shift);
+	clocksource_calc_mult_shift(&cksrc_pxa_oscr0, clock_tick_rate, 4);
+	clockevents_calc_mult_shift(&ckevt_pxa_osmr0, clock_tick_rate, 4);
 	ckevt_pxa_osmr0.max_delta_ns =
 		clockevent_delta2ns(0x7fffffff, &ckevt_pxa_osmr0);
 	ckevt_pxa_osmr0.min_delta_ns =
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/tosa.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/tosa.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/tosa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/tosa.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,8 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/pxa2xx_spi.h>
 #include <linux/input/matrix_keypad.h>
+#include <linux/i2c/pxa-i2c.h>
+#include <linux/usb/gpio_vbus.h>
 
 #include <asm/setup.h>
 #include <asm/mach-types.h>
@@ -41,7 +43,6 @@
 #include <mach/pxa25x.h>
 #include <mach/reset.h>
 #include <mach/irda.h>
-#include <plat/i2c.h>
 #include <mach/mmc.h>
 #include <mach/udc.h>
 #include <mach/tosa_bt.h>
@@ -240,12 +241,20 @@
 /*
  * USB Device Controller
  */
-static struct pxa2xx_udc_mach_info udc_info __initdata = {
+static struct gpio_vbus_mach_info tosa_udc_info = {
 	.gpio_pullup		= TOSA_GPIO_USB_PULLUP,
 	.gpio_vbus		= TOSA_GPIO_USB_IN,
 	.gpio_vbus_inverted	= 1,
 };
 
+static struct platform_device tosa_gpio_vbus = {
+	.name	= "gpio-vbus",
+	.id	= -1,
+	.dev	= {
+		.platform_data	= &tosa_udc_info,
+	},
+};
+
 /*
  * MMC/SD Device
  */
@@ -891,6 +900,7 @@
 	&tosa_bt_device,
 	&sharpsl_rom_device,
 	&wm9712_device,
+	&tosa_gpio_vbus,
 };
 
 static void tosa_poweroff(void)
@@ -937,7 +947,6 @@
 	dummy = gpiochip_reserve(TOSA_TC6393XB_GPIO_BASE, 16);
 
 	pxa_set_mci_info(&tosa_mci_platform_data);
-	pxa_set_udc_info(&udc_info);
 	pxa_set_ficp_info(&tosa_ficp_platform_data);
 	pxa_set_i2c_info(NULL);
 	pxa_set_ac97_info(NULL);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/trizeps4.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/trizeps4.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/trizeps4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/trizeps4.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/dm9000.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
@@ -47,7 +48,6 @@
 #include <mach/irda.h>
 #include <mach/ohci.h>
 #include <mach/smemc.h>
-#include <plat/i2c.h>
 
 #include "generic.h"
 #include "devices.h"
@@ -516,9 +516,9 @@
 	pxa_set_stuart_info(NULL);
 
 	if (0)	/* dont know how to determine LCD */
-		set_pxa_fb_info(&sharp_lcd);
+		pxa_set_fb_info(NULL, &sharp_lcd);
 	else
-		set_pxa_fb_info(&toshiba_lcd);
+		pxa_set_fb_info(NULL, &toshiba_lcd);
 
 	pxa_set_mci_info(&trizeps4_mci_platform_data);
 #ifndef STATUS_LEDS_ON_STUART_PINS
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/viper.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/viper.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/viper.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/viper.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/gpio.h>
 #include <linux/jiffies.h>
 #include <linux/i2c-gpio.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/serial_8250.h>
 #include <linux/smc91x.h>
 #include <linux/pwm_backlight.h>
@@ -47,7 +48,6 @@
 #include <mach/pxa25x.h>
 #include <mach/audio.h>
 #include <mach/pxafb.h>
-#include <plat/i2c.h>
 #include <mach/regs-uart.h>
 #include <mach/arcom-pcmcia.h>
 #include <mach/viper.h>
@@ -310,14 +310,14 @@
 	/* setup ISA IRQs */
 	for (level = 0; level < ARRAY_SIZE(viper_isa_irqs); level++) {
 		isa_irq = viper_bit_to_irq(level);
-		set_irq_chip(isa_irq, &viper_irq_chip);
-		set_irq_handler(isa_irq, handle_edge_irq);
+		irq_set_chip_and_handler(isa_irq, &viper_irq_chip,
+					 handle_edge_irq);
 		set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	set_irq_chained_handler(gpio_to_irq(VIPER_CPLD_GPIO),
+	irq_set_chained_handler(gpio_to_irq(VIPER_CPLD_GPIO),
 				viper_irq_handler);
-	set_irq_type(gpio_to_irq(VIPER_CPLD_GPIO), IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(gpio_to_irq(VIPER_CPLD_GPIO), IRQ_TYPE_EDGE_BOTH);
 }
 
 /* Flat Panel */
@@ -932,7 +932,7 @@
 	/* Wake-up serial console */
 	viper_init_serial_gpio();
 
-	set_pxa_fb_info(&fb_info);
+	pxa_set_fb_info(NULL, &fb_info);
 
 	/* v1 hardware cannot use the datacs line */
 	version = viper_hw_version();
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/vpac270.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/vpac270.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/vpac270.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/vpac270.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/ucb1400.h>
 #include <linux/ata_platform.h>
 #include <linux/regulator/max1586.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -40,8 +41,6 @@
 #include <mach/udc.h>
 #include <mach/pata_pxa.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
@@ -573,7 +572,7 @@
 	}
 
 	vpac270_lcd_screen.pxafb_lcd_power = vpac270_lcd_power;
-	set_pxa_fb_info(&vpac270_lcd_screen);
+	pxa_set_fb_info(NULL, &vpac270_lcd_screen);
 	return;
 
 err2:
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/xcep.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/xcep.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/xcep.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/xcep.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/smc91x.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
@@ -26,8 +27,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include <plat/i2c.h>
-
 #include <mach/hardware.h>
 #include <mach/pxa2xx-regs.h>
 #include <mach/mfp-pxa25x.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/z2.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/z2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/z2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/z2.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/delay.h>
 #include <linux/regulator/machine.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -40,8 +41,6 @@
 #include <mach/mmc.h>
 #include <plat/pxa27x_keypad.h>
 
-#include <plat/i2c.h>
-
 #include "generic.h"
 #include "devices.h"
 
@@ -92,13 +91,13 @@
 	GPIO47_STUART_TXD,
 
 	/* Keypad */
-	GPIO100_KP_MKIN_0	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO101_KP_MKIN_1	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO102_KP_MKIN_2	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO34_KP_MKIN_3	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO38_KP_MKIN_4	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO16_KP_MKIN_5	| WAKEUP_ON_LEVEL_HIGH,
-	GPIO17_KP_MKIN_6	| WAKEUP_ON_LEVEL_HIGH,
+	GPIO100_KP_MKIN_0,
+	GPIO101_KP_MKIN_1,
+	GPIO102_KP_MKIN_2,
+	GPIO34_KP_MKIN_3,
+	GPIO38_KP_MKIN_4,
+	GPIO16_KP_MKIN_5,
+	GPIO17_KP_MKIN_6,
 	GPIO103_KP_MKOUT_0,
 	GPIO104_KP_MKOUT_1,
 	GPIO105_KP_MKOUT_2,
@@ -139,8 +138,7 @@
 	GPIO1_GPIO,		/* Power button */
 	GPIO37_GPIO,		/* Headphone detect */
 	GPIO98_GPIO,		/* Lid switch */
-	GPIO14_GPIO,		/* WiFi Reset */
-	GPIO15_GPIO,		/* WiFi Power */
+	GPIO14_GPIO,		/* WiFi Power */
 	GPIO24_GPIO,		/* WiFi CS */
 	GPIO36_GPIO,		/* WiFi IRQ */
 	GPIO88_GPIO,		/* LCD CS */
@@ -205,7 +203,7 @@
 		/* Keypad Backlight */
 		.pwm_id		= 1,
 		.max_brightness	= 1023,
-		.dft_brightness	= 512,
+		.dft_brightness	= 0,
 		.pwm_period_ns	= 1260320,
 	},
 	[1] = {
@@ -272,7 +270,7 @@
 
 static void __init z2_lcd_init(void)
 {
-	set_pxa_fb_info(&z2_lcd_screen);
+	pxa_set_fb_info(NULL, &z2_lcd_screen);
 }
 #else
 static inline void z2_lcd_init(void) {}
@@ -310,12 +308,12 @@
 	.active_low		= 1,
 }, {
 	.name			= "z2:green:charged",
-	.default_trigger	= "none",
+	.default_trigger	= "mmc0",
 	.gpio			= GPIO85_ZIPITZ2_LED_CHARGED,
 	.active_low		= 1,
 }, {
 	.name			= "z2:amber:charging",
-	.default_trigger	= "none",
+	.default_trigger	= "Z2-charging-or-full",
 	.gpio			= GPIO83_ZIPITZ2_LED_CHARGING,
 	.active_low		= 1,
 },
@@ -428,8 +426,22 @@
  ******************************************************************************/
 #if defined(CONFIG_KEYBOARD_GPIO) || defined(CONFIG_KEYBOARD_GPIO_MODULE)
 static struct gpio_keys_button z2_pxa_buttons[] = {
-	{KEY_POWER, GPIO1_ZIPITZ2_POWER_BUTTON, 0, "Power Button" },
-	{KEY_CLOSE, GPIO98_ZIPITZ2_LID_BUTTON, 0, "Lid Button" },
+	{
+		.code		= KEY_POWER,
+		.gpio		= GPIO1_ZIPITZ2_POWER_BUTTON,
+		.active_low	= 0,
+		.desc		= "Power Button",
+		.wakeup		= 1,
+		.type		= EV_KEY,
+	},
+	{
+		.code		= SW_LID,
+		.gpio		= GPIO98_ZIPITZ2_LID_BUTTON,
+		.active_low	= 1,
+		.desc		= "Lid Switch",
+		.wakeup		= 0,
+		.type		= EV_SW,
+	},
 };
 
 static struct gpio_keys_platform_data z2_pxa_keys_data = {
@@ -462,9 +474,9 @@
 	.batt_I2C_addr	= 0x55,
 	.batt_I2C_reg	= 2,
 	.charge_gpio	= GPIO0_ZIPITZ2_AC_DETECT,
-	.min_voltage	= 2400000,
-	.max_voltage	= 3700000,
-	.batt_div	= 69,
+	.min_voltage	= 3475000,
+	.max_voltage	= 4190000,
+	.batt_div	= 59,
 	.batt_mult	= 1000000,
 	.batt_tech	= POWER_SUPPLY_TECHNOLOGY_LION,
 	.batt_name	= "Z2",
@@ -498,26 +510,16 @@
 {
 	int ret = 0;
 
-	ret = gpio_request(GPIO15_ZIPITZ2_WIFI_POWER, "WiFi Power");
+	ret = gpio_request(GPIO14_ZIPITZ2_WIFI_POWER, "WiFi Power");
 	if (ret)
 		goto err;
 
-	ret = gpio_direction_output(GPIO15_ZIPITZ2_WIFI_POWER, 1);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO14_ZIPITZ2_WIFI_RESET, "WiFi Reset");
+	ret = gpio_direction_output(GPIO14_ZIPITZ2_WIFI_POWER, 1);
 	if (ret)
 		goto err2;
 
-	ret = gpio_direction_output(GPIO14_ZIPITZ2_WIFI_RESET, 0);
-	if (ret)
-		goto err3;
-
-	/* Reset the card */
+	/* Wait until card is powered on */
 	mdelay(180);
-	gpio_set_value(GPIO14_ZIPITZ2_WIFI_RESET, 1);
-	mdelay(20);
 
 	spi->bits_per_word = 16;
 	spi->mode = SPI_MODE_2,
@@ -526,22 +528,18 @@
 
 	return 0;
 
-err3:
-	gpio_free(GPIO14_ZIPITZ2_WIFI_RESET);
 err2:
-	gpio_free(GPIO15_ZIPITZ2_WIFI_POWER);
+	gpio_free(GPIO14_ZIPITZ2_WIFI_POWER);
 err:
 	return ret;
 };
 
 static int z2_lbs_spi_teardown(struct spi_device *spi)
 {
-	gpio_set_value(GPIO14_ZIPITZ2_WIFI_RESET, 0);
-	gpio_set_value(GPIO15_ZIPITZ2_WIFI_POWER, 0);
-	gpio_free(GPIO14_ZIPITZ2_WIFI_RESET);
-	gpio_free(GPIO15_ZIPITZ2_WIFI_POWER);
-	return 0;
+	gpio_set_value(GPIO14_ZIPITZ2_WIFI_POWER, 0);
+	gpio_free(GPIO14_ZIPITZ2_WIFI_POWER);
 
+	return 0;
 };
 
 static struct pxa2xx_spi_chip z2_lbs_chip_info = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/zeus.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/zeus.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/zeus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/zeus.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/apm-emulation.h>
 #include <linux/can/platform/mcp251x.h>
@@ -33,8 +34,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
-#include <plat/i2c.h>
-
 #include <mach/pxa2xx-regs.h>
 #include <mach/regs-uart.h>
 #include <mach/ohci.h>
@@ -137,22 +136,23 @@
 
 	/* Peripheral IRQs. It would be nice to move those inside driver
 	   configuration, but it is not supported at the moment. */
-	set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO),	IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO),	IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO),	IRQ_TYPE_EDGE_RISING);
-	set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO),	IRQ_TYPE_EDGE_FALLING);
-	set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO),	IRQ_TYPE_EDGE_FALLING);
+	irq_set_irq_type(gpio_to_irq(ZEUS_AC97_GPIO), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(ZEUS_WAKEUP_GPIO), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(ZEUS_PTT_GPIO), IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(ZEUS_EXTGPIO_GPIO),
+			 IRQ_TYPE_EDGE_FALLING);
+	irq_set_irq_type(gpio_to_irq(ZEUS_CAN_GPIO), IRQ_TYPE_EDGE_FALLING);
 
 	/* Setup ISA IRQs */
 	for (level = 0; level < ARRAY_SIZE(zeus_isa_irqs); level++) {
 		isa_irq = zeus_bit_to_irq(level);
-		set_irq_chip(isa_irq, &zeus_irq_chip);
-		set_irq_handler(isa_irq, handle_edge_irq);
+		irq_set_chip_and_handler(isa_irq, &zeus_irq_chip,
+					 handle_edge_irq);
 		set_irq_flags(isa_irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING);
-	set_irq_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler);
+	irq_set_irq_type(gpio_to_irq(ZEUS_ISA_GPIO), IRQ_TYPE_EDGE_RISING);
+	irq_set_chained_handler(gpio_to_irq(ZEUS_ISA_GPIO), zeus_irq_handler);
 }
 
 
@@ -676,7 +676,7 @@
 static void zeus_power_off(void)
 {
 	local_irq_disable();
-	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP);
+	pxa27x_cpu_suspend(PWRMODE_DEEPSLEEP, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 }
 #else
 #define zeus_power_off   NULL
@@ -847,7 +847,7 @@
 	if (zeus_setup_fb_gpios())
 		pr_err("Failed to setup fb gpios\n");
 	else
-		set_pxa_fb_info(&zeus_fb_info);
+		pxa_set_fb_info(NULL, &zeus_fb_info);
 
 	pxa_set_mci_info(&zeus_mci_platform_data);
 	pxa_set_udc_info(&zeus_udc_info);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/zylonite.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/zylonite.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/zylonite.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/zylonite.c	2011-05-19 00:06:34.000000000 -0400
@@ -208,7 +208,7 @@
 	platform_device_register(&zylonite_backlight_device);
 
 	if (lcd_id & 0x20) {
-		set_pxa_fb_info(&zylonite_sharp_lcd_info);
+		pxa_set_fb_info(NULL, &zylonite_sharp_lcd_info);
 		return;
 	}
 
@@ -220,7 +220,7 @@
 	else
 		zylonite_toshiba_lcd_info.modes = &toshiba_ltm04c380k_mode;
 
-	set_pxa_fb_info(&zylonite_toshiba_lcd_info);
+	pxa_set_fb_info(NULL, &zylonite_toshiba_lcd_info);
 }
 #else
 static inline void zylonite_init_lcd(void) {}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-pxa/zylonite_pxa300.c linux-libre-2.6.39-gnu/arch/arm/mach-pxa/zylonite_pxa300.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-pxa/zylonite_pxa300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-pxa/zylonite_pxa300.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,11 +17,11 @@
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/i2c/pxa-i2c.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/gpio.h>
 
 #include <mach/pxa300.h>
-#include <plat/i2c.h>
 #include <mach/zylonite.h>
 
 #include "generic.h"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/core.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,7 @@
 #include <mach/irqs.h>
 #include <asm/hardware/timer-sp.h>
 
+#include <plat/clcd.h>
 #include <plat/sched_clock.h>
 
 #include "core.h"
@@ -359,18 +360,19 @@
 	}
 };
 
-static int __init clk_init(void)
+void __init realview_init_early(void)
 {
+	void __iomem *sys = __io_address(REALVIEW_SYS_BASE);
+
 	if (machine_is_realview_pb1176())
-		oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC0_OFFSET;
+		oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC0_OFFSET;
 	else
-		oscvco_clk.vcoreg = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_OSC4_OFFSET;
+		oscvco_clk.vcoreg = sys + REALVIEW_SYS_OSC4_OFFSET;
 
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
-	return 0;
+	versatile_sched_clock_init(sys + REALVIEW_SYS_24MHz_OFFSET, 24000000);
 }
-core_initcall(clk_init);
 
 /*
  * CLCD support.
@@ -385,157 +387,6 @@
 #define SYS_CLCD_ID_SANYO_2_5	(0x07 << 8)
 #define SYS_CLCD_ID_VGA		(0x1f << 8)
 
-static struct clcd_panel vga = {
-	.mode		= {
-		.name		= "VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 39721,
-		.left_margin	= 40,
-		.right_margin	= 24,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 96,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel xvga = {
-	.mode		= {
-		.name		= "XVGA",
-		.refresh	= 60,
-		.xres		= 1024,
-		.yres		= 768,
-		.pixclock	= 15748,
-		.left_margin	= 152,
-		.right_margin	= 48,
-		.upper_margin	= 23,
-		.lower_margin	= 3,
-		.hsync_len	= 104,
-		.vsync_len	= 4,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel sanyo_3_8_in = {
-	.mode		= {
-		.name		= "Sanyo QVGA",
-		.refresh	= 116,
-		.xres		= 320,
-		.yres		= 240,
-		.pixclock	= 100000,
-		.left_margin	= 6,
-		.right_margin	= 6,
-		.upper_margin	= 5,
-		.lower_margin	= 5,
-		.hsync_len	= 6,
-		.vsync_len	= 6,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel sanyo_2_5_in = {
-	.mode		= {
-		.name		= "Sanyo QVGA Portrait",
-		.refresh	= 116,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 100000,
-		.left_margin	= 20,
-		.right_margin	= 10,
-		.upper_margin	= 2,
-		.lower_margin	= 2,
-		.hsync_len	= 10,
-		.vsync_len	= 2,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IVS | TIM2_IHS | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel epson_2_2_in = {
-	.mode		= {
-		.name		= "Epson QCIF",
-		.refresh	= 390,
-		.xres		= 176,
-		.yres		= 220,
-		.pixclock	= 62500,
-		.left_margin	= 3,
-		.right_margin	= 2,
-		.upper_margin	= 1,
-		.lower_margin	= 0,
-		.hsync_len	= 3,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-/*
- * Detect which LCD panel is connected, and return the appropriate
- * clcd_panel structure.  Note: we do not have any information on
- * the required timings for the 8.4in panel, so we presently assume
- * VGA timings.
- */
-static struct clcd_panel *realview_clcd_panel(void)
-{
-	void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
-	struct clcd_panel *vga_panel;
-	struct clcd_panel *panel;
-	u32 val;
-
-	if (machine_is_realview_eb())
-		vga_panel = &vga;
-	else
-		vga_panel = &xvga;
-
-	val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
-	if (val == SYS_CLCD_ID_SANYO_3_8)
-		panel = &sanyo_3_8_in;
-	else if (val == SYS_CLCD_ID_SANYO_2_5)
-		panel = &sanyo_2_5_in;
-	else if (val == SYS_CLCD_ID_EPSON_2_2)
-		panel = &epson_2_2_in;
-	else if (val == SYS_CLCD_ID_VGA)
-		panel = vga_panel;
-	else {
-		printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
-			val);
-		panel = vga_panel;
-	}
-
-	return panel;
-}
-
 /*
  * Disable all display connectors on the interface module.
  */
@@ -565,56 +416,60 @@
 	writel(val, sys_clcd);
 }
 
+/*
+ * Detect which LCD panel is connected, and return the appropriate
+ * clcd_panel structure.  Note: we do not have any information on
+ * the required timings for the 8.4in panel, so we presently assume
+ * VGA timings.
+ */
 static int realview_clcd_setup(struct clcd_fb *fb)
 {
+	void __iomem *sys_clcd = __io_address(REALVIEW_SYS_BASE) + REALVIEW_SYS_CLCD_OFFSET;
+	const char *panel_name, *vga_panel_name;
 	unsigned long framesize;
-	dma_addr_t dma;
+	u32 val;
 
-	if (machine_is_realview_eb())
+	if (machine_is_realview_eb()) {
 		/* VGA, 16bpp */
 		framesize = 640 * 480 * 2;
-	else
+		vga_panel_name = "VGA";
+	} else {
 		/* XVGA, 16bpp */
 		framesize = 1024 * 768 * 2;
-
-	fb->panel		= realview_clcd_panel();
-
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-						    &dma, GFP_KERNEL | GFP_DMA);
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
+		vga_panel_name = "XVGA";
 	}
 
-	fb->fb.fix.smem_start	= dma;
-	fb->fb.fix.smem_len	= framesize;
-
-	return 0;
-}
+	val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
+	if (val == SYS_CLCD_ID_SANYO_3_8)
+		panel_name = "Sanyo TM38QV67A02A";
+	else if (val == SYS_CLCD_ID_SANYO_2_5)
+		panel_name = "Sanyo QVGA Portrait";
+	else if (val == SYS_CLCD_ID_EPSON_2_2)
+		panel_name = "Epson L2F50113T00";
+	else if (val == SYS_CLCD_ID_VGA)
+		panel_name = vga_panel_name;
+	else {
+		pr_err("CLCD: unknown LCD panel ID 0x%08x, using VGA\n", val);
+		panel_name = vga_panel_name;
+	}
 
-static int realview_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-				     fb->fb.screen_base,
-				     fb->fb.fix.smem_start,
-				     fb->fb.fix.smem_len);
-}
+	fb->panel = versatile_clcd_get_panel(panel_name);
+	if (!fb->panel)
+		return -EINVAL;
 
-static void realview_clcd_remove(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-			      fb->fb.screen_base, fb->fb.fix.smem_start);
+	return versatile_clcd_setup_dma(fb, framesize);
 }
 
 struct clcd_board clcd_plat_data = {
 	.name		= "RealView",
+	.caps		= CLCD_CAP_ALL,
 	.check		= clcdfb_check,
 	.decode		= clcdfb_decode,
 	.disable	= realview_clcd_disable,
 	.enable		= realview_clcd_enable,
 	.setup		= realview_clcd_setup,
-	.mmap		= realview_clcd_mmap,
-	.remove		= realview_clcd_remove,
+	.mmap		= versatile_clcd_mmap_dma,
+	.remove		= versatile_clcd_remove_dma,
 };
 
 #ifdef CONFIG_LEDS
@@ -656,12 +511,6 @@
 #endif	/* CONFIG_LEDS */
 
 /*
- * The sched_clock counter
- */
-#define REFCOUNTER		(__io_address(REALVIEW_SYS_BASE) + \
-				 REALVIEW_SYS_24MHz_OFFSET)
-
-/*
  * Where is the timer (VA)?
  */
 void __iomem *timer0_va_base;
@@ -676,8 +525,6 @@
 {
 	u32 val;
 
-	versatile_sched_clock_init(REFCOUNTER, 24000000);
-
 	/* 
 	 * set clock frequency: 
 	 *	REALVIEW_REFCLK is 32KHz
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/core.h linux-libre-2.6.39-gnu/arch/arm/mach-realview/core.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/core.h	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,6 @@
 	},							\
 	.dma_mask	= ~0,					\
 	.irq		= base##_IRQ,				\
-	/* .dma		= base##_DMA,*/				\
 }
 
 struct machine_desc;
@@ -63,6 +62,7 @@
 extern int realview_flash_register(struct resource *res, u32 num);
 extern int realview_eth_register(const char *name, struct resource *res);
 extern int realview_usb_register(struct resource *res);
+extern void realview_init_early(void);
 extern void realview_fixup(struct machine_desc *mdesc, struct tag *tags,
 			   char **from, struct meminfo *meminfo);
 extern void (*realview_reset)(char);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/headsmp.S linux-libre-2.6.39-gnu/arch/arm/mach-realview/headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/headsmp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/headsmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- *  linux/arch/arm/mach-realview/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  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/linkage.h>
-#include <linux/init.h>
-
-	__INIT
-
-/*
- * Realview specific entry point for secondary CPUs.  This provides
- * a "holding pen" into which all secondary cores are held until we're
- * ready for them to initialise.
- */
-ENTRY(realview_secondary_startup)
-	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	add	r6, r6, r4
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-	.align
-1:	.long	.
-	.long	pen_release
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/include/mach/barriers.h linux-libre-2.6.39-gnu/arch/arm/mach-realview/include/mach/barriers.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/include/mach/barriers.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/include/mach/barriers.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,5 +4,5 @@
  * operation to deadlock the system.
  */
 #define mb()		dsb()
-#define rmb()		dmb()
+#define rmb()		dsb()
 #define wmb()		mb()
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-realview/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,9 +24,9 @@
  * Physical DRAM offset.
  */
 #ifdef CONFIG_REALVIEW_HIGH_PHYS_OFFSET
-#define PHYS_OFFSET		UL(0x70000000)
+#define PLAT_PHYS_OFFSET		UL(0x70000000)
 #else
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 #endif
 
 #if !defined(__ASSEMBLY__) && defined(CONFIG_ZONE_DMA)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-realview/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 config REALVIEW_EB_ARM11MP
 	bool "Support ARM11MPCore Tile"
 	depends on MACH_REALVIEW_EB
-	select CPU_V6
+	select CPU_V6K
 	select ARCH_HAS_BARRIERS if SMP
 	help
 	  Enable support for the ARM11MPCore tile fitted to the Realview(R)
@@ -36,7 +36,7 @@
 
 config MACH_REALVIEW_PB11MP
 	bool "Support RealView(R) Platform Baseboard for ARM11MPCore"
-	select CPU_V6
+	select CPU_V6K
 	select ARM_GIC
 	select HAVE_PATA_PLATFORM
 	select ARCH_HAS_BARRIERS if SMP
@@ -45,6 +45,7 @@
 	  the ARM11MPCore.  This platform has an on-board ARM11MPCore and has
 	  support for PCI-E and Compact Flash.
 
+# ARMv6 CPU without K extensions, but does have the new exclusive ops
 config MACH_REALVIEW_PB1176
 	bool "Support RealView(R) Platform Baseboard for ARM1176JZF-S"
 	select CPU_V6
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/localtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/localtimer.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- *  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/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 = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-realview/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,5 @@
 obj-$(CONFIG_MACH_REALVIEW_PB1176)	+= realview_pb1176.o
 obj-$(CONFIG_MACH_REALVIEW_PBA8)	+= realview_pba8.o
 obj-$(CONFIG_MACH_REALVIEW_PBX)		+= realview_pbx.o
-obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
+obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
-obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/platsmp.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/platsmp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/platsmp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/platsmp.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,44 +10,21 @@
  */
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
 
-#include <asm/cacheflush.h>
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
+#include <asm/smp_scu.h>
 #include <asm/unified.h>
 
 #include <mach/board-eb.h>
 #include <mach/board-pb11mp.h>
 #include <mach/board-pbx.h>
-#include <asm/smp_scu.h>
 
 #include "core.h"
 
-extern void realview_secondary_startup(void);
-
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-volatile int __cpuinitdata pen_release = -1;
-
-/*
- * Write pen_release in a way that is guaranteed to be visible to all
- * observers, irrespective of whether they're taking part in coherency
- * or not.  This is necessary for the hotplug code to work reliably.
- */
-static void __cpuinit write_pen_release(int val)
-{
-	pen_release = val;
-	smp_wmb();
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
-}
+extern void versatile_secondary_startup(void);
 
 static void __iomem *scu_base_addr(void)
 {
@@ -62,75 +39,6 @@
 		return (void __iomem *)0;
 }
 
-static DEFINE_SPINLOCK(boot_lock);
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
-{
-	/*
-	 * 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_secondary_init(0);
-
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	write_pen_release(-1);
-
-	/*
-	 * 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);
-
-	/*
-	 * The secondary processor is waiting to be released from
-	 * the holding pen - release it, then wait for it to flag
-	 * that it has been released by resetting pen_release.
-	 *
-	 * Note that "pen_release" is the hardware CPU ID, whereas
-	 * "cpu" is Linux's internal ID.
-	 */
-	write_pen_release(cpu);
-
-	/*
-	 * Send the secondary CPU a soft interrupt, thereby causing
-	 * the boot monitor to read the system wide flags register,
-	 * and branch to the address found there.
-	 */
-	smp_cross_call(cpumask_of(cpu), 1);
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
-
 /*
  * Initialise the CPU possible map early - this describes the CPUs
  * which may be present or become present in the system.
@@ -174,6 +82,6 @@
 	 * until it receives a soft interrupt, and then the
 	 * secondary CPU branches to this address.
 	 */
-	__raw_writel(BSYM(virt_to_phys(realview_secondary_startup)),
+	__raw_writel(BSYM(virt_to_phys(versatile_secondary_startup)),
 		     __io_address(REALVIEW_SYS_FLAGSSET));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_eb.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_eb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_eb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_eb.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,60 +144,39 @@
  * These devices are connected via the core APB bridge
  */
 #define GPIO2_IRQ	{ IRQ_EB_GPIO2, NO_IRQ }
-#define GPIO2_DMA	{ 0, 0 }
 #define GPIO3_IRQ	{ IRQ_EB_GPIO3, NO_IRQ }
-#define GPIO3_DMA	{ 0, 0 }
 
 #define AACI_IRQ	{ IRQ_EB_AACI, NO_IRQ }
-#define AACI_DMA	{ 0x80, 0x81 }
 #define MMCI0_IRQ	{ IRQ_EB_MMCI0A, IRQ_EB_MMCI0B }
-#define MMCI0_DMA	{ 0x84, 0 }
 #define KMI0_IRQ	{ IRQ_EB_KMI0, NO_IRQ }
-#define KMI0_DMA	{ 0, 0 }
 #define KMI1_IRQ	{ IRQ_EB_KMI1, NO_IRQ }
-#define KMI1_DMA	{ 0, 0 }
 
 /*
  * These devices are connected directly to the multi-layer AHB switch
  */
 #define EB_SMC_IRQ	{ NO_IRQ, NO_IRQ }
-#define EB_SMC_DMA	{ 0, 0 }
 #define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
-#define MPMC_DMA	{ 0, 0 }
 #define EB_CLCD_IRQ	{ IRQ_EB_CLCD, NO_IRQ }
-#define EB_CLCD_DMA	{ 0, 0 }
 #define DMAC_IRQ	{ IRQ_EB_DMA, NO_IRQ }
-#define DMAC_DMA	{ 0, 0 }
 
 /*
  * These devices are connected via the core APB bridge
  */
 #define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
-#define SCTL_DMA	{ 0, 0 }
 #define EB_WATCHDOG_IRQ	{ IRQ_EB_WDOG, NO_IRQ }
-#define EB_WATCHDOG_DMA	{ 0, 0 }
 #define EB_GPIO0_IRQ	{ IRQ_EB_GPIO0, NO_IRQ }
-#define EB_GPIO0_DMA	{ 0, 0 }
 #define GPIO1_IRQ	{ IRQ_EB_GPIO1, NO_IRQ }
-#define GPIO1_DMA	{ 0, 0 }
 #define EB_RTC_IRQ	{ IRQ_EB_RTC, NO_IRQ }
-#define EB_RTC_DMA	{ 0, 0 }
 
 /*
  * These devices are connected via the DMA APB bridge
  */
 #define SCI_IRQ		{ IRQ_EB_SCI, NO_IRQ }
-#define SCI_DMA		{ 7, 6 }
 #define EB_UART0_IRQ	{ IRQ_EB_UART0, NO_IRQ }
-#define EB_UART0_DMA	{ 15, 14 }
 #define EB_UART1_IRQ	{ IRQ_EB_UART1, NO_IRQ }
-#define EB_UART1_DMA	{ 13, 12 }
 #define EB_UART2_IRQ	{ IRQ_EB_UART2, NO_IRQ }
-#define EB_UART2_DMA	{ 11, 10 }
 #define EB_UART3_IRQ	{ IRQ_EB_UART3, NO_IRQ }
-#define EB_UART3_DMA	{ 0x86, 0x87 }
 #define EB_SSP_IRQ	{ IRQ_EB_SSP, NO_IRQ }
-#define EB_SSP_DMA	{ 9, 8 }
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,  "fpga:aaci",  AACI,     NULL);
@@ -369,7 +348,7 @@
 
 #ifndef CONFIG_REALVIEW_EB_ARM11MP_REVB
 		/* board GIC, secondary */
-		gic_init(1, 64, __io_address(REALVIEW_EB_GIC_DIST_BASE),
+		gic_init(1, 96, __io_address(REALVIEW_EB_GIC_DIST_BASE),
 			 __io_address(REALVIEW_EB_GIC_CPU_BASE));
 		gic_cascade_irq(1, IRQ_EB11MP_EB_IRQ1);
 #endif
@@ -484,9 +463,10 @@
 
 MACHINE_START(REALVIEW_EB, "ARM-RealView EB")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_eb_map_io,
+	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_eb_timer,
 	.init_machine	= realview_eb_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pb1176.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pb1176.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pb1176.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pb1176.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,47 +134,26 @@
  * RealView PB1176 AMBA devices
  */
 #define GPIO2_IRQ	{ IRQ_PB1176_GPIO2, NO_IRQ }
-#define GPIO2_DMA	{ 0, 0 }
 #define GPIO3_IRQ	{ IRQ_PB1176_GPIO3, NO_IRQ }
-#define GPIO3_DMA	{ 0, 0 }
 #define AACI_IRQ	{ IRQ_PB1176_AACI, NO_IRQ }
-#define AACI_DMA	{ 0x80, 0x81 }
 #define MMCI0_IRQ	{ IRQ_PB1176_MMCI0A, IRQ_PB1176_MMCI0B }
-#define MMCI0_DMA	{ 0x84, 0 }
 #define KMI0_IRQ	{ IRQ_PB1176_KMI0, NO_IRQ }
-#define KMI0_DMA	{ 0, 0 }
 #define KMI1_IRQ	{ IRQ_PB1176_KMI1, NO_IRQ }
-#define KMI1_DMA	{ 0, 0 }
 #define PB1176_SMC_IRQ	{ NO_IRQ, NO_IRQ }
-#define PB1176_SMC_DMA	{ 0, 0 }
 #define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
-#define MPMC_DMA	{ 0, 0 }
 #define PB1176_CLCD_IRQ	{ IRQ_DC1176_CLCD, NO_IRQ }
-#define PB1176_CLCD_DMA	{ 0, 0 }
 #define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
-#define SCTL_DMA	{ 0, 0 }
 #define PB1176_WATCHDOG_IRQ	{ IRQ_DC1176_WATCHDOG, NO_IRQ }
-#define PB1176_WATCHDOG_DMA	{ 0, 0 }
 #define PB1176_GPIO0_IRQ	{ IRQ_PB1176_GPIO0, NO_IRQ }
-#define PB1176_GPIO0_DMA	{ 0, 0 }
 #define GPIO1_IRQ	{ IRQ_PB1176_GPIO1, NO_IRQ }
-#define GPIO1_DMA	{ 0, 0 }
 #define PB1176_RTC_IRQ	{ IRQ_DC1176_RTC, NO_IRQ }
-#define PB1176_RTC_DMA	{ 0, 0 }
 #define SCI_IRQ		{ IRQ_PB1176_SCI, NO_IRQ }
-#define SCI_DMA		{ 7, 6 }
 #define PB1176_UART0_IRQ	{ IRQ_DC1176_UART0, NO_IRQ }
-#define PB1176_UART0_DMA	{ 15, 14 }
 #define PB1176_UART1_IRQ	{ IRQ_DC1176_UART1, NO_IRQ }
-#define PB1176_UART1_DMA	{ 13, 12 }
 #define PB1176_UART2_IRQ	{ IRQ_DC1176_UART2, NO_IRQ }
-#define PB1176_UART2_DMA	{ 11, 10 }
 #define PB1176_UART3_IRQ	{ IRQ_DC1176_UART3, NO_IRQ }
-#define PB1176_UART3_DMA	{ 0x86, 0x87 }
 #define PB1176_UART4_IRQ	{ IRQ_PB1176_UART4, NO_IRQ }
-#define PB1176_UART4_DMA	{ 0, 0 }
 #define PB1176_SSP_IRQ		{ IRQ_DC1176_SSP, NO_IRQ }
-#define PB1176_SSP_DMA		{ 9, 8 }
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,	"fpga:aaci",	AACI,		NULL);
@@ -379,9 +358,10 @@
 
 MACHINE_START(REALVIEW_PB1176, "ARM-RealView PB1176")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_pb1176_fixup,
 	.map_io		= realview_pb1176_map_io,
+	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pb1176_timer,
 	.init_machine	= realview_pb1176_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pb11mp.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pb11mp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pb11mp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pb11mp.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,47 +136,26 @@
  */
 
 #define GPIO2_IRQ		{ IRQ_PB11MP_GPIO2, NO_IRQ }
-#define GPIO2_DMA		{ 0, 0 }
 #define GPIO3_IRQ		{ IRQ_PB11MP_GPIO3, NO_IRQ }
-#define GPIO3_DMA		{ 0, 0 }
 #define AACI_IRQ		{ IRQ_TC11MP_AACI, NO_IRQ }
-#define AACI_DMA		{ 0x80, 0x81 }
 #define MMCI0_IRQ		{ IRQ_TC11MP_MMCI0A, IRQ_TC11MP_MMCI0B }
-#define MMCI0_DMA		{ 0x84, 0 }
 #define KMI0_IRQ		{ IRQ_TC11MP_KMI0, NO_IRQ }
-#define KMI0_DMA		{ 0, 0 }
 #define KMI1_IRQ		{ IRQ_TC11MP_KMI1, NO_IRQ }
-#define KMI1_DMA		{ 0, 0 }
 #define PB11MP_SMC_IRQ		{ NO_IRQ, NO_IRQ }
-#define PB11MP_SMC_DMA		{ 0, 0 }
 #define MPMC_IRQ		{ NO_IRQ, NO_IRQ }
-#define MPMC_DMA		{ 0, 0 }
 #define PB11MP_CLCD_IRQ		{ IRQ_PB11MP_CLCD, NO_IRQ }
-#define PB11MP_CLCD_DMA		{ 0, 0 }
 #define DMAC_IRQ		{ IRQ_PB11MP_DMAC, NO_IRQ }
-#define DMAC_DMA		{ 0, 0 }
 #define SCTL_IRQ		{ NO_IRQ, NO_IRQ }
-#define SCTL_DMA		{ 0, 0 }
 #define PB11MP_WATCHDOG_IRQ	{ IRQ_PB11MP_WATCHDOG, NO_IRQ }
-#define PB11MP_WATCHDOG_DMA	{ 0, 0 }
 #define PB11MP_GPIO0_IRQ	{ IRQ_PB11MP_GPIO0, NO_IRQ }
-#define PB11MP_GPIO0_DMA	{ 0, 0 }
 #define GPIO1_IRQ		{ IRQ_PB11MP_GPIO1, NO_IRQ }
-#define GPIO1_DMA		{ 0, 0 }
 #define PB11MP_RTC_IRQ		{ IRQ_TC11MP_RTC, NO_IRQ }
-#define PB11MP_RTC_DMA		{ 0, 0 }
 #define SCI_IRQ			{ IRQ_PB11MP_SCI, NO_IRQ }
-#define SCI_DMA			{ 7, 6 }
 #define PB11MP_UART0_IRQ	{ IRQ_TC11MP_UART0, NO_IRQ }
-#define PB11MP_UART0_DMA	{ 15, 14 }
 #define PB11MP_UART1_IRQ	{ IRQ_TC11MP_UART1, NO_IRQ }
-#define PB11MP_UART1_DMA	{ 13, 12 }
 #define PB11MP_UART2_IRQ	{ IRQ_PB11MP_UART2, NO_IRQ }
-#define PB11MP_UART2_DMA	{ 11, 10 }
 #define PB11MP_UART3_IRQ	{ IRQ_PB11MP_UART3, NO_IRQ }
-#define PB11MP_UART3_DMA	{ 0x86, 0x87 }
 #define PB11MP_SSP_IRQ		{ IRQ_PB11MP_SSP, NO_IRQ }
-#define PB11MP_SSP_DMA		{ 9, 8 }
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,	"fpga:aaci",	AACI,		NULL);
@@ -381,9 +360,10 @@
 
 MACHINE_START(REALVIEW_PB11MP, "ARM-RealView PB11MPCore")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pb11mp_map_io,
+	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pb11mp_timer,
 	.init_machine	= realview_pb11mp_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pba8.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pba8.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pba8.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pba8.c	2011-05-19 00:06:34.000000000 -0400
@@ -126,47 +126,26 @@
  */
 
 #define GPIO2_IRQ		{ IRQ_PBA8_GPIO2, NO_IRQ }
-#define GPIO2_DMA		{ 0, 0 }
 #define GPIO3_IRQ		{ IRQ_PBA8_GPIO3, NO_IRQ }
-#define GPIO3_DMA		{ 0, 0 }
 #define AACI_IRQ		{ IRQ_PBA8_AACI, NO_IRQ }
-#define AACI_DMA		{ 0x80, 0x81 }
 #define MMCI0_IRQ		{ IRQ_PBA8_MMCI0A, IRQ_PBA8_MMCI0B }
-#define MMCI0_DMA		{ 0x84, 0 }
 #define KMI0_IRQ		{ IRQ_PBA8_KMI0, NO_IRQ }
-#define KMI0_DMA		{ 0, 0 }
 #define KMI1_IRQ		{ IRQ_PBA8_KMI1, NO_IRQ }
-#define KMI1_DMA		{ 0, 0 }
 #define PBA8_SMC_IRQ		{ NO_IRQ, NO_IRQ }
-#define PBA8_SMC_DMA		{ 0, 0 }
 #define MPMC_IRQ		{ NO_IRQ, NO_IRQ }
-#define MPMC_DMA		{ 0, 0 }
 #define PBA8_CLCD_IRQ		{ IRQ_PBA8_CLCD, NO_IRQ }
-#define PBA8_CLCD_DMA		{ 0, 0 }
 #define DMAC_IRQ		{ IRQ_PBA8_DMAC, NO_IRQ }
-#define DMAC_DMA		{ 0, 0 }
 #define SCTL_IRQ		{ NO_IRQ, NO_IRQ }
-#define SCTL_DMA		{ 0, 0 }
 #define PBA8_WATCHDOG_IRQ	{ IRQ_PBA8_WATCHDOG, NO_IRQ }
-#define PBA8_WATCHDOG_DMA	{ 0, 0 }
 #define PBA8_GPIO0_IRQ		{ IRQ_PBA8_GPIO0, NO_IRQ }
-#define PBA8_GPIO0_DMA		{ 0, 0 }
 #define GPIO1_IRQ		{ IRQ_PBA8_GPIO1, NO_IRQ }
-#define GPIO1_DMA		{ 0, 0 }
 #define PBA8_RTC_IRQ		{ IRQ_PBA8_RTC, NO_IRQ }
-#define PBA8_RTC_DMA		{ 0, 0 }
 #define SCI_IRQ			{ IRQ_PBA8_SCI, NO_IRQ }
-#define SCI_DMA			{ 7, 6 }
 #define PBA8_UART0_IRQ		{ IRQ_PBA8_UART0, NO_IRQ }
-#define PBA8_UART0_DMA		{ 15, 14 }
 #define PBA8_UART1_IRQ		{ IRQ_PBA8_UART1, NO_IRQ }
-#define PBA8_UART1_DMA		{ 13, 12 }
 #define PBA8_UART2_IRQ		{ IRQ_PBA8_UART2, NO_IRQ }
-#define PBA8_UART2_DMA		{ 11, 10 }
 #define PBA8_UART3_IRQ		{ IRQ_PBA8_UART3, NO_IRQ }
-#define PBA8_UART3_DMA		{ 0x86, 0x87 }
 #define PBA8_SSP_IRQ		{ IRQ_PBA8_SSP, NO_IRQ }
-#define PBA8_SSP_DMA		{ 9, 8 }
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,	"fpga:aaci",	AACI,		NULL);
@@ -331,9 +310,10 @@
 
 MACHINE_START(REALVIEW_PBA8, "ARM-RealView PB-A8")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_fixup,
 	.map_io		= realview_pba8_map_io,
+	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pba8_timer,
 	.init_machine	= realview_pba8_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pbx.c linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pbx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-realview/realview_pbx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-realview/realview_pbx.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,47 +148,26 @@
  */
 
 #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:aaci",	AACI,		NULL);
@@ -414,9 +393,10 @@
 
 MACHINE_START(REALVIEW_PBX, "ARM-RealView PBX")
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.fixup		= realview_pbx_fixup,
 	.map_io		= realview_pbx_map_io,
+	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
 	.timer		= &realview_pbx_timer,
 	.init_machine	= realview_pbx_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-rpc/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-rpc/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-rpc/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-rpc/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x10000000)
+#define PLAT_PHYS_OFFSET	UL(0x10000000)
 
 /*
  * Cache flushing area - ROM
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-rpc/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-rpc/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-rpc/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-rpc/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,25 +133,25 @@
 
 		switch (irq) {
 		case 0 ... 7:
-			set_irq_chip(irq, &iomd_a_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &iomd_a_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, flags);
 			break;
 
 		case 8 ... 15:
-			set_irq_chip(irq, &iomd_b_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &iomd_b_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, flags);
 			break;
 
 		case 16 ... 21:
-			set_irq_chip(irq, &iomd_dma_chip);
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_chip_and_handler(irq, &iomd_dma_chip,
+						 handle_level_irq);
 			set_irq_flags(irq, flags);
 			break;
 
 		case 64 ... 71:
-			set_irq_chip(irq, &iomd_fiq_chip);
+			irq_set_chip(irq, &iomd_fiq_chip);
 			set_irq_flags(irq, IRQF_VALID);
 			break;
 		}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2400/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c2400/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2400/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2400/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x0C000000)
+#define PLAT_PHYS_OFFSET	UL(0x0C000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/bast-irq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/bast-irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/bast-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/bast-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -147,15 +147,15 @@
 
 		__raw_writeb(0x0, BAST_VA_PC104_IRQMASK);
 
-		set_irq_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
+		irq_set_chained_handler(IRQ_ISA, bast_irq_pc104_demux);
 
 		/* register our IRQs */
 
 		for (i = 0; i < 4; i++) {
 			unsigned int irqno = bast_pc104_irqs[i];
 
-			set_irq_chip(irqno, &bast_pc104_chip);
-			set_irq_handler(irqno, handle_level_irq);
+			irq_set_chip_and_handler(irqno, &bast_pc104_chip,
+						 handle_level_irq);
 			set_irq_flags(irqno, IRQF_VALID);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/h1940-bluetooth.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,12 +18,14 @@
 #include <linux/leds.h>
 #include <linux/gpio.h>
 #include <linux/rfkill.h>
+#include <linux/leds.h>
 
 #include <mach/regs-gpio.h>
 #include <mach/hardware.h>
 #include <mach/h1940-latch.h>
+#include <mach/h1940.h>
 
-#define DRV_NAME              "h1940-bt"
+#define DRV_NAME "h1940-bt"
 
 /* Bluetooth control */
 static void h1940bt_enable(int on)
@@ -37,6 +39,8 @@
 		gpio_set_value(S3C2410_GPH(1), 1);
 		mdelay(10);
 		gpio_set_value(S3C2410_GPH(1), 0);
+
+		h1940_led_blink_set(-EINVAL, GPIO_LED_BLINK, NULL, NULL);
 	}
 	else {
 		gpio_set_value(S3C2410_GPH(1), 1);
@@ -44,6 +48,8 @@
 		gpio_set_value(S3C2410_GPH(1), 0);
 		mdelay(10);
 		gpio_set_value(H1940_LATCH_BLUETOOTH_POWER, 0);
+
+		h1940_led_blink_set(-EINVAL, GPIO_LED_NO_BLINK_LOW, NULL, NULL);
 	}
 }
 
@@ -85,7 +91,6 @@
 	s3c_gpio_cfgpin(S3C2410_GPH(3), S3C2410_GPH3_RXD0);
 	s3c_gpio_setpull(S3C2410_GPH(3), S3C_GPIO_PULL_NONE);
 
-
 	rfk = rfkill_alloc(DRV_NAME, &pdev->dev, RFKILL_TYPE_BLUETOOTH,
 			&h1940bt_rfkill_ops, NULL);
 	if (!rfk) {
@@ -93,8 +98,6 @@
 		goto err_rfk_alloc;
 	}
 
-	rfkill_set_led_trigger_name(rfk, "h1940-bluetooth");
-
 	ret = rfkill_register(rfk);
 	if (ret)
 		goto err_rfkill;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/dma.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 #define MAX_DMA_TRANSFER_SIZE   0x100000 /* Data Unit is half word  */
 
 /* We use `virtual` dma channels to hide the fact we have only a limited
- * number of DMA channels, and not of all of them (dependant on the device)
+ * number of DMA channels, and not of all of them (dependent on the device)
  * can be attached to any DMA source. We therefore let the DMA core handle
  * the allocation of hardware channels to clients.
 */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/h1940.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/h1940.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/h1940.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/h1940.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,5 +17,8 @@
 #define H1940_SUSPEND_CHECK		(0x30080000)
 
 extern void h1940_pm_return(void);
+extern int h1940_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off);
+
 
 #endif /* __ASM_ARCH_H1940_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x30000000)
+#define PLAT_PHYS_OFFSET	UL(0x30000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/regs-mem.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/regs-mem.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/include/mach/regs-mem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/include/mach/regs-mem.h	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 #define S3C2410_BANKCON_PMC16		(0x03)
 
 /* bank configurations for banks 0..7, note banks
- * 6 and 7 have differnt configurations depending on
+ * 6 and 7 have different configurations depending on
  * the memory type bits */
 
 #define S3C2410_BANKCON_Tacp2		(0x0 << 2)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/mach-h1940.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/mach-h1940.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/mach-h1940.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/mach-h1940.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,8 +23,15 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
 #include <linux/pwm_backlight.h>
 #include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/pda_power.h>
+#include <linux/s3c_adc_battery.h>
+#include <linux/delay.h>
+
 #include <video/platform_lcd.h>
 
 #include <linux/mmc/host.h>
@@ -162,29 +169,10 @@
 	.get			= h1940_gpiolib_latch_get,
 };
 
-static void h1940_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
-
-	switch (cmd)
-	{
-		case S3C2410_UDC_P_ENABLE :
-			gpio_set_value(H1940_LATCH_USB_DP, 1);
-			break;
-		case S3C2410_UDC_P_DISABLE :
-			gpio_set_value(H1940_LATCH_USB_DP, 0);
-			break;
-		case S3C2410_UDC_P_RESET :
-			break;
-		default:
-			break;
-	}
-}
-
 static struct s3c2410_udc_mach_info h1940_udc_cfg __initdata = {
-	.udc_command		= h1940_udc_pullup,
 	.vbus_pin		= S3C2410_GPG(5),
 	.vbus_pin_inverted	= 1,
+	.pullup_pin		= H1940_LATCH_USB_DP,
 };
 
 static struct s3c2410_ts_mach_info h1940_ts_cfg __initdata = {
@@ -222,20 +210,239 @@
 	.num_displays = 1,
 	.default_display = 0,
 
-	.lpcsel=	0x02,
-	.gpccon=	0xaa940659,
-	.gpccon_mask=	0xffffffff,
-	.gpcup=		0x0000ffff,
-	.gpcup_mask=	0xffffffff,
-	.gpdcon=	0xaa84aaa0,
-	.gpdcon_mask=	0xffffffff,
-	.gpdup=		0x0000faff,
-	.gpdup_mask=	0xffffffff,
+	.lpcsel =	0x02,
+	.gpccon =	0xaa940659,
+	.gpccon_mask =	0xffffc0f0,
+	.gpcup =	0x0000ffff,
+	.gpcup_mask =	0xffffffff,
+	.gpdcon =	0xaa84aaa0,
+	.gpdcon_mask =	0xffffffff,
+	.gpdup =	0x0000faff,
+	.gpdup_mask =	0xffffffff,
 };
 
-static struct platform_device h1940_device_leds = {
-	.name             = "h1940-leds",
+static int power_supply_init(struct device *dev)
+{
+	return gpio_request(S3C2410_GPF(2), "cable plugged");
+}
+
+static int h1940_is_ac_online(void)
+{
+	return !gpio_get_value(S3C2410_GPF(2));
+}
+
+static void power_supply_exit(struct device *dev)
+{
+	gpio_free(S3C2410_GPF(2));
+}
+
+static char *h1940_supplicants[] = {
+	"main-battery",
+	"backup-battery",
+};
+
+static struct pda_power_pdata power_supply_info = {
+	.init			= power_supply_init,
+	.is_ac_online		= h1940_is_ac_online,
+	.exit			= power_supply_exit,
+	.supplied_to		= h1940_supplicants,
+	.num_supplicants	= ARRAY_SIZE(h1940_supplicants),
+};
+
+static struct resource power_supply_resources[] = {
+	[0] = {
+			.name	= "ac",
+			.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_LOWEDGE |
+					  IORESOURCE_IRQ_HIGHEDGE,
+			.start	= IRQ_EINT2,
+			.end	= IRQ_EINT2,
+	},
+};
+
+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),
+};
+
+static const struct s3c_adc_bat_thresh bat_lut_noac[] = {
+	{ .volt = 4070, .cur = 162, .level = 100},
+	{ .volt = 4040, .cur = 165, .level = 95},
+	{ .volt = 4016, .cur = 164, .level = 90},
+	{ .volt = 3996, .cur = 166, .level = 85},
+	{ .volt = 3971, .cur = 168, .level = 80},
+	{ .volt = 3951, .cur = 168, .level = 75},
+	{ .volt = 3931, .cur = 170, .level = 70},
+	{ .volt = 3903, .cur = 172, .level = 65},
+	{ .volt = 3886, .cur = 172, .level = 60},
+	{ .volt = 3858, .cur = 176, .level = 55},
+	{ .volt = 3842, .cur = 176, .level = 50},
+	{ .volt = 3818, .cur = 176, .level = 45},
+	{ .volt = 3789, .cur = 180, .level = 40},
+	{ .volt = 3769, .cur = 180, .level = 35},
+	{ .volt = 3749, .cur = 184, .level = 30},
+	{ .volt = 3732, .cur = 184, .level = 25},
+	{ .volt = 3716, .cur = 184, .level = 20},
+	{ .volt = 3708, .cur = 184, .level = 15},
+	{ .volt = 3716, .cur = 96, .level = 10},
+	{ .volt = 3700, .cur = 96, .level = 5},
+	{ .volt = 3684, .cur = 96, .level = 0},
+};
+
+static const struct s3c_adc_bat_thresh bat_lut_acin[] = {
+	{ .volt = 4130, .cur = 0, .level = 100},
+	{ .volt = 3982, .cur = 0, .level = 50},
+	{ .volt = 3854, .cur = 0, .level = 10},
+	{ .volt = 3841, .cur = 0, .level = 0},
+};
+
+int h1940_bat_init(void)
+{
+	int ret;
+
+	ret = gpio_request(H1940_LATCH_SM803_ENABLE, "h1940-charger-enable");
+	if (ret)
+		return ret;
+	gpio_direction_output(H1940_LATCH_SM803_ENABLE, 0);
+
+	return 0;
+
+}
+
+void h1940_bat_exit(void)
+{
+	gpio_free(H1940_LATCH_SM803_ENABLE);
+}
+
+void h1940_enable_charger(void)
+{
+	gpio_set_value(H1940_LATCH_SM803_ENABLE, 1);
+}
+
+void h1940_disable_charger(void)
+{
+	gpio_set_value(H1940_LATCH_SM803_ENABLE, 0);
+}
+
+static struct s3c_adc_bat_pdata h1940_bat_cfg = {
+	.init = h1940_bat_init,
+	.exit = h1940_bat_exit,
+	.enable_charger = h1940_enable_charger,
+	.disable_charger = h1940_disable_charger,
+	.gpio_charge_finished = S3C2410_GPF(3),
+	.gpio_inverted = 1,
+	.lut_noac = bat_lut_noac,
+	.lut_noac_cnt = ARRAY_SIZE(bat_lut_noac),
+	.lut_acin = bat_lut_acin,
+	.lut_acin_cnt = ARRAY_SIZE(bat_lut_acin),
+	.volt_channel = 0,
+	.current_channel = 1,
+	.volt_mult = 4056,
+	.current_mult = 1893,
+	.internal_impedance = 200,
+	.backup_volt_channel = 3,
+	/* TODO Check backup volt multiplier */
+	.backup_volt_mult = 4056,
+	.backup_volt_min = 0,
+	.backup_volt_max = 4149288
+};
+
+static struct platform_device h1940_battery = {
+	.name             = "s3c-adc-battery",
 	.id               = -1,
+	.dev = {
+		.parent = &s3c_device_adc.dev,
+		.platform_data = &h1940_bat_cfg,
+	},
+};
+
+DEFINE_SPINLOCK(h1940_blink_spin);
+
+int h1940_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off)
+{
+	int blink_gpio, check_gpio1, check_gpio2;
+
+	switch (gpio) {
+	case H1940_LATCH_LED_GREEN:
+		blink_gpio = S3C2410_GPA(7);
+		check_gpio1 = S3C2410_GPA(1);
+		check_gpio2 = S3C2410_GPA(3);
+		break;
+	case H1940_LATCH_LED_RED:
+		blink_gpio = S3C2410_GPA(1);
+		check_gpio1 = S3C2410_GPA(7);
+		check_gpio2 = S3C2410_GPA(3);
+		break;
+	default:
+		blink_gpio = S3C2410_GPA(3);
+		check_gpio1 = S3C2410_GPA(1);
+		check_gpio1 = S3C2410_GPA(7);
+		break;
+	}
+
+	if (delay_on && delay_off && !*delay_on && !*delay_off)
+		*delay_on = *delay_off = 500;
+
+	spin_lock(&h1940_blink_spin);
+
+	switch (state) {
+	case GPIO_LED_NO_BLINK_LOW:
+	case GPIO_LED_NO_BLINK_HIGH:
+		if (!gpio_get_value(check_gpio1) &&
+		    !gpio_get_value(check_gpio2))
+			gpio_set_value(H1940_LATCH_LED_FLASH, 0);
+		gpio_set_value(blink_gpio, 0);
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, state);
+		break;
+	case GPIO_LED_BLINK:
+		if (gpio_is_valid(gpio))
+			gpio_set_value(gpio, 0);
+		gpio_set_value(H1940_LATCH_LED_FLASH, 1);
+		gpio_set_value(blink_gpio, 1);
+		break;
+	}
+
+	spin_unlock(&h1940_blink_spin);
+
+	return 0;
+}
+EXPORT_SYMBOL(h1940_led_blink_set);
+
+static struct gpio_led h1940_leds_desc[] = {
+	{
+		.name			= "Green",
+		.default_trigger	= "main-battery-full",
+		.gpio			= H1940_LATCH_LED_GREEN,
+		.retain_state_suspended	= 1,
+	},
+	{
+		.name			= "Red",
+		.default_trigger
+			= "main-battery-charging-blink-full-solid",
+		.gpio			= H1940_LATCH_LED_RED,
+		.retain_state_suspended	= 1,
+	},
+};
+
+static struct gpio_led_platform_data h1940_leds_pdata = {
+	.num_leds	= ARRAY_SIZE(h1940_leds_desc),
+	.leds		= h1940_leds_desc,
+	.gpio_blink_set	= h1940_led_blink_set,
+};
+
+static struct platform_device h1940_device_leds = {
+	.name	= "leds-gpio",
+	.id	= -1,
+	.dev	= {
+			.platform_data = &h1940_leds_pdata,
+	},
 };
 
 static struct platform_device h1940_device_bluetooth = {
@@ -321,14 +528,14 @@
 static void h1940_lcd_power_set(struct plat_lcd_data *pd,
 					unsigned int power)
 {
-	int value;
+	int value, retries = 100;
 
 	if (!power) {
 		gpio_set_value(S3C2410_GPC(0), 0);
 		/* wait for 3ac */
 		do {
 			value = gpio_get_value(S3C2410_GPC(6));
-		} while (value);
+		} while (value && retries--);
 
 		gpio_set_value(H1940_LATCH_LCD_P2, 0);
 		gpio_set_value(H1940_LATCH_LCD_P3, 0);
@@ -346,6 +553,9 @@
 		gpio_set_value(H1940_LATCH_LCD_P0, 1);
 		gpio_set_value(H1940_LATCH_LCD_P1, 1);
 
+		gpio_direction_input(S3C2410_GPC(1));
+		gpio_direction_input(S3C2410_GPC(4));
+		mdelay(10);
 		s3c_gpio_cfgpin(S3C2410_GPC(1), S3C_GPIO_SFN(2));
 		s3c_gpio_cfgpin(S3C2410_GPC(4), S3C_GPIO_SFN(2));
 
@@ -381,7 +591,44 @@
 	},
 };
 
+#define DECLARE_BUTTON(p, k, n, w)	\
+	{				\
+		.gpio		= p,	\
+		.code		= k,	\
+		.desc		= n,	\
+		.wakeup		= w,	\
+		.active_low	= 1,	\
+	}
+
+static struct gpio_keys_button h1940_buttons[] = {
+	DECLARE_BUTTON(S3C2410_GPF(0),       KEY_POWER,          "Power", 1),
+	DECLARE_BUTTON(S3C2410_GPF(6),       KEY_ENTER,         "Select", 1),
+	DECLARE_BUTTON(S3C2410_GPF(7),      KEY_RECORD,         "Record", 0),
+	DECLARE_BUTTON(S3C2410_GPG(0),         KEY_F11,       "Calendar", 0),
+	DECLARE_BUTTON(S3C2410_GPG(2),         KEY_F12,       "Contacts", 0),
+	DECLARE_BUTTON(S3C2410_GPG(3),        KEY_MAIL,           "Mail", 0),
+	DECLARE_BUTTON(S3C2410_GPG(6),        KEY_LEFT,     "Left_arrow", 0),
+	DECLARE_BUTTON(S3C2410_GPG(7),    KEY_HOMEPAGE,           "Home", 0),
+	DECLARE_BUTTON(S3C2410_GPG(8),       KEY_RIGHT,    "Right_arrow", 0),
+	DECLARE_BUTTON(S3C2410_GPG(9),          KEY_UP,       "Up_arrow", 0),
+	DECLARE_BUTTON(S3C2410_GPG(10),       KEY_DOWN,     "Down_arrow", 0),
+};
+
+static struct gpio_keys_platform_data h1940_buttons_data = {
+	.buttons	= h1940_buttons,
+	.nbuttons	= ARRAY_SIZE(h1940_buttons),
+};
+
+static struct platform_device h1940_dev_buttons = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data  = &h1940_buttons_data,
+	}
+};
+
 static struct platform_device *h1940_devices[] __initdata = {
+	&h1940_dev_buttons,
 	&s3c_device_ohci,
 	&s3c_device_lcd,
 	&s3c_device_wdt,
@@ -398,6 +645,8 @@
 	&h1940_lcd_powerdev,
 	&s3c_device_adc,
 	&s3c_device_ts,
+	&power_supply,
+	&h1940_battery,
 };
 
 static void __init h1940_map_io(void)
@@ -475,14 +724,20 @@
 	gpio_direction_output(H1940_LATCH_LCD_P4, 0);
 	gpio_direction_output(H1940_LATCH_MAX1698_nSHUTDOWN, 0);
 
-	gpio_request(H1940_LATCH_USB_DP, "USB pullup");
-	gpio_direction_output(H1940_LATCH_USB_DP, 0);
-
 	gpio_request(H1940_LATCH_SD_POWER, "SD power");
 	gpio_direction_output(H1940_LATCH_SD_POWER, 0);
 
 	platform_add_devices(h1940_devices, ARRAY_SIZE(h1940_devices));
 
+	gpio_request(S3C2410_GPA(1), "Red LED blink");
+	gpio_request(S3C2410_GPA(3), "Blue LED blink");
+	gpio_request(S3C2410_GPA(7), "Green LED blink");
+	gpio_request(H1940_LATCH_LED_FLASH, "LED blink");
+	gpio_direction_output(S3C2410_GPA(1), 0);
+	gpio_direction_output(S3C2410_GPA(3), 0);
+	gpio_direction_output(S3C2410_GPA(7), 0);
+	gpio_direction_output(H1940_LATCH_LED_FLASH, 0);
+
 	i2c_register_board_info(0, h1940_i2c_devices,
 		ARRAY_SIZE(h1940_i2c_devices));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/mach-n30.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/mach-n30.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2410/mach-n30.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2410/mach-n30.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,26 +84,10 @@
 	},
 };
 
-static void n30_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	switch (cmd) {
-	case S3C2410_UDC_P_ENABLE :
-		gpio_set_value(S3C2410_GPB(3), 1);
-		break;
-	case S3C2410_UDC_P_DISABLE :
-		gpio_set_value(S3C2410_GPB(3), 0);
-		break;
-	case S3C2410_UDC_P_RESET :
-		break;
-	default:
-		break;
-	}
-}
-
 static struct s3c2410_udc_mach_info n30_udc_cfg __initdata = {
-	.udc_command		= n30_udc_pullup,
 	.vbus_pin		= S3C2410_GPG(1),
 	.vbus_pin_inverted	= 0,
+	.pullup_pin		= S3C2410_GPB(3),
 };
 
 static struct gpio_keys_button n30_buttons[] = {
@@ -268,7 +252,7 @@
 	.def_trigger	= "",
 };
 
-/* This is the blue LED on the device. Originaly used to indicate GPS activity
+/* This is the blue LED on the device. Originally used to indicate GPS activity
  * by flashing. */
 static struct s3c24xx_led_platdata n35_blue_led_pdata = {
 	.name		= "blue_led",
@@ -596,9 +580,6 @@
 
 		platform_add_devices(n35_devices, ARRAY_SIZE(n35_devices));
 	}
-
-	WARN_ON(gpio_request(S3C2410_GPB(3), "udc pup"));
-	gpio_direction_output(S3C2410_GPB(3), 0);
 }
 
 MACHINE_START(N30, "Acer-N30")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2412/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2412/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2412/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2412/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -175,18 +175,18 @@
 	unsigned int irqno;
 
 	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
-		set_irq_chip(irqno, &s3c2412_irq_eint0t4);
-		set_irq_handler(irqno, handle_edge_irq);
+		irq_set_chip_and_handler(irqno, &s3c2412_irq_eint0t4,
+					 handle_edge_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
 	/* add demux support for CF/SDI */
 
-	set_irq_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
+	irq_set_chained_handler(IRQ_S3C2412_CFSDI, s3c2412_irq_demux_cfsdi);
 
 	for (irqno = IRQ_S3C2412_SDI; irqno <= IRQ_S3C2412_CF; irqno++) {
-		set_irq_chip(irqno, &s3c2412_irq_cfsdi);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &s3c2412_irq_cfsdi,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
@@ -195,7 +195,7 @@
 	s3c2412_irq_rtc_chip = s3c_irq_chip;
 	s3c2412_irq_rtc_chip.irq_set_wake = s3c2412_irq_rtc_wake;
 
-	set_irq_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
+	irq_set_chip(IRQ_RTC, &s3c2412_irq_rtc_chip);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2412/mach-smdk2413.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,28 +78,9 @@
 	}
 };
 
-static void smdk2413_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	printk(KERN_DEBUG "udc: pullup(%d)\n",cmd);
-
-	switch (cmd)
-	{
-		case S3C2410_UDC_P_ENABLE :
-			gpio_set_value(S3C2410_GPF(2), 1);
-			break;
-		case S3C2410_UDC_P_DISABLE :
-			gpio_set_value(S3C2410_GPF(2), 0);
-			break;
-		case S3C2410_UDC_P_RESET :
-			break;
-		default:
-			break;
-	}
-}
-
 
 static struct s3c2410_udc_mach_info smdk2413_udc_cfg __initdata = {
-	.udc_command		= smdk2413_udc_pullup,
+	.pullup_pin = S3C2410_GPF(2),
 };
 
 
@@ -133,9 +114,6 @@
 {	/* Turn off suspend on both USB ports, and switch the
 	 * selectable USB port to USB device mode. */
 
-	WARN_ON(gpio_request(S3C2410_GPF(2), "udc pull"));
-	gpio_direction_output(S3C2410_GPF(2), 0);
-
 	s3c2410_modify_misccr(S3C2410_MISCCR_USBHOST |
 			      S3C2410_MISCCR_USBSUSPND0 |
 			      S3C2410_MISCCR_USBSUSPND1, 0x0);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2416/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2416/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2416/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2416/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,13 +202,11 @@
 {
 	unsigned int irqno;
 
-	set_irq_chip(base, &s3c_irq_level_chip);
-	set_irq_handler(base, handle_level_irq);
-	set_irq_chained_handler(base, demux);
+	irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
+	irq_set_chained_handler(base, demux);
 
 	for (irqno = start; irqno <= end; irqno++) {
-		set_irq_chip(irqno, chip);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, chip, handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,13 +100,13 @@
 
 	/* add new chained handler for wdt, ac7 */
 
-	set_irq_chip(IRQ_WDT, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_WDT, handle_level_irq);
-	set_irq_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
+	irq_set_chip_and_handler(IRQ_WDT, &s3c_irq_level_chip,
+				 handle_level_irq);
+	irq_set_chained_handler(IRQ_WDT, s3c_irq_demux_wdtac97);
 
 	for (irqno = IRQ_S3C2440_WDT; irqno <= IRQ_S3C2440_AC97; irqno++) {
-		set_irq_chip(irqno, &s3c_irq_wdtac97);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_wdtac97,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-gta02.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/mach-gta02.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-gta02.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/mach-gta02.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,9 @@
 #include <linux/mfd/pcf50633/pmic.h>
 #include <linux/mfd/pcf50633/backlight.h>
 
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -86,6 +89,8 @@
 #include <plat/udc.h>
 #include <plat/gpio-cfg.h>
 #include <plat/iic.h>
+#include <plat/ts.h>
+
 
 static struct pcf50633 *gta02_pcf;
 
@@ -280,9 +285,6 @@
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
 				.always_on = 1,
 				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_DOWN1] = {
@@ -301,9 +303,6 @@
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
 				.apply_uV = 1,
 				.always_on = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_HCLDO] = {
@@ -311,8 +310,8 @@
 				.min_uV = 2000000,
 				.max_uV = 3300000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE,
-				.always_on = 1,
+				.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+						REGULATOR_CHANGE_STATUS,
 			},
 		},
 		[PCF50633_REGULATOR_LDO1] = {
@@ -320,10 +319,8 @@
 				.min_uV = 3300000,
 				.max_uV = 3300000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 0,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_LDO2] = {
@@ -347,6 +344,7 @@
 				.min_uV = 3200000,
 				.max_uV = 3200000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 				.apply_uV = 1,
 			},
 		},
@@ -355,10 +353,8 @@
 				.min_uV = 3000000,
 				.max_uV = 3000000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
+				.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 				.apply_uV = 1,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 		[PCF50633_REGULATOR_LDO6] = {
@@ -373,9 +369,6 @@
 				.min_uV = 1800000,
 				.max_uV = 1800000,
 				.valid_modes_mask = REGULATOR_MODE_NORMAL,
-				.state_mem = {
-					.enabled = 1,
-				},
 			},
 		},
 
@@ -416,6 +409,10 @@
 	.num_resources	= 0,
 };
 
+static struct platform_device gta02_dfbmcs320_device = {
+	.name = "dfbmcs320",
+};
+
 static struct i2c_board_info gta02_i2c_devs[] __initdata = {
 	{
 		I2C_BOARD_INFO("pcf50633", 0x73),
@@ -455,28 +452,10 @@
 };
 
 
-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 = {
+static struct s3c2410_udc_mach_info gta02_udc_cfg __initdata = {
 	.vbus_draw	= gta02_udc_vbus_draw,
-	.udc_command	= gta02_udc_command,
-
+	.pullup_pin = GTA02_GPIO_USB_PULLUP,
 };
 
 /* USB */
@@ -489,6 +468,43 @@
 	},
 };
 
+/* Touchscreen */
+static struct s3c2410_ts_mach_info gta02_ts_info = {
+	.delay			= 10000,
+	.presc			= 0xff, /* slow as we can go */
+	.oversampling_shift	= 2,
+};
+
+/* Buttons */
+static struct gpio_keys_button gta02_buttons[] = {
+	{
+		.gpio = GTA02_GPIO_AUX_KEY,
+		.code = KEY_PHONE,
+		.desc = "Aux",
+		.type = EV_KEY,
+		.debounce_interval = 100,
+	},
+	{
+		.gpio = GTA02_GPIO_HOLD_KEY,
+		.code = KEY_PAUSE,
+		.desc = "Hold",
+		.type = EV_KEY,
+		.debounce_interval = 100,
+	},
+};
+
+static struct gpio_keys_platform_data gta02_buttons_pdata = {
+	.buttons = gta02_buttons,
+	.nbuttons = ARRAY_SIZE(gta02_buttons),
+};
+
+static struct platform_device gta02_buttons_device = {
+	.name = "gpio-keys",
+	.id = -1,
+	.dev = {
+		.platform_data = &gta02_buttons_pdata,
+	},
+};
 
 static void __init gta02_map_io(void)
 {
@@ -509,7 +525,12 @@
 	&gta02_nor_flash,
 	&s3c24xx_pwm_device,
 	&s3c_device_iis,
+	&samsung_asoc_dma,
 	&s3c_device_i2c0,
+	&gta02_dfbmcs320_device,
+	&gta02_buttons_device,
+	&s3c_device_adc,
+	&s3c_device_ts,
 };
 
 /* These guys DO need to be children of PMU. */
@@ -559,6 +580,7 @@
 #endif
 
 	s3c24xx_udc_set_platdata(&gta02_udc_cfg);
+	s3c24xx_ts_set_platdata(&gta02_ts_info);
 	s3c_ohci_set_platdata(&gta02_usb_info);
 	s3c_nand_set_platdata(&gta02_nand_info);
 	s3c_i2c0_set_platdata(NULL);
@@ -567,6 +589,8 @@
 
 	platform_add_devices(gta02_devices, ARRAY_SIZE(gta02_devices));
 	pm_power_off = gta02_poweroff;
+
+	regulator_has_full_constraints();
 }
 
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-mini2440.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/mach-mini2440.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/mach-mini2440.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,26 +97,8 @@
 
 /* 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 :
-			gpio_set_value(S3C2410_GPC(5), 1);
-			break;
-		case S3C2410_UDC_P_DISABLE :
-			gpio_set_value(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,
+	.pullup_pin = S3C2410_GPC(5),
 };
 
 
@@ -173,7 +155,7 @@
 	 * 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.
+	 * Therefore timings for other resolutions have been omitted here.
 	 */
 	[2] = {
 		_LCD_DECLARE(
@@ -506,6 +488,11 @@
 	},
 };
 
+static struct platform_device uda1340_codec = {
+		.name = "uda134x-codec",
+		.id = -1,
+};
+
 static struct platform_device *mini2440_devices[] __initdata = {
 	&s3c_device_ohci,
 	&s3c_device_wdt,
@@ -521,7 +508,9 @@
 	&s3c_device_nand,
 	&s3c_device_sdi,
 	&s3c_device_iis,
+	&uda1340_codec,
 	&mini2440_audio,
+	&samsung_asoc_dma,
 };
 
 static void __init mini2440_map_io(void)
@@ -644,10 +633,6 @@
 	s3c2410_gpio_setpin(S3C2410_GPB(1), 0);
 	s3c_gpio_cfgpin(S3C2410_GPB(1), S3C2410_GPIO_INPUT);
 
-	/* Make sure the D+ pullup pin is output */
-	WARN_ON(gpio_request(S3C2410_GPC(5), "udc pup"));
-	gpio_direction_output(S3C2410_GPC(5), 0);
-
 	/* mark the key as input, without pullups (there is one on the board) */
 	for (i = 0; i < ARRAY_SIZE(mini2440_buttons); i++) {
 		s3c_gpio_setpull(mini2440_buttons[i].gpio, S3C_GPIO_PULL_UP);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-rx1950.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/mach-rx1950.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/mach-rx1950.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/mach-rx1950.c	2011-05-19 00:06:34.000000000 -0400
@@ -263,27 +263,78 @@
 	gpio_direction_output(S3C2410_GPJ(3), 0);
 }
 
+DEFINE_SPINLOCK(rx1950_blink_spin);
+
+static int rx1950_led_blink_set(unsigned gpio, int state,
+	unsigned long *delay_on, unsigned long *delay_off)
+{
+	int blink_gpio, check_gpio;
+
+	switch (gpio) {
+	case S3C2410_GPA(6):
+		blink_gpio = S3C2410_GPA(4);
+		check_gpio = S3C2410_GPA(3);
+		break;
+	case S3C2410_GPA(7):
+		blink_gpio = S3C2410_GPA(3);
+		check_gpio = S3C2410_GPA(4);
+		break;
+	default:
+		return -EINVAL;
+		break;
+	}
+
+	if (delay_on && delay_off && !*delay_on && !*delay_off)
+		*delay_on = *delay_off = 500;
+
+	spin_lock(&rx1950_blink_spin);
+
+	switch (state) {
+	case GPIO_LED_NO_BLINK_LOW:
+	case GPIO_LED_NO_BLINK_HIGH:
+		if (!gpio_get_value(check_gpio))
+			gpio_set_value(S3C2410_GPJ(6), 0);
+		gpio_set_value(blink_gpio, 0);
+		gpio_set_value(gpio, state);
+		break;
+	case GPIO_LED_BLINK:
+		gpio_set_value(gpio, 0);
+		gpio_set_value(S3C2410_GPJ(6), 1);
+		gpio_set_value(blink_gpio, 1);
+		break;
+	}
+
+	spin_unlock(&rx1950_blink_spin);
+
+	return 0;
+}
+
 static struct gpio_led rx1950_leds_desc[] = {
 	{
-		.name				= "Green",
-		.default_trigger	= "main-battery-charging-or-full",
-		.gpio				= S3C2410_GPA(6),
+		.name			= "Green",
+		.default_trigger	= "main-battery-full",
+		.gpio			= S3C2410_GPA(6),
+		.retain_state_suspended	= 1,
 	},
 	{
-		.name				= "Red",
-		.default_trigger	= "main-battery-full",
-		.gpio				= S3C2410_GPA(7),
+		.name			= "Red",
+		.default_trigger
+			= "main-battery-charging-blink-full-solid",
+		.gpio			= S3C2410_GPA(7),
+		.retain_state_suspended	= 1,
 	},
 	{
-		.name				= "Blue",
+		.name			= "Blue",
 		.default_trigger	= "rx1950-acx-mem",
-		.gpio				= S3C2410_GPA(11),
+		.gpio			= S3C2410_GPA(11),
+		.retain_state_suspended	= 1,
 	},
 };
 
 static struct gpio_led_platform_data rx1950_leds_pdata = {
 	.num_leds	= ARRAY_SIZE(rx1950_leds_desc),
 	.leds		= rx1950_leds_desc,
+	.gpio_blink_set	= rx1950_led_blink_set,
 };
 
 static struct platform_device rx1950_leds = {
@@ -566,26 +617,10 @@
 	.sets = rx1950_nand_sets,
 };
 
-static void rx1950_udc_pullup(enum s3c2410_udc_cmd_e cmd)
-{
-	switch (cmd) {
-	case S3C2410_UDC_P_ENABLE:
-		gpio_direction_output(S3C2410_GPJ(5), 1);
-		break;
-	case S3C2410_UDC_P_DISABLE:
-		gpio_direction_output(S3C2410_GPJ(5), 0);
-		break;
-	case S3C2410_UDC_P_RESET:
-		break;
-	default:
-		break;
-	}
-}
-
 static struct s3c2410_udc_mach_info rx1950_udc_cfg __initdata = {
-	.udc_command = rx1950_udc_pullup,
 	.vbus_pin = S3C2410_GPG(5),
 	.vbus_pin_inverted = 1,
+	.pullup_pin = S3C2410_GPJ(5),
 };
 
 static struct s3c2410_ts_mach_info rx1950_ts_cfg __initdata = {
@@ -750,9 +785,6 @@
 						S3C2410_MISCCR_USBSUSPND0 |
 						S3C2410_MISCCR_USBSUSPND1, 0x0);
 
-	WARN_ON(gpio_request(S3C2410_GPJ(5), "UDC pullup"));
-	gpio_direction_output(S3C2410_GPJ(5), 0);
-
 	/* mmc power is disabled by default */
 	WARN_ON(gpio_request(S3C2410_GPJ(1), "MMC power"));
 	gpio_direction_output(S3C2410_GPJ(1), 0);
@@ -771,6 +803,13 @@
 
 	WARN_ON(gpio_request(S3C2410_GPB(1), "LCD power"));
 
+	WARN_ON(gpio_request(S3C2410_GPA(3), "Red blink"));
+	WARN_ON(gpio_request(S3C2410_GPA(4), "Green blink"));
+	WARN_ON(gpio_request(S3C2410_GPJ(6), "LED blink"));
+	gpio_direction_output(S3C2410_GPA(3), 0);
+	gpio_direction_output(S3C2410_GPA(4), 0);
+	gpio_direction_output(S3C2410_GPJ(6), 0);
+
 	platform_add_devices(rx1950_devices, ARRAY_SIZE(rx1950_devices));
 
 	i2c_register_board_info(0, rx1950_i2c_devices,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/s3c244x-irq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/s3c244x-irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2440/s3c244x-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2440/s3c244x-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,19 +95,19 @@
 {
 	unsigned int irqno;
 
-	set_irq_chip(IRQ_NFCON, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_NFCON, handle_level_irq);
+	irq_set_chip_and_handler(IRQ_NFCON, &s3c_irq_level_chip,
+				 handle_level_irq);
 	set_irq_flags(IRQ_NFCON, IRQF_VALID);
 
 	/* add chained handler for camera */
 
-	set_irq_chip(IRQ_CAM, &s3c_irq_level_chip);
-	set_irq_handler(IRQ_CAM, handle_level_irq);
-	set_irq_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
+	irq_set_chip_and_handler(IRQ_CAM, &s3c_irq_level_chip,
+				 handle_level_irq);
+	irq_set_chained_handler(IRQ_CAM, s3c_irq_demux_cam);
 
 	for (irqno = IRQ_S3C2440_CAM_C; irqno <= IRQ_S3C2440_CAM_P; irqno++) {
-		set_irq_chip(irqno, &s3c_irq_cam);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_cam,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c2443/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c2443/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c2443/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c2443/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,13 +230,11 @@
 {
 	unsigned int irqno;
 
-	set_irq_chip(base, &s3c_irq_level_chip);
-	set_irq_handler(base, handle_level_irq);
-	set_irq_chained_handler(base, demux);
+	irq_set_chip_and_handler(base, &s3c_irq_level_chip, handle_level_irq);
+	irq_set_chained_handler(base, demux);
 
 	for (irqno = start; irqno <= end; irqno++) {
-		set_irq_chip(irqno, chip);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, chip, handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c24a0/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c24a0/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c24a0/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c24a0/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 #ifndef __ASM_ARCH_24A0_MEMORY_H
 #define __ASM_ARCH_24A0_MEMORY_H __FILE__
 
-#define PHYS_OFFSET UL(0x10000000)
+#define PLAT_PHYS_OFFSET UL(0x10000000)
 
 #define __virt_to_bus(x) __virt_to_phys(x)
 #define __bus_to_virt(x) __phys_to_virt(x)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/cpufreq.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,7 +181,7 @@
 }
 #endif
 
-static int __init s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
+static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
 {
 	int ret;
 	struct cpufreq_frequency_table *freq;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/dma.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -315,7 +315,7 @@
 	case S3C2410_DMAOP_FLUSH:
 		return s3c64xx_dma_flush(chan);
 
-	/* belive PAUSE/RESUME are no-ops */
+	/* believe PAUSE/RESUME are no-ops */
 	case S3C2410_DMAOP_PAUSE:
 	case S3C2410_DMAOP_RESUME:
 	case S3C2410_DMAOP_STARTED:
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET     UL(0x50000000)
+#define PLAT_PHYS_OFFSET     UL(0x50000000)
 
 #define CONSISTENT_DMA_SIZE	SZ_8M
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/irq-eint.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/irq-eint.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/irq-eint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/irq-eint.c	2011-05-19 00:06:34.000000000 -0400
@@ -197,16 +197,15 @@
 	int irq;
 
 	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(27); irq++) {
-		set_irq_chip(irq, &s3c_irq_eint);
-		set_irq_chip_data(irq, (void *)eint_irq_to_bit(irq));
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &s3c_irq_eint, handle_level_irq);
+		irq_set_chip_data(irq, (void *)eint_irq_to_bit(irq));
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	set_irq_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
-	set_irq_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
-	set_irq_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
-	set_irq_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
+	irq_set_chained_handler(IRQ_EINT0_3, s3c_irq_demux_eint0_3);
+	irq_set_chained_handler(IRQ_EINT4_11, s3c_irq_demux_eint4_11);
+	irq_set_chained_handler(IRQ_EINT12_19, s3c_irq_demux_eint12_19);
+	irq_set_chained_handler(IRQ_EINT20_27, s3c_irq_demux_eint20_27);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -143,6 +143,7 @@
 	select S3C_DEV_USB_HSOTG
 	select S3C_DEV_WDT
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select HAVE_S3C2410_WATCHDOG if WATCHDOG
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_I2C1
@@ -231,7 +232,7 @@
 	select S3C_DEV_NAND
 	select S3C_DEV_USB_HOST
 	select S3C64XX_SETUP_FB_24BPP
-	select HAVE_PWM
+	select SAMSUNG_DEV_PWM
 	help
 	  Machine support for the Airgoo HMT
 
@@ -249,8 +250,8 @@
 	select S3C64XX_SETUP_SDHCI
 	select S3C64XX_SETUP_FB_24BPP
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
-	select HAVE_PWM
 	help
 	    Shared machine support for SmartQ 5/7
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/mach-smdk6410.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/smsc911x.h>
 #include <linux/regulator/fixed.h>
 #include <linux/regulator/machine.h>
+#include <linux/pwm_backlight.h>
 
 #ifdef CONFIG_SMDK6410_WM1190_EV1
 #include <linux/mfd/wm8350/core.h>
@@ -49,6 +50,7 @@
 #include <mach/hardware.h>
 #include <mach/regs-fb.h>
 #include <mach/map.h>
+#include <mach/gpio-bank-f.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
@@ -119,7 +121,6 @@
 {
 	if (power) {
 		gpio_direction_output(S3C64XX_GPF(13), 1);
-		gpio_direction_output(S3C64XX_GPF(15), 1);
 
 		/* fire nRESET on power up */
 		gpio_direction_output(S3C64XX_GPN(5), 0);
@@ -127,7 +128,6 @@
 		gpio_direction_output(S3C64XX_GPN(5), 1);
 		msleep(1);
 	} else {
-		gpio_direction_output(S3C64XX_GPF(15), 0);
 		gpio_direction_output(S3C64XX_GPF(13), 0);
 	}
 }
@@ -270,6 +270,45 @@
 	.cols		= 8,
 };
 
+static int smdk6410_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S3C64XX_GPF(15), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S3C64XX_GPF15_PWM_TOUT1 */
+	s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdk6410_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S3C64XX_GPF(15), S3C_GPIO_OUTPUT);
+	gpio_free(S3C64XX_GPF(15));
+}
+
+static struct platform_pwm_backlight_data smdk6410_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdk6410_backlight_init,
+	.exit		= smdk6410_backlight_exit,
+};
+
+static struct platform_device smdk6410_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[1].dev,
+		.platform_data	= &smdk6410_backlight_data,
+	},
+};
+
 static struct map_desc smdk6410_iodesc[] = {};
 
 static struct platform_device *smdk6410_devices[] __initdata = {
@@ -299,6 +338,8 @@
 	&s3c_device_rtc,
 	&s3c_device_ts,
 	&s3c_device_wdt,
+	&s3c_device_timer[1],
+	&smdk6410_backlight_device,
 };
 
 #ifdef CONFIG_REGULATOR
@@ -694,7 +735,6 @@
 
 	gpio_request(S3C64XX_GPN(5), "LCD power");
 	gpio_request(S3C64XX_GPF(13), "LCD power");
-	gpio_request(S3C64XX_GPF(15), "LCD power");
 
 	i2c_register_board_info(0, i2c_devs0, ARRAY_SIZE(i2c_devs0));
 	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/sleep.S linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-s3c64xx/sleep.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s3c64xx/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -32,25 +32,13 @@
 	 * code after resume.
 	 *
 	 * entry:
-	 *	r0 = pointer to the save block
+	 *	r1 = v:p offset
 	*/
 
 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
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
 
 	@@ call final suspend code
 	ldr	r0, =pm_cpu_sleep
@@ -61,18 +49,6 @@
 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. */
 
@@ -110,35 +86,4 @@
 	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
+	b	cpu_resume
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5p6442/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s5p6442/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5p6442/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5p6442/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #define CONSISTENT_DMA_SIZE	SZ_8M
 
 #endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/cpu.c linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/cpu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,7 +119,7 @@
 	s3c_adc_setname("s3c64xx-adc");
 
 	iotable_init(s5p64x0_iodesc, ARRAY_SIZE(s5p64x0_iodesc));
-	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6440_iodesc));
+	iotable_init(s5p6450_iodesc, ARRAY_SIZE(s5p6450_iodesc));
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H __FILE__
 
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #define CONSISTENT_DMA_SIZE	SZ_8M
 
 #endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -10,12 +10,14 @@
 config CPU_S5P6440
 	bool
 	select S3C_PL330_DMA
+	select S5P_HRT
 	help
 	  Enable S5P6440 CPU support
 
 config CPU_S5P6450
 	bool
 	select S3C_PL330_DMA
+	select S5P_HRT
 	help
 	  Enable S5P6450 CPU support
 
@@ -34,6 +36,7 @@
 	select S3C_DEV_WDT
 	select S3C64XX_DEV_SPI
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5P64X0_SETUP_I2C1
 	help
@@ -47,6 +50,7 @@
 	select S3C_DEV_WDT
 	select S3C64XX_DEV_SPI
 	select SAMSUNG_DEV_ADC
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5P64X0_SETUP_I2C1
 	help
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/mach-smdk6440.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -32,6 +33,7 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/i2c.h>
+#include <mach/regs-gpio.h>
 
 #include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
@@ -43,6 +45,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <plat/ts.h>
+#include <plat/s5p-time.h>
 
 #define SMDK6440_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -88,6 +91,45 @@
 	},
 };
 
+static int smdk6440_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5P6440_GPF(15), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5P6440_GPF15_PWM_TOUT1 */
+	s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdk6440_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5P6440_GPF(15), S3C_GPIO_OUTPUT);
+	gpio_free(S5P6440_GPF(15));
+}
+
+static struct platform_pwm_backlight_data smdk6440_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdk6440_backlight_init,
+	.exit		= smdk6440_backlight_exit,
+};
+
+static struct platform_device smdk6440_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[1].dev,
+		.platform_data	= &smdk6440_backlight_data,
+	},
+};
+
 static struct platform_device *smdk6440_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -97,6 +139,8 @@
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6440_device_iis,
+	&s3c_device_timer[1],
+	&smdk6440_backlight_device,
 };
 
 static struct s3c2410_platform_i2c s5p6440_i2c0_data __initdata = {
@@ -136,6 +180,7 @@
 	s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
 	s3c24xx_init_clocks(12000000);
 	s3c24xx_init_uarts(smdk6440_uartcfgs, ARRAY_SIZE(smdk6440_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init smdk6440_machine_init(void)
@@ -159,5 +204,5 @@
 	.init_irq	= s5p6440_init_irq,
 	.map_io		= smdk6440_map_io,
 	.init_machine	= smdk6440_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5p64x0/mach-smdk6450.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/module.h>
 #include <linux/clk.h>
 #include <linux/gpio.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -32,6 +33,7 @@
 #include <mach/map.h>
 #include <mach/regs-clock.h>
 #include <mach/i2c.h>
+#include <mach/regs-gpio.h>
 
 #include <plat/regs-serial.h>
 #include <plat/gpio-cfg.h>
@@ -43,6 +45,7 @@
 #include <plat/pll.h>
 #include <plat/adc.h>
 #include <plat/ts.h>
+#include <plat/s5p-time.h>
 
 #define SMDK6450_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
 				S3C2410_UCON_RXILEVEL |		\
@@ -106,6 +109,45 @@
 #endif
 };
 
+static int smdk6450_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5P6450_GPF(15), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT1\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5P6450_GPF15_PWM_TOUT1 */
+	s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdk6450_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5P6450_GPF(15), S3C_GPIO_OUTPUT);
+	gpio_free(S5P6450_GPF(15));
+}
+
+static struct platform_pwm_backlight_data smdk6450_backlight_data = {
+	.pwm_id		= 1,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdk6450_backlight_init,
+	.exit		= smdk6450_backlight_exit,
+};
+
+static struct platform_device smdk6450_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[1].dev,
+		.platform_data	= &smdk6450_backlight_data,
+	},
+};
+
 static struct platform_device *smdk6450_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_rtc,
@@ -115,6 +157,8 @@
 	&s3c_device_wdt,
 	&samsung_asoc_dma,
 	&s5p6450_device_iis0,
+	&s3c_device_timer[1],
+	&smdk6450_backlight_device,
 	/* s5p6450_device_spi0 will be added */
 };
 
@@ -155,6 +199,7 @@
 	s5p_init_io(NULL, 0, S5P64X0_SYS_ID);
 	s3c24xx_init_clocks(19200000);
 	s3c24xx_init_uarts(smdk6450_uartcfgs, ARRAY_SIZE(smdk6450_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init smdk6450_machine_init(void)
@@ -178,5 +223,5 @@
 	.init_irq	= s5p6450_init_irq,
 	.map_io		= smdk6450_map_io,
 	.init_machine	= smdk6450_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/gpiolib.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/gpiolib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/gpiolib.c	2011-05-19 00:06:34.000000000 -0400
@@ -348,6 +348,7 @@
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pc100_gpio_chips, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET     	UL(0x20000000)
+#define PLAT_PHYS_OFFSET     	UL(0x20000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/include/mach/regs-fb.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/include/mach/regs-fb.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/include/mach/regs-fb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/include/mach/regs-fb.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 #define WPALCON_H					(0x19c)
 #define WPALCON_L					(0x1a0)
 
-/* Pallete contro for WPAL0 and WPAL1 is the same as in S3C64xx, but
+/* Palette control for WPAL0 and WPAL1 is the same as in S3C64xx, but
  * different for WPAL2-4
  */
 /* In WPALCON_L (aka WPALCON) */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,7 @@
 	select SAMSUNG_DEV_ADC
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5PC100_SETUP_FB_24BPP
 	select S5PC100_SETUP_I2C1
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/mach-smdkc100.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,12 +23,15 @@
 #include <linux/fb.h>
 #include <linux/delay.h>
 #include <linux/input.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
 #include <mach/map.h>
 #include <mach/regs-fb.h>
+#include <mach/regs-gpio.h>
+
 #include <video/platform_lcd.h>
 
 #include <asm/irq.h>
@@ -107,9 +110,6 @@
 static void smdkc100_lcd_power_set(struct plat_lcd_data *pd,
 				   unsigned int power)
 {
-	/* backlight */
-	gpio_direction_output(S5PC100_GPD(0), power);
-
 	if (power) {
 		/* module reset */
 		gpio_direction_output(S5PC100_GPH0(6), 1);
@@ -179,6 +179,45 @@
 	.cols		= 8,
 };
 
+static int smdkc100_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5PC100_GPD(0), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPF for PWM-OUT0\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5PC100_GPD_TOUT_0 */
+	s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdkc100_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5PC100_GPD(0), S3C_GPIO_OUTPUT);
+	gpio_free(S5PC100_GPD(0));
+}
+
+static struct platform_pwm_backlight_data smdkc100_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdkc100_backlight_init,
+	.exit		= smdkc100_backlight_exit,
+};
+
+static struct platform_device smdkc100_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[0].dev,
+		.platform_data	= &smdkc100_backlight_data,
+	},
+};
+
 static struct platform_device *smdkc100_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_cfcon,
@@ -200,6 +239,8 @@
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
 	&s5pc100_device_spdif,
+	&s3c_device_timer[0],
+	&smdkc100_backlight_device,
 };
 
 static struct s3c2410_ts_mach_info s3c_ts_platform __initdata = {
@@ -233,7 +274,6 @@
 	s5pc100_spdif_setup_gpio(S5PC100_SPDIF_GPD);
 
 	/* LCD init */
-	gpio_request(S5PC100_GPD(0), "GPD");
 	gpio_request(S5PC100_GPH0(6), "GPH0");
 	smdkc100_lcd_power_set(&smdkc100_lcd_power_data, 0);
 	platform_add_devices(smdkc100_devices, ARRAY_SIZE(smdkc100_devices));
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/setup-sdhci.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/setup-sdhci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pc100/setup-sdhci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pc100/setup-sdhci.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 {
 	u32 ctrl2, ctrl3;
 
-	/* don't need to alter anything acording to card-type */
+	/* don't need to alter anything according to card-type */
 
 	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/cpufreq.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -390,8 +390,7 @@
 }
 
 #ifdef CONFIG_PM
-static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy,
-				   pm_message_t pmsg)
+static int s5pv210_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/gpiolib.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/gpiolib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/gpiolib.c	2011-05-19 00:06:34.000000000 -0400
@@ -281,6 +281,7 @@
 	}
 
 	samsung_gpiolib_add_4bit_chips(s5pv210_gpio_4bit, nr_chips);
+	s5p_register_gpioint_bank(IRQ_GPIOINT, 0, S5P_GPIOINT_GROUP_MAXNR);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
 #define gpio_cansleep	__gpio_cansleep
 #define gpio_to_irq	__gpio_to_irq
 
-/* Practically, GPIO banks upto MP03 are the configurable gpio banks */
+/* Practically, GPIO banks up to MP03 are the configurable gpio banks */
 
 /* GPIO bank sizes */
 #define S5PV210_GPIO_A0_NR	(8)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -99,9 +99,9 @@
 #define IRQ_TC			IRQ_PENDN
 #define IRQ_KEYPAD		S5P_IRQ_VIC2(25)
 #define IRQ_CG			S5P_IRQ_VIC2(26)
-#define IRQ_SEC			S5P_IRQ_VIC2(27)
-#define IRQ_SECRX		S5P_IRQ_VIC2(28)
-#define IRQ_SECTX		S5P_IRQ_VIC2(29)
+#define IRQ_SSS_INT		S5P_IRQ_VIC2(27)
+#define IRQ_SSS_HASH		S5P_IRQ_VIC2(28)
+#define IRQ_PCM2		S5P_IRQ_VIC2(29)
 #define IRQ_SDMIRQ		S5P_IRQ_VIC2(30)
 #define IRQ_SDMFIQ		S5P_IRQ_VIC2(31)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 #define CONSISTENT_DMA_SIZE	(SZ_8M + SZ_4M + SZ_2M)
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/include/mach/regs-clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -146,6 +146,10 @@
 #define S5P_OM_STAT		S5P_CLKREG(0xE100)
 #define S5P_USB_PHY_CONTROL	S5P_CLKREG(0xE80C)
 #define S5P_DAC_CONTROL		S5P_CLKREG(0xE810)
+#define S5P_MIPI_DPHY_CONTROL(x) S5P_CLKREG(0xE814)
+#define S5P_MIPI_DPHY_ENABLE	(1 << 0)
+#define S5P_MIPI_DPHY_SRESETN	(1 << 1)
+#define S5P_MIPI_DPHY_MRESETN	(1 << 2)
 
 #define S5P_INFORM0		S5P_CLKREG(0xF000)
 #define S5P_INFORM1		S5P_CLKREG(0xF004)
@@ -161,7 +165,6 @@
 #define S5P_MDNIE_SEL		S5P_CLKREG(0x7008)
 #define S5P_MIPI_PHY_CON0	S5P_CLKREG(0x7200)
 #define S5P_MIPI_PHY_CON1	S5P_CLKREG(0x7204)
-#define S5P_MIPI_DPHY_CONTROL	S5P_CLKREG(0xE814)
 
 #define S5P_IDLE_CFG_TL_MASK	(3 << 30)
 #define S5P_IDLE_CFG_TM_MASK	(3 << 28)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 	bool
 	select S3C_PL330_DMA
 	select S5P_EXT_INT
+	select S5P_HRT
 	select S5PV210_PM if PM
 	help
 	  Enable S5PV210 CPU support
@@ -53,6 +54,11 @@
 	help
 	  Common setup code for SDHCI gpio.
 
+config S5PV210_SETUP_FIMC
+	bool
+	help
+	  Common setup code for the camera interfaces.
+
 menu "S5PC110 Machines"
 
 config MACH_AQUILA
@@ -130,6 +136,7 @@
 	select SAMSUNG_DEV_ADC
 	select SAMSUNG_DEV_IDE
 	select SAMSUNG_DEV_KEYPAD
+	select SAMSUNG_DEV_PWM
 	select SAMSUNG_DEV_TS
 	select S5PV210_SETUP_FB_24BPP
 	select S5PV210_SETUP_I2C1
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-aquila.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-aquila.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-aquila.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-aquila.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 #include <plat/fb.h>
 #include <plat/fimc-core.h>
 #include <plat/sdhci.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define AQUILA_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -296,13 +297,11 @@
 };
 
 /* BUCK */
-static struct regulator_consumer_supply buck1_consumer[] = {
-	{	.supply	= "vddarm", },
-};
+static struct regulator_consumer_supply buck1_consumer =
+	REGULATOR_SUPPLY("vddarm", NULL);
 
-static struct regulator_consumer_supply buck2_consumer[] = {
-	{	.supply	= "vddint", },
-};
+static struct regulator_consumer_supply buck2_consumer =
+	REGULATOR_SUPPLY("vddint", NULL);
 
 static struct regulator_init_data aquila_buck1_data = {
 	.constraints	= {
@@ -313,8 +312,8 @@
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck1_consumer),
-	.consumer_supplies	= buck1_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck1_consumer,
 };
 
 static struct regulator_init_data aquila_buck2_data = {
@@ -326,8 +325,8 @@
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck2_consumer),
-	.consumer_supplies	= buck2_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck2_consumer,
 };
 
 static struct regulator_init_data aquila_buck3_data = {
@@ -391,26 +390,14 @@
 #endif
 
 static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "DBVDD",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "AVDD2",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "CPVDD",
-	},
+	REGULATOR_SUPPLY("DBVDD", "5-001a"),
+	REGULATOR_SUPPLY("AVDD2", "5-001a"),
+	REGULATOR_SUPPLY("CPVDD", "5-001a"),
 };
 
 static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD1",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD2",
-	},
+	REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
+	REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
 };
 
 static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
@@ -459,15 +446,11 @@
 	},
 };
 
-static struct regulator_consumer_supply wm8994_avdd1_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "AVDD1",
-};
+static struct regulator_consumer_supply wm8994_avdd1_supply =
+	REGULATOR_SUPPLY("AVDD1", "5-001a");
 
-static struct regulator_consumer_supply wm8994_dcvdd_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "DCVDD",
-};
+static struct regulator_consumer_supply wm8994_dcvdd_supply =
+	REGULATOR_SUPPLY("DCVDD", "5-001a");
 
 static struct regulator_init_data wm8994_ldo1_data = {
 	.constraints	= {
@@ -664,6 +647,7 @@
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(aquila_uartcfgs, ARRAY_SIZE(aquila_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init aquila_machine_init(void)
@@ -698,5 +682,5 @@
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= aquila_map_io,
 	.init_machine	= aquila_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-goni.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-goni.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-goni.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-goni.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 #include <linux/fb.h>
 #include <linux/i2c.h>
 #include <linux/i2c-gpio.h>
-#include <linux/i2c/qt602240_ts.h>
+#include <linux/i2c/atmel_mxt_ts.h>
 #include <linux/mfd/max8998.h>
 #include <linux/mfd/wm8994/pdata.h>
 #include <linux/regulator/fixed.h>
@@ -25,6 +25,7 @@
 #include <linux/gpio_keys.h>
 #include <linux/input.h>
 #include <linux/gpio.h>
+#include <linux/interrupt.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -45,6 +46,7 @@
 #include <plat/keypad.h>
 #include <plat/sdhci.h>
 #include <plat/clock.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define GONI_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -108,6 +110,8 @@
 	},
 	.max_bpp	= 32,
 	.default_bpp	= 16,
+	.virtual_x	= 480,
+	.virtual_y	= 2 * 800,
 };
 
 static struct s3c_fb_platdata goni_lcd_pdata __initdata = {
@@ -222,7 +226,7 @@
 }
 
 /* TSP */
-static struct qt602240_platform_data qt602240_platform_data = {
+static struct mxt_platform_data qt602240_platform_data = {
 	.x_line		= 17,
 	.y_line		= 11,
 	.x_size		= 800,
@@ -230,7 +234,8 @@
 	.blen		= 0x21,
 	.threshold	= 0x28,
 	.voltage	= 2800000,              /* 2.8V */
-	.orient		= QT602240_DIAGONAL,
+	.orient		= MXT_DIAGONAL,
+	.irqflags	= IRQF_TRIGGER_FALLING,
 };
 
 static struct s3c2410_platform_i2c i2c2_data __initdata = {
@@ -269,10 +274,30 @@
 /* MAX8998 regulators */
 #if defined(CONFIG_REGULATOR_MAX8998) || defined(CONFIG_REGULATOR_MAX8998_MODULE)
 
+static struct regulator_consumer_supply goni_ldo3_consumers[] = {
+	REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
+};
+
 static struct regulator_consumer_supply goni_ldo5_consumers[] = {
 	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
 };
 
+static struct regulator_consumer_supply goni_ldo8_consumers[] = {
+	REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"),
+};
+
+static struct regulator_consumer_supply goni_ldo11_consumers[] = {
+	REGULATOR_SUPPLY("vddio", "0-0030"), /* "CAM_IO_2.8V" */
+};
+
+static struct regulator_consumer_supply goni_ldo13_consumers[] = {
+	REGULATOR_SUPPLY("vdda", "0-0030"), /* "CAM_A_2.8V" */
+};
+
+static struct regulator_consumer_supply goni_ldo14_consumers[] = {
+	REGULATOR_SUPPLY("vdd_core", "0-0030"), /* "CAM_CIF_1.8V" */
+};
+
 static struct regulator_init_data goni_ldo2_data = {
 	.constraints	= {
 		.name		= "VALIVE_1.1V",
@@ -292,8 +317,10 @@
 		.min_uV		= 1100000,
 		.max_uV		= 1100000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies = ARRAY_SIZE(goni_ldo3_consumers),
+	.consumer_supplies = goni_ldo3_consumers,
 };
 
 static struct regulator_init_data goni_ldo4_data = {
@@ -311,6 +338,7 @@
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
 	.num_consumer_supplies = ARRAY_SIZE(goni_ldo5_consumers),
 	.consumer_supplies = goni_ldo5_consumers,
@@ -341,8 +369,10 @@
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies = ARRAY_SIZE(goni_ldo8_consumers),
+	.consumer_supplies = goni_ldo8_consumers,
 };
 
 static struct regulator_init_data goni_ldo9_data = {
@@ -351,7 +381,6 @@
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -371,8 +400,10 @@
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo11_consumers),
+	.consumer_supplies	= goni_ldo11_consumers,
 };
 
 static struct regulator_init_data goni_ldo12_data = {
@@ -381,7 +412,6 @@
 		.min_uV		= 1200000,
 		.max_uV		= 1200000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -391,8 +421,10 @@
 		.min_uV		= 2800000,
 		.max_uV		= 2800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo13_consumers),
+	.consumer_supplies	= goni_ldo13_consumers,
 };
 
 static struct regulator_init_data goni_ldo14_data = {
@@ -401,8 +433,10 @@
 		.min_uV		= 1800000,
 		.max_uV		= 1800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
+		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
 	},
+	.num_consumer_supplies	= ARRAY_SIZE(goni_ldo14_consumers),
+	.consumer_supplies	= goni_ldo14_consumers,
 };
 
 static struct regulator_init_data goni_ldo15_data = {
@@ -411,7 +445,6 @@
 		.min_uV		= 3300000,
 		.max_uV		= 3300000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -421,7 +454,6 @@
 		.min_uV		= 1800000,
 		.max_uV		= 1800000,
 		.apply_uV	= 1,
-		.always_on	= 1,
 	},
 };
 
@@ -436,13 +468,11 @@
 };
 
 /* BUCK */
-static struct regulator_consumer_supply buck1_consumer[] = {
-	{	.supply	= "vddarm", },
-};
+static struct regulator_consumer_supply buck1_consumer =
+	REGULATOR_SUPPLY("vddarm", NULL);
 
-static struct regulator_consumer_supply buck2_consumer[] = {
-	{	.supply	= "vddint", },
-};
+static struct regulator_consumer_supply buck2_consumer =
+	REGULATOR_SUPPLY("vddint", NULL);
 
 static struct regulator_init_data goni_buck1_data = {
 	.constraints	= {
@@ -453,8 +483,8 @@
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck1_consumer),
-	.consumer_supplies	= buck1_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck1_consumer,
 };
 
 static struct regulator_init_data goni_buck2_data = {
@@ -466,8 +496,8 @@
 		.valid_ops_mask	= REGULATOR_CHANGE_VOLTAGE |
 				  REGULATOR_CHANGE_STATUS,
 	},
-	.num_consumer_supplies	= ARRAY_SIZE(buck2_consumer),
-	.consumer_supplies	= buck2_consumer,
+	.num_consumer_supplies	= 1,
+	.consumer_supplies	= &buck2_consumer,
 };
 
 static struct regulator_init_data goni_buck3_data = {
@@ -531,26 +561,14 @@
 #endif
 
 static struct regulator_consumer_supply wm8994_fixed_voltage0_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "DBVDD",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "AVDD2",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "CPVDD",
-	},
+	REGULATOR_SUPPLY("DBVDD", "5-001a"),
+	REGULATOR_SUPPLY("AVDD2", "5-001a"),
+	REGULATOR_SUPPLY("CPVDD", "5-001a"),
 };
 
 static struct regulator_consumer_supply wm8994_fixed_voltage1_supplies[] = {
-	{
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD1",
-	}, {
-		.dev_name	= "5-001a",
-		.supply		= "SPKVDD2",
-	},
+	REGULATOR_SUPPLY("SPKVDD1", "5-001a"),
+	REGULATOR_SUPPLY("SPKVDD2", "5-001a"),
 };
 
 static struct regulator_init_data wm8994_fixed_voltage0_init_data = {
@@ -599,15 +617,11 @@
 	},
 };
 
-static struct regulator_consumer_supply wm8994_avdd1_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "AVDD1",
-};
+static struct regulator_consumer_supply wm8994_avdd1_supply =
+	REGULATOR_SUPPLY("AVDD1", "5-001a");
 
-static struct regulator_consumer_supply wm8994_dcvdd_supply = {
-	.dev_name	= "5-001a",
-	.supply		= "DCVDD",
-};
+static struct regulator_consumer_supply wm8994_dcvdd_supply =
+	REGULATOR_SUPPLY("DCVDD", "5-001a");
 
 static struct regulator_init_data wm8994_ldo1_data = {
 	.constraints	= {
@@ -794,6 +808,7 @@
 	&goni_i2c_gpio5,
 	&mmc2_fixed_voltage,
 	&goni_device_gpiokeys,
+	&s3c_device_i2c0,
 	&s5p_device_fimc0,
 	&s5p_device_fimc1,
 	&s5p_device_fimc2,
@@ -823,6 +838,7 @@
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(goni_uartcfgs, ARRAY_SIZE(goni_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init goni_machine_init(void)
@@ -830,6 +846,9 @@
 	/* Radio: call before I2C 1 registeration */
 	goni_radio_init();
 
+	/* I2C0 */
+	s3c_i2c0_set_platdata(NULL);
+
 	/* I2C1 */
 	s3c_i2c1_set_platdata(NULL);
 	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
@@ -873,5 +892,5 @@
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-smdkc110.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include <plat/ata.h>
 #include <plat/iic.h>
 #include <plat/pm.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKC110_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -111,6 +112,7 @@
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init smdkc110_machine_init(void)
@@ -138,5 +140,5 @@
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkc110_map_io,
 	.init_machine	= smdkc110_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-smdkv210.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/fb.h>
 #include <linux/gpio.h>
 #include <linux/delay.h>
+#include <linux/pwm_backlight.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -43,6 +44,7 @@
 #include <plat/keypad.h>
 #include <plat/pm.h>
 #include <plat/fb.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define SMDKV210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -208,6 +210,45 @@
 	.setup_gpio	= s5pv210_fb_gpio_setup_24bpp,
 };
 
+static int smdkv210_backlight_init(struct device *dev)
+{
+	int ret;
+
+	ret = gpio_request(S5PV210_GPD0(3), "Backlight");
+	if (ret) {
+		printk(KERN_ERR "failed to request GPD for PWM-OUT 3\n");
+		return ret;
+	}
+
+	/* Configure GPIO pin with S5PV210_GPD_0_3_TOUT_3 */
+	s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_SFN(2));
+
+	return 0;
+}
+
+static void smdkv210_backlight_exit(struct device *dev)
+{
+	s3c_gpio_cfgpin(S5PV210_GPD0(3), S3C_GPIO_OUTPUT);
+	gpio_free(S5PV210_GPD0(3));
+}
+
+static struct platform_pwm_backlight_data smdkv210_backlight_data = {
+	.pwm_id		= 3,
+	.max_brightness	= 255,
+	.dft_brightness	= 255,
+	.pwm_period_ns	= 78770,
+	.init		= smdkv210_backlight_init,
+	.exit		= smdkv210_backlight_exit,
+};
+
+static struct platform_device smdkv210_backlight_device = {
+	.name		= "pwm-backlight",
+	.dev		= {
+		.parent		= &s3c_device_timer[3].dev,
+		.platform_data	= &smdkv210_backlight_data,
+	},
+};
+
 static struct platform_device *smdkv210_devices[] __initdata = {
 	&s3c_device_adc,
 	&s3c_device_cfcon,
@@ -229,6 +270,8 @@
 	&samsung_device_keypad,
 	&smdkv210_dm9000,
 	&smdkv210_lcd_lte480wv,
+	&s3c_device_timer[3],
+	&smdkv210_backlight_device,
 };
 
 static void __init smdkv210_dm9000_init(void)
@@ -272,6 +315,7 @@
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(smdkv210_uartcfgs, ARRAY_SIZE(smdkv210_uartcfgs));
+	s5p_set_timer_source(S5P_PWM2, S5P_PWM4);
 }
 
 static void __init smdkv210_machine_init(void)
@@ -306,5 +350,5 @@
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= smdkv210_map_io,
 	.init_machine	= smdkv210_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-torbreck.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-torbreck.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/mach-torbreck.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/mach-torbreck.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <plat/devs.h>
 #include <plat/cpu.h>
 #include <plat/iic.h>
+#include <plat/s5p-time.h>
 
 /* Following are default values for UCON, ULCON and UFCON UART registers */
 #define TORBRECK_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
@@ -104,6 +105,7 @@
 	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
 	s3c24xx_init_clocks(24000000);
 	s3c24xx_init_uarts(torbreck_uartcfgs, ARRAY_SIZE(torbreck_uartcfgs));
+	s5p_set_timer_source(S5P_PWM3, S5P_PWM4);
 }
 
 static void __init torbreck_machine_init(void)
@@ -127,5 +129,5 @@
 	.init_irq	= s5pv210_init_irq,
 	.map_io		= torbreck_map_io,
 	.init_machine	= torbreck_machine_init,
-	.timer		= &s3c24xx_timer,
+	.timer		= &s5p_timer,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 obj-$(CONFIG_S3C64XX_DEV_SPI)	+= dev-spi.o
 
 obj-$(CONFIG_S5PV210_SETUP_FB_24BPP)	+= setup-fb-24bpp.o
+obj-$(CONFIG_S5PV210_SETUP_FIMC)	+= setup-fimc.o
 obj-$(CONFIG_S5PV210_SETUP_I2C1) 	+= setup-i2c1.o
 obj-$(CONFIG_S5PV210_SETUP_I2C2) 	+= setup-i2c2.o
 obj-$(CONFIG_S5PV210_SETUP_IDE)		+= setup-ide.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/setup-fimc.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/setup-fimc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/setup-fimc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/setup-fimc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5PV210 camera interface GPIO configuration.
+ *
+ * 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 <plat/gpio-cfg.h>
+#include <plat/camport.h>
+
+int s5pv210_fimc_setup_gpio(enum s5p_camport_id id)
+{
+	u32 gpio8, gpio5;
+	int ret;
+
+	switch (id) {
+	case S5P_CAMPORT_A:
+		gpio8 = S5PV210_GPE0(0);
+		gpio5 = S5PV210_GPE1(0);
+		break;
+
+	case S5P_CAMPORT_B:
+		gpio8 = S5PV210_GPJ0(0);
+		gpio5 = S5PV210_GPJ1(0);
+		break;
+
+	default:
+		WARN(1, "Wrong camport id: %d\n", id);
+		return -EINVAL;
+	}
+
+	ret = s3c_gpio_cfgall_range(gpio8, 8, S3C_GPIO_SFN(2),
+				    S3C_GPIO_PULL_UP);
+	if (ret)
+		return ret;
+
+	return s3c_gpio_cfgall_range(gpio5, 5, S3C_GPIO_SFN(2),
+				     S3C_GPIO_PULL_UP);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/setup-sdhci.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/setup-sdhci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/setup-sdhci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/setup-sdhci.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 {
 	u32 ctrl2, ctrl3;
 
-	/* don't need to alter anything acording to card-type */
+	/* don't need to alter anything according to card-type */
 
 	writel(S3C64XX_SDHCI_CONTROL4_DRIVE_9mA, r + S3C64XX_SDHCI_CONTROL4);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/setup-sdhci-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,10 +32,10 @@
 
 	switch (width) {
 	case 8:
-		/* GPG1[3:6] special-funtion 3 */
+		/* GPG1[3:6] special-function 3 */
 		s3c_gpio_cfgrange_nopull(S5PV210_GPG1(3), 4, S3C_GPIO_SFN(3));
 	case 4:
-		/* GPG0[3:6] special-funtion 2 */
+		/* GPG0[3:6] special-function 2 */
 		s3c_gpio_cfgrange_nopull(S5PV210_GPG0(3), 4, S3C_GPIO_SFN(2));
 	default:
 		break;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/sleep.S linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv210/sleep.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv210/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -35,50 +35,24 @@
 	/* s3c_cpu_save
 	 *
 	 * entry:
-	 *	r0 = save address (virtual addr of s3c_sleep_save_phys)
+	 *	r1 = v:p offset
 	*/
 
 ENTRY(s3c_cpu_save)
 
 	stmfd	sp!, { r3 - 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
-	mrc	p15, 0, r12, c10, c2, 0	@ Read PRRR
-	mrc	p15, 0, r3, c10, c2, 1	@ READ NMRR
-
-	stmia	r0, { r3 - r13 }
-
-	bl	s3c_pm_cb_flushcache
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
 
 	ldr	r0, =pm_cpu_sleep
 	ldr	r0, [ r0 ]
 	mov	pc, r0
 
 resume_with_mmu:
-	/*
-	 * After MMU is turned on, restore the previous MMU table.
-	 */
-	ldr	r9 , =(PAGE_OFFSET - PHYS_OFFSET)
-	add	r4, r4, r9
-	str	r12, [r4]
-
 	ldmfd	sp!, { r3 - r12, pc }
 
 	.ltorg
 
-	.data
-
-	.global	s3c_sleep_save_phys
-s3c_sleep_save_phys:
-	.word	0
-
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
@@ -96,75 +70,4 @@
 	*/
 
 ENTRY(s3c_cpu_resume)
-	mov	r0, #PSR_I_BIT | PSR_F_BIT | SVC_MODE
-	msr	cpsr_c, r0
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0		@ invalidate TLBs
-	mcr	p15, 0, r1, c7, c5, 0		@ invalidate I Cache
-
-	ldr	r0, s3c_sleep_save_phys		@ address of restore block
-	ldmia	r0, { r3 - r13 }
-
-	mcr	p15, 0, r4, c13, c0, 0		@ FCSE/PID
-	mcr	p15, 0, r5, c3, c0, 0		@ Domain ID
-
-	mcr	p15, 0, r8, c2, c0, 2		@ Translation Table Control
-	mcr	p15, 0, r7, c2, c0, 1		@ Translation Table BASE1
-	mcr	p15, 0, r6, c2, c0, 0		@ Translation Table BASE0
-
-	mcr	p15, 0, r10, c1, c0, 1		@ Auxiliary control register
-
-	mov	r0, #0
-	mcr	p15, 0, r0, c8, c7, 0		@ Invalidate I & D TLB
-
-	mov	r0, #0				@ restore copro access
-	mcr	p15, 0, r11, c1, c0, 2		@ Co-processor access
-	mcr 	p15, 0, r0, c7, c5, 4
-
-	mcr	p15, 0, r12, c10, c2, 0		@ write PRRR
-	mcr	p15, 0, r3, c10, c2, 1		@ write NMRR
-
-	/*
-	 * In Cortex-A8, when MMU is turned on, the pipeline is flushed.
-	 * And there are no valid entries in the MMU table at this point.
-	 * So before turning on the MMU, the MMU entry for the DRAM address
-	 * range is added. After the MMU is turned on, the other entries
-	 * in the MMU table will be restored.
-	*/
-
-	/* r6 = Translation Table BASE0 */
-	mov	r4, r6
-	mov	r4, r4, LSR #14
-	mov	r4, r4, LSL #14
-
-	/* Load address for adding to MMU table list */
-	ldr	r11, =0xE010F000		@ INFORM0 reg.
-	ldr	r10, [r11, #0]
-	mov	r10, r10, LSR #18
-	bic	r10, r10, #0x3
-	orr	r4, r4, r10
-
-	/* Calculate MMU table entry */
-	mov 	r10, r10, LSL #18
-	ldr	r5, =0x40E
-	orr	r10, r10, r5
-
-	/* Back up originally data */
-	ldr	r12, [r4]
-
-	/* Add calculated MMU table entry into MMU table list */
-	str	r10, [r4]
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r9, c1, c0, 0		@ turn on MMU, etc
-
-	nop
-	nop
-	nop
-	nop
-	nop					@ second-to-last before mmu
-
-	mov	pc, r2				@ go back to virtual address
-
-	.ltorg
+	b	cpu_resume
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/clock.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1122 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/clock.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Clock 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/err.h>
-#include <linux/io.h>
-
-#include <plat/cpu-freq.h>
-#include <plat/clock.h>
-#include <plat/cpu.h>
-#include <plat/pll.h>
-#include <plat/s5p-clock.h>
-#include <plat/clock-clksrc.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-
-static struct clk clk_sclk_hdmi27m = {
-	.name		= "sclk_hdmi27m",
-	.id		= -1,
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_hdmiphy = {
-	.name		= "sclk_hdmiphy",
-	.id		= -1,
-};
-
-static struct clk clk_sclk_usbphy0 = {
-	.name		= "sclk_usbphy0",
-	.id		= -1,
-	.rate		= 27000000,
-};
-
-static struct clk clk_sclk_usbphy1 = {
-	.name		= "sclk_usbphy1",
-	.id		= -1,
-};
-
-static int s5pv310_clksrc_mask_top_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_TOP, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_CAM, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD0, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_LCD1, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_FSYS, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_peril0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL0, clk, enable);
-}
-
-static int s5pv310_clksrc_mask_peril1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKSRC_MASK_PERIL1, clk, enable);
-}
-
-static int s5pv310_clk_ip_cam_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_CAM, clk, enable);
-}
-
-static int s5pv310_clk_ip_image_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_IMAGE, clk, enable);
-}
-
-static int s5pv310_clk_ip_lcd0_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_LCD0, clk, enable);
-}
-
-static int s5pv310_clk_ip_lcd1_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_LCD1, clk, enable);
-}
-
-static int s5pv310_clk_ip_fsys_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_FSYS, clk, enable);
-}
-
-static int s5pv310_clk_ip_peril_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_PERIL, clk, enable);
-}
-
-static int s5pv310_clk_ip_perir_ctrl(struct clk *clk, int enable)
-{
-	return s5p_gatectrl(S5P_CLKGATE_IP_PERIR, clk, enable);
-}
-
-/* Core list of CMU_CPU side */
-
-static struct clksrc_clk clk_mout_apll = {
-	.clk	= {
-		.name		= "mout_apll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_apll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 0, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_apll = {
-	.clk	= {
-		.name		= "sclk_apll",
-		.id		= -1,
-		.parent		= &clk_mout_apll.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 24, .size = 3 },
-};
-
-static struct clksrc_clk clk_mout_epll = {
-	.clk	= {
-		.name		= "mout_epll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_epll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_mout_mpll = {
-	.clk = {
-		.name		= "mout_mpll",
-		.id		= -1,
-	},
-	.sources	= &clk_src_mpll,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 8, .size = 1 },
-};
-
-static struct clk *clkset_moutcore_list[] = {
-	[0] = &clk_mout_apll.clk,
-	[1] = &clk_mout_mpll.clk,
-};
-
-static struct clksrc_sources clkset_moutcore = {
-	.sources	= clkset_moutcore_list,
-	.nr_sources	= ARRAY_SIZE(clkset_moutcore_list),
-};
-
-static struct clksrc_clk clk_moutcore = {
-	.clk	= {
-		.name		= "moutcore",
-		.id		= -1,
-	},
-	.sources	= &clkset_moutcore,
-	.reg_src	= { .reg = S5P_CLKSRC_CPU, .shift = 16, .size = 1 },
-};
-
-static struct clksrc_clk clk_coreclk = {
-	.clk	= {
-		.name		= "core_clk",
-		.id		= -1,
-		.parent		= &clk_moutcore.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_armclk = {
-	.clk	= {
-		.name		= "armclk",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-};
-
-static struct clksrc_clk clk_aclk_corem0 = {
-	.clk	= {
-		.name		= "aclk_corem0",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_cores = {
-	.clk	= {
-		.name		= "aclk_cores",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 4, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_corem1 = {
-	.clk	= {
-		.name		= "aclk_corem1",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_periphclk = {
-	.clk	= {
-		.name		= "periphclk",
-		.id		= -1,
-		.parent		= &clk_coreclk.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_CPU, .shift = 12, .size = 3 },
-};
-
-/* Core list of CMU_CORE side */
-
-static struct clk *clkset_corebus_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_corebus = {
-	.sources	= clkset_corebus_list,
-	.nr_sources	= ARRAY_SIZE(clkset_corebus_list),
-};
-
-static struct clksrc_clk clk_mout_corebus = {
-	.clk	= {
-		.name		= "mout_corebus",
-		.id		= -1,
-	},
-	.sources	= &clkset_mout_corebus,
-	.reg_src	= { .reg = S5P_CLKSRC_DMC, .shift = 4, .size = 1 },
-};
-
-static struct clksrc_clk clk_sclk_dmc = {
-	.clk	= {
-		.name		= "sclk_dmc",
-		.id		= -1,
-		.parent		= &clk_mout_corebus.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 12, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_cored = {
-	.clk	= {
-		.name		= "aclk_cored",
-		.id		= -1,
-		.parent		= &clk_sclk_dmc.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 16, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_corep = {
-	.clk	= {
-		.name		= "aclk_corep",
-		.id		= -1,
-		.parent		= &clk_aclk_cored.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 20, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_acp = {
-	.clk	= {
-		.name		= "aclk_acp",
-		.id		= -1,
-		.parent		= &clk_mout_corebus.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_pclk_acp = {
-	.clk	= {
-		.name		= "pclk_acp",
-		.id		= -1,
-		.parent		= &clk_aclk_acp.clk,
-	},
-	.reg_div	= { .reg = S5P_CLKDIV_DMC0, .shift = 4, .size = 3 },
-};
-
-/* Core list of CMU_TOP side */
-
-static struct clk *clkset_aclk_top_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_aclk = {
-	.sources	= clkset_aclk_top_list,
-	.nr_sources	= ARRAY_SIZE(clkset_aclk_top_list),
-};
-
-static struct clksrc_clk clk_aclk_200 = {
-	.clk	= {
-		.name		= "aclk_200",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 12, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 0, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_100 = {
-	.clk	= {
-		.name		= "aclk_100",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 16, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 4, .size = 4 },
-};
-
-static struct clksrc_clk clk_aclk_160 = {
-	.clk	= {
-		.name		= "aclk_160",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 20, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 8, .size = 3 },
-};
-
-static struct clksrc_clk clk_aclk_133 = {
-	.clk	= {
-		.name		= "aclk_133",
-		.id		= -1,
-	},
-	.sources	= &clkset_aclk,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 24, .size = 1 },
-	.reg_div	= { .reg = S5P_CLKDIV_TOP, .shift = 12, .size = 3 },
-};
-
-static struct clk *clkset_vpllsrc_list[] = {
-	[0] = &clk_fin_vpll,
-	[1] = &clk_sclk_hdmi27m,
-};
-
-static struct clksrc_sources clkset_vpllsrc = {
-	.sources	= clkset_vpllsrc_list,
-	.nr_sources	= ARRAY_SIZE(clkset_vpllsrc_list),
-};
-
-static struct clksrc_clk clk_vpllsrc = {
-	.clk	= {
-		.name		= "vpll_src",
-		.id		= -1,
-		.enable		= s5pv310_clksrc_mask_top_ctrl,
-		.ctrlbit	= (1 << 0),
-	},
-	.sources	= &clkset_vpllsrc,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP1, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_sclk_vpll_list[] = {
-	[0] = &clk_vpllsrc.clk,
-	[1] = &clk_fout_vpll,
-};
-
-static struct clksrc_sources clkset_sclk_vpll = {
-	.sources	= clkset_sclk_vpll_list,
-	.nr_sources	= ARRAY_SIZE(clkset_sclk_vpll_list),
-};
-
-static struct clksrc_clk clk_sclk_vpll = {
-	.clk	= {
-		.name		= "sclk_vpll",
-		.id		= -1,
-	},
-	.sources	= &clkset_sclk_vpll,
-	.reg_src	= { .reg = S5P_CLKSRC_TOP0, .shift = 8, .size = 1 },
-};
-
-static struct clk init_clocks_off[] = {
-	{
-		.name		= "timers",
-		.id		= -1,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1<<24),
-	}, {
-		.name		= "csis",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "csis",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "fimc",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimc",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "fimc",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "fimc",
-		.id		= 3,
-		.enable		= s5pv310_clk_ip_cam_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "fimd",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_lcd0_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "fimd",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_lcd1_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "hsmmc",
-		.id		= 0,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 5),
-	}, {
-		.name		= "hsmmc",
-		.id		= 1,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "hsmmc",
-		.id		= 2,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "hsmmc",
-		.id		= 3,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "hsmmc",
-		.id		= 4,
-		.parent		= &clk_aclk_133.clk,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "sata",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "pdma",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "pdma",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "adc",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "rtc",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 15),
-	}, {
-		.name		= "watchdog",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_perir_ctrl,
-		.ctrlbit	= (1 << 14),
-	}, {
-		.name		= "usbhost",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl ,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "otg",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_fsys_ctrl,
-		.ctrlbit	= (1 << 13),
-	}, {
-		.name		= "spi",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 16),
-	}, {
-		.name		= "spi",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 17),
-	}, {
-		.name		= "spi",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 18),
-	}, {
-		.name		= "iis",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 19),
-	}, {
-		.name		= "iis",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 20),
-	}, {
-		.name		= "iis",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 21),
-	}, {
-		.name		= "ac97",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 27),
-	}, {
-		.name		= "fimg2d",
-		.id		= -1,
-		.enable		= s5pv310_clk_ip_image_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "i2c",
-		.id		= 0,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 6),
-	}, {
-		.name		= "i2c",
-		.id		= 1,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 7),
-	}, {
-		.name		= "i2c",
-		.id		= 2,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 8),
-	}, {
-		.name		= "i2c",
-		.id		= 3,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 9),
-	}, {
-		.name		= "i2c",
-		.id		= 4,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 10),
-	}, {
-		.name		= "i2c",
-		.id		= 5,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 11),
-	}, {
-		.name		= "i2c",
-		.id		= 6,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 12),
-	}, {
-		.name		= "i2c",
-		.id		= 7,
-		.parent		= &clk_aclk_100.clk,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 13),
-	},
-};
-
-static struct clk init_clocks[] = {
-	{
-		.name		= "uart",
-		.id		= 0,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 0),
-	}, {
-		.name		= "uart",
-		.id		= 1,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 1),
-	}, {
-		.name		= "uart",
-		.id		= 2,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 2),
-	}, {
-		.name		= "uart",
-		.id		= 3,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 3),
-	}, {
-		.name		= "uart",
-		.id		= 4,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 4),
-	}, {
-		.name		= "uart",
-		.id		= 5,
-		.enable		= s5pv310_clk_ip_peril_ctrl,
-		.ctrlbit	= (1 << 5),
-	}
-};
-
-static struct clk *clkset_group_list[] = {
-	[0] = &clk_ext_xtal_mux,
-	[1] = &clk_xusbxti,
-	[2] = &clk_sclk_hdmi27m,
-	[3] = &clk_sclk_usbphy0,
-	[4] = &clk_sclk_usbphy1,
-	[5] = &clk_sclk_hdmiphy,
-	[6] = &clk_mout_mpll.clk,
-	[7] = &clk_mout_epll.clk,
-	[8] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_group = {
-	.sources	= clkset_group_list,
-	.nr_sources	= ARRAY_SIZE(clkset_group_list),
-};
-
-static struct clk *clkset_mout_g2d0_list[] = {
-	[0] = &clk_mout_mpll.clk,
-	[1] = &clk_sclk_apll.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d0 = {
-	.sources	= clkset_mout_g2d0_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d0_list),
-};
-
-static struct clksrc_clk clk_mout_g2d0 = {
-	.clk	= {
-		.name		= "mout_g2d0",
-		.id		= -1,
-	},
-	.sources	= &clkset_mout_g2d0,
-	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 0, .size = 1 },
-};
-
-static struct clk *clkset_mout_g2d1_list[] = {
-	[0] = &clk_mout_epll.clk,
-	[1] = &clk_sclk_vpll.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d1 = {
-	.sources	= clkset_mout_g2d1_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d1_list),
-};
-
-static struct clksrc_clk clk_mout_g2d1 = {
-	.clk	= {
-		.name		= "mout_g2d1",
-		.id		= -1,
-	},
-	.sources	= &clkset_mout_g2d1,
-	.reg_src	= { .reg = S5P_CLKSRC_IMAGE, .shift = 4, .size = 1 },
-};
-
-static struct clk *clkset_mout_g2d_list[] = {
-	[0] = &clk_mout_g2d0.clk,
-	[1] = &clk_mout_g2d1.clk,
-};
-
-static struct clksrc_sources clkset_mout_g2d = {
-	.sources	= clkset_mout_g2d_list,
-	.nr_sources	= ARRAY_SIZE(clkset_mout_g2d_list),
-};
-
-static struct clksrc_clk clk_dout_mmc0 = {
-	.clk		= {
-		.name		= "dout_mmc0",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 0, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc1 = {
-	.clk		= {
-		.name		= "dout_mmc1",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 4, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc2 = {
-	.clk		= {
-		.name		= "dout_mmc2",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 8, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc3 = {
-	.clk		= {
-		.name		= "dout_mmc3",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 12, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 16, .size = 4 },
-};
-
-static struct clksrc_clk clk_dout_mmc4 = {
-	.clk		= {
-		.name		= "dout_mmc4",
-		.id		= -1,
-	},
-	.sources = &clkset_group,
-	.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 16, .size = 4 },
-	.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 0, .size = 4 },
-};
-
-static struct clksrc_clk clksrcs[] = {
-	{
-		.clk	= {
-			.name		= "uclk1",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 4, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.id		= 2,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 8, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "uclk1",
-			.id		= 3,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL0, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_pwm",
-			.id		= -1,
-			.enable		= s5pv310_clksrc_mask_peril0_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL0, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL3, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 24, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_csis",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 28),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 28, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 28, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_cam",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 4, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 4, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 2,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 8, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 8, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimc",
-			.id		= 3,
-			.enable		= s5pv310_clksrc_mask_cam_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_CAM, .shift = 12, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_CAM, .shift = 12, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_lcd0_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD0, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD0, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimd",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_lcd1_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_LCD1, .shift = 0, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_LCD1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_sata",
-			.id		= -1,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_mout_corebus,
-		.reg_src = { .reg = S5P_CLKSRC_FSYS, .shift = 24, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_FSYS0, .shift = 20, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.id		= 0,
-			.enable		= s5pv310_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 16, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.id		= 1,
-			.enable		= s5pv310_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 20),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 20, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL1, .shift = 16, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_spi",
-			.id		= 2,
-			.enable		= s5pv310_clksrc_mask_peril1_ctrl,
-			.ctrlbit	= (1 << 24),
-		},
-		.sources = &clkset_group,
-		.reg_src = { .reg = S5P_CLKSRC_PERIL1, .shift = 24, .size = 4 },
-		.reg_div = { .reg = S5P_CLKDIV_PERIL2, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_fimg2d",
-			.id		= -1,
-		},
-		.sources = &clkset_mout_g2d,
-		.reg_src = { .reg = S5P_CLKSRC_IMAGE, .shift = 8, .size = 1 },
-		.reg_div = { .reg = S5P_CLKDIV_IMAGE, .shift = 0, .size = 4 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 0,
-			.parent		= &clk_dout_mmc0.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 0),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 8, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 1,
-			.parent         = &clk_dout_mmc1.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 4),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS1, .shift = 24, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 2,
-			.parent         = &clk_dout_mmc2.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 8),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 8, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 3,
-			.parent         = &clk_dout_mmc3.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 12),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS2, .shift = 24, .size = 8 },
-	}, {
-		.clk		= {
-			.name		= "sclk_mmc",
-			.id		= 4,
-			.parent         = &clk_dout_mmc4.clk,
-			.enable		= s5pv310_clksrc_mask_fsys_ctrl,
-			.ctrlbit	= (1 << 16),
-		},
-		.reg_div = { .reg = S5P_CLKDIV_FSYS3, .shift = 8, .size = 8 },
-	}
-};
-
-/* Clock initialization code */
-static struct clksrc_clk *sysclks[] = {
-	&clk_mout_apll,
-	&clk_sclk_apll,
-	&clk_mout_epll,
-	&clk_mout_mpll,
-	&clk_moutcore,
-	&clk_coreclk,
-	&clk_armclk,
-	&clk_aclk_corem0,
-	&clk_aclk_cores,
-	&clk_aclk_corem1,
-	&clk_periphclk,
-	&clk_mout_corebus,
-	&clk_sclk_dmc,
-	&clk_aclk_cored,
-	&clk_aclk_corep,
-	&clk_aclk_acp,
-	&clk_pclk_acp,
-	&clk_vpllsrc,
-	&clk_sclk_vpll,
-	&clk_aclk_200,
-	&clk_aclk_100,
-	&clk_aclk_160,
-	&clk_aclk_133,
-	&clk_dout_mmc0,
-	&clk_dout_mmc1,
-	&clk_dout_mmc2,
-	&clk_dout_mmc3,
-	&clk_dout_mmc4,
-};
-
-static int xtal_rate;
-
-static unsigned long s5pv310_fout_apll_get_rate(struct clk *clk)
-{
-	return s5p_get_pll45xx(xtal_rate, __raw_readl(S5P_APLL_CON0), pll_4508);
-}
-
-static struct clk_ops s5pv310_fout_apll_ops = {
-	.get_rate = s5pv310_fout_apll_get_rate,
-};
-
-void __init_or_cpufreq s5pv310_setup_clocks(void)
-{
-	struct clk *xtal_clk;
-	unsigned long apll;
-	unsigned long mpll;
-	unsigned long epll;
-	unsigned long vpll;
-	unsigned long vpllsrc;
-	unsigned long xtal;
-	unsigned long armclk;
-	unsigned long sclk_dmc;
-	unsigned long aclk_200;
-	unsigned long aclk_100;
-	unsigned long aclk_160;
-	unsigned long aclk_133;
-	unsigned int ptr;
-
-	printk(KERN_DEBUG "%s: registering clocks\n", __func__);
-
-	xtal_clk = clk_get(NULL, "xtal");
-	BUG_ON(IS_ERR(xtal_clk));
-
-	xtal = clk_get_rate(xtal_clk);
-
-	xtal_rate = xtal;
-
-	clk_put(xtal_clk);
-
-	printk(KERN_DEBUG "%s: xtal is %ld\n", __func__, xtal);
-
-	apll = s5p_get_pll45xx(xtal, __raw_readl(S5P_APLL_CON0), pll_4508);
-	mpll = s5p_get_pll45xx(xtal, __raw_readl(S5P_MPLL_CON0), pll_4508);
-	epll = s5p_get_pll46xx(xtal, __raw_readl(S5P_EPLL_CON0),
-				__raw_readl(S5P_EPLL_CON1), pll_4600);
-
-	vpllsrc = clk_get_rate(&clk_vpllsrc.clk);
-	vpll = s5p_get_pll46xx(vpllsrc, __raw_readl(S5P_VPLL_CON0),
-				__raw_readl(S5P_VPLL_CON1), pll_4650);
-
-	clk_fout_apll.ops = &s5pv310_fout_apll_ops;
-	clk_fout_mpll.rate = mpll;
-	clk_fout_epll.rate = epll;
-	clk_fout_vpll.rate = vpll;
-
-	printk(KERN_INFO "S5PV310: PLL settings, A=%ld, M=%ld, E=%ld V=%ld",
-			apll, mpll, epll, vpll);
-
-	armclk = clk_get_rate(&clk_armclk.clk);
-	sclk_dmc = clk_get_rate(&clk_sclk_dmc.clk);
-
-	aclk_200 = clk_get_rate(&clk_aclk_200.clk);
-	aclk_100 = clk_get_rate(&clk_aclk_100.clk);
-	aclk_160 = clk_get_rate(&clk_aclk_160.clk);
-	aclk_133 = clk_get_rate(&clk_aclk_133.clk);
-
-	printk(KERN_INFO "S5PV310: ARMCLK=%ld, DMC=%ld, ACLK200=%ld\n"
-			 "ACLK100=%ld, ACLK160=%ld, ACLK133=%ld\n",
-			armclk, sclk_dmc, aclk_200,
-			aclk_100, aclk_160, aclk_133);
-
-	clk_f.rate = armclk;
-	clk_h.rate = sclk_dmc;
-	clk_p.rate = aclk_100;
-
-	for (ptr = 0; ptr < ARRAY_SIZE(clksrcs); ptr++)
-		s3c_set_clksrc(&clksrcs[ptr], true);
-}
-
-static struct clk *clks[] __initdata = {
-	/* Nothing here yet */
-};
-
-void __init s5pv310_register_clocks(void)
-{
-	int ptr;
-
-	s3c24xx_register_clocks(clks, ARRAY_SIZE(clks));
-
-	for (ptr = 0; ptr < ARRAY_SIZE(sysclks); ptr++)
-		s3c_register_clksrc(sysclks[ptr], 1);
-
-	s3c_register_clksrc(clksrcs, ARRAY_SIZE(clksrcs));
-	s3c_register_clocks(init_clocks, ARRAY_SIZE(init_clocks));
-
-	s3c_register_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-	s3c_disable_clocks(init_clocks_off, ARRAY_SIZE(init_clocks_off));
-
-	s3c_pwmclk_init();
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/cpu.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/cpu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/cpu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,202 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/cpu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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/sched.h>
-#include <linux/sysdev.h>
-
-#include <asm/mach/map.h>
-#include <asm/mach/irq.h>
-
-#include <asm/proc-fns.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include <plat/cpu.h>
-#include <plat/clock.h>
-#include <plat/s5pv310.h>
-#include <plat/sdhci.h>
-
-#include <mach/regs-irq.h>
-
-extern int combiner_init(unsigned int combiner_nr, void __iomem *base,
-			 unsigned int irq_start);
-extern void combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq);
-
-/* Initial IO mappings */
-static struct map_desc s5pv310_iodesc[] __initdata = {
-	{
-		.virtual	= (unsigned long)S5P_VA_SYSRAM,
-		.pfn		= __phys_to_pfn(S5PV310_PA_SYSRAM),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_CMU,
-		.pfn		= __phys_to_pfn(S5PV310_PA_CMU),
-		.length		= SZ_128K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_PMU,
-		.pfn		= __phys_to_pfn(S5PV310_PA_PMU),
-		.length		= SZ_64K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_COMBINER_BASE,
-		.pfn		= __phys_to_pfn(S5PV310_PA_COMBINER),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_COREPERI_BASE,
-		.pfn		= __phys_to_pfn(S5PV310_PA_COREPERI),
-		.length		= SZ_8K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_L2CC,
-		.pfn		= __phys_to_pfn(S5PV310_PA_L2CC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO1,
-		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO1),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO2,
-		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO2),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_GPIO3,
-		.pfn		= __phys_to_pfn(S5PV310_PA_GPIO3),
-		.length		= SZ_256,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_DMC0,
-		.pfn		= __phys_to_pfn(S5PV310_PA_DMC0),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S3C_VA_UART,
-		.pfn		= __phys_to_pfn(S3C_PA_UART),
-		.length		= SZ_512K,
-		.type		= MT_DEVICE,
-	}, {
-		.virtual	= (unsigned long)S5P_VA_SROMC,
-		.pfn		= __phys_to_pfn(S5PV310_PA_SROMC),
-		.length		= SZ_4K,
-		.type		= MT_DEVICE,
-	},
-};
-
-static void s5pv310_idle(void)
-{
-	if (!need_resched())
-		cpu_do_idle();
-
-	local_irq_enable();
-}
-
-/* s5pv310_map_io
- *
- * register the standard cpu IO areas
-*/
-void __init s5pv310_map_io(void)
-{
-	iotable_init(s5pv310_iodesc, ARRAY_SIZE(s5pv310_iodesc));
-
-	/* initialize device information early */
-	s5pv310_default_sdhci0();
-	s5pv310_default_sdhci1();
-	s5pv310_default_sdhci2();
-	s5pv310_default_sdhci3();
-}
-
-void __init s5pv310_init_clocks(int xtal)
-{
-	printk(KERN_DEBUG "%s: initializing clocks\n", __func__);
-
-	s3c24xx_register_baseclocks(xtal);
-	s5p_register_clocks(xtal);
-	s5pv310_register_clocks();
-	s5pv310_setup_clocks();
-}
-
-void __init s5pv310_init_irq(void)
-{
-	int irq;
-
-	gic_init(0, IRQ_LOCALTIMER, S5P_VA_GIC_DIST, S5P_VA_GIC_CPU);
-
-	for (irq = 0; irq < MAX_COMBINER_NR; irq++) {
-
-		/*
-		 * From SPI(0) to SPI(39) and SPI(51), SPI(53) are
-		 * connected to the interrupt combiner. These irqs
-		 * should be initialized to support cascade interrupt.
-		 */
-		if ((irq >= 40) && !(irq == 51) && !(irq == 53))
-			continue;
-
-		combiner_init(irq, (void __iomem *)S5P_VA_COMBINER(irq),
-				COMBINER_IRQ(irq, 0));
-		combiner_cascade_irq(irq, IRQ_SPI(irq));
-	}
-
-	/* The parameters of s5p_init_irq() are for VIC init.
-	 * Theses parameters should be NULL and 0 because S5PV310
-	 * uses GIC instead of VIC.
-	 */
-	s5p_init_irq(NULL, 0);
-}
-
-struct sysdev_class s5pv310_sysclass = {
-	.name	= "s5pv310-core",
-};
-
-static struct sys_device s5pv310_sysdev = {
-	.cls	= &s5pv310_sysclass,
-};
-
-static int __init s5pv310_core_init(void)
-{
-	return sysdev_class_register(&s5pv310_sysclass);
-}
-
-core_initcall(s5pv310_core_init);
-
-#ifdef CONFIG_CACHE_L2X0
-static int __init s5pv310_l2x0_cache_init(void)
-{
-	/* TAG, Data Latency Control: 2cycle */
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_TAG_LATENCY_CTRL);
-	__raw_writel(0x110, S5P_VA_L2CC + L2X0_DATA_LATENCY_CTRL);
-
-	/* L2X0 Prefetch Control */
-	__raw_writel(0x30000007, S5P_VA_L2CC + L2X0_PREFETCH_CTRL);
-
-	/* L2X0 Power Control */
-	__raw_writel(L2X0_DYNAMIC_CLK_GATING_EN | L2X0_STNDBY_MODE_EN,
-		     S5P_VA_L2CC + L2X0_POWER_CTRL);
-
-	l2x0_init(S5P_VA_L2CC, 0x7C470001, 0xC200ffff);
-
-	return 0;
-}
-
-early_initcall(s5pv310_l2x0_cache_init);
-#endif
-
-int __init s5pv310_init(void)
-{
-	printk(KERN_INFO "S5PV310: Initializing architecture\n");
-
-	/* set idle function */
-	pm_idle = s5pv310_idle;
-
-	return sysdev_register(&s5pv310_sysdev);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/cpufreq.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/cpufreq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,580 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/cpufreq.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - CPU frequency scaling 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/types.h>
-#include <linux/kernel.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
-#include <linux/cpufreq.h>
-
-#include <mach/map.h>
-#include <mach/regs-clock.h>
-#include <mach/regs-mem.h>
-
-#include <plat/clock.h>
-#include <plat/pm.h>
-
-static struct clk *cpu_clk;
-static struct clk *moutcore;
-static struct clk *mout_mpll;
-static struct clk *mout_apll;
-
-#ifdef CONFIG_REGULATOR
-static struct regulator *arm_regulator;
-static struct regulator *int_regulator;
-#endif
-
-static struct cpufreq_freqs freqs;
-static unsigned int memtype;
-
-enum s5pv310_memory_type {
-	DDR2 = 4,
-	LPDDR2,
-	DDR3,
-};
-
-enum cpufreq_level_index {
-	L0, L1, L2, L3, CPUFREQ_LEVEL_END,
-};
-
-static struct cpufreq_frequency_table s5pv310_freq_table[] = {
-	{L0, 1000*1000},
-	{L1, 800*1000},
-	{L2, 400*1000},
-	{L3, 100*1000},
-	{0, CPUFREQ_TABLE_END},
-};
-
-static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVCORE, DIVCOREM0, DIVCOREM1, DIVPERIPH,
-	 *		DIVATB, DIVPCLK_DBG, DIVAPLL }
-	 */
-
-	/* ARM L0: 1000MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
-
-	/* ARM L1: 800MHz */
-	{ 0, 3, 7, 3, 3, 0, 1 },
-
-	/* ARM L2: 400MHz */
-	{ 0, 1, 3, 1, 3, 0, 1 },
-
-	/* ARM L3: 100MHz */
-	{ 0, 0, 1, 0, 3, 1, 1 },
-};
-
-static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVCOPY, DIVHPM }
-	 */
-
-	 /* ARM L0: 1000MHz */
-	{ 3, 0 },
-
-	/* ARM L1: 800MHz */
-	{ 3, 0 },
-
-	/* ARM L2: 400MHz */
-	{ 3, 0 },
-
-	/* ARM L3: 100MHz */
-	{ 3, 0 },
-};
-
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
-	 *		DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
-	 */
-
-	/* DMC L0: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L1: 400MHz */
-	{ 3, 1, 1, 1, 1, 1, 3, 1 },
-
-	/* DMC L2: 266.7MHz */
-	{ 7, 1, 1, 2, 1, 1, 3, 1 },
-
-	/* DMC L3: 200MHz */
-	{ 7, 1, 1, 3, 1, 1, 3, 1 },
-};
-
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
-	 */
-
-	/* ACLK200 L0: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L1: 200MHz */
-	{ 3, 7, 4, 5, 1 },
-
-	/* ACLK200 L2: 160MHz */
-	{ 4, 7, 5, 7, 1 },
-
-	/* ACLK200 L3: 133.3MHz */
-	{ 5, 7, 7, 7, 1 },
-};
-
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
-	/*
-	 * Clock divider value for following
-	 * { DIVGDL/R, DIVGPL/R }
-	 */
-
-	/* ACLK_GDL/R L0: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L1: 200MHz */
-	{ 3, 1 },
-
-	/* ACLK_GDL/R L2: 160MHz */
-	{ 4, 1 },
-
-	/* ACLK_GDL/R L3: 133.3MHz */
-	{ 5, 1 },
-};
-
-struct cpufreq_voltage_table {
-	unsigned int	index;		/* any */
-	unsigned int	arm_volt;	/* uV */
-	unsigned int	int_volt;
-};
-
-static struct cpufreq_voltage_table s5pv310_volt_table[CPUFREQ_LEVEL_END] = {
-	{
-		.index		= L0,
-		.arm_volt	= 1200000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L1,
-		.arm_volt	= 1100000,
-		.int_volt	= 1100000,
-	}, {
-		.index		= L2,
-		.arm_volt	= 1000000,
-		.int_volt	= 1000000,
-	}, {
-		.index		= L3,
-		.arm_volt	= 900000,
-		.int_volt	= 1000000,
-	},
-};
-
-static unsigned int s5pv310_apll_pms_table[CPUFREQ_LEVEL_END] = {
-	/* APLL FOUT L0: 1000MHz */
-	((250 << 16) | (6 << 8) | 1),
-
-	/* APLL FOUT L1: 800MHz */
-	((200 << 16) | (6 << 8) | 1),
-
-	/* APLL FOUT L2 : 400MHz */
-	((200 << 16) | (6 << 8) | 2),
-
-	/* APLL FOUT L3: 100MHz */
-	((200 << 16) | (6 << 8) | 4),
-};
-
-int s5pv310_verify_speed(struct cpufreq_policy *policy)
-{
-	return cpufreq_frequency_table_verify(policy, s5pv310_freq_table);
-}
-
-unsigned int s5pv310_getspeed(unsigned int cpu)
-{
-	return clk_get_rate(cpu_clk) / 1000;
-}
-
-void s5pv310_set_clkdiv(unsigned int div_index)
-{
-	unsigned int tmp;
-
-	/* Change Divider - CPU0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_CPU);
-
-	tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
-		S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
-		S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
-		S5P_CLKDIV_CPU0_APLL_MASK);
-
-	tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
-		(clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
-		(clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
-		(clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
-		(clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
-		(clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
-		(clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_CPU);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STATCPU);
-	} while (tmp & 0x1111111);
-
-	/* Change Divider - CPU1 */
-
-	tmp = __raw_readl(S5P_CLKDIV_CPU1);
-
-	tmp &= ~((0x7 << 4) | 0x7);
-
-	tmp |= ((clkdiv_cpu1[div_index][0] << 4) |
-		(clkdiv_cpu1[div_index][1] << 0));
-
-	__raw_writel(tmp, S5P_CLKDIV_CPU1);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
-	} while (tmp & 0x11);
-
-	/* Change Divider - DMC0 */
-
-	tmp = __raw_readl(S5P_CLKDIV_DMC0);
-
-	tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
-		S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
-		S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
-		S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
-
-	tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
-		(clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
-		(clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
-		(clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
-		(clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
-		(clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
-		(clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
-		(clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_DMC0);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
-	} while (tmp & 0x11111111);
-
-	/* Change Divider - TOP */
-
-	tmp = __raw_readl(S5P_CLKDIV_TOP);
-
-	tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
-		S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
-		S5P_CLKDIV_TOP_ONENAND_MASK);
-
-	tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
-		(clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
-		(clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
-		(clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
-		(clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_TOP);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
-	} while (tmp & 0x11111);
-
-	/* Change Divider - LEFTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
-	} while (tmp & 0x11);
-
-	/* Change Divider - RIGHTBUS */
-
-	tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
-
-	tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
-	tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
-		(clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
-	__raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
-
-	do {
-		tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
-	} while (tmp & 0x11);
-}
-
-static void s5pv310_set_apll(unsigned int index)
-{
-	unsigned int tmp;
-
-	/* 1. MUX_CORE_SEL = MPLL, ARMCLK uses MPLL for lock time */
-	clk_set_parent(moutcore, mout_mpll);
-
-	do {
-		tmp = (__raw_readl(S5P_CLKMUX_STATCPU)
-			>> S5P_CLKSRC_CPU_MUXCORE_SHIFT);
-		tmp &= 0x7;
-	} while (tmp != 0x2);
-
-	/* 2. Set APLL Lock time */
-	__raw_writel(S5P_APLL_LOCKTIME, S5P_APLL_LOCK);
-
-	/* 3. Change PLL PMS values */
-	tmp = __raw_readl(S5P_APLL_CON0);
-	tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
-	tmp |= s5pv310_apll_pms_table[index];
-	__raw_writel(tmp, S5P_APLL_CON0);
-
-	/* 4. wait_lock_time */
-	do {
-		tmp = __raw_readl(S5P_APLL_CON0);
-	} while (!(tmp & (0x1 << S5P_APLLCON0_LOCKED_SHIFT)));
-
-	/* 5. MUX_CORE_SEL = APLL */
-	clk_set_parent(moutcore, mout_apll);
-
-	do {
-		tmp = __raw_readl(S5P_CLKMUX_STATCPU);
-		tmp &= S5P_CLKMUX_STATCPU_MUXCORE_MASK;
-	} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
-}
-
-static void s5pv310_set_frequency(unsigned int old_index, unsigned int new_index)
-{
-	unsigned int tmp;
-
-	if (old_index > new_index) {
-		/* The frequency changing to L0 needs to change apll */
-		if (freqs.new == s5pv310_freq_table[L0].frequency) {
-			/* 1. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-
-			/* 2. Change the apll m,p,s value */
-			s5pv310_set_apll(new_index);
-		} else {
-			/* 1. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-
-			/* 2. Change just s value in apll m,p,s value */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp &= ~(0x7 << 0);
-			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
-			__raw_writel(tmp, S5P_APLL_CON0);
-		}
-	}
-
-	else if (old_index < new_index) {
-		/* The frequency changing from L0 needs to change apll */
-		if (freqs.old == s5pv310_freq_table[L0].frequency) {
-			/* 1. Change the apll m,p,s value */
-			s5pv310_set_apll(new_index);
-
-			/* 2. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-		} else {
-			/* 1. Change just s value in apll m,p,s value */
-			tmp = __raw_readl(S5P_APLL_CON0);
-			tmp &= ~(0x7 << 0);
-			tmp |= (s5pv310_apll_pms_table[new_index] & 0x7);
-			__raw_writel(tmp, S5P_APLL_CON0);
-
-			/* 2. Change the system clock divider values */
-			s5pv310_set_clkdiv(new_index);
-		}
-	}
-}
-
-static int s5pv310_target(struct cpufreq_policy *policy,
-			  unsigned int target_freq,
-			  unsigned int relation)
-{
-	unsigned int index, old_index;
-	unsigned int arm_volt, int_volt;
-
-	freqs.old = s5pv310_getspeed(policy->cpu);
-
-	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
-					   freqs.old, relation, &old_index))
-		return -EINVAL;
-
-	if (cpufreq_frequency_table_target(policy, s5pv310_freq_table,
-					   target_freq, relation, &index))
-		return -EINVAL;
-
-	freqs.new = s5pv310_freq_table[index].frequency;
-	freqs.cpu = policy->cpu;
-
-	if (freqs.new == freqs.old)
-		return 0;
-
-	/* get the voltage value */
-	arm_volt = s5pv310_volt_table[index].arm_volt;
-	int_volt = s5pv310_volt_table[index].int_volt;
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
-	/* control regulator */
-	if (freqs.new > freqs.old) {
-		/* Voltage up */
-#ifdef CONFIG_REGULATOR
-		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-#endif
-	}
-
-	/* Clock Configuration Procedure */
-	s5pv310_set_frequency(old_index, index);
-
-	/* control regulator */
-	if (freqs.new < freqs.old) {
-		/* Voltage down */
-#ifdef CONFIG_REGULATOR
-		regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
-		regulator_set_voltage(int_regulator, int_volt, int_volt);
-#endif
-	}
-
-	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int s5pv310_cpufreq_suspend(struct cpufreq_policy *policy,
-				   pm_message_t pmsg)
-{
-	return 0;
-}
-
-static int s5pv310_cpufreq_resume(struct cpufreq_policy *policy)
-{
-	return 0;
-}
-#endif
-
-static int s5pv310_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
-	policy->cur = policy->min = policy->max = s5pv310_getspeed(policy->cpu);
-
-	cpufreq_frequency_table_get_attr(s5pv310_freq_table, policy->cpu);
-
-	/* set the transition latency value */
-	policy->cpuinfo.transition_latency = 100000;
-
-	/*
-	 * S5PV310 multi-core processors has 2 cores
-	 * that the frequency cannot be set independently.
-	 * Each cpu is bound to the same speed.
-	 * So the affected cpu is all of the cpus.
-	 */
-	cpumask_setall(policy->cpus);
-
-	return cpufreq_frequency_table_cpuinfo(policy, s5pv310_freq_table);
-}
-
-static struct cpufreq_driver s5pv310_driver = {
-	.flags		= CPUFREQ_STICKY,
-	.verify		= s5pv310_verify_speed,
-	.target		= s5pv310_target,
-	.get		= s5pv310_getspeed,
-	.init		= s5pv310_cpufreq_cpu_init,
-	.name		= "s5pv310_cpufreq",
-#ifdef CONFIG_PM
-	.suspend	= s5pv310_cpufreq_suspend,
-	.resume		= s5pv310_cpufreq_resume,
-#endif
-};
-
-static int __init s5pv310_cpufreq_init(void)
-{
-	cpu_clk = clk_get(NULL, "armclk");
-	if (IS_ERR(cpu_clk))
-		return PTR_ERR(cpu_clk);
-
-	moutcore = clk_get(NULL, "moutcore");
-	if (IS_ERR(moutcore))
-		goto out;
-
-	mout_mpll = clk_get(NULL, "mout_mpll");
-	if (IS_ERR(mout_mpll))
-		goto out;
-
-	mout_apll = clk_get(NULL, "mout_apll");
-	if (IS_ERR(mout_apll))
-		goto out;
-
-#ifdef CONFIG_REGULATOR
-	arm_regulator = regulator_get(NULL, "vdd_arm");
-	if (IS_ERR(arm_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
-		goto out;
-	}
-
-	int_regulator = regulator_get(NULL, "vdd_int");
-	if (IS_ERR(int_regulator)) {
-		printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
-		goto out;
-	}
-#endif
-
-	/*
-	 * Check DRAM type.
-	 * Because DVFS level is different according to DRAM type.
-	 */
-	memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
-	memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
-	memtype &= S5P_DMC0_MEMTYPE_MASK;
-
-	if ((memtype < DDR2) && (memtype > DDR3)) {
-		printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
-		goto out;
-	} else {
-		printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
-	}
-
-	return cpufreq_register_driver(&s5pv310_driver);
-
-out:
-	if (!IS_ERR(cpu_clk))
-		clk_put(cpu_clk);
-
-	if (!IS_ERR(moutcore))
-		clk_put(moutcore);
-
-	if (!IS_ERR(mout_mpll))
-		clk_put(mout_mpll);
-
-	if (!IS_ERR(mout_apll))
-		clk_put(mout_apll);
-
-#ifdef CONFIG_REGULATOR
-	if (!IS_ERR(arm_regulator))
-		regulator_put(arm_regulator);
-
-	if (!IS_ERR(int_regulator))
-		regulator_put(int_regulator);
-#endif
-
-	printk(KERN_ERR "%s: failed initialization\n", __func__);
-
-	return -EINVAL;
-}
-late_initcall(s5pv310_cpufreq_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dev-audio.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dev-audio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dev-audio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dev-audio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,364 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/dev-audio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co. Ltd
- *	Jaswinder Singh <jassi.brar@samsung.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 <linux/dma-mapping.h>
-#include <linux/gpio.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/audio.h>
-
-#include <mach/map.h>
-#include <mach/dma.h>
-#include <mach/irqs.h>
-
-static const char *rclksrc[] = {
-	[0] = "busclk",
-	[1] = "i2sclk",
-};
-
-static int s5pv310_cfg_i2s(struct platform_device *pdev)
-{
-	/* configure GPIO for i2s port */
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 7, S3C_GPIO_SFN(2));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(2));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 5, S3C_GPIO_SFN(4));
-		break;
-	default:
-		printk(KERN_ERR "Invalid Device %d\n", pdev->id);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata i2sv5_pdata = {
-	.cfg_gpio = s5pv310_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_PRI_6CHAN | QUIRK_SEC_DAI
-					 | QUIRK_NEED_RSTCLR,
-			.src_clk = rclksrc,
-		},
-	},
-};
-
-static struct resource s5pv310_i2s0_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_I2S0,
-		.end	= S5PV310_PA_I2S0 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S0_TX,
-		.end	= DMACH_I2S0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S0_RX,
-		.end	= DMACH_I2S0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DMACH_I2S0S_TX,
-		.end	= DMACH_I2S0S_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_i2s0 = {
-	.name = "samsung-i2s",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(s5pv310_i2s0_resource),
-	.resource = s5pv310_i2s0_resource,
-	.dev = {
-		.platform_data = &i2sv5_pdata,
-	},
-};
-
-static const char *rclksrc_v3[] = {
-	[0] = "sclk_i2s",
-	[1] = "no_such_clock",
-};
-
-static struct s3c_audio_pdata i2sv3_pdata = {
-	.cfg_gpio = s5pv310_cfg_i2s,
-	.type = {
-		.i2s = {
-			.quirks = QUIRK_NO_MUXPSR,
-			.src_clk = rclksrc_v3,
-		},
-	},
-};
-
-static struct resource s5pv310_i2s1_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_I2S1,
-		.end	= S5PV310_PA_I2S1 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S1_TX,
-		.end	= DMACH_I2S1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S1_RX,
-		.end	= DMACH_I2S1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_i2s1 = {
-	.name = "samsung-i2s",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(s5pv310_i2s1_resource),
-	.resource = s5pv310_i2s1_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-static struct resource s5pv310_i2s2_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_I2S2,
-		.end	= S5PV310_PA_I2S2 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_I2S2_TX,
-		.end	= DMACH_I2S2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_I2S2_RX,
-		.end	= DMACH_I2S2_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_i2s2 = {
-	.name = "samsung-i2s",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(s5pv310_i2s2_resource),
-	.resource = s5pv310_i2s2_resource,
-	.dev = {
-		.platform_data = &i2sv3_pdata,
-	},
-};
-
-/* PCM Controller platform_devices */
-
-static int s5pv310_pcm_cfg_gpio(struct platform_device *pdev)
-{
-	switch (pdev->id) {
-	case 0:
-		s3c_gpio_cfgpin_range(S5PV310_GPZ(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 1:
-		s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(3));
-		break;
-	case 2:
-		s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 5, S3C_GPIO_SFN(3));
-		break;
-	default:
-		printk(KERN_DEBUG "Invalid PCM Controller number!");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static struct s3c_audio_pdata s3c_pcm_pdata = {
-	.cfg_gpio = s5pv310_pcm_cfg_gpio,
-};
-
-static struct resource s5pv310_pcm0_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PCM0,
-		.end	= S5PV310_PA_PCM0 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM0_TX,
-		.end	= DMACH_PCM0_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM0_RX,
-		.end	= DMACH_PCM0_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_pcm0 = {
-	.name = "samsung-pcm",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(s5pv310_pcm0_resource),
-	.resource = s5pv310_pcm0_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pv310_pcm1_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PCM1,
-		.end	= S5PV310_PA_PCM1 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM1_TX,
-		.end	= DMACH_PCM1_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM1_RX,
-		.end	= DMACH_PCM1_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_pcm1 = {
-	.name = "samsung-pcm",
-	.id = 1,
-	.num_resources = ARRAY_SIZE(s5pv310_pcm1_resource),
-	.resource = s5pv310_pcm1_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-static struct resource s5pv310_pcm2_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PCM2,
-		.end	= S5PV310_PA_PCM2 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_PCM2_TX,
-		.end	= DMACH_PCM2_TX,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_PCM2_RX,
-		.end	= DMACH_PCM2_RX,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-struct platform_device s5pv310_device_pcm2 = {
-	.name = "samsung-pcm",
-	.id = 2,
-	.num_resources = ARRAY_SIZE(s5pv310_pcm2_resource),
-	.resource = s5pv310_pcm2_resource,
-	.dev = {
-		.platform_data = &s3c_pcm_pdata,
-	},
-};
-
-/* AC97 Controller platform devices */
-
-static int s5pv310_ac97_cfg_gpio(struct platform_device *pdev)
-{
-	return s3c_gpio_cfgpin_range(S5PV310_GPC0(0), 5, S3C_GPIO_SFN(4));
-}
-
-static struct resource s5pv310_ac97_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_AC97,
-		.end	= S5PV310_PA_AC97 + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_AC97_PCMOUT,
-		.end	= DMACH_AC97_PCMOUT,
-		.flags	= IORESOURCE_DMA,
-	},
-	[2] = {
-		.start	= DMACH_AC97_PCMIN,
-		.end	= DMACH_AC97_PCMIN,
-		.flags	= IORESOURCE_DMA,
-	},
-	[3] = {
-		.start	= DMACH_AC97_MICIN,
-		.end	= DMACH_AC97_MICIN,
-		.flags	= IORESOURCE_DMA,
-	},
-	[4] = {
-		.start	= IRQ_AC97,
-		.end	= IRQ_AC97,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_audio_pdata s3c_ac97_pdata = {
-	.cfg_gpio = s5pv310_ac97_cfg_gpio,
-};
-
-static u64 s5pv310_ac97_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv310_device_ac97 = {
-	.name = "samsung-ac97",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(s5pv310_ac97_resource),
-	.resource = s5pv310_ac97_resource,
-	.dev = {
-		.platform_data = &s3c_ac97_pdata,
-		.dma_mask = &s5pv310_ac97_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
-
-/* S/PDIF Controller platform_device */
-
-static int s5pv310_spdif_cfg_gpio(struct platform_device *pdev)
-{
-	s3c_gpio_cfgpin_range(S5PV310_GPC1(0), 2, S3C_GPIO_SFN(3));
-
-	return 0;
-}
-
-static struct resource s5pv310_spdif_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_SPDIF,
-		.end	= S5PV310_PA_SPDIF + 0x100 - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= DMACH_SPDIF,
-		.end	= DMACH_SPDIF,
-		.flags	= IORESOURCE_DMA,
-	},
-};
-
-static struct s3c_audio_pdata samsung_spdif_pdata = {
-	.cfg_gpio = s5pv310_spdif_cfg_gpio,
-};
-
-static u64 s5pv310_spdif_dmamask = DMA_BIT_MASK(32);
-
-struct platform_device s5pv310_device_spdif = {
-	.name = "samsung-spdif",
-	.id = -1,
-	.num_resources = ARRAY_SIZE(s5pv310_spdif_resource),
-	.resource = s5pv310_spdif_resource,
-	.dev = {
-		.platform_data = &samsung_spdif_pdata,
-		.dma_mask = &s5pv310_spdif_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-	},
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dev-pd.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dev-pd.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dev-pd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dev-pd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/dev-pd.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - Power Domain 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/io.h>
-#include <linux/kernel.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-
-#include <mach/regs-pmu.h>
-
-#include <plat/pd.h>
-
-static int s5pv310_pd_enable(struct device *dev)
-{
-	struct samsung_pd_info *pdata =  dev->platform_data;
-	u32 timeout;
-
-	__raw_writel(S5P_INT_LOCAL_PWR_EN, pdata->base);
-
-	/* Wait max 1ms */
-	timeout = 10;
-	while ((__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN)
-		!= S5P_INT_LOCAL_PWR_EN) {
-		if (timeout == 0) {
-			printk(KERN_ERR "Power domain %s enable failed.\n",
-				dev_name(dev));
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		udelay(100);
-	}
-
-	return 0;
-}
-
-static int s5pv310_pd_disable(struct device *dev)
-{
-	struct samsung_pd_info *pdata =  dev->platform_data;
-	u32 timeout;
-
-	__raw_writel(0, pdata->base);
-
-	/* Wait max 1ms */
-	timeout = 10;
-	while (__raw_readl(pdata->base + 0x4) & S5P_INT_LOCAL_PWR_EN) {
-		if (timeout == 0) {
-			printk(KERN_ERR "Power domain %s disable failed.\n",
-				dev_name(dev));
-			return -ETIMEDOUT;
-		}
-		timeout--;
-		udelay(100);
-	}
-
-	return 0;
-}
-
-struct platform_device s5pv310_device_pd[] = {
-	{
-		.name		= "samsung-pd",
-		.id		= 0,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_MFC_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 1,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_G3D_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 2,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_LCD0_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 3,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_LCD1_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 4,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_TV_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 5,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_CAM_CONF,
-			},
-		},
-	}, {
-		.name		= "samsung-pd",
-		.id		= 6,
-		.dev = {
-			.platform_data = &(struct samsung_pd_info) {
-				.enable		= s5pv310_pd_enable,
-				.disable	= s5pv310_pd_disable,
-				.base		= S5P_PMU_GPS_CONF,
-			},
-		},
-	},
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dev-sysmmu.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dev-sysmmu.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dev-sysmmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dev-sysmmu.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,187 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/dev-sysmmu.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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 <linux/dma-mapping.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-static struct resource s5pv310_sysmmu_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_SYSMMU_MDMA,
-		.end	= S5PV310_PA_SYSMMU_MDMA + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_SYSMMU_MDMA0_0,
-		.end	= IRQ_SYSMMU_MDMA0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[2] = {
-		.start	= S5PV310_PA_SYSMMU_SSS,
-		.end	= S5PV310_PA_SYSMMU_SSS + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[3] = {
-		.start	= IRQ_SYSMMU_SSS_0,
-		.end	= IRQ_SYSMMU_SSS_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[4] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC0,
-		.end	= S5PV310_PA_SYSMMU_FIMC0 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[5] = {
-		.start	= IRQ_SYSMMU_FIMC0_0,
-		.end	= IRQ_SYSMMU_FIMC0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[6] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC1,
-		.end	= S5PV310_PA_SYSMMU_FIMC1 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[7] = {
-		.start	= IRQ_SYSMMU_FIMC1_0,
-		.end	= IRQ_SYSMMU_FIMC1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[8] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC2,
-		.end	= S5PV310_PA_SYSMMU_FIMC2 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[9] = {
-		.start	= IRQ_SYSMMU_FIMC2_0,
-		.end	= IRQ_SYSMMU_FIMC2_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[10] = {
-		.start	= S5PV310_PA_SYSMMU_FIMC3,
-		.end	= S5PV310_PA_SYSMMU_FIMC3 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[11] = {
-		.start	= IRQ_SYSMMU_FIMC3_0,
-		.end	= IRQ_SYSMMU_FIMC3_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[12] = {
-		.start	= S5PV310_PA_SYSMMU_JPEG,
-		.end	= S5PV310_PA_SYSMMU_JPEG + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[13] = {
-		.start	= IRQ_SYSMMU_JPEG_0,
-		.end	= IRQ_SYSMMU_JPEG_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[14] = {
-		.start	= S5PV310_PA_SYSMMU_FIMD0,
-		.end	= S5PV310_PA_SYSMMU_FIMD0 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[15] = {
-		.start	= IRQ_SYSMMU_LCD0_M0_0,
-		.end	= IRQ_SYSMMU_LCD0_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[16] = {
-		.start	= S5PV310_PA_SYSMMU_FIMD1,
-		.end	= S5PV310_PA_SYSMMU_FIMD1 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[17] = {
-		.start	= IRQ_SYSMMU_LCD1_M1_0,
-		.end	= IRQ_SYSMMU_LCD1_M1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[18] = {
-		.start	= S5PV310_PA_SYSMMU_PCIe,
-		.end	= S5PV310_PA_SYSMMU_PCIe + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[19] = {
-		.start	= IRQ_SYSMMU_PCIE_0,
-		.end	= IRQ_SYSMMU_PCIE_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[20] = {
-		.start	= S5PV310_PA_SYSMMU_G2D,
-		.end	= S5PV310_PA_SYSMMU_G2D + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[21] = {
-		.start	= IRQ_SYSMMU_2D_0,
-		.end	= IRQ_SYSMMU_2D_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[22] = {
-		.start	= S5PV310_PA_SYSMMU_ROTATOR,
-		.end	= S5PV310_PA_SYSMMU_ROTATOR + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[23] = {
-		.start	= IRQ_SYSMMU_ROTATOR_0,
-		.end	= IRQ_SYSMMU_ROTATOR_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[24] = {
-		.start	= S5PV310_PA_SYSMMU_MDMA2,
-		.end	= S5PV310_PA_SYSMMU_MDMA2 + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[25] = {
-		.start	= IRQ_SYSMMU_MDMA1_0,
-		.end	= IRQ_SYSMMU_MDMA1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[26] = {
-		.start	= S5PV310_PA_SYSMMU_TV,
-		.end	= S5PV310_PA_SYSMMU_TV + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[27] = {
-		.start	= IRQ_SYSMMU_TV_M0_0,
-		.end	= IRQ_SYSMMU_TV_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[28] = {
-		.start	= S5PV310_PA_SYSMMU_MFC_L,
-		.end	= S5PV310_PA_SYSMMU_MFC_L + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[29] = {
-		.start	= IRQ_SYSMMU_MFC_M0_0,
-		.end	= IRQ_SYSMMU_MFC_M0_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-	[30] = {
-		.start	= S5PV310_PA_SYSMMU_MFC_R,
-		.end	= S5PV310_PA_SYSMMU_MFC_R + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[31] = {
-		.start	= IRQ_SYSMMU_MFC_M1_0,
-		.end	= IRQ_SYSMMU_MFC_M1_0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-struct platform_device s5pv310_device_sysmmu = {
-	.name		= "s5p-sysmmu",
-	.id		= 32,
-	.num_resources	= ARRAY_SIZE(s5pv310_sysmmu_resource),
-	.resource	= s5pv310_sysmmu_resource,
-};
-
-EXPORT_SYMBOL(s5pv310_device_sysmmu);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dma.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,168 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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/platform_device.h>
-#include <linux/dma-mapping.h>
-
-#include <plat/devs.h>
-#include <plat/irqs.h>
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#include <plat/s3c-pl330-pdata.h>
-
-static u64 dma_dmamask = DMA_BIT_MASK(32);
-
-static struct resource s5pv310_pdma0_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PDMA0,
-		.end	= S5PV310_PA_PDMA0 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA0,
-		.end	= IRQ_PDMA0,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata s5pv310_pdma0_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM2_RX,
-		[3] = DMACH_PCM2_TX,
-		[4] = DMACH_MSM_REQ0,
-		[5] = DMACH_MSM_REQ2,
-		[6] = DMACH_SPI0_RX,
-		[7] = DMACH_SPI0_TX,
-		[8] = DMACH_SPI2_RX,
-		[9] = DMACH_SPI2_TX,
-		[10] = DMACH_I2S0S_TX,
-		[11] = DMACH_I2S0_RX,
-		[12] = DMACH_I2S0_TX,
-		[13] = DMACH_I2S2_RX,
-		[14] = DMACH_I2S2_TX,
-		[15] = DMACH_UART0_RX,
-		[16] = DMACH_UART0_TX,
-		[17] = DMACH_UART2_RX,
-		[18] = DMACH_UART2_TX,
-		[19] = DMACH_UART4_RX,
-		[20] = DMACH_UART4_TX,
-		[21] = DMACH_SLIMBUS0_RX,
-		[22] = DMACH_SLIMBUS0_TX,
-		[23] = DMACH_SLIMBUS2_RX,
-		[24] = DMACH_SLIMBUS2_TX,
-		[25] = DMACH_SLIMBUS4_RX,
-		[26] = DMACH_SLIMBUS4_TX,
-		[27] = DMACH_AC97_MICIN,
-		[28] = DMACH_AC97_PCMIN,
-		[29] = DMACH_AC97_PCMOUT,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device s5pv310_device_pdma0 = {
-	.name		= "s3c-pl330",
-	.id		= 0,
-	.num_resources	= ARRAY_SIZE(s5pv310_pdma0_resource),
-	.resource	= s5pv310_pdma0_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &s5pv310_pdma0_pdata,
-	},
-};
-
-static struct resource s5pv310_pdma1_resource[] = {
-	[0] = {
-		.start	= S5PV310_PA_PDMA1,
-		.end	= S5PV310_PA_PDMA1 + SZ_4K,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_PDMA1,
-		.end	= IRQ_PDMA1,
-		.flags	= IORESOURCE_IRQ,
-	},
-};
-
-static struct s3c_pl330_platdata s5pv310_pdma1_pdata = {
-	.peri = {
-		[0] = DMACH_PCM0_RX,
-		[1] = DMACH_PCM0_TX,
-		[2] = DMACH_PCM1_RX,
-		[3] = DMACH_PCM1_TX,
-		[4] = DMACH_MSM_REQ1,
-		[5] = DMACH_MSM_REQ3,
-		[6] = DMACH_SPI1_RX,
-		[7] = DMACH_SPI1_TX,
-		[8] = DMACH_I2S0S_TX,
-		[9] = DMACH_I2S0_RX,
-		[10] = DMACH_I2S0_TX,
-		[11] = DMACH_I2S1_RX,
-		[12] = DMACH_I2S1_TX,
-		[13] = DMACH_UART0_RX,
-		[14] = DMACH_UART0_TX,
-		[15] = DMACH_UART1_RX,
-		[16] = DMACH_UART1_TX,
-		[17] = DMACH_UART3_RX,
-		[18] = DMACH_UART3_TX,
-		[19] = DMACH_SLIMBUS1_RX,
-		[20] = DMACH_SLIMBUS1_TX,
-		[21] = DMACH_SLIMBUS3_RX,
-		[22] = DMACH_SLIMBUS3_TX,
-		[23] = DMACH_SLIMBUS5_RX,
-		[24] = DMACH_SLIMBUS5_TX,
-		[25] = DMACH_SLIMBUS0AUX_RX,
-		[26] = DMACH_SLIMBUS0AUX_TX,
-		[27] = DMACH_SPDIF,
-		[28] = DMACH_MAX,
-		[29] = DMACH_MAX,
-		[30] = DMACH_MAX,
-		[31] = DMACH_MAX,
-	},
-};
-
-static struct platform_device s5pv310_device_pdma1 = {
-	.name		= "s3c-pl330",
-	.id		= 1,
-	.num_resources	= ARRAY_SIZE(s5pv310_pdma1_resource),
-	.resource	= s5pv310_pdma1_resource,
-	.dev		= {
-		.dma_mask = &dma_dmamask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
-		.platform_data = &s5pv310_pdma1_pdata,
-	},
-};
-
-static struct platform_device *s5pv310_dmacs[] __initdata = {
-	&s5pv310_device_pdma0,
-	&s5pv310_device_pdma1,
-};
-
-static int __init s5pv310_dma_init(void)
-{
-	platform_add_devices(s5pv310_dmacs, ARRAY_SIZE(s5pv310_dmacs));
-
-	return 0;
-}
-arch_initcall(s5pv310_dma_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/gpiolib.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/gpiolib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/gpiolib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,304 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/gpiolib.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - GPIOlib 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/irq.h>
-#include <linux/io.h>
-#include <linux/gpio.h>
-
-#include <mach/map.h>
-
-#include <plat/gpio-core.h>
-#include <plat/gpio-cfg.h>
-#include <plat/gpio-cfg-helpers.h>
-
-static struct s3c_gpio_cfg gpio_cfg = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-static struct s3c_gpio_cfg gpio_cfg_noint = {
-	.set_config	= s3c_gpio_setcfg_s3c64xx_4bit,
-	.set_pull	= s3c_gpio_setpull_updown,
-	.get_pull	= s3c_gpio_getpull_updown,
-};
-
-/*
- * Following are the gpio banks in v310.
- *
- * The 'config' member when left to NULL, is initialized to the default
- * structure gpio_cfg in the init function below.
- *
- * The 'base' member is also initialized in the init function below.
- * Note: The initialization of 'base' member of s3c_gpio_chip structure
- * uses the above macro and depends on the banks being listed in order here.
- */
-static struct s3c_gpio_chip s5pv310_gpio_part1_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV310_GPA0(0),
-			.ngpio	= S5PV310_GPIO_A0_NR,
-			.label	= "GPA0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPA1(0),
-			.ngpio	= S5PV310_GPIO_A1_NR,
-			.label	= "GPA1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPB(0),
-			.ngpio	= S5PV310_GPIO_B_NR,
-			.label	= "GPB",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPC0(0),
-			.ngpio	= S5PV310_GPIO_C0_NR,
-			.label	= "GPC0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPC1(0),
-			.ngpio	= S5PV310_GPIO_C1_NR,
-			.label	= "GPC1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPD0(0),
-			.ngpio	= S5PV310_GPIO_D0_NR,
-			.label	= "GPD0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPD1(0),
-			.ngpio	= S5PV310_GPIO_D1_NR,
-			.label	= "GPD1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE0(0),
-			.ngpio	= S5PV310_GPIO_E0_NR,
-			.label	= "GPE0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE1(0),
-			.ngpio	= S5PV310_GPIO_E1_NR,
-			.label	= "GPE1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE2(0),
-			.ngpio	= S5PV310_GPIO_E2_NR,
-			.label	= "GPE2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE3(0),
-			.ngpio	= S5PV310_GPIO_E3_NR,
-			.label	= "GPE3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPE4(0),
-			.ngpio	= S5PV310_GPIO_E4_NR,
-			.label	= "GPE4",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF0(0),
-			.ngpio	= S5PV310_GPIO_F0_NR,
-			.label	= "GPF0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF1(0),
-			.ngpio	= S5PV310_GPIO_F1_NR,
-			.label	= "GPF1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF2(0),
-			.ngpio	= S5PV310_GPIO_F2_NR,
-			.label	= "GPF2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPF3(0),
-			.ngpio	= S5PV310_GPIO_F3_NR,
-			.label	= "GPF3",
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5pv310_gpio_part2_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV310_GPJ0(0),
-			.ngpio	= S5PV310_GPIO_J0_NR,
-			.label	= "GPJ0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPJ1(0),
-			.ngpio	= S5PV310_GPIO_J1_NR,
-			.label	= "GPJ1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK0(0),
-			.ngpio	= S5PV310_GPIO_K0_NR,
-			.label	= "GPK0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK1(0),
-			.ngpio	= S5PV310_GPIO_K1_NR,
-			.label	= "GPK1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK2(0),
-			.ngpio	= S5PV310_GPIO_K2_NR,
-			.label	= "GPK2",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPK3(0),
-			.ngpio	= S5PV310_GPIO_K3_NR,
-			.label	= "GPK3",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPL0(0),
-			.ngpio	= S5PV310_GPIO_L0_NR,
-			.label	= "GPL0",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPL1(0),
-			.ngpio	= S5PV310_GPIO_L1_NR,
-			.label	= "GPL1",
-		},
-	}, {
-		.chip	= {
-			.base	= S5PV310_GPL2(0),
-			.ngpio	= S5PV310_GPIO_L2_NR,
-			.label	= "GPL2",
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC00),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(0),
-		.chip	= {
-			.base	= S5PV310_GPX0(0),
-			.ngpio	= S5PV310_GPIO_X0_NR,
-			.label	= "GPX0",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC20),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(8),
-		.chip	= {
-			.base	= S5PV310_GPX1(0),
-			.ngpio	= S5PV310_GPIO_X1_NR,
-			.label	= "GPX1",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC40),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(16),
-		.chip	= {
-			.base	= S5PV310_GPX2(0),
-			.ngpio	= S5PV310_GPIO_X2_NR,
-			.label	= "GPX2",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	}, {
-		.base	= (S5P_VA_GPIO2 + 0xC60),
-		.config	= &gpio_cfg_noint,
-		.irq_base = IRQ_EINT(24),
-		.chip	= {
-			.base	= S5PV310_GPX3(0),
-			.ngpio	= S5PV310_GPIO_X3_NR,
-			.label	= "GPX3",
-			.to_irq	= samsung_gpiolib_to_irq,
-		},
-	},
-};
-
-static struct s3c_gpio_chip s5pv310_gpio_part3_4bit[] = {
-	{
-		.chip	= {
-			.base	= S5PV310_GPZ(0),
-			.ngpio	= S5PV310_GPIO_Z_NR,
-			.label	= "GPZ",
-		},
-	},
-};
-
-static __init int s5pv310_gpiolib_init(void)
-{
-	struct s3c_gpio_chip *chip;
-	int i;
-	int nr_chips;
-
-	/* GPIO part 1 */
-
-	chip = s5pv310_gpio_part1_4bit;
-	nr_chips = ARRAY_SIZE(s5pv310_gpio_part1_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
-			chip->config = &gpio_cfg;
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO1 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part1_4bit, nr_chips);
-
-	/* GPIO part 2 */
-
-	chip = s5pv310_gpio_part2_4bit;
-	nr_chips = ARRAY_SIZE(s5pv310_gpio_part2_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
-			chip->config = &gpio_cfg;
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO2 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part2_4bit, nr_chips);
-
-	/* GPIO part 3 */
-
-	chip = s5pv310_gpio_part3_4bit;
-	nr_chips = ARRAY_SIZE(s5pv310_gpio_part3_4bit);
-
-	for (i = 0; i < nr_chips; i++, chip++) {
-		if (chip->config == NULL)
-			chip->config = &gpio_cfg;
-		if (chip->base == NULL)
-			chip->base = S5P_VA_GPIO3 + (i) * 0x20;
-	}
-
-	samsung_gpiolib_add_4bit_chips(s5pv310_gpio_part3_4bit, nr_chips);
-
-	return 0;
-}
-core_initcall(s5pv310_gpiolib_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/headsmp.S linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/headsmp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/headsmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/*
- *  linux/arch/arm/mach-s5pv310/headsmp.S
- *
- *  Cloned from linux/arch/arm/mach-realview/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  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/linkage.h>
-#include <linux/init.h>
-
-	__INIT
-
-/*
- * s5pv310 specific entry point for secondary CPUs.  This provides
- * a "holding pen" into which all secondary cores are held until we're
- * ready for them to initialise.
- */
-ENTRY(s5pv310_secondary_startup)
-	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	add	r6, r6, r4
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-1:	.long	.
-	.long	pen_release
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/hotplug.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/hotplug.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/hotplug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/hotplug.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,130 +0,0 @@
-/* linux arch/arm/mach-s5pv310/hotplug.c
- *
- *  Cloned from linux/arch/arm/mach-realview/hotplug.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/kernel.h>
-#include <linux/errno.h>
-#include <linux/smp.h>
-
-#include <asm/cacheflush.h>
-
-extern volatile int pen_release;
-
-static inline void cpu_enter_lowpower(void)
-{
-	unsigned int v;
-
-	flush_cache_all();
-	asm volatile(
-	"	mcr	p15, 0, %1, c7, c5, 0\n"
-	"	mcr	p15, 0, %1, c7, c10, 4\n"
-	/*
-	 * Turn off coherency
-	 */
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	bic	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	"	mrc	p15, 0, %0, c1, c0, 0\n"
-	"	bic	%0, %0, %2\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	  : "=&r" (v)
-	  : "r" (0), "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void cpu_leave_lowpower(void)
-{
-	unsigned int v;
-
-	asm volatile(
-	"mrc	p15, 0, %0, c1, c0, 0\n"
-	"	orr	%0, %0, %1\n"
-	"	mcr	p15, 0, %0, c1, c0, 0\n"
-	"	mrc	p15, 0, %0, c1, c0, 1\n"
-	"	orr	%0, %0, #0x20\n"
-	"	mcr	p15, 0, %0, c1, c0, 1\n"
-	  : "=&r" (v)
-	  : "Ir" (CR_C)
-	  : "cc");
-}
-
-static inline void platform_do_lowpower(unsigned int cpu, int *spurious)
-{
-	/*
-	 * there is no power-control hardware on this platform, so all
-	 * we can do is put the core into WFI; this is safe as the calling
-	 * code will have already disabled interrupts
-	 */
-	for (;;) {
-		/*
-		 * here's the WFI
-		 */
-		asm(".word	0xe320f003\n"
-		    :
-		    :
-		    : "memory", "cc");
-
-		if (pen_release == cpu) {
-			/*
-			 * OK, proper wakeup, we're done
-			 */
-			break;
-		}
-
-		/*
-		 * Getting here, means that we have come out of WFI without
-		 * having been woken up - this shouldn't happen
-		 *
-		 * Just note it happening - when we're woken, we can report
-		 * its occurrence.
-		 */
-		(*spurious)++;
-	}
-}
-
-int platform_cpu_kill(unsigned int cpu)
-{
-	return 1;
-}
-
-/*
- * platform-specific code to shutdown a CPU
- *
- * Called with IRQs disabled
- */
-void platform_cpu_die(unsigned int cpu)
-{
-	int spurious = 0;
-
-	/*
-	 * we're ready for shutdown now, so do it
-	 */
-	cpu_enter_lowpower();
-	platform_do_lowpower(cpu, &spurious);
-
-	/*
-	 * bring this CPU back into the world of cache
-	 * coherency, and then restore interrupts
-	 */
-	cpu_leave_lowpower();
-
-	if (spurious)
-		pr_warn("CPU%u: %u spurious wakeup calls\n", cpu, spurious);
-}
-
-int platform_cpu_disable(unsigned int cpu)
-{
-	/*
-	 * we don't allow CPU 0 to be shutdown (it is still too special
-	 * e.g. clock tick interrupts)
-	 */
-	return cpu == 0 ? -EPERM : 0;
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/debug-macro.S
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/mach-s3c6400/include/mach/debug-macro.S
- *
- * 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.
-*/
-
-/* pull in the relevant register and map files. */
-
-#include <mach/map.h>
-
-	/* note, for the boot process to work we have to keep the UART
-	 * virtual address aligned to an 1MiB boundary for the L1
-	 * mapping the head code makes. We keep the UART virtual address
-	 * aligned and add in the offset when we load the value here.
-	 */
-
-	.macro addruart, rp, rv
-		ldreq	\rp, = S3C_PA_UART
-		ldrne	\rv, = S3C_VA_UART
-#if CONFIG_DEBUG_S3C_UART != 0
-		add	\rp, \rp, #(0x10000 * CONFIG_DEBUG_S3C_UART)
-		add	\rv, \rv, #(0x10000 * CONFIG_DEBUG_S3C_UART)
-#endif
-	.endm
-
-#define fifo_full fifo_full_s5pv210
-#define fifo_level fifo_level_s5pv210
-
-#include <plat/debug-macro.S>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/dma.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics Co. Ltd.
- *	Jaswinder Singh <jassi.brar@samsung.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 __MACH_DMA_H
-#define __MACH_DMA_H
-
-/* This platform uses the common S3C DMA API driver for PL330 */
-#include <plat/s3c-dma-pl330.h>
-
-#endif /* __MACH_DMA_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-/* arch/arm/mach-s5pv310/include/mach/entry-macro.S
- *
- * Cloned from arch/arm/mach-realview/include/mach/entry-macro.S
- *
- * Low-level IRQ helper macros for S5PV310 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>
-#include <asm/hardware/gic.h>
-
-		.macro	disable_fiq
-		.endm
-
-		.macro  get_irqnr_preamble, base, tmp
-		ldr	\base, =gic_cpu_base_addr
-		ldr	\base, [\base]
-		.endm
-
-		.macro  arch_ret_to_user, tmp1, tmp2
-		.endm
-
-		/*
-		 * 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     \irqstat, [\base, #GIC_CPU_INTACK] /* bits 12-10 = src CPU, 9-0 = int # */
-
-		ldr	\tmp, =1021
-
-		bic     \irqnr, \irqstat, #0x1c00
-
-		cmp     \irqnr, #29
-		cmpcc	\irqnr, \irqnr
-		cmpne	\irqnr, \tmp
-		cmpcs	\irqnr, \irqnr
-		addne	\irqnr, \irqnr, #32
-
-		.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
-		strcc	\irqstat, [\base, #GIC_CPU_EOI]
-		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
-		moveq	\tmp, #1
-		streq	\irqstat, [\base, #GIC_CPU_EOI]
-		cmp	\tmp, #0
-		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,135 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - GPIO lib 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.
-*/
-
-#ifndef __ASM_ARCH_GPIO_H
-#define __ASM_ARCH_GPIO_H __FILE__
-
-#define gpio_get_value	__gpio_get_value
-#define gpio_set_value	__gpio_set_value
-#define gpio_cansleep	__gpio_cansleep
-#define gpio_to_irq	__gpio_to_irq
-
-/* Practically, GPIO banks upto GPZ are the configurable gpio banks */
-
-/* GPIO bank sizes */
-#define S5PV310_GPIO_A0_NR	(8)
-#define S5PV310_GPIO_A1_NR	(6)
-#define S5PV310_GPIO_B_NR	(8)
-#define S5PV310_GPIO_C0_NR	(5)
-#define S5PV310_GPIO_C1_NR	(5)
-#define S5PV310_GPIO_D0_NR	(4)
-#define S5PV310_GPIO_D1_NR	(4)
-#define S5PV310_GPIO_E0_NR	(5)
-#define S5PV310_GPIO_E1_NR	(8)
-#define S5PV310_GPIO_E2_NR	(6)
-#define S5PV310_GPIO_E3_NR	(8)
-#define S5PV310_GPIO_E4_NR	(8)
-#define S5PV310_GPIO_F0_NR	(8)
-#define S5PV310_GPIO_F1_NR	(8)
-#define S5PV310_GPIO_F2_NR	(8)
-#define S5PV310_GPIO_F3_NR	(6)
-#define S5PV310_GPIO_J0_NR	(8)
-#define S5PV310_GPIO_J1_NR	(5)
-#define S5PV310_GPIO_K0_NR	(7)
-#define S5PV310_GPIO_K1_NR	(7)
-#define S5PV310_GPIO_K2_NR	(7)
-#define S5PV310_GPIO_K3_NR	(7)
-#define S5PV310_GPIO_L0_NR	(8)
-#define S5PV310_GPIO_L1_NR	(3)
-#define S5PV310_GPIO_L2_NR	(8)
-#define S5PV310_GPIO_X0_NR	(8)
-#define S5PV310_GPIO_X1_NR	(8)
-#define S5PV310_GPIO_X2_NR	(8)
-#define S5PV310_GPIO_X3_NR	(8)
-#define S5PV310_GPIO_Z_NR	(7)
-
-/* GPIO bank numbers */
-
-#define S5PV310_GPIO_NEXT(__gpio) \
-	((__gpio##_START) + (__gpio##_NR) + CONFIG_S3C_GPIO_SPACE + 1)
-
-enum s5p_gpio_number {
-	S5PV310_GPIO_A0_START	= 0,
-	S5PV310_GPIO_A1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A0),
-	S5PV310_GPIO_B_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_A1),
-	S5PV310_GPIO_C0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_B),
-	S5PV310_GPIO_C1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C0),
-	S5PV310_GPIO_D0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_C1),
-	S5PV310_GPIO_D1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D0),
-	S5PV310_GPIO_E0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_D1),
-	S5PV310_GPIO_E1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E0),
-	S5PV310_GPIO_E2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E1),
-	S5PV310_GPIO_E3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E2),
-	S5PV310_GPIO_E4_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E3),
-	S5PV310_GPIO_F0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_E4),
-	S5PV310_GPIO_F1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F0),
-	S5PV310_GPIO_F2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F1),
-	S5PV310_GPIO_F3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F2),
-	S5PV310_GPIO_J0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_F3),
-	S5PV310_GPIO_J1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J0),
-	S5PV310_GPIO_K0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_J1),
-	S5PV310_GPIO_K1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K0),
-	S5PV310_GPIO_K2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K1),
-	S5PV310_GPIO_K3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K2),
-	S5PV310_GPIO_L0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_K3),
-	S5PV310_GPIO_L1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L0),
-	S5PV310_GPIO_L2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L1),
-	S5PV310_GPIO_X0_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_L2),
-	S5PV310_GPIO_X1_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X0),
-	S5PV310_GPIO_X2_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X1),
-	S5PV310_GPIO_X3_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X2),
-	S5PV310_GPIO_Z_START	= S5PV310_GPIO_NEXT(S5PV310_GPIO_X3),
-};
-
-/* S5PV310 GPIO number definitions */
-#define S5PV310_GPA0(_nr)	(S5PV310_GPIO_A0_START + (_nr))
-#define S5PV310_GPA1(_nr)	(S5PV310_GPIO_A1_START + (_nr))
-#define S5PV310_GPB(_nr)	(S5PV310_GPIO_B_START + (_nr))
-#define S5PV310_GPC0(_nr)	(S5PV310_GPIO_C0_START + (_nr))
-#define S5PV310_GPC1(_nr)	(S5PV310_GPIO_C1_START + (_nr))
-#define S5PV310_GPD0(_nr)	(S5PV310_GPIO_D0_START + (_nr))
-#define S5PV310_GPD1(_nr)	(S5PV310_GPIO_D1_START + (_nr))
-#define S5PV310_GPE0(_nr)	(S5PV310_GPIO_E0_START + (_nr))
-#define S5PV310_GPE1(_nr)	(S5PV310_GPIO_E1_START + (_nr))
-#define S5PV310_GPE2(_nr)	(S5PV310_GPIO_E2_START + (_nr))
-#define S5PV310_GPE3(_nr)	(S5PV310_GPIO_E3_START + (_nr))
-#define S5PV310_GPE4(_nr)	(S5PV310_GPIO_E4_START + (_nr))
-#define S5PV310_GPF0(_nr)	(S5PV310_GPIO_F0_START + (_nr))
-#define S5PV310_GPF1(_nr)	(S5PV310_GPIO_F1_START + (_nr))
-#define S5PV310_GPF2(_nr)	(S5PV310_GPIO_F2_START + (_nr))
-#define S5PV310_GPF3(_nr)	(S5PV310_GPIO_F3_START + (_nr))
-#define S5PV310_GPJ0(_nr)	(S5PV310_GPIO_J0_START + (_nr))
-#define S5PV310_GPJ1(_nr)	(S5PV310_GPIO_J1_START + (_nr))
-#define S5PV310_GPK0(_nr)	(S5PV310_GPIO_K0_START + (_nr))
-#define S5PV310_GPK1(_nr)	(S5PV310_GPIO_K1_START + (_nr))
-#define S5PV310_GPK2(_nr)	(S5PV310_GPIO_K2_START + (_nr))
-#define S5PV310_GPK3(_nr)	(S5PV310_GPIO_K3_START + (_nr))
-#define S5PV310_GPL0(_nr)	(S5PV310_GPIO_L0_START + (_nr))
-#define S5PV310_GPL1(_nr)	(S5PV310_GPIO_L1_START + (_nr))
-#define S5PV310_GPL2(_nr)	(S5PV310_GPIO_L2_START + (_nr))
-#define S5PV310_GPX0(_nr)	(S5PV310_GPIO_X0_START + (_nr))
-#define S5PV310_GPX1(_nr)	(S5PV310_GPIO_X1_START + (_nr))
-#define S5PV310_GPX2(_nr)	(S5PV310_GPIO_X2_START + (_nr))
-#define S5PV310_GPX3(_nr)	(S5PV310_GPIO_X3_START + (_nr))
-#define S5PV310_GPZ(_nr)	(S5PV310_GPIO_Z_START + (_nr))
-
-/* the end of the S5PV310 specific gpios */
-#define S5PV310_GPIO_END	(S5PV310_GPZ(S5PV310_GPIO_Z_NR) + 1)
-#define S3C_GPIO_END		S5PV310_GPIO_END
-
-/* define the number of gpios we need to the one after the GPZ() range */
-#define ARCH_NR_GPIOS		(S5PV310_GPZ(S5PV310_GPIO_Z_NR) +	\
-				 CONFIG_SAMSUNG_GPIO_EXTRA + 1)
-
-#include <asm-generic/gpio.h>
-
-#endif /* __ASM_ARCH_GPIO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/hardware.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Hardware 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.
-*/
-
-#ifndef __ASM_ARCH_HARDWARE_H
-#define __ASM_ARCH_HARDWARE_H __FILE__
-
-/* currently nothing here, placeholder */
-
-#endif /* __ASM_ARCH_HARDWARE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/io.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2008-2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/io.h
- *
- * Default IO routines for S5PV310
- *
- * 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_ARCH_IO_H
-#define __ASM_ARM_ARCH_IO_H __FILE__
-
-/* No current ISA/PCI bus support. */
-#define __io(a)		__typesafe_io(a)
-#define __mem_pci(a)	(a)
-
-#define IO_SPACE_LIMIT (0xFFFFFFFF)
-
-#endif /* __ASM_ARM_ARCH_IO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,146 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/irqs.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - IRQ 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.
-*/
-
-#ifndef __ASM_ARCH_IRQS_H
-#define __ASM_ARCH_IRQS_H __FILE__
-
-#include <plat/irqs.h>
-
-/* PPI: Private Peripheral Interrupt */
-
-#define IRQ_PPI(x)		S5P_IRQ(x+16)
-
-#define IRQ_LOCALTIMER		IRQ_PPI(13)
-
-/* SPI: Shared Peripheral Interrupt */
-
-#define IRQ_SPI(x)		S5P_IRQ(x+32)
-
-#define IRQ_MCT1		IRQ_SPI(35)
-
-#define IRQ_EINT0		IRQ_SPI(40)
-#define IRQ_EINT1		IRQ_SPI(41)
-#define IRQ_EINT2		IRQ_SPI(42)
-#define IRQ_EINT3		IRQ_SPI(43)
-#define IRQ_USB_HSOTG		IRQ_SPI(44)
-#define IRQ_USB_HOST		IRQ_SPI(45)
-#define IRQ_MODEM_IF		IRQ_SPI(46)
-#define IRQ_ROTATOR		IRQ_SPI(47)
-#define IRQ_JPEG		IRQ_SPI(48)
-#define IRQ_2D			IRQ_SPI(49)
-#define IRQ_PCIE		IRQ_SPI(50)
-#define IRQ_MCT0		IRQ_SPI(51)
-#define IRQ_MFC			IRQ_SPI(52)
-#define IRQ_AUDIO_SS		IRQ_SPI(54)
-#define IRQ_AC97		IRQ_SPI(55)
-#define IRQ_SPDIF		IRQ_SPI(56)
-#define IRQ_KEYPAD		IRQ_SPI(57)
-#define IRQ_INTFEEDCTRL_SSS	IRQ_SPI(58)
-#define IRQ_SLIMBUS		IRQ_SPI(59)
-#define IRQ_PMU			IRQ_SPI(60)
-#define IRQ_TSI			IRQ_SPI(61)
-#define IRQ_SATA		IRQ_SPI(62)
-#define IRQ_GPS			IRQ_SPI(63)
-
-#define MAX_IRQ_IN_COMBINER	8
-#define COMBINER_GROUP(x)	((x) * MAX_IRQ_IN_COMBINER + IRQ_SPI(64))
-#define COMBINER_IRQ(x, y)	(COMBINER_GROUP(x) + y)
-
-#define IRQ_SYSMMU_MDMA0_0	COMBINER_IRQ(4, 0)
-#define IRQ_SYSMMU_SSS_0	COMBINER_IRQ(4, 1)
-#define IRQ_SYSMMU_FIMC0_0	COMBINER_IRQ(4, 2)
-#define IRQ_SYSMMU_FIMC1_0	COMBINER_IRQ(4, 3)
-#define IRQ_SYSMMU_FIMC2_0	COMBINER_IRQ(4, 4)
-#define IRQ_SYSMMU_FIMC3_0	COMBINER_IRQ(4, 5)
-#define IRQ_SYSMMU_JPEG_0	COMBINER_IRQ(4, 6)
-#define IRQ_SYSMMU_2D_0		COMBINER_IRQ(4, 7)
-
-#define IRQ_SYSMMU_ROTATOR_0	COMBINER_IRQ(5, 0)
-#define IRQ_SYSMMU_MDMA1_0	COMBINER_IRQ(5, 1)
-#define IRQ_SYSMMU_LCD0_M0_0	COMBINER_IRQ(5, 2)
-#define IRQ_SYSMMU_LCD1_M1_0	COMBINER_IRQ(5, 3)
-#define IRQ_SYSMMU_TV_M0_0	COMBINER_IRQ(5, 4)
-#define IRQ_SYSMMU_MFC_M0_0	COMBINER_IRQ(5, 5)
-#define IRQ_SYSMMU_MFC_M1_0	COMBINER_IRQ(5, 6)
-#define IRQ_SYSMMU_PCIE_0	COMBINER_IRQ(5, 7)
-
-#define IRQ_PDMA0		COMBINER_IRQ(21, 0)
-#define IRQ_PDMA1		COMBINER_IRQ(21, 1)
-
-#define IRQ_TIMER0_VIC		COMBINER_IRQ(22, 0)
-#define IRQ_TIMER1_VIC		COMBINER_IRQ(22, 1)
-#define IRQ_TIMER2_VIC		COMBINER_IRQ(22, 2)
-#define IRQ_TIMER3_VIC		COMBINER_IRQ(22, 3)
-#define IRQ_TIMER4_VIC		COMBINER_IRQ(22, 4)
-
-#define IRQ_RTC_ALARM		COMBINER_IRQ(23, 0)
-#define IRQ_RTC_TIC		COMBINER_IRQ(23, 1)
-
-#define IRQ_UART0		COMBINER_IRQ(26, 0)
-#define IRQ_UART1		COMBINER_IRQ(26, 1)
-#define IRQ_UART2		COMBINER_IRQ(26, 2)
-#define IRQ_UART3		COMBINER_IRQ(26, 3)
-#define IRQ_UART4		COMBINER_IRQ(26, 4)
-
-#define IRQ_IIC			COMBINER_IRQ(27, 0)
-#define IRQ_IIC1		COMBINER_IRQ(27, 1)
-#define IRQ_IIC2		COMBINER_IRQ(27, 2)
-#define IRQ_IIC3		COMBINER_IRQ(27, 3)
-#define IRQ_IIC4		COMBINER_IRQ(27, 4)
-#define IRQ_IIC5		COMBINER_IRQ(27, 5)
-#define IRQ_IIC6		COMBINER_IRQ(27, 6)
-#define IRQ_IIC7		COMBINER_IRQ(27, 7)
-
-#define IRQ_HSMMC0		COMBINER_IRQ(29, 0)
-#define IRQ_HSMMC1		COMBINER_IRQ(29, 1)
-#define IRQ_HSMMC2		COMBINER_IRQ(29, 2)
-#define IRQ_HSMMC3		COMBINER_IRQ(29, 3)
-
-#define IRQ_MIPI_CSIS0		COMBINER_IRQ(30, 0)
-#define IRQ_MIPI_CSIS1		COMBINER_IRQ(30, 1)
-
-#define IRQ_ONENAND_AUDI	COMBINER_IRQ(34, 0)
-
-#define IRQ_MCT_L1		COMBINER_IRQ(35, 3)
-
-#define IRQ_EINT4		COMBINER_IRQ(37, 0)
-#define IRQ_EINT5		COMBINER_IRQ(37, 1)
-#define IRQ_EINT6		COMBINER_IRQ(37, 2)
-#define IRQ_EINT7		COMBINER_IRQ(37, 3)
-#define IRQ_EINT8		COMBINER_IRQ(38, 0)
-
-#define IRQ_EINT9		COMBINER_IRQ(38, 1)
-#define IRQ_EINT10		COMBINER_IRQ(38, 2)
-#define IRQ_EINT11		COMBINER_IRQ(38, 3)
-#define IRQ_EINT12		COMBINER_IRQ(38, 4)
-#define IRQ_EINT13		COMBINER_IRQ(38, 5)
-#define IRQ_EINT14		COMBINER_IRQ(38, 6)
-#define IRQ_EINT15		COMBINER_IRQ(38, 7)
-
-#define IRQ_EINT16_31		COMBINER_IRQ(39, 0)
-
-#define IRQ_MCT_L0		COMBINER_IRQ(51, 0)
-
-#define IRQ_WDT			COMBINER_IRQ(53, 0)
-
-#define MAX_COMBINER_NR		54
-
-#define S5P_IRQ_EINT_BASE	COMBINER_IRQ(MAX_COMBINER_NR, 0)
-
-#define S5P_EINT_BASE1		(S5P_IRQ_EINT_BASE + 0)
-#define S5P_EINT_BASE2		(S5P_IRQ_EINT_BASE + 16)
-
-/* Set the default NR_IRQS */
-
-#define NR_IRQS			(S5P_IRQ_EINT_BASE + 32)
-
-#endif /* __ASM_ARCH_IRQS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/map.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/map.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/map.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,144 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/map.h
- *
- * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Memory map 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.
-*/
-
-#ifndef __ASM_ARCH_MAP_H
-#define __ASM_ARCH_MAP_H __FILE__
-
-#include <plat/map-base.h>
-
-/*
- * S5PV310 UART offset is 0x10000 but the older S5P SoCs are 0x400.
- * So need to define it, and here is to avoid redefinition warning.
- */
-#define S3C_UART_OFFSET			(0x10000)
-
-#include <plat/map-s5p.h>
-
-#define S5PV310_PA_SYSRAM		0x02025000
-
-#define S5PV310_PA_I2S0			0x03830000
-#define S5PV310_PA_I2S1			0xE3100000
-#define S5PV310_PA_I2S2			0xE2A00000
-
-#define S5PV310_PA_PCM0			0x03840000
-#define S5PV310_PA_PCM1			0x13980000
-#define S5PV310_PA_PCM2			0x13990000
-
-#define S5PV310_PA_SROM_BANK(x)		(0x04000000 + ((x) * 0x01000000))
-
-#define S5PC210_PA_ONENAND		0x0C000000
-#define S5PC210_PA_ONENAND_DMA		0x0C600000
-
-#define S5PV310_PA_CHIPID		0x10000000
-
-#define S5PV310_PA_SYSCON		0x10010000
-#define S5PV310_PA_PMU			0x10020000
-#define S5PV310_PA_CMU			0x10030000
-
-#define S5PV310_PA_WATCHDOG		0x10060000
-#define S5PV310_PA_RTC			0x10070000
-
-#define S5PV310_PA_DMC0			0x10400000
-
-#define S5PV310_PA_COMBINER		0x10448000
-
-#define S5PV310_PA_COREPERI		0x10500000
-#define S5PV310_PA_GIC_CPU		0x10500100
-#define S5PV310_PA_TWD			0x10500600
-#define S5PV310_PA_GIC_DIST		0x10501000
-#define S5PV310_PA_L2CC			0x10502000
-
-#define S5PV310_PA_MDMA			0x10810000
-#define S5PV310_PA_PDMA0		0x12680000
-#define S5PV310_PA_PDMA1		0x12690000
-
-#define S5PV310_PA_SYSMMU_MDMA		0x10A40000
-#define S5PV310_PA_SYSMMU_SSS		0x10A50000
-#define S5PV310_PA_SYSMMU_FIMC0		0x11A20000
-#define S5PV310_PA_SYSMMU_FIMC1		0x11A30000
-#define S5PV310_PA_SYSMMU_FIMC2		0x11A40000
-#define S5PV310_PA_SYSMMU_FIMC3		0x11A50000
-#define S5PV310_PA_SYSMMU_JPEG		0x11A60000
-#define S5PV310_PA_SYSMMU_FIMD0		0x11E20000
-#define S5PV310_PA_SYSMMU_FIMD1		0x12220000
-#define S5PV310_PA_SYSMMU_PCIe		0x12620000
-#define S5PV310_PA_SYSMMU_G2D		0x12A20000
-#define S5PV310_PA_SYSMMU_ROTATOR	0x12A30000
-#define S5PV310_PA_SYSMMU_MDMA2		0x12A40000
-#define S5PV310_PA_SYSMMU_TV		0x12E20000
-#define S5PV310_PA_SYSMMU_MFC_L		0x13620000
-#define S5PV310_PA_SYSMMU_MFC_R		0x13630000
-
-#define S5PV310_PA_GPIO1		0x11400000
-#define S5PV310_PA_GPIO2		0x11000000
-#define S5PV310_PA_GPIO3		0x03860000
-
-#define S5PV310_PA_MIPI_CSIS0		0x11880000
-#define S5PV310_PA_MIPI_CSIS1		0x11890000
-
-#define S5PV310_PA_HSMMC(x)		(0x12510000 + ((x) * 0x10000))
-
-#define S5PV310_PA_SROMC		0x12570000
-
-#define S5PV310_PA_UART			0x13800000
-
-#define S5PV310_PA_IIC(x)		(0x13860000 + ((x) * 0x10000))
-
-#define S5PV310_PA_AC97			0x139A0000
-
-#define S5PV310_PA_TIMER		0x139D0000
-
-#define S5PV310_PA_SDRAM		0x40000000
-
-#define S5PV310_PA_SPDIF		0xE1100000
-
-/* Compatibiltiy Defines */
-
-#define S3C_PA_HSMMC0			S5PV310_PA_HSMMC(0)
-#define S3C_PA_HSMMC1			S5PV310_PA_HSMMC(1)
-#define S3C_PA_HSMMC2			S5PV310_PA_HSMMC(2)
-#define S3C_PA_HSMMC3			S5PV310_PA_HSMMC(3)
-#define S3C_PA_IIC			S5PV310_PA_IIC(0)
-#define S3C_PA_IIC1			S5PV310_PA_IIC(1)
-#define S3C_PA_IIC2			S5PV310_PA_IIC(2)
-#define S3C_PA_IIC3			S5PV310_PA_IIC(3)
-#define S3C_PA_IIC4			S5PV310_PA_IIC(4)
-#define S3C_PA_IIC5			S5PV310_PA_IIC(5)
-#define S3C_PA_IIC6			S5PV310_PA_IIC(6)
-#define S3C_PA_IIC7			S5PV310_PA_IIC(7)
-#define S3C_PA_RTC			S5PV310_PA_RTC
-#define S3C_PA_WDT			S5PV310_PA_WATCHDOG
-
-#define S5P_PA_CHIPID			S5PV310_PA_CHIPID
-#define S5P_PA_MIPI_CSIS0		S5PV310_PA_MIPI_CSIS0
-#define S5P_PA_MIPI_CSIS1		S5PV310_PA_MIPI_CSIS1
-#define S5P_PA_ONENAND			S5PC210_PA_ONENAND
-#define S5P_PA_ONENAND_DMA		S5PC210_PA_ONENAND_DMA
-#define S5P_PA_SDRAM			S5PV310_PA_SDRAM
-#define S5P_PA_SROMC			S5PV310_PA_SROMC
-#define S5P_PA_SYSCON			S5PV310_PA_SYSCON
-#define S5P_PA_TIMER			S5PV310_PA_TIMER
-
-/* UART */
-
-#define S3C_PA_UART			S5PV310_PA_UART
-
-#define S5P_PA_UART(x)			(S3C_PA_UART + ((x) * S3C_UART_OFFSET))
-#define S5P_PA_UART0			S5P_PA_UART(0)
-#define S5P_PA_UART1			S5P_PA_UART(1)
-#define S5P_PA_UART2			S5P_PA_UART(2)
-#define S5P_PA_UART3			S5P_PA_UART(3)
-#define S5P_PA_UART4			S5P_PA_UART(4)
-
-#define S5P_SZ_UART			SZ_256
-
-#endif /* __ASM_ARCH_MAP_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/memory.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Memory 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.
-*/
-
-#ifndef __ASM_ARCH_MEMORY_H
-#define __ASM_ARCH_MEMORY_H __FILE__
-
-#define PHYS_OFFSET		UL(0x40000000)
-
-/* Maximum of 256MiB in one bank */
-#define MAX_PHYSMEM_BITS	32
-#define SECTION_SIZE_BITS	28
-
-#endif /* __ASM_ARCH_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/pwm-clock.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/pwm-clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/pwm-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,70 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/pwm-clock.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *      Ben Dooks <ben@simtec.co.uk>
- *      http://armlinux.simtec.co.uk/
- *
- * Based on arch/arm/mach-s3c64xx/include/mach/pwm-clock.h
- *
- * S5PV310 - pwm clock and timer 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.
-*/
-
-#ifndef __ASM_ARCH_PWMCLK_H
-#define __ASM_ARCH_PWMCLK_H __FILE__
-
-/**
- * pwm_cfg_src_is_tclk() - return whether the given mux config is a tclk
- * @tcfg: The timer TCFG1 register bits shifted down to 0.
- *
- * Return true if the given configuration from TCFG1 is a TCLK instead
- * any of the TDIV clocks.
- */
-static inline int pwm_cfg_src_is_tclk(unsigned long tcfg)
-{
-	return tcfg == S3C64XX_TCFG1_MUX_TCLK;
-}
-
-/**
- * tcfg_to_divisor() - convert tcfg1 setting to a divisor
- * @tcfg1: The tcfg1 setting, shifted down.
- *
- * Get the divisor value for the given tcfg1 setting. We assume the
- * caller has already checked to see if this is not a TCLK source.
- */
-static inline unsigned long tcfg_to_divisor(unsigned long tcfg1)
-{
-	return 1 << tcfg1;
-}
-
-/**
- * pwm_tdiv_has_div1() - does the tdiv setting have a /1
- *
- * Return true if we have a /1 in the tdiv setting.
- */
-static inline unsigned int pwm_tdiv_has_div1(void)
-{
-	return 1;
-}
-
-/**
- * pwm_tdiv_div_bits() - calculate TCFG1 divisor value.
- * @div: The divisor to calculate the bit information for.
- *
- * Turn a divisor into the necessary bit field for TCFG1.
- */
-static inline unsigned long pwm_tdiv_div_bits(unsigned int div)
-{
-	return ilog2(div);
-}
-
-#define S3C_TCFG1_MUX_TCLK S3C64XX_TCFG1_MUX_TCLK
-
-#endif /* __ASM_ARCH_PWMCLK_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-clock.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-clock.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,167 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-clock.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - Clock 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.
-*/
-
-#ifndef __ASM_ARCH_REGS_CLOCK_H
-#define __ASM_ARCH_REGS_CLOCK_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_CLKREG(x)			(S5P_VA_CMU + (x))
-
-#define S5P_INFORM0			S5P_CLKREG(0x800)
-
-#define S5P_CLKDIV_LEFTBUS		S5P_CLKREG(0x04500)
-#define S5P_CLKDIV_STAT_LEFTBUS		S5P_CLKREG(0x04600)
-
-#define S5P_CLKDIV_RIGHTBUS		S5P_CLKREG(0x08500)
-#define S5P_CLKDIV_STAT_RIGHTBUS	S5P_CLKREG(0x08600)
-
-#define S5P_EPLL_CON0			S5P_CLKREG(0x0C110)
-#define S5P_EPLL_CON1			S5P_CLKREG(0x0C114)
-#define S5P_VPLL_CON0			S5P_CLKREG(0x0C120)
-#define S5P_VPLL_CON1			S5P_CLKREG(0x0C124)
-
-#define S5P_CLKSRC_TOP0			S5P_CLKREG(0x0C210)
-#define S5P_CLKSRC_TOP1			S5P_CLKREG(0x0C214)
-#define S5P_CLKSRC_CAM			S5P_CLKREG(0x0C220)
-#define S5P_CLKSRC_IMAGE		S5P_CLKREG(0x0C230)
-#define S5P_CLKSRC_LCD0			S5P_CLKREG(0x0C234)
-#define S5P_CLKSRC_LCD1			S5P_CLKREG(0x0C238)
-#define S5P_CLKSRC_FSYS			S5P_CLKREG(0x0C240)
-#define S5P_CLKSRC_PERIL0		S5P_CLKREG(0x0C250)
-#define S5P_CLKSRC_PERIL1		S5P_CLKREG(0x0C254)
-
-#define S5P_CLKDIV_TOP			S5P_CLKREG(0x0C510)
-#define S5P_CLKDIV_CAM			S5P_CLKREG(0x0C520)
-#define S5P_CLKDIV_IMAGE		S5P_CLKREG(0x0C530)
-#define S5P_CLKDIV_LCD0			S5P_CLKREG(0x0C534)
-#define S5P_CLKDIV_LCD1			S5P_CLKREG(0x0C538)
-#define S5P_CLKDIV_FSYS0		S5P_CLKREG(0x0C540)
-#define S5P_CLKDIV_FSYS1		S5P_CLKREG(0x0C544)
-#define S5P_CLKDIV_FSYS2		S5P_CLKREG(0x0C548)
-#define S5P_CLKDIV_FSYS3		S5P_CLKREG(0x0C54C)
-#define S5P_CLKDIV_PERIL0		S5P_CLKREG(0x0C550)
-#define S5P_CLKDIV_PERIL1		S5P_CLKREG(0x0C554)
-#define S5P_CLKDIV_PERIL2		S5P_CLKREG(0x0C558)
-#define S5P_CLKDIV_PERIL3		S5P_CLKREG(0x0C55C)
-#define S5P_CLKDIV_PERIL4		S5P_CLKREG(0x0C560)
-#define S5P_CLKDIV_PERIL5		S5P_CLKREG(0x0C564)
-
-#define S5P_CLKSRC_MASK_TOP		S5P_CLKREG(0x0C310)
-#define S5P_CLKSRC_MASK_CAM		S5P_CLKREG(0x0C320)
-#define S5P_CLKSRC_MASK_LCD0		S5P_CLKREG(0x0C334)
-#define S5P_CLKSRC_MASK_LCD1		S5P_CLKREG(0x0C338)
-#define S5P_CLKSRC_MASK_FSYS		S5P_CLKREG(0x0C340)
-#define S5P_CLKSRC_MASK_PERIL0		S5P_CLKREG(0x0C350)
-#define S5P_CLKSRC_MASK_PERIL1		S5P_CLKREG(0x0C354)
-
-#define S5P_CLKDIV_STAT_TOP		S5P_CLKREG(0x0C610)
-
-#define S5P_CLKGATE_IP_CAM		S5P_CLKREG(0x0C920)
-#define S5P_CLKGATE_IP_IMAGE		S5P_CLKREG(0x0C930)
-#define S5P_CLKGATE_IP_LCD0		S5P_CLKREG(0x0C934)
-#define S5P_CLKGATE_IP_LCD1		S5P_CLKREG(0x0C938)
-#define S5P_CLKGATE_IP_FSYS		S5P_CLKREG(0x0C940)
-#define S5P_CLKGATE_IP_PERIL		S5P_CLKREG(0x0C950)
-#define S5P_CLKGATE_IP_PERIR		S5P_CLKREG(0x0C960)
-
-#define S5P_CLKSRC_DMC			S5P_CLKREG(0x10200)
-#define S5P_CLKDIV_DMC0			S5P_CLKREG(0x10500)
-#define S5P_CLKDIV_STAT_DMC0		S5P_CLKREG(0x10600)
-
-#define S5P_APLL_LOCK			S5P_CLKREG(0x14000)
-#define S5P_MPLL_LOCK			S5P_CLKREG(0x14004)
-#define S5P_APLL_CON0			S5P_CLKREG(0x14100)
-#define S5P_APLL_CON1			S5P_CLKREG(0x14104)
-#define S5P_MPLL_CON0			S5P_CLKREG(0x14108)
-#define S5P_MPLL_CON1			S5P_CLKREG(0x1410C)
-
-#define S5P_CLKSRC_CPU			S5P_CLKREG(0x14200)
-#define S5P_CLKMUX_STATCPU		S5P_CLKREG(0x14400)
-
-#define S5P_CLKDIV_CPU			S5P_CLKREG(0x14500)
-#define S5P_CLKDIV_CPU1			S5P_CLKREG(0x14504)
-#define S5P_CLKDIV_STATCPU		S5P_CLKREG(0x14600)
-#define S5P_CLKDIV_STATCPU1		S5P_CLKREG(0x14604)
-
-#define S5P_CLKGATE_SCLKCPU		S5P_CLKREG(0x14800)
-
-/* APLL_LOCK */
-#define S5P_APLL_LOCKTIME		(0x1C20)	/* 300us */
-
-/* APLL_CON0 */
-#define S5P_APLLCON0_ENABLE_SHIFT	(31)
-#define S5P_APLLCON0_LOCKED_SHIFT	(29)
-#define S5P_APLL_VAL_1000		((250 << 16) | (6 << 8) | 1)
-#define S5P_APLL_VAL_800		((200 << 16) | (6 << 8) | 1)
-
-/* CLK_SRC_CPU */
-#define S5P_CLKSRC_CPU_MUXCORE_SHIFT	(16)
-#define S5P_CLKMUX_STATCPU_MUXCORE_MASK	(0x7 << S5P_CLKSRC_CPU_MUXCORE_SHIFT)
-
-/* CLKDIV_CPU0 */
-#define S5P_CLKDIV_CPU0_CORE_SHIFT	(0)
-#define S5P_CLKDIV_CPU0_CORE_MASK	(0x7 << S5P_CLKDIV_CPU0_CORE_SHIFT)
-#define S5P_CLKDIV_CPU0_COREM0_SHIFT	(4)
-#define S5P_CLKDIV_CPU0_COREM0_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM0_SHIFT)
-#define S5P_CLKDIV_CPU0_COREM1_SHIFT	(8)
-#define S5P_CLKDIV_CPU0_COREM1_MASK	(0x7 << S5P_CLKDIV_CPU0_COREM1_SHIFT)
-#define S5P_CLKDIV_CPU0_PERIPH_SHIFT	(12)
-#define S5P_CLKDIV_CPU0_PERIPH_MASK	(0x7 << S5P_CLKDIV_CPU0_PERIPH_SHIFT)
-#define S5P_CLKDIV_CPU0_ATB_SHIFT	(16)
-#define S5P_CLKDIV_CPU0_ATB_MASK	(0x7 << S5P_CLKDIV_CPU0_ATB_SHIFT)
-#define S5P_CLKDIV_CPU0_PCLKDBG_SHIFT	(20)
-#define S5P_CLKDIV_CPU0_PCLKDBG_MASK	(0x7 << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT)
-#define S5P_CLKDIV_CPU0_APLL_SHIFT	(24)
-#define S5P_CLKDIV_CPU0_APLL_MASK	(0x7 << S5P_CLKDIV_CPU0_APLL_SHIFT)
-
-/* CLKDIV_DMC0 */
-#define S5P_CLKDIV_DMC0_ACP_SHIFT	(0)
-#define S5P_CLKDIV_DMC0_ACP_MASK	(0x7 << S5P_CLKDIV_DMC0_ACP_SHIFT)
-#define S5P_CLKDIV_DMC0_ACPPCLK_SHIFT	(4)
-#define S5P_CLKDIV_DMC0_ACPPCLK_MASK	(0x7 << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT)
-#define S5P_CLKDIV_DMC0_DPHY_SHIFT	(8)
-#define S5P_CLKDIV_DMC0_DPHY_MASK	(0x7 << S5P_CLKDIV_DMC0_DPHY_SHIFT)
-#define S5P_CLKDIV_DMC0_DMC_SHIFT	(12)
-#define S5P_CLKDIV_DMC0_DMC_MASK	(0x7 << S5P_CLKDIV_DMC0_DMC_SHIFT)
-#define S5P_CLKDIV_DMC0_DMCD_SHIFT	(16)
-#define S5P_CLKDIV_DMC0_DMCD_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCD_SHIFT)
-#define S5P_CLKDIV_DMC0_DMCP_SHIFT	(20)
-#define S5P_CLKDIV_DMC0_DMCP_MASK	(0x7 << S5P_CLKDIV_DMC0_DMCP_SHIFT)
-#define S5P_CLKDIV_DMC0_COPY2_SHIFT	(24)
-#define S5P_CLKDIV_DMC0_COPY2_MASK	(0x7 << S5P_CLKDIV_DMC0_COPY2_SHIFT)
-#define S5P_CLKDIV_DMC0_CORETI_SHIFT	(28)
-#define S5P_CLKDIV_DMC0_CORETI_MASK	(0x7 << S5P_CLKDIV_DMC0_CORETI_SHIFT)
-
-/* CLKDIV_TOP */
-#define S5P_CLKDIV_TOP_ACLK200_SHIFT	(0)
-#define S5P_CLKDIV_TOP_ACLK200_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK200_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK100_SHIFT	(4)
-#define S5P_CLKDIV_TOP_ACLK100_MASK	(0xf << S5P_CLKDIV_TOP_ACLK100_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK160_SHIFT	(8)
-#define S5P_CLKDIV_TOP_ACLK160_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK160_SHIFT)
-#define S5P_CLKDIV_TOP_ACLK133_SHIFT	(12)
-#define S5P_CLKDIV_TOP_ACLK133_MASK	(0x7 << S5P_CLKDIV_TOP_ACLK133_SHIFT)
-#define S5P_CLKDIV_TOP_ONENAND_SHIFT	(16)
-#define S5P_CLKDIV_TOP_ONENAND_MASK	(0x7 << S5P_CLKDIV_TOP_ONENAND_SHIFT)
-
-/* CLKDIV_LEFTBUS / CLKDIV_RIGHTBUS*/
-#define S5P_CLKDIV_BUS_GDLR_SHIFT	(0)
-#define S5P_CLKDIV_BUS_GDLR_MASK	(0x7 << S5P_CLKDIV_BUS_GDLR_SHIFT)
-#define S5P_CLKDIV_BUS_GPLR_SHIFT	(4)
-#define S5P_CLKDIV_BUS_GPLR_MASK	(0x7 << S5P_CLKDIV_BUS_GPLR_SHIFT)
-
-/* Compatibility defines */
-
-#define S5P_EPLL_CON			S5P_EPLL_CON0
-
-#endif /* __ASM_ARCH_REGS_CLOCK_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-gpio.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - GPIO (including EINT) 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.
-*/
-
-#ifndef __ASM_ARCH_REGS_GPIO_H
-#define __ASM_ARCH_REGS_GPIO_H __FILE__
-
-#include <mach/map.h>
-#include <mach/irqs.h>
-
-#define S5PV310_EINT40CON		(S5P_VA_GPIO2 + 0xE00)
-#define S5P_EINT_CON(x)			(S5PV310_EINT40CON + ((x) * 0x4))
-
-#define S5PV310_EINT40FLTCON0		(S5P_VA_GPIO2 + 0xE80)
-#define S5P_EINT_FLTCON(x)		(S5PV310_EINT40FLTCON0 + ((x) * 0x4))
-
-#define S5PV310_EINT40MASK		(S5P_VA_GPIO2 + 0xF00)
-#define S5P_EINT_MASK(x)		(S5PV310_EINT40MASK + ((x) * 0x4))
-
-#define S5PV310_EINT40PEND		(S5P_VA_GPIO2 + 0xF40)
-#define S5P_EINT_PEND(x)		(S5PV310_EINT40PEND + ((x) * 0x4))
-
-#define EINT_REG_NR(x)			(EINT_OFFSET(x) >> 3)
-
-#define eint_irq_to_bit(irq)		(1 << (EINT_OFFSET(irq) & 0x7))
-
-#define EINT_MODE			S3C_GPIO_SFN(0xf)
-
-#define EINT_GPIO_0(x)			S5PV310_GPX0(x)
-#define EINT_GPIO_1(x)			S5PV310_GPX1(x)
-#define EINT_GPIO_2(x)			S5PV310_GPX2(x)
-#define EINT_GPIO_3(x)			S5PV310_GPX3(x)
-
-#endif /* __ASM_ARCH_REGS_GPIO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-irq.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-irq.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-irq.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-irq.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - IRQ 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.
-*/
-
-#ifndef __ASM_ARCH_REGS_IRQ_H
-#define __ASM_ARCH_REGS_IRQ_H __FILE__
-
-#include <asm/hardware/gic.h>
-#include <mach/map.h>
-
-#endif /* __ASM_ARCH_REGS_IRQ_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-mem.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-mem.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-mem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-mem.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-mem.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - SROMC and DMC 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.
-*/
-
-#ifndef __ASM_ARCH_REGS_MEM_H
-#define __ASM_ARCH_REGS_MEM_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_DMC0_MEMCON_OFFSET		0x04
-
-#define S5P_DMC0_MEMTYPE_SHIFT		8
-#define S5P_DMC0_MEMTYPE_MASK		0xF
-
-#endif /* __ASM_ARCH_REGS_MEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-pmu.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-pmu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-pmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-pmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - Power management unit definition
- *
- * 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_REGS_PMU_H
-#define __ASM_ARCH_REGS_PMU_H __FILE__
-
-#include <mach/map.h>
-
-#define S5P_PMUREG(x)			(S5P_VA_PMU + (x))
-
-#define S5P_PMU_CAM_CONF		S5P_PMUREG(0x3C00)
-#define S5P_PMU_TV_CONF		S5P_PMUREG(0x3C20)
-#define S5P_PMU_MFC_CONF		S5P_PMUREG(0x3C40)
-#define S5P_PMU_G3D_CONF		S5P_PMUREG(0x3C60)
-#define S5P_PMU_LCD0_CONF		S5P_PMUREG(0x3C80)
-#define S5P_PMU_LCD1_CONF		S5P_PMUREG(0x3CA0)
-#define S5P_PMU_GPS_CONF		S5P_PMUREG(0x3CE0)
-
-#define S5P_INT_LOCAL_PWR_EN		0x7
-
-#endif /* __ASM_ARCH_REGS_PMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,24 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/regs-sysmmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - System MMU register
- *
- * 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_REGS_SYSMMU_H
-#define __ASM_ARCH_REGS_SYSMMU_H __FILE__
-
-#define S5P_MMU_CTRL			0x000
-#define S5P_MMU_CFG			0x004
-#define S5P_MMU_STATUS			0x008
-#define S5P_MMU_FLUSH			0x00C
-#define S5P_PT_BASE_ADDR		0x014
-#define S5P_INT_STATUS			0x018
-#define S5P_PAGE_FAULT_ADDR		0x024
-
-#endif /* __ASM_ARCH_REGS_SYSMMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/smp.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/smp.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/smp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/smp.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,19 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/smp.h
- *
- * Cloned from arch/arm/mach-realview/include/mach/smp.h
-*/
-
-#ifndef ASM_ARCH_SMP_H
-#define ASM_ARCH_SMP_H __FILE__
-
-#include <asm/hardware/gic.h>
-
-/*
- * We use IRQ1 as the IPI
- */
-static inline void smp_cross_call(const struct cpumask *mask, int ipi)
-{
-	gic_raise_softirq(mask, ipi);
-}
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/sysmmu.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/sysmmu.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/sysmmu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,122 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/sysmmu.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Samsung sysmmu driver for S5PV310
- *
- * 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_ARCH_SYSMMU_H
-#define __ASM_ARM_ARCH_SYSMMU_H __FILE__
-
-#define S5PV310_SYSMMU_TOTAL_IPNUM	16
-#define S5P_SYSMMU_TOTAL_IPNUM		S5PV310_SYSMMU_TOTAL_IPNUM
-
-enum s5pv310_sysmmu_ips {
-	SYSMMU_MDMA,
-	SYSMMU_SSS,
-	SYSMMU_FIMC0,
-	SYSMMU_FIMC1,
-	SYSMMU_FIMC2,
-	SYSMMU_FIMC3,
-	SYSMMU_JPEG,
-	SYSMMU_FIMD0,
-	SYSMMU_FIMD1,
-	SYSMMU_PCIe,
-	SYSMMU_G2D,
-	SYSMMU_ROTATOR,
-	SYSMMU_MDMA2,
-	SYSMMU_TV,
-	SYSMMU_MFC_L,
-	SYSMMU_MFC_R,
-};
-
-static char *sysmmu_ips_name[S5PV310_SYSMMU_TOTAL_IPNUM] = {
-	"SYSMMU_MDMA"	,
-	"SYSMMU_SSS"	,
-	"SYSMMU_FIMC0"	,
-	"SYSMMU_FIMC1"	,
-	"SYSMMU_FIMC2"	,
-	"SYSMMU_FIMC3"	,
-	"SYSMMU_JPEG"	,
-	"SYSMMU_FIMD0"	,
-	"SYSMMU_FIMD1"	,
-	"SYSMMU_PCIe"	,
-	"SYSMMU_G2D"	,
-	"SYSMMU_ROTATOR",
-	"SYSMMU_MDMA2"	,
-	"SYSMMU_TV"	,
-	"SYSMMU_MFC_L"	,
-	"SYSMMU_MFC_R"	,
-};
-
-typedef enum s5pv310_sysmmu_ips sysmmu_ips;
-
-struct sysmmu_tt_info {
-	unsigned long *pgd;
-	unsigned long pgd_paddr;
-	unsigned long *pte;
-};
-
-struct sysmmu_controller {
-	const char		*name;
-
-	/* channels registers */
-	void __iomem		*regs;
-
-	/* channel irq */
-	unsigned int		irq;
-
-	sysmmu_ips		ips;
-
-	/* Translation Table Info. */
-	struct sysmmu_tt_info	*tt_info;
-
-	struct resource		*mem;
-	struct device		*dev;
-
-	/* SysMMU controller enable - true : enable */
-	bool			enable;
-};
-
-/**
- * s5p_sysmmu_enable() - enable system mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function enable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_enable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_disable() - disable sysmmu mmu of ip
- * @ips: The ip connected system mmu.
- *
- * This function disable system mmu to transfer address
- * from virtual address to physical address
- */
-int s5p_sysmmu_disable(sysmmu_ips ips);
-
-/**
- * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
- * @ips: The ip connected system mmu.
- * @pgd: The page table base address.
- *
- * This function set page table base address
- * When system mmu transfer address from virtaul address to physical address,
- * system mmu refer address information from page table
- */
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
-
-/**
- * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
- * @ips: The ip connected system mmu.
- *
- * This function flush all TLB entry in system mmu
- */
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
-#endif /* __ASM_ARM_ARCH_SYSMMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/system.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - system support header
- *
- * 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_SYSTEM_H
-#define __ASM_ARCH_SYSTEM_H __FILE__
-
-#include <plat/system-reset.h>
-
-static void arch_idle(void)
-{
-	/* nothing here yet */
-}
-#endif /* __ASM_ARCH_SYSTEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/timex.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/timex.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/timex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/timex.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright (c) 2003-2010 Simtec Electronics
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * Based on arch/arm/mach-s5p6442/include/mach/timex.h
- *
- * S5PV310 - time parameters
- *
- * 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_TIMEX_H
-#define __ASM_ARCH_TIMEX_H __FILE__
-
-/* CLOCK_TICK_RATE needs to be evaluatable by the cpp, so making it
- * a variable is useless. It seems as long as we make our timers an
- * exact multiple of HZ, any value that makes a 1->1 correspondence
- * for the time conversion functions to/from jiffies is acceptable.
-*/
-
-#define CLOCK_TICK_RATE 12000000
-
-#endif /* __ASM_ARCH_TIMEX_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,30 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/uncompress.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - uncompress 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.
-*/
-
-#ifndef __ASM_ARCH_UNCOMPRESS_H
-#define __ASM_ARCH_UNCOMPRESS_H __FILE__
-
-#include <mach/map.h>
-#include <plat/uncompress.h>
-
-static void arch_detect_cpu(void)
-{
-	/* we do not need to do any cpu detection here at the moment. */
-
-	/*
-	 * For preventing FIFO overrun or infinite loop of UART console,
-	 * fifo_max should be the minimum fifo size of all of the UART channels
-	 */
-	fifo_mask = S5PV210_UFSTAT_TXMASK;
-	fifo_max = 15 << S5PV210_UFSTAT_TXSHIFT;
-}
-#endif /* __ASM_ARCH_UNCOMPRESS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/vmalloc.h linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/vmalloc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/include/mach/vmalloc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/include/mach/vmalloc.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Copyright 2010 Ben Dooks <ben-linux@fluff.org>
- *
- * Based on arch/arm/mach-s5p6440/include/mach/vmalloc.h
- *
- * 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.
- *
- * S5PV310 vmalloc definition
-*/
-
-#ifndef __ASM_ARCH_VMALLOC_H
-#define __ASM_ARCH_VMALLOC_H __FILE__
-
-#define VMALLOC_END	0xF6000000UL
-
-#endif /* __ASM_ARCH_VMALLOC_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/init.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/init.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/init.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,41 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/init.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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/serial_core.h>
-
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/regs-serial.h>
-
-static struct s3c24xx_uart_clksrc s5pv310_serial_clocks[] = {
-	[0] = {
-		.name		= "uclk1",
-		.divisor	= 1,
-		.min_baud	= 0,
-		.max_baud	= 0,
-	},
-};
-
-/* uart registration process */
-void __init s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no)
-{
-	struct s3c2410_uartcfg *tcfg = cfg;
-	u32 ucnt;
-
-	for (ucnt = 0; ucnt < no; ucnt++, tcfg++) {
-		if (!tcfg->clocks) {
-			tcfg->has_fracval = 1;
-			tcfg->clocks = s5pv310_serial_clocks;
-			tcfg->clocks_size = ARRAY_SIZE(s5pv310_serial_clocks);
-		}
-	}
-
-	s3c24xx_init_uartdevs("s5pv210-uart", s5p_uart_resources, cfg, no);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/irq-combiner.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/irq-combiner.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/irq-combiner.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/irq-combiner.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,127 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/irq-combiner.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Based on arch/arm/common/gic.c
- *
- * IRQ COMBINER 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/io.h>
-
-#include <asm/mach/irq.h>
-
-#define COMBINER_ENABLE_SET	0x0
-#define COMBINER_ENABLE_CLEAR	0x4
-#define COMBINER_INT_STATUS	0xC
-
-static DEFINE_SPINLOCK(irq_controller_lock);
-
-struct combiner_chip_data {
-	unsigned int irq_offset;
-	unsigned int irq_mask;
-	void __iomem *base;
-};
-
-static struct combiner_chip_data combiner_data[MAX_COMBINER_NR];
-
-static inline void __iomem *combiner_base(struct irq_data *data)
-{
-	struct combiner_chip_data *combiner_data =
-		irq_data_get_irq_chip_data(data);
-
-	return combiner_data->base;
-}
-
-static void combiner_mask_irq(struct irq_data *data)
-{
-	u32 mask = 1 << (data->irq % 32);
-
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_CLEAR);
-}
-
-static void combiner_unmask_irq(struct irq_data *data)
-{
-	u32 mask = 1 << (data->irq % 32);
-
-	__raw_writel(mask, combiner_base(data) + COMBINER_ENABLE_SET);
-}
-
-static void combiner_handle_cascade_irq(unsigned int irq, struct irq_desc *desc)
-{
-	struct combiner_chip_data *chip_data = get_irq_data(irq);
-	struct irq_chip *chip = get_irq_chip(irq);
-	unsigned int cascade_irq, combiner_irq;
-	unsigned long status;
-
-	/* primary controller ack'ing */
-	chip->irq_ack(&desc->irq_data);
-
-	spin_lock(&irq_controller_lock);
-	status = __raw_readl(chip_data->base + COMBINER_INT_STATUS);
-	spin_unlock(&irq_controller_lock);
-	status &= chip_data->irq_mask;
-
-	if (status == 0)
-		goto out;
-
-	combiner_irq = __ffs(status);
-
-	cascade_irq = combiner_irq + (chip_data->irq_offset & ~31);
-	if (unlikely(cascade_irq >= NR_IRQS))
-		do_bad_IRQ(cascade_irq, desc);
-	else
-		generic_handle_irq(cascade_irq);
-
- out:
-	/* primary controller unmasking */
-	chip->irq_unmask(&desc->irq_data);
-}
-
-static struct irq_chip combiner_chip = {
-	.name		= "COMBINER",
-	.irq_mask	= combiner_mask_irq,
-	.irq_unmask	= combiner_unmask_irq,
-};
-
-void __init combiner_cascade_irq(unsigned int combiner_nr, unsigned int irq)
-{
-	if (combiner_nr >= MAX_COMBINER_NR)
-		BUG();
-	if (set_irq_data(irq, &combiner_data[combiner_nr]) != 0)
-		BUG();
-	set_irq_chained_handler(irq, combiner_handle_cascade_irq);
-}
-
-void __init combiner_init(unsigned int combiner_nr, void __iomem *base,
-			  unsigned int irq_start)
-{
-	unsigned int i;
-
-	if (combiner_nr >= MAX_COMBINER_NR)
-		BUG();
-
-	combiner_data[combiner_nr].base = base;
-	combiner_data[combiner_nr].irq_offset = irq_start;
-	combiner_data[combiner_nr].irq_mask = 0xff << ((combiner_nr % 4) << 3);
-
-	/* Disable all interrupts */
-
-	__raw_writel(combiner_data[combiner_nr].irq_mask,
-		     base + COMBINER_ENABLE_CLEAR);
-
-	/* Setup the Linux IRQ subsystem */
-
-	for (i = irq_start; i < combiner_data[combiner_nr].irq_offset
-				+ MAX_IRQ_IN_COMBINER; i++) {
-		set_irq_chip(i, &combiner_chip);
-		set_irq_chip_data(i, &combiner_data[combiner_nr]);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/irq-eint.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/irq-eint.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/irq-eint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/irq-eint.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,229 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/irq-eint.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 - IRQ EINT 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/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <linux/sysdev.h>
-#include <linux/gpio.h>
-
-#include <plat/pm.h>
-#include <plat/cpu.h>
-#include <plat/gpio-cfg.h>
-
-#include <mach/regs-gpio.h>
-
-static DEFINE_SPINLOCK(eint_lock);
-
-static unsigned int eint0_15_data[16];
-
-static unsigned int s5pv310_get_irq_nr(unsigned int number)
-{
-	u32 ret = 0;
-
-	switch (number) {
-	case 0 ... 3:
-		ret = (number + IRQ_EINT0);
-		break;
-	case 4 ... 7:
-		ret = (number + (IRQ_EINT4 - 4));
-		break;
-	case 8 ... 15:
-		ret = (number + (IRQ_EINT8 - 8));
-		break;
-	default:
-		printk(KERN_ERR "number available : %d\n", number);
-	}
-
-	return ret;
-}
-
-static inline void s5pv310_irq_eint_mask(struct irq_data *data)
-{
-	u32 mask;
-
-	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask |= eint_irq_to_bit(data->irq);
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-}
-
-static void s5pv310_irq_eint_unmask(struct irq_data *data)
-{
-	u32 mask;
-
-	spin_lock(&eint_lock);
-	mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	mask &= ~(eint_irq_to_bit(data->irq));
-	__raw_writel(mask, S5P_EINT_MASK(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-}
-
-static inline void s5pv310_irq_eint_ack(struct irq_data *data)
-{
-	__raw_writel(eint_irq_to_bit(data->irq),
-		     S5P_EINT_PEND(EINT_REG_NR(data->irq)));
-}
-
-static void s5pv310_irq_eint_maskack(struct irq_data *data)
-{
-	s5pv310_irq_eint_mask(data);
-	s5pv310_irq_eint_ack(data);
-}
-
-static int s5pv310_irq_eint_set_type(struct irq_data *data, unsigned int type)
-{
-	int offs = EINT_OFFSET(data->irq);
-	int shift;
-	u32 ctrl, mask;
-	u32 newvalue = 0;
-
-	switch (type) {
-	case IRQ_TYPE_EDGE_RISING:
-		newvalue = S5P_IRQ_TYPE_EDGE_RISING;
-		break;
-
-	case IRQ_TYPE_EDGE_FALLING:
-		newvalue = S5P_IRQ_TYPE_EDGE_FALLING;
-		break;
-
-	case IRQ_TYPE_EDGE_BOTH:
-		newvalue = S5P_IRQ_TYPE_EDGE_BOTH;
-		break;
-
-	case IRQ_TYPE_LEVEL_LOW:
-		newvalue = S5P_IRQ_TYPE_LEVEL_LOW;
-		break;
-
-	case IRQ_TYPE_LEVEL_HIGH:
-		newvalue = S5P_IRQ_TYPE_LEVEL_HIGH;
-		break;
-
-	default:
-		printk(KERN_ERR "No such irq type %d", type);
-		return -EINVAL;
-	}
-
-	shift = (offs & 0x7) * 4;
-	mask = 0x7 << shift;
-
-	spin_lock(&eint_lock);
-	ctrl = __raw_readl(S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	ctrl &= ~mask;
-	ctrl |= newvalue << shift;
-	__raw_writel(ctrl, S5P_EINT_CON(EINT_REG_NR(data->irq)));
-	spin_unlock(&eint_lock);
-
-	switch (offs) {
-	case 0 ... 7:
-		s3c_gpio_cfgpin(EINT_GPIO_0(offs & 0x7), EINT_MODE);
-		break;
-	case 8 ... 15:
-		s3c_gpio_cfgpin(EINT_GPIO_1(offs & 0x7), EINT_MODE);
-		break;
-	case 16 ... 23:
-		s3c_gpio_cfgpin(EINT_GPIO_2(offs & 0x7), EINT_MODE);
-		break;
-	case 24 ... 31:
-		s3c_gpio_cfgpin(EINT_GPIO_3(offs & 0x7), EINT_MODE);
-		break;
-	default:
-		printk(KERN_ERR "No such irq number %d", offs);
-	}
-
-	return 0;
-}
-
-static struct irq_chip s5pv310_irq_eint = {
-	.name		= "s5pv310-eint",
-	.irq_mask	= s5pv310_irq_eint_mask,
-	.irq_unmask	= s5pv310_irq_eint_unmask,
-	.irq_mask_ack	= s5pv310_irq_eint_maskack,
-	.irq_ack	= s5pv310_irq_eint_ack,
-	.irq_set_type	= s5pv310_irq_eint_set_type,
-#ifdef CONFIG_PM
-	.irq_set_wake	= s3c_irqext_wake,
-#endif
-};
-
-/* s5pv310_irq_demux_eint
- *
- * This function demuxes the IRQ from from EINTs 16 to 31.
- * It is designed to be inlined into the specific handler
- * s5p_irq_demux_eintX_Y.
- *
- * Each EINT pend/mask registers handle eight of them.
- */
-static inline void s5pv310_irq_demux_eint(unsigned int start)
-{
-	unsigned int irq;
-
-	u32 status = __raw_readl(S5P_EINT_PEND(EINT_REG_NR(start)));
-	u32 mask = __raw_readl(S5P_EINT_MASK(EINT_REG_NR(start)));
-
-	status &= ~mask;
-	status &= 0xff;
-
-	while (status) {
-		irq = fls(status) - 1;
-		generic_handle_irq(irq + start);
-		status &= ~(1 << irq);
-	}
-}
-
-static void s5pv310_irq_demux_eint16_31(unsigned int irq, struct irq_desc *desc)
-{
-	s5pv310_irq_demux_eint(IRQ_EINT(16));
-	s5pv310_irq_demux_eint(IRQ_EINT(24));
-}
-
-static void s5pv310_irq_eint0_15(unsigned int irq, struct irq_desc *desc)
-{
-	u32 *irq_data = get_irq_data(irq);
-	struct irq_chip *chip = get_irq_chip(irq);
-
-	chip->irq_mask(&desc->irq_data);
-
-	if (chip->irq_ack)
-		chip->irq_ack(&desc->irq_data);
-
-	generic_handle_irq(*irq_data);
-
-	chip->irq_unmask(&desc->irq_data);
-}
-
-int __init s5pv310_init_irq_eint(void)
-{
-	int irq;
-
-	for (irq = 0 ; irq <= 31 ; irq++) {
-		set_irq_chip(IRQ_EINT(irq), &s5pv310_irq_eint);
-		set_irq_handler(IRQ_EINT(irq), handle_level_irq);
-		set_irq_flags(IRQ_EINT(irq), IRQF_VALID);
-	}
-
-	set_irq_chained_handler(IRQ_EINT16_31, s5pv310_irq_demux_eint16_31);
-
-	for (irq = 0 ; irq <= 15 ; irq++) {
-		eint0_15_data[irq] = IRQ_EINT(irq);
-
-		set_irq_data(s5pv310_get_irq_nr(irq), &eint0_15_data[irq]);
-		set_irq_chained_handler(s5pv310_get_irq_nr(irq),
-					s5pv310_irq_eint0_15);
-	}
-
-	return 0;
-}
-
-arch_initcall(s5pv310_init_irq_eint);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,151 +0,0 @@
-# arch/arm/mach-s5pv310/Kconfig
-#
-# Copyright (c) 2010 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-# Configuration options for the S5PV310
-
-if ARCH_S5PV310
-
-config CPU_S5PV310
-	bool
-	select S3C_PL330_DMA
-	help
-	  Enable S5PV310 CPU support
-
-config S5PV310_DEV_PD
-	bool
-	help
-	  Compile in platform device definitions for Power Domain
-
-config S5PV310_SETUP_I2C1
-	bool
-	help
-	  Common setup code for i2c bus 1.
-
-config S5PV310_SETUP_I2C2
-	bool
-	help
-	  Common setup code for i2c bus 2.
-
-config S5PV310_SETUP_I2C3
-	bool
-	help
-	  Common setup code for i2c bus 3.
-
-config S5PV310_SETUP_I2C4
-	bool
-	help
-	  Common setup code for i2c bus 4.
-
-config S5PV310_SETUP_I2C5
-	bool
-	help
-	  Common setup code for i2c bus 5.
-
-config S5PV310_SETUP_I2C6
-	bool
-	help
-	  Common setup code for i2c bus 6.
-
-config S5PV310_SETUP_I2C7
-	bool
-	help
-	  Common setup code for i2c bus 7.
-
-config S5PV310_SETUP_SDHCI
-	bool
-	select S5PV310_SETUP_SDHCI_GPIO
-	help
-	  Internal helper functions for S5PV310 based SDHCI systems.
-
-config S5PV310_SETUP_SDHCI_GPIO
-	bool
-	help
-	  Common setup code for SDHCI gpio.
-
-config S5PV310_DEV_SYSMMU
-	bool
-	help
-	  Common setup code for SYSTEM MMU in S5PV310
-
-# machine support
-
-menu "S5PC210 Machines"
-
-config MACH_SMDKC210
-	bool "SMDKC210"
-	select CPU_S5PV310
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S5PV310_DEV_PD
-	select S5PV310_SETUP_I2C1
-	select S5PV310_SETUP_SDHCI
-	select S5PV310_DEV_SYSMMU
-	help
-	  Machine support for Samsung SMDKC210
-	  S5PC210(MCP) is one of package option of S5PV310
-
-config MACH_UNIVERSAL_C210
-	bool "Mobile UNIVERSAL_C210 Board"
-	select CPU_S5PV310
-	select S5P_DEV_ONENAND
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S5PV310_SETUP_SDHCI
-	select S3C_DEV_I2C1
-	select S5PV310_SETUP_I2C1
-	help
-	  Machine support for Samsung Mobile Universal S5PC210 Reference
-	  Board. S5PC210(MCP) is one of package option of S5PV310
-
-endmenu
-
-menu "S5PV310 Machines"
-
-config MACH_SMDKV310
-	bool "SMDKV310"
-	select CPU_S5PV310
-	select S3C_DEV_RTC
-	select S3C_DEV_WDT
-	select S3C_DEV_I2C1
-	select S3C_DEV_HSMMC
-	select S3C_DEV_HSMMC1
-	select S3C_DEV_HSMMC2
-	select S3C_DEV_HSMMC3
-	select S5PV310_DEV_PD
-	select S5PV310_DEV_SYSMMU
-	select S5PV310_SETUP_I2C1
-	select S5PV310_SETUP_SDHCI
-	help
-	  Machine support for Samsung SMDKV310
-
-endmenu
-
-comment "Configuration for HSMMC bus width"
-
-menu "Use 8-bit bus width"
-
-config S5PV310_SDHCI_CH0_8BIT
-	bool "Channel 0 with 8-bit bus"
-	help
-	  Support HSMMC Channel 0 8-bit bus.
-	  If selected, Channel 1 is disabled.
-
-config S5PV310_SDHCI_CH2_8BIT
-	bool "Channel 2 with 8-bit bus"
-	help
-	  Support HSMMC Channel 2 8-bit bus.
-	  If selected, Channel 3 is disabled.
-
-endmenu
-
-endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/localtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/localtimer.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,25 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/localtimer.c
- *
- * 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/clockchips.h>
-
-#include <asm/irq.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 = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/mach-smdkc210.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/mach-smdkc210.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/mach-smdkc210.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/mach-smdkc210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,223 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/mach-smdkc210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/s5pv310.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKC210_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKC210_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKC210_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkc210_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKC210_UCON_DEFAULT,
-		.ulcon		= SMDKC210_ULCON_DEFAULT,
-		.ufcon		= SMDKC210_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkc210_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct resource smdkc210_smsc911x_resources[] = {
-	[0] = {
-		.start	= S5PV310_PA_SROM_BANK(1),
-		.end	= S5PV310_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkc210_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkc210_smsc911x_resources),
-	.resource	= smdkc210_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkc210_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&s5pv310_device_ac97,
-	&s5pv310_device_i2s0,
-	&s5pv310_device_pd[PD_MFC],
-	&s5pv310_device_pd[PD_G3D],
-	&s5pv310_device_pd[PD_LCD0],
-	&s5pv310_device_pd[PD_LCD1],
-	&s5pv310_device_pd[PD_CAM],
-	&s5pv310_device_pd[PD_TV],
-	&s5pv310_device_pd[PD_GPS],
-	&s5pv310_device_sysmmu,
-	&samsung_asoc_dma,
-	&smdkc210_smsc911x,
-};
-
-static void __init smdkc210_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-static void __init smdkc210_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkc210_uartcfgs, ARRAY_SIZE(smdkc210_uartcfgs));
-}
-
-static void __init smdkc210_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkc210_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkc210_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkc210_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkc210_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkc210_hsmmc3_pdata);
-
-	platform_add_devices(smdkc210_devices, ARRAY_SIZE(smdkc210_devices));
-}
-
-MACHINE_START(SMDKC210, "SMDKC210")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= s5pv310_init_irq,
-	.map_io		= smdkc210_map_io,
-	.init_machine	= smdkc210_machine_init,
-	.timer		= &s5pv310_timer,
-MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/mach-smdkv310.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/mach-smdkv310.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/mach-smdkv310.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/mach-smdkv310.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,224 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/mach-smdkv310.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.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/serial_core.h>
-#include <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/platform_device.h>
-#include <linux/smsc911x.h>
-#include <linux/io.h>
-#include <linux/i2c.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/regs-srom.h>
-#include <plat/s5pv310.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-#include <plat/iic.h>
-#include <plat/pd.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define SMDKV310_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define SMDKV310_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define SMDKV310_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG4 |	\
-				 S5PV210_UFCON_RXTRIG4)
-
-static struct s3c2410_uartcfg smdkv310_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.flags		= 0,
-		.ucon		= SMDKV310_UCON_DEFAULT,
-		.ulcon		= SMDKV310_ULCON_DEFAULT,
-		.ufcon		= SMDKV310_UFCON_DEFAULT,
-	},
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc0_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH0_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc1_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK0(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc2_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-#ifdef CONFIG_S5PV310_SDHCI_CH2_8BIT
-	.max_width		= 8,
-	.host_caps		= MMC_CAP_8_BIT_DATA,
-#endif
-};
-
-static struct s3c_sdhci_platdata smdkv310_hsmmc3_pdata __initdata = {
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.ext_cd_gpio		= S5PV310_GPK2(2),
-	.ext_cd_gpio_invert	= 1,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct resource smdkv310_smsc911x_resources[] = {
-	[0] = {
-		.start	= S5PV310_PA_SROM_BANK(1),
-		.end	= S5PV310_PA_SROM_BANK(1) + SZ_64K - 1,
-		.flags	= IORESOURCE_MEM,
-	},
-	[1] = {
-		.start	= IRQ_EINT(5),
-		.end	= IRQ_EINT(5),
-		.flags	= IORESOURCE_IRQ | IRQF_TRIGGER_LOW,
-	},
-};
-
-static struct smsc911x_platform_config smsc9215_config = {
-	.irq_polarity	= SMSC911X_IRQ_POLARITY_ACTIVE_HIGH,
-	.irq_type	= SMSC911X_IRQ_TYPE_PUSH_PULL,
-	.flags		= SMSC911X_USE_16BIT | SMSC911X_FORCE_INTERNAL_PHY,
-	.phy_interface	= PHY_INTERFACE_MODE_MII,
-	.mac		= {0x00, 0x80, 0x00, 0x23, 0x45, 0x67},
-};
-
-static struct platform_device smdkv310_smsc911x = {
-	.name		= "smsc911x",
-	.id		= -1,
-	.num_resources	= ARRAY_SIZE(smdkv310_smsc911x_resources),
-	.resource	= smdkv310_smsc911x_resources,
-	.dev		= {
-		.platform_data	= &smsc9215_config,
-	},
-};
-
-static struct i2c_board_info i2c_devs1[] __initdata = {
-	{I2C_BOARD_INFO("wm8994", 0x1a),},
-};
-
-static struct platform_device *smdkv310_devices[] __initdata = {
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc1,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-	&s3c_device_i2c1,
-	&s3c_device_rtc,
-	&s3c_device_wdt,
-	&s5pv310_device_ac97,
-	&s5pv310_device_i2s0,
-	&s5pv310_device_pd[PD_MFC],
-	&s5pv310_device_pd[PD_G3D],
-	&s5pv310_device_pd[PD_LCD0],
-	&s5pv310_device_pd[PD_LCD1],
-	&s5pv310_device_pd[PD_CAM],
-	&s5pv310_device_pd[PD_TV],
-	&s5pv310_device_pd[PD_GPS],
-	&s5pv310_device_sysmmu,
-	&samsung_asoc_dma,
-	&smdkv310_smsc911x,
-};
-
-static void __init smdkv310_smsc911x_init(void)
-{
-	u32 cs1;
-
-	/* configure nCS1 width to 16 bits */
-	cs1 = __raw_readl(S5P_SROM_BW) &
-		~(S5P_SROM_BW__CS_MASK << S5P_SROM_BW__NCS1__SHIFT);
-	cs1 |= ((1 << S5P_SROM_BW__DATAWIDTH__SHIFT) |
-		(1 << S5P_SROM_BW__WAITENABLE__SHIFT) |
-		(1 << S5P_SROM_BW__BYTEENABLE__SHIFT)) <<
-		S5P_SROM_BW__NCS1__SHIFT;
-	__raw_writel(cs1, S5P_SROM_BW);
-
-	/* set timing for nCS1 suitable for ethernet chip */
-	__raw_writel((0x1 << S5P_SROM_BCX__PMC__SHIFT) |
-		     (0x9 << S5P_SROM_BCX__TACP__SHIFT) |
-		     (0xc << S5P_SROM_BCX__TCAH__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOH__SHIFT) |
-		     (0x6 << S5P_SROM_BCX__TACC__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TCOS__SHIFT) |
-		     (0x1 << S5P_SROM_BCX__TACS__SHIFT), S5P_SROM_BC1);
-}
-
-static void __init smdkv310_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(smdkv310_uartcfgs, ARRAY_SIZE(smdkv310_uartcfgs));
-}
-
-static void __init smdkv310_machine_init(void)
-{
-	s3c_i2c1_set_platdata(NULL);
-	i2c_register_board_info(1, i2c_devs1, ARRAY_SIZE(i2c_devs1));
-
-	smdkv310_smsc911x_init();
-
-	s3c_sdhci0_set_platdata(&smdkv310_hsmmc0_pdata);
-	s3c_sdhci1_set_platdata(&smdkv310_hsmmc1_pdata);
-	s3c_sdhci2_set_platdata(&smdkv310_hsmmc2_pdata);
-	s3c_sdhci3_set_platdata(&smdkv310_hsmmc3_pdata);
-
-	platform_add_devices(smdkv310_devices, ARRAY_SIZE(smdkv310_devices));
-}
-
-MACHINE_START(SMDKV310, "SMDKV310")
-	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
-	/* Maintainer: Changhwan Youn <chaos.youn@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= s5pv310_init_irq,
-	.map_io		= smdkv310_map_io,
-	.init_machine	= smdkv310_machine_init,
-	.timer		= &s5pv310_timer,
-MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/mach-universal_c210.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/mach-universal_c210.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/mach-universal_c210.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/mach-universal_c210.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,237 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/mach-universal_c210.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., 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/platform_device.h>
-#include <linux/serial_core.h>
-#include <linux/input.h>
-#include <linux/i2c.h>
-#include <linux/gpio_keys.h>
-#include <linux/gpio.h>
-#include <linux/regulator/machine.h>
-#include <linux/regulator/fixed.h>
-#include <linux/mmc/host.h>
-
-#include <asm/mach/arch.h>
-#include <asm/mach-types.h>
-
-#include <plat/regs-serial.h>
-#include <plat/s5pv310.h>
-#include <plat/cpu.h>
-#include <plat/devs.h>
-#include <plat/sdhci.h>
-
-#include <mach/map.h>
-
-/* Following are default values for UCON, ULCON and UFCON UART registers */
-#define UNIVERSAL_UCON_DEFAULT	(S3C2410_UCON_TXILEVEL |	\
-				 S3C2410_UCON_RXILEVEL |	\
-				 S3C2410_UCON_TXIRQMODE |	\
-				 S3C2410_UCON_RXIRQMODE |	\
-				 S3C2410_UCON_RXFIFO_TOI |	\
-				 S3C2443_UCON_RXERR_IRQEN)
-
-#define UNIVERSAL_ULCON_DEFAULT	S3C2410_LCON_CS8
-
-#define UNIVERSAL_UFCON_DEFAULT	(S3C2410_UFCON_FIFOMODE |	\
-				 S5PV210_UFCON_TXTRIG256 |	\
-				 S5PV210_UFCON_RXTRIG256)
-
-static struct s3c2410_uartcfg universal_uartcfgs[] __initdata = {
-	[0] = {
-		.hwport		= 0,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[1] = {
-		.hwport		= 1,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[2] = {
-		.hwport		= 2,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-	[3] = {
-		.hwport		= 3,
-		.ucon		= UNIVERSAL_UCON_DEFAULT,
-		.ulcon		= UNIVERSAL_ULCON_DEFAULT,
-		.ufcon		= UNIVERSAL_UFCON_DEFAULT,
-	},
-};
-
-static struct gpio_keys_button universal_gpio_keys_tables[] = {
-	{
-		.code			= KEY_VOLUMEUP,
-		.gpio			= S5PV310_GPX2(0),	/* XEINT16 */
-		.desc			= "gpio-keys: KEY_VOLUMEUP",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_VOLUMEDOWN,
-		.gpio			= S5PV310_GPX2(1),	/* XEINT17 */
-		.desc			= "gpio-keys: KEY_VOLUMEDOWN",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_CONFIG,
-		.gpio			= S5PV310_GPX2(2),	/* XEINT18 */
-		.desc			= "gpio-keys: KEY_CONFIG",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_CAMERA,
-		.gpio			= S5PV310_GPX2(3),	/* XEINT19 */
-		.desc			= "gpio-keys: KEY_CAMERA",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	}, {
-		.code			= KEY_OK,
-		.gpio			= S5PV310_GPX3(5),	/* XEINT29 */
-		.desc			= "gpio-keys: KEY_OK",
-		.type			= EV_KEY,
-		.active_low		= 1,
-		.debounce_interval	= 1,
-	},
-};
-
-static struct gpio_keys_platform_data universal_gpio_keys_data = {
-	.buttons	= universal_gpio_keys_tables,
-	.nbuttons	= ARRAY_SIZE(universal_gpio_keys_tables),
-};
-
-static struct platform_device universal_gpio_keys = {
-	.name			= "gpio-keys",
-	.dev			= {
-		.platform_data	= &universal_gpio_keys_data,
-	},
-};
-
-/* eMMC */
-static struct s3c_sdhci_platdata universal_hsmmc0_data __initdata = {
-	.max_width		= 8,
-	.host_caps		= (MMC_CAP_8_BIT_DATA | MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE),
-	.cd_type		= S3C_SDHCI_CD_PERMANENT,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-static struct regulator_consumer_supply mmc0_supplies[] = {
-	REGULATOR_SUPPLY("vmmc", "s3c-sdhci.0"),
-};
-
-static struct regulator_init_data mmc0_fixed_voltage_init_data = {
-	.constraints		= {
-		.name		= "VMEM_VDD_2.8V",
-		.valid_ops_mask	= REGULATOR_CHANGE_STATUS,
-	},
-	.num_consumer_supplies	= ARRAY_SIZE(mmc0_supplies),
-	.consumer_supplies	= mmc0_supplies,
-};
-
-static struct fixed_voltage_config mmc0_fixed_voltage_config = {
-	.supply_name		= "MASSMEMORY_EN",
-	.microvolts		= 2800000,
-	.gpio			= S5PV310_GPE1(3),
-	.enable_high		= true,
-	.init_data		= &mmc0_fixed_voltage_init_data,
-};
-
-static struct platform_device mmc0_fixed_voltage = {
-	.name			= "reg-fixed-voltage",
-	.id			= 0,
-	.dev			= {
-		.platform_data	= &mmc0_fixed_voltage_config,
-	},
-};
-
-/* SD */
-static struct s3c_sdhci_platdata universal_hsmmc2_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.ext_cd_gpio		= S5PV310_GPX3(4),      /* XEINT_28 */
-	.ext_cd_gpio_invert	= 1,
-	.cd_type		= S3C_SDHCI_CD_GPIO,
-	.clk_type		= S3C_SDHCI_CLK_DIV_EXTERNAL,
-};
-
-/* WiFi */
-static struct s3c_sdhci_platdata universal_hsmmc3_data __initdata = {
-	.max_width		= 4,
-	.host_caps		= MMC_CAP_4_BIT_DATA |
-				MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
-				MMC_CAP_DISABLE,
-	.cd_type		= S3C_SDHCI_CD_EXTERNAL,
-};
-
-static void __init universal_sdhci_init(void)
-{
-	s3c_sdhci0_set_platdata(&universal_hsmmc0_data);
-	s3c_sdhci2_set_platdata(&universal_hsmmc2_data);
-	s3c_sdhci3_set_platdata(&universal_hsmmc3_data);
-}
-
-/* I2C0 */
-static struct i2c_board_info i2c0_devs[] __initdata = {
-	/* Camera, To be updated */
-};
-
-/* I2C1 */
-static struct i2c_board_info i2c1_devs[] __initdata = {
-	/* Gyro, To be updated */
-};
-
-static struct platform_device *universal_devices[] __initdata = {
-	/* Samsung Platform Devices */
-	&mmc0_fixed_voltage,
-	&s3c_device_hsmmc0,
-	&s3c_device_hsmmc2,
-	&s3c_device_hsmmc3,
-
-	/* Universal Devices */
-	&universal_gpio_keys,
-	&s5p_device_onenand,
-};
-
-static void __init universal_map_io(void)
-{
-	s5p_init_io(NULL, 0, S5P_VA_CHIPID);
-	s3c24xx_init_clocks(24000000);
-	s3c24xx_init_uarts(universal_uartcfgs, ARRAY_SIZE(universal_uartcfgs));
-}
-
-static void __init universal_machine_init(void)
-{
-	universal_sdhci_init();
-
-	i2c_register_board_info(0, i2c0_devs, ARRAY_SIZE(i2c0_devs));
-	i2c_register_board_info(1, i2c1_devs, ARRAY_SIZE(i2c1_devs));
-
-	/* Last */
-	platform_add_devices(universal_devices, ARRAY_SIZE(universal_devices));
-}
-
-MACHINE_START(UNIVERSAL_C210, "UNIVERSAL_C210")
-	/* Maintainer: Kyungmin Park <kyungmin.park@samsung.com> */
-	.boot_params	= S5P_PA_SDRAM + 0x100,
-	.init_irq	= s5pv310_init_irq,
-	.map_io		= universal_map_io,
-	.init_machine	= universal_machine_init,
-	.timer		= &s5pv310_timer,
-MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,43 +0,0 @@
-# arch/arm/mach-s5pv310/Makefile
-#
-# Copyright (c) 2010 Samsung Electronics Co., Ltd.
-#		http://www.samsung.com/
-#
-# Licensed under GPLv2
-
-obj-y				:=
-obj-m				:=
-obj-n				:=
-obj-				:=
-
-# Core support for S5PV310 system
-
-obj-$(CONFIG_CPU_S5PV310)	+= cpu.o init.o clock.o irq-combiner.o
-obj-$(CONFIG_CPU_S5PV310)	+= setup-i2c0.o time.o gpiolib.o irq-eint.o dma.o
-obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
-
-obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
-obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
-
-# machine support
-
-obj-$(CONFIG_MACH_SMDKC210)	+= mach-smdkc210.o
-obj-$(CONFIG_MACH_SMDKV310)	+= mach-smdkv310.o
-obj-$(CONFIG_MACH_UNIVERSAL_C210)	+= mach-universal_c210.o
-
-# device support
-
-obj-y					+= dev-audio.o
-obj-$(CONFIG_S5PV310_DEV_PD)		+= dev-pd.o
-obj-$(CONFIG_S5PV310_DEV_SYSMMU)	+= dev-sysmmu.o
-
-obj-$(CONFIG_S5PV310_SETUP_I2C1)	+= setup-i2c1.o
-obj-$(CONFIG_S5PV310_SETUP_I2C2)	+= setup-i2c2.o
-obj-$(CONFIG_S5PV310_SETUP_I2C3)	+= setup-i2c3.o
-obj-$(CONFIG_S5PV310_SETUP_I2C4)	+= setup-i2c4.o
-obj-$(CONFIG_S5PV310_SETUP_I2C5)	+= setup-i2c5.o
-obj-$(CONFIG_S5PV310_SETUP_I2C6)	+= setup-i2c6.o
-obj-$(CONFIG_S5PV310_SETUP_I2C7)	+= setup-i2c7.o
-obj-$(CONFIG_S5PV310_SETUP_SDHCI)	+= setup-sdhci.o
-obj-$(CONFIG_S5PV310_SETUP_SDHCI_GPIO)	+= setup-sdhci-gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/Makefile.boot linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/Makefile.boot
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/Makefile.boot	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
@@ -1,2 +0,0 @@
-   zreladdr-y	:= 0x40008000
-params_phys-y	:= 0x40000100
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/platsmp.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/platsmp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/platsmp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/platsmp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,172 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/platsmp.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Cloned from linux/arch/arm/mach-vexpress/platsmp.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/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
-#include <linux/smp.h>
-#include <linux/io.h>
-
-#include <asm/cacheflush.h>
-#include <asm/smp_scu.h>
-#include <asm/unified.h>
-
-#include <mach/hardware.h>
-#include <mach/regs-clock.h>
-
-extern void s5pv310_secondary_startup(void);
-
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-
-volatile int __cpuinitdata pen_release = -1;
-
-/*
- * Write pen_release in a way that is guaranteed to be visible to all
- * observers, irrespective of whether they're taking part in coherency
- * or not.  This is necessary for the hotplug code to work reliably.
- */
-static void write_pen_release(int val)
-{
-	pen_release = val;
-	smp_wmb();
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
-}
-
-static void __iomem *scu_base_addr(void)
-{
-	return (void __iomem *)(S5P_VA_SCU);
-}
-
-static DEFINE_SPINLOCK(boot_lock);
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
-{
-	/*
-	 * 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_secondary_init(0);
-
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	write_pen_release(-1);
-
-	/*
-	 * 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);
-
-	/*
-	 * The secondary processor is waiting to be released from
-	 * the holding pen - release it, then wait for it to flag
-	 * that it has been released by resetting pen_release.
-	 *
-	 * Note that "pen_release" is the hardware CPU ID, whereas
-	 * "cpu" is Linux's internal ID.
-	 */
-	write_pen_release(cpu);
-
-	/*
-	 * Send the secondary CPU a soft interrupt, thereby causing
-	 * the boot monitor to read the system wide flags register,
-	 * and branch to the address found there.
-	 */
-	smp_cross_call(cpumask_of(cpu), 1);
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
-
-/*
- * 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)
-{
-	void __iomem *scu_base = scu_base_addr();
-	unsigned int i, ncores;
-
-	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-
-	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "S5PV310: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-}
-
-void __init platform_smp_prepare_cpus(unsigned int max_cpus)
-{
-	int i;
-
-	/*
-	 * 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);
-
-	scu_enable(scu_base_addr());
-
-	/*
-	 * Write the address of secondary startup into the
-	 * system-wide flags register. The boot monitor waits
-	 * until it receives a soft interrupt, and then the
-	 * secondary CPU branches to this address.
-	 */
-	__raw_writel(BSYM(virt_to_phys(s5pv310_secondary_startup)), S5P_VA_SYSRAM);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c0.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c0.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c0.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c0.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * I2C0 GPIO configuration.
- *
- * Based on plat-s3c64xx/setup-i2c0.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.
-*/
-
-struct platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c0_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPD1(0), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c1.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c1.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c1.c
- *
- * Copyright (C) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C1 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c1_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPD1(2), 2,
-			      S3C_GPIO_SFN(2), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c2.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c2.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c2.c
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *
- * I2C2 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c2_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPA0(6), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c3.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c3.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c3.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C3 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c3_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPA1(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c4.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c4.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c4.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c4.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C4 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c4_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPB(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c5.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c5.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c5.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c5.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c5.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C5 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c5_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPB(6), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c6.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c6.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c6.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c6.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c6.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C6 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c6_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPC1(3), 2,
-			      S3C_GPIO_SFN(4), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c7.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c7.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-i2c7.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-i2c7.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,23 +0,0 @@
-/*
- * linux/arch/arm/mach-s5pv310/setup-i2c7.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *
- * I2C7 GPIO configuration.
- *
- * 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 platform_device; /* don't need the contents */
-
-#include <linux/gpio.h>
-#include <plat/iic.h>
-#include <plat/gpio-cfg.h>
-
-void s3c_i2c7_cfg_gpio(struct platform_device *dev)
-{
-	s3c_gpio_cfgall_range(S5PV310_GPD0(2), 2,
-			      S3C_GPIO_SFN(3), S3C_GPIO_PULL_UP);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-sdhci.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-sdhci.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-sdhci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-sdhci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/setup-sdhci.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - 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>
-
-/* clock sources for the mmc bus clock, order as for the ctrl2[5..4] */
-
-char *s5pv310_hsmmc_clksrcs[4] = {
-	[0] = NULL,
-	[1] = NULL,
-	[2] = "sclk_mmc",	/* mmc_bus */
-	[3] = NULL,
-};
-
-void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev, void __iomem *r,
-				  struct mmc_ios *ios, struct mmc_card *card)
-{
-	u32 ctrl2, ctrl3;
-
-	/* don't need to alter anything acording to card-type */
-
-	ctrl2 = readl(r + S3C_SDHCI_CONTROL2);
-
-	/* select base clock source to HCLK */
-
-	ctrl2 &= S3C_SDHCI_CTRL2_SELBASECLK_MASK;
-
-	/*
-	 * clear async mode, enable conflict mask, rx feedback ctrl, SD
-	 * clk hold and no use debounce count
-	 */
-
-	ctrl2 |= (S3C64XX_SDHCI_CTRL2_ENSTAASYNCCLR |
-		  S3C64XX_SDHCI_CTRL2_ENCMDCNFMSK |
-		  S3C_SDHCI_CTRL2_ENFBCLKRX |
-		  S3C_SDHCI_CTRL2_DFCNT_NONE |
-		  S3C_SDHCI_CTRL2_ENCLKOUTHOLD);
-
-	/* Tx and Rx feedback clock delay control */
-
-	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);
-
-	writel(ctrl2, r + S3C_SDHCI_CONTROL2);
-	writel(ctrl3, r + S3C_SDHCI_CONTROL3);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-sdhci-gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/setup-sdhci-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/setup-sdhci-gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,152 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/setup-sdhci-gpio.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * S5PV310 - 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 <linux/gpio.h>
-#include <linux/mmc/host.h>
-#include <linux/mmc/card.h>
-
-#include <plat/gpio-cfg.h>
-#include <plat/regs-sdhci.h>
-#include <plat/sdhci.h>
-
-void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK0[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK0(0); gpio < S5PV310_GPK0(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	switch (width) {
-	case 8:
-		for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) {
-			/* Data pin GPK1[3:6] to special-funtion 3 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	case 4:
-		for (gpio = S5PV310_GPK0(3); gpio <= S5PV310_GPK0(6); gpio++) {
-			/* Data pin GPK0[3:6] to special-funtion 2 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK0(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK0(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK1[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK1(0); gpio < S5PV310_GPK1(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	for (gpio = S5PV310_GPK1(3); gpio <= S5PV310_GPK1(6); gpio++) {
-		/* Data pin GPK1[3:6] to special-function 2 */
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK1(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK1(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK2[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK2(0); gpio < S5PV310_GPK2(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	switch (width) {
-	case 8:
-		for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) {
-			/* Data pin GPK3[3:6] to special-function 3 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(3));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	case 4:
-		for (gpio = S5PV310_GPK2(3); gpio <= S5PV310_GPK2(6); gpio++) {
-			/* Data pin GPK2[3:6] to special-function 2 */
-			s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-			s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-			s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-		}
-	default:
-		break;
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK2(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK2(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
-
-void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *dev, int width)
-{
-	struct s3c_sdhci_platdata *pdata = dev->dev.platform_data;
-	unsigned int gpio;
-
-	/* Set all the necessary GPK3[0:1] pins to special-function 2 */
-	for (gpio = S5PV310_GPK3(0); gpio < S5PV310_GPK3(2); gpio++) {
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_NONE);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	for (gpio = S5PV310_GPK3(3); gpio <= S5PV310_GPK3(6); gpio++) {
-		/* Data pin GPK3[3:6] to special-function 2 */
-		s3c_gpio_cfgpin(gpio, S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(gpio, S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-
-	if (pdata->cd_type == S3C_SDHCI_CD_INTERNAL) {
-		s3c_gpio_cfgpin(S5PV310_GPK3(2), S3C_GPIO_SFN(2));
-		s3c_gpio_setpull(S5PV310_GPK3(2), S3C_GPIO_PULL_UP);
-		s5p_gpio_set_drvstr(gpio, S5P_GPIO_DRVSTR_LV4);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/time.c linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/time.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-s5pv310/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-s5pv310/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,283 +0,0 @@
-/* linux/arch/arm/mach-s5pv310/time.c
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * S5PV310 (and compatible) HRT support
- * PWM 2/4 is used for this feature
- *
- * 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/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/err.h>
-#include <linux/clk.h>
-#include <linux/clockchips.h>
-#include <linux/platform_device.h>
-
-#include <asm/smp_twd.h>
-
-#include <mach/map.h>
-#include <plat/regs-timer.h>
-#include <asm/mach/time.h>
-
-static unsigned long clock_count_per_tick;
-
-static struct clk *tin2;
-static struct clk *tin4;
-static struct clk *tdiv2;
-static struct clk *tdiv4;
-static struct clk *timerclk;
-
-static void s5pv310_pwm_stop(unsigned int pwm_id)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	switch (pwm_id) {
-	case 2:
-		tcon &= ~S3C2410_TCON_T2START;
-		break;
-	case 4:
-		tcon &= ~S3C2410_TCON_T4START;
-		break;
-	default:
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static void s5pv310_pwm_init(unsigned int pwm_id, unsigned long tcnt)
-{
-	unsigned long tcon;
-
-	tcon = __raw_readl(S3C2410_TCON);
-
-	/* timers reload after counting zero, so reduce the count by 1 */
-	tcnt--;
-
-	/* ensure timer is stopped... */
-	switch (pwm_id) {
-	case 2:
-		tcon &= ~(0xf<<12);
-		tcon |= S3C2410_TCON_T2MANUALUPD;
-
-		__raw_writel(tcnt, S3C2410_TCNTB(2));
-		__raw_writel(tcnt, S3C2410_TCMPB(2));
-		__raw_writel(tcon, S3C2410_TCON);
-
-		break;
-	case 4:
-		tcon &= ~(7<<20);
-		tcon |= S3C2410_TCON_T4MANUALUPD;
-
-		__raw_writel(tcnt, S3C2410_TCNTB(4));
-		__raw_writel(tcnt, S3C2410_TCMPB(4));
-		__raw_writel(tcon, S3C2410_TCON);
-
-		break;
-	default:
-		break;
-	}
-}
-
-static inline void s5pv310_pwm_start(unsigned int pwm_id, bool periodic)
-{
-	unsigned long tcon;
-
-	tcon  = __raw_readl(S3C2410_TCON);
-
-	switch (pwm_id) {
-	case 2:
-		tcon |= S3C2410_TCON_T2START;
-		tcon &= ~S3C2410_TCON_T2MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T2RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T2RELOAD;
-		break;
-	case 4:
-		tcon |= S3C2410_TCON_T4START;
-		tcon &= ~S3C2410_TCON_T4MANUALUPD;
-
-		if (periodic)
-			tcon |= S3C2410_TCON_T4RELOAD;
-		else
-			tcon &= ~S3C2410_TCON_T4RELOAD;
-		break;
-	default:
-		break;
-	}
-	__raw_writel(tcon, S3C2410_TCON);
-}
-
-static int s5pv310_pwm_set_next_event(unsigned long cycles,
-					struct clock_event_device *evt)
-{
-	s5pv310_pwm_init(2, cycles);
-	s5pv310_pwm_start(2, 0);
-	return 0;
-}
-
-static void s5pv310_pwm_set_mode(enum clock_event_mode mode,
-				struct clock_event_device *evt)
-{
-	s5pv310_pwm_stop(2);
-
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-		s5pv310_pwm_init(2, clock_count_per_tick);
-		s5pv310_pwm_start(2, 1);
-		break;
-	case CLOCK_EVT_MODE_ONESHOT:
-		break;
-	case CLOCK_EVT_MODE_UNUSED:
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_RESUME:
-		break;
-	}
-}
-
-static struct clock_event_device pwm_event_device = {
-	.name		= "pwm_timer2",
-	.features       = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.shift		= 32,
-	.set_next_event	= s5pv310_pwm_set_next_event,
-	.set_mode	= s5pv310_pwm_set_mode,
-};
-
-irqreturn_t s5pv310_clock_event_isr(int irq, void *dev_id)
-{
-	struct clock_event_device *evt = &pwm_event_device;
-
-	evt->event_handler(evt);
-
-	return IRQ_HANDLED;
-}
-
-static struct irqaction s5pv310_clock_event_irq = {
-	.name		= "pwm_timer2_irq",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= s5pv310_clock_event_isr,
-};
-
-static void __init s5pv310_clockevent_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-	struct clk *tscaler;
-
-	pclk = clk_get_rate(timerclk);
-
-	/* configure clock tick */
-
-	tscaler = clk_get_parent(tdiv2);
-
-	clk_set_rate(tscaler, pclk / 2);
-	clk_set_rate(tdiv2, pclk / 2);
-	clk_set_parent(tin2, tdiv2);
-
-	clock_rate = clk_get_rate(tin2);
-
-	clock_count_per_tick = clock_rate / HZ;
-
-	pwm_event_device.mult =
-		div_sc(clock_rate, NSEC_PER_SEC, pwm_event_device.shift);
-	pwm_event_device.max_delta_ns =
-		clockevent_delta2ns(-1, &pwm_event_device);
-	pwm_event_device.min_delta_ns =
-		clockevent_delta2ns(1, &pwm_event_device);
-
-	pwm_event_device.cpumask = cpumask_of(0);
-	clockevents_register_device(&pwm_event_device);
-
-	setup_irq(IRQ_TIMER2, &s5pv310_clock_event_irq);
-}
-
-static cycle_t s5pv310_pwm4_read(struct clocksource *cs)
-{
-	return (cycle_t) ~__raw_readl(S3C_TIMERREG(0x40));
-}
-
-struct clocksource pwm_clocksource = {
-	.name		= "pwm_timer4",
-	.rating		= 250,
-	.read		= s5pv310_pwm4_read,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS ,
-};
-
-static void __init s5pv310_clocksource_init(void)
-{
-	unsigned long pclk;
-	unsigned long clock_rate;
-
-	pclk = clk_get_rate(timerclk);
-
-	clk_set_rate(tdiv4, pclk / 2);
-	clk_set_parent(tin4, tdiv4);
-
-	clock_rate = clk_get_rate(tin4);
-
-	s5pv310_pwm_init(4, ~0);
-	s5pv310_pwm_start(4, 1);
-
-	if (clocksource_register_hz(&pwm_clocksource, clock_rate))
-		panic("%s: can't register clocksource\n", pwm_clocksource.name);
-}
-
-static void __init s5pv310_timer_resources(void)
-{
-	struct platform_device tmpdev;
-
-	tmpdev.dev.bus = &platform_bus_type;
-
-	timerclk = clk_get(NULL, "timers");
-	if (IS_ERR(timerclk))
-		panic("failed to get timers clock for system timer");
-
-	clk_enable(timerclk);
-
-	tmpdev.id = 2;
-	tin2 = clk_get(&tmpdev.dev, "pwm-tin");
-	if (IS_ERR(tin2))
-		panic("failed to get pwm-tin2 clock for system timer");
-
-	tdiv2 = clk_get(&tmpdev.dev, "pwm-tdiv");
-	if (IS_ERR(tdiv2))
-		panic("failed to get pwm-tdiv2 clock for system timer");
-	clk_enable(tin2);
-
-	tmpdev.id = 4;
-	tin4 = clk_get(&tmpdev.dev, "pwm-tin");
-	if (IS_ERR(tin4))
-		panic("failed to get pwm-tin4 clock for system timer");
-
-	tdiv4 = clk_get(&tmpdev.dev, "pwm-tdiv");
-	if (IS_ERR(tdiv4))
-		panic("failed to get pwm-tdiv4 clock for system timer");
-
-	clk_enable(tin4);
-}
-
-static void __init s5pv310_timer_init(void)
-{
-#ifdef CONFIG_LOCAL_TIMERS
-	twd_base = S5P_VA_TWD;
-#endif
-
-	s5pv310_timer_resources();
-	s5pv310_clockevent_init();
-	s5pv310_clocksource_init();
-}
-
-struct sys_timer s5pv310_timer = {
-	.init		= s5pv310_timer_init,
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/cerf.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/cerf.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/cerf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/cerf.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 static void __init cerf_init_irq(void)
 {
 	sa1100_init_irq();
-	set_irq_type(CERF_ETH_IRQ, IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(CERF_ETH_IRQ, IRQ_TYPE_EDGE_RISING);
 }
 
 static struct map_desc cerf_io_desc[] __initdata = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/cpu-sa1100.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/cpu-sa1100.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/cpu-sa1100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/cpu-sa1100.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,7 +68,7 @@
  * clock change in ROM and jump to that code from the kernel. The main
  * disadvantage is that the ROM has to be modified, which is not
  * possible on all SA-1100 platforms. Another disadvantage is that
- * jumping to ROM makes clock switching unecessary complicated.
+ * jumping to ROM makes clock switching unnecessary complicated.
  *
  * The idea behind this driver is that the memory configuration can be
  * changed while running from DRAM (even with interrupts turned on!)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset is 0xc0000000 on the SA1100
  */
-#define PHYS_OFFSET	UL(0xc0000000)
+#define PLAT_PHYS_OFFSET	UL(0xc0000000)
 
 #ifndef __ASSEMBLY__
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/include/mach/SA-1100.h linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/include/mach/SA-1100.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/include/mach/SA-1100.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/include/mach/SA-1100.h	2011-05-19 00:06:34.000000000 -0400
@@ -1794,7 +1794,7 @@
                 	(DDAR_DevRd + DDAR_Brst4 + DDAR_16BitDev + \
                 	 DDAR_Ser4SSPRc + DDAR_DevAdd (__PREG(Ser4SSDR)))
 
-#define DCSR_RUN	0x00000001	/* DMA RUNing                      */
+#define DCSR_RUN	0x00000001	/* DMA running                     */
 #define DCSR_IE 	0x00000002	/* DMA Interrupt Enable            */
 #define DCSR_ERROR	0x00000004	/* DMA ERROR                       */
 #define DCSR_DONEA	0x00000008	/* DONE DMA transfer buffer A      */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -323,28 +323,28 @@
 	ICCR = 1;
 
 	for (irq = 0; irq <= 10; irq++) {
-		set_irq_chip(irq, &sa1100_low_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &sa1100_low_gpio_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	for (irq = 12; irq <= 31; irq++) {
-		set_irq_chip(irq, &sa1100_normal_chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &sa1100_normal_chip,
+					 handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
 	for (irq = 32; irq <= 48; irq++) {
-		set_irq_chip(irq, &sa1100_high_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &sa1100_high_gpio_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	/*
 	 * Install handler for GPIO 11-27 edge detect interrupts
 	 */
-	set_irq_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
-	set_irq_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
+	irq_set_chip(IRQ_GPIO11_27, &sa1100_normal_chip);
+	irq_set_chained_handler(IRQ_GPIO11_27, sa1100_high_gpio_handler);
 
 	sa1100_init_gpio();
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/jornada720_ssp.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/jornada720_ssp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/jornada720_ssp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/jornada720_ssp.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 /**
  * jornada_ssp_reverse - reverses input byte
  *
- * we need to reverse all data we recieve from the mcu due to its physical location
+ * we need to reverse all data we receive from the mcu due to its physical location
  * returns : 01110111 -> 11101110
  */
 u8 inline jornada_ssp_reverse(u8 byte)
@@ -179,7 +179,7 @@
 
 static int jornada_ssp_remove(struct platform_device *dev)
 {
-	/* Note that this doesnt actually remove the driver, since theres nothing to remove
+	/* Note that this doesn't actually remove the driver, since theres nothing to remove
 	 * It just makes sure everything is turned off */
 	GPSR = GPIO_GPIO25;
 	ssp_exit();
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 # LEDs support
 obj-$(CONFIG_LEDS) += $(led-y)
 
-# Miscelaneous functions
+# Miscellaneous functions
 obj-$(CONFIG_PM)			+= pm.o sleep.o
 obj-$(CONFIG_SA1100_SSP)		+= ssp.o
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/neponset.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/neponset.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/neponset.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/neponset.c	2011-05-19 00:06:34.000000000 -0400
@@ -145,8 +145,8 @@
 	/*
 	 * Install handler for GPIO25.
 	 */
-	set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
-	set_irq_chained_handler(IRQ_GPIO25, neponset_irq_handler);
+	irq_set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
+	irq_set_chained_handler(IRQ_GPIO25, neponset_irq_handler);
 
 	/*
 	 * We would set IRQ_GPIO25 to be a wake-up IRQ, but
@@ -161,9 +161,9 @@
 	 * Setup other Neponset IRQs.  SA1111 will be done by the
 	 * generic SA1111 code.
 	 */
-	set_irq_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
+	irq_set_handler(IRQ_NEPONSET_SMC9196, handle_simple_irq);
 	set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE);
-	set_irq_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
+	irq_set_handler(IRQ_NEPONSET_USAR, handle_simple_irq);
 	set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE);
 
 	/*
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/pleb.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/pleb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/pleb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/pleb.c	2011-05-19 00:06:34.000000000 -0400
@@ -142,7 +142,7 @@
 
 	GPDR &= ~GPIO_ETH0_IRQ;
 
-	set_irq_type(GPIO_ETH0_IRQ, IRQ_TYPE_EDGE_FALLING);
+	irq_set_irq_type(GPIO_ETH0_IRQ, IRQ_TYPE_EDGE_FALLING);
 }
 
 MACHINE_START(PLEB, "PLEB")
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/pm.c linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,8 +32,7 @@
 #include <asm/system.h>
 #include <asm/mach/time.h>
 
-extern void sa1100_cpu_suspend(void);
-extern void sa1100_cpu_resume(void);
+extern void sa1100_cpu_suspend(long);
 
 #define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
 #define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
@@ -73,10 +72,10 @@
 	RCSR = RCSR_HWR | RCSR_SWR | RCSR_WDR | RCSR_SMR;
 
 	/* set resume return address */
-	PSPR = virt_to_phys(sa1100_cpu_resume);
+	PSPR = virt_to_phys(cpu_resume);
 
 	/* go zzz */
-	sa1100_cpu_suspend();
+	sa1100_cpu_suspend(PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
 	cpu_init();
 
@@ -115,11 +114,6 @@
 	return 0;
 }
 
-unsigned long sleep_phys_sp(void *sp)
-{
-	return virt_to_phys(sp);
-}
-
 static const struct platform_suspend_ops sa11x0_pm_ops = {
 	.enter		= sa11x0_pm_enter,
 	.valid		= suspend_valid_only_mem,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/sleep.S linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-sa1100/sleep.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-sa1100/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -20,12 +20,7 @@
 #include <asm/assembler.h>
 #include <mach/hardware.h>
 
-
-
 		.text
-
-
-
 /*
  * sa1100_cpu_suspend()
  *
@@ -34,27 +29,10 @@
  */
 
 ENTRY(sa1100_cpu_suspend)
-
 	stmfd	sp!, {r4 - r12, lr}		@ save registers on stack
-
-	@ get coprocessor registers
-	mrc 	p15, 0, r4, c3, c0, 0		@ domain ID
-	mrc 	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mrc	p15, 0, r6, c13, c0, 0		@ PID
-	mrc 	p15, 0, r7, c1, c0, 0		@ control reg
-
-	@ store them plus current virtual stack ptr on stack
-	mov	r8, sp
-	stmfd	sp!, {r4 - r8}
-
-	@ preserve phys address of stack
-	mov	r0, sp
-	bl	sleep_phys_sp
-	ldr	r1, =sleep_save_sp
-	str	r0, [r1]
-
-	@ clean data cache and invalidate WB
-	bl	v4wb_flush_kern_cache_all
+	mov	r1, r0
+	ldr	r3, =sa1100_cpu_resume		@ return function
+	bl	cpu_suspend
 
 	@ disable clock switching
 	mcr	p15, 0, r1, c15, c2, 2
@@ -166,50 +144,8 @@
  * cpu_sa1100_resume()
  *
  * entry point from bootloader into kernel during resume
- *
- * Note: Yes, part of the following code is located into the .data section.
- *       This is to allow sleep_save_sp to be accessed with a relative load
- *       while we can't rely on any MMU translation.  We could have put
- *       sleep_save_sp in the .text section as well, but some setups might
- *       insist on it to be truly read-only.
  */
-
-	.data
 	.align 5
-ENTRY(sa1100_cpu_resume)
-	mov	r0, #PSR_F_BIT | PSR_I_BIT | SVC_MODE
-	msr	cpsr_c, r0			@ set SVC, irqs off
-
-	ldr	r0, sleep_save_sp		@ stack phys addr
-	ldr	r2, =resume_after_mmu		@ its absolute virtual address
-	ldmfd	r0, {r4 - r7, sp}		@ CP regs + virt stack ptr
-
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0   	@ flush I+D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
-	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
-	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
-
-	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
-	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
-	mcr	p15, 0, r6, c13, c0, 0		@ PID
-	b	resume_turn_on_mmu		@ cache align execution
-
-	.align 5
-resume_turn_on_mmu:
-	mcr 	p15, 0, r7, c1, c0, 0		@ turn on MMU, caches, etc.
-	nop
-	mov	pc, r2				@ jump to virtual addr
-	nop
-	nop
-	nop
-
-sleep_save_sp:
-	.word	0				@ preserve stack phys ptr here
-
-	.text
-resume_after_mmu:
+sa1100_cpu_resume:
 	mcr	p15, 0, r1, c15, c1, 2		@ enable clock switching
 	ldmfd	sp!, {r4 - r12, pc}		@ return to caller
-
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shark/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-shark/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-shark/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shark/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET     UL(0x08000000)
+#define PLAT_PHYS_OFFSET     UL(0x08000000)
 
 #ifndef __ASSEMBLY__
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shark/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-shark/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shark/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shark/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,8 +80,7 @@
 	int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++) {
-		set_irq_chip(irq, &fb_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &fb_chip, handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-ag5evm.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-ag5evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-ag5evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-ag5evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,13 +119,6 @@
 };
 
 /* FSI A */
-static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_OUT_SLAVE_MODE	|
-		       SH_FSI_IN_SLAVE_MODE	|
-		       SH_FSI_OFMT(I2S)		|
-		       SH_FSI_IFMT(I2S),
-};
-
 static struct resource fsi_resources[] = {
 	[0] = {
 		.name	= "FSI",
@@ -144,9 +137,6 @@
 	.id		= -1,
 	.num_resources	= ARRAY_SIZE(fsi_resources),
 	.resource	= fsi_resources,
-	.dev	= {
-		.platform_data	= &fsi_info,
-	},
 };
 
 static struct resource sh_mmcif_resources[] = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-ap4evb.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-ap4evb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-ap4evb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-ap4evb.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,9 +24,9 @@
 #include <linux/irq.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
@@ -312,7 +312,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start  = 0xe6850000,
-		.end    = 0xe68501ff,
+		.end    = 0xe68500ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -345,7 +345,7 @@
 	[0] = {
 		.name	= "SDHI1",
 		.start  = 0xe6860000,
-		.end    = 0xe68601ff,
+		.end    = 0xe68600ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -673,16 +673,12 @@
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OUT_SLAVE_MODE |
-		       SH_FSI_IN_SLAVE_MODE |
-		       SH_FSI_OFMT(PCM) |
-		       SH_FSI_IFMT(PCM),
+	.porta_flags = SH_FSI_BRS_INV,
 
 	.portb_flags = SH_FSI_BRS_INV |
 		       SH_FSI_BRM_INV |
 		       SH_FSI_LRS_INV |
-		       SH_FSI_OFMT(SPDIF),
+		       SH_FSI_FMT_SPDIF,
 	.set_rate = fsi_set_rate,
 };
 
@@ -783,6 +779,10 @@
 	},
 };
 
+static struct platform_device fsi_hdmi_device = {
+	.name		= "sh_fsi2_b_hdmi",
+};
+
 static long ap4evb_clk_optimize(unsigned long target, unsigned long *best_freq,
 				unsigned long *parent_freq)
 {
@@ -923,7 +923,8 @@
 	.num_resources	= ARRAY_SIZE(ceu_resources),
 	.resource	= ceu_resources,
 	.dev	= {
-		.platform_data	= &sh_mobile_ceu_info,
+		.platform_data		= &sh_mobile_ceu_info,
+		.coherent_dma_mask	= 0xffffffff,
 	},
 };
 
@@ -936,6 +937,7 @@
 	&usb1_host_device,
 	&fsi_device,
 	&fsi_ak4643_device,
+	&fsi_hdmi_device,
 	&sh_mmcif_device,
 	&lcdc1_device,
 	&lcdc_device,
@@ -945,7 +947,7 @@
 	&ap4evb_camera,
 };
 
-static int __init hdmi_init_pm_clock(void)
+static void __init hdmi_init_pm_clock(void)
 {
 	struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
 	int ret;
@@ -986,20 +988,15 @@
 	pr_debug("PLLC2 set frequency %lu\n", rate);
 
 	ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
-	if (ret < 0) {
+	if (ret < 0)
 		pr_err("Cannot set HDMI parent: %d\n", ret);
-		goto out;
-	}
 
 out:
 	if (!IS_ERR(hdmi_ick))
 		clk_put(hdmi_ick);
-	return ret;
 }
 
-device_initcall(hdmi_init_pm_clock);
-
-static int __init fsi_init_pm_clock(void)
+static void __init fsi_init_pm_clock(void)
 {
 	struct clk *fsia_ick;
 	int ret;
@@ -1008,7 +1005,7 @@
 	if (IS_ERR(fsia_ick)) {
 		ret = PTR_ERR(fsia_ick);
 		pr_err("Cannot get FSI ICK: %d\n", ret);
-		return ret;
+		return;
 	}
 
 	ret = clk_set_parent(fsia_ick, &sh7372_fsiack_clk);
@@ -1016,10 +1013,7 @@
 		pr_err("Cannot set FSI-A parent: %d\n", ret);
 
 	clk_put(fsia_ick);
-
-	return ret;
 }
-device_initcall(fsi_init_pm_clock);
 
 /*
  * FIXME !!
@@ -1253,7 +1247,7 @@
 	gpio_request(GPIO_FN_KEYIN4,     NULL);
 
 	/* enable TouchScreen */
-	set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ28, IRQ_TYPE_LEVEL_LOW);
 
 	tsc_device.irq = IRQ28;
 	i2c_register_board_info(1, &tsc_device, 1);
@@ -1309,7 +1303,7 @@
 	lcdc_info.ch[0].lcd_size_cfg.height	= 91;
 
 	/* enable TouchScreen */
-	set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
 
 	tsc_device.irq = IRQ7;
 	i2c_register_board_info(0, &tsc_device, 1);
@@ -1346,6 +1340,9 @@
 	__raw_writel(srcr4 & ~(1 << 13), SRCR4);
 
 	platform_add_devices(ap4evb_devices, ARRAY_SIZE(ap4evb_devices));
+
+	hdmi_init_pm_clock();
+	fsi_init_pm_clock();
 }
 
 static void __init ap4evb_timer_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-g4evm.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-g4evm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-g4evm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-g4evm.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
 #include <linux/mmc/host.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/gpio.h>
 #include <mach/sh7377.h>
 #include <mach/common.h>
@@ -205,7 +205,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start  = 0xe6d50000,
-		.end    = 0xe6d501ff,
+		.end    = 0xe6d50nff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -232,7 +232,7 @@
 	[0] = {
 		.name	= "SDHI1",
 		.start  = 0xe6d60000,
-		.end    = 0xe6d601ff,
+		.end    = 0xe6d600ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-mackerel.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-mackerel.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/board-mackerel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/board-mackerel.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,10 +32,10 @@
 #include <linux/io.h>
 #include <linux/i2c.h>
 #include <linux/leds.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/physmap.h>
@@ -295,6 +295,18 @@
 	},
 };
 
+static int mackerel_set_brightness(void *board_data, int brightness)
+{
+	gpio_set_value(GPIO_PORT31, brightness);
+
+	return 0;
+}
+
+static int mackerel_get_brightness(void *board_data)
+{
+	return gpio_get_value(GPIO_PORT31);
+}
+
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.clock_source = LCDC_CLK_BUS,
 	.ch[0] = {
@@ -307,6 +319,14 @@
 		.flags			= 0,
 		.lcd_size_cfg.width	= 152,
 		.lcd_size_cfg.height	= 91,
+		.board_cfg = {
+			.set_brightness = mackerel_set_brightness,
+			.get_brightness = mackerel_get_brightness,
+		},
+		.bl_info = {
+			.name = "sh_mobile_lcdc_bl",
+			.max_brightness = 1,
+		},
 	}
 };
 
@@ -399,7 +419,11 @@
 	},
 };
 
-static int __init hdmi_init_pm_clock(void)
+static struct platform_device fsi_hdmi_device = {
+	.name		= "sh_fsi2_b_hdmi",
+};
+
+static void __init hdmi_init_pm_clock(void)
 {
 	struct clk *hdmi_ick = clk_get(&hdmi_device.dev, "ick");
 	int ret;
@@ -443,17 +467,13 @@
 	pr_debug("PLLC2 set frequency %lu\n", rate);
 
 	ret = clk_set_parent(hdmi_ick, &sh7372_pllc2_clk);
-	if (ret < 0) {
+	if (ret < 0)
 		pr_err("Cannot set HDMI parent: %d\n", ret);
-		goto out;
-	}
 
 out:
 	if (!IS_ERR(hdmi_ick))
 		clk_put(hdmi_ick);
-	return ret;
 }
-device_initcall(hdmi_init_pm_clock);
 
 /* USB1 (Host) */
 static void usb1_host_port_power(int port, int power)
@@ -609,16 +629,12 @@
 }
 
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags =	SH_FSI_BRS_INV		|
-			SH_FSI_OUT_SLAVE_MODE	|
-			SH_FSI_IN_SLAVE_MODE	|
-			SH_FSI_OFMT(PCM)	|
-			SH_FSI_IFMT(PCM),
+	.porta_flags =	SH_FSI_BRS_INV,
 
 	.portb_flags =	SH_FSI_BRS_INV	|
 			SH_FSI_BRM_INV	|
 			SH_FSI_LRS_INV	|
-			SH_FSI_OFMT(SPDIF),
+			SH_FSI_FMT_SPDIF,
 
 	.set_rate = fsi_set_rate,
 };
@@ -670,7 +686,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start	= 0xe6850000,
-		.end	= 0xe68501ff,
+		.end	= 0xe68500ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -705,7 +721,7 @@
 	[0] = {
 		.name	= "SDHI1",
 		.start	= 0xe6860000,
-		.end	= 0xe68601ff,
+		.end	= 0xe68600ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -748,7 +764,7 @@
 	[0] = {
 		.name	= "SDHI2",
 		.start	= 0xe6870000,
-		.end	= 0xe68701ff,
+		.end	= 0xe68700ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -901,7 +917,8 @@
 	.num_resources	= ARRAY_SIZE(ceu_resources),
 	.resource	= ceu_resources,
 	.dev		= {
-		.platform_data	= &sh_mobile_ceu_info,
+		.platform_data		= &sh_mobile_ceu_info,
+		.coherent_dma_mask	= 0xffffffff,
 	},
 };
 
@@ -921,6 +938,7 @@
 	&leds_device,
 	&fsi_device,
 	&fsi_ak4643_device,
+	&fsi_hdmi_device,
 	&sdhi0_device,
 #if !defined(CONFIG_MMC_SH_MMCIF)
 	&sdhi1_device,
@@ -1058,7 +1076,7 @@
 	gpio_request(GPIO_FN_LCDDCK,   NULL);
 
 	gpio_request(GPIO_PORT31, NULL); /* backlight */
-	gpio_direction_output(GPIO_PORT31, 1);
+	gpio_direction_output(GPIO_PORT31, 0); /* off by default */
 
 	gpio_request(GPIO_PORT151, NULL); /* LCDDON */
 	gpio_direction_output(GPIO_PORT151, 1);
@@ -1102,15 +1120,15 @@
 
 	/* enable Keypad */
 	gpio_request(GPIO_FN_IRQ9_42,	NULL);
-	set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH);
+	irq_set_irq_type(IRQ9, IRQ_TYPE_LEVEL_HIGH);
 
 	/* enable Touchscreen */
 	gpio_request(GPIO_FN_IRQ7_40,	NULL);
-	set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
+	irq_set_irq_type(IRQ7, IRQ_TYPE_LEVEL_LOW);
 
 	/* enable Accelerometer */
 	gpio_request(GPIO_FN_IRQ21,	NULL);
-	set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
+	irq_set_irq_type(IRQ21, IRQ_TYPE_LEVEL_HIGH);
 
 	/* enable SDHI0 */
 	gpio_request(GPIO_FN_SDHICD0, NULL);
@@ -1196,6 +1214,8 @@
 	sh7372_add_standard_devices();
 
 	platform_add_devices(mackerel_devices, ARRAY_SIZE(mackerel_devices));
+
+	hdmi_init_pm_clock();
 }
 
 static void __init mackerel_timer_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __ASM_MACH_MEMORY_H
 #define __ASM_MACH_MEMORY_H
 
-#define PHYS_OFFSET	UL(CONFIG_MEMORY_START)
+#define PLAT_PHYS_OFFSET	UL(CONFIG_MEMORY_START)
 #define MEM_SIZE	UL(CONFIG_MEMORY_SIZE)
 
 /* DMA memory at 0xf6000000 - 0xffdfffff */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/mmc-ap4eb.h linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/mmc-ap4eb.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/mmc-ap4eb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/mmc-ap4eb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29 @@
+#ifndef MMC_AP4EB_H
+#define MMC_AP4EB_H
+
+#define PORT185CR      (void __iomem *)0xe60520b9
+#define PORT186CR      (void __iomem *)0xe60520ba
+#define PORT187CR      (void __iomem *)0xe60520bb
+#define PORT188CR      (void __iomem *)0xe60520bc
+
+#define PORTR191_160DR (void __iomem *)0xe6056014
+
+static inline void mmc_init_progress(void)
+{
+       /* Initialise LEDS1-4
+        * registers: PORT185CR-PORT188CR (LED1-LED4 Control)
+        * value:     0x10 - enable output
+        */
+       __raw_writeb(0x10, PORT185CR);
+       __raw_writeb(0x10, PORT186CR);
+       __raw_writeb(0x10, PORT187CR);
+       __raw_writeb(0x10, PORT188CR);
+}
+
+static inline void mmc_update_progress(int n)
+{
+	__raw_writel((__raw_readl(PORTR191_160DR) & ~(0xf << 25)) |
+		     (1 << (25 + n)), PORTR191_160DR);
+}
+
+#endif /* MMC_AP4EB_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/mmc.h linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/mmc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/mmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#ifndef MMC_H
+#define MMC_H
+
+/**************************************************
+ *
+ *		board specific settings
+ *
+ **************************************************/
+
+#ifdef CONFIG_MACH_AP4EVB
+#include "mach/mmc-ap4eb.h"
+#elif defined(CONFIG_MACH_MACKEREL)
+#include "mach/mmc-mackerel.h"
+#else
+#error "unsupported board."
+#endif
+
+#endif /* MMC_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/mmc-mackerel.h linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/mmc-mackerel.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/mmc-mackerel.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/mmc-mackerel.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+#ifndef MMC_MACKEREL_H
+#define MMC_MACKEREL_H
+
+#define PORT0CR      (void __iomem *)0xe6051000
+#define PORT1CR      (void __iomem *)0xe6051001
+#define PORT2CR      (void __iomem *)0xe6051002
+#define PORT159CR    (void __iomem *)0xe605009f
+
+#define PORTR031_000DR (void __iomem *)0xe6055000
+#define PORTL159_128DR (void __iomem *)0xe6054010
+
+static inline void mmc_init_progress(void)
+{
+       /* Initialise LEDS0-3
+        * registers: PORT0CR-PORT2CR,PORT159CR (LED0-LED3 Control)
+        * value:     0x10 - enable output
+        */
+       __raw_writeb(0x10, PORT0CR);
+       __raw_writeb(0x10, PORT1CR);
+       __raw_writeb(0x10, PORT2CR);
+       __raw_writeb(0x10, PORT159CR);
+}
+
+static inline void mmc_update_progress(int n)
+{
+	unsigned a = 0, b = 0;
+
+	if (n < 3)
+		a = 1 << n;
+	else
+		b = 1 << 31;
+
+	__raw_writel((__raw_readl(PORTR031_000DR) & ~0x7) | a,
+		     PORTR031_000DR);
+	__raw_writel((__raw_readl(PORTL159_128DR) & ~(1 << 31)) | b,
+		     PORTL159_128DR);
+}
+#endif /* MMC_MACKEREL_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/zboot.h linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/zboot.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/include/mach/zboot.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/include/mach/zboot.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #ifdef CONFIG_MACH_AP4EVB
 #define MACH_TYPE	MACH_TYPE_AP4EVB
 #include "mach/head-ap4evb.txt"
-#elif CONFIG_MACH_MACKEREL
+#elif defined(CONFIG_MACH_MACKEREL)
 #define MACH_TYPE	MACH_TYPE_MACKEREL
 #include "mach/head-mackerel.txt"
 #else
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/intc-sh7367.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/intc-sh7367.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/intc-sh7367.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/intc-sh7367.c	2011-05-19 00:06:34.000000000 -0400
@@ -421,7 +421,7 @@
 
 static void intcs_demux(unsigned int irq, struct irq_desc *desc)
 {
-	void __iomem *reg = (void *)get_irq_data(irq);
+	void __iomem *reg = (void *)irq_get_handler_data(irq);
 	unsigned int evtcodeas = ioread32(reg);
 
 	generic_handle_irq(intcs_evt2irq(evtcodeas));
@@ -435,6 +435,6 @@
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
-	set_irq_data(evt2irq(0xf80), (void *)intevtsa);
-	set_irq_chained_handler(evt2irq(0xf80), intcs_demux);
+	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
+	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/intc-sh7372.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/intc-sh7372.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/intc-sh7372.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/intc-sh7372.c	2011-05-19 00:06:34.000000000 -0400
@@ -601,7 +601,7 @@
 
 static void intcs_demux(unsigned int irq, struct irq_desc *desc)
 {
-	void __iomem *reg = (void *)get_irq_data(irq);
+	void __iomem *reg = (void *)irq_get_handler_data(irq);
 	unsigned int evtcodeas = ioread32(reg);
 
 	generic_handle_irq(intcs_evt2irq(evtcodeas));
@@ -615,6 +615,6 @@
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
-	set_irq_data(evt2irq(0xf80), (void *)intevtsa);
-	set_irq_chained_handler(evt2irq(0xf80), intcs_demux);
+	irq_set_handler_data(evt2irq(0xf80), (void *)intevtsa);
+	irq_set_chained_handler(evt2irq(0xf80), intcs_demux);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/intc-sh7377.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/intc-sh7377.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/intc-sh7377.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/intc-sh7377.c	2011-05-19 00:06:34.000000000 -0400
@@ -626,7 +626,7 @@
 
 static void intcs_demux(unsigned int irq, struct irq_desc *desc)
 {
-	void __iomem *reg = (void *)get_irq_data(irq);
+	void __iomem *reg = (void *)irq_get_handler_data(irq);
 	unsigned int evtcodeas = ioread32(reg);
 
 	generic_handle_irq(intcs_evt2irq(evtcodeas));
@@ -641,6 +641,6 @@
 	register_intc_controller(&intcs_desc);
 
 	/* demux using INTEVTSA */
-	set_irq_data(evt2irq(INTCS_INTVECT), (void *)intevtsa);
-	set_irq_chained_handler(evt2irq(INTCS_INTVECT), intcs_demux);
+	irq_set_handler_data(evt2irq(INTCS_INTVECT), (void *)intevtsa);
+	irq_set_chained_handler(evt2irq(INTCS_INTVECT), intcs_demux);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-shmobile/localtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-shmobile/localtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,8 +18,9 @@
 /*
  * Setup the local clock events for a CPU.
  */
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	evt->irq = 29;
 	twd_timer_setup(evt);
+	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,8 +13,8 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <mach/misc_regs.h>
 #include <plat/clock.h>
+#include <mach/misc_regs.h>
 
 /* root clks */
 /* 32 KHz oscillator clock */
@@ -39,18 +39,43 @@
 };
 
 /* clock derived from 24 MHz osc clk */
+/* pll masks structure */
+static struct pll_clk_masks pll1_masks = {
+	.mode_mask = PLL_MODE_MASK,
+	.mode_shift = PLL_MODE_SHIFT,
+	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
+	.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
+	.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
+	.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
+	.div_p_mask = PLL_DIV_P_MASK,
+	.div_p_shift = PLL_DIV_P_SHIFT,
+	.div_n_mask = PLL_DIV_N_MASK,
+	.div_n_shift = PLL_DIV_N_SHIFT,
+};
+
 /* pll1 configuration structure */
 static struct pll_clk_config pll1_config = {
 	.mode_reg = PLL1_CTR,
 	.cfg_reg = PLL1_FRQ,
+	.masks = &pll1_masks,
+};
+
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
 /* PLL1 clock */
 static struct clk pll1_clk = {
+	.flags = ENABLED_ON_INIT,
 	.pclk = &osc_24m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
-	.recalc = &pll1_clk_recalc,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
 	.private_data = &pll1_config,
 };
 
@@ -76,36 +101,83 @@
 	.recalc = &follow_parent,
 };
 
+/* ahb masks structure */
+static struct bus_clk_masks ahb_masks = {
+	.mask = PLL_HCLK_RATIO_MASK,
+	.shift = PLL_HCLK_RATIO_SHIFT,
+};
+
 /* ahb configuration structure */
 static struct bus_clk_config ahb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = PLL_HCLK_RATIO_MASK,
-	.shift = PLL_HCLK_RATIO_SHIFT,
+	.masks = &ahb_masks,
+};
+
+/* ahb rate configuration table, in ascending order of rates */
+struct bus_rate_tbl bus_rtbl[] = {
+	{.div = 3}, /* == parent divided by 4 */
+	{.div = 2}, /* == parent divided by 3 */
+	{.div = 1}, /* == parent divided by 2 */
+	{.div = 0}, /* == parent divided by 1 */
 };
 
 /* ahb clock */
 static struct clk ahb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &pll1_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &ahb_config,
 };
 
-/* uart configurations */
-static struct aux_clk_config uart_config = {
+/* auxiliary synthesizers masks */
+static struct aux_clk_masks aux_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = AUX_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = AUX_XSCALE_MASK,
+	.xscale_sel_shift = AUX_XSCALE_SHIFT,
+	.yscale_sel_mask = AUX_YSCALE_MASK,
+	.yscale_sel_shift = AUX_YSCALE_SHIFT,
+};
+
+/* uart synth configurations */
+static struct aux_clk_config uart_synth_config = {
 	.synth_reg = UART_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+	/* For PLL1 = 332 MHz */
+	{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
+	{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+	.en_reg = UART_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
+	.private_data = &uart_synth_config,
 };
 
 /* uart parents */
 static struct pclk_info uart_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &uart_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -123,25 +195,35 @@
 	.en_reg_bit = UART_CLK_ENB,
 	.pclk_sel = &uart_pclk_sel,
 	.pclk_sel_shift = UART_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &uart_config,
+	.recalc = &follow_parent,
 };
 
 /* firda configurations */
-static struct aux_clk_config firda_config = {
+static struct aux_clk_config firda_synth_config = {
 	.synth_reg = FIRDA_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* firda synth clock */
+static struct clk firda_synth_clk = {
+	.en_reg = FIRDA_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 1},
+	.private_data = &firda_synth_config,
 };
 
 /* firda parents */
 static struct pclk_info firda_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &firda_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -159,73 +241,155 @@
 	.en_reg_bit = FIRDA_CLK_ENB,
 	.pclk_sel = &firda_pclk_sel,
 	.pclk_sel_shift = FIRDA_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &firda_config,
+	.recalc = &follow_parent,
+};
+
+/* gpt synthesizer masks */
+static struct gpt_clk_masks gpt_masks = {
+	.mscale_sel_mask = GPT_MSCALE_MASK,
+	.mscale_sel_shift = GPT_MSCALE_SHIFT,
+	.nscale_sel_mask = GPT_NSCALE_MASK,
+	.nscale_sel_shift = GPT_NSCALE_SHIFT,
+};
+
+/* gpt rate configuration table, in ascending order of rates */
+struct gpt_rate_tbl gpt_rtbl[] = {
+	/* For pll1 = 332 MHz */
+	{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+	{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+	{.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* gpt0 synth clk config*/
+static struct gpt_clk_config gpt0_synth_config = {
+	.synth_reg = PRSC1_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt0_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt0_synth_config,
 };
 
 /* gpt parents */
-static struct pclk_info gpt_pclk_info[] = {
+static struct pclk_info gpt0_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &gpt0_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
 /* gpt parent select structure */
-static struct pclk_sel gpt_pclk_sel = {
-	.pclk_info = gpt_pclk_info,
-	.pclk_count = ARRAY_SIZE(gpt_pclk_info),
+static struct pclk_sel gpt0_pclk_sel = {
+	.pclk_info = gpt0_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
 	.pclk_sel_reg = PERIP_CLK_CFG,
 	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
-/* gpt0 configurations */
-static struct aux_clk_config gpt0_config = {
-	.synth_reg = PRSC1_CLK_CFG,
-};
-
 /* gpt0 timer clock */
 static struct clk gpt0_clk = {
 	.flags = ALWAYS_ENABLED,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt0_pclk_sel,
 	.pclk_sel_shift = GPT0_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt0_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt1 configurations */
-static struct aux_clk_config gpt1_config = {
+/* gpt1 synth clk configurations */
+static struct gpt_clk_config gpt1_synth_config = {
 	.synth_reg = PRSC2_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt1 synth clock */
+static struct clk gpt1_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt1_synth_config,
+};
+
+static struct pclk_info gpt1_pclk_info[] = {
+	{
+		.pclk = &gpt1_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt1_pclk_sel = {
+	.pclk_info = gpt1_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt1_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt1 timer clock */
 static struct clk gpt1_clk = {
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = GPT1_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt1_pclk_sel,
 	.pclk_sel_shift = GPT1_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt1_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt2 configurations */
-static struct aux_clk_config gpt2_config = {
+/* gpt2 synth clk configurations */
+static struct gpt_clk_config gpt2_synth_config = {
 	.synth_reg = PRSC3_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt1 synth clock */
+static struct clk gpt2_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt2_synth_config,
+};
+
+static struct pclk_info gpt2_pclk_info[] = {
+	{
+		.pclk = &gpt2_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt2_pclk_sel = {
+	.pclk_info = gpt2_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt2 timer clock */
 static struct clk gpt2_clk = {
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = GPT2_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt2_pclk_sel,
 	.pclk_sel_shift = GPT2_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt2_config,
+	.recalc = &follow_parent,
 };
 
 /* clock derived from pll3 clk */
@@ -245,26 +409,27 @@
 	.recalc = &follow_parent,
 };
 
-/* clcd clock */
-static struct clk clcd_clk = {
-	.flags = ALWAYS_ENABLED,
-	.pclk = &pll3_48m_clk,
-	.recalc = &follow_parent,
+/* clock derived from ahb clk */
+/* apb masks structure */
+static struct bus_clk_masks apb_masks = {
+	.mask = HCLK_PCLK_RATIO_MASK,
+	.shift = HCLK_PCLK_RATIO_SHIFT,
 };
 
-/* clock derived from ahb clk */
 /* apb configuration structure */
 static struct bus_clk_config apb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = HCLK_PCLK_RATIO_MASK,
-	.shift = HCLK_PCLK_RATIO_SHIFT,
+	.masks = &apb_masks,
 };
 
 /* apb clock */
 static struct clk apb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &ahb_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &apb_config,
 };
 
@@ -325,8 +490,17 @@
 	.recalc = &follow_parent,
 };
 
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+/* emi clock */
+static struct clk emi_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
 /* ssp clock */
-static struct clk ssp_clk = {
+static struct clk ssp0_clk = {
 	.pclk = &apb_clk,
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = SSP_CLK_ENB,
@@ -343,14 +517,145 @@
 
 static struct clk dummy_apb_pclk;
 
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
+	defined(CONFIG_MACH_SPEAR320)
+/* fsmc clock */
+static struct clk fsmc_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
+/* common clocks to spear310 and spear320 */
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+/* uart1 clock */
+static struct clk uart1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart2 clock */
+static struct clk uart2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
+
+/* common clocks to spear300 and spear320 */
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
+/* clcd clock */
+static struct clk clcd_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll3_48m_clk,
+	.recalc = &follow_parent,
+};
+
+/* sdhci clock */
+static struct clk sdhci_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+
+/* spear300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR300
+/* gpio1 clock */
+static struct clk gpio1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* keyboard clock */
+static struct clk kbd_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+#endif
+
+/* spear310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR310
+/* uart3 clock */
+static struct clk uart3_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart4 clock */
+static struct clk uart4_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* uart5 clock */
+static struct clk uart5_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
+/* spear320 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR320
+/* can0 clock */
+static struct clk can0_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* can1 clock */
+static struct clk can1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* i2c1 clock */
+static struct clk i2c1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &ahb_clk,
+	.recalc = &follow_parent,
+};
+
+/* ssp1 clock */
+static struct clk ssp1_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* ssp2 clock */
+static struct clk ssp2_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+
+/* pwm clock */
+static struct clk pwm_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &apb_clk,
+	.recalc = &follow_parent,
+};
+#endif
+
 /* array of all spear 3xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
-	{ .con_id = "apb_pclk",	.clk = &dummy_apb_pclk},
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{ .con_id = "osc_32k_clk",	.clk = &osc_32k_clk},
 	{ .con_id = "osc_24m_clk",	.clk = &osc_24m_clk},
 	/* clock derived from 32 KHz osc clk */
-	{ .dev_id = "rtc",		.clk = &rtc_clk},
+	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 24 MHz osc clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
@@ -358,18 +663,22 @@
 	/* clock derived from pll1 clk */
 	{ .con_id = "cpu_clk",		.clk = &cpu_clk},
 	{ .con_id = "ahb_clk",		.clk = &ahb_clk},
+	{ .con_id = "uart_synth_clk",	.clk = &uart_synth_clk},
+	{ .con_id = "firda_synth_clk",	.clk = &firda_synth_clk},
+	{ .con_id = "gpt0_synth_clk",	.clk = &gpt0_synth_clk},
+	{ .con_id = "gpt1_synth_clk",	.clk = &gpt1_synth_clk},
+	{ .con_id = "gpt2_synth_clk",	.clk = &gpt2_synth_clk},
 	{ .dev_id = "uart",		.clk = &uart_clk},
 	{ .dev_id = "firda",		.clk = &firda_clk},
 	{ .dev_id = "gpt0",		.clk = &gpt0_clk},
 	{ .dev_id = "gpt1",		.clk = &gpt1_clk},
 	{ .dev_id = "gpt2",		.clk = &gpt2_clk},
 	/* clock derived from pll3 clk */
-	{ .dev_id = "usbh",		.clk = &usbh_clk},
-	{ .dev_id = "usbd",		.clk = &usbd_clk},
-	{ .dev_id = "clcd",		.clk = &clcd_clk},
+	{ .dev_id = "designware_udc",   .clk = &usbd_clk},
+	{ .con_id = "usbh_clk",		.clk = &usbh_clk},
 	/* clock derived from ahb clk */
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
-	{ .dev_id = "i2c",		.clk = &i2c_clk},
+	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
 	{ .dev_id = "jpeg",		.clk = &jpeg_clk},
 	{ .dev_id = "gmac",		.clk = &gmac_clk},
@@ -377,8 +686,50 @@
 	{ .dev_id = "c3",		.clk = &c3_clk},
 	/* clock derived from apb clk */
 	{ .dev_id = "adc",		.clk = &adc_clk},
-	{ .dev_id = "ssp",		.clk = &ssp_clk},
+	{ .dev_id = "ssp-pl022.0",	.clk = &ssp0_clk},
 	{ .dev_id = "gpio",		.clk = &gpio_clk},
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+	{ .dev_id = "physmap-flash",	.clk = &emi_clk},
+#endif
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR310) || \
+	defined(CONFIG_MACH_SPEAR320)
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
+#endif
+
+/* common clocks to spear310 and spear320 */
+#if defined(CONFIG_MACH_SPEAR310) || defined(CONFIG_MACH_SPEAR320)
+	{ .dev_id = "uart1",		.clk = &uart1_clk},
+	{ .dev_id = "uart2",		.clk = &uart2_clk},
+#endif
+
+	/* common clock to spear300 and spear320 */
+#if defined(CONFIG_MACH_SPEAR300) || defined(CONFIG_MACH_SPEAR320)
+	{ .dev_id = "clcd",		.clk = &clcd_clk},
+	{ .dev_id = "sdhci",		.clk = &sdhci_clk},
+#endif /* CONFIG_MACH_SPEAR300 || CONFIG_MACH_SPEAR320 */
+
+	/* spear300 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR300
+	{ .dev_id = "gpio1",		.clk = &gpio1_clk},
+	{ .dev_id = "keyboard",		.clk = &kbd_clk},
+#endif
+
+	/* spear310 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR310
+	{ .dev_id = "uart3",		.clk = &uart3_clk},
+	{ .dev_id = "uart4",		.clk = &uart4_clk},
+	{ .dev_id = "uart5",		.clk = &uart5_clk},
+
+#endif
+	/* spear320 machine specific clock structures */
+#ifdef CONFIG_MACH_SPEAR320
+	{ .dev_id = "c_can_platform.0",	.clk = &can0_clk},
+	{ .dev_id = "c_can_platform.1",	.clk = &can1_clk},
+	{ .dev_id = "i2c_designware.1",	.clk = &i2c1_clk},
+	{ .dev_id = "ssp-pl022.1",	.clk = &ssp1_clk},
+	{ .dev_id = "ssp-pl022.2",	.clk = &ssp2_clk},
+	{ .dev_id = "pwm",		.clk = &pwm_clk},
+#endif
 };
 
 void __init clk_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/entry-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -11,9 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <mach/hardware.h>
-#include <mach/spear.h>
 #include <asm/hardware/vic.h>
+#include <mach/hardware.h>
 
 		.macro	disable_fiq
 		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/generic.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/generic.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/generic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/generic.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,11 +14,11 @@
 #ifndef __MACH_GENERIC_H
 #define __MACH_GENERIC_H
 
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
 #include <plat/padmux.h>
 
 /* spear3xx declarations */
@@ -33,14 +33,14 @@
 /* Add spear3xx family device structure declarations here */
 extern struct amba_device gpio_device;
 extern struct amba_device uart_device;
-extern struct sys_timer spear_sys_timer;
+extern struct sys_timer spear3xx_timer;
 
 /* Add spear3xx family function declarations here */
 void __init clk_init(void);
+void __init spear_setup_timer(void);
 void __init spear3xx_map_io(void);
 void __init spear3xx_init_irq(void);
 void __init spear3xx_init(void);
-void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size);
 
 /* pad mux declarations */
 #define PMX_FIRDA_MASK		(1 << 14)
@@ -129,12 +129,10 @@
 extern struct pmx_dev pmx_telecom_dac;
 extern struct pmx_dev pmx_telecom_i2s;
 extern struct pmx_dev pmx_telecom_boot_pins;
-extern struct pmx_dev pmx_telecom_sdio_4bit;
-extern struct pmx_dev pmx_telecom_sdio_8bit;
+extern struct pmx_dev pmx_telecom_sdhci_4bit;
+extern struct pmx_dev pmx_telecom_sdhci_8bit;
 extern struct pmx_dev pmx_gpio1;
 
-void spear300_pmx_init(void);
-
 /* Add spear300 machine function declarations here */
 void __init spear300_init(void);
 
@@ -154,8 +152,6 @@
 extern struct pmx_dev pmx_rs485_0_1;
 extern struct pmx_dev pmx_tdm0;
 
-void spear310_pmx_init(void);
-
 /* Add spear310 machine function declarations here */
 void __init spear310_init(void);
 
@@ -176,14 +172,14 @@
 extern struct pmx_dev pmx_emi;
 extern struct pmx_dev pmx_fsmc;
 extern struct pmx_dev pmx_spp;
-extern struct pmx_dev pmx_sdio;
+extern struct pmx_dev pmx_sdhci;
 extern struct pmx_dev pmx_i2s;
 extern struct pmx_dev pmx_uart1;
 extern struct pmx_dev pmx_uart1_modem;
 extern struct pmx_dev pmx_uart2;
 extern struct pmx_dev pmx_touchscreen;
 extern struct pmx_dev pmx_can;
-extern struct pmx_dev pmx_sdio_led;
+extern struct pmx_dev pmx_sdhci_led;
 extern struct pmx_dev pmx_pwm0;
 extern struct pmx_dev pmx_pwm1;
 extern struct pmx_dev pmx_pwm2;
@@ -195,8 +191,6 @@
 extern struct pmx_dev pmx_smii1;
 extern struct pmx_dev pmx_i2c1;
 
-void spear320_pmx_init(void);
-
 /* Add spear320 machine function declarations here */
 void __init spear320_init(void);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,9 @@
 #ifndef __MACH_HARDWARE_H
 #define __MACH_HARDWARE_H
 
+#include <plat/hardware.h>
+#include <mach/spear.h>
+
 /* Vitual to physical translation of statically mapped space */
 #define IO_ADDRESS(x)		(x | 0xF0000000)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,7 +69,7 @@
 #define IRQ_CLCD				IRQ_GEN_RAS_3
 
 /* IRQs sharing IRQ_INTRCOMM_RAS_ARM */
-#define IRQ_SDIO				IRQ_INTRCOMM_RAS_ARM
+#define IRQ_SDHCI				IRQ_INTRCOMM_RAS_ARM
 
 /* GPIO pins virtual irqs */
 #define SPEAR_GPIO_INT_BASE			(VIRQ_START + 9)
@@ -115,7 +115,7 @@
 #define VIRQ_SPP				(VIRQ_START + 2)
 
 /* IRQs sharing IRQ_GEN_RAS_2 */
-#define IRQ_SDIO				IRQ_GEN_RAS_2
+#define IRQ_SDHCI				IRQ_GEN_RAS_2
 
 /* IRQs sharing IRQ_GEN_RAS_3 */
 #define VIRQ_PLGPIO				(VIRQ_START + 3)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/misc_regs.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/misc_regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/misc_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/misc_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,16 +14,16 @@
 #ifndef __MACH_MISC_REGS_H
 #define __MACH_MISC_REGS_H
 
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
-#define MISC_BASE		VA_SPEAR3XX_ICM3_MISC_REG_BASE
+#define MISC_BASE		IOMEM(VA_SPEAR3XX_ICM3_MISC_REG_BASE)
 
-#define SOC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x000))
-#define DIAG_CFG_CTR		((unsigned int *)(MISC_BASE + 0x004))
-#define PLL1_CTR		((unsigned int *)(MISC_BASE + 0x008))
-#define PLL1_FRQ		((unsigned int *)(MISC_BASE + 0x00C))
-#define PLL1_MOD		((unsigned int *)(MISC_BASE + 0x010))
-#define PLL2_CTR		((unsigned int *)(MISC_BASE + 0x014))
+#define SOC_CFG_CTR		(MISC_BASE + 0x000)
+#define DIAG_CFG_CTR		(MISC_BASE + 0x004)
+#define PLL1_CTR		(MISC_BASE + 0x008)
+#define PLL1_FRQ		(MISC_BASE + 0x00C)
+#define PLL1_MOD		(MISC_BASE + 0x010)
+#define PLL2_CTR		(MISC_BASE + 0x014)
 /* PLL_CTR register masks */
 #define PLL_ENABLE		2
 #define PLL_MODE_SHIFT		4
@@ -33,7 +33,7 @@
 #define PLL_MODE_DITH_DSB	2
 #define PLL_MODE_DITH_SSB	3
 
-#define PLL2_FRQ		((unsigned int *)(MISC_BASE + 0x018))
+#define PLL2_FRQ		(MISC_BASE + 0x018)
 /* PLL FRQ register masks */
 #define PLL_DIV_N_SHIFT		0
 #define PLL_DIV_N_MASK		0xFF
@@ -44,16 +44,16 @@
 #define PLL_DITH_FDBK_M_SHIFT	16
 #define PLL_DITH_FDBK_M_MASK	0xFFFF
 
-#define PLL2_MOD		((unsigned int *)(MISC_BASE + 0x01C))
-#define PLL_CLK_CFG		((unsigned int *)(MISC_BASE + 0x020))
-#define CORE_CLK_CFG		((unsigned int *)(MISC_BASE + 0x024))
+#define PLL2_MOD		(MISC_BASE + 0x01C)
+#define PLL_CLK_CFG		(MISC_BASE + 0x020)
+#define CORE_CLK_CFG		(MISC_BASE + 0x024)
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
 #define PLL_HCLK_RATIO_MASK	0x3
 #define HCLK_PCLK_RATIO_SHIFT	8
 #define HCLK_PCLK_RATIO_MASK	0x3
 
-#define PERIP_CLK_CFG		((unsigned int *)(MISC_BASE + 0x028))
+#define PERIP_CLK_CFG		(MISC_BASE + 0x028)
 /* PERIP_CLK_CFG register masks */
 #define UART_CLK_SHIFT		4
 #define UART_CLK_MASK		0x1
@@ -63,10 +63,10 @@
 #define GPT1_CLK_SHIFT		11
 #define GPT2_CLK_SHIFT		12
 #define GPT_CLK_MASK		0x1
-#define AUX_CLK_PLL3_MASK	0
-#define AUX_CLK_PLL1_MASK	1
+#define AUX_CLK_PLL3_VAL	0
+#define AUX_CLK_PLL1_VAL	1
 
-#define PERIP1_CLK_ENB		((unsigned int *)(MISC_BASE + 0x02C))
+#define PERIP1_CLK_ENB		(MISC_BASE + 0x02C)
 /* PERIP1_CLK_ENB register masks */
 #define UART_CLK_ENB		3
 #define SSP_CLK_ENB		5
@@ -85,34 +85,35 @@
 #define USBH_CLK_ENB		25
 #define C3_CLK_ENB		31
 
-#define SOC_CORE_ID		((unsigned int *)(MISC_BASE + 0x030))
-#define RAS_CLK_ENB		((unsigned int *)(MISC_BASE + 0x034))
-#define PERIP1_SOF_RST		((unsigned int *)(MISC_BASE + 0x038))
+#define SOC_CORE_ID		(MISC_BASE + 0x030)
+#define RAS_CLK_ENB		(MISC_BASE + 0x034)
+#define PERIP1_SOF_RST		(MISC_BASE + 0x038)
 /* PERIP1_SOF_RST register masks */
 #define JPEG_SOF_RST		8
 
-#define SOC_USER_ID		((unsigned int *)(MISC_BASE + 0x03C))
-#define RAS_SOF_RST		((unsigned int *)(MISC_BASE + 0x040))
-#define PRSC1_CLK_CFG		((unsigned int *)(MISC_BASE + 0x044))
-#define PRSC2_CLK_CFG		((unsigned int *)(MISC_BASE + 0x048))
-#define PRSC3_CLK_CFG		((unsigned int *)(MISC_BASE + 0x04C))
+#define SOC_USER_ID		(MISC_BASE + 0x03C)
+#define RAS_SOF_RST		(MISC_BASE + 0x040)
+#define PRSC1_CLK_CFG		(MISC_BASE + 0x044)
+#define PRSC2_CLK_CFG		(MISC_BASE + 0x048)
+#define PRSC3_CLK_CFG		(MISC_BASE + 0x04C)
 /* gpt synthesizer register masks */
 #define GPT_MSCALE_SHIFT	0
 #define GPT_MSCALE_MASK		0xFFF
 #define GPT_NSCALE_SHIFT	12
 #define GPT_NSCALE_MASK		0xF
 
-#define AMEM_CLK_CFG		((unsigned int *)(MISC_BASE + 0x050))
-#define EXPI_CLK_CFG		((unsigned int *)(MISC_BASE + 0x054))
-#define CLCD_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x05C))
-#define FIRDA_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x060))
-#define UART_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x064))
-#define GMAC_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x068))
-#define RAS1_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x06C))
-#define RAS2_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x070))
-#define RAS3_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x074))
-#define RAS4_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x078))
+#define AMEM_CLK_CFG		(MISC_BASE + 0x050)
+#define EXPI_CLK_CFG		(MISC_BASE + 0x054)
+#define CLCD_CLK_SYNT		(MISC_BASE + 0x05C)
+#define FIRDA_CLK_SYNT		(MISC_BASE + 0x060)
+#define UART_CLK_SYNT		(MISC_BASE + 0x064)
+#define GMAC_CLK_SYNT		(MISC_BASE + 0x068)
+#define RAS1_CLK_SYNT		(MISC_BASE + 0x06C)
+#define RAS2_CLK_SYNT		(MISC_BASE + 0x070)
+#define RAS3_CLK_SYNT		(MISC_BASE + 0x074)
+#define RAS4_CLK_SYNT		(MISC_BASE + 0x078)
 /* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB		31
 #define AUX_EQ_SEL_SHIFT	30
 #define AUX_EQ_SEL_MASK		1
 #define AUX_EQ1_SEL		0
@@ -122,42 +123,42 @@
 #define AUX_YSCALE_SHIFT	0
 #define AUX_YSCALE_MASK		0xFFF
 
-#define ICM1_ARB_CFG		((unsigned int *)(MISC_BASE + 0x07C))
-#define ICM2_ARB_CFG		((unsigned int *)(MISC_BASE + 0x080))
-#define ICM3_ARB_CFG		((unsigned int *)(MISC_BASE + 0x084))
-#define ICM4_ARB_CFG		((unsigned int *)(MISC_BASE + 0x088))
-#define ICM5_ARB_CFG		((unsigned int *)(MISC_BASE + 0x08C))
-#define ICM6_ARB_CFG		((unsigned int *)(MISC_BASE + 0x090))
-#define ICM7_ARB_CFG		((unsigned int *)(MISC_BASE + 0x094))
-#define ICM8_ARB_CFG		((unsigned int *)(MISC_BASE + 0x098))
-#define ICM9_ARB_CFG		((unsigned int *)(MISC_BASE + 0x09C))
-#define DMA_CHN_CFG		((unsigned int *)(MISC_BASE + 0x0A0))
-#define USB2_PHY_CFG		((unsigned int *)(MISC_BASE + 0x0A4))
-#define GMAC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0A8))
-#define EXPI_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0AC))
-#define PRC1_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C0))
-#define PRC2_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C4))
-#define PRC3_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C8))
-#define PRC4_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0CC))
-#define PRC1_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D0))
-#define PRC2_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D4))
-#define PRC3_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D8))
-#define PRC4_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0DC))
-#define PWRDOWN_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0E0))
-#define COMPSSTL_1V8_CFG	((unsigned int *)(MISC_BASE + 0x0E4))
-#define COMPSSTL_2V5_CFG	((unsigned int *)(MISC_BASE + 0x0E8))
-#define COMPCOR_3V3_CFG		((unsigned int *)(MISC_BASE + 0x0EC))
-#define SSTLPAD_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F0))
-#define BIST1_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F4))
-#define BIST2_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F8))
-#define BIST3_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0FC))
-#define BIST4_CFG_CTR		((unsigned int *)(MISC_BASE + 0x100))
-#define BIST5_CFG_CTR		((unsigned int *)(MISC_BASE + 0x104))
-#define BIST1_STS_RES		((unsigned int *)(MISC_BASE + 0x108))
-#define BIST2_STS_RES		((unsigned int *)(MISC_BASE + 0x10C))
-#define BIST3_STS_RES		((unsigned int *)(MISC_BASE + 0x110))
-#define BIST4_STS_RES		((unsigned int *)(MISC_BASE + 0x114))
-#define BIST5_STS_RES		((unsigned int *)(MISC_BASE + 0x118))
-#define SYSERR_CFG_CTR		((unsigned int *)(MISC_BASE + 0x11C))
+#define ICM1_ARB_CFG		(MISC_BASE + 0x07C)
+#define ICM2_ARB_CFG		(MISC_BASE + 0x080)
+#define ICM3_ARB_CFG		(MISC_BASE + 0x084)
+#define ICM4_ARB_CFG		(MISC_BASE + 0x088)
+#define ICM5_ARB_CFG		(MISC_BASE + 0x08C)
+#define ICM6_ARB_CFG		(MISC_BASE + 0x090)
+#define ICM7_ARB_CFG		(MISC_BASE + 0x094)
+#define ICM8_ARB_CFG		(MISC_BASE + 0x098)
+#define ICM9_ARB_CFG		(MISC_BASE + 0x09C)
+#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
+#define USB2_PHY_CFG		(MISC_BASE + 0x0A4)
+#define GMAC_CFG_CTR		(MISC_BASE + 0x0A8)
+#define EXPI_CFG_CTR		(MISC_BASE + 0x0AC)
+#define PRC1_LOCK_CTR		(MISC_BASE + 0x0C0)
+#define PRC2_LOCK_CTR		(MISC_BASE + 0x0C4)
+#define PRC3_LOCK_CTR		(MISC_BASE + 0x0C8)
+#define PRC4_LOCK_CTR		(MISC_BASE + 0x0CC)
+#define PRC1_IRQ_CTR		(MISC_BASE + 0x0D0)
+#define PRC2_IRQ_CTR		(MISC_BASE + 0x0D4)
+#define PRC3_IRQ_CTR		(MISC_BASE + 0x0D8)
+#define PRC4_IRQ_CTR		(MISC_BASE + 0x0DC)
+#define PWRDOWN_CFG_CTR		(MISC_BASE + 0x0E0)
+#define COMPSSTL_1V8_CFG	(MISC_BASE + 0x0E4)
+#define COMPSSTL_2V5_CFG	(MISC_BASE + 0x0E8)
+#define COMPCOR_3V3_CFG		(MISC_BASE + 0x0EC)
+#define SSTLPAD_CFG_CTR		(MISC_BASE + 0x0F0)
+#define BIST1_CFG_CTR		(MISC_BASE + 0x0F4)
+#define BIST2_CFG_CTR		(MISC_BASE + 0x0F8)
+#define BIST3_CFG_CTR		(MISC_BASE + 0x0FC)
+#define BIST4_CFG_CTR		(MISC_BASE + 0x100)
+#define BIST5_CFG_CTR		(MISC_BASE + 0x104)
+#define BIST1_STS_RES		(MISC_BASE + 0x108)
+#define BIST2_STS_RES		(MISC_BASE + 0x10C)
+#define BIST3_STS_RES		(MISC_BASE + 0x110)
+#define BIST4_STS_RES		(MISC_BASE + 0x114)
+#define BIST5_STS_RES		(MISC_BASE + 0x118)
+#define SYSERR_CFG_CTR		(MISC_BASE + 0x11C)
 
 #endif /* __MACH_MISC_REGS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear300.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear300.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear300.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear300.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,11 +17,9 @@
 #define __MACH_SPEAR300_H
 
 /* Base address of various IPs */
-#define SPEAR300_TELECOM_BASE		0x50000000
-#define SPEAR300_TELECOM_SIZE		0x10000000
+#define SPEAR300_TELECOM_BASE		UL(0x50000000)
 
 /* Interrupt registers offsets and masks */
-#define SPEAR300_TELECOM_REG_SIZE	0x00010000
 #define INT_ENB_MASK_REG		0x54
 #define INT_STS_MASK_REG		0x58
 #define IT_PERS_S_IRQ_MASK		(1 << 0)
@@ -36,47 +34,20 @@
 
 #define SHIRQ_RAS1_MASK			0x1FF
 
-#define SPEAR300_CLCD_BASE		0x60000000
-#define SPEAR300_CLCD_SIZE		0x10000000
-
-#define SPEAR300_SDIO_BASE		0x70000000
-#define SPEAR300_SDIO_SIZE		0x10000000
-
-#define SPEAR300_NAND_0_BASE		0x80000000
-#define SPEAR300_NAND_0_SIZE		0x04000000
-
-#define SPEAR300_NAND_1_BASE		0x84000000
-#define SPEAR300_NAND_1_SIZE		0x04000000
-
-#define SPEAR300_NAND_2_BASE		0x88000000
-#define SPEAR300_NAND_2_SIZE		0x04000000
-
-#define SPEAR300_NAND_3_BASE		0x8c000000
-#define SPEAR300_NAND_3_SIZE		0x04000000
-
-#define SPEAR300_NOR_0_BASE		0x90000000
-#define SPEAR300_NOR_0_SIZE		0x01000000
-
-#define SPEAR300_NOR_1_BASE		0x91000000
-#define SPEAR300_NOR_1_SIZE		0x01000000
-
-#define SPEAR300_NOR_2_BASE		0x92000000
-#define SPEAR300_NOR_2_SIZE		0x01000000
-
-#define SPEAR300_NOR_3_BASE		0x93000000
-#define SPEAR300_NOR_3_SIZE		0x01000000
-
-#define SPEAR300_FSMC_BASE		0x94000000
-#define SPEAR300_FSMC_SIZE		0x05000000
-
-#define SPEAR300_SOC_CONFIG_BASE	0x99000000
-#define SPEAR300_SOC_CONFIG_SIZE	0x00000008
-
-#define SPEAR300_KEYBOARD_BASE		0xA0000000
-#define SPEAR300_KEYBOARD_SIZE		0x09000000
-
-#define SPEAR300_GPIO_BASE		0xA9000000
-#define SPEAR300_GPIO_SIZE		0x07000000
+#define SPEAR300_CLCD_BASE		UL(0x60000000)
+#define SPEAR300_SDHCI_BASE		UL(0x70000000)
+#define SPEAR300_NAND_0_BASE		UL(0x80000000)
+#define SPEAR300_NAND_1_BASE		UL(0x84000000)
+#define SPEAR300_NAND_2_BASE		UL(0x88000000)
+#define SPEAR300_NAND_3_BASE		UL(0x8c000000)
+#define SPEAR300_NOR_0_BASE		UL(0x90000000)
+#define SPEAR300_NOR_1_BASE		UL(0x91000000)
+#define SPEAR300_NOR_2_BASE		UL(0x92000000)
+#define SPEAR300_NOR_3_BASE		UL(0x93000000)
+#define SPEAR300_FSMC_BASE		UL(0x94000000)
+#define SPEAR300_SOC_CONFIG_BASE	UL(0x99000000)
+#define SPEAR300_KEYBOARD_BASE		UL(0xA0000000)
+#define SPEAR300_GPIO_BASE		UL(0xA9000000)
 
 #endif /* __MACH_SPEAR300_H */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear310.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear310.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear310.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear310.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,30 +16,18 @@
 #ifndef __MACH_SPEAR310_H
 #define __MACH_SPEAR310_H
 
-#define SPEAR310_NAND_BASE		0x40000000
-#define SPEAR310_NAND_SIZE		0x04000000
-
-#define SPEAR310_FSMC_BASE		0x44000000
-#define SPEAR310_FSMC_SIZE		0x01000000
-
-#define SPEAR310_UART1_BASE		0xB2000000
-#define SPEAR310_UART2_BASE		0xB2080000
-#define SPEAR310_UART3_BASE		0xB2100000
-#define SPEAR310_UART4_BASE		0xB2180000
-#define SPEAR310_UART5_BASE		0xB2200000
-#define SPEAR310_UART_SIZE		0x00080000
-
-#define SPEAR310_HDLC_BASE		0xB2800000
-#define SPEAR310_HDLC_SIZE		0x00800000
-
-#define SPEAR310_RS485_0_BASE		0xB3000000
-#define SPEAR310_RS485_0_SIZE		0x00800000
-
-#define SPEAR310_RS485_1_BASE		0xB3800000
-#define SPEAR310_RS485_1_SIZE		0x00800000
+#define SPEAR310_NAND_BASE		UL(0x40000000)
+#define SPEAR310_FSMC_BASE		UL(0x44000000)
+#define SPEAR310_UART1_BASE		UL(0xB2000000)
+#define SPEAR310_UART2_BASE		UL(0xB2080000)
+#define SPEAR310_UART3_BASE		UL(0xB2100000)
+#define SPEAR310_UART4_BASE		UL(0xB2180000)
+#define SPEAR310_UART5_BASE		UL(0xB2200000)
+#define SPEAR310_HDLC_BASE		UL(0xB2800000)
+#define SPEAR310_RS485_0_BASE		UL(0xB3000000)
+#define SPEAR310_RS485_1_BASE		UL(0xB3800000)
+#define SPEAR310_SOC_CONFIG_BASE	UL(0xB4000000)
 
-#define SPEAR310_SOC_CONFIG_BASE	0xB4000000
-#define SPEAR310_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
 #define SMII0_IRQ_MASK			(1 << 0)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear320.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear320.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear320.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear320.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,54 +16,25 @@
 #ifndef __MACH_SPEAR320_H
 #define __MACH_SPEAR320_H
 
-#define SPEAR320_EMI_CTRL_BASE		0x40000000
-#define SPEAR320_EMI_CTRL_SIZE		0x08000000
-
-#define SPEAR320_FSMC_BASE		0x4C000000
-#define SPEAR320_FSMC_SIZE		0x01000000
-
-#define SPEAR320_I2S_BASE		0x60000000
-#define SPEAR320_I2S_SIZE		0x10000000
-
-#define SPEAR320_SDIO_BASE		0x70000000
-#define SPEAR320_SDIO_SIZE		0x10000000
-
-#define SPEAR320_CLCD_BASE		0x90000000
-#define SPEAR320_CLCD_SIZE		0x10000000
-
-#define SPEAR320_PAR_PORT_BASE		0xA0000000
-#define SPEAR320_PAR_PORT_SIZE		0x01000000
-
-#define SPEAR320_CAN0_BASE		0xA1000000
-#define SPEAR320_CAN0_SIZE		0x01000000
-
-#define SPEAR320_CAN1_BASE		0xA2000000
-#define SPEAR320_CAN1_SIZE		0x01000000
-
-#define SPEAR320_UART1_BASE		0xA3000000
-#define SPEAR320_UART2_BASE		0xA4000000
-#define SPEAR320_UART_SIZE		0x01000000
-
-#define SPEAR320_SSP0_BASE		0xA5000000
-#define SPEAR320_SSP0_SIZE		0x01000000
-
-#define SPEAR320_SSP1_BASE		0xA6000000
-#define SPEAR320_SSP1_SIZE		0x01000000
-
-#define SPEAR320_I2C_BASE		0xA7000000
-#define SPEAR320_I2C_SIZE		0x01000000
-
-#define SPEAR320_PWM_BASE		0xA8000000
-#define SPEAR320_PWM_SIZE		0x01000000
-
-#define SPEAR320_SMII0_BASE		0xAA000000
-#define SPEAR320_SMII0_SIZE		0x01000000
-
-#define SPEAR320_SMII1_BASE		0xAB000000
-#define SPEAR320_SMII1_SIZE		0x01000000
+#define SPEAR320_EMI_CTRL_BASE		UL(0x40000000)
+#define SPEAR320_FSMC_BASE		UL(0x4C000000)
+#define SPEAR320_NAND_BASE		UL(0x50000000)
+#define SPEAR320_I2S_BASE		UL(0x60000000)
+#define SPEAR320_SDHCI_BASE		UL(0x70000000)
+#define SPEAR320_CLCD_BASE		UL(0x90000000)
+#define SPEAR320_PAR_PORT_BASE		UL(0xA0000000)
+#define SPEAR320_CAN0_BASE		UL(0xA1000000)
+#define SPEAR320_CAN1_BASE		UL(0xA2000000)
+#define SPEAR320_UART1_BASE		UL(0xA3000000)
+#define SPEAR320_UART2_BASE		UL(0xA4000000)
+#define SPEAR320_SSP0_BASE		UL(0xA5000000)
+#define SPEAR320_SSP1_BASE		UL(0xA6000000)
+#define SPEAR320_I2C_BASE		UL(0xA7000000)
+#define SPEAR320_PWM_BASE		UL(0xA8000000)
+#define SPEAR320_SMII0_BASE		UL(0xAA000000)
+#define SPEAR320_SMII1_BASE		UL(0xAB000000)
+#define SPEAR320_SOC_CONFIG_BASE	UL(0xB3000000)
 
-#define SPEAR320_SOC_CONFIG_BASE	0xB3000000
-#define SPEAR320_SOC_CONFIG_SIZE	0x00000070
 /* Interrupt registers offsets and masks */
 #define INT_STS_MASK_REG		0x04
 #define INT_CLR_MASK_REG		0x04
@@ -74,7 +45,7 @@
 #define EMI_IRQ_MASK			(1 << 7)
 #define CLCD_IRQ_MASK			(1 << 8)
 #define SPP_IRQ_MASK			(1 << 9)
-#define SDIO_IRQ_MASK			(1 << 10)
+#define SDHCI_IRQ_MASK			(1 << 10)
 #define CAN_U_IRQ_MASK			(1 << 11)
 #define CAN_L_IRQ_MASK			(1 << 12)
 #define UART1_IRQ_MASK			(1 << 13)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear.h linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/include/mach/spear.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/include/mach/spear.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,124 +14,61 @@
 #ifndef __MACH_SPEAR3XX_H
 #define __MACH_SPEAR3XX_H
 
-#include <mach/hardware.h>
+#include <asm/memory.h>
 #include <mach/spear300.h>
 #include <mach/spear310.h>
 #include <mach/spear320.h>
 
-#define SPEAR3XX_ML_SDRAM_BASE		0x00000000
-#define SPEAR3XX_ML_SDRAM_SIZE		0x40000000
+#define SPEAR3XX_ML_SDRAM_BASE		UL(0x00000000)
 
-#define SPEAR3XX_ICM9_BASE		0xC0000000
-#define SPEAR3XX_ICM9_SIZE		0x10000000
+#define SPEAR3XX_ICM9_BASE		UL(0xC0000000)
 
 /* ICM1 - Low speed connection */
-#define SPEAR3XX_ICM1_2_BASE		0xD0000000
-#define SPEAR3XX_ICM1_2_SIZE		0x10000000
-
-#define SPEAR3XX_ICM1_UART_BASE		0xD0000000
+#define SPEAR3XX_ICM1_2_BASE		UL(0xD0000000)
+#define SPEAR3XX_ICM1_UART_BASE		UL(0xD0000000)
 #define VA_SPEAR3XX_ICM1_UART_BASE	IO_ADDRESS(SPEAR3XX_ICM1_UART_BASE)
-#define SPEAR3XX_ICM1_UART_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_ADC_BASE		0xD0080000
-#define SPEAR3XX_ICM1_ADC_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_SSP_BASE		0xD0100000
-#define SPEAR3XX_ICM1_SSP_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_I2C_BASE		0xD0180000
-#define SPEAR3XX_ICM1_I2C_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_JPEG_BASE		0xD0800000
-#define SPEAR3XX_ICM1_JPEG_SIZE		0x00800000
-
-#define SPEAR3XX_ICM1_IRDA_BASE		0xD1000000
-#define SPEAR3XX_ICM1_IRDA_SIZE		0x00080000
-
-#define SPEAR3XX_ICM1_SRAM_BASE		0xD2800000
-#define SPEAR3XX_ICM1_SRAM_SIZE		0x05800000
+#define SPEAR3XX_ICM1_ADC_BASE		UL(0xD0080000)
+#define SPEAR3XX_ICM1_SSP_BASE		UL(0xD0100000)
+#define SPEAR3XX_ICM1_I2C_BASE		UL(0xD0180000)
+#define SPEAR3XX_ICM1_JPEG_BASE		UL(0xD0800000)
+#define SPEAR3XX_ICM1_IRDA_BASE		UL(0xD1000000)
+#define SPEAR3XX_ICM1_SRAM_BASE		UL(0xD2800000)
 
 /* ICM2 - Application Subsystem */
-#define SPEAR3XX_ICM2_HWACCEL0_BASE	0xD8800000
-#define SPEAR3XX_ICM2_HWACCEL0_SIZE	0x00800000
-
-#define SPEAR3XX_ICM2_HWACCEL1_BASE	0xD9000000
-#define SPEAR3XX_ICM2_HWACCEL1_SIZE	0x00800000
+#define SPEAR3XX_ICM2_HWACCEL0_BASE	UL(0xD8800000)
+#define SPEAR3XX_ICM2_HWACCEL1_BASE	UL(0xD9000000)
 
 /* ICM4 - High Speed Connection */
-#define SPEAR3XX_ICM4_BASE		0xE0000000
-#define SPEAR3XX_ICM4_SIZE		0x08000000
-
-#define SPEAR3XX_ICM4_MII_BASE		0xE0800000
-#define SPEAR3XX_ICM4_MII_SIZE		0x00800000
-
-#define SPEAR3XX_ICM4_USBD_FIFO_BASE	0xE1000000
-#define SPEAR3XX_ICM4_USBD_FIFO_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USBD_CSR_BASE	0xE1100000
-#define SPEAR3XX_ICM4_USBD_CSR_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USBD_PLDT_BASE	0xE1200000
-#define SPEAR3XX_ICM4_USBD_PLDT_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE	0xE1800000
-#define SPEAR3XX_ICM4_USB_EHCI0_1_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_OHCI0_BASE	0xE1900000
-#define SPEAR3XX_ICM4_USB_OHCI0_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_OHCI1_BASE	0xE2100000
-#define SPEAR3XX_ICM4_USB_OHCI1_SIZE	0x00100000
-
-#define SPEAR3XX_ICM4_USB_ARB_BASE	0xE2800000
-#define SPEAR3XX_ICM4_USB_ARB_SIZE	0x00010000
+#define SPEAR3XX_ICM4_BASE		UL(0xE0000000)
+#define SPEAR3XX_ICM4_MII_BASE		UL(0xE0800000)
+#define SPEAR3XX_ICM4_USBD_FIFO_BASE	UL(0xE1000000)
+#define SPEAR3XX_ICM4_USBD_CSR_BASE	UL(0xE1100000)
+#define SPEAR3XX_ICM4_USBD_PLDT_BASE	UL(0xE1200000)
+#define SPEAR3XX_ICM4_USB_EHCI0_1_BASE	UL(0xE1800000)
+#define SPEAR3XX_ICM4_USB_OHCI0_BASE	UL(0xE1900000)
+#define SPEAR3XX_ICM4_USB_OHCI1_BASE	UL(0xE2100000)
+#define SPEAR3XX_ICM4_USB_ARB_BASE	UL(0xE2800000)
 
 /* ML1 - Multi Layer CPU Subsystem */
-#define SPEAR3XX_ICM3_ML1_2_BASE	0xF0000000
-#define SPEAR3XX_ICM3_ML1_2_SIZE	0x0F000000
-
-#define SPEAR3XX_ML1_TMR_BASE		0xF0000000
-#define SPEAR3XX_ML1_TMR_SIZE		0x00100000
-
-#define SPEAR3XX_ML1_VIC_BASE		0xF1100000
+#define SPEAR3XX_ICM3_ML1_2_BASE	UL(0xF0000000)
+#define SPEAR3XX_ML1_TMR_BASE		UL(0xF0000000)
+#define SPEAR3XX_ML1_VIC_BASE		UL(0xF1100000)
 #define VA_SPEAR3XX_ML1_VIC_BASE	IO_ADDRESS(SPEAR3XX_ML1_VIC_BASE)
-#define SPEAR3XX_ML1_VIC_SIZE		0x00100000
 
 /* ICM3 - Basic Subsystem */
-#define SPEAR3XX_ICM3_SMEM_BASE		0xF8000000
-#define SPEAR3XX_ICM3_SMEM_SIZE		0x04000000
-
-#define SPEAR3XX_ICM3_SMI_CTRL_BASE	0xFC000000
-#define SPEAR3XX_ICM3_SMI_CTRL_SIZE	0x00200000
-
-#define SPEAR3XX_ICM3_DMA_BASE		0xFC400000
-#define SPEAR3XX_ICM3_DMA_SIZE		0x00200000
-
-#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE	0xFC600000
-#define SPEAR3XX_ICM3_SDRAM_CTRL_SIZE	0x00200000
-
-#define SPEAR3XX_ICM3_TMR0_BASE		0xFC800000
-#define SPEAR3XX_ICM3_TMR0_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_WDT_BASE		0xFC880000
-#define SPEAR3XX_ICM3_WDT_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_RTC_BASE		0xFC900000
-#define SPEAR3XX_ICM3_RTC_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_GPIO_BASE		0xFC980000
-#define SPEAR3XX_ICM3_GPIO_SIZE		0x00080000
-
-#define SPEAR3XX_ICM3_SYS_CTRL_BASE	0xFCA00000
+#define SPEAR3XX_ICM3_SMEM_BASE		UL(0xF8000000)
+#define SPEAR3XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define SPEAR3XX_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR3XX_ICM3_SDRAM_CTRL_BASE	UL(0xFC600000)
+#define SPEAR3XX_ICM3_TMR0_BASE		UL(0xFC800000)
+#define SPEAR3XX_ICM3_WDT_BASE		UL(0xFC880000)
+#define SPEAR3XX_ICM3_RTC_BASE		UL(0xFC900000)
+#define SPEAR3XX_ICM3_GPIO_BASE		UL(0xFC980000)
+#define SPEAR3XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
 #define VA_SPEAR3XX_ICM3_SYS_CTRL_BASE	IO_ADDRESS(SPEAR3XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR3XX_ICM3_SYS_CTRL_SIZE	0x00080000
-
-#define SPEAR3XX_ICM3_MISC_REG_BASE	0xFCA80000
+#define SPEAR3XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
 #define VA_SPEAR3XX_ICM3_MISC_REG_BASE	IO_ADDRESS(SPEAR3XX_ICM3_MISC_REG_BASE)
-#define SPEAR3XX_ICM3_MISC_REG_SIZE	0x00080000
-
-#define SPEAR3XX_ICM3_TMR1_BASE		0xFCB00000
-#define SPEAR3XX_ICM3_TMR1_SIZE		0x00080000
+#define SPEAR3XX_ICM3_TMR1_BASE		UL(0xFCB00000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR3XX_ICM1_UART_BASE
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear300.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear300.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear300.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,9 +15,9 @@
 #include <linux/amba/pl061.h>
 #include <linux/ptrace.h>
 #include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
 #include <plat/shirq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
 
 /* pad multiplexing support */
 /* muxing registers */
@@ -310,7 +310,7 @@
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdio_4bit_modes[] = {
+struct pmx_dev_mode pmx_telecom_sdhci_4bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
@@ -323,14 +323,14 @@
 	},
 };
 
-struct pmx_dev pmx_telecom_sdio_4bit = {
-	.name = "telecom_sdio_4bit",
-	.modes = pmx_telecom_sdio_4bit_modes,
-	.mode_count = ARRAY_SIZE(pmx_telecom_sdio_4bit_modes),
+struct pmx_dev pmx_telecom_sdhci_4bit = {
+	.name = "telecom_sdhci_4bit",
+	.modes = pmx_telecom_sdhci_4bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_4bit_modes),
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_telecom_sdio_8bit_modes[] = {
+struct pmx_dev_mode pmx_telecom_sdhci_8bit_modes[] = {
 	{
 		.ids = PHOTO_FRAME_MODE | LEND_IP_PHONE_MODE |
 			HEND_IP_PHONE_MODE | LEND_WIFI_PHONE_MODE |
@@ -342,10 +342,10 @@
 	},
 };
 
-struct pmx_dev pmx_telecom_sdio_8bit = {
-	.name = "telecom_sdio_8bit",
-	.modes = pmx_telecom_sdio_8bit_modes,
-	.mode_count = ARRAY_SIZE(pmx_telecom_sdio_8bit_modes),
+struct pmx_dev pmx_telecom_sdhci_8bit = {
+	.name = "telecom_sdhci_8bit",
+	.modes = pmx_telecom_sdhci_8bit_modes,
+	.mode_count = ARRAY_SIZE(pmx_telecom_sdhci_8bit_modes),
 	.enb_on_reset = 1,
 };
 
@@ -370,26 +370,6 @@
 	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
-/* Add spear300 specific devices here */
-/* arm gpio1 device registration */
-static struct pl061_platform_data gpio1_plat_data = {
-	.gpio_base	= 8,
-	.irq_base	= SPEAR_GPIO1_INT_BASE,
-};
-
-struct amba_device gpio1_device = {
-	.dev = {
-		.init_name = "gpio1",
-		.platform_data = &gpio1_plat_data,
-	},
-	.res = {
-		.start = SPEAR300_GPIO_BASE,
-		.end = SPEAR300_GPIO_BASE + SPEAR300_GPIO_SIZE - 1,
-		.flags = IORESOURCE_MEM,
-	},
-	.irq = {VIRQ_GPIO1, NO_IRQ},
-};
-
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -443,6 +423,26 @@
 	},
 };
 
+/* Add spear300 specific devices here */
+/* arm gpio1 device registration */
+static struct pl061_platform_data gpio1_plat_data = {
+	.gpio_base	= 8,
+	.irq_base	= SPEAR_GPIO1_INT_BASE,
+};
+
+struct amba_device gpio1_device = {
+	.dev = {
+		.init_name = "gpio1",
+		.platform_data = &gpio1_plat_data,
+	},
+	.res = {
+		.start = SPEAR300_GPIO_BASE,
+		.end = SPEAR300_GPIO_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	.irq = {VIRQ_GPIO1, NO_IRQ},
+};
+
 /* spear300 routines */
 void __init spear300_init(void)
 {
@@ -452,17 +452,21 @@
 	spear3xx_init();
 
 	/* shared irq registration */
-	shirq_ras1.regs.base =
-		ioremap(SPEAR300_TELECOM_BASE, SPEAR300_TELECOM_REG_SIZE);
+	shirq_ras1.regs.base = ioremap(SPEAR300_TELECOM_BASE, SZ_4K);
 	if (shirq_ras1.regs.base) {
 		ret = spear_shirq_register(&shirq_ras1);
 		if (ret)
 			printk(KERN_ERR "Error registering Shared IRQ\n");
 	}
-}
 
-void spear300_pmx_init(void)
-{
-	spear_pmx_init(&pmx_driver, SPEAR300_SOC_CONFIG_BASE,
-			SPEAR300_SOC_CONFIG_SIZE);
+	/* pmx initialization */
+	pmx_driver.base = ioremap(SPEAR300_SOC_CONFIG_BASE, SZ_4K);
+	if (pmx_driver.base) {
+		ret = pmx_register(&pmx_driver);
+		if (ret)
+			printk(KERN_ERR "padmux: registeration failed. err no"
+					": %d\n", ret);
+		/* Free Mapping, device selection already done */
+		iounmap(pmx_driver.base);
+	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear300_evb.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear300_evb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear300_evb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear300_evb.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -28,7 +28,7 @@
 	/* spear300 specific devices */
 	&pmx_fsmc_2_chips,
 	&pmx_clcd,
-	&pmx_telecom_sdio_4bit,
+	&pmx_telecom_sdhci_4bit,
 	&pmx_gpio1,
 };
 
@@ -51,14 +51,13 @@
 {
 	unsigned int i;
 
-	/* call spear300 machine init function */
-	spear300_init();
-
-	/* padmux initialization */
+	/* padmux initialization, must be done before spear300_init */
 	pmx_driver.mode = &photo_frame_mode;
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-	spear300_pmx_init();
+
+	/* call spear300 machine init function */
+	spear300_init();
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -72,6 +71,6 @@
 	.boot_params	=	0x00000100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear3xx_timer,
 	.init_machine	=	spear300_evb_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear310.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear310.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear310.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear310.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,9 +13,9 @@
 
 #include <linux/ptrace.h>
 #include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
 #include <plat/shirq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
 
 /* pad multiplexing support */
 /* muxing registers */
@@ -139,8 +139,6 @@
 	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
-/* Add spear310 specific devices here */
-
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -257,6 +255,8 @@
 	},
 };
 
+/* Add spear310 specific devices here */
+
 /* spear310 routines */
 void __init spear310_init(void)
 {
@@ -267,7 +267,7 @@
 	spear3xx_init();
 
 	/* shared irq registration */
-	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SPEAR310_SOC_CONFIG_SIZE);
+	base = ioremap(SPEAR310_SOC_CONFIG_BASE, SZ_4K);
 	if (base) {
 		/* shirq 1 */
 		shirq_ras1.regs.base = base;
@@ -293,10 +293,11 @@
 		if (ret)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
-}
 
-void spear310_pmx_init(void)
-{
-	spear_pmx_init(&pmx_driver, SPEAR310_SOC_CONFIG_BASE,
-			SPEAR310_SOC_CONFIG_SIZE);
+	/* pmx initialization */
+	pmx_driver.base = base;
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
+				ret);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear310_evb.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear310_evb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear310_evb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear310_evb.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -58,14 +58,13 @@
 {
 	unsigned int i;
 
-	/* call spear310 machine init function */
-	spear310_init();
-
-	/* padmux initialization */
+	/* padmux initialization, must be done before spear310_init */
 	pmx_driver.mode = NULL;
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-	spear310_pmx_init();
+
+	/* call spear310 machine init function */
+	spear310_init();
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -79,6 +78,6 @@
 	.boot_params	=	0x00000100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear3xx_timer,
 	.init_machine	=	spear310_evb_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear320.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear320.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear320.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear320.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,9 +13,9 @@
 
 #include <linux/ptrace.h>
 #include <asm/irq.h>
-#include <mach/generic.h>
-#include <mach/spear.h>
 #include <plat/shirq.h>
+#include <mach/generic.h>
+#include <mach/hardware.h>
 
 /* pad multiplexing support */
 /* muxing registers */
@@ -110,7 +110,7 @@
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdio_modes[] = {
+struct pmx_dev_mode pmx_sdhci_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE |
 			SMALL_PRINTERS_MODE,
@@ -118,10 +118,10 @@
 	},
 };
 
-struct pmx_dev pmx_sdio = {
-	.name = "sdio",
-	.modes = pmx_sdio_modes,
-	.mode_count = ARRAY_SIZE(pmx_sdio_modes),
+struct pmx_dev pmx_sdhci = {
+	.name = "sdhci",
+	.modes = pmx_sdhci_modes,
+	.mode_count = ARRAY_SIZE(pmx_sdhci_modes),
 	.enb_on_reset = 1,
 };
 
@@ -215,17 +215,17 @@
 	.enb_on_reset = 1,
 };
 
-struct pmx_dev_mode pmx_sdio_led_modes[] = {
+struct pmx_dev_mode pmx_sdhci_led_modes[] = {
 	{
 		.ids = AUTO_NET_SMII_MODE | AUTO_NET_MII_MODE,
 		.mask = PMX_SSP_CS_MASK,
 	},
 };
 
-struct pmx_dev pmx_sdio_led = {
-	.name = "sdio_led",
-	.modes = pmx_sdio_led_modes,
-	.mode_count = ARRAY_SIZE(pmx_sdio_led_modes),
+struct pmx_dev pmx_sdhci_led = {
+	.name = "sdhci_led",
+	.modes = pmx_sdhci_led_modes,
+	.mode_count = ARRAY_SIZE(pmx_sdhci_led_modes),
 	.enb_on_reset = 1,
 };
 
@@ -384,8 +384,6 @@
 	.mux_reg = {.offset = PAD_MUX_CONFIG_REG, .mask = 0x00007fff},
 };
 
-/* Add spear320 specific devices here */
-
 /* spear3xx shared irq */
 struct shirq_dev_config shirq_ras1_config[] = {
 	{
@@ -510,6 +508,8 @@
 	},
 };
 
+/* Add spear320 specific devices here */
+
 /* spear320 routines */
 void __init spear320_init(void)
 {
@@ -520,7 +520,7 @@
 	spear3xx_init();
 
 	/* shared irq registration */
-	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SPEAR320_SOC_CONFIG_SIZE);
+	base = ioremap(SPEAR320_SOC_CONFIG_BASE, SZ_4K);
 	if (base) {
 		/* shirq 1 */
 		shirq_ras1.regs.base = base;
@@ -540,10 +540,11 @@
 		if (ret)
 			printk(KERN_ERR "Error registering Shared IRQ 4\n");
 	}
-}
 
-void spear320_pmx_init(void)
-{
-	spear_pmx_init(&pmx_driver, SPEAR320_SOC_CONFIG_BASE,
-			SPEAR320_SOC_CONFIG_SIZE);
+	/* pmx initialization */
+	pmx_driver.base = base;
+	ret = pmx_register(&pmx_driver);
+	if (ret)
+		printk(KERN_ERR "padmux: registeration failed. err no: %d\n",
+				ret);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear320_evb.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear320_evb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear320_evb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear320_evb.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* padmux devices to enable */
 static struct pmx_dev *pmx_devs[] = {
@@ -26,7 +26,7 @@
 
 	/* spear320 specific devices */
 	&pmx_fsmc,
-	&pmx_sdio,
+	&pmx_sdhci,
 	&pmx_i2s,
 	&pmx_uart1,
 	&pmx_uart2,
@@ -55,14 +55,13 @@
 {
 	unsigned int i;
 
-	/* call spear320 machine init function */
-	spear320_init();
-
-	/* padmux initialization */
+	/* padmux initialization, must be done before spear320_init */
 	pmx_driver.mode = &auto_net_mii_mode;
 	pmx_driver.devs = pmx_devs;
 	pmx_driver.devs_count = ARRAY_SIZE(pmx_devs);
-	spear320_pmx_init();
+
+	/* call spear320 machine init function */
+	spear320_init();
 
 	/* Add Platform Devices */
 	platform_add_devices(plat_devs, ARRAY_SIZE(plat_devs));
@@ -76,6 +75,6 @@
 	.boot_params	=	0x00000100,
 	.map_io		=	spear3xx_map_io,
 	.init_irq	=	spear3xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear3xx_timer,
 	.init_machine	=	spear320_evb_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear3xx.c linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear3xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear3xx/spear3xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear3xx/spear3xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* Add spear3xx machines common devices here */
 /* gpio device registration */
@@ -35,7 +35,7 @@
 	},
 	.res = {
 		.start = SPEAR3XX_ICM3_GPIO_BASE,
-		.end = SPEAR3XX_ICM3_GPIO_BASE + SPEAR3XX_ICM3_GPIO_SIZE - 1,
+		.end = SPEAR3XX_ICM3_GPIO_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.irq = {IRQ_BASIC_GPIO, NO_IRQ},
@@ -48,7 +48,7 @@
 	},
 	.res = {
 		.start = SPEAR3XX_ICM1_UART_BASE,
-		.end = SPEAR3XX_ICM1_UART_BASE + SPEAR3XX_ICM1_UART_SIZE - 1,
+		.end = SPEAR3XX_ICM1_UART_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 	.irq = {IRQ_UART, NO_IRQ},
@@ -71,22 +71,22 @@
 	{
 		.virtual	= VA_SPEAR3XX_ICM1_UART_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM1_UART_BASE),
-		.length		= SPEAR3XX_ICM1_UART_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ML1_VIC_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ML1_VIC_BASE),
-		.length		= SPEAR3XX_ML1_VIC_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ICM3_SYS_CTRL_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_SYS_CTRL_BASE),
-		.length		= SPEAR3XX_ICM3_SYS_CTRL_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR3XX_ICM3_MISC_REG_BASE,
 		.pfn		= __phys_to_pfn(SPEAR3XX_ICM3_MISC_REG_BASE),
-		.length		= SPEAR3XX_ICM3_MISC_REG_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	},
 };
@@ -523,26 +523,35 @@
 	.mode_count = ARRAY_SIZE(pmx_plgpio_45_46_49_50_modes),
 	.enb_on_reset = 1,
 };
+#endif /* CONFIG_MACH_SPEAR310 || CONFIG_MACH_SPEAR320 */
 
-#endif
-
-/* spear padmux initialization function */
-void spear_pmx_init(struct pmx_driver *pmx_driver, uint base, uint size)
+static void __init spear3xx_timer_init(void)
 {
-	int ret = 0;
+	char pclk_name[] = "pll3_48m_clk";
+	struct clk *gpt_clk, *pclk;
 
-	/* pad mux initialization */
-	pmx_driver->base = ioremap(base, size);
-	if (!pmx_driver->base) {
-		ret = -ENOMEM;
-		goto pmx_fail;
+	/* get the system timer clock */
+	gpt_clk = clk_get_sys("gpt0", NULL);
+	if (IS_ERR(gpt_clk)) {
+		pr_err("%s:couldn't get clk for gpt\n", __func__);
+		BUG();
 	}
 
-	ret = pmx_register(pmx_driver);
-	iounmap(pmx_driver->base);
+	/* get the suitable parent clock for timer*/
+	pclk = clk_get(NULL, pclk_name);
+	if (IS_ERR(pclk)) {
+		pr_err("%s:couldn't get %s as parent for gpt\n",
+				__func__, pclk_name);
+		BUG();
+	}
 
-pmx_fail:
-	if (ret)
-		printk(KERN_ERR "padmux: registration failed. err no: %d\n",
-				ret);
+	clk_set_parent(gpt_clk, pclk);
+	clk_put(gpt_clk);
+	clk_put(pclk);
+
+	spear_setup_timer();
 }
+
+struct sys_timer spear3xx_timer = {
+	.init = spear3xx_timer_init,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,8 +13,8 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <mach/misc_regs.h>
 #include <plat/clock.h>
+#include <mach/misc_regs.h>
 
 /* root clks */
 /* 32 KHz oscillator clock */
@@ -39,18 +39,43 @@
 };
 
 /* clock derived from 30 MHz osc clk */
+/* pll masks structure */
+static struct pll_clk_masks pll1_masks = {
+	.mode_mask = PLL_MODE_MASK,
+	.mode_shift = PLL_MODE_SHIFT,
+	.norm_fdbk_m_mask = PLL_NORM_FDBK_M_MASK,
+	.norm_fdbk_m_shift = PLL_NORM_FDBK_M_SHIFT,
+	.dith_fdbk_m_mask = PLL_DITH_FDBK_M_MASK,
+	.dith_fdbk_m_shift = PLL_DITH_FDBK_M_SHIFT,
+	.div_p_mask = PLL_DIV_P_MASK,
+	.div_p_shift = PLL_DIV_P_SHIFT,
+	.div_n_mask = PLL_DIV_N_MASK,
+	.div_n_shift = PLL_DIV_N_SHIFT,
+};
+
 /* pll1 configuration structure */
 static struct pll_clk_config pll1_config = {
 	.mode_reg = PLL1_CTR,
 	.cfg_reg = PLL1_FRQ,
+	.masks = &pll1_masks,
+};
+
+/* pll rate configuration table, in ascending order of rates */
+struct pll_rate_tbl pll_rtbl[] = {
+	{.mode = 0, .m = 0x85, .n = 0x0C, .p = 0x1}, /* 266 MHz */
+	{.mode = 0, .m = 0xA6, .n = 0x0C, .p = 0x1}, /* 332 MHz */
 };
 
 /* PLL1 clock */
 static struct clk pll1_clk = {
+	.flags = ENABLED_ON_INIT,
 	.pclk = &osc_30m_clk,
 	.en_reg = PLL1_CTR,
 	.en_reg_bit = PLL_ENABLE,
-	.recalc = &pll1_clk_recalc,
+	.calc_rate = &pll_calc_rate,
+	.recalc = &pll_clk_recalc,
+	.set_rate = &pll_clk_set_rate,
+	.rate_config = {pll_rtbl, ARRAY_SIZE(pll_rtbl), 1},
 	.private_data = &pll1_config,
 };
 
@@ -76,31 +101,83 @@
 	.recalc = &follow_parent,
 };
 
+/* ahb masks structure */
+static struct bus_clk_masks ahb_masks = {
+	.mask = PLL_HCLK_RATIO_MASK,
+	.shift = PLL_HCLK_RATIO_SHIFT,
+};
+
 /* ahb configuration structure */
 static struct bus_clk_config ahb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = PLL_HCLK_RATIO_MASK,
-	.shift = PLL_HCLK_RATIO_SHIFT,
+	.masks = &ahb_masks,
+};
+
+/* ahb rate configuration table, in ascending order of rates */
+struct bus_rate_tbl bus_rtbl[] = {
+	{.div = 3}, /* == parent divided by 4 */
+	{.div = 2}, /* == parent divided by 3 */
+	{.div = 1}, /* == parent divided by 2 */
+	{.div = 0}, /* == parent divided by 1 */
 };
 
 /* ahb clock */
 static struct clk ahb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &pll1_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &ahb_config,
 };
 
+/* auxiliary synthesizers masks */
+static struct aux_clk_masks aux_masks = {
+	.eq_sel_mask = AUX_EQ_SEL_MASK,
+	.eq_sel_shift = AUX_EQ_SEL_SHIFT,
+	.eq1_mask = AUX_EQ1_SEL,
+	.eq2_mask = AUX_EQ2_SEL,
+	.xscale_sel_mask = AUX_XSCALE_MASK,
+	.xscale_sel_shift = AUX_XSCALE_SHIFT,
+	.yscale_sel_mask = AUX_YSCALE_MASK,
+	.yscale_sel_shift = AUX_YSCALE_SHIFT,
+};
+
+/* uart configurations */
+static struct aux_clk_config uart_synth_config = {
+	.synth_reg = UART_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* aux rate configuration table, in ascending order of rates */
+struct aux_rate_tbl aux_rtbl[] = {
+	/* For PLL1 = 332 MHz */
+	{.xscale = 1, .yscale = 8, .eq = 1}, /* 41.5 MHz */
+	{.xscale = 1, .yscale = 4, .eq = 1}, /* 83 MHz */
+	{.xscale = 1, .yscale = 2, .eq = 1}, /* 166 MHz */
+};
+
+/* uart synth clock */
+static struct clk uart_synth_clk = {
+	.en_reg = UART_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.private_data = &uart_synth_config,
+};
+
 /* uart parents */
 static struct pclk_info uart_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &uart_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -112,19 +189,13 @@
 	.pclk_sel_mask = UART_CLK_MASK,
 };
 
-/* uart configurations */
-static struct aux_clk_config uart_config = {
-	.synth_reg = UART_CLK_SYNT,
-};
-
 /* uart0 clock */
 static struct clk uart0_clk = {
 	.en_reg = PERIP1_CLK_ENB,
 	.en_reg_bit = UART0_CLK_ENB,
 	.pclk_sel = &uart_pclk_sel,
 	.pclk_sel_shift = UART_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &uart_config,
+	.recalc = &follow_parent,
 };
 
 /* uart1 clock */
@@ -133,25 +204,35 @@
 	.en_reg_bit = UART1_CLK_ENB,
 	.pclk_sel = &uart_pclk_sel,
 	.pclk_sel_shift = UART_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &uart_config,
+	.recalc = &follow_parent,
 };
 
 /* firda configurations */
-static struct aux_clk_config firda_config = {
+static struct aux_clk_config firda_synth_config = {
 	.synth_reg = FIRDA_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* firda synth clock */
+static struct clk firda_synth_clk = {
+	.en_reg = FIRDA_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.private_data = &firda_synth_config,
 };
 
 /* firda parents */
 static struct pclk_info firda_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &firda_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -169,25 +250,35 @@
 	.en_reg_bit = FIRDA_CLK_ENB,
 	.pclk_sel = &firda_pclk_sel,
 	.pclk_sel_shift = FIRDA_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &firda_config,
+	.recalc = &follow_parent,
 };
 
 /* clcd configurations */
-static struct aux_clk_config clcd_config = {
+static struct aux_clk_config clcd_synth_config = {
 	.synth_reg = CLCD_CLK_SYNT,
+	.masks = &aux_masks,
+};
+
+/* firda synth clock */
+static struct clk clcd_synth_clk = {
+	.en_reg = CLCD_CLK_SYNT,
+	.en_reg_bit = AUX_SYNT_ENB,
+	.pclk = &pll1_clk,
+	.calc_rate = &aux_calc_rate,
+	.recalc = &aux_clk_recalc,
+	.set_rate = &aux_clk_set_rate,
+	.rate_config = {aux_rtbl, ARRAY_SIZE(aux_rtbl), 2},
+	.private_data = &clcd_synth_config,
 };
 
 /* clcd parents */
 static struct pclk_info clcd_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &clcd_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
@@ -205,82 +296,173 @@
 	.en_reg_bit = CLCD_CLK_ENB,
 	.pclk_sel = &clcd_pclk_sel,
 	.pclk_sel_shift = CLCD_CLK_SHIFT,
-	.recalc = &aux_clk_recalc,
-	.private_data = &clcd_config,
+	.recalc = &follow_parent,
+};
+
+/* gpt synthesizer masks */
+static struct gpt_clk_masks gpt_masks = {
+	.mscale_sel_mask = GPT_MSCALE_MASK,
+	.mscale_sel_shift = GPT_MSCALE_SHIFT,
+	.nscale_sel_mask = GPT_NSCALE_MASK,
+	.nscale_sel_shift = GPT_NSCALE_SHIFT,
+};
+
+/* gpt rate configuration table, in ascending order of rates */
+struct gpt_rate_tbl gpt_rtbl[] = {
+	/* For pll1 = 332 MHz */
+	{.mscale = 4, .nscale = 0}, /* 41.5 MHz */
+	{.mscale = 2, .nscale = 0}, /* 55.3 MHz */
+	{.mscale = 1, .nscale = 0}, /* 83 MHz */
+};
+
+/* gpt0 synth clk config*/
+static struct gpt_clk_config gpt0_synth_config = {
+	.synth_reg = PRSC1_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt0_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt0_synth_config,
 };
 
 /* gpt parents */
-static struct pclk_info gpt_pclk_info[] = {
+static struct pclk_info gpt0_pclk_info[] = {
 	{
-		.pclk = &pll1_clk,
-		.pclk_mask = AUX_CLK_PLL1_MASK,
-		.scalable = 1,
+		.pclk = &gpt0_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
 	}, {
 		.pclk = &pll3_48m_clk,
-		.pclk_mask = AUX_CLK_PLL3_MASK,
-		.scalable = 0,
+		.pclk_val = AUX_CLK_PLL3_VAL,
 	},
 };
 
 /* gpt parent select structure */
-static struct pclk_sel gpt_pclk_sel = {
-	.pclk_info = gpt_pclk_info,
-	.pclk_count = ARRAY_SIZE(gpt_pclk_info),
+static struct pclk_sel gpt0_pclk_sel = {
+	.pclk_info = gpt0_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
 	.pclk_sel_reg = PERIP_CLK_CFG,
 	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
-/* gpt0_1 configurations */
-static struct aux_clk_config gpt0_1_config = {
-	.synth_reg = PRSC1_CLK_CFG,
-};
-
 /* gpt0 ARM1 subsystem timer clock */
 static struct clk gpt0_clk = {
 	.flags = ALWAYS_ENABLED,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt0_pclk_sel,
 	.pclk_sel_shift = GPT0_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt0_1_config,
+	.recalc = &follow_parent,
+};
+
+
+/* Note: gpt0 and gpt1 share same parent clocks */
+/* gpt parent select structure */
+static struct pclk_sel gpt1_pclk_sel = {
+	.pclk_info = gpt0_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt0_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt1 timer clock */
 static struct clk gpt1_clk = {
 	.flags = ALWAYS_ENABLED,
-	.pclk_sel = &gpt_pclk_sel,
+	.pclk_sel = &gpt1_pclk_sel,
 	.pclk_sel_shift = GPT1_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt0_1_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt2 configurations */
-static struct aux_clk_config gpt2_config = {
+/* gpt2 synth clk config*/
+static struct gpt_clk_config gpt2_synth_config = {
 	.synth_reg = PRSC2_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt2_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt2_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt2_pclk_info[] = {
+	{
+		.pclk = &gpt2_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt2_pclk_sel = {
+	.pclk_info = gpt2_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt2_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt2 timer clock */
 static struct clk gpt2_clk = {
-	.en_reg = PERIP1_CLK_ENB,
-	.en_reg_bit = GPT2_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &gpt2_pclk_sel,
 	.pclk_sel_shift = GPT2_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt2_config,
+	.recalc = &follow_parent,
 };
 
-/* gpt3 configurations */
-static struct aux_clk_config gpt3_config = {
+/* gpt3 synth clk config*/
+static struct gpt_clk_config gpt3_synth_config = {
 	.synth_reg = PRSC3_CLK_CFG,
+	.masks = &gpt_masks,
+};
+
+/* gpt synth clock */
+static struct clk gpt3_synth_clk = {
+	.flags = ALWAYS_ENABLED,
+	.pclk = &pll1_clk,
+	.calc_rate = &gpt_calc_rate,
+	.recalc = &gpt_clk_recalc,
+	.set_rate = &gpt_clk_set_rate,
+	.rate_config = {gpt_rtbl, ARRAY_SIZE(gpt_rtbl), 2},
+	.private_data = &gpt3_synth_config,
+};
+
+/* gpt parents */
+static struct pclk_info gpt3_pclk_info[] = {
+	{
+		.pclk = &gpt3_synth_clk,
+		.pclk_val = AUX_CLK_PLL1_VAL,
+	}, {
+		.pclk = &pll3_48m_clk,
+		.pclk_val = AUX_CLK_PLL3_VAL,
+	},
+};
+
+/* gpt parent select structure */
+static struct pclk_sel gpt3_pclk_sel = {
+	.pclk_info = gpt3_pclk_info,
+	.pclk_count = ARRAY_SIZE(gpt3_pclk_info),
+	.pclk_sel_reg = PERIP_CLK_CFG,
+	.pclk_sel_mask = GPT_CLK_MASK,
 };
 
 /* gpt3 timer clock */
 static struct clk gpt3_clk = {
-	.en_reg = PERIP1_CLK_ENB,
-	.en_reg_bit = GPT3_CLK_ENB,
-	.pclk_sel = &gpt_pclk_sel,
+	.flags = ALWAYS_ENABLED,
+	.pclk_sel = &gpt3_pclk_sel,
 	.pclk_sel_shift = GPT3_CLK_SHIFT,
-	.recalc = &gpt_clk_recalc,
-	.private_data = &gpt3_config,
+	.recalc = &follow_parent,
 };
 
 /* clock derived from pll3 clk */
@@ -309,18 +491,26 @@
 };
 
 /* clock derived from ahb clk */
+/* apb masks structure */
+static struct bus_clk_masks apb_masks = {
+	.mask = HCLK_PCLK_RATIO_MASK,
+	.shift = HCLK_PCLK_RATIO_SHIFT,
+};
+
 /* apb configuration structure */
 static struct bus_clk_config apb_config = {
 	.reg = CORE_CLK_CFG,
-	.mask = HCLK_PCLK_RATIO_MASK,
-	.shift = HCLK_PCLK_RATIO_SHIFT,
+	.masks = &apb_masks,
 };
 
 /* apb clock */
 static struct clk apb_clk = {
 	.flags = ALWAYS_ENABLED,
 	.pclk = &ahb_clk,
+	.calc_rate = &bus_calc_rate,
 	.recalc = &bus_clk_recalc,
+	.set_rate = &bus_clk_set_rate,
+	.rate_config = {bus_rtbl, ARRAY_SIZE(bus_rtbl), 2},
 	.private_data = &apb_config,
 };
 
@@ -432,12 +622,12 @@
 
 /* array of all spear 6xx clock lookups */
 static struct clk_lookup spear_clk_lookups[] = {
-	{ .con_id = "apb_pclk",	.clk = &dummy_apb_pclk},
+	{ .con_id = "apb_pclk",		.clk = &dummy_apb_pclk},
 	/* root clks */
 	{ .con_id = "osc_32k_clk",	.clk = &osc_32k_clk},
 	{ .con_id = "osc_30m_clk",	.clk = &osc_30m_clk},
 	/* clock derived from 32 KHz os		 clk */
-	{ .dev_id = "rtc",		.clk = &rtc_clk},
+	{ .dev_id = "rtc-spear",	.clk = &rtc_clk},
 	/* clock derived from 30 MHz os		 clk */
 	{ .con_id = "pll1_clk",		.clk = &pll1_clk},
 	{ .con_id = "pll3_48m_clk",	.clk = &pll3_48m_clk},
@@ -445,6 +635,12 @@
 	/* clock derived from pll1 clk */
 	{ .con_id = "cpu_clk",		.clk = &cpu_clk},
 	{ .con_id = "ahb_clk",		.clk = &ahb_clk},
+	{ .con_id = "uart_synth_clk",	.clk = &uart_synth_clk},
+	{ .con_id = "firda_synth_clk",	.clk = &firda_synth_clk},
+	{ .con_id = "clcd_synth_clk",	.clk = &clcd_synth_clk},
+	{ .con_id = "gpt0_synth_clk",	.clk = &gpt0_synth_clk},
+	{ .con_id = "gpt2_synth_clk",	.clk = &gpt2_synth_clk},
+	{ .con_id = "gpt3_synth_clk",	.clk = &gpt3_synth_clk},
 	{ .dev_id = "uart0",		.clk = &uart0_clk},
 	{ .dev_id = "uart1",		.clk = &uart1_clk},
 	{ .dev_id = "firda",		.clk = &firda_clk},
@@ -454,22 +650,22 @@
 	{ .dev_id = "gpt2",		.clk = &gpt2_clk},
 	{ .dev_id = "gpt3",		.clk = &gpt3_clk},
 	/* clock derived from pll3 clk */
-	{ .dev_id = "usbh0",		.clk = &usbh0_clk},
-	{ .dev_id = "usbh1",		.clk = &usbh1_clk},
-	{ .dev_id = "usbd",		.clk = &usbd_clk},
+	{ .dev_id = "designware_udc",	.clk = &usbd_clk},
+	{ .con_id = "usbh.0_clk",	.clk = &usbh0_clk},
+	{ .con_id = "usbh.1_clk",	.clk = &usbh1_clk},
 	/* clock derived from ahb clk */
 	{ .con_id = "apb_clk",		.clk = &apb_clk},
-	{ .dev_id = "i2c",		.clk = &i2c_clk},
+	{ .dev_id = "i2c_designware.0",	.clk = &i2c_clk},
 	{ .dev_id = "dma",		.clk = &dma_clk},
 	{ .dev_id = "jpeg",		.clk = &jpeg_clk},
 	{ .dev_id = "gmac",		.clk = &gmac_clk},
 	{ .dev_id = "smi",		.clk = &smi_clk},
-	{ .dev_id = "fsmc",		.clk = &fsmc_clk},
+	{ .con_id = "fsmc",		.clk = &fsmc_clk},
 	/* clock derived from apb clk */
 	{ .dev_id = "adc",		.clk = &adc_clk},
-	{ .dev_id = "ssp0",		.clk = &ssp0_clk},
-	{ .dev_id = "ssp1",		.clk = &ssp1_clk},
-	{ .dev_id = "ssp2",		.clk = &ssp2_clk},
+	{ .dev_id = "ssp-pl022.0",	.clk = &ssp0_clk},
+	{ .dev_id = "ssp-pl022.1",	.clk = &ssp1_clk},
+	{ .dev_id = "ssp-pl022.2",	.clk = &ssp2_clk},
 	{ .dev_id = "gpio0",		.clk = &gpio0_clk},
 	{ .dev_id = "gpio1",		.clk = &gpio1_clk},
 	{ .dev_id = "gpio2",		.clk = &gpio2_clk},
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/entry-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -11,9 +11,8 @@
  * warranty of any kind, whether express or implied.
  */
 
-#include <mach/hardware.h>
-#include <mach/spear.h>
 #include <asm/hardware/vic.h>
+#include <mach/hardware.h>
 
 		.macro	disable_fiq
 		.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/generic.h linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/generic.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/generic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/generic.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,11 +14,11 @@
 #ifndef __MACH_GENERIC_H
 #define __MACH_GENERIC_H
 
-#include <asm/mach/time.h>
-#include <asm/mach/map.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/amba/bus.h>
+#include <asm/mach/time.h>
+#include <asm/mach/map.h>
 
 /*
  * Each GPT has 2 timer channels
@@ -31,9 +31,10 @@
 /* Add spear6xx family device structure declarations here */
 extern struct amba_device gpio_device[];
 extern struct amba_device uart_device[];
-extern struct sys_timer spear_sys_timer;
+extern struct sys_timer spear6xx_timer;
 
 /* Add spear6xx family function declarations here */
+void __init spear_setup_timer(void);
 void __init spear6xx_map_io(void);
 void __init spear6xx_init_irq(void);
 void __init spear6xx_init(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,8 +14,10 @@
 #ifndef __MACH_HARDWARE_H
 #define __MACH_HARDWARE_H
 
+#include <plat/hardware.h>
+#include <mach/spear.h>
+
 /* Vitual to physical translation of statically mapped space */
 #define IO_ADDRESS(x)		(x | 0xF0000000)
 
 #endif /* __MACH_HARDWARE_H */
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/misc_regs.h linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/misc_regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/misc_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/misc_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,16 +14,16 @@
 #ifndef __MACH_MISC_REGS_H
 #define __MACH_MISC_REGS_H
 
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
-#define MISC_BASE		VA_SPEAR6XX_ICM3_MISC_REG_BASE
+#define MISC_BASE		IOMEM(VA_SPEAR6XX_ICM3_MISC_REG_BASE)
 
-#define SOC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x000))
-#define DIAG_CFG_CTR		((unsigned int *)(MISC_BASE + 0x004))
-#define PLL1_CTR		((unsigned int *)(MISC_BASE + 0x008))
-#define PLL1_FRQ		((unsigned int *)(MISC_BASE + 0x00C))
-#define PLL1_MOD		((unsigned int *)(MISC_BASE + 0x010))
-#define PLL2_CTR		((unsigned int *)(MISC_BASE + 0x014))
+#define SOC_CFG_CTR		(MISC_BASE + 0x000)
+#define DIAG_CFG_CTR		(MISC_BASE + 0x004)
+#define PLL1_CTR		(MISC_BASE + 0x008)
+#define PLL1_FRQ		(MISC_BASE + 0x00C)
+#define PLL1_MOD		(MISC_BASE + 0x010)
+#define PLL2_CTR		(MISC_BASE + 0x014)
 /* PLL_CTR register masks */
 #define PLL_ENABLE		2
 #define PLL_MODE_SHIFT		4
@@ -33,7 +33,7 @@
 #define PLL_MODE_DITH_DSB	2
 #define PLL_MODE_DITH_SSB	3
 
-#define PLL2_FRQ		((unsigned int *)(MISC_BASE + 0x018))
+#define PLL2_FRQ		(MISC_BASE + 0x018)
 /* PLL FRQ register masks */
 #define PLL_DIV_N_SHIFT		0
 #define PLL_DIV_N_MASK		0xFF
@@ -44,16 +44,16 @@
 #define PLL_DITH_FDBK_M_SHIFT	16
 #define PLL_DITH_FDBK_M_MASK	0xFFFF
 
-#define PLL2_MOD		((unsigned int *)(MISC_BASE + 0x01C))
-#define PLL_CLK_CFG		((unsigned int *)(MISC_BASE + 0x020))
-#define CORE_CLK_CFG		((unsigned int *)(MISC_BASE + 0x024))
+#define PLL2_MOD		(MISC_BASE + 0x01C)
+#define PLL_CLK_CFG		(MISC_BASE + 0x020)
+#define CORE_CLK_CFG		(MISC_BASE + 0x024)
 /* CORE CLK CFG register masks */
 #define PLL_HCLK_RATIO_SHIFT	10
 #define PLL_HCLK_RATIO_MASK	0x3
 #define HCLK_PCLK_RATIO_SHIFT	8
 #define HCLK_PCLK_RATIO_MASK	0x3
 
-#define PERIP_CLK_CFG		((unsigned int *)(MISC_BASE + 0x028))
+#define PERIP_CLK_CFG		(MISC_BASE + 0x028)
 /* PERIP_CLK_CFG register masks */
 #define CLCD_CLK_SHIFT		2
 #define CLCD_CLK_MASK		0x3
@@ -66,10 +66,10 @@
 #define GPT2_CLK_SHIFT		11
 #define GPT3_CLK_SHIFT		12
 #define GPT_CLK_MASK		0x1
-#define AUX_CLK_PLL3_MASK	0
-#define AUX_CLK_PLL1_MASK	1
+#define AUX_CLK_PLL3_VAL	0
+#define AUX_CLK_PLL1_VAL	1
 
-#define PERIP1_CLK_ENB		((unsigned int *)(MISC_BASE + 0x02C))
+#define PERIP1_CLK_ENB		(MISC_BASE + 0x02C)
 /* PERIP1_CLK_ENB register masks */
 #define UART0_CLK_ENB		3
 #define UART1_CLK_ENB		4
@@ -95,34 +95,35 @@
 #define USBH0_CLK_ENB		25
 #define USBH1_CLK_ENB		26
 
-#define SOC_CORE_ID		((unsigned int *)(MISC_BASE + 0x030))
-#define RAS_CLK_ENB		((unsigned int *)(MISC_BASE + 0x034))
-#define PERIP1_SOF_RST		((unsigned int *)(MISC_BASE + 0x038))
+#define SOC_CORE_ID		(MISC_BASE + 0x030)
+#define RAS_CLK_ENB		(MISC_BASE + 0x034)
+#define PERIP1_SOF_RST		(MISC_BASE + 0x038)
 /* PERIP1_SOF_RST register masks */
 #define JPEG_SOF_RST		8
 
-#define SOC_USER_ID		((unsigned int *)(MISC_BASE + 0x03C))
-#define RAS_SOF_RST		((unsigned int *)(MISC_BASE + 0x040))
-#define PRSC1_CLK_CFG		((unsigned int *)(MISC_BASE + 0x044))
-#define PRSC2_CLK_CFG		((unsigned int *)(MISC_BASE + 0x048))
-#define PRSC3_CLK_CFG		((unsigned int *)(MISC_BASE + 0x04C))
+#define SOC_USER_ID		(MISC_BASE + 0x03C)
+#define RAS_SOF_RST		(MISC_BASE + 0x040)
+#define PRSC1_CLK_CFG		(MISC_BASE + 0x044)
+#define PRSC2_CLK_CFG		(MISC_BASE + 0x048)
+#define PRSC3_CLK_CFG		(MISC_BASE + 0x04C)
 /* gpt synthesizer register masks */
 #define GPT_MSCALE_SHIFT	0
 #define GPT_MSCALE_MASK		0xFFF
 #define GPT_NSCALE_SHIFT	12
 #define GPT_NSCALE_MASK		0xF
 
-#define AMEM_CLK_CFG		((unsigned int *)(MISC_BASE + 0x050))
-#define EXPI_CLK_CFG		((unsigned int *)(MISC_BASE + 0x054))
-#define CLCD_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x05C))
-#define FIRDA_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x060))
-#define UART_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x064))
-#define GMAC_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x068))
-#define RAS1_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x06C))
-#define RAS2_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x070))
-#define RAS3_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x074))
-#define RAS4_CLK_SYNT		((unsigned int *)(MISC_BASE + 0x078))
+#define AMEM_CLK_CFG		(MISC_BASE + 0x050)
+#define EXPI_CLK_CFG		(MISC_BASE + 0x054)
+#define CLCD_CLK_SYNT		(MISC_BASE + 0x05C)
+#define FIRDA_CLK_SYNT		(MISC_BASE + 0x060)
+#define UART_CLK_SYNT		(MISC_BASE + 0x064)
+#define GMAC_CLK_SYNT		(MISC_BASE + 0x068)
+#define RAS1_CLK_SYNT		(MISC_BASE + 0x06C)
+#define RAS2_CLK_SYNT		(MISC_BASE + 0x070)
+#define RAS3_CLK_SYNT		(MISC_BASE + 0x074)
+#define RAS4_CLK_SYNT		(MISC_BASE + 0x078)
 /* aux clk synthesiser register masks for irda to ras4 */
+#define AUX_SYNT_ENB		31
 #define AUX_EQ_SEL_SHIFT	30
 #define AUX_EQ_SEL_MASK		1
 #define AUX_EQ1_SEL		0
@@ -132,42 +133,42 @@
 #define AUX_YSCALE_SHIFT	0
 #define AUX_YSCALE_MASK		0xFFF
 
-#define ICM1_ARB_CFG		((unsigned int *)(MISC_BASE + 0x07C))
-#define ICM2_ARB_CFG		((unsigned int *)(MISC_BASE + 0x080))
-#define ICM3_ARB_CFG		((unsigned int *)(MISC_BASE + 0x084))
-#define ICM4_ARB_CFG		((unsigned int *)(MISC_BASE + 0x088))
-#define ICM5_ARB_CFG		((unsigned int *)(MISC_BASE + 0x08C))
-#define ICM6_ARB_CFG		((unsigned int *)(MISC_BASE + 0x090))
-#define ICM7_ARB_CFG		((unsigned int *)(MISC_BASE + 0x094))
-#define ICM8_ARB_CFG		((unsigned int *)(MISC_BASE + 0x098))
-#define ICM9_ARB_CFG		((unsigned int *)(MISC_BASE + 0x09C))
-#define DMA_CHN_CFG		((unsigned int *)(MISC_BASE + 0x0A0))
-#define USB2_PHY_CFG		((unsigned int *)(MISC_BASE + 0x0A4))
-#define GMAC_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0A8))
-#define EXPI_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0AC))
-#define PRC1_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C0))
-#define PRC2_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C4))
-#define PRC3_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0C8))
-#define PRC4_LOCK_CTR		((unsigned int *)(MISC_BASE + 0x0CC))
-#define PRC1_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D0))
-#define PRC2_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D4))
-#define PRC3_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0D8))
-#define PRC4_IRQ_CTR		((unsigned int *)(MISC_BASE + 0x0DC))
-#define PWRDOWN_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0E0))
-#define COMPSSTL_1V8_CFG	((unsigned int *)(MISC_BASE + 0x0E4))
-#define COMPSSTL_2V5_CFG	((unsigned int *)(MISC_BASE + 0x0E8))
-#define COMPCOR_3V3_CFG		((unsigned int *)(MISC_BASE + 0x0EC))
-#define SSTLPAD_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F0))
-#define BIST1_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F4))
-#define BIST2_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0F8))
-#define BIST3_CFG_CTR		((unsigned int *)(MISC_BASE + 0x0FC))
-#define BIST4_CFG_CTR		((unsigned int *)(MISC_BASE + 0x100))
-#define BIST5_CFG_CTR		((unsigned int *)(MISC_BASE + 0x104))
-#define BIST1_STS_RES		((unsigned int *)(MISC_BASE + 0x108))
-#define BIST2_STS_RES		((unsigned int *)(MISC_BASE + 0x10C))
-#define BIST3_STS_RES		((unsigned int *)(MISC_BASE + 0x110))
-#define BIST4_STS_RES		((unsigned int *)(MISC_BASE + 0x114))
-#define BIST5_STS_RES		((unsigned int *)(MISC_BASE + 0x118))
-#define SYSERR_CFG_CTR		((unsigned int *)(MISC_BASE + 0x11C))
+#define ICM1_ARB_CFG		(MISC_BASE + 0x07C)
+#define ICM2_ARB_CFG		(MISC_BASE + 0x080)
+#define ICM3_ARB_CFG		(MISC_BASE + 0x084)
+#define ICM4_ARB_CFG		(MISC_BASE + 0x088)
+#define ICM5_ARB_CFG		(MISC_BASE + 0x08C)
+#define ICM6_ARB_CFG		(MISC_BASE + 0x090)
+#define ICM7_ARB_CFG		(MISC_BASE + 0x094)
+#define ICM8_ARB_CFG		(MISC_BASE + 0x098)
+#define ICM9_ARB_CFG		(MISC_BASE + 0x09C)
+#define DMA_CHN_CFG		(MISC_BASE + 0x0A0)
+#define USB2_PHY_CFG		(MISC_BASE + 0x0A4)
+#define GMAC_CFG_CTR		(MISC_BASE + 0x0A8)
+#define EXPI_CFG_CTR		(MISC_BASE + 0x0AC)
+#define PRC1_LOCK_CTR		(MISC_BASE + 0x0C0)
+#define PRC2_LOCK_CTR		(MISC_BASE + 0x0C4)
+#define PRC3_LOCK_CTR		(MISC_BASE + 0x0C8)
+#define PRC4_LOCK_CTR		(MISC_BASE + 0x0CC)
+#define PRC1_IRQ_CTR		(MISC_BASE + 0x0D0)
+#define PRC2_IRQ_CTR		(MISC_BASE + 0x0D4)
+#define PRC3_IRQ_CTR		(MISC_BASE + 0x0D8)
+#define PRC4_IRQ_CTR		(MISC_BASE + 0x0DC)
+#define PWRDOWN_CFG_CTR		(MISC_BASE + 0x0E0)
+#define COMPSSTL_1V8_CFG	(MISC_BASE + 0x0E4)
+#define COMPSSTL_2V5_CFG	(MISC_BASE + 0x0E8)
+#define COMPCOR_3V3_CFG		(MISC_BASE + 0x0EC)
+#define SSTLPAD_CFG_CTR		(MISC_BASE + 0x0F0)
+#define BIST1_CFG_CTR		(MISC_BASE + 0x0F4)
+#define BIST2_CFG_CTR		(MISC_BASE + 0x0F8)
+#define BIST3_CFG_CTR		(MISC_BASE + 0x0FC)
+#define BIST4_CFG_CTR		(MISC_BASE + 0x100)
+#define BIST5_CFG_CTR		(MISC_BASE + 0x104)
+#define BIST1_STS_RES		(MISC_BASE + 0x108)
+#define BIST2_STS_RES		(MISC_BASE + 0x10C)
+#define BIST3_STS_RES		(MISC_BASE + 0x110)
+#define BIST4_STS_RES		(MISC_BASE + 0x114)
+#define BIST5_STS_RES		(MISC_BASE + 0x118)
+#define SYSERR_CFG_CTR		(MISC_BASE + 0x11C)
 
 #endif /* __MACH_MISC_REGS_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/spear.h linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/spear.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/include/mach/spear.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/include/mach/spear.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,153 +14,70 @@
 #ifndef __MACH_SPEAR6XX_H
 #define __MACH_SPEAR6XX_H
 
-#include <mach/hardware.h>
+#include <asm/memory.h>
 #include <mach/spear600.h>
 
-#define SPEAR6XX_ML_SDRAM_BASE		0x00000000
-#define SPEAR6XX_ML_SDRAM_SIZE		0x40000000
-
+#define SPEAR6XX_ML_SDRAM_BASE		UL(0x00000000)
 /* ICM1 - Low speed connection */
-#define SPEAR6XX_ICM1_BASE		0xD0000000
-#define SPEAR6XX_ICM1_SIZE		0x08000000
+#define SPEAR6XX_ICM1_BASE		UL(0xD0000000)
 
-#define SPEAR6XX_ICM1_UART0_BASE	0xD0000000
+#define SPEAR6XX_ICM1_UART0_BASE	UL(0xD0000000)
 #define VA_SPEAR6XX_ICM1_UART0_BASE	IO_ADDRESS(SPEAR6XX_ICM1_UART0_BASE)
-#define SPEAR6XX_ICM1_UART0_SIZE	0x00080000
-
-#define SPEAR6XX_ICM1_UART1_BASE	0xD0080000
-#define SPEAR6XX_ICM1_UART1_SIZE	0x00080000
-
-#define SPEAR6XX_ICM1_SSP0_BASE		0xD0100000
-#define SPEAR6XX_ICM1_SSP0_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_SSP1_BASE		0xD0180000
-#define SPEAR6XX_ICM1_SSP1_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_I2C_BASE		0xD0200000
-#define SPEAR6XX_ICM1_I2C_SIZE		0x00080000
-
-#define SPEAR6XX_ICM1_JPEG_BASE		0xD0800000
-#define SPEAR6XX_ICM1_JPEG_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_IRDA_BASE		0xD1000000
-#define SPEAR6XX_ICM1_IRDA_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_FSMC_BASE		0xD1800000
-#define SPEAR6XX_ICM1_FSMC_SIZE		0x00800000
 
-#define SPEAR6XX_ICM1_NAND_BASE		0xD2000000
-#define SPEAR6XX_ICM1_NAND_SIZE		0x00800000
-
-#define SPEAR6XX_ICM1_SRAM_BASE		0xD2800000
-#define SPEAR6XX_ICM1_SRAM_SIZE		0x00800000
+#define SPEAR6XX_ICM1_UART1_BASE	UL(0xD0080000)
+#define SPEAR6XX_ICM1_SSP0_BASE		UL(0xD0100000)
+#define SPEAR6XX_ICM1_SSP1_BASE		UL(0xD0180000)
+#define SPEAR6XX_ICM1_I2C_BASE		UL(0xD0200000)
+#define SPEAR6XX_ICM1_JPEG_BASE		UL(0xD0800000)
+#define SPEAR6XX_ICM1_IRDA_BASE		UL(0xD1000000)
+#define SPEAR6XX_ICM1_FSMC_BASE		UL(0xD1800000)
+#define SPEAR6XX_ICM1_NAND_BASE		UL(0xD2000000)
+#define SPEAR6XX_ICM1_SRAM_BASE		UL(0xD2800000)
 
 /* ICM2 - Application Subsystem */
-#define SPEAR6XX_ICM2_BASE		0xD8000000
-#define SPEAR6XX_ICM2_SIZE		0x08000000
-
-#define SPEAR6XX_ICM2_TMR0_BASE		0xD8000000
-#define SPEAR6XX_ICM2_TMR0_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_TMR1_BASE		0xD8080000
-#define SPEAR6XX_ICM2_TMR1_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_GPIO_BASE		0xD8100000
-#define SPEAR6XX_ICM2_GPIO_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_SPI2_BASE		0xD8180000
-#define SPEAR6XX_ICM2_SPI2_SIZE		0x00080000
-
-#define SPEAR6XX_ICM2_ADC_BASE		0xD8200000
-#define SPEAR6XX_ICM2_ADC_SIZE		0x00080000
+#define SPEAR6XX_ICM2_BASE		UL(0xD8000000)
+#define SPEAR6XX_ICM2_TMR0_BASE		UL(0xD8000000)
+#define SPEAR6XX_ICM2_TMR1_BASE		UL(0xD8080000)
+#define SPEAR6XX_ICM2_GPIO_BASE		UL(0xD8100000)
+#define SPEAR6XX_ICM2_SSP2_BASE		UL(0xD8180000)
+#define SPEAR6XX_ICM2_ADC_BASE		UL(0xD8200000)
 
 /* ML-1, 2 - Multi Layer CPU Subsystem */
-#define SPEAR6XX_ML_CPU_BASE		0xF0000000
-#define SPEAR6XX_ML_CPU_SIZE		0x08000000
-
-#define SPEAR6XX_CPU_TMR_BASE		0xF0000000
-#define SPEAR6XX_CPU_TMR_SIZE		0x00100000
-
-#define SPEAR6XX_CPU_GPIO_BASE		0xF0100000
-#define SPEAR6XX_CPU_GPIO_SIZE		0x00100000
-
-#define SPEAR6XX_CPU_VIC_SEC_BASE	0xF1000000
+#define SPEAR6XX_ML_CPU_BASE		UL(0xF0000000)
+#define SPEAR6XX_CPU_TMR_BASE		UL(0xF0000000)
+#define SPEAR6XX_CPU_GPIO_BASE		UL(0xF0100000)
+#define SPEAR6XX_CPU_VIC_SEC_BASE	UL(0xF1000000)
 #define VA_SPEAR6XX_CPU_VIC_SEC_BASE	IO_ADDRESS(SPEAR6XX_CPU_VIC_SEC_BASE)
-#define SPEAR6XX_CPU_VIC_SEC_SIZE	0x00100000
-
-#define SPEAR6XX_CPU_VIC_PRI_BASE	0xF1100000
+#define SPEAR6XX_CPU_VIC_PRI_BASE	UL(0xF1100000)
 #define VA_SPEAR6XX_CPU_VIC_PRI_BASE	IO_ADDRESS(SPEAR6XX_CPU_VIC_PRI_BASE)
-#define SPEAR6XX_CPU_VIC_PRI_SIZE	0x00100000
 
 /* ICM3 - Basic Subsystem */
-#define SPEAR6XX_ICM3_BASE		0xF8000000
-#define SPEAR6XX_ICM3_SIZE		0x08000000
-
-#define SPEAR6XX_ICM3_SMEM_BASE		0xF8000000
-#define SPEAR6XX_ICM3_SMEM_SIZE		0x04000000
-
-#define SPEAR6XX_ICM3_SMI_CTRL_BASE	0xFC000000
-#define SPEAR6XX_ICM3_SMI_CTRL_SIZE	0x00200000
-
-#define SPEAR6XX_ICM3_CLCD_BASE		0xFC200000
-#define SPEAR6XX_ICM3_CLCD_SIZE		0x00200000
-
-#define SPEAR6XX_ICM3_DMA_BASE		0xFC400000
-#define SPEAR6XX_ICM3_DMA_SIZE		0x00200000
-
-#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE	0xFC600000
-#define SPEAR6XX_ICM3_SDRAM_CTRL_SIZE	0x00200000
-
-#define SPEAR6XX_ICM3_TMR_BASE		0xFC800000
-#define SPEAR6XX_ICM3_TMR_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_WDT_BASE		0xFC880000
-#define SPEAR6XX_ICM3_WDT_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_RTC_BASE		0xFC900000
-#define SPEAR6XX_ICM3_RTC_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_GPIO_BASE		0xFC980000
-#define SPEAR6XX_ICM3_GPIO_SIZE		0x00080000
-
-#define SPEAR6XX_ICM3_SYS_CTRL_BASE	0xFCA00000
+#define SPEAR6XX_ICM3_BASE		UL(0xF8000000)
+#define SPEAR6XX_ICM3_SMEM_BASE		UL(0xF8000000)
+#define SPEAR6XX_ICM3_SMI_CTRL_BASE	UL(0xFC000000)
+#define SPEAR6XX_ICM3_CLCD_BASE		UL(0xFC200000)
+#define SPEAR6XX_ICM3_DMA_BASE		UL(0xFC400000)
+#define SPEAR6XX_ICM3_SDRAM_CTRL_BASE	UL(0xFC600000)
+#define SPEAR6XX_ICM3_TMR_BASE		UL(0xFC800000)
+#define SPEAR6XX_ICM3_WDT_BASE		UL(0xFC880000)
+#define SPEAR6XX_ICM3_RTC_BASE		UL(0xFC900000)
+#define SPEAR6XX_ICM3_GPIO_BASE		UL(0xFC980000)
+#define SPEAR6XX_ICM3_SYS_CTRL_BASE	UL(0xFCA00000)
 #define VA_SPEAR6XX_ICM3_SYS_CTRL_BASE	IO_ADDRESS(SPEAR6XX_ICM3_SYS_CTRL_BASE)
-#define SPEAR6XX_ICM3_SYS_CTRL_SIZE	0x00080000
-
-#define SPEAR6XX_ICM3_MISC_REG_BASE	0xFCA80000
+#define SPEAR6XX_ICM3_MISC_REG_BASE	UL(0xFCA80000)
 #define VA_SPEAR6XX_ICM3_MISC_REG_BASE	IO_ADDRESS(SPEAR6XX_ICM3_MISC_REG_BASE)
-#define SPEAR6XX_ICM3_MISC_REG_SIZE	0x00080000
 
 /* ICM4 - High Speed Connection */
-#define SPEAR6XX_ICM4_BASE		0xE0000000
-#define SPEAR6XX_ICM4_SIZE		0x08000000
-
-#define SPEAR6XX_ICM4_GMAC_BASE		0xE0800000
-#define SPEAR6XX_ICM4_GMAC_SIZE		0x00800000
-
-#define SPEAR6XX_ICM4_USBD_FIFO_BASE	0xE1000000
-#define SPEAR6XX_ICM4_USBD_FIFO_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USBD_CSR_BASE	0xE1100000
-#define SPEAR6XX_ICM4_USBD_CSR_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USBD_PLDT_BASE	0xE1200000
-#define SPEAR6XX_ICM4_USBD_PLDT_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_EHCI0_BASE	0xE1800000
-#define SPEAR6XX_ICM4_USB_EHCI0_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_OHCI0_BASE	0xE1900000
-#define SPEAR6XX_ICM4_USB_OHCI0_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_EHCI1_BASE	0xE2000000
-#define SPEAR6XX_ICM4_USB_EHCI1_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_OHCI1_BASE	0xE2100000
-#define SPEAR6XX_ICM4_USB_OHCI1_SIZE	0x00100000
-
-#define SPEAR6XX_ICM4_USB_ARB_BASE	0xE2800000
-#define SPEAR6XX_ICM4_USB_ARB_SIZE	0x00010000
+#define SPEAR6XX_ICM4_BASE		UL(0xE0000000)
+#define SPEAR6XX_ICM4_GMAC_BASE		UL(0xE0800000)
+#define SPEAR6XX_ICM4_USBD_FIFO_BASE	UL(0xE1000000)
+#define SPEAR6XX_ICM4_USBD_CSR_BASE	UL(0xE1100000)
+#define SPEAR6XX_ICM4_USBD_PLDT_BASE	UL(0xE1200000)
+#define SPEAR6XX_ICM4_USB_EHCI0_BASE	UL(0xE1800000)
+#define SPEAR6XX_ICM4_USB_OHCI0_BASE	UL(0xE1900000)
+#define SPEAR6XX_ICM4_USB_EHCI1_BASE	UL(0xE2000000)
+#define SPEAR6XX_ICM4_USB_OHCI1_BASE	UL(0xE2100000)
+#define SPEAR6XX_ICM4_USB_ARB_BASE	UL(0xE2800000)
 
 /* Debug uart for linux, will be used for debug and uncompress messages */
 #define SPEAR_DBG_UART_BASE		SPEAR6XX_ICM1_UART0_BASE
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/spear600.c linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/spear600.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/spear600.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/spear600.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 #include <linux/ptrace.h>
 #include <asm/irq.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 /* Add spear600 specific devices here */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/spear600_evb.c linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/spear600_evb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/spear600_evb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/spear600_evb.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 static struct amba_device *amba_devs[] __initdata = {
 	&gpio_device[0],
@@ -46,6 +46,6 @@
 	.boot_params	=	0x00000100,
 	.map_io		=	spear6xx_map_io,
 	.init_irq	=	spear6xx_init_irq,
-	.timer		=	&spear_sys_timer,
+	.timer		=	&spear6xx_timer,
 	.init_machine	=	spear600_evb_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/spear6xx.c linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/spear6xx.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-spear6xx/spear6xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-spear6xx/spear6xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,9 +18,9 @@
 #include <asm/hardware/vic.h>
 #include <asm/irq.h>
 #include <asm/mach/arch.h>
-#include <mach/irqs.h>
 #include <mach/generic.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
 
 /* Add spear6xx machines common devices here */
 /* uart device registration */
@@ -31,8 +31,7 @@
 		},
 		.res = {
 			.start = SPEAR6XX_ICM1_UART0_BASE,
-			.end = SPEAR6XX_ICM1_UART0_BASE +
-				SPEAR6XX_ICM1_UART0_SIZE - 1,
+			.end = SPEAR6XX_ICM1_UART0_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_UART_0, NO_IRQ},
@@ -42,8 +41,7 @@
 		},
 		.res = {
 			.start = SPEAR6XX_ICM1_UART1_BASE,
-			.end = SPEAR6XX_ICM1_UART1_BASE +
-				SPEAR6XX_ICM1_UART1_SIZE - 1,
+			.end = SPEAR6XX_ICM1_UART1_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_UART_1, NO_IRQ},
@@ -72,8 +70,7 @@
 		},
 		.res = {
 			.start = SPEAR6XX_CPU_GPIO_BASE,
-			.end = SPEAR6XX_CPU_GPIO_BASE +
-				SPEAR6XX_CPU_GPIO_SIZE - 1,
+			.end = SPEAR6XX_CPU_GPIO_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_LOCAL_GPIO, NO_IRQ},
@@ -84,8 +81,7 @@
 		},
 		.res = {
 			.start = SPEAR6XX_ICM3_GPIO_BASE,
-			.end = SPEAR6XX_ICM3_GPIO_BASE +
-				SPEAR6XX_ICM3_GPIO_SIZE - 1,
+			.end = SPEAR6XX_ICM3_GPIO_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_BASIC_GPIO, NO_IRQ},
@@ -96,8 +92,7 @@
 		},
 		.res = {
 			.start = SPEAR6XX_ICM2_GPIO_BASE,
-			.end = SPEAR6XX_ICM2_GPIO_BASE +
-				SPEAR6XX_ICM2_GPIO_SIZE - 1,
+			.end = SPEAR6XX_ICM2_GPIO_BASE + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		},
 		.irq = {IRQ_APPL_GPIO, NO_IRQ},
@@ -122,27 +117,27 @@
 	{
 		.virtual	= VA_SPEAR6XX_ICM1_UART0_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM1_UART0_BASE),
-		.length		= SPEAR6XX_ICM1_UART0_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_CPU_VIC_PRI_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_CPU_VIC_PRI_BASE),
-		.length		= SPEAR6XX_CPU_VIC_PRI_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_CPU_VIC_SEC_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_CPU_VIC_SEC_BASE),
-		.length		= SPEAR6XX_CPU_VIC_SEC_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_ICM3_SYS_CTRL_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_SYS_CTRL_BASE),
-		.length		= SPEAR6XX_ICM3_MISC_REG_BASE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	}, {
 		.virtual	= VA_SPEAR6XX_ICM3_MISC_REG_BASE,
 		.pfn		= __phys_to_pfn(SPEAR6XX_ICM3_MISC_REG_BASE),
-		.length		= SPEAR6XX_ICM3_MISC_REG_SIZE,
+		.length		= SZ_4K,
 		.type		= MT_DEVICE
 	},
 };
@@ -155,3 +150,34 @@
 	/* This will initialize clock framework */
 	clk_init();
 }
+
+static void __init spear6xx_timer_init(void)
+{
+	char pclk_name[] = "pll3_48m_clk";
+	struct clk *gpt_clk, *pclk;
+
+	/* get the system timer clock */
+	gpt_clk = clk_get_sys("gpt0", NULL);
+	if (IS_ERR(gpt_clk)) {
+		pr_err("%s:couldn't get clk for gpt\n", __func__);
+		BUG();
+	}
+
+	/* get the suitable parent clock for timer*/
+	pclk = clk_get(NULL, pclk_name);
+	if (IS_ERR(pclk)) {
+		pr_err("%s:couldn't get %s as parent for gpt\n",
+				__func__, pclk_name);
+		BUG();
+	}
+
+	clk_set_parent(gpt_clk, pclk);
+	clk_put(gpt_clk);
+	clk_put(pclk);
+
+	spear_setup_timer();
+}
+
+struct sys_timer spear6xx_timer = {
+	.init = spear6xx_timer_init,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c linux-libre-2.6.39-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tcc8k/board-tcc8000-sdk.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
  * published by the Free Software Foundation.
  */
 
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/platform_device.h>
@@ -17,6 +18,8 @@
 #include <asm/mach/time.h>
 
 #include <mach/clock.h>
+#include <mach/tcc-nand.h>
+#include <mach/tcc8k-regs.h>
 
 #include "common.h"
 
@@ -51,10 +54,26 @@
 static void __init tcc8k_map_io(void)
 {
 	tcc8k_map_common_io();
+
+	/* set PLL0 clock to 96MHz, adapt UART0 divisor */
+	__raw_writel(0x00026003, CKC_BASE + PLL0CFG_OFFS);
+	__raw_writel(0x10000001, CKC_BASE + ACLKUART0_OFFS);
+
+	/* set PLL1 clock to 192MHz */
+	__raw_writel(0x00016003, CKC_BASE + PLL1CFG_OFFS);
+
+	/* set PLL2 clock to 48MHz */
+	__raw_writel(0x00036003, CKC_BASE + PLL2CFG_OFFS);
+
+	/* with CPU freq higher than 150 MHz, need extra DTCM wait */
+	__raw_writel(0x00000001, SCFG_BASE + DTCMWAIT_OFFS);
+
+	/* PLL locking time as specified */
+	udelay(300);
 }
 
 MACHINE_START(TCC8000_SDK, "Telechips TCC8000-SDK Demo Board")
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
 	.map_io		= tcc8k_map_io,
 	.init_irq	= tcc8k_init_irq,
 	.init_machine	= tcc8k_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tcc8k/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-tcc8k/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tcc8k/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tcc8k/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,11 +45,12 @@
 #define ACLKGSB1	(CKC_BASE + ACLKGSB1_OFFS)
 #define ACLKGSB2	(CKC_BASE + ACLKGSB2_OFFS)
 #define ACLKGSB3	(CKC_BASE + ACLKGSB3_OFFS)
-#define ACLKUSBH	(CKC_BASE + ACLKUSBH_OFFS)
 #define ACLKTCT		(CKC_BASE + ACLKTCT_OFFS)
 #define ACLKTCX		(CKC_BASE + ACLKTCX_OFFS)
 #define ACLKTCZ		(CKC_BASE + ACLKTCZ_OFFS)
 
+#define ACLK_MAX_DIV	(0xfff + 1)
+
 /* Crystal frequencies */
 static unsigned long xi_rate, xti_rate;
 
@@ -106,9 +107,9 @@
 	return 0;
 }
 
-static int root_clk_disable(enum root_clks root_src)
+static int root_clk_disable(enum root_clks src)
 {
-	switch (root_src) {
+	switch (src) {
 	case CLK_SRC_PLL0: return pll_enable(0, 0);
 	case CLK_SRC_PLL1: return pll_enable(1, 0);
 	case CLK_SRC_PLL2: return pll_enable(2, 0);
@@ -197,7 +198,7 @@
 		addr = CKC_BASE + CLKDIVC1_OFFS;
 		reg = __raw_readl(addr);
 		if (reg & CLKDIVC1_P2E)
-			div = __raw_readl(addr) & 0x3f;
+			div = reg & 0x3f;
 		break;
 	}
 	return get_rate_pll(pll) / (div + 1);
@@ -258,14 +259,19 @@
 {
 	unsigned long div, src, freq, r1, r2;
 
+	if (!rate)
+		return ACLK_MAX_DIV;
+
 	src = __raw_readl(clk->aclkreg) >> ACLK_SEL_SHIFT;
 	src &= CLK_SRC_MASK;
 	freq = root_clk_get_rate(src);
-	div = freq / rate + 1;
+	div = freq / rate;
+	if (!div)
+		return 1;
+	if (div >= ACLK_MAX_DIV)
+		return ACLK_MAX_DIV;
 	r1 = freq / div;
 	r2 = freq / (div + 1);
-	if (r2 >= rate)
-		return div + 1;
 	if ((rate - r2) < (r1 - rate))
 		return div + 1;
 
@@ -287,7 +293,8 @@
 	u32 reg;
 
 	reg = __raw_readl(clk->aclkreg) & ~ACLK_DIV_MASK;
-	reg |= aclk_best_div(clk, rate);
+	reg |= aclk_best_div(clk, rate) - 1;
+	__raw_writel(reg, clk->aclkreg);
 	return 0;
 }
 
@@ -296,15 +303,22 @@
 	unsigned int src;
 
 	src = __raw_readl(CKC_BASE + CLKCTRL_OFFS) & CLK_SRC_MASK;
-		return root_clk_get_rate(src);
+	return root_clk_get_rate(src);
 }
 
 static unsigned long get_rate_bus(struct clk *clk)
 {
-	unsigned int div;
+	unsigned int reg, sdiv, bdiv, rate;
 
-	div = (__raw_readl(CKC_BASE + CLKCTRL_OFFS) >> 4) & 0xff;
-	return get_rate_sys(clk) / (div + 1);
+	reg = __raw_readl(CKC_BASE + CLKCTRL_OFFS);
+	rate = get_rate_sys(clk);
+	sdiv = (reg >> 20) & 3;
+	if (sdiv)
+		rate /= sdiv + 1;
+	bdiv = (reg >> 4) & 0xff;
+	if (bdiv)
+		rate /= bdiv + 1;
+	return rate;
 }
 
 static unsigned long get_rate_cpu(struct clk *clk)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tcc8k/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-tcc8k/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tcc8k/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tcc8k/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,10 +102,10 @@
 
 	for (irqno = 0; irqno < NR_IRQS; irqno++) {
 		if (irqno < 32)
-			set_irq_chip(irqno, &tcc8000_irq_chip0);
+			irq_set_chip(irqno, &tcc8000_irq_chip0);
 		else
-			set_irq_chip(irqno, &tcc8000_irq_chip1);
-		set_irq_handler(irqno, handle_level_irq);
+			irq_set_chip(irqno, &tcc8000_irq_chip1);
+		irq_set_handler(irqno, handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,9 @@
 
 #include <linux/types.h>
 
-void __init tegra_common_init(void);
+void tegra_assert_system_reset(char mode, const char *cmd);
+
+void __init tegra_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_init_clock(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,7 @@
  * arch/arm/mach-tegra/board-harmony.c
  *
  * Copyright (C) 2010 Google, Inc.
+ * Copyright (C) 2011 NVIDIA, Inc.
  *
  * This software is licensed under the terms of the GNU General Public
  * License version 2, as published by the Free Software Foundation, and
@@ -22,43 +23,27 @@
 #include <linux/dma-mapping.h>
 #include <linux/pda_power.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+
+#include <sound/wm8903.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/setup.h>
 
+#include <mach/harmony_audio.h>
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/sdhci.h>
 
 #include "board.h"
 #include "board-harmony.h"
 #include "clock.h"
-
-/* NVidia bootloader tags */
-#define ATAG_NVIDIA		0x41000801
-
-#define ATAG_NVIDIA_RM			0x1
-#define ATAG_NVIDIA_DISPLAY		0x2
-#define ATAG_NVIDIA_FRAMEBUFFER		0x3
-#define ATAG_NVIDIA_CHIPSHMOO		0x4
-#define ATAG_NVIDIA_CHIPSHMOOPHYS	0x5
-#define ATAG_NVIDIA_PRESERVED_MEM_0	0x10000
-#define ATAG_NVIDIA_PRESERVED_MEM_N	2
-#define ATAG_NVIDIA_FORCE_32		0x7fffffff
-
-struct tag_tegra {
-	__u32 bootarg_key;
-	__u32 bootarg_len;
-	char bootarg[1];
-};
-
-static int __init parse_tag_nvidia(const struct tag *tag)
-{
-
-	return 0;
-}
-__tagtable(ATAG_NVIDIA, parse_tag_nvidia);
+#include "devices.h"
+#include "gpio-names.h"
 
 static struct plat_serial8250_port debug_uart_platform_data[] = {
 	{
@@ -82,8 +67,81 @@
 	},
 };
 
+static struct harmony_audio_platform_data harmony_audio_pdata = {
+	.gpio_spkr_en		= TEGRA_GPIO_SPKR_EN,
+	.gpio_hp_det		= TEGRA_GPIO_HP_DET,
+	.gpio_int_mic_en	= TEGRA_GPIO_INT_MIC_EN,
+	.gpio_ext_mic_en	= TEGRA_GPIO_EXT_MIC_EN,
+};
+
+static struct platform_device harmony_audio_device = {
+	.name	= "tegra-snd-harmony",
+	.id	= 0,
+	.dev	= {
+		.platform_data  = &harmony_audio_pdata,
+	},
+};
+
+static struct tegra_i2c_platform_data harmony_i2c1_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data harmony_i2c2_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data harmony_i2c3_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct tegra_i2c_platform_data harmony_dvc_platform_data = {
+	.bus_clk_rate   = 400000,
+};
+
+static struct wm8903_platform_data harmony_wm8903_pdata = {
+	.irq_active_low = 0,
+	.micdet_cfg = 0,
+	.micdet_delay = 100,
+	.gpio_base = HARMONY_GPIO_WM8903(0),
+	.gpio_cfg = {
+		WM8903_GPIO_NO_CONFIG,
+		WM8903_GPIO_NO_CONFIG,
+		0,
+		WM8903_GPIO_NO_CONFIG,
+		WM8903_GPIO_NO_CONFIG,
+	},
+};
+
+static struct i2c_board_info __initdata wm8903_board_info = {
+	I2C_BOARD_INFO("wm8903", 0x1a),
+	.platform_data = &harmony_wm8903_pdata,
+	.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_CDC_IRQ),
+};
+
+static void __init harmony_i2c_init(void)
+{
+	tegra_i2c_device1.dev.platform_data = &harmony_i2c1_platform_data;
+	tegra_i2c_device2.dev.platform_data = &harmony_i2c2_platform_data;
+	tegra_i2c_device3.dev.platform_data = &harmony_i2c3_platform_data;
+	tegra_i2c_device4.dev.platform_data = &harmony_dvc_platform_data;
+
+	platform_device_register(&tegra_i2c_device1);
+	platform_device_register(&tegra_i2c_device2);
+	platform_device_register(&tegra_i2c_device3);
+	platform_device_register(&tegra_i2c_device4);
+
+	i2c_register_board_info(0, &wm8903_board_info, 1);
+}
+
 static struct platform_device *harmony_devices[] __initdata = {
 	&debug_uart,
+	&tegra_sdhci_device1,
+	&tegra_sdhci_device2,
+	&tegra_sdhci_device4,
+	&tegra_i2s_device1,
+	&tegra_das_device,
+	&tegra_pcm_device,
+	&harmony_audio_device,
 };
 
 static void __init tegra_harmony_fixup(struct machine_desc *desc,
@@ -99,25 +157,54 @@
 static __initdata struct tegra_clk_init_table harmony_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "uartd",	"pll_p",	216000000,	true },
+	{ "pll_a",	"pll_p_out1",	56448000,	true },
+	{ "pll_a_out0",	"pll_a",	11289600,	true },
+	{ "cdev1",	NULL,		0,		true },
+	{ "i2s1",	"pll_a_out0",	11289600,	false},
 	{ NULL,		NULL,		0,		0},
 };
 
+
+static struct tegra_sdhci_platform_data sdhci_pdata1 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata2 = {
+	.cd_gpio	= TEGRA_GPIO_SD2_CD,
+	.wp_gpio	= TEGRA_GPIO_SD2_WP,
+	.power_gpio	= TEGRA_GPIO_SD2_POWER,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
+	.cd_gpio	= TEGRA_GPIO_SD4_CD,
+	.wp_gpio	= TEGRA_GPIO_SD4_WP,
+	.power_gpio	= TEGRA_GPIO_SD4_POWER,
+	.is_8bit	= 1,
+};
+
 static void __init tegra_harmony_init(void)
 {
-	tegra_common_init();
-
 	tegra_clk_init_from_table(harmony_clk_init_table);
 
 	harmony_pinmux_init();
 
+	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
+	tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
+	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
+
 	platform_add_devices(harmony_devices, ARRAY_SIZE(harmony_devices));
+	harmony_i2c_init();
+	harmony_regulator_init();
 }
 
 MACHINE_START(HARMONY, "harmony")
 	.boot_params  = 0x00000100,
 	.fixup		= tegra_harmony_fixup,
-	.init_irq       = tegra_init_irq,
-	.init_machine   = tegra_harmony_init,
 	.map_io         = tegra_map_common_io,
+	.init_early	= tegra_init_early,
+	.init_irq       = tegra_init_irq,
 	.timer          = &tegra_timer,
+	.init_machine   = tegra_harmony_init,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,21 @@
 #ifndef _MACH_TEGRA_BOARD_HARMONY_H
 #define _MACH_TEGRA_BOARD_HARMONY_H
 
+#define HARMONY_GPIO_WM8903(_x_)	(TEGRA_NR_GPIOS + (_x_))
+
+#define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5
+#define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1
+#define TEGRA_GPIO_SD2_POWER		TEGRA_GPIO_PT3
+#define TEGRA_GPIO_SD4_CD		TEGRA_GPIO_PH2
+#define TEGRA_GPIO_SD4_WP		TEGRA_GPIO_PH3
+#define TEGRA_GPIO_SD4_POWER		TEGRA_GPIO_PI6
+#define TEGRA_GPIO_CDC_IRQ		TEGRA_GPIO_PX3
+#define TEGRA_GPIO_SPKR_EN		HARMONY_GPIO_WM8903(2)
+#define TEGRA_GPIO_HP_DET		TEGRA_GPIO_PW2
+#define TEGRA_GPIO_INT_MIC_EN		TEGRA_GPIO_PX0
+#define TEGRA_GPIO_EXT_MIC_EN		TEGRA_GPIO_PX1
+
 void harmony_pinmux_init(void);
+int harmony_regulator_init(void);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony-pcie.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony-pcie.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony-pcie.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony-pcie.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,13 +27,29 @@
 
 #ifdef CONFIG_TEGRA_PCI
 
+/* GPIO 3 of the PMIC */
+#define EN_VDD_1V05_GPIO	(TEGRA_NR_GPIOS + 2)
+
 static int __init harmony_pcie_init(void)
 {
+	struct regulator *regulator = NULL;
 	int err;
 
 	if (!machine_is_harmony())
 		return 0;
 
+	err = gpio_request(EN_VDD_1V05_GPIO, "EN_VDD_1V05");
+	if (err)
+		return err;
+
+	gpio_direction_output(EN_VDD_1V05_GPIO, 1);
+
+	regulator = regulator_get(NULL, "pex_clk");
+	if (IS_ERR_OR_NULL(regulator))
+		goto err_reg;
+
+	regulator_enable(regulator);
+
 	tegra_pinmux_set_tristate(TEGRA_PINGROUP_GPV, TEGRA_TRI_NORMAL);
 	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_NORMAL);
 	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_NORMAL);
@@ -49,9 +65,15 @@
 	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXA, TEGRA_TRI_TRISTATE);
 	tegra_pinmux_set_tristate(TEGRA_PINGROUP_SLXK, TEGRA_TRI_TRISTATE);
 
+	regulator_disable(regulator);
+	regulator_put(regulator);
+err_reg:
+	gpio_free(EN_VDD_1V05_GPIO);
+
 	return err;
 }
 
-subsys_initcall(harmony_pcie_init);
+/* PCI should be initialized after I2C, mfd and regulators */
+subsys_initcall_sync(harmony_pcie_init);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony-pinmux.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,8 +15,10 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/gpio.h>
 #include <mach/pinmux.h>
 
+#include "gpio-names.h"
 #include "board-harmony.h"
 
 static struct tegra_pingroup_config harmony_pinmux[] = {
@@ -25,19 +27,19 @@
 	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
-	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
-	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
 	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
@@ -112,13 +114,13 @@
 	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
-	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
 	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
@@ -138,7 +140,22 @@
 	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
 };
 
+static struct tegra_gpio_table gpio_table[] = {
+	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD2_POWER,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD4_CD,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD4_WP,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD4_POWER,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_CDC_IRQ,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_HP_DET,		.enable = true	},
+	{ .gpio = TEGRA_GPIO_INT_MIC_EN,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_EXT_MIC_EN,	.enable = true	},
+};
+
 void harmony_pinmux_init(void)
 {
 	tegra_pinmux_config_table(harmony_pinmux, ARRAY_SIZE(harmony_pinmux));
+
+	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony-power.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony-power.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-harmony-power.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-harmony-power.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,117 @@
+/*
+ * Copyright (C) 2010 NVIDIA, 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/gpio.h>
+
+#include <linux/regulator/machine.h>
+#include <linux/mfd/tps6586x.h>
+
+#include <mach/irqs.h>
+
+#define PMC_CTRL		0x0
+#define PMC_CTRL_INTR_LOW	(1 << 17)
+
+static struct regulator_consumer_supply tps658621_ldo0_supply[] = {
+	REGULATOR_SUPPLY("pex_clk", NULL),
+};
+
+static struct regulator_init_data ldo0_data = {
+	.constraints = {
+		.min_uV = 1250 * 1000,
+		.max_uV = 3300 * 1000,
+		.valid_modes_mask = (REGULATOR_MODE_NORMAL |
+				     REGULATOR_MODE_STANDBY),
+		.valid_ops_mask = (REGULATOR_CHANGE_MODE |
+				   REGULATOR_CHANGE_STATUS |
+				   REGULATOR_CHANGE_VOLTAGE),
+	},
+	.num_consumer_supplies = ARRAY_SIZE(tps658621_ldo0_supply),
+	.consumer_supplies = tps658621_ldo0_supply,
+};
+
+#define HARMONY_REGULATOR_INIT(_id, _minmv, _maxmv)			\
+	static struct regulator_init_data _id##_data = {		\
+		.constraints = {					\
+			.min_uV = (_minmv)*1000,			\
+			.max_uV = (_maxmv)*1000,			\
+			.valid_modes_mask = (REGULATOR_MODE_NORMAL |	\
+					     REGULATOR_MODE_STANDBY),	\
+			.valid_ops_mask = (REGULATOR_CHANGE_MODE |	\
+					   REGULATOR_CHANGE_STATUS |	\
+					   REGULATOR_CHANGE_VOLTAGE),	\
+		},							\
+	}
+
+HARMONY_REGULATOR_INIT(sm0, 725, 1500);
+HARMONY_REGULATOR_INIT(sm1, 725, 1500);
+HARMONY_REGULATOR_INIT(sm2, 3000, 4550);
+HARMONY_REGULATOR_INIT(ldo1, 725, 1500);
+HARMONY_REGULATOR_INIT(ldo2, 725, 1500);
+HARMONY_REGULATOR_INIT(ldo3, 1250, 3300);
+HARMONY_REGULATOR_INIT(ldo4, 1700, 2475);
+HARMONY_REGULATOR_INIT(ldo5, 1250, 3300);
+HARMONY_REGULATOR_INIT(ldo6, 1250, 3300);
+HARMONY_REGULATOR_INIT(ldo7, 1250, 3300);
+HARMONY_REGULATOR_INIT(ldo8, 1250, 3300);
+HARMONY_REGULATOR_INIT(ldo9, 1250, 3300);
+
+#define TPS_REG(_id, _data)			\
+	{					\
+		.id = TPS6586X_ID_##_id,	\
+		.name = "tps6586x-regulator",	\
+		.platform_data = _data,		\
+	}
+
+static struct tps6586x_subdev_info tps_devs[] = {
+	TPS_REG(SM_0, &sm0_data),
+	TPS_REG(SM_1, &sm1_data),
+	TPS_REG(SM_2, &sm2_data),
+	TPS_REG(LDO_0, &ldo0_data),
+	TPS_REG(LDO_1, &ldo1_data),
+	TPS_REG(LDO_2, &ldo2_data),
+	TPS_REG(LDO_3, &ldo3_data),
+	TPS_REG(LDO_4, &ldo4_data),
+	TPS_REG(LDO_5, &ldo5_data),
+	TPS_REG(LDO_6, &ldo6_data),
+	TPS_REG(LDO_7, &ldo7_data),
+	TPS_REG(LDO_8, &ldo8_data),
+	TPS_REG(LDO_9, &ldo9_data),
+};
+
+static struct tps6586x_platform_data tps_platform = {
+	.irq_base	= TEGRA_NR_IRQS,
+	.num_subdevs	= ARRAY_SIZE(tps_devs),
+	.subdevs	= tps_devs,
+	.gpio_base	= TEGRA_NR_GPIOS,
+};
+
+static struct i2c_board_info __initdata harmony_regulators[] = {
+	{
+		I2C_BOARD_INFO("tps6586x", 0x34),
+		.irq		= INT_EXTERNAL_PMU,
+		.platform_data	= &tps_platform,
+	},
+};
+
+int __init harmony_regulator_init(void)
+{
+	i2c_register_board_info(3, harmony_regulators, 1);
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-paz00.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-paz00.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-paz00.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-paz00.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,128 @@
+/*
+ * arch/arm/mach-tegra/board-paz00.c
+ *
+ * Copyright (C) 2011 Marc Dietrich <marvin24@gmx.de>
+ *
+ * Based on board-harmony.c
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/pda_power.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/time.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/sdhci.h>
+
+#include "board.h"
+#include "board-paz00.h"
+#include "clock.h"
+#include "devices.h"
+#include "gpio-names.h"
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+	{
+		.membase	= IO_ADDRESS(TEGRA_UARTD_BASE),
+		.mapbase	= TEGRA_UARTD_BASE,
+		.irq		= INT_UARTD,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		.flags		= 0
+	}
+};
+
+static struct platform_device debug_uart = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = debug_uart_platform_data,
+	},
+};
+
+static struct platform_device *paz00_devices[] __initdata = {
+	&debug_uart,
+	&tegra_sdhci_device1,
+	&tegra_sdhci_device2,
+	&tegra_sdhci_device4,
+};
+
+static void __init tegra_paz00_fixup(struct machine_desc *desc,
+	struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks = 1;
+	mi->bank[0].start = PHYS_OFFSET;
+	mi->bank[0].size = 448 * SZ_1M;
+}
+
+static __initdata struct tegra_clk_init_table paz00_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uartd",	"pll_p",	216000000,	true },
+	{ NULL,		NULL,		0,		0},
+};
+
+
+static struct tegra_sdhci_platform_data sdhci_pdata1 = {
+	.cd_gpio	= TEGRA_GPIO_SD1_CD,
+	.wp_gpio	= TEGRA_GPIO_SD1_WP,
+	.power_gpio	= TEGRA_GPIO_SD1_POWER,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata2 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
+	.cd_gpio	= TEGRA_GPIO_SD4_CD,
+	.wp_gpio	= TEGRA_GPIO_SD4_WP,
+	.power_gpio	= TEGRA_GPIO_SD4_POWER,
+	.is_8bit	= 1,
+};
+
+static void __init tegra_paz00_init(void)
+{
+	tegra_clk_init_from_table(paz00_clk_init_table);
+
+	paz00_pinmux_init();
+
+	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
+	tegra_sdhci_device2.dev.platform_data = &sdhci_pdata2;
+	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
+
+	platform_add_devices(paz00_devices, ARRAY_SIZE(paz00_devices));
+}
+
+MACHINE_START(PAZ00, "paz00")
+	.boot_params	= 0x00000100,
+	.fixup		= tegra_paz00_fixup,
+	.map_io         = tegra_map_common_io,
+	.init_early	= tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_paz00_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-paz00.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-paz00.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-paz00.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-paz00.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * arch/arm/mach-tegra/board-paz00.h
+ *
+ * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_PAZ00_H
+#define _MACH_TEGRA_BOARD_PAZ00_H
+
+#define TEGRA_GPIO_SD1_CD               TEGRA_GPIO_PV5
+#define TEGRA_GPIO_SD1_WP               TEGRA_GPIO_PH1
+#define TEGRA_GPIO_SD1_POWER            TEGRA_GPIO_PT3
+#define TEGRA_GPIO_SD4_CD               TEGRA_GPIO_PH2
+#define TEGRA_GPIO_SD4_WP               TEGRA_GPIO_PH3
+#define TEGRA_GPIO_SD4_POWER            TEGRA_GPIO_PI6
+
+void paz00_pinmux_init(void);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-paz00-pinmux.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,157 @@
+/*
+ * arch/arm/mach-tegra/board-paz00-pinmux.c
+ *
+ * Copyright (C) 2010 Marc Dietrich <marvin24@gmx.de>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/gpio.h>
+#include <mach/pinmux.h>
+
+#include "gpio-names.h"
+#include "board-paz00.h"
+
+static struct tegra_pingroup_config paz00_pinmux[] = {
+	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_PLLC_OUT1,     TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_RSVD1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMB,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMC,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GME,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTA,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTA,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCB,  TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCD,  TEGRA_MUX_SDIO2,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LCSN,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDC,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LM1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSCK,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_OWC,   TEGRA_MUX_OWR,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PTA,   TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDB,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SDC,   TEGRA_MUX_TWC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SDD,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SPI4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SPI4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_SPDIF,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+};
+
+static struct tegra_gpio_table gpio_table[] = {
+	{ .gpio = TEGRA_GPIO_SD1_CD,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD1_WP,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD1_POWER,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD4_CD,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD4_WP,	.enable = true	},
+	{ .gpio = TEGRA_GPIO_SD4_POWER,	.enable = true	},
+};
+
+void paz00_pinmux_init(void)
+{
+	tegra_pinmux_config_table(paz00_pinmux, ARRAY_SIZE(paz00_pinmux));
+
+	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-seaboard.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-seaboard.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-seaboard.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-seaboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,250 @@
+/*
+ * Copyright (c) 2010, 2011 NVIDIA Corporation.
+ * Copyright (C) 2010, 2011 Google, 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.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/i2c.h>
+#include <linux/i2c-tegra.h>
+#include <linux/delay.h>
+#include <linux/input.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+
+#include <mach/iomap.h>
+#include <mach/irqs.h>
+#include <mach/sdhci.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "board.h"
+#include "board-seaboard.h"
+#include "clock.h"
+#include "devices.h"
+#include "gpio-names.h"
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+	{
+		/* Memory and IRQ filled in before registration */
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		.flags		= 0,
+	}
+};
+
+static struct platform_device debug_uart = {
+	.name = "serial8250",
+	.id = PLAT8250_DEV_PLATFORM,
+	.dev = {
+		.platform_data = debug_uart_platform_data,
+	},
+};
+
+static __initdata struct tegra_clk_init_table seaboard_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uartb",	"pll_p",	216000000,	true},
+	{ "uartd",	"pll_p",	216000000,	true},
+	{ NULL,		NULL,		0,		0},
+};
+
+static struct tegra_i2c_platform_data seaboard_i2c1_platform_data = {
+	.bus_clk_rate	= 400000.
+};
+
+static struct tegra_i2c_platform_data seaboard_i2c2_platform_data = {
+	.bus_clk_rate	= 400000,
+};
+
+static struct tegra_i2c_platform_data seaboard_i2c3_platform_data = {
+	.bus_clk_rate	= 400000,
+};
+
+static struct tegra_i2c_platform_data seaboard_dvc_platform_data = {
+	.bus_clk_rate	= 400000,
+};
+
+static struct gpio_keys_button seaboard_gpio_keys_buttons[] = {
+	{
+		.code		= SW_LID,
+		.gpio		= TEGRA_GPIO_LIDSWITCH,
+		.active_low	= 0,
+		.desc		= "Lid",
+		.type		= EV_SW,
+		.wakeup		= 1,
+		.debounce_interval = 1,
+	},
+	{
+		.code		= KEY_POWER,
+		.gpio		= TEGRA_GPIO_POWERKEY,
+		.active_low	= 1,
+		.desc		= "Power",
+		.type		= EV_KEY,
+		.wakeup		= 1,
+	},
+};
+
+static struct gpio_keys_platform_data seaboard_gpio_keys = {
+	.buttons	= seaboard_gpio_keys_buttons,
+	.nbuttons	= ARRAY_SIZE(seaboard_gpio_keys_buttons),
+};
+
+static struct platform_device seaboard_gpio_keys_device = {
+	.name		= "gpio-keys",
+	.id		= -1,
+	.dev		= {
+		.platform_data = &seaboard_gpio_keys,
+	}
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata1 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata3 = {
+	.cd_gpio	= TEGRA_GPIO_SD2_CD,
+	.wp_gpio	= TEGRA_GPIO_SD2_WP,
+	.power_gpio	= TEGRA_GPIO_SD2_POWER,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+	.is_8bit	= 1,
+};
+
+static struct platform_device *seaboard_devices[] __initdata = {
+	&debug_uart,
+	&tegra_pmu_device,
+	&tegra_sdhci_device1,
+	&tegra_sdhci_device3,
+	&tegra_sdhci_device4,
+	&seaboard_gpio_keys_device,
+};
+
+static struct i2c_board_info __initdata isl29018_device = {
+	I2C_BOARD_INFO("isl29018", 0x44),
+	.irq = TEGRA_GPIO_TO_IRQ(TEGRA_GPIO_ISL29018_IRQ),
+};
+
+static struct i2c_board_info __initdata adt7461_device = {
+	I2C_BOARD_INFO("adt7461", 0x4c),
+};
+
+static void __init seaboard_i2c_init(void)
+{
+	gpio_request(TEGRA_GPIO_ISL29018_IRQ, "isl29018");
+	gpio_direction_input(TEGRA_GPIO_ISL29018_IRQ);
+
+	i2c_register_board_info(0, &isl29018_device, 1);
+
+	i2c_register_board_info(4, &adt7461_device, 1);
+
+	tegra_i2c_device1.dev.platform_data = &seaboard_i2c1_platform_data;
+	tegra_i2c_device2.dev.platform_data = &seaboard_i2c2_platform_data;
+	tegra_i2c_device3.dev.platform_data = &seaboard_i2c3_platform_data;
+	tegra_i2c_device4.dev.platform_data = &seaboard_dvc_platform_data;
+
+	platform_device_register(&tegra_i2c_device1);
+	platform_device_register(&tegra_i2c_device2);
+	platform_device_register(&tegra_i2c_device3);
+	platform_device_register(&tegra_i2c_device4);
+}
+
+static void __init seaboard_common_init(void)
+{
+	seaboard_pinmux_init();
+
+	tegra_clk_init_from_table(seaboard_clk_init_table);
+
+	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
+	tegra_sdhci_device3.dev.platform_data = &sdhci_pdata3;
+	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
+
+	platform_add_devices(seaboard_devices, ARRAY_SIZE(seaboard_devices));
+}
+
+static void __init tegra_seaboard_init(void)
+{
+	/* Seaboard uses UARTD for the debug port. */
+	debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTD_BASE);
+	debug_uart_platform_data[0].mapbase = TEGRA_UARTD_BASE;
+	debug_uart_platform_data[0].irq = INT_UARTD;
+
+	seaboard_common_init();
+
+	seaboard_i2c_init();
+}
+
+static void __init tegra_kaen_init(void)
+{
+	/* Kaen uses UARTB for the debug port. */
+	debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
+	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
+	debug_uart_platform_data[0].irq = INT_UARTB;
+
+	seaboard_common_init();
+
+	seaboard_i2c_init();
+}
+
+static void __init tegra_wario_init(void)
+{
+	/* Wario uses UARTB for the debug port. */
+	debug_uart_platform_data[0].membase = IO_ADDRESS(TEGRA_UARTB_BASE);
+	debug_uart_platform_data[0].mapbase = TEGRA_UARTB_BASE;
+	debug_uart_platform_data[0].irq = INT_UARTB;
+
+	seaboard_common_init();
+
+	seaboard_i2c_init();
+}
+
+
+MACHINE_START(SEABOARD, "seaboard")
+	.boot_params    = 0x00000100,
+	.map_io         = tegra_map_common_io,
+	.init_early     = tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_seaboard_init,
+MACHINE_END
+
+MACHINE_START(KAEN, "kaen")
+	.boot_params    = 0x00000100,
+	.map_io         = tegra_map_common_io,
+	.init_early     = tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_kaen_init,
+MACHINE_END
+
+MACHINE_START(WARIO, "wario")
+	.boot_params    = 0x00000100,
+	.map_io         = tegra_map_common_io,
+	.init_early     = tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_wario_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-seaboard.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-seaboard.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-seaboard.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-seaboard.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * arch/arm/mach-tegra/board-seaboard.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_SEABOARD_H
+#define _MACH_TEGRA_BOARD_SEABOARD_H
+
+#define TEGRA_GPIO_SD2_CD		TEGRA_GPIO_PI5
+#define TEGRA_GPIO_SD2_WP		TEGRA_GPIO_PH1
+#define TEGRA_GPIO_SD2_POWER		TEGRA_GPIO_PI6
+#define TEGRA_GPIO_LIDSWITCH		TEGRA_GPIO_PC7
+#define TEGRA_GPIO_USB1			TEGRA_GPIO_PD0
+#define TEGRA_GPIO_POWERKEY		TEGRA_GPIO_PV2
+#define TEGRA_GPIO_BACKLIGHT		TEGRA_GPIO_PD4
+#define TEGRA_GPIO_LVDS_SHUTDOWN	TEGRA_GPIO_PB2
+#define TEGRA_GPIO_BACKLIGHT_PWM	TEGRA_GPIO_PU5
+#define TEGRA_GPIO_BACKLIGHT_VDD	TEGRA_GPIO_PW0
+#define TEGRA_GPIO_EN_VDD_PNL		TEGRA_GPIO_PC6
+#define TEGRA_GPIO_MAGNETOMETER		TEGRA_GPIO_PN5
+#define TEGRA_GPIO_ISL29018_IRQ		TEGRA_GPIO_PZ2
+#define TEGRA_GPIO_AC_ONLINE		TEGRA_GPIO_PV3
+
+#define TPS_GPIO_BASE			TEGRA_NR_GPIOS
+
+#define TPS_GPIO_WWAN_PWR		(TPS_GPIO_BASE + 2)
+
+void seaboard_pinmux_init(void);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-seaboard-pinmux.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2010 NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/gpio.h>
+
+#include <mach/pinmux.h>
+#include <mach/pinmux-t2.h>
+
+#include "gpio-names.h"
+#include "board-seaboard.h"
+
+#define DEFAULT_DRIVE(_name)					\
+	{							\
+		.pingroup = TEGRA_DRIVE_PINGROUP_##_name,	\
+		.hsm = TEGRA_HSM_DISABLE,			\
+		.schmitt = TEGRA_SCHMITT_ENABLE,		\
+		.drive = TEGRA_DRIVE_DIV_1,			\
+		.pull_down = TEGRA_PULL_31,			\
+		.pull_up = TEGRA_PULL_31,			\
+		.slew_rising = TEGRA_SLEW_SLOWEST,		\
+		.slew_falling = TEGRA_SLEW_SLOWEST,		\
+	}
+
+static __initdata struct tegra_drive_pingroup_config seaboard_drive_pinmux[] = {
+	DEFAULT_DRIVE(SDIO1),
+};
+
+static __initdata struct tegra_pingroup_config seaboard_pinmux[] = {
+	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_PLLA_OUT,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_VI,            TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMB,   TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GMC,   TEGRA_MUX_UARTD,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,   TEGRA_MUX_SFLASH,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GME,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCB,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCD,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LCSN,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDC,   TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM0,   TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM1,   TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW0,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW1,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW2,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSCK,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA,  TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDI,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVP0,  TEGRA_MUX_RSVD4,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_OWC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PTA,   TEGRA_MUX_HDMI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDB,   TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDC,   TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDD,   TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_GMI,           TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN, TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,    TEGRA_TRI_NORMAL},
+};
+
+
+
+
+static struct tegra_gpio_table gpio_table[] = {
+	{ .gpio = TEGRA_GPIO_SD2_CD,		.enable = true },
+	{ .gpio = TEGRA_GPIO_SD2_WP,		.enable = true },
+	{ .gpio = TEGRA_GPIO_SD2_POWER,		.enable = true },
+	{ .gpio = TEGRA_GPIO_LIDSWITCH,		.enable = true },
+	{ .gpio = TEGRA_GPIO_POWERKEY,		.enable = true },
+	{ .gpio = TEGRA_GPIO_ISL29018_IRQ,	.enable = true },
+};
+
+void __init seaboard_pinmux_init(void)
+{
+	tegra_pinmux_config_table(seaboard_pinmux, ARRAY_SIZE(seaboard_pinmux));
+
+	tegra_drive_pinmux_config_table(seaboard_drive_pinmux,
+					ARRAY_SIZE(seaboard_drive_pinmux));
+
+	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-trimslice.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-trimslice.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-trimslice.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-trimslice.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,125 @@
+/*
+ * arch/arm/mach-tegra/board-trimslice.c
+ *
+ * Copyright (C) 2011 CompuLab, Ltd.
+ * Author: Mike Rapoport <mike@compulab.co.il>
+ *
+ * Based on board-harmony.c
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/platform_device.h>
+#include <linux/serial_8250.h>
+#include <linux/io.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <asm/setup.h>
+
+#include <mach/iomap.h>
+#include <mach/sdhci.h>
+
+#include "board.h"
+#include "clock.h"
+#include "devices.h"
+#include "gpio-names.h"
+
+#include "board-trimslice.h"
+
+static struct plat_serial8250_port debug_uart_platform_data[] = {
+	{
+		.membase	= IO_ADDRESS(TEGRA_UARTA_BASE),
+		.mapbase	= TEGRA_UARTA_BASE,
+		.irq		= INT_UARTA,
+		.flags		= UPF_BOOT_AUTOCONF,
+		.iotype		= UPIO_MEM,
+		.regshift	= 2,
+		.uartclk	= 216000000,
+	}, {
+		.flags		= 0
+	}
+};
+
+static struct platform_device debug_uart = {
+	.name	= "serial8250",
+	.id	= PLAT8250_DEV_PLATFORM,
+	.dev	= {
+		.platform_data	= debug_uart_platform_data,
+	},
+};
+static struct tegra_sdhci_platform_data sdhci_pdata1 = {
+	.cd_gpio	= -1,
+	.wp_gpio	= -1,
+	.power_gpio	= -1,
+};
+
+static struct tegra_sdhci_platform_data sdhci_pdata4 = {
+	.cd_gpio	= TRIMSLICE_GPIO_SD4_CD,
+	.wp_gpio	= TRIMSLICE_GPIO_SD4_WP,
+	.power_gpio	= -1,
+};
+
+static struct platform_device *trimslice_devices[] __initdata = {
+	&debug_uart,
+	&tegra_sdhci_device1,
+	&tegra_sdhci_device4,
+};
+
+static void __init tegra_trimslice_fixup(struct machine_desc *desc,
+	struct tag *tags, char **cmdline, struct meminfo *mi)
+{
+	mi->nr_banks = 2;
+	mi->bank[0].start = PHYS_OFFSET;
+	mi->bank[0].size = 448 * SZ_1M;
+	mi->bank[1].start = SZ_512M;
+	mi->bank[1].size = SZ_512M;
+}
+
+static __initdata struct tegra_clk_init_table trimslice_clk_init_table[] = {
+	/* name		parent		rate		enabled */
+	{ "uarta",	"pll_p",	216000000,	true },
+	{ NULL,		NULL,		0,		0},
+};
+
+static int __init tegra_trimslice_pci_init(void)
+{
+	if (!machine_is_trimslice())
+		return 0;
+
+	return tegra_pcie_init(true, true);
+}
+subsys_initcall(tegra_trimslice_pci_init);
+
+static void __init tegra_trimslice_init(void)
+{
+	tegra_clk_init_from_table(trimslice_clk_init_table);
+
+	trimslice_pinmux_init();
+
+	tegra_sdhci_device1.dev.platform_data = &sdhci_pdata1;
+	tegra_sdhci_device4.dev.platform_data = &sdhci_pdata4;
+
+	platform_add_devices(trimslice_devices, ARRAY_SIZE(trimslice_devices));
+}
+
+MACHINE_START(TRIMSLICE, "trimslice")
+	.boot_params	= 0x00000100,
+	.fixup		= tegra_trimslice_fixup,
+	.map_io         = tegra_map_common_io,
+	.init_early	= tegra_init_early,
+	.init_irq       = tegra_init_irq,
+	.timer          = &tegra_timer,
+	.init_machine   = tegra_trimslice_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-trimslice.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-trimslice.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-trimslice.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-trimslice.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * arch/arm/mach-tegra/board-trimslice.h
+ *
+ * Copyright (C) 2011 CompuLab, Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MACH_TEGRA_BOARD_TRIMSLICE_H
+#define _MACH_TEGRA_BOARD_TRIMSLICE_H
+
+#define TRIMSLICE_GPIO_SD4_CD	TEGRA_GPIO_PP1	/* mmc4 cd */
+#define TRIMSLICE_GPIO_SD4_WP	TEGRA_GPIO_PP2	/* mmc4 wp */
+
+void trimslice_pinmux_init(void);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/board-trimslice-pinmux.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * arch/arm/mach-tegra/board-trimslice-pinmux.c
+ *
+ * Copyright (C) 2011 CompuLab, Ltd.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <mach/pinmux.h>
+#include <mach/gpio.h>
+
+#include "gpio-names.h"
+#include "board-trimslice.h"
+
+static __initdata struct tegra_pingroup_config trimslice_pinmux[] = {
+	{TEGRA_PINGROUP_ATA,   TEGRA_MUX_IDE,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_ATB,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,	TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_ATC,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_ATD,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_ATE,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,	TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CDEV1, TEGRA_MUX_OSC,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_CDEV2, TEGRA_MUX_PLLP_OUT4,     TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CRTP,  TEGRA_MUX_CRT,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CSUS,  TEGRA_MUX_VI_SENSOR_CLK, TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP1,  TEGRA_MUX_DAP1,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP2,  TEGRA_MUX_DAP2,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DAP3,  TEGRA_MUX_DAP3,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DAP4,  TEGRA_MUX_DAP4,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DDC,   TEGRA_MUX_I2C2,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DTA,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTB,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTC,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTD,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTE,   TEGRA_MUX_VI,            TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_DTF,   TEGRA_MUX_I2C3,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMA,   TEGRA_MUX_SDIO4,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMB,   TEGRA_MUX_NAND,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GMC,   TEGRA_MUX_SFLASH,        TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GMD,   TEGRA_MUX_SFLASH,        TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GME,   TEGRA_MUX_GMI,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_GPU,   TEGRA_MUX_UARTA,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPU7,  TEGRA_MUX_RTCK,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_GPV,   TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_HDINT, TEGRA_MUX_HDMI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_I2CP,  TEGRA_MUX_I2C,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_IRRX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_IRTX,  TEGRA_MUX_UARTB,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCA,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCB,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCC,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCD,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCE,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_KBCF,  TEGRA_MUX_KBC,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LCSN,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LD0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD2,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD3,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD4,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD5,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD6,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD7,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD8,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD9,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD10,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD11,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD12,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD13,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD14,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD15,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD16,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LD17,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LDC,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LDI,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHP2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LHS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM0,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LM1,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPP,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LPW1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LPW2,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LSC1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSCK,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDA,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSDI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LSPI,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVP0,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_LVP1,  TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_LVS,   TEGRA_MUX_DISPLAYA,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_OWC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PMC,   TEGRA_MUX_PWR_ON,        TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_PTA,   TEGRA_MUX_RSVD3,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_RM,    TEGRA_MUX_I2C,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDB,   TEGRA_MUX_PWM,           TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDC,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDD,   TEGRA_MUX_PWM,           TEGRA_PUPD_PULL_UP,     TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SDIO1, TEGRA_MUX_SDIO1,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXA,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SLXC,  TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXD,  TEGRA_MUX_SDIO3,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SLXK,  TEGRA_MUX_PCIE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_SPDI,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPDO,  TEGRA_MUX_SPDIF,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIA,  TEGRA_MUX_SPI2,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIB,  TEGRA_MUX_SPI2,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIC,  TEGRA_MUX_SPI2,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPID,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIE,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIF,  TEGRA_MUX_SPI1,          TEGRA_PUPD_PULL_DOWN,   TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIG,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_SPIH,  TEGRA_MUX_SPI2_ALT,      TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAB,   TEGRA_MUX_ULPI,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAC,   TEGRA_MUX_RSVD2,         TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UAD,   TEGRA_MUX_IRDA,          TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCA,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UCB,   TEGRA_MUX_UARTC,         TEGRA_PUPD_PULL_UP,     TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_UDA,   TEGRA_MUX_ULPI,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_TRISTATE},
+	{TEGRA_PINGROUP_CK32,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_DDRC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCA,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCB,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCC,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCD,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_PMCE,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2C,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+	{TEGRA_PINGROUP_XM2D,  TEGRA_MUX_NONE,          TEGRA_PUPD_NORMAL,      TEGRA_TRI_NORMAL},
+};
+
+static struct tegra_gpio_table gpio_table[] = {
+	{ .gpio = TRIMSLICE_GPIO_SD4_CD, .enable = true	}, /* mmc4 cd */
+	{ .gpio = TRIMSLICE_GPIO_SD4_WP, .enable = true	}, /* mmc4 wp */
+};
+
+void __init trimslice_pinmux_init(void)
+{
+	tegra_pinmux_config_table(trimslice_pinmux, ARRAY_SIZE(trimslice_pinmux));
+	tegra_gpio_config(gpio_table, ARRAY_SIZE(gpio_table));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,238 +18,177 @@
 
 #include <linux/kernel.h>
 #include <linux/clk.h>
-#include <linux/list.h>
+#include <linux/clkdev.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/module.h>
-#include <linux/debugfs.h>
-#include <linux/slab.h>
+#include <linux/sched.h>
 #include <linux/seq_file.h>
-#include <linux/regulator/consumer.h>
-#include <linux/clkdev.h>
+#include <linux/slab.h>
+
+#include <mach/clk.h>
 
-#include "clock.h"
 #include "board.h"
-#include "fuse.h"
+#include "clock.h"
 
+/*
+ * Locking:
+ *
+ * Each struct clk has a spinlock.
+ *
+ * To avoid AB-BA locking problems, locks must always be traversed from child
+ * clock to parent clock.  For example, when enabling a clock, the clock's lock
+ * is taken, and then clk_enable is called on the parent, which take's the
+ * parent clock's lock.  There is one exceptions to this ordering: When dumping
+ * the clock tree through debugfs.  In this case, clk_lock_all is called,
+ * which attemps to iterate through the entire list of clocks and take every
+ * clock lock.  If any call to spin_trylock fails, all locked clocks are
+ * unlocked, and the process is retried.  When all the locks are held,
+ * the only clock operation that can be called is clk_get_rate_all_locked.
+ *
+ * Within a single clock, no clock operation can call another clock operation
+ * on itself, except for clk_get_rate_locked and clk_set_rate_locked.  Any
+ * clock operation can call any other clock operation on any of it's possible
+ * parents.
+ *
+ * An additional mutex, clock_list_lock, is used to protect the list of all
+ * clocks.
+ *
+ * The clock operations must lock internally to protect against
+ * read-modify-write on registers that are shared by multiple clocks
+ */
+static DEFINE_MUTEX(clock_list_lock);
 static LIST_HEAD(clocks);
 
-static DEFINE_SPINLOCK(clock_lock);
-static DEFINE_MUTEX(dvfs_lock);
-
-static int clk_is_dvfs(struct clk *c)
-{
-	return (c->dvfs != NULL);
-};
-
-static int dvfs_set_rate(struct dvfs *d, unsigned long rate)
-{
-	struct dvfs_table *t;
-
-	if (d->table == NULL)
-		return -ENODEV;
-
-	for (t = d->table; t->rate != 0; t++) {
-		if (rate <= t->rate) {
-			if (!d->reg)
-				return 0;
-
-			return regulator_set_voltage(d->reg,
-				t->millivolts * 1000,
-				d->max_millivolts * 1000);
-		}
-	}
-
-	return -EINVAL;
-}
-
-static void dvfs_init(struct clk *c)
-{
-	int process_id;
-	int i;
-	struct dvfs_table *table;
-
-	process_id = c->dvfs->cpu ? tegra_core_process_id() :
-		tegra_cpu_process_id();
-
-	for (i = 0; i < c->dvfs->process_id_table_length; i++)
-		if (process_id == c->dvfs->process_id_table[i].process_id)
-			c->dvfs->table = c->dvfs->process_id_table[i].table;
-
-	if (c->dvfs->table == NULL) {
-		pr_err("Failed to find dvfs table for clock %s process %d\n",
-			c->name, process_id);
-		return;
-	}
-
-	c->dvfs->max_millivolts = 0;
-	for (table = c->dvfs->table; table->rate != 0; table++)
-		if (c->dvfs->max_millivolts < table->millivolts)
-			c->dvfs->max_millivolts = table->millivolts;
-
-	c->dvfs->reg = regulator_get(NULL, c->dvfs->reg_id);
-
-	if (IS_ERR(c->dvfs->reg)) {
-		pr_err("Failed to get regulator %s for clock %s\n",
-			c->dvfs->reg_id, c->name);
-		c->dvfs->reg = NULL;
-		return;
-	}
-
-	if (c->refcnt > 0)
-		dvfs_set_rate(c->dvfs, c->rate);
-}
-
 struct clk *tegra_get_clock_by_name(const char *name)
 {
 	struct clk *c;
 	struct clk *ret = NULL;
-	unsigned long flags;
-	spin_lock_irqsave(&clock_lock, flags);
+	mutex_lock(&clock_list_lock);
 	list_for_each_entry(c, &clocks, node) {
 		if (strcmp(c->name, name) == 0) {
 			ret = c;
 			break;
 		}
 	}
-	spin_unlock_irqrestore(&clock_lock, flags);
+	mutex_unlock(&clock_list_lock);
 	return ret;
 }
 
-static void clk_recalculate_rate(struct clk *c)
+/* Must be called with c->spinlock held */
+static unsigned long clk_predict_rate_from_parent(struct clk *c, struct clk *p)
 {
 	u64 rate;
 
-	if (!c->parent)
-		return;
-
-	rate = c->parent->rate;
+	rate = clk_get_rate(p);
 
 	if (c->mul != 0 && c->div != 0) {
-		rate = rate * c->mul;
+		rate *= c->mul;
+		rate += c->div - 1; /* round up */
 		do_div(rate, c->div);
 	}
 
-	if (rate > c->max_rate)
-		pr_warn("clocks: Set clock %s to rate %llu, max is %lu\n",
-			c->name, rate, c->max_rate);
-
-	c->rate = rate;
+	return rate;
 }
 
-int clk_reparent(struct clk *c, struct clk *parent)
+/* Must be called with c->spinlock held */
+unsigned long clk_get_rate_locked(struct clk *c)
 {
-	pr_debug("%s: %s\n", __func__, c->name);
-	c->parent = parent;
-	list_del(&c->sibling);
-	list_add_tail(&c->sibling, &parent->children);
-	return 0;
-}
+	unsigned long rate;
 
-static void propagate_rate(struct clk *c)
-{
-	struct clk *clkp;
-	pr_debug("%s: %s\n", __func__, c->name);
-	list_for_each_entry(clkp, &c->children, sibling) {
-		pr_debug("   %s\n", clkp->name);
-		clk_recalculate_rate(clkp);
-		propagate_rate(clkp);
-	}
+	if (c->parent)
+		rate = clk_predict_rate_from_parent(c, c->parent);
+	else
+		rate = c->rate;
+
+	return rate;
 }
 
-void clk_init(struct clk *c)
+unsigned long clk_get_rate(struct clk *c)
 {
 	unsigned long flags;
+	unsigned long rate;
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	spin_lock_irqsave(&c->spinlock, flags);
 
-	spin_lock_irqsave(&clock_lock, flags);
+	rate = clk_get_rate_locked(c);
 
-	INIT_LIST_HEAD(&c->children);
-	INIT_LIST_HEAD(&c->sibling);
+	spin_unlock_irqrestore(&c->spinlock, flags);
+
+	return rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+int clk_reparent(struct clk *c, struct clk *parent)
+{
+	c->parent = parent;
+	return 0;
+}
+
+void clk_init(struct clk *c)
+{
+	spin_lock_init(&c->spinlock);
 
 	if (c->ops && c->ops->init)
 		c->ops->init(c);
 
-	clk_recalculate_rate(c);
+	if (!c->ops || !c->ops->enable) {
+		c->refcnt++;
+		c->set = true;
+		if (c->parent)
+			c->state = c->parent->state;
+		else
+			c->state = ON;
+	}
 
+	mutex_lock(&clock_list_lock);
 	list_add(&c->node, &clocks);
-
-	if (c->parent)
-		list_add_tail(&c->sibling, &c->parent->children);
-
-	spin_unlock_irqrestore(&clock_lock, flags);
+	mutex_unlock(&clock_list_lock);
 }
 
-int clk_enable_locked(struct clk *c)
+int clk_enable(struct clk *c)
 {
-	int ret;
-	pr_debug("%s: %s\n", __func__, c->name);
+	int ret = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&c->spinlock, flags);
+
 	if (c->refcnt == 0) {
 		if (c->parent) {
-			ret = clk_enable_locked(c->parent);
+			ret = clk_enable(c->parent);
 			if (ret)
-				return ret;
+				goto out;
 		}
 
 		if (c->ops && c->ops->enable) {
 			ret = c->ops->enable(c);
 			if (ret) {
 				if (c->parent)
-					clk_disable_locked(c->parent);
-				return ret;
+					clk_disable(c->parent);
+				goto out;
 			}
 			c->state = ON;
-#ifdef CONFIG_DEBUG_FS
-			c->set = 1;
-#endif
+			c->set = true;
 		}
 	}
 	c->refcnt++;
-
-	return 0;
-}
-
-int clk_enable_cansleep(struct clk *c)
-{
-	int ret;
-	unsigned long flags;
-
-	mutex_lock(&dvfs_lock);
-
-	if (clk_is_dvfs(c) && c->refcnt > 0)
-		dvfs_set_rate(c->dvfs, c->rate);
-
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_enable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
-
-	mutex_unlock(&dvfs_lock);
-
+out:
+	spin_unlock_irqrestore(&c->spinlock, flags);
 	return ret;
 }
-EXPORT_SYMBOL(clk_enable_cansleep);
+EXPORT_SYMBOL(clk_enable);
 
-int clk_enable(struct clk *c)
+void clk_disable(struct clk *c)
 {
-	int ret;
 	unsigned long flags;
 
-	if (clk_is_dvfs(c))
-		BUG();
-
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_enable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
-
-	return ret;
-}
-EXPORT_SYMBOL(clk_enable);
+	spin_lock_irqsave(&c->spinlock, flags);
 
-void clk_disable_locked(struct clk *c)
-{
-	pr_debug("%s: %s\n", __func__, c->name);
 	if (c->refcnt == 0) {
 		WARN(1, "Attempting to disable clock %s with refcnt 0", c->name);
+		spin_unlock_irqrestore(&c->spinlock, flags);
 		return;
 	}
 	if (c->refcnt == 1) {
@@ -257,71 +196,39 @@
 			c->ops->disable(c);
 
 		if (c->parent)
-			clk_disable_locked(c->parent);
+			clk_disable(c->parent);
 
 		c->state = OFF;
 	}
 	c->refcnt--;
-}
-
-void clk_disable_cansleep(struct clk *c)
-{
-	unsigned long flags;
-
-	mutex_lock(&dvfs_lock);
-
-	spin_lock_irqsave(&clock_lock, flags);
-	clk_disable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
-
-	if (clk_is_dvfs(c) && c->refcnt == 0)
-		dvfs_set_rate(c->dvfs, c->rate);
-
-	mutex_unlock(&dvfs_lock);
-}
-EXPORT_SYMBOL(clk_disable_cansleep);
-
-void clk_disable(struct clk *c)
-{
-	unsigned long flags;
 
-	if (clk_is_dvfs(c))
-		BUG();
-
-	spin_lock_irqsave(&clock_lock, flags);
-	clk_disable_locked(c);
-	spin_unlock_irqrestore(&clock_lock, flags);
+	spin_unlock_irqrestore(&c->spinlock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
 
-int clk_set_parent_locked(struct clk *c, struct clk *parent)
+int clk_set_parent(struct clk *c, struct clk *parent)
 {
 	int ret;
+	unsigned long flags;
+	unsigned long new_rate;
+	unsigned long old_rate;
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	spin_lock_irqsave(&c->spinlock, flags);
 
-	if (!c->ops || !c->ops->set_parent)
-		return -ENOSYS;
+	if (!c->ops || !c->ops->set_parent) {
+		ret = -ENOSYS;
+		goto out;
+	}
 
-	ret = c->ops->set_parent(c, parent);
+	new_rate = clk_predict_rate_from_parent(c, parent);
+	old_rate = clk_get_rate_locked(c);
 
+	ret = c->ops->set_parent(c, parent);
 	if (ret)
-		return ret;
-
-	clk_recalculate_rate(c);
-
-	propagate_rate(c);
-
-	return 0;
-}
+		goto out;
 
-int clk_set_parent(struct clk *c, struct clk *parent)
-{
-	int ret;
-	unsigned long flags;
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_set_parent_locked(c, parent);
-	spin_unlock_irqrestore(&clock_lock, flags);
+out:
+	spin_unlock_irqrestore(&c->spinlock, flags);
 	return ret;
 }
 EXPORT_SYMBOL(clk_set_parent);
@@ -334,100 +241,86 @@
 
 int clk_set_rate_locked(struct clk *c, unsigned long rate)
 {
-	int ret;
-
-	if (rate > c->max_rate)
-		rate = c->max_rate;
+	long new_rate;
 
 	if (!c->ops || !c->ops->set_rate)
 		return -ENOSYS;
 
-	ret = c->ops->set_rate(c, rate);
-
-	if (ret)
-		return ret;
-
-	clk_recalculate_rate(c);
-
-	propagate_rate(c);
-
-	return 0;
-}
-
-int clk_set_rate_cansleep(struct clk *c, unsigned long rate)
-{
-	int ret = 0;
-	unsigned long flags;
-
-	pr_debug("%s: %s\n", __func__, c->name);
-
-	mutex_lock(&dvfs_lock);
-
-	if (rate > c->rate)
-		ret = dvfs_set_rate(c->dvfs, rate);
-	if (ret)
-		goto out;
+	if (rate > c->max_rate)
+		rate = c->max_rate;
 
-	spin_lock_irqsave(&clock_lock, flags);
-	ret = clk_set_rate_locked(c, rate);
-	spin_unlock_irqrestore(&clock_lock, flags);
+	if (c->ops && c->ops->round_rate) {
+		new_rate = c->ops->round_rate(c, rate);
 
-	if (ret)
-		goto out;
+		if (new_rate < 0)
+			return new_rate;
 
-	ret = dvfs_set_rate(c->dvfs, rate);
+		rate = new_rate;
+	}
 
-out:
-	mutex_unlock(&dvfs_lock);
-	return ret;
+	return c->ops->set_rate(c, rate);
 }
-EXPORT_SYMBOL(clk_set_rate_cansleep);
 
 int clk_set_rate(struct clk *c, unsigned long rate)
 {
-	int ret = 0;
+	int ret;
 	unsigned long flags;
 
-	pr_debug("%s: %s\n", __func__, c->name);
-
-	if (clk_is_dvfs(c))
-		BUG();
+	spin_lock_irqsave(&c->spinlock, flags);
 
-	spin_lock_irqsave(&clock_lock, flags);
 	ret = clk_set_rate_locked(c, rate);
-	spin_unlock_irqrestore(&clock_lock, flags);
+
+	spin_unlock_irqrestore(&c->spinlock, flags);
 
 	return ret;
 }
 EXPORT_SYMBOL(clk_set_rate);
 
-unsigned long clk_get_rate(struct clk *c)
-{
-	unsigned long flags;
-	unsigned long ret;
 
-	spin_lock_irqsave(&clock_lock, flags);
+/* Must be called with clocks lock and all indvidual clock locks held */
+unsigned long clk_get_rate_all_locked(struct clk *c)
+{
+	u64 rate;
+	int mul = 1;
+	int div = 1;
+	struct clk *p = c;
 
-	pr_debug("%s: %s\n", __func__, c->name);
+	while (p) {
+		c = p;
+		if (c->mul != 0 && c->div != 0) {
+			mul *= c->mul;
+			div *= c->div;
+		}
+		p = c->parent;
+	}
 
-	ret = c->rate;
+	rate = c->rate;
+	rate *= mul;
+	do_div(rate, div);
 
-	spin_unlock_irqrestore(&clock_lock, flags);
-	return ret;
+	return rate;
 }
-EXPORT_SYMBOL(clk_get_rate);
 
 long clk_round_rate(struct clk *c, unsigned long rate)
 {
-	pr_debug("%s: %s\n", __func__, c->name);
+	unsigned long flags;
+	long ret;
 
-	if (!c->ops || !c->ops->round_rate)
-		return -ENOSYS;
+	spin_lock_irqsave(&c->spinlock, flags);
+
+	if (!c->ops || !c->ops->round_rate) {
+		ret = -ENOSYS;
+		goto out;
+	}
 
 	if (rate > c->max_rate)
 		rate = c->max_rate;
 
-	return c->ops->round_rate(c, rate);
+	ret = c->ops->round_rate(c, rate);
+
+out:
+	spin_unlock_irqrestore(&c->spinlock, flags);
+	return ret;
 }
 EXPORT_SYMBOL(clk_round_rate);
 
@@ -509,31 +402,90 @@
 	tegra2_init_clocks();
 }
 
-int __init tegra_init_dvfs(void)
+/*
+ * The SDMMC controllers have extra bits in the clock source register that
+ * adjust the delay between the clock and data to compenstate for delays
+ * on the PCB.
+ */
+void tegra_sdmmc_tap_delay(struct clk *c, int delay)
 {
-	struct clk *c, *safe;
+	unsigned long flags;
 
-	mutex_lock(&dvfs_lock);
+	spin_lock_irqsave(&c->spinlock, flags);
+	tegra2_sdmmc_tap_delay(c, delay);
+	spin_unlock_irqrestore(&c->spinlock, flags);
+}
 
-	list_for_each_entry_safe(c, safe, &clocks, node)
-		if (c->dvfs)
-			dvfs_init(c);
+#ifdef CONFIG_DEBUG_FS
 
-	mutex_unlock(&dvfs_lock);
+static int __clk_lock_all_spinlocks(void)
+{
+	struct clk *c;
+
+	list_for_each_entry(c, &clocks, node)
+		if (!spin_trylock(&c->spinlock))
+			goto unlock_spinlocks;
 
 	return 0;
+
+unlock_spinlocks:
+	list_for_each_entry_continue_reverse(c, &clocks, node)
+		spin_unlock(&c->spinlock);
+
+	return -EAGAIN;
 }
 
-late_initcall(tegra_init_dvfs);
+static void __clk_unlock_all_spinlocks(void)
+{
+	struct clk *c;
+
+	list_for_each_entry_reverse(c, &clocks, node)
+		spin_unlock(&c->spinlock);
+}
+
+/*
+ * This function retries until it can take all locks, and may take
+ * an arbitrarily long time to complete.
+ * Must be called with irqs enabled, returns with irqs disabled
+ * Must be called with clock_list_lock held
+ */
+static void clk_lock_all(void)
+{
+	int ret;
+retry:
+	local_irq_disable();
+
+	ret = __clk_lock_all_spinlocks();
+	if (ret)
+		goto failed_spinlocks;
+
+	/* All locks taken successfully, return */
+	return;
+
+failed_spinlocks:
+	local_irq_enable();
+	yield();
+	goto retry;
+}
+
+/*
+ * Unlocks all clocks after a clk_lock_all
+ * Must be called with irqs disabled, returns with irqs enabled
+ * Must be called with clock_list_lock held
+ */
+static void clk_unlock_all(void)
+{
+	__clk_unlock_all_spinlocks();
+
+	local_irq_enable();
+}
 
-#ifdef CONFIG_DEBUG_FS
 static struct dentry *clk_debugfs_root;
 
 
 static void clock_tree_show_one(struct seq_file *s, struct clk *c, int level)
 {
 	struct clk *child;
-	struct clk *safe;
 	const char *state = "uninit";
 	char div[8] = {0};
 
@@ -564,8 +516,12 @@
 		c->rate > c->max_rate ? '!' : ' ',
 		!c->set ? '*' : ' ',
 		30 - level * 3, c->name,
-		state, c->refcnt, div, c->rate);
-	list_for_each_entry_safe(child, safe, &c->children, sibling) {
+		state, c->refcnt, div, clk_get_rate_all_locked(c));
+
+	list_for_each_entry(child, &clocks, node) {
+		if (child->parent != c)
+			continue;
+
 		clock_tree_show_one(s, child, level + 1);
 	}
 }
@@ -573,14 +529,20 @@
 static int clock_tree_show(struct seq_file *s, void *data)
 {
 	struct clk *c;
-	unsigned long flags;
 	seq_printf(s, "   clock                          state  ref div      rate\n");
 	seq_printf(s, "--------------------------------------------------------------\n");
-	spin_lock_irqsave(&clock_lock, flags);
+
+	mutex_lock(&clock_list_lock);
+
+	clk_lock_all();
+
 	list_for_each_entry(c, &clocks, node)
 		if (c->parent == NULL)
 			clock_tree_show_one(s, c, 0);
-	spin_unlock_irqrestore(&clock_lock, flags);
+
+	clk_unlock_all();
+
+	mutex_unlock(&clock_list_lock);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/clock.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/clock.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,8 +20,9 @@
 #ifndef __MACH_TEGRA_CLOCK_H
 #define __MACH_TEGRA_CLOCK_H
 
-#include <linux/list.h>
 #include <linux/clkdev.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
 
 #define DIV_BUS			(1 << 0)
 #define DIV_U71			(1 << 1)
@@ -41,36 +42,13 @@
 #define ENABLE_ON_INIT		(1 << 28)
 
 struct clk;
-struct regulator;
-
-struct dvfs_table {
-	unsigned long rate;
-	int millivolts;
-};
-
-struct dvfs_process_id_table {
-	int process_id;
-	struct dvfs_table *table;
-};
-
-
-struct dvfs {
-	struct regulator *reg;
-	struct dvfs_table *table;
-	int max_millivolts;
-
-	int process_id_table_length;
-	const char *reg_id;
-	bool cpu;
-	struct dvfs_process_id_table process_id_table[];
-};
 
 struct clk_mux_sel {
 	struct clk	*input;
 	u32		value;
 };
 
-struct clk_pll_table {
+struct clk_pll_freq_table {
 	unsigned long	input_rate;
 	unsigned long	output_rate;
 	u16		n;
@@ -86,6 +64,7 @@
 	int		(*set_parent)(struct clk *, struct clk *);
 	int		(*set_rate)(struct clk *, unsigned long);
 	long		(*round_rate)(struct clk *, unsigned long);
+	void		(*reset)(struct clk *, bool);
 };
 
 enum clk_state {
@@ -96,54 +75,63 @@
 
 struct clk {
 	/* node for master clocks list */
-	struct list_head		node;
-	struct list_head		children;	/* list of children */
-	struct list_head		sibling;	/* node for children */
-#ifdef CONFIG_DEBUG_FS
-	struct dentry			*dent;
-	struct dentry			*parent_dent;
-#endif
-	struct clk_ops			*ops;
-	struct clk			*parent;
-	struct clk_lookup		lookup;
-	unsigned long			rate;
-	unsigned long			max_rate;
-	u32				flags;
-	u32				refcnt;
-	const char			*name;
-	u32				reg;
-	u32				reg_shift;
-	unsigned int			clk_num;
-	enum clk_state			state;
+	struct list_head	node;		/* node for list of all clocks */
+	struct clk_lookup	lookup;
+
 #ifdef CONFIG_DEBUG_FS
-	bool				set;
+	struct dentry		*dent;
 #endif
+	bool			set;
+	struct clk_ops		*ops;
+	unsigned long		rate;
+	unsigned long		max_rate;
+	unsigned long		min_rate;
+	u32			flags;
+	const char		*name;
 
-	/* PLL */
-	unsigned long			input_min;
-	unsigned long			input_max;
-	unsigned long			cf_min;
-	unsigned long			cf_max;
-	unsigned long			vco_min;
-	unsigned long			vco_max;
-	const struct clk_pll_table	*pll_table;
-
-	/* DIV */
-	u32				div;
-	u32				mul;
+	u32			refcnt;
+	enum clk_state		state;
+	struct clk		*parent;
+	u32			div;
+	u32			mul;
 
-	/* MUX */
 	const struct clk_mux_sel	*inputs;
-	u32				sel;
-	u32				reg_mask;
+	u32				reg;
+	u32				reg_shift;
 
-	/* Virtual cpu clock */
-	struct clk			*main;
-	struct clk			*backup;
+	struct list_head		shared_bus_list;
 
-	struct dvfs			*dvfs;
-};
+	union {
+		struct {
+			unsigned int			clk_num;
+		} periph;
+		struct {
+			unsigned long			input_min;
+			unsigned long			input_max;
+			unsigned long			cf_min;
+			unsigned long			cf_max;
+			unsigned long			vco_min;
+			unsigned long			vco_max;
+			const struct clk_pll_freq_table	*freq_table;
+			int				lock_delay;
+		} pll;
+		struct {
+			u32				sel;
+			u32				reg_mask;
+		} mux;
+		struct {
+			struct clk			*main;
+			struct clk			*backup;
+		} cpu;
+		struct {
+			struct list_head		node;
+			bool				enabled;
+			unsigned long			rate;
+		} shared_bus_user;
+	} u;
 
+	spinlock_t spinlock;
+};
 
 struct clk_duplicate {
 	const char *name;
@@ -163,11 +151,10 @@
 void clk_init(struct clk *clk);
 struct clk *tegra_get_clock_by_name(const char *name);
 unsigned long clk_measure_input_freq(void);
-void clk_disable_locked(struct clk *c);
-int clk_enable_locked(struct clk *c);
-int clk_set_parent_locked(struct clk *c, struct clk *parent);
-int clk_set_rate_locked(struct clk *c, unsigned long rate);
 int clk_reparent(struct clk *c, struct clk *parent);
 void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
+unsigned long clk_get_rate_locked(struct clk *c);
+int clk_set_rate_locked(struct clk *c, unsigned long rate);
+void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/common.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,12 +25,25 @@
 #include <asm/hardware/cache-l2x0.h>
 
 #include <mach/iomap.h>
-#include <mach/dma.h>
+#include <mach/system.h>
 
 #include "board.h"
 #include "clock.h"
 #include "fuse.h"
 
+void (*arch_reset)(char mode, const char *cmd) = tegra_assert_system_reset;
+
+void tegra_assert_system_reset(char mode, const char *cmd)
+{
+	void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
+	u32 reg;
+
+	/* use *_related to avoid spinlock since caches are off */
+	reg = readl_relaxed(reset);
+	reg |= 0x04;
+	writel_relaxed(reg, reset);
+}
+
 static __initdata struct tegra_clk_init_table common_clk_init_table[] = {
 	/* name		parent		rate		enabled */
 	{ "clk_m",	NULL,		0,		true },
@@ -42,6 +55,9 @@
 	{ "sclk",	"pll_p_out4",	108000000,	true },
 	{ "hclk",	"sclk",		108000000,	true },
 	{ "pclk",	"hclk",		54000000,	true },
+	{ "csite",	NULL,		0,		true },
+	{ "emc",	NULL,		0,		true },
+	{ "cpu",	NULL,		0,		true },
 	{ NULL,		NULL,		0,		0},
 };
 
@@ -50,21 +66,18 @@
 #ifdef CONFIG_CACHE_L2X0
 	void __iomem *p = IO_ADDRESS(TEGRA_ARM_PERIF_BASE) + 0x3000;
 
-	writel(0x331, p + L2X0_TAG_LATENCY_CTRL);
-	writel(0x441, p + L2X0_DATA_LATENCY_CTRL);
+	writel_relaxed(0x331, p + L2X0_TAG_LATENCY_CTRL);
+	writel_relaxed(0x441, p + L2X0_DATA_LATENCY_CTRL);
 
 	l2x0_init(p, 0x6C080001, 0x8200c3fe);
 #endif
 
 }
 
-void __init tegra_common_init(void)
+void __init tegra_init_early(void)
 {
 	tegra_init_fuse();
 	tegra_init_clock();
 	tegra_clk_init_from_table(common_clk_init_table);
 	tegra_init_cache();
-#ifdef CONFIG_TEGRA_SYSTEM_DMA
-	tegra_dma_init();
-#endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/cpu-tegra.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/cpu-tegra.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/cpu-tegra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/cpu-tegra.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/io.h>
+#include <linux/suspend.h>
 
 #include <asm/system.h>
 
@@ -36,21 +37,25 @@
 
 /* Frequency table index must be sequential starting at 0 */
 static struct cpufreq_frequency_table freq_table[] = {
-	{ 0, 312000 },
-	{ 1, 456000 },
-	{ 2, 608000 },
-	{ 3, 760000 },
-	{ 4, 816000 },
-	{ 5, 912000 },
-	{ 6, 1000000 },
-	{ 7, CPUFREQ_TABLE_END },
+	{ 0, 216000 },
+	{ 1, 312000 },
+	{ 2, 456000 },
+	{ 3, 608000 },
+	{ 4, 760000 },
+	{ 5, 816000 },
+	{ 6, 912000 },
+	{ 7, 1000000 },
+	{ 8, CPUFREQ_TABLE_END },
 };
 
 #define NUM_CPUS	2
 
 static struct clk *cpu_clk;
+static struct clk *emc_clk;
 
 static unsigned long target_cpu_speed[NUM_CPUS];
+static DEFINE_MUTEX(tegra_cpu_lock);
+static bool is_suspended;
 
 int tegra_verify_speed(struct cpufreq_policy *policy)
 {
@@ -68,22 +73,28 @@
 	return rate;
 }
 
-static int tegra_update_cpu_speed(void)
+static int tegra_update_cpu_speed(unsigned long rate)
 {
-	int i;
-	unsigned long rate = 0;
 	int ret = 0;
 	struct cpufreq_freqs freqs;
 
-	for_each_online_cpu(i)
-		rate = max(rate, target_cpu_speed[i]);
-
 	freqs.old = tegra_getspeed(0);
 	freqs.new = rate;
 
 	if (freqs.old == freqs.new)
 		return ret;
 
+	/*
+	 * Vote on memory bus frequency based on cpu frequency
+	 * This sets the minimum frequency, display or avp may request higher
+	 */
+	if (rate >= 816000)
+		clk_set_rate(emc_clk, 600000000); /* cpu 816 MHz, emc max */
+	else if (rate >= 456000)
+		clk_set_rate(emc_clk, 300000000); /* cpu 456 MHz, emc 150Mhz */
+	else
+		clk_set_rate(emc_clk, 100000000);  /* emc 50Mhz */
+
 	for_each_online_cpu(freqs.cpu)
 		cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
@@ -92,7 +103,7 @@
 	       freqs.old, freqs.new);
 #endif
 
-	ret = clk_set_rate_cansleep(cpu_clk, freqs.new * 1000);
+	ret = clk_set_rate(cpu_clk, freqs.new * 1000);
 	if (ret) {
 		pr_err("cpu-tegra: Failed to set cpu frequency to %d kHz\n",
 			freqs.new);
@@ -105,12 +116,30 @@
 	return 0;
 }
 
+static unsigned long tegra_cpu_highest_speed(void)
+{
+	unsigned long rate = 0;
+	int i;
+
+	for_each_online_cpu(i)
+		rate = max(rate, target_cpu_speed[i]);
+	return rate;
+}
+
 static int tegra_target(struct cpufreq_policy *policy,
 		       unsigned int target_freq,
 		       unsigned int relation)
 {
 	int idx;
 	unsigned int freq;
+	int ret = 0;
+
+	mutex_lock(&tegra_cpu_lock);
+
+	if (is_suspended) {
+		ret = -EBUSY;
+		goto out;
+	}
 
 	cpufreq_frequency_table_target(policy, freq_table, target_freq,
 		relation, &idx);
@@ -119,9 +148,34 @@
 
 	target_cpu_speed[policy->cpu] = freq;
 
-	return tegra_update_cpu_speed();
+	ret = tegra_update_cpu_speed(tegra_cpu_highest_speed());
+
+out:
+	mutex_unlock(&tegra_cpu_lock);
+	return ret;
+}
+
+static int tegra_pm_notify(struct notifier_block *nb, unsigned long event,
+	void *dummy)
+{
+	mutex_lock(&tegra_cpu_lock);
+	if (event == PM_SUSPEND_PREPARE) {
+		is_suspended = true;
+		pr_info("Tegra cpufreq suspend: setting frequency to %d kHz\n",
+			freq_table[0].frequency);
+		tegra_update_cpu_speed(freq_table[0].frequency);
+	} else if (event == PM_POST_SUSPEND) {
+		is_suspended = false;
+	}
+	mutex_unlock(&tegra_cpu_lock);
+
+	return NOTIFY_OK;
 }
 
+static struct notifier_block tegra_cpu_pm_notifier = {
+	.notifier_call = tegra_pm_notify,
+};
+
 static int tegra_cpu_init(struct cpufreq_policy *policy)
 {
 	if (policy->cpu >= NUM_CPUS)
@@ -131,6 +185,15 @@
 	if (IS_ERR(cpu_clk))
 		return PTR_ERR(cpu_clk);
 
+	emc_clk = clk_get_sys("cpu", "emc");
+	if (IS_ERR(emc_clk)) {
+		clk_put(cpu_clk);
+		return PTR_ERR(emc_clk);
+	}
+
+	clk_enable(emc_clk);
+	clk_enable(cpu_clk);
+
 	cpufreq_frequency_table_cpuinfo(policy, freq_table);
 	cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
 	policy->cur = tegra_getspeed(policy->cpu);
@@ -142,12 +205,17 @@
 	policy->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 	cpumask_copy(policy->related_cpus, cpu_possible_mask);
 
+	if (policy->cpu == 0)
+		register_pm_notifier(&tegra_cpu_pm_notifier);
+
 	return 0;
 }
 
 static int tegra_cpu_exit(struct cpufreq_policy *policy)
 {
 	cpufreq_frequency_table_cpuinfo(policy, freq_table);
+	clk_disable(emc_clk);
+	clk_put(emc_clk);
 	clk_put(cpu_clk);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/devices.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,575 @@
+/*
+ * Copyright (C) 2010,2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *	Erik Gilling <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#include <linux/resource.h>
+#include <linux/platform_device.h>
+#include <linux/dma-mapping.h>
+#include <linux/fsl_devices.h>
+#include <linux/serial_8250.h>
+#include <asm/pmu.h>
+#include <mach/irqs.h>
+#include <mach/iomap.h>
+#include <mach/dma.h>
+
+static struct resource i2c_resource1[] = {
+	[0] = {
+		.start	= INT_I2C,
+		.end	= INT_I2C,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_I2C_BASE,
+		.end	= TEGRA_I2C_BASE + TEGRA_I2C_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c_resource2[] = {
+	[0] = {
+		.start	= INT_I2C2,
+		.end	= INT_I2C2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_I2C2_BASE,
+		.end	= TEGRA_I2C2_BASE + TEGRA_I2C2_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c_resource3[] = {
+	[0] = {
+		.start	= INT_I2C3,
+		.end	= INT_I2C3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_I2C3_BASE,
+		.end	= TEGRA_I2C3_BASE + TEGRA_I2C3_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource i2c_resource4[] = {
+	[0] = {
+		.start	= INT_DVC,
+		.end	= INT_DVC,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_DVC_BASE,
+		.end	= TEGRA_DVC_BASE + TEGRA_DVC_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_i2c_device1 = {
+	.name		= "tegra-i2c",
+	.id		= 0,
+	.resource	= i2c_resource1,
+	.num_resources	= ARRAY_SIZE(i2c_resource1),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+struct platform_device tegra_i2c_device2 = {
+	.name		= "tegra-i2c",
+	.id		= 1,
+	.resource	= i2c_resource2,
+	.num_resources	= ARRAY_SIZE(i2c_resource2),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+struct platform_device tegra_i2c_device3 = {
+	.name		= "tegra-i2c",
+	.id		= 2,
+	.resource	= i2c_resource3,
+	.num_resources	= ARRAY_SIZE(i2c_resource3),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+struct platform_device tegra_i2c_device4 = {
+	.name		= "tegra-i2c",
+	.id		= 3,
+	.resource	= i2c_resource4,
+	.num_resources	= ARRAY_SIZE(i2c_resource4),
+	.dev = {
+		.platform_data = 0,
+	},
+};
+
+static struct resource spi_resource1[] = {
+	[0] = {
+		.start	= INT_S_LINK1,
+		.end	= INT_S_LINK1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI1_BASE,
+		.end	= TEGRA_SPI1_BASE + TEGRA_SPI1_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource spi_resource2[] = {
+	[0] = {
+		.start	= INT_SPI_2,
+		.end	= INT_SPI_2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI2_BASE,
+		.end	= TEGRA_SPI2_BASE + TEGRA_SPI2_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource spi_resource3[] = {
+	[0] = {
+		.start	= INT_SPI_3,
+		.end	= INT_SPI_3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI3_BASE,
+		.end	= TEGRA_SPI3_BASE + TEGRA_SPI3_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource spi_resource4[] = {
+	[0] = {
+		.start	= INT_SPI_4,
+		.end	= INT_SPI_4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SPI4_BASE,
+		.end	= TEGRA_SPI4_BASE + TEGRA_SPI4_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_spi_device1 = {
+	.name		= "spi_tegra",
+	.id		= 0,
+	.resource	= spi_resource1,
+	.num_resources	= ARRAY_SIZE(spi_resource1),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device tegra_spi_device2 = {
+	.name		= "spi_tegra",
+	.id		= 1,
+	.resource	= spi_resource2,
+	.num_resources	= ARRAY_SIZE(spi_resource2),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device tegra_spi_device3 = {
+	.name		= "spi_tegra",
+	.id		= 2,
+	.resource	= spi_resource3,
+	.num_resources	= ARRAY_SIZE(spi_resource3),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+struct platform_device tegra_spi_device4 = {
+	.name		= "spi_tegra",
+	.id		= 3,
+	.resource	= spi_resource4,
+	.num_resources	= ARRAY_SIZE(spi_resource4),
+	.dev		= {
+		.coherent_dma_mask	= 0xffffffff,
+	},
+};
+
+
+static struct resource sdhci_resource1[] = {
+	[0] = {
+		.start	= INT_SDMMC1,
+		.end	= INT_SDMMC1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC1_BASE,
+		.end	= TEGRA_SDMMC1_BASE + TEGRA_SDMMC1_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sdhci_resource2[] = {
+	[0] = {
+		.start	= INT_SDMMC2,
+		.end	= INT_SDMMC2,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC2_BASE,
+		.end	= TEGRA_SDMMC2_BASE + TEGRA_SDMMC2_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sdhci_resource3[] = {
+	[0] = {
+		.start	= INT_SDMMC3,
+		.end	= INT_SDMMC3,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC3_BASE,
+		.end	= TEGRA_SDMMC3_BASE + TEGRA_SDMMC3_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource sdhci_resource4[] = {
+	[0] = {
+		.start	= INT_SDMMC4,
+		.end	= INT_SDMMC4,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= TEGRA_SDMMC4_BASE,
+		.end	= TEGRA_SDMMC4_BASE + TEGRA_SDMMC4_SIZE-1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+/* board files should fill in platform_data register the devices themselvs.
+ * See board-harmony.c for an example
+ */
+struct platform_device tegra_sdhci_device1 = {
+	.name		= "sdhci-tegra",
+	.id		= 0,
+	.resource	= sdhci_resource1,
+	.num_resources	= ARRAY_SIZE(sdhci_resource1),
+};
+
+struct platform_device tegra_sdhci_device2 = {
+	.name		= "sdhci-tegra",
+	.id		= 1,
+	.resource	= sdhci_resource2,
+	.num_resources	= ARRAY_SIZE(sdhci_resource2),
+};
+
+struct platform_device tegra_sdhci_device3 = {
+	.name		= "sdhci-tegra",
+	.id		= 2,
+	.resource	= sdhci_resource3,
+	.num_resources	= ARRAY_SIZE(sdhci_resource3),
+};
+
+struct platform_device tegra_sdhci_device4 = {
+	.name		= "sdhci-tegra",
+	.id		= 3,
+	.resource	= sdhci_resource4,
+	.num_resources	= ARRAY_SIZE(sdhci_resource4),
+};
+
+static struct resource tegra_usb1_resources[] = {
+	[0] = {
+		.start	= TEGRA_USB_BASE,
+		.end	= TEGRA_USB_BASE + TEGRA_USB_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_USB,
+		.end	= INT_USB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_usb2_resources[] = {
+	[0] = {
+		.start	= TEGRA_USB2_BASE,
+		.end	= TEGRA_USB2_BASE + TEGRA_USB2_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_USB2,
+		.end	= INT_USB2,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_usb3_resources[] = {
+	[0] = {
+		.start	= TEGRA_USB3_BASE,
+		.end	= TEGRA_USB3_BASE + TEGRA_USB3_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_USB3,
+		.end	= INT_USB3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 tegra_ehci_dmamask = DMA_BIT_MASK(32);
+
+struct platform_device tegra_ehci1_device = {
+	.name	= "tegra-ehci",
+	.id	= 0,
+	.dev	= {
+		.dma_mask	= &tegra_ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = tegra_usb1_resources,
+	.num_resources = ARRAY_SIZE(tegra_usb1_resources),
+};
+
+struct platform_device tegra_ehci2_device = {
+	.name	= "tegra-ehci",
+	.id	= 1,
+	.dev	= {
+		.dma_mask	= &tegra_ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = tegra_usb2_resources,
+	.num_resources = ARRAY_SIZE(tegra_usb2_resources),
+};
+
+struct platform_device tegra_ehci3_device = {
+	.name	= "tegra-ehci",
+	.id	= 2,
+	.dev	= {
+		.dma_mask	= &tegra_ehci_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.resource = tegra_usb3_resources,
+	.num_resources = ARRAY_SIZE(tegra_usb3_resources),
+};
+
+static struct resource tegra_pmu_resources[] = {
+	[0] = {
+		.start	= INT_CPU0_PMU_INTR,
+		.end	= INT_CPU0_PMU_INTR,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start	= INT_CPU1_PMU_INTR,
+		.end	= INT_CPU1_PMU_INTR,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_pmu_device = {
+	.name		= "arm-pmu",
+	.id		= ARM_PMU_DEVICE_CPU,
+	.num_resources	= ARRAY_SIZE(tegra_pmu_resources),
+	.resource	= tegra_pmu_resources,
+};
+
+static struct resource tegra_uarta_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTA_BASE,
+		.end	= TEGRA_UARTA_BASE + TEGRA_UARTA_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTA,
+		.end	= INT_UARTA,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uartb_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTB_BASE,
+		.end	= TEGRA_UARTB_BASE + TEGRA_UARTB_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTB,
+		.end	= INT_UARTB,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uartc_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTC_BASE,
+		.end	= TEGRA_UARTC_BASE + TEGRA_UARTC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTC,
+		.end	= INT_UARTC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uartd_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTD_BASE,
+		.end	= TEGRA_UARTD_BASE + TEGRA_UARTD_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTD,
+		.end	= INT_UARTD,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource tegra_uarte_resources[] = {
+	[0] = {
+		.start	= TEGRA_UARTE_BASE,
+		.end	= TEGRA_UARTE_BASE + TEGRA_UARTE_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= INT_UARTE,
+		.end	= INT_UARTE,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device tegra_uarta_device = {
+	.name	= "tegra_uart",
+	.id	= 0,
+	.num_resources	= ARRAY_SIZE(tegra_uarta_resources),
+	.resource	= tegra_uarta_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uartb_device = {
+	.name	= "tegra_uart",
+	.id	= 1,
+	.num_resources	= ARRAY_SIZE(tegra_uartb_resources),
+	.resource	= tegra_uartb_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uartc_device = {
+	.name	= "tegra_uart",
+	.id	= 2,
+	.num_resources	= ARRAY_SIZE(tegra_uartc_resources),
+	.resource	= tegra_uartc_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uartd_device = {
+	.name	= "tegra_uart",
+	.id	= 3,
+	.num_resources	= ARRAY_SIZE(tegra_uartd_resources),
+	.resource	= tegra_uartd_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device tegra_uarte_device = {
+	.name	= "tegra_uart",
+	.id	= 4,
+	.num_resources	= ARRAY_SIZE(tegra_uarte_resources),
+	.resource	= tegra_uarte_resources,
+	.dev	= {
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
+static struct resource i2s_resource1[] = {
+	[0] = {
+		.start	= INT_I2S1,
+		.end	= INT_I2S1,
+		.flags	= IORESOURCE_IRQ
+	},
+	[1] = {
+		.start	= TEGRA_DMA_REQ_SEL_I2S_1,
+		.end	= TEGRA_DMA_REQ_SEL_I2S_1,
+		.flags	= IORESOURCE_DMA
+	},
+	[2] = {
+		.start	= TEGRA_I2S1_BASE,
+		.end	= TEGRA_I2S1_BASE + TEGRA_I2S1_SIZE - 1,
+		.flags	= IORESOURCE_MEM
+	}
+};
+
+static struct resource i2s_resource2[] = {
+	[0] = {
+		.start	= INT_I2S2,
+		.end	= INT_I2S2,
+		.flags	= IORESOURCE_IRQ
+	},
+	[1] = {
+		.start	= TEGRA_DMA_REQ_SEL_I2S2_1,
+		.end	= TEGRA_DMA_REQ_SEL_I2S2_1,
+		.flags	= IORESOURCE_DMA
+	},
+	[2] = {
+		.start	= TEGRA_I2S2_BASE,
+		.end	= TEGRA_I2S2_BASE + TEGRA_I2S2_SIZE - 1,
+		.flags	= IORESOURCE_MEM
+	}
+};
+
+struct platform_device tegra_i2s_device1 = {
+	.name		= "tegra-i2s",
+	.id		= 0,
+	.resource	= i2s_resource1,
+	.num_resources	= ARRAY_SIZE(i2s_resource1),
+};
+
+struct platform_device tegra_i2s_device2 = {
+	.name		= "tegra-i2s",
+	.id		= 1,
+	.resource	= i2s_resource2,
+	.num_resources	= ARRAY_SIZE(i2s_resource2),
+};
+
+static struct resource tegra_das_resources[] = {
+	[0] = {
+		.start = TEGRA_APB_MISC_DAS_BASE,
+		.end = TEGRA_APB_MISC_DAS_BASE + TEGRA_APB_MISC_DAS_SIZE - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device tegra_das_device = {
+	.name		= "tegra-das",
+	.id		= -1,
+	.num_resources	= ARRAY_SIZE(tegra_das_resources),
+	.resource	= tegra_das_resources,
+};
+
+struct platform_device tegra_pcm_device = {
+	.name = "tegra-pcm-audio",
+	.id = -1,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/devices.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/devices.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/devices.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/devices.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010,2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *	Erik Gilling <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_TEGRA_DEVICES_H
+#define __MACH_TEGRA_DEVICES_H
+
+#include <linux/platform_device.h>
+
+extern struct platform_device tegra_sdhci_device1;
+extern struct platform_device tegra_sdhci_device2;
+extern struct platform_device tegra_sdhci_device3;
+extern struct platform_device tegra_sdhci_device4;
+extern struct platform_device tegra_i2c_device1;
+extern struct platform_device tegra_i2c_device2;
+extern struct platform_device tegra_i2c_device3;
+extern struct platform_device tegra_i2c_device4;
+extern struct platform_device tegra_spi_device1;
+extern struct platform_device tegra_spi_device2;
+extern struct platform_device tegra_spi_device3;
+extern struct platform_device tegra_spi_device4;
+extern struct platform_device tegra_ehci1_device;
+extern struct platform_device tegra_ehci2_device;
+extern struct platform_device tegra_ehci3_device;
+extern struct platform_device tegra_uarta_device;
+extern struct platform_device tegra_uartb_device;
+extern struct platform_device tegra_uartc_device;
+extern struct platform_device tegra_uartd_device;
+extern struct platform_device tegra_uarte_device;
+extern struct platform_device tegra_pmu_device;
+extern struct platform_device tegra_i2s_device1;
+extern struct platform_device tegra_i2s_device2;
+extern struct platform_device tegra_das_device;
+extern struct platform_device tegra_pcm_device;
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/dma.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,9 +27,11 @@
 #include <linux/err.h>
 #include <linux/irq.h>
 #include <linux/delay.h>
+#include <linux/clk.h>
 #include <mach/dma.h>
 #include <mach/irqs.h>
 #include <mach/iomap.h>
+#include <mach/suspend.h>
 
 #define APB_DMA_GEN				0x000
 #define GEN_ENABLE				(1<<31)
@@ -120,17 +122,14 @@
 	void  __iomem		*addr;
 	int			mode;
 	int			irq;
-
-	/* Register shadow */
-	u32			csr;
-	u32			ahb_seq;
-	u32			ahb_ptr;
-	u32			apb_seq;
-	u32			apb_ptr;
+	int			req_transfer_count;
 };
 
 #define  NV_DMA_MAX_CHANNELS  32
 
+static bool tegra_dma_initialized;
+static DEFINE_MUTEX(tegra_dma_lock);
+
 static DECLARE_BITMAP(channel_usage, NV_DMA_MAX_CHANNELS);
 static struct tegra_dma_channel dma_channels[NV_DMA_MAX_CHANNELS];
 
@@ -138,7 +137,6 @@
 	struct tegra_dma_req *req);
 static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
 	struct tegra_dma_req *req);
-static void tegra_dma_init_hw(struct tegra_dma_channel *ch);
 static void tegra_dma_stop(struct tegra_dma_channel *ch);
 
 void tegra_dma_flush(struct tegra_dma_channel *ch)
@@ -150,6 +148,9 @@
 {
 	struct tegra_dma_req *req;
 
+	if (tegra_dma_is_empty(ch))
+		return;
+
 	req = list_entry(ch->list.next, typeof(*req), node);
 
 	tegra_dma_dequeue_req(ch, req);
@@ -158,10 +159,10 @@
 
 void tegra_dma_stop(struct tegra_dma_channel *ch)
 {
-	unsigned int csr;
-	unsigned int status;
+	u32 csr;
+	u32 status;
 
-	csr = ch->csr;
+	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
 	csr &= ~CSR_IE_EOC;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
@@ -175,19 +176,16 @@
 
 int tegra_dma_cancel(struct tegra_dma_channel *ch)
 {
-	unsigned int csr;
+	u32 csr;
 	unsigned long irq_flags;
 
 	spin_lock_irqsave(&ch->lock, irq_flags);
 	while (!list_empty(&ch->list))
 		list_del(ch->list.next);
 
-	csr = ch->csr;
+	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
 	csr &= ~CSR_REQ_SEL_MASK;
 	csr |= CSR_REQ_SEL_INVALID;
-
-	/* Set the enable as that is not shadowed */
-	csr |= CSR_ENB;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
 	tegra_dma_stop(ch);
@@ -225,22 +223,19 @@
 	 *  - Change the source selector to invalid to stop the DMA from
 	 *    FIFO to memory.
 	 *  - Read the status register to know the number of pending
-	 *    bytes to be transfered.
+	 *    bytes to be transferred.
 	 *  - Finally stop or program the DMA to the next buffer in the
 	 *    list.
 	 */
-	csr = ch->csr;
+	csr = readl(ch->addr + APB_DMA_CHAN_CSR);
 	csr &= ~CSR_REQ_SEL_MASK;
 	csr |= CSR_REQ_SEL_INVALID;
-
-	/* Set the enable as that is not shadowed */
-	csr |= CSR_ENB;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
 	/* Get the transfer count */
 	status = readl(ch->addr + APB_DMA_CHAN_STA);
 	to_transfer = (status & STA_COUNT_MASK) >> STA_COUNT_SHIFT;
-	req_transfer_count = (ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+	req_transfer_count = ch->req_transfer_count;
 	req_transfer_count += 1;
 	to_transfer += 1;
 
@@ -249,7 +244,7 @@
 	if (status & STA_BUSY)
 		req->bytes_transferred -= to_transfer;
 
-	/* In continous transfer mode, DMA only tracks the count of the
+	/* In continuous transfer mode, DMA only tracks the count of the
 	 * half DMA buffer. So, if the DMA already finished half the DMA
 	 * then add the half buffer to the completed count.
 	 *
@@ -318,6 +313,7 @@
 	struct tegra_dma_req *req)
 {
 	unsigned long irq_flags;
+	struct tegra_dma_req *_req;
 	int start_dma = 0;
 
 	if (req->size > NV_DMA_MAX_TRASFER_SIZE ||
@@ -328,6 +324,13 @@
 
 	spin_lock_irqsave(&ch->lock, irq_flags);
 
+	list_for_each_entry(_req, &ch->list, node) {
+		if (req == _req) {
+		    spin_unlock_irqrestore(&ch->lock, irq_flags);
+		    return -EEXIST;
+		}
+	}
+
 	req->bytes_transferred = 0;
 	req->status = 0;
 	req->buffer_status = 0;
@@ -348,7 +351,12 @@
 struct tegra_dma_channel *tegra_dma_allocate_channel(int mode)
 {
 	int channel;
-	struct tegra_dma_channel *ch;
+	struct tegra_dma_channel *ch = NULL;
+
+	if (WARN_ON(!tegra_dma_initialized))
+		return NULL;
+
+	mutex_lock(&tegra_dma_lock);
 
 	/* first channel is the shared channel */
 	if (mode & TEGRA_DMA_SHARED) {
@@ -357,11 +365,14 @@
 		channel = find_first_zero_bit(channel_usage,
 			ARRAY_SIZE(dma_channels));
 		if (channel >= ARRAY_SIZE(dma_channels))
-			return NULL;
+			goto out;
 	}
 	__set_bit(channel, channel_usage);
 	ch = &dma_channels[channel];
 	ch->mode = mode;
+
+out:
+	mutex_unlock(&tegra_dma_lock);
 	return ch;
 }
 EXPORT_SYMBOL(tegra_dma_allocate_channel);
@@ -371,22 +382,27 @@
 	if (ch->mode & TEGRA_DMA_SHARED)
 		return;
 	tegra_dma_cancel(ch);
+	mutex_lock(&tegra_dma_lock);
 	__clear_bit(ch->id, channel_usage);
+	mutex_unlock(&tegra_dma_lock);
 }
 EXPORT_SYMBOL(tegra_dma_free_channel);
 
 static void tegra_dma_update_hw_partial(struct tegra_dma_channel *ch,
 	struct tegra_dma_req *req)
 {
+	u32 apb_ptr;
+	u32 ahb_ptr;
+
 	if (req->to_memory) {
-		ch->apb_ptr = req->source_addr;
-		ch->ahb_ptr = req->dest_addr;
+		apb_ptr = req->source_addr;
+		ahb_ptr = req->dest_addr;
 	} else {
-		ch->apb_ptr = req->dest_addr;
-		ch->ahb_ptr = req->source_addr;
+		apb_ptr = req->dest_addr;
+		ahb_ptr = req->source_addr;
 	}
-	writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
-	writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+	writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+	writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
 
 	req->status = TEGRA_DMA_REQ_INFLIGHT;
 	return;
@@ -400,38 +416,39 @@
 	int ahb_bus_width;
 	int apb_bus_width;
 	int index;
-	unsigned long csr;
 
+	u32 ahb_seq;
+	u32 apb_seq;
+	u32 ahb_ptr;
+	u32 apb_ptr;
+	u32 csr;
 
-	ch->csr |= CSR_FLOW;
-	ch->csr &= ~CSR_REQ_SEL_MASK;
-	ch->csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
-	ch->ahb_seq &= ~AHB_SEQ_BURST_MASK;
-	ch->ahb_seq |= AHB_SEQ_BURST_1;
+	csr = CSR_IE_EOC | CSR_FLOW;
+	ahb_seq = AHB_SEQ_INTR_ENB | AHB_SEQ_BURST_1;
+	apb_seq = 0;
+
+	csr |= req->req_sel << CSR_REQ_SEL_SHIFT;
 
 	/* One shot mode is always single buffered,
 	 * continuous mode is always double buffered
 	 * */
 	if (ch->mode & TEGRA_DMA_MODE_ONESHOT) {
-		ch->csr |= CSR_ONCE;
-		ch->ahb_seq &= ~AHB_SEQ_DBL_BUF;
-		ch->csr &= ~CSR_WCOUNT_MASK;
-		ch->csr |= ((req->size>>2) - 1) << CSR_WCOUNT_SHIFT;
+		csr |= CSR_ONCE;
+		ch->req_transfer_count = (req->size >> 2) - 1;
 	} else {
-		ch->csr &= ~CSR_ONCE;
-		ch->ahb_seq |= AHB_SEQ_DBL_BUF;
+		ahb_seq |= AHB_SEQ_DBL_BUF;
 
 		/* In double buffered mode, we set the size to half the
 		 * requested size and interrupt when half the buffer
 		 * is full */
-		ch->csr &= ~CSR_WCOUNT_MASK;
-		ch->csr |= ((req->size>>3) - 1) << CSR_WCOUNT_SHIFT;
+		ch->req_transfer_count = (req->size >> 3) - 1;
 	}
 
+	csr |= ch->req_transfer_count << CSR_WCOUNT_SHIFT;
+
 	if (req->to_memory) {
-		ch->csr &= ~CSR_DIR;
-		ch->apb_ptr = req->source_addr;
-		ch->ahb_ptr = req->dest_addr;
+		apb_ptr = req->source_addr;
+		ahb_ptr = req->dest_addr;
 
 		apb_addr_wrap = req->source_wrap;
 		ahb_addr_wrap = req->dest_wrap;
@@ -439,9 +456,9 @@
 		ahb_bus_width = req->dest_bus_width;
 
 	} else {
-		ch->csr |= CSR_DIR;
-		ch->apb_ptr = req->dest_addr;
-		ch->ahb_ptr = req->source_addr;
+		csr |= CSR_DIR;
+		apb_ptr = req->dest_addr;
+		ahb_ptr = req->source_addr;
 
 		apb_addr_wrap = req->dest_wrap;
 		ahb_addr_wrap = req->source_wrap;
@@ -460,8 +477,7 @@
 		index++;
 	} while (index < ARRAY_SIZE(apb_addr_wrap_table));
 	BUG_ON(index == ARRAY_SIZE(apb_addr_wrap_table));
-	ch->apb_seq &= ~APB_SEQ_WRAP_MASK;
-	ch->apb_seq |= index << APB_SEQ_WRAP_SHIFT;
+	apb_seq |= index << APB_SEQ_WRAP_SHIFT;
 
 	/* set address wrap for AHB size */
 	index = 0;
@@ -471,55 +487,42 @@
 		index++;
 	} while (index < ARRAY_SIZE(ahb_addr_wrap_table));
 	BUG_ON(index == ARRAY_SIZE(ahb_addr_wrap_table));
-	ch->ahb_seq &= ~AHB_SEQ_WRAP_MASK;
-	ch->ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
+	ahb_seq |= index << AHB_SEQ_WRAP_SHIFT;
 
 	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
 		if (bus_width_table[index] == ahb_bus_width)
 			break;
 	}
 	BUG_ON(index == ARRAY_SIZE(bus_width_table));
-	ch->ahb_seq &= ~AHB_SEQ_BUS_WIDTH_MASK;
-	ch->ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
+	ahb_seq |= index << AHB_SEQ_BUS_WIDTH_SHIFT;
 
 	for (index = 0; index < ARRAY_SIZE(bus_width_table); index++) {
 		if (bus_width_table[index] == apb_bus_width)
 			break;
 	}
 	BUG_ON(index == ARRAY_SIZE(bus_width_table));
-	ch->apb_seq &= ~APB_SEQ_BUS_WIDTH_MASK;
-	ch->apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
-
-	ch->csr |= CSR_IE_EOC;
+	apb_seq |= index << APB_SEQ_BUS_WIDTH_SHIFT;
 
-	/* update hw registers with the shadow */
-	writel(ch->csr, ch->addr + APB_DMA_CHAN_CSR);
-	writel(ch->apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
-	writel(ch->apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
-	writel(ch->ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
-	writel(ch->ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
+	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
+	writel(apb_seq, ch->addr + APB_DMA_CHAN_APB_SEQ);
+	writel(apb_ptr, ch->addr + APB_DMA_CHAN_APB_PTR);
+	writel(ahb_seq, ch->addr + APB_DMA_CHAN_AHB_SEQ);
+	writel(ahb_ptr, ch->addr + APB_DMA_CHAN_AHB_PTR);
 
-	csr = ch->csr | CSR_ENB;
+	csr |= CSR_ENB;
 	writel(csr, ch->addr + APB_DMA_CHAN_CSR);
 
 	req->status = TEGRA_DMA_REQ_INFLIGHT;
 }
 
-static void tegra_dma_init_hw(struct tegra_dma_channel *ch)
-{
-	/* One shot with an interrupt to CPU after transfer */
-	ch->csr = CSR_ONCE | CSR_IE_EOC;
-	ch->ahb_seq = AHB_SEQ_BUS_WIDTH_32 | AHB_SEQ_INTR_ENB;
-	ch->apb_seq = APB_SEQ_BUS_WIDTH_32 | 1 << APB_SEQ_WRAP_SHIFT;
-}
-
 static void handle_oneshot_dma(struct tegra_dma_channel *ch)
 {
 	struct tegra_dma_req *req;
+	unsigned long irq_flags;
 
-	spin_lock(&ch->lock);
+	spin_lock_irqsave(&ch->lock, irq_flags);
 	if (list_empty(&ch->list)) {
-		spin_unlock(&ch->lock);
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		return;
 	}
 
@@ -527,8 +530,7 @@
 	if (req) {
 		int bytes_transferred;
 
-		bytes_transferred =
-			(ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+		bytes_transferred = ch->req_transfer_count;
 		bytes_transferred += 1;
 		bytes_transferred <<= 2;
 
@@ -536,12 +538,12 @@
 		req->bytes_transferred = bytes_transferred;
 		req->status = TEGRA_DMA_REQ_SUCCESS;
 
-		spin_unlock(&ch->lock);
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		/* Callback should be called without any lock */
 		pr_debug("%s: transferred %d bytes\n", __func__,
 			req->bytes_transferred);
 		req->complete(req);
-		spin_lock(&ch->lock);
+		spin_lock_irqsave(&ch->lock, irq_flags);
 	}
 
 	if (!list_empty(&ch->list)) {
@@ -551,22 +553,55 @@
 		if (req->status != TEGRA_DMA_REQ_INFLIGHT)
 			tegra_dma_update_hw(ch, req);
 	}
-	spin_unlock(&ch->lock);
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
 }
 
 static void handle_continuous_dma(struct tegra_dma_channel *ch)
 {
 	struct tegra_dma_req *req;
+	unsigned long irq_flags;
 
-	spin_lock(&ch->lock);
+	spin_lock_irqsave(&ch->lock, irq_flags);
 	if (list_empty(&ch->list)) {
-		spin_unlock(&ch->lock);
+		spin_unlock_irqrestore(&ch->lock, irq_flags);
 		return;
 	}
 
 	req = list_entry(ch->list.next, typeof(*req), node);
 	if (req) {
 		if (req->buffer_status == TEGRA_DMA_REQ_BUF_STATUS_EMPTY) {
+			bool is_dma_ping_complete;
+			is_dma_ping_complete = (readl(ch->addr + APB_DMA_CHAN_STA)
+						& STA_PING_PONG) ? true : false;
+			if (req->to_memory)
+				is_dma_ping_complete = !is_dma_ping_complete;
+			/* Out of sync - Release current buffer */
+			if (!is_dma_ping_complete) {
+				int bytes_transferred;
+
+				bytes_transferred = ch->req_transfer_count;
+				bytes_transferred += 1;
+				bytes_transferred <<= 3;
+				req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_FULL;
+				req->bytes_transferred = bytes_transferred;
+				req->status = TEGRA_DMA_REQ_SUCCESS;
+				tegra_dma_stop(ch);
+
+				if (!list_is_last(&req->node, &ch->list)) {
+					struct tegra_dma_req *next_req;
+
+					next_req = list_entry(req->node.next,
+						typeof(*next_req), node);
+					tegra_dma_update_hw(ch, next_req);
+				}
+
+				list_del(&req->node);
+
+				/* DMA lock is NOT held when callbak is called */
+				spin_unlock_irqrestore(&ch->lock, irq_flags);
+				req->complete(req);
+				return;
+			}
 			/* Load the next request into the hardware, if available
 			 * */
 			if (!list_is_last(&req->node, &ch->list)) {
@@ -579,7 +614,7 @@
 			req->buffer_status = TEGRA_DMA_REQ_BUF_STATUS_HALF_FULL;
 			req->status = TEGRA_DMA_REQ_SUCCESS;
 			/* DMA lock is NOT held when callback is called */
-			spin_unlock(&ch->lock);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			if (likely(req->threshold))
 				req->threshold(req);
 			return;
@@ -590,8 +625,7 @@
 			 * the second  interrupt */
 			int bytes_transferred;
 
-			bytes_transferred =
-				(ch->csr & CSR_WCOUNT_MASK) >> CSR_WCOUNT_SHIFT;
+			bytes_transferred = ch->req_transfer_count;
 			bytes_transferred += 1;
 			bytes_transferred <<= 3;
 
@@ -601,7 +635,7 @@
 			list_del(&req->node);
 
 			/* DMA lock is NOT held when callbak is called */
-			spin_unlock(&ch->lock);
+			spin_unlock_irqrestore(&ch->lock, irq_flags);
 			req->complete(req);
 			return;
 
@@ -609,7 +643,7 @@
 			BUG();
 		}
 	}
-	spin_unlock(&ch->lock);
+	spin_unlock_irqrestore(&ch->lock, irq_flags);
 }
 
 static irqreturn_t dma_isr(int irq, void *data)
@@ -646,6 +680,21 @@
 	int i;
 	unsigned int irq;
 	void __iomem *addr;
+	struct clk *c;
+
+	bitmap_fill(channel_usage, NV_DMA_MAX_CHANNELS);
+
+	c = clk_get_sys("tegra-dma", NULL);
+	if (IS_ERR(c)) {
+		pr_err("Unable to get clock for APB DMA\n");
+		ret = PTR_ERR(c);
+		goto fail;
+	}
+	ret = clk_enable(c);
+	if (ret != 0) {
+		pr_err("Unable to enable clock for APB DMA\n");
+		goto fail;
+	}
 
 	addr = IO_ADDRESS(TEGRA_APB_DMA_BASE);
 	writel(GEN_ENABLE, addr + APB_DMA_GEN);
@@ -653,18 +702,9 @@
 	writel(0xFFFFFFFFul >> (31 - TEGRA_SYSTEM_DMA_CH_MAX),
 	       addr + APB_DMA_IRQ_MASK_SET);
 
-	memset(channel_usage, 0, sizeof(channel_usage));
-	memset(dma_channels, 0, sizeof(dma_channels));
-
-	/* Reserve all the channels we are not supposed to touch */
-	for (i = 0; i < TEGRA_SYSTEM_DMA_CH_MIN; i++)
-		__set_bit(i, channel_usage);
-
 	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
 		struct tegra_dma_channel *ch = &dma_channels[i];
 
-		__clear_bit(i, channel_usage);
-
 		ch->id = i;
 		snprintf(ch->name, TEGRA_DMA_NAME_SIZE, "dma_channel_%d", i);
 
@@ -673,7 +713,6 @@
 
 		spin_lock_init(&ch->lock);
 		INIT_LIST_HEAD(&ch->list);
-		tegra_dma_init_hw(ch);
 
 		irq = INT_APB_DMA_CH0 + i;
 		ret = request_threaded_irq(irq, dma_isr, dma_thread_fn, 0,
@@ -684,14 +723,15 @@
 			goto fail;
 		}
 		ch->irq = irq;
+
+		__clear_bit(i, channel_usage);
 	}
 	/* mark the shared channel allocated */
 	__set_bit(TEGRA_SYSTEM_DMA_CH_MIN, channel_usage);
 
-	for (i = TEGRA_SYSTEM_DMA_CH_MAX+1; i < NV_DMA_MAX_CHANNELS; i++)
-		__set_bit(i, channel_usage);
+	tegra_dma_initialized = true;
 
-	return ret;
+	return 0;
 fail:
 	writel(0, addr + APB_DMA_GEN);
 	for (i = TEGRA_SYSTEM_DMA_CH_MIN; i <= TEGRA_SYSTEM_DMA_CH_MAX; i++) {
@@ -701,6 +741,7 @@
 	}
 	return ret;
 }
+postcore_initcall(tegra_dma_init);
 
 #ifdef CONFIG_PM
 static u32 apb_dma[5*TEGRA_SYSTEM_DMA_CH_NR + 3];
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/gpio.h>
 
 #include <mach/iomap.h>
+#include <mach/suspend.h>
 
 #define GPIO_BANK(x)		((x) >> 5)
 #define GPIO_PORT(x)		(((x) >> 3) & 0x3)
@@ -207,9 +208,9 @@
 	spin_unlock_irqrestore(&bank->lvl_lock[port], flags);
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-		__set_irq_handler_unlocked(d->irq, handle_level_irq);
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		__set_irq_handler_unlocked(d->irq, handle_edge_irq);
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 
 	return 0;
 }
@@ -223,7 +224,7 @@
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-	bank = get_irq_data(irq);
+	bank = irq_get_handler_data(irq);
 
 	for (port = 0; port < 4; port++) {
 		int gpio = tegra_gpio_compose(bank->bank, port, 0);
@@ -256,7 +257,8 @@
 void tegra_gpio_resume(void)
 {
 	unsigned long flags;
-	int b, p, i;
+	int b;
+	int p;
 
 	local_irq_save(flags);
 
@@ -274,31 +276,13 @@
 	}
 
 	local_irq_restore(flags);
-
-	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-		if (!desc || (desc->status & IRQ_WAKEUP))
-			continue;
-		enable_irq(i);
-	}
 }
 
 void tegra_gpio_suspend(void)
 {
 	unsigned long flags;
-	int b, p, i;
-
-	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-		if (!desc)
-			continue;
-		if (desc->status & IRQ_WAKEUP) {
-			int gpio = i - INT_GPIO_BASE;
-			pr_debug("gpio %d.%d is wakeup\n", gpio/8, gpio&7);
-			continue;
-		}
-		disable_irq(i);
-	}
+	int b;
+	int p;
 
 	local_irq_save(flags);
 	for (b = 0; b < ARRAY_SIZE(tegra_gpio_banks); b++) {
@@ -319,7 +303,7 @@
 static int tegra_gpio_wake_enable(struct irq_data *d, unsigned int enable)
 {
 	struct tegra_gpio_bank *bank = irq_data_get_irq_chip_data(d);
-	return set_irq_wake(bank->irq, enable);
+	return irq_set_irq_wake(bank->irq, enable);
 }
 #endif
 
@@ -358,18 +342,18 @@
 	for (i = INT_GPIO_BASE; i < (INT_GPIO_BASE + TEGRA_NR_GPIOS); i++) {
 		bank = &tegra_gpio_banks[GPIO_BANK(irq_to_gpio(i))];
 
-		lockdep_set_class(&irq_desc[i].lock, &gpio_lock_class);
-		set_irq_chip_data(i, bank);
-		set_irq_chip(i, &tegra_gpio_irq_chip);
-		set_irq_handler(i, handle_simple_irq);
+		irq_set_lockdep_class(i, &gpio_lock_class);
+		irq_set_chip_data(i, bank);
+		irq_set_chip_and_handler(i, &tegra_gpio_irq_chip,
+					 handle_simple_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
 	for (i = 0; i < ARRAY_SIZE(tegra_gpio_banks); i++) {
 		bank = &tegra_gpio_banks[i];
 
-		set_irq_chained_handler(bank->irq, tegra_gpio_irq_handler);
-		set_irq_data(bank->irq, bank);
+		irq_set_chained_handler(bank->irq, tegra_gpio_irq_handler);
+		irq_set_handler_data(bank->irq, bank);
 
 		for (j = 0; j < 4; j++)
 			spin_lock_init(&bank->lvl_lock[j]);
@@ -380,6 +364,20 @@
 
 postcore_initcall(tegra_gpio_init);
 
+void __init tegra_gpio_config(struct tegra_gpio_table *table, int num)
+{
+	int i;
+
+	for (i = 0; i < num; i++) {
+		int gpio = table[i].gpio;
+
+		if (table[i].enable)
+			tegra_gpio_enable(gpio);
+		else
+			tegra_gpio_disable(gpio);
+	}
+}
+
 #ifdef	CONFIG_DEBUG_FS
 
 #include <linux/debugfs.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/barriers.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/barriers.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/barriers.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/barriers.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 
 #include <asm/outercache.h>
 
-#define rmb()		dmb()
+#define rmb()		dsb()
 #define wmb()		do { dsb(); outer_sync(); } while (0)
 #define mb()		wmb()
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/clk.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/clk.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/clk.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/clk.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,9 +25,7 @@
 void tegra_periph_reset_deassert(struct clk *c);
 void tegra_periph_reset_assert(struct clk *c);
 
-int clk_enable_cansleep(struct clk *clk);
-void clk_disable_cansleep(struct clk *clk);
-int clk_set_rate_cansleep(struct clk *clk, unsigned long rate);
-int clk_set_parent_cansleep(struct clk *clk, struct clk *parent);
+unsigned long clk_get_rate_all_locked(struct clk *c);
+void tegra_sdmmc_tap_delay(struct clk *c, int delay);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -19,30 +19,15 @@
  */
 
 #include <mach/io.h>
+#include <mach/iomap.h>
 
 	.macro  addruart, rp, rv
         ldr     \rp, =IO_APB_PHYS       @ physical
         ldr     \rv, =IO_APB_VIRT        @ virtual
-#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
-#error "A debug UART must be selected in the kernel config to use DEBUG_LL"
-#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
-        orr     \rp, \rp, #0x6000
-        orr     \rv, \rv, #0x6000
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-        orr     \rp, \rp, #0x6000
-	orr	\rp, \rp, #0x40
-        orr     \rv, \rv, #0x6000
-	orr	\rv, \rv, #0x40
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-        orr     \rp, \rp, #0x6200
-        orr     \rv, \rv, #0x6200
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-        orr     \rp, \rp, #0x6300
-        orr     \rv, \rv, #0x6300
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-        orr     \rp, \rp, #0x6400
-        orr     \rv, \rv, #0x6400
-#endif
+	orr	\rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF)
+	orr	\rp, \rp, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
+	orr	\rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF)
+	orr	\rv, \rv, #(TEGRA_DEBUG_UART_BASE & 0xFF00)
 	.endm
 
 #define UART_SHIFT	2
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/dma.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -92,11 +92,11 @@
 	/*  This is a called from the DMA ISR context when the DMA is still in
 	 *  progress and is actively filling same buffer.
 	 *
-	 *  In case of continous mode receive, this threshold is 1/2 the buffer
+	 *  In case of continuous mode receive, this threshold is 1/2 the buffer
 	 *  size. In other cases, this will not even be called as there is no
 	 *  hardware support for it.
 	 *
-	 * In the case of continous mode receive, if there is next req already
+	 * In the case of continuous mode receive, if there is next req already
 	 * queued, DMA programs the HW to use that req when this req is
 	 * completed. If there is no "next req" queued, then DMA ISR doesn't do
 	 * anything before calling this callback.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #ifndef __MACH_TEGRA_GPIO_H
 #define __MACH_TEGRA_GPIO_H
 
+#include <linux/init.h>
 #include <mach/irqs.h>
 
 #define TEGRA_NR_GPIOS		INT_GPIO_NR
@@ -31,7 +32,7 @@
 #define gpio_cansleep		__gpio_cansleep
 
 #define TEGRA_GPIO_TO_IRQ(gpio) (INT_GPIO_BASE + (gpio))
-#define TEGRA_IRQ_TO_GPIO(irq) ((gpio) - INT_GPIO_BASE)
+#define TEGRA_IRQ_TO_GPIO(irq) ((irq) - INT_GPIO_BASE)
 
 static inline int gpio_to_irq(unsigned int gpio)
 {
@@ -47,6 +48,12 @@
 	return -EINVAL;
 }
 
+struct tegra_gpio_table {
+	int	gpio;	/* GPIO number */
+	bool	enable;	/* Enable for GPIO at init? */
+};
+
+void tegra_gpio_config(struct tegra_gpio_table *table, int num);
 void tegra_gpio_enable(int gpio);
 void tegra_gpio_disable(int gpio);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/harmony_audio.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/harmony_audio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/harmony_audio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/harmony_audio.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * arch/arm/mach-tegra/include/mach/harmony_audio.h
+ *
+ * Copyright 2011 NVIDIA, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+struct harmony_audio_platform_data {
+	int gpio_spkr_en;
+	int gpio_hp_det;
+	int gpio_int_mic_en;
+	int gpio_ext_mic_en;
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/iomap.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/iomap.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/iomap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/iomap.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,9 @@
 #define TEGRA_IRAM_BASE			0x40000000
 #define TEGRA_IRAM_SIZE			SZ_256K
 
+#define TEGRA_HOST1X_BASE		0x50000000
+#define TEGRA_HOST1X_SIZE		0x24000
+
 #define TEGRA_ARM_PERIF_BASE		0x50040000
 #define TEGRA_ARM_PERIF_SIZE		SZ_8K
 
@@ -35,12 +38,30 @@
 #define TEGRA_ARM_INT_DIST_BASE		0x50041000
 #define TEGRA_ARM_INT_DIST_SIZE		SZ_4K
 
+#define TEGRA_MPE_BASE			0x54040000
+#define TEGRA_MPE_SIZE			SZ_256K
+
+#define TEGRA_VI_BASE			0x54080000
+#define TEGRA_VI_SIZE			SZ_256K
+
+#define TEGRA_ISP_BASE			0x54100000
+#define TEGRA_ISP_SIZE			SZ_256K
+
 #define TEGRA_DISPLAY_BASE		0x54200000
 #define TEGRA_DISPLAY_SIZE		SZ_256K
 
 #define TEGRA_DISPLAY2_BASE		0x54240000
 #define TEGRA_DISPLAY2_SIZE		SZ_256K
 
+#define TEGRA_HDMI_BASE			0x54280000
+#define TEGRA_HDMI_SIZE			SZ_256K
+
+#define TEGRA_GART_BASE			0x58000000
+#define TEGRA_GART_SIZE			SZ_32M
+
+#define TEGRA_RES_SEMA_BASE		0x60001000
+#define TEGRA_RES_SEMA_SIZE		SZ_4K
+
 #define TEGRA_PRIMARY_ICTLR_BASE	0x60004000
 #define TEGRA_PRIMARY_ICTLR_SIZE	SZ_64
 
@@ -101,6 +122,9 @@
 #define TEGRA_APB_MISC_BASE		0x70000000
 #define TEGRA_APB_MISC_SIZE		SZ_4K
 
+#define TEGRA_APB_MISC_DAS_BASE		0x70000c00
+#define TEGRA_APB_MISC_DAS_SIZE		SZ_128
+
 #define TEGRA_AC97_BASE			0x70002000
 #define TEGRA_AC97_SIZE			SZ_512
 
@@ -140,6 +164,18 @@
 #define TEGRA_PWFM_BASE			0x7000A000
 #define TEGRA_PWFM_SIZE			SZ_256
 
+#define TEGRA_PWFM0_BASE		0x7000A000
+#define TEGRA_PWFM0_SIZE		4
+
+#define TEGRA_PWFM1_BASE		0x7000A010
+#define TEGRA_PWFM1_SIZE		4
+
+#define TEGRA_PWFM2_BASE		0x7000A020
+#define TEGRA_PWFM2_SIZE		4
+
+#define TEGRA_PWFM3_BASE		0x7000A030
+#define TEGRA_PWFM3_SIZE		4
+
 #define TEGRA_MIPI_BASE			0x7000B000
 #define TEGRA_MIPI_SIZE			SZ_256
 
@@ -221,4 +257,18 @@
 #define TEGRA_SDMMC4_BASE		0xC8000600
 #define TEGRA_SDMMC4_SIZE		SZ_512
 
+#if defined(CONFIG_TEGRA_DEBUG_UART_NONE)
+# define TEGRA_DEBUG_UART_BASE 0
+#elif defined(CONFIG_TEGRA_DEBUG_UARTA)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTA_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTB_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTC_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTD_BASE
+#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
+# define TEGRA_DEBUG_UART_BASE TEGRA_UARTE_BASE
+#endif
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 #define INT_SYS_STATS_MON		(INT_SEC_BASE + 22)
 #define INT_GPIO5			(INT_SEC_BASE + 23)
 #define INT_CPU0_PMU_INTR		(INT_SEC_BASE + 24)
-#define INT_CPU2_PMU_INTR		(INT_SEC_BASE + 25)
+#define INT_CPU1_PMU_INTR		(INT_SEC_BASE + 25)
 #define INT_SEC_RES_26			(INT_SEC_BASE + 26)
 #define INT_S_LINK1			(INT_SEC_BASE + 27)
 #define INT_APB_DMA_COP			(INT_SEC_BASE + 28)
@@ -166,10 +166,18 @@
 #define INT_QUAD_RES_30			(INT_QUAD_BASE + 30)
 #define INT_QUAD_RES_31			(INT_QUAD_BASE + 31)
 
-#define INT_GPIO_BASE			(INT_QUAD_BASE + 32)
+#define INT_MAIN_NR			(INT_QUAD_BASE + 32 - INT_PRI_BASE)
+
+#define INT_GPIO_BASE			(INT_PRI_BASE + INT_MAIN_NR)
+
 #define INT_GPIO_NR			(28 * 8)
 
-#define NR_IRQS				(INT_GPIO_BASE + INT_GPIO_NR)
+#define TEGRA_NR_IRQS			(INT_GPIO_BASE + INT_GPIO_NR)
+
+#define INT_BOARD_BASE			TEGRA_NR_IRQS
+#define NR_BOARD_IRQS			32
+
+#define NR_IRQS				(INT_BOARD_BASE + NR_BOARD_IRQS)
 #endif
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/legacy_irq.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/legacy_irq.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/legacy_irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/legacy_irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,5 +27,9 @@
 void tegra_legacy_select_fiq(unsigned int irq, bool fiq);
 unsigned long tegra_legacy_vfiq(int nr);
 unsigned long tegra_legacy_class(int nr);
+int tegra_legacy_irq_set_wake(int irq, int enable);
+void tegra_legacy_irq_set_lp1_wake_mask(void);
+void tegra_legacy_irq_restore_mask(void);
+void tegra_init_legacy_irq(void);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
 #define __MACH_TEGRA_MEMORY_H
 
 /* physical offset of RAM */
-#define PHYS_OFFSET		UL(0)
+#define PLAT_PHYS_OFFSET		UL(0)
 
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/pinmux-t2.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/pinmux-t2.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/pinmux-t2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/pinmux-t2.h	2011-05-19 00:06:34.000000000 -0400
@@ -167,6 +167,16 @@
 	TEGRA_DRIVE_PINGROUP_XM2D,
 	TEGRA_DRIVE_PINGROUP_XM2CLK,
 	TEGRA_DRIVE_PINGROUP_MEMCOMP,
+	TEGRA_DRIVE_PINGROUP_SDIO1,
+	TEGRA_DRIVE_PINGROUP_CRT,
+	TEGRA_DRIVE_PINGROUP_DDC,
+	TEGRA_DRIVE_PINGROUP_GMA,
+	TEGRA_DRIVE_PINGROUP_GMB,
+	TEGRA_DRIVE_PINGROUP_GMC,
+	TEGRA_DRIVE_PINGROUP_GMD,
+	TEGRA_DRIVE_PINGROUP_GME,
+	TEGRA_DRIVE_PINGROUP_OWR,
+	TEGRA_DRIVE_PINGROUP_UAD,
 	TEGRA_MAX_DRIVE_PINGROUP,
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/powergate.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/powergate.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/powergate.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/powergate.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * drivers/regulator/tegra-regulator.c
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef _MACH_TEGRA_POWERGATE_H_
+#define _MACH_TEGRA_POWERGATE_H_
+
+#define TEGRA_POWERGATE_CPU	0
+#define TEGRA_POWERGATE_3D	1
+#define TEGRA_POWERGATE_VENC	2
+#define TEGRA_POWERGATE_PCIE	3
+#define TEGRA_POWERGATE_VDEC	4
+#define TEGRA_POWERGATE_L2	5
+#define TEGRA_POWERGATE_MPE	6
+#define TEGRA_NUM_POWERGATE	7
+
+int tegra_powergate_power_on(int id);
+int tegra_powergate_power_off(int id);
+bool tegra_powergate_is_powered(int id);
+int tegra_powergate_remove_clamping(int id);
+
+/* Must be called with clk disabled, and returns with clk enabled */
+int tegra_powergate_sequence_power_up(int id, struct clk *clk);
+
+#endif /* _MACH_TEGRA_POWERGATE_H_ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/suspend.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/suspend.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/suspend.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/suspend.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * arch/arm/mach-tegra/include/mach/suspend.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+
+#ifndef _MACH_TEGRA_SUSPEND_H_
+#define _MACH_TEGRA_SUSPEND_H_
+
+void tegra_pinmux_suspend(void);
+void tegra_irq_suspend(void);
+void tegra_gpio_suspend(void);
+void tegra_clk_suspend(void);
+void tegra_dma_suspend(void);
+void tegra_timer_suspend(void);
+
+void tegra_pinmux_resume(void);
+void tegra_irq_resume(void);
+void tegra_gpio_resume(void);
+void tegra_clk_resume(void);
+void tegra_dma_resume(void);
+void tegra_timer_resume(void);
+
+#endif /* _MACH_TEGRA_SUSPEND_H_ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,16 +24,10 @@
 #include <mach/hardware.h>
 #include <mach/iomap.h>
 
-static inline void arch_idle(void)
-{
-}
+extern void (*arch_reset)(char mode, const char *cmd);
 
-static inline void arch_reset(char mode, const char *cmd)
+static inline void arch_idle(void)
 {
-	void __iomem *reset = IO_ADDRESS(TEGRA_CLK_RESET_BASE + 0x04);
-	u32 reg = readl(reset);
-	reg |= 0x04;
-	writel(reg, reset);
 }
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,23 +26,9 @@
 
 #include <mach/iomap.h>
 
-#if defined(CONFIG_TEGRA_DEBUG_UARTA)
-#define DEBUG_UART_BASE TEGRA_UARTA_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTB)
-#define DEBUG_UART_BASE TEGRA_UARTB_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTC)
-#define DEBUG_UART_BASE TEGRA_UARTC_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTD)
-#define DEBUG_UART_BASE TEGRA_UARTD_BASE
-#elif defined(CONFIG_TEGRA_DEBUG_UARTE)
-#define DEBUG_UART_BASE TEGRA_UARTE_BASE
-#else
-#define DEBUG_UART_BASE NULL
-#endif
-
 static void putc(int c)
 {
-	volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+	volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
 	int shift = 2;
 
 	if (uart == NULL)
@@ -59,7 +45,7 @@
 
 static inline void arch_decomp_setup(void)
 {
-	volatile u8 *uart = (volatile u8 *)DEBUG_UART_BASE;
+	volatile u8 *uart = (volatile u8 *)TEGRA_DEBUG_UART_BASE;
 	int shift = 2;
 
 	if (uart == NULL)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/usb_phy.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/usb_phy.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/include/mach/usb_phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/include/mach/usb_phy.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * arch/arm/mach-tegra/include/mach/usb_phy.h
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MACH_USB_PHY_H
+#define __MACH_USB_PHY_H
+
+#include <linux/clk.h>
+#include <linux/usb/otg.h>
+
+struct tegra_utmip_config {
+	u8 hssync_start_delay;
+	u8 elastic_limit;
+	u8 idle_wait_delay;
+	u8 term_range_adj;
+	u8 xcvr_setup;
+	u8 xcvr_lsfslew;
+	u8 xcvr_lsrslew;
+};
+
+struct tegra_ulpi_config {
+	int reset_gpio;
+	const char *clk;
+};
+
+enum tegra_usb_phy_port_speed {
+	TEGRA_USB_PHY_PORT_SPEED_FULL = 0,
+	TEGRA_USB_PHY_PORT_SPEED_LOW,
+	TEGRA_USB_PHY_PORT_SPEED_HIGH,
+};
+
+enum tegra_usb_phy_mode {
+	TEGRA_USB_PHY_MODE_DEVICE,
+	TEGRA_USB_PHY_MODE_HOST,
+};
+
+struct tegra_xtal_freq;
+
+struct tegra_usb_phy {
+	int instance;
+	const struct tegra_xtal_freq *freq;
+	void __iomem *regs;
+	void __iomem *pad_regs;
+	struct clk *clk;
+	struct clk *pll_u;
+	struct clk *pad_clk;
+	enum tegra_usb_phy_mode mode;
+	void *config;
+	struct otg_transceiver *ulpi;
+};
+
+struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
+			void *config, enum tegra_usb_phy_mode phy_mode);
+
+int tegra_usb_phy_power_on(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_power_off(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_preresume(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_postresume(struct tegra_usb_phy *phy);
+
+void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
+				 enum tegra_usb_phy_port_speed port_speed);
+
+void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
+
+void tegra_usb_phy_close(struct tegra_usb_phy *phy);
+
+#endif /* __MACH_USB_PHY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/delay.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -26,146 +27,134 @@
 #include <asm/hardware/gic.h>
 
 #include <mach/iomap.h>
+#include <mach/legacy_irq.h>
+#include <mach/suspend.h>
 
 #include "board.h"
 
-#define INT_SYS_NR	(INT_GPIO_BASE - INT_PRI_BASE)
-#define INT_SYS_SZ	(INT_SEC_BASE - INT_PRI_BASE)
-#define PPI_NR		((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+#define PMC_CTRL		0x0
+#define PMC_CTRL_LATCH_WAKEUPS	(1 << 5)
+#define PMC_WAKE_MASK		0xc
+#define PMC_WAKE_LEVEL		0x10
+#define PMC_WAKE_STATUS		0x14
+#define PMC_SW_WAKE_STATUS	0x18
+#define PMC_DPD_SAMPLE		0x20
 
-#define APBDMA_IRQ_STA_CPU  0x14
-#define APBDMA_IRQ_MASK_SET 0x20
-#define APBDMA_IRQ_MASK_CLR 0x24
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
 
-#define ICTLR_CPU_IER		0x20
-#define ICTLR_CPU_IER_SET	0x24
-#define ICTLR_CPU_IER_CLR	0x28
-#define ICTLR_CPU_IEP_CLASS	0x2c
-#define ICTLR_COP_IER		0x30
-#define ICTLR_COP_IER_SET	0x34
-#define ICTLR_COP_IER_CLR	0x38
-#define ICTLR_COP_IEP_CLASS	0x3c
+static u32 tegra_lp0_wake_enb;
+static u32 tegra_lp0_wake_level;
+static u32 tegra_lp0_wake_level_any;
 
 static void (*tegra_gic_mask_irq)(struct irq_data *d);
 static void (*tegra_gic_unmask_irq)(struct irq_data *d);
+static void (*tegra_gic_ack_irq)(struct irq_data *d);
 
-#define irq_to_ictlr(irq) (((irq) - 32) >> 5)
-static void __iomem *tegra_ictlr_base = IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE);
-#define ictlr_to_virt(ictlr) (tegra_ictlr_base + (ictlr) * 0x100)
+/* ensures that sufficient time is passed for a register write to
+ * serialize into the 32KHz domain */
+static void pmc_32kwritel(u32 val, unsigned long offs)
+{
+	writel(val, pmc + offs);
+	udelay(130);
+}
+
+int tegra_set_lp1_wake(int irq, int enable)
+{
+	return tegra_legacy_irq_set_wake(irq, enable);
+}
+
+void tegra_set_lp0_wake_pads(u32 wake_enb, u32 wake_level, u32 wake_any)
+{
+	u32 temp;
+	u32 status;
+	u32 lvl;
+
+	wake_level &= wake_enb;
+	wake_any &= wake_enb;
+
+	wake_level |= (tegra_lp0_wake_level & tegra_lp0_wake_enb);
+	wake_any |= (tegra_lp0_wake_level_any & tegra_lp0_wake_enb);
+
+	wake_enb |= tegra_lp0_wake_enb;
+
+	pmc_32kwritel(0, PMC_SW_WAKE_STATUS);
+	temp = readl(pmc + PMC_CTRL);
+	temp |= PMC_CTRL_LATCH_WAKEUPS;
+	pmc_32kwritel(temp, PMC_CTRL);
+	temp &= ~PMC_CTRL_LATCH_WAKEUPS;
+	pmc_32kwritel(temp, PMC_CTRL);
+	status = readl(pmc + PMC_SW_WAKE_STATUS);
+	lvl = readl(pmc + PMC_WAKE_LEVEL);
+
+	/* flip the wakeup trigger for any-edge triggered pads
+	 * which are currently asserting as wakeups */
+	lvl ^= status;
+	lvl &= wake_any;
+
+	wake_level |= lvl;
+
+	writel(wake_level, pmc + PMC_WAKE_LEVEL);
+	/* Enable DPD sample to trigger sampling pads data and direction
+	 * in which pad will be driven during lp0 mode*/
+	writel(0x1, pmc + PMC_DPD_SAMPLE);
+
+	writel(wake_enb, pmc + PMC_WAKE_MASK);
+}
 
 static void tegra_mask(struct irq_data *d)
 {
-	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
 	tegra_gic_mask_irq(d);
-	writel(1 << (d->irq & 31), addr+ICTLR_CPU_IER_CLR);
+	tegra_legacy_mask_irq(d->irq);
 }
 
 static void tegra_unmask(struct irq_data *d)
 {
-	void __iomem *addr = ictlr_to_virt(irq_to_ictlr(d->irq));
 	tegra_gic_unmask_irq(d);
-	writel(1<<(d->irq&31), addr+ICTLR_CPU_IER_SET);
+	tegra_legacy_unmask_irq(d->irq);
 }
 
-#ifdef CONFIG_PM
+static void tegra_ack(struct irq_data *d)
+{
+	tegra_legacy_force_irq_clr(d->irq);
+	tegra_gic_ack_irq(d);
+}
 
-static int tegra_set_wake(struct irq_data *d, unsigned int on)
+static int tegra_retrigger(struct irq_data *d)
 {
-	return 0;
+	tegra_legacy_force_irq_set(d->irq);
+	return 1;
 }
-#endif
 
 static struct irq_chip tegra_irq = {
-	.name		= "PPI",
-	.irq_mask	= tegra_mask,
-	.irq_unmask	= tegra_unmask,
-#ifdef CONFIG_PM
-	.irq_set_wake	= tegra_set_wake,
-#endif
+	.name			= "PPI",
+	.irq_ack		= tegra_ack,
+	.irq_mask		= tegra_mask,
+	.irq_unmask		= tegra_unmask,
+	.irq_retrigger		= tegra_retrigger,
 };
 
 void __init tegra_init_irq(void)
 {
 	struct irq_chip *gic;
 	unsigned int i;
+	int irq;
 
-	for (i = 0; i < PPI_NR; i++) {
-		writel(~0, ictlr_to_virt(i) + ICTLR_CPU_IER_CLR);
-		writel(0, ictlr_to_virt(i) + ICTLR_CPU_IEP_CLASS);
-	}
+	tegra_init_legacy_irq();
 
 	gic_init(0, 29, IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE),
 		 IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
 
-	gic = get_irq_chip(29);
+	gic = irq_get_chip(29);
 	tegra_gic_unmask_irq = gic->irq_unmask;
 	tegra_gic_mask_irq = gic->irq_mask;
-	tegra_irq.irq_ack = gic->irq_ack;
+	tegra_gic_ack_irq = gic->irq_ack;
 #ifdef CONFIG_SMP
 	tegra_irq.irq_set_affinity = gic->irq_set_affinity;
 #endif
 
-	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
-		set_irq_chip(i, &tegra_irq);
-		set_irq_handler(i, handle_level_irq);
-		set_irq_flags(i, IRQF_VALID);
-	}
-}
-
-#ifdef CONFIG_PM
-static u32 cop_ier[PPI_NR];
-static u32 cpu_ier[PPI_NR];
-static u32 cpu_iep[PPI_NR];
-
-void tegra_irq_suspend(void)
-{
-	unsigned long flags;
-	int i;
-
-	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-		if (!desc)
-			continue;
-		if (desc->status & IRQ_WAKEUP) {
-			pr_debug("irq %d is wakeup\n", i);
-			continue;
-		}
-		disable_irq(i);
-	}
-
-	local_irq_save(flags);
-	for (i = 0; i < PPI_NR; i++) {
-		void __iomem *ictlr = ictlr_to_virt(i);
-		cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
-		cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
-		cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
-		writel(~0, ictlr + ICTLR_COP_IER_CLR);
-	}
-	local_irq_restore(flags);
-}
-
-void tegra_irq_resume(void)
-{
-	unsigned long flags;
-	int i;
-
-	local_irq_save(flags);
-	for (i = 0; i < PPI_NR; i++) {
-		void __iomem *ictlr = ictlr_to_virt(i);
-		writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
-		writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-		writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
-		writel(0, ictlr + ICTLR_COP_IEP_CLASS);
-		writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
-		writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
-	}
-	local_irq_restore(flags);
-
-	for (i = INT_PRI_BASE; i < INT_GPIO_BASE; i++) {
-		struct irq_desc *desc = irq_to_desc(i);
-		if (!desc || (desc->status & IRQ_WAKEUP))
-			continue;
-		enable_irq(i);
+	for (i = 0; i < INT_MAIN_NR; i++) {
+		irq = INT_PRI_BASE + i;
+		irq_set_chip_and_handler(irq, &tegra_irq, handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
 	}
 }
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-tegra/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -10,6 +10,9 @@
 	select CPU_V7
 	select ARM_GIC
 	select ARCH_REQUIRE_GPIOLIB
+	select USB_ARCH_HAS_EHCI if USB_SUPPORT
+	select USB_ULPI if USB_SUPPORT
+	select USB_ULPI_VIEWPORT if USB_SUPPORT
 	help
 	  Support for NVIDIA Tegra AP20 and T20 processors, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
@@ -27,6 +30,36 @@
        help
          Support for nVidia Harmony development platform
 
+config MACH_KAEN
+       bool "Kaen board"
+       select MACH_SEABOARD
+       help
+         Support for the Kaen version of Seaboard
+
+config MACH_PAZ00
+       bool "Paz00 board"
+       help
+         Support for the Toshiba AC100/Dynabook AZ netbook
+
+config MACH_SEABOARD
+       bool "Seaboard board"
+       help
+         Support for nVidia Seaboard development platform. It will
+	 also be included for some of the derivative boards that
+	 have large similarities with the seaboard design.
+
+config MACH_TRIMSLICE
+       bool "TrimSlice board"
+       select TEGRA_PCI
+       help
+         Support for CompuLab TrimSlice platform
+
+config MACH_WARIO
+       bool "Wario board"
+       select MACH_SEABOARD
+       help
+         Support for the Wario version of Seaboard
+
 choice
         prompt "Low-level debug console UART"
         default TEGRA_DEBUG_UART_NONE
@@ -58,4 +91,7 @@
 	  Adds system DMA functionality for NVIDIA Tegra SoCs, used by
 	  several Tegra device drivers
 
+config TEGRA_EMC_SCALING_ENABLE
+	bool "Enable scaling the memory frequency"
+
 endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/legacy_irq.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/legacy_irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/legacy_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/legacy_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,17 +18,30 @@
 #include <linux/io.h>
 #include <linux/kernel.h>
 #include <mach/iomap.h>
+#include <mach/irqs.h>
 #include <mach/legacy_irq.h>
 
-#define ICTLR_CPU_IER		0x20
-#define ICTLR_CPU_IER_SET	0x24
-#define ICTLR_CPU_IER_CLR	0x28
-#define ICTLR_CPU_IEP_CLASS	0x2C
+#define INT_SYS_NR	(INT_GPIO_BASE - INT_PRI_BASE)
+#define INT_SYS_SZ	(INT_SEC_BASE - INT_PRI_BASE)
+#define PPI_NR		((INT_SYS_NR+INT_SYS_SZ-1)/INT_SYS_SZ)
+
 #define ICTLR_CPU_IEP_VFIQ	0x08
 #define ICTLR_CPU_IEP_FIR	0x14
 #define ICTLR_CPU_IEP_FIR_SET	0x18
 #define ICTLR_CPU_IEP_FIR_CLR	0x1c
 
+#define ICTLR_CPU_IER		0x20
+#define ICTLR_CPU_IER_SET	0x24
+#define ICTLR_CPU_IER_CLR	0x28
+#define ICTLR_CPU_IEP_CLASS	0x2C
+
+#define ICTLR_COP_IER		0x30
+#define ICTLR_COP_IER_SET	0x34
+#define ICTLR_COP_IER_CLR	0x38
+#define ICTLR_COP_IEP_CLASS	0x3c
+
+#define NUM_ICTLRS 4
+
 static void __iomem *ictlr_reg_base[] = {
 	IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
 	IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
@@ -36,6 +49,9 @@
 	IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
 };
 
+static u32 tegra_legacy_wake_mask[4];
+static u32 tegra_legacy_saved_mask[4];
+
 /* When going into deep sleep, the CPU is powered down, taking the GIC with it
    In order to wake, the wake interrupts need to be enabled in the legacy
    interrupt controller. */
@@ -112,3 +128,88 @@
 	base = ictlr_reg_base[nr];
 	return readl(base + ICTLR_CPU_IEP_CLASS);
 }
+
+int tegra_legacy_irq_set_wake(int irq, int enable)
+{
+	irq -= 32;
+	if (enable)
+		tegra_legacy_wake_mask[irq >> 5] |= 1 << (irq & 31);
+	else
+		tegra_legacy_wake_mask[irq >> 5] &= ~(1 << (irq & 31));
+
+	return 0;
+}
+
+void tegra_legacy_irq_set_lp1_wake_mask(void)
+{
+	void __iomem *base;
+	int i;
+
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		base = ictlr_reg_base[i];
+		tegra_legacy_saved_mask[i] = readl(base + ICTLR_CPU_IER);
+		writel(tegra_legacy_wake_mask[i], base + ICTLR_CPU_IER);
+	}
+}
+
+void tegra_legacy_irq_restore_mask(void)
+{
+	void __iomem *base;
+	int i;
+
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		base = ictlr_reg_base[i];
+		writel(tegra_legacy_saved_mask[i], base + ICTLR_CPU_IER);
+	}
+}
+
+void tegra_init_legacy_irq(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		void __iomem *ictlr = ictlr_reg_base[i];
+		writel(~0, ictlr + ICTLR_CPU_IER_CLR);
+		writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
+	}
+}
+
+#ifdef CONFIG_PM
+static u32 cop_ier[NUM_ICTLRS];
+static u32 cpu_ier[NUM_ICTLRS];
+static u32 cpu_iep[NUM_ICTLRS];
+
+void tegra_irq_suspend(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		void __iomem *ictlr = ictlr_reg_base[i];
+		cpu_ier[i] = readl(ictlr + ICTLR_CPU_IER);
+		cpu_iep[i] = readl(ictlr + ICTLR_CPU_IEP_CLASS);
+		cop_ier[i] = readl(ictlr + ICTLR_COP_IER);
+		writel(~0, ictlr + ICTLR_COP_IER_CLR);
+	}
+	local_irq_restore(flags);
+}
+
+void tegra_irq_resume(void)
+{
+	unsigned long flags;
+	int i;
+
+	local_irq_save(flags);
+	for (i = 0; i < NUM_ICTLRS; i++) {
+		void __iomem *ictlr = ictlr_reg_base[i];
+		writel(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
+		writel(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+		writel(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
+		writel(0, ictlr + ICTLR_COP_IEP_CLASS);
+		writel(~0ul, ictlr + ICTLR_COP_IER_CLR);
+		writel(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
+	}
+	local_irq_restore(flags);
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/localtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/localtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,8 +18,9 @@
 /*
  * Setup the local clock events for a CPU.
  */
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	evt->irq = IRQ_LOCALTIMER;
 	twd_timer_setup(evt);
+	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-tegra/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,21 +1,34 @@
 obj-y                                   += common.o
+obj-y                                   += devices.o
 obj-y                                   += io.o
 obj-y                                   += irq.o legacy_irq.o
 obj-y                                   += clock.o
 obj-y                                   += timer.o
 obj-y                                   += gpio.o
 obj-y                                   += pinmux.o
+obj-y                                   += powergate.o
 obj-y					+= fuse.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clock.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_clocks.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra2_dvfs.o
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= pinmux-t2-tables.o
 obj-$(CONFIG_SMP)                       += platsmp.o localtimer.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 obj-$(CONFIG_TEGRA_SYSTEM_DMA)		+= dma.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
+obj-$(CONFIG_USB_SUPPORT)		+= usb_phy.o
 
 obj-${CONFIG_MACH_HARMONY}              += board-harmony.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pinmux.o
 obj-${CONFIG_MACH_HARMONY}              += board-harmony-pcie.o
+obj-${CONFIG_MACH_HARMONY}              += board-harmony-power.o
+
+obj-${CONFIG_MACH_PAZ00}		+= board-paz00.o
+obj-${CONFIG_MACH_PAZ00}		+= board-paz00-pinmux.o
+
+obj-${CONFIG_MACH_SEABOARD}             += board-seaboard.o
+obj-${CONFIG_MACH_SEABOARD}             += board-seaboard-pinmux.o
+
+obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice.o
+obj-${CONFIG_MACH_TRIMSLICE}            += board-trimslice-pinmux.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/pcie.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/pcie.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/pcie.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/pcie.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 #include <mach/pinmux.h>
 #include <mach/iomap.h>
 #include <mach/clk.h>
+#include <mach/powergate.h>
 
 /* register definitions */
 #define AFI_OFFSET	0x3800
@@ -682,24 +683,41 @@
 	pmc_writel(reg, PMC_SCRATCH42);
 }
 
-static int tegra_pcie_power_on(void)
+static void tegra_pcie_power_off(void)
 {
-	tegra_pcie_xclk_clamp(true);
 	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
-	tegra_pcie_xclk_clamp(false);
+	tegra_periph_reset_assert(tegra_pcie.afi_clk);
+	tegra_periph_reset_assert(tegra_pcie.pex_clk);
 
-	clk_enable(tegra_pcie.afi_clk);
-	clk_enable(tegra_pcie.pex_clk);
-	return clk_enable(tegra_pcie.pll_e);
+	tegra_powergate_power_off(TEGRA_POWERGATE_PCIE);
+	tegra_pcie_xclk_clamp(true);
 }
 
-static void tegra_pcie_power_off(void)
+static int tegra_pcie_power_regate(void)
 {
+	int err;
+
+	tegra_pcie_power_off();
+
+	tegra_pcie_xclk_clamp(true);
+
 	tegra_periph_reset_assert(tegra_pcie.pcie_xclk);
 	tegra_periph_reset_assert(tegra_pcie.afi_clk);
-	tegra_periph_reset_assert(tegra_pcie.pex_clk);
 
-	tegra_pcie_xclk_clamp(true);
+	err = tegra_powergate_sequence_power_up(TEGRA_POWERGATE_PCIE,
+						tegra_pcie.pex_clk);
+	if (err) {
+		pr_err("PCIE: powerup sequence failed: %d\n", err);
+		return err;
+	}
+
+	tegra_periph_reset_deassert(tegra_pcie.afi_clk);
+
+	tegra_pcie_xclk_clamp(false);
+
+	clk_enable(tegra_pcie.afi_clk);
+	clk_enable(tegra_pcie.pex_clk);
+	return clk_enable(tegra_pcie.pll_e);
 }
 
 static int tegra_pcie_clocks_get(void)
@@ -759,7 +777,7 @@
 		return err;
 	}
 
-	err = tegra_pcie_power_on();
+	err = tegra_pcie_power_regate();
 	if (err) {
 		pr_err("PCIE: failed to power up: %d\n", err);
 		goto err_pwr_on;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/pinmux-t2-tables.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 
 #include <mach/iomap.h>
 #include <mach/pinmux.h>
+#include <mach/suspend.h>
 
 #define DRIVE_PINGROUP(pg_name, r)				\
 	[TEGRA_DRIVE_PINGROUP_ ## pg_name] = {			\
@@ -65,6 +66,16 @@
 	DRIVE_PINGROUP(XM2D,		0x8cc),
 	DRIVE_PINGROUP(XM2CLK,		0x8d0),
 	DRIVE_PINGROUP(MEMCOMP,		0x8d4),
+	DRIVE_PINGROUP(SDIO1,		0x8e0),
+	DRIVE_PINGROUP(CRT,		0x8ec),
+	DRIVE_PINGROUP(DDC,		0x8f0),
+	DRIVE_PINGROUP(GMA,		0x8f4),
+	DRIVE_PINGROUP(GMB,		0x8f8),
+	DRIVE_PINGROUP(GMC,		0x8fc),
+	DRIVE_PINGROUP(GMD,		0x900),
+	DRIVE_PINGROUP(GME,		0x904),
+	DRIVE_PINGROUP(OWR,		0x908),
+	DRIVE_PINGROUP(UAD,		0x90c),
 };
 
 #define PINGROUP(pg_name, vdd, f0, f1, f2, f3, f_safe,		\
@@ -216,7 +227,8 @@
 #define PULLUPDOWN_REG_NUM     5
 
 static u32 pinmux_reg[TRISTATE_REG_NUM + PIN_MUX_CTL_REG_NUM +
-		     PULLUPDOWN_REG_NUM];
+		      PULLUPDOWN_REG_NUM +
+		      ARRAY_SIZE(tegra_soc_drive_pingroups)];
 
 static inline unsigned long pg_readl(unsigned long offset)
 {
@@ -233,14 +245,17 @@
 	unsigned int i;
 	u32 *ctx = pinmux_reg;
 
-	for (i = 0; i < TRISTATE_REG_NUM; i++)
-		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
-
 	for (i = 0; i < PIN_MUX_CTL_REG_NUM; i++)
 		*ctx++ = pg_readl(PIN_MUX_CTL_REG_A + i*4);
 
 	for (i = 0; i < PULLUPDOWN_REG_NUM; i++)
 		*ctx++ = pg_readl(PULLUPDOWN_REG_A + i*4);
+
+	for (i = 0; i < TRISTATE_REG_NUM; i++)
+		*ctx++ = pg_readl(TRISTATE_REG_A + i*4);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
+		*ctx++ = pg_readl(tegra_soc_drive_pingroups[i].reg);
 }
 
 void tegra_pinmux_resume(void)
@@ -256,5 +271,8 @@
 
 	for (i = 0; i < TRISTATE_REG_NUM; i++)
 		pg_writel(*ctx++, TRISTATE_REG_A + i*4);
+
+	for (i = 0; i < ARRAY_SIZE(tegra_soc_drive_pingroups); i++)
+		pg_writel(*ctx++, tegra_soc_drive_pingroups[i].reg);
 }
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/powergate.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/powergate.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/powergate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/powergate.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,212 @@
+/*
+ * drivers/powergate/tegra-powergate.c
+ *
+ * Copyright (c) 2010 Google, Inc
+ *
+ * Author:
+ *	Colin Cross <ccross@google.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/clk.h>
+#include <linux/debugfs.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/seq_file.h>
+#include <linux/spinlock.h>
+
+#include <mach/clk.h>
+#include <mach/iomap.h>
+#include <mach/powergate.h>
+
+#define PWRGATE_TOGGLE		0x30
+#define  PWRGATE_TOGGLE_START	(1 << 8)
+
+#define REMOVE_CLAMPING		0x34
+
+#define PWRGATE_STATUS		0x38
+
+static DEFINE_SPINLOCK(tegra_powergate_lock);
+
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+
+static u32 pmc_read(unsigned long reg)
+{
+	return readl(pmc + reg);
+}
+
+static void pmc_write(u32 val, unsigned long reg)
+{
+	writel(val, pmc + reg);
+}
+
+static int tegra_powergate_set(int id, bool new_state)
+{
+	bool status;
+	unsigned long flags;
+
+	spin_lock_irqsave(&tegra_powergate_lock, flags);
+
+	status = pmc_read(PWRGATE_STATUS) & (1 << id);
+
+	if (status == new_state) {
+		spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+		return -EINVAL;
+	}
+
+	pmc_write(PWRGATE_TOGGLE_START | id, PWRGATE_TOGGLE);
+
+	spin_unlock_irqrestore(&tegra_powergate_lock, flags);
+
+	return 0;
+}
+
+int tegra_powergate_power_on(int id)
+{
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	return tegra_powergate_set(id, true);
+}
+
+int tegra_powergate_power_off(int id)
+{
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	return tegra_powergate_set(id, false);
+}
+
+bool tegra_powergate_is_powered(int id)
+{
+	u32 status;
+
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	status = pmc_read(PWRGATE_STATUS) & (1 << id);
+	return !!status;
+}
+
+int tegra_powergate_remove_clamping(int id)
+{
+	u32 mask;
+
+	if (id < 0 || id >= TEGRA_NUM_POWERGATE)
+		return -EINVAL;
+
+	/*
+	 * Tegra 2 has a bug where PCIE and VDE clamping masks are
+	 * swapped relatively to the partition ids
+	 */
+	if (id ==  TEGRA_POWERGATE_VDEC)
+		mask = (1 << TEGRA_POWERGATE_PCIE);
+	else if	(id == TEGRA_POWERGATE_PCIE)
+		mask = (1 << TEGRA_POWERGATE_VDEC);
+	else
+		mask = (1 << id);
+
+	pmc_write(mask, REMOVE_CLAMPING);
+
+	return 0;
+}
+
+/* Must be called with clk disabled, and returns with clk enabled */
+int tegra_powergate_sequence_power_up(int id, struct clk *clk)
+{
+	int ret;
+
+	tegra_periph_reset_assert(clk);
+
+	ret = tegra_powergate_power_on(id);
+	if (ret)
+		goto err_power;
+
+	ret = clk_enable(clk);
+	if (ret)
+		goto err_clk;
+
+	udelay(10);
+
+	ret = tegra_powergate_remove_clamping(id);
+	if (ret)
+		goto err_clamp;
+
+	udelay(10);
+	tegra_periph_reset_deassert(clk);
+
+	return 0;
+
+err_clamp:
+	clk_disable(clk);
+err_clk:
+	tegra_powergate_power_off(id);
+err_power:
+	return ret;
+}
+
+#ifdef CONFIG_DEBUG_FS
+
+static const char * const powergate_name[] = {
+	[TEGRA_POWERGATE_CPU]	= "cpu",
+	[TEGRA_POWERGATE_3D]	= "3d",
+	[TEGRA_POWERGATE_VENC]	= "venc",
+	[TEGRA_POWERGATE_VDEC]	= "vdec",
+	[TEGRA_POWERGATE_PCIE]	= "pcie",
+	[TEGRA_POWERGATE_L2]	= "l2",
+	[TEGRA_POWERGATE_MPE]	= "mpe",
+};
+
+static int powergate_show(struct seq_file *s, void *data)
+{
+	int i;
+
+	seq_printf(s, " powergate powered\n");
+	seq_printf(s, "------------------\n");
+
+	for (i = 0; i < TEGRA_NUM_POWERGATE; i++)
+		seq_printf(s, " %9s %7s\n", powergate_name[i],
+			tegra_powergate_is_powered(i) ? "yes" : "no");
+	return 0;
+}
+
+static int powergate_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, powergate_show, inode->i_private);
+}
+
+static const struct file_operations powergate_fops = {
+	.open		= powergate_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init powergate_debugfs_init(void)
+{
+	struct dentry *d;
+	int err = -ENOMEM;
+
+	d = debugfs_create_file("powergate", S_IRUGO, NULL, NULL,
+		&powergate_fops);
+	if (!d)
+		return -ENOMEM;
+
+	return err;
+}
+
+late_initcall(powergate_debugfs_init);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_clocks.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_clocks.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_clocks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_clocks.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,14 +23,15 @@
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/io.h>
-#include <linux/hrtimer.h>
 #include <linux/clkdev.h>
+#include <linux/clk.h>
 
 #include <mach/iomap.h>
+#include <mach/suspend.h>
 
 #include "clock.h"
 #include "fuse.h"
-#include "tegra2_dvfs.h"
+#include "tegra2_emc.h"
 
 #define RST_DEVICES			0x004
 #define RST_DEVICES_SET			0x300
@@ -51,7 +52,7 @@
 #define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
 #define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
 #define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
-#define OSC_CTRL_MASK			0x3f2
+#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
 
 #define OSC_FREQ_DET			0x58
 #define OSC_FREQ_DET_TRIG		(1<<31)
@@ -73,12 +74,15 @@
 #define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
 #define PERIPH_CLK_SOURCE_DIV_SHIFT	0
 
+#define SDMMC_CLK_INT_FB_SEL		(1 << 23)
+#define SDMMC_CLK_INT_FB_DLY_SHIFT	16
+#define SDMMC_CLK_INT_FB_DLY_MASK	(0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
+
 #define PLL_BASE			0x0
 #define PLL_BASE_BYPASS			(1<<31)
 #define PLL_BASE_ENABLE			(1<<30)
 #define PLL_BASE_REF_ENABLE		(1<<29)
 #define PLL_BASE_OVERRIDE		(1<<28)
-#define PLL_BASE_LOCK			(1<<27)
 #define PLL_BASE_DIVP_MASK		(0x7<<20)
 #define PLL_BASE_DIVP_SHIFT		20
 #define PLL_BASE_DIVN_MASK		(0x3FF<<8)
@@ -93,7 +97,6 @@
 #define PLL_OUT_RESET_DISABLE		(1<<0)
 
 #define PLL_MISC(c)			(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
-#define PLL_MISC_LOCK_ENABLE(c)		(((c)->flags & PLLU) ? (1<<22) : (1<<18))
 
 #define PLL_MISC_DCCON_SHIFT		20
 #define PLL_MISC_CPCON_SHIFT		8
@@ -111,9 +114,9 @@
 
 #define PLLE_MISC_READY			(1 << 15)
 
-#define PERIPH_CLK_TO_ENB_REG(c)	((c->clk_num / 32) * 4)
-#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->clk_num / 32) * 8)
-#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->clk_num % 32))
+#define PERIPH_CLK_TO_ENB_REG(c)	((c->u.periph.clk_num / 32) * 4)
+#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->u.periph.clk_num / 32) * 8)
+#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->u.periph.clk_num % 32))
 
 #define SUPER_CLK_MUX			0x00
 #define SUPER_STATE_SHIFT		28
@@ -134,12 +137,42 @@
 #define BUS_CLK_DISABLE			(1<<3)
 #define BUS_CLK_DIV_MASK		0x3
 
+#define PMC_CTRL			0x0
+ #define PMC_CTRL_BLINK_ENB		(1 << 7)
+
+#define PMC_DPD_PADS_ORIDE		0x1c
+ #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
+
+#define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
+#define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
+#define PMC_BLINK_TIMER_ENB		(1 << 15)
+#define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
+#define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
+
 static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
+static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
+
+/*
+ * Some clocks share a register with other clocks.  Any clock op that
+ * non-atomically modifies a register used by another clock must lock
+ * clock_register_lock first.
+ */
+static DEFINE_SPINLOCK(clock_register_lock);
+
+/*
+ * Some peripheral clocks share an enable bit, so refcount the enable bits
+ * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
+ */
+static int tegra_periph_clk_enable_refcount[3 * 32];
 
 #define clk_writel(value, reg) \
 	__raw_writel(value, (u32)reg_clk_base + (reg))
 #define clk_readl(reg) \
 	__raw_readl((u32)reg_clk_base + (reg))
+#define pmc_writel(value, reg) \
+	__raw_writel(value, (u32)reg_pmc_base + (reg))
+#define pmc_readl(reg) \
+	__raw_readl((u32)reg_pmc_base + (reg))
 
 unsigned long clk_measure_input_freq(void)
 {
@@ -245,6 +278,18 @@
 	.disable	= tegra2_clk_m_disable,
 };
 
+void tegra2_periph_reset_assert(struct clk *c)
+{
+	BUG_ON(!c->ops->reset);
+	c->ops->reset(c, true);
+}
+
+void tegra2_periph_reset_deassert(struct clk *c)
+{
+	BUG_ON(!c->ops->reset);
+	c->ops->reset(c, false);
+}
+
 /* super clock functions */
 /* "super clocks" on tegra have two-stage muxes and a clock skipping
  * super divider.  We will ignore the clock skipping divider, since we
@@ -303,12 +348,12 @@
 			val |= sel->value << shift;
 
 			if (c->refcnt)
-				clk_enable_locked(p);
+				clk_enable(p);
 
 			clk_writel(val, c->reg);
 
 			if (c->refcnt && c->parent)
-				clk_disable_locked(c->parent);
+				clk_disable(c->parent);
 
 			clk_reparent(c, p);
 			return 0;
@@ -317,11 +362,24 @@
 	return -EINVAL;
 }
 
+/*
+ * Super clocks have "clock skippers" instead of dividers.  Dividing using
+ * a clock skipper does not allow the voltage to be scaled down, so instead
+ * adjust the rate of the parent clock.  This requires that the parent of a
+ * super clock have no other children, otherwise the rate will change
+ * underneath the other children.
+ */
+static int tegra2_super_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	return clk_set_rate(c->parent, rate);
+}
+
 static struct clk_ops tegra_super_ops = {
 	.init			= tegra2_super_clk_init,
 	.enable			= tegra2_super_clk_enable,
 	.disable		= tegra2_super_clk_disable,
 	.set_parent		= tegra2_super_clk_set_parent,
+	.set_rate		= tegra2_super_clk_set_rate,
 };
 
 /* virtual cpu clock functions */
@@ -351,25 +409,36 @@
 static int tegra2_cpu_clk_set_rate(struct clk *c, unsigned long rate)
 {
 	int ret;
-	ret = clk_set_parent_locked(c->parent, c->backup);
+	/*
+	 * Take an extra reference to the main pll so it doesn't turn
+	 * off when we move the cpu off of it
+	 */
+	clk_enable(c->u.cpu.main);
+
+	ret = clk_set_parent(c->parent, c->u.cpu.backup);
 	if (ret) {
-		pr_err("Failed to switch cpu to clock %s\n", c->backup->name);
-		return ret;
+		pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.backup->name);
+		goto out;
 	}
 
-	ret = clk_set_rate_locked(c->main, rate);
+	if (rate == clk_get_rate(c->u.cpu.backup))
+		goto out;
+
+	ret = clk_set_rate(c->u.cpu.main, rate);
 	if (ret) {
 		pr_err("Failed to change cpu pll to %lu\n", rate);
-		return ret;
+		goto out;
 	}
 
-	ret = clk_set_parent_locked(c->parent, c->main);
+	ret = clk_set_parent(c->parent, c->u.cpu.main);
 	if (ret) {
-		pr_err("Failed to switch cpu to clock %s\n", c->main->name);
-		return ret;
+		pr_err("Failed to switch cpu to clock %s\n", c->u.cpu.main->name);
+		goto out;
 	}
 
-	return 0;
+out:
+	clk_disable(c->u.cpu.main);
+	return ret;
 }
 
 static struct clk_ops tegra_cpu_ops = {
@@ -379,6 +448,20 @@
 	.set_rate = tegra2_cpu_clk_set_rate,
 };
 
+/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
+ * reset the COP block (i.e. AVP) */
+static void tegra2_cop_clk_reset(struct clk *c, bool assert)
+{
+	unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+	pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
+	clk_writel(1 << 1, reg);
+}
+
+static struct clk_ops tegra_cop_ops = {
+	.reset    = tegra2_cop_clk_reset,
+};
+
 /* bus clock functions */
 static void tegra2_bus_clk_init(struct clk *c)
 {
@@ -390,24 +473,45 @@
 
 static int tegra2_bus_clk_enable(struct clk *c)
 {
-	u32 val = clk_readl(c->reg);
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
 	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
 	clk_writel(val, c->reg);
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
 	return 0;
 }
 
 static void tegra2_bus_clk_disable(struct clk *c)
 {
-	u32 val = clk_readl(c->reg);
+	u32 val;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
 	val |= BUS_CLK_DISABLE << c->reg_shift;
 	clk_writel(val, c->reg);
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
 }
 
 static int tegra2_bus_clk_set_rate(struct clk *c, unsigned long rate)
 {
-	u32 val = clk_readl(c->reg);
-	unsigned long parent_rate = c->parent->rate;
+	u32 val;
+	unsigned long parent_rate = clk_get_rate(c->parent);
+	unsigned long flags;
+	int ret = -EINVAL;
 	int i;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	val = clk_readl(c->reg);
 	for (i = 1; i <= 4; i++) {
 		if (rate == parent_rate / i) {
 			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
@@ -415,10 +519,14 @@
 			clk_writel(val, c->reg);
 			c->div = i;
 			c->mul = 1;
-			return 0;
+			ret = 0;
+			break;
 		}
 	}
-	return -EINVAL;
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
+	return ret;
 }
 
 static struct clk_ops tegra_bus_ops = {
@@ -428,20 +536,92 @@
 	.set_rate		= tegra2_bus_clk_set_rate,
 };
 
-/* PLL Functions */
-static int tegra2_pll_clk_wait_for_lock(struct clk *c)
+/* Blink output functions */
+
+static void tegra2_blink_clk_init(struct clk *c)
 {
-	ktime_t before;
+	u32 val;
 
-	before = ktime_get();
+	val = pmc_readl(PMC_CTRL);
+	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
+	c->mul = 1;
+	val = pmc_readl(c->reg);
 
-	while (!(clk_readl(c->reg + PLL_BASE) & PLL_BASE_LOCK)) {
-		if (ktime_us_delta(ktime_get(), before) > 5000) {
-			pr_err("Timed out waiting for lock bit on pll %s",
-				c->name);
-			return -1;
-		}
+	if (val & PMC_BLINK_TIMER_ENB) {
+		unsigned int on_off;
+
+		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
+			PMC_BLINK_TIMER_DATA_ON_MASK;
+		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off += val;
+		/* each tick in the blink timer is 4 32KHz clocks */
+		c->div = on_off * 4;
+	} else {
+		c->div = 1;
 	}
+}
+
+static int tegra2_blink_clk_enable(struct clk *c)
+{
+	u32 val;
+
+	val = pmc_readl(PMC_DPD_PADS_ORIDE);
+	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+
+	val = pmc_readl(PMC_CTRL);
+	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+	return 0;
+}
+
+static void tegra2_blink_clk_disable(struct clk *c)
+{
+	u32 val;
+
+	val = pmc_readl(PMC_CTRL);
+	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
+
+	val = pmc_readl(PMC_DPD_PADS_ORIDE);
+	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
+}
+
+static int tegra2_blink_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long parent_rate = clk_get_rate(c->parent);
+	if (rate >= parent_rate) {
+		c->div = 1;
+		pmc_writel(0, c->reg);
+	} else {
+		unsigned int on_off;
+		u32 val;
+
+		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
+		c->div = on_off * 8;
+
+		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
+			PMC_BLINK_TIMER_DATA_ON_SHIFT;
+		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
+		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
+		val |= on_off;
+		val |= PMC_BLINK_TIMER_ENB;
+		pmc_writel(val, c->reg);
+	}
+
+	return 0;
+}
+
+static struct clk_ops tegra_blink_clk_ops = {
+	.init			= &tegra2_blink_clk_init,
+	.enable			= &tegra2_blink_clk_enable,
+	.disable		= &tegra2_blink_clk_disable,
+	.set_rate		= &tegra2_blink_clk_set_rate,
+};
+
+/* PLL Functions */
+static int tegra2_pll_clk_wait_for_lock(struct clk *c)
+{
+	udelay(c->u.pll.lock_delay);
 
 	return 0;
 }
@@ -479,10 +659,6 @@
 	val |= PLL_BASE_ENABLE;
 	clk_writel(val, c->reg + PLL_BASE);
 
-	val = clk_readl(c->reg + PLL_MISC(c));
-	val |= PLL_MISC_LOCK_ENABLE(c);
-	clk_writel(val, c->reg + PLL_MISC(c));
-
 	tegra2_pll_clk_wait_for_lock(c);
 
 	return 0;
@@ -502,13 +678,12 @@
 {
 	u32 val;
 	unsigned long input_rate;
-	const struct clk_pll_table *sel;
+	const struct clk_pll_freq_table *sel;
 
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
-	BUG_ON(c->refcnt != 0);
 
-	input_rate = c->parent->rate;
-	for (sel = c->pll_table; sel->input_rate != 0; sel++) {
+	input_rate = clk_get_rate(c->parent);
+	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
 		if (sel->input_rate == input_rate && sel->output_rate == rate) {
 			c->mul = sel->n;
 			c->div = sel->m * sel->p;
@@ -620,9 +795,11 @@
 {
 	u32 val;
 	u32 new_val;
+	unsigned long flags;
 
 	pr_debug("%s: %s\n", __func__, c->name);
 	if (c->flags & DIV_U71) {
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		new_val = val >> c->reg_shift;
 		new_val &= 0xFFFF;
@@ -632,12 +809,15 @@
 		val &= ~(0xFFFF << c->reg_shift);
 		val |= new_val << c->reg_shift;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 		return 0;
 	} else if (c->flags & DIV_2) {
 		BUG_ON(!(c->flags & PLLD));
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		val &= ~PLLD_MISC_DIV_RST;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 		return 0;
 	}
 	return -EINVAL;
@@ -647,9 +827,11 @@
 {
 	u32 val;
 	u32 new_val;
+	unsigned long flags;
 
 	pr_debug("%s: %s\n", __func__, c->name);
 	if (c->flags & DIV_U71) {
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		new_val = val >> c->reg_shift;
 		new_val &= 0xFFFF;
@@ -659,11 +841,14 @@
 		val &= ~(0xFFFF << c->reg_shift);
 		val |= new_val << c->reg_shift;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 	} else if (c->flags & DIV_2) {
 		BUG_ON(!(c->flags & PLLD));
+		spin_lock_irqsave(&clock_register_lock, flags);
 		val = clk_readl(c->reg);
 		val |= PLLD_MISC_DIV_RST;
 		clk_writel(val, c->reg);
+		spin_unlock_irqrestore(&clock_register_lock, flags);
 	}
 }
 
@@ -672,10 +857,14 @@
 	u32 val;
 	u32 new_val;
 	int divider_u71;
+	unsigned long parent_rate = clk_get_rate(c->parent);
+	unsigned long flags;
+
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(c->parent->rate, rate);
+		divider_u71 = clk_div71_get_divider(parent_rate, rate);
 		if (divider_u71 >= 0) {
+			spin_lock_irqsave(&clock_register_lock, flags);
 			val = clk_readl(c->reg);
 			new_val = val >> c->reg_shift;
 			new_val &= 0xFFFF;
@@ -689,10 +878,11 @@
 			clk_writel(val, c->reg);
 			c->div = divider_u71 + 2;
 			c->mul = 2;
+			spin_unlock_irqrestore(&clock_register_lock, flags);
 			return 0;
 		}
 	} else if (c->flags & DIV_2) {
-		if (c->parent->rate == rate * 2)
+		if (parent_rate == rate * 2)
 			return 0;
 	}
 	return -EINVAL;
@@ -701,15 +891,16 @@
 static long tegra2_pll_div_clk_round_rate(struct clk *c, unsigned long rate)
 {
 	int divider;
+	unsigned long parent_rate = clk_get_rate(c->parent);
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 
 	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(c->parent->rate, rate);
+		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
-		return c->parent->rate * 2 / (divider + 2);
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 	} else if (c->flags & DIV_2) {
-		return c->parent->rate / 2;
+		return DIV_ROUND_UP(parent_rate, 2);
 	}
 	return -EINVAL;
 }
@@ -755,9 +946,14 @@
 	}
 
 	c->state = ON;
+
+	if (!c->u.periph.clk_num)
+		return;
+
 	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
 			PERIPH_CLK_TO_ENB_BIT(c)))
 		c->state = OFF;
+
 	if (!(c->flags & PERIPH_NO_RESET))
 		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
 				PERIPH_CLK_TO_ENB_BIT(c))
@@ -767,8 +963,20 @@
 static int tegra2_periph_clk_enable(struct clk *c)
 {
 	u32 val;
+	unsigned long flags;
+	int refcount;
 	pr_debug("%s on clock %s\n", __func__, c->name);
 
+	if (!c->u.periph.clk_num)
+		return 0;
+
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	refcount = tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
+
+	if (refcount > 1)
+		goto out;
+
 	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
 		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
 	if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
@@ -781,34 +989,48 @@
 		val |= 0x3 << 24;
 		clk_writel(val, c->reg);
 	}
+
+out:
+	spin_unlock_irqrestore(&clock_register_lock, flags);
+
 	return 0;
 }
 
 static void tegra2_periph_clk_disable(struct clk *c)
 {
+	unsigned long flags;
+
 	pr_debug("%s on clock %s\n", __func__, c->name);
 
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-}
+	if (!c->u.periph.clk_num)
+		return;
 
-void tegra2_periph_reset_deassert(struct clk *c)
-{
-	pr_debug("%s on clock %s\n", __func__, c->name);
-	if (!(c->flags & PERIPH_NO_RESET))
+	spin_lock_irqsave(&clock_register_lock, flags);
+
+	if (c->refcnt)
+		tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
+
+	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] == 0)
 		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+			CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+
+	spin_unlock_irqrestore(&clock_register_lock, flags);
 }
 
-void tegra2_periph_reset_assert(struct clk *c)
+static void tegra2_periph_clk_reset(struct clk *c, bool assert)
 {
-	pr_debug("%s on clock %s\n", __func__, c->name);
+	unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
+
+	pr_debug("%s %s on clock %s\n", __func__,
+		 assert ? "assert" : "deassert", c->name);
+
+	BUG_ON(!c->u.periph.clk_num);
+
 	if (!(c->flags & PERIPH_NO_RESET))
 		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			RST_DEVICES_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+			   base + PERIPH_CLK_TO_ENB_SET_REG(c));
 }
 
-
 static int tegra2_periph_clk_set_parent(struct clk *c, struct clk *p)
 {
 	u32 val;
@@ -821,12 +1043,12 @@
 			val |= (sel->value) << PERIPH_CLK_SOURCE_SHIFT;
 
 			if (c->refcnt)
-				clk_enable_locked(p);
+				clk_enable(p);
 
 			clk_writel(val, c->reg);
 
 			if (c->refcnt && c->parent)
-				clk_disable_locked(c->parent);
+				clk_disable(c->parent);
 
 			clk_reparent(c, p);
 			return 0;
@@ -840,9 +1062,10 @@
 {
 	u32 val;
 	int divider;
-	pr_debug("%s: %lu\n", __func__, rate);
+	unsigned long parent_rate = clk_get_rate(c->parent);
+
 	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(c->parent->rate, rate);
+		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider >= 0) {
 			val = clk_readl(c->reg);
 			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
@@ -853,7 +1076,7 @@
 			return 0;
 		}
 	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(c->parent->rate, rate);
+		divider = clk_div16_get_divider(parent_rate, rate);
 		if (divider >= 0) {
 			val = clk_readl(c->reg);
 			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
@@ -863,7 +1086,7 @@
 			c->mul = 1;
 			return 0;
 		}
-	} else if (c->parent->rate <= rate) {
+	} else if (parent_rate <= rate) {
 		c->div = 1;
 		c->mul = 1;
 		return 0;
@@ -875,19 +1098,20 @@
 	unsigned long rate)
 {
 	int divider;
+	unsigned long parent_rate = clk_get_rate(c->parent);
 	pr_debug("%s: %s %lu\n", __func__, c->name, rate);
 
 	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(c->parent->rate, rate);
+		divider = clk_div71_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
 
-		return c->parent->rate * 2 / (divider + 2);
+		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
 	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(c->parent->rate, rate);
+		divider = clk_div16_get_divider(parent_rate, rate);
 		if (divider < 0)
 			return divider;
-		return c->parent->rate / (divider + 1);
+		return DIV_ROUND_UP(parent_rate, divider + 1);
 	}
 	return -EINVAL;
 }
@@ -899,6 +1123,71 @@
 	.set_parent		= &tegra2_periph_clk_set_parent,
 	.set_rate		= &tegra2_periph_clk_set_rate,
 	.round_rate		= &tegra2_periph_clk_round_rate,
+	.reset			= &tegra2_periph_clk_reset,
+};
+
+/* The SDMMC controllers have extra bits in the clock source register that
+ * adjust the delay between the clock and data to compenstate for delays
+ * on the PCB. */
+void tegra2_sdmmc_tap_delay(struct clk *c, int delay)
+{
+	u32 reg;
+
+	delay = clamp(delay, 0, 15);
+	reg = clk_readl(c->reg);
+	reg &= ~SDMMC_CLK_INT_FB_DLY_MASK;
+	reg |= SDMMC_CLK_INT_FB_SEL;
+	reg |= delay << SDMMC_CLK_INT_FB_DLY_SHIFT;
+	clk_writel(reg, c->reg);
+}
+
+/* External memory controller clock ops */
+static void tegra2_emc_clk_init(struct clk *c)
+{
+	tegra2_periph_clk_init(c);
+	c->max_rate = clk_get_rate_locked(c);
+}
+
+static long tegra2_emc_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	long new_rate = rate;
+
+	new_rate = tegra_emc_round_rate(new_rate);
+	if (new_rate < 0)
+		return c->max_rate;
+
+	BUG_ON(new_rate != tegra2_periph_clk_round_rate(c, new_rate));
+
+	return new_rate;
+}
+
+static int tegra2_emc_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret;
+	/*
+	 * The Tegra2 memory controller has an interlock with the clock
+	 * block that allows memory shadowed registers to be updated,
+	 * and then transfer them to the main registers at the same
+	 * time as the clock update without glitches.
+	 */
+	ret = tegra_emc_set_rate(rate);
+	if (ret < 0)
+		return ret;
+
+	ret = tegra2_periph_clk_set_rate(c, rate);
+	udelay(1);
+
+	return ret;
+}
+
+static struct clk_ops tegra_emc_clk_ops = {
+	.init			= &tegra2_emc_clk_init,
+	.enable			= &tegra2_periph_clk_enable,
+	.disable		= &tegra2_periph_clk_disable,
+	.set_parent		= &tegra2_periph_clk_set_parent,
+	.set_rate		= &tegra2_emc_clk_set_rate,
+	.round_rate		= &tegra2_emc_clk_round_rate,
+	.reset			= &tegra2_periph_clk_reset,
 };
 
 /* Clock doubler ops */
@@ -907,6 +1196,10 @@
 	c->mul = 2;
 	c->div = 1;
 	c->state = ON;
+
+	if (!c->u.periph.clk_num)
+		return;
+
 	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
 			PERIPH_CLK_TO_ENB_BIT(c)))
 		c->state = OFF;
@@ -914,7 +1207,7 @@
 
 static int tegra2_clk_double_set_rate(struct clk *c, unsigned long rate)
 {
-	if (rate != 2 * c->parent->rate)
+	if (rate != 2 * clk_get_rate(c->parent))
 		return -EINVAL;
 	c->mul = 2;
 	c->div = 1;
@@ -928,6 +1221,7 @@
 	.set_rate		= &tegra2_clk_double_set_rate,
 };
 
+/* Audio sync clock ops */
 static void tegra2_audio_sync_clk_init(struct clk *c)
 {
 	int source;
@@ -964,12 +1258,12 @@
 			val |= sel->value;
 
 			if (c->refcnt)
-				clk_enable_locked(p);
+				clk_enable(p);
 
 			clk_writel(val, c->reg);
 
 			if (c->refcnt && c->parent)
-				clk_disable_locked(c->parent);
+				clk_disable(c->parent);
 
 			clk_reparent(c, p);
 			return 0;
@@ -979,33 +1273,154 @@
 	return -EINVAL;
 }
 
-static int tegra2_audio_sync_clk_set_rate(struct clk *c, unsigned long rate)
-{
-	unsigned long parent_rate;
-	if (!c->parent) {
-		pr_err("%s: clock has no parent\n", __func__);
-		return -EINVAL;
-	}
-	parent_rate = c->parent->rate;
-	if (rate != parent_rate) {
-		pr_err("%s: %s/%ld differs from parent %s/%ld\n",
-			__func__,
-			c->name, rate,
-			c->parent->name, parent_rate);
-		return -EINVAL;
-	}
-	c->rate = parent_rate;
-	return 0;
-}
-
 static struct clk_ops tegra_audio_sync_clk_ops = {
 	.init       = tegra2_audio_sync_clk_init,
 	.enable     = tegra2_audio_sync_clk_enable,
 	.disable    = tegra2_audio_sync_clk_disable,
-	.set_rate   = tegra2_audio_sync_clk_set_rate,
 	.set_parent = tegra2_audio_sync_clk_set_parent,
 };
 
+/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
+
+static void tegra2_cdev_clk_init(struct clk *c)
+{
+	/* We could un-tristate the cdev1 or cdev2 pingroup here; this is
+	 * currently done in the pinmux code. */
+	c->state = ON;
+
+	BUG_ON(!c->u.periph.clk_num);
+
+	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
+			PERIPH_CLK_TO_ENB_BIT(c)))
+		c->state = OFF;
+}
+
+static int tegra2_cdev_clk_enable(struct clk *c)
+{
+	BUG_ON(!c->u.periph.clk_num);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
+	return 0;
+}
+
+static void tegra2_cdev_clk_disable(struct clk *c)
+{
+	BUG_ON(!c->u.periph.clk_num);
+
+	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
+		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
+}
+
+static struct clk_ops tegra_cdev_clk_ops = {
+	.init			= &tegra2_cdev_clk_init,
+	.enable			= &tegra2_cdev_clk_enable,
+	.disable		= &tegra2_cdev_clk_disable,
+};
+
+/* shared bus ops */
+/*
+ * Some clocks may have multiple downstream users that need to request a
+ * higher clock rate.  Shared bus clocks provide a unique shared_bus_user
+ * clock to each user.  The frequency of the bus is set to the highest
+ * enabled shared_bus_user clock, with a minimum value set by the
+ * shared bus.
+ */
+static int tegra_clk_shared_bus_update(struct clk *bus)
+{
+	struct clk *c;
+	unsigned long rate = bus->min_rate;
+
+	list_for_each_entry(c, &bus->shared_bus_list, u.shared_bus_user.node)
+		if (c->u.shared_bus_user.enabled)
+			rate = max(c->u.shared_bus_user.rate, rate);
+
+	if (rate == clk_get_rate_locked(bus))
+		return 0;
+
+	return clk_set_rate_locked(bus, rate);
+};
+
+static void tegra_clk_shared_bus_init(struct clk *c)
+{
+	unsigned long flags;
+
+	c->max_rate = c->parent->max_rate;
+	c->u.shared_bus_user.rate = c->parent->max_rate;
+	c->state = OFF;
+	c->set = true;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	list_add_tail(&c->u.shared_bus_user.node,
+		&c->parent->shared_bus_list);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+}
+
+static int tegra_clk_shared_bus_set_rate(struct clk *c, unsigned long rate)
+{
+	unsigned long flags;
+	int ret;
+	long new_rate = rate;
+
+	new_rate = clk_round_rate(c->parent, new_rate);
+	if (new_rate < 0)
+		return new_rate;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	c->u.shared_bus_user.rate = new_rate;
+	ret = tegra_clk_shared_bus_update(c->parent);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+
+	return ret;
+}
+
+static long tegra_clk_shared_bus_round_rate(struct clk *c, unsigned long rate)
+{
+	return clk_round_rate(c->parent, rate);
+}
+
+static int tegra_clk_shared_bus_enable(struct clk *c)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	c->u.shared_bus_user.enabled = true;
+	ret = tegra_clk_shared_bus_update(c->parent);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+
+	return ret;
+}
+
+static void tegra_clk_shared_bus_disable(struct clk *c)
+{
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&c->parent->spinlock, flags);
+
+	c->u.shared_bus_user.enabled = false;
+	ret = tegra_clk_shared_bus_update(c->parent);
+	WARN_ON_ONCE(ret);
+
+	spin_unlock_irqrestore(&c->parent->spinlock, flags);
+}
+
+static struct clk_ops tegra_clk_shared_bus_ops = {
+	.init = tegra_clk_shared_bus_init,
+	.enable = tegra_clk_shared_bus_enable,
+	.disable = tegra_clk_shared_bus_disable,
+	.set_rate = tegra_clk_shared_bus_set_rate,
+	.round_rate = tegra_clk_shared_bus_round_rate,
+};
+
+
 /* Clock definitions */
 static struct clk tegra_clk_32k = {
 	.name = "clk_32k",
@@ -1014,7 +1429,7 @@
 	.max_rate = 32768,
 };
 
-static struct clk_pll_table tegra_pll_s_table[] = {
+static struct clk_pll_freq_table tegra_pll_s_freq_table[] = {
 	{32768, 12000000, 366, 1, 1, 0},
 	{32768, 13000000, 397, 1, 1, 0},
 	{32768, 19200000, 586, 1, 1, 0},
@@ -1026,16 +1441,19 @@
 	.name      = "pll_s",
 	.flags     = PLL_ALT_MISC_REG,
 	.ops       = &tegra_pll_ops,
-	.reg       = 0xf0,
-	.input_min = 32768,
-	.input_max = 32768,
 	.parent    = &tegra_clk_32k,
-	.cf_min    = 0, /* FIXME */
-	.cf_max    = 0, /* FIXME */
-	.vco_min   = 12000000,
-	.vco_max   = 26000000,
-	.pll_table = tegra_pll_s_table,
 	.max_rate  = 26000000,
+	.reg       = 0xf0,
+	.u.pll = {
+		.input_min = 32768,
+		.input_max = 32768,
+		.cf_min    = 0, /* FIXME */
+		.cf_max    = 0, /* FIXME */
+		.vco_min   = 12000000,
+		.vco_max   = 26000000,
+		.freq_table = tegra_pll_s_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk_mux_sel tegra_clk_m_sel[] = {
@@ -1043,18 +1461,18 @@
 	{ .input = &tegra_pll_s,  .value = 1},
 	{ 0, 0},
 };
+
 static struct clk tegra_clk_m = {
 	.name      = "clk_m",
 	.flags     = ENABLE_ON_INIT,
 	.ops       = &tegra_clk_m_ops,
 	.inputs    = tegra_clk_m_sel,
 	.reg       = 0x1fc,
-	.reg_mask  = (1<<28),
 	.reg_shift = 28,
 	.max_rate  = 26000000,
 };
 
-static struct clk_pll_table tegra_pll_c_table[] = {
+static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -1063,15 +1481,18 @@
 	.flags	   = PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0x80,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1400000000,
-	.pll_table = tegra_pll_c_table,
 	.max_rate  = 600000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1400000000,
+		.freq_table = tegra_pll_c_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_c_out1 = {
@@ -1084,7 +1505,7 @@
 	.max_rate  = 600000000,
 };
 
-static struct clk_pll_table tegra_pll_m_table[] = {
+static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
 	{ 12000000, 666000000, 666, 12, 1, 8},
 	{ 13000000, 666000000, 666, 13, 1, 8},
 	{ 19200000, 666000000, 555, 16, 1, 8},
@@ -1101,15 +1522,18 @@
 	.flags     = PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0x90,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1200000000,
-	.pll_table = tegra_pll_m_table,
 	.max_rate  = 800000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1200000000,
+		.freq_table = tegra_pll_m_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_m_out1 = {
@@ -1122,7 +1546,7 @@
 	.max_rate  = 600000000,
 };
 
-static struct clk_pll_table tegra_pll_p_table[] = {
+static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
 	{ 12000000, 216000000, 432, 12, 2, 8},
 	{ 13000000, 216000000, 432, 13, 2, 8},
 	{ 19200000, 216000000, 90,   4, 2, 1},
@@ -1139,15 +1563,18 @@
 	.flags     = ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xa0,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1400000000,
-	.pll_table = tegra_pll_p_table,
 	.max_rate  = 432000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1400000000,
+		.freq_table = tegra_pll_p_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_p_out1 = {
@@ -1190,11 +1617,9 @@
 	.max_rate  = 432000000,
 };
 
-static struct clk_pll_table tegra_pll_a_table[] = {
+static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
 	{ 28800000, 56448000, 49, 25, 1, 1},
 	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 11289600, 49, 25, 1, 1},
-	{ 28800000, 12288000, 64, 25, 1, 1},
 	{ 28800000, 24000000,  5,  6, 1, 1},
 	{ 0, 0, 0, 0, 0, 0 },
 };
@@ -1204,15 +1629,18 @@
 	.flags     = PLL_HAS_CPCON,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xb0,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_pll_p_out1,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1400000000,
-	.pll_table = tegra_pll_a_table,
-	.max_rate  = 56448000,
+	.max_rate  = 73728000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1400000000,
+		.freq_table = tegra_pll_a_freq_table,
+		.lock_delay = 300,
+	},
 };
 
 static struct clk tegra_pll_a_out0 = {
@@ -1222,14 +1650,25 @@
 	.parent    = &tegra_pll_a,
 	.reg       = 0xb4,
 	.reg_shift = 0,
-	.max_rate  = 56448000,
+	.max_rate  = 73728000,
 };
 
-static struct clk_pll_table tegra_pll_d_table[] = {
+static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
+	{ 12000000, 216000000, 216, 12, 1, 4},
+	{ 13000000, 216000000, 216, 13, 1, 4},
+	{ 19200000, 216000000, 135, 12, 1, 3},
+	{ 26000000, 216000000, 216, 26, 1, 4},
+
+	{ 12000000, 594000000, 594, 12, 1, 8},
+	{ 13000000, 594000000, 594, 13, 1, 8},
+	{ 19200000, 594000000, 495, 16, 1, 8},
+	{ 26000000, 594000000, 594, 26, 1, 8},
+
 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 	{ 13000000, 1000000000, 1000, 13, 1, 12},
 	{ 19200000, 1000000000, 625,  12, 1, 8},
 	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
 	{ 0, 0, 0, 0, 0, 0 },
 };
 
@@ -1238,15 +1677,18 @@
 	.flags     = PLL_HAS_CPCON | PLLD,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xd0,
-	.input_min = 2000000,
-	.input_max = 40000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 40000000,
-	.vco_max   = 1000000000,
-	.pll_table = tegra_pll_d_table,
 	.max_rate  = 1000000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 40000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 40000000,
+		.vco_max   = 1000000000,
+		.freq_table = tegra_pll_d_freq_table,
+		.lock_delay = 1000,
+	},
 };
 
 static struct clk tegra_pll_d_out0 = {
@@ -1257,7 +1699,7 @@
 	.max_rate  = 500000000,
 };
 
-static struct clk_pll_table tegra_pll_u_table[] = {
+static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
 	{ 12000000, 480000000, 960, 12, 2, 0},
 	{ 13000000, 480000000, 960, 13, 2, 0},
 	{ 19200000, 480000000, 200, 4,  2, 0},
@@ -1270,18 +1712,21 @@
 	.flags     = PLLU,
 	.ops       = &tegra_pll_ops,
 	.reg       = 0xc0,
-	.input_min = 2000000,
-	.input_max = 40000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 480000000,
-	.vco_max   = 960000000,
-	.pll_table = tegra_pll_u_table,
 	.max_rate  = 480000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 40000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 480000000,
+		.vco_max   = 960000000,
+		.freq_table = tegra_pll_u_freq_table,
+		.lock_delay = 1000,
+	},
 };
 
-static struct clk_pll_table tegra_pll_x_table[] = {
+static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
 	/* 1 GHz */
 	{ 12000000, 1000000000, 1000, 12, 1, 12},
 	{ 13000000, 1000000000, 1000, 13, 1, 12},
@@ -1307,10 +1752,10 @@
 	{ 26000000, 760000000,  760,  26, 1, 12},
 
 	/* 608 MHz */
-	{ 12000000, 608000000,  760,  12, 1, 12},
-	{ 13000000, 608000000,  760,  13, 1, 12},
+	{ 12000000, 608000000,  608,  12, 1, 12},
+	{ 13000000, 608000000,  608,  13, 1, 12},
 	{ 19200000, 608000000,  380,  12, 1, 8},
-	{ 26000000, 608000000,  760,  26, 1, 12},
+	{ 26000000, 608000000,  608,  26, 1, 12},
 
 	/* 456 MHz */
 	{ 12000000, 456000000,  456,  12, 1, 12},
@@ -1332,18 +1777,21 @@
 	.flags     = PLL_HAS_CPCON | PLL_ALT_MISC_REG,
 	.ops       = &tegra_pllx_ops,
 	.reg       = 0xe0,
-	.input_min = 2000000,
-	.input_max = 31000000,
 	.parent    = &tegra_clk_m,
-	.cf_min    = 1000000,
-	.cf_max    = 6000000,
-	.vco_min   = 20000000,
-	.vco_max   = 1200000000,
-	.pll_table = tegra_pll_x_table,
 	.max_rate  = 1000000000,
+	.u.pll = {
+		.input_min = 2000000,
+		.input_max = 31000000,
+		.cf_min    = 1000000,
+		.cf_max    = 6000000,
+		.vco_min   = 20000000,
+		.vco_max   = 1200000000,
+		.freq_table = tegra_pll_x_freq_table,
+		.lock_delay = 300,
+	},
 };
 
-static struct clk_pll_table tegra_pll_e_table[] = {
+static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
 	{ 12000000, 100000000,  200,  24, 1, 0 },
 	{ 0, 0, 0, 0, 0, 0 },
 };
@@ -1352,23 +1800,49 @@
 	.name      = "pll_e",
 	.flags	   = PLL_ALT_MISC_REG,
 	.ops       = &tegra_plle_ops,
-	.input_min = 12000000,
-	.input_max = 12000000,
-	.max_rate  = 100000000,
 	.parent    = &tegra_clk_m,
 	.reg       = 0xe8,
-	.pll_table = tegra_pll_e_table,
+	.max_rate  = 100000000,
+	.u.pll = {
+		.input_min = 12000000,
+		.input_max = 12000000,
+		.freq_table = tegra_pll_e_freq_table,
+	},
 };
 
 static struct clk tegra_clk_d = {
 	.name      = "clk_d",
 	.flags     = PERIPH_NO_RESET,
 	.ops       = &tegra_clk_double_ops,
-	.clk_num   = 90,
 	.reg       = 0x34,
 	.reg_shift = 12,
 	.parent    = &tegra_clk_m,
 	.max_rate  = 52000000,
+	.u.periph  = {
+		.clk_num = 90,
+	},
+};
+
+/* dap_mclk1, belongs to the cdev1 pingroup. */
+static struct clk tegra_clk_cdev1 = {
+	.name      = "cdev1",
+	.ops       = &tegra_cdev_clk_ops,
+	.rate      = 26000000,
+	.max_rate  = 26000000,
+	.u.periph  = {
+		.clk_num = 94,
+	},
+};
+
+/* dap_mclk2, belongs to the cdev2 pingroup. */
+static struct clk tegra_clk_cdev2 = {
+	.name      = "cdev2",
+	.ops       = &tegra_cdev_clk_ops,
+	.rate      = 26000000,
+	.max_rate  = 26000000,
+	.u.periph  = {
+		.clk_num   = 93,
+	},
 };
 
 /* initialized before peripheral clocks */
@@ -1394,7 +1868,7 @@
 	.name      = "audio",
 	.inputs    = mux_audio_sync_clk,
 	.reg       = 0x38,
-	.max_rate  = 24000000,
+	.max_rate  = 73728000,
 	.ops       = &tegra_audio_sync_clk_ops
 };
 
@@ -1403,10 +1877,12 @@
 	.flags     = PERIPH_NO_RESET,
 	.max_rate  = 48000000,
 	.ops       = &tegra_clk_double_ops,
-	.clk_num   = 89,
 	.reg       = 0x34,
 	.reg_shift = 8,
 	.parent    = &tegra_clk_audio,
+	.u.periph = {
+		.clk_num = 89,
+	},
 };
 
 struct clk_lookup tegra_audio_clk_lookups[] = {
@@ -1478,17 +1954,26 @@
 	.inputs	= mux_sclk,
 	.reg	= 0x28,
 	.ops	= &tegra_super_ops,
-	.max_rate = 600000000,
+	.max_rate = 240000000,
+	.min_rate = 120000000,
 };
 
 static struct clk tegra_clk_virtual_cpu = {
 	.name      = "cpu",
 	.parent    = &tegra_clk_cclk,
-	.main      = &tegra_pll_x,
-	.backup    = &tegra_clk_m,
 	.ops       = &tegra_cpu_ops,
 	.max_rate  = 1000000000,
-	.dvfs      = &tegra_dvfs_virtual_cpu_dvfs,
+	.u.cpu = {
+		.main      = &tegra_pll_x,
+		.backup    = &tegra_pll_p,
+	},
+};
+
+static struct clk tegra_clk_cop = {
+	.name      = "cop",
+	.parent    = &tegra_clk_sclk,
+	.ops       = &tegra_cop_ops,
+	.max_rate  = 240000000,
 };
 
 static struct clk tegra_clk_hclk = {
@@ -1508,7 +1993,15 @@
 	.reg		= 0x30,
 	.reg_shift	= 0,
 	.ops		= &tegra_bus_ops,
-	.max_rate       = 108000000,
+	.max_rate       = 120000000,
+};
+
+static struct clk tegra_clk_blink = {
+	.name		= "blink",
+	.parent		= &tegra_clk_32k,
+	.reg		= 0x40,
+	.ops		= &tegra_blink_clk_ops,
+	.max_rate	= 32768,
 };
 
 static struct clk_mux_sel mux_pllm_pllc_pllp_plla[] = {
@@ -1587,6 +2080,23 @@
 	{ 0, 0},
 };
 
+static struct clk_mux_sel mux_pclk[] = {
+	{ .input = &tegra_clk_pclk, .value = 0},
+	{ 0, 0},
+};
+
+static struct clk tegra_clk_emc = {
+	.name = "emc",
+	.ops = &tegra_emc_clk_ops,
+	.reg = 0x19c,
+	.max_rate = 800000000,
+	.inputs = mux_pllm_pllc_pllp_clkm,
+	.flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
+	.u.periph = {
+		.clk_num = 57,
+	},
+};
+
 #define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg, _max, _inputs, _flags) \
 	{						\
 		.name      = _name,			\
@@ -1595,19 +2105,32 @@
 			.con_id	   = _con,		\
 		},					\
 		.ops       = &tegra_periph_clk_ops,	\
-		.clk_num   = _clk_num,			\
 		.reg       = _reg,			\
 		.inputs    = _inputs,			\
 		.flags     = _flags,			\
 		.max_rate  = _max,			\
+		.u.periph = {				\
+			.clk_num   = _clk_num,		\
+		},					\
 	}
 
-struct clk tegra_periph_clks[] = {
+#define SHARED_CLK(_name, _dev, _con, _parent)		\
+	{						\
+		.name      = _name,			\
+		.lookup    = {				\
+			.dev_id    = _dev,		\
+			.con_id    = _con,		\
+		},					\
+		.ops       = &tegra_clk_shared_bus_ops,	\
+		.parent = _parent,			\
+	}
+
+struct clk tegra_list_clks[] = {
+	PERIPH_CLK("apbdma",	"tegra-dma",		NULL,	34,	0,	108000000, mux_pclk,			0),
 	PERIPH_CLK("rtc",	"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET),
 	PERIPH_CLK("timer",	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0),
-	PERIPH_CLK("i2s1",	"i2s.0",		NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	PERIPH_CLK("i2s2",	"i2s.1",		NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
-	/* FIXME: spdif has 2 clocks but 1 enable */
+	PERIPH_CLK("i2s1",	"tegra-i2s.0",		NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
+	PERIPH_CLK("i2s2",	"tegra-i2s.1",		NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("spdif_out",	"spdif_out",		NULL,	10,	0x108,	100000000, mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("spdif_in",	"spdif_in",		NULL,	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71),
 	PERIPH_CLK("pwm",	"pwm",			NULL,	17,	0x110,	432000000, mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71),
@@ -1620,13 +2143,15 @@
 	PERIPH_CLK("sbc4",	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("ide",	"ide",			NULL,	25,	0x144,	100000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("ndflash",	"tegra_nand",		NULL,	13,	0x160,	164000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	/* FIXME: vfir shares an enable with uartb */
 	PERIPH_CLK("vfir",	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
 	PERIPH_CLK("sdmmc1",	"sdhci-tegra.0",	NULL,	14,	0x150,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 	PERIPH_CLK("sdmmc2",	"sdhci-tegra.1",	NULL,	9,	0x154,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
 	PERIPH_CLK("sdmmc3",	"sdhci-tegra.2",	NULL,	69,	0x1bc,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x160,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
-	PERIPH_CLK("vde",	"vde",			NULL,	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("sdmmc4",	"sdhci-tegra.3",	NULL,	15,	0x164,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage */
+	PERIPH_CLK("vcp",	"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0),
+	PERIPH_CLK("bsea",	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0),
+	PERIPH_CLK("bsev",	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0),
+	PERIPH_CLK("vde",	"tegra-avp",		"vde",	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("csite",	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71), /* max rate ??? */
 	/* FIXME: what is la? */
 	PERIPH_CLK("la",	"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71),
@@ -1641,37 +2166,46 @@
 	PERIPH_CLK("i2c2_i2c",	"tegra-i2c.1",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
 	PERIPH_CLK("i2c3_i2c",	"tegra-i2c.2",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
 	PERIPH_CLK("dvc_i2c",	"tegra-i2c.3",		"i2c",	0,	0,	72000000,  mux_pllp_out3,			0),
-	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
-	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	216000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uarta",	"uart.0",		NULL,	6,	0x178,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartb",	"uart.1",		NULL,	7,	0x17c,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartc",	"uart.2",		NULL,	55,	0x1a0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uartd",	"uart.3",		NULL,	65,	0x1c0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
+	PERIPH_CLK("uarte",	"uart.4",		NULL,	66,	0x1c4,	600000000, mux_pllp_pllc_pllm_clkm,	MUX),
 	PERIPH_CLK("3d",	"3d",			NULL,	24,	0x158,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET), /* scales with voltage and process_id */
 	PERIPH_CLK("2d",	"2d",			NULL,	21,	0x15c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	/* FIXME: vi and vi_sensor share an enable */
-	PERIPH_CLK("vi",	"vi",			NULL,	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("vi_sensor",	"vi_sensor",		NULL,	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
+	PERIPH_CLK("vi",	"tegra_camera",		"vi",	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("vi_sensor",	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET), /* scales with voltage and process_id */
 	PERIPH_CLK("epp",	"epp",			NULL,	19,	0x16c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("mpe",	"mpe",			NULL,	60,	0x170,	250000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("host1x",	"host1x",		NULL,	28,	0x180,	166000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71), /* scales with voltage and process_id */
-	/* FIXME: cve and tvo share an enable	*/
 	PERIPH_CLK("cve",	"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("tvo",	"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
+	PERIPH_CLK("hdmi",	"hdmi",			NULL,	51,	0x18c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
 	PERIPH_CLK("tvdac",	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* requires min voltage */
-	PERIPH_CLK("disp1",	"tegrafb.0",		NULL,	27,	0x138,	190000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
-	PERIPH_CLK("disp2",	"tegrafb.1",		NULL,	26,	0x13c,	190000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("disp1",	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
+	PERIPH_CLK("disp2",	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71), /* scales with voltage and process_id */
 	PERIPH_CLK("usbd",	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 	PERIPH_CLK("usb2",	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
 	PERIPH_CLK("usb3",	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0), /* requires min voltage */
-	PERIPH_CLK("emc",	"emc",			NULL,	57,	0x19c,	800000000, mux_pllm_pllc_pllp_clkm,	MUX | DIV_U71 | PERIPH_EMC_ENB),
 	PERIPH_CLK("dsi",	"dsi",			NULL,	48,	0,	500000000, mux_plld,			0), /* scales with voltage */
-	PERIPH_CLK("csi",	"csi",			NULL,	52,	0,	72000000,  mux_pllp_out3,		0),
-	PERIPH_CLK("isp",	"isp",			NULL,	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
-	PERIPH_CLK("csus",	"csus",			NULL,	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
+	PERIPH_CLK("csi",	"tegra_camera",		"csi",	52,	0,	72000000,  mux_pllp_out3,		0),
+	PERIPH_CLK("isp",	"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0), /* same frequency as VI */
+	PERIPH_CLK("csus",	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET),
 	PERIPH_CLK("pex",       NULL,			"pex",  70,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
 	PERIPH_CLK("afi",       NULL,			"afi",  72,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
 	PERIPH_CLK("pcie_xclk", NULL,		  "pcie_xclk",  74,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET),
+
+	SHARED_CLK("avp.sclk",	"tegra-avp",		"sclk",	&tegra_clk_sclk),
+	SHARED_CLK("avp.emc",	"tegra-avp",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("cpu.emc",	"cpu",			"emc",	&tegra_clk_emc),
+	SHARED_CLK("disp1.emc",	"tegradc.0",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("disp2.emc",	"tegradc.1",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("hdmi.emc",	"hdmi",			"emc",	&tegra_clk_emc),
+	SHARED_CLK("host.emc",	"tegra_grhost",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("usbd.emc",	"fsl-tegra-udc",	"emc",	&tegra_clk_emc),
+	SHARED_CLK("usb1.emc",	"tegra-ehci.0",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("usb2.emc",	"tegra-ehci.1",		"emc",	&tegra_clk_emc),
+	SHARED_CLK("usb3.emc",	"tegra-ehci.2",		"emc",	&tegra_clk_emc),
 };
 
 #define CLK_DUPLICATE(_name, _dev, _con)		\
@@ -1693,9 +2227,22 @@
 	CLK_DUPLICATE("uartc",	"tegra_uart.2",	NULL),
 	CLK_DUPLICATE("uartd",	"tegra_uart.3",	NULL),
 	CLK_DUPLICATE("uarte",	"tegra_uart.4",	NULL),
-	CLK_DUPLICATE("host1x", "tegrafb.0", "host1x"),
-	CLK_DUPLICATE("host1x", "tegrafb.1", "host1x"),
+	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
 	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
+	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
+	CLK_DUPLICATE("hdmi", "tegradc.0", "hdmi"),
+	CLK_DUPLICATE("hdmi", "tegradc.1", "hdmi"),
+	CLK_DUPLICATE("pwm", "tegra_pwm.0", NULL),
+	CLK_DUPLICATE("pwm", "tegra_pwm.1", NULL),
+	CLK_DUPLICATE("pwm", "tegra_pwm.2", NULL),
+	CLK_DUPLICATE("pwm", "tegra_pwm.3", NULL),
+	CLK_DUPLICATE("host1x", "tegra_grhost", "host1x"),
+	CLK_DUPLICATE("2d", "tegra_grhost", "gr2d"),
+	CLK_DUPLICATE("3d", "tegra_grhost", "gr3d"),
+	CLK_DUPLICATE("epp", "tegra_grhost", "epp"),
+	CLK_DUPLICATE("mpe", "tegra_grhost", "mpe"),
+	CLK_DUPLICATE("cop", "tegra-avp", "cop"),
+	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
 };
 
 #define CLK(dev, con, ck)	\
@@ -1705,68 +2252,70 @@
 		.clk = ck,	\
 	}
 
-struct clk_lookup tegra_clk_lookups[] = {
-	/* external root sources */
-	CLK(NULL,	"32k_clk",	&tegra_clk_32k),
-	CLK(NULL,	"pll_s",	&tegra_pll_s),
-	CLK(NULL,	"clk_m",	&tegra_clk_m),
-	CLK(NULL,	"pll_m",	&tegra_pll_m),
-	CLK(NULL,	"pll_m_out1",	&tegra_pll_m_out1),
-	CLK(NULL,	"pll_c",	&tegra_pll_c),
-	CLK(NULL,	"pll_c_out1",	&tegra_pll_c_out1),
-	CLK(NULL,	"pll_p",	&tegra_pll_p),
-	CLK(NULL,	"pll_p_out1",	&tegra_pll_p_out1),
-	CLK(NULL,	"pll_p_out2",	&tegra_pll_p_out2),
-	CLK(NULL,	"pll_p_out3",	&tegra_pll_p_out3),
-	CLK(NULL,	"pll_p_out4",	&tegra_pll_p_out4),
-	CLK(NULL,	"pll_a",	&tegra_pll_a),
-	CLK(NULL,	"pll_a_out0",	&tegra_pll_a_out0),
-	CLK(NULL,	"pll_d",	&tegra_pll_d),
-	CLK(NULL,	"pll_d_out0",	&tegra_pll_d_out0),
-	CLK(NULL,	"pll_u",	&tegra_pll_u),
-	CLK(NULL,	"pll_x",	&tegra_pll_x),
-	CLK(NULL,	"pll_e",	&tegra_pll_e),
-	CLK(NULL,	"cclk",		&tegra_clk_cclk),
-	CLK(NULL,	"sclk",		&tegra_clk_sclk),
-	CLK(NULL,	"hclk",		&tegra_clk_hclk),
-	CLK(NULL,	"pclk",		&tegra_clk_pclk),
-	CLK(NULL,	"clk_d",	&tegra_clk_d),
-	CLK(NULL,	"cpu",		&tegra_clk_virtual_cpu),
+struct clk *tegra_ptr_clks[] = {
+	&tegra_clk_32k,
+	&tegra_pll_s,
+	&tegra_clk_m,
+	&tegra_pll_m,
+	&tegra_pll_m_out1,
+	&tegra_pll_c,
+	&tegra_pll_c_out1,
+	&tegra_pll_p,
+	&tegra_pll_p_out1,
+	&tegra_pll_p_out2,
+	&tegra_pll_p_out3,
+	&tegra_pll_p_out4,
+	&tegra_pll_a,
+	&tegra_pll_a_out0,
+	&tegra_pll_d,
+	&tegra_pll_d_out0,
+	&tegra_pll_u,
+	&tegra_pll_x,
+	&tegra_pll_e,
+	&tegra_clk_cclk,
+	&tegra_clk_sclk,
+	&tegra_clk_hclk,
+	&tegra_clk_pclk,
+	&tegra_clk_d,
+	&tegra_clk_cdev1,
+	&tegra_clk_cdev2,
+	&tegra_clk_virtual_cpu,
+	&tegra_clk_blink,
+	&tegra_clk_cop,
+	&tegra_clk_emc,
 };
 
+static void tegra2_init_one_clock(struct clk *c)
+{
+	clk_init(c);
+	INIT_LIST_HEAD(&c->shared_bus_list);
+	if (!c->lookup.dev_id && !c->lookup.con_id)
+		c->lookup.con_id = c->name;
+	c->lookup.clk = c;
+	clkdev_add(&c->lookup);
+}
+
 void __init tegra2_init_clocks(void)
 {
 	int i;
-	struct clk_lookup *cl;
 	struct clk *c;
-	struct clk_duplicate *cd;
 
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_lookups); i++) {
-		cl = &tegra_clk_lookups[i];
-		clk_init(cl->clk);
-		clkdev_add(cl);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(tegra_periph_clks); i++) {
-		c = &tegra_periph_clks[i];
-		cl = &c->lookup;
-		cl->clk = c;
+	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
+		tegra2_init_one_clock(tegra_ptr_clks[i]);
 
-		clk_init(cl->clk);
-		clkdev_add(cl);
-	}
+	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
+		tegra2_init_one_clock(&tegra_list_clks[i]);
 
 	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
-		cd = &tegra_clk_duplicates[i];
-		c = tegra_get_clock_by_name(cd->name);
-		if (c) {
-			cl = &cd->lookup;
-			cl->clk = c;
-			clkdev_add(cl);
-		} else {
+		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
+		if (!c) {
 			pr_err("%s: Unknown duplicate clock %s\n", __func__,
-				cd->name);
+				tegra_clk_duplicates[i].name);
+			continue;
 		}
+
+		tegra_clk_duplicates[i].lookup.clk = c;
+		clkdev_add(&tegra_clk_duplicates[i].lookup);
 	}
 
 	init_audio_sync_clock_mux();
@@ -1774,7 +2323,7 @@
 
 #ifdef CONFIG_PM
 static u32 clk_rst_suspend[RST_DEVICES_NUM + CLK_OUT_ENB_NUM +
-			   PERIPH_CLK_SOURCE_NUM + 3];
+			   PERIPH_CLK_SOURCE_NUM + 22];
 
 void tegra_clk_suspend(void)
 {
@@ -1782,6 +2331,29 @@
 	u32 *ctx = clk_rst_suspend;
 
 	*ctx++ = clk_readl(OSC_CTRL) & OSC_CTRL_MASK;
+	*ctx++ = clk_readl(tegra_pll_c.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
+	*ctx++ = clk_readl(tegra_pll_a.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
+	*ctx++ = clk_readl(tegra_pll_s.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+	*ctx++ = clk_readl(tegra_pll_d.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+	*ctx++ = clk_readl(tegra_pll_u.reg + PLL_BASE);
+	*ctx++ = clk_readl(tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
+
+	*ctx++ = clk_readl(tegra_pll_m_out1.reg);
+	*ctx++ = clk_readl(tegra_pll_a_out0.reg);
+	*ctx++ = clk_readl(tegra_pll_c_out1.reg);
+
+	*ctx++ = clk_readl(tegra_clk_cclk.reg);
+	*ctx++ = clk_readl(tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
+
+	*ctx++ = clk_readl(tegra_clk_sclk.reg);
+	*ctx++ = clk_readl(tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
+	*ctx++ = clk_readl(tegra_clk_pclk.reg);
+
+	*ctx++ = clk_readl(tegra_clk_audio.reg);
 
 	for (off = PERIPH_CLK_SOURCE_I2S1; off <= PERIPH_CLK_SOURCE_OSC;
 			off += 4) {
@@ -1800,6 +2372,8 @@
 
 	*ctx++ = clk_readl(MISC_CLK_ENB);
 	*ctx++ = clk_readl(CLK_MASK_ARM);
+
+	BUG_ON(ctx - clk_rst_suspend != ARRAY_SIZE(clk_rst_suspend));
 }
 
 void tegra_clk_resume(void)
@@ -1812,6 +2386,31 @@
 	val |= *ctx++;
 	clk_writel(val, OSC_CTRL);
 
+	clk_writel(*ctx++, tegra_pll_c.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_c.reg + PLL_MISC(&tegra_pll_c));
+	clk_writel(*ctx++, tegra_pll_a.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_a.reg + PLL_MISC(&tegra_pll_a));
+	clk_writel(*ctx++, tegra_pll_s.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_s.reg + PLL_MISC(&tegra_pll_s));
+	clk_writel(*ctx++, tegra_pll_d.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_d.reg + PLL_MISC(&tegra_pll_d));
+	clk_writel(*ctx++, tegra_pll_u.reg + PLL_BASE);
+	clk_writel(*ctx++, tegra_pll_u.reg + PLL_MISC(&tegra_pll_u));
+	udelay(1000);
+
+	clk_writel(*ctx++, tegra_pll_m_out1.reg);
+	clk_writel(*ctx++, tegra_pll_a_out0.reg);
+	clk_writel(*ctx++, tegra_pll_c_out1.reg);
+
+	clk_writel(*ctx++, tegra_clk_cclk.reg);
+	clk_writel(*ctx++, tegra_clk_cclk.reg + SUPER_CLK_DIVIDER);
+
+	clk_writel(*ctx++, tegra_clk_sclk.reg);
+	clk_writel(*ctx++, tegra_clk_sclk.reg + SUPER_CLK_DIVIDER);
+	clk_writel(*ctx++, tegra_clk_pclk.reg);
+
+	clk_writel(*ctx++, tegra_clk_audio.reg);
+
 	/* enable all clocks before configuring clock sources */
 	clk_writel(0xbffffff9ul, CLK_OUT_ENB);
 	clk_writel(0xfefffff7ul, CLK_OUT_ENB + 4);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_dvfs.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_dvfs.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_dvfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_dvfs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra2_dvfs.c
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 "clock.h"
-#include "tegra2_dvfs.h"
-
-static struct dvfs_table virtual_cpu_process_0[] = {
-	{314000000,  750},
-	{456000000,  825},
-	{608000000,  900},
-	{760000000,  975},
-	{817000000,  1000},
-	{912000000,  1050},
-	{1000000000, 1100},
-	{0, 0},
-};
-
-static struct dvfs_table virtual_cpu_process_1[] = {
-	{314000000,  750},
-	{456000000,  825},
-	{618000000,  900},
-	{770000000,  975},
-	{827000000,  1000},
-	{922000000,  1050},
-	{1000000000, 1100},
-	{0, 0},
-};
-
-static struct dvfs_table virtual_cpu_process_2[] = {
-	{494000000,  750},
-	{675000000,  825},
-	{817000000,  875},
-	{922000000,  925},
-	{1000000000, 975},
-	{0, 0},
-};
-
-static struct dvfs_table virtual_cpu_process_3[] = {
-	{730000000,  750},
-	{760000000,  775},
-	{845000000,  800},
-	{1000000000, 875},
-	{0, 0},
-};
-
-struct dvfs tegra_dvfs_virtual_cpu_dvfs = {
-	.reg_id = "vdd_cpu",
-	.process_id_table = {
-		{
-			.process_id = 0,
-			.table = virtual_cpu_process_0,
-		},
-		{
-			.process_id = 1,
-			.table = virtual_cpu_process_1,
-		},
-		{
-			.process_id = 2,
-			.table = virtual_cpu_process_2,
-		},
-		{
-			.process_id = 3,
-			.table = virtual_cpu_process_3,
-		},
-	},
-	.process_id_table_length = 4,
-	.cpu = 1,
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_dvfs.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_dvfs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_dvfs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_dvfs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra2_dvfs.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- */
-
-extern struct dvfs tegra_dvfs_virtual_cpu_dvfs;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_emc.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_emc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_emc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_emc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,178 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/module.h>
+
+#include <mach/iomap.h>
+
+#include "tegra2_emc.h"
+
+#ifdef CONFIG_TEGRA_EMC_SCALING_ENABLE
+static bool emc_enable = true;
+#else
+static bool emc_enable;
+#endif
+module_param(emc_enable, bool, 0644);
+
+static void __iomem *emc = IO_ADDRESS(TEGRA_EMC_BASE);
+static const struct tegra_emc_table *tegra_emc_table;
+static int tegra_emc_table_size;
+
+static inline void emc_writel(u32 val, unsigned long addr)
+{
+	writel(val, emc + addr);
+}
+
+static inline u32 emc_readl(unsigned long addr)
+{
+	return readl(emc + addr);
+}
+
+static const unsigned long emc_reg_addr[TEGRA_EMC_NUM_REGS] = {
+	0x2c,	/* RC */
+	0x30,	/* RFC */
+	0x34,	/* RAS */
+	0x38,	/* RP */
+	0x3c,	/* R2W */
+	0x40,	/* W2R */
+	0x44,	/* R2P */
+	0x48,	/* W2P */
+	0x4c,	/* RD_RCD */
+	0x50,	/* WR_RCD */
+	0x54,	/* RRD */
+	0x58,	/* REXT */
+	0x5c,	/* WDV */
+	0x60,	/* QUSE */
+	0x64,	/* QRST */
+	0x68,	/* QSAFE */
+	0x6c,	/* RDV */
+	0x70,	/* REFRESH */
+	0x74,	/* BURST_REFRESH_NUM */
+	0x78,	/* PDEX2WR */
+	0x7c,	/* PDEX2RD */
+	0x80,	/* PCHG2PDEN */
+	0x84,	/* ACT2PDEN */
+	0x88,	/* AR2PDEN */
+	0x8c,	/* RW2PDEN */
+	0x90,	/* TXSR */
+	0x94,	/* TCKE */
+	0x98,	/* TFAW */
+	0x9c,	/* TRPAB */
+	0xa0,	/* TCLKSTABLE */
+	0xa4,	/* TCLKSTOP */
+	0xa8,	/* TREFBW */
+	0xac,	/* QUSE_EXTRA */
+	0x114,	/* FBIO_CFG6 */
+	0xb0,	/* ODT_WRITE */
+	0xb4,	/* ODT_READ */
+	0x104,	/* FBIO_CFG5 */
+	0x2bc,	/* CFG_DIG_DLL */
+	0x2c0,	/* DLL_XFORM_DQS */
+	0x2c4,	/* DLL_XFORM_QUSE */
+	0x2e0,	/* ZCAL_REF_CNT */
+	0x2e4,	/* ZCAL_WAIT_CNT */
+	0x2a8,	/* AUTO_CAL_INTERVAL */
+	0x2d0,	/* CFG_CLKTRIM_0 */
+	0x2d4,	/* CFG_CLKTRIM_1 */
+	0x2d8,	/* CFG_CLKTRIM_2 */
+};
+
+/* Select the closest EMC rate that is higher than the requested rate */
+long tegra_emc_round_rate(unsigned long rate)
+{
+	int i;
+	int best = -1;
+	unsigned long distance = ULONG_MAX;
+
+	if (!tegra_emc_table)
+		return -EINVAL;
+
+	if (!emc_enable)
+		return -EINVAL;
+
+	pr_debug("%s: %lu\n", __func__, rate);
+
+	/*
+	 * The EMC clock rate is twice the bus rate, and the bus rate is
+	 * measured in kHz
+	 */
+	rate = rate / 2 / 1000;
+
+	for (i = 0; i < tegra_emc_table_size; i++) {
+		if (tegra_emc_table[i].rate >= rate &&
+		    (tegra_emc_table[i].rate - rate) < distance) {
+			distance = tegra_emc_table[i].rate - rate;
+			best = i;
+		}
+	}
+
+	if (best < 0)
+		return -EINVAL;
+
+	pr_debug("%s: using %lu\n", __func__, tegra_emc_table[best].rate);
+
+	return tegra_emc_table[best].rate * 2 * 1000;
+}
+
+/*
+ * The EMC registers have shadow registers.  When the EMC clock is updated
+ * in the clock controller, the shadow registers are copied to the active
+ * registers, allowing glitchless memory bus frequency changes.
+ * This function updates the shadow registers for a new clock frequency,
+ * and relies on the clock lock on the emc clock to avoid races between
+ * multiple frequency changes
+ */
+int tegra_emc_set_rate(unsigned long rate)
+{
+	int i;
+	int j;
+
+	if (!tegra_emc_table)
+		return -EINVAL;
+
+	/*
+	 * The EMC clock rate is twice the bus rate, and the bus rate is
+	 * measured in kHz
+	 */
+	rate = rate / 2 / 1000;
+
+	for (i = 0; i < tegra_emc_table_size; i++)
+		if (tegra_emc_table[i].rate == rate)
+			break;
+
+	if (i >= tegra_emc_table_size)
+		return -EINVAL;
+
+	pr_debug("%s: setting to %lu\n", __func__, rate);
+
+	for (j = 0; j < TEGRA_EMC_NUM_REGS; j++)
+		emc_writel(tegra_emc_table[i].regs[j], emc_reg_addr[j]);
+
+	emc_readl(tegra_emc_table[i].regs[TEGRA_EMC_NUM_REGS - 1]);
+
+	return 0;
+}
+
+void tegra_init_emc(const struct tegra_emc_table *table, int table_size)
+{
+	tegra_emc_table = table;
+	tegra_emc_table_size = table_size;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_emc.h linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_emc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/tegra2_emc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/tegra2_emc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ *	Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define TEGRA_EMC_NUM_REGS 46
+
+struct tegra_emc_table {
+	unsigned long rate;
+	u32 regs[TEGRA_EMC_NUM_REGS];
+};
+
+int tegra_emc_set_rate(unsigned long rate);
+long tegra_emc_round_rate(unsigned long rate);
+void tegra_init_emc(const struct tegra_emc_table *table, int table_size);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/timer.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/timer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/err.h>
 #include <linux/sched.h>
 #include <linux/time.h>
 #include <linux/interrupt.h>
@@ -33,10 +34,15 @@
 
 #include <mach/iomap.h>
 #include <mach/irqs.h>
+#include <mach/suspend.h>
 
 #include "board.h"
 #include "clock.h"
 
+#define RTC_SECONDS            0x08
+#define RTC_SHADOW_SECONDS     0x0c
+#define RTC_MILLISECONDS       0x10
+
 #define TIMERUS_CNTR_1US 0x10
 #define TIMERUS_USEC_CFG 0x14
 #define TIMERUS_CNTR_FREEZE 0x4c
@@ -49,9 +55,11 @@
 #define TIMER_PTV 0x0
 #define TIMER_PCR 0x4
 
-struct tegra_timer;
-
 static void __iomem *timer_reg_base = IO_ADDRESS(TEGRA_TMR1_BASE);
+static void __iomem *rtc_base = IO_ADDRESS(TEGRA_RTC_BASE);
+
+static struct timespec persistent_ts;
+static u64 persistent_ms, last_persistent_ms;
 
 #define timer_writel(value, reg) \
 	__raw_writel(value, (u32)timer_reg_base + (reg))
@@ -132,6 +140,42 @@
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
+/*
+ * tegra_rtc_read - Reads the Tegra RTC registers
+ * Care must be taken that this funciton is not called while the
+ * tegra_rtc driver could be executing to avoid race conditions
+ * on the RTC shadow register
+ */
+u64 tegra_rtc_read_ms(void)
+{
+	u32 ms = readl(rtc_base + RTC_MILLISECONDS);
+	u32 s = readl(rtc_base + RTC_SHADOW_SECONDS);
+	return (u64)s * MSEC_PER_SEC + ms;
+}
+
+/*
+ * read_persistent_clock -  Return time from a persistent clock.
+ *
+ * Reads the time from a source which isn't disabled during PM, the
+ * 32k sync timer.  Convert the cycles elapsed since last read into
+ * nsecs and adds to a monotonically increasing timespec.
+ * Care must be taken that this funciton is not called while the
+ * tegra_rtc driver could be executing to avoid race conditions
+ * on the RTC shadow register
+ */
+void read_persistent_clock(struct timespec *ts)
+{
+	u64 delta;
+	struct timespec *tsp = &persistent_ts;
+
+	last_persistent_ms = persistent_ms;
+	persistent_ms = tegra_rtc_read_ms();
+	delta = persistent_ms - last_persistent_ms;
+
+	timespec_add_ns(tsp, delta * NSEC_PER_MSEC);
+	*ts = *tsp;
+}
+
 static irqreturn_t tegra_timer_interrupt(int irq, void *dev_id)
 {
 	struct clock_event_device *evt = (struct clock_event_device *)dev_id;
@@ -150,9 +194,22 @@
 
 static void __init tegra_init_timer(void)
 {
+	struct clk *clk;
 	unsigned long rate = clk_measure_input_freq();
 	int ret;
 
+	clk = clk_get_sys("timer", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_enable(clk);
+
+	/*
+	 * rtc registers are used by read_persistent_clock, keep the rtc clock
+	 * enabled
+	 */
+	clk = clk_get_sys("rtc-tegra", NULL);
+	BUG_ON(IS_ERR(clk));
+	clk_enable(clk);
+
 #ifdef CONFIG_HAVE_ARM_TWD
 	twd_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x600);
 #endif
@@ -196,10 +253,22 @@
 	tegra_clockevent.cpumask = cpu_all_mask;
 	tegra_clockevent.irq = tegra_timer_irq.irq;
 	clockevents_register_device(&tegra_clockevent);
-
-	return;
 }
 
 struct sys_timer tegra_timer = {
 	.init = tegra_init_timer,
 };
+
+#ifdef CONFIG_PM
+static u32 usec_config;
+
+void tegra_timer_suspend(void)
+{
+	usec_config = timer_readl(TIMERUS_USEC_CFG);
+}
+
+void tegra_timer_resume(void)
+{
+	timer_writel(usec_config, TIMERUS_USEC_CFG);
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-tegra/usb_phy.c linux-libre-2.6.39-gnu/arch/arm/mach-tegra/usb_phy.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-tegra/usb_phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-tegra/usb_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,795 @@
+/*
+ * arch/arm/mach-tegra/usb_phy.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ *
+ * Author:
+ *	Erik Gilling <konkers@google.com>
+ *	Benoit Goby <benoit@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/resource.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
+#include <asm/mach-types.h>
+#include <mach/usb_phy.h>
+#include <mach/iomap.h>
+
+#define ULPI_VIEWPORT		0x170
+
+#define USB_PORTSC1		0x184
+#define   USB_PORTSC1_PTS(x)	(((x) & 0x3) << 30)
+#define   USB_PORTSC1_PSPD(x)	(((x) & 0x3) << 26)
+#define   USB_PORTSC1_PHCD	(1 << 23)
+#define   USB_PORTSC1_WKOC	(1 << 22)
+#define   USB_PORTSC1_WKDS	(1 << 21)
+#define   USB_PORTSC1_WKCN	(1 << 20)
+#define   USB_PORTSC1_PTC(x)	(((x) & 0xf) << 16)
+#define   USB_PORTSC1_PP	(1 << 12)
+#define   USB_PORTSC1_SUSP	(1 << 7)
+#define   USB_PORTSC1_PE	(1 << 2)
+#define   USB_PORTSC1_CCS	(1 << 0)
+
+#define USB_SUSP_CTRL		0x400
+#define   USB_WAKE_ON_CNNT_EN_DEV	(1 << 3)
+#define   USB_WAKE_ON_DISCON_EN_DEV	(1 << 4)
+#define   USB_SUSP_CLR		(1 << 5)
+#define   USB_PHY_CLK_VALID	(1 << 7)
+#define   UTMIP_RESET			(1 << 11)
+#define   UHSIC_RESET			(1 << 11)
+#define   UTMIP_PHY_ENABLE		(1 << 12)
+#define   ULPI_PHY_ENABLE	(1 << 13)
+#define   USB_SUSP_SET		(1 << 14)
+#define   USB_WAKEUP_DEBOUNCE_COUNT(x)	(((x) & 0x7) << 16)
+
+#define USB1_LEGACY_CTRL	0x410
+#define   USB1_NO_LEGACY_MODE			(1 << 0)
+#define   USB1_VBUS_SENSE_CTL_MASK		(3 << 1)
+#define   USB1_VBUS_SENSE_CTL_VBUS_WAKEUP	(0 << 1)
+#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD_OR_VBUS_WAKEUP \
+						(1 << 1)
+#define   USB1_VBUS_SENSE_CTL_AB_SESS_VLD	(2 << 1)
+#define   USB1_VBUS_SENSE_CTL_A_SESS_VLD	(3 << 1)
+
+#define ULPI_TIMING_CTRL_0	0x424
+#define   ULPI_OUTPUT_PINMUX_BYP	(1 << 10)
+#define   ULPI_CLKOUT_PINMUX_BYP	(1 << 11)
+
+#define ULPI_TIMING_CTRL_1	0x428
+#define   ULPI_DATA_TRIMMER_LOAD	(1 << 0)
+#define   ULPI_DATA_TRIMMER_SEL(x)	(((x) & 0x7) << 1)
+#define   ULPI_STPDIRNXT_TRIMMER_LOAD	(1 << 16)
+#define   ULPI_STPDIRNXT_TRIMMER_SEL(x)	(((x) & 0x7) << 17)
+#define   ULPI_DIR_TRIMMER_LOAD		(1 << 24)
+#define   ULPI_DIR_TRIMMER_SEL(x)	(((x) & 0x7) << 25)
+
+#define UTMIP_PLL_CFG1		0x804
+#define   UTMIP_XTAL_FREQ_COUNT(x)		(((x) & 0xfff) << 0)
+#define   UTMIP_PLLU_ENABLE_DLY_COUNT(x)	(((x) & 0x1f) << 27)
+
+#define UTMIP_XCVR_CFG0		0x808
+#define   UTMIP_XCVR_SETUP(x)			(((x) & 0xf) << 0)
+#define   UTMIP_XCVR_LSRSLEW(x)			(((x) & 0x3) << 8)
+#define   UTMIP_XCVR_LSFSLEW(x)			(((x) & 0x3) << 10)
+#define   UTMIP_FORCE_PD_POWERDOWN		(1 << 14)
+#define   UTMIP_FORCE_PD2_POWERDOWN		(1 << 16)
+#define   UTMIP_FORCE_PDZI_POWERDOWN		(1 << 18)
+#define   UTMIP_XCVR_HSSLEW_MSB(x)		(((x) & 0x7f) << 25)
+
+#define UTMIP_BIAS_CFG0		0x80c
+#define   UTMIP_OTGPD			(1 << 11)
+#define   UTMIP_BIASPD			(1 << 10)
+
+#define UTMIP_HSRX_CFG0		0x810
+#define   UTMIP_ELASTIC_LIMIT(x)	(((x) & 0x1f) << 10)
+#define   UTMIP_IDLE_WAIT(x)		(((x) & 0x1f) << 15)
+
+#define UTMIP_HSRX_CFG1		0x814
+#define   UTMIP_HS_SYNC_START_DLY(x)	(((x) & 0x1f) << 1)
+
+#define UTMIP_TX_CFG0		0x820
+#define   UTMIP_FS_PREABMLE_J		(1 << 19)
+#define   UTMIP_HS_DISCON_DISABLE	(1 << 8)
+
+#define UTMIP_MISC_CFG0		0x824
+#define   UTMIP_DPDM_OBSERVE		(1 << 26)
+#define   UTMIP_DPDM_OBSERVE_SEL(x)	(((x) & 0xf) << 27)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_J	UTMIP_DPDM_OBSERVE_SEL(0xf)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_K	UTMIP_DPDM_OBSERVE_SEL(0xe)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE1 UTMIP_DPDM_OBSERVE_SEL(0xd)
+#define   UTMIP_DPDM_OBSERVE_SEL_FS_SE0 UTMIP_DPDM_OBSERVE_SEL(0xc)
+#define   UTMIP_SUSPEND_EXIT_ON_EDGE	(1 << 22)
+
+#define UTMIP_MISC_CFG1		0x828
+#define   UTMIP_PLL_ACTIVE_DLY_COUNT(x)	(((x) & 0x1f) << 18)
+#define   UTMIP_PLLU_STABLE_COUNT(x)	(((x) & 0xfff) << 6)
+
+#define UTMIP_DEBOUNCE_CFG0	0x82c
+#define   UTMIP_BIAS_DEBOUNCE_A(x)	(((x) & 0xffff) << 0)
+
+#define UTMIP_BAT_CHRG_CFG0	0x830
+#define   UTMIP_PD_CHRG			(1 << 0)
+
+#define UTMIP_SPARE_CFG0	0x834
+#define   FUSE_SETUP_SEL		(1 << 3)
+
+#define UTMIP_XCVR_CFG1		0x838
+#define   UTMIP_FORCE_PDDISC_POWERDOWN	(1 << 0)
+#define   UTMIP_FORCE_PDCHRP_POWERDOWN	(1 << 2)
+#define   UTMIP_FORCE_PDDR_POWERDOWN	(1 << 4)
+#define   UTMIP_XCVR_TERM_RANGE_ADJ(x)	(((x) & 0xf) << 18)
+
+#define UTMIP_BIAS_CFG1		0x83c
+#define   UTMIP_BIAS_PDTRK_COUNT(x)	(((x) & 0x1f) << 3)
+
+static DEFINE_SPINLOCK(utmip_pad_lock);
+static int utmip_pad_count;
+
+struct tegra_xtal_freq {
+	int freq;
+	u8 enable_delay;
+	u8 stable_count;
+	u8 active_delay;
+	u8 xtal_freq_count;
+	u16 debounce;
+};
+
+static const struct tegra_xtal_freq tegra_freq_table[] = {
+	{
+		.freq = 12000000,
+		.enable_delay = 0x02,
+		.stable_count = 0x2F,
+		.active_delay = 0x04,
+		.xtal_freq_count = 0x76,
+		.debounce = 0x7530,
+	},
+	{
+		.freq = 13000000,
+		.enable_delay = 0x02,
+		.stable_count = 0x33,
+		.active_delay = 0x05,
+		.xtal_freq_count = 0x7F,
+		.debounce = 0x7EF4,
+	},
+	{
+		.freq = 19200000,
+		.enable_delay = 0x03,
+		.stable_count = 0x4B,
+		.active_delay = 0x06,
+		.xtal_freq_count = 0xBB,
+		.debounce = 0xBB80,
+	},
+	{
+		.freq = 26000000,
+		.enable_delay = 0x04,
+		.stable_count = 0x66,
+		.active_delay = 0x09,
+		.xtal_freq_count = 0xFE,
+		.debounce = 0xFDE8,
+	},
+};
+
+static struct tegra_utmip_config utmip_default[] = {
+	[0] = {
+		.hssync_start_delay = 9,
+		.idle_wait_delay = 17,
+		.elastic_limit = 16,
+		.term_range_adj = 6,
+		.xcvr_setup = 9,
+		.xcvr_lsfslew = 1,
+		.xcvr_lsrslew = 1,
+	},
+	[2] = {
+		.hssync_start_delay = 9,
+		.idle_wait_delay = 17,
+		.elastic_limit = 16,
+		.term_range_adj = 6,
+		.xcvr_setup = 9,
+		.xcvr_lsfslew = 2,
+		.xcvr_lsrslew = 2,
+	},
+};
+
+static inline bool phy_is_ulpi(struct tegra_usb_phy *phy)
+{
+	return (phy->instance == 1);
+}
+
+static int utmip_pad_open(struct tegra_usb_phy *phy)
+{
+	phy->pad_clk = clk_get_sys("utmip-pad", NULL);
+	if (IS_ERR(phy->pad_clk)) {
+		pr_err("%s: can't get utmip pad clock\n", __func__);
+		return PTR_ERR(phy->pad_clk);
+	}
+
+	if (phy->instance == 0) {
+		phy->pad_regs = phy->regs;
+	} else {
+		phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
+		if (!phy->pad_regs) {
+			pr_err("%s: can't remap usb registers\n", __func__);
+			clk_put(phy->pad_clk);
+			return -ENOMEM;
+		}
+	}
+	return 0;
+}
+
+static void utmip_pad_close(struct tegra_usb_phy *phy)
+{
+	if (phy->instance != 0)
+		iounmap(phy->pad_regs);
+	clk_put(phy->pad_clk);
+}
+
+static void utmip_pad_power_on(struct tegra_usb_phy *phy)
+{
+	unsigned long val, flags;
+	void __iomem *base = phy->pad_regs;
+
+	clk_enable(phy->pad_clk);
+
+	spin_lock_irqsave(&utmip_pad_lock, flags);
+
+	if (utmip_pad_count++ == 0) {
+		val = readl(base + UTMIP_BIAS_CFG0);
+		val &= ~(UTMIP_OTGPD | UTMIP_BIASPD);
+		writel(val, base + UTMIP_BIAS_CFG0);
+	}
+
+	spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+	clk_disable(phy->pad_clk);
+}
+
+static int utmip_pad_power_off(struct tegra_usb_phy *phy)
+{
+	unsigned long val, flags;
+	void __iomem *base = phy->pad_regs;
+
+	if (!utmip_pad_count) {
+		pr_err("%s: utmip pad already powered off\n", __func__);
+		return -EINVAL;
+	}
+
+	clk_enable(phy->pad_clk);
+
+	spin_lock_irqsave(&utmip_pad_lock, flags);
+
+	if (--utmip_pad_count == 0) {
+		val = readl(base + UTMIP_BIAS_CFG0);
+		val |= UTMIP_OTGPD | UTMIP_BIASPD;
+		writel(val, base + UTMIP_BIAS_CFG0);
+	}
+
+	spin_unlock_irqrestore(&utmip_pad_lock, flags);
+
+	clk_disable(phy->pad_clk);
+
+	return 0;
+}
+
+static int utmi_wait_register(void __iomem *reg, u32 mask, u32 result)
+{
+	unsigned long timeout = 2000;
+	do {
+		if ((readl(reg) & mask) == result)
+			return 0;
+		udelay(1);
+		timeout--;
+	} while (timeout);
+	return -1;
+}
+
+static void utmi_phy_clk_disable(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	if (phy->instance == 0) {
+		val = readl(base + USB_SUSP_CTRL);
+		val |= USB_SUSP_SET;
+		writel(val, base + USB_SUSP_CTRL);
+
+		udelay(10);
+
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_SUSP_SET;
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	if (phy->instance == 2) {
+		val = readl(base + USB_PORTSC1);
+		val |= USB_PORTSC1_PHCD;
+		writel(val, base + USB_PORTSC1);
+	}
+
+	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
+		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+}
+
+static void utmi_phy_clk_enable(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	if (phy->instance == 0) {
+		val = readl(base + USB_SUSP_CTRL);
+		val |= USB_SUSP_CLR;
+		writel(val, base + USB_SUSP_CTRL);
+
+		udelay(10);
+
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_SUSP_CLR;
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	if (phy->instance == 2) {
+		val = readl(base + USB_PORTSC1);
+		val &= ~USB_PORTSC1_PHCD;
+		writel(val, base + USB_PORTSC1);
+	}
+
+	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
+						     USB_PHY_CLK_VALID))
+		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
+}
+
+static int utmi_phy_power_on(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+	struct tegra_utmip_config *config = phy->config;
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= UTMIP_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	if (phy->instance == 0) {
+		val = readl(base + USB1_LEGACY_CTRL);
+		val |= USB1_NO_LEGACY_MODE;
+		writel(val, base + USB1_LEGACY_CTRL);
+	}
+
+	val = readl(base + UTMIP_TX_CFG0);
+	val &= ~UTMIP_FS_PREABMLE_J;
+	writel(val, base + UTMIP_TX_CFG0);
+
+	val = readl(base + UTMIP_HSRX_CFG0);
+	val &= ~(UTMIP_IDLE_WAIT(~0) | UTMIP_ELASTIC_LIMIT(~0));
+	val |= UTMIP_IDLE_WAIT(config->idle_wait_delay);
+	val |= UTMIP_ELASTIC_LIMIT(config->elastic_limit);
+	writel(val, base + UTMIP_HSRX_CFG0);
+
+	val = readl(base + UTMIP_HSRX_CFG1);
+	val &= ~UTMIP_HS_SYNC_START_DLY(~0);
+	val |= UTMIP_HS_SYNC_START_DLY(config->hssync_start_delay);
+	writel(val, base + UTMIP_HSRX_CFG1);
+
+	val = readl(base + UTMIP_DEBOUNCE_CFG0);
+	val &= ~UTMIP_BIAS_DEBOUNCE_A(~0);
+	val |= UTMIP_BIAS_DEBOUNCE_A(phy->freq->debounce);
+	writel(val, base + UTMIP_DEBOUNCE_CFG0);
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val &= ~UTMIP_SUSPEND_EXIT_ON_EDGE;
+	writel(val, base + UTMIP_MISC_CFG0);
+
+	val = readl(base + UTMIP_MISC_CFG1);
+	val &= ~(UTMIP_PLL_ACTIVE_DLY_COUNT(~0) | UTMIP_PLLU_STABLE_COUNT(~0));
+	val |= UTMIP_PLL_ACTIVE_DLY_COUNT(phy->freq->active_delay) |
+		UTMIP_PLLU_STABLE_COUNT(phy->freq->stable_count);
+	writel(val, base + UTMIP_MISC_CFG1);
+
+	val = readl(base + UTMIP_PLL_CFG1);
+	val &= ~(UTMIP_XTAL_FREQ_COUNT(~0) | UTMIP_PLLU_ENABLE_DLY_COUNT(~0));
+	val |= UTMIP_XTAL_FREQ_COUNT(phy->freq->xtal_freq_count) |
+		UTMIP_PLLU_ENABLE_DLY_COUNT(phy->freq->enable_delay);
+	writel(val, base + UTMIP_PLL_CFG1);
+
+	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~(USB_WAKE_ON_CNNT_EN_DEV | USB_WAKE_ON_DISCON_EN_DEV);
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	utmip_pad_power_on(phy);
+
+	val = readl(base + UTMIP_XCVR_CFG0);
+	val &= ~(UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
+		 UTMIP_FORCE_PDZI_POWERDOWN | UTMIP_XCVR_SETUP(~0) |
+		 UTMIP_XCVR_LSFSLEW(~0) | UTMIP_XCVR_LSRSLEW(~0) |
+		 UTMIP_XCVR_HSSLEW_MSB(~0));
+	val |= UTMIP_XCVR_SETUP(config->xcvr_setup);
+	val |= UTMIP_XCVR_LSFSLEW(config->xcvr_lsfslew);
+	val |= UTMIP_XCVR_LSRSLEW(config->xcvr_lsrslew);
+	writel(val, base + UTMIP_XCVR_CFG0);
+
+	val = readl(base + UTMIP_XCVR_CFG1);
+	val &= ~(UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+		 UTMIP_FORCE_PDDR_POWERDOWN | UTMIP_XCVR_TERM_RANGE_ADJ(~0));
+	val |= UTMIP_XCVR_TERM_RANGE_ADJ(config->term_range_adj);
+	writel(val, base + UTMIP_XCVR_CFG1);
+
+	val = readl(base + UTMIP_BAT_CHRG_CFG0);
+	val &= ~UTMIP_PD_CHRG;
+	writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+	val = readl(base + UTMIP_BIAS_CFG1);
+	val &= ~UTMIP_BIAS_PDTRK_COUNT(~0);
+	val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
+	writel(val, base + UTMIP_BIAS_CFG1);
+
+	if (phy->instance == 0) {
+		val = readl(base + UTMIP_SPARE_CFG0);
+		if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
+			val &= ~FUSE_SETUP_SEL;
+		else
+			val |= FUSE_SETUP_SEL;
+		writel(val, base + UTMIP_SPARE_CFG0);
+	}
+
+	if (phy->instance == 2) {
+		val = readl(base + USB_SUSP_CTRL);
+		val |= UTMIP_PHY_ENABLE;
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	val = readl(base + USB_SUSP_CTRL);
+	val &= ~UTMIP_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	if (phy->instance == 0) {
+		val = readl(base + USB1_LEGACY_CTRL);
+		val &= ~USB1_VBUS_SENSE_CTL_MASK;
+		val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
+		writel(val, base + USB1_LEGACY_CTRL);
+
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_SUSP_SET;
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	utmi_phy_clk_enable(phy);
+
+	if (phy->instance == 2) {
+		val = readl(base + USB_PORTSC1);
+		val &= ~USB_PORTSC1_PTS(~0);
+		writel(val, base + USB_PORTSC1);
+	}
+
+	return 0;
+}
+
+static void utmi_phy_power_off(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	utmi_phy_clk_disable(phy);
+
+	if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE) {
+		val = readl(base + USB_SUSP_CTRL);
+		val &= ~USB_WAKEUP_DEBOUNCE_COUNT(~0);
+		val |= USB_WAKE_ON_CNNT_EN_DEV | USB_WAKEUP_DEBOUNCE_COUNT(5);
+		writel(val, base + USB_SUSP_CTRL);
+	}
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= UTMIP_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	val = readl(base + UTMIP_BAT_CHRG_CFG0);
+	val |= UTMIP_PD_CHRG;
+	writel(val, base + UTMIP_BAT_CHRG_CFG0);
+
+	val = readl(base + UTMIP_XCVR_CFG0);
+	val |= UTMIP_FORCE_PD_POWERDOWN | UTMIP_FORCE_PD2_POWERDOWN |
+	       UTMIP_FORCE_PDZI_POWERDOWN;
+	writel(val, base + UTMIP_XCVR_CFG0);
+
+	val = readl(base + UTMIP_XCVR_CFG1);
+	val |= UTMIP_FORCE_PDDISC_POWERDOWN | UTMIP_FORCE_PDCHRP_POWERDOWN |
+	       UTMIP_FORCE_PDDR_POWERDOWN;
+	writel(val, base + UTMIP_XCVR_CFG1);
+
+	utmip_pad_power_off(phy);
+}
+
+static void utmi_phy_preresume(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_TX_CFG0);
+	val |= UTMIP_HS_DISCON_DISABLE;
+	writel(val, base + UTMIP_TX_CFG0);
+}
+
+static void utmi_phy_postresume(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_TX_CFG0);
+	val &= ~UTMIP_HS_DISCON_DISABLE;
+	writel(val, base + UTMIP_TX_CFG0);
+}
+
+static void utmi_phy_restore_start(struct tegra_usb_phy *phy,
+				   enum tegra_usb_phy_port_speed port_speed)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val &= ~UTMIP_DPDM_OBSERVE_SEL(~0);
+	if (port_speed == TEGRA_USB_PHY_PORT_SPEED_LOW)
+		val |= UTMIP_DPDM_OBSERVE_SEL_FS_K;
+	else
+		val |= UTMIP_DPDM_OBSERVE_SEL_FS_J;
+	writel(val, base + UTMIP_MISC_CFG0);
+	udelay(1);
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val |= UTMIP_DPDM_OBSERVE;
+	writel(val, base + UTMIP_MISC_CFG0);
+	udelay(10);
+}
+
+static void utmi_phy_restore_end(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+
+	val = readl(base + UTMIP_MISC_CFG0);
+	val &= ~UTMIP_DPDM_OBSERVE;
+	writel(val, base + UTMIP_MISC_CFG0);
+	udelay(10);
+}
+
+static int ulpi_phy_power_on(struct tegra_usb_phy *phy)
+{
+	int ret;
+	unsigned long val;
+	void __iomem *base = phy->regs;
+	struct tegra_ulpi_config *config = phy->config;
+
+	gpio_direction_output(config->reset_gpio, 0);
+	msleep(5);
+	gpio_direction_output(config->reset_gpio, 1);
+
+	clk_enable(phy->clk);
+	msleep(1);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= UHSIC_RESET;
+	writel(val, base + USB_SUSP_CTRL);
+
+	val = readl(base + ULPI_TIMING_CTRL_0);
+	val |= ULPI_OUTPUT_PINMUX_BYP | ULPI_CLKOUT_PINMUX_BYP;
+	writel(val, base + ULPI_TIMING_CTRL_0);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= ULPI_PHY_ENABLE;
+	writel(val, base + USB_SUSP_CTRL);
+
+	val = 0;
+	writel(val, base + ULPI_TIMING_CTRL_1);
+
+	val |= ULPI_DATA_TRIMMER_SEL(4);
+	val |= ULPI_STPDIRNXT_TRIMMER_SEL(4);
+	val |= ULPI_DIR_TRIMMER_SEL(4);
+	writel(val, base + ULPI_TIMING_CTRL_1);
+	udelay(10);
+
+	val |= ULPI_DATA_TRIMMER_LOAD;
+	val |= ULPI_STPDIRNXT_TRIMMER_LOAD;
+	val |= ULPI_DIR_TRIMMER_LOAD;
+	writel(val, base + ULPI_TIMING_CTRL_1);
+
+	/* Fix VbusInvalid due to floating VBUS */
+	ret = otg_io_write(phy->ulpi, 0x40, 0x08);
+	if (ret) {
+		pr_err("%s: ulpi write failed\n", __func__);
+		return ret;
+	}
+
+	ret = otg_io_write(phy->ulpi, 0x80, 0x0B);
+	if (ret) {
+		pr_err("%s: ulpi write failed\n", __func__);
+		return ret;
+	}
+
+	val = readl(base + USB_PORTSC1);
+	val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
+	writel(val, base + USB_PORTSC1);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val |= USB_SUSP_CLR;
+	writel(val, base + USB_SUSP_CTRL);
+	udelay(100);
+
+	val = readl(base + USB_SUSP_CTRL);
+	val &= ~USB_SUSP_CLR;
+	writel(val, base + USB_SUSP_CTRL);
+
+	return 0;
+}
+
+static void ulpi_phy_power_off(struct tegra_usb_phy *phy)
+{
+	unsigned long val;
+	void __iomem *base = phy->regs;
+	struct tegra_ulpi_config *config = phy->config;
+
+	/* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
+	 * Controller to immediately bring the ULPI PHY out of low power
+	 */
+	val = readl(base + USB_PORTSC1);
+	val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
+	writel(val, base + USB_PORTSC1);
+
+	gpio_direction_output(config->reset_gpio, 0);
+	clk_disable(phy->clk);
+}
+
+struct tegra_usb_phy *tegra_usb_phy_open(int instance, void __iomem *regs,
+			void *config, enum tegra_usb_phy_mode phy_mode)
+{
+	struct tegra_usb_phy *phy;
+	struct tegra_ulpi_config *ulpi_config;
+	unsigned long parent_rate;
+	int i;
+	int err;
+
+	phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
+	if (!phy)
+		return ERR_PTR(-ENOMEM);
+
+	phy->instance = instance;
+	phy->regs = regs;
+	phy->config = config;
+	phy->mode = phy_mode;
+
+	if (!phy->config) {
+		if (phy_is_ulpi(phy)) {
+			pr_err("%s: ulpi phy configuration missing", __func__);
+			err = -EINVAL;
+			goto err0;
+		} else {
+			phy->config = &utmip_default[instance];
+		}
+	}
+
+	phy->pll_u = clk_get_sys(NULL, "pll_u");
+	if (IS_ERR(phy->pll_u)) {
+		pr_err("Can't get pll_u clock\n");
+		err = PTR_ERR(phy->pll_u);
+		goto err0;
+	}
+	clk_enable(phy->pll_u);
+
+	parent_rate = clk_get_rate(clk_get_parent(phy->pll_u));
+	for (i = 0; i < ARRAY_SIZE(tegra_freq_table); i++) {
+		if (tegra_freq_table[i].freq == parent_rate) {
+			phy->freq = &tegra_freq_table[i];
+			break;
+		}
+	}
+	if (!phy->freq) {
+		pr_err("invalid pll_u parent rate %ld\n", parent_rate);
+		err = -EINVAL;
+		goto err1;
+	}
+
+	if (phy_is_ulpi(phy)) {
+		ulpi_config = config;
+		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
+		if (IS_ERR(phy->clk)) {
+			pr_err("%s: can't get ulpi clock\n", __func__);
+			err = -ENXIO;
+			goto err1;
+		}
+		tegra_gpio_enable(ulpi_config->reset_gpio);
+		gpio_request(ulpi_config->reset_gpio, "ulpi_phy_reset_b");
+		gpio_direction_output(ulpi_config->reset_gpio, 0);
+		phy->ulpi = otg_ulpi_create(&ulpi_viewport_access_ops, 0);
+		phy->ulpi->io_priv = regs + ULPI_VIEWPORT;
+	} else {
+		err = utmip_pad_open(phy);
+		if (err < 0)
+			goto err1;
+	}
+
+	return phy;
+
+err1:
+	clk_disable(phy->pll_u);
+	clk_put(phy->pll_u);
+err0:
+	kfree(phy);
+	return ERR_PTR(err);
+}
+
+int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		return ulpi_phy_power_on(phy);
+	else
+		return utmi_phy_power_on(phy);
+}
+
+void tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		ulpi_phy_power_off(phy);
+	else
+		utmi_phy_power_off(phy);
+}
+
+void tegra_usb_phy_preresume(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_preresume(phy);
+}
+
+void tegra_usb_phy_postresume(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_postresume(phy);
+}
+
+void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
+				 enum tegra_usb_phy_port_speed port_speed)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_restore_start(phy, port_speed);
+}
+
+void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_restore_end(phy);
+}
+
+void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_clk_disable(phy);
+}
+
+void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
+{
+	if (!phy_is_ulpi(phy))
+		utmi_phy_clk_enable(phy);
+}
+
+void tegra_usb_phy_close(struct tegra_usb_phy *phy)
+{
+	if (phy_is_ulpi(phy))
+		clk_put(phy->clk);
+	else
+		utmip_pad_close(phy);
+	clk_disable(phy->pll_u);
+	clk_put(phy->pll_u);
+	kfree(phy);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-u300/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-u300/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -263,7 +263,7 @@
 	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 */
+	/* Deactivate VCXO if no one 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);
@@ -283,7 +283,7 @@
 	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 */
+	/* Deactivate VCXO if no one 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);
@@ -649,7 +649,7 @@
  */
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
-	/* TODO: get apropriate switches for EMIFCLK, AHBCLK and MCLK */
+	/* TODO: get appropriate switches for EMIFCLK, AHBCLK and MCLK */
 	/* Else default to fixed value */
 
 	if (clk->round_rate) {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-u300/core.c linux-libre-2.6.39-gnu/arch/arm/mach-u300/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  * arch/arm/mach-u300/core.c
  *
  *
- * Copyright (C) 2007-2010 ST-Ericsson AB
+ * Copyright (C) 2007-2010 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  * Core platform support, IRQ handling and device definitions.
  * Author: Linus Walleij <linus.walleij@stericsson.com>
@@ -16,7 +16,9 @@
 #include <linux/device.h>
 #include <linux/mm.h>
 #include <linux/termios.h>
+#include <linux/dmaengine.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/serial.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/clk.h>
@@ -96,10 +98,20 @@
  * Declaration of devices found on the U300 board and
  * their respective memory locations.
  */
+
+static struct amba_pl011_data uart0_plat_data = {
+#ifdef CONFIG_COH901318
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_UART0_RX,
+	.dma_tx_param = (void *) U300_DMA_UART0_TX,
+#endif
+};
+
 static struct amba_device uart0_device = {
 	.dev = {
+		.coherent_dma_mask = ~0,
 		.init_name = "uart0", /* Slow device at 0x3000 offset */
-		.platform_data = NULL,
+		.platform_data = &uart0_plat_data,
 	},
 	.res = {
 		.start = U300_UART0_BASE,
@@ -111,10 +123,19 @@
 
 /* The U335 have an additional UART1 on the APP CPU */
 #ifdef CONFIG_MACH_U300_BS335
+static struct amba_pl011_data uart1_plat_data = {
+#ifdef CONFIG_COH901318
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_UART1_RX,
+	.dma_tx_param = (void *) U300_DMA_UART1_TX,
+#endif
+};
+
 static struct amba_device uart1_device = {
 	.dev = {
+		.coherent_dma_mask = ~0,
 		.init_name = "uart1", /* Fast device at 0x7000 offset */
-		.platform_data = NULL,
+		.platform_data = &uart1_plat_data,
 	},
 	.res = {
 		.start = U300_UART1_BASE,
@@ -960,42 +981,37 @@
 		.priority_high = 0,
 		.dev_addr = U300_MSL_BASE + 6 * 0x40 + 0x220,
 	},
+	/*
+	 * Don't set up device address, burst count or size of src
+	 * or dst bus for this peripheral - handled by PrimeCell
+	 * DMA extension.
+	 */
 	{
 		.number = U300_DMA_MMCSD_RX_TX,
 		.name = "MMCSD RX TX",
 		.priority_high = 0,
-		.dev_addr =  U300_MMCSD_BASE + 0x080,
 		.param.config = COH901318_CX_CFG_CH_DISABLE |
 				COH901318_CX_CFG_LCR_DISABLE |
 				COH901318_CX_CFG_TC_IRQ_ENABLE |
 				COH901318_CX_CFG_BE_IRQ_ENABLE,
 		.param.ctrl_lli_chained = 0 |
 				COH901318_CX_CTRL_TC_ENABLE |
-				COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_ENABLE |
-				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
 				COH901318_CX_CTRL_HSP_ENABLE |
 				COH901318_CX_CTRL_HSS_DISABLE |
 				COH901318_CX_CTRL_DDMA_LEGACY,
 		.param.ctrl_lli = 0 |
 				COH901318_CX_CTRL_TC_ENABLE |
-				COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_ENABLE |
-				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
 				COH901318_CX_CTRL_HSP_ENABLE |
 				COH901318_CX_CTRL_HSS_DISABLE |
 				COH901318_CX_CTRL_DDMA_LEGACY,
 		.param.ctrl_lli_last = 0 |
 				COH901318_CX_CTRL_TC_ENABLE |
-				COH901318_CX_CTRL_BURST_COUNT_32_BYTES |
-				COH901318_CX_CTRL_SRC_BUS_SIZE_32_BITS |
-				COH901318_CX_CTRL_DST_BUS_SIZE_32_BITS |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_DISABLE |
 				COH901318_CX_CTRL_TC_IRQ_ENABLE |
@@ -1014,15 +1030,76 @@
 		.name = "MSPRO RX",
 		.priority_high = 0,
 	},
+	/*
+	 * Don't set up device address, burst count or size of src
+	 * or dst bus for this peripheral - handled by PrimeCell
+	 * DMA extension.
+	 */
 	{
 		.number = U300_DMA_UART0_TX,
 		.name = "UART0 TX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
 	},
 	{
 		.number = U300_DMA_UART0_RX,
 		.name = "UART0 RX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
 	},
 	{
 		.number = U300_DMA_APEX_TX,
@@ -1080,7 +1157,7 @@
 				COH901318_CX_CTRL_DST_ADDR_INC_DISABLE |
 				COH901318_CX_CTRL_MASTER_MODE_M1RW |
 				COH901318_CX_CTRL_TCP_ENABLE |
-				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
 				COH901318_CX_CTRL_HSP_ENABLE |
 				COH901318_CX_CTRL_HSS_DISABLE |
 				COH901318_CX_CTRL_DDMA_LEGACY |
@@ -1252,15 +1329,77 @@
 		.name = "XGAM PDI",
 		.priority_high = 0,
 	},
+	/*
+	 * Don't set up device address, burst count or size of src
+	 * or dst bus for this peripheral - handled by PrimeCell
+	 * DMA extension.
+	 */
 	{
 		.number = U300_DMA_SPI_TX,
 		.name = "SPI TX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
 	},
 	{
 		.number = U300_DMA_SPI_RX,
 		.name = "SPI RX",
 		.priority_high = 0,
+		.param.config = COH901318_CX_CFG_CH_DISABLE |
+				COH901318_CX_CFG_LCR_DISABLE |
+				COH901318_CX_CFG_TC_IRQ_ENABLE |
+				COH901318_CX_CFG_BE_IRQ_ENABLE,
+		.param.ctrl_lli_chained = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_DISABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+		.param.ctrl_lli_last = 0 |
+				COH901318_CX_CTRL_TC_ENABLE |
+				COH901318_CX_CTRL_MASTER_MODE_M1RW |
+				COH901318_CX_CTRL_TCP_DISABLE |
+				COH901318_CX_CTRL_TC_IRQ_ENABLE |
+				COH901318_CX_CTRL_HSP_ENABLE |
+				COH901318_CX_CTRL_HSS_DISABLE |
+				COH901318_CX_CTRL_DDMA_LEGACY,
+
 	},
 	{
 		.number = U300_DMA_GENERAL_PURPOSE_0,
@@ -1617,7 +1756,7 @@
 #endif
 #ifdef CONFIG_MACH_U300_BS335
 	if ((val & 0xFF00U) != 0xf000 && (val & 0xFF00U) != 0xf100) {
-		printk(KERN_ERR "Platform configured for BS365 " \
+		printk(KERN_ERR "Platform configured for BS335 " \
 		       " with DB3350 but %s detected, expect problems!",
 		       chipname);
 	}
@@ -1692,12 +1831,12 @@
 	/* Register subdevices on the I2C buses */
 	u300_i2c_register_board_devices();
 
-	/* Register subdevices on the SPI bus */
-	u300_spi_register_board_devices();
-
 	/* Register the platform devices */
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
+	/* Register subdevices on the SPI bus */
+	u300_spi_register_board_devices();
+
 #ifndef CONFIG_MACH_U300_SEMI_IS_SHARED
 	/*
 	 * Enable SEMI self refresh. Self-refresh of the SDRAM is entered when
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-u300/include/mach/coh901318.h linux-libre-2.6.39-gnu/arch/arm/mach-u300/include/mach/coh901318.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/include/mach/coh901318.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/include/mach/coh901318.h	2011-05-19 00:06:34.000000000 -0400
@@ -102,6 +102,7 @@
 	const int max_channels;
 };
 
+#ifdef CONFIG_COH901318
 /**
  * coh901318_filter_id() - DMA channel filter function
  * @chan: dma channel handle
@@ -110,6 +111,12 @@
  * In dma_request_channel() it specifies what channel id to be requested
  */
 bool coh901318_filter_id(struct dma_chan *chan, void *chan_id);
+#else
+static inline bool coh901318_filter_id(struct dma_chan *chan, void *chan_id)
+{
+	return false;
+}
+#endif
 
 /*
  * DMA Controller - this access the static mappings of the coh901318 dma.
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-u300/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-u300/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,17 +15,17 @@
 
 #ifdef CONFIG_MACH_U300_DUAL_RAM
 
-#define PHYS_OFFSET		UL(0x48000000)
+#define PLAT_PHYS_OFFSET		UL(0x48000000)
 #define BOOT_PARAMS_OFFSET	(PHYS_OFFSET + 0x100)
 
 #else
 
 #ifdef CONFIG_MACH_U300_2MB_ALIGNMENT_FIX
-#define PHYS_OFFSET (0x28000000 + \
+#define PLAT_PHYS_OFFSET (0x28000000 + \
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE - \
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
 #else
-#define PHYS_OFFSET (0x28000000 + \
+#define PLAT_PHYS_OFFSET (0x28000000 + \
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE +	\
 	     (CONFIG_MACH_U300_ACCESS_MEM_SIZE & 1))*1024*1024)
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-u300/mmc.c linux-libre-2.6.39-gnu/arch/arm/mach-u300/mmc.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/mmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,159 +3,52 @@
  * arch/arm/mach-u300/mmc.c
  *
  *
- * Copyright (C) 2009 ST-Ericsson AB
+ * Copyright (C) 2009 ST-Ericsson SA
  * License terms: GNU General Public License (GPL) version 2
  *
  * Author: Linus Walleij <linus.walleij@stericsson.com>
- * Author: Johan Lundin <johan.lundin@stericsson.com>
+ * Author: Johan Lundin
  * 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 <linux/dmaengine.h>
 #include <linux/amba/mmci.h>
 #include <linux/slab.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
 
 #include "mmc.h"
 #include "padmux.h"
 
-struct mmci_card_event {
-	struct input_dev *mmc_input;
-	int mmc_inserted;
-	struct work_struct workq;
-	struct mmci_platform_data mmc0_plat_data;
+static struct mmci_platform_data mmc0_plat_data = {
+	/*
+	 * Do not set ocr_mask or voltage translation function,
+	 * we have a regulator we can control instead.
+	 */
+	/* Nominally 2.85V on our platform */
+	.f_max = 24000000,
+	.gpio_wp = -1,
+	.gpio_cd = U300_GPIO_PIN_MMC_CD,
+	.cd_invert = true,
+	.capabilities = MMC_CAP_MMC_HIGHSPEED |
+	MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+#ifdef CONFIG_COH901318
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_MMCSD_RX_TX,
+	/* Don't specify a TX channel, this RX channel is bidirectional */
+#endif
 };
 
-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;
-}
-
-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 ? "inserted" : "removed");
-
-	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;
 	struct pmx *pmx;
 	int ret = 0;
 
-	mmci_card = kzalloc(sizeof(struct mmci_card_event), GFP_KERNEL);
-	if (!mmci_card)
-		return -ENOMEM;
-
-	/*
-	 * Do not set ocr_mask or voltage translation function,
-	 * we have a regulator we can control instead.
-	 */
-	/* Nominally 2.85V on our platform */
-	mmci_card->mmc0_plat_data.f_max = 24000000;
-	mmci_card->mmc0_plat_data.status = mmc_status;
-	mmci_card->mmc0_plat_data.gpio_wp = -1;
-	mmci_card->mmc0_plat_data.gpio_cd = -1;
-	mmci_card->mmc0_plat_data.capabilities = MMC_CAP_MMC_HIGHSPEED |
-		MMC_CAP_SD_HIGHSPEED | MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
-
-	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);
+	mmcsd_device->platform_data = &mmc0_plat_data;
 
 	/*
 	 * Setup padmuxing for MMC. Since this must always be
@@ -171,12 +64,5 @@
 			pr_warning("Could not activate padmuxing\n");
 	}
 
-	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.38-gnu/arch/arm/mach-u300/spi.c linux-libre-2.6.39-gnu/arch/arm/mach-u300/spi.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,9 @@
 #include <linux/spi/spi.h>
 #include <linux/amba/pl022.h>
 #include <linux/err.h>
+#include <mach/coh901318.h>
+#include <mach/dma_channels.h>
+
 #include "padmux.h"
 
 /*
@@ -30,11 +33,8 @@
 }
 
 struct pl022_config_chip dummy_chip_info = {
-	/*
-	 * available POLLING_TRANSFER and INTERRUPT_TRANSFER,
-	 * DMA_TRANSFER does not work
-	 */
-	.com_mode = INTERRUPT_TRANSFER,
+	/* available POLLING_TRANSFER, INTERRUPT_TRANSFER, DMA_TRANSFER */
+	.com_mode = DMA_TRANSFER,
 	.iface = SSP_INTERFACE_MOTOROLA_SPI,
 	/* We can only act as master but SSP_SLAVE is possible in theory */
 	.hierarchy = SSP_MASTER,
@@ -75,8 +75,6 @@
 static struct pl022_ssp_controller ssp_platform_data = {
 	/* If you have several SPI buses this varies, we have only bus 0 */
 	.bus_id = 0,
-	/* Set this to 1 when we think we got DMA working */
-	.enable_dma = 0,
 	/*
 	 * On the APP CPU GPIO 4, 5 and 6 are connected as generic
 	 * chip selects for SPI. (Same on U330, U335 and U365.)
@@ -84,6 +82,14 @@
 	 * and do padmuxing accordingly too.
 	 */
 	.num_chipselect = 3,
+#ifdef CONFIG_COH901318
+	.enable_dma = 1,
+	.dma_filter = coh901318_filter_id,
+	.dma_rx_param = (void *) U300_DMA_SPI_RX,
+	.dma_tx_param = (void *) U300_DMA_SPI_TX,
+#else
+	.enable_dma = 0,
+#endif
 };
 
 
@@ -109,6 +115,7 @@
 	}
 
 }
+
 void __init u300_spi_register_board_devices(void)
 {
 	/* Register any SPI devices */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-u300/u300.c linux-libre-2.6.39-gnu/arch/arm/mach-u300/u300.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-u300/u300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-u300/u300.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,9 +19,9 @@
 #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>
+#include <asm/memory.h>
 
 static void __init u300_reserve(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,72 +17,62 @@
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
 #include <linux/amba/pl022.h>
+#include <linux/amba/serial.h>
 #include <linux/spi/spi.h>
 #include <linux/mfd/ab8500.h>
+#include <linux/regulator/ab8500.h>
 #include <linux/mfd/tc3589x.h>
+#include <linux/mfd/tps6105x.h>
+#include <linux/mfd/ab8500/gpio.h>
+#include <linux/leds-lp5521.h>
+#include <linux/input.h>
+#include <linux/gpio_keys.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
-#include <plat/pincfg.h>
 #include <plat/i2c.h>
+#include <plat/ste_dma40.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
 #include <mach/irqs.h>
 
+#include "ste-dma40-db8500.h"
 #include "devices-db8500.h"
-#include "pins-db8500.h"
 #include "board-mop500.h"
 #include "board-mop500-regulators.h"
 
-static pin_cfg_t mop500_pins[] = {
-	/* SSP0 */
-	GPIO143_SSP0_CLK,
-	GPIO144_SSP0_FRM,
-	GPIO145_SSP0_RXD,
-	GPIO146_SSP0_TXD,
-
-	/* I2C */
-	GPIO147_I2C0_SCL,
-	GPIO148_I2C0_SDA,
-	GPIO16_I2C1_SCL,
-	GPIO17_I2C1_SDA,
-	GPIO10_I2C2_SDA,
-	GPIO11_I2C2_SCL,
-	GPIO229_I2C3_SDA,
-	GPIO230_I2C3_SCL,
-
-	/* SKE keypad */
-	GPIO153_KP_I7,
-	GPIO154_KP_I6,
-	GPIO155_KP_I5,
-	GPIO156_KP_I4,
-	GPIO157_KP_O7,
-	GPIO158_KP_O6,
-	GPIO159_KP_O5,
-	GPIO160_KP_O4,
-	GPIO161_KP_I3,
-	GPIO162_KP_I2,
-	GPIO163_KP_I1,
-	GPIO164_KP_I0,
-	GPIO165_KP_O3,
-	GPIO166_KP_O2,
-	GPIO167_KP_O1,
-	GPIO168_KP_O0,
-
-	/* GPIO_EXP_INT */
-	GPIO217_GPIO,
-
-	/* STMPE1601 IRQ */
-	GPIO218_GPIO    | PIN_INPUT_PULLUP,
+static struct ab8500_gpio_platform_data ab8500_gpio_pdata = {
+	.gpio_base		= MOP500_AB8500_GPIO(0),
+	.irq_base		= MOP500_AB8500_VIR_GPIO_IRQ_BASE,
+	/* config_reg is the initial configuration of ab8500 pins.
+	 * The pins can be configured as GPIO or alt functions based
+	 * on value present in GpioSel1 to GpioSel6 and AlternatFunction
+	 * register. This is the array of 7 configuration settings.
+	 * One has to compile time decide these settings. Below is the
+	 * explanation of these setting
+	 * GpioSel1 = 0x00 => Pins GPIO1 to GPIO8 are not used as GPIO
+	 * GpioSel2 = 0x1E => Pins GPIO10 to GPIO13 are configured as GPIO
+	 * GpioSel3 = 0x80 => Pin GPIO24 is configured as GPIO
+	 * GpioSel4 = 0x01 => Pin GPIo25 is configured as GPIO
+	 * GpioSel5 = 0x7A => Pins GPIO34, GPIO36 to GPIO39 are conf as GPIO
+	 * GpioSel6 = 0x00 => Pins GPIO41 & GPIo42 are not configured as GPIO
+	 * AlternaFunction = 0x00 => If Pins GPIO10 to 13 are not configured
+	 * as GPIO then this register selectes the alternate fucntions
+	 */
+	.config_reg		= {0x00, 0x1E, 0x80, 0x01,
+					0x7A, 0x00, 0x00},
 };
 
 static struct ab8500_platform_data ab8500_platdata = {
 	.irq_base	= MOP500_AB8500_IRQ_BASE,
+	.regulator_reg_init = ab8500_regulator_reg_init,
+	.num_regulator_reg_init	= ARRAY_SIZE(ab8500_regulator_reg_init),
 	.regulator	= ab8500_regulators,
 	.num_regulator	= ARRAY_SIZE(ab8500_regulators),
+	.gpio		= &ab8500_gpio_pdata,
 };
 
 static struct resource ab8500_resources[] = {
@@ -103,14 +93,13 @@
 	.resource = ab8500_resources,
 };
 
-static struct pl022_ssp_controller ssp0_platform_data = {
-	.bus_id = 0,
-	/* pl022 not yet supports dma */
-	.enable_dma = 0,
-	/* on this platform, gpio 31,142,144,214 &
-	 * 224 are connected as chip selects
-	 */
-	.num_chipselect = 5,
+/*
+ * TPS61052
+ */
+
+static struct tps6105x_platform_data mop500_tps61052_data = {
+	.mode = TPS6105X_MODE_VOLTAGE,
+	.regulator_data = &tps61052_regulator,
 };
 
 /*
@@ -133,12 +122,86 @@
 	.irq_base	= MOP500_EGPIO_IRQ_BASE,
 };
 
-static struct i2c_board_info mop500_i2c0_devices[] = {
+static struct lp5521_led_config lp5521_pri_led[] = {
+       [0] = {
+	       .chan_nr = 0,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [1] = {
+	       .chan_nr = 1,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [2] = {
+	       .chan_nr = 2,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+};
+
+static struct lp5521_platform_data __initdata lp5521_pri_data = {
+       .label = "lp5521_pri",
+       .led_config     = &lp5521_pri_led[0],
+       .num_channels   = 3,
+       .clock_mode     = LP5521_CLOCK_EXT,
+};
+
+static struct lp5521_led_config lp5521_sec_led[] = {
+       [0] = {
+	       .chan_nr = 0,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [1] = {
+	       .chan_nr = 1,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+       [2] = {
+	       .chan_nr = 2,
+	       .led_current = 0x2f,
+	       .max_current = 0x5f,
+       },
+};
+
+static struct lp5521_platform_data __initdata lp5521_sec_data = {
+       .label = "lp5521_sec",
+       .led_config     = &lp5521_sec_led[0],
+       .num_channels   = 3,
+       .clock_mode     = LP5521_CLOCK_EXT,
+};
+
+static struct i2c_board_info __initdata mop500_i2c0_devices[] = {
 	{
 		I2C_BOARD_INFO("tc3589x", 0x42),
-		.irq            = NOMADIK_GPIO_TO_IRQ(217),
+		.irq		= NOMADIK_GPIO_TO_IRQ(217),
 		.platform_data  = &mop500_tc35892_data,
 	},
+	/* I2C0 devices only available prior to HREFv60 */
+	{
+		I2C_BOARD_INFO("tps61052", 0x33),
+		.platform_data  = &mop500_tps61052_data,
+	},
+};
+
+#define NUM_PRE_V60_I2C0_DEVICES 1
+
+static struct i2c_board_info __initdata mop500_i2c2_devices[] = {
+	{
+		/* lp5521 LED driver, 1st device */
+		I2C_BOARD_INFO("lp5521", 0x33),
+		.platform_data = &lp5521_pri_data,
+	},
+	{
+		/* lp5521 LED driver, 2st device */
+		I2C_BOARD_INFO("lp5521", 0x34),
+		.platform_data = &lp5521_sec_data,
+	},
+	{
+		/* Light sensor Rohm BH1780GLI */
+		I2C_BOARD_INFO("bh1780", 0x29),
+	},
 };
 
 #define U8500_I2C_CONTROLLER(id, _slsu, _tft, _rft, clk, _sm) \
@@ -178,8 +241,93 @@
 	db8500_add_i2c3(&u8500_i2c3_data);
 }
 
+static struct gpio_keys_button mop500_gpio_keys[] = {
+	{
+		.desc			= "SFH7741 Proximity Sensor",
+		.type			= EV_SW,
+		.code			= SW_FRONT_PROXIMITY,
+		.active_low		= 0,
+		.can_disable		= 1,
+	}
+};
+
+static struct regulator *prox_regulator;
+static int mop500_prox_activate(struct device *dev);
+static void mop500_prox_deactivate(struct device *dev);
+
+static struct gpio_keys_platform_data mop500_gpio_keys_data = {
+	.buttons	= mop500_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(mop500_gpio_keys),
+	.enable		= mop500_prox_activate,
+	.disable	= mop500_prox_deactivate,
+};
+
+static struct platform_device mop500_gpio_keys_device = {
+	.name	= "gpio-keys",
+	.id	= 0,
+	.dev	= {
+		.platform_data	= &mop500_gpio_keys_data,
+	},
+};
+
+static int mop500_prox_activate(struct device *dev)
+{
+	prox_regulator = regulator_get(&mop500_gpio_keys_device.dev,
+						"vcc");
+	if (IS_ERR(prox_regulator)) {
+		dev_err(&mop500_gpio_keys_device.dev,
+			"no regulator\n");
+		return PTR_ERR(prox_regulator);
+	}
+	regulator_enable(prox_regulator);
+	return 0;
+}
+
+static void mop500_prox_deactivate(struct device *dev)
+{
+	regulator_disable(prox_regulator);
+	regulator_put(prox_regulator);
+}
+
 /* add any platform devices here - TODO */
 static struct platform_device *platform_devs[] __initdata = {
+	&mop500_gpio_keys_device,
+};
+
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg ssp0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV8_SSP0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg ssp0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV8_SSP0_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+#endif
+
+static struct pl022_ssp_controller ssp0_platform_data = {
+	.bus_id = 0,
+#ifdef CONFIG_STE_DMA40
+	.enable_dma = 1,
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &ssp0_dma_cfg_rx,
+	.dma_tx_param = &ssp0_dma_cfg_tx,
+#else
+	.enable_dma = 0,
+#endif
+	/* on this platform, gpio 31,142,144,214 &
+	 * 224 are connected as chip selects
+	 */
+	.num_chipselect = 5,
 };
 
 static void __init mop500_spi_init(void)
@@ -187,18 +335,110 @@
 	db8500_add_ssp0(&ssp0_platform_data);
 }
 
+#ifdef CONFIG_STE_DMA40
+static struct stedma40_chan_cfg uart0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV13_UART0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV13_UART0_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart1_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV12_UART1_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart1_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV12_UART1_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart2_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV11_UART2_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+
+static struct stedma40_chan_cfg uart2_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV11_UART2_TX,
+	.src_info.data_width = STEDMA40_BYTE_WIDTH,
+	.dst_info.data_width = STEDMA40_BYTE_WIDTH,
+};
+#endif
+
+static struct amba_pl011_data uart0_plat = {
+#ifdef CONFIG_STE_DMA40
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &uart0_dma_cfg_rx,
+	.dma_tx_param = &uart0_dma_cfg_tx,
+#endif
+};
+
+static struct amba_pl011_data uart1_plat = {
+#ifdef CONFIG_STE_DMA40
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &uart1_dma_cfg_rx,
+	.dma_tx_param = &uart1_dma_cfg_tx,
+#endif
+};
+
+static struct amba_pl011_data uart2_plat = {
+#ifdef CONFIG_STE_DMA40
+	.dma_filter = stedma40_filter,
+	.dma_rx_param = &uart2_dma_cfg_rx,
+	.dma_tx_param = &uart2_dma_cfg_tx,
+#endif
+};
+
 static void __init mop500_uart_init(void)
 {
-	db8500_add_uart0();
-	db8500_add_uart1();
-	db8500_add_uart2();
+	db8500_add_uart0(&uart0_plat);
+	db8500_add_uart1(&uart1_plat);
+	db8500_add_uart2(&uart2_plat);
 }
 
-static void __init u8500_init_machine(void)
+static void __init mop500_init_machine(void)
 {
+	int i2c0_devs;
+
+	/*
+	 * The HREFv60 board removed a GPIO expander and routed
+	 * all these GPIO pins to the internal GPIO controller
+	 * instead.
+	 */
+	if (machine_is_hrefv60())
+		mop500_gpio_keys[0].gpio = HREFV60_PROX_SENSE_GPIO;
+	else
+		mop500_gpio_keys[0].gpio = GPIO_PROX_SENSOR;
+
 	u8500_init_devices();
 
-	nmk_config_pins(mop500_pins, ARRAY_SIZE(mop500_pins));
+	mop500_pins_init();
 
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
 
@@ -207,12 +447,15 @@
 	mop500_spi_init();
 	mop500_uart_init();
 
-	mop500_keypad_init();
-
 	platform_device_register(&ab8500_device);
 
-	i2c_register_board_info(0, mop500_i2c0_devices,
-				ARRAY_SIZE(mop500_i2c0_devices));
+	i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
+	if (machine_is_hrefv60())
+		i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
+
+	i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
+	i2c_register_board_info(2, mop500_i2c2_devices,
+				ARRAY_SIZE(mop500_i2c2_devices));
 }
 
 MACHINE_START(U8500, "ST-Ericsson MOP500 platform")
@@ -222,5 +465,13 @@
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
 	.timer		= &ux500_timer,
-	.init_machine	= u8500_init_machine,
+	.init_machine	= mop500_init_machine,
+MACHINE_END
+
+MACHINE_START(HREFV60, "ST-Ericsson U8500 Platform HREFv60+")
+	.boot_params	= 0x100,
+	.map_io		= u8500_map_io,
+	.init_irq	= ux500_init_irq,
+	.timer		= &ux500_timer,
+	.init_machine	= mop500_init_machine,
 MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,15 +7,40 @@
 #ifndef __BOARD_MOP500_H
 #define __BOARD_MOP500_H
 
-#define MOP500_EGPIO(x)			(NOMADIK_NR_GPIO + (x))
+/* HREFv60-specific GPIO assignments, this board has no GPIO expander */
+#define HREFV60_TOUCH_RST_GPIO		143
+#define HREFV60_PROX_SENSE_GPIO		217
+#define HREFV60_HAL_SW_GPIO		145
+#define HREFV60_SDMMC_EN_GPIO		169
+#define HREFV60_SDMMC_1V8_3V_GPIO	5
+#define HREFV60_SDMMC_CD_GPIO		95
+#define HREFV60_ACCEL_INT1_GPIO		82
+#define HREFV60_ACCEL_INT2_GPIO		83
+#define HREFV60_MAGNET_DRDY_GPIO	32
+#define HREFV60_DISP1_RST_GPIO		65
+#define HREFV60_DISP2_RST_GPIO		66
 
 /* GPIOs on the TC35892 expander */
+#define MOP500_EGPIO(x)			(NOMADIK_NR_GPIO + (x))
 #define GPIO_SDMMC_CD			MOP500_EGPIO(3)
+#define GPIO_PROX_SENSOR		MOP500_EGPIO(7)
+#define GPIO_BU21013_CS			MOP500_EGPIO(13)
 #define GPIO_SDMMC_EN			MOP500_EGPIO(17)
 #define GPIO_SDMMC_1V8_3V_SEL		MOP500_EGPIO(18)
+#define MOP500_EGPIO_END		MOP500_EGPIO(24)
+
+/* GPIOs on the AB8500 mixed-signals circuit */
+#define MOP500_AB8500_GPIO(x)		(MOP500_EGPIO_END + (x))
+
+struct i2c_board_info;
 
 extern void mop500_sdi_init(void);
 extern void mop500_sdi_tc35892_init(void);
-extern void mop500_keypad_init(void);
+void __init mop500_u8500uib_init(void);
+void __init mop500_stuib_init(void);
+void __init mop500_pins_init(void);
+
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
+		unsigned n);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-keypads.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-keypads.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-keypads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-keypads.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,229 +0,0 @@
-/*
- * Copyright (C) ST-Ericsson SA 2010
- *
- * License Terms: GNU General Public License v2
- *
- * Keypad layouts for various boards
- */
-
-#include <linux/i2c.h>
-#include <linux/gpio.h>
-#include <linux/interrupt.h>
-#include <linux/platform_device.h>
-#include <linux/mfd/stmpe.h>
-#include <linux/mfd/tc3589x.h>
-#include <linux/input/matrix_keypad.h>
-
-#include <plat/pincfg.h>
-#include <plat/ske.h>
-
-#include <mach/devices.h>
-#include <mach/hardware.h>
-
-#include "devices-db8500.h"
-#include "board-mop500.h"
-
-/* STMPE/SKE keypad use this key layout */
-static const unsigned int mop500_keymap[] = {
-	KEY(2, 5, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(3, 5, KEY_VOLUMEDOWN),
-	KEY(1, 3, KEY_3),
-	KEY(5, 2, KEY_RIGHT),
-	KEY(5, 0, KEY_9),
-
-	KEY(0, 5, KEY_MENU),
-	KEY(7, 6, KEY_ENTER),
-	KEY(4, 5, KEY_0),
-	KEY(6, 7, KEY_2),
-	KEY(3, 4, KEY_UP),
-	KEY(3, 3, KEY_DOWN),
-
-	KEY(6, 4, KEY_SEND),
-	KEY(6, 2, KEY_BACK),
-	KEY(4, 2, KEY_VOLUMEUP),
-	KEY(5, 5, KEY_1),
-	KEY(4, 3, KEY_LEFT),
-	KEY(3, 2, KEY_7),
-};
-
-static const struct matrix_keymap_data mop500_keymap_data = {
-	.keymap		= mop500_keymap,
-	.keymap_size    = ARRAY_SIZE(mop500_keymap),
-};
-
-/*
- * Nomadik SKE keypad
- */
-#define ROW_PIN_I0      164
-#define ROW_PIN_I1      163
-#define ROW_PIN_I2      162
-#define ROW_PIN_I3      161
-#define ROW_PIN_I4      156
-#define ROW_PIN_I5      155
-#define ROW_PIN_I6      154
-#define ROW_PIN_I7      153
-#define COL_PIN_O0      168
-#define COL_PIN_O1      167
-#define COL_PIN_O2      166
-#define COL_PIN_O3      165
-#define COL_PIN_O4      160
-#define COL_PIN_O5      159
-#define COL_PIN_O6      158
-#define COL_PIN_O7      157
-
-#define SKE_KPD_MAX_ROWS	8
-#define SKE_KPD_MAX_COLS	8
-
-static int ske_kp_rows[] = {
-	ROW_PIN_I0, ROW_PIN_I1, ROW_PIN_I2, ROW_PIN_I3,
-	ROW_PIN_I4, ROW_PIN_I5, ROW_PIN_I6, ROW_PIN_I7,
-};
-
-/*
- * ske_set_gpio_row: request and set gpio rows
- */
-static int ske_set_gpio_row(int gpio)
-{
-	int ret;
-
-	ret = gpio_request(gpio, "ske-kp");
-	if (ret < 0) {
-		pr_err("ske_set_gpio_row: gpio request failed\n");
-		return ret;
-	}
-
-	ret = gpio_direction_output(gpio, 1);
-	if (ret < 0) {
-		pr_err("ske_set_gpio_row: gpio direction failed\n");
-		gpio_free(gpio);
-	}
-
-	return ret;
-}
-
-/*
- * ske_kp_init - enable the gpio configuration
- */
-static int ske_kp_init(void)
-{
-	int ret, i;
-
-	for (i = 0; i < SKE_KPD_MAX_ROWS; i++) {
-		ret = ske_set_gpio_row(ske_kp_rows[i]);
-		if (ret < 0) {
-			pr_err("ske_kp_init: failed init\n");
-			return ret;
-		}
-	}
-
-	return 0;
-}
-
-static struct ske_keypad_platform_data ske_keypad_board = {
-	.init		= ske_kp_init,
-	.keymap_data    = &mop500_keymap_data,
-	.no_autorepeat  = true,
-	.krow		= SKE_KPD_MAX_ROWS,     /* 8x8 matrix */
-	.kcol		= SKE_KPD_MAX_COLS,
-	.debounce_ms    = 40,			/* in millisecs */
-};
-
-/*
- * STMPE1601
- */
-static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
-	.debounce_ms    = 64,
-	.scan_count     = 8,
-	.no_autorepeat  = true,
-	.keymap_data    = &mop500_keymap_data,
-};
-
-static struct stmpe_platform_data stmpe1601_data = {
-	.id             = 1,
-	.blocks         = STMPE_BLOCK_KEYPAD,
-	.irq_trigger    = IRQF_TRIGGER_FALLING,
-	.irq_base       = MOP500_STMPE1601_IRQ(0),
-	.keypad         = &stmpe1601_keypad_data,
-	.autosleep      = true,
-	.autosleep_timeout = 1024,
-};
-
-static struct i2c_board_info mop500_i2c0_devices_stuib[] = {
-	{
-		I2C_BOARD_INFO("stmpe1601", 0x40),
-		.irq = NOMADIK_GPIO_TO_IRQ(218),
-		.platform_data = &stmpe1601_data,
-		.flags = I2C_CLIENT_WAKE,
-	},
-};
-
-/*
- * TC35893
- */
-
-static const unsigned int uib_keymap[] = {
-	KEY(3, 1, KEY_END),
-	KEY(4, 1, KEY_POWER),
-	KEY(6, 4, KEY_VOLUMEDOWN),
-	KEY(4, 2, KEY_EMAIL),
-	KEY(3, 3, KEY_RIGHT),
-	KEY(2, 5, KEY_BACKSPACE),
-
-	KEY(6, 7, KEY_MENU),
-	KEY(5, 0, KEY_ENTER),
-	KEY(4, 3, KEY_0),
-	KEY(3, 4, KEY_DOT),
-	KEY(5, 2, KEY_UP),
-	KEY(3, 5, KEY_DOWN),
-
-	KEY(4, 5, KEY_SEND),
-	KEY(0, 5, KEY_BACK),
-	KEY(6, 2, KEY_VOLUMEUP),
-	KEY(1, 3, KEY_SPACE),
-	KEY(7, 6, KEY_LEFT),
-	KEY(5, 5, KEY_SEARCH),
-};
-
-static struct matrix_keymap_data uib_keymap_data = {
-	.keymap         = uib_keymap,
-	.keymap_size    = ARRAY_SIZE(uib_keymap),
-};
-
-static struct tc3589x_keypad_platform_data tc35893_data = {
-	.krow = TC_KPD_ROWS,
-	.kcol = TC_KPD_COLUMNS,
-	.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
-	.settle_time = TC_KPD_SETTLE_TIME,
-	.irqtype = IRQF_TRIGGER_FALLING,
-	.enable_wakeup = true,
-	.keymap_data    = &uib_keymap_data,
-	.no_autorepeat  = true,
-};
-
-static struct tc3589x_platform_data tc3589x_keypad_data = {
-	.block = TC3589x_BLOCK_KEYPAD,
-	.keypad = &tc35893_data,
-	.irq_base = MOP500_EGPIO_IRQ_BASE,
-};
-
-static struct i2c_board_info mop500_i2c0_devices_uib[] = {
-	{
-		I2C_BOARD_INFO("tc3589x", 0x44),
-		.platform_data = &tc3589x_keypad_data,
-		.irq = NOMADIK_GPIO_TO_IRQ(218),
-		.flags = I2C_CLIENT_WAKE,
-	},
-};
-
-void mop500_keypad_init(void)
-{
-	db8500_add_ske_keypad(&ske_keypad_board);
-
-	i2c_register_board_info(0, mop500_i2c0_devices_stuib,
-			ARRAY_SIZE(mop500_i2c0_devices_stuib));
-
-	i2c_register_board_info(0, mop500_i2c0_devices_uib,
-			ARRAY_SIZE(mop500_i2c0_devices_uib));
-
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-pins.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-pins.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-pins.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-pins.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <plat/pincfg.h>
+#include <mach/hardware.h>
+
+#include "pins-db8500.h"
+
+static pin_cfg_t mop500_pins_common[] = {
+	/* I2C */
+	GPIO147_I2C0_SCL,
+	GPIO148_I2C0_SDA,
+	GPIO16_I2C1_SCL,
+	GPIO17_I2C1_SDA,
+	GPIO10_I2C2_SDA,
+	GPIO11_I2C2_SCL,
+	GPIO229_I2C3_SDA,
+	GPIO230_I2C3_SCL,
+
+	/* MSP0 */
+	GPIO12_MSP0_TXD,
+	GPIO13_MSP0_TFS,
+	GPIO14_MSP0_TCK,
+	GPIO15_MSP0_RXD,
+
+	/* MSP2: HDMI */
+	GPIO193_MSP2_TXD,
+	GPIO194_MSP2_TCK,
+	GPIO195_MSP2_TFS,
+	GPIO196_MSP2_RXD | PIN_OUTPUT_LOW,
+
+	/* Touch screen INTERFACE */
+	GPIO84_GPIO	| PIN_INPUT_PULLUP, /* TOUCH_INT1 */
+
+	/* STMPE1601/tc35893 keypad  IRQ */
+	GPIO218_GPIO	| PIN_INPUT_PULLUP,
+
+	/* MMC0 (MicroSD card) */
+	GPIO18_MC0_CMDDIR	| PIN_OUTPUT_HIGH,
+	GPIO19_MC0_DAT0DIR	| PIN_OUTPUT_HIGH,
+	GPIO20_MC0_DAT2DIR	| PIN_OUTPUT_HIGH,
+
+	GPIO22_MC0_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO23_MC0_CLK		| PIN_OUTPUT_LOW,
+	GPIO24_MC0_CMD		| PIN_INPUT_PULLUP,
+	GPIO25_MC0_DAT0		| PIN_INPUT_PULLUP,
+	GPIO26_MC0_DAT1		| PIN_INPUT_PULLUP,
+	GPIO27_MC0_DAT2		| PIN_INPUT_PULLUP,
+	GPIO28_MC0_DAT3		| PIN_INPUT_PULLUP,
+
+	/* SDI1 (SDIO) */
+	GPIO208_MC1_CLK		| PIN_OUTPUT_LOW,
+	GPIO209_MC1_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO210_MC1_CMD		| PIN_INPUT_PULLUP,
+	GPIO211_MC1_DAT0	| PIN_INPUT_PULLUP,
+	GPIO212_MC1_DAT1	| PIN_INPUT_PULLUP,
+	GPIO213_MC1_DAT2	| PIN_INPUT_PULLUP,
+	GPIO214_MC1_DAT3	| PIN_INPUT_PULLUP,
+
+	/* MMC2 (On-board DATA INTERFACE eMMC) */
+	GPIO128_MC2_CLK		| PIN_OUTPUT_LOW,
+	GPIO129_MC2_CMD		| PIN_INPUT_PULLUP,
+	GPIO130_MC2_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO131_MC2_DAT0	| PIN_INPUT_PULLUP,
+	GPIO132_MC2_DAT1	| PIN_INPUT_PULLUP,
+	GPIO133_MC2_DAT2	| PIN_INPUT_PULLUP,
+	GPIO134_MC2_DAT3	| PIN_INPUT_PULLUP,
+	GPIO135_MC2_DAT4	| PIN_INPUT_PULLUP,
+	GPIO136_MC2_DAT5	| PIN_INPUT_PULLUP,
+	GPIO137_MC2_DAT6	| PIN_INPUT_PULLUP,
+	GPIO138_MC2_DAT7	| PIN_INPUT_PULLUP,
+
+	/* MMC4 (On-board STORAGE INTERFACE eMMC) */
+	GPIO197_MC4_DAT3	| PIN_INPUT_PULLUP,
+	GPIO198_MC4_DAT2	| PIN_INPUT_PULLUP,
+	GPIO199_MC4_DAT1	| PIN_INPUT_PULLUP,
+	GPIO200_MC4_DAT0	| PIN_INPUT_PULLUP,
+	GPIO201_MC4_CMD		| PIN_INPUT_PULLUP,
+	GPIO202_MC4_FBCLK	| PIN_INPUT_NOPULL,
+	GPIO203_MC4_CLK		| PIN_OUTPUT_LOW,
+	GPIO204_MC4_DAT7	| PIN_INPUT_PULLUP,
+	GPIO205_MC4_DAT6	| PIN_INPUT_PULLUP,
+	GPIO206_MC4_DAT5	| PIN_INPUT_PULLUP,
+	GPIO207_MC4_DAT4	| PIN_INPUT_PULLUP,
+
+	/* SKE keypad */
+	GPIO153_KP_I7,
+	GPIO154_KP_I6,
+	GPIO155_KP_I5,
+	GPIO156_KP_I4,
+	GPIO157_KP_O7,
+	GPIO158_KP_O6,
+	GPIO159_KP_O5,
+	GPIO160_KP_O4,
+	GPIO161_KP_I3,
+	GPIO162_KP_I2,
+	GPIO163_KP_I1,
+	GPIO164_KP_I0,
+	GPIO165_KP_O3,
+	GPIO166_KP_O2,
+	GPIO167_KP_O1,
+	GPIO168_KP_O0,
+
+	/* UART */
+	GPIO0_U0_CTSn	| PIN_INPUT_PULLUP,
+	GPIO1_U0_RTSn	| PIN_OUTPUT_HIGH,
+	GPIO2_U0_RXD	| PIN_INPUT_PULLUP,
+	GPIO3_U0_TXD	| PIN_OUTPUT_HIGH,
+
+	GPIO29_U2_RXD	| PIN_INPUT_PULLUP,
+	GPIO30_U2_TXD	| PIN_OUTPUT_HIGH,
+	GPIO31_U2_CTSn	| PIN_INPUT_PULLUP,
+	GPIO32_U2_RTSn	| PIN_OUTPUT_HIGH,
+
+	/* Display & HDMI HW sync */
+	GPIO68_LCD_VSI0	| PIN_INPUT_PULLUP,
+	GPIO69_LCD_VSI1	| PIN_INPUT_PULLUP,
+};
+
+static pin_cfg_t mop500_pins_default[] = {
+	/* SSP0 */
+	GPIO143_SSP0_CLK,
+	GPIO144_SSP0_FRM,
+	GPIO145_SSP0_RXD | PIN_PULL_DOWN,
+	GPIO146_SSP0_TXD,
+
+
+	GPIO217_GPIO	| PIN_INPUT_PULLUP, /* TC35892 IRQ */
+
+	/* SDI0 (MicroSD card) */
+	GPIO21_MC0_DAT31DIR	| PIN_OUTPUT_HIGH,
+
+	/* UART */
+	GPIO4_U1_RXD	| PIN_INPUT_PULLUP,
+	GPIO5_U1_TXD	| PIN_OUTPUT_HIGH,
+	GPIO6_U1_CTSn	| PIN_INPUT_PULLUP,
+	GPIO7_U1_RTSn	| PIN_OUTPUT_HIGH,
+};
+
+static pin_cfg_t mop500_pins_hrefv60[] = {
+	/* WLAN */
+	GPIO4_GPIO		| PIN_INPUT_PULLUP,/* WLAN_IRQ */
+	GPIO85_GPIO		| PIN_OUTPUT_LOW,/* WLAN_ENA */
+
+	/* XENON Flashgun INTERFACE */
+	GPIO6_IP_GPIO0	| PIN_INPUT_PULLUP,/* XENON_FLASH_ID */
+	GPIO7_IP_GPIO1	| PIN_INPUT_PULLUP,/* XENON_READY */
+	GPIO170_GPIO	| PIN_OUTPUT_LOW, /* XENON_CHARGE */
+
+	/* Assistant LED INTERFACE */
+	GPIO21_GPIO | PIN_OUTPUT_LOW,  /* XENON_EN1 */
+	GPIO64_IP_GPIO4 | PIN_OUTPUT_LOW,  /* XENON_EN2 */
+
+	/* Magnetometer */
+	GPIO31_GPIO | PIN_INPUT_PULLUP,  /* magnetometer_INT */
+	GPIO32_GPIO | PIN_INPUT_PULLDOWN, /* Magnetometer DRDY */
+
+	/* Display Interface */
+	GPIO65_GPIO		| PIN_OUTPUT_LOW, /* DISP1 RST */
+	GPIO66_GPIO		| PIN_OUTPUT_LOW, /* DISP2 RST */
+
+	/* Touch screen INTERFACE */
+	GPIO143_GPIO	| PIN_OUTPUT_LOW,/*TOUCH_RST1 */
+
+	/* Touch screen INTERFACE 2 */
+	GPIO67_GPIO	| PIN_INPUT_PULLUP, /* TOUCH_INT2 */
+	GPIO146_GPIO	| PIN_OUTPUT_LOW,/*TOUCH_RST2 */
+
+	/* ETM_PTM_TRACE INTERFACE */
+	GPIO70_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA23 */
+	GPIO71_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA22 */
+	GPIO72_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA21 */
+	GPIO73_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA20 */
+	GPIO74_GPIO	| PIN_OUTPUT_LOW,/* ETM_PTM_DATA19 */
+
+	/* NAHJ INTERFACE */
+	GPIO76_GPIO	| PIN_OUTPUT_LOW,/* NAHJ_CTRL */
+	GPIO216_GPIO	| PIN_OUTPUT_HIGH,/* NAHJ_CTRL_INV */
+
+	/* NFC INTERFACE */
+	GPIO77_GPIO	| PIN_OUTPUT_LOW, /* NFC_ENA */
+	GPIO144_GPIO	| PIN_INPUT_PULLDOWN, /* NFC_IRQ */
+	GPIO142_GPIO	| PIN_OUTPUT_LOW, /* NFC_RESET */
+
+	/* Keyboard MATRIX INTERFACE */
+	GPIO90_MC5_CMD	| PIN_OUTPUT_LOW, /* KP_O_1 */
+	GPIO87_MC5_DAT1	| PIN_OUTPUT_LOW, /* KP_O_2 */
+	GPIO86_MC5_DAT0	| PIN_OUTPUT_LOW, /* KP_O_3 */
+	GPIO96_KP_O6	| PIN_OUTPUT_LOW, /* KP_O_6 */
+	GPIO94_KP_O7	| PIN_OUTPUT_LOW, /* KP_O_7 */
+	GPIO93_MC5_DAT4	| PIN_INPUT_PULLUP, /* KP_I_0 */
+	GPIO89_MC5_DAT3	| PIN_INPUT_PULLUP, /* KP_I_2 */
+	GPIO88_MC5_DAT2	| PIN_INPUT_PULLUP, /* KP_I_3 */
+	GPIO91_GPIO	| PIN_INPUT_PULLUP, /* FORCE_SENSING_INT */
+	GPIO92_GPIO	| PIN_OUTPUT_LOW, /* FORCE_SENSING_RST */
+	GPIO97_GPIO	| PIN_OUTPUT_LOW, /* FORCE_SENSING_WU */
+
+	/* DiPro Sensor Interface */
+	GPIO139_GPIO	| PIN_INPUT_PULLUP, /* DIPRO_INT */
+
+	/* HAL SWITCH INTERFACE */
+	GPIO145_GPIO	| PIN_INPUT_PULLDOWN,/* HAL_SW */
+
+	/* Audio Amplifier Interface */
+	GPIO149_GPIO	| PIN_OUTPUT_LOW, /* VAUDIO_HF_EN */
+
+	/* GBF INTERFACE */
+	GPIO171_GPIO	| PIN_OUTPUT_LOW, /* GBF_ENA_RESET */
+
+	/* MSP : HDTV INTERFACE */
+	GPIO192_GPIO	| PIN_INPUT_PULLDOWN,
+
+	/* ACCELEROMETER_INTERFACE */
+	GPIO82_GPIO		| PIN_INPUT_PULLUP, /* ACC_INT1 */
+	GPIO83_GPIO		| PIN_INPUT_PULLUP, /* ACC_INT2 */
+
+	/* Proximity Sensor */
+	GPIO217_GPIO		| PIN_INPUT_PULLUP,
+
+
+};
+
+void __init mop500_pins_init(void)
+{
+	nmk_config_pins(mop500_pins_common,
+				ARRAY_SIZE(mop500_pins_common));
+	if (machine_is_hrefv60())
+		nmk_config_pins(mop500_pins_hrefv60,
+				ARRAY_SIZE(mop500_pins_hrefv60));
+	else
+		nmk_config_pins(mop500_pins_default,
+				ARRAY_SIZE(mop500_pins_default));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-regulators.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-regulators.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-regulators.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-regulators.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,256 @@
 #include <linux/kernel.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
+#include "board-mop500-regulators.h"
+
+/*
+ * TPS61052 regulator
+ */
+static struct regulator_consumer_supply tps61052_vaudio_consumers[] = {
+	/*
+	 * Boost converter supply to raise voltage on audio speaker, this
+	 * is actually connected to three pins, VInVhfL (left amplifier)
+	 * VInVhfR (right amplifier) and VIntDClassInt - all three must
+	 * be connected to the same voltage.
+	 */
+	REGULATOR_SUPPLY("vintdclassint", "ab8500-codec.0"),
+};
+
+struct regulator_init_data tps61052_regulator = {
+	.constraints = {
+		.name = "vaudio-hf",
+		.min_uV = 4500000,
+		.max_uV = 4500000,
+		.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+	},
+	.num_consumer_supplies = ARRAY_SIZE(tps61052_vaudio_consumers),
+	.consumer_supplies = tps61052_vaudio_consumers,
+};
+
+static struct regulator_consumer_supply ab8500_vaux1_consumers[] = {
+	/* External displays, connector on board 2v5 power supply */
+	REGULATOR_SUPPLY("vaux12v5", "mcde.0"),
+	/* SFH7741 proximity sensor */
+	REGULATOR_SUPPLY("vcc", "gpio-keys.0"),
+	/* BH1780GLS ambient light sensor */
+	REGULATOR_SUPPLY("vcc", "2-0029"),
+	/* lsm303dlh accelerometer */
+	REGULATOR_SUPPLY("vdd", "3-0018"),
+	/* lsm303dlh magnetometer */
+	REGULATOR_SUPPLY("vdd", "3-001e"),
+	/* Rohm BU21013 Touchscreen devices */
+	REGULATOR_SUPPLY("avdd", "3-005c"),
+	REGULATOR_SUPPLY("avdd", "3-005d"),
+	/* Synaptics RMI4 Touchscreen device */
+	REGULATOR_SUPPLY("vdd", "3-004b"),
+};
+
+static struct regulator_consumer_supply ab8500_vaux2_consumers[] = {
+	/* On-board eMMC power */
+	REGULATOR_SUPPLY("vmmc", "sdi4"),
+	/* AB8500 audio codec */
+	REGULATOR_SUPPLY("vcc-N2158", "ab8500-codec.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vaux3_consumers[] = {
+	/* External MMC slot power */
+	REGULATOR_SUPPLY("vmmc", "sdi0"),
+};
+
+static struct regulator_consumer_supply ab8500_vtvout_consumers[] = {
+	/* TV-out DENC supply */
+	REGULATOR_SUPPLY("vtvout", "ab8500-denc.0"),
+	/* Internal general-purpose ADC */
+	REGULATOR_SUPPLY("vddadc", "ab8500-gpadc.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vintcore_consumers[] = {
+	/* SoC core supply, no device */
+	REGULATOR_SUPPLY("v-intcore", NULL),
+	/* USB Transciever */
+	REGULATOR_SUPPLY("vddulpivio18", "ab8500-usb.0"),
+};
+
+static struct regulator_consumer_supply ab8500_vana_consumers[] = {
+	/* External displays, connector on board, 1v8 power supply */
+	REGULATOR_SUPPLY("vsmps2", "mcde.0"),
+};
+
+/* ab8500 regulator register initialization */
+struct ab8500_regulator_reg_init
+ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS] = {
+	/*
+	 * VanaRequestCtrl          = HP/LP depending on VxRequest
+	 * VextSupply1RequestCtrl   = HP/LP depending on VxRequest
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL2, 0x00),
+	/*
+	 * VextSupply2RequestCtrl   = HP/LP depending on VxRequest
+	 * VextSupply3RequestCtrl   = HP/LP depending on VxRequest
+	 * Vaux1RequestCtrl         = HP/LP depending on VxRequest
+	 * Vaux2RequestCtrl         = HP/LP depending on VxRequest
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL3, 0x00),
+	/*
+	 * Vaux3RequestCtrl         = HP/LP depending on VxRequest
+	 * SwHPReq                  = Control through SWValid disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUREQUESTCTRL4, 0x00),
+	/*
+	 * VanaSysClkReq1HPValid    = disabled
+	 * Vaux1SysClkReq1HPValid   = disabled
+	 * Vaux2SysClkReq1HPValid   = disabled
+	 * Vaux3SysClkReq1HPValid   = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID1, 0x00),
+	/*
+	 * VextSupply1SysClkReq1HPValid = disabled
+	 * VextSupply2SysClkReq1HPValid = disabled
+	 * VextSupply3SysClkReq1HPValid = SysClkReq1 controlled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQ1HPVALID2, 0x40),
+	/*
+	 * VanaHwHPReq1Valid        = disabled
+	 * Vaux1HwHPreq1Valid       = disabled
+	 * Vaux2HwHPReq1Valid       = disabled
+	 * Vaux3HwHPReqValid        = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID1, 0x00),
+	/*
+	 * VextSupply1HwHPReq1Valid = disabled
+	 * VextSupply2HwHPReq1Valid = disabled
+	 * VextSupply3HwHPReq1Valid = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ1VALID2, 0x00),
+	/*
+	 * VanaHwHPReq2Valid        = disabled
+	 * Vaux1HwHPReq2Valid       = disabled
+	 * Vaux2HwHPReq2Valid       = disabled
+	 * Vaux3HwHPReq2Valid       = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID1, 0x00),
+	/*
+	 * VextSupply1HwHPReq2Valid = disabled
+	 * VextSupply2HwHPReq2Valid = disabled
+	 * VextSupply3HwHPReq2Valid = HWReq2 controlled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUHWHPREQ2VALID2, 0x04),
+	/*
+	 * VanaSwHPReqValid         = disabled
+	 * Vaux1SwHPReqValid        = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID1, 0x00),
+	/*
+	 * Vaux2SwHPReqValid        = disabled
+	 * Vaux3SwHPReqValid        = disabled
+	 * VextSupply1SwHPReqValid  = disabled
+	 * VextSupply2SwHPReqValid  = disabled
+	 * VextSupply3SwHPReqValid  = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSWHPREQVALID2, 0x00),
+	/*
+	 * SysClkReq2Valid1         = SysClkReq2 controlled
+	 * SysClkReq3Valid1         = disabled
+	 * SysClkReq4Valid1         = SysClkReq4 controlled
+	 * SysClkReq5Valid1         = disabled
+	 * SysClkReq6Valid1         = SysClkReq6 controlled
+	 * SysClkReq7Valid1         = disabled
+	 * SysClkReq8Valid1         = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID1, 0x2a),
+	/*
+	 * SysClkReq2Valid2         = disabled
+	 * SysClkReq3Valid2         = disabled
+	 * SysClkReq4Valid2         = disabled
+	 * SysClkReq5Valid2         = disabled
+	 * SysClkReq6Valid2         = SysClkReq6 controlled
+	 * SysClkReq7Valid2         = disabled
+	 * SysClkReq8Valid2         = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUSYSCLKREQVALID2, 0x20),
+	/*
+	 * VTVoutEna                = disabled
+	 * Vintcore12Ena            = disabled
+	 * Vintcore12Sel            = 1.25 V
+	 * Vintcore12LP             = inactive (HP)
+	 * VTVoutLP                 = inactive (HP)
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUMISC1, 0x10),
+	/*
+	 * VaudioEna                = disabled
+	 * VdmicEna                 = disabled
+	 * Vamic1Ena                = disabled
+	 * Vamic2Ena                = disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUDIOSUPPLY, 0x00),
+	/*
+	 * Vamic1_dzout             = high-Z when Vamic1 is disabled
+	 * Vamic2_dzout             = high-Z when Vamic2 is disabled
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL1VAMIC, 0x00),
+	/*
+	 * VPll                     = Hw controlled
+	 * VanaRegu                 = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VPLLVANAREGU, 0x02),
+	/*
+	 * VrefDDREna               = disabled
+	 * VrefDDRSleepMode         = inactive (no pulldown)
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VREFDDR, 0x00),
+	/*
+	 * VextSupply1Regu          = HW control
+	 * VextSupply2Regu          = HW control
+	 * VextSupply3Regu          = HW control
+	 * ExtSupply2Bypass         = ExtSupply12LPn ball is 0 when Ena is 0
+	 * ExtSupply3Bypass         = ExtSupply3LPn ball is 0 when Ena is 0
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_EXTSUPPLYREGU, 0x2a),
+	/*
+	 * Vaux1Regu                = force HP
+	 * Vaux2Regu                = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUX12REGU, 0x01),
+	/*
+	 * Vaux3regu                = force off
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3REGU, 0x00),
+	/*
+	 * Vsmps1                   = 1.15V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VSMPS1SEL1, 0x24),
+	/*
+	 * Vaux1Sel                 = 2.5 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUX1SEL, 0x08),
+	/*
+	 * Vaux2Sel                 = 2.9 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VAUX2SEL, 0x0d),
+	/*
+	 * Vaux3Sel                 = 2.91 V
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_VRF1VAUX3SEL, 0x07),
+	/*
+	 * VextSupply12LP           = disabled (no LP)
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRL2SPARE, 0x00),
+	/*
+	 * Vaux1Disch               = short discharge time
+	 * Vaux2Disch               = short discharge time
+	 * Vaux3Disch               = short discharge time
+	 * Vintcore12Disch          = short discharge time
+	 * VTVoutDisch              = short discharge time
+	 * VaudioDisch              = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH, 0x00),
+	/*
+	 * VanaDisch                = short discharge time
+	 * VdmicPullDownEna         = pulldown disabled when Vdmic is disabled
+	 * VdmicDisch               = short discharge time
+	 */
+	INIT_REGULATOR_REGISTER(AB8500_REGUCTRLDISCH2, 0x00),
+};
 
 /* AB8500 regulators */
 struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS] = {
@@ -22,7 +272,10 @@
 			.max_uV = 2900000,
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
+			.boot_on = 1, /* must be on for display */
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux1_consumers),
+		.consumer_supplies = ab8500_vaux1_consumers,
 	},
 	/* supplies to the on-board eMMC */
 	[AB8500_LDO_AUX2] = {
@@ -33,6 +286,8 @@
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux2_consumers),
+		.consumer_supplies = ab8500_vaux2_consumers,
 	},
 	/* supply for VAUX3, supplies to SDcard slots */
 	[AB8500_LDO_AUX3] = {
@@ -43,6 +298,8 @@
 			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
 					  REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vaux3_consumers),
+		.consumer_supplies = ab8500_vaux3_consumers,
 	},
 	/* supply for tvout, gpadc, TVOUT LDO */
 	[AB8500_LDO_TVOUT] = {
@@ -50,6 +307,8 @@
 			.name = "V-TVOUT",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vtvout_consumers),
+		.consumer_supplies = ab8500_vtvout_consumers,
 	},
 	/* supply for ab8500-vaudio, VAUDIO LDO */
 	[AB8500_LDO_AUDIO] = {
@@ -85,6 +344,8 @@
 			.name = "V-INTCORE",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vintcore_consumers),
+		.consumer_supplies = ab8500_vintcore_consumers,
 	},
 	/* supply for U8500 CSI/DSI, VANA LDO */
 	[AB8500_LDO_ANA] = {
@@ -92,5 +353,7 @@
 			.name = "V-CSI/DSI",
 			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
 		},
+		.num_consumer_supplies = ARRAY_SIZE(ab8500_vana_consumers),
+		.consumer_supplies = ab8500_vana_consumers,
 	},
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-regulators.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-regulators.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-regulators.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-regulators.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,9 @@
 #include <linux/regulator/machine.h>
 #include <linux/regulator/ab8500.h>
 
+extern struct ab8500_regulator_reg_init
+ab8500_regulator_reg_init[AB8500_NUM_REGULATOR_REGISTERS];
 extern struct regulator_init_data ab8500_regulators[AB8500_NUM_REGULATORS];
+extern struct regulator_init_data tps61052_regulator;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-sdi.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-sdi.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-sdi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-sdi.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,56 +12,14 @@
 #include <linux/mmc/host.h>
 #include <linux/platform_device.h>
 
-#include <plat/pincfg.h>
+#include <asm/mach-types.h>
+#include <plat/ste_dma40.h>
 #include <mach/devices.h>
 #include <mach/hardware.h>
 
 #include "devices-db8500.h"
-#include "pins-db8500.h"
 #include "board-mop500.h"
-
-static pin_cfg_t mop500_sdi_pins[] = {
-	/* SDI0 (MicroSD slot) */
-	GPIO18_MC0_CMDDIR,
-	GPIO19_MC0_DAT0DIR,
-	GPIO20_MC0_DAT2DIR,
-	GPIO21_MC0_DAT31DIR,
-	GPIO22_MC0_FBCLK,
-	GPIO23_MC0_CLK,
-	GPIO24_MC0_CMD,
-	GPIO25_MC0_DAT0,
-	GPIO26_MC0_DAT1,
-	GPIO27_MC0_DAT2,
-	GPIO28_MC0_DAT3,
-
-	/* SDI4 (on-board eMMC) */
-	GPIO197_MC4_DAT3,
-	GPIO198_MC4_DAT2,
-	GPIO199_MC4_DAT1,
-	GPIO200_MC4_DAT0,
-	GPIO201_MC4_CMD,
-	GPIO202_MC4_FBCLK,
-	GPIO203_MC4_CLK,
-	GPIO204_MC4_DAT7,
-	GPIO205_MC4_DAT6,
-	GPIO206_MC4_DAT5,
-	GPIO207_MC4_DAT4,
-};
-
-static pin_cfg_t mop500_sdi2_pins[] = {
-	/* SDI2 (POP eMMC) */
-	GPIO128_MC2_CLK,
-	GPIO129_MC2_CMD,
-	GPIO130_MC2_FBCLK,
-	GPIO131_MC2_DAT0,
-	GPIO132_MC2_DAT1,
-	GPIO133_MC2_DAT2,
-	GPIO134_MC2_DAT3,
-	GPIO135_MC2_DAT4,
-	GPIO136_MC2_DAT5,
-	GPIO137_MC2_DAT6,
-	GPIO138_MC2_DAT7,
-};
+#include "ste-dma40-db8500.h"
 
 /*
  * SDI 0 (MicroSD slot)
@@ -86,48 +44,134 @@
 	       MCI_DATA2DIREN | MCI_DATA31DIREN;
 }
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg mop500_sdi0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type = DB8500_DMA_DEV29_SD_MM0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg mop500_sdi0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV29_SD_MM0_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data mop500_sdi0_data = {
 	.vdd_handler	= mop500_sdi0_vdd_handler,
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 100000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA,
-	.gpio_cd	= GPIO_SDMMC_CD,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &mop500_sdi0_dma_cfg_rx,
+	.dma_tx_param	= &mop500_sdi0_dma_cfg_tx,
+#endif
 };
 
-void mop500_sdi_tc35892_init(void)
+/* GPIO pins used by the sdi0 level shifter */
+static int sdi0_en = -1;
+static int sdi0_vsel = -1;
+
+static void sdi0_configure(void)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_SDMMC_EN, "SDMMC_EN");
+	ret = gpio_request(sdi0_en, "level shifter enable");
 	if (!ret)
-		ret = gpio_request(GPIO_SDMMC_1V8_3V_SEL,
-				   "GPIO_SDMMC_1V8_3V_SEL");
-	if (ret)
+		ret = gpio_request(sdi0_vsel,
+				   "level shifter 1v8-3v select");
+
+	if (ret) {
+		pr_warning("unable to config sdi0 gpios for level shifter.\n");
 		return;
+	}
 
-	gpio_direction_output(GPIO_SDMMC_1V8_3V_SEL, 1);
-	gpio_direction_output(GPIO_SDMMC_EN, 0);
+	/* Select the default 2.9V and enable level shifter */
+	gpio_direction_output(sdi0_vsel, 0);
+	gpio_direction_output(sdi0_en, 1);
 
+	/* Add the device */
 	db8500_add_sdi0(&mop500_sdi0_data);
 }
 
+void mop500_sdi_tc35892_init(void)
+{
+	mop500_sdi0_data.gpio_cd = GPIO_SDMMC_CD;
+	sdi0_en = GPIO_SDMMC_EN;
+	sdi0_vsel = GPIO_SDMMC_1V8_3V_SEL;
+	sdi0_configure();
+}
+
 /*
  * SDI 2 (POP eMMC, not on DB8500ed)
  */
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg mop500_sdi2_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV28_SD_MM2_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg mop500_sdi2_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV28_SD_MM2_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data mop500_sdi2_data = {
 	.ocr_mask	= MMC_VDD_165_195,
 	.f_max		= 100000000,
 	.capabilities	= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &mop500_sdi2_dma_cfg_rx,
+	.dma_tx_param	= &mop500_sdi2_dma_cfg_tx,
+#endif
 };
 
 /*
  * SDI 4 (on-board eMMC)
  */
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg mop500_sdi4_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type =  DB8500_DMA_DEV42_SD_MM4_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg mop500_sdi4_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB8500_DMA_DEV42_SD_MM4_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data mop500_sdi4_data = {
 	.ocr_mask	= MMC_VDD_29_30,
 	.f_max		= 100000000,
@@ -135,26 +179,32 @@
 			  MMC_CAP_MMC_HIGHSPEED,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &mop500_sdi4_dma_cfg_rx,
+	.dma_tx_param	= &mop500_sdi4_dma_cfg_tx,
+#endif
 };
 
 void __init mop500_sdi_init(void)
 {
-	nmk_config_pins(mop500_sdi_pins, ARRAY_SIZE(mop500_sdi_pins));
+	/* PoP:ed eMMC on top of DB8500 v1.0 has problems with high speed */
+	if (!cpu_is_u8500v10())
+		mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
+	db8500_add_sdi2(&mop500_sdi2_data);
+
+	/* On-board eMMC */
+	db8500_add_sdi4(&mop500_sdi4_data);
 
+	if (machine_is_hrefv60()) {
+		mop500_sdi0_data.gpio_cd = HREFV60_SDMMC_CD_GPIO;
+		sdi0_en = HREFV60_SDMMC_EN_GPIO;
+		sdi0_vsel = HREFV60_SDMMC_1V8_3V_GPIO;
+		sdi0_configure();
+	}
 	/*
-	 * sdi0 will finally be added when the TC35892 initializes and calls
+	 * On boards with the TC35892 GPIO expander, sdi0 will finally
+	 * be added when the TC35892 initializes and calls
 	 * mop500_sdi_tc35892_init() above.
 	 */
-
-	/* PoP:ed eMMC */
-	if (!cpu_is_u8500ed()) {
-		nmk_config_pins(mop500_sdi2_pins, ARRAY_SIZE(mop500_sdi2_pins));
-		/* POP eMMC on v1.0 has problems with high speed */
-		if (!cpu_is_u8500v10())
-			mop500_sdi2_data.capabilities |= MMC_CAP_MMC_HIGHSPEED;
-		db8500_add_sdi2(&mop500_sdi2_data);
-	}
-
-	/* On-board eMMC */
-	db8500_add_sdi4(&mop500_sdi4_data);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-stuib.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-stuib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-stuib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-stuib.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,205 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/mfd/stmpe.h>
+#include <linux/input/bu21013.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/input/matrix_keypad.h>
+#include <asm/mach-types.h>
+
+#include "board-mop500.h"
+
+/* STMPE/SKE keypad use this key layout */
+static const unsigned int mop500_keymap[] = {
+	KEY(2, 5, KEY_END),
+	KEY(4, 1, KEY_POWER),
+	KEY(3, 5, KEY_VOLUMEDOWN),
+	KEY(1, 3, KEY_3),
+	KEY(5, 2, KEY_RIGHT),
+	KEY(5, 0, KEY_9),
+
+	KEY(0, 5, KEY_MENU),
+	KEY(7, 6, KEY_ENTER),
+	KEY(4, 5, KEY_0),
+	KEY(6, 7, KEY_2),
+	KEY(3, 4, KEY_UP),
+	KEY(3, 3, KEY_DOWN),
+
+	KEY(6, 4, KEY_SEND),
+	KEY(6, 2, KEY_BACK),
+	KEY(4, 2, KEY_VOLUMEUP),
+	KEY(5, 5, KEY_1),
+	KEY(4, 3, KEY_LEFT),
+	KEY(3, 2, KEY_7),
+};
+
+static const struct matrix_keymap_data mop500_keymap_data = {
+	.keymap		= mop500_keymap,
+	.keymap_size    = ARRAY_SIZE(mop500_keymap),
+};
+/*
+ * STMPE1601
+ */
+static struct stmpe_keypad_platform_data stmpe1601_keypad_data = {
+	.debounce_ms    = 64,
+	.scan_count     = 8,
+	.no_autorepeat  = true,
+	.keymap_data    = &mop500_keymap_data,
+};
+
+static struct stmpe_platform_data stmpe1601_data = {
+	.id		= 1,
+	.blocks		= STMPE_BLOCK_KEYPAD,
+	.irq_trigger    = IRQF_TRIGGER_FALLING,
+	.irq_base       = MOP500_STMPE1601_IRQ(0),
+	.keypad		= &stmpe1601_keypad_data,
+	.autosleep      = true,
+	.autosleep_timeout = 1024,
+};
+
+static struct i2c_board_info __initdata mop500_i2c0_devices_stuib[] = {
+	{
+		I2C_BOARD_INFO("stmpe1601", 0x40),
+		.irq = NOMADIK_GPIO_TO_IRQ(218),
+		.platform_data = &stmpe1601_data,
+		.flags = I2C_CLIENT_WAKE,
+	},
+};
+
+/*
+ * BU21013 ROHM touchscreen interface on the STUIBs
+ */
+
+/* tracks number of bu21013 devices being enabled */
+static int bu21013_devices;
+
+#define TOUCH_GPIO_PIN  84
+
+#define TOUCH_XMAX	384
+#define TOUCH_YMAX	704
+
+#define PRCMU_CLOCK_OCR		0x1CC
+#define TSC_EXT_CLOCK_9_6MHZ	0x840000
+
+/**
+ * bu21013_gpio_board_init : configures the touch panel.
+ * @reset_pin: reset pin number
+ * This function can be used to configures
+ * the voltage and reset the touch panel controller.
+ */
+static int bu21013_gpio_board_init(int reset_pin)
+{
+	int retval = 0;
+
+	bu21013_devices++;
+	if (bu21013_devices == 1) {
+		retval = gpio_request(reset_pin, "touchp_reset");
+		if (retval) {
+			printk(KERN_ERR "Unable to request gpio reset_pin");
+			return retval;
+		}
+		retval = gpio_direction_output(reset_pin, 1);
+		if (retval < 0) {
+			printk(KERN_ERR "%s: gpio direction failed\n",
+					__func__);
+			return retval;
+		}
+	}
+
+	return retval;
+}
+
+/**
+ * bu21013_gpio_board_exit : deconfigures the touch panel controller
+ * @reset_pin: reset pin number
+ * This function can be used to deconfigures the chip selection
+ * for touch panel controller.
+ */
+static int bu21013_gpio_board_exit(int reset_pin)
+{
+	int retval = 0;
+
+	if (bu21013_devices == 1) {
+		retval = gpio_direction_output(reset_pin, 0);
+		if (retval < 0) {
+			printk(KERN_ERR "%s: gpio direction failed\n",
+					__func__);
+			return retval;
+		}
+		gpio_set_value(reset_pin, 0);
+	}
+	bu21013_devices--;
+
+	return retval;
+}
+
+/**
+ * bu21013_read_pin_val : get the interrupt pin value
+ * This function can be used to get the interrupt pin value for touch panel
+ * controller.
+ */
+static int bu21013_read_pin_val(void)
+{
+	return gpio_get_value(TOUCH_GPIO_PIN);
+}
+
+static struct bu21013_platform_device tsc_plat_device = {
+	.cs_en = bu21013_gpio_board_init,
+	.cs_dis = bu21013_gpio_board_exit,
+	.irq_read_val = bu21013_read_pin_val,
+	.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+	.touch_x_max = TOUCH_XMAX,
+	.touch_y_max = TOUCH_YMAX,
+	.ext_clk = false,
+	.x_flip = false,
+	.y_flip = true,
+};
+
+static struct bu21013_platform_device tsc_plat2_device = {
+	.cs_en = bu21013_gpio_board_init,
+	.cs_dis = bu21013_gpio_board_exit,
+	.irq_read_val = bu21013_read_pin_val,
+	.irq = NOMADIK_GPIO_TO_IRQ(TOUCH_GPIO_PIN),
+	.touch_x_max = TOUCH_XMAX,
+	.touch_y_max = TOUCH_YMAX,
+	.ext_clk = false,
+	.x_flip = false,
+	.y_flip = true,
+};
+
+static struct i2c_board_info __initdata u8500_i2c3_devices_stuib[] = {
+	{
+		I2C_BOARD_INFO("bu21013_tp", 0x5C),
+		.platform_data = &tsc_plat_device,
+	},
+	{
+		I2C_BOARD_INFO("bu21013_tp", 0x5D),
+		.platform_data = &tsc_plat2_device,
+	},
+
+};
+
+void __init mop500_stuib_init(void)
+{
+	if (machine_is_hrefv60()) {
+		tsc_plat_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
+		tsc_plat2_device.cs_pin = HREFV60_TOUCH_RST_GPIO;
+	} else {
+		tsc_plat_device.cs_pin = GPIO_BU21013_CS;
+		tsc_plat2_device.cs_pin = GPIO_BU21013_CS;
+
+	}
+
+	mop500_uib_i2c_add(0, mop500_i2c0_devices_stuib,
+			ARRAY_SIZE(mop500_i2c0_devices_stuib));
+
+	mop500_uib_i2c_add(3, u8500_i2c3_devices_stuib,
+			ARRAY_SIZE(u8500_i2c3_devices_stuib));
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-u8500uib.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Board data for the U8500 UIB, also known as the New UIB
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/gpio.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/tc3589x.h>
+#include <linux/input/matrix_keypad.h>
+#include <../drivers/staging/ste_rmi4/synaptics_i2c_rmi4.h>
+
+#include <mach/gpio.h>
+#include <mach/irqs.h>
+
+#include "board-mop500.h"
+
+/*
+ * Synaptics RMI4 touchscreen interface on the U8500 UIB
+ */
+
+/*
+ * Descriptor structure.
+ * Describes the number of i2c devices on the bus that speak RMI.
+ */
+static struct synaptics_rmi4_platform_data rmi4_i2c_dev_platformdata = {
+	.irq_number     = NOMADIK_GPIO_TO_IRQ(84),
+	.irq_type       = (IRQF_TRIGGER_FALLING | IRQF_SHARED),
+	.x_flip		= false,
+	.y_flip		= true,
+	.regulator_en   = false,
+};
+
+static struct i2c_board_info __initdata mop500_i2c3_devices_u8500[] = {
+	{
+		I2C_BOARD_INFO("synaptics_rmi4_i2c", 0x4B),
+		.platform_data = &rmi4_i2c_dev_platformdata,
+	},
+};
+
+/*
+ * TC35893
+ */
+static const unsigned int u8500_keymap[] = {
+	KEY(3, 1, KEY_END),
+	KEY(4, 1, KEY_POWER),
+	KEY(6, 4, KEY_VOLUMEDOWN),
+	KEY(4, 2, KEY_EMAIL),
+	KEY(3, 3, KEY_RIGHT),
+	KEY(2, 5, KEY_BACKSPACE),
+
+	KEY(6, 7, KEY_MENU),
+	KEY(5, 0, KEY_ENTER),
+	KEY(4, 3, KEY_0),
+	KEY(3, 4, KEY_DOT),
+	KEY(5, 2, KEY_UP),
+	KEY(3, 5, KEY_DOWN),
+
+	KEY(4, 5, KEY_SEND),
+	KEY(0, 5, KEY_BACK),
+	KEY(6, 2, KEY_VOLUMEUP),
+	KEY(1, 3, KEY_SPACE),
+	KEY(7, 6, KEY_LEFT),
+	KEY(5, 5, KEY_SEARCH),
+};
+
+static struct matrix_keymap_data u8500_keymap_data = {
+	.keymap		= u8500_keymap,
+	.keymap_size    = ARRAY_SIZE(u8500_keymap),
+};
+
+static struct tc3589x_keypad_platform_data tc35893_data = {
+	.krow = TC_KPD_ROWS,
+	.kcol = TC_KPD_COLUMNS,
+	.debounce_period = TC_KPD_DEBOUNCE_PERIOD,
+	.settle_time = TC_KPD_SETTLE_TIME,
+	.irqtype = IRQF_TRIGGER_FALLING,
+	.enable_wakeup = true,
+	.keymap_data    = &u8500_keymap_data,
+	.no_autorepeat  = true,
+};
+
+static struct tc3589x_platform_data tc3589x_keypad_data = {
+	.block = TC3589x_BLOCK_KEYPAD,
+	.keypad = &tc35893_data,
+	.irq_base = MOP500_EGPIO_IRQ_BASE,
+};
+
+static struct i2c_board_info __initdata mop500_i2c0_devices_u8500[] = {
+	{
+		I2C_BOARD_INFO("tc3589x", 0x44),
+		.platform_data = &tc3589x_keypad_data,
+		.irq = NOMADIK_GPIO_TO_IRQ(218),
+		.flags = I2C_CLIENT_WAKE,
+	},
+};
+
+
+void __init mop500_u8500uib_init(void)
+{
+	mop500_uib_i2c_add(3, mop500_i2c3_devices_u8500,
+			ARRAY_SIZE(mop500_i2c3_devices_u8500));
+
+	mop500_uib_i2c_add(0, mop500_i2c0_devices_u8500,
+			ARRAY_SIZE(mop500_i2c0_devices_u8500));
+
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-uib.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-uib.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-mop500-uib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-mop500-uib.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * Author: Rabin Vincent <rabin.vincent@stericsson.com> for ST-Ericsson
+ * License terms: GNU General Public License (GPL), version 2
+ */
+
+#define pr_fmt(fmt)	"mop500-uib: " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+
+#include <mach/hardware.h>
+#include "board-mop500.h"
+
+enum mop500_uib {
+	STUIB,
+	U8500UIB,
+};
+
+struct uib {
+	const char *name;
+	const char *option;
+	void (*init)(void);
+};
+
+static struct __initdata uib mop500_uibs[] = {
+	[STUIB] = {
+		.name	= "ST-UIB",
+		.option	= "stuib",
+		.init	= mop500_stuib_init,
+	},
+	[U8500UIB] = {
+		.name	= "U8500-UIB",
+		.option	= "u8500uib",
+		.init	= mop500_u8500uib_init,
+	},
+};
+
+static struct uib *mop500_uib;
+
+static int __init mop500_uib_setup(char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mop500_uibs); i++) {
+		struct uib *uib = &mop500_uibs[i];
+
+		if (!strcmp(str, uib->option)) {
+			mop500_uib = uib;
+			break;
+		}
+	}
+
+	if (i == ARRAY_SIZE(mop500_uibs))
+		pr_err("invalid uib= option (%s)\n", str);
+
+	return 1;
+}
+__setup("uib=", mop500_uib_setup);
+
+/*
+ * The UIBs are detected after the I2C host controllers are registered, so
+ * i2c_register_board_info() can't be used.
+ */
+void mop500_uib_i2c_add(int busnum, struct i2c_board_info *info,
+		unsigned n)
+{
+	struct i2c_adapter *adap;
+	struct i2c_client *client;
+	int i;
+
+	adap = i2c_get_adapter(busnum);
+	if (!adap) {
+		pr_err("failed to get adapter i2c%d\n", busnum);
+		return;
+	}
+
+	for (i = 0; i < n; i++) {
+		client = i2c_new_device(adap, &info[i]);
+		if (!client)
+			pr_err("failed to register %s to i2c%d\n",
+					info[i].type, busnum);
+	}
+
+	i2c_put_adapter(adap);
+}
+
+static void __init __mop500_uib_init(struct uib *uib, const char *why)
+{
+	pr_info("%s (%s)\n", uib->name, why);
+	uib->init();
+}
+
+/*
+ * Detect the UIB attached based on the presence or absence of i2c devices.
+ */
+static int __init mop500_uib_init(void)
+{
+	struct uib *uib = mop500_uib;
+	struct i2c_adapter *i2c0;
+	int ret;
+
+	if (!cpu_is_u8500())
+		return -ENODEV;
+
+	if (uib) {
+		__mop500_uib_init(uib, "from uib= boot argument");
+		return 0;
+	}
+
+	i2c0 = i2c_get_adapter(0);
+	if (!i2c0) {
+		__mop500_uib_init(&mop500_uibs[STUIB],
+				"fallback, could not get i2c0");
+		return -ENODEV;
+	}
+
+	/* U8500-UIB has the TC35893 at 0x44 on I2C0, the ST-UIB doesn't. */
+	ret = i2c_smbus_xfer(i2c0, 0x44, 0, I2C_SMBUS_WRITE, 0,
+			I2C_SMBUS_QUICK, NULL);
+	i2c_put_adapter(i2c0);
+
+	if (ret == 0)
+		uib = &mop500_uibs[U8500UIB];
+	else
+		uib = &mop500_uibs[STUIB];
+
+	__mop500_uib_init(uib, "detected");
+
+	return 0;
+}
+
+module_init(mop500_uib_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-u5500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-u5500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-u5500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-u5500.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,9 +22,9 @@
 
 static void __init u5500_uart_init(void)
 {
-	db5500_add_uart0();
-	db5500_add_uart1();
-	db5500_add_uart2();
+	db5500_add_uart0(NULL);
+	db5500_add_uart1(NULL);
+	db5500_add_uart2(NULL);
 }
 
 static void __init u5500_init_machine(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-u5500-sdi.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-u5500-sdi.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/board-u5500-sdi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/board-u5500-sdi.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,26 @@
 	GPIO14_MC0_CLK		| PIN_DIR_OUTPUT | PIN_VAL_LOW,
 };
 
+#ifdef CONFIG_STE_DMA40
+struct stedma40_chan_cfg u5500_sdi0_dma_cfg_rx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_PERIPH_TO_MEM,
+	.src_dev_type = DB5500_DMA_DEV24_SDMMC0_RX,
+	.dst_dev_type = STEDMA40_DEV_DST_MEMORY,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+
+static struct stedma40_chan_cfg u5500_sdi0_dma_cfg_tx = {
+	.mode = STEDMA40_MODE_LOGICAL,
+	.dir = STEDMA40_MEM_TO_PERIPH,
+	.src_dev_type = STEDMA40_DEV_SRC_MEMORY,
+	.dst_dev_type = DB5500_DMA_DEV24_SDMMC0_TX,
+	.src_info.data_width = STEDMA40_WORD_WIDTH,
+	.dst_info.data_width = STEDMA40_WORD_WIDTH,
+};
+#endif
+
 static struct mmci_platform_data u5500_sdi0_data = {
 	.ocr_mask	= MMC_VDD_165_195,
 	.f_max		= 50000000,
@@ -39,6 +59,11 @@
 				MMC_CAP_MMC_HIGHSPEED,
 	.gpio_cd	= -1,
 	.gpio_wp	= -1,
+#ifdef CONFIG_STE_DMA40
+	.dma_filter	= stedma40_filter,
+	.dma_rx_param	= &u5500_sdi0_dma_cfg_rx,
+	.dma_tx_param	= &u5500_sdi0_dma_cfg_tx,
+#endif
 };
 
 void __init u5500_sdi_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/clock.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -313,7 +313,7 @@
 static DEFINE_PRCMU_CLK(msp02clk,	0x0, 6, MSP02CLK);
 static DEFINE_PRCMU_CLK(msp1clk,	0x0, 7, MSP1CLK); /* v1 */
 static DEFINE_PRCMU_CLK_RATE(i2cclk,	0x0, 8, I2CCLK, 48000000);
-static DEFINE_PRCMU_CLK_RATE(sdmmcclk,	0x0, 9, SDMMCCLK, 50000000);
+static DEFINE_PRCMU_CLK_RATE(sdmmcclk,	0x0, 9, SDMMCCLK, 100000000);
 static DEFINE_PRCMU_CLK(slimclk,	0x0, 10, SLIMCLK);
 static DEFINE_PRCMU_CLK(per1clk,	0x0, 11, PER1CLK);
 static DEFINE_PRCMU_CLK(per2clk,	0x0, 12, PER2CLK);
@@ -520,7 +520,7 @@
 	CLK(ssp0_ed,	"ssp0",		NULL),
 
 	/* Peripheral Cluster #5 */
-	CLK(usb_ed,	"musb_hdrc.0",	"usb"),
+	CLK(usb_ed,	"musb-ux500.0",	"usb"),
 
 	/* Peripheral Cluster #6 */
 	CLK(dmc_ed,	"dmc",		NULL),
@@ -561,7 +561,7 @@
 	CLK(ssp0_v1,	"ssp0",		NULL),
 
 	/* Peripheral Cluster #5 */
-	CLK(usb_v1,	"musb_hdrc.0",	"usb"),
+	CLK(usb_v1,	"musb-ux500.0",	"usb"),
 
 	/* Peripheral Cluster #6 */
 	CLK(mtu1_v1,	"mtu1",		NULL),
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/cpu-db5500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/cpu-db5500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/cpu-db5500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/cpu-db5500.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/irq.h>
 
 #include <asm/mach/map.h>
+#include <asm/pmu.h>
 
 #include <plat/gpio.h>
 
@@ -18,8 +19,10 @@
 #include <mach/devices.h>
 #include <mach/setup.h>
 #include <mach/irqs.h>
+#include <mach/usb.h>
 
 #include "devices-db5500.h"
+#include "ste-dma40-db5500.h"
 
 static struct map_desc u5500_uart_io_desc[] __initdata = {
 	__IO_DEV_DESC(U5500_UART0_BASE, SZ_4K),
@@ -43,6 +46,26 @@
 	__IO_DEV_DESC(U5500_PRCMU_BASE, SZ_4K),
 };
 
+static struct resource db5500_pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_DB5500_PMU0,
+		.end		= IRQ_DB5500_PMU0,
+		.flags		= IORESOURCE_IRQ,
+	},
+	[1] = {
+		.start		= IRQ_DB5500_PMU1,
+		.end		= IRQ_DB5500_PMU1,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device db5500_pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(db5500_pmu_resources),
+	.resource		= db5500_pmu_resources,
+};
+
 static struct resource mbox0_resources[] = {
 	{
 		.name = "mbox_peer",
@@ -127,7 +150,8 @@
 	.num_resources = ARRAY_SIZE(mbox2_resources),
 };
 
-static struct platform_device *u5500_platform_devs[] __initdata = {
+static struct platform_device *db5500_platform_devs[] __initdata = {
+	&db5500_pmu_device,
 	&mbox0_device,
 	&mbox1_device,
 	&mbox2_device,
@@ -166,12 +190,35 @@
 	iotable_init(u5500_io_desc, ARRAY_SIZE(u5500_io_desc));
 }
 
+static int usb_db5500_rx_dma_cfg[] = {
+	DB5500_DMA_DEV4_USB_OTG_IEP_1_9,
+	DB5500_DMA_DEV5_USB_OTG_IEP_2_10,
+	DB5500_DMA_DEV6_USB_OTG_IEP_3_11,
+	DB5500_DMA_DEV20_USB_OTG_IEP_4_12,
+	DB5500_DMA_DEV21_USB_OTG_IEP_5_13,
+	DB5500_DMA_DEV22_USB_OTG_IEP_6_14,
+	DB5500_DMA_DEV23_USB_OTG_IEP_7_15,
+	DB5500_DMA_DEV38_USB_OTG_IEP_8
+};
+
+static int usb_db5500_tx_dma_cfg[] = {
+	DB5500_DMA_DEV4_USB_OTG_OEP_1_9,
+	DB5500_DMA_DEV5_USB_OTG_OEP_2_10,
+	DB5500_DMA_DEV6_USB_OTG_OEP_3_11,
+	DB5500_DMA_DEV20_USB_OTG_OEP_4_12,
+	DB5500_DMA_DEV21_USB_OTG_OEP_5_13,
+	DB5500_DMA_DEV22_USB_OTG_OEP_6_14,
+	DB5500_DMA_DEV23_USB_OTG_OEP_7_15,
+	DB5500_DMA_DEV38_USB_OTG_OEP_8
+};
+
 void __init u5500_init_devices(void)
 {
 	db5500_add_gpios();
 	db5500_dma_init();
 	db5500_add_rtc();
+	db5500_add_usb(usb_db5500_rx_dma_cfg, usb_db5500_tx_dma_cfg);
 
-	platform_add_devices(u5500_platform_devs,
-			     ARRAY_SIZE(u5500_platform_devs));
+	platform_add_devices(db5500_platform_devs,
+			     ARRAY_SIZE(db5500_platform_devs));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/cpu-db8500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/cpu-db8500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/cpu-db8500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/cpu-db8500.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,21 +12,21 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
+#include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
 #include <asm/mach/map.h>
+#include <asm/pmu.h>
 #include <mach/hardware.h>
 #include <mach/setup.h>
 #include <mach/devices.h>
+#include <mach/usb.h>
 
 #include "devices-db8500.h"
-
-static struct platform_device *platform_devs[] __initdata = {
-	&u8500_dma40_device,
-};
+#include "ste-dma40-db8500.h"
 
 /* minimum static i/o mapping required to boot U8500 platforms */
 static struct map_desc u8500_uart_io_desc[] __initdata = {
@@ -89,6 +89,51 @@
 		iotable_init(u8500_v2_io_desc, ARRAY_SIZE(u8500_v2_io_desc));
 }
 
+static struct resource db8500_pmu_resources[] = {
+	[0] = {
+		.start		= IRQ_DB8500_PMU,
+		.end		= IRQ_DB8500_PMU,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+/*
+ * The PMU IRQ lines of two cores are wired together into a single interrupt.
+ * Bounce the interrupt to the other core if it's not ours.
+ */
+static irqreturn_t db8500_pmu_handler(int irq, void *dev, irq_handler_t handler)
+{
+	irqreturn_t ret = handler(irq, dev);
+	int other = !smp_processor_id();
+
+	if (ret == IRQ_NONE && cpu_online(other))
+		irq_set_affinity(irq, cpumask_of(other));
+
+	/*
+	 * We should be able to get away with the amount of IRQ_NONEs we give,
+	 * while still having the spurious IRQ detection code kick in if the
+	 * interrupt really starts hitting spuriously.
+	 */
+	return ret;
+}
+
+static struct arm_pmu_platdata db8500_pmu_platdata = {
+	.handle_irq		= db8500_pmu_handler,
+};
+
+static struct platform_device db8500_pmu_device = {
+	.name			= "arm-pmu",
+	.id			= ARM_PMU_DEVICE_CPU,
+	.num_resources		= ARRAY_SIZE(db8500_pmu_resources),
+	.resource		= db8500_pmu_resources,
+	.dev.platform_data	= &db8500_pmu_platdata,
+};
+
+static struct platform_device *platform_devs[] __initdata = {
+	&u8500_dma40_device,
+	&db8500_pmu_device,
+};
+
 static resource_size_t __initdata db8500_gpio_base[] = {
 	U8500_GPIOBANK0_BASE,
 	U8500_GPIOBANK1_BASE,
@@ -111,6 +156,28 @@
 			 IRQ_DB8500_GPIO0, &pdata);
 }
 
+static int usb_db8500_rx_dma_cfg[] = {
+	DB8500_DMA_DEV38_USB_OTG_IEP_1_9,
+	DB8500_DMA_DEV37_USB_OTG_IEP_2_10,
+	DB8500_DMA_DEV36_USB_OTG_IEP_3_11,
+	DB8500_DMA_DEV19_USB_OTG_IEP_4_12,
+	DB8500_DMA_DEV18_USB_OTG_IEP_5_13,
+	DB8500_DMA_DEV17_USB_OTG_IEP_6_14,
+	DB8500_DMA_DEV16_USB_OTG_IEP_7_15,
+	DB8500_DMA_DEV39_USB_OTG_IEP_8
+};
+
+static int usb_db8500_tx_dma_cfg[] = {
+	DB8500_DMA_DEV38_USB_OTG_OEP_1_9,
+	DB8500_DMA_DEV37_USB_OTG_OEP_2_10,
+	DB8500_DMA_DEV36_USB_OTG_OEP_3_11,
+	DB8500_DMA_DEV19_USB_OTG_OEP_4_12,
+	DB8500_DMA_DEV18_USB_OTG_OEP_5_13,
+	DB8500_DMA_DEV17_USB_OTG_OEP_6_14,
+	DB8500_DMA_DEV16_USB_OTG_OEP_7_15,
+	DB8500_DMA_DEV39_USB_OTG_OEP_8
+};
+
 /*
  * This function is called from the board init
  */
@@ -121,6 +188,7 @@
 
 	db8500_add_rtc();
 	db8500_add_gpios();
+	db8500_add_usb(usb_db8500_rx_dma_cfg, usb_db8500_tx_dma_cfg);
 
 	platform_device_register_simple("cpufreq-u8500", -1, NULL, 0);
 	platform_add_devices(platform_devs, ARRAY_SIZE(platform_devs));
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-common.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-common.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,6 +139,7 @@
 	for (i = 0; i < num; i++, first += 32, irq++) {
 		pdata->first_gpio = first;
 		pdata->first_irq = NOMADIK_GPIO_TO_IRQ(first);
+		pdata->num_gpio = 32;
 
 		dbx500_add_gpio(i, base[i], irq, pdata);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-common.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-common.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-common.h	2011-05-19 00:06:34.000000000 -0400
@@ -42,10 +42,13 @@
 	return dbx500_add_amba_device(name, base, irq, pdata, 0);
 }
 
+struct amba_pl011_data;
+
 static inline struct amba_device *
-dbx500_add_uart(const char *name, resource_size_t base, int irq)
+dbx500_add_uart(const char *name, resource_size_t base, int irq,
+		struct amba_pl011_data *pdata)
 {
-	return dbx500_add_amba_device(name, base, irq, NULL, 0);
+	return dbx500_add_amba_device(name, base, irq, pdata, 0);
 }
 
 struct nmk_i2c_controller;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-db5500.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-db5500.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-db5500.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-db5500.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,9 @@
 #define db5500_add_rtc() \
 	dbx500_add_rtc(U5500_RTC_BASE, IRQ_DB5500_RTC);
 
+#define db5500_add_usb(rx_cfg, tx_cfg) \
+	ux500_add_usb(U5500_USBOTG_BASE, IRQ_DB5500_USBOTG, rx_cfg, tx_cfg)
+
 #define db5500_add_sdi0(pdata) \
 	dbx500_add_sdi("sdi0", U5500_SDI0_BASE, IRQ_DB5500_SDMMC0, pdata)
 #define db5500_add_sdi1(pdata) \
@@ -54,13 +57,13 @@
 #define db5500_add_spi3(pdata) \
 	dbx500_add_spi("spi3", U5500_SPI3_BASE, IRQ_DB5500_SPI3, pdata)
 
-#define db5500_add_uart0() \
-	dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0)
-#define db5500_add_uart1() \
-	dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1)
-#define db5500_add_uart2() \
-	dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2)
-#define db5500_add_uart3() \
-	dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3)
+#define db5500_add_uart0(plat) \
+	dbx500_add_uart("uart0", U5500_UART0_BASE, IRQ_DB5500_UART0, plat)
+#define db5500_add_uart1(plat) \
+	dbx500_add_uart("uart1", U5500_UART1_BASE, IRQ_DB5500_UART1, plat)
+#define db5500_add_uart2(plat) \
+	dbx500_add_uart("uart2", U5500_UART2_BASE, IRQ_DB5500_UART2, plat)
+#define db5500_add_uart3(plat) \
+	dbx500_add_uart("uart3", U5500_UART3_BASE, IRQ_DB5500_UART3, plat)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-db8500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-db8500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-db8500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-db8500.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/amba/bus.h>
+#include <linux/amba/pl022.h>
 
 #include <plat/ste_dma40.h>
 
@@ -67,12 +68,72 @@
 
 /*
  * Mapping between destination event lines and physical device address.
- * The event line is tied to a device and therefor the address is constant.
+ * The event line is tied to a device and therefore the address is constant.
+ * When the address comes from a primecell it will be configured in runtime
+ * and we set the address to -1 as a placeholder.
  */
-static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV];
+static const dma_addr_t dma40_tx_map[DB8500_DMA_NR_DEV] = {
+	/* MUSB - these will be runtime-reconfigured */
+	[DB8500_DMA_DEV39_USB_OTG_OEP_8] = -1,
+	[DB8500_DMA_DEV16_USB_OTG_OEP_7_15] = -1,
+	[DB8500_DMA_DEV17_USB_OTG_OEP_6_14] = -1,
+	[DB8500_DMA_DEV18_USB_OTG_OEP_5_13] = -1,
+	[DB8500_DMA_DEV19_USB_OTG_OEP_4_12] = -1,
+	[DB8500_DMA_DEV36_USB_OTG_OEP_3_11] = -1,
+	[DB8500_DMA_DEV37_USB_OTG_OEP_2_10] = -1,
+	[DB8500_DMA_DEV38_USB_OTG_OEP_1_9] = -1,
+	/* PrimeCells - run-time configured */
+	[DB8500_DMA_DEV0_SPI0_TX] = -1,
+	[DB8500_DMA_DEV1_SD_MMC0_TX] = -1,
+	[DB8500_DMA_DEV2_SD_MMC1_TX] = -1,
+	[DB8500_DMA_DEV3_SD_MMC2_TX] = -1,
+	[DB8500_DMA_DEV8_SSP0_TX] = -1,
+	[DB8500_DMA_DEV9_SSP1_TX] = -1,
+	[DB8500_DMA_DEV11_UART2_TX] = -1,
+	[DB8500_DMA_DEV12_UART1_TX] = -1,
+	[DB8500_DMA_DEV13_UART0_TX] = -1,
+	[DB8500_DMA_DEV28_SD_MM2_TX] = -1,
+	[DB8500_DMA_DEV29_SD_MM0_TX] = -1,
+	[DB8500_DMA_DEV32_SD_MM1_TX] = -1,
+	[DB8500_DMA_DEV33_SPI2_TX] = -1,
+	[DB8500_DMA_DEV35_SPI1_TX] = -1,
+	[DB8500_DMA_DEV40_SPI3_TX] = -1,
+	[DB8500_DMA_DEV41_SD_MM3_TX] = -1,
+	[DB8500_DMA_DEV42_SD_MM4_TX] = -1,
+	[DB8500_DMA_DEV43_SD_MM5_TX] = -1,
+};
 
 /* Mapping between source event lines and physical device address */
-static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV];
+static const dma_addr_t dma40_rx_map[DB8500_DMA_NR_DEV] = {
+	/* MUSB - these will be runtime-reconfigured */
+	[DB8500_DMA_DEV39_USB_OTG_IEP_8] = -1,
+	[DB8500_DMA_DEV16_USB_OTG_IEP_7_15] = -1,
+	[DB8500_DMA_DEV17_USB_OTG_IEP_6_14] = -1,
+	[DB8500_DMA_DEV18_USB_OTG_IEP_5_13] = -1,
+	[DB8500_DMA_DEV19_USB_OTG_IEP_4_12] = -1,
+	[DB8500_DMA_DEV36_USB_OTG_IEP_3_11] = -1,
+	[DB8500_DMA_DEV37_USB_OTG_IEP_2_10] = -1,
+	[DB8500_DMA_DEV38_USB_OTG_IEP_1_9] = -1,
+	/* PrimeCells */
+	[DB8500_DMA_DEV0_SPI0_RX] = -1,
+	[DB8500_DMA_DEV1_SD_MMC0_RX] = -1,
+	[DB8500_DMA_DEV2_SD_MMC1_RX] = -1,
+	[DB8500_DMA_DEV3_SD_MMC2_RX] = -1,
+	[DB8500_DMA_DEV8_SSP0_RX] = -1,
+	[DB8500_DMA_DEV9_SSP1_RX] = -1,
+	[DB8500_DMA_DEV11_UART2_RX] = -1,
+	[DB8500_DMA_DEV12_UART1_RX] = -1,
+	[DB8500_DMA_DEV13_UART0_RX] = -1,
+	[DB8500_DMA_DEV28_SD_MM2_RX] = -1,
+	[DB8500_DMA_DEV29_SD_MM0_RX] = -1,
+	[DB8500_DMA_DEV32_SD_MM1_RX] = -1,
+	[DB8500_DMA_DEV33_SPI2_RX] = -1,
+	[DB8500_DMA_DEV35_SPI1_RX] = -1,
+	[DB8500_DMA_DEV40_SPI3_RX] = -1,
+	[DB8500_DMA_DEV41_SD_MM3_RX] = -1,
+	[DB8500_DMA_DEV42_SD_MM4_RX] = -1,
+	[DB8500_DMA_DEV43_SD_MM5_RX] = -1,
+};
 
 /* Reserved event lines for memcpy only */
 static int dma40_memcpy_event[] = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-db8500.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-db8500.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/devices-db8500.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/devices-db8500.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,9 @@
 #define db8500_add_rtc() \
 	dbx500_add_rtc(U8500_RTC_BASE, IRQ_DB8500_RTC);
 
+#define db8500_add_usb(rx_cfg, tx_cfg) \
+	ux500_add_usb(U8500_USBOTG_BASE, IRQ_DB8500_USBOTG, rx_cfg, tx_cfg)
+
 #define db8500_add_sdi0(pdata) \
 	dbx500_add_sdi("sdi0", U8500_SDI0_BASE, IRQ_DB8500_SDMMC0, pdata)
 #define db8500_add_sdi1(pdata) \
@@ -88,11 +91,11 @@
 #define db8500_add_spi3(pdata) \
 	dbx500_add_spi("spi3", U8500_SPI3_BASE, IRQ_DB8500_SPI3, pdata)
 
-#define db8500_add_uart0() \
-	dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0)
-#define db8500_add_uart1() \
-	dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1)
-#define db8500_add_uart2() \
-	dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2)
+#define db8500_add_uart0(pdata) \
+	dbx500_add_uart("uart0", U8500_UART0_BASE, IRQ_DB8500_UART0, pdata)
+#define db8500_add_uart1(pdata) \
+	dbx500_add_uart("uart1", U8500_UART1_BASE, IRQ_DB8500_UART1, pdata)
+#define db8500_add_uart2(pdata) \
+	dbx500_add_uart("uart2", U8500_UART2_BASE, IRQ_DB8500_UART2, pdata)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/dma-db5500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/dma-db5500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/dma-db5500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/dma-db5500.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,11 +73,27 @@
  */
 static const dma_addr_t dma40_rx_map[DB5500_DMA_NR_DEV] = {
 	[DB5500_DMA_DEV24_SDMMC0_RX] = -1,
+	[DB5500_DMA_DEV38_USB_OTG_IEP_8] = -1,
+	[DB5500_DMA_DEV23_USB_OTG_IEP_7_15] = -1,
+	[DB5500_DMA_DEV22_USB_OTG_IEP_6_14] = -1,
+	[DB5500_DMA_DEV21_USB_OTG_IEP_5_13] = -1,
+	[DB5500_DMA_DEV20_USB_OTG_IEP_4_12] = -1,
+	[DB5500_DMA_DEV6_USB_OTG_IEP_3_11] = -1,
+	[DB5500_DMA_DEV5_USB_OTG_IEP_2_10] = -1,
+	[DB5500_DMA_DEV4_USB_OTG_IEP_1_9] = -1,
 };
 
 /* Mapping between destination event lines and physical device address */
 static const dma_addr_t dma40_tx_map[DB5500_DMA_NR_DEV] = {
 	[DB5500_DMA_DEV24_SDMMC0_TX] = -1,
+	[DB5500_DMA_DEV38_USB_OTG_OEP_8] = -1,
+	[DB5500_DMA_DEV23_USB_OTG_OEP_7_15] = -1,
+	[DB5500_DMA_DEV22_USB_OTG_OEP_6_14] = -1,
+	[DB5500_DMA_DEV21_USB_OTG_OEP_5_13] = -1,
+	[DB5500_DMA_DEV20_USB_OTG_OEP_4_12] = -1,
+	[DB5500_DMA_DEV6_USB_OTG_OEP_3_11] = -1,
+	[DB5500_DMA_DEV5_USB_OTG_OEP_2_10] = -1,
+	[DB5500_DMA_DEV4_USB_OTG_OEP_1_9] = -1,
 };
 
 static int dma40_memcpy_event[] = {
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/db8500-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -58,7 +58,7 @@
 #define U8500_GPIO2_BASE	(U8500_PER2_BASE + 0xE000)
 #define U8500_GPIO3_BASE	(U8500_PER5_BASE + 0x1E000)
 
-/* per7 base addressess */
+/* per7 base addresses */
 #define U8500_CR_BASE_ED	(U8500_PER7_BASE_ED + 0x8000)
 #define U8500_MTU0_BASE_ED	(U8500_PER7_BASE_ED + 0xa000)
 #define U8500_MTU1_BASE_ED	(U8500_PER7_BASE_ED + 0xb000)
@@ -68,7 +68,7 @@
 #define U8500_UART0_BASE	(U8500_PER1_BASE + 0x0000)
 #define U8500_UART1_BASE	(U8500_PER1_BASE + 0x1000)
 
-/* per6 base addressess */
+/* per6 base addresses */
 #define U8500_RNG_BASE		(U8500_PER6_BASE + 0x0000)
 #define U8500_PKA_BASE		(U8500_PER6_BASE + 0x1000)
 #define U8500_PKAM_BASE		(U8500_PER6_BASE + 0x2000)
@@ -79,11 +79,11 @@
 #define U8500_CRYPTO1_BASE	(U8500_PER6_BASE + 0xb000)
 #define U8500_CLKRST6_BASE	(U8500_PER6_BASE + 0xf000)
 
-/* per5 base addressess */
+/* per5 base addresses */
 #define U8500_USBOTG_BASE	(U8500_PER5_BASE + 0x00000)
 #define U8500_CLKRST5_BASE	(U8500_PER5_BASE + 0x1f000)
 
-/* per4 base addressess */
+/* per4 base addresses */
 #define U8500_BACKUPRAM0_BASE	(U8500_PER4_BASE + 0x00000)
 #define U8500_BACKUPRAM1_BASE	(U8500_PER4_BASE + 0x01000)
 #define U8500_RTT0_BASE		(U8500_PER4_BASE + 0x02000)
@@ -106,7 +106,7 @@
 #define U8500_SDI5_BASE		(U8500_PER3_BASE + 0x8000)
 #define U8500_CLKRST3_BASE	(U8500_PER3_BASE + 0xf000)
 
-/* per2 base addressess */
+/* per2 base addresses */
 #define U8500_I2C3_BASE		(U8500_PER2_BASE + 0x0000)
 #define U8500_SPI2_BASE		(U8500_PER2_BASE + 0x1000)
 #define U8500_SPI1_BASE		(U8500_PER2_BASE + 0x2000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/irqs-board-mop500.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,9 +35,20 @@
 #define MOP500_STMPE1601_IRQBASE        MOP500_EGPIO_IRQ_END
 #define MOP500_STMPE1601_IRQ(x)         (MOP500_STMPE1601_IRQBASE + (x))
 
-#define MOP500_NR_IRQS          MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
+#define MOP500_STMPE1601_IRQ_END	\
+	MOP500_STMPE1601_IRQ(STMPE_NR_INTERNAL_IRQS)
 
-#define MOP500_IRQ_END          MOP500_NR_IRQS
+/* AB8500 virtual gpio IRQ */
+#define AB8500_VIR_GPIO_NR_IRQS			16
+
+#define MOP500_AB8500_VIR_GPIO_IRQ_BASE		\
+	MOP500_STMPE1601_IRQ_END
+#define MOP500_AB8500_VIR_GPIO_IRQ_END		\
+	(MOP500_AB8500_VIR_GPIO_IRQ_BASE + AB8500_VIR_GPIO_NR_IRQS)
+
+#define MOP500_NR_IRQS		MOP500_AB8500_VIR_GPIO_IRQ_END
+
+#define MOP500_IRQ_END		MOP500_NR_IRQS
 
 #if MOP500_IRQ_END > IRQ_BOARD_END
 #undef IRQ_BOARD_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 #define BUS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,11 @@
 
 static inline void arch_decomp_setup(void)
 {
-	if (machine_is_u8500())
+	/* Check in run time if we run on an U8500 or U5500 */
+	if (machine_is_u8500() ||
+	    machine_is_svp8500v1() ||
+	    machine_is_svp8500v2() ||
+	    machine_is_hrefv60())
 		ux500_uart_base = U8500_UART2_BASE;
 	else if (machine_is_u5500())
 		ux500_uart_base = U5500_UART0_BASE;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/usb.h linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/usb.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/include/mach/usb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/include/mach/usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#ifndef __ASM_ARCH_USB_H
+#define __ASM_ARCH_USB_H
+
+#include <linux/dmaengine.h>
+
+#define UX500_MUSB_DMA_NUM_RX_CHANNELS 8
+#define UX500_MUSB_DMA_NUM_TX_CHANNELS 8
+
+struct ux500_musb_board_data {
+	void	**dma_rx_param_array;
+	void	**dma_tx_param_array;
+	u32	num_rx_channels;
+	u32	num_tx_channels;
+	bool (*dma_filter)(struct dma_chan *chan, void *filter_param);
+};
+
+void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
+	int *dma_tx_cfg);
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-ux500/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
 	select ARM_GIC
 	select HAS_MTU
 	select NOMADIK_GPIO
+	select ARM_ERRATA_753970
 
 menu "Ux500 SoC"
 
@@ -22,6 +23,7 @@
 config MACH_U8500
 	bool "U8500 Development platform"
 	depends on UX500_SOC_DB8500
+	select TPS6105X
 	help
 	  Include support for the mop500 development platform.
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/localtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/localtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,8 +21,9 @@
 /*
  * Setup the local clock events for a CPU.
  */
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
 {
 	evt->irq = IRQ_LOCALTIMER;
 	twd_timer_setup(evt);
+	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-ux500/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -3,16 +3,18 @@
 #
 
 obj-y				:= clock.o cpu.o devices.o devices-common.o \
-				   id.o
+				   id.o usb.o
 obj-$(CONFIG_UX500_SOC_DB5500)	+= cpu-db5500.o dma-db5500.o
 obj-$(CONFIG_UX500_SOC_DB8500)	+= cpu-db8500.o devices-db8500.o prcmu.o
 obj-$(CONFIG_MACH_U8500)	+= board-mop500.o board-mop500-sdi.o \
-				board-mop500-keypads.o
+				board-mop500-regulators.o \
+				board-mop500-uib.o board-mop500-stuib.o \
+				board-mop500-u8500uib.o \
+				board-mop500-pins.o
 obj-$(CONFIG_MACH_U5500)	+= board-u5500.o board-u5500-sdi.o
 obj-$(CONFIG_SMP)		+= platsmp.o headsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
 obj-$(CONFIG_LOCAL_TIMERS)	+= localtimer.o
-obj-$(CONFIG_REGULATOR_AB8500)	+= board-mop500-regulators.o
 obj-$(CONFIG_U5500_MODEM_IRQ)	+= modem-irq-db5500.o
 obj-$(CONFIG_U5500_MBOX)	+= mbox-db5500.o
 obj-$(CONFIG_CPU_FREQ)		+= cpufreq.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/mbox-db5500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/mbox-db5500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/mbox-db5500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/mbox-db5500.c	2011-05-19 00:06:34.000000000 -0400
@@ -498,7 +498,7 @@
 #endif
 
 	dev_info(&(mbox->pdev->dev),
-		 "Mailbox driver with index %d initated!\n", mbox_id);
+		 "Mailbox driver with index %d initiated!\n", mbox_id);
 
 exit:
 	return mbox;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/modem-irq-db5500.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/modem-irq-db5500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/modem-irq-db5500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/modem-irq-db5500.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,8 +90,7 @@
 
 static void create_virtual_irq(int irq, struct irq_chip *modem_irq_chip)
 {
-	set_irq_chip(irq, modem_irq_chip);
-	set_irq_handler(irq, handle_simple_irq);
+	irq_set_chip_and_handler(irq, modem_irq_chip, handle_simple_irq);
 	set_irq_flags(irq, IRQF_VALID);
 
 	pr_debug("modem_irq: Created virtual IRQ %d\n", irq);
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-ux500/usb.c linux-libre-2.6.39-gnu/arch/arm/mach-ux500/usb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-ux500/usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-ux500/usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,160 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: Mian Yousaf Kaukab <mian.yousaf.kaukab@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ */
+#include <linux/platform_device.h>
+#include <linux/usb/musb.h>
+#include <plat/ste_dma40.h>
+#include <mach/hardware.h>
+#include <mach/usb.h>
+
+#define MUSB_DMA40_RX_CH { \
+		.mode = STEDMA40_MODE_LOGICAL, \
+		.dir = STEDMA40_PERIPH_TO_MEM, \
+		.dst_dev_type = STEDMA40_DEV_DST_MEMORY, \
+		.src_info.data_width = STEDMA40_WORD_WIDTH, \
+		.dst_info.data_width = STEDMA40_WORD_WIDTH, \
+		.src_info.psize = STEDMA40_PSIZE_LOG_16, \
+		.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
+	}
+
+#define MUSB_DMA40_TX_CH { \
+		.mode = STEDMA40_MODE_LOGICAL, \
+		.dir = STEDMA40_MEM_TO_PERIPH, \
+		.src_dev_type = STEDMA40_DEV_SRC_MEMORY, \
+		.src_info.data_width = STEDMA40_WORD_WIDTH, \
+		.dst_info.data_width = STEDMA40_WORD_WIDTH, \
+		.src_info.psize = STEDMA40_PSIZE_LOG_16, \
+		.dst_info.psize = STEDMA40_PSIZE_LOG_16, \
+	}
+
+static struct stedma40_chan_cfg musb_dma_rx_ch[UX500_MUSB_DMA_NUM_RX_CHANNELS]
+	= {
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH,
+	MUSB_DMA40_RX_CH
+};
+
+static struct stedma40_chan_cfg musb_dma_tx_ch[UX500_MUSB_DMA_NUM_TX_CHANNELS]
+	= {
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+	MUSB_DMA40_TX_CH,
+};
+
+static void *ux500_dma_rx_param_array[UX500_MUSB_DMA_NUM_RX_CHANNELS] = {
+	&musb_dma_rx_ch[0],
+	&musb_dma_rx_ch[1],
+	&musb_dma_rx_ch[2],
+	&musb_dma_rx_ch[3],
+	&musb_dma_rx_ch[4],
+	&musb_dma_rx_ch[5],
+	&musb_dma_rx_ch[6],
+	&musb_dma_rx_ch[7]
+};
+
+static void *ux500_dma_tx_param_array[UX500_MUSB_DMA_NUM_TX_CHANNELS] = {
+	&musb_dma_tx_ch[0],
+	&musb_dma_tx_ch[1],
+	&musb_dma_tx_ch[2],
+	&musb_dma_tx_ch[3],
+	&musb_dma_tx_ch[4],
+	&musb_dma_tx_ch[5],
+	&musb_dma_tx_ch[6],
+	&musb_dma_tx_ch[7]
+};
+
+static struct ux500_musb_board_data musb_board_data = {
+	.dma_rx_param_array = ux500_dma_rx_param_array,
+	.dma_tx_param_array = ux500_dma_tx_param_array,
+	.num_rx_channels = UX500_MUSB_DMA_NUM_RX_CHANNELS,
+	.num_tx_channels = UX500_MUSB_DMA_NUM_TX_CHANNELS,
+	.dma_filter = stedma40_filter,
+};
+
+static u64 ux500_musb_dmamask = DMA_BIT_MASK(32);
+
+static struct musb_hdrc_config musb_hdrc_config = {
+	.multipoint	= true,
+	.dyn_fifo	= true,
+	.num_eps	= 16,
+	.ram_bits	= 16,
+};
+
+static struct musb_hdrc_platform_data musb_platform_data = {
+#if defined(CONFIG_USB_MUSB_OTG)
+	.mode = MUSB_OTG,
+#elif defined(CONFIG_USB_MUSB_PERIPHERAL)
+	.mode = MUSB_PERIPHERAL,
+#else /* defined(CONFIG_USB_MUSB_HOST) */
+	.mode = MUSB_HOST,
+#endif
+	.config = &musb_hdrc_config,
+	.board_data = &musb_board_data,
+};
+
+static struct resource usb_resources[] = {
+	[0] = {
+		.name	= "usb-mem",
+		.flags	=  IORESOURCE_MEM,
+	},
+
+	[1] = {
+		.name   = "mc", /* hard-coded in musb */
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+struct platform_device ux500_musb_device = {
+	.name = "musb-ux500",
+	.id = 0,
+	.dev = {
+		.platform_data = &musb_platform_data,
+		.dma_mask = &ux500_musb_dmamask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+	.num_resources = ARRAY_SIZE(usb_resources),
+	.resource = usb_resources,
+};
+
+static inline void ux500_usb_dma_update_rx_ch_config(int *src_dev_type)
+{
+	u32 idx;
+
+	for (idx = 0; idx < UX500_MUSB_DMA_NUM_RX_CHANNELS; idx++)
+		musb_dma_rx_ch[idx].src_dev_type = src_dev_type[idx];
+}
+
+static inline void ux500_usb_dma_update_tx_ch_config(int *dst_dev_type)
+{
+	u32 idx;
+
+	for (idx = 0; idx < UX500_MUSB_DMA_NUM_TX_CHANNELS; idx++)
+		musb_dma_tx_ch[idx].dst_dev_type = dst_dev_type[idx];
+}
+
+void ux500_add_usb(resource_size_t base, int irq, int *dma_rx_cfg,
+	int *dma_tx_cfg)
+{
+	ux500_musb_device.resource[0].start = base;
+	ux500_musb_device.resource[0].end = base + SZ_64K - 1;
+	ux500_musb_device.resource[1].start = irq;
+	ux500_musb_device.resource[1].end = irq;
+
+	ux500_usb_dma_update_rx_ch_config(dma_rx_cfg);
+	ux500_usb_dma_update_tx_ch_config(dma_tx_cfg);
+
+	platform_device_register(&ux500_musb_device);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-versatile/core.c linux-libre-2.6.39-gnu/arch/arm/mach-versatile/core.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-versatile/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-versatile/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,6 +50,8 @@
 #include <mach/platform.h>
 #include <asm/hardware/timer-sp.h>
 
+#include <plat/clcd.h>
+#include <plat/fpga-irq.h>
 #include <plat/sched_clock.h>
 
 #include "core.h"
@@ -63,47 +65,12 @@
 #define VA_VIC_BASE		__io_address(VERSATILE_VIC_BASE)
 #define VA_SIC_BASE		__io_address(VERSATILE_SIC_BASE)
 
-static void sic_mask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_SIC_START;
-
-	writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
-}
-
-static void sic_unmask_irq(struct irq_data *d)
-{
-	unsigned int irq = d->irq - IRQ_SIC_START;
-
-	writel(1 << irq, VA_SIC_BASE + SIC_IRQ_ENABLE_SET);
-}
-
-static struct irq_chip sic_chip = {
-	.name		= "SIC",
-	.irq_ack	= sic_mask_irq,
-	.irq_mask	= sic_mask_irq,
-	.irq_unmask	= sic_unmask_irq,
+static struct fpga_irq_data sic_irq = {
+	.base		= VA_SIC_BASE,
+	.irq_start	= IRQ_SIC_START,
+	.chip.name	= "SIC",
 };
 
-static void
-sic_handle_irq(unsigned int irq, struct irq_desc *desc)
-{
-	unsigned long status = readl(VA_SIC_BASE + SIC_IRQ_STATUS);
-
-	if (status == 0) {
-		do_bad_IRQ(irq, desc);
-		return;
-	}
-
-	do {
-		irq = ffs(status) - 1;
-		status &= ~(1 << irq);
-
-		irq += IRQ_SIC_START;
-
-		generic_handle_irq(irq);
-	} while (status);
-}
-
 #if 1
 #define IRQ_MMCI0A	IRQ_VICSOURCE22
 #define IRQ_AACI	IRQ_VICSOURCE24
@@ -118,22 +85,11 @@
 
 void __init versatile_init_irq(void)
 {
-	unsigned int i;
-
 	vic_init(VA_VIC_BASE, IRQ_VIC_START, ~0, 0);
 
-	set_irq_chained_handler(IRQ_VICSOURCE31, sic_handle_irq);
-
-	/* Do second interrupt controller */
 	writel(~0, VA_SIC_BASE + SIC_IRQ_ENABLE_CLEAR);
 
-	for (i = IRQ_SIC_START; i <= IRQ_SIC_END; i++) {
-		if ((PIC_MASK & (1 << (i - IRQ_SIC_START))) == 0) {
-			set_irq_chip(i, &sic_chip);
-			set_irq_handler(i, handle_level_irq);
-			set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
-		}
-	}
+	fpga_irq_init(IRQ_VICSOURCE31, ~PIC_MASK, &sic_irq);
 
 	/*
 	 * Interrupts on secondary controller from 0 to 8 are routed to
@@ -476,127 +432,7 @@
 #define SYS_CLCD_ID_SANYO_2_5	(0x07 << 8)
 #define SYS_CLCD_ID_VGA		(0x1f << 8)
 
-static struct clcd_panel vga = {
-	.mode		= {
-		.name		= "VGA",
-		.refresh	= 60,
-		.xres		= 640,
-		.yres		= 480,
-		.pixclock	= 39721,
-		.left_margin	= 40,
-		.right_margin	= 24,
-		.upper_margin	= 32,
-		.lower_margin	= 11,
-		.hsync_len	= 96,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel sanyo_3_8_in = {
-	.mode		= {
-		.name		= "Sanyo QVGA",
-		.refresh	= 116,
-		.xres		= 320,
-		.yres		= 240,
-		.pixclock	= 100000,
-		.left_margin	= 6,
-		.right_margin	= 6,
-		.upper_margin	= 5,
-		.lower_margin	= 5,
-		.hsync_len	= 6,
-		.vsync_len	= 6,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD,
-	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel sanyo_2_5_in = {
-	.mode		= {
-		.name		= "Sanyo QVGA Portrait",
-		.refresh	= 116,
-		.xres		= 240,
-		.yres		= 320,
-		.pixclock	= 100000,
-		.left_margin	= 20,
-		.right_margin	= 10,
-		.upper_margin	= 2,
-		.lower_margin	= 2,
-		.hsync_len	= 10,
-		.vsync_len	= 2,
-		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_IVS | TIM2_IHS | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-static struct clcd_panel epson_2_2_in = {
-	.mode		= {
-		.name		= "Epson QCIF",
-		.refresh	= 390,
-		.xres		= 176,
-		.yres		= 220,
-		.pixclock	= 62500,
-		.left_margin	= 3,
-		.right_margin	= 2,
-		.upper_margin	= 1,
-		.lower_margin	= 0,
-		.hsync_len	= 3,
-		.vsync_len	= 2,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
-/*
- * Detect which LCD panel is connected, and return the appropriate
- * clcd_panel structure.  Note: we do not have any information on
- * the required timings for the 8.4in panel, so we presently assume
- * VGA timings.
- */
-static struct clcd_panel *versatile_clcd_panel(void)
-{
-	void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
-	struct clcd_panel *panel = &vga;
-	u32 val;
-
-	val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
-	if (val == SYS_CLCD_ID_SANYO_3_8)
-		panel = &sanyo_3_8_in;
-	else if (val == SYS_CLCD_ID_SANYO_2_5)
-		panel = &sanyo_2_5_in;
-	else if (val == SYS_CLCD_ID_EPSON_2_2)
-		panel = &epson_2_2_in;
-	else if (val == SYS_CLCD_ID_VGA)
-		panel = &vga;
-	else {
-		printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
-			val);
-		panel = &vga;
-	}
-
-	return panel;
-}
+static bool is_sanyo_2_5_lcd;
 
 /*
  * Disable all display connectors on the interface module.
@@ -614,7 +450,7 @@
 	/*
 	 * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light off
 	 */
-	if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) {
+	if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) {
 		void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
 		unsigned long ctrl;
 
@@ -630,18 +466,22 @@
  */
 static void versatile_clcd_enable(struct clcd_fb *fb)
 {
+	struct fb_var_screeninfo *var = &fb->fb.var;
 	void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
 	u32 val;
 
 	val = readl(sys_clcd);
 	val &= ~SYS_CLCD_MODE_MASK;
 
-	switch (fb->fb.var.green.length) {
+	switch (var->green.length) {
 	case 5:
 		val |= SYS_CLCD_MODE_5551;
 		break;
 	case 6:
-		val |= SYS_CLCD_MODE_565_RLSB;
+		if (var->red.offset == 0)
+			val |= SYS_CLCD_MODE_565_RLSB;
+		else
+			val |= SYS_CLCD_MODE_565_BLSB;
 		break;
 	case 8:
 		val |= SYS_CLCD_MODE_888;
@@ -663,7 +503,7 @@
 	/*
 	 * If the LCD is Sanyo 2x5 in on the IB2 board, turn the back-light on
 	 */
-	if (machine_is_versatile_ab() && fb->panel == &sanyo_2_5_in) {
+	if (machine_is_versatile_ab() && is_sanyo_2_5_lcd) {
 		void __iomem *versatile_ib2_ctrl = __io_address(VERSATILE_IB2_CTRL);
 		unsigned long ctrl;
 
@@ -674,50 +514,62 @@
 #endif
 }
 
-static unsigned long framesize = SZ_1M;
-
+/*
+ * Detect which LCD panel is connected, and return the appropriate
+ * clcd_panel structure.  Note: we do not have any information on
+ * the required timings for the 8.4in panel, so we presently assume
+ * VGA timings.
+ */
 static int versatile_clcd_setup(struct clcd_fb *fb)
 {
-	dma_addr_t dma;
+	void __iomem *sys_clcd = __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_CLCD_OFFSET;
+	const char *panel_name;
+	u32 val;
 
-	fb->panel		= versatile_clcd_panel();
+	is_sanyo_2_5_lcd = false;
 
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-						    &dma, GFP_KERNEL);
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map framebuffer\n");
-		return -ENOMEM;
+	val = readl(sys_clcd) & SYS_CLCD_ID_MASK;
+	if (val == SYS_CLCD_ID_SANYO_3_8)
+		panel_name = "Sanyo TM38QV67A02A";
+	else if (val == SYS_CLCD_ID_SANYO_2_5) {
+		panel_name = "Sanyo QVGA Portrait";
+		is_sanyo_2_5_lcd = true;
+	} else if (val == SYS_CLCD_ID_EPSON_2_2)
+		panel_name = "Epson L2F50113T00";
+	else if (val == SYS_CLCD_ID_VGA)
+		panel_name = "VGA";
+	else {
+		printk(KERN_ERR "CLCD: unknown LCD panel ID 0x%08x, using VGA\n",
+			val);
+		panel_name = "VGA";
 	}
 
-	fb->fb.fix.smem_start	= dma;
-	fb->fb.fix.smem_len	= framesize;
+	fb->panel = versatile_clcd_get_panel(panel_name);
+	if (!fb->panel)
+		return -EINVAL;
 
-	return 0;
+	return versatile_clcd_setup_dma(fb, SZ_1M);
 }
 
-static int versatile_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
+static void versatile_clcd_decode(struct clcd_fb *fb, struct clcd_regs *regs)
 {
-	return dma_mmap_writecombine(&fb->dev->dev, vma,
-				     fb->fb.screen_base,
-				     fb->fb.fix.smem_start,
-				     fb->fb.fix.smem_len);
-}
+	clcdfb_decode(fb, regs);
 
-static void versatile_clcd_remove(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-			      fb->fb.screen_base, fb->fb.fix.smem_start);
+	/* Always clear BGR for RGB565: we do the routing externally */
+	if (fb->fb.var.green.length == 6)
+		regs->cntl &= ~CNTL_BGR;
 }
 
 static struct clcd_board clcd_plat_data = {
 	.name		= "Versatile",
+	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
 	.check		= clcdfb_check,
-	.decode		= clcdfb_decode,
+	.decode		= versatile_clcd_decode,
 	.disable	= versatile_clcd_disable,
 	.enable		= versatile_clcd_enable,
 	.setup		= versatile_clcd_setup,
-	.mmap		= versatile_clcd_mmap,
-	.remove		= versatile_clcd_remove,
+	.mmap		= versatile_clcd_mmap_dma,
+	.remove		= versatile_clcd_remove_dma,
 };
 
 static struct pl061_platform_data gpio0_plat_data = {
@@ -737,53 +589,35 @@
 };
 
 #define AACI_IRQ	{ IRQ_AACI, NO_IRQ }
-#define AACI_DMA	{ 0x80, 0x81 }
 #define MMCI0_IRQ	{ IRQ_MMCI0A,IRQ_SIC_MMCI0B }
-#define MMCI0_DMA	{ 0x84, 0 }
 #define KMI0_IRQ	{ IRQ_SIC_KMI0, NO_IRQ }
-#define KMI0_DMA	{ 0, 0 }
 #define KMI1_IRQ	{ IRQ_SIC_KMI1, NO_IRQ }
-#define KMI1_DMA	{ 0, 0 }
 
 /*
  * These devices are connected directly to the multi-layer AHB switch
  */
 #define SMC_IRQ		{ NO_IRQ, NO_IRQ }
-#define SMC_DMA		{ 0, 0 }
 #define MPMC_IRQ	{ NO_IRQ, NO_IRQ }
-#define MPMC_DMA	{ 0, 0 }
 #define CLCD_IRQ	{ IRQ_CLCDINT, NO_IRQ }
-#define CLCD_DMA	{ 0, 0 }
 #define DMAC_IRQ	{ IRQ_DMAINT, NO_IRQ }
-#define DMAC_DMA	{ 0, 0 }
 
 /*
  * These devices are connected via the core APB bridge
  */
 #define SCTL_IRQ	{ NO_IRQ, NO_IRQ }
-#define SCTL_DMA	{ 0, 0 }
 #define WATCHDOG_IRQ	{ IRQ_WDOGINT, NO_IRQ }
-#define WATCHDOG_DMA	{ 0, 0 }
 #define GPIO0_IRQ	{ IRQ_GPIOINT0, NO_IRQ }
-#define GPIO0_DMA	{ 0, 0 }
 #define GPIO1_IRQ	{ IRQ_GPIOINT1, NO_IRQ }
-#define GPIO1_DMA	{ 0, 0 }
 #define RTC_IRQ		{ IRQ_RTCINT, NO_IRQ }
-#define RTC_DMA		{ 0, 0 }
 
 /*
  * These devices are connected via the DMA APB bridge
  */
 #define SCI_IRQ		{ IRQ_SCIINT, NO_IRQ }
-#define SCI_DMA		{ 7, 6 }
 #define UART0_IRQ	{ IRQ_UARTINT0, NO_IRQ }
-#define UART0_DMA	{ 15, 14 }
 #define UART1_IRQ	{ IRQ_UARTINT1, NO_IRQ }
-#define UART1_DMA	{ 13, 12 }
 #define UART2_IRQ	{ IRQ_UARTINT2, NO_IRQ }
-#define UART2_DMA	{ 11, 10 }
 #define SSP_IRQ		{ IRQ_SSPINT, NO_IRQ }
-#define SSP_DMA		{ 9, 8 }
 
 /* FPGA Primecells */
 AMBA_DEVICE(aaci,  "fpga:04", AACI,     NULL);
@@ -865,14 +699,21 @@
 }
 #endif	/* CONFIG_LEDS */
 
-void __init versatile_init(void)
+/* Early initializations */
+void __init versatile_init_early(void)
 {
-	int i;
-
-	osc4_clk.vcoreg	= __io_address(VERSATILE_SYS_BASE) + VERSATILE_SYS_OSCCLCD_OFFSET;
+	void __iomem *sys = __io_address(VERSATILE_SYS_BASE);
 
+	osc4_clk.vcoreg	= sys + VERSATILE_SYS_OSCCLCD_OFFSET;
 	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
 
+	versatile_sched_clock_init(sys + VERSATILE_SYS_24MHz_OFFSET, 24000000);
+}
+
+void __init versatile_init(void)
+{
+	int i;
+
 	platform_device_register(&versatile_flash_device);
 	platform_device_register(&versatile_i2c_device);
 	platform_device_register(&smc91x_device);
@@ -889,12 +730,6 @@
 }
 
 /*
- * The sched_clock counter
- */
-#define REFCOUNTER		(__io_address(VERSATILE_SYS_BASE) + \
-				 VERSATILE_SYS_24MHz_OFFSET)
-
-/*
  * Where is the timer (VA)?
  */
 #define TIMER0_VA_BASE		 __io_address(VERSATILE_TIMER0_1_BASE)
@@ -909,8 +744,6 @@
 {
 	u32 val;
 
-	versatile_sched_clock_init(REFCOUNTER, 24000000);
-
 	/* 
 	 * set clock frequency: 
 	 *	VERSATILE_REFCLK is 32KHz
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-versatile/core.h linux-libre-2.6.39-gnu/arch/arm/mach-versatile/core.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-versatile/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-versatile/core.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/amba/bus.h>
 
 extern void __init versatile_init(void);
+extern void __init versatile_init_early(void);
 extern void __init versatile_init_irq(void);
 extern void __init versatile_map_io(void);
 extern struct sys_timer versatile_timer;
@@ -44,7 +45,6 @@
 	},							\
 	.dma_mask	= ~0,					\
 	.irq		= base##_IRQ,				\
-	/* .dma		= base##_DMA,*/				\
 }
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-versatile/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-versatile/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-versatile/include/mach/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-versatile/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,6 @@
 /* macro to get at IO space when running virtually */
 #define IO_ADDRESS(x)		(((x) & 0x0fffffff) + (((x) >> 4) & 0x0f000000) + 0xf0000000)
 
-#define __io_address(n)		__io(IO_ADDRESS(n))
+#define __io_address(n)		((void __iomem __force *)IO_ADDRESS(n))
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-versatile/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-versatile/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-versatile/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-versatile/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-versatile/versatile_ab.c linux-libre-2.6.39-gnu/arch/arm/mach-versatile/versatile_ab.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-versatile/versatile_ab.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-versatile/versatile_ab.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,6 +37,7 @@
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.boot_params	= 0x00000100,
 	.map_io		= versatile_map_io,
+	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
 	.timer		= &versatile_timer,
 	.init_machine	= versatile_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-versatile/versatile_pb.c linux-libre-2.6.39-gnu/arch/arm/mach-versatile/versatile_pb.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-versatile/versatile_pb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-versatile/versatile_pb.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,19 +59,14 @@
 };
 
 #define UART3_IRQ	{ IRQ_SIC_UART3, NO_IRQ }
-#define UART3_DMA	{ 0x86, 0x87 }
 #define SCI1_IRQ	{ IRQ_SIC_SCI3, NO_IRQ }
-#define SCI1_DMA	{ 0x88, 0x89 }
 #define MMCI1_IRQ	{ IRQ_MMCI1A, IRQ_SIC_MMCI1B }
-#define MMCI1_DMA	{ 0x85, 0 }
 
 /*
  * These devices are connected via the core APB bridge
  */
 #define GPIO2_IRQ	{ IRQ_GPIOINT2, NO_IRQ }
-#define GPIO2_DMA	{ 0, 0 }
 #define GPIO3_IRQ	{ IRQ_GPIOINT3, NO_IRQ }
-#define GPIO3_DMA	{ 0, 0 }
 
 /*
  * These devices are connected via the DMA APB bridge
@@ -110,6 +105,7 @@
 	/* Maintainer: ARM Ltd/Deep Blue Solutions Ltd */
 	.boot_params	= 0x00000100,
 	.map_io		= versatile_map_io,
+	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
 	.timer		= &versatile_timer,
 	.init_machine	= versatile_pb_init,
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/core.h linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/core.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/core.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,8 +17,3 @@
 	.irq		= IRQ_##base,		\
 	/* .dma		= DMA_##base,*/		\
 }
-
-struct map_desc;
-
-void v2m_map_io(struct map_desc *tile, size_t num);
-extern struct sys_timer v2m_timer;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/ct-ca9x4.c linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/ct-ca9x4.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/ct-ca9x4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/ct-ca9x4.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,19 +10,17 @@
 #include <linux/amba/clcd.h>
 #include <linux/clkdev.h>
 
-#include <asm/pgtable.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/hardware/gic.h>
-#include <asm/mach-types.h>
 #include <asm/pmu.h>
+#include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
 #include <mach/ct-ca9x4.h>
 
 #include <asm/hardware/timer-sp.h>
 
-#include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
@@ -30,6 +28,8 @@
 
 #include <mach/motherboard.h>
 
+#include <plat/clcd.h>
+
 #define V2M_PA_CS7	0x10000000
 
 static struct map_desc ct_ca9x4_io_desc[] __initdata = {
@@ -56,7 +56,7 @@
 #ifdef CONFIG_LOCAL_TIMERS
 	twd_base = MMIO_P2V(A9_MPCORE_TWD);
 #endif
-	v2m_map_io(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
+	iotable_init(ct_ca9x4_io_desc, ARRAY_SIZE(ct_ca9x4_io_desc));
 }
 
 static void __init ct_ca9x4_init_irq(void)
@@ -80,29 +80,6 @@
 };
 #endif
 
-static struct clcd_panel xvga_panel = {
-	.mode		= {
-		.name		= "XVGA",
-		.refresh	= 60,
-		.xres		= 1024,
-		.yres		= 768,
-		.pixclock	= 15384,
-		.left_margin	= 168,
-		.right_margin	= 8,
-		.upper_margin	= 29,
-		.lower_margin	= 3,
-		.hsync_len	= 144,
-		.vsync_len	= 6,
-		.sync		= 0,
-		.vmode		= FB_VMODE_NONINTERLACED,
-	},
-	.width		= -1,
-	.height		= -1,
-	.tim2		= TIM2_BCD | TIM2_IPC,
-	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
-	.bpp		= 16,
-};
-
 static void ct_ca9x4_clcd_enable(struct clcd_fb *fb)
 {
 	v2m_cfg_write(SYS_CFG_MUXFPGA | SYS_CFG_SITE_DB1, 0);
@@ -112,42 +89,23 @@
 static int ct_ca9x4_clcd_setup(struct clcd_fb *fb)
 {
 	unsigned long framesize = 1024 * 768 * 2;
-	dma_addr_t dma;
-
-	fb->panel = &xvga_panel;
 
-	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
-				&dma, GFP_KERNEL);
-	if (!fb->fb.screen_base) {
-		printk(KERN_ERR "CLCD: unable to map frame buffer\n");
-		return -ENOMEM;
-	}
-	fb->fb.fix.smem_start = dma;
-	fb->fb.fix.smem_len = framesize;
-
-	return 0;
-}
-
-static int ct_ca9x4_clcd_mmap(struct clcd_fb *fb, struct vm_area_struct *vma)
-{
-	return dma_mmap_writecombine(&fb->dev->dev, vma, fb->fb.screen_base,
-		fb->fb.fix.smem_start, fb->fb.fix.smem_len);
-}
+	fb->panel = versatile_clcd_get_panel("XVGA");
+	if (!fb->panel)
+		return -EINVAL;
 
-static void ct_ca9x4_clcd_remove(struct clcd_fb *fb)
-{
-	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
-		fb->fb.screen_base, fb->fb.fix.smem_start);
+	return versatile_clcd_setup_dma(fb, framesize);
 }
 
 static struct clcd_board ct_ca9x4_clcd_data = {
 	.name		= "CT-CA9X4",
+	.caps		= CLCD_CAP_5551 | CLCD_CAP_565,
 	.check		= clcdfb_check,
 	.decode		= clcdfb_decode,
 	.enable		= ct_ca9x4_clcd_enable,
 	.setup		= ct_ca9x4_clcd_setup,
-	.mmap		= ct_ca9x4_clcd_mmap,
-	.remove		= ct_ca9x4_clcd_remove,
+	.mmap		= versatile_clcd_mmap_dma,
+	.remove		= versatile_clcd_remove_dma,
 };
 
 static AMBA_DEVICE(clcd, "ct:clcd", CT_CA9X4_CLCDC, &ct_ca9x4_clcd_data);
@@ -220,6 +178,11 @@
 	.resource	= pmu_resources,
 };
 
+static void __init ct_ca9x4_init_early(void)
+{
+	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
+}
+
 static void __init ct_ca9x4_init(void)
 {
 	int i;
@@ -234,22 +197,40 @@
 	l2x0_init(l2x0_base, 0x00400000, 0xfe0fffff);
 #endif
 
-	clkdev_add_table(lookups, ARRAY_SIZE(lookups));
-
 	for (i = 0; i < ARRAY_SIZE(ct_ca9x4_amba_devs); i++)
 		amba_device_register(ct_ca9x4_amba_devs[i], &iomem_resource);
 
 	platform_device_register(&pmu_device);
 }
 
-MACHINE_START(VEXPRESS, "ARM-Versatile Express CA9x4")
-	.boot_params	= PHYS_OFFSET + 0x00000100,
+#ifdef CONFIG_SMP
+static void ct_ca9x4_init_cpu_map(void)
+{
+	int i, ncores = scu_get_core_count(MMIO_P2V(A9_MPCORE_SCU));
+
+	for (i = 0; i < ncores; ++i)
+		set_cpu_possible(i, true);
+}
+
+static void ct_ca9x4_smp_enable(unsigned int max_cpus)
+{
+	int i;
+	for (i = 0; i < max_cpus; i++)
+		set_cpu_present(i, true);
+
+	scu_enable(MMIO_P2V(A9_MPCORE_SCU));
+}
+#endif
+
+struct ct_desc ct_ca9x4_desc __initdata = {
+	.id		= V2M_CT_ID_CA9,
+	.name		= "CA9x4",
 	.map_io		= ct_ca9x4_map_io,
+	.init_early	= ct_ca9x4_init_early,
 	.init_irq	= ct_ca9x4_init_irq,
-#if 0
-	.timer		= &ct_ca9x4_timer,
-#else
-	.timer		= &v2m_timer,
+	.init_tile	= ct_ca9x4_init,
+#ifdef CONFIG_SMP
+	.init_cpu_map	= ct_ca9x4_init_cpu_map,
+	.smp_enable	= ct_ca9x4_smp_enable,
 #endif
-	.init_machine	= ct_ca9x4_init,
-MACHINE_END
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/headsmp.S linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/headsmp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/headsmp.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,40 +0,0 @@
-/*
- *  linux/arch/arm/mach-vexpress/headsmp.S
- *
- *  Copyright (c) 2003 ARM Limited
- *  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/linkage.h>
-#include <linux/init.h>
-
-	__INIT
-
-/*
- * Versatile Express specific entry point for secondary CPUs.  This
- * provides a "holding pen" into which all secondary cores are held
- * until we're ready for them to initialise.
- */
-ENTRY(vexpress_secondary_startup)
-	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
-	adr	r4, 1f
-	ldmia	r4, {r5, r6}
-	sub	r4, r4, r5
-	add	r6, r6, r4
-pen:	ldr	r7, [r6]
-	cmp	r7, r0
-	bne	pen
-
-	/*
-	 * we've been released from the holding pen: secondary_stack
-	 * should now contain the SVC stack for this core
-	 */
-	b	secondary_startup
-
-	.align
-1:	.long	.
-	.long	pen_release
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/include/mach/ct-ca9x4.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,4 +45,6 @@
 #define IRQ_CT_CA9X4_PMU_CPU2	94
 #define IRQ_CT_CA9X4_PMU_CPU3	95
 
+extern struct ct_desc ct_ca9x4_desc;
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET		UL(0x60000000)
+#define PLAT_PHYS_OFFSET		UL(0x60000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/include/mach/motherboard.h linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/include/mach/motherboard.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/include/mach/motherboard.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/include/mach/motherboard.h	2011-05-19 00:06:34.000000000 -0400
@@ -118,4 +118,26 @@
 int v2m_cfg_write(u32 devfn, u32 data);
 int v2m_cfg_read(u32 devfn, u32 *data);
 
+/*
+ * Core tile IDs
+ */
+#define V2M_CT_ID_CA9		0x0c000191
+#define V2M_CT_ID_UNSUPPORTED	0xff000191
+#define V2M_CT_ID_MASK		0xff000fff
+
+struct ct_desc {
+	u32			id;
+	const char		*name;
+	void			(*map_io)(void);
+	void			(*init_early)(void);
+	void			(*init_irq)(void);
+	void			(*init_tile)(void);
+#ifdef CONFIG_SMP
+	void			(*init_cpu_map)(void);
+	void			(*smp_enable)(unsigned int);
+#endif
+};
+
+extern struct ct_desc *ct_desc;
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -5,5 +5,8 @@
 	bool "Versatile Express Cortex-A9x4 tile"
 	select CPU_V7
 	select ARM_GIC
+	select ARM_ERRATA_720789
+	select ARM_ERRATA_751472
+	select ARM_ERRATA_753970
 
 endmenu
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/localtimer.c linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/localtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/localtimer.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/*
- *  linux/arch/arm/mach-vexpress/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/smp.h>
-#include <linux/clockchips.h>
-
-#include <asm/smp_twd.h>
-#include <asm/localtimer.h>
-#include <mach/irqs.h>
-
-/*
- * Setup the local clock events for a CPU.
- */
-void __cpuinit local_timer_setup(struct clock_event_device *evt)
-{
-	evt->irq = IRQ_LOCALTIMER;
-	twd_timer_setup(evt);
-}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,6 +4,5 @@
 
 obj-y					:= v2m.o
 obj-$(CONFIG_ARCH_VEXPRESS_CA9X4)	+= ct-ca9x4.o
-obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
+obj-$(CONFIG_SMP)			+= platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU)		+= hotplug.o
-obj-$(CONFIG_LOCAL_TIMERS)		+= localtimer.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/platsmp.c linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/platsmp.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/platsmp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/platsmp.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,114 +10,17 @@
  */
 #include <linux/init.h>
 #include <linux/errno.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
 
-#include <asm/cacheflush.h>
-#include <asm/smp_scu.h>
 #include <asm/unified.h>
 
-#include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
 #define V2M_PA_CS7 0x10000000
 
 #include "core.h"
 
-extern void vexpress_secondary_startup(void);
-
-/*
- * control for which core is the next to come out of the secondary
- * boot "holding pen"
- */
-volatile int __cpuinitdata pen_release = -1;
-
-/*
- * Write pen_release in a way that is guaranteed to be visible to all
- * observers, irrespective of whether they're taking part in coherency
- * or not.  This is necessary for the hotplug code to work reliably.
- */
-static void __cpuinit write_pen_release(int val)
-{
-	pen_release = val;
-	smp_wmb();
-	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
-	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
-}
-
-static void __iomem *scu_base_addr(void)
-{
-	return MMIO_P2V(A9_MPCORE_SCU);
-}
-
-static DEFINE_SPINLOCK(boot_lock);
-
-void __cpuinit platform_secondary_init(unsigned int cpu)
-{
-	/*
-	 * 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_secondary_init(0);
-
-	/*
-	 * let the primary processor know we're out of the
-	 * pen, then head off into the C entry point
-	 */
-	write_pen_release(-1);
-
-	/*
-	 * 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);
-
-	/*
-	 * This is really belt and braces; we hold unintended secondary
-	 * CPUs in the holding pen until we're ready for them.  However,
-	 * since we haven't sent them a soft interrupt, they shouldn't
-	 * be there.
-	 */
-	write_pen_release(cpu);
-
-	/*
-	 * Send the secondary CPU a soft interrupt, thereby causing
-	 * the boot monitor to read the system wide flags register,
-	 * and branch to the address found there.
-	 */
-	smp_cross_call(cpumask_of(cpu), 1);
-
-	timeout = jiffies + (1 * HZ);
-	while (time_before(jiffies, timeout)) {
-		smp_rmb();
-		if (pen_release == -1)
-			break;
-
-		udelay(10);
-	}
-
-	/*
-	 * now the secondary core is starting up let it run its
-	 * calibrations, then wait for it to finish
-	 */
-	spin_unlock(&boot_lock);
-
-	return pen_release != -1 ? -ENOSYS : 0;
-}
+extern void versatile_secondary_startup(void);
 
 /*
  * Initialise the CPU possible map early - this describes the CPUs
@@ -125,36 +28,16 @@
  */
 void __init smp_init_cpus(void)
 {
-	void __iomem *scu_base = scu_base_addr();
-	unsigned int i, ncores;
-
-	ncores = scu_base ? scu_get_core_count(scu_base) : 1;
-
-	/* sanity check */
-	if (ncores > NR_CPUS) {
-		printk(KERN_WARNING
-		       "vexpress: no. of cores (%d) greater than configured "
-		       "maximum of %d - clipping\n",
-		       ncores, NR_CPUS);
-		ncores = NR_CPUS;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
+	ct_desc->init_cpu_map();
 }
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i;
-
 	/*
 	 * 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);
-
-	scu_enable(scu_base_addr());
+	ct_desc->smp_enable(max_cpus);
 
 	/*
 	 * Write the address of secondary startup into the
@@ -163,6 +46,6 @@
 	 * secondary CPU branches to this address.
 	 */
 	writel(~0, MMIO_P2V(V2M_SYS_FLAGSCLR));
-	writel(BSYM(virt_to_phys(vexpress_secondary_startup)),
+	writel(BSYM(virt_to_phys(versatile_secondary_startup)),
 		MMIO_P2V(V2M_SYS_FLAGSSET));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/v2m.c linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/v2m.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vexpress/v2m.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vexpress/v2m.c	2011-05-19 00:06:34.000000000 -0400
@@ -7,13 +7,16 @@
 #include <linux/io.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
+#include <linux/ata_platform.h>
 #include <linux/smsc911x.h>
 #include <linux/spinlock.h>
 #include <linux/sysdev.h>
 #include <linux/usb/isp1760.h>
 #include <linux/clkdev.h>
 
+#include <asm/mach-types.h>
 #include <asm/sizes.h>
+#include <asm/mach/arch.h>
 #include <asm/mach/flash.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -21,6 +24,7 @@
 #include <asm/hardware/timer-sp.h>
 #include <asm/hardware/sp810.h>
 
+#include <mach/ct-ca9x4.h>
 #include <mach/motherboard.h>
 
 #include <plat/sched_clock.h>
@@ -42,19 +46,16 @@
 	},
 };
 
-void __init v2m_map_io(struct map_desc *tile, size_t num)
+static void __init v2m_init_early(void)
 {
-	iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
-	iotable_init(tile, num);
+	ct_desc->init_early();
+	versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
 }
 
-
 static void __init v2m_timer_init(void)
 {
 	u32 scctrl;
 
-	versatile_sched_clock_init(MMIO_P2V(V2M_SYS_24MHZ), 24000000);
-
 	/* Select 1MHz TIMCLK as the reference clock for SP804 timers */
 	scctrl = readl(MMIO_P2V(V2M_SYSCTL + SCCTRL));
 	scctrl |= SCCTRL_TIMEREN0SEL_TIMCLK;
@@ -68,7 +69,7 @@
 	sp804_clockevents_init(MMIO_P2V(V2M_TIMER0), IRQ_V2M_TIMER0);
 }
 
-struct sys_timer v2m_timer = {
+static struct sys_timer v2m_timer = {
 	.init	= v2m_timer_init,
 };
 
@@ -249,6 +250,29 @@
 	.dev.platform_data = &v2m_flash_data,
 };
 
+static struct pata_platform_info v2m_pata_data = {
+	.ioport_shift	= 2,
+};
+
+static struct resource v2m_pata_resources[] = {
+	{
+		.start	= V2M_CF,
+		.end	= V2M_CF + 0xff,
+		.flags	= IORESOURCE_MEM,
+	}, {
+		.start	= V2M_CF + 0x100,
+		.end	= V2M_CF + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device v2m_cf_device = {
+	.name		= "pata_platform",
+	.id		= -1,
+	.resource	= v2m_pata_resources,
+	.num_resources	= ARRAY_SIZE(v2m_pata_resources),
+	.dev.platform_data = &v2m_pata_data,
+};
 
 static unsigned int v2m_mmci_status(struct device *dev)
 {
@@ -354,7 +378,44 @@
 		printk(KERN_EMERG "Unable to reboot\n");
 }
 
-static int __init v2m_init(void)
+struct ct_desc *ct_desc;
+
+static struct ct_desc *ct_descs[] __initdata = {
+#ifdef CONFIG_ARCH_VEXPRESS_CA9X4
+	&ct_ca9x4_desc,
+#endif
+};
+
+static void __init v2m_populate_ct_desc(void)
+{
+	int i;
+	u32 current_tile_id;
+
+	ct_desc = NULL;
+	current_tile_id = readl(MMIO_P2V(V2M_SYS_PROCID0)) & V2M_CT_ID_MASK;
+
+	for (i = 0; i < ARRAY_SIZE(ct_descs) && !ct_desc; ++i)
+		if (ct_descs[i]->id == current_tile_id)
+			ct_desc = ct_descs[i];
+
+	if (!ct_desc)
+		panic("vexpress: failed to populate core tile description "
+		      "for tile ID 0x%8x\n", current_tile_id);
+}
+
+static void __init v2m_map_io(void)
+{
+	iotable_init(v2m_io_desc, ARRAY_SIZE(v2m_io_desc));
+	v2m_populate_ct_desc();
+	ct_desc->map_io();
+}
+
+static void __init v2m_init_irq(void)
+{
+	ct_desc->init_irq();
+}
+
+static void __init v2m_init(void)
 {
 	int i;
 
@@ -363,6 +424,7 @@
 	platform_device_register(&v2m_pcie_i2c_device);
 	platform_device_register(&v2m_ddc_i2c_device);
 	platform_device_register(&v2m_flash_device);
+	platform_device_register(&v2m_cf_device);
 	platform_device_register(&v2m_eth_device);
 	platform_device_register(&v2m_usb_device);
 
@@ -372,6 +434,14 @@
 	pm_power_off = v2m_power_off;
 	arm_pm_restart = v2m_restart;
 
-	return 0;
+	ct_desc->init_tile();
 }
-arch_initcall(v2m_init);
+
+MACHINE_START(VEXPRESS, "ARM-Versatile Express")
+	.boot_params	= PLAT_PHYS_OFFSET + 0x00000100,
+	.map_io		= v2m_map_io,
+	.init_early	= v2m_init_early,
+	.init_irq	= v2m_init_irq,
+	.timer		= &v2m_timer,
+	.init_machine	= v2m_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/bv07.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/bv07.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/bv07.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/bv07.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ *  arch/arm/mach-vt8500/bv07.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "devices.h"
+
+static void __iomem *pmc_hiber;
+
+static struct platform_device *devices[] __initdata = {
+	&vt8500_device_uart0,
+	&vt8500_device_lcdc,
+	&vt8500_device_ehci,
+	&vt8500_device_ge_rops,
+	&vt8500_device_pwm,
+	&vt8500_device_pwmbl,
+	&vt8500_device_rtc,
+};
+
+static void vt8500_power_off(void)
+{
+	local_irq_disable();
+	writew(5, pmc_hiber);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init bv07_init(void)
+{
+#ifdef CONFIG_FB_VT8500
+	void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
+	if (gpio_mux_reg) {
+		writel(readl(gpio_mux_reg) | 1, gpio_mux_reg);
+		iounmap(gpio_mux_reg);
+	} else {
+		printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
+	}
+#endif
+	pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
+	if (pmc_hiber)
+		pm_power_off = &vt8500_power_off;
+	else
+		printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
+
+	vt8500_set_resources();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	vt8500_gpio_init();
+}
+
+MACHINE_START(BV07, "Benign BV07 Mini Netbook")
+	.boot_params	= 0x00000100,
+	.reserve	= vt8500_reserve_mem,
+	.map_io		= vt8500_map_io,
+	.init_irq	= vt8500_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= bv07_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,270 @@
+/* linux/arch/arm/mach-vt8500/devices.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/io.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/pwm_backlight.h>
+#include <linux/memblock.h>
+
+#include <asm/mach/arch.h>
+
+#include <mach/vt8500fb.h>
+#include <mach/i8042.h>
+#include "devices.h"
+
+/* These can't use resources currently */
+unsigned long wmt_ic_base __initdata;
+unsigned long wmt_sic_base __initdata;
+unsigned long wmt_gpio_base __initdata;
+unsigned long wmt_pmc_base __initdata;
+unsigned long wmt_i8042_base __initdata;
+
+int wmt_nr_irqs __initdata;
+int wmt_timer_irq __initdata;
+int wmt_gpio_ext_irq[8] __initdata;
+
+/* Should remain accessible after init.
+ * i8042 driver desperately calls for attention...
+ */
+int wmt_i8042_kbd_irq;
+int wmt_i8042_aux_irq;
+
+static u64 fb_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device vt8500_device_lcdc = {
+	.name           = "vt8500-lcd",
+	.id             = 0,
+	.dev		= {
+		.dma_mask	= &fb_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device vt8500_device_wm8505_fb = {
+	.name           = "wm8505-fb",
+	.id             = 0,
+};
+
+/* Smallest to largest */
+static struct vt8500fb_platform_data panels[] = {
+#ifdef CONFIG_WMT_PANEL_800X480
+{
+	.xres_virtual	= 800,
+	.yres_virtual	= 480 * 2,
+	.mode		= {
+		.name		= "800x480",
+		.xres		= 800,
+		.yres		= 480,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 1,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+#ifdef CONFIG_WMT_PANEL_800X600
+{
+	.xres_virtual	= 800,
+	.yres_virtual	= 600 * 2,
+	.mode		= {
+		.name		= "800x600",
+		.xres		= 800,
+		.yres		= 600,
+		.left_margin	= 88,
+		.right_margin	= 40,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 0,
+		.vsync_len	= 1,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+#ifdef CONFIG_WMT_PANEL_1024X576
+{
+	.xres_virtual	= 1024,
+	.yres_virtual	= 576 * 2,
+	.mode		= {
+		.name		= "1024x576",
+		.xres		= 1024,
+		.yres		= 576,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+#ifdef CONFIG_WMT_PANEL_1024X600
+{
+	.xres_virtual	= 1024,
+	.yres_virtual	= 600 * 2,
+	.mode		= {
+		.name		= "1024x600",
+		.xres		= 1024,
+		.yres		= 600,
+		.left_margin	= 66,
+		.right_margin	= 2,
+		.upper_margin	= 19,
+		.lower_margin	= 1,
+		.hsync_len	= 23,
+		.vsync_len	= 8,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+},
+#endif
+};
+
+static int current_panel_idx __initdata = ARRAY_SIZE(panels) - 1;
+
+static int __init panel_setup(char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(panels); i++) {
+		if (strcmp(panels[i].mode.name, str) == 0) {
+			current_panel_idx = i;
+			break;
+		}
+	}
+	return 0;
+}
+
+early_param("panel", panel_setup);
+
+static inline void preallocate_fb(struct vt8500fb_platform_data *p,
+				  unsigned long align) {
+	p->video_mem_len = (p->xres_virtual * p->yres_virtual * 4) >>
+			(p->bpp > 16 ? 0 : (p->bpp > 8 ? 1 :
+					(8 / p->bpp) + 1));
+	p->video_mem_phys = (unsigned long)memblock_alloc(p->video_mem_len,
+							  align);
+	p->video_mem_virt = phys_to_virt(p->video_mem_phys);
+}
+
+struct platform_device vt8500_device_uart0 = {
+	.name		= "vt8500_serial",
+	.id		= 0,
+};
+
+struct platform_device vt8500_device_uart1 = {
+	.name		= "vt8500_serial",
+	.id		= 1,
+};
+
+struct platform_device vt8500_device_uart2 = {
+	.name		= "vt8500_serial",
+	.id		= 2,
+};
+
+struct platform_device vt8500_device_uart3 = {
+	.name		= "vt8500_serial",
+	.id		= 3,
+};
+
+struct platform_device vt8500_device_uart4 = {
+	.name		= "vt8500_serial",
+	.id		= 4,
+};
+
+struct platform_device vt8500_device_uart5 = {
+	.name		= "vt8500_serial",
+	.id		= 5,
+};
+
+static u64 ehci_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device vt8500_device_ehci = {
+	.name		= "vt8500-ehci",
+	.id		= 0,
+	.dev		= {
+		.dma_mask	= &ehci_dma_mask,
+		.coherent_dma_mask = DMA_BIT_MASK(32),
+	},
+};
+
+struct platform_device vt8500_device_ge_rops = {
+	.name		= "wmt_ge_rops",
+	.id		= -1,
+};
+
+struct platform_device vt8500_device_pwm = {
+	.name		= "vt8500-pwm",
+	.id		= 0,
+};
+
+static struct platform_pwm_backlight_data vt8500_pwmbl_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 128,
+	.dft_brightness = 70,
+	.pwm_period_ns	= 250000, /* revisit when clocks are implemented */
+};
+
+struct platform_device vt8500_device_pwmbl = {
+	.name		= "pwm-backlight",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &vt8500_pwmbl_data,
+	},
+};
+
+struct platform_device vt8500_device_rtc = {
+	.name		= "vt8500-rtc",
+	.id		= 0,
+};
+
+struct map_desc wmt_io_desc[] __initdata = {
+	/* SoC MMIO registers */
+	[0] = {
+		.virtual	= 0xf8000000,
+		.pfn		= __phys_to_pfn(0xd8000000),
+		.length		= 0x00390000, /* max of all chip variants */
+		.type		= MT_DEVICE
+	},
+	/* PCI I/O space, numbers tied to those in <mach/io.h> */
+	[1] = {
+		.virtual	= 0xf0000000,
+		.pfn		= __phys_to_pfn(0xc0000000),
+		.length		= SZ_64K,
+		.type		= MT_DEVICE
+	},
+};
+
+void __init vt8500_reserve_mem(void)
+{
+#ifdef CONFIG_FB_VT8500
+	panels[current_panel_idx].bpp = 16; /* Always use RGB565 */
+	preallocate_fb(&panels[current_panel_idx], SZ_4M);
+	vt8500_device_lcdc.dev.platform_data = &panels[current_panel_idx];
+#endif
+}
+
+void __init wm8505_reserve_mem(void)
+{
+#if defined CONFIG_FB_WM8505
+	panels[current_panel_idx].bpp = 32; /* Always use RGB888 */
+	preallocate_fb(&panels[current_panel_idx], 32);
+	vt8500_device_wm8505_fb.dev.platform_data = &panels[current_panel_idx];
+#endif
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,88 @@
+/* linux/arch/arm/mach-vt8500/devices.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_VT8500_DEVICES_H
+#define __ARCH_ARM_MACH_VT8500_DEVICES_H
+
+#include <linux/platform_device.h>
+#include <asm/mach/map.h>
+
+void __init vt8500_init_irq(void);
+void __init wm8505_init_irq(void);
+void __init vt8500_map_io(void);
+void __init wm8505_map_io(void);
+void __init vt8500_reserve_mem(void);
+void __init wm8505_reserve_mem(void);
+void __init vt8500_gpio_init(void);
+void __init vt8500_set_resources(void);
+void __init wm8505_set_resources(void);
+
+extern unsigned long wmt_ic_base __initdata;
+extern unsigned long wmt_sic_base __initdata;
+extern unsigned long wmt_gpio_base __initdata;
+extern unsigned long wmt_pmc_base __initdata;
+
+extern int wmt_nr_irqs __initdata;
+extern int wmt_timer_irq __initdata;
+extern int wmt_gpio_ext_irq[8] __initdata;
+
+extern struct map_desc wmt_io_desc[2] __initdata;
+
+static inline struct resource wmt_mmio_res(u32 start, u32 size)
+{
+	struct resource tmp = {
+		.flags = IORESOURCE_MEM,
+		.start = start,
+		.end = start + size - 1,
+	};
+
+	return tmp;
+}
+
+static inline struct resource wmt_irq_res(int irq)
+{
+	struct resource tmp = {
+		.flags = IORESOURCE_IRQ,
+		.start = irq,
+		.end = irq,
+	};
+
+	return tmp;
+}
+
+static inline void wmt_res_add(struct platform_device *pdev,
+			       const struct resource *res, unsigned int num)
+{
+	if (unlikely(platform_device_add_resources(pdev, res, num)))
+		pr_err("Failed to assign resources\n");
+}
+
+extern struct sys_timer vt8500_timer;
+
+extern struct platform_device vt8500_device_uart0;
+extern struct platform_device vt8500_device_uart1;
+extern struct platform_device vt8500_device_uart2;
+extern struct platform_device vt8500_device_uart3;
+extern struct platform_device vt8500_device_uart4;
+extern struct platform_device vt8500_device_uart5;
+
+extern struct platform_device vt8500_device_lcdc;
+extern struct platform_device vt8500_device_wm8505_fb;
+extern struct platform_device vt8500_device_ehci;
+extern struct platform_device vt8500_device_ge_rops;
+extern struct platform_device vt8500_device_pwm;
+extern struct platform_device vt8500_device_pwmbl;
+extern struct platform_device vt8500_device_rtc;
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices-vt8500.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices-vt8500.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices-vt8500.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices-vt8500.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,91 @@
+/* linux/arch/arm/mach-vt8500/devices-vt8500.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+
+#include <mach/vt8500_regs.h>
+#include <mach/vt8500_irqs.h>
+#include <mach/i8042.h>
+#include "devices.h"
+
+void __init vt8500_set_resources(void)
+{
+	struct resource tmp[3];
+
+	tmp[0] = wmt_mmio_res(VT8500_LCDC_BASE, SZ_1K);
+	tmp[1] = wmt_irq_res(IRQ_LCDC);
+	wmt_res_add(&vt8500_device_lcdc, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART0_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART0);
+	wmt_res_add(&vt8500_device_uart0, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART1_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART1);
+	wmt_res_add(&vt8500_device_uart1, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART2_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART2);
+	wmt_res_add(&vt8500_device_uart2, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_UART3_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART3);
+	wmt_res_add(&vt8500_device_uart3, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_EHCI_BASE, SZ_512);
+	tmp[1] = wmt_irq_res(IRQ_EHCI);
+	wmt_res_add(&vt8500_device_ehci, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(VT8500_GEGEA_BASE, SZ_256);
+	wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(VT8500_PWM_BASE, 0x44);
+	wmt_res_add(&vt8500_device_pwm, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(VT8500_RTC_BASE, 0x2c);
+	tmp[1] = wmt_irq_res(IRQ_RTC);
+	tmp[2] = wmt_irq_res(IRQ_RTCSM);
+	wmt_res_add(&vt8500_device_rtc, tmp, 3);
+}
+
+static void __init vt8500_set_externs(void)
+{
+	/* Non-resource-aware stuff */
+	wmt_ic_base = VT8500_IC_BASE;
+	wmt_gpio_base = VT8500_GPIO_BASE;
+	wmt_pmc_base = VT8500_PMC_BASE;
+	wmt_i8042_base = VT8500_PS2_BASE;
+
+	wmt_nr_irqs = VT8500_NR_IRQS;
+	wmt_timer_irq = IRQ_PMCOS0;
+	wmt_gpio_ext_irq[0] = IRQ_EXT0;
+	wmt_gpio_ext_irq[1] = IRQ_EXT1;
+	wmt_gpio_ext_irq[2] = IRQ_EXT2;
+	wmt_gpio_ext_irq[3] = IRQ_EXT3;
+	wmt_gpio_ext_irq[4] = IRQ_EXT4;
+	wmt_gpio_ext_irq[5] = IRQ_EXT5;
+	wmt_gpio_ext_irq[6] = IRQ_EXT6;
+	wmt_gpio_ext_irq[7] = IRQ_EXT7;
+	wmt_i8042_kbd_irq = IRQ_PS2KBD;
+	wmt_i8042_aux_irq = IRQ_PS2MOUSE;
+}
+
+void __init vt8500_map_io(void)
+{
+	iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
+
+	/* Should be done before interrupts and timers are initialized */
+	vt8500_set_externs();
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices-wm8505.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices-wm8505.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/devices-wm8505.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/devices-wm8505.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,99 @@
+/* linux/arch/arm/mach-vt8500/devices-wm8505.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/platform_device.h>
+
+#include <mach/wm8505_regs.h>
+#include <mach/wm8505_irqs.h>
+#include <mach/i8042.h>
+#include "devices.h"
+
+void __init wm8505_set_resources(void)
+{
+	struct resource tmp[3];
+
+	tmp[0] = wmt_mmio_res(WM8505_GOVR_BASE, SZ_512);
+	wmt_res_add(&vt8500_device_wm8505_fb, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART0_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART0);
+	wmt_res_add(&vt8500_device_uart0, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART1_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART1);
+	wmt_res_add(&vt8500_device_uart1, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART2_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART2);
+	wmt_res_add(&vt8500_device_uart2, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART3_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART3);
+	wmt_res_add(&vt8500_device_uart3, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART4_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART4);
+	wmt_res_add(&vt8500_device_uart4, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_UART5_BASE, 0x1040);
+	tmp[1] = wmt_irq_res(IRQ_UART5);
+	wmt_res_add(&vt8500_device_uart5, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_EHCI_BASE, SZ_512);
+	tmp[1] = wmt_irq_res(IRQ_EHCI);
+	wmt_res_add(&vt8500_device_ehci, tmp, 2);
+
+	tmp[0] = wmt_mmio_res(WM8505_GEGEA_BASE, SZ_256);
+	wmt_res_add(&vt8500_device_ge_rops, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(WM8505_PWM_BASE, 0x44);
+	wmt_res_add(&vt8500_device_pwm, tmp, 1);
+
+	tmp[0] = wmt_mmio_res(WM8505_RTC_BASE, 0x2c);
+	tmp[1] = wmt_irq_res(IRQ_RTC);
+	tmp[2] = wmt_irq_res(IRQ_RTCSM);
+	wmt_res_add(&vt8500_device_rtc, tmp, 3);
+}
+
+static void __init wm8505_set_externs(void)
+{
+	/* Non-resource-aware stuff */
+	wmt_ic_base = WM8505_IC_BASE;
+	wmt_sic_base = WM8505_SIC_BASE;
+	wmt_gpio_base = WM8505_GPIO_BASE;
+	wmt_pmc_base = WM8505_PMC_BASE;
+	wmt_i8042_base = WM8505_PS2_BASE;
+
+	wmt_nr_irqs = WM8505_NR_IRQS;
+	wmt_timer_irq = IRQ_PMCOS0;
+	wmt_gpio_ext_irq[0] = IRQ_EXT0;
+	wmt_gpio_ext_irq[1] = IRQ_EXT1;
+	wmt_gpio_ext_irq[2] = IRQ_EXT2;
+	wmt_gpio_ext_irq[3] = IRQ_EXT3;
+	wmt_gpio_ext_irq[4] = IRQ_EXT4;
+	wmt_gpio_ext_irq[5] = IRQ_EXT5;
+	wmt_gpio_ext_irq[6] = IRQ_EXT6;
+	wmt_gpio_ext_irq[7] = IRQ_EXT7;
+	wmt_i8042_kbd_irq = IRQ_PS2KBD;
+	wmt_i8042_aux_irq = IRQ_PS2MOUSE;
+}
+
+void __init wm8505_map_io(void)
+{
+	iotable_init(wmt_io_desc, ARRAY_SIZE(wmt_io_desc));
+
+	/* Should be done before interrupts and timers are initialized */
+	wm8505_set_externs();
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/gpio.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,240 @@
+/* linux/arch/arm/mach-vt8500/gpio.c
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/gpio.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include "devices.h"
+
+#define to_vt8500(__chip) container_of(__chip, struct vt8500_gpio_chip, chip)
+
+#define ENABLE_REGS	0x0
+#define DIRECTION_REGS	0x20
+#define OUTVALUE_REGS	0x40
+#define INVALUE_REGS	0x60
+
+#define EXT_REGOFF	0x1c
+
+static void __iomem *regbase;
+
+struct vt8500_gpio_chip {
+	struct gpio_chip	chip;
+	unsigned int		shift;
+	unsigned int		regoff;
+};
+
+static int gpio_to_irq_map[8];
+
+static int vt8500_muxed_gpio_request(struct gpio_chip *chip,
+				     unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
+
+	val |= (1 << vt8500_chip->shift << offset);
+	writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
+
+	return 0;
+}
+
+static void vt8500_muxed_gpio_free(struct gpio_chip *chip,
+				   unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + ENABLE_REGS + vt8500_chip->regoff);
+
+	val &= ~(1 << vt8500_chip->shift << offset);
+	writel(val, regbase + ENABLE_REGS + vt8500_chip->regoff);
+}
+
+static int vt8500_muxed_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	val &= ~(1 << vt8500_chip->shift << offset);
+	writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	return 0;
+}
+
+static int vt8500_muxed_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	val |= (1 << vt8500_chip->shift << offset);
+	writel(val, regbase + DIRECTION_REGS + vt8500_chip->regoff);
+
+	if (value) {
+		val = readl(regbase + OUTVALUE_REGS + vt8500_chip->regoff);
+		val |= (1 << vt8500_chip->shift << offset);
+		writel(val, regbase + OUTVALUE_REGS + vt8500_chip->regoff);
+	}
+	return 0;
+}
+
+static int vt8500_muxed_gpio_get_value(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+
+	return (readl(regbase + INVALUE_REGS + vt8500_chip->regoff)
+		>> vt8500_chip->shift >> offset) & 1;
+}
+
+static void vt8500_muxed_gpio_set_value(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	struct vt8500_gpio_chip *vt8500_chip = to_vt8500(chip);
+	unsigned val = readl(regbase + INVALUE_REGS + vt8500_chip->regoff);
+
+	if (value)
+		val |= (1 << vt8500_chip->shift << offset);
+	else
+		val &= ~(1 << vt8500_chip->shift << offset);
+
+	writel(val, regbase + INVALUE_REGS + vt8500_chip->regoff);
+}
+
+#define VT8500_GPIO_BANK(__name, __shift, __off, __base, __num)		\
+{									\
+	.chip = {							\
+		.label			= __name,			\
+		.request		= vt8500_muxed_gpio_request,	\
+		.free			= vt8500_muxed_gpio_free,	\
+		.direction_input  = vt8500_muxed_gpio_direction_input,	\
+		.direction_output = vt8500_muxed_gpio_direction_output,	\
+		.get			= vt8500_muxed_gpio_get_value,	\
+		.set			= vt8500_muxed_gpio_set_value,	\
+		.can_sleep		= 0,				\
+		.base			= __base,			\
+		.ngpio			= __num,			\
+	},								\
+	.shift		= __shift,					\
+	.regoff		= __off,					\
+}
+
+static struct vt8500_gpio_chip vt8500_muxed_gpios[] = {
+	VT8500_GPIO_BANK("uart0",	0,	0x0,	8,	4),
+	VT8500_GPIO_BANK("uart1",	4,	0x0,	12,	4),
+	VT8500_GPIO_BANK("spi0",	8,	0x0,	16,	4),
+	VT8500_GPIO_BANK("spi1",	12,	0x0,	20,	4),
+	VT8500_GPIO_BANK("spi2",	16,	0x0,	24,	4),
+	VT8500_GPIO_BANK("pwmout",	24,	0x0,	28,	2),
+
+	VT8500_GPIO_BANK("sdmmc",	0,	0x4,	30,	11),
+	VT8500_GPIO_BANK("ms",		16,	0x4,	41,	7),
+	VT8500_GPIO_BANK("i2c0",	24,	0x4,	48,	2),
+	VT8500_GPIO_BANK("i2c1",	26,	0x4,	50,	2),
+
+	VT8500_GPIO_BANK("mii",		0,	0x8,	52,	20),
+	VT8500_GPIO_BANK("see",		20,	0x8,	72,	4),
+	VT8500_GPIO_BANK("ide",		24,	0x8,	76,	7),
+
+	VT8500_GPIO_BANK("ccir",	0,	0xc,	83,	19),
+
+	VT8500_GPIO_BANK("ts",		8,	0x10,	102,	11),
+
+	VT8500_GPIO_BANK("lcd",		0,	0x14,	113,	23),
+};
+
+static int vt8500_gpio_direction_input(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
+
+	val &= ~(1 << offset);
+	writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
+	return 0;
+}
+
+static int vt8500_gpio_direction_output(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	unsigned val = readl(regbase + DIRECTION_REGS + EXT_REGOFF);
+
+	val |= (1 << offset);
+	writel(val, regbase + DIRECTION_REGS + EXT_REGOFF);
+
+	if (value) {
+		val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
+		val |= (1 << offset);
+		writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
+	}
+	return 0;
+}
+
+static int vt8500_gpio_get_value(struct gpio_chip *chip,
+				       unsigned offset)
+{
+	return (readl(regbase + INVALUE_REGS + EXT_REGOFF) >> offset) & 1;
+}
+
+static void vt8500_gpio_set_value(struct gpio_chip *chip,
+					unsigned offset, int value)
+{
+	unsigned val = readl(regbase + OUTVALUE_REGS + EXT_REGOFF);
+
+	if (value)
+		val |= (1 << offset);
+	else
+		val &= ~(1 << offset);
+
+	writel(val, regbase + OUTVALUE_REGS + EXT_REGOFF);
+}
+
+static int vt8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	if (offset > 7)
+		return -EINVAL;
+
+	return gpio_to_irq_map[offset];
+}
+
+static struct gpio_chip vt8500_external_gpios = {
+	.label			= "extgpio",
+	.direction_input	= vt8500_gpio_direction_input,
+	.direction_output	= vt8500_gpio_direction_output,
+	.get			= vt8500_gpio_get_value,
+	.set			= vt8500_gpio_set_value,
+	.to_irq			= vt8500_gpio_to_irq,
+	.can_sleep		= 0,
+	.base			= 0,
+	.ngpio			= 8,
+};
+
+void __init vt8500_gpio_init(void)
+{
+	int i;
+
+	for (i = 0; i < 8; i++)
+		gpio_to_irq_map[i] = wmt_gpio_ext_irq[i];
+
+	regbase = ioremap(wmt_gpio_base, SZ_64K);
+	if (!regbase) {
+		printk(KERN_ERR "Failed to map MMIO registers for GPIO\n");
+		return;
+	}
+
+	gpiochip_add(&vt8500_external_gpios);
+
+	for (i = 0; i < ARRAY_SIZE(vt8500_muxed_gpios); i++)
+		gpiochip_add(&vt8500_muxed_gpios[i].chip);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/debug-macro.S
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Debugging macro include header
+ *
+ * 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, rp, rv
+	mov	\rp,      #0x00200000
+	orr	\rv, \rp, #0xf8000000
+	orr	\rp, \rp, #0xd8000000
+	.endm
+
+	.macro	senduart,rd,rx
+	strb	\rd, [\rx, #0]
+	.endm
+
+	.macro	busyuart,rd,rx
+1001:	ldr	\rd, [\rx, #0x1c]
+	ands	\rd, \rd, #0x2
+	bne	1001b
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/entry-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/entry-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/entry-macro.S
+ *
+ * Low-level IRQ helper macros for VIA VT8500
+ *
+ * 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.
+ */
+
+	.macro	disable_fiq
+	.endm
+
+	.macro  get_irqnr_preamble, base, tmp
+	@ physical 0xd8140000 is virtual 0xf8140000
+	mov	\base, #0xf8000000
+	orr	\base, \base, #0x00140000
+	.endm
+
+	.macro  arch_ret_to_user, tmp1, tmp2
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldr	\irqnr, [\base]
+	cmp	\irqnr, #63 @ may be false positive, check interrupt status
+	bne	1001f
+	ldr	\irqstat, [\base, #0x84]
+	ands	\irqstat, #0x80000000
+	moveq	\irqnr, #0
+1001:
+	.endm
+
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+#include <asm-generic/gpio.h>
+
+#define gpio_get_value	__gpio_get_value
+#define gpio_set_value	__gpio_set_value
+#define gpio_cansleep	__gpio_cansleep
+#define gpio_to_irq	__gpio_to_irq
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,12 @@
+/* arch/arm/mach-vt8500/include/mach/hardware.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/i8042.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/i8042.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/i8042.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/i8042.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+/* arch/arm/mach-vt8500/include/mach/i8042.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+extern unsigned long wmt_i8042_base __initdata;
+extern int wmt_i8042_kbd_irq;
+extern int wmt_i8042_aux_irq;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/io.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/io.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/io.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 0xffff
+
+#define __io(a)		__typesafe_io((a) + 0xf0000000)
+#define __mem_pci(a)	(a)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* This value is just to make the core happy, never used otherwise */
+#define NR_IRQS 128
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/memory.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
+ */
+#ifndef __ASM_ARCH_MEMORY_H
+#define __ASM_ARCH_MEMORY_H
+
+/*
+ * Physical DRAM offset.
+ */
+#define PHYS_OFFSET	UL(0x00000000)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * arch/arm/mach-vt8500/include/mach/system.h
+ *
+ */
+#include <asm/io.h>
+
+/* PM Software Reset request register */
+#define VT8500_PMSR_VIRT	0xf8130060
+
+static inline void arch_idle(void)
+{
+	cpu_do_idle();
+}
+
+static inline void arch_reset(char mode, const char *cmd)
+{
+	writel(1, VT8500_PMSR_VIRT);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/timex.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/timex.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/timex.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/timex.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#ifndef MACH_TIMEX_H
+#define MACH_TIMEX_H
+
+#define CLOCK_TICK_RATE		(3000000)
+
+#endif /* MACH_TIMEX_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,37 @@
+/* arch/arm/mach-vt8500/include/mach/uncompress.h
+ *
+ * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * Based on arch/arm/mach-dove/include/mach/uncompress.h
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#define UART0_PHYS 0xd8200000
+#include <asm/io.h>
+
+static void putc(const char c)
+{
+	while (readb(UART0_PHYS + 0x1c) & 0x2)
+		/* Tx busy, wait and poll */;
+
+	writeb(c, UART0_PHYS);
+}
+
+static void flush(void)
+{
+}
+
+/*
+ * nothing to do
+ */
+#define arch_decomp_setup()
+#define arch_decomp_wdog()
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vmalloc.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vmalloc.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vmalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vmalloc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ *  arch/arm/mach-vt8500/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	0xd0000000UL
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vt8500fb.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vt8500fb.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vt8500fb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vt8500fb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ *  VT8500/WM8505 Frame Buffer platform data definitions
+ *
+ *  Copyright (C) 2010 Ed Spiridonov <edo.rus@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _VT8500FB_H
+#define _VT8500FB_H
+
+#include <linux/fb.h>
+
+struct vt8500fb_platform_data {
+	struct fb_videomode	mode;
+	u32			xres_virtual;
+	u32			yres_virtual;
+	u32			bpp;
+	unsigned long		video_mem_phys;
+	void			*video_mem_virt;
+	unsigned long		video_mem_len;
+};
+
+#endif /* _VT8500FB_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vt8500_irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,88 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vt8500_irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* VT8500 Interrupt Sources */
+
+#define IRQ_JPEGENC	0	/* JPEG Encoder */
+#define IRQ_JPEGDEC	1	/* JPEG Decoder */
+				/* Reserved */
+#define IRQ_PATA	3	/* PATA Controller */
+				/* Reserved */
+#define IRQ_DMA		5	/* DMA Controller */
+#define IRQ_EXT0	6	/* External Interrupt 0 */
+#define IRQ_EXT1	7	/* External Interrupt 1 */
+#define IRQ_GE		8	/* Graphic Engine */
+#define IRQ_GOV		9	/* Graphic Overlay Engine */
+#define IRQ_ETHER	10	/* Ethernet MAC */
+#define IRQ_MPEGTS	11	/* Transport Stream Interface */
+#define IRQ_LCDC	12	/* LCD Controller */
+#define IRQ_EXT2	13	/* External Interrupt 2 */
+#define IRQ_EXT3	14	/* External Interrupt 3 */
+#define IRQ_EXT4	15	/* External Interrupt 4 */
+#define IRQ_CIPHER	16	/* Cipher */
+#define IRQ_VPP		17	/* Video Post-Processor */
+#define IRQ_I2C1	18	/* I2C 1 */
+#define IRQ_I2C0	19	/* I2C 0 */
+#define IRQ_SDMMC	20	/* SD/MMC Controller */
+#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
+#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
+				/* Reserved */
+#define IRQ_SPI0	24	/* SPI 0 */
+#define IRQ_SPI1	25	/* SPI 1 */
+#define IRQ_SPI2	26	/* SPI 2 */
+#define IRQ_LCDDF	27	/* LCD Data Formatter */
+#define IRQ_NAND	28	/* NAND Flash Controller */
+#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
+#define IRQ_MS		30	/* MemoryStick Controller */
+#define IRQ_MS_DMA	31	/* MemoryStick Controller DMA */
+#define IRQ_UART0	32	/* UART 0 */
+#define IRQ_UART1	33	/* UART 1 */
+#define IRQ_I2S		34	/* I2S */
+#define IRQ_PCM		35	/* PCM */
+#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
+#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
+#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
+#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
+#define IRQ_VPU		40	/* Video Processing Unit */
+#define IRQ_VID		41	/* Video Digital Input Interface */
+#define IRQ_AC97	42	/* AC97 Interface */
+#define IRQ_EHCI	43	/* USB */
+#define IRQ_NOR		44	/* NOR Flash Controller */
+#define IRQ_PS2MOUSE	45	/* PS/2 Mouse */
+#define IRQ_PS2KBD	46	/* PS/2 Keyboard */
+#define IRQ_UART2	47	/* UART 2 */
+#define IRQ_RTC		48	/* RTC Interrupt */
+#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
+#define IRQ_UART3	50	/* UART 3 */
+#define IRQ_ADC		51	/* ADC */
+#define IRQ_EXT5	52	/* External Interrupt 5 */
+#define IRQ_EXT6	53	/* External Interrupt 6 */
+#define IRQ_EXT7	54	/* External Interrupt 7 */
+#define IRQ_CIR		55	/* CIR */
+#define IRQ_DMA0	56	/* DMA Channel 0 */
+#define IRQ_DMA1	57	/* DMA Channel 1 */
+#define IRQ_DMA2	58	/* DMA Channel 2 */
+#define IRQ_DMA3	59	/* DMA Channel 3 */
+#define IRQ_DMA4	60	/* DMA Channel 4 */
+#define IRQ_DMA5	61	/* DMA Channel 5 */
+#define IRQ_DMA6	62	/* DMA Channel 6 */
+#define IRQ_DMA7	63	/* DMA Channel 7 */
+
+#define VT8500_NR_IRQS		64
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vt8500_regs.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vt8500_regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/vt8500_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/vt8500_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,79 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/vt8500_regs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_VT8500_REGS_H
+#define __ASM_ARM_ARCH_VT8500_REGS_H
+
+/* VT8500 Registers Map */
+
+#define VT8500_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
+#define VT8500_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
+
+#define VT8500_DDR_BASE		0xd8000000	/* 1k	DDR/DDR2 Memory
+							Controller */
+#define VT8500_DMA_BASE		0xd8001000	/* 1k	DMA Controller */
+#define VT8500_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
+							Controller */
+#define VT8500_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
+#define VT8500_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
+#define VT8500_USB_BASE		0xd8007800	/* 2k	USB OTG */
+# define VT8500_EHCI_BASE	0xd8007900	/*	EHCI */
+# define VT8500_UHCI_BASE	0xd8007b01	/*	UHCI */
+#define VT8500_PATA_BASE	0xd8008000	/* 512	PATA */
+#define VT8500_PS2_BASE		0xd8008800	/* 1k	PS/2 */
+#define VT8500_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
+#define VT8500_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
+#define VT8500_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
+#define VT8500_MS_BASE		0xd800b000	/* 1k	MS/MSPRO Controller */
+#define VT8500_LCDC_BASE	0xd800e400	/* 1k	LCD Controller */
+#define VT8500_VPU_BASE		0xd8050000	/* 256	VPU */
+#define VT8500_GOV_BASE		0xd8050300	/* 256	GOV */
+#define VT8500_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
+#define VT8500_LCDF_BASE	0xd8050900	/* 256	LCD Formatter */
+#define VT8500_VID_BASE		0xd8050a00	/* 256	VID */
+#define VT8500_VPP_BASE		0xd8050b00	/* 256	VPP */
+#define VT8500_TSBK_BASE	0xd80f4000	/* 4k	TSBK */
+#define VT8500_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
+#define VT8500_JPEGENC_BASE	0xd80ff000	/* 4k	JPEG Encoder */
+#define VT8500_RTC_BASE		0xd8100000	/* 64k	RTC */
+#define VT8500_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
+#define VT8500_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
+#define VT8500_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
+#define VT8500_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
+#define VT8500_UART0_BASE	0xd8200000	/* 64k	UART 0 */
+#define VT8500_UART2_BASE	0xd8210000	/* 64k	UART 2 */
+#define VT8500_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
+#define VT8500_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
+#define VT8500_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
+#define VT8500_CIR_BASE		0xd8270000	/* 64k	CIR */
+#define VT8500_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
+#define VT8500_AC97_BASE	0xd8290000	/* 64k	AC97 */
+#define VT8500_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
+#define VT8500_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
+#define VT8500_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
+#define VT8500_PCM_BASE		0xd82d0000	/* 64k	PCM */
+#define VT8500_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
+#define VT8500_I2S_BASE		0xd8330000	/* 64k	I2S */
+#define VT8500_ADC_BASE		0xd8340000	/* 64k	ADC */
+
+#define VT8500_REGS_END_PHYS	0xd834ffff	/* End of MMIO registers */
+#define VT8500_REGS_LENGTH	(VT8500_REGS_END_PHYS \
+				- VT8500_REGS_START_PHYS + 1)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/wm8505_irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/wm8505_irqs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+/* WM8505 Interrupt Sources */
+
+#define IRQ_UHCI	0	/* UHC FS (UHCI?) */
+#define IRQ_EHCI	1	/* UHC HS */
+#define IRQ_UDCDMA	2	/* UDC DMA */
+				/* Reserved */
+#define IRQ_PS2MOUSE	4	/* PS/2 Mouse */
+#define IRQ_UDC		5	/* UDC */
+#define IRQ_EXT0	6	/* External Interrupt 0 */
+#define IRQ_EXT1	7	/* External Interrupt 1 */
+#define IRQ_KEYPAD	8	/* Keypad */
+#define IRQ_DMA		9	/* DMA Controller */
+#define IRQ_ETHER	10	/* Ethernet MAC */
+				/* Reserved */
+				/* Reserved */
+#define IRQ_EXT2	13	/* External Interrupt 2 */
+#define IRQ_EXT3	14	/* External Interrupt 3 */
+#define IRQ_EXT4	15	/* External Interrupt 4 */
+#define IRQ_APB		16	/* APB Bridge */
+#define IRQ_DMA0	17	/* DMA Channel 0 */
+#define IRQ_I2C1	18	/* I2C 1 */
+#define IRQ_I2C0	19	/* I2C 0 */
+#define IRQ_SDMMC	20	/* SD/MMC Controller */
+#define IRQ_SDMMC_DMA	21	/* SD/MMC Controller DMA */
+#define IRQ_PMC_WU	22	/* Power Management Controller Wakeup */
+#define IRQ_PS2KBD	23	/* PS/2 Keyboard */
+#define IRQ_SPI0	24	/* SPI 0 */
+#define IRQ_SPI1	25	/* SPI 1 */
+#define IRQ_SPI2	26	/* SPI 2 */
+#define IRQ_DMA1	27	/* DMA Channel 1 */
+#define IRQ_NAND	28	/* NAND Flash Controller */
+#define IRQ_NAND_DMA	29	/* NAND Flash Controller DMA */
+#define IRQ_UART5	30	/* UART 5 */
+#define IRQ_UART4	31	/* UART 4 */
+#define IRQ_UART0	32	/* UART 0 */
+#define IRQ_UART1	33	/* UART 1 */
+#define IRQ_DMA2	34	/* DMA Channel 2 */
+#define IRQ_I2S		35	/* I2S */
+#define IRQ_PMCOS0	36	/* PMC OS Timer 0 */
+#define IRQ_PMCOS1	37	/* PMC OS Timer 1 */
+#define IRQ_PMCOS2	38	/* PMC OS Timer 2 */
+#define IRQ_PMCOS3	39	/* PMC OS Timer 3 */
+#define IRQ_DMA3	40	/* DMA Channel 3 */
+#define IRQ_DMA4	41	/* DMA Channel 4 */
+#define IRQ_AC97	42	/* AC97 Interface */
+				/* Reserved */
+#define IRQ_NOR		44	/* NOR Flash Controller */
+#define IRQ_DMA5	45	/* DMA Channel 5 */
+#define IRQ_DMA6	46	/* DMA Channel 6 */
+#define IRQ_UART2	47	/* UART 2 */
+#define IRQ_RTC		48	/* RTC Interrupt */
+#define IRQ_RTCSM	49	/* RTC Second/Minute Update Interrupt */
+#define IRQ_UART3	50	/* UART 3 */
+#define IRQ_DMA7	51	/* DMA Channel 7 */
+#define IRQ_EXT5	52	/* External Interrupt 5 */
+#define IRQ_EXT6	53	/* External Interrupt 6 */
+#define IRQ_EXT7	54	/* External Interrupt 7 */
+#define IRQ_CIR		55	/* CIR */
+#define IRQ_SIC0	56	/* SIC IRQ0 */
+#define IRQ_SIC1	57	/* SIC IRQ1 */
+#define IRQ_SIC2	58	/* SIC IRQ2 */
+#define IRQ_SIC3	59	/* SIC IRQ3 */
+#define IRQ_SIC4	60	/* SIC IRQ4 */
+#define IRQ_SIC5	61	/* SIC IRQ5 */
+#define IRQ_SIC6	62	/* SIC IRQ6 */
+#define IRQ_SIC7	63	/* SIC IRQ7 */
+				/* Reserved */
+#define IRQ_JPEGDEC	65	/* JPEG Decoder */
+#define IRQ_SAE		66	/* SAE (?) */
+				/* Reserved */
+#define IRQ_VPU		79	/* Video Processing Unit */
+#define IRQ_VPP		80	/* Video Post-Processor */
+#define IRQ_VID		81	/* Video Digital Input Interface */
+#define IRQ_SPU		82	/* SPU (?) */
+#define IRQ_PIP		83	/* PIP Error */
+#define IRQ_GE		84	/* Graphic Engine */
+#define IRQ_GOV		85	/* Graphic Overlay Engine */
+#define IRQ_DVO		86	/* Digital Video Output */
+				/* Reserved */
+#define IRQ_DMA8	92	/* DMA Channel 8 */
+#define IRQ_DMA9	93	/* DMA Channel 9 */
+#define IRQ_DMA10	94	/* DMA Channel 10 */
+#define IRQ_DMA11	95	/* DMA Channel 11 */
+#define IRQ_DMA12	96	/* DMA Channel 12 */
+#define IRQ_DMA13	97	/* DMA Channel 13 */
+#define IRQ_DMA14	98	/* DMA Channel 14 */
+#define IRQ_DMA15	99	/* DMA Channel 15 */
+				/* Reserved */
+#define IRQ_GOVW	111	/* GOVW (?) */
+#define IRQ_GOVRSDSCD	112	/* GOVR SDSCD (?) */
+#define IRQ_GOVRSDMIF	113	/* GOVR SDMIF (?) */
+#define IRQ_GOVRHDSCD	114	/* GOVR HDSCD (?) */
+#define IRQ_GOVRHDMIF	115	/* GOVR HDMIF (?) */
+
+#define WM8505_NR_IRQS		116
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/wm8505_regs.h linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/wm8505_regs.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/include/mach/wm8505_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/include/mach/wm8505_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ *  arch/arm/mach-vt8500/include/mach/wm8505_regs.h
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#ifndef __ASM_ARM_ARCH_WM8505_REGS_H
+#define __ASM_ARM_ARCH_WM8505_REGS_H
+
+/* WM8505 Registers Map */
+
+#define WM8505_REGS_START_PHYS	0xd8000000	/* Start of MMIO registers */
+#define WM8505_REGS_START_VIRT	0xf8000000	/* Virtual mapping start */
+
+#define WM8505_DDR_BASE		0xd8000400	/* 1k	DDR/DDR2 Memory
+							Controller */
+#define WM8505_DMA_BASE		0xd8001800	/* 1k	DMA Controller */
+#define WM8505_VDMA_BASE	0xd8001c00	/* 1k	VDMA */
+#define WM8505_SFLASH_BASE	0xd8002000	/* 1k	Serial Flash Memory
+							Controller */
+#define WM8505_ETHER_BASE	0xd8004000	/* 1k	Ethernet MAC 0 */
+#define WM8505_CIPHER_BASE	0xd8006000	/* 4k	Cipher */
+#define WM8505_USB_BASE		0xd8007000	/* 2k	USB 2.0 Host */
+# define WM8505_EHCI_BASE	0xd8007100	/*	EHCI */
+# define WM8505_UHCI_BASE	0xd8007301	/*	UHCI */
+#define WM8505_PS2_BASE		0xd8008800	/* 1k	PS/2 */
+#define WM8505_NAND_BASE	0xd8009000	/* 1k	NAND Controller */
+#define WM8505_NOR_BASE		0xd8009400	/* 1k	NOR Controller */
+#define WM8505_SDMMC_BASE	0xd800a000	/* 1k	SD/MMC Controller */
+#define WM8505_VPU_BASE		0xd8050000	/* 256	VPU */
+#define WM8505_GOV_BASE		0xd8050300	/* 256	GOV */
+#define WM8505_GEGEA_BASE	0xd8050400	/* 768	GE/GE Alpha Mixing */
+#define WM8505_GOVR_BASE	0xd8050800	/* 512	GOVR (frambuffer) */
+#define WM8505_VID_BASE		0xd8050a00	/* 256	VID */
+#define WM8505_SCL_BASE		0xd8050d00	/* 256	SCL */
+#define WM8505_VPP_BASE		0xd8050f00	/* 256	VPP */
+#define WM8505_JPEGDEC_BASE	0xd80fe000	/* 4k	JPEG Decoder */
+#define WM8505_RTC_BASE		0xd8100000	/* 64k	RTC */
+#define WM8505_GPIO_BASE	0xd8110000	/* 64k	GPIO Configuration */
+#define WM8505_SCC_BASE		0xd8120000	/* 64k	System Configuration*/
+#define WM8505_PMC_BASE		0xd8130000	/* 64k	PMC Configuration */
+#define WM8505_IC_BASE		0xd8140000	/* 64k	Interrupt Controller*/
+#define WM8505_SIC_BASE		0xd8150000	/* 64k	Secondary IC */
+#define WM8505_UART0_BASE	0xd8200000	/* 64k	UART 0 */
+#define WM8505_UART2_BASE	0xd8210000	/* 64k	UART 2 */
+#define WM8505_PWM_BASE		0xd8220000	/* 64k	PWM Configuration */
+#define WM8505_SPI0_BASE	0xd8240000	/* 64k	SPI 0 */
+#define WM8505_SPI1_BASE	0xd8250000	/* 64k	SPI 1 */
+#define WM8505_KEYPAD_BASE	0xd8260000	/* 64k	Keypad control */
+#define WM8505_CIR_BASE		0xd8270000	/* 64k	CIR */
+#define WM8505_I2C0_BASE	0xd8280000	/* 64k	I2C 0 */
+#define WM8505_AC97_BASE	0xd8290000	/* 64k	AC97 */
+#define WM8505_SPI2_BASE	0xd82a0000	/* 64k	SPI 2 */
+#define WM8505_UART1_BASE	0xd82b0000	/* 64k	UART 1 */
+#define WM8505_UART3_BASE	0xd82c0000	/* 64k	UART 3 */
+#define WM8505_I2C1_BASE	0xd8320000	/* 64k	I2C 1 */
+#define WM8505_I2S_BASE		0xd8330000	/* 64k	I2S */
+#define WM8505_UART4_BASE	0xd8370000	/* 64k	UART 4 */
+#define WM8505_UART5_BASE	0xd8380000	/* 64k	UART 5 */
+
+#define WM8505_REGS_END_PHYS	0xd838ffff	/* End of MMIO registers */
+#define WM8505_REGS_LENGTH	(WM8505_REGS_END_PHYS \
+				- WM8505_REGS_START_PHYS + 1)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,177 @@
+/*
+ *  arch/arm/mach-vt8500/irq.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+
+#include "devices.h"
+
+#define VT8500_IC_DCTR		0x40		/* Destination control
+						register, 64*u8 */
+#define VT8500_INT_ENABLE	(1 << 3)
+#define VT8500_TRIGGER_HIGH	(0 << 4)
+#define VT8500_TRIGGER_RISING	(1 << 4)
+#define VT8500_TRIGGER_FALLING	(2 << 4)
+#define VT8500_EDGE		( VT8500_TRIGGER_RISING \
+				| VT8500_TRIGGER_FALLING)
+#define VT8500_IC_STATUS	0x80		/* Interrupt status, 2*u32 */
+
+static void __iomem *ic_regbase;
+static void __iomem *sic_regbase;
+
+static void vt8500_irq_mask(unsigned int irq)
+{
+	void __iomem *base = ic_regbase;
+	u8 edge;
+
+	if (irq >= 64) {
+		base = sic_regbase;
+		irq -= 64;
+	}
+	edge = readb(base + VT8500_IC_DCTR + irq) & VT8500_EDGE;
+	if (edge) {
+		void __iomem *stat_reg = base + VT8500_IC_STATUS
+						+ (irq < 32 ? 0 : 4);
+		unsigned status = readl(stat_reg);
+
+		status |= (1 << (irq & 0x1f));
+		writel(status, stat_reg);
+	} else {
+		u8 dctr = readb(base + VT8500_IC_DCTR + irq);
+
+		dctr &= ~VT8500_INT_ENABLE;
+		writeb(dctr, base + VT8500_IC_DCTR + irq);
+	}
+}
+
+static void vt8500_irq_unmask(unsigned int irq)
+{
+	void __iomem *base = ic_regbase;
+	u8 dctr;
+
+	if (irq >= 64) {
+		base = sic_regbase;
+		irq -= 64;
+	}
+	dctr = readb(base + VT8500_IC_DCTR + irq);
+	dctr |= VT8500_INT_ENABLE;
+	writeb(dctr, base + VT8500_IC_DCTR + irq);
+}
+
+static int vt8500_irq_set_type(unsigned int irq, unsigned int flow_type)
+{
+	void __iomem *base = ic_regbase;
+	unsigned int orig_irq = irq;
+	u8 dctr;
+
+	if (irq >= 64) {
+		base = sic_regbase;
+		irq -= 64;
+	}
+
+	dctr = readb(base + VT8500_IC_DCTR + irq);
+	dctr &= ~VT8500_EDGE;
+
+	switch (flow_type) {
+	case IRQF_TRIGGER_LOW:
+		return -EINVAL;
+	case IRQF_TRIGGER_HIGH:
+		dctr |= VT8500_TRIGGER_HIGH;
+		__irq_set_handler_locked(orig_irq, handle_level_irq);
+		break;
+	case IRQF_TRIGGER_FALLING:
+		dctr |= VT8500_TRIGGER_FALLING;
+		__irq_set_handler_locked(orig_irq, handle_edge_irq);
+		break;
+	case IRQF_TRIGGER_RISING:
+		dctr |= VT8500_TRIGGER_RISING;
+		__irq_set_handler_locked(orig_irq, handle_edge_irq);
+		break;
+	}
+	writeb(dctr, base + VT8500_IC_DCTR + irq);
+
+	return 0;
+}
+
+static struct irq_chip vt8500_irq_chip = {
+	.name      = "vt8500",
+	.ack       = vt8500_irq_mask,
+	.mask      = vt8500_irq_mask,
+	.unmask    = vt8500_irq_unmask,
+	.set_type  = vt8500_irq_set_type,
+};
+
+void __init vt8500_init_irq(void)
+{
+	unsigned int i;
+
+	ic_regbase = ioremap(wmt_ic_base, SZ_64K);
+
+	if (ic_regbase) {
+		/* Enable rotating priority for IRQ */
+		writel((1 << 6), ic_regbase + 0x20);
+		writel(0, ic_regbase + 0x24);
+
+		for (i = 0; i < wmt_nr_irqs; i++) {
+			/* Disable all interrupts and route them to IRQ */
+			writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
+
+			irq_set_chip_and_handler(i, &vt8500_irq_chip,
+						 handle_level_irq);
+			set_irq_flags(i, IRQF_VALID);
+		}
+	} else {
+		printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
+	}
+}
+
+void __init wm8505_init_irq(void)
+{
+	unsigned int i;
+
+	ic_regbase = ioremap(wmt_ic_base, SZ_64K);
+	sic_regbase = ioremap(wmt_sic_base, SZ_64K);
+
+	if (ic_regbase && sic_regbase) {
+		/* Enable rotating priority for IRQ */
+		writel((1 << 6), ic_regbase + 0x20);
+		writel(0, ic_regbase + 0x24);
+		writel((1 << 6), sic_regbase + 0x20);
+		writel(0, sic_regbase + 0x24);
+
+		for (i = 0; i < wmt_nr_irqs; i++) {
+			/* Disable all interrupts and route them to IRQ */
+			if (i < 64)
+				writeb(0x00, ic_regbase + VT8500_IC_DCTR + i);
+			else
+				writeb(0x00, sic_regbase + VT8500_IC_DCTR
+								+ i - 64);
+
+			irq_set_chip_and_handler(i, &vt8500_irq_chip,
+						 handle_level_irq);
+			set_irq_flags(i, IRQF_VALID);
+		}
+	} else {
+		printk(KERN_ERR "Unable to remap the Interrupt Controller registers, not enabling IRQs!\n");
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/Kconfig linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,73 @@
+if ARCH_VT8500
+
+config VTWM_VERSION_VT8500
+	bool
+
+config VTWM_VERSION_WM8505
+	bool
+
+config MACH_BV07
+	bool "Benign BV07-8500 Mini Netbook"
+	depends on ARCH_VT8500
+	select VTWM_VERSION_VT8500
+	help
+	  Add support for the inexpensive 7-inch netbooks sold by many
+	  Chinese distributors under various names. Note that there are
+	  many hardware implementations in identical exterior, make sure
+	  that yours is indeed based on a VIA VT8500 chip.
+
+config MACH_WM8505_7IN_NETBOOK
+	bool "WM8505 7-inch generic netbook"
+	depends on ARCH_VT8500
+	select VTWM_VERSION_WM8505
+	help
+	  Add support for the inexpensive 7-inch netbooks sold by many
+	  Chinese distributors under various names. Note that there are
+	  many hardware implementations in identical exterior, make sure
+	  that yours is indeed based on a WonderMedia WM8505 chip.
+
+comment "LCD panel size"
+
+config WMT_PANEL_800X480
+	bool "7-inch with 800x480 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	default y
+	help
+	  These are found in most of the netbooks in generic cases, as
+	  well as in Eken M001 tablets and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=800x480' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+config WMT_PANEL_800X600
+	bool "8-inch with 800x600 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	help
+	  These are found in Eken M003 tablets and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=800x600' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+config WMT_PANEL_1024X576
+	bool "10-inch with 1024x576 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	help
+	  These are found in CherryPal netbooks and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=1024x576' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+config WMT_PANEL_1024X600
+	bool "10-inch with 1024x600 resolution"
+	depends on (FB_VT8500 || FB_WM8505)
+	help
+	  These are found in Eken M006 tablets and possibly elsewhere.
+
+	  To select this panel at runtime, say y here and append
+	  'panel=1024x600' to your kernel command line. Otherwise, the
+	  largest one available will be used.
+
+endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/Makefile linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,9 @@
+obj-y += devices.o gpio.o irq.o timer.o
+
+obj-$(CONFIG_VTWM_VERSION_VT8500) += devices-vt8500.o
+obj-$(CONFIG_VTWM_VERSION_WM8505) += devices-wm8505.o
+
+obj-$(CONFIG_MACH_BV07) += bv07.o
+obj-$(CONFIG_MACH_WM8505_7IN_NETBOOK) += wm8505_7in.o
+
+obj-$(CONFIG_HAVE_PWM) += pwm.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/Makefile.boot linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/Makefile.boot
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/Makefile.boot	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/Makefile.boot	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3 @@
+   zreladdr-y	:= 0x00008000
+params_phys-y	:= 0x00000100
+initrd_phys-y	:= 0x01000000
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/pwm.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/pwm.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/pwm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/pwm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,265 @@
+/*
+ * arch/arm/mach-vt8500/pwm.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+#include <linux/delay.h>
+
+#include <asm/div64.h>
+
+#define VT8500_NR_PWMS 4
+
+static DEFINE_MUTEX(pwm_lock);
+static LIST_HEAD(pwm_list);
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device	*pdev;
+
+	const char	*label;
+
+	void __iomem	*regbase;
+
+	unsigned int	use_count;
+	unsigned int	pwm_id;
+};
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+static inline void pwm_busy_wait(void __iomem *reg, u8 bitmask)
+{
+	int loops = msecs_to_loops(10);
+	while ((readb(reg) & bitmask) && --loops)
+		cpu_relax();
+
+	if (unlikely(!loops))
+		pr_warning("Waiting for status bits 0x%x to clear timed out\n",
+			   bitmask);
+}
+
+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 = 25000000/2; /* wild guess --- need to implement clocks */
+	c = c * period_ns;
+	do_div(c, 1000000000);
+	period_cycles = c;
+
+	if (period_cycles < 1)
+		period_cycles = 1;
+	prescale = (period_cycles - 1) / 4096;
+	pv = period_cycles / (prescale + 1) - 1;
+	if (pv > 4095)
+		pv = 4095;
+
+	if (prescale > 1023)
+		return -EINVAL;
+
+	c = (unsigned long long)pv * duty_ns;
+	do_div(c, period_ns);
+	dc = c;
+
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 1));
+	writel(prescale, pwm->regbase + 0x4 + (pwm->pwm_id << 4));
+
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 2));
+	writel(pv, pwm->regbase + 0x8 + (pwm->pwm_id << 4));
+
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 3));
+	writel(dc, pwm->regbase + 0xc + (pwm->pwm_id << 4));
+
+	return 0;
+}
+EXPORT_SYMBOL(pwm_config);
+
+int pwm_enable(struct pwm_device *pwm)
+{
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0));
+	writel(5, pwm->regbase + (pwm->pwm_id << 4));
+	return 0;
+}
+EXPORT_SYMBOL(pwm_enable);
+
+void pwm_disable(struct pwm_device *pwm)
+{
+	pwm_busy_wait(pwm->regbase + 0x40 + pwm->pwm_id, (1 << 0));
+	writel(0, pwm->regbase + (pwm->pwm_id << 4));
+}
+EXPORT_SYMBOL(pwm_disable);
+
+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 pwm_device *pwms;
+	struct resource *r;
+	int ret = 0;
+	int i;
+
+	pwms = kzalloc(sizeof(struct pwm_device) * VT8500_NR_PWMS, GFP_KERNEL);
+	if (pwms == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < VT8500_NR_PWMS; i++) {
+		pwms[i].use_count = 0;
+		pwms[i].pwm_id = i;
+		pwms[i].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;
+	}
+
+	r = request_mem_region(r->start, resource_size(r), pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free;
+	}
+
+	pwms[0].regbase = ioremap(r->start, resource_size(r));
+	if (pwms[0].regbase == NULL) {
+		dev_err(&pdev->dev, "failed to ioremap() registers\n");
+		ret = -ENODEV;
+		goto err_free_mem;
+	}
+
+	for (i = 1; i < VT8500_NR_PWMS; i++)
+		pwms[i].regbase = pwms[0].regbase;
+
+	for (i = 0; i < VT8500_NR_PWMS; i++)
+		__add_pwm(&pwms[i]);
+
+	platform_set_drvdata(pdev, pwms);
+	return 0;
+
+err_free_mem:
+	release_mem_region(r->start, resource_size(r));
+err_free:
+	kfree(pwms);
+	return ret;
+}
+
+static int __devexit pwm_remove(struct platform_device *pdev)
+{
+	struct pwm_device *pwms;
+	struct resource *r;
+	int i;
+
+	pwms = platform_get_drvdata(pdev);
+	if (pwms == NULL)
+		return -ENODEV;
+
+	mutex_lock(&pwm_lock);
+
+	for (i = 0; i < VT8500_NR_PWMS; i++)
+		list_del(&pwms[i].node);
+	mutex_unlock(&pwm_lock);
+
+	iounmap(pwms[0].regbase);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	kfree(pwms);
+	return 0;
+}
+
+static struct platform_driver pwm_driver = {
+	.driver		= {
+		.name	= "vt8500-pwm",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= pwm_probe,
+	.remove		= __devexit_p(pwm_remove),
+};
+
+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");
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/timer.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/timer.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,155 @@
+/*
+ *  arch/arm/mach-vt8500/timer.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/clocksource.h>
+#include <linux/clockchips.h>
+#include <linux/delay.h>
+
+#include <asm/mach/time.h>
+
+#include "devices.h"
+
+#define VT8500_TIMER_OFFSET	0x0100
+#define TIMER_MATCH_VAL		0x0000
+#define TIMER_COUNT_VAL		0x0010
+#define TIMER_STATUS_VAL	0x0014
+#define TIMER_IER_VAL		0x001c		/* interrupt enable */
+#define TIMER_CTRL_VAL		0x0020
+#define TIMER_AS_VAL		0x0024		/* access status */
+#define TIMER_COUNT_R_ACTIVE	(1 << 5)	/* not ready for read */
+#define TIMER_COUNT_W_ACTIVE	(1 << 4)	/* not ready for write */
+#define TIMER_MATCH_W_ACTIVE	(1 << 0)	/* not ready for write */
+#define VT8500_TIMER_HZ		3000000
+
+#define msecs_to_loops(t) (loops_per_jiffy / 1000 * HZ * t)
+
+static void __iomem *regbase;
+
+static cycle_t vt8500_timer_read(struct clocksource *cs)
+{
+	int loops = msecs_to_loops(10);
+	writel(3, regbase + TIMER_CTRL_VAL);
+	while ((readl((regbase + TIMER_AS_VAL)) & TIMER_COUNT_R_ACTIVE)
+						&& --loops)
+		cpu_relax();
+	return readl(regbase + TIMER_COUNT_VAL);
+}
+
+struct clocksource clocksource = {
+	.name           = "vt8500_timer",
+	.rating         = 200,
+	.read           = vt8500_timer_read,
+	.mask           = CLOCKSOURCE_MASK(32),
+	.flags          = CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int vt8500_timer_set_next_event(unsigned long cycles,
+				    struct clock_event_device *evt)
+{
+	int loops = msecs_to_loops(10);
+	cycle_t alarm = clocksource.read(&clocksource) + cycles;
+	while ((readl(regbase + TIMER_AS_VAL) & TIMER_MATCH_W_ACTIVE)
+						&& --loops)
+		cpu_relax();
+	writel((unsigned long)alarm, regbase + TIMER_MATCH_VAL);
+
+	if ((signed)(alarm - clocksource.read(&clocksource)) <= 16)
+		return -ETIME;
+
+	writel(1, regbase + TIMER_IER_VAL);
+
+	return 0;
+}
+
+static void vt8500_timer_set_mode(enum clock_event_mode mode,
+			      struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel(readl(regbase + TIMER_CTRL_VAL) | 1,
+			regbase + TIMER_CTRL_VAL);
+		writel(0, regbase + TIMER_IER_VAL);
+		break;
+	}
+}
+
+struct clock_event_device clockevent = {
+	.name           = "vt8500_timer",
+	.features       = CLOCK_EVT_FEAT_ONESHOT,
+	.rating         = 200,
+	.set_next_event = vt8500_timer_set_next_event,
+	.set_mode       = vt8500_timer_set_mode,
+};
+
+static irqreturn_t vt8500_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+	writel(0xf, regbase + TIMER_STATUS_VAL);
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+struct irqaction irq = {
+	.name    = "vt8500_timer",
+	.flags   = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler = vt8500_timer_interrupt,
+	.dev_id  = &clockevent,
+};
+
+static void __init vt8500_timer_init(void)
+{
+	regbase = ioremap(wmt_pmc_base + VT8500_TIMER_OFFSET, 0x28);
+	if (!regbase)
+		printk(KERN_ERR "vt8500_timer_init: failed to map MMIO registers\n");
+
+	writel(1, regbase + TIMER_CTRL_VAL);
+	writel(0xf, regbase + TIMER_STATUS_VAL);
+	writel(~0, regbase + TIMER_MATCH_VAL);
+
+	if (clocksource_register_hz(&clocksource, VT8500_TIMER_HZ))
+		printk(KERN_ERR "vt8500_timer_init: clocksource_register failed for %s\n",
+					clocksource.name);
+
+	clockevents_calc_mult_shift(&clockevent, VT8500_TIMER_HZ, 4);
+
+	/* copy-pasted from mach-msm; no idea */
+	clockevent.max_delta_ns =
+		clockevent_delta2ns(0xf0000000, &clockevent);
+	clockevent.min_delta_ns = clockevent_delta2ns(4, &clockevent);
+	clockevent.cpumask = cpumask_of(0);
+
+	if (setup_irq(wmt_timer_irq, &irq))
+		printk(KERN_ERR "vt8500_timer_init: setup_irq failed for %s\n",
+					clockevent.name);
+	clockevents_register_device(&clockevent);
+}
+
+struct sys_timer vt8500_timer = {
+	.init = vt8500_timer_init
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/wm8505_7in.c linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/wm8505_7in.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-vt8500/wm8505_7in.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/mach-vt8500/wm8505_7in.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ *  arch/arm/mach-vt8500/wm8505_7in.c
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/io.h>
+#include <linux/pm.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include "devices.h"
+
+static void __iomem *pmc_hiber;
+
+static struct platform_device *devices[] __initdata = {
+	&vt8500_device_uart0,
+	&vt8500_device_ehci,
+	&vt8500_device_wm8505_fb,
+	&vt8500_device_ge_rops,
+	&vt8500_device_pwm,
+	&vt8500_device_pwmbl,
+	&vt8500_device_rtc,
+};
+
+static void vt8500_power_off(void)
+{
+	local_irq_disable();
+	writew(5, pmc_hiber);
+	asm("mcr%? p15, 0, %0, c7, c0, 4" : : "r" (0));
+}
+
+void __init wm8505_7in_init(void)
+{
+#ifdef CONFIG_FB_WM8505
+	void __iomem *gpio_mux_reg = ioremap(wmt_gpio_base + 0x200, 4);
+	if (gpio_mux_reg) {
+		writel(readl(gpio_mux_reg) | 0x80000000, gpio_mux_reg);
+		iounmap(gpio_mux_reg);
+	} else {
+		printk(KERN_ERR "Could not remap the GPIO mux register, display may not work properly!\n");
+	}
+#endif
+	pmc_hiber = ioremap(wmt_pmc_base + 0x12, 2);
+	if (pmc_hiber)
+		pm_power_off = &vt8500_power_off;
+	else
+		printk(KERN_ERR "PMC Hibernation register could not be remapped, not enabling power off!\n");
+
+	wm8505_set_resources();
+	platform_add_devices(devices, ARRAY_SIZE(devices));
+	vt8500_gpio_init();
+}
+
+MACHINE_START(WM8505_7IN_NETBOOK, "WM8505 7-inch generic netbook")
+	.boot_params	= 0x00000100,
+	.reserve	= wm8505_reserve_mem,
+	.map_io		= wm8505_map_io,
+	.init_irq	= wm8505_init_irq,
+	.timer		= &vt8500_timer,
+	.init_machine	= wm8505_7in_init,
+MACHINE_END
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-w90x900/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/mach-w90x900/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/mach-w90x900/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-w90x900/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,6 @@
 #ifndef __ASM_ARCH_MEMORY_H
 #define __ASM_ARCH_MEMORY_H
 
-#define PHYS_OFFSET	UL(0x00000000)
+#define PLAT_PHYS_OFFSET	UL(0x00000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mach-w90x900/irq.c linux-libre-2.6.39-gnu/arch/arm/mach-w90x900/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/mach-w90x900/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mach-w90x900/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,8 +207,8 @@
 	__raw_writel(0xFFFFFFFE, REG_AIC_MDCR);
 
 	for (irqno = IRQ_WDT; irqno <= IRQ_ADC; irqno++) {
-		set_irq_chip(irqno, &nuc900_irq_chip);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &nuc900_irq_chip,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/Makefile linux-libre-2.6.39-gnu/arch/arm/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -89,6 +89,7 @@
 tune-$(CONFIG_CPU_XSC3)		:=$(call cc-option,-mtune=xscale,-mtune=strongarm110) -Wa,-mcpu=xscale
 tune-$(CONFIG_CPU_FEROCEON)	:=$(call cc-option,-mtune=marvell-f,-mtune=xscale)
 tune-$(CONFIG_CPU_V6)		:=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
+tune-$(CONFIG_CPU_V6K)		:=$(call cc-option,-mtune=arm1136j-s,-mtune=strongarm)
 
 ifeq ($(CONFIG_AEABI),y)
 CFLAGS_ABI	:=-mabi=aapcs-linux -mno-thumb-interwork
@@ -105,6 +106,10 @@
 AFLAGS_NOWARN	:=$(call as-option,-Wa$(comma)-mno-warn-deprecated,-Wa$(comma)-W)
 CFLAGS_THUMB2	:=-mthumb $(AFLAGS_AUTOIT) $(AFLAGS_NOWARN)
 AFLAGS_THUMB2	:=$(CFLAGS_THUMB2) -Wa$(comma)-mthumb
+# Work around buggy relocation from gas if requested:
+ifeq ($(CONFIG_THUMB2_AVOID_R_ARM_THM_JUMP11),y)
+CFLAGS_MODULE	+=-fno-optimize-sibling-calls
+endif
 endif
 
 # Need -Uarm for gcc < 3.x
@@ -126,7 +131,6 @@
 
 # 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_BCMRING)		:= bcmring
 machine-$(CONFIG_ARCH_CLPS711X)		:= clps711x
@@ -146,7 +150,6 @@
 machine-$(CONFIG_ARCH_IXP4XX)		:= ixp4xx
 machine-$(CONFIG_ARCH_KIRKWOOD)		:= kirkwood
 machine-$(CONFIG_ARCH_KS8695)		:= ks8695
-machine-$(CONFIG_ARCH_LH7A40X)		:= lh7a40x
 machine-$(CONFIG_ARCH_LOKI) 		:= loki
 machine-$(CONFIG_ARCH_LPC32XX)		:= lpc32xx
 machine-$(CONFIG_ARCH_MMP)		:= mmp
@@ -178,7 +181,7 @@
 machine-$(CONFIG_ARCH_S5P6442)		:= s5p6442
 machine-$(CONFIG_ARCH_S5PC100)		:= s5pc100
 machine-$(CONFIG_ARCH_S5PV210)		:= s5pv210
-machine-$(CONFIG_ARCH_S5PV310)		:= s5pv310
+machine-$(CONFIG_ARCH_EXYNOS4)		:= exynos4
 machine-$(CONFIG_ARCH_SA1100)		:= sa1100
 machine-$(CONFIG_ARCH_SHARK)		:= shark
 machine-$(CONFIG_ARCH_SHMOBILE) 	:= shmobile
@@ -190,6 +193,7 @@
 machine-$(CONFIG_ARCH_U8500)		:= ux500
 machine-$(CONFIG_ARCH_VERSATILE)	:= versatile
 machine-$(CONFIG_ARCH_VEXPRESS)		:= vexpress
+machine-$(CONFIG_ARCH_VT8500)		:= vt8500
 machine-$(CONFIG_ARCH_W90X900)		:= w90x900
 machine-$(CONFIG_ARCH_NUC93X)		:= nuc93x
 machine-$(CONFIG_FOOTBRIDGE)		:= footbridge
@@ -280,7 +284,7 @@
 zImage Image xipImage bootpImage uImage: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
-zinstall install: vmlinux
+zinstall uinstall install: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
@@ -301,6 +305,7 @@
   echo  '                  (supply initrd image via make variable INITRD=<path>)'
   echo  '  install       - Install uncompressed kernel'
   echo  '  zinstall      - Install compressed kernel'
+  echo  '  uinstall      - Install U-Boot wrapped compressed kernel'
   echo  '                  Install using (your) ~/bin/$(INSTALLKERNEL) or'
   echo  '                  (distribution) /sbin/$(INSTALLKERNEL) or'
   echo  '                  install to $$(INSTALL_PATH) and run lilo'
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/abort-ev6.S linux-libre-2.6.39-gnu/arch/arm/mm/abort-ev6.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/abort-ev6.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/abort-ev6.S	2011-05-19 00:06:34.000000000 -0400
@@ -20,11 +20,11 @@
  */
 	.align	5
 ENTRY(v6_early_abort)
-#ifdef CONFIG_CPU_32v6K
-	clrex
-#else
+#ifdef CONFIG_CPU_V6
 	sub	r1, sp, #4			@ Get unused stack location
 	strex	r0, r1, [r1]			@ Clear the exclusive monitor
+#elif defined(CONFIG_CPU_32v6K)
+	clrex
 #endif
 	mrc	p15, 0, r1, c5, c0, 0		@ get FSR
 	mrc	p15, 0, r0, c6, c0, 0		@ get FAR
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/cache-l2x0.c linux-libre-2.6.39-gnu/arch/arm/mm/cache-l2x0.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/cache-l2x0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/cache-l2x0.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,18 +73,24 @@
 	writel_relaxed(addr, base + L2X0_INV_LINE_PA);
 }
 
-#ifdef CONFIG_PL310_ERRATA_588369
-static void debug_writel(unsigned long val)
-{
-	extern void omap_smc1(u32 fn, u32 arg);
+#if defined(CONFIG_PL310_ERRATA_588369) || defined(CONFIG_PL310_ERRATA_727915)
 
-	/*
-	 * Texas Instrument secure monitor api to modify the
-	 * PL310 Debug Control Register.
-	 */
-	omap_smc1(0x100, val);
+#define debug_writel(val)	outer_cache.set_debug(val)
+
+static void l2x0_set_debug(unsigned long val)
+{
+	writel_relaxed(val, l2x0_base + L2X0_DEBUG_CTRL);
+}
+#else
+/* Optimised out for non-errata case */
+static inline void debug_writel(unsigned long val)
+{
 }
 
+#define l2x0_set_debug	NULL
+#endif
+
+#ifdef CONFIG_PL310_ERRATA_588369
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
@@ -97,11 +103,6 @@
 }
 #else
 
-/* Optimised out for non-errata case */
-static inline void debug_writel(unsigned long val)
-{
-}
-
 static inline void l2x0_flush_line(unsigned long addr)
 {
 	void __iomem *base = l2x0_base;
@@ -125,9 +126,11 @@
 
 	/* clean all ways */
 	spin_lock_irqsave(&l2x0_lock, flags);
+	debug_writel(0x03);
 	writel_relaxed(l2x0_way_mask, l2x0_base + L2X0_CLEAN_INV_WAY);
 	cache_wait_way(l2x0_base + L2X0_CLEAN_INV_WAY, l2x0_way_mask);
 	cache_sync();
+	debug_writel(0x00);
 	spin_unlock_irqrestore(&l2x0_lock, flags);
 }
 
@@ -335,6 +338,7 @@
 	outer_cache.flush_all = l2x0_flush_all;
 	outer_cache.inv_all = l2x0_inv_all;
 	outer_cache.disable = l2x0_disable;
+	outer_cache.set_debug = l2x0_set_debug;
 
 	printk(KERN_INFO "%s cache controller enabled\n", type);
 	printk(KERN_INFO "l2x0: %d ways, CACHE_ID 0x%08x, AUX_CTRL 0x%08x, Cache size: %d B\n",
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/cache-v4wb.S linux-libre-2.6.39-gnu/arch/arm/mm/cache-v4wb.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/cache-v4wb.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/cache-v4wb.S	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  *
  *  Size  Clean (ticks) Dirty (ticks)
  *   4096   21  20  21    53  55  54
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/cache-v4wt.S linux-libre-2.6.39-gnu/arch/arm/mm/cache-v4wt.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/cache-v4wt.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/cache-v4wt.S	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  *
  * *** This needs benchmarking
  */
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/cache-v7.S linux-libre-2.6.39-gnu/arch/arm/mm/cache-v7.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/cache-v7.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/cache-v7.S	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
  *	Flush the entire cache system.
  *  The data cache flush is now achieved using atomic clean / invalidates
  *  working outwards from L1 cache. This is done using Set/Way based cache
- *  maintainance instructions.
+ *  maintenance instructions.
  *  The instruction cache can still be invalidated back to the point of
  *  unification in a single instruction.
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/dma-mapping.c linux-libre-2.6.39-gnu/arch/arm/mm/dma-mapping.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/dma-mapping.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/dma-mapping.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,6 +149,7 @@
 {
 	int ret = 0;
 	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	int i = 0;
@@ -156,7 +157,15 @@
 
 	do {
 		pgd = pgd_offset(&init_mm, base);
-		pmd = pmd_alloc(&init_mm, pgd, base);
+
+		pud = pud_alloc(&init_mm, pgd, base);
+		if (!pud) {
+			printk(KERN_ERR "%s: no pud tables\n", __func__);
+			ret = -ENOMEM;
+			break;
+		}
+
+		pmd = pmd_alloc(&init_mm, pud, base);
 		if (!pmd) {
 			printk(KERN_ERR "%s: no pmd tables\n", __func__);
 			ret = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/fault-armv.c linux-libre-2.6.39-gnu/arch/arm/mm/fault-armv.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/fault-armv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/fault-armv.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,6 +95,7 @@
 {
 	spinlock_t *ptl;
 	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
 	pte_t *pte;
 	int ret;
@@ -103,7 +104,11 @@
 	if (pgd_none_or_clear_bad(pgd))
 		return 0;
 
-	pmd = pmd_offset(pgd, address);
+	pud = pud_offset(pgd, address);
+	if (pud_none_or_clear_bad(pud))
+		return 0;
+
+	pmd = pmd_offset(pud, address);
 	if (pmd_none_or_clear_bad(pmd))
 		return 0;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/fault.c linux-libre-2.6.39-gnu/arch/arm/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,9 +76,11 @@
 
 	printk(KERN_ALERT "pgd = %p\n", mm->pgd);
 	pgd = pgd_offset(mm, addr);
-	printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
+	printk(KERN_ALERT "[%08lx] *pgd=%08llx",
+			addr, (long long)pgd_val(*pgd));
 
 	do {
+		pud_t *pud;
 		pmd_t *pmd;
 		pte_t *pte;
 
@@ -90,9 +92,21 @@
 			break;
 		}
 
-		pmd = pmd_offset(pgd, addr);
+		pud = pud_offset(pgd, addr);
+		if (PTRS_PER_PUD != 1)
+			printk(", *pud=%08lx", pud_val(*pud));
+
+		if (pud_none(*pud))
+			break;
+
+		if (pud_bad(*pud)) {
+			printk("(bad)");
+			break;
+		}
+
+		pmd = pmd_offset(pud, addr);
 		if (PTRS_PER_PMD != 1)
-			printk(", *pmd=%08lx", pmd_val(*pmd));
+			printk(", *pmd=%08llx", (long long)pmd_val(*pmd));
 
 		if (pmd_none(*pmd))
 			break;
@@ -107,8 +121,9 @@
 			break;
 
 		pte = pte_offset_map(pmd, addr);
-		printk(", *pte=%08lx", pte_val(*pte));
-		printk(", *ppte=%08lx", pte_val(pte[PTE_HWTABLE_PTRS]));
+		printk(", *pte=%08llx", (long long)pte_val(*pte));
+		printk(", *ppte=%08llx",
+		       (long long)pte_val(pte[PTE_HWTABLE_PTRS]));
 		pte_unmap(pte);
 	} while(0);
 
@@ -388,6 +403,7 @@
 {
 	unsigned int index;
 	pgd_t *pgd, *pgd_k;
+	pud_t *pud, *pud_k;
 	pmd_t *pmd, *pmd_k;
 
 	if (addr < TASK_SIZE)
@@ -406,12 +422,19 @@
 
 	if (pgd_none(*pgd_k))
 		goto bad_area;
-
 	if (!pgd_present(*pgd))
 		set_pgd(pgd, *pgd_k);
 
-	pmd_k = pmd_offset(pgd_k, addr);
-	pmd   = pmd_offset(pgd, addr);
+	pud = pud_offset(pgd, addr);
+	pud_k = pud_offset(pgd_k, addr);
+
+	if (pud_none(*pud_k))
+		goto bad_area;
+	if (!pud_present(*pud))
+		set_pud(pud, *pud_k);
+
+	pmd = pmd_offset(pud, addr);
+	pmd_k = pmd_offset(pud_k, addr);
 
 	/*
 	 * On ARM one Linux PGD entry contains two hardware entries (see page
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/idmap.c linux-libre-2.6.39-gnu/arch/arm/mm/idmap.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/idmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/idmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,10 +4,10 @@
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
 
-static void idmap_add_pmd(pgd_t *pgd, unsigned long addr, unsigned long end,
+static void idmap_add_pmd(pud_t *pud, unsigned long addr, unsigned long end,
 	unsigned long prot)
 {
-	pmd_t *pmd = pmd_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
 
 	addr = (addr & PMD_MASK) | prot;
 	pmd[0] = __pmd(addr);
@@ -16,6 +16,18 @@
 	flush_pmd_entry(pmd);
 }
 
+static void idmap_add_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
+	unsigned long prot)
+{
+	pud_t *pud = pud_offset(pgd, addr);
+	unsigned long next;
+
+	do {
+		next = pud_addr_end(addr, end);
+		idmap_add_pmd(pud, addr, next, prot);
+	} while (pud++, addr = next, addr != end);
+}
+
 void identity_mapping_add(pgd_t *pgd, unsigned long addr, unsigned long end)
 {
 	unsigned long prot, next;
@@ -27,17 +39,28 @@
 	pgd += pgd_index(addr);
 	do {
 		next = pgd_addr_end(addr, end);
-		idmap_add_pmd(pgd, addr, next, prot);
+		idmap_add_pud(pgd, addr, next, prot);
 	} while (pgd++, addr = next, addr != end);
 }
 
 #ifdef CONFIG_SMP
-static void idmap_del_pmd(pgd_t *pgd, unsigned long addr, unsigned long end)
+static void idmap_del_pmd(pud_t *pud, unsigned long addr, unsigned long end)
 {
-	pmd_t *pmd = pmd_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
 	pmd_clear(pmd);
 }
 
+static void idmap_del_pud(pgd_t *pgd, unsigned long addr, unsigned long end)
+{
+	pud_t *pud = pud_offset(pgd, addr);
+	unsigned long next;
+
+	do {
+		next = pud_addr_end(addr, end);
+		idmap_del_pmd(pud, addr, next);
+	} while (pud++, addr = next, addr != end);
+}
+
 void identity_mapping_del(pgd_t *pgd, unsigned long addr, unsigned long end)
 {
 	unsigned long next;
@@ -45,7 +68,7 @@
 	pgd += pgd_index(addr);
 	do {
 		next = pgd_addr_end(addr, end);
-		idmap_del_pmd(pgd, addr, next);
+		idmap_del_pud(pgd, addr, next);
 	} while (pgd++, addr = next, addr != end);
 }
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/init.c linux-libre-2.6.39-gnu/arch/arm/mm/init.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
  */
 struct meminfo meminfo;
 
-void show_mem(void)
+void show_mem(unsigned int filter)
 {
 	int free = 0, total = 0, reserved = 0;
 	int shared = 0, cached = 0, slab = 0, i;
@@ -350,7 +350,7 @@
 	 */
 	arm_bootmem_free(min, max_low, max_high);
 
-	high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
+	high_memory = __va(((phys_addr_t)max_low << PAGE_SHIFT) - 1) + 1;
 
 	/*
 	 * This doesn't seem to be used by the Linux memory manager any
@@ -392,14 +392,14 @@
 	 * Convert start_pfn/end_pfn to a struct page pointer.
 	 */
 	start_pg = pfn_to_page(start_pfn - 1) + 1;
-	end_pg = pfn_to_page(end_pfn);
+	end_pg = pfn_to_page(end_pfn - 1) + 1;
 
 	/*
 	 * Convert to physical addresses, and
 	 * round start upwards and end downwards.
 	 */
-	pg = PAGE_ALIGN(__pa(start_pg));
-	pgend = __pa(end_pg) & PAGE_MASK;
+	pg = (unsigned long)PAGE_ALIGN(__pa(start_pg));
+	pgend = (unsigned long)__pa(end_pg) & PAGE_MASK;
 
 	/*
 	 * If there are free pages between these,
@@ -426,6 +426,14 @@
 
 		bank_start = bank_pfn_start(bank);
 
+#ifdef CONFIG_SPARSEMEM
+		/*
+		 * Take care not to free memmap entries that don't exist
+		 * due to SPARSEMEM sections which aren't present.
+		 */
+		bank_start = min(bank_start,
+				 ALIGN(prev_bank_end, PAGES_PER_SECTION));
+#endif
 		/*
 		 * If we had a previous bank, and there is a space
 		 * between the current bank and the previous, free it.
@@ -440,6 +448,12 @@
 		 */
 		prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
 	}
+
+#ifdef CONFIG_SPARSEMEM
+	if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION))
+		free_memmap(prev_bank_end,
+			    ALIGN(prev_bank_end, PAGES_PER_SECTION));
+#endif
 }
 
 static void __init free_highpages(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/Kconfig linux-libre-2.6.39-gnu/arch/arm/mm/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/mm/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -390,7 +390,7 @@
 
 # ARMv6
 config CPU_V6
-	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX || ARCH_DOVE
+	bool "Support ARM V6 processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
 	select CPU_32v6
 	select CPU_ABRT_EV6
 	select CPU_PABRT_V6
@@ -402,16 +402,18 @@
 	select CPU_TLB_V6 if MMU
 
 # ARMv6k
-config CPU_32v6K
-	bool "Support ARM V6K processor extensions" if !SMP
-	depends on CPU_V6 || CPU_V7
-	default y if SMP
-	help
-	  Say Y here if your ARMv6 processor supports the 'K' extension.
-	  This enables the kernel to use some instructions not present
-	  on previous processors, and as such a kernel build with this
-	  enabled will not boot on processors with do not support these
-	  instructions.
+config CPU_V6K
+	bool "Support ARM V6K processor" if ARCH_INTEGRATOR || MACH_REALVIEW_EB || MACH_REALVIEW_PBX
+	select CPU_32v6
+	select CPU_32v6K
+	select CPU_ABRT_EV6
+	select CPU_PABRT_V6
+	select CPU_CACHE_V6
+	select CPU_CACHE_VIPT
+	select CPU_CP15_MMU
+	select CPU_HAS_ASID if MMU
+	select CPU_COPY_V6 if MMU
+	select CPU_TLB_V6 if MMU
 
 # ARMv7
 config CPU_V7
@@ -433,25 +435,33 @@
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v4
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v4T
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v5
 	bool
 	select TLS_REG_EMUL if SMP || !MMU
 	select NEEDS_SYSCALL_FOR_CMPXCHG if SMP
+	select CPU_USE_DOMAINS if MMU
 
 config CPU_32v6
 	bool
 	select TLS_REG_EMUL if !CPU_32v6K && !MMU
+	select CPU_USE_DOMAINS if CPU_V6 && MMU
+
+config CPU_32v6K
+	bool
 
 config CPU_32v7
 	bool
@@ -607,8 +617,6 @@
 
 config CPU_USE_DOMAINS
 	bool
-	depends on MMU
-	default y if !CPU_32v6K
 	help
 	  This option enables or disables the use of domain switching
 	  via the set_fs() function.
@@ -623,7 +631,7 @@
 
 config ARM_THUMB
 	bool "Support Thumb user binaries"
-	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V7 || CPU_FEROCEON
+	depends on CPU_ARM720T || CPU_ARM740T || CPU_ARM920T || CPU_ARM922T || CPU_ARM925T || CPU_ARM926T || CPU_ARM940T || CPU_ARM946E || CPU_ARM1020 || CPU_ARM1020E || CPU_ARM1022 || CPU_ARM1026 || CPU_XSCALE || CPU_XSC3 || CPU_MOHAWK || CPU_V6 || CPU_V6K || CPU_V7 || CPU_FEROCEON
 	default y
 	help
 	  Say Y if you want to include kernel support for running user space
@@ -644,7 +652,7 @@
 
 config SWP_EMULATE
 	bool "Emulate SWP/SWPB instructions"
-	depends on !CPU_USE_DOMAINS && CPU_V7 && !CPU_V6
+	depends on !CPU_USE_DOMAINS && CPU_V7
 	select HAVE_PROC_CPU if PROC_FS
 	default y if SMP
 	help
@@ -681,7 +689,7 @@
 config CPU_ENDIAN_BE8
 	bool
 	depends on CPU_BIG_ENDIAN
-	default CPU_V6 || CPU_V7
+	default CPU_V6 || CPU_V6K || CPU_V7
 	help
 	  Support for the BE-8 (big-endian) mode on ARMv6 and ARMv7 processors.
 
@@ -747,7 +755,7 @@
 
 config CPU_BPREDICT_DISABLE
 	bool "Disable branch prediction"
-	depends on CPU_ARM1020 || CPU_V6 || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526
+	depends on CPU_ARM1020 || CPU_V6 || CPU_V6K || CPU_MOHAWK || CPU_XSC3 || CPU_V7 || CPU_FA526
 	help
 	  Say Y here to disable branch prediction.  If unsure, say N.
 
@@ -767,7 +775,7 @@
 
 config DMA_CACHE_RWFO
 	bool "Enable read/write for ownership DMA cache maintenance"
-	depends on CPU_V6 && SMP
+	depends on CPU_V6K && SMP
 	default y
 	help
 	  The Snoop Control Unit on ARM11MPCore does not detect the
@@ -811,8 +819,8 @@
 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 || MACH_REALVIEW_PBX || \
-		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_S5PV310 || ARCH_TEGRA || \
+		   REALVIEW_EB_A9MP || SOC_IMX35 || SOC_IMX31 || MACH_REALVIEW_PBX || \
+		   ARCH_NOMADIK || ARCH_OMAP4 || ARCH_EXYNOS4 || ARCH_TEGRA || \
 		   ARCH_U8500 || ARCH_VEXPRESS_CA9X4 || ARCH_SHMOBILE
 	default y
 	select OUTER_CACHE
@@ -823,7 +831,7 @@
 config CACHE_PL310
 	bool
 	depends on CACHE_L2X0
-	default y if CPU_V7 && !CPU_V6
+	default y if CPU_V7 && !(CPU_V6 || CPU_V6K)
 	help
 	  This option enables optimisations for the PL310 cache
 	  controller.
@@ -845,16 +853,21 @@
 	help
 	  This option enables the L2 cache on XScale3.
 
+config ARM_L1_CACHE_SHIFT_6
+	bool
+	help
+	  Setting ARM L1 cache line size to 64 Bytes.
+
 config ARM_L1_CACHE_SHIFT
 	int
 	default 6 if ARM_L1_CACHE_SHIFT_6
 	default 5
 
 config ARM_DMA_MEM_BUFFERABLE
-	bool "Use non-cacheable memory for DMA" if CPU_V6 && !CPU_V7
+	bool "Use non-cacheable memory for DMA" if (CPU_V6 || CPU_V6K) && !CPU_V7
 	depends on !(MACH_REALVIEW_PB1176 || REALVIEW_EB_ARM11MP || \
 		     MACH_REALVIEW_PB11MP)
-	default y if CPU_V6 || CPU_V7
+	default y if CPU_V6 || CPU_V6K || CPU_V7
 	help
 	  Historically, the kernel has used strongly ordered mappings to
 	  provide DMA coherent memory.  With the advent of ARMv7, mapping
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/Makefile linux-libre-2.6.39-gnu/arch/arm/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -90,6 +90,7 @@
 obj-$(CONFIG_CPU_MOHAWK)	+= proc-mohawk.o
 obj-$(CONFIG_CPU_FEROCEON)	+= proc-feroceon.o
 obj-$(CONFIG_CPU_V6)		+= proc-v6.o
+obj-$(CONFIG_CPU_V6K)		+= proc-v6.o
 obj-$(CONFIG_CPU_V7)		+= proc-v7.o
 
 AFLAGS_proc-v6.o	:=-Wa,-march=armv6
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/mmap.c linux-libre-2.6.39-gnu/arch/arm/mm/mmap.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/mmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/mmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,7 @@
 #include <linux/shm.h>
 #include <linux/sched.h>
 #include <linux/io.h>
+#include <linux/personality.h>
 #include <linux/random.h>
 #include <asm/cputype.h>
 #include <asm/system.h>
@@ -31,7 +32,7 @@
 	struct mm_struct *mm = current->mm;
 	struct vm_area_struct *vma;
 	unsigned long start_addr;
-#ifdef CONFIG_CPU_V6
+#if defined(CONFIG_CPU_V6) || defined(CONFIG_CPU_V6K)
 	unsigned int cache_type;
 	int do_align = 0, aliasing = 0;
 
@@ -82,7 +83,8 @@
 	        mm->cached_hole_size = 0;
 	}
 	/* 8 bits of randomness in 20 address space bits */
-	if (current->flags & PF_RANDOMIZE)
+	if ((current->flags & PF_RANDOMIZE) &&
+	    !(current->personality & ADDR_NO_RANDOMIZE))
 		addr += (get_random_int() % (1 << 8)) << PAGE_SHIFT;
 
 full_search:
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/mm.h linux-libre-2.6.39-gnu/arch/arm/mm/mm.h
--- linux-libre-2.6.38-gnu/arch/arm/mm/mm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/mm.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 
 static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
 {
-	return pmd_offset(pgd, virt);
+	return pmd_offset(pud_offset(pgd, virt), virt);
 }
 
 static inline pmd_t *pmd_off_k(unsigned long virt)
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/mmu.c linux-libre-2.6.39-gnu/arch/arm/mm/mmu.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/mmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/mmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -533,7 +533,7 @@
 static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr, unsigned long prot)
 {
 	if (pmd_none(*pmd)) {
-		pte_t *pte = early_alloc(2 * PTRS_PER_PTE * sizeof(pte_t));
+		pte_t *pte = early_alloc(PTE_HWTABLE_OFF + PTE_HWTABLE_SIZE);
 		__pmd_populate(pmd, __pa(pte), prot);
 	}
 	BUG_ON(pmd_bad(*pmd));
@@ -551,11 +551,11 @@
 	} while (pte++, addr += PAGE_SIZE, addr != end);
 }
 
-static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
+static void __init alloc_init_section(pud_t *pud, unsigned long addr,
 				      unsigned long end, phys_addr_t phys,
 				      const struct mem_type *type)
 {
-	pmd_t *pmd = pmd_offset(pgd, addr);
+	pmd_t *pmd = pmd_offset(pud, addr);
 
 	/*
 	 * Try a section mapping - end, addr and phys must all be aligned
@@ -584,6 +584,19 @@
 	}
 }
 
+static void alloc_init_pud(pgd_t *pgd, unsigned long addr, unsigned long end,
+	unsigned long phys, const struct mem_type *type)
+{
+	pud_t *pud = pud_offset(pgd, addr);
+	unsigned long next;
+
+	do {
+		next = pud_addr_end(addr, end);
+		alloc_init_section(pud, addr, next, phys, type);
+		phys += next - addr;
+	} while (pud++, addr = next, addr != end);
+}
+
 static void __init create_36bit_mapping(struct map_desc *md,
 					const struct mem_type *type)
 {
@@ -592,13 +605,13 @@
 	pgd_t *pgd;
 
 	addr = md->virtual;
-	phys = (unsigned long)__pfn_to_phys(md->pfn);
+	phys = __pfn_to_phys(md->pfn);
 	length = PAGE_ALIGN(md->length);
 
 	if (!(cpu_architecture() >= CPU_ARCH_ARMv6 || cpu_is_xsc3())) {
 		printk(KERN_ERR "MM: CPU does not support supersection "
 		       "mapping for 0x%08llx at 0x%08lx\n",
-		       __pfn_to_phys((u64)md->pfn), addr);
+		       (long long)__pfn_to_phys((u64)md->pfn), addr);
 		return;
 	}
 
@@ -611,14 +624,14 @@
 	if (type->domain) {
 		printk(KERN_ERR "MM: invalid domain in supersection "
 		       "mapping for 0x%08llx at 0x%08lx\n",
-		       __pfn_to_phys((u64)md->pfn), addr);
+		       (long long)__pfn_to_phys((u64)md->pfn), addr);
 		return;
 	}
 
 	if ((addr | length | __pfn_to_phys(md->pfn)) & ~SUPERSECTION_MASK) {
-		printk(KERN_ERR "MM: cannot create mapping for "
-		       "0x%08llx at 0x%08lx invalid alignment\n",
-		       __pfn_to_phys((u64)md->pfn), addr);
+		printk(KERN_ERR "MM: cannot create mapping for 0x%08llx"
+		       " at 0x%08lx invalid alignment\n",
+		       (long long)__pfn_to_phys((u64)md->pfn), addr);
 		return;
 	}
 
@@ -631,7 +644,8 @@
 	pgd = pgd_offset_k(addr);
 	end = addr + length;
 	do {
-		pmd_t *pmd = pmd_offset(pgd, addr);
+		pud_t *pud = pud_offset(pgd, addr);
+		pmd_t *pmd = pmd_offset(pud, addr);
 		int i;
 
 		for (i = 0; i < 16; i++)
@@ -652,22 +666,23 @@
  */
 static void __init create_mapping(struct map_desc *md)
 {
-	unsigned long phys, addr, length, end;
+	unsigned long addr, length, end;
+	phys_addr_t phys;
 	const struct mem_type *type;
 	pgd_t *pgd;
 
 	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
-		printk(KERN_WARNING "BUG: not creating mapping for "
-		       "0x%08llx at 0x%08lx in user region\n",
-		       __pfn_to_phys((u64)md->pfn), md->virtual);
+		printk(KERN_WARNING "BUG: not creating mapping for 0x%08llx"
+		       " at 0x%08lx in user region\n",
+		       (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
 		return;
 	}
 
 	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
 	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
-		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
-		       "overlaps vmalloc space\n",
-		       __pfn_to_phys((u64)md->pfn), md->virtual);
+		printk(KERN_WARNING "BUG: mapping for 0x%08llx"
+		       " at 0x%08lx overlaps vmalloc space\n",
+		       (long long)__pfn_to_phys((u64)md->pfn), md->virtual);
 	}
 
 	type = &mem_types[md->type];
@@ -681,13 +696,13 @@
 	}
 
 	addr = md->virtual & PAGE_MASK;
-	phys = (unsigned long)__pfn_to_phys(md->pfn);
+	phys = __pfn_to_phys(md->pfn);
 	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
 
 	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
-		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
+		printk(KERN_WARNING "BUG: map for 0x%08llx at 0x%08lx can not "
 		       "be mapped using pages, ignoring.\n",
-		       __pfn_to_phys(md->pfn), addr);
+		       (long long)__pfn_to_phys(md->pfn), addr);
 		return;
 	}
 
@@ -696,7 +711,7 @@
 	do {
 		unsigned long next = pgd_addr_end(addr, end);
 
-		alloc_init_section(pgd, addr, next, phys, type);
+		alloc_init_pud(pgd, addr, next, phys, type);
 
 		phys += next - addr;
 		addr = next;
@@ -794,9 +809,10 @@
 		 */
 		if (__va(bank->start) >= vmalloc_min ||
 		    __va(bank->start) < (void *)PAGE_OFFSET) {
-			printk(KERN_NOTICE "Ignoring RAM at %.8lx-%.8lx "
+			printk(KERN_NOTICE "Ignoring RAM at %.8llx-%.8llx "
 			       "(vmalloc region overlap).\n",
-			       bank->start, bank->start + bank->size - 1);
+			       (unsigned long long)bank->start,
+			       (unsigned long long)bank->start + bank->size - 1);
 			continue;
 		}
 
@@ -807,10 +823,11 @@
 		if (__va(bank->start + bank->size) > vmalloc_min ||
 		    __va(bank->start + bank->size) < __va(bank->start)) {
 			unsigned long newsize = vmalloc_min - __va(bank->start);
-			printk(KERN_NOTICE "Truncating RAM at %.8lx-%.8lx "
-			       "to -%.8lx (vmalloc region overlap).\n",
-			       bank->start, bank->start + bank->size - 1,
-			       bank->start + newsize - 1);
+			printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
+			       "to -%.8llx (vmalloc region overlap).\n",
+			       (unsigned long long)bank->start,
+			       (unsigned long long)bank->start + bank->size - 1,
+			       (unsigned long long)bank->start + newsize - 1);
 			bank->size = newsize;
 		}
 #endif
@@ -827,16 +844,6 @@
 			 * rather difficult.
 			 */
 			reason = "with VIPT aliasing cache";
-		} else if (is_smp() && tlb_ops_need_broadcast()) {
-			/*
-			 * kmap_high needs to occasionally flush TLB entries,
-			 * however, if the TLB entries need to be broadcast
-			 * we may deadlock:
-			 *  kmap_high(irqs off)->flush_all_zero_pkmaps->
-			 *  flush_tlb_kernel_range->smp_call_function_many
-			 *   (must not be called with irqs off)
-			 */
-			reason = "without hardware TLB ops broadcasting";
 		}
 		if (reason) {
 			printk(KERN_CRIT "HIGHMEM is not supported %s, ignoring high memory\n",
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/pgd.c linux-libre-2.6.39-gnu/arch/arm/mm/pgd.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/pgd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/pgd.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 pgd_t *pgd_alloc(struct mm_struct *mm)
 {
 	pgd_t *new_pgd, *init_pgd;
+	pud_t *new_pud, *init_pud;
 	pmd_t *new_pmd, *init_pmd;
 	pte_t *new_pte, *init_pte;
 
@@ -46,7 +47,11 @@
 		 * On ARM, first page must always be allocated since it
 		 * contains the machine vectors.
 		 */
-		new_pmd = pmd_alloc(mm, new_pgd, 0);
+		new_pud = pud_alloc(mm, new_pgd, 0);
+		if (!new_pud)
+			goto no_pud;
+
+		new_pmd = pmd_alloc(mm, new_pud, 0);
 		if (!new_pmd)
 			goto no_pmd;
 
@@ -54,7 +59,8 @@
 		if (!new_pte)
 			goto no_pte;
 
-		init_pmd = pmd_offset(init_pgd, 0);
+		init_pud = pud_offset(init_pgd, 0);
+		init_pmd = pmd_offset(init_pud, 0);
 		init_pte = pte_offset_map(init_pmd, 0);
 		set_pte_ext(new_pte, *init_pte, 0);
 		pte_unmap(init_pte);
@@ -66,6 +72,8 @@
 no_pte:
 	pmd_free(mm, new_pmd);
 no_pmd:
+	pud_free(mm, new_pud);
+no_pud:
 	free_pages((unsigned long)new_pgd, 2);
 no_pgd:
 	return NULL;
@@ -74,6 +82,7 @@
 void pgd_free(struct mm_struct *mm, pgd_t *pgd_base)
 {
 	pgd_t *pgd;
+	pud_t *pud;
 	pmd_t *pmd;
 	pgtable_t pte;
 
@@ -84,7 +93,11 @@
 	if (pgd_none_or_clear_bad(pgd))
 		goto no_pgd;
 
-	pmd = pmd_offset(pgd, 0);
+	pud = pud_offset(pgd, 0);
+	if (pud_none_or_clear_bad(pud))
+		goto no_pud;
+
+	pmd = pmd_offset(pud, 0);
 	if (pmd_none_or_clear_bad(pmd))
 		goto no_pmd;
 
@@ -92,8 +105,11 @@
 	pmd_clear(pmd);
 	pte_free(mm, pte);
 no_pmd:
-	pgd_clear(pgd);
+	pud_clear(pud);
 	pmd_free(mm, pmd);
+no_pud:
+	pgd_clear(pgd);
+	pud_free(mm, pud);
 no_pgd:
 	free_pages((unsigned long) pgd_base, 2);
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1020e.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1020e.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1020e.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1020e.S	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  */
 #define CACHE_DLIMIT	32768
 
@@ -474,6 +474,9 @@
 	.word	cpu_arm1020e_dcache_clean_area
 	.word	cpu_arm1020e_switch_mm
 	.word	cpu_arm1020e_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020e_processor_functions, . - arm1020e_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1020.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1020.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1020.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1020.S	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  */
 #define CACHE_DLIMIT	32768
 
@@ -493,6 +493,9 @@
 	.word	cpu_arm1020_dcache_clean_area
 	.word	cpu_arm1020_switch_mm
 	.word	cpu_arm1020_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1020_processor_functions, . - arm1020_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1022.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1022.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1022.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1022.S	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  */
 #define CACHE_DLIMIT	32768
 
@@ -457,6 +457,9 @@
 	.word	cpu_arm1022_dcache_clean_area
 	.word	cpu_arm1022_switch_mm
 	.word	cpu_arm1022_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1022_processor_functions, . - arm1022_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1026.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1026.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm1026.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm1026.S	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  */
 #define CACHE_DLIMIT	32768
 
@@ -452,6 +452,9 @@
 	.word	cpu_arm1026_dcache_clean_area
 	.word	cpu_arm1026_switch_mm
 	.word	cpu_arm1026_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm1026_processor_functions, . - arm1026_processor_functions
 
 	.section .rodata
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm6_7.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm6_7.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm6_7.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm6_7.S	2011-05-19 00:06:34.000000000 -0400
@@ -284,6 +284,9 @@
 		.word	cpu_arm6_dcache_clean_area
 		.word	cpu_arm6_switch_mm
 		.word	cpu_arm6_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm6_processor_functions, . - arm6_processor_functions
 
 /*
@@ -301,6 +304,9 @@
 		.word	cpu_arm7_dcache_clean_area
 		.word	cpu_arm7_switch_mm
 		.word	cpu_arm7_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7_processor_functions, . - arm7_processor_functions
 
 		.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm720.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm720.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm720.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm720.S	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,7 @@
 /*
  * Function: arm720_proc_do_idle(void)
  * Params  : r0 = unused
- * Purpose : put the processer in proper idle mode
+ * Purpose : put the processor in proper idle mode
  */
 ENTRY(cpu_arm720_do_idle)
 		mov	pc, lr
@@ -185,6 +185,9 @@
 		.word	cpu_arm720_dcache_clean_area
 		.word	cpu_arm720_switch_mm
 		.word	cpu_arm720_set_pte_ext
+		.word	0
+		.word	0
+		.word	0
 		.size	arm720_processor_functions, . - arm720_processor_functions
 
 		.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm740.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm740.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm740.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm740.S	2011-05-19 00:06:34.000000000 -0400
@@ -130,6 +130,9 @@
 	.word	cpu_arm740_dcache_clean_area
 	.word	cpu_arm740_switch_mm
 	.word	0			@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm740_processor_functions, . - arm740_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm7tdmi.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm7tdmi.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm7tdmi.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm7tdmi.S	2011-05-19 00:06:34.000000000 -0400
@@ -70,6 +70,9 @@
 		.word	cpu_arm7tdmi_dcache_clean_area
 		.word	cpu_arm7tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm7tdmi_processor_functions, . - arm7tdmi_processor_functions
 
 		.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm920.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm920.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm920.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm920.S	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  */
 #define CACHE_DLIMIT	65536
 
@@ -387,6 +387,40 @@
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	cpu_arm920_suspend_size
+.equ	cpu_arm920_suspend_size, 4 * 3
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_arm920_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_arm920_do_suspend)
+
+ENTRY(cpu_arm920_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_arm920_do_resume)
+#else
+#define cpu_arm920_do_suspend	0
+#define cpu_arm920_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm920_setup, #function
@@ -432,6 +466,9 @@
 	.word	cpu_arm920_dcache_clean_area
 	.word	cpu_arm920_switch_mm
 	.word	cpu_arm920_set_pte_ext
+	.word	cpu_arm920_suspend_size
+	.word	cpu_arm920_do_suspend
+	.word	cpu_arm920_do_resume
 	.size	arm920_processor_functions, . - arm920_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm922.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm922.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm922.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm922.S	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.  (I think this should
+ * cache line maintenance instructions.  (I think this should
  * be 32768).
  */
 #define CACHE_DLIMIT	8192
@@ -436,6 +436,9 @@
 	.word	cpu_arm922_dcache_clean_area
 	.word	cpu_arm922_switch_mm
 	.word	cpu_arm922_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm922_processor_functions, . - arm922_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm925.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm925.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm925.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm925.S	2011-05-19 00:06:34.000000000 -0400
@@ -77,7 +77,7 @@
 /*
  * This is the size at which it becomes more efficient to
  * clean the whole cache, rather than using the individual
- * cache line maintainence instructions.
+ * cache line maintenance instructions.
  */
 #define CACHE_DLIMIT	8192
 
@@ -503,6 +503,9 @@
 	.word	cpu_arm925_dcache_clean_area
 	.word	cpu_arm925_switch_mm
 	.word	cpu_arm925_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	arm925_processor_functions, . - arm925_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm926.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm926.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm926.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm926.S	2011-05-19 00:06:34.000000000 -0400
@@ -401,6 +401,40 @@
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/plat-s3c24xx/sleep.S */
+.globl	cpu_arm926_suspend_size
+.equ	cpu_arm926_suspend_size, 4 * 3
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_arm926_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ PID
+	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r6, c2, c0, 0	@ TTB address
+	mrc	p15, 0, r7, c1, c0, 0	@ Control register
+	stmia	r0, {r4 - r7}
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_arm926_do_suspend)
+
+ENTRY(cpu_arm926_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I+D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I+D caches
+	ldmia	r0, {r4 - r7}
+	mcr	p15, 0, r4, c13, c0, 0	@ PID
+	mcr	p15, 0, r5, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r6, c2, c0, 0	@ TTB address
+	mov	r0, r7			@ control register
+	mov	r2, r6, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_BIT4 | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_arm926_do_resume)
+#else
+#define cpu_arm926_do_suspend	0
+#define cpu_arm926_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__arm926_setup, #function
@@ -456,6 +490,9 @@
 	.word	cpu_arm926_dcache_clean_area
 	.word	cpu_arm926_switch_mm
 	.word	cpu_arm926_set_pte_ext
+	.word	cpu_arm926_suspend_size
+	.word	cpu_arm926_do_suspend
+	.word	cpu_arm926_do_resume
 	.size	arm926_processor_functions, . - arm926_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm940.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm940.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm940.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm940.S	2011-05-19 00:06:34.000000000 -0400
@@ -363,6 +363,9 @@
 	.word	cpu_arm940_dcache_clean_area
 	.word	cpu_arm940_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm940_processor_functions, . - arm940_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm946.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm946.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm946.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm946.S	2011-05-19 00:06:34.000000000 -0400
@@ -419,6 +419,9 @@
 	.word	cpu_arm946_dcache_clean_area
 	.word	cpu_arm946_switch_mm
 	.word	0		@ cpu_*_set_pte
+	.word	0
+	.word	0
+	.word	0
 	.size	arm946_processor_functions, . - arm946_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm9tdmi.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm9tdmi.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-arm9tdmi.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-arm9tdmi.S	2011-05-19 00:06:34.000000000 -0400
@@ -70,6 +70,9 @@
 		.word	cpu_arm9tdmi_dcache_clean_area
 		.word	cpu_arm9tdmi_switch_mm
 		.word	0		@ cpu_*_set_pte
+		.word	0
+		.word	0
+		.word	0
 		.size	arm9tdmi_processor_functions, . - arm9tdmi_processor_functions
 
 		.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-fa526.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-fa526.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-fa526.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-fa526.S	2011-05-19 00:06:34.000000000 -0400
@@ -195,6 +195,9 @@
 	.word	cpu_fa526_dcache_clean_area
 	.word	cpu_fa526_switch_mm
 	.word	cpu_fa526_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	fa526_processor_functions, . - fa526_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-feroceon.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-feroceon.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-feroceon.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-feroceon.S	2011-05-19 00:06:34.000000000 -0400
@@ -554,6 +554,9 @@
 	.word	cpu_feroceon_dcache_clean_area
 	.word	cpu_feroceon_switch_mm
 	.word	cpu_feroceon_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	feroceon_processor_functions, . - feroceon_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-macros.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-macros.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-macros.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-macros.S	2011-05-19 00:06:34.000000000 -0400
@@ -85,7 +85,7 @@
 
 /*
  * Sanity check the PTE configuration for the code below - which makes
- * certain assumptions about how these bits are layed out.
+ * certain assumptions about how these bits are laid out.
  */
 #ifdef CONFIG_MMU
 #if L_PTE_SHARED != PTE_EXT_SHARED
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-mohawk.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-mohawk.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-mohawk.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-mohawk.S	2011-05-19 00:06:34.000000000 -0400
@@ -388,6 +388,9 @@
 	.word	cpu_mohawk_dcache_clean_area
 	.word	cpu_mohawk_switch_mm
 	.word	cpu_mohawk_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	mohawk_processor_functions, . - mohawk_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-sa1100.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-sa1100.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-sa1100.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-sa1100.S	2011-05-19 00:06:34.000000000 -0400
@@ -169,6 +169,42 @@
 #endif
 	mov	pc, lr
 
+.globl	cpu_sa1100_suspend_size
+.equ	cpu_sa1100_suspend_size, 4*4
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_sa1100_do_suspend)
+	stmfd	sp!, {r4 - r7, lr}
+	mrc	p15, 0, r4, c3, c0, 0		@ domain ID
+	mrc	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mrc	p15, 0, r6, c13, c0, 0		@ PID
+	mrc	p15, 0, r7, c1, c0, 0		@ control reg
+	stmia	r0, {r4 - r7}			@ store cp regs
+	ldmfd	sp!, {r4 - r7, pc}
+ENDPROC(cpu_sa1100_do_suspend)
+
+ENTRY(cpu_sa1100_do_resume)
+	ldmia	r0, {r4 - r7}			@ load cp regs
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c7, 0		@ flush I+D TLBs
+	mcr	p15, 0, r1, c7, c7, 0		@ flush I&D cache
+	mcr	p15, 0, r1, c9, c0, 0		@ invalidate RB
+	mcr	p15, 0, r1, c9, c0, 5		@ allow user space to use RB
+
+	mcr	p15, 0, r4, c3, c0, 0		@ domain ID
+	mcr	p15, 0, r5, c2, c0, 0		@ translation table base addr
+	mcr	p15, 0, r6, c13, c0, 0		@ PID
+	mov	r0, r7				@ control register
+	mov	r2, r5, lsr #14			@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_sa1100_do_resume)
+#else
+#define cpu_sa1100_do_suspend	0
+#define cpu_sa1100_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__sa1100_setup, #function
@@ -218,6 +254,9 @@
 	.word	cpu_sa1100_dcache_clean_area
 	.word	cpu_sa1100_switch_mm
 	.word	cpu_sa1100_set_pte_ext
+	.word	cpu_sa1100_suspend_size
+	.word	cpu_sa1100_do_suspend
+	.word	cpu_sa1100_do_resume
 	.size	sa1100_processor_functions, . - sa1100_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-sa110.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-sa110.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-sa110.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-sa110.S	2011-05-19 00:06:34.000000000 -0400
@@ -203,6 +203,9 @@
 	.word	cpu_sa110_dcache_clean_area
 	.word	cpu_sa110_switch_mm
 	.word	cpu_sa110_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	sa110_processor_functions, . - sa110_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-v6.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-v6.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-v6.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-v6.S	2011-05-19 00:06:34.000000000 -0400
@@ -121,6 +121,53 @@
 #endif
 	mov	pc, lr
 
+/* Suspend/resume support: taken from arch/arm/mach-s3c64xx/sleep.S */
+.globl	cpu_v6_suspend_size
+.equ	cpu_v6_suspend_size, 4 * 8
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_v6_do_suspend)
+	stmfd	sp!, {r4 - r11, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ Translation table base 0
+	mrc	p15, 0, r8, c2, c0, 1	@ Translation table base 1
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control register
+	mrc	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mrc	p15, 0, r11, c1, c0, 0	@ control register
+	stmia	r0, {r4 - r11}
+	ldmfd	sp!, {r4- r11, pc}
+ENDPROC(cpu_v6_do_suspend)
+
+ENTRY(cpu_v6_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c14, 0	@ clean+invalidate D cache
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 0, ip, c7, c15, 0	@ clean+invalidate cache
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write buffer
+	ldmia	r0, {r4 - r11}
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0	@ Translation table base 0
+	mcr	p15, 0, r8, c2, c0, 1	@ Translation table base 1
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control register
+	mcr	p15, 0, r10, c1, c0, 2	@ co-processor access control
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, ip, c7, c5, 4	@ ISB
+	mov	r0, r11			@ control register
+	mov	r2, r7, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v6_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v6_do_suspend 0
+#define cpu_v6_do_resume 0
+#endif
 
 
 	.type	cpu_v6_name, #object
@@ -206,6 +253,9 @@
 	.word	cpu_v6_dcache_clean_area
 	.word	cpu_v6_switch_mm
 	.word	cpu_v6_set_pte_ext
+	.word	cpu_v6_suspend_size
+	.word	cpu_v6_do_suspend
+	.word	cpu_v6_do_resume
 	.size	v6_processor_functions, . - v6_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-v7.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-v7.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-v7.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-v7.S	2011-05-19 00:06:34.000000000 -0400
@@ -108,10 +108,16 @@
 #ifdef CONFIG_ARM_ERRATA_430973
 	mcr	p15, 0, r2, c7, c5, 6		@ flush BTAC/BTB
 #endif
+#ifdef CONFIG_ARM_ERRATA_754322
+	dsb
+#endif
 	mcr	p15, 0, r2, c13, c0, 1		@ set reserved context ID
 	isb
 1:	mcr	p15, 0, r0, c2, c0, 0		@ set TTB 0
 	isb
+#ifdef CONFIG_ARM_ERRATA_754322
+	dsb
+#endif
 	mcr	p15, 0, r1, c13, c0, 1		@ set context ID
 	isb
 #endif
@@ -171,6 +177,87 @@
 	.ascii	"ARMv7 Processor"
 	.align
 
+	/*
+	 * 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
+	 */
+.equ	PRRR,	0xff0a81a8
+.equ	NMRR,	0x40e040e0
+
+/* Suspend/resume support: derived from arch/arm/mach-s5pv210/sleep.S */
+.globl	cpu_v7_suspend_size
+.equ	cpu_v7_suspend_size, 4 * 8
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_v7_do_suspend)
+	stmfd	sp!, {r4 - r11, lr}
+	mrc	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mrc	p15, 0, r5, c13, c0, 1	@ Context ID
+	mrc	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mrc	p15, 0, r7, c2, c0, 0	@ TTB 0
+	mrc	p15, 0, r8, c2, c0, 1	@ TTB 1
+	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 control
+	stmia	r0, {r4 - r11}
+	ldmfd	sp!, {r4 - r11, pc}
+ENDPROC(cpu_v7_do_suspend)
+
+ENTRY(cpu_v7_do_resume)
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate TLBs
+	mcr	p15, 0, ip, c7, c5, 0	@ invalidate I cache
+	ldmia	r0, {r4 - r11}
+	mcr	p15, 0, r4, c13, c0, 0	@ FCSE/PID
+	mcr	p15, 0, r5, c13, c0, 1	@ Context ID
+	mcr	p15, 0, r6, c3, c0, 0	@ Domain ID
+	mcr	p15, 0, r7, c2, c0, 0	@ TTB 0
+	mcr	p15, 0, r8, c2, c0, 1	@ TTB 1
+	mcr	p15, 0, ip, c2, c0, 2	@ TTB control register
+	mcr	p15, 0, r10, c1, c0, 1	@ Auxiliary control register
+	mcr	p15, 0, r11, c1, c0, 2	@ Co-processor access control
+	ldr	r4, =PRRR		@ PRRR
+	ldr	r5, =NMRR		@ NMRR
+	mcr	p15, 0, r4, c10, c2, 0	@ write PRRR
+	mcr	p15, 0, r5, c10, c2, 1	@ write NMRR
+	isb
+	mov	r0, r9			@ control register
+	mov	r2, r7, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, cpu_resume_l1_flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_v7_do_resume)
+cpu_resume_l1_flags:
+	ALT_SMP(.long PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_SMP)
+	ALT_UP(.long  PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_FLAGS_UP)
+#else
+#define cpu_v7_do_suspend	0
+#define cpu_v7_do_resume	0
+#endif
+
 	__CPUINIT
 
 /*
@@ -282,36 +369,8 @@
 	ALT_SMP(orr	r4, r4, #TTB_FLAGS_SMP)
 	ALT_UP(orr	r4, r4, #TTB_FLAGS_UP)
 	mcr	p15, 0, r4, c2, c0, 1		@ load TTB1
-	/*
-	 * 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
+	ldr	r5, =PRRR			@ PRRR
+	ldr	r6, =NMRR			@ NMRR
 	mcr	p15, 0, r5, c10, c2, 0		@ write PRRR
 	mcr	p15, 0, r6, c10, c2, 1		@ write NMRR
 #endif
@@ -357,6 +416,9 @@
 	.word	cpu_v7_dcache_clean_area
 	.word	cpu_v7_switch_mm
 	.word	cpu_v7_set_pte_ext
+	.word	0
+	.word	0
+	.word	0
 	.size	v7_processor_functions, . - v7_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-xsc3.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-xsc3.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-xsc3.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-xsc3.S	2011-05-19 00:06:34.000000000 -0400
@@ -413,9 +413,52 @@
 	mov	pc, lr
 
 	.ltorg
-
 	.align
 
+.globl	cpu_xsc3_suspend_size
+.equ	cpu_xsc3_suspend_size, 4 * 8
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_xsc3_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc 	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc 	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+	mrc 	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r1, r4 - r10}	@ store v:p offset + cp regs
+	ldmia	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xsc3_do_suspend)
+
+ENTRY(cpu_xsc3_do_resume)
+	ldmia	r0, {r1, r4 - r10}	@ load v:p offset + cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p15, 0, ip, c7, c10, 4	@ drain write (&fill) buffer
+	mcr	p15, 0, ip, c7, c5, 4	@ flush prefetch buffer
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c0, 1	@ auxiliary control reg
+
+	@ temporarily map resume_turn_on_mmu into the page table,
+	@ otherwise prefetch abort occurs after MMU is turned on
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =0x542e		@ section flags
+	b	cpu_resume_mmu
+ENDPROC(cpu_xsc3_do_resume)
+#else
+#define cpu_xsc3_do_suspend	0
+#define cpu_xsc3_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xsc3_setup, #function
@@ -476,6 +519,9 @@
 	.word	cpu_xsc3_dcache_clean_area
 	.word	cpu_xsc3_switch_mm
 	.word	cpu_xsc3_set_pte_ext
+	.word	cpu_xsc3_suspend_size
+	.word	cpu_xsc3_do_suspend
+	.word	cpu_xsc3_do_resume
 	.size	xsc3_processor_functions, . - xsc3_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/proc-xscale.S linux-libre-2.6.39-gnu/arch/arm/mm/proc-xscale.S
--- linux-libre-2.6.38-gnu/arch/arm/mm/proc-xscale.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/proc-xscale.S	2011-05-19 00:06:34.000000000 -0400
@@ -395,7 +395,7 @@
 	teq	r2, #DMA_TO_DEVICE
 	beq	xscale_dma_clean_range
 	b	xscale_dma_flush_range
-ENDPROC(xscsale_dma_a0_map_area)
+ENDPROC(xscale_dma_a0_map_area)
 
 /*
  *	dma_unmap_area(start, size, dir)
@@ -513,11 +513,49 @@
 	xscale_set_pte_ext_epilogue
 	mov	pc, lr
 
-
 	.ltorg
-
 	.align
 
+.globl	cpu_xscale_suspend_size
+.equ	cpu_xscale_suspend_size, 4 * 7
+#ifdef CONFIG_PM_SLEEP
+ENTRY(cpu_xscale_do_suspend)
+	stmfd	sp!, {r4 - r10, lr}
+	mrc	p14, 0, r4, c6, c0, 0	@ clock configuration, for turbo mode
+	mrc	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mrc	p15, 0, r6, c13, c0, 0	@ PID
+	mrc	p15, 0, r7, c3, c0, 0	@ domain ID
+	mrc	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mrc	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mrc	p15, 0, r10, c1, c0, 0	@ control reg
+	bic	r4, r4, #2		@ clear frequency change bit
+	stmia	r0, {r4 - r10}		@ store cp regs
+	ldmfd	sp!, {r4 - r10, pc}
+ENDPROC(cpu_xscale_do_suspend)
+
+ENTRY(cpu_xscale_do_resume)
+	ldmia	r0, {r4 - r10}		@ load cp regs
+	mov	ip, #0
+	mcr	p15, 0, ip, c8, c7, 0	@ invalidate I & D TLBs
+	mcr	p15, 0, ip, c7, c7, 0	@ invalidate I & D caches, BTB
+	mcr	p14, 0, r4, c6, c0, 0	@ clock configuration, turbo mode.
+	mcr	p15, 0, r5, c15, c1, 0	@ CP access reg
+	mcr	p15, 0, r6, c13, c0, 0	@ PID
+	mcr	p15, 0, r7, c3, c0, 0	@ domain ID
+	mcr	p15, 0, r8, c2, c0, 0	@ translation table base addr
+	mcr	p15, 0, r9, c1, c1, 0	@ auxiliary control reg
+	mov	r0, r10			@ control register
+	mov	r2, r8, lsr #14		@ get TTB0 base
+	mov	r2, r2, lsl #14
+	ldr	r3, =PMD_TYPE_SECT | PMD_SECT_BUFFERABLE | \
+		     PMD_SECT_CACHEABLE | PMD_SECT_AP_WRITE
+	b	cpu_resume_mmu
+ENDPROC(cpu_xscale_do_resume)
+#else
+#define cpu_xscale_do_suspend	0
+#define cpu_xscale_do_resume	0
+#endif
+
 	__CPUINIT
 
 	.type	__xscale_setup, #function
@@ -565,6 +603,9 @@
 	.word	cpu_xscale_dcache_clean_area
 	.word	cpu_xscale_switch_mm
 	.word	cpu_xscale_set_pte_ext
+	.word	cpu_xscale_suspend_size
+	.word	cpu_xscale_do_suspend
+	.word	cpu_xscale_do_resume
 	.size	xscale_processor_functions, . - xscale_processor_functions
 
 	.section ".rodata"
diff -druN linux-libre-2.6.38-gnu/arch/arm/mm/vmregion.c linux-libre-2.6.39-gnu/arch/arm/mm/vmregion.c
--- linux-libre-2.6.38-gnu/arch/arm/mm/vmregion.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/mm/vmregion.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 arm_vmregion_alloc(struct arm_vmregion_head *head, size_t align,
 		   size_t size, gfp_t gfp)
 {
-	unsigned long addr = head->vm_start, end = head->vm_end - size;
+	unsigned long start = head->vm_start, addr = head->vm_end;
 	unsigned long flags;
 	struct arm_vmregion *c, *new;
 
@@ -54,21 +54,20 @@
 
 	spin_lock_irqsave(&head->vm_lock, flags);
 
-	list_for_each_entry(c, &head->vm_list, vm_list) {
-		if ((addr + size) < addr)
-			goto nospc;
-		if ((addr + size) <= c->vm_start)
+	addr = rounddown(addr - size, align);
+	list_for_each_entry_reverse(c, &head->vm_list, vm_list) {
+		if (addr >= c->vm_end)
 			goto found;
-		addr = ALIGN(c->vm_end, align);
-		if (addr > end)
+		addr = rounddown(c->vm_start - size, align);
+		if (addr < start)
 			goto nospc;
 	}
 
  found:
 	/*
-	 * Insert this entry _before_ the one we found.
+	 * Insert this entry after the one we found.
 	 */
-	list_add_tail(&new->vm_list, &c->vm_list);
+	list_add(&new->vm_list, &c->vm_list);
 	new->vm_start = addr;
 	new->vm_end = addr + size;
 	new->vm_active = 1;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/3ds_debugboard.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/3ds_debugboard.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/3ds_debugboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/3ds_debugboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,14 +100,9 @@
 
 	expio_irq = MXC_BOARD_IRQ_START;
 	for (; int_valid != 0; int_valid >>= 1, expio_irq++) {
-		struct irq_desc *d;
 		if ((int_valid & 1) == 0)
 			continue;
-		d = irq_desc + expio_irq;
-		if (unlikely(!(d->handle_irq)))
-			pr_err("\nEXPIO irq: %d unhandled\n", expio_irq);
-		else
-			d->handle_irq(expio_irq, d);
+		generic_handle_irq(expio_irq);
 	}
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
@@ -186,12 +181,11 @@
 	__raw_writew(0x1F, brd_io + INTR_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);
+		irq_set_chip_and_handler(i, &expio_irq_chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
-	set_irq_type(p_irq, IRQF_TRIGGER_LOW);
-	set_irq_chained_handler(p_irq, mxc_expio_irq_handler);
+	irq_set_irq_type(p_irq, IRQF_TRIGGER_LOW);
+	irq_set_chained_handler(p_irq, mxc_expio_irq_handler);
 
 	/* Register Lan device on the debugboard */
 	smsc911x_resources[0].start = LAN9217_BASE_ADDR(base);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/avic.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/avic.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/avic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/avic.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,8 +139,8 @@
 	__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.base);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &mxc_avic_chip.base,
+					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/cpufreq.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 
 /*
  * A driver for the Freescale Semiconductor i.MXC CPUfreq module.
- * The CPUFREQ driver is for controling CPU frequency. It allows you to change
+ * The CPUFREQ driver is for controlling CPU frequency. It allows you to change
  * the CPU clock speed on the fly.
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-fec.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-fec.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-fec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-fec.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,11 @@
 	imx_fec_data_entry_single(MX35);
 #endif
 
+#ifdef CONFIG_SOC_IMX50
+const struct imx_fec_data imx50_fec_data __initconst =
+	imx_fec_data_entry_single(MX50);
+#endif
+
 #ifdef CONFIG_SOC_IMX51
 const struct imx_fec_data imx51_fec_data __initconst =
 	imx_fec_data_entry_single(MX51);
@@ -48,7 +53,7 @@
 	struct resource res[] = {
 		{
 			.start = data->iobase,
-			.end = data->iobase + SZ_4K,
+			.end = data->iobase + SZ_4K - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
 			.start = data->irq,
@@ -57,7 +62,7 @@
 		},
 	};
 
-	return imx_add_platform_device("fec", 0 /* -1? */,
+	return imx_add_platform_device_dmamask("fec", 0,
 			res, ARRAY_SIZE(res),
-			pdata, sizeof(*pdata));
+			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx2-wdt.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx2-wdt.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx2-wdt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx2-wdt.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,6 +53,15 @@
 };
 #endif /* ifdef CONFIG_SOC_IMX51 */
 
+#ifdef CONFIG_SOC_IMX53
+const struct imx_imx2_wdt_data imx53_imx2_wdt_data[] __initconst = {
+#define imx53_imx2_wdt_data_entry(_id, _hwid)				\
+	imx_imx2_wdt_data_entry(MX53, _id, _hwid, SZ_16K)
+	imx53_imx2_wdt_data_entry(0, 1),
+	imx53_imx2_wdt_data_entry(1, 2),
+};
+#endif /* ifdef CONFIG_SOC_IMX53 */
+
 struct platform_device *__init imx_add_imx2_wdt(
 		const struct imx_imx2_wdt_data *data)
 {
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imxdi_rtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 	struct resource res[] = {
 		{
 			.start = data->iobase,
-			.end = data->iobase + SZ_16K,
+			.end = data->iobase + SZ_16K - 1,
 			.flags = IORESOURCE_MEM,
 		}, {
 			.start = data->irq,
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx-dma.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx-dma.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx-dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx-dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 static struct sdma_script_start_addrs addr_imx31_to1 = {
 	.per_2_per_addr = 1677,
 };
@@ -106,7 +106,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 static struct sdma_script_start_addrs addr_imx35_to1 = {
 	.ap_2_ap_addr = 642,
 	.uart_2_mcu_addr = 817,
@@ -194,7 +194,7 @@
 	} else
 #endif
 
-#if defined(CONFIG_ARCH_MX51)
+#if defined(CONFIG_SOC_IMX51)
 	if (cpu_is_mx51()) {
 		imx51_imx_sdma_data.pdata.script_addrs = &addr_imx51_to1;
 		ret = imx_add_imx_sdma(&imx51_imx_sdma_data);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx-fb.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx-fb.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx-fb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx-fb.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,11 @@
 		.irq = soc ## _INT_LCDC,				\
 	}
 
+#ifdef CONFIG_SOC_IMX1
+const struct imx_imx_fb_data imx1_imx_fb_data __initconst =
+	imx_imx_fb_data_entry_single(MX1, SZ_4K);
+#endif /* ifdef CONFIG_SOC_IMX1 */
+
 #ifdef CONFIG_SOC_IMX21
 const struct imx_imx_fb_data imx21_imx_fb_data __initconst =
 	imx_imx_fb_data_entry_single(MX21, SZ_4K);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-imx-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,6 +69,16 @@
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
+#ifdef CONFIG_SOC_IMX50
+const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
+#define imx50_imx_i2c_data_entry(_id, _hwid)				\
+	imx_imx_i2c_data_entry(MX50, _id, _hwid, SZ_4K)
+	imx50_imx_i2c_data_entry(0, 1),
+	imx50_imx_i2c_data_entry(1, 2),
+	imx50_imx_i2c_data_entry(2, 3),
+};
+#endif /* ifdef CONFIG_SOC_IMX51 */
+
 #ifdef CONFIG_SOC_IMX51
 const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 #define imx51_imx_i2c_data_entry(_id, _hwid)				\
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-spi_imx.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-spi_imx.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices/platform-spi_imx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices/platform-spi_imx.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,15 @@
 #define imx_spi_imx_data_entry(soc, type, devid, id, hwid, size)	\
 	[id] = imx_spi_imx_data_entry_single(soc, type, devid, id, hwid, size)
 
+#ifdef CONFIG_SOC_IMX1
+const struct imx_spi_imx_data imx1_cspi_data[] __initconst = {
+#define imx1_cspi_data_entry(_id, _hwid) \
+	imx_spi_imx_data_entry(MX1, CSPI, "imx1-cspi", _id, _hwid, SZ_4K)
+	imx1_cspi_data_entry(0, 1),
+	imx1_cspi_data_entry(1, 2),
+};
+#endif
+
 #ifdef CONFIG_SOC_IMX21
 const struct imx_spi_imx_data imx21_cspi_data[] __initconst = {
 #define imx21_cspi_data_entry(_id, _hwid)                            \
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,6 +81,8 @@
 	ret = platform_device_add(pdev);
 	if (ret) {
 err:
+		if (dmamask)
+			kfree(pdev->dev.dma_mask);
 		platform_device_put(pdev);
 		return ERR_PTR(ret);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/ehci.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/ehci.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/ehci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/ehci.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,369 +0,0 @@
-/*
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.de>
- * Copyright (C) 2010 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.
- *
- * This program is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * for more details.
- */
-
-#include <linux/platform_device.h>
-#include <linux/io.h>
-
-#include <mach/hardware.h>
-#include <mach/mxc_ehci.h>
-
-#define USBCTRL_OTGBASE_OFFSET	0x600
-
-#define MX31_OTG_SIC_SHIFT	29
-#define MX31_OTG_SIC_MASK	(0x3 << MX31_OTG_SIC_SHIFT)
-#define MX31_OTG_PM_BIT		(1 << 24)
-
-#define MX31_H2_SIC_SHIFT	21
-#define MX31_H2_SIC_MASK	(0x3 << MX31_H2_SIC_SHIFT)
-#define MX31_H2_PM_BIT		(1 << 16)
-#define MX31_H2_DT_BIT		(1 << 5)
-
-#define MX31_H1_SIC_SHIFT	13
-#define MX31_H1_SIC_MASK	(0x3 << MX31_H1_SIC_SHIFT)
-#define MX31_H1_PM_BIT		(1 << 8)
-#define MX31_H1_DT_BIT		(1 << 4)
-
-#define MX35_OTG_SIC_SHIFT	29
-#define MX35_OTG_SIC_MASK	(0x3 << MX35_OTG_SIC_SHIFT)
-#define MX35_OTG_PM_BIT		(1 << 24)
-
-#define MX35_H1_SIC_SHIFT	21
-#define MX35_H1_SIC_MASK	(0x3 << MX35_H1_SIC_SHIFT)
-#define MX35_H1_PM_BIT		(1 << 8)
-#define MX35_H1_IPPUE_UP_BIT	(1 << 7)
-#define MX35_H1_IPPUE_DOWN_BIT	(1 << 6)
-#define MX35_H1_TLL_BIT		(1 << 5)
-#define MX35_H1_USBTE_BIT	(1 << 4)
-
-#define MXC_OTG_OFFSET		0
-#define MXC_H1_OFFSET		0x200
-#define MXC_H2_OFFSET		0x400
-
-/* USB_CTRL */
-#define MXC_OTG_UCTRL_OWIE_BIT		(1 << 27)	/* OTG wakeup intr enable */
-#define MXC_OTG_UCTRL_OPM_BIT		(1 << 24)	/* OTG power mask */
-#define MXC_H1_UCTRL_H1UIE_BIT		(1 << 12)	/* Host1 ULPI interrupt enable */
-#define MXC_H1_UCTRL_H1WIE_BIT		(1 << 11)	/* HOST1 wakeup intr enable */
-#define MXC_H1_UCTRL_H1PM_BIT		(1 <<  8)		/* HOST1 power mask */
-
-/* USB_PHY_CTRL_FUNC */
-#define MXC_OTG_PHYCTRL_OC_DIS_BIT	(1 << 8)	/* OTG Disable Overcurrent Event */
-#define MXC_H1_OC_DIS_BIT			(1 << 5)	/* UH1 Disable Overcurrent Event */
-
-/* USBH2CTRL */
-#define MXC_H2_UCTRL_H2UIE_BIT		(1 << 8)
-#define MXC_H2_UCTRL_H2WIE_BIT		(1 << 7)
-#define MXC_H2_UCTRL_H2PM_BIT		(1 << 4)
-
-#define MXC_USBCMD_OFFSET			0x140
-
-/* USBCMD */
-#define MXC_UCMD_ITC_NO_THRESHOLD_MASK	(~(0xff << 16))	/* Interrupt Threshold Control */
-
-int mxc_initialize_usb_hw(int port, unsigned int flags)
-{
-	unsigned int v;
-#if defined(CONFIG_SOC_IMX25)
-	if (cpu_is_mx25()) {
-		v = readl(MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX35_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_OTG_PM_BIT;
-
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX35_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX35_H1_TLL_BIT;
-
-			if (flags & MXC_EHCI_INTERNAL_PHY)
-				v |= MX35_H1_USBTE_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_DOWN)
-				v |= MX35_H1_IPPUE_DOWN_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_UP)
-				v |= MX35_H1_IPPUE_UP_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		writel(v, MX25_IO_ADDRESS(MX25_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-#endif /* if defined(CONFIG_SOC_IMX25) */
-#if defined(CONFIG_ARCH_MX3)
-	if (cpu_is_mx31()) {
-		v = readl(MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX31_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_OTG_PM_BIT;
-
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H1_DT_BIT;
-
-			break;
-		case 2:	/* H2 port */
-			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H2_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H2_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H2_DT_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		writel(v, MX31_IO_ADDRESS(MX31_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-
-	if (cpu_is_mx35()) {
-		v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX35_OTG_SIC_MASK | MX35_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX35_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_OTG_PM_BIT;
-
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX35_H1_SIC_MASK | MX35_H1_PM_BIT | MX35_H1_TLL_BIT |
-				MX35_H1_USBTE_BIT | MX35_H1_IPPUE_DOWN_BIT | MX35_H1_IPPUE_UP_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX35_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX35_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX35_H1_TLL_BIT;
-
-			if (flags & MXC_EHCI_INTERNAL_PHY)
-				v |= MX35_H1_USBTE_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_DOWN)
-				v |= MX35_H1_IPPUE_DOWN_BIT;
-
-			if (flags & MXC_EHCI_IPPUE_UP)
-				v |= MX35_H1_IPPUE_UP_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-
-		writel(v, MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-#endif /* CONFIG_ARCH_MX3 */
-#ifdef CONFIG_MACH_MX27
-	if (cpu_is_mx27()) {
-		/* On i.MX27 we can use the i.MX31 USBCTRL bits, they
-		 * are identical
-		 */
-		v = readl(MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		switch (port) {
-		case 0:	/* OTG port */
-			v &= ~(MX31_OTG_SIC_MASK | MX31_OTG_PM_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-					<< MX31_OTG_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_OTG_PM_BIT;
-			break;
-		case 1: /* H1 port */
-			v &= ~(MX31_H1_SIC_MASK | MX31_H1_PM_BIT | MX31_H1_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H1_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H1_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H1_DT_BIT;
-
-			break;
-		case 2:	/* H2 port */
-			v &= ~(MX31_H2_SIC_MASK | MX31_H2_PM_BIT | MX31_H2_DT_BIT);
-			v |= (flags & MXC_EHCI_INTERFACE_MASK)
-						<< MX31_H2_SIC_SHIFT;
-			if (!(flags & MXC_EHCI_POWER_PINS_ENABLED))
-				v |= MX31_H2_PM_BIT;
-
-			if (!(flags & MXC_EHCI_TTL_ENABLED))
-				v |= MX31_H2_DT_BIT;
-
-			break;
-		default:
-			return -EINVAL;
-		}
-		writel(v, MX27_IO_ADDRESS(MX27_USB_BASE_ADDR +
-				     USBCTRL_OTGBASE_OFFSET));
-		return 0;
-	}
-#endif /* CONFIG_MACH_MX27 */
-#ifdef CONFIG_SOC_IMX51
-	if (cpu_is_mx51()) {
-		void __iomem *usb_base;
-		void __iomem *usbotg_base;
-		void __iomem *usbother_base;
-		int ret = 0;
-
-		usb_base = ioremap(MX51_OTG_BASE_ADDR, SZ_4K);
-		if (!usb_base) {
-			printk(KERN_ERR "%s(): ioremap failed\n", __func__);
-			return -ENOMEM;
-		}
-
-		switch (port) {
-		case 0:	/* OTG port */
-			usbotg_base = usb_base + MXC_OTG_OFFSET;
-			break;
-		case 1:	/* Host 1 port */
-			usbotg_base = usb_base + MXC_H1_OFFSET;
-			break;
-		case 2: /* Host 2 port */
-			usbotg_base = usb_base + MXC_H2_OFFSET;
-			break;
-		default:
-			printk(KERN_ERR"%s no such port %d\n", __func__, port);
-			ret = -ENOENT;
-			goto error;
-		}
-		usbother_base = usb_base + MX5_USBOTHER_REGS_OFFSET;
-
-		switch (port) {
-		case 0:	/*OTG port */
-			if (flags & MXC_EHCI_INTERNAL_PHY) {
-				v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-				if (flags & MXC_EHCI_POWER_PINS_ENABLED) {
-					/* OC/USBPWR is not used */
-					v |= MXC_OTG_PHYCTRL_OC_DIS_BIT;
-				} else {
-					/* OC/USBPWR is used */
-					v &= ~MXC_OTG_PHYCTRL_OC_DIS_BIT;
-				}
-				__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-				v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-				if (flags & MXC_EHCI_WAKEUP_ENABLED)
-					v |= MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup enable */
-				else
-					v &= ~MXC_OTG_UCTRL_OWIE_BIT;/* OTG wakeup disable */
-				if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-					v |= MXC_OTG_UCTRL_OPM_BIT;
-				else
-					v &= ~MXC_OTG_UCTRL_OPM_BIT;
-				__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-			}
-			break;
-		case 1:	/* Host 1 */
-			/*Host ULPI */
-			v = __raw_readl(usbother_base + MXC_USBCTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-				/* HOST1 wakeup/ULPI intr enable */
-				v |= (MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-			} else {
-				/* HOST1 wakeup/ULPI intr disable */
-				v &= ~(MXC_H1_UCTRL_H1WIE_BIT | MXC_H1_UCTRL_H1UIE_BIT);
-			}
-
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-			else
-				v |= MXC_H1_UCTRL_H1PM_BIT; /* HOST1 power mask used*/
-			__raw_writel(v, usbother_base + MXC_USBCTRL_OFFSET);
-
-			v = __raw_readl(usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_H1_OC_DIS_BIT; /* OC is used */
-			else
-				v |= MXC_H1_OC_DIS_BIT; /* OC is not used */
-			__raw_writel(v, usbother_base + MXC_USB_PHY_CTR_FUNC_OFFSET);
-
-			v = __raw_readl(usbotg_base + MXC_USBCMD_OFFSET);
-			if (flags & MXC_EHCI_ITC_NO_THRESHOLD)
-				/* Interrupt Threshold Control:Immediate (no threshold) */
-				v &= MXC_UCMD_ITC_NO_THRESHOLD_MASK;
-			__raw_writel(v, usbotg_base + MXC_USBCMD_OFFSET);
-			break;
-		case 2: /* Host 2 ULPI */
-			v = __raw_readl(usbother_base + MXC_USBH2CTRL_OFFSET);
-			if (flags & MXC_EHCI_WAKEUP_ENABLED) {
-				/* HOST1 wakeup/ULPI intr enable */
-				v |= (MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-			} else {
-				/* HOST1 wakeup/ULPI intr disable */
-				v &= ~(MXC_H2_UCTRL_H2WIE_BIT | MXC_H2_UCTRL_H2UIE_BIT);
-			}
-
-			if (flags & MXC_EHCI_POWER_PINS_ENABLED)
-				v &= ~MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-			else
-				v |= MXC_H2_UCTRL_H2PM_BIT; /* HOST2 power mask used*/
-			__raw_writel(v, usbother_base + MXC_USBH2CTRL_OFFSET);
-			break;
-		}
-
-error:
-		iounmap(usb_base);
-		return ret;
-	}
-#endif
-	printk(KERN_WARNING
-		"%s() unable to setup USBCONTROL for this CPU\n", __func__);
-	return -EINVAL;
-}
-EXPORT_SYMBOL(mxc_initialize_usb_hw);
-
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/gpio.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -175,7 +175,7 @@
 static void mx3_gpio_irq_handler(u32 irq, struct irq_desc *desc)
 {
 	u32 irq_stat;
-	struct mxc_gpio_port *port = get_irq_data(irq);
+	struct mxc_gpio_port *port = irq_get_handler_data(irq);
 
 	irq_stat = __raw_readl(port->base + GPIO_ISR) &
 			__raw_readl(port->base + GPIO_IMR);
@@ -188,7 +188,7 @@
 {
 	int i;
 	u32 irq_msk, irq_stat;
-	struct mxc_gpio_port *port = get_irq_data(irq);
+	struct mxc_gpio_port *port = irq_get_handler_data(irq);
 
 	/* walk through all interrupt status registers */
 	for (i = 0; i < gpio_table_size; i++) {
@@ -233,6 +233,7 @@
 }
 
 static struct irq_chip gpio_irq_chip = {
+	.name = "GPIO",
 	.irq_ack = gpio_ack_irq,
 	.irq_mask = gpio_mask_irq,
 	.irq_unmask = gpio_unmask_irq,
@@ -294,6 +295,12 @@
 	return 0;
 }
 
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parents, so it won't report false recursion.
+ */
+static struct lock_class_key gpio_lock_class;
+
 int __init mxc_gpio_init(struct mxc_gpio_port *port, int cnt)
 {
 	int i, j;
@@ -310,8 +317,9 @@
 		__raw_writel(~0, port[i].base + GPIO_ISR);
 		for (j = port[i].virtual_irq_start;
 			j < port[i].virtual_irq_start + 32; j++) {
-			set_irq_chip(j, &gpio_irq_chip);
-			set_irq_handler(j, handle_level_irq);
+			irq_set_lockdep_class(j, &gpio_lock_class);
+			irq_set_chip_and_handler(j, &gpio_irq_chip,
+						 handle_level_irq);
 			set_irq_flags(j, IRQF_VALID);
 		}
 
@@ -330,132 +338,24 @@
 
 		if (cpu_is_mx1() || cpu_is_mx3() || cpu_is_mx25() || cpu_is_mx51()) {
 			/* setup one handler for each entry */
-			set_irq_chained_handler(port[i].irq, mx3_gpio_irq_handler);
-			set_irq_data(port[i].irq, &port[i]);
+			irq_set_chained_handler(port[i].irq,
+						mx3_gpio_irq_handler);
+			irq_set_handler_data(port[i].irq, &port[i]);
 			if (port[i].irq_high) {
 				/* setup handler for GPIO 16 to 31 */
-				set_irq_chained_handler(port[i].irq_high,
-						mx3_gpio_irq_handler);
-				set_irq_data(port[i].irq_high, &port[i]);
+				irq_set_chained_handler(port[i].irq_high,
+							mx3_gpio_irq_handler);
+				irq_set_handler_data(port[i].irq_high,
+						     &port[i]);
 			}
 		}
 	}
 
 	if (cpu_is_mx2()) {
 		/* setup one handler for all GPIO interrupts */
-		set_irq_chained_handler(port[0].irq, mx2_gpio_irq_handler);
-		set_irq_data(port[0].irq, port);
+		irq_set_chained_handler(port[0].irq, mx2_gpio_irq_handler);
+		irq_set_handler_data(port[0].irq, port);
 	}
 
 	return 0;
 }
-
-#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\
-	{								\
-		.chip.label = "gpio-" #_id,				\
-		.irq = _irq,						\
-		.irq_high = _irq_high,					\
-		.base = soc ## _IO_ADDRESS(				\
-				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\
-		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\
-	}
-
-#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
-#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\
-	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
-
-#define DEFINE_REGISTER_FUNCTION(prefix)				\
-int __init prefix ## _register_gpios(void)				\
-{									\
-	return mxc_gpio_init(prefix ## _gpio_ports,			\
-			ARRAY_SIZE(prefix ## _gpio_ports));		\
-}
-
-#if defined(CONFIG_SOC_IMX1)
-static struct mxc_gpio_port imx1_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 0, 1, MX1_GPIO_INT_PORTA),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 1, 2, MX1_GPIO_INT_PORTB),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 2, 3, MX1_GPIO_INT_PORTC),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX1, 3, 4, MX1_GPIO_INT_PORTD),
-};
-
-DEFINE_REGISTER_FUNCTION(imx1)
-
-#endif /* if defined(CONFIG_SOC_IMX1) */
-
-#if defined(CONFIG_SOC_IMX21)
-static struct mxc_gpio_port imx21_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX21, 0, 1, MX21_INT_GPIO),
-	DEFINE_IMX_GPIO_PORT(MX21, 1, 2),
-	DEFINE_IMX_GPIO_PORT(MX21, 2, 3),
-	DEFINE_IMX_GPIO_PORT(MX21, 3, 4),
-	DEFINE_IMX_GPIO_PORT(MX21, 4, 5),
-	DEFINE_IMX_GPIO_PORT(MX21, 5, 6),
-};
-
-DEFINE_REGISTER_FUNCTION(imx21)
-
-#endif /* if defined(CONFIG_SOC_IMX21) */
-
-#if defined(CONFIG_SOC_IMX25)
-static struct mxc_gpio_port imx25_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 0, 1, MX25_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 1, 2, MX25_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 2, 3, MX25_INT_GPIO3),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX25, 3, 4, MX25_INT_GPIO4),
-};
-
-DEFINE_REGISTER_FUNCTION(imx25)
-
-#endif /* if defined(CONFIG_SOC_IMX25) */
-
-#if defined(CONFIG_SOC_IMX27)
-static struct mxc_gpio_port imx27_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX27, 0, 1, MX27_INT_GPIO),
-	DEFINE_IMX_GPIO_PORT(MX27, 1, 2),
-	DEFINE_IMX_GPIO_PORT(MX27, 2, 3),
-	DEFINE_IMX_GPIO_PORT(MX27, 3, 4),
-	DEFINE_IMX_GPIO_PORT(MX27, 4, 5),
-	DEFINE_IMX_GPIO_PORT(MX27, 5, 6),
-};
-
-DEFINE_REGISTER_FUNCTION(imx27)
-
-#endif /* if defined(CONFIG_SOC_IMX27) */
-
-#if defined(CONFIG_SOC_IMX31)
-static struct mxc_gpio_port imx31_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 0, 1, MX31_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 1, 2, MX31_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX31, 2, 3, MX31_INT_GPIO3),
-};
-
-DEFINE_REGISTER_FUNCTION(imx31)
-
-#endif /* if defined(CONFIG_SOC_IMX31) */
-
-#if defined(CONFIG_SOC_IMX35)
-static struct mxc_gpio_port imx35_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 0, 1, MX35_INT_GPIO1),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 1, 2, MX35_INT_GPIO2),
-	DEFINE_IMX_GPIO_PORT_IRQ(MX35, 2, 3, MX35_INT_GPIO3),
-};
-
-DEFINE_REGISTER_FUNCTION(imx35)
-
-#endif /* if defined(CONFIG_SOC_IMX35) */
-
-#if defined(CONFIG_SOC_IMX50)
-static struct mxc_gpio_port imx50_gpio_ports[] = {
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 0, 1, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 1, 2, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 2, 3, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 3, 4, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 4, 5, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(MX50, 5, 6, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH),
-};
-
-DEFINE_REGISTER_FUNCTION(imx50)
-
-#endif /* if defined(CONFIG_SOC_IMX50) */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/audmux.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/audmux.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/audmux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/audmux.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,14 @@
 #define MX31_AUDMUX_PORT5_SSI_PINS_5	4
 #define MX31_AUDMUX_PORT6_SSI_PINS_6	5
 
+#define MX51_AUDMUX_PORT1_SSI0		0
+#define MX51_AUDMUX_PORT2_SSI1		1
+#define MX51_AUDMUX_PORT3		2
+#define MX51_AUDMUX_PORT4		3
+#define MX51_AUDMUX_PORT5		4
+#define MX51_AUDMUX_PORT6		5
+#define MX51_AUDMUX_PORT7		6
+
 /* Register definitions for the i.MX21/27 Digital Audio Multiplexer */
 #define MXC_AUDMUX_V1_PCR_INMMASK(x)	((x) & 0xff)
 #define MXC_AUDMUX_V1_PCR_INMEN		(1 << 8)
@@ -28,7 +36,7 @@
 #define MXC_AUDMUX_V1_PCR_TCLKDIR	(1 << 30)
 #define MXC_AUDMUX_V1_PCR_TFSDIR	(1 << 31)
 
-/* Register definitions for the i.MX25/31/35 Digital Audio Multiplexer */
+/* Register definitions for the i.MX25/31/35/51 Digital Audio Multiplexer */
 #define MXC_AUDMUX_V2_PTCR_TFSDIR	(1 << 31)
 #define MXC_AUDMUX_V2_PTCR_TFSEL(x)	(((x) & 0xf) << 27)
 #define MXC_AUDMUX_V2_PTCR_TCLKDIR	(1 << 26)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/common.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/common.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,16 @@
 extern void mx51_map_io(void);
 extern void mx53_map_io(void);
 extern void mxc91231_map_io(void);
+extern void imx1_init_early(void);
+extern void imx21_init_early(void);
+extern void imx25_init_early(void);
+extern void imx27_init_early(void);
+extern void imx31_init_early(void);
+extern void imx35_init_early(void);
+extern void imx50_init_early(void);
+extern void imx51_init_early(void);
+extern void imx53_init_early(void);
+extern void mxc91231_init_early(void);
 extern void mxc_init_irq(void __iomem *);
 extern void tzic_init_irq(void __iomem *);
 extern void mx1_init_irq(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/entry-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -33,9 +33,9 @@
 	.macro  arch_ret_to_user, tmp1, tmp2
 	.endm
 
-	@ this macro checks which interrupt occured
+	@ this macro checks which interrupt occurred
 	@ and returns its number in irqnr
-	@ and returns if an interrupt occured in irqstat
+	@ and returns if an interrupt occurred in irqstat
 	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
 #ifndef CONFIG_MXC_TZIC
 	@ Load offset & priority of the highest priority
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/esdhc.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/esdhc.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/esdhc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/esdhc.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,17 @@
 #ifndef __ASM_ARCH_IMX_ESDHC_H
 #define __ASM_ARCH_IMX_ESDHC_H
 
+/**
+ * struct esdhc_platform_data - optional platform data for esdhc on i.MX
+ *
+ * strongly recommended for i.MX25/35, not needed for other variants
+ *
+ * @wp_gpio:	gpio for write_protect (-EINVAL if unused)
+ * @cd_gpio:	gpio for card_detect interrupt (-EINVAL if unused)
+ */
+
 struct esdhc_platform_data {
-	unsigned int wp_gpio;	/* write protect pin */
+	unsigned int wp_gpio;
+	unsigned int cd_gpio;
 };
 #endif /* __ASM_ARCH_IMX_ESDHC_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/gpio.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -46,6 +46,21 @@
 	spinlock_t lock;
 };
 
+#define DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, _irq_high)	\
+	{								\
+		.chip.label = "gpio-" #_id,				\
+		.irq = _irq,						\
+		.irq_high = _irq_high,					\
+		.base = soc ## _IO_ADDRESS(				\
+				soc ## _GPIO ## _hwid ## _BASE_ADDR),	\
+		.virtual_irq_start = MXC_GPIO_IRQ_START + (_id) * 32,	\
+	}
+
+#define DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, _irq)			\
+	DEFINE_IMX_GPIO_PORT_IRQ_HIGH(soc, _id, _hwid, _irq, 0)
+#define DEFINE_IMX_GPIO_PORT(soc, _id, _hwid)				\
+	DEFINE_IMX_GPIO_PORT_IRQ(soc, _id, _hwid, 0)
+
 int mxc_gpio_init(struct mxc_gpio_port*, int);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx2x.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx2x.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx2x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx2x.h	2011-05-19 00:06:34.000000000 -0400
@@ -90,12 +90,12 @@
 #define PC31_PF_SSI3_CLK	(GPIO_PORTC | GPIO_PF | GPIO_IN | 31)
 #define PD17_PF_I2C_DATA	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 17)
 #define PD18_PF_I2C_CLK		(GPIO_PORTD | GPIO_PF | GPIO_OUT | 18)
-#define PD19_PF_CSPI2_SS2	(GPIO_PORTD | GPIO_PF | 19)
-#define PD20_PF_CSPI2_SS1	(GPIO_PORTD | GPIO_PF | 20)
-#define PD21_PF_CSPI2_SS0	(GPIO_PORTD | GPIO_PF | 21)
-#define PD22_PF_CSPI2_SCLK	(GPIO_PORTD | GPIO_PF | 22)
-#define PD23_PF_CSPI2_MISO	(GPIO_PORTD | GPIO_PF | 23)
-#define PD24_PF_CSPI2_MOSI	(GPIO_PORTD | GPIO_PF | 24)
+#define PD19_PF_CSPI2_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 19)
+#define PD20_PF_CSPI2_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 20)
+#define PD21_PF_CSPI2_SS0	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 21)
+#define PD22_PF_CSPI2_SCLK	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 22)
+#define PD23_PF_CSPI2_MISO	(GPIO_PORTD | GPIO_PF | GPIO_IN | 23)
+#define PD24_PF_CSPI2_MOSI	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 24)
 #define PD25_PF_CSPI1_RDY	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 25)
 #define PD26_PF_CSPI1_SS2	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 26)
 #define PD27_PF_CSPI1_SS1	(GPIO_PORTD | GPIO_PF | GPIO_OUT | 27)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx35.h	2011-05-19 00:06:34.000000000 -0400
@@ -989,13 +989,13 @@
 #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_DATA3__ATA_DATA_3				IOMUX_PAD(0x6ec, 0x288, 0, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ESDHC3_CLK				IOMUX_PAD(0x6ec, 0x288, 1, 0x814, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__USB_TOP_USBOTG_DATA_5		IOMUX_PAD(0x6ec, 0x288, 2, 0x9b8, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__CSPI2_SCLK				IOMUX_PAD(0x6ec, 0x288, 4, 0x7e0, 2, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__GPIO2_16				IOMUX_PAD(0x6ec, 0x288, 5, 0x884, 1, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__IPU_DIAGB_10			IOMUX_PAD(0x6ec, 0x288, 6, 0x0,   0, NO_PAD_CTRL)
+#define MX35_PAD_ATA_DATA3__ARM11P_TOP_TRACE_29			IOMUX_PAD(0x6ec, 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)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx3.h	2011-05-19 00:06:34.000000000 -0400
@@ -112,12 +112,12 @@
  * 	- setups the iomux according to the configuration
  * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
  */
-int mxc_iomux_alloc_pin(const unsigned int pin, const char *label);
+int mxc_iomux_alloc_pin(unsigned int pin, const char *label);
 /*
  * setups mutliple pins
  * convenient way to call the above function with tables
  */
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label);
 
 /*
@@ -126,12 +126,12 @@
  * 	- frees the GPIO if the pin was configured as GPIO
  * 	- DOES NOT reconfigure the IOMUX in its reset state
  */
-void mxc_iomux_release_pin(const unsigned int pin);
+void mxc_iomux_release_pin(unsigned int pin);
 /*
  * releases multiple pins
  * convenvient way to call the above function with tables
  */
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count);
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
 
 /*
  * This function enables/disables the general purpose function for a particular
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx50.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx50.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx50.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx50.h	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 #define MX50_PAD_I2C1_SCL__I2C1_SCL	IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \
 							MX50_I2C_PAD_CTRL)
 #define MX50_PAD_I2C1_SCL__GPIO_6_18	IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x7cc, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 
 #define MX50_PAD_I2C1_SDA__I2C1_SDA	IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \
 							MX50_I2C_PAD_CTRL)
@@ -96,7 +96,7 @@
 #define MX50_PAD_I2C2_SCL__I2C2_SCL	IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \
 							MX50_I2C_PAD_CTRL)
 #define MX50_PAD_I2C2_SCL__GPIO_6_20	IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x7c8, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_I2C2_SCL__DCDC_OK	IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL)
 
 #define MX50_PAD_I2C2_SDA__I2C2_SDA	IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \
@@ -172,7 +172,7 @@
 
 #define MX50_PAD_SSI_RXFS__AUD3_RXFS	IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_SSI_RXFS__GPIO_6_4	IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x7e4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_SSI_RXFS__WEIM_D6	IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL)
 #define MX50_PAD_SSI_RXFS__CSPI_SS2	IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD)
 #define MX50_PAD_SSI_RXFS__FEC_COL	IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH)
@@ -186,25 +186,25 @@
 #define MX50_PAD_SSI_RXC__FEC_RX_CLK	IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL)
 #define MX50_PAD_SSI_RXC__FEC_MDIO	IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL)
 
-#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x7c4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_TXD__GPIO_6_6	IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL)
 
 #define MX50_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_RXD__GPIO_6_7	IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL)
 
-#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x7c0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_CTS__GPIO_6_8	IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x7e4, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_CTS__SD4_D4	IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART1_CTS__SD4_CMD	IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL)
 
 #define MX50_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART1_RTS__GPIO_6_9	IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART1_RTS__UART5_RXD	IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x0, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x0, 1, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x764, 0, MX50_SD_PAD_CTRL)
+#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x748, 0, MX50_SD_PAD_CTRL)
 
-#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x7cc, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART2_TXD__GPIO_6_10	IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART2_TXD__SD4_D6	IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_TXD__SD4_D4	IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL)
@@ -214,7 +214,7 @@
 #define MX50_PAD_UART2_RXD__SD4_D7	IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_RXD__SD4_D5	IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL)
 
-#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x7c8, 2, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART2_CTS__GPIO_6_12	IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART2_CTS__SD4_CMD	IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_CTS__SD4_D6	IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL)
@@ -224,7 +224,7 @@
 #define MX50_PAD_UART2_RTS__SD4_CLK	IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART2_RTS__SD4_D7	IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL)
 
-#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x7d4, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART3_TXD__GPIO_6_14	IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_UART3_TXD__SD1_D4	IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART3_TXD__SD4_D0	IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL)
@@ -238,9 +238,9 @@
 #define MX50_PAD_UART3_RXD__SD2_CD	IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART3_RXD__WEIM_D13	IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL)
 
-#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x7dc, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__GPIO_6_16	IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x7d0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__SD1_D6	IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__SD4_D2	IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL)
 #define MX50_PAD_UART4_TXD__SD2_LCTL	IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL)
@@ -278,7 +278,7 @@
 #define MX50_PAD_ECSPI1_MOSI__GPIO_4_13		IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI1_MOSI__CSPI_SS1		IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD)
 #define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1	IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x7d0, 3, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7	IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI1_MOSI__WEIM_D9		IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL)
 
@@ -294,7 +294,7 @@
 #define MX50_PAD_ECSPI1_SS0__GPIO_4_15		IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
 #define MX50_PAD_ECSPI1_SS0__CSPI_SS3		IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD)
 #define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3		IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x7d8, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9		IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI1_SS0__WEIM_D11		IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL)
 
@@ -311,17 +311,17 @@
 #define MX50_PAD_ECSPI2_MOSI__GPIO_4_17		IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD		IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1	IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x7e0, 1, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN		IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5	IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MOSI__WEIM_D9		IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL)
 
-#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x73c, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__GPIO_4_18		IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
 #define MX50_PAD_ECSPI2_MISO__ELCDIF_RS		IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2	IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x7e4, 4, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x0, 0, NO_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x0, 0, MX50_UART_PAD_CTRL)
+#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x73c, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__NANDF_CEN6	IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_ECSPI2_MISO__WEIM_D10		IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL)
 
@@ -503,7 +503,7 @@
 #define MX50_PAD_DISP_RD__ELCDIF_EN	IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
 #define MX50_PAD_DISP_RD__WEIM_A25	IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
 
-#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
 #define MX50_PAD_DISP_RS__GPIO_2_17	IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_DISP_RS__ELCDIF_VSYNC	IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
 #define MX50_PAD_DISP_RS__WEIM_A26	IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
@@ -691,8 +691,8 @@
 
 #define MX50_PAD_EPDC_D9__EPDC_D9	IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_EPDC_D9__GPIO_3_9	IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x810, 2, MX50_ELCDIF_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x810, 2, NO_PAD_CTRL)
+#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
 
 #define MX50_PAD_EPDC_D10__EPDC_D10	IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL)
 #define MX50_PAD_EPDC_D10__GPIO_3_10	IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx51.h	2011-05-19 00:06:34.000000000 -0400
@@ -473,7 +473,7 @@
 #define _MX51_PAD_UART2_RXD__UART2_RXD		IOMUX_PAD(0x628, 0x238, 0, 0x09ec, 2, 0)
 #define _MX51_PAD_UART2_TXD__FIRI_RXD		IOMUX_PAD(0x62c, 0x23c, 1, 0x0000, 0, 0)
 #define _MX51_PAD_UART2_TXD__GPIO1_21		IOMUX_PAD(0x62c, 0x23c, 3, 0x0000, 0, 0)
-#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x09ec, 3, 0)
+#define _MX51_PAD_UART2_TXD__UART2_TXD		IOMUX_PAD(0x62c, 0x23c, 0, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__CSI1_D0		IOMUX_PAD(0x630, 0x240, 2, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__GPIO1_22		IOMUX_PAD(0x630, 0x240, 3, 0x0000, 0, 0)
 #define _MX51_PAD_UART3_RXD__UART1_DTR		IOMUX_PAD(0x630, 0x240, 0, 0x0000, 0, 0)
@@ -528,7 +528,7 @@
 #define _MX51_PAD_USBH1_DATA1__UART2_RXD	IOMUX_PAD(0x68c, 0x28c, 1, 0x09ec, 4, 0)
 #define _MX51_PAD_USBH1_DATA1__USBH1_DATA1	IOMUX_PAD(0x68c, 0x28c, 0, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA2__GPIO1_13		IOMUX_PAD(0x690, 0x290, 2, 0x0000, 0, 0)
-#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x09ec, 5, 0)
+#define _MX51_PAD_USBH1_DATA2__UART2_TXD	IOMUX_PAD(0x690, 0x290, 1, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA2__USBH1_DATA2	IOMUX_PAD(0x690, 0x290, 0, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA3__GPIO1_14		IOMUX_PAD(0x694, 0x294, 2, 0x0000, 0, 0)
 #define _MX51_PAD_USBH1_DATA3__UART2_RTS	IOMUX_PAD(0x694, 0x294, 1, 0x09e8, 5, 0)
@@ -985,11 +985,11 @@
 #define MX51_PAD_NANDF_WE_B__GPIO3_3		(_MX51_PAD_NANDF_WE_B__GPIO3_3 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_WE_B__NANDF_WE_B		(_MX51_PAD_NANDF_WE_B__NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_WE_B__PATA_DIOW		(_MX51_PAD_NANDF_WE_B__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WE_B__SD3_DATA0		(_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_WE_B__SD3_DATA0		(_MX51_PAD_NANDF_WE_B__SD3_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RE_B__GPIO3_4		(_MX51_PAD_NANDF_RE_B__GPIO3_4 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RE_B__NANDF_RE_B		(_MX51_PAD_NANDF_RE_B__NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RE_B__PATA_DIOR		(_MX51_PAD_NANDF_RE_B__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RE_B__SD3_DATA1		(_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RE_B__SD3_DATA1		(_MX51_PAD_NANDF_RE_B__SD3_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_ALE__GPIO3_5		(_MX51_PAD_NANDF_ALE__GPIO3_5 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_ALE__NANDF_ALE		(_MX51_PAD_NANDF_ALE__NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_ALE__PATA_BUFFER_EN	(_MX51_PAD_NANDF_ALE__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -999,18 +999,18 @@
 #define MX51_PAD_NANDF_WP_B__GPIO3_7		(_MX51_PAD_NANDF_WP_B__GPIO3_7 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_WP_B__NANDF_WP_B		(_MX51_PAD_NANDF_WP_B__NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_WP_B__PATA_DMACK		(_MX51_PAD_NANDF_WP_B__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_WP_B__SD3_DATA2		(_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_WP_B__SD3_DATA2		(_MX51_PAD_NANDF_WP_B__SD3_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__ECSPI2_SS1		(_MX51_PAD_NANDF_RB0__ECSPI2_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__GPIO3_8		(_MX51_PAD_NANDF_RB0__GPIO3_8 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__NANDF_RB0		(_MX51_PAD_NANDF_RB0__NANDF_RB0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB0__PATA_DMARQ		(_MX51_PAD_NANDF_RB0__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB0__SD3_DATA3		(_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RB0__SD3_DATA3		(_MX51_PAD_NANDF_RB0__SD3_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__CSPI_MOSI		(_MX51_PAD_NANDF_RB1__CSPI_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__ECSPI2_RDY		(_MX51_PAD_NANDF_RB1__ECSPI2_RDY | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__GPIO3_9		(_MX51_PAD_NANDF_RB1__GPIO3_9 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__NANDF_RB1		(_MX51_PAD_NANDF_RB1__NANDF_RB1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB1__PATA_IORDY		(_MX51_PAD_NANDF_RB1__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RB1__SD4_CMD		(_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RB1__SD4_CMD		(_MX51_PAD_NANDF_RB1__SD4_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB2__DISP2_WAIT		(_MX51_PAD_NANDF_RB2__DISP2_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_RB2__ECSPI2_SCLK		(_MX51_PAD_NANDF_RB2__ECSPI2_SCLK | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RB2__FEC_COL		(_MX51_PAD_NANDF_RB2__FEC_COL | MUX_PAD_CTRL(MX51_PAD_CTRL_2))
@@ -1036,41 +1036,41 @@
 #define MX51_PAD_NANDF_CS2__GPIO3_18		(_MX51_PAD_NANDF_CS2__GPIO3_18 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS2__NANDF_CS2		(_MX51_PAD_NANDF_CS2__NANDF_CS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS2__PATA_CS_0		(_MX51_PAD_NANDF_CS2__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS2__SD4_CLK		(_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS2__SD4_CLK		(_MX51_PAD_NANDF_CS2__SD4_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_NANDF_CS2__USBH3_H1_DP		(_MX51_PAD_NANDF_CS2__USBH3_H1_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__FEC_MDC		(_MX51_PAD_NANDF_CS3__FEC_MDC | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS3__GPIO3_19		(_MX51_PAD_NANDF_CS3__GPIO3_19 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__NANDF_CS3		(_MX51_PAD_NANDF_CS3__NANDF_CS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__PATA_CS_1		(_MX51_PAD_NANDF_CS3__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS3__SD4_DAT0		(_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS3__SD4_DAT0		(_MX51_PAD_NANDF_CS3__SD4_DAT0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS3__USBH3_H1_DM		(_MX51_PAD_NANDF_CS3__USBH3_H1_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__FEC_TDATA1		(_MX51_PAD_NANDF_CS4__FEC_TDATA1 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS4__GPIO3_20		(_MX51_PAD_NANDF_CS4__GPIO3_20 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__NANDF_CS4		(_MX51_PAD_NANDF_CS4__NANDF_CS4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__PATA_DA_0		(_MX51_PAD_NANDF_CS4__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS4__SD4_DAT1		(_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS4__SD4_DAT1		(_MX51_PAD_NANDF_CS4__SD4_DAT1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS4__USBH3_STP		(_MX51_PAD_NANDF_CS4__USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__FEC_TDATA2		(_MX51_PAD_NANDF_CS5__FEC_TDATA2 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS5__GPIO3_21		(_MX51_PAD_NANDF_CS5__GPIO3_21 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__NANDF_CS5		(_MX51_PAD_NANDF_CS5__NANDF_CS5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__PATA_DA_1		(_MX51_PAD_NANDF_CS5__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS5__SD4_DAT2		(_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS5__SD4_DAT2		(_MX51_PAD_NANDF_CS5__SD4_DAT2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS5__USBH3_DIR		(_MX51_PAD_NANDF_CS5__USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__CSPI_SS3		(_MX51_PAD_NANDF_CS6__CSPI_SS3 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__FEC_TDATA3		(_MX51_PAD_NANDF_CS6__FEC_TDATA3 | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS6__GPIO3_22		(_MX51_PAD_NANDF_CS6__GPIO3_22 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__NANDF_CS6		(_MX51_PAD_NANDF_CS6__NANDF_CS6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS6__PATA_DA_2		(_MX51_PAD_NANDF_CS6__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS6__SD4_DAT3		(_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS6__SD4_DAT3		(_MX51_PAD_NANDF_CS6__SD4_DAT3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_CS7__FEC_TX_EN		(_MX51_PAD_NANDF_CS7__FEC_TX_EN | MUX_PAD_CTRL(MX51_PAD_CTRL_5))
 #define MX51_PAD_NANDF_CS7__GPIO3_23		(_MX51_PAD_NANDF_CS7__GPIO3_23 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_CS7__NANDF_CS7		(_MX51_PAD_NANDF_CS7__NANDF_CS7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_CS7__SD3_CLK		(_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_CS7__SD3_CLK		(_MX51_PAD_NANDF_CS7__SD3_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0	(_MX51_PAD_NANDF_RDY_INT__ECSPI2_SS0 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK	(_MX51_PAD_NANDF_RDY_INT__FEC_TX_CLK | MUX_PAD_CTRL(MX51_PAD_CTRL_4))
 #define MX51_PAD_NANDF_RDY_INT__GPIO3_24	(_MX51_PAD_NANDF_RDY_INT__GPIO3_24 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT	(_MX51_PAD_NANDF_RDY_INT__NANDF_RDY_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		(_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_NANDF_RDY_INT__SD3_CMD		(_MX51_PAD_NANDF_RDY_INT__SD3_CMD | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_NANDF_D15__ECSPI2_MOSI		(_MX51_PAD_NANDF_D15__ECSPI2_MOSI | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_NANDF_D15__GPIO3_25		(_MX51_PAD_NANDF_D15__GPIO3_25 | MUX_PAD_CTRL(MX51_GPIO_PAD_CTRL))
 #define MX51_PAD_NANDF_D15__NANDF_D15		(_MX51_PAD_NANDF_D15__NANDF_D15 | MUX_PAD_CTRL(NO_PAD_CTRL))
@@ -1479,26 +1479,26 @@
 #define MX51_PAD_SD1_CLK__SD1_CLK		(_MX51_PAD_SD1_CLK__SD1_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_SD1_DATA0__AUD5_TXD		(_MX51_PAD_SD1_DATA0__AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA0__CSPI_MISO		(_MX51_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA0__SD1_DATA0		(_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA0__SD1_DATA0		(_MX51_PAD_SD1_DATA0__SD1_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_EIM_DA0__EIM_DA0		(_MX51_PAD_EIM_DA0__EIM_DA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA1__EIM_DA1		(_MX51_PAD_EIM_DA1__EIM_DA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA2__EIM_DA2		(_MX51_PAD_EIM_DA2__EIM_DA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA3__EIM_DA3		(_MX51_PAD_EIM_DA3__EIM_DA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA1__AUD5_RXD		(_MX51_PAD_SD1_DATA1__AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA1__SD1_DATA1		(_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA1__SD1_DATA1		(_MX51_PAD_SD1_DATA1__SD1_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_EIM_DA4__EIM_DA4		(_MX51_PAD_EIM_DA4__EIM_DA4 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA5__EIM_DA5		(_MX51_PAD_EIM_DA5__EIM_DA5 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA6__EIM_DA6		(_MX51_PAD_EIM_DA6__EIM_DA6 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA7__EIM_DA7		(_MX51_PAD_EIM_DA7__EIM_DA7 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA2__AUD5_TXC		(_MX51_PAD_SD1_DATA2__AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD1_DATA2__SD1_DATA2		(_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA2__SD1_DATA2		(_MX51_PAD_SD1_DATA2__SD1_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_EIM_DA10__EIM_DA10		(_MX51_PAD_EIM_DA10__EIM_DA10 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA11__EIM_DA11		(_MX51_PAD_EIM_DA11__EIM_DA11 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA8__EIM_DA8		(_MX51_PAD_EIM_DA8__EIM_DA8 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_EIM_DA9__EIM_DA9		(_MX51_PAD_EIM_DA9__EIM_DA9 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA3__AUD5_TXFS		(_MX51_PAD_SD1_DATA3__AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD1_DATA3__CSPI_SS1		(_MX51_PAD_SD1_DATA3__CSPI_SS1 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
-#define MX51_PAD_SD1_DATA3__SD1_DATA3		(_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD1_DATA3__SD1_DATA3		(_MX51_PAD_SD1_DATA3__SD1_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_GPIO1_0__CSPI_SS2		(_MX51_PAD_GPIO1_0__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_GPIO1_0__GPIO1_0		(_MX51_PAD_GPIO1_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_GPIO1_0__SD1_CD		(_MX51_PAD_GPIO1_0__SD1_CD | MUX_PAD_CTRL(MX51_ESDHC_PAD_CTRL))
@@ -1517,16 +1517,16 @@
 #define MX51_PAD_SD2_CLK__SD2_CLK		(_MX51_PAD_SD2_CLK__SD2_CLK | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL | PAD_CTL_HYS))
 #define MX51_PAD_SD2_DATA0__CSPI_MISO		(_MX51_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA0__SD1_DAT4		(_MX51_PAD_SD2_DATA0__SD1_DAT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA0__SD2_DATA0		(_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA0__SD2_DATA0		(_MX51_PAD_SD2_DATA0__SD2_DATA0 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA1__SD1_DAT5		(_MX51_PAD_SD2_DATA1__SD1_DAT5 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA1__SD2_DATA1		(_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA1__SD2_DATA1		(_MX51_PAD_SD2_DATA1__SD2_DATA1 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA1__USBH3_H2_DP		(_MX51_PAD_SD2_DATA1__USBH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD2_DATA2__SD1_DAT6		(_MX51_PAD_SD2_DATA2__SD1_DAT6 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA2__SD2_DATA2		(_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA2__SD2_DATA2		(_MX51_PAD_SD2_DATA2__SD2_DATA2 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA2__USBH3_H2_DM		(_MX51_PAD_SD2_DATA2__USBH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_SD2_DATA3__CSPI_SS2		(_MX51_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(MX51_ECSPI_PAD_CTRL))
 #define MX51_PAD_SD2_DATA3__SD1_DAT7		(_MX51_PAD_SD2_DATA3__SD1_DAT7 | MUX_PAD_CTRL(NO_PAD_CTRL))
-#define MX51_PAD_SD2_DATA3__SD2_DATA3		(_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX51_PAD_SD2_DATA3__SD2_DATA3		(_MX51_PAD_SD2_DATA3__SD2_DATA3 | MUX_PAD_CTRL(MX51_SDHCI_PAD_CTRL))
 #define MX51_PAD_GPIO1_2__CCM_OUT_2		(_MX51_PAD_GPIO1_2__CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_GPIO1_2__GPIO1_2		(_MX51_PAD_GPIO1_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
 #define MX51_PAD_GPIO1_2__I2C2_SCL		(_MX51_PAD_GPIO1_2__I2C2_SCL | MUX_PAD_CTRL(MX51_I2C_PAD_CTRL))
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mx53.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2010-2011 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
@@ -21,305 +21,2358 @@
 
 #include <mach/iomux-v3.h>
 
-/*
- * various IOMUX alternate output functions (1-7)
- */
-typedef enum iomux_config {
-	IOMUX_CONFIG_ALT0,
-	IOMUX_CONFIG_ALT1,
-	IOMUX_CONFIG_ALT2,
-	IOMUX_CONFIG_ALT3,
-	IOMUX_CONFIG_ALT4,
-	IOMUX_CONFIG_ALT5,
-	IOMUX_CONFIG_ALT6,
-	IOMUX_CONFIG_ALT7,
-	IOMUX_CONFIG_GPIO, /* added to help user use GPIO mode */
-} iomux_pin_cfg_t;
-
 /* These 2 defines are for pins that may not have a mux register, but could
  * have a pad setting register, and vice-versa. */
-#define NON_MUX_I	0x00
 #define NON_PAD_I	0x00
 
 #define MX53_UART_PAD_CTRL		(PAD_CTL_PKE | PAD_CTL_PUE |	\
 		PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST | PAD_CTL_HYS)
-/* UART1 */
-#define MX53_PAD_CSI0_D10__UART1_TXD	IOMUX_PAD(0x414, 0xE8, 2, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_CSI0_D11__UART1_RXD	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DIOW__UART1_TXD	IOMUX_PAD(0x5F0, 0x270, 3, 0x0,	0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DMACK__UART1_RXD	IOMUX_PAD(0x5F4, 0x274, 3, 0x880, 3, MX53_UART_PAD_CTRL)
-
-/* UART2 */
-#define MX53_PAD_ATA_BUFFER_EN__UART2_RXD	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DMARQ__UART2_TXD	IOMUX_PAD(0x5F8, 0x278, 3, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DIOR__UART2_RTS	IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_INTRQ__UART2_CTS	IOMUX_PAD(0x600, 0x280, 3, 0x0, 0, MX53_UART_PAD_CTRL)
+#define MX53_SDHC_PAD_CTRL 	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
+				PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH | \
+				PAD_CTL_SRE_FAST)
 
-/* UART3 */
-#define MX53_PAD_ATA_CS_0__UART3_TXD	IOMUX_PAD(0x61C, 0x29C, 4, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_CS_1__UART3_RXD	IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DA_1__UART3_CTS	IOMUX_PAD(0x614, 0x294, 4, 0x0, 0, MX53_UART_PAD_CTRL)
-#define MX53_PAD_ATA_DA_2__UART3_RTS	IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, MX53_UART_PAD_CTRL)
+#define _MX53_PAD_GPIO_19__KPP_COL_5		IOMUX_PAD(0x348, 0x20, 0, 0x840, 0, 0)
+#define _MX53_PAD_GPIO_19__GPIO4_5		IOMUX_PAD(0x348, 0x20, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__CCM_CLKO		IOMUX_PAD(0x348, 0x20, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__SPDIF_OUT1	IOMUX_PAD(0x348, 0x20, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2	IOMUX_PAD(0x348, 0x20, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__ECSPI1_RDY	IOMUX_PAD(0x348, 0x20, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__FEC_TDATA_3	IOMUX_PAD(0x348, 0x20, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_19__SRC_INT_BOOT	IOMUX_PAD(0x348, 0x20,7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__KPP_COL_0	IOMUX_PAD(0x34C, 0x24, o, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__GPIO4_6		IOMUX_PAD(0x34C, 0x24, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC	IOMUX_PAD(0x34C, 0x24, 2, 0x758, 0, 0)
+#define _MX53_PAD_KEY_COL0__UART4_TXD_MUX	IOMUX_PAD(0x34C, 0x24, 4, 0x890, 0, 0)
+#define _MX53_PAD_KEY_COL0__ECSPI1_SCLK	IOMUX_PAD(0x34C, 0x24, 5, 0x79C, 0, 0)
+#define _MX53_PAD_KEY_COL0__FEC_RDATA_3	IOMUX_PAD(0x34C, 0x24, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL0__SRC_ANY_PU_RST	IOMUX_PAD(0x34C, 0x24, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW0__KPP_ROW_0	IOMUX_PAD(0x350, 0x28, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW0__GPIO4_7		IOMUX_PAD(0x350, 0x28, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD	IOMUX_PAD(0x350, 0x28, 2, 0x74C, 0, 0)
+#define _MX53_PAD_KEY_ROW0__UART4_RXD_MUX	IOMUX_PAD(0x350, 0x28, 4, 0x890, 1, 0)
+#define _MX53_PAD_KEY_ROW0__ECSPI1_MOSI	IOMUX_PAD(0x350, 0x28, 5, 0x7A4, 0, 0)
+#define _MX53_PAD_KEY_ROW0__FEC_TX_ER	IOMUX_PAD(0x350, 0x28, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL1__KPP_COL_1	IOMUX_PAD(0x354, 0x2C, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL1__GPIO4_8		IOMUX_PAD(0x354, 0x2C, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x354, 0x2C, 2, 0x75C, 0, 0)
+#define _MX53_PAD_KEY_COL1__UART5_TXD_MUX	IOMUX_PAD(0x354, 0x2C, 4, 0x898, 0, 0)
+#define _MX53_PAD_KEY_COL1__ECSPI1_MISO	IOMUX_PAD(0x354, 0x2C, 5, 0x7A0, 0, 0)
+#define _MX53_PAD_KEY_COL1__FEC_RX_CLK	IOMUX_PAD(0x354, 0x2C, 6, 0x808, 0, 0)
+#define _MX53_PAD_KEY_COL1__USBPHY1_TXREADY	IOMUX_PAD(0x354, 0x2C, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW1__KPP_ROW_1	IOMUX_PAD(0x358, 0x30, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW1__GPIO4_9		IOMUX_PAD(0x358, 0x30, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD	IOMUX_PAD(0x358, 0x30, 2, 0x748, 0, 0)
+#define _MX53_PAD_KEY_ROW1__UART5_RXD_MUX	IOMUX_PAD(0x358, 0x30, 4, 0x898, 1, 0)
+#define _MX53_PAD_KEY_ROW1__ECSPI1_SS0	IOMUX_PAD(0x358, 0x30, 5, 0x7A8, 0, 0)
+#define _MX53_PAD_KEY_ROW1__FEC_COL		IOMUX_PAD(0x358, 0x30, 6, 0x800, 0, 0)
+#define _MX53_PAD_KEY_ROW1__USBPHY1_RXVALID	IOMUX_PAD(0x358, 0x30, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__KPP_COL_2	IOMUX_PAD(0x35C, 0x34, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__GPIO4_10		IOMUX_PAD(0x35C, 0x34, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__CAN1_TXCAN	IOMUX_PAD(0x35C, 0x34, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__FEC_MDIO		IOMUX_PAD(0x35C, 0x34, 4, 0x804, 0, 0)
+#define _MX53_PAD_KEY_COL2__ECSPI1_SS1	IOMUX_PAD(0x35C, 0x34, 5, 0x7AC, 0, 0)
+#define _MX53_PAD_KEY_COL2__FEC_RDATA_2	IOMUX_PAD(0x35C, 0x34, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE	IOMUX_PAD(0x35C, 0x34, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__KPP_ROW_2	IOMUX_PAD(0x360, 0x38, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__GPIO4_11	IOMUX_PAD(0x360, 0x38, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__CAN1_RXCAN	IOMUX_PAD(0x360, 0x38, 2, 0x760, 0, 0)
+#define _MX53_PAD_KEY_ROW2__FEC_MDC		IOMUX_PAD(0x360, 0x38, 4, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__ECSPI1_SS2	IOMUX_PAD(0x360, 0x38, 5, 0x7B0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__FEC_TDATA_2	IOMUX_PAD(0x360, 0x38, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW2__USBPHY1_RXERROR	IOMUX_PAD(0x360, 0x38, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__KPP_COL_3	IOMUX_PAD(0x364, 0x3C, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__GPIO4_12		IOMUX_PAD(0x364, 0x3C, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__USBOH3_H2_DP	IOMUX_PAD(0x364, 0x3C, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__SPDIF_IN1	IOMUX_PAD(0x364, 0x3C, 3, 0x870, 0, 0)
+#define _MX53_PAD_KEY_COL3__I2C2_SCL		IOMUX_PAD(0x364, 0x3C, 4 | IOMUX_CONFIG_SION, 0x81C, 0, 0)
+#define _MX53_PAD_KEY_COL3__ECSPI1_SS3	IOMUX_PAD(0x364, 0x3C, 5, 0x7B4, 0, 0)
+#define _MX53_PAD_KEY_COL3__FEC_CRS		IOMUX_PAD(0x364, 0x3C, 6, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK	IOMUX_PAD(0x364, 0x3C, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__KPP_ROW_3	IOMUX_PAD(0x368, 0x40, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__GPIO4_13	IOMUX_PAD(0x368, 0x40, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__USBOH3_H2_DM	IOMUX_PAD(0x368, 0x40, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x368, 0x40, 3, 0x768, 0, 0)
+#define _MX53_PAD_KEY_ROW3__I2C2_SDA	IOMUX_PAD(0x368, 0x40, 4 | IOMUX_CONFIG_SION, 0x820, 0, 0)
+#define _MX53_PAD_KEY_ROW3__OSC32K_32K_OUT	IOMUX_PAD(0x368, 0x40, 5, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW3__CCM_PLL4_BYP	IOMUX_PAD(0x368, 0x40, 6, 0x77C, 0, 0)
+#define _MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0	IOMUX_PAD(0x368, 0x40, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__KPP_COL_4	IOMUX_PAD(0x36C, 0x44, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__GPIO4_14		IOMUX_PAD(0x36C, 0x44, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__CAN2_TXCAN	IOMUX_PAD(0x36C, 0x44, 2, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__IPU_SISG_4	IOMUX_PAD(0x36C, 0x44, 3, 0x0, 0, 0)
+#define _MX53_PAD_KEY_COL4__UART5_RTS	IOMUX_PAD(0x36C, 0x44, 4, 0x894, 0, 0)
+#define _MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC	IOMUX_PAD(0x36C, 0x44, 5, 0x89C, 0, 0)
+#define _MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1	IOMUX_PAD(0x36C, 0x44, 7, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__KPP_ROW_4	IOMUX_PAD(0x370, 0x48, 0, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__GPIO4_15	IOMUX_PAD(0x370, 0x48, 1, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__CAN2_RXCAN	IOMUX_PAD(0x370, 0x48, 2, 0x764, 0, 0)
+#define _MX53_PAD_KEY_ROW4__IPU_SISG_5	IOMUX_PAD(0x370, 0x48, 3, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__UART5_CTS	IOMUX_PAD(0x370, 0x48, 4, 0x894, 1, 0)
+#define _MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR	IOMUX_PAD(0x370, 0x48, 5, 0x0, 0, 0)
+#define _MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID	IOMUX_PAD(0x370, 0x48, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK	IOMUX_PAD(0x378, 0x4C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__GPIO4_16		IOMUX_PAD(0x378, 0x4C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR	IOMUX_PAD(0x378, 0x4C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0	IOMUX_PAD(0x378, 0x4C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0	IOMUX_PAD(0x378, 0x4C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID	IOMUX_PAD(0x378, 0x4C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		IOMUX_PAD(0x37C, 0x50, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__GPIO4_17		IOMUX_PAD(0x37C, 0x50, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC	IOMUX_PAD(0x37C, 0x50, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1	IOMUX_PAD(0x37C, 0x50, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1	IOMUX_PAD(0x37C, 0x50, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN15__USBPHY1_BVALID		IOMUX_PAD(0x37C, 0x50, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		IOMUX_PAD(0x380, 0x54, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__GPIO4_18			IOMUX_PAD(0x380, 0x54, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD	IOMUX_PAD(0x380, 0x54, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2	IOMUX_PAD(0x380, 0x54, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		IOMUX_PAD(0x380, 0x54, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION	IOMUX_PAD(0x380, 0x54, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		IOMUX_PAD(0x384, 0x58, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__GPIO4_19			IOMUX_PAD(0x384, 0x58, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS	IOMUX_PAD(0x384, 0x58, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3	IOMUX_PAD(0x384, 0x58, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		IOMUX_PAD(0x384, 0x58, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		IOMUX_PAD(0x384, 0x58, 7, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		IOMUX_PAD(0x388, 0x5C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__GPIO4_20			IOMUX_PAD(0x388, 0x5C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD	IOMUX_PAD(0x388, 0x5C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__ESDHC1_WP		IOMUX_PAD(0x388, 0x5C, 3, 0x7FC, 0, 0)
+#define _MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD	IOMUX_PAD(0x388, 0x5C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		IOMUX_PAD(0x388, 0x5C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT	IOMUX_PAD(0x388, 0x5C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0	IOMUX_PAD(0x38C, 0x60, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__GPIO4_21		IOMUX_PAD(0x38C, 0x60, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__CSPI_SCLK		IOMUX_PAD(0x38C, 0x60, 2, 0x780, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0	IOMUX_PAD(0x38C, 0x60, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN	IOMUX_PAD(0x38C, 0x60, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5	IOMUX_PAD(0x38C, 0x60, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY	IOMUX_PAD(0x38C, 0x60, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1	IOMUX_PAD(0x390, 0x64, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__GPIO4_22		IOMUX_PAD(0x390, 0x64, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__CSPI_MOSI		IOMUX_PAD(0x390, 0x64, 2, 0x788, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1	IOMUX_PAD(0x390, 0x64, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL	IOMUX_PAD(0x390, 0x64, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6	IOMUX_PAD(0x390, 0x64, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID	IOMUX_PAD(0x390, 0x64, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2	IOMUX_PAD(0x394, 0x68, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__GPIO4_23		IOMUX_PAD(0x394, 0x68, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__CSPI_MISO		IOMUX_PAD(0x394, 0x68, 2, 0x784, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2	IOMUX_PAD(0x394, 0x68, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE	IOMUX_PAD(0x394, 0x68, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7	IOMUX_PAD(0x394, 0x68, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE	IOMUX_PAD(0x394, 0x68, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3	IOMUX_PAD(0x398, 0x6C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__GPIO4_24		IOMUX_PAD(0x398, 0x6C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__CSPI_SS0		IOMUX_PAD(0x398, 0x6C, 2, 0x78C, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3	IOMUX_PAD(0x398, 0x6C, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR	IOMUX_PAD(0x398, 0x6C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8	IOMUX_PAD(0x398, 0x6C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR	IOMUX_PAD(0x398, 0x6C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4	IOMUX_PAD(0x39C, 0x70, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__GPIO4_25		IOMUX_PAD(0x39C, 0x70, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__CSPI_SS1		IOMUX_PAD(0x39C, 0x70, 2, 0x790, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4	IOMUX_PAD(0x39C, 0x70, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB	IOMUX_PAD(0x39C, 0x70, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9	IOMUX_PAD(0x39C, 0x70, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK	IOMUX_PAD(0x39C, 0x70, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5	IOMUX_PAD(0x3A0, 0x74, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__GPIO4_26		IOMUX_PAD(0x3A0, 0x74, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__CSPI_SS2		IOMUX_PAD(0x3A0, 0x74, 2, 0x794, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5	IOMUX_PAD(0x3A0, 0x74, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS	IOMUX_PAD(0x3A0, 0x74, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10	IOMUX_PAD(0x3A0, 0x74, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0	IOMUX_PAD(0x3A0, 0x74, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6	IOMUX_PAD(0x3A4, 0x78, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__GPIO4_27		IOMUX_PAD(0x3A4, 0x78, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__CSPI_SS3		IOMUX_PAD(0x3A4, 0x78, 2, 0x798, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6	IOMUX_PAD(0x3A4, 0x78, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE	IOMUX_PAD(0x3A4, 0x78, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11	IOMUX_PAD(0x3A4, 0x78, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1	IOMUX_PAD(0x3A4, 0x78, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7	IOMUX_PAD(0x3A8, 0x7C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__GPIO4_28		IOMUX_PAD(0x3A8, 0x7C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__CSPI_RDY		IOMUX_PAD(0x3A8, 0x7C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7	IOMUX_PAD(0x3A8, 0x7C, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0	IOMUX_PAD(0x3A8, 0x7C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12	IOMUX_PAD(0x3A8, 0x7C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID	IOMUX_PAD(0x3A8, 0x7C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8	IOMUX_PAD(0x3AC, 0x80, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__GPIO4_29		IOMUX_PAD(0x3AC, 0x80, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__PWM1_PWMO		IOMUX_PAD(0x3AC, 0x80, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B	IOMUX_PAD(0x3AC, 0x80, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1	IOMUX_PAD(0x3AC, 0x80, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13	IOMUX_PAD(0x3AC, 0x80, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT8__USBPHY2_AVALID	IOMUX_PAD(0x3AC, 0x80, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9	IOMUX_PAD(0x3B0, 0x84, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__GPIO4_30		IOMUX_PAD(0x3B0, 0x84, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__PWM2_PWMO		IOMUX_PAD(0x3B0, 0x84, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B	IOMUX_PAD(0x3B0, 0x84, 3, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		IOMUX_PAD(0x3B0, 0x84, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14	IOMUX_PAD(0x3B0, 0x84, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0	IOMUX_PAD(0x3B0, 0x84, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10	IOMUX_PAD(0x3B4, 0x88, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__GPIO4_31		IOMUX_PAD(0x3B4, 0x88, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP	IOMUX_PAD(0x3B4, 0x88, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3	IOMUX_PAD(0x3B4, 0x88, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15	IOMUX_PAD(0x3B4, 0x88, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1	IOMUX_PAD(0x3B4, 0x88, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11	IOMUX_PAD(0x3B8, 0x8C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__GPIO5_5		IOMUX_PAD(0x3B8, 0x8C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT	IOMUX_PAD(0x3B8, 0x8C, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4	IOMUX_PAD(0x3B8, 0x8C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16	IOMUX_PAD(0x3B8, 0x8C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2	IOMUX_PAD(0x3B8, 0x8C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12	IOMUX_PAD(0x3BC, 0x90, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__GPIO5_6		IOMUX_PAD(0x3BC, 0x90, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK	IOMUX_PAD(0x3BC, 0x90, 2, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5	IOMUX_PAD(0x3BC, 0x90, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17	IOMUX_PAD(0x3BC, 0x90, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3	IOMUX_PAD(0x3BC, 0x90, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13	IOMUX_PAD(0x3C0, 0x94, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__GPIO5_7		IOMUX_PAD(0x3C0, 0x94, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x3C0, 0x94, 3, 0x754, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0	IOMUX_PAD(0x3C0, 0x94, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18	IOMUX_PAD(0x3C0, 0x94, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4	IOMUX_PAD(0x3C0, 0x94, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14	IOMUX_PAD(0x3C4, 0x98, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__GPIO5_8		IOMUX_PAD(0x3C4, 0x98, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC	IOMUX_PAD(0x3C4, 0x98, 3, 0x750, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1	IOMUX_PAD(0x3C4, 0x98, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19	IOMUX_PAD(0x3C4, 0x98, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5	IOMUX_PAD(0x3C4, 0x98, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15	IOMUX_PAD(0x3C8, 0x9C, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__GPIO5_9		IOMUX_PAD(0x3C8, 0x9C, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__ECSPI1_SS1		IOMUX_PAD(0x3C8, 0x9C, 2, 0x7AC, 1, 0)
+#define _MX53_PAD_DISP0_DAT15__ECSPI2_SS1		IOMUX_PAD(0x3C8, 0x9C, 3, 0x7C8, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2	IOMUX_PAD(0x3C8, 0x9C, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20	IOMUX_PAD(0x3C8, 0x9C, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6	IOMUX_PAD(0x3C8, 0x9C, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16	IOMUX_PAD(0x3CC, 0xA0, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__GPIO5_10		IOMUX_PAD(0x3CC, 0xA0, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		IOMUX_PAD(0x3CC, 0xA0, 2, 0x7C0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC	IOMUX_PAD(0x3CC, 0xA0, 3, 0x758, 1, 0)
+#define _MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0	IOMUX_PAD(0x3CC, 0xA0, 4, 0x868, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3	IOMUX_PAD(0x3CC, 0xA0, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21	IOMUX_PAD(0x3CC, 0xA0, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7	IOMUX_PAD(0x3CC, 0xA0, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17	IOMUX_PAD(0x3D0, 0xA4, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__GPIO5_11		IOMUX_PAD(0x3D0, 0xA4, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__ECSPI2_MISO		IOMUX_PAD(0x3D0, 0xA4, 2, 0x7BC, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD	IOMUX_PAD(0x3D0, 0xA4, 3, 0x74C, 1, 0)
+#define _MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1	IOMUX_PAD(0x3D0, 0xA4, 4, 0x86C, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4	IOMUX_PAD(0x3D0, 0xA4, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22	IOMUX_PAD(0x3D0, 0xA4, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18	IOMUX_PAD(0x3D4, 0xA8, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__GPIO5_12		IOMUX_PAD(0x3D4, 0xA8, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__ECSPI2_SS0		IOMUX_PAD(0x3D4, 0xA8, 2, 0x7C4, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS	IOMUX_PAD(0x3D4, 0xA8, 3, 0x75C, 1, 0)
+#define _MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x3D4, 0xA8, 4, 0x73C, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5	IOMUX_PAD(0x3D4, 0xA8, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23	IOMUX_PAD(0x3D4, 0xA8, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2	IOMUX_PAD(0x3D4, 0xA8, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19	IOMUX_PAD(0x3D8, 0xAC, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__GPIO5_13		IOMUX_PAD(0x3D8, 0xAC, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		IOMUX_PAD(0x3D8, 0xAC, 2, 0x7B8, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD	IOMUX_PAD(0x3D8, 0xAC, 3, 0x748, 1, 0)
+#define _MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC	IOMUX_PAD(0x3D8, 0xAC, 4, 0x738, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6	IOMUX_PAD(0x3D8, 0xAC, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24	IOMUX_PAD(0x3D8, 0xAC, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3	IOMUX_PAD(0x3D8, 0xAC, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20	IOMUX_PAD(0x3DC, 0xB0, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__GPIO5_14		IOMUX_PAD(0x3DC, 0xB0, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		IOMUX_PAD(0x3DC, 0xB0, 2, 0x79C, 1, 0)
+#define _MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC	IOMUX_PAD(0x3DC, 0xB0, 3, 0x740, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7	IOMUX_PAD(0x3DC, 0xB0, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25	IOMUX_PAD(0x3DC, 0xB0, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		IOMUX_PAD(0x3DC, 0xB0, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21	IOMUX_PAD(0x3E0, 0xB4, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__GPIO5_15		IOMUX_PAD(0x3E0, 0xB4, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		IOMUX_PAD(0x3E0, 0xB4, 2, 0x7A4, 1, 0)
+#define _MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD	IOMUX_PAD(0x3E0, 0xB4, 3, 0x734, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0	IOMUX_PAD(0x3E0, 0xB4, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26	IOMUX_PAD(0x3E0, 0xB4, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT21__SATA_PHY_TDO	IOMUX_PAD(0x3E0, 0xB4, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22	IOMUX_PAD(0x3E4, 0xB8, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__GPIO5_16		IOMUX_PAD(0x3E4, 0xB8, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__ECSPI1_MISO		IOMUX_PAD(0x3E4, 0xB8, 2, 0x7A0, 1, 0)
+#define _MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x3E4, 0xB8, 3, 0x744, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1	IOMUX_PAD(0x3E4, 0xB8, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27	IOMUX_PAD(0x3E4, 0xB8, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT22__SATA_PHY_TCK	IOMUX_PAD(0x3E4, 0xB8, 7, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23	IOMUX_PAD(0x3E8, 0xBC, 0, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__GPIO5_17		IOMUX_PAD(0x3E8, 0xBC, 1, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__ECSPI1_SS0		IOMUX_PAD(0x3E8, 0xBC, 2, 0x7A8, 1, 0)
+#define _MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD	IOMUX_PAD(0x3E8, 0xBC, 3, 0x730, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2	IOMUX_PAD(0x3E8, 0xBC, 5, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28	IOMUX_PAD(0x3E8, 0xBC, 6, 0x0, 0, 0)
+#define _MX53_PAD_DISP0_DAT23__SATA_PHY_TMS	IOMUX_PAD(0x3E8, 0xBC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK	IOMUX_PAD(0x3EC, 0xC0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__GPIO5_18		IOMUX_PAD(0x3EC, 0xC0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0	IOMUX_PAD(0x3EC, 0xC0, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29	IOMUX_PAD(0x3EC, 0xC0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		IOMUX_PAD(0x3F0, 0xC4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__GPIO5_19		IOMUX_PAD(0x3F0, 0xC4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		IOMUX_PAD(0x3F0, 0xC4, 2, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1	IOMUX_PAD(0x3F0, 0xC4, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30	IOMUX_PAD(0x3F0, 0xC4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_MCLK__TPIU_TRCTL		IOMUX_PAD(0x3F0, 0xC4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN	IOMUX_PAD(0x3F4, 0xC8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__GPIO5_20		IOMUX_PAD(0x3F4, 0xC8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2	IOMUX_PAD(0x3F4, 0xC8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31	IOMUX_PAD(0x3F4, 0xC8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		IOMUX_PAD(0x3F4, 0xC8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC	IOMUX_PAD(0x3F8, 0xCC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__GPIO5_21		IOMUX_PAD(0x3F8, 0xCC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3	IOMUX_PAD(0x3F8, 0xCC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32	IOMUX_PAD(0x3F8, 0xCC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		IOMUX_PAD(0x3F8, 0xCC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		IOMUX_PAD(0x3FC, 0xD0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__GPIO5_22		IOMUX_PAD(0x3FC, 0xD0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__KPP_COL_5		IOMUX_PAD(0x3FC, 0xD0, 2, 0x840, 1, 0)
+#define _MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		IOMUX_PAD(0x3FC, 0xD0, 3, 0x79C, 2, 0)
+#define _MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP	IOMUX_PAD(0x3FC, 0xD0, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC	IOMUX_PAD(0x3FC, 0xD0, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33	IOMUX_PAD(0x3FC, 0xD0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		IOMUX_PAD(0x3FC, 0xD0, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		IOMUX_PAD(0x400, 0xD4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__GPIO5_23		IOMUX_PAD(0x400, 0xD4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__KPP_ROW_5		IOMUX_PAD(0x400, 0xD4, 2, 0x84C, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		IOMUX_PAD(0x400, 0xD4, 3, 0x7A4, 2, 0)
+#define _MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT	IOMUX_PAD(0x400, 0xD4, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD	IOMUX_PAD(0x400, 0xD4, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34	IOMUX_PAD(0x400, 0xD4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		IOMUX_PAD(0x400, 0xD4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		IOMUX_PAD(0x404, 0xD8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__GPIO5_24		IOMUX_PAD(0x404, 0xD8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__KPP_COL_6		IOMUX_PAD(0x404, 0xD8, 2, 0x844, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__ECSPI1_MISO		IOMUX_PAD(0x404, 0xD8, 3, 0x7A0, 2, 0)
+#define _MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK	IOMUX_PAD(0x404, 0xD8, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS	IOMUX_PAD(0x404, 0xD8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35	IOMUX_PAD(0x404, 0xD8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		IOMUX_PAD(0x404, 0xD8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		IOMUX_PAD(0x408, 0xDC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__GPIO5_25		IOMUX_PAD(0x408, 0xDC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__KPP_ROW_6		IOMUX_PAD(0x408, 0xDC, 2, 0x850, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__ECSPI1_SS0		IOMUX_PAD(0x408, 0xDC, 3, 0x7A8, 2, 0)
+#define _MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR	IOMUX_PAD(0x408, 0xDC, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD	IOMUX_PAD(0x408, 0xDC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36	IOMUX_PAD(0x408, 0xDC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		IOMUX_PAD(0x408, 0xDC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		IOMUX_PAD(0x40C, 0xE0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__GPIO5_26		IOMUX_PAD(0x40C, 0xE0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__KPP_COL_7		IOMUX_PAD(0x40C, 0xE0, 2, 0x848, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		IOMUX_PAD(0x40C, 0xE0, 3, 0x7B8, 1, 0)
+#define _MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC	IOMUX_PAD(0x40C, 0xE0, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__I2C1_SDA		IOMUX_PAD(0x40C, 0xE0, 5 | IOMUX_CONFIG_SION, 0x818, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37	IOMUX_PAD(0x40C, 0xE0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		IOMUX_PAD(0x40C, 0xE0, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		IOMUX_PAD(0x410, 0xE4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__GPIO5_27		IOMUX_PAD(0x410, 0xE4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__KPP_ROW_7		IOMUX_PAD(0x410, 0xE4, 2, 0x854, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		IOMUX_PAD(0x410, 0xE4, 3, 0x7C0, 1, 0)
+#define _MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR	IOMUX_PAD(0x410, 0xE4, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__I2C1_SCL		IOMUX_PAD(0x410, 0xE4, 5 | IOMUX_CONFIG_SION, 0x814, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38	IOMUX_PAD(0x410, 0xE4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		IOMUX_PAD(0x410, 0xE4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		IOMUX_PAD(0x414, 0xE8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__GPIO5_28		IOMUX_PAD(0x414, 0xE8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__UART1_TXD_MUX	IOMUX_PAD(0x414, 0xE8, 2, 0x878, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__ECSPI2_MISO		IOMUX_PAD(0x414, 0xE8, 3, 0x7BC, 1, 0)
+#define _MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC	IOMUX_PAD(0x414, 0xE8, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4	IOMUX_PAD(0x414, 0xE8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39	IOMUX_PAD(0x414, 0xE8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		IOMUX_PAD(0x414, 0xE8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		IOMUX_PAD(0x418, 0xEC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__GPIO5_29		IOMUX_PAD(0x418, 0xEC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__UART1_RXD_MUX	IOMUX_PAD(0x418, 0xEC, 2, 0x878, 1, 0)
+#define _MX53_PAD_CSI0_DAT11__ECSPI2_SS0		IOMUX_PAD(0x418, 0xEC, 3, 0x7C4, 1, 0)
+#define _MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS	IOMUX_PAD(0x418, 0xEC, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5	IOMUX_PAD(0x418, 0xEC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40	IOMUX_PAD(0x418, 0xEC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		IOMUX_PAD(0x418, 0xEC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		IOMUX_PAD(0x41C, 0xF0, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__GPIO5_30		IOMUX_PAD(0x41C, 0xF0, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__UART4_TXD_MUX	IOMUX_PAD(0x41C, 0xF0, 2, 0x890, 2, 0)
+#define _MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0	IOMUX_PAD(0x41C, 0xF0, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6	IOMUX_PAD(0x41C, 0xF0, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41	IOMUX_PAD(0x41C, 0xF0, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		IOMUX_PAD(0x41C, 0xF0, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		IOMUX_PAD(0x420, 0xF4, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__GPIO5_31		IOMUX_PAD(0x420, 0xF4, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__UART4_RXD_MUX	IOMUX_PAD(0x420, 0xF4, 2, 0x890, 3, 0)
+#define _MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1	IOMUX_PAD(0x420, 0xF4, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7	IOMUX_PAD(0x420, 0xF4, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42	IOMUX_PAD(0x420, 0xF4, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		IOMUX_PAD(0x420, 0xF4, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		IOMUX_PAD(0x424, 0xF8, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__GPIO6_0		IOMUX_PAD(0x424, 0xF8, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__UART5_TXD_MUX	IOMUX_PAD(0x424, 0xF8, 2, 0x898, 2, 0)
+#define _MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2	IOMUX_PAD(0x424, 0xF8, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8	IOMUX_PAD(0x424, 0xF8, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43	IOMUX_PAD(0x424, 0xF8, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		IOMUX_PAD(0x424, 0xF8, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		IOMUX_PAD(0x428, 0xFC, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__GPIO6_1		IOMUX_PAD(0x428, 0xFC, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__UART5_RXD_MUX	IOMUX_PAD(0x428, 0xFC, 2, 0x898, 3, 0)
+#define _MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3	IOMUX_PAD(0x428, 0xFC, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9	IOMUX_PAD(0x428, 0xFC, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44	IOMUX_PAD(0x428, 0xFC, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		IOMUX_PAD(0x428, 0xFC, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		IOMUX_PAD(0x42C, 0x100, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__GPIO6_2		IOMUX_PAD(0x42C, 0x100, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__UART4_RTS		IOMUX_PAD(0x42C, 0x100, 2, 0x88C, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4	IOMUX_PAD(0x42C, 0x100, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10	IOMUX_PAD(0x42C, 0x100, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45	IOMUX_PAD(0x42C, 0x100, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		IOMUX_PAD(0x42C, 0x100, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		IOMUX_PAD(0x430, 0x104, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__GPIO6_3		IOMUX_PAD(0x430, 0x104, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__UART4_CTS		IOMUX_PAD(0x430, 0x104, 2, 0x88C, 1, 0)
+#define _MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5	IOMUX_PAD(0x430, 0x104, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11	IOMUX_PAD(0x430, 0x104, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46	IOMUX_PAD(0x430, 0x104, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		IOMUX_PAD(0x430, 0x104, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		IOMUX_PAD(0x434, 0x108, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__GPIO6_4		IOMUX_PAD(0x434, 0x108, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__UART5_RTS		IOMUX_PAD(0x434, 0x108, 2, 0x894, 2, 0)
+#define _MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6	IOMUX_PAD(0x434, 0x108, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12	IOMUX_PAD(0x434, 0x108, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47	IOMUX_PAD(0x434, 0x108, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		IOMUX_PAD(0x434, 0x108, 7, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		IOMUX_PAD(0x438, 0x10C, 0, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__GPIO6_5		IOMUX_PAD(0x438, 0x10C, 1, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__UART5_CTS		IOMUX_PAD(0x438, 0x10C, 2, 0x894, 3, 0)
+#define _MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7	IOMUX_PAD(0x438, 0x10C, 4, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13	IOMUX_PAD(0x438, 0x10C, 5, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48	IOMUX_PAD(0x438, 0x10C, 6, 0x0, 0, 0)
+#define _MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK	IOMUX_PAD(0x438, 0x10C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__EMI_WEIM_A_25		IOMUX_PAD(0x458, 0x110, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__GPIO5_2			IOMUX_PAD(0x458, 0x110, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__ECSPI2_RDY		IOMUX_PAD(0x458, 0x110, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__IPU_DI1_PIN12		IOMUX_PAD(0x458, 0x110, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__CSPI_SS1			IOMUX_PAD(0x458, 0x110, 4, 0x790, 1, 0)
+#define _MX53_PAD_EIM_A25__IPU_DI0_D1_CS		IOMUX_PAD(0x458, 0x110, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A25__USBPHY1_BISTOK		IOMUX_PAD(0x458, 0x110, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		IOMUX_PAD(0x45C, 0x114, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__GPIO2_30			IOMUX_PAD(0x45C, 0x114, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		IOMUX_PAD(0x45C, 0x114, 2, 0x76C, 0, 0)
+#define _MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		IOMUX_PAD(0x45C, 0x114, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB2__ECSPI1_SS0		IOMUX_PAD(0x45C, 0x114, 4, 0x7A8, 3, 0)
+#define _MX53_PAD_EIM_EB2__I2C2_SCL			IOMUX_PAD(0x45C, 0x114, 5 | IOMUX_CONFIG_SION, 0x81C, 1, 0)
+#define _MX53_PAD_EIM_D16__EMI_WEIM_D_16		IOMUX_PAD(0x460, 0x118, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__GPIO3_16			IOMUX_PAD(0x460, 0x118, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__IPU_DI0_PIN5		IOMUX_PAD(0x460, 0x118, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK	IOMUX_PAD(0x460, 0x118, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D16__ECSPI1_SCLK		IOMUX_PAD(0x460, 0x118, 4, 0x79C, 3, 0)
+#define _MX53_PAD_EIM_D16__I2C2_SDA			IOMUX_PAD(0x460, 0x118, 5, 0x820, 1, 0)
+#define _MX53_PAD_EIM_D17__EMI_WEIM_D_17		IOMUX_PAD(0x464, 0x11C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D17__GPIO3_17			IOMUX_PAD(0x464, 0x11C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D17__IPU_DI0_PIN6		IOMUX_PAD(0x464, 0x11C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN	IOMUX_PAD(0x464, 0x11C, 3, 0x830, 0, 0)
+#define _MX53_PAD_EIM_D17__ECSPI1_MISO		IOMUX_PAD(0x464, 0x11C, 4, 0x7A0, 3, 0)
+#define _MX53_PAD_EIM_D17__I2C3_SCL			IOMUX_PAD(0x464, 0x11C, 5, 0x824, 0, 0)
+#define _MX53_PAD_EIM_D18__EMI_WEIM_D_18		IOMUX_PAD(0x468, 0x120, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D18__GPIO3_18			IOMUX_PAD(0x468, 0x120, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D18__IPU_DI0_PIN7		IOMUX_PAD(0x468, 0x120, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO	IOMUX_PAD(0x468, 0x120, 3, 0x830, 1, 0)
+#define _MX53_PAD_EIM_D18__ECSPI1_MOSI		IOMUX_PAD(0x468, 0x120, 4, 0x7A4, 3, 0)
+#define _MX53_PAD_EIM_D18__I2C3_SDA			IOMUX_PAD(0x468, 0x120, 5, 0x828, 0, 0)
+#define _MX53_PAD_EIM_D18__IPU_DI1_D0_CS		IOMUX_PAD(0x468, 0x120, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__EMI_WEIM_D_19		IOMUX_PAD(0x46C, 0x124, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__GPIO3_19			IOMUX_PAD(0x46C, 0x124, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__IPU_DI0_PIN8		IOMUX_PAD(0x46C, 0x124, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS	IOMUX_PAD(0x46C, 0x124, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__ECSPI1_SS1		IOMUX_PAD(0x46C, 0x124, 4, 0x7AC, 2, 0)
+#define _MX53_PAD_EIM_D19__EPIT1_EPITO		IOMUX_PAD(0x46C, 0x124, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D19__UART1_CTS			IOMUX_PAD(0x46C, 0x124, 6, 0x874, 0, 0)
+#define _MX53_PAD_EIM_D19__USBOH3_USBH2_OC		IOMUX_PAD(0x46C, 0x124, 7, 0x8A4, 0, 0)
+#define _MX53_PAD_EIM_D20__EMI_WEIM_D_20		IOMUX_PAD(0x470, 0x128, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__GPIO3_20			IOMUX_PAD(0x470, 0x128, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__IPU_DI0_PIN16		IOMUX_PAD(0x470, 0x128, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		IOMUX_PAD(0x470, 0x128, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__CSPI_SS0			IOMUX_PAD(0x470, 0x128, 4, 0x78C, 1, 0)
+#define _MX53_PAD_EIM_D20__EPIT2_EPITO		IOMUX_PAD(0x470, 0x128, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D20__UART1_RTS			IOMUX_PAD(0x470, 0x128, 6, 0x874, 1, 0)
+#define _MX53_PAD_EIM_D20__USBOH3_USBH2_PWR	IOMUX_PAD(0x470, 0x128, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__EMI_WEIM_D_21		IOMUX_PAD(0x474, 0x12C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__GPIO3_21			IOMUX_PAD(0x474, 0x12C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__IPU_DI0_PIN17		IOMUX_PAD(0x474, 0x12C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK	IOMUX_PAD(0x474, 0x12C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D21__CSPI_SCLK			IOMUX_PAD(0x474, 0x12C, 4, 0x780, 1, 0)
+#define _MX53_PAD_EIM_D21__I2C1_SCL			IOMUX_PAD(0x474, 0x12C, 5, 0x814, 1, 0)
+#define _MX53_PAD_EIM_D21__USBOH3_USBOTG_OC	IOMUX_PAD(0x474, 0x12C, 6, 0x89C, 1, 0)
+#define _MX53_PAD_EIM_D22__EMI_WEIM_D_22		IOMUX_PAD(0x478, 0x130, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D22__GPIO3_22			IOMUX_PAD(0x478, 0x130, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D22__IPU_DI0_PIN1		IOMUX_PAD(0x478, 0x130, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN	IOMUX_PAD(0x478, 0x130, 3, 0x82C, 0, 0)
+#define _MX53_PAD_EIM_D22__CSPI_MISO			IOMUX_PAD(0x478, 0x130, 4, 0x784, 1, 0)
+#define _MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR	IOMUX_PAD(0x478, 0x130, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__EMI_WEIM_D_23		IOMUX_PAD(0x47C, 0x134, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__GPIO3_23			IOMUX_PAD(0x47C, 0x134, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__UART3_CTS			IOMUX_PAD(0x47C, 0x134, 2, 0x884, 0, 0)
+#define _MX53_PAD_EIM_D23__UART1_DCD		IOMUX_PAD(0x47C, 0x134, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_DI0_D0_CS		IOMUX_PAD(0x47C, 0x134, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_DI1_PIN2		IOMUX_PAD(0x47C, 0x134, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		IOMUX_PAD(0x47C, 0x134, 6, 0x834, 0, 0)
+#define _MX53_PAD_EIM_D23__IPU_DI1_PIN14		IOMUX_PAD(0x47C, 0x134, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		IOMUX_PAD(0x480, 0x138, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__GPIO2_31			IOMUX_PAD(0x480, 0x138, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__UART3_RTS			IOMUX_PAD(0x480, 0x138, 2, 0x884, 1, 0)
+#define _MX53_PAD_EIM_EB3__UART1_RI			IOMUX_PAD(0x480, 0x138, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN3		IOMUX_PAD(0x480, 0x138, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		IOMUX_PAD(0x480, 0x138, 6, 0x838, 0, 0)
+#define _MX53_PAD_EIM_EB3__IPU_DI1_PIN16		IOMUX_PAD(0x480, 0x138, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__EMI_WEIM_D_24		IOMUX_PAD(0x484, 0x13C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__GPIO3_24			IOMUX_PAD(0x484, 0x13C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__UART3_TXD_MUX		IOMUX_PAD(0x484, 0x13C, 2, 0x888, 0, 0)
+#define _MX53_PAD_EIM_D24__ECSPI1_SS2		IOMUX_PAD(0x484, 0x13C, 3, 0x7B0, 1, 0)
+#define _MX53_PAD_EIM_D24__CSPI_SS2			IOMUX_PAD(0x484, 0x13C, 4, 0x794, 1, 0)
+#define _MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS	IOMUX_PAD(0x484, 0x13C, 5, 0x754, 1, 0)
+#define _MX53_PAD_EIM_D24__ECSPI2_SS2		IOMUX_PAD(0x484, 0x13C, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D24__UART1_DTR		IOMUX_PAD(0x484, 0x13C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__EMI_WEIM_D_25		IOMUX_PAD(0x488, 0x140, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__GPIO3_25			IOMUX_PAD(0x488, 0x140, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__UART3_RXD_MUX		IOMUX_PAD(0x488, 0x140, 2, 0x888, 1, 0)
+#define _MX53_PAD_EIM_D25__ECSPI1_SS3		IOMUX_PAD(0x488, 0x140, 3, 0x7B4, 1, 0)
+#define _MX53_PAD_EIM_D25__CSPI_SS3			IOMUX_PAD(0x488, 0x140, 4, 0x798, 1, 0)
+#define _MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		IOMUX_PAD(0x488, 0x140, 5, 0x750, 1, 0)
+#define _MX53_PAD_EIM_D25__ECSPI2_SS3		IOMUX_PAD(0x488, 0x140, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D25__UART1_DSR		IOMUX_PAD(0x488, 0x140, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__EMI_WEIM_D_26		IOMUX_PAD(0x48C, 0x144, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__GPIO3_26			IOMUX_PAD(0x48C, 0x144, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__UART2_TXD_MUX		IOMUX_PAD(0x48C, 0x144, 2, 0x880, 0, 0)
+#define _MX53_PAD_EIM_D26__FIRI_RXD			IOMUX_PAD(0x48C, 0x144, 3, 0x80C, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_CSI0_D_1		IOMUX_PAD(0x48C, 0x144, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_DI1_PIN11		IOMUX_PAD(0x48C, 0x144, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_SISG_2		IOMUX_PAD(0x48C, 0x144, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		IOMUX_PAD(0x48C, 0x144, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__EMI_WEIM_D_27		IOMUX_PAD(0x490, 0x148, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__GPIO3_27			IOMUX_PAD(0x490, 0x148, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__UART2_RXD_MUX		IOMUX_PAD(0x490, 0x148, 2, 0x880, 1, 0)
+#define _MX53_PAD_EIM_D27__FIRI_TXD			IOMUX_PAD(0x490, 0x148, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_CSI0_D_0		IOMUX_PAD(0x490, 0x148, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_DI1_PIN13		IOMUX_PAD(0x490, 0x148, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_SISG_3		IOMUX_PAD(0x490, 0x148, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		IOMUX_PAD(0x490, 0x148, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__EMI_WEIM_D_28		IOMUX_PAD(0x494, 0x14C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__GPIO3_28			IOMUX_PAD(0x494, 0x14C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__UART2_CTS			IOMUX_PAD(0x494, 0x14C, 2, 0x87C, 0, 0)
+#define _MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO	IOMUX_PAD(0x494, 0x14C, 3, 0x82C, 1, 0)
+#define _MX53_PAD_EIM_D28__CSPI_MOSI			IOMUX_PAD(0x494, 0x14C, 4, 0x788, 1, 0)
+#define _MX53_PAD_EIM_D28__I2C1_SDA			IOMUX_PAD(0x494, 0x14C, 5, 0x818, 1, 0)
+#define _MX53_PAD_EIM_D28__IPU_EXT_TRIG		IOMUX_PAD(0x494, 0x14C, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D28__IPU_DI0_PIN13		IOMUX_PAD(0x494, 0x14C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__EMI_WEIM_D_29		IOMUX_PAD(0x498, 0x150, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__GPIO3_29			IOMUX_PAD(0x498, 0x150, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__UART2_RTS			IOMUX_PAD(0x498, 0x150, 2, 0x87C, 1, 0)
+#define _MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS	IOMUX_PAD(0x498, 0x150, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__CSPI_SS0			IOMUX_PAD(0x498, 0x150, 4, 0x78C, 2, 0)
+#define _MX53_PAD_EIM_D29__IPU_DI1_PIN15		IOMUX_PAD(0x498, 0x150, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		IOMUX_PAD(0x498, 0x150, 6, 0x83C, 0, 0)
+#define _MX53_PAD_EIM_D29__IPU_DI0_PIN14		IOMUX_PAD(0x498, 0x150, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__EMI_WEIM_D_30		IOMUX_PAD(0x49C, 0x154, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__GPIO3_30			IOMUX_PAD(0x49C, 0x154, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__UART3_CTS			IOMUX_PAD(0x49C, 0x154, 2, 0x884, 2, 0)
+#define _MX53_PAD_EIM_D30__IPU_CSI0_D_3		IOMUX_PAD(0x49C, 0x154, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__IPU_DI0_PIN11		IOMUX_PAD(0x49C, 0x154, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		IOMUX_PAD(0x49C, 0x154, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D30__USBOH3_USBH1_OC		IOMUX_PAD(0x49C, 0x154, 6, 0x8A0, 0, 0)
+#define _MX53_PAD_EIM_D30__USBOH3_USBH2_OC		IOMUX_PAD(0x49C, 0x154, 7, 0x8A4, 1, 0)
+#define _MX53_PAD_EIM_D31__EMI_WEIM_D_31		IOMUX_PAD(0x4A0, 0x158, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__GPIO3_31			IOMUX_PAD(0x4A0, 0x158, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__UART3_RTS			IOMUX_PAD(0x4A0, 0x158, 2, 0x884, 3, 0)
+#define _MX53_PAD_EIM_D31__IPU_CSI0_D_2		IOMUX_PAD(0x4A0, 0x158, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__IPU_DI0_PIN12		IOMUX_PAD(0x4A0, 0x158, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		IOMUX_PAD(0x4A0, 0x158, 5, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__USBOH3_USBH1_PWR	IOMUX_PAD(0x4A0, 0x158, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_D31__USBOH3_USBH2_PWR	IOMUX_PAD(0x4A0, 0x158, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__EMI_WEIM_A_24		IOMUX_PAD(0x4A8, 0x15C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__GPIO5_4			IOMUX_PAD(0x4A8, 0x15C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		IOMUX_PAD(0x4A8, 0x15C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__IPU_CSI1_D_19		IOMUX_PAD(0x4A8, 0x15C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__IPU_SISG_2		IOMUX_PAD(0x4A8, 0x15C, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A24__USBPHY2_BVALID		IOMUX_PAD(0x4A8, 0x15C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__EMI_WEIM_A_23		IOMUX_PAD(0x4AC, 0x160, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__GPIO6_6			IOMUX_PAD(0x4AC, 0x160, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		IOMUX_PAD(0x4AC, 0x160, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__IPU_CSI1_D_18		IOMUX_PAD(0x4AC, 0x160, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__IPU_SISG_3		IOMUX_PAD(0x4AC, 0x160, 6, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A23__USBPHY2_ENDSESSION	IOMUX_PAD(0x4AC, 0x160, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__EMI_WEIM_A_22		IOMUX_PAD(0x4B0, 0x164, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__GPIO2_16			IOMUX_PAD(0x4B0, 0x164, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		IOMUX_PAD(0x4B0, 0x164, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__IPU_CSI1_D_17		IOMUX_PAD(0x4B0, 0x164, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A22__SRC_BT_CFG1_7		IOMUX_PAD(0x4B0, 0x164, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__EMI_WEIM_A_21		IOMUX_PAD(0x4B4, 0x168, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__GPIO2_17			IOMUX_PAD(0x4B4, 0x168, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		IOMUX_PAD(0x4B4, 0x168, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__IPU_CSI1_D_16		IOMUX_PAD(0x4B4, 0x168, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A21__SRC_BT_CFG1_6		IOMUX_PAD(0x4B4, 0x168, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__EMI_WEIM_A_20		IOMUX_PAD(0x4B8, 0x16C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__GPIO2_18			IOMUX_PAD(0x4B8, 0x16C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		IOMUX_PAD(0x4B8, 0x16C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__IPU_CSI1_D_15		IOMUX_PAD(0x4B8, 0x16C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A20__SRC_BT_CFG1_5		IOMUX_PAD(0x4B8, 0x16C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__EMI_WEIM_A_19		IOMUX_PAD(0x4BC, 0x170, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__GPIO2_19			IOMUX_PAD(0x4BC, 0x170, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		IOMUX_PAD(0x4BC, 0x170, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__IPU_CSI1_D_14		IOMUX_PAD(0x4BC, 0x170, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A19__SRC_BT_CFG1_4		IOMUX_PAD(0x4BC, 0x170, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__EMI_WEIM_A_18		IOMUX_PAD(0x4C0, 0x174, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__GPIO2_20			IOMUX_PAD(0x4C0, 0x174, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		IOMUX_PAD(0x4C0, 0x174, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__IPU_CSI1_D_13		IOMUX_PAD(0x4C0, 0x174, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A18__SRC_BT_CFG1_3		IOMUX_PAD(0x4C0, 0x174, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__EMI_WEIM_A_17		IOMUX_PAD(0x4C4, 0x178, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__GPIO2_21			IOMUX_PAD(0x4C4, 0x178, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		IOMUX_PAD(0x4C4, 0x178, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__IPU_CSI1_D_12		IOMUX_PAD(0x4C4, 0x178, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A17__SRC_BT_CFG1_2		IOMUX_PAD(0x4C4, 0x178, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__EMI_WEIM_A_16		IOMUX_PAD(0x4C8, 0x17C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__GPIO2_22			IOMUX_PAD(0x4C8, 0x17C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		IOMUX_PAD(0x4C8, 0x17C, 2, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		IOMUX_PAD(0x4C8, 0x17C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_A16__SRC_BT_CFG1_1		IOMUX_PAD(0x4C8, 0x17C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		IOMUX_PAD(0x4CC, 0x180, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS0__GPIO2_23			IOMUX_PAD(0x4CC, 0x180, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS0__ECSPI2_SCLK		IOMUX_PAD(0x4CC, 0x180, 2, 0x7B8, 2, 0)
+#define _MX53_PAD_EIM_CS0__IPU_DI1_PIN5		IOMUX_PAD(0x4CC, 0x180, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		IOMUX_PAD(0x4D0, 0x184, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS1__GPIO2_24			IOMUX_PAD(0x4D0, 0x184, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_CS1__ECSPI2_MOSI		IOMUX_PAD(0x4D0, 0x184, 2, 0x7C0, 2, 0)
+#define _MX53_PAD_EIM_CS1__IPU_DI1_PIN6		IOMUX_PAD(0x4D0, 0x184, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__EMI_WEIM_OE		IOMUX_PAD(0x4D4, 0x188, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__GPIO2_25			IOMUX_PAD(0x4D4, 0x188, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__ECSPI2_MISO		IOMUX_PAD(0x4D4, 0x188, 2, 0x7BC, 2, 0)
+#define _MX53_PAD_EIM_OE__IPU_DI1_PIN7		IOMUX_PAD(0x4D4, 0x188, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_OE__USBPHY2_IDDIG		IOMUX_PAD(0x4D4, 0x188, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__EMI_WEIM_RW		IOMUX_PAD(0x4D8, 0x18C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__GPIO2_26			IOMUX_PAD(0x4D8, 0x18C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__ECSPI2_SS0			IOMUX_PAD(0x4D8, 0x18C, 2, 0x7C4, 2, 0)
+#define _MX53_PAD_EIM_RW__IPU_DI1_PIN8		IOMUX_PAD(0x4D8, 0x18C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT	IOMUX_PAD(0x4D8, 0x18C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__EMI_WEIM_LBA		IOMUX_PAD(0x4DC, 0x190, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__GPIO2_27			IOMUX_PAD(0x4DC, 0x190, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__ECSPI2_SS1		IOMUX_PAD(0x4DC, 0x190, 2, 0x7C8, 1, 0)
+#define _MX53_PAD_EIM_LBA__IPU_DI1_PIN17		IOMUX_PAD(0x4DC, 0x190, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		IOMUX_PAD(0x4DC, 0x190, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		IOMUX_PAD(0x4E4, 0x194, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__GPIO2_28			IOMUX_PAD(0x4E4, 0x194, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		IOMUX_PAD(0x4E4, 0x194, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__IPU_CSI1_D_11		IOMUX_PAD(0x4E4, 0x194, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB0__GPC_PMIC_RDY		IOMUX_PAD(0x4E4, 0x194, 5, 0x810, 0, 0)
+#define _MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		IOMUX_PAD(0x4E4, 0x194, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		IOMUX_PAD(0x4E8, 0x198, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__GPIO2_29			IOMUX_PAD(0x4E8, 0x198, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		IOMUX_PAD(0x4E8, 0x198, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__IPU_CSI1_D_10		IOMUX_PAD(0x4E8, 0x198, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		IOMUX_PAD(0x4E8, 0x198, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0	IOMUX_PAD(0x4EC, 0x19C, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__GPIO3_0			IOMUX_PAD(0x4EC, 0x19C, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		IOMUX_PAD(0x4EC, 0x19C, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__IPU_CSI1_D_9		IOMUX_PAD(0x4EC, 0x19C, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		IOMUX_PAD(0x4EC, 0x19C, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1	IOMUX_PAD(0x4F0, 0x1A0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__GPIO3_1			IOMUX_PAD(0x4F0, 0x1A0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		IOMUX_PAD(0x4F0, 0x1A0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__IPU_CSI1_D_8		IOMUX_PAD(0x4F0, 0x1A0, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		IOMUX_PAD(0x4F0, 0x1A0, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2	IOMUX_PAD(0x4F4, 0x1A4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__GPIO3_2			IOMUX_PAD(0x4F4, 0x1A4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		IOMUX_PAD(0x4F4, 0x1A4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__IPU_CSI1_D_7		IOMUX_PAD(0x4F4, 0x1A4, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		IOMUX_PAD(0x4F4, 0x1A4, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3	IOMUX_PAD(0x4F8, 0x1A8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__GPIO3_3			IOMUX_PAD(0x4F8, 0x1A8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		IOMUX_PAD(0x4F8, 0x1A8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__IPU_CSI1_D_6		IOMUX_PAD(0x4F8, 0x1A8, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		IOMUX_PAD(0x4F8, 0x1A8, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4	IOMUX_PAD(0x4FC, 0x1AC, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__GPIO3_4			IOMUX_PAD(0x4FC, 0x1AC, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		IOMUX_PAD(0x4FC, 0x1AC, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__IPU_CSI1_D_5		IOMUX_PAD(0x4FC, 0x1AC, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		IOMUX_PAD(0x4FC, 0x1AC, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5	IOMUX_PAD(0x500, 0x1B0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__GPIO3_5			IOMUX_PAD(0x500, 0x1B0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		IOMUX_PAD(0x500, 0x1B0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__IPU_CSI1_D_4		IOMUX_PAD(0x500, 0x1B0, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		IOMUX_PAD(0x500, 0x1B0, 17, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6	IOMUX_PAD(0x504, 0x1B4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__GPIO3_6			IOMUX_PAD(0x504, 0x1B4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		IOMUX_PAD(0x504, 0x1B4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__IPU_CSI1_D_3		IOMUX_PAD(0x504, 0x1B4, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		IOMUX_PAD(0x504, 0x1B4, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7	IOMUX_PAD(0x508, 0x1B8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__GPIO3_7			IOMUX_PAD(0x508, 0x1B8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		IOMUX_PAD(0x508, 0x1B8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__IPU_CSI1_D_2		IOMUX_PAD(0x508, 0x1B8, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		IOMUX_PAD(0x508, 0x1B8, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8	IOMUX_PAD(0x50C, 0x1BC, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__GPIO3_8			IOMUX_PAD(0x50C, 0x1BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		IOMUX_PAD(0x50C, 0x1BC, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__IPU_CSI1_D_1		IOMUX_PAD(0x50C, 0x1BC, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		IOMUX_PAD(0x50C, 0x1BC, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9	IOMUX_PAD(0x510, 0x1C0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__GPIO3_9			IOMUX_PAD(0x510, 0x1C0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		IOMUX_PAD(0x510, 0x1C0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__IPU_CSI1_D_0		IOMUX_PAD(0x510, 0x1C0, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		IOMUX_PAD(0x510, 0x1C0, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10	IOMUX_PAD(0x514, 0x1C4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__GPIO3_10			IOMUX_PAD(0x514, 0x1C4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__IPU_DI1_PIN15		IOMUX_PAD(0x514, 0x1C4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN	IOMUX_PAD(0x514, 0x1C4, 4, 0x834, 1, 0)
+#define _MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		IOMUX_PAD(0x514, 0x1C4, 7, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11	IOMUX_PAD(0x518, 0x1C8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__GPIO3_11			IOMUX_PAD(0x518, 0x1C8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__IPU_DI1_PIN2		IOMUX_PAD(0x518, 0x1C8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		IOMUX_PAD(0x518, 0x1C8, 4, 0x838, 1, 0)
+#define _MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12	IOMUX_PAD(0x51C, 0x1CC, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA12__GPIO3_12			IOMUX_PAD(0x51C, 0x1CC, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA12__IPU_DI1_PIN3		IOMUX_PAD(0x51C, 0x1CC, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		IOMUX_PAD(0x51C, 0x1CC, 4, 0x83C, 1, 0)
+#define _MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13	IOMUX_PAD(0x520, 0x1D0, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA13__GPIO3_13			IOMUX_PAD(0x520, 0x1D0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		IOMUX_PAD(0x520, 0x1D0, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		IOMUX_PAD(0x520, 0x1D0, 4, 0x76C, 1, 0)
+#define _MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14	IOMUX_PAD(0x524, 0x1D4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA14__GPIO3_14			IOMUX_PAD(0x524, 0x1D4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		IOMUX_PAD(0x524, 0x1D4, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		IOMUX_PAD(0x524, 0x1D4, 4, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15	IOMUX_PAD(0x528, 0x1D8, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__GPIO3_15			IOMUX_PAD(0x528, 0x1D8, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN1		IOMUX_PAD(0x528, 0x1D8, 3, 0x0, 0, 0)
+#define _MX53_PAD_EIM_DA15__IPU_DI1_PIN4		IOMUX_PAD(0x528, 0x1D8, 4, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B	IOMUX_PAD(0x52C, 0x1DC, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WE_B__GPIO6_12		IOMUX_PAD(0x52C, 0x1DC, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B	IOMUX_PAD(0x530, 0x1E0, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RE_B__GPIO6_13		IOMUX_PAD(0x530, 0x1E0, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		IOMUX_PAD(0x534, 0x1E4, 0, 0x0, 0, 0)
+#define _MX53_PAD_EIM_WAIT__GPIO5_0			IOMUX_PAD(0x534, 0x1E4, 1, 0x0, 0, 0)
+#define _MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B	IOMUX_PAD(0x534, 0x1E4, 2, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX3_P__GPIO6_22		IOMUX_PAD(NON_PAD_I, 0x1EC, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3	IOMUX_PAD(NON_PAD_I, 0x1EC, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX2_P__GPIO6_24		IOMUX_PAD(NON_PAD_I, 0x1F0, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2	IOMUX_PAD(NON_PAD_I, 0x1F0, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_CLK_P__GPIO6_26		IOMUX_PAD(NON_PAD_I, 0x1F4, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK	IOMUX_PAD(NON_PAD_I, 0x1F4, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX1_P__GPIO6_28		IOMUX_PAD(NON_PAD_I, 0x1F8, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1	IOMUX_PAD(NON_PAD_I, 0x1F8, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX0_P__GPIO6_30		IOMUX_PAD(NON_PAD_I, 0x1FC, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0	IOMUX_PAD(NON_PAD_I, 0x1FC, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX3_P__GPIO7_22		IOMUX_PAD(NON_PAD_I, 0x200, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3	IOMUX_PAD(NON_PAD_I, 0x200, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_CLK_P__GPIO7_24		IOMUX_PAD(NON_PAD_I, 0x204, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK	IOMUX_PAD(NON_PAD_I, 0x204, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX2_P__GPIO7_26		IOMUX_PAD(NON_PAD_I, 0x208, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2	IOMUX_PAD(NON_PAD_I, 0x208, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX1_P__GPIO7_28		IOMUX_PAD(NON_PAD_I, 0x20C, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1	IOMUX_PAD(NON_PAD_I, 0x20C, 1, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX0_P__GPIO7_30		IOMUX_PAD(NON_PAD_I, 0x210, 0, 0x0, 0, 0)
+#define _MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0	IOMUX_PAD(NON_PAD_I, 0x210, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_10__GPIO4_0			IOMUX_PAD(0x540, 0x214, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_10__OSC32k_32K_OUT		IOMUX_PAD(0x540, 0x214, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_11__GPIO4_1			IOMUX_PAD(0x544, 0x218, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_12__GPIO4_2			IOMUX_PAD(0x548, 0x21C, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_13__GPIO4_3			IOMUX_PAD(0x54C, 0x220, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_14__GPIO4_4			IOMUX_PAD(0x550, 0x224, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		IOMUX_PAD(0x5A0, 0x228, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CLE__GPIO6_7			IOMUX_PAD(0x5A0, 0x228, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0	IOMUX_PAD(0x5A0, 0x228, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		IOMUX_PAD(0x5A4, 0x22C, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_ALE__GPIO6_8		IOMUX_PAD(0x5A4, 0x22C, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1	IOMUX_PAD(0x5A4, 0x22C, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B	IOMUX_PAD(0x5A8, 0x230, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WP_B__GPIO6_9		IOMUX_PAD(0x5A8, 0x230, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2	IOMUX_PAD(0x5A8, 0x230, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0	IOMUX_PAD(0x5AC, 0x234, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RB0__GPIO6_10		IOMUX_PAD(0x5AC, 0x234, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3	IOMUX_PAD(0x5AC, 0x234, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0	IOMUX_PAD(0x5B0, 0x238, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS0__GPIO6_11		IOMUX_PAD(0x5B0, 0x238, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4	IOMUX_PAD(0x5B0, 0x238, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1	IOMUX_PAD(0x5B4, 0x23C, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS1__GPIO6_14		IOMUX_PAD(0x5B4, 0x23C, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS1__MLB_MLBCLK		IOMUX_PAD(0x5B4, 0x23C, 6, 0x858, 0, 0)
+#define _MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5	IOMUX_PAD(0x5B4, 0x23C, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2	IOMUX_PAD(0x5B8, 0x240, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__GPIO6_15		IOMUX_PAD(0x5B8, 0x240, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__IPU_SISG_0		IOMUX_PAD(0x5B8, 0x240, 2, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__ESAI1_TX0		IOMUX_PAD(0x5B8, 0x240, 3, 0x7E4, 0, 0)
+#define _MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		IOMUX_PAD(0x5B8, 0x240, 4, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		IOMUX_PAD(0x5B8, 0x240, 5, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS2__MLB_MLBSIG		IOMUX_PAD(0x5B8, 0x240, 6, 0x860, 0, 0)
+#define _MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6	IOMUX_PAD(0x5B8, 0x240, 7, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3	IOMUX_PAD(0x5BC, 0x244, 0, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__GPIO6_16		IOMUX_PAD(0x5BC, 0x244, 1, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__IPU_SISG_1		IOMUX_PAD(0x5BC, 0x244, 2, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__ESAI1_TX1		IOMUX_PAD(0x5BC, 0x244, 3, 0x7E8, 0, 0)
+#define _MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		IOMUX_PAD(0x5BC, 0x244, 4, 0x0, 0, 0)
+#define _MX53_PAD_NANDF_CS3__MLB_MLBDAT		IOMUX_PAD(0x5BC, 0x244, 6, 0x85C, 0, 0)
+#define _MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7	IOMUX_PAD(0x5BC, 0x244, 7, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__FEC_MDIO		IOMUX_PAD(0x5C4, 0x248, 0, 0x804, 1, 0)
+#define _MX53_PAD_FEC_MDIO__GPIO1_22			IOMUX_PAD(0x5C4, 0x248, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__ESAI1_SCKR		IOMUX_PAD(0x5C4, 0x248, 2, 0x7DC, 0, 0)
+#define _MX53_PAD_FEC_MDIO__FEC_COL			IOMUX_PAD(0x5C4, 0x248, 3, 0x800, 1, 0)
+#define _MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		IOMUX_PAD(0x5C4, 0x248, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3	IOMUX_PAD(0x5C4, 0x248, 5, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49	IOMUX_PAD(0x5C4, 0x248, 6, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		IOMUX_PAD(0x5C8, 0x24C, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__GPIO1_23		IOMUX_PAD(0x5C8, 0x24C, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__ESAI1_FSR		IOMUX_PAD(0x5C8, 0x24C, 2, 0x7CC, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4	IOMUX_PAD(0x5C8, 0x24C, 5, 0x0, 0, 0)
+#define _MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50	IOMUX_PAD(0x5C8, 0x24C, 6, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__FEC_RX_ER		IOMUX_PAD(0x5CC, 0x250, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__GPIO1_24		IOMUX_PAD(0x5CC, 0x250, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__ESAI1_HCKR		IOMUX_PAD(0x5CC, 0x250, 2, 0x7D4, 0, 0)
+#define _MX53_PAD_FEC_RX_ER__FEC_RX_CLK		IOMUX_PAD(0x5CC, 0x250, 3, 0x808, 1, 0)
+#define _MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		IOMUX_PAD(0x5CC, 0x250, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_CRS_DV__FEC_RX_DV		IOMUX_PAD(0x5D0, 0x254, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_CRS_DV__GPIO1_25		IOMUX_PAD(0x5D0, 0x254, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		IOMUX_PAD(0x5D0, 0x254, 2, 0x7E0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__FEC_RDATA_1		IOMUX_PAD(0x5D4, 0x258, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__GPIO1_26			IOMUX_PAD(0x5D4, 0x258, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__ESAI1_FST		IOMUX_PAD(0x5D4, 0x258, 2, 0x7D0, 0, 0)
+#define _MX53_PAD_FEC_RXD1__MLB_MLBSIG		IOMUX_PAD(0x5D4, 0x258, 3, 0x860, 1, 0)
+#define _MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		IOMUX_PAD(0x5D4, 0x258, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD0__FEC_RDATA_0		IOMUX_PAD(0x5D8, 0x25C, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD0__GPIO1_27			IOMUX_PAD(0x5D8, 0x25C, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_RXD0__ESAI1_HCKT		IOMUX_PAD(0x5D8, 0x25C, 2, 0x7D8, 0, 0)
+#define _MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		IOMUX_PAD(0x5D8, 0x25C, 3, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TX_EN__FEC_TX_EN		IOMUX_PAD(0x5DC, 0x260, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TX_EN__GPIO1_28		IOMUX_PAD(0x5DC, 0x260, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		IOMUX_PAD(0x5DC, 0x260, 2, 0x7F0, 0, 0)
+#define _MX53_PAD_FEC_TXD1__FEC_TDATA_1		IOMUX_PAD(0x5E0, 0x264, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD1__GPIO1_29			IOMUX_PAD(0x5E0, 0x264, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		IOMUX_PAD(0x5E0, 0x264, 2, 0x7EC, 0, 0)
+#define _MX53_PAD_FEC_TXD1__MLB_MLBCLK		IOMUX_PAD(0x5E0, 0x264, 3, 0x858, 1, 0)
+#define _MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK	IOMUX_PAD(0x5E0, 0x264, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD0__FEC_TDATA_0		IOMUX_PAD(0x5E4, 0x268, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD0__GPIO1_30			IOMUX_PAD(0x5E4, 0x268, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		IOMUX_PAD(0x5E4, 0x268, 2, 0x7F4, 0, 0)
+#define _MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0	IOMUX_PAD(0x5E4, 0x268, 7, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__FEC_MDC			IOMUX_PAD(0x5E8, 0x26C, 0, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__GPIO1_31			IOMUX_PAD(0x5E8, 0x26C, 1, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		IOMUX_PAD(0x5E8, 0x26C, 2, 0x7F8, 0, 0)
+#define _MX53_PAD_FEC_MDC__MLB_MLBDAT		IOMUX_PAD(0x5E8, 0x26C, 3, 0x85C, 1, 0)
+#define _MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG	IOMUX_PAD(0x5E8, 0x26C, 4, 0x0, 0, 0)
+#define _MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1	IOMUX_PAD(0x5E8, 0x26C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOW__PATA_DIOW		IOMUX_PAD(0x5F0, 0x270, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOW__GPIO6_17		IOMUX_PAD(0x5F0, 0x270, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOW__UART1_TXD_MUX	IOMUX_PAD(0x5F0, 0x270, 3, 0x878, 2, 0)
+#define _MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2	IOMUX_PAD(0x5F0, 0x270, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMACK__PATA_DMACK		IOMUX_PAD(0x5F4, 0x274, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMACK__GPIO6_18		IOMUX_PAD(0x5F4, 0x274, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMACK__UART1_RXD_MUX	IOMUX_PAD(0x5F4, 0x274, 3, 0x878, 3, 0)
+#define _MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3	IOMUX_PAD(0x5F4, 0x274, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__PATA_DMARQ		IOMUX_PAD(0x5F8, 0x278, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__GPIO7_0		IOMUX_PAD(0x5F8, 0x278, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__UART2_TXD_MUX	IOMUX_PAD(0x5F8, 0x278, 3, 0x880, 2, 0)
+#define _MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0	IOMUX_PAD(0x5F8, 0x278, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4	IOMUX_PAD(0x5F8, 0x278, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN	IOMUX_PAD(0x5FC, 0x27C, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__GPIO7_1		IOMUX_PAD(0x5FC, 0x27C, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX	IOMUX_PAD(0x5FC, 0x27C, 3, 0x880, 3, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1	IOMUX_PAD(0x5FC, 0x27C, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5	IOMUX_PAD(0x5FC, 0x27C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__PATA_INTRQ		IOMUX_PAD(0x600, 0x280, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__GPIO7_2		IOMUX_PAD(0x600, 0x280, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__UART2_CTS		IOMUX_PAD(0x600, 0x280, 3, 0x87C, 2, 0)
+#define _MX53_PAD_PATA_INTRQ__CAN1_TXCAN		IOMUX_PAD(0x600, 0x280, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2	IOMUX_PAD(0x600, 0x280, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6	IOMUX_PAD(0x600, 0x280, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOR__PATA_DIOR		IOMUX_PAD(0x604, 0x284, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOR__GPIO7_3			IOMUX_PAD(0x604, 0x284, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DIOR__UART2_RTS		IOMUX_PAD(0x604, 0x284, 3, 0x87C, 3, 0)
+#define _MX53_PAD_PATA_DIOR__CAN1_RXCAN		IOMUX_PAD(0x604, 0x284, 4, 0x760, 1, 0)
+#define _MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7	IOMUX_PAD(0x604, 0x284, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B	IOMUX_PAD(0x608, 0x288, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__GPIO7_4		IOMUX_PAD(0x608, 0x288, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__ESDHC3_CMD		IOMUX_PAD(0x608, 0x288, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__UART1_CTS		IOMUX_PAD(0x608, 0x288, 3, 0x874, 2, 0)
+#define _MX53_PAD_PATA_RESET_B__CAN2_TXCAN		IOMUX_PAD(0x608, 0x288, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0	IOMUX_PAD(0x608, 0x288, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__PATA_IORDY		IOMUX_PAD(0x60C, 0x28C, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__GPIO7_5		IOMUX_PAD(0x60C, 0x28C, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__ESDHC3_CLK		IOMUX_PAD(0x60C, 0x28C, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_IORDY__UART1_RTS		IOMUX_PAD(0x60C, 0x28C, 3, 0x874, 3, 0)
+#define _MX53_PAD_PATA_IORDY__CAN2_RXCAN		IOMUX_PAD(0x60C, 0x28C, 4, 0x764, 1, 0)
+#define _MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1	IOMUX_PAD(0x60C, 0x28C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__PATA_DA_0		IOMUX_PAD(0x610, 0x290, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__GPIO7_6		IOMUX_PAD(0x610, 0x290, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__ESDHC3_RST		IOMUX_PAD(0x610, 0x290, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_0__OWIRE_LINE		IOMUX_PAD(0x610, 0x290, 4, 0x864, 0, 0)
+#define _MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2	IOMUX_PAD(0x610, 0x290, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__PATA_DA_1		IOMUX_PAD(0x614, 0x294, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__GPIO7_7		IOMUX_PAD(0x614, 0x294, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__ESDHC4_CMD		IOMUX_PAD(0x614, 0x294, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_1__UART3_CTS		IOMUX_PAD(0x614, 0x294, 4, 0x884, 4, 0)
+#define _MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3	IOMUX_PAD(0x614, 0x294, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__PATA_DA_2		IOMUX_PAD(0x618, 0x298, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__GPIO7_8		IOMUX_PAD(0x618, 0x298, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__ESDHC4_CLK		IOMUX_PAD(0x618, 0x298, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DA_2__UART3_RTS		IOMUX_PAD(0x618, 0x298, 4, 0x884, 5, 0)
+#define _MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4	IOMUX_PAD(0x618, 0x298, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_0__PATA_CS_0		IOMUX_PAD(0x61C, 0x29C, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_0__GPIO7_9			IOMUX_PAD(0x61C, 0x29C, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_0__UART3_TXD_MUX		IOMUX_PAD(0x61C, 0x29C, 4, 0x888, 2, 0)
+#define _MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5	IOMUX_PAD(0x61C, 0x29C, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_1__PATA_CS_1		IOMUX_PAD(0x620, 0x2A0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_1__GPIO7_10		IOMUX_PAD(0x620, 0x2A0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_CS_1__UART3_RXD_MUX		IOMUX_PAD(0x620, 0x2A0, 4, 0x888, 3, 0)
+#define _MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6	IOMUX_PAD(0x620, 0x2A0, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__PATA_DATA_0		IOMUX_PAD(0x628, 0x2A4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__GPIO2_0		IOMUX_PAD(0x628, 0x2A4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__EMI_NANDF_D_0	IOMUX_PAD(0x628, 0x2A4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__ESDHC3_DAT4		IOMUX_PAD(0x628, 0x2A4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0	IOMUX_PAD(0x628, 0x2A4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0	IOMUX_PAD(0x628, 0x2A4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7	IOMUX_PAD(0x628, 0x2A4, 7, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__PATA_DATA_1		IOMUX_PAD(0x62C, 0x2A8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__GPIO2_1		IOMUX_PAD(0x62C, 0x2A8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__EMI_NANDF_D_1	IOMUX_PAD(0x62C, 0x2A8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__ESDHC3_DAT5		IOMUX_PAD(0x62C, 0x2A8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1	IOMUX_PAD(0x62C, 0x2A8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1	IOMUX_PAD(0x62C, 0x2A8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__PATA_DATA_2		IOMUX_PAD(0x630, 0x2AC, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__GPIO2_2		IOMUX_PAD(0x630, 0x2AC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__EMI_NANDF_D_2	IOMUX_PAD(0x630, 0x2AC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__ESDHC3_DAT6		IOMUX_PAD(0x630, 0x2AC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2	IOMUX_PAD(0x630, 0x2AC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2	IOMUX_PAD(0x630, 0x2AC, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__PATA_DATA_3		IOMUX_PAD(0x634, 0x2B0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__GPIO2_3		IOMUX_PAD(0x634, 0x2B0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__EMI_NANDF_D_3	IOMUX_PAD(0x634, 0x2B0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__ESDHC3_DAT7		IOMUX_PAD(0x634, 0x2B0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3	IOMUX_PAD(0x634, 0x2B0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3	IOMUX_PAD(0x634, 0x2B0, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__PATA_DATA_4		IOMUX_PAD(0x638, 0x2B4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__GPIO2_4		IOMUX_PAD(0x638, 0x2B4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__EMI_NANDF_D_4	IOMUX_PAD(0x638, 0x2B4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__ESDHC4_DAT4		IOMUX_PAD(0x638, 0x2B4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4	IOMUX_PAD(0x638, 0x2B4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4	IOMUX_PAD(0x638, 0x2B4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__PATA_DATA_5	IOMUX_PAD(0x63C, 0x2B8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__GPIO2_5		IOMUX_PAD(0x63C, 0x2B8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__EMI_NANDF_D_5	IOMUX_PAD(0x63C, 0x2B8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__ESDHC4_DAT5		IOMUX_PAD(0x63C, 0x2B8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5	IOMUX_PAD(0x63C, 0x2B8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5	IOMUX_PAD(0x63C, 0x2B8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__PATA_DATA_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__GPIO2_6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__EMI_NANDF_D_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__ESDHC4_DAT6		IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6	IOMUX_PAD(0x640, 0x2BC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__PATA_DATA_7		IOMUX_PAD(0x644, 0x2C0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__GPIO2_7		IOMUX_PAD(0x644, 0x2C0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__EMI_NANDF_D_7	IOMUX_PAD(0x644, 0x2C0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__ESDHC4_DAT7		IOMUX_PAD(0x644, 0x2C0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7	IOMUX_PAD(0x644, 0x2C0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7	IOMUX_PAD(0x644, 0x2C0, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__PATA_DATA_8		IOMUX_PAD(0x648, 0x2C4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__GPIO2_8		IOMUX_PAD(0x648, 0x2C4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__ESDHC1_DAT4		IOMUX_PAD(0x648, 0x2C4, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__EMI_NANDF_D_8	IOMUX_PAD(0x648, 0x2C4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__ESDHC3_DAT0		IOMUX_PAD(0x648, 0x2C4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8	IOMUX_PAD(0x648, 0x2C4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8	IOMUX_PAD(0x648, 0x2C4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__PATA_DATA_9		IOMUX_PAD(0x64C, 0x2C8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__GPIO2_9		IOMUX_PAD(0x64C, 0x2C8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__ESDHC1_DAT5		IOMUX_PAD(0x64C, 0x2C8, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__EMI_NANDF_D_9	IOMUX_PAD(0x64C, 0x2C8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__ESDHC3_DAT1		IOMUX_PAD(0x64C, 0x2C8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9	IOMUX_PAD(0x64C, 0x2C8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9	IOMUX_PAD(0x64C, 0x2C8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__PATA_DATA_10	IOMUX_PAD(0x650, 0x2CC, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__GPIO2_10		IOMUX_PAD(0x650, 0x2CC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__ESDHC1_DAT6		IOMUX_PAD(0x650, 0x2CC, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__EMI_NANDF_D_10	IOMUX_PAD(0x650, 0x2CC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__ESDHC3_DAT2		IOMUX_PAD(0x650, 0x2CC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10	IOMUX_PAD(0x650, 0x2CC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10	IOMUX_PAD(0x650, 0x2CC, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__PATA_DATA_11	IOMUX_PAD(0x654, 0x2D0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__GPIO2_11		IOMUX_PAD(0x654, 0x2D0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__ESDHC1_DAT7		IOMUX_PAD(0x654, 0x2D0, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__EMI_NANDF_D_11	IOMUX_PAD(0x654, 0x2D0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__ESDHC3_DAT3		IOMUX_PAD(0x654, 0x2D0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11	IOMUX_PAD(0x654, 0x2D0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11	IOMUX_PAD(0x654, 0x2D0, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__PATA_DATA_12	IOMUX_PAD(0x658, 0x2D4, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__GPIO2_12		IOMUX_PAD(0x658, 0x2D4, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__ESDHC2_DAT4		IOMUX_PAD(0x658, 0x2D4, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__EMI_NANDF_D_12	IOMUX_PAD(0x658, 0x2D4, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__ESDHC4_DAT0		IOMUX_PAD(0x658, 0x2D4, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12	IOMUX_PAD(0x658, 0x2D4, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12	IOMUX_PAD(0x658, 0x2D4, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__PATA_DATA_13	IOMUX_PAD(0x65C, 0x2D8, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__GPIO2_13		IOMUX_PAD(0x65C, 0x2D8, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__ESDHC2_DAT5		IOMUX_PAD(0x65C, 0x2D8, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__EMI_NANDF_D_13	IOMUX_PAD(0x65C, 0x2D8, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__ESDHC4_DAT1		IOMUX_PAD(0x65C, 0x2D8, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13	IOMUX_PAD(0x65C, 0x2D8, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13	IOMUX_PAD(0x65C, 0x2D8, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__PATA_DATA_14	IOMUX_PAD(0x660, 0x2DC, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__GPIO2_14		IOMUX_PAD(0x660, 0x2DC, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__ESDHC2_DAT6		IOMUX_PAD(0x660, 0x2DC, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__EMI_NANDF_D_14	IOMUX_PAD(0x660, 0x2DC, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__ESDHC4_DAT2		IOMUX_PAD(0x660, 0x2DC, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14	IOMUX_PAD(0x660, 0x2DC, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14	IOMUX_PAD(0x660, 0x2DC, 6, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__PATA_DATA_15	IOMUX_PAD(0x664, 0x2E0, 0, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__GPIO2_15		IOMUX_PAD(0x664, 0x2E0, 1, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__ESDHC2_DAT7		IOMUX_PAD(0x664, 0x2E0, 2, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__EMI_NANDF_D_15	IOMUX_PAD(0x664, 0x2E0, 3, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__ESDHC4_DAT3		IOMUX_PAD(0x664, 0x2E0, 4, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15	IOMUX_PAD(0x664, 0x2E0, 5, 0x0, 0, 0)
+#define _MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15	IOMUX_PAD(0x664, 0x2E0, 6, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__ESDHC1_DAT0	IOMUX_PAD(0x66C, 0x2E4, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__GPIO1_16	IOMUX_PAD(0x66C, 0x2E4, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__GPT_CAPIN1	IOMUX_PAD(0x66C, 0x2E4, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA0__CSPI_MISO	IOMUX_PAD(0x66C, 0x2E4, 5, 0x784, 2, 0)
+#define _MX53_PAD_SD1_DATA0__CCM_PLL3_BYP	IOMUX_PAD(0x66C, 0x2E4, 7, 0x778, 0, 0)
+#define _MX53_PAD_SD1_DATA1__ESDHC1_DAT1	IOMUX_PAD(0x670, 0x2E8, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA1__GPIO1_17	IOMUX_PAD(0x670, 0x2E8, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA1__GPT_CAPIN2	IOMUX_PAD(0x670, 0x2E8, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA1__CSPI_SS0	IOMUX_PAD(0x670, 0x2E8, 5, 0x78C, 3, 0)
+#define _MX53_PAD_SD1_DATA1__CCM_PLL4_BYP	IOMUX_PAD(0x670, 0x2E8, 7, 0x77C, 1, 0)
+#define _MX53_PAD_SD1_CMD__ESDHC1_CMD	IOMUX_PAD(0x674, 0x2EC, IOMUX_CONFIG_SION, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CMD__GPIO1_18		IOMUX_PAD(0x674, 0x2EC, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CMD__GPT_CMPOUT1	IOMUX_PAD(0x674, 0x2EC, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CMD__CSPI_MOSI		IOMUX_PAD(0x674, 0x2EC, 5, 0x788, 2, 0)
+#define _MX53_PAD_SD1_CMD__CCM_PLL1_BYP	IOMUX_PAD(0x674, 0x2EC, 7, 0x770, 0, 0)
+#define _MX53_PAD_SD1_DATA2__ESDHC1_DAT2		IOMUX_PAD(0x678, 0x2F0, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__GPIO1_19		IOMUX_PAD(0x678, 0x2F0, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__GPT_CMPOUT2		IOMUX_PAD(0x678, 0x2F0, 2, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__PWM2_PWMO		IOMUX_PAD(0x678, 0x2F0, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		IOMUX_PAD(0x678, 0x2F0, 4, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__CSPI_SS1		IOMUX_PAD(0x678, 0x2F0, 5, 0x790, 2, 0)
+#define _MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB	IOMUX_PAD(0x678, 0x2F0, 6, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		IOMUX_PAD(0x678, 0x2F0, 7, 0x774, 0, 0)
+#define _MX53_PAD_SD1_CLK__ESDHC1_CLK	IOMUX_PAD(0x67C, 0x2F4, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__GPIO1_20		IOMUX_PAD(0x67C, 0x2F4, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__OSC32k_32K_OUT	IOMUX_PAD(0x67C, 0x2F4, 2, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__GPT_CLKIN		IOMUX_PAD(0x67C, 0x2F4, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_CLK__CSPI_SCLK		IOMUX_PAD(0x67C, 0x2F4, 5, 0x780, 2, 0)
+#define _MX53_PAD_SD1_CLK__SATA_PHY_DTB_0	IOMUX_PAD(0x67C, 0x2F4, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__ESDHC1_DAT3	IOMUX_PAD(0x680, 0x2F8, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__GPIO1_21	IOMUX_PAD(0x680, 0x2F8, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__GPT_CMPOUT3	IOMUX_PAD(0x680, 0x2F8, 2, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__PWM1_PWMO	IOMUX_PAD(0x680, 0x2F8, 3, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_B	IOMUX_PAD(0x680, 0x2F8, 4, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__CSPI_SS2	IOMUX_PAD(0x680, 0x2F8, 5, 0x794, 2, 0)
+#define _MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB	IOMUX_PAD(0x680, 0x2F8, 6, 0x0, 0, 0)
+#define _MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1	IOMUX_PAD(0x680, 0x2F8, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CLK__ESDHC2_CLK	IOMUX_PAD(0x688, 0x2FC, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CLK__GPIO1_10		IOMUX_PAD(0x688, 0x2FC, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CLK__KPP_COL_5		IOMUX_PAD(0x688, 0x2FC, 2, 0x840, 2, 0)
+#define _MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS	IOMUX_PAD(0x688, 0x2FC, 3, 0x73C, 1, 0)
+#define _MX53_PAD_SD2_CLK__CSPI_SCLK		IOMUX_PAD(0x688, 0x2FC, 5, 0x780, 3, 0)
+#define _MX53_PAD_SD2_CLK__SCC_RANDOM_V	IOMUX_PAD(0x688, 0x2FC, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CMD__ESDHC2_CMD	IOMUX_PAD(0x68C, 0x300, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CMD__GPIO1_11		IOMUX_PAD(0x68C, 0x300, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_CMD__KPP_ROW_5	IOMUX_PAD(0x68C, 0x300, 2, 0x84C, 1, 0)
+#define _MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC	IOMUX_PAD(0x68C, 0x300, 3, 0x738, 1, 0)
+#define _MX53_PAD_SD2_CMD__CSPI_MOSI		IOMUX_PAD(0x68C, 0x300, 5, 0x788, 3, 0)
+#define _MX53_PAD_SD2_CMD__SCC_RANDOM	IOMUX_PAD(0x68C, 0x300, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA3__ESDHC2_DAT3	IOMUX_PAD(0x690, 0x304, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA3__GPIO1_12	IOMUX_PAD(0x690, 0x304, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA3__KPP_COL_6	IOMUX_PAD(0x690, 0x304, 2, 0x844, 1, 0)
+#define _MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC	IOMUX_PAD(0x690, 0x304, 3, 0x740, 1, 0)
+#define _MX53_PAD_SD2_DATA3__CSPI_SS2	IOMUX_PAD(0x690, 0x304, 5, 0x794, 3, 0)
+#define _MX53_PAD_SD2_DATA3__SJC_DONE	IOMUX_PAD(0x690, 0x304, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA2__ESDHC2_DAT2	IOMUX_PAD(0x694, 0x308, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA2__GPIO1_13	IOMUX_PAD(0x694, 0x308, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA2__KPP_ROW_6	IOMUX_PAD(0x694, 0x308, 2, 0x850, 1, 0)
+#define _MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD	IOMUX_PAD(0x694, 0x308, 3, 0x734, 1, 0)
+#define _MX53_PAD_SD2_DATA2__CSPI_SS1	IOMUX_PAD(0x694, 0x308, 5, 0x790, 3, 0)
+#define _MX53_PAD_SD2_DATA2__SJC_FAIL	IOMUX_PAD(0x694, 0x308, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA1__ESDHC2_DAT1	IOMUX_PAD(0x698, 0x30C, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA1__GPIO1_14	IOMUX_PAD(0x698, 0x30C, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA1__KPP_COL_7	IOMUX_PAD(0x698, 0x30C, 2, 0x848, 1, 0)
+#define _MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS	IOMUX_PAD(0x698, 0x30C, 3, 0x744, 0, 0)
+#define _MX53_PAD_SD2_DATA1__CSPI_SS0	IOMUX_PAD(0x698, 0x30C, 5, 0x78C, 4, 0)
+#define _MX53_PAD_SD2_DATA1__RTIC_SEC_VIO	IOMUX_PAD(0x698, 0x30C, 7, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA0__ESDHC2_DAT0	IOMUX_PAD(0x69C, 0x310, 0, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA0__GPIO1_15	IOMUX_PAD(0x69C, 0x310, 1, 0x0, 0, 0)
+#define _MX53_PAD_SD2_DATA0__KPP_ROW_7	IOMUX_PAD(0x69C, 0x310, 2, 0x854, 1, 0)
+#define _MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD	IOMUX_PAD(0x69C, 0x310, 3, 0x730, 1, 0)
+#define _MX53_PAD_SD2_DATA0__CSPI_MISO	IOMUX_PAD(0x69C, 0x310, 5, 0x784, 3, 0)
+#define _MX53_PAD_SD2_DATA0__RTIC_DONE_INT	IOMUX_PAD(0x69C, 0x310, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__CCM_CLKO		IOMUX_PAD(0x6A4, 0x314, 0, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__GPIO1_0		IOMUX_PAD(0x6A4, 0x314, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__KPP_COL_5		IOMUX_PAD(0x6A4, 0x314, 2, 0x840, 3, 0)
+#define _MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK	IOMUX_PAD(0x6A4, 0x314, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__EPIT1_EPITO	IOMUX_PAD(0x6A4, 0x314, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__SRTC_ALARM_DEB	IOMUX_PAD(0x6A4, 0x314, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__USBOH3_USBH1_PWR	IOMUX_PAD(0x6A4, 0x314, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_0__CSU_TD		IOMUX_PAD(0x6A4, 0x314, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__ESAI1_SCKR		IOMUX_PAD(0x6A8, 0x318, 0, 0x7DC, 1, 0)
+#define _MX53_PAD_GPIO_1__GPIO1_1		IOMUX_PAD(0x6A8, 0x318, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__KPP_ROW_5		IOMUX_PAD(0x6A8, 0x318, 2, 0x84C, 2, 0)
+#define _MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK	IOMUX_PAD(0x6A8, 0x318, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__PWM2_PWMO	IOMUX_PAD(0x6A8, 0x318, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__WDOG2_WDOG_B	IOMUX_PAD(0x6A8, 0x318, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__ESDHC1_CD		IOMUX_PAD(0x6A8, 0x318, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_1__SRC_TESTER_ACK	IOMUX_PAD(0x6A8, 0x318, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__ESAI1_FSR		IOMUX_PAD(0x6AC, 0x31C, 0, 0x7CC, 1, 0)
+#define _MX53_PAD_GPIO_9__GPIO1_9		IOMUX_PAD(0x6AC, 0x31C, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__KPP_COL_6		IOMUX_PAD(0x6AC, 0x31C, 2, 0x844, 2, 0)
+#define _MX53_PAD_GPIO_9__CCM_REF_EN_B	IOMUX_PAD(0x6AC, 0x31C, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__PWM1_PWMO	IOMUX_PAD(0x6AC, 0x31C, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__WDOG1_WDOG_B	IOMUX_PAD(0x6AC, 0x31C, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_9__ESDHC1_WP		IOMUX_PAD(0x6AC, 0x31C, 6, 0x7FC, 1, 0)
+#define _MX53_PAD_GPIO_9__SCC_FAIL_STATE	IOMUX_PAD(0x6AC, 0x31C, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__ESAI1_HCKR		IOMUX_PAD(0x6B0, 0x320, 0, 0x7D4, 1, 0)
+#define _MX53_PAD_GPIO_3__GPIO1_3		IOMUX_PAD(0x6B0, 0x320, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__I2C3_SCL		IOMUX_PAD(0x6B0, 0x320, 2 | IOMUX_CONFIG_SION, 0x824, 1, 0)
+#define _MX53_PAD_GPIO_3__DPLLIP1_TOG_EN	IOMUX_PAD(0x6B0, 0x320, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__CCM_CLKO2		IOMUX_PAD(0x6B0, 0x320, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0	IOMUX_PAD(0x6B0, 0x320, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_3__USBOH3_USBH1_OC	IOMUX_PAD(0x6B0, 0x320, 6, 0x8A0, 1, 0)
+#define _MX53_PAD_GPIO_3__MLB_MLBCLK		IOMUX_PAD(0x6B0, 0x320, 7, 0x858, 2, 0)
+#define _MX53_PAD_GPIO_6__ESAI1_SCKT		IOMUX_PAD(0x6B4, 0x324, 0, 0x7E0, 1, 0)
+#define _MX53_PAD_GPIO_6__GPIO1_6		IOMUX_PAD(0x6B4, 0x324, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__I2C3_SDA		IOMUX_PAD(0x6B4, 0x324, 2 | IOMUX_CONFIG_SION, 0x828, 1, 0)
+#define _MX53_PAD_GPIO_6__CCM_CCM_OUT_0	IOMUX_PAD(0x6B4, 0x324, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__CSU_CSU_INT_DEB	IOMUX_PAD(0x6B4, 0x324, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1	IOMUX_PAD(0x6B4, 0x324, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__ESDHC2_LCTL	IOMUX_PAD(0x6B4, 0x324, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_6__MLB_MLBSIG		IOMUX_PAD(0x6B4, 0x324, 7, 0x860, 2, 0)
+#define _MX53_PAD_GPIO_2__ESAI1_FST		IOMUX_PAD(0x6B8, 0x328, 0, 0x7D0, 1, 0)
+#define _MX53_PAD_GPIO_2__GPIO1_2		IOMUX_PAD(0x6B8, 0x328, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__KPP_ROW_6		IOMUX_PAD(0x6B8, 0x328, 2, 0x850, 2, 0)
+#define _MX53_PAD_GPIO_2__CCM_CCM_OUT_1	IOMUX_PAD(0x6B8, 0x328, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0	IOMUX_PAD(0x6B8, 0x328, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2	IOMUX_PAD(0x6B8, 0x328, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__ESDHC2_WP		IOMUX_PAD(0x6B8, 0x328, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_2__MLB_MLBDAT	IOMUX_PAD(0x6B8, 0x328, 7, 0x85C, 2, 0)
+#define _MX53_PAD_GPIO_4__ESAI1_HCKT		IOMUX_PAD(0x6BC, 0x32C, 0, 0x7D8, 1, 0)
+#define _MX53_PAD_GPIO_4__GPIO1_4		IOMUX_PAD(0x6BC, 0x32C, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__KPP_COL_7		IOMUX_PAD(0x6BC, 0x32C, 2, 0x848, 2, 0)
+#define _MX53_PAD_GPIO_4__CCM_CCM_OUT_2	IOMUX_PAD(0x6BC, 0x32C, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1	IOMUX_PAD(0x6BC, 0x32C, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3	IOMUX_PAD(0x6BC, 0x32C, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__ESDHC2_CD		IOMUX_PAD(0x6BC, 0x32C, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_4__SCC_SEC_STATE	IOMUX_PAD(0x6BC, 0x32C, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__ESAI1_TX2_RX3	IOMUX_PAD(0x6C0, 0x330, 0, 0x7EC, 1, 0)
+#define _MX53_PAD_GPIO_5__GPIO1_5		IOMUX_PAD(0x6C0, 0x330, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__KPP_ROW_7		IOMUX_PAD(0x6C0, 0x330, 2, 0x854, 2, 0)
+#define _MX53_PAD_GPIO_5__CCM_CLKO		IOMUX_PAD(0x6C0, 0x330, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2	IOMUX_PAD(0x6C0, 0x330, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4	IOMUX_PAD(0x6C0, 0x330, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_5__I2C3_SCL		IOMUX_PAD(0x6C0, 0x330, 6, 0x824, 2, 0)
+#define _MX53_PAD_GPIO_5__CCM_PLL1_BYP	IOMUX_PAD(0x6C0, 0x330, 7, 0x770, 1, 0)
+#define _MX53_PAD_GPIO_7__ESAI1_TX4_RX1	IOMUX_PAD(0x6C4, 0x334, 0, 0x7F4, 1, 0)
+#define _MX53_PAD_GPIO_7__GPIO1_7		IOMUX_PAD(0x6C4, 0x334, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__EPIT1_EPITO	IOMUX_PAD(0x6C4, 0x334, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__CAN1_TXCAN	IOMUX_PAD(0x6C4, 0x334, 3, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__UART2_TXD_MUX	IOMUX_PAD(0x6C4, 0x334, 4, 0x880, 4, 0)
+#define _MX53_PAD_GPIO_7__FIRI_RXD		IOMUX_PAD(0x6C4, 0x334, 5, 0x80C, 1, 0)
+#define _MX53_PAD_GPIO_7__SPDIF_PLOCK	IOMUX_PAD(0x6C4, 0x334, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_7__CCM_PLL2_BYP	IOMUX_PAD(0x6C4, 0x334, 7, 0x774, 1, 0)
+#define _MX53_PAD_GPIO_8__ESAI1_TX5_RX0	IOMUX_PAD(0x6C8, 0x338, 0, 0x7F8, 1, 0)
+#define _MX53_PAD_GPIO_8__GPIO1_8		IOMUX_PAD(0x6C8, 0x338, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__EPIT2_EPITO	IOMUX_PAD(0x6C8, 0x338, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__CAN1_RXCAN	IOMUX_PAD(0x6C8, 0x338, 3, 0x760, 3, 0)
+#define _MX53_PAD_GPIO_8__UART2_RXD_MUX	IOMUX_PAD(0x6C8, 0x338, 4, 0x880, 5, 0)
+#define _MX53_PAD_GPIO_8__FIRI_TXD		IOMUX_PAD(0x6C8, 0x338, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__SPDIF_SRCLK	IOMUX_PAD(0x6C8, 0x338, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_8__CCM_PLL3_BYP	IOMUX_PAD(0x6C8, 0x338, 7, 0x778, 1, 0)
+#define _MX53_PAD_GPIO_16__ESAI1_TX3_RX2	IOMUX_PAD(0x6CC, 0x33C, 0, 0x7F0, 1, 0)
+#define _MX53_PAD_GPIO_16__GPIO7_11		IOMUX_PAD(0x6CC, 0x33C, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT	IOMUX_PAD(0x6CC, 0x33C, 2, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1	IOMUX_PAD(0x6CC, 0x33C, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_16__SPDIF_IN1		IOMUX_PAD(0x6CC, 0x33C, 5, 0x870, 1, 0)
+#define _MX53_PAD_GPIO_16__I2C3_SDA		IOMUX_PAD(0x6CC, 0x33C, 6 | IOMUX_CONFIG_SION, 0x828, 2, 0)
+#define _MX53_PAD_GPIO_16__SJC_DE_B		IOMUX_PAD(0x6CC, 0x33C, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__ESAI1_TX0		IOMUX_PAD(0x6D0, 0x340, 0, 0x7E4, 1, 0)
+#define _MX53_PAD_GPIO_17__GPIO7_12		IOMUX_PAD(0x6D0, 0x340, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0	IOMUX_PAD(0x6D0, 0x340, 2, 0x868, 1, 0)
+#define _MX53_PAD_GPIO_17__GPC_PMIC_RDY	IOMUX_PAD(0x6D0, 0x340, 3, 0x810, 1, 0)
+#define _MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG	IOMUX_PAD(0x6D0, 0x340, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__SPDIF_OUT1	IOMUX_PAD(0x6D0, 0x340, 5, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__IPU_SNOOP2	IOMUX_PAD(0x6D0, 0x340, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_17__SJC_JTAG_ACT	IOMUX_PAD(0x6D0, 0x340, 7, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__ESAI1_TX1		IOMUX_PAD(0x6D4, 0x344, 0, 0x7E8, 1, 0)
+#define _MX53_PAD_GPIO_18__GPIO7_13		IOMUX_PAD(0x6D4, 0x344, 1, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1	IOMUX_PAD(0x6D4, 0x344, 2, 0x86C, 1, 0)
+#define _MX53_PAD_GPIO_18__OWIRE_LINE	IOMUX_PAD(0x6D4, 0x344, 3, 0x864, 1, 0)
+#define _MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG	IOMUX_PAD(0x6D4, 0x344, 4, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK	IOMUX_PAD(0x6D4, 0x344, 5, 0x768, 1, 0)
+#define _MX53_PAD_GPIO_18__ESDHC1_LCTL	IOMUX_PAD(0x6D4, 0x344, 6, 0x0, 0, 0)
+#define _MX53_PAD_GPIO_18__SRC_SYSTEM_RST	IOMUX_PAD(0x6D4, 0x344, 7, 0x0, 0, 0)
 
-#define MX53_PAD_GPIO_19__GPIO_4_5		IOMUX_PAD(0x348, 0x20,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL0__GPIO_4_6		IOMUX_PAD(0x34C, 0x24,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW0__GPIO_4_7		IOMUX_PAD(0x350, 0x28,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL1__GPIO_4_8		IOMUX_PAD(0x354, 0x2C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW1__GPIO_4_9		IOMUX_PAD(0x358, 0x30,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL2__GPIO_4_10		IOMUX_PAD(0x35C, 0x34,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW2__GPIO_4_11	IOMUX_PAD(0x360, 0x38,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL3__GPIO_4_12		IOMUX_PAD(0x364, 0x3C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW3__GPIO_4_13	IOMUX_PAD(0x368, 0x40,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_COL4__GPIO_4_14		IOMUX_PAD(0x36C, 0x44,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_KEY_ROW4__GPIO_4_15	IOMUX_PAD(0x370, 0x48,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_KEYPAD__NVCC_KEYPAD	IOMUX_PAD(0x374, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_DISP_CLK__GPIO_4_16	IOMUX_PAD(0x378, 0x4C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN15__GPIO_4_17	IOMUX_PAD(0x37C, 0x50,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN2__GPIO_4_18		IOMUX_PAD(0x380, 0x54,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN3__GPIO_4_19		IOMUX_PAD(0x384, 0x58,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DI0_PIN4__GPIO_4_20		IOMUX_PAD(0x388, 0x5C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT0__GPIO_4_21	IOMUX_PAD(0x38C, 0x60,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT1__GPIO_4_22	IOMUX_PAD(0x390, 0x64,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT2__GPIO_4_23	IOMUX_PAD(0x394, 0x68,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT3__GPIO_4_24	IOMUX_PAD(0x398, 0x6C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT4__GPIO_4_25	IOMUX_PAD(0x39C, 0x70,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT5__GPIO_4_26	IOMUX_PAD(0x3A0, 0x74,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT6__GPIO_4_27	IOMUX_PAD(0x3A4, 0x78,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT7__GPIO_4_28	IOMUX_PAD(0x3A8, 0x7C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT8__GPIO_4_29	IOMUX_PAD(0x3AC, 0x80,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT9__GPIO_4_30	IOMUX_PAD(0x3B0, 0x84,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT10__GPIO_4_31	IOMUX_PAD(0x3B4, 0x88,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT11__GPIO_5_5	IOMUX_PAD(0x3B8, 0x8C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT12__GPIO_5_6	IOMUX_PAD(0x3BC, 0x90,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT13__GPIO_5_7	IOMUX_PAD(0x3C0, 0x94,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT14__GPIO_5_8	IOMUX_PAD(0x3C4, 0x98,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT15__GPIO_5_9	IOMUX_PAD(0x3C8, 0x9C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT16__GPIO_5_10	IOMUX_PAD(0x3CC, 0xA0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT17__GPIO_5_11	IOMUX_PAD(0x3D0, 0xA4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT18__GPIO_5_12	IOMUX_PAD(0x3D4, 0xA8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT19__GPIO_5_13	IOMUX_PAD(0x3D8, 0xAC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT20__GPIO_5_14	IOMUX_PAD(0x3DC, 0xB0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT21__GPIO_5_15	IOMUX_PAD(0x3E0, 0xB4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT22__GPIO_5_16	IOMUX_PAD(0x3E4, 0xB8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DISP0_DAT23__GPIO_5_17	IOMUX_PAD(0x3E8, 0xBC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_PIXCLK__GPIO_5_18	IOMUX_PAD(0x3EC, 0xC0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_MCLK__GPIO_5_19	IOMUX_PAD(0x3F0, 0xC4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_DATA_EN__GPIO_5_20	IOMUX_PAD(0x3F4, 0xC8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_VSYNC__GPIO_5_21	IOMUX_PAD(0x3F8, 0xCC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D4__GPIO_5_22		IOMUX_PAD(0x3FC, 0xD0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D5__GPIO_5_23		IOMUX_PAD(0x400, 0xD4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D6__GPIO_5_24		IOMUX_PAD(0x404, 0xD8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D7__GPIO_5_25		IOMUX_PAD(0x408, 0xDC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D8__GPIO_5_26		IOMUX_PAD(0x40C, 0xE0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D9__GPIO_5_27		IOMUX_PAD(0x410, 0xE4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D10__GPIO_5_28		IOMUX_PAD(0x414, 0xE8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D11__GPIO_5_29		IOMUX_PAD(0x418, 0xEC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D12__GPIO_5_30		IOMUX_PAD(0x41C, 0xF0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D13__GPIO_5_31		IOMUX_PAD(0x420, 0xF4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D14__GPIO_6_0		IOMUX_PAD(0x424, 0xF8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D15__GPIO_6_1		IOMUX_PAD(0x428, 0xFC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D16__GPIO_6_2		IOMUX_PAD(0x42C, 0x100,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D17__GPIO_6_3		IOMUX_PAD(0x430, 0x104,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D18__GPIO_6_4		IOMUX_PAD(0x434, 0x108,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_CSI0_D19__GPIO_6_5		IOMUX_PAD(0x438, 0x10C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_CSI0__NVCC_CSI0	IOMUX_PAD(0x43C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TMS__JTAG_TMS		IOMUX_PAD(0x440, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_MOD__JTAG_MOD		IOMUX_PAD(0x444, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TRSTB__JTAG_TRSTB	IOMUX_PAD(0x448, NON_MUX_I,IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TDI__JTAG_TDI		IOMUX_PAD(0x44C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TCK__JTAG_TCK		IOMUX_PAD(0x450, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_JTAG_TDO__JTAG_TDO		IOMUX_PAD(0x454, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A25__GPIO_5_2		IOMUX_PAD(0x458, 0x110,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB2__GPIO_2_30		IOMUX_PAD(0x45C, 0x114,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__GPIO_3_16		IOMUX_PAD(0x460, 0x118,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__GPIO_3_17		IOMUX_PAD(0x464, 0x11C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__GPIO_3_18		IOMUX_PAD(0x468, 0x120,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D16__CSPI1_SCLK		IOMUX_PAD(0x460, 0x118,IOMUX_CONFIG_ALT4, 0x79c, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D17__CSPI1_MISO		IOMUX_PAD(0x464, 0x11C,IOMUX_CONFIG_ALT4, 0x7a0, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D18__CSPI1_MOSI		IOMUX_PAD(0x468, 0x120,IOMUX_CONFIG_ALT4, 0x7a4, 3, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D19__GPIO_3_19		IOMUX_PAD(0x46C, 0x124,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D20__GPIO_3_20		IOMUX_PAD(0x470, 0x128,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D21__GPIO_3_21		IOMUX_PAD(0x474, 0x12C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D22__GPIO_3_22		IOMUX_PAD(0x478, 0x130,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D23__GPIO_3_23		IOMUX_PAD(0x47C, 0x134,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB3__GPIO_2_31		IOMUX_PAD(0x480, 0x138,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D24__GPIO_3_24		IOMUX_PAD(0x484, 0x13C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D25__GPIO_3_25		IOMUX_PAD(0x488, 0x140,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D26__GPIO_3_26		IOMUX_PAD(0x48C, 0x144,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D27__GPIO_3_27		IOMUX_PAD(0x490, 0x148,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D28__GPIO_3_28		IOMUX_PAD(0x494, 0x14C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D29__GPIO_3_29		IOMUX_PAD(0x498, 0x150,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D30__GPIO_3_30		IOMUX_PAD(0x49C, 0x154,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_D31__GPIO_3_31		IOMUX_PAD(0x4A0, 0x158,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_EIM1__NVCC_EIM1	IOMUX_PAD(0x4A4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A24__GPIO_5_4		IOMUX_PAD(0x4A8, 0x15C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A23__GPIO_6_6		IOMUX_PAD(0x4AC, 0x160,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A22__GPIO_2_16		IOMUX_PAD(0x4B0, 0x164,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A21__GPIO_2_17		IOMUX_PAD(0x4B4, 0x168,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A20__GPIO_2_18		IOMUX_PAD(0x4B8, 0x16C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A19__GPIO_2_19		IOMUX_PAD(0x4BC, 0x170,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A18__GPIO_2_20		IOMUX_PAD(0x4C0, 0x174,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A17__GPIO_2_21		IOMUX_PAD(0x4C4, 0x178,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_A16__GPIO_2_22		IOMUX_PAD(0x4C8, 0x17C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS0__GPIO_2_23		IOMUX_PAD(0x4CC, 0x180,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_CS1__GPIO_2_24		IOMUX_PAD(0x4D0, 0x184,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_OE__GPIO_2_25		IOMUX_PAD(0x4D4, 0x188,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_RW__GPIO_2_26		IOMUX_PAD(0x4D8, 0x18C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_LBA__GPIO_2_27		IOMUX_PAD(0x4DC, 0x190,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_EIM4__NVCC_EIM4	IOMUX_PAD(0x4E0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB0__GPIO_2_28		IOMUX_PAD(0x4E4, 0x194,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_EB1__GPIO_2_29		IOMUX_PAD(0x4E8, 0x198,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA0__GPIO_3_0		IOMUX_PAD(0x4EC, 0x19C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA1__GPIO_3_1		IOMUX_PAD(0x4F0, 0x1A0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA2__GPIO_3_2		IOMUX_PAD(0x4F4, 0x1A4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA3__GPIO_3_3		IOMUX_PAD(0x4F8, 0x1A8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA4__GPIO_3_4		IOMUX_PAD(0x4FC, 0x1AC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA5__GPIO_3_5		IOMUX_PAD(0x500, 0x1B0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA6__GPIO_3_6		IOMUX_PAD(0x504, 0x1B4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA7__GPIO_3_7		IOMUX_PAD(0x508, 0x1B8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA8__GPIO_3_8		IOMUX_PAD(0x50C, 0x1BC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA9__GPIO_3_9		IOMUX_PAD(0x510, 0x1C0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA10__GPIO_3_10		IOMUX_PAD(0x514, 0x1C4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA11__GPIO_3_11		IOMUX_PAD(0x518, 0x1C8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA12__GPIO_3_12		IOMUX_PAD(0x51C, 0x1CC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA13__GPIO_3_13		IOMUX_PAD(0x520, 0x1D0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA14__GPIO_3_14		IOMUX_PAD(0x524, 0x1D4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_DA15__GPIO_3_15		IOMUX_PAD(0x528, 0x1D8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WE_B__GPIO_6_12	IOMUX_PAD(0x52C, 0x1DC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RE_B__GPIO_6_13	IOMUX_PAD(0x530, 0x1E0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_WAIT__GPIO_5_0		IOMUX_PAD(0x534, 0x1E4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_EIM_BCLK__EIM_BCLK		IOMUX_PAD(0x538, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_EIM7__NVCC_EIM7	IOMUX_PAD(0x53C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX3_P__GPIO_6_22	IOMUX_PAD(NON_PAD_I, 0x1EC, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX2_P__GPIO_6_24	IOMUX_PAD(NON_PAD_I, 0x1F0, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_CLK_P__GPIO_6_26	IOMUX_PAD(NON_PAD_I, 0x1F4, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX1_P__GPIO_6_28	IOMUX_PAD(NON_PAD_I, 0x1F8, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS1_TX0_P__GPIO_6_30	IOMUX_PAD(NON_PAD_I, 0x1FC, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX3_P__GPIO_7_22	IOMUX_PAD(NON_PAD_I, 0x200, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_CLK_P__GPIO_7_24	IOMUX_PAD(NON_PAD_I, 0x204, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX2_P__GPIO_7_26	IOMUX_PAD(NON_PAD_I, 0x208, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX1_P__GPIO_7_28	IOMUX_PAD(NON_PAD_I, 0x20C, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_LVDS0_TX0_P__GPIO_7_30	IOMUX_PAD(NON_PAD_I, 0x210, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_10__GPIO_4_0		IOMUX_PAD(0x540, 0x214, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_11__GPIO_4_1		IOMUX_PAD(0x544, 0x218, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_12__GPIO_4_2		IOMUX_PAD(0x548, 0x21C, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_13__GPIO_4_3		IOMUX_PAD(0x54C, 0x220, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_14__GPIO_4_4		IOMUX_PAD(0x550, 0x224, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM3__DRAM_DQM3	IOMUX_PAD(0x554, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS3__DRAM_SDQS3	IOMUX_PAD(0x558, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCKE1__DRAM_SDCKE1	IOMUX_PAD(0x55C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM2__DRAM_DQM2	IOMUX_PAD(0x560, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDODT1__DRAM_SDODT1	IOMUX_PAD(0x564, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS2__DRAM_SDQS2	IOMUX_PAD(0x568, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_RESET__DRAM_RESET	IOMUX_PAD(0x56C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCLK1__DRAM_SDCLK1	IOMUX_PAD(0x570, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_CAS__DRAM_CAS		IOMUX_PAD(0x574, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCLK0__DRAM_SDCLK0	IOMUX_PAD(0x578, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS0__DRAM_SDQS0	IOMUX_PAD(0x57C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDODT0__DRAM_SDODT0	IOMUX_PAD(0x580, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM0__DRAM_DQM0	IOMUX_PAD(0x584, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_RAS__DRAM_RAS		IOMUX_PAD(0x588, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDCKE0__DRAM_SDCKE0	IOMUX_PAD(0x58C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_SDQS1__DRAM_SDQS1	IOMUX_PAD(0x590, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_DRAM_DQM1__DRAM_DQM1	IOMUX_PAD(0x594, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x598, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x59C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CLE__GPIO_6_7		IOMUX_PAD(0x5A0, 0x228,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_ALE__GPIO_6_8	IOMUX_PAD(0x5A4, 0x22C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_WP_B__GPIO_6_9	IOMUX_PAD(0x5A8, 0x230,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_RB0__GPIO_6_10	IOMUX_PAD(0x5AC, 0x234,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS0__GPIO_6_11	IOMUX_PAD(0x5B0, 0x238,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS1__GPIO_6_14	IOMUX_PAD(0x5B4, 0x23C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS2__GPIO_6_15	IOMUX_PAD(0x5B8, 0x240,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NANDF_CS3__GPIO_6_16	IOMUX_PAD(0x5BC, 0x244,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_NANDF__NVCC_NANDF	IOMUX_PAD(0x5C0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDIO__GPIO_1_22		IOMUX_PAD(0x5C4, 0x248,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_REF_CLK__GPIO_1_23	IOMUX_PAD(0x5C8, 0x24C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RX_ER__GPIO_1_24	IOMUX_PAD(0x5CC, 0x250,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_CRS_DV__GPIO_1_25	IOMUX_PAD(0x5D0, 0x254,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD1__GPIO_1_26		IOMUX_PAD(0x5D4, 0x258,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_RXD0__GPIO_1_27		IOMUX_PAD(0x5D8, 0x25C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TX_EN__GPIO_1_28	IOMUX_PAD(0x5DC, 0x260,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD1__GPIO_1_29		IOMUX_PAD(0x5E0, 0x264,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_TXD0__GPIO_1_30		IOMUX_PAD(0x5E4, 0x268,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_FEC_MDC__GPIO_1_31		IOMUX_PAD(0x5E8, 0x26C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_FEC__NVCC_FEC		IOMUX_PAD(0x5EC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DIOW__GPIO_6_17	IOMUX_PAD(0x5F0, 0x270,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DMACK__GPIO_6_18	IOMUX_PAD(0x5F4, 0x274,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DMARQ__GPIO_7_0	IOMUX_PAD(0x5F8, 0x278,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_BUFFER_EN__GPIO_7_1	IOMUX_PAD(0x5FC, 0x27C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_INTRQ__GPIO_7_2		IOMUX_PAD(0x600, 0x280,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DIOR__GPIO_7_3		IOMUX_PAD(0x604, 0x284,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_RESET_B__GPIO_7_4	IOMUX_PAD(0x608, 0x288,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_IORDY__GPIO_7_5		IOMUX_PAD(0x60C, 0x28C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DA_0__GPIO_7_6		IOMUX_PAD(0x610, 0x290,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DA_1__GPIO_7_7		IOMUX_PAD(0x614, 0x294,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DA_2__GPIO_7_8		IOMUX_PAD(0x618, 0x298,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_CS_0__GPIO_7_9		IOMUX_PAD(0x61C, 0x29C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_CS_1__GPIO_7_10		IOMUX_PAD(0x620, 0x2A0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_ATA2__NVCC_ATA2	IOMUX_PAD(0x624, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA0__GPIO_2_0	IOMUX_PAD(0x628, 0x2A4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA1__GPIO_2_1	IOMUX_PAD(0x62C, 0x2A8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA2__GPIO_2_2	IOMUX_PAD(0x630, 0x2AC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA3__GPIO_2_3	IOMUX_PAD(0x634, 0x2B0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA4__GPIO_2_4	IOMUX_PAD(0x638, 0x2B4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA5__GPIO_2_5	IOMUX_PAD(0x63C, 0x2B8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA6__GPIO_2_6	IOMUX_PAD(0x640, 0x2BC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA7__GPIO_2_7	IOMUX_PAD(0x644, 0x2C0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA8__GPIO_2_8	IOMUX_PAD(0x648, 0x2C4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA9__GPIO_2_9	IOMUX_PAD(0x64C, 0x2C8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA10__GPIO_2_10	IOMUX_PAD(0x650, 0x2CC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA11__GPIO_2_11	IOMUX_PAD(0x654, 0x2D0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA12__GPIO_2_12	IOMUX_PAD(0x658, 0x2D4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA13__GPIO_2_13	IOMUX_PAD(0x65C, 0x2D8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA14__GPIO_2_14	IOMUX_PAD(0x660, 0x2DC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_ATA_DATA15__GPIO_2_15	IOMUX_PAD(0x664, 0x2E0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_ATA0__NVCC_ATA0	IOMUX_PAD(0x668, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA0__GPIO_1_16	IOMUX_PAD(0x66C, 0x2E4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA1__GPIO_1_17	IOMUX_PAD(0x670, 0x2E8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CMD__GPIO_1_18		IOMUX_PAD(0x674, 0x2EC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA2__GPIO_1_19	IOMUX_PAD(0x678, 0x2F0,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_CLK__GPIO_1_20		IOMUX_PAD(0x67C, 0x2F4,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD1_DATA3__GPIO_1_21	IOMUX_PAD(0x680, 0x2F8,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_SD1__NVCC_SD1		IOMUX_PAD(0x684, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CLK__GPIO_1_10		IOMUX_PAD(0x688, 0x2FC,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_CMD__GPIO_1_11		IOMUX_PAD(0x68C, 0x300,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA3__GPIO_1_12	IOMUX_PAD(0x690, 0x304,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA2__GPIO_1_13	IOMUX_PAD(0x694, 0x308,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA1__GPIO_1_14	IOMUX_PAD(0x698, 0x30C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_SD2_DATA0__GPIO_1_15	IOMUX_PAD(0x69C, 0x310,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_SD2__NVCC_SD2		IOMUX_PAD(0x6A0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_0__GPIO_1_0		IOMUX_PAD(0x6A4, 0x314,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_1__GPIO_1_1		IOMUX_PAD(0x6A8, 0x318,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_9__GPIO_1_9		IOMUX_PAD(0x6AC, 0x31C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_3__GPIO_1_3		IOMUX_PAD(0x6B0, 0x320,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_6__GPIO_1_6		IOMUX_PAD(0x6B4, 0x324,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_2__GPIO_1_2		IOMUX_PAD(0x6B8, 0x328,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_4__GPIO_1_4		IOMUX_PAD(0x6BC, 0x32C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_5__GPIO_1_5		IOMUX_PAD(0x6C0, 0x330,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_7__GPIO_1_7		IOMUX_PAD(0x6C4, 0x334,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_8__GPIO_1_8		IOMUX_PAD(0x6C8, 0x338,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_16__GPIO_7_11		IOMUX_PAD(0x6CC, 0x33C,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_17__GPIO_7_12		IOMUX_PAD(0x6D0, 0x340,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GPIO_18__GPIO_7_13		IOMUX_PAD(0x6D4, 0x344,IOMUX_CONFIG_ALT1, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_NVCC_GPIO__NVCC_GPIO	IOMUX_PAD(0x6D8, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_POR_B__POR_B			IOMUX_PAD(0x6DC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_BOOT_MODE1__BOOT_MODE1	IOMUX_PAD(0x6E0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_RESET_IN_B__RESET_IN_B	IOMUX_PAD(0x6E4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_BOOT_MODE0__BOOT_MODE0	IOMUX_PAD(0x6E8, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_TEST_MODE__TEST_MODE	IOMUX_PAD(0x6EC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_ADDDS__GRP_ADDDS	IOMUX_PAD(0x6F0, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRMODE_CTL__GRP_DDRMODE_CTL	IOMUX_PAD(0x6F4, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRPKE__GRP_DDRPKE	IOMUX_PAD(0x6FC, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRPK__GRP_DDRPK	IOMUX_PAD(0x708, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_TERM_CTL3__GRP_TERM_CTL3	IOMUX_PAD(0x70C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRHYS__GRP_DDRHYS	IOMUX_PAD(0x710, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDRMODE__GRP_DDRMODE	IOMUX_PAD(0x714, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B0DS__GRP_B0DS		IOMUX_PAD(0x718, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B1DS__GRP_B1DS		IOMUX_PAD(0x71C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_CTLDS__GRP_CTLDS	IOMUX_PAD(0x720, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_DDR_TYPE__GRP_DDR_TYPE	IOMUX_PAD(0x724, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B2DS__GRP_B2DS		IOMUX_PAD(0x728, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
-#define MX53_PAD_GRP_B3DS__GRP_B3DS		IOMUX_PAD(0x72C, NON_MUX_I, IOMUX_CONFIG_ALT0, 0x0, 0, NO_PAD_CTRL)
+#define MX53_PAD_GPIO_19__KPP_COL_5		(_MX53_PAD_GPIO_19__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__GPIO4_5		(_MX53_PAD_GPIO_19__GPIO4_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__CCM_CLKO		(_MX53_PAD_GPIO_19__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__SPDIF_OUT1		(_MX53_PAD_GPIO_19__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2		(_MX53_PAD_GPIO_19__RTC_CE_RTC_EXT_TRIG2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__ECSPI1_RDY		(_MX53_PAD_GPIO_19__ECSPI1_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__FEC_TDATA_3		(_MX53_PAD_GPIO_19__FEC_TDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_19__SRC_INT_BOOT		(_MX53_PAD_GPIO_19__SRC_INT_BOOT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__KPP_COL_0		(_MX53_PAD_KEY_COL0__KPP_COL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__GPIO4_6		(_MX53_PAD_KEY_COL0__GPIO4_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC		(_MX53_PAD_KEY_COL0__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__UART4_TXD_MUX		(_MX53_PAD_KEY_COL0__UART4_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__ECSPI1_SCLK		(_MX53_PAD_KEY_COL0__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__FEC_RDATA_3		(_MX53_PAD_KEY_COL0__FEC_RDATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL0__SRC_ANY_PU_RST		(_MX53_PAD_KEY_COL0__SRC_ANY_PU_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__KPP_ROW_0		(_MX53_PAD_KEY_ROW0__KPP_ROW_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__GPIO4_7		(_MX53_PAD_KEY_ROW0__GPIO4_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD		(_MX53_PAD_KEY_ROW0__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__UART4_RXD_MUX		(_MX53_PAD_KEY_ROW0__UART4_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__ECSPI1_MOSI		(_MX53_PAD_KEY_ROW0__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW0__FEC_TX_ER		(_MX53_PAD_KEY_ROW0__FEC_TX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__KPP_COL_1		(_MX53_PAD_KEY_COL1__KPP_COL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__GPIO4_8		(_MX53_PAD_KEY_COL1__GPIO4_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS		(_MX53_PAD_KEY_COL1__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__UART5_TXD_MUX		(_MX53_PAD_KEY_COL1__UART5_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__ECSPI1_MISO		(_MX53_PAD_KEY_COL1__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__FEC_RX_CLK		(_MX53_PAD_KEY_COL1__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL1__USBPHY1_TXREADY		(_MX53_PAD_KEY_COL1__USBPHY1_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__KPP_ROW_1		(_MX53_PAD_KEY_ROW1__KPP_ROW_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__GPIO4_9		(_MX53_PAD_KEY_ROW1__GPIO4_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD		(_MX53_PAD_KEY_ROW1__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__UART5_RXD_MUX		(_MX53_PAD_KEY_ROW1__UART5_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__ECSPI1_SS0		(_MX53_PAD_KEY_ROW1__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__FEC_COL		(_MX53_PAD_KEY_ROW1__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW1__USBPHY1_RXVALID		(_MX53_PAD_KEY_ROW1__USBPHY1_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__KPP_COL_2		(_MX53_PAD_KEY_COL2__KPP_COL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__GPIO4_10		(_MX53_PAD_KEY_COL2__GPIO4_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__CAN1_TXCAN		(_MX53_PAD_KEY_COL2__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__FEC_MDIO		(_MX53_PAD_KEY_COL2__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__ECSPI1_SS1		(_MX53_PAD_KEY_COL2__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__FEC_RDATA_2		(_MX53_PAD_KEY_COL2__FEC_RDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE		(_MX53_PAD_KEY_COL2__USBPHY1_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__KPP_ROW_2		(_MX53_PAD_KEY_ROW2__KPP_ROW_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__GPIO4_11		(_MX53_PAD_KEY_ROW2__GPIO4_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__CAN1_RXCAN		(_MX53_PAD_KEY_ROW2__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__FEC_MDC		(_MX53_PAD_KEY_ROW2__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__ECSPI1_SS2		(_MX53_PAD_KEY_ROW2__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__FEC_TDATA_2		(_MX53_PAD_KEY_ROW2__FEC_TDATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW2__USBPHY1_RXERROR		(_MX53_PAD_KEY_ROW2__USBPHY1_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__KPP_COL_3		(_MX53_PAD_KEY_COL3__KPP_COL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__GPIO4_12		(_MX53_PAD_KEY_COL3__GPIO4_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__USBOH3_H2_DP		(_MX53_PAD_KEY_COL3__USBOH3_H2_DP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__SPDIF_IN1		(_MX53_PAD_KEY_COL3__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__I2C2_SCL		(_MX53_PAD_KEY_COL3__I2C2_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__ECSPI1_SS3		(_MX53_PAD_KEY_COL3__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__FEC_CRS		(_MX53_PAD_KEY_COL3__FEC_CRS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK		(_MX53_PAD_KEY_COL3__USBPHY1_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__KPP_ROW_3		(_MX53_PAD_KEY_ROW3__KPP_ROW_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__GPIO4_13		(_MX53_PAD_KEY_ROW3__GPIO4_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__USBOH3_H2_DM		(_MX53_PAD_KEY_ROW3__USBOH3_H2_DM | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK		(_MX53_PAD_KEY_ROW3__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__I2C2_SDA		(_MX53_PAD_KEY_ROW3__I2C2_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__OSC32K_32K_OUT		(_MX53_PAD_KEY_ROW3__OSC32K_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__CCM_PLL4_BYP		(_MX53_PAD_KEY_ROW3__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0		(_MX53_PAD_KEY_ROW3__USBPHY1_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__KPP_COL_4		(_MX53_PAD_KEY_COL4__KPP_COL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__GPIO4_14		(_MX53_PAD_KEY_COL4__GPIO4_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__CAN2_TXCAN		(_MX53_PAD_KEY_COL4__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__IPU_SISG_4		(_MX53_PAD_KEY_COL4__IPU_SISG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__UART5_RTS		(_MX53_PAD_KEY_COL4__UART5_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC		(_MX53_PAD_KEY_COL4__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1		(_MX53_PAD_KEY_COL4__USBPHY1_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__KPP_ROW_4		(_MX53_PAD_KEY_ROW4__KPP_ROW_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__GPIO4_15		(_MX53_PAD_KEY_ROW4__GPIO4_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__CAN2_RXCAN		(_MX53_PAD_KEY_ROW4__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__IPU_SISG_5		(_MX53_PAD_KEY_ROW4__IPU_SISG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__UART5_CTS		(_MX53_PAD_KEY_ROW4__UART5_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR		(_MX53_PAD_KEY_ROW4__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID		(_MX53_PAD_KEY_ROW4__USBPHY1_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK		(_MX53_PAD_DI0_DISP_CLK__IPU_DI0_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__GPIO4_16		(_MX53_PAD_DI0_DISP_CLK__GPIO4_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR		(_MX53_PAD_DI0_DISP_CLK__USBOH3_USBH2_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0		(_MX53_PAD_DI0_DISP_CLK__SDMA_DEBUG_CORE_STATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0		(_MX53_PAD_DI0_DISP_CLK__EMI_EMI_DEBUG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID		(_MX53_PAD_DI0_DISP_CLK__USBPHY1_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__IPU_DI0_PIN15		(_MX53_PAD_DI0_PIN15__IPU_DI0_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__GPIO4_17		(_MX53_PAD_DI0_PIN15__GPIO4_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC		(_MX53_PAD_DI0_PIN15__AUDMUX_AUD6_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1		(_MX53_PAD_DI0_PIN15__SDMA_DEBUG_CORE_STATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1		(_MX53_PAD_DI0_PIN15__EMI_EMI_DEBUG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN15__USBPHY1_BVALID		(_MX53_PAD_DI0_PIN15__USBPHY1_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__IPU_DI0_PIN2		(_MX53_PAD_DI0_PIN2__IPU_DI0_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__GPIO4_18		(_MX53_PAD_DI0_PIN2__GPIO4_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD		(_MX53_PAD_DI0_PIN2__AUDMUX_AUD6_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2		(_MX53_PAD_DI0_PIN2__SDMA_DEBUG_CORE_STATE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2		(_MX53_PAD_DI0_PIN2__EMI_EMI_DEBUG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION		(_MX53_PAD_DI0_PIN2__USBPHY1_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__IPU_DI0_PIN3		(_MX53_PAD_DI0_PIN3__IPU_DI0_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__GPIO4_19		(_MX53_PAD_DI0_PIN3__GPIO4_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS		(_MX53_PAD_DI0_PIN3__AUDMUX_AUD6_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3		(_MX53_PAD_DI0_PIN3__SDMA_DEBUG_CORE_STATE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3		(_MX53_PAD_DI0_PIN3__EMI_EMI_DEBUG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN3__USBPHY1_IDDIG		(_MX53_PAD_DI0_PIN3__USBPHY1_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__IPU_DI0_PIN4		(_MX53_PAD_DI0_PIN4__IPU_DI0_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__GPIO4_20		(_MX53_PAD_DI0_PIN4__GPIO4_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD		(_MX53_PAD_DI0_PIN4__AUDMUX_AUD6_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__ESDHC1_WP		(_MX53_PAD_DI0_PIN4__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD		(_MX53_PAD_DI0_PIN4__SDMA_DEBUG_YIELD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4		(_MX53_PAD_DI0_PIN4__EMI_EMI_DEBUG_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT		(_MX53_PAD_DI0_PIN4__USBPHY1_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0		(_MX53_PAD_DISP0_DAT0__IPU_DISP0_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__GPIO4_21		(_MX53_PAD_DISP0_DAT0__GPIO4_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__CSPI_SCLK		(_MX53_PAD_DISP0_DAT0__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0		(_MX53_PAD_DISP0_DAT0__USBOH3_USBH2_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN		(_MX53_PAD_DISP0_DAT0__SDMA_DEBUG_CORE_RUN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5		(_MX53_PAD_DISP0_DAT0__EMI_EMI_DEBUG_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY		(_MX53_PAD_DISP0_DAT0__USBPHY2_TXREADY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1		(_MX53_PAD_DISP0_DAT1__IPU_DISP0_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__GPIO4_22		(_MX53_PAD_DISP0_DAT1__GPIO4_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__CSPI_MOSI		(_MX53_PAD_DISP0_DAT1__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1		(_MX53_PAD_DISP0_DAT1__USBOH3_USBH2_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL		(_MX53_PAD_DISP0_DAT1__SDMA_DEBUG_EVENT_CHANNEL_SEL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6		(_MX53_PAD_DISP0_DAT1__EMI_EMI_DEBUG_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID		(_MX53_PAD_DISP0_DAT1__USBPHY2_RXVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2		(_MX53_PAD_DISP0_DAT2__IPU_DISP0_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__GPIO4_23		(_MX53_PAD_DISP0_DAT2__GPIO4_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__CSPI_MISO		(_MX53_PAD_DISP0_DAT2__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2		(_MX53_PAD_DISP0_DAT2__USBOH3_USBH2_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE		(_MX53_PAD_DISP0_DAT2__SDMA_DEBUG_MODE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7		(_MX53_PAD_DISP0_DAT2__EMI_EMI_DEBUG_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE		(_MX53_PAD_DISP0_DAT2__USBPHY2_RXACTIVE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3		(_MX53_PAD_DISP0_DAT3__IPU_DISP0_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__GPIO4_24		(_MX53_PAD_DISP0_DAT3__GPIO4_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__CSPI_SS0		(_MX53_PAD_DISP0_DAT3__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3		(_MX53_PAD_DISP0_DAT3__USBOH3_USBH2_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR		(_MX53_PAD_DISP0_DAT3__SDMA_DEBUG_BUS_ERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8		(_MX53_PAD_DISP0_DAT3__EMI_EMI_DEBUG_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR		(_MX53_PAD_DISP0_DAT3__USBPHY2_RXERROR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4		(_MX53_PAD_DISP0_DAT4__IPU_DISP0_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__GPIO4_25		(_MX53_PAD_DISP0_DAT4__GPIO4_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__CSPI_SS1		(_MX53_PAD_DISP0_DAT4__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4		(_MX53_PAD_DISP0_DAT4__USBOH3_USBH2_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB		(_MX53_PAD_DISP0_DAT4__SDMA_DEBUG_BUS_RWB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9		(_MX53_PAD_DISP0_DAT4__EMI_EMI_DEBUG_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK		(_MX53_PAD_DISP0_DAT4__USBPHY2_SIECLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5		(_MX53_PAD_DISP0_DAT5__IPU_DISP0_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__GPIO4_26		(_MX53_PAD_DISP0_DAT5__GPIO4_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__CSPI_SS2		(_MX53_PAD_DISP0_DAT5__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5		(_MX53_PAD_DISP0_DAT5__USBOH3_USBH2_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS		(_MX53_PAD_DISP0_DAT5__SDMA_DEBUG_MATCHED_DMBUS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10		(_MX53_PAD_DISP0_DAT5__EMI_EMI_DEBUG_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0		(_MX53_PAD_DISP0_DAT5__USBPHY2_LINESTATE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6		(_MX53_PAD_DISP0_DAT6__IPU_DISP0_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__GPIO4_27		(_MX53_PAD_DISP0_DAT6__GPIO4_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__CSPI_SS3		(_MX53_PAD_DISP0_DAT6__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6		(_MX53_PAD_DISP0_DAT6__USBOH3_USBH2_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE		(_MX53_PAD_DISP0_DAT6__SDMA_DEBUG_RTBUFFER_WRITE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11		(_MX53_PAD_DISP0_DAT6__EMI_EMI_DEBUG_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1		(_MX53_PAD_DISP0_DAT6__USBPHY2_LINESTATE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7		(_MX53_PAD_DISP0_DAT7__IPU_DISP0_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__GPIO4_28		(_MX53_PAD_DISP0_DAT7__GPIO4_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__CSPI_RDY		(_MX53_PAD_DISP0_DAT7__CSPI_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7		(_MX53_PAD_DISP0_DAT7__USBOH3_USBH2_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0		(_MX53_PAD_DISP0_DAT7__SDMA_DEBUG_EVENT_CHANNEL_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12		(_MX53_PAD_DISP0_DAT7__EMI_EMI_DEBUG_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID		(_MX53_PAD_DISP0_DAT7__USBPHY2_VBUSVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8		(_MX53_PAD_DISP0_DAT8__IPU_DISP0_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__GPIO4_29		(_MX53_PAD_DISP0_DAT8__GPIO4_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__PWM1_PWMO		(_MX53_PAD_DISP0_DAT8__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B		(_MX53_PAD_DISP0_DAT8__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1		(_MX53_PAD_DISP0_DAT8__SDMA_DEBUG_EVENT_CHANNEL_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13		(_MX53_PAD_DISP0_DAT8__EMI_EMI_DEBUG_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT8__USBPHY2_AVALID		(_MX53_PAD_DISP0_DAT8__USBPHY2_AVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9		(_MX53_PAD_DISP0_DAT9__IPU_DISP0_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__GPIO4_30		(_MX53_PAD_DISP0_DAT9__GPIO4_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__PWM2_PWMO		(_MX53_PAD_DISP0_DAT9__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B		(_MX53_PAD_DISP0_DAT9__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2		(_MX53_PAD_DISP0_DAT9__SDMA_DEBUG_EVENT_CHANNEL_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14		(_MX53_PAD_DISP0_DAT9__EMI_EMI_DEBUG_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0		(_MX53_PAD_DISP0_DAT9__USBPHY2_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10		(_MX53_PAD_DISP0_DAT10__IPU_DISP0_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__GPIO4_31		(_MX53_PAD_DISP0_DAT10__GPIO4_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP		(_MX53_PAD_DISP0_DAT10__USBOH3_USBH2_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3		(_MX53_PAD_DISP0_DAT10__SDMA_DEBUG_EVENT_CHANNEL_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15		(_MX53_PAD_DISP0_DAT10__EMI_EMI_DEBUG_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1		(_MX53_PAD_DISP0_DAT10__USBPHY2_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11		(_MX53_PAD_DISP0_DAT11__IPU_DISP0_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__GPIO5_5		(_MX53_PAD_DISP0_DAT11__GPIO5_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT		(_MX53_PAD_DISP0_DAT11__USBOH3_USBH2_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4		(_MX53_PAD_DISP0_DAT11__SDMA_DEBUG_EVENT_CHANNEL_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16		(_MX53_PAD_DISP0_DAT11__EMI_EMI_DEBUG_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2		(_MX53_PAD_DISP0_DAT11__USBPHY2_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12		(_MX53_PAD_DISP0_DAT12__IPU_DISP0_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__GPIO5_6		(_MX53_PAD_DISP0_DAT12__GPIO5_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK		(_MX53_PAD_DISP0_DAT12__USBOH3_USBH2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5		(_MX53_PAD_DISP0_DAT12__SDMA_DEBUG_EVENT_CHANNEL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17		(_MX53_PAD_DISP0_DAT12__EMI_EMI_DEBUG_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3		(_MX53_PAD_DISP0_DAT12__USBPHY2_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13		(_MX53_PAD_DISP0_DAT13__IPU_DISP0_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__GPIO5_7		(_MX53_PAD_DISP0_DAT13__GPIO5_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS		(_MX53_PAD_DISP0_DAT13__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0		(_MX53_PAD_DISP0_DAT13__SDMA_DEBUG_EVT_CHN_LINES_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18		(_MX53_PAD_DISP0_DAT13__EMI_EMI_DEBUG_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4		(_MX53_PAD_DISP0_DAT13__USBPHY2_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14		(_MX53_PAD_DISP0_DAT14__IPU_DISP0_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__GPIO5_8		(_MX53_PAD_DISP0_DAT14__GPIO5_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC		(_MX53_PAD_DISP0_DAT14__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1		(_MX53_PAD_DISP0_DAT14__SDMA_DEBUG_EVT_CHN_LINES_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19		(_MX53_PAD_DISP0_DAT14__EMI_EMI_DEBUG_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5		(_MX53_PAD_DISP0_DAT14__USBPHY2_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15		(_MX53_PAD_DISP0_DAT15__IPU_DISP0_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__GPIO5_9		(_MX53_PAD_DISP0_DAT15__GPIO5_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__ECSPI1_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__ECSPI2_SS1		(_MX53_PAD_DISP0_DAT15__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2		(_MX53_PAD_DISP0_DAT15__SDMA_DEBUG_EVT_CHN_LINES_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20		(_MX53_PAD_DISP0_DAT15__EMI_EMI_DEBUG_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6		(_MX53_PAD_DISP0_DAT15__USBPHY2_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16		(_MX53_PAD_DISP0_DAT16__IPU_DISP0_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__GPIO5_10		(_MX53_PAD_DISP0_DAT16__GPIO5_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__ECSPI2_MOSI		(_MX53_PAD_DISP0_DAT16__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC		(_MX53_PAD_DISP0_DAT16__AUDMUX_AUD5_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0		(_MX53_PAD_DISP0_DAT16__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3		(_MX53_PAD_DISP0_DAT16__SDMA_DEBUG_EVT_CHN_LINES_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21		(_MX53_PAD_DISP0_DAT16__EMI_EMI_DEBUG_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7		(_MX53_PAD_DISP0_DAT16__USBPHY2_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17		(_MX53_PAD_DISP0_DAT17__IPU_DISP0_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__GPIO5_11		(_MX53_PAD_DISP0_DAT17__GPIO5_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__ECSPI2_MISO		(_MX53_PAD_DISP0_DAT17__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD		(_MX53_PAD_DISP0_DAT17__AUDMUX_AUD5_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1		(_MX53_PAD_DISP0_DAT17__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4		(_MX53_PAD_DISP0_DAT17__SDMA_DEBUG_EVT_CHN_LINES_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22		(_MX53_PAD_DISP0_DAT17__EMI_EMI_DEBUG_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18		(_MX53_PAD_DISP0_DAT18__IPU_DISP0_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__GPIO5_12		(_MX53_PAD_DISP0_DAT18__GPIO5_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__ECSPI2_SS0		(_MX53_PAD_DISP0_DAT18__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD5_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS		(_MX53_PAD_DISP0_DAT18__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5		(_MX53_PAD_DISP0_DAT18__SDMA_DEBUG_EVT_CHN_LINES_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23		(_MX53_PAD_DISP0_DAT18__EMI_EMI_DEBUG_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2		(_MX53_PAD_DISP0_DAT18__EMI_WEIM_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19		(_MX53_PAD_DISP0_DAT19__IPU_DISP0_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__GPIO5_13		(_MX53_PAD_DISP0_DAT19__GPIO5_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__ECSPI2_SCLK		(_MX53_PAD_DISP0_DAT19__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD5_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC		(_MX53_PAD_DISP0_DAT19__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6		(_MX53_PAD_DISP0_DAT19__SDMA_DEBUG_EVT_CHN_LINES_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24		(_MX53_PAD_DISP0_DAT19__EMI_EMI_DEBUG_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3		(_MX53_PAD_DISP0_DAT19__EMI_WEIM_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20		(_MX53_PAD_DISP0_DAT20__IPU_DISP0_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__GPIO5_14		(_MX53_PAD_DISP0_DAT20__GPIO5_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__ECSPI1_SCLK		(_MX53_PAD_DISP0_DAT20__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC		(_MX53_PAD_DISP0_DAT20__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7		(_MX53_PAD_DISP0_DAT20__SDMA_DEBUG_EVT_CHN_LINES_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25		(_MX53_PAD_DISP0_DAT20__EMI_EMI_DEBUG_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT20__SATA_PHY_TDI		(_MX53_PAD_DISP0_DAT20__SATA_PHY_TDI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21		(_MX53_PAD_DISP0_DAT21__IPU_DISP0_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__GPIO5_15		(_MX53_PAD_DISP0_DAT21__GPIO5_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__ECSPI1_MOSI		(_MX53_PAD_DISP0_DAT21__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD		(_MX53_PAD_DISP0_DAT21__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0		(_MX53_PAD_DISP0_DAT21__SDMA_DEBUG_BUS_DEVICE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26		(_MX53_PAD_DISP0_DAT21__EMI_EMI_DEBUG_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT21__SATA_PHY_TDO		(_MX53_PAD_DISP0_DAT21__SATA_PHY_TDO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22		(_MX53_PAD_DISP0_DAT22__IPU_DISP0_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__GPIO5_16		(_MX53_PAD_DISP0_DAT22__GPIO5_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__ECSPI1_MISO		(_MX53_PAD_DISP0_DAT22__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS		(_MX53_PAD_DISP0_DAT22__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1		(_MX53_PAD_DISP0_DAT22__SDMA_DEBUG_BUS_DEVICE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27		(_MX53_PAD_DISP0_DAT22__EMI_EMI_DEBUG_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT22__SATA_PHY_TCK		(_MX53_PAD_DISP0_DAT22__SATA_PHY_TCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23		(_MX53_PAD_DISP0_DAT23__IPU_DISP0_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__GPIO5_17		(_MX53_PAD_DISP0_DAT23__GPIO5_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__ECSPI1_SS0		(_MX53_PAD_DISP0_DAT23__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD		(_MX53_PAD_DISP0_DAT23__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2		(_MX53_PAD_DISP0_DAT23__SDMA_DEBUG_BUS_DEVICE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28		(_MX53_PAD_DISP0_DAT23__EMI_EMI_DEBUG_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_DISP0_DAT23__SATA_PHY_TMS		(_MX53_PAD_DISP0_DAT23__SATA_PHY_TMS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK		(_MX53_PAD_CSI0_PIXCLK__IPU_CSI0_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__GPIO5_18		(_MX53_PAD_CSI0_PIXCLK__GPIO5_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0		(_MX53_PAD_CSI0_PIXCLK__SDMA_DEBUG_PC_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29		(_MX53_PAD_CSI0_PIXCLK__EMI_EMI_DEBUG_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC		(_MX53_PAD_CSI0_MCLK__IPU_CSI0_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__GPIO5_19		(_MX53_PAD_CSI0_MCLK__GPIO5_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK		(_MX53_PAD_CSI0_MCLK__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1		(_MX53_PAD_CSI0_MCLK__SDMA_DEBUG_PC_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30		(_MX53_PAD_CSI0_MCLK__EMI_EMI_DEBUG_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_MCLK__TPIU_TRCTL		(_MX53_PAD_CSI0_MCLK__TPIU_TRCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN		(_MX53_PAD_CSI0_DATA_EN__IPU_CSI0_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__GPIO5_20		(_MX53_PAD_CSI0_DATA_EN__GPIO5_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2		(_MX53_PAD_CSI0_DATA_EN__SDMA_DEBUG_PC_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31		(_MX53_PAD_CSI0_DATA_EN__EMI_EMI_DEBUG_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK		(_MX53_PAD_CSI0_DATA_EN__TPIU_TRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC		(_MX53_PAD_CSI0_VSYNC__IPU_CSI0_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__GPIO5_21		(_MX53_PAD_CSI0_VSYNC__GPIO5_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3		(_MX53_PAD_CSI0_VSYNC__SDMA_DEBUG_PC_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32		(_MX53_PAD_CSI0_VSYNC__EMI_EMI_DEBUG_32 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0		(_MX53_PAD_CSI0_VSYNC__TPIU_TRACE_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4		(_MX53_PAD_CSI0_DAT4__IPU_CSI0_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__GPIO5_22		(_MX53_PAD_CSI0_DAT4__GPIO5_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__KPP_COL_5		(_MX53_PAD_CSI0_DAT4__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__ECSPI1_SCLK		(_MX53_PAD_CSI0_DAT4__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP		(_MX53_PAD_CSI0_DAT4__USBOH3_USBH3_STP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC		(_MX53_PAD_CSI0_DAT4__AUDMUX_AUD3_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33		(_MX53_PAD_CSI0_DAT4__EMI_EMI_DEBUG_33 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT4__TPIU_TRACE_1		(_MX53_PAD_CSI0_DAT4__TPIU_TRACE_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5		(_MX53_PAD_CSI0_DAT5__IPU_CSI0_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__GPIO5_23		(_MX53_PAD_CSI0_DAT5__GPIO5_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__KPP_ROW_5		(_MX53_PAD_CSI0_DAT5__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__ECSPI1_MOSI		(_MX53_PAD_CSI0_DAT5__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT		(_MX53_PAD_CSI0_DAT5__USBOH3_USBH3_NXT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD		(_MX53_PAD_CSI0_DAT5__AUDMUX_AUD3_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34		(_MX53_PAD_CSI0_DAT5__EMI_EMI_DEBUG_34 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT5__TPIU_TRACE_2		(_MX53_PAD_CSI0_DAT5__TPIU_TRACE_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6		(_MX53_PAD_CSI0_DAT6__IPU_CSI0_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__GPIO5_24		(_MX53_PAD_CSI0_DAT6__GPIO5_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__KPP_COL_6		(_MX53_PAD_CSI0_DAT6__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__ECSPI1_MISO		(_MX53_PAD_CSI0_DAT6__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK		(_MX53_PAD_CSI0_DAT6__USBOH3_USBH3_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS		(_MX53_PAD_CSI0_DAT6__AUDMUX_AUD3_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35		(_MX53_PAD_CSI0_DAT6__EMI_EMI_DEBUG_35 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT6__TPIU_TRACE_3		(_MX53_PAD_CSI0_DAT6__TPIU_TRACE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7		(_MX53_PAD_CSI0_DAT7__IPU_CSI0_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__GPIO5_25		(_MX53_PAD_CSI0_DAT7__GPIO5_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__KPP_ROW_6		(_MX53_PAD_CSI0_DAT7__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__ECSPI1_SS0		(_MX53_PAD_CSI0_DAT7__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR		(_MX53_PAD_CSI0_DAT7__USBOH3_USBH3_DIR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD		(_MX53_PAD_CSI0_DAT7__AUDMUX_AUD3_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36		(_MX53_PAD_CSI0_DAT7__EMI_EMI_DEBUG_36 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT7__TPIU_TRACE_4		(_MX53_PAD_CSI0_DAT7__TPIU_TRACE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8		(_MX53_PAD_CSI0_DAT8__IPU_CSI0_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__GPIO5_26		(_MX53_PAD_CSI0_DAT8__GPIO5_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__KPP_COL_7		(_MX53_PAD_CSI0_DAT8__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__ECSPI2_SCLK		(_MX53_PAD_CSI0_DAT8__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC		(_MX53_PAD_CSI0_DAT8__USBOH3_USBH3_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__I2C1_SDA		(_MX53_PAD_CSI0_DAT8__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37		(_MX53_PAD_CSI0_DAT8__EMI_EMI_DEBUG_37 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT8__TPIU_TRACE_5		(_MX53_PAD_CSI0_DAT8__TPIU_TRACE_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9		(_MX53_PAD_CSI0_DAT9__IPU_CSI0_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__GPIO5_27		(_MX53_PAD_CSI0_DAT9__GPIO5_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__KPP_ROW_7		(_MX53_PAD_CSI0_DAT9__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__ECSPI2_MOSI		(_MX53_PAD_CSI0_DAT9__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR		(_MX53_PAD_CSI0_DAT9__USBOH3_USBH3_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__I2C1_SCL		(_MX53_PAD_CSI0_DAT9__I2C1_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38		(_MX53_PAD_CSI0_DAT9__EMI_EMI_DEBUG_38 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT9__TPIU_TRACE_6		(_MX53_PAD_CSI0_DAT9__TPIU_TRACE_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10		(_MX53_PAD_CSI0_DAT10__IPU_CSI0_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__GPIO5_28		(_MX53_PAD_CSI0_DAT10__GPIO5_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__UART1_TXD_MUX		(_MX53_PAD_CSI0_DAT10__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__ECSPI2_MISO		(_MX53_PAD_CSI0_DAT10__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC		(_MX53_PAD_CSI0_DAT10__AUDMUX_AUD3_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4		(_MX53_PAD_CSI0_DAT10__SDMA_DEBUG_PC_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39		(_MX53_PAD_CSI0_DAT10__EMI_EMI_DEBUG_39 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT10__TPIU_TRACE_7		(_MX53_PAD_CSI0_DAT10__TPIU_TRACE_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11		(_MX53_PAD_CSI0_DAT11__IPU_CSI0_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__GPIO5_29		(_MX53_PAD_CSI0_DAT11__GPIO5_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__UART1_RXD_MUX		(_MX53_PAD_CSI0_DAT11__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__ECSPI2_SS0		(_MX53_PAD_CSI0_DAT11__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS		(_MX53_PAD_CSI0_DAT11__AUDMUX_AUD3_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5		(_MX53_PAD_CSI0_DAT11__SDMA_DEBUG_PC_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40		(_MX53_PAD_CSI0_DAT11__EMI_EMI_DEBUG_40 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT11__TPIU_TRACE_8		(_MX53_PAD_CSI0_DAT11__TPIU_TRACE_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12		(_MX53_PAD_CSI0_DAT12__IPU_CSI0_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__GPIO5_30		(_MX53_PAD_CSI0_DAT12__GPIO5_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__UART4_TXD_MUX		(_MX53_PAD_CSI0_DAT12__UART4_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0		(_MX53_PAD_CSI0_DAT12__USBOH3_USBH3_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6		(_MX53_PAD_CSI0_DAT12__SDMA_DEBUG_PC_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41		(_MX53_PAD_CSI0_DAT12__EMI_EMI_DEBUG_41 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT12__TPIU_TRACE_9		(_MX53_PAD_CSI0_DAT12__TPIU_TRACE_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13		(_MX53_PAD_CSI0_DAT13__IPU_CSI0_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__GPIO5_31		(_MX53_PAD_CSI0_DAT13__GPIO5_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__UART4_RXD_MUX		(_MX53_PAD_CSI0_DAT13__UART4_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1		(_MX53_PAD_CSI0_DAT13__USBOH3_USBH3_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7		(_MX53_PAD_CSI0_DAT13__SDMA_DEBUG_PC_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42		(_MX53_PAD_CSI0_DAT13__EMI_EMI_DEBUG_42 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT13__TPIU_TRACE_10		(_MX53_PAD_CSI0_DAT13__TPIU_TRACE_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14		(_MX53_PAD_CSI0_DAT14__IPU_CSI0_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__GPIO6_0		(_MX53_PAD_CSI0_DAT14__GPIO6_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__UART5_TXD_MUX		(_MX53_PAD_CSI0_DAT14__UART5_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2		(_MX53_PAD_CSI0_DAT14__USBOH3_USBH3_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8		(_MX53_PAD_CSI0_DAT14__SDMA_DEBUG_PC_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43		(_MX53_PAD_CSI0_DAT14__EMI_EMI_DEBUG_43 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT14__TPIU_TRACE_11		(_MX53_PAD_CSI0_DAT14__TPIU_TRACE_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15		(_MX53_PAD_CSI0_DAT15__IPU_CSI0_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__GPIO6_1		(_MX53_PAD_CSI0_DAT15__GPIO6_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__UART5_RXD_MUX		(_MX53_PAD_CSI0_DAT15__UART5_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3		(_MX53_PAD_CSI0_DAT15__USBOH3_USBH3_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9		(_MX53_PAD_CSI0_DAT15__SDMA_DEBUG_PC_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44		(_MX53_PAD_CSI0_DAT15__EMI_EMI_DEBUG_44 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT15__TPIU_TRACE_12		(_MX53_PAD_CSI0_DAT15__TPIU_TRACE_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16		(_MX53_PAD_CSI0_DAT16__IPU_CSI0_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__GPIO6_2		(_MX53_PAD_CSI0_DAT16__GPIO6_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__UART4_RTS		(_MX53_PAD_CSI0_DAT16__UART4_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4		(_MX53_PAD_CSI0_DAT16__USBOH3_USBH3_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10		(_MX53_PAD_CSI0_DAT16__SDMA_DEBUG_PC_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45		(_MX53_PAD_CSI0_DAT16__EMI_EMI_DEBUG_45 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT16__TPIU_TRACE_13		(_MX53_PAD_CSI0_DAT16__TPIU_TRACE_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17		(_MX53_PAD_CSI0_DAT17__IPU_CSI0_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__GPIO6_3		(_MX53_PAD_CSI0_DAT17__GPIO6_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__UART4_CTS		(_MX53_PAD_CSI0_DAT17__UART4_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5		(_MX53_PAD_CSI0_DAT17__USBOH3_USBH3_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11		(_MX53_PAD_CSI0_DAT17__SDMA_DEBUG_PC_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46		(_MX53_PAD_CSI0_DAT17__EMI_EMI_DEBUG_46 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT17__TPIU_TRACE_14		(_MX53_PAD_CSI0_DAT17__TPIU_TRACE_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18		(_MX53_PAD_CSI0_DAT18__IPU_CSI0_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__GPIO6_4		(_MX53_PAD_CSI0_DAT18__GPIO6_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__UART5_RTS		(_MX53_PAD_CSI0_DAT18__UART5_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6		(_MX53_PAD_CSI0_DAT18__USBOH3_USBH3_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12		(_MX53_PAD_CSI0_DAT18__SDMA_DEBUG_PC_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47		(_MX53_PAD_CSI0_DAT18__EMI_EMI_DEBUG_47 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT18__TPIU_TRACE_15		(_MX53_PAD_CSI0_DAT18__TPIU_TRACE_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19		(_MX53_PAD_CSI0_DAT19__IPU_CSI0_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__GPIO6_5		(_MX53_PAD_CSI0_DAT19__GPIO6_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__UART5_CTS		(_MX53_PAD_CSI0_DAT19__UART5_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7		(_MX53_PAD_CSI0_DAT19__USBOH3_USBH3_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13		(_MX53_PAD_CSI0_DAT19__SDMA_DEBUG_PC_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48		(_MX53_PAD_CSI0_DAT19__EMI_EMI_DEBUG_48 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK		(_MX53_PAD_CSI0_DAT19__USBPHY2_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__EMI_WEIM_A_25		(_MX53_PAD_EIM_A25__EMI_WEIM_A_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__GPIO5_2		(_MX53_PAD_EIM_A25__GPIO5_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__ECSPI2_RDY		(_MX53_PAD_EIM_A25__ECSPI2_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__IPU_DI1_PIN12		(_MX53_PAD_EIM_A25__IPU_DI1_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__CSPI_SS1		(_MX53_PAD_EIM_A25__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__IPU_DI0_D1_CS		(_MX53_PAD_EIM_A25__IPU_DI0_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A25__USBPHY1_BISTOK		(_MX53_PAD_EIM_A25__USBPHY1_BISTOK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__EMI_WEIM_EB_2		(_MX53_PAD_EIM_EB2__EMI_WEIM_EB_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__GPIO2_30		(_MX53_PAD_EIM_EB2__GPIO2_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_EB2__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS		(_MX53_PAD_EIM_EB2__IPU_SER_DISP1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__ECSPI1_SS0		(_MX53_PAD_EIM_EB2__ECSPI1_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB2__I2C2_SCL		(_MX53_PAD_EIM_EB2__I2C2_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__EMI_WEIM_D_16		(_MX53_PAD_EIM_D16__EMI_WEIM_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__GPIO3_16		(_MX53_PAD_EIM_D16__GPIO3_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__IPU_DI0_PIN5		(_MX53_PAD_EIM_D16__IPU_DI0_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK		(_MX53_PAD_EIM_D16__IPU_DISPB1_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__ECSPI1_SCLK		(_MX53_PAD_EIM_D16__ECSPI1_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D16__I2C2_SDA		(_MX53_PAD_EIM_D16__I2C2_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__EMI_WEIM_D_17		(_MX53_PAD_EIM_D17__EMI_WEIM_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__GPIO3_17		(_MX53_PAD_EIM_D17__GPIO3_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__IPU_DI0_PIN6		(_MX53_PAD_EIM_D17__IPU_DI0_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN		(_MX53_PAD_EIM_D17__IPU_DISPB1_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__ECSPI1_MISO		(_MX53_PAD_EIM_D17__ECSPI1_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D17__I2C3_SCL		(_MX53_PAD_EIM_D17__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__EMI_WEIM_D_18		(_MX53_PAD_EIM_D18__EMI_WEIM_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__GPIO3_18		(_MX53_PAD_EIM_D18__GPIO3_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__IPU_DI0_PIN7		(_MX53_PAD_EIM_D18__IPU_DI0_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO		(_MX53_PAD_EIM_D18__IPU_DISPB1_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__ECSPI1_MOSI		(_MX53_PAD_EIM_D18__ECSPI1_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__I2C3_SDA		(_MX53_PAD_EIM_D18__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D18__IPU_DI1_D0_CS		(_MX53_PAD_EIM_D18__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__EMI_WEIM_D_19		(_MX53_PAD_EIM_D19__EMI_WEIM_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__GPIO3_19		(_MX53_PAD_EIM_D19__GPIO3_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__IPU_DI0_PIN8		(_MX53_PAD_EIM_D19__IPU_DI0_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS		(_MX53_PAD_EIM_D19__IPU_DISPB1_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__ECSPI1_SS1		(_MX53_PAD_EIM_D19__ECSPI1_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__EPIT1_EPITO		(_MX53_PAD_EIM_D19__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__UART1_CTS		(_MX53_PAD_EIM_D19__UART1_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D19__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D19__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__EMI_WEIM_D_20		(_MX53_PAD_EIM_D20__EMI_WEIM_D_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__GPIO3_20		(_MX53_PAD_EIM_D20__GPIO3_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__IPU_DI0_PIN16		(_MX53_PAD_EIM_D20__IPU_DI0_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__IPU_SER_DISP0_CS		(_MX53_PAD_EIM_D20__IPU_SER_DISP0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__CSPI_SS0		(_MX53_PAD_EIM_D20__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__EPIT2_EPITO		(_MX53_PAD_EIM_D20__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__UART1_RTS		(_MX53_PAD_EIM_D20__UART1_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D20__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D20__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__EMI_WEIM_D_21		(_MX53_PAD_EIM_D21__EMI_WEIM_D_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__GPIO3_21		(_MX53_PAD_EIM_D21__GPIO3_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__IPU_DI0_PIN17		(_MX53_PAD_EIM_D21__IPU_DI0_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK		(_MX53_PAD_EIM_D21__IPU_DISPB0_SER_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__CSPI_SCLK		(_MX53_PAD_EIM_D21__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__I2C1_SCL		(_MX53_PAD_EIM_D21__I2C1_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D21__USBOH3_USBOTG_OC		(_MX53_PAD_EIM_D21__USBOH3_USBOTG_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__EMI_WEIM_D_22		(_MX53_PAD_EIM_D22__EMI_WEIM_D_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__GPIO3_22		(_MX53_PAD_EIM_D22__GPIO3_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__IPU_DI0_PIN1		(_MX53_PAD_EIM_D22__IPU_DI0_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN		(_MX53_PAD_EIM_D22__IPU_DISPB0_SER_DIN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__CSPI_MISO		(_MX53_PAD_EIM_D22__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR		(_MX53_PAD_EIM_D22__USBOH3_USBOTG_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__EMI_WEIM_D_23		(_MX53_PAD_EIM_D23__EMI_WEIM_D_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__GPIO3_23		(_MX53_PAD_EIM_D23__GPIO3_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__UART3_CTS		(_MX53_PAD_EIM_D23__UART3_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__UART1_DCD		(_MX53_PAD_EIM_D23__UART1_DCD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_DI0_D0_CS		(_MX53_PAD_EIM_D23__IPU_DI0_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN2		(_MX53_PAD_EIM_D23__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_D23__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D23__IPU_DI1_PIN14		(_MX53_PAD_EIM_D23__IPU_DI1_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__EMI_WEIM_EB_3		(_MX53_PAD_EIM_EB3__EMI_WEIM_EB_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__GPIO2_31		(_MX53_PAD_EIM_EB3__GPIO2_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__UART3_RTS		(_MX53_PAD_EIM_EB3__UART3_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__UART1_RI		(_MX53_PAD_EIM_EB3__UART1_RI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN3		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_EB3__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB3__IPU_DI1_PIN16		(_MX53_PAD_EIM_EB3__IPU_DI1_PIN16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__EMI_WEIM_D_24		(_MX53_PAD_EIM_D24__EMI_WEIM_D_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__GPIO3_24		(_MX53_PAD_EIM_D24__GPIO3_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__UART3_TXD_MUX		(_MX53_PAD_EIM_D24__UART3_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__ECSPI1_SS2		(_MX53_PAD_EIM_D24__ECSPI1_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__CSPI_SS2		(_MX53_PAD_EIM_D24__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS		(_MX53_PAD_EIM_D24__AUDMUX_AUD5_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__ECSPI2_SS2		(_MX53_PAD_EIM_D24__ECSPI2_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D24__UART1_DTR		(_MX53_PAD_EIM_D24__UART1_DTR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__EMI_WEIM_D_25		(_MX53_PAD_EIM_D25__EMI_WEIM_D_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__GPIO3_25		(_MX53_PAD_EIM_D25__GPIO3_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__UART3_RXD_MUX		(_MX53_PAD_EIM_D25__UART3_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__ECSPI1_SS3		(_MX53_PAD_EIM_D25__ECSPI1_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__CSPI_SS3		(_MX53_PAD_EIM_D25__CSPI_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC		(_MX53_PAD_EIM_D25__AUDMUX_AUD5_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__ECSPI2_SS3		(_MX53_PAD_EIM_D25__ECSPI2_SS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D25__UART1_DSR		(_MX53_PAD_EIM_D25__UART1_DSR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__EMI_WEIM_D_26		(_MX53_PAD_EIM_D26__EMI_WEIM_D_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__GPIO3_26		(_MX53_PAD_EIM_D26__GPIO3_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__UART2_TXD_MUX		(_MX53_PAD_EIM_D26__UART2_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__FIRI_RXD		(_MX53_PAD_EIM_D26__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_CSI0_D_1		(_MX53_PAD_EIM_D26__IPU_CSI0_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_DI1_PIN11		(_MX53_PAD_EIM_D26__IPU_DI1_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_SISG_2		(_MX53_PAD_EIM_D26__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D26__IPU_DISP1_DAT_22		(_MX53_PAD_EIM_D26__IPU_DISP1_DAT_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__EMI_WEIM_D_27		(_MX53_PAD_EIM_D27__EMI_WEIM_D_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__GPIO3_27		(_MX53_PAD_EIM_D27__GPIO3_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__UART2_RXD_MUX		(_MX53_PAD_EIM_D27__UART2_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__FIRI_TXD		(_MX53_PAD_EIM_D27__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_CSI0_D_0		(_MX53_PAD_EIM_D27__IPU_CSI0_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_DI1_PIN13		(_MX53_PAD_EIM_D27__IPU_DI1_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_SISG_3		(_MX53_PAD_EIM_D27__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D27__IPU_DISP1_DAT_23		(_MX53_PAD_EIM_D27__IPU_DISP1_DAT_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__EMI_WEIM_D_28		(_MX53_PAD_EIM_D28__EMI_WEIM_D_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__GPIO3_28		(_MX53_PAD_EIM_D28__GPIO3_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__UART2_CTS		(_MX53_PAD_EIM_D28__UART2_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO		(_MX53_PAD_EIM_D28__IPU_DISPB0_SER_DIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__CSPI_MOSI		(_MX53_PAD_EIM_D28__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__I2C1_SDA		(_MX53_PAD_EIM_D28__I2C1_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__IPU_EXT_TRIG		(_MX53_PAD_EIM_D28__IPU_EXT_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D28__IPU_DI0_PIN13		(_MX53_PAD_EIM_D28__IPU_DI0_PIN13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__EMI_WEIM_D_29		(_MX53_PAD_EIM_D29__EMI_WEIM_D_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__GPIO3_29		(_MX53_PAD_EIM_D29__GPIO3_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__UART2_RTS		(_MX53_PAD_EIM_D29__UART2_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS		(_MX53_PAD_EIM_D29__IPU_DISPB0_SER_RS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__CSPI_SS0		(_MX53_PAD_EIM_D29__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_DI1_PIN15		(_MX53_PAD_EIM_D29__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_D29__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D29__IPU_DI0_PIN14		(_MX53_PAD_EIM_D29__IPU_DI0_PIN14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__EMI_WEIM_D_30		(_MX53_PAD_EIM_D30__EMI_WEIM_D_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__GPIO3_30		(_MX53_PAD_EIM_D30__GPIO3_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__UART3_CTS		(_MX53_PAD_EIM_D30__UART3_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__IPU_CSI0_D_3		(_MX53_PAD_EIM_D30__IPU_CSI0_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__IPU_DI0_PIN11		(_MX53_PAD_EIM_D30__IPU_DI0_PIN11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__IPU_DISP1_DAT_21		(_MX53_PAD_EIM_D30__IPU_DISP1_DAT_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__USBOH3_USBH1_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D30__USBOH3_USBH2_OC		(_MX53_PAD_EIM_D30__USBOH3_USBH2_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__EMI_WEIM_D_31		(_MX53_PAD_EIM_D31__EMI_WEIM_D_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__GPIO3_31		(_MX53_PAD_EIM_D31__GPIO3_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__UART3_RTS		(_MX53_PAD_EIM_D31__UART3_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__IPU_CSI0_D_2		(_MX53_PAD_EIM_D31__IPU_CSI0_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__IPU_DI0_PIN12		(_MX53_PAD_EIM_D31__IPU_DI0_PIN12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__IPU_DISP1_DAT_20		(_MX53_PAD_EIM_D31__IPU_DISP1_DAT_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__USBOH3_USBH1_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_D31__USBOH3_USBH2_PWR		(_MX53_PAD_EIM_D31__USBOH3_USBH2_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__EMI_WEIM_A_24		(_MX53_PAD_EIM_A24__EMI_WEIM_A_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__GPIO5_4		(_MX53_PAD_EIM_A24__GPIO5_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__IPU_DISP1_DAT_19		(_MX53_PAD_EIM_A24__IPU_DISP1_DAT_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__IPU_CSI1_D_19		(_MX53_PAD_EIM_A24__IPU_CSI1_D_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__IPU_SISG_2		(_MX53_PAD_EIM_A24__IPU_SISG_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A24__USBPHY2_BVALID		(_MX53_PAD_EIM_A24__USBPHY2_BVALID | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__EMI_WEIM_A_23		(_MX53_PAD_EIM_A23__EMI_WEIM_A_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__GPIO6_6		(_MX53_PAD_EIM_A23__GPIO6_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__IPU_DISP1_DAT_18		(_MX53_PAD_EIM_A23__IPU_DISP1_DAT_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__IPU_CSI1_D_18		(_MX53_PAD_EIM_A23__IPU_CSI1_D_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__IPU_SISG_3		(_MX53_PAD_EIM_A23__IPU_SISG_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A23__USBPHY2_ENDSESSION		(_MX53_PAD_EIM_A23__USBPHY2_ENDSESSION | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__EMI_WEIM_A_22		(_MX53_PAD_EIM_A22__EMI_WEIM_A_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__GPIO2_16		(_MX53_PAD_EIM_A22__GPIO2_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__IPU_DISP1_DAT_17		(_MX53_PAD_EIM_A22__IPU_DISP1_DAT_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__IPU_CSI1_D_17		(_MX53_PAD_EIM_A22__IPU_CSI1_D_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A22__SRC_BT_CFG1_7		(_MX53_PAD_EIM_A22__SRC_BT_CFG1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__EMI_WEIM_A_21		(_MX53_PAD_EIM_A21__EMI_WEIM_A_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__GPIO2_17		(_MX53_PAD_EIM_A21__GPIO2_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__IPU_DISP1_DAT_16		(_MX53_PAD_EIM_A21__IPU_DISP1_DAT_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__IPU_CSI1_D_16		(_MX53_PAD_EIM_A21__IPU_CSI1_D_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A21__SRC_BT_CFG1_6		(_MX53_PAD_EIM_A21__SRC_BT_CFG1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__EMI_WEIM_A_20		(_MX53_PAD_EIM_A20__EMI_WEIM_A_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__GPIO2_18		(_MX53_PAD_EIM_A20__GPIO2_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__IPU_DISP1_DAT_15		(_MX53_PAD_EIM_A20__IPU_DISP1_DAT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__IPU_CSI1_D_15		(_MX53_PAD_EIM_A20__IPU_CSI1_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A20__SRC_BT_CFG1_5		(_MX53_PAD_EIM_A20__SRC_BT_CFG1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__EMI_WEIM_A_19		(_MX53_PAD_EIM_A19__EMI_WEIM_A_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__GPIO2_19		(_MX53_PAD_EIM_A19__GPIO2_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__IPU_DISP1_DAT_14		(_MX53_PAD_EIM_A19__IPU_DISP1_DAT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__IPU_CSI1_D_14		(_MX53_PAD_EIM_A19__IPU_CSI1_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A19__SRC_BT_CFG1_4		(_MX53_PAD_EIM_A19__SRC_BT_CFG1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__EMI_WEIM_A_18		(_MX53_PAD_EIM_A18__EMI_WEIM_A_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__GPIO2_20		(_MX53_PAD_EIM_A18__GPIO2_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__IPU_DISP1_DAT_13		(_MX53_PAD_EIM_A18__IPU_DISP1_DAT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__IPU_CSI1_D_13		(_MX53_PAD_EIM_A18__IPU_CSI1_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A18__SRC_BT_CFG1_3		(_MX53_PAD_EIM_A18__SRC_BT_CFG1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__EMI_WEIM_A_17		(_MX53_PAD_EIM_A17__EMI_WEIM_A_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__GPIO2_21		(_MX53_PAD_EIM_A17__GPIO2_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__IPU_DISP1_DAT_12		(_MX53_PAD_EIM_A17__IPU_DISP1_DAT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__IPU_CSI1_D_12		(_MX53_PAD_EIM_A17__IPU_CSI1_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A17__SRC_BT_CFG1_2		(_MX53_PAD_EIM_A17__SRC_BT_CFG1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__EMI_WEIM_A_16		(_MX53_PAD_EIM_A16__EMI_WEIM_A_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__GPIO2_22		(_MX53_PAD_EIM_A16__GPIO2_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK		(_MX53_PAD_EIM_A16__IPU_DI1_DISP_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK		(_MX53_PAD_EIM_A16__IPU_CSI1_PIXCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_A16__SRC_BT_CFG1_1		(_MX53_PAD_EIM_A16__SRC_BT_CFG1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__EMI_WEIM_CS_0		(_MX53_PAD_EIM_CS0__EMI_WEIM_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__GPIO2_23		(_MX53_PAD_EIM_CS0__GPIO2_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__ECSPI2_SCLK		(_MX53_PAD_EIM_CS0__ECSPI2_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS0__IPU_DI1_PIN5		(_MX53_PAD_EIM_CS0__IPU_DI1_PIN5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__EMI_WEIM_CS_1		(_MX53_PAD_EIM_CS1__EMI_WEIM_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__GPIO2_24		(_MX53_PAD_EIM_CS1__GPIO2_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__ECSPI2_MOSI		(_MX53_PAD_EIM_CS1__ECSPI2_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_CS1__IPU_DI1_PIN6		(_MX53_PAD_EIM_CS1__IPU_DI1_PIN6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__EMI_WEIM_OE		(_MX53_PAD_EIM_OE__EMI_WEIM_OE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__GPIO2_25		(_MX53_PAD_EIM_OE__GPIO2_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__ECSPI2_MISO		(_MX53_PAD_EIM_OE__ECSPI2_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__IPU_DI1_PIN7		(_MX53_PAD_EIM_OE__IPU_DI1_PIN7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_OE__USBPHY2_IDDIG		(_MX53_PAD_EIM_OE__USBPHY2_IDDIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__EMI_WEIM_RW		(_MX53_PAD_EIM_RW__EMI_WEIM_RW | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__GPIO2_26		(_MX53_PAD_EIM_RW__GPIO2_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__ECSPI2_SS0		(_MX53_PAD_EIM_RW__ECSPI2_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__IPU_DI1_PIN8		(_MX53_PAD_EIM_RW__IPU_DI1_PIN8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT		(_MX53_PAD_EIM_RW__USBPHY2_HOSTDISCONNECT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__EMI_WEIM_LBA		(_MX53_PAD_EIM_LBA__EMI_WEIM_LBA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__GPIO2_27		(_MX53_PAD_EIM_LBA__GPIO2_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__ECSPI2_SS1		(_MX53_PAD_EIM_LBA__ECSPI2_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__IPU_DI1_PIN17		(_MX53_PAD_EIM_LBA__IPU_DI1_PIN17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_LBA__SRC_BT_CFG1_0		(_MX53_PAD_EIM_LBA__SRC_BT_CFG1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__EMI_WEIM_EB_0		(_MX53_PAD_EIM_EB0__EMI_WEIM_EB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__GPIO2_28		(_MX53_PAD_EIM_EB0__GPIO2_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11		(_MX53_PAD_EIM_EB0__IPU_DISP1_DAT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__IPU_CSI1_D_11		(_MX53_PAD_EIM_EB0__IPU_CSI1_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__GPC_PMIC_RDY		(_MX53_PAD_EIM_EB0__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB0__SRC_BT_CFG2_7		(_MX53_PAD_EIM_EB0__SRC_BT_CFG2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__EMI_WEIM_EB_1		(_MX53_PAD_EIM_EB1__EMI_WEIM_EB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__GPIO2_29		(_MX53_PAD_EIM_EB1__GPIO2_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10		(_MX53_PAD_EIM_EB1__IPU_DISP1_DAT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__IPU_CSI1_D_10		(_MX53_PAD_EIM_EB1__IPU_CSI1_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_EB1__SRC_BT_CFG2_6		(_MX53_PAD_EIM_EB1__SRC_BT_CFG2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0		(_MX53_PAD_EIM_DA0__EMI_NAND_WEIM_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__GPIO3_0		(_MX53_PAD_EIM_DA0__GPIO3_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9		(_MX53_PAD_EIM_DA0__IPU_DISP1_DAT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__IPU_CSI1_D_9		(_MX53_PAD_EIM_DA0__IPU_CSI1_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA0__SRC_BT_CFG2_5		(_MX53_PAD_EIM_DA0__SRC_BT_CFG2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1		(_MX53_PAD_EIM_DA1__EMI_NAND_WEIM_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__GPIO3_1		(_MX53_PAD_EIM_DA1__GPIO3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8		(_MX53_PAD_EIM_DA1__IPU_DISP1_DAT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__IPU_CSI1_D_8		(_MX53_PAD_EIM_DA1__IPU_CSI1_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA1__SRC_BT_CFG2_4		(_MX53_PAD_EIM_DA1__SRC_BT_CFG2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2		(_MX53_PAD_EIM_DA2__EMI_NAND_WEIM_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__GPIO3_2		(_MX53_PAD_EIM_DA2__GPIO3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7		(_MX53_PAD_EIM_DA2__IPU_DISP1_DAT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__IPU_CSI1_D_7		(_MX53_PAD_EIM_DA2__IPU_CSI1_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA2__SRC_BT_CFG2_3		(_MX53_PAD_EIM_DA2__SRC_BT_CFG2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3		(_MX53_PAD_EIM_DA3__EMI_NAND_WEIM_DA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__GPIO3_3		(_MX53_PAD_EIM_DA3__GPIO3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6		(_MX53_PAD_EIM_DA3__IPU_DISP1_DAT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__IPU_CSI1_D_6		(_MX53_PAD_EIM_DA3__IPU_CSI1_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA3__SRC_BT_CFG2_2		(_MX53_PAD_EIM_DA3__SRC_BT_CFG2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4		(_MX53_PAD_EIM_DA4__EMI_NAND_WEIM_DA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__GPIO3_4		(_MX53_PAD_EIM_DA4__GPIO3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5		(_MX53_PAD_EIM_DA4__IPU_DISP1_DAT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__IPU_CSI1_D_5		(_MX53_PAD_EIM_DA4__IPU_CSI1_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA4__SRC_BT_CFG3_7		(_MX53_PAD_EIM_DA4__SRC_BT_CFG3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5		(_MX53_PAD_EIM_DA5__EMI_NAND_WEIM_DA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__GPIO3_5		(_MX53_PAD_EIM_DA5__GPIO3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4		(_MX53_PAD_EIM_DA5__IPU_DISP1_DAT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__IPU_CSI1_D_4		(_MX53_PAD_EIM_DA5__IPU_CSI1_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA5__SRC_BT_CFG3_6		(_MX53_PAD_EIM_DA5__SRC_BT_CFG3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6		(_MX53_PAD_EIM_DA6__EMI_NAND_WEIM_DA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__GPIO3_6		(_MX53_PAD_EIM_DA6__GPIO3_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3		(_MX53_PAD_EIM_DA6__IPU_DISP1_DAT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__IPU_CSI1_D_3		(_MX53_PAD_EIM_DA6__IPU_CSI1_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA6__SRC_BT_CFG3_5		(_MX53_PAD_EIM_DA6__SRC_BT_CFG3_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7		(_MX53_PAD_EIM_DA7__EMI_NAND_WEIM_DA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__GPIO3_7		(_MX53_PAD_EIM_DA7__GPIO3_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2		(_MX53_PAD_EIM_DA7__IPU_DISP1_DAT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__IPU_CSI1_D_2		(_MX53_PAD_EIM_DA7__IPU_CSI1_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA7__SRC_BT_CFG3_4		(_MX53_PAD_EIM_DA7__SRC_BT_CFG3_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8		(_MX53_PAD_EIM_DA8__EMI_NAND_WEIM_DA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__GPIO3_8		(_MX53_PAD_EIM_DA8__GPIO3_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1		(_MX53_PAD_EIM_DA8__IPU_DISP1_DAT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__IPU_CSI1_D_1		(_MX53_PAD_EIM_DA8__IPU_CSI1_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA8__SRC_BT_CFG3_3		(_MX53_PAD_EIM_DA8__SRC_BT_CFG3_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9		(_MX53_PAD_EIM_DA9__EMI_NAND_WEIM_DA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__GPIO3_9		(_MX53_PAD_EIM_DA9__GPIO3_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0		(_MX53_PAD_EIM_DA9__IPU_DISP1_DAT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__IPU_CSI1_D_0		(_MX53_PAD_EIM_DA9__IPU_CSI1_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA9__SRC_BT_CFG3_2		(_MX53_PAD_EIM_DA9__SRC_BT_CFG3_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10		(_MX53_PAD_EIM_DA10__EMI_NAND_WEIM_DA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__GPIO3_10		(_MX53_PAD_EIM_DA10__GPIO3_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__IPU_DI1_PIN15		(_MX53_PAD_EIM_DA10__IPU_DI1_PIN15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN		(_MX53_PAD_EIM_DA10__IPU_CSI1_DATA_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA10__SRC_BT_CFG3_1		(_MX53_PAD_EIM_DA10__SRC_BT_CFG3_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11		(_MX53_PAD_EIM_DA11__EMI_NAND_WEIM_DA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__GPIO3_11		(_MX53_PAD_EIM_DA11__GPIO3_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__IPU_DI1_PIN2		(_MX53_PAD_EIM_DA11__IPU_DI1_PIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC		(_MX53_PAD_EIM_DA11__IPU_CSI1_HSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12		(_MX53_PAD_EIM_DA12__EMI_NAND_WEIM_DA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__GPIO3_12		(_MX53_PAD_EIM_DA12__GPIO3_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__IPU_DI1_PIN3		(_MX53_PAD_EIM_DA12__IPU_DI1_PIN3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC		(_MX53_PAD_EIM_DA12__IPU_CSI1_VSYNC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13		(_MX53_PAD_EIM_DA13__EMI_NAND_WEIM_DA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__GPIO3_13		(_MX53_PAD_EIM_DA13__GPIO3_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__IPU_DI1_D0_CS		(_MX53_PAD_EIM_DA13__IPU_DI1_D0_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK		(_MX53_PAD_EIM_DA13__CCM_DI1_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14		(_MX53_PAD_EIM_DA14__EMI_NAND_WEIM_DA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__GPIO3_14		(_MX53_PAD_EIM_DA14__GPIO3_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__IPU_DI1_D1_CS		(_MX53_PAD_EIM_DA14__IPU_DI1_D1_CS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK		(_MX53_PAD_EIM_DA14__CCM_DI0_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15		(_MX53_PAD_EIM_DA15__EMI_NAND_WEIM_DA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__GPIO3_15		(_MX53_PAD_EIM_DA15__GPIO3_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN1		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_DA15__IPU_DI1_PIN4		(_MX53_PAD_EIM_DA15__IPU_DI1_PIN4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B		(_MX53_PAD_NANDF_WE_B__EMI_NANDF_WE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WE_B__GPIO6_12		(_MX53_PAD_NANDF_WE_B__GPIO6_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B		(_MX53_PAD_NANDF_RE_B__EMI_NANDF_RE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RE_B__GPIO6_13		(_MX53_PAD_NANDF_RE_B__GPIO6_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT		(_MX53_PAD_EIM_WAIT__EMI_WEIM_WAIT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_WAIT__GPIO5_0		(_MX53_PAD_EIM_WAIT__GPIO5_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B		(_MX53_PAD_EIM_WAIT__EMI_WEIM_DTACK_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX3_P__GPIO6_22		(_MX53_PAD_LVDS1_TX3_P__GPIO6_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3		(_MX53_PAD_LVDS1_TX3_P__LDB_LVDS1_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX2_P__GPIO6_24		(_MX53_PAD_LVDS1_TX2_P__GPIO6_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2		(_MX53_PAD_LVDS1_TX2_P__LDB_LVDS1_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_CLK_P__GPIO6_26		(_MX53_PAD_LVDS1_CLK_P__GPIO6_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK		(_MX53_PAD_LVDS1_CLK_P__LDB_LVDS1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX1_P__GPIO6_28		(_MX53_PAD_LVDS1_TX1_P__GPIO6_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1		(_MX53_PAD_LVDS1_TX1_P__LDB_LVDS1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX0_P__GPIO6_30		(_MX53_PAD_LVDS1_TX0_P__GPIO6_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0		(_MX53_PAD_LVDS1_TX0_P__LDB_LVDS1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX3_P__GPIO7_22		(_MX53_PAD_LVDS0_TX3_P__GPIO7_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3		(_MX53_PAD_LVDS0_TX3_P__LDB_LVDS0_TX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_CLK_P__GPIO7_24		(_MX53_PAD_LVDS0_CLK_P__GPIO7_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK		(_MX53_PAD_LVDS0_CLK_P__LDB_LVDS0_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX2_P__GPIO7_26		(_MX53_PAD_LVDS0_TX2_P__GPIO7_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2		(_MX53_PAD_LVDS0_TX2_P__LDB_LVDS0_TX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX1_P__GPIO7_28		(_MX53_PAD_LVDS0_TX1_P__GPIO7_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1		(_MX53_PAD_LVDS0_TX1_P__LDB_LVDS0_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX0_P__GPIO7_30		(_MX53_PAD_LVDS0_TX0_P__GPIO7_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0		(_MX53_PAD_LVDS0_TX0_P__LDB_LVDS0_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_10__GPIO4_0		(_MX53_PAD_GPIO_10__GPIO4_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_10__OSC32k_32K_OUT		(_MX53_PAD_GPIO_10__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_11__GPIO4_1		(_MX53_PAD_GPIO_11__GPIO4_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_12__GPIO4_2		(_MX53_PAD_GPIO_12__GPIO4_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_13__GPIO4_3		(_MX53_PAD_GPIO_13__GPIO4_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_14__GPIO4_4		(_MX53_PAD_GPIO_14__GPIO4_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CLE__EMI_NANDF_CLE		(_MX53_PAD_NANDF_CLE__EMI_NANDF_CLE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CLE__GPIO6_7		(_MX53_PAD_NANDF_CLE__GPIO6_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0		(_MX53_PAD_NANDF_CLE__USBPHY1_VSTATUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_ALE__EMI_NANDF_ALE		(_MX53_PAD_NANDF_ALE__EMI_NANDF_ALE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_ALE__GPIO6_8		(_MX53_PAD_NANDF_ALE__GPIO6_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1		(_MX53_PAD_NANDF_ALE__USBPHY1_VSTATUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B		(_MX53_PAD_NANDF_WP_B__EMI_NANDF_WP_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WP_B__GPIO6_9		(_MX53_PAD_NANDF_WP_B__GPIO6_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2		(_MX53_PAD_NANDF_WP_B__USBPHY1_VSTATUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0		(_MX53_PAD_NANDF_RB0__EMI_NANDF_RB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RB0__GPIO6_10		(_MX53_PAD_NANDF_RB0__GPIO6_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3		(_MX53_PAD_NANDF_RB0__USBPHY1_VSTATUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0		(_MX53_PAD_NANDF_CS0__EMI_NANDF_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS0__GPIO6_11		(_MX53_PAD_NANDF_CS0__GPIO6_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4		(_MX53_PAD_NANDF_CS0__USBPHY1_VSTATUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1		(_MX53_PAD_NANDF_CS1__EMI_NANDF_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__GPIO6_14		(_MX53_PAD_NANDF_CS1__GPIO6_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__MLB_MLBCLK		(_MX53_PAD_NANDF_CS1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5		(_MX53_PAD_NANDF_CS1__USBPHY1_VSTATUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2		(_MX53_PAD_NANDF_CS2__EMI_NANDF_CS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__GPIO6_15		(_MX53_PAD_NANDF_CS2__GPIO6_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__IPU_SISG_0		(_MX53_PAD_NANDF_CS2__IPU_SISG_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__ESAI1_TX0		(_MX53_PAD_NANDF_CS2__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__EMI_WEIM_CRE		(_MX53_PAD_NANDF_CS2__EMI_WEIM_CRE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK		(_MX53_PAD_NANDF_CS2__CCM_CSI0_MCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__MLB_MLBSIG		(_MX53_PAD_NANDF_CS2__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6		(_MX53_PAD_NANDF_CS2__USBPHY1_VSTATUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3		(_MX53_PAD_NANDF_CS3__EMI_NANDF_CS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__GPIO6_16		(_MX53_PAD_NANDF_CS3__GPIO6_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__IPU_SISG_1		(_MX53_PAD_NANDF_CS3__IPU_SISG_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__ESAI1_TX1		(_MX53_PAD_NANDF_CS3__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__EMI_WEIM_A_26		(_MX53_PAD_NANDF_CS3__EMI_WEIM_A_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__MLB_MLBDAT		(_MX53_PAD_NANDF_CS3__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7		(_MX53_PAD_NANDF_CS3__USBPHY1_VSTATUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__FEC_MDIO		(_MX53_PAD_FEC_MDIO__FEC_MDIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__GPIO1_22		(_MX53_PAD_FEC_MDIO__GPIO1_22 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__ESAI1_SCKR		(_MX53_PAD_FEC_MDIO__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__FEC_COL		(_MX53_PAD_FEC_MDIO__FEC_COL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2		(_MX53_PAD_FEC_MDIO__RTC_CE_RTC_PS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3		(_MX53_PAD_FEC_MDIO__SDMA_DEBUG_BUS_DEVICE_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49		(_MX53_PAD_FEC_MDIO__EMI_EMI_DEBUG_49 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__FEC_TX_CLK		(_MX53_PAD_FEC_REF_CLK__FEC_TX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__GPIO1_23		(_MX53_PAD_FEC_REF_CLK__GPIO1_23 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__ESAI1_FSR		(_MX53_PAD_FEC_REF_CLK__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4		(_MX53_PAD_FEC_REF_CLK__SDMA_DEBUG_BUS_DEVICE_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50		(_MX53_PAD_FEC_REF_CLK__EMI_EMI_DEBUG_50 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__FEC_RX_ER		(_MX53_PAD_FEC_RX_ER__FEC_RX_ER | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__GPIO1_24		(_MX53_PAD_FEC_RX_ER__GPIO1_24 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__ESAI1_HCKR		(_MX53_PAD_FEC_RX_ER__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__FEC_RX_CLK		(_MX53_PAD_FEC_RX_ER__FEC_RX_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3		(_MX53_PAD_FEC_RX_ER__RTC_CE_RTC_PS3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_CRS_DV__FEC_RX_DV		(_MX53_PAD_FEC_CRS_DV__FEC_RX_DV | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_CRS_DV__GPIO1_25		(_MX53_PAD_FEC_CRS_DV__GPIO1_25 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_CRS_DV__ESAI1_SCKT		(_MX53_PAD_FEC_CRS_DV__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__FEC_RDATA_1		(_MX53_PAD_FEC_RXD1__FEC_RDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__GPIO1_26		(_MX53_PAD_FEC_RXD1__GPIO1_26 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__ESAI1_FST		(_MX53_PAD_FEC_RXD1__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__MLB_MLBSIG		(_MX53_PAD_FEC_RXD1__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1		(_MX53_PAD_FEC_RXD1__RTC_CE_RTC_PS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__FEC_RDATA_0		(_MX53_PAD_FEC_RXD0__FEC_RDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__GPIO1_27		(_MX53_PAD_FEC_RXD0__GPIO1_27 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__ESAI1_HCKT		(_MX53_PAD_FEC_RXD0__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_RXD0__OSC32k_32K_OUT		(_MX53_PAD_FEC_RXD0__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TX_EN__FEC_TX_EN		(_MX53_PAD_FEC_TX_EN__FEC_TX_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TX_EN__GPIO1_28		(_MX53_PAD_FEC_TX_EN__GPIO1_28 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2		(_MX53_PAD_FEC_TX_EN__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__FEC_TDATA_1		(_MX53_PAD_FEC_TXD1__FEC_TDATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__GPIO1_29		(_MX53_PAD_FEC_TXD1__GPIO1_29 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3		(_MX53_PAD_FEC_TXD1__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__MLB_MLBCLK		(_MX53_PAD_FEC_TXD1__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK		(_MX53_PAD_FEC_TXD1__RTC_CE_RTC_PRSC_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__FEC_TDATA_0		(_MX53_PAD_FEC_TXD0__FEC_TDATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__GPIO1_30		(_MX53_PAD_FEC_TXD0__GPIO1_30 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1		(_MX53_PAD_FEC_TXD0__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0		(_MX53_PAD_FEC_TXD0__USBPHY2_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__FEC_MDC		(_MX53_PAD_FEC_MDC__FEC_MDC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__GPIO1_31		(_MX53_PAD_FEC_MDC__GPIO1_31 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__ESAI1_TX5_RX0		(_MX53_PAD_FEC_MDC__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__MLB_MLBDAT		(_MX53_PAD_FEC_MDC__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG		(_MX53_PAD_FEC_MDC__RTC_CE_RTC_ALARM1_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1		(_MX53_PAD_FEC_MDC__USBPHY2_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__PATA_DIOW		(_MX53_PAD_PATA_DIOW__PATA_DIOW | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__GPIO6_17		(_MX53_PAD_PATA_DIOW__GPIO6_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__UART1_TXD_MUX		(_MX53_PAD_PATA_DIOW__UART1_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2		(_MX53_PAD_PATA_DIOW__USBPHY2_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__PATA_DMACK		(_MX53_PAD_PATA_DMACK__PATA_DMACK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__GPIO6_18		(_MX53_PAD_PATA_DMACK__GPIO6_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__UART1_RXD_MUX		(_MX53_PAD_PATA_DMACK__UART1_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3		(_MX53_PAD_PATA_DMACK__USBPHY2_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__PATA_DMARQ		(_MX53_PAD_PATA_DMARQ__PATA_DMARQ | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__GPIO7_0		(_MX53_PAD_PATA_DMARQ__GPIO7_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__UART2_TXD_MUX		(_MX53_PAD_PATA_DMARQ__UART2_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0		(_MX53_PAD_PATA_DMARQ__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4		(_MX53_PAD_PATA_DMARQ__USBPHY2_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN		(_MX53_PAD_PATA_BUFFER_EN__PATA_BUFFER_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__GPIO7_1		(_MX53_PAD_PATA_BUFFER_EN__GPIO7_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX		(_MX53_PAD_PATA_BUFFER_EN__UART2_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1		(_MX53_PAD_PATA_BUFFER_EN__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5		(_MX53_PAD_PATA_BUFFER_EN__USBPHY2_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__PATA_INTRQ		(_MX53_PAD_PATA_INTRQ__PATA_INTRQ | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__GPIO7_2		(_MX53_PAD_PATA_INTRQ__GPIO7_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__UART2_CTS		(_MX53_PAD_PATA_INTRQ__UART2_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__CAN1_TXCAN		(_MX53_PAD_PATA_INTRQ__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2		(_MX53_PAD_PATA_INTRQ__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6		(_MX53_PAD_PATA_INTRQ__USBPHY2_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__PATA_DIOR		(_MX53_PAD_PATA_DIOR__PATA_DIOR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__GPIO7_3		(_MX53_PAD_PATA_DIOR__GPIO7_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__UART2_RTS		(_MX53_PAD_PATA_DIOR__UART2_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__CAN1_RXCAN		(_MX53_PAD_PATA_DIOR__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7		(_MX53_PAD_PATA_DIOR__USBPHY2_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B		(_MX53_PAD_PATA_RESET_B__PATA_PATA_RESET_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__GPIO7_4		(_MX53_PAD_PATA_RESET_B__GPIO7_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__ESDHC3_CMD		(_MX53_PAD_PATA_RESET_B__ESDHC3_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__UART1_CTS		(_MX53_PAD_PATA_RESET_B__UART1_CTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__CAN2_TXCAN		(_MX53_PAD_PATA_RESET_B__CAN2_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0		(_MX53_PAD_PATA_RESET_B__USBPHY1_DATAOUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__PATA_IORDY		(_MX53_PAD_PATA_IORDY__PATA_IORDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__GPIO7_5		(_MX53_PAD_PATA_IORDY__GPIO7_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__ESDHC3_CLK		(_MX53_PAD_PATA_IORDY__ESDHC3_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__UART1_RTS		(_MX53_PAD_PATA_IORDY__UART1_RTS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__CAN2_RXCAN		(_MX53_PAD_PATA_IORDY__CAN2_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1		(_MX53_PAD_PATA_IORDY__USBPHY1_DATAOUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__PATA_DA_0		(_MX53_PAD_PATA_DA_0__PATA_DA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__GPIO7_6		(_MX53_PAD_PATA_DA_0__GPIO7_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__ESDHC3_RST		(_MX53_PAD_PATA_DA_0__ESDHC3_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__OWIRE_LINE		(_MX53_PAD_PATA_DA_0__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2		(_MX53_PAD_PATA_DA_0__USBPHY1_DATAOUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__PATA_DA_1		(_MX53_PAD_PATA_DA_1__PATA_DA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__GPIO7_7		(_MX53_PAD_PATA_DA_1__GPIO7_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__ESDHC4_CMD		(_MX53_PAD_PATA_DA_1__ESDHC4_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__UART3_CTS		(_MX53_PAD_PATA_DA_1__UART3_CTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3		(_MX53_PAD_PATA_DA_1__USBPHY1_DATAOUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__PATA_DA_2		(_MX53_PAD_PATA_DA_2__PATA_DA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__GPIO7_8		(_MX53_PAD_PATA_DA_2__GPIO7_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__ESDHC4_CLK		(_MX53_PAD_PATA_DA_2__ESDHC4_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__UART3_RTS		(_MX53_PAD_PATA_DA_2__UART3_RTS | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4		(_MX53_PAD_PATA_DA_2__USBPHY1_DATAOUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__PATA_CS_0		(_MX53_PAD_PATA_CS_0__PATA_CS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__GPIO7_9		(_MX53_PAD_PATA_CS_0__GPIO7_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__UART3_TXD_MUX		(_MX53_PAD_PATA_CS_0__UART3_TXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5		(_MX53_PAD_PATA_CS_0__USBPHY1_DATAOUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__PATA_CS_1		(_MX53_PAD_PATA_CS_1__PATA_CS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__GPIO7_10		(_MX53_PAD_PATA_CS_1__GPIO7_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__UART3_RXD_MUX		(_MX53_PAD_PATA_CS_1__UART3_RXD_MUX | MUX_PAD_CTRL(MX53_UART_PAD_CTRL))
+#define MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6		(_MX53_PAD_PATA_CS_1__USBPHY1_DATAOUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__PATA_DATA_0		(_MX53_PAD_PATA_DATA0__PATA_DATA_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__GPIO2_0		(_MX53_PAD_PATA_DATA0__GPIO2_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__EMI_NANDF_D_0		(_MX53_PAD_PATA_DATA0__EMI_NANDF_D_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__ESDHC3_DAT4		(_MX53_PAD_PATA_DATA0__ESDHC3_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0		(_MX53_PAD_PATA_DATA0__GPU3d_GPU_DEBUG_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0		(_MX53_PAD_PATA_DATA0__IPU_DIAG_BUS_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7		(_MX53_PAD_PATA_DATA0__USBPHY1_DATAOUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__PATA_DATA_1		(_MX53_PAD_PATA_DATA1__PATA_DATA_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__GPIO2_1		(_MX53_PAD_PATA_DATA1__GPIO2_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__EMI_NANDF_D_1		(_MX53_PAD_PATA_DATA1__EMI_NANDF_D_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__ESDHC3_DAT5		(_MX53_PAD_PATA_DATA1__ESDHC3_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1		(_MX53_PAD_PATA_DATA1__GPU3d_GPU_DEBUG_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1		(_MX53_PAD_PATA_DATA1__IPU_DIAG_BUS_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__PATA_DATA_2		(_MX53_PAD_PATA_DATA2__PATA_DATA_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__GPIO2_2		(_MX53_PAD_PATA_DATA2__GPIO2_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__EMI_NANDF_D_2		(_MX53_PAD_PATA_DATA2__EMI_NANDF_D_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__ESDHC3_DAT6		(_MX53_PAD_PATA_DATA2__ESDHC3_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2		(_MX53_PAD_PATA_DATA2__GPU3d_GPU_DEBUG_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2		(_MX53_PAD_PATA_DATA2__IPU_DIAG_BUS_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__PATA_DATA_3		(_MX53_PAD_PATA_DATA3__PATA_DATA_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__GPIO2_3		(_MX53_PAD_PATA_DATA3__GPIO2_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__EMI_NANDF_D_3		(_MX53_PAD_PATA_DATA3__EMI_NANDF_D_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__ESDHC3_DAT7		(_MX53_PAD_PATA_DATA3__ESDHC3_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3		(_MX53_PAD_PATA_DATA3__GPU3d_GPU_DEBUG_OUT_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3		(_MX53_PAD_PATA_DATA3__IPU_DIAG_BUS_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__PATA_DATA_4		(_MX53_PAD_PATA_DATA4__PATA_DATA_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__GPIO2_4		(_MX53_PAD_PATA_DATA4__GPIO2_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__EMI_NANDF_D_4		(_MX53_PAD_PATA_DATA4__EMI_NANDF_D_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__ESDHC4_DAT4		(_MX53_PAD_PATA_DATA4__ESDHC4_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4		(_MX53_PAD_PATA_DATA4__GPU3d_GPU_DEBUG_OUT_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4		(_MX53_PAD_PATA_DATA4__IPU_DIAG_BUS_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__PATA_DATA_5		(_MX53_PAD_PATA_DATA5__PATA_DATA_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__GPIO2_5		(_MX53_PAD_PATA_DATA5__GPIO2_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__EMI_NANDF_D_5		(_MX53_PAD_PATA_DATA5__EMI_NANDF_D_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__ESDHC4_DAT5		(_MX53_PAD_PATA_DATA5__ESDHC4_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5		(_MX53_PAD_PATA_DATA5__GPU3d_GPU_DEBUG_OUT_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5		(_MX53_PAD_PATA_DATA5__IPU_DIAG_BUS_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__PATA_DATA_6		(_MX53_PAD_PATA_DATA6__PATA_DATA_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__GPIO2_6		(_MX53_PAD_PATA_DATA6__GPIO2_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__EMI_NANDF_D_6		(_MX53_PAD_PATA_DATA6__EMI_NANDF_D_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__ESDHC4_DAT6		(_MX53_PAD_PATA_DATA6__ESDHC4_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6		(_MX53_PAD_PATA_DATA6__GPU3d_GPU_DEBUG_OUT_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6		(_MX53_PAD_PATA_DATA6__IPU_DIAG_BUS_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__PATA_DATA_7		(_MX53_PAD_PATA_DATA7__PATA_DATA_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__GPIO2_7		(_MX53_PAD_PATA_DATA7__GPIO2_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__EMI_NANDF_D_7		(_MX53_PAD_PATA_DATA7__EMI_NANDF_D_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__ESDHC4_DAT7		(_MX53_PAD_PATA_DATA7__ESDHC4_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7		(_MX53_PAD_PATA_DATA7__GPU3d_GPU_DEBUG_OUT_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7		(_MX53_PAD_PATA_DATA7__IPU_DIAG_BUS_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__PATA_DATA_8		(_MX53_PAD_PATA_DATA8__PATA_DATA_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__GPIO2_8		(_MX53_PAD_PATA_DATA8__GPIO2_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__ESDHC1_DAT4		(_MX53_PAD_PATA_DATA8__ESDHC1_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__EMI_NANDF_D_8		(_MX53_PAD_PATA_DATA8__EMI_NANDF_D_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__ESDHC3_DAT0		(_MX53_PAD_PATA_DATA8__ESDHC3_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8		(_MX53_PAD_PATA_DATA8__GPU3d_GPU_DEBUG_OUT_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8		(_MX53_PAD_PATA_DATA8__IPU_DIAG_BUS_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__PATA_DATA_9		(_MX53_PAD_PATA_DATA9__PATA_DATA_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__GPIO2_9		(_MX53_PAD_PATA_DATA9__GPIO2_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__ESDHC1_DAT5		(_MX53_PAD_PATA_DATA9__ESDHC1_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__EMI_NANDF_D_9		(_MX53_PAD_PATA_DATA9__EMI_NANDF_D_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__ESDHC3_DAT1		(_MX53_PAD_PATA_DATA9__ESDHC3_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9		(_MX53_PAD_PATA_DATA9__GPU3d_GPU_DEBUG_OUT_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9		(_MX53_PAD_PATA_DATA9__IPU_DIAG_BUS_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__PATA_DATA_10		(_MX53_PAD_PATA_DATA10__PATA_DATA_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__GPIO2_10		(_MX53_PAD_PATA_DATA10__GPIO2_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__ESDHC1_DAT6		(_MX53_PAD_PATA_DATA10__ESDHC1_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__EMI_NANDF_D_10		(_MX53_PAD_PATA_DATA10__EMI_NANDF_D_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__ESDHC3_DAT2		(_MX53_PAD_PATA_DATA10__ESDHC3_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10		(_MX53_PAD_PATA_DATA10__GPU3d_GPU_DEBUG_OUT_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10		(_MX53_PAD_PATA_DATA10__IPU_DIAG_BUS_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__PATA_DATA_11		(_MX53_PAD_PATA_DATA11__PATA_DATA_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__GPIO2_11		(_MX53_PAD_PATA_DATA11__GPIO2_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__ESDHC1_DAT7		(_MX53_PAD_PATA_DATA11__ESDHC1_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__EMI_NANDF_D_11		(_MX53_PAD_PATA_DATA11__EMI_NANDF_D_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__ESDHC3_DAT3		(_MX53_PAD_PATA_DATA11__ESDHC3_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11		(_MX53_PAD_PATA_DATA11__GPU3d_GPU_DEBUG_OUT_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11		(_MX53_PAD_PATA_DATA11__IPU_DIAG_BUS_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__PATA_DATA_12		(_MX53_PAD_PATA_DATA12__PATA_DATA_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__GPIO2_12		(_MX53_PAD_PATA_DATA12__GPIO2_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__ESDHC2_DAT4		(_MX53_PAD_PATA_DATA12__ESDHC2_DAT4 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__EMI_NANDF_D_12		(_MX53_PAD_PATA_DATA12__EMI_NANDF_D_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__ESDHC4_DAT0		(_MX53_PAD_PATA_DATA12__ESDHC4_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12		(_MX53_PAD_PATA_DATA12__GPU3d_GPU_DEBUG_OUT_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12		(_MX53_PAD_PATA_DATA12__IPU_DIAG_BUS_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__PATA_DATA_13		(_MX53_PAD_PATA_DATA13__PATA_DATA_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__GPIO2_13		(_MX53_PAD_PATA_DATA13__GPIO2_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__ESDHC2_DAT5		(_MX53_PAD_PATA_DATA13__ESDHC2_DAT5 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__EMI_NANDF_D_13		(_MX53_PAD_PATA_DATA13__EMI_NANDF_D_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__ESDHC4_DAT1		(_MX53_PAD_PATA_DATA13__ESDHC4_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13		(_MX53_PAD_PATA_DATA13__GPU3d_GPU_DEBUG_OUT_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13		(_MX53_PAD_PATA_DATA13__IPU_DIAG_BUS_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__PATA_DATA_14		(_MX53_PAD_PATA_DATA14__PATA_DATA_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__GPIO2_14		(_MX53_PAD_PATA_DATA14__GPIO2_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__ESDHC2_DAT6		(_MX53_PAD_PATA_DATA14__ESDHC2_DAT6 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__EMI_NANDF_D_14		(_MX53_PAD_PATA_DATA14__EMI_NANDF_D_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__ESDHC4_DAT2		(_MX53_PAD_PATA_DATA14__ESDHC4_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14		(_MX53_PAD_PATA_DATA14__GPU3d_GPU_DEBUG_OUT_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14		(_MX53_PAD_PATA_DATA14__IPU_DIAG_BUS_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__PATA_DATA_15		(_MX53_PAD_PATA_DATA15__PATA_DATA_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__GPIO2_15		(_MX53_PAD_PATA_DATA15__GPIO2_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__ESDHC2_DAT7		(_MX53_PAD_PATA_DATA15__ESDHC2_DAT7 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__EMI_NANDF_D_15		(_MX53_PAD_PATA_DATA15__EMI_NANDF_D_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__ESDHC4_DAT3		(_MX53_PAD_PATA_DATA15__ESDHC4_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15		(_MX53_PAD_PATA_DATA15__GPU3d_GPU_DEBUG_OUT_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15		(_MX53_PAD_PATA_DATA15__IPU_DIAG_BUS_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__ESDHC1_DAT0		(_MX53_PAD_SD1_DATA0__ESDHC1_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__GPIO1_16		(_MX53_PAD_SD1_DATA0__GPIO1_16 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__GPT_CAPIN1		(_MX53_PAD_SD1_DATA0__GPT_CAPIN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__CSPI_MISO		(_MX53_PAD_SD1_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA0__CCM_PLL3_BYP		(_MX53_PAD_SD1_DATA0__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__ESDHC1_DAT1		(_MX53_PAD_SD1_DATA1__ESDHC1_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__GPIO1_17		(_MX53_PAD_SD1_DATA1__GPIO1_17 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__GPT_CAPIN2		(_MX53_PAD_SD1_DATA1__GPT_CAPIN2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__CSPI_SS0		(_MX53_PAD_SD1_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA1__CCM_PLL4_BYP		(_MX53_PAD_SD1_DATA1__CCM_PLL4_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__ESDHC1_CMD		(_MX53_PAD_SD1_CMD__ESDHC1_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__GPIO1_18		(_MX53_PAD_SD1_CMD__GPIO1_18 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__GPT_CMPOUT1		(_MX53_PAD_SD1_CMD__GPT_CMPOUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__CSPI_MOSI		(_MX53_PAD_SD1_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CMD__CCM_PLL1_BYP		(_MX53_PAD_SD1_CMD__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__ESDHC1_DAT2		(_MX53_PAD_SD1_DATA2__ESDHC1_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__GPIO1_19		(_MX53_PAD_SD1_DATA2__GPIO1_19 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__GPT_CMPOUT2		(_MX53_PAD_SD1_DATA2__GPT_CMPOUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__PWM2_PWMO		(_MX53_PAD_SD1_DATA2__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_B		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__CSPI_SS1		(_MX53_PAD_SD1_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA2__WDOG1_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA2__CCM_PLL2_BYP		(_MX53_PAD_SD1_DATA2__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__ESDHC1_CLK		(_MX53_PAD_SD1_CLK__ESDHC1_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__GPIO1_20		(_MX53_PAD_SD1_CLK__GPIO1_20 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__OSC32k_32K_OUT		(_MX53_PAD_SD1_CLK__OSC32k_32K_OUT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__GPT_CLKIN		(_MX53_PAD_SD1_CLK__GPT_CLKIN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__CSPI_SCLK		(_MX53_PAD_SD1_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_CLK__SATA_PHY_DTB_0		(_MX53_PAD_SD1_CLK__SATA_PHY_DTB_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__ESDHC1_DAT3		(_MX53_PAD_SD1_DATA3__ESDHC1_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__GPIO1_21		(_MX53_PAD_SD1_DATA3__GPIO1_21 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__GPT_CMPOUT3		(_MX53_PAD_SD1_DATA3__GPT_CMPOUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__PWM1_PWMO		(_MX53_PAD_SD1_DATA3__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_B		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__CSPI_SS2		(_MX53_PAD_SD1_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB		(_MX53_PAD_SD1_DATA3__WDOG2_WDOG_RST_B_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1		(_MX53_PAD_SD1_DATA3__SATA_PHY_DTB_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__ESDHC2_CLK		(_MX53_PAD_SD2_CLK__ESDHC2_CLK | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__GPIO1_10		(_MX53_PAD_SD2_CLK__GPIO1_10 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__KPP_COL_5		(_MX53_PAD_SD2_CLK__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS		(_MX53_PAD_SD2_CLK__AUDMUX_AUD4_RXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__CSPI_SCLK		(_MX53_PAD_SD2_CLK__CSPI_SCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CLK__SCC_RANDOM_V		(_MX53_PAD_SD2_CLK__SCC_RANDOM_V | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__ESDHC2_CMD		(_MX53_PAD_SD2_CMD__ESDHC2_CMD | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__GPIO1_11		(_MX53_PAD_SD2_CMD__GPIO1_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__KPP_ROW_5		(_MX53_PAD_SD2_CMD__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC		(_MX53_PAD_SD2_CMD__AUDMUX_AUD4_RXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__CSPI_MOSI		(_MX53_PAD_SD2_CMD__CSPI_MOSI | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_CMD__SCC_RANDOM		(_MX53_PAD_SD2_CMD__SCC_RANDOM | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__ESDHC2_DAT3		(_MX53_PAD_SD2_DATA3__ESDHC2_DAT3 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__GPIO1_12		(_MX53_PAD_SD2_DATA3__GPIO1_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__KPP_COL_6		(_MX53_PAD_SD2_DATA3__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC		(_MX53_PAD_SD2_DATA3__AUDMUX_AUD4_TXC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__CSPI_SS2		(_MX53_PAD_SD2_DATA3__CSPI_SS2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA3__SJC_DONE		(_MX53_PAD_SD2_DATA3__SJC_DONE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__ESDHC2_DAT2		(_MX53_PAD_SD2_DATA2__ESDHC2_DAT2 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__GPIO1_13		(_MX53_PAD_SD2_DATA2__GPIO1_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__KPP_ROW_6		(_MX53_PAD_SD2_DATA2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD		(_MX53_PAD_SD2_DATA2__AUDMUX_AUD4_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__CSPI_SS1		(_MX53_PAD_SD2_DATA2__CSPI_SS1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA2__SJC_FAIL		(_MX53_PAD_SD2_DATA2__SJC_FAIL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__ESDHC2_DAT1		(_MX53_PAD_SD2_DATA1__ESDHC2_DAT1 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__GPIO1_14		(_MX53_PAD_SD2_DATA1__GPIO1_14 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__KPP_COL_7		(_MX53_PAD_SD2_DATA1__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS		(_MX53_PAD_SD2_DATA1__AUDMUX_AUD4_TXFS | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__CSPI_SS0		(_MX53_PAD_SD2_DATA1__CSPI_SS0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA1__RTIC_SEC_VIO		(_MX53_PAD_SD2_DATA1__RTIC_SEC_VIO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__ESDHC2_DAT0		(_MX53_PAD_SD2_DATA0__ESDHC2_DAT0 | MUX_PAD_CTRL(MX53_SDHC_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__GPIO1_15		(_MX53_PAD_SD2_DATA0__GPIO1_15 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__KPP_ROW_7		(_MX53_PAD_SD2_DATA0__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD		(_MX53_PAD_SD2_DATA0__AUDMUX_AUD4_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__CSPI_MISO		(_MX53_PAD_SD2_DATA0__CSPI_MISO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_SD2_DATA0__RTIC_DONE_INT		(_MX53_PAD_SD2_DATA0__RTIC_DONE_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__CCM_CLKO		(_MX53_PAD_GPIO_0__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__GPIO1_0		(_MX53_PAD_GPIO_0__GPIO1_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__KPP_COL_5		(_MX53_PAD_GPIO_0__KPP_COL_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK		(_MX53_PAD_GPIO_0__CCM_SSI_EXT1_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__EPIT1_EPITO		(_MX53_PAD_GPIO_0__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__SRTC_ALARM_DEB		(_MX53_PAD_GPIO_0__SRTC_ALARM_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__USBOH3_USBH1_PWR		(_MX53_PAD_GPIO_0__USBOH3_USBH1_PWR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_0__CSU_TD		(_MX53_PAD_GPIO_0__CSU_TD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__ESAI1_SCKR		(_MX53_PAD_GPIO_1__ESAI1_SCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__GPIO1_1		(_MX53_PAD_GPIO_1__GPIO1_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__KPP_ROW_5		(_MX53_PAD_GPIO_1__KPP_ROW_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK		(_MX53_PAD_GPIO_1__CCM_SSI_EXT2_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__PWM2_PWMO		(_MX53_PAD_GPIO_1__PWM2_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__WDOG2_WDOG_B		(_MX53_PAD_GPIO_1__WDOG2_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__ESDHC1_CD		(_MX53_PAD_GPIO_1__ESDHC1_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_1__SRC_TESTER_ACK		(_MX53_PAD_GPIO_1__SRC_TESTER_ACK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__ESAI1_FSR		(_MX53_PAD_GPIO_9__ESAI1_FSR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__GPIO1_9		(_MX53_PAD_GPIO_9__GPIO1_9 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__KPP_COL_6		(_MX53_PAD_GPIO_9__KPP_COL_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__CCM_REF_EN_B		(_MX53_PAD_GPIO_9__CCM_REF_EN_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__PWM1_PWMO		(_MX53_PAD_GPIO_9__PWM1_PWMO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__WDOG1_WDOG_B		(_MX53_PAD_GPIO_9__WDOG1_WDOG_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__ESDHC1_WP		(_MX53_PAD_GPIO_9__ESDHC1_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_9__SCC_FAIL_STATE		(_MX53_PAD_GPIO_9__SCC_FAIL_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__ESAI1_HCKR		(_MX53_PAD_GPIO_3__ESAI1_HCKR | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__GPIO1_3		(_MX53_PAD_GPIO_3__GPIO1_3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__I2C3_SCL		(_MX53_PAD_GPIO_3__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__DPLLIP1_TOG_EN		(_MX53_PAD_GPIO_3__DPLLIP1_TOG_EN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__CCM_CLKO2		(_MX53_PAD_GPIO_3__CCM_CLKO2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0		(_MX53_PAD_GPIO_3__OBSERVE_MUX_OBSRV_INT_OUT0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__USBOH3_USBH1_OC		(_MX53_PAD_GPIO_3__USBOH3_USBH1_OC | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_3__MLB_MLBCLK		(_MX53_PAD_GPIO_3__MLB_MLBCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__ESAI1_SCKT		(_MX53_PAD_GPIO_6__ESAI1_SCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__GPIO1_6		(_MX53_PAD_GPIO_6__GPIO1_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__I2C3_SDA		(_MX53_PAD_GPIO_6__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__CCM_CCM_OUT_0		(_MX53_PAD_GPIO_6__CCM_CCM_OUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__CSU_CSU_INT_DEB		(_MX53_PAD_GPIO_6__CSU_CSU_INT_DEB | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1		(_MX53_PAD_GPIO_6__OBSERVE_MUX_OBSRV_INT_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__ESDHC2_LCTL		(_MX53_PAD_GPIO_6__ESDHC2_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_6__MLB_MLBSIG		(_MX53_PAD_GPIO_6__MLB_MLBSIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__ESAI1_FST		(_MX53_PAD_GPIO_2__ESAI1_FST | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__GPIO1_2		(_MX53_PAD_GPIO_2__GPIO1_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__KPP_ROW_6		(_MX53_PAD_GPIO_2__KPP_ROW_6 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__CCM_CCM_OUT_1		(_MX53_PAD_GPIO_2__CCM_CCM_OUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0		(_MX53_PAD_GPIO_2__CSU_CSU_ALARM_AUT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2		(_MX53_PAD_GPIO_2__OBSERVE_MUX_OBSRV_INT_OUT2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__ESDHC2_WP		(_MX53_PAD_GPIO_2__ESDHC2_WP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_2__MLB_MLBDAT		(_MX53_PAD_GPIO_2__MLB_MLBDAT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__ESAI1_HCKT		(_MX53_PAD_GPIO_4__ESAI1_HCKT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__GPIO1_4		(_MX53_PAD_GPIO_4__GPIO1_4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__KPP_COL_7		(_MX53_PAD_GPIO_4__KPP_COL_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__CCM_CCM_OUT_2		(_MX53_PAD_GPIO_4__CCM_CCM_OUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1		(_MX53_PAD_GPIO_4__CSU_CSU_ALARM_AUT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3		(_MX53_PAD_GPIO_4__OBSERVE_MUX_OBSRV_INT_OUT3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__ESDHC2_CD		(_MX53_PAD_GPIO_4__ESDHC2_CD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_4__SCC_SEC_STATE		(_MX53_PAD_GPIO_4__SCC_SEC_STATE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__ESAI1_TX2_RX3		(_MX53_PAD_GPIO_5__ESAI1_TX2_RX3 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__GPIO1_5		(_MX53_PAD_GPIO_5__GPIO1_5 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__KPP_ROW_7		(_MX53_PAD_GPIO_5__KPP_ROW_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__CCM_CLKO		(_MX53_PAD_GPIO_5__CCM_CLKO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2		(_MX53_PAD_GPIO_5__CSU_CSU_ALARM_AUT_2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4		(_MX53_PAD_GPIO_5__OBSERVE_MUX_OBSRV_INT_OUT4 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__I2C3_SCL		(_MX53_PAD_GPIO_5__I2C3_SCL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_5__CCM_PLL1_BYP		(_MX53_PAD_GPIO_5__CCM_PLL1_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__ESAI1_TX4_RX1		(_MX53_PAD_GPIO_7__ESAI1_TX4_RX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__GPIO1_7		(_MX53_PAD_GPIO_7__GPIO1_7 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__EPIT1_EPITO		(_MX53_PAD_GPIO_7__EPIT1_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__CAN1_TXCAN		(_MX53_PAD_GPIO_7__CAN1_TXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__UART2_TXD_MUX		(_MX53_PAD_GPIO_7__UART2_TXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__FIRI_RXD		(_MX53_PAD_GPIO_7__FIRI_RXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__SPDIF_PLOCK		(_MX53_PAD_GPIO_7__SPDIF_PLOCK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_7__CCM_PLL2_BYP		(_MX53_PAD_GPIO_7__CCM_PLL2_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__ESAI1_TX5_RX0		(_MX53_PAD_GPIO_8__ESAI1_TX5_RX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__GPIO1_8		(_MX53_PAD_GPIO_8__GPIO1_8 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__EPIT2_EPITO		(_MX53_PAD_GPIO_8__EPIT2_EPITO | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__CAN1_RXCAN		(_MX53_PAD_GPIO_8__CAN1_RXCAN | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__UART2_RXD_MUX		(_MX53_PAD_GPIO_8__UART2_RXD_MUX | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__FIRI_TXD		(_MX53_PAD_GPIO_8__FIRI_TXD | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__SPDIF_SRCLK		(_MX53_PAD_GPIO_8__SPDIF_SRCLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_8__CCM_PLL3_BYP		(_MX53_PAD_GPIO_8__CCM_PLL3_BYP | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__ESAI1_TX3_RX2		(_MX53_PAD_GPIO_16__ESAI1_TX3_RX2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__GPIO7_11		(_MX53_PAD_GPIO_16__GPIO7_11 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT		(_MX53_PAD_GPIO_16__TZIC_PWRFAIL_INT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1		(_MX53_PAD_GPIO_16__RTC_CE_RTC_EXT_TRIG1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__SPDIF_IN1		(_MX53_PAD_GPIO_16__SPDIF_IN1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__I2C3_SDA		(_MX53_PAD_GPIO_16__I2C3_SDA | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_16__SJC_DE_B		(_MX53_PAD_GPIO_16__SJC_DE_B | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__ESAI1_TX0		(_MX53_PAD_GPIO_17__ESAI1_TX0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__GPIO7_12		(_MX53_PAD_GPIO_17__GPIO7_12 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0		(_MX53_PAD_GPIO_17__SDMA_EXT_EVENT_0 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__GPC_PMIC_RDY		(_MX53_PAD_GPIO_17__GPC_PMIC_RDY | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG		(_MX53_PAD_GPIO_17__RTC_CE_RTC_FSV_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__SPDIF_OUT1		(_MX53_PAD_GPIO_17__SPDIF_OUT1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__IPU_SNOOP2		(_MX53_PAD_GPIO_17__IPU_SNOOP2 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_17__SJC_JTAG_ACT		(_MX53_PAD_GPIO_17__SJC_JTAG_ACT | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__ESAI1_TX1		(_MX53_PAD_GPIO_18__ESAI1_TX1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__GPIO7_13		(_MX53_PAD_GPIO_18__GPIO7_13 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1		(_MX53_PAD_GPIO_18__SDMA_EXT_EVENT_1 | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__OWIRE_LINE		(_MX53_PAD_GPIO_18__OWIRE_LINE | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG		(_MX53_PAD_GPIO_18__RTC_CE_RTC_ALARM2_TRIG | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK		(_MX53_PAD_GPIO_18__CCM_ASRC_EXT_CLK | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__ESDHC1_LCTL		(_MX53_PAD_GPIO_18__ESDHC1_LCTL | MUX_PAD_CTRL(NO_PAD_CTRL))
+#define MX53_PAD_GPIO_18__SRC_SYSTEM_RST		(_MX53_PAD_GPIO_18__SRC_SYSTEM_RST | MUX_PAD_CTRL(NO_PAD_CTRL))
 
 #endif	/* __MACH_IOMUX_MX53_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-mxc91231.h	2011-05-19 00:06:34.000000000 -0400
@@ -46,12 +46,12 @@
  * 	- setups the iomux according to the configuration
  * 	- if the pin is configured as a GPIO, we claim it through kernel gpiolib
  */
-int mxc_iomux_alloc_pin(const unsigned int pin_mode, const char *label);
+int mxc_iomux_alloc_pin(unsigned int pin_mode, const char *label);
 /*
  * setups mutliple pins
  * convenient way to call the above function with tables
  */
-int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
+int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
 		const char *label);
 
 /*
@@ -60,12 +60,12 @@
  * 	- frees the GPIO if the pin was configured as GPIO
  * 	- DOES NOT reconfigure the IOMUX in its reset state
  */
-void mxc_iomux_release_pin(const unsigned int pin_mode);
+void mxc_iomux_release_pin(unsigned int pin_mode);
 /*
  * releases multiple pins
  * convenvient way to call the above function with tables
  */
-void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count);
+void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count);
 
 #define MUX_SIDE_AP		(0)
 #define MUX_SIDE_SP		(1)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-v1.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-v1.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/iomux-v1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/iomux-v1.h	2011-05-19 00:06:34.000000000 -0400
@@ -100,4 +100,6 @@
 		const char *label);
 extern void mxc_gpio_release_multiple_pins(const int *pin_list, int count);
 
+extern int __init imx_iomuxv1_init(void __iomem *base, int numports);
+
 #endif /* __MACH_IOMUX_V1_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/irqs.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,17 +23,17 @@
 #define MXC_GPIO_IRQ_START	MXC_INTERNAL_IRQS
 
 /* these are ordered by size to support multi-SoC kernels */
-#if defined CONFIG_ARCH_MX53
+#if defined CONFIG_SOC_IMX53
 #define MXC_GPIO_IRQS		(32 * 7)
 #elif defined CONFIG_ARCH_MX2
 #define MXC_GPIO_IRQS		(32 * 6)
-#elif defined CONFIG_ARCH_MX50
+#elif defined CONFIG_SOC_IMX50
 #define MXC_GPIO_IRQS		(32 * 6)
 #elif defined CONFIG_ARCH_MX1
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MX25
 #define MXC_GPIO_IRQS		(32 * 4)
-#elif defined CONFIG_ARCH_MX51
+#elif defined CONFIG_SOC_IMX51
 #define MXC_GPIO_IRQS		(32 * 4)
 #elif defined CONFIG_ARCH_MXC91231
 #define MXC_GPIO_IRQS		(32 * 4)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,23 +23,23 @@
 
 #if !defined(CONFIG_RUNTIME_PHYS_OFFSET)
 # if defined CONFIG_ARCH_MX1
-#  define PHYS_OFFSET		MX1_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX1_PHYS_OFFSET
 # elif defined CONFIG_MACH_MX21
-#  define PHYS_OFFSET		MX21_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX21_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX25
-#  define PHYS_OFFSET		MX25_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX25_PHYS_OFFSET
 # elif defined CONFIG_MACH_MX27
-#  define PHYS_OFFSET		MX27_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX27_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX3
-#  define PHYS_OFFSET		MX3x_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX3x_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MXC91231
-#  define PHYS_OFFSET		MXC91231_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MXC91231_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX50
-#  define PHYS_OFFSET		MX50_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX50_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX51
-#  define PHYS_OFFSET		MX51_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX51_PHYS_OFFSET
 # elif defined CONFIG_ARCH_MX53
-#  define PHYS_OFFSET		MX53_PHYS_OFFSET
+#  define PLAT_PHYS_OFFSET		MX53_PHYS_OFFSET
 # endif
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx1.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx1.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx1.h	2011-05-19 00:06:34.000000000 -0400
@@ -54,13 +54,13 @@
 #define MX1_AIPI2_BASE_ADDR		(0x10000 + MX1_IO_BASE_ADDR)
 #define MX1_SIM_BASE_ADDR		(0x11000 + MX1_IO_BASE_ADDR)
 #define MX1_USBD_BASE_ADDR		(0x12000 + MX1_IO_BASE_ADDR)
-#define MX1_SPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
+#define MX1_CSPI1_BASE_ADDR		(0x13000 + MX1_IO_BASE_ADDR)
 #define MX1_MMC_BASE_ADDR		(0x14000 + MX1_IO_BASE_ADDR)
 #define MX1_ASP_BASE_ADDR		(0x15000 + MX1_IO_BASE_ADDR)
 #define MX1_BTA_BASE_ADDR		(0x16000 + MX1_IO_BASE_ADDR)
 #define MX1_I2C_BASE_ADDR		(0x17000 + MX1_IO_BASE_ADDR)
 #define MX1_SSI_BASE_ADDR		(0x18000 + MX1_IO_BASE_ADDR)
-#define MX1_SPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
+#define MX1_CSPI2_BASE_ADDR		(0x19000 + MX1_IO_BASE_ADDR)
 #define MX1_MSHC_BASE_ADDR		(0x1A000 + MX1_IO_BASE_ADDR)
 #define MX1_CCM_BASE_ADDR		(0x1B000 + MX1_IO_BASE_ADDR)
 #define MX1_SCM_BASE_ADDR		(0x1B804 + MX1_IO_BASE_ADDR)
@@ -89,7 +89,7 @@
 #define MX1_GPIO_INT_PORTA	11
 #define MX1_GPIO_INT_PORTB	12
 #define MX1_GPIO_INT_PORTC	13
-#define MX1_LCDC_INT		14
+#define MX1_INT_LCDC		14
 #define MX1_SIM_INT		15
 #define MX1_SIM_DATA_INT	16
 #define MX1_RTC_INT		17
@@ -112,7 +112,8 @@
 #define MX1_PWM_INT		34
 #define MX1_SDHC_INT		35
 #define MX1_INT_I2C		39
-#define MX1_CSPI_INT		41
+#define MX1_INT_CSPI2		40
+#define MX1_INT_CSPI1		41
 #define MX1_SSI_TX_INT		42
 #define MX1_SSI_TX_ERR_INT	43
 #define MX1_SSI_RX_INT		44
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx50.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx50.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx50.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx50.h	2011-05-19 00:06:34.000000000 -0400
@@ -282,4 +282,8 @@
 #define MX50_INT_APBHDMA_CHAN6	116
 #define MX50_INT_APBHDMA_CHAN7	117
 
+#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
+extern int mx50_revision(void);
+#endif
+
 #endif /* ifndef __MACH_MX50_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx51.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx51.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx51.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx51.h	2011-05-19 00:06:34.000000000 -0400
@@ -347,6 +347,7 @@
 
 #if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
 extern int mx51_revision(void);
+extern void mx51_display_revision(void);
 #endif
 
 /* tape-out 1 defines */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx53.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx53.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mx53.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mx53.h	2011-05-19 00:06:34.000000000 -0400
@@ -79,7 +79,7 @@
 #define MX53_GPIO3_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0008C000)
 #define MX53_GPIO4_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00090000)
 #define MX53_KPP_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00094000)
-#define MX53_WDOG_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
+#define MX53_WDOG1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x00098000)
 #define MX53_WDOG2_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x0009C000)
 #define MX53_GPT1_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A0000)
 #define MX53_SRTC_BASE_ADDR	(MX53_AIPS1_BASE_ADDR + 0x000A4000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mxc_ehci.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mxc_ehci.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mxc_ehci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mxc_ehci.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,11 +44,14 @@
 	int (*exit)(struct platform_device *pdev);
 
 	unsigned int		 portsc;
-	unsigned int		 flags;
 	struct otg_transceiver	*otg;
 };
 
-int mxc_initialize_usb_hw(int port, unsigned int flags);
+int mx51_initialize_usb_hw(int port, unsigned int flags);
+int mx25_initialize_usb_hw(int port, unsigned int flags);
+int mx31_initialize_usb_hw(int port, unsigned int flags);
+int mx35_initialize_usb_hw(int port, unsigned int flags);
+int mx27_initialize_usb_hw(int port, unsigned int flags);
 
 #endif /* __INCLUDE_ASM_ARCH_MXC_EHCI_H */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mxc.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mxc.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mxc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mxc.h	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,20 @@
 #define IMX_CHIP_REVISION_3_3		0x33
 #define IMX_CHIP_REVISION_UNKNOWN	0xff
 
+#define IMX_CHIP_REVISION_1_0_STRING		"1.0"
+#define IMX_CHIP_REVISION_1_1_STRING		"1.1"
+#define IMX_CHIP_REVISION_1_2_STRING		"1.2"
+#define IMX_CHIP_REVISION_1_3_STRING		"1.3"
+#define IMX_CHIP_REVISION_2_0_STRING		"2.0"
+#define IMX_CHIP_REVISION_2_1_STRING		"2.1"
+#define IMX_CHIP_REVISION_2_2_STRING		"2.2"
+#define IMX_CHIP_REVISION_2_3_STRING		"2.3"
+#define IMX_CHIP_REVISION_3_0_STRING		"3.0"
+#define IMX_CHIP_REVISION_3_1_STRING		"3.1"
+#define IMX_CHIP_REVISION_3_2_STRING		"3.2"
+#define IMX_CHIP_REVISION_3_3_STRING		"3.3"
+#define IMX_CHIP_REVISION_UNKNOWN_STRING	"unknown"
+
 #ifndef __ASSEMBLY__
 extern unsigned int __mxc_cpu_type;
 #endif
@@ -103,7 +117,7 @@
 # define cpu_is_mx27()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX31
+#ifdef CONFIG_SOC_IMX31
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -115,7 +129,7 @@
 # define cpu_is_mx31()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX35
+#ifdef CONFIG_SOC_IMX35
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -127,7 +141,7 @@
 # define cpu_is_mx35()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX50
+#ifdef CONFIG_SOC_IMX50
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -139,7 +153,7 @@
 # define cpu_is_mx50()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX51
+#ifdef CONFIG_SOC_IMX51
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -151,7 +165,7 @@
 # define cpu_is_mx51()		(0)
 #endif
 
-#ifdef CONFIG_ARCH_MX53
+#ifdef CONFIG_SOC_IMX53
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
 #  define mxc_cpu_type __mxc_cpu_type
@@ -181,6 +195,15 @@
 	u32 cpu_rate;
 };
 
+int tzic_enable_wake(int is_idle);
+enum mxc_cpu_pwr_mode {
+	WAIT_CLOCKED,		/* wfi only */
+	WAIT_UNCLOCKED,		/* WAIT */
+	WAIT_UNCLOCKED_POWER_OFF,	/* WAIT + SRPG */
+	STOP_POWER_ON,		/* just STOP */
+	STOP_POWER_OFF,		/* STOP + SRPG */
+};
+
 extern struct cpu_op *(*get_cpu_op)(int *op);
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mxc_nand.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mxc_nand.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/mxc_nand.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/mxc_nand.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 
 struct mxc_nand_platform_data {
 	unsigned int width;	/* data bus width in bytes */
-	unsigned int hw_ecc:1;	/* 0 if supress hardware ECC */
+	unsigned int hw_ecc:1;	/* 0 if suppress hardware ECC */
 	unsigned int flash_bbt:1; /* set to 1 to use a flash based bbt */
 	struct mtd_partition *parts;	/* partition table */
 	int nr_parts;			/* size of parts */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/system.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/system.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,8 @@
 #include <mach/hardware.h>
 #include <mach/common.h>
 
+extern void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode);
+
 static inline void arch_idle(void)
 {
 #ifdef CONFIG_ARCH_MXC91231
@@ -54,7 +56,9 @@
 			"orr %0, %0, #0x00000004\n"
 			"mcr p15, 0, %0, c1, c0, 0\n"
 			: "=r" (reg));
-	} else
+	} else if (cpu_is_mx51())
+		mx5_cpu_lp_set(WAIT_UNCLOCKED_POWER_OFF);
+	else
 		cpu_do_idle();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/ulpi.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/ulpi.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/ulpi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/ulpi.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,15 @@
 #ifndef __MACH_ULPI_H
 #define __MACH_ULPI_H
 
+#ifdef CONFIG_USB_ULPI
+struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags);
+#else
+static inline struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags)
+{
+	return NULL;
+}
+#endif
+
 extern struct otg_io_access_ops mxc_ulpi_access_ops;
 
 #endif /* __MACH_ULPI_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/include/mach/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -62,6 +62,7 @@
 #define MX2X_UART1_BASE_ADDR	0x1000a000
 #define MX3X_UART1_BASE_ADDR	0x43F90000
 #define MX3X_UART2_BASE_ADDR	0x43F94000
+#define MX3X_UART5_BASE_ADDR	0x43FB4000
 #define MX51_UART1_BASE_ADDR	0x73fbc000
 #define MX50_UART1_BASE_ADDR	0x53fbc000
 #define MX53_UART1_BASE_ADDR	0x53fbc000
@@ -83,6 +84,7 @@
 	case MACH_TYPE_MX21ADS:
 	case MACH_TYPE_PCA100:
 	case MACH_TYPE_MXT_TD60:
+	case MACH_TYPE_IMX27IPCAM:
 		uart_base = MX2X_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX31LITE:
@@ -101,6 +103,9 @@
 	case MACH_TYPE_MAGX_ZN5:
 		uart_base = MX3X_UART2_BASE_ADDR;
 		break;
+	case MACH_TYPE_BUG:
+		uart_base = MX3X_UART5_BASE_ADDR;
+		break;
 	case MACH_TYPE_MX51_BABBAGE:
 	case MACH_TYPE_EUKREA_CPUIMX51SD:
 	case MACH_TYPE_MX51_3DS:
@@ -110,6 +115,8 @@
 		uart_base = MX50_UART1_BASE_ADDR;
 		break;
 	case MACH_TYPE_MX53_EVK:
+	case MACH_TYPE_MX53_LOCO:
+	case MACH_TYPE_MX53_SMD:
 		uart_base = MX53_UART1_BASE_ADDR;
 		break;
 	default:
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/iomux-v1.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/iomux-v1.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/iomux-v1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/iomux-v1.c	2011-05-19 00:06:34.000000000 -0400
@@ -211,28 +211,10 @@
 }
 EXPORT_SYMBOL(mxc_gpio_release_multiple_pins);
 
-static int imx_iomuxv1_init(void)
+int __init imx_iomuxv1_init(void __iomem *base, int numports)
 {
-#ifdef CONFIG_ARCH_MX1
-	if (cpu_is_mx1()) {
-		imx_iomuxv1_baseaddr = MX1_IO_ADDRESS(MX1_GPIO_BASE_ADDR);
-		imx_iomuxv1_numports = MX1_NUM_GPIO_PORT;
-	} else
-#endif
-#ifdef CONFIG_MACH_MX21
-	if (cpu_is_mx21()) {
-		imx_iomuxv1_baseaddr = MX21_IO_ADDRESS(MX21_GPIO_BASE_ADDR);
-		imx_iomuxv1_numports = MX21_NUM_GPIO_PORT;
-	} else
-#endif
-#ifdef CONFIG_MACH_MX27
-	if (cpu_is_mx27()) {
-		imx_iomuxv1_baseaddr = MX27_IO_ADDRESS(MX27_GPIO_BASE_ADDR);
-		imx_iomuxv1_numports = MX27_NUM_GPIO_PORT;
-	} else
-#endif
-		return -ENODEV;
+	imx_iomuxv1_baseaddr = base;
+	imx_iomuxv1_numports = numports;
 
 	return 0;
 }
-pure_initcall(imx_iomuxv1_init);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/irq-common.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/irq-common.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/irq-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/irq-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 
 	ret = -ENOSYS;
 
-	base = get_irq_chip(irq);
+	base = irq_get_chip(irq);
 	if (base) {
 		chip = container_of(base, struct mxc_irq_chip, base);
 		if (chip->set_priority)
@@ -48,7 +48,7 @@
 
 	ret = -ENOSYS;
 
-	base = get_irq_chip(irq);
+	base = irq_get_chip(irq);
 	if (base) {
 		chip = container_of(base, struct mxc_irq_chip, base);
 		if (chip->set_irq_fiq)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/Kconfig linux-libre-2.6.39-gnu/arch/arm/plat-mxc/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,7 @@
 config ARCH_MXC91231
 	bool "MXC91231-based"
 	select CPU_V6
+	select MXC_AVIC
 	help
 	  This enables support for systems based on the Freescale MXC91231 family
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/Makefile linux-libre-2.6.39-gnu/arch/arm/plat-mxc/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,6 @@
 obj-$(CONFIG_ARCH_MXC_IOMUX_V3) += iomux-v3.o
 obj-$(CONFIG_IRAM_ALLOC) += iram_alloc.o
 obj-$(CONFIG_MXC_PWM)  += pwm.o
-obj-$(CONFIG_USB_EHCI_MXC) += ehci.o
 obj-$(CONFIG_MXC_ULPI) += ulpi.o
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_ARCH_MXC_AUDMUX_V1) += audmux-v1.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/ssi-fiq.S linux-libre-2.6.39-gnu/arch/arm/plat-mxc/ssi-fiq.S
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/ssi-fiq.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/ssi-fiq.S	2011-05-19 00:06:34.000000000 -0400
@@ -124,6 +124,8 @@
 1:
 		@ return from FIQ
 		subs	pc, lr, #4
+
+		.align
 imx_ssi_fiq_base:
 		.word 0x0
 imx_ssi_fiq_rx_buffer:
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/time.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/time.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 
 #include <mach/hardware.h>
+#include <asm/sched_clock.h>
 #include <asm/mach/time.h>
 #include <mach/common.h>
 
@@ -105,6 +106,11 @@
 		__raw_writel(V2_TSTAT_OF1, timer_base + V2_TSTAT);
 }
 
+static cycle_t dummy_get_cycles(struct clocksource *cs)
+{
+	return 0;
+}
+
 static cycle_t mx1_2_get_cycles(struct clocksource *cs)
 {
 	return __raw_readl(timer_base + MX1_2_TCN);
@@ -118,18 +124,35 @@
 static struct clocksource clocksource_mxc = {
 	.name 		= "mxc_timer1",
 	.rating		= 200,
-	.read		= mx1_2_get_cycles,
+	.read		= dummy_get_cycles,
 	.mask		= CLOCKSOURCE_MASK(32),
 	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
 };
 
+static DEFINE_CLOCK_DATA(cd);
+unsigned long long notrace sched_clock(void)
+{
+	cycle_t cyc = clocksource_mxc.read(&clocksource_mxc);
+
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace mxc_update_sched_clock(void)
+{
+	cycle_t cyc = clocksource_mxc.read(&clocksource_mxc);
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
 static int __init mxc_clocksource_init(struct clk *timer_clk)
 {
 	unsigned int c = clk_get_rate(timer_clk);
 
 	if (timer_is_v2())
 		clocksource_mxc.read = v2_get_cycles;
+	else
+		clocksource_mxc.read = mx1_2_get_cycles;
 
+	init_sched_clock(&cd, mxc_update_sched_clock, 32, c);
 	clocksource_register_hz(&clocksource_mxc, c);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/tzic.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/tzic.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/tzic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/tzic.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,8 +167,8 @@
 	/* all IRQ no FIQ Warning :: No selection */
 
 	for (i = 0; i < MXC_INTERNAL_IRQS; i++) {
-		set_irq_chip(i, &mxc_tzic_chip.base);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, &mxc_tzic_chip.base,
+					 handle_level_irq);
 		set_irq_flags(i, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-mxc/ulpi.c linux-libre-2.6.39-gnu/arch/arm/plat-mxc/ulpi.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-mxc/ulpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-mxc/ulpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
+#include <linux/usb/ulpi.h>
 
 #include <mach/ulpi.h>
 
@@ -111,3 +112,7 @@
 };
 EXPORT_SYMBOL_GPL(mxc_ulpi_access_ops);
 
+struct otg_transceiver *imx_otg_ulpi_create(unsigned int flags)
+{
+	return otg_ulpi_create(&mxc_ulpi_access_ops, flags);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-nomadik/gpio.c linux-libre-2.6.39-gnu/arch/arm/plat-nomadik/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-nomadik/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-nomadik/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,23 +30,40 @@
 /*
  * The GPIO module in the Nomadik family of Systems-on-Chip is an
  * AMBA device, managing 32 pins and alternate functions.  The logic block
- * is currently only used in the Nomadik.
+ * is currently used in the Nomadik and ux500.
  *
  * Symbols in this file are called "nmk_gpio" for "nomadik gpio"
  */
 
-#define NMK_GPIO_PER_CHIP 32
+#define NMK_GPIO_PER_CHIP	32
+
 struct nmk_gpio_chip {
 	struct gpio_chip chip;
 	void __iomem *addr;
 	struct clk *clk;
+	unsigned int bank;
 	unsigned int parent_irq;
+	int secondary_parent_irq;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
 	spinlock_t lock;
 	/* Keep track of configured edges */
 	u32 edge_rising;
 	u32 edge_falling;
+	u32 real_wake;
+	u32 rwimsc;
+	u32 fwimsc;
+	u32 slpm;
+	u32 enabled;
 };
 
+static struct nmk_gpio_chip *
+nmk_gpio_chips[DIV_ROUND_UP(ARCH_NR_GPIOS, NMK_GPIO_PER_CHIP)];
+
+static DEFINE_SPINLOCK(nmk_gpio_slpm_lock);
+
+#define NUM_BANKS ARRAY_SIZE(nmk_gpio_chips)
+
 static void __nmk_gpio_set_mode(struct nmk_gpio_chip *nmk_chip,
 				unsigned offset, int gpio_mode)
 {
@@ -118,8 +135,35 @@
 	__nmk_gpio_set_output(nmk_chip, offset, val);
 }
 
+static void __nmk_gpio_set_mode_safe(struct nmk_gpio_chip *nmk_chip,
+				     unsigned offset, int gpio_mode,
+				     bool glitch)
+{
+	u32 rwimsc = readl(nmk_chip->addr + NMK_GPIO_RWIMSC);
+	u32 fwimsc = readl(nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+	if (glitch && nmk_chip->set_ioforce) {
+		u32 bit = BIT(offset);
+
+		/* Prevent spurious wakeups */
+		writel(rwimsc & ~bit, nmk_chip->addr + NMK_GPIO_RWIMSC);
+		writel(fwimsc & ~bit, nmk_chip->addr + NMK_GPIO_FWIMSC);
+
+		nmk_chip->set_ioforce(true);
+	}
+
+	__nmk_gpio_set_mode(nmk_chip, offset, gpio_mode);
+
+	if (glitch && nmk_chip->set_ioforce) {
+		nmk_chip->set_ioforce(false);
+
+		writel(rwimsc, nmk_chip->addr + NMK_GPIO_RWIMSC);
+		writel(fwimsc, nmk_chip->addr + NMK_GPIO_FWIMSC);
+	}
+}
+
 static void __nmk_config_pin(struct nmk_gpio_chip *nmk_chip, unsigned offset,
-			     pin_cfg_t cfg, bool sleep)
+			     pin_cfg_t cfg, bool sleep, unsigned int *slpmregs)
 {
 	static const char *afnames[] = {
 		[NMK_GPIO_ALT_GPIO]	= "GPIO",
@@ -144,6 +188,7 @@
 	int slpm = PIN_SLPM(cfg);
 	int output = PIN_DIR(cfg);
 	int val = PIN_VAL(cfg);
+	bool glitch = af == NMK_GPIO_ALT_C;
 
 	dev_dbg(nmk_chip->chip.dev, "pin %d [%#lx]: af %s, pull %s, slpm %s (%s%s)\n",
 		pin, cfg, afnames[af], pullnames[pull], slpmnames[slpm],
@@ -155,6 +200,8 @@
 		int slpm_output = PIN_SLPM_DIR(cfg);
 		int slpm_val = PIN_SLPM_VAL(cfg);
 
+		af = NMK_GPIO_ALT_GPIO;
+
 		/*
 		 * The SLPM_* values are normal values + 1 to allow zero to
 		 * mean "same as normal".
@@ -180,8 +227,116 @@
 		__nmk_gpio_set_pull(nmk_chip, offset, pull);
 	}
 
-	__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
-	__nmk_gpio_set_mode(nmk_chip, offset, af);
+	/*
+	 * If we've backed up the SLPM registers (glitch workaround), modify
+	 * the backups since they will be restored.
+	 */
+	if (slpmregs) {
+		if (slpm == NMK_GPIO_SLPM_NOCHANGE)
+			slpmregs[nmk_chip->bank] |= BIT(offset);
+		else
+			slpmregs[nmk_chip->bank] &= ~BIT(offset);
+	} else
+		__nmk_gpio_set_slpm(nmk_chip, offset, slpm);
+
+	__nmk_gpio_set_mode_safe(nmk_chip, offset, af, glitch);
+}
+
+/*
+ * Safe sequence used to switch IOs between GPIO and Alternate-C mode:
+ *  - Save SLPM registers
+ *  - Set SLPM=0 for the IOs you want to switch and others to 1
+ *  - Configure the GPIO registers for the IOs that are being switched
+ *  - Set IOFORCE=1
+ *  - Modify the AFLSA/B registers for the IOs that are being switched
+ *  - Set IOFORCE=0
+ *  - Restore SLPM registers
+ *  - Any spurious wake up event during switch sequence to be ignored and
+ *    cleared
+ */
+static void nmk_gpio_glitch_slpm_init(unsigned int *slpm)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+		unsigned int temp = slpm[i];
+
+		if (!chip)
+			break;
+
+		slpm[i] = readl(chip->addr + NMK_GPIO_SLPC);
+		writel(temp, chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
+static void nmk_gpio_glitch_slpm_restore(unsigned int *slpm)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		writel(slpm[i], chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
+static int __nmk_config_pins(pin_cfg_t *cfgs, int num, bool sleep)
+{
+	static unsigned int slpm[NUM_BANKS];
+	unsigned long flags;
+	bool glitch = false;
+	int ret = 0;
+	int i;
+
+	for (i = 0; i < num; i++) {
+		if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C) {
+			glitch = true;
+			break;
+		}
+	}
+
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+
+	if (glitch) {
+		memset(slpm, 0xff, sizeof(slpm));
+
+		for (i = 0; i < num; i++) {
+			int pin = PIN_NUM(cfgs[i]);
+			int offset = pin % NMK_GPIO_PER_CHIP;
+
+			if (PIN_ALT(cfgs[i]) == NMK_GPIO_ALT_C)
+				slpm[pin / NMK_GPIO_PER_CHIP] &= ~BIT(offset);
+		}
+
+		nmk_gpio_glitch_slpm_init(slpm);
+	}
+
+	for (i = 0; i < num; i++) {
+		struct nmk_gpio_chip *nmk_chip;
+		int pin = PIN_NUM(cfgs[i]);
+
+		nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(pin));
+		if (!nmk_chip) {
+			ret = -EINVAL;
+			break;
+		}
+
+		spin_lock(&nmk_chip->lock);
+		__nmk_config_pin(nmk_chip, pin - nmk_chip->chip.base,
+				 cfgs[i], sleep, glitch ? slpm : NULL);
+		spin_unlock(&nmk_chip->lock);
+	}
+
+	if (glitch)
+		nmk_gpio_glitch_slpm_restore(slpm);
+
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
+
+	return ret;
 }
 
 /**
@@ -200,19 +355,7 @@
  */
 int nmk_config_pin(pin_cfg_t cfg, bool sleep)
 {
-	struct nmk_gpio_chip *nmk_chip;
-	int gpio = PIN_NUM(cfg);
-	unsigned long flags;
-
-	nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
-	if (!nmk_chip)
-		return -EINVAL;
-
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_config_pin(nmk_chip, gpio - nmk_chip->chip.base, cfg, sleep);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
-
-	return 0;
+	return __nmk_config_pins(&cfg, 1, sleep);
 }
 EXPORT_SYMBOL(nmk_config_pin);
 
@@ -226,31 +369,13 @@
  */
 int nmk_config_pins(pin_cfg_t *cfgs, int num)
 {
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < num; i++) {
-		ret = nmk_config_pin(cfgs[i], false);
-		if (ret)
-			break;
-	}
-
-	return ret;
+	return __nmk_config_pins(cfgs, num, false);
 }
 EXPORT_SYMBOL(nmk_config_pins);
 
 int nmk_config_pins_sleep(pin_cfg_t *cfgs, int num)
 {
-	int ret = 0;
-	int i;
-
-	for (i = 0; i < num; i++) {
-		ret = nmk_config_pin(cfgs[i], true);
-		if (ret)
-			break;
-	}
-
-	return ret;
+	return __nmk_config_pins(cfgs, num, true);
 }
 EXPORT_SYMBOL(nmk_config_pins_sleep);
 
@@ -273,13 +398,17 @@
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 
-	nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+	nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
 	if (!nmk_chip)
 		return -EINVAL;
 
-	spin_lock_irqsave(&nmk_chip->lock, flags);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
 	__nmk_gpio_set_slpm(nmk_chip, gpio - nmk_chip->chip.base, mode);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 
 	return 0;
 }
@@ -302,7 +431,7 @@
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 
-	nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+	nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
 	if (!nmk_chip)
 		return -EINVAL;
 
@@ -314,12 +443,21 @@
 }
 
 /* Mode functions */
+/**
+ * nmk_gpio_set_mode() - set the mux mode of a gpio pin
+ * @gpio: pin number
+ * @gpio_mode: one of NMK_GPIO_ALT_GPIO, NMK_GPIO_ALT_A,
+ *	       NMK_GPIO_ALT_B, and NMK_GPIO_ALT_C
+ *
+ * Sets the mode of the specified pin to one of the alternate functions or
+ * plain GPIO.
+ */
 int nmk_gpio_set_mode(int gpio, int gpio_mode)
 {
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
 
-	nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+	nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
 	if (!nmk_chip)
 		return -EINVAL;
 
@@ -336,7 +474,7 @@
 	struct nmk_gpio_chip *nmk_chip;
 	u32 afunc, bfunc, bit;
 
-	nmk_chip = get_irq_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
+	nmk_chip = irq_get_chip_data(NOMADIK_GPIO_TO_IRQ(gpio));
 	if (!nmk_chip)
 		return -EINVAL;
 
@@ -401,8 +539,13 @@
 	}
 }
 
-static int nmk_gpio_irq_modify(struct irq_data *d, enum nmk_gpio_irq_type which,
-			       bool enable)
+static void __nmk_gpio_set_wake(struct nmk_gpio_chip *nmk_chip,
+				int gpio, bool on)
+{
+	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
+}
+
+static int nmk_gpio_irq_maskunmask(struct irq_data *d, bool enable)
 {
 	int gpio;
 	struct nmk_gpio_chip *nmk_chip;
@@ -415,53 +558,68 @@
 	if (!nmk_chip)
 		return -EINVAL;
 
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-	__nmk_gpio_irq_modify(nmk_chip, gpio, which, enable);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	if (enable)
+		nmk_chip->enabled |= bitmask;
+	else
+		nmk_chip->enabled &= ~bitmask;
+
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
+	__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, enable);
+
+	if (!(nmk_chip->real_wake & bitmask))
+		__nmk_gpio_set_wake(nmk_chip, gpio, enable);
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 
 	return 0;
 }
 
 static void nmk_gpio_irq_mask(struct irq_data *d)
 {
-	nmk_gpio_irq_modify(d, NORMAL, false);
+	nmk_gpio_irq_maskunmask(d, false);
 }
 
 static void nmk_gpio_irq_unmask(struct irq_data *d)
 {
-	nmk_gpio_irq_modify(d, NORMAL, true);
+	nmk_gpio_irq_maskunmask(d, true);
 }
 
 static int nmk_gpio_irq_set_wake(struct irq_data *d, unsigned int on)
 {
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
+	u32 bitmask;
 	int gpio;
 
 	gpio = NOMADIK_IRQ_TO_GPIO(d->irq);
 	nmk_chip = irq_data_get_irq_chip_data(d);
 	if (!nmk_chip)
 		return -EINVAL;
+	bitmask = nmk_gpio_get_bitmask(gpio);
 
-	spin_lock_irqsave(&nmk_chip->lock, flags);
-#ifdef CONFIG_ARCH_U8500
-	if (cpu_is_u8500v2()) {
-		__nmk_gpio_set_slpm(nmk_chip, gpio,
-				    on ? NMK_GPIO_SLPM_WAKEUP_ENABLE
-				       : NMK_GPIO_SLPM_WAKEUP_DISABLE);
-	}
-#endif
-	__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, on);
-	spin_unlock_irqrestore(&nmk_chip->lock, flags);
+	spin_lock_irqsave(&nmk_gpio_slpm_lock, flags);
+	spin_lock(&nmk_chip->lock);
+
+	if (!(nmk_chip->enabled & bitmask))
+		__nmk_gpio_set_wake(nmk_chip, gpio, on);
+
+	if (on)
+		nmk_chip->real_wake |= bitmask;
+	else
+		nmk_chip->real_wake &= ~bitmask;
+
+	spin_unlock(&nmk_chip->lock);
+	spin_unlock_irqrestore(&nmk_gpio_slpm_lock, flags);
 
 	return 0;
 }
 
 static int nmk_gpio_irq_set_type(struct irq_data *d, unsigned int type)
 {
-	struct irq_desc *desc = irq_to_desc(d->irq);
-	bool enabled = !(desc->status & IRQ_DISABLED);
-	bool wake = desc->wake_depth;
+	bool enabled, wake = irqd_is_wakeup_set(d);
 	int gpio;
 	struct nmk_gpio_chip *nmk_chip;
 	unsigned long flags;
@@ -478,12 +636,14 @@
 	if (type & IRQ_TYPE_LEVEL_LOW)
 		return -EINVAL;
 
+	enabled = nmk_chip->enabled & bitmask;
+
 	spin_lock_irqsave(&nmk_chip->lock, flags);
 
 	if (enabled)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, false);
 
-	if (wake)
+	if (enabled || wake)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, false);
 
 	nmk_chip->edge_rising &= ~bitmask;
@@ -497,7 +657,7 @@
 	if (enabled)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, NORMAL, true);
 
-	if (wake)
+	if (enabled || wake)
 		__nmk_gpio_irq_modify(nmk_chip, gpio, WAKE, true);
 
 	spin_unlock_irqrestore(&nmk_chip->lock, flags);
@@ -514,12 +674,11 @@
 	.irq_set_wake	= nmk_gpio_irq_set_wake,
 };
 
-static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+static void __nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc,
+				   u32 status)
 {
 	struct nmk_gpio_chip *nmk_chip;
-	struct irq_chip *host_chip = get_irq_chip(irq);
-	unsigned int gpio_irq;
-	u32 pending;
+	struct irq_chip *host_chip = irq_get_chip(irq);
 	unsigned int first_irq;
 
 	if (host_chip->irq_mask_ack)
@@ -530,31 +689,58 @@
 			host_chip->irq_ack(&desc->irq_data);
 	}
 
-	nmk_chip = get_irq_data(irq);
+	nmk_chip = irq_get_handler_data(irq);
 	first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-	while ( (pending = readl(nmk_chip->addr + NMK_GPIO_IS)) ) {
-		gpio_irq = first_irq + __ffs(pending);
-		generic_handle_irq(gpio_irq);
+	while (status) {
+		int bit = __ffs(status);
+
+		generic_handle_irq(first_irq + bit);
+		status &= ~BIT(bit);
 	}
 
 	host_chip->irq_unmask(&desc->irq_data);
 }
 
+static void nmk_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
+	u32 status = readl(nmk_chip->addr + NMK_GPIO_IS);
+
+	__nmk_gpio_irq_handler(irq, desc, status);
+}
+
+static void nmk_gpio_secondary_irq_handler(unsigned int irq,
+					   struct irq_desc *desc)
+{
+	struct nmk_gpio_chip *nmk_chip = irq_get_handler_data(irq);
+	u32 status = nmk_chip->get_secondary_status(nmk_chip->bank);
+
+	__nmk_gpio_irq_handler(irq, desc, status);
+}
+
 static int nmk_gpio_init_irq(struct nmk_gpio_chip *nmk_chip)
 {
 	unsigned int first_irq;
 	int i;
 
 	first_irq = NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base);
-	for (i = first_irq; i < first_irq + NMK_GPIO_PER_CHIP; i++) {
-		set_irq_chip(i, &nmk_gpio_irq_chip);
-		set_irq_handler(i, handle_edge_irq);
+	for (i = first_irq; i < first_irq + nmk_chip->chip.ngpio; i++) {
+		irq_set_chip_and_handler(i, &nmk_gpio_irq_chip,
+					 handle_edge_irq);
 		set_irq_flags(i, IRQF_VALID);
-		set_irq_chip_data(i, nmk_chip);
-		set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
+		irq_set_chip_data(i, nmk_chip);
+		irq_set_irq_type(i, IRQ_TYPE_EDGE_FALLING);
 	}
-	set_irq_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
-	set_irq_data(nmk_chip->parent_irq, nmk_chip);
+
+	irq_set_chained_handler(nmk_chip->parent_irq, nmk_gpio_irq_handler);
+	irq_set_handler_data(nmk_chip->parent_irq, nmk_chip);
+
+	if (nmk_chip->secondary_parent_irq >= 0) {
+		irq_set_chained_handler(nmk_chip->secondary_parent_irq,
+					nmk_gpio_secondary_irq_handler);
+		irq_set_handler_data(nmk_chip->secondary_parent_irq, nmk_chip);
+	}
+
 	return 0;
 }
 
@@ -605,6 +791,52 @@
 	return NOMADIK_GPIO_TO_IRQ(nmk_chip->chip.base) + offset;
 }
 
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/seq_file.h>
+
+static void nmk_gpio_dbg_show(struct seq_file *s, struct gpio_chip *chip)
+{
+	int mode;
+	unsigned		i;
+	unsigned		gpio = chip->base;
+	int			is_out;
+	struct nmk_gpio_chip *nmk_chip =
+		container_of(chip, struct nmk_gpio_chip, chip);
+	const char *modes[] = {
+		[NMK_GPIO_ALT_GPIO]	= "gpio",
+		[NMK_GPIO_ALT_A]	= "altA",
+		[NMK_GPIO_ALT_B]	= "altB",
+		[NMK_GPIO_ALT_C]	= "altC",
+	};
+
+	for (i = 0; i < chip->ngpio; i++, gpio++) {
+		const char *label = gpiochip_is_requested(chip, i);
+		bool pull;
+		u32 bit = 1 << i;
+
+		if (!label)
+			continue;
+
+		is_out = readl(nmk_chip->addr + NMK_GPIO_DIR) & bit;
+		pull = !(readl(nmk_chip->addr + NMK_GPIO_PDIS) & bit);
+		mode = nmk_gpio_get_mode(gpio);
+		seq_printf(s, " gpio-%-3d (%-20.20s) %s %s %s %s",
+			gpio, label,
+			is_out ? "out" : "in ",
+			chip->get
+				? (chip->get(chip, i) ? "hi" : "lo")
+				: "?  ",
+			(mode < 0) ? "unknown" : modes[mode],
+			pull ? "pull" : "none");
+		seq_printf(s, "\n");
+	}
+}
+
+#else
+#define nmk_gpio_dbg_show	NULL
+#endif
+
 /* This structure is replicated for each GPIO block allocated at probe time */
 static struct gpio_chip nmk_gpio_template = {
 	.direction_input	= nmk_gpio_make_input,
@@ -612,10 +844,64 @@
 	.direction_output	= nmk_gpio_make_output,
 	.set			= nmk_gpio_set_output,
 	.to_irq			= nmk_gpio_to_irq,
-	.ngpio			= NMK_GPIO_PER_CHIP,
+	.dbg_show		= nmk_gpio_dbg_show,
 	.can_sleep		= 0,
 };
 
+/*
+ * Called from the suspend/resume path to only keep the real wakeup interrupts
+ * (those that have had set_irq_wake() called on them) as wakeup interrupts,
+ * and not the rest of the interrupts which we needed to have as wakeups for
+ * cpuidle.
+ *
+ * PM ops are not used since this needs to be done at the end, after all the
+ * other drivers are done with their suspend callbacks.
+ */
+void nmk_gpio_wakeups_suspend(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		chip->rwimsc = readl(chip->addr + NMK_GPIO_RWIMSC);
+		chip->fwimsc = readl(chip->addr + NMK_GPIO_FWIMSC);
+
+		writel(chip->rwimsc & chip->real_wake,
+		       chip->addr + NMK_GPIO_RWIMSC);
+		writel(chip->fwimsc & chip->real_wake,
+		       chip->addr + NMK_GPIO_FWIMSC);
+
+		if (cpu_is_u8500v2()) {
+			chip->slpm = readl(chip->addr + NMK_GPIO_SLPC);
+
+			/* 0 -> wakeup enable */
+			writel(~chip->real_wake, chip->addr + NMK_GPIO_SLPC);
+		}
+	}
+}
+
+void nmk_gpio_wakeups_resume(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_BANKS; i++) {
+		struct nmk_gpio_chip *chip = nmk_gpio_chips[i];
+
+		if (!chip)
+			break;
+
+		writel(chip->rwimsc, chip->addr + NMK_GPIO_RWIMSC);
+		writel(chip->fwimsc, chip->addr + NMK_GPIO_FWIMSC);
+
+		if (cpu_is_u8500v2())
+			writel(chip->slpm, chip->addr + NMK_GPIO_SLPC);
+	}
+}
+
 static int __devinit nmk_gpio_probe(struct platform_device *dev)
 {
 	struct nmk_gpio_platform_data *pdata = dev->dev.platform_data;
@@ -623,6 +909,7 @@
 	struct gpio_chip *chip;
 	struct resource *res;
 	struct clk *clk;
+	int secondary_irq;
 	int irq;
 	int ret;
 
@@ -641,6 +928,12 @@
 		goto out;
 	}
 
+	secondary_irq = platform_get_irq(dev, 1);
+	if (secondary_irq >= 0 && !pdata->get_secondary_status) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	if (request_mem_region(res->start, resource_size(res),
 			       dev_name(&dev->dev)) == NULL) {
 		ret = -EBUSY;
@@ -664,14 +957,19 @@
 	 * The virt address in nmk_chip->addr is in the nomadik register space,
 	 * so we can simply convert the resource address, without remapping
 	 */
+	nmk_chip->bank = dev->id;
 	nmk_chip->clk = clk;
 	nmk_chip->addr = io_p2v(res->start);
 	nmk_chip->chip = nmk_gpio_template;
 	nmk_chip->parent_irq = irq;
+	nmk_chip->secondary_parent_irq = secondary_irq;
+	nmk_chip->get_secondary_status = pdata->get_secondary_status;
+	nmk_chip->set_ioforce = pdata->set_ioforce;
 	spin_lock_init(&nmk_chip->lock);
 
 	chip = &nmk_chip->chip;
 	chip->base = pdata->first_gpio;
+	chip->ngpio = pdata->num_gpio;
 	chip->label = pdata->name ?: dev_name(&dev->dev);
 	chip->dev = &dev->dev;
 	chip->owner = THIS_MODULE;
@@ -680,6 +978,9 @@
 	if (ret)
 		goto out_free;
 
+	BUG_ON(nmk_chip->bank >= ARRAY_SIZE(nmk_gpio_chips));
+
+	nmk_gpio_chips[nmk_chip->bank] = nmk_chip;
 	platform_set_drvdata(dev, nmk_chip);
 
 	nmk_gpio_init_irq(nmk_chip);
@@ -705,10 +1006,8 @@
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "gpio",
-		},
+	},
 	.probe = nmk_gpio_probe,
-	.suspend = NULL, /* to be done */
-	.resume = NULL,
 };
 
 static int __init nmk_gpio_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-nomadik/include/plat/gpio.h linux-libre-2.6.39-gnu/arch/arm/plat-nomadik/include/plat/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-nomadik/include/plat/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-nomadik/include/plat/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -75,6 +75,9 @@
 extern int nmk_gpio_set_mode(int gpio, int gpio_mode);
 extern int nmk_gpio_get_mode(int gpio);
 
+extern void nmk_gpio_wakeups_suspend(void);
+extern void nmk_gpio_wakeups_resume(void);
+
 /*
  * Platform data to register a block: only the initial gpio/irq number.
  */
@@ -82,6 +85,9 @@
 	char *name;
 	int first_gpio;
 	int first_irq;
+	int num_gpio;
+	u32 (*get_secondary_status)(unsigned int bank);
+	void (*set_ioforce)(bool enable);
 };
 
 #endif /* __ASM_PLAT_GPIO_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-nomadik/include/plat/ste_dma40.h linux-libre-2.6.39-gnu/arch/arm/plat-nomadik/include/plat/ste_dma40.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-nomadik/include/plat/ste_dma40.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-nomadik/include/plat/ste_dma40.h	2011-05-19 00:06:34.000000000 -0400
@@ -104,6 +104,8 @@
  *
  * @dir: MEM 2 MEM, PERIPH 2 MEM , MEM 2 PERIPH, PERIPH 2 PERIPH
  * @high_priority: true if high-priority
+ * @realtime: true if realtime mode is to be enabled.  Only available on DMA40
+ * version 3+, i.e DB8500v2+
  * @mode: channel mode: physical, logical, or operation
  * @mode_opt: options for the chosen channel mode
  * @src_dev_type: Src device type
@@ -119,6 +121,7 @@
 struct stedma40_chan_cfg {
 	enum stedma40_xfer_dir			 dir;
 	bool					 high_priority;
+	bool					 realtime;
 	enum stedma40_mode			 mode;
 	enum stedma40_mode_opt			 mode_opt;
 	int					 src_dev_type;
@@ -169,25 +172,6 @@
 bool stedma40_filter(struct dma_chan *chan, void *data);
 
 /**
- * stedma40_memcpy_sg() - extension of the dma framework, memcpy to/from
- * scattergatter lists.
- *
- * @chan: dmaengine handle
- * @sgl_dst: Destination scatter list
- * @sgl_src: Source scatter list
- * @sgl_len: The length of each scatterlist. Both lists must be of equal length
- * and each element must match the corresponding element in the other scatter
- * list.
- * @flags: is actually enum dma_ctrl_flags. See dmaengine.h
- */
-
-struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan,
-						   struct scatterlist *sgl_dst,
-						   struct scatterlist *sgl_src,
-						   unsigned int sgl_len,
-						   unsigned long flags);
-
-/**
  * stedma40_slave_mem() - Transfers a raw data buffer to or from a slave
  * (=device)
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/clock.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,14 +37,16 @@
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
-	int ret = 0;
+	int ret;
 
 	if (clk == NULL || IS_ERR(clk))
 		return -EINVAL;
 
+	if (!arch_clock || !arch_clock->clk_enable)
+		return -EINVAL;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_enable)
-		ret = arch_clock->clk_enable(clk);
+	ret = arch_clock->clk_enable(clk);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -58,6 +60,9 @@
 	if (clk == NULL || IS_ERR(clk))
 		return;
 
+	if (!arch_clock || !arch_clock->clk_disable)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
 		pr_err("Trying disable clock %s with 0 usecount\n",
@@ -66,8 +71,7 @@
 		goto out;
 	}
 
-	if (arch_clock->clk_disable)
-		arch_clock->clk_disable(clk);
+	arch_clock->clk_disable(clk);
 
 out:
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -77,7 +81,7 @@
 unsigned long clk_get_rate(struct clk *clk)
 {
 	unsigned long flags;
-	unsigned long ret = 0;
+	unsigned long ret;
 
 	if (clk == NULL || IS_ERR(clk))
 		return 0;
@@ -97,14 +101,16 @@
 long clk_round_rate(struct clk *clk, unsigned long rate)
 {
 	unsigned long flags;
-	long ret = 0;
+	long ret;
 
 	if (clk == NULL || IS_ERR(clk))
-		return ret;
+		return 0;
+
+	if (!arch_clock || !arch_clock->clk_round_rate)
+		return 0;
 
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_round_rate)
-		ret = arch_clock->clk_round_rate(clk, rate);
+	ret = arch_clock->clk_round_rate(clk, rate);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -119,14 +125,13 @@
 	if (clk == NULL || IS_ERR(clk))
 		return ret;
 
+	if (!arch_clock || !arch_clock->clk_set_rate)
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_set_rate)
-		ret = arch_clock->clk_set_rate(clk, rate);
-	if (ret == 0) {
-		if (clk->recalc)
-			clk->rate = clk->recalc(clk);
+	ret = arch_clock->clk_set_rate(clk, rate);
+	if (ret == 0)
 		propagate_rate(clk);
-	}
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 
 	return ret;
@@ -141,15 +146,14 @@
 	if (clk == NULL || IS_ERR(clk) || parent == NULL || IS_ERR(parent))
 		return ret;
 
+	if (!arch_clock || !arch_clock->clk_set_parent)
+		return ret;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
 	if (clk->usecount == 0) {
-		if (arch_clock->clk_set_parent)
-			ret = arch_clock->clk_set_parent(clk, parent);
-		if (ret == 0) {
-			if (clk->recalc)
-				clk->rate = clk->recalc(clk);
+		ret = arch_clock->clk_set_parent(clk, parent);
+		if (ret == 0)
 			propagate_rate(clk);
-		}
 	} else
 		ret = -EBUSY;
 	spin_unlock_irqrestore(&clockfw_lock, flags);
@@ -335,6 +339,38 @@
 	return ret;
 }
 
+int omap_clk_enable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->allow_idle)
+			c->ops->allow_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
+int omap_clk_disable_autoidle_all(void)
+{
+	struct clk *c;
+	unsigned long flags;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+
+	list_for_each_entry(c, &clocks, node)
+		if (c->ops->deny_idle)
+			c->ops->deny_idle(c);
+
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+
 /*
  * Low level helpers
  */
@@ -367,9 +403,11 @@
 {
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_init_cpufreq_table)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_init_cpufreq_table)
-		arch_clock->clk_init_cpufreq_table(table);
+	arch_clock->clk_init_cpufreq_table(table);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 
@@ -377,9 +415,11 @@
 {
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_exit_cpufreq_table)
+		return;
+
 	spin_lock_irqsave(&clockfw_lock, flags);
-	if (arch_clock->clk_exit_cpufreq_table)
-		arch_clock->clk_exit_cpufreq_table(table);
+	arch_clock->clk_exit_cpufreq_table(table);
 	spin_unlock_irqrestore(&clockfw_lock, flags);
 }
 #endif
@@ -397,6 +437,9 @@
 	struct clk *ck;
 	unsigned long flags;
 
+	if (!arch_clock || !arch_clock->clk_disable_unused)
+		return 0;
+
 	pr_info("clock: disabling unused clocks to save power\n");
 	list_for_each_entry(ck, &clocks, node) {
 		if (ck->ops == &clkops_null)
@@ -406,14 +449,14 @@
 			continue;
 
 		spin_lock_irqsave(&clockfw_lock, flags);
-		if (arch_clock->clk_disable_unused)
-			arch_clock->clk_disable_unused(ck);
+		arch_clock->clk_disable_unused(ck);
 		spin_unlock_irqrestore(&clockfw_lock, flags);
 	}
 
 	return 0;
 }
 late_initcall(clk_disable_unused);
+late_initcall(omap_clk_enable_autoidle_all);
 #endif
 
 int __init clk_init(struct clk_functions * custom_clocks)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/common.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/common.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,10 +24,11 @@
 
 #define NO_LENGTH_CHECK 0xffffffff
 
-struct omap_board_config_kernel *omap_board_config;
+struct omap_board_config_kernel *omap_board_config __initdata;
 int omap_board_config_size;
 
-static const void *get_config(u16 tag, size_t len, int skip, size_t *len_out)
+static const void *__init get_config(u16 tag, size_t len,
+		int skip, size_t *len_out)
 {
 	struct omap_board_config_kernel *kinfo = NULL;
 	int i;
@@ -49,17 +50,15 @@
 	return kinfo->data;
 }
 
-const void *__omap_get_config(u16 tag, size_t len, int nr)
+const void *__init __omap_get_config(u16 tag, size_t len, int nr)
 {
         return get_config(tag, len, nr, NULL);
 }
-EXPORT_SYMBOL(__omap_get_config);
 
-const void *omap_get_var_config(u16 tag, size_t *len)
+const void *__init omap_get_var_config(u16 tag, size_t *len)
 {
         return get_config(tag, NO_LENGTH_CHECK, 0, len);
 }
-EXPORT_SYMBOL(omap_get_var_config);
 
 void __init omap_reserve(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/counter_32k.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/counter_32k.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/counter_32k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/counter_32k.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 #define omap16xx_32k_read	NULL
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 static cycle_t notrace omap2420_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP2420_32KSYNCT_BASE + 0x10) - offset_32k;
@@ -63,7 +63,7 @@
 #define omap2420_32k_read	NULL
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 static cycle_t notrace omap2430_32k_read(struct clocksource *cs)
 {
 	return omap_readl(OMAP2430_32KSYNCT_BASE + 0x10) - offset_32k;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/cpu-omap.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/cpu-omap.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/cpu-omap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/cpu-omap.c	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 	return ret;
 }
 
-static int __init omap_cpu_init(struct cpufreq_policy *policy)
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
 {
 	int result = 0;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/devices.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/devices.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/devices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/devices.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,8 +35,8 @@
 
 static struct platform_device **omap_mcbsp_devices;
 
-void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
-					int size)
+void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
 {
 	int i;
 
@@ -54,6 +54,8 @@
 		new_mcbsp = platform_device_alloc("omap-mcbsp", i + 1);
 		if (!new_mcbsp)
 			continue;
+		platform_device_add_resources(new_mcbsp, &res[i * res_count],
+					res_count);
 		new_mcbsp->dev.platform_data = &config[i];
 		ret = platform_device_add(new_mcbsp);
 		if (ret) {
@@ -65,8 +67,8 @@
 }
 
 #else
-void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
-					int size)
+void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size)
 {  }
 #endif
 
@@ -278,7 +280,7 @@
  * Claiming GPIOs, and setting their direction and initial values, is the
  * responsibility of the device drivers.  So is responding to probe().
  *
- * Board-specific knowlege like creating devices or pin setup is to be
+ * Board-specific knowledge like creating devices or pin setup is to be
  * kept out of drivers as much as possible.  In particular, pin setup
  * may be handled by the boot loader, and drivers should expect it will
  * normally have been done by the time they're probed.
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/dma.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,7 +134,7 @@
 
 #ifdef CONFIG_ARCH_OMAP15XX
 /* Returns 1 if the DMA module is in OMAP1510-compatible mode, 0 otherwise */
-int omap_dma_in_1510_mode(void)
+static int omap_dma_in_1510_mode(void)
 {
 	return enable_1510_mode;
 }
@@ -1019,7 +1019,7 @@
  * If the channel is running the caller must disable interrupts prior calling
  * this function and process the returned value before re-enabling interrupt to
  * prevent races with the interrupt handler. Note that in continuous mode there
- * is a chance for CSSA_L register overflow inbetween the two reads resulting
+ * is a chance for CSSA_L register overflow between the two reads resulting
  * in incorrect return value.
  */
 dma_addr_t omap_get_dma_src_pos(int lch)
@@ -1046,7 +1046,7 @@
  * If the channel is running the caller must disable interrupts prior calling
  * this function and process the returned value before re-enabling interrupt to
  * prevent races with the interrupt handler. Note that in continuous mode there
- * is a chance for CDSA_L register overflow inbetween the two reads resulting
+ * is a chance for CDSA_L register overflow between the two reads resulting
  * in incorrect return value.
  */
 dma_addr_t omap_get_dma_dst_pos(int lch)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/dmtimer.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/dmtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/dmtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/dmtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -342,6 +342,10 @@
 	l |= 0x02 << 3;  /* Set to smart-idle mode */
 	l |= 0x2 << 8;   /* Set clock activity to perserve f-clock on idle */
 
+	/* Enable autoidle on OMAP2 / OMAP3 */
+	if (cpu_is_omap24xx() || cpu_is_omap34xx())
+		l |= 0x1 << 0;
+
 	/*
 	 * Enable wake-up on OMAP2 CPUs.
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/gpio.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -755,18 +755,12 @@
 	bank = irq_data_get_irq_chip_data(d);
 	spin_lock_irqsave(&bank->lock, flags);
 	retval = _set_gpio_triggering(bank, get_gpio_index(gpio), type);
-	if (retval == 0) {
-		struct irq_desc *desc = irq_to_desc(d->irq);
-
-		desc->status &= ~IRQ_TYPE_SENSE_MASK;
-		desc->status |= type;
-	}
 	spin_unlock_irqrestore(&bank->lock, flags);
 
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
-		__set_irq_handler_unlocked(d->irq, handle_level_irq);
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
-		__set_irq_handler_unlocked(d->irq, handle_edge_irq);
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 
 	return retval;
 }
@@ -1146,7 +1140,7 @@
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 
-	bank = get_irq_data(irq);
+	bank = irq_get_handler_data(irq);
 #ifdef CONFIG_ARCH_OMAP1
 	if (bank->method == METHOD_MPUIO)
 		isr_reg = bank->base +
@@ -1270,8 +1264,7 @@
 	unsigned int gpio = d->irq - IH_GPIO_BASE;
 	struct gpio_bank *bank = irq_data_get_irq_chip_data(d);
 	unsigned int irq_mask = 1 << get_gpio_index(gpio);
-	struct irq_desc *desc = irq_to_desc(d->irq);
-	u32 trigger = desc->status & IRQ_TYPE_SENSE_MASK;
+	u32 trigger = irqd_get_trigger_type(d);
 
 	if (trigger)
 		_set_gpio_triggering(bank, get_gpio_index(gpio), trigger);
@@ -1672,19 +1665,17 @@
 
 	for (j = bank->virtual_irq_start;
 		     j < bank->virtual_irq_start + bank_width; j++) {
-		struct irq_desc *d = irq_to_desc(j);
-
-		lockdep_set_class(&d->lock, &gpio_lock_class);
-		set_irq_chip_data(j, bank);
+		irq_set_lockdep_class(j, &gpio_lock_class);
+		irq_set_chip_data(j, bank);
 		if (bank_is_mpuio(bank))
-			set_irq_chip(j, &mpuio_irq_chip);
+			irq_set_chip(j, &mpuio_irq_chip);
 		else
-			set_irq_chip(j, &gpio_irq_chip);
-		set_irq_handler(j, handle_simple_irq);
+			irq_set_chip(j, &gpio_irq_chip);
+		irq_set_handler(j, handle_simple_irq);
 		set_irq_flags(j, IRQF_VALID);
 	}
-	set_irq_chained_handler(bank->irq, gpio_irq_handler);
-	set_irq_data(bank->irq, bank);
+	irq_set_chained_handler(bank->irq, gpio_irq_handler);
+	irq_set_handler_data(bank->irq, bank);
 }
 
 static int __devinit omap_gpio_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/i2c.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/i2c.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,6 +112,7 @@
 }
 
 
+#ifdef CONFIG_ARCH_OMAP2PLUS
 /*
  * XXX This function is a temporary compatibility wrapper - only
  * needed until the I2C driver can be converted to call
@@ -130,7 +131,6 @@
 	},
 };
 
-#ifdef CONFIG_ARCH_OMAP2PLUS
 static inline int omap2_i2c_add_bus(int bus_id)
 {
 	int l;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/board.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/board.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/board.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/board.h	2011-05-19 00:06:34.000000000 -0400
@@ -151,14 +151,14 @@
 	const void *data;
 };
 
-extern const void *__omap_get_config(u16 tag, size_t len, int nr);
+extern const void *__init __omap_get_config(u16 tag, size_t len, int nr);
 
 #define omap_get_config(tag, type) \
 	((const type *) __omap_get_config((tag), sizeof(type), 0))
 #define omap_get_nr_config(tag, type, nr) \
 	((const type *) __omap_get_config((tag), sizeof(type), (nr)))
 
-extern const void *omap_get_var_config(u16 tag, size_t *len);
+extern const void *__init omap_get_var_config(u16 tag, size_t *len);
 
 extern struct omap_board_config_kernel *omap_board_config;
 extern int omap_board_config_size;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/clkdev_omap.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/clkdev_omap.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/clkdev_omap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/clkdev_omap.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,7 @@
 #define CK_3517		(1 << 9)
 #define CK_36XX		(1 << 10)	/* 36xx/37xx-specific clocks */
 #define CK_443X		(1 << 11)
+#define CK_TI816X	(1 << 12)
 
 
 #define CK_34XX		(CK_3430ES1 | CK_3430ES2PLUS)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/clock.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/clock.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,8 @@
  * @disable: fn ptr that enables the current clock in hardware
  * @find_idlest: function returning the IDLEST register for the clock's IP blk
  * @find_companion: function returning the "companion" clk reg for the clock
+ * @allow_idle: fn ptr that enables autoidle for the current clock in hardware
+ * @deny_idle: fn ptr that disables autoidle for the current clock in hardware
  *
  * A "companion" clk is an accompanying clock to the one being queried
  * that must be enabled for the IP module connected to the clock to
@@ -42,6 +44,8 @@
 					       u8 *, u8 *);
 	void			(*find_companion)(struct clk *, void __iomem **,
 						  u8 *);
+	void			(*allow_idle)(struct clk *);
+	void			(*deny_idle)(struct clk *);
 };
 
 #ifdef CONFIG_ARCH_OMAP2PLUS
@@ -53,6 +57,7 @@
 #define RATE_IN_3430ES2PLUS	(1 << 3)	/* 3430 ES >= 2 rates only */
 #define RATE_IN_36XX		(1 << 4)
 #define RATE_IN_4430		(1 << 5)
+#define RATE_IN_TI816X		(1 << 6)
 
 #define RATE_IN_24XX		(RATE_IN_242X | RATE_IN_243X)
 #define RATE_IN_34XX		(RATE_IN_3430ES1 | RATE_IN_3430ES2PLUS)
@@ -104,7 +109,6 @@
  * @clk_ref: struct clk pointer to the clock's reference clock input
  * @control_reg: register containing the DPLL mode bitfield
  * @enable_mask: mask of the DPLL mode bitfield in @control_reg
- * @rate_tolerance: maximum variance allowed from target rate (in Hz)
  * @last_rounded_rate: cache of the last rate result of omap2_dpll_round_rate()
  * @last_rounded_m: cache of the last M result of omap2_dpll_round_rate()
  * @max_multiplier: maximum valid non-bypass multiplier value (actual)
@@ -130,12 +134,9 @@
  * XXX Some DPLLs have multiple bypass inputs, so it's not technically
  * correct to only have one @clk_bypass pointer.
  *
- * XXX @rate_tolerance should probably be deprecated - currently there
- * don't seem to be any usecases for DPLL rounding that is not exact.
- *
  * XXX The runtime-variable fields (@last_rounded_rate, @last_rounded_m,
  * @last_rounded_n) should be separated from the runtime-fixed fields
- * and placed into a differenct structure, so that the runtime-fixed data
+ * and placed into a different structure, so that the runtime-fixed data
  * can be placed into read-only space.
  */
 struct dpll_data {
@@ -146,7 +147,6 @@
 	struct clk		*clk_ref;
 	void __iomem		*control_reg;
 	u32			enable_mask;
-	unsigned int		rate_tolerance;
 	unsigned long		last_rounded_rate;
 	u16			last_rounded_m;
 	u16			max_multiplier;
@@ -171,12 +171,24 @@
 
 #endif
 
-/* struct clk.flags possibilities */
+/*
+ * struct clk.flags possibilities
+ *
+ * XXX document the rest of the clock flags here
+ *
+ * CLOCK_CLKOUTX2: (OMAP4 only) DPLL CLKOUT and CLKOUTX2 GATE_CTRL
+ *     bits share the same register.  This flag allows the
+ *     omap4_dpllmx*() code to determine which GATE_CTRL bit field
+ *     should be used.  This is a temporary solution - a better approach
+ *     would be to associate clock type-specific data with the clock,
+ *     similar to the struct dpll_data approach.
+ */
 #define ENABLE_REG_32BIT	(1 << 0)	/* Use 32-bit access */
 #define CLOCK_IDLE_CONTROL	(1 << 1)
 #define CLOCK_NO_IDLE_PARENT	(1 << 2)
 #define ENABLE_ON_INIT		(1 << 3)	/* Enable upon framework init */
 #define INVERT_ENABLE		(1 << 4)	/* 0 enables, 1 disables */
+#define CLOCK_CLKOUTX2		(1 << 5)
 
 /**
  * struct clk - OMAP struct clk
@@ -292,6 +304,8 @@
 extern void clk_exit_cpufreq_table(struct cpufreq_frequency_table **table);
 #endif
 extern struct clk *omap_clk_get_by_name(const char *name);
+extern int omap_clk_enable_autoidle_all(void);
+extern int omap_clk_disable_autoidle_all(void);
 
 extern const struct clkops clkops_null;
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/common.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/common.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -56,16 +56,13 @@
 	unsigned long   prm;            /* Power and Reset Management */
 	unsigned long   cm;             /* Clock Management */
 	unsigned long   cm2;
-	unsigned long	uart1_phys;
-	unsigned long	uart2_phys;
-	unsigned long	uart3_phys;
-	unsigned long	uart4_phys;
 };
 
 void omap2_set_globals_242x(void);
 void omap2_set_globals_243x(void);
 void omap2_set_globals_3xxx(void);
 void omap2_set_globals_443x(void);
+void omap2_set_globals_ti816x(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.38-gnu/arch/arm/plat-omap/include/plat/cpu.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/cpu.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/cpu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/cpu.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Copyright (C) 2004, 2008 Nokia Corporation
  *
- * Copyright (C) 2009 Texas Instruments.
+ * Copyright (C) 2009-11 Texas Instruments.
  *
  * Written by Tony Lindgren <tony.lindgren@nokia.com>
  *
@@ -105,6 +105,12 @@
 	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
 }
 
+#define IS_TI_SUBCLASS(subclass, id)			\
+static inline int is_ti ##subclass (void)		\
+{							\
+	return (GET_OMAP_SUBCLASS == (id)) ? 1 : 0;	\
+}
+
 IS_OMAP_CLASS(7xx, 0x07)
 IS_OMAP_CLASS(15xx, 0x15)
 IS_OMAP_CLASS(16xx, 0x16)
@@ -118,6 +124,8 @@
 IS_OMAP_SUBCLASS(363x, 0x363)
 IS_OMAP_SUBCLASS(443x, 0x443)
 
+IS_TI_SUBCLASS(816x, 0x816)
+
 #define cpu_is_omap7xx()		0
 #define cpu_is_omap15xx()		0
 #define cpu_is_omap16xx()		0
@@ -126,6 +134,7 @@
 #define cpu_is_omap243x()		0
 #define cpu_is_omap34xx()		0
 #define cpu_is_omap343x()		0
+#define cpu_is_ti816x()			0
 #define cpu_is_omap44xx()		0
 #define cpu_is_omap443x()		0
 
@@ -170,11 +179,11 @@
 #  undef  cpu_is_omap24xx
 #  define cpu_is_omap24xx()		is_omap24xx()
 # endif
-# if defined (CONFIG_ARCH_OMAP2420)
+# if defined (CONFIG_SOC_OMAP2420)
 #  undef  cpu_is_omap242x
 #  define cpu_is_omap242x()		is_omap242x()
 # endif
-# if defined (CONFIG_ARCH_OMAP2430)
+# if defined (CONFIG_SOC_OMAP2430)
 #  undef  cpu_is_omap243x
 #  define cpu_is_omap243x()		is_omap243x()
 # endif
@@ -189,11 +198,11 @@
 #  undef  cpu_is_omap24xx
 #  define cpu_is_omap24xx()		1
 # endif
-# if defined(CONFIG_ARCH_OMAP2420)
+# if defined(CONFIG_SOC_OMAP2420)
 #  undef  cpu_is_omap242x
 #  define cpu_is_omap242x()		1
 # endif
-# if defined(CONFIG_ARCH_OMAP2430)
+# if defined(CONFIG_SOC_OMAP2430)
 #  undef  cpu_is_omap243x
 #  define cpu_is_omap243x()		1
 # endif
@@ -201,7 +210,7 @@
 #  undef  cpu_is_omap34xx
 #  define cpu_is_omap34xx()		1
 # endif
-# if defined(CONFIG_ARCH_OMAP3430)
+# if defined(CONFIG_SOC_OMAP3430)
 #  undef  cpu_is_omap343x
 #  define cpu_is_omap343x()		1
 # endif
@@ -330,6 +339,7 @@
 # undef cpu_is_omap3530
 # undef cpu_is_omap3505
 # undef cpu_is_omap3517
+# undef cpu_is_ti816x
 # define cpu_is_omap3430()		is_omap3430()
 # define cpu_is_omap3503()		(cpu_is_omap3430() &&		\
 						(!omap3_has_iva()) &&	\
@@ -345,6 +355,7 @@
 # define cpu_is_omap3517()		is_omap3517()
 # undef cpu_is_omap3630
 # define cpu_is_omap3630()		is_omap363x()
+# define cpu_is_ti816x()		is_ti816x()
 #endif
 
 # if defined(CONFIG_ARCH_OMAP4)
@@ -389,9 +400,15 @@
 #define OMAP3505_REV(v)		(OMAP35XX_CLASS | (0x3505 << 16) | (v << 8))
 #define OMAP3517_REV(v)		(OMAP35XX_CLASS | (0x3517 << 16) | (v << 8))
 
+#define TI816X_CLASS		0x81600034
+#define TI8168_REV_ES1_0	TI816X_CLASS
+#define TI8168_REV_ES1_1	(TI816X_CLASS | (OMAP_REVBITS_01 << 8))
+
 #define OMAP443X_CLASS		0x44300044
-#define OMAP4430_REV_ES1_0	OMAP443X_CLASS
-#define OMAP4430_REV_ES2_0	0x44301044
+#define OMAP4430_REV_ES1_0	(OMAP443X_CLASS | (0x10 << 8))
+#define OMAP4430_REV_ES2_0	(OMAP443X_CLASS | (0x20 << 8))
+#define OMAP4430_REV_ES2_1	(OMAP443X_CLASS | (0x21 << 8))
+#define OMAP4430_REV_ES2_2	(OMAP443X_CLASS | (0x22 << 8))
 
 /*
  * omap_chip bits
@@ -419,11 +436,16 @@
 #define CHIP_IS_OMAP3630ES1_1           (1 << 9)
 #define CHIP_IS_OMAP3630ES1_2           (1 << 10)
 #define CHIP_IS_OMAP4430ES2		(1 << 11)
+#define CHIP_IS_OMAP4430ES2_1		(1 << 12)
+#define CHIP_IS_OMAP4430ES2_2		(1 << 13)
+#define CHIP_IS_TI816X			(1 << 14)
 
 #define CHIP_IS_OMAP24XX		(CHIP_IS_OMAP2420 | CHIP_IS_OMAP2430)
 
-#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 | \
-						 CHIP_IS_OMAP4430ES2)
+#define CHIP_IS_OMAP4430		(CHIP_IS_OMAP4430ES1 |		\
+					 CHIP_IS_OMAP4430ES2 |		\
+					 CHIP_IS_OMAP4430ES2_1 |	\
+					 CHIP_IS_OMAP4430ES2_2)
 
 /*
  * "GE" here represents "greater than or equal to" in terms of ES
@@ -455,6 +477,7 @@
 #define OMAP3_HAS_ISP			BIT(4)
 #define OMAP3_HAS_192MHZ_CLK		BIT(5)
 #define OMAP3_HAS_IO_WAKEUP		BIT(6)
+#define OMAP3_HAS_SDRC			BIT(7)
 
 #define OMAP3_HAS_FEATURE(feat,flag)			\
 static inline unsigned int omap3_has_ ##feat(void)	\
@@ -469,5 +492,6 @@
 OMAP3_HAS_FEATURE(isp, ISP)
 OMAP3_HAS_FEATURE(192mhz_clk, 192MHZ_CLK)
 OMAP3_HAS_FEATURE(io_wakeup, IO_WAKEUP)
+OMAP3_HAS_FEATURE(sdrc, SDRC)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/display.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/display.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/display.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/display.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/list.h>
 #include <linux/kobject.h>
 #include <linux/device.h>
+#include <linux/platform_device.h>
 #include <asm/atomic.h>
 
 #define DISPC_IRQ_FRAMEDONE		(1 << 0)
@@ -57,6 +58,7 @@
 	OMAP_DISPLAY_TYPE_SDI		= 1 << 2,
 	OMAP_DISPLAY_TYPE_DSI		= 1 << 3,
 	OMAP_DISPLAY_TYPE_VENC		= 1 << 4,
+	OMAP_DISPLAY_TYPE_HDMI		= 1 << 5,
 };
 
 enum omap_plane {
@@ -226,6 +228,23 @@
 	struct omap_dss_device *default_device;
 };
 
+#if defined(CONFIG_OMAP2_DSS_MODULE) || defined(CONFIG_OMAP2_DSS)
+/* Init with the board info */
+extern int omap_display_init(struct omap_dss_board_info *board_data);
+#else
+static inline int omap_display_init(struct omap_dss_board_info *board_data)
+{
+	return 0;
+}
+#endif
+
+struct omap_display_platform_data {
+	struct omap_dss_board_info *board_data;
+	/* TODO: Additional members to be added when PM is considered */
+
+	bool (*opt_clock_available)(const char *clk_role);
+};
+
 struct omap_video_timings {
 	/* Unit: pixels */
 	u16 x_res;
@@ -385,8 +404,8 @@
 			struct {
 				u16 regn;
 				u16 regm;
-				u16 regm3;
-				u16 regm4;
+				u16 regm_dispc;
+				u16 regm_dsi;
 
 				u16 lp_clk_div;
 
@@ -544,6 +563,9 @@
 		int channel,
 		u16 x, u16 y, u16 w, u16 h,
 		void (*callback)(int, void *), void *data);
+int omap_dsi_request_vc(struct omap_dss_device *dssdev, int *channel);
+int omap_dsi_set_vc_id(struct omap_dss_device *dssdev, int channel, int vc_id);
+void omap_dsi_release_vc(struct omap_dss_device *dssdev, int channel);
 
 int omapdss_dsi_display_enable(struct omap_dss_device *dssdev);
 void omapdss_dsi_display_disable(struct omap_dss_device *dssdev);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/dmtimer.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/dmtimer.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/dmtimer.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/dmtimer.h	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,12 @@
  *
  * OMAP Dual-Mode Timers
  *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ * Tarun Kanti DebBarma <tarun.kanti@ti.com>
+ * Thara Gopinath <thara@ti.com>
+ *
+ * Platform device conversion and hwmod support.
+ *
  * Copyright (C) 2005 Nokia Corporation
  * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
  * PWM and clock framwork support by Timo Teras.
@@ -44,6 +50,11 @@
 #define OMAP_TIMER_TRIGGER_OVERFLOW		0x01
 #define OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE	0x02
 
+/*
+ * IP revision identifier so that Highlander IP
+ * in OMAP4 can be distinguished.
+ */
+#define OMAP_TIMER_IP_VERSION_1                        0x1
 struct omap_dm_timer;
 extern struct omap_dm_timer *gptimer_wakeup;
 extern struct sys_timer omap_timer;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/fpga.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/fpga.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/fpga.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/fpga.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,18 +30,18 @@
  * ---------------------------------------------------------------------------
  */
 /* maps in the FPGA registers and the ETHR registers */
-#define H2P2_DBG_FPGA_BASE		IOMEM(0xE8000000)	/* VA */
+#define H2P2_DBG_FPGA_BASE		0xE8000000		/* VA */
 #define H2P2_DBG_FPGA_SIZE		SZ_4K			/* SIZE */
 #define H2P2_DBG_FPGA_START		0x04000000		/* PA */
 
 #define H2P2_DBG_FPGA_ETHR_START	(H2P2_DBG_FPGA_START + 0x300)
-#define H2P2_DBG_FPGA_FPGA_REV		(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
-#define H2P2_DBG_FPGA_BOARD_REV		(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
-#define H2P2_DBG_FPGA_GPIO		(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
-#define H2P2_DBG_FPGA_LEDS		(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
-#define H2P2_DBG_FPGA_MISC_INPUTS	(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
-#define H2P2_DBG_FPGA_LAN_STATUS	(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
-#define H2P2_DBG_FPGA_LAN_RESET		(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
+#define H2P2_DBG_FPGA_FPGA_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x10)	/* FPGA Revision */
+#define H2P2_DBG_FPGA_BOARD_REV		IOMEM(H2P2_DBG_FPGA_BASE + 0x12)	/* Board Revision */
+#define H2P2_DBG_FPGA_GPIO		IOMEM(H2P2_DBG_FPGA_BASE + 0x14)	/* GPIO outputs */
+#define H2P2_DBG_FPGA_LEDS		IOMEM(H2P2_DBG_FPGA_BASE + 0x16)	/* LEDs outputs */
+#define H2P2_DBG_FPGA_MISC_INPUTS	IOMEM(H2P2_DBG_FPGA_BASE + 0x18)	/* Misc inputs */
+#define H2P2_DBG_FPGA_LAN_STATUS	IOMEM(H2P2_DBG_FPGA_BASE + 0x1A)	/* LAN Status line */
+#define H2P2_DBG_FPGA_LAN_RESET		IOMEM(H2P2_DBG_FPGA_BASE + 0x1C)	/* LAN Reset line */
 
 /* NOTE:  most boards don't have a static mapping for the FPGA ... */
 struct h2p2_dbg_fpga {
@@ -81,55 +81,55 @@
  *  OMAP-1510 FPGA
  * ---------------------------------------------------------------------------
  */
-#define OMAP1510_FPGA_BASE		IOMEM(0xE8000000)	/* VA */
+#define OMAP1510_FPGA_BASE		0xE8000000		/* VA */
 #define OMAP1510_FPGA_SIZE		SZ_4K
 #define OMAP1510_FPGA_START		0x08000000		/* PA */
 
 /* Revision */
-#define OMAP1510_FPGA_REV_LOW			(OMAP1510_FPGA_BASE + 0x0)
-#define OMAP1510_FPGA_REV_HIGH			(OMAP1510_FPGA_BASE + 0x1)
+#define OMAP1510_FPGA_REV_LOW			IOMEM(OMAP1510_FPGA_BASE + 0x0)
+#define OMAP1510_FPGA_REV_HIGH			IOMEM(OMAP1510_FPGA_BASE + 0x1)
 
-#define OMAP1510_FPGA_LCD_PANEL_CONTROL		(OMAP1510_FPGA_BASE + 0x2)
-#define OMAP1510_FPGA_LED_DIGIT			(OMAP1510_FPGA_BASE + 0x3)
-#define INNOVATOR_FPGA_HID_SPI			(OMAP1510_FPGA_BASE + 0x4)
-#define OMAP1510_FPGA_POWER			(OMAP1510_FPGA_BASE + 0x5)
+#define OMAP1510_FPGA_LCD_PANEL_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x2)
+#define OMAP1510_FPGA_LED_DIGIT			IOMEM(OMAP1510_FPGA_BASE + 0x3)
+#define INNOVATOR_FPGA_HID_SPI			IOMEM(OMAP1510_FPGA_BASE + 0x4)
+#define OMAP1510_FPGA_POWER			IOMEM(OMAP1510_FPGA_BASE + 0x5)
 
 /* Interrupt status */
-#define OMAP1510_FPGA_ISR_LO			(OMAP1510_FPGA_BASE + 0x6)
-#define OMAP1510_FPGA_ISR_HI			(OMAP1510_FPGA_BASE + 0x7)
+#define OMAP1510_FPGA_ISR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x6)
+#define OMAP1510_FPGA_ISR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x7)
 
 /* Interrupt mask */
-#define OMAP1510_FPGA_IMR_LO			(OMAP1510_FPGA_BASE + 0x8)
-#define OMAP1510_FPGA_IMR_HI			(OMAP1510_FPGA_BASE + 0x9)
+#define OMAP1510_FPGA_IMR_LO			IOMEM(OMAP1510_FPGA_BASE + 0x8)
+#define OMAP1510_FPGA_IMR_HI			IOMEM(OMAP1510_FPGA_BASE + 0x9)
 
 /* Reset registers */
-#define OMAP1510_FPGA_HOST_RESET		(OMAP1510_FPGA_BASE + 0xa)
-#define OMAP1510_FPGA_RST			(OMAP1510_FPGA_BASE + 0xb)
+#define OMAP1510_FPGA_HOST_RESET		IOMEM(OMAP1510_FPGA_BASE + 0xa)
+#define OMAP1510_FPGA_RST			IOMEM(OMAP1510_FPGA_BASE + 0xb)
 
-#define OMAP1510_FPGA_AUDIO			(OMAP1510_FPGA_BASE + 0xc)
-#define OMAP1510_FPGA_DIP			(OMAP1510_FPGA_BASE + 0xe)
-#define OMAP1510_FPGA_FPGA_IO			(OMAP1510_FPGA_BASE + 0xf)
-#define OMAP1510_FPGA_UART1			(OMAP1510_FPGA_BASE + 0x14)
-#define OMAP1510_FPGA_UART2			(OMAP1510_FPGA_BASE + 0x15)
-#define OMAP1510_FPGA_OMAP1510_STATUS		(OMAP1510_FPGA_BASE + 0x16)
-#define OMAP1510_FPGA_BOARD_REV			(OMAP1510_FPGA_BASE + 0x18)
-#define OMAP1510P1_PPT_DATA			(OMAP1510_FPGA_BASE + 0x100)
-#define OMAP1510P1_PPT_STATUS			(OMAP1510_FPGA_BASE + 0x101)
-#define OMAP1510P1_PPT_CONTROL			(OMAP1510_FPGA_BASE + 0x102)
+#define OMAP1510_FPGA_AUDIO			IOMEM(OMAP1510_FPGA_BASE + 0xc)
+#define OMAP1510_FPGA_DIP			IOMEM(OMAP1510_FPGA_BASE + 0xe)
+#define OMAP1510_FPGA_FPGA_IO			IOMEM(OMAP1510_FPGA_BASE + 0xf)
+#define OMAP1510_FPGA_UART1			IOMEM(OMAP1510_FPGA_BASE + 0x14)
+#define OMAP1510_FPGA_UART2			IOMEM(OMAP1510_FPGA_BASE + 0x15)
+#define OMAP1510_FPGA_OMAP1510_STATUS		IOMEM(OMAP1510_FPGA_BASE + 0x16)
+#define OMAP1510_FPGA_BOARD_REV			IOMEM(OMAP1510_FPGA_BASE + 0x18)
+#define OMAP1510P1_PPT_DATA			IOMEM(OMAP1510_FPGA_BASE + 0x100)
+#define OMAP1510P1_PPT_STATUS			IOMEM(OMAP1510_FPGA_BASE + 0x101)
+#define OMAP1510P1_PPT_CONTROL			IOMEM(OMAP1510_FPGA_BASE + 0x102)
 
-#define OMAP1510_FPGA_TOUCHSCREEN		(OMAP1510_FPGA_BASE + 0x204)
+#define OMAP1510_FPGA_TOUCHSCREEN		IOMEM(OMAP1510_FPGA_BASE + 0x204)
 
-#define INNOVATOR_FPGA_INFO			(OMAP1510_FPGA_BASE + 0x205)
-#define INNOVATOR_FPGA_LCD_BRIGHT_LO		(OMAP1510_FPGA_BASE + 0x206)
-#define INNOVATOR_FPGA_LCD_BRIGHT_HI		(OMAP1510_FPGA_BASE + 0x207)
-#define INNOVATOR_FPGA_LED_GRN_LO		(OMAP1510_FPGA_BASE + 0x208)
-#define INNOVATOR_FPGA_LED_GRN_HI		(OMAP1510_FPGA_BASE + 0x209)
-#define INNOVATOR_FPGA_LED_RED_LO		(OMAP1510_FPGA_BASE + 0x20a)
-#define INNOVATOR_FPGA_LED_RED_HI		(OMAP1510_FPGA_BASE + 0x20b)
-#define INNOVATOR_FPGA_CAM_USB_CONTROL		(OMAP1510_FPGA_BASE + 0x20c)
-#define INNOVATOR_FPGA_EXP_CONTROL		(OMAP1510_FPGA_BASE + 0x20d)
-#define INNOVATOR_FPGA_ISR2			(OMAP1510_FPGA_BASE + 0x20e)
-#define INNOVATOR_FPGA_IMR2			(OMAP1510_FPGA_BASE + 0x210)
+#define INNOVATOR_FPGA_INFO			IOMEM(OMAP1510_FPGA_BASE + 0x205)
+#define INNOVATOR_FPGA_LCD_BRIGHT_LO		IOMEM(OMAP1510_FPGA_BASE + 0x206)
+#define INNOVATOR_FPGA_LCD_BRIGHT_HI		IOMEM(OMAP1510_FPGA_BASE + 0x207)
+#define INNOVATOR_FPGA_LED_GRN_LO		IOMEM(OMAP1510_FPGA_BASE + 0x208)
+#define INNOVATOR_FPGA_LED_GRN_HI		IOMEM(OMAP1510_FPGA_BASE + 0x209)
+#define INNOVATOR_FPGA_LED_RED_LO		IOMEM(OMAP1510_FPGA_BASE + 0x20a)
+#define INNOVATOR_FPGA_LED_RED_HI		IOMEM(OMAP1510_FPGA_BASE + 0x20b)
+#define INNOVATOR_FPGA_CAM_USB_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20c)
+#define INNOVATOR_FPGA_EXP_CONTROL		IOMEM(OMAP1510_FPGA_BASE + 0x20d)
+#define INNOVATOR_FPGA_ISR2			IOMEM(OMAP1510_FPGA_BASE + 0x20e)
+#define INNOVATOR_FPGA_IMR2			IOMEM(OMAP1510_FPGA_BASE + 0x210)
 
 #define OMAP1510_FPGA_ETHR_START		(OMAP1510_FPGA_START + 0x300)
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/gpio.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 /* Wrappers for "new style" GPIO calls, using the new infrastructure
  * which lets us plug in FPGA, I2C, and other implementations.
  * *
- * The original OMAP-specfic calls should eventually be removed.
+ * The original OMAP-specific calls should eventually be removed.
  */
 
 #include <linux/errno.h>
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/gpmc.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/gpmc.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/gpmc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/gpmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -41,6 +41,8 @@
 #define GPMC_NAND_ADDRESS	0x0000000b
 #define GPMC_NAND_DATA		0x0000000c
 
+#define GPMC_ENABLE_IRQ		0x0000000d
+
 /* ECC commands */
 #define GPMC_ECC_READ		0 /* Reset Hardware ECC for read */
 #define GPMC_ECC_WRITE		1 /* Reset Hardware ECC for write */
@@ -78,6 +80,19 @@
 #define WR_RD_PIN_MONITORING		0x00600000
 #define GPMC_PREFETCH_STATUS_FIFO_CNT(val)	((val >> 24) & 0x7F)
 #define GPMC_PREFETCH_STATUS_COUNT(val)	(val & 0x00003fff)
+#define GPMC_IRQ_FIFOEVENTENABLE	0x01
+#define GPMC_IRQ_COUNT_EVENT		0x02
+
+#define PREFETCH_FIFOTHRESHOLD_MAX	0x40
+#define PREFETCH_FIFOTHRESHOLD(val)	((val) << 8)
+
+enum omap_ecc {
+		/* 1-bit ecc: stored at end of spare area */
+	OMAP_ECC_HAMMING_CODE_DEFAULT = 0, /* Default, s/w method */
+	OMAP_ECC_HAMMING_CODE_HW, /* gpmc to detect the error */
+		/* 1-bit ecc: stored at beginning of spare area as romcode */
+	OMAP_ECC_HAMMING_CODE_HW_ROMCODE, /* gpmc method & romcode layout */
+};
 
 /*
  * Note that all values in this struct are in nanoseconds except sync_clk
@@ -130,12 +145,11 @@
 extern void gpmc_cs_free(int cs);
 extern int gpmc_cs_set_reserved(int cs, int reserved);
 extern int gpmc_cs_reserved(int cs);
-extern int gpmc_prefetch_enable(int cs, int dma_mode,
+extern int gpmc_prefetch_enable(int cs, int fifo_th, int dma_mode,
 					unsigned int u32_count, int is_write);
 extern int gpmc_prefetch_reset(int cs);
 extern void omap3_gpmc_save_context(void);
 extern void omap3_gpmc_restore_context(void);
-extern void gpmc_init(void);
 extern int gpmc_read_status(int cmd);
 extern int gpmc_cs_configure(int cs, int cmd, int wval);
 extern int gpmc_nand_read(int cs, int cmd);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/hardware.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -286,5 +286,6 @@
 #include <plat/omap24xx.h>
 #include <plat/omap34xx.h>
 #include <plat/omap44xx.h>
+#include <plat/ti816x.h>
 
 #endif	/* __ASM_ARCH_OMAP_HARDWARE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/io.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/io.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -259,7 +259,7 @@
 extern void omap1_map_common_io(void);
 extern void omap1_init_common_hw(void);
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 extern void omap242x_map_common_io(void);
 #else
 static inline void omap242x_map_common_io(void)
@@ -267,7 +267,7 @@
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 extern void omap243x_map_common_io(void);
 #else
 static inline void omap243x_map_common_io(void)
@@ -282,6 +282,14 @@
 {
 }
 #endif
+
+#ifdef CONFIG_SOC_OMAPTI816X
+extern void omapti816x_map_common_io(void);
+#else
+static inline void omapti816x_map_common_io(void)
+{
+}
+#endif
 
 #ifdef CONFIG_ARCH_OMAP4
 extern void omap44xx_map_common_io(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/iommu.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/iommu.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/iommu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/iommu.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 	struct clk	*clk;
 	void __iomem	*regbase;
 	struct device	*dev;
+	void		*isr_priv;
 
 	unsigned int	refcount;
 	struct mutex	iommu_lock;	/* global for this whole object */
@@ -47,7 +48,7 @@
 	struct list_head	mmap;
 	struct mutex		mmap_lock; /* protect mmap */
 
-	int (*isr)(struct iommu *obj);
+	int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs, void *priv);
 
 	void *ctx; /* iommu context: registres saved area */
 	u32 da_start;
@@ -109,6 +110,13 @@
 	u32 da_end;
 };
 
+/* IOMMU errors */
+#define OMAP_IOMMU_ERR_TLB_MISS		(1 << 0)
+#define OMAP_IOMMU_ERR_TRANS_FAULT	(1 << 1)
+#define OMAP_IOMMU_ERR_EMU_MISS		(1 << 2)
+#define OMAP_IOMMU_ERR_TBLWALK_FAULT	(1 << 3)
+#define OMAP_IOMMU_ERR_MULTIHIT_FAULT	(1 << 4)
+
 #if defined(CONFIG_ARCH_OMAP1)
 #error "iommu for this processor not implemented yet"
 #else
@@ -154,11 +162,17 @@
 extern void flush_iotlb_all(struct iommu *obj);
 
 extern int iopgtable_store_entry(struct iommu *obj, struct iotlb_entry *e);
+extern void iopgtable_lookup_entry(struct iommu *obj, u32 da, u32 **ppgd,
+				   u32 **ppte);
 extern size_t iopgtable_clear_entry(struct iommu *obj, u32 iova);
 
 extern int iommu_set_da_range(struct iommu *obj, u32 start, u32 end);
 extern struct iommu *iommu_get(const char *name);
 extern void iommu_put(struct iommu *obj);
+extern int iommu_set_isr(const char *name,
+			 int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
+				    void *priv),
+			 void *isr_priv);
 
 extern void iommu_save_ctx(struct iommu *obj);
 extern void iommu_restore_ctx(struct iommu *obj);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/iovmm.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/iovmm.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/iovmm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/iovmm.h	2011-05-19 00:06:34.000000000 -0400
@@ -71,8 +71,6 @@
 #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);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/irqs.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/irqs.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/irqs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/irqs.h	2011-05-19 00:06:34.000000000 -0400
@@ -315,9 +315,12 @@
 #define INT_34XX_SSM_ABORT_IRQ	6
 #define INT_34XX_SYS_NIRQ	7
 #define INT_34XX_D2D_FW_IRQ	8
+#define INT_34XX_L3_DBG_IRQ     9
+#define INT_34XX_L3_APP_IRQ     10
 #define INT_34XX_PRCM_MPU_IRQ	11
 #define INT_34XX_MCBSP1_IRQ	16
 #define INT_34XX_MCBSP2_IRQ	17
+#define INT_34XX_GPMC_IRQ	20
 #define INT_34XX_MCBSP3_IRQ	22
 #define INT_34XX_MCBSP4_IRQ	23
 #define INT_34XX_CAM_IRQ	24
@@ -411,7 +414,13 @@
 #define TWL_IRQ_END		TWL6030_IRQ_END
 #endif
 
-#define NR_IRQS			TWL_IRQ_END
+/* GPMC related */
+#define OMAP_GPMC_IRQ_BASE	(TWL_IRQ_END)
+#define OMAP_GPMC_NR_IRQS	8
+#define OMAP_GPMC_IRQ_END	(OMAP_GPMC_IRQ_BASE + OMAP_GPMC_NR_IRQS)
+
+
+#define NR_IRQS			OMAP_GPMC_IRQ_END
 
 #define OMAP_IRQ_BIT(irq)	(1 << ((irq) % 32))
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l3_2xxx.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l3_2xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l3_2xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l3_2xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-omap/include/plat/l3_2xxx.h - L3 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_2XXX_H
+
+/* L3 CONNIDs */
+/* Display Sub system (DSS) */
+#define OMAP2_L3_CORE_FW_CONNID_DSS			8
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l3_3xxx.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l3_3xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l3_3xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l3_3xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * arch/arm/plat-omap/include/plat/l3_3xxx.h - L3 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L3_3XXX_H
+
+/* L3 Initiator IDs */
+/* Display Sub system (DSS) */
+#define OMAP3_L3_CORE_FW_INIT_ID_DSS			29
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l4_2xxx.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l4_2xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l4_2xxx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l4_2xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * arch/arm/plat-omap/include/plat/l4_2xxx.h - L4 firewall definitions
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
+ *	Sumit Semwal
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
+#define __ARCH_ARM_PLAT_OMAP_INCLUDE_PLAT_L4_2XXX_H
+
+/* L4 CORE */
+/* Display Sub system (DSS) */
+#define OMAP2420_L4_CORE_FW_DSS_CORE_REGION			28
+#define OMAP2420_L4_CORE_FW_DSS_DISPC_REGION			29
+#define OMAP2420_L4_CORE_FW_DSS_RFBI_REGION			30
+#define OMAP2420_L4_CORE_FW_DSS_VENC_REGION			31
+#define OMAP2420_L4_CORE_FW_DSS_TA_REGION			32
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l4_3xxx.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l4_3xxx.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/l4_3xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/l4_3xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,4 +21,14 @@
 #define OMAP3_L4_CORE_FW_I2C3_REGION				73
 #define OMAP3_L4_CORE_FW_I2C3_TA_REGION				74
 
+/* Display Sub system (DSS) */
+#define OMAP3_L4_CORE_FW_DSS_PROT_GROUP				2
+
+#define OMAP3_L4_CORE_FW_DSS_DSI_REGION				104
+#define OMAP3ES1_L4_CORE_FW_DSS_CORE_REGION			3
+#define OMAP3_L4_CORE_FW_DSS_CORE_REGION			4
+#define OMAP3_L4_CORE_FW_DSS_DISPC_REGION			4
+#define OMAP3_L4_CORE_FW_DSS_RFBI_REGION			5
+#define OMAP3_L4_CORE_FW_DSS_VENC_REGION			6
+#define OMAP3_L4_CORE_FW_DSS_TA_REGION				7
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/mcbsp.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/mcbsp.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/mcbsp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/mcbsp.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,6 +37,10 @@
 	.id	= OMAP_MCBSP##port_nr,			\
 }
 
+#define MCBSP_CONFIG_TYPE2	0x2
+#define MCBSP_CONFIG_TYPE3	0x3
+#define MCBSP_CONFIG_TYPE4	0x4
+
 #define OMAP7XX_MCBSP1_BASE	0xfffb1000
 #define OMAP7XX_MCBSP2_BASE	0xfffb1800
 
@@ -48,32 +52,14 @@
 #define OMAP1610_MCBSP2_BASE	0xfffb1000
 #define OMAP1610_MCBSP3_BASE	0xe1017000
 
-#define OMAP24XX_MCBSP1_BASE	0x48074000
-#define OMAP24XX_MCBSP2_BASE	0x48076000
-#define OMAP2430_MCBSP3_BASE	0x4808c000
-#define OMAP2430_MCBSP4_BASE	0x4808e000
-#define OMAP2430_MCBSP5_BASE	0x48096000
-
-#define OMAP34XX_MCBSP1_BASE	0x48074000
-#define OMAP34XX_MCBSP2_BASE	0x49022000
-#define OMAP34XX_MCBSP2_ST_BASE	0x49028000
-#define OMAP34XX_MCBSP3_BASE	0x49024000
-#define OMAP34XX_MCBSP3_ST_BASE	0x4902A000
-#define OMAP34XX_MCBSP3_BASE	0x49024000
-#define OMAP34XX_MCBSP4_BASE	0x49026000
-#define OMAP34XX_MCBSP5_BASE	0x48096000
-
-#define OMAP44XX_MCBSP1_BASE	0x49022000
-#define OMAP44XX_MCBSP2_BASE	0x49024000
-#define OMAP44XX_MCBSP3_BASE	0x49026000
-#define OMAP44XX_MCBSP4_BASE	0x48096000
-
-#if defined(CONFIG_ARCH_OMAP15XX) || defined(CONFIG_ARCH_OMAP16XX) || defined(CONFIG_ARCH_OMAP730) || defined(CONFIG_ARCH_OMAP850)
+#ifdef CONFIG_ARCH_OMAP1
 
 #define OMAP_MCBSP_REG_DRR2	0x00
 #define OMAP_MCBSP_REG_DRR1	0x02
 #define OMAP_MCBSP_REG_DXR2	0x04
 #define OMAP_MCBSP_REG_DXR1	0x06
+#define OMAP_MCBSP_REG_DRR	0x02
+#define OMAP_MCBSP_REG_DXR	0x06
 #define OMAP_MCBSP_REG_SPCR2	0x08
 #define OMAP_MCBSP_REG_SPCR1	0x0a
 #define OMAP_MCBSP_REG_RCR2	0x0c
@@ -106,13 +92,6 @@
 #define OMAP_MCBSP_REG_XCCR	0x00
 #define OMAP_MCBSP_REG_RCCR	0x00
 
-#define AUDIO_MCBSP_DATAWRITE	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DXR1)
-#define AUDIO_MCBSP_DATAREAD	(OMAP1510_MCBSP1_BASE + OMAP_MCBSP_REG_DRR1)
-
-#define AUDIO_MCBSP		OMAP_MCBSP1
-#define AUDIO_DMA_TX		OMAP_DMA_MCBSP1_TX
-#define AUDIO_DMA_RX		OMAP_DMA_MCBSP1_RX
-
 #else
 
 #define OMAP_MCBSP_REG_DRR2	0x00
@@ -168,13 +147,6 @@
 #define OMAP_ST_REG_SFIRCR	0x28
 #define OMAP_ST_REG_SSELCR	0x2C
 
-#define AUDIO_MCBSP_DATAWRITE	(OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DXR1)
-#define AUDIO_MCBSP_DATAREAD	(OMAP24XX_MCBSP2_BASE + OMAP_MCBSP_REG_DRR1)
-
-#define AUDIO_MCBSP		OMAP_MCBSP2
-#define AUDIO_DMA_TX		OMAP24XX_DMA_MCBSP2_TX
-#define AUDIO_DMA_RX		OMAP24XX_DMA_MCBSP2_RX
-
 #endif
 
 /************************** McBSP SPCR1 bit definitions ***********************/
@@ -428,8 +400,9 @@
 #ifdef CONFIG_ARCH_OMAP3
 	/* Sidetone block for McBSP 2 and 3 */
 	unsigned long phys_base_st;
-	u16 buffer_size;
 #endif
+	u16 buffer_size;
+	unsigned int mcbsp_config_type;
 };
 
 struct omap_mcbsp_st_data {
@@ -445,6 +418,7 @@
 struct omap_mcbsp {
 	struct device *dev;
 	unsigned long phys_base;
+	unsigned long phys_dma_base;
 	void __iomem *io_base;
 	u8 id;
 	u8 free;
@@ -471,7 +445,6 @@
 	/* Protect the field .free, while checking if the mcbsp is in use */
 	spinlock_t lock;
 	struct omap_mcbsp_platform_data *pdata;
-	struct clk *iclk;
 	struct clk *fclk;
 #ifdef CONFIG_ARCH_OMAP3
 	struct omap_mcbsp_st_data *st_data;
@@ -480,7 +453,17 @@
 	u16 max_rx_thres;
 #endif
 	void *reg_cache;
+	unsigned int mcbsp_config_type;
 };
+
+/**
+ * omap_mcbsp_dev_attr - OMAP McBSP device attributes for omap_hwmod
+ * @sidetone: name of the sidetone device
+ */
+struct omap_mcbsp_dev_attr {
+	const char *sidetone;
+};
+
 extern struct omap_mcbsp **mcbsp_ptr;
 extern int omap_mcbsp_count, omap_mcbsp_cache_size;
 
@@ -488,8 +471,8 @@
 #define id_to_mcbsp_ptr(id)		mcbsp_ptr[id];
 
 int omap_mcbsp_init(void);
-void omap_mcbsp_register_board_cfg(struct omap_mcbsp_platform_data *config,
-					int size);
+void omap_mcbsp_register_board_cfg(struct resource *res, int res_count,
+			struct omap_mcbsp_platform_data *config, int size);
 void omap_mcbsp_config(unsigned int id, const struct omap_mcbsp_reg_cfg * config);
 #ifdef CONFIG_ARCH_OMAP3
 void omap_mcbsp_set_tx_threshold(unsigned int id, u16 threshold);
@@ -539,6 +522,9 @@
 void omap2_mcbsp1_mux_clkr_src(u8 mux);
 void omap2_mcbsp1_mux_fsr_src(u8 mux);
 
+int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream);
+int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream);
+
 #ifdef CONFIG_ARCH_OMAP3
 /* Sidetone specific API */
 int omap_st_set_chgain(unsigned int id, int channel, s16 chgain);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/mcspi.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/mcspi.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/mcspi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/mcspi.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,19 @@
 #ifndef _OMAP2_MCSPI_H
 #define _OMAP2_MCSPI_H
 
+#define OMAP2_MCSPI_REV 0
+#define OMAP3_MCSPI_REV 1
+#define OMAP4_MCSPI_REV 2
+
+#define OMAP4_MCSPI_REG_OFFSET 0x100
+
 struct omap2_mcspi_platform_config {
 	unsigned short	num_cs;
+	unsigned int regs_offset;
+};
+
+struct omap2_mcspi_dev_attr {
+	unsigned short num_chipselect;
 };
 
 struct omap2_mcspi_device_config {
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/memory.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,9 +37,9 @@
  * Physical DRAM offset.
  */
 #if defined(CONFIG_ARCH_OMAP1)
-#define PHYS_OFFSET		UL(0x10000000)
+#define PLAT_PHYS_OFFSET		UL(0x10000000)
 #else
-#define PHYS_OFFSET		UL(0x80000000)
+#define PLAT_PHYS_OFFSET		UL(0x80000000)
 #endif
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/mmc.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/mmc.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/mmc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/mmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,25 +24,19 @@
 #define OMAP1_MMC2_BASE		0xfffb7c00	/* omap16xx only */
 
 #define OMAP24XX_NR_MMC		2
-#define OMAP34XX_NR_MMC		3
-#define OMAP44XX_NR_MMC		5
 #define OMAP2420_MMC_SIZE	OMAP1_MMC_SIZE
-#define OMAP3_HSMMC_SIZE	0x200
-#define OMAP4_HSMMC_SIZE	0x1000
 #define OMAP2_MMC1_BASE		0x4809c000
-#define OMAP2_MMC2_BASE		0x480b4000
-#define OMAP3_MMC3_BASE		0x480ad000
-#define OMAP4_MMC4_BASE		0x480d1000
-#define OMAP4_MMC5_BASE		0x480d5000
+
 #define OMAP4_MMC_REG_OFFSET	0x100
-#define HSMMC5			(1 << 4)
-#define HSMMC4			(1 << 3)
-#define HSMMC3			(1 << 2)
-#define HSMMC2			(1 << 1)
-#define HSMMC1			(1 << 0)
 
 #define OMAP_MMC_MAX_SLOTS	2
 
+#define OMAP_HSMMC_SUPPORTS_DUAL_VOLT	BIT(1)
+
+struct omap_mmc_dev_attr {
+	u8 flags;
+};
+
 struct omap_mmc_platform_data {
 	/* back-link to device */
 	struct device *dev;
@@ -71,6 +65,9 @@
 
 	u64 dma_mask;
 
+	/* Integrating attributes from the omap_hwmod layer */
+	u8 controller_flags;
+
 	/* Register offset deviation */
 	u16 reg_offset;
 
@@ -159,8 +156,7 @@
 	defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
 void omap1_init_mmc(struct omap_mmc_platform_data **mmc_data,
 				int nr_controllers);
-void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
-				int nr_controllers);
+void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data);
 int omap_mmc_add(const char *name, int id, unsigned long base,
 				unsigned long size, unsigned int irq,
 				struct omap_mmc_platform_data *data);
@@ -169,8 +165,7 @@
 				int nr_controllers)
 {
 }
-static inline void omap2_init_mmc(struct omap_mmc_platform_data **mmc_data,
-				int nr_controllers)
+static inline void omap242x_init_mmc(struct omap_mmc_platform_data **mmc_data)
 {
 }
 static inline int omap_mmc_add(const char *name, int id, unsigned long base,
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/multi.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/multi.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/multi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/multi.h	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
 #  error "OMAP1 and OMAP2PLUS can't be selected at the same time"
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP2
 #  define MULTI_OMAP2
@@ -74,7 +74,7 @@
 #  define OMAP_NAME omap2420
 # endif
 #endif
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 # ifdef OMAP_NAME
 #  undef  MULTI_OMAP2
 #  define MULTI_OMAP2
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/nand.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/nand.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/nand.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/nand.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,8 +8,16 @@
  * published by the Free Software Foundation.
  */
 
+#include <plat/gpmc.h>
 #include <linux/mtd/partitions.h>
 
+enum nand_io {
+	NAND_OMAP_PREFETCH_POLLED = 0,	/* prefetch polled mode, default */
+	NAND_OMAP_POLLED,		/* polled mode, without prefetch */
+	NAND_OMAP_PREFETCH_DMA,		/* prefetch enabled sDMA mode */
+	NAND_OMAP_PREFETCH_IRQ		/* prefetch enabled irq mode */
+};
+
 struct omap_nand_platform_data {
 	unsigned int		options;
 	int			cs;
@@ -20,8 +28,11 @@
 	int			(*nand_setup)(void);
 	int			(*dev_ready)(struct omap_nand_platform_data *);
 	int			dma_channel;
+	int			gpmc_irq;
+	enum nand_io		xfer_type;
 	unsigned long		phys_base;
 	int			devsize;
+	enum omap_ecc           ecc_opt;
 };
 
 /* minimum size for IO mapping */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/omap34xx.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/omap34xx.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/omap34xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/omap34xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -56,8 +56,12 @@
 #define OMAP3430_ISP_RESZ_BASE		(OMAP3430_ISP_BASE + 0x1000)
 #define OMAP3430_ISP_SBL_BASE		(OMAP3430_ISP_BASE + 0x1200)
 #define OMAP3430_ISP_MMU_BASE		(OMAP3430_ISP_BASE + 0x1400)
-#define OMAP3430_ISP_CSI2A_BASE		(OMAP3430_ISP_BASE + 0x1800)
-#define OMAP3430_ISP_CSI2PHY_BASE	(OMAP3430_ISP_BASE + 0x1970)
+#define OMAP3430_ISP_CSI2A_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1800)
+#define OMAP3430_ISP_CSIPHY2_BASE	(OMAP3430_ISP_BASE + 0x1970)
+#define OMAP3630_ISP_CSI2A_REGS2_BASE	(OMAP3430_ISP_BASE + 0x19C0)
+#define OMAP3630_ISP_CSI2C_REGS1_BASE	(OMAP3430_ISP_BASE + 0x1C00)
+#define OMAP3630_ISP_CSIPHY1_BASE	(OMAP3430_ISP_BASE + 0x1D70)
+#define OMAP3630_ISP_CSI2C_REGS2_BASE	(OMAP3430_ISP_BASE + 0x1DC0)
 
 #define OMAP3430_ISP_END		(OMAP3430_ISP_BASE         + 0x06F)
 #define OMAP3430_ISP_CBUFF_END		(OMAP3430_ISP_CBUFF_BASE   + 0x077)
@@ -69,8 +73,12 @@
 #define OMAP3430_ISP_RESZ_END		(OMAP3430_ISP_RESZ_BASE    + 0x0AB)
 #define OMAP3430_ISP_SBL_END		(OMAP3430_ISP_SBL_BASE     + 0x0FB)
 #define OMAP3430_ISP_MMU_END		(OMAP3430_ISP_MMU_BASE     + 0x06F)
-#define OMAP3430_ISP_CSI2A_END		(OMAP3430_ISP_CSI2A_BASE   + 0x16F)
-#define OMAP3430_ISP_CSI2PHY_END	(OMAP3430_ISP_CSI2PHY_BASE + 0x007)
+#define OMAP3430_ISP_CSI2A_REGS1_END	(OMAP3430_ISP_CSI2A_REGS1_BASE + 0x16F)
+#define OMAP3430_ISP_CSIPHY2_END	(OMAP3430_ISP_CSIPHY2_BASE + 0x00B)
+#define OMAP3630_ISP_CSI2A_REGS2_END	(OMAP3630_ISP_CSI2A_REGS2_BASE + 0x3F)
+#define OMAP3630_ISP_CSI2C_REGS1_END	(OMAP3630_ISP_CSI2C_REGS1_BASE + 0x16F)
+#define OMAP3630_ISP_CSIPHY1_END	(OMAP3630_ISP_CSIPHY1_BASE + 0x00B)
+#define OMAP3630_ISP_CSI2C_REGS2_END	(OMAP3630_ISP_CSI2C_REGS2_BASE + 0x3F)
 
 #define OMAP34XX_HSUSB_OTG_BASE	(L4_34XX_BASE + 0xAB000)
 #define OMAP34XX_USBTLL_BASE	(L4_34XX_BASE + 0x62000)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/omap_hwmod.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * omap_hwmod macros, structures
  *
- * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009-2011 Nokia Corporation
  * Paul Walmsley
  *
  * Created in collaboration with (alphabetical order): BenoÃ®t Cousson,
@@ -30,11 +30,11 @@
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_HWMOD_H
 
 #include <linux/kernel.h>
+#include <linux/init.h>
 #include <linux/list.h>
 #include <linux/ioport.h>
 #include <linux/spinlock.h>
 #include <plat/cpu.h>
-#include <plat/voltage.h>
 
 struct omap_device;
 
@@ -90,6 +90,9 @@
 struct omap_hwmod_mux_info {
 	int				nr_pads;
 	struct omap_device_pad		*pads;
+	int				nr_pads_dynamic;
+	struct omap_device_pad		**pads_dynamic;
+	bool				enabled;
 };
 
 /**
@@ -124,6 +127,7 @@
  * struct omap_hwmod_rst_info - IPs reset lines use by hwmod
  * @name: name of the reset line (module local name)
  * @rst_shift: Offset of the reset bit
+ * @st_shift: Offset of the reset status bit (OMAP2/3 only)
  *
  * @name should be something short, e.g., "cpu0" or "rst". It is defined
  * locally to the hwmod.
@@ -131,6 +135,7 @@
 struct omap_hwmod_rst_info {
 	const char	*name;
 	u8		rst_shift;
+	u8		st_shift;
 };
 
 /**
@@ -178,7 +183,8 @@
 #define ADDR_TYPE_RT		(1 << 1)
 
 /**
- * struct omap_hwmod_addr_space - MPU address space handled by the hwmod
+ * struct omap_hwmod_addr_space - address space handled by the hwmod
+ * @name: name of the address space
  * @pa_start: starting physical address
  * @pa_end: ending physical address
  * @flags: (see omap_hwmod_addr_space.flags macros above)
@@ -187,6 +193,7 @@
  * structure.  GPMC is one example.
  */
 struct omap_hwmod_addr_space {
+	const char *name;
 	u32 pa_start;
 	u32 pa_end;
 	u8 flags;
@@ -370,9 +377,11 @@
  *     of standby, rather than relying on module smart-standby
  * HWMOD_INIT_NO_RESET: don't reset this module at boot - important for
  *     SDRAM controller, etc. XXX probably belongs outside the main hwmod file
+ *     XXX Should be HWMOD_SETUP_NO_RESET
  * HWMOD_INIT_NO_IDLE: don't idle this module at boot - important for SDRAM
  *     controller, etc. XXX probably belongs outside the main hwmod file
- * HWMOD_NO_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
+ *     XXX Should be HWMOD_SETUP_NO_IDLE
+ * HWMOD_NO_OCP_AUTOIDLE: disable module autoidle (OCP_SYSCONFIG.AUTOIDLE)
  *     when module is enabled, rather than the default, which is to
  *     enable autoidle
  * HWMOD_SET_DEFAULT_CLOCKACT: program CLOCKACTIVITY bits at startup
@@ -535,11 +544,12 @@
 	const struct omap_chip_id	omap_chip;
 };
 
-int omap_hwmod_init(struct omap_hwmod **ohs);
+int omap_hwmod_register(struct omap_hwmod **ohs);
 struct omap_hwmod *omap_hwmod_lookup(const char *name);
 int omap_hwmod_for_each(int (*fn)(struct omap_hwmod *oh, void *data),
 			void *data);
-int omap_hwmod_late_init(void);
+
+int __init omap_hwmod_setup_one(const char *name);
 
 int omap_hwmod_enable(struct omap_hwmod *oh);
 int _omap_hwmod_enable(struct omap_hwmod *oh);
@@ -555,6 +565,7 @@
 int omap_hwmod_disable_clocks(struct omap_hwmod *oh);
 
 int omap_hwmod_set_slave_idlemode(struct omap_hwmod *oh, u8 idlemode);
+int omap_hwmod_set_ocp_autoidle(struct omap_hwmod *oh, u8 autoidle);
 
 int omap_hwmod_reset(struct omap_hwmod *oh);
 void omap_hwmod_ocp_barrier(struct omap_hwmod *oh);
@@ -589,6 +600,8 @@
 int omap_hwmod_set_postsetup_state(struct omap_hwmod *oh, u8 state);
 u32 omap_hwmod_get_context_loss_count(struct omap_hwmod *oh);
 
+int omap_hwmod_no_setup_reset(struct omap_hwmod *oh);
+
 /*
  * Chip variant-specific hwmod init routines - XXX should be converted
  * to use initcalls once the initial boot ordering is straightened out
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/onenand.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/onenand.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/onenand.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/onenand.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,15 +15,24 @@
 #define ONENAND_SYNC_READ	(1 << 0)
 #define ONENAND_SYNC_READWRITE	(1 << 1)
 
+struct onenand_freq_info {
+	u16			maf_id;
+	u16			dev_id;
+	u16			ver_id;
+};
+
 struct omap_onenand_platform_data {
 	int			cs;
 	int			gpio_irq;
 	struct mtd_partition	*parts;
 	int			nr_parts;
-	int                     (*onenand_setup)(void __iomem *, int freq);
+	int			(*onenand_setup)(void __iomem *, int *freq_ptr);
+	int		(*get_freq)(const struct onenand_freq_info *freq_info,
+				    bool *clk_dep);
 	int			dma_channel;
 	u8			flags;
 	u8			regulator_can_sleep;
+	u8			skip_initial_unlocking;
 };
 
 #define ONENAND_MAX_PARTITIONS 8
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/prcm.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/prcm.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/prcm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/prcm.h	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,6 @@
 #define __ASM_ARM_ARCH_OMAP_PRCM_H
 
 u32 omap_prcm_get_reset_sources(void);
-void omap_prcm_arch_reset(char mode, const char *cmd);
 int omap2_cm_wait_idlest(void __iomem *reg, u32 mask, u8 idlest,
 			 const char *name);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/sdrc.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/sdrc.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/sdrc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/sdrc.h	2011-05-19 00:06:34.000000000 -0400
@@ -124,8 +124,14 @@
 	u32 mr;
 };
 
-void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
+void omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
 			    struct omap_sdrc_params *sdrc_cs1);
+#else
+static inline void __init omap2_sdrc_init(struct omap_sdrc_params *sdrc_cs0,
+					  struct omap_sdrc_params *sdrc_cs1) {};
+#endif
+
 int omap2_sdrc_get_params(unsigned long r,
 			  struct omap_sdrc_params **sdrc_cs0,
 			  struct omap_sdrc_params **sdrc_cs1);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/serial.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/serial.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/serial.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/serial.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
  * 2. We assume printascii is called at least once before paging_init,
  *    and addruart has a chance to read OMAP_UART_INFO
  */
-#define OMAP_UART_INFO		(PHYS_OFFSET + 0x3ffc)
+#define OMAP_UART_INFO		(PLAT_PHYS_OFFSET + 0x3ffc)
 
 /* OMAP1 serial ports */
 #define OMAP1_UART1_BASE	0xfffb0000
@@ -51,6 +51,11 @@
 #define OMAP4_UART3_BASE	0x48020000
 #define OMAP4_UART4_BASE	0x4806e000
 
+/* TI816X serial ports */
+#define TI816X_UART1_BASE	0x48020000
+#define TI816X_UART2_BASE	0x48022000
+#define TI816X_UART3_BASE	0x48024000
+
 /* External port on Zoom2/3 */
 #define ZOOM_UART_BASE		0x10000000
 #define ZOOM_UART_VIRT		0xfa400000
@@ -81,6 +86,9 @@
 #define OMAP4UART2		OMAP2UART2
 #define OMAP4UART3		43
 #define OMAP4UART4		44
+#define TI816XUART1		81
+#define TI816XUART2		82
+#define TI816XUART3		83
 #define ZOOM_UART		95		/* Only on zoom2/3 */
 
 /* This is only used by 8250.c for omap1510 */
@@ -96,7 +104,6 @@
 
 struct omap_board_data;
 
-extern void __init omap_serial_early_init(void);
 extern void omap_serial_init(void);
 extern void omap_serial_init_port(struct omap_board_data *bdata);
 extern int omap_uart_can_sleep(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/smartreflex.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/smartreflex.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/smartreflex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/smartreflex.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,245 +0,0 @@
-/*
- * OMAP Smartreflex Defines and Routines
- *
- * Author: Thara Gopinath	<thara@ti.com>
- *
- * Copyright (C) 2010 Texas Instruments, Inc.
- * Thara Gopinath <thara@ti.com>
- *
- * Copyright (C) 2008 Nokia Corporation
- * Kalle Jokiniemi
- *
- * Copyright (C) 2007 Texas Instruments, Inc.
- * Lesly A M <x0080970@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_ARM_OMAP_SMARTREFLEX_H
-#define __ASM_ARM_OMAP_SMARTREFLEX_H
-
-#include <linux/platform_device.h>
-#include <plat/voltage.h>
-
-/*
- * Different Smartreflex IPs version. The v1 is the 65nm version used in
- * OMAP3430. The v2 is the update for the 45nm version of the IP
- * used in OMAP3630 and OMAP4430
- */
-#define SR_TYPE_V1	1
-#define SR_TYPE_V2	2
-
-/* SMART REFLEX REG ADDRESS OFFSET */
-#define SRCONFIG		0x00
-#define SRSTATUS		0x04
-#define SENVAL			0x08
-#define SENMIN			0x0C
-#define SENMAX			0x10
-#define SENAVG			0x14
-#define AVGWEIGHT		0x18
-#define NVALUERECIPROCAL	0x1c
-#define SENERROR_V1		0x20
-#define ERRCONFIG_V1		0x24
-#define IRQ_EOI			0x20
-#define IRQSTATUS_RAW		0x24
-#define IRQSTATUS		0x28
-#define IRQENABLE_SET		0x2C
-#define IRQENABLE_CLR		0x30
-#define SENERROR_V2		0x34
-#define ERRCONFIG_V2		0x38
-
-/* Bit/Shift Positions */
-
-/* SRCONFIG */
-#define SRCONFIG_ACCUMDATA_SHIFT	22
-#define SRCONFIG_SRCLKLENGTH_SHIFT	12
-#define SRCONFIG_SENNENABLE_V1_SHIFT	5
-#define SRCONFIG_SENPENABLE_V1_SHIFT	3
-#define SRCONFIG_SENNENABLE_V2_SHIFT	1
-#define SRCONFIG_SENPENABLE_V2_SHIFT	0
-#define SRCONFIG_CLKCTRL_SHIFT		0
-
-#define SRCONFIG_ACCUMDATA_MASK		(0x3ff << 22)
-
-#define SRCONFIG_SRENABLE		BIT(11)
-#define SRCONFIG_SENENABLE		BIT(10)
-#define SRCONFIG_ERRGEN_EN		BIT(9)
-#define SRCONFIG_MINMAXAVG_EN		BIT(8)
-#define SRCONFIG_DELAYCTRL		BIT(2)
-
-/* AVGWEIGHT */
-#define AVGWEIGHT_SENPAVGWEIGHT_SHIFT	2
-#define AVGWEIGHT_SENNAVGWEIGHT_SHIFT	0
-
-/* NVALUERECIPROCAL */
-#define NVALUERECIPROCAL_SENPGAIN_SHIFT	20
-#define NVALUERECIPROCAL_SENNGAIN_SHIFT	16
-#define NVALUERECIPROCAL_RNSENP_SHIFT	8
-#define NVALUERECIPROCAL_RNSENN_SHIFT	0
-
-/* ERRCONFIG */
-#define ERRCONFIG_ERRWEIGHT_SHIFT	16
-#define ERRCONFIG_ERRMAXLIMIT_SHIFT	8
-#define ERRCONFIG_ERRMINLIMIT_SHIFT	0
-
-#define SR_ERRWEIGHT_MASK		(0x07 << 16)
-#define SR_ERRMAXLIMIT_MASK		(0xff << 8)
-#define SR_ERRMINLIMIT_MASK		(0xff << 0)
-
-#define ERRCONFIG_VPBOUNDINTEN_V1	BIT(31)
-#define ERRCONFIG_VPBOUNDINTST_V1	BIT(30)
-#define	ERRCONFIG_MCUACCUMINTEN		BIT(29)
-#define ERRCONFIG_MCUACCUMINTST		BIT(28)
-#define	ERRCONFIG_MCUVALIDINTEN		BIT(27)
-#define ERRCONFIG_MCUVALIDINTST		BIT(26)
-#define ERRCONFIG_MCUBOUNDINTEN		BIT(25)
-#define	ERRCONFIG_MCUBOUNDINTST		BIT(24)
-#define	ERRCONFIG_MCUDISACKINTEN	BIT(23)
-#define ERRCONFIG_VPBOUNDINTST_V2	BIT(23)
-#define ERRCONFIG_MCUDISACKINTST	BIT(22)
-#define ERRCONFIG_VPBOUNDINTEN_V2	BIT(22)
-
-#define ERRCONFIG_STATUS_V1_MASK	(ERRCONFIG_VPBOUNDINTST_V1 | \
-					ERRCONFIG_MCUACCUMINTST | \
-					ERRCONFIG_MCUVALIDINTST | \
-					ERRCONFIG_MCUBOUNDINTST | \
-					ERRCONFIG_MCUDISACKINTST)
-/* IRQSTATUS */
-#define IRQSTATUS_MCUACCUMINT		BIT(3)
-#define IRQSTATUS_MCVALIDINT		BIT(2)
-#define IRQSTATUS_MCBOUNDSINT		BIT(1)
-#define IRQSTATUS_MCUDISABLEACKINT	BIT(0)
-
-/* IRQENABLE_SET and IRQENABLE_CLEAR */
-#define IRQENABLE_MCUACCUMINT		BIT(3)
-#define IRQENABLE_MCUVALIDINT		BIT(2)
-#define IRQENABLE_MCUBOUNDSINT		BIT(1)
-#define IRQENABLE_MCUDISABLEACKINT	BIT(0)
-
-/* Common Bit values */
-
-#define SRCLKLENGTH_12MHZ_SYSCLK	0x3c
-#define SRCLKLENGTH_13MHZ_SYSCLK	0x41
-#define SRCLKLENGTH_19MHZ_SYSCLK	0x60
-#define SRCLKLENGTH_26MHZ_SYSCLK	0x82
-#define SRCLKLENGTH_38MHZ_SYSCLK	0xC0
-
-/*
- * 3430 specific values. Maybe these should be passed from board file or
- * pmic structures.
- */
-#define OMAP3430_SR_ACCUMDATA		0x1f4
-
-#define OMAP3430_SR1_SENPAVGWEIGHT	0x03
-#define OMAP3430_SR1_SENNAVGWEIGHT	0x03
-
-#define OMAP3430_SR2_SENPAVGWEIGHT	0x01
-#define OMAP3430_SR2_SENNAVGWEIGHT	0x01
-
-#define OMAP3430_SR_ERRWEIGHT		0x04
-#define OMAP3430_SR_ERRMAXLIMIT		0x02
-
-/**
- * struct omap_sr_pmic_data - Strucutre to be populated by pmic code to pass
- *				pmic specific info to smartreflex driver
- *
- * @sr_pmic_init:	API to initialize smartreflex on the PMIC side.
- */
-struct omap_sr_pmic_data {
-	void (*sr_pmic_init) (void);
-};
-
-#ifdef CONFIG_OMAP_SMARTREFLEX
-/*
- * The smart reflex driver supports CLASS1 CLASS2 and CLASS3 SR.
- * The smartreflex class driver should pass the class type.
- * Should be used to populate the class_type field of the
- * omap_smartreflex_class_data structure.
- */
-#define SR_CLASS1	0x1
-#define SR_CLASS2	0x2
-#define SR_CLASS3	0x3
-
-/**
- * struct omap_sr_class_data - Smartreflex class driver info
- *
- * @enable:		API to enable a particular class smaartreflex.
- * @disable:		API to disable a particular class smartreflex.
- * @configure:		API to configure a particular class smartreflex.
- * @notify:		API to notify the class driver about an event in SR.
- *			Not needed for class3.
- * @notify_flags:	specify the events to be notified to the class driver
- * @class_type:		specify which smartreflex class.
- *			Can be used by the SR driver to take any class
- *			based decisions.
- */
-struct omap_sr_class_data {
-	int (*enable)(struct voltagedomain *voltdm);
-	int (*disable)(struct voltagedomain *voltdm, int is_volt_reset);
-	int (*configure)(struct voltagedomain *voltdm);
-	int (*notify)(struct voltagedomain *voltdm, u32 status);
-	u8 notify_flags;
-	u8 class_type;
-};
-
-/**
- * struct omap_sr_nvalue_table	- Smartreflex n-target value info
- *
- * @efuse_offs:	The offset of the efuse where n-target values are stored.
- * @nvalue:	The n-target value.
- */
-struct omap_sr_nvalue_table {
-	u32 efuse_offs;
-	u32 nvalue;
-};
-
-/**
- * struct omap_sr_data - Smartreflex platform data.
- *
- * @ip_type:		Smartreflex IP type.
- * @senp_mod:		SENPENABLE value for the sr
- * @senn_mod:		SENNENABLE value for sr
- * @nvalue_count:	Number of distinct nvalues in the nvalue table
- * @enable_on_init:	whether this sr module needs to enabled at
- *			boot up or not.
- * @nvalue_table:	table containing the  efuse offsets and nvalues
- *			corresponding to them.
- * @voltdm:		Pointer to the voltage domain associated with the SR
- */
-struct omap_sr_data {
-	int				ip_type;
-	u32				senp_mod;
-	u32				senn_mod;
-	int				nvalue_count;
-	bool				enable_on_init;
-	struct omap_sr_nvalue_table	*nvalue_table;
-	struct voltagedomain		*voltdm;
-};
-
-/* Smartreflex module enable/disable interface */
-void omap_sr_enable(struct voltagedomain *voltdm);
-void omap_sr_disable(struct voltagedomain *voltdm);
-void omap_sr_disable_reset_volt(struct voltagedomain *voltdm);
-
-/* API to register the pmic specific data with the smartreflex driver. */
-void omap_sr_register_pmic(struct omap_sr_pmic_data *pmic_data);
-
-/* Smartreflex driver hooks to be called from Smartreflex class driver */
-int sr_enable(struct voltagedomain *voltdm, unsigned long volt);
-void sr_disable(struct voltagedomain *voltdm);
-int sr_configure_errgen(struct voltagedomain *voltdm);
-int sr_configure_minmax(struct voltagedomain *voltdm);
-
-/* API to register the smartreflex class driver with the smartreflex driver */
-int sr_register_class(struct omap_sr_class_data *class_data);
-#else
-static inline void omap_sr_enable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable(struct voltagedomain *voltdm) {}
-static inline void omap_sr_disable_reset_volt(
-		struct voltagedomain *voltdm) {}
-static inline void omap_sr_register_pmic(
-		struct omap_sr_pmic_data *pmic_data) {}
-#endif
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/sram.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/sram.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/sram.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/sram.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,19 @@
 #define __ARCH_ARM_OMAP_SRAM_H
 
 #ifndef __ASSEMBLY__
-extern void * omap_sram_push(void * start, unsigned long size);
+#include <asm/fncpy.h>
+
+extern void *omap_sram_push_address(unsigned long size);
+
+/* Macro to push a function to the internal SRAM, using the fncpy API */
+#define omap_sram_push(funcp, size) ({				\
+	typeof(&(funcp)) _res = NULL;				\
+	void *_sram_address = omap_sram_push_address(size);	\
+	if (_sram_address)					\
+		_res = fncpy(_sram_address, &(funcp), size);	\
+	_res;							\
+})
+
 extern void omap_sram_reprogram_clock(u32 dpllctl, u32 ckctl);
 
 extern void omap2_sram_ddr_init(u32 *slow_dll_ctrl, u32 fast_dll_ctrl,
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/system.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/system.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,48 +4,14 @@
  */
 #ifndef __ASM_ARCH_SYSTEM_H
 #define __ASM_ARCH_SYSTEM_H
-#include <linux/clk.h>
-
-#include <asm/mach-types.h>
-#include <mach/hardware.h>
-
-#include <plat/prcm.h>
 
-#ifndef CONFIG_MACH_VOICEBLUE
-#define voiceblue_reset()		do {} while (0)
-#else
-extern void voiceblue_reset(void);
-#endif
+#include <asm/proc-fns.h>
 
 static inline void arch_idle(void)
 {
 	cpu_do_idle();
 }
 
-static inline void omap1_arch_reset(char mode, const char *cmd)
-{
-	/*
-	 * Workaround for 5912/1611b bug mentioned in sprz209d.pdf p. 28
-	 * "Global Software Reset Affects Traffic Controller Frequency".
-	 */
-	if (cpu_is_omap5912()) {
-		omap_writew(omap_readw(DPLL_CTL) & ~(1 << 4),
-				 DPLL_CTL);
-		omap_writew(0x8, ARM_RSTCT1);
-	}
-
-	if (machine_is_voiceblue())
-		voiceblue_reset();
-	else
-		omap_writew(1, ARM_RSTCT1);
-}
-
-static inline void arch_reset(char mode, const char *cmd)
-{
-	if (!cpu_class_is_omap2())
-		omap1_arch_reset(mode, cmd);
-	else
-		omap_prcm_arch_reset(mode, cmd);
-}
+extern void (*arch_reset)(char, const char *);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/ti816x.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/ti816x.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/ti816x.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/ti816x.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * This file contains the address data for various TI816X modules.
+ *
+ * Copyright (C) 2010 Texas Instruments, Inc. - 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 __ASM_ARCH_TI816X_H
+#define __ASM_ARCH_TI816X_H
+
+#define L4_SLOW_TI816X_BASE	0x48000000
+
+#define TI816X_SCM_BASE		0x48140000
+#define TI816X_CTRL_BASE	TI816X_SCM_BASE
+#define TI816X_PRCM_BASE	0x48180000
+
+#define TI816X_ARM_INTC_BASE	0x48200000
+
+#endif /* __ASM_ARCH_TI816X_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/uncompress.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -93,6 +93,10 @@
 #define DEBUG_LL_ZOOM(mach)						\
 	_DEBUG_LL_ENTRY(mach, ZOOM_UART_BASE, ZOOM_PORT_SHIFT, ZOOM_UART)
 
+#define DEBUG_LL_TI816X(p, mach)					\
+	_DEBUG_LL_ENTRY(mach, TI816X_UART##p##_BASE, OMAP_PORT_SHIFT,	\
+		TI816XUART##p)
+
 static inline void __arch_decomp_setup(unsigned long arch_id)
 {
 	int port = 0;
@@ -166,6 +170,9 @@
 		DEBUG_LL_ZOOM(omap_zoom2);
 		DEBUG_LL_ZOOM(omap_zoom3);
 
+		/* TI8168 base boards using UART3 */
+		DEBUG_LL_TI816X(3, ti8168evm);
+
 	} while (0);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/usb.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/usb.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,15 +7,12 @@
 #include <plat/board.h>
 
 #define OMAP3_HS_USB_PORTS	3
-enum ehci_hcd_omap_mode {
-	EHCI_HCD_OMAP_MODE_UNKNOWN,
-	EHCI_HCD_OMAP_MODE_PHY,
-	EHCI_HCD_OMAP_MODE_TLL,
-	EHCI_HCD_OMAP_MODE_HSIC,
-};
 
-enum ohci_omap3_port_mode {
-	OMAP_OHCI_PORT_MODE_UNUSED,
+enum usbhs_omap_port_mode {
+	OMAP_USBHS_PORT_MODE_UNUSED,
+	OMAP_EHCI_PORT_MODE_PHY,
+	OMAP_EHCI_PORT_MODE_TLL,
+	OMAP_EHCI_PORT_MODE_HSIC,
 	OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0,
 	OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM,
 	OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0,
@@ -25,24 +22,45 @@
 	OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0,
 	OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM,
 	OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0,
-	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM,
+	OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM
 };
 
-struct ehci_hcd_omap_platform_data {
-	enum ehci_hcd_omap_mode		port_mode[OMAP3_HS_USB_PORTS];
-	unsigned			phy_reset:1;
+struct usbhs_omap_board_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
 
 	/* have to be valid if phy_reset is true and portx is in phy mode */
 	int	reset_gpio_port[OMAP3_HS_USB_PORTS];
+
+	/* Set this to true for ES2.x silicon */
+	unsigned			es2_compatibility:1;
+
+	unsigned			phy_reset:1;
+
+	/*
+	 * Regulators for USB PHYs.
+	 * Each PHY can have a separate regulator.
+	 */
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
 };
 
-struct ohci_hcd_omap_platform_data {
-	enum ohci_omap3_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+struct ehci_hcd_omap_platform_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
+	int				reset_gpio_port[OMAP3_HS_USB_PORTS];
+	struct regulator		*regulator[OMAP3_HS_USB_PORTS];
+	unsigned			phy_reset:1;
+};
 
-	/* Set this to true for ES2.x silicon */
+struct ohci_hcd_omap_platform_data {
+	enum usbhs_omap_port_mode	port_mode[OMAP3_HS_USB_PORTS];
 	unsigned			es2_compatibility:1;
 };
 
+struct usbhs_omap_platform_data {
+	enum usbhs_omap_port_mode		port_mode[OMAP3_HS_USB_PORTS];
+
+	struct ehci_hcd_omap_platform_data	*ehci_data;
+	struct ohci_hcd_omap_platform_data	*ohci_data;
+};
 /*-------------------------------------------------------------------------*/
 
 #define OMAP1_OTG_BASE			0xfffb0400
@@ -80,17 +98,22 @@
 
 extern void usb_musb_init(struct omap_musb_board_data *board_data);
 
-extern void usb_ehci_init(const struct ehci_hcd_omap_platform_data *pdata);
+extern void usbhs_init(const struct usbhs_omap_board_data *pdata);
 
-extern void usb_ohci_init(const struct ohci_hcd_omap_platform_data *pdata);
+extern int omap_usbhs_enable(struct device *dev);
+extern void omap_usbhs_disable(struct device *dev);
 
 extern int omap4430_phy_power(struct device *dev, int ID, int on);
 extern int omap4430_phy_set_clk(struct device *dev, int on);
 extern int omap4430_phy_init(struct device *dev);
 extern int omap4430_phy_exit(struct device *dev);
-
+extern int omap4430_phy_suspend(struct device *dev, int suspend);
 #endif
 
+extern void am35x_musb_reset(void);
+extern void am35x_musb_phy_power(u8 on);
+extern void am35x_musb_clear_irq(void);
+extern void am35x_musb_set_mode(u8 musb_mode);
 
 /*
  * FIXME correct answer depends on hmc_mode,
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/voltage.h linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/voltage.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/include/plat/voltage.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/include/plat/voltage.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,155 +0,0 @@
-/*
- * OMAP Voltage Management Routines
- *
- * Author: Thara Gopinath	<thara@ti.com>
- *
- * Copyright (C) 2009 Texas Instruments, Inc.
- * Thara Gopinath <thara@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 __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
-#define __ARCH_ARM_MACH_OMAP2_VOLTAGE_H
-
-#include <linux/err.h>
-
-#define VOLTSCALE_VPFORCEUPDATE		1
-#define VOLTSCALE_VCBYPASS		2
-
-/*
- * OMAP3 GENERIC setup times. Revisit to see if these needs to be
- * passed from board or PMIC file
- */
-#define OMAP3_CLKSETUP		0xff
-#define OMAP3_VOLTOFFSET	0xff
-#define OMAP3_VOLTSETUP2	0xff
-
-/* Voltage value defines */
-#define OMAP3430_VDD_MPU_OPP1_UV		975000
-#define OMAP3430_VDD_MPU_OPP2_UV		1075000
-#define OMAP3430_VDD_MPU_OPP3_UV		1200000
-#define OMAP3430_VDD_MPU_OPP4_UV		1270000
-#define OMAP3430_VDD_MPU_OPP5_UV		1350000
-
-#define OMAP3430_VDD_CORE_OPP1_UV		975000
-#define OMAP3430_VDD_CORE_OPP2_UV		1050000
-#define OMAP3430_VDD_CORE_OPP3_UV		1150000
-
-#define OMAP3630_VDD_MPU_OPP50_UV		1012500
-#define OMAP3630_VDD_MPU_OPP100_UV		1200000
-#define OMAP3630_VDD_MPU_OPP120_UV		1325000
-#define OMAP3630_VDD_MPU_OPP1G_UV		1375000
-
-#define OMAP3630_VDD_CORE_OPP50_UV		1000000
-#define OMAP3630_VDD_CORE_OPP100_UV		1200000
-
-#define OMAP4430_VDD_MPU_OPP50_UV		930000
-#define OMAP4430_VDD_MPU_OPP100_UV		1100000
-#define OMAP4430_VDD_MPU_OPPTURBO_UV		1260000
-#define OMAP4430_VDD_MPU_OPPNITRO_UV		1350000
-
-#define OMAP4430_VDD_IVA_OPP50_UV		930000
-#define OMAP4430_VDD_IVA_OPP100_UV		1100000
-#define OMAP4430_VDD_IVA_OPPTURBO_UV		1260000
-
-#define OMAP4430_VDD_CORE_OPP50_UV		930000
-#define OMAP4430_VDD_CORE_OPP100_UV		1100000
-
-/**
- * struct voltagedomain - omap voltage domain global structure.
- * @name:	Name of the voltage domain which can be used as a unique
- *		identifier.
- */
-struct voltagedomain {
-	char *name;
-};
-
-/**
- * struct omap_volt_data - Omap voltage specific data.
- * @voltage_nominal:	The possible voltage value in uV
- * @sr_efuse_offs:	The offset of the efuse register(from system
- *			control module base address) from where to read
- *			the n-target value for the smartreflex module.
- * @sr_errminlimit:	Error min limit value for smartreflex. This value
- *			differs at differnet opp and thus is linked
- *			with voltage.
- * @vp_errorgain:	Error gain value for the voltage processor. This
- *			field also differs according to the voltage/opp.
- */
-struct omap_volt_data {
-	u32	volt_nominal;
-	u32	sr_efuse_offs;
-	u8	sr_errminlimit;
-	u8	vp_errgain;
-};
-
-/**
- * struct omap_volt_pmic_info - PMIC specific data required by voltage driver.
- * @slew_rate:	PMIC slew rate (in uv/us)
- * @step_size:	PMIC voltage step size (in uv)
- * @vsel_to_uv:	PMIC API to convert vsel value to actual voltage in uV.
- * @uv_to_vsel:	PMIC API to convert voltage in uV to vsel value.
- */
-struct omap_volt_pmic_info {
-	int slew_rate;
-	int step_size;
-	u32 on_volt;
-	u32 onlp_volt;
-	u32 ret_volt;
-	u32 off_volt;
-	u16 volt_setup_time;
-	u8 vp_erroroffset;
-	u8 vp_vstepmin;
-	u8 vp_vstepmax;
-	u8 vp_vddmin;
-	u8 vp_vddmax;
-	u8 vp_timeout_us;
-	u8 i2c_slave_addr;
-	u8 pmic_reg;
-	unsigned long (*vsel_to_uv) (const u8 vsel);
-	u8 (*uv_to_vsel) (unsigned long uV);
-};
-
-unsigned long omap_vp_get_curr_volt(struct voltagedomain *voltdm);
-void omap_vp_enable(struct voltagedomain *voltdm);
-void omap_vp_disable(struct voltagedomain *voltdm);
-int omap_voltage_scale_vdd(struct voltagedomain *voltdm,
-		unsigned long target_volt);
-void omap_voltage_reset(struct voltagedomain *voltdm);
-void omap_voltage_get_volttable(struct voltagedomain *voltdm,
-		struct omap_volt_data **volt_data);
-struct omap_volt_data *omap_voltage_get_voltdata(struct voltagedomain *voltdm,
-		unsigned long volt);
-unsigned long omap_voltage_get_nom_volt(struct voltagedomain *voltdm);
-struct dentry *omap_voltage_get_dbgdir(struct voltagedomain *voltdm);
-#ifdef CONFIG_PM
-int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info);
-void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method);
-/* API to get the voltagedomain pointer */
-struct voltagedomain *omap_voltage_domain_lookup(char *name);
-
-int omap_voltage_late_init(void);
-#else
-static inline int omap_voltage_register_pmic(struct voltagedomain *voltdm,
-		struct omap_volt_pmic_info *pmic_info)
-{
-	return -EINVAL;
-}
-static inline  void omap_change_voltscale_method(struct voltagedomain *voltdm,
-		int voltscale_method) {}
-static inline int omap_voltage_late_init(void)
-{
-	return -EINVAL;
-}
-static inline struct voltagedomain *omap_voltage_domain_lookup(char *name)
-{
-	return ERR_PTR(-EINVAL);
-}
-#endif
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/io.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/io.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/io.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,7 +85,10 @@
 	}
 #endif
 #ifdef CONFIG_ARCH_OMAP3
-	if (cpu_is_omap34xx()) {
+	if (cpu_is_ti816x()) {
+		if (BETWEEN(p, L4_34XX_PHYS, L4_34XX_SIZE))
+			return XLATE(p, L4_34XX_PHYS, L4_34XX_VIRT);
+	} else if (cpu_is_omap34xx()) {
 		if (BETWEEN(p, L3_34XX_PHYS, L3_34XX_SIZE))
 			return XLATE(p, L3_34XX_PHYS, L3_34XX_VIRT);
 		if (BETWEEN(p, L4_34XX_PHYS, L4_34XX_SIZE))
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/iommu.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/iommu.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/iommu.c	2011-05-19 00:06:34.000000000 -0400
@@ -104,6 +104,9 @@
 	if (!obj)
 		return -EINVAL;
 
+	if (!arch_iommu)
+		return -ENODEV;
+
 	clk_enable(obj->clk);
 
 	err = arch_iommu->enable(obj);
@@ -780,25 +783,21 @@
  */
 static irqreturn_t iommu_fault_handler(int irq, void *data)
 {
-	u32 stat, da;
+	u32 da, errs;
 	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);
+	errs = iommu_report_fault(obj, &da);
 	clk_disable(obj->clk);
-	if (!stat)
+	if (errs == 0)
+		return IRQ_HANDLED;
+
+	/* Fault callback or TLB/PTE Dynamic loading */
+	if (obj->isr && !obj->isr(obj, da, errs, obj->isr_priv))
 		return IRQ_HANDLED;
 
 	iommu_disable(obj);
@@ -806,15 +805,16 @@
 	iopgd = iopgd_offset(obj, da);
 
 	if (!iopgd_is_table(*iopgd)) {
-		dev_err(obj->dev, "%s: da:%08x pgd:%p *pgd:%08x\n", __func__,
-			da, iopgd, *iopgd);
+		dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p "
+			"*pgd:px%08x\n", obj->name, errs, 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);
+	dev_err(obj->dev, "%s: errs:0x%08x da:0x%08x pgd:0x%p *pgd:0x%08x "
+		"pte:0x%p *pte:0x%08x\n", obj->name, errs, da, iopgd, *iopgd,
+		iopte, *iopte);
 
 	return IRQ_NONE;
 }
@@ -917,6 +917,33 @@
 }
 EXPORT_SYMBOL_GPL(iommu_put);
 
+int iommu_set_isr(const char *name,
+		  int (*isr)(struct iommu *obj, u32 da, u32 iommu_errs,
+			     void *priv),
+		  void *isr_priv)
+{
+	struct device *dev;
+	struct iommu *obj;
+
+	dev = driver_find_device(&omap_iommu_driver.driver, NULL, (void *)name,
+				 device_match_by_alias);
+	if (!dev)
+		return -ENODEV;
+
+	obj = to_iommu(dev);
+	mutex_lock(&obj->iommu_lock);
+	if (obj->refcount != 0) {
+		mutex_unlock(&obj->iommu_lock);
+		return -EBUSY;
+	}
+	obj->isr = isr;
+	obj->isr_priv = isr_priv;
+	mutex_unlock(&obj->iommu_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_set_isr);
+
 /*
  *	OMAP Device MMU(IOMMU) detection
  */
@@ -957,11 +984,6 @@
 		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));
@@ -970,6 +992,12 @@
 		goto err_mem;
 	}
 
+	obj->regbase = ioremap(res->start, resource_size(res));
+	if (!obj->regbase) {
+		err = -ENOMEM;
+		goto err_ioremap;
+	}
+
 	irq = platform_get_irq(pdev, 0);
 	if (irq < 0) {
 		err = -ENODEV;
@@ -998,8 +1026,9 @@
 err_pgd:
 	free_irq(irq, obj);
 err_irq:
-	release_mem_region(res->start, resource_size(res));
 	iounmap(obj->regbase);
+err_ioremap:
+	release_mem_region(res->start, resource_size(res));
 err_mem:
 	clk_put(obj->clk);
 err_clk:
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/iovmm.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/iovmm.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/iovmm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/iovmm.c	2011-05-19 00:06:34.000000000 -0400
@@ -271,20 +271,21 @@
 					   size_t bytes, u32 flags)
 {
 	struct iovm_struct *new, *tmp;
-	u32 start, prev_end, alignement;
+	u32 start, prev_end, alignment;
 
 	if (!obj || !bytes)
 		return ERR_PTR(-EINVAL);
 
 	start = da;
-	alignement = PAGE_SIZE;
+	alignment = PAGE_SIZE;
 
-	if (flags & IOVMF_DA_ANON) {
-		start = obj->da_start;
+	if (~flags & IOVMF_DA_FIXED) {
+		/* Don't map address 0 */
+		start = obj->da_start ? obj->da_start : alignment;
 
 		if (flags & IOVMF_LINEAR)
-			alignement = iopgsz_max(bytes);
-		start = roundup(start, alignement);
+			alignment = iopgsz_max(bytes);
+		start = roundup(start, alignment);
 	} else if (start < obj->da_start || start > obj->da_end ||
 					obj->da_end - start < bytes) {
 		return ERR_PTR(-EINVAL);
@@ -303,8 +304,8 @@
 		if (tmp->da_start > start && (tmp->da_start - start) >= bytes)
 			goto found;
 
-		if (tmp->da_end >= start && flags & IOVMF_DA_ANON)
-			start = roundup(tmp->da_end + 1, alignement);
+		if (tmp->da_end >= start && ~flags & IOVMF_DA_FIXED)
+			start = roundup(tmp->da_end + 1, alignment);
 
 		prev_end = tmp->da_end;
 	}
@@ -650,7 +651,6 @@
 	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))
@@ -690,7 +690,7 @@
  * @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.
+ * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
  */
 u32 iommu_vmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
 {
@@ -709,7 +709,6 @@
 	flags &= IOVMF_HW_MASK;
 	flags |= IOVMF_DISCONT;
 	flags |= IOVMF_ALLOC;
-	flags |= (da ? IOVMF_DA_FIXED : IOVMF_DA_ANON);
 
 	sgt = sgtable_alloc(bytes, flags, da, 0);
 	if (IS_ERR(sgt)) {
@@ -780,7 +779,7 @@
  * @flags:	iovma and page property
  *
  * Creates 1-1-1 mapping and returns @da again, which can be
- * adjusted if 'IOVMF_DA_ANON' is set.
+ * adjusted if 'IOVMF_DA_FIXED' is not set.
  */
 u32 iommu_kmap(struct iommu *obj, u32 da, u32 pa, size_t bytes,
 		 u32 flags)
@@ -799,7 +798,6 @@
 	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))
@@ -838,7 +836,7 @@
  * @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.
+ * @da again, which might be adjusted if 'IOVMF_DA_FIXED' is not set.
  */
 u32 iommu_kmalloc(struct iommu *obj, u32 da, size_t bytes, u32 flags)
 {
@@ -858,7 +856,6 @@
 	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))
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/Kconfig linux-libre-2.6.39-gnu/arch/arm/plat-omap/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 	  user must write 1 to
 		/debug/voltage/vdd_<X>/smartreflex/autocomp,
 	  where X is mpu or core for OMAP3.
-	  Optionallly autocompensation can be enabled in the kernel
+	  Optionally autocompensation can be enabled in the kernel
 	  by default during system init via the enable_on_init flag
 	  which an be passed as platform data to the smartreflex driver.
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/mailbox.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/mailbox.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/mailbox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/mailbox.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,6 @@
 
 #include <plat/mailbox.h>
 
-static struct workqueue_struct *mboxd;
 static struct omap_mbox **mboxes;
 
 static int mbox_configured;
@@ -197,7 +196,7 @@
 	/* no more messages in the fifo. clear IRQ source. */
 	ack_mbox_irq(mbox, IRQ_RX);
 nomem:
-	queue_work(mboxd, &mbox->rxq->work);
+	schedule_work(&mbox->rxq->work);
 }
 
 static irqreturn_t mbox_interrupt(int irq, void *p)
@@ -307,7 +306,7 @@
 	if (!--mbox->use_count) {
 		free_irq(mbox->irq, mbox);
 		tasklet_kill(&mbox->txq->tasklet);
-		flush_work(&mbox->rxq->work);
+	flush_work_sync(&mbox->rxq->work);
 		mbox_queue_free(mbox->txq);
 		mbox_queue_free(mbox->rxq);
 	}
@@ -409,10 +408,6 @@
 	if (err)
 		return err;
 
-	mboxd = create_workqueue("mboxd");
-	if (!mboxd)
-		return -ENOMEM;
-
 	/* kfifo size sanity check: alignment and minimal size */
 	mbox_kfifo_size = ALIGN(mbox_kfifo_size, sizeof(mbox_msg_t));
 	mbox_kfifo_size = max_t(unsigned int, mbox_kfifo_size,
@@ -424,7 +419,6 @@
 
 static void __exit omap_mbox_exit(void)
 {
-	destroy_workqueue(mboxd);
 	class_unregister(&omap_mbox_class);
 }
 module_exit(omap_mbox_exit);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/mcbsp.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/mcbsp.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/mcbsp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/mcbsp.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,8 @@
 
 #include <plat/dma.h>
 #include <plat/mcbsp.h>
+#include <plat/omap_device.h>
+#include <linux/pm_runtime.h>
 
 /* XXX These "sideways" includes are a sign that something is wrong */
 #include "../mach-omap2/cm2xxx_3xxx.h"
@@ -227,10 +229,83 @@
 }
 EXPORT_SYMBOL(omap_mcbsp_config);
 
+/**
+ * omap_mcbsp_dma_params - returns the dma channel number
+ * @id - mcbsp id
+ * @stream - indicates the direction of data flow (rx or tx)
+ *
+ * Returns the dma channel number for the rx channel or tx channel
+ * based on the value of @stream for the requested mcbsp given by @id
+ */
+int omap_mcbsp_dma_ch_params(unsigned int id, unsigned int stream)
+{
+	struct omap_mcbsp *mcbsp;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+		return -ENODEV;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	if (stream)
+		return mcbsp->dma_rx_sync;
+	else
+		return mcbsp->dma_tx_sync;
+}
+EXPORT_SYMBOL(omap_mcbsp_dma_ch_params);
+
+/**
+ * omap_mcbsp_dma_reg_params - returns the address of mcbsp data register
+ * @id - mcbsp id
+ * @stream - indicates the direction of data flow (rx or tx)
+ *
+ * Returns the address of mcbsp data transmit register or data receive register
+ * to be used by DMA for transferring/receiving data based on the value of
+ * @stream for the requested mcbsp given by @id
+ */
+int omap_mcbsp_dma_reg_params(unsigned int id, unsigned int stream)
+{
+	struct omap_mcbsp *mcbsp;
+	int data_reg;
+
+	if (!omap_mcbsp_check_valid_id(id)) {
+		printk(KERN_ERR "%s: Invalid id (%d)\n", __func__, id + 1);
+		return -ENODEV;
+	}
+	mcbsp = id_to_mcbsp_ptr(id);
+
+	data_reg = mcbsp->phys_dma_base;
+
+	if (mcbsp->mcbsp_config_type < MCBSP_CONFIG_TYPE2) {
+		if (stream)
+			data_reg += OMAP_MCBSP_REG_DRR1;
+		else
+			data_reg += OMAP_MCBSP_REG_DXR1;
+	} else {
+		if (stream)
+			data_reg += OMAP_MCBSP_REG_DRR;
+		else
+			data_reg += OMAP_MCBSP_REG_DXR;
+	}
+
+	return data_reg;
+}
+EXPORT_SYMBOL(omap_mcbsp_dma_reg_params);
+
 #ifdef CONFIG_ARCH_OMAP3
+static struct omap_device *find_omap_device_by_dev(struct device *dev)
+{
+	struct platform_device *pdev = container_of(dev,
+					struct platform_device, dev);
+	return container_of(pdev, struct omap_device, pdev);
+}
+
 static void omap_st_on(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	/*
 	 * Sidetone uses McBSP ICLK - which must not idle when sidetones
@@ -244,9 +319,6 @@
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w | SIDETONEEN);
 
-	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE));
-
 	/* Enable Sidetone from Sidetone Core */
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 	MCBSP_ST_WRITE(mcbsp, SSELCR, w | ST_SIDETONEEN);
@@ -255,13 +327,13 @@
 static void omap_st_off(struct omap_mcbsp *mcbsp)
 {
 	unsigned int w;
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 	MCBSP_ST_WRITE(mcbsp, SSELCR, w & ~(ST_SIDETONEEN));
 
-	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w | ST_AUTOIDLE);
-
 	w = MCBSP_READ(mcbsp, SSELCR);
 	MCBSP_WRITE(mcbsp, SSELCR, w & ~(SIDETONEEN));
 
@@ -273,9 +345,9 @@
 static void omap_st_fir_write(struct omap_mcbsp *mcbsp, s16 *fir)
 {
 	u16 val, i;
+	struct omap_device *od;
 
-	val = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, val & ~(ST_AUTOIDLE));
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	val = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -303,9 +375,9 @@
 {
 	u16 w;
 	struct omap_mcbsp_st_data *st_data = mcbsp->st_data;
+	struct omap_device *od;
 
-	w = MCBSP_ST_READ(mcbsp, SYSCONFIG);
-	MCBSP_ST_WRITE(mcbsp, SYSCONFIG, w & ~(ST_AUTOIDLE));
+	od = find_omap_device_by_dev(mcbsp->dev);
 
 	w = MCBSP_ST_READ(mcbsp, SSELCR);
 
@@ -648,48 +720,33 @@
 
 static inline void omap34xx_mcbsp_request(struct omap_mcbsp *mcbsp)
 {
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
 	/*
 	 * Enable wakup behavior, smart idle and all wakeups
 	 * REVISIT: some wakeups may be unnecessary
 	 */
 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		u16 syscon;
-
-		syscon = MCBSP_READ(mcbsp, SYSCON);
-		syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
-
-		if (mcbsp->dma_op_mode == MCBSP_DMA_MODE_THRESHOLD) {
-			syscon |= (ENAWAKEUP | SIDLEMODE(0x02) |
-					CLOCKACTIVITY(0x02));
-			MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
-		} else {
-			syscon |= SIDLEMODE(0x01);
-		}
-
-		MCBSP_WRITE(mcbsp, SYSCON, syscon);
+		MCBSP_WRITE(mcbsp, WAKEUPEN, XRDYEN | RRDYEN);
 	}
 }
 
 static inline void omap34xx_mcbsp_free(struct omap_mcbsp *mcbsp)
 {
+	struct omap_device *od;
+
+	od = find_omap_device_by_dev(mcbsp->dev);
+
 	/*
 	 * Disable wakup behavior, smart idle and all wakeups
 	 */
 	if (cpu_is_omap34xx() || cpu_is_omap44xx()) {
-		u16 syscon;
-
-		syscon = MCBSP_READ(mcbsp, SYSCON);
-		syscon &= ~(ENAWAKEUP | SIDLEMODE(0x03) | CLOCKACTIVITY(0x03));
 		/*
 		 * HW bug workaround - If no_idle mode is taken, we need to
 		 * go to smart_idle before going to always_idle, or the
 		 * device will not hit retention anymore.
 		 */
-		syscon |= SIDLEMODE(0x02);
-		MCBSP_WRITE(mcbsp, SYSCON, syscon);
-
-		syscon &= ~(SIDLEMODE(0x03));
-		MCBSP_WRITE(mcbsp, SYSCON, syscon);
 
 		MCBSP_WRITE(mcbsp, WAKEUPEN, 0);
 	}
@@ -764,8 +821,7 @@
 	if (mcbsp->pdata && mcbsp->pdata->ops && mcbsp->pdata->ops->request)
 		mcbsp->pdata->ops->request(id);
 
-	clk_enable(mcbsp->iclk);
-	clk_enable(mcbsp->fclk);
+	pm_runtime_get_sync(mcbsp->dev);
 
 	/* Do procedure specific to omap34xx arch, if applicable */
 	omap34xx_mcbsp_request(mcbsp);
@@ -813,8 +869,7 @@
 	/* Do procedure specific to omap34xx arch, if applicable */
 	omap34xx_mcbsp_free(mcbsp);
 
-	clk_disable(mcbsp->fclk);
-	clk_disable(mcbsp->iclk);
+	pm_runtime_put_sync(mcbsp->dev);
 
 	spin_lock(&mcbsp->lock);
 	mcbsp->free = true;
@@ -844,8 +899,7 @@
 	/* Do procedure specific to omap34xx arch, if applicable */
 	omap34xx_mcbsp_free(mcbsp);
 
-	clk_disable(mcbsp->fclk);
-	clk_disable(mcbsp->iclk);
+	pm_runtime_put_sync(mcbsp->dev);
 
 	if (mcbsp->io_type == OMAP_MCBSP_IRQ_IO) {
 		/* Free IRQs */
@@ -1049,7 +1103,7 @@
 		/* resend */
 		return -1;
 	} else {
-		/* wait for recieve confirmation */
+		/* wait for receive confirmation */
 		int attemps = 0;
 		while (!(MCBSP_READ(mcbsp, SPCR1) & RRDY)) {
 			if (attemps++ > 1000) {
@@ -1649,7 +1703,8 @@
 
 static int __devinit omap_st_add(struct omap_mcbsp *mcbsp)
 {
-	struct omap_mcbsp_platform_data *pdata = mcbsp->pdata;
+	struct platform_device *pdev;
+	struct resource *res;
 	struct omap_mcbsp_st_data *st_data;
 	int err;
 
@@ -1659,7 +1714,10 @@
 		goto err1;
 	}
 
-	st_data->io_base_st = ioremap(pdata->phys_base_st, SZ_4K);
+	pdev = container_of(mcbsp->dev, struct platform_device, dev);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sidetone");
+	st_data->io_base_st = ioremap(res->start, resource_size(res));
 	if (!st_data->io_base_st) {
 		err = -ENOMEM;
 		goto err2;
@@ -1748,6 +1806,7 @@
 	struct omap_mcbsp_platform_data *pdata = pdev->dev.platform_data;
 	struct omap_mcbsp *mcbsp;
 	int id = pdev->id - 1;
+	struct resource *res;
 	int ret = 0;
 
 	if (!pdata) {
@@ -1777,47 +1836,78 @@
 	mcbsp->dma_tx_lch = -1;
 	mcbsp->dma_rx_lch = -1;
 
-	mcbsp->phys_base = pdata->phys_base;
-	mcbsp->io_base = ioremap(pdata->phys_base, SZ_4K);
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "mpu");
+	if (!res) {
+		res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+		if (!res) {
+			dev_err(&pdev->dev, "%s:mcbsp%d has invalid memory"
+					"resource\n", __func__, pdev->id);
+			ret = -ENOMEM;
+			goto exit;
+		}
+	}
+	mcbsp->phys_base = res->start;
+	omap_mcbsp_cache_size = resource_size(res);
+	mcbsp->io_base = ioremap(res->start, resource_size(res));
 	if (!mcbsp->io_base) {
 		ret = -ENOMEM;
 		goto err_ioremap;
 	}
 
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dma");
+	if (!res)
+		mcbsp->phys_dma_base = mcbsp->phys_base;
+	else
+		mcbsp->phys_dma_base = res->start;
+
 	/* Default I/O is IRQ based */
 	mcbsp->io_type = OMAP_MCBSP_IRQ_IO;
-	mcbsp->tx_irq = pdata->tx_irq;
-	mcbsp->rx_irq = pdata->rx_irq;
-	mcbsp->dma_rx_sync = pdata->dma_rx_sync;
-	mcbsp->dma_tx_sync = pdata->dma_tx_sync;
 
-	mcbsp->iclk = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(mcbsp->iclk)) {
-		ret = PTR_ERR(mcbsp->iclk);
-		dev_err(&pdev->dev, "unable to get ick: %d\n", ret);
-		goto err_iclk;
+	mcbsp->tx_irq = platform_get_irq_byname(pdev, "tx");
+	mcbsp->rx_irq = platform_get_irq_byname(pdev, "rx");
+
+	/* From OMAP4 there will be a single irq line */
+	if (mcbsp->tx_irq == -ENXIO)
+		mcbsp->tx_irq = platform_get_irq(pdev, 0);
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "rx");
+	if (!res) {
+		dev_err(&pdev->dev, "%s:mcbsp%d has invalid rx DMA channel\n",
+					__func__, pdev->id);
+		ret = -ENODEV;
+		goto err_res;
 	}
+	mcbsp->dma_rx_sync = res->start;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_DMA, "tx");
+	if (!res) {
+		dev_err(&pdev->dev, "%s:mcbsp%d has invalid tx DMA channel\n",
+					__func__, pdev->id);
+		ret = -ENODEV;
+		goto err_res;
+	}
+	mcbsp->dma_tx_sync = res->start;
 
 	mcbsp->fclk = clk_get(&pdev->dev, "fck");
 	if (IS_ERR(mcbsp->fclk)) {
 		ret = PTR_ERR(mcbsp->fclk);
 		dev_err(&pdev->dev, "unable to get fck: %d\n", ret);
-		goto err_fclk;
+		goto err_res;
 	}
 
 	mcbsp->pdata = pdata;
 	mcbsp->dev = &pdev->dev;
 	mcbsp_ptr[id] = mcbsp;
+	mcbsp->mcbsp_config_type = pdata->mcbsp_config_type;
 	platform_set_drvdata(pdev, mcbsp);
+	pm_runtime_enable(mcbsp->dev);
 
 	/* Initialize mcbsp properties for OMAP34XX if needed / applicable */
 	omap34xx_device_init(mcbsp);
 
 	return 0;
 
-err_fclk:
-	clk_put(mcbsp->iclk);
-err_iclk:
+err_res:
 	iounmap(mcbsp->io_base);
 err_ioremap:
 	kfree(mcbsp);
@@ -1839,7 +1929,6 @@
 		omap34xx_device_exit(mcbsp);
 
 		clk_put(mcbsp->fclk);
-		clk_put(mcbsp->iclk);
 
 		iounmap(mcbsp->io_base);
 		kfree(mcbsp);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/omap_device.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/omap_device.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/omap_device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/omap_device.c	2011-05-19 00:06:34.000000000 -0400
@@ -83,9 +83,11 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clk.h>
+#include <linux/clkdev.h>
 
 #include <plat/omap_device.h>
 #include <plat/omap_hwmod.h>
+#include <plat/clock.h>
 
 /* These parameters are passed to _omap_device_{de,}activate() */
 #define USE_WAKEUP_LAT			0
@@ -239,12 +241,12 @@
 }
 
 /**
- * _add_optional_clock_alias - Add clock alias for hwmod optional clocks
+ * _add_optional_clock_clkdev - Add clkdev entry for hwmod optional clocks
  * @od: struct omap_device *od
  *
  * For every optional clock present per hwmod per omap_device, this function
- * adds an entry in the clocks list of the form <dev-id=dev_name, con-id=role>
- * if an entry is already present in it with the form <dev-id=NULL, con-id=role>
+ * adds an entry in the clkdev table of the form <dev-id=dev_name, con-id=role>
+ * if it does not exist already.
  *
  * The function is called from inside omap_device_build_ss(), after
  * omap_device_register.
@@ -254,25 +256,39 @@
  *
  * No return value.
  */
-static void _add_optional_clock_alias(struct omap_device *od,
+static void _add_optional_clock_clkdev(struct omap_device *od,
 				      struct omap_hwmod *oh)
 {
 	int i;
 
 	for (i = 0; i < oh->opt_clks_cnt; i++) {
 		struct omap_hwmod_opt_clk *oc;
-		int r;
+		struct clk *r;
+		struct clk_lookup *l;
 
 		oc = &oh->opt_clks[i];
 
 		if (!oc->_clk)
 			continue;
 
-		r = clk_add_alias(oc->role, dev_name(&od->pdev.dev),
-				  (char *)oc->clk, &od->pdev.dev);
-		if (r)
-			pr_err("omap_device: %s: clk_add_alias for %s failed\n",
+		r = clk_get_sys(dev_name(&od->pdev.dev), oc->role);
+		if (!IS_ERR(r))
+			continue; /* clkdev entry exists */
+
+		r = omap_clk_get_by_name((char *)oc->clk);
+		if (IS_ERR(r)) {
+			pr_err("omap_device: %s: omap_clk_get_by_name for %s failed\n",
+			       dev_name(&od->pdev.dev), oc->clk);
+			continue;
+		}
+
+		l = clkdev_alloc(r, oc->role, dev_name(&od->pdev.dev));
+		if (!l) {
+			pr_err("omap_device: %s: clkdev_alloc for %s failed\n",
 			       dev_name(&od->pdev.dev), oc->role);
+			return;
+		}
+		clkdev_add(l);
 	}
 }
 
@@ -480,7 +496,7 @@
 
 	for (i = 0; i < oh_cnt; i++) {
 		hwmods[i]->od = od;
-		_add_optional_clock_alias(od, hwmods[i]);
+		_add_optional_clock_clkdev(od, hwmods[i]);
 	}
 
 	if (ret)
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-omap/sram.c linux-libre-2.6.39-gnu/arch/arm/plat-omap/sram.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-omap/sram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-omap/sram.c	2011-05-19 00:06:34.000000000 -0400
@@ -242,7 +242,14 @@
 	       omap_sram_size - SRAM_BOOTLOADER_SZ);
 }
 
-void * omap_sram_push(void * start, unsigned long size)
+/*
+ * Memory allocator for SRAM: calculates the new ceiling address
+ * for pushing a function using the fncpy API.
+ *
+ * Note that fncpy requires the returned address to be aligned
+ * to an 8-byte boundary.
+ */
+void *omap_sram_push_address(unsigned long size)
 {
 	if (size > (omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ))) {
 		printk(KERN_ERR "Not enough space in SRAM\n");
@@ -250,10 +257,7 @@
 	}
 
 	omap_sram_ceil -= size;
-	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, sizeof(void *));
-	memcpy((void *)omap_sram_ceil, start, size);
-	flush_icache_range((unsigned long)omap_sram_ceil,
-		(unsigned long)(omap_sram_ceil + size));
+	omap_sram_ceil = ROUND_DOWN(omap_sram_ceil, FNCPY_ALIGN);
 
 	return (void *)omap_sram_ceil;
 }
@@ -312,7 +316,7 @@
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2420
+#ifdef CONFIG_SOC_OMAP2420
 static int __init omap242x_sram_init(void)
 {
 	_omap2_sram_ddr_init = omap_sram_push(omap242x_sram_ddr_init,
@@ -333,7 +337,7 @@
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP2430
+#ifdef CONFIG_SOC_OMAP2430
 static int __init omap243x_sram_init(void)
 {
 	_omap2_sram_ddr_init = omap_sram_push(omap243x_sram_ddr_init,
@@ -405,20 +409,6 @@
 }
 #endif
 
-#ifdef CONFIG_ARCH_OMAP4
-static int __init omap44xx_sram_init(void)
-{
-	printk(KERN_ERR "FIXME: %s not implemented\n", __func__);
-
-	return -ENODEV;
-}
-#else
-static inline int omap44xx_sram_init(void)
-{
-	return 0;
-}
-#endif
-
 int __init omap_sram_init(void)
 {
 	omap_detect_sram();
@@ -432,8 +422,6 @@
 		omap243x_sram_init();
 	else if (cpu_is_omap34xx())
 		omap34xx_sram_init();
-	else if (cpu_is_omap44xx())
-		omap44xx_sram_init();
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-orion/gpio.c linux-libre-2.6.39-gnu/arch/arm/plat-orion/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-orion/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-orion/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,55 +17,123 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 
-static DEFINE_SPINLOCK(gpio_lock);
-static unsigned long gpio_valid_input[BITS_TO_LONGS(GPIO_MAX)];
-static unsigned long gpio_valid_output[BITS_TO_LONGS(GPIO_MAX)];
+/*
+ * GPIO unit register offsets.
+ */
+#define GPIO_OUT_OFF		0x0000
+#define GPIO_IO_CONF_OFF	0x0004
+#define GPIO_BLINK_EN_OFF	0x0008
+#define GPIO_IN_POL_OFF		0x000c
+#define GPIO_DATA_IN_OFF	0x0010
+#define GPIO_EDGE_CAUSE_OFF	0x0014
+#define GPIO_EDGE_MASK_OFF	0x0018
+#define GPIO_LEVEL_MASK_OFF	0x001c
 
-static inline void __set_direction(unsigned pin, int input)
+struct orion_gpio_chip {
+	struct gpio_chip	chip;
+	spinlock_t		lock;
+	void __iomem		*base;
+	unsigned long		valid_input;
+	unsigned long		valid_output;
+	int			mask_offset;
+	int			secondary_irq_base;
+};
+
+static void __iomem *GPIO_OUT(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_OUT_OFF;
+}
+
+static void __iomem *GPIO_IO_CONF(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_IO_CONF_OFF;
+}
+
+static void __iomem *GPIO_BLINK_EN(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_BLINK_EN_OFF;
+}
+
+static void __iomem *GPIO_IN_POL(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_IN_POL_OFF;
+}
+
+static void __iomem *GPIO_DATA_IN(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_DATA_IN_OFF;
+}
+
+static void __iomem *GPIO_EDGE_CAUSE(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + GPIO_EDGE_CAUSE_OFF;
+}
+
+static void __iomem *GPIO_EDGE_MASK(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + ochip->mask_offset + GPIO_EDGE_MASK_OFF;
+}
+
+static void __iomem *GPIO_LEVEL_MASK(struct orion_gpio_chip *ochip)
+{
+	return ochip->base + ochip->mask_offset + GPIO_LEVEL_MASK_OFF;
+}
+
+
+static struct orion_gpio_chip orion_gpio_chips[2];
+static int orion_gpio_chip_count;
+
+static inline void
+__set_direction(struct orion_gpio_chip *ochip, unsigned pin, int input)
 {
 	u32 u;
 
-	u = readl(GPIO_IO_CONF(pin));
+	u = readl(GPIO_IO_CONF(ochip));
 	if (input)
-		u |= 1 << (pin & 31);
+		u |= 1 << pin;
 	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_IO_CONF(pin));
+		u &= ~(1 << pin);
+	writel(u, GPIO_IO_CONF(ochip));
 }
 
-static void __set_level(unsigned pin, int high)
+static void __set_level(struct orion_gpio_chip *ochip, unsigned pin, int high)
 {
 	u32 u;
 
-	u = readl(GPIO_OUT(pin));
+	u = readl(GPIO_OUT(ochip));
 	if (high)
-		u |= 1 << (pin & 31);
+		u |= 1 << pin;
 	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_OUT(pin));
+		u &= ~(1 << pin);
+	writel(u, GPIO_OUT(ochip));
 }
 
-static inline void __set_blinking(unsigned pin, int blink)
+static inline void
+__set_blinking(struct orion_gpio_chip *ochip, unsigned pin, int blink)
 {
 	u32 u;
 
-	u = readl(GPIO_BLINK_EN(pin));
+	u = readl(GPIO_BLINK_EN(ochip));
 	if (blink)
-		u |= 1 << (pin & 31);
+		u |= 1 << pin;
 	else
-		u &= ~(1 << (pin & 31));
-	writel(u, GPIO_BLINK_EN(pin));
+		u &= ~(1 << pin);
+	writel(u, GPIO_BLINK_EN(ochip));
 }
 
-static inline int orion_gpio_is_valid(unsigned pin, int mode)
+static inline int
+orion_gpio_is_valid(struct orion_gpio_chip *ochip, 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;
-	}
+	if (pin >= ochip->chip.ngpio)
+		goto err_out;
+
+	if ((mode & GPIO_INPUT_OK) && !test_bit(pin, &ochip->valid_input))
+		goto err_out;
+
+	if ((mode & GPIO_OUTPUT_OK) && !test_bit(pin, &ochip->valid_output))
+		goto err_out;
+
+	return 1;
 
 err_out:
 	pr_debug("%s: invalid GPIO %d\n", __func__, pin);
@@ -75,134 +143,155 @@
 /*
  * GENERIC_GPIO primitives.
  */
+static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
+{
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
+
+	if (orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK) ||
+	    orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK))
+		return 0;
+
+	return -EINVAL;
+}
+
 static int orion_gpio_direction_input(struct gpio_chip *chip, unsigned pin)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	unsigned long flags;
 
-	if (!orion_gpio_is_valid(pin, GPIO_INPUT_OK))
+	if (!orion_gpio_is_valid(ochip, pin, GPIO_INPUT_OK))
 		return -EINVAL;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Configure GPIO direction. */
-	__set_direction(pin, 1);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_direction(ochip, pin, 1);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 
 	return 0;
 }
 
-static int orion_gpio_get_value(struct gpio_chip *chip, unsigned pin)
+static int orion_gpio_get(struct gpio_chip *chip, unsigned pin)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	int val;
 
-	if (readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31)))
-		val = readl(GPIO_DATA_IN(pin)) ^ readl(GPIO_IN_POL(pin));
-	else
-		val = readl(GPIO_OUT(pin));
+	if (readl(GPIO_IO_CONF(ochip)) & (1 << pin)) {
+		val = readl(GPIO_DATA_IN(ochip)) ^ readl(GPIO_IN_POL(ochip));
+	} else {
+		val = readl(GPIO_OUT(ochip));
+	}
 
-	return (val >> (pin & 31)) & 1;
+	return (val >> pin) & 1;
 }
 
-static int orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin,
-	int value)
+static int
+orion_gpio_direction_output(struct gpio_chip *chip, unsigned pin, int value)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	unsigned long flags;
 
-	if (!orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
+	if (!orion_gpio_is_valid(ochip, pin, GPIO_OUTPUT_OK))
 		return -EINVAL;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Disable blinking. */
-	__set_blinking(pin, 0);
-
-	/* Configure GPIO output value. */
-	__set_level(pin, value);
-
-	/* Configure GPIO direction. */
-	__set_direction(pin, 0);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_blinking(ochip, pin, 0);
+	__set_level(ochip, pin, value);
+	__set_direction(ochip, pin, 0);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 
 	return 0;
 }
 
-static void orion_gpio_set_value(struct gpio_chip *chip, unsigned pin,
-	int value)
+static void orion_gpio_set(struct gpio_chip *chip, unsigned pin, int value)
 {
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 	unsigned long flags;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Configure GPIO output value. */
-	__set_level(pin, value);
-
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_level(ochip, pin, value);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 }
 
-static int orion_gpio_request(struct gpio_chip *chip, unsigned pin)
+static int orion_gpio_to_irq(struct gpio_chip *chip, unsigned pin)
 {
-	if (orion_gpio_is_valid(pin, GPIO_INPUT_OK) ||
-	    orion_gpio_is_valid(pin, GPIO_OUTPUT_OK))
-		return 0;
-	return -EINVAL;
-}
-
-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,
-};
+	struct orion_gpio_chip *ochip =
+		container_of(chip, struct orion_gpio_chip, chip);
 
-void __init orion_gpio_init(void)
-{
-	gpiochip_add(&orion_gpiochip);
+	return ochip->secondary_irq_base + pin;
 }
 
+
 /*
  * Orion-specific GPIO API extensions.
  */
+static struct orion_gpio_chip *orion_gpio_chip_find(int pin)
+{
+	int i;
+
+	for (i = 0; i < orion_gpio_chip_count; i++) {
+		struct orion_gpio_chip *ochip = orion_gpio_chips + i;
+		struct gpio_chip *chip = &ochip->chip;
+
+		if (pin >= chip->base && pin < chip->base + chip->ngpio)
+			return ochip;
+	}
+
+	return NULL;
+}
+
 void __init orion_gpio_set_unused(unsigned pin)
 {
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+
+	if (ochip == NULL)
+		return;
+
+	pin -= ochip->chip.base;
+
 	/* Configure as output, drive low. */
-	__set_level(pin, 0);
-	__set_direction(pin, 0);
+	__set_level(ochip, pin, 0);
+	__set_direction(ochip, pin, 0);
 }
 
 void __init orion_gpio_set_valid(unsigned pin, int mode)
 {
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
+
+	if (ochip == NULL)
+		return;
+
+	pin -= ochip->chip.base;
+
 	if (mode == 1)
 		mode = GPIO_INPUT_OK | GPIO_OUTPUT_OK;
+
 	if (mode & GPIO_INPUT_OK)
-		__set_bit(pin, gpio_valid_input);
+		__set_bit(pin, &ochip->valid_input);
 	else
-		__clear_bit(pin, gpio_valid_input);
+		__clear_bit(pin, &ochip->valid_input);
+
 	if (mode & GPIO_OUTPUT_OK)
-		__set_bit(pin, gpio_valid_output);
+		__set_bit(pin, &ochip->valid_output);
 	else
-		__clear_bit(pin, gpio_valid_output);
+		__clear_bit(pin, &ochip->valid_output);
 }
 
 void orion_gpio_set_blink(unsigned pin, int blink)
 {
+	struct orion_gpio_chip *ochip = orion_gpio_chip_find(pin);
 	unsigned long flags;
 
-	spin_lock_irqsave(&gpio_lock, flags);
-
-	/* Set output value to zero. */
-	__set_level(pin, 0);
-
-	/* Set blinking. */
-	__set_blinking(pin, blink);
+	if (ochip == NULL)
+		return;
 
-	spin_unlock_irqrestore(&gpio_lock, flags);
+	spin_lock_irqsave(&ochip->lock, flags);
+	__set_level(ochip, pin, 0);
+	__set_blinking(ochip, pin, blink);
+	spin_unlock_irqrestore(&ochip->lock, flags);
 }
 EXPORT_SYMBOL(orion_gpio_set_blink);
 
@@ -234,59 +323,75 @@
  ****************************************************************************/
 static void gpio_irq_ack(struct irq_data *d)
 {
-	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int type = irqd_get_trigger_type(d);
+
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-		int pin = irq_to_gpio(d->irq);
-		writel(~(1 << (pin & 31)), GPIO_EDGE_CAUSE(pin));
+		int pin = d->irq - ochip->secondary_irq_base;
+
+		writel(~(1 << pin), GPIO_EDGE_CAUSE(ochip));
 	}
 }
 
 static void gpio_irq_mask(struct irq_data *d)
 {
-	int pin = irq_to_gpio(d->irq);
-	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
-	u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
-		GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
-	u32 u = readl(reg);
-	u &= ~(1 << (pin & 31));
-	writel(u, reg);
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int type = irqd_get_trigger_type(d);
+	void __iomem *reg;
+	int pin;
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		reg = GPIO_EDGE_MASK(ochip);
+	else
+		reg = GPIO_LEVEL_MASK(ochip);
+
+	pin = d->irq - ochip->secondary_irq_base;
+
+	writel(readl(reg) & ~(1 << pin), reg);
 }
 
 static void gpio_irq_unmask(struct irq_data *d)
 {
-	int pin = irq_to_gpio(d->irq);
-	int type = irq_desc[d->irq].status & IRQ_TYPE_SENSE_MASK;
-	u32 reg = (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) ?
-		GPIO_EDGE_MASK(pin) : GPIO_LEVEL_MASK(pin);
-	u32 u = readl(reg);
-	u |= 1 << (pin & 31);
-	writel(u, reg);
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int type = irqd_get_trigger_type(d);
+	void __iomem *reg;
+	int pin;
+
+	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING))
+		reg = GPIO_EDGE_MASK(ochip);
+	else
+		reg = GPIO_LEVEL_MASK(ochip);
+
+	pin = d->irq - ochip->secondary_irq_base;
+
+	writel(readl(reg) | (1 << pin), reg);
 }
 
 static int gpio_irq_set_type(struct irq_data *d, u32 type)
 {
-	int pin = irq_to_gpio(d->irq);
-	struct irq_desc *desc;
+	struct orion_gpio_chip *ochip = irq_data_get_irq_chip_data(d);
+	int pin;
 	u32 u;
 
-	u = readl(GPIO_IO_CONF(pin)) & (1 << (pin & 31));
+	pin = d->irq - ochip->secondary_irq_base;
+
+	u = readl(GPIO_IO_CONF(ochip)) & (1 << pin);
 	if (!u) {
 		printk(KERN_ERR "orion gpio_irq_set_type failed "
 				"(irq %d, pin %d).\n", d->irq, pin);
 		return -EINVAL;
 	}
 
-	desc = irq_desc + d->irq;
-
 	/*
 	 * Set edge/level type.
 	 */
 	if (type & (IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING)) {
-		desc->handle_irq = handle_edge_irq;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 	} else if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW)) {
-		desc->handle_irq = handle_level_irq;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
 	} else {
-		printk(KERN_ERR "failed to set irq=%d (type=%d)\n", d->irq, type);
+		printk(KERN_ERR "failed to set irq=%d (type=%d)\n",
+		       d->irq, type);
 		return -EINVAL;
 	}
 
@@ -294,31 +399,29 @@
 	 * Configure interrupt polarity.
 	 */
 	if (type == IRQ_TYPE_EDGE_RISING || type == IRQ_TYPE_LEVEL_HIGH) {
-		u = readl(GPIO_IN_POL(pin));
-		u &= ~(1 << (pin & 31));
-		writel(u, GPIO_IN_POL(pin));
+		u = readl(GPIO_IN_POL(ochip));
+		u &= ~(1 << pin);
+		writel(u, GPIO_IN_POL(ochip));
 	} else if (type == IRQ_TYPE_EDGE_FALLING || type == IRQ_TYPE_LEVEL_LOW) {
-		u = readl(GPIO_IN_POL(pin));
-		u |= 1 << (pin & 31);
-		writel(u, GPIO_IN_POL(pin));
+		u = readl(GPIO_IN_POL(ochip));
+		u |= 1 << pin;
+		writel(u, GPIO_IN_POL(ochip));
 	} else if (type == IRQ_TYPE_EDGE_BOTH) {
 		u32 v;
 
-		v = readl(GPIO_IN_POL(pin)) ^ readl(GPIO_DATA_IN(pin));
+		v = readl(GPIO_IN_POL(ochip)) ^ readl(GPIO_DATA_IN(ochip));
 
 		/*
 		 * set initial polarity based on current input level
 		 */
-		u = readl(GPIO_IN_POL(pin));
-		if (v & (1 << (pin & 31)))
-			u |= 1 << (pin & 31);		/* falling */
+		u = readl(GPIO_IN_POL(ochip));
+		if (v & (1 << pin))
+			u |= 1 << pin;		/* falling */
 		else
-			u &= ~(1 << (pin & 31));	/* rising */
-		writel(u, GPIO_IN_POL(pin));
+			u &= ~(1 << pin);	/* rising */
+		writel(u, GPIO_IN_POL(ochip));
 	}
 
-	desc->status = (desc->status & ~IRQ_TYPE_SENSE_MASK) | type;
-
 	return 0;
 }
 
@@ -330,29 +433,85 @@
 	.irq_set_type	= gpio_irq_set_type,
 };
 
+void __init orion_gpio_init(int gpio_base, int ngpio,
+			    u32 base, int mask_offset, int secondary_irq_base)
+{
+	struct orion_gpio_chip *ochip;
+	int i;
+
+	if (orion_gpio_chip_count == ARRAY_SIZE(orion_gpio_chips))
+		return;
+
+	ochip = orion_gpio_chips + orion_gpio_chip_count;
+	ochip->chip.label = "orion_gpio";
+	ochip->chip.request = orion_gpio_request;
+	ochip->chip.direction_input = orion_gpio_direction_input;
+	ochip->chip.get = orion_gpio_get;
+	ochip->chip.direction_output = orion_gpio_direction_output;
+	ochip->chip.set = orion_gpio_set;
+	ochip->chip.to_irq = orion_gpio_to_irq;
+	ochip->chip.base = gpio_base;
+	ochip->chip.ngpio = ngpio;
+	ochip->chip.can_sleep = 0;
+	spin_lock_init(&ochip->lock);
+	ochip->base = (void __iomem *)base;
+	ochip->valid_input = 0;
+	ochip->valid_output = 0;
+	ochip->mask_offset = mask_offset;
+	ochip->secondary_irq_base = secondary_irq_base;
+
+	gpiochip_add(&ochip->chip);
+
+	orion_gpio_chip_count++;
+
+	/*
+	 * Mask and clear GPIO interrupts.
+	 */
+	writel(0, GPIO_EDGE_CAUSE(ochip));
+	writel(0, GPIO_EDGE_MASK(ochip));
+	writel(0, GPIO_LEVEL_MASK(ochip));
+
+	for (i = 0; i < ngpio; i++) {
+		unsigned int irq = secondary_irq_base + i;
+
+		irq_set_chip_and_handler(irq, &orion_gpio_irq_chip,
+					 handle_level_irq);
+		irq_set_chip_data(irq, ochip);
+		irq_set_status_flags(irq, IRQ_LEVEL);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+}
+
 void orion_gpio_irq_handler(int pinoff)
 {
-	u32 cause;
-	int pin;
+	struct orion_gpio_chip *ochip;
+	u32 cause, type;
+	int i;
 
-	cause = readl(GPIO_DATA_IN(pinoff)) & readl(GPIO_LEVEL_MASK(pinoff));
-	cause |= readl(GPIO_EDGE_CAUSE(pinoff)) & readl(GPIO_EDGE_MASK(pinoff));
+	ochip = orion_gpio_chip_find(pinoff);
+	if (ochip == NULL)
+		return;
 
-	for (pin = pinoff; pin < pinoff + 8; pin++) {
-		int irq = gpio_to_irq(pin);
-		struct irq_desc *desc = irq_desc + irq;
+	cause = readl(GPIO_DATA_IN(ochip)) & readl(GPIO_LEVEL_MASK(ochip));
+	cause |= readl(GPIO_EDGE_CAUSE(ochip)) & readl(GPIO_EDGE_MASK(ochip));
 
-		if (!(cause & (1 << (pin & 31))))
+	for (i = 0; i < ochip->chip.ngpio; i++) {
+		int irq;
+
+		irq = ochip->secondary_irq_base + i;
+
+		if (!(cause & (1 << i)))
 			continue;
 
-		if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+		type = irqd_get_trigger_type(irq_get_irq_data(irq));
+		if ((type & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
 			/* Swap polarity (race with GPIO line) */
 			u32 polarity;
 
-			polarity = readl(GPIO_IN_POL(pin));
-			polarity ^= 1 << (pin & 31);
-			writel(polarity, GPIO_IN_POL(pin));
+			polarity = readl(GPIO_IN_POL(ochip));
+			polarity ^= 1 << i;
+			writel(polarity, GPIO_IN_POL(ochip));
 		}
-		desc_handle_irq(irq, desc);
+		generic_handle_irq(irq);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-orion/include/plat/gpio.h linux-libre-2.6.39-gnu/arch/arm/plat-orion/include/plat/gpio.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-orion/include/plat/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-orion/include/plat/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 #define __PLAT_GPIO_H
 
 #include <linux/init.h>
+#include <asm-generic/gpio.h>
 
 /*
  * GENERIC_GPIO primitives.
@@ -19,6 +20,7 @@
 #define gpio_get_value  __gpio_get_value
 #define gpio_set_value  __gpio_set_value
 #define gpio_cansleep   __gpio_cansleep
+#define gpio_to_irq     __gpio_to_irq
 
 /*
  * Orion-specific GPIO API extensions.
@@ -31,7 +33,8 @@
 void orion_gpio_set_valid(unsigned pin, int mode);
 
 /* Initialize gpiolib. */
-void __init orion_gpio_init(void);
+void __init orion_gpio_init(int gpio_base, int ngpio,
+			    u32 base, int mask_offset, int secondary_irq_base);
 
 /*
  * GPIO interrupt handling.
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-orion/include/plat/time.h linux-libre-2.6.39-gnu/arch/arm/plat-orion/include/plat/time.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-orion/include/plat/time.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-orion/include/plat/time.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,10 @@
 #ifndef __PLAT_TIME_H
 #define __PLAT_TIME_H
 
-void orion_time_init(unsigned int irq, unsigned int tclk);
+void orion_time_set_base(u32 timer_base);
+
+void orion_time_init(u32 bridge_base, u32 bridge_timer1_clr_mask,
+		     unsigned int irq, unsigned int tclk);
 
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-orion/irq.c linux-libre-2.6.39-gnu/arch/arm/plat-orion/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-orion/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-orion/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,10 +56,10 @@
 	for (i = 0; i < 32; i++) {
 		unsigned int irq = irq_start + i;
 
-		set_irq_chip(irq, &orion_irq_chip);
-		set_irq_chip_data(irq, maskaddr);
-		set_irq_handler(irq, handle_level_irq);
-		irq_desc[irq].status |= IRQ_LEVEL;
+		irq_set_chip_and_handler(irq, &orion_irq_chip,
+					 handle_level_irq);
+		irq_set_chip_data(irq, maskaddr);
+		irq_set_status_flags(irq, IRQ_LEVEL);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-orion/time.c linux-libre-2.6.39-gnu/arch/arm/plat-orion/time.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-orion/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-orion/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,28 +18,42 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <asm/sched_clock.h>
-#include <asm/mach/time.h>
-#include <mach/bridge-regs.h>
-#include <mach/hardware.h>
 
 /*
- * Number of timer ticks per jiffy.
+ * MBus bridge block registers.
  */
-static u32 ticks_per_jiffy;
+#define BRIDGE_CAUSE_OFF	0x0110
+#define BRIDGE_MASK_OFF		0x0114
+#define  BRIDGE_INT_TIMER0	 0x0002
+#define  BRIDGE_INT_TIMER1	 0x0004
 
 
 /*
  * Timer block registers.
  */
-#define TIMER_CTRL		(TIMER_VIRT_BASE + 0x0000)
-#define  TIMER0_EN		0x0001
-#define  TIMER0_RELOAD_EN	0x0002
-#define  TIMER1_EN		0x0004
-#define  TIMER1_RELOAD_EN	0x0008
-#define TIMER0_RELOAD		(TIMER_VIRT_BASE + 0x0010)
-#define TIMER0_VAL		(TIMER_VIRT_BASE + 0x0014)
-#define TIMER1_RELOAD		(TIMER_VIRT_BASE + 0x0018)
-#define TIMER1_VAL		(TIMER_VIRT_BASE + 0x001c)
+#define TIMER_CTRL_OFF		0x0000
+#define  TIMER0_EN		 0x0001
+#define  TIMER0_RELOAD_EN	 0x0002
+#define  TIMER1_EN		 0x0004
+#define  TIMER1_RELOAD_EN	 0x0008
+#define TIMER0_RELOAD_OFF	0x0010
+#define TIMER0_VAL_OFF		0x0014
+#define TIMER1_RELOAD_OFF	0x0018
+#define TIMER1_VAL_OFF		0x001c
+
+
+/*
+ * SoC-specific data.
+ */
+static void __iomem *bridge_base;
+static u32 bridge_timer1_clr_mask;
+static void __iomem *timer_base;
+
+
+/*
+ * Number of timer ticks per jiffy.
+ */
+static u32 ticks_per_jiffy;
 
 
 /*
@@ -50,14 +64,14 @@
 
 unsigned long long notrace sched_clock(void)
 {
-	u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+	u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF);
 	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
 }
 
 
 static void notrace orion_update_sched_clock(void)
 {
-	u32 cyc = 0xffffffff - readl(TIMER0_VAL);
+	u32 cyc = ~readl(timer_base + TIMER0_VAL_OFF);
 	update_sched_clock(&cd, cyc, (u32)~0);
 }
 
@@ -71,7 +85,7 @@
  */
 static cycle_t orion_clksrc_read(struct clocksource *cs)
 {
-	return 0xffffffff - readl(TIMER0_VAL);
+	return 0xffffffff - readl(timer_base + TIMER0_VAL_OFF);
 }
 
 static struct clocksource orion_clksrc = {
@@ -101,23 +115,23 @@
 	/*
 	 * Clear and enable clockevent timer interrupt.
 	 */
-	writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 
-	u = readl(BRIDGE_MASK);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
 	u |= BRIDGE_INT_TIMER1;
-	writel(u, BRIDGE_MASK);
+	writel(u, bridge_base + BRIDGE_MASK_OFF);
 
 	/*
 	 * Setup new clockevent timer value.
 	 */
-	writel(delta, TIMER1_VAL);
+	writel(delta, timer_base + TIMER1_VAL_OFF);
 
 	/*
 	 * Enable the timer.
 	 */
-	u = readl(TIMER_CTRL);
+	u = readl(timer_base + TIMER_CTRL_OFF);
 	u = (u & ~TIMER1_RELOAD_EN) | TIMER1_EN;
-	writel(u, TIMER_CTRL);
+	writel(u, timer_base + TIMER_CTRL_OFF);
 
 	local_irq_restore(flags);
 
@@ -135,37 +149,38 @@
 		/*
 		 * Setup timer to fire at 1/HZ intervals.
 		 */
-		writel(ticks_per_jiffy - 1, TIMER1_RELOAD);
-		writel(ticks_per_jiffy - 1, TIMER1_VAL);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_RELOAD_OFF);
+		writel(ticks_per_jiffy - 1, timer_base + TIMER1_VAL_OFF);
 
 		/*
 		 * Enable timer interrupt.
 		 */
-		u = readl(BRIDGE_MASK);
-		writel(u | BRIDGE_INT_TIMER1, BRIDGE_MASK);
+		u = readl(bridge_base + BRIDGE_MASK_OFF);
+		writel(u | BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
 
 		/*
 		 * Enable timer.
 		 */
-		u = readl(TIMER_CTRL);
-		writel(u | TIMER1_EN | TIMER1_RELOAD_EN, TIMER_CTRL);
+		u = readl(timer_base + TIMER_CTRL_OFF);
+		writel(u | TIMER1_EN | TIMER1_RELOAD_EN,
+		       timer_base + TIMER_CTRL_OFF);
 	} else {
 		/*
 		 * Disable timer.
 		 */
-		u = readl(TIMER_CTRL);
-		writel(u & ~TIMER1_EN, TIMER_CTRL);
+		u = readl(timer_base + TIMER_CTRL_OFF);
+		writel(u & ~TIMER1_EN, timer_base + TIMER_CTRL_OFF);
 
 		/*
 		 * Disable timer interrupt.
 		 */
-		u = readl(BRIDGE_MASK);
-		writel(u & ~BRIDGE_INT_TIMER1, BRIDGE_MASK);
+		u = readl(bridge_base + BRIDGE_MASK_OFF);
+		writel(u & ~BRIDGE_INT_TIMER1, bridge_base + BRIDGE_MASK_OFF);
 
 		/*
 		 * ACK pending timer interrupt.
 		 */
-		writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+		writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 
 	}
 	local_irq_restore(flags);
@@ -185,7 +200,7 @@
 	/*
 	 * ACK timer interrupt and call event handler.
 	 */
-	writel(BRIDGE_INT_TIMER1_CLR, BRIDGE_CAUSE);
+	writel(bridge_timer1_clr_mask, bridge_base + BRIDGE_CAUSE_OFF);
 	orion_clkevt.event_handler(&orion_clkevt);
 
 	return IRQ_HANDLED;
@@ -197,31 +212,45 @@
 	.handler	= orion_timer_interrupt
 };
 
-void __init orion_time_init(unsigned int irq, unsigned int tclk)
+void __init
+orion_time_set_base(u32 _timer_base)
+{
+	timer_base = (void __iomem *)_timer_base;
+}
+
+void __init
+orion_time_init(u32 _bridge_base, u32 _bridge_timer1_clr_mask,
+		unsigned int irq, unsigned int tclk)
 {
 	u32 u;
 
+	/*
+	 * Set SoC-specific data.
+	 */
+	bridge_base = (void __iomem *)_bridge_base;
+	bridge_timer1_clr_mask = _bridge_timer1_clr_mask;
+
 	ticks_per_jiffy = (tclk + HZ/2) / HZ;
 
 	/*
-	 * Set scale and timer for sched_clock
+	 * Set scale and timer for sched_clock.
 	 */
 	setup_sched_clock(tclk);
 
 	/*
 	 * Setup free-running clocksource timer (interrupts
-	 * disabled.)
+	 * disabled).
 	 */
-	writel(0xffffffff, TIMER0_VAL);
-	writel(0xffffffff, TIMER0_RELOAD);
-	u = readl(BRIDGE_MASK);
-	writel(u & ~BRIDGE_INT_TIMER0, BRIDGE_MASK);
-	u = readl(TIMER_CTRL);
-	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, TIMER_CTRL);
+	writel(0xffffffff, timer_base + TIMER0_VAL_OFF);
+	writel(0xffffffff, timer_base + TIMER0_RELOAD_OFF);
+	u = readl(bridge_base + BRIDGE_MASK_OFF);
+	writel(u & ~BRIDGE_INT_TIMER0, bridge_base + BRIDGE_MASK_OFF);
+	u = readl(timer_base + TIMER_CTRL_OFF);
+	writel(u | TIMER0_EN | TIMER0_RELOAD_EN, timer_base + TIMER_CTRL_OFF);
 	clocksource_register_hz(&orion_clksrc, tclk);
 
 	/*
-	 * Setup clockevent timer (interrupt-driven.)
+	 * Setup clockevent timer (interrupt-driven).
 	 */
 	setup_irq(irq, &orion_timer_irq);
 	orion_clkevt.mult = div_sc(tclk, NSEC_PER_SEC, orion_clkevt.shift);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-pxa/gpio.c linux-libre-2.6.39-gnu/arch/arm/plat-pxa/gpio.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-pxa/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-pxa/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -284,13 +284,13 @@
 	}
 
 	for (irq  = gpio_to_irq(start); irq <= gpio_to_irq(end); irq++) {
-		set_irq_chip(irq, &pxa_muxed_gpio_chip);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &pxa_muxed_gpio_chip,
+					 handle_edge_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	/* Install handler for GPIO>=2 edge detect interrupts */
-	set_irq_chained_handler(mux_irq, pxa_gpio_demux_handler);
+	irq_set_chained_handler(mux_irq, pxa_gpio_demux_handler);
 	pxa_muxed_gpio_chip.irq_set_wake = fn;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-pxa/include/plat/i2c.h linux-libre-2.6.39-gnu/arch/arm/plat-pxa/include/plat/i2c.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-pxa/include/plat/i2c.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-pxa/include/plat/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.38-gnu/arch/arm/plat-pxa/include/plat/mfp.h linux-libre-2.6.39-gnu/arch/arm/plat-pxa/include/plat/mfp.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-pxa/include/plat/mfp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-pxa/include/plat/mfp.h	2011-05-19 00:06:34.000000000 -0400
@@ -434,7 +434,7 @@
  *
  * mfp_init_addr() - accepts a table of "mfp_addr_map" structure, which
  * represents a range of MFP pins from "start" to "end", with the offset
- * begining at "offset", to define a single pin, let "end" = -1.
+ * beginning at "offset", to define a single pin, let "end" = -1.
  *
  * use
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h linux-libre-2.6.39-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-pxa/include/plat/pxa3xx_nand.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 };
 
 struct pxa3xx_nand_flash {
+	char		*name;
 	uint32_t	chip_id;
 	unsigned int	page_per_block; /* Pages per block (PG_PER_BLK) */
 	unsigned int	page_size;	/* Page size in bytes (PAGE_SZ) */
@@ -37,7 +38,6 @@
 	unsigned int	dfc_width;	/* Width of flash controller(DWIDTH_C) */
 	unsigned int	num_blocks;	/* Number of physical blocks in Flash */
 
-	struct pxa3xx_nand_cmdset *cmdset;	/* NAND command set */
 	struct pxa3xx_nand_timing *timing;	/* NAND Flash timing */
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/cpu-freq.c linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/cpu-freq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/cpu-freq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/cpu-freq.c	2011-05-19 00:06:34.000000000 -0400
@@ -433,7 +433,7 @@
 static struct cpufreq_frequency_table suspend_pll;
 static unsigned int suspend_freq;
 
-static int s3c_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
+static int s3c_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	suspend_pll.frequency = clk_get_rate(_clk_mpll);
 	suspend_pll.index = __raw_readl(S3C2410_MPLLCON);
@@ -455,7 +455,7 @@
 
 	/* whilst we will be called later on, we try and re-set the
 	 * cpu frequencies as soon as possible so that we do not end
-	 * up resuming devices and then immediatley having to re-set
+	 * up resuming devices and then immediately having to re-set
 	 * a number of settings once these devices have restarted.
 	 *
 	 * as a note, it is expected devices are not used until they
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/dma.c linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/dma.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -557,7 +557,7 @@
 		break;
 
 	case S3C2410_DMALOAD_1LOADED_1RUNNING:
-		/* I belive in this case we do not have anything to do
+		/* I believe in this case we do not have anything to do
 		 * until the next buffer comes along, and we turn off the
 		 * reload */
 		return;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/include/plat/udc.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,10 @@
 struct s3c2410_udc_mach_info {
 	void	(*udc_command)(enum s3c2410_udc_cmd_e);
  	void	(*vbus_draw)(unsigned int ma);
+
+	unsigned int pullup_pin;
+	unsigned int pullup_pin_inverted;
+
 	unsigned int vbus_pin;
 	unsigned char vbus_pin_inverted;
 };
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/irq.c linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -592,8 +592,8 @@
 		case IRQ_UART1:
 		case IRQ_UART2:
 		case IRQ_ADCPARENT:
-			set_irq_chip(irqno, &s3c_irq_level_chip);
-			set_irq_handler(irqno, handle_level_irq);
+			irq_set_chip_and_handler(irqno, &s3c_irq_level_chip,
+						 handle_level_irq);
 			break;
 
 		case IRQ_RESERVED6:
@@ -603,35 +603,35 @@
 
 		default:
 			//irqdbf("registering irq %d (s3c irq)\n", irqno);
-			set_irq_chip(irqno, &s3c_irq_chip);
-			set_irq_handler(irqno, handle_edge_irq);
+			irq_set_chip_and_handler(irqno, &s3c_irq_chip,
+						 handle_edge_irq);
 			set_irq_flags(irqno, IRQF_VALID);
 		}
 	}
 
 	/* setup the cascade irq handlers */
 
-	set_irq_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
-	set_irq_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
+	irq_set_chained_handler(IRQ_EINT4t7, s3c_irq_demux_extint4t7);
+	irq_set_chained_handler(IRQ_EINT8t23, s3c_irq_demux_extint8);
 
-	set_irq_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
-	set_irq_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
-	set_irq_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
-	set_irq_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
+	irq_set_chained_handler(IRQ_UART0, s3c_irq_demux_uart0);
+	irq_set_chained_handler(IRQ_UART1, s3c_irq_demux_uart1);
+	irq_set_chained_handler(IRQ_UART2, s3c_irq_demux_uart2);
+	irq_set_chained_handler(IRQ_ADCPARENT, s3c_irq_demux_adc);
 
 	/* external interrupts */
 
 	for (irqno = IRQ_EINT0; irqno <= IRQ_EINT3; irqno++) {
 		irqdbf("registering irq %d (ext int)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_eint0t4);
-		set_irq_handler(irqno, handle_edge_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_eint0t4,
+					 handle_edge_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
 	for (irqno = IRQ_EINT4; irqno <= IRQ_EINT23; irqno++) {
 		irqdbf("registering irq %d (extended s3c irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irqext_chip);
-		set_irq_handler(irqno, handle_edge_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irqext_chip,
+					 handle_edge_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
@@ -641,29 +641,28 @@
 
 	for (irqno = IRQ_S3CUART_RX0; irqno <= IRQ_S3CUART_ERR0; irqno++) {
 		irqdbf("registering irq %d (s3c uart0 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart0);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_uart0,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
 	for (irqno = IRQ_S3CUART_RX1; irqno <= IRQ_S3CUART_ERR1; irqno++) {
 		irqdbf("registering irq %d (s3c uart1 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart1);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_uart1,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
 	for (irqno = IRQ_S3CUART_RX2; irqno <= IRQ_S3CUART_ERR2; irqno++) {
 		irqdbf("registering irq %d (s3c uart2 irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_uart2);
-		set_irq_handler(irqno, handle_level_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_uart2,
+					 handle_level_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
 	for (irqno = IRQ_TC; irqno <= IRQ_ADC; irqno++) {
 		irqdbf("registering irq %d (s3c adc irq)\n", irqno);
-		set_irq_chip(irqno, &s3c_irq_adc);
-		set_irq_handler(irqno, handle_edge_irq);
+		irq_set_chip_and_handler(irqno, &s3c_irq_adc, handle_edge_irq);
 		set_irq_flags(irqno, IRQF_VALID);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/Kconfig linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -56,13 +56,6 @@
 	help
 	  Clock code for supporting DCLK/CLKOUT on S3C24XX architectures
 
-config S3C24XX_PWM
-	bool "PWM device support"
-	select HAVE_PWM
-	help
-	  Support for exporting the PWM timer blocks via the pwm device
-	  system.
-
 # gpio configurations
 
 config S3C24XX_GPIO_EXTRA
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/Makefile linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 obj-$(CONFIG_CPU_FREQ_S3C24XX)	+= cpu-freq.o
 obj-$(CONFIG_CPU_FREQ_S3C24XX_DEBUGFS) += cpu-freq-debugfs.o
 
-# Architecture dependant builds
+# Architecture dependent builds
 
 obj-$(CONFIG_PM_SIMTEC)		+= pm-simtec.o
 obj-$(CONFIG_PM)		+= pm.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/sleep.S linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/sleep.S
--- linux-libre-2.6.38-gnu/arch/arm/plat-s3c24xx/sleep.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s3c24xx/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -44,23 +44,13 @@
 	/* s3c_cpu_save
 	 *
 	 * entry:
-	 *	r0 = save address (virtual addr of s3c_sleep_save_phys)
+	 *	r1 = v:p offset
 	*/
 
 ENTRY(s3c_cpu_save)
 	stmfd	sp!, { r4 - r12, lr }
-
-	@@ store co-processor registers
-
-	mrc	p15, 0, r4, c13, c0, 0	@ PID
-	mrc	p15, 0, r5, c3, c0, 0	@ Domain ID
-	mrc	p15, 0, r6, c2, c0, 0	@ translation table base address
-	mrc	p15, 0, r7, c1, c0, 0	@ control register
-
-	stmia	r0, { r4 - r13 }
-
-	@@ write our state back to RAM
-	bl	s3c_pm_cb_flushcache
+	ldr	r3, =resume_with_mmu
+	bl	cpu_suspend
 
 	@@ jump to final code to send system to sleep
 	ldr	r0, =pm_cpu_sleep
@@ -76,20 +66,6 @@
 
 	.ltorg
 
-	@@ the next bits sit in the .data segment, even though they
-	@@ happen to be code... the s3c_sleep_save_phys needs to be
-	@@ accessed by the resume code before it can restore the MMU.
-	@@ This means that the variable has to be close enough for the
-	@@ code to read it... since the .text segment needs to be RO,
-	@@ the data segment can be the only place to put this code.
-
-	.data
-
-	.global	s3c_sleep_save_phys
-s3c_sleep_save_phys:
-	.word	0
-
-
 	/* sleep magic, to allow the bootloader to check for an valid
 	 * image to resume to. Must be the first word before the
 	 * s3c_cpu_resume entry.
@@ -100,10 +76,6 @@
 	/* s3c_cpu_resume
 	 *
 	 * resume code entry for bootloader to call
-	 *
-	 * we must put this code here in the data segment as we have no
-	 * other way of restoring the stack pointer after sleep, and we
-	 * must not write to the code segment (code is read-only)
 	*/
 
 ENTRY(s3c_cpu_resume)
@@ -134,25 +106,4 @@
 	beq	1001b
 #endif /* CONFIG_DEBUG_RESUME */
 
-	mov	r1, #0
-	mcr	p15, 0, r1, c8, c7, 0		@@ invalidate I & D TLBs
-	mcr	p15, 0, r1, c7, c7, 0		@@ invalidate I & D caches
-
-	ldr	r0, s3c_sleep_save_phys		@ address of restore block
-	ldmia	r0, { r4 - r13 }
-
-	mcr	p15, 0, r4, c13, c0, 0		@ PID
-	mcr	p15, 0, r5, c3, c0, 0		@ Domain ID
-	mcr	p15, 0, r6, c2, c0, 0		@ translation table base
-
-#ifdef CONFIG_DEBUG_RESUME
-	mov	r3, #'R'
-	strb	r3, [ r2, #S3C2410_UTXH ]
-#endif
-
-	ldr	r2, =resume_with_mmu
-	mcr	p15, 0, r7, c1, c0, 0		@ turn on MMU, etc
-	nop					@ second-to-last before mmu
-	mov	pc, r2				@ go back to virtual address
-
-	.ltorg
+	b	cpu_resume
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/cpu.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/cpu.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /* linux/arch/arm/plat-s5p/cpu.c
  *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
+ * Copyright (c) 2009-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
  *
  * S5P CPU Support
  *
@@ -12,17 +12,20 @@
 
 #include <linux/init.h>
 #include <linux/module.h>
-#include <mach/map.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
+
+#include <mach/map.h>
 #include <mach/regs-clock.h>
+
 #include <plat/cpu.h>
 #include <plat/s5p6440.h>
 #include <plat/s5p6442.h>
 #include <plat/s5p6450.h>
 #include <plat/s5pc100.h>
 #include <plat/s5pv210.h>
-#include <plat/s5pv310.h>
+#include <plat/exynos4.h>
 
 /* table of supported CPUs */
 
@@ -31,12 +34,12 @@
 static const char name_s5p6450[] = "S5P6450";
 static const char name_s5pc100[] = "S5PC100";
 static const char name_s5pv210[] = "S5PV210/S5PC110";
-static const char name_s5pv310[] = "S5PV310";
+static const char name_exynos4210[] = "EXYNOS4210";
 
 static struct cpu_table cpu_ids[] __initdata = {
 	{
 		.idcode		= 0x56440100,
-		.idmask		= 0xffffff00,
+		.idmask		= 0xfffff000,
 		.map_io		= s5p6440_map_io,
 		.init_clocks	= s5p6440_init_clocks,
 		.init_uarts	= s5p6440_init_uarts,
@@ -44,7 +47,7 @@
 		.name		= name_s5p6440,
 	}, {
 		.idcode		= 0x36442000,
-		.idmask		= 0xffffff00,
+		.idmask		= 0xfffff000,
 		.map_io		= s5p6442_map_io,
 		.init_clocks	= s5p6442_init_clocks,
 		.init_uarts	= s5p6442_init_uarts,
@@ -52,7 +55,7 @@
 		.name		= name_s5p6442,
 	}, {
 		.idcode		= 0x36450000,
-		.idmask		= 0xffffff00,
+		.idmask		= 0xfffff000,
 		.map_io		= s5p6450_map_io,
 		.init_clocks	= s5p6450_init_clocks,
 		.init_uarts	= s5p6450_init_uarts,
@@ -75,13 +78,13 @@
 		.init		= s5pv210_init,
 		.name		= name_s5pv210,
 	}, {
-		.idcode		= 0x43200000,
-		.idmask		= 0xfffff000,
-		.map_io		= s5pv310_map_io,
-		.init_clocks	= s5pv310_init_clocks,
-		.init_uarts	= s5pv310_init_uarts,
-		.init		= s5pv310_init,
-		.name		= name_s5pv310,
+		.idcode		= 0x43210000,
+		.idmask		= 0xfffe0000,
+		.map_io		= exynos4_map_io,
+		.init_clocks	= exynos4_init_clocks,
+		.init_uarts	= exynos4_init_uarts,
+		.init		= exynos4_init,
+		.name		= name_exynos4210,
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/dev-csis0.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/dev-csis0.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/dev-csis0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/dev-csis0.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
  *
  * S5P series device definition for MIPI-CSIS channel 0
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/dev-csis1.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/dev-csis1.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/dev-csis1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/dev-csis1.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 Samsung Electronics
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
  *
  * S5P series device definition for MIPI-CSIS channel 1
  *
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/dev-fimc3.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/dev-fimc3.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/dev-fimc3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/dev-fimc3.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,43 @@
+/* linux/arch/arm/plat-s5p/dev-fimc3.c
+ *
+ * Copyright (c) 2010 Samsung Electronics
+ *
+ * Base S5P FIMC3 resource and device 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/dma-mapping.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/ioport.h>
+#include <mach/map.h>
+
+static struct resource s5p_fimc3_resource[] = {
+	[0] = {
+		.start	= S5P_PA_FIMC3,
+		.end	= S5P_PA_FIMC3 + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_FIMC3,
+		.end	= IRQ_FIMC3,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static u64 s5p_fimc3_dma_mask = DMA_BIT_MASK(32);
+
+struct platform_device s5p_device_fimc3 = {
+	.name		= "s5p-fimc",
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(s5p_fimc3_resource),
+	.resource	= s5p_fimc3_resource,
+	.dev		= {
+		.dma_mask		= &s5p_fimc3_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/camport.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/camport.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/camport.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/camport.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series camera interface helper functions
+ *
+ * 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_S5P_CAMPORT_H_
+#define PLAT_S5P_CAMPORT_H_ __FILE__
+
+enum s5p_camport_id {
+	S5P_CAMPORT_A,
+	S5P_CAMPORT_B,
+};
+
+/*
+ * The helper functions to configure GPIO for the camera parallel bus.
+ * The camera port can be multiplexed with any FIMC entity, even multiple
+ * FIMC entities are allowed to be attached to a single port simultaneously.
+ * These functions are to be used in the board setup code.
+ */
+int s5pv210_fimc_setup_gpio(enum s5p_camport_id id);
+int exynos4_fimc_setup_gpio(enum s5p_camport_id id);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/csis.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/csis.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/csis.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/csis.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2010 Samsung Electronics
- *
- * S5P series MIPI CSI slave device 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.
- */
-
-#ifndef PLAT_S5P_CSIS_H_
-#define PLAT_S5P_CSIS_H_ __FILE__
-
-/**
- * struct s5p_platform_mipi_csis - platform data for MIPI-CSIS
- * @clk_rate: bus clock frequency
- * @lanes: number of data lanes used
- * @alignment: data alignment in bits
- * @hs_settle: HS-RX settle time
- */
-struct s5p_platform_mipi_csis {
-	unsigned long clk_rate;
-	u8 lanes;
-	u8 alignment;
-	u8 hs_settle;
-};
-
-#endif /* PLAT_S5P_CSIS_H_ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/exynos4.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/exynos4.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/exynos4.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/exynos4.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+/* linux/arch/arm/plat-s5p/include/plat/exynos4.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Header file for exynos4 cpu 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.
+*/
+
+/* Common init code for EXYNOS4 related SoCs */
+
+extern void exynos4_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
+extern void exynos4_register_clocks(void);
+extern void exynos4_setup_clocks(void);
+
+#ifdef CONFIG_CPU_EXYNOS4210
+
+extern  int exynos4_init(void);
+extern void exynos4_init_irq(void);
+extern void exynos4_map_io(void);
+extern void exynos4_init_clocks(int xtal);
+extern struct sys_timer exynos4_timer;
+
+#define exynos4_init_uarts exynos4_common_init_uarts
+
+#else
+#define exynos4_init_clocks NULL
+#define exynos4_init_uarts NULL
+#define exynos4_map_io NULL
+#define exynos4_init NULL
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/mipi_csis.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2010-2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P series MIPI CSI slave device 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.
+ */
+
+#ifndef PLAT_S5P_MIPI_CSIS_H_
+#define PLAT_S5P_MIPI_CSIS_H_ __FILE__
+
+struct platform_device;
+
+/**
+ * struct s5p_platform_mipi_csis - platform data for S5P MIPI-CSIS driver
+ * @clk_rate: bus clock frequency
+ * @lanes: number of data lanes used
+ * @alignment: data alignment in bits
+ * @hs_settle: HS-RX settle time
+ * @fixed_phy_vdd: false to enable external D-PHY regulator management in the
+ *		   driver or true in case this regulator has no enable function
+ * @phy_enable: pointer to a callback controlling D-PHY enable/reset
+ */
+struct s5p_platform_mipi_csis {
+	unsigned long clk_rate;
+	u8 lanes;
+	u8 alignment;
+	u8 hs_settle;
+	bool fixed_phy_vdd;
+	int (*phy_enable)(struct platform_device *pdev, bool on);
+};
+
+/**
+ * s5p_csis_phy_enable - global MIPI-CSI receiver D-PHY control
+ * @pdev: MIPI-CSIS platform device
+ * @on: true to enable D-PHY and deassert its reset
+ *	false to disable D-PHY
+ */
+int s5p_csis_phy_enable(struct platform_device *pdev, bool on);
+
+#endif /* PLAT_S5P_MIPI_CSIS_H_ */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/s5p-time.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,40 @@
+/* linux/arch/arm/plat-s5p/include/plat/s5p-time.h
+ *
+ * Copyright 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * Header file for s5p time 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.
+*/
+
+#ifndef __ASM_PLAT_S5P_TIME_H
+#define __ASM_PLAT_S5P_TIME_H __FILE__
+
+/* S5P HR-Timer Clock mode */
+enum s5p_timer_mode {
+	S5P_PWM0,
+	S5P_PWM1,
+	S5P_PWM2,
+	S5P_PWM3,
+	S5P_PWM4,
+};
+
+struct s5p_timer_source {
+	unsigned int event_id;
+	unsigned int source_id;
+};
+
+/* Be able to sleep for atleast 4 seconds (usually more) */
+#define S5PTIMER_MIN_RANGE	4
+
+#define TCNT_MAX		0xffffffff
+#define NON_PERIODIC		0
+#define PERIODIC		1
+
+extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
+					enum s5p_timer_mode source);
+extern	struct sys_timer s5p_timer;
+#endif /* __ASM_PLAT_S5P_TIME_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/s5pv310.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/s5pv310.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/s5pv310.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/s5pv310.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/* linux/arch/arm/plat-s5p/include/plat/s5pv310.h
- *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Header file for s5pv310 cpu 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.
-*/
-
-/* Common init code for S5PV310 related SoCs */
-
-extern void s5pv310_common_init_uarts(struct s3c2410_uartcfg *cfg, int no);
-extern void s5pv310_register_clocks(void);
-extern void s5pv310_setup_clocks(void);
-
-#ifdef CONFIG_CPU_S5PV310
-
-extern  int s5pv310_init(void);
-extern void s5pv310_init_irq(void);
-extern void s5pv310_map_io(void);
-extern void s5pv310_init_clocks(int xtal);
-extern struct sys_timer s5pv310_timer;
-
-#define s5pv310_init_uarts s5pv310_common_init_uarts
-
-#else
-#define s5pv310_init_clocks NULL
-#define s5pv310_init_uarts NULL
-#define s5pv310_map_io NULL
-#define s5pv310_init NULL
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/include/plat/sysmmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,95 @@
+/* linux/arch/arm/plat-s5p/include/plat/sysmmu.h
+ *
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Samsung System MMU driver for S5P platform
+ *
+ * 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__PLAT_SYSMMU_H
+#define __ASM__PLAT_SYSMMU_H __FILE__
+
+enum S5P_SYSMMU_INTERRUPT_TYPE {
+	SYSMMU_PAGEFAULT,
+	SYSMMU_AR_MULTIHIT,
+	SYSMMU_AW_MULTIHIT,
+	SYSMMU_BUSERROR,
+	SYSMMU_AR_SECURITY,
+	SYSMMU_AR_ACCESS,
+	SYSMMU_AW_SECURITY,
+	SYSMMU_AW_PROTECTION, /* 7 */
+	SYSMMU_FAULTS_NUM
+};
+
+#ifdef CONFIG_S5P_SYSTEM_MMU
+
+#include <mach/sysmmu.h>
+
+/**
+ * s5p_sysmmu_enable() - enable system mmu of ip
+ * @ips: The ip connected system mmu.
+ * #pgd: Base physical address of the 1st level page table
+ *
+ * This function enable system mmu to transfer address
+ * from virtual address to physical address
+ */
+void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd);
+
+/**
+ * s5p_sysmmu_disable() - disable sysmmu mmu of ip
+ * @ips: The ip connected system mmu.
+ *
+ * This function disable system mmu to transfer address
+ * from virtual address to physical address
+ */
+void s5p_sysmmu_disable(sysmmu_ips ips);
+
+/**
+ * s5p_sysmmu_set_tablebase_pgd() - set page table base address to refer page table
+ * @ips: The ip connected system mmu.
+ * @pgd: The page table base address.
+ *
+ * This function set page table base address
+ * When system mmu transfer address from virtaul address to physical address,
+ * system mmu refer address information from page table
+ */
+void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd);
+
+/**
+ * s5p_sysmmu_tlb_invalidate() - flush all TLB entry in system mmu
+ * @ips: The ip connected system mmu.
+ *
+ * This function flush all TLB entry in system mmu
+ */
+void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips);
+
+/** s5p_sysmmu_set_fault_handler() - Fault handler for System MMUs
+ * @itype: type of fault.
+ * @pgtable_base: the physical address of page table base. This is 0 if @ips is
+ *               SYSMMU_BUSERROR.
+ * @fault_addr: the device (virtual) address that the System MMU tried to
+ *             translated. This is 0 if @ips is SYSMMU_BUSERROR.
+ * Called when interrupt occurred by the System MMUs
+ * The device drivers of peripheral devices that has a System MMU can implement
+ * a fault handler to resolve address translation fault by System MMU.
+ * The meanings of return value and parameters are described below.
+
+ * return value: non-zero if the fault is correctly resolved.
+ *         zero if the fault is not handled.
+ */
+void s5p_sysmmu_set_fault_handler(sysmmu_ips ips,
+			int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+					unsigned long pgtable_base,
+					unsigned long fault_addr));
+#else
+#define s5p_sysmmu_enable(ips, pgd) do { } while (0)
+#define s5p_sysmmu_disable(ips) do { } while (0)
+#define s5p_sysmmu_set_tablebase_pgd(ips, pgd) do { } while (0)
+#define s5p_sysmmu_tlb_invalidate(ips) do { } while (0)
+#define s5p_sysmmu_set_fault_handler(ips, handler) do { } while (0)
+#endif
+#endif /* __ASM_PLAT_SYSMMU_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/irq-eint.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/irq-eint.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/irq-eint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/irq-eint.c	2011-05-19 00:06:34.000000000 -0400
@@ -205,15 +205,14 @@
 	int irq;
 
 	for (irq = IRQ_EINT(0); irq <= IRQ_EINT(15); irq++)
-		set_irq_chip(irq, &s5p_irq_vic_eint);
+		irq_set_chip(irq, &s5p_irq_vic_eint);
 
 	for (irq = IRQ_EINT(16); irq <= IRQ_EINT(31); irq++) {
-		set_irq_chip(irq, &s5p_irq_eint);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &s5p_irq_eint, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	set_irq_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
+	irq_set_chained_handler(IRQ_EINT16_31, s5p_irq_demux_eint16_31);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/irq-gpioint.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/irq-gpioint.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/irq-gpioint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/irq-gpioint.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,82 +17,79 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/slab.h>
 
 #include <mach/map.h>
 #include <plat/gpio-core.h>
 #include <plat/gpio-cfg.h>
 
-#define S5P_GPIOREG(x)			(S5P_VA_GPIO + (x))
-
-#define GPIOINT_CON_OFFSET		0x700
-#define GPIOINT_MASK_OFFSET		0x900
-#define GPIOINT_PEND_OFFSET		0xA00
-
-static struct s3c_gpio_chip *irq_chips[S5P_GPIOINT_GROUP_MAXNR];
+#define GPIO_BASE(chip)		(((unsigned long)(chip)->base) & 0xFFFFF000u)
 
-static int s5p_gpioint_get_group(struct irq_data *data)
-{
-	struct gpio_chip *chip = irq_data_get_irq_data(data);
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-	int group;
+#define CON_OFFSET		0x700
+#define MASK_OFFSET		0x900
+#define PEND_OFFSET		0xA00
+#define REG_OFFSET(x)		((x) << 2)
 
-	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++)
-		if (s3c_chip == irq_chips[group])
-			break;
+struct s5p_gpioint_bank {
+	struct list_head	list;
+	int			start;
+	int			nr_groups;
+	int			irq;
+	struct s3c_gpio_chip	**chips;
+	void			(*handler)(unsigned int, struct irq_desc *);
+};
 
-	return group;
-}
+LIST_HEAD(banks);
 
 static int s5p_gpioint_get_offset(struct irq_data *data)
 {
-	struct gpio_chip *chip = irq_data_get_irq_data(data);
-	struct s3c_gpio_chip *s3c_chip = container_of(chip,
-			struct s3c_gpio_chip, chip);
-
-	return data->irq - s3c_chip->irq_base;
+	struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
+	return data->irq - chip->irq_base;
 }
 
 static void s5p_gpioint_ack(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
 	int group, offset, pend_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	pend_offset = group << 2;
+	pend_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
-	value |= 1 << offset;
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_PEND_OFFSET) + pend_offset);
+	value = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
+	value |= BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
 }
 
 static void s5p_gpioint_mask(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	mask_offset = group << 2;
+	mask_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
-	value |= 1 << offset;
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
+	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
+	value |= BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 }
 
 static void s5p_gpioint_unmask(struct irq_data *data)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
 	int group, offset, mask_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	mask_offset = group << 2;
+	mask_offset = REG_OFFSET(group);
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
-	value &= ~(1 << offset);
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_MASK_OFFSET) + mask_offset);
+	value = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
+	value &= ~BIT(offset);
+	__raw_writel(value, GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 }
 
 static void s5p_gpioint_mask_ack(struct irq_data *data)
@@ -103,12 +100,13 @@
 
 static int s5p_gpioint_set_type(struct irq_data *data, unsigned int type)
 {
+	struct s3c_gpio_chip *chip = irq_data_get_irq_handler_data(data);
 	int group, offset, con_offset;
 	unsigned int value;
 
-	group = s5p_gpioint_get_group(data);
+	group = chip->group;
 	offset = s5p_gpioint_get_offset(data);
-	con_offset = group << 2;
+	con_offset = REG_OFFSET(group);
 
 	switch (type) {
 	case IRQ_TYPE_EDGE_RISING:
@@ -132,15 +130,15 @@
 		return -EINVAL;
 	}
 
-	value = __raw_readl(S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
+	value = __raw_readl(GPIO_BASE(chip) + CON_OFFSET + con_offset);
 	value &= ~(0x7 << (offset * 0x4));
 	value |= (type << (offset * 0x4));
-	__raw_writel(value, S5P_GPIOREG(GPIOINT_CON_OFFSET) + con_offset);
+	__raw_writel(value, GPIO_BASE(chip) + CON_OFFSET + con_offset);
 
 	return 0;
 }
 
-struct irq_chip s5p_gpioint = {
+static struct irq_chip s5p_gpioint = {
 	.name		= "s5p_gpioint",
 	.irq_ack	= s5p_gpioint_ack,
 	.irq_mask	= s5p_gpioint_mask,
@@ -151,30 +149,29 @@
 
 static void s5p_gpioint_handler(unsigned int irq, struct irq_desc *desc)
 {
-	int group, offset, pend_offset, mask_offset;
-	int real_irq;
+	struct s5p_gpioint_bank *bank = irq_get_handler_data(irq);
+	int group, pend_offset, mask_offset;
 	unsigned int pend, mask;
 
-	for (group = 0; group < S5P_GPIOINT_GROUP_MAXNR; group++) {
-		pend_offset = group << 2;
-		pend = __raw_readl(S5P_GPIOREG(GPIOINT_PEND_OFFSET) +
-				pend_offset);
+	for (group = 0; group < bank->nr_groups; group++) {
+		struct s3c_gpio_chip *chip = bank->chips[group];
+		if (!chip)
+			continue;
+
+		pend_offset = REG_OFFSET(group);
+		pend = __raw_readl(GPIO_BASE(chip) + PEND_OFFSET + pend_offset);
 		if (!pend)
 			continue;
 
-		mask_offset = group << 2;
-		mask = __raw_readl(S5P_GPIOREG(GPIOINT_MASK_OFFSET) +
-				mask_offset);
+		mask_offset = REG_OFFSET(group);
+		mask = __raw_readl(GPIO_BASE(chip) + MASK_OFFSET + mask_offset);
 		pend &= ~mask;
 
-		for (offset = 0; offset < 8; offset++) {
-			if (pend & (1 << offset)) {
-				struct s3c_gpio_chip *chip = irq_chips[group];
-				if (chip) {
-					real_irq = chip->irq_base + offset;
-					generic_handle_irq(real_irq);
-				}
-			}
+		while (pend) {
+			int offset = fls(pend) - 1;
+			int real_irq = chip->irq_base + offset;
+			generic_handle_irq(real_irq);
+			pend &= ~BIT(offset);
 		}
 	}
 }
@@ -182,28 +179,49 @@
 static __init int s5p_gpioint_add(struct s3c_gpio_chip *chip)
 {
 	static int used_gpioint_groups = 0;
-	static bool handler_registered = 0;
 	int irq, group = chip->group;
 	int i;
+	struct s5p_gpioint_bank *bank = NULL;
 
 	if (used_gpioint_groups >= S5P_GPIOINT_GROUP_COUNT)
 		return -ENOMEM;
 
+	list_for_each_entry(bank, &banks, list) {
+		if (group >= bank->start &&
+		    group < bank->start + bank->nr_groups)
+			break;
+	}
+	if (!bank)
+		return -EINVAL;
+
+	if (!bank->handler) {
+		bank->chips = kzalloc(sizeof(struct s3c_gpio_chip *) *
+				      bank->nr_groups, GFP_KERNEL);
+		if (!bank->chips)
+			return -ENOMEM;
+
+		irq_set_chained_handler(bank->irq, s5p_gpioint_handler);
+		irq_set_handler_data(bank->irq, bank);
+		bank->handler = s5p_gpioint_handler;
+		printk(KERN_INFO "Registered chained gpio int handler for interrupt %d.\n",
+		       bank->irq);
+	}
+
+	/*
+	 * chained GPIO irq has been successfully registered, allocate new gpio
+	 * int group and assign irq nubmers
+	 */
+
 	chip->irq_base = S5P_GPIOINT_BASE +
 			 used_gpioint_groups * S5P_GPIOINT_GROUP_SIZE;
 	used_gpioint_groups++;
 
-	if (!handler_registered) {
-		set_irq_chained_handler(IRQ_GPIOINT, s5p_gpioint_handler);
-		handler_registered = 1;
-	}
-
-	irq_chips[group] = chip;
+	bank->chips[group - bank->start] = chip;
 	for (i = 0; i < chip->chip.ngpio; i++) {
 		irq = chip->irq_base + i;
-		set_irq_chip(irq, &s5p_gpioint);
-		set_irq_data(irq, &chip->chip);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip(irq, &s5p_gpioint);
+		irq_set_handler_data(irq, chip);
+		irq_set_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 	return 0;
@@ -235,3 +253,19 @@
 	}
 	return ret;
 }
+
+int __init s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups)
+{
+	struct s5p_gpioint_bank *bank;
+
+	bank = kzalloc(sizeof(*bank), GFP_KERNEL);
+	if (!bank)
+		return -ENOMEM;
+
+	bank->start = start;
+	bank->nr_groups = nr_groups;
+	bank->irq = chain_irq;
+
+	list_add_tail(&bank->list, &banks);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/Kconfig linux-libre-2.6.39-gnu/arch/arm/plat-s5p/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -7,10 +7,10 @@
 
 config PLAT_S5P
 	bool
-	depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310)
+	depends on (ARCH_S5P64X0 || ARCH_S5P6442 || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4)
 	default y
-	select ARM_VIC if !ARCH_S5PV310
-	select ARM_GIC if ARCH_S5PV310
+	select ARM_VIC if !ARCH_EXYNOS4
+	select ARM_GIC if ARCH_EXYNOS4
 	select NO_IOPORT
 	select ARCH_REQUIRE_GPIOLIB
 	select S3C_GPIO_TRACK
@@ -37,11 +37,16 @@
 	help
 	  Common code for the GPIO interrupts (other than external interrupts.)
 
+config S5P_HRT
+	bool
+	help
+	  Use the High Resolution timer support
+
 comment "System MMU"
 
 config S5P_SYSTEM_MMU
 	bool "S5P SYSTEM MMU"
-	depends on ARCH_S5PV310
+	depends on ARCH_EXYNOS4
 	help
 	  Say Y here if you want to enable System MMU
 
@@ -60,6 +65,11 @@
 	help
 	  Compile in platform device definitions for FIMC controller 2
 
+config S5P_DEV_FIMC3
+	bool
+	help
+	  Compile in platform device definitions for FIMC controller 3
+
 config S5P_DEV_ONENAND
 	bool
 	help
@@ -74,3 +84,8 @@
 	bool
 	help
 	  Compile in platform device definitions for MIPI-CSIS channel 1
+
+config S5P_SETUP_MIPIPHY
+	bool
+	help
+	  Compile in common setup code for MIPI-CSIS and MIPI-DSIM devices
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/Makefile linux-libre-2.6.39-gnu/arch/arm/plat-s5p/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -22,12 +22,15 @@
 obj-$(CONFIG_S5P_SYSTEM_MMU)	+= sysmmu.o
 obj-$(CONFIG_PM)		+= pm.o
 obj-$(CONFIG_PM)		+= irq-pm.o
+obj-$(CONFIG_S5P_HRT) 		+= s5p-time.o
 
 # devices
 
 obj-$(CONFIG_S5P_DEV_FIMC0)	+= dev-fimc0.o
 obj-$(CONFIG_S5P_DEV_FIMC1)	+= dev-fimc1.o
 obj-$(CONFIG_S5P_DEV_FIMC2)	+= dev-fimc2.o
+obj-$(CONFIG_S5P_DEV_FIMC3)	+= dev-fimc3.o
 obj-$(CONFIG_S5P_DEV_ONENAND)	+= dev-onenand.o
 obj-$(CONFIG_S5P_DEV_CSIS0)	+= dev-csis0.o
 obj-$(CONFIG_S5P_DEV_CSIS1)	+= dev-csis1.o
+obj-$(CONFIG_S5P_SETUP_MIPIPHY)	+= setup-mipiphy.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/pm.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,17 +19,6 @@
 
 #define PFX "s5p pm: "
 
-/* s3c_pm_check_resume_pin
- *
- * check to see if the pin is configured correctly for sleep mode, and
- * make any necessary adjustments if it is not
-*/
-
-static void s3c_pm_check_resume_pin(unsigned int pin, unsigned int irqoffs)
-{
-	/* nothing here yet */
-}
-
 /* s3c_pm_configure_extint
  *
  * configure all external interrupt pins
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/s5p-time.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/s5p-time.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/s5p-time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/s5p-time.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,448 @@
+/* linux/arch/arm/plat-s5p/s5p-time.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com/
+ *
+ * S5P - Common hr-timer 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/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/clockchips.h>
+#include <linux/platform_device.h>
+
+#include <asm/smp_twd.h>
+#include <asm/mach/time.h>
+#include <asm/mach/arch.h>
+#include <asm/mach/map.h>
+#include <asm/sched_clock.h>
+
+#include <mach/map.h>
+#include <plat/devs.h>
+#include <plat/regs-timer.h>
+#include <plat/s5p-time.h>
+
+static struct clk *tin_event;
+static struct clk *tin_source;
+static struct clk *tdiv_event;
+static struct clk *tdiv_source;
+static struct clk *timerclk;
+static struct s5p_timer_source timer_source;
+static unsigned long clock_count_per_tick;
+static void s5p_timer_resume(void);
+
+static void s5p_time_stop(enum s5p_timer_mode mode)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case S5P_PWM0:
+		tcon &= ~S3C2410_TCON_T0START;
+		break;
+
+	case S5P_PWM1:
+		tcon &= ~S3C2410_TCON_T1START;
+		break;
+
+	case S5P_PWM2:
+		tcon &= ~S3C2410_TCON_T2START;
+		break;
+
+	case S5P_PWM3:
+		tcon &= ~S3C2410_TCON_T3START;
+		break;
+
+	case S5P_PWM4:
+		tcon &= ~S3C2410_TCON_T4START;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void s5p_time_setup(enum s5p_timer_mode mode, unsigned long tcnt)
+{
+	unsigned long tcon;
+
+	tcon = __raw_readl(S3C2410_TCON);
+
+	tcnt--;
+
+	switch (mode) {
+	case S5P_PWM0:
+		tcon &= ~(0x0f << 0);
+		tcon |= S3C2410_TCON_T0MANUALUPD;
+		break;
+
+	case S5P_PWM1:
+		tcon &= ~(0x0f << 8);
+		tcon |= S3C2410_TCON_T1MANUALUPD;
+		break;
+
+	case S5P_PWM2:
+		tcon &= ~(0x0f << 12);
+		tcon |= S3C2410_TCON_T2MANUALUPD;
+		break;
+
+	case S5P_PWM3:
+		tcon &= ~(0x0f << 16);
+		tcon |= S3C2410_TCON_T3MANUALUPD;
+		break;
+
+	case S5P_PWM4:
+		tcon &= ~(0x07 << 20);
+		tcon |= S3C2410_TCON_T4MANUALUPD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+
+	__raw_writel(tcnt, S3C2410_TCNTB(mode));
+	__raw_writel(tcnt, S3C2410_TCMPB(mode));
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static void s5p_time_start(enum s5p_timer_mode mode, bool periodic)
+{
+	unsigned long tcon;
+
+	tcon  = __raw_readl(S3C2410_TCON);
+
+	switch (mode) {
+	case S5P_PWM0:
+		tcon |= S3C2410_TCON_T0START;
+		tcon &= ~S3C2410_TCON_T0MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T0RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T0RELOAD;
+		break;
+
+	case S5P_PWM1:
+		tcon |= S3C2410_TCON_T1START;
+		tcon &= ~S3C2410_TCON_T1MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T1RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T1RELOAD;
+		break;
+
+	case S5P_PWM2:
+		tcon |= S3C2410_TCON_T2START;
+		tcon &= ~S3C2410_TCON_T2MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T2RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T2RELOAD;
+		break;
+
+	case S5P_PWM3:
+		tcon |= S3C2410_TCON_T3START;
+		tcon &= ~S3C2410_TCON_T3MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T3RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T3RELOAD;
+		break;
+
+	case S5P_PWM4:
+		tcon |= S3C2410_TCON_T4START;
+		tcon &= ~S3C2410_TCON_T4MANUALUPD;
+
+		if (periodic)
+			tcon |= S3C2410_TCON_T4RELOAD;
+		else
+			tcon &= ~S3C2410_TCON_T4RELOAD;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", mode);
+		break;
+	}
+	__raw_writel(tcon, S3C2410_TCON);
+}
+
+static int s5p_set_next_event(unsigned long cycles,
+				struct clock_event_device *evt)
+{
+	s5p_time_setup(timer_source.event_id, cycles);
+	s5p_time_start(timer_source.event_id, NON_PERIODIC);
+
+	return 0;
+}
+
+static void s5p_set_mode(enum clock_event_mode mode,
+				struct clock_event_device *evt)
+{
+	s5p_time_stop(timer_source.event_id);
+
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+		s5p_time_setup(timer_source.event_id, clock_count_per_tick);
+		s5p_time_start(timer_source.event_id, PERIODIC);
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+		break;
+
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		s5p_timer_resume();
+		break;
+	}
+}
+
+static void s5p_timer_resume(void)
+{
+	/* event timer restart */
+	s5p_time_setup(timer_source.event_id, clock_count_per_tick);
+	s5p_time_start(timer_source.event_id, PERIODIC);
+
+	/* source timer restart */
+	s5p_time_setup(timer_source.source_id, TCNT_MAX);
+	s5p_time_start(timer_source.source_id, PERIODIC);
+}
+
+void __init s5p_set_timer_source(enum s5p_timer_mode event,
+				 enum s5p_timer_mode source)
+{
+	s3c_device_timer[event].dev.bus = &platform_bus_type;
+	s3c_device_timer[source].dev.bus = &platform_bus_type;
+
+	timer_source.event_id = event;
+	timer_source.source_id = source;
+}
+
+static struct clock_event_device time_event_device = {
+	.name		= "s5p_event_timer",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= s5p_set_next_event,
+	.set_mode	= s5p_set_mode,
+};
+
+static irqreturn_t s5p_clock_event_isr(int irq, void *dev_id)
+{
+	struct clock_event_device *evt = dev_id;
+
+	evt->event_handler(evt);
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction s5p_clock_event_irq = {
+	.name		= "s5p_time_irq",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= s5p_clock_event_isr,
+	.dev_id		= &time_event_device,
+};
+
+static void __init s5p_clockevent_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+	unsigned int irq_number;
+	struct clk *tscaler;
+
+	pclk = clk_get_rate(timerclk);
+
+	tscaler = clk_get_parent(tdiv_event);
+
+	clk_set_rate(tscaler, pclk / 2);
+	clk_set_rate(tdiv_event, pclk / 2);
+	clk_set_parent(tin_event, tdiv_event);
+
+	clock_rate = clk_get_rate(tin_event);
+	clock_count_per_tick = clock_rate / HZ;
+
+	clockevents_calc_mult_shift(&time_event_device,
+				    clock_rate, S5PTIMER_MIN_RANGE);
+	time_event_device.max_delta_ns =
+		clockevent_delta2ns(-1, &time_event_device);
+	time_event_device.min_delta_ns =
+		clockevent_delta2ns(1, &time_event_device);
+
+	time_event_device.cpumask = cpumask_of(0);
+	clockevents_register_device(&time_event_device);
+
+	irq_number = timer_source.event_id + IRQ_TIMER0;
+	setup_irq(irq_number, &s5p_clock_event_irq);
+}
+
+static cycle_t s5p_timer_read(struct clocksource *cs)
+{
+	unsigned long offset = 0;
+
+	switch (timer_source.source_id) {
+	case S5P_PWM0:
+	case S5P_PWM1:
+	case S5P_PWM2:
+	case S5P_PWM3:
+		offset = (timer_source.source_id * 0x0c) + 0x14;
+		break;
+
+	case S5P_PWM4:
+		offset = 0x40;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+		return 0;
+	}
+
+	return (cycle_t) ~__raw_readl(S3C_TIMERREG(offset));
+}
+
+/*
+ * Override the global weak sched_clock symbol with this
+ * local implementation which uses the clocksource to get some
+ * better resolution when scheduling the kernel. We accept that
+ * this wraps around for now, since it is just a relative time
+ * stamp. (Inspired by U300 implementation.)
+ */
+static DEFINE_CLOCK_DATA(cd);
+
+unsigned long long notrace sched_clock(void)
+{
+	u32 cyc;
+	unsigned long offset = 0;
+
+	switch (timer_source.source_id) {
+	case S5P_PWM0:
+	case S5P_PWM1:
+	case S5P_PWM2:
+	case S5P_PWM3:
+		offset = (timer_source.source_id * 0x0c) + 0x14;
+		break;
+
+	case S5P_PWM4:
+		offset = 0x40;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+		return 0;
+	}
+
+	cyc = ~__raw_readl(S3C_TIMERREG(offset));
+	return cyc_to_sched_clock(&cd, cyc, (u32)~0);
+}
+
+static void notrace s5p_update_sched_clock(void)
+{
+	u32 cyc;
+	unsigned long offset = 0;
+
+	switch (timer_source.source_id) {
+	case S5P_PWM0:
+	case S5P_PWM1:
+	case S5P_PWM2:
+	case S5P_PWM3:
+		offset = (timer_source.source_id * 0x0c) + 0x14;
+		break;
+
+	case S5P_PWM4:
+		offset = 0x40;
+		break;
+
+	default:
+		printk(KERN_ERR "Invalid Timer %d\n", timer_source.source_id);
+	}
+
+	cyc = ~__raw_readl(S3C_TIMERREG(offset));
+	update_sched_clock(&cd, cyc, (u32)~0);
+}
+
+struct clocksource time_clocksource = {
+	.name		= "s5p_clocksource_timer",
+	.rating		= 250,
+	.read		= s5p_timer_read,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static void __init s5p_clocksource_init(void)
+{
+	unsigned long pclk;
+	unsigned long clock_rate;
+
+	pclk = clk_get_rate(timerclk);
+
+	clk_set_rate(tdiv_source, pclk / 2);
+	clk_set_parent(tin_source, tdiv_source);
+
+	clock_rate = clk_get_rate(tin_source);
+
+	init_sched_clock(&cd, s5p_update_sched_clock, 32, clock_rate);
+
+	s5p_time_setup(timer_source.source_id, TCNT_MAX);
+	s5p_time_start(timer_source.source_id, PERIODIC);
+
+	if (clocksource_register_hz(&time_clocksource, clock_rate))
+		panic("%s: can't register clocksource\n", time_clocksource.name);
+}
+
+static void __init s5p_timer_resources(void)
+{
+
+	unsigned long event_id = timer_source.event_id;
+	unsigned long source_id = timer_source.source_id;
+
+	timerclk = clk_get(NULL, "timers");
+	if (IS_ERR(timerclk))
+		panic("failed to get timers clock for timer");
+
+	clk_enable(timerclk);
+
+	tin_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tin");
+	if (IS_ERR(tin_event))
+		panic("failed to get pwm-tin clock for event timer");
+
+	tdiv_event = clk_get(&s3c_device_timer[event_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_event))
+		panic("failed to get pwm-tdiv clock for event timer");
+
+	clk_enable(tin_event);
+
+	tin_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tin");
+	if (IS_ERR(tin_source))
+		panic("failed to get pwm-tin clock for source timer");
+
+	tdiv_source = clk_get(&s3c_device_timer[source_id].dev, "pwm-tdiv");
+	if (IS_ERR(tdiv_source))
+		panic("failed to get pwm-tdiv clock for source timer");
+
+	clk_enable(tin_source);
+}
+
+static void __init s5p_timer_init(void)
+{
+	s5p_timer_resources();
+	s5p_clockevent_init();
+	s5p_clocksource_init();
+}
+
+struct sys_timer s5p_timer = {
+	.init		= s5p_timer_init,
+};
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/setup-mipiphy.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/setup-mipiphy.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/setup-mipiphy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/setup-mipiphy.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ *
+ * S5P - Helper functions for MIPI-CSIS and MIPI-DSIM D-PHY control
+ *
+ * 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/io.h>
+#include <linux/spinlock.h>
+#include <mach/regs-clock.h>
+
+static int __s5p_mipi_phy_control(struct platform_device *pdev,
+				  bool on, u32 reset)
+{
+	static DEFINE_SPINLOCK(lock);
+	void __iomem *addr;
+	unsigned long flags;
+	int pid;
+	u32 cfg;
+
+	if (!pdev)
+		return -EINVAL;
+
+	pid = (pdev->id == -1) ? 0 : pdev->id;
+
+	if (pid != 0 && pid != 1)
+		return -EINVAL;
+
+	addr = S5P_MIPI_DPHY_CONTROL(pid);
+
+	spin_lock_irqsave(&lock, flags);
+
+	cfg = __raw_readl(addr);
+	cfg = on ? (cfg | reset) : (cfg & ~reset);
+	__raw_writel(cfg, addr);
+
+	if (on) {
+		cfg |= S5P_MIPI_DPHY_ENABLE;
+	} else if (!(cfg & (S5P_MIPI_DPHY_SRESETN |
+			    S5P_MIPI_DPHY_MRESETN) & ~reset)) {
+		cfg &= ~S5P_MIPI_DPHY_ENABLE;
+	}
+
+	__raw_writel(cfg, addr);
+	spin_unlock_irqrestore(&lock, flags);
+
+	return 0;
+}
+
+int s5p_csis_phy_enable(struct platform_device *pdev, bool on)
+{
+	return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN);
+}
+
+int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
+{
+	return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-s5p/sysmmu.c linux-libre-2.6.39-gnu/arch/arm/plat-s5p/sysmmu.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-s5p/sysmmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-s5p/sysmmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,280 +12,266 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 
+#include <asm/pgtable.h>
+
 #include <mach/map.h>
 #include <mach/regs-sysmmu.h>
-#include <mach/sysmmu.h>
-
-struct sysmmu_controller s5p_sysmmu_cntlrs[S5P_SYSMMU_TOTAL_IPNUM];
-
-void s5p_sysmmu_register(struct sysmmu_controller *sysmmuconp)
-{
-	unsigned int reg_mmu_ctrl;
-	unsigned int reg_mmu_status;
-	unsigned int reg_pt_base_addr;
-	unsigned int reg_int_status;
-	unsigned int reg_page_ft_addr;
+#include <plat/sysmmu.h>
 
-	reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
-	reg_mmu_ctrl = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg_mmu_status = __raw_readl(sysmmuconp->regs + S5P_MMU_STATUS);
-	reg_pt_base_addr = __raw_readl(sysmmuconp->regs + S5P_PT_BASE_ADDR);
-	reg_page_ft_addr = __raw_readl(sysmmuconp->regs + S5P_PAGE_FAULT_ADDR);
+#define CTRL_ENABLE	0x5
+#define CTRL_BLOCK	0x7
+#define CTRL_DISABLE	0x0
 
-	printk(KERN_INFO "%s: ips:%s\n", __func__, sysmmuconp->name);
-	printk(KERN_INFO "%s: MMU_CTRL:0x%X, ", __func__, reg_mmu_ctrl);
-	printk(KERN_INFO "MMU_STATUS:0x%X, PT_BASE_ADDR:0x%X\n", reg_mmu_status, reg_pt_base_addr);
-	printk(KERN_INFO "%s: INT_STATUS:0x%X, PAGE_FAULT_ADDR:0x%X\n", __func__, reg_int_status, reg_page_ft_addr);
+static struct device *dev;
 
-	switch (reg_int_status & 0xFF) {
-	case 0x1:
-		printk(KERN_INFO "%s: Page fault\n", __func__);
-		printk(KERN_INFO "%s: Virtual address causing last page fault or bus error : 0x%x\n", __func__ , reg_page_ft_addr);
-		break;
-	case 0x2:
-		printk(KERN_INFO "%s: AR multi-hit fault\n", __func__);
-		break;
-	case 0x4:
-		printk(KERN_INFO "%s: AW multi-hit fault\n", __func__);
-		break;
-	case 0x8:
-		printk(KERN_INFO "%s: Bus error\n", __func__);
-		break;
-	case 0x10:
-		printk(KERN_INFO "%s: AR Security protection fault\n", __func__);
-		break;
-	case 0x20:
-		printk(KERN_INFO "%s: AR Access protection fault\n", __func__);
-		break;
-	case 0x40:
-		printk(KERN_INFO "%s: AW Security protection fault\n", __func__);
-		break;
-	case 0x80:
-		printk(KERN_INFO "%s: AW Access protection fault\n", __func__);
-		break;
-	}
-}
+static unsigned short fault_reg_offset[SYSMMU_FAULTS_NUM] = {
+	S5P_PAGE_FAULT_ADDR,
+	S5P_AR_FAULT_ADDR,
+	S5P_AW_FAULT_ADDR,
+	S5P_DEFAULT_SLAVE_ADDR,
+	S5P_AR_FAULT_ADDR,
+	S5P_AR_FAULT_ADDR,
+	S5P_AW_FAULT_ADDR,
+	S5P_AW_FAULT_ADDR
+};
 
-static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
-{
-	unsigned int i;
-	unsigned int reg_int_status;
-	struct sysmmu_controller *sysmmuconp;
+static char *sysmmu_fault_name[SYSMMU_FAULTS_NUM] = {
+	"PAGE FAULT",
+	"AR MULTI-HIT FAULT",
+	"AW MULTI-HIT FAULT",
+	"BUS ERROR",
+	"AR SECURITY PROTECTION FAULT",
+	"AR ACCESS PROTECTION FAULT",
+	"AW SECURITY PROTECTION FAULT",
+	"AW ACCESS PROTECTION FAULT"
+};
 
-	for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
-		sysmmuconp = &s5p_sysmmu_cntlrs[i];
+static int (*fault_handlers[S5P_SYSMMU_TOTAL_IPNUM])(
+		enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+		unsigned long pgtable_base,
+		unsigned long fault_addr);
 
-		if (sysmmuconp->enable == true) {
-			reg_int_status = __raw_readl(sysmmuconp->regs + S5P_INT_STATUS);
+/*
+ * If adjacent 2 bits are true, the system MMU is enabled.
+ * The system MMU is disabled, otherwise.
+ */
+static unsigned long sysmmu_states;
 
-			if (reg_int_status & 0xFF)
-				s5p_sysmmu_register(sysmmuconp);
-		}
-	}
-	return IRQ_HANDLED;
+static inline void set_sysmmu_active(sysmmu_ips ips)
+{
+	sysmmu_states |= 3 << (ips * 2);
 }
 
-int s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
+static inline void set_sysmmu_inactive(sysmmu_ips ips)
 {
-	struct sysmmu_controller *sysmmuconp = NULL;
-
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
-	}
+	sysmmu_states &= ~(3 << (ips * 2));
+}
 
-	/* Set sysmmu page table base address */
-	__raw_writel(pgd, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+static inline int is_sysmmu_active(sysmmu_ips ips)
+{
+	return sysmmu_states & (3 << (ips * 2));
+}
 
-	if (s5p_sysmmu_tlb_invalidate(ips) != 0)
-		printk(KERN_ERR "failed s5p_sysmmu_tlb_invalidate\n");
+static void __iomem *sysmmusfrs[S5P_SYSMMU_TOTAL_IPNUM];
 
-	return 0;
+static inline void sysmmu_block(sysmmu_ips ips)
+{
+	__raw_writel(CTRL_BLOCK, sysmmusfrs[ips] + S5P_MMU_CTRL);
+	dev_dbg(dev, "%s is blocked.\n", sysmmu_ips_name[ips]);
 }
 
-static int s5p_sysmmu_set_tablebase(sysmmu_ips ips)
+static inline void sysmmu_unblock(sysmmu_ips ips)
 {
-	unsigned int pg;
-	struct sysmmu_controller *sysmmuconp;
+	__raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
+	dev_dbg(dev, "%s is unblocked.\n", sysmmu_ips_name[ips]);
+}
 
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+static inline void __sysmmu_tlb_invalidate(sysmmu_ips ips)
+{
+	__raw_writel(0x1, sysmmusfrs[ips] + S5P_MMU_FLUSH);
+	dev_dbg(dev, "TLB of %s is invalidated.\n", sysmmu_ips_name[ips]);
+}
 
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
+static inline void __sysmmu_set_ptbase(sysmmu_ips ips, unsigned long pgd)
+{
+	if (unlikely(pgd == 0)) {
+		pgd = (unsigned long)ZERO_PAGE(0);
+		__raw_writel(0x20, sysmmusfrs[ips] + S5P_MMU_CFG); /* 4KB LV1 */
+	} else {
+		__raw_writel(0x0, sysmmusfrs[ips] + S5P_MMU_CFG); /* 16KB LV1 */
 	}
 
-	__asm__("mrc	p15, 0, %0, c2, c0, 0"	\
-		: "=r" (pg) : : "cc");		\
-		pg &= ~0x3fff;
-
-	printk(KERN_INFO "%s: CP15 TTBR0 : 0x%x\n", __func__, pg);
+	__raw_writel(pgd, sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
 
-	/* Set sysmmu page table base address */
-	__raw_writel(pg, sysmmuconp->regs + S5P_PT_BASE_ADDR);
+	dev_dbg(dev, "Page table base of %s is initialized with 0x%08lX.\n",
+						sysmmu_ips_name[ips], pgd);
+	__sysmmu_tlb_invalidate(ips);
+}
 
-	return 0;
+void sysmmu_set_fault_handler(sysmmu_ips ips,
+			int (*handler)(enum S5P_SYSMMU_INTERRUPT_TYPE itype,
+					unsigned long pgtable_base,
+					unsigned long fault_addr))
+{
+	BUG_ON(!((ips >= SYSMMU_MDMA) && (ips < S5P_SYSMMU_TOTAL_IPNUM)));
+	fault_handlers[ips] = handler;
 }
 
-int s5p_sysmmu_enable(sysmmu_ips ips)
+static irqreturn_t s5p_sysmmu_irq(int irq, void *dev_id)
 {
-	unsigned int reg;
+	/* SYSMMU is in blocked when interrupt occurred. */
+	unsigned long base = 0;
+	sysmmu_ips ips = (sysmmu_ips)dev_id;
+	enum S5P_SYSMMU_INTERRUPT_TYPE itype;
 
-	struct sysmmu_controller *sysmmuconp;
+	itype = (enum S5P_SYSMMU_INTERRUPT_TYPE)
+		__ffs(__raw_readl(sysmmusfrs[ips] + S5P_INT_STATUS));
 
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
+	BUG_ON(!((itype >= 0) && (itype < 8)));
 
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
-	}
+	dev_alert(dev, "%s occurred by %s.\n", sysmmu_fault_name[itype],
+							sysmmu_ips_name[ips]);
 
-	s5p_sysmmu_set_tablebase(ips);
+	if (fault_handlers[ips]) {
+		unsigned long addr;
 
-	/* replacement policy : LRU */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
-	reg |= 0x1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
+		base = __raw_readl(sysmmusfrs[ips] + S5P_PT_BASE_ADDR);
+		addr = __raw_readl(sysmmusfrs[ips] + fault_reg_offset[itype]);
 
-	/* Enable interrupt, Enable MMU */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg |= (0x1 << 2) | (0x1 << 0);
+		if (fault_handlers[ips](itype, base, addr)) {
+			__raw_writel(1 << itype,
+					sysmmusfrs[ips] + S5P_INT_CLEAR);
+			dev_notice(dev, "%s from %s is resolved."
+					" Retrying translation.\n",
+				sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
+		} else {
+			base = 0;
+		}
+	}
 
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+	sysmmu_unblock(ips);
 
-	sysmmuconp->enable = true;
+	if (!base)
+		dev_notice(dev, "%s from %s is not handled.\n",
+			sysmmu_fault_name[itype], sysmmu_ips_name[ips]);
 
-	return 0;
+	return IRQ_HANDLED;
 }
 
-int s5p_sysmmu_disable(sysmmu_ips ips)
+void s5p_sysmmu_set_tablebase_pgd(sysmmu_ips ips, unsigned long pgd)
 {
-	unsigned int reg;
-
-	struct sysmmu_controller *sysmmuconp = NULL;
-
-	if (ips > S5P_SYSMMU_TOTAL_IPNUM)
-		printk(KERN_ERR "failed to get ips parameter\n");
-
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
+	if (is_sysmmu_active(ips)) {
+		sysmmu_block(ips);
+		__sysmmu_set_ptbase(ips, pgd);
+		sysmmu_unblock(ips);
+	} else {
+		dev_dbg(dev, "%s is disabled. "
+			"Skipping initializing page table base.\n",
+						sysmmu_ips_name[ips]);
 	}
+}
 
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CFG);
-
-	/* replacement policy : LRU */
-	reg |= 0x1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CFG);
-
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
+void s5p_sysmmu_enable(sysmmu_ips ips, unsigned long pgd)
+{
+	if (!is_sysmmu_active(ips)) {
+		sysmmu_clk_enable(ips);
 
-	/* Disable MMU */
-	reg &= ~0x1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
+		__sysmmu_set_ptbase(ips, pgd);
 
-	sysmmuconp->enable = false;
+		__raw_writel(CTRL_ENABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
 
-	return 0;
+		set_sysmmu_active(ips);
+		dev_dbg(dev, "%s is enabled.\n", sysmmu_ips_name[ips]);
+	} else {
+		dev_dbg(dev, "%s is already enabled.\n", sysmmu_ips_name[ips]);
+	}
 }
 
-int s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
+void s5p_sysmmu_disable(sysmmu_ips ips)
 {
-	unsigned int reg;
-	struct sysmmu_controller *sysmmuconp = NULL;
-
-	sysmmuconp = &s5p_sysmmu_cntlrs[ips];
-
-	if (sysmmuconp == NULL) {
-		printk(KERN_ERR "failed to get ip's sysmmu info\n");
-		return 1;
+	if (is_sysmmu_active(ips)) {
+		__raw_writel(CTRL_DISABLE, sysmmusfrs[ips] + S5P_MMU_CTRL);
+		set_sysmmu_inactive(ips);
+		sysmmu_clk_disable(ips);
+		dev_dbg(dev, "%s is disabled.\n", sysmmu_ips_name[ips]);
+	} else {
+		dev_dbg(dev, "%s is already disabled.\n", sysmmu_ips_name[ips]);
 	}
+}
 
-	/* set Block MMU for flush TLB */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg |= 0x1 << 1;
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
-	/* flush all TLB entry */
-	__raw_writel(0x1, sysmmuconp->regs + S5P_MMU_FLUSH);
-
-	/* set Un-block MMU after flush TLB */
-	reg = __raw_readl(sysmmuconp->regs + S5P_MMU_CTRL);
-	reg &= ~(0x1 << 1);
-	__raw_writel(reg, sysmmuconp->regs + S5P_MMU_CTRL);
-
-	return 0;
+void s5p_sysmmu_tlb_invalidate(sysmmu_ips ips)
+{
+	if (is_sysmmu_active(ips)) {
+		sysmmu_block(ips);
+		__sysmmu_tlb_invalidate(ips);
+		sysmmu_unblock(ips);
+	} else {
+		dev_dbg(dev, "%s is disabled. "
+			"Skipping invalidating TLB.\n", sysmmu_ips_name[ips]);
+	}
 }
 
 static int s5p_sysmmu_probe(struct platform_device *pdev)
 {
-	int i;
-	int ret;
-	struct resource *res;
-	struct sysmmu_controller *sysmmuconp;
-	sysmmu_ips ips;
+	int i, ret;
+	struct resource *res, *mem;
+
+	dev = &pdev->dev;
 
 	for (i = 0; i < S5P_SYSMMU_TOTAL_IPNUM; i++) {
-		sysmmuconp = &s5p_sysmmu_cntlrs[i];
-		if (sysmmuconp == NULL) {
-			printk(KERN_ERR "failed to get ip's sysmmu info\n");
-			ret = -ENOENT;
-			goto err_res;
-		}
+		int irq;
 
-		sysmmuconp->name = sysmmu_ips_name[i];
+		sysmmu_clk_init(dev, i);
+		sysmmu_clk_disable(i);
 
 		res = platform_get_resource(pdev, IORESOURCE_MEM, i);
 		if (!res) {
-			printk(KERN_ERR "failed to get sysmmu resource\n");
+			dev_err(dev, "Failed to get the resource of %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENODEV;
 			goto err_res;
 		}
 
-		sysmmuconp->mem = request_mem_region(res->start,
+		mem = request_mem_region(res->start,
 				((res->end) - (res->start)) + 1, pdev->name);
-		if (!sysmmuconp->mem) {
-			pr_err("failed to request sysmmu memory region\n");
+		if (!mem) {
+			dev_err(dev, "Failed to request the memory region of %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -EBUSY;
 			goto err_res;
 		}
 
-		sysmmuconp->regs = ioremap(res->start, res->end - res->start + 1);
-		if (!sysmmuconp->regs) {
-			pr_err("failed to sysmmu ioremap\n");
+		sysmmusfrs[i] = ioremap(res->start, res->end - res->start + 1);
+		if (!sysmmusfrs[i]) {
+			dev_err(dev, "Failed to ioremap() for %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENXIO;
 			goto err_reg;
 		}
 
-		sysmmuconp->irq = platform_get_irq(pdev, i);
-		if (sysmmuconp->irq <= 0) {
-			pr_err("failed to get sysmmu irq resource\n");
+		irq = platform_get_irq(pdev, i);
+		if (irq <= 0) {
+			dev_err(dev, "Failed to get the IRQ resource of %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENOENT;
 			goto err_map;
 		}
 
-		ret = request_irq(sysmmuconp->irq, s5p_sysmmu_irq, IRQF_DISABLED, pdev->name, sysmmuconp);
-		if (ret) {
-			pr_err("failed to request irq\n");
+		if (request_irq(irq, s5p_sysmmu_irq, IRQF_DISABLED,
+						pdev->name, (void *)i)) {
+			dev_err(dev, "Failed to request IRQ for %s.\n",
+							sysmmu_ips_name[i]);
 			ret = -ENOENT;
 			goto err_map;
 		}
-
-		ips = (sysmmu_ips)i;
-
-		sysmmuconp->ips = ips;
 	}
 
 	return 0;
 
-err_reg:
-	release_mem_region((resource_size_t)sysmmuconp->mem, (resource_size_t)((res->end) - (res->start) + 1));
 err_map:
-	iounmap(sysmmuconp->regs);
+	iounmap(sysmmusfrs[i]);
+err_reg:
+	release_mem_region(mem->start, resource_size(mem));
 err_res:
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/dev-pwm.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/dev-pwm.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/dev-pwm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/dev-pwm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,53 @@
+/* linux/arch/arm/plat-samsung/dev-pwm.c
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
+ * Copyright (c) 2007 Ben Dooks
+ * Copyright (c) 2008 Simtec Electronics
+ *	Ben Dooks <ben@simtec.co.uk>, <ben-linux@fluff.org>
+ *
+ * S3C series device definition for the PWM timer
+ *
+ * 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 <mach/irqs.h>
+
+#include <plat/devs.h>
+
+#define TIMER_RESOURCE_SIZE (1)
+
+#define TIMER_RESOURCE(_tmr, _irq)			\
+	(struct resource [TIMER_RESOURCE_SIZE]) {	\
+		[0] = {					\
+			.start	= _irq,			\
+			.end	= _irq,			\
+			.flags	= IORESOURCE_IRQ	\
+		}					\
+	}
+
+#define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
+	.name		= "s3c24xx-pwm",		\
+	.id		= _tmr_no,			\
+	.num_resources	= TIMER_RESOURCE_SIZE,		\
+	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
+
+/*
+ * since we already have an static mapping for the timer,
+ * we do not bother setting any IO resource for the base.
+ */
+
+struct platform_device s3c_device_timer[] = {
+	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
+	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
+	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
+	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
+	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
+};
+EXPORT_SYMBOL(s3c_device_timer);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/clock.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/clock.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
  * @set_parent: set the clock's parent, see clk_set_parent().
  *
  * Group the common clock implementations together so that we
- * don't have to keep setting the same fiels again. We leave
+ * don't have to keep setting the same fields again. We leave
  * enable in struct clk.
  *
  * Adding an extra layer of indirection into the process should
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/cpu.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/cpu.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/cpu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/cpu.h	2011-05-19 00:06:34.000000000 -0400
@@ -82,6 +82,7 @@
 extern struct sysdev_class s5p64x0_sysclass;
 extern struct sysdev_class s5p6442_sysclass;
 extern struct sysdev_class s5pv210_sysclass;
+extern struct sysdev_class exynos4_sysclass;
 
 extern void (*s5pc1xx_idle)(void);
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/devs.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/devs.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/devs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/devs.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,8 @@
 /* arch/arm/plat-samsung/include/plat/devs.h
  *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
+ *
  * Copyright (c) 2004 Simtec Electronics
  * Ben Dooks <ben@simtec.co.uk>
  *
@@ -96,15 +99,16 @@
 extern struct platform_device s5pv210_device_iis2;
 extern struct platform_device s5pv210_device_spdif;
 
-extern struct platform_device s5pv310_device_ac97;
-extern struct platform_device s5pv310_device_pcm0;
-extern struct platform_device s5pv310_device_pcm1;
-extern struct platform_device s5pv310_device_pcm2;
-extern struct platform_device s5pv310_device_i2s0;
-extern struct platform_device s5pv310_device_i2s1;
-extern struct platform_device s5pv310_device_i2s2;
-extern struct platform_device s5pv310_device_spdif;
-extern struct platform_device s5pv310_device_pd[];
+extern struct platform_device exynos4_device_ac97;
+extern struct platform_device exynos4_device_pcm0;
+extern struct platform_device exynos4_device_pcm1;
+extern struct platform_device exynos4_device_pcm2;
+extern struct platform_device exynos4_device_i2s0;
+extern struct platform_device exynos4_device_i2s1;
+extern struct platform_device exynos4_device_i2s2;
+extern struct platform_device exynos4_device_spdif;
+extern struct platform_device exynos4_device_pd[];
+extern struct platform_device exynos4_device_ahci;
 
 extern struct platform_device s5p6442_device_pcm0;
 extern struct platform_device s5p6442_device_pcm1;
@@ -133,11 +137,12 @@
 extern struct platform_device s5p_device_fimc0;
 extern struct platform_device s5p_device_fimc1;
 extern struct platform_device s5p_device_fimc2;
+extern struct platform_device s5p_device_fimc3;
 
 extern struct platform_device s5p_device_mipi_csis0;
 extern struct platform_device s5p_device_mipi_csis1;
 
-extern struct platform_device s5pv310_device_sysmmu;
+extern struct platform_device exynos4_device_sysmmu;
 
 /* s3c2440 specific devices */
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/fimc-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,11 @@
 		s5p_device_fimc2.name = name;
 		break;
 #endif
+#ifdef CONFIG_S5P_DEV_FIMC3
+	case 3:
+		s5p_device_fimc3.name = name;
+		break;
+#endif
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg.h	2011-05-19 00:06:34.000000000 -0400
@@ -125,7 +125,7 @@
  *
  * These values control the state of the weak pull-{up,down} resistors
  * available on most pins on the S3C series. Not all chips support both
- * up or down settings, and it may be dependant on the chip that is being
+ * up or down settings, and it may be dependent on the chip that is being
  * used to whether the particular mode is available.
  */
 #define S3C_GPIO_PULL_NONE	((__force s3c_gpio_pull_t)0x00)
@@ -138,7 +138,7 @@
  * @pull: The configuration for the pull resistor.
  *
  * This function sets the state of the pull-{up,down} resistor for the
- * specified pin. It will return 0 if successfull, or a negative error
+ * specified pin. It will return 0 if successful, or a negative error
  * code if the pin cannot support the requested pull setting.
  *
  * @pull is one of S3C_GPIO_PULL_NONE, S3C_GPIO_PULL_DOWN or S3C_GPIO_PULL_UP.
@@ -202,7 +202,7 @@
  * @drvstr: The new value of the driver strength
  *
  * This function sets the driver strength value for the specified pin.
- * It will return 0 if successfull, or a negative error code if the pin
+ * It will return 0 if successful, or a negative error code if the pin
  * cannot support the requested setting.
 */
 extern int s5p_gpio_set_drvstr(unsigned int pin, s5p_gpio_drvstr_t drvstr);
@@ -225,4 +225,20 @@
  */
 extern int s5p_register_gpio_interrupt(int pin);
 
+/** s5p_register_gpioint_bank() - add gpio bank for further gpio interrupt
+ * registration (see s5p_register_gpio_interrupt function)
+ * @chain_irq: chained irq number for the gpio int handler for this bank
+ * @start: start gpio group number of this bank
+ * @nr_groups: number of gpio groups handled by this bank
+ *
+ * This functions registers initial information about gpio banks that
+ * can be later used by the s5p_register_gpio_interrupt() function to
+ * enable support for gpio interrupt for particular gpio group.
+ */
+#ifdef CONFIG_S5P_GPIO_INT
+extern int s5p_register_gpioint_bank(int chain_irq, int start, int nr_groups);
+#else
+#define s5p_register_gpioint_bank(chain_irq, start, nr_groups) do { } while (0)
+#endif
+
 #endif /* __PLAT_GPIO_CFG_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/gpio-cfg-helpers.h	2011-05-19 00:06:34.000000000 -0400
@@ -114,7 +114,7 @@
  * of control per GPIO, generally in the form of:
  *	0000 = Input
  *	0001 = Output
- *	others = Special functions (dependant on bank)
+ *	others = Special functions (dependent on bank)
  *
  * Note, since the code to deal with the case where there are two control
  * registers instead of one, we do not have a separate set of functions for
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/gpio-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -108,7 +108,7 @@
  * of control per GPIO, generally in the form of:
  * 0000 = Input
  * 0001 = Output
- * others = Special functions (dependant on bank)
+ * others = Special functions (dependent on bank)
  *
  * Note, since the code to deal with the case where there are two control
  * registers instead of one, we do not have a separate set of function
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/pd.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/pd.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/pd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/pd.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /* linux/arch/arm/plat-samsung/include/plat/pd.h
  *
- * Copyright (c) 2010 Samsung Electronics Co., Ltd.
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *		http://www.samsung.com
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,7 +17,7 @@
 	void __iomem *base;
 };
 
-enum s5pv310_pd_block {
+enum exynos4_pd_block {
 	PD_MFC,
 	PD_G3D,
 	PD_LCD0,
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/pm.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/pm.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/pm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/pm.h	2011-05-19 00:06:34.000000000 -0400
@@ -52,13 +52,11 @@
 
 /* from sleep.S */
 
-extern int  s3c_cpu_save(unsigned long *saveblk);
+extern int  s3c_cpu_save(unsigned long *saveblk, long);
 extern void s3c_cpu_resume(void);
 
 extern void s3c2410_cpu_suspend(void);
 
-extern unsigned long s3c_sleep_save_phys;
-
 /* sleep save info */
 
 /**
@@ -181,13 +179,5 @@
  */
 extern void s3c_pm_save_gpios(void);
 
-/**
- * s3c_pm_cb_flushcache - callback for assembly code
- *
- * Callback to issue flush_cache_all() as this call is
- * not a directly callable object.
- */
-extern void s3c_pm_cb_flushcache(void);
-
 extern void s3c_pm_save_core(void);
 extern void s3c_pm_restore_core(void);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/sdhci.h linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/sdhci.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/include/plat/sdhci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/include/plat/sdhci.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,7 @@
-/* linux/arch/arm/plat-s3c/include/plat/sdhci.h
+/* linux/arch/arm/plat-samsung/include/plat/sdhci.h
+ *
+ * Copyright (c) 2011 Samsung Electronics Co., Ltd.
+ *		http://www.samsung.com
  *
  * Copyright 2008 Openmoko, Inc.
  * Copyright 2008 Simtec Electronics
@@ -54,7 +57,7 @@
  * @cfg_gpio: Configure the GPIO for a specific card bit-width
  * @cfg_card: Configure the interface for a specific card and speed. This
  *            is necessary the controllers and/or GPIO blocks require the
- *	      changing of driver-strength and other controls dependant on
+ *	      changing of driver-strength and other controls dependent on
  *	      the card and speed of operation.
  *
  * Initialisation data specific to either the machine or the platform
@@ -105,7 +108,7 @@
 extern struct s3c_sdhci_platdata s3c_hsmmc2_def_platdata;
 extern struct s3c_sdhci_platdata s3c_hsmmc3_def_platdata;
 
-/* Helper function availablity */
+/* Helper function availability */
 
 extern void s3c2416_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
 extern void s3c2416_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
@@ -119,10 +122,10 @@
 extern void s5pv210_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
 extern void s5pv210_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
 extern void s5pv210_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
-extern void s5pv310_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci0_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci1_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci2_cfg_gpio(struct platform_device *, int w);
+extern void exynos4_setup_sdhci3_cfg_gpio(struct platform_device *, int w);
 
 /* S3C2416 SDHCI setup */
 
@@ -334,57 +337,57 @@
 
 #endif /* CONFIG_S5PV210_SETUP_SDHCI */
 
-/* S5PV310 SDHCI setup */
-#ifdef CONFIG_S5PV310_SETUP_SDHCI
-extern char *s5pv310_hsmmc_clksrcs[4];
+/* EXYNOS4 SDHCI setup */
+#ifdef CONFIG_EXYNOS4_SETUP_SDHCI
+extern char *exynos4_hsmmc_clksrcs[4];
 
-extern void s5pv310_setup_sdhci_cfg_card(struct platform_device *dev,
+extern void exynos4_setup_sdhci_cfg_card(struct platform_device *dev,
 					   void __iomem *r,
 					   struct mmc_ios *ios,
 					   struct mmc_card *card);
 
-static inline void s5pv310_default_sdhci0(void)
+static inline void exynos4_default_sdhci0(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC
-	s3c_hsmmc0_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc0_def_platdata.cfg_gpio = s5pv310_setup_sdhci0_cfg_gpio;
-	s3c_hsmmc0_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc0_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc0_def_platdata.cfg_gpio = exynos4_setup_sdhci0_cfg_gpio;
+	s3c_hsmmc0_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
-static inline void s5pv310_default_sdhci1(void)
+static inline void exynos4_default_sdhci1(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC1
-	s3c_hsmmc1_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc1_def_platdata.cfg_gpio = s5pv310_setup_sdhci1_cfg_gpio;
-	s3c_hsmmc1_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc1_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc1_def_platdata.cfg_gpio = exynos4_setup_sdhci1_cfg_gpio;
+	s3c_hsmmc1_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
-static inline void s5pv310_default_sdhci2(void)
+static inline void exynos4_default_sdhci2(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC2
-	s3c_hsmmc2_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc2_def_platdata.cfg_gpio = s5pv310_setup_sdhci2_cfg_gpio;
-	s3c_hsmmc2_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc2_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc2_def_platdata.cfg_gpio = exynos4_setup_sdhci2_cfg_gpio;
+	s3c_hsmmc2_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
-static inline void s5pv310_default_sdhci3(void)
+static inline void exynos4_default_sdhci3(void)
 {
 #ifdef CONFIG_S3C_DEV_HSMMC3
-	s3c_hsmmc3_def_platdata.clocks = s5pv310_hsmmc_clksrcs;
-	s3c_hsmmc3_def_platdata.cfg_gpio = s5pv310_setup_sdhci3_cfg_gpio;
-	s3c_hsmmc3_def_platdata.cfg_card = s5pv310_setup_sdhci_cfg_card;
+	s3c_hsmmc3_def_platdata.clocks = exynos4_hsmmc_clksrcs;
+	s3c_hsmmc3_def_platdata.cfg_gpio = exynos4_setup_sdhci3_cfg_gpio;
+	s3c_hsmmc3_def_platdata.cfg_card = exynos4_setup_sdhci_cfg_card;
 #endif
 }
 
 #else
-static inline void s5pv310_default_sdhci0(void) { }
-static inline void s5pv310_default_sdhci1(void) { }
-static inline void s5pv310_default_sdhci2(void) { }
-static inline void s5pv310_default_sdhci3(void) { }
+static inline void exynos4_default_sdhci0(void) { }
+static inline void exynos4_default_sdhci1(void) { }
+static inline void exynos4_default_sdhci2(void) { }
+static inline void exynos4_default_sdhci3(void) { }
 
-#endif /* CONFIG_S5PV310_SETUP_SDHCI */
+#endif /* CONFIG_EXYNOS4_SETUP_SDHCI */
 
 #endif /* __PLAT_S3C_SDHCI_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/init.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/init.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 						unsigned int count)
 {
 	for (; count != 0; count--, tab++) {
-		if ((idcode & tab->idmask) == tab->idcode)
+		if ((idcode & tab->idmask) == (tab->idcode & tab->idmask))
 			return tab;
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/irq-uart.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/irq-uart.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/irq-uart.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/irq-uart.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,7 +107,6 @@
 
 static void __init s3c_init_uart_irq(struct s3c_uart_irq *uirq)
 {
-	struct irq_desc *desc = irq_to_desc(uirq->parent_irq);
 	void __iomem *reg_base = uirq->regs;
 	unsigned int irq;
 	int offs;
@@ -118,14 +117,13 @@
 	for (offs = 0; offs < 3; offs++) {
 		irq = uirq->base_irq + offs;
 
-		set_irq_chip(irq, &s3c_irq_uart);
-		set_irq_chip_data(irq, uirq);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &s3c_irq_uart, handle_level_irq);
+		irq_set_chip_data(irq, uirq);
 		set_irq_flags(irq, IRQF_VALID);
 	}
 
-	desc->irq_data.handler_data = uirq;
-	set_irq_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
+	irq_set_handler_data(uirq->parent_irq, uirq);
+	irq_set_chained_handler(uirq->parent_irq, s3c_irq_demux_uart);
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/irq-vic-timer.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/irq-vic-timer.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/irq-vic-timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/irq-vic-timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -77,14 +77,11 @@
 void __init s3c_init_vic_timer_irq(unsigned int parent_irq,
 				   unsigned int timer_irq)
 {
-	struct irq_desc *desc = irq_to_desc(parent_irq);
 
-	set_irq_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
+	irq_set_chained_handler(parent_irq, s3c_irq_demux_vic_timer);
+	irq_set_handler_data(parent_irq, (void *)timer_irq);
 
-	set_irq_chip(timer_irq, &s3c_irq_timer);
-	set_irq_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0)));
-	set_irq_handler(timer_irq, handle_level_irq);
+	irq_set_chip_and_handler(timer_irq, &s3c_irq_timer, handle_level_irq);
+	irq_set_chip_data(timer_irq, (void *)(1 << (timer_irq - IRQ_TIMER0)));
 	set_irq_flags(timer_irq, IRQF_VALID);
-
-	desc->irq_data.handler_data = (void *)timer_irq;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/Kconfig linux-libre-2.6.39-gnu/arch/arm/plat-samsung/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -273,6 +273,19 @@
 	help
 	  Compile in platform device definitions for keypad
 
+config SAMSUNG_DEV_PWM
+	bool
+	default y if ARCH_S3C2410
+	help
+	  Compile in platform device definition for PWM Timer
+
+config S3C24XX_PWM
+	bool "PWM device support"
+	select HAVE_PWM
+	help
+	  Support for exporting the PWM timer blocks via the pwm device
+	  system
+
 # DMA
 
 config S3C_DMA
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/Makefile linux-libre-2.6.39-gnu/arch/arm/plat-samsung/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -59,6 +59,7 @@
 obj-$(CONFIG_SAMSUNG_DEV_IDE)	+= dev-ide.o
 obj-$(CONFIG_SAMSUNG_DEV_TS)	+= dev-ts.o
 obj-$(CONFIG_SAMSUNG_DEV_KEYPAD)	+= dev-keypad.o
+obj-$(CONFIG_SAMSUNG_DEV_PWM)	+= dev-pwm.o
 
 # DMA support
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/pm.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/pm.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,8 +214,9 @@
  *
  * print any IRQs asserted at resume time (ie, we woke from)
 */
-static void s3c_pm_show_resume_irqs(int start, unsigned long which,
-				    unsigned long mask)
+static void __maybe_unused s3c_pm_show_resume_irqs(int start,
+						   unsigned long which,
+						   unsigned long mask)
 {
 	int i;
 
@@ -241,8 +242,6 @@
 
 static int s3c_pm_enter(suspend_state_t state)
 {
-	static unsigned long regs_save[16];
-
 	/* ensure the debug is initialised (if enabled) */
 
 	s3c_pm_debug_init();
@@ -266,12 +265,6 @@
 		return -EINVAL;
 	}
 
-	/* store the physical address of the register recovery block */
-
-	s3c_sleep_save_phys = virt_to_phys(regs_save);
-
-	S3C_PMDBG("s3c_sleep_save_phys=0x%08lx\n", s3c_sleep_save_phys);
-
 	/* save all necessary core registers not covered by the drivers */
 
 	s3c_pm_save_gpios();
@@ -305,7 +298,7 @@
 	 * we resume as it saves its own register state and restores it
 	 * during the resume.  */
 
-	s3c_cpu_save(regs_save);
+	s3c_cpu_save(0, PLAT_PHYS_OFFSET - PAGE_OFFSET);
 
 	/* restore the cpu state using the kernel's cpu init code. */
 
@@ -336,12 +329,6 @@
 	return 0;
 }
 
-/* callback from assembly code */
-void s3c_pm_cb_flushcache(void)
-{
-	flush_cache_all();
-}
-
 static int s3c_pm_prepare(void)
 {
 	/* prepare check area if configured */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/pm-check.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/pm-check.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/pm-check.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/pm-check.c	2011-05-19 00:06:34.000000000 -0400
@@ -164,7 +164,6 @@
  */
 static u32 *s3c_pm_runcheck(struct resource *res, u32 *val)
 {
-	void *save_at = phys_to_virt(s3c_sleep_save_phys);
 	unsigned long addr;
 	unsigned long left;
 	void *stkpage;
@@ -192,11 +191,6 @@
 			goto skip_check;
 		}
 
-		if (in_region(ptr, left, save_at, 32*4 )) {
-			S3C_PMDBG("skipping %08lx, has save block in\n", addr);
-			goto skip_check;
-		}
-
 		/* calculate and check the checksum */
 
 		calc = crc32_le(~0, ptr, left);
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/pwm.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/pwm.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/pwm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/pwm.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,10 +20,8 @@
 #include <linux/io.h>
 #include <linux/pwm.h>
 
-#include <mach/irqs.h>
 #include <mach/map.h>
 
-#include <plat/devs.h>
 #include <plat/regs-timer.h>
 
 struct pwm_device {
@@ -47,37 +45,6 @@
 
 static struct clk *clk_scaler[2];
 
-/* Standard setup for a timer block. */
-
-#define TIMER_RESOURCE_SIZE (1)
-
-#define TIMER_RESOURCE(_tmr, _irq)			\
-	(struct resource [TIMER_RESOURCE_SIZE]) {	\
-		[0] = {					\
-			.start	= _irq,			\
-			.end	= _irq,			\
-			.flags	= IORESOURCE_IRQ	\
-		}					\
-	}
-
-#define DEFINE_S3C_TIMER(_tmr_no, _irq)			\
-	.name		= "s3c24xx-pwm",		\
-	.id		= _tmr_no,			\
-	.num_resources	= TIMER_RESOURCE_SIZE,		\
-	.resource	= TIMER_RESOURCE(_tmr_no, _irq),	\
-
-/* since we already have an static mapping for the timer, we do not
- * bother setting any IO resource for the base.
- */
-
-struct platform_device s3c_device_timer[] = {
-	[0] = { DEFINE_S3C_TIMER(0, IRQ_TIMER0) },
-	[1] = { DEFINE_S3C_TIMER(1, IRQ_TIMER1) },
-	[2] = { DEFINE_S3C_TIMER(2, IRQ_TIMER2) },
-	[3] = { DEFINE_S3C_TIMER(3, IRQ_TIMER3) },
-	[4] = { DEFINE_S3C_TIMER(4, IRQ_TIMER4) },
-};
-
 static inline int pwm_is_tdiv(struct pwm_device *pwm)
 {
 	return clk_get_parent(pwm->clk) == pwm->clk_div;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/s3c-pl330.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/s3c-pl330.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/s3c-pl330.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/s3c-pl330.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,7 +68,7 @@
  * @req: Two requests to communicate with the PL330 engine.
  * @callback_fn: Callback function to the client.
  * @rqcfg: Channel configuration for the xfers.
- * @xfer_head: Pointer to the xfer to be next excecuted.
+ * @xfer_head: Pointer to the xfer to be next executed.
  * @dmac: Pointer to the DMAC that manages this channel, NULL if the
  * 	channel is available to be acquired.
  * @client: Client of this channel. NULL if the
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-samsung/wakeup-mask.c linux-libre-2.6.39-gnu/arch/arm/plat-samsung/wakeup-mask.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-samsung/wakeup-mask.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-samsung/wakeup-mask.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
 void samsung_sync_wakemask(void __iomem *reg,
 			   struct samsung_wakeup_mask *mask, int nr_mask)
 {
-	struct irq_desc *desc;
+	struct irq_data *data;
 	u32 val;
 
 	val = __raw_readl(reg);
@@ -33,10 +33,10 @@
 			continue;
 		}
 
-		desc = irq_to_desc(mask->irq);
+		data = irq_get_irq_data(mask->irq);
 
-		/* bit of a liberty to read this directly from irq_desc. */
-		if (desc->wake_depth > 0)
+		/* bit of a liberty to read this directly from irq_data. */
+		if (irqd_is_wakeup_set(data))
 			val &= ~mask->bit;
 		else
 			val |= mask->bit;
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/clock.c linux-libre-2.6.39-gnu/arch/arm/plat-spear/clock.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,18 +12,25 @@
  */
 
 #include <linux/bug.h>
+#include <linux/clk.h>
+#include <linux/debugfs.h>
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/module.h>
 #include <linux/spinlock.h>
-#include <mach/misc_regs.h>
 #include <plat/clock.h>
 
 static DEFINE_SPINLOCK(clocks_lock);
 static LIST_HEAD(root_clks);
+#ifdef CONFIG_DEBUG_FS
+static LIST_HEAD(clocks);
+#endif
 
-static void propagate_rate(struct list_head *);
+static void propagate_rate(struct clk *, int on_init);
+#ifdef CONFIG_DEBUG_FS
+static int clk_debugfs_reparent(struct clk *);
+#endif
 
 static int generic_clk_enable(struct clk *clk)
 {
@@ -65,6 +72,104 @@
 	.disable = generic_clk_disable,
 };
 
+/* returns current programmed clocks clock info structure */
+static struct pclk_info *pclk_info_get(struct clk *clk)
+{
+	unsigned int val, i;
+	struct pclk_info *info = NULL;
+
+	val = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
+		& clk->pclk_sel->pclk_sel_mask;
+
+	for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
+		if (clk->pclk_sel->pclk_info[i].pclk_val == val)
+			info = &clk->pclk_sel->pclk_info[i];
+	}
+
+	return info;
+}
+
+/*
+ * Set Update pclk, and pclk_info of clk and add clock sibling node to current
+ * parents children list
+ */
+static void clk_reparent(struct clk *clk, struct pclk_info *pclk_info)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	list_del(&clk->sibling);
+	list_add(&clk->sibling, &pclk_info->pclk->children);
+
+	clk->pclk = pclk_info->pclk;
+	spin_unlock_irqrestore(&clocks_lock, flags);
+
+#ifdef CONFIG_DEBUG_FS
+	clk_debugfs_reparent(clk);
+#endif
+}
+
+static void do_clk_disable(struct clk *clk)
+{
+	if (!clk)
+		return;
+
+	if (!clk->usage_count) {
+		WARN_ON(1);
+		return;
+	}
+
+	clk->usage_count--;
+
+	if (clk->usage_count == 0) {
+		/*
+		 * Surely, there are no active childrens or direct users
+		 * of this clock
+		 */
+		if (clk->pclk)
+			do_clk_disable(clk->pclk);
+
+		if (clk->ops && clk->ops->disable)
+			clk->ops->disable(clk);
+	}
+}
+
+static int do_clk_enable(struct clk *clk)
+{
+	int ret = 0;
+
+	if (!clk)
+		return -EFAULT;
+
+	if (clk->usage_count == 0) {
+		if (clk->pclk) {
+			ret = do_clk_enable(clk->pclk);
+			if (ret)
+				goto err;
+		}
+		if (clk->ops && clk->ops->enable) {
+			ret = clk->ops->enable(clk);
+			if (ret) {
+				if (clk->pclk)
+					do_clk_disable(clk->pclk);
+				goto err;
+			}
+		}
+		/*
+		 * Since the clock is going to be used for the first
+		 * time please reclac
+		 */
+		if (clk->recalc) {
+			ret = clk->recalc(clk);
+			if (ret)
+				goto err;
+		}
+	}
+	clk->usage_count++;
+err:
+	return ret;
+}
+
 /*
  * clk_enable - inform the system when the clock source should be running.
  * @clk: clock source
@@ -78,17 +183,9 @@
 	unsigned long flags;
 	int ret = 0;
 
-	if (!clk || IS_ERR(clk))
-		return -EFAULT;
-
 	spin_lock_irqsave(&clocks_lock, flags);
-	if (clk->usage_count == 0) {
-		if (clk->ops && clk->ops->enable)
-			ret = clk->ops->enable(clk);
-	}
-	clk->usage_count++;
+	ret = do_clk_enable(clk);
 	spin_unlock_irqrestore(&clocks_lock, flags);
-
 	return ret;
 }
 EXPORT_SYMBOL(clk_enable);
@@ -109,17 +206,8 @@
 {
 	unsigned long flags;
 
-	if (!clk || IS_ERR(clk))
-		return;
-
-	WARN_ON(clk->usage_count == 0);
-
 	spin_lock_irqsave(&clocks_lock, flags);
-	clk->usage_count--;
-	if (clk->usage_count == 0) {
-		if (clk->ops && clk->ops->disable)
-			clk->ops->disable(clk);
-	}
+	do_clk_disable(clk);
 	spin_unlock_irqrestore(&clocks_lock, flags);
 }
 EXPORT_SYMBOL(clk_disable);
@@ -153,15 +241,14 @@
 	int i, found = 0, val = 0;
 	unsigned long flags;
 
-	if (!clk || IS_ERR(clk) || !parent || IS_ERR(parent))
+	if (!clk || !parent)
 		return -EFAULT;
-	if (clk->usage_count)
-		return -EBUSY;
-	if (!clk->pclk_sel)
-		return -EPERM;
 	if (clk->pclk == parent)
 		return 0;
+	if (!clk->pclk_sel)
+		return -EPERM;
 
+	/* check if requested parent is in clk parent list */
 	for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
 		if (clk->pclk_sel->pclk_info[i].pclk == parent) {
 			found = 1;
@@ -176,25 +263,58 @@
 	/* reflect parent change in hardware */
 	val = readl(clk->pclk_sel->pclk_sel_reg);
 	val &= ~(clk->pclk_sel->pclk_sel_mask << clk->pclk_sel_shift);
-	val |= clk->pclk_sel->pclk_info[i].pclk_mask << clk->pclk_sel_shift;
+	val |= clk->pclk_sel->pclk_info[i].pclk_val << clk->pclk_sel_shift;
 	writel(val, clk->pclk_sel->pclk_sel_reg);
 	spin_unlock_irqrestore(&clocks_lock, flags);
 
 	/* reflect parent change in software */
-	clk->recalc(clk);
-	propagate_rate(&clk->children);
+	clk_reparent(clk, &clk->pclk_sel->pclk_info[i]);
+
+	propagate_rate(clk, 0);
 	return 0;
 }
 EXPORT_SYMBOL(clk_set_parent);
 
+/**
+ * clk_set_rate - set the clock rate for a clock source
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns success (0) or negative errno.
+ */
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (!clk || !rate)
+		return -EFAULT;
+
+	if (clk->set_rate) {
+		spin_lock_irqsave(&clocks_lock, flags);
+		ret = clk->set_rate(clk, rate);
+		if (!ret)
+			/* if successful -> propagate */
+			propagate_rate(clk, 0);
+		spin_unlock_irqrestore(&clocks_lock, flags);
+	} else if (clk->pclk) {
+		u32 mult = clk->div_factor ? clk->div_factor : 1;
+		ret = clk_set_rate(clk->pclk, mult * rate);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
 /* registers clock in platform clock framework */
 void clk_register(struct clk_lookup *cl)
 {
-	struct clk *clk = cl->clk;
+	struct clk *clk;
 	unsigned long flags;
 
-	if (!clk || IS_ERR(clk))
+	if (!cl || !cl->clk)
 		return;
+	clk = cl->clk;
 
 	spin_lock_irqsave(&clocks_lock, flags);
 
@@ -207,71 +327,173 @@
 	/* root clock don't have any parents */
 	if (!clk->pclk && !clk->pclk_sel) {
 		list_add(&clk->sibling, &root_clks);
-		/* add clocks with only one parent to parent's children list */
 	} else if (clk->pclk && !clk->pclk_sel) {
+		/* add clocks with only one parent to parent's children list */
 		list_add(&clk->sibling, &clk->pclk->children);
 	} else {
-		/* add clocks with > 1 parent to 1st parent's children list */
-		list_add(&clk->sibling,
-			 &clk->pclk_sel->pclk_info[0].pclk->children);
+		/* clocks with more than one parent */
+		struct pclk_info *pclk_info;
+
+		pclk_info = pclk_info_get(clk);
+		if (!pclk_info) {
+			pr_err("CLKDEV: invalid pclk info of clk with"
+					" %s dev_id and %s con_id\n",
+					cl->dev_id, cl->con_id);
+		} else {
+			clk->pclk = pclk_info->pclk;
+			list_add(&clk->sibling, &pclk_info->pclk->children);
+		}
 	}
+
 	spin_unlock_irqrestore(&clocks_lock, flags);
 
+	/* debugfs specific */
+#ifdef CONFIG_DEBUG_FS
+	list_add(&clk->node, &clocks);
+	clk->cl = cl;
+#endif
+
 	/* add clock to arm clockdev framework */
 	clkdev_add(cl);
 }
 
 /**
- * propagate_rate - recalculate and propagate all clocks in list head
+ * propagate_rate - recalculate and propagate all clocks to children
+ * @pclk: parent clock required to be propogated
+ * @on_init: flag for enabling clocks which are ENABLED_ON_INIT.
  *
- * Recalculates all root clocks in list head, which if the clock's .recalc is
- * set correctly, should also propagate their rates.
+ * Recalculates all children clocks
  */
-static void propagate_rate(struct list_head *lhead)
+void propagate_rate(struct clk *pclk, int on_init)
 {
-	struct clk *clkp, *_temp;
+	struct clk *clk, *_temp;
+	int ret = 0;
 
-	list_for_each_entry_safe(clkp, _temp, lhead, sibling) {
-		if (clkp->recalc)
-			clkp->recalc(clkp);
-		propagate_rate(&clkp->children);
+	list_for_each_entry_safe(clk, _temp, &pclk->children, sibling) {
+		if (clk->recalc) {
+			ret = clk->recalc(clk);
+			/*
+			 * recalc will return error if clk out is not programmed
+			 * In this case configure default rate.
+			 */
+			if (ret && clk->set_rate)
+				clk->set_rate(clk, 0);
+		}
+		propagate_rate(clk, on_init);
+
+		if (!on_init)
+			continue;
+
+		/* Enable clks enabled on init, in software view */
+		if (clk->flags & ENABLED_ON_INIT)
+			do_clk_enable(clk);
 	}
 }
 
-/* returns current programmed clocks clock info structure */
-static struct pclk_info *pclk_info_get(struct clk *clk)
+/**
+ * round_rate_index - return closest programmable rate index in rate_config tbl
+ * @clk: ptr to clock structure
+ * @drate: desired rate
+ * @rate: final rate will be returned in this variable only.
+ *
+ * Finds index in rate_config for highest clk rate which is less than
+ * requested rate. If there is no clk rate lesser than requested rate then
+ * -EINVAL is returned. This routine assumes that rate_config is written
+ * in incrementing order of clk rates.
+ * If drate passed is zero then default rate is programmed.
+ */
+static int
+round_rate_index(struct clk *clk, unsigned long drate, unsigned long *rate)
 {
-	unsigned int mask, i;
-	unsigned long flags;
-	struct pclk_info *info = NULL;
+	unsigned long tmp = 0, prev_rate = 0;
+	int index;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	mask = (readl(clk->pclk_sel->pclk_sel_reg) >> clk->pclk_sel_shift)
-			& clk->pclk_sel->pclk_sel_mask;
+	if (!clk->calc_rate)
+		return -EFAULT;
 
-	for (i = 0; i < clk->pclk_sel->pclk_count; i++) {
-		if (clk->pclk_sel->pclk_info[i].pclk_mask == mask)
-			info = &clk->pclk_sel->pclk_info[i];
+	if (!drate)
+		return -EINVAL;
+
+	/*
+	 * This loops ends on two conditions:
+	 * - as soon as clk is found with rate greater than requested rate.
+	 * - if all clks in rate_config are smaller than requested rate.
+	 */
+	for (index = 0; index < clk->rate_config.count; index++) {
+		prev_rate = tmp;
+		tmp = clk->calc_rate(clk, index);
+		if (drate < tmp) {
+			index--;
+			break;
+		}
 	}
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	/* return if can't find suitable clock */
+	if (index < 0) {
+		index = -EINVAL;
+		*rate = 0;
+	} else if (index == clk->rate_config.count) {
+		/* program with highest clk rate possible */
+		index = clk->rate_config.count - 1;
+		*rate = tmp;
+	} else
+		*rate = prev_rate;
 
-	return info;
+	return index;
 }
 
-/*
- * Set pclk as cclk's parent and add clock sibling node to current parents
- * children list
+/**
+ * clk_round_rate - adjust a rate to the exact rate a clock can provide
+ * @clk: clock source
+ * @rate: desired clock rate in Hz
+ *
+ * Returns rounded clock rate in Hz, or negative errno.
  */
-static void change_parent(struct clk *cclk, struct clk *pclk)
+long clk_round_rate(struct clk *clk, unsigned long drate)
 {
-	unsigned long flags;
+	long rate = 0;
+	int index;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	list_del(&cclk->sibling);
-	list_add(&cclk->sibling, &pclk->children);
+	/*
+	 * propagate call to parent who supports calc_rate. Similar approach is
+	 * used in clk_set_rate.
+	 */
+	if (!clk->calc_rate) {
+		u32 mult;
+		if (!clk->pclk)
+			return clk->rate;
 
-	cclk->pclk = pclk;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+		mult = clk->div_factor ? clk->div_factor : 1;
+		return clk_round_rate(clk->pclk, mult * drate) / mult;
+	}
+
+	index = round_rate_index(clk, drate, &rate);
+	if (index >= 0)
+		return rate;
+	else
+		return index;
+}
+EXPORT_SYMBOL(clk_round_rate);
+
+/*All below functions are called with lock held */
+
+/*
+ * Calculates pll clk rate for specific value of mode, m, n and p
+ *
+ * In normal mode
+ * rate = (2 * M[15:8] * Fin)/(N * 2^P)
+ *
+ * In Dithered mode
+ * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
+ */
+unsigned long pll_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct pll_rate_tbl *tbls = clk->rate_config.tbls;
+	unsigned int mode;
+
+	mode = tbls[index].mode ? 256 : 1;
+	return (((2 * rate / 10000) * tbls[index].m) /
+			(mode * tbls[index].n * (1 << tbls[index].p))) * 10000;
 }
 
 /*
@@ -283,47 +505,146 @@
  * In Dithered mode
  * rate = (2 * M[15:0] * Fin)/(256 * N * 2^P)
  */
-void pll1_clk_recalc(struct clk *clk)
+int pll_clk_recalc(struct clk *clk)
 {
 	struct pll_clk_config *config = clk->private_data;
 	unsigned int num = 2, den = 0, val, mode = 0;
-	unsigned long flags;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	mode = (readl(config->mode_reg) >> PLL_MODE_SHIFT) &
-		PLL_MODE_MASK;
+	mode = (readl(config->mode_reg) >> config->masks->mode_shift) &
+		config->masks->mode_mask;
 
 	val = readl(config->cfg_reg);
 	/* calculate denominator */
-	den = (val >> PLL_DIV_P_SHIFT) & PLL_DIV_P_MASK;
+	den = (val >> config->masks->div_p_shift) & config->masks->div_p_mask;
 	den = 1 << den;
-	den *= (val >> PLL_DIV_N_SHIFT) & PLL_DIV_N_MASK;
+	den *= (val >> config->masks->div_n_shift) & config->masks->div_n_mask;
 
 	/* calculate numerator & denominator */
 	if (!mode) {
 		/* Normal mode */
-		num *= (val >> PLL_NORM_FDBK_M_SHIFT) & PLL_NORM_FDBK_M_MASK;
+		num *= (val >> config->masks->norm_fdbk_m_shift) &
+			config->masks->norm_fdbk_m_mask;
 	} else {
 		/* Dithered mode */
-		num *= (val >> PLL_DITH_FDBK_M_SHIFT) & PLL_DITH_FDBK_M_MASK;
+		num *= (val >> config->masks->dith_fdbk_m_shift) &
+			config->masks->dith_fdbk_m_mask;
 		den *= 256;
 	}
 
+	if (!den)
+		return -EINVAL;
+
 	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+/*
+ * Configures new clock rate of pll
+ */
+int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct pll_rate_tbl *tbls = clk->rate_config.tbls;
+	struct pll_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->mode_reg) &
+		~(config->masks->mode_mask << config->masks->mode_shift);
+	val |= (tbls[i].mode & config->masks->mode_mask) <<
+		config->masks->mode_shift;
+	writel(val, config->mode_reg);
+
+	val = readl(config->cfg_reg) &
+		~(config->masks->div_p_mask << config->masks->div_p_shift);
+	val |= (tbls[i].p & config->masks->div_p_mask) <<
+		config->masks->div_p_shift;
+	val &= ~(config->masks->div_n_mask << config->masks->div_n_shift);
+	val |= (tbls[i].n & config->masks->div_n_mask) <<
+		config->masks->div_n_shift;
+	val &= ~(config->masks->dith_fdbk_m_mask <<
+			config->masks->dith_fdbk_m_shift);
+	if (tbls[i].mode)
+		val |= (tbls[i].m & config->masks->dith_fdbk_m_mask) <<
+			config->masks->dith_fdbk_m_shift;
+	else
+		val |= (tbls[i].m & config->masks->norm_fdbk_m_mask) <<
+			config->masks->norm_fdbk_m_shift;
+
+	writel(val, config->cfg_reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * Calculates ahb, apb clk rate for specific value of div
+ */
+unsigned long bus_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct bus_rate_tbl *tbls = clk->rate_config.tbls;
+
+	return rate / (tbls[index].div + 1);
 }
 
 /* calculates current programmed rate of ahb or apb bus */
-void bus_clk_recalc(struct clk *clk)
+int bus_clk_recalc(struct clk *clk)
 {
 	struct bus_clk_config *config = clk->private_data;
 	unsigned int div;
-	unsigned long flags;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	div = ((readl(config->reg) >> config->shift) & config->mask) + 1;
+	div = ((readl(config->reg) >> config->masks->shift) &
+			config->masks->mask) + 1;
+
+	if (!div)
+		return -EINVAL;
+
 	clk->rate = (unsigned long)clk->pclk->rate / div;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+/* Configures new clock rate of AHB OR APB bus */
+int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct bus_rate_tbl *tbls = clk->rate_config.tbls;
+	struct bus_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->reg) &
+		~(config->masks->mask << config->masks->shift);
+	val |= (tbls[i].div & config->masks->mask) << config->masks->shift;
+	writel(val, config->reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * gives rate for different values of eq, x and y
+ *
+ * Fout from synthesizer can be given from two equations:
+ * Fout1 = (Fin * X/Y)/2		EQ1
+ * Fout2 = Fin * X/Y			EQ2
+ */
+unsigned long aux_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct aux_rate_tbl *tbls = clk->rate_config.tbls;
+	u8 eq = tbls[index].eq ? 1 : 2;
+
+	return (((rate/10000) * tbls[index].xscale) /
+			(tbls[index].yscale * eq)) * 10000;
 }
 
 /*
@@ -336,44 +657,76 @@
  *
  * Selection of eqn 1 or 2 is programmed in register
  */
-void aux_clk_recalc(struct clk *clk)
+int aux_clk_recalc(struct clk *clk)
 {
 	struct aux_clk_config *config = clk->private_data;
-	struct pclk_info *pclk_info = NULL;
 	unsigned int num = 1, den = 1, val, eqn;
-	unsigned long flags;
 
-	/* get current programmed parent */
-	pclk_info = pclk_info_get(clk);
-	if (!pclk_info) {
-		spin_lock_irqsave(&clocks_lock, flags);
-		clk->pclk = NULL;
-		clk->rate = 0;
-		spin_unlock_irqrestore(&clocks_lock, flags);
-		return;
-	}
+	val = readl(config->synth_reg);
 
-	change_parent(clk, pclk_info->pclk);
+	eqn = (val >> config->masks->eq_sel_shift) &
+		config->masks->eq_sel_mask;
+	if (eqn == config->masks->eq1_mask)
+		den *= 2;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (pclk_info->scalable) {
-		val = readl(config->synth_reg);
+	/* calculate numerator */
+	num = (val >> config->masks->xscale_sel_shift) &
+		config->masks->xscale_sel_mask;
 
-		eqn = (val >> AUX_EQ_SEL_SHIFT) & AUX_EQ_SEL_MASK;
-		if (eqn == AUX_EQ1_SEL)
-			den *= 2;
+	/* calculate denominator */
+	den *= (val >> config->masks->yscale_sel_shift) &
+		config->masks->yscale_sel_mask;
 
-		/* calculate numerator */
-		num = (val >> AUX_XSCALE_SHIFT) & AUX_XSCALE_MASK;
+	if (!den)
+		return -EINVAL;
 
-		/* calculate denominator */
-		den *= (val >> AUX_YSCALE_SHIFT) & AUX_YSCALE_MASK;
-		val = (((clk->pclk->rate/10000) * num) / den) * 10000;
-	} else
-		val = clk->pclk->rate;
+	clk->rate = (((clk->pclk->rate/10000) * num) / den) * 10000;
+	return 0;
+}
 
-	clk->rate = val;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
+int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct aux_rate_tbl *tbls = clk->rate_config.tbls;
+	struct aux_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->synth_reg) &
+		~(config->masks->eq_sel_mask << config->masks->eq_sel_shift);
+	val |= (tbls[i].eq & config->masks->eq_sel_mask) <<
+		config->masks->eq_sel_shift;
+	val &= ~(config->masks->xscale_sel_mask <<
+			config->masks->xscale_sel_shift);
+	val |= (tbls[i].xscale & config->masks->xscale_sel_mask) <<
+		config->masks->xscale_sel_shift;
+	val &= ~(config->masks->yscale_sel_mask <<
+			config->masks->yscale_sel_shift);
+	val |= (tbls[i].yscale & config->masks->yscale_sel_mask) <<
+		config->masks->yscale_sel_shift;
+	writel(val, config->synth_reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * Calculates gpt clk rate for different values of mscale and nscale
+ *
+ * Fout= Fin/((2 ^ (N+1)) * (M+1))
+ */
+unsigned long gpt_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
+
+	return rate / ((1 << (tbls[index].nscale + 1)) *
+			(tbls[index].mscale + 1));
 }
 
 /*
@@ -381,46 +734,142 @@
  * Fout from synthesizer can be given from below equations:
  * Fout= Fin/((2 ^ (N+1)) * (M+1))
  */
-void gpt_clk_recalc(struct clk *clk)
+int gpt_clk_recalc(struct clk *clk)
 {
-	struct aux_clk_config *config = clk->private_data;
-	struct pclk_info *pclk_info = NULL;
+	struct gpt_clk_config *config = clk->private_data;
 	unsigned int div = 1, val;
-	unsigned long flags;
 
-	pclk_info = pclk_info_get(clk);
-	if (!pclk_info) {
-		spin_lock_irqsave(&clocks_lock, flags);
-		clk->pclk = NULL;
-		clk->rate = 0;
-		spin_unlock_irqrestore(&clocks_lock, flags);
-		return;
-	}
-
-	change_parent(clk, pclk_info->pclk);
+	val = readl(config->synth_reg);
+	div += (val >> config->masks->mscale_sel_shift) &
+		config->masks->mscale_sel_mask;
+	div *= 1 << (((val >> config->masks->nscale_sel_shift) &
+				config->masks->nscale_sel_mask) + 1);
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	if (pclk_info->scalable) {
-		val = readl(config->synth_reg);
-		div += (val >> GPT_MSCALE_SHIFT) & GPT_MSCALE_MASK;
-		div *= 1 << (((val >> GPT_NSCALE_SHIFT) & GPT_NSCALE_MASK) + 1);
-	}
+	if (!div)
+		return -EINVAL;
 
 	clk->rate = (unsigned long)clk->pclk->rate / div;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	return 0;
+}
+
+/* Configures new clock rate of gptiliary synthesizers used by: UART, FIRDA*/
+int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct gpt_rate_tbl *tbls = clk->rate_config.tbls;
+	struct gpt_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->synth_reg) & ~(config->masks->mscale_sel_mask <<
+			config->masks->mscale_sel_shift);
+	val |= (tbls[i].mscale & config->masks->mscale_sel_mask) <<
+		config->masks->mscale_sel_shift;
+	val &= ~(config->masks->nscale_sel_mask <<
+			config->masks->nscale_sel_shift);
+	val |= (tbls[i].nscale & config->masks->nscale_sel_mask) <<
+		config->masks->nscale_sel_shift;
+	writel(val, config->synth_reg);
+
+	clk->rate = rate;
+
+	return 0;
 }
 
 /*
- * Used for clocks that always have same value as the parent clock divided by a
+ * Calculates clcd clk rate for different values of div
+ *
+ * Fout from synthesizer can be given from below equation:
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ *	0-13 (fractional part)
+ *	14-16 (integer part)
+ * To calculate Fout we left shift val by 14 bits and divide Fin by
+ * complete div (including fractional part) and then right shift the
+ * result by 14 places.
+ */
+unsigned long clcd_calc_rate(struct clk *clk, int index)
+{
+	unsigned long rate = clk->pclk->rate;
+	struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
+
+	rate /= 1000;
+	rate <<= 12;
+	rate /= (2 * tbls[index].div);
+	rate >>= 12;
+	rate *= 1000;
+
+	return rate;
+}
+
+/*
+ * calculates current programmed rate of clcd synthesizer
+ * Fout from synthesizer can be given from below equation:
+ * Fout= Fin/2*div (division factor)
+ * div is 17 bits:-
+ *	0-13 (fractional part)
+ *	14-16 (integer part)
+ * To calculate Fout we left shift val by 14 bits and divide Fin by
+ * complete div (including fractional part) and then right shift the
+ * result by 14 places.
+ */
+int clcd_clk_recalc(struct clk *clk)
+{
+	struct clcd_clk_config *config = clk->private_data;
+	unsigned int div = 1;
+	unsigned long prate;
+	unsigned int val;
+
+	val = readl(config->synth_reg);
+	div = (val >> config->masks->div_factor_shift) &
+		config->masks->div_factor_mask;
+
+	if (!div)
+		return -EINVAL;
+
+	prate = clk->pclk->rate / 1000; /* first level division, make it KHz */
+
+	clk->rate = (((unsigned long)prate << 12) / (2 * div)) >> 12;
+	clk->rate *= 1000;
+	return 0;
+}
+
+/* Configures new clock rate of auxiliary synthesizers used by: UART, FIRDA*/
+int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate)
+{
+	struct clcd_rate_tbl *tbls = clk->rate_config.tbls;
+	struct clcd_clk_config *config = clk->private_data;
+	unsigned long val, rate;
+	int i;
+
+	i = round_rate_index(clk, desired_rate, &rate);
+	if (i < 0)
+		return i;
+
+	val = readl(config->synth_reg) & ~(config->masks->div_factor_mask <<
+			config->masks->div_factor_shift);
+	val |= (tbls[i].div & config->masks->div_factor_mask) <<
+		config->masks->div_factor_shift;
+	writel(val, config->synth_reg);
+
+	clk->rate = rate;
+
+	return 0;
+}
+
+/*
+ * Used for clocks that always have value as the parent clock divided by a
  * fixed divisor
  */
-void follow_parent(struct clk *clk)
+int follow_parent(struct clk *clk)
 {
-	unsigned long flags;
+	unsigned int div_factor = (clk->div_factor < 1) ? 1 : clk->div_factor;
 
-	spin_lock_irqsave(&clocks_lock, flags);
-	clk->rate = clk->pclk->rate;
-	spin_unlock_irqrestore(&clocks_lock, flags);
+	clk->rate = clk->pclk->rate/div_factor;
+	return 0;
 }
 
 /**
@@ -431,5 +880,124 @@
  */
 void recalc_root_clocks(void)
 {
-	propagate_rate(&root_clks);
+	struct clk *pclk;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&clocks_lock, flags);
+	list_for_each_entry(pclk, &root_clks, sibling) {
+		if (pclk->recalc) {
+			ret = pclk->recalc(pclk);
+			/*
+			 * recalc will return error if clk out is not programmed
+			 * In this case configure default clock.
+			 */
+			if (ret && pclk->set_rate)
+				pclk->set_rate(pclk, 0);
+		}
+		propagate_rate(pclk, 1);
+		/* Enable clks enabled on init, in software view */
+		if (pclk->flags & ENABLED_ON_INIT)
+			do_clk_enable(pclk);
+	}
+	spin_unlock_irqrestore(&clocks_lock, flags);
 }
+
+#ifdef CONFIG_DEBUG_FS
+/*
+ *	debugfs support to trace clock tree hierarchy and attributes
+ */
+static struct dentry *clk_debugfs_root;
+static int clk_debugfs_register_one(struct clk *c)
+{
+	int err;
+	struct dentry *d, *child;
+	struct clk *pa = c->pclk;
+	char s[255];
+	char *p = s;
+
+	if (c) {
+		if (c->cl->con_id)
+			p += sprintf(p, "%s", c->cl->con_id);
+		if (c->cl->dev_id)
+			p += sprintf(p, "%s", c->cl->dev_id);
+	}
+	d = debugfs_create_dir(s, pa ? pa->dent : clk_debugfs_root);
+	if (!d)
+		return -ENOMEM;
+	c->dent = d;
+
+	d = debugfs_create_u32("usage_count", S_IRUGO, c->dent,
+			(u32 *)&c->usage_count);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_u32("rate", S_IRUGO, c->dent, (u32 *)&c->rate);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	d = debugfs_create_x32("flags", S_IRUGO, c->dent, (u32 *)&c->flags);
+	if (!d) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+	return 0;
+
+err_out:
+	d = c->dent;
+	list_for_each_entry(child, &d->d_subdirs, d_u.d_child)
+		debugfs_remove(child);
+	debugfs_remove(c->dent);
+	return err;
+}
+
+static int clk_debugfs_register(struct clk *c)
+{
+	int err;
+	struct clk *pa = c->pclk;
+
+	if (pa && !pa->dent) {
+		err = clk_debugfs_register(pa);
+		if (err)
+			return err;
+	}
+
+	if (!c->dent) {
+		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, &clocks, node) {
+		err = clk_debugfs_register(c);
+		if (err)
+			goto err_out;
+	}
+	return 0;
+err_out:
+	debugfs_remove_recursive(clk_debugfs_root);
+	return err;
+}
+late_initcall(clk_debugfs_init);
+
+static int clk_debugfs_reparent(struct clk *c)
+{
+	debugfs_remove(c->dent);
+	return clk_debugfs_register_one(c);
+}
+#endif /* CONFIG_DEBUG_FS */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/clock.h linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/clock.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/clock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/clock.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 /* clk structure flags */
 #define	ALWAYS_ENABLED		(1 << 0) /* clock always enabled */
 #define	RESET_TO_ENABLE		(1 << 1) /* reset register bit to enable clk */
+#define	ENABLED_ON_INIT		(1 << 2) /* clocks enabled at init */
 
 /**
  * struct clkops - clock operations
@@ -35,13 +36,11 @@
 /**
  * struct pclk_info - parents info
  * @pclk: pointer to parent clk
- * @pclk_mask: value to be written for selecting this parent
- * @scalable: Is parent scalable (1 - YES, 0 - NO)
+ * @pclk_val: value to be written for selecting this parent
  */
 struct pclk_info {
 	struct clk *pclk;
-	u8 pclk_mask;
-	u8 scalable;
+	u8 pclk_val;
 };
 
 /**
@@ -54,11 +53,23 @@
 struct pclk_sel {
 	struct pclk_info *pclk_info;
 	u8 pclk_count;
-	unsigned int *pclk_sel_reg;
+	void __iomem *pclk_sel_reg;
 	unsigned int pclk_sel_mask;
 };
 
 /**
+ * struct rate_config - clk rate configurations
+ * @tbls: array of device specific clk rate tables, in ascending order of rates
+ * @count: size of tbls array
+ * @default_index: default setting when originally disabled
+ */
+struct rate_config {
+	void *tbls;
+	u8 count;
+	u8 default_index;
+};
+
+/**
  * struct clk - clock structure
  * @usage_count: num of users who enabled this clock
  * @flags: flags for clock properties
@@ -67,21 +78,32 @@
  * @en_reg_bit: clk enable/disable bit
  * @ops: clk enable/disable ops - generic_clkops selected if NULL
  * @recalc: pointer to clock rate recalculate function
+ * @set_rate: pointer to clock set rate function
+ * @calc_rate: pointer to clock get rate function for index
+ * @rate_config: rate configuration information, used by set_rate
+ * @div_factor: division factor to parent clock.
  * @pclk: current parent clk
  * @pclk_sel: pointer to parent selection structure
  * @pclk_sel_shift: register shift for selecting parent of this clock
  * @children: list for childrens or this clock
  * @sibling: node for list of clocks having same parents
  * @private_data: clock specific private data
+ * @node: list to maintain clocks linearly
+ * @cl: clocklook up associated with this clock
+ * @dent: object for debugfs
  */
 struct clk {
 	unsigned int usage_count;
 	unsigned int flags;
 	unsigned long rate;
-	unsigned int *en_reg;
+	void __iomem *en_reg;
 	u8 en_reg_bit;
 	const struct clkops *ops;
-	void (*recalc) (struct clk *);
+	int (*recalc) (struct clk *);
+	int (*set_rate) (struct clk *, unsigned long rate);
+	unsigned long (*calc_rate)(struct clk *, int index);
+	struct rate_config rate_config;
+	unsigned int div_factor;
 
 	struct clk *pclk;
 	struct pclk_sel *pclk_sel;
@@ -90,37 +112,137 @@
 	struct list_head children;
 	struct list_head sibling;
 	void *private_data;
+#ifdef CONFIG_DEBUG_FS
+	struct list_head node;
+	struct clk_lookup *cl;
+	struct dentry *dent;
+#endif
 };
 
 /* pll configuration structure */
+struct pll_clk_masks {
+	u32 mode_mask;
+	u32 mode_shift;
+
+	u32 norm_fdbk_m_mask;
+	u32 norm_fdbk_m_shift;
+	u32 dith_fdbk_m_mask;
+	u32 dith_fdbk_m_shift;
+	u32 div_p_mask;
+	u32 div_p_shift;
+	u32 div_n_mask;
+	u32 div_n_shift;
+};
+
 struct pll_clk_config {
-	unsigned int *mode_reg;
-	unsigned int *cfg_reg;
+	void __iomem *mode_reg;
+	void __iomem *cfg_reg;
+	struct pll_clk_masks *masks;
+};
+
+/* pll clk rate config structure */
+struct pll_rate_tbl {
+	u8 mode;
+	u16 m;
+	u8 n;
+	u8 p;
 };
 
 /* ahb and apb bus configuration structure */
+struct bus_clk_masks {
+	u32 mask;
+	u32 shift;
+};
+
 struct bus_clk_config {
-	unsigned int *reg;
-	unsigned int mask;
-	unsigned int shift;
+	void __iomem *reg;
+	struct bus_clk_masks *masks;
+};
+
+/* ahb and apb clk bus rate config structure */
+struct bus_rate_tbl {
+	u8 div;
+};
+
+/* Aux clk configuration structure: applicable to UART and FIRDA */
+struct aux_clk_masks {
+	u32 eq_sel_mask;
+	u32 eq_sel_shift;
+	u32 eq1_mask;
+	u32 eq2_mask;
+	u32 xscale_sel_mask;
+	u32 xscale_sel_shift;
+	u32 yscale_sel_mask;
+	u32 yscale_sel_shift;
 };
 
-/*
- * Aux clk configuration structure: applicable to GPT, UART and FIRDA
- */
 struct aux_clk_config {
-	unsigned int *synth_reg;
+	void __iomem *synth_reg;
+	struct aux_clk_masks *masks;
+};
+
+/* aux clk rate config structure */
+struct aux_rate_tbl {
+	u16 xscale;
+	u16 yscale;
+	u8 eq;
+};
+
+/* GPT clk configuration structure */
+struct gpt_clk_masks {
+	u32 mscale_sel_mask;
+	u32 mscale_sel_shift;
+	u32 nscale_sel_mask;
+	u32 nscale_sel_shift;
+};
+
+struct gpt_clk_config {
+	void __iomem *synth_reg;
+	struct gpt_clk_masks *masks;
+};
+
+/* gpt clk rate config structure */
+struct gpt_rate_tbl {
+	u16 mscale;
+	u16 nscale;
+};
+
+/* clcd clk configuration structure */
+struct clcd_synth_masks {
+	u32 div_factor_mask;
+	u32 div_factor_shift;
+};
+
+struct clcd_clk_config {
+	void __iomem *synth_reg;
+	struct clcd_synth_masks *masks;
+};
+
+/* clcd clk rate config structure */
+struct clcd_rate_tbl {
+	u16 div;
 };
 
 /* platform specific clock functions */
 void clk_register(struct clk_lookup *cl);
 void recalc_root_clocks(void);
 
-/* clock recalc functions */
-void follow_parent(struct clk *clk);
-void pll1_clk_recalc(struct clk *clk);
-void bus_clk_recalc(struct clk *clk);
-void gpt_clk_recalc(struct clk *clk);
-void aux_clk_recalc(struct clk *clk);
+/* clock recalc & set rate functions */
+int follow_parent(struct clk *clk);
+unsigned long pll_calc_rate(struct clk *clk, int index);
+int pll_clk_recalc(struct clk *clk);
+int pll_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long bus_calc_rate(struct clk *clk, int index);
+int bus_clk_recalc(struct clk *clk);
+int bus_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long gpt_calc_rate(struct clk *clk, int index);
+int gpt_clk_recalc(struct clk *clk);
+int gpt_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long aux_calc_rate(struct clk *clk, int index);
+int aux_clk_recalc(struct clk *clk);
+int aux_clk_set_rate(struct clk *clk, unsigned long desired_rate);
+unsigned long clcd_calc_rate(struct clk *clk, int index);
+int clcd_clk_recalc(struct clk *clk);
+int clcd_clk_set_rate(struct clk *clk, unsigned long desired_rate);
 
 #endif /* __PLAT_CLOCK_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/debug-macro.S linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/debug-macro.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
  */
 
 #include <linux/amba/serial.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 		.macro	addruart, rp, rv
 		mov	\rp, #SPEAR_DBG_UART_BASE		@ Physical base
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/hardware.h linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/hardware.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * arch/arm/plat-spear/include/plat/hardware.h
+ *
+ * Hardware definitions for SPEAr
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Viresh Kumar<viresh.kumar@st.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 __PLAT_HARDWARE_H
+#define __PLAT_HARDWARE_H
+
+#ifndef __ASSEMBLY__
+#define IOMEM(x)	((void __iomem __force *)(x))
+#else
+#define IOMEM(x)	(x)
+#endif
+
+#endif /* __PLAT_HARDWARE_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/memory.h linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,6 @@
 #define __PLAT_MEMORY_H
 
 /* Physical DRAM offset */
-#define PHYS_OFFSET		UL(0x00000000)
+#define PLAT_PHYS_OFFSET		UL(0x00000000)
 
 #endif /* __PLAT_MEMORY_H */
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/system.h linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/system.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,9 +14,9 @@
 #ifndef __PLAT_SYSTEM_H
 #define __PLAT_SYSTEM_H
 
-#include <asm/hardware/sp810.h>
 #include <linux/io.h>
-#include <mach/spear.h>
+#include <asm/hardware/sp810.h>
+#include <mach/hardware.h>
 
 static inline void arch_idle(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/uncompress.h linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/uncompress.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/include/plat/uncompress.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/include/plat/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 
 #include <linux/io.h>
 #include <linux/amba/serial.h>
-#include <mach/spear.h>
+#include <mach/hardware.h>
 
 #ifndef __PLAT_UNCOMPRESS_H
 #define __PLAT_UNCOMPRESS_H
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/Makefile linux-libre-2.6.39-gnu/arch/arm/plat-spear/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,6 @@
 #
 
 # Common support
-obj-y	:= clock.o padmux.o time.o
+obj-y	:= clock.o time.o
 
-obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o
+obj-$(CONFIG_ARCH_SPEAR3XX)	+= shirq.o padmux.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/shirq.c linux-libre-2.6.39-gnu/arch/arm/plat-spear/shirq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/shirq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/shirq.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,7 +68,7 @@
 static void shirq_handler(unsigned irq, struct irq_desc *desc)
 {
 	u32 i, val, mask;
-	struct spear_shirq *shirq = get_irq_data(irq);
+	struct spear_shirq *shirq = irq_get_handler_data(irq);
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	while ((val = readl(shirq->regs.base + shirq->regs.status_reg) &
@@ -105,14 +105,14 @@
 	if (!shirq->dev_count)
 		return -EINVAL;
 
-	set_irq_chained_handler(shirq->irq, shirq_handler);
+	irq_set_chained_handler(shirq->irq, shirq_handler);
 	for (i = 0; i < shirq->dev_count; i++) {
-		set_irq_chip(shirq->dev_config[i].virq, &shirq_chip);
-		set_irq_handler(shirq->dev_config[i].virq, handle_simple_irq);
+		irq_set_chip_and_handler(shirq->dev_config[i].virq,
+					 &shirq_chip, handle_simple_irq);
 		set_irq_flags(shirq->dev_config[i].virq, IRQF_VALID);
-		set_irq_chip_data(shirq->dev_config[i].virq, shirq);
+		irq_set_chip_data(shirq->dev_config[i].virq, shirq);
 	}
 
-	set_irq_data(shirq->irq, shirq);
+	irq_set_handler_data(shirq->irq, shirq);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-spear/time.c linux-libre-2.6.39-gnu/arch/arm/plat-spear/time.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-spear/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-spear/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * arch/arm/plat-spear/time.c
  *
- * Copyright (C) 2009 ST Microelectronics
+ * Copyright (C) 2010 ST Microelectronics
  * Shiraz Hashim<shiraz.hashim@st.com>
  *
  * This file is licensed under the terms of the GNU General Public
@@ -20,10 +20,9 @@
 #include <linux/time.h>
 #include <linux/irq.h>
 #include <asm/mach/time.h>
-#include <mach/irqs.h>
-#include <mach/hardware.h>
-#include <mach/spear.h>
 #include <mach/generic.h>
+#include <mach/hardware.h>
+#include <mach/irqs.h>
 
 /*
  * We would use TIMER0 and TIMER1 as clockevent and clocksource.
@@ -211,7 +210,7 @@
 
 void __init spear_setup_timer(void)
 {
-	struct clk *pll3_clk;
+	int ret;
 
 	if (!request_mem_region(SPEAR_GPT0_BASE, SZ_1K, "gpt0")) {
 		pr_err("%s:cannot get IO addr\n", __func__);
@@ -230,26 +229,21 @@
 		goto err_iomap;
 	}
 
-	pll3_clk = clk_get(NULL, "pll3_48m_clk");
-	if (!pll3_clk) {
-		pr_err("%s:couldn't get PLL3 as parent for gpt\n", __func__);
-		goto err_iomap;
+	ret = clk_enable(gpt_clk);
+	if (ret < 0) {
+		pr_err("%s:couldn't enable gpt clock\n", __func__);
+		goto err_clk;
 	}
 
-	clk_set_parent(gpt_clk, pll3_clk);
-
 	spear_clockevent_init();
 	spear_clocksource_init();
 
 	return;
 
+err_clk:
+	clk_put(gpt_clk);
 err_iomap:
 	iounmap(gpt_base);
-
 err_mem:
 	release_mem_region(SPEAR_GPT0_BASE, SZ_1K);
 }
-
-struct sys_timer spear_sys_timer = {
-	.init = spear_setup_timer,
-};
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-stmp3xxx/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET	UL(0x40000000)
+#define PLAT_PHYS_OFFSET	UL(0x40000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-stmp3xxx/irq.c linux-libre-2.6.39-gnu/arch/arm/plat-stmp3xxx/irq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-stmp3xxx/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-stmp3xxx/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,8 +35,7 @@
 	/* Disable all interrupts initially */
 	for (i = 0; i < NR_REAL_IRQS; i++) {
 		chip->irq_mask(irq_get_irq_data(i));
-		set_irq_chip(i, chip);
-		set_irq_handler(i, handle_level_irq);
+		irq_set_chip_and_handler(i, chip, handle_level_irq);
 		set_irq_flags(i, IRQF_VALID | IRQF_PROBE);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-stmp3xxx/pinmux.c linux-libre-2.6.39-gnu/arch/arm/plat-stmp3xxx/pinmux.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-stmp3xxx/pinmux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-stmp3xxx/pinmux.c	2011-05-19 00:06:34.000000000 -0400
@@ -489,14 +489,13 @@
 
 static void stmp3xxx_gpio_irq(u32 irq, struct irq_desc *desc)
 {
-	struct stmp3xxx_pinmux_bank *pm = get_irq_data(irq);
+	struct stmp3xxx_pinmux_bank *pm = irq_get_handler_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]);
+			generic_handle_irq(gpio_irq);
 		gpio_irq++;
 		stat >>= 1;
 	}
@@ -534,15 +533,15 @@
 
 		for (virq = pm->virq; virq < pm->virq; virq++) {
 			gpio_irq_chip.irq_mask(irq_get_irq_data(virq));
-			set_irq_chip(virq, &gpio_irq_chip);
-			set_irq_handler(virq, handle_level_irq);
+			irq_set_chip_and_handler(virq, &gpio_irq_chip,
+						 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);
+		irq_set_chained_handler(pm->irq, stmp3xxx_gpio_irq);
+		irq_set_handler_data(pm->irq, pm);
 	}
 	return r;
 }
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-tcc/include/mach/memory.h linux-libre-2.6.39-gnu/arch/arm/plat-tcc/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-tcc/include/mach/memory.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-tcc/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,6 @@
 /*
  * Physical DRAM offset.
  */
-#define PHYS_OFFSET		UL(0x20000000)
+#define PLAT_PHYS_OFFSET		UL(0x20000000)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/clcd.c linux-libre-2.6.39-gnu/arch/arm/plat-versatile/clcd.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/clcd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/clcd.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,182 @@
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/amba/bus.h>
+#include <linux/amba/clcd.h>
+#include <plat/clcd.h>
+
+static struct clcd_panel vga = {
+	.mode		= {
+		.name		= "VGA",
+		.refresh	= 60,
+		.xres		= 640,
+		.yres		= 480,
+		.pixclock	= 39721,
+		.left_margin	= 40,
+		.right_margin	= 24,
+		.upper_margin	= 32,
+		.lower_margin	= 11,
+		.hsync_len	= 96,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
+	.bpp		= 16,
+};
+
+static struct clcd_panel xvga = {
+	.mode		= {
+		.name		= "XVGA",
+		.refresh	= 60,
+		.xres		= 1024,
+		.yres		= 768,
+		.pixclock	= 15748,
+		.left_margin	= 152,
+		.right_margin	= 48,
+		.upper_margin	= 23,
+		.lower_margin	= 3,
+		.hsync_len	= 104,
+		.vsync_len	= 4,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551 | CLCD_CAP_565 | CLCD_CAP_888,
+	.bpp		= 16,
+};
+
+/* Sanyo TM38QV67A02A - 3.8 inch QVGA (320x240) Color TFT */
+static struct clcd_panel sanyo_tm38qv67a02a = {
+	.mode		= {
+		.name		= "Sanyo TM38QV67A02A",
+		.refresh	= 116,
+		.xres		= 320,
+		.yres		= 240,
+		.pixclock	= 100000,
+		.left_margin	= 6,
+		.right_margin	= 6,
+		.upper_margin	= 5,
+		.lower_margin	= 5,
+		.hsync_len	= 6,
+		.vsync_len	= 6,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551,
+	.bpp		= 16,
+};
+
+static struct clcd_panel sanyo_2_5_in = {
+	.mode		= {
+		.name		= "Sanyo QVGA Portrait",
+		.refresh	= 116,
+		.xres		= 240,
+		.yres		= 320,
+		.pixclock	= 100000,
+		.left_margin	= 20,
+		.right_margin	= 10,
+		.upper_margin	= 2,
+		.lower_margin	= 2,
+		.hsync_len	= 10,
+		.vsync_len	= 2,
+		.sync		= FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_IVS | TIM2_IHS | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551,
+	.bpp		= 16,
+};
+
+/* Epson L2F50113T00 - 2.2 inch 176x220 Color TFT */
+static struct clcd_panel epson_l2f50113t00 = {
+	.mode		= {
+		.name		= "Epson L2F50113T00",
+		.refresh	= 390,
+		.xres		= 176,
+		.yres		= 220,
+		.pixclock	= 62500,
+		.left_margin	= 3,
+		.right_margin	= 2,
+		.upper_margin	= 1,
+		.lower_margin	= 0,
+		.hsync_len	= 3,
+		.vsync_len	= 2,
+		.sync		= 0,
+		.vmode		= FB_VMODE_NONINTERLACED,
+	},
+	.width		= -1,
+	.height		= -1,
+	.tim2		= TIM2_BCD | TIM2_IPC,
+	.cntl		= CNTL_LCDTFT | CNTL_BGR | CNTL_LCDVCOMP(1),
+	.caps		= CLCD_CAP_5551,
+	.bpp		= 16,
+};
+
+static struct clcd_panel *panels[] = {
+	&vga,
+	&xvga,
+	&sanyo_tm38qv67a02a,
+	&sanyo_2_5_in,
+	&epson_l2f50113t00,
+};
+
+struct clcd_panel *versatile_clcd_get_panel(const char *name)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(panels); i++)
+		if (strcmp(panels[i]->mode.name, name) == 0)
+			break;
+
+	if (i < ARRAY_SIZE(panels))
+		return panels[i];
+
+	pr_err("CLCD: couldn't get parameters for panel %s\n", name);
+
+	return NULL;
+}
+
+int versatile_clcd_setup_dma(struct clcd_fb *fb, unsigned long framesize)
+{
+	dma_addr_t dma;
+
+	fb->fb.screen_base = dma_alloc_writecombine(&fb->dev->dev, framesize,
+						    &dma, GFP_KERNEL);
+	if (!fb->fb.screen_base) {
+		pr_err("CLCD: unable to map framebuffer\n");
+		return -ENOMEM;
+	}
+
+	fb->fb.fix.smem_start	= dma;
+	fb->fb.fix.smem_len	= framesize;
+
+	return 0;
+}
+
+int versatile_clcd_mmap_dma(struct clcd_fb *fb, struct vm_area_struct *vma)
+{
+	return dma_mmap_writecombine(&fb->dev->dev, vma,
+				     fb->fb.screen_base,
+				     fb->fb.fix.smem_start,
+				     fb->fb.fix.smem_len);
+}
+
+void versatile_clcd_remove_dma(struct clcd_fb *fb)
+{
+	dma_free_writecombine(&fb->dev->dev, fb->fb.fix.smem_len,
+			      fb->fb.screen_base, fb->fb.fix.smem_start);
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/fpga-irq.c linux-libre-2.6.39-gnu/arch/arm/plat-versatile/fpga-irq.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/fpga-irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/fpga-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ *  Support for Versatile FPGA-based IRQ controllers
+ */
+#include <linux/irq.h>
+#include <linux/io.h>
+
+#include <asm/mach/irq.h>
+#include <plat/fpga-irq.h>
+
+#define IRQ_STATUS		0x00
+#define IRQ_RAW_STATUS		0x04
+#define IRQ_ENABLE_SET		0x08
+#define IRQ_ENABLE_CLEAR	0x0c
+
+static void fpga_irq_mask(struct irq_data *d)
+{
+	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
+	u32 mask = 1 << (d->irq - f->irq_start);
+
+	writel(mask, f->base + IRQ_ENABLE_CLEAR);
+}
+
+static void fpga_irq_unmask(struct irq_data *d)
+{
+	struct fpga_irq_data *f = irq_data_get_irq_chip_data(d);
+	u32 mask = 1 << (d->irq - f->irq_start);
+
+	writel(mask, f->base + IRQ_ENABLE_SET);
+}
+
+static void fpga_irq_handle(unsigned int irq, struct irq_desc *desc)
+{
+	struct fpga_irq_data *f = irq_desc_get_handler_data(desc);
+	u32 status = readl(f->base + IRQ_STATUS);
+
+	if (status == 0) {
+		do_bad_IRQ(irq, desc);
+		return;
+	}
+
+	do {
+		irq = ffs(status) - 1;
+		status &= ~(1 << irq);
+
+		generic_handle_irq(irq + f->irq_start);
+	} while (status);
+}
+
+void __init fpga_irq_init(int parent_irq, u32 valid, struct fpga_irq_data *f)
+{
+	unsigned int i;
+
+	f->chip.irq_ack = fpga_irq_mask;
+	f->chip.irq_mask = fpga_irq_mask;
+	f->chip.irq_unmask = fpga_irq_unmask;
+
+	if (parent_irq != -1) {
+		irq_set_handler_data(parent_irq, f);
+		irq_set_chained_handler(parent_irq, fpga_irq_handle);
+	}
+
+	for (i = 0; i < 32; i++) {
+		if (valid & (1 << i)) {
+			unsigned int irq = f->irq_start + i;
+
+			irq_set_chip_data(irq, f);
+			irq_set_chip_and_handler(irq, &f->chip,
+						 handle_level_irq);
+			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
+		}
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/headsmp.S linux-libre-2.6.39-gnu/arch/arm/plat-versatile/headsmp.S
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/headsmp.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/headsmp.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ *  linux/arch/arm/plat-versatile/headsmp.S
+ *
+ *  Copyright (c) 2003 ARM Limited
+ *  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/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+
+/*
+ * Realview/Versatile Express specific entry point for secondary CPUs.
+ * This provides a "holding pen" into which all secondary cores are held
+ * until we're ready for them to initialise.
+ */
+ENTRY(versatile_secondary_startup)
+	mrc	p15, 0, r0, c0, c0, 5
+	and	r0, r0, #15
+	adr	r4, 1f
+	ldmia	r4, {r5, r6}
+	sub	r4, r4, r5
+	add	r6, r6, r4
+pen:	ldr	r7, [r6]
+	cmp	r7, r0
+	bne	pen
+
+	/*
+	 * we've been released from the holding pen: secondary_stack
+	 * should now contain the SVC stack for this core
+	 */
+	b	secondary_startup
+
+	.align
+1:	.long	.
+	.long	pen_release
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/include/plat/clcd.h linux-libre-2.6.39-gnu/arch/arm/plat-versatile/include/plat/clcd.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/include/plat/clcd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/include/plat/clcd.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,9 @@
+#ifndef PLAT_CLCD_H
+#define PLAT_CLCD_H
+
+struct clcd_panel *versatile_clcd_get_panel(const char *);
+int versatile_clcd_setup_dma(struct clcd_fb *, unsigned long);
+int versatile_clcd_mmap_dma(struct clcd_fb *, struct vm_area_struct *);
+void versatile_clcd_remove_dma(struct clcd_fb *);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/include/plat/fpga-irq.h linux-libre-2.6.39-gnu/arch/arm/plat-versatile/include/plat/fpga-irq.h
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/include/plat/fpga-irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/include/plat/fpga-irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef PLAT_FPGA_IRQ_H
+#define PLAT_FPGA_IRQ_H
+
+struct fpga_irq_data {
+	void __iomem *base;
+	unsigned int irq_start;
+	struct irq_chip chip;
+};
+
+void fpga_irq_init(int, u32, struct fpga_irq_data *);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/Kconfig linux-libre-2.6.39-gnu/arch/arm/plat-versatile/Kconfig
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+if PLAT_VERSATILE
+
+config PLAT_VERSATILE_CLCD
+	bool
+
+config PLAT_VERSATILE_FPGA_IRQ
+	bool
+
+config PLAT_VERSATILE_LEDS
+	def_bool y if LEDS_CLASS
+	depends on ARCH_REALVIEW || ARCH_VERSATILE
+
+config PLAT_VERSATILE_SCHED_CLOCK
+	def_bool y if !ARCH_INTEGRATOR_AP
+	select HAVE_SCHED_CLOCK
+
+endif
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/localtimer.c linux-libre-2.6.39-gnu/arch/arm/plat-versatile/localtimer.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/localtimer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/localtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ *  linux/arch/arm/plat-versatile/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/smp.h>
+#include <linux/clockchips.h>
+
+#include <asm/smp_twd.h>
+#include <asm/localtimer.h>
+#include <mach/irqs.h>
+
+/*
+ * Setup the local clock events for a CPU.
+ */
+int __cpuinit local_timer_setup(struct clock_event_device *evt)
+{
+	evt->irq = IRQ_LOCALTIMER;
+	twd_timer_setup(evt);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/Makefile linux-libre-2.6.39-gnu/arch/arm/plat-versatile/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,7 @@
 obj-y	:= clock.o
-ifneq ($(CONFIG_ARCH_INTEGRATOR),y)
-obj-y	+= sched-clock.o
-endif
-ifeq ($(CONFIG_LEDS_CLASS),y)
-obj-$(CONFIG_ARCH_REALVIEW) += leds.o
-obj-$(CONFIG_ARCH_VERSATILE) += leds.o
-endif
+obj-$(CONFIG_LOCAL_TIMERS) += localtimer.o
+obj-$(CONFIG_PLAT_VERSATILE_CLCD) += clcd.o
+obj-$(CONFIG_PLAT_VERSATILE_FPGA_IRQ) += fpga-irq.o
+obj-$(CONFIG_PLAT_VERSATILE_LEDS) += leds.o
+obj-$(CONFIG_PLAT_VERSATILE_SCHED_CLOCK) += sched-clock.o
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
diff -druN linux-libre-2.6.38-gnu/arch/arm/plat-versatile/platsmp.c linux-libre-2.6.39-gnu/arch/arm/plat-versatile/platsmp.c
--- linux-libre-2.6.38-gnu/arch/arm/plat-versatile/platsmp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/arm/plat-versatile/platsmp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ *  linux/arch/arm/plat-versatile/platsmp.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/errno.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/jiffies.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+
+/*
+ * control for which core is the next to come out of the secondary
+ * boot "holding pen"
+ */
+volatile int __cpuinitdata pen_release = -1;
+
+/*
+ * Write pen_release in a way that is guaranteed to be visible to all
+ * observers, irrespective of whether they're taking part in coherency
+ * or not.  This is necessary for the hotplug code to work reliably.
+ */
+static void __cpuinit write_pen_release(int val)
+{
+	pen_release = val;
+	smp_wmb();
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+}
+
+static DEFINE_SPINLOCK(boot_lock);
+
+void __cpuinit platform_secondary_init(unsigned int cpu)
+{
+	/*
+	 * 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_secondary_init(0);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	write_pen_release(-1);
+
+	/*
+	 * 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);
+
+	/*
+	 * This is really belt and braces; we hold unintended secondary
+	 * CPUs in the holding pen until we're ready for them.  However,
+	 * since we haven't sent them a soft interrupt, they shouldn't
+	 * be there.
+	 */
+	write_pen_release(cpu);
+
+	/*
+	 * Send the secondary CPU a soft interrupt, thereby causing
+	 * the boot monitor to read the system wide flags register,
+	 * and branch to the address found there.
+	 */
+	smp_cross_call(cpumask_of(cpu), 1);
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/arm/tools/mach-types linux-libre-2.6.39-gnu/arch/arm/tools/mach-types
--- linux-libre-2.6.38-gnu/arch/arm/tools/mach-types	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/tools/mach-types	2011-05-19 00:06:34.000000000 -0400
@@ -12,2745 +12,458 @@
 #
 #   http://www.arm.linux.org.uk/developer/machines/?action=new
 #
-# Last update: Mon Feb 7 08:59:27 2011
+# XXX: This is a cut-down version of the file; it contains only machines that
+# XXX: are in mainline or have been submitted to the machine database within
+# XXX: the last 12 months.  If your entry is missing please email rmk at
+# XXX: <linux@arm.linux.org.uk>
+#
+# Last update: Sun Mar 20 18:06:11 2011
 #
 # machine_is_xxx	CONFIG_xxxx		MACH_TYPE_xxx		number
 #
 ebsa110			ARCH_EBSA110		EBSA110			0
 riscpc			ARCH_RPC		RISCPC			1
-nexuspci		ARCH_NEXUSPCI		NEXUSPCI		3
 ebsa285			ARCH_EBSA285		EBSA285			4
 netwinder		ARCH_NETWINDER		NETWINDER		5
 cats			ARCH_CATS		CATS			6
-tbox			ARCH_TBOX		TBOX			7
-co285			ARCH_CO285		CO285			8
-clps7110		ARCH_CLPS7110		CLPS7110		9
-archimedes		ARCH_ARC		ARCHIMEDES		10
-a5k			ARCH_A5K		A5K			11
-etoile			ARCH_ETOILE		ETOILE			12
-lacie_nas		ARCH_LACIE_NAS		LACIE_NAS		13
-clps7500		ARCH_CLPS7500		CLPS7500		14
 shark			ARCH_SHARK		SHARK			15
 brutus			SA1100_BRUTUS		BRUTUS			16
 personal_server		ARCH_PERSONAL_SERVER	PERSONAL_SERVER		17
-itsy			SA1100_ITSY		ITSY			18
 l7200			ARCH_L7200		L7200			19
 pleb			SA1100_PLEB		PLEB			20
 integrator		ARCH_INTEGRATOR		INTEGRATOR		21
 h3600			SA1100_H3600		H3600			22
-ixp1200			ARCH_IXP1200		IXP1200			23
 p720t			ARCH_P720T		P720T			24
 assabet			SA1100_ASSABET		ASSABET			25
-victor			SA1100_VICTOR		VICTOR			26
 lart			SA1100_LART		LART			27
-ranger			SA1100_RANGER		RANGER			28
 graphicsclient		SA1100_GRAPHICSCLIENT	GRAPHICSCLIENT		29
 xp860			SA1100_XP860		XP860			30
 cerf			SA1100_CERF		CERF			31
 nanoengine		SA1100_NANOENGINE	NANOENGINE		32
-fpic			SA1100_FPIC		FPIC			33
-extenex1		SA1100_EXTENEX1		EXTENEX1		34
-sherman			SA1100_SHERMAN		SHERMAN			35
-accelent_sa		SA1100_ACCELENT		ACCELENT_SA		36
-accelent_l7200		ARCH_L7200_ACCELENT	ACCELENT_L7200		37
-netport			SA1100_NETPORT		NETPORT			38
-pangolin		SA1100_PANGOLIN		PANGOLIN		39
-yopy			SA1100_YOPY		YOPY			40
-coolidge		SA1100_COOLIDGE		COOLIDGE		41
-huw_webpanel		SA1100_HUW_WEBPANEL	HUW_WEBPANEL		42
-spotme			ARCH_SPOTME		SPOTME			43
-freebird		ARCH_FREEBIRD		FREEBIRD		44
-ti925			ARCH_TI925		TI925			45
-riscstation		ARCH_RISCSTATION	RISCSTATION		46
-cavy			SA1100_CAVY		CAVY			47
 jornada720		SA1100_JORNADA720	JORNADA720		48
-omnimeter		SA1100_OMNIMETER	OMNIMETER		49
 edb7211			ARCH_EDB7211		EDB7211			50
-citygo			SA1100_CITYGO		CITYGO			51
 pfs168			SA1100_PFS168		PFS168			52
-spot			SA1100_SPOT		SPOT			53
 flexanet		SA1100_FLEXANET		FLEXANET		54
-webpal			ARCH_WEBPAL		WEBPAL			55
-linpda			SA1100_LINPDA		LINPDA			56
-anakin			ARCH_ANAKIN		ANAKIN			57
-mvi			SA1100_MVI		MVI			58
-jupiter			SA1100_JUPITER		JUPITER			59
-psionw			ARCH_PSIONW		PSIONW			60
-aln			SA1100_ALN		ALN			61
-epxa			ARCH_CAMELOT		CAMELOT			62
-gds2200			SA1100_GDS2200		GDS2200			63
-netbook			SA1100_PSION_SERIES7	PSION_SERIES7		64
-xfile			SA1100_XFILE		XFILE			65
-accelent_ep9312		ARCH_ACCELENT_EP9312	ACCELENT_EP9312		66
-ic200			ARCH_IC200		IC200			67
-creditlart		SA1100_CREDITLART	CREDITLART		68
-htm			SA1100_HTM		HTM			69
-iq80310			ARCH_IQ80310		IQ80310			70
-freebot			SA1100_FREEBOT		FREEBOT			71
-entel			ARCH_ENTEL		ENTEL			72
-enp3510			ARCH_ENP3510		ENP3510			73
-trizeps			SA1100_TRIZEPS		TRIZEPS			74
-nesa			SA1100_NESA		NESA			75
-venus			ARCH_VENUS		VENUS			76
-tardis			ARCH_TARDIS		TARDIS			77
-mercury			ARCH_MERCURY		MERCURY			78
-empeg			SA1100_EMPEG		EMPEG			79
-adi_evb			ARCH_I80200FCC		I80200FCC		80
-itt_cpb			SA1100_ITT_CPB		ITT_CPB			81
-svc			SA1100_SVC		SVC			82
-alpha2			SA1100_ALPHA2		ALPHA2			84
-alpha1			SA1100_ALPHA1		ALPHA1			85
-netarm			ARCH_NETARM		NETARM			86
 simpad			SA1100_SIMPAD		SIMPAD			87
-pda1			ARCH_PDA1		PDA1			88
 lubbock			ARCH_LUBBOCK		LUBBOCK			89
-aniko			ARCH_ANIKO		ANIKO			90
 clep7212		ARCH_CLEP7212		CLEP7212		91
-cs89712			ARCH_CS89712		CS89712			92
-weararm			SA1100_WEARARM		WEARARM			93
-possio_px		SA1100_POSSIO_PX	POSSIO_PX		94
-sidearm			SA1100_SIDEARM		SIDEARM			95
-stork			SA1100_STORK		STORK			96
 shannon			SA1100_SHANNON		SHANNON			97
-ace			ARCH_ACE		ACE			98
-ballyarm		SA1100_BALLYARM		BALLYARM		99
-simputer		SA1100_SIMPUTER		SIMPUTER		100
-nexterm			SA1100_NEXTERM		NEXTERM			101
-sa1100_elf		SA1100_SA1100_ELF	SA1100_ELF		102
-gator			SA1100_GATOR		GATOR			103
-granite			ARCH_GRANITE		GRANITE			104
 consus			SA1100_CONSUS		CONSUS			105
 aaed2000		ARCH_AAED2000		AAED2000		106
 cdb89712		ARCH_CDB89712		CDB89712		107
 graphicsmaster		SA1100_GRAPHICSMASTER	GRAPHICSMASTER		108
 adsbitsy		SA1100_ADSBITSY		ADSBITSY		109
 pxa_idp			ARCH_PXA_IDP		PXA_IDP			110
-plce			ARCH_PLCE		PLCE			111
 pt_system3		SA1100_PT_SYSTEM3	PT_SYSTEM3		112
-murphy			ARCH_MEDALB		MEDALB			113
-eagle			ARCH_EAGLE		EAGLE			114
-dsc21			ARCH_DSC21		DSC21			115
-dsc24			ARCH_DSC24		DSC24			116
-ti5472			ARCH_TI5472		TI5472			117
 autcpu12		ARCH_AUTCPU12		AUTCPU12		118
-uengine			ARCH_UENGINE		UENGINE			119
-bluestem		SA1100_BLUESTEM		BLUESTEM		120
-xingu8			ARCH_XINGU8		XINGU8			121
-bushstb			ARCH_BUSHSTB		BUSHSTB			122
-epsilon1		SA1100_EPSILON1		EPSILON1		123
-balloon			SA1100_BALLOON		BALLOON			124
-puppy			ARCH_PUPPY		PUPPY			125
-elroy			SA1100_ELROY		ELROY			126
-gms720			ARCH_GMS720		GMS720			127
-s24x			ARCH_S24X		S24X			128
-jtel_clep7312		ARCH_JTEL_CLEP7312	JTEL_CLEP7312		129
-cx821xx			ARCH_CX821XX		CX821XX			130
-edb7312			ARCH_EDB7312		EDB7312			131
-bsa1110			SA1100_BSA1110		BSA1110			132
-powerpin		ARCH_POWERPIN		POWERPIN		133
-openarm			ARCH_OPENARM		OPENARM			134
-whitechapel		SA1100_WHITECHAPEL	WHITECHAPEL		135
 h3100			SA1100_H3100		H3100			136
-h3800			SA1100_H3800		H3800			137
-blue_v1			ARCH_BLUE_V1		BLUE_V1			138
-pxa_cerf		ARCH_PXA_CERF		PXA_CERF		139
-arm7tevb		ARCH_ARM7TEVB		ARM7TEVB		140
-d7400			SA1100_D7400		D7400			141
-piranha			ARCH_PIRANHA		PIRANHA			142
-sbcamelot		SA1100_SBCAMELOT	SBCAMELOT		143
-kings			SA1100_KINGS		KINGS			144
-smdk2400		ARCH_SMDK2400		SMDK2400		145
 collie			SA1100_COLLIE		COLLIE			146
-idr			ARCH_IDR		IDR			147
 badge4			SA1100_BADGE4		BADGE4			148
-webnet			ARCH_WEBNET		WEBNET			149
-d7300			SA1100_D7300		D7300			150
-cep			SA1100_CEP		CEP			151
 fortunet		ARCH_FORTUNET		FORTUNET		152
-vc547x			ARCH_VC547X		VC547X			153
-filewalker		SA1100_FILEWALKER	FILEWALKER		154
-netgateway		SA1100_NETGATEWAY	NETGATEWAY		155
-symbol2800		SA1100_SYMBOL2800	SYMBOL2800		156
-suns			SA1100_SUNS		SUNS			157
-frodo			SA1100_FRODO		FRODO			158
-ms301			SA1100_MACH_TYTE_MS301	MACH_TYTE_MS301		159
 mx1ads			ARCH_MX1ADS		MX1ADS			160
 h7201			ARCH_H7201		H7201			161
 h7202			ARCH_H7202		H7202			162
-amico			ARCH_AMICO		AMICO			163
-iam			SA1100_IAM		IAM			164
-tt530			SA1100_TT530		TT530			165
-sam2400			ARCH_SAM2400		SAM2400			166
-jornada56x		SA1100_JORNADA56X	JORNADA56X		167
-active			SA1100_ACTIVE		ACTIVE			168
 iq80321			ARCH_IQ80321		IQ80321			169
-wid			SA1100_WID		WID			170
-sabinal			ARCH_SABINAL		SABINAL			171
-ixp425_matacumbe	ARCH_IXP425_MATACUMBE	IXP425_MATACUMBE	172
-miniprint		SA1100_MINIPRINT	MINIPRINT		173
-adm510x			ARCH_ADM510X		ADM510X			174
-svs200			SA1100_SVS200		SVS200			175
-atg_tcu			ARCH_ATG_TCU		ATG_TCU			176
-jornada820		SA1100_JORNADA820	JORNADA820		177
-s3c44b0			ARCH_S3C44B0		S3C44B0			178
-margis2			ARCH_MARGIS2		MARGIS2			179
 ks8695			ARCH_KS8695		KS8695			180
-brh			ARCH_BRH		BRH			181
-s3c2410			ARCH_S3C2410		S3C2410			182
-possio_px30		ARCH_POSSIO_PX30	POSSIO_PX30		183
-s3c2800			ARCH_S3C2800		S3C2800			184
-fleetwood		SA1100_FLEETWOOD	FLEETWOOD		185
-omaha			ARCH_OMAHA		OMAHA			186
-ta7			ARCH_TA7		TA7			187
-nova			SA1100_NOVA		NOVA			188
-hmk			ARCH_HMK		HMK			189
-karo			ARCH_KARO		KARO			190
-fester			SA1100_FESTER		FESTER			191
-gpi			ARCH_GPI		GPI			192
 smdk2410		ARCH_SMDK2410		SMDK2410		193
-i519			ARCH_I519		I519			194
-nexio			SA1100_NEXIO		NEXIO			195
-bitbox			SA1100_BITBOX		BITBOX			196
-g200			SA1100_G200		G200			197
-gill			SA1100_GILL		GILL			198
-pxa_mercury		ARCH_PXA_MERCURY	PXA_MERCURY		199
 ceiva			ARCH_CEIVA		CEIVA			200
-fret			SA1100_FRET		FRET			201
-emailphone		SA1100_EMAILPHONE	EMAILPHONE		202
-h3900			ARCH_H3900		H3900			203
-pxa1			ARCH_PXA1		PXA1			204
-koan369			SA1100_KOAN369		KOAN369			205
-cogent			ARCH_COGENT		COGENT			206
-esl_simputer		ARCH_ESL_SIMPUTER	ESL_SIMPUTER		207
-esl_simputer_clr	ARCH_ESL_SIMPUTER_CLR	ESL_SIMPUTER_CLR	208
-esl_simputer_bw		ARCH_ESL_SIMPUTER_BW	ESL_SIMPUTER_BW		209
-hhp_cradle		ARCH_HHP_CRADLE		HHP_CRADLE		210
-he500			ARCH_HE500		HE500			211
-inhandelf2		SA1100_INHANDELF2	INHANDELF2		212
-inhandftip		SA1100_INHANDFTIP	INHANDFTIP		213
-dnp1110			SA1100_DNP1110		DNP1110			214
-pnp1110			SA1100_PNP1110		PNP1110			215
-csb226			ARCH_CSB226		CSB226			216
-arnold			SA1100_ARNOLD		ARNOLD			217
 voiceblue		MACH_VOICEBLUE		VOICEBLUE		218
-jz8028			ARCH_JZ8028		JZ8028			219
 h5400			ARCH_H5400		H5400			220
-forte			SA1100_FORTE		FORTE			221
-acam			SA1100_ACAM		ACAM			222
-abox			SA1100_ABOX		ABOX			223
-atmel			ARCH_ATMEL		ATMEL			224
-sitsang			ARCH_SITSANG		SITSANG			225
-cpu1110lcdnet		SA1100_CPU1110LCDNET	CPU1110LCDNET		226
-mpl_vcma9		ARCH_MPL_VCMA9		MPL_VCMA9		227
-opus_a1			ARCH_OPUS_A1		OPUS_A1			228
-daytona			ARCH_DAYTONA		DAYTONA			229
-killbear		SA1100_KILLBEAR		KILLBEAR		230
-yoho			ARCH_YOHO		YOHO			231
-jasper			ARCH_JASPER		JASPER			232
-dsc25			ARCH_DSC25		DSC25			233
 omap_innovator		MACH_OMAP_INNOVATOR	OMAP_INNOVATOR		234
-mnci			ARCH_RAMSES		RAMSES			235
-s28x			ARCH_S28X		S28X			236
-mport3			ARCH_MPORT3		MPORT3			237
-pxa_eagle250		ARCH_PXA_EAGLE250	PXA_EAGLE250		238
-pdb			ARCH_PDB		PDB			239
-blue_2g			SA1100_BLUE_2G		BLUE_2G			240
-bluearch		SA1100_BLUEARCH		BLUEARCH		241
 ixdp2400		ARCH_IXDP2400		IXDP2400		242
 ixdp2800		ARCH_IXDP2800		IXDP2800		243
-explorer		SA1100_EXPLORER		EXPLORER		244
 ixdp425			ARCH_IXDP425		IXDP425			245
-chimp			ARCH_CHIMP		CHIMP			246
-stork_nest		ARCH_STORK_NEST		STORK_NEST		247
-stork_egg		ARCH_STORK_EGG		STORK_EGG		248
-wismo			SA1100_WISMO		WISMO			249
-ezlinx			ARCH_EZLINX		EZLINX			250
-at91rm9200		ARCH_AT91RM9200		AT91RM9200		251
-adtech_orion		ARCH_ADTECH_ORION	ADTECH_ORION		252
-neptune			ARCH_NEPTUNE		NEPTUNE			253
 hackkit			SA1100_HACKKIT		HACKKIT			254
-pxa_wins30		ARCH_PXA_WINS30		PXA_WINS30		255
-lavinna			SA1100_LAVINNA		LAVINNA			256
-pxa_uengine		ARCH_PXA_UENGINE	PXA_UENGINE		257
-innokom			ARCH_INNOKOM		INNOKOM			258
-bms			ARCH_BMS		BMS			259
 ixcdp1100		ARCH_IXCDP1100		IXCDP1100		260
-prpmc1100		ARCH_PRPMC1100		PRPMC1100		261
 at91rm9200dk		ARCH_AT91RM9200DK	AT91RM9200DK		262
-armstick		ARCH_ARMSTICK		ARMSTICK		263
-armonie			ARCH_ARMONIE		ARMONIE			264
-mport1			ARCH_MPORT1		MPORT1			265
-s3c5410			ARCH_S3C5410		S3C5410			266
-zcp320a			ARCH_ZCP320A		ZCP320A			267
-i_box			ARCH_I_BOX		I_BOX			268
-stlc1502		ARCH_STLC1502		STLC1502		269
-siren			ARCH_SIREN		SIREN			270
-greenlake		ARCH_GREENLAKE		GREENLAKE		271
-argus			ARCH_ARGUS		ARGUS			272
-combadge		SA1100_COMBADGE		COMBADGE		273
-rokepxa			ARCH_ROKEPXA		ROKEPXA			274
 cintegrator		ARCH_CINTEGRATOR	CINTEGRATOR		275
-guidea07		ARCH_GUIDEA07		GUIDEA07		276
-tat257			ARCH_TAT257		TAT257			277
-igp2425			ARCH_IGP2425		IGP2425			278
-bluegrama		ARCH_BLUEGRAMMA		BLUEGRAMMA		279
-ipod			ARCH_IPOD		IPOD			280
-adsbitsyx		ARCH_ADSBITSYX		ADSBITSYX		281
-trizeps2		ARCH_TRIZEPS2		TRIZEPS2		282
 viper			ARCH_VIPER		VIPER			283
-adsbitsyplus		SA1100_ADSBITSYPLUS	ADSBITSYPLUS		284
-adsagc			SA1100_ADSAGC		ADSAGC			285
-stp7312			ARCH_STP7312		STP7312			286
-nx_phnx			MACH_NX_PHNX		NX_PHNX			287
-wep_ep250		ARCH_WEP_EP250		WEP_EP250		288
-inhandelf3		ARCH_INHANDELF3		INHANDELF3		289
 adi_coyote		ARCH_ADI_COYOTE		ADI_COYOTE		290
-iyonix			ARCH_IYONIX		IYONIX			291
-damicam1		ARCH_DAMICAM_SA1110	DAMICAM_SA1110		292
-meg03			ARCH_MEG03		MEG03			293
-pxa_whitechapel		ARCH_PXA_WHITECHAPEL	PXA_WHITECHAPEL		294
-nwsc			ARCH_NWSC		NWSC			295
-nwlarm			ARCH_NWLARM		NWLARM			296
-ixp425_mguard		ARCH_IXP425_MGUARD	IXP425_MGUARD		297
-pxa_netdcu4		ARCH_PXA_NETDCU4	PXA_NETDCU4		298
 ixdp2401		ARCH_IXDP2401		IXDP2401		299
 ixdp2801		ARCH_IXDP2801		IXDP2801		300
-zodiac			ARCH_ZODIAC		ZODIAC			301
-armmodul		ARCH_ARMMODUL		ARMMODUL		302
-ketop			SA1100_KETOP		KETOP			303
-av7200			ARCH_AV7200		AV7200			304
-arch_ti925		ARCH_ARCH_TI925		ARCH_TI925		305
-acq200			ARCH_ACQ200		ACQ200			306
-pt_dafit		SA1100_PT_DAFIT		PT_DAFIT		307
-ihba			ARCH_IHBA		IHBA			308
-quinque			ARCH_QUINQUE		QUINQUE			309
-nimbraone		ARCH_NIMBRAONE		NIMBRAONE		310
-nimbra29x		ARCH_NIMBRA29X		NIMBRA29X		311
-nimbra210		ARCH_NIMBRA210		NIMBRA210		312
-hhp_d95xx		ARCH_HHP_D95XX		HHP_D95XX		313
-labarm			ARCH_LABARM		LABARM			314
-m825xx			ARCH_M825XX		M825XX			315
-m7100			SA1100_M7100		M7100			316
-nipc2			ARCH_NIPC2		NIPC2			317
-fu7202			ARCH_FU7202		FU7202			318
-adsagx			ARCH_ADSAGX		ADSAGX			319
-pxa_pooh		ARCH_PXA_POOH		PXA_POOH		320
-bandon			ARCH_BANDON		BANDON			321
-pcm7210			ARCH_PCM7210		PCM7210			322
-nms9200			ARCH_NMS9200		NMS9200			323
-logodl			ARCH_LOGODL		LOGODL			324
-m7140			SA1100_M7140		M7140			325
-korebot			ARCH_KOREBOT		KOREBOT			326
 iq31244			ARCH_IQ31244		IQ31244			327
-koan393			SA1100_KOAN393		KOAN393			328
-inhandftip3		ARCH_INHANDFTIP3	INHANDFTIP3		329
-gonzo			ARCH_GONZO		GONZO			330
 bast			ARCH_BAST		BAST			331
-scanpass		ARCH_SCANPASS		SCANPASS		332
-ep7312_pooh		ARCH_EP7312_POOH	EP7312_POOH		333
-ta7s			ARCH_TA7S		TA7S			334
-ta7v			ARCH_TA7V		TA7V			335
-icarus			SA1100_ICARUS		ICARUS			336
-h1900			ARCH_H1900		H1900			337
-gemini			SA1100_GEMINI		GEMINI			338
-axim			ARCH_AXIM		AXIM			339
-audiotron		ARCH_AUDIOTRON		AUDIOTRON		340
-h2200			ARCH_H2200		H2200			341
-loox600			ARCH_LOOX600		LOOX600			342
-niop			ARCH_NIOP		NIOP			343
-dm310			ARCH_DM310		DM310			344
-seedpxa_c2		ARCH_SEEDPXA_C2		SEEDPXA_C2		345
-ixp4xx_mguardpci	ARCH_IXP4XX_MGUARD_PCI	IXP4XX_MGUARD_PCI	346
 h1940			ARCH_H1940		H1940			347
-scorpio			ARCH_SCORPIO		SCORPIO			348
-viva			ARCH_VIVA		VIVA			349
-pxa_xcard		ARCH_PXA_XCARD		PXA_XCARD		350
-csb335			ARCH_CSB335		CSB335			351
-ixrd425			ARCH_IXRD425		IXRD425			352
-iq80315			ARCH_IQ80315		IQ80315			353
-nmp7312			ARCH_NMP7312		NMP7312			354
-cx861xx			ARCH_CX861XX		CX861XX			355
 enp2611			ARCH_ENP2611		ENP2611			356
-xda			SA1100_XDA		XDA			357
-csir_ims		ARCH_CSIR_IMS		CSIR_IMS		358
-ixp421_dnaeeth		ARCH_IXP421_DNAEETH	IXP421_DNAEETH		359
-pocketserv9200		ARCH_POCKETSERV9200	POCKETSERV9200		360
-toto			ARCH_TOTO		TOTO			361
 s3c2440			ARCH_S3C2440		S3C2440			362
-ks8695p			ARCH_KS8695P		KS8695P			363
-se4000			ARCH_SE4000		SE4000			364
-quadriceps		ARCH_QUADRICEPS		QUADRICEPS		365
-bronco			ARCH_BRONCO		BRONCO			366
-esl_wireless_tab	ARCH_ESL_WIRELESS_TAB	ESL_WIRELESS_TAB	367
-esl_sofcomp		ARCH_ESL_SOFCOMP	ESL_SOFCOMP		368
-s5c7375			ARCH_S5C7375		S5C7375			369
-spearhead		ARCH_SPEARHEAD		SPEARHEAD		370
-pantera			ARCH_PANTERA		PANTERA			371
-prayoglite		ARCH_PRAYOGLITE		PRAYOGLITE		372
 gumstix			ARCH_GUMSTIX		GUMSTIX			373
-rcube			ARCH_RCUBE		RCUBE			374
-rea_olv			ARCH_REA_OLV		REA_OLV			375
-pxa_iphone		ARCH_PXA_IPHONE		PXA_IPHONE		376
-s3c3410			ARCH_S3C3410		S3C3410			377
-espd_4510b		ARCH_ESPD_4510B		ESPD_4510B		378
-mp1x			ARCH_MP1X		MP1X			379
-at91rm9200tb		ARCH_AT91RM9200TB	AT91RM9200TB		380
-adsvgx			ARCH_ADSVGX		ADSVGX			381
 omap_h2			MACH_OMAP_H2		OMAP_H2			382
-pelee			ARCH_PELEE		PELEE			383
 e740			MACH_E740		E740			384
 iq80331			ARCH_IQ80331		IQ80331			385
 versatile_pb		ARCH_VERSATILE_PB	VERSATILE_PB		387
 kev7a400		MACH_KEV7A400		KEV7A400		388
 lpd7a400		MACH_LPD7A400		LPD7A400		389
 lpd7a404		MACH_LPD7A404		LPD7A404		390
-fujitsu_camelot		ARCH_FUJITSU_CAMELOT	FUJITSU_CAMELOT		391
-janus2m			ARCH_JANUS2M		JANUS2M			392
-embtf			MACH_EMBTF		EMBTF			393
-hpm			MACH_HPM		HPM			394
-smdk2410tk		MACH_SMDK2410TK		SMDK2410TK		395
-smdk2410aj		MACH_SMDK2410AJ		SMDK2410AJ		396
-streetracer		MACH_STREETRACER	STREETRACER		397
-eframe			MACH_EFRAME		EFRAME			398
 csb337			MACH_CSB337		CSB337			399
-pxa_lark		MACH_PXA_LARK		PXA_LARK		400
-pxa_pnp2110		MACH_PNP2110		PNP2110			401
-tcc72x			MACH_TCC72X		TCC72X			402
-altair			MACH_ALTAIR		ALTAIR			403
-kc3			MACH_KC3		KC3			404
-sinteftd		MACH_SINTEFTD		SINTEFTD		405
 mainstone		MACH_MAINSTONE		MAINSTONE		406
-aday4x			MACH_ADAY4X		ADAY4X			407
-lite300			MACH_LITE300		LITE300			408
-s5c7376			MACH_S5C7376		S5C7376			409
-mt02			MACH_MT02		MT02			410
-mport3s			MACH_MPORT3S		MPORT3S			411
-ra_alpha		MACH_RA_ALPHA		RA_ALPHA		412
 xcep			MACH_XCEP		XCEP			413
 arcom_vulcan		MACH_ARCOM_VULCAN	ARCOM_VULCAN		414
-stargate		MACH_STARGATE		STARGATE		415
-armadilloj		MACH_ARMADILLOJ		ARMADILLOJ		416
-elroy_jack		MACH_ELROY_JACK		ELROY_JACK		417
-backend			MACH_BACKEND		BACKEND			418
-s5linbox		MACH_S5LINBOX		S5LINBOX		419
 nomadik			MACH_NOMADIK		NOMADIK			420
-ia_cpu_9200		MACH_IA_CPU_9200	IA_CPU_9200		421
-at91_bja1		MACH_AT91_BJA1		AT91_BJA1		422
 corgi			MACH_CORGI		CORGI			423
 poodle			MACH_POODLE		POODLE			424
-ten			MACH_TEN		TEN			425
-roverp5p		MACH_ROVERP5P		ROVERP5P		426
-sc2700			MACH_SC2700		SC2700			427
-ex_eagle		MACH_EX_EAGLE		EX_EAGLE		428
-nx_pxa12		MACH_NX_PXA12		NX_PXA12		429
-nx_pxa5			MACH_NX_PXA5		NX_PXA5			430
-blackboard2		MACH_BLACKBOARD2	BLACKBOARD2		431
-i819			MACH_I819		I819			432
-ixmb995e		MACH_IXMB995E		IXMB995E		433
-skyrider		MACH_SKYRIDER		SKYRIDER		434
-skyhawk			MACH_SKYHAWK		SKYHAWK			435
-enterprise		MACH_ENTERPRISE		ENTERPRISE		436
-dep2410			MACH_DEP2410		DEP2410			437
 armcore			MACH_ARMCORE		ARMCORE			438
-hobbit			MACH_HOBBIT		HOBBIT			439
-h7210			MACH_H7210		H7210			440
-pxa_netdcu5		MACH_PXA_NETDCU5	PXA_NETDCU5		441
-acc			MACH_ACC		ACC			442
-esl_sarva		MACH_ESL_SARVA		ESL_SARVA		443
-xm250			MACH_XM250		XM250			444
-t6tc1xb			MACH_T6TC1XB		T6TC1XB			445
-ess710			MACH_ESS710		ESS710			446
 mx31ads			MACH_MX31ADS		MX31ADS			447
 himalaya		MACH_HIMALAYA		HIMALAYA		448
-bolfenk			MACH_BOLFENK		BOLFENK			449
-at91rm9200kr		MACH_AT91RM9200KR	AT91RM9200KR		450
 edb9312			MACH_EDB9312		EDB9312			451
 omap_generic		MACH_OMAP_GENERIC	OMAP_GENERIC		452
-aximx3			MACH_AXIMX3		AXIMX3			453
-eb67xdip		MACH_EB67XDIP		EB67XDIP		454
-webtxs			MACH_WEBTXS		WEBTXS			455
-hawk			MACH_HAWK		HAWK			456
-ccat91sbc001		MACH_CCAT91SBC001	CCAT91SBC001		457
-expresso		MACH_EXPRESSO		EXPRESSO		458
-h4000			MACH_H4000		H4000			459
-dino			MACH_DINO		DINO			460
-ml675k			MACH_ML675K		ML675K			461
 edb9301			MACH_EDB9301		EDB9301			462
 edb9315			MACH_EDB9315		EDB9315			463
-reciva_tt		MACH_RECIVA_TT		RECIVA_TT		464
-cstcb01			MACH_CSTCB01		CSTCB01			465
-cstcb1			MACH_CSTCB1		CSTCB1			466
-shadwell		MACH_SHADWELL		SHADWELL		467
-goepel263		MACH_GOEPEL263		GOEPEL263		468
-acq100			MACH_ACQ100		ACQ100			469
-mx1fs2			MACH_MX1FS2		MX1FS2			470
-hiptop_g1		MACH_HIPTOP_G1		HIPTOP_G1		471
-sparky			MACH_SPARKY		SPARKY			472
-ns9750			MACH_NS9750		NS9750			473
-phoenix			MACH_PHOENIX		PHOENIX			474
 vr1000			MACH_VR1000		VR1000			475
-deisterpxa		MACH_DEISTERPXA		DEISTERPXA		476
-bcm1160			MACH_BCM1160		BCM1160			477
-pcm022			MACH_PCM022		PCM022			478
-adsgcx			MACH_ADSGCX		ADSGCX			479
-dreadnaught		MACH_DREADNAUGHT	DREADNAUGHT		480
-dm320			MACH_DM320		DM320			481
-markov			MACH_MARKOV		MARKOV			482
-cos7a400		MACH_COS7A400		COS7A400		483
-milano			MACH_MILANO		MILANO			484
-ue9328			MACH_UE9328		UE9328			485
-uex255			MACH_UEX255		UEX255			486
-ue2410			MACH_UE2410		UE2410			487
-a620			MACH_A620		A620			488
-ocelot			MACH_OCELOT		OCELOT			489
-cheetah			MACH_CHEETAH		CHEETAH			490
 omap_perseus2		MACH_OMAP_PERSEUS2	OMAP_PERSEUS2		491
-zvue			MACH_ZVUE		ZVUE			492
-roverp1			MACH_ROVERP1		ROVERP1			493
-asidial2		MACH_ASIDIAL2		ASIDIAL2		494
-s3c24a0			MACH_S3C24A0		S3C24A0			495
 e800			MACH_E800		E800			496
 e750			MACH_E750		E750			497
-s3c5500			MACH_S3C5500		S3C5500			498
-smdk5500		MACH_SMDK5500		SMDK5500		499
-signalsync		MACH_SIGNALSYNC		SIGNALSYNC		500
-nbc			MACH_NBC		NBC			501
-kodiak			MACH_KODIAK		KODIAK			502
-netbookpro		MACH_NETBOOKPRO		NETBOOKPRO		503
-hw90200			MACH_HW90200		HW90200			504
-condor			MACH_CONDOR		CONDOR			505
-cup			MACH_CUP		CUP			506
-kite			MACH_KITE		KITE			507
 scb9328			MACH_SCB9328		SCB9328			508
 omap_h3			MACH_OMAP_H3		OMAP_H3			509
 omap_h4			MACH_OMAP_H4		OMAP_H4			510
-n10			MACH_N10		N10			511
-montejade		MACH_MONTAJADE		MONTAJADE		512
-sg560			MACH_SG560		SG560			513
-dp1000			MACH_DP1000		DP1000			514
 omap_osk		MACH_OMAP_OSK		OMAP_OSK		515
-rg100v3			MACH_RG100V3		RG100V3			516
-mx2ads			MACH_MX2ADS		MX2ADS			517
-pxa_kilo		MACH_PXA_KILO		PXA_KILO		518
-ixp4xx_eagle		MACH_IXP4XX_EAGLE	IXP4XX_EAGLE		519
 tosa			MACH_TOSA		TOSA			520
-mb2520f			MACH_MB2520F		MB2520F			521
-emc1000			MACH_EMC1000		EMC1000			522
-tidsc25			MACH_TIDSC25		TIDSC25			523
-akcpmxl			MACH_AKCPMXL		AKCPMXL			524
-av3xx			MACH_AV3XX		AV3XX			525
 avila			MACH_AVILA		AVILA			526
-pxa_mpm10		MACH_PXA_MPM10		PXA_MPM10		527
-pxa_kyanite		MACH_PXA_KYANITE	PXA_KYANITE		528
-sgold			MACH_SGOLD		SGOLD			529
-oscar			MACH_OSCAR		OSCAR			530
-epxa4usb2		MACH_EPXA4USB2		EPXA4USB2		531
-xsengine		MACH_XSENGINE		XSENGINE		532
-ip600			MACH_IP600		IP600			533
-mcan2			MACH_MCAN2		MCAN2			534
-ddi_blueridge		MACH_DDI_BLUERIDGE	DDI_BLUERIDGE		535
-skyminder		MACH_SKYMINDER		SKYMINDER		536
-lpd79520		MACH_LPD79520		LPD79520		537
 edb9302			MACH_EDB9302		EDB9302			538
-hw90340			MACH_HW90340		HW90340			539
-cip_box			MACH_CIP_BOX		CIP_BOX			540
-ivpn			MACH_IVPN		IVPN			541
-rsoc2			MACH_RSOC2		RSOC2			542
 husky			MACH_HUSKY		HUSKY			543
-boxer			MACH_BOXER		BOXER			544
 shepherd		MACH_SHEPHERD		SHEPHERD		545
-aml42800aa		MACH_AML42800AA		AML42800AA		546
-lpc2294			MACH_LPC2294		LPC2294			548
-switchgrass		MACH_SWITCHGRASS	SWITCHGRASS		549
-ens_cmu			MACH_ENS_CMU		ENS_CMU			550
-mm6_sdb			MACH_MM6_SDB		MM6_SDB			551
-saturn			MACH_SATURN		SATURN			552
-i30030evb		MACH_I30030EVB		I30030EVB		553
-mxc27530evb		MACH_MXC27530EVB	MXC27530EVB		554
-smdk2800		MACH_SMDK2800		SMDK2800		555
-mtwilson		MACH_MTWILSON		MTWILSON		556
-ziti			MACH_ZITI		ZITI			557
-grandfather		MACH_GRANDFATHER	GRANDFATHER		558
-tengine			MACH_TENGINE		TENGINE			559
-s3c2460			MACH_S3C2460		S3C2460			560
-pdm			MACH_PDM		PDM			561
 h4700			MACH_H4700		H4700			562
-h6300			MACH_H6300		H6300			563
-rz1700			MACH_RZ1700		RZ1700			564
-a716			MACH_A716		A716			565
-estk2440a		MACH_ESTK2440A		ESTK2440A		566
-atwixp425		MACH_ATWIXP425		ATWIXP425		567
-csb336			MACH_CSB336		CSB336			568
-rirm2			MACH_RIRM2		RIRM2			569
-cx23518			MACH_CX23518		CX23518			570
-cx2351x			MACH_CX2351X		CX2351X			571
-computime		MACH_COMPUTIME		COMPUTIME		572
-izarus			MACH_IZARUS		IZARUS			573
-pxa_rts			MACH_RTS		RTS			574
-se5100			MACH_SE5100		SE5100			575
-s3c2510			MACH_S3C2510		S3C2510			576
-csb437tl		MACH_CSB437TL		CSB437TL		577
-slauson			MACH_SLAUSON		SLAUSON			578
-pearlriver		MACH_PEARLRIVER		PEARLRIVER		579
-tdc_p210		MACH_TDC_P210		TDC_P210		580
-sg580			MACH_SG580		SG580			581
-wrsbcarm7		MACH_WRSBCARM7		WRSBCARM7		582
-ipd			MACH_IPD		IPD			583
-pxa_dnp2110		MACH_PXA_DNP2110	PXA_DNP2110		584
-xaeniax			MACH_XAENIAX		XAENIAX			585
-somn4250		MACH_SOMN4250		SOMN4250		586
-pleb2			MACH_PLEB2		PLEB2			587
-cornwallis		MACH_CORNWALLIS		CORNWALLIS		588
-gurney_drv		MACH_GURNEY_DRV		GURNEY_DRV		589
-chaffee			MACH_CHAFFEE		CHAFFEE			590
-rms101			MACH_RMS101		RMS101			591
 rx3715			MACH_RX3715		RX3715			592
-swift			MACH_SWIFT		SWIFT			593
-roverp7			MACH_ROVERP7		ROVERP7			594
-pr818s			MACH_PR818S		PR818S			595
-trxpro			MACH_TRXPRO		TRXPRO			596
 nslu2			MACH_NSLU2		NSLU2			597
 e400			MACH_E400		E400			598
-trab			MACH_TRAB		TRAB			599
-cmc_pu2			MACH_CMC_PU2		CMC_PU2			600
-fulcrum			MACH_FULCRUM		FULCRUM			601
-netgate42x		MACH_NETGATE42X		NETGATE42X		602
-str710			MACH_STR710		STR710			603
 ixdpg425		MACH_IXDPG425		IXDPG425		604
-tomtomgo		MACH_TOMTOMGO		TOMTOMGO		605
 versatile_ab		MACH_VERSATILE_AB	VERSATILE_AB		606
 edb9307			MACH_EDB9307		EDB9307			607
-sg565			MACH_SG565		SG565			608
-lpd79524		MACH_LPD79524		LPD79524		609
-lpd79525		MACH_LPD79525		LPD79525		610
-rms100			MACH_RMS100		RMS100			611
 kb9200			MACH_KB9200		KB9200			612
 sx1			MACH_SX1		SX1			613
-hms39c7092		MACH_HMS39C7092		HMS39C7092		614
-armadillo		MACH_ARMADILLO		ARMADILLO		615
-ipcu			MACH_IPCU		IPCU			616
-loox720			MACH_LOOX720		LOOX720			617
 ixdp465			MACH_IXDP465		IXDP465			618
 ixdp2351		MACH_IXDP2351		IXDP2351		619
-adsvix			MACH_ADSVIX		ADSVIX			620
-dm270			MACH_DM270		DM270			621
-socltplus		MACH_SOCLTPLUS		SOCLTPLUS		622
-ecia			MACH_ECIA		ECIA			623
-cm4008			MACH_CM4008		CM4008			624
-p2001			MACH_P2001		P2001			625
-twister			MACH_TWISTER		TWISTER			626
-mudshark		MACH_MUDSHARK		MUDSHARK		627
-hb2			MACH_HB2		HB2			628
 iq80332			MACH_IQ80332		IQ80332			629
-sendt			MACH_SENDT		SENDT			630
-mx2jazz			MACH_MX2JAZZ		MX2JAZZ			631
-multiio			MACH_MULTIIO		MULTIIO			632
-hrdisplay		MACH_HRDISPLAY		HRDISPLAY		633
-mxc27530ads		MACH_MXC27530ADS	MXC27530ADS		634
-trizeps3		MACH_TRIZEPS3		TRIZEPS3		635
-zefeerdza		MACH_ZEFEERDZA		ZEFEERDZA		636
-zefeerdzb		MACH_ZEFEERDZB		ZEFEERDZB		637
-zefeerdzg		MACH_ZEFEERDZG		ZEFEERDZG		638
-zefeerdzn		MACH_ZEFEERDZN		ZEFEERDZN		639
-zefeerdzq		MACH_ZEFEERDZQ		ZEFEERDZQ		640
 gtwx5715		MACH_GTWX5715		GTWX5715		641
-astro_jack		MACH_ASTRO_JACK		ASTRO_JACK		643
-tip03			MACH_TIP03		TIP03			644
-a9200ec			MACH_A9200EC		A9200EC			645
-pnx0105			MACH_PNX0105		PNX0105			646
-adcpoecpu		MACH_ADCPOECPU		ADCPOECPU		647
 csb637			MACH_CSB637		CSB637			648
-mb9200			MACH_MB9200		MB9200			650
-kulun			MACH_KULUN		KULUN			651
-snapper			MACH_SNAPPER		SNAPPER			652
-optima			MACH_OPTIMA		OPTIMA			653
-dlhsbc			MACH_DLHSBC		DLHSBC			654
-x30			MACH_X30		X30			655
 n30			MACH_N30		N30			656
-manga_ks8695		MACH_MANGA_KS8695	MANGA_KS8695		657
-ajax			MACH_AJAX		AJAX			658
 nec_mp900		MACH_NEC_MP900		NEC_MP900		659
-vvtk1000		MACH_VVTK1000		VVTK1000		661
 kafa			MACH_KAFA		KAFA			662
-vvtk3000		MACH_VVTK3000		VVTK3000		663
-pimx1			MACH_PIMX1		PIMX1			664
-ollie			MACH_OLLIE		OLLIE			665
-skymax			MACH_SKYMAX		SKYMAX			666
-jazz			MACH_JAZZ		JAZZ			667
-tel_t3			MACH_TEL_T3		TEL_T3			668
-aisino_fcr255		MACH_AISINO_FCR255	AISINO_FCR255		669
-btweb			MACH_BTWEB		BTWEB			670
-dbg_lh79520		MACH_DBG_LH79520	DBG_LH79520		671
-cm41xx			MACH_CM41XX		CM41XX			672
 ts72xx			MACH_TS72XX		TS72XX			673
-nggpxa			MACH_NGGPXA		NGGPXA			674
-csb535			MACH_CSB535		CSB535			675
-csb536			MACH_CSB536		CSB536			676
-pxa_trakpod		MACH_PXA_TRAKPOD	PXA_TRAKPOD		677
-praxis			MACH_PRAXIS		PRAXIS			678
-lh75411			MACH_LH75411		LH75411			679
 otom			MACH_OTOM		OTOM			680
 nexcoder_2440		MACH_NEXCODER_2440	NEXCODER_2440		681
-loox410			MACH_LOOX410		LOOX410			682
-westlake		MACH_WESTLAKE		WESTLAKE		683
-nsb			MACH_NSB		NSB			684
-esl_sarva_stn		MACH_ESL_SARVA_STN	ESL_SARVA_STN		685
-esl_sarva_tft		MACH_ESL_SARVA_TFT	ESL_SARVA_TFT		686
-esl_sarva_iad		MACH_ESL_SARVA_IAD	ESL_SARVA_IAD		687
-esl_sarva_acc		MACH_ESL_SARVA_ACC	ESL_SARVA_ACC		688
-typhoon			MACH_TYPHOON		TYPHOON			689
-cnav			MACH_CNAV		CNAV			690
-a730			MACH_A730		A730			691
-netstar			MACH_NETSTAR		NETSTAR			692
-supercon		MACH_PHASEFALE_SUPERCON	PHASEFALE_SUPERCON	693
-shiva1100		MACH_SHIVA1100		SHIVA1100		694
-etexsc			MACH_ETEXSC		ETEXSC			695
-ixdpg465		MACH_IXDPG465		IXDPG465		696
-a9m2410			MACH_A9M2410		A9M2410			697
-a9m2440			MACH_A9M2440		A9M2440			698
-a9m9750			MACH_A9M9750		A9M9750			699
-a9m9360			MACH_A9M9360		A9M9360			700
-unc90			MACH_UNC90		UNC90			701
 eco920			MACH_ECO920		ECO920			702
-satview			MACH_SATVIEW		SATVIEW			703
 roadrunner		MACH_ROADRUNNER		ROADRUNNER		704
 at91rm9200ek		MACH_AT91RM9200EK	AT91RM9200EK		705
-gp32			MACH_GP32		GP32			706
-gem			MACH_GEM		GEM			707
-i858			MACH_I858		I858			708
-hx2750			MACH_HX2750		HX2750			709
-mxc91131evb		MACH_MXC91131EVB	MXC91131EVB		710
-p700			MACH_P700		P700			711
-cpe			MACH_CPE		CPE			712
 spitz			MACH_SPITZ		SPITZ			713
-nimbra340		MACH_NIMBRA340		NIMBRA340		714
-lpc22xx			MACH_LPC22XX		LPC22XX			715
-omap_comet3		MACH_COMET3		COMET3			716
-omap_comet4		MACH_COMET4		COMET4			717
-csb625			MACH_CSB625		CSB625			718
-fortunet2		MACH_FORTUNET2		FORTUNET2		719
-s5h2200			MACH_S5H2200		S5H2200			720
-optorm920		MACH_OPTORM920		OPTORM920		721
-adsbitsyxb		MACH_ADSBITSYXB		ADSBITSYXB		722
 adssphere		MACH_ADSSPHERE		ADSSPHERE		723
-adsportal		MACH_ADSPORTAL		ADSPORTAL		724
-ln2410sbc		MACH_LN2410SBC		LN2410SBC		725
-cb3rufc			MACH_CB3RUFC		CB3RUFC			726
-mp2usb			MACH_MP2USB		MP2USB			727
-ntnp425c		MACH_NTNP425C		NTNP425C		728
 colibri			MACH_COLIBRI		COLIBRI			729
-pcm7220			MACH_PCM7220		PCM7220			730
 gateway7001		MACH_GATEWAY7001	GATEWAY7001		731
 pcm027			MACH_PCM027		PCM027			732
-cmpxa			MACH_CMPXA		CMPXA			733
 anubis			MACH_ANUBIS		ANUBIS			734
-ite8152			MACH_ITE8152		ITE8152			735
-lpc3xxx			MACH_LPC3XXX		LPC3XXX			736
-puppeteer		MACH_PUPPETEER		PUPPETEER		737
-e570			MACH_E570		E570			739
-x50			MACH_X50		X50			740
-recon			MACH_RECON		RECON			741
-xboardgp8		MACH_XBOARDGP8		XBOARDGP8		742
-fpic2			MACH_FPIC2		FPIC2			743
 akita			MACH_AKITA		AKITA			744
-a81			MACH_A81		A81			745
-svm_sc25x		MACH_SVM_SC25X		SVM_SC25X		746
-vt020			MACH_VADATECH020	VADATECH020		747
-tli			MACH_TLI		TLI			748
-edb9315lc		MACH_EDB9315LC		EDB9315LC		749
-passec			MACH_PASSEC		PASSEC			750
-ds_tiger		MACH_DS_TIGER		DS_TIGER		751
-e310			MACH_E310		E310			752
 e330			MACH_E330		E330			753
-rt3000			MACH_RT3000		RT3000			754
 nokia770		MACH_NOKIA770		NOKIA770		755
-pnx0106			MACH_PNX0106		PNX0106			756
-hx21xx			MACH_HX21XX		HX21XX			757
-faraday			MACH_FARADAY		FARADAY			758
-sbc9312			MACH_SBC9312		SBC9312			759
-batman			MACH_BATMAN		BATMAN			760
-jpd201			MACH_JPD201		JPD201			761
-mipsa			MACH_MIPSA		MIPSA			762
-kacom			MACH_KACOM		KACOM			763
-swarcocpu		MACH_SWARCOCPU		SWARCOCPU		764
-swarcodsl		MACH_SWARCODSL		SWARCODSL		765
-blueangel		MACH_BLUEANGEL		BLUEANGEL		766
-hairygrama		MACH_HAIRYGRAMA		HAIRYGRAMA		767
-banff			MACH_BANFF		BANFF			768
 carmeva			MACH_CARMEVA		CARMEVA			769
-sam255			MACH_SAM255		SAM255			770
-ppm10			MACH_PPM10		PPM10			771
 edb9315a		MACH_EDB9315A		EDB9315A		772
-sunset			MACH_SUNSET		SUNSET			773
 stargate2		MACH_STARGATE2		STARGATE2		774
 intelmote2		MACH_INTELMOTE2		INTELMOTE2		775
 trizeps4		MACH_TRIZEPS4		TRIZEPS4		776
-mainstone2		MACH_MAINSTONE2		MAINSTONE2		777
-ez_ixp42x		MACH_EZ_IXP42X		EZ_IXP42X		778
-tapwave_zodiac		MACH_TAPWAVE_ZODIAC	TAPWAVE_ZODIAC		779
-universalmeter		MACH_UNIVERSALMETER	UNIVERSALMETER		780
-hicoarm9		MACH_HICOARM9		HICOARM9		781
 pnx4008			MACH_PNX4008		PNX4008			782
-kws6000			MACH_KWS6000		KWS6000			783
-portux920t		MACH_PORTUX920T		PORTUX920T		784
-ez_x5			MACH_EZ_X5		EZ_X5			785
-omap_rudolph		MACH_OMAP_RUDOLPH	OMAP_RUDOLPH		786
 cpuat91			MACH_CPUAT91		CPUAT91			787
-rea9200			MACH_REA9200		REA9200			788
-acts_pune_sa1110	MACH_ACTS_PUNE_SA1110	ACTS_PUNE_SA1110	789
-ixp425			MACH_IXP425		IXP425			790
-i30030ads		MACH_I30030ADS		I30030ADS		791
-perch			MACH_PERCH		PERCH			792
-eis05r1			MACH_EIS05R1		EIS05R1			793
-pepperpad		MACH_PEPPERPAD		PEPPERPAD		794
-sb3010			MACH_SB3010		SB3010			795
-rm9200			MACH_RM9200		RM9200			796
-dma03			MACH_DMA03		DMA03			797
-road_s101		MACH_ROAD_S101		ROAD_S101		798
 iq81340sc		MACH_IQ81340SC		IQ81340SC		799
-iq_nextgen_b		MACH_IQ_NEXTGEN_B	IQ_NEXTGEN_B		800
 iq81340mc		MACH_IQ81340MC		IQ81340MC		801
-iq_nextgen_d		MACH_IQ_NEXTGEN_D	IQ_NEXTGEN_D		802
-iq_nextgen_e		MACH_IQ_NEXTGEN_E	IQ_NEXTGEN_E		803
-mallow_at91		MACH_MALLOW_AT91	MALLOW_AT91		804
-cybertracker_i		MACH_CYBERTRACKER_I	CYBERTRACKER_I		805
-gesbc931x		MACH_GESBC931X		GESBC931X		806
-centipad		MACH_CENTIPAD		CENTIPAD		807
-armsoc			MACH_ARMSOC		ARMSOC			808
-se4200			MACH_SE4200		SE4200			809
-ems197a			MACH_EMS197A		EMS197A			810
 micro9			MACH_MICRO9		MICRO9			811
 micro9l			MACH_MICRO9L		MICRO9L			812
-uc5471dsp		MACH_UC5471DSP		UC5471DSP		813
-sj5471eng		MACH_SJ5471ENG		SJ5471ENG		814
-none			MACH_CMPXA26X		CMPXA26X		815
-nc1			MACH_NC			NC			816
 omap_palmte		MACH_OMAP_PALMTE	OMAP_PALMTE		817
-ajax52x			MACH_AJAX52X		AJAX52X			818
-siriustar		MACH_SIRIUSTAR		SIRIUSTAR		819
-iodata_hdlg		MACH_IODATA_HDLG	IODATA_HDLG		820
-at91rm9200utl		MACH_AT91RM9200UTL	AT91RM9200UTL		821
-biosafe			MACH_BIOSAFE		BIOSAFE			822
-mp1000			MACH_MP1000		MP1000			823
-parsy			MACH_PARSY		PARSY			824
-ccxp270			MACH_CCXP		CCXP			825
-omap_gsample		MACH_OMAP_GSAMPLE	OMAP_GSAMPLE		826
 realview_eb		MACH_REALVIEW_EB	REALVIEW_EB		827
-samoa			MACH_SAMOA		SAMOA			828
-palmt3			MACH_PALMT3		PALMT3			829
-i878			MACH_I878		I878			830
 borzoi			MACH_BORZOI		BORZOI			831
-gecko			MACH_GECKO		GECKO			832
-ds101			MACH_DS101		DS101			833
-omap_palmtt2		MACH_OMAP_PALMTT2	OMAP_PALMTT2		834
 palmld			MACH_PALMLD		PALMLD			835
-cc9c			MACH_CC9C		CC9C			836
-sbc1670			MACH_SBC1670		SBC1670			837
 ixdp28x5		MACH_IXDP28X5		IXDP28X5		838
 omap_palmtt		MACH_OMAP_PALMTT	OMAP_PALMTT		839
-ml696k			MACH_ML696K		ML696K			840
 arcom_zeus		MACH_ARCOM_ZEUS		ARCOM_ZEUS		841
 osiris			MACH_OSIRIS		OSIRIS			842
-maestro			MACH_MAESTRO		MAESTRO			843
 palmte2			MACH_PALMTE2		PALMTE2			844
-ixbbm			MACH_IXBBM		IXBBM			845
 mx27ads			MACH_MX27ADS		MX27ADS			846
-ax8004			MACH_AX8004		AX8004			847
 at91sam9261ek		MACH_AT91SAM9261EK	AT91SAM9261EK		848
 loft			MACH_LOFT		LOFT			849
-magpie			MACH_MAGPIE		MAGPIE			850
 mx21ads			MACH_MX21ADS		MX21ADS			851
-mb87m3400		MACH_MB87M3400		MB87M3400		852
-mguard_delta		MACH_MGUARD_DELTA	MGUARD_DELTA		853
-davinci_dvdp		MACH_DAVINCI_DVDP	DAVINCI_DVDP		854
-htcuniversal		MACH_HTCUNIVERSAL	HTCUNIVERSAL		855
-tpad			MACH_TPAD		TPAD			856
-roverp3			MACH_ROVERP3		ROVERP3			857
-jornada928		MACH_JORNADA928		JORNADA928		858
-mv88fxx81		MACH_MV88FXX81		MV88FXX81		859
-stmp36xx		MACH_STMP36XX		STMP36XX		860
-sxni79524		MACH_SXNI79524		SXNI79524		861
 ams_delta		MACH_AMS_DELTA		AMS_DELTA		862
-uranium			MACH_URANIUM		URANIUM			863
-ucon			MACH_UCON		UCON			864
 nas100d			MACH_NAS100D		NAS100D			865
-l083			MACH_L083_1000		L083_1000		866
-ezx			MACH_EZX		EZX			867
-pnx5220			MACH_PNX5220		PNX5220			868
-butte			MACH_BUTTE		BUTTE			869
-srm2			MACH_SRM2		SRM2			870
-dsbr			MACH_DSBR		DSBR			871
-crystalball		MACH_CRYSTALBALL	CRYSTALBALL		872
-tinypxa27x		MACH_TINYPXA27X		TINYPXA27X		873
-herbie			MACH_HERBIE		HERBIE			874
 magician		MACH_MAGICIAN		MAGICIAN		875
-cm4002			MACH_CM4002		CM4002			876
-b4			MACH_B4			B4			877
-maui			MACH_MAUI		MAUI			878
-cybertracker_g		MACH_CYBERTRACKER_G	CYBERTRACKER_G		879
 nxdkn			MACH_NXDKN		NXDKN			880
-mio8390			MACH_MIO8390		MIO8390			881
-omi_board		MACH_OMI_BOARD		OMI_BOARD		882
-mx21civ			MACH_MX21CIV		MX21CIV			883
-mahi_cdac		MACH_MAHI_CDAC		MAHI_CDAC		884
 palmtx			MACH_PALMTX		PALMTX			885
 s3c2413			MACH_S3C2413		S3C2413			887
-samsys_ep0		MACH_SAMSYS_EP0		SAMSYS_EP0		888
-wg302v1			MACH_WG302V1		WG302V1			889
 wg302v2			MACH_WG302V2		WG302V2			890
-eb42x			MACH_EB42X		EB42X			891
-iq331es			MACH_IQ331ES		IQ331ES			892
-cosydsp			MACH_COSYDSP		COSYDSP			893
-uplat7d_proto		MACH_UPLAT7D		UPLAT7D			894
-ptdavinci		MACH_PTDAVINCI		PTDAVINCI		895
-mbus			MACH_MBUS		MBUS			896
-nadia2vb		MACH_NADIA2VB		NADIA2VB		897
-r1000			MACH_R1000		R1000			898
-hw90250			MACH_HW90250		HW90250			899
 omap_2430sdp		MACH_OMAP_2430SDP	OMAP_2430SDP		900
 davinci_evm		MACH_DAVINCI_EVM	DAVINCI_EVM		901
-omap_tornado		MACH_OMAP_TORNADO	OMAP_TORNADO		902
-olocreek		MACH_OLOCREEK		OLOCREEK		903
 palmz72			MACH_PALMZ72		PALMZ72			904
 nxdb500			MACH_NXDB500		NXDB500			905
-apf9328			MACH_APF9328		APF9328			906
-omap_wipoq		MACH_OMAP_WIPOQ		OMAP_WIPOQ		907
-omap_twip		MACH_OMAP_TWIP		OMAP_TWIP		908
-treo650			MACH_TREO650		TREO650			909
-acumen			MACH_ACUMEN		ACUMEN			910
-xp100			MACH_XP100		XP100			911
-fs2410			MACH_FS2410		FS2410			912
-pxa270_cerf		MACH_PXA270_CERF	PXA270_CERF		913
-sq2ftlpalm		MACH_SQ2FTLPALM		SQ2FTLPALM		914
-bsemserver		MACH_BSEMSERVER		BSEMSERVER		915
-netclient		MACH_NETCLIENT		NETCLIENT		916
 palmt5			MACH_PALMT5		PALMT5			917
 palmtc			MACH_PALMTC		PALMTC			918
 omap_apollon		MACH_OMAP_APOLLON	OMAP_APOLLON		919
-mxc30030evb		MACH_MXC30030EVB	MXC30030EVB		920
-rea_cpu2		MACH_REA_2D		REA_2D			921
-eti3e524		MACH_TI3E524		TI3E524			922
 ateb9200		MACH_ATEB9200		ATEB9200		923
-auckland		MACH_AUCKLAND		AUCKLAND		924
-ak3220m			MACH_AK3320M		AK3320M			925
-duramax			MACH_DURAMAX		DURAMAX			926
 n35			MACH_N35		N35			927
-pronghorn		MACH_PRONGHORN		PRONGHORN		928
-fundy			MACH_FUNDY		FUNDY			929
 logicpd_pxa270		MACH_LOGICPD_PXA270	LOGICPD_PXA270		930
-cpu777			MACH_CPU777		CPU777			931
-simicon9201		MACH_SIMICON9201	SIMICON9201		932
-leap2_hpm		MACH_LEAP2_HPM		LEAP2_HPM		933
-cm922txa10		MACH_CM922TXA10		CM922TXA10		934
-sandgate		MACH_PXA		PXA			935
-sandgate2		MACH_SANDGATE2		SANDGATE2		936
-sandgate2g		MACH_SANDGATE2G		SANDGATE2G		937
-sandgate2p		MACH_SANDGATE2P		SANDGATE2P		938
-fred_jack		MACH_FRED_JACK		FRED_JACK		939
-ttg_color1		MACH_TTG_COLOR1		TTG_COLOR1		940
 nxeb500hmi		MACH_NXEB500HMI		NXEB500HMI		941
-netdcu8			MACH_NETDCU8		NETDCU8			942
-ng_fvx538		MACH_NG_FVX538		NG_FVX538		944
-ng_fvs338		MACH_NG_FVS338		NG_FVS338		945
-pnx4103			MACH_PNX4103		PNX4103			946
-hesdb			MACH_HESDB		HESDB			947
-xsilo			MACH_XSILO		XSILO			948
 espresso		MACH_ESPRESSO		ESPRESSO		949
-emlc			MACH_EMLC		EMLC			950
-sisteron		MACH_SISTERON		SISTERON		951
 rx1950			MACH_RX1950		RX1950			952
-tsc_venus		MACH_TSC_VENUS		TSC_VENUS		953
-ds101j			MACH_DS101J		DS101J			954
-mxc30030ads		MACH_MXC30030ADS	MXC30030ADS		955
-fujitsu_wimaxsoc	MACH_FUJITSU_WIMAXSOC	FUJITSU_WIMAXSOC	956
-dualpcmodem		MACH_DUALPCMODEM	DUALPCMODEM		957
 gesbc9312		MACH_GESBC9312		GESBC9312		958
-htcapache		MACH_HTCAPACHE		HTCAPACHE		959
-ixdp435			MACH_IXDP435		IXDP435			960
-catprovt100		MACH_CATPROVT100	CATPROVT100		961
-picotux1xx		MACH_PICOTUX1XX		PICOTUX1XX		962
 picotux2xx		MACH_PICOTUX2XX		PICOTUX2XX		963
 dsmg600			MACH_DSMG600		DSMG600			964
-empc2			MACH_EMPC2		EMPC2			965
-ventura			MACH_VENTURA		VENTURA			966
-phidget_sbc		MACH_PHIDGET_SBC	PHIDGET_SBC		967
-ij3k			MACH_IJ3K		IJ3K			968
-pisgah			MACH_PISGAH		PISGAH			969
 omap_fsample		MACH_OMAP_FSAMPLE	OMAP_FSAMPLE		970
-sg720			MACH_SG720		SG720			971
-redfox			MACH_REDFOX		REDFOX			972
-mysh_ep9315_1		MACH_MYSH_EP9315_1	MYSH_EP9315_1		973
-tpf106			MACH_TPF106		TPF106			974
-at91rm9200kg		MACH_AT91RM9200KG	AT91RM9200KG		975
-rcmt2			MACH_SLEDB		SLEDB			976
-ontrack			MACH_ONTRACK		ONTRACK			977
-pm1200			MACH_PM1200		PM1200			978
-ess24562		MACH_ESS24XXX		ESS24XXX		979
-coremp7			MACH_COREMP7		COREMP7			980
-nexcoder_6446		MACH_NEXCODER_6446	NEXCODER_6446		981
-stvc8380		MACH_STVC8380		STVC8380		982
-teklynx			MACH_TEKLYNX		TEKLYNX			983
-carbonado		MACH_CARBONADO		CARBONADO		984
-sysmos_mp730		MACH_SYSMOS_MP730	SYSMOS_MP730		985
 snapper_cl15		MACH_SNAPPER_CL15	SNAPPER_CL15		986
-pgigim			MACH_PGIGIM		PGIGIM			987
-ptx9160p2		MACH_PTX9160P2		PTX9160P2		988
-dcore1			MACH_DCORE1		DCORE1			989
-victorpxa		MACH_VICTORPXA		VICTORPXA		990
-mx2dtb			MACH_MX2DTB		MX2DTB			991
-pxa_irex_er0100		MACH_PXA_IREX_ER0100	PXA_IREX_ER0100		992
 omap_palmz71		MACH_OMAP_PALMZ71	OMAP_PALMZ71		993
-bartec_deg		MACH_BARTEC_DEG		BARTEC_DEG		994
-hw50251			MACH_HW50251		HW50251			995
-ibox			MACH_IBOX		IBOX			996
-atlaslh7a404		MACH_ATLASLH7A404	ATLASLH7A404		997
-pt2026			MACH_PT2026		PT2026			998
-htcalpine		MACH_HTCALPINE		HTCALPINE		999
-bartec_vtu		MACH_BARTEC_VTU		BARTEC_VTU		1000
-vcoreii			MACH_VCOREII		VCOREII			1001
-pdnb3			MACH_PDNB3		PDNB3			1002
-htcbeetles		MACH_HTCBEETLES		HTCBEETLES		1003
-s3c6400			MACH_S3C6400		S3C6400			1004
-s3c2443			MACH_S3C2443		S3C2443			1005
-omap_ldk		MACH_OMAP_LDK		OMAP_LDK		1006
-smdk2460		MACH_SMDK2460		SMDK2460		1007
-smdk2440		MACH_SMDK2440		SMDK2440		1008
 smdk2412		MACH_SMDK2412		SMDK2412		1009
-webbox			MACH_WEBBOX		WEBBOX			1010
-cwwndp			MACH_CWWNDP		CWWNDP			1011
-i839			MACH_DRAGON		DRAGON			1012
-opendo_cpu_board	MACH_OPENDO_CPU_BOARD	OPENDO_CPU_BOARD	1013
-ccm2200			MACH_CCM2200		CCM2200			1014
-etwarm			MACH_ETWARM		ETWARM			1015
-m93030			MACH_M93030		M93030			1016
-cc7u			MACH_CC7U		CC7U			1017
-mtt_ranger		MACH_MTT_RANGER		MTT_RANGER		1018
-nexus			MACH_NEXUS		NEXUS			1019
-desman			MACH_DESMAN		DESMAN			1020
-bkde303			MACH_BKDE303		BKDE303			1021
 smdk2413		MACH_SMDK2413		SMDK2413		1022
-aml_m7200		MACH_AML_M7200		AML_M7200		1023
 aml_m5900		MACH_AML_M5900		AML_M5900		1024
-sg640			MACH_SG640		SG640			1025
-edg79524		MACH_EDG79524		EDG79524		1026
-ai2410			MACH_AI2410		AI2410			1027
-ixp465			MACH_IXP465		IXP465			1028
 balloon3		MACH_BALLOON3		BALLOON3		1029
-heins			MACH_HEINS		HEINS			1030
-mpluseva		MACH_MPLUSEVA		MPLUSEVA		1031
-rt042			MACH_RT042		RT042			1032
-cwiem			MACH_CWIEM		CWIEM			1033
-cm_x270			MACH_CM_X270		CM_X270			1034
-cm_x255			MACH_CM_X255		CM_X255			1035
-esh_at91		MACH_ESH_AT91		ESH_AT91		1036
-sandgate3		MACH_SANDGATE3		SANDGATE3		1037
-primo			MACH_PRIMO		PRIMO			1038
-gemstone		MACH_GEMSTONE		GEMSTONE		1039
-pronghorn_metro		MACH_PRONGHORNMETRO	PRONGHORNMETRO		1040
-sidewinder		MACH_SIDEWINDER		SIDEWINDER		1041
-picomod1		MACH_PICOMOD1		PICOMOD1		1042
-sg590			MACH_SG590		SG590			1043
-akai9307		MACH_AKAI9307		AKAI9307		1044
-fontaine		MACH_FONTAINE		FONTAINE		1045
-wombat			MACH_WOMBAT		WOMBAT			1046
-acq300			MACH_ACQ300		ACQ300			1047
-mod272			MACH_MOD_270		MOD_270			1048
-vmc_vc0820		MACH_VC0820		VC0820			1049
-ani_aim			MACH_ANI_AIM		ANI_AIM			1050
-jellyfish		MACH_JELLYFISH		JELLYFISH		1051
-amanita			MACH_AMANITA		AMANITA			1052
-vlink			MACH_VLINK		VLINK			1053
-dexflex			MACH_DEXFLEX		DEXFLEX			1054
-eigen_ttq		MACH_EIGEN_TTQ		EIGEN_TTQ		1055
-arcom_titan		MACH_ARCOM_TITAN	ARCOM_TITAN		1056
-tabla			MACH_TABLA		TABLA			1057
-mdirac3			MACH_MDIRAC3		MDIRAC3			1058
-mrhfbp2			MACH_MRHFBP2		MRHFBP2			1059
-at91rm9200rb		MACH_AT91RM9200RB	AT91RM9200RB		1060
-ani_apm			MACH_ANI_APM		ANI_APM			1061
-ella1			MACH_ELLA1		ELLA1			1062
-inhand_pxa27x		MACH_INHAND_PXA27X	INHAND_PXA27X		1063
-inhand_pxa25x		MACH_INHAND_PXA25X	INHAND_PXA25X		1064
-empos_xm		MACH_EMPOS_XM		EMPOS_XM		1065
-empos			MACH_EMPOS		EMPOS			1066
-empos_tiny		MACH_EMPOS_TINY		EMPOS_TINY		1067
-empos_sm		MACH_EMPOS_SM		EMPOS_SM		1068
-egret			MACH_EGRET		EGRET			1069
-ostrich			MACH_OSTRICH		OSTRICH			1070
-n50			MACH_N50		N50			1071
 ecbat91			MACH_ECBAT91		ECBAT91			1072
-stareast		MACH_STAREAST		STAREAST		1073
-dspg_dw			MACH_DSPG_DW		DSPG_DW			1074
 onearm			MACH_ONEARM		ONEARM			1075
-mrg110_6		MACH_MRG110_6		MRG110_6		1076
-wrt300nv2		MACH_WRT300NV2		WRT300NV2		1077
-xm_bulverde		MACH_XM_BULVERDE	XM_BULVERDE		1078
-msm6100			MACH_MSM6100		MSM6100			1079
-eti_b1			MACH_ETI_B1		ETI_B1			1080
-za9l_series		MACH_ZILOG_ZA9L		ZILOG_ZA9L		1081
-bit2440			MACH_BIT2440		BIT2440			1082
-nbi			MACH_NBI		NBI			1083
 smdk2443		MACH_SMDK2443		SMDK2443		1084
-vdavinci		MACH_VDAVINCI		VDAVINCI		1085
-atc6			MACH_ATC6		ATC6			1086
-multmdw			MACH_MULTMDW		MULTMDW			1087
-mba2440			MACH_MBA2440		MBA2440			1088
-ecsd			MACH_ECSD		ECSD			1089
-palmz31			MACH_PALMZ31		PALMZ31			1090
 fsg			MACH_FSG		FSG			1091
-razor101		MACH_RAZOR101		RAZOR101		1092
-opera_tdm		MACH_OPERA_TDM		OPERA_TDM		1093
-comcerto		MACH_COMCERTO		COMCERTO		1094
-tb0319			MACH_TB0319		TB0319			1095
-kws8000			MACH_KWS8000		KWS8000			1096
-b2			MACH_B2			B2			1097
-lcl54			MACH_LCL54		LCL54			1098
 at91sam9260ek		MACH_AT91SAM9260EK	AT91SAM9260EK		1099
 glantank		MACH_GLANTANK		GLANTANK		1100
 n2100			MACH_N2100		N2100			1101
-n4100			MACH_N4100		N4100			1102
-rsc4			MACH_VERTICAL_RSC4	VERTICAL_RSC4		1103
-sg8100			MACH_SG8100		SG8100			1104
-im42xx			MACH_IM42XX		IM42XX			1105
-ftxx			MACH_FTXX		FTXX			1106
-lwfusion		MACH_LWFUSION		LWFUSION		1107
 qt2410			MACH_QT2410		QT2410			1108
 kixrp435		MACH_KIXRP435		KIXRP435		1109
-ccw9c			MACH_CCW9C		CCW9C			1110
-dabhs			MACH_DABHS		DABHS			1111
-gzmx			MACH_GZMX		GZMX			1112
-ipnw100ap		MACH_IPNW100AP		IPNW100AP		1113
 cc9p9360dev		MACH_CC9P9360DEV	CC9P9360DEV		1114
-cc9p9750dev		MACH_CC9P9750DEV	CC9P9750DEV		1115
-cc9p9360val		MACH_CC9P9360VAL	CC9P9360VAL		1116
-cc9p9750val		MACH_CC9P9750VAL	CC9P9750VAL		1117
-nx70v			MACH_NX70V		NX70V			1118
-at91rm9200df		MACH_AT91RM9200DF	AT91RM9200DF		1119
-se_pilot2		MACH_SE_PILOT2		SE_PILOT2		1120
-mtcn_t800		MACH_MTCN_T800		MTCN_T800		1121
-vcmx212			MACH_VCMX212		VCMX212			1122
-lynx			MACH_LYNX		LYNX			1123
-at91sam9260id		MACH_AT91SAM9260ID	AT91SAM9260ID		1124
-hw86052			MACH_HW86052		HW86052			1125
-pilz_pmi3		MACH_PILZ_PMI3		PILZ_PMI3		1126
 edb9302a		MACH_EDB9302A		EDB9302A		1127
 edb9307a		MACH_EDB9307A		EDB9307A		1128
-ct_dfs			MACH_CT_DFS		CT_DFS			1129
-pilz_pmi4		MACH_PILZ_PMI4		PILZ_PMI4		1130
-xceednp_ixp		MACH_XCEEDNP_IXP	XCEEDNP_IXP		1131
-smdk2442b		MACH_SMDK2442B		SMDK2442B		1132
-xnode			MACH_XNODE		XNODE			1133
-aidx270			MACH_AIDX270		AIDX270			1134
-rema			MACH_REMA		REMA			1135
-bps1000			MACH_BPS1000		BPS1000			1136
-hw90350			MACH_HW90350		HW90350			1137
 omap_3430sdp		MACH_OMAP_3430SDP	OMAP_3430SDP		1138
-bluetouch		MACH_BLUETOUCH		BLUETOUCH		1139
 vstms			MACH_VSTMS		VSTMS			1140
-xsbase270		MACH_XSBASE270		XSBASE270		1141
-at91sam9260ek_cn	MACH_AT91SAM9260EK_CN	AT91SAM9260EK_CN	1142
-adsturboxb		MACH_ADSTURBOXB		ADSTURBOXB		1143
-oti4110			MACH_OTI4110		OTI4110			1144
-hme_pxa			MACH_HME_PXA		HME_PXA			1145
-deisterdca		MACH_DEISTERDCA		DEISTERDCA		1146
-ces_ssem2		MACH_CES_SSEM2		CES_SSEM2		1147
-ces_mtr			MACH_CES_MTR		CES_MTR			1148
-tds_avng_sbc		MACH_TDS_AVNG_SBC	TDS_AVNG_SBC		1149
-everest			MACH_EVEREST		EVEREST			1150
-pnx4010			MACH_PNX4010		PNX4010			1151
-oxnas			MACH_OXNAS		OXNAS			1152
-fiori			MACH_FIORI		FIORI			1153
-ml1200			MACH_ML1200		ML1200			1154
-pecos			MACH_PECOS		PECOS			1155
-nb2xxx			MACH_NB2XXX		NB2XXX			1156
-hw6900			MACH_HW6900		HW6900			1157
-cdcs_quoll		MACH_CDCS_QUOLL		CDCS_QUOLL		1158
-quicksilver		MACH_QUICKSILVER	QUICKSILVER		1159
-uplat926		MACH_UPLAT926		UPLAT926		1160
-dep2410_dep2410		MACH_DEP2410_THOMAS	DEP2410_THOMAS		1161
-dtk2410			MACH_DTK2410		DTK2410			1162
-chili			MACH_CHILI		CHILI			1163
-demeter			MACH_DEMETER		DEMETER			1164
-dionysus		MACH_DIONYSUS		DIONYSUS		1165
-as352x			MACH_AS352X		AS352X			1166
-service			MACH_SERVICE		SERVICE			1167
-cs_e9301		MACH_CS_E9301		CS_E9301		1168
 micro9m			MACH_MICRO9M		MICRO9M			1169
-ia_mospck		MACH_IA_MOSPCK		IA_MOSPCK		1170
-ql201b			MACH_QL201B		QL201B			1171
-bbm			MACH_BBM		BBM			1174
-exxx			MACH_EXXX		EXXX			1175
-wma11b			MACH_WMA11B		WMA11B			1176
-pelco_atlas		MACH_PELCO_ATLAS	PELCO_ATLAS		1177
-g500			MACH_G500		G500			1178
 bug			MACH_BUG		BUG			1179
-mx33ads			MACH_MX33ADS		MX33ADS			1180
-chub			MACH_CHUB		CHUB			1181
-neo1973_gta01		MACH_NEO1973_GTA01	NEO1973_GTA01		1182
-w90n740			MACH_W90N740		W90N740			1183
-medallion_sa2410	MACH_MEDALLION_SA2410	MEDALLION_SA2410	1184
-ia_cpu_9200_2		MACH_IA_CPU_9200_2	IA_CPU_9200_2		1185
-dimmrm9200		MACH_DIMMRM9200		DIMMRM9200		1186
-pm9261			MACH_PM9261		PM9261			1187
-ml7304			MACH_ML7304		ML7304			1189
-ucp250			MACH_UCP250		UCP250			1190
-intboard		MACH_INTBOARD		INTBOARD		1191
-gulfstream		MACH_GULFSTREAM		GULFSTREAM		1192
-labquest		MACH_LABQUEST		LABQUEST		1193
-vcmx313			MACH_VCMX313		VCMX313			1194
-urg200			MACH_URG200		URG200			1195
-cpux255lcdnet		MACH_CPUX255LCDNET	CPUX255LCDNET		1196
-netdcu9			MACH_NETDCU9		NETDCU9			1197
-netdcu10		MACH_NETDCU10		NETDCU10		1198
-dspg_dga		MACH_DSPG_DGA		DSPG_DGA		1199
-dspg_dvw		MACH_DSPG_DVW		DSPG_DVW		1200
-solos			MACH_SOLOS		SOLOS			1201
 at91sam9263ek		MACH_AT91SAM9263EK	AT91SAM9263EK		1202
-osstbox			MACH_OSSTBOX		OSSTBOX			1203
-kbat9261		MACH_KBAT9261		KBAT9261		1204
-ct1100			MACH_CT1100		CT1100			1205
-akcppxa			MACH_AKCPPXA		AKCPPXA			1206
-ochaya1020		MACH_OCHAYA1020		OCHAYA1020		1207
-hitrack			MACH_HITRACK		HITRACK			1208
-syme1			MACH_SYME1		SYME1			1209
-syhl1			MACH_SYHL1		SYHL1			1210
-empca400		MACH_EMPCA400		EMPCA400		1211
 em7210			MACH_EM7210		EM7210			1212
-htchermes		MACH_HTCHERMES		HTCHERMES		1213
-eti_c1			MACH_ETI_C1		ETI_C1			1214
-ac100			MACH_AC100		AC100			1216
-sneetch			MACH_SNEETCH		SNEETCH			1217
-studentmate		MACH_STUDENTMATE	STUDENTMATE		1218
-zir2410			MACH_ZIR2410		ZIR2410			1219
-zir2413			MACH_ZIR2413		ZIR2413			1220
-dlonip3			MACH_DLONIP3		DLONIP3			1221
-instream		MACH_INSTREAM		INSTREAM		1222
-ambarella		MACH_AMBARELLA		AMBARELLA		1223
-nevis			MACH_NEVIS		NEVIS			1224
-htc_trinity		MACH_HTC_TRINITY	HTC_TRINITY		1225
-ql202b			MACH_QL202B		QL202B			1226
 vpac270			MACH_VPAC270		VPAC270			1227
-rd129			MACH_RD129		RD129			1228
-htcwizard		MACH_HTCWIZARD		HTCWIZARD		1229
 treo680			MACH_TREO680		TREO680			1230
-tecon_tmezon		MACH_TECON_TMEZON	TECON_TMEZON		1231
 zylonite		MACH_ZYLONITE		ZYLONITE		1233
-gene1270		MACH_GENE1270		GENE1270		1234
-zir2412			MACH_ZIR2412		ZIR2412			1235
 mx31lite		MACH_MX31LITE		MX31LITE		1236
-t700wx			MACH_T700WX		T700WX			1237
-vf100			MACH_VF100		VF100			1238
-nsb2			MACH_NSB2		NSB2			1239
-nxhmi_bb		MACH_NXHMI_BB		NXHMI_BB		1240
-nxhmi_re		MACH_NXHMI_RE		NXHMI_RE		1241
-n4100pro		MACH_N4100PRO		N4100PRO		1242
-sam9260			MACH_SAM9260		SAM9260			1243
-omap_treo600		MACH_OMAP_TREO600	OMAP_TREO600		1244
-indy2410		MACH_INDY2410		INDY2410		1245
-nelt_a			MACH_NELT_A		NELT_A			1246
-n311			MACH_N311		N311			1248
-at91sam9260vgk		MACH_AT91SAM9260VGK	AT91SAM9260VGK		1249
-at91leppe		MACH_AT91LEPPE		AT91LEPPE		1250
-at91lepccn		MACH_AT91LEPCCN		AT91LEPCCN		1251
-apc7100			MACH_APC7100		APC7100			1252
-stargazer		MACH_STARGAZER		STARGAZER		1253
-sonata			MACH_SONATA		SONATA			1254
-schmoogie		MACH_SCHMOOGIE		SCHMOOGIE		1255
-aztool			MACH_AZTOOL		AZTOOL			1256
 mioa701			MACH_MIOA701		MIOA701			1257
-sxni9260		MACH_SXNI9260		SXNI9260		1258
-mxc27520evb		MACH_MXC27520EVB	MXC27520EVB		1259
 armadillo5x0		MACH_ARMADILLO5X0	ARMADILLO5X0		1260
-mb9260			MACH_MB9260		MB9260			1261
-mb9263			MACH_MB9263		MB9263			1262
-ipac9302		MACH_IPAC9302		IPAC9302		1263
 cc9p9360js		MACH_CC9P9360JS		CC9P9360JS		1264
-gallium			MACH_GALLIUM		GALLIUM			1265
-msc2410			MACH_MSC2410		MSC2410			1266
-ghi270			MACH_GHI270		GHI270			1267
-davinci_leonardo	MACH_DAVINCI_LEONARDO	DAVINCI_LEONARDO	1268
-oiab			MACH_OIAB		OIAB			1269
 smdk6400		MACH_SMDK6400		SMDK6400		1270
 nokia_n800		MACH_NOKIA_N800		NOKIA_N800		1271
-greenphone		MACH_GREENPHONE		GREENPHONE		1272
-compex42x		MACH_COMPEXWP18		COMPEXWP18		1273
-xmate			MACH_XMATE		XMATE			1274
-energizer		MACH_ENERGIZER		ENERGIZER		1275
-ime1			MACH_IME1		IME1			1276
-sweda_tms		MACH_SWEDATMS		SWEDATMS		1277
-ntnp435c		MACH_NTNP435C		NTNP435C		1278
-spectro2		MACH_SPECTRO2		SPECTRO2		1279
-h6039			MACH_H6039		H6039			1280
 ep80219			MACH_EP80219		EP80219			1281
-samoa_ii		MACH_SAMOA_II		SAMOA_II		1282
-cwmxl			MACH_CWMXL		CWMXL			1283
-as9200			MACH_AS9200		AS9200			1284
-sfx1149			MACH_SFX1149		SFX1149			1285
-navi010			MACH_NAVI010		NAVI010			1286
-multmdp			MACH_MULTMDP		MULTMDP			1287
-scb9520			MACH_SCB9520		SCB9520			1288
-htcathena		MACH_HTCATHENA		HTCATHENA		1289
-xp179			MACH_XP179		XP179			1290
-h4300			MACH_H4300		H4300			1291
 goramo_mlr		MACH_GORAMO_MLR		GORAMO_MLR		1292
-mxc30020evb		MACH_MXC30020EVB	MXC30020EVB		1293
-adsbitsyg5		MACH_ADSBITSYG5		ADSBITSYG5		1294
-adsportalplus		MACH_ADSPORTALPLUS	ADSPORTALPLUS		1295
-mmsp2plus		MACH_MMSP2PLUS		MMSP2PLUS		1296
 em_x270			MACH_EM_X270		EM_X270			1297
-tpp302			MACH_TPP302		TPP302			1298
-tpp104			MACH_TPM104		TPM104			1299
-tpm102			MACH_TPM102		TPM102			1300
-tpm109			MACH_TPM109		TPM109			1301
-fbxo1			MACH_FBXO1		FBXO1			1302
-hxd8			MACH_HXD8		HXD8			1303
 neo1973_gta02		MACH_NEO1973_GTA02	NEO1973_GTA02		1304
-emtest			MACH_EMTEST		EMTEST			1305
-ad6900			MACH_AD6900		AD6900			1306
-europa			MACH_EUROPA		EUROPA			1307
-metroconnect		MACH_METROCONNECT	METROCONNECT		1308
-ez_s2410		MACH_EZ_S2410		EZ_S2410		1309
-ez_s2440		MACH_EZ_S2440		EZ_S2440		1310
-ez_ep9312		MACH_EZ_EP9312		EZ_EP9312		1311
-ez_ep9315		MACH_EZ_EP9315		EZ_EP9315		1312
-ez_x7			MACH_EZ_X7		EZ_X7			1313
-godotdb			MACH_GODOTDB		GODOTDB			1314
-mistral			MACH_MISTRAL		MISTRAL			1315
-msm			MACH_MSM		MSM			1316
-ct5910			MACH_CT5910		CT5910			1317
-ct5912			MACH_CT5912		CT5912			1318
-hynet_ine		MACH_HYNET_INE		HYNET_INE		1319
-hynet_app		MACH_HYNET_APP		HYNET_APP		1320
-msm7200			MACH_MSM7200		MSM7200			1321
-msm7600			MACH_MSM7600		MSM7600			1322
-ceb255			MACH_CEB255		CEB255			1323
-ciel			MACH_CIEL		CIEL			1324
-slm5650			MACH_SLM5650		SLM5650			1325
 at91sam9rlek		MACH_AT91SAM9RLEK	AT91SAM9RLEK		1326
-comtech_router		MACH_COMTECH_ROUTER	COMTECH_ROUTER		1327
-sbc2410x		MACH_SBC2410X		SBC2410X		1328
-at4x0bd			MACH_AT4X0BD		AT4X0BD			1329
-cbifr			MACH_CBIFR		CBIFR			1330
-arcom_quantum		MACH_ARCOM_QUANTUM	ARCOM_QUANTUM		1331
-matrix520		MACH_MATRIX520		MATRIX520		1332
-matrix510		MACH_MATRIX510		MATRIX510		1333
-matrix500		MACH_MATRIX500		MATRIX500		1334
-m501			MACH_M501		M501			1335
-aaeon1270		MACH_AAEON1270		AAEON1270		1336
-matrix500ev		MACH_MATRIX500EV	MATRIX500EV		1337
-pac500			MACH_PAC500		PAC500			1338
-pnx8181			MACH_PNX8181		PNX8181			1339
 colibri320		MACH_COLIBRI320		COLIBRI320		1340
-aztoolbb		MACH_AZTOOLBB		AZTOOLBB		1341
-aztoolg2		MACH_AZTOOLG2		AZTOOLG2		1342
-dvlhost			MACH_DVLHOST		DVLHOST			1343
-zir9200			MACH_ZIR9200		ZIR9200			1344
-zir9260			MACH_ZIR9260		ZIR9260			1345
-cocopah			MACH_COCOPAH		COCOPAH			1346
-nds			MACH_NDS		NDS			1347
-rosencrantz		MACH_ROSENCRANTZ	ROSENCRANTZ		1348
-fttx_odsc		MACH_FTTX_ODSC		FTTX_ODSC		1349
-classe_r6904		MACH_CLASSE_R6904	CLASSE_R6904		1350
 cam60			MACH_CAM60		CAM60			1351
-mxc30031ads		MACH_MXC30031ADS	MXC30031ADS		1352
-datacall		MACH_DATACALL		DATACALL		1353
 at91eb01		MACH_AT91EB01		AT91EB01		1354
-rty			MACH_RTY		RTY			1355
-dwl2100			MACH_DWL2100		DWL2100			1356
-vinsi			MACH_VINSI		VINSI			1357
 db88f5281		MACH_DB88F5281		DB88F5281		1358
 csb726			MACH_CSB726		CSB726			1359
-tik27			MACH_TIK27		TIK27			1360
-mx_uc7420		MACH_MX_UC7420		MX_UC7420		1361
-rirm3			MACH_RIRM3		RIRM3			1362
-pelco_odyssey		MACH_PELCO_ODYSSEY	PELCO_ODYSSEY		1363
-adx_abox		MACH_ADX_ABOX		ADX_ABOX		1365
-adx_tpid		MACH_ADX_TPID		ADX_TPID		1366
-minicheck		MACH_MINICHECK		MINICHECK		1367
-idam			MACH_IDAM		IDAM			1368
-mario_mx		MACH_MARIO_MX		MARIO_MX		1369
-vi1888			MACH_VI1888		VI1888			1370
-zr4230			MACH_ZR4230		ZR4230			1371
-t1_ix_blue		MACH_T1_IX_BLUE		T1_IX_BLUE		1372
-syhq2			MACH_SYHQ2		SYHQ2			1373
-computime_r3		MACH_COMPUTIME_R3	COMPUTIME_R3		1374
-oratis			MACH_ORATIS		ORATIS			1375
-mikko			MACH_MIKKO		MIKKO			1376
-holon			MACH_HOLON		HOLON			1377
-olip8			MACH_OLIP8		OLIP8			1378
-ghi270hg		MACH_GHI270HG		GHI270HG		1379
 davinci_dm6467_evm	MACH_DAVINCI_DM6467_EVM	DAVINCI_DM6467_EVM	1380
 davinci_dm355_evm	MACH_DAVINCI_DM355_EVM	DAVINCI_DM355_EVM	1381
-blackriver		MACH_BLACKRIVER		BLACKRIVER		1383
-sandgate_wp		MACH_SANDGATEWP		SANDGATEWP		1384
-cdotbwsg		MACH_CDOTBWSG		CDOTBWSG		1385
-quark963		MACH_QUARK963		QUARK963		1386
-csb735			MACH_CSB735		CSB735			1387
 littleton		MACH_LITTLETON		LITTLETON		1388
-mio_p550		MACH_MIO_P550		MIO_P550		1389
-motion2440		MACH_MOTION2440		MOTION2440		1390
-imm500			MACH_IMM500		IMM500			1391
-homematic		MACH_HOMEMATIC		HOMEMATIC		1392
-ermine			MACH_ERMINE		ERMINE			1393
-kb9202b			MACH_KB9202B		KB9202B			1394
-hs1xx			MACH_HS1XX		HS1XX			1395
-studentmate2440		MACH_STUDENTMATE2440	STUDENTMATE2440		1396
-arvoo_l1_z1		MACH_ARVOO_L1_Z1	ARVOO_L1_Z1		1397
-dep2410k		MACH_DEP2410K		DEP2410K		1398
-xxsvideo		MACH_XXSVIDEO		XXSVIDEO		1399
-im4004			MACH_IM4004		IM4004			1400
-ochaya1050		MACH_OCHAYA1050		OCHAYA1050		1401
-lep9261			MACH_LEP9261		LEP9261			1402
-svenmeb			MACH_SVENMEB		SVENMEB			1403
-fortunet2ne		MACH_FORTUNET2NE	FORTUNET2NE		1404
-nxhx			MACH_NXHX		NXHX			1406
 realview_pb11mp		MACH_REALVIEW_PB11MP	REALVIEW_PB11MP		1407
-ids500			MACH_IDS500		IDS500			1408
-ors_n725		MACH_ORS_N725		ORS_N725		1409
-hsdarm			MACH_HSDARM		HSDARM			1410
-sha_pon003		MACH_SHA_PON003		SHA_PON003		1411
-sha_pon004		MACH_SHA_PON004		SHA_PON004		1412
-sha_pon007		MACH_SHA_PON007		SHA_PON007		1413
-sha_pon011		MACH_SHA_PON011		SHA_PON011		1414
-h6042			MACH_H6042		H6042			1415
-h6043			MACH_H6043		H6043			1416
-looxc550		MACH_LOOXC550		LOOXC550		1417
-cnty_titan		MACH_CNTY_TITAN		CNTY_TITAN		1418
-app3xx			MACH_APP3XX		APP3XX			1419
-sideoatsgrama		MACH_SIDEOATSGRAMA	SIDEOATSGRAMA		1420
-treo700p		MACH_TREO700P		TREO700P		1421
-treo700w		MACH_TREO700W		TREO700W		1422
-treo750			MACH_TREO750		TREO750			1423
-treo755p		MACH_TREO755P		TREO755P		1424
-ezreganut9200		MACH_EZREGANUT9200	EZREGANUT9200		1425
-sarge			MACH_SARGE		SARGE			1426
-a696			MACH_A696		A696			1427
-turtle1916		MACH_TURTLE		TURTLE			1428
 mx27_3ds		MACH_MX27_3DS		MX27_3DS		1430
-bishop			MACH_BISHOP		BISHOP			1431
-pxx			MACH_PXX		PXX			1432
-redwood			MACH_REDWOOD		REDWOOD			1433
-omap_2430dlp		MACH_OMAP_2430DLP	OMAP_2430DLP		1436
-omap_2430osk		MACH_OMAP_2430OSK	OMAP_2430OSK		1437
-sardine			MACH_SARDINE		SARDINE			1438
 halibut			MACH_HALIBUT		HALIBUT			1439
 trout			MACH_TROUT		TROUT			1440
-goldfish		MACH_GOLDFISH		GOLDFISH		1441
-gesbc2440		MACH_GESBC2440		GESBC2440		1442
-nomad			MACH_NOMAD		NOMAD			1443
-rosalind		MACH_ROSALIND		ROSALIND		1444
-cc9p9215		MACH_CC9P9215		CC9P9215		1445
-cc9p9210		MACH_CC9P9210		CC9P9210		1446
-cc9p9215js		MACH_CC9P9215JS		CC9P9215JS		1447
-cc9p9210js		MACH_CC9P9210JS		CC9P9210JS		1448
-nasffe			MACH_NASFFE		NASFFE			1449
-tn2x0bd			MACH_TN2X0BD		TN2X0BD			1450
-gwmpxa			MACH_GWMPXA		GWMPXA			1451
-exyplus			MACH_EXYPLUS		EXYPLUS			1452
-jadoo21			MACH_JADOO21		JADOO21			1453
-looxn560		MACH_LOOXN560		LOOXN560		1454
-bonsai			MACH_BONSAI		BONSAI			1455
-adsmilgato		MACH_ADSMILGATO		ADSMILGATO		1456
-gba			MACH_GBA		GBA			1457
-h6044			MACH_H6044		H6044			1458
-app			MACH_APP		APP			1459
 tct_hammer		MACH_TCT_HAMMER		TCT_HAMMER		1460
 herald			MACH_HERALD		HERALD			1461
-artemis			MACH_ARTEMIS		ARTEMIS			1462
-htctitan		MACH_HTCTITAN		HTCTITAN		1463
-qranium			MACH_QRANIUM		QRANIUM			1464
-adx_wsc2		MACH_ADX_WSC2		ADX_WSC2		1465
-adx_medcom		MACH_ADX_MEDCOM		ADX_MEDCOM		1466
-bboard			MACH_BBOARD		BBOARD			1467
-cambria			MACH_CAMBRIA		CAMBRIA			1468
-mt7xxx			MACH_MT7XXX		MT7XXX			1469
-matrix512		MACH_MATRIX512		MATRIX512		1470
-matrix522		MACH_MATRIX522		MATRIX522		1471
-ipac5010		MACH_IPAC5010		IPAC5010		1472
-sakura			MACH_SAKURA		SAKURA			1473
-grocx			MACH_GROCX		GROCX			1474
-pm9263			MACH_PM9263		PM9263			1475
 sim_one			MACH_SIM_ONE		SIM_ONE			1476
-acq132			MACH_ACQ132		ACQ132			1477
-datr			MACH_DATR		DATR			1478
-actux1			MACH_ACTUX1		ACTUX1			1479
-actux2			MACH_ACTUX2		ACTUX2			1480
-actux3			MACH_ACTUX3		ACTUX3			1481
-flexit			MACH_FLEXIT		FLEXIT			1482
-bh2x0bd			MACH_BH2X0BD		BH2X0BD			1483
-atb2002			MACH_ATB2002		ATB2002			1484
-xenon			MACH_XENON		XENON			1485
-fm607			MACH_FM607		FM607			1486
-matrix514		MACH_MATRIX514		MATRIX514		1487
-matrix524		MACH_MATRIX524		MATRIX524		1488
-inpod			MACH_INPOD		INPOD			1489
 jive			MACH_JIVE		JIVE			1490
-tll_mx21		MACH_TLL_MX21		TLL_MX21		1491
-sbc2800			MACH_SBC2800		SBC2800			1492
-cc7ucamry		MACH_CC7UCAMRY		CC7UCAMRY		1493
-ubisys_p9_sc15		MACH_UBISYS_P9_SC15	UBISYS_P9_SC15		1494
-ubisys_p9_ssc2d10	MACH_UBISYS_P9_SSC2D10	UBISYS_P9_SSC2D10	1495
-ubisys_p9_rcu3		MACH_UBISYS_P9_RCU3	UBISYS_P9_RCU3		1496
-aml_m8000		MACH_AML_M8000		AML_M8000		1497
-snapper_270		MACH_SNAPPER_270	SNAPPER_270		1498
-omap_bbx		MACH_OMAP_BBX		OMAP_BBX		1499
-ucn2410			MACH_UCN2410		UCN2410			1500
 sam9_l9260		MACH_SAM9_L9260		SAM9_L9260		1501
-eti_c2			MACH_ETI_C2		ETI_C2			1502
-avalanche		MACH_AVALANCHE		AVALANCHE		1503
 realview_pb1176		MACH_REALVIEW_PB1176	REALVIEW_PB1176		1504
-dp1500			MACH_DP1500		DP1500			1505
-apple_iphone		MACH_APPLE_IPHONE	APPLE_IPHONE		1506
 yl9200			MACH_YL9200		YL9200			1507
 rd88f5182		MACH_RD88F5182		RD88F5182		1508
 kurobox_pro		MACH_KUROBOX_PRO	KUROBOX_PRO		1509
-se_poet			MACH_SE_POET		SE_POET			1510
 mx31_3ds		MACH_MX31_3DS		MX31_3DS		1511
-r270			MACH_R270		R270			1512
-armour21		MACH_ARMOUR21		ARMOUR21		1513
-dt2			MACH_DT2		DT2			1514
-vt4			MACH_VT4		VT4			1515
-tyco320			MACH_TYCO320		TYCO320			1516
-adma			MACH_ADMA		ADMA			1517
-wp188			MACH_WP188		WP188			1518
-corsica			MACH_CORSICA		CORSICA			1519
-bigeye			MACH_BIGEYE		BIGEYE			1520
-tll5000			MACH_TLL5000		TLL5000			1522
-bebot			MACH_BEBOT		BEBOT			1523
 qong			MACH_QONG		QONG			1524
-tcompact		MACH_TCOMPACT		TCOMPACT		1525
-puma5			MACH_PUMA5		PUMA5			1526
-elara			MACH_ELARA		ELARA			1527
-ellington		MACH_ELLINGTON		ELLINGTON		1528
-xda_atom		MACH_XDA_ATOM		XDA_ATOM		1529
-energizer2		MACH_ENERGIZER2		ENERGIZER2		1530
-odin			MACH_ODIN		ODIN			1531
-actux4			MACH_ACTUX4		ACTUX4			1532
-esl_omap		MACH_ESL_OMAP		ESL_OMAP		1533
 omap2evm		MACH_OMAP2EVM		OMAP2EVM		1534
 omap3evm		MACH_OMAP3EVM		OMAP3EVM		1535
-adx_pcu57		MACH_ADX_PCU57		ADX_PCU57		1536
-monaco			MACH_MONACO		MONACO			1537
-levante			MACH_LEVANTE		LEVANTE			1538
-tmxipx425		MACH_TMXIPX425		TMXIPX425		1539
-leep			MACH_LEEP		LEEP			1540
-raad			MACH_RAAD		RAAD			1541
 dns323			MACH_DNS323		DNS323			1542
-ap1000			MACH_AP1000		AP1000			1543
-a9sam6432		MACH_A9SAM6432		A9SAM6432		1544
-shiny			MACH_SHINY		SHINY			1545
 omap3_beagle		MACH_OMAP3_BEAGLE	OMAP3_BEAGLE		1546
-csr_bdb2		MACH_CSR_BDB2		CSR_BDB2		1547
 nokia_n810		MACH_NOKIA_N810		NOKIA_N810		1548
-c270			MACH_C270		C270			1549
-sentry			MACH_SENTRY		SENTRY			1550
 pcm038			MACH_PCM038		PCM038			1551
-anc300			MACH_ANC300		ANC300			1552
-htckaiser		MACH_HTCKAISER		HTCKAISER		1553
-sbat100			MACH_SBAT100		SBAT100			1554
-modunorm		MACH_MODUNORM		MODUNORM		1555
-pelos_twarm		MACH_PELOS_TWARM	PELOS_TWARM		1556
-flank			MACH_FLANK		FLANK			1557
-sirloin			MACH_SIRLOIN		SIRLOIN			1558
-brisket			MACH_BRISKET		BRISKET			1559
-chuck			MACH_CHUCK		CHUCK			1560
-otter			MACH_OTTER		OTTER			1561
-davinci_ldk		MACH_DAVINCI_LDK	DAVINCI_LDK		1562
-phreedom		MACH_PHREEDOM		PHREEDOM		1563
-sg310			MACH_SG310		SG310			1564
 ts_x09			MACH_TS209		TS209			1565
 at91cap9adk		MACH_AT91CAP9ADK	AT91CAP9ADK		1566
-tion9315		MACH_TION9315		TION9315		1567
-mast			MACH_MAST		MAST			1568
-pfw			MACH_PFW		PFW			1569
-yl_p2440		MACH_YL_P2440		YL_P2440		1570
-zsbc32			MACH_ZSBC32		ZSBC32			1571
-omap_pace2		MACH_OMAP_PACE2		OMAP_PACE2		1572
-imx_pace2		MACH_IMX_PACE2		IMX_PACE2		1573
 mx31moboard		MACH_MX31MOBOARD	MX31MOBOARD		1574
-mx37_3ds		MACH_MX37_3DS		MX37_3DS		1575
-rcc			MACH_RCC		RCC			1576
-dmp			MACH_ARM9		ARM9			1577
-vision_ep9307		MACH_VISION_EP9307	VISION_EP9307		1578
-scly1000		MACH_SCLY1000		SCLY1000		1579
-fontel_ep		MACH_FONTEL_EP		FONTEL_EP		1580
-voiceblue3g		MACH_VOICEBLUE3G	VOICEBLUE3G		1581
-tt9200			MACH_TT9200		TT9200			1582
-digi2410		MACH_DIGI2410		DIGI2410		1583
 terastation_pro2	MACH_TERASTATION_PRO2	TERASTATION_PRO2	1584
 linkstation_pro		MACH_LINKSTATION_PRO	LINKSTATION_PRO		1585
-motorola_a780		MACH_MOTOROLA_A780	MOTOROLA_A780		1587
-motorola_e6		MACH_MOTOROLA_E6	MOTOROLA_E6		1588
-motorola_e2		MACH_MOTOROLA_E2	MOTOROLA_E2		1589
-motorola_e680		MACH_MOTOROLA_E680	MOTOROLA_E680		1590
-ur2410			MACH_UR2410		UR2410			1591
-tas9261			MACH_TAS9261		TAS9261			1592
-davinci_hermes_hd	MACH_HERMES_HD		HERMES_HD		1593
-davinci_perseo_hd	MACH_PERSEO_HD		PERSEO_HD		1594
-stargazer2		MACH_STARGAZER2		STARGAZER2		1595
 e350			MACH_E350		E350			1596
-wpcm450			MACH_WPCM450		WPCM450			1597
-cartesio		MACH_CARTESIO		CARTESIO		1598
-toybox			MACH_TOYBOX		TOYBOX			1599
-tx27			MACH_TX27		TX27			1600
 ts409			MACH_TS409		TS409			1601
-p300			MACH_P300		P300			1602
-xdacomet		MACH_XDACOMET		XDACOMET		1603
-dexflex2		MACH_DEXFLEX2		DEXFLEX2		1604
-ow			MACH_OW			OW			1605
-armebs3			MACH_ARMEBS3		ARMEBS3			1606
-u3			MACH_U3			U3			1607
-smdk2450		MACH_SMDK2450		SMDK2450		1608
-rsi_ews			MACH_RSI_EWS		RSI_EWS			1609
-tnb			MACH_TNB		TNB			1610
-toepath			MACH_TOEPATH		TOEPATH			1611
-kb9263			MACH_KB9263		KB9263			1612
-mt7108			MACH_MT7108		MT7108			1613
-smtr2440		MACH_SMTR2440		SMTR2440		1614
-manao			MACH_MANAO		MANAO			1615
 cm_x300			MACH_CM_X300		CM_X300			1616
-gulfstream_kp		MACH_GULFSTREAM_KP	GULFSTREAM_KP		1617
-lanreadyfn522		MACH_LANREADYFN522	LANREADYFN522		1618
-arma37			MACH_ARMA37		ARMA37			1619
-mendel			MACH_MENDEL		MENDEL			1620
-pelco_iliad		MACH_PELCO_ILIAD	PELCO_ILIAD		1621
-unit2p			MACH_UNIT2P		UNIT2P			1622
-inc20otter		MACH_INC20OTTER		INC20OTTER		1623
 at91sam9g20ek		MACH_AT91SAM9G20EK	AT91SAM9G20EK		1624
-sc_ge2			MACH_STORCENTER		STORCENTER		1625
 smdk6410		MACH_SMDK6410		SMDK6410		1626
 u300			MACH_U300		U300			1627
-u500			MACH_U500		U500			1628
-ds9260			MACH_DS9260		DS9260			1629
-riverrock		MACH_RIVERROCK		RIVERROCK		1630
-scibath			MACH_SCIBATH		SCIBATH			1631
-at91sam7se		MACH_AT91SAM7SE512EK	AT91SAM7SE512EK		1632
 wrt350n_v2		MACH_WRT350N_V2		WRT350N_V2		1633
-multimedia		MACH_MULTIMEDIA		MULTIMEDIA		1634
-marvin			MACH_MARVIN		MARVIN			1635
-x500			MACH_X500		X500			1636
-awlug4lcu		MACH_AWLUG4LCU		AWLUG4LCU		1637
-palermoc		MACH_PALERMOC		PALERMOC		1638
 omap_ldp		MACH_OMAP_LDP		OMAP_LDP		1639
-ip500			MACH_IP500		IP500			1640
-ase2			MACH_ASE2		ASE2			1642
-mx35evb			MACH_MX35EVB		MX35EVB			1643
-aml_m8050		MACH_AML_M8050		AML_M8050		1644
 mx35_3ds		MACH_MX35_3DS		MX35_3DS		1645
-mars			MACH_MARS		MARS			1646
 neuros_osd2		MACH_NEUROS_OSD2	NEUROS_OSD2		1647
-badger			MACH_BADGER		BADGER			1648
 trizeps4wl		MACH_TRIZEPS4WL		TRIZEPS4WL		1649
-trizeps5		MACH_TRIZEPS5		TRIZEPS5		1650
-marlin			MACH_MARLIN		MARLIN			1651
 ts78xx			MACH_TS78XX		TS78XX			1652
-hpipaq214		MACH_HPIPAQ214		HPIPAQ214		1653
-at572d940dcm		MACH_AT572D940DCM	AT572D940DCM		1654
-ne1board		MACH_NE1BOARD		NE1BOARD		1655
-zante			MACH_ZANTE		ZANTE			1656
 sffsdr			MACH_SFFSDR		SFFSDR			1657
-tw2662			MACH_TW2662		TW2662			1658
-vf10xx			MACH_VF10XX		VF10XX			1659
-zoran43xx		MACH_ZORAN43XX		ZORAN43XX		1660
-sonix926		MACH_SONIX926		SONIX926		1661
-celestialsemi		MACH_CELESTIALSEMI	CELESTIALSEMI		1662
-cc9m2443js		MACH_CC9M2443JS		CC9M2443JS		1663
-tw5334			MACH_TW5334		TW5334			1664
-omap_htcartemis		MACH_HTCARTEMIS		HTCARTEMIS		1665
-nal_hlite		MACH_NAL_HLITE		NAL_HLITE		1666
-htcvogue		MACH_HTCVOGUE		HTCVOGUE		1667
-smartweb		MACH_SMARTWEB		SMARTWEB		1668
-mv86xx			MACH_MV86XX		MV86XX			1669
-mv87xx			MACH_MV87XX		MV87XX			1670
-songyoungho		MACH_SONGYOUNGHO	SONGYOUNGHO		1671
-younghotema		MACH_YOUNGHOTEMA	YOUNGHOTEMA		1672
 pcm037			MACH_PCM037		PCM037			1673
-mmvp			MACH_MMVP		MMVP			1674
-mmap			MACH_MMAP		MMAP			1675
-ptid2410		MACH_PTID2410		PTID2410		1676
-james_926		MACH_JAMES_926		JAMES_926		1677
-fm6000			MACH_FM6000		FM6000			1678
 db88f6281_bp		MACH_DB88F6281_BP	DB88F6281_BP		1680
 rd88f6192_nas		MACH_RD88F6192_NAS	RD88F6192_NAS		1681
 rd88f6281		MACH_RD88F6281		RD88F6281		1682
 db78x00_bp		MACH_DB78X00_BP		DB78X00_BP		1683
 smdk2416		MACH_SMDK2416		SMDK2416		1685
-oce_spider_si		MACH_OCE_SPIDER_SI	OCE_SPIDER_SI		1686
-oce_spider_sk		MACH_OCE_SPIDER_SK	OCE_SPIDER_SK		1687
-rovern6			MACH_ROVERN6		ROVERN6			1688
-pelco_evolution		MACH_PELCO_EVOLUTION	PELCO_EVOLUTION		1689
 wbd111			MACH_WBD111		WBD111			1690
-elaracpe		MACH_ELARACPE		ELARACPE		1691
-mabv3			MACH_MABV3		MABV3			1692
 mv2120			MACH_MV2120		MV2120			1693
-csb737			MACH_CSB737		CSB737			1695
 mx51_3ds		MACH_MX51_3DS		MX51_3DS		1696
-g900			MACH_G900		G900			1697
-apf27			MACH_APF27		APF27			1698
-ggus2000		MACH_GGUS2000		GGUS2000		1699
-omap_2430_mimic		MACH_OMAP_2430_MIMIC	OMAP_2430_MIMIC		1700
 imx27lite		MACH_IMX27LITE		IMX27LITE		1701
-almex			MACH_ALMEX		ALMEX			1702
-control			MACH_CONTROL		CONTROL			1703
-mba2410			MACH_MBA2410		MBA2410			1704
-volcano			MACH_VOLCANO		VOLCANO			1705
-zenith			MACH_ZENITH		ZENITH			1706
-muchip			MACH_MUCHIP		MUCHIP			1707
-magellan		MACH_MAGELLAN		MAGELLAN		1708
 usb_a9260		MACH_USB_A9260		USB_A9260		1709
 usb_a9263		MACH_USB_A9263		USB_A9263		1710
 qil_a9260		MACH_QIL_A9260		QIL_A9260		1711
-cme9210			MACH_CME9210		CME9210			1712
-hczh4			MACH_HCZH4		HCZH4			1713
-spearbasic		MACH_SPEARBASIC		SPEARBASIC		1714
-dep2440			MACH_DEP2440		DEP2440			1715
-hdl_gxr			MACH_HDL_GXR		HDL_GXR			1716
-hdl_gt			MACH_HDL_GT		HDL_GT			1717
-hdl_4g			MACH_HDL_4G		HDL_4G			1718
-s3c6000			MACH_S3C6000		S3C6000			1719
-mmsp2_mdk		MACH_MMSP2_MDK		MMSP2_MDK		1720
-mpx220			MACH_MPX220		MPX220			1721
 kzm_arm11_01		MACH_KZM_ARM11_01	KZM_ARM11_01		1722
-htc_polaris		MACH_HTC_POLARIS	HTC_POLARIS		1723
-htc_kaiser		MACH_HTC_KAISER		HTC_KAISER		1724
-lg_ks20			MACH_LG_KS20		LG_KS20			1725
-hhgps			MACH_HHGPS		HHGPS			1726
 nokia_n810_wimax	MACH_NOKIA_N810_WIMAX	NOKIA_N810_WIMAX	1727
-insight			MACH_INSIGHT		INSIGHT			1728
 sapphire		MACH_SAPPHIRE		SAPPHIRE		1729
-csb637xo		MACH_CSB637XO		CSB637XO		1730
-evisiong		MACH_EVISIONG		EVISIONG		1731
 stmp37xx		MACH_STMP37XX		STMP37XX		1732
 stmp378x		MACH_STMP378X		STMP378X		1733
-tnt			MACH_TNT		TNT			1734
-tbxt			MACH_TBXT		TBXT			1735
-playmate		MACH_PLAYMATE		PLAYMATE		1736
-pns10			MACH_PNS10		PNS10			1737
-eznavi			MACH_EZNAVI		EZNAVI			1738
-ps4000			MACH_PS4000		PS4000			1739
 ezx_a780		MACH_EZX_A780		EZX_A780		1740
 ezx_e680		MACH_EZX_E680		EZX_E680		1741
 ezx_a1200		MACH_EZX_A1200		EZX_A1200		1742
 ezx_e6			MACH_EZX_E6		EZX_E6			1743
 ezx_e2			MACH_EZX_E2		EZX_E2			1744
 ezx_a910		MACH_EZX_A910		EZX_A910		1745
-cwmx31			MACH_CWMX31		CWMX31			1746
-sl2312			MACH_SL2312		SL2312			1747
-blenny			MACH_BLENNY		BLENNY			1748
-ds107			MACH_DS107		DS107			1749
-dsx07			MACH_DSX07		DSX07			1750
-picocom1		MACH_PICOCOM1		PICOCOM1		1751
-lynx_wolverine		MACH_LYNX_WOLVERINE	LYNX_WOLVERINE		1752
-ubisys_p9_sc19		MACH_UBISYS_P9_SC19	UBISYS_P9_SC19		1753
-kratos_low		MACH_KRATOS_LOW		KRATOS_LOW		1754
-m700			MACH_M700		M700			1755
 edmini_v2		MACH_EDMINI_V2		EDMINI_V2		1756
 zipit2			MACH_ZIPIT2		ZIPIT2			1757
-hslfemtocell		MACH_HSLFEMTOCELL	HSLFEMTOCELL		1758
-daintree_at91		MACH_DAINTREE_AT91	DAINTREE_AT91		1759
-sg560usb		MACH_SG560USB		SG560USB		1760
 omap3_pandora		MACH_OMAP3_PANDORA	OMAP3_PANDORA		1761
-usr8200			MACH_USR8200		USR8200			1762
-s1s65k			MACH_S1S65K		S1S65K			1763
-s2s65a			MACH_S2S65A		S2S65A			1764
-icore			MACH_ICORE		ICORE			1765
 mss2			MACH_MSS2		MSS2			1766
-belmont			MACH_BELMONT		BELMONT			1767
-asusp525		MACH_ASUSP525		ASUSP525		1768
 lb88rc8480		MACH_LB88RC8480		LB88RC8480		1769
-hipxa			MACH_HIPXA		HIPXA			1770
 mx25_3ds		MACH_MX25_3DS		MX25_3DS		1771
-m800			MACH_M800		M800			1772
 omap3530_lv_som		MACH_OMAP3530_LV_SOM	OMAP3530_LV_SOM		1773
-prima_evb		MACH_PRIMA_EVB		PRIMA_EVB		1774
-mx31bt1			MACH_MX31BT1		MX31BT1			1775
-atlas4_evb		MACH_ATLAS4_EVB		ATLAS4_EVB		1776
-mx31cicada		MACH_MX31CICADA		MX31CICADA		1777
-mi424wr			MACH_MI424WR		MI424WR			1778
-axs_ultrax		MACH_AXS_ULTRAX		AXS_ULTRAX		1779
-at572d940deb		MACH_AT572D940DEB	AT572D940DEB		1780
 davinci_da830_evm	MACH_DAVINCI_DA830_EVM	DAVINCI_DA830_EVM	1781
-ep9302			MACH_EP9302		EP9302			1782
 at572d940hfek		MACH_AT572D940HFEB	AT572D940HFEB		1783
-cybook3			MACH_CYBOOK3		CYBOOK3			1784
-wdg002			MACH_WDG002		WDG002			1785
-sg560adsl		MACH_SG560ADSL		SG560ADSL		1786
-nextio_n2800_ica	MACH_NEXTIO_N2800_ICA	NEXTIO_N2800_ICA	1787
 dove_db			MACH_DOVE_DB		DOVE_DB			1788
-marvell_newdb		MACH_MARVELL_NEWDB	MARVELL_NEWDB		1789
-vandihud		MACH_VANDIHUD		VANDIHUD		1790
-magx_e8			MACH_MAGX_E8		MAGX_E8			1791
-magx_z6			MACH_MAGX_Z6		MAGX_Z6			1792
-magx_v8			MACH_MAGX_V8		MAGX_V8			1793
-magx_u9			MACH_MAGX_U9		MAGX_U9			1794
-toughcf08		MACH_TOUGHCF08		TOUGHCF08		1795
-zw4400			MACH_ZW4400		ZW4400			1796
-marat91			MACH_MARAT91		MARAT91			1797
 overo			MACH_OVERO		OVERO			1798
 at2440evb		MACH_AT2440EVB		AT2440EVB		1799
 neocore926		MACH_NEOCORE926		NEOCORE926		1800
 wnr854t			MACH_WNR854T		WNR854T			1801
-imx27			MACH_IMX27		IMX27			1802
-moose_db		MACH_MOOSE_DB		MOOSE_DB		1803
-fab4			MACH_FAB4		FAB4			1804
-htcdiamond		MACH_HTCDIAMOND		HTCDIAMOND		1805
-fiona			MACH_FIONA		FIONA			1806
-mxc30030_x		MACH_MXC30030_X		MXC30030_X		1807
-bmp1000			MACH_BMP1000		BMP1000			1808
-logi9200		MACH_LOGI9200		LOGI9200		1809
-tqma31			MACH_TQMA31		TQMA31			1810
-ccw9p9215js		MACH_CCW9P9215JS	CCW9P9215JS		1811
 rd88f5181l_ge		MACH_RD88F5181L_GE	RD88F5181L_GE		1812
-sifmain			MACH_SIFMAIN		SIFMAIN			1813
-sam9_l9261		MACH_SAM9_L9261		SAM9_L9261		1814
-cc9m2443		MACH_CC9M2443		CC9M2443		1815
-xaria300		MACH_XARIA300		XARIA300		1816
-it9200			MACH_IT9200		IT9200			1817
 rd88f5181l_fxo		MACH_RD88F5181L_FXO	RD88F5181L_FXO		1818
-kriss_sensor		MACH_KRISS_SENSOR	KRISS_SENSOR		1819
-pilz_pmi5		MACH_PILZ_PMI5		PILZ_PMI5		1820
-jade			MACH_JADE		JADE			1821
-ks8695_softplc		MACH_KS8695_SOFTPLC	KS8695_SOFTPLC		1822
-gprisc3			MACH_GPRISC3		GPRISC3			1823
 stamp9g20		MACH_STAMP9G20		STAMP9G20		1824
-smdk6430		MACH_SMDK6430		SMDK6430		1825
 smdkc100		MACH_SMDKC100		SMDKC100		1826
 tavorevb		MACH_TAVOREVB		TAVOREVB		1827
 saar			MACH_SAAR		SAAR			1828
-deister_eyecam		MACH_DEISTER_EYECAM	DEISTER_EYECAM		1829
 at91sam9m10g45ek	MACH_AT91SAM9M10G45EK	AT91SAM9M10G45EK	1830
-linkstation_produo	MACH_LINKSTATION_PRODUO	LINKSTATION_PRODUO	1831
-hit_b0			MACH_HIT_B0		HIT_B0			1832
-adx_rmu			MACH_ADX_RMU		ADX_RMU			1833
-xg_cpe_main		MACH_XG_CPE_MAIN	XG_CPE_MAIN		1834
-edb9407a		MACH_EDB9407A		EDB9407A		1835
-dtb9608			MACH_DTB9608		DTB9608			1836
-em104v1			MACH_EM104V1		EM104V1			1837
-demo			MACH_DEMO		DEMO			1838
-logi9260		MACH_LOGI9260		LOGI9260		1839
-mx31_exm32		MACH_MX31_EXM32		MX31_EXM32		1840
-usb_a9g20		MACH_USB_A9G20		USB_A9G20		1841
-picproje2008		MACH_PICPROJE2008	PICPROJE2008		1842
-cs_e9315		MACH_CS_E9315		CS_E9315		1843
-qil_a9g20		MACH_QIL_A9G20		QIL_A9G20		1844
-sha_pon020		MACH_SHA_PON020		SHA_PON020		1845
-nad			MACH_NAD		NAD			1846
-sbc35_a9260		MACH_SBC35_A9260	SBC35_A9260		1847
-sbc35_a9g20		MACH_SBC35_A9G20	SBC35_A9G20		1848
-davinci_beginning	MACH_DAVINCI_BEGINNING	DAVINCI_BEGINNING	1849
-uwc			MACH_UWC		UWC			1850
 mxlads			MACH_MXLADS		MXLADS			1851
-htcnike			MACH_HTCNIKE		HTCNIKE			1852
-deister_pxa270		MACH_DEISTER_PXA270	DEISTER_PXA270		1853
-cme9210js		MACH_CME9210JS		CME9210JS		1854
-cc9p9360		MACH_CC9P9360		CC9P9360		1855
-mocha			MACH_MOCHA		MOCHA			1856
-wapd170ag		MACH_WAPD170AG		WAPD170AG		1857
 linkstation_mini	MACH_LINKSTATION_MINI	LINKSTATION_MINI	1858
 afeb9260		MACH_AFEB9260		AFEB9260		1859
-w90x900			MACH_W90X900		W90X900			1860
-w90x700			MACH_W90X700		W90X700			1861
-kt300ip			MACH_KT300IP		KT300IP			1862
-kt300ip_g20		MACH_KT300IP_G20	KT300IP_G20		1863
-srcm			MACH_SRCM		SRCM			1864
-wlnx_9260		MACH_WLNX_9260		WLNX_9260		1865
-openmoko_gta03		MACH_OPENMOKO_GTA03	OPENMOKO_GTA03		1866
-osprey2			MACH_OSPREY2		OSPREY2			1867
-kbio9260		MACH_KBIO9260		KBIO9260		1868
-ginza			MACH_GINZA		GINZA			1869
-a636n			MACH_A636N		A636N			1870
 imx27ipcam		MACH_IMX27IPCAM		IMX27IPCAM		1871
-nemoc			MACH_NEMOC		NEMOC			1872
-geneva			MACH_GENEVA		GENEVA			1873
-htcpharos		MACH_HTCPHAROS		HTCPHAROS		1874
-neonc			MACH_NEONC		NEONC			1875
-nas7100			MACH_NAS7100		NAS7100			1876
-teuphone		MACH_TEUPHONE		TEUPHONE		1877
-annax_eth2		MACH_ANNAX_ETH2		ANNAX_ETH2		1878
-csb733			MACH_CSB733		CSB733			1879
-bk3			MACH_BK3		BK3			1880
-omap_em32		MACH_OMAP_EM32		OMAP_EM32		1881
-et9261cp		MACH_ET9261CP		ET9261CP		1882
-jasperc			MACH_JASPERC		JASPERC			1883
-issi_arm9		MACH_ISSI_ARM9		ISSI_ARM9		1884
-ued			MACH_UED		UED			1885
-esiblade		MACH_ESIBLADE		ESIBLADE		1886
-eye02			MACH_EYE02		EYE02			1887
-imx27kbd		MACH_IMX27KBD		IMX27KBD		1888
-sst61vc010_fpga		MACH_SST61VC010_FPGA	SST61VC010_FPGA		1889
-kixvp435		MACH_KIXVP435		KIXVP435		1890
-kixnp435		MACH_KIXNP435		KIXNP435		1891
-africa			MACH_AFRICA		AFRICA			1892
-nh233			MACH_NH233		NH233			1893
 rd88f6183ap_ge		MACH_RD88F6183AP_GE	RD88F6183AP_GE		1894
-bcm4760			MACH_BCM4760		BCM4760			1895
-eddy_v2			MACH_EDDY_V2		EDDY_V2			1896
 realview_pba8		MACH_REALVIEW_PBA8	REALVIEW_PBA8		1897
-hid_a7			MACH_HID_A7		HID_A7			1898
-hero			MACH_HERO		HERO			1899
-omap_poseidon		MACH_OMAP_POSEIDON	OMAP_POSEIDON		1900
 realview_pbx		MACH_REALVIEW_PBX	REALVIEW_PBX		1901
 micro9s			MACH_MICRO9S		MICRO9S			1902
-mako			MACH_MAKO		MAKO			1903
-xdaflame		MACH_XDAFLAME		XDAFLAME		1904
-phidget_sbc2		MACH_PHIDGET_SBC2	PHIDGET_SBC2		1905
-limestone		MACH_LIMESTONE		LIMESTONE		1906
-iprobe_c32		MACH_IPROBE_C32		IPROBE_C32		1907
 rut100			MACH_RUT100		RUT100			1908
-asusp535		MACH_ASUSP535		ASUSP535		1909
-htcraphael		MACH_HTCRAPHAEL		HTCRAPHAEL		1910
-sygdg1			MACH_SYGDG1		SYGDG1			1911
-sygdg2			MACH_SYGDG2		SYGDG2			1912
-seoul			MACH_SEOUL		SEOUL			1913
-salerno			MACH_SALERNO		SALERNO			1914
-ucn_s3c64xx		MACH_UCN_S3C64XX	UCN_S3C64XX		1915
-msm7201a		MACH_MSM7201A		MSM7201A		1916
-lpr1			MACH_LPR1		LPR1			1917
-armadillo500fx		MACH_ARMADILLO500FX	ARMADILLO500FX		1918
 g3evm			MACH_G3EVM		G3EVM			1919
-z3_dm355		MACH_Z3_DM355		Z3_DM355		1920
 w90p910evb		MACH_W90P910EVB		W90P910EVB		1921
-w90p920evb		MACH_W90P920EVB		W90P920EVB		1922
 w90p950evb		MACH_W90P950EVB		W90P950EVB		1923
 w90n960evb		MACH_W90N960EVB		W90N960EVB		1924
-camhd			MACH_CAMHD		CAMHD			1925
-mvc100			MACH_MVC100		MVC100			1926
-electrum_200		MACH_ELECTRUM_200	ELECTRUM_200		1927
-htcjade			MACH_HTCJADE		HTCJADE			1928
-memphis			MACH_MEMPHIS		MEMPHIS			1929
-imx27sbc		MACH_IMX27SBC		IMX27SBC		1930
-lextar			MACH_LEXTAR		LEXTAR			1931
 mv88f6281gtw_ge		MACH_MV88F6281GTW_GE	MV88F6281GTW_GE		1932
 ncp			MACH_NCP		NCP			1933
-z32an_series		MACH_Z32AN		Z32AN			1934
-tmq_capd		MACH_TMQ_CAPD		TMQ_CAPD		1935
-omap3_wl		MACH_OMAP3_WL		OMAP3_WL		1936
-chumby			MACH_CHUMBY		CHUMBY			1937
-atsarm9			MACH_ATSARM9		ATSARM9			1938
 davinci_dm365_evm	MACH_DAVINCI_DM365_EVM	DAVINCI_DM365_EVM	1939
-bahamas			MACH_BAHAMAS		BAHAMAS			1940
-das			MACH_DAS		DAS			1941
-minidas			MACH_MINIDAS		MINIDAS			1942
-vk1000			MACH_VK1000		VK1000			1943
 centro			MACH_CENTRO		CENTRO			1944
-ctera_2bay		MACH_CTERA_2BAY		CTERA_2BAY		1945
-edgeconnect		MACH_EDGECONNECT	EDGECONNECT		1946
-nd27000			MACH_ND27000		ND27000			1947
-cobra			MACH_GEMALTO_COBRA	GEMALTO_COBRA		1948
-ingelabs_comet		MACH_INGELABS_COMET	INGELABS_COMET		1949
-pollux_wiz		MACH_POLLUX_WIZ		POLLUX_WIZ		1950
-blackstone		MACH_BLACKSTONE		BLACKSTONE		1951
-topaz			MACH_TOPAZ		TOPAZ			1952
-aixle			MACH_AIXLE		AIXLE			1953
-mw998			MACH_MW998		MW998			1954
 nokia_rx51		MACH_NOKIA_RX51		NOKIA_RX51		1955
-vsc5605ev		MACH_VSC5605EV		VSC5605EV		1956
-nt98700dk		MACH_NT98700DK		NT98700DK		1957
-icontact		MACH_ICONTACT		ICONTACT		1958
-swarco_frcpu		MACH_SWARCO_FRCPU	SWARCO_FRCPU		1959
-swarco_scpu		MACH_SWARCO_SCPU	SWARCO_SCPU		1960
-bbox_p16		MACH_BBOX_P16		BBOX_P16		1961
-bstd			MACH_BSTD		BSTD			1962
-sbc2440ii		MACH_SBC2440II		SBC2440II		1963
-pcm034			MACH_PCM034		PCM034			1964
-neso			MACH_NESO		NESO			1965
-wlnx_9g20		MACH_WLNX_9G20		WLNX_9G20		1966
 omap_zoom2		MACH_OMAP_ZOOM2		OMAP_ZOOM2		1967
-totemnova		MACH_TOTEMNOVA		TOTEMNOVA		1968
-c5000			MACH_C5000		C5000			1969
-unipo_at91sam9263	MACH_UNIPO_AT91SAM9263	UNIPO_AT91SAM9263	1970
-ethernut5		MACH_ETHERNUT5		ETHERNUT5		1971
-arm11			MACH_ARM11		ARM11			1972
 cpuat9260		MACH_CPUAT9260		CPUAT9260		1973
-cpupxa255		MACH_CPUPXA255		CPUPXA255		1974
 eukrea_cpuimx27		MACH_CPUIMX27		CPUIMX27		1975
-cheflux			MACH_CHEFLUX		CHEFLUX			1976
-eb_cpux9k2		MACH_EB_CPUX9K2		EB_CPUX9K2		1977
-opcotec			MACH_OPCOTEC		OPCOTEC			1978
-yt			MACH_YT			YT			1979
-motoq			MACH_MOTOQ		MOTOQ			1980
-bsb1			MACH_BSB1		BSB1			1981
 acs5k			MACH_ACS5K		ACS5K			1982
-milan			MACH_MILAN		MILAN			1983
-quartzv2		MACH_QUARTZV2		QUARTZV2		1984
-rsvp			MACH_RSVP		RSVP			1985
-rmp200			MACH_RMP200		RMP200			1986
 snapper_9260		MACH_SNAPPER_9260	SNAPPER_9260		1987
 dsm320			MACH_DSM320		DSM320			1988
-adsgcm			MACH_ADSGCM		ADSGCM			1989
-ase2_400		MACH_ASE2_400		ASE2_400		1990
-pizza			MACH_PIZZA		PIZZA			1991
-spot_ngpl		MACH_SPOT_NGPL		SPOT_NGPL		1992
-armata			MACH_ARMATA		ARMATA			1993
 exeda			MACH_EXEDA		EXEDA			1994
-mx31sf005		MACH_MX31SF005		MX31SF005		1995
-f5d8231_4_v2		MACH_F5D8231_4_V2	F5D8231_4_V2		1996
-q2440			MACH_Q2440		Q2440			1997
-qq2440			MACH_QQ2440		QQ2440			1998
 mini2440		MACH_MINI2440		MINI2440		1999
 colibri300		MACH_COLIBRI300		COLIBRI300		2000
-jades			MACH_JADES		JADES			2001
-spark			MACH_SPARK		SPARK			2002
-benzina			MACH_BENZINA		BENZINA			2003
-blaze			MACH_BLAZE		BLAZE			2004
 linkstation_ls_hgl	MACH_LINKSTATION_LS_HGL	LINKSTATION_LS_HGL	2005
-htckovsky		MACH_HTCKOVSKY		HTCKOVSKY		2006
-sony_prs505		MACH_SONY_PRS505	SONY_PRS505		2007
-hanlin_v3		MACH_HANLIN_V3		HANLIN_V3		2008
-sapphira		MACH_SAPPHIRA		SAPPHIRA		2009
-dack_sda_01		MACH_DACK_SDA_01	DACK_SDA_01		2010
-armbox			MACH_ARMBOX		ARMBOX			2011
-harris_rvp		MACH_HARRIS_RVP		HARRIS_RVP		2012
-ribaldo			MACH_RIBALDO		RIBALDO			2013
-agora			MACH_AGORA		AGORA			2014
-omap3_mini		MACH_OMAP3_MINI		OMAP3_MINI		2015
-a9sam6432_b		MACH_A9SAM6432_B	A9SAM6432_B		2016
-usg2410			MACH_USG2410		USG2410			2017
-pc72052_i10_revb	MACH_PC72052_I10_REVB	PC72052_I10_REVB	2018
-mx35_exm32		MACH_MX35_EXM32		MX35_EXM32		2019
-topas910		MACH_TOPAS910		TOPAS910		2020
-hyena			MACH_HYENA		HYENA			2021
-pospax			MACH_POSPAX		POSPAX			2022
-hdl_gx			MACH_HDL_GX		HDL_GX			2023
-ctera_4bay		MACH_CTERA_4BAY		CTERA_4BAY		2024
-ctera_plug_c		MACH_CTERA_PLUG_C	CTERA_PLUG_C		2025
-crwea_plug_i		MACH_CRWEA_PLUG_I	CRWEA_PLUG_I		2026
-egauge2			MACH_EGAUGE2		EGAUGE2			2027
-didj			MACH_DIDJ		DIDJ			2028
-m_s3c2443		MACH_MEISTER		MEISTER			2029
-htcblackstone		MACH_HTCBLACKSTONE	HTCBLACKSTONE		2030
 cpuat9g20		MACH_CPUAT9G20		CPUAT9G20		2031
 smdk6440		MACH_SMDK6440		SMDK6440		2032
-omap_35xx_mvp		MACH_OMAP_35XX_MVP	OMAP_35XX_MVP		2033
-ctera_plug_i		MACH_CTERA_PLUG_I	CTERA_PLUG_I		2034
-pvg610_100		MACH_PVG610		PVG610			2035
-hprw6815		MACH_HPRW6815		HPRW6815		2036
-omap3_oswald		MACH_OMAP3_OSWALD	OMAP3_OSWALD		2037
 nas4220b		MACH_NAS4220B		NAS4220B		2038
-htcraphael_cdma		MACH_HTCRAPHAEL_CDMA	HTCRAPHAEL_CDMA		2039
-htcdiamond_cdma		MACH_HTCDIAMOND_CDMA	HTCDIAMOND_CDMA		2040
-scaler			MACH_SCALER		SCALER			2041
 zylonite2		MACH_ZYLONITE2		ZYLONITE2		2042
 aspenite		MACH_ASPENITE		ASPENITE		2043
-teton			MACH_TETON		TETON			2044
 ttc_dkb			MACH_TTC_DKB		TTC_DKB			2045
-bishop2			MACH_BISHOP2		BISHOP2			2046
-ippv5			MACH_IPPV5		IPPV5			2047
-farm926			MACH_FARM926		FARM926			2048
-mmccpu			MACH_MMCCPU		MMCCPU			2049
-sgmsfl			MACH_SGMSFL		SGMSFL			2050
-tt8000			MACH_TT8000		TT8000			2051
-zrn4300lp		MACH_ZRN4300LP		ZRN4300LP		2052
-mptc			MACH_MPTC		MPTC			2053
-h6051			MACH_H6051		H6051			2054
-pvg610_101		MACH_PVG610_101		PVG610_101		2055
-stamp9261_pc_evb	MACH_STAMP9261_PC_EVB	STAMP9261_PC_EVB	2056
-pelco_odysseus		MACH_PELCO_ODYSSEUS	PELCO_ODYSSEUS		2057
-tny_a9260		MACH_TNY_A9260		TNY_A9260		2058
-tny_a9g20		MACH_TNY_A9G20		TNY_A9G20		2059
-aesop_mp2530f		MACH_AESOP_MP2530F	AESOP_MP2530F		2060
-dx900			MACH_DX900		DX900			2061
-cpodc2			MACH_CPODC2		CPODC2			2062
-tilt_8925		MACH_TILT_8925		TILT_8925		2063
-davinci_dm357_evm	MACH_DAVINCI_DM357_EVM	DAVINCI_DM357_EVM	2064
-swordfish		MACH_SWORDFISH		SWORDFISH		2065
-corvus			MACH_CORVUS		CORVUS			2066
-taurus			MACH_TAURUS		TAURUS			2067
-axm			MACH_AXM		AXM			2068
-axc			MACH_AXC		AXC			2069
-baby			MACH_BABY		BABY			2070
-mp200			MACH_MP200		MP200			2071
 pcm043			MACH_PCM043		PCM043			2072
-hanlin_v3c		MACH_HANLIN_V3C		HANLIN_V3C		2073
-kbk9g20			MACH_KBK9G20		KBK9G20			2074
-adsturbog5		MACH_ADSTURBOG5		ADSTURBOG5		2075
-avenger_lite1		MACH_AVENGER_LITE1	AVENGER_LITE1		2076
-suc82x			MACH_SUC		SUC			2077
-at91sam7s256		MACH_AT91SAM7S256	AT91SAM7S256		2078
-mendoza			MACH_MENDOZA		MENDOZA			2079
-kira			MACH_KIRA		KIRA			2080
-mx1hbm			MACH_MX1HBM		MX1HBM			2081
-quatro43xx		MACH_QUATRO43XX		QUATRO43XX		2082
-quatro4230		MACH_QUATRO4230		QUATRO4230		2083
-nsb400			MACH_NSB400		NSB400			2084
-drp255			MACH_DRP255		DRP255			2085
-thoth			MACH_THOTH		THOTH			2086
-firestone		MACH_FIRESTONE		FIRESTONE		2087
-asusp750		MACH_ASUSP750		ASUSP750		2088
-ctera_dl		MACH_CTERA_DL		CTERA_DL		2089
-socr			MACH_SOCR		SOCR			2090
-htcoxygen		MACH_HTCOXYGEN		HTCOXYGEN		2091
-heroc			MACH_HEROC		HEROC			2092
-zeno6800		MACH_ZENO6800		ZENO6800		2093
-sc2mcs			MACH_SC2MCS		SC2MCS			2094
-gene100			MACH_GENE100		GENE100			2095
-as353x			MACH_AS353X		AS353X			2096
 sheevaplug		MACH_SHEEVAPLUG		SHEEVAPLUG		2097
-at91sam9g20		MACH_AT91SAM9G20	AT91SAM9G20		2098
-mv88f6192gtw_fe		MACH_MV88F6192GTW_FE	MV88F6192GTW_FE		2099
-cc9200			MACH_CC9200		CC9200			2100
-sm9200			MACH_SM9200		SM9200			2101
-tp9200			MACH_TP9200		TP9200			2102
-snapperdv		MACH_SNAPPERDV		SNAPPERDV		2103
 avengers_lite		MACH_AVENGERS_LITE	AVENGERS_LITE		2104
-avengers_lite1		MACH_AVENGERS_LITE1	AVENGERS_LITE1		2105
-omap3axon		MACH_OMAP3AXON		OMAP3AXON		2106
-ma8xx			MACH_MA8XX		MA8XX			2107
-mp201ek			MACH_MP201EK		MP201EK			2108
-davinci_tux		MACH_DAVINCI_TUX	DAVINCI_TUX		2109
-mpa1600			MACH_MPA1600		MPA1600			2110
-pelco_troy		MACH_PELCO_TROY		PELCO_TROY		2111
-nsb667			MACH_NSB667		NSB667			2112
-rovers5_4mpix		MACH_ROVERS5_4MPIX	ROVERS5_4MPIX		2113
-twocom			MACH_TWOCOM		TWOCOM			2114
-ubisys_p9_rcu3r2	MACH_UBISYS_P9_RCU3R2	UBISYS_P9_RCU3R2	2115
-hero_espresso		MACH_HERO_ESPRESSO	HERO_ESPRESSO		2116
-afeusb			MACH_AFEUSB		AFEUSB			2117
-t830			MACH_T830		T830			2118
-spd8020_cc		MACH_SPD8020_CC		SPD8020_CC		2119
-om_3d7k			MACH_OM_3D7K		OM_3D7K			2120
-picocom2		MACH_PICOCOM2		PICOCOM2		2121
-uwg4mx27		MACH_UWG4MX27		UWG4MX27		2122
-uwg4mx31		MACH_UWG4MX31		UWG4MX31		2123
-cherry			MACH_CHERRY		CHERRY			2124
 mx51_babbage		MACH_MX51_BABBAGE	MX51_BABBAGE		2125
-s3c2440turkiye		MACH_S3C2440TURKIYE	S3C2440TURKIYE		2126
-tx37			MACH_TX37		TX37			2127
-sbc2800_9g20		MACH_SBC2800_9G20	SBC2800_9G20		2128
-benzglb			MACH_BENZGLB		BENZGLB			2129
-benztd			MACH_BENZTD		BENZTD			2130
-cartesio_plus		MACH_CARTESIO_PLUS	CARTESIO_PLUS		2131
-solrad_g20		MACH_SOLRAD_G20		SOLRAD_G20		2132
-mx27wallace		MACH_MX27WALLACE	MX27WALLACE		2133
-fmzwebmodul		MACH_FMZWEBMODUL	FMZWEBMODUL		2134
 rd78x00_masa		MACH_RD78X00_MASA	RD78X00_MASA		2135
-smallogger		MACH_SMALLOGGER		SMALLOGGER		2136
-ccw9p9215		MACH_CCW9P9215		CCW9P9215		2137
 dm355_leopard		MACH_DM355_LEOPARD	DM355_LEOPARD		2138
 ts219			MACH_TS219		TS219			2139
-tny_a9263		MACH_TNY_A9263		TNY_A9263		2140
-apollo			MACH_APOLLO		APOLLO			2141
-at91cap9stk		MACH_AT91CAP9STK	AT91CAP9STK		2142
-spc300			MACH_SPC300		SPC300			2143
-eko			MACH_EKO		EKO			2144
-ccw9m2443		MACH_CCW9M2443		CCW9M2443		2145
-ccw9m2443js		MACH_CCW9M2443JS	CCW9M2443JS		2146
-m2m_router_device	MACH_M2M_ROUTER_DEVICE	M2M_ROUTER_DEVICE	2147
-str9104nas		MACH_STAR9104NAS	STAR9104NAS		2148
 pca100			MACH_PCA100		PCA100			2149
-z3_dm365_mod_01		MACH_Z3_DM365_MOD_01	Z3_DM365_MOD_01		2150
-hipox			MACH_HIPOX		HIPOX			2151
-omap3_piteds		MACH_OMAP3_PITEDS	OMAP3_PITEDS		2152
-bm150r			MACH_BM150R		BM150R			2153
-tbone			MACH_TBONE		TBONE			2154
-merlin			MACH_MERLIN		MERLIN			2155
-falcon			MACH_FALCON		FALCON			2156
 davinci_da850_evm	MACH_DAVINCI_DA850_EVM	DAVINCI_DA850_EVM	2157
-s5p6440			MACH_S5P6440		S5P6440			2158
 at91sam9g10ek		MACH_AT91SAM9G10EK	AT91SAM9G10EK		2159
 omap_4430sdp		MACH_OMAP_4430SDP	OMAP_4430SDP		2160
-lpc313x			MACH_LPC313X		LPC313X			2161
 magx_zn5		MACH_MAGX_ZN5		MAGX_ZN5		2162
-magx_em30		MACH_MAGX_EM30		MAGX_EM30		2163
-magx_ve66		MACH_MAGX_VE66		MAGX_VE66		2164
-meesc			MACH_MEESC		MEESC			2165
-otc570			MACH_OTC570		OTC570			2166
-bcu2412			MACH_BCU2412		BCU2412			2167
-beacon			MACH_BEACON		BEACON			2168
-actia_tgw		MACH_ACTIA_TGW		ACTIA_TGW		2169
-e4430			MACH_E4430		E4430			2170
-ql300			MACH_QL300		QL300			2171
-btmavb101		MACH_BTMAVB101		BTMAVB101		2172
-btmawb101		MACH_BTMAWB101		BTMAWB101		2173
-sq201			MACH_SQ201		SQ201			2174
-quatro45xx		MACH_QUATRO45XX		QUATRO45XX		2175
-openpad			MACH_OPENPAD		OPENPAD			2176
-tx25			MACH_TX25		TX25			2177
 omap3_torpedo		MACH_OMAP3_TORPEDO	OMAP3_TORPEDO		2178
-htcraphael_k		MACH_HTCRAPHAEL_K	HTCRAPHAEL_K		2179
-lal43			MACH_LAL43		LAL43			2181
-htcraphael_cdma500	MACH_HTCRAPHAEL_CDMA500	HTCRAPHAEL_CDMA500	2182
 anw6410			MACH_ANW6410		ANW6410			2183
-htcprophet		MACH_HTCPROPHET		HTCPROPHET		2185
-cfa_10022		MACH_CFA_10022		CFA_10022		2186
 imx27_visstrim_m10	MACH_IMX27_VISSTRIM_M10	IMX27_VISSTRIM_M10	2187
-px2imx27		MACH_PX2IMX27		PX2IMX27		2188
-stm3210e_eval		MACH_STM3210E_EVAL	STM3210E_EVAL		2189
-dvs10			MACH_DVS10		DVS10			2190
 portuxg20		MACH_PORTUXG20		PORTUXG20		2191
-arm_spv			MACH_ARM_SPV		ARM_SPV			2192
 smdkc110		MACH_SMDKC110		SMDKC110		2193
-cabespresso		MACH_CABESPRESSO	CABESPRESSO		2194
-hmc800			MACH_HMC800		HMC800			2195
-sholes			MACH_SHOLES		SHOLES			2196
-btmxc31			MACH_BTMXC31		BTMXC31			2197
-dt501			MACH_DT501		DT501			2198
-ktx			MACH_KTX		KTX			2199
 omap3517evm		MACH_OMAP3517EVM	OMAP3517EVM		2200
 netspace_v2		MACH_NETSPACE_V2	NETSPACE_V2		2201
 netspace_max_v2		MACH_NETSPACE_MAX_V2	NETSPACE_MAX_V2		2202
 d2net_v2		MACH_D2NET_V2		D2NET_V2		2203
 net2big_v2		MACH_NET2BIG_V2		NET2BIG_V2		2204
-net4big_v2		MACH_NET4BIG_V2		NET4BIG_V2		2205
 net5big_v2		MACH_NET5BIG_V2		NET5BIG_V2		2206
-endb2443		MACH_ENDB2443		ENDB2443		2207
 inetspace_v2		MACH_INETSPACE_V2	INETSPACE_V2		2208
-tros			MACH_TROS		TROS			2209
-pelco_homer		MACH_PELCO_HOMER	PELCO_HOMER		2210
-ofsp8			MACH_OFSP8		OFSP8			2211
 at91sam9g45ekes		MACH_AT91SAM9G45EKES	AT91SAM9G45EKES		2212
-guf_cupid		MACH_GUF_CUPID		GUF_CUPID		2213
-eab1r			MACH_EAB1R		EAB1R			2214
-desirec			MACH_DESIREC		DESIREC			2215
-cordoba			MACH_CORDOBA		CORDOBA			2216
-irvine			MACH_IRVINE		IRVINE			2217
-sff772			MACH_SFF772		SFF772			2218
-pelco_milano		MACH_PELCO_MILANO	PELCO_MILANO		2219
 pc7302			MACH_PC7302		PC7302			2220
-bip6000			MACH_BIP6000		BIP6000			2221
-silvermoon		MACH_SILVERMOON		SILVERMOON		2222
-vc0830			MACH_VC0830		VC0830			2223
-dt430			MACH_DT430		DT430			2224
-ji42pf			MACH_JI42PF		JI42PF			2225
-gnet_ksm		MACH_GNET_KSM		GNET_KSM		2226
-gnet_sgm		MACH_GNET_SGM		GNET_SGM		2227
-gnet_sgr		MACH_GNET_SGR		GNET_SGR		2228
-omap3_icetekevm		MACH_OMAP3_ICETEKEVM	OMAP3_ICETEKEVM		2229
-pnp			MACH_PNP		PNP			2230
-ctera_2bay_k		MACH_CTERA_2BAY_K	CTERA_2BAY_K		2231
-ctera_2bay_u		MACH_CTERA_2BAY_U	CTERA_2BAY_U		2232
-sas_c			MACH_SAS_C		SAS_C			2233
-vma2315			MACH_VMA2315		VMA2315			2234
-vcs			MACH_VCS		VCS			2235
 spear600		MACH_SPEAR600		SPEAR600		2236
 spear300		MACH_SPEAR300		SPEAR300		2237
-spear1300		MACH_SPEAR1300		SPEAR1300		2238
 lilly1131		MACH_LILLY1131		LILLY1131		2239
-arvoo_ax301		MACH_ARVOO_AX301	ARVOO_AX301		2240
-mapphone		MACH_MAPPHONE		MAPPHONE		2241
-legend			MACH_LEGEND		LEGEND			2242
-salsa			MACH_SALSA		SALSA			2243
-lounge			MACH_LOUNGE		LOUNGE			2244
-vision			MACH_VISION		VISION			2245
-vmb20			MACH_VMB20		VMB20			2246
-hy2410			MACH_HY2410		HY2410			2247
-hy9315			MACH_HY9315		HY9315			2248
-bullwinkle		MACH_BULLWINKLE		BULLWINKLE		2249
-arm_ultimator2		MACH_ARM_ULTIMATOR2	ARM_ULTIMATOR2		2250
-vs_v210			MACH_VS_V210		VS_V210			2252
-vs_v212			MACH_VS_V212		VS_V212			2253
 hmt			MACH_HMT		HMT			2254
-km_kirkwood		MACH_KM_KIRKWOOD	KM_KIRKWOOD		2255
-vesper			MACH_VESPER		VESPER			2256
-str9			MACH_STR9		STR9			2257
-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
-sgh_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
 vexpress		MACH_VEXPRESS		VEXPRESS		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
-sc_p270			MACH_SC_P270		SC_P270			2296
-atlas5_evb		MACH_ATLAS5_EVB		ATLAS5_EVB		2297
-pelco_lobox		MACH_PELCO_LOBOX	PELCO_LOBOX		2298
-dilax_pcu200		MACH_DILAX_PCU200	DILAX_PCU200		2299
-leonardo		MACH_LEONARDO		LEONARDO		2300
-zoran_approach7		MACH_ZORAN_APPROACH7	ZORAN_APPROACH7		2301
-dp6xx			MACH_DP6XX		DP6XX			2302
-bcm2153_vesper		MACH_BCM2153_VESPER	BCM2153_VESPER		2303
 mahimahi		MACH_MAHIMAHI		MAHIMAHI		2304
-clickc			MACH_CLICKC		CLICKC			2305
-zb_gateway		MACH_ZB_GATEWAY		ZB_GATEWAY		2306
-tazcard			MACH_TAZCARD		TAZCARD			2307
-tazdev			MACH_TAZDEV		TAZDEV			2308
-annax_cb_arm		MACH_ANNAX_CB_ARM	ANNAX_CB_ARM		2309
-annax_dm3		MACH_ANNAX_DM3		ANNAX_DM3		2310
-cerebric		MACH_CEREBRIC		CEREBRIC		2311
-orca			MACH_ORCA		ORCA			2312
-pc9260			MACH_PC9260		PC9260			2313
-ems285a			MACH_EMS285A		EMS285A			2314
-gec2410			MACH_GEC2410		GEC2410			2315
-gec2440			MACH_GEC2440		GEC2440			2316
-mw903			MACH_ARCH_MW903		ARCH_MW903		2317
-mw2440			MACH_MW2440		MW2440			2318
-ecac2378		MACH_ECAC2378		ECAC2378		2319
-tazkiosk		MACH_TAZKIOSK		TAZKIOSK		2320
-whiterabbit_mch		MACH_WHITERABBIT_MCH	WHITERABBIT_MCH		2321
-sbox9263		MACH_SBOX9263		SBOX9263		2322
-oreo			MACH_OREO		OREO			2323
 smdk6442		MACH_SMDK6442		SMDK6442		2324
 openrd_base		MACH_OPENRD_BASE	OPENRD_BASE		2325
-incredible		MACH_INCREDIBLE		INCREDIBLE		2326
-incrediblec		MACH_INCREDIBLEC	INCREDIBLEC		2327
-heroct			MACH_HEROCT		HEROCT			2328
-mmnet1000		MACH_MMNET1000		MMNET1000		2329
 devkit8000		MACH_DEVKIT8000		DEVKIT8000		2330
-devkit9000		MACH_DEVKIT9000		DEVKIT9000		2331
-mx31txtr		MACH_MX31TXTR		MX31TXTR		2332
-u380			MACH_U380		U380			2333
-oamp3_hualu		MACH_HUALU_BOARD	HUALU_BOARD		2334
-npcmx50			MACH_NPCMX50		NPCMX50			2335
 mx51_efikamx		MACH_MX51_EFIKAMX	MX51_EFIKAMX		2336
-mx51_lange52		MACH_MX51_LANGE52	MX51_LANGE52		2337
-riom			MACH_RIOM		RIOM			2338
-comcas			MACH_COMCAS		COMCAS			2339
-wsi_mx27		MACH_WSI_MX27		WSI_MX27		2340
 cm_t35			MACH_CM_T35		CM_T35			2341
 net2big			MACH_NET2BIG		NET2BIG			2342
-motorola_a1600		MACH_MOTOROLA_A1600	MOTOROLA_A1600		2343
 igep0020		MACH_IGEP0020		IGEP0020		2344
-igep0010		MACH_IGEP0010		IGEP0010		2345
-mv6281gtwge2		MACH_MV6281GTWGE2	MV6281GTWGE2		2346
-scat100			MACH_SCAT100		SCAT100			2347
-sanmina			MACH_SANMINA		SANMINA			2348
-momento			MACH_MOMENTO		MOMENTO			2349
-nuc9xx			MACH_NUC9XX		NUC9XX			2350
-nuc910evb		MACH_NUC910EVB		NUC910EVB		2351
-nuc920evb		MACH_NUC920EVB		NUC920EVB		2352
-nuc950evb		MACH_NUC950EVB		NUC950EVB		2353
-nuc945evb		MACH_NUC945EVB		NUC945EVB		2354
-nuc960evb		MACH_NUC960EVB		NUC960EVB		2355
 nuc932evb		MACH_NUC932EVB		NUC932EVB		2356
-nuc900			MACH_NUC900		NUC900			2357
-sd1soc			MACH_SD1SOC		SD1SOC			2358
-ln2440bc		MACH_LN2440BC		LN2440BC		2359
-rsbc			MACH_RSBC		RSBC			2360
 openrd_client		MACH_OPENRD_CLIENT	OPENRD_CLIENT		2361
-hpipaq11x		MACH_HPIPAQ11X		HPIPAQ11X		2362
-wayland			MACH_WAYLAND		WAYLAND			2363
-acnbsx102		MACH_ACNBSX102		ACNBSX102		2364
-hwat91			MACH_HWAT91		HWAT91			2365
-at91sam9263cs		MACH_AT91SAM9263CS	AT91SAM9263CS		2366
-csb732			MACH_CSB732		CSB732			2367
 u8500			MACH_U8500		U8500			2368
-huqiu			MACH_HUQIU		HUQIU			2369
 mx51_efikasb		MACH_MX51_EFIKASB	MX51_EFIKASB		2370
-pmt1g			MACH_PMT1G		PMT1G			2371
-htcelf			MACH_HTCELF		HTCELF			2372
-armadillo420		MACH_ARMADILLO420	ARMADILLO420		2373
-armadillo440		MACH_ARMADILLO440	ARMADILLO440		2374
-u_chip_dual_arm		MACH_U_CHIP_DUAL_ARM	U_CHIP_DUAL_ARM		2375
-csr_bdb3		MACH_CSR_BDB3		CSR_BDB3		2376
-dolby_cat1018		MACH_DOLBY_CAT1018	DOLBY_CAT1018		2377
-hy9307			MACH_HY9307		HY9307			2378
-aspire_easystore	MACH_A_ES		A_ES			2379
-davinci_irif		MACH_DAVINCI_IRIF	DAVINCI_IRIF		2380
-agama9263		MACH_AGAMA9263		AGAMA9263		2381
 marvell_jasper		MACH_MARVELL_JASPER	MARVELL_JASPER		2382
 flint			MACH_FLINT		FLINT			2383
 tavorevb3		MACH_TAVOREVB3		TAVOREVB3		2384
-sch_m490		MACH_SCH_M490		SCH_M490		2386
-rbl01			MACH_RBL01		RBL01			2387
-omnifi			MACH_OMNIFI		OMNIFI			2388
-otavalo			MACH_OTAVALO		OTAVALO			2389
-sienna			MACH_SIENNA		SIENNA			2390
-htc_excalibur_s620	MACH_HTC_EXCALIBUR_S620	HTC_EXCALIBUR_S620	2391
-htc_opal		MACH_HTC_OPAL		HTC_OPAL		2392
 touchbook		MACH_TOUCHBOOK		TOUCHBOOK		2393
-latte			MACH_LATTE		LATTE			2394
-xa200			MACH_XA200		XA200			2395
-nimrod			MACH_NIMROD		NIMROD			2396
-cc9p9215_3g		MACH_CC9P9215_3G	CC9P9215_3G		2397
-cc9p9215_3gjs		MACH_CC9P9215_3GJS	CC9P9215_3GJS		2398
-tk71			MACH_TK71		TK71			2399
-comham3525		MACH_COMHAM3525		COMHAM3525		2400
-mx31erebus		MACH_MX31EREBUS		MX31EREBUS		2401
-mcardmx27		MACH_MCARDMX27		MCARDMX27		2402
-paradise		MACH_PARADISE		PARADISE		2403
-tide			MACH_TIDE		TIDE			2404
-wzl2440			MACH_WZL2440		WZL2440			2405
-sdrdemo			MACH_SDRDEMO		SDRDEMO			2406
-ethercan2		MACH_ETHERCAN2		ETHERCAN2		2407
-ecmimg20		MACH_ECMIMG20		ECMIMG20		2408
-omap_dragon		MACH_OMAP_DRAGON	OMAP_DRAGON		2409
-halo			MACH_HALO		HALO			2410
-huangshan		MACH_HUANGSHAN		HUANGSHAN		2411
-vl_ma2sc		MACH_VL_MA2SC		VL_MA2SC		2412
 raumfeld_rc		MACH_RAUMFELD_RC	RAUMFELD_RC		2413
 raumfeld_connector	MACH_RAUMFELD_CONNECTOR	RAUMFELD_CONNECTOR	2414
 raumfeld_speaker	MACH_RAUMFELD_SPEAKER	RAUMFELD_SPEAKER	2415
-multibus_master		MACH_MULTIBUS_MASTER	MULTIBUS_MASTER		2416
-multibus_pbk		MACH_MULTIBUS_PBK	MULTIBUS_PBK		2417
 tnetv107x		MACH_TNETV107X		TNETV107X		2418
-snake			MACH_SNAKE		SNAKE			2419
-cwmx27			MACH_CWMX27		CWMX27			2420
-sch_m480		MACH_SCH_M480		SCH_M480		2421
-platypus		MACH_PLATYPUS		PLATYPUS		2422
-pss2			MACH_PSS2		PSS2			2423
-davinci_apm150		MACH_DAVINCI_APM150	DAVINCI_APM150		2424
-str9100			MACH_STR9100		STR9100			2425
-net5big			MACH_NET5BIG		NET5BIG			2426
-seabed9263		MACH_SEABED9263		SEABED9263		2427
-mx51_m2id		MACH_MX51_M2ID		MX51_M2ID		2428
-octvocplus_eb		MACH_OCTVOCPLUS_EB	OCTVOCPLUS_EB		2429
-klk_firefox		MACH_KLK_FIREFOX	KLK_FIREFOX		2430
-klk_wirma_module	MACH_KLK_WIRMA_MODULE	KLK_WIRMA_MODULE	2431
-klk_wirma_mmi		MACH_KLK_WIRMA_MMI	KLK_WIRMA_MMI		2432
-supersonic		MACH_SUPERSONIC		SUPERSONIC		2433
-liberty			MACH_LIBERTY		LIBERTY			2434
-mh355			MACH_MH355		MH355			2435
-pc7802			MACH_PC7802		PC7802			2436
-gnet_sgc		MACH_GNET_SGC		GNET_SGC		2437
-einstein15		MACH_EINSTEIN15		EINSTEIN15		2438
-cmpd			MACH_CMPD		CMPD			2439
-davinci_hase1		MACH_DAVINCI_HASE1	DAVINCI_HASE1		2440
-lgeincitephone		MACH_LGEINCITEPHONE	LGEINCITEPHONE		2441
-ea313x			MACH_EA313X		EA313X			2442
-fwbd_39064		MACH_FWBD_39064		FWBD_39064		2443
-fwbd_390128		MACH_FWBD_390128	FWBD_390128		2444
-pelco_moe		MACH_PELCO_MOE		PELCO_MOE		2445
-minimix27		MACH_MINIMIX27		MINIMIX27		2446
-omap3_thunder		MACH_OMAP3_THUNDER	OMAP3_THUNDER		2447
-passionc		MACH_PASSIONC		PASSIONC		2448
-mx27amata		MACH_MX27AMATA		MX27AMATA		2449
-bgat1			MACH_BGAT1		BGAT1			2450
-buzz			MACH_BUZZ		BUZZ			2451
-mb9g20			MACH_MB9G20		MB9G20			2452
-yushan			MACH_YUSHAN		YUSHAN			2453
-lizard			MACH_LIZARD		LIZARD			2454
-omap3polycom		MACH_OMAP3POLYCOM	OMAP3POLYCOM		2455
 smdkv210		MACH_SMDKV210		SMDKV210		2456
-bravo			MACH_BRAVO		BRAVO			2457
-siogentoo1		MACH_SIOGENTOO1		SIOGENTOO1		2458
-siogentoo2		MACH_SIOGENTOO2		SIOGENTOO2		2459
-sm3k			MACH_SM3K		SM3K			2460
-acer_tempo_f900		MACH_ACER_TEMPO_F900	ACER_TEMPO_F900		2461
-sst61vc010_dev		MACH_SST61VC010_DEV	SST61VC010_DEV		2462
-glittertind		MACH_GLITTERTIND	GLITTERTIND		2463
 omap_zoom3		MACH_OMAP_ZOOM3		OMAP_ZOOM3		2464
 omap_3630sdp		MACH_OMAP_3630SDP	OMAP_3630SDP		2465
-cybook2440		MACH_CYBOOK2440		CYBOOK2440		2466
-torino_s		MACH_TORINO_S		TORINO_S		2467
-havana			MACH_HAVANA		HAVANA			2468
-beaumont_11		MACH_BEAUMONT_11	BEAUMONT_11		2469
-vanguard		MACH_VANGUARD		VANGUARD		2470
-s5pc110_draco		MACH_S5PC110_DRACO	S5PC110_DRACO		2471
-cartesio_two		MACH_CARTESIO_TWO	CARTESIO_TWO		2472
-aster			MACH_ASTER		ASTER			2473
-voguesv210		MACH_VOGUESV210		VOGUESV210		2474
-acm500x			MACH_ACM500X		ACM500X			2475
-km9260			MACH_KM9260		KM9260			2476
-nideflexg1		MACH_NIDEFLEXG1		NIDEFLEXG1		2477
-ctera_plug_io		MACH_CTERA_PLUG_IO	CTERA_PLUG_IO		2478
 smartq7			MACH_SMARTQ7		SMARTQ7			2479
-at91sam9g10ek2		MACH_AT91SAM9G10EK2	AT91SAM9G10EK2		2480
-asusp527		MACH_ASUSP527		ASUSP527		2481
-at91sam9g20mpm2		MACH_AT91SAM9G20MPM2	AT91SAM9G20MPM2		2482
-topasa900		MACH_TOPASA900		TOPASA900		2483
-electrum_100		MACH_ELECTRUM_100	ELECTRUM_100		2484
-mx51grb			MACH_MX51GRB		MX51GRB			2485
-xea300			MACH_XEA300		XEA300			2486
-htcstartrek		MACH_HTCSTARTREK	HTCSTARTREK		2487
-lima			MACH_LIMA		LIMA			2488
-csb740			MACH_CSB740		CSB740			2489
-usb_s8815		MACH_USB_S8815		USB_S8815		2490
-watson_efm_plugin	MACH_WATSON_EFM_PLUGIN	WATSON_EFM_PLUGIN	2491
-milkyway		MACH_MILKYWAY		MILKYWAY		2492
 g4evm			MACH_G4EVM		G4EVM			2493
-picomod6		MACH_PICOMOD6		PICOMOD6		2494
 omapl138_hawkboard	MACH_OMAPL138_HAWKBOARD	OMAPL138_HAWKBOARD	2495
-ip6000			MACH_IP6000		IP6000			2496
-ip6010			MACH_IP6010		IP6010			2497
-utm400			MACH_UTM400		UTM400			2498
-omap3_zybex		MACH_OMAP3_ZYBEX	OMAP3_ZYBEX		2499
-wireless_space		MACH_WIRELESS_SPACE	WIRELESS_SPACE		2500
-sx560			MACH_SX560		SX560			2501
 ts41x			MACH_TS41X		TS41X			2502
-elphel10373		MACH_ELPHEL10373	ELPHEL10373		2503
-rhobot			MACH_RHOBOT		RHOBOT			2504
-mx51_refresh		MACH_MX51_REFRESH	MX51_REFRESH		2505
-ls9260			MACH_LS9260		LS9260			2506
-shank			MACH_SHANK		SHANK			2507
-qsd8x50_st1		MACH_QSD8X50_ST1	QSD8X50_ST1		2508
-at91sam9m10ekes		MACH_AT91SAM9M10EKES	AT91SAM9M10EKES		2509
-hiram			MACH_HIRAM		HIRAM			2510
 phy3250			MACH_PHY3250		PHY3250			2511
-ea3250			MACH_EA3250		EA3250			2512
-fdi3250			MACH_FDI3250		FDI3250			2513
-whitestone		MACH_WHITESTONE		WHITESTONE		2514
-at91sam9263nit		MACH_AT91SAM9263NIT	AT91SAM9263NIT		2515
-ccmx51			MACH_CCMX51		CCMX51			2516
-ccmx51js		MACH_CCMX51JS		CCMX51JS		2517
-ccwmx51			MACH_CCWMX51		CCWMX51			2518
-ccwmx51js		MACH_CCWMX51JS		CCWMX51JS		2519
 mini6410		MACH_MINI6410		MINI6410		2520
-tiny6410		MACH_TINY6410		TINY6410		2521
-nano6410		MACH_NANO6410		NANO6410		2522
-at572d940hfnldb		MACH_AT572D940HFNLDB	AT572D940HFNLDB		2523
-htcleo			MACH_HTCLEO		HTCLEO			2524
-avp13			MACH_AVP13		AVP13			2525
-xxsvideod		MACH_XXSVIDEOD		XXSVIDEOD		2526
-vpnext			MACH_VPNEXT		VPNEXT			2527
-swarco_itc3		MACH_SWARCO_ITC3	SWARCO_ITC3		2528
-tx51			MACH_TX51		TX51			2529
-dolby_cat1021		MACH_DOLBY_CAT1021	DOLBY_CAT1021		2530
 mx28evk			MACH_MX28EVK		MX28EVK			2531
-phoenix260		MACH_PHOENIX260		PHOENIX260		2532
-uvaca_stork		MACH_UVACA_STORK	UVACA_STORK		2533
 smartq5			MACH_SMARTQ5		SMARTQ5			2534
-all3078			MACH_ALL3078		ALL3078			2535
-ctera_2bay_ds		MACH_CTERA_2BAY_DS	CTERA_2BAY_DS		2536
-siogentoo3		MACH_SIOGENTOO3		SIOGENTOO3		2537
-epb5000			MACH_EPB5000		EPB5000			2538
-hy9263			MACH_HY9263		HY9263			2539
-acer_tempo_m900		MACH_ACER_TEMPO_M900	ACER_TEMPO_M900		2540
-acer_tempo_dx650	MACH_ACER_TEMPO_DX900	ACER_TEMPO_DX900	2541
-acer_tempo_x960		MACH_ACER_TEMPO_X960	ACER_TEMPO_X960		2542
-acer_eten_v900		MACH_ACER_ETEN_V900	ACER_ETEN_V900		2543
-acer_eten_x900		MACH_ACER_ETEN_X900	ACER_ETEN_X900		2544
-bonnell			MACH_BONNELL		BONNELL			2545
-oht_mx27		MACH_OHT_MX27		OHT_MX27		2546
-htcquartz		MACH_HTCQUARTZ		HTCQUARTZ		2547
 davinci_dm6467tevm	MACH_DAVINCI_DM6467TEVM	DAVINCI_DM6467TEVM	2548
-c3ax03			MACH_C3AX03		C3AX03			2549
 mxt_td60		MACH_MXT_TD60		MXT_TD60		2550
-esyx			MACH_ESYX		ESYX			2551
-dove_db2		MACH_DOVE_DB2		DOVE_DB2		2552
-bulldog			MACH_BULLDOG		BULLDOG			2553
-derell_me2000		MACH_DERELL_ME2000	DERELL_ME2000		2554
-bcmring_base		MACH_BCMRING_BASE	BCMRING_BASE		2555
-bcmring_evm		MACH_BCMRING_EVM	BCMRING_EVM		2556
-bcmring_evm_jazz	MACH_BCMRING_EVM_JAZZ	BCMRING_EVM_JAZZ	2557
-bcmring_sp		MACH_BCMRING_SP		BCMRING_SP		2558
-bcmring_sv		MACH_BCMRING_SV		BCMRING_SV		2559
-bcmring_sv_jazz		MACH_BCMRING_SV_JAZZ	BCMRING_SV_JAZZ		2560
-bcmring_tablet		MACH_BCMRING_TABLET	BCMRING_TABLET		2561
-bcmring_vp		MACH_BCMRING_VP		BCMRING_VP		2562
-bcmring_evm_seikor	MACH_BCMRING_EVM_SEIKOR	BCMRING_EVM_SEIKOR	2563
-bcmring_sp_wqvga	MACH_BCMRING_SP_WQVGA	BCMRING_SP_WQVGA	2564
-bcmring_custom		MACH_BCMRING_CUSTOM	BCMRING_CUSTOM		2565
-acer_s200		MACH_ACER_S200		ACER_S200		2566
-bt270			MACH_BT270		BT270			2567
-iseo			MACH_ISEO		ISEO			2568
-cezanne			MACH_CEZANNE		CEZANNE			2569
-lucca			MACH_LUCCA		LUCCA			2570
-supersmart		MACH_SUPERSMART		SUPERSMART		2571
-arm11_board		MACH_CS_MISANO		CS_MISANO		2572
-magnolia2		MACH_MAGNOLIA2		MAGNOLIA2		2573
-emxx			MACH_EMXX		EMXX			2574
-outlaw			MACH_OUTLAW		OUTLAW			2575
-riot_bei2		MACH_RIOT_BEI2		RIOT_BEI2		2576
-riot_vox		MACH_RIOT_VOX		RIOT_VOX		2577
-riot_x37		MACH_RIOT_X37		RIOT_X37		2578
-mega25mx		MACH_MEGA25MX		MEGA25MX		2579
-benzina2		MACH_BENZINA2		BENZINA2		2580
-ignite			MACH_IGNITE		IGNITE			2581
-foggia			MACH_FOGGIA		FOGGIA			2582
-arezzo			MACH_AREZZO		AREZZO			2583
-leica_skywalker		MACH_LEICA_SKYWALKER	LEICA_SKYWALKER		2584
-jacinto2_jamr		MACH_JACINTO2_JAMR	JACINTO2_JAMR		2585
-gts_nova		MACH_GTS_NOVA		GTS_NOVA		2586
-p3600			MACH_P3600		P3600			2587
-dlt2			MACH_DLT2		DLT2			2588
-df3120			MACH_DF3120		DF3120			2589
-ecucore_9g20		MACH_ECUCORE_9G20	ECUCORE_9G20		2590
-nautel_lpc3240		MACH_NAUTEL_LPC3240	NAUTEL_LPC3240		2591
-glacier			MACH_GLACIER		GLACIER			2592
-phrazer_bulldog		MACH_PHRAZER_BULLDOG	PHRAZER_BULLDOG		2593
-omap3_bulldog		MACH_OMAP3_BULLDOG	OMAP3_BULLDOG		2594
-pca101			MACH_PCA101		PCA101			2595
-buzzc			MACH_BUZZC		BUZZC			2596
-sasie2			MACH_SASIE2		SASIE2			2597
-davinci_cio		MACH_DAVINCI_CIO	DAVINCI_CIO		2598
-smartmeter_dl		MACH_SMARTMETER_DL	SMARTMETER_DL		2599
-wzl6410			MACH_WZL6410		WZL6410			2600
-wzl6410m		MACH_WZL6410M		WZL6410M		2601
-wzl6410f		MACH_WZL6410F		WZL6410F		2602
-wzl6410i		MACH_WZL6410I		WZL6410I		2603
-spacecom1		MACH_SPACECOM1		SPACECOM1		2604
-pingu920		MACH_PINGU920		PINGU920		2605
-bravoc			MACH_BRAVOC		BRAVOC			2606
-cybo2440		MACH_CYBO2440		CYBO2440		2607
-vdssw			MACH_VDSSW		VDSSW			2608
-romulus			MACH_ROMULUS		ROMULUS			2609
-omap_magic		MACH_OMAP_MAGIC		OMAP_MAGIC		2610
-eltd100			MACH_ELTD100		ELTD100			2611
 capc7117		MACH_CAPC7117		CAPC7117		2612
-swan			MACH_SWAN		SWAN			2613
-veu			MACH_VEU		VEU			2614
-rm2			MACH_RM2		RM2			2615
-tt2100			MACH_TT2100		TT2100			2616
-venice			MACH_VENICE		VENICE			2617
-pc7323			MACH_PC7323		PC7323			2618
-masp			MACH_MASP		MASP			2619
-fujitsu_tvstbsoc0	MACH_FUJITSU_TVSTBSOC	FUJITSU_TVSTBSOC	2620
-fujitsu_tvstbsoc1	MACH_FUJITSU_TVSTBSOC1	FUJITSU_TVSTBSOC1	2621
-lexikon			MACH_LEXIKON		LEXIKON			2622
-mini2440v2		MACH_MINI2440V2		MINI2440V2		2623
 icontrol		MACH_ICONTROL		ICONTROL		2624
-gplugd			MACH_SHEEVAD		SHEEVAD			2625
-qsd8x50a_st1_1		MACH_QSD8X50A_ST1_1	QSD8X50A_ST1_1		2626
 qsd8x50a_st1_5		MACH_QSD8X50A_ST1_5	QSD8X50A_ST1_5		2627
-bee			MACH_BEE		BEE			2628
 mx23evk			MACH_MX23EVK		MX23EVK			2629
 ap4evb			MACH_AP4EVB		AP4EVB			2630
-stockholm		MACH_STOCKHOLM		STOCKHOLM		2631
-lpc_h3131		MACH_LPC_H3131		LPC_H3131		2632
-stingray		MACH_STINGRAY		STINGRAY		2633
-kraken			MACH_KRAKEN		KRAKEN			2634
-gw2388			MACH_GW2388		GW2388			2635
-jadecpu			MACH_JADECPU		JADECPU			2636
-carlisle		MACH_CARLISLE		CARLISLE		2637
-lux_sf9			MACH_LUX_SF9		LUX_SF9			2638
-nemid_tb		MACH_NEMID_TB		NEMID_TB		2639
-terrier			MACH_TERRIER		TERRIER			2640
-turbot			MACH_TURBOT		TURBOT			2641
-sanddab			MACH_SANDDAB		SANDDAB			2642
-mx35_cicada		MACH_MX35_CICADA	MX35_CICADA		2643
-ghi2703d		MACH_GHI2703D		GHI2703D		2644
-lux_sfx9		MACH_LUX_SFX9		LUX_SFX9		2645
-lux_sf9g		MACH_LUX_SF9G		LUX_SF9G		2646
-lux_edk9		MACH_LUX_EDK9		LUX_EDK9		2647
-hw90240			MACH_HW90240		HW90240			2648
-dm365_leopard		MACH_DM365_LEOPARD	DM365_LEOPARD		2649
 mityomapl138		MACH_MITYOMAPL138	MITYOMAPL138		2650
-scat110			MACH_SCAT110		SCAT110			2651
-acer_a1			MACH_ACER_A1		ACER_A1			2652
-cmcontrol		MACH_CMCONTROL		CMCONTROL		2653
-pelco_lamar		MACH_PELCO_LAMAR	PELCO_LAMAR		2654
-rfp43			MACH_RFP43		RFP43			2655
-sk86r0301		MACH_SK86R0301		SK86R0301		2656
-ctpxa			MACH_CTPXA		CTPXA			2657
-epb_arm9_a		MACH_EPB_ARM9_A		EPB_ARM9_A		2658
 guruplug		MACH_GURUPLUG		GURUPLUG		2659
 spear310		MACH_SPEAR310		SPEAR310		2660
 spear320		MACH_SPEAR320		SPEAR320		2661
-robotx			MACH_ROBOTX		ROBOTX			2662
-lsxhl			MACH_LSXHL		LSXHL			2663
-smartlite		MACH_SMARTLITE		SMARTLITE		2664
-cws2			MACH_CWS2		CWS2			2665
-m619			MACH_M619		M619			2666
-smartview		MACH_SMARTVIEW		SMARTVIEW		2667
-lsa_salsa		MACH_LSA_SALSA		LSA_SALSA		2668
-kizbox			MACH_KIZBOX		KIZBOX			2669
-htccharmer		MACH_HTCCHARMER		HTCCHARMER		2670
-guf_neso_lt		MACH_GUF_NESO_LT	GUF_NESO_LT		2671
-pm9g45			MACH_PM9G45		PM9G45			2672
-htcpanther		MACH_HTCPANTHER		HTCPANTHER		2673
-htcpanther_cdma		MACH_HTCPANTHER_CDMA	HTCPANTHER_CDMA		2674
-reb01			MACH_REB01		REB01			2675
 aquila			MACH_AQUILA		AQUILA			2676
-spark_sls_hw2		MACH_SPARK_SLS_HW2	SPARK_SLS_HW2		2677
 sheeva_esata		MACH_ESATA_SHEEVAPLUG	ESATA_SHEEVAPLUG	2678
 msm7x30_surf		MACH_MSM7X30_SURF	MSM7X30_SURF		2679
-micro2440		MACH_MICRO2440		MICRO2440		2680
-am2440			MACH_AM2440		AM2440			2681
-tq2440			MACH_TQ2440		TQ2440			2682
-lpc2478oem		MACH_LPC2478OEM		LPC2478OEM		2683
-ak880x			MACH_AK880X		AK880X			2684
-cobra3530		MACH_COBRA3530		COBRA3530		2685
-pmppb			MACH_PMPPB		PMPPB			2686
-u6715			MACH_U6715		U6715			2687
-axar1500_sender		MACH_AXAR1500_SENDER	AXAR1500_SENDER		2688
-g30_dvb			MACH_G30_DVB		G30_DVB			2689
-vc088x			MACH_VC088X		VC088X			2690
-mioa702			MACH_MIOA702		MIOA702			2691
-hpmin			MACH_HPMIN		HPMIN			2692
-ak880xak		MACH_AK880XAK		AK880XAK		2693
-arm926tomap850		MACH_ARM926TOMAP850	ARM926TOMAP850		2694
-lkevm			MACH_LKEVM		LKEVM			2695
-mw6410			MACH_MW6410		MW6410			2696
 terastation_wxl		MACH_TERASTATION_WXL	TERASTATION_WXL		2697
-cpu8000e		MACH_CPU8000E		CPU8000E		2698
-catania			MACH_CATANIA		CATANIA			2699
-tokyo			MACH_TOKYO		TOKYO			2700
-msm7201a_surf		MACH_MSM7201A_SURF	MSM7201A_SURF		2701
-msm7201a_ffa		MACH_MSM7201A_FFA	MSM7201A_FFA		2702
 msm7x25_surf		MACH_MSM7X25_SURF	MSM7X25_SURF		2703
 msm7x25_ffa		MACH_MSM7X25_FFA	MSM7X25_FFA		2704
 msm7x27_surf		MACH_MSM7X27_SURF	MSM7X27_SURF		2705
 msm7x27_ffa		MACH_MSM7X27_FFA	MSM7X27_FFA		2706
 msm7x30_ffa		MACH_MSM7X30_FFA	MSM7X30_FFA		2707
 qsd8x50_surf		MACH_QSD8X50_SURF	QSD8X50_SURF		2708
-qsd8x50_comet		MACH_QSD8X50_COMET	QSD8X50_COMET		2709
-qsd8x50_ffa		MACH_QSD8X50_FFA	QSD8X50_FFA		2710
-qsd8x50a_surf		MACH_QSD8X50A_SURF	QSD8X50A_SURF		2711
-qsd8x50a_ffa		MACH_QSD8X50A_FFA	QSD8X50A_FFA		2712
-adx_xgcp10		MACH_ADX_XGCP10		ADX_XGCP10		2713
-mcgwumts2a		MACH_MCGWUMTS2A		MCGWUMTS2A		2714
-mobikt			MACH_MOBIKT		MOBIKT			2715
 mx53_evk		MACH_MX53_EVK		MX53_EVK		2716
 igep0030		MACH_IGEP0030		IGEP0030		2717
-axell_h40_h50_ctrl	MACH_AXELL_H40_H50_CTRL	AXELL_H40_H50_CTRL	2718
-dtcommod		MACH_DTCOMMOD		DTCOMMOD		2719
-gould			MACH_GOULD		GOULD			2720
-siberia			MACH_SIBERIA		SIBERIA			2721
 sbc3530			MACH_SBC3530		SBC3530			2722
-qarm			MACH_QARM		QARM			2723
-mips			MACH_MIPS		MIPS			2724
-mx27grb			MACH_MX27GRB		MX27GRB			2725
-sbc8100			MACH_SBC8100		SBC8100			2726
 saarb			MACH_SAARB		SAARB			2727
-omap3mini		MACH_OMAP3MINI		OMAP3MINI		2728
-cnmbook7se		MACH_CNMBOOK7SE		CNMBOOK7SE		2729
-catan			MACH_CATAN		CATAN			2730
 harmony			MACH_HARMONY		HARMONY			2731
-tonga			MACH_TONGA		TONGA			2732
-cybook_orizon		MACH_CYBOOK_ORIZON	CYBOOK_ORIZON		2733
-htcrhodiumcdma		MACH_HTCRHODIUMCDMA	HTCRHODIUMCDMA		2734
-epc_g45			MACH_EPC_G45		EPC_G45			2735
-epc_lpc3250		MACH_EPC_LPC3250	EPC_LPC3250		2736
-mxc91341evb		MACH_MXC91341EVB	MXC91341EVB		2737
-rtw1000			MACH_RTW1000		RTW1000			2738
-bobcat			MACH_BOBCAT		BOBCAT			2739
-trizeps6		MACH_TRIZEPS6		TRIZEPS6		2740
 msm7x30_fluid		MACH_MSM7X30_FLUID	MSM7X30_FLUID		2741
-nedap9263		MACH_NEDAP9263		NEDAP9263		2742
-netgear_ms2110		MACH_NETGEAR_MS2110	NETGEAR_MS2110		2743
-bmx			MACH_BMX		BMX			2744
-netstream		MACH_NETSTREAM		NETSTREAM		2745
-vpnext_rcu		MACH_VPNEXT_RCU		VPNEXT_RCU		2746
-vpnext_mpu		MACH_VPNEXT_MPU		VPNEXT_MPU		2747
-bcmring_tablet_v1	MACH_BCMRING_TABLET_V1	BCMRING_TABLET_V1	2748
-sgarm10			MACH_SGARM10		SGARM10			2749
 cm_t3517		MACH_CM_T3517		CM_T3517		2750
-omap3_cps		MACH_OMAP3_CPS		OMAP3_CPS		2751
-axar1500_receiver	MACH_AXAR1500_RECEIVER	AXAR1500_RECEIVER	2752
 wbd222			MACH_WBD222		WBD222			2753
-mt65xx			MACH_MT65XX		MT65XX			2754
 msm8x60_surf		MACH_MSM8X60_SURF	MSM8X60_SURF		2755
 msm8x60_sim		MACH_MSM8X60_SIM	MSM8X60_SIM		2756
-vmc300			MACH_VMC300		VMC300			2757
 tcc8000_sdk		MACH_TCC8000_SDK	TCC8000_SDK		2758
-nanos			MACH_NANOS		NANOS			2759
-stamp9g10		MACH_STAMP9G10		STAMP9G10		2760
-stamp9g45		MACH_STAMP9G45		STAMP9G45		2761
-h6053			MACH_H6053		H6053			2762
-smint01			MACH_SMINT01		SMINT01			2763
-prtlvt2			MACH_PRTLVT2		PRTLVT2			2764
 ap420			MACH_AP420		AP420			2765
-htcshift		MACH_HTCSHIFT		HTCSHIFT		2766
 davinci_dm365_fc	MACH_DAVINCI_DM365_FC	DAVINCI_DM365_FC	2767
 msm8x55_surf		MACH_MSM8X55_SURF	MSM8X55_SURF		2768
 msm8x55_ffa		MACH_MSM8X55_FFA	MSM8X55_FFA		2769
@@ -2761,7 +474,6 @@
 kopin_models		MACH_KOPIN_MODELS	KOPIN_MODELS		2774
 ttc_vision2		MACH_TTC_VISION2	TTC_VISION2		2775
 cns3420vb		MACH_CNS3420VB		CNS3420VB		2776
-lpc2			MACH_LPC2		LPC2			2777
 olympus			MACH_OLYMPUS		OLYMPUS			2778
 vortex			MACH_VORTEX		VORTEX			2779
 s5pc200			MACH_S5PC200		S5PC200			2780
@@ -2788,7 +500,6 @@
 neocoreomap		MACH_NEOCOREOMAP	NEOCOREOMAP		2801
 withings_wbp		MACH_WITHINGS_WBP	WITHINGS_WBP		2802
 dbps			MACH_DBPS		DBPS			2803
-sbc9261			MACH_SBC9261		SBC9261			2804
 pcbfp0001		MACH_PCBFP0001		PCBFP0001		2805
 speedy			MACH_SPEEDY		SPEEDY			2806
 chrysaor		MACH_CHRYSAOR		CHRYSAOR		2807
@@ -2812,7 +523,6 @@
 acer_a4			MACH_ACER_A4		ACER_A4			2825
 davinci_dm368_bip	MACH_DAVINCI_DM368_BIP	DAVINCI_DM368_BIP	2826
 eshare			MACH_ESHARE		ESHARE			2827
-hw_omapl138_europa	MACH_HW_OMAPL138_EUROPA	HW_OMAPL138_EUROPA	2828
 wlbargn			MACH_WLBARGN		WLBARGN			2829
 bm170			MACH_BM170		BM170			2830
 netspace_mini_v2	MACH_NETSPACE_MINI_V2	NETSPACE_MINI_V2	2831
@@ -2879,7 +589,6 @@
 mecha			MACH_MECHA		MECHA			2892
 bubba3			MACH_BUBBA3		BUBBA3			2893
 pupitre			MACH_PUPITRE		PUPITRE			2894
-tegra_harmony		MACH_TEGRA_HARMONY	TEGRA_HARMONY		2895
 tegra_vogue		MACH_TEGRA_VOGUE	TEGRA_VOGUE		2896
 tegra_e1165		MACH_TEGRA_E1165	TEGRA_E1165		2897
 simplenet		MACH_SIMPLENET		SIMPLENET		2898
@@ -2969,7 +678,6 @@
 ssc			MACH_SSC		SSC			2984
 premierwave_en		MACH_PREMIERWAVE_EN	PREMIERWAVE_EN		2985
 wasabi			MACH_WASABI		WASABI			2986
-vivow			MACH_VIVOW		VIVOW			2987
 mx50_rdp		MACH_MX50_RDP		MX50_RDP		2988
 universal_c210		MACH_UNIVERSAL_C210	UNIVERSAL_C210		2989
 real6410		MACH_REAL6410		REAL6410		2990
@@ -3017,12 +725,10 @@
 at91cap7xdk		MACH_AT91CAP7XDK	AT91CAP7XDK		3032
 at91cap7stk		MACH_AT91CAP7STK	AT91CAP7STK		3033
 kt_sbc_sam9_1		MACH_KT_SBC_SAM9_1	KT_SBC_SAM9_1		3034
-oratisrouter		MACH_ORATISROUTER	ORATISROUTER		3035
 armada_xp_db		MACH_ARMADA_XP_DB	ARMADA_XP_DB		3036
 spdm			MACH_SPDM		SPDM			3037
 gtib			MACH_GTIB		GTIB			3038
 dgm3240			MACH_DGM3240		DGM3240			3039
-atlas_i_lpe		MACH_ATLAS_I_LPE	ATLAS_I_LPE		3040
 htcmega			MACH_HTCMEGA		HTCMEGA			3041
 tricorder		MACH_TRICORDER		TRICORDER		3042
 tx28			MACH_TX28		TX28			3043
@@ -3062,7 +768,6 @@
 rump			MACH_RUMP		RUMP			3078
 tenderloin		MACH_TENDERLOIN		TENDERLOIN		3079
 shortloin		MACH_SHORTLOIN		SHORTLOIN		3080
-crespo			MACH_CRESPO		CRESPO			3081
 antares			MACH_ANTARES		ANTARES			3082
 wb40n			MACH_WB40N		WB40N			3083
 herring			MACH_HERRING		HERRING			3084
@@ -3111,7 +816,6 @@
 smartqv7		MACH_SMARTQV7		SMARTQV7		3127
 paz00			MACH_PAZ00		PAZ00			3128
 acmenetusfoxg20		MACH_ACMENETUSFOXG20	ACMENETUSFOXG20		3129
-htcwillow		MACH_HTCWILLOW		HTCWILLOW		3130
 fwbd_0404		MACH_FWBD_0404		FWBD_0404		3131
 hdgu			MACH_HDGU		HDGU			3132
 pyramid			MACH_PYRAMID		PYRAMID			3133
@@ -3162,7 +866,6 @@
 s5500			MACH_S5500		S5500			3178
 icon			MACH_ICON		ICON			3179
 elephant		MACH_ELEPHANT		ELEPHANT		3180
-msm8x60_fusion		MACH_MSM8X60_FUSION	MSM8X60_FUSION		3181
 shooter			MACH_SHOOTER		SHOOTER			3182
 spade_lte		MACH_SPADE_LTE		SPADE_LTE		3183
 philhwani		MACH_PHILHWANI		PHILHWANI		3184
@@ -3174,13 +877,11 @@
 sc575plc		MACH_SC575PLC		SC575PLC		3190
 sc575hmi		MACH_SC575IPC		SC575IPC		3191
 omap3_tdm3730		MACH_OMAP3_TDM3730	OMAP3_TDM3730		3192
-g7			MACH_G7			G7			3193
 top9000_eval		MACH_TOP9000_EVAL	TOP9000_EVAL		3194
 top9000_su		MACH_TOP9000_SU		TOP9000_SU		3195
 utm300			MACH_UTM300		UTM300			3196
 tsunagi			MACH_TSUNAGI		TSUNAGI			3197
 ts75xx			MACH_TS75XX		TS75XX			3198
-msm8x60_fusn_ffa	MACH_MSM8X60_FUSN_FFA	MSM8X60_FUSN_FFA	3199
 ts47xx			MACH_TS47XX		TS47XX			3200
 da850_k5		MACH_DA850_K5		DA850_K5		3201
 ax502			MACH_AX502		AX502			3202
@@ -3285,7 +986,6 @@
 nmh			MACH_NMH		NMH			3305
 wn802t			MACH_WN802T		WN802T			3306
 dragonet		MACH_DRAGONET		DRAGONET		3307
-geneva_b		MACH_GENEVA_B		GENEVA_B		3308
 at91sam9263desk16l	MACH_AT91SAM9263DESK16L	AT91SAM9263DESK16L	3309
 bcmhana_sv		MACH_BCMHANA_SV		BCMHANA_SV		3310
 bcmhana_tablet		MACH_BCMHANA_TABLET	BCMHANA_TABLET		3311
@@ -3316,3 +1016,86 @@
 t5388p			MACH_T5388P		T5388P			3336
 dingo			MACH_DINGO		DINGO			3337
 goflexhome		MACH_GOFLEXHOME		GOFLEXHOME		3338
+lanreadyfn511		MACH_LANREADYFN511	LANREADYFN511		3340
+omap3_baia		MACH_OMAP3_BAIA		OMAP3_BAIA		3341
+omap3smartdisplay	MACH_OMAP3SMARTDISPLAY	OMAP3SMARTDISPLAY	3342
+xilinx			MACH_XILINX		XILINX			3343
+a2f			MACH_A2F		A2F			3344
+sky25			MACH_SKY25		SKY25			3345
+ccmx53			MACH_CCMX53		CCMX53			3346
+ccmx53js		MACH_CCMX53JS		CCMX53JS		3347
+ccwmx53			MACH_CCWMX53		CCWMX53			3348
+ccwmx53js		MACH_CCWMX53JS		CCWMX53JS		3349
+frisms			MACH_FRISMS		FRISMS			3350
+msm7x27a_ffa		MACH_MSM7X27A_FFA	MSM7X27A_FFA		3351
+msm7x27a_surf		MACH_MSM7X27A_SURF	MSM7X27A_SURF		3352
+msm7x27a_rumi3		MACH_MSM7X27A_RUMI3	MSM7X27A_RUMI3		3353
+dimmsam9g20		MACH_DIMMSAM9G20	DIMMSAM9G20		3354
+dimm_imx28		MACH_DIMM_IMX28		DIMM_IMX28		3355
+amk_a4			MACH_AMK_A4		AMK_A4			3356
+gnet_sgme		MACH_GNET_SGME		GNET_SGME		3357
+shooter_u		MACH_SHOOTER_U		SHOOTER_U		3358
+vmx53			MACH_VMX53		VMX53			3359
+rhino			MACH_RHINO		RHINO			3360
+armlex4210		MACH_ARMLEX4210		ARMLEX4210		3361
+swarcoextmodem		MACH_SWARCOEXTMODEM	SWARCOEXTMODEM		3362
+snowball		MACH_SNOWBALL		SNOWBALL		3363
+pcm049			MACH_PCM049		PCM049			3364
+vigor			MACH_VIGOR		VIGOR			3365
+oslo_amundsen		MACH_OSLO_AMUNDSEN	OSLO_AMUNDSEN		3366
+gsl_diamond		MACH_GSL_DIAMOND	GSL_DIAMOND		3367
+cv2201			MACH_CV2201		CV2201			3368
+cv2202			MACH_CV2202		CV2202			3369
+cv2203			MACH_CV2203		CV2203			3370
+vit_ibox		MACH_VIT_IBOX		VIT_IBOX		3371
+dm6441_esp		MACH_DM6441_ESP		DM6441_ESP		3372
+at91sam9x5ek		MACH_AT91SAM9X5EK	AT91SAM9X5EK		3373
+libra			MACH_LIBRA		LIBRA			3374
+easycrrh		MACH_EASYCRRH		EASYCRRH		3375
+tripel			MACH_TRIPEL		TRIPEL			3376
+endian_mini		MACH_ENDIAN_MINI	ENDIAN_MINI		3377
+xilinx_ep107		MACH_XILINX_EP107	XILINX_EP107		3378
+nuri			MACH_NURI		NURI			3379
+janus			MACH_JANUS		JANUS			3380
+ddnas			MACH_DDNAS		DDNAS			3381
+tag			MACH_TAG		TAG			3382
+tagw			MACH_TAGW		TAGW			3383
+nitrogen_vm_imx51	MACH_NITROGEN_VM_IMX51	NITROGEN_VM_IMX51	3384
+viprinet		MACH_VIPRINET		VIPRINET		3385
+bockw			MACH_BOCKW		BOCKW			3386
+eva2000			MACH_EVA2000		EVA2000			3387
+steelyard		MACH_STEELYARD		STEELYARD		3388
+sdh001			MACH_MACH_SDH001	MACH_SDH001		3390
+nsslsboard		MACH_NSSLSBOARD		NSSLSBOARD		3392
+geneva_b5		MACH_GENEVA_B5		GENEVA_B5		3393
+spear1340		MACH_SPEAR1340		SPEAR1340		3394
+rexmas			MACH_REXMAS		REXMAS			3395
+msm8960_cdp		MACH_MSM8960_CDP	MSM8960_CDP		3396
+msm8960_mdp		MACH_MSM8960_MDP	MSM8960_MDP		3397
+msm8960_fluid		MACH_MSM8960_FLUID	MSM8960_FLUID		3398
+msm8960_apq		MACH_MSM8960_APQ	MSM8960_APQ		3399
+helios_v2		MACH_HELIOS_V2		HELIOS_V2		3400
+mif10p			MACH_MIF10P		MIF10P			3401
+iam28			MACH_IAM28		IAM28			3402
+picasso			MACH_PICASSO		PICASSO			3403
+mr301a			MACH_MR301A		MR301A			3404
+notle			MACH_NOTLE		NOTLE			3405
+eelx2			MACH_EELX2		EELX2			3406
+moon			MACH_MOON		MOON			3407
+ruby			MACH_RUBY		RUBY			3408
+goldengate		MACH_GOLDENGATE		GOLDENGATE		3409
+ctbu_gen2		MACH_CTBU_GEN2		CTBU_GEN2		3410
+kmp_am17_01		MACH_KMP_AM17_01	KMP_AM17_01		3411
+wtplug			MACH_WTPLUG		WTPLUG			3412
+mx27su2			MACH_MX27SU2		MX27SU2			3413
+nb31			MACH_NB31		NB31			3414
+hjsdu			MACH_HJSDU		HJSDU			3415
+td3_rev1		MACH_TD3_REV1		TD3_REV1		3416
+eag_ci4000		MACH_EAG_CI4000		EAG_CI4000		3417
+net5big_nand_v2		MACH_NET5BIG_NAND_V2	NET5BIG_NAND_V2		3418
+cpx2			MACH_CPX2		CPX2			3419
+net2big_nand_v2		MACH_NET2BIG_NAND_V2	NET2BIG_NAND_V2		3420
+ecuv5			MACH_ECUV5		ECUV5			3421
+hsgx6d			MACH_HSGX6D		HSGX6D			3422
+dawad7			MACH_DAWAD7		DAWAD7			3423
+sam9repeater		MACH_SAM9REPEATER	SAM9REPEATER		3424
diff -druN linux-libre-2.6.38-gnu/arch/arm/vfp/Makefile linux-libre-2.6.39-gnu/arch/arm/vfp/Makefile
--- linux-libre-2.6.38-gnu/arch/arm/vfp/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/vfp/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,8 +4,8 @@
 # Copyright (C) 2001 ARM Limited
 #
 
-# EXTRA_CFLAGS := -DDEBUG
-# EXTRA_AFLAGS := -DDEBUG
+# ccflags-y := -DDEBUG
+# asflags-y := -DDEBUG
 
 KBUILD_AFLAGS	:=$(KBUILD_AFLAGS:-msoft-float=-Wa,-mfpu=softvfp+vfp)
 LDFLAGS		+=--no-warn-mismatch
diff -druN linux-libre-2.6.38-gnu/arch/arm/vfp/vfpmodule.c linux-libre-2.6.39-gnu/arch/arm/vfp/vfpmodule.c
--- linux-libre-2.6.38-gnu/arch/arm/vfp/vfpmodule.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/arm/vfp/vfpmodule.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,6 +78,14 @@
 	put_cpu();
 }
 
+static void vfp_thread_copy(struct thread_info *thread)
+{
+	struct thread_info *parent = current_thread_info();
+
+	vfp_sync_hwstate(parent);
+	thread->vfpstate = parent->vfpstate;
+}
+
 /*
  * When this function is called with the following 'cmd's, the following
  * is true while this function is being run:
@@ -104,12 +112,17 @@
 static int vfp_notifier(struct notifier_block *self, unsigned long cmd, void *v)
 {
 	struct thread_info *thread = v;
+	u32 fpexc;
+#ifdef CONFIG_SMP
+	unsigned int cpu;
+#endif
 
-	if (likely(cmd == THREAD_NOTIFY_SWITCH)) {
-		u32 fpexc = fmrx(FPEXC);
+	switch (cmd) {
+	case THREAD_NOTIFY_SWITCH:
+		fpexc = fmrx(FPEXC);
 
 #ifdef CONFIG_SMP
-		unsigned int cpu = thread->cpu;
+		cpu = thread->cpu;
 
 		/*
 		 * On SMP, if VFP is enabled, save the old state in
@@ -134,13 +147,20 @@
 		 * old state.
 		 */
 		fmxr(FPEXC, fpexc & ~FPEXC_EN);
-		return NOTIFY_DONE;
-	}
+		break;
 
-	if (cmd == THREAD_NOTIFY_FLUSH)
+	case THREAD_NOTIFY_FLUSH:
 		vfp_thread_flush(thread);
-	else
+		break;
+
+	case THREAD_NOTIFY_EXIT:
 		vfp_thread_exit(thread);
+		break;
+
+	case THREAD_NOTIFY_COPY:
+		vfp_thread_copy(thread);
+		break;
+	}
 
 	return NOTIFY_DONE;
 }
@@ -153,7 +173,7 @@
  * Raise a SIGFPE for the current process.
  * sicode describes the signal being raised.
  */
-void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
+static void vfp_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
 {
 	siginfo_t info;
 
@@ -489,8 +509,11 @@
 
 /*
  * VFP hardware can lose all context when a CPU goes offline.
- * Safely clear our held state when a CPU has been killed, and
- * re-enable access to VFP when the CPU comes back online.
+ * As we will be running in SMP mode with CPU hotplug, we will save the
+ * hardware state at every thread switch.  We clear our held state when
+ * a CPU has been killed, indicating that the VFP hardware doesn't contain
+ * a threads VFP state.  When a CPU starts up, we re-enable access to the
+ * VFP hardware.
  *
  * Both CPU_DYING and CPU_STARTING are called on the CPU which
  * is being offlined/onlined.
diff -druN linux-libre-2.6.38-gnu/arch/avr32/boards/atngw100/mrmt.c linux-libre-2.6.39-gnu/arch/avr32/boards/atngw100/mrmt.c
--- linux-libre-2.6.38-gnu/arch/avr32/boards/atngw100/mrmt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/boards/atngw100/mrmt.c	2011-05-19 00:06:34.000000000 -0400
@@ -301,7 +301,7 @@
 	/* 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 );
+	irq_set_irq_type(AT32_EXTINT(TS_IRQ), IRQ_TYPE_EDGE_FALLING);
 	at32_spi_setup_slaves(0,spi01_board_info,ARRAY_SIZE(spi01_board_info));
 	spi_register_board_info(spi01_board_info,ARRAY_SIZE(spi01_board_info));
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/avr32/boards/atngw100/setup.c linux-libre-2.6.39-gnu/arch/avr32/boards/atngw100/setup.c
--- linux-libre-2.6.38-gnu/arch/avr32/boards/atngw100/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/boards/atngw100/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -322,6 +322,6 @@
 	/* set_irq_type() after the arch_initcall for EIC has run, and
 	 * before the I2C subsystem could try using this IRQ.
 	 */
-	return set_irq_type(AT32_EXTINT(3), IRQ_TYPE_EDGE_FALLING);
+	return irq_set_irq_type(AT32_EXTINT(3), IRQ_TYPE_EDGE_FALLING);
 }
 arch_initcall(atngw100_arch_init);
diff -druN linux-libre-2.6.38-gnu/arch/avr32/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/avr32/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/avr32/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -299,8 +299,7 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix-le.h>
 
 #endif /* __ASM_AVR32_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/avr32/include/asm/setup.h linux-libre-2.6.39-gnu/arch/avr32/include/asm/setup.h
--- linux-libre-2.6.38-gnu/arch/avr32/include/asm/setup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/include/asm/setup.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,6 +94,13 @@
 
 #define ETH_INVALID_PHY	0xff
 
+/* board information */
+#define ATAG_BOARDINFO	0x54410008
+
+struct tag_boardinfo {
+	u32	board_number;
+};
+
 struct tag {
 	struct tag_header hdr;
 	union {
@@ -102,6 +109,7 @@
 		struct tag_cmdline cmdline;
 		struct tag_clock clock;
 		struct tag_ethernet ethernet;
+		struct tag_boardinfo boardinfo;
 	} u;
 };
 
@@ -128,6 +136,7 @@
 
 extern resource_size_t fbmem_start;
 extern resource_size_t fbmem_size;
+extern u32 board_number;
 
 void setup_processor(void);
 
diff -druN linux-libre-2.6.38-gnu/arch/avr32/include/asm/types.h linux-libre-2.6.39-gnu/arch/avr32/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/avr32/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,14 +23,6 @@
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 
diff -druN linux-libre-2.6.38-gnu/arch/avr32/Kconfig linux-libre-2.6.39-gnu/arch/avr32/Kconfig
--- linux-libre-2.6.38-gnu/arch/avr32/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,10 @@
 	select HAVE_CLK
 	select HAVE_OPROFILE
 	select HAVE_KPROBES
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_PROBE
+	select HARDIRQS_SW_RESEND
+	select GENERIC_IRQ_SHOW
 	help
 	  AVR32 is a high-performance 32-bit RISC microprocessor core,
 	  designed for cost-sensitive embedded applications, with particular
@@ -17,9 +21,6 @@
 config GENERIC_GPIO
 	def_bool y
 
-config GENERIC_HARDIRQS
-	def_bool y
-
 config STACKTRACE_SUPPORT
 	def_bool y
 
@@ -29,12 +30,6 @@
 config TRACE_IRQFLAGS_SUPPORT
 	def_bool y
 
-config HARDIRQS_SW_RESEND
-	def_bool y
-
-config GENERIC_IRQ_PROBE
-	def_bool y
-
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
 
diff -druN linux-libre-2.6.38-gnu/arch/avr32/kernel/avr32_ksyms.c linux-libre-2.6.39-gnu/arch/avr32/kernel/avr32_ksyms.c
--- linux-libre-2.6.38-gnu/arch/avr32/kernel/avr32_ksyms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/kernel/avr32_ksyms.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,8 +58,8 @@
 EXPORT_SYMBOL(find_next_zero_bit);
 EXPORT_SYMBOL(find_first_bit);
 EXPORT_SYMBOL(find_next_bit);
-EXPORT_SYMBOL(generic_find_next_le_bit);
-EXPORT_SYMBOL(generic_find_next_zero_le_bit);
+EXPORT_SYMBOL(find_next_bit_le);
+EXPORT_SYMBOL(find_next_zero_bit_le);
 
 /* I/O primitives (lib/io-*.S) */
 EXPORT_SYMBOL(__raw_readsb);
diff -druN linux-libre-2.6.38-gnu/arch/avr32/kernel/irq.c linux-libre-2.6.39-gnu/arch/avr32/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/avr32/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,40 +26,3 @@
 {
 
 }
-
-#ifdef CONFIG_PROC_FS
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *)v, cpu;
-	struct irqaction *action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_puts(p, "           ");
-		for_each_online_cpu(cpu)
-			seq_printf(p, "CPU%d       ", cpu);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_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(cpu)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-		seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
-		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-	unlock:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-
-	return 0;
-}
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/avr32/kernel/setup.c linux-libre-2.6.39-gnu/arch/avr32/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/avr32/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -391,6 +391,21 @@
 __tagtable(ATAG_CLOCK, parse_tag_clock);
 
 /*
+ * The board_number correspond to the bd->bi_board_number in U-Boot. This
+ * parameter is only available during initialisation and can be used in some
+ * kind of board identification.
+ */
+u32 __initdata board_number;
+
+static int __init parse_tag_boardinfo(struct tag *tag)
+{
+	board_number = tag->u.boardinfo.board_number;
+
+	return 0;
+}
+__tagtable(ATAG_BOARDINFO, parse_tag_boardinfo);
+
+/*
  * Scan the tag table for this tag, and call its parse function. The
  * tag table is built by the linker from all the __tagtable
  * declarations.
diff -druN linux-libre-2.6.38-gnu/arch/avr32/kernel/traps.c linux-libre-2.6.39-gnu/arch/avr32/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/avr32/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,28 +95,6 @@
 	info.si_code = code;
 	info.si_addr = (void __user *)addr;
 	force_sig_info(signr, &info, current);
-
-	/*
-	 * Init gets no signals that it doesn't have a handler for.
-	 * That's all very well, but if it has caused a synchronous
-	 * exception and we ignore the resulting signal, it will just
-	 * generate the same exception over and over again and we get
-	 * nowhere.  Better to kill it and let the kernel panic.
-	 */
-	if (is_global_init(current)) {
-		__sighandler_t handler;
-
-		spin_lock_irq(&current->sighand->siglock);
-		handler = current->sighand->action[signr-1].sa.sa_handler;
-		spin_unlock_irq(&current->sighand->siglock);
-		if (handler == SIG_DFL) {
-			/* init has generated a synchronous exception
-			   and it doesn't have a handler for the signal */
-			printk(KERN_CRIT "init has generated signal %ld "
-			       "but has no handler for it\n", signr);
-			do_exit(signr);
-		}
-	}
 }
 
 asmlinkage void do_nmi(unsigned long ecr, struct pt_regs *regs)
diff -druN linux-libre-2.6.38-gnu/arch/avr32/lib/findbit.S linux-libre-2.6.39-gnu/arch/avr32/lib/findbit.S
--- linux-libre-2.6.38-gnu/arch/avr32/lib/findbit.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/lib/findbit.S	2011-05-19 00:06:34.000000000 -0400
@@ -123,7 +123,7 @@
 	brgt	1b
 	retal	r11
 
-ENTRY(generic_find_next_le_bit)
+ENTRY(find_next_bit_le)
 	lsr	r8, r10, 5
 	sub	r9, r11, r10
 	retle	r11
@@ -153,7 +153,7 @@
 	brgt	1b
 	retal	r11
 
-ENTRY(generic_find_next_zero_le_bit)
+ENTRY(find_next_zero_bit_le)
 	lsr	r8, r10, 5
 	sub	r9, r11, r10
 	retle	r11
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/at32ap700x.c linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/at32ap700x.c
--- linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/at32ap700x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/at32ap700x.c	2011-05-19 00:06:34.000000000 -0400
@@ -2048,6 +2048,11 @@
 		rx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT;
 		rx_dws->cfg_hi = DWC_CFGH_SRC_PER(3);
 		rx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
+		rx_dws->src_master = 0;
+		rx_dws->dst_master = 1;
+		rx_dws->src_msize = DW_DMA_MSIZE_1;
+		rx_dws->dst_msize = DW_DMA_MSIZE_1;
+		rx_dws->fc = DW_DMA_FC_D_P2M;
 	}
 
 	/* Check if DMA slave interface for playback should be configured. */
@@ -2056,6 +2061,11 @@
 		tx_dws->reg_width = DW_DMA_SLAVE_WIDTH_16BIT;
 		tx_dws->cfg_hi = DWC_CFGH_DST_PER(4);
 		tx_dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
+		tx_dws->src_master = 0;
+		tx_dws->dst_master = 1;
+		tx_dws->src_msize = DW_DMA_MSIZE_1;
+		tx_dws->dst_msize = DW_DMA_MSIZE_1;
+		tx_dws->fc = DW_DMA_FC_D_M2P;
 	}
 
 	if (platform_device_add_data(pdev, data,
@@ -2128,6 +2138,11 @@
 	dws->reg_width = DW_DMA_SLAVE_WIDTH_32BIT;
 	dws->cfg_hi = DWC_CFGH_DST_PER(2);
 	dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | DWC_CFGL_HS_SRC_POL);
+	dws->src_master = 0;
+	dws->dst_master = 1;
+	dws->src_msize = DW_DMA_MSIZE_1;
+	dws->dst_msize = DW_DMA_MSIZE_1;
+	dws->fc = DW_DMA_FC_D_M2P;
 
 	if (platform_device_add_data(pdev, data,
 				sizeof(struct atmel_abdac_pdata)))
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/clock.c linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/clock.c
--- linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/clock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,22 +35,30 @@
 	spin_unlock(&clk_list_lock);
 }
 
-struct clk *clk_get(struct device *dev, const char *id)
+static struct clk *__clk_get(struct device *dev, const char *id)
 {
 	struct clk *clk;
 
-	spin_lock(&clk_list_lock);
-
 	list_for_each_entry(clk, &at32_clock_list, list) {
 		if (clk->dev == dev && strcmp(id, clk->name) == 0) {
-			spin_unlock(&clk_list_lock);
 			return clk;
 		}
 	}
 
-	spin_unlock(&clk_list_lock);
 	return ERR_PTR(-ENOENT);
 }
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	struct clk *clk;
+
+	spin_lock(&clk_list_lock);
+	clk = __clk_get(dev, id);
+	spin_unlock(&clk_list_lock);
+
+	return clk;
+}
+
 EXPORT_SYMBOL(clk_get);
 
 void clk_put(struct clk *clk)
@@ -257,15 +265,15 @@
 	spin_lock(&clk_list_lock);
 
 	/* show clock tree as derived from the three oscillators */
-	clk = clk_get(NULL, "osc32k");
+	clk = __clk_get(NULL, "osc32k");
 	dump_clock(clk, &r);
 	clk_put(clk);
 
-	clk = clk_get(NULL, "osc0");
+	clk = __clk_get(NULL, "osc0");
 	dump_clock(clk, &r);
 	clk_put(clk);
 
-	clk = clk_get(NULL, "osc1");
+	clk = __clk_get(NULL, "osc1");
 	dump_clock(clk, &r);
 	clk_put(clk);
 
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/extint.c linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/extint.c
--- linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/extint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/extint.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,45 +61,42 @@
 static struct eic *nmi_eic;
 static bool nmi_enabled;
 
-static void eic_ack_irq(unsigned int irq)
+static void eic_ack_irq(struct irq_data *d)
 {
-	struct eic *eic = get_irq_chip_data(irq);
-	eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
+	struct eic *eic = irq_data_get_irq_chip_data(d);
+	eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
 }
 
-static void eic_mask_irq(unsigned int irq)
+static void eic_mask_irq(struct irq_data *d)
 {
-	struct eic *eic = get_irq_chip_data(irq);
-	eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
+	struct eic *eic = irq_data_get_irq_chip_data(d);
+	eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
 }
 
-static void eic_mask_ack_irq(unsigned int irq)
+static void eic_mask_ack_irq(struct irq_data *d)
 {
-	struct eic *eic = get_irq_chip_data(irq);
-	eic_writel(eic, ICR, 1 << (irq - eic->first_irq));
-	eic_writel(eic, IDR, 1 << (irq - eic->first_irq));
+	struct eic *eic = irq_data_get_irq_chip_data(d);
+	eic_writel(eic, ICR, 1 << (d->irq - eic->first_irq));
+	eic_writel(eic, IDR, 1 << (d->irq - eic->first_irq));
 }
 
-static void eic_unmask_irq(unsigned int irq)
+static void eic_unmask_irq(struct irq_data *d)
 {
-	struct eic *eic = get_irq_chip_data(irq);
-	eic_writel(eic, IER, 1 << (irq - eic->first_irq));
+	struct eic *eic = irq_data_get_irq_chip_data(d);
+	eic_writel(eic, IER, 1 << (d->irq - eic->first_irq));
 }
 
-static int eic_set_irq_type(unsigned int irq, unsigned int flow_type)
+static int eic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct eic *eic = get_irq_chip_data(irq);
-	struct irq_desc *desc;
+	struct eic *eic = irq_data_get_irq_chip_data(d);
+	unsigned int irq = d->irq;
 	unsigned int i = irq - eic->first_irq;
 	u32 mode, edge, level;
-	int ret = 0;
 
 	flow_type &= IRQ_TYPE_SENSE_MASK;
 	if (flow_type == IRQ_TYPE_NONE)
 		flow_type = IRQ_TYPE_LEVEL_LOW;
 
-	desc = &irq_desc[irq];
-
 	mode = eic_readl(eic, MODE);
 	edge = eic_readl(eic, EDGE);
 	level = eic_readl(eic, LEVEL);
@@ -122,39 +119,34 @@
 		edge &= ~(1 << i);
 		break;
 	default:
-		ret = -EINVAL;
-		break;
+		return -EINVAL;
 	}
 
-	if (ret == 0) {
-		eic_writel(eic, MODE, mode);
-		eic_writel(eic, EDGE, edge);
-		eic_writel(eic, LEVEL, level);
+	eic_writel(eic, MODE, mode);
+	eic_writel(eic, EDGE, edge);
+	eic_writel(eic, LEVEL, level);
 
-		if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH)) {
-			flow_type |= IRQ_LEVEL;
-			__set_irq_handler_unlocked(irq, handle_level_irq);
-		} else
-			__set_irq_handler_unlocked(irq, handle_edge_irq);
-		desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-		desc->status |= flow_type;
-	}
+	irqd_set_trigger_type(d, flow_type);
+	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+		__irq_set_handler_locked(irq, handle_level_irq);
+	else
+		__irq_set_handler_locked(irq, handle_edge_irq);
 
-	return ret;
+	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
 static struct irq_chip eic_chip = {
 	.name		= "eic",
-	.ack		= eic_ack_irq,
-	.mask		= eic_mask_irq,
-	.mask_ack	= eic_mask_ack_irq,
-	.unmask		= eic_unmask_irq,
-	.set_type	= eic_set_irq_type,
+	.irq_ack	= eic_ack_irq,
+	.irq_mask	= eic_mask_irq,
+	.irq_mask_ack	= eic_mask_ack_irq,
+	.irq_unmask	= eic_unmask_irq,
+	.irq_set_type	= eic_set_irq_type,
 };
 
 static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct eic *eic = desc->handler_data;
+	struct eic *eic = irq_desc_get_handler_data(desc);
 	unsigned long status, pending;
 	unsigned int i;
 
@@ -199,7 +191,7 @@
 
 	regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int_irq = platform_get_irq(pdev, 0);
-	if (!regs || !int_irq) {
+	if (!regs || (int)int_irq <= 0) {
 		dev_dbg(&pdev->dev, "missing regs and/or irq resource\n");
 		return -ENXIO;
 	}
@@ -234,13 +226,13 @@
 	eic->chip = &eic_chip;
 
 	for (i = 0; i < nr_of_irqs; i++) {
-		set_irq_chip_and_handler(eic->first_irq + i, &eic_chip,
+		irq_set_chip_and_handler(eic->first_irq + i, &eic_chip,
 					 handle_level_irq);
-		set_irq_chip_data(eic->first_irq + i, eic);
+		irq_set_chip_data(eic->first_irq + i, eic);
 	}
 
-	set_irq_chained_handler(int_irq, demux_eic_irq);
-	set_irq_data(int_irq, eic);
+	irq_set_chained_handler(int_irq, demux_eic_irq);
+	irq_set_handler_data(int_irq, eic);
 
 	if (pdev->id == 0) {
 		nmi_eic = eic;
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/intc.c linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/intc.c
--- linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/intc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/intc.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,12 +34,12 @@
  * TODO: We may be able to implement mask/unmask by setting IxM flags
  * in the status register.
  */
-static void intc_mask_irq(unsigned int irq)
+static void intc_mask_irq(struct irq_data *d)
 {
 
 }
 
-static void intc_unmask_irq(unsigned int irq)
+static void intc_unmask_irq(struct irq_data *d)
 {
 
 }
@@ -47,8 +47,8 @@
 static struct intc intc0 = {
 	.chip = {
 		.name		= "intc",
-		.mask		= intc_mask_irq,
-		.unmask		= intc_unmask_irq,
+		.irq_mask	= intc_mask_irq,
+		.irq_unmask	= intc_unmask_irq,
 	},
 };
 
@@ -57,7 +57,6 @@
  */
 asmlinkage void do_IRQ(int level, struct pt_regs *regs)
 {
-	struct irq_desc *desc;
 	struct pt_regs *old_regs;
 	unsigned int irq;
 	unsigned long status_reg;
@@ -69,8 +68,7 @@
 	irq_enter();
 
 	irq = intc_readl(&intc0, INTCAUSE0 - 4 * level);
-	desc = irq_desc + irq;
-	desc->handle_irq(irq, desc);
+	generic_handle_irq(irq);
 
 	/*
 	 * Clear all interrupt level masks so that we may handle
@@ -128,7 +126,7 @@
 		intc_writel(&intc0, INTPR0 + 4 * i, offset);
 		readback = intc_readl(&intc0, INTPR0 + 4 * i);
 		if (readback == offset)
-			set_irq_chip_and_handler(i, &intc0.chip,
+			irq_set_chip_and_handler(i, &intc0.chip,
 						 handle_simple_irq);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/pio.c linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/pio.c
--- linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/pio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/pio.c	2011-05-19 00:06:34.000000000 -0400
@@ -249,23 +249,23 @@
 
 /* GPIO IRQ support */
 
-static void gpio_irq_mask(unsigned irq)
+static void gpio_irq_mask(struct irq_data *d)
 {
-	unsigned		gpio = irq_to_gpio(irq);
+	unsigned		gpio = irq_to_gpio(d->irq);
 	struct pio_device	*pio = &pio_dev[gpio >> 5];
 
 	pio_writel(pio, IDR, 1 << (gpio & 0x1f));
 }
 
-static void gpio_irq_unmask(unsigned irq)
+static void gpio_irq_unmask(struct irq_data *d)
 {
-	unsigned		gpio = irq_to_gpio(irq);
+	unsigned		gpio = irq_to_gpio(d->irq);
 	struct pio_device	*pio = &pio_dev[gpio >> 5];
 
 	pio_writel(pio, IER, 1 << (gpio & 0x1f));
 }
 
-static int gpio_irq_type(unsigned irq, unsigned type)
+static int gpio_irq_type(struct irq_data *d, unsigned type)
 {
 	if (type != IRQ_TYPE_EDGE_BOTH && type != IRQ_TYPE_NONE)
 		return -EINVAL;
@@ -275,20 +275,19 @@
 
 static struct irq_chip gpio_irqchip = {
 	.name		= "gpio",
-	.mask		= gpio_irq_mask,
-	.unmask		= gpio_irq_unmask,
-	.set_type	= gpio_irq_type,
+	.irq_mask	= gpio_irq_mask,
+	.irq_unmask	= gpio_irq_unmask,
+	.irq_set_type	= gpio_irq_type,
 };
 
 static void gpio_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct pio_device	*pio = get_irq_chip_data(irq);
+	struct pio_device	*pio = irq_desc_get_chip_data(desc);
 	unsigned		gpio_irq;
 
-	gpio_irq = (unsigned) get_irq_data(irq);
+	gpio_irq = (unsigned) irq_get_handler_data(irq);
 	for (;;) {
 		u32		isr;
-		struct irq_desc	*d;
 
 		/* ack pending GPIO interrupts */
 		isr = pio_readl(pio, ISR) & pio_readl(pio, IMR);
@@ -301,9 +300,7 @@
 			isr &= ~(1 << i);
 
 			i += gpio_irq;
-			d = &irq_desc[i];
-
-			d->handle_irq(i, d);
+			generic_handle_irq(i);
 		} while (isr);
 	}
 }
@@ -313,16 +310,16 @@
 {
 	unsigned	i;
 
-	set_irq_chip_data(irq, pio);
-	set_irq_data(irq, (void *) gpio_irq);
+	irq_set_chip_data(irq, pio);
+	irq_set_handler_data(irq, (void *)gpio_irq);
 
 	for (i = 0; i < 32; i++, gpio_irq++) {
-		set_irq_chip_data(gpio_irq, pio);
-		set_irq_chip_and_handler(gpio_irq, &gpio_irqchip,
-				handle_simple_irq);
+		irq_set_chip_data(gpio_irq, pio);
+		irq_set_chip_and_handler(gpio_irq, &gpio_irqchip,
+					 handle_simple_irq);
 	}
 
-	set_irq_chained_handler(irq, gpio_irq_handler);
+	irq_set_chained_handler(irq, gpio_irq_handler);
 }
 
 /*--------------------------------------------------------------------------*/
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/pm-at32ap700x.S linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/pm-at32ap700x.S
--- linux-libre-2.6.38-gnu/arch/avr32/mach-at32ap/pm-at32ap700x.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mach-at32ap/pm-at32ap700x.S	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 	st.w	r8[TI_flags], r9
 	unmask_interrupts
 	sleep	CPU_SLEEP_IDLE
-	.size	cpu_idle_sleep, . - cpu_idle_sleep
+	.size	cpu_enter_idle, . - cpu_enter_idle
 
 	/*
 	 * Common return path for PM functions that don't run from
diff -druN linux-libre-2.6.38-gnu/arch/avr32/mm/cache.c linux-libre-2.6.39-gnu/arch/avr32/mm/cache.c
--- linux-libre-2.6.38-gnu/arch/avr32/mm/cache.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/avr32/mm/cache.c	2011-05-19 00:06:34.000000000 -0400
@@ -113,7 +113,7 @@
 }
 
 /*
- * This one is called from do_no_page(), do_swap_page() and install_page().
+ * This one is called from __do_fault() and do_swap_page().
  */
 void flush_icache_page(struct vm_area_struct *vma, struct page *page)
 {
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF518F-EZBRD_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -115,6 +115,7 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF526-EZBRD_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -153,6 +153,7 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_CCITT=m
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF527-AD7160-EVAL_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,6 @@
 # CONFIG_WIRELESS is not set
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF527-EZKIT_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -175,5 +175,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF527-EZKIT-V2_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF527-EZKIT-V2_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF527-EZKIT-V2_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF527-EZKIT-V2_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -183,5 +183,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF533-EZKIT_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -108,5 +108,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF533-STAMP_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF533-STAMP_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF533-STAMP_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF533-STAMP_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -122,5 +122,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF537-STAMP_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF537-STAMP_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF537-STAMP_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF537-STAMP_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -133,5 +133,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF538-EZKIT_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -70,7 +70,6 @@
 CONFIG_MTD_PHYSMAP=m
 CONFIG_MTD_NAND=m
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
 CONFIG_PHYLIB=y
 CONFIG_SMSC_PHY=y
@@ -131,5 +130,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF548-EZKIT_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -205,5 +205,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF561-ACVILON_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF561-ACVILON_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF561-ACVILON_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF561-ACVILON_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,6 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=2
 CONFIG_BLK_DEV_RAM_SIZE=16384
-# CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
 CONFIG_BLK_DEV_SD=y
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF561-EZKIT_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -111,5 +111,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BF561-EZKIT-SMP_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -109,5 +109,6 @@
 CONFIG_DEBUG_BFIN_HWTRACE_COMPRESSION_ONE=y
 CONFIG_EARLY_PRINTK=y
 CONFIG_CPLB_INFO=y
+CONFIG_BFIN_PSEUDODBG_INSNS=y
 CONFIG_CRYPTO=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/BlackStamp_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/BlackStamp_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/BlackStamp_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/BlackStamp_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT25=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/CM-BF527_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/CM-BF527_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/CM-BF527_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/CM-BF527_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,6 @@
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_GPIO_ADDR=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 # CONFIG_SCSI_LOWLEVEL is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/CM-BF533_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/CM-BF533_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/CM-BF533_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/CM-BF533_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,6 @@
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_RAM=y
 CONFIG_MTD_PHYSMAP=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
 # CONFIG_NETDEV_10000 is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/CM-BF548_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/CM-BF548_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/CM-BF548_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/CM-BF548_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,6 @@
 CONFIG_MTD_COMPLEX_MAPPINGS=y
 CONFIG_MTD_PHYSMAP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_SCSI=m
 CONFIG_BLK_DEV_SD=m
 # CONFIG_SCSI_LOWLEVEL is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/DNP5370_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/DNP5370_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/DNP5370_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/DNP5370_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,6 @@
 CONFIG_MTD_NAND_PLATFORM=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_NET_ETHERNET=y
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/H8606_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/H8606_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/H8606_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/H8606_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 CONFIG_MTD_M25P80=y
 # CONFIG_M25PXX_USE_FAST_READ is not set
 CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT25=y
 CONFIG_NETDEVICES=y
 CONFIG_NET_ETHERNET=y
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/configs/SRV1_defconfig linux-libre-2.6.39-gnu/arch/blackfin/configs/SRV1_defconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/configs/SRV1_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/configs/SRV1_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -48,6 +48,7 @@
 CONFIG_MTD_UCLINUX=y
 CONFIG_MTD_NAND=m
 CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT25=m
 CONFIG_NETDEVICES=y
 # CONFIG_NETDEV_1000 is not set
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/atomic.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/atomic.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/atomic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/atomic.h	2011-05-19 00:06:34.000000000 -0400
@@ -121,4 +121,6 @@
 
 #endif
 
+#include <asm-generic/atomic64.h>
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,9 +25,7 @@
 #include <asm-generic/bitops/const_hweight.h>
 #include <asm-generic/bitops/lock.h>
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
 
 #ifndef CONFIG_SMP
 #include <linux/irqflags.h>
@@ -114,6 +112,9 @@
 
 #endif /* CONFIG_SMP */
 
+/* Needs to be after test_bit and friends */
+#include <asm-generic/bitops/le.h>
+
 /*
  * hweightN: returns the hamming weight (i.e. the number
  * of bits set) of a N-bit word
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/def_LPBlackfin.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/def_LPBlackfin.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/def_LPBlackfin.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/def_LPBlackfin.h	2011-05-19 00:06:34.000000000 -0400
@@ -58,14 +58,26 @@
     ({ BUG(); 0; }); \
 })
 #define bfin_write(addr, val) \
-({ \
+do { \
 	switch (sizeof(*(addr))) { \
 	case 1: bfin_write8(addr, val);  break; \
 	case 2: bfin_write16(addr, val); break; \
 	case 4: bfin_write32(addr, val); break; \
 	default: BUG(); \
 	} \
-})
+} while (0)
+
+#define bfin_write_or(addr, bits) \
+do { \
+	void *__addr = (void *)(addr); \
+	bfin_write(__addr, bfin_read(__addr) | (bits)); \
+} while (0)
+
+#define bfin_write_and(addr, bits) \
+do { \
+	void *__addr = (void *)(addr); \
+	bfin_write(__addr, bfin_read(__addr) & (bits)); \
+} while (0)
 
 #endif /* __ASSEMBLY__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/dpmc.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/dpmc.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/dpmc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/dpmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -125,6 +125,9 @@
 
 #define VRPAIR(vlev, freq) (((vlev) << 16) | ((freq) >> 16))
 
+#ifdef CONFIG_CPU_FREQ
+#define CPUFREQ_CPU 0
+#endif
 struct bfin_dpmc_platform_data {
 	const unsigned int *tuple_tab;
 	unsigned short tabsize;
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/ipipe_base.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/ipipe_base.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/ipipe_base.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/ipipe_base.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,8 +24,10 @@
 
 #ifdef CONFIG_IPIPE
 
+#include <asm/bitsperlong.h>
+#include <mach/irq.h>
+
 #define IPIPE_NR_XIRQS		NR_IRQS
-#define IPIPE_IRQ_ISHIFT	5	/* 2^5 for 32bits arch. */
 
 /* Blackfin-specific, per-cpu pipeline status */
 #define IPIPE_SYNCDEFER_FLAG	15
@@ -42,11 +44,14 @@
 #define IPIPE_EVENT_INIT	(IPIPE_FIRST_EVENT + 4)
 #define IPIPE_EVENT_EXIT	(IPIPE_FIRST_EVENT + 5)
 #define IPIPE_EVENT_CLEANUP	(IPIPE_FIRST_EVENT + 6)
-#define IPIPE_LAST_EVENT	IPIPE_EVENT_CLEANUP
+#define IPIPE_EVENT_RETURN	(IPIPE_FIRST_EVENT + 7)
+#define IPIPE_LAST_EVENT	IPIPE_EVENT_RETURN
 #define IPIPE_NR_EVENTS		(IPIPE_LAST_EVENT + 1)
 
 #define IPIPE_TIMER_IRQ		IRQ_CORETMR
 
+#define __IPIPE_FEATURE_SYSINFO_V2	1
+
 #ifndef __ASSEMBLY__
 
 extern unsigned long __ipipe_root_status; /* Alias to ipipe_root_cpudom_var(status) */
@@ -63,6 +68,8 @@
 
 #endif /* !__ASSEMBLY__ */
 
+#define __IPIPE_FEATURE_SYSINFO_V2	1
+
 #endif /* CONFIG_IPIPE */
 
 #endif /* !__ASM_BLACKFIN_IPIPE_BASE_H */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/ipipe.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/ipipe.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/ipipe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/ipipe.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,11 +34,12 @@
 #include <asm/bitops.h>
 #include <asm/atomic.h>
 #include <asm/traps.h>
+#include <asm/bitsperlong.h>
 
-#define IPIPE_ARCH_STRING     "1.12-00"
+#define IPIPE_ARCH_STRING     "1.16-01"
 #define IPIPE_MAJOR_NUMBER    1
-#define IPIPE_MINOR_NUMBER    12
-#define IPIPE_PATCH_NUMBER    0
+#define IPIPE_MINOR_NUMBER    16
+#define IPIPE_PATCH_NUMBER    1
 
 #ifdef CONFIG_SMP
 #error "I-pipe/blackfin: SMP not implemented"
@@ -55,25 +56,19 @@
 #define task_hijacked(p)						\
 	({								\
 		int __x__ = __ipipe_root_domain_p;			\
-		__clear_bit(IPIPE_SYNC_FLAG, &ipipe_root_cpudom_var(status)); \
 		if (__x__)						\
-			hard_local_irq_enable();				\
+			hard_local_irq_enable();			\
 		!__x__;							\
 	})
 
 struct ipipe_domain;
 
 struct ipipe_sysinfo {
-
-	int ncpus;		/* Number of CPUs on board */
-	u64 cpufreq;		/* CPU frequency (in Hz) */
-
-	/* Arch-dependent block */
-
-	struct {
-		unsigned tmirq;	/* Timer tick IRQ */
-		u64 tmfreq;	/* Timer frequency */
-	} archdep;
+	int sys_nr_cpus;	/* Number of CPUs on board */
+	int sys_hrtimer_irq;	/* hrtimer device IRQ */
+	u64 sys_hrtimer_freq;	/* hrtimer device frequency */
+	u64 sys_hrclock_freq;	/* hrclock device frequency */
+	u64 sys_cpu_freq;	/* CPU frequency (Hz) */
 };
 
 #define ipipe_read_tsc(t)					\
@@ -115,9 +110,19 @@
 void __ipipe_disable_irqdesc(struct ipipe_domain *ipd,
 			     unsigned irq);
 
-#define __ipipe_enable_irq(irq)		(irq_desc[irq].chip->unmask(irq))
+#define __ipipe_enable_irq(irq)						\
+	do {								\
+		struct irq_desc *desc = irq_to_desc(irq);		\
+		struct irq_chip *chip = get_irq_desc_chip(desc);	\
+		chip->irq_unmask(&desc->irq_data);			\
+	} while (0)
 
-#define __ipipe_disable_irq(irq)	(irq_desc[irq].chip->mask(irq))
+#define __ipipe_disable_irq(irq)					\
+	do {								\
+		struct irq_desc *desc = irq_to_desc(irq);		\
+		struct irq_chip *chip = get_irq_desc_chip(desc);	\
+		chip->irq_mask(&desc->irq_data);			\
+	} while (0)
 
 static inline int __ipipe_check_tickdev(const char *devname)
 {
@@ -128,12 +133,11 @@
 
 #define __ipipe_hook_critical_ipi(ipd) do { } while (0)
 
-#define __ipipe_sync_pipeline  ___ipipe_sync_pipeline
-void ___ipipe_sync_pipeline(unsigned long syncmask);
+void ___ipipe_sync_pipeline(void);
 
 void __ipipe_handle_irq(unsigned irq, struct pt_regs *regs);
 
-int __ipipe_get_irq_priority(unsigned irq);
+int __ipipe_get_irq_priority(unsigned int irq);
 
 void __ipipe_serial_debug(const char *fmt, ...);
 
@@ -152,7 +156,10 @@
 	return ffs(ul) - 1;
 }
 
-#define __ipipe_run_irqtail()  /* Must be a macro */			\
+#define __ipipe_do_root_xirq(ipd, irq)					\
+	((ipd)->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)))
+
+#define __ipipe_run_irqtail(irq)  /* Must be a macro */			\
 	do {								\
 		unsigned long __pending;				\
 		CSYNC();						\
@@ -164,42 +171,8 @@
 		}							\
 	} while (0)
 
-#define __ipipe_run_isr(ipd, irq)					\
-	do {								\
-		if (!__ipipe_pipeline_head_p(ipd))			\
-			hard_local_irq_enable();				\
-		if (ipd == ipipe_root_domain) {				\
-			if (unlikely(ipipe_virtual_irq_p(irq))) {	\
-				irq_enter();				\
-				ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-				irq_exit();				\
-			} else 						\
-				ipd->irqs[irq].handler(irq, &__raw_get_cpu_var(__ipipe_tick_regs)); \
-		} else {						\
-			__clear_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-			ipd->irqs[irq].handler(irq, ipd->irqs[irq].cookie); \
-			/* Attempt to exit the outer interrupt level before \
-			 * starting the deferred IRQ processing. */	\
-			__ipipe_run_irqtail();				\
-			__set_bit(IPIPE_SYNC_FLAG, &ipipe_cpudom_var(ipd, status)); \
-		}							\
-		hard_local_irq_disable();					\
-	} while (0)
-
 #define __ipipe_syscall_watched_p(p, sc)	\
-	(((p)->flags & PF_EVNOTIFY) || (unsigned long)sc >= NR_syscalls)
-
-void ipipe_init_irq_threads(void);
-
-int ipipe_start_irq_thread(unsigned irq, struct irq_desc *desc);
-
-#ifdef CONFIG_TICKSOURCE_CORETMR
-#define IRQ_SYSTMR		IRQ_CORETMR
-#define IRQ_PRIOTMR		IRQ_CORETMR
-#else
-#define IRQ_SYSTMR		IRQ_TIMER0
-#define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
-#endif
+	(ipipe_notifier_enabled_p(p) || (unsigned long)sc >= NR_syscalls)
 
 #ifdef CONFIG_BF561
 #define bfin_write_TIMER_DISABLE(val)	bfin_write_TMRS8_DISABLE(val)
@@ -219,11 +192,11 @@
 
 #define task_hijacked(p)		0
 #define ipipe_trap_notify(t, r)  	0
+#define __ipipe_root_tick_p(regs)	1
 
-#define ipipe_init_irq_threads()		do { } while (0)
-#define ipipe_start_irq_thread(irq, desc)	0
+#endif /* !CONFIG_IPIPE */
 
-#ifndef CONFIG_TICKSOURCE_GPTMR0
+#ifdef CONFIG_TICKSOURCE_CORETMR
 #define IRQ_SYSTMR		IRQ_CORETMR
 #define IRQ_PRIOTMR		IRQ_CORETMR
 #else
@@ -231,10 +204,6 @@
 #define IRQ_PRIOTMR		CONFIG_IRQ_TIMER0
 #endif
 
-#define __ipipe_root_tick_p(regs)	1
-
-#endif /* !CONFIG_IPIPE */
-
 #define ipipe_update_tick_evtdev(evtdev)	do { } while (0)
 
 #endif	/* !__ASM_BLACKFIN_IPIPE_H */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/irqflags.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/irqflags.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/irqflags.h	2011-05-19 00:06:34.000000000 -0400
@@ -89,15 +89,33 @@
 #ifdef CONFIG_IPIPE
 
 #include <linux/compiler.h>
-#include <linux/ipipe_base.h>
 #include <linux/ipipe_trace.h>
+/*
+ * Way too many inter-deps between low-level headers in this port, so
+ * we redeclare the required bits we cannot pick from
+ * <asm/ipipe_base.h> to prevent circular dependencies.
+ */
+void __ipipe_stall_root(void);
+void __ipipe_unstall_root(void);
+unsigned long __ipipe_test_root(void);
+unsigned long __ipipe_test_and_stall_root(void);
+void __ipipe_restore_root(unsigned long flags);
+
+#ifdef CONFIG_IPIPE_DEBUG_CONTEXT
+struct ipipe_domain;
+extern struct ipipe_domain ipipe_root;
+void ipipe_check_context(struct ipipe_domain *ipd);
+#define __check_irqop_context(ipd)  ipipe_check_context(&ipipe_root)
+#else /* !CONFIG_IPIPE_DEBUG_CONTEXT */
+#define __check_irqop_context(ipd)  do { } while (0)
+#endif /* !CONFIG_IPIPE_DEBUG_CONTEXT */
 
 /*
  * Interrupt pipe interface to linux/irqflags.h.
  */
 static inline void arch_local_irq_disable(void)
 {
-	ipipe_check_context(ipipe_root_domain);
+	__check_irqop_context();
 	__ipipe_stall_root();
 	barrier();
 }
@@ -105,7 +123,7 @@
 static inline void arch_local_irq_enable(void)
 {
 	barrier();
-	ipipe_check_context(ipipe_root_domain);
+	__check_irqop_context();
 	__ipipe_unstall_root();
 }
 
@@ -119,16 +137,21 @@
 	return flags == bfin_no_irqs;
 }
 
-static inline void arch_local_irq_save_ptr(unsigned long *_flags)
+static inline unsigned long arch_local_irq_save(void)
 {
-	x = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
+	unsigned long flags;
+
+	__check_irqop_context();
+	flags = __ipipe_test_and_stall_root() ? bfin_no_irqs : bfin_irq_flags;
 	barrier();
+
+	return flags;
 }
 
-static inline unsigned long arch_local_irq_save(void)
+static inline void arch_local_irq_restore(unsigned long flags)
 {
-	ipipe_check_context(ipipe_root_domain);
-	return __hard_local_irq_save();
+	__check_irqop_context();
+	__ipipe_restore_root(flags == bfin_no_irqs);
 }
 
 static inline unsigned long arch_mangle_irq_bits(int virt, unsigned long real)
@@ -192,7 +215,10 @@
 # define hard_local_irq_restore(flags)	__hard_local_irq_restore(flags)
 #endif /* !CONFIG_IPIPE_TRACE_IRQSOFF */
 
-#else /* CONFIG_IPIPE */
+#define hard_local_irq_save_cond()		hard_local_irq_save()
+#define hard_local_irq_restore_cond(flags)	hard_local_irq_restore(flags)
+
+#else /* !CONFIG_IPIPE */
 
 /*
  * Direct interface to linux/irqflags.h.
@@ -212,7 +238,48 @@
 #define hard_local_irq_restore(flags)	__hard_local_irq_restore(flags)
 #define hard_local_irq_enable()		__hard_local_irq_enable()
 #define hard_local_irq_disable()	__hard_local_irq_disable()
-
+#define hard_local_irq_save_cond()		hard_local_save_flags()
+#define hard_local_irq_restore_cond(flags)	do { (void)(flags); } while (0)
 
 #endif /* !CONFIG_IPIPE */
+
+#ifdef CONFIG_SMP
+#define hard_local_irq_save_smp()		hard_local_irq_save()
+#define hard_local_irq_restore_smp(flags)	hard_local_irq_restore(flags)
+#else
+#define hard_local_irq_save_smp()		hard_local_save_flags()
+#define hard_local_irq_restore_smp(flags)	do { (void)(flags); } while (0)
+#endif
+
+/*
+ * Remap the arch-neutral IRQ state manipulation macros to the
+ * blackfin-specific hard_local_irq_* API.
+ */
+#define local_irq_save_hw(flags)			\
+	do {						\
+		(flags) = hard_local_irq_save();	\
+	} while (0)
+#define local_irq_restore_hw(flags)		\
+	do {					\
+		hard_local_irq_restore(flags);	\
+	} while (0)
+#define local_irq_disable_hw()			\
+	do {					\
+		hard_local_irq_disable();	\
+	} while (0)
+#define local_irq_enable_hw()			\
+	do {					\
+		hard_local_irq_enable();	\
+	} while (0)
+#define local_irq_save_hw_notrace(flags)		\
+	do {						\
+		(flags) = __hard_local_irq_save();	\
+	} while (0)
+#define local_irq_restore_hw_notrace(flags)		\
+	do {						\
+		__hard_local_irq_restore(flags);	\
+	} while (0)
+
+#define irqs_disabled_hw()	hard_irqs_disabled()
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/smp.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/smp.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/smp.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,12 @@
 
 #define raw_smp_processor_id()  blackfin_core_id()
 
-extern char coreb_trampoline_start, coreb_trampoline_end;
+extern void bfin_relocate_coreb_l1_mem(void);
+
+#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
+asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
+extern unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
 
 struct corelock_slot {
 	int lock;
@@ -34,7 +39,7 @@
 void smp_icache_flush_range_others(unsigned long start,
 				   unsigned long end);
 #ifdef CONFIG_HOTPLUG_CPU
-void coreb_sleep(u32 sic_iwr0, u32 sic_iwr1, u32 sic_iwr2);
+void coreb_die(void);
 void cpu_die(void);
 void platform_cpu_die(void);
 int __cpu_disable(void);
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/system.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,11 +19,11 @@
  * Force strict CPU ordering.
  */
 #define nop()  __asm__ __volatile__ ("nop;\n\t" : : )
-#define mb()   __asm__ __volatile__ (""   : : : "memory")
-#define rmb()  __asm__ __volatile__ (""   : : : "memory")
-#define wmb()  __asm__ __volatile__ (""   : : : "memory")
-#define set_mb(var, value) do { (void) xchg(&var, value); } while (0)
-#define read_barrier_depends() 		do { } while(0)
+#define smp_mb()  mb()
+#define smp_rmb() rmb()
+#define smp_wmb() wmb()
+#define set_mb(var, value) do { var = value; mb(); } while (0)
+#define smp_read_barrier_depends()	read_barrier_depends()
 
 #ifdef CONFIG_SMP
 asmlinkage unsigned long __raw_xchg_1_asm(volatile void *ptr, unsigned long value);
@@ -37,16 +37,16 @@
 					unsigned long new, unsigned long old);
 
 #ifdef __ARCH_SYNC_CORE_DCACHE
-# define smp_mb()	do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0)
-# define smp_rmb()	do { barrier(); smp_check_barrier(); } while (0)
-# define smp_wmb()	do { barrier(); smp_mark_barrier(); } while (0)
-#define smp_read_barrier_depends()	do { barrier(); smp_check_barrier(); } while (0)
-
+/* Force Core data cache coherence */
+# define mb()	do { barrier(); smp_check_barrier(); smp_mark_barrier(); } while (0)
+# define rmb()	do { barrier(); smp_check_barrier(); } while (0)
+# define wmb()	do { barrier(); smp_mark_barrier(); } while (0)
+# define read_barrier_depends()	do { barrier(); smp_check_barrier(); } while (0)
 #else
-# define smp_mb()	barrier()
-# define smp_rmb()	barrier()
-# define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	barrier()
+# define mb()	barrier()
+# define rmb()	barrier()
+# define wmb()	barrier()
+# define read_barrier_depends()	do { } while (0)
 #endif
 
 static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
@@ -99,10 +99,10 @@
 
 #else /* !CONFIG_SMP */
 
-#define smp_mb()	barrier()
-#define smp_rmb()	barrier()
-#define smp_wmb()	barrier()
-#define smp_read_barrier_depends()	do { } while(0)
+#define mb()	barrier()
+#define rmb()	barrier()
+#define wmb()	barrier()
+#define read_barrier_depends()	do { } while (0)
 
 struct __xchg_dummy {
 	unsigned long a[100];
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/traps.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/traps.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/traps.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/traps.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 #define HWC_x3(level) \
 	"External Memory Addressing Error\n"
 #define EXC_0x04(level) \
-	"Unimplmented exception occured\n" \
+	"Unimplmented exception occurred\n" \
 	level " - Maybe you forgot to install a custom exception handler?\n"
 #define HWC_x12(level) \
 	"Performance Monitor Overflow\n"
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/blackfin/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/blackfin/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -393,8 +393,12 @@
 #define __NR_fanotify_mark	372
 #define __NR_prlimit64		373
 #define __NR_cacheflush		374
+#define __NR_name_to_handle_at	375
+#define __NR_open_by_handle_at	376
+#define __NR_clock_adjtime	377
+#define __NR_syncfs		378
 
-#define __NR_syscall		375
+#define __NR_syscall		379
 #define NR_syscalls		__NR_syscall
 
 /* Old optional stuff no one actually uses */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/Kconfig linux-libre-2.6.39-gnu/arch/blackfin/Kconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 	select HAVE_OPROFILE
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_ATOMIC64
 	select GENERIC_IRQ_PROBE
 	select IRQ_PER_CPU if SMP
 
@@ -690,13 +691,13 @@
 
 
 menu "Blackfin Kernel Optimizations"
-	depends on !SMP
 
 comment "Memory Optimizations"
 
 config I_ENTRY_L1
 	bool "Locate interrupt entry code in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, interrupt entry code (STORE/RESTORE CONTEXT) is linked
 	  into L1 instruction memory. (less latency)
@@ -704,6 +705,7 @@
 config EXCPT_IRQ_SYSC_L1
 	bool "Locate entire ASM lowlevel exception / interrupt - Syscall and CPLB handler code in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the entire ASM lowlevel exception and interrupt entry code
 	  (STORE/RESTORE CONTEXT) is linked into L1 instruction memory.
@@ -712,6 +714,7 @@
 config DO_IRQ_L1
 	bool "Locate frequently called do_irq dispatcher function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called do_irq dispatcher function is linked
 	  into L1 instruction memory. (less latency)
@@ -719,6 +722,7 @@
 config CORE_TIMER_IRQ_L1
 	bool "Locate frequently called timer_interrupt() function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called timer_interrupt() function is linked
 	  into L1 instruction memory. (less latency)
@@ -726,6 +730,7 @@
 config IDLE_L1
 	bool "Locate frequently idle function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called idle function is linked
 	  into L1 instruction memory. (less latency)
@@ -733,6 +738,7 @@
 config SCHEDULE_L1
 	bool "Locate kernel schedule function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the frequently called kernel schedule is linked
 	  into L1 instruction memory. (less latency)
@@ -740,6 +746,7 @@
 config ARITHMETIC_OPS_L1
 	bool "Locate kernel owned arithmetic functions in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, arithmetic functions are linked
 	  into L1 instruction memory. (less latency)
@@ -747,6 +754,7 @@
 config ACCESS_OK_L1
 	bool "Locate access_ok function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the access_ok function is linked
 	  into L1 instruction memory. (less latency)
@@ -754,6 +762,7 @@
 config MEMSET_L1
 	bool "Locate memset function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the memset function is linked
 	  into L1 instruction memory. (less latency)
@@ -761,6 +770,7 @@
 config MEMCPY_L1
 	bool "Locate memcpy function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the memcpy function is linked
 	  into L1 instruction memory. (less latency)
@@ -768,6 +778,7 @@
 config STRCMP_L1
 	bool "locate strcmp function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strcmp function is linked
 	  into L1 instruction memory (less latency).
@@ -775,6 +786,7 @@
 config STRNCMP_L1
 	bool "locate strncmp function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strncmp function is linked
 	  into L1 instruction memory (less latency).
@@ -782,6 +794,7 @@
 config STRCPY_L1
 	bool "locate strcpy function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strcpy function is linked
 	  into L1 instruction memory (less latency).
@@ -789,6 +802,7 @@
 config STRNCPY_L1
 	bool "locate strncpy function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, the strncpy function is linked
 	  into L1 instruction memory (less latency).
@@ -796,6 +810,7 @@
 config SYS_BFIN_SPINLOCK_L1
 	bool "Locate sys_bfin_spinlock function in L1 Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled, sys_bfin_spinlock function is linked
 	  into L1 instruction memory. (less latency)
@@ -803,6 +818,7 @@
 config IP_CHECKSUM_L1
 	bool "Locate IP Checksum function in L1 Memory"
 	default n
+	depends on !SMP
 	help
 	  If enabled, the IP Checksum function is linked
 	  into L1 instruction memory. (less latency)
@@ -811,7 +827,7 @@
 	bool "Locate cacheline_aligned data to L1 Data Memory"
 	default y if !BF54x
 	default n if BF54x
-	depends on !BF531
+	depends on !SMP && !BF531
 	help
 	  If enabled, cacheline_aligned data is linked
 	  into L1 data memory. (less latency)
@@ -819,7 +835,7 @@
 config SYSCALL_TAB_L1
 	bool "Locate Syscall Table L1 Data Memory"
 	default n
-	depends on !BF531
+	depends on !SMP && !BF531
 	help
 	  If enabled, the Syscall LUT is linked
 	  into L1 data memory. (less latency)
@@ -827,16 +843,16 @@
 config CPLB_SWITCH_TAB_L1
 	bool "Locate CPLB Switch Tables L1 Data Memory"
 	default n
-	depends on !BF531
+	depends on !SMP && !BF531
 	help
 	  If enabled, the CPLB Switch Tables are linked
 	  into L1 data memory. (less latency)
 
-config CACHE_FLUSH_L1
-	bool "Locate cache flush funcs in L1 Inst Memory"
+config ICACHE_FLUSH_L1
+	bool "Locate icache flush funcs in L1 Inst Memory"
 	default y
 	help
-	  If enabled, the Blackfin cache flushing functions are linked
+	  If enabled, the Blackfin icache flushing functions are linked
 	  into L1 instruction memory.
 
 	  Note that this might be required to address anomalies, but
@@ -844,9 +860,18 @@
 	  If you are using a processor affected by an anomaly, the build
 	  system will double check for you and prevent it.
 
+config DCACHE_FLUSH_L1
+	bool "Locate dcache flush funcs in L1 Inst Memory"
+	default y
+	depends on !SMP
+	help
+	  If enabled, the Blackfin dcache flushing functions are linked
+	  into L1 instruction memory.
+
 config APP_STACK_L1
 	bool "Support locating application stack in L1 Scratch Memory"
 	default y
+	depends on !SMP
 	help
 	  If enabled the application stack can be located in L1
 	  scratch memory (less latency).
@@ -856,7 +881,7 @@
 config EXCEPTION_L1_SCRATCH
 	bool "Locate exception stack in L1 Scratch Memory"
 	default n
-	depends on !APP_STACK_L1
+	depends on !SMP && !APP_STACK_L1
 	help
 	  Whenever an exception occurs, use the L1 Scratch memory for
 	  stack storage.  You cannot place the stacks of FLAT binaries
@@ -868,6 +893,7 @@
 config BFIN_INS_LOWOVERHEAD
 	bool "ins[bwl] low overhead, higher interrupt latency"
 	default y
+	depends on !SMP
 	help
 	  Reads on the Blackfin are speculative. In Blackfin terms, this means
 	  they can be interrupted at any time (even after they have been issued
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/Kconfig.debug linux-libre-2.6.39-gnu/arch/blackfin/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/blackfin/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -59,7 +59,7 @@
           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
+	  try turning this on to ensure they are at least coming from the
 	  proper thread.
 
 	  On production systems, it is safe (and a small optimization) to say N.
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/bfin_dma_5xx.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/bfin_dma_5xx.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/bfin_dma_5xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/bfin_dma_5xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,6 +84,24 @@
 late_initcall(proc_dma_init);
 #endif
 
+static void set_dma_peripheral_map(unsigned int channel, const char *device_id)
+{
+#ifdef CONFIG_BF54x
+	unsigned int per_map;
+
+	switch (channel) {
+		case CH_UART2_RX: per_map = 0xC << 12; break;
+		case CH_UART2_TX: per_map = 0xD << 12; break;
+		case CH_UART3_RX: per_map = 0xE << 12; break;
+		case CH_UART3_TX: per_map = 0xF << 12; break;
+		default:          return;
+	}
+
+	if (strncmp(device_id, "BFIN_UART", 9) == 0)
+		dma_ch[channel].regs->peripheral_map = per_map;
+#endif
+}
+
 /**
  *	request_dma - request a DMA channel
  *
@@ -111,19 +129,7 @@
 		return -EBUSY;
 	}
 
-#ifdef CONFIG_BF54x
-	if (channel >= CH_UART2_RX && channel <= CH_UART3_TX) {
-		unsigned int per_map;
-		per_map = dma_ch[channel].regs->peripheral_map & 0xFFF;
-		if (strncmp(device_id, "BFIN_UART", 9) == 0)
-			dma_ch[channel].regs->peripheral_map = per_map |
-				((channel - CH_UART2_RX + 0xC)<<12);
-		else
-			dma_ch[channel].regs->peripheral_map = per_map |
-				((channel - CH_UART2_RX + 0x6)<<12);
-	}
-#endif
-
+	set_dma_peripheral_map(channel, device_id);
 	dma_ch[channel].device_id = device_id;
 	dma_ch[channel].irq = 0;
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/gptimers.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/gptimers.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/gptimers.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/gptimers.c	2011-05-19 00:06:34.000000000 -0400
@@ -268,7 +268,7 @@
 	_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];
+			group_regs[BFIN_TIMER_OCTET(i)]->status = trun_mask[i];
 	SSYNC();
 }
 EXPORT_SYMBOL(disable_gptimers);
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/ipipe.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/ipipe.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/ipipe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/ipipe.c	2011-05-19 00:06:34.000000000 -0400
@@ -154,7 +154,7 @@
 	 * pending for it.
 	 */
 	if (test_bit(IPIPE_AHEAD_FLAG, &this_domain->flags) &&
-	    ipipe_head_cpudom_var(irqpend_himask) == 0)
+	    !__ipipe_ipending_p(ipipe_head_cpudom_ptr()))
 		goto out;
 
 	__ipipe_walk_pipeline(head);
@@ -185,25 +185,21 @@
 }
 EXPORT_SYMBOL(__ipipe_disable_irqdesc);
 
-int __ipipe_syscall_root(struct pt_regs *regs)
+asmlinkage int __ipipe_syscall_root(struct pt_regs *regs)
 {
 	struct ipipe_percpu_domain_data *p;
-	unsigned long flags;
+	void (*hook)(void);
 	int ret;
 
+	WARN_ON_ONCE(irqs_disabled_hw());
+
 	/*
-	 * We need to run the IRQ tail hook whenever we don't
-	 * propagate a syscall to higher domains, because we know that
-	 * important operations might be pending there (e.g. Xenomai
-	 * deferred rescheduling).
+	 * We need to run the IRQ tail hook each time we intercept a
+	 * syscall, because we know that important operations might be
+	 * pending there (e.g. Xenomai deferred rescheduling).
 	 */
-
-	if (regs->orig_p0 < NR_syscalls) {
-		void (*hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
-		hook();
-		if ((current->flags & PF_EVNOTIFY) == 0)
-			return 0;
-	}
+	hook = (__typeof__(hook))__ipipe_irq_tail_hook;
+	hook();
 
 	/*
 	 * This routine either returns:
@@ -214,51 +210,47 @@
 	 * tail work has to be performed (for handling signals etc).
 	 */
 
-	if (!__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
+	if (!__ipipe_syscall_watched_p(current, regs->orig_p0) ||
+	    !__ipipe_event_monitored_p(IPIPE_EVENT_SYSCALL))
 		return 0;
 
 	ret = __ipipe_dispatch_event(IPIPE_EVENT_SYSCALL, regs);
 
-	flags = hard_local_irq_save();
+	hard_local_irq_disable();
 
-	if (!__ipipe_root_domain_p) {
-		hard_local_irq_restore(flags);
-		return 1;
+	/*
+	 * This is the end of the syscall path, so we may
+	 * safely assume a valid Linux task stack here.
+	 */
+	if (current->ipipe_flags & PF_EVTRET) {
+		current->ipipe_flags &= ~PF_EVTRET;
+		__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
 	}
 
-	p = ipipe_root_cpudom_ptr();
-	if ((p->irqpend_himask & IPIPE_IRQMASK_VIRT) != 0)
-		__ipipe_sync_pipeline(IPIPE_IRQMASK_VIRT);
+	if (!__ipipe_root_domain_p)
+		ret = -1;
+	else {
+		p = ipipe_root_cpudom_ptr();
+		if (__ipipe_ipending_p(p))
+			__ipipe_sync_pipeline();
+	}
 
-	hard_local_irq_restore(flags);
+	hard_local_irq_enable();
 
 	return -ret;
 }
 
-unsigned long ipipe_critical_enter(void (*syncfn) (void))
-{
-	unsigned long flags;
-
-	flags = hard_local_irq_save();
-
-	return flags;
-}
-
-void ipipe_critical_exit(unsigned long flags)
-{
-	hard_local_irq_restore(flags);
-}
-
 static void __ipipe_no_irqtail(void)
 {
 }
 
 int ipipe_get_sysinfo(struct ipipe_sysinfo *info)
 {
-	info->ncpus = num_online_cpus();
-	info->cpufreq = ipipe_cpu_freq();
-	info->archdep.tmirq = IPIPE_TIMER_IRQ;
-	info->archdep.tmfreq = info->cpufreq;
+	info->sys_nr_cpus = num_online_cpus();
+	info->sys_cpu_freq = ipipe_cpu_freq();
+	info->sys_hrtimer_irq = IPIPE_TIMER_IRQ;
+	info->sys_hrtimer_freq = __ipipe_core_clock;
+	info->sys_hrclock_freq = __ipipe_core_clock;
 
 	return 0;
 }
@@ -289,6 +281,7 @@
 asmlinkage void __ipipe_sync_root(void)
 {
 	void (*irq_tail_hook)(void) = (void (*)(void))__ipipe_irq_tail_hook;
+	struct ipipe_percpu_domain_data *p;
 	unsigned long flags;
 
 	BUG_ON(irqs_disabled());
@@ -300,19 +293,20 @@
 
 	clear_thread_flag(TIF_IRQ_SYNC);
 
-	if (ipipe_root_cpudom_var(irqpend_himask) != 0)
-		__ipipe_sync_pipeline(IPIPE_IRQMASK_ANY);
+	p = ipipe_root_cpudom_ptr();
+	if (__ipipe_ipending_p(p))
+		__ipipe_sync_pipeline();
 
 	hard_local_irq_restore(flags);
 }
 
-void ___ipipe_sync_pipeline(unsigned long syncmask)
+void ___ipipe_sync_pipeline(void)
 {
 	if (__ipipe_root_domain_p &&
 	    test_bit(IPIPE_SYNCDEFER_FLAG, &ipipe_root_cpudom_var(status)))
 		return;
 
-	__ipipe_sync_stage(syncmask);
+	__ipipe_sync_stage();
 }
 
 void __ipipe_disable_root_irqs_hw(void)
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/irqchip.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/irqchip.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/irqchip.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/irqchip.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,21 +39,23 @@
 	unsigned long flags;
 
 	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		struct irq_desc *desc = irq_to_desc(i);
+
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
 		for_each_online_cpu(j)
 			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-		seq_printf(p, " %8s", irq_desc[i].chip->name);
+		seq_printf(p, " %8s", irq_desc_get_chip(desc)->name);
 		seq_printf(p, "  %s", action->name);
 		for (action = action->next; action; action = action->next)
 			seq_printf(p, "  %s", action->name);
 
 		seq_putc(p, '\n');
  skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	} else if (i == NR_IRQS) {
 		seq_printf(p, "NMI: ");
 		for_each_online_cpu(j)
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/kgdb.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/kgdb.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/kgdb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/kgdb.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,7 +181,7 @@
 		return -ENOSPC;
 	}
 
-	/* Becasue hardware data watchpoint impelemented in current
+	/* Because hardware data watchpoint impelemented in current
 	 * Blackfin can not trigger an exception event as the hardware
 	 * instrction watchpoint does, we ignaore all data watch point here.
 	 * They can be turned on easily after future blackfin design
@@ -422,11 +422,7 @@
 
 struct kgdb_arch arch_kgdb_ops = {
 	.gdb_bpt_instr = {0xa1},
-#ifdef CONFIG_SMP
-	.flags = KGDB_HW_BREAKPOINT|KGDB_THR_PROC_SWAP,
-#else
 	.flags = KGDB_HW_BREAKPOINT,
-#endif
 	.set_hw_breakpoint = bfin_set_hw_break,
 	.remove_hw_breakpoint = bfin_remove_hw_break,
 	.disable_hw_break = bfin_disable_hw_debug,
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/module.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/module.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/module.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * Licensed under the GPL-2 or later
  */
 
-#define pr_fmt(fmt) "module %s: " fmt
+#define pr_fmt(fmt) "module %s: " fmt, mod->name
 
 #include <linux/moduleloader.h>
 #include <linux/elf.h>
@@ -57,8 +57,7 @@
 			dest = l1_inst_sram_alloc(s->sh_size);
 			mod->arch.text_l1 = dest;
 			if (dest == NULL) {
-				pr_err("L1 inst memory allocation failed\n",
-					mod->name);
+				pr_err("L1 inst memory allocation failed\n");
 				return -1;
 			}
 			dma_memcpy(dest, (void *)s->sh_addr, s->sh_size);
@@ -70,8 +69,7 @@
 			dest = l1_data_sram_alloc(s->sh_size);
 			mod->arch.data_a_l1 = dest;
 			if (dest == NULL) {
-				pr_err("L1 data memory allocation failed\n",
-					mod->name);
+				pr_err("L1 data memory allocation failed\n");
 				return -1;
 			}
 			memcpy(dest, (void *)s->sh_addr, s->sh_size);
@@ -83,8 +81,7 @@
 			dest = l1_data_sram_zalloc(s->sh_size);
 			mod->arch.bss_a_l1 = dest;
 			if (dest == NULL) {
-				pr_err("L1 data memory allocation failed\n",
-					mod->name);
+				pr_err("L1 data memory allocation failed\n");
 				return -1;
 			}
 
@@ -93,8 +90,7 @@
 			dest = l1_data_B_sram_alloc(s->sh_size);
 			mod->arch.data_b_l1 = dest;
 			if (dest == NULL) {
-				pr_err("L1 data memory allocation failed\n",
-					mod->name);
+				pr_err("L1 data memory allocation failed\n");
 				return -1;
 			}
 			memcpy(dest, (void *)s->sh_addr, s->sh_size);
@@ -104,8 +100,7 @@
 			dest = l1_data_B_sram_alloc(s->sh_size);
 			mod->arch.bss_b_l1 = dest;
 			if (dest == NULL) {
-				pr_err("L1 data memory allocation failed\n",
-					mod->name);
+				pr_err("L1 data memory allocation failed\n");
 				return -1;
 			}
 			memset(dest, 0, s->sh_size);
@@ -117,8 +112,7 @@
 			dest = l2_sram_alloc(s->sh_size);
 			mod->arch.text_l2 = dest;
 			if (dest == NULL) {
-				pr_err("L2 SRAM allocation failed\n",
-					mod->name);
+				pr_err("L2 SRAM allocation failed\n");
 				return -1;
 			}
 			memcpy(dest, (void *)s->sh_addr, s->sh_size);
@@ -130,8 +124,7 @@
 			dest = l2_sram_alloc(s->sh_size);
 			mod->arch.data_l2 = dest;
 			if (dest == NULL) {
-				pr_err("L2 SRAM allocation failed\n",
-					mod->name);
+				pr_err("L2 SRAM allocation failed\n");
 				return -1;
 			}
 			memcpy(dest, (void *)s->sh_addr, s->sh_size);
@@ -143,8 +136,7 @@
 			dest = l2_sram_zalloc(s->sh_size);
 			mod->arch.bss_l2 = dest;
 			if (dest == NULL) {
-				pr_err("L2 SRAM allocation failed\n",
-					mod->name);
+				pr_err("L2 SRAM allocation failed\n");
 				return -1;
 			}
 
@@ -160,9 +152,9 @@
 
 int
 apply_relocate(Elf_Shdr * sechdrs, const char *strtab,
-	       unsigned int symindex, unsigned int relsec, struct module *me)
+	       unsigned int symindex, unsigned int relsec, struct module *mod)
 {
-	pr_err(".rel unsupported\n", me->name);
+	pr_err(".rel unsupported\n");
 	return -ENOEXEC;
 }
 
@@ -186,7 +178,7 @@
 	Elf32_Sym *sym;
 	unsigned long location, value, size;
 
-	pr_debug("applying relocate section %u to %u\n", mod->name,
+	pr_debug("applying relocate section %u to %u\n",
 		relsec, sechdrs[relsec].sh_info);
 
 	for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
@@ -203,14 +195,14 @@
 
 #ifdef CONFIG_SMP
 		if (location >= COREB_L1_DATA_A_START) {
-			pr_err("cannot relocate in L1: %u (SMP kernel)",
-				mod->name, ELF32_R_TYPE(rel[i].r_info));
+			pr_err("cannot relocate in L1: %u (SMP kernel)\n",
+				ELF32_R_TYPE(rel[i].r_info));
 			return -ENOEXEC;
 		}
 #endif
 
 		pr_debug("location is %lx, value is %lx type is %d\n",
-			mod->name, location, value, ELF32_R_TYPE(rel[i].r_info));
+			location, value, ELF32_R_TYPE(rel[i].r_info));
 
 		switch (ELF32_R_TYPE(rel[i].r_info)) {
 
@@ -230,11 +222,11 @@
 		case R_BFIN_PCREL12_JUMP_S:
 		case R_BFIN_PCREL10:
 			pr_err("unsupported relocation: %u (no -mlong-calls?)\n",
-				mod->name, ELF32_R_TYPE(rel[i].r_info));
+				ELF32_R_TYPE(rel[i].r_info));
 			return -ENOEXEC;
 
 		default:
-			pr_err("unknown relocation: %u\n", mod->name,
+			pr_err("unknown relocation: %u\n",
 				ELF32_R_TYPE(rel[i].r_info));
 			return -ENOEXEC;
 		}
@@ -251,8 +243,7 @@
 			isram_memcpy((void *)location, &value, size);
 			break;
 		default:
-			pr_err("invalid relocation for %#lx\n",
-				mod->name, location);
+			pr_err("invalid relocation for %#lx\n", location);
 			return -ENOEXEC;
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/setup.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -215,11 +215,48 @@
 
 	early_dma_memcpy_done();
 
+#if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
+	blackfin_iflush_l1_entry[0] = (unsigned long)blackfin_icache_flush_range_l1;
+#endif
+
 	/* if necessary, copy L2 text/data to L2 SRAM */
 	if (L2_LENGTH && l2_len)
 		memcpy(_stext_l2, _l2_lma, l2_len);
 }
 
+#ifdef CONFIG_SMP
+void __init bfin_relocate_coreb_l1_mem(void)
+{
+	unsigned long text_l1_len = (unsigned long)_text_l1_len;
+	unsigned long data_l1_len = (unsigned long)_data_l1_len;
+	unsigned long data_b_l1_len = (unsigned long)_data_b_l1_len;
+
+	blackfin_dma_early_init();
+
+	/* if necessary, copy L1 text to L1 instruction SRAM */
+	if (L1_CODE_LENGTH && text_l1_len)
+		early_dma_memcpy((void *)COREB_L1_CODE_START, _text_l1_lma,
+				text_l1_len);
+
+	/* if necessary, copy L1 data to L1 data bank A SRAM */
+	if (L1_DATA_A_LENGTH && data_l1_len)
+		early_dma_memcpy((void *)COREB_L1_DATA_A_START, _data_l1_lma,
+				data_l1_len);
+
+	/* if necessary, copy L1 data B to L1 data bank B SRAM */
+	if (L1_DATA_B_LENGTH && data_b_l1_len)
+		early_dma_memcpy((void *)COREB_L1_DATA_B_START, _data_b_l1_lma,
+				data_b_l1_len);
+
+	early_dma_memcpy_done();
+
+#ifdef CONFIG_ICACHE_FLUSH_L1
+	blackfin_iflush_l1_entry[1] = (unsigned long)blackfin_icache_flush_range_l1 -
+			(unsigned long)_stext_l1 + COREB_L1_CODE_START;
+#endif
+}
+#endif
+
 #ifdef CONFIG_ROMKERNEL
 void __init bfin_relocate_xip_data(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/time.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -114,16 +114,14 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 #ifdef CONFIG_CORE_TIMER_IRQ_L1
 __attribute__((l1_text))
 #endif
 irqreturn_t timer_interrupt(int irq, void *dummy)
 {
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 
 #ifdef CONFIG_IPIPE
 	update_root_process_times(get_irq_regs());
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/time-ts.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/time-ts.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/time-ts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/time-ts.c	2011-05-19 00:06:34.000000000 -0400
@@ -206,8 +206,14 @@
 {
 	struct clock_event_device *evt = dev_id;
 	smp_mb();
-	evt->event_handler(evt);
+	/*
+	 * We want to ACK before we handle so that we can handle smaller timer
+	 * intervals.  This way if the timer expires again while we're handling
+	 * things, we're more likely to see that 2nd int rather than swallowing
+	 * it by ACKing the int at the end of this handler.
+	 */
 	bfin_gptmr0_ack();
+	evt->event_handler(evt);
 	return IRQ_HANDLED;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/trace.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/trace.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/trace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/trace.c	2011-05-19 00:06:34.000000000 -0400
@@ -912,10 +912,11 @@
 	/* if no interrupts are going off, don't print this out */
 	if (fp->ipend & ~0x3F) {
 		for (i = 0; i < (NR_IRQS - 1); i++) {
+			struct irq_desc *desc = irq_to_desc(i);
 			if (!in_atomic)
-				raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
+				raw_spin_lock_irqsave(&desc->lock, flags);
 
-			action = irq_desc[i].action;
+			action = desc->action;
 			if (!action)
 				goto unlock;
 
@@ -928,7 +929,7 @@
 			pr_cont("\n");
 unlock:
 			if (!in_atomic)
-				raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+				raw_spin_unlock_irqrestore(&desc->lock, flags);
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/traps.c linux-libre-2.6.39-gnu/arch/blackfin/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,7 +98,7 @@
 	/* send the appropriate signal to the user program */
 	switch (trapnr) {
 
-	/* This table works in conjuction with the one in ./mach-common/entry.S
+	/* This table works in conjunction with the one in ./mach-common/entry.S
 	 * Some exceptions are handled there (in assembly, in exception space)
 	 * Some are handled here, (in C, in interrupt space)
 	 * Some, like CPLB, are handled in both, where the normal path is
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/blackfin/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/blackfin/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,7 @@
 
 	. = ALIGN(16);
 	INIT_DATA_SECTION(16)
-	PERCPU(4)
+	PERCPU(32, PAGE_SIZE)
 
 	.exit.data :
 	{
@@ -176,6 +176,7 @@
 	{
 		. = ALIGN(4);
 		__stext_l1 = .;
+		*(.l1.text.head)
 		*(.l1.text)
 #ifdef CONFIG_SCHEDULE_L1
 		SCHED_TEXT
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/lib/ins.S linux-libre-2.6.39-gnu/arch/blackfin/lib/ins.S
--- linux-libre-2.6.38-gnu/arch/blackfin/lib/ins.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/lib/ins.S	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
  *  - DMA version, which do not suffer from this issue. DMA versions have
  *      different name (prefixed by dma_ ), and are located in
  *      ../kernel/bfin_dma_5xx.c
- * Using the dma related functions are recommended for transfering large
+ * Using the dma related functions are recommended for transferring large
  * buffers in/out of FIFOs.
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/lib/memmove.S linux-libre-2.6.39-gnu/arch/blackfin/lib/memmove.S
--- linux-libre-2.6.38-gnu/arch/blackfin/lib/memmove.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/lib/memmove.S	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
 	[P0++] = R1;
 
 	CC = P2 == 0;             /* any remaining bytes? */
-	P3 = I0;                  /* Ammend P3 to updated ptr. */
+	P3 = I0;                  /* Amend P3 to updated ptr. */
 	IF !CC JUMP .Lbytes;
 	P3 = I1;
 	RTS;
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf518/include/mach/defBF512.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf518/include/mach/defBF512.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf518/include/mach/defBF512.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf518/include/mach/defBF512.h	2011-05-19 00:06:34.000000000 -0400
@@ -1201,25 +1201,6 @@
 #define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
 #define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
 
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
-#define	REP			0x0002	/* HDMA Request Polarity					*/
-#define	UTE			0x0004	/* Urgency Threshold Enable					*/
-#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
-#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
-#define	DRQ			0x0300	/* HDMA Request Type						*/
-#define	DRQ_NONE	0x0000	/* 		No Request							*/
-#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
-#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
-#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
-#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
-#define	PS			0x2000	/* HDMA Pin Status							*/
-#define	OI			0x4000	/* Overflow Interrupt Generated				*/
-#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf527/include/mach/defBF522.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf527/include/mach/defBF522.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf527/include/mach/defBF522.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf527/include/mach/defBF522.h	2011-05-19 00:06:34.000000000 -0400
@@ -1204,25 +1204,6 @@
 #define	PGTE_PPI		0x0000			/* 		Enable PPI D15:13			*/
 #define	PGTE_SPORT		0x0800			/* 		Enable DT1PRI/TFS1/TSCLK1	*/
 
-
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1					*/
-#define	REP			0x0002	/* HDMA Request Polarity					*/
-#define	UTE			0x0004	/* Urgency Threshold Enable					*/
-#define	OIE			0x0010	/* Overflow Interrupt Enable				*/
-#define	BDIE		0x0020	/* Block Done Interrupt Enable				*/
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT		*/
-#define	DRQ			0x0300	/* HDMA Request Type						*/
-#define	DRQ_NONE	0x0000	/* 		No Request							*/
-#define	DRQ_SINGLE	0x0100	/* 		Channels Request Single				*/
-#define	DRQ_MULTI	0x0200	/* 		Channels Request Multi (Default)	*/
-#define	DRQ_URGENT	0x0300	/* 		Channels Request Multi Urgent		*/
-#define	RBC			0x1000	/* Reload BCNT With IBCNT					*/
-#define	PS			0x2000	/* HDMA Pin Status							*/
-#define	OI			0x4000	/* Overflow Interrupt Generated				*/
-#define	BDI			0x8000	/* Block Done Interrupt Generated			*/
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf533/boards/ip0x.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf533/boards/ip0x.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf533/boards/ip0x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf533/boards/ip0x.c	2011-05-19 00:06:34.000000000 -0400
@@ -289,8 +289,6 @@
 
 static int __init ip0x_init(void)
 {
-	int i;
-
 	printk(KERN_INFO "%s(): registering device resources\n", __func__);
 	platform_add_devices(ip0x_devices, ARRAY_SIZE(ip0x_devices));
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/cm_bf537e.c	2011-05-19 00:06:34.000000000 -0400
@@ -775,7 +775,7 @@
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/cm_bf537u.c	2011-05-19 00:06:34.000000000 -0400
@@ -740,7 +740,7 @@
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/dnp5370.c	2011-05-19 00:06:34.000000000 -0400
@@ -128,30 +128,11 @@
 
 #if defined(CONFIG_MMC_SPI) || defined(CONFIG_MMC_SPI_MODULE)
 
-#define MMC_SPI_CARD_DETECT_INT IRQ_PF5
-
-static int bfin_mmc_spi_init(struct device *dev,
-	irqreturn_t (*detect_int)(int, void *), void *data)
-{
-	return request_irq(MMC_SPI_CARD_DETECT_INT, detect_int,
-		IRQF_TRIGGER_FALLING, "mmc-spi-detect", data);
-}
-
-static void bfin_mmc_spi_exit(struct device *dev, void *data)
-{
-	free_irq(MMC_SPI_CARD_DETECT_INT, data);
-}
-
 static struct bfin5xx_spi_chip mmc_spi_chip_info = {
 	.enable_dma    = 0,	 /* use no dma transfer with this chip*/
 	.bits_per_word = 8,
 };
 
-static struct mmc_spi_platform_data bfin_mmc_spi_pdata = {
-	.init = bfin_mmc_spi_init,
-	.exit = bfin_mmc_spi_exit,
-	.detect_delay = 100, /* msecs */
-};
 #endif
 
 #if defined(CONFIG_MTD_DATAFLASH) || defined(CONFIG_MTD_DATAFLASH_MODULE)
@@ -192,7 +173,6 @@
 		.max_speed_hz    = 20000000,
 		.bus_num	 = 0,
 		.chip_select     = 1,
-		.platform_data   = &bfin_mmc_spi_pdata,
 		.controller_data = &mmc_spi_chip_info,
 		.mode	         = SPI_MODE_3,
 	},
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/stamp.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/stamp.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/stamp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/stamp.c	2011-05-19 00:06:34.000000000 -0400
@@ -2530,7 +2530,7 @@
 static struct pata_platform_info bfin_pata_platform_data = {
 	.ioport_shift = 0,
 };
-/* CompactFlash Storage Card Memory Mapped Adressing
+/* CompactFlash Storage Card Memory Mapped Addressing
  * /REG = A11 = 1
  */
 static struct resource bfin_pata_resources[] = {
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/boards/tcm_bf537.c	2011-05-19 00:06:34.000000000 -0400
@@ -742,7 +742,7 @@
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/include/mach/defBF534.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/include/mach/defBF534.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf537/include/mach/defBF534.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf537/include/mach/defBF534.h	2011-05-19 00:06:34.000000000 -0400
@@ -1520,24 +1520,6 @@
 #define	PGTE_PPI		0x0000	/*              Enable PPI D15:13                       */
 #define	PGTE_SPORT		0x0800	/*              Enable DT1PRI/TFS1/TSCLK1       */
 
-/*  ******************  HANDSHAKE DMA (HDMA) MASKS  *********************/
-/* HDMAx_CTL Masks														*/
-#define	HMDMAEN		0x0001	/* Enable Handshake DMA 0/1                                     */
-#define	REP			0x0002	/* HDMA Request Polarity                                        */
-#define	UTE			0x0004	/* Urgency Threshold Enable                                     */
-#define	OIE			0x0010	/* Overflow Interrupt Enable                            */
-#define	BDIE		0x0020	/* Block Done Interrupt Enable                          */
-#define	MBDI		0x0040	/* Mask Block Done IRQ If Pending ECNT          */
-#define	DRQ			0x0300	/* HDMA Request Type                                            */
-#define	DRQ_NONE	0x0000	/*              No Request                                                      */
-#define	DRQ_SINGLE	0x0100	/*              Channels Request Single                         */
-#define	DRQ_MULTI	0x0200	/*              Channels Request Multi (Default)        */
-#define	DRQ_URGENT	0x0300	/*              Channels Request Multi Urgent           */
-#define	RBC			0x1000	/* Reload BCNT With IBCNT                                       */
-#define	PS			0x2000	/* HDMA Pin Status                                                      */
-#define	OI			0x4000	/* Overflow Interrupt Generated                         */
-#define	BDI			0x8000	/* Block Done Interrupt Generated                       */
-
 /* entry addresses of the user-callable Boot ROM functions */
 
 #define _BOOTROM_RESET 0xEF000000 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/boards/ezkit.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/boards/ezkit.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/boards/ezkit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/boards/ezkit.c	2011-05-19 00:06:34.000000000 -0400
@@ -778,11 +778,12 @@
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-static unsigned short bfin_can_peripherals[] = {
+
+static unsigned short bfin_can0_peripherals[] = {
 	P_CAN0_RX, P_CAN0_TX, 0
 };
 
-static struct resource bfin_can_resources[] = {
+static struct resource bfin_can0_resources[] = {
 	{
 		.start = 0xFFC02A00,
 		.end = 0xFFC02FFF,
@@ -805,14 +806,53 @@
 	},
 };
 
-static struct platform_device bfin_can_device = {
+static struct platform_device bfin_can0_device = {
 	.name = "bfin_can",
-	.num_resources = ARRAY_SIZE(bfin_can_resources),
-	.resource = bfin_can_resources,
+	.id = 0,
+	.num_resources = ARRAY_SIZE(bfin_can0_resources),
+	.resource = bfin_can0_resources,
 	.dev = {
-		.platform_data = &bfin_can_peripherals, /* Passed to driver */
+		.platform_data = &bfin_can0_peripherals, /* Passed to driver */
 	},
 };
+
+static unsigned short bfin_can1_peripherals[] = {
+	P_CAN1_RX, P_CAN1_TX, 0
+};
+
+static struct resource bfin_can1_resources[] = {
+	{
+		.start = 0xFFC03200,
+		.end = 0xFFC037FF,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = IRQ_CAN1_RX,
+		.end = IRQ_CAN1_RX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN1_TX,
+		.end = IRQ_CAN1_TX,
+		.flags = IORESOURCE_IRQ,
+	},
+	{
+		.start = IRQ_CAN1_ERROR,
+		.end = IRQ_CAN1_ERROR,
+		.flags = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device bfin_can1_device = {
+	.name = "bfin_can",
+	.id = 1,
+	.num_resources = ARRAY_SIZE(bfin_can1_resources),
+	.resource = bfin_can1_resources,
+	.dev = {
+		.platform_data = &bfin_can1_peripherals, /* Passed to driver */
+	},
+};
+
 #endif
 
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
@@ -1366,7 +1406,8 @@
 #endif
 
 #if defined(CONFIG_CAN_BFIN) || defined(CONFIG_CAN_BFIN_MODULE)
-	&bfin_can_device,
+	&bfin_can0_device,
+	&bfin_can1_device,
 #endif
 
 #if defined(CONFIG_PATA_BF54X) || defined(CONFIG_PATA_BF54X_MODULE)
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/anomaly.h	2011-05-19 00:06:34.000000000 -0400
@@ -81,7 +81,11 @@
 /* PLL Status Register Is Inaccurate */
 #define ANOMALY_05000351 (__SILICON_REVISION__ < 1)
 /* bfrom_SysControl() Firmware Function Performs Improper System Reset */
-#define ANOMALY_05000353 (__SILICON_REVISION__ < 2)
+/*
+ * Note: anomaly sheet says this is fixed with bf54x-0.2+, but testing
+ *       shows that the fix itself does not cover all cases.
+ */
+#define ANOMALY_05000353 (1)
 /* Regulator Programming Blocked when Hibernate Wakeup Source Remains Active */
 #define ANOMALY_05000355 (__SILICON_REVISION__ < 1)
 /* System Stalled During A Core Access To AMC While A Core Access To NFC FIFO Is Required */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/defBF544.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/defBF544.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/defBF544.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/defBF544.h	2011-05-19 00:06:34.000000000 -0400
@@ -657,22 +657,4 @@
 
 /* Bit masks for EPPI0 are obtained from common base header for EPPIx (EPPI1 and EPPI2) */
 
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
 #endif /* _DEF_BF544_H */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/defBF547.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/defBF547.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/defBF547.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/defBF547.h	2011-05-19 00:06:34.000000000 -0400
@@ -1063,23 +1063,4 @@
 
 #define             DMA_COUNT_LOW  0xffff     /* Lower 16-bits of byte count of DMA transfer for DMA master channel */
 
-/* Bit masks for HMDMAx_CONTROL */
-
-#define                   HMDMAEN  0x1        /* Handshake MDMA Enable */
-#define                       REP  0x2        /* Handshake MDMA Request Polarity */
-#define                       UTE  0x8        /* Urgency Threshold Enable */
-#define                       OIE  0x10       /* Overflow Interrupt Enable */
-#define                      BDIE  0x20       /* Block Done Interrupt Enable */
-#define                      MBDI  0x40       /* Mask Block Done Interrupt */
-#define                       DRQ  0x300      /* Handshake MDMA Request Type */
-#define                       RBC  0x1000     /* Force Reload of BCOUNT */
-#define                        PS  0x2000     /* Pin Status */
-#define                        OI  0x4000     /* Overflow Interrupt Generated */
-#define                       BDI  0x8000     /* Block Done Interrupt Generated */
-
-/* ******************************************* */
-/*     MULTI BIT MACRO ENUMERATIONS            */
-/* ******************************************* */
-
-
 #endif /* _DEF_BF547_H */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/dma.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,17 +27,37 @@
 #define CH_PIXC_OVERLAY		16
 #define CH_PIXC_OUTPUT		17
 #define CH_SPORT2_RX		18
-#define CH_UART2_RX		18
 #define CH_SPORT2_TX		19
-#define CH_UART2_TX		19
 #define CH_SPORT3_RX		20
-#define CH_UART3_RX		20
 #define CH_SPORT3_TX		21
-#define CH_UART3_TX		21
 #define CH_SDH			22
 #define CH_NFC			22
 #define CH_SPI2			23
 
+#if defined(CONFIG_UART2_DMA_RX_ON_DMA13)
+#define CH_UART2_RX		13
+#define IRQ_UART2_RX		BFIN_IRQ(37)	/* UART2 RX USE EPP1 (DMA13) Interrupt */
+#define CH_UART2_TX		14
+#define IRQ_UART2_TX		BFIN_IRQ(38)	/* UART2 RX USE EPP1 (DMA14) Interrupt */
+#else						/* Default USE SPORT2's DMA Channel */
+#define CH_UART2_RX		18
+#define IRQ_UART2_RX		BFIN_IRQ(33)	/* UART2 RX (DMA18) Interrupt */
+#define CH_UART2_TX		19
+#define IRQ_UART2_TX		BFIN_IRQ(34)	/* UART2 TX (DMA19) Interrupt */
+#endif
+
+#if defined(CONFIG_UART3_DMA_RX_ON_DMA15)
+#define CH_UART3_RX		15
+#define IRQ_UART3_RX		BFIN_IRQ(64)	/* UART3 RX USE PIXC IN0 (DMA15) Interrupt */
+#define CH_UART3_TX		16
+#define IRQ_UART3_TX		BFIN_IRQ(65)	/* UART3 TX USE PIXC IN1 (DMA16) Interrupt */
+#else						/* Default USE SPORT3's DMA Channel */
+#define CH_UART3_RX		20
+#define IRQ_UART3_RX		BFIN_IRQ(35)	/* UART3 RX (DMA20) Interrupt */
+#define CH_UART3_TX		21
+#define IRQ_UART3_TX		BFIN_IRQ(36)	/* UART3 TX (DMA21) Interrupt */
+#endif
+
 #define CH_MEM_STREAM0_DEST	24
 #define CH_MEM_STREAM0_SRC	25
 #define CH_MEM_STREAM1_DEST	26
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/irq.h linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/irq.h
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/include/mach/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/include/mach/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -74,13 +74,9 @@
 #define IRQ_UART2_ERROR		BFIN_IRQ(31)	/* UART2 Status (Error) Interrupt */
 #define IRQ_CAN0_ERROR		BFIN_IRQ(32)	/* CAN0 Status (Error) Interrupt */
 #define IRQ_SPORT2_RX		BFIN_IRQ(33)	/* SPORT2 RX (DMA18) Interrupt */
-#define IRQ_UART2_RX		BFIN_IRQ(33)	/* UART2 RX (DMA18) Interrupt */
 #define IRQ_SPORT2_TX		BFIN_IRQ(34)	/* SPORT2 TX (DMA19) Interrupt */
-#define IRQ_UART2_TX		BFIN_IRQ(34)	/* UART2 TX (DMA19) Interrupt */
 #define IRQ_SPORT3_RX		BFIN_IRQ(35)	/* SPORT3 RX (DMA20) Interrupt */
-#define IRQ_UART3_RX		BFIN_IRQ(35)	/* UART3 RX (DMA20) Interrupt */
 #define IRQ_SPORT3_TX		BFIN_IRQ(36)	/* SPORT3 TX (DMA21) Interrupt */
-#define IRQ_UART3_TX		BFIN_IRQ(36)	/* UART3 TX (DMA21) Interrupt */
 #define IRQ_EPPI1		BFIN_IRQ(37)	/* EPP1 (DMA13) Interrupt */
 #define IRQ_EPPI2		BFIN_IRQ(38)	/* EPP2 (DMA14) Interrupt */
 #define IRQ_SPI1		BFIN_IRQ(39)	/* SPI1 (DMA5) Interrupt */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/Kconfig linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/Kconfig
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf548/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf548/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,65 @@
 	  async address or GPIO port F and G. Select y to route it
 	  to GPIO.
 
+choice
+	prompt "UART2 DMA channel selection"
+	depends on SERIAL_BFIN_UART2
+	default UART2_DMA_RX_ON_DMA18
+	help
+		UART2 DMA channel selection
+		RX -> DMA18
+		TX -> DMA19
+		or
+		RX -> DMA13
+		TX -> DMA14
+
+config UART2_DMA_RX_ON_DMA18
+	bool "UART2 DMA RX -> DMA18 TX -> DMA19"
+	help
+		UART2 DMA channel assignment
+		RX -> DMA18
+		TX -> DMA19
+		use SPORT2 default DMA channel
+
+config UART2_DMA_RX_ON_DMA13
+	bool "UART2 DMA RX -> DMA13 TX -> DMA14"
+	help
+		UART2 DMA channel assignment
+		RX -> DMA13
+		TX -> DMA14
+		use EPPI1 EPPI2 default DMA channel
+endchoice
+
+choice
+	prompt "UART3 DMA channel selection"
+	depends on SERIAL_BFIN_UART3
+	default UART3_DMA_RX_ON_DMA20
+	help
+		UART3 DMA channel selection
+		RX -> DMA20
+		TX -> DMA21
+		or
+		RX -> DMA15
+		TX -> DMA16
+
+config UART3_DMA_RX_ON_DMA20
+	bool "UART3 DMA RX -> DMA20 TX -> DMA21"
+	help
+		UART3 DMA channel assignment
+		RX -> DMA20
+		TX -> DMA21
+		use SPORT3 default DMA channel
+
+config UART3_DMA_RX_ON_DMA15
+	bool "UART3 DMA RX -> DMA15 TX -> DMA16"
+	help
+		UART3 DMA channel assignment
+		RX -> DMA15
+		TX -> DMA16
+		use PIXC default DMA channel
+
+endchoice
+
 comment "Interrupt Priority Assignment"
 menu "Priority"
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/boards/cm_bf561.c	2011-05-19 00:06:34.000000000 -0400
@@ -541,7 +541,7 @@
 #endif
 
 #if defined(CONFIG_PATA_PLATFORM) || defined(CONFIG_PATA_PLATFORM_MODULE)
-	irq_desc[PATA_INT].status |= IRQ_NOAUTOEN;
+	irq_set_status_flags(PATA_INT, IRQ_NOAUTOEN);
 #endif
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/hotplug.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/hotplug.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/hotplug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/hotplug.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,30 +5,36 @@
  * Licensed under the GPL-2 or later.
  */
 
+#include <linux/smp.h>
 #include <asm/blackfin.h>
-#include <asm/irq.h>
-#include <asm/smp.h>
-
-#define SIC_SYSIRQ(irq)	(irq - (IRQ_CORETMR + 1))
+#include <asm/cacheflush.h>
+#include <mach/pll.h>
 
 int hotplug_coreb;
 
 void platform_cpu_die(void)
 {
-	unsigned long iwr[2] = {0, 0};
-	unsigned long bank = SIC_SYSIRQ(IRQ_SUPPLE_0) / 32;
-	unsigned long bit = 1 << (SIC_SYSIRQ(IRQ_SUPPLE_0) % 32);
+	unsigned long iwr;
 
 	hotplug_coreb = 1;
 
-	iwr[bank] = bit;
+	/*
+	 * When CoreB wakes up, the code in _coreb_trampoline_start cannot
+	 * turn off the data cache. This causes the CoreB failed to boot.
+	 * As a workaround, we invalidate all the data cache before sleep.
+	 */
+	blackfin_invalidate_entire_dcache();
 
 	/* disable core timer */
 	bfin_write_TCNTL(0);
 
-	/* clear ipi interrupt IRQ_SUPPLE_0 */
+	/* clear ipi interrupt IRQ_SUPPLE_0 of CoreB */
 	bfin_write_SICB_SYSCR(bfin_read_SICB_SYSCR() | (1 << (10 + 1)));
 	SSYNC();
 
-	coreb_sleep(iwr[0], iwr[1], 0);
+	/* set CoreB wakeup by ipi0, iwr will be discarded */
+	bfin_iwr_set_sup0(&iwr, &iwr, &iwr);
+	SSYNC();
+
+	coreb_die();
 }
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/secondary.S linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/secondary.S
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/secondary.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/secondary.S	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,11 @@
 #include <asm/asm-offsets.h>
 #include <asm/trace.h>
 
-__INIT
+/*
+ * This code must come first as CoreB is hardcoded (in hardware)
+ * to start at the beginning of its L1 instruction memory.
+ */
+.section .l1.text.head
 
 /* Lay the initial stack into the L1 scratch area of Core B */
 #define INITIAL_STACK	(COREB_L1_SCRATCH_START + L1_SCRATCH_LENGTH - 12)
@@ -160,43 +164,34 @@
 .LWAIT_HERE:
 	jump .LWAIT_HERE;
 ENDPROC(_coreb_trampoline_start)
-ENTRY(_coreb_trampoline_end)
 
+#ifdef CONFIG_HOTPLUG_CPU
 .section ".text"
-ENTRY(_set_sicb_iwr)
-	P0.H = hi(SICB_IWR0);
-	P0.L = lo(SICB_IWR0);
-	P1.H = hi(SICB_IWR1);
-	P1.L = lo(SICB_IWR1);
-	[P0] = R0;
-	[P1] = R1;
-	SSYNC;
-	RTS;
-ENDPROC(_set_sicb_iwr)
-
-ENTRY(_coreb_sleep)
+ENTRY(_coreb_die)
 	sp.l = lo(INITIAL_STACK);
 	sp.h = hi(INITIAL_STACK);
 	fp = sp;
 	usp = sp;
 
-	call _set_sicb_iwr;
-
 	CLI R2;
 	SSYNC;
 	IDLE;
 	STI R2;
 
 	R0 = IWR_DISABLE_ALL;
-	R1 = IWR_DISABLE_ALL;
-	call _set_sicb_iwr;
+	P0.H = hi(SYSMMR_BASE);
+	P0.L = lo(SYSMMR_BASE);
+	[P0 + (SICB_IWR0 - SYSMMR_BASE)] = R0;
+	[P0 + (SICB_IWR1 - SYSMMR_BASE)] = R0;
+	SSYNC;
 
 	p0.h = hi(COREB_L1_CODE_START);
 	p0.l = lo(COREB_L1_CODE_START);
 	jump (p0);
-ENDPROC(_coreb_sleep)
+ENDPROC(_coreb_die)
+#endif
 
-__CPUINIT
+__INIT
 ENTRY(_coreb_start)
 	[--sp] = reti;
 
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/smp.c linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/smp.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-bf561/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-bf561/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,18 +30,11 @@
 
 void __init platform_prepare_cpus(unsigned int max_cpus)
 {
-	int len;
-
-	len = &coreb_trampoline_end - &coreb_trampoline_start + 1;
-	BUG_ON(len > L1_CODE_LENGTH);
-
-	dma_memcpy((void *)COREB_L1_CODE_START, &coreb_trampoline_start, len);
+	bfin_relocate_coreb_l1_mem();
 
 	/* Both cores ought to be present on a bf561! */
 	cpu_set(0, cpu_present_map); /* CoreA */
 	cpu_set(1, cpu_present_map); /* CoreB */
-
-	printk(KERN_INFO "CoreB bootstrap code to SRAM %p via DMA.\n", (void *)COREB_L1_CODE_START);
 }
 
 int __init setup_profiling_timer(unsigned int multiplier) /* not supported */
@@ -161,9 +154,13 @@
 void __cpuinit bfin_local_timer_setup(void)
 {
 #if defined(CONFIG_TICKSOURCE_CORETMR)
+	struct irq_data *data = irq_get_irq_data(IRQ_CORETMR);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+
 	bfin_coretmr_init();
 	bfin_coretmr_clockevent_init();
-	get_irq_chip(IRQ_CORETMR)->unmask(IRQ_CORETMR);
+
+	chip->irq_unmask(data);
 #else
 	/* Power down the core timer, just to play safe. */
 	bfin_write_TCNTL(0);
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/arch_checks.c linux-libre-2.6.39-gnu/arch/blackfin/mach-common/arch_checks.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/arch_checks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/arch_checks.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,6 @@
 # error "Anomaly 05000220 does not allow you to use Write Back cache with L2 or External Memory"
 #endif
 
-#if ANOMALY_05000491 && !defined(CONFIG_CACHE_FLUSH_L1)
+#if ANOMALY_05000491 && !defined(CONFIG_ICACHE_FLUSH_L1)
 # error You need IFLUSH in L1 inst while Anomaly 05000491 applies
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/cache.S linux-libre-2.6.39-gnu/arch/blackfin/mach-common/cache.S
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/cache.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/cache.S	2011-05-19 00:06:34.000000000 -0400
@@ -11,12 +11,6 @@
 #include <asm/cache.h>
 #include <asm/page.h>
 
-#ifdef CONFIG_CACHE_FLUSH_L1
-.section .l1.text
-#else
-.text
-#endif
-
 /* 05000443 - IFLUSH cannot be last instruction in hardware loop */
 #if ANOMALY_05000443
 # define BROK_FLUSH_INST "IFLUSH"
@@ -68,11 +62,43 @@
 	RTS;
 .endm
 
+#ifdef CONFIG_ICACHE_FLUSH_L1
+.section .l1.text
+#else
+.text
+#endif
+
 /* Invalidate all instruction cache lines assocoiated with this memory area */
+#ifdef CONFIG_SMP
+# define _blackfin_icache_flush_range _blackfin_icache_flush_range_l1
+#endif
 ENTRY(_blackfin_icache_flush_range)
 	do_flush IFLUSH
 ENDPROC(_blackfin_icache_flush_range)
 
+#ifdef CONFIG_SMP
+.text
+# undef _blackfin_icache_flush_range
+ENTRY(_blackfin_icache_flush_range)
+	p0.L = LO(DSPID);
+	p0.H = HI(DSPID);
+	r3 = [p0];
+	r3 = r3.b (z);
+	p2 = r3;
+	p0.L = _blackfin_iflush_l1_entry;
+	p0.H = _blackfin_iflush_l1_entry;
+	p0 = p0 + (p2 << 2);
+	p1 = [p0];
+	jump (p1);
+ENDPROC(_blackfin_icache_flush_range)
+#endif
+
+#ifdef CONFIG_DCACHE_FLUSH_L1
+.section .l1.text
+#else
+.text
+#endif
+
 /* 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
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/cpufreq.c linux-libre-2.6.39-gnu/arch/blackfin/mach-common/cpufreq.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Blackfin core clock scaling
  *
- * Copyright 2008-2009 Analog Devices Inc.
+ * Copyright 2008-2011 Analog Devices Inc.
  *
  * Licensed under the GPL-2 or later.
  */
@@ -16,10 +16,8 @@
 #include <asm/time.h>
 #include <asm/dpmc.h>
 
-#define CPUFREQ_CPU 0
-
 /* this is the table of CCLK frequencies, in Hz */
-/* .index is the entry in the auxillary dpm_state_table[] */
+/* .index is the entry in the auxiliary dpm_state_table[] */
 static struct cpufreq_frequency_table bfin_freq_table[] = {
 	{
 		.frequency = CPUFREQ_TABLE_END,
@@ -46,7 +44,7 @@
 
 #if defined(CONFIG_CYCLES_CLOCKSOURCE)
 /*
- * normalized to maximum frequncy offset for CYCLES,
+ * normalized to maximum frequency offset for CYCLES,
  * used in time-ts cycles clock source, but could be used
  * somewhere also.
  */
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/dpmc.c linux-libre-2.6.39-gnu/arch/blackfin/mach-common/dpmc.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/dpmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/dpmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,17 +61,63 @@
 }
 
 #ifdef CONFIG_CPU_FREQ
+# ifdef CONFIG_SMP
+static void bfin_idle_this_cpu(void *info)
+{
+	unsigned long flags = 0;
+	unsigned long iwr0, iwr1, iwr2;
+	unsigned int cpu = smp_processor_id();
+
+	local_irq_save_hw(flags);
+	bfin_iwr_set_sup0(&iwr0, &iwr1, &iwr2);
+
+	platform_clear_ipi(cpu, IRQ_SUPPLE_0);
+	SSYNC();
+	asm("IDLE;");
+	bfin_iwr_restore(iwr0, iwr1, iwr2);
+
+	local_irq_restore_hw(flags);
+}
+
+static void bfin_idle_cpu(void)
+{
+	smp_call_function(bfin_idle_this_cpu, NULL, 0);
+}
+
+static void bfin_wakeup_cpu(void)
+{
+	unsigned int cpu;
+	unsigned int this_cpu = smp_processor_id();
+	cpumask_t mask = cpu_online_map;
+
+	cpu_clear(this_cpu, mask);
+	for_each_cpu_mask(cpu, mask)
+		platform_send_ipi_cpu(cpu, IRQ_SUPPLE_0);
+}
+
+# else
+static void bfin_idle_cpu(void) {}
+static void bfin_wakeup_cpu(void) {}
+# endif
+
 static int
 vreg_cpufreq_notifier(struct notifier_block *nb, unsigned long val, void *data)
 {
 	struct cpufreq_freqs *freq = data;
 
+	if (freq->cpu != CPUFREQ_CPU)
+		return 0;
+
 	if (val == CPUFREQ_PRECHANGE && freq->old < freq->new) {
+		bfin_idle_cpu();
 		bfin_set_vlev(bfin_get_vlev(freq->new));
 		udelay(pdata->vr_settling_time); /* Wait until Volatge settled */
-
-	} else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new)
+		bfin_wakeup_cpu();
+	} else if (val == CPUFREQ_POSTCHANGE && freq->old > freq->new) {
+		bfin_idle_cpu();
 		bfin_set_vlev(bfin_get_vlev(freq->new));
+		bfin_wakeup_cpu();
+	}
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/entry.S linux-libre-2.6.39-gnu/arch/blackfin/mach-common/entry.S
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -268,7 +268,7 @@
 	/* To get here, we just tried and failed to change a CPLB
 	 * so, handle things in trap_c (C code), by lowering to
 	 * IRQ5, just like we normally do. Since this is not a
-	 * "normal" return path, we have a do alot of stuff to
+	 * "normal" return path, we have a do a lot of stuff to
 	 * the stack to get ready so, we can fall through - we
 	 * need to make a CPLB exception look like a normal exception
 	 */
@@ -817,7 +817,7 @@
 	rets = [sp++];
 
 	/*
-	 * When we come out of resume, r0 carries "old" task, becuase we are
+	 * When we come out of resume, r0 carries "old" task, because we are
 	 * in "new" task.
 	 */
 	rts;
@@ -952,8 +952,17 @@
 #ifdef CONFIG_IPIPE
 
 _resume_kernel_from_int:
+	r1 = LO(~0x8000) (Z);
+	r1 = r0 & r1;
+	r0 = 1;
+	r0 = r1 - r0;
+	r2 = r1 & r0;
+	cc = r2 == 0;
+	/* Sync the root stage only from the outer interrupt level. */
+	if !cc jump .Lnosync;
 	r0.l = ___ipipe_sync_root;
 	r0.h = ___ipipe_sync_root;
+	[--sp] = reti;
 	[--sp] = rets;
 	[--sp] = ( r7:4, p5:3 );
 	SP += -12;
@@ -961,6 +970,8 @@
 	SP += 12;
 	( r7:4, p5:3 ) = [sp++];
 	rets = [sp++];
+	reti = [sp++];
+.Lnosync:
 	rts
 #elif defined(CONFIG_PREEMPT)
 
@@ -1738,6 +1749,10 @@
 	.long _sys_fanotify_mark
 	.long _sys_prlimit64
 	.long _sys_cacheflush
+	.long _sys_name_to_handle_at	/* 375 */
+	.long _sys_open_by_handle_at
+	.long _sys_clock_adjtime
+	.long _sys_syncfs
 
 	.rept NR_syscalls-(.-_sys_call_table)/4
 	.long _sys_ni_syscall
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/head.S linux-libre-2.6.39-gnu/arch/blackfin/mach-common/head.S
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 ENTRY(__start)
 	/* R0: argument of command line string, passed from uboot, save it */
 	R7 = R0;
+
 	/* Enable Cycle Counter and Nesting Of Interrupts */
 #ifdef CONFIG_BFIN_SCRATCH_REG_CYCLES
 	R0 = SYSCFG_SNEN;
@@ -38,76 +39,49 @@
 	R0 = SYSCFG_SNEN | SYSCFG_CCEN;
 #endif
 	SYSCFG = R0;
-	R0 = 0;
-
-	/* Clear Out All the data and pointer Registers */
-	R1 = R0;
-	R2 = R0;
-	R3 = R0;
-	R4 = R0;
-	R5 = R0;
-	R6 = R0;
-
-	P0 = R0;
-	P1 = R0;
-	P2 = R0;
-	P3 = R0;
-	P4 = R0;
-	P5 = R0;
 
-	LC0 = r0;
-	LC1 = r0;
-	L0 = r0;
-	L1 = r0;
-	L2 = r0;
-	L3 = r0;
+	/* Optimization register tricks: keep a base value in the
+	 * reserved P registers so we use the load/store with an
+	 * offset syntax.  R0 = [P5 + <constant>];
+	 *   P5 - core MMR base
+	 *   R6 - 0
+	 */
+	r6 = 0;
+	p5.l = 0;
+	p5.h = hi(COREMMR_BASE);
 
-	/* Clear Out All the DAG Registers */
-	B0 = r0;
-	B1 = r0;
-	B2 = r0;
-	B3 = r0;
+	/* Zero out registers required by Blackfin ABI */
 
-	I0 = r0;
-	I1 = r0;
-	I2 = r0;
-	I3 = r0;
+	/* Disable circular buffers */
+	L0 = r6;
+	L1 = r6;
+	L2 = r6;
+	L3 = r6;
 
-	M0 = r0;
-	M1 = r0;
-	M2 = r0;
-	M3 = r0;
+	/* Disable hardware loops in case we were started by 'go' */
+	LC0 = r6;
+	LC1 = r6;
 
 	/*
 	 * Clear ITEST_COMMAND and DTEST_COMMAND registers,
 	 * Leaving these as non-zero can confuse the emulator
 	 */
-	p0.L = LO(DTEST_COMMAND);
-	p0.H = HI(DTEST_COMMAND);
-	[p0] = R0;
-	[p0 + (ITEST_COMMAND - DTEST_COMMAND)] = R0;
+	[p5 + (DTEST_COMMAND - COREMMR_BASE)] = r6;
+	[p5 + (ITEST_COMMAND - COREMMR_BASE)] = r6;
 	CSYNC;
 
 	trace_buffer_init(p0,r0);
-	P0 = R1;
-	R0 = R1;
 
 	/* Turn off the icache */
-	p0.l = LO(IMEM_CONTROL);
-	p0.h = HI(IMEM_CONTROL);
-	R1 = [p0];
-	R0 = ~ENICPLB;
-	R0 = R0 & R1;
-	[p0] = R0;
+	r1 = [p5 + (IMEM_CONTROL - COREMMR_BASE)];
+	BITCLR (r1, ENICPLB_P);
+	[p5 + (IMEM_CONTROL - COREMMR_BASE)] = r1;
 	SSYNC;
 
 	/* Turn off the dcache */
-	p0.l = LO(DMEM_CONTROL);
-	p0.h = HI(DMEM_CONTROL);
-	R1 = [p0];
-	R0 = ~ENDCPLB;
-	R0 = R0 & R1;
-	[p0] = R0;
+	r1 = [p5 + (DMEM_CONTROL - COREMMR_BASE)];
+	BITCLR (r1, ENDCPLB_P);
+	[p5 + (DMEM_CONTROL - COREMMR_BASE)] = r1;
 	SSYNC;
 
 	/* in case of double faults, save a few things */
@@ -122,25 +96,25 @@
 	 * below
 	 */
 	GET_PDA(p0, r0);
-	r6 = [p0 + PDA_DF_RETX];
+	r5 = [p0 + PDA_DF_RETX];
 	p1.l = _init_saved_retx;
 	p1.h = _init_saved_retx;
-	[p1] = r6;
+	[p1] = r5;
 
-	r6 = [p0 + PDA_DF_DCPLB];
+	r5 = [p0 + PDA_DF_DCPLB];
 	p1.l = _init_saved_dcplb_fault_addr;
 	p1.h = _init_saved_dcplb_fault_addr;
-	[p1] = r6;
+	[p1] = r5;
 
-	r6 = [p0 + PDA_DF_ICPLB];
+	r5 = [p0 + PDA_DF_ICPLB];
 	p1.l = _init_saved_icplb_fault_addr;
 	p1.h = _init_saved_icplb_fault_addr;
-	[p1] = r6;
+	[p1] = r5;
 
-	r6 = [p0 + PDA_DF_SEQSTAT];
+	r5 = [p0 + PDA_DF_SEQSTAT];
 	p1.l = _init_saved_seqstat;
 	p1.h = _init_saved_seqstat;
-	[p1] = r6;
+	[p1] = r5;
 #endif
 
 	/* Initialize stack pointer */
@@ -155,7 +129,7 @@
 	sti r0;
 #endif
 
-	r0 = 0 (x);
+	r0 = r6;
 	/* Zero out all of the fun bss regions */
 #if L1_DATA_A_LENGTH > 0
 	r1.l = __sbss_l1;
@@ -200,7 +174,7 @@
 	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 */
+	sp = usp;	/* usp hasn't been touched, so restore from there */
 #endif
 
 	/* This section keeps the processor in supervisor mode
@@ -210,11 +184,9 @@
 
 	/* EVT15 = _real_start */
 
-	p0.l = lo(EVT15);
-	p0.h = hi(EVT15);
 	p1.l = _real_start;
 	p1.h = _real_start;
-	[p0] = p1;
+	[p5 + (EVT15 - COREMMR_BASE)] = p1;
 	csync;
 
 #ifdef CONFIG_EARLY_PRINTK
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/interrupt.S linux-libre-2.6.39-gnu/arch/blackfin/mach-common/interrupt.S
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/interrupt.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/interrupt.S	2011-05-19 00:06:34.000000000 -0400
@@ -274,16 +274,16 @@
  * level to EVT14 to prepare the caller for a normal interrupt
  * return through RTI.
  *
- * We currently use this facility in two occasions:
+ * We currently use this feature in two occasions:
  *
- * - to branch to __ipipe_irq_tail_hook as requested by a high
+ * - before branching to __ipipe_irq_tail_hook as requested by a high
  *   priority domain after the pipeline delivered an interrupt,
  *   e.g. such as Xenomai, in order to start its rescheduling
  *   procedure, since we may not switch tasks when IRQ levels are
  *   nested on the Blackfin, so we have to fake an interrupt return
  *   so that we may reschedule immediately.
  *
- * - to branch to sync_root_irqs, in order to play any interrupt
+ * - before branching to __ipipe_sync_root(), in order to play any interrupt
  *   pending for the root domain (i.e. the Linux kernel). This lowers
  *   the core priority level enough so that Linux IRQ handlers may
  *   never delay interrupts handled by high priority domains; we defer
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/ints-priority.c linux-libre-2.6.39-gnu/arch/blackfin/mach-common/ints-priority.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/ints-priority.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/ints-priority.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/kernel_stat.h>
 #include <linux/seq_file.h>
 #include <linux/irq.h>
+#include <linux/sched.h>
 #ifdef CONFIG_IPIPE
 #include <linux/ipipe.h>
 #endif
@@ -124,21 +125,21 @@
  * This is for core internal IRQs
  */
 
-static void bfin_ack_noop(unsigned int irq)
+static void bfin_ack_noop(struct irq_data *d)
 {
 	/* Dummy function.  */
 }
 
-static void bfin_core_mask_irq(unsigned int irq)
+static void bfin_core_mask_irq(struct irq_data *d)
 {
-	bfin_irq_flags &= ~(1 << irq);
+	bfin_irq_flags &= ~(1 << d->irq);
 	if (!hard_irqs_disabled())
 		hard_local_irq_enable();
 }
 
-static void bfin_core_unmask_irq(unsigned int irq)
+static void bfin_core_unmask_irq(struct irq_data *d)
 {
-	bfin_irq_flags |= 1 << irq;
+	bfin_irq_flags |= 1 << d->irq;
 	/*
 	 * If interrupts are enabled, IMASK must contain the same value
 	 * as bfin_irq_flags.  Make sure that invariant holds.  If interrupts
@@ -176,6 +177,11 @@
 	hard_local_irq_restore(flags);
 }
 
+static void bfin_internal_mask_irq_chip(struct irq_data *d)
+{
+	bfin_internal_mask_irq(d->irq);
+}
+
 #ifdef CONFIG_SMP
 static void bfin_internal_unmask_irq_affinity(unsigned int irq,
 		const struct cpumask *affinity)
@@ -211,19 +217,24 @@
 }
 
 #ifdef CONFIG_SMP
-static void bfin_internal_unmask_irq(unsigned int irq)
+static void bfin_internal_unmask_irq_chip(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	bfin_internal_unmask_irq_affinity(irq, desc->affinity);
+	bfin_internal_unmask_irq_affinity(d->irq, d->affinity);
 }
 
-static int bfin_internal_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bfin_internal_set_affinity(struct irq_data *d,
+				      const struct cpumask *mask, bool force)
 {
-	bfin_internal_mask_irq(irq);
-	bfin_internal_unmask_irq_affinity(irq, mask);
+	bfin_internal_mask_irq(d->irq);
+	bfin_internal_unmask_irq_affinity(d->irq, mask);
 
 	return 0;
 }
+#else
+static void bfin_internal_unmask_irq_chip(struct irq_data *d)
+{
+	bfin_internal_unmask_irq(d->irq);
+}
 #endif
 
 #ifdef CONFIG_PM
@@ -279,28 +290,33 @@
 
 	return 0;
 }
+
+static int bfin_internal_set_wake_chip(struct irq_data *d, unsigned int state)
+{
+	return bfin_internal_set_wake(d->irq, state);
+}
 #endif
 
 static struct irq_chip bfin_core_irqchip = {
 	.name = "CORE",
-	.ack = bfin_ack_noop,
-	.mask = bfin_core_mask_irq,
-	.unmask = bfin_core_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask = bfin_core_mask_irq,
+	.irq_unmask = bfin_core_unmask_irq,
 };
 
 static struct irq_chip bfin_internal_irqchip = {
 	.name = "INTN",
-	.ack = bfin_ack_noop,
-	.mask = bfin_internal_mask_irq,
-	.unmask = bfin_internal_unmask_irq,
-	.mask_ack = bfin_internal_mask_irq,
-	.disable = bfin_internal_mask_irq,
-	.enable = bfin_internal_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask = bfin_internal_mask_irq_chip,
+	.irq_unmask = bfin_internal_unmask_irq_chip,
+	.irq_mask_ack = bfin_internal_mask_irq_chip,
+	.irq_disable = bfin_internal_mask_irq_chip,
+	.irq_enable = bfin_internal_unmask_irq_chip,
 #ifdef CONFIG_SMP
-	.set_affinity = bfin_internal_set_affinity,
+	.irq_set_affinity = bfin_internal_set_affinity,
 #endif
 #ifdef CONFIG_PM
-	.set_wake = bfin_internal_set_wake,
+	.irq_set_wake = bfin_internal_set_wake_chip,
 #endif
 };
 
@@ -312,33 +328,32 @@
 	__ipipe_handle_irq(irq, &regs);
 	ipipe_trace_irq_exit(irq);
 #else /* !CONFIG_IPIPE */
-	struct irq_desc *desc = irq_desc + irq;
-	desc->handle_irq(irq, desc);
+	generic_handle_irq(irq);
 #endif  /* !CONFIG_IPIPE */
 }
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 static int error_int_mask;
 
-static void bfin_generic_error_mask_irq(unsigned int irq)
+static void bfin_generic_error_mask_irq(struct irq_data *d)
 {
-	error_int_mask &= ~(1L << (irq - IRQ_PPI_ERROR));
+	error_int_mask &= ~(1L << (d->irq - IRQ_PPI_ERROR));
 	if (!error_int_mask)
 		bfin_internal_mask_irq(IRQ_GENERIC_ERROR);
 }
 
-static void bfin_generic_error_unmask_irq(unsigned int irq)
+static void bfin_generic_error_unmask_irq(struct irq_data *d)
 {
 	bfin_internal_unmask_irq(IRQ_GENERIC_ERROR);
-	error_int_mask |= 1L << (irq - IRQ_PPI_ERROR);
+	error_int_mask |= 1L << (d->irq - IRQ_PPI_ERROR);
 }
 
 static struct irq_chip bfin_generic_error_irqchip = {
 	.name = "ERROR",
-	.ack = bfin_ack_noop,
-	.mask_ack = bfin_generic_error_mask_irq,
-	.mask = bfin_generic_error_mask_irq,
-	.unmask = bfin_generic_error_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask_ack = bfin_generic_error_mask_irq,
+	.irq_mask = bfin_generic_error_mask_irq,
+	.irq_unmask = bfin_generic_error_unmask_irq,
 };
 
 static void bfin_demux_error_irq(unsigned int int_err_irq,
@@ -448,8 +463,10 @@
 	}
 }
 
-static void bfin_mac_status_mask_irq(unsigned int irq)
+static void bfin_mac_status_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	mac_stat_int_mask &= ~(1L << (irq - IRQ_MAC_PHYINT));
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	switch (irq) {
@@ -466,8 +483,10 @@
 	bfin_mac_status_ack_irq(irq);
 }
 
-static void bfin_mac_status_unmask_irq(unsigned int irq)
+static void bfin_mac_status_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	switch (irq) {
 	case IRQ_MAC_PHYINT:
@@ -484,7 +503,7 @@
 }
 
 #ifdef CONFIG_PM
-int bfin_mac_status_set_wake(unsigned int irq, unsigned int state)
+int bfin_mac_status_set_wake(struct irq_data *d, unsigned int state)
 {
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	return bfin_internal_set_wake(IRQ_GENERIC_ERROR, state);
@@ -496,12 +515,12 @@
 
 static struct irq_chip bfin_mac_status_irqchip = {
 	.name = "MACST",
-	.ack = bfin_ack_noop,
-	.mask_ack = bfin_mac_status_mask_irq,
-	.mask = bfin_mac_status_mask_irq,
-	.unmask = bfin_mac_status_unmask_irq,
+	.irq_ack = bfin_ack_noop,
+	.irq_mask_ack = bfin_mac_status_mask_irq,
+	.irq_mask = bfin_mac_status_mask_irq,
+	.irq_unmask = bfin_mac_status_unmask_irq,
 #ifdef CONFIG_PM
-	.set_wake = bfin_mac_status_set_wake,
+	.irq_set_wake = bfin_mac_status_set_wake,
 #endif
 };
 
@@ -538,13 +557,9 @@
 static inline void bfin_set_irq_handler(unsigned irq, irq_flow_handler_t handle)
 {
 #ifdef CONFIG_IPIPE
-	_set_irq_handler(irq, handle_level_irq);
-#else
-	struct irq_desc *desc = irq_desc + irq;
-	/* May not call generic set_irq_handler() due to spinlock
-	   recursion. */
-	desc->handle_irq = handle;
+	handle = handle_level_irq;
 #endif
+	__irq_set_handler_locked(irq, handle);
 }
 
 static DECLARE_BITMAP(gpio_enabled, MAX_BLACKFIN_GPIOS);
@@ -552,58 +567,59 @@
 
 #if !defined(CONFIG_BF54x)
 
-static void bfin_gpio_ack_irq(unsigned int irq)
+static void bfin_gpio_ack_irq(struct irq_data *d)
 {
 	/* AFAIK ack_irq in case mask_ack is provided
 	 * get's only called for edge sense irqs
 	 */
-	set_gpio_data(irq_to_gpio(irq), 0);
+	set_gpio_data(irq_to_gpio(d->irq), 0);
 }
 
-static void bfin_gpio_mask_ack_irq(unsigned int irq)
+static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_desc + irq;
+	unsigned int irq = d->irq;
 	u32 gpionr = irq_to_gpio(irq);
 
-	if (desc->handle_irq == handle_edge_irq)
+	if (!irqd_is_level_type(d))
 		set_gpio_data(gpionr, 0);
 
 	set_gpio_maska(gpionr, 0);
 }
 
-static void bfin_gpio_mask_irq(unsigned int irq)
+static void bfin_gpio_mask_irq(struct irq_data *d)
 {
-	set_gpio_maska(irq_to_gpio(irq), 0);
+	set_gpio_maska(irq_to_gpio(d->irq), 0);
 }
 
-static void bfin_gpio_unmask_irq(unsigned int irq)
+static void bfin_gpio_unmask_irq(struct irq_data *d)
 {
-	set_gpio_maska(irq_to_gpio(irq), 1);
+	set_gpio_maska(irq_to_gpio(d->irq), 1);
 }
 
-static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+static unsigned int bfin_gpio_irq_startup(struct irq_data *d)
 {
-	u32 gpionr = irq_to_gpio(irq);
+	u32 gpionr = irq_to_gpio(d->irq);
 
 	if (__test_and_set_bit(gpionr, gpio_enabled))
 		bfin_gpio_irq_prepare(gpionr);
 
-	bfin_gpio_unmask_irq(irq);
+	bfin_gpio_unmask_irq(d);
 
 	return 0;
 }
 
-static void bfin_gpio_irq_shutdown(unsigned int irq)
+static void bfin_gpio_irq_shutdown(struct irq_data *d)
 {
-	u32 gpionr = irq_to_gpio(irq);
+	u32 gpionr = irq_to_gpio(d->irq);
 
-	bfin_gpio_mask_irq(irq);
+	bfin_gpio_mask_irq(d);
 	__clear_bit(gpionr, gpio_enabled);
 	bfin_gpio_irq_free(gpionr);
 }
 
-static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
+	unsigned int irq = d->irq;
 	int ret;
 	char buf[16];
 	u32 gpionr = irq_to_gpio(irq);
@@ -664,9 +680,9 @@
 }
 
 #ifdef CONFIG_PM
-int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
-	return gpio_pm_wakeup_ctrl(irq_to_gpio(irq), state);
+	return gpio_pm_wakeup_ctrl(irq_to_gpio(d->irq), state);
 }
 #endif
 
@@ -818,14 +834,13 @@
 	}
 }
 
-static void bfin_gpio_ack_irq(unsigned int irq)
+static void bfin_gpio_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_desc + irq;
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
-	if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
 		if (pint[bank]->invert_set & pintbit)
 			pint[bank]->invert_clear = pintbit;
 		else
@@ -835,14 +850,13 @@
 
 }
 
-static void bfin_gpio_mask_ack_irq(unsigned int irq)
+static void bfin_gpio_mask_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_desc + irq;
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
-	if ((desc->status & IRQ_TYPE_SENSE_MASK) == IRQ_TYPE_EDGE_BOTH) {
+	if (irqd_get_trigger_type(d) == IRQ_TYPE_EDGE_BOTH) {
 		if (pint[bank]->invert_set & pintbit)
 			pint[bank]->invert_clear = pintbit;
 		else
@@ -853,24 +867,25 @@
 	pint[bank]->mask_clear = pintbit;
 }
 
-static void bfin_gpio_mask_irq(unsigned int irq)
+static void bfin_gpio_mask_irq(struct irq_data *d)
 {
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 
 	pint[PINT_2_BANK(pint_val)]->mask_clear = PINT_BIT(pint_val);
 }
 
-static void bfin_gpio_unmask_irq(unsigned int irq)
+static void bfin_gpio_unmask_irq(struct irq_data *d)
 {
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 pintbit = PINT_BIT(pint_val);
 	u32 bank = PINT_2_BANK(pint_val);
 
 	pint[bank]->mask_set = pintbit;
 }
 
-static unsigned int bfin_gpio_irq_startup(unsigned int irq)
+static unsigned int bfin_gpio_irq_startup(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	u32 gpionr = irq_to_gpio(irq);
 	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
 
@@ -884,22 +899,23 @@
 	if (__test_and_set_bit(gpionr, gpio_enabled))
 		bfin_gpio_irq_prepare(gpionr);
 
-	bfin_gpio_unmask_irq(irq);
+	bfin_gpio_unmask_irq(d);
 
 	return 0;
 }
 
-static void bfin_gpio_irq_shutdown(unsigned int irq)
+static void bfin_gpio_irq_shutdown(struct irq_data *d)
 {
-	u32 gpionr = irq_to_gpio(irq);
+	u32 gpionr = irq_to_gpio(d->irq);
 
-	bfin_gpio_mask_irq(irq);
+	bfin_gpio_mask_irq(d);
 	__clear_bit(gpionr, gpio_enabled);
 	bfin_gpio_irq_free(gpionr);
 }
 
-static int bfin_gpio_irq_type(unsigned int irq, unsigned int type)
+static int bfin_gpio_irq_type(struct irq_data *d, unsigned int type)
 {
+	unsigned int irq = d->irq;
 	int ret;
 	char buf[16];
 	u32 gpionr = irq_to_gpio(irq);
@@ -961,10 +977,10 @@
 u32 pint_saved_masks[NR_PINT_SYS_IRQS];
 u32 pint_wakeup_masks[NR_PINT_SYS_IRQS];
 
-int bfin_gpio_set_wake(unsigned int irq, unsigned int state)
+int bfin_gpio_set_wake(struct irq_data *d, unsigned int state)
 {
 	u32 pint_irq;
-	u32 pint_val = irq2pint_lut[irq - SYS_IRQS];
+	u32 pint_val = irq2pint_lut[d->irq - SYS_IRQS];
 	u32 bank = PINT_2_BANK(pint_val);
 	u32 pintbit = PINT_BIT(pint_val);
 
@@ -1066,17 +1082,17 @@
 
 static struct irq_chip bfin_gpio_irqchip = {
 	.name = "GPIO",
-	.ack = bfin_gpio_ack_irq,
-	.mask = bfin_gpio_mask_irq,
-	.mask_ack = bfin_gpio_mask_ack_irq,
-	.unmask = bfin_gpio_unmask_irq,
-	.disable = bfin_gpio_mask_irq,
-	.enable = bfin_gpio_unmask_irq,
-	.set_type = bfin_gpio_irq_type,
-	.startup = bfin_gpio_irq_startup,
-	.shutdown = bfin_gpio_irq_shutdown,
+	.irq_ack = bfin_gpio_ack_irq,
+	.irq_mask = bfin_gpio_mask_irq,
+	.irq_mask_ack = bfin_gpio_mask_ack_irq,
+	.irq_unmask = bfin_gpio_unmask_irq,
+	.irq_disable = bfin_gpio_mask_irq,
+	.irq_enable = bfin_gpio_unmask_irq,
+	.irq_set_type = bfin_gpio_irq_type,
+	.irq_startup = bfin_gpio_irq_startup,
+	.irq_shutdown = bfin_gpio_irq_shutdown,
 #ifdef CONFIG_PM
-	.set_wake = bfin_gpio_set_wake,
+	.irq_set_wake = bfin_gpio_set_wake,
 #endif
 };
 
@@ -1147,9 +1163,9 @@
 
 	for (irq = 0; irq <= SYS_IRQS; irq++) {
 		if (irq <= IRQ_CORETMR)
-			set_irq_chip(irq, &bfin_core_irqchip);
+			irq_set_chip(irq, &bfin_core_irqchip);
 		else
-			set_irq_chip(irq, &bfin_internal_irqchip);
+			irq_set_chip(irq, &bfin_internal_irqchip);
 
 		switch (irq) {
 #if defined(CONFIG_BF53x)
@@ -1173,50 +1189,50 @@
 #elif defined(CONFIG_BF538) || defined(CONFIG_BF539)
 		case IRQ_PORTF_INTA:
 #endif
-			set_irq_chained_handler(irq,
-						bfin_demux_gpio_irq);
+			irq_set_chained_handler(irq, bfin_demux_gpio_irq);
 			break;
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 		case IRQ_GENERIC_ERROR:
-			set_irq_chained_handler(irq, bfin_demux_error_irq);
+			irq_set_chained_handler(irq, bfin_demux_error_irq);
 			break;
 #endif
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 		case IRQ_MAC_ERROR:
-			set_irq_chained_handler(irq, bfin_demux_mac_status_irq);
+			irq_set_chained_handler(irq,
+						bfin_demux_mac_status_irq);
 			break;
 #endif
 #ifdef CONFIG_SMP
 		case IRQ_SUPPLE_0:
 		case IRQ_SUPPLE_1:
-			set_irq_handler(irq, handle_percpu_irq);
+			irq_set_handler(irq, handle_percpu_irq);
 			break;
 #endif
 
 #ifdef CONFIG_TICKSOURCE_CORETMR
 		case IRQ_CORETMR:
 # ifdef CONFIG_SMP
-			set_irq_handler(irq, handle_percpu_irq);
+			irq_set_handler(irq, handle_percpu_irq);
 			break;
 # else
-			set_irq_handler(irq, handle_simple_irq);
+			irq_set_handler(irq, handle_simple_irq);
 			break;
 # endif
 #endif
 
 #ifdef CONFIG_TICKSOURCE_GPTMR0
 		case IRQ_TIMER0:
-			set_irq_handler(irq, handle_simple_irq);
+			irq_set_handler(irq, handle_simple_irq);
 			break;
 #endif
 
 #ifdef CONFIG_IPIPE
 		default:
-			set_irq_handler(irq, handle_level_irq);
+			irq_set_handler(irq, handle_level_irq);
 			break;
 #else /* !CONFIG_IPIPE */
 		default:
-			set_irq_handler(irq, handle_simple_irq);
+			irq_set_handler(irq, handle_simple_irq);
 			break;
 #endif /* !CONFIG_IPIPE */
 		}
@@ -1224,22 +1240,22 @@
 
 #ifdef BF537_GENERIC_ERROR_INT_DEMUX
 	for (irq = IRQ_PPI_ERROR; irq <= IRQ_UART1_ERROR; irq++)
-		set_irq_chip_and_handler(irq, &bfin_generic_error_irqchip,
+		irq_set_chip_and_handler(irq, &bfin_generic_error_irqchip,
 					 handle_level_irq);
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
-	set_irq_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq);
+	irq_set_chained_handler(IRQ_MAC_ERROR, bfin_demux_mac_status_irq);
 #endif
 #endif
 
 #if defined(CONFIG_BFIN_MAC) || defined(CONFIG_BFIN_MAC_MODULE)
 	for (irq = IRQ_MAC_PHYINT; irq <= IRQ_MAC_STMDONE; irq++)
-		set_irq_chip_and_handler(irq, &bfin_mac_status_irqchip,
+		irq_set_chip_and_handler(irq, &bfin_mac_status_irqchip,
 					 handle_level_irq);
 #endif
 	/* if configured as edge, then will be changed to do_edge_IRQ */
 	for (irq = GPIO_IRQ_BASE;
 		irq < (GPIO_IRQ_BASE + MAX_BLACKFIN_GPIOS); irq++)
-		set_irq_chip_and_handler(irq, &bfin_gpio_irqchip,
+		irq_set_chip_and_handler(irq, &bfin_gpio_irqchip,
 					 handle_level_irq);
 
 	bfin_write_IMASK(0);
@@ -1373,7 +1389,7 @@
 	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;
+	int irq, s = 0;
 
 	if (likely(vec == EVT_IVTMR_P))
 		irq = IRQ_CORETMR;
@@ -1423,6 +1439,21 @@
 			__raw_get_cpu_var(__ipipe_tick_regs).ipend |= 0x10;
 	}
 
+	/*
+	 * We don't want Linux interrupt handlers to run at the
+	 * current core priority level (i.e. < EVT15), since this
+	 * might delay other interrupts handled by a high priority
+	 * domain. Here is what we do instead:
+	 *
+	 * - we raise the SYNCDEFER bit to prevent
+	 * __ipipe_handle_irq() to sync the pipeline for the root
+	 * stage for the incoming interrupt. Upon return, that IRQ is
+	 * pending in the interrupt log.
+	 *
+	 * - we raise the TIF_IRQ_SYNC bit for the current thread, so
+	 * that _schedule_and_signal_from_int will eventually sync the
+	 * pipeline from EVT15.
+	 */
 	if (this_domain == ipipe_root_domain) {
 		s = __test_and_set_bit(IPIPE_SYNCDEFER_FLAG, &p->status);
 		barrier();
@@ -1432,6 +1463,24 @@
 	__ipipe_handle_irq(irq, regs);
 	ipipe_trace_irq_exit(irq);
 
+	if (user_mode(regs) &&
+	    !ipipe_test_foreign_stack() &&
+	    (current->ipipe_flags & PF_EVTRET) != 0) {
+		/*
+		 * Testing for user_regs() does NOT fully eliminate
+		 * foreign stack contexts, because of the forged
+		 * interrupt returns we do through
+		 * __ipipe_call_irqtail. In that case, we might have
+		 * preempted a foreign stack context in a high
+		 * priority domain, with a single interrupt level now
+		 * pending after the irqtail unwinding is done. In
+		 * which case user_mode() is now true, and the event
+		 * gets dispatched spuriously.
+		 */
+		current->ipipe_flags &= ~PF_EVTRET;
+		__ipipe_dispatch_event(IPIPE_EVENT_RETURN, regs);
+	}
+
 	if (this_domain == ipipe_root_domain) {
 		set_thread_flag(TIF_IRQ_SYNC);
 		if (!s) {
diff -druN linux-libre-2.6.38-gnu/arch/blackfin/mach-common/smp.c linux-libre-2.6.39-gnu/arch/blackfin/mach-common/smp.c
--- linux-libre-2.6.38-gnu/arch/blackfin/mach-common/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/blackfin/mach-common/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,10 @@
  */
 struct corelock_slot corelock __attribute__ ((__section__(".l2.bss")));
 
+#ifdef CONFIG_ICACHE_FLUSH_L1
+unsigned long blackfin_iflush_l1_entry[NR_CPUS];
+#endif
+
 void __cpuinitdata *init_retx_coreb, *init_saved_retx_coreb,
 	*init_saved_seqstat_coreb, *init_saved_icplb_fault_addr_coreb,
 	*init_saved_dcplb_fault_addr_coreb;
@@ -108,6 +112,19 @@
 	blackfin_dcache_invalidate_range((unsigned long)fdata,
 					 (unsigned long)fdata + sizeof(*fdata));
 
+	/* 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();
+
+	/* ipi_flaush_icache is invoked by generic flush_icache_range,
+	 * so call blackfin arch icache flush directly here.
+	 */
 	blackfin_icache_flush_range(fdata->start, fdata->end);
 }
 
@@ -244,12 +261,13 @@
 {
 	cpumask_t callmap;
 
+	preempt_disable();
 	callmap = cpu_online_map;
 	cpu_clear(smp_processor_id(), callmap);
-	if (cpus_empty(callmap))
-		return 0;
+	if (!cpus_empty(callmap))
+		smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
 
-	smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
+	preempt_enable();
 
 	return 0;
 }
@@ -286,12 +304,13 @@
 {
 	cpumask_t callmap;
 
+	preempt_disable();
 	callmap = cpu_online_map;
 	cpu_clear(smp_processor_id(), callmap);
-	if (cpus_empty(callmap))
-		return;
+	if (!cpus_empty(callmap))
+		smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
 
-	smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
+	preempt_enable();
 
 	return;
 }
@@ -361,8 +380,6 @@
 	 */
 	init_exception_vectors();
 
-	bfin_setup_caches(cpu);
-
 	local_irq_disable();
 
 	/* Attach the new idle task to the global mm. */
@@ -381,6 +398,8 @@
 
 	local_irq_enable();
 
+	bfin_setup_caches(cpu);
+
 	/*
 	 * Calibrate loops per jiffy value.
 	 * IRQs need to be enabled here - D-cache can be invalidated
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/drivers/axisflashmap.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/drivers/axisflashmap.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/drivers/axisflashmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/drivers/axisflashmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -234,7 +234,6 @@
 	}
 
 	if (mtd_cse0 && mtd_cse1) {
-#ifdef CONFIG_MTD_CONCAT
 		struct mtd_info *mtds[] = { mtd_cse0, mtd_cse1 };
 
 		/* Since the concatenation layer adds a small overhead we
@@ -246,11 +245,6 @@
 		 */
 		mtd_cse = mtd_concat_create(mtds, ARRAY_SIZE(mtds),
 					    "cse0+cse1");
-#else
-		printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
-		       "(mis)configuration!\n", map_cse0.name, map_cse1.name);
-		mtd_cse = NULL;
-#endif
 		if (!mtd_cse) {
 			printk(KERN_ERR "%s and %s: Concatenation failed!\n",
 			       map_cse0.name, map_cse1.name);
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/drivers/pcf8563.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/drivers/pcf8563.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/drivers/pcf8563.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/drivers/pcf8563.c	2011-05-19 00:06:34.000000000 -0400
@@ -345,7 +345,7 @@
 	int ret;
 
 	mutex_lock(&pcf8563_mutex);
-	return pcf8563_ioctl(filp, cmd, arg);
+	ret = pcf8563_ioctl(filp, cmd, arg);
 	mutex_unlock(&pcf8563_mutex);
 
 	return ret;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/drivers/sync_serial.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/drivers/sync_serial.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/drivers/sync_serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/drivers/sync_serial.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #include <asm/sync_serial.h>
 #include <arch/io_interface_mux.h>
 
-/* The receiver is a bit tricky beacuse of the continuous stream of data.*/
+/* The receiver is a bit tricky because of the continuous stream of data.*/
 /*                                                                       */
 /* Three DMA descriptors are linked together. Each DMA descriptor is     */
 /* responsible for port->bufchunk of a common buffer.                    */
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/kernel/irq.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -199,7 +199,7 @@
 
 	/* Initialize IRQ handler descriptors. */
 	for(i = 2; i < NR_IRQS; i++) {
-		set_irq_desc_and_handler(i, &crisv10_irq_type,
+		irq_set_chip_and_handler(i, &crisv10_irq_type,
 					 handle_simple_irq);
 		set_int_vector(i, interrupt[i]);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/kernel/signal.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -537,7 +537,7 @@
 			RESTART_CRIS_SYS(regs);
 		}
 		if (regs->r10 == -ERESTART_RESTARTBLOCK) {
-			regs->r10 = __NR_restart_syscall;
+			regs->r9 = __NR_restart_syscall;
 			regs->irp -= 2;
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/kernel/time.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,7 +140,7 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 
 //static unsigned short myjiff; /* used by our debug routine print_timestamp */
@@ -176,7 +176,7 @@
 
 	/* call the real timer interrupt handler */
 
-	do_timer(1);
+	xtime_update(1);
 	
         cris_do_profile(regs); /* Save profiling information */
         return IRQ_HANDLED;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/mm/init.c linux-libre-2.6.39-gnu/arch/cris/arch-v10/mm/init.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,7 +241,7 @@
 }
 
 /* Due to a bug in Etrax100(LX) all versions, receiving DMA buffers
- * will occationally corrupt certain CPU writes if the DMA buffers
+ * will occasionally corrupt certain CPU writes if the DMA buffers
  * happen to be hot in the cache.
  * 
  * As a workaround, we have to flush the relevant parts of the cache
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v10/README.mm linux-libre-2.6.39-gnu/arch/cris/arch-v10/README.mm
--- linux-libre-2.6.38-gnu/arch/cris/arch-v10/README.mm	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v10/README.mm	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 map during kernel-mode, so that the kernel easily can access the corresponding
 user-mode process' data.
 
-As a comparision, the Linux/i386 2.0 puts the kernel and physical RAM at
+As a comparison, the Linux/i386 2.0 puts the kernel and physical RAM at
 address 0, overlapping with the user-mode virtual space, so that descriptor
 registers are needed for each memory access to specify which MMU space to
 map through. That changed in 2.2, putting the kernel/physical RAM at 
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/axisflashmap.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/axisflashmap.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/axisflashmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/axisflashmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -215,7 +215,7 @@
 };
 #endif
 
-/* Auxilliary partition if we find another flash */
+/* Auxiliary partition if we find another flash */
 static struct mtd_partition aux_partition = {
 	.name = "aux",
 	.size = 0,
@@ -275,7 +275,6 @@
 	}
 
 	if (count > 1) {
-#ifdef CONFIG_MTD_CONCAT
 		/* Since the concatenation layer adds a small overhead we
 		 * could try to figure out if the chips in cse0 and cse1 are
 		 * identical and reprobe the whole cse0+cse1 window. But since
@@ -284,11 +283,6 @@
 		 * complicating the probing procedure.
 		 */
 		mtd_total = mtd_concat_create(mtds, count, "cse0+cse1");
-#else
-		printk(KERN_ERR "%s and %s: Cannot concatenate due to kernel "
-		       "(mis)configuration!\n", map_cse0.name, map_cse1.name);
-		mtd_toal = NULL;
-#endif
 		if (!mtd_total) {
 			printk(KERN_ERR "%s and %s: Concatenation failed!\n",
 				map_cse0.name, map_cse1.name);
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/Kconfig linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/Kconfig
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -406,7 +406,6 @@
 	select MTD_CHAR
 	select MTD_BLOCK
 	select MTD_PARTITIONS
-	select MTD_CONCAT
 	select MTD_COMPLEX_MAPPINGS
 	help
 	  This option enables MTD mapping of flash devices.  Needed to use
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/mach-a3/nandflash.c	2011-05-19 00:06:34.000000000 -0400
@@ -165,7 +165,7 @@
 	/* Enable the following for a flash based bad block table */
 	/* this->options = NAND_USE_FLASH_BBT; */
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
 		err = -ENXIO;
 		goto out_mtd;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/mach-fs/nandflash.c	2011-05-19 00:06:34.000000000 -0400
@@ -156,7 +156,7 @@
 	/* Enable the following for a flash based bad block table */
 	/* this->options = NAND_USE_FLASH_BBT; */
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(crisv32_mtd, 1)) {
 		err = -ENXIO;
 		goto out_ior;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/Makefile linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/Makefile
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,6 @@
 obj-$(CONFIG_ETRAXFS)                   += mach-fs/
 obj-$(CONFIG_CRIS_MACH_ARTPEC3)         += mach-a3/
 obj-$(CONFIG_ETRAX_IOP_FW_LOAD)         += iop_fw_load.o
-obj-$(CONFIG_ETRAX_PCF8563)		+= pcf8563.o
 obj-$(CONFIG_ETRAX_I2C)			+= i2c.o
 obj-$(CONFIG_ETRAX_SYNCHRONOUS_SERIAL)	+= sync_serial.o
 obj-$(CONFIG_PCI)			+= pci/
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/pcf8563.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/pcf8563.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/pcf8563.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/pcf8563.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,377 +0,0 @@
-/*
- * PCF8563 RTC
- *
- * From Phillips' datasheet:
- *
- * The PCF8563 is a CMOS real-time clock/calendar optimized for low power
- * consumption. A programmable clock output, interrupt output and voltage
- * low detector are also provided. All address and data are transferred
- * serially via two-line bidirectional I2C-bus. Maximum bus speed is
- * 400 kbits/s. The built-in word address register is incremented
- * automatically after each written or read byte.
- *
- * Copyright (c) 2002-2007, Axis Communications AB
- * All rights reserved.
- *
- * Author: Tobias Anderberg <tobiasa@axis.com>.
- *
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/fs.h>
-#include <linux/ioctl.h>
-#include <linux/delay.h>
-#include <linux/bcd.h>
-#include <linux/mutex.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/rtc.h>
-
-#include "i2c.h"
-
-#define PCF8563_MAJOR	121	/* Local major number. */
-#define DEVICE_NAME	"rtc"	/* Name which is registered in /proc/devices. */
-#define PCF8563_NAME	"PCF8563"
-#define DRIVER_VERSION	"$Revision: 1.17 $"
-
-/* Two simple wrapper macros, saves a few keystrokes. */
-#define rtc_read(x) i2c_readreg(RTC_I2C_READ, x)
-#define rtc_write(x,y) i2c_writereg(RTC_I2C_WRITE, x, y)
-
-static DEFINE_MUTEX(pcf8563_mutex);
-static DEFINE_MUTEX(rtc_lock); /* Protect state etc */
-
-static const unsigned char days_in_month[] =
-	{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
-
-static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-
-/* Cache VL bit value read at driver init since writing the RTC_SECOND
- * register clears the VL status.
- */
-static int voltage_low;
-
-static const struct file_operations pcf8563_fops = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl = pcf8563_unlocked_ioctl,
-	.llseek		= noop_llseek,
-};
-
-unsigned char
-pcf8563_readreg(int reg)
-{
-	unsigned char res = rtc_read(reg);
-
-	/* The PCF8563 does not return 0 for unimplemented bits. */
-	switch (reg) {
-		case RTC_SECONDS:
-		case RTC_MINUTES:
-			res &= 0x7F;
-			break;
-		case RTC_HOURS:
-		case RTC_DAY_OF_MONTH:
-			res &= 0x3F;
-			break;
-		case RTC_WEEKDAY:
-			res &= 0x07;
-			break;
-		case RTC_MONTH:
-			res &= 0x1F;
-			break;
-		case RTC_CONTROL1:
-			res &= 0xA8;
-			break;
-		case RTC_CONTROL2:
-			res &= 0x1F;
-			break;
-		case RTC_CLOCKOUT_FREQ:
-		case RTC_TIMER_CONTROL:
-			res &= 0x83;
-			break;
-	}
-	return res;
-}
-
-void
-pcf8563_writereg(int reg, unsigned char val)
-{
-	rtc_write(reg, val);
-}
-
-void
-get_rtc_time(struct rtc_time *tm)
-{
-	tm->tm_sec  = rtc_read(RTC_SECONDS);
-	tm->tm_min  = rtc_read(RTC_MINUTES);
-	tm->tm_hour = rtc_read(RTC_HOURS);
-	tm->tm_mday = rtc_read(RTC_DAY_OF_MONTH);
-	tm->tm_wday = rtc_read(RTC_WEEKDAY);
-	tm->tm_mon  = rtc_read(RTC_MONTH);
-	tm->tm_year = rtc_read(RTC_YEAR);
-
-	if (tm->tm_sec & 0x80) {
-		printk(KERN_ERR "%s: RTC Voltage Low - reliable date/time "
-		       "information is no longer guaranteed!\n", PCF8563_NAME);
-	}
-
-	tm->tm_year  = bcd2bin(tm->tm_year) +
-		       ((tm->tm_mon & 0x80) ? 100 : 0);
-	tm->tm_sec  &= 0x7F;
-	tm->tm_min  &= 0x7F;
-	tm->tm_hour &= 0x3F;
-	tm->tm_mday &= 0x3F;
-	tm->tm_wday &= 0x07; /* Not coded in BCD. */
-	tm->tm_mon  &= 0x1F;
-
-	tm->tm_sec = bcd2bin(tm->tm_sec);
-	tm->tm_min = bcd2bin(tm->tm_min);
-	tm->tm_hour = bcd2bin(tm->tm_hour);
-	tm->tm_mday = bcd2bin(tm->tm_mday);
-	tm->tm_mon = bcd2bin(tm->tm_mon);
-	tm->tm_mon--; /* Month is 1..12 in RTC but 0..11 in linux */
-}
-
-int __init
-pcf8563_init(void)
-{
-	static int res;
-	static int first = 1;
-
-	if (!first)
-		return res;
-	first = 0;
-
-	/* Initiate the i2c protocol. */
-	res = i2c_init();
-	if (res < 0) {
-		printk(KERN_CRIT "pcf8563_init: Failed to init i2c.\n");
-		return res;
-	}
-
-	/*
-	 * First of all we need to reset the chip. This is done by
-	 * clearing control1, control2 and clk freq and resetting
-	 * all alarms.
-	 */
-	if (rtc_write(RTC_CONTROL1, 0x00) < 0)
-		goto err;
-
-	if (rtc_write(RTC_CONTROL2, 0x00) < 0)
-		goto err;
-
-	if (rtc_write(RTC_CLOCKOUT_FREQ, 0x00) < 0)
-		goto err;
-
-	if (rtc_write(RTC_TIMER_CONTROL, 0x03) < 0)
-		goto err;
-
-	/* Reset the alarms. */
-	if (rtc_write(RTC_MINUTE_ALARM, 0x80) < 0)
-		goto err;
-
-	if (rtc_write(RTC_HOUR_ALARM, 0x80) < 0)
-		goto err;
-
-	if (rtc_write(RTC_DAY_ALARM, 0x80) < 0)
-		goto err;
-
-	if (rtc_write(RTC_WEEKDAY_ALARM, 0x80) < 0)
-		goto err;
-
-	/* Check for low voltage, and warn about it. */
-	if (rtc_read(RTC_SECONDS) & 0x80) {
-		voltage_low = 1;
-		printk(KERN_WARNING "%s: RTC Voltage Low - reliable "
-		       "date/time information is no longer guaranteed!\n",
-		       PCF8563_NAME);
-	}
-
-	return res;
-
-err:
-	printk(KERN_INFO "%s: Error initializing chip.\n", PCF8563_NAME);
-	res = -1;
-	return res;
-}
-
-void __exit
-pcf8563_exit(void)
-{
-	unregister_chrdev(PCF8563_MAJOR, DEVICE_NAME);
-}
-
-/*
- * ioctl calls for this driver. Why return -ENOTTY upon error? Because
- * POSIX says so!
- */
-static int pcf8563_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	/* Some sanity checks. */
-	if (_IOC_TYPE(cmd) != RTC_MAGIC)
-		return -ENOTTY;
-
-	if (_IOC_NR(cmd) > RTC_MAX_IOCTL)
-		return -ENOTTY;
-
-	switch (cmd) {
-	case RTC_RD_TIME:
-	{
-		struct rtc_time tm;
-
-		mutex_lock(&rtc_lock);
-		memset(&tm, 0, sizeof tm);
-		get_rtc_time(&tm);
-
-		if (copy_to_user((struct rtc_time *) arg, &tm,
-				 sizeof tm)) {
-			mutex_unlock(&rtc_lock);
-			return -EFAULT;
-		}
-
-		mutex_unlock(&rtc_lock);
-
-		return 0;
-	}
-	case RTC_SET_TIME:
-	{
-		int leap;
-		int year;
-		int century;
-		struct rtc_time tm;
-
-		memset(&tm, 0, sizeof tm);
-		if (!capable(CAP_SYS_TIME))
-			return -EPERM;
-
-		if (copy_from_user(&tm, (struct rtc_time *) arg,
-				   sizeof tm))
-			return -EFAULT;
-
-		/* Convert from struct tm to struct rtc_time. */
-		tm.tm_year += 1900;
-		tm.tm_mon += 1;
-
-		/*
-		 * Check if tm.tm_year is a leap year. A year is a leap
-		 * year if it is divisible by 4 but not 100, except
-		 * that years divisible by 400 _are_ leap years.
-		 */
-		year = tm.tm_year;
-		leap = (tm.tm_mon == 2) &&
-			((year % 4 == 0 && year % 100 != 0) || year % 400 == 0);
-
-		/* Perform some sanity checks. */
-		if ((tm.tm_year < 1970) ||
-		    (tm.tm_mon > 12) ||
-		    (tm.tm_mday == 0) ||
-		    (tm.tm_mday > days_in_month[tm.tm_mon] + leap) ||
-		    (tm.tm_wday >= 7) ||
-		    (tm.tm_hour >= 24) ||
-		    (tm.tm_min >= 60) ||
-		    (tm.tm_sec >= 60))
-			return -EINVAL;
-
-		century = (tm.tm_year >= 2000) ? 0x80 : 0;
-		tm.tm_year = tm.tm_year % 100;
-
-		tm.tm_year = bin2bcd(tm.tm_year);
-		tm.tm_mon = bin2bcd(tm.tm_mon);
-		tm.tm_mday = bin2bcd(tm.tm_mday);
-		tm.tm_hour = bin2bcd(tm.tm_hour);
-		tm.tm_min = bin2bcd(tm.tm_min);
-		tm.tm_sec = bin2bcd(tm.tm_sec);
-		tm.tm_mon |= century;
-
-		mutex_lock(&rtc_lock);
-
-		rtc_write(RTC_YEAR, tm.tm_year);
-		rtc_write(RTC_MONTH, tm.tm_mon);
-		rtc_write(RTC_WEEKDAY, tm.tm_wday); /* Not coded in BCD. */
-		rtc_write(RTC_DAY_OF_MONTH, tm.tm_mday);
-		rtc_write(RTC_HOURS, tm.tm_hour);
-		rtc_write(RTC_MINUTES, tm.tm_min);
-		rtc_write(RTC_SECONDS, tm.tm_sec);
-
-		mutex_unlock(&rtc_lock);
-
-		return 0;
-	}
-	case RTC_VL_READ:
-		if (voltage_low)
-			printk(KERN_ERR "%s: RTC Voltage Low - "
-			       "reliable date/time information is no "
-			       "longer guaranteed!\n", PCF8563_NAME);
-
-		if (copy_to_user((int *) arg, &voltage_low, sizeof(int)))
-			return -EFAULT;
-		return 0;
-
-	case RTC_VL_CLR:
-	{
-		/* Clear the VL bit in the seconds register in case
-		 * the time has not been set already (which would
-		 * have cleared it). This does not really matter
-		 * because of the cached voltage_low value but do it
-		 * anyway for consistency. */
-
-		int ret = rtc_read(RTC_SECONDS);
-
-		rtc_write(RTC_SECONDS, (ret & 0x7F));
-
-		/* Clear the cached value. */
-		voltage_low = 0;
-
-		return 0;
-	}
-	default:
-		return -ENOTTY;
-	}
-
-	return 0;
-}
-
-static long pcf8563_unlocked_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-
-	mutex_lock(&pcf8563_mutex);
-	return pcf8563_ioctl(filp, cmd, arg);
-	mutex_unlock(&pcf8563_mutex);
-
-	return ret;
-}
-
-static int __init pcf8563_register(void)
-{
-	if (pcf8563_init() < 0) {
-		printk(KERN_INFO "%s: Unable to initialize Real-Time Clock "
-		       "Driver, %s\n", PCF8563_NAME, DRIVER_VERSION);
-		return -1;
-	}
-
-	if (register_chrdev(PCF8563_MAJOR, DEVICE_NAME, &pcf8563_fops) < 0) {
-		printk(KERN_INFO "%s: Unable to get major numer %d for RTC "
-		       "device.\n", PCF8563_NAME, PCF8563_MAJOR);
-		return -1;
-	}
-
-	printk(KERN_INFO "%s Real-Time Clock Driver, %s\n", PCF8563_NAME,
-	       DRIVER_VERSION);
-
-	/* Check for low voltage, and warn about it. */
-	if (voltage_low) {
-		printk(KERN_WARNING "%s: RTC Voltage Low - reliable date/time "
-		       "information is no longer guaranteed!\n", PCF8563_NAME);
-	}
-
-	return 0;
-}
-
-module_init(pcf8563_register);
-module_exit(pcf8563_exit);
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/sync_serial.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/sync_serial.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/drivers/sync_serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/drivers/sync_serial.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 #include <asm/sync_serial.h>
 
 
-/* The receiver is a bit tricky beacuse of the continuous stream of data.*/
+/* The receiver is a bit tricky because of the continuous stream of data.*/
 /*                                                                       */
 /* Three DMA descriptors are linked together. Each DMA descriptor is     */
 /* responsible for port->bufchunk of a common buffer.                    */
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/entry.S linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -182,7 +182,7 @@
 	move.d	$r0, [$sp]
 
 	;; The registers carrying parameters (R10-R13) are intact. The optional
-	;; fifth and sixth parameters is in MOF and SRP respectivly. Put them
+	;; fifth and sixth parameters is in MOF and SRP respectively. Put them
 	;; back on the stack.
 	subq	4, $sp
 	move	$srp, [$sp]
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/irq.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -374,7 +374,7 @@
 	irq_enter();
 
 	for (i = 0; i < NBR_REGS; i++) {
-		/* Get which IRQs that happend. */
+		/* Get which IRQs that happened. */
 		masked[i] = REG_RD_INT_VECT(intr_vect, irq_regs[cpu],
 			r_masked_vect, i);
 
@@ -451,16 +451,16 @@
 
 	/* Point all IRQ's to bad handlers. */
 	for (i = FIRST_IRQ, j = 0; j < NR_IRQS; i++, j++) {
-		set_irq_chip_and_handler(j, &crisv32_irq_type,
+		irq_set_chip_and_handler(j, &crisv32_irq_type,
 					 handle_simple_irq);
 		set_exception_vector(i, interrupt[j]);
 	}
 
-        /* Mark Timer and IPI IRQs as CPU local */
+	/* Mark Timer and IPI IRQs as CPU local */
 	irq_allocations[TIMER0_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
-	irq_desc[TIMER0_INTR_VECT].status |= IRQ_PER_CPU;
+	irq_set_status_flags(TIMER0_INTR_VECT, IRQ_PER_CPU);
 	irq_allocations[IPI_INTR_VECT - FIRST_IRQ].cpu = CPU_FIXED;
-	irq_desc[IPI_INTR_VECT].status |= IRQ_PER_CPU;
+	irq_set_status_flags(IPI_INTR_VECT, IRQ_PER_CPU);
 
 	set_exception_vector(0x00, nmi_interrupt);
 	set_exception_vector(0x30, multiple_interrupt);
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/kgdb.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/kgdb.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/kgdb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/kgdb.c	2011-05-19 00:06:34.000000000 -0400
@@ -925,7 +925,7 @@
 
 					if (reg.eda >= bp_d_regs[bp * 2] &&
 					    reg.eda <= bp_d_regs[bp * 2 + 1]) {
-						/* EDA withing range for this BP; it must be the one
+						/* EDA within range for this BP; it must be the one
 						   we're looking for. */
 						stopped_data_address = reg.eda;
 						break;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/process.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
         childregs->r10 = 0;	/* Child returns 0 after a fork/clone. */
 
 	/* Set a new TLS ?
-	 * The TLS is in $mof beacuse it is the 5th argument to sys_clone.
+	 * The TLS is in $mof because it is the 5th argument to sys_clone.
 	 */
 	if (p->mm && (clone_flags & CLONE_SETTLS)) {
 		task_thread_info(p)->tls = regs->mof;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/signal.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -610,7 +610,7 @@
 		user_regs(ti)->spc = 0;
 	}
 	/* FIXME: Filter out false h/w breakpoint hits (i.e. EDA
-	   not withing any configured h/w breakpoint range). Synchronize with
+	   not within any configured h/w breakpoint range). Synchronize with
 	   what already exists for kernel debugging.  */
 	if (((user_regs(ti)->exs & 0xff00) >> 8) == BREAK_8_INTR_VECT) {
 		/* Break 8: subtract 2 from ERP unless in a delay slot. */
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/smp.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/smp.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,7 +26,9 @@
 #define FLUSH_ALL (void*)0xffffffff
 
 /* Vector of locks used for various atomic operations */
-spinlock_t cris_atomic_locks[] = { [0 ... LOCK_COUNT - 1] = SPIN_LOCK_UNLOCKED};
+spinlock_t cris_atomic_locks[] = {
+	[0 ... LOCK_COUNT - 1] = __SPIN_LOCK_UNLOCKED(cris_atomic_locks)
+};
 
 /* CPU masks */
 cpumask_t phys_cpu_present_map = CPU_MASK_NONE;
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/time.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -183,7 +183,7 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick.
+ * as well as call the "xtime_update()" routine every clocktick.
  */
 extern void cris_do_profile(struct pt_regs *regs);
 
@@ -216,9 +216,7 @@
 		return IRQ_HANDLED;
 
 	/* Call the real timer interrupt handler */
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
         return IRQ_HANDLED;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/mach-a3/arbiter.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/mach-a3/arbiter.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/mach-a3/arbiter.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/mach-a3/arbiter.c	2011-05-19 00:06:34.000000000 -0400
@@ -568,7 +568,7 @@
 	REG_WR(marb_foo_bp, watch->instance, rw_ack, ack);
 	REG_WR(marb_foo, regi_marb_foo, rw_ack_intr, ack_intr);
 
-	printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs());
+	printk(KERN_DEBUG "IRQ occurred at %X\n", (unsigned)get_irq_regs());
 
 	if (watch->cb)
 		watch->cb();
@@ -624,7 +624,7 @@
 	REG_WR(marb_bar_bp, watch->instance, rw_ack, ack);
 	REG_WR(marb_bar, regi_marb_bar, rw_ack_intr, ack_intr);
 
-	printk(KERN_DEBUG "IRQ occured at %X\n", (unsigned)get_irq_regs()->erp);
+	printk(KERN_DEBUG "IRQ occurred at %X\n", (unsigned)get_irq_regs()->erp);
 
 	if (watch->cb)
 		watch->cb();
diff -druN linux-libre-2.6.38-gnu/arch/cris/arch-v32/mach-fs/arbiter.c linux-libre-2.6.39-gnu/arch/cris/arch-v32/mach-fs/arbiter.c
--- linux-libre-2.6.38-gnu/arch/cris/arch-v32/mach-fs/arbiter.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/arch-v32/mach-fs/arbiter.c	2011-05-19 00:06:34.000000000 -0400
@@ -395,7 +395,7 @@
 	REG_WR(marb_bp, watch->instance, rw_ack, ack);
 	REG_WR(marb, regi_marb, rw_ack_intr, ack_intr);
 
-	printk(KERN_INFO "IRQ occured at %lX\n", get_irq_regs()->erp);
+	printk(KERN_INFO "IRQ occurred at %lX\n", get_irq_regs()->erp);
 
 	if (watch->cb)
 		watch->cb();
diff -druN linux-libre-2.6.38-gnu/arch/cris/boot/rescue/head_v10.S linux-libre-2.6.39-gnu/arch/cris/boot/rescue/head_v10.S
--- linux-libre-2.6.38-gnu/arch/cris/boot/rescue/head_v10.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/boot/rescue/head_v10.S	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
  * for each partition that this code should check.
  *
  * If any of the checksums fail, we assume the flash is so
- * corrupt that we cant use it to boot into the ftp flash
+ * corrupt that we can't use it to boot into the ftp flash
  * loader, and instead we initialize the serial port to
  * receive a flash-loader and new flash image. we dont include
  * any flash code here, but just accept a certain amount of
diff -druN linux-libre-2.6.38-gnu/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile linux-libre-2.6.39-gnu/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile
--- linux-libre-2.6.38-gnu/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/include/arch-v32/arch/hwregs/iop/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 # $Id: Makefile,v 1.3 2004/01/07 20:34:55 johana Exp $
 # Makefile to generate or copy the latest register definitions
 # and related datastructures and helpermacros.
-# The offical place for these files is probably at:
+# The official place for these files is probably at:
 RELEASE ?= r1_alfa5
 IOPOFFICIAL_INCDIR = /n/asic/projects/guinness/releases/$(RELEASE)/design/top/sw/include/
 
diff -druN linux-libre-2.6.38-gnu/arch/cris/include/arch-v32/arch/hwregs/Makefile linux-libre-2.6.39-gnu/arch/cris/include/arch-v32/arch/hwregs/Makefile
--- linux-libre-2.6.38-gnu/arch/cris/include/arch-v32/arch/hwregs/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/include/arch-v32/arch/hwregs/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 # Makefile to generate or copy the latest register definitions
 # and related datastructures and helpermacros.
-# The offical place for these files is at:
+# The official place for these files is at:
 RELEASE ?= r1_alfa5
 OFFICIAL_INCDIR = /n/asic/projects/guinness/releases/$(RELEASE)/design/top/sw/include/
 
diff -druN linux-libre-2.6.38-gnu/arch/cris/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/cris/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/cris/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -154,12 +154,11 @@
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/lock.h>
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #define ext2_set_bit_atomic(l,n,a)   test_and_set_bit(n,a)
 #define ext2_clear_bit_atomic(l,n,a) test_and_clear_bit(n,a)
 
-#include <asm-generic/bitops/minix.h>
 #include <asm-generic/bitops/sched.h>
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/cris/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/cris/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/cris/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 #define pte_clear(mm,addr,xp)	do { pte_val(*(xp)) = 0; } while (0)
 
 #define pmd_none(x)     (!pmd_val(x))
-/* by removing the _PAGE_KERNEL bit from the comparision, the same pmd_bad
+/* by removing the _PAGE_KERNEL bit from the comparison, the same pmd_bad
  * works for both _PAGE_TABLE and _KERNPG_TABLE pmd entries.
  */
 #define	pmd_bad(x)	((pmd_val(x) & (~PAGE_MASK & ~_PAGE_KERNEL)) != _PAGE_TABLE)
diff -druN linux-libre-2.6.38-gnu/arch/cris/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/cris/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/cris/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -68,7 +68,7 @@
 #define init_thread_info	(init_thread_union.thread_info)
 
 /* thread information allocation */
-#define alloc_thread_info(tsk) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
+#define alloc_thread_info(tsk, node) ((struct thread_info *) __get_free_pages(GFP_KERNEL,1))
 #define free_thread_info(ti) free_pages((unsigned long) (ti), 1)
 
 #endif /* !__ASSEMBLY__ */
diff -druN linux-libre-2.6.38-gnu/arch/cris/include/asm/types.h linux-libre-2.6.39-gnu/arch/cris/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/cris/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,15 +16,6 @@
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide, just like our other addresses.  */
- 
-typedef u32 dma_addr_t;
-typedef u32 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/cris/Kconfig linux-libre-2.6.39-gnu/arch/cris/Kconfig
--- linux-libre-2.6.38-gnu/arch/cris/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,7 @@
 	default y
 	select HAVE_IDE
 	select HAVE_GENERIC_HARDIRQS
-	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select GENERIC_IRQ_SHOW
 
 config HZ
 	int
@@ -275,7 +275,6 @@
 	select MTD_CHAR
 	select MTD_BLOCK
 	select MTD_PARTITIONS
-	select MTD_CONCAT
 	select MTD_COMPLEX_MAPPINGS
 	help
 	  This option enables MTD mapping of flash devices.  Needed to use
@@ -296,8 +295,7 @@
 choice
 	prompt "RTC chip"
 	depends on ETRAX_RTC
-	default ETRAX_PCF8563 if ETRAX_ARCH_V32
-	default ETRAX_DS1302 if ETRAX_ARCH_V10
+	default ETRAX_DS1302
 
 config ETRAX_DS1302
 	depends on ETRAX_ARCH_V10
diff -druN linux-libre-2.6.38-gnu/arch/cris/kernel/irq.c linux-libre-2.6.39-gnu/arch/cris/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/cris/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,45 +37,6 @@
 
 #include <asm/io.h>
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	return 0;
-}
-
-
 /* called by the assembler IRQ entry functions defined in irq.h
  * to dispatch the interrupts to registered handlers
  * interrupts are disabled upon entry - depending on if the
diff -druN linux-libre-2.6.38-gnu/arch/cris/kernel/traps.c linux-libre-2.6.39-gnu/arch/cris/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/cris/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -183,7 +183,7 @@
 
 /*
  * This gets called from entry.S when the watchdog has bitten. Show something
- * similiar to an Oops dump, and if the kernel is configured to be a nice
+ * similar to an Oops dump, and if the kernel is configured to be a nice
  * doggy, then halt instead of reboot.
  */
 void
diff -druN linux-libre-2.6.38-gnu/arch/cris/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/cris/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/cris/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/cris/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,7 @@
 #endif
 	__vmlinux_end = .;		/* Last address of the physical file. */
 #ifdef CONFIG_ETRAX_ARCH_V32
-	PERCPU(PAGE_SIZE)
+	PERCPU(32, PAGE_SIZE)
 
 	.init.ramfs : {
 		INIT_RAM_FS
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/frv/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -401,13 +401,11 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #define ext2_set_bit_atomic(lock,nr,addr)	test_and_set_bit  ((nr) ^ 0x18, (addr))
 #define ext2_clear_bit_atomic(lock,nr,addr)	test_and_clear_bit((nr) ^ 0x18, (addr))
 
-#include <asm-generic/bitops/minix-le.h>
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/futex.h linux-libre-2.6.39-gnu/arch/frv/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,10 +7,11 @@
 #include <asm/errno.h>
 #include <asm/uaccess.h>
 
-extern int futex_atomic_op_inuser(int encoded_op, int __user *uaddr);
+extern int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr);
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
 	return -ENOSYS;
 }
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/pci.h linux-libre-2.6.39-gnu/arch/frv/include/asm/pci.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 #endif
 
 /*
- *	These are pretty much arbitary with the CoMEM implementation.
+ *	These are pretty much arbitrary with the CoMEM implementation.
  *	We have the whole address space to ourselves.
  */
 #define PCIBIOS_MIN_IO		0x100
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/processor.h linux-libre-2.6.39-gnu/arch/frv/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -137,7 +137,7 @@
 #define	KSTK_ESP(tsk)	((tsk)->thread.frame0->sp)
 
 /* Allocation and freeing of basic task resources. */
-extern struct task_struct *alloc_task_struct(void);
+extern struct task_struct *alloc_task_struct_node(int node);
 extern void free_task_struct(struct task_struct *p);
 
 #define cpu_relax()    barrier()
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/spr-regs.h linux-libre-2.6.39-gnu/arch/frv/include/asm/spr-regs.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/spr-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/spr-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -274,7 +274,7 @@
 #define MSR0_RD			0xc0000000	/* rounding mode */
 #define MSR0_RD_NEAREST		0x00000000	/* - nearest */
 #define MSR0_RD_ZERO		0x40000000	/* - zero */
-#define MSR0_RD_POS_INF		0x80000000	/* - postive infinity */
+#define MSR0_RD_POS_INF		0x80000000	/* - positive infinity */
 #define MSR0_RD_NEG_INF		0xc0000000	/* - negative infinity */
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/system.h linux-libre-2.6.39-gnu/arch/frv/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,21 +45,12 @@
 #define wmb()			asm volatile ("membar" : : :"memory")
 #define read_barrier_depends()	do { } while (0)
 
-#ifdef CONFIG_SMP
-#define smp_mb()			mb()
-#define smp_rmb()			rmb()
-#define smp_wmb()			wmb()
-#define smp_read_barrier_depends()	read_barrier_depends()
-#define set_mb(var, value) \
-	do { xchg(&var, (value)); } while (0)
-#else
 #define smp_mb()			barrier()
 #define smp_rmb()			barrier()
 #define smp_wmb()			barrier()
 #define smp_read_barrier_depends()	do {} while(0)
 #define set_mb(var, value) \
 	do { var = (value); barrier(); } while (0)
-#endif
 
 extern void die_if_kernel(const char *, ...) __attribute__((format(printf, 1, 2)));
 extern void free_initmem(void);
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/frv/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,8 @@
 
 #define THREAD_SIZE		8192
 
+#define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
+
 /*
  * low level task data that entry.S needs immediate access to
  * - this struct should fit entirely inside of one cache line
@@ -84,16 +86,11 @@
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-	({							\
-		struct thread_info *ret;			\
-								\
-		ret = kzalloc(THREAD_SIZE, GFP_KERNEL);		\
-								\
-		ret;						\
-	})
+#define alloc_thread_info_node(tsk, node)			\
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk)	kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(info)	kfree(info)
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/types.h linux-libre-2.6.39-gnu/arch/frv/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,14 +27,6 @@
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TYPES_H */
diff -druN linux-libre-2.6.38-gnu/arch/frv/include/asm/virtconvert.h linux-libre-2.6.39-gnu/arch/frv/include/asm/virtconvert.h
--- linux-libre-2.6.38-gnu/arch/frv/include/asm/virtconvert.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/include/asm/virtconvert.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* virtconvert.h: virtual/physical/page address convertion
+/* virtconvert.h: virtual/physical/page address conversion
  *
  * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
  * Written by David Howells (dhowells@redhat.com)
diff -druN linux-libre-2.6.38-gnu/arch/frv/Kconfig linux-libre-2.6.39-gnu/arch/frv/Kconfig
--- linux-libre-2.6.38-gnu/arch/frv/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
 	select HAVE_IRQ_WORK
 	select HAVE_PERF_EVENTS
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
 
 config ZONE_DMA
 	bool
@@ -22,6 +23,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -357,7 +362,6 @@
 
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
-	depends on !SMP
 
 source kernel/power/Kconfig
 endmenu
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/entry-table.S linux-libre-2.6.39-gnu/arch/frv/kernel/entry-table.S
--- linux-libre-2.6.38-gnu/arch/frv/kernel/entry-table.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/entry-table.S	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 	.globl		__break_kerneltrap_fixup_table
 __break_kerneltrap_fixup_table:
 
-	# handler declaration for a sofware or program interrupt
+	# handler declaration for a software or program interrupt
 .macro VECTOR_SOFTPROG tbr_tt, vec
 	.section .trap.user
 	.org		\tbr_tt
@@ -145,7 +145,7 @@
 	.long		\vec
 .endm
 
-	# handler declaration for an MMU only sofware or program interrupt
+	# handler declaration for an MMU only software or program interrupt
 .macro VECTOR_SP_MMU tbr_tt, vec
 #ifdef CONFIG_MMU
  	VECTOR_SOFTPROG	\tbr_tt, \vec
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/futex.c linux-libre-2.6.39-gnu/arch/frv/kernel/futex.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/futex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/futex.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
  * the various futex operations; MMU fault checking is ignored under no-MMU
  * conditions
  */
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -50,7 +50,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -83,7 +83,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -116,7 +116,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -149,7 +149,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr, int *_oldval)
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr, int *_oldval)
 {
 	int oldval, ret;
 
@@ -186,7 +186,7 @@
 /*
  * do the futex operations
  */
-int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -197,7 +197,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/irq.c linux-libre-2.6.39-gnu/arch/frv/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,89 +47,45 @@
 
 atomic_t irq_err_count;
 
-/*
- * Generic, controller-independent functions:
- */
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, cpu;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		char cpuname[12];
-
-		seq_printf(p, "    ");
-		for_each_present_cpu(cpu) {
-			sprintf(cpuname, "CPU%d", cpu);
-			seq_printf(p, " %10s", cpuname);
-		}
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (action) {
-			seq_printf(p, "%3d: ", i);
-			for_each_present_cpu(cpu)
-				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-			seq_printf(p, " %10s", irq_desc[i].chip->name ? : "-");
-			seq_printf(p, "  %s", action->name);
-			for (action = action->next;
-			     action;
-			     action = action->next)
-				seq_printf(p, ", %s", action->name);
-
-			seq_putc(p, '\n');
-		}
-
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
-		seq_printf(p, "Err: %10u\n", atomic_read(&irq_err_count));
-	}
-
+	seq_printf(p, "%*s: ", prec, "ERR");
+	seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
 	return 0;
 }
 
 /*
  * on-CPU PIC operations
  */
-static void frv_cpupic_ack(unsigned int irqlevel)
+static void frv_cpupic_ack(struct irq_data *d)
 {
-	__clr_RC(irqlevel);
+	__clr_RC(d->irq);
 	__clr_IRL();
 }
 
-static void frv_cpupic_mask(unsigned int irqlevel)
+static void frv_cpupic_mask(struct irq_data *d)
 {
-	__set_MASK(irqlevel);
+	__set_MASK(d->irq);
 }
 
-static void frv_cpupic_mask_ack(unsigned int irqlevel)
+static void frv_cpupic_mask_ack(struct irq_data *d)
 {
-	__set_MASK(irqlevel);
-	__clr_RC(irqlevel);
+	__set_MASK(d->irq);
+	__clr_RC(d->irq);
 	__clr_IRL();
 }
 
-static void frv_cpupic_unmask(unsigned int irqlevel)
-{
-	__clr_MASK(irqlevel);
-}
-
-static void frv_cpupic_end(unsigned int irqlevel)
+static void frv_cpupic_unmask(struct irq_data *d)
 {
-	__clr_MASK(irqlevel);
+	__clr_MASK(d->irq);
 }
 
 static struct irq_chip frv_cpu_pic = {
 	.name		= "cpu",
-	.ack		= frv_cpupic_ack,
-	.mask		= frv_cpupic_mask,
-	.mask_ack	= frv_cpupic_mask_ack,
-	.unmask		= frv_cpupic_unmask,
-	.end		= frv_cpupic_end,
+	.irq_ack	= frv_cpupic_ack,
+	.irq_mask	= frv_cpupic_mask,
+	.irq_mask_ack	= frv_cpupic_mask_ack,
+	.irq_unmask	= frv_cpupic_unmask,
 };
 
 /*
@@ -161,10 +117,10 @@
 	int level;
 
 	for (level = 1; level <= 14; level++)
-		set_irq_chip_and_handler(level, &frv_cpu_pic,
+		irq_set_chip_and_handler(level, &frv_cpu_pic,
 					 handle_level_irq);
 
-	set_irq_handler(IRQ_CPU_TIMER0, handle_edge_irq);
+	irq_set_handler(IRQ_CPU_TIMER0, handle_edge_irq);
 
 	/* set the trigger levels for internal interrupt sources
 	 * - timers all falling-edge
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/irq-mb93091.c linux-libre-2.6.39-gnu/arch/frv/kernel/irq-mb93091.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/irq-mb93091.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/irq-mb93091.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,45 +36,45 @@
 /*
  * on-motherboard FPGA PIC operations
  */
-static void frv_fpga_mask(unsigned int irq)
+static void frv_fpga_mask(struct irq_data *d)
 {
 	uint16_t imr = __get_IMR();
 
-	imr |= 1 << (irq - IRQ_BASE_FPGA);
+	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 
 	__set_IMR(imr);
 }
 
-static void frv_fpga_ack(unsigned int irq)
+static void frv_fpga_ack(struct irq_data *d)
 {
-	__clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_mask_ack(unsigned int irq)
+static void frv_fpga_mask_ack(struct irq_data *d)
 {
 	uint16_t imr = __get_IMR();
 
-	imr |= 1 << (irq - IRQ_BASE_FPGA);
+	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 	__set_IMR(imr);
 
-	__clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_unmask(unsigned int irq)
+static void frv_fpga_unmask(struct irq_data *d)
 {
 	uint16_t imr = __get_IMR();
 
-	imr &= ~(1 << (irq - IRQ_BASE_FPGA));
+	imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
 
 	__set_IMR(imr);
 }
 
 static struct irq_chip frv_fpga_pic = {
 	.name		= "mb93091",
-	.ack		= frv_fpga_ack,
-	.mask		= frv_fpga_mask,
-	.mask_ack	= frv_fpga_mask_ack,
-	.unmask		= frv_fpga_unmask,
+	.irq_ack	= frv_fpga_ack,
+	.irq_mask	= frv_fpga_mask,
+	.irq_mask_ack	= frv_fpga_mask_ack,
+	.irq_unmask	= frv_fpga_unmask,
 };
 
 /*
@@ -146,9 +146,9 @@
 	__clr_IFR(0x0000);
 
 	for (irq = IRQ_BASE_FPGA + 1; irq <= IRQ_BASE_FPGA + 14; irq++)
-		set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
+		irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_level_irq);
 
-	set_irq_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
+	irq_set_chip_and_handler(IRQ_FPGA_NMI, &frv_fpga_pic, handle_edge_irq);
 
 	/* the FPGA drives the first four external IRQ inputs on the CPU PIC */
 	setup_irq(IRQ_CPU_EXTERNAL0, &fpga_irq[0]);
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/irq-mb93093.c linux-libre-2.6.39-gnu/arch/frv/kernel/irq-mb93093.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/irq-mb93093.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/irq-mb93093.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,45 +35,44 @@
 /*
  * off-CPU FPGA PIC operations
  */
-static void frv_fpga_mask(unsigned int irq)
+static void frv_fpga_mask(struct irq_data *d)
 {
 	uint16_t imr = __get_IMR();
 
-	imr |= 1 << (irq - IRQ_BASE_FPGA);
+	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 	__set_IMR(imr);
 }
 
-static void frv_fpga_ack(unsigned int irq)
+static void frv_fpga_ack(struct irq_data *d)
 {
-	__clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_mask_ack(unsigned int irq)
+static void frv_fpga_mask_ack(struct irq_data *d)
 {
 	uint16_t imr = __get_IMR();
 
-	imr |= 1 << (irq - IRQ_BASE_FPGA);
+	imr |= 1 << (d->irq - IRQ_BASE_FPGA);
 	__set_IMR(imr);
 
-	__clr_IFR(1 << (irq - IRQ_BASE_FPGA));
+	__clr_IFR(1 << (d->irq - IRQ_BASE_FPGA));
 }
 
-static void frv_fpga_unmask(unsigned int irq)
+static void frv_fpga_unmask(struct irq_data *d)
 {
 	uint16_t imr = __get_IMR();
 
-	imr &= ~(1 << (irq - IRQ_BASE_FPGA));
+	imr &= ~(1 << (d->irq - IRQ_BASE_FPGA));
 
 	__set_IMR(imr);
 }
 
 static struct irq_chip frv_fpga_pic = {
 	.name		= "mb93093",
-	.ack		= frv_fpga_ack,
-	.mask		= frv_fpga_mask,
-	.mask_ack	= frv_fpga_mask_ack,
-	.unmask		= frv_fpga_unmask,
-	.end		= frv_fpga_end,
+	.irq_ack	= frv_fpga_ack,
+	.irq_mask	= frv_fpga_mask,
+	.irq_mask_ack	= frv_fpga_mask_ack,
+	.irq_unmask	= frv_fpga_unmask,
 };
 
 /*
@@ -94,7 +93,7 @@
 		irq = 31 - irq;
 		mask &= ~(1 << irq);
 
-		generic_irq_handle(IRQ_BASE_FPGA + irq);
+		generic_handle_irq(IRQ_BASE_FPGA + irq);
 	}
 
 	return IRQ_HANDLED;
@@ -125,7 +124,7 @@
 	__clr_IFR(0x0000);
 
 	for (irq = IRQ_BASE_FPGA + 8; irq <= IRQ_BASE_FPGA + 10; irq++)
-		set_irq_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &frv_fpga_pic, handle_edge_irq);
 
 	/* the FPGA drives external IRQ input #2 on the CPU PIC */
 	setup_irq(IRQ_CPU_EXTERNAL2, &fpga_irq[0]);
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/irq-mb93493.c linux-libre-2.6.39-gnu/arch/frv/kernel/irq-mb93493.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/irq-mb93493.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/irq-mb93493.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,46 +45,46 @@
  * daughter board PIC operations
  * - there is no way to ACK interrupts in the MB93493 chip
  */
-static void frv_mb93493_mask(unsigned int irq)
+static void frv_mb93493_mask(struct irq_data *d)
 {
 	uint32_t iqsr;
 	volatile void *piqsr;
 
-	if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+	if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
 		piqsr = __addr_MB93493_IQSR(1);
 	else
 		piqsr = __addr_MB93493_IQSR(0);
 
 	iqsr = readl(piqsr);
-	iqsr &= ~(1 << (irq - IRQ_BASE_MB93493 + 16));
+	iqsr &= ~(1 << (d->irq - IRQ_BASE_MB93493 + 16));
 	writel(iqsr, piqsr);
 }
 
-static void frv_mb93493_ack(unsigned int irq)
+static void frv_mb93493_ack(struct irq_data *d)
 {
 }
 
-static void frv_mb93493_unmask(unsigned int irq)
+static void frv_mb93493_unmask(struct irq_data *d)
 {
 	uint32_t iqsr;
 	volatile void *piqsr;
 
-	if (IRQ_ROUTING & (1 << (irq - IRQ_BASE_MB93493)))
+	if (IRQ_ROUTING & (1 << (d->irq - IRQ_BASE_MB93493)))
 		piqsr = __addr_MB93493_IQSR(1);
 	else
 		piqsr = __addr_MB93493_IQSR(0);
 
 	iqsr = readl(piqsr);
-	iqsr |= 1 << (irq - IRQ_BASE_MB93493 + 16);
+	iqsr |= 1 << (d->irq - IRQ_BASE_MB93493 + 16);
 	writel(iqsr, piqsr);
 }
 
 static struct irq_chip frv_mb93493_pic = {
 	.name		= "mb93093",
-	.ack		= frv_mb93493_ack,
-	.mask		= frv_mb93493_mask,
-	.mask_ack	= frv_mb93493_mask,
-	.unmask		= frv_mb93493_unmask,
+	.irq_ack	= frv_mb93493_ack,
+	.irq_mask	= frv_mb93493_mask,
+	.irq_mask_ack	= frv_mb93493_mask,
+	.irq_unmask	= frv_mb93493_unmask,
 };
 
 /*
@@ -139,7 +139,8 @@
 	int irq;
 
 	for (irq = IRQ_BASE_MB93493 + 0; irq <= IRQ_BASE_MB93493 + 10; irq++)
-		set_irq_chip_and_handler(irq, &frv_mb93493_pic, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &frv_mb93493_pic,
+					 handle_edge_irq);
 
 	/* the MB93493 drives external IRQ inputs on the CPU PIC */
 	setup_irq(IRQ_CPU_MB93493_0, &mb93493_irq[0]);
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/process.c linux-libre-2.6.39-gnu/arch/frv/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,9 +44,10 @@
 void (*pm_power_off)(void);
 EXPORT_SYMBOL(pm_power_off);
 
-struct task_struct *alloc_task_struct(void)
+struct task_struct *alloc_task_struct_node(int node)
 {
-	struct task_struct *p = kmalloc(THREAD_SIZE, GFP_KERNEL);
+	struct task_struct *p = kmalloc_node(THREAD_SIZE, GFP_KERNEL, node);
+
 	if (p)
 		atomic_set((atomic_t *)(p+1), 1);
 	return p;
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/time.c linux-libre-2.6.39-gnu/arch/frv/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/frv/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,21 +50,13 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 static irqreturn_t timer_interrupt(int irq, void *dummy)
 {
 	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);
+	xtime_update(1);
 
 #ifdef CONFIG_HEARTBEAT
 	static unsigned short n;
@@ -72,8 +64,6 @@
 	__set_LEDS(n);
 #endif /* CONFIG_HEARTBEAT */
 
-	write_sequnlock(&xtime_lock);
-
 	update_process_times(user_mode(get_irq_regs()));
 
 	return IRQ_HANDLED;
diff -druN linux-libre-2.6.38-gnu/arch/frv/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/frv/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/frv/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/frv/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
   _einittext = .;
 
   INIT_DATA_SECTION(8)
-  PERCPU(4096)
+  PERCPU(L1_CACHE_BYTES, 4096)
 
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
diff -druN linux-libre-2.6.38-gnu/arch/h8300/boot/compressed/Makefile linux-libre-2.6.39-gnu/arch/h8300/boot/compressed/Makefile
--- linux-libre-2.6.38-gnu/arch/h8300/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/boot/compressed/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
 #
 
 targets		:= vmlinux vmlinux.bin vmlinux.bin.gz head.o misc.o piggy.o
-EXTRA_AFLAGS	:= -traditional
+asflags-y	:= -traditional
 
 OBJECTS = $(obj)/head.o $(obj)/misc.o
 
diff -druN linux-libre-2.6.38-gnu/arch/h8300/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/h8300/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/h8300/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -200,9 +200,8 @@
 #include <asm-generic/bitops/sched.h>
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/h8300/include/asm/types.h linux-libre-2.6.39-gnu/arch/h8300/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/h8300/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,10 +22,6 @@
 
 #define BITS_PER_LONG 32
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
 #endif /* __KERNEL__ */
 
 #endif /* __ASSEMBLY__ */
diff -druN linux-libre-2.6.38-gnu/arch/h8300/Kconfig linux-libre-2.6.39-gnu/arch/h8300/Kconfig
--- linux-libre-2.6.38-gnu/arch/h8300/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
 	default y
 	select HAVE_IDE
 	select HAVE_GENERIC_HARDIRQS
-	select GENERIC_HARDIRQS_NO_DEPRECATED
+	select GENERIC_IRQ_SHOW
 
 config SYMBOL_PREFIX
 	string
@@ -45,6 +45,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
diff -druN linux-libre-2.6.38-gnu/arch/h8300/kernel/irq.c linux-libre-2.6.39-gnu/arch/h8300/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/h8300/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -155,7 +155,7 @@
 	setup_vector();
 
 	for (c = 0; c < NR_IRQS; c++)
-		set_irq_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
+		irq_set_chip_and_handler(c, &h8300irq_chip, handle_simple_irq);
 }
 
 asmlinkage void do_IRQ(int irq)
@@ -164,34 +164,3 @@
 	generic_handle_irq(irq);
 	irq_exit();
 }
-
-#if defined(CONFIG_PROC_FS)
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0)
-		seq_puts(p, "           CPU0");
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto unlock;
-		seq_printf(p, "%3d: ",i);
-		seq_printf(p, "%10u ", kstat_irqs(i));
-		seq_printf(p, " %14s", irq_desc[i].irq_data.chip->name);
-		seq_printf(p, "-%-8s", irq_desc[i].name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-		seq_putc(p, '\n');
-unlock:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	return 0;
-}
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/h8300/kernel/time.c linux-libre-2.6.39-gnu/arch/h8300/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/h8300/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,9 +35,7 @@
 {
 	if (current->pid)
 		profile_tick(CPU_PROFILING);
-	write_seqlock(&xtime_lock);
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 	update_process_times(user_mode(get_irq_regs()));
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/h8300/kernel/timer/timer8.c linux-libre-2.6.39-gnu/arch/h8300/kernel/timer/timer8.c
--- linux-libre-2.6.38-gnu/arch/h8300/kernel/timer/timer8.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/h8300/kernel/timer/timer8.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
diff -druN linux-libre-2.6.38-gnu/arch/ia64/configs/generic_defconfig linux-libre-2.6.39-gnu/arch/ia64/configs/generic_defconfig
--- linux-libre-2.6.38-gnu/arch/ia64/configs/generic_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/configs/generic_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -233,3 +233,4 @@
 CONFIG_CRYPTO_MD5=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 CONFIG_CRC_T10DIF=y
+CONFIG_MISC_DEVICES=y
diff -druN linux-libre-2.6.38-gnu/arch/ia64/configs/gensparse_defconfig linux-libre-2.6.39-gnu/arch/ia64/configs/gensparse_defconfig
--- linux-libre-2.6.38-gnu/arch/ia64/configs/gensparse_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/configs/gensparse_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -208,3 +208,4 @@
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_MUTEXES=y
 CONFIG_CRYPTO_MD5=y
+CONFIG_MISC_DEVICES=y
diff -druN linux-libre-2.6.38-gnu/arch/ia64/hp/sim/hpsim_irq.c linux-libre-2.6.39-gnu/arch/ia64/hp/sim/hpsim_irq.c
--- linux-libre-2.6.38-gnu/arch/ia64/hp/sim/hpsim_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/hp/sim/hpsim_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,42 +11,41 @@
 #include <linux/irq.h>
 
 static unsigned int
-hpsim_irq_startup (unsigned int irq)
+hpsim_irq_startup(struct irq_data *data)
 {
 	return 0;
 }
 
 static void
-hpsim_irq_noop (unsigned int irq)
+hpsim_irq_noop(struct irq_data *data)
 {
 }
 
 static int
-hpsim_set_affinity_noop(unsigned int a, const struct cpumask *b)
+hpsim_set_affinity_noop(struct irq_data *d, const struct cpumask *b, bool f)
 {
 	return 0;
 }
 
 static struct irq_chip irq_type_hp_sim = {
-	.name =		"hpsim",
-	.startup =	hpsim_irq_startup,
-	.shutdown =	hpsim_irq_noop,
-	.enable =	hpsim_irq_noop,
-	.disable =	hpsim_irq_noop,
-	.ack =		hpsim_irq_noop,
-	.end =		hpsim_irq_noop,
-	.set_affinity =	hpsim_set_affinity_noop,
+	.name =			"hpsim",
+	.irq_startup =		hpsim_irq_startup,
+	.irq_shutdown =		hpsim_irq_noop,
+	.irq_enable =		hpsim_irq_noop,
+	.irq_disable =		hpsim_irq_noop,
+	.irq_ack =		hpsim_irq_noop,
+	.irq_set_affinity =	hpsim_set_affinity_noop,
 };
 
 void __init
 hpsim_irq_init (void)
 {
-	struct irq_desc *idesc;
 	int i;
 
-	for (i = 0; i < NR_IRQS; ++i) {
-		idesc = irq_desc + i;
-		if (idesc->chip == &no_irq_chip)
-			idesc->chip = &irq_type_hp_sim;
+	for_each_active_irq(i) {
+		struct irq_chip *chip = irq_get_chip(i);
+
+		if (chip == &no_irq_chip)
+			irq_set_chip(i, &irq_type_hp_sim);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/ia64/hp/sim/simserial.c linux-libre-2.6.39-gnu/arch/ia64/hp/sim/simserial.c
--- linux-libre-2.6.38-gnu/arch/ia64/hp/sim/simserial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/hp/sim/simserial.c	2011-05-19 00:06:34.000000000 -0400
@@ -390,8 +390,7 @@
 }
 
 
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
+static int rs_ioctl(struct tty_struct *tty, unsigned int cmd, unsigned long arg)
 {
 	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
 	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/acpi.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/acpi.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/acpi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/acpi.h	2011-05-19 00:06:34.000000000 -0400
@@ -128,9 +128,9 @@
 int acpi_request_vector (u32 int_type);
 int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
 
-/* routines for saving/restoring kernel state */
-extern int acpi_save_state_mem(void);
-extern void acpi_restore_state_mem(void);
+/* Low-level suspend routine. */
+extern int acpi_suspend_lowlevel(void);
+
 extern unsigned long acpi_wakeup_address;
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -456,12 +456,11 @@
 
 #ifdef __KERNEL__
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #define ext2_set_bit_atomic(l,n,a)	test_and_set_bit(n,a)
 #define ext2_clear_bit_atomic(l,n,a)	test_and_clear_bit(n,a)
 
-#include <asm-generic/bitops/minix.h>
 #include <asm-generic/bitops/sched.h>
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/dma-mapping.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/dma-mapping.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/dma-mapping.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/dma-mapping.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,8 @@
 
 #define ARCH_HAS_DMA_GET_REQUIRED_MASK
 
+#define DMA_ERROR_CODE 0
+
 extern struct dma_map_ops *dma_ops;
 extern struct ia64_machine_vector ia64_mv;
 extern void set_iommu_machvec(void);
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/futex.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
 } while (0)
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -56,7 +56,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -100,23 +100,26 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	{
-		register unsigned long r8 __asm ("r8");
+		register unsigned long r8 __asm ("r8") = 0;
+		unsigned long prev;
 		__asm__ __volatile__(
 			"	mf;;					\n"
 			"	mov ar.ccv=%3;;				\n"
 			"[1:]	cmpxchg4.acq %0=[%1],%2,ar.ccv		\n"
 			"	.xdata4 \"__ex_table\", 1b-., 2f-.	\n"
 			"[2:]"
-			: "=r" (r8)
+			: "=r" (prev)
 			: "r" (uaddr), "r" (newval),
 			  "rO" ((long) (unsigned) oldval)
 			: "memory");
+		*uval = prev;
 		return r8;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/hw_irq.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/hw_irq.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/hw_irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/hw_irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -151,9 +151,6 @@
 /*
  * Default implementations for the irq-descriptor API:
  */
-
-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.38-gnu/arch/ia64/include/asm/pal.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/pal.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/pal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/pal.h	2011-05-19 00:06:34.000000000 -0400
@@ -1669,7 +1669,7 @@
 } pal_vp_info_u_t;
 
 /*
- * Returns infomation about virtual processor features
+ * Returns information about virtual processor features
  */
 static inline s64
 ia64_pal_vp_info (u64 feature_set, u64 vp_buffer, u64 *vp_info, u64 *vmm_id)
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/perfmon_default_smpl.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/perfmon_default_smpl.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/perfmon_default_smpl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/perfmon_default_smpl.h	2011-05-19 00:06:34.000000000 -0400
@@ -67,8 +67,8 @@
         unsigned long   ip;                     /* where did the overflow interrupt happened  */
         unsigned long   tstamp;                 /* ar.itc when entering perfmon intr. handler */
 
-        unsigned short  cpu;                    /* cpu on which the overflow occured */
-        unsigned short  set;                    /* event set active when overflow ocurred   */
+        unsigned short  cpu;                    /* cpu on which the overflow occurred */
+        unsigned short  set;                    /* event set active when overflow occurred   */
         int    		tgid;              	/* thread group id (for NPTL, this is getpid()) */
 } pfm_default_smpl_entry_t;
 
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/perfmon.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/perfmon.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/perfmon.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/perfmon.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 #define _ASM_IA64_PERFMON_H
 
 /*
- * perfmon comamnds supported on all CPU models
+ * perfmon commands supported on all CPU models
  */
 #define PFM_WRITE_PMCS		0x01
 #define PFM_WRITE_PMDS		0x02
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,20 +25,8 @@
 #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
 #endif
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
 #include <asm/intrinsics.h>
 
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	signed long		count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-};
-
 #define RWSEM_UNLOCKED_VALUE		__IA64_UL_CONST(0x0000000000000000)
 #define RWSEM_ACTIVE_BIAS		(1L)
 #define RWSEM_ACTIVE_MASK		(0xffffffffL)
@@ -46,26 +34,6 @@
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-	  LIST_HEAD_INIT((name).wait_list) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-static inline void
-init_rwsem (struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
-
 /*
  * lock for reading
  */
@@ -174,9 +142,4 @@
 #define rwsem_atomic_add(delta, sem)	atomic64_add(delta, (atomic64_t *)(&(sem)->count))
 #define rwsem_atomic_update(delta, sem)	atomic64_add_return(delta, (atomic64_t *)(&(sem)->count))
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* _ASM_IA64_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/sn/bte.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/sn/bte.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/sn/bte.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/sn/bte.h	2011-05-19 00:06:34.000000000 -0400
@@ -216,7 +216,7 @@
 	bte_copy(0, dest, len, ((mode) | BTE_ZERO_FILL), notification)
 
 /*
- * The following is the prefered way of calling bte_unaligned_copy
+ * The following is the preferred way of calling bte_unaligned_copy
  * If the copy is fully cache line aligned, then bte_copy is
  * used instead.  Since bte_copy is inlined, this saves a call
  * stack.  NOTE: bte_copy is called synchronously and does block
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/sn/shubio.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/sn/shubio.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/sn/shubio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/sn/shubio.h	2011-05-19 00:06:34.000000000 -0400
@@ -1383,7 +1383,7 @@
  * response is capture in IXSM and IXSS, and IXSS[VALID] is set. The    *
  * errant header is thereby captured, and no further spurious read      *
  * respones are captured until IXSS[VALID] is cleared by setting the    *
- * appropriate bit in IECLR.Everytime a spurious read response is       *
+ * appropriate bit in IECLR. Every time a spurious read response is     *
  * detected, the SPUR_RD bit of the PRB corresponding to the incoming   *
  * message's SIDN field is set. This always happens, regarless of       *
  * whether a header is captured. The programmer should check            *
@@ -2738,7 +2738,7 @@
 /************************************************************************
  *									*
  * The following defines which were not formed into structures are	*
- * probably indentical to another register, and the name of the		*
+ * probably identical to another register, and the name of the		*
  * register is provided against each of these registers. This		*
  * information needs to be checked carefully				*
  *									*
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/sn/shub_mmr.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/sn/shub_mmr.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/sn/shub_mmr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/sn/shub_mmr.h	2011-05-19 00:06:34.000000000 -0400
@@ -459,7 +459,7 @@
 /* ==================================================================== */
 /* Some MMRs are functionally identical (or close enough) on both SHUB1 */
 /* and SHUB2 that it makes sense to define a geberic name for the MMR.  */
-/* It is acceptible to use (for example) SH_IPI_INT to reference the    */
+/* It is acceptable to use (for example) SH_IPI_INT to reference the    */
 /* the IPI MMR. The value of SH_IPI_INT is determined at runtime based  */
 /* on the type of the SHUB. Do not use these #defines in performance    */
 /* critical code  or loops - there is a small performance penalty.      */
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -59,11 +59,12 @@
 #ifndef ASM_OFFSETS_C
 /* how to get the thread information struct from C */
 #define current_thread_info()	((struct thread_info *) ((char *) current + IA64_TASK_SIZE))
-#define alloc_thread_info(tsk)	((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
+#define alloc_thread_info_node(tsk, node)	\
+		((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
 #define task_thread_info(tsk)	((struct thread_info *) ((char *) (tsk) + IA64_TASK_SIZE))
 #else
 #define current_thread_info()	((struct thread_info *) 0)
-#define alloc_thread_info(tsk)	((struct thread_info *) 0)
+#define alloc_thread_info_node(tsk, node)	((struct thread_info *) 0)
 #define task_thread_info(tsk)	((struct thread_info *) 0)
 #endif
 #define free_thread_info(ti)	/* nothing */
@@ -84,7 +85,14 @@
 #define end_of_stack(p) (unsigned long *)((void *)(p) + IA64_RBS_OFFSET)
 
 #define __HAVE_ARCH_TASK_STRUCT_ALLOCATOR
-#define alloc_task_struct()	((struct task_struct *)__get_free_pages(GFP_KERNEL | __GFP_COMP, KERNEL_STACK_SIZE_ORDER))
+#define alloc_task_struct_node(node)						\
+({										\
+	struct page *page = alloc_pages_node(node, GFP_KERNEL | __GFP_COMP,	\
+					     KERNEL_STACK_SIZE_ORDER);		\
+	struct task_struct *ret = page ? page_address(page) : NULL;		\
+										\
+	ret;									\
+})
 #define free_task_struct(tsk)	free_pages((unsigned long) (tsk), KERNEL_STACK_SIZE_ORDER)
 
 #endif /* !__ASSEMBLY */
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/types.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,9 +40,6 @@
 	unsigned long gp;
 };
 
-/* DMA addresses are 64-bits wide, in general.  */
-typedef u64 dma_addr_t;
-
 # endif /* __KERNEL__ */
 #endif /* !__ASSEMBLY__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -315,11 +315,15 @@
 #define __NR_fanotify_init		1323
 #define __NR_fanotify_mark		1324
 #define __NR_prlimit64			1325
+#define __NR_name_to_handle_at		1326
+#define __NR_open_by_handle_at  	1327
+#define __NR_clock_adjtime		1328
+#define __NR_syncfs			1329
 
 #ifdef __KERNEL__
 
 
-#define NR_syscalls			302 /* length of syscall table */
+#define NR_syscalls			306 /* length of syscall table */
 
 /*
  * The following defines stop scripts/checksyscalls.sh from complaining about
diff -druN linux-libre-2.6.38-gnu/arch/ia64/include/asm/xen/hypercall.h linux-libre-2.6.39-gnu/arch/ia64/include/asm/xen/hypercall.h
--- linux-libre-2.6.38-gnu/arch/ia64/include/asm/xen/hypercall.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/include/asm/xen/hypercall.h	2011-05-19 00:06:34.000000000 -0400
@@ -107,7 +107,7 @@
 static inline int
 xencomm_arch_hypercall_sched_op(int cmd, struct xencomm_handle *arg)
 {
-	return _hypercall2(int, sched_op_new, cmd, arg);
+	return _hypercall2(int, sched_op, cmd, arg);
 }
 
 static inline long
diff -druN linux-libre-2.6.38-gnu/arch/ia64/Kconfig linux-libre-2.6.39-gnu/arch/ia64/Kconfig
--- linux-libre-2.6.38-gnu/arch/ia64/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
 	select IRQ_PER_CPU
+	select GENERIC_IRQ_SHOW
 	default y
 	help
 	  The Itanium Processor Family is Intel's 64-bit successor to
@@ -413,11 +414,11 @@
 	support. 
 
 config FORCE_CPEI_RETARGET
-	bool "Force assumption that CPEI can be re-targetted"
+	bool "Force assumption that CPEI can be re-targeted"
 	depends on PERMIT_BSP_REMOVE
 	default n
 	---help---
-	Say Y if you need to force the assumption that CPEI can be re-targetted to
+	Say Y if you need to force the assumption that CPEI can be re-targeted to
 	any cpu in the system. This hint is available via ACPI 3.0 specifications.
 	Tiger4 systems are capable of re-directing CPEI to any CPU other than BSP.
 	This option it useful to enable this feature on older BIOS's as well.
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/acpi.c linux-libre-2.6.39-gnu/arch/ia64/kernel/acpi.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -803,7 +803,7 @@
  *  ACPI based hotplug CPU support
  */
 #ifdef CONFIG_ACPI_HOTPLUG_CPU
-static
+static __cpuinit
 int acpi_map_cpu2node(acpi_handle handle, int cpu, int physid)
 {
 #ifdef CONFIG_ACPI_NUMA
@@ -878,7 +878,7 @@
 		set_cpu_possible(i, true);
 }
 
-int acpi_map_lsapic(acpi_handle handle, int *pcpu)
+static int __cpuinit _acpi_map_lsapic(acpi_handle handle, int *pcpu)
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *obj;
@@ -929,6 +929,11 @@
 	return (0);
 }
 
+/* wrapper to silence section mismatch warning */
+int __ref acpi_map_lsapic(acpi_handle handle, int *pcpu)
+{
+	return _acpi_map_lsapic(handle, pcpu);
+}
 EXPORT_SYMBOL(acpi_map_lsapic);
 
 int acpi_unmap_lsapic(int cpu)
@@ -1034,18 +1039,8 @@
 EXPORT_SYMBOL(acpi_unregister_ioapic);
 
 /*
- * acpi_save_state_mem() - save kernel state
+ * acpi_suspend_lowlevel() - save kernel state and suspend.
  *
  * TBD when when IA64 starts to support suspend...
  */
-int acpi_save_state_mem(void) { return 0; } 
-
-/*
- * acpi_restore_state()
- */
-void acpi_restore_state_mem(void) {}
-
-/*
- * do_suspend_lowlevel()
- */
-void do_suspend_lowlevel(void) {}
+int acpi_suspend_lowlevel(void) { return 0; }
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/crash_dump.c linux-libre-2.6.39-gnu/arch/ia64/kernel/crash_dump.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/crash_dump.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/crash_dump.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,9 +13,6 @@
 #include <asm/page.h>
 #include <asm/uaccess.h>
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/cyclone.c linux-libre-2.6.39-gnu/arch/ia64/kernel/cyclone.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/cyclone.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/cyclone.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
         .rating         = 300,
         .read           = read_cyclone,
         .mask           = (1LL << 40) - 1,
-        .mult           = 0, /*to be caluclated*/
+        .mult           = 0, /*to be calculated*/
         .shift          = 16,
         .flags          = CLOCK_SOURCE_IS_CONTINUOUS,
 };
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/efi.c linux-libre-2.6.39-gnu/arch/ia64/kernel/efi.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/efi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/efi.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
  */
 #include <linux/module.h>
 #include <linux/bootmem.h>
+#include <linux/crash_dump.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/types.h>
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/entry.S linux-libre-2.6.39-gnu/arch/ia64/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -1771,6 +1771,10 @@
 	data8 sys_fanotify_init
 	data8 sys_fanotify_mark
 	data8 sys_prlimit64			// 1325
+	data8 sys_name_to_handle_at
+	data8 sys_open_by_handle_at
+	data8 sys_clock_adjtime
+	data8 sys_syncfs
 
 	.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.38-gnu/arch/ia64/kernel/iosapic.c linux-libre-2.6.39-gnu/arch/ia64/kernel/iosapic.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/iosapic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/iosapic.c	2011-05-19 00:06:34.000000000 -0400
@@ -257,7 +257,7 @@
 }
 
 static void
-nop (unsigned int irq)
+nop (struct irq_data *data)
 {
 	/* do nothing... */
 }
@@ -287,8 +287,9 @@
 #endif
 
 static void
-mask_irq (unsigned int irq)
+mask_irq (struct irq_data *data)
 {
+	unsigned int irq = data->irq;
 	u32 low32;
 	int rte_index;
 	struct iosapic_rte_info *rte;
@@ -305,8 +306,9 @@
 }
 
 static void
-unmask_irq (unsigned int irq)
+unmask_irq (struct irq_data *data)
 {
+	unsigned int irq = data->irq;
 	u32 low32;
 	int rte_index;
 	struct iosapic_rte_info *rte;
@@ -323,9 +325,11 @@
 
 
 static int
-iosapic_set_affinity(unsigned int irq, const struct cpumask *mask)
+iosapic_set_affinity(struct irq_data *data, const struct cpumask *mask,
+		     bool force)
 {
 #ifdef CONFIG_SMP
+	unsigned int irq = data->irq;
 	u32 high32, low32;
 	int cpu, dest, rte_index;
 	int redir = (irq & IA64_IRQ_REDIRECTED) ? 1 : 0;
@@ -379,32 +383,33 @@
  */
 
 static unsigned int
-iosapic_startup_level_irq (unsigned int irq)
+iosapic_startup_level_irq (struct irq_data *data)
 {
-	unmask_irq(irq);
+	unmask_irq(data);
 	return 0;
 }
 
 static void
-iosapic_unmask_level_irq (unsigned int irq)
+iosapic_unmask_level_irq (struct irq_data *data)
 {
+	unsigned int irq = data->irq;
 	ia64_vector vec = irq_to_vector(irq);
 	struct iosapic_rte_info *rte;
 	int do_unmask_irq = 0;
 
 	irq_complete_move(irq);
-	if (unlikely(irq_desc[irq].status & IRQ_MOVE_PENDING)) {
+	if (unlikely(irqd_is_setaffinity_pending(data))) {
 		do_unmask_irq = 1;
-		mask_irq(irq);
+		mask_irq(data);
 	} else
-		unmask_irq(irq);
+		unmask_irq(data);
 
 	list_for_each_entry(rte, &iosapic_intr_info[irq].rtes, rte_list)
 		iosapic_eoi(rte->iosapic->addr, vec);
 
 	if (unlikely(do_unmask_irq)) {
-		move_masked_irq(irq);
-		unmask_irq(irq);
+		irq_move_masked_irq(data);
+		unmask_irq(data);
 	}
 }
 
@@ -414,15 +419,15 @@
 #define iosapic_ack_level_irq		nop
 
 static struct irq_chip irq_type_iosapic_level = {
-	.name =		"IO-SAPIC-level",
-	.startup =	iosapic_startup_level_irq,
-	.shutdown =	iosapic_shutdown_level_irq,
-	.enable =	iosapic_enable_level_irq,
-	.disable =	iosapic_disable_level_irq,
-	.ack =		iosapic_ack_level_irq,
-	.mask =		mask_irq,
-	.unmask =	iosapic_unmask_level_irq,
-	.set_affinity =	iosapic_set_affinity
+	.name =			"IO-SAPIC-level",
+	.irq_startup =		iosapic_startup_level_irq,
+	.irq_shutdown =		iosapic_shutdown_level_irq,
+	.irq_enable =		iosapic_enable_level_irq,
+	.irq_disable =		iosapic_disable_level_irq,
+	.irq_ack =		iosapic_ack_level_irq,
+	.irq_mask =		mask_irq,
+	.irq_unmask =		iosapic_unmask_level_irq,
+	.irq_set_affinity =	iosapic_set_affinity
 };
 
 /*
@@ -430,9 +435,9 @@
  */
 
 static unsigned int
-iosapic_startup_edge_irq (unsigned int irq)
+iosapic_startup_edge_irq (struct irq_data *data)
 {
-	unmask_irq(irq);
+	unmask_irq(data);
 	/*
 	 * IOSAPIC simply drops interrupts pended while the
 	 * corresponding pin was masked, so we can't know if an
@@ -442,37 +447,25 @@
 }
 
 static void
-iosapic_ack_edge_irq (unsigned int irq)
+iosapic_ack_edge_irq (struct irq_data *data)
 {
-	struct irq_desc *idesc = irq_desc + irq;
-
-	irq_complete_move(irq);
-	move_native_irq(irq);
-	/*
-	 * Once we have recorded IRQ_PENDING already, we can mask the
-	 * interrupt for real. This prevents IRQ storms from unhandled
-	 * devices.
-	 */
-	if ((idesc->status & (IRQ_PENDING|IRQ_DISABLED)) ==
-	    (IRQ_PENDING|IRQ_DISABLED))
-		mask_irq(irq);
+	irq_complete_move(data->irq);
+	irq_move_irq(data);
 }
 
 #define iosapic_enable_edge_irq		unmask_irq
 #define iosapic_disable_edge_irq	nop
-#define iosapic_end_edge_irq		nop
 
 static struct irq_chip irq_type_iosapic_edge = {
-	.name =		"IO-SAPIC-edge",
-	.startup =	iosapic_startup_edge_irq,
-	.shutdown =	iosapic_disable_edge_irq,
-	.enable =	iosapic_enable_edge_irq,
-	.disable =	iosapic_disable_edge_irq,
-	.ack =		iosapic_ack_edge_irq,
-	.end =		iosapic_end_edge_irq,
-	.mask =		mask_irq,
-	.unmask =	unmask_irq,
-	.set_affinity =	iosapic_set_affinity
+	.name =			"IO-SAPIC-edge",
+	.irq_startup =		iosapic_startup_edge_irq,
+	.irq_shutdown =		iosapic_disable_edge_irq,
+	.irq_enable =		iosapic_enable_edge_irq,
+	.irq_disable =		iosapic_disable_edge_irq,
+	.irq_ack =		iosapic_ack_edge_irq,
+	.irq_mask =		mask_irq,
+	.irq_unmask =		unmask_irq,
+	.irq_set_affinity =	iosapic_set_affinity
 };
 
 static unsigned int
@@ -562,8 +555,7 @@
 register_intr (unsigned int gsi, int irq, unsigned char delivery,
 	       unsigned long polarity, unsigned long trigger)
 {
-	struct irq_desc *idesc;
-	struct irq_chip *irq_type;
+	struct irq_chip *chip, *irq_type;
 	int index;
 	struct iosapic_rte_info *rte;
 
@@ -610,19 +602,18 @@
 
 	irq_type = iosapic_get_irq_chip(trigger);
 
-	idesc = irq_desc + irq;
-	if (irq_type != NULL && idesc->chip != irq_type) {
-		if (idesc->chip != &no_irq_chip)
+	chip = irq_get_chip(irq);
+	if (irq_type != NULL && chip != irq_type) {
+		if (chip != &no_irq_chip)
 			printk(KERN_WARNING
 			       "%s: changing vector %d from %s to %s\n",
 			       __func__, irq_to_vector(irq),
-			       idesc->chip->name, irq_type->name);
-		idesc->chip = irq_type;
+			       chip->name, irq_type->name);
+		chip = irq_type;
 	}
-	if (trigger == IOSAPIC_EDGE)
-		__set_irq_handler_unlocked(irq, handle_edge_irq);
-	else
-		__set_irq_handler_unlocked(irq, handle_level_irq);
+	__irq_set_chip_handler_name_locked(irq, chip, trigger == IOSAPIC_EDGE ?
+					   handle_edge_irq : handle_level_irq,
+					   NULL);
 	return 0;
 }
 
@@ -732,6 +723,7 @@
 	struct iosapic_rte_info *rte;
 	u32 low32;
 	unsigned char dmode;
+	struct irq_desc *desc;
 
 	/*
 	 * If this GSI has already been registered (i.e., it's a
@@ -759,12 +751,13 @@
 			goto unlock_iosapic_lock;
 	}
 
-	raw_spin_lock(&irq_desc[irq].lock);
+	desc = irq_to_desc(irq);
+	raw_spin_lock(&desc->lock);
 	dest = get_target_cpu(gsi, irq);
 	dmode = choose_dmode();
 	err = register_intr(gsi, irq, dmode, polarity, trigger);
 	if (err < 0) {
-		raw_spin_unlock(&irq_desc[irq].lock);
+		raw_spin_unlock(&desc->lock);
 		irq = err;
 		goto unlock_iosapic_lock;
 	}
@@ -783,7 +776,7 @@
 	       (polarity == IOSAPIC_POL_HIGH ? "high" : "low"),
 	       cpu_logical_id(dest), dest, irq_to_vector(irq));
 
-	raw_spin_unlock(&irq_desc[irq].lock);
+	raw_spin_unlock(&desc->lock);
  unlock_iosapic_lock:
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 	return irq;
@@ -794,7 +787,6 @@
 {
 	unsigned long flags;
 	int irq, index;
-	struct irq_desc *idesc;
 	u32 low32;
 	unsigned long trigger, polarity;
 	unsigned int dest;
@@ -824,7 +816,6 @@
 	if (--rte->refcnt > 0)
 		goto out;
 
-	idesc = irq_desc + irq;
 	rte->refcnt = NO_REF_RTE;
 
 	/* Mask the interrupt */
@@ -848,7 +839,7 @@
 	if (iosapic_intr_info[irq].count == 0) {
 #ifdef CONFIG_SMP
 		/* Clear affinity */
-		cpumask_setall(idesc->affinity);
+		cpumask_setall(irq_get_irq_data(irq)->affinity);
 #endif
 		/* Clear the interrupt information */
 		iosapic_intr_info[irq].dest = 0;
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/irq.c linux-libre-2.6.39-gnu/arch/ia64/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,47 +53,9 @@
 /*
  * /proc/interrupts printing:
  */
-
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		char cpuname[16];
-		seq_printf(p, "     ");
-		for_each_online_cpu(j) {
-			snprintf(cpuname, 10, "CPU%d", j);
-			seq_printf(p, "%10s ", cpuname);
-		}
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j) {
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-		}
-#endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS)
-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
+	seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
 	return 0;
 }
 
@@ -103,7 +65,7 @@
 void set_irq_affinity_info (unsigned int irq, int hwid, int redir)
 {
 	if (irq < NR_IRQS) {
-		cpumask_copy(irq_desc[irq].affinity,
+		cpumask_copy(irq_get_irq_data(irq)->affinity,
 			     cpumask_of(cpu_logical_id(hwid)));
 		irq_redir[irq] = (char) (redir & 0xff);
 	}
@@ -130,13 +92,14 @@
  */
 static void migrate_irqs(void)
 {
-	struct irq_desc *desc;
 	int 		irq, new_cpu;
 
 	for (irq=0; irq < NR_IRQS; irq++) {
-		desc = irq_desc + irq;
+		struct irq_desc *desc = irq_to_desc(irq);
+		struct irq_data *data = irq_desc_get_irq_data(desc);
+		struct irq_chip *chip = irq_data_get_irq_chip(data);
 
-		if (desc->status == IRQ_DISABLED)
+		if (irqd_irq_disabled(data))
 			continue;
 
 		/*
@@ -145,10 +108,10 @@
 		 * tell CPU not to respond to these local intr sources.
 		 * such as ITV,CPEI,MCA etc.
 		 */
-		if (desc->status == IRQ_PER_CPU)
+		if (irqd_is_per_cpu(data))
 			continue;
 
-		if (cpumask_any_and(irq_desc[irq].affinity, cpu_online_mask)
+		if (cpumask_any_and(data->affinity, cpu_online_mask)
 		    >= nr_cpu_ids) {
 			/*
 			 * Save it for phase 2 processing
@@ -160,16 +123,16 @@
 			/*
 			 * Al three are essential, currently WARN_ON.. maybe panic?
 			 */
-			if (desc->chip && desc->chip->disable &&
-				desc->chip->enable && desc->chip->set_affinity) {
-				desc->chip->disable(irq);
-				desc->chip->set_affinity(irq,
-							 cpumask_of(new_cpu));
-				desc->chip->enable(irq);
+			if (chip && chip->irq_disable &&
+				chip->irq_enable && chip->irq_set_affinity) {
+				chip->irq_disable(data);
+				chip->irq_set_affinity(data,
+						       cpumask_of(new_cpu), false);
+				chip->irq_enable(data);
 			} else {
-				WARN_ON((!(desc->chip) || !(desc->chip->disable) ||
-						!(desc->chip->enable) ||
-						!(desc->chip->set_affinity)));
+				WARN_ON((!chip || !chip->irq_disable ||
+					 !chip->irq_enable ||
+					 !chip->irq_set_affinity));
 			}
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/irq_ia64.c linux-libre-2.6.39-gnu/arch/ia64/kernel/irq_ia64.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/irq_ia64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/irq_ia64.c	2011-05-19 00:06:34.000000000 -0400
@@ -343,7 +343,7 @@
 		if (irq < 0)
 			continue;
 
-		desc = irq_desc + irq;
+		desc = irq_to_desc(irq);
 		cfg = irq_cfg + irq;
 		raw_spin_lock(&desc->lock);
 		if (!cfg->move_cleanup_count)
@@ -626,17 +626,15 @@
 void
 ia64_native_register_percpu_irq (ia64_vector vec, struct irqaction *action)
 {
-	struct irq_desc *desc;
 	unsigned int irq;
 
 	irq = vec;
 	BUG_ON(bind_irq_vector(irq, vec, CPU_MASK_ALL));
-	desc = irq_desc + irq;
-	desc->status |= IRQ_PER_CPU;
-	set_irq_chip(irq, &irq_type_ia64_lsapic);
+	irq_set_status_flags(irq, IRQ_PER_CPU);
+	irq_set_chip(irq, &irq_type_ia64_lsapic);
 	if (action)
 		setup_irq(irq, action);
-	set_irq_handler(irq, handle_percpu_irq);
+	irq_set_handler(irq, handle_percpu_irq);
 }
 
 void __init
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/irq_lsapic.c linux-libre-2.6.39-gnu/arch/ia64/kernel/irq_lsapic.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/irq_lsapic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/irq_lsapic.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,31 +15,30 @@
 #include <linux/irq.h>
 
 static unsigned int
-lsapic_noop_startup (unsigned int irq)
+lsapic_noop_startup (struct irq_data *data)
 {
 	return 0;
 }
 
 static void
-lsapic_noop (unsigned int irq)
+lsapic_noop (struct irq_data *data)
 {
 	/* nothing to do... */
 }
 
-static int lsapic_retrigger(unsigned int irq)
+static int lsapic_retrigger(struct irq_data *data)
 {
-	ia64_resend_irq(irq);
+	ia64_resend_irq(data->irq);
 
 	return 1;
 }
 
 struct irq_chip irq_type_ia64_lsapic = {
-	.name =		"LSAPIC",
-	.startup =	lsapic_noop_startup,
-	.shutdown =	lsapic_noop,
-	.enable =	lsapic_noop,
-	.disable =	lsapic_noop,
-	.ack =		lsapic_noop,
-	.end =		lsapic_noop,
-	.retrigger =	lsapic_retrigger,
+	.name =			"LSAPIC",
+	.irq_startup =		lsapic_noop_startup,
+	.irq_shutdown =		lsapic_noop,
+	.irq_enable =		lsapic_noop,
+	.irq_disable =		lsapic_noop,
+	.irq_ack =		lsapic_noop,
+	.irq_retrigger =	lsapic_retrigger,
 };
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/mca.c linux-libre-2.6.39-gnu/arch/ia64/kernel/mca.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/mca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/mca.c	2011-05-19 00:06:34.000000000 -0400
@@ -582,6 +582,8 @@
 	/* Get the CPE error record and log it */
 	ia64_mca_log_sal_error_record(SAL_INFO_TYPE_CPE);
 
+	local_irq_disable();
+
 	return IRQ_HANDLED;
 }
 
@@ -1859,7 +1861,8 @@
 			data = mca_bootmem();
 			first_time = 0;
 		} else
-			data = __get_free_pages(GFP_KERNEL, get_order(sz));
+			data = (void *)__get_free_pages(GFP_KERNEL,
+							get_order(sz));
 		if (!data)
 			panic("Could not allocate MCA memory for cpu %d\n",
 					cpu);
@@ -2122,7 +2125,6 @@
 	cpe_poll_timer.function = ia64_mca_cpe_poll;
 
 	{
-		struct irq_desc *desc;
 		unsigned int irq;
 
 		if (cpe_vector >= 0) {
@@ -2130,8 +2132,7 @@
 			irq = local_vector_to_irq(cpe_vector);
 			if (irq > 0) {
 				cpe_poll_enabled = 0;
-				desc = irq_desc + irq;
-				desc->status |= IRQ_PER_CPU;
+				irq_set_status_flags(irq, IRQ_PER_CPU);
 				setup_irq(irq, &mca_cpe_irqaction);
 				ia64_cpe_irq = irq;
 				ia64_mca_register_cpev(cpe_vector);
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/msi_ia64.c linux-libre-2.6.39-gnu/arch/ia64/kernel/msi_ia64.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/msi_ia64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/msi_ia64.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,12 +12,13 @@
 static struct irq_chip	ia64_msi_chip;
 
 #ifdef CONFIG_SMP
-static int ia64_set_msi_irq_affinity(unsigned int irq,
-				      const cpumask_t *cpu_mask)
+static int ia64_set_msi_irq_affinity(struct irq_data *idata,
+				     const cpumask_t *cpu_mask, bool force)
 {
 	struct msi_msg msg;
 	u32 addr, data;
 	int cpu = first_cpu(*cpu_mask);
+	unsigned int irq = idata->irq;
 
 	if (!cpu_online(cpu))
 		return -1;
@@ -38,7 +39,7 @@
 	msg.data = data;
 
 	write_msi_msg(irq, &msg);
-	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+	cpumask_copy(idata->affinity, cpumask_of(cpu));
 
 	return 0;
 }
@@ -55,7 +56,7 @@
 	if (irq < 0)
 		return irq;
 
-	set_irq_msi(irq, desc);
+	irq_set_msi_desc(irq, desc);
 	cpus_and(mask, irq_to_domain(irq), cpu_online_map);
 	dest_phys_id = cpu_physical_id(first_cpu(mask));
 	vector = irq_to_vector(irq);
@@ -74,7 +75,7 @@
 		MSI_DATA_VECTOR(vector);
 
 	write_msi_msg(irq, &msg);
-	set_irq_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
+	irq_set_chip_and_handler(irq, &ia64_msi_chip, handle_edge_irq);
 
 	return 0;
 }
@@ -84,16 +85,16 @@
 	destroy_irq(irq);
 }
 
-static void ia64_ack_msi_irq(unsigned int irq)
+static void ia64_ack_msi_irq(struct irq_data *data)
 {
-	irq_complete_move(irq);
-	move_native_irq(irq);
+	irq_complete_move(data->irq);
+	irq_move_irq(data);
 	ia64_eoi();
 }
 
-static int ia64_msi_retrigger_irq(unsigned int irq)
+static int ia64_msi_retrigger_irq(struct irq_data *data)
 {
-	unsigned int vector = irq_to_vector(irq);
+	unsigned int vector = irq_to_vector(data->irq);
 	ia64_resend_irq(vector);
 
 	return 1;
@@ -103,14 +104,14 @@
  * Generic ops used on most IA64 platforms.
  */
 static struct irq_chip ia64_msi_chip = {
-	.name		= "PCI-MSI",
-	.irq_mask	= mask_msi_irq,
-	.irq_unmask	= unmask_msi_irq,
-	.ack		= ia64_ack_msi_irq,
+	.name			= "PCI-MSI",
+	.irq_mask		= mask_msi_irq,
+	.irq_unmask		= unmask_msi_irq,
+	.irq_ack		= ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity	= ia64_set_msi_irq_affinity,
+	.irq_set_affinity	= ia64_set_msi_irq_affinity,
 #endif
-	.retrigger	= ia64_msi_retrigger_irq,
+	.irq_retrigger		= ia64_msi_retrigger_irq,
 };
 
 
@@ -132,8 +133,10 @@
 
 #ifdef CONFIG_DMAR
 #ifdef CONFIG_SMP
-static int dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int dmar_msi_set_affinity(struct irq_data *data,
+				 const struct cpumask *mask, bool force)
 {
+	unsigned int irq = data->irq;
 	struct irq_cfg *cfg = irq_cfg + irq;
 	struct msi_msg msg;
 	int cpu = cpumask_first(mask);
@@ -152,7 +155,7 @@
 	msg.address_lo |= MSI_ADDR_DEST_ID_CPU(cpu_physical_id(cpu));
 
 	dmar_msi_write(irq, &msg);
-	cpumask_copy(irq_desc[irq].affinity, mask);
+	cpumask_copy(data->affinity, mask);
 
 	return 0;
 }
@@ -162,11 +165,11 @@
 	.name = "DMAR_MSI",
 	.irq_unmask = dmar_msi_unmask,
 	.irq_mask = dmar_msi_mask,
-	.ack = ia64_ack_msi_irq,
+	.irq_ack = ia64_ack_msi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity = dmar_msi_set_affinity,
+	.irq_set_affinity = dmar_msi_set_affinity,
 #endif
-	.retrigger = ia64_msi_retrigger_irq,
+	.irq_retrigger = ia64_msi_retrigger_irq,
 };
 
 static int
@@ -203,8 +206,8 @@
 	if (ret < 0)
 		return ret;
 	dmar_msi_write(irq, &msg);
-	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-		"edge");
+	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+				      "edge");
 	return 0;
 }
 #endif /* CONFIG_DMAR */
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/perfmon_default_smpl.c linux-libre-2.6.39-gnu/arch/ia64/kernel/perfmon_default_smpl.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/perfmon_default_smpl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/perfmon_default_smpl.c	2011-05-19 00:06:34.000000000 -0400
@@ -150,7 +150,7 @@
 	 * current = task running at the time of the overflow.
 	 *
 	 * per-task mode:
-	 * 	- this is ususally the task being monitored.
+	 * 	- this is usually the task being monitored.
 	 * 	  Under certain conditions, it might be a different task
 	 *
 	 * system-wide:
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/setup.c linux-libre-2.6.39-gnu/arch/ia64/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -479,25 +479,7 @@
 }
 early_param("nomca", setup_nomca);
 
-/*
- * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
- * is_kdump_kernel() to determine if we are booting after a panic. Hence
- * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
- */
 #ifdef CONFIG_CRASH_DUMP
-/* elfcorehdr= specifies the location of elf core header
- * stored by the crashed kernel.
- */
-static int __init parse_elfcorehdr(char *arg)
-{
-	if (!arg)
-		return -EINVAL;
-
-        elfcorehdr_addr = memparse(arg, &arg);
-	return 0;
-}
-early_param("elfcorehdr", parse_elfcorehdr);
-
 int __init reserve_elfcorehdr(u64 *start, u64 *end)
 {
 	u64 length;
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/smpboot.c linux-libre-2.6.39-gnu/arch/ia64/kernel/smpboot.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/smpboot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/smpboot.c	2011-05-19 00:06:34.000000000 -0400
@@ -677,7 +677,7 @@
 int migrate_platform_irqs(unsigned int cpu)
 {
 	int new_cpei_cpu;
-	struct irq_desc *desc = NULL;
+	struct irq_data *data = NULL;
 	const struct cpumask *mask;
 	int 		retval = 0;
 
@@ -693,20 +693,20 @@
 			new_cpei_cpu = any_online_cpu(cpu_online_map);
 			mask = cpumask_of(new_cpei_cpu);
 			set_cpei_target_cpu(new_cpei_cpu);
-			desc = irq_desc + ia64_cpe_irq;
+			data = irq_get_irq_data(ia64_cpe_irq);
 			/*
 			 * Switch for now, immediately, we need to do fake intr
 			 * as other interrupts, but need to study CPEI behaviour with
 			 * polling before making changes.
 			 */
-			if (desc) {
-				desc->chip->disable(ia64_cpe_irq);
-				desc->chip->set_affinity(ia64_cpe_irq, mask);
-				desc->chip->enable(ia64_cpe_irq);
-				printk ("Re-targetting CPEI to cpu %d\n", new_cpei_cpu);
+			if (data && data->chip) {
+				data->chip->irq_disable(data);
+				data->chip->irq_set_affinity(data, mask, false);
+				data->chip->irq_enable(data);
+				printk ("Re-targeting CPEI to cpu %d\n", new_cpei_cpu);
 			}
 		}
-		if (!desc) {
+		if (!data) {
 			printk ("Unable to retarget CPEI, offline cpu [%d] failed\n", cpu);
 			retval = -EBUSY;
 		}
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/time.c linux-libre-2.6.39-gnu/arch/ia64/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -190,19 +190,10 @@
 
 		new_itm += local_cpu_data->itm_delta;
 
-		if (smp_processor_id() == time_keeper_id) {
-			/*
-			 * Here we are in the timer irq handler. We have irqs locally
-			 * disabled, but we don't know if the timer_bh is running on
-			 * another CPU. We need to avoid to SMP race by acquiring the
-			 * xtime_lock.
-			 */
-			write_seqlock(&xtime_lock);
-			do_timer(1);
-			local_cpu_data->itm_next = new_itm;
-			write_sequnlock(&xtime_lock);
-		} else
-			local_cpu_data->itm_next = new_itm;
+		if (smp_processor_id() == time_keeper_id)
+			xtime_update(1);
+
+		local_cpu_data->itm_next = new_itm;
 
 		if (time_after(new_itm, ia64_get_itc()))
 			break;
@@ -222,7 +213,7 @@
 		 * comfort, we increase the safety margin by
 		 * intentionally dropping the next tick(s).  We do NOT
 		 * update itm.next because that would force us to call
-		 * do_timer() which in turn would let our clock run
+		 * xtime_update() which in turn would let our clock run
 		 * too fast (with the potentially devastating effect
 		 * of losing monotony of time).
 		 */
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/topology.c linux-libre-2.6.39-gnu/arch/ia64/kernel/topology.c
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/topology.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/topology.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,7 +43,7 @@
 {
 #ifdef CONFIG_ACPI
 	/*
-	 * If CPEI can be re-targetted or if this is not
+	 * If CPEI can be re-targeted or if this is not
 	 * CPEI target, then it is hotpluggable
 	 */
 	if (can_cpei_retarget() || !is_cpu_cpei_target(num))
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/ia64/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/ia64/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -198,7 +198,7 @@
 
 	/* Per-cpu data: */
 	. = ALIGN(PERCPU_PAGE_SIZE);
-	PERCPU_VADDR(PERCPU_ADDR, :percpu)
+	PERCPU_VADDR(SMP_CACHE_BYTES, PERCPU_ADDR, :percpu)
 	__phys_per_cpu_start = __per_cpu_load;
 	/*
 	 * ensure percpu data fits
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kvm/kvm-ia64.c linux-libre-2.6.39-gnu/arch/ia64/kvm/kvm-ia64.c
--- linux-libre-2.6.38-gnu/arch/ia64/kvm/kvm-ia64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kvm/kvm-ia64.c	2011-05-19 00:06:34.000000000 -0400
@@ -662,6 +662,7 @@
 		goto vcpu_run_fail;
 
 	srcu_read_unlock(&vcpu->kvm->srcu, idx);
+	vcpu->mode = IN_GUEST_MODE;
 	kvm_guest_enter();
 
 	/*
@@ -683,6 +684,7 @@
 	 */
 	barrier();
 	kvm_guest_exit();
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	preempt_enable();
 
 	idx = srcu_read_lock(&vcpu->kvm->srcu);
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kvm/Makefile linux-libre-2.6.39-gnu/arch/ia64/kvm/Makefile
--- linux-libre-2.6.38-gnu/arch/ia64/kvm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kvm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -45,8 +45,8 @@
 # Makefile for Kernel-based Virtual Machine module
 #
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
-EXTRA_AFLAGS += -Ivirt/kvm -Iarch/ia64/kvm/
+ccflags-y := -Ivirt/kvm -Iarch/ia64/kvm/
+asflags-y := -Ivirt/kvm -Iarch/ia64/kvm/
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o ioapic.o \
 		coalesced_mmio.o irq_comm.o assigned-dev.o)
diff -druN linux-libre-2.6.38-gnu/arch/ia64/kvm/process.c linux-libre-2.6.39-gnu/arch/ia64/kvm/process.c
--- linux-libre-2.6.38-gnu/arch/ia64/kvm/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/kvm/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -987,7 +987,7 @@
 
 static void kvm_do_resume_op(struct kvm_vcpu *vcpu)
 {
-	vmm_sanity_check(vcpu); /*Guarantee vcpu runing on healthy vmm!*/
+	vmm_sanity_check(vcpu); /*Guarantee vcpu running on healthy vmm!*/
 
 	if (test_and_clear_bit(KVM_REQ_RESUME, &vcpu->requests)) {
 		vcpu_do_resume(vcpu);
diff -druN linux-libre-2.6.38-gnu/arch/ia64/lib/do_csum.S linux-libre-2.6.39-gnu/arch/ia64/lib/do_csum.S
--- linux-libre-2.6.38-gnu/arch/ia64/lib/do_csum.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/lib/do_csum.S	2011-05-19 00:06:34.000000000 -0400
@@ -201,7 +201,7 @@
 	;;
 (p6)	adds result1[0]=1,result1[0]
 (p9)	br.cond.sptk .do_csum_exit	// if (count == 1) exit
-	// Fall through to caluculate the checksum, feeding result1[0] as
+	// Fall through to calculate the checksum, feeding result1[0] as
 	// the initial value in result1[0].
 	//
 	// Calculate the checksum loading two 8-byte words per loop.
diff -druN linux-libre-2.6.38-gnu/arch/ia64/mm/contig.c linux-libre-2.6.39-gnu/arch/ia64/mm/contig.c
--- linux-libre-2.6.38-gnu/arch/ia64/mm/contig.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/mm/contig.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
  * Shows a simple page count of reserved and used pages in the system.
  * For discontig machines, it does this on a per-pgdat basis.
  */
-void show_mem(void)
+void show_mem(unsigned int filter)
 {
 	int i, total_reserved = 0;
 	int total_shared = 0, total_cached = 0;
diff -druN linux-libre-2.6.38-gnu/arch/ia64/mm/discontig.c linux-libre-2.6.39-gnu/arch/ia64/mm/discontig.c
--- linux-libre-2.6.38-gnu/arch/ia64/mm/discontig.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/mm/discontig.c	2011-05-19 00:06:34.000000000 -0400
@@ -614,7 +614,7 @@
  * Shows a simple page count of reserved and used pages in the system.
  * For discontig machines, it does this on a per-pgdat basis.
  */
-void show_mem(void)
+void show_mem(unsigned int filter)
 {
 	int i, total_reserved = 0;
 	int total_shared = 0, total_cached = 0;
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/irq.c linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,11 +23,9 @@
 #include <asm/sn/sn_sal.h>
 #include <asm/sn/sn_feature_sets.h>
 
-static void force_interrupt(int irq);
 static void register_intr_pda(struct sn_irq_info *sn_irq_info);
 static void unregister_intr_pda(struct sn_irq_info *sn_irq_info);
 
-int sn_force_interrupt_flag = 1;
 extern int sn_ioif_inited;
 struct list_head **sn_irq_lh;
 static DEFINE_SPINLOCK(sn_irq_info_lock); /* non-IRQ lock */
@@ -78,62 +76,40 @@
 	return ret_stuff.status;
 }
 
-static unsigned int sn_startup_irq(unsigned int irq)
+static unsigned int sn_startup_irq(struct irq_data *data)
 {
 	return 0;
 }
 
-static void sn_shutdown_irq(unsigned int irq)
+static void sn_shutdown_irq(struct irq_data *data)
 {
 }
 
 extern void ia64_mca_register_cpev(int);
 
-static void sn_disable_irq(unsigned int irq)
+static void sn_disable_irq(struct irq_data *data)
 {
-	if (irq == local_vector_to_irq(IA64_CPE_VECTOR))
+	if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
 		ia64_mca_register_cpev(0);
 }
 
-static void sn_enable_irq(unsigned int irq)
+static void sn_enable_irq(struct irq_data *data)
 {
-	if (irq == local_vector_to_irq(IA64_CPE_VECTOR))
-		ia64_mca_register_cpev(irq);
+	if (data->irq == local_vector_to_irq(IA64_CPE_VECTOR))
+		ia64_mca_register_cpev(data->irq);
 }
 
-static void sn_ack_irq(unsigned int irq)
+static void sn_ack_irq(struct irq_data *data)
 {
 	u64 event_occurred, mask;
+	unsigned int irq = data->irq & 0xff;
 
-	irq = irq & 0xff;
 	event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED));
 	mask = event_occurred & SH_ALL_INT_MASK;
 	HUB_S((u64*)LOCAL_MMR_ADDR(SH_EVENT_OCCURRED_ALIAS), mask);
 	__set_bit(irq, (volatile void *)pda->sn_in_service_ivecs);
 
-	move_native_irq(irq);
-}
-
-static void sn_end_irq(unsigned int irq)
-{
-	int ivec;
-	u64 event_occurred;
-
-	ivec = irq & 0xff;
-	if (ivec == SGI_UART_VECTOR) {
-		event_occurred = HUB_L((u64*)LOCAL_MMR_ADDR (SH_EVENT_OCCURRED));
-		/* If the UART bit is set here, we may have received an
-		 * interrupt from the UART that the driver missed.  To
-		 * make sure, we IPI ourselves to force us to look again.
-		 */
-		if (event_occurred & SH_EVENT_OCCURRED_UART_INT_MASK) {
-			platform_send_ipi(smp_processor_id(), SGI_UART_VECTOR,
-					  IA64_IPI_DM_INT, 0);
-		}
-	}
-	__clear_bit(ivec, (volatile void *)pda->sn_in_service_ivecs);
-	if (sn_force_interrupt_flag)
-		force_interrupt(irq);
+	irq_move_irq(data);
 }
 
 static void sn_irq_info_free(struct rcu_head *head);
@@ -228,9 +204,11 @@
 	return new_irq_info;
 }
 
-static int sn_set_affinity_irq(unsigned int irq, const struct cpumask *mask)
+static int sn_set_affinity_irq(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
 {
 	struct sn_irq_info *sn_irq_info, *sn_irq_info_safe;
+	unsigned int irq = data->irq;
 	nasid_t nasid;
 	int slice;
 
@@ -249,7 +227,7 @@
 {
         /*
          * On systems which support CPU disabling (SHub2), all error interrupts
-         * are targetted at the boot CPU.
+         * are targeted at the boot CPU.
          */
         if (is_shub2() && sn_prom_feature_available(PRF_CPU_DISABLE_SUPPORT))
                 set_irq_affinity_info(irq, cpu_physical_id(0), 0);
@@ -259,26 +237,25 @@
 #endif
 
 static void
-sn_mask_irq(unsigned int irq)
+sn_mask_irq(struct irq_data *data)
 {
 }
 
 static void
-sn_unmask_irq(unsigned int irq)
+sn_unmask_irq(struct irq_data *data)
 {
 }
 
 struct irq_chip irq_type_sn = {
-	.name		= "SN hub",
-	.startup	= sn_startup_irq,
-	.shutdown	= sn_shutdown_irq,
-	.enable		= sn_enable_irq,
-	.disable	= sn_disable_irq,
-	.ack		= sn_ack_irq,
-	.end		= sn_end_irq,
-	.mask		= sn_mask_irq,
-	.unmask		= sn_unmask_irq,
-	.set_affinity	= sn_set_affinity_irq
+	.name			= "SN hub",
+	.irq_startup		= sn_startup_irq,
+	.irq_shutdown		= sn_shutdown_irq,
+	.irq_enable		= sn_enable_irq,
+	.irq_disable		= sn_disable_irq,
+	.irq_ack		= sn_ack_irq,
+	.irq_mask		= sn_mask_irq,
+	.irq_unmask		= sn_unmask_irq,
+	.irq_set_affinity	= sn_set_affinity_irq
 };
 
 ia64_vector sn_irq_to_vector(int irq)
@@ -296,15 +273,13 @@
 void sn_irq_init(void)
 {
 	int i;
-	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_chip) {
-			base_desc[i].chip = &irq_type_sn;
-		}
+		if (irq_get_chip(i) == &no_irq_chip)
+			irq_set_chip(i, &irq_type_sn);
 	}
 }
 
@@ -378,7 +353,6 @@
 	int cpu = nasid_slice_to_cpuid(nasid, slice);
 #ifdef CONFIG_SMP
 	int cpuphys;
-	struct irq_desc *desc;
 #endif
 
 	pci_dev_get(pci_dev);
@@ -395,12 +369,11 @@
 #ifdef CONFIG_SMP
 	cpuphys = cpu_physical_id(cpu);
 	set_irq_affinity_info(sn_irq_info->irq_irq, cpuphys, 0);
-	desc = irq_to_desc(sn_irq_info->irq_irq);
 	/*
 	 * Affinity was set by the PROM, prevent it from
 	 * being reset by the request_irq() path.
 	 */
-	desc->status |= IRQ_AFFINITY_SET;
+	irqd_mark_affinity_was_set(irq_get_irq_data(sn_irq_info->irq_irq));
 #endif
 }
 
@@ -439,25 +412,11 @@
 	pci_provider = sn_pci_provider[sn_irq_info->irq_bridge_type];
 
 	/* Don't force an interrupt if the irq has been disabled */
-	if (!(irq_desc[sn_irq_info->irq_irq].status & IRQ_DISABLED) &&
+	if (!irqd_irq_disabled(irq_get_irq_data(sn_irq_info->irq_irq)) &&
 	    pci_provider && pci_provider->force_interrupt)
 		(*pci_provider->force_interrupt)(sn_irq_info);
 }
 
-static void force_interrupt(int irq)
-{
-	struct sn_irq_info *sn_irq_info;
-
-	if (!sn_ioif_inited)
-		return;
-
-	rcu_read_lock();
-	list_for_each_entry_rcu(sn_irq_info, sn_irq_lh[irq], list)
-		sn_call_force_intr_provider(sn_irq_info);
-
-	rcu_read_unlock();
-}
-
 /*
  * Check for lost interrupts.  If the PIC int_status reg. says that
  * an interrupt has been sent, but not handled, and the interrupt
@@ -476,7 +435,7 @@
 	/*
 	 * Bridge types attached to TIO (anything but PIC) do not need this WAR
 	 * since they do not target Shub II interrupt registers.  If that
-	 * ever changes, this check needs to accomodate.
+	 * ever changes, this check needs to accommodate.
 	 */
 	if (sn_irq_info->irq_bridge_type != PCIIO_ASIC_TYPE_PIC)
 		return;
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/Makefile linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 # Copyright (C) 1999,2001-2006,2008 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y				+= setup.o bte.o bte_error.o irq.o mca.o idle.o \
 				   huberror.o io_acpi_init.o io_common.o \
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/msi_sn.c linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/msi_sn.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/msi_sn.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/msi_sn.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,16 +144,16 @@
 	 */
 	msg.data = 0x100 + irq;
 
-	set_irq_msi(irq, entry);
+	irq_set_msi_desc(irq, entry);
 	write_msi_msg(irq, &msg);
-	set_irq_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
+	irq_set_chip_and_handler(irq, &sn_msi_chip, handle_edge_irq);
 
 	return 0;
 }
 
 #ifdef CONFIG_SMP
-static int sn_set_msi_irq_affinity(unsigned int irq,
-				    const struct cpumask *cpu_mask)
+static int sn_set_msi_irq_affinity(struct irq_data *data,
+				   const struct cpumask *cpu_mask, bool force)
 {
 	struct msi_msg msg;
 	int slice;
@@ -164,7 +164,7 @@
 	struct sn_irq_info *sn_irq_info;
 	struct sn_irq_info *new_irq_info;
 	struct sn_pcibus_provider *provider;
-	unsigned int cpu;
+	unsigned int cpu, irq = data->irq;
 
 	cpu = cpumask_first(cpu_mask);
 	sn_irq_info = sn_msi_info[irq].sn_irq_info;
@@ -206,33 +206,33 @@
 	msg.address_lo = (u32)(bus_addr & 0x00000000ffffffff);
 
 	write_msi_msg(irq, &msg);
-	cpumask_copy(irq_desc[irq].affinity, cpu_mask);
+	cpumask_copy(data->affinity, cpu_mask);
 
 	return 0;
 }
 #endif /* CONFIG_SMP */
 
-static void sn_ack_msi_irq(unsigned int irq)
+static void sn_ack_msi_irq(struct irq_data *data)
 {
-	move_native_irq(irq);
+	irq_move_irq(data);
 	ia64_eoi();
 }
 
-static int sn_msi_retrigger_irq(unsigned int irq)
+static int sn_msi_retrigger_irq(struct irq_data *data)
 {
-	unsigned int vector = irq;
+	unsigned int vector = data->irq;
 	ia64_resend_irq(vector);
 
 	return 1;
 }
 
 static struct irq_chip sn_msi_chip = {
-	.name		= "PCI-MSI",
-	.irq_mask	= mask_msi_irq,
-	.irq_unmask	= unmask_msi_irq,
-	.ack		= sn_ack_msi_irq,
+	.name			= "PCI-MSI",
+	.irq_mask		= mask_msi_irq,
+	.irq_unmask		= unmask_msi_irq,
+	.irq_ack		= sn_ack_msi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity	= sn_set_msi_irq_affinity,
+	.irq_set_affinity	= sn_set_msi_irq_affinity,
 #endif
-	.retrigger	= sn_msi_retrigger_irq,
+	.irq_retrigger		= sn_msi_retrigger_irq,
 };
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/setup.c linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -592,7 +592,7 @@
 	/*
 	 * Don't check status. The SAL call is not supported on all PROMs
 	 * but a failure is harmless.
-	 * Architechtuallly, cpu_init is always called twice on cpu 0. We
+	 * Architecturally, cpu_init is always called twice on cpu 0. We
 	 * should set cpu_number on cpu 0 once.
 	 */
 	if (cpuid == 0) {
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/sn2/Makefile linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/sn2/Makefile
--- linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/sn2/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/sn2/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
 # sn2 specific kernel files
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y += cache.o io.o ptc_deadlock.o sn2_smp.o sn_proc_fs.o \
 	 prominfo_proc.o timer.o timer_interrupt.o sn_hwperf.o
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/kernel/sn2/sn_proc_fs.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,38 +45,6 @@
 	return single_open(file, licenseID_show, NULL);
 }
 
-/*
- * Enable forced interrupt by default.
- * When set, the sn interrupt handler writes the force interrupt register on
- * the bridge chip.  The hardware will then send an interrupt message if the
- * interrupt line is active.  This mimics a level sensitive interrupt.
- */
-extern int sn_force_interrupt_flag;
-
-static int sn_force_interrupt_show(struct seq_file *s, void *p)
-{
-	seq_printf(s, "Force interrupt is %s\n",
-		sn_force_interrupt_flag ? "enabled" : "disabled");
-	return 0;
-}
-
-static ssize_t sn_force_interrupt_write_proc(struct file *file,
-		const char __user *buffer, size_t count, loff_t *data)
-{
-	char val;
-
-	if (copy_from_user(&val, buffer, 1))
-		return -EFAULT;
-
-	sn_force_interrupt_flag = (val == '0') ? 0 : 1;
-	return count;
-}
-
-static int sn_force_interrupt_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, sn_force_interrupt_show, NULL);
-}
-
 static int coherence_id_show(struct seq_file *s, void *p)
 {
 	seq_printf(s, "%d\n", partition_coherence_id());
@@ -114,14 +82,6 @@
 	.release	= single_release,
 };
 
-static const struct file_operations proc_sn_force_intr_fops = {
-	.open		= sn_force_interrupt_open,
-	.read		= seq_read,
-	.write		= sn_force_interrupt_write_proc,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
 static const struct file_operations proc_coherence_id_fops = {
 	.open		= coherence_id_open,
 	.read		= seq_read,
@@ -149,8 +109,6 @@
 	proc_create("system_serial_number", 0444, sgi_proc_dir,
 		    &proc_system_sn_fops);
 	proc_create("licenseID", 0444, sgi_proc_dir, &proc_license_id_fops);
-	proc_create("sn_force_interrupt", 0644, sgi_proc_dir,
-		    &proc_sn_force_intr_fops);
 	proc_create("coherence_id", 0444, sgi_proc_dir,
 		    &proc_coherence_id_fops);
 	proc_create("sn_topology", 0444, sgi_proc_dir, &proc_sn_topo_fops);
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/pci/Makefile linux-libre-2.6.39-gnu/arch/ia64/sn/pci/Makefile
--- linux-libre-2.6.38-gnu/arch/ia64/sn/pci/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/pci/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,6 @@
 #
 # Makefile for the sn pci general routines.
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y := pci_dma.o tioca_provider.o tioce_provider.o pcibr/
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/pci/pcibr/Makefile linux-libre-2.6.39-gnu/arch/ia64/sn/pci/pcibr/Makefile
--- linux-libre-2.6.38-gnu/arch/ia64/sn/pci/pcibr/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/pci/pcibr/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 #
 # Makefile for the sn2 io routines.
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y				+=  pcibr_dma.o pcibr_reg.o \
 				    pcibr_ate.o pcibr_provider.o
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c linux-libre-2.6.39-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/pci/pcibr/pcibr_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -227,7 +227,7 @@
  * after doing the read.  For PIC this routine then forces a fake interrupt
  * on another line, which is logically associated with the slot that the PIO
  * is addressed to.  It then spins while watching the memory location that
- * the interrupt is targetted to.  When the interrupt response arrives, we 
+ * the interrupt is targeted to.  When the interrupt response arrives, we 
  * are sure that the DMA has landed in memory and it is safe for the driver
  * to proceed.	For TIOCP use the Device(x) Write Request Buffer Flush 
  * Bridge register since it ensures the data has entered the coherence domain,
diff -druN linux-libre-2.6.38-gnu/arch/ia64/sn/pci/tioca_provider.c linux-libre-2.6.39-gnu/arch/ia64/sn/pci/tioca_provider.c
--- linux-libre-2.6.38-gnu/arch/ia64/sn/pci/tioca_provider.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/sn/pci/tioca_provider.c	2011-05-19 00:06:34.000000000 -0400
@@ -509,7 +509,7 @@
  * use the GART mapped mode.
  */
 static u64
-tioca_dma_map(struct pci_dev *pdev, u64 paddr, size_t byte_count, int dma_flags)
+tioca_dma_map(struct pci_dev *pdev, unsigned long paddr, size_t byte_count, int dma_flags)
 {
 	u64 mapaddr;
 
diff -druN linux-libre-2.6.38-gnu/arch/ia64/uv/kernel/Makefile linux-libre-2.6.39-gnu/arch/ia64/uv/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/ia64/uv/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/uv/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 # Copyright (C) 2008 Silicon Graphics, Inc.  All Rights Reserved.
 #
 
-EXTRA_CFLAGS += -Iarch/ia64/sn/include
+ccflags-y := -Iarch/ia64/sn/include
 
 obj-y				+= setup.o
 obj-$(CONFIG_IA64_GENERIC)      += machvec.o
diff -druN linux-libre-2.6.38-gnu/arch/ia64/xen/irq_xen.c linux-libre-2.6.39-gnu/arch/ia64/xen/irq_xen.c
--- linux-libre-2.6.38-gnu/arch/ia64/xen/irq_xen.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/xen/irq_xen.c	2011-05-19 00:06:34.000000000 -0400
@@ -138,7 +138,6 @@
 __xen_register_percpu_irq(unsigned int cpu, unsigned int vec,
 			struct irqaction *action, int save)
 {
-	struct irq_desc *desc;
 	int irq = 0;
 
 	if (xen_slab_ready) {
@@ -223,8 +222,7 @@
 			 * mark the interrupt for migrations and trigger it
 			 * on cpu hotplug.
 			 */
-			desc = irq_desc + irq;
-			desc->status |= IRQ_PER_CPU;
+			irq_set_status_flags(irq, IRQ_PER_CPU);
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/ia64/xen/suspend.c linux-libre-2.6.39-gnu/arch/ia64/xen/suspend.c
--- linux-libre-2.6.38-gnu/arch/ia64/xen/suspend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/xen/suspend.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,19 +37,14 @@
 	/* nothing */
 }
 
-void xen_pre_device_suspend(void)
-{
-	/* nothing */
-}
-
 void
-xen_pre_suspend()
+xen_arch_pre_suspend()
 {
 	/* nothing */
 }
 
 void
-xen_post_suspend(int suspend_cancelled)
+xen_arch_post_suspend(int suspend_cancelled)
 {
 	if (suspend_cancelled)
 		return;
diff -druN linux-libre-2.6.38-gnu/arch/ia64/xen/time.c linux-libre-2.6.39-gnu/arch/ia64/xen/time.c
--- linux-libre-2.6.38-gnu/arch/ia64/xen/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/ia64/xen/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,14 +139,11 @@
 		run_posix_cpu_timers(p);
 		delta_itm += local_cpu_data->itm_delta * (stolen + blocked);
 
-		if (cpu == time_keeper_id) {
-			write_seqlock(&xtime_lock);
-			do_timer(stolen + blocked);
-			local_cpu_data->itm_next = delta_itm + new_itm;
-			write_sequnlock(&xtime_lock);
-		} else {
-			local_cpu_data->itm_next = delta_itm + new_itm;
-		}
+		if (cpu == time_keeper_id)
+			xtime_update(stolen + blocked);
+
+		local_cpu_data->itm_next = delta_itm + new_itm;
+
 		per_cpu(xen_stolen_time, cpu) += NS_PER_TICK * stolen;
 		per_cpu(xen_blocked_time, cpu) += NS_PER_TICK * blocked;
 	}
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -266,9 +266,8 @@
 
 #ifdef __KERNEL__
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/m32104ut/m32104ut_pld.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/m32104ut/m32104ut_pld.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/m32104ut/m32104ut_pld.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/m32104ut/m32104ut_pld.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 /*
  * include/asm-m32r/m32104ut/m32104ut_pld.h
  *
- * Definitions for Programable Logic Device(PLD) on M32104UT board.
+ * Definitions for Programmable Logic Device(PLD) on M32104UT board.
  * Based on m32700ut_pld.h
  *
  * Copyright (c) 2002	Takeo Takahashi
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/m32700ut/m32700ut_pld.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/m32700ut/m32700ut_pld.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/m32700ut/m32700ut_pld.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/m32700ut/m32700ut_pld.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 /*
  * include/asm-m32r/m32700ut/m32700ut_pld.h
  *
- * Definitions for Programable Logic Device(PLD) on M32700UT board.
+ * Definitions for Programmable Logic Device(PLD) on M32700UT board.
  *
  * Copyright (c) 2002	Takeo Takahashi
  *
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/opsput/opsput_pld.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/opsput/opsput_pld.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/opsput/opsput_pld.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/opsput/opsput_pld.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 /*
  * include/asm-m32r/opsput/opsput_pld.h
  *
- * Definitions for Programable Logic Device(PLD) on OPSPUT board.
+ * Definitions for Programmable Logic Device(PLD) on OPSPUT board.
  *
  * Copyright (c) 2002	Takeo Takahashi
  *
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/pgtable-2level.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/pgtable-2level.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/pgtable-2level.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/pgtable-2level.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,7 @@
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
 /*
- * (pmds are folded into pgds so this doesnt get actually called,
+ * (pmds are folded into pgds so this doesn't get actually called,
  * but the define is needed for a generic inline function.)
  */
 #define set_pmd(pmdptr, pmdval) (*(pmdptr) = pmdval)
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -96,16 +96,11 @@
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-	({							\
-		struct thread_info *ret;			\
-	 							\
-	 	ret = kzalloc(THREAD_SIZE, GFP_KERNEL);		\
-								\
-	 	ret;						\
-	 })
+#define alloc_thread_info_node(tsk, node)			\
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(info) kfree(info)
diff -druN linux-libre-2.6.38-gnu/arch/m32r/include/asm/types.h linux-libre-2.6.39-gnu/arch/m32r/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/m32r/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,15 +16,6 @@
 
 #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 /* _ASM_M32R_TYPES_H */
diff -druN linux-libre-2.6.38-gnu/arch/m32r/Kconfig linux-libre-2.6.39-gnu/arch/m32r/Kconfig
--- linux-libre-2.6.38-gnu/arch/m32r/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -8,8 +8,8 @@
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
 	select HAVE_GENERIC_HARDIRQS
-	select GENERIC_HARDIRQS_NO_DEPRECATED
 	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
 
 config SBUS
 	bool
@@ -260,6 +260,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
diff -druN linux-libre-2.6.38-gnu/arch/m32r/kernel/irq.c linux-libre-2.6.39-gnu/arch/m32r/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/m32r/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,55 +18,10 @@
 
 #include <linux/kernel_stat.h>
 #include <linux/interrupt.h>
-#include <linux/seq_file.h>
 #include <linux/module.h>
 #include <asm/uaccess.h>
 
 /*
- * Generic, controller-independent functions:
- */
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		struct irq_desc *desc = irq_to_desc(i);
-
-		raw_spin_lock_irqsave(&desc->lock, flags);
-		action = desc->action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", desc->irq_data.chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&desc->lock, flags);
-	}
-	return 0;
-}
-
-/*
  * do_IRQ handles all normal device IRQs (the special
  * SMP cross-CPU interrupts have their own specific
  * handlers).
diff -druN linux-libre-2.6.38-gnu/arch/m32r/kernel/time.c linux-libre-2.6.39-gnu/arch/m32r/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/m32r/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,15 +107,14 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 static irqreturn_t timer_interrupt(int irq, void *dev_id)
 {
 #ifndef CONFIG_SMP
 	profile_tick(CPU_PROFILING);
 #endif
-	/* XXX FIXME. Uh, the xtime_lock should be held here, no? */
-	do_timer(1);
+	xtime_update(1);
 
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
diff -druN linux-libre-2.6.38-gnu/arch/m32r/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/m32r/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/m32r/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
   __init_begin = .;
   INIT_TEXT_SECTION(PAGE_SIZE)
   INIT_DATA_SECTION(16)
-  PERCPU(PAGE_SIZE)
+  PERCPU(32, PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
diff -druN linux-libre-2.6.38-gnu/arch/m32r/mm/fault.c linux-libre-2.6.39-gnu/arch/m32r/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/m32r/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -120,7 +120,7 @@
 
 	/* 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.  Unfortunatly, in the case of an
+	 * 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
@@ -128,7 +128,7 @@
 	 * exceptions table.
 	 *
 	 * As the vast majority of faults will be valid we will only perform
-	 * the source reference check when there is a possibilty of a deadlock.
+	 * 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.
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/m32104ut/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/m32104ut/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/m32104ut/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/m32104ut/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
 
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on M32104UT-LAN (SMC91C111)*/
-	set_irq_chip_and_handler(M32R_IRQ_INT0, &m32104ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT0, &m32104ut_irq_type,
 				 handle_level_irq);
 	/* "H" level sense */
 	cu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD11;
@@ -84,20 +84,20 @@
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &m32104ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &m32104ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &m32104ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &m32104ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &m32104ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &m32104ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = M32R_ICUCR_IEN;
 	disable_m32104ut_irq(M32R_IRQ_SIO0_S);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/m32700ut/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/m32700ut/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/m32700ut/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/m32700ut/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -259,76 +259,76 @@
 {
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on M32700UT-LAN (SMC91C111)*/
-	set_irq_chip_and_handler(M32700UT_LAN_IRQ_LAN,
+	irq_set_chip_and_handler(M32700UT_LAN_IRQ_LAN,
 				 &m32700ut_lanpld_irq_type, handle_level_irq);
 	lanpld_icu_data[irq2lanpldirq(M32700UT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
 	disable_m32700ut_lanpld_irq(M32700UT_LAN_IRQ_LAN);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_m32700ut_irq(M32R_IRQ_MFT2);
 
 	/* SIO0 : receive */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0 : send */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1 : receive */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1 : send */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_SIO1_S);
 
 	/* DMA1 : */
-	set_irq_chip_and_handler(M32R_IRQ_DMA1, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_DMA1, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_DMA1].icucr = 0;
 	disable_m32700ut_irq(M32R_IRQ_DMA1);
 
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 	/* INT#1: SIO0 Receive on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_SIO0_RCV, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_SIO0_RCV, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_RCV);
 
 	/* INT#1: SIO0 Send on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_SIO0_SND, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_SIO0_SND, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_m32700ut_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
 	/* INT#1: CFC IREQ on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFIREQ, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFIREQ);
 
 	/* INT#1: CFC Insert on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_INSERT, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_INSERT);
 
 	/* INT#1: CFC Eject on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_EJECT, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_EJECT, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_CFC_EJECT);
@@ -349,7 +349,7 @@
 
 #if defined(CONFIG_USB)
 	outw(USBCR_OTGS, USBCR); 	/* USBCR: non-OTG */
-	set_irq_chip_and_handler(M32700UT_LCD_IRQ_USB_INT1,
+	irq_set_chip_and_handler(M32700UT_LCD_IRQ_USB_INT1,
 				 &m32700ut_lcdpld_irq_type, handle_level_irq);
 
 	lcdpld_icu_data[irq2lcdpldirq(M32700UT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
@@ -366,7 +366,7 @@
 	/*
 	 * INT3# is used for AR
 	 */
-	set_irq_chip_and_handler(M32R_IRQ_INT3, &m32700ut_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT3, &m32700ut_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_m32700ut_irq(M32R_IRQ_INT3);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/mappi/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/mappi/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/mappi/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/mappi/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,39 +75,39 @@
 
 #ifdef CONFIG_NE2000
 	/* INT0 : LAN controller (RTL8019AS) */
-	set_irq_chip_and_handler(M32R_IRQ_INT0, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT0, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD11;
 	disable_mappi_irq(M32R_IRQ_INT0);
 #endif /* CONFIG_M32R_NE2000 */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
@@ -115,13 +115,13 @@
 
 #if defined(CONFIG_M32R_PCC)
 	/* INT1 : pccard0 interrupt */
-	set_irq_chip_and_handler(M32R_IRQ_INT1, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT1, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT1);
 
 	/* INT2 : pccard1 interrupt */
-	set_irq_chip_and_handler(M32R_IRQ_INT2, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT2, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT2].icucr = M32R_ICUCR_IEN | M32R_ICUCR_ISMOD00;
 	disable_mappi_irq(M32R_IRQ_INT2);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/mappi2/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/mappi2/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/mappi2/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/mappi2/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,38 +76,38 @@
 {
 #if defined(CONFIG_SMC91X)
 	/* INT0 : LAN controller (SMC91111) */
-	set_irq_chip_and_handler(M32R_IRQ_INT0, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT0, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi2_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi2_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO0_S);
 	/* SIO1_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi2_irq(M32R_IRQ_SIO1_S);
@@ -115,27 +115,27 @@
 
 #if defined(CONFIG_USB)
 	/* INT1 : USB Host controller interrupt */
-	set_irq_chip_and_handler(M32R_IRQ_INT1, &mappi2_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT1, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(M32R_IRQ_INT1);
 #endif /* CONFIG_USB */
 
 	/* ICUCR40: CFC IREQ */
-	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &mappi2_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFIREQ, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi2_irq(PLD_IRQ_CFIREQ);
 
 #if defined(CONFIG_M32R_CFC)
 	/* ICUCR41: CFC Insert */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &mappi2_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_INSERT, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	disable_mappi2_irq(PLD_IRQ_CFC_INSERT);
 
 	/* ICUCR42: CFC Eject */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_EJECT, &mappi2_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_EJECT, &mappi2_irq_type,
 				 handle_level_irq);
 	icu_data[PLD_IRQ_CFC_EJECT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi2_irq(PLD_IRQ_CFC_EJECT);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/mappi3/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/mappi3/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/mappi3/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/mappi3/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,38 +75,38 @@
 {
 #if defined(CONFIG_SMC91X)
 	/* INT0 : LAN controller (SMC91111) */
-	set_irq_chip_and_handler(M32R_IRQ_INT0, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT0, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT0].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi3_irq(M32R_IRQ_INT0);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi3_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO0_S);
 	/* SIO1_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi3_irq(M32R_IRQ_SIO1_S);
@@ -114,21 +114,21 @@
 
 #if defined(CONFIG_USB)
 	/* INT1 : USB Host controller interrupt */
-	set_irq_chip_and_handler(M32R_IRQ_INT1, &mappi3_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT1, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT1].icucr = M32R_ICUCR_ISMOD01;
 	disable_mappi3_irq(M32R_IRQ_INT1);
 #endif /* CONFIG_USB */
 
 	/* CFC IREQ */
-	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &mappi3_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFIREQ, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[PLD_IRQ_CFIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD01;
 	disable_mappi3_irq(PLD_IRQ_CFIREQ);
 
 #if defined(CONFIG_M32R_CFC)
 	/* ICUCR41: CFC Insert & eject */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &mappi3_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_INSERT, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[PLD_IRQ_CFC_INSERT].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD00;
 	disable_mappi3_irq(PLD_IRQ_CFC_INSERT);
@@ -136,7 +136,7 @@
 #endif /* CONFIG_M32R_CFC */
 
 	/* IDE IREQ */
-	set_irq_chip_and_handler(PLD_IRQ_IDEIREQ, &mappi3_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_IDEIREQ, &mappi3_irq_type,
 				 handle_level_irq);
 	icu_data[PLD_IRQ_IDEIREQ].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_mappi3_irq(PLD_IRQ_IDEIREQ);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/oaks32r/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/oaks32r/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/oaks32r/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/oaks32r/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,39 +74,39 @@
 
 #ifdef CONFIG_NE2000
 	/* INT3 : LAN controller (RTL8019AS) */
-	set_irq_chip_and_handler(M32R_IRQ_INT3, &oaks32r_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT3, &oaks32r_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_oaks32r_irq(M32R_IRQ_INT3);
 #endif /* CONFIG_M32R_NE2000 */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &oaks32r_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &oaks32r_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_oaks32r_irq(M32R_IRQ_MFT2);
 
 #ifdef CONFIG_SERIAL_M32R_SIO
 	/* SIO0_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &oaks32r_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &oaks32r_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &oaks32r_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &oaks32r_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &oaks32r_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &oaks32r_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &oaks32r_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &oaks32r_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_oaks32r_irq(M32R_IRQ_SIO1_S);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/opsput/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/opsput/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/opsput/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/opsput/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -259,76 +259,76 @@
 {
 #if defined(CONFIG_SMC91X)
 	/* INT#0: LAN controller on OPSPUT-LAN (SMC91C111)*/
-	set_irq_chip_and_handler(OPSPUT_LAN_IRQ_LAN, &opsput_lanpld_irq_type,
+	irq_set_chip_and_handler(OPSPUT_LAN_IRQ_LAN, &opsput_lanpld_irq_type,
 				 handle_level_irq);
 	lanpld_icu_data[irq2lanpldirq(OPSPUT_LAN_IRQ_LAN)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* "H" edge sense */
 	disable_opsput_lanpld_irq(OPSPUT_LAN_IRQ_LAN);
 #endif  /* CONFIG_SMC91X */
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_opsput_irq(M32R_IRQ_MFT2);
 
 	/* SIO0 : receive */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0 : send */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1 : receive */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1 : send */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_SIO1_S);
 
 	/* DMA1 : */
-	set_irq_chip_and_handler(M32R_IRQ_DMA1, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_DMA1, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_DMA1].icucr = 0;
 	disable_opsput_irq(M32R_IRQ_DMA1);
 
 #ifdef CONFIG_SERIAL_M32R_PLDSIO
 	/* INT#1: SIO0 Receive on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_SIO0_RCV, &opsput_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_SIO0_RCV, &opsput_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_RCV)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_opsput_pld_irq(PLD_IRQ_SIO0_RCV);
 
 	/* INT#1: SIO0 Send on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_SIO0_SND, &opsput_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_SIO0_SND, &opsput_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SIO0_SND)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD03;
 	disable_opsput_pld_irq(PLD_IRQ_SIO0_SND);
 #endif  /* CONFIG_SERIAL_M32R_PLDSIO */
 
 	/* INT#1: CFC IREQ on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_CFIREQ, &opsput_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFIREQ, &opsput_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFIREQ)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* 'L' level sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFIREQ);
 
 	/* INT#1: CFC Insert on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_INSERT, &opsput_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_INSERT, &opsput_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_INSERT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD00;	/* 'L' edge sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFC_INSERT);
 
 	/* INT#1: CFC Eject on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_CFC_EJECT, &opsput_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_CFC_EJECT, &opsput_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_CFC_EJECT)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD02;	/* 'H' edge sense */
 	disable_opsput_pld_irq(PLD_IRQ_CFC_EJECT);
@@ -349,7 +349,7 @@
 
 #if defined(CONFIG_USB)
 	outw(USBCR_OTGS, USBCR);	/* USBCR: non-OTG */
-	set_irq_chip_and_handler(OPSPUT_LCD_IRQ_USB_INT1,
+	irq_set_chip_and_handler(OPSPUT_LCD_IRQ_USB_INT1,
 				 &opsput_lcdpld_irq_type, handle_level_irq);
 	lcdpld_icu_data[irq2lcdpldirq(OPSPUT_LCD_IRQ_USB_INT1)].icucr = PLD_ICUCR_IEN|PLD_ICUCR_ISMOD01;	/* "L" level sense */
 	disable_opsput_lcdpld_irq(OPSPUT_LCD_IRQ_USB_INT1);
@@ -365,7 +365,7 @@
 	/*
 	 * INT3# is used for AR
 	 */
-	set_irq_chip_and_handler(M32R_IRQ_INT3, &opsput_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_INT3, &opsput_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_INT3].icucr = M32R_ICUCR_IEN|M32R_ICUCR_ISMOD10;
 	disable_opsput_irq(M32R_IRQ_INT3);
diff -druN linux-libre-2.6.38-gnu/arch/m32r/platforms/usrv/setup.c linux-libre-2.6.39-gnu/arch/m32r/platforms/usrv/setup.c
--- linux-libre-2.6.38-gnu/arch/m32r/platforms/usrv/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m32r/platforms/usrv/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -138,32 +138,32 @@
 		once++;
 
 	/* MFT2 : system timer */
-	set_irq_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_MFT2, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_MFT2].icucr = M32R_ICUCR_IEN;
 	disable_mappi_irq(M32R_IRQ_MFT2);
 
 #if defined(CONFIG_SERIAL_M32R_SIO)
 	/* SIO0_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_R, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_R);
 
 	/* SIO0_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO0_S, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO0_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO0_S);
 
 	/* SIO1_R : uart receive data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_R, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_R].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_R);
 
 	/* SIO1_S : uart send data */
-	set_irq_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
+	irq_set_chip_and_handler(M32R_IRQ_SIO1_S, &mappi_irq_type,
 				 handle_level_irq);
 	icu_data[M32R_IRQ_SIO1_S].icucr = 0;
 	disable_mappi_irq(M32R_IRQ_SIO1_S);
@@ -171,7 +171,7 @@
 
 	/* INT#67-#71: CFC#0 IREQ on PLD */
 	for (i = 0 ; i < CONFIG_M32R_CFC_NUM ; i++ ) {
-		set_irq_chip_and_handler(PLD_IRQ_CF0 + i,
+		irq_set_chip_and_handler(PLD_IRQ_CF0 + i,
 					 &m32700ut_pld_irq_type,
 					 handle_level_irq);
 		pld_icu_data[irq2pldirq(PLD_IRQ_CF0 + i)].icucr
@@ -181,14 +181,14 @@
 
 #if defined(CONFIG_SERIAL_8250) || defined(CONFIG_SERIAL_8250_MODULE)
 	/* INT#76: 16552D#0 IREQ on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_UART0, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_UART0, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_UART0)].icucr
 		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
 	disable_m32700ut_pld_irq(PLD_IRQ_UART0);
 
 	/* INT#77: 16552D#1 IREQ on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_UART1, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_UART1, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_UART1)].icucr
 		= PLD_ICUCR_ISMOD03;	/* 'H' level sense */
@@ -197,7 +197,7 @@
 
 #if defined(CONFIG_IDC_AK4524) || defined(CONFIG_IDC_AK4524_MODULE)
 	/* INT#80: AK4524 IREQ on PLD */
-	set_irq_chip_and_handler(PLD_IRQ_SNDINT, &m32700ut_pld_irq_type,
+	irq_set_chip_and_handler(PLD_IRQ_SNDINT, &m32700ut_pld_irq_type,
 				 handle_level_irq);
 	pld_icu_data[irq2pldirq(PLD_IRQ_SNDINT)].icucr
 		= PLD_ICUCR_ISMOD01;	/* 'L' level sense */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/amiga/chipram.c linux-libre-2.6.39-gnu/arch/m68k/amiga/chipram.c
--- linux-libre-2.6.38-gnu/arch/m68k/amiga/chipram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/amiga/chipram.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,10 +33,6 @@
     if (!AMIGAHW_PRESENT(CHIP_RAM))
 	return;
 
-    /*
-     *  Remove the first 4 pages where PPC exception handlers will be located
-     */
-    amiga_chip_size -= 0x4000;
     chipram_res.end = amiga_chip_size-1;
     request_resource(&iomem_resource, &chipram_res);
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/atari/atakeyb.c linux-libre-2.6.39-gnu/arch/m68k/atari/atakeyb.c
--- linux-libre-2.6.38-gnu/arch/m68k/atari/atakeyb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/atari/atakeyb.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,7 +130,7 @@
  * it's really hard to decide whether they're mouse or keyboard bytes. Since
  * overruns usually occur when moving the Atari mouse rapidly, they're seen as
  * mouse bytes here. If this is wrong, only a make code of the keyboard gets
- * lost, which isn't too bad. Loosing a break code would be disastrous,
+ * lost, which isn't too bad. Losing a break code would be disastrous,
  * because then the keyboard repeat strikes...
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/bvme6000/config.c linux-libre-2.6.39-gnu/arch/m68k/bvme6000/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/bvme6000/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/bvme6000/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,8 +45,8 @@
 extern void bvme6000_reset (void);
 void bvme6000_set_vectors (void);
 
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c, called via bvme6000_process_int() */
+/* Save tick handler routine pointer, will point to xtime_update() in
+ * kernel/timer/timekeeping.c, called via bvme6000_process_int() */
 
 static irq_handler_t tick_handler;
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/configs/m5208evb_defconfig linux-libre-2.6.39-gnu/arch/m68k/configs/m5208evb_defconfig
--- linux-libre-2.6.38-gnu/arch/m68k/configs/m5208evb_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/configs/m5208evb_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,76 @@
+# CONFIG_MMU is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_COMPAT_BRK is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_M520x=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=166666666
+CONFIG_CLOCK_DIV=2
+CONFIG_M5208EVB=y
+# CONFIG_4KSTACKS is not set
+CONFIG_RAMBASE=0x40000000
+CONFIG_RAMSIZE=0x2000000
+CONFIG_VECTORBASE=0x40000000
+CONFIG_KERNELBASE=0x40020000
+CONFIG_RAM16BIT=y
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=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_IPV6 is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_FEC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_BAUDRATE=115200
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+# CONFIG_SYSFS is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_FULLDEBUG=y
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff -druN linux-libre-2.6.38-gnu/arch/m68k/configs/m5249evb_defconfig linux-libre-2.6.39-gnu/arch/m68k/configs/m5249evb_defconfig
--- linux-libre-2.6.38-gnu/arch/m68k/configs/m5249evb_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/configs/m5249evb_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,69 @@
+# CONFIG_MMU is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_M5249=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=140000000
+CONFIG_CLOCK_DIV=2
+CONFIG_M5249C3=y
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=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_IPV6 is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
+# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68k/configs/m5272c3_defconfig linux-libre-2.6.39-gnu/arch/m68k/configs/m5272c3_defconfig
--- linux-libre-2.6.38-gnu/arch/m68k/configs/m5272c3_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/configs/m5272c3_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,67 @@
+# CONFIG_MMU is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_M5272=y
+CONFIG_CLOCK_SET=y
+CONFIG_M5272C3=y
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=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_IPV6 is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_FEC=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff -druN linux-libre-2.6.38-gnu/arch/m68k/configs/m5275evb_defconfig linux-libre-2.6.39-gnu/arch/m68k/configs/m5275evb_defconfig
--- linux-libre-2.6.38-gnu/arch/m68k/configs/m5275evb_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/configs/m5275evb_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,74 @@
+# CONFIG_MMU is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_M5275=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=150000000
+CONFIG_CLOCK_DIV=2
+CONFIG_M5275EVB=y
+# CONFIG_4KSTACKS is not set
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00000000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=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_IPV6 is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_FEC=y
+CONFIG_FEC2=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+# CONFIG_INPUT is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
+# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68k/configs/m5307c3_defconfig linux-libre-2.6.39-gnu/arch/m68k/configs/m5307c3_defconfig
--- linux-libre-2.6.38-gnu/arch/m68k/configs/m5307c3_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/configs/m5307c3_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,77 @@
+# CONFIG_MMU is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+# CONFIG_SLUB_DEBUG is not set
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_M5307=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=90000000
+CONFIG_CLOCK_DIV=2
+CONFIG_M5307C3=y
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00800000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=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_IPV6 is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+CONFIG_SLIP=y
+CONFIG_SLIP_COMPRESSED=y
+# CONFIG_INPUT_MOUSEDEV is not set
+# CONFIG_INPUT_KEYBOARD is not set
+# CONFIG_INPUT_MOUSE is not set
+# CONFIG_SERIO is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_LEGACY_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_HID_SUPPORT is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_DNOTIFY is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_FULLDEBUG=y
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
+# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68k/configs/m5407c3_defconfig linux-libre-2.6.39-gnu/arch/m68k/configs/m5407c3_defconfig
--- linux-libre-2.6.38-gnu/arch/m68k/configs/m5407c3_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/configs/m5407c3_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,71 @@
+# CONFIG_MMU is not set
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOG_BUF_SHIFT=14
+# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
+CONFIG_EXPERT=y
+# CONFIG_KALLSYMS is not set
+# CONFIG_HOTPLUG is not set
+# CONFIG_FUTEX is not set
+# CONFIG_EPOLL is not set
+# CONFIG_SIGNALFD is not set
+# CONFIG_TIMERFD is not set
+# CONFIG_EVENTFD is not set
+# CONFIG_AIO is not set
+# CONFIG_VM_EVENT_COUNTERS is not set
+CONFIG_MODULES=y
+CONFIG_MODULE_UNLOAD=y
+# CONFIG_BLK_DEV_BSG is not set
+# CONFIG_IOSCHED_DEADLINE is not set
+# CONFIG_IOSCHED_CFQ is not set
+CONFIG_M5407=y
+CONFIG_CLOCK_SET=y
+CONFIG_CLOCK_FREQ=50000000
+CONFIG_M5407C3=y
+CONFIG_RAMBASE=0x00000000
+CONFIG_RAMSIZE=0x00000000
+CONFIG_VECTORBASE=0x00000000
+CONFIG_KERNELBASE=0x00020000
+CONFIG_BINFMT_FLAT=y
+CONFIG_NET=y
+CONFIG_PACKET=y
+CONFIG_UNIX=y
+CONFIG_INET=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_IPV6 is not set
+# CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_RAM=y
+CONFIG_MTD_UCLINUX=y
+CONFIG_BLK_DEV_RAM=y
+# CONFIG_MISC_DEVICES is not set
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+# CONFIG_NETDEV_1000 is not set
+# CONFIG_NETDEV_10000 is not set
+CONFIG_PPP=y
+# CONFIG_INPUT is not set
+# CONFIG_VT is not set
+CONFIG_SERIAL_MCF=y
+CONFIG_SERIAL_MCF_CONSOLE=y
+# CONFIG_UNIX98_PTYS is not set
+# CONFIG_HW_RANDOM is not set
+# CONFIG_HWMON is not set
+# CONFIG_USB_SUPPORT is not set
+CONFIG_EXT2_FS=y
+# CONFIG_FILE_LOCKING is not set
+# CONFIG_DNOTIFY is not set
+CONFIG_ROMFS_FS=y
+CONFIG_ROMFS_BACKED_BY_MTD=y
+# CONFIG_NETWORK_FILESYSTEMS is not set
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_BOOTPARAM=y
+CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
+# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68k/emu/Makefile linux-libre-2.6.39-gnu/arch/m68k/emu/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/emu/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/emu/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,9 @@
+#
+# Makefile for Linux arch/m68k/emu source directory
+#
+
+obj-y			+= natfeat.o
+
+obj-$(CONFIG_NFBLOCK)	+= nfblock.o
+obj-$(CONFIG_NFCON)	+= nfcon.o
+obj-$(CONFIG_NFETH)	+= nfeth.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/emu/natfeat.c linux-libre-2.6.39-gnu/arch/m68k/emu/natfeat.c
--- linux-libre-2.6.38-gnu/arch/m68k/emu/natfeat.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/emu/natfeat.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,78 @@
+/*
+ * natfeat.c - ARAnyM hardware support via Native Features (natfeats)
+ *
+ * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
+ *
+ * Reworked for Linux by Roman Zippel <zippel@linux-m68k.org>
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#include <linux/types.h>
+#include <linux/console.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/natfeat.h>
+
+asm("\n"
+"	.global nf_get_id,nf_call\n"
+"nf_get_id:\n"
+"	.short	0x7300\n"
+"	rts\n"
+"nf_call:\n"
+"	.short	0x7301\n"
+"	rts\n"
+"1:	moveq.l	#0,%d0\n"
+"	rts\n"
+"	.section __ex_table,\"a\"\n"
+"	.long	nf_get_id,1b\n"
+"	.long	nf_call,1b\n"
+"	.previous");
+EXPORT_SYMBOL_GPL(nf_get_id);
+EXPORT_SYMBOL_GPL(nf_call);
+
+void nfprint(const char *fmt, ...)
+{
+	static char buf[256];
+	va_list ap;
+	int n;
+
+	va_start(ap, fmt);
+	n = vsnprintf(buf, 256, fmt, ap);
+	nf_call(nf_get_id("NF_STDERR"), buf);
+	va_end(ap);
+}
+
+static void nf_poweroff(void)
+{
+	long id = nf_get_id("NF_SHUTDOWN");
+
+	if (id)
+		nf_call(id);
+}
+
+void nf_init(void)
+{
+	unsigned long id, version;
+	char buf[256];
+
+	id = nf_get_id("NF_VERSION");
+	if (!id)
+		return;
+	version = nf_call(id);
+
+	id = nf_get_id("NF_NAME");
+	if (!id)
+		return;
+	nf_call(id, buf, 256);
+	buf[255] = 0;
+
+	pr_info("NatFeats found (%s, %lu.%lu)\n", buf, version >> 16,
+		version & 0xffff);
+
+	mach_power_off = nf_poweroff;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/emu/nfblock.c linux-libre-2.6.39-gnu/arch/m68k/emu/nfblock.c
--- linux-libre-2.6.38-gnu/arch/m68k/emu/nfblock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/emu/nfblock.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * ARAnyM block device driver
+ *
+ * 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/moduleparam.h>
+#include <linux/init.h>
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/genhd.h>
+#include <linux/blkdev.h>
+#include <linux/hdreg.h>
+#include <linux/slab.h>
+
+#include <asm/natfeat.h>
+
+static long nfhd_id;
+
+enum {
+	/* emulation entry points */
+	NFHD_READ_WRITE = 10,
+	NFHD_GET_CAPACITY = 14,
+
+	/* skip ACSI devices */
+	NFHD_DEV_OFFSET = 8,
+};
+
+static inline s32 nfhd_read_write(u32 major, u32 minor, u32 rwflag, u32 recno,
+				  u32 count, u32 buf)
+{
+	return nf_call(nfhd_id + NFHD_READ_WRITE, major, minor, rwflag, recno,
+		       count, buf);
+}
+
+static inline s32 nfhd_get_capacity(u32 major, u32 minor, u32 *blocks,
+				    u32 *blocksize)
+{
+	return nf_call(nfhd_id + NFHD_GET_CAPACITY, major, minor, blocks,
+		       blocksize);
+}
+
+static LIST_HEAD(nfhd_list);
+
+static int major_num;
+module_param(major_num, int, 0);
+
+struct nfhd_device {
+	struct list_head list;
+	int id;
+	u32 blocks, bsize;
+	int bshift;
+	struct request_queue *queue;
+	struct gendisk *disk;
+};
+
+static int nfhd_make_request(struct request_queue *queue, struct bio *bio)
+{
+	struct nfhd_device *dev = queue->queuedata;
+	struct bio_vec *bvec;
+	int i, dir, len, shift;
+	sector_t sec = bio->bi_sector;
+
+	dir = bio_data_dir(bio);
+	shift = dev->bshift;
+	bio_for_each_segment(bvec, bio, i) {
+		len = bvec->bv_len;
+		len >>= 9;
+		nfhd_read_write(dev->id, 0, dir, sec >> shift, len >> shift,
+				bvec_to_phys(bvec));
+		sec += len;
+	}
+	bio_endio(bio, 0);
+	return 0;
+}
+
+static int nfhd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
+{
+	struct nfhd_device *dev = bdev->bd_disk->private_data;
+
+	geo->cylinders = dev->blocks >> (6 - dev->bshift);
+	geo->heads = 4;
+	geo->sectors = 16;
+
+	return 0;
+}
+
+static const struct block_device_operations nfhd_ops = {
+	.owner	= THIS_MODULE,
+	.getgeo	= nfhd_getgeo,
+};
+
+static int __init nfhd_init_one(int id, u32 blocks, u32 bsize)
+{
+	struct nfhd_device *dev;
+	int dev_id = id - NFHD_DEV_OFFSET;
+
+	pr_info("nfhd%u: found device with %u blocks (%u bytes)\n", dev_id,
+		blocks, bsize);
+
+	if (bsize < 512 || (bsize & (bsize - 1))) {
+		pr_warn("nfhd%u: invalid block size\n", dev_id);
+		return -EINVAL;
+	}
+
+	dev = kmalloc(sizeof(struct nfhd_device), GFP_KERNEL);
+	if (!dev)
+		goto out;
+
+	dev->id = id;
+	dev->blocks = blocks;
+	dev->bsize = bsize;
+	dev->bshift = ffs(bsize) - 10;
+
+	dev->queue = blk_alloc_queue(GFP_KERNEL);
+	if (dev->queue == NULL)
+		goto free_dev;
+
+	dev->queue->queuedata = dev;
+	blk_queue_make_request(dev->queue, nfhd_make_request);
+	blk_queue_logical_block_size(dev->queue, bsize);
+
+	dev->disk = alloc_disk(16);
+	if (!dev->disk)
+		goto free_queue;
+
+	dev->disk->major = major_num;
+	dev->disk->first_minor = dev_id * 16;
+	dev->disk->fops = &nfhd_ops;
+	dev->disk->private_data = dev;
+	sprintf(dev->disk->disk_name, "nfhd%u", dev_id);
+	set_capacity(dev->disk, (sector_t)blocks * (bsize / 512));
+	dev->disk->queue = dev->queue;
+
+	add_disk(dev->disk);
+
+	list_add_tail(&dev->list, &nfhd_list);
+
+	return 0;
+
+free_queue:
+	blk_cleanup_queue(dev->queue);
+free_dev:
+	kfree(dev);
+out:
+	return -ENOMEM;
+}
+
+static int __init nfhd_init(void)
+{
+	u32 blocks, bsize;
+	int i;
+
+	nfhd_id = nf_get_id("XHDI");
+	if (!nfhd_id)
+		return -ENODEV;
+
+	major_num = register_blkdev(major_num, "nfhd");
+	if (major_num <= 0) {
+		pr_warn("nfhd: unable to get major number\n");
+		return major_num;
+	}
+
+	for (i = NFHD_DEV_OFFSET; i < 24; i++) {
+		if (nfhd_get_capacity(i, 0, &blocks, &bsize))
+			continue;
+		nfhd_init_one(i, blocks, bsize);
+	}
+
+	return 0;
+}
+
+static void __exit nfhd_exit(void)
+{
+	struct nfhd_device *dev, *next;
+
+	list_for_each_entry_safe(dev, next, &nfhd_list, list) {
+		list_del(&dev->list);
+		del_gendisk(dev->disk);
+		put_disk(dev->disk);
+		blk_cleanup_queue(dev->queue);
+		kfree(dev);
+	}
+	unregister_blkdev(major_num, "nfhd");
+}
+
+module_init(nfhd_init);
+module_exit(nfhd_exit);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/arch/m68k/emu/nfcon.c linux-libre-2.6.39-gnu/arch/m68k/emu/nfcon.c
--- linux-libre-2.6.38-gnu/arch/m68k/emu/nfcon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/emu/nfcon.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,162 @@
+/*
+ * ARAnyM console driver
+ *
+ * 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/init.h>
+#include <linux/console.h>
+#include <linux/tty.h>
+#include <linux/tty_driver.h>
+#include <linux/tty_flip.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/uaccess.h>
+
+#include <asm/natfeat.h>
+
+static int stderr_id;
+static struct tty_driver *nfcon_tty_driver;
+
+static void nfputs(const char *str, unsigned int count)
+{
+	char buf[68];
+
+	buf[64] = 0;
+	while (count > 64) {
+		memcpy(buf, str, 64);
+		nf_call(stderr_id, buf);
+		str += 64;
+		count -= 64;
+	}
+	memcpy(buf, str, count);
+	buf[count] = 0;
+	nf_call(stderr_id, buf);
+}
+
+static void nfcon_write(struct console *con, const char *str,
+			unsigned int count)
+{
+	nfputs(str, count);
+}
+
+static struct tty_driver *nfcon_device(struct console *con, int *index)
+{
+	*index = 0;
+	return (con->flags & CON_ENABLED) ? nfcon_tty_driver : NULL;
+}
+
+static struct console nf_console = {
+	.name	= "nfcon",
+	.write	= nfcon_write,
+	.device	= nfcon_device,
+	.flags	= CON_PRINTBUFFER,
+	.index	= -1,
+};
+
+
+static int nfcon_tty_open(struct tty_struct *tty, struct file *filp)
+{
+	return 0;
+}
+
+static void nfcon_tty_close(struct tty_struct *tty, struct file *filp)
+{
+}
+
+static int nfcon_tty_write(struct tty_struct *tty, const unsigned char *buf,
+			   int count)
+{
+	nfputs(buf, count);
+	return count;
+}
+
+static int nfcon_tty_put_char(struct tty_struct *tty, unsigned char ch)
+{
+	char temp[2] = { ch, 0 };
+
+	nf_call(stderr_id, temp);
+	return 1;
+}
+
+static int nfcon_tty_write_room(struct tty_struct *tty)
+{
+	return 64;
+}
+
+static const struct tty_operations nfcon_tty_ops = {
+	.open		= nfcon_tty_open,
+	.close		= nfcon_tty_close,
+	.write		= nfcon_tty_write,
+	.put_char	= nfcon_tty_put_char,
+	.write_room	= nfcon_tty_write_room,
+};
+
+#ifndef MODULE
+
+static int __init nf_debug_setup(char *arg)
+{
+	if (strcmp(arg, "nfcon"))
+		return 0;
+
+	stderr_id = nf_get_id("NF_STDERR");
+	if (stderr_id) {
+		nf_console.flags |= CON_ENABLED;
+		register_console(&nf_console);
+	}
+
+	return 0;
+}
+
+early_param("debug", nf_debug_setup);
+
+#endif /* !MODULE */
+
+static int __init nfcon_init(void)
+{
+	int res;
+
+	stderr_id = nf_get_id("NF_STDERR");
+	if (!stderr_id)
+		return -ENODEV;
+
+	nfcon_tty_driver = alloc_tty_driver(1);
+	if (!nfcon_tty_driver)
+		return -ENOMEM;
+
+	nfcon_tty_driver->owner = THIS_MODULE;
+	nfcon_tty_driver->driver_name = "nfcon";
+	nfcon_tty_driver->name = "nfcon";
+	nfcon_tty_driver->type = TTY_DRIVER_TYPE_SYSTEM;
+	nfcon_tty_driver->subtype = SYSTEM_TYPE_TTY;
+	nfcon_tty_driver->init_termios = tty_std_termios;
+	nfcon_tty_driver->flags = TTY_DRIVER_REAL_RAW;
+
+	tty_set_operations(nfcon_tty_driver, &nfcon_tty_ops);
+	res = tty_register_driver(nfcon_tty_driver);
+	if (res) {
+		pr_err("failed to register nfcon tty driver\n");
+		put_tty_driver(nfcon_tty_driver);
+		return res;
+	}
+
+	if (!(nf_console.flags & CON_ENABLED))
+		register_console(&nf_console);
+
+	return 0;
+}
+
+static void __exit nfcon_exit(void)
+{
+	unregister_console(&nf_console);
+	tty_unregister_driver(nfcon_tty_driver);
+	put_tty_driver(nfcon_tty_driver);
+}
+
+module_init(nfcon_init);
+module_exit(nfcon_exit);
+
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/arch/m68k/emu/nfeth.c linux-libre-2.6.39-gnu/arch/m68k/emu/nfeth.c
--- linux-libre-2.6.38-gnu/arch/m68k/emu/nfeth.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/emu/nfeth.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,270 @@
+/*
+ * atari_nfeth.c - ARAnyM ethernet card driver for GNU/Linux
+ *
+ * Copyright (c) 2005 Milan Jurik, Petr Stehlik of ARAnyM dev team
+ *
+ * Based on ARAnyM driver for FreeMiNT written by Standa Opichal
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#define DRV_VERSION	"0.3"
+#define DRV_RELDATE	"10/12/2005"
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/module.h>
+#include <asm/natfeat.h>
+#include <asm/virtconvert.h>
+
+enum {
+	GET_VERSION = 0,/* no parameters, return NFAPI_VERSION in d0 */
+	XIF_INTLEVEL,	/* no parameters, return Interrupt Level in d0 */
+	XIF_IRQ,	/* acknowledge interrupt from host */
+	XIF_START,	/* (ethX), called on 'ifup', start receiver thread */
+	XIF_STOP,	/* (ethX), called on 'ifdown', stop the thread */
+	XIF_READLENGTH,	/* (ethX), return size of network data block to read */
+	XIF_READBLOCK,	/* (ethX, buffer, size), read block of network data */
+	XIF_WRITEBLOCK,	/* (ethX, buffer, size), write block of network data */
+	XIF_GET_MAC,	/* (ethX, buffer, size), return MAC HW addr in buffer */
+	XIF_GET_IPHOST,	/* (ethX, buffer, size), return IP address of host */
+	XIF_GET_IPATARI,/* (ethX, buffer, size), return IP address of atari */
+	XIF_GET_NETMASK	/* (ethX, buffer, size), return IP netmask */
+};
+
+#define MAX_UNIT	8
+
+/* These identify the driver base version and may not be removed. */
+static const char version[] __devinitdata =
+	KERN_INFO KBUILD_MODNAME ".c:v" DRV_VERSION " " DRV_RELDATE
+	" S.Opichal, M.Jurik, P.Stehlik\n"
+	KERN_INFO " http://aranym.org/\n";
+
+MODULE_AUTHOR("Milan Jurik");
+MODULE_DESCRIPTION("Atari NFeth driver");
+MODULE_LICENSE("GPL");
+/*
+MODULE_PARM(nfeth_debug, "i");
+MODULE_PARM_DESC(nfeth_debug, "nfeth_debug level (1-2)");
+*/
+
+
+static long nfEtherID;
+static int nfEtherIRQ;
+
+struct nfeth_private {
+	int ethX;
+};
+
+static struct net_device *nfeth_dev[MAX_UNIT];
+
+static int nfeth_open(struct net_device *dev)
+{
+	struct nfeth_private *priv = netdev_priv(dev);
+	int res;
+
+	res = nf_call(nfEtherID + XIF_START, priv->ethX);
+	netdev_dbg(dev, "%s: %d\n", __func__, res);
+
+	/* Ready for data */
+	netif_start_queue(dev);
+
+	return 0;
+}
+
+static int nfeth_stop(struct net_device *dev)
+{
+	struct nfeth_private *priv = netdev_priv(dev);
+
+	/* No more data */
+	netif_stop_queue(dev);
+
+	nf_call(nfEtherID + XIF_STOP, priv->ethX);
+
+	return 0;
+}
+
+/*
+ * Read a packet out of the adapter and pass it to the upper layers
+ */
+static inline void recv_packet(struct net_device *dev)
+{
+	struct nfeth_private *priv = netdev_priv(dev);
+	unsigned short pktlen;
+	struct sk_buff *skb;
+
+	/* read packet length (excluding 32 bit crc) */
+	pktlen = nf_call(nfEtherID + XIF_READLENGTH, priv->ethX);
+
+	netdev_dbg(dev, "%s: %u\n", __func__, pktlen);
+
+	if (!pktlen) {
+		netdev_dbg(dev, "%s: pktlen == 0\n", __func__);
+		dev->stats.rx_errors++;
+		return;
+	}
+
+	skb = dev_alloc_skb(pktlen + 2);
+	if (!skb) {
+		netdev_dbg(dev, "%s: out of mem (buf_alloc failed)\n",
+			   __func__);
+		dev->stats.rx_dropped++;
+		return;
+	}
+
+	skb->dev = dev;
+	skb_reserve(skb, 2);		/* 16 Byte align  */
+	skb_put(skb, pktlen);		/* make room */
+	nf_call(nfEtherID + XIF_READBLOCK, priv->ethX, virt_to_phys(skb->data),
+		pktlen);
+
+	skb->protocol = eth_type_trans(skb, dev);
+	netif_rx(skb);
+	dev->last_rx = jiffies;
+	dev->stats.rx_packets++;
+	dev->stats.rx_bytes += pktlen;
+
+	/* and enqueue packet */
+	return;
+}
+
+static irqreturn_t nfeth_interrupt(int irq, void *dev_id)
+{
+	int i, m, mask;
+
+	mask = nf_call(nfEtherID + XIF_IRQ, 0);
+	for (i = 0, m = 1; i < MAX_UNIT; m <<= 1, i++) {
+		if (mask & m && nfeth_dev[i]) {
+			recv_packet(nfeth_dev[i]);
+			nf_call(nfEtherID + XIF_IRQ, m);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+static int nfeth_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	unsigned int len;
+	char *data, shortpkt[ETH_ZLEN];
+	struct nfeth_private *priv = netdev_priv(dev);
+
+	data = skb->data;
+	len = skb->len;
+	if (len < ETH_ZLEN) {
+		memset(shortpkt, 0, ETH_ZLEN);
+		memcpy(shortpkt, data, len);
+		data = shortpkt;
+		len = ETH_ZLEN;
+	}
+
+	netdev_dbg(dev, "%s: send %u bytes\n", __func__, len);
+	nf_call(nfEtherID + XIF_WRITEBLOCK, priv->ethX, virt_to_phys(data),
+		len);
+
+	dev->stats.tx_packets++;
+	dev->stats.tx_bytes += len;
+
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+static void nfeth_tx_timeout(struct net_device *dev)
+{
+	dev->stats.tx_errors++;
+	netif_wake_queue(dev);
+}
+
+static const struct net_device_ops nfeth_netdev_ops = {
+	.ndo_open		= nfeth_open,
+	.ndo_stop		= nfeth_stop,
+	.ndo_start_xmit		= nfeth_xmit,
+	.ndo_tx_timeout		= nfeth_tx_timeout,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_change_mtu		= eth_change_mtu,
+	.ndo_set_mac_address	= eth_mac_addr,
+};
+
+static struct net_device * __init nfeth_probe(int unit)
+{
+	struct net_device *dev;
+	struct nfeth_private *priv;
+	char mac[ETH_ALEN], host_ip[32], local_ip[32];
+	int err;
+
+	if (!nf_call(nfEtherID + XIF_GET_MAC, unit, mac, ETH_ALEN))
+		return NULL;
+
+	dev = alloc_etherdev(sizeof(struct nfeth_private));
+	if (!dev)
+		return NULL;
+
+	dev->irq = nfEtherIRQ;
+	dev->netdev_ops = &nfeth_netdev_ops;
+
+	dev->flags |= NETIF_F_NO_CSUM;
+	memcpy(dev->dev_addr, mac, ETH_ALEN);
+
+	priv = netdev_priv(dev);
+	priv->ethX = unit;
+
+	err = register_netdev(dev);
+	if (err) {
+		free_netdev(dev);
+		return NULL;
+	}
+
+	nf_call(nfEtherID + XIF_GET_IPHOST, unit,
+		host_ip, sizeof(host_ip));
+	nf_call(nfEtherID + XIF_GET_IPATARI, unit,
+		local_ip, sizeof(local_ip));
+
+	netdev_info(dev, KBUILD_MODNAME " addr:%s (%s) HWaddr:%pM\n", host_ip,
+		    local_ip, mac);
+
+	return dev;
+}
+
+static int __init nfeth_init(void)
+{
+	long ver;
+	int error, i;
+
+	nfEtherID = nf_get_id("ETHERNET");
+	if (!nfEtherID)
+		return -ENODEV;
+
+	ver = nf_call(nfEtherID + GET_VERSION);
+	pr_info("API %lu\n", ver);
+
+	nfEtherIRQ = nf_call(nfEtherID + XIF_INTLEVEL);
+	error = request_irq(nfEtherIRQ, nfeth_interrupt, IRQF_SHARED,
+			    "eth emu", nfeth_interrupt);
+	if (error) {
+		pr_err("request for irq %d failed %d", nfEtherIRQ, error);
+		return error;
+	}
+
+	for (i = 0; i < MAX_UNIT; i++)
+		nfeth_dev[i] = nfeth_probe(i);
+
+	return 0;
+}
+
+static void __exit nfeth_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < MAX_UNIT; i++) {
+		if (nfeth_dev[i]) {
+			unregister_netdev(nfeth_dev[0]);
+			free_netdev(nfeth_dev[0]);
+		}
+	}
+	free_irq(nfEtherIRQ, nfeth_interrupt);
+}
+
+module_init(nfeth_init);
+module_exit(nfeth_cleanup);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/fpsp040/bindec.S linux-libre-2.6.39-gnu/arch/m68k/fpsp040/bindec.S
--- linux-libre-2.6.38-gnu/arch/m68k/fpsp040/bindec.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/fpsp040/bindec.S	2011-05-19 00:06:34.000000000 -0400
@@ -609,7 +609,7 @@
 |      A6.  This test occurs only on the first pass.  If the
 |      result is exactly 10^LEN, decrement ILOG and divide
 |      the mantissa by 10.  The calculation of 10^LEN cannot
-|      be inexact, since all powers of ten upto 10^27 are exact
+|      be inexact, since all powers of ten up to 10^27 are exact
 |      in extended precision, so the use of a previous power-of-ten
 |      table will introduce no error.
 |
diff -druN linux-libre-2.6.38-gnu/arch/m68k/ifpsp060/src/fpsp.S linux-libre-2.6.39-gnu/arch/m68k/ifpsp060/src/fpsp.S
--- linux-libre-2.6.38-gnu/arch/m68k/ifpsp060/src/fpsp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/ifpsp060/src/fpsp.S	2011-05-19 00:06:34.000000000 -0400
@@ -11813,7 +11813,7 @@
 	bne.b		fmul_unfl_ena_sd	# no, sgl or dbl
 
 # if the rnd mode is anything but RZ, then we have to re-do the above
-# multiplication becuase we used RZ for all.
+# multiplication because we used RZ for all.
 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
 
 fmul_unfl_ena_cont:
@@ -18095,7 +18095,7 @@
 
 	rts
 
-# addresing mode is post-increment. write the result byte. if the write
+# addressing mode is post-increment. write the result byte. if the write
 # fails then don't update the address register. if write passes then
 # call inc_areg() to update the address register.
 fscc_mem_inc:
@@ -20876,7 +20876,7 @@
 	swap		%d0			# d0 now in upper word
 	lsl.l		&0x4,%d0		# d0 in proper place for dbl prec exp
 	tst.b		FTEMP_EX(%a0)		# test sign
-	bpl.b		dst_get_dman		# if postive, go process mantissa
+	bpl.b		dst_get_dman		# if positive, go process mantissa
 	bset		&0x1f,%d0		# if negative, set sign
 dst_get_dman:
 	mov.l		FTEMP_HI(%a0),%d1	# get ms mantissa
@@ -22943,7 +22943,7 @@
 #	FP_SRC(a6) = packed operand now as a binary FP number		#
 #									#
 # ALGORITHM ***********************************************************	#
-#	Get the correct <ea> whihc is the value on the exception stack	#
+#	Get the correct <ea> which is the value on the exception stack	#
 # frame w/ maybe a correction factor if the <ea> is -(an) or (an)+.	#
 # Then, fetch the operand from memory. If the fetch fails, exit		#
 # through facc_in_x().							#
@@ -24096,7 +24096,7 @@
 #      A6.  This test occurs only on the first pass.  If the
 #      result is exactly 10^LEN, decrement ILOG and divide
 #      the mantissa by 10.  The calculation of 10^LEN cannot
-#      be inexact, since all powers of ten upto 10^27 are exact
+#      be inexact, since all powers of ten up to 10^27 are exact
 #      in extended precision, so the use of a previous power-of-ten
 #      table will introduce no error.
 #
diff -druN linux-libre-2.6.38-gnu/arch/m68k/ifpsp060/src/pfpsp.S linux-libre-2.6.39-gnu/arch/m68k/ifpsp060/src/pfpsp.S
--- linux-libre-2.6.38-gnu/arch/m68k/ifpsp060/src/pfpsp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/ifpsp060/src/pfpsp.S	2011-05-19 00:06:34.000000000 -0400
@@ -7777,7 +7777,7 @@
 	swap		%d0			# d0 now in upper word
 	lsl.l		&0x4,%d0		# d0 in proper place for dbl prec exp
 	tst.b		FTEMP_EX(%a0)		# test sign
-	bpl.b		dst_get_dman		# if postive, go process mantissa
+	bpl.b		dst_get_dman		# if positive, go process mantissa
 	bset		&0x1f,%d0		# if negative, set sign
 dst_get_dman:
 	mov.l		FTEMP_HI(%a0),%d1	# get ms mantissa
@@ -8244,7 +8244,7 @@
 	bne.b		fmul_unfl_ena_sd	# no, sgl or dbl
 
 # if the rnd mode is anything but RZ, then we have to re-do the above
-# multiplication becuase we used RZ for all.
+# multiplication because we used RZ for all.
 	fmov.l		L_SCR3(%a6),%fpcr	# set FPCR
 
 fmul_unfl_ena_cont:
@@ -12903,7 +12903,7 @@
 #	FP_SRC(a6) = packed operand now as a binary FP number		#
 #									#
 # ALGORITHM ***********************************************************	#
-#	Get the correct <ea> whihc is the value on the exception stack	#
+#	Get the correct <ea> which is the value on the exception stack	#
 # frame w/ maybe a correction factor if the <ea> is -(an) or (an)+.	#
 # Then, fetch the operand from memory. If the fetch fails, exit		#
 # through facc_in_x().							#
@@ -14056,7 +14056,7 @@
 #      A6.  This test occurs only on the first pass.  If the
 #      result is exactly 10^LEN, decrement ILOG and divide
 #      the mantissa by 10.  The calculation of 10^LEN cannot
-#      be inexact, since all powers of ten upto 10^27 are exact
+#      be inexact, since all powers of ten up to 10^27 are exact
 #      in extended precision, so the use of a previous power-of-ten
 #      table will introduce no error.
 #
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/atariints.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/atariints.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/atariints.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/atariints.h	2011-05-19 00:06:34.000000000 -0400
@@ -146,7 +146,7 @@
 
 /*
  * {en,dis}able_irq have the usual semantics of temporary blocking the
- * interrupt, but not loosing requests that happen between disabling and
+ * interrupt, but not losing requests that happen between disabling and
  * enabling. This is done with the MFP mask registers.
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/bitops_mm.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/bitops_mm.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/bitops_mm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/bitops_mm.h	2011-05-19 00:06:34.000000000 -0400
@@ -325,58 +325,45 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 
-/* Bitmap functions for the minix filesystem */
+/* Bitmap functions for the little endian bitmap. */
 
-static inline int minix_find_first_zero_bit(const void *vaddr, unsigned size)
+static inline void __set_bit_le(int nr, void *addr)
 {
-	const unsigned short *p = vaddr, *addr = vaddr;
-	int res;
-	unsigned short num;
-
-	if (!size)
-		return 0;
-
-	size = (size >> 4) + ((size & 15) > 0);
-	while (*p++ == 0xffff)
-	{
-		if (--size == 0)
-			return (p - addr) << 4;
-	}
+	__set_bit(nr ^ 24, addr);
+}
 
-	num = ~*--p;
-	__asm__ __volatile__ ("bfffo %1{#16,#16},%0"
-			      : "=d" (res) : "d" (num & -num));
-	return ((p - addr) << 4) + (res ^ 31);
+static inline void __clear_bit_le(int nr, void *addr)
+{
+	__clear_bit(nr ^ 24, addr);
 }
 
-#define minix_test_and_set_bit(nr, addr)	__test_and_set_bit((nr) ^ 16, (unsigned long *)(addr))
-#define minix_set_bit(nr,addr)			__set_bit((nr) ^ 16, (unsigned long *)(addr))
-#define minix_test_and_clear_bit(nr, addr)	__test_and_clear_bit((nr) ^ 16, (unsigned long *)(addr))
+static inline int __test_and_set_bit_le(int nr, void *addr)
+{
+	return __test_and_set_bit(nr ^ 24, addr);
+}
 
-static inline int minix_test_bit(int nr, const void *vaddr)
+static inline int test_and_set_bit_le(int nr, void *addr)
 {
-	const unsigned short *p = vaddr;
-	return (p[nr >> 4] & (1U << (nr & 15))) != 0;
+	return test_and_set_bit(nr ^ 24, addr);
 }
 
-/* Bitmap functions for the ext2 filesystem. */
+static inline int __test_and_clear_bit_le(int nr, void *addr)
+{
+	return __test_and_clear_bit(nr ^ 24, addr);
+}
 
-#define ext2_set_bit(nr, addr)			__test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
-#define ext2_set_bit_atomic(lock, nr, addr)	test_and_set_bit((nr) ^ 24, (unsigned long *)(addr))
-#define ext2_clear_bit(nr, addr)		__test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
-#define ext2_clear_bit_atomic(lock, nr, addr)	test_and_clear_bit((nr) ^ 24, (unsigned long *)(addr))
-#define ext2_find_next_zero_bit(addr, size, offset) \
-	generic_find_next_zero_le_bit((unsigned long *)addr, size, offset)
-#define ext2_find_next_bit(addr, size, offset) \
-	generic_find_next_le_bit((unsigned long *)addr, size, offset)
+static inline int test_and_clear_bit_le(int nr, void *addr)
+{
+	return test_and_clear_bit(nr ^ 24, addr);
+}
 
-static inline int ext2_test_bit(int nr, const void *vaddr)
+static inline int test_bit_le(int nr, const void *vaddr)
 {
 	const unsigned char *p = vaddr;
 	return (p[nr >> 3] & (1U << (nr & 7))) != 0;
 }
 
-static inline int ext2_find_first_zero_bit(const void *vaddr, unsigned size)
+static inline int find_first_zero_bit_le(const void *vaddr, unsigned size)
 {
 	const unsigned long *p = vaddr, *addr = vaddr;
 	int res;
@@ -393,33 +380,36 @@
 
 	--p;
 	for (res = 0; res < 32; res++)
-		if (!ext2_test_bit (res, p))
+		if (!test_bit_le(res, p))
 			break;
 	return (p - addr) * 32 + res;
 }
 
-static inline unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
+static inline unsigned long find_next_zero_bit_le(const void *addr,
 		unsigned long size, unsigned long offset)
 {
-	const unsigned long *p = addr + (offset >> 5);
+	const unsigned long *p = addr;
 	int bit = offset & 31UL, res;
 
 	if (offset >= size)
 		return size;
 
+	p += offset >> 5;
+
 	if (bit) {
+		offset -= bit;
 		/* Look for zero in first longword */
 		for (res = bit; res < 32; res++)
-			if (!ext2_test_bit (res, p))
-				return (p - addr) * 32 + res;
+			if (!test_bit_le(res, p))
+				return offset + res;
 		p++;
+		offset += 32;
 	}
 	/* No zero yet, search remaining full bytes for a zero */
-	res = ext2_find_first_zero_bit (p, size - 32 * (p - addr));
-	return (p - addr) * 32 + res;
+	return offset + find_first_zero_bit_le(p, size - offset);
 }
 
-static inline int ext2_find_first_bit(const void *vaddr, unsigned size)
+static inline int find_first_bit_le(const void *vaddr, unsigned size)
 {
 	const unsigned long *p = vaddr, *addr = vaddr;
 	int res;
@@ -435,32 +425,42 @@
 
 	--p;
 	for (res = 0; res < 32; res++)
-		if (ext2_test_bit(res, p))
+		if (test_bit_le(res, p))
 			break;
 	return (p - addr) * 32 + res;
 }
 
-static inline unsigned long generic_find_next_le_bit(const unsigned long *addr,
+static inline unsigned long find_next_bit_le(const void *addr,
 		unsigned long size, unsigned long offset)
 {
-	const unsigned long *p = addr + (offset >> 5);
+	const unsigned long *p = addr;
 	int bit = offset & 31UL, res;
 
 	if (offset >= size)
 		return size;
 
+	p += offset >> 5;
+
 	if (bit) {
+		offset -= bit;
 		/* Look for one in first longword */
 		for (res = bit; res < 32; res++)
-			if (ext2_test_bit(res, p))
-				return (p - addr) * 32 + res;
+			if (test_bit_le(res, p))
+				return offset + res;
 		p++;
+		offset += 32;
 	}
 	/* No set bit yet, search remaining full bytes for a set bit */
-	res = ext2_find_first_bit(p, size - 32 * (p - addr));
-	return (p - addr) * 32 + res;
+	return offset + find_first_bit_le(p, size - offset);
 }
 
+/* Bitmap functions for the ext2 filesystem. */
+
+#define ext2_set_bit_atomic(lock, nr, addr)	\
+	test_and_set_bit_le(nr, addr)
+#define ext2_clear_bit_atomic(lock, nr, addr)	\
+	test_and_clear_bit_le(nr, addr)
+
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/bitops_no.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/bitops_no.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/bitops_no.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/bitops_no.h	2011-05-19 00:06:34.000000000 -0400
@@ -196,7 +196,19 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 
-static __inline__ int ext2_set_bit(int nr, volatile void * addr)
+#define BITOP_LE_SWIZZLE	((BITS_PER_LONG-1) & ~0x7)
+
+static inline void __set_bit_le(int nr, void *addr)
+{
+	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline void __clear_bit_le(int nr, void *addr)
+{
+	__clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline int __test_and_set_bit_le(int nr, volatile void *addr)
 {
 	char retval;
 
@@ -215,7 +227,7 @@
 	return retval;
 }
 
-static __inline__ int ext2_clear_bit(int nr, volatile void * addr)
+static inline int __test_and_clear_bit_le(int nr, volatile void *addr)
 {
 	char retval;
 
@@ -238,7 +250,7 @@
 	({						\
 		int ret;				\
 		spin_lock(lock);			\
-		ret = ext2_set_bit((nr), (addr));	\
+		ret = __test_and_set_bit_le((nr), (addr));	\
 		spin_unlock(lock);			\
 		ret;					\
 	})
@@ -247,12 +259,12 @@
 	({						\
 		int ret;				\
 		spin_lock(lock);			\
-		ret = ext2_clear_bit((nr), (addr));	\
+		ret = __test_and_clear_bit_le((nr), (addr));	\
 		spin_unlock(lock);			\
 		ret;					\
 	})
 
-static __inline__ int ext2_test_bit(int nr, const volatile void * addr)
+static inline int test_bit_le(int nr, const volatile void *addr)
 {
 	char retval;
 
@@ -271,10 +283,10 @@
 	return retval;
 }
 
-#define ext2_find_first_zero_bit(addr, size) \
-        ext2_find_next_zero_bit((addr), (size), 0)
+#define find_first_zero_bit_le(addr, size)	\
+	find_next_zero_bit_le((addr), (size), 0)
 
-static __inline__ unsigned long ext2_find_next_zero_bit(void *addr, unsigned long size, unsigned long offset)
+static inline unsigned long find_next_zero_bit_le(void *addr, unsigned long size, unsigned long offset)
 {
 	unsigned long *p = ((unsigned long *) addr) + (offset >> 5);
 	unsigned long result = offset & ~31UL;
@@ -324,10 +336,6 @@
 	return result + ffz(__swab32(tmp));
 }
 
-#define ext2_find_next_bit(addr, size, off) \
-	generic_find_next_le_bit((unsigned long *)(addr), (size), (off))
-#include <asm-generic/bitops/minix.h>
-
 #endif /* __KERNEL__ */
 
 #include <asm-generic/bitops/fls.h>
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/bootstd.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/bootstd.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/bootstd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/bootstd.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #define __BN_flash_write_range		20
 
 /* Calling conventions compatible to (uC)linux/68k
- * We use simmilar macros to call into the bootloader as for uClinux
+ * We use similar macros to call into the bootloader as for uClinux
  */
 
 #define __bsc_return(type, res) \
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/coldfire.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/coldfire.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/coldfire.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/coldfire.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,39 +14,35 @@
 
 
 /*
- *	Define master clock frequency. This is essentially done at config
- *	time now. No point enumerating dozens of possible clock options
- *	here. Also the peripheral clock (bus clock) divide ratio is set
- *	at config time too.
+ *	Define master clock frequency. This is done at config time now.
+ *	No point enumerating dozens of possible clock options here. And
+ *	in any case new boards come along from time to time that have yet
+ *	another different clocking frequency.
  */
 #ifdef CONFIG_CLOCK_SET
 #define	MCF_CLK		CONFIG_CLOCK_FREQ
-#define	MCF_BUSCLK	(CONFIG_CLOCK_FREQ / CONFIG_CLOCK_DIV)
 #else
 #error "Don't know what your ColdFire CPU clock frequency is??"
 #endif
 
 /*
- *	Define the processor support peripherals base address.
- *	This is generally setup by the boards start up code.
+ *	Define the processor internal peripherals base address.
+ *
+ *	The majority of ColdFire parts use an MBAR register to set
+ *	the base address. Some have an IPSBAR register instead, and it
+ *	has slightly different rules on its size and alignment. Some
+ *	parts have fixed addresses and the internal peripherals cannot
+ *	be relocated in the CPU address space.
+ *
+ *	The value of MBAR or IPSBAR is config time selectable, we no
+ *	longer hard define it here. No MBAR or IPSBAR will be defined if
+ *	this part has a fixed peripheral address map.
  */
-#define	MCF_MBAR	0x10000000
-#define	MCF_MBAR2	0x80000000
-#if defined(CONFIG_M54xx)
-#define	MCF_IPSBAR	MCF_MBAR
-#elif defined(CONFIG_M520x)
-#define	MCF_IPSBAR	0xFC000000
-#else
-#define	MCF_IPSBAR	0x40000000
+#ifdef CONFIG_MBAR
+#define	MCF_MBAR	CONFIG_MBAR
 #endif
-
-#if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x)
-#undef MCF_MBAR
-#define	MCF_MBAR	MCF_IPSBAR
-#elif defined(CONFIG_M532x)
-#undef MCF_MBAR
-#define MCF_MBAR	0x00000000
+#ifdef CONFIG_IPSBAR
+#define	MCF_IPSBAR	CONFIG_IPSBAR
 #endif
 
 /****************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/commproc.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/commproc.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/commproc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/commproc.h	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 
 
 /* rx bd status/control bits */
-#define BD_SC_EMPTY	((ushort)0x8000)	/* Recieve is empty */
+#define BD_SC_EMPTY	((ushort)0x8000)	/* Receive is empty */
 #define BD_SC_WRAP	((ushort)0x2000)	/* Last buffer descriptor in table */
 #define BD_SC_INTRPT	((ushort)0x1000)	/* Interrupt on change */
 #define BD_SC_LAST	((ushort)0x0800)	/* Last buffer in frame OR control char */
@@ -96,7 +96,7 @@
 #define BD_SC_FIRST	((ushort)0x0400)	/* 1st buffer in an HDLC frame */
 #define BD_SC_ADDR	((ushort)0x0400)	/* 1st byte is a multidrop address */
 
-#define BD_SC_CM	((ushort)0x0200)	/* Continous mode */
+#define BD_SC_CM	((ushort)0x0200)	/* Continuous mode */
 #define BD_SC_ID	((ushort)0x0100)	/* Received too many idles */
 
 #define BD_SC_AM	((ushort)0x0080)	/* Multidrop address match */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/delay_no.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/delay_no.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/delay_no.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/delay_no.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,7 +16,7 @@
 	 * long word alignment which is the faster version.
 	 * The 0x4a8e is of course a 'tstl %fp' instruction.  This is better
 	 * than using a NOP (0x4e71) instruction because it executes in one
-	 * cycle not three and doesn't allow for an arbitary delay waiting
+	 * cycle not three and doesn't allow for an arbitrary delay waiting
 	 * for bus cycles to finish.  Also fp/a6 isn't likely to cause a
 	 * stall waiting for the register to become valid if such is added
 	 * to the coldfire at some stage.
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/gpio.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/gpio.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/gpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
  * GPIOs in a single control area, others have some GPIOs implemented in
  * different modules.
  *
- * This implementation attempts accomodate the differences while presenting
+ * This implementation attempts accommodate the differences while presenting
  * a generic interface that will optimize to as few instructions as possible.
  */
 #if defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5206sim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5206sim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5206sim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5206sim.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5206)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		MCF_CLK
 
 #include <asm/m52xxacr.h>
 
@@ -48,14 +49,14 @@
 #define	MCFSIM_SWIVR		0x42		/* SW Watchdog intr reg (r/w) */
 #define	MCFSIM_SWSR		0x43		/* SW Watchdog service (r/w) */
 
-#define	MCFSIM_DCRR		0x46		/* DRAM Refresh reg (r/w) */
-#define	MCFSIM_DCTR		0x4a		/* DRAM Timing reg (r/w) */
-#define	MCFSIM_DAR0		0x4c		/* DRAM 0 Address reg(r/w) */
-#define	MCFSIM_DMR0		0x50		/* DRAM 0 Mask reg (r/w) */
-#define	MCFSIM_DCR0		0x57		/* DRAM 0 Control reg (r/w) */
-#define	MCFSIM_DAR1		0x58		/* DRAM 1 Address reg (r/w) */
-#define	MCFSIM_DMR1		0x5c		/* DRAM 1 Mask reg (r/w) */
-#define	MCFSIM_DCR1		0x63		/* DRAM 1 Control reg (r/w) */
+#define	MCFSIM_DCRR		(MCF_MBAR + 0x46) /* DRAM Refresh reg (r/w) */
+#define	MCFSIM_DCTR		(MCF_MBAR + 0x4a) /* DRAM Timing reg (r/w) */
+#define	MCFSIM_DAR0		(MCF_MBAR + 0x4c) /* DRAM 0 Address reg(r/w) */
+#define	MCFSIM_DMR0		(MCF_MBAR + 0x50) /* DRAM 0 Mask reg (r/w) */
+#define	MCFSIM_DCR0		(MCF_MBAR + 0x57) /* DRAM 0 Control reg (r/w) */
+#define	MCFSIM_DAR1		(MCF_MBAR + 0x58) /* DRAM 1 Address reg (r/w) */
+#define	MCFSIM_DMR1		(MCF_MBAR + 0x5c) /* DRAM 1 Mask reg (r/w) */
+#define	MCFSIM_DCR1		(MCF_MBAR + 0x63) /* DRAM 1 Control reg (r/w) */
 
 #define	MCFSIM_CSAR0		0x64		/* CS 0 Address 0 reg (r/w) */
 #define	MCFSIM_CSMR0		0x68		/* CS 0 Mask 0 reg (r/w) */
@@ -89,9 +90,15 @@
 #define	MCFSIM_PAR		0xcb		/* Pin Assignment reg (r/w) */
 #endif
 
+#define	MCFTIMER_BASE1		(MCF_MBAR + 0x100)	/* Base of TIMER1 */
+#define	MCFTIMER_BASE2		(MCF_MBAR + 0x120)	/* Base of TIMER2 */
+
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x1c5)	/* Parallel Direction (r/w) */
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x1c9)	/* Parallel Port Value (r/w) */
 
+#define	MCFDMA_BASE0		(MCF_MBAR + 0x200)	/* Base address DMA 0 */
+#define	MCFDMA_BASE1		(MCF_MBAR + 0x240)	/* Base address DMA 1 */
+
 #if defined(CONFIG_NETtel)
 #define	MCFUART_BASE1		0x180		/* Base address of UART1 */
 #define	MCFUART_BASE2		0x140		/* Base address of UART2 */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m520xsim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m520xsim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m520xsim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m520xsim.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,13 +13,14 @@
 
 #define	CPU_NAME		"COLDFIRE(m520x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
  *  Define the 520x SIM register set addresses.
  */
-#define MCFICM_INTC0        0x48000     /* Base for Interrupt Ctrl 0 */
+#define MCFICM_INTC0        0xFC048000  /* Base for Interrupt Ctrl 0 */
 #define MCFINTC_IPRH        0x00        /* Interrupt pending 32-63 */
 #define MCFINTC_IPRL        0x04        /* Interrupt pending 1-31 */
 #define MCFINTC_IMRH        0x08        /* Interrupt mask 32-63 */
@@ -35,9 +36,9 @@
  *  address to the SIMR and CIMR registers (not offsets into IPSBAR).
  *  The 520x family only has a single INTC unit.
  */
-#define MCFINTC0_SIMR       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_SIMR)
-#define MCFINTC0_CIMR       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_CIMR)
-#define	MCFINTC0_ICR0       (MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_ICR0)
+#define MCFINTC0_SIMR       (MCFICM_INTC0 + MCFINTC_SIMR)
+#define MCFINTC0_CIMR       (MCFICM_INTC0 + MCFINTC_CIMR)
+#define	MCFINTC0_ICR0       (MCFICM_INTC0 + MCFINTC_ICR0)
 #define MCFINTC1_SIMR       (0)
 #define MCFINTC1_CIMR       (0)
 #define	MCFINTC1_ICR0       (0)
@@ -52,19 +53,22 @@
 /*
  *  SDRAM configuration registers.
  */
-#define MCFSIM_SDMR         0x000a8000	/* SDRAM Mode/Extended Mode Register */
-#define MCFSIM_SDCR         0x000a8004	/* SDRAM Control Register */
-#define MCFSIM_SDCFG1       0x000a8008	/* SDRAM Configuration Register 1 */
-#define MCFSIM_SDCFG2       0x000a800c	/* SDRAM Configuration Register 2 */
-#define MCFSIM_SDCS0        0x000a8110	/* SDRAM Chip Select 0 Configuration */
-#define MCFSIM_SDCS1        0x000a8114	/* SDRAM Chip Select 1 Configuration */
+#define MCFSIM_SDMR         0xFC0a8000	/* SDRAM Mode/Extended Mode Register */
+#define MCFSIM_SDCR         0xFC0a8004	/* SDRAM Control Register */
+#define MCFSIM_SDCFG1       0xFC0a8008	/* SDRAM Configuration Register 1 */
+#define MCFSIM_SDCFG2       0xFC0a800c	/* SDRAM Configuration Register 2 */
+#define MCFSIM_SDCS0        0xFC0a8110	/* SDRAM Chip Select 0 Configuration */
+#define MCFSIM_SDCS1        0xFC0a8114	/* SDRAM Chip Select 1 Configuration */
 
 /*
  * EPORT and GPIO registers.
  */
+#define MCFEPORT_EPPAR			0xFC088000
 #define MCFEPORT_EPDDR			0xFC088002
+#define MCFEPORT_EPIER			0xFC088003
 #define MCFEPORT_EPDR			0xFC088004
 #define MCFEPORT_EPPDR			0xFC088005
+#define MCFEPORT_EPFR			0xFC088006
 
 #define MCFGPIO_PODR_BUSCTL		0xFC0A4000
 #define MCFGPIO_PODR_BE			0xFC0A4001
@@ -119,10 +123,10 @@
 #define MCFGPIO_IRQ_MAX			8
 #define MCFGPIO_IRQ_VECBASE		MCFINT_VECBASE
 
-#define MCF_GPIO_PAR_UART                   (0xA4036)
-#define MCF_GPIO_PAR_FECI2C                 (0xA4033)
-#define MCF_GPIO_PAR_QSPI                   (0xA4034)
-#define MCF_GPIO_PAR_FEC                    (0xA4038)
+#define MCF_GPIO_PAR_UART		0xFC0A4036
+#define MCF_GPIO_PAR_FECI2C		0xFC0A4033
+#define MCF_GPIO_PAR_QSPI		0xFC0A4034
+#define MCF_GPIO_PAR_FEC		0xFC0A4038
 
 #define MCF_GPIO_PAR_UART_PAR_URXD0         (0x0001)
 #define MCF_GPIO_PAR_UART_PAR_UTXD0         (0x0002)
@@ -134,14 +138,26 @@
 #define MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2   (0x04)
 
 /*
+ *  PIT timer module.
+ */
+#define	MCFPIT_BASE1		0xFC080000	/* Base address of TIMER1 */
+#define	MCFPIT_BASE2		0xFC084000	/* Base address of TIMER2 */
+
+/*
  *  UART module.
  */
-#define MCFUART_BASE1		0x60000		/* Base address of UART1 */
-#define MCFUART_BASE2		0x64000		/* Base address of UART2 */
-#define MCFUART_BASE3		0x68000		/* Base address of UART2 */
+#define MCFUART_BASE1		0xFC060000	/* Base address of UART1 */
+#define MCFUART_BASE2		0xFC064000	/* Base address of UART2 */
+#define MCFUART_BASE3		0xFC068000	/* Base address of UART2 */
 
 /*
- *  Reset Controll Unit.
+ *  FEC module.
+ */
+#define	MCFFEC_BASE		0xFC030000	/* Base of FEC ethernet */
+#define	MCFFEC_SIZE		0x800		/* Register set size */
+
+/*
+ *  Reset Control Unit.
  */
 #define	MCF_RCR			0xFC0A0000
 #define	MCF_RSR			0xFC0A0001
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m523xsim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m523xsim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m523xsim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m523xsim.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,14 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m523x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
  *	Define the 523x SIM register set addresses.
  */
-#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
-#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC0		(MCF_IPSBAR + 0x0c00)	/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		(MCF_IPSBAR + 0x0d00)	/* Base for Interrupt Ctrl 0 */
+
 #define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -39,14 +41,14 @@
 /*
  *	SDRAM configuration registers.
  */
-#define	MCFSIM_DCR		0x44		/* SDRAM control */
-#define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
-#define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x44)	/* Control */
+#define	MCFSIM_DACR0		(MCF_IPSBAR + 0x48)	/* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x4c)	/* Address mask 0 */
+#define	MCFSIM_DACR1		(MCF_IPSBAR + 0x50)	/* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x54)	/* Address mask 1 */
 
 /*
- *  Reset Controll Unit (relative to IPSBAR).
+ *  Reset Control Unit (relative to IPSBAR).
  */
 #define	MCF_RCR			0x110000
 #define	MCF_RSR			0x110001
@@ -57,10 +59,19 @@
 /*
  *  UART module.
  */
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+#define MCFUART_BASE1		(MCF_IPSBAR + 0x200)
+#define MCFUART_BASE2		(MCF_IPSBAR + 0x240)
+#define MCFUART_BASE3		(MCF_IPSBAR + 0x280)
+
+/*
+ *  FEC ethernet module.
+ */
+#define	MCFFEC_BASE		(MCF_IPSBAR + 0x1000)
+#define	MCFFEC_SIZE		0x800
 
+/*
+ *  GPIO module.
+ */
 #define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
 #define MCFGPIO_PODR_DATAH	(MCF_IPSBAR + 0x100001)
 #define MCFGPIO_PODR_DATAL	(MCF_IPSBAR + 0x100002)
@@ -118,12 +129,22 @@
 #define MCFGPIO_PCLRR_ETPU	(MCF_IPSBAR + 0x10003C)
 
 /*
- * EPort
+ * PIT timer base addresses.
  */
+#define	MCFPIT_BASE1		(MCF_IPSBAR + 0x150000)
+#define	MCFPIT_BASE2		(MCF_IPSBAR + 0x160000)
+#define	MCFPIT_BASE3		(MCF_IPSBAR + 0x170000)
+#define	MCFPIT_BASE4		(MCF_IPSBAR + 0x180000)
 
+/*
+ * EPort
+ */
+#define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x130000)
 #define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x130002)
+#define MCFEPORT_EPIER		(MCF_IPSBAR + 0x130003)
 #define MCFEPORT_EPDR		(MCF_IPSBAR + 0x130004)
 #define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x130005)
+#define MCFEPORT_EPFR		(MCF_IPSBAR + 0x130006)
 
 /*
  * Generic GPIO support
@@ -143,5 +164,14 @@
 */
 #define	MCFGPIO_PAR_QSPI	(MCF_IPSBAR + 0x10004A)
 #define	MCFGPIO_PAR_TIMER	(MCF_IPSBAR + 0x10004C)
+
+/*
+ * DMA unit base addresses.
+ */
+#define	MCFDMA_BASE0		(MCF_IPSBAR + 0x100)
+#define	MCFDMA_BASE1		(MCF_IPSBAR + 0x140)
+#define	MCFDMA_BASE2		(MCF_IPSBAR + 0x180)
+#define	MCFDMA_BASE3		(MCF_IPSBAR + 0x1C0)
+
 /****************************************************************************/
 #endif	/* m523xsim_h */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5249sim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5249sim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5249sim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5249sim.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,10 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m5249)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
+ *	The 5249 has a second MBAR region, define its address.
+ */
+#define MCF_MBAR2		0x80000000
+
+/*
  *	Define the 5249 SIM register set addresses.
  */
 #define	MCFSIM_RSR		0x00		/* Reset Status reg (r/w) */
@@ -55,11 +61,17 @@
 #define MCFSIM_CSMR3		0xa8		/* CS 3 Mask reg (r/w) */
 #define MCFSIM_CSCR3		0xae		/* CS 3 Control reg (r/w) */
 
-#define MCFSIM_DCR		0x100		/* DRAM Control reg (r/w) */
-#define MCFSIM_DACR0		0x108		/* DRAM 0 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR0		0x10c		/* DRAM 0 Mask reg (r/w) */
-#define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
+#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
+#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM 0 Addr/Ctrl */
+#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM 0 Mask */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM 1 Addr/Ctrl */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM 1 Mask */
+
+/*
+ *	Timer module.
+ */
+#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
+#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
 
 /*
  *	UART module.
@@ -68,6 +80,14 @@
 #define MCFUART_BASE2		0x200           /* Base address of UART2 */
 
 /*
+ *	DMA unit base addresses.
+ */
+#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
+#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
+#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
+#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
+
+/*
  *	Some symbol defines for the above...
  */
 #define	MCFSIM_SWDICR		MCFSIM_ICR0	/* Watchdog timer ICR */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5272sim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5272sim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5272sim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5272sim.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5272)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		MCF_CLK
 
 #include <asm/m52xxacr.h>
 
@@ -80,6 +81,13 @@
 #define	MCFSIM_PCDAT		(MCF_MBAR + 0x96) /* Port C Data (r/w) */
 #define	MCFSIM_PDCNT		(MCF_MBAR + 0x98) /* Port D Control (r/w) */
 
+#define	MCFDMA_BASE0		(MCF_MBAR + 0xe0) /* Base address DMA 0 */
+
+#define	MCFTIMER_BASE1		(MCF_MBAR + 0x200) /* Base address TIMER1 */
+#define	MCFTIMER_BASE2		(MCF_MBAR + 0x220) /* Base address TIMER2 */
+#define	MCFTIMER_BASE3		(MCF_MBAR + 0x240) /* Base address TIMER4 */
+#define	MCFTIMER_BASE4		(MCF_MBAR + 0x260) /* Base address TIMER3 */
+
 /*
  *	Define system peripheral IRQ usage.
  */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m527xsim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m527xsim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m527xsim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m527xsim.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,14 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m527x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m52xxacr.h>
 
 /*
  *	Define the 5270/5271 SIM register set addresses.
  */
-#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
-#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 1 */
+#define	MCFICM_INTC0		(MCF_IPSBAR + 0x0c00)	/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		(MCF_IPSBAR + 0x0d00)	/* Base for Interrupt Ctrl 1 */
+
 #define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -42,29 +44,45 @@
  *	SDRAM configuration registers.
  */
 #ifdef CONFIG_M5271
-#define	MCFSIM_DCR		0x40		/* SDRAM control */
-#define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
-#define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x40)	/* Control */
+#define	MCFSIM_DACR0		(MCF_IPSBAR + 0x48)	/* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x4c)	/* Address mask 0 */
+#define	MCFSIM_DACR1		(MCF_IPSBAR + 0x50)	/* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x54)	/* Address mask 1 */
 #endif
 #ifdef CONFIG_M5275
-#define	MCFSIM_DMR		0x40		/* SDRAM mode */
-#define	MCFSIM_DCR		0x44		/* SDRAM control */
-#define	MCFSIM_DCFG1		0x48		/* SDRAM configuration 1 */
-#define	MCFSIM_DCFG2		0x4c		/* SDRAM configuration 2 */
-#define	MCFSIM_DBAR0		0x50		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x54		/* SDRAM address mask 0 */
-#define	MCFSIM_DBAR1		0x58		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x5c		/* SDRAM address mask 1 */
+#define	MCFSIM_DMR		(MCF_IPSBAR + 0x40)	/* Mode */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x44)	/* Control */
+#define	MCFSIM_DCFG1		(MCF_IPSBAR + 0x48)	/* Configuration 1 */
+#define	MCFSIM_DCFG2		(MCF_IPSBAR + 0x4c)	/* Configuration 2 */
+#define	MCFSIM_DBAR0		(MCF_IPSBAR + 0x50)	/* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x54)	/* Address mask 0 */
+#define	MCFSIM_DBAR1		(MCF_IPSBAR + 0x58)	/* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x5c)	/* Address mask 1 */
 #endif
 
 /*
+ *	DMA unit base addresses.
+ */
+#define	MCFDMA_BASE0		(MCF_IPSBAR + 0x100)
+#define	MCFDMA_BASE1		(MCF_IPSBAR + 0x140)
+#define	MCFDMA_BASE2		(MCF_IPSBAR + 0x180)
+#define	MCFDMA_BASE3		(MCF_IPSBAR + 0x1C0)
+
+/*
  *	UART module.
  */
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+#define MCFUART_BASE1		(MCF_IPSBAR + 0x200)
+#define MCFUART_BASE2		(MCF_IPSBAR + 0x240)
+#define MCFUART_BASE3		(MCF_IPSBAR + 0x280)
+
+/*
+ *	FEC ethernet module.
+ */
+#define	MCFFEC_BASE0		(MCF_IPSBAR + 0x1000)
+#define	MCFFEC_SIZE0		0x800
+#define	MCFFEC_BASE1		(MCF_IPSBAR + 0x1800)
+#define	MCFFEC_SIZE1		0x800
 
 #ifdef CONFIG_M5271
 #define MCFGPIO_PODR_ADDR	(MCF_IPSBAR + 0x100000)
@@ -231,14 +249,22 @@
 #endif
 
 /*
- * EPort
+ * PIT timer base addresses.
  */
+#define	MCFPIT_BASE1		(MCF_IPSBAR + 0x150000)
+#define	MCFPIT_BASE2		(MCF_IPSBAR + 0x160000)
+#define	MCFPIT_BASE3		(MCF_IPSBAR + 0x170000)
+#define	MCFPIT_BASE4		(MCF_IPSBAR + 0x180000)
 
+/*
+ * EPort
+ */
+#define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x130000)
 #define MCFEPORT_EPDDR		(MCF_IPSBAR + 0x130002)
+#define MCFEPORT_EPIER		(MCF_IPSBAR + 0x130003)
 #define MCFEPORT_EPDR		(MCF_IPSBAR + 0x130004)
 #define MCFEPORT_EPPDR		(MCF_IPSBAR + 0x130005)
-
-
+#define MCFEPORT_EPFR		(MCF_IPSBAR + 0x130006)
 
 /*
  *	GPIO pins setups to enable the UARTs.
@@ -257,7 +283,7 @@
 #endif
 
 /*
- *  Reset Controll Unit (relative to IPSBAR).
+ *  Reset Control Unit (relative to IPSBAR).
  */
 #define	MCF_RCR			0x110000
 #define	MCF_RSR			0x110001
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m528xsim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m528xsim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m528xsim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m528xsim.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,14 +13,16 @@
 
 #define	CPU_NAME		"COLDFIRE(m528x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		MCF_CLK
 
 #include <asm/m52xxacr.h>
 
 /*
  *	Define the 5280/5282 SIM register set addresses.
  */
-#define	MCFICM_INTC0		0x0c00		/* Base for Interrupt Ctrl 0 */
-#define	MCFICM_INTC1		0x0d00		/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC0		(MCF_IPSBAR + 0x0c00)	/* Base for Interrupt Ctrl 0 */
+#define	MCFICM_INTC1		(MCF_IPSBAR + 0x0d00)	/* Base for Interrupt Ctrl 0 */
+
 #define	MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define	MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define	MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -39,18 +41,32 @@
 /*
  *	SDRAM configuration registers.
  */
-#define	MCFSIM_DCR		0x44		/* SDRAM control */
-#define	MCFSIM_DACR0		0x48		/* SDRAM base address 0 */
-#define	MCFSIM_DMR0		0x4c		/* SDRAM address mask 0 */
-#define	MCFSIM_DACR1		0x50		/* SDRAM base address 1 */
-#define	MCFSIM_DMR1		0x54		/* SDRAM address mask 1 */
+#define	MCFSIM_DCR		(MCF_IPSBAR + 0x00000044) /* Control */
+#define	MCFSIM_DACR0		(MCF_IPSBAR + 0x00000048) /* Base address 0 */
+#define	MCFSIM_DMR0		(MCF_IPSBAR + 0x0000004c) /* Address mask 0 */
+#define	MCFSIM_DACR1		(MCF_IPSBAR + 0x00000050) /* Base address 1 */
+#define	MCFSIM_DMR1		(MCF_IPSBAR + 0x00000054) /* Address mask 1 */
+
+/*
+ *	DMA unit base addresses.
+ */
+#define	MCFDMA_BASE0		(MCF_IPSBAR + 0x00000100)
+#define	MCFDMA_BASE1		(MCF_IPSBAR + 0x00000140)
+#define	MCFDMA_BASE2		(MCF_IPSBAR + 0x00000180)
+#define	MCFDMA_BASE3		(MCF_IPSBAR + 0x000001C0)
 
 /*
  *	UART module.
  */
-#define MCFUART_BASE1		0x200           /* Base address of UART1 */
-#define MCFUART_BASE2		0x240           /* Base address of UART2 */
-#define MCFUART_BASE3		0x280           /* Base address of UART3 */
+#define	MCFUART_BASE1		(MCF_IPSBAR + 0x00000200)
+#define	MCFUART_BASE2		(MCF_IPSBAR + 0x00000240)
+#define	MCFUART_BASE3		(MCF_IPSBAR + 0x00000280)
+
+/*
+ *	FEC ethernet module.
+ */
+#define	MCFFEC_BASE		(MCF_IPSBAR + 0x00001000)
+#define	MCFFEC_SIZE		0x800
 
 /*
  * 	GPIO registers
@@ -163,6 +179,14 @@
 #define MCFGPIO_PUAPAR		(MCF_IPSBAR + 0x0010005C)
 
 /*
+ * PIT timer base addresses.
+ */
+#define	MCFPIT_BASE1		(MCF_IPSBAR + 0x00150000)
+#define	MCFPIT_BASE2		(MCF_IPSBAR + 0x00160000)
+#define	MCFPIT_BASE3		(MCF_IPSBAR + 0x00170000)
+#define	MCFPIT_BASE4		(MCF_IPSBAR + 0x00180000)
+
+/*
  * 	Edge Port registers
  */
 #define MCFEPORT_EPPAR		(MCF_IPSBAR + 0x00130000)
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5307sim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5307sim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5307sim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5307sim.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5307)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m53xxacr.h>
 
@@ -28,7 +29,7 @@
 #define	MCFSIM_SWSR		0x03		/* SW Watchdog service (r/w) */
 #define	MCFSIM_PAR		0x04		/* Pin Assignment reg (r/w) */
 #define	MCFSIM_IRQPAR		0x06		/* Interrupt Assignment reg (r/w) */
-#define	MCFSIM_PLLCR		0x08		/* PLL Controll Reg*/
+#define	MCFSIM_PLLCR		0x08		/* PLL Control Reg*/
 #define	MCFSIM_MPARK		0x0C		/* BUS Master Control Reg*/
 #define	MCFSIM_IPR		0x40		/* Interrupt Pend reg (r/w) */
 #define	MCFSIM_IMR		0x44		/* Interrupt Mask reg (r/w) */
@@ -89,16 +90,30 @@
 #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
 #endif /* CONFIG_OLDMASK */
 
-#define MCFSIM_DCR		0x100		/* DRAM Control reg (r/w) */
-#define MCFSIM_DACR0		0x108		/* DRAM 0 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR0		0x10c		/* DRAM 0 Mask reg (r/w) */
-#define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
+#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
+#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM Addr/Ctrl 0 */
+#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM Mask 0 */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM Addr/Ctrl 1 */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM Mask 1 */
+
+/*
+ *  Timer module.
+ */
+#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
+#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
 
 #define	MCFSIM_PADDR		(MCF_MBAR + 0x244)
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
 /*
+ *  DMA unit base addresses.
+ */
+#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
+#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
+#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
+#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
+
+/*
  *  UART module.
  */
 #if defined(CONFIG_NETtel) || defined(CONFIG_SECUREEDGEMP3)
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m532xsim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m532xsim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m532xsim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m532xsim.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m532x)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 3)
 
 #include <asm/m53xxacr.h>
 
@@ -85,6 +86,14 @@
 #define MCFUART_BASE2		0xFC064000	/* Base address of UART2 */
 #define MCFUART_BASE3		0xFC068000	/* Base address of UART3 */
 
+/*
+ *  Timer module.
+ */
+#define MCFTIMER_BASE1		0xFC070000	/* Base address of TIMER1 */
+#define MCFTIMER_BASE2		0xFC074000	/* Base address of TIMER2 */
+#define MCFTIMER_BASE3		0xFC078000	/* Base address of TIMER3 */
+#define MCFTIMER_BASE4		0xFC07C000	/* Base address of TIMER4 */
+
 /*********************************************************************
  *
  * Reset Controller Module
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5407sim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5407sim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m5407sim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m5407sim.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m5407)"
 #define	CPU_INSTR_PER_JIFFY	3
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m54xxacr.h>
 
@@ -28,7 +29,7 @@
 #define	MCFSIM_SWSR		0x03		/* SW Watchdog service (r/w) */
 #define	MCFSIM_PAR		0x04		/* Pin Assignment reg (r/w) */
 #define	MCFSIM_IRQPAR		0x06		/* Interrupt Assignment reg (r/w) */
-#define	MCFSIM_PLLCR		0x08		/* PLL Controll Reg*/
+#define	MCFSIM_PLLCR		0x08		/* PLL Control Reg*/
 #define	MCFSIM_MPARK		0x0C		/* BUS Master Control Reg*/
 #define	MCFSIM_IPR		0x40		/* Interrupt Pend reg (r/w) */
 #define	MCFSIM_IMR		0x44		/* Interrupt Mask reg (r/w) */
@@ -72,11 +73,17 @@
 #define MCFSIM_CSMR7		0xd8		/* CS 7 Mask reg (r/w) */
 #define MCFSIM_CSCR7		0xde		/* CS 7 Control reg (r/w) */
 
-#define MCFSIM_DCR		0x100		/* DRAM Control reg (r/w) */
-#define MCFSIM_DACR0		0x108		/* DRAM 0 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR0		0x10c		/* DRAM 0 Mask reg (r/w) */
-#define MCFSIM_DACR1		0x110		/* DRAM 1 Addr and Ctrl (r/w) */
-#define MCFSIM_DMR1		0x114		/* DRAM 1 Mask reg (r/w) */
+#define MCFSIM_DCR		(MCF_MBAR + 0x100)	/* DRAM Control */
+#define MCFSIM_DACR0		(MCF_MBAR + 0x108)	/* DRAM 0 Addr/Ctrl */
+#define MCFSIM_DMR0		(MCF_MBAR + 0x10c)	/* DRAM 0 Mask */
+#define MCFSIM_DACR1		(MCF_MBAR + 0x110)	/* DRAM 1 Addr/Ctrl */
+#define MCFSIM_DMR1		(MCF_MBAR + 0x114)	/* DRAM 1 Mask */
+
+/*
+ *	Timer module.
+ */
+#define MCFTIMER_BASE1		(MCF_MBAR + 0x140)	/* Base of TIMER1 */
+#define MCFTIMER_BASE2		(MCF_MBAR + 0x180)	/* Base of TIMER2 */
 
 #define MCFUART_BASE1		0x1c0           /* Base address of UART1 */
 #define MCFUART_BASE2		0x200           /* Base address of UART2 */
@@ -85,6 +92,14 @@
 #define	MCFSIM_PADAT		(MCF_MBAR + 0x248)
 
 /*
+ *	DMA unit base addresses.
+ */
+#define MCFDMA_BASE0		(MCF_MBAR + 0x300)	/* Base address DMA 0 */
+#define MCFDMA_BASE1		(MCF_MBAR + 0x340)	/* Base address DMA 1 */
+#define MCFDMA_BASE2		(MCF_MBAR + 0x380)	/* Base address DMA 2 */
+#define MCFDMA_BASE3		(MCF_MBAR + 0x3C0)	/* Base address DMA 3 */
+
+/*
  * Generic GPIO support
  */
 #define MCFGPIO_PIN_MAX			16
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m54xxsim.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m54xxsim.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m54xxsim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m54xxsim.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,7 @@
 
 #define	CPU_NAME		"COLDFIRE(m54xx)"
 #define	CPU_INSTR_PER_JIFFY	2
+#define	MCF_BUSCLK		(MCF_CLK / 2)
 
 #include <asm/m54xxacr.h>
 
@@ -15,7 +16,8 @@
 /*
  *      Interrupt Controller Registers
  */
-#define MCFICM_INTC0		0x0700		/* Base for Interrupt Ctrl 0 */
+#define MCFICM_INTC0		(MCF_MBAR + 0x700) 	/* Base for Interrupt Ctrl 0 */
+
 #define MCFINTC_IPRH		0x00		/* Interrupt pending 32-63 */
 #define MCFINTC_IPRL		0x04		/* Interrupt pending 1-31 */
 #define MCFINTC_IMRH		0x08		/* Interrupt mask 32-63 */
@@ -48,6 +50,16 @@
 #define MCFGPIO_IRQ_VECBASE	-1
 
 /*
+ *	EDGE Port support.
+ */
+#define	MCFEPORT_EPPAR		(MCF_MBAR + 0xf00)	/* Pin assignment */
+#define	MCFEPORT_EPDDR		(MCF_MBAR + 0xf04)	/* Data direction */
+#define	MCFEPORT_EPIER		(MCF_MBAR + 0xf05)	/* Interrupt enable */
+#define	MCFEPORT_EPDR		(MCF_MBAR + 0xf08)	/* Port data (w) */
+#define	MCFEPORT_EPPDR		(MCF_MBAR + 0xf09)	/* Port data (r) */
+#define	MCFEPORT_EPFR		(MCF_MBAR + 0xf0c)	/* Flags */
+
+/*
  *	Some PSC related definitions
  */
 #define MCF_PAR_PSC(x)		(0x000A4F-((x)&0x3))
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/m68360_quicc.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/m68360_quicc.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/m68360_quicc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/m68360_quicc.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
     /* BASE + 0x000: user data memory */
     volatile unsigned char      udata_bd_ucode[0x400]; /*user data bd's Ucode*/
     volatile unsigned char      udata_bd[0x200];       /*user data Ucode     */
-    volatile unsigned char      ucode_ext[0x100];      /*Ucode Extention ram */
+    volatile unsigned char      ucode_ext[0x100];      /*Ucode Extension ram */
     volatile unsigned char      RESERVED1[0x500];      /* Reserved area      */
 };
 #else
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/macintosh.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/macintosh.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/macintosh.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/macintosh.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 extern int mac_irq_pending(unsigned int);
 
 /*
- *	Floppy driver magic hook - probably shouldnt be here
+ *	Floppy driver magic hook - probably shouldn't be here
  */
 
 extern void via1_set_head(int);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/mac_oss.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/mac_oss.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/mac_oss.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/mac_oss.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
 /*
  * OSS Interrupt levels for various sub-systems
  *
- * This mapping is layed out with two things in mind: first, we try to keep
+ * This mapping is laid out with two things in mind: first, we try to keep
  * things on their own levels to avoid having to do double-dispatches. Second,
  * the levels match as closely as possible the alternate IRQ mapping mode (aka
  * "A/UX mode") available on some VIA machines.
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/mac_via.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/mac_via.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/mac_via.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/mac_via.h	2011-05-19 00:06:34.000000000 -0400
@@ -204,7 +204,7 @@
 #define vT2CL	0x1000  /* [VIA only] Timer two counter low. */
 #define vT2CH	0x1200  /* [VIA only] Timer two counter high. */
 #define vSR	0x1400  /* [VIA only] Shift register. */
-#define vACR	0x1600  /* [VIA only] Auxilary control register. */
+#define vACR	0x1600  /* [VIA only] Auxiliary control register. */
 #define vPCR	0x1800  /* [VIA only] Peripheral control register. */
                         /*            CHRP sez never ever to *write* this.
 			 *            Mac family says never to *change* this.
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/mcfdma.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/mcfdma.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/mcfdma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/mcfdma.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,29 +11,6 @@
 #define	mcfdma_h
 /****************************************************************************/
 
-
-/*
- *	Get address specific defines for this Coldfire member.
- */
-#if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
-#define	MCFDMA_BASE0		0x200		/* Base address of DMA 0 */
-#define	MCFDMA_BASE1		0x240		/* Base address of DMA 1 */
-#elif defined(CONFIG_M5272)
-#define	MCFDMA_BASE0		0x0e0		/* Base address of DMA 0 */
-#elif defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x)
-/* These are relative to the IPSBAR, not MBAR */
-#define	MCFDMA_BASE0		0x100		/* Base address of DMA 0 */
-#define	MCFDMA_BASE1		0x140		/* Base address of DMA 1 */
-#define	MCFDMA_BASE2		0x180		/* Base address of DMA 2 */
-#define	MCFDMA_BASE3		0x1C0		/* Base address of DMA 3 */
-#elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
-#define	MCFDMA_BASE0		0x300		/* Base address of DMA 0 */
-#define	MCFDMA_BASE1		0x340		/* Base address of DMA 1 */
-#define	MCFDMA_BASE2		0x380		/* Base address of DMA 2 */
-#define	MCFDMA_BASE3		0x3C0		/* Base address of DMA 3 */
-#endif
-
-
 #if !defined(CONFIG_M5272)
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/mcfpit.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/mcfpit.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/mcfpit.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/mcfpit.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,22 +11,8 @@
 #define	mcfpit_h
 /****************************************************************************/
 
-
-/*
- *	Get address specific defines for the 5270/5271, 5280/5282, and 5208.
- */
-#if defined(CONFIG_M520x)
-#define	MCFPIT_BASE1		0x00080000	/* Base address of TIMER1 */
-#define	MCFPIT_BASE2		0x00084000	/* Base address of TIMER2 */
-#else
-#define	MCFPIT_BASE1		0x00150000	/* Base address of TIMER1 */
-#define	MCFPIT_BASE2		0x00160000	/* Base address of TIMER2 */
-#define	MCFPIT_BASE3		0x00170000	/* Base address of TIMER3 */
-#define	MCFPIT_BASE4		0x00180000	/* Base address of TIMER4 */
-#endif
-
 /*
- *	Define the PIT timer register set addresses.
+ *	Define the PIT timer register address offsets.
  */
 #define	MCFPIT_PCSR		0x0		/* PIT control register */
 #define	MCFPIT_PMR		0x2		/* PIT modulus register */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/mcftimer.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/mcftimer.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/mcftimer.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/mcftimer.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,29 +12,6 @@
 #define	mcftimer_h
 /****************************************************************************/
 
-
-/*
- *	Get address specific defines for this ColdFire member.
- */
-#if defined(CONFIG_M5206) || defined(CONFIG_M5206e)
-#define	MCFTIMER_BASE1		0x100		/* Base address of TIMER1 */
-#define	MCFTIMER_BASE2		0x120		/* Base address of TIMER2 */
-#elif defined(CONFIG_M5272)
-#define MCFTIMER_BASE1		0x200           /* Base address of TIMER1 */
-#define MCFTIMER_BASE2		0x220           /* Base address of TIMER2 */
-#define MCFTIMER_BASE3		0x240           /* Base address of TIMER4 */
-#define MCFTIMER_BASE4		0x260           /* Base address of TIMER3 */
-#elif defined(CONFIG_M5249) || defined(CONFIG_M5307) || defined(CONFIG_M5407)
-#define MCFTIMER_BASE1		0x140           /* Base address of TIMER1 */
-#define MCFTIMER_BASE2		0x180           /* Base address of TIMER2 */
-#elif defined(CONFIG_M532x)
-#define MCFTIMER_BASE1		0xfc070000	/* Base address of TIMER1 */
-#define MCFTIMER_BASE2		0xfc074000	/* Base address of TIMER2 */
-#define MCFTIMER_BASE3		0xfc078000	/* Base address of TIMER3 */
-#define MCFTIMER_BASE4		0xfc07c000	/* Base address of TIMER4 */
-#endif
-
-
 /*
  *	Define the TIMER register set addresses.
  */
@@ -50,7 +27,7 @@
 
 /*
  *	Bit definitions for the Timer Mode Register (TMR).
- *	Register bit flags are common accross ColdFires.
+ *	Register bit flags are common across ColdFires.
  */
 #define	MCFTIMER_TMR_PREMASK	0xff00		/* Prescalar mask */
 #define	MCFTIMER_TMR_DISCE	0x0000		/* Disable capture */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/natfeat.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/natfeat.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/natfeat.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/natfeat.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * ARAnyM hardware support via Native Features (natfeats)
+ *
+ * Copyright (c) 2005 Petr Stehlik of ARAnyM dev team
+ *
+ * This software may be used and distributed according to the terms of
+ * the GNU General Public License (GPL), incorporated herein by reference.
+ */
+
+#ifndef _NATFEAT_H
+#define _NATFEAT_H
+
+long nf_get_id(const char *feature_name);
+long nf_call(long id, ...);
+
+void nf_init(void);
+void nf_shutdown(void);
+
+void nfprint(const char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
+
+# endif /* _NATFEAT_H */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/processor.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -113,6 +113,8 @@
 	wrusp(usp);
 }
 
+extern int handle_kernel_fault(struct pt_regs *regs);
+
 #else
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/types.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,15 +23,6 @@
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* DMA addresses are always 32-bits wide */
-
-typedef u32 dma_addr_t;
-typedef u32 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* _M68K_TYPES_H */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/m68k/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/m68k/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -343,10 +343,14 @@
 #define __NR_fanotify_init	337
 #define __NR_fanotify_mark	338
 #define __NR_prlimit64		339
+#define __NR_name_to_handle_at	340
+#define __NR_open_by_handle_at	341
+#define __NR_clock_adjtime	342
+#define __NR_syncfs		343
 
 #ifdef __KERNEL__
 
-#define NR_syscalls		340
+#define NR_syscalls		344
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Kconfig linux-libre-2.6.39-gnu/arch/m68k/Kconfig
--- linux-libre-2.6.38-gnu/arch/m68k/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,13 +1,10 @@
 config M68K
 	bool
 	default y
-	select HAVE_AOUT
 	select HAVE_IDE
-	select GENERIC_ATOMIC64
-
-config MMU
-	bool
-	default y
+	select HAVE_AOUT if MMU
+	select GENERIC_ATOMIC64 if MMU
+	select HAVE_GENERIC_HARDIRQS if !MMU
 
 config RWSEM_GENERIC_SPINLOCK
 	bool
@@ -18,11 +15,9 @@
 
 config ARCH_HAS_ILOG2_U32
 	bool
-	default n
 
 config ARCH_HAS_ILOG2_U64
 	bool
-	default n
 
 config GENERIC_HWEIGHT
 	bool
@@ -36,426 +31,67 @@
 	bool
 	default y
 
-config GENERIC_IOMAP
-	bool
-	default y
-
-config ARCH_MAY_HAVE_PC_FDC
-	bool
-	depends on BROKEN && (Q40 || SUN3X)
-	default y
-
 config NO_IOPORT
 	def_bool y
 
 config NO_DMA
-	def_bool SUN3
+	def_bool (MMU && SUN3) || (!MMU && !COLDFIRE)
 
+config ZONE_DMA
+	bool
+	default y
 config HZ
 	int
+	default 1000 if CLEOPATRA
 	default 100
 
-config ARCH_USES_GETTIMEOFFSET
-	def_bool y
-
 source "init/Kconfig"
 
 source "kernel/Kconfig.freezer"
 
-menu "Platform dependent setup"
-
-config EISA
-	bool
-	---help---
-	  The Extended Industry Standard Architecture (EISA) bus was
-	  developed as an open alternative to the IBM MicroChannel bus.
-
-	  The EISA bus provided some of the features of the IBM MicroChannel
-	  bus while maintaining backward compatibility with cards made for
-	  the older ISA bus.  The EISA bus saw limited use between 1988 and
-	  1995 when it was made obsolete by the PCI bus.
-
-	  Say Y here if you are building a kernel for an EISA-based machine.
-
-	  Otherwise, say N.
-
-config MCA
-	bool
-	help
-	  MicroChannel Architecture is found in some IBM PS/2 machines and
-	  laptops.  It is a bus system similar to PCI or ISA. See
-	  <file:Documentation/mca.txt> (and especially the web page given
-	  there) before attempting to build an MCA bus kernel.
-
-config PCMCIA
-	tristate
-	---help---
-	  Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
-	  computer.  These are credit-card size devices such as network cards,
-	  modems or hard drives often used with laptops computers.  There are
-	  actually two varieties of these cards: the older 16 bit PCMCIA cards
-	  and the newer 32 bit CardBus cards.  If you want to use CardBus
-	  cards, you need to say Y here and also to "CardBus support" below.
-
-	  To use your PC-cards, you will need supporting software from David
-	  Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
-	  for location).  Please also read the PCMCIA-HOWTO, available from
-	  <http://www.tldp.org/docs.html#howto>.
-
-	  To compile this driver as modules, choose M here: the
-	  modules will be called pcmcia_core and ds.
-
-config AMIGA
-	bool "Amiga support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the Amiga series of computers. If
-	  you plan to use this kernel on an Amiga, say Y here and browse the
-	  material available in <file:Documentation/m68k>; otherwise say N.
-
-config ATARI
-	bool "Atari support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the 68000-based Atari series of
-	  computers (including the TT, Falcon and Medusa). If you plan to use
-	  this kernel on an Atari, say Y here and browse the material
-	  available in <file:Documentation/m68k>; otherwise say N.
-
-config MAC
-	bool "Macintosh support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the Apple Macintosh series of
-	  computers (yes, there is experimental support now, at least for part
-	  of the series).
-
-	  Say N unless you're willing to code the remaining necessary support.
-	  ;)
-
-config NUBUS
-	bool
-	depends on MAC
-	default y
-
-config M68K_L2_CACHE
-	bool
-	depends on MAC
-	default y
-
-config APOLLO
-	bool "Apollo support"
-	select MMU_MOTOROLA if MMU
-	help
-	  Say Y here if you want to run Linux on an MC680x0-based Apollo
-	  Domain workstation such as the DN3500.
-
-config VME
-	bool "VME (Motorola and BVM) support"
-	select MMU_MOTOROLA if MMU
-	help
-	  Say Y here if you want to build a kernel for a 680x0 based VME
-	  board.  Boards currently supported include Motorola boards MVME147,
-	  MVME162, MVME166, MVME167, MVME172, and MVME177.  BVME4000 and
-	  BVME6000 boards from BVM Ltd are also supported.
-
-config MVME147
-	bool "MVME147 support"
-	depends on VME
-	help
-	  Say Y to include support for early Motorola VME boards.  This will
-	  build a kernel which can run on MVME147 single-board computers.  If
-	  you select this option you will have to select the appropriate
-	  drivers for SCSI, Ethernet and serial ports later on.
-
-config MVME16x
-	bool "MVME162, 166 and 167 support"
-	depends on VME
-	help
-	  Say Y to include support for Motorola VME boards.  This will build a
-	  kernel which can run on MVME162, MVME166, MVME167, MVME172, and
-	  MVME177 boards.  If you select this option you will have to select
-	  the appropriate drivers for SCSI, Ethernet and serial ports later
-	  on.
-
-config BVME6000
-	bool "BVME4000 and BVME6000 support"
-	depends on VME
-	help
-	  Say Y to include support for VME boards from BVM Ltd.  This will
-	  build a kernel which can run on BVME4000 and BVME6000 boards.  If
-	  you select this option you will have to select the appropriate
-	  drivers for SCSI, Ethernet and serial ports later on.
-
-config HP300
-	bool "HP9000/300 and HP9000/400 support"
-	select MMU_MOTOROLA if MMU
-	help
-	  This option enables support for the HP9000/300 and HP9000/400 series
-	  of workstations. Support for these machines is still somewhat
-	  experimental. If you plan to try to use the kernel on such a machine
-	  say Y here.
-	  Everybody else says N.
-
-config DIO
-	bool "DIO bus support"
-	depends on HP300
+config MMU
+	bool "MMU-based Paged Memory Management Support"
 	default y
 	help
-	  Say Y here to enable support for the "DIO" expansion bus used in
-	  HP300 machines. If you are using such a system you almost certainly
-	  want this.
-
-config SUN3X
-	bool "Sun3x support"
-	select MMU_MOTOROLA if MMU
-	select M68030
-	help
-	  This option enables support for the Sun 3x series of workstations.
-	  Be warned that this support is very experimental.
-	  Note that Sun 3x kernels are not compatible with Sun 3 hardware.
-	  General Linux information on the Sun 3x series (now discontinued)
-	  is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
-
-	  If you don't want to compile a kernel for a Sun 3x, say N.
-
-config Q40
-	bool "Q40/Q60 support"
-	select MMU_MOTOROLA if MMU
-	help
-	  The Q40 is a Motorola 68040-based successor to the Sinclair QL
-	  manufactured in Germany.  There is an official Q40 home page at
-	  <http://www.q40.de/>.  This option enables support for the Q40 and
-	  Q60. Select your CPU below.  For 68LC060 don't forget to enable FPU
-	  emulation.
-
-config SUN3
-	bool "Sun3 support"
-	depends on !MMU_MOTOROLA
-	select MMU_SUN3 if MMU
-	select M68020
-	help
-	  This option enables support for the Sun 3 series of workstations
-	  (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
-	  that all other hardware types must be disabled, as Sun 3 kernels
-	  are incompatible with all other m68k targets (including Sun 3x!).
-
-	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
-
-comment "Processor type"
-
-config M68020
-	bool "68020 support"
-	help
-	  If you anticipate running this kernel on a computer with a MC68020
-	  processor, say Y. Otherwise, say N. Note that the 68020 requires a
-	  68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
-	  Sun 3, which provides its own version.
-
-config M68030
-	bool "68030 support"
-	depends on !MMU_SUN3
-	help
-	  If you anticipate running this kernel on a computer with a MC68030
-	  processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
-	  work, as it does not include an MMU (Memory Management Unit).
-
-config M68040
-	bool "68040 support"
-	depends on !MMU_SUN3
-	help
-	  If you anticipate running this kernel on a computer with a MC68LC040
-	  or MC68040 processor, say Y. Otherwise, say N. Note that an
-	  MC68EC040 will not work, as it does not include an MMU (Memory
-	  Management Unit).
-
-config M68060
-	bool "68060 support"
-	depends on !MMU_SUN3
-	help
-	  If you anticipate running this kernel on a computer with a MC68060
-	  processor, say Y. Otherwise, say N.
-
-config MMU_MOTOROLA
-	bool
-
-config MMU_SUN3
-	bool
-	depends on MMU && !MMU_MOTOROLA
-
-config M68KFPU_EMU
-	bool "Math emulation support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	help
-	  At some point in the future, this will cause floating-point math
-	  instructions to be emulated by the kernel on machines that lack a
-	  floating-point math coprocessor.  Thrill-seekers and chronically
-	  sleep-deprived psychotic hacker types can say Y now, everyone else
-	  should probably wait a while.
-
-config M68KFPU_EMU_EXTRAPREC
-	bool "Math emulation extra precision"
-	depends on M68KFPU_EMU
-	help
-	  The fpu uses normally a few bit more during calculations for
-	  correct rounding, the emulator can (often) do the same but this
-	  extra calculation can cost quite some time, so you can disable
-	  it here. The emulator will then "only" calculate with a 64 bit
-	  mantissa and round slightly incorrect, what is more than enough
-	  for normal usage.
-
-config M68KFPU_EMU_ONLY
-	bool "Math emulation only kernel"
-	depends on M68KFPU_EMU
-	help
-	  This option prevents any floating-point instructions from being
-	  compiled into the kernel, thereby the kernel doesn't save any
-	  floating point context anymore during task switches, so this
-	  kernel will only be usable on machines without a floating-point
-	  math coprocessor. This makes the kernel a bit faster as no tests
-	  needs to be executed whether a floating-point instruction in the
-	  kernel should be executed or not.
-
-config ADVANCED
-	bool "Advanced configuration options"
-	---help---
-	  This gives you access to some advanced options for the CPU. The
-	  defaults should be fine for most users, but these options may make
-	  it possible for you to improve performance somewhat if you know what
-	  you are doing.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about these options.
-
-	  Most users should say N to this question.
-
-config RMW_INSNS
-	bool "Use read-modify-write instructions"
-	depends on ADVANCED
-	---help---
-	  This allows to use certain instructions that work with indivisible
-	  read-modify-write bus cycles. While this is faster than the
-	  workaround of disabling interrupts, it can conflict with DMA
-	  ( = direct memory access) on many Amiga systems, and it is also said
-	  to destabilize other machines. It is very likely that this will
-	  cause serious problems on any Amiga or Atari Medusa if set. The only
-	  configuration where it should work are 68030-based Ataris, where it
-	  apparently improves performance. But you've been warned! Unless you
-	  really know what you are doing, say N. Try Y only if you're quite
-	  adventurous.
-
-config SINGLE_MEMORY_CHUNK
-	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
-	default y if SUN3
-	select NEED_MULTIPLE_NODES
-	help
-	  Ignore all but the first contiguous chunk of physical memory for VM
-	  purposes.  This will save a few bytes kernel size and may speed up
-	  some operations.  Say N if not sure.
-
-config 060_WRITETHROUGH
-	bool "Use write-through caching for 68060 supervisor accesses"
-	depends on ADVANCED && M68060
-	---help---
-	  The 68060 generally uses copyback caching of recently accessed data.
-	  Copyback caching means that memory writes will be held in an on-chip
-	  cache and only written back to memory some time later.  Saying Y
-	  here will force supervisor (kernel) accesses to use writethrough
-	  caching.  Writethrough caching means that data is written to memory
-	  straight away, so that cache and memory data always agree.
-	  Writethrough caching is less efficient, but is needed for some
-	  drivers on 68060 based systems where the 68060 bus snooping signal
-	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
-	  this problem.
+	  Select if you want MMU-based virtualised addressing space
+	  support by paged memory management. If unsure, say 'Y'.
 
-config ARCH_DISCONTIGMEM_ENABLE
-	def_bool !SINGLE_MEMORY_CHUNK
+menu "Platform dependent setup"
 
-config NODES_SHIFT
-	int
-	default "3"
-	depends on !SINGLE_MEMORY_CHUNK
+if MMU
+source arch/m68k/Kconfig.mmu
+endif
+if !MMU
+source arch/m68k/Kconfig.nommu
+endif
 
 source "mm/Kconfig"
 
 endmenu
 
-menu "General setup"
+menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
 
-config ZORRO
-	bool "Amiga Zorro (AutoConfig) bus support"
-	depends on AMIGA
-	help
-	  This enables support for the Zorro bus in the Amiga. If you have
-	  expansion cards in your Amiga that conform to the Amiga
-	  AutoConfig(tm) specification, say Y, otherwise N. Note that even
-	  expansion cards that do not fit in the Zorro slots but fit in e.g.
-	  the CPU slot may fall in this category, so you have to say Y to let
-	  Linux use these.
-
-config AMIGA_PCMCIA
-	bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
-	depends on AMIGA && EXPERIMENTAL
-	help
-	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
-	  600. If you intend to use pcmcia cards say Y; otherwise say N.
-
-config STRAM_PROC
-	bool "ST-RAM statistics in /proc"
-	depends on ATARI
-	help
-	  Say Y here to report ST-RAM usage statistics in /proc/stram.
-
-config HEARTBEAT
-	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
-	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
-	help
-	  Use the power-on LED on your machine as a load meter.  The exact
-	  behavior is platform-dependent, but normally the flash frequency is
-	  a hyperbolic function of the 5-minute load average.
-
-# We have a dedicated heartbeat LED. :-)
-config PROC_HARDWARE
-	bool "/proc/hardware support"
-	help
-	  Say Y here to support the /proc/hardware file, which gives you
-	  access to information about the machine you're running on,
-	  including the model, CPU, MMU, clock speed, BogoMIPS rating,
-	  and memory size.
-
-config ISA
-	bool
-	depends on Q40 || AMIGA_PCMCIA
-	default y
-	help
-	  Find out whether you have ISA slots on your motherboard.  ISA is the
-	  name of a bus system, i.e. the way the CPU talks to the other stuff
-	  inside your box.  Other bus systems are PCI, EISA, MicroChannel
-	  (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
-	  newer boards don't support it.  If you have ISA, say Y, otherwise N.
-
-config GENERIC_ISA_DMA
-	bool
-	depends on Q40 || AMIGA_PCMCIA
-	default y
-
-config ZONE_DMA
-	bool
-	default y
+endmenu
 
-source "drivers/pci/Kconfig"
+if !MMU
+menu "Power management options"
 
-source "drivers/zorro/Kconfig"
+config PM
+        bool "Power Management support"
+        help
+          Support processor power management modes
 
 endmenu
+endif
 
 source "net/Kconfig"
 
 source "drivers/Kconfig"
 
+if MMU
+
 menu "Character devices"
 
 config ATARI_MFPSER
@@ -554,14 +190,6 @@
 	  This is the driver for the serial ports on the Motorola MVME147
 	  boards.  Everyone using one of these boards should say Y here.
 
-config SERIAL167
-	bool "CD2401 support for MVME166/7 serial ports"
-	depends on MVME16x
-	help
-	  This is the driver for the serial ports on the Motorola MVME166,
-	  167, and 172 boards.  Everyone using one of these boards should say
-	  Y here.
-
 config MVME162_SCC
 	bool "SCC support for MVME162 serial ports"
 	depends on MVME16x && BROKEN
@@ -606,6 +234,8 @@
 
 endmenu
 
+endif
+
 source "fs/Kconfig"
 
 source "arch/m68k/Kconfig.debug"
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Kconfig.debug linux-libre-2.6.39-gnu/arch/m68k/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/m68k/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -2,4 +2,38 @@
 
 source "lib/Kconfig.debug"
 
+if !MMU
+
+config FULLDEBUG
+	bool "Full Symbolic/Source Debugging support"
+	help
+	  Enable debugging symbols on kernel build.
+
+config HIGHPROFILE
+	bool "Use fast second timer for profiling"
+	depends on COLDFIRE
+	help
+	  Use a fast secondary clock to produce profiling information.
+
+config BOOTPARAM
+	bool 'Compiled-in Kernel Boot Parameter'
+
+config BOOTPARAM_STRING
+	string 'Kernel Boot Parameter'
+	default 'console=ttyS0,19200'
+	depends on BOOTPARAM
+
+config NO_KERNEL_MSG
+	bool "Suppress Kernel BUG Messages"
+	help
+	  Do not output any debug BUG messages within the kernel.
+
+config BDM_DISABLE
+	bool "Disable BDM signals"
+	depends on (EXPERIMENTAL && COLDFIRE)
+	help
+	  Disable the ColdFire CPU's BDM signals.
+
+endif
+
 endmenu
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Kconfig.mmu linux-libre-2.6.39-gnu/arch/m68k/Kconfig.mmu
--- linux-libre-2.6.38-gnu/arch/m68k/Kconfig.mmu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/Kconfig.mmu	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,417 @@
+config GENERIC_IOMAP
+	bool
+	default y
+
+config ARCH_MAY_HAVE_PC_FDC
+	bool
+	depends on BROKEN && (Q40 || SUN3X)
+	default y
+
+config ARCH_USES_GETTIMEOFFSET
+	def_bool y
+
+config EISA
+	bool
+	---help---
+	  The Extended Industry Standard Architecture (EISA) bus was
+	  developed as an open alternative to the IBM MicroChannel bus.
+
+	  The EISA bus provided some of the features of the IBM MicroChannel
+	  bus while maintaining backward compatibility with cards made for
+	  the older ISA bus.  The EISA bus saw limited use between 1988 and
+	  1995 when it was made obsolete by the PCI bus.
+
+	  Say Y here if you are building a kernel for an EISA-based machine.
+
+	  Otherwise, say N.
+
+config MCA
+	bool
+	help
+	  MicroChannel Architecture is found in some IBM PS/2 machines and
+	  laptops.  It is a bus system similar to PCI or ISA. See
+	  <file:Documentation/mca.txt> (and especially the web page given
+	  there) before attempting to build an MCA bus kernel.
+
+config PCMCIA
+	tristate
+	---help---
+	  Say Y here if you want to attach PCMCIA- or PC-cards to your Linux
+	  computer.  These are credit-card size devices such as network cards,
+	  modems or hard drives often used with laptops computers.  There are
+	  actually two varieties of these cards: the older 16 bit PCMCIA cards
+	  and the newer 32 bit CardBus cards.  If you want to use CardBus
+	  cards, you need to say Y here and also to "CardBus support" below.
+
+	  To use your PC-cards, you will need supporting software from David
+	  Hinds' pcmcia-cs package (see the file <file:Documentation/Changes>
+	  for location).  Please also read the PCMCIA-HOWTO, available from
+	  <http://www.tldp.org/docs.html#howto>.
+
+	  To compile this driver as modules, choose M here: the
+	  modules will be called pcmcia_core and ds.
+
+config AMIGA
+	bool "Amiga support"
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the Amiga series of computers. If
+	  you plan to use this kernel on an Amiga, say Y here and browse the
+	  material available in <file:Documentation/m68k>; otherwise say N.
+
+config ATARI
+	bool "Atari support"
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the 68000-based Atari series of
+	  computers (including the TT, Falcon and Medusa). If you plan to use
+	  this kernel on an Atari, say Y here and browse the material
+	  available in <file:Documentation/m68k>; otherwise say N.
+
+config MAC
+	bool "Macintosh support"
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the Apple Macintosh series of
+	  computers (yes, there is experimental support now, at least for part
+	  of the series).
+
+	  Say N unless you're willing to code the remaining necessary support.
+	  ;)
+
+config NUBUS
+	bool
+	depends on MAC
+	default y
+
+config M68K_L2_CACHE
+	bool
+	depends on MAC
+	default y
+
+config APOLLO
+	bool "Apollo support"
+	select MMU_MOTOROLA if MMU
+	help
+	  Say Y here if you want to run Linux on an MC680x0-based Apollo
+	  Domain workstation such as the DN3500.
+
+config VME
+	bool "VME (Motorola and BVM) support"
+	select MMU_MOTOROLA if MMU
+	help
+	  Say Y here if you want to build a kernel for a 680x0 based VME
+	  board.  Boards currently supported include Motorola boards MVME147,
+	  MVME162, MVME166, MVME167, MVME172, and MVME177.  BVME4000 and
+	  BVME6000 boards from BVM Ltd are also supported.
+
+config MVME147
+	bool "MVME147 support"
+	depends on VME
+	help
+	  Say Y to include support for early Motorola VME boards.  This will
+	  build a kernel which can run on MVME147 single-board computers.  If
+	  you select this option you will have to select the appropriate
+	  drivers for SCSI, Ethernet and serial ports later on.
+
+config MVME16x
+	bool "MVME162, 166 and 167 support"
+	depends on VME
+	help
+	  Say Y to include support for Motorola VME boards.  This will build a
+	  kernel which can run on MVME162, MVME166, MVME167, MVME172, and
+	  MVME177 boards.  If you select this option you will have to select
+	  the appropriate drivers for SCSI, Ethernet and serial ports later
+	  on.
+
+config BVME6000
+	bool "BVME4000 and BVME6000 support"
+	depends on VME
+	help
+	  Say Y to include support for VME boards from BVM Ltd.  This will
+	  build a kernel which can run on BVME4000 and BVME6000 boards.  If
+	  you select this option you will have to select the appropriate
+	  drivers for SCSI, Ethernet and serial ports later on.
+
+config HP300
+	bool "HP9000/300 and HP9000/400 support"
+	select MMU_MOTOROLA if MMU
+	help
+	  This option enables support for the HP9000/300 and HP9000/400 series
+	  of workstations. Support for these machines is still somewhat
+	  experimental. If you plan to try to use the kernel on such a machine
+	  say Y here.
+	  Everybody else says N.
+
+config DIO
+	bool "DIO bus support"
+	depends on HP300
+	default y
+	help
+	  Say Y here to enable support for the "DIO" expansion bus used in
+	  HP300 machines. If you are using such a system you almost certainly
+	  want this.
+
+config SUN3X
+	bool "Sun3x support"
+	select MMU_MOTOROLA if MMU
+	select M68030
+	help
+	  This option enables support for the Sun 3x series of workstations.
+	  Be warned that this support is very experimental.
+	  Note that Sun 3x kernels are not compatible with Sun 3 hardware.
+	  General Linux information on the Sun 3x series (now discontinued)
+	  is at <http://www.angelfire.com/ca2/tech68k/sun3.html>.
+
+	  If you don't want to compile a kernel for a Sun 3x, say N.
+
+config Q40
+	bool "Q40/Q60 support"
+	select MMU_MOTOROLA if MMU
+	help
+	  The Q40 is a Motorola 68040-based successor to the Sinclair QL
+	  manufactured in Germany.  There is an official Q40 home page at
+	  <http://www.q40.de/>.  This option enables support for the Q40 and
+	  Q60. Select your CPU below.  For 68LC060 don't forget to enable FPU
+	  emulation.
+
+config SUN3
+	bool "Sun3 support"
+	depends on !MMU_MOTOROLA
+	select MMU_SUN3 if MMU
+	select M68020
+	help
+	  This option enables support for the Sun 3 series of workstations
+	  (3/50, 3/60, 3/1xx, 3/2xx systems). Enabling this option requires
+	  that all other hardware types must be disabled, as Sun 3 kernels
+	  are incompatible with all other m68k targets (including Sun 3x!).
+
+	  If you don't want to compile a kernel exclusively for a Sun 3, say N.
+
+config NATFEAT
+	bool "ARAnyM emulator support"
+	depends on ATARI
+	help
+	  This option enables support for ARAnyM native features, such as
+	  access to a disk image as /dev/hda.
+
+config NFBLOCK
+	tristate "NatFeat block device support"
+	depends on BLOCK && NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat block device
+	  which allows direct access to the hard drives without using
+	  the hardware emulation.
+
+config NFCON
+	tristate "NatFeat console driver"
+	depends on NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat console driver
+	  which allows the console output to be redirected to the stderr
+	  output of ARAnyM.
+
+config NFETH
+	tristate "NatFeat Ethernet support"
+	depends on NET_ETHERNET && NATFEAT
+	help
+	  Say Y to include support for the ARAnyM NatFeat network device
+	  which will emulate a regular ethernet device while presenting an
+	  ethertap device to the host system.
+
+comment "Processor type"
+
+config M68020
+	bool "68020 support"
+	help
+	  If you anticipate running this kernel on a computer with a MC68020
+	  processor, say Y. Otherwise, say N. Note that the 68020 requires a
+	  68851 MMU (Memory Management Unit) to run Linux/m68k, except on the
+	  Sun 3, which provides its own version.
+
+config M68030
+	bool "68030 support"
+	depends on !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68030
+	  processor, say Y. Otherwise, say N. Note that a MC68EC030 will not
+	  work, as it does not include an MMU (Memory Management Unit).
+
+config M68040
+	bool "68040 support"
+	depends on !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68LC040
+	  or MC68040 processor, say Y. Otherwise, say N. Note that an
+	  MC68EC040 will not work, as it does not include an MMU (Memory
+	  Management Unit).
+
+config M68060
+	bool "68060 support"
+	depends on !MMU_SUN3
+	help
+	  If you anticipate running this kernel on a computer with a MC68060
+	  processor, say Y. Otherwise, say N.
+
+config MMU_MOTOROLA
+	bool
+
+config MMU_SUN3
+	bool
+	depends on MMU && !MMU_MOTOROLA
+
+config M68KFPU_EMU
+	bool "Math emulation support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	help
+	  At some point in the future, this will cause floating-point math
+	  instructions to be emulated by the kernel on machines that lack a
+	  floating-point math coprocessor.  Thrill-seekers and chronically
+	  sleep-deprived psychotic hacker types can say Y now, everyone else
+	  should probably wait a while.
+
+config M68KFPU_EMU_EXTRAPREC
+	bool "Math emulation extra precision"
+	depends on M68KFPU_EMU
+	help
+	  The fpu uses normally a few bit more during calculations for
+	  correct rounding, the emulator can (often) do the same but this
+	  extra calculation can cost quite some time, so you can disable
+	  it here. The emulator will then "only" calculate with a 64 bit
+	  mantissa and round slightly incorrect, what is more than enough
+	  for normal usage.
+
+config M68KFPU_EMU_ONLY
+	bool "Math emulation only kernel"
+	depends on M68KFPU_EMU
+	help
+	  This option prevents any floating-point instructions from being
+	  compiled into the kernel, thereby the kernel doesn't save any
+	  floating point context anymore during task switches, so this
+	  kernel will only be usable on machines without a floating-point
+	  math coprocessor. This makes the kernel a bit faster as no tests
+	  needs to be executed whether a floating-point instruction in the
+	  kernel should be executed or not.
+
+config ADVANCED
+	bool "Advanced configuration options"
+	---help---
+	  This gives you access to some advanced options for the CPU. The
+	  defaults should be fine for most users, but these options may make
+	  it possible for you to improve performance somewhat if you know what
+	  you are doing.
+
+	  Note that the answer to this question won't directly affect the
+	  kernel: saying N will just cause the configurator to skip all
+	  the questions about these options.
+
+	  Most users should say N to this question.
+
+config RMW_INSNS
+	bool "Use read-modify-write instructions"
+	depends on ADVANCED
+	---help---
+	  This allows to use certain instructions that work with indivisible
+	  read-modify-write bus cycles. While this is faster than the
+	  workaround of disabling interrupts, it can conflict with DMA
+	  ( = direct memory access) on many Amiga systems, and it is also said
+	  to destabilize other machines. It is very likely that this will
+	  cause serious problems on any Amiga or Atari Medusa if set. The only
+	  configuration where it should work are 68030-based Ataris, where it
+	  apparently improves performance. But you've been warned! Unless you
+	  really know what you are doing, say N. Try Y only if you're quite
+	  adventurous.
+
+config SINGLE_MEMORY_CHUNK
+	bool "Use one physical chunk of memory only" if ADVANCED && !SUN3
+	default y if SUN3
+	select NEED_MULTIPLE_NODES
+	help
+	  Ignore all but the first contiguous chunk of physical memory for VM
+	  purposes.  This will save a few bytes kernel size and may speed up
+	  some operations.  Say N if not sure.
+
+config 060_WRITETHROUGH
+	bool "Use write-through caching for 68060 supervisor accesses"
+	depends on ADVANCED && M68060
+	---help---
+	  The 68060 generally uses copyback caching of recently accessed data.
+	  Copyback caching means that memory writes will be held in an on-chip
+	  cache and only written back to memory some time later.  Saying Y
+	  here will force supervisor (kernel) accesses to use writethrough
+	  caching.  Writethrough caching means that data is written to memory
+	  straight away, so that cache and memory data always agree.
+	  Writethrough caching is less efficient, but is needed for some
+	  drivers on 68060 based systems where the 68060 bus snooping signal
+	  is hardwired on.  The 53c710 SCSI driver is known to suffer from
+	  this problem.
+
+config ARCH_DISCONTIGMEM_ENABLE
+	def_bool !SINGLE_MEMORY_CHUNK
+
+config NODES_SHIFT
+	int
+	default "3"
+	depends on !SINGLE_MEMORY_CHUNK
+
+config ZORRO
+	bool "Amiga Zorro (AutoConfig) bus support"
+	depends on AMIGA
+	help
+	  This enables support for the Zorro bus in the Amiga. If you have
+	  expansion cards in your Amiga that conform to the Amiga
+	  AutoConfig(tm) specification, say Y, otherwise N. Note that even
+	  expansion cards that do not fit in the Zorro slots but fit in e.g.
+	  the CPU slot may fall in this category, so you have to say Y to let
+	  Linux use these.
+
+config AMIGA_PCMCIA
+	bool "Amiga 1200/600 PCMCIA support (EXPERIMENTAL)"
+	depends on AMIGA && EXPERIMENTAL
+	help
+	  Include support in the kernel for pcmcia on Amiga 1200 and Amiga
+	  600. If you intend to use pcmcia cards say Y; otherwise say N.
+
+config STRAM_PROC
+	bool "ST-RAM statistics in /proc"
+	depends on ATARI
+	help
+	  Say Y here to report ST-RAM usage statistics in /proc/stram.
+
+config HEARTBEAT
+	bool "Use power LED as a heartbeat" if AMIGA || APOLLO || ATARI || MAC ||Q40
+	default y if !AMIGA && !APOLLO && !ATARI && !MAC && !Q40 && HP300
+	help
+	  Use the power-on LED on your machine as a load meter.  The exact
+	  behavior is platform-dependent, but normally the flash frequency is
+	  a hyperbolic function of the 5-minute load average.
+
+# We have a dedicated heartbeat LED. :-)
+config PROC_HARDWARE
+	bool "/proc/hardware support"
+	help
+	  Say Y here to support the /proc/hardware file, which gives you
+	  access to information about the machine you're running on,
+	  including the model, CPU, MMU, clock speed, BogoMIPS rating,
+	  and memory size.
+
+config ISA
+	bool
+	depends on Q40 || AMIGA_PCMCIA
+	default y
+	help
+	  Find out whether you have ISA slots on your motherboard.  ISA is the
+	  name of a bus system, i.e. the way the CPU talks to the other stuff
+	  inside your box.  Other bus systems are PCI, EISA, MicroChannel
+	  (MCA) or VESA.  ISA is an older system, now being displaced by PCI;
+	  newer boards don't support it.  If you have ISA, say Y, otherwise N.
+
+config GENERIC_ISA_DMA
+	bool
+	depends on Q40 || AMIGA_PCMCIA
+	default y
+
+source "drivers/pci/Kconfig"
+
+source "drivers/zorro/Kconfig"
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Kconfig.nommu linux-libre-2.6.39-gnu/arch/m68k/Kconfig.nommu
--- linux-libre-2.6.38-gnu/arch/m68k/Kconfig.nommu	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/Kconfig.nommu	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,750 @@
+config FPU
+	bool
+	default n
+
+config GENERIC_FIND_NEXT_BIT
+	bool
+	default y
+
+config GENERIC_GPIO
+	bool
+	default n
+
+config GENERIC_CMOS_UPDATE
+	bool
+	default y
+
+config GENERIC_CLOCKEVENTS
+	bool
+	default n
+
+config COLDFIRE_SW_A7
+	bool
+	default n
+
+config HAVE_CACHE_SPLIT
+	bool
+
+config HAVE_CACHE_CB
+	bool
+
+config HAVE_MBAR
+	bool
+
+config HAVE_IPSBAR
+	bool
+
+choice
+	prompt "CPU"
+	default M68EZ328
+
+config M68328
+	bool "MC68328"
+	help
+	  Motorola 68328 processor support.
+
+config M68EZ328
+	bool "MC68EZ328"
+	help
+	  Motorola 68EX328 processor support.
+
+config M68VZ328
+	bool "MC68VZ328"
+	help
+	  Motorola 68VZ328 processor support.
+
+config M68360
+	bool "MC68360"
+	help
+	  Motorola 68360 processor support.
+
+config M5206
+	bool "MCF5206"
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5206 processor support.
+
+config M5206e
+	bool "MCF5206e"
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5206e processor support.
+
+config M520x
+	bool "MCF520x"
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	help
+	   Freescale Coldfire 5207/5208 processor support.
+
+config M523x
+	bool "MCF523x"
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Freescale Coldfire 5230/1/2/4/5 processor support
+
+config M5249
+	bool "MCF5249"
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5249 processor support.
+
+config M5271
+	bool "MCF5271"
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Freescale (Motorola) ColdFire 5270/5271 processor support.
+
+config M5272
+	bool "MCF5272"
+	select COLDFIRE_SW_A7
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5272 processor support.
+
+config M5275
+	bool "MCF5275"
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Freescale (Motorola) ColdFire 5274/5275 processor support.
+
+config M528x
+	bool "MCF528x"
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CACHE_SPLIT
+	select HAVE_IPSBAR
+	help
+	  Motorola ColdFire 5280/5282 processor support.
+
+config M5307
+	bool "MCF5307"
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5307 processor support.
+
+config M532x
+	bool "MCF532x"
+	select HAVE_CACHE_CB
+	help
+	  Freescale (Motorola) ColdFire 532x processor support.
+
+config M5407
+	bool "MCF5407"
+	select COLDFIRE_SW_A7
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Motorola ColdFire 5407 processor support.
+
+config M547x
+	bool "MCF547x"
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
+
+config M548x
+	bool "MCF548x"
+	select HAVE_CACHE_CB
+	select HAVE_MBAR
+	help
+	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
+
+endchoice
+
+config M527x
+	bool
+	depends on (M5271 || M5275)
+	select GENERIC_CLOCKEVENTS
+	default y
+
+config M54xx
+	bool
+	depends on (M548x || M547x)
+	default y
+
+config COLDFIRE
+	bool
+	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M54xx)
+	select GENERIC_GPIO
+	select ARCH_REQUIRE_GPIOLIB
+	default y
+
+config CLOCK_SET
+	bool "Enable setting the CPU clock frequency"
+	default n
+	help
+	  On some CPU's you do not need to know what the core CPU clock
+	  frequency is. On these you can disable clock setting. On some
+	  traditional 68K parts, and on all ColdFire parts you need to set
+	  the appropriate CPU clock frequency. On these devices many of the
+	  onboard peripherals derive their timing from the master CPU clock
+	  frequency.
+
+config CLOCK_FREQ
+	int "Set the core clock frequency"
+	default "66666666"
+	depends on CLOCK_SET
+	help
+	  Define the CPU clock frequency in use. This is the core clock
+	  frequency, it may or may not be the same as the external clock
+	  crystal fitted to your board. Some processors have an internal
+	  PLL and can have their frequency programmed at run time, others
+	  use internal dividers. In general the kernel won't setup a PLL
+	  if it is fitted (there are some exceptions). This value will be
+	  specific to the exact CPU that you are using.
+
+config OLDMASK
+	bool "Old mask 5307 (1H55J) silicon"
+	depends on M5307
+	help
+	  Build support for the older revision ColdFire 5307 silicon.
+	  Specifically this is the 1H55J mask revision.
+
+if HAVE_CACHE_SPLIT
+choice
+	prompt "Split Cache Configuration"
+	default CACHE_I
+
+config CACHE_I
+	bool "Instruction"
+	help
+	  Use all of the ColdFire CPU cache memory as an instruction cache.
+
+config CACHE_D
+	bool "Data"
+	help
+	  Use all of the ColdFire CPU cache memory as a data cache.
+
+config CACHE_BOTH
+	bool "Both"
+	help
+	  Split the ColdFire CPU cache, and use half as an instruction cache
+	  and half as a data cache.
+endchoice
+endif
+
+if HAVE_CACHE_CB
+choice
+	prompt "Data cache mode"
+	default CACHE_WRITETHRU
+
+config CACHE_WRITETHRU
+	bool "Write-through"
+	help
+	  The ColdFire CPU cache is set into Write-through mode.
+
+config CACHE_COPYBACK
+	bool "Copy-back"
+	help
+	  The ColdFire CPU cache is set into Copy-back mode.
+endchoice
+endif
+
+comment "Platform"
+
+config PILOT3
+	bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
+	depends on M68328
+	help
+	  Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
+
+config XCOPILOT_BUGS
+	bool "(X)Copilot support"
+	depends on PILOT3
+	help
+	  Support the bugs of Xcopilot.
+
+config UC5272
+	bool 'Arcturus Networks uC5272 dimm board support'
+	depends on M5272
+	help
+	  Support for the Arcturus Networks uC5272 dimm board.
+
+config UC5282
+	bool "Arcturus Networks uC5282 board support"
+	depends on M528x
+	help
+	  Support for the Arcturus Networks uC5282 dimm board.
+
+config UCSIMM
+	bool "uCsimm module support"
+	depends on M68EZ328
+	help
+	  Support for the Arcturus Networks uCsimm module.
+
+config UCDIMM
+	bool "uDsimm module support"
+	depends on M68VZ328
+	help
+	  Support for the Arcturus Networks uDsimm module.
+
+config DRAGEN2
+	bool "DragenEngine II board support"
+	depends on M68VZ328
+	help
+	  Support for the DragenEngine II board.
+
+config DIRECT_IO_ACCESS
+	bool "Allow user to access IO directly"
+	depends on (UCSIMM || UCDIMM || DRAGEN2)
+	help
+	  Disable the CPU internal registers protection in user mode,
+	  to allow a user application to read/write them.
+
+config INIT_LCD
+	bool "Initialize LCD"
+	depends on (UCSIMM || UCDIMM || DRAGEN2)
+	help
+	  Initialize the LCD controller of the 68x328 processor.
+
+config MEMORY_RESERVE
+	int "Memory reservation (MiB)"
+	depends on (UCSIMM || UCDIMM)
+	help
+	  Reserve certain memory regions on 68x328 based boards.
+
+config UCQUICC
+	bool "Lineo uCquicc board support"
+	depends on M68360
+	help
+	  Support for the Lineo uCquicc board.
+
+config ARN5206
+	bool "Arnewsh 5206 board support"
+	depends on M5206
+	help
+	  Support for the Arnewsh 5206 board.
+
+config M5206eC3
+	bool "Motorola M5206eC3 board support"
+	depends on M5206e
+	help
+	  Support for the Motorola M5206eC3 board.
+
+config ELITE
+	bool "Motorola M5206eLITE board support"
+	depends on M5206e
+	help
+	  Support for the Motorola M5206eLITE board.
+
+config M5208EVB
+	bool "Freescale M5208EVB board support"
+	depends on M520x
+	help
+	  Support for the Freescale Coldfire M5208EVB.
+
+config M5235EVB
+	bool "Freescale M5235EVB support"
+	depends on M523x
+	help
+	  Support for the Freescale M5235EVB board.
+
+config M5249C3
+	bool "Motorola M5249C3 board support"
+	depends on M5249
+	help
+	  Support for the Motorola M5249C3 board.
+
+config M5271EVB
+	bool "Freescale (Motorola) M5271EVB board support"
+	depends on M5271
+	help
+	  Support for the Freescale (Motorola) M5271EVB board.
+
+config M5275EVB
+	bool "Freescale (Motorola) M5275EVB board support"
+	depends on M5275
+	help
+	  Support for the Freescale (Motorola) M5275EVB board.
+
+config M5272C3
+	bool "Motorola M5272C3 board support"
+	depends on M5272
+	help
+	  Support for the Motorola M5272C3 board.
+
+config COBRA5272
+	bool "senTec COBRA5272 board support"
+	depends on M5272
+	help
+	  Support for the senTec COBRA5272 board.
+
+config AVNET5282
+	bool "Avnet 5282 board support"
+	depends on M528x
+	help
+	  Support for the Avnet 5282 board.  
+	  
+config M5282EVB
+	bool "Motorola M5282EVB board support"
+	depends on M528x
+	help
+	  Support for the Motorola M5282EVB board.
+
+config COBRA5282
+	bool "senTec COBRA5282 board support"
+	depends on M528x
+	help
+	  Support for the senTec COBRA5282 board.
+	  
+config SOM5282EM
+	bool "EMAC.Inc SOM5282EM board support"
+	depends on M528x
+	help
+	  Support for the EMAC.Inc SOM5282EM module.  
+	  
+config WILDFIRE
+	bool "Intec Automation Inc. WildFire board support"
+	depends on M528x
+	help
+	  Support for the Intec Automation Inc. WildFire.
+	  
+config WILDFIREMOD
+	bool "Intec Automation Inc. WildFire module support"
+	depends on M528x
+	help
+	  Support for the Intec Automation Inc. WildFire module.
+
+config ARN5307
+	bool "Arnewsh 5307 board support"
+	depends on M5307
+	help
+	  Support for the Arnewsh 5307 board.
+
+config M5307C3
+	bool "Motorola M5307C3 board support"
+	depends on M5307
+	help
+	  Support for the Motorola M5307C3 board.
+
+config SECUREEDGEMP3
+	bool "SnapGear SecureEdge/MP3 platform support"
+	depends on M5307
+	help
+	  Support for the SnapGear SecureEdge/MP3 platform.
+
+config M5329EVB
+	bool "Freescale (Motorola) M5329EVB board support"
+	depends on M532x
+	help
+	  Support for the Freescale (Motorola) M5329EVB board.
+
+config COBRA5329
+	bool "senTec COBRA5329 board support"
+	depends on M532x
+	help
+	  Support for the senTec COBRA5329 board.
+
+config M5407C3
+	bool "Motorola M5407C3 board support"
+	depends on M5407
+	help
+	  Support for the Motorola M5407C3 board.
+
+config FIREBEE
+	bool "FireBee board support"
+	depends on M547x
+	help
+	  Support for the FireBee ColdFire 5475 based board.
+
+config CLEOPATRA
+	bool "Feith CLEOPATRA board support"
+	depends on (M5307 || M5407)
+	help
+	  Support for the Feith Cleopatra boards.
+
+config CANCam
+	bool "Feith CANCam board support"
+	depends on M5272
+	help
+	  Support for the Feith CANCam board.
+
+config SCALES
+	bool "Feith SCALES board support"
+	depends on M5272
+	help
+	  Support for the Feith SCALES board.
+
+config NETtel
+	bool "SecureEdge/NETtel board support"
+	depends on (M5206e || M5272 || M5307)
+	help
+	  Support for the SnapGear NETtel/SecureEdge/SnapGear boards.
+
+config SNAPGEAR
+	bool "SnapGear router board support"
+	depends on NETtel
+	help
+	  Special additional support for SnapGear router boards.
+
+config CPU16B
+	bool "Sneha Technologies S.L. Sarasvati board support"
+	depends on M5272
+	help
+	  Support for the SNEHA CPU16B board.
+
+config MOD5272
+	bool "Netburner MOD-5272 board support"
+	depends on M5272
+	help
+	  Support for the Netburner MOD-5272 board.
+
+config SAVANTrosie1
+	bool "Savant Rosie1 board support"
+	depends on M523x
+	help
+	  Support for the Savant Rosie1 board.
+
+config ROMFS_FROM_ROM
+	bool "ROMFS image not RAM resident"
+	depends on (NETtel || SNAPGEAR)
+	help
+	  The ROMfs filesystem will stay resident in the FLASH/ROM, not be
+	  moved into RAM.
+
+config PILOT
+	bool
+	default y
+	depends on (PILOT3 || PILOT5)
+
+config ARNEWSH
+	bool
+	default y
+	depends on (ARN5206 || ARN5307)
+
+config FREESCALE
+	bool
+	default y
+	depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3)
+
+config HW_FEITH
+	bool
+	default y
+	depends on (CLEOPATRA || CANCam || SCALES)
+
+config senTec
+	bool
+	default y
+	depends on (COBRA5272 || COBRA5282)
+	
+config EMAC_INC
+	bool
+	default y
+	depends on (SOM5282EM)
+
+config SNEHA
+	bool
+	default y
+	depends on CPU16B
+
+config SAVANT
+	bool
+	default y
+	depends on SAVANTrosie1
+
+config AVNET
+	bool
+	default y
+	depends on (AVNET5282)
+
+config UBOOT
+	bool "Support for U-Boot command line parameters"
+	help
+	  If you say Y here kernel will try to collect command
+	  line parameters from the initial u-boot stack.
+	default n
+
+config 4KSTACKS
+	bool "Use 4Kb for kernel stacks instead of 8Kb"
+	default y
+	help
+	  If you say Y here the kernel will use a 4Kb stacksize for the
+	  kernel stack attached to each process/thread. This facilitates
+	  running more threads on a system and also reduces the pressure
+	  on the VM subsystem for higher order allocations.
+
+comment "RAM configuration"
+
+config RAMBASE
+	hex "Address of the base of RAM"
+	default "0"
+	help
+	  Define the address that RAM starts at. On many platforms this is
+	  0, the base of the address space. And this is the default. Some
+	  platforms choose to setup their RAM at other addresses within the
+	  processor address space.
+
+config RAMSIZE
+	hex "Size of RAM (in bytes), or 0 for automatic"
+	default "0x400000"
+	help
+	  Define the size of the system RAM. If you select 0 then the
+	  kernel will try to probe the RAM size at runtime. This is not
+	  supported on all CPU types.
+
+config VECTORBASE
+	hex "Address of the base of system vectors"
+	default "0"
+	help
+	  Define the address of the system vectors. Commonly this is
+	  put at the start of RAM, but it doesn't have to be. On ColdFire
+	  platforms this address is programmed into the VBR register, thus
+	  actually setting the address to use.
+
+config MBAR
+	hex "Address of the MBAR (internal peripherals)"
+	default "0x10000000"
+	depends on HAVE_MBAR
+	help
+	  Define the address of the internal system peripherals. This value
+	  is set in the processors MBAR register. This is generally setup by
+	  the boot loader, and will not be written by the kernel. By far most
+	  ColdFire boards use the default 0x10000000 value, so if unsure then
+	  use this.
+
+config IPSBAR
+	hex "Address of the IPSBAR (internal peripherals)"
+	default "0x40000000"
+	depends on HAVE_IPSBAR
+	help
+	  Define the address of the internal system peripherals. This value
+	  is set in the processors IPSBAR register. This is generally setup by
+	  the boot loader, and will not be written by the kernel. By far most
+	  ColdFire boards use the default 0x40000000 value, so if unsure then
+	  use this.
+
+config KERNELBASE
+	hex "Address of the base of kernel code"
+	default "0x400"
+	help
+	  Typically on m68k systems the kernel will not start at the base
+	  of RAM, but usually some small offset from it. Define the start
+	  address of the kernel here. The most common setup will have the
+	  processor vectors at the base of RAM and then the start of the
+	  kernel. On some platforms some RAM is reserved for boot loaders
+	  and the kernel starts after that. The 0x400 default was based on
+	  a system with the RAM based at address 0, and leaving enough room
+	  for the theoretical maximum number of 256 vectors.
+
+choice
+	prompt "RAM bus width"
+	default RAMAUTOBIT
+
+config RAMAUTOBIT
+	bool "AUTO"
+	help
+	  Select the physical RAM data bus size. Not needed on most platforms,
+	  so you can generally choose AUTO.
+
+config RAM8BIT
+	bool "8bit"
+	help
+	  Configure RAM bus to be 8 bits wide.
+
+config RAM16BIT
+	bool "16bit"
+	help
+	  Configure RAM bus to be 16 bits wide.
+
+config RAM32BIT
+	bool "32bit"
+	help
+	  Configure RAM bus to be 32 bits wide.
+
+endchoice
+
+comment "ROM configuration"
+
+config ROM
+	bool "Specify ROM linker regions"
+	default n
+	help
+	  Define a ROM region for the linker script. This creates a kernel
+	  that can be stored in flash, with possibly the text, and data
+	  regions being copied out to RAM at startup.
+
+config ROMBASE
+	hex "Address of the base of ROM device"
+	default "0"
+	depends on ROM
+	help
+	  Define the address that the ROM region starts at. Some platforms
+	  use this to set their chip select region accordingly for the boot
+	  device.
+
+config ROMVEC
+	hex "Address of the base of the ROM vectors"
+	default "0"
+	depends on ROM
+	help
+	  This is almost always the same as the base of the ROM. Since on all
+	  68000 type variants the vectors are at the base of the boot device
+	  on system startup.
+
+config ROMVECSIZE
+	hex "Size of ROM vector region (in bytes)"
+	default "0x400"
+	depends on ROM
+	help
+	  Define the size of the vector region in ROM. For most 68000
+	  variants this would be 0x400 bytes in size. Set to 0 if you do
+	  not want a vector region at the start of the ROM.
+
+config ROMSTART
+	hex "Address of the base of system image in ROM"
+	default "0x400"
+	depends on ROM
+	help
+	  Define the start address of the system image in ROM. Commonly this
+	  is strait after the ROM vectors.
+
+config ROMSIZE
+	hex "Size of the ROM device"
+	default "0x100000"
+	depends on ROM
+	help
+	  Size of the ROM device. On some platforms this is used to setup
+	  the chip select that controls the boot ROM device.
+
+choice
+	prompt "Kernel executes from"
+	---help---
+	  Choose the memory type that the kernel will be running in.
+
+config RAMKERNEL
+	bool "RAM"
+	help
+	  The kernel will be resident in RAM when running.
+
+config ROMKERNEL
+	bool "ROM"
+	help
+	  The kernel will be resident in FLASH/ROM when running. This is
+	  often referred to as Execute-in-Place (XIP), since the kernel
+	  code executes from the position it is stored in the FLASH/ROM.
+
+endchoice
+
+if COLDFIRE
+source "kernel/Kconfig.preempt"
+endif
+
+source "kernel/time/Kconfig"
+
+config ISA_DMA_API
+	bool
+	depends on !M5272
+	default y
+
+source "drivers/pcmcia/Kconfig"
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/asm-offsets.c linux-libre-2.6.39-gnu/arch/m68k/kernel/asm-offsets.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/asm-offsets.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/asm-offsets.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,100 +1,5 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#define ASM_OFFSETS_C
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/kbuild.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/amigahw.h>
-#include <linux/font.h>
-
-int main(void)
-{
-	/* offsets into the task struct */
-	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-	DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
-	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
 #ifdef CONFIG_MMU
-	DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
+#include "asm-offsets_mm.c"
+#else
+#include "asm-offsets_no.c"
 #endif
-
-	/* offsets into the thread struct */
-	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
-	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
-	DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
-	DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
-	DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
-	DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
-	DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
-	DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
-	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
-
-	/* offsets into the thread_info struct */
-	DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
-	DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
-
-	/* offsets into the pt_regs */
-	DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
-	DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
-	DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
-	DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
-	DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
-	DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
-	DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
-	DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
-	DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
-	DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
-	DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
-	DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
-	/* bitfields are a bit difficult */
-	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
-
-	/* offsets into the irq_cpustat_t struct */
-	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
-
-	/* offsets into the bi_record struct */
-	DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
-	DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
-	DEFINE(BIR_DATA, offsetof(struct bi_record, data));
-
-	/* offsets into font_desc (drivers/video/console/font.h) */
-	DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
-	DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
-	DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
-	DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
-	DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
-	DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
-
-	/* signal defines */
-	DEFINE(LSIGSEGV, SIGSEGV);
-	DEFINE(LSEGV_MAPERR, SEGV_MAPERR);
-	DEFINE(LSIGTRAP, SIGTRAP);
-	DEFINE(LTRAP_TRACE, TRAP_TRACE);
-
-	/* offsets into the custom struct */
-	DEFINE(CUSTOMBASE, &amiga_custom);
-	DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
-	DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
-	DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
-	DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
-	DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
-	DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
-	DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
-	DEFINE(CIAABASE, &ciaa);
-	DEFINE(CIABBASE, &ciab);
-	DEFINE(C_PRA, offsetof(struct CIA, pra));
-	DEFINE(ZTWOBASE, zTwoBase);
-
-	return 0;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/asm-offsets_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/asm-offsets_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/asm-offsets_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/asm-offsets_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#define ASM_OFFSETS_C
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/kbuild.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/amigahw.h>
+#include <linux/font.h>
+
+int main(void)
+{
+	/* offsets into the task struct */
+	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+	DEFINE(TASK_INFO, offsetof(struct task_struct, thread.info));
+	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+#ifdef CONFIG_MMU
+	DEFINE(TASK_TINFO, offsetof(struct task_struct, thread.info));
+#endif
+
+	/* offsets into the thread struct */
+	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+	DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
+	DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
+	DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
+	DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+	DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
+	DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
+	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
+
+	/* offsets into the thread_info struct */
+	DEFINE(TINFO_PREEMPT, offsetof(struct thread_info, preempt_count));
+	DEFINE(TINFO_FLAGS, offsetof(struct thread_info, flags));
+
+	/* offsets into the pt_regs */
+	DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
+	DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+	DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
+	DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
+	DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
+	DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
+	DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
+	DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
+	DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
+	DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
+	DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
+	DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
+	/* bitfields are a bit difficult */
+	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
+
+	/* offsets into the irq_cpustat_t struct */
+	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
+
+	/* offsets into the bi_record struct */
+	DEFINE(BIR_TAG, offsetof(struct bi_record, tag));
+	DEFINE(BIR_SIZE, offsetof(struct bi_record, size));
+	DEFINE(BIR_DATA, offsetof(struct bi_record, data));
+
+	/* offsets into font_desc (drivers/video/console/font.h) */
+	DEFINE(FONT_DESC_IDX, offsetof(struct font_desc, idx));
+	DEFINE(FONT_DESC_NAME, offsetof(struct font_desc, name));
+	DEFINE(FONT_DESC_WIDTH, offsetof(struct font_desc, width));
+	DEFINE(FONT_DESC_HEIGHT, offsetof(struct font_desc, height));
+	DEFINE(FONT_DESC_DATA, offsetof(struct font_desc, data));
+	DEFINE(FONT_DESC_PREF, offsetof(struct font_desc, pref));
+
+	/* signal defines */
+	DEFINE(LSIGSEGV, SIGSEGV);
+	DEFINE(LSEGV_MAPERR, SEGV_MAPERR);
+	DEFINE(LSIGTRAP, SIGTRAP);
+	DEFINE(LTRAP_TRACE, TRAP_TRACE);
+
+	/* offsets into the custom struct */
+	DEFINE(CUSTOMBASE, &amiga_custom);
+	DEFINE(C_INTENAR, offsetof(struct CUSTOM, intenar));
+	DEFINE(C_INTREQR, offsetof(struct CUSTOM, intreqr));
+	DEFINE(C_INTENA, offsetof(struct CUSTOM, intena));
+	DEFINE(C_INTREQ, offsetof(struct CUSTOM, intreq));
+	DEFINE(C_SERDATR, offsetof(struct CUSTOM, serdatr));
+	DEFINE(C_SERDAT, offsetof(struct CUSTOM, serdat));
+	DEFINE(C_SERPER, offsetof(struct CUSTOM, serper));
+	DEFINE(CIAABASE, &ciaa);
+	DEFINE(CIABBASE, &ciab);
+	DEFINE(C_PRA, offsetof(struct CIA, pra));
+	DEFINE(ZTWOBASE, zTwoBase);
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/asm-offsets_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/asm-offsets_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/asm-offsets_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/asm-offsets_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,76 @@
+/*
+ * This program is used to generate definitions needed by
+ * assembly language modules.
+ *
+ * We use the technique used in the OSF Mach kernel code:
+ * generate asm statements containing #defines,
+ * compile this file to assembler, and then extract the
+ * #defines from the assembly-language output.
+ */
+
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/kernel_stat.h>
+#include <linux/ptrace.h>
+#include <linux/hardirq.h>
+#include <linux/kbuild.h>
+#include <asm/bootinfo.h>
+#include <asm/irq.h>
+#include <asm/thread_info.h>
+
+int main(void)
+{
+	/* offsets into the task struct */
+	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
+	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
+
+	/* offsets into the irq_cpustat_t struct */
+	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
+
+	/* offsets into the thread struct */
+	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
+	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
+	DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
+	DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
+	DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
+	DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
+	DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
+	DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
+	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
+
+	/* offsets into the pt_regs */
+	DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
+	DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
+	DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
+	DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
+	DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
+	DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
+	DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
+	DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
+	DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
+	DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
+	DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
+	DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
+
+#ifdef CONFIG_COLDFIRE
+	/* bitfields are a bit difficult */
+	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
+#else
+	/* bitfields are a bit difficult */
+	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
+#endif
+
+	/* signal defines */
+	DEFINE(SIGSEGV, SIGSEGV);
+	DEFINE(SEGV_MAPERR, SEGV_MAPERR);
+	DEFINE(SIGTRAP, SIGTRAP);
+	DEFINE(TRAP_TRACE, TRAP_TRACE);
+
+	DEFINE(PT_PTRACED, PT_PTRACED);
+
+	/* Offsets in thread_info structure */
+	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
+	DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/dma.c linux-libre-2.6.39-gnu/arch/m68k/kernel/dma.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,130 +1,5 @@
-/*
- * 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/dma-mapping.h>
-#include <linux/device.h>
-#include <linux/kernel.h>
-#include <linux/scatterlist.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/pgalloc.h>
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-			 dma_addr_t *handle, gfp_t flag)
-{
-	struct page *page, **map;
-	pgprot_t pgprot;
-	void *addr;
-	int i, order;
-
-	pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
-
-	size = PAGE_ALIGN(size);
-	order = get_order(size);
-
-	page = alloc_pages(flag, order);
-	if (!page)
-		return NULL;
-
-	*handle = page_to_phys(page);
-	map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
-	if (!map) {
-		__free_pages(page, order);
-		return NULL;
-	}
-	split_page(page, order);
-
-	order = 1 << order;
-	size >>= PAGE_SHIFT;
-	map[0] = page;
-	for (i = 1; i < size; i++)
-		map[i] = page + i;
-	for (; i < order; i++)
-		__free_page(page + i);
-	pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
-	if (CPU_IS_040_OR_060)
-		pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
-	else
-		pgprot_val(pgprot) |= _PAGE_NOCACHE030;
-	addr = vmap(map, size, VM_MAP, pgprot);
-	kfree(map);
-
-	return addr;
-}
-EXPORT_SYMBOL(dma_alloc_coherent);
-
-void dma_free_coherent(struct device *dev, size_t size,
-		       void *addr, dma_addr_t handle)
-{
-	pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
-	vfree(addr);
-}
-EXPORT_SYMBOL(dma_free_coherent);
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
-				size_t size, enum dma_data_direction dir)
-{
-	switch (dir) {
-	case DMA_TO_DEVICE:
-		cache_push(handle, size);
-		break;
-	case DMA_FROM_DEVICE:
-		cache_clear(handle, size);
-		break;
-	default:
-		if (printk_ratelimit())
-			printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
-		break;
-	}
-}
-EXPORT_SYMBOL(dma_sync_single_for_device);
-
-void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
-			    enum dma_data_direction dir)
-{
-	int i;
-
-	for (i = 0; i < nents; sg++, i++)
-		dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
-}
-EXPORT_SYMBOL(dma_sync_sg_for_device);
-
-dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
-			  enum dma_data_direction dir)
-{
-	dma_addr_t handle = virt_to_bus(addr);
-
-	dma_sync_single_for_device(dev, handle, size, dir);
-	return handle;
-}
-EXPORT_SYMBOL(dma_map_single);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-			unsigned long offset, size_t size,
-			enum dma_data_direction dir)
-{
-	dma_addr_t handle = page_to_phys(page) + offset;
-
-	dma_sync_single_for_device(dev, handle, size, dir);
-	return handle;
-}
-EXPORT_SYMBOL(dma_map_page);
-
-int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
-	       enum dma_data_direction dir)
-{
-	int i;
-
-	for (i = 0; i < nents; sg++, i++) {
-		sg->dma_address = sg_phys(sg);
-		dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
-	}
-	return nents;
-}
-EXPORT_SYMBOL(dma_map_sg);
+#ifdef CONFIG_MMU
+#include "dma_mm.c"
+#else
+#include "dma_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/dma_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/dma_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/dma_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/dma_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,130 @@
+/*
+ * 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/dma-mapping.h>
+#include <linux/device.h>
+#include <linux/kernel.h>
+#include <linux/scatterlist.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <asm/pgalloc.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			 dma_addr_t *handle, gfp_t flag)
+{
+	struct page *page, **map;
+	pgprot_t pgprot;
+	void *addr;
+	int i, order;
+
+	pr_debug("dma_alloc_coherent: %d,%x\n", size, flag);
+
+	size = PAGE_ALIGN(size);
+	order = get_order(size);
+
+	page = alloc_pages(flag, order);
+	if (!page)
+		return NULL;
+
+	*handle = page_to_phys(page);
+	map = kmalloc(sizeof(struct page *) << order, flag & ~__GFP_DMA);
+	if (!map) {
+		__free_pages(page, order);
+		return NULL;
+	}
+	split_page(page, order);
+
+	order = 1 << order;
+	size >>= PAGE_SHIFT;
+	map[0] = page;
+	for (i = 1; i < size; i++)
+		map[i] = page + i;
+	for (; i < order; i++)
+		__free_page(page + i);
+	pgprot = __pgprot(_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+	if (CPU_IS_040_OR_060)
+		pgprot_val(pgprot) |= _PAGE_GLOBAL040 | _PAGE_NOCACHE_S;
+	else
+		pgprot_val(pgprot) |= _PAGE_NOCACHE030;
+	addr = vmap(map, size, VM_MAP, pgprot);
+	kfree(map);
+
+	return addr;
+}
+EXPORT_SYMBOL(dma_alloc_coherent);
+
+void dma_free_coherent(struct device *dev, size_t size,
+		       void *addr, dma_addr_t handle)
+{
+	pr_debug("dma_free_coherent: %p, %x\n", addr, handle);
+	vfree(addr);
+}
+EXPORT_SYMBOL(dma_free_coherent);
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+				size_t size, enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		cache_push(handle, size);
+		break;
+	case DMA_FROM_DEVICE:
+		cache_clear(handle, size);
+		break;
+	default:
+		if (printk_ratelimit())
+			printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+		break;
+	}
+}
+EXPORT_SYMBOL(dma_sync_single_for_device);
+
+void dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nents,
+			    enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nents; sg++, i++)
+		dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+}
+EXPORT_SYMBOL(dma_sync_sg_for_device);
+
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+			  enum dma_data_direction dir)
+{
+	dma_addr_t handle = virt_to_bus(addr);
+
+	dma_sync_single_for_device(dev, handle, size, dir);
+	return handle;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+			unsigned long offset, size_t size,
+			enum dma_data_direction dir)
+{
+	dma_addr_t handle = page_to_phys(page) + offset;
+
+	dma_sync_single_for_device(dev, handle, size, dir);
+	return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
+
+int dma_map_sg(struct device *dev, struct scatterlist *sg, int nents,
+	       enum dma_data_direction dir)
+{
+	int i;
+
+	for (i = 0; i < nents; sg++, i++) {
+		sg->dma_address = sg_phys(sg);
+		dma_sync_single_for_device(dev, sg->dma_address, sg->length, dir);
+	}
+	return nents;
+}
+EXPORT_SYMBOL(dma_map_sg);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/dma_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/dma_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/dma_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/dma_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * Dynamic DMA mapping support.
+ *
+ * We never have any address translations to worry about, so this
+ * is just alloc/free.
+ */
+
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <asm/cacheflush.h>
+
+void *dma_alloc_coherent(struct device *dev, size_t size,
+			   dma_addr_t *dma_handle, gfp_t gfp)
+{
+	void *ret;
+	/* ignore region specifiers */
+	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
+
+	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
+		gfp |= GFP_DMA;
+	ret = (void *)__get_free_pages(gfp, get_order(size));
+
+	if (ret != NULL) {
+		memset(ret, 0, size);
+		*dma_handle = virt_to_phys(ret);
+	}
+	return ret;
+}
+
+void dma_free_coherent(struct device *dev, size_t size,
+			 void *vaddr, dma_addr_t dma_handle)
+{
+	free_pages((unsigned long)vaddr, get_order(size));
+}
+
+void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
+				size_t size, enum dma_data_direction dir)
+{
+	switch (dir) {
+	case DMA_TO_DEVICE:
+		flush_dcache_range(handle, size);
+		break;
+	case DMA_FROM_DEVICE:
+		/* Should be clear already */
+		break;
+	default:
+		if (printk_ratelimit())
+			printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
+		break;
+	}
+}
+
+EXPORT_SYMBOL(dma_sync_single_for_device);
+dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
+			  enum dma_data_direction dir)
+{
+	dma_addr_t handle = virt_to_phys(addr);
+	flush_dcache_range(handle, size);
+	return handle;
+}
+EXPORT_SYMBOL(dma_map_single);
+
+dma_addr_t dma_map_page(struct device *dev, struct page *page,
+			unsigned long offset, size_t size,
+			enum dma_data_direction dir)
+{
+	dma_addr_t handle = page_to_phys(page) + offset;
+	dma_sync_single_for_device(dev, handle, size, dir);
+	return handle;
+}
+EXPORT_SYMBOL(dma_map_page);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/entry_mm.S linux-libre-2.6.39-gnu/arch/m68k/kernel/entry_mm.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/entry_mm.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/entry_mm.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,757 @@
+/* -*- mode: asm -*-
+ *
+ *  linux/arch/m68k/kernel/entry.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ *
+ */
+
+/*
+ * entry.S  contains the system-call and fault low-level handling routines.
+ * This also contains the timer-interrupt handler, as well as all interrupts
+ * and faults that can result in a task-switch.
+ *
+ * NOTE: This code handles signal-recognition, which happens every time
+ * after a timer-interrupt and after each system call.
+ *
+ */
+
+/*
+ * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
+ *               all pointers that used to be 'current' are now entry
+ *               number 0 in the 'current_set' list.
+ *
+ *  6/05/00 RZ:	 addedd writeback completion after return from sighandler
+ *		 for 68040
+ */
+
+#include <linux/linkage.h>
+#include <asm/entry.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/traps.h>
+#include <asm/unistd.h>
+
+#include <asm/asm-offsets.h>
+
+.globl system_call, buserr, trap, resume
+.globl sys_call_table
+.globl sys_fork, sys_clone, sys_vfork
+.globl ret_from_interrupt, bad_interrupt
+.globl auto_irqhandler_fixup
+.globl user_irqvec_fixup, user_irqhandler_fixup
+
+.text
+ENTRY(buserr)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	movel	%sp,%sp@-		| stack frame pointer argument
+	bsrl	buserr_c
+	addql	#4,%sp
+	jra	.Lret_from_exception
+
+ENTRY(trap)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	movel	%sp,%sp@-		| stack frame pointer argument
+	bsrl	trap_c
+	addql	#4,%sp
+	jra	.Lret_from_exception
+
+	| After a fork we jump here directly from resume,
+	| so that %d1 contains the previous task
+	| schedule_tail now used regardless of CONFIG_SMP
+ENTRY(ret_from_fork)
+	movel	%d1,%sp@-
+	jsr	schedule_tail
+	addql	#4,%sp
+	jra	.Lret_from_exception
+
+do_trace_entry:
+	movel	#-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
+	subql	#4,%sp
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	movel	%sp@(PT_OFF_ORIG_D0),%d0
+	cmpl	#NR_syscalls,%d0
+	jcs	syscall
+badsys:
+	movel	#-ENOSYS,%sp@(PT_OFF_D0)
+	jra	ret_from_syscall
+
+do_trace_exit:
+	subql	#4,%sp
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jra	.Lret_from_exception
+
+ENTRY(ret_from_signal)
+	tstb	%curptr@(TASK_INFO+TINFO_FLAGS+2)
+	jge	1f
+	jbsr	syscall_trace
+1:	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+/* on 68040 complete pending writebacks if any */
+#ifdef CONFIG_M68040
+	bfextu	%sp@(PT_OFF_FORMATVEC){#0,#4},%d0
+	subql	#7,%d0				| bus error frame ?
+	jbne	1f
+	movel	%sp,%sp@-
+	jbsr	berr_040cleanup
+	addql	#4,%sp
+1:
+#endif
+	jra	.Lret_from_exception
+
+ENTRY(system_call)
+	SAVE_ALL_SYS
+
+	GET_CURRENT(%d1)
+	| save top of frame
+	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
+
+	| syscall trace?
+	tstb	%curptr@(TASK_INFO+TINFO_FLAGS+2)
+	jmi	do_trace_entry
+	cmpl	#NR_syscalls,%d0
+	jcc	badsys
+syscall:
+	jbsr	@(sys_call_table,%d0:l:4)@(0)
+	movel	%d0,%sp@(PT_OFF_D0)	| save the return value
+ret_from_syscall:
+	|oriw	#0x0700,%sr
+	movew	%curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
+	jne	syscall_exit_work
+1:	RESTORE_ALL
+
+syscall_exit_work:
+	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
+	bnes	1b			| if so, skip resched, signals
+	lslw	#1,%d0
+	jcs	do_trace_exit
+	jmi	do_delayed_trace
+	lslw	#8,%d0
+	jmi	do_signal_return
+	pea	resume_userspace
+	jra	schedule
+
+
+ENTRY(ret_from_exception)
+.Lret_from_exception:
+	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
+	bnes	1f			| if so, skip resched, signals
+	| only allow interrupts when we are really the last one on the
+	| kernel stack, otherwise stack overflow can occur during
+	| heavy interrupt load
+	andw	#ALLOWINT,%sr
+
+resume_userspace:
+	moveb	%curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
+	jne	exit_work
+1:	RESTORE_ALL
+
+exit_work:
+	| save top of frame
+	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
+	lslb	#1,%d0
+	jmi	do_signal_return
+	pea	resume_userspace
+	jra	schedule
+
+
+do_signal_return:
+	|andw	#ALLOWINT,%sr
+	subql	#4,%sp			| dummy return address
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	bsrl	do_signal
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jbra	resume_userspace
+
+do_delayed_trace:
+	bclr	#7,%sp@(PT_OFF_SR)	| clear trace bit in SR
+	pea	1			| send SIGTRAP
+	movel	%curptr,%sp@-
+	pea	LSIGTRAP
+	jbsr	send_sig
+	addql	#8,%sp
+	addql	#4,%sp
+	jbra	resume_userspace
+
+
+/* This is the main interrupt handler for autovector interrupts */
+
+ENTRY(auto_inthandler)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+					|  put exception # in d0
+	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0
+	subw	#VEC_SPUR,%d0
+
+	movel	%sp,%sp@-
+	movel	%d0,%sp@-		|  put vector # on stack
+auto_irqhandler_fixup = . + 2
+	jsr	__m68k_handle_int	|  process the IRQ
+	addql	#8,%sp			|  pop parameters off stack
+
+ret_from_interrupt:
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+	jeq	ret_from_last_interrupt
+2:	RESTORE_ALL
+
+	ALIGN
+ret_from_last_interrupt:
+	moveq	#(~ALLOWINT>>8)&0xff,%d0
+	andb	%sp@(PT_OFF_SR),%d0
+	jne	2b
+
+	/* check if we need to do software interrupts */
+	tstl	irq_stat+CPUSTAT_SOFTIRQ_PENDING
+	jeq	.Lret_from_exception
+	pea	ret_from_exception
+	jra	do_softirq
+
+/* Handler for user defined interrupt vectors */
+
+ENTRY(user_inthandler)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+					|  put exception # in d0
+	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0
+user_irqvec_fixup = . + 2
+	subw	#VEC_USER,%d0
+
+	movel	%sp,%sp@-
+	movel	%d0,%sp@-		|  put vector # on stack
+user_irqhandler_fixup = . + 2
+	jsr	__m68k_handle_int	|  process the IRQ
+	addql	#8,%sp			|  pop parameters off stack
+
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+	jeq	ret_from_last_interrupt
+	RESTORE_ALL
+
+/* Handler for uninitialized and spurious interrupts */
+
+ENTRY(bad_inthandler)
+	SAVE_ALL_INT
+	GET_CURRENT(%d0)
+	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+
+	movel	%sp,%sp@-
+	jsr	handle_badint
+	addql	#4,%sp
+
+	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
+	jeq	ret_from_last_interrupt
+	RESTORE_ALL
+
+
+ENTRY(sys_fork)
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	m68k_fork
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_clone)
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	m68k_clone
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_vfork)
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	m68k_vfork
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_sigreturn)
+	SAVE_SWITCH_STACK
+	jbsr	do_sigreturn
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_rt_sigreturn)
+	SAVE_SWITCH_STACK
+	jbsr	do_rt_sigreturn
+	RESTORE_SWITCH_STACK
+	rts
+
+resume:
+	/*
+	 * Beware - when entering resume, prev (the current task) is
+	 * in a0, next (the new task) is in a1,so don't change these
+	 * registers until their contents are no longer needed.
+	 */
+
+	/* save sr */
+	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)
+
+	/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
+	movec	%sfc,%d0
+	movew	%d0,%a0@(TASK_THREAD+THREAD_FS)
+
+	/* save usp */
+	/* it is better to use a movel here instead of a movew 8*) */
+	movec	%usp,%d0
+	movel	%d0,%a0@(TASK_THREAD+THREAD_USP)
+
+	/* save non-scratch registers on stack */
+	SAVE_SWITCH_STACK
+
+	/* save current kernel stack pointer */
+	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP)
+
+	/* save floating point context */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+	tstl	m68k_fputype
+	jeq	3f
+#endif
+	fsave	%a0@(TASK_THREAD+THREAD_FPSTATE)
+
+#if defined(CONFIG_M68060)
+#if !defined(CPU_M68060_ONLY)
+	btst	#3,m68k_cputype+3
+	beqs	1f
+#endif
+	/* The 060 FPU keeps status in bits 15-8 of the first longword */
+	tstb	%a0@(TASK_THREAD+THREAD_FPSTATE+2)
+	jeq	3f
+#if !defined(CPU_M68060_ONLY)
+	jra	2f
+#endif
+#endif /* CONFIG_M68060 */
+#if !defined(CPU_M68060_ONLY)
+1:	tstb	%a0@(TASK_THREAD+THREAD_FPSTATE)
+	jeq	3f
+#endif
+2:	fmovemx	%fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
+	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
+3:
+#endif	/* CONFIG_M68KFPU_EMU_ONLY */
+	/* Return previous task in %d1 */
+	movel	%curptr,%d1
+
+	/* switch to new task (a1 contains new task) */
+	movel	%a1,%curptr
+
+	/* restore floating point context */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+#ifdef CONFIG_M68KFPU_EMU
+	tstl	m68k_fputype
+	jeq	4f
+#endif
+#if defined(CONFIG_M68060)
+#if !defined(CPU_M68060_ONLY)
+	btst	#3,m68k_cputype+3
+	beqs	1f
+#endif
+	/* The 060 FPU keeps status in bits 15-8 of the first longword */
+	tstb	%a1@(TASK_THREAD+THREAD_FPSTATE+2)
+	jeq	3f
+#if !defined(CPU_M68060_ONLY)
+	jra	2f
+#endif
+#endif /* CONFIG_M68060 */
+#if !defined(CPU_M68060_ONLY)
+1:	tstb	%a1@(TASK_THREAD+THREAD_FPSTATE)
+	jeq	3f
+#endif
+2:	fmovemx	%a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
+	fmoveml	%a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
+3:	frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
+4:
+#endif	/* CONFIG_M68KFPU_EMU_ONLY */
+
+	/* restore the kernel stack pointer */
+	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp
+
+	/* restore non-scratch registers */
+	RESTORE_SWITCH_STACK
+
+	/* restore user stack pointer */
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a0
+	movel	%a0,%usp
+
+	/* restore fs (sfc,%dfc) */
+	movew	%a1@(TASK_THREAD+THREAD_FS),%a0
+	movec	%a0,%sfc
+	movec	%a0,%dfc
+
+	/* restore status register */
+	movew	%a1@(TASK_THREAD+THREAD_SR),%sr
+
+	rts
+
+.data
+ALIGN
+sys_call_table:
+	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
+	.long sys_exit
+	.long sys_fork
+	.long sys_read
+	.long sys_write
+	.long sys_open		/* 5 */
+	.long sys_close
+	.long sys_waitpid
+	.long sys_creat
+	.long sys_link
+	.long sys_unlink	/* 10 */
+	.long sys_execve
+	.long sys_chdir
+	.long sys_time
+	.long sys_mknod
+	.long sys_chmod		/* 15 */
+	.long sys_chown16
+	.long sys_ni_syscall				/* old break syscall holder */
+	.long sys_stat
+	.long sys_lseek
+	.long sys_getpid	/* 20 */
+	.long sys_mount
+	.long sys_oldumount
+	.long sys_setuid16
+	.long sys_getuid16
+	.long sys_stime		/* 25 */
+	.long sys_ptrace
+	.long sys_alarm
+	.long sys_fstat
+	.long sys_pause
+	.long sys_utime		/* 30 */
+	.long sys_ni_syscall				/* old stty syscall holder */
+	.long sys_ni_syscall				/* old gtty syscall holder */
+	.long sys_access
+	.long sys_nice
+	.long sys_ni_syscall	/* 35 */	/* old ftime syscall holder */
+	.long sys_sync
+	.long sys_kill
+	.long sys_rename
+	.long sys_mkdir
+	.long sys_rmdir		/* 40 */
+	.long sys_dup
+	.long sys_pipe
+	.long sys_times
+	.long sys_ni_syscall				/* old prof syscall holder */
+	.long sys_brk		/* 45 */
+	.long sys_setgid16
+	.long sys_getgid16
+	.long sys_signal
+	.long sys_geteuid16
+	.long sys_getegid16	/* 50 */
+	.long sys_acct
+	.long sys_umount				/* recycled never used phys() */
+	.long sys_ni_syscall				/* old lock syscall holder */
+	.long sys_ioctl
+	.long sys_fcntl		/* 55 */
+	.long sys_ni_syscall				/* old mpx syscall holder */
+	.long sys_setpgid
+	.long sys_ni_syscall				/* old ulimit syscall holder */
+	.long sys_ni_syscall
+	.long sys_umask		/* 60 */
+	.long sys_chroot
+	.long sys_ustat
+	.long sys_dup2
+	.long sys_getppid
+	.long sys_getpgrp	/* 65 */
+	.long sys_setsid
+	.long sys_sigaction
+	.long sys_sgetmask
+	.long sys_ssetmask
+	.long sys_setreuid16	/* 70 */
+	.long sys_setregid16
+	.long sys_sigsuspend
+	.long sys_sigpending
+	.long sys_sethostname
+	.long sys_setrlimit	/* 75 */
+	.long sys_old_getrlimit
+	.long sys_getrusage
+	.long sys_gettimeofday
+	.long sys_settimeofday
+	.long sys_getgroups16	/* 80 */
+	.long sys_setgroups16
+	.long sys_old_select
+	.long sys_symlink
+	.long sys_lstat
+	.long sys_readlink	/* 85 */
+	.long sys_uselib
+	.long sys_swapon
+	.long sys_reboot
+	.long sys_old_readdir
+	.long sys_old_mmap	/* 90 */
+	.long sys_munmap
+	.long sys_truncate
+	.long sys_ftruncate
+	.long sys_fchmod
+	.long sys_fchown16	/* 95 */
+	.long sys_getpriority
+	.long sys_setpriority
+	.long sys_ni_syscall				/* old profil syscall holder */
+	.long sys_statfs
+	.long sys_fstatfs	/* 100 */
+	.long sys_ni_syscall				/* ioperm for i386 */
+	.long sys_socketcall
+	.long sys_syslog
+	.long sys_setitimer
+	.long sys_getitimer	/* 105 */
+	.long sys_newstat
+	.long sys_newlstat
+	.long sys_newfstat
+	.long sys_ni_syscall
+	.long sys_ni_syscall	/* 110 */	/* iopl for i386 */
+	.long sys_vhangup
+	.long sys_ni_syscall				/* obsolete idle() syscall */
+	.long sys_ni_syscall				/* vm86old for i386 */
+	.long sys_wait4
+	.long sys_swapoff	/* 115 */
+	.long sys_sysinfo
+	.long sys_ipc
+	.long sys_fsync
+	.long sys_sigreturn
+	.long sys_clone		/* 120 */
+	.long sys_setdomainname
+	.long sys_newuname
+	.long sys_cacheflush				/* modify_ldt for i386 */
+	.long sys_adjtimex
+	.long sys_mprotect	/* 125 */
+	.long sys_sigprocmask
+	.long sys_ni_syscall		/* old "create_module" */
+	.long sys_init_module
+	.long sys_delete_module
+	.long sys_ni_syscall	/* 130 - old "get_kernel_syms" */
+	.long sys_quotactl
+	.long sys_getpgid
+	.long sys_fchdir
+	.long sys_bdflush
+	.long sys_sysfs		/* 135 */
+	.long sys_personality
+	.long sys_ni_syscall				/* for afs_syscall */
+	.long sys_setfsuid16
+	.long sys_setfsgid16
+	.long sys_llseek	/* 140 */
+	.long sys_getdents
+	.long sys_select
+	.long sys_flock
+	.long sys_msync
+	.long sys_readv		/* 145 */
+	.long sys_writev
+	.long sys_getsid
+	.long sys_fdatasync
+	.long sys_sysctl
+	.long sys_mlock		/* 150 */
+	.long sys_munlock
+	.long sys_mlockall
+	.long sys_munlockall
+	.long sys_sched_setparam
+	.long sys_sched_getparam	/* 155 */
+	.long sys_sched_setscheduler
+	.long sys_sched_getscheduler
+	.long sys_sched_yield
+	.long sys_sched_get_priority_max
+	.long sys_sched_get_priority_min  /* 160 */
+	.long sys_sched_rr_get_interval
+	.long sys_nanosleep
+	.long sys_mremap
+	.long sys_setresuid16
+	.long sys_getresuid16	/* 165 */
+	.long sys_getpagesize
+	.long sys_ni_syscall		/* old sys_query_module */
+	.long sys_poll
+	.long sys_nfsservctl
+	.long sys_setresgid16	/* 170 */
+	.long sys_getresgid16
+	.long sys_prctl
+	.long sys_rt_sigreturn
+	.long sys_rt_sigaction
+	.long sys_rt_sigprocmask	/* 175 */
+	.long sys_rt_sigpending
+	.long sys_rt_sigtimedwait
+	.long sys_rt_sigqueueinfo
+	.long sys_rt_sigsuspend
+	.long sys_pread64	/* 180 */
+	.long sys_pwrite64
+	.long sys_lchown16;
+	.long sys_getcwd
+	.long sys_capget
+	.long sys_capset	/* 185 */
+	.long sys_sigaltstack
+	.long sys_sendfile
+	.long sys_ni_syscall				/* streams1 */
+	.long sys_ni_syscall				/* streams2 */
+	.long sys_vfork		/* 190 */
+	.long sys_getrlimit
+	.long sys_mmap2
+	.long sys_truncate64
+	.long sys_ftruncate64
+	.long sys_stat64	/* 195 */
+	.long sys_lstat64
+	.long sys_fstat64
+	.long sys_chown
+	.long sys_getuid
+	.long sys_getgid	/* 200 */
+	.long sys_geteuid
+	.long sys_getegid
+	.long sys_setreuid
+	.long sys_setregid
+	.long sys_getgroups	/* 205 */
+	.long sys_setgroups
+	.long sys_fchown
+	.long sys_setresuid
+	.long sys_getresuid
+	.long sys_setresgid	/* 210 */
+	.long sys_getresgid
+	.long sys_lchown
+	.long sys_setuid
+	.long sys_setgid
+	.long sys_setfsuid	/* 215 */
+	.long sys_setfsgid
+	.long sys_pivot_root
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_getdents64	/* 220 */
+	.long sys_gettid
+	.long sys_tkill
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr	/* 225 */
+	.long sys_getxattr
+	.long sys_lgetxattr
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr	/* 230 */
+	.long sys_flistxattr
+	.long sys_removexattr
+	.long sys_lremovexattr
+	.long sys_fremovexattr
+	.long sys_futex		/* 235 */
+	.long sys_sendfile64
+	.long sys_mincore
+	.long sys_madvise
+	.long sys_fcntl64
+	.long sys_readahead	/* 240 */
+	.long sys_io_setup
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel	/* 245 */
+	.long sys_fadvise64
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl	/* 250 */
+	.long sys_epoll_wait
+	.long sys_remap_file_pages
+	.long sys_set_tid_address
+	.long sys_timer_create
+	.long sys_timer_settime	/* 255 */
+	.long sys_timer_gettime
+	.long sys_timer_getoverrun
+	.long sys_timer_delete
+	.long sys_clock_settime
+	.long sys_clock_gettime	/* 260 */
+	.long sys_clock_getres
+	.long sys_clock_nanosleep
+	.long sys_statfs64
+	.long sys_fstatfs64
+	.long sys_tgkill	/* 265 */
+	.long sys_utimes
+	.long sys_fadvise64_64
+	.long sys_mbind
+	.long sys_get_mempolicy
+	.long sys_set_mempolicy	/* 270 */
+	.long sys_mq_open
+	.long sys_mq_unlink
+	.long sys_mq_timedsend
+	.long sys_mq_timedreceive
+	.long sys_mq_notify	/* 275 */
+	.long sys_mq_getsetattr
+	.long sys_waitid
+	.long sys_ni_syscall	/* for sys_vserver */
+	.long sys_add_key
+	.long sys_request_key	/* 280 */
+	.long sys_keyctl
+	.long sys_ioprio_set
+	.long sys_ioprio_get
+	.long sys_inotify_init
+	.long sys_inotify_add_watch	/* 285 */
+	.long sys_inotify_rm_watch
+	.long sys_migrate_pages
+	.long sys_openat
+	.long sys_mkdirat
+	.long sys_mknodat		/* 290 */
+	.long sys_fchownat
+	.long sys_futimesat
+	.long sys_fstatat64
+	.long sys_unlinkat
+	.long sys_renameat		/* 295 */
+	.long sys_linkat
+	.long sys_symlinkat
+	.long sys_readlinkat
+	.long sys_fchmodat
+	.long sys_faccessat		/* 300 */
+	.long sys_ni_syscall		/* Reserved for pselect6 */
+	.long sys_ni_syscall		/* Reserved for ppoll */
+	.long sys_unshare
+	.long sys_set_robust_list
+	.long sys_get_robust_list	/* 305 */
+	.long sys_splice
+	.long sys_sync_file_range
+	.long sys_tee
+	.long sys_vmsplice
+	.long sys_move_pages		/* 310 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_kexec_load
+	.long sys_getcpu
+	.long sys_epoll_pwait		/* 315 */
+	.long sys_utimensat
+	.long sys_signalfd
+	.long sys_timerfd_create
+	.long sys_eventfd
+	.long sys_fallocate		/* 320 */
+	.long sys_timerfd_settime
+	.long sys_timerfd_gettime
+	.long sys_signalfd4
+	.long sys_eventfd2
+	.long sys_epoll_create1		/* 325 */
+	.long sys_dup3
+	.long sys_pipe2
+	.long sys_inotify_init1
+	.long sys_preadv
+	.long sys_pwritev		/* 330 */
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_event_open
+	.long sys_get_thread_area
+	.long sys_set_thread_area
+	.long sys_atomic_cmpxchg_32	/* 335 */
+	.long sys_atomic_barrier
+	.long sys_fanotify_init
+	.long sys_fanotify_mark
+	.long sys_prlimit64
+	.long sys_name_to_handle_at	/* 340 */
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
+	.long sys_syncfs
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/entry_no.S linux-libre-2.6.39-gnu/arch/m68k/kernel/entry_no.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/entry_no.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/entry_no.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ *  linux/arch/m68knommu/kernel/entry.S
+ *
+ *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
+ *                      Kenneth Albanowski <kjahds@kjahds.com>,
+ *  Copyright (C) 2000  Lineo Inc. (www.lineo.com) 
+ *
+ * Based on:
+ *
+ *  linux/arch/m68k/kernel/entry.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ * ColdFire support by Greg Ungerer (gerg@snapgear.com)
+ * 5307 fixes by David W. Miller
+ * linux 2.4 support David McCullough <davidm@snapgear.com>
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+#include <asm/unistd.h>
+
+.text
+
+.globl buserr
+.globl trap
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_fork
+.globl sys_clone
+.globl sys_vfork
+
+ENTRY(buserr)
+	SAVE_ALL
+	moveq	#-1,%d0
+	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+	movel	%sp,%sp@- 		/* stack frame pointer argument */
+	jsr	buserr_c
+	addql	#4,%sp
+	jra	ret_from_exception
+
+ENTRY(trap)
+	SAVE_ALL
+	moveq	#-1,%d0
+	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+	movel	%sp,%sp@- 		/* stack frame pointer argument */
+	jsr	trap_c
+	addql	#4,%sp
+	jra	ret_from_exception
+
+#ifdef TRAP_DBG_INTERRUPT
+
+.globl dbginterrupt
+ENTRY(dbginterrupt)
+	SAVE_ALL
+	moveq	#-1,%d0
+	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+	movel	%sp,%sp@- 		/* stack frame pointer argument */
+	jsr	dbginterrupt_c
+	addql	#4,%sp
+	jra	ret_from_exception
+#endif
+
+ENTRY(reschedule)
+	/* save top of frame */
+	pea	%sp@
+	jbsr	set_esp0
+	addql	#4,%sp
+	pea	ret_from_exception
+	jmp	schedule
+
+ENTRY(ret_from_fork)
+	movel	%d1,%sp@-
+	jsr	schedule_tail
+	addql	#4,%sp
+	jra	ret_from_exception
+
+ENTRY(sys_fork)
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	m68k_fork
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_vfork)
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	m68k_vfork
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_clone)
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jbsr	m68k_clone
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_sigreturn)
+	SAVE_SWITCH_STACK
+	jbsr	do_sigreturn
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(sys_rt_sigreturn)
+	SAVE_SWITCH_STACK
+	jbsr	do_rt_sigreturn
+	RESTORE_SWITCH_STACK
+	rts
+
+ENTRY(ret_from_user_signal)
+	moveq #__NR_sigreturn,%d0
+	trap #0
+
+ENTRY(ret_from_user_rt_signal)
+	movel #__NR_rt_sigreturn,%d0
+	trap #0
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/entry.S linux-libre-2.6.39-gnu/arch/m68k/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -1,753 +1,5 @@
-/* -*- mode: asm -*-
- *
- *  linux/arch/m68k/kernel/entry.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- *
- */
-
-/*
- * entry.S  contains the system-call and fault low-level handling routines.
- * This also contains the timer-interrupt handler, as well as all interrupts
- * and faults that can result in a task-switch.
- *
- * NOTE: This code handles signal-recognition, which happens every time
- * after a timer-interrupt and after each system call.
- *
- */
-
-/*
- * 12/03/96 Jes: Currently we only support m68k single-cpu systems, so
- *               all pointers that used to be 'current' are now entry
- *               number 0 in the 'current_set' list.
- *
- *  6/05/00 RZ:	 addedd writeback completion after return from sighandler
- *		 for 68040
- */
-
-#include <linux/linkage.h>
-#include <asm/entry.h>
-#include <asm/errno.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/traps.h>
-#include <asm/unistd.h>
-
-#include <asm/asm-offsets.h>
-
-.globl system_call, buserr, trap, resume
-.globl sys_call_table
-.globl sys_fork, sys_clone, sys_vfork
-.globl ret_from_interrupt, bad_interrupt
-.globl auto_irqhandler_fixup
-.globl user_irqvec_fixup, user_irqhandler_fixup
-
-.text
-ENTRY(buserr)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	movel	%sp,%sp@-		| stack frame pointer argument
-	bsrl	buserr_c
-	addql	#4,%sp
-	jra	.Lret_from_exception
-
-ENTRY(trap)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	movel	%sp,%sp@-		| stack frame pointer argument
-	bsrl	trap_c
-	addql	#4,%sp
-	jra	.Lret_from_exception
-
-	| After a fork we jump here directly from resume,
-	| so that %d1 contains the previous task
-	| schedule_tail now used regardless of CONFIG_SMP
-ENTRY(ret_from_fork)
-	movel	%d1,%sp@-
-	jsr	schedule_tail
-	addql	#4,%sp
-	jra	.Lret_from_exception
-
-do_trace_entry:
-	movel	#-ENOSYS,%sp@(PT_OFF_D0)| needed for strace
-	subql	#4,%sp
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	movel	%sp@(PT_OFF_ORIG_D0),%d0
-	cmpl	#NR_syscalls,%d0
-	jcs	syscall
-badsys:
-	movel	#-ENOSYS,%sp@(PT_OFF_D0)
-	jra	ret_from_syscall
-
-do_trace_exit:
-	subql	#4,%sp
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jra	.Lret_from_exception
-
-ENTRY(ret_from_signal)
-	tstb	%curptr@(TASK_INFO+TINFO_FLAGS+2)
-	jge	1f
-	jbsr	syscall_trace
-1:	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-/* on 68040 complete pending writebacks if any */
-#ifdef CONFIG_M68040
-	bfextu	%sp@(PT_OFF_FORMATVEC){#0,#4},%d0
-	subql	#7,%d0				| bus error frame ?
-	jbne	1f
-	movel	%sp,%sp@-
-	jbsr	berr_040cleanup
-	addql	#4,%sp
-1:
-#endif
-	jra	.Lret_from_exception
-
-ENTRY(system_call)
-	SAVE_ALL_SYS
-
-	GET_CURRENT(%d1)
-	| save top of frame
-	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
-
-	| syscall trace?
-	tstb	%curptr@(TASK_INFO+TINFO_FLAGS+2)
-	jmi	do_trace_entry
-	cmpl	#NR_syscalls,%d0
-	jcc	badsys
-syscall:
-	jbsr	@(sys_call_table,%d0:l:4)@(0)
-	movel	%d0,%sp@(PT_OFF_D0)	| save the return value
-ret_from_syscall:
-	|oriw	#0x0700,%sr
-	movew	%curptr@(TASK_INFO+TINFO_FLAGS+2),%d0
-	jne	syscall_exit_work
-1:	RESTORE_ALL
-
-syscall_exit_work:
-	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
-	bnes	1b			| if so, skip resched, signals
-	lslw	#1,%d0
-	jcs	do_trace_exit
-	jmi	do_delayed_trace
-	lslw	#8,%d0
-	jmi	do_signal_return
-	pea	resume_userspace
-	jra	schedule
-
-
-ENTRY(ret_from_exception)
-.Lret_from_exception:
-	btst	#5,%sp@(PT_OFF_SR)	| check if returning to kernel
-	bnes	1f			| if so, skip resched, signals
-	| only allow interrupts when we are really the last one on the
-	| kernel stack, otherwise stack overflow can occur during
-	| heavy interrupt load
-	andw	#ALLOWINT,%sr
-
-resume_userspace:
-	moveb	%curptr@(TASK_INFO+TINFO_FLAGS+3),%d0
-	jne	exit_work
-1:	RESTORE_ALL
-
-exit_work:
-	| save top of frame
-	movel	%sp,%curptr@(TASK_THREAD+THREAD_ESP0)
-	lslb	#1,%d0
-	jmi	do_signal_return
-	pea	resume_userspace
-	jra	schedule
-
-
-do_signal_return:
-	|andw	#ALLOWINT,%sr
-	subql	#4,%sp			| dummy return address
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	bsrl	do_signal
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jbra	resume_userspace
-
-do_delayed_trace:
-	bclr	#7,%sp@(PT_OFF_SR)	| clear trace bit in SR
-	pea	1			| send SIGTRAP
-	movel	%curptr,%sp@-
-	pea	LSIGTRAP
-	jbsr	send_sig
-	addql	#8,%sp
-	addql	#4,%sp
-	jbra	resume_userspace
-
-
-/* This is the main interrupt handler for autovector interrupts */
-
-ENTRY(auto_inthandler)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
-					|  put exception # in d0
-	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0
-	subw	#VEC_SPUR,%d0
-
-	movel	%sp,%sp@-
-	movel	%d0,%sp@-		|  put vector # on stack
-auto_irqhandler_fixup = . + 2
-	jsr	__m68k_handle_int	|  process the IRQ
-	addql	#8,%sp			|  pop parameters off stack
-
-ret_from_interrupt:
-	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
-	jeq	ret_from_last_interrupt
-2:	RESTORE_ALL
-
-	ALIGN
-ret_from_last_interrupt:
-	moveq	#(~ALLOWINT>>8)&0xff,%d0
-	andb	%sp@(PT_OFF_SR),%d0
-	jne	2b
-
-	/* check if we need to do software interrupts */
-	tstl	irq_stat+CPUSTAT_SOFTIRQ_PENDING
-	jeq	.Lret_from_exception
-	pea	ret_from_exception
-	jra	do_softirq
-
-/* Handler for user defined interrupt vectors */
-
-ENTRY(user_inthandler)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
-					|  put exception # in d0
-	bfextu	%sp@(PT_OFF_FORMATVEC){#4,#10},%d0
-user_irqvec_fixup = . + 2
-	subw	#VEC_USER,%d0
-
-	movel	%sp,%sp@-
-	movel	%d0,%sp@-		|  put vector # on stack
-user_irqhandler_fixup = . + 2
-	jsr	__m68k_handle_int	|  process the IRQ
-	addql	#8,%sp			|  pop parameters off stack
-
-	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
-	jeq	ret_from_last_interrupt
-	RESTORE_ALL
-
-/* Handler for uninitialized and spurious interrupts */
-
-ENTRY(bad_inthandler)
-	SAVE_ALL_INT
-	GET_CURRENT(%d0)
-	addqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
-
-	movel	%sp,%sp@-
-	jsr	handle_badint
-	addql	#4,%sp
-
-	subqb	#1,%curptr@(TASK_INFO+TINFO_PREEMPT+1)
-	jeq	ret_from_last_interrupt
-	RESTORE_ALL
-
-
-ENTRY(sys_fork)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_fork
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_clone)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_clone
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_vfork)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_vfork
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_sigreturn)
-	SAVE_SWITCH_STACK
-	jbsr	do_sigreturn
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_rt_sigreturn)
-	SAVE_SWITCH_STACK
-	jbsr	do_rt_sigreturn
-	RESTORE_SWITCH_STACK
-	rts
-
-resume:
-	/*
-	 * Beware - when entering resume, prev (the current task) is
-	 * in a0, next (the new task) is in a1,so don't change these
-	 * registers until their contents are no longer needed.
-	 */
-
-	/* save sr */
-	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)
-
-	/* save fs (sfc,%dfc) (may be pointing to kernel memory) */
-	movec	%sfc,%d0
-	movew	%d0,%a0@(TASK_THREAD+THREAD_FS)
-
-	/* save usp */
-	/* it is better to use a movel here instead of a movew 8*) */
-	movec	%usp,%d0
-	movel	%d0,%a0@(TASK_THREAD+THREAD_USP)
-
-	/* save non-scratch registers on stack */
-	SAVE_SWITCH_STACK
-
-	/* save current kernel stack pointer */
-	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP)
-
-	/* save floating point context */
-#ifndef CONFIG_M68KFPU_EMU_ONLY
-#ifdef CONFIG_M68KFPU_EMU
-	tstl	m68k_fputype
-	jeq	3f
-#endif
-	fsave	%a0@(TASK_THREAD+THREAD_FPSTATE)
-
-#if defined(CONFIG_M68060)
-#if !defined(CPU_M68060_ONLY)
-	btst	#3,m68k_cputype+3
-	beqs	1f
-#endif
-	/* The 060 FPU keeps status in bits 15-8 of the first longword */
-	tstb	%a0@(TASK_THREAD+THREAD_FPSTATE+2)
-	jeq	3f
-#if !defined(CPU_M68060_ONLY)
-	jra	2f
-#endif
-#endif /* CONFIG_M68060 */
-#if !defined(CPU_M68060_ONLY)
-1:	tstb	%a0@(TASK_THREAD+THREAD_FPSTATE)
-	jeq	3f
-#endif
-2:	fmovemx	%fp0-%fp7,%a0@(TASK_THREAD+THREAD_FPREG)
-	fmoveml	%fpcr/%fpsr/%fpiar,%a0@(TASK_THREAD+THREAD_FPCNTL)
-3:
-#endif	/* CONFIG_M68KFPU_EMU_ONLY */
-	/* Return previous task in %d1 */
-	movel	%curptr,%d1
-
-	/* switch to new task (a1 contains new task) */
-	movel	%a1,%curptr
-
-	/* restore floating point context */
-#ifndef CONFIG_M68KFPU_EMU_ONLY
-#ifdef CONFIG_M68KFPU_EMU
-	tstl	m68k_fputype
-	jeq	4f
-#endif
-#if defined(CONFIG_M68060)
-#if !defined(CPU_M68060_ONLY)
-	btst	#3,m68k_cputype+3
-	beqs	1f
-#endif
-	/* The 060 FPU keeps status in bits 15-8 of the first longword */
-	tstb	%a1@(TASK_THREAD+THREAD_FPSTATE+2)
-	jeq	3f
-#if !defined(CPU_M68060_ONLY)
-	jra	2f
-#endif
-#endif /* CONFIG_M68060 */
-#if !defined(CPU_M68060_ONLY)
-1:	tstb	%a1@(TASK_THREAD+THREAD_FPSTATE)
-	jeq	3f
+#ifdef CONFIG_MMU
+#include "entry_mm.S"
+#else
+#include "entry_no.S"
 #endif
-2:	fmovemx	%a1@(TASK_THREAD+THREAD_FPREG),%fp0-%fp7
-	fmoveml	%a1@(TASK_THREAD+THREAD_FPCNTL),%fpcr/%fpsr/%fpiar
-3:	frestore %a1@(TASK_THREAD+THREAD_FPSTATE)
-4:
-#endif	/* CONFIG_M68KFPU_EMU_ONLY */
-
-	/* restore the kernel stack pointer */
-	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp
-
-	/* restore non-scratch registers */
-	RESTORE_SWITCH_STACK
-
-	/* restore user stack pointer */
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0
-	movel	%a0,%usp
-
-	/* restore fs (sfc,%dfc) */
-	movew	%a1@(TASK_THREAD+THREAD_FS),%a0
-	movec	%a0,%sfc
-	movec	%a0,%dfc
-
-	/* restore status register */
-	movew	%a1@(TASK_THREAD+THREAD_SR),%sr
-
-	rts
-
-.data
-ALIGN
-sys_call_table:
-	.long sys_restart_syscall	/* 0 - old "setup()" system call, used for restarting */
-	.long sys_exit
-	.long sys_fork
-	.long sys_read
-	.long sys_write
-	.long sys_open		/* 5 */
-	.long sys_close
-	.long sys_waitpid
-	.long sys_creat
-	.long sys_link
-	.long sys_unlink	/* 10 */
-	.long sys_execve
-	.long sys_chdir
-	.long sys_time
-	.long sys_mknod
-	.long sys_chmod		/* 15 */
-	.long sys_chown16
-	.long sys_ni_syscall				/* old break syscall holder */
-	.long sys_stat
-	.long sys_lseek
-	.long sys_getpid	/* 20 */
-	.long sys_mount
-	.long sys_oldumount
-	.long sys_setuid16
-	.long sys_getuid16
-	.long sys_stime		/* 25 */
-	.long sys_ptrace
-	.long sys_alarm
-	.long sys_fstat
-	.long sys_pause
-	.long sys_utime		/* 30 */
-	.long sys_ni_syscall				/* old stty syscall holder */
-	.long sys_ni_syscall				/* old gtty syscall holder */
-	.long sys_access
-	.long sys_nice
-	.long sys_ni_syscall	/* 35 */	/* old ftime syscall holder */
-	.long sys_sync
-	.long sys_kill
-	.long sys_rename
-	.long sys_mkdir
-	.long sys_rmdir		/* 40 */
-	.long sys_dup
-	.long sys_pipe
-	.long sys_times
-	.long sys_ni_syscall				/* old prof syscall holder */
-	.long sys_brk		/* 45 */
-	.long sys_setgid16
-	.long sys_getgid16
-	.long sys_signal
-	.long sys_geteuid16
-	.long sys_getegid16	/* 50 */
-	.long sys_acct
-	.long sys_umount				/* recycled never used phys() */
-	.long sys_ni_syscall				/* old lock syscall holder */
-	.long sys_ioctl
-	.long sys_fcntl		/* 55 */
-	.long sys_ni_syscall				/* old mpx syscall holder */
-	.long sys_setpgid
-	.long sys_ni_syscall				/* old ulimit syscall holder */
-	.long sys_ni_syscall
-	.long sys_umask		/* 60 */
-	.long sys_chroot
-	.long sys_ustat
-	.long sys_dup2
-	.long sys_getppid
-	.long sys_getpgrp	/* 65 */
-	.long sys_setsid
-	.long sys_sigaction
-	.long sys_sgetmask
-	.long sys_ssetmask
-	.long sys_setreuid16	/* 70 */
-	.long sys_setregid16
-	.long sys_sigsuspend
-	.long sys_sigpending
-	.long sys_sethostname
-	.long sys_setrlimit	/* 75 */
-	.long sys_old_getrlimit
-	.long sys_getrusage
-	.long sys_gettimeofday
-	.long sys_settimeofday
-	.long sys_getgroups16	/* 80 */
-	.long sys_setgroups16
-	.long sys_old_select
-	.long sys_symlink
-	.long sys_lstat
-	.long sys_readlink	/* 85 */
-	.long sys_uselib
-	.long sys_swapon
-	.long sys_reboot
-	.long sys_old_readdir
-	.long sys_old_mmap	/* 90 */
-	.long sys_munmap
-	.long sys_truncate
-	.long sys_ftruncate
-	.long sys_fchmod
-	.long sys_fchown16	/* 95 */
-	.long sys_getpriority
-	.long sys_setpriority
-	.long sys_ni_syscall				/* old profil syscall holder */
-	.long sys_statfs
-	.long sys_fstatfs	/* 100 */
-	.long sys_ni_syscall				/* ioperm for i386 */
-	.long sys_socketcall
-	.long sys_syslog
-	.long sys_setitimer
-	.long sys_getitimer	/* 105 */
-	.long sys_newstat
-	.long sys_newlstat
-	.long sys_newfstat
-	.long sys_ni_syscall
-	.long sys_ni_syscall	/* 110 */	/* iopl for i386 */
-	.long sys_vhangup
-	.long sys_ni_syscall				/* obsolete idle() syscall */
-	.long sys_ni_syscall				/* vm86old for i386 */
-	.long sys_wait4
-	.long sys_swapoff	/* 115 */
-	.long sys_sysinfo
-	.long sys_ipc
-	.long sys_fsync
-	.long sys_sigreturn
-	.long sys_clone		/* 120 */
-	.long sys_setdomainname
-	.long sys_newuname
-	.long sys_cacheflush				/* modify_ldt for i386 */
-	.long sys_adjtimex
-	.long sys_mprotect	/* 125 */
-	.long sys_sigprocmask
-	.long sys_ni_syscall		/* old "create_module" */
-	.long sys_init_module
-	.long sys_delete_module
-	.long sys_ni_syscall	/* 130 - old "get_kernel_syms" */
-	.long sys_quotactl
-	.long sys_getpgid
-	.long sys_fchdir
-	.long sys_bdflush
-	.long sys_sysfs		/* 135 */
-	.long sys_personality
-	.long sys_ni_syscall				/* for afs_syscall */
-	.long sys_setfsuid16
-	.long sys_setfsgid16
-	.long sys_llseek	/* 140 */
-	.long sys_getdents
-	.long sys_select
-	.long sys_flock
-	.long sys_msync
-	.long sys_readv		/* 145 */
-	.long sys_writev
-	.long sys_getsid
-	.long sys_fdatasync
-	.long sys_sysctl
-	.long sys_mlock		/* 150 */
-	.long sys_munlock
-	.long sys_mlockall
-	.long sys_munlockall
-	.long sys_sched_setparam
-	.long sys_sched_getparam	/* 155 */
-	.long sys_sched_setscheduler
-	.long sys_sched_getscheduler
-	.long sys_sched_yield
-	.long sys_sched_get_priority_max
-	.long sys_sched_get_priority_min  /* 160 */
-	.long sys_sched_rr_get_interval
-	.long sys_nanosleep
-	.long sys_mremap
-	.long sys_setresuid16
-	.long sys_getresuid16	/* 165 */
-	.long sys_getpagesize
-	.long sys_ni_syscall		/* old sys_query_module */
-	.long sys_poll
-	.long sys_nfsservctl
-	.long sys_setresgid16	/* 170 */
-	.long sys_getresgid16
-	.long sys_prctl
-	.long sys_rt_sigreturn
-	.long sys_rt_sigaction
-	.long sys_rt_sigprocmask	/* 175 */
-	.long sys_rt_sigpending
-	.long sys_rt_sigtimedwait
-	.long sys_rt_sigqueueinfo
-	.long sys_rt_sigsuspend
-	.long sys_pread64	/* 180 */
-	.long sys_pwrite64
-	.long sys_lchown16;
-	.long sys_getcwd
-	.long sys_capget
-	.long sys_capset	/* 185 */
-	.long sys_sigaltstack
-	.long sys_sendfile
-	.long sys_ni_syscall				/* streams1 */
-	.long sys_ni_syscall				/* streams2 */
-	.long sys_vfork		/* 190 */
-	.long sys_getrlimit
-	.long sys_mmap2
-	.long sys_truncate64
-	.long sys_ftruncate64
-	.long sys_stat64	/* 195 */
-	.long sys_lstat64
-	.long sys_fstat64
-	.long sys_chown
-	.long sys_getuid
-	.long sys_getgid	/* 200 */
-	.long sys_geteuid
-	.long sys_getegid
-	.long sys_setreuid
-	.long sys_setregid
-	.long sys_getgroups	/* 205 */
-	.long sys_setgroups
-	.long sys_fchown
-	.long sys_setresuid
-	.long sys_getresuid
-	.long sys_setresgid	/* 210 */
-	.long sys_getresgid
-	.long sys_lchown
-	.long sys_setuid
-	.long sys_setgid
-	.long sys_setfsuid	/* 215 */
-	.long sys_setfsgid
-	.long sys_pivot_root
-	.long sys_ni_syscall
-	.long sys_ni_syscall
-	.long sys_getdents64	/* 220 */
-	.long sys_gettid
-	.long sys_tkill
-	.long sys_setxattr
-	.long sys_lsetxattr
-	.long sys_fsetxattr	/* 225 */
-	.long sys_getxattr
-	.long sys_lgetxattr
-	.long sys_fgetxattr
-	.long sys_listxattr
-	.long sys_llistxattr	/* 230 */
-	.long sys_flistxattr
-	.long sys_removexattr
-	.long sys_lremovexattr
-	.long sys_fremovexattr
-	.long sys_futex		/* 235 */
-	.long sys_sendfile64
-	.long sys_mincore
-	.long sys_madvise
-	.long sys_fcntl64
-	.long sys_readahead	/* 240 */
-	.long sys_io_setup
-	.long sys_io_destroy
-	.long sys_io_getevents
-	.long sys_io_submit
-	.long sys_io_cancel	/* 245 */
-	.long sys_fadvise64
-	.long sys_exit_group
-	.long sys_lookup_dcookie
-	.long sys_epoll_create
-	.long sys_epoll_ctl	/* 250 */
-	.long sys_epoll_wait
-	.long sys_remap_file_pages
-	.long sys_set_tid_address
-	.long sys_timer_create
-	.long sys_timer_settime	/* 255 */
-	.long sys_timer_gettime
-	.long sys_timer_getoverrun
-	.long sys_timer_delete
-	.long sys_clock_settime
-	.long sys_clock_gettime	/* 260 */
-	.long sys_clock_getres
-	.long sys_clock_nanosleep
-	.long sys_statfs64
-	.long sys_fstatfs64
-	.long sys_tgkill	/* 265 */
-	.long sys_utimes
-	.long sys_fadvise64_64
-	.long sys_mbind
-	.long sys_get_mempolicy
-	.long sys_set_mempolicy	/* 270 */
-	.long sys_mq_open
-	.long sys_mq_unlink
-	.long sys_mq_timedsend
-	.long sys_mq_timedreceive
-	.long sys_mq_notify	/* 275 */
-	.long sys_mq_getsetattr
-	.long sys_waitid
-	.long sys_ni_syscall	/* for sys_vserver */
-	.long sys_add_key
-	.long sys_request_key	/* 280 */
-	.long sys_keyctl
-	.long sys_ioprio_set
-	.long sys_ioprio_get
-	.long sys_inotify_init
-	.long sys_inotify_add_watch	/* 285 */
-	.long sys_inotify_rm_watch
-	.long sys_migrate_pages
-	.long sys_openat
-	.long sys_mkdirat
-	.long sys_mknodat		/* 290 */
-	.long sys_fchownat
-	.long sys_futimesat
-	.long sys_fstatat64
-	.long sys_unlinkat
-	.long sys_renameat		/* 295 */
-	.long sys_linkat
-	.long sys_symlinkat
-	.long sys_readlinkat
-	.long sys_fchmodat
-	.long sys_faccessat		/* 300 */
-	.long sys_ni_syscall		/* Reserved for pselect6 */
-	.long sys_ni_syscall		/* Reserved for ppoll */
-	.long sys_unshare
-	.long sys_set_robust_list
-	.long sys_get_robust_list	/* 305 */
-	.long sys_splice
-	.long sys_sync_file_range
-	.long sys_tee
-	.long sys_vmsplice
-	.long sys_move_pages		/* 310 */
-	.long sys_sched_setaffinity
-	.long sys_sched_getaffinity
-	.long sys_kexec_load
-	.long sys_getcpu
-	.long sys_epoll_pwait		/* 315 */
-	.long sys_utimensat
-	.long sys_signalfd
-	.long sys_timerfd_create
-	.long sys_eventfd
-	.long sys_fallocate		/* 320 */
-	.long sys_timerfd_settime
-	.long sys_timerfd_gettime
-	.long sys_signalfd4
-	.long sys_eventfd2
-	.long sys_epoll_create1		/* 325 */
-	.long sys_dup3
-	.long sys_pipe2
-	.long sys_inotify_init1
-	.long sys_preadv
-	.long sys_pwritev		/* 330 */
-	.long sys_rt_tgsigqueueinfo
-	.long sys_perf_event_open
-	.long sys_get_thread_area
-	.long sys_set_thread_area
-	.long sys_atomic_cmpxchg_32	/* 335 */
-	.long sys_atomic_barrier
-	.long sys_fanotify_init
-	.long sys_fanotify_mark
-	.long sys_prlimit64
-
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/head.S linux-libre-2.6.39-gnu/arch/m68k/kernel/head.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -134,7 +134,7 @@
  *	Thanks to a small helping routine enabling the mmu got quite simple
  * and there is only one way left. mmu_engage makes a complete a new mapping
  * that only includes the absolute necessary to be able to jump to the final
- * postion and to restore the original mapping.
+ * position and to restore the original mapping.
  * As this code doesn't need a transparent translation register anymore this
  * means all registers are free to be used by machines that needs them for
  * other purposes.
@@ -969,7 +969,7 @@
 	is_not_040_or_060(1f)
 
 	/*
-	 * 040: Map the 16Meg range physical 0x0 upto logical 0x8000.0000
+	 * 040: Map the 16Meg range physical 0x0 up to logical 0x8000.0000
 	 */
 	mmu_map		#0x80000000,#0,#0x01000000,#_PAGE_NOCACHE_S
 	/*
@@ -982,7 +982,7 @@
 
 1:
 	/*
-	 * 030:	Map the 32Meg range physical 0x0 upto logical 0x8000.0000
+	 * 030:	Map the 32Meg range physical 0x0 up to logical 0x8000.0000
 	 */
 	mmu_map		#0x80000000,#0,#0x02000000,#_PAGE_NOCACHE030
 	mmu_map_tt	#1,#0x40000000,#0x20000000,#_PAGE_NOCACHE030
@@ -1074,7 +1074,7 @@
 	is_040(1f)
 
 	/*
-	 * 030: Map the 32Meg range physical 0x0 upto logical 0xf000.0000
+	 * 030: Map the 32Meg range physical 0x0 up to logical 0xf000.0000
 	 */
 	mmu_map	#0xf0000000,#0,#0x02000000,#_PAGE_NOCACHE030
 
@@ -1082,7 +1082,7 @@
 
 1:
 	/*
-	 * 040: Map the 16Meg range physical 0x0 upto logical 0xf000.0000
+	 * 040: Map the 16Meg range physical 0x0 up to logical 0xf000.0000
 	 */
 	mmu_map #0xf0000000,#0,#0x01000000,#_PAGE_NOCACHE_S
 
@@ -3078,7 +3078,7 @@
 	/*
 	 * If the loader gave us a board type then we can use that to
 	 * select an appropriate output routine; otherwise we just use
-	 * the Bug code.  If we haev to use the Bug that means the Bug
+	 * the Bug code.  If we have to use the Bug that means the Bug
 	 * workspace has to be valid, which means the Bug has to use
 	 * the SRAM, which is non-standard.
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/init_task.c linux-libre-2.6.39-gnu/arch/m68k/kernel/init_task.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/init_task.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/init_task.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ *  linux/arch/m68knommu/kernel/init_task.c
+ */
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/fs.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+__asm__(".align 4");
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
+
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by having a special
+ * "init_task" linker map entry..
+ */
+union thread_union init_thread_union __init_task_data =
+	{ INIT_THREAD_INFO(init_task) };
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/irq.c linux-libre-2.6.39-gnu/arch/m68k/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ * irq.c
+ *
+ * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/seq_file.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
+{
+	struct pt_regs *oldregs = set_irq_regs(regs);
+
+	irq_enter();
+	generic_handle_irq(irq);
+	irq_exit();
+
+	set_irq_regs(oldregs);
+}
+
+int show_interrupts(struct seq_file *p, void *v)
+{
+	struct irqaction *ap;
+	int irq = *((loff_t *) v);
+
+	if (irq == 0)
+		seq_puts(p, "           CPU0\n");
+
+	if (irq < NR_IRQS) {
+		struct irq_desc *desc = irq_to_desc(irq);
+
+		ap = desc->action;
+		if (ap) {
+			seq_printf(p, "%3d: ", irq);
+			seq_printf(p, "%10u ", kstat_irqs(irq));
+			seq_printf(p, "%14s  ", irq_desc_get_chip(desc)->name);
+
+			seq_printf(p, "%s", ap->name);
+			for (ap = ap->next; ap; ap = ap->next)
+				seq_printf(p, ", %s", ap->name);
+			seq_putc(p, '\n');
+		}
+	}
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/m68k_ksyms.c linux-libre-2.6.39-gnu/arch/m68k/kernel/m68k_ksyms.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/m68k_ksyms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/m68k_ksyms.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,16 +1,5 @@
-#include <linux/module.h>
-
-asmlinkage long long __ashldi3 (long long, int);
-asmlinkage long long __ashrdi3 (long long, int);
-asmlinkage long long __lshrdi3 (long long, int);
-asmlinkage long long __muldi3 (long long, long long);
-
-/* The following are special because they're not called
-   explicitly (the C compiler generates them).  Fortunately,
-   their interface isn't gonna change any time soon now, so
-   it's OK to leave it out of version control.  */
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(__muldi3);
-
+#ifdef CONFIG_MMU
+#include "m68k_ksyms_mm.c"
+#else
+#include "m68k_ksyms_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/m68k_ksyms_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/m68k_ksyms_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/m68k_ksyms_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/m68k_ksyms_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,16 @@
+#include <linux/module.h>
+
+asmlinkage long long __ashldi3 (long long, int);
+asmlinkage long long __ashrdi3 (long long, int);
+asmlinkage long long __lshrdi3 (long long, int);
+asmlinkage long long __muldi3 (long long, long long);
+
+/* The following are special because they're not called
+   explicitly (the C compiler generates them).  Fortunately,
+   their interface isn't gonna change any time soon now, so
+   it's OK to leave it out of version control.  */
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__muldi3);
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/m68k_ksyms_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/m68k_ksyms_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/m68k_ksyms_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/m68k_ksyms_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,78 @@
+#include <linux/module.h>
+#include <linux/linkage.h>
+#include <linux/sched.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/user.h>
+#include <linux/elfcore.h>
+#include <linux/in6.h>
+#include <linux/interrupt.h>
+
+#include <asm/setup.h>
+#include <asm/machdep.h>
+#include <asm/pgalloc.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/checksum.h>
+#include <asm/current.h>
+
+extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
+
+/* platform dependent support */
+
+EXPORT_SYMBOL(__ioremap);
+EXPORT_SYMBOL(iounmap);
+EXPORT_SYMBOL(dump_fpu);
+
+EXPORT_SYMBOL(ip_fast_csum);
+
+EXPORT_SYMBOL(kernel_thread);
+
+/* Networking helper routines. */
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+
+/* The following are special because they're not called
+   explicitly (the C compiler generates them).  Fortunately,
+   their interface isn't gonna change any time soon now, so
+   it's OK to leave it out of version control.  */
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memset);
+
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler...  (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __mulsi3(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+
+        /* gcc lib functions */
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__mulsi3);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+
+#ifdef CONFIG_COLDFIRE
+extern unsigned int *dma_device_address;
+extern unsigned long dma_base_addr, _ramend;
+EXPORT_SYMBOL(dma_base_addr);
+EXPORT_SYMBOL(dma_device_address);
+EXPORT_SYMBOL(_ramend);
+
+extern asmlinkage void trap(void);
+extern void	*_ramvec;
+EXPORT_SYMBOL(trap);
+EXPORT_SYMBOL(_ramvec);
+#endif /* CONFIG_COLDFIRE */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/Makefile linux-libre-2.6.39-gnu/arch/m68k/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,17 +1,5 @@
-#
-# Makefile for the linux kernel.
-#
-
-ifndef CONFIG_SUN3
-  extra-y := head.o
+ifdef CONFIG_MMU
+include arch/m68k/kernel/Makefile_mm
 else
-  extra-y := sun3-head.o
+include arch/m68k/kernel/Makefile_no
 endif
-extra-y	+= vmlinux.lds
-
-obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
-	   sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
-
-devres-y = ../../../kernel/irq/devres.o
-
-obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/Makefile_mm linux-libre-2.6.39-gnu/arch/m68k/kernel/Makefile_mm
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/Makefile_mm	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+#
+# Makefile for the linux kernel.
+#
+
+ifndef CONFIG_SUN3
+  extra-y := head.o
+else
+  extra-y := sun3-head.o
+endif
+extra-y	+= vmlinux.lds
+
+obj-y	:= entry.o process.o traps.o ints.o signal.o ptrace.o module.o \
+	   sys_m68k.o time.o setup.o m68k_ksyms.o devres.o
+
+devres-y = ../../../kernel/irq/devres.o
+
+obj-y$(CONFIG_MMU_SUN3) += dma.o	# no, it's not a typo
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/Makefile_no linux-libre-2.6.39-gnu/arch/m68k/kernel/Makefile_no
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/Makefile_no	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/Makefile_no	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+#
+# Makefile for arch/m68knommu/kernel.
+#
+
+extra-y := vmlinux.lds
+
+obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
+	 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
+
+obj-$(CONFIG_MODULES)	+= module.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/module.c linux-libre-2.6.39-gnu/arch/m68k/kernel/module.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/module.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,155 +1,5 @@
-/*
- * 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/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
+#ifdef CONFIG_MMU
+#include "module_mm.c"
 #else
-#define DEBUGP(fmt...)
+#include "module_no.c"
 #endif
-
-#ifdef CONFIG_MODULES
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* 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;
-}
-
-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_68K_32:
-			/* We add the value into the location given */
-			*location += sym->st_value;
-			break;
-		case R_68K_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)
-{
-	unsigned int i;
-	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate_add 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_68K_32:
-			/* We add the value into the location given */
-			*location = rel[i].r_addend + sym->st_value;
-			break;
-		case R_68K_PC32:
-			/* Add the value, subtract its postition */
-			*location = rel[i].r_addend + 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 module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *mod)
-{
-	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
-
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
-
-#endif /* CONFIG_MODULES */
-
-void module_fixup(struct module *mod, struct m68k_fixup_info *start,
-		  struct m68k_fixup_info *end)
-{
-	struct m68k_fixup_info *fixup;
-
-	for (fixup = start; fixup < end; fixup++) {
-		switch (fixup->type) {
-		case m68k_fixup_memoffset:
-			*(u32 *)fixup->addr = m68k_memoffset;
-			break;
-		case m68k_fixup_vnode_shift:
-			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
-			break;
-		}
-	}
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/module_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/module_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/module_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/module_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,155 @@
+/*
+ * 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/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+#ifdef CONFIG_MODULES
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc(size);
+}
+
+
+/* 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;
+}
+
+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_68K_32:
+			/* We add the value into the location given */
+			*location += sym->st_value;
+			break;
+		case R_68K_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)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate_add 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_68K_32:
+			/* We add the value into the location given */
+			*location = rel[i].r_addend + sym->st_value;
+			break;
+		case R_68K_PC32:
+			/* Add the value, subtract its postition */
+			*location = rel[i].r_addend + 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 module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *mod)
+{
+	module_fixup(mod, mod->arch.fixup_start, mod->arch.fixup_end);
+
+	return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
+
+#endif /* CONFIG_MODULES */
+
+void module_fixup(struct module *mod, struct m68k_fixup_info *start,
+		  struct m68k_fixup_info *end)
+{
+	struct m68k_fixup_info *fixup;
+
+	for (fixup = start; fixup < end; fixup++) {
+		switch (fixup->type) {
+		case m68k_fixup_memoffset:
+			*(u32 *)fixup->addr = m68k_memoffset;
+			break;
+		case m68k_fixup_vnode_shift:
+			*(u16 *)fixup->addr += m68k_virt_to_node_shift;
+			break;
+		}
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/module_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/module_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/module_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/module_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,126 @@
+#include <linux/moduleloader.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/kernel.h>
+
+#if 0
+#define DEBUGP printk
+#else
+#define DEBUGP(fmt...)
+#endif
+
+void *module_alloc(unsigned long size)
+{
+	if (size == 0)
+		return NULL;
+	return vmalloc(size);
+}
+
+
+/* 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;
+}
+
+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_68K_32:
+			/* We add the value into the location given */
+			*location += sym->st_value;
+			break;
+		case R_68K_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)
+{
+	unsigned int i;
+	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
+	Elf32_Sym *sym;
+	uint32_t *location;
+
+	DEBUGP("Applying relocate_add 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_68K_32:
+			/* We add the value into the location given */
+			*location = rel[i].r_addend + sym->st_value;
+			break;
+		case R_68K_PC32:
+			/* Add the value, subtract its postition */
+			*location = rel[i].r_addend + 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 module_finalize(const Elf_Ehdr *hdr,
+		    const Elf_Shdr *sechdrs,
+		    struct module *me)
+{
+	return 0;
+}
+
+void module_arch_cleanup(struct module *mod)
+{
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/process.c linux-libre-2.6.39-gnu/arch/m68k/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,354 +1,5 @@
-/*
- *  linux/arch/m68k/kernel/process.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  68060 fixes by Jesper Skov
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/reboot.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-
-/*
- * Initial task/thread structure. Make this a per-architecture thing,
- * because different architectures tend to have different
- * alignment requirements and potentially different initial
- * setup.
- */
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-union thread_union init_thread_union __init_task_data
-	__attribute__((aligned(THREAD_SIZE))) =
-		{ INIT_THREAD_INFO(init_task) };
-
-/* initial task structure */
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
-asmlinkage void ret_from_fork(void);
-
-
-/*
- * Return saved PC from a blocked thread
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
-	/* Check whether the thread is blocked in resume() */
-	if (in_sched_functions(sw->retpc))
-		return ((unsigned long *)sw->a6)[1];
-	else
-		return sw->retpc;
-}
-
-/*
- * The idle loop on an m68k..
- */
-static void default_idle(void)
-{
-	if (!need_resched())
-#if defined(MACH_ATARI_ONLY)
-		/* block out HSYNC on the atari (falcon) */
-		__asm__("stop #0x2200" : : : "cc");
+#ifdef CONFIG_MMU
+#include "process_mm.c"
 #else
-		__asm__("stop #0x2000" : : : "cc");
+#include "process_no.c"
 #endif
-}
-
-void (*idle)(void) = default_idle;
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle(void)
-{
-	/* endless idle loop with no priority at all */
-	while (1) {
-		while (!need_resched())
-			idle();
-		preempt_enable_no_resched();
-		schedule();
-		preempt_disable();
-	}
-}
-
-void machine_restart(char * __unused)
-{
-	if (mach_reset)
-		mach_reset();
-	for (;;);
-}
-
-void machine_halt(void)
-{
-	if (mach_halt)
-		mach_halt();
-	for (;;);
-}
-
-void machine_power_off(void)
-{
-	if (mach_power_off)
-		mach_power_off();
-	for (;;);
-}
-
-void (*pm_power_off)(void) = machine_power_off;
-EXPORT_SYMBOL(pm_power_off);
-
-void show_regs(struct pt_regs * regs)
-{
-	printk("\n");
-	printk("Format %02x  Vector: %04x  PC: %08lx  Status: %04x    %s\n",
-	       regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
-	printk("ORIG_D0: %08lx  D0: %08lx  A2: %08lx  A1: %08lx\n",
-	       regs->orig_d0, regs->d0, regs->a2, regs->a1);
-	printk("A0: %08lx  D5: %08lx  D4: %08lx\n",
-	       regs->a0, regs->d5, regs->d4);
-	printk("D3: %08lx  D2: %08lx  D1: %08lx\n",
-	       regs->d3, regs->d2, regs->d1);
-	if (!(regs->sr & PS_S))
-		printk("USP: %08lx\n", rdusp());
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	int pid;
-	mm_segment_t fs;
-
-	fs = get_fs();
-	set_fs (KERNEL_DS);
-
-	{
-	register long retval __asm__ ("d0");
-	register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
-
-	retval = __NR_clone;
-	__asm__ __volatile__
-	  ("clrl %%d2\n\t"
-	   "trap #0\n\t"		/* Linux/m68k system call */
-	   "tstl %0\n\t"		/* child or parent */
-	   "jne 1f\n\t"			/* parent - jump */
-	   "lea %%sp@(%c7),%6\n\t"	/* reload current */
-	   "movel %6@,%6\n\t"
-	   "movel %3,%%sp@-\n\t"	/* push argument */
-	   "jsr %4@\n\t"		/* call fn */
-	   "movel %0,%%d1\n\t"		/* pass exit value */
-	   "movel %2,%%d0\n\t"		/* exit */
-	   "trap #0\n"
-	   "1:"
-	   : "+d" (retval)
-	   : "i" (__NR_clone), "i" (__NR_exit),
-	     "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
-	     "i" (-THREAD_SIZE)
-	   : "d2");
-
-	pid = retval;
-	}
-
-	set_fs (fs);
-	return pid;
-}
-EXPORT_SYMBOL(kernel_thread);
-
-void flush_thread(void)
-{
-	unsigned long zero = 0;
-	set_fs(USER_DS);
-	current->thread.fs = __USER_DS;
-	if (!FPU_IS_EMU)
-		asm volatile (".chip 68k/68881\n\t"
-			      "frestore %0@\n\t"
-			      ".chip 68k" : : "a" (&zero));
-}
-
-/*
- * "m68k_fork()".. By the time we get here, the
- * non-volatile registers have also been saved on the
- * stack. We do some ugly pointer stuff here.. (see
- * also copy_thread)
- */
-
-asmlinkage int m68k_fork(struct pt_regs *regs)
-{
-	return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-asmlinkage int m68k_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
-		       NULL, NULL);
-}
-
-asmlinkage int m68k_clone(struct pt_regs *regs)
-{
-	unsigned long clone_flags;
-	unsigned long newsp;
-	int __user *parent_tidptr, *child_tidptr;
-
-	/* syscall2 puts clone_flags in d1 and usp in d2 */
-	clone_flags = regs->d1;
-	newsp = regs->d2;
-	parent_tidptr = (int __user *)regs->d3;
-	child_tidptr = (int __user *)regs->d4;
-	if (!newsp)
-		newsp = rdusp();
-	return do_fork(clone_flags, newsp, regs, 0,
-		       parent_tidptr, child_tidptr);
-}
-
-int copy_thread(unsigned long clone_flags, unsigned long usp,
-		 unsigned long unused,
-		 struct task_struct * p, struct pt_regs * regs)
-{
-	struct pt_regs * childregs;
-	struct switch_stack * childstack, *stack;
-	unsigned long *retp;
-
-	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-
-	*childregs = *regs;
-	childregs->d0 = 0;
-
-	retp = ((unsigned long *) regs);
-	stack = ((struct switch_stack *) retp) - 1;
-
-	childstack = ((struct switch_stack *) childregs) - 1;
-	*childstack = *stack;
-	childstack->retpc = (unsigned long)ret_from_fork;
-
-	p->thread.usp = usp;
-	p->thread.ksp = (unsigned long)childstack;
-
-	if (clone_flags & CLONE_SETTLS)
-		task_thread_info(p)->tp_value = regs->d5;
-
-	/*
-	 * Must save the current SFC/DFC value, NOT the value when
-	 * the parent was last descheduled - RGH  10-08-96
-	 */
-	p->thread.fs = get_fs().seg;
-
-	if (!FPU_IS_EMU) {
-		/* Copy the current fpu state */
-		asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
-
-		if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
-		  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
-				"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
-				: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
-				: "memory");
-		/* Restore the state in case the fpu was busy */
-		asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
-	}
-
-	return 0;
-}
-
-/* Fill in the fpu structure for a core dump.  */
-
-int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
-{
-	char fpustate[216];
-
-	if (FPU_IS_EMU) {
-		int i;
-
-		memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
-		memcpy(fpu->fpregs, current->thread.fp, 96);
-		/* Convert internal fpu reg representation
-		 * into long double format
-		 */
-		for (i = 0; i < 24; i += 3)
-			fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
-			                 ((fpu->fpregs[i] & 0x0000ffff) << 16);
-		return 1;
-	}
-
-	/* First dump the fpu context to avoid protocol violation.  */
-	asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
-	if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
-		return 0;
-
-	asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
-		:: "m" (fpu->fpcntl[0])
-		: "memory");
-	asm volatile ("fmovemx %/fp0-%/fp7,%0"
-		:: "m" (fpu->fpregs[0])
-		: "memory");
-	return 1;
-}
-EXPORT_SYMBOL(dump_fpu);
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char __user *name,
-			  const char __user *const __user *argv,
-			  const char __user *const __user *envp)
-{
-	int error;
-	char * filename;
-	struct pt_regs *regs = (struct pt_regs *) &name;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
-unsigned long get_wchan(struct task_struct *p)
-{
-	unsigned long fp, pc;
-	unsigned long stack_page;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
-		return 0;
-
-	stack_page = (unsigned long)task_stack_page(p);
-	fp = ((struct switch_stack *)p->thread.ksp)->a6;
-	do {
-		if (fp < stack_page+sizeof(struct thread_info) ||
-		    fp >= 8184+stack_page)
-			return 0;
-		pc = ((unsigned long *)fp)[1];
-		if (!in_sched_functions(pc))
-			return pc;
-		fp = *(unsigned long *) fp;
-	} while (count++ < 16);
-	return 0;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/process_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/process_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/process_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/process_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,354 @@
+/*
+ *  linux/arch/m68k/kernel/process.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  68060 fixes by Jesper Skov
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/reboot.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+
+/*
+ * Initial task/thread structure. Make this a per-architecture thing,
+ * because different architectures tend to have different
+ * alignment requirements and potentially different initial
+ * setup.
+ */
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+union thread_union init_thread_union __init_task_data
+	__attribute__((aligned(THREAD_SIZE))) =
+		{ INIT_THREAD_INFO(init_task) };
+
+/* initial task structure */
+struct task_struct init_task = INIT_TASK(init_task);
+
+EXPORT_SYMBOL(init_task);
+
+asmlinkage void ret_from_fork(void);
+
+
+/*
+ * Return saved PC from a blocked thread
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
+	/* Check whether the thread is blocked in resume() */
+	if (in_sched_functions(sw->retpc))
+		return ((unsigned long *)sw->a6)[1];
+	else
+		return sw->retpc;
+}
+
+/*
+ * The idle loop on an m68k..
+ */
+static void default_idle(void)
+{
+	if (!need_resched())
+#if defined(MACH_ATARI_ONLY)
+		/* block out HSYNC on the atari (falcon) */
+		__asm__("stop #0x2200" : : : "cc");
+#else
+		__asm__("stop #0x2000" : : : "cc");
+#endif
+}
+
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+	/* endless idle loop with no priority at all */
+	while (1) {
+		while (!need_resched())
+			idle();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+void machine_restart(char * __unused)
+{
+	if (mach_reset)
+		mach_reset();
+	for (;;);
+}
+
+void machine_halt(void)
+{
+	if (mach_halt)
+		mach_halt();
+	for (;;);
+}
+
+void machine_power_off(void)
+{
+	if (mach_power_off)
+		mach_power_off();
+	for (;;);
+}
+
+void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
+
+void show_regs(struct pt_regs * regs)
+{
+	printk("\n");
+	printk("Format %02x  Vector: %04x  PC: %08lx  Status: %04x    %s\n",
+	       regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
+	printk("ORIG_D0: %08lx  D0: %08lx  A2: %08lx  A1: %08lx\n",
+	       regs->orig_d0, regs->d0, regs->a2, regs->a1);
+	printk("A0: %08lx  D5: %08lx  D4: %08lx\n",
+	       regs->a0, regs->d5, regs->d4);
+	printk("D3: %08lx  D2: %08lx  D1: %08lx\n",
+	       regs->d3, regs->d2, regs->d1);
+	if (!(regs->sr & PS_S))
+		printk("USP: %08lx\n", rdusp());
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	int pid;
+	mm_segment_t fs;
+
+	fs = get_fs();
+	set_fs (KERNEL_DS);
+
+	{
+	register long retval __asm__ ("d0");
+	register long clone_arg __asm__ ("d1") = flags | CLONE_VM | CLONE_UNTRACED;
+
+	retval = __NR_clone;
+	__asm__ __volatile__
+	  ("clrl %%d2\n\t"
+	   "trap #0\n\t"		/* Linux/m68k system call */
+	   "tstl %0\n\t"		/* child or parent */
+	   "jne 1f\n\t"			/* parent - jump */
+	   "lea %%sp@(%c7),%6\n\t"	/* reload current */
+	   "movel %6@,%6\n\t"
+	   "movel %3,%%sp@-\n\t"	/* push argument */
+	   "jsr %4@\n\t"		/* call fn */
+	   "movel %0,%%d1\n\t"		/* pass exit value */
+	   "movel %2,%%d0\n\t"		/* exit */
+	   "trap #0\n"
+	   "1:"
+	   : "+d" (retval)
+	   : "i" (__NR_clone), "i" (__NR_exit),
+	     "r" (arg), "a" (fn), "d" (clone_arg), "r" (current),
+	     "i" (-THREAD_SIZE)
+	   : "d2");
+
+	pid = retval;
+	}
+
+	set_fs (fs);
+	return pid;
+}
+EXPORT_SYMBOL(kernel_thread);
+
+void flush_thread(void)
+{
+	unsigned long zero = 0;
+	set_fs(USER_DS);
+	current->thread.fs = __USER_DS;
+	if (!FPU_IS_EMU)
+		asm volatile (".chip 68k/68881\n\t"
+			      "frestore %0@\n\t"
+			      ".chip 68k" : : "a" (&zero));
+}
+
+/*
+ * "m68k_fork()".. By the time we get here, the
+ * non-volatile registers have also been saved on the
+ * stack. We do some ugly pointer stuff here.. (see
+ * also copy_thread)
+ */
+
+asmlinkage int m68k_fork(struct pt_regs *regs)
+{
+	return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+}
+
+asmlinkage int m68k_vfork(struct pt_regs *regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0,
+		       NULL, NULL);
+}
+
+asmlinkage int m68k_clone(struct pt_regs *regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+	int __user *parent_tidptr, *child_tidptr;
+
+	/* syscall2 puts clone_flags in d1 and usp in d2 */
+	clone_flags = regs->d1;
+	newsp = regs->d2;
+	parent_tidptr = (int __user *)regs->d3;
+	child_tidptr = (int __user *)regs->d4;
+	if (!newsp)
+		newsp = rdusp();
+	return do_fork(clone_flags, newsp, regs, 0,
+		       parent_tidptr, child_tidptr);
+}
+
+int copy_thread(unsigned long clone_flags, unsigned long usp,
+		 unsigned long unused,
+		 struct task_struct * p, struct pt_regs * regs)
+{
+	struct pt_regs * childregs;
+	struct switch_stack * childstack, *stack;
+	unsigned long *retp;
+
+	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
+
+	*childregs = *regs;
+	childregs->d0 = 0;
+
+	retp = ((unsigned long *) regs);
+	stack = ((struct switch_stack *) retp) - 1;
+
+	childstack = ((struct switch_stack *) childregs) - 1;
+	*childstack = *stack;
+	childstack->retpc = (unsigned long)ret_from_fork;
+
+	p->thread.usp = usp;
+	p->thread.ksp = (unsigned long)childstack;
+
+	if (clone_flags & CLONE_SETTLS)
+		task_thread_info(p)->tp_value = regs->d5;
+
+	/*
+	 * Must save the current SFC/DFC value, NOT the value when
+	 * the parent was last descheduled - RGH  10-08-96
+	 */
+	p->thread.fs = get_fs().seg;
+
+	if (!FPU_IS_EMU) {
+		/* Copy the current fpu state */
+		asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
+
+		if (!CPU_IS_060 ? p->thread.fpstate[0] : p->thread.fpstate[2])
+		  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
+				"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
+				: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
+				: "memory");
+		/* Restore the state in case the fpu was busy */
+		asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
+	}
+
+	return 0;
+}
+
+/* Fill in the fpu structure for a core dump.  */
+
+int dump_fpu (struct pt_regs *regs, struct user_m68kfp_struct *fpu)
+{
+	char fpustate[216];
+
+	if (FPU_IS_EMU) {
+		int i;
+
+		memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
+		memcpy(fpu->fpregs, current->thread.fp, 96);
+		/* Convert internal fpu reg representation
+		 * into long double format
+		 */
+		for (i = 0; i < 24; i += 3)
+			fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
+			                 ((fpu->fpregs[i] & 0x0000ffff) << 16);
+		return 1;
+	}
+
+	/* First dump the fpu context to avoid protocol violation.  */
+	asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
+	if (!CPU_IS_060 ? !fpustate[0] : !fpustate[2])
+		return 0;
+
+	asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
+		:: "m" (fpu->fpcntl[0])
+		: "memory");
+	asm volatile ("fmovemx %/fp0-%/fp7,%0"
+		:: "m" (fpu->fpregs[0])
+		: "memory");
+	return 1;
+}
+EXPORT_SYMBOL(dump_fpu);
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(const char __user *name,
+			  const char __user *const __user *argv,
+			  const char __user *const __user *envp)
+{
+	int error;
+	char * filename;
+	struct pt_regs *regs = (struct pt_regs *) &name;
+
+	filename = getname(name);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return error;
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+	return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, pc;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = (unsigned long)task_stack_page(p);
+	fp = ((struct switch_stack *)p->thread.ksp)->a6;
+	do {
+		if (fp < stack_page+sizeof(struct thread_info) ||
+		    fp >= 8184+stack_page)
+			return 0;
+		pc = ((unsigned long *)fp)[1];
+		if (!in_sched_functions(pc))
+			return pc;
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/process_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/process_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/process_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/process_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,404 @@
+/*
+ *  linux/arch/m68knommu/kernel/process.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  68060 fixes by Jesper Skov
+ *
+ *  uClinux changes
+ *  Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
+ */
+
+/*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
+#include <linux/fs.h>
+#include <linux/slab.h>
+
+#include <asm/uaccess.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/setup.h>
+#include <asm/pgtable.h>
+
+asmlinkage void ret_from_fork(void);
+
+/*
+ * The following aren't currently used.
+ */
+void (*pm_idle)(void);
+EXPORT_SYMBOL(pm_idle);
+
+void (*pm_power_off)(void);
+EXPORT_SYMBOL(pm_power_off);
+
+/*
+ * The idle loop on an m68knommu..
+ */
+static void default_idle(void)
+{
+	local_irq_disable();
+ 	while (!need_resched()) {
+		/* This stop will re-enable interrupts */
+ 		__asm__("stop #0x2000" : : : "cc");
+		local_irq_disable();
+	}
+	local_irq_enable();
+}
+
+void (*idle)(void) = default_idle;
+
+/*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+void cpu_idle(void)
+{
+	/* endless idle loop with no priority at all */
+	while (1) {
+		idle();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+void machine_restart(char * __unused)
+{
+	if (mach_reset)
+		mach_reset();
+	for (;;);
+}
+
+void machine_halt(void)
+{
+	if (mach_halt)
+		mach_halt();
+	for (;;);
+}
+
+void machine_power_off(void)
+{
+	if (mach_power_off)
+		mach_power_off();
+	for (;;);
+}
+
+void show_regs(struct pt_regs * regs)
+{
+	printk(KERN_NOTICE "\n");
+	printk(KERN_NOTICE "Format %02x  Vector: %04x  PC: %08lx  Status: %04x    %s\n",
+	       regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
+	printk(KERN_NOTICE "ORIG_D0: %08lx  D0: %08lx  A2: %08lx  A1: %08lx\n",
+	       regs->orig_d0, regs->d0, regs->a2, regs->a1);
+	printk(KERN_NOTICE "A0: %08lx  D5: %08lx  D4: %08lx\n",
+	       regs->a0, regs->d5, regs->d4);
+	printk(KERN_NOTICE "D3: %08lx  D2: %08lx  D1: %08lx\n",
+	       regs->d3, regs->d2, regs->d1);
+	if (!(regs->sr & PS_S))
+		printk(KERN_NOTICE "USP: %08lx\n", rdusp());
+}
+
+/*
+ * Create a kernel thread
+ */
+int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+{
+	int retval;
+	long clone_arg = flags | CLONE_VM;
+	mm_segment_t fs;
+
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	__asm__ __volatile__ (
+			"movel	%%sp, %%d2\n\t"
+			"movel	%5, %%d1\n\t"
+			"movel	%1, %%d0\n\t"
+			"trap	#0\n\t"
+			"cmpl	%%sp, %%d2\n\t"
+			"jeq	1f\n\t"
+			"movel	%3, %%sp@-\n\t"
+			"jsr	%4@\n\t"
+			"movel	%2, %%d0\n\t"
+			"trap	#0\n"
+			"1:\n\t"
+			"movel	%%d0, %0\n"
+		: "=d" (retval)
+		: "i" (__NR_clone),
+		  "i" (__NR_exit),
+		  "a" (arg),
+		  "a" (fn),
+		  "a" (clone_arg)
+		: "cc", "%d0", "%d1", "%d2");
+
+	set_fs(fs);
+	return retval;
+}
+
+void flush_thread(void)
+{
+#ifdef CONFIG_FPU
+	unsigned long zero = 0;
+#endif
+	set_fs(USER_DS);
+	current->thread.fs = __USER_DS;
+#ifdef CONFIG_FPU
+	if (!FPU_IS_EMU)
+		asm volatile (".chip 68k/68881\n\t"
+			      "frestore %0@\n\t"
+			      ".chip 68k" : : "a" (&zero));
+#endif
+}
+
+/*
+ * "m68k_fork()".. By the time we get here, the
+ * non-volatile registers have also been saved on the
+ * stack. We do some ugly pointer stuff here.. (see
+ * also copy_thread)
+ */
+
+asmlinkage int m68k_fork(struct pt_regs *regs)
+{
+	/* fork almost works, enough to trick you into looking elsewhere :-( */
+	return(-EINVAL);
+}
+
+asmlinkage int m68k_vfork(struct pt_regs *regs)
+{
+	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
+}
+
+asmlinkage int m68k_clone(struct pt_regs *regs)
+{
+	unsigned long clone_flags;
+	unsigned long newsp;
+
+	/* syscall2 puts clone_flags in d1 and usp in d2 */
+	clone_flags = regs->d1;
+	newsp = regs->d2;
+	if (!newsp)
+		newsp = rdusp();
+        return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
+}
+
+int copy_thread(unsigned long clone_flags,
+		unsigned long usp, unsigned long topstk,
+		struct task_struct * p, struct pt_regs * regs)
+{
+	struct pt_regs * childregs;
+	struct switch_stack * childstack, *stack;
+	unsigned long *retp;
+
+	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
+
+	*childregs = *regs;
+	childregs->d0 = 0;
+
+	retp = ((unsigned long *) regs);
+	stack = ((struct switch_stack *) retp) - 1;
+
+	childstack = ((struct switch_stack *) childregs) - 1;
+	*childstack = *stack;
+	childstack->retpc = (unsigned long)ret_from_fork;
+
+	p->thread.usp = usp;
+	p->thread.ksp = (unsigned long)childstack;
+
+	if (clone_flags & CLONE_SETTLS)
+		task_thread_info(p)->tp_value = regs->d5;
+
+	/*
+	 * Must save the current SFC/DFC value, NOT the value when
+	 * the parent was last descheduled - RGH  10-08-96
+	 */
+	p->thread.fs = get_fs().seg;
+
+#ifdef CONFIG_FPU
+	if (!FPU_IS_EMU) {
+		/* Copy the current fpu state */
+		asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
+
+		if (p->thread.fpstate[0])
+		  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
+				"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
+				: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
+				: "memory");
+		/* Restore the state in case the fpu was busy */
+		asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
+	}
+#endif
+
+	return 0;
+}
+
+/* Fill in the fpu structure for a core dump.  */
+
+int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu)
+{
+#ifdef CONFIG_FPU
+	char fpustate[216];
+
+	if (FPU_IS_EMU) {
+		int i;
+
+		memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
+		memcpy(fpu->fpregs, current->thread.fp, 96);
+		/* Convert internal fpu reg representation
+		 * into long double format
+		 */
+		for (i = 0; i < 24; i += 3)
+			fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
+			                 ((fpu->fpregs[i] & 0x0000ffff) << 16);
+		return 1;
+	}
+
+	/* First dump the fpu context to avoid protocol violation.  */
+	asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
+	if (!fpustate[0])
+		return 0;
+
+	asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
+		:: "m" (fpu->fpcntl[0])
+		: "memory");
+	asm volatile ("fmovemx %/fp0-%/fp7,%0"
+		:: "m" (fpu->fpregs[0])
+		: "memory");
+#endif
+	return 1;
+}
+
+/*
+ *	Generic dumping code. Used for panic and debug.
+ */
+void dump(struct pt_regs *fp)
+{
+	unsigned long	*sp;
+	unsigned char	*tp;
+	int		i;
+
+	printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
+	printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
+
+	if (current->mm) {
+		printk(KERN_EMERG "TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
+			(int) current->mm->start_code,
+			(int) current->mm->end_code,
+			(int) current->mm->start_data,
+			(int) current->mm->end_data,
+			(int) current->mm->end_data,
+			(int) current->mm->brk);
+		printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
+			(int) current->mm->start_stack,
+			(int)(((unsigned long) current) + THREAD_SIZE));
+	}
+
+	printk(KERN_EMERG "PC: %08lx\n", fp->pc);
+	printk(KERN_EMERG "SR: %08lx    SP: %08lx\n", (long) fp->sr, (long) fp);
+	printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
+		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 "\nUSP: %08x   TRAPFRAME: %p\n",
+		(unsigned int) rdusp(), fp);
+
+	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(KERN_EMERG "%p: ", tp + i);
+		printk("%08x ", (int) *sp++);
+	}
+	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(KERN_EMERG "%p: ", tp + i);
+		printk("%08x ", (int) *sp++);
+	}
+	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(KERN_EMERG "%p: ", tp + i);
+		printk("%08x ", (int) *sp++);
+	}
+	printk(KERN_EMERG "\n");
+}
+
+/*
+ * sys_execve() executes a new program.
+ */
+asmlinkage int sys_execve(const char *name,
+			  const char *const *argv,
+			  const char *const *envp)
+{
+	int error;
+	char * filename;
+	struct pt_regs *regs = (struct pt_regs *) &name;
+
+	filename = getname(name);
+	error = PTR_ERR(filename);
+	if (IS_ERR(filename))
+		return error;
+	error = do_execve(filename, argv, envp, regs);
+	putname(filename);
+	return error;
+}
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	unsigned long fp, pc;
+	unsigned long stack_page;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	stack_page = (unsigned long)p;
+	fp = ((struct switch_stack *)p->thread.ksp)->a6;
+	do {
+		if (fp < stack_page+sizeof(struct thread_info) ||
+		    fp >= THREAD_SIZE-8+stack_page)
+			return 0;
+		pc = ((unsigned long *)fp)[1];
+		if (!in_sched_functions(pc))
+			return pc;
+		fp = *(unsigned long *) fp;
+	} while (count++ < 16);
+	return 0;
+}
+
+/*
+ * Return saved PC of a blocked thread.
+ */
+unsigned long thread_saved_pc(struct task_struct *tsk)
+{
+	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
+
+	/* Check whether the thread is blocked in resume() */
+	if (in_sched_functions(sw->retpc))
+		return ((unsigned long *)sw->a6)[1];
+	else
+		return sw->retpc;
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/m68k/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,277 +1,5 @@
-/*
- *  linux/arch/m68k/kernel/ptrace.c
- *
- *  Copyright (C) 1994 by Hamish Macdonald
- *  Taken from linux/kernel/ptrace.c and modified for M680x0.
- *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by 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/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/signal.h>
-
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/processor.h>
-
-/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
-
-/* determines which bits in the SR the user has access to. */
-/* 1 = access 0 = no access */
-#define SR_MASK 0x001f
-
-/* sets the trace bits. */
-#define TRACE_BITS 0xC000
-#define T1_BIT 0x8000
-#define T0_BIT 0x4000
-
-/* Find the stack offset for a register, relative to thread.esp0. */
-#define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
-#define SW_REG(reg)	((long)&((struct switch_stack *)0)->reg \
-			 - sizeof(struct switch_stack))
-/* Mapping from PT_xxx to the stack offset at which the register is
-   saved.  Notice that usp has no stack-slot and needs to be treated
-   specially (see get_reg/put_reg below). */
-static const int regoff[] = {
-	[0]	= PT_REG(d1),
-	[1]	= PT_REG(d2),
-	[2]	= PT_REG(d3),
-	[3]	= PT_REG(d4),
-	[4]	= PT_REG(d5),
-	[5]	= SW_REG(d6),
-	[6]	= SW_REG(d7),
-	[7]	= PT_REG(a0),
-	[8]	= PT_REG(a1),
-	[9]	= PT_REG(a2),
-	[10]	= SW_REG(a3),
-	[11]	= SW_REG(a4),
-	[12]	= SW_REG(a5),
-	[13]	= SW_REG(a6),
-	[14]	= PT_REG(d0),
-	[15]	= -1,
-	[16]	= PT_REG(orig_d0),
-	[17]	= PT_REG(sr),
-	[18]	= PT_REG(pc),
-};
-
-/*
- * Get contents of register REGNO in task TASK.
- */
-static inline long get_reg(struct task_struct *task, int regno)
-{
-	unsigned long *addr;
-
-	if (regno == PT_USP)
-		addr = &task->thread.usp;
-	else if (regno < ARRAY_SIZE(regoff))
-		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
-	else
-		return 0;
-	/* Need to take stkadj into account. */
-	if (regno == PT_SR || regno == PT_PC) {
-		long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
-		addr = (unsigned long *) ((unsigned long)addr + stkadj);
-		/* The sr is actually a 16 bit register.  */
-		if (regno == PT_SR)
-			return *(unsigned short *)addr;
-	}
-	return *addr;
-}
-
-/*
- * Write contents of register REGNO in task TASK.
- */
-static inline int put_reg(struct task_struct *task, int regno,
-			  unsigned long data)
-{
-	unsigned long *addr;
-
-	if (regno == PT_USP)
-		addr = &task->thread.usp;
-	else if (regno < ARRAY_SIZE(regoff))
-		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
-	else
-		return -1;
-	/* Need to take stkadj into account. */
-	if (regno == PT_SR || regno == PT_PC) {
-		long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
-		addr = (unsigned long *) ((unsigned long)addr + stkadj);
-		/* The sr is actually a 16 bit register.  */
-		if (regno == PT_SR) {
-			*(unsigned short *)addr = data;
-			return 0;
-		}
-	}
-	*addr = data;
-	return 0;
-}
-
-/*
- * Make sure the single step bit is not set.
- */
-static inline void singlestep_disable(struct task_struct *child)
-{
-	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
-	put_reg(child, PT_SR, tmp);
-	clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
-}
-
-/*
- * Called by kernel/ptrace.c when detaching..
- */
-void ptrace_disable(struct task_struct *child)
-{
-	singlestep_disable(child);
-}
-
-void user_enable_single_step(struct task_struct *child)
-{
-	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
-	put_reg(child, PT_SR, tmp | T1_BIT);
-	set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
-}
-
-void user_enable_block_step(struct task_struct *child)
-{
-	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
-	put_reg(child, PT_SR, tmp | T0_BIT);
-}
-
-void user_disable_single_step(struct task_struct *child)
-{
-	singlestep_disable(child);
-}
-
-long arch_ptrace(struct task_struct *child, long request,
-		 unsigned long addr, unsigned long data)
-{
-	unsigned long tmp;
-	int i, ret = 0;
-	int regno = addr >> 2; /* temporary hack. */
-	unsigned long __user *datap = (unsigned long __user *) data;
-
-	switch (request) {
-	/* read the word at location addr in the USER area. */
-	case PTRACE_PEEKUSR:
-		if (addr & 3)
-			goto out_eio;
-
-		if (regno >= 0 && regno < 19) {
-			tmp = get_reg(child, regno);
-		} else if (regno >= 21 && regno < 49) {
-			tmp = child->thread.fp[regno - 21];
-			/* Convert internal fpu reg representation
-			 * into long double format
-			 */
-			if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
-				tmp = ((tmp & 0xffff0000) << 15) |
-				      ((tmp & 0x0000ffff) << 16);
-		} else
-			goto out_eio;
-		ret = put_user(tmp, datap);
-		break;
-
-	case PTRACE_POKEUSR:
-	/* write the word at location addr in the USER area */
-		if (addr & 3)
-			goto out_eio;
-
-		if (regno == PT_SR) {
-			data &= SR_MASK;
-			data |= get_reg(child, PT_SR) & ~SR_MASK;
-		}
-		if (regno >= 0 && regno < 19) {
-			if (put_reg(child, regno, data))
-				goto out_eio;
-		} else if (regno >= 21 && regno < 48) {
-			/* Convert long double format
-			 * into internal fpu reg representation
-			 */
-			if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
-				data <<= 15;
-				data = (data & 0xffff0000) |
-				       ((data & 0x0000ffff) >> 1);
-			}
-			child->thread.fp[regno - 21] = data;
-		} else
-			goto out_eio;
-		break;
-
-	case PTRACE_GETREGS:	/* Get all gp regs from the child. */
-		for (i = 0; i < 19; i++) {
-			tmp = get_reg(child, i);
-			ret = put_user(tmp, datap);
-			if (ret)
-				break;
-			datap++;
-		}
-		break;
-
-	case PTRACE_SETREGS:	/* Set all gp regs in the child. */
-		for (i = 0; i < 19; i++) {
-			ret = get_user(tmp, datap);
-			if (ret)
-				break;
-			if (i == PT_SR) {
-				tmp &= SR_MASK;
-				tmp |= get_reg(child, PT_SR) & ~SR_MASK;
-			}
-			put_reg(child, i, tmp);
-			datap++;
-		}
-		break;
-
-	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
-		if (copy_to_user(datap, &child->thread.fp,
-				 sizeof(struct user_m68kfp_struct)))
-			ret = -EFAULT;
-		break;
-
-	case PTRACE_SETFPREGS:	/* Set the child FPU state. */
-		if (copy_from_user(&child->thread.fp, datap,
-				   sizeof(struct user_m68kfp_struct)))
-			ret = -EFAULT;
-		break;
-
-	case PTRACE_GET_THREAD_AREA:
-		ret = put_user(task_thread_info(child)->tp_value, datap);
-		break;
-
-	default:
-		ret = ptrace_request(child, request, addr, data);
-		break;
-	}
-
-	return ret;
-out_eio:
-	return -EIO;
-}
-
-asmlinkage void syscall_trace(void)
-{
-	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
-				 ? 0x80 : 0));
-	/*
-	 * 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;
-	}
-}
+#ifdef CONFIG_MMU
+#include "ptrace_mm.c"
+#else
+#include "ptrace_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/ptrace_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/ptrace_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/ptrace_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/ptrace_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,277 @@
+/*
+ *  linux/arch/m68k/kernel/ptrace.c
+ *
+ *  Copyright (C) 1994 by Hamish Macdonald
+ *  Taken from linux/kernel/ptrace.c and modified for M680x0.
+ *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by 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/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/signal.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which bits in the SR the user has access to. */
+/* 1 = access 0 = no access */
+#define SR_MASK 0x001f
+
+/* sets the trace bits. */
+#define TRACE_BITS 0xC000
+#define T1_BIT 0x8000
+#define T0_BIT 0x4000
+
+/* Find the stack offset for a register, relative to thread.esp0. */
+#define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
+#define SW_REG(reg)	((long)&((struct switch_stack *)0)->reg \
+			 - sizeof(struct switch_stack))
+/* Mapping from PT_xxx to the stack offset at which the register is
+   saved.  Notice that usp has no stack-slot and needs to be treated
+   specially (see get_reg/put_reg below). */
+static const int regoff[] = {
+	[0]	= PT_REG(d1),
+	[1]	= PT_REG(d2),
+	[2]	= PT_REG(d3),
+	[3]	= PT_REG(d4),
+	[4]	= PT_REG(d5),
+	[5]	= SW_REG(d6),
+	[6]	= SW_REG(d7),
+	[7]	= PT_REG(a0),
+	[8]	= PT_REG(a1),
+	[9]	= PT_REG(a2),
+	[10]	= SW_REG(a3),
+	[11]	= SW_REG(a4),
+	[12]	= SW_REG(a5),
+	[13]	= SW_REG(a6),
+	[14]	= PT_REG(d0),
+	[15]	= -1,
+	[16]	= PT_REG(orig_d0),
+	[17]	= PT_REG(sr),
+	[18]	= PT_REG(pc),
+};
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+	unsigned long *addr;
+
+	if (regno == PT_USP)
+		addr = &task->thread.usp;
+	else if (regno < ARRAY_SIZE(regoff))
+		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
+	else
+		return 0;
+	/* Need to take stkadj into account. */
+	if (regno == PT_SR || regno == PT_PC) {
+		long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
+		addr = (unsigned long *) ((unsigned long)addr + stkadj);
+		/* The sr is actually a 16 bit register.  */
+		if (regno == PT_SR)
+			return *(unsigned short *)addr;
+	}
+	return *addr;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task, int regno,
+			  unsigned long data)
+{
+	unsigned long *addr;
+
+	if (regno == PT_USP)
+		addr = &task->thread.usp;
+	else if (regno < ARRAY_SIZE(regoff))
+		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
+	else
+		return -1;
+	/* Need to take stkadj into account. */
+	if (regno == PT_SR || regno == PT_PC) {
+		long stkadj = *(long *)(task->thread.esp0 + PT_REG(stkadj));
+		addr = (unsigned long *) ((unsigned long)addr + stkadj);
+		/* The sr is actually a 16 bit register.  */
+		if (regno == PT_SR) {
+			*(unsigned short *)addr = data;
+			return 0;
+		}
+	}
+	*addr = data;
+	return 0;
+}
+
+/*
+ * Make sure the single step bit is not set.
+ */
+static inline void singlestep_disable(struct task_struct *child)
+{
+	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
+	put_reg(child, PT_SR, tmp);
+	clear_tsk_thread_flag(child, TIF_DELAYED_TRACE);
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	singlestep_disable(child);
+}
+
+void user_enable_single_step(struct task_struct *child)
+{
+	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
+	put_reg(child, PT_SR, tmp | T1_BIT);
+	set_tsk_thread_flag(child, TIF_DELAYED_TRACE);
+}
+
+void user_enable_block_step(struct task_struct *child)
+{
+	unsigned long tmp = get_reg(child, PT_SR) & ~TRACE_BITS;
+	put_reg(child, PT_SR, tmp | T0_BIT);
+}
+
+void user_disable_single_step(struct task_struct *child)
+{
+	singlestep_disable(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	unsigned long tmp;
+	int i, ret = 0;
+	int regno = addr >> 2; /* temporary hack. */
+	unsigned long __user *datap = (unsigned long __user *) data;
+
+	switch (request) {
+	/* read the word at location addr in the USER area. */
+	case PTRACE_PEEKUSR:
+		if (addr & 3)
+			goto out_eio;
+
+		if (regno >= 0 && regno < 19) {
+			tmp = get_reg(child, regno);
+		} else if (regno >= 21 && regno < 49) {
+			tmp = child->thread.fp[regno - 21];
+			/* Convert internal fpu reg representation
+			 * into long double format
+			 */
+			if (FPU_IS_EMU && (regno < 45) && !(regno % 3))
+				tmp = ((tmp & 0xffff0000) << 15) |
+				      ((tmp & 0x0000ffff) << 16);
+		} else
+			goto out_eio;
+		ret = put_user(tmp, datap);
+		break;
+
+	case PTRACE_POKEUSR:
+	/* write the word at location addr in the USER area */
+		if (addr & 3)
+			goto out_eio;
+
+		if (regno == PT_SR) {
+			data &= SR_MASK;
+			data |= get_reg(child, PT_SR) & ~SR_MASK;
+		}
+		if (regno >= 0 && regno < 19) {
+			if (put_reg(child, regno, data))
+				goto out_eio;
+		} else if (regno >= 21 && regno < 48) {
+			/* Convert long double format
+			 * into internal fpu reg representation
+			 */
+			if (FPU_IS_EMU && (regno < 45) && !(regno % 3)) {
+				data <<= 15;
+				data = (data & 0xffff0000) |
+				       ((data & 0x0000ffff) >> 1);
+			}
+			child->thread.fp[regno - 21] = data;
+		} else
+			goto out_eio;
+		break;
+
+	case PTRACE_GETREGS:	/* Get all gp regs from the child. */
+		for (i = 0; i < 19; i++) {
+			tmp = get_reg(child, i);
+			ret = put_user(tmp, datap);
+			if (ret)
+				break;
+			datap++;
+		}
+		break;
+
+	case PTRACE_SETREGS:	/* Set all gp regs in the child. */
+		for (i = 0; i < 19; i++) {
+			ret = get_user(tmp, datap);
+			if (ret)
+				break;
+			if (i == PT_SR) {
+				tmp &= SR_MASK;
+				tmp |= get_reg(child, PT_SR) & ~SR_MASK;
+			}
+			put_reg(child, i, tmp);
+			datap++;
+		}
+		break;
+
+	case PTRACE_GETFPREGS:	/* Get the child FPU state. */
+		if (copy_to_user(datap, &child->thread.fp,
+				 sizeof(struct user_m68kfp_struct)))
+			ret = -EFAULT;
+		break;
+
+	case PTRACE_SETFPREGS:	/* Set the child FPU state. */
+		if (copy_from_user(&child->thread.fp, datap,
+				   sizeof(struct user_m68kfp_struct)))
+			ret = -EFAULT;
+		break;
+
+	case PTRACE_GET_THREAD_AREA:
+		ret = put_user(task_thread_info(child)->tp_value, datap);
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+out_eio:
+	return -EIO;
+}
+
+asmlinkage void syscall_trace(void)
+{
+	ptrace_notify(SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD)
+				 ? 0x80 : 0));
+	/*
+	 * 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;
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/ptrace_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/ptrace_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/ptrace_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/ptrace_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,255 @@
+/*
+ *  linux/arch/m68knommu/kernel/ptrace.c
+ *
+ *  Copyright (C) 1994 by Hamish Macdonald
+ *  Taken from linux/kernel/ptrace.c and modified for M680x0.
+ *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by 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/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/ptrace.h>
+#include <linux/user.h>
+#include <linux/signal.h>
+#include <linux/tracehook.h>
+
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/processor.h>
+
+/*
+ * does not yet catch signals sent when the child dies.
+ * in exit.c or in signal.c.
+ */
+
+/* determines which bits in the SR the user has access to. */
+/* 1 = access 0 = no access */
+#define SR_MASK 0x001f
+
+/* sets the trace bits. */
+#define TRACE_BITS 0x8000
+
+/* Find the stack offset for a register, relative to thread.esp0. */
+#define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
+#define SW_REG(reg)	((long)&((struct switch_stack *)0)->reg \
+			 - sizeof(struct switch_stack))
+/* Mapping from PT_xxx to the stack offset at which the register is
+   saved.  Notice that usp has no stack-slot and needs to be treated
+   specially (see get_reg/put_reg below). */
+static int regoff[] = {
+	PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
+	PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
+	PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
+	SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
+	PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
+};
+
+/*
+ * Get contents of register REGNO in task TASK.
+ */
+static inline long get_reg(struct task_struct *task, int regno)
+{
+	unsigned long *addr;
+
+	if (regno == PT_USP)
+		addr = &task->thread.usp;
+	else if (regno < ARRAY_SIZE(regoff))
+		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
+	else
+		return 0;
+	return *addr;
+}
+
+/*
+ * Write contents of register REGNO in task TASK.
+ */
+static inline int put_reg(struct task_struct *task, int regno,
+			  unsigned long data)
+{
+	unsigned long *addr;
+
+	if (regno == PT_USP)
+		addr = &task->thread.usp;
+	else if (regno < ARRAY_SIZE(regoff))
+		addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
+	else
+		return -1;
+	*addr = data;
+	return 0;
+}
+
+void user_enable_single_step(struct task_struct *task)
+{
+	unsigned long srflags;
+	srflags = get_reg(task, PT_SR) | (TRACE_BITS << 16);
+	put_reg(task, PT_SR, srflags);
+}
+
+void user_disable_single_step(struct task_struct *task)
+{
+	unsigned long srflags;
+	srflags = get_reg(task, PT_SR) & ~(TRACE_BITS << 16);
+	put_reg(task, PT_SR, srflags);
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ *
+ * Make sure the single step bit is not set.
+ */
+void ptrace_disable(struct task_struct *child)
+{
+	/* make sure the single step bit is not set. */
+	user_disable_single_step(child);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	int ret;
+	int regno = addr >> 2;
+	unsigned long __user *datap = (unsigned long __user *) data;
+
+	switch (request) {
+		/* read the word at location addr in the USER area. */
+		case PTRACE_PEEKUSR: {
+			unsigned long tmp;
+			
+			ret = -EIO;
+			if ((addr & 3) || addr > sizeof(struct user) - 3)
+				break;
+			
+			tmp = 0;  /* Default return condition */
+			ret = -EIO;
+			if (regno < 19) {
+				tmp = get_reg(child, regno);
+				if (regno == PT_SR)
+					tmp >>= 16;
+			} else if (regno >= 21 && regno < 49) {
+				tmp = child->thread.fp[regno - 21];
+			} else if (regno == 49) {
+				tmp = child->mm->start_code;
+			} else if (regno == 50) {
+				tmp = child->mm->start_data;
+			} else if (regno == 51) {
+				tmp = child->mm->end_code;
+			} else
+				break;
+			ret = put_user(tmp, datap);
+			break;
+		}
+
+		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
+			ret = -EIO;
+			if ((addr & 3) || addr > sizeof(struct user) - 3)
+				break;
+
+			if (regno == PT_SR) {
+				data &= SR_MASK;
+				data <<= 16;
+				data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
+			}
+			if (regno < 19) {
+				if (put_reg(child, regno, data))
+					break;
+				ret = 0;
+				break;
+			}
+			if (regno >= 21 && regno < 48)
+			{
+				child->thread.fp[regno - 21] = data;
+				ret = 0;
+			}
+			break;
+
+		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
+		  	int i;
+			unsigned long tmp;
+			for (i = 0; i < 19; i++) {
+			    tmp = get_reg(child, i);
+			    if (i == PT_SR)
+				tmp >>= 16;
+			    if (put_user(tmp, datap)) {
+				ret = -EFAULT;
+				break;
+			    }
+			    datap++;
+			}
+			ret = 0;
+			break;
+		}
+
+		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
+			int i;
+			unsigned long tmp;
+			for (i = 0; i < 19; i++) {
+			    if (get_user(tmp, datap)) {
+				ret = -EFAULT;
+				break;
+			    }
+			    if (i == PT_SR) {
+				tmp &= SR_MASK;
+				tmp <<= 16;
+				tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
+			    }
+			    put_reg(child, i, tmp);
+			    datap++;
+			}
+			ret = 0;
+			break;
+		}
+
+#ifdef PTRACE_GETFPREGS
+		case PTRACE_GETFPREGS: { /* Get the child FPU state. */
+			ret = 0;
+			if (copy_to_user(datap, &child->thread.fp,
+					 sizeof(struct user_m68kfp_struct)))
+				ret = -EFAULT;
+			break;
+		}
+#endif
+
+#ifdef PTRACE_SETFPREGS
+		case PTRACE_SETFPREGS: { /* Set the child FPU state. */
+			ret = 0;
+			if (copy_from_user(&child->thread.fp, datap,
+					   sizeof(struct user_m68kfp_struct)))
+				ret = -EFAULT;
+			break;
+		}
+#endif
+
+	case PTRACE_GET_THREAD_AREA:
+		ret = put_user(task_thread_info(child)->tp_value, datap);
+		break;
+
+		default:
+			ret = ptrace_request(child, request, addr, data);
+			break;
+	}
+	return ret;
+}
+
+asmlinkage int syscall_trace_enter(void)
+{
+	int ret = 0;
+
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		ret = tracehook_report_syscall_entry(task_pt_regs(current));
+	return ret;
+}
+
+asmlinkage void syscall_trace_leave(void)
+{
+	if (test_thread_flag(TIF_SYSCALL_TRACE))
+		tracehook_report_syscall_exit(task_pt_regs(current), 0);
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/setup.c linux-libre-2.6.39-gnu/arch/m68k/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,528 +1,5 @@
-/*
- *  linux/arch/m68k/kernel/setup.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- */
-
-/*
- * This file handles the architecture-dependent parts of system setup
- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fs.h>
-#include <linux/console.h>
-#include <linux/genhd.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-#include <linux/module.h>
-#include <linux/initrd.h>
-
-#include <asm/bootinfo.h>
-#include <asm/sections.h>
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-#ifdef CONFIG_AMIGA
-#include <asm/amigahw.h>
-#endif
-#ifdef CONFIG_ATARI
-#include <asm/atarihw.h>
-#include <asm/atari_stram.h>
-#endif
-#ifdef CONFIG_SUN3X
-#include <asm/dvma.h>
-#endif
-
-#if !FPSTATESIZE || !NR_IRQS
-#warning No CPU/platform type selected, your kernel will not work!
-#warning Are you building an allnoconfig kernel?
-#endif
-
-unsigned long m68k_machtype;
-EXPORT_SYMBOL(m68k_machtype);
-unsigned long m68k_cputype;
-EXPORT_SYMBOL(m68k_cputype);
-unsigned long m68k_fputype;
-unsigned long m68k_mmutype;
-EXPORT_SYMBOL(m68k_mmutype);
-#ifdef CONFIG_VME
-unsigned long vme_brdtype;
-EXPORT_SYMBOL(vme_brdtype);
-#endif
-
-int m68k_is040or060;
-EXPORT_SYMBOL(m68k_is040or060);
-
-extern unsigned long availmem;
-
-int m68k_num_memory;
-EXPORT_SYMBOL(m68k_num_memory);
-int m68k_realnum_memory;
-EXPORT_SYMBOL(m68k_realnum_memory);
-unsigned long m68k_memoffset;
-struct mem_info m68k_memory[NUM_MEMINFO];
-EXPORT_SYMBOL(m68k_memory);
-
-struct mem_info m68k_ramdisk;
-
-static char m68k_command_line[CL_SIZE];
-
-void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
-/* machine dependent irq functions */
-void (*mach_init_IRQ) (void) __initdata = NULL;
-void (*mach_get_model) (char *model);
-void (*mach_get_hardware_list) (struct seq_file *m);
-/* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
-int (*mach_hwclk) (int, struct rtc_time*);
-EXPORT_SYMBOL(mach_hwclk);
-int (*mach_set_clock_mmss) (unsigned long);
-unsigned int (*mach_get_ss)(void);
-int (*mach_get_rtc_pll)(struct rtc_pll_info *);
-int (*mach_set_rtc_pll)(struct rtc_pll_info *);
-EXPORT_SYMBOL(mach_get_ss);
-EXPORT_SYMBOL(mach_get_rtc_pll);
-EXPORT_SYMBOL(mach_set_rtc_pll);
-void (*mach_reset)( void );
-void (*mach_halt)( void );
-void (*mach_power_off)( void );
-long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
-#ifdef CONFIG_HEARTBEAT
-void (*mach_heartbeat) (int);
-EXPORT_SYMBOL(mach_heartbeat);
-#endif
-#ifdef CONFIG_M68K_L2_CACHE
-void (*mach_l2_flush) (int);
-#endif
-#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
-void (*mach_beep)(unsigned int, unsigned int);
-EXPORT_SYMBOL(mach_beep);
-#endif
-#if defined(CONFIG_ISA) && defined(MULTI_ISA)
-int isa_type;
-int isa_sex;
-EXPORT_SYMBOL(isa_type);
-EXPORT_SYMBOL(isa_sex);
-#endif
-
-extern int amiga_parse_bootinfo(const struct bi_record *);
-extern int atari_parse_bootinfo(const struct bi_record *);
-extern int mac_parse_bootinfo(const struct bi_record *);
-extern int q40_parse_bootinfo(const struct bi_record *);
-extern int bvme6000_parse_bootinfo(const struct bi_record *);
-extern int mvme16x_parse_bootinfo(const struct bi_record *);
-extern int mvme147_parse_bootinfo(const struct bi_record *);
-extern int hp300_parse_bootinfo(const struct bi_record *);
-extern int apollo_parse_bootinfo(const struct bi_record *);
-
-extern void config_amiga(void);
-extern void config_atari(void);
-extern void config_mac(void);
-extern void config_sun3(void);
-extern void config_apollo(void);
-extern void config_mvme147(void);
-extern void config_mvme16x(void);
-extern void config_bvme6000(void);
-extern void config_hp300(void);
-extern void config_q40(void);
-extern void config_sun3x(void);
-
-#define MASK_256K 0xfffc0000
-
-extern void paging_init(void);
-
-static void __init m68k_parse_bootinfo(const struct bi_record *record)
-{
-	while (record->tag != BI_LAST) {
-		int unknown = 0;
-		const unsigned long *data = record->data;
-
-		switch (record->tag) {
-		case BI_MACHTYPE:
-		case BI_CPUTYPE:
-		case BI_FPUTYPE:
-		case BI_MMUTYPE:
-			/* Already set up by head.S */
-			break;
-
-		case BI_MEMCHUNK:
-			if (m68k_num_memory < NUM_MEMINFO) {
-				m68k_memory[m68k_num_memory].addr = data[0];
-				m68k_memory[m68k_num_memory].size = data[1];
-				m68k_num_memory++;
-			} else
-				printk("m68k_parse_bootinfo: too many memory chunks\n");
-			break;
-
-		case BI_RAMDISK:
-			m68k_ramdisk.addr = data[0];
-			m68k_ramdisk.size = data[1];
-			break;
-
-		case BI_COMMAND_LINE:
-			strlcpy(m68k_command_line, (const char *)data,
-				sizeof(m68k_command_line));
-			break;
-
-		default:
-			if (MACH_IS_AMIGA)
-				unknown = amiga_parse_bootinfo(record);
-			else if (MACH_IS_ATARI)
-				unknown = atari_parse_bootinfo(record);
-			else if (MACH_IS_MAC)
-				unknown = mac_parse_bootinfo(record);
-			else if (MACH_IS_Q40)
-				unknown = q40_parse_bootinfo(record);
-			else if (MACH_IS_BVME6000)
-				unknown = bvme6000_parse_bootinfo(record);
-			else if (MACH_IS_MVME16x)
-				unknown = mvme16x_parse_bootinfo(record);
-			else if (MACH_IS_MVME147)
-				unknown = mvme147_parse_bootinfo(record);
-			else if (MACH_IS_HP300)
-				unknown = hp300_parse_bootinfo(record);
-			else if (MACH_IS_APOLLO)
-				unknown = apollo_parse_bootinfo(record);
-			else
-				unknown = 1;
-		}
-		if (unknown)
-			printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
-			       record->tag);
-		record = (struct bi_record *)((unsigned long)record +
-					      record->size);
-	}
-
-	m68k_realnum_memory = m68k_num_memory;
-#ifdef CONFIG_SINGLE_MEMORY_CHUNK
-	if (m68k_num_memory > 1) {
-		printk("Ignoring last %i chunks of physical memory\n",
-		       (m68k_num_memory - 1));
-		m68k_num_memory = 1;
-	}
-#endif
-}
-
-void __init setup_arch(char **cmdline_p)
-{
-	int i;
-
-	/* The bootinfo is located right after the kernel bss */
-	m68k_parse_bootinfo((const struct bi_record *)_end);
-
-	if (CPU_IS_040)
-		m68k_is040or060 = 4;
-	else if (CPU_IS_060)
-		m68k_is040or060 = 6;
-
-	/* FIXME: m68k_fputype is passed in by Penguin booter, which can
-	 * be confused by software FPU emulation. BEWARE.
-	 * We should really do our own FPU check at startup.
-	 * [what do we do with buggy 68LC040s? if we have problems
-	 *  with them, we should add a test to check_bugs() below] */
-#ifndef CONFIG_M68KFPU_EMU_ONLY
-	/* clear the fpu if we have one */
-	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
-		volatile int zero = 0;
-		asm volatile ("frestore %0" : : "m" (zero));
-	}
-#endif
-
-	if (CPU_IS_060) {
-		u32 pcr;
-
-		asm (".chip 68060; movec %%pcr,%0; .chip 68k"
-		     : "=d" (pcr));
-		if (((pcr >> 8) & 0xff) <= 5) {
-			printk("Enabling workaround for errata I14\n");
-			asm (".chip 68060; movec %0,%%pcr; .chip 68k"
-			     : : "d" (pcr | 0x20));
-		}
-	}
-
-	init_mm.start_code = PAGE_OFFSET;
-	init_mm.end_code = (unsigned long)_etext;
-	init_mm.end_data = (unsigned long)_edata;
-	init_mm.brk = (unsigned long)_end;
-
-	*cmdline_p = m68k_command_line;
-	memcpy(boot_command_line, *cmdline_p, CL_SIZE);
-
-	parse_early_param();
-
-#ifdef CONFIG_DUMMY_CONSOLE
-	conswitchp = &dummy_con;
-#endif
-
-	switch (m68k_machtype) {
-#ifdef CONFIG_AMIGA
-	case MACH_AMIGA:
-		config_amiga();
-		break;
-#endif
-#ifdef CONFIG_ATARI
-	case MACH_ATARI:
-		config_atari();
-		break;
-#endif
-#ifdef CONFIG_MAC
-	case MACH_MAC:
-		config_mac();
-		break;
-#endif
-#ifdef CONFIG_SUN3
-	case MACH_SUN3:
-		config_sun3();
-		break;
-#endif
-#ifdef CONFIG_APOLLO
-	case MACH_APOLLO:
-		config_apollo();
-		break;
-#endif
-#ifdef CONFIG_MVME147
-	case MACH_MVME147:
-		config_mvme147();
-		break;
-#endif
-#ifdef CONFIG_MVME16x
-	case MACH_MVME16x:
-		config_mvme16x();
-		break;
-#endif
-#ifdef CONFIG_BVME6000
-	case MACH_BVME6000:
-		config_bvme6000();
-		break;
-#endif
-#ifdef CONFIG_HP300
-	case MACH_HP300:
-		config_hp300();
-		break;
-#endif
-#ifdef CONFIG_Q40
-	case MACH_Q40:
-		config_q40();
-		break;
-#endif
-#ifdef CONFIG_SUN3X
-	case MACH_SUN3X:
-		config_sun3x();
-		break;
-#endif
-	default:
-		panic("No configuration setup");
-	}
-
-	paging_init();
-
-#ifndef CONFIG_SUN3
-	for (i = 1; i < m68k_num_memory; i++)
-		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
-				  m68k_memory[i].size);
-#ifdef CONFIG_BLK_DEV_INITRD
-	if (m68k_ramdisk.size) {
-		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
-				     m68k_ramdisk.addr, m68k_ramdisk.size,
-				     BOOTMEM_DEFAULT);
-		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
-		initrd_end = initrd_start + m68k_ramdisk.size;
-		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
-	}
-#endif
-
-#ifdef CONFIG_ATARI
-	if (MACH_IS_ATARI)
-		atari_stram_reserve_pages((void *)availmem);
-#endif
-#ifdef CONFIG_SUN3X
-	if (MACH_IS_SUN3X) {
-		dvma_init();
-	}
-#endif
-
-#endif /* !CONFIG_SUN3 */
-
-/* set ISA defs early as possible */
-#if defined(CONFIG_ISA) && defined(MULTI_ISA)
-	if (MACH_IS_Q40) {
-		isa_type = ISA_TYPE_Q40;
-		isa_sex = 0;
-	}
-#ifdef CONFIG_AMIGA_PCMCIA
-	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
-		isa_type = ISA_TYPE_AG;
-		isa_sex = 1;
-	}
-#endif
-#endif
-}
-
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
-	const char *cpu, *mmu, *fpu;
-	unsigned long clockfreq, clockfactor;
-
-#define LOOP_CYCLES_68020	(8)
-#define LOOP_CYCLES_68030	(8)
-#define LOOP_CYCLES_68040	(3)
-#define LOOP_CYCLES_68060	(1)
-
-	if (CPU_IS_020) {
-		cpu = "68020";
-		clockfactor = LOOP_CYCLES_68020;
-	} else if (CPU_IS_030) {
-		cpu = "68030";
-		clockfactor = LOOP_CYCLES_68030;
-	} else if (CPU_IS_040) {
-		cpu = "68040";
-		clockfactor = LOOP_CYCLES_68040;
-	} else if (CPU_IS_060) {
-		cpu = "68060";
-		clockfactor = LOOP_CYCLES_68060;
-	} else {
-		cpu = "680x0";
-		clockfactor = 0;
-	}
-
-#ifdef CONFIG_M68KFPU_EMU_ONLY
-	fpu = "none(soft float)";
+#ifdef CONFIG_MMU
+#include "setup_mm.c"
 #else
-	if (m68k_fputype & FPU_68881)
-		fpu = "68881";
-	else if (m68k_fputype & FPU_68882)
-		fpu = "68882";
-	else if (m68k_fputype & FPU_68040)
-		fpu = "68040";
-	else if (m68k_fputype & FPU_68060)
-		fpu = "68060";
-	else if (m68k_fputype & FPU_SUNFPA)
-		fpu = "Sun FPA";
-	else
-		fpu = "none";
-#endif
-
-	if (m68k_mmutype & MMU_68851)
-		mmu = "68851";
-	else if (m68k_mmutype & MMU_68030)
-		mmu = "68030";
-	else if (m68k_mmutype & MMU_68040)
-		mmu = "68040";
-	else if (m68k_mmutype & MMU_68060)
-		mmu = "68060";
-	else if (m68k_mmutype & MMU_SUN3)
-		mmu = "Sun-3";
-	else if (m68k_mmutype & MMU_APOLLO)
-		mmu = "Apollo";
-	else
-		mmu = "unknown";
-
-	clockfreq = loops_per_jiffy * HZ * clockfactor;
-
-	seq_printf(m, "CPU:\t\t%s\n"
-		   "MMU:\t\t%s\n"
-		   "FPU:\t\t%s\n"
-		   "Clocking:\t%lu.%1luMHz\n"
-		   "BogoMips:\t%lu.%02lu\n"
-		   "Calibration:\t%lu loops\n",
-		   cpu, mmu, fpu,
-		   clockfreq/1000000,(clockfreq/100000)%10,
-		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
-		   loops_per_jiffy);
-	return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-	return *pos < 1 ? (void *)1 : NULL;
-}
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	++*pos;
-	return NULL;
-}
-static void c_stop(struct seq_file *m, void *v)
-{
-}
-const struct seq_operations cpuinfo_op = {
-	.start	= c_start,
-	.next	= c_next,
-	.stop	= c_stop,
-	.show	= show_cpuinfo,
-};
-
-#ifdef CONFIG_PROC_HARDWARE
-static int hardware_proc_show(struct seq_file *m, void *v)
-{
-	char model[80];
-	unsigned long mem;
-	int i;
-
-	if (mach_get_model)
-		mach_get_model(model);
-	else
-		strcpy(model, "Unknown m68k");
-
-	seq_printf(m, "Model:\t\t%s\n", model);
-	for (mem = 0, i = 0; i < m68k_num_memory; i++)
-		mem += m68k_memory[i].size;
-	seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
-
-	if (mach_get_hardware_list)
-		mach_get_hardware_list(m);
-
-	return 0;
-}
-
-static int hardware_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, hardware_proc_show, NULL);
-}
-
-static const struct file_operations hardware_proc_fops = {
-	.open		= hardware_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-static int __init proc_hardware_init(void)
-{
-	proc_create("hardware", 0, NULL, &hardware_proc_fops);
-	return 0;
-}
-module_init(proc_hardware_init);
+#include "setup_no.c"
 #endif
-
-void check_bugs(void)
-{
-#ifndef CONFIG_M68KFPU_EMU
-	if (m68k_fputype == 0) {
-		printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
-			"WHICH IS REQUIRED BY LINUX/M68K ***\n");
-		printk(KERN_EMERG "Upgrade your hardware or join the FPU "
-			"emulation project\n");
-		panic("no FPU");
-	}
-#endif /* !CONFIG_M68KFPU_EMU */
-}
-
-#ifdef CONFIG_ADB
-static int __init adb_probe_sync_enable (char *str) {
-	extern int __adb_probe_sync;
-	__adb_probe_sync = 1;
-	return 1;
-}
-
-__setup("adb_sync", adb_probe_sync_enable);
-#endif /* CONFIG_ADB */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/setup_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/setup_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/setup_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/setup_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,533 @@
+/*
+ *  linux/arch/m68k/kernel/setup.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ */
+
+/*
+ * This file handles the architecture-dependent parts of system setup
+ */
+
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fs.h>
+#include <linux/console.h>
+#include <linux/genhd.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <linux/module.h>
+#include <linux/initrd.h>
+
+#include <asm/bootinfo.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+#ifdef CONFIG_AMIGA
+#include <asm/amigahw.h>
+#endif
+#ifdef CONFIG_ATARI
+#include <asm/atarihw.h>
+#include <asm/atari_stram.h>
+#endif
+#ifdef CONFIG_SUN3X
+#include <asm/dvma.h>
+#endif
+#include <asm/natfeat.h>
+
+#if !FPSTATESIZE || !NR_IRQS
+#warning No CPU/platform type selected, your kernel will not work!
+#warning Are you building an allnoconfig kernel?
+#endif
+
+unsigned long m68k_machtype;
+EXPORT_SYMBOL(m68k_machtype);
+unsigned long m68k_cputype;
+EXPORT_SYMBOL(m68k_cputype);
+unsigned long m68k_fputype;
+unsigned long m68k_mmutype;
+EXPORT_SYMBOL(m68k_mmutype);
+#ifdef CONFIG_VME
+unsigned long vme_brdtype;
+EXPORT_SYMBOL(vme_brdtype);
+#endif
+
+int m68k_is040or060;
+EXPORT_SYMBOL(m68k_is040or060);
+
+extern unsigned long availmem;
+
+int m68k_num_memory;
+EXPORT_SYMBOL(m68k_num_memory);
+int m68k_realnum_memory;
+EXPORT_SYMBOL(m68k_realnum_memory);
+unsigned long m68k_memoffset;
+struct mem_info m68k_memory[NUM_MEMINFO];
+EXPORT_SYMBOL(m68k_memory);
+
+struct mem_info m68k_ramdisk;
+
+static char m68k_command_line[CL_SIZE];
+
+void (*mach_sched_init) (irq_handler_t handler) __initdata = NULL;
+/* machine dependent irq functions */
+void (*mach_init_IRQ) (void) __initdata = NULL;
+void (*mach_get_model) (char *model);
+void (*mach_get_hardware_list) (struct seq_file *m);
+/* machine dependent timer functions */
+unsigned long (*mach_gettimeoffset) (void);
+int (*mach_hwclk) (int, struct rtc_time*);
+EXPORT_SYMBOL(mach_hwclk);
+int (*mach_set_clock_mmss) (unsigned long);
+unsigned int (*mach_get_ss)(void);
+int (*mach_get_rtc_pll)(struct rtc_pll_info *);
+int (*mach_set_rtc_pll)(struct rtc_pll_info *);
+EXPORT_SYMBOL(mach_get_ss);
+EXPORT_SYMBOL(mach_get_rtc_pll);
+EXPORT_SYMBOL(mach_set_rtc_pll);
+void (*mach_reset)( void );
+void (*mach_halt)( void );
+void (*mach_power_off)( void );
+long mach_max_dma_address = 0x00ffffff; /* default set to the lower 16MB */
+#ifdef CONFIG_HEARTBEAT
+void (*mach_heartbeat) (int);
+EXPORT_SYMBOL(mach_heartbeat);
+#endif
+#ifdef CONFIG_M68K_L2_CACHE
+void (*mach_l2_flush) (int);
+#endif
+#if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
+void (*mach_beep)(unsigned int, unsigned int);
+EXPORT_SYMBOL(mach_beep);
+#endif
+#if defined(CONFIG_ISA) && defined(MULTI_ISA)
+int isa_type;
+int isa_sex;
+EXPORT_SYMBOL(isa_type);
+EXPORT_SYMBOL(isa_sex);
+#endif
+
+extern int amiga_parse_bootinfo(const struct bi_record *);
+extern int atari_parse_bootinfo(const struct bi_record *);
+extern int mac_parse_bootinfo(const struct bi_record *);
+extern int q40_parse_bootinfo(const struct bi_record *);
+extern int bvme6000_parse_bootinfo(const struct bi_record *);
+extern int mvme16x_parse_bootinfo(const struct bi_record *);
+extern int mvme147_parse_bootinfo(const struct bi_record *);
+extern int hp300_parse_bootinfo(const struct bi_record *);
+extern int apollo_parse_bootinfo(const struct bi_record *);
+
+extern void config_amiga(void);
+extern void config_atari(void);
+extern void config_mac(void);
+extern void config_sun3(void);
+extern void config_apollo(void);
+extern void config_mvme147(void);
+extern void config_mvme16x(void);
+extern void config_bvme6000(void);
+extern void config_hp300(void);
+extern void config_q40(void);
+extern void config_sun3x(void);
+
+#define MASK_256K 0xfffc0000
+
+extern void paging_init(void);
+
+static void __init m68k_parse_bootinfo(const struct bi_record *record)
+{
+	while (record->tag != BI_LAST) {
+		int unknown = 0;
+		const unsigned long *data = record->data;
+
+		switch (record->tag) {
+		case BI_MACHTYPE:
+		case BI_CPUTYPE:
+		case BI_FPUTYPE:
+		case BI_MMUTYPE:
+			/* Already set up by head.S */
+			break;
+
+		case BI_MEMCHUNK:
+			if (m68k_num_memory < NUM_MEMINFO) {
+				m68k_memory[m68k_num_memory].addr = data[0];
+				m68k_memory[m68k_num_memory].size = data[1];
+				m68k_num_memory++;
+			} else
+				printk("m68k_parse_bootinfo: too many memory chunks\n");
+			break;
+
+		case BI_RAMDISK:
+			m68k_ramdisk.addr = data[0];
+			m68k_ramdisk.size = data[1];
+			break;
+
+		case BI_COMMAND_LINE:
+			strlcpy(m68k_command_line, (const char *)data,
+				sizeof(m68k_command_line));
+			break;
+
+		default:
+			if (MACH_IS_AMIGA)
+				unknown = amiga_parse_bootinfo(record);
+			else if (MACH_IS_ATARI)
+				unknown = atari_parse_bootinfo(record);
+			else if (MACH_IS_MAC)
+				unknown = mac_parse_bootinfo(record);
+			else if (MACH_IS_Q40)
+				unknown = q40_parse_bootinfo(record);
+			else if (MACH_IS_BVME6000)
+				unknown = bvme6000_parse_bootinfo(record);
+			else if (MACH_IS_MVME16x)
+				unknown = mvme16x_parse_bootinfo(record);
+			else if (MACH_IS_MVME147)
+				unknown = mvme147_parse_bootinfo(record);
+			else if (MACH_IS_HP300)
+				unknown = hp300_parse_bootinfo(record);
+			else if (MACH_IS_APOLLO)
+				unknown = apollo_parse_bootinfo(record);
+			else
+				unknown = 1;
+		}
+		if (unknown)
+			printk("m68k_parse_bootinfo: unknown tag 0x%04x ignored\n",
+			       record->tag);
+		record = (struct bi_record *)((unsigned long)record +
+					      record->size);
+	}
+
+	m68k_realnum_memory = m68k_num_memory;
+#ifdef CONFIG_SINGLE_MEMORY_CHUNK
+	if (m68k_num_memory > 1) {
+		printk("Ignoring last %i chunks of physical memory\n",
+		       (m68k_num_memory - 1));
+		m68k_num_memory = 1;
+	}
+#endif
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+	int i;
+
+	/* The bootinfo is located right after the kernel bss */
+	m68k_parse_bootinfo((const struct bi_record *)_end);
+
+	if (CPU_IS_040)
+		m68k_is040or060 = 4;
+	else if (CPU_IS_060)
+		m68k_is040or060 = 6;
+
+	/* FIXME: m68k_fputype is passed in by Penguin booter, which can
+	 * be confused by software FPU emulation. BEWARE.
+	 * We should really do our own FPU check at startup.
+	 * [what do we do with buggy 68LC040s? if we have problems
+	 *  with them, we should add a test to check_bugs() below] */
+#ifndef CONFIG_M68KFPU_EMU_ONLY
+	/* clear the fpu if we have one */
+	if (m68k_fputype & (FPU_68881|FPU_68882|FPU_68040|FPU_68060)) {
+		volatile int zero = 0;
+		asm volatile ("frestore %0" : : "m" (zero));
+	}
+#endif
+
+	if (CPU_IS_060) {
+		u32 pcr;
+
+		asm (".chip 68060; movec %%pcr,%0; .chip 68k"
+		     : "=d" (pcr));
+		if (((pcr >> 8) & 0xff) <= 5) {
+			printk("Enabling workaround for errata I14\n");
+			asm (".chip 68060; movec %0,%%pcr; .chip 68k"
+			     : : "d" (pcr | 0x20));
+		}
+	}
+
+	init_mm.start_code = PAGE_OFFSET;
+	init_mm.end_code = (unsigned long)_etext;
+	init_mm.end_data = (unsigned long)_edata;
+	init_mm.brk = (unsigned long)_end;
+
+	*cmdline_p = m68k_command_line;
+	memcpy(boot_command_line, *cmdline_p, CL_SIZE);
+
+	parse_early_param();
+
+#ifdef CONFIG_DUMMY_CONSOLE
+	conswitchp = &dummy_con;
+#endif
+
+	switch (m68k_machtype) {
+#ifdef CONFIG_AMIGA
+	case MACH_AMIGA:
+		config_amiga();
+		break;
+#endif
+#ifdef CONFIG_ATARI
+	case MACH_ATARI:
+		config_atari();
+		break;
+#endif
+#ifdef CONFIG_MAC
+	case MACH_MAC:
+		config_mac();
+		break;
+#endif
+#ifdef CONFIG_SUN3
+	case MACH_SUN3:
+		config_sun3();
+		break;
+#endif
+#ifdef CONFIG_APOLLO
+	case MACH_APOLLO:
+		config_apollo();
+		break;
+#endif
+#ifdef CONFIG_MVME147
+	case MACH_MVME147:
+		config_mvme147();
+		break;
+#endif
+#ifdef CONFIG_MVME16x
+	case MACH_MVME16x:
+		config_mvme16x();
+		break;
+#endif
+#ifdef CONFIG_BVME6000
+	case MACH_BVME6000:
+		config_bvme6000();
+		break;
+#endif
+#ifdef CONFIG_HP300
+	case MACH_HP300:
+		config_hp300();
+		break;
+#endif
+#ifdef CONFIG_Q40
+	case MACH_Q40:
+		config_q40();
+		break;
+#endif
+#ifdef CONFIG_SUN3X
+	case MACH_SUN3X:
+		config_sun3x();
+		break;
+#endif
+	default:
+		panic("No configuration setup");
+	}
+
+#ifdef CONFIG_NATFEAT
+	nf_init();
+#endif
+
+	paging_init();
+
+#ifndef CONFIG_SUN3
+	for (i = 1; i < m68k_num_memory; i++)
+		free_bootmem_node(NODE_DATA(i), m68k_memory[i].addr,
+				  m68k_memory[i].size);
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (m68k_ramdisk.size) {
+		reserve_bootmem_node(__virt_to_node(phys_to_virt(m68k_ramdisk.addr)),
+				     m68k_ramdisk.addr, m68k_ramdisk.size,
+				     BOOTMEM_DEFAULT);
+		initrd_start = (unsigned long)phys_to_virt(m68k_ramdisk.addr);
+		initrd_end = initrd_start + m68k_ramdisk.size;
+		printk("initrd: %08lx - %08lx\n", initrd_start, initrd_end);
+	}
+#endif
+
+#ifdef CONFIG_ATARI
+	if (MACH_IS_ATARI)
+		atari_stram_reserve_pages((void *)availmem);
+#endif
+#ifdef CONFIG_SUN3X
+	if (MACH_IS_SUN3X) {
+		dvma_init();
+	}
+#endif
+
+#endif /* !CONFIG_SUN3 */
+
+/* set ISA defs early as possible */
+#if defined(CONFIG_ISA) && defined(MULTI_ISA)
+	if (MACH_IS_Q40) {
+		isa_type = ISA_TYPE_Q40;
+		isa_sex = 0;
+	}
+#ifdef CONFIG_AMIGA_PCMCIA
+	if (MACH_IS_AMIGA && AMIGAHW_PRESENT(PCMCIA)) {
+		isa_type = ISA_TYPE_AG;
+		isa_sex = 1;
+	}
+#endif
+#endif
+}
+
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	const char *cpu, *mmu, *fpu;
+	unsigned long clockfreq, clockfactor;
+
+#define LOOP_CYCLES_68020	(8)
+#define LOOP_CYCLES_68030	(8)
+#define LOOP_CYCLES_68040	(3)
+#define LOOP_CYCLES_68060	(1)
+
+	if (CPU_IS_020) {
+		cpu = "68020";
+		clockfactor = LOOP_CYCLES_68020;
+	} else if (CPU_IS_030) {
+		cpu = "68030";
+		clockfactor = LOOP_CYCLES_68030;
+	} else if (CPU_IS_040) {
+		cpu = "68040";
+		clockfactor = LOOP_CYCLES_68040;
+	} else if (CPU_IS_060) {
+		cpu = "68060";
+		clockfactor = LOOP_CYCLES_68060;
+	} else {
+		cpu = "680x0";
+		clockfactor = 0;
+	}
+
+#ifdef CONFIG_M68KFPU_EMU_ONLY
+	fpu = "none(soft float)";
+#else
+	if (m68k_fputype & FPU_68881)
+		fpu = "68881";
+	else if (m68k_fputype & FPU_68882)
+		fpu = "68882";
+	else if (m68k_fputype & FPU_68040)
+		fpu = "68040";
+	else if (m68k_fputype & FPU_68060)
+		fpu = "68060";
+	else if (m68k_fputype & FPU_SUNFPA)
+		fpu = "Sun FPA";
+	else
+		fpu = "none";
+#endif
+
+	if (m68k_mmutype & MMU_68851)
+		mmu = "68851";
+	else if (m68k_mmutype & MMU_68030)
+		mmu = "68030";
+	else if (m68k_mmutype & MMU_68040)
+		mmu = "68040";
+	else if (m68k_mmutype & MMU_68060)
+		mmu = "68060";
+	else if (m68k_mmutype & MMU_SUN3)
+		mmu = "Sun-3";
+	else if (m68k_mmutype & MMU_APOLLO)
+		mmu = "Apollo";
+	else
+		mmu = "unknown";
+
+	clockfreq = loops_per_jiffy * HZ * clockfactor;
+
+	seq_printf(m, "CPU:\t\t%s\n"
+		   "MMU:\t\t%s\n"
+		   "FPU:\t\t%s\n"
+		   "Clocking:\t%lu.%1luMHz\n"
+		   "BogoMips:\t%lu.%02lu\n"
+		   "Calibration:\t%lu loops\n",
+		   cpu, mmu, fpu,
+		   clockfreq/1000000,(clockfreq/100000)%10,
+		   loops_per_jiffy/(500000/HZ),(loops_per_jiffy/(5000/HZ))%100,
+		   loops_per_jiffy);
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
+};
+
+#ifdef CONFIG_PROC_HARDWARE
+static int hardware_proc_show(struct seq_file *m, void *v)
+{
+	char model[80];
+	unsigned long mem;
+	int i;
+
+	if (mach_get_model)
+		mach_get_model(model);
+	else
+		strcpy(model, "Unknown m68k");
+
+	seq_printf(m, "Model:\t\t%s\n", model);
+	for (mem = 0, i = 0; i < m68k_num_memory; i++)
+		mem += m68k_memory[i].size;
+	seq_printf(m, "System Memory:\t%ldK\n", mem >> 10);
+
+	if (mach_get_hardware_list)
+		mach_get_hardware_list(m);
+
+	return 0;
+}
+
+static int hardware_proc_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, hardware_proc_show, NULL);
+}
+
+static const struct file_operations hardware_proc_fops = {
+	.open		= hardware_proc_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int __init proc_hardware_init(void)
+{
+	proc_create("hardware", 0, NULL, &hardware_proc_fops);
+	return 0;
+}
+module_init(proc_hardware_init);
+#endif
+
+void check_bugs(void)
+{
+#ifndef CONFIG_M68KFPU_EMU
+	if (m68k_fputype == 0) {
+		printk(KERN_EMERG "*** YOU DO NOT HAVE A FLOATING POINT UNIT, "
+			"WHICH IS REQUIRED BY LINUX/M68K ***\n");
+		printk(KERN_EMERG "Upgrade your hardware or join the FPU "
+			"emulation project\n");
+		panic("no FPU");
+	}
+#endif /* !CONFIG_M68KFPU_EMU */
+}
+
+#ifdef CONFIG_ADB
+static int __init adb_probe_sync_enable (char *str) {
+	extern int __adb_probe_sync;
+	__adb_probe_sync = 1;
+	return 1;
+}
+
+__setup("adb_sync", adb_probe_sync_enable);
+#endif /* CONFIG_ADB */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/setup_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/setup_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/setup_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/setup_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,317 @@
+/*
+ *  linux/arch/m68knommu/kernel/setup.c
+ *
+ *  Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org>
+ *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
+ *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
+ *  Copyright (C) 1995       Hamish Macdonald
+ *  Copyright (C) 2000       Lineo Inc. (www.lineo.com)
+ *  Copyright (C) 2001 	     Lineo, Inc. <www.lineo.com>
+ *
+ *  68VZ328 Fixes/support    Evan Stawnyczy <e@lineo.ca>
+ */
+
+/*
+ * This file handles the architecture-dependent parts of system setup
+ */
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/console.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/init.h>
+#include <linux/initrd.h>
+#include <linux/root_dev.h>
+
+#include <asm/setup.h>
+#include <asm/irq.h>
+#include <asm/machdep.h>
+#include <asm/pgtable.h>
+
+unsigned long memory_start;
+unsigned long memory_end;
+
+EXPORT_SYMBOL(memory_start);
+EXPORT_SYMBOL(memory_end);
+
+char __initdata command_line[COMMAND_LINE_SIZE];
+
+/* machine dependent timer functions */
+void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
+int (*mach_set_clock_mmss)(unsigned long);
+
+/* machine dependent reboot functions */
+void (*mach_reset)(void);
+void (*mach_halt)(void);
+void (*mach_power_off)(void);
+
+#ifdef CONFIG_M68328
+#define CPU_NAME	"MC68328"
+#endif
+#ifdef CONFIG_M68EZ328
+#define CPU_NAME	"MC68EZ328"
+#endif
+#ifdef CONFIG_M68VZ328
+#define CPU_NAME	"MC68VZ328"
+#endif
+#ifdef CONFIG_M68360
+#define CPU_NAME	"MC68360"
+#endif
+#ifndef CPU_NAME
+#define	CPU_NAME	"UNKNOWN"
+#endif
+
+/*
+ * Different cores have different instruction execution timings.
+ * The old/traditional 68000 cores are basically all the same, at 16.
+ * The ColdFire cores vary a little, their values are defined in their
+ * headers. We default to the standard 68000 value here.
+ */
+#ifndef CPU_INSTR_PER_JIFFY
+#define	CPU_INSTR_PER_JIFFY	16
+#endif
+
+extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
+extern int _ramstart, _ramend;
+
+#if defined(CONFIG_UBOOT)
+/*
+ * parse_uboot_commandline
+ *
+ * Copies u-boot commandline arguments and store them in the proper linux
+ * variables.
+ *
+ * Assumes:
+ *	_init_sp global contains the address in the stack pointer when the
+ *	kernel starts (see head.S::_start)
+ *
+ *	U-Boot calling convention:
+ *	(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
+ *
+ *	_init_sp can be parsed as such
+ *
+ *	_init_sp+00 = u-boot cmd after jsr into kernel (skip)
+ *	_init_sp+04 = &kernel board_info (residual data)
+ *	_init_sp+08 = &initrd_start
+ *	_init_sp+12 = &initrd_end
+ *	_init_sp+16 = &cmd_start
+ *	_init_sp+20 = &cmd_end
+ *
+ *	This also assumes that the memory locations pointed to are still
+ *	unmodified. U-boot places them near the end of external SDRAM.
+ *
+ * Argument(s):
+ *	commandp = the linux commandline arg container to fill.
+ *	size     = the sizeof commandp.
+ *
+ * Returns:
+ */
+void parse_uboot_commandline(char *commandp, int size)
+{
+	extern unsigned long _init_sp;
+	unsigned long *sp;
+	unsigned long uboot_kbd;
+	unsigned long uboot_initrd_start, uboot_initrd_end;
+	unsigned long uboot_cmd_start, uboot_cmd_end;
+
+
+	sp = (unsigned long *)_init_sp;
+	uboot_kbd = sp[1];
+	uboot_initrd_start = sp[2];
+	uboot_initrd_end = sp[3];
+	uboot_cmd_start = sp[4];
+	uboot_cmd_end = sp[5];
+
+	if (uboot_cmd_start && uboot_cmd_end)
+		strncpy(commandp, (const char *)uboot_cmd_start, size);
+#if defined(CONFIG_BLK_DEV_INITRD)
+	if (uboot_initrd_start && uboot_initrd_end &&
+		(uboot_initrd_end > uboot_initrd_start)) {
+		initrd_start = uboot_initrd_start;
+		initrd_end = uboot_initrd_end;
+		ROOT_DEV = Root_RAM0;
+		printk(KERN_INFO "initrd at 0x%lx:0x%lx\n",
+			initrd_start, initrd_end);
+	}
+#endif /* if defined(CONFIG_BLK_DEV_INITRD) */
+}
+#endif /* #if defined(CONFIG_UBOOT) */
+
+void __init setup_arch(char **cmdline_p)
+{
+	int bootmap_size;
+
+	memory_start = PAGE_ALIGN(_ramstart);
+	memory_end = _ramend;
+
+	init_mm.start_code = (unsigned long) &_stext;
+	init_mm.end_code = (unsigned long) &_etext;
+	init_mm.end_data = (unsigned long) &_edata;
+	init_mm.brk = (unsigned long) 0;
+
+	config_BSP(&command_line[0], sizeof(command_line));
+
+#if defined(CONFIG_BOOTPARAM)
+	strncpy(&command_line[0], CONFIG_BOOTPARAM_STRING, sizeof(command_line));
+	command_line[sizeof(command_line) - 1] = 0;
+#endif /* CONFIG_BOOTPARAM */
+
+#if defined(CONFIG_UBOOT)
+	/* CONFIG_UBOOT and CONFIG_BOOTPARAM defined, concatenate cmdline */
+	#if defined(CONFIG_BOOTPARAM)
+		/* Add the whitespace separator */
+		command_line[strlen(CONFIG_BOOTPARAM_STRING)] = ' ';
+		/* Parse uboot command line into the rest of the buffer */
+		parse_uboot_commandline(
+			&command_line[(strlen(CONFIG_BOOTPARAM_STRING)+1)],
+			(sizeof(command_line) -
+			(strlen(CONFIG_BOOTPARAM_STRING)+1)));
+	/* Only CONFIG_UBOOT defined, create cmdline */
+	#else
+		parse_uboot_commandline(&command_line[0], sizeof(command_line));
+	#endif /* CONFIG_BOOTPARAM */
+	command_line[sizeof(command_line) - 1] = 0;
+#endif /* CONFIG_UBOOT */
+
+	printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU_NAME "\n");
+
+#ifdef CONFIG_UCDIMM
+	printk(KERN_INFO "uCdimm by Lineo, Inc. <www.lineo.com>\n");
+#endif
+#ifdef CONFIG_M68VZ328
+	printk(KERN_INFO "M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n");
+#endif
+#ifdef CONFIG_COLDFIRE
+	printk(KERN_INFO "COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n");
+#ifdef CONFIG_M5307
+	printk(KERN_INFO "Modified for M5307 by Dave Miller, dmiller@intellistor.com\n");
+#endif
+#ifdef CONFIG_ELITE
+	printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
+#endif
+#endif
+	printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
+
+#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
+	printk(KERN_INFO "TRG SuperPilot FLASH card support <info@trgnet.com>\n");
+#endif
+#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
+	printk(KERN_INFO "PalmV support by Lineo Inc. <jeff@uclinux.com>\n");
+#endif
+#if defined (CONFIG_M68360)
+	printk(KERN_INFO "QUICC port done by SED Systems <hamilton@sedsystems.ca>,\n");
+	printk(KERN_INFO "based on 2.0.38 port by Lineo Inc. <mleslie@lineo.com>.\n");
+#endif
+#ifdef CONFIG_DRAGEN2
+	printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
+#endif
+#ifdef CONFIG_M5235EVB
+	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n");
+#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];
+	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
+
+#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+
+	/*
+	 * Give all the memory to the bootmap allocator, tell it to put the
+	 * boot mem_map at the start of memory.
+	 */
+	bootmap_size = init_bootmem_node(
+			NODE_DATA(0),
+			memory_start >> PAGE_SHIFT, /* map goes here */
+			PAGE_OFFSET >> PAGE_SHIFT,	/* 0 on coldfire */
+			memory_end >> PAGE_SHIFT);
+	/*
+	 * Free the usable memory, we have to make sure we do not free
+	 * the bootmem bitmap so we then reserve it after freeing it :-)
+	 */
+	free_bootmem(memory_start, memory_end - memory_start);
+	reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
+
+#if defined(CONFIG_UBOOT) && defined(CONFIG_BLK_DEV_INITRD)
+	if ((initrd_start > 0) && (initrd_start < initrd_end) &&
+			(initrd_end < memory_end))
+		reserve_bootmem(initrd_start, initrd_end - initrd_start,
+				 BOOTMEM_DEFAULT);
+#endif /* if defined(CONFIG_BLK_DEV_INITRD) */
+
+	/*
+	 * Get kmalloc into gear.
+	 */
+	paging_init();
+}
+
+/*
+ *	Get CPU information for use by the procfs.
+ */
+static int show_cpuinfo(struct seq_file *m, void *v)
+{
+	char *cpu, *mmu, *fpu;
+	u_long clockfreq;
+
+	cpu = CPU_NAME;
+	mmu = "none";
+	fpu = "none";
+	clockfreq = (loops_per_jiffy * HZ) * CPU_INSTR_PER_JIFFY;
+
+	seq_printf(m, "CPU:\t\t%s\n"
+		      "MMU:\t\t%s\n"
+		      "FPU:\t\t%s\n"
+		      "Clocking:\t%lu.%1luMHz\n"
+		      "BogoMips:\t%lu.%02lu\n"
+		      "Calibration:\t%lu loops\n",
+		      cpu, mmu, fpu,
+		      clockfreq / 1000000,
+		      (clockfreq / 100000) % 10,
+		      (loops_per_jiffy * HZ) / 500000,
+		      ((loops_per_jiffy * HZ) / 5000) % 100,
+		      (loops_per_jiffy * HZ));
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return c_start(m, pos);
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= show_cpuinfo,
+};
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/signal.c linux-libre-2.6.39-gnu/arch/m68k/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,995 +1,5 @@
-/*
- *  linux/arch/m68k/kernel/signal.c
- *
- *  Copyright (C) 1991, 1992  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.
- */
-
-/*
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- *
- * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
- *
- * mathemu support by Roman Zippel
- *  (Note: fpstate in the signal context is completely ignored for the emulator
- *         and the internal floating point format is put on stack)
- */
-
-/*
- * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
- * Atari :-) Current limitation: Only one sigstack can be active at one time.
- * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
- * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
- * signal handlers!
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/highuid.h>
-#include <linux/personality.h>
-#include <linux/tty.h>
-#include <linux/binfmts.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/ucontext.h>
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-const int frame_extra_sizes[16] = {
-  [1]	= -1, /* sizeof(((struct frame *)0)->un.fmt1), */
-  [2]	= sizeof(((struct frame *)0)->un.fmt2),
-  [3]	= sizeof(((struct frame *)0)->un.fmt3),
-  [4]	= sizeof(((struct frame *)0)->un.fmt4),
-  [5]	= -1, /* sizeof(((struct frame *)0)->un.fmt5), */
-  [6]	= -1, /* sizeof(((struct frame *)0)->un.fmt6), */
-  [7]	= sizeof(((struct frame *)0)->un.fmt7),
-  [8]	= -1, /* sizeof(((struct frame *)0)->un.fmt8), */
-  [9]	= sizeof(((struct frame *)0)->un.fmt9),
-  [10]	= sizeof(((struct frame *)0)->un.fmta),
-  [11]	= sizeof(((struct frame *)0)->un.fmtb),
-  [12]	= -1, /* sizeof(((struct frame *)0)->un.fmtc), */
-  [13]	= -1, /* sizeof(((struct frame *)0)->un.fmtd), */
-  [14]	= -1, /* sizeof(((struct frame *)0)->un.fmte), */
-  [15]	= -1, /* sizeof(((struct frame *)0)->un.fmtf), */
-};
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
-{
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	current->saved_sigmask = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-	set_restore_sigmask();
-
-	return -ERESTARTNOHAND;
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction __user *act,
-	      struct old_sigaction __user *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) ||
-		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
-		    __get_user(mask, &act->sa_mask))
-			return -EFAULT;
-		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) ||
-		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
-		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-asmlinkage int
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
-	return do_sigaltstack(uss, uoss, rdusp());
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- *
- * Keep the return code on the stack quadword aligned!
- * That makes the cache flush below easier.
- */
-
-struct sigframe
-{
-	char __user *pretcode;
-	int sig;
-	int code;
-	struct sigcontext __user *psc;
-	char retcode[8];
-	unsigned long extramask[_NSIG_WORDS-1];
-	struct sigcontext sc;
-};
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct siginfo __user *pinfo;
-	void __user *puc;
-	char retcode[8];
-	struct siginfo info;
-	struct ucontext uc;
-};
-
-
-static unsigned char fpu_version;	/* version number of fpu, set by setup_frame */
-
-static inline int restore_fpu_state(struct sigcontext *sc)
-{
-	int err = 1;
-
-	if (FPU_IS_EMU) {
-	    /* restore registers */
-	    memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
-	    memcpy(current->thread.fp, sc->sc_fpregs, 24);
-	    return 0;
-	}
-
-	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
-	    /* Verify the frame format.  */
-	    if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
-		goto out;
-	    if (CPU_IS_020_OR_030) {
-		if (m68k_fputype & FPU_68881 &&
-		    !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
-		    goto out;
-		if (m68k_fputype & FPU_68882 &&
-		    !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
-		    goto out;
-	    } else if (CPU_IS_040) {
-		if (!(sc->sc_fpstate[1] == 0x00 ||
-                      sc->sc_fpstate[1] == 0x28 ||
-                      sc->sc_fpstate[1] == 0x60))
-		    goto out;
-	    } else if (CPU_IS_060) {
-		if (!(sc->sc_fpstate[3] == 0x00 ||
-                      sc->sc_fpstate[3] == 0x60 ||
-		      sc->sc_fpstate[3] == 0xe0))
-		    goto out;
-	    } else
-		goto out;
-
-	    __asm__ volatile (".chip 68k/68881\n\t"
-			      "fmovemx %0,%%fp0-%%fp1\n\t"
-			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
-			      ".chip 68k"
-			      : /* no outputs */
-			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
-	}
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "frestore %0\n\t"
-			  ".chip 68k" : : "m" (*sc->sc_fpstate));
-	err = 0;
-
-out:
-	return err;
-}
-
-#define FPCONTEXT_SIZE	216
-#define uc_fpstate	uc_filler[0]
-#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4]
-#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1]
-
-static inline int rt_restore_fpu_state(struct ucontext __user *uc)
-{
-	unsigned char fpstate[FPCONTEXT_SIZE];
-	int context_size = CPU_IS_060 ? 8 : 0;
-	fpregset_t fpregs;
-	int err = 1;
-
-	if (FPU_IS_EMU) {
-		/* restore fpu control register */
-		if (__copy_from_user(current->thread.fpcntl,
-				uc->uc_mcontext.fpregs.f_fpcntl, 12))
-			goto out;
-		/* restore all other fpu register */
-		if (__copy_from_user(current->thread.fp,
-				uc->uc_mcontext.fpregs.f_fpregs, 96))
-			goto out;
-		return 0;
-	}
-
-	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
-		goto out;
-	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
-		if (!CPU_IS_060)
-			context_size = fpstate[1];
-		/* Verify the frame format.  */
-		if (!CPU_IS_060 && (fpstate[0] != fpu_version))
-			goto out;
-		if (CPU_IS_020_OR_030) {
-			if (m68k_fputype & FPU_68881 &&
-			    !(context_size == 0x18 || context_size == 0xb4))
-				goto out;
-			if (m68k_fputype & FPU_68882 &&
-			    !(context_size == 0x38 || context_size == 0xd4))
-				goto out;
-		} else if (CPU_IS_040) {
-			if (!(context_size == 0x00 ||
-			      context_size == 0x28 ||
-			      context_size == 0x60))
-				goto out;
-		} else if (CPU_IS_060) {
-			if (!(fpstate[3] == 0x00 ||
-			      fpstate[3] == 0x60 ||
-			      fpstate[3] == 0xe0))
-				goto out;
-		} else
-			goto out;
-		if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
-				     sizeof(fpregs)))
-			goto out;
-		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %0,%%fp0-%%fp7\n\t"
-				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
-				  ".chip 68k"
-				  : /* no outputs */
-				  : "m" (*fpregs.f_fpregs),
-				    "m" (*fpregs.f_fpcntl));
-	}
-	if (context_size &&
-	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
-			     context_size))
-		goto out;
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "frestore %0\n\t"
-			  ".chip 68k" : : "m" (*fpstate));
-	err = 0;
-
-out:
-	return err;
-}
-
-static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
-			       void __user *fp)
-{
-	int fsize = frame_extra_sizes[formatvec >> 12];
-	if (fsize < 0) {
-		/*
-		 * user process trying to return with weird frame format
-		 */
-#ifdef DEBUG
-		printk("user process returning with weird frame format\n");
-#endif
-		return 1;
-	}
-	if (!fsize) {
-		regs->format = formatvec >> 12;
-		regs->vector = formatvec & 0xfff;
-	} else {
-		struct switch_stack *sw = (struct switch_stack *)regs - 1;
-		unsigned long buf[fsize / 2]; /* yes, twice as much */
-
-		/* that'll make sure that expansion won't crap over data */
-		if (copy_from_user(buf + fsize / 4, fp, fsize))
-			return 1;
-
-		/* point of no return */
-		regs->format = formatvec >> 12;
-		regs->vector = formatvec & 0xfff;
-#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
-		__asm__ __volatile__
-			("   movel %0,%/a0\n\t"
-			 "   subl %1,%/a0\n\t"     /* make room on stack */
-			 "   movel %/a0,%/sp\n\t"  /* set stack pointer */
-			 /* move switch_stack and pt_regs */
-			 "1: movel %0@+,%/a0@+\n\t"
-			 "   dbra %2,1b\n\t"
-			 "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
-			 "   lsrl  #2,%1\n\t"
-			 "   subql #1,%1\n\t"
-			 /* copy to the gap we'd made */
-			 "2: movel %4@+,%/a0@+\n\t"
-			 "   dbra %1,2b\n\t"
-			 "   bral ret_from_signal\n"
-			 : /* no outputs, it doesn't ever return */
-			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
-			   "n" (frame_offset), "a" (buf + fsize/4)
-			 : "a0");
-#undef frame_offset
-	}
-	return 0;
-}
-
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
-{
-	int formatvec;
-	struct sigcontext context;
-	int err;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	/* get previous context */
-	if (copy_from_user(&context, usc, sizeof(context)))
-		goto badframe;
-
-	/* restore passed registers */
-	regs->d0 = context.sc_d0;
-	regs->d1 = context.sc_d1;
-	regs->a0 = context.sc_a0;
-	regs->a1 = context.sc_a1;
-	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
-	regs->pc = context.sc_pc;
-	regs->orig_d0 = -1;		/* disable syscall checks */
-	wrusp(context.sc_usp);
-	formatvec = context.sc_formatvec;
-
-	err = restore_fpu_state(&context);
-
-	if (err || mangle_kernel_stack(regs, formatvec, fp))
-		goto badframe;
-
-	return 0;
-
-badframe:
-	return 1;
-}
-
-static inline int
-rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
-		    struct ucontext __user *uc)
-{
-	int temp;
-	greg_t __user *gregs = uc->uc_mcontext.gregs;
-	unsigned long usp;
-	int err;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	err = __get_user(temp, &uc->uc_mcontext.version);
-	if (temp != MCONTEXT_VERSION)
-		goto badframe;
-	/* restore passed registers */
-	err |= __get_user(regs->d0, &gregs[0]);
-	err |= __get_user(regs->d1, &gregs[1]);
-	err |= __get_user(regs->d2, &gregs[2]);
-	err |= __get_user(regs->d3, &gregs[3]);
-	err |= __get_user(regs->d4, &gregs[4]);
-	err |= __get_user(regs->d5, &gregs[5]);
-	err |= __get_user(sw->d6, &gregs[6]);
-	err |= __get_user(sw->d7, &gregs[7]);
-	err |= __get_user(regs->a0, &gregs[8]);
-	err |= __get_user(regs->a1, &gregs[9]);
-	err |= __get_user(regs->a2, &gregs[10]);
-	err |= __get_user(sw->a3, &gregs[11]);
-	err |= __get_user(sw->a4, &gregs[12]);
-	err |= __get_user(sw->a5, &gregs[13]);
-	err |= __get_user(sw->a6, &gregs[14]);
-	err |= __get_user(usp, &gregs[15]);
-	wrusp(usp);
-	err |= __get_user(regs->pc, &gregs[16]);
-	err |= __get_user(temp, &gregs[17]);
-	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
-	regs->orig_d0 = -1;		/* disable syscall checks */
-	err |= __get_user(temp, &uc->uc_formatvec);
-
-	err |= rt_restore_fpu_state(uc);
-
-	if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
-		goto badframe;
-
-	if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
-		goto badframe;
-
-	return 0;
-
-badframe:
-	return 1;
-}
-
-asmlinkage int do_sigreturn(unsigned long __unused)
-{
-	struct switch_stack *sw = (struct switch_stack *) &__unused;
-	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
-	unsigned long usp = rdusp();
-	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
-	sigset_t set;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-	if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
-	    (_NSIG_WORDS > 1 &&
-	     __copy_from_user(&set.sig[1], &frame->extramask,
-			      sizeof(frame->extramask))))
-		goto badframe;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	current->blocked = set;
-	recalc_sigpending();
-
-	if (restore_sigcontext(regs, &frame->sc, frame + 1))
-		goto badframe;
-	return regs->d0;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-asmlinkage int do_rt_sigreturn(unsigned long __unused)
-{
-	struct switch_stack *sw = (struct switch_stack *) &__unused;
-	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
-	unsigned long usp = rdusp();
-	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
-	sigset_t set;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-		goto badframe;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	current->blocked = set;
-	recalc_sigpending();
-
-	if (rt_restore_ucontext(regs, sw, &frame->uc))
-		goto badframe;
-	return regs->d0;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-/*
- * Set up a signal frame.
- */
-
-static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
-{
-	if (FPU_IS_EMU) {
-		/* save registers */
-		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
-		memcpy(sc->sc_fpregs, current->thread.fp, 24);
-		return;
-	}
-
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "fsave %0\n\t"
-			  ".chip 68k"
-			  : : "m" (*sc->sc_fpstate) : "memory");
-
-	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
-		fpu_version = sc->sc_fpstate[0];
-		if (CPU_IS_020_OR_030 &&
-		    regs->vector >= (VEC_FPBRUC * 4) &&
-		    regs->vector <= (VEC_FPNAN * 4)) {
-			/* Clear pending exception in 68882 idle frame */
-			if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
-				sc->sc_fpstate[0x38] |= 1 << 3;
-		}
-		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %%fp0-%%fp1,%0\n\t"
-				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
-				  ".chip 68k"
-				  : "=m" (*sc->sc_fpregs),
-				    "=m" (*sc->sc_fpcntl)
-				  : /* no inputs */
-				  : "memory");
-	}
-}
-
-static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
-{
-	unsigned char fpstate[FPCONTEXT_SIZE];
-	int context_size = CPU_IS_060 ? 8 : 0;
-	int err = 0;
-
-	if (FPU_IS_EMU) {
-		/* save fpu control register */
-		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
-				current->thread.fpcntl, 12);
-		/* save all other fpu register */
-		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
-				current->thread.fp, 96);
-		return err;
-	}
-
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "fsave %0\n\t"
-			  ".chip 68k"
-			  : : "m" (*fpstate) : "memory");
-
-	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
-	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
-		fpregset_t fpregs;
-		if (!CPU_IS_060)
-			context_size = fpstate[1];
-		fpu_version = fpstate[0];
-		if (CPU_IS_020_OR_030 &&
-		    regs->vector >= (VEC_FPBRUC * 4) &&
-		    regs->vector <= (VEC_FPNAN * 4)) {
-			/* Clear pending exception in 68882 idle frame */
-			if (*(unsigned short *) fpstate == 0x1f38)
-				fpstate[0x38] |= 1 << 3;
-		}
-		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %%fp0-%%fp7,%0\n\t"
-				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
-				  ".chip 68k"
-				  : "=m" (*fpregs.f_fpregs),
-				    "=m" (*fpregs.f_fpcntl)
-				  : /* no inputs */
-				  : "memory");
-		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
-				    sizeof(fpregs));
-	}
-	if (context_size)
-		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
-				    context_size);
-	return err;
-}
-
-static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
-			     unsigned long mask)
-{
-	sc->sc_mask = mask;
-	sc->sc_usp = rdusp();
-	sc->sc_d0 = regs->d0;
-	sc->sc_d1 = regs->d1;
-	sc->sc_a0 = regs->a0;
-	sc->sc_a1 = regs->a1;
-	sc->sc_sr = regs->sr;
-	sc->sc_pc = regs->pc;
-	sc->sc_formatvec = regs->format << 12 | regs->vector;
-	save_fpu_state(sc, regs);
-}
-
-static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
-{
-	struct switch_stack *sw = (struct switch_stack *)regs - 1;
-	greg_t __user *gregs = uc->uc_mcontext.gregs;
-	int err = 0;
-
-	err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
-	err |= __put_user(regs->d0, &gregs[0]);
-	err |= __put_user(regs->d1, &gregs[1]);
-	err |= __put_user(regs->d2, &gregs[2]);
-	err |= __put_user(regs->d3, &gregs[3]);
-	err |= __put_user(regs->d4, &gregs[4]);
-	err |= __put_user(regs->d5, &gregs[5]);
-	err |= __put_user(sw->d6, &gregs[6]);
-	err |= __put_user(sw->d7, &gregs[7]);
-	err |= __put_user(regs->a0, &gregs[8]);
-	err |= __put_user(regs->a1, &gregs[9]);
-	err |= __put_user(regs->a2, &gregs[10]);
-	err |= __put_user(sw->a3, &gregs[11]);
-	err |= __put_user(sw->a4, &gregs[12]);
-	err |= __put_user(sw->a5, &gregs[13]);
-	err |= __put_user(sw->a6, &gregs[14]);
-	err |= __put_user(rdusp(), &gregs[15]);
-	err |= __put_user(regs->pc, &gregs[16]);
-	err |= __put_user(regs->sr, &gregs[17]);
-	err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
-	err |= rt_save_fpu_state(uc, regs);
-	return err;
-}
-
-static inline void push_cache (unsigned long vaddr)
-{
-	/*
-	 * Using the old cache_push_v() was really a big waste.
-	 *
-	 * What we are trying to do is to flush 8 bytes to ram.
-	 * Flushing 2 cache lines of 16 bytes is much cheaper than
-	 * flushing 1 or 2 pages, as previously done in
-	 * cache_push_v().
-	 *                                                     Jes
-	 */
-	if (CPU_IS_040) {
-		unsigned long temp;
-
-		__asm__ __volatile__ (".chip 68040\n\t"
-				      "nop\n\t"
-				      "ptestr (%1)\n\t"
-				      "movec %%mmusr,%0\n\t"
-				      ".chip 68k"
-				      : "=r" (temp)
-				      : "a" (vaddr));
-
-		temp &= PAGE_MASK;
-		temp |= vaddr & ~PAGE_MASK;
-
-		__asm__ __volatile__ (".chip 68040\n\t"
-				      "nop\n\t"
-				      "cpushl %%bc,(%0)\n\t"
-				      ".chip 68k"
-				      : : "a" (temp));
-	}
-	else if (CPU_IS_060) {
-		unsigned long temp;
-		__asm__ __volatile__ (".chip 68060\n\t"
-				      "plpar (%0)\n\t"
-				      ".chip 68k"
-				      : "=a" (temp)
-				      : "0" (vaddr));
-		__asm__ __volatile__ (".chip 68060\n\t"
-				      "cpushl %%bc,(%0)\n\t"
-				      ".chip 68k"
-				      : : "a" (temp));
-	}
-	else {
-		/*
-		 * 68030/68020 have no writeback cache;
-		 * still need to clear icache.
-		 * Note that vaddr is guaranteed to be long word aligned.
-		 */
-		unsigned long temp;
-		asm volatile ("movec %%cacr,%0" : "=r" (temp));
-		temp += 4;
-		asm volatile ("movec %0,%%caar\n\t"
-			      "movec %1,%%cacr"
-			      : : "r" (vaddr), "r" (temp));
-		asm volatile ("movec %0,%%caar\n\t"
-			      "movec %1,%%cacr"
-			      : : "r" (vaddr + 4), "r" (temp));
-	}
-}
-
-static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
-	unsigned long usp;
-
-	/* Default to using normal stack.  */
-	usp = rdusp();
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!sas_ss_flags(usp))
-			usp = current->sas_ss_sp + current->sas_ss_size;
-	}
-	return (void __user *)((usp - frame_size) & -8UL);
-}
-
-static int setup_frame (int sig, struct k_sigaction *ka,
-			 sigset_t *set, struct pt_regs *regs)
-{
-	struct sigframe __user *frame;
-	int fsize = frame_extra_sizes[regs->format];
-	struct sigcontext context;
-	int err = 0;
-
-	if (fsize < 0) {
-#ifdef DEBUG
-		printk ("setup_frame: Unknown frame format %#x\n",
-			regs->format);
-#endif
-		goto give_sigsegv;
-	}
-
-	frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
-
-	if (fsize)
-		err |= copy_to_user (frame + 1, regs + 1, fsize);
-
-	err |= __put_user((current_thread_info()->exec_domain
-			   && current_thread_info()->exec_domain->signal_invmap
-			   && sig < 32
-			   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
-
-	err |= __put_user(regs->vector, &frame->code);
-	err |= __put_user(&frame->sc, &frame->psc);
-
-	if (_NSIG_WORDS > 1)
-		err |= copy_to_user(frame->extramask, &set->sig[1],
-				    sizeof(frame->extramask));
-
-	setup_sigcontext(&context, regs, set->sig[0]);
-	err |= copy_to_user (&frame->sc, &context, sizeof(context));
-
-	/* Set up to return from userspace.  */
-	err |= __put_user(frame->retcode, &frame->pretcode);
-	/* moveq #,d0; trap #0 */
-	err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
-			  (long __user *)(frame->retcode));
-
-	if (err)
-		goto give_sigsegv;
-
-	push_cache ((unsigned long) &frame->retcode);
-
-	/*
-	 * Set up registers for signal handler.  All the state we are about
-	 * to destroy is successfully copied to sigframe.
-	 */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
-
-	/*
-	 * This is subtle; if we build more than one sigframe, all but the
-	 * first one will see frame format 0 and have fsize == 0, so we won't
-	 * screw stkadj.
-	 */
-	if (fsize)
-		regs->stkadj = fsize;
-
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
-#ifdef DEBUG
-		printk("Performing stackadjust=%04x\n", regs->stkadj);
-#endif
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
-		tregs->vector = 0;
-		tregs->format = 0;
-		tregs->pc = regs->pc;
-		tregs->sr = regs->sr;
-	}
-	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return err;
-}
-
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
-			    sigset_t *set, struct pt_regs *regs)
-{
-	struct rt_sigframe __user *frame;
-	int fsize = frame_extra_sizes[regs->format];
-	int err = 0;
-
-	if (fsize < 0) {
-#ifdef DEBUG
-		printk ("setup_frame: Unknown frame format %#x\n",
-			regs->format);
-#endif
-		goto give_sigsegv;
-	}
-
-	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	if (fsize)
-		err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
-
-	err |= __put_user((current_thread_info()->exec_domain
-			   && current_thread_info()->exec_domain->signal_invmap
-			   && sig < 32
-			   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
-
-	/* Create the ucontext.  */
-	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(NULL, &frame->uc.uc_link);
-	err |= __put_user((void __user *)current->sas_ss_sp,
-			  &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(rdusp()),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= rt_setup_ucontext(&frame->uc, regs);
-	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
-
-	/* Set up to return from userspace.  */
-	err |= __put_user(frame->retcode, &frame->pretcode);
-#ifdef __mcoldfire__
-	/* movel #__NR_rt_sigreturn,d0; trap #0 */
-	err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
-	err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
-			  (long __user *)(frame->retcode + 4));
+#ifdef CONFIG_MMU
+#include "signal_mm.c"
 #else
-	/* moveq #,d0; notb d0; trap #0 */
-	err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
-			  (long __user *)(frame->retcode + 0));
-	err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
-#endif
-
-	if (err)
-		goto give_sigsegv;
-
-	push_cache ((unsigned long) &frame->retcode);
-
-	/*
-	 * Set up registers for signal handler.  All the state we are about
-	 * to destroy is successfully copied to sigframe.
-	 */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
-
-	/*
-	 * This is subtle; if we build more than one sigframe, all but the
-	 * first one will see frame format 0 and have fsize == 0, so we won't
-	 * screw stkadj.
-	 */
-	if (fsize)
-		regs->stkadj = fsize;
-
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
-#ifdef DEBUG
-		printk("Performing stackadjust=%04x\n", regs->stkadj);
+#include "signal_no.c"
 #endif
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
-		tregs->vector = 0;
-		tregs->format = 0;
-		tregs->pc = regs->pc;
-		tregs->sr = regs->sr;
-	}
-	return 0;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	return err;
-}
-
-static inline void
-handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
-{
-	switch (regs->d0) {
-	case -ERESTARTNOHAND:
-		if (!has_handler)
-			goto do_restart;
-		regs->d0 = -EINTR;
-		break;
-
-	case -ERESTART_RESTARTBLOCK:
-		if (!has_handler) {
-			regs->d0 = __NR_restart_syscall;
-			regs->pc -= 2;
-			break;
-		}
-		regs->d0 = -EINTR;
-		break;
-
-	case -ERESTARTSYS:
-		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
-			regs->d0 = -EINTR;
-			break;
-		}
-	/* fallthrough */
-	case -ERESTARTNOINTR:
-	do_restart:
-		regs->d0 = regs->orig_d0;
-		regs->pc -= 2;
-		break;
-	}
-}
-
-void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
-{
-	if (regs->orig_d0 < 0)
-		return;
-	switch (regs->d0) {
-	case -ERESTARTNOHAND:
-	case -ERESTARTSYS:
-	case -ERESTARTNOINTR:
-		regs->d0 = regs->orig_d0;
-		regs->orig_d0 = -1;
-		regs->pc -= 2;
-		break;
-	}
-}
-
-/*
- * OK, we're invoking a handler
- */
-static void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-	      sigset_t *oldset, struct pt_regs *regs)
-{
-	int err;
-	/* are we from a system call? */
-	if (regs->orig_d0 >= 0)
-		/* If so, check system call restarting.. */
-		handle_restart(regs, ka, 1);
-
-	/* set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		err = setup_rt_frame(sig, ka, info, oldset, regs);
-	else
-		err = setup_frame(sig, ka, oldset, regs);
-
-	if (err)
-		return;
-
-	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-	if (!(ka->sa.sa_flags & SA_NODEFER))
-		sigaddset(&current->blocked,sig);
-	recalc_sigpending();
-
-	if (test_thread_flag(TIF_DELAYED_TRACE)) {
-		regs->sr &= ~0x8000;
-		send_sig(SIGTRAP, current, 1);
-	}
-
-	clear_thread_flag(TIF_RESTORE_SIGMASK);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-asmlinkage void do_signal(struct pt_regs *regs)
-{
-	siginfo_t info;
-	struct k_sigaction ka;
-	int signr;
-	sigset_t *oldset;
-
-	current->thread.esp0 = (unsigned long) regs;
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, oldset, regs);
-		return;
-	}
-
-	/* Did we come from a system call? */
-	if (regs->orig_d0 >= 0)
-		/* Restart the system call - no handlers present */
-		handle_restart(regs, NULL, 0);
-
-	/* If there's no signal to deliver, we just restore the saved mask.  */
-	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
-		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/signal_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/signal_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/signal_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/signal_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1017 @@
+/*
+ *  linux/arch/m68k/kernel/signal.c
+ *
+ *  Copyright (C) 1991, 1992  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.
+ */
+
+/*
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ *
+ * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ *  (Note: fpstate in the signal context is completely ignored for the emulator
+ *         and the internal floating point format is put on stack)
+ */
+
+/*
+ * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
+ * Atari :-) Current limitation: Only one sigstack can be active at one time.
+ * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
+ * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
+ * signal handlers!
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/highuid.h>
+#include <linux/personality.h>
+#include <linux/tty.h>
+#include <linux/binfmts.h>
+#include <linux/module.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+static const int frame_extra_sizes[16] = {
+  [1]	= -1, /* sizeof(((struct frame *)0)->un.fmt1), */
+  [2]	= sizeof(((struct frame *)0)->un.fmt2),
+  [3]	= sizeof(((struct frame *)0)->un.fmt3),
+  [4]	= sizeof(((struct frame *)0)->un.fmt4),
+  [5]	= -1, /* sizeof(((struct frame *)0)->un.fmt5), */
+  [6]	= -1, /* sizeof(((struct frame *)0)->un.fmt6), */
+  [7]	= sizeof(((struct frame *)0)->un.fmt7),
+  [8]	= -1, /* sizeof(((struct frame *)0)->un.fmt8), */
+  [9]	= sizeof(((struct frame *)0)->un.fmt9),
+  [10]	= sizeof(((struct frame *)0)->un.fmta),
+  [11]	= sizeof(((struct frame *)0)->un.fmtb),
+  [12]	= -1, /* sizeof(((struct frame *)0)->un.fmtc), */
+  [13]	= -1, /* sizeof(((struct frame *)0)->un.fmtd), */
+  [14]	= -1, /* sizeof(((struct frame *)0)->un.fmte), */
+  [15]	= -1, /* sizeof(((struct frame *)0)->un.fmtf), */
+};
+
+int handle_kernel_fault(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+	struct pt_regs *tregs;
+
+	/* Are we prepared to handle this kernel fault? */
+	fixup = search_exception_tables(regs->pc);
+	if (!fixup)
+		return 0;
+
+	/* Create a new four word stack frame, discarding the old one. */
+	regs->stkadj = frame_extra_sizes[regs->format];
+	tregs =	(struct pt_regs *)((long)regs + regs->stkadj);
+	tregs->vector = regs->vector;
+	tregs->format = 0;
+	tregs->pc = fixup->fixup;
+	tregs->sr = regs->sr;
+
+	return 1;
+}
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
+{
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sighand->siglock);
+	current->saved_sigmask = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_restore_sigmask();
+
+	return -ERESTARTNOHAND;
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+	      struct old_sigaction __user *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) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
+			return -EFAULT;
+		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) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+	return do_sigaltstack(uss, uoss, rdusp());
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
+ */
+
+struct sigframe
+{
+	char __user *pretcode;
+	int sig;
+	int code;
+	struct sigcontext __user *psc;
+	char retcode[8];
+	unsigned long extramask[_NSIG_WORDS-1];
+	struct sigcontext sc;
+};
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	char retcode[8];
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+
+static unsigned char fpu_version;	/* version number of fpu, set by setup_frame */
+
+static inline int restore_fpu_state(struct sigcontext *sc)
+{
+	int err = 1;
+
+	if (FPU_IS_EMU) {
+	    /* restore registers */
+	    memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+	    memcpy(current->thread.fp, sc->sc_fpregs, 24);
+	    return 0;
+	}
+
+	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
+	    /* Verify the frame format.  */
+	    if (!CPU_IS_060 && (sc->sc_fpstate[0] != fpu_version))
+		goto out;
+	    if (CPU_IS_020_OR_030) {
+		if (m68k_fputype & FPU_68881 &&
+		    !(sc->sc_fpstate[1] == 0x18 || sc->sc_fpstate[1] == 0xb4))
+		    goto out;
+		if (m68k_fputype & FPU_68882 &&
+		    !(sc->sc_fpstate[1] == 0x38 || sc->sc_fpstate[1] == 0xd4))
+		    goto out;
+	    } else if (CPU_IS_040) {
+		if (!(sc->sc_fpstate[1] == 0x00 ||
+                      sc->sc_fpstate[1] == 0x28 ||
+                      sc->sc_fpstate[1] == 0x60))
+		    goto out;
+	    } else if (CPU_IS_060) {
+		if (!(sc->sc_fpstate[3] == 0x00 ||
+                      sc->sc_fpstate[3] == 0x60 ||
+		      sc->sc_fpstate[3] == 0xe0))
+		    goto out;
+	    } else
+		goto out;
+
+	    __asm__ volatile (".chip 68k/68881\n\t"
+			      "fmovemx %0,%%fp0-%%fp1\n\t"
+			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
+			      ".chip 68k"
+			      : /* no outputs */
+			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
+	}
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "frestore %0\n\t"
+			  ".chip 68k" : : "m" (*sc->sc_fpstate));
+	err = 0;
+
+out:
+	return err;
+}
+
+#define FPCONTEXT_SIZE	216
+#define uc_fpstate	uc_filler[0]
+#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4]
+#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1]
+
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
+{
+	unsigned char fpstate[FPCONTEXT_SIZE];
+	int context_size = CPU_IS_060 ? 8 : 0;
+	fpregset_t fpregs;
+	int err = 1;
+
+	if (FPU_IS_EMU) {
+		/* restore fpu control register */
+		if (__copy_from_user(current->thread.fpcntl,
+				uc->uc_mcontext.fpregs.f_fpcntl, 12))
+			goto out;
+		/* restore all other fpu register */
+		if (__copy_from_user(current->thread.fp,
+				uc->uc_mcontext.fpregs.f_fpregs, 96))
+			goto out;
+		return 0;
+	}
+
+	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
+		goto out;
+	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
+		if (!CPU_IS_060)
+			context_size = fpstate[1];
+		/* Verify the frame format.  */
+		if (!CPU_IS_060 && (fpstate[0] != fpu_version))
+			goto out;
+		if (CPU_IS_020_OR_030) {
+			if (m68k_fputype & FPU_68881 &&
+			    !(context_size == 0x18 || context_size == 0xb4))
+				goto out;
+			if (m68k_fputype & FPU_68882 &&
+			    !(context_size == 0x38 || context_size == 0xd4))
+				goto out;
+		} else if (CPU_IS_040) {
+			if (!(context_size == 0x00 ||
+			      context_size == 0x28 ||
+			      context_size == 0x60))
+				goto out;
+		} else if (CPU_IS_060) {
+			if (!(fpstate[3] == 0x00 ||
+			      fpstate[3] == 0x60 ||
+			      fpstate[3] == 0xe0))
+				goto out;
+		} else
+			goto out;
+		if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
+				     sizeof(fpregs)))
+			goto out;
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %0,%%fp0-%%fp7\n\t"
+				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
+				  ".chip 68k"
+				  : /* no outputs */
+				  : "m" (*fpregs.f_fpregs),
+				    "m" (*fpregs.f_fpcntl));
+	}
+	if (context_size &&
+	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
+			     context_size))
+		goto out;
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "frestore %0\n\t"
+			  ".chip 68k" : : "m" (*fpstate));
+	err = 0;
+
+out:
+	return err;
+}
+
+static int mangle_kernel_stack(struct pt_regs *regs, int formatvec,
+			       void __user *fp)
+{
+	int fsize = frame_extra_sizes[formatvec >> 12];
+	if (fsize < 0) {
+		/*
+		 * user process trying to return with weird frame format
+		 */
+#ifdef DEBUG
+		printk("user process returning with weird frame format\n");
+#endif
+		return 1;
+	}
+	if (!fsize) {
+		regs->format = formatvec >> 12;
+		regs->vector = formatvec & 0xfff;
+	} else {
+		struct switch_stack *sw = (struct switch_stack *)regs - 1;
+		unsigned long buf[fsize / 2]; /* yes, twice as much */
+
+		/* that'll make sure that expansion won't crap over data */
+		if (copy_from_user(buf + fsize / 4, fp, fsize))
+			return 1;
+
+		/* point of no return */
+		regs->format = formatvec >> 12;
+		regs->vector = formatvec & 0xfff;
+#define frame_offset (sizeof(struct pt_regs)+sizeof(struct switch_stack))
+		__asm__ __volatile__
+			("   movel %0,%/a0\n\t"
+			 "   subl %1,%/a0\n\t"     /* make room on stack */
+			 "   movel %/a0,%/sp\n\t"  /* set stack pointer */
+			 /* move switch_stack and pt_regs */
+			 "1: movel %0@+,%/a0@+\n\t"
+			 "   dbra %2,1b\n\t"
+			 "   lea %/sp@(%c3),%/a0\n\t" /* add offset of fmt */
+			 "   lsrl  #2,%1\n\t"
+			 "   subql #1,%1\n\t"
+			 /* copy to the gap we'd made */
+			 "2: movel %4@+,%/a0@+\n\t"
+			 "   dbra %1,2b\n\t"
+			 "   bral ret_from_signal\n"
+			 : /* no outputs, it doesn't ever return */
+			 : "a" (sw), "d" (fsize), "d" (frame_offset/4-1),
+			   "n" (frame_offset), "a" (buf + fsize/4)
+			 : "a0");
+#undef frame_offset
+	}
+	return 0;
+}
+
+static inline int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp)
+{
+	int formatvec;
+	struct sigcontext context;
+	int err;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/* get previous context */
+	if (copy_from_user(&context, usc, sizeof(context)))
+		goto badframe;
+
+	/* restore passed registers */
+	regs->d0 = context.sc_d0;
+	regs->d1 = context.sc_d1;
+	regs->a0 = context.sc_a0;
+	regs->a1 = context.sc_a1;
+	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
+	regs->pc = context.sc_pc;
+	regs->orig_d0 = -1;		/* disable syscall checks */
+	wrusp(context.sc_usp);
+	formatvec = context.sc_formatvec;
+
+	err = restore_fpu_state(&context);
+
+	if (err || mangle_kernel_stack(regs, formatvec, fp))
+		goto badframe;
+
+	return 0;
+
+badframe:
+	return 1;
+}
+
+static inline int
+rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
+		    struct ucontext __user *uc)
+{
+	int temp;
+	greg_t __user *gregs = uc->uc_mcontext.gregs;
+	unsigned long usp;
+	int err;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	err = __get_user(temp, &uc->uc_mcontext.version);
+	if (temp != MCONTEXT_VERSION)
+		goto badframe;
+	/* restore passed registers */
+	err |= __get_user(regs->d0, &gregs[0]);
+	err |= __get_user(regs->d1, &gregs[1]);
+	err |= __get_user(regs->d2, &gregs[2]);
+	err |= __get_user(regs->d3, &gregs[3]);
+	err |= __get_user(regs->d4, &gregs[4]);
+	err |= __get_user(regs->d5, &gregs[5]);
+	err |= __get_user(sw->d6, &gregs[6]);
+	err |= __get_user(sw->d7, &gregs[7]);
+	err |= __get_user(regs->a0, &gregs[8]);
+	err |= __get_user(regs->a1, &gregs[9]);
+	err |= __get_user(regs->a2, &gregs[10]);
+	err |= __get_user(sw->a3, &gregs[11]);
+	err |= __get_user(sw->a4, &gregs[12]);
+	err |= __get_user(sw->a5, &gregs[13]);
+	err |= __get_user(sw->a6, &gregs[14]);
+	err |= __get_user(usp, &gregs[15]);
+	wrusp(usp);
+	err |= __get_user(regs->pc, &gregs[16]);
+	err |= __get_user(temp, &gregs[17]);
+	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
+	regs->orig_d0 = -1;		/* disable syscall checks */
+	err |= __get_user(temp, &uc->uc_formatvec);
+
+	err |= rt_restore_fpu_state(uc);
+
+	if (err || do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
+		goto badframe;
+
+	if (mangle_kernel_stack(regs, temp, &uc->uc_extra))
+		goto badframe;
+
+	return 0;
+
+badframe:
+	return 1;
+}
+
+asmlinkage int do_sigreturn(unsigned long __unused)
+{
+	struct switch_stack *sw = (struct switch_stack *) &__unused;
+	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+	unsigned long usp = rdusp();
+	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
+	sigset_t set;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
+	    (_NSIG_WORDS > 1 &&
+	     __copy_from_user(&set.sig[1], &frame->extramask,
+			      sizeof(frame->extramask))))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	current->blocked = set;
+	recalc_sigpending();
+
+	if (restore_sigcontext(regs, &frame->sc, frame + 1))
+		goto badframe;
+	return regs->d0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
+{
+	struct switch_stack *sw = (struct switch_stack *) &__unused;
+	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+	unsigned long usp = rdusp();
+	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
+	sigset_t set;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	current->blocked = set;
+	recalc_sigpending();
+
+	if (rt_restore_ucontext(regs, sw, &frame->uc))
+		goto badframe;
+	return regs->d0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+/*
+ * Set up a signal frame.
+ */
+
+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+	if (FPU_IS_EMU) {
+		/* save registers */
+		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+		memcpy(sc->sc_fpregs, current->thread.fp, 24);
+		return;
+	}
+
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "fsave %0\n\t"
+			  ".chip 68k"
+			  : : "m" (*sc->sc_fpstate) : "memory");
+
+	if (CPU_IS_060 ? sc->sc_fpstate[2] : sc->sc_fpstate[0]) {
+		fpu_version = sc->sc_fpstate[0];
+		if (CPU_IS_020_OR_030 &&
+		    regs->vector >= (VEC_FPBRUC * 4) &&
+		    regs->vector <= (VEC_FPNAN * 4)) {
+			/* Clear pending exception in 68882 idle frame */
+			if (*(unsigned short *) sc->sc_fpstate == 0x1f38)
+				sc->sc_fpstate[0x38] |= 1 << 3;
+		}
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %%fp0-%%fp1,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
+				  ".chip 68k"
+				  : "=m" (*sc->sc_fpregs),
+				    "=m" (*sc->sc_fpcntl)
+				  : /* no inputs */
+				  : "memory");
+	}
+}
+
+static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
+{
+	unsigned char fpstate[FPCONTEXT_SIZE];
+	int context_size = CPU_IS_060 ? 8 : 0;
+	int err = 0;
+
+	if (FPU_IS_EMU) {
+		/* save fpu control register */
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpcntl,
+				current->thread.fpcntl, 12);
+		/* save all other fpu register */
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+				current->thread.fp, 96);
+		return err;
+	}
+
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "fsave %0\n\t"
+			  ".chip 68k"
+			  : : "m" (*fpstate) : "memory");
+
+	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
+	if (CPU_IS_060 ? fpstate[2] : fpstate[0]) {
+		fpregset_t fpregs;
+		if (!CPU_IS_060)
+			context_size = fpstate[1];
+		fpu_version = fpstate[0];
+		if (CPU_IS_020_OR_030 &&
+		    regs->vector >= (VEC_FPBRUC * 4) &&
+		    regs->vector <= (VEC_FPNAN * 4)) {
+			/* Clear pending exception in 68882 idle frame */
+			if (*(unsigned short *) fpstate == 0x1f38)
+				fpstate[0x38] |= 1 << 3;
+		}
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %%fp0-%%fp7,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
+				  ".chip 68k"
+				  : "=m" (*fpregs.f_fpregs),
+				    "=m" (*fpregs.f_fpcntl)
+				  : /* no inputs */
+				  : "memory");
+		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
+				    sizeof(fpregs));
+	}
+	if (context_size)
+		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
+				    context_size);
+	return err;
+}
+
+static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+			     unsigned long mask)
+{
+	sc->sc_mask = mask;
+	sc->sc_usp = rdusp();
+	sc->sc_d0 = regs->d0;
+	sc->sc_d1 = regs->d1;
+	sc->sc_a0 = regs->a0;
+	sc->sc_a1 = regs->a1;
+	sc->sc_sr = regs->sr;
+	sc->sc_pc = regs->pc;
+	sc->sc_formatvec = regs->format << 12 | regs->vector;
+	save_fpu_state(sc, regs);
+}
+
+static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	greg_t __user *gregs = uc->uc_mcontext.gregs;
+	int err = 0;
+
+	err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+	err |= __put_user(regs->d0, &gregs[0]);
+	err |= __put_user(regs->d1, &gregs[1]);
+	err |= __put_user(regs->d2, &gregs[2]);
+	err |= __put_user(regs->d3, &gregs[3]);
+	err |= __put_user(regs->d4, &gregs[4]);
+	err |= __put_user(regs->d5, &gregs[5]);
+	err |= __put_user(sw->d6, &gregs[6]);
+	err |= __put_user(sw->d7, &gregs[7]);
+	err |= __put_user(regs->a0, &gregs[8]);
+	err |= __put_user(regs->a1, &gregs[9]);
+	err |= __put_user(regs->a2, &gregs[10]);
+	err |= __put_user(sw->a3, &gregs[11]);
+	err |= __put_user(sw->a4, &gregs[12]);
+	err |= __put_user(sw->a5, &gregs[13]);
+	err |= __put_user(sw->a6, &gregs[14]);
+	err |= __put_user(rdusp(), &gregs[15]);
+	err |= __put_user(regs->pc, &gregs[16]);
+	err |= __put_user(regs->sr, &gregs[17]);
+	err |= __put_user((regs->format << 12) | regs->vector, &uc->uc_formatvec);
+	err |= rt_save_fpu_state(uc, regs);
+	return err;
+}
+
+static inline void push_cache (unsigned long vaddr)
+{
+	/*
+	 * Using the old cache_push_v() was really a big waste.
+	 *
+	 * What we are trying to do is to flush 8 bytes to ram.
+	 * Flushing 2 cache lines of 16 bytes is much cheaper than
+	 * flushing 1 or 2 pages, as previously done in
+	 * cache_push_v().
+	 *                                                     Jes
+	 */
+	if (CPU_IS_040) {
+		unsigned long temp;
+
+		__asm__ __volatile__ (".chip 68040\n\t"
+				      "nop\n\t"
+				      "ptestr (%1)\n\t"
+				      "movec %%mmusr,%0\n\t"
+				      ".chip 68k"
+				      : "=r" (temp)
+				      : "a" (vaddr));
+
+		temp &= PAGE_MASK;
+		temp |= vaddr & ~PAGE_MASK;
+
+		__asm__ __volatile__ (".chip 68040\n\t"
+				      "nop\n\t"
+				      "cpushl %%bc,(%0)\n\t"
+				      ".chip 68k"
+				      : : "a" (temp));
+	}
+	else if (CPU_IS_060) {
+		unsigned long temp;
+		__asm__ __volatile__ (".chip 68060\n\t"
+				      "plpar (%0)\n\t"
+				      ".chip 68k"
+				      : "=a" (temp)
+				      : "0" (vaddr));
+		__asm__ __volatile__ (".chip 68060\n\t"
+				      "cpushl %%bc,(%0)\n\t"
+				      ".chip 68k"
+				      : : "a" (temp));
+	}
+	else {
+		/*
+		 * 68030/68020 have no writeback cache;
+		 * still need to clear icache.
+		 * Note that vaddr is guaranteed to be long word aligned.
+		 */
+		unsigned long temp;
+		asm volatile ("movec %%cacr,%0" : "=r" (temp));
+		temp += 4;
+		asm volatile ("movec %0,%%caar\n\t"
+			      "movec %1,%%cacr"
+			      : : "r" (vaddr), "r" (temp));
+		asm volatile ("movec %0,%%caar\n\t"
+			      "movec %1,%%cacr"
+			      : : "r" (vaddr + 4), "r" (temp));
+	}
+}
+
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+	unsigned long usp;
+
+	/* Default to using normal stack.  */
+	usp = rdusp();
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (!sas_ss_flags(usp))
+			usp = current->sas_ss_sp + current->sas_ss_size;
+	}
+	return (void __user *)((usp - frame_size) & -8UL);
+}
+
+static int setup_frame (int sig, struct k_sigaction *ka,
+			 sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe __user *frame;
+	int fsize = frame_extra_sizes[regs->format];
+	struct sigcontext context;
+	int err = 0;
+
+	if (fsize < 0) {
+#ifdef DEBUG
+		printk ("setup_frame: Unknown frame format %#x\n",
+			regs->format);
+#endif
+		goto give_sigsegv;
+	}
+
+	frame = get_sigframe(ka, regs, sizeof(*frame) + fsize);
+
+	if (fsize)
+		err |= copy_to_user (frame + 1, regs + 1, fsize);
+
+	err |= __put_user((current_thread_info()->exec_domain
+			   && current_thread_info()->exec_domain->signal_invmap
+			   && sig < 32
+			   ? current_thread_info()->exec_domain->signal_invmap[sig]
+			   : sig),
+			  &frame->sig);
+
+	err |= __put_user(regs->vector, &frame->code);
+	err |= __put_user(&frame->sc, &frame->psc);
+
+	if (_NSIG_WORDS > 1)
+		err |= copy_to_user(frame->extramask, &set->sig[1],
+				    sizeof(frame->extramask));
+
+	setup_sigcontext(&context, regs, set->sig[0]);
+	err |= copy_to_user (&frame->sc, &context, sizeof(context));
+
+	/* Set up to return from userspace.  */
+	err |= __put_user(frame->retcode, &frame->pretcode);
+	/* moveq #,d0; trap #0 */
+	err |= __put_user(0x70004e40 + (__NR_sigreturn << 16),
+			  (long __user *)(frame->retcode));
+
+	if (err)
+		goto give_sigsegv;
+
+	push_cache ((unsigned long) &frame->retcode);
+
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
+	wrusp ((unsigned long) frame);
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+
+	/*
+	 * This is subtle; if we build more than one sigframe, all but the
+	 * first one will see frame format 0 and have fsize == 0, so we won't
+	 * screw stkadj.
+	 */
+	if (fsize)
+		regs->stkadj = fsize;
+
+	/* Prepare to skip over the extra stuff in the exception frame.  */
+	if (regs->stkadj) {
+		struct pt_regs *tregs =
+			(struct pt_regs *)((ulong)regs + regs->stkadj);
+#ifdef DEBUG
+		printk("Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+		/* This must be copied with decreasing addresses to
+                   handle overlaps.  */
+		tregs->vector = 0;
+		tregs->format = 0;
+		tregs->pc = regs->pc;
+		tregs->sr = regs->sr;
+	}
+	return 0;
+
+give_sigsegv:
+	force_sigsegv(sig, current);
+	return err;
+}
+
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+			    sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	int fsize = frame_extra_sizes[regs->format];
+	int err = 0;
+
+	if (fsize < 0) {
+#ifdef DEBUG
+		printk ("setup_frame: Unknown frame format %#x\n",
+			regs->format);
+#endif
+		goto give_sigsegv;
+	}
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	if (fsize)
+		err |= copy_to_user (&frame->uc.uc_extra, regs + 1, fsize);
+
+	err |= __put_user((current_thread_info()->exec_domain
+			   && current_thread_info()->exec_domain->signal_invmap
+			   && sig < 32
+			   ? current_thread_info()->exec_domain->signal_invmap[sig]
+			   : sig),
+			  &frame->sig);
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void __user *)current->sas_ss_sp,
+			  &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(rdusp()),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= rt_setup_ucontext(&frame->uc, regs);
+	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	/* Set up to return from userspace.  */
+	err |= __put_user(frame->retcode, &frame->pretcode);
+#ifdef __mcoldfire__
+	/* movel #__NR_rt_sigreturn,d0; trap #0 */
+	err |= __put_user(0x203c0000, (long __user *)(frame->retcode + 0));
+	err |= __put_user(0x00004e40 + (__NR_rt_sigreturn << 16),
+			  (long __user *)(frame->retcode + 4));
+#else
+	/* moveq #,d0; notb d0; trap #0 */
+	err |= __put_user(0x70004600 + ((__NR_rt_sigreturn ^ 0xff) << 16),
+			  (long __user *)(frame->retcode + 0));
+	err |= __put_user(0x4e40, (short __user *)(frame->retcode + 4));
+#endif
+
+	if (err)
+		goto give_sigsegv;
+
+	push_cache ((unsigned long) &frame->retcode);
+
+	/*
+	 * Set up registers for signal handler.  All the state we are about
+	 * to destroy is successfully copied to sigframe.
+	 */
+	wrusp ((unsigned long) frame);
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+
+	/*
+	 * This is subtle; if we build more than one sigframe, all but the
+	 * first one will see frame format 0 and have fsize == 0, so we won't
+	 * screw stkadj.
+	 */
+	if (fsize)
+		regs->stkadj = fsize;
+
+	/* Prepare to skip over the extra stuff in the exception frame.  */
+	if (regs->stkadj) {
+		struct pt_regs *tregs =
+			(struct pt_regs *)((ulong)regs + regs->stkadj);
+#ifdef DEBUG
+		printk("Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+		/* This must be copied with decreasing addresses to
+                   handle overlaps.  */
+		tregs->vector = 0;
+		tregs->format = 0;
+		tregs->pc = regs->pc;
+		tregs->sr = regs->sr;
+	}
+	return 0;
+
+give_sigsegv:
+	force_sigsegv(sig, current);
+	return err;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+	switch (regs->d0) {
+	case -ERESTARTNOHAND:
+		if (!has_handler)
+			goto do_restart;
+		regs->d0 = -EINTR;
+		break;
+
+	case -ERESTART_RESTARTBLOCK:
+		if (!has_handler) {
+			regs->d0 = __NR_restart_syscall;
+			regs->pc -= 2;
+			break;
+		}
+		regs->d0 = -EINTR;
+		break;
+
+	case -ERESTARTSYS:
+		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+			regs->d0 = -EINTR;
+			break;
+		}
+	/* fallthrough */
+	case -ERESTARTNOINTR:
+	do_restart:
+		regs->d0 = regs->orig_d0;
+		regs->pc -= 2;
+		break;
+	}
+}
+
+void ptrace_signal_deliver(struct pt_regs *regs, void *cookie)
+{
+	if (regs->orig_d0 < 0)
+		return;
+	switch (regs->d0) {
+	case -ERESTARTNOHAND:
+	case -ERESTARTSYS:
+	case -ERESTARTNOINTR:
+		regs->d0 = regs->orig_d0;
+		regs->orig_d0 = -1;
+		regs->pc -= 2;
+		break;
+	}
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void
+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
+	      sigset_t *oldset, struct pt_regs *regs)
+{
+	int err;
+	/* are we from a system call? */
+	if (regs->orig_d0 >= 0)
+		/* If so, check system call restarting.. */
+		handle_restart(regs, ka, 1);
+
+	/* set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		err = setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		err = setup_frame(sig, ka, oldset, regs);
+
+	if (err)
+		return;
+
+	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&current->blocked,sig);
+	recalc_sigpending();
+
+	if (test_thread_flag(TIF_DELAYED_TRACE)) {
+		regs->sr &= ~0x8000;
+		send_sig(SIGTRAP, current, 1);
+	}
+
+	clear_thread_flag(TIF_RESTORE_SIGMASK);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+asmlinkage void do_signal(struct pt_regs *regs)
+{
+	siginfo_t info;
+	struct k_sigaction ka;
+	int signr;
+	sigset_t *oldset;
+
+	current->thread.esp0 = (unsigned long) regs;
+
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, &ka, &info, oldset, regs);
+		return;
+	}
+
+	/* Did we come from a system call? */
+	if (regs->orig_d0 >= 0)
+		/* Restart the system call - no handlers present */
+		handle_restart(regs, NULL, 0);
+
+	/* If there's no signal to deliver, we just restore the saved mask.  */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/signal_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/signal_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/signal_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/signal_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,765 @@
+/*
+ *  linux/arch/m68knommu/kernel/signal.c
+ *
+ *  Copyright (C) 1991, 1992  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.
+ */
+
+/*
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ *
+ * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
+ *
+ * mathemu support by Roman Zippel
+ *  (Note: fpstate in the signal context is completely ignored for the emulator
+ *         and the internal floating point format is put on stack)
+ */
+
+/*
+ * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
+ * Atari :-) Current limitation: Only one sigstack can be active at one time.
+ * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
+ * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
+ * signal handlers!
+ */
+
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/syscalls.h>
+#include <linux/errno.h>
+#include <linux/wait.h>
+#include <linux/ptrace.h>
+#include <linux/unistd.h>
+#include <linux/stddef.h>
+#include <linux/highuid.h>
+#include <linux/tty.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/pgtable.h>
+#include <asm/traps.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+void ret_from_user_signal(void);
+void ret_from_user_rt_signal(void);
+
+/*
+ * Atomically swap in the new signal mask, and wait for a signal.
+ */
+asmlinkage int
+sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
+{
+	mask &= _BLOCKABLE;
+	spin_lock_irq(&current->sighand->siglock);
+	current->saved_sigmask = current->blocked;
+	siginitset(&current->blocked, mask);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	current->state = TASK_INTERRUPTIBLE;
+	schedule();
+	set_restore_sigmask();
+
+	return -ERESTARTNOHAND;
+}
+
+asmlinkage int
+sys_sigaction(int sig, const struct old_sigaction __user *act,
+	      struct old_sigaction __user *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) ||
+		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
+		    __get_user(mask, &act->sa_mask))
+			return -EFAULT;
+		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) ||
+		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
+		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
+			return -EFAULT;
+	}
+
+	return ret;
+}
+
+asmlinkage int
+sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
+{
+	return do_sigaltstack(uss, uoss, rdusp());
+}
+
+
+/*
+ * Do a signal return; undo the signal stack.
+ *
+ * Keep the return code on the stack quadword aligned!
+ * That makes the cache flush below easier.
+ */
+
+struct sigframe
+{
+	char __user *pretcode;
+	int sig;
+	int code;
+	struct sigcontext __user *psc;
+	char retcode[8];
+	unsigned long extramask[_NSIG_WORDS-1];
+	struct sigcontext sc;
+};
+
+struct rt_sigframe
+{
+	char __user *pretcode;
+	int sig;
+	struct siginfo __user *pinfo;
+	void __user *puc;
+	char retcode[8];
+	struct siginfo info;
+	struct ucontext uc;
+};
+
+#ifdef CONFIG_FPU
+
+static unsigned char fpu_version = 0;	/* version number of fpu, set by setup_frame */
+
+static inline int restore_fpu_state(struct sigcontext *sc)
+{
+	int err = 1;
+
+	if (FPU_IS_EMU) {
+	    /* restore registers */
+	    memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
+	    memcpy(current->thread.fp, sc->sc_fpregs, 24);
+	    return 0;
+	}
+
+	if (sc->sc_fpstate[0]) {
+	    /* Verify the frame format.  */
+	    if (sc->sc_fpstate[0] != fpu_version)
+		goto out;
+
+	    __asm__ volatile (".chip 68k/68881\n\t"
+			      "fmovemx %0,%%fp0-%%fp1\n\t"
+			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
+			      ".chip 68k"
+			      : /* no outputs */
+			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
+	}
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "frestore %0\n\t"
+			  ".chip 68k" : : "m" (*sc->sc_fpstate));
+	err = 0;
+
+out:
+	return err;
+}
+
+#define FPCONTEXT_SIZE	216
+#define uc_fpstate	uc_filler[0]
+#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4]
+#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1]
+
+static inline int rt_restore_fpu_state(struct ucontext __user *uc)
+{
+	unsigned char fpstate[FPCONTEXT_SIZE];
+	int context_size = 0;
+	fpregset_t fpregs;
+	int err = 1;
+
+	if (FPU_IS_EMU) {
+		/* restore fpu control register */
+		if (__copy_from_user(current->thread.fpcntl,
+				uc->uc_mcontext.fpregs.f_fpcntl, 12))
+			goto out;
+		/* restore all other fpu register */
+		if (__copy_from_user(current->thread.fp,
+				uc->uc_mcontext.fpregs.f_fpregs, 96))
+			goto out;
+		return 0;
+	}
+
+	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
+		goto out;
+	if (fpstate[0]) {
+		context_size = fpstate[1];
+
+		/* Verify the frame format.  */
+		if (fpstate[0] != fpu_version)
+			goto out;
+		if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
+		     sizeof(fpregs)))
+			goto out;
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %0,%%fp0-%%fp7\n\t"
+				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
+				  ".chip 68k"
+				  : /* no outputs */
+				  : "m" (*fpregs.f_fpregs),
+				    "m" (*fpregs.f_fpcntl));
+	}
+	if (context_size &&
+	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
+			     context_size))
+		goto out;
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "frestore %0\n\t"
+			  ".chip 68k" : : "m" (*fpstate));
+	err = 0;
+
+out:
+	return err;
+}
+
+#endif
+
+static inline int
+restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
+		   int *pd0)
+{
+	int formatvec;
+	struct sigcontext context;
+	int err = 0;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/* get previous context */
+	if (copy_from_user(&context, usc, sizeof(context)))
+		goto badframe;
+	
+	/* restore passed registers */
+	regs->d1 = context.sc_d1;
+	regs->a0 = context.sc_a0;
+	regs->a1 = context.sc_a1;
+	((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
+	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
+	regs->pc = context.sc_pc;
+	regs->orig_d0 = -1;		/* disable syscall checks */
+	wrusp(context.sc_usp);
+	formatvec = context.sc_formatvec;
+	regs->format = formatvec >> 12;
+	regs->vector = formatvec & 0xfff;
+
+#ifdef CONFIG_FPU
+	err = restore_fpu_state(&context);
+#endif
+
+	*pd0 = context.sc_d0;
+	return err;
+
+badframe:
+	return 1;
+}
+
+static inline int
+rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
+		    struct ucontext __user *uc, int *pd0)
+{
+	int temp;
+	greg_t __user *gregs = uc->uc_mcontext.gregs;
+	unsigned long usp;
+	int err;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	err = __get_user(temp, &uc->uc_mcontext.version);
+	if (temp != MCONTEXT_VERSION)
+		goto badframe;
+	/* restore passed registers */
+	err |= __get_user(regs->d0, &gregs[0]);
+	err |= __get_user(regs->d1, &gregs[1]);
+	err |= __get_user(regs->d2, &gregs[2]);
+	err |= __get_user(regs->d3, &gregs[3]);
+	err |= __get_user(regs->d4, &gregs[4]);
+	err |= __get_user(regs->d5, &gregs[5]);
+	err |= __get_user(sw->d6, &gregs[6]);
+	err |= __get_user(sw->d7, &gregs[7]);
+	err |= __get_user(regs->a0, &gregs[8]);
+	err |= __get_user(regs->a1, &gregs[9]);
+	err |= __get_user(regs->a2, &gregs[10]);
+	err |= __get_user(sw->a3, &gregs[11]);
+	err |= __get_user(sw->a4, &gregs[12]);
+	err |= __get_user(sw->a5, &gregs[13]);
+	err |= __get_user(sw->a6, &gregs[14]);
+	err |= __get_user(usp, &gregs[15]);
+	wrusp(usp);
+	err |= __get_user(regs->pc, &gregs[16]);
+	err |= __get_user(temp, &gregs[17]);
+	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
+	regs->orig_d0 = -1;		/* disable syscall checks */
+	regs->format = temp >> 12;
+	regs->vector = temp & 0xfff;
+
+	if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
+		goto badframe;
+
+	*pd0 = regs->d0;
+	return err;
+
+badframe:
+	return 1;
+}
+
+asmlinkage int do_sigreturn(unsigned long __unused)
+{
+	struct switch_stack *sw = (struct switch_stack *) &__unused;
+	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+	unsigned long usp = rdusp();
+	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
+	sigset_t set;
+	int d0;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
+	    (_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, frame + 1, &d0))
+		goto badframe;
+	return d0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+asmlinkage int do_rt_sigreturn(unsigned long __unused)
+{
+	struct switch_stack *sw = (struct switch_stack *) &__unused;
+	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
+	unsigned long usp = rdusp();
+	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
+	sigset_t set;
+	int d0;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
+		goto badframe;
+
+	sigdelsetmask(&set, ~_BLOCKABLE);
+	spin_lock_irq(&current->sighand->siglock);
+	current->blocked = set;
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+	
+	if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
+		goto badframe;
+	return d0;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+#ifdef CONFIG_FPU
+/*
+ * Set up a signal frame.
+ */
+
+static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
+{
+	if (FPU_IS_EMU) {
+		/* save registers */
+		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
+		memcpy(sc->sc_fpregs, current->thread.fp, 24);
+		return;
+	}
+
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "fsave %0\n\t"
+			  ".chip 68k"
+			  : : "m" (*sc->sc_fpstate) : "memory");
+
+	if (sc->sc_fpstate[0]) {
+		fpu_version = sc->sc_fpstate[0];
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %%fp0-%%fp1,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
+				  ".chip 68k"
+				  : "=m" (*sc->sc_fpregs),
+				    "=m" (*sc->sc_fpcntl)
+				  : /* no inputs */
+				  : "memory");
+	}
+}
+
+static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
+{
+	unsigned char fpstate[FPCONTEXT_SIZE];
+	int context_size = 0;
+	int err = 0;
+
+	if (FPU_IS_EMU) {
+		/* save fpu control register */
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_pcntl,
+				current->thread.fpcntl, 12);
+		/* save all other fpu register */
+		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
+				current->thread.fp, 96);
+		return err;
+	}
+
+	__asm__ volatile (".chip 68k/68881\n\t"
+			  "fsave %0\n\t"
+			  ".chip 68k"
+			  : : "m" (*fpstate) : "memory");
+
+	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
+	if (fpstate[0]) {
+		fpregset_t fpregs;
+		context_size = fpstate[1];
+		fpu_version = fpstate[0];
+		__asm__ volatile (".chip 68k/68881\n\t"
+				  "fmovemx %%fp0-%%fp7,%0\n\t"
+				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
+				  ".chip 68k"
+				  : "=m" (*fpregs.f_fpregs),
+				    "=m" (*fpregs.f_fpcntl)
+				  : /* no inputs */
+				  : "memory");
+		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
+				    sizeof(fpregs));
+	}
+	if (context_size)
+		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
+				    context_size);
+	return err;
+}
+
+#endif
+
+static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
+			     unsigned long mask)
+{
+	sc->sc_mask = mask;
+	sc->sc_usp = rdusp();
+	sc->sc_d0 = regs->d0;
+	sc->sc_d1 = regs->d1;
+	sc->sc_a0 = regs->a0;
+	sc->sc_a1 = regs->a1;
+	sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
+	sc->sc_sr = regs->sr;
+	sc->sc_pc = regs->pc;
+	sc->sc_formatvec = regs->format << 12 | regs->vector;
+#ifdef CONFIG_FPU
+	save_fpu_state(sc, regs);
+#endif
+}
+
+static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
+{
+	struct switch_stack *sw = (struct switch_stack *)regs - 1;
+	greg_t __user *gregs = uc->uc_mcontext.gregs;
+	int err = 0;
+
+	err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
+	err |= __put_user(regs->d0, &gregs[0]);
+	err |= __put_user(regs->d1, &gregs[1]);
+	err |= __put_user(regs->d2, &gregs[2]);
+	err |= __put_user(regs->d3, &gregs[3]);
+	err |= __put_user(regs->d4, &gregs[4]);
+	err |= __put_user(regs->d5, &gregs[5]);
+	err |= __put_user(sw->d6, &gregs[6]);
+	err |= __put_user(sw->d7, &gregs[7]);
+	err |= __put_user(regs->a0, &gregs[8]);
+	err |= __put_user(regs->a1, &gregs[9]);
+	err |= __put_user(regs->a2, &gregs[10]);
+	err |= __put_user(sw->a3, &gregs[11]);
+	err |= __put_user(sw->a4, &gregs[12]);
+	err |= __put_user(sw->a5, &gregs[13]);
+	err |= __put_user(sw->a6, &gregs[14]);
+	err |= __put_user(rdusp(), &gregs[15]);
+	err |= __put_user(regs->pc, &gregs[16]);
+	err |= __put_user(regs->sr, &gregs[17]);
+#ifdef CONFIG_FPU
+	err |= rt_save_fpu_state(uc, regs);
+#endif
+	return err;
+}
+
+static inline void __user *
+get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
+{
+	unsigned long usp;
+
+	/* Default to using normal stack.  */
+	usp = rdusp();
+
+	/* This is the X/Open sanctioned signal stack switching.  */
+	if (ka->sa.sa_flags & SA_ONSTACK) {
+		if (!sas_ss_flags(usp))
+			usp = current->sas_ss_sp + current->sas_ss_size;
+	}
+	return (void __user *)((usp - frame_size) & -8UL);
+}
+
+static int setup_frame (int sig, struct k_sigaction *ka,
+			 sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe __user *frame;
+	struct sigcontext context;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	err |= __put_user((current_thread_info()->exec_domain
+			   && current_thread_info()->exec_domain->signal_invmap
+			   && sig < 32
+			   ? current_thread_info()->exec_domain->signal_invmap[sig]
+			   : sig),
+			  &frame->sig);
+
+	err |= __put_user(regs->vector, &frame->code);
+	err |= __put_user(&frame->sc, &frame->psc);
+
+	if (_NSIG_WORDS > 1)
+		err |= copy_to_user(frame->extramask, &set->sig[1],
+				    sizeof(frame->extramask));
+
+	setup_sigcontext(&context, regs, set->sig[0]);
+	err |= copy_to_user (&frame->sc, &context, sizeof(context));
+
+	/* Set up to return from userspace.  */
+	err |= __put_user((void *) ret_from_user_signal, &frame->pretcode);
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up registers for signal handler */
+	wrusp ((unsigned long) frame);
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+	regs->format = 0x4; /*set format byte to make stack appear modulo 4 
+						which it will be when doing the rte */
+
+adjust_stack:
+	/* Prepare to skip over the extra stuff in the exception frame.  */
+	if (regs->stkadj) {
+		struct pt_regs *tregs =
+			(struct pt_regs *)((ulong)regs + regs->stkadj);
+#if defined(DEBUG)
+		printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+		/* This must be copied with decreasing addresses to
+                   handle overlaps.  */
+		tregs->vector = 0;
+		tregs->format = 0;
+		tregs->pc = regs->pc;
+		tregs->sr = regs->sr;
+	}
+	return err;
+
+give_sigsegv:
+	force_sigsegv(sig, current);
+	goto adjust_stack;
+}
+
+static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
+			    sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+	int err = 0;
+
+	frame = get_sigframe(ka, regs, sizeof(*frame));
+
+	err |= __put_user((current_thread_info()->exec_domain
+			   && current_thread_info()->exec_domain->signal_invmap
+			   && sig < 32
+			   ? current_thread_info()->exec_domain->signal_invmap[sig]
+			   : sig),
+			  &frame->sig);
+	err |= __put_user(&frame->info, &frame->pinfo);
+	err |= __put_user(&frame->uc, &frame->puc);
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	/* Create the ucontext.  */
+	err |= __put_user(0, &frame->uc.uc_flags);
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void __user *)current->sas_ss_sp,
+			  &frame->uc.uc_stack.ss_sp);
+	err |= __put_user(sas_ss_flags(rdusp()),
+			  &frame->uc.uc_stack.ss_flags);
+	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
+	err |= rt_setup_ucontext(&frame->uc, regs);
+	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
+
+	/* Set up to return from userspace.  */
+	err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode);
+
+	if (err)
+		goto give_sigsegv;
+
+	/* Set up registers for signal handler */
+	wrusp ((unsigned long) frame);
+	regs->pc = (unsigned long) ka->sa.sa_handler;
+	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
+	regs->format = 0x4; /*set format byte to make stack appear modulo 4 
+						which it will be when doing the rte */
+
+adjust_stack:
+	/* Prepare to skip over the extra stuff in the exception frame.  */
+	if (regs->stkadj) {
+		struct pt_regs *tregs =
+			(struct pt_regs *)((ulong)regs + regs->stkadj);
+#if defined(DEBUG)
+		printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
+#endif
+		/* This must be copied with decreasing addresses to
+                   handle overlaps.  */
+		tregs->vector = 0;
+		tregs->format = 0;
+		tregs->pc = regs->pc;
+		tregs->sr = regs->sr;
+	}
+	return err;
+
+give_sigsegv:
+	force_sigsegv(sig, current);
+	goto adjust_stack;
+}
+
+static inline void
+handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
+{
+	switch (regs->d0) {
+	case -ERESTARTNOHAND:
+		if (!has_handler)
+			goto do_restart;
+		regs->d0 = -EINTR;
+		break;
+
+	case -ERESTART_RESTARTBLOCK:
+		if (!has_handler) {
+			regs->d0 = __NR_restart_syscall;
+			regs->pc -= 2;
+			break;
+		}
+		regs->d0 = -EINTR;
+		break;
+
+	case -ERESTARTSYS:
+		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
+			regs->d0 = -EINTR;
+			break;
+		}
+	/* fallthrough */
+	case -ERESTARTNOINTR:
+	do_restart:
+		regs->d0 = regs->orig_d0;
+		regs->pc -= 2;
+		break;
+	}
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static void
+handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
+	      sigset_t *oldset, struct pt_regs *regs)
+{
+	int err;
+	/* are we from a system call? */
+	if (regs->orig_d0 >= 0)
+		/* If so, check system call restarting.. */
+		handle_restart(regs, ka, 1);
+
+	/* set up the stack frame */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		err = setup_rt_frame(sig, ka, info, oldset, regs);
+	else
+		err = setup_frame(sig, ka, oldset, regs);
+
+	if (err)
+		return;
+
+	spin_lock_irq(&current->sighand->siglock);
+	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&current->blocked,sig);
+	recalc_sigpending();
+	spin_unlock_irq(&current->sighand->siglock);
+
+	clear_thread_flag(TIF_RESTORE_SIGMASK);
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ */
+asmlinkage void do_signal(struct pt_regs *regs)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	int signr;
+	sigset_t *oldset;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return;
+
+	if (test_thread_flag(TIF_RESTORE_SIGMASK))
+		oldset = &current->saved_sigmask;
+	else
+		oldset = &current->blocked;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		/* Whee!  Actually deliver the signal.  */
+		handle_signal(signr, &ka, &info, oldset, regs);
+		return;
+	}
+
+	/* Did we come from a system call? */
+	if (regs->orig_d0 >= 0) {
+		/* Restart the system call - no handlers present */
+		handle_restart(regs, NULL, 0);
+	}
+
+	/* If there's no signal to deliver, we just restore the saved mask.  */
+	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+		clear_thread_flag(TIF_RESTORE_SIGMASK);
+		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/syscalltable.S linux-libre-2.6.39-gnu/arch/m68k/kernel/syscalltable.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/syscalltable.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/syscalltable.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,369 @@
+/*
+ *  linux/arch/m68knommu/kernel/syscalltable.S
+ *
+ *  Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
+ *
+ *  Based on older entry.S files, the following copyrights apply:
+ *
+ *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
+ *                      Kenneth Albanowski <kjahds@kjahds.com>,
+ *  Copyright (C) 2000  Lineo Inc. (www.lineo.com) 
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+
+.text
+ALIGN
+ENTRY(sys_call_table)
+	.long sys_restart_syscall	/* 0  -  old "setup()" system call */
+	.long sys_exit
+	.long sys_fork
+	.long sys_read
+	.long sys_write
+	.long sys_open		/* 5 */
+	.long sys_close
+	.long sys_waitpid
+	.long sys_creat
+	.long sys_link
+	.long sys_unlink	/* 10 */
+	.long sys_execve
+	.long sys_chdir
+	.long sys_time
+	.long sys_mknod
+	.long sys_chmod		/* 15 */
+	.long sys_chown16
+	.long sys_ni_syscall	/* old break syscall holder */
+	.long sys_stat
+	.long sys_lseek
+	.long sys_getpid	/* 20 */
+	.long sys_mount
+	.long sys_oldumount
+	.long sys_setuid16
+	.long sys_getuid16
+	.long sys_stime		/* 25 */
+	.long sys_ptrace
+	.long sys_alarm
+	.long sys_fstat
+	.long sys_pause
+	.long sys_utime		/* 30 */
+	.long sys_ni_syscall	/* old stty syscall holder */
+	.long sys_ni_syscall	/* old gtty syscall holder */
+	.long sys_access
+	.long sys_nice
+	.long sys_ni_syscall	/* 35 */ /* old ftime syscall holder */
+	.long sys_sync
+	.long sys_kill
+	.long sys_rename
+	.long sys_mkdir
+	.long sys_rmdir		/* 40 */
+	.long sys_dup
+	.long sys_pipe
+	.long sys_times
+	.long sys_ni_syscall	/* old prof syscall holder */
+	.long sys_brk		/* 45 */
+	.long sys_setgid16
+	.long sys_getgid16
+	.long sys_signal
+	.long sys_geteuid16
+	.long sys_getegid16	/* 50 */
+	.long sys_acct
+	.long sys_umount	/* recycled never used phys() */
+	.long sys_ni_syscall	/* old lock syscall holder */
+	.long sys_ioctl
+	.long sys_fcntl		/* 55 */
+	.long sys_ni_syscall	/* old mpx syscall holder */
+	.long sys_setpgid
+	.long sys_ni_syscall	/* old ulimit syscall holder */
+	.long sys_ni_syscall
+	.long sys_umask		/* 60 */
+	.long sys_chroot
+	.long sys_ustat
+	.long sys_dup2
+	.long sys_getppid
+	.long sys_getpgrp	/* 65 */
+	.long sys_setsid
+	.long sys_sigaction
+	.long sys_sgetmask
+	.long sys_ssetmask
+	.long sys_setreuid16	/* 70 */
+	.long sys_setregid16
+	.long sys_sigsuspend
+	.long sys_sigpending
+	.long sys_sethostname
+	.long sys_setrlimit	/* 75 */
+	.long sys_old_getrlimit
+	.long sys_getrusage
+	.long sys_gettimeofday
+	.long sys_settimeofday
+	.long sys_getgroups16	/* 80 */
+	.long sys_setgroups16
+	.long sys_old_select
+	.long sys_symlink
+	.long sys_lstat
+	.long sys_readlink	/* 85 */
+	.long sys_uselib
+	.long sys_ni_syscall	/* sys_swapon */
+	.long sys_reboot
+	.long sys_old_readdir
+	.long sys_old_mmap	/* 90 */
+	.long sys_munmap
+	.long sys_truncate
+	.long sys_ftruncate
+	.long sys_fchmod
+	.long sys_fchown16	/* 95 */
+	.long sys_getpriority
+	.long sys_setpriority
+	.long sys_ni_syscall	/* old profil syscall holder */
+	.long sys_statfs
+	.long sys_fstatfs	/* 100 */
+	.long sys_ni_syscall	/* ioperm for i386 */
+	.long sys_socketcall
+	.long sys_syslog
+	.long sys_setitimer
+	.long sys_getitimer	/* 105 */
+	.long sys_newstat
+	.long sys_newlstat
+	.long sys_newfstat
+	.long sys_ni_syscall
+	.long sys_ni_syscall	/* iopl for i386 */ /* 110 */
+	.long sys_vhangup
+	.long sys_ni_syscall	/* obsolete idle() syscall */
+	.long sys_ni_syscall	/* vm86old for i386 */
+	.long sys_wait4
+	.long sys_ni_syscall	/* 115 */ /* sys_swapoff */
+	.long sys_sysinfo
+	.long sys_ipc
+	.long sys_fsync
+	.long sys_sigreturn
+	.long sys_clone		/* 120 */
+	.long sys_setdomainname
+	.long sys_newuname
+	.long sys_cacheflush	/* modify_ldt for i386 */
+	.long sys_adjtimex
+	.long sys_ni_syscall	/* 125 */ /* sys_mprotect */
+	.long sys_sigprocmask
+	.long sys_ni_syscall	/* old "creat_module" */
+	.long sys_init_module
+	.long sys_delete_module
+	.long sys_ni_syscall	/* 130: old "get_kernel_syms" */
+	.long sys_quotactl
+	.long sys_getpgid
+	.long sys_fchdir
+	.long sys_bdflush
+	.long sys_sysfs		/* 135 */
+	.long sys_personality
+	.long sys_ni_syscall	/* for afs_syscall */
+	.long sys_setfsuid16
+	.long sys_setfsgid16
+	.long sys_llseek	/* 140 */
+	.long sys_getdents
+	.long sys_select
+	.long sys_flock
+	.long sys_ni_syscall	/* sys_msync */
+	.long sys_readv		/* 145 */
+	.long sys_writev
+	.long sys_getsid
+	.long sys_fdatasync
+	.long sys_sysctl
+	.long sys_ni_syscall	/* 150 */ /* sys_mlock */
+	.long sys_ni_syscall	/* sys_munlock */
+	.long sys_ni_syscall	/* sys_mlockall */
+	.long sys_ni_syscall	/* sys_munlockall */
+	.long sys_sched_setparam
+	.long sys_sched_getparam /* 155 */
+	.long sys_sched_setscheduler
+	.long sys_sched_getscheduler
+	.long sys_sched_yield
+	.long sys_sched_get_priority_max
+	.long sys_sched_get_priority_min  /* 160 */
+	.long sys_sched_rr_get_interval
+	.long sys_nanosleep
+	.long sys_ni_syscall	/* sys_mremap */
+	.long sys_setresuid16
+	.long sys_getresuid16	/* 165 */
+	.long sys_getpagesize	/* sys_getpagesize */
+	.long sys_ni_syscall	/* old "query_module" */
+	.long sys_poll
+	.long sys_ni_syscall	/* sys_nfsservctl */
+	.long sys_setresgid16	/* 170 */
+	.long sys_getresgid16
+	.long sys_prctl
+	.long sys_rt_sigreturn
+	.long sys_rt_sigaction
+	.long sys_rt_sigprocmask /* 175 */
+	.long sys_rt_sigpending
+	.long sys_rt_sigtimedwait
+	.long sys_rt_sigqueueinfo
+	.long sys_rt_sigsuspend
+	.long sys_pread64	/* 180 */
+	.long sys_pwrite64
+	.long sys_lchown16
+	.long sys_getcwd
+	.long sys_capget
+	.long sys_capset	/* 185 */
+	.long sys_sigaltstack
+	.long sys_sendfile
+	.long sys_ni_syscall	/* streams1 */
+	.long sys_ni_syscall	/* streams2 */
+	.long sys_vfork		/* 190 */
+	.long sys_getrlimit
+	.long sys_mmap_pgoff
+	.long sys_truncate64
+	.long sys_ftruncate64
+	.long sys_stat64	/* 195 */
+	.long sys_lstat64
+	.long sys_fstat64
+	.long sys_chown
+	.long sys_getuid
+	.long sys_getgid	/* 200 */
+	.long sys_geteuid
+	.long sys_getegid
+	.long sys_setreuid
+	.long sys_setregid
+	.long sys_getgroups	/* 205 */
+	.long sys_setgroups
+	.long sys_fchown
+	.long sys_setresuid
+	.long sys_getresuid
+	.long sys_setresgid	/* 210 */
+	.long sys_getresgid
+	.long sys_lchown
+	.long sys_setuid
+	.long sys_setgid
+	.long sys_setfsuid	/* 215 */
+	.long sys_setfsgid
+	.long sys_pivot_root
+	.long sys_ni_syscall
+	.long sys_ni_syscall
+	.long sys_getdents64	/* 220 */
+	.long sys_gettid
+	.long sys_tkill
+	.long sys_setxattr
+	.long sys_lsetxattr
+	.long sys_fsetxattr	/* 225 */
+	.long sys_getxattr
+	.long sys_lgetxattr
+	.long sys_fgetxattr
+	.long sys_listxattr
+	.long sys_llistxattr	/* 230 */
+	.long sys_flistxattr
+	.long sys_removexattr
+	.long sys_lremovexattr
+	.long sys_fremovexattr
+	.long sys_futex		/* 235 */
+	.long sys_sendfile64
+	.long sys_ni_syscall	/* sys_mincore */
+	.long sys_ni_syscall	/* sys_madvise */
+	.long sys_fcntl64
+	.long sys_readahead	/* 240 */
+	.long sys_io_setup
+	.long sys_io_destroy
+	.long sys_io_getevents
+	.long sys_io_submit
+	.long sys_io_cancel	/* 245 */
+	.long sys_fadvise64
+	.long sys_exit_group
+	.long sys_lookup_dcookie
+	.long sys_epoll_create
+	.long sys_epoll_ctl	/* 250 */
+	.long sys_epoll_wait
+	.long sys_ni_syscall	/* sys_remap_file_pages */
+	.long sys_set_tid_address
+	.long sys_timer_create
+	.long sys_timer_settime	/* 255 */
+	.long sys_timer_gettime
+	.long sys_timer_getoverrun
+	.long sys_timer_delete
+	.long sys_clock_settime
+	.long sys_clock_gettime	/* 260 */
+	.long sys_clock_getres
+	.long sys_clock_nanosleep
+	.long sys_statfs64
+	.long sys_fstatfs64
+	.long sys_tgkill	/* 265 */
+	.long sys_utimes
+	.long sys_fadvise64_64
+	.long sys_mbind	
+	.long sys_get_mempolicy
+	.long sys_set_mempolicy	/* 270 */
+	.long sys_mq_open
+	.long sys_mq_unlink
+	.long sys_mq_timedsend
+	.long sys_mq_timedreceive
+	.long sys_mq_notify	/* 275 */
+	.long sys_mq_getsetattr
+	.long sys_waitid
+	.long sys_ni_syscall	/* for sys_vserver */
+	.long sys_add_key
+	.long sys_request_key	/* 280 */
+	.long sys_keyctl
+	.long sys_ioprio_set
+	.long sys_ioprio_get
+	.long sys_inotify_init
+	.long sys_inotify_add_watch	/* 285 */
+	.long sys_inotify_rm_watch
+	.long sys_migrate_pages
+	.long sys_openat
+	.long sys_mkdirat
+	.long sys_mknodat		/* 290 */
+	.long sys_fchownat
+	.long sys_futimesat
+	.long sys_fstatat64
+	.long sys_unlinkat
+	.long sys_renameat		/* 295 */
+	.long sys_linkat
+	.long sys_symlinkat
+	.long sys_readlinkat
+	.long sys_fchmodat
+	.long sys_faccessat		/* 300 */
+	.long sys_ni_syscall		/* Reserved for pselect6 */
+	.long sys_ni_syscall		/* Reserved for ppoll */
+	.long sys_unshare
+	.long sys_set_robust_list
+	.long sys_get_robust_list	/* 305 */
+	.long sys_splice
+	.long sys_sync_file_range
+	.long sys_tee
+	.long sys_vmsplice
+	.long sys_move_pages		/* 310 */
+	.long sys_sched_setaffinity
+	.long sys_sched_getaffinity
+	.long sys_kexec_load
+	.long sys_getcpu
+	.long sys_epoll_pwait		/* 315 */
+	.long sys_utimensat
+	.long sys_signalfd
+	.long sys_timerfd_create
+	.long sys_eventfd
+	.long sys_fallocate		/* 320 */
+	.long sys_timerfd_settime
+	.long sys_timerfd_gettime
+	.long sys_signalfd4
+	.long sys_eventfd2
+	.long sys_epoll_create1		/* 325 */
+	.long sys_dup3
+	.long sys_pipe2
+	.long sys_inotify_init1
+	.long sys_preadv
+	.long sys_pwritev		/* 330 */
+	.long sys_rt_tgsigqueueinfo
+	.long sys_perf_event_open
+	.long sys_get_thread_area
+	.long sys_set_thread_area
+	.long sys_atomic_cmpxchg_32	/* 335 */
+	.long sys_atomic_barrier
+	.long sys_fanotify_init
+	.long sys_fanotify_mark
+	.long sys_prlimit64
+	.long sys_name_to_handle_at	/* 340 */
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
+	.long sys_syncfs
+
+	.rept NR_syscalls-(.-sys_call_table)/4
+		.long sys_ni_syscall
+	.endr
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/sys_m68k.c linux-libre-2.6.39-gnu/arch/m68k/kernel/sys_m68k.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/sys_m68k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/sys_m68k.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,546 +1,5 @@
-/*
- * linux/arch/m68k/kernel/sys_m68k.c
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/m68k
- * platform.
- */
-
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/ipc.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/cachectl.h>
-#include <asm/traps.h>
-#include <asm/page.h>
-#include <asm/unistd.h>
-#include <linux/elf.h>
-#include <asm/tlb.h>
-
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
-			     unsigned long error_code);
-
-asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
-	unsigned long prot, unsigned long flags,
-	unsigned long fd, unsigned long pgoff)
-{
-	/*
-	 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
-	 * so we need to shift the argument down by 1; m68k mmap64(3)
-	 * (in libc) expects the last argument of mmap2 in 4Kb units.
-	 */
-	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
-}
-
-/* Convert virtual (user) address VADDR to physical address PADDR */
-#define virt_to_phys_040(vaddr)						\
-({									\
-  unsigned long _mmusr, _paddr;						\
-									\
-  __asm__ __volatile__ (".chip 68040\n\t"				\
-			"ptestr (%1)\n\t"				\
-			"movec %%mmusr,%0\n\t"				\
-			".chip 68k"					\
-			: "=r" (_mmusr)					\
-			: "a" (vaddr));					\
-  _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0;		\
-  _paddr;								\
-})
-
-static inline int
-cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
-{
-  unsigned long paddr, i;
-
-  switch (scope)
-    {
-    case FLUSH_SCOPE_ALL:
-      switch (cache)
-	{
-	case FLUSH_CACHE_DATA:
-	  /* This nop is needed for some broken versions of the 68040.  */
-	  __asm__ __volatile__ ("nop\n\t"
-				".chip 68040\n\t"
-				"cpusha %dc\n\t"
-				".chip 68k");
-	  break;
-	case FLUSH_CACHE_INSN:
-	  __asm__ __volatile__ ("nop\n\t"
-				".chip 68040\n\t"
-				"cpusha %ic\n\t"
-				".chip 68k");
-	  break;
-	default:
-	case FLUSH_CACHE_BOTH:
-	  __asm__ __volatile__ ("nop\n\t"
-				".chip 68040\n\t"
-				"cpusha %bc\n\t"
-				".chip 68k");
-	  break;
-	}
-      break;
-
-    case FLUSH_SCOPE_LINE:
-      /* Find the physical address of the first mapped page in the
-	 address range.  */
-      if ((paddr = virt_to_phys_040(addr))) {
-        paddr += addr & ~(PAGE_MASK | 15);
-        len = (len + (addr & 15) + 15) >> 4;
-      } else {
-	unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
-
-	if (len <= tmp)
-	  return 0;
-	addr += tmp;
-	len -= tmp;
-	tmp = PAGE_SIZE;
-	for (;;)
-	  {
-	    if ((paddr = virt_to_phys_040(addr)))
-	      break;
-	    if (len <= tmp)
-	      return 0;
-	    addr += tmp;
-	    len -= tmp;
-	  }
-	len = (len + 15) >> 4;
-      }
-      i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
-      while (len--)
-	{
-	  switch (cache)
-	    {
-	    case FLUSH_CACHE_DATA:
-	      __asm__ __volatile__ ("nop\n\t"
-				    ".chip 68040\n\t"
-				    "cpushl %%dc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    case FLUSH_CACHE_INSN:
-	      __asm__ __volatile__ ("nop\n\t"
-				    ".chip 68040\n\t"
-				    "cpushl %%ic,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    default:
-	    case FLUSH_CACHE_BOTH:
-	      __asm__ __volatile__ ("nop\n\t"
-				    ".chip 68040\n\t"
-				    "cpushl %%bc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    }
-	  if (!--i && len)
-	    {
-	      /*
-	       * No need to page align here since it is done by
-	       * virt_to_phys_040().
-	       */
-	      addr += PAGE_SIZE;
-	      i = PAGE_SIZE / 16;
-	      /* Recompute physical address when crossing a page
-	         boundary. */
-	      for (;;)
-		{
-		  if ((paddr = virt_to_phys_040(addr)))
-		    break;
-		  if (len <= i)
-		    return 0;
-		  len -= i;
-		  addr += PAGE_SIZE;
-		}
-	    }
-	  else
-	    paddr += 16;
-	}
-      break;
-
-    default:
-    case FLUSH_SCOPE_PAGE:
-      len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
-      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
-	{
-	  if (!(paddr = virt_to_phys_040(addr)))
-	    continue;
-	  switch (cache)
-	    {
-	    case FLUSH_CACHE_DATA:
-	      __asm__ __volatile__ ("nop\n\t"
-				    ".chip 68040\n\t"
-				    "cpushp %%dc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    case FLUSH_CACHE_INSN:
-	      __asm__ __volatile__ ("nop\n\t"
-				    ".chip 68040\n\t"
-				    "cpushp %%ic,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    default:
-	    case FLUSH_CACHE_BOTH:
-	      __asm__ __volatile__ ("nop\n\t"
-				    ".chip 68040\n\t"
-				    "cpushp %%bc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    }
-	}
-      break;
-    }
-  return 0;
-}
-
-#define virt_to_phys_060(vaddr)				\
-({							\
-  unsigned long paddr;					\
-  __asm__ __volatile__ (".chip 68060\n\t"		\
-			"plpar (%0)\n\t"		\
-			".chip 68k"			\
-			: "=a" (paddr)			\
-			: "0" (vaddr));			\
-  (paddr); /* XXX */					\
-})
-
-static inline int
-cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
-{
-  unsigned long paddr, i;
-
-  /*
-   * 68060 manual says:
-   *  cpush %dc : flush DC, remains valid (with our %cacr setup)
-   *  cpush %ic : invalidate IC
-   *  cpush %bc : flush DC + invalidate IC
-   */
-  switch (scope)
-    {
-    case FLUSH_SCOPE_ALL:
-      switch (cache)
-	{
-	case FLUSH_CACHE_DATA:
-	  __asm__ __volatile__ (".chip 68060\n\t"
-				"cpusha %dc\n\t"
-				".chip 68k");
-	  break;
-	case FLUSH_CACHE_INSN:
-	  __asm__ __volatile__ (".chip 68060\n\t"
-				"cpusha %ic\n\t"
-				".chip 68k");
-	  break;
-	default:
-	case FLUSH_CACHE_BOTH:
-	  __asm__ __volatile__ (".chip 68060\n\t"
-				"cpusha %bc\n\t"
-				".chip 68k");
-	  break;
-	}
-      break;
-
-    case FLUSH_SCOPE_LINE:
-      /* Find the physical address of the first mapped page in the
-	 address range.  */
-      len += addr & 15;
-      addr &= -16;
-      if (!(paddr = virt_to_phys_060(addr))) {
-	unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
-
-	if (len <= tmp)
-	  return 0;
-	addr += tmp;
-	len -= tmp;
-	tmp = PAGE_SIZE;
-	for (;;)
-	  {
-	    if ((paddr = virt_to_phys_060(addr)))
-	      break;
-	    if (len <= tmp)
-	      return 0;
-	    addr += tmp;
-	    len -= tmp;
-	  }
-      }
-      len = (len + 15) >> 4;
-      i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
-      while (len--)
-	{
-	  switch (cache)
-	    {
-	    case FLUSH_CACHE_DATA:
-	      __asm__ __volatile__ (".chip 68060\n\t"
-				    "cpushl %%dc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    case FLUSH_CACHE_INSN:
-	      __asm__ __volatile__ (".chip 68060\n\t"
-				    "cpushl %%ic,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    default:
-	    case FLUSH_CACHE_BOTH:
-	      __asm__ __volatile__ (".chip 68060\n\t"
-				    "cpushl %%bc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    }
-	  if (!--i && len)
-	    {
-
-	      /*
-	       * We just want to jump to the first cache line
-	       * in the next page.
-	       */
-	      addr += PAGE_SIZE;
-	      addr &= PAGE_MASK;
-
-	      i = PAGE_SIZE / 16;
-	      /* Recompute physical address when crossing a page
-	         boundary. */
-	      for (;;)
-	        {
-	          if ((paddr = virt_to_phys_060(addr)))
-	            break;
-	          if (len <= i)
-	            return 0;
-	          len -= i;
-	          addr += PAGE_SIZE;
-	        }
-	    }
-	  else
-	    paddr += 16;
-	}
-      break;
-
-    default:
-    case FLUSH_SCOPE_PAGE:
-      len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
-      addr &= PAGE_MASK;	/* Workaround for bug in some
-				   revisions of the 68060 */
-      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
-	{
-	  if (!(paddr = virt_to_phys_060(addr)))
-	    continue;
-	  switch (cache)
-	    {
-	    case FLUSH_CACHE_DATA:
-	      __asm__ __volatile__ (".chip 68060\n\t"
-				    "cpushp %%dc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    case FLUSH_CACHE_INSN:
-	      __asm__ __volatile__ (".chip 68060\n\t"
-				    "cpushp %%ic,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    default:
-	    case FLUSH_CACHE_BOTH:
-	      __asm__ __volatile__ (".chip 68060\n\t"
-				    "cpushp %%bc,(%0)\n\t"
-				    ".chip 68k"
-				    : : "a" (paddr));
-	      break;
-	    }
-	}
-      break;
-    }
-  return 0;
-}
-
-/* sys_cacheflush -- flush (part of) the processor cache.  */
-asmlinkage int
-sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
-{
-	struct vm_area_struct *vma;
-	int ret = -EINVAL;
-
-	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
-	    cache & ~FLUSH_CACHE_BOTH)
-		goto out;
-
-	if (scope == FLUSH_SCOPE_ALL) {
-		/* Only the superuser may explicitly flush the whole cache. */
-		ret = -EPERM;
-		if (!capable(CAP_SYS_ADMIN))
-			goto out;
-	} else {
-		/*
-		 * Verify that the specified address region actually belongs
-		 * to this process.
-		 */
-		vma = find_vma (current->mm, addr);
-		ret = -EINVAL;
-		/* Check for overflow.  */
-		if (addr + len < addr)
-			goto out;
-		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
-			goto out;
-	}
-
-	if (CPU_IS_020_OR_030) {
-		if (scope == FLUSH_SCOPE_LINE && len < 256) {
-			unsigned long cacr;
-			__asm__ ("movec %%cacr, %0" : "=r" (cacr));
-			if (cache & FLUSH_CACHE_INSN)
-				cacr |= 4;
-			if (cache & FLUSH_CACHE_DATA)
-				cacr |= 0x400;
-			len >>= 2;
-			while (len--) {
-				__asm__ __volatile__ ("movec %1, %%caar\n\t"
-						      "movec %0, %%cacr"
-						      : /* no outputs */
-						      : "r" (cacr), "r" (addr));
-				addr += 4;
-			}
-		} else {
-			/* Flush the whole cache, even if page granularity requested. */
-			unsigned long cacr;
-			__asm__ ("movec %%cacr, %0" : "=r" (cacr));
-			if (cache & FLUSH_CACHE_INSN)
-				cacr |= 8;
-			if (cache & FLUSH_CACHE_DATA)
-				cacr |= 0x800;
-			__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
-		}
-		ret = 0;
-		goto out;
-	} else {
-	    /*
-	     * 040 or 060: don't blindly trust 'scope', someone could
-	     * try to flush a few megs of memory.
-	     */
-
-	    if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
-	        scope=FLUSH_SCOPE_PAGE;
-	    if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
-	        scope=FLUSH_SCOPE_ALL;
-	    if (CPU_IS_040) {
-		ret = cache_flush_040 (addr, scope, cache, len);
-	    } else if (CPU_IS_060) {
-		ret = cache_flush_060 (addr, scope, cache, len);
-	    }
-	}
-out:
-	return ret;
-}
-
-asmlinkage int sys_getpagesize(void)
-{
-	return PAGE_SIZE;
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register long __res asm ("%d0") = __NR_execve;
-	register long __a asm ("%d1") = (long)(filename);
-	register long __b asm ("%d2") = (long)(argv);
-	register long __c asm ("%d3") = (long)(envp);
-	asm volatile ("trap  #0" : "+d" (__res)
-			: "d" (__a), "d" (__b), "d" (__c));
-	return __res;
-}
-
-asmlinkage unsigned long sys_get_thread_area(void)
-{
-	return current_thread_info()->tp_value;
-}
-
-asmlinkage int sys_set_thread_area(unsigned long tp)
-{
-	current_thread_info()->tp_value = tp;
-	return 0;
-}
-
-/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
-   D1 (newval).  */
-asmlinkage int
-sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
-		      unsigned long __user * mem)
-{
-	/* This was borrowed from ARM's implementation.  */
-	for (;;) {
-		struct mm_struct *mm = current->mm;
-		pgd_t *pgd;
-		pmd_t *pmd;
-		pte_t *pte;
-		spinlock_t *ptl;
-		unsigned long mem_value;
-
-		down_read(&mm->mmap_sem);
-		pgd = pgd_offset(mm, (unsigned long)mem);
-		if (!pgd_present(*pgd))
-			goto bad_access;
-		pmd = pmd_offset(pgd, (unsigned long)mem);
-		if (!pmd_present(*pmd))
-			goto bad_access;
-		pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
-		if (!pte_present(*pte) || !pte_dirty(*pte)
-		    || !pte_write(*pte)) {
-			pte_unmap_unlock(pte, ptl);
-			goto bad_access;
-		}
-
-		mem_value = *mem;
-		if (mem_value == oldval)
-			*mem = newval;
-
-		pte_unmap_unlock(pte, ptl);
-		up_read(&mm->mmap_sem);
-		return mem_value;
-
-	      bad_access:
-		up_read(&mm->mmap_sem);
-		/* This is not necessarily a bad access, we can get here if
-		   a memory we're trying to write to should be copied-on-write.
-		   Make the kernel do the necessary page stuff, then re-iterate.
-		   Simulate a write access fault to do that.  */
-		{
-			/* The first argument of the function corresponds to
-			   D1, which is the first field of struct pt_regs.  */
-			struct pt_regs *fp = (struct pt_regs *)&newval;
-
-			/* '3' is an RMW flag.  */
-			if (do_page_fault(fp, (unsigned long)mem, 3))
-				/* If the do_page_fault() failed, we don't
-				   have anything meaningful to return.
-				   There should be a SIGSEGV pending for
-				   the process.  */
-				return 0xdeadbeef;
-		}
-	}
-}
-
-asmlinkage int sys_atomic_barrier(void)
-{
-	/* no code needed for uniprocs */
-	return 0;
-}
+#ifdef CONFIG_MMU
+#include "sys_m68k_mm.c"
+#else
+#include "sys_m68k_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/sys_m68k_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/sys_m68k_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/sys_m68k_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/sys_m68k_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,546 @@
+/*
+ * linux/arch/m68k/kernel/sys_m68k.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/m68k
+ * platform.
+ */
+
+#include <linux/capability.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/fs.h>
+#include <linux/smp.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/ipc.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/traps.h>
+#include <asm/page.h>
+#include <asm/unistd.h>
+#include <linux/elf.h>
+#include <asm/tlb.h>
+
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+			     unsigned long error_code);
+
+asmlinkage long sys_mmap2(unsigned long addr, unsigned long len,
+	unsigned long prot, unsigned long flags,
+	unsigned long fd, unsigned long pgoff)
+{
+	/*
+	 * This is wrong for sun3 - there PAGE_SIZE is 8Kb,
+	 * so we need to shift the argument down by 1; m68k mmap64(3)
+	 * (in libc) expects the last argument of mmap2 in 4Kb units.
+	 */
+	return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff);
+}
+
+/* Convert virtual (user) address VADDR to physical address PADDR */
+#define virt_to_phys_040(vaddr)						\
+({									\
+  unsigned long _mmusr, _paddr;						\
+									\
+  __asm__ __volatile__ (".chip 68040\n\t"				\
+			"ptestr (%1)\n\t"				\
+			"movec %%mmusr,%0\n\t"				\
+			".chip 68k"					\
+			: "=r" (_mmusr)					\
+			: "a" (vaddr));					\
+  _paddr = (_mmusr & MMU_R_040) ? (_mmusr & PAGE_MASK) : 0;		\
+  _paddr;								\
+})
+
+static inline int
+cache_flush_040 (unsigned long addr, int scope, int cache, unsigned long len)
+{
+  unsigned long paddr, i;
+
+  switch (scope)
+    {
+    case FLUSH_SCOPE_ALL:
+      switch (cache)
+	{
+	case FLUSH_CACHE_DATA:
+	  /* This nop is needed for some broken versions of the 68040.  */
+	  __asm__ __volatile__ ("nop\n\t"
+				".chip 68040\n\t"
+				"cpusha %dc\n\t"
+				".chip 68k");
+	  break;
+	case FLUSH_CACHE_INSN:
+	  __asm__ __volatile__ ("nop\n\t"
+				".chip 68040\n\t"
+				"cpusha %ic\n\t"
+				".chip 68k");
+	  break;
+	default:
+	case FLUSH_CACHE_BOTH:
+	  __asm__ __volatile__ ("nop\n\t"
+				".chip 68040\n\t"
+				"cpusha %bc\n\t"
+				".chip 68k");
+	  break;
+	}
+      break;
+
+    case FLUSH_SCOPE_LINE:
+      /* Find the physical address of the first mapped page in the
+	 address range.  */
+      if ((paddr = virt_to_phys_040(addr))) {
+        paddr += addr & ~(PAGE_MASK | 15);
+        len = (len + (addr & 15) + 15) >> 4;
+      } else {
+	unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
+
+	if (len <= tmp)
+	  return 0;
+	addr += tmp;
+	len -= tmp;
+	tmp = PAGE_SIZE;
+	for (;;)
+	  {
+	    if ((paddr = virt_to_phys_040(addr)))
+	      break;
+	    if (len <= tmp)
+	      return 0;
+	    addr += tmp;
+	    len -= tmp;
+	  }
+	len = (len + 15) >> 4;
+      }
+      i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
+      while (len--)
+	{
+	  switch (cache)
+	    {
+	    case FLUSH_CACHE_DATA:
+	      __asm__ __volatile__ ("nop\n\t"
+				    ".chip 68040\n\t"
+				    "cpushl %%dc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    case FLUSH_CACHE_INSN:
+	      __asm__ __volatile__ ("nop\n\t"
+				    ".chip 68040\n\t"
+				    "cpushl %%ic,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    default:
+	    case FLUSH_CACHE_BOTH:
+	      __asm__ __volatile__ ("nop\n\t"
+				    ".chip 68040\n\t"
+				    "cpushl %%bc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    }
+	  if (!--i && len)
+	    {
+	      /*
+	       * No need to page align here since it is done by
+	       * virt_to_phys_040().
+	       */
+	      addr += PAGE_SIZE;
+	      i = PAGE_SIZE / 16;
+	      /* Recompute physical address when crossing a page
+	         boundary. */
+	      for (;;)
+		{
+		  if ((paddr = virt_to_phys_040(addr)))
+		    break;
+		  if (len <= i)
+		    return 0;
+		  len -= i;
+		  addr += PAGE_SIZE;
+		}
+	    }
+	  else
+	    paddr += 16;
+	}
+      break;
+
+    default:
+    case FLUSH_SCOPE_PAGE:
+      len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
+      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
+	{
+	  if (!(paddr = virt_to_phys_040(addr)))
+	    continue;
+	  switch (cache)
+	    {
+	    case FLUSH_CACHE_DATA:
+	      __asm__ __volatile__ ("nop\n\t"
+				    ".chip 68040\n\t"
+				    "cpushp %%dc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    case FLUSH_CACHE_INSN:
+	      __asm__ __volatile__ ("nop\n\t"
+				    ".chip 68040\n\t"
+				    "cpushp %%ic,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    default:
+	    case FLUSH_CACHE_BOTH:
+	      __asm__ __volatile__ ("nop\n\t"
+				    ".chip 68040\n\t"
+				    "cpushp %%bc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    }
+	}
+      break;
+    }
+  return 0;
+}
+
+#define virt_to_phys_060(vaddr)				\
+({							\
+  unsigned long paddr;					\
+  __asm__ __volatile__ (".chip 68060\n\t"		\
+			"plpar (%0)\n\t"		\
+			".chip 68k"			\
+			: "=a" (paddr)			\
+			: "0" (vaddr));			\
+  (paddr); /* XXX */					\
+})
+
+static inline int
+cache_flush_060 (unsigned long addr, int scope, int cache, unsigned long len)
+{
+  unsigned long paddr, i;
+
+  /*
+   * 68060 manual says:
+   *  cpush %dc : flush DC, remains valid (with our %cacr setup)
+   *  cpush %ic : invalidate IC
+   *  cpush %bc : flush DC + invalidate IC
+   */
+  switch (scope)
+    {
+    case FLUSH_SCOPE_ALL:
+      switch (cache)
+	{
+	case FLUSH_CACHE_DATA:
+	  __asm__ __volatile__ (".chip 68060\n\t"
+				"cpusha %dc\n\t"
+				".chip 68k");
+	  break;
+	case FLUSH_CACHE_INSN:
+	  __asm__ __volatile__ (".chip 68060\n\t"
+				"cpusha %ic\n\t"
+				".chip 68k");
+	  break;
+	default:
+	case FLUSH_CACHE_BOTH:
+	  __asm__ __volatile__ (".chip 68060\n\t"
+				"cpusha %bc\n\t"
+				".chip 68k");
+	  break;
+	}
+      break;
+
+    case FLUSH_SCOPE_LINE:
+      /* Find the physical address of the first mapped page in the
+	 address range.  */
+      len += addr & 15;
+      addr &= -16;
+      if (!(paddr = virt_to_phys_060(addr))) {
+	unsigned long tmp = PAGE_SIZE - (addr & ~PAGE_MASK);
+
+	if (len <= tmp)
+	  return 0;
+	addr += tmp;
+	len -= tmp;
+	tmp = PAGE_SIZE;
+	for (;;)
+	  {
+	    if ((paddr = virt_to_phys_060(addr)))
+	      break;
+	    if (len <= tmp)
+	      return 0;
+	    addr += tmp;
+	    len -= tmp;
+	  }
+      }
+      len = (len + 15) >> 4;
+      i = (PAGE_SIZE - (paddr & ~PAGE_MASK)) >> 4;
+      while (len--)
+	{
+	  switch (cache)
+	    {
+	    case FLUSH_CACHE_DATA:
+	      __asm__ __volatile__ (".chip 68060\n\t"
+				    "cpushl %%dc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    case FLUSH_CACHE_INSN:
+	      __asm__ __volatile__ (".chip 68060\n\t"
+				    "cpushl %%ic,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    default:
+	    case FLUSH_CACHE_BOTH:
+	      __asm__ __volatile__ (".chip 68060\n\t"
+				    "cpushl %%bc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    }
+	  if (!--i && len)
+	    {
+
+	      /*
+	       * We just want to jump to the first cache line
+	       * in the next page.
+	       */
+	      addr += PAGE_SIZE;
+	      addr &= PAGE_MASK;
+
+	      i = PAGE_SIZE / 16;
+	      /* Recompute physical address when crossing a page
+	         boundary. */
+	      for (;;)
+	        {
+	          if ((paddr = virt_to_phys_060(addr)))
+	            break;
+	          if (len <= i)
+	            return 0;
+	          len -= i;
+	          addr += PAGE_SIZE;
+	        }
+	    }
+	  else
+	    paddr += 16;
+	}
+      break;
+
+    default:
+    case FLUSH_SCOPE_PAGE:
+      len += (addr & ~PAGE_MASK) + (PAGE_SIZE - 1);
+      addr &= PAGE_MASK;	/* Workaround for bug in some
+				   revisions of the 68060 */
+      for (len >>= PAGE_SHIFT; len--; addr += PAGE_SIZE)
+	{
+	  if (!(paddr = virt_to_phys_060(addr)))
+	    continue;
+	  switch (cache)
+	    {
+	    case FLUSH_CACHE_DATA:
+	      __asm__ __volatile__ (".chip 68060\n\t"
+				    "cpushp %%dc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    case FLUSH_CACHE_INSN:
+	      __asm__ __volatile__ (".chip 68060\n\t"
+				    "cpushp %%ic,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    default:
+	    case FLUSH_CACHE_BOTH:
+	      __asm__ __volatile__ (".chip 68060\n\t"
+				    "cpushp %%bc,(%0)\n\t"
+				    ".chip 68k"
+				    : : "a" (paddr));
+	      break;
+	    }
+	}
+      break;
+    }
+  return 0;
+}
+
+/* sys_cacheflush -- flush (part of) the processor cache.  */
+asmlinkage int
+sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
+{
+	struct vm_area_struct *vma;
+	int ret = -EINVAL;
+
+	if (scope < FLUSH_SCOPE_LINE || scope > FLUSH_SCOPE_ALL ||
+	    cache & ~FLUSH_CACHE_BOTH)
+		goto out;
+
+	if (scope == FLUSH_SCOPE_ALL) {
+		/* Only the superuser may explicitly flush the whole cache. */
+		ret = -EPERM;
+		if (!capable(CAP_SYS_ADMIN))
+			goto out;
+	} else {
+		/*
+		 * Verify that the specified address region actually belongs
+		 * to this process.
+		 */
+		vma = find_vma (current->mm, addr);
+		ret = -EINVAL;
+		/* Check for overflow.  */
+		if (addr + len < addr)
+			goto out;
+		if (vma == NULL || addr < vma->vm_start || addr + len > vma->vm_end)
+			goto out;
+	}
+
+	if (CPU_IS_020_OR_030) {
+		if (scope == FLUSH_SCOPE_LINE && len < 256) {
+			unsigned long cacr;
+			__asm__ ("movec %%cacr, %0" : "=r" (cacr));
+			if (cache & FLUSH_CACHE_INSN)
+				cacr |= 4;
+			if (cache & FLUSH_CACHE_DATA)
+				cacr |= 0x400;
+			len >>= 2;
+			while (len--) {
+				__asm__ __volatile__ ("movec %1, %%caar\n\t"
+						      "movec %0, %%cacr"
+						      : /* no outputs */
+						      : "r" (cacr), "r" (addr));
+				addr += 4;
+			}
+		} else {
+			/* Flush the whole cache, even if page granularity requested. */
+			unsigned long cacr;
+			__asm__ ("movec %%cacr, %0" : "=r" (cacr));
+			if (cache & FLUSH_CACHE_INSN)
+				cacr |= 8;
+			if (cache & FLUSH_CACHE_DATA)
+				cacr |= 0x800;
+			__asm__ __volatile__ ("movec %0, %%cacr" : : "r" (cacr));
+		}
+		ret = 0;
+		goto out;
+	} else {
+	    /*
+	     * 040 or 060: don't blindly trust 'scope', someone could
+	     * try to flush a few megs of memory.
+	     */
+
+	    if (len>=3*PAGE_SIZE && scope<FLUSH_SCOPE_PAGE)
+	        scope=FLUSH_SCOPE_PAGE;
+	    if (len>=10*PAGE_SIZE && scope<FLUSH_SCOPE_ALL)
+	        scope=FLUSH_SCOPE_ALL;
+	    if (CPU_IS_040) {
+		ret = cache_flush_040 (addr, scope, cache, len);
+	    } else if (CPU_IS_060) {
+		ret = cache_flush_060 (addr, scope, cache, len);
+	    }
+	}
+out:
+	return ret;
+}
+
+asmlinkage int sys_getpagesize(void)
+{
+	return PAGE_SIZE;
+}
+
+/*
+ * Do a system call from kernel instead of calling sys_execve so we
+ * end up with proper pt_regs.
+ */
+int kernel_execve(const char *filename,
+		  const char *const argv[],
+		  const char *const envp[])
+{
+	register long __res asm ("%d0") = __NR_execve;
+	register long __a asm ("%d1") = (long)(filename);
+	register long __b asm ("%d2") = (long)(argv);
+	register long __c asm ("%d3") = (long)(envp);
+	asm volatile ("trap  #0" : "+d" (__res)
+			: "d" (__a), "d" (__b), "d" (__c));
+	return __res;
+}
+
+asmlinkage unsigned long sys_get_thread_area(void)
+{
+	return current_thread_info()->tp_value;
+}
+
+asmlinkage int sys_set_thread_area(unsigned long tp)
+{
+	current_thread_info()->tp_value = tp;
+	return 0;
+}
+
+/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
+   D1 (newval).  */
+asmlinkage int
+sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
+		      unsigned long __user * mem)
+{
+	/* This was borrowed from ARM's implementation.  */
+	for (;;) {
+		struct mm_struct *mm = current->mm;
+		pgd_t *pgd;
+		pmd_t *pmd;
+		pte_t *pte;
+		spinlock_t *ptl;
+		unsigned long mem_value;
+
+		down_read(&mm->mmap_sem);
+		pgd = pgd_offset(mm, (unsigned long)mem);
+		if (!pgd_present(*pgd))
+			goto bad_access;
+		pmd = pmd_offset(pgd, (unsigned long)mem);
+		if (!pmd_present(*pmd))
+			goto bad_access;
+		pte = pte_offset_map_lock(mm, pmd, (unsigned long)mem, &ptl);
+		if (!pte_present(*pte) || !pte_dirty(*pte)
+		    || !pte_write(*pte)) {
+			pte_unmap_unlock(pte, ptl);
+			goto bad_access;
+		}
+
+		mem_value = *mem;
+		if (mem_value == oldval)
+			*mem = newval;
+
+		pte_unmap_unlock(pte, ptl);
+		up_read(&mm->mmap_sem);
+		return mem_value;
+
+	      bad_access:
+		up_read(&mm->mmap_sem);
+		/* This is not necessarily a bad access, we can get here if
+		   a memory we're trying to write to should be copied-on-write.
+		   Make the kernel do the necessary page stuff, then re-iterate.
+		   Simulate a write access fault to do that.  */
+		{
+			/* The first argument of the function corresponds to
+			   D1, which is the first field of struct pt_regs.  */
+			struct pt_regs *fp = (struct pt_regs *)&newval;
+
+			/* '3' is an RMW flag.  */
+			if (do_page_fault(fp, (unsigned long)mem, 3))
+				/* If the do_page_fault() failed, we don't
+				   have anything meaningful to return.
+				   There should be a SIGSEGV pending for
+				   the process.  */
+				return 0xdeadbeef;
+		}
+	}
+}
+
+asmlinkage int sys_atomic_barrier(void)
+{
+	/* no code needed for uniprocs */
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/sys_m68k_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/sys_m68k_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/sys_m68k_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/sys_m68k_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * linux/arch/m68knommu/kernel/sys_m68k.c
+ *
+ * This file contains various random system calls that
+ * have a non-standard calling sequence on the Linux/m68k
+ * platform.
+ */
+
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/smp.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/file.h>
+#include <linux/ipc.h>
+#include <linux/fs.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/cachectl.h>
+#include <asm/traps.h>
+#include <asm/cacheflush.h>
+#include <asm/unistd.h>
+
+/* sys_cacheflush -- flush (part of) the processor cache.  */
+asmlinkage int
+sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
+{
+	flush_cache_all();
+	return(0);
+}
+
+asmlinkage int sys_getpagesize(void)
+{
+	return PAGE_SIZE;
+}
+
+/*
+ * Do a system call from kernel instead of calling sys_execve so we
+ * end up with proper pt_regs.
+ */
+int kernel_execve(const char *filename,
+		  const char *const argv[],
+		  const char *const envp[])
+{
+	register long __res asm ("%d0") = __NR_execve;
+	register long __a asm ("%d1") = (long)(filename);
+	register long __b asm ("%d2") = (long)(argv);
+	register long __c asm ("%d3") = (long)(envp);
+	asm volatile ("trap  #0" : "+d" (__res)
+			: "d" (__a), "d" (__b), "d" (__c));
+	return __res;
+}
+
+asmlinkage unsigned long sys_get_thread_area(void)
+{
+	return current_thread_info()->tp_value;
+}
+
+asmlinkage int sys_set_thread_area(unsigned long tp)
+{
+	current_thread_info()->tp_value = tp;
+	return 0;
+}
+
+/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
+   D1 (newval).  */
+asmlinkage int
+sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
+		      unsigned long __user * mem)
+{
+	struct mm_struct *mm = current->mm;
+	unsigned long mem_value;
+
+	down_read(&mm->mmap_sem);
+
+	mem_value = *mem;
+	if (mem_value == oldval)
+		*mem = newval;
+
+	up_read(&mm->mmap_sem);
+	return mem_value;
+}
+
+asmlinkage int sys_atomic_barrier(void)
+{
+	/* no code needed for uniprocs */
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/time.c linux-libre-2.6.39-gnu/arch/m68k/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,114 +1,5 @@
-/*
- *  linux/arch/m68k/kernel/time.c
- *
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * This file contains the m68k-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- *
- * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
- *		"A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/rtc.h>
-#include <linux/platform_device.h>
-
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/irq_regs.h>
-
-#include <linux/time.h>
-#include <linux/timex.h>
-#include <linux/profile.h>
-
-static inline int set_rtc_mmss(unsigned long nowtime)
-{
-  if (mach_set_clock_mmss)
-    return mach_set_clock_mmss (nowtime);
-  return -1;
-}
-
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-static irqreturn_t timer_interrupt(int irq, void *dummy)
-{
-	do_timer(1);
-	update_process_times(user_mode(get_irq_regs()));
-	profile_tick(CPU_PROFILING);
-
-#ifdef CONFIG_HEARTBEAT
-	/* use power LED as a heartbeat instead -- much more useful
-	   for debugging -- based on the version for PReP by Cort */
-	/* acts like an actual heart beat -- ie thump-thump-pause... */
-	if (mach_heartbeat) {
-	    static unsigned cnt = 0, period = 0, dist = 0;
-
-	    if (cnt == 0 || cnt == dist)
-		mach_heartbeat( 1 );
-	    else if (cnt == 7 || cnt == dist+7)
-		mach_heartbeat( 0 );
-
-	    if (++cnt > period) {
-		cnt = 0;
-		/* The hyperbolic function below modifies the heartbeat period
-		 * length in dependency of the current (5min) load. It goes
-		 * through the points f(0)=126, f(1)=86, f(5)=51,
-		 * f(inf)->30. */
-		period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
-		dist = period / 4;
-	    }
-	}
-#endif /* CONFIG_HEARTBEAT */
-	return IRQ_HANDLED;
-}
-
-void read_persistent_clock(struct timespec *ts)
-{
-	struct rtc_time time;
-	ts->tv_sec = 0;
-	ts->tv_nsec = 0;
-
-	if (mach_hwclk) {
-		mach_hwclk(0, &time);
-
-		if ((time.tm_year += 1900) < 1970)
-			time.tm_year += 100;
-		ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
-				      time.tm_hour, time.tm_min, time.tm_sec);
-	}
-}
-
-void __init time_init(void)
-{
-	mach_sched_init(timer_interrupt);
-}
-
-u32 arch_gettimeoffset(void)
-{
-	return mach_gettimeoffset() * 1000;
-}
-
-static int __init rtc_init(void)
-{
-	struct platform_device *pdev;
-
-	if (!mach_hwclk)
-		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_init);
+#ifdef CONFIG_MMU
+#include "time_mm.c"
+#else
+#include "time_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/time_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/time_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/time_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/time_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,114 @@
+/*
+ *  linux/arch/m68k/kernel/time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * This file contains the m68k-specific time handling details.
+ * Most of the stuff is located in the machine specific files.
+ *
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/irq_regs.h>
+
+#include <linux/time.h>
+#include <linux/timex.h>
+#include <linux/profile.h>
+
+static inline int set_rtc_mmss(unsigned long nowtime)
+{
+  if (mach_set_clock_mmss)
+    return mach_set_clock_mmss (nowtime);
+  return -1;
+}
+
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "xtime_update()" routine every clocktick
+ */
+static irqreturn_t timer_interrupt(int irq, void *dummy)
+{
+	xtime_update(1);
+	update_process_times(user_mode(get_irq_regs()));
+	profile_tick(CPU_PROFILING);
+
+#ifdef CONFIG_HEARTBEAT
+	/* use power LED as a heartbeat instead -- much more useful
+	   for debugging -- based on the version for PReP by Cort */
+	/* acts like an actual heart beat -- ie thump-thump-pause... */
+	if (mach_heartbeat) {
+	    static unsigned cnt = 0, period = 0, dist = 0;
+
+	    if (cnt == 0 || cnt == dist)
+		mach_heartbeat( 1 );
+	    else if (cnt == 7 || cnt == dist+7)
+		mach_heartbeat( 0 );
+
+	    if (++cnt > period) {
+		cnt = 0;
+		/* The hyperbolic function below modifies the heartbeat period
+		 * length in dependency of the current (5min) load. It goes
+		 * through the points f(0)=126, f(1)=86, f(5)=51,
+		 * f(inf)->30. */
+		period = ((672<<FSHIFT)/(5*avenrun[0]+(7<<FSHIFT))) + 30;
+		dist = period / 4;
+	    }
+	}
+#endif /* CONFIG_HEARTBEAT */
+	return IRQ_HANDLED;
+}
+
+void read_persistent_clock(struct timespec *ts)
+{
+	struct rtc_time time;
+	ts->tv_sec = 0;
+	ts->tv_nsec = 0;
+
+	if (mach_hwclk) {
+		mach_hwclk(0, &time);
+
+		if ((time.tm_year += 1900) < 1970)
+			time.tm_year += 100;
+		ts->tv_sec = mktime(time.tm_year, time.tm_mon, time.tm_mday,
+				      time.tm_hour, time.tm_min, time.tm_sec);
+	}
+}
+
+void __init time_init(void)
+{
+	mach_sched_init(timer_interrupt);
+}
+
+u32 arch_gettimeoffset(void)
+{
+	return mach_gettimeoffset() * 1000;
+}
+
+static int __init rtc_init(void)
+{
+	struct platform_device *pdev;
+
+	if (!mach_hwclk)
+		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_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/time_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/time_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/time_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/time_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ *  linux/arch/m68knommu/kernel/time.c
+ *
+ *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
+ *
+ * This file contains the m68k-specific time handling details.
+ * Most of the stuff is located in the machine specific files.
+ *
+ * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
+ *		"A Kernel Model for Precision Timekeeping" by Dave Mills
+ */
+
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/profile.h>
+#include <linux/time.h>
+#include <linux/timex.h>
+
+#include <asm/machdep.h>
+#include <asm/irq_regs.h>
+
+#define	TICK_SIZE (tick_nsec / 1000)
+
+static inline int set_rtc_mmss(unsigned long nowtime)
+{
+	if (mach_set_clock_mmss)
+		return mach_set_clock_mmss (nowtime);
+	return -1;
+}
+
+#ifndef CONFIG_GENERIC_CLOCKEVENTS
+/*
+ * timer_interrupt() needs to keep up the real-time clock,
+ * as well as call the "xtime_update()" routine every clocktick
+ */
+irqreturn_t arch_timer_interrupt(int irq, void *dummy)
+{
+
+	if (current->pid)
+		profile_tick(CPU_PROFILING);
+
+	xtime_update(1);
+
+	update_process_times(user_mode(get_irq_regs()));
+
+	return(IRQ_HANDLED);
+}
+#endif
+
+static unsigned long read_rtc_mmss(void)
+{
+	unsigned int year, mon, day, hour, min, sec;
+
+	if (mach_gettod) {
+		mach_gettod(&year, &mon, &day, &hour, &min, &sec);
+		if ((year += 1900) < 1970)
+			year += 100;
+	} else {
+		year = 1970;
+		mon = day = 1;
+		hour = min = sec = 0;
+	}
+
+
+	return  mktime(year, mon, day, hour, min, sec);
+}
+
+void read_persistent_clock(struct timespec *ts)
+{
+	ts->tv_sec = read_rtc_mmss();
+	ts->tv_nsec = 0;
+}
+
+int update_persistent_clock(struct timespec now)
+{
+	return set_rtc_mmss(now.tv_sec);
+}
+
+void time_init(void)
+{
+	hw_timer_init();
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/traps.c linux-libre-2.6.39-gnu/arch/m68k/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,1203 +1,5 @@
-/*
- *  linux/arch/m68k/kernel/traps.c
- *
- *  Copyright (C) 1993, 1994 by Hamish Macdonald
- *
- *  68040 fixes by Michael Rausch
- *  68040 fixes by Martin Apel
- *  68040 fixes and writeback by Richard Zidlicky
- *  68060 fixes by Roman Hodek
- *  68060 fixes by Jesper Skov
- *
- * 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.
- */
-
-/*
- * Sets up all exception vectors
- */
-
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/kallsyms.h>
-
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/pgalloc.h>
-#include <asm/machdep.h>
-#include <asm/siginfo.h>
-
-/* assembler routines */
-asmlinkage void system_call(void);
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void nmihandler(void);
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpu_emu(void);
-#endif
-
-e_vector vectors[256] = {
-	[VEC_BUSERR]	= buserr,
-	[VEC_SYS]	= system_call,
-};
-
-/* nmi handler for the Amiga */
-asm(".text\n"
-    __ALIGN_STR "\n"
-    "nmihandler: rte");
-
-/*
- * this must be called very early as the kernel might
- * use some instruction that are emulated on the 060
- */
-void __init base_trap_init(void)
-{
-	if(MACH_IS_SUN3X) {
-		extern e_vector *sun3x_prom_vbr;
-
-		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
-	}
-
-	/* setup the exception vector table */
-	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
-
-	if (CPU_IS_060) {
-		/* set up ISP entry points */
-		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
-
-		vectors[VEC_UNIMPII] = unimp_vec;
-	}
-}
-
-void __init trap_init (void)
-{
-	int i;
-
-	for (i = VEC_SPUR; i <= VEC_INT7; i++)
-		vectors[i] = bad_inthandler;
-
-	for (i = 0; i < VEC_USER; i++)
-		if (!vectors[i])
-			vectors[i] = trap;
-
-	for (i = VEC_USER; i < 256; i++)
-		vectors[i] = bad_inthandler;
-
-#ifdef CONFIG_M68KFPU_EMU
-	if (FPU_IS_EMU)
-		vectors[VEC_LINE11] = fpu_emu;
-#endif
-
-	if (CPU_IS_040 && !FPU_IS_EMU) {
-		/* set up FPSP entry points */
-		asmlinkage void dz_vec(void) asm ("dz");
-		asmlinkage void inex_vec(void) asm ("inex");
-		asmlinkage void ovfl_vec(void) asm ("ovfl");
-		asmlinkage void unfl_vec(void) asm ("unfl");
-		asmlinkage void snan_vec(void) asm ("snan");
-		asmlinkage void operr_vec(void) asm ("operr");
-		asmlinkage void bsun_vec(void) asm ("bsun");
-		asmlinkage void fline_vec(void) asm ("fline");
-		asmlinkage void unsupp_vec(void) asm ("unsupp");
-
-		vectors[VEC_FPDIVZ] = dz_vec;
-		vectors[VEC_FPIR] = inex_vec;
-		vectors[VEC_FPOVER] = ovfl_vec;
-		vectors[VEC_FPUNDER] = unfl_vec;
-		vectors[VEC_FPNAN] = snan_vec;
-		vectors[VEC_FPOE] = operr_vec;
-		vectors[VEC_FPBRUC] = bsun_vec;
-		vectors[VEC_LINE11] = fline_vec;
-		vectors[VEC_FPUNSUP] = unsupp_vec;
-	}
-
-	if (CPU_IS_060 && !FPU_IS_EMU) {
-		/* set up IFPSP entry points */
-		asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
-		asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
-		asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
-		asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
-		asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
-		asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
-		asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
-		asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
-		asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
-
-		vectors[VEC_FPNAN] = snan_vec6;
-		vectors[VEC_FPOE] = operr_vec6;
-		vectors[VEC_FPOVER] = ovfl_vec6;
-		vectors[VEC_FPUNDER] = unfl_vec6;
-		vectors[VEC_FPDIVZ] = dz_vec6;
-		vectors[VEC_FPIR] = inex_vec6;
-		vectors[VEC_LINE11] = fline_vec6;
-		vectors[VEC_FPUNSUP] = unsupp_vec6;
-		vectors[VEC_UNIMPEA] = effadd_vec6;
-	}
-
-        /* if running on an amiga, make the NMI interrupt do nothing */
-	if (MACH_IS_AMIGA) {
-		vectors[VEC_INT7] = nmihandler;
-	}
-}
-
-
-static const char *vec_names[] = {
-	[VEC_RESETSP]	= "RESET SP",
-	[VEC_RESETPC]	= "RESET PC",
-	[VEC_BUSERR]	= "BUS ERROR",
-	[VEC_ADDRERR]	= "ADDRESS ERROR",
-	[VEC_ILLEGAL]	= "ILLEGAL INSTRUCTION",
-	[VEC_ZERODIV]	= "ZERO DIVIDE",
-	[VEC_CHK]	= "CHK",
-	[VEC_TRAP]	= "TRAPcc",
-	[VEC_PRIV]	= "PRIVILEGE VIOLATION",
-	[VEC_TRACE]	= "TRACE",
-	[VEC_LINE10]	= "LINE 1010",
-	[VEC_LINE11]	= "LINE 1111",
-	[VEC_RESV12]	= "UNASSIGNED RESERVED 12",
-	[VEC_COPROC]	= "COPROCESSOR PROTOCOL VIOLATION",
-	[VEC_FORMAT]	= "FORMAT ERROR",
-	[VEC_UNINT]	= "UNINITIALIZED INTERRUPT",
-	[VEC_RESV16]	= "UNASSIGNED RESERVED 16",
-	[VEC_RESV17]	= "UNASSIGNED RESERVED 17",
-	[VEC_RESV18]	= "UNASSIGNED RESERVED 18",
-	[VEC_RESV19]	= "UNASSIGNED RESERVED 19",
-	[VEC_RESV20]	= "UNASSIGNED RESERVED 20",
-	[VEC_RESV21]	= "UNASSIGNED RESERVED 21",
-	[VEC_RESV22]	= "UNASSIGNED RESERVED 22",
-	[VEC_RESV23]	= "UNASSIGNED RESERVED 23",
-	[VEC_SPUR]	= "SPURIOUS INTERRUPT",
-	[VEC_INT1]	= "LEVEL 1 INT",
-	[VEC_INT2]	= "LEVEL 2 INT",
-	[VEC_INT3]	= "LEVEL 3 INT",
-	[VEC_INT4]	= "LEVEL 4 INT",
-	[VEC_INT5]	= "LEVEL 5 INT",
-	[VEC_INT6]	= "LEVEL 6 INT",
-	[VEC_INT7]	= "LEVEL 7 INT",
-	[VEC_SYS]	= "SYSCALL",
-	[VEC_TRAP1]	= "TRAP #1",
-	[VEC_TRAP2]	= "TRAP #2",
-	[VEC_TRAP3]	= "TRAP #3",
-	[VEC_TRAP4]	= "TRAP #4",
-	[VEC_TRAP5]	= "TRAP #5",
-	[VEC_TRAP6]	= "TRAP #6",
-	[VEC_TRAP7]	= "TRAP #7",
-	[VEC_TRAP8]	= "TRAP #8",
-	[VEC_TRAP9]	= "TRAP #9",
-	[VEC_TRAP10]	= "TRAP #10",
-	[VEC_TRAP11]	= "TRAP #11",
-	[VEC_TRAP12]	= "TRAP #12",
-	[VEC_TRAP13]	= "TRAP #13",
-	[VEC_TRAP14]	= "TRAP #14",
-	[VEC_TRAP15]	= "TRAP #15",
-	[VEC_FPBRUC]	= "FPCP BSUN",
-	[VEC_FPIR]	= "FPCP INEXACT",
-	[VEC_FPDIVZ]	= "FPCP DIV BY 0",
-	[VEC_FPUNDER]	= "FPCP UNDERFLOW",
-	[VEC_FPOE]	= "FPCP OPERAND ERROR",
-	[VEC_FPOVER]	= "FPCP OVERFLOW",
-	[VEC_FPNAN]	= "FPCP SNAN",
-	[VEC_FPUNSUP]	= "FPCP UNSUPPORTED OPERATION",
-	[VEC_MMUCFG]	= "MMU CONFIGURATION ERROR",
-	[VEC_MMUILL]	= "MMU ILLEGAL OPERATION ERROR",
-	[VEC_MMUACC]	= "MMU ACCESS LEVEL VIOLATION ERROR",
-	[VEC_RESV59]	= "UNASSIGNED RESERVED 59",
-	[VEC_UNIMPEA]	= "UNASSIGNED RESERVED 60",
-	[VEC_UNIMPII]	= "UNASSIGNED RESERVED 61",
-	[VEC_RESV62]	= "UNASSIGNED RESERVED 62",
-	[VEC_RESV63]	= "UNASSIGNED RESERVED 63",
-};
-
-static const char *space_names[] = {
-	[0]		= "Space 0",
-	[USER_DATA]	= "User Data",
-	[USER_PROGRAM]	= "User Program",
-#ifndef CONFIG_SUN3
-	[3]		= "Space 3",
-#else
-	[FC_CONTROL]	= "Control",
-#endif
-	[4]		= "Space 4",
-	[SUPER_DATA]	= "Super Data",
-	[SUPER_PROGRAM]	= "Super Program",
-	[CPU_SPACE]	= "CPU"
-};
-
-void die_if_kernel(char *,struct pt_regs *,int);
-asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
-                             unsigned long error_code);
-int send_fault_sig(struct pt_regs *regs);
-
-asmlinkage void trap_c(struct frame *fp);
-
-#if defined (CONFIG_M68060)
-static inline void access_error060 (struct frame *fp)
-{
-	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
-
-#ifdef DEBUG
-	printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
-#endif
-
-	if (fslw & MMU060_BPE) {
-		/* branch prediction error -> clear branch cache */
-		__asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
-				      "orl   #0x00400000,%/d0\n\t"
-				      "movec %/d0,%/cacr"
-				      : : : "d0" );
-		/* return if there's no other error */
-		if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
-			return;
-	}
-
-	if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
-		unsigned long errorcode;
-		unsigned long addr = fp->un.fmt4.effaddr;
-
-		if (fslw & MMU060_MA)
-			addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
-
-		errorcode = 1;
-		if (fslw & MMU060_DESC_ERR) {
-			__flush_tlb040_one(addr);
-			errorcode = 0;
-		}
-		if (fslw & MMU060_W)
-			errorcode |= 2;
-#ifdef DEBUG
-		printk("errorcode = %d\n", errorcode );
-#endif
-		do_page_fault(&fp->ptregs, addr, errorcode);
-	} else if (fslw & (MMU060_SEE)){
-		/* Software Emulation Error.
-		 * fault during mem_read/mem_write in ifpsp060/os.S
-		 */
-		send_fault_sig(&fp->ptregs);
-	} else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
-		   send_fault_sig(&fp->ptregs) > 0) {
-		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
-		printk( "68060 access error, fslw=%lx\n", fslw );
-		trap_c( fp );
-	}
-}
-#endif /* CONFIG_M68060 */
-
-#if defined (CONFIG_M68040)
-static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
-{
-	unsigned long mmusr;
-	mm_segment_t old_fs = get_fs();
-
-	set_fs(MAKE_MM_SEG(wbs));
-
-	if (iswrite)
-		asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
-	else
-		asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
-
-	asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
-
-	set_fs(old_fs);
-
-	return mmusr;
-}
-
-static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
-				   unsigned long wbd)
-{
-	int res = 0;
-	mm_segment_t old_fs = get_fs();
-
-	/* set_fs can not be moved, otherwise put_user() may oops */
-	set_fs(MAKE_MM_SEG(wbs));
-
-	switch (wbs & WBSIZ_040) {
-	case BA_SIZE_BYTE:
-		res = put_user(wbd & 0xff, (char __user *)wba);
-		break;
-	case BA_SIZE_WORD:
-		res = put_user(wbd & 0xffff, (short __user *)wba);
-		break;
-	case BA_SIZE_LONG:
-		res = put_user(wbd, (int __user *)wba);
-		break;
-	}
-
-	/* set_fs can not be moved, otherwise put_user() may oops */
-	set_fs(old_fs);
-
-
-#ifdef DEBUG
-	printk("do_040writeback1, res=%d\n",res);
-#endif
-
-	return res;
-}
-
-/* after an exception in a writeback the stack frame corresponding
- * to that exception is discarded, set a few bits in the old frame
- * to simulate what it should look like
- */
-static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
-{
-	fp->un.fmt7.faddr = wba;
-	fp->un.fmt7.ssw = wbs & 0xff;
-	if (wba != current->thread.faddr)
-	    fp->un.fmt7.ssw |= MA_040;
-}
-
-static inline void do_040writebacks(struct frame *fp)
-{
-	int res = 0;
-#if 0
-	if (fp->un.fmt7.wb1s & WBV_040)
-		printk("access_error040: cannot handle 1st writeback. oops.\n");
-#endif
-
-	if ((fp->un.fmt7.wb2s & WBV_040) &&
-	    !(fp->un.fmt7.wb2s & WBTT_040)) {
-		res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
-				       fp->un.fmt7.wb2d);
-		if (res)
-			fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
-		else
-			fp->un.fmt7.wb2s = 0;
-	}
-
-	/* do the 2nd wb only if the first one was successful (except for a kernel wb) */
-	if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
-		res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
-				       fp->un.fmt7.wb3d);
-		if (res)
-		    {
-			fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
-
-			fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
-			fp->un.fmt7.wb3s &= (~WBV_040);
-			fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
-			fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
-		    }
-		else
-			fp->un.fmt7.wb3s = 0;
-	}
-
-	if (res)
-		send_fault_sig(&fp->ptregs);
-}
-
-/*
- * called from sigreturn(), must ensure userspace code didn't
- * manipulate exception frame to circumvent protection, then complete
- * pending writebacks
- * we just clear TM2 to turn it into a userspace access
- */
-asmlinkage void berr_040cleanup(struct frame *fp)
-{
-	fp->un.fmt7.wb2s &= ~4;
-	fp->un.fmt7.wb3s &= ~4;
-
-	do_040writebacks(fp);
-}
-
-static inline void access_error040(struct frame *fp)
-{
-	unsigned short ssw = fp->un.fmt7.ssw;
-	unsigned long mmusr;
-
-#ifdef DEBUG
-	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
-        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
-		fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
-	printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
-		fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
-		fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
-#endif
-
-	if (ssw & ATC_040) {
-		unsigned long addr = fp->un.fmt7.faddr;
-		unsigned long errorcode;
-
-		/*
-		 * The MMU status has to be determined AFTER the address
-		 * has been corrected if there was a misaligned access (MA).
-		 */
-		if (ssw & MA_040)
-			addr = (addr + 7) & -8;
-
-		/* MMU error, get the MMUSR info for this access */
-		mmusr = probe040(!(ssw & RW_040), addr, ssw);
-#ifdef DEBUG
-		printk("mmusr = %lx\n", mmusr);
-#endif
-		errorcode = 1;
-		if (!(mmusr & MMU_R_040)) {
-			/* clear the invalid atc entry */
-			__flush_tlb040_one(addr);
-			errorcode = 0;
-		}
-
-		/* despite what documentation seems to say, RMW
-		 * accesses have always both the LK and RW bits set */
-		if (!(ssw & RW_040) || (ssw & LK_040))
-			errorcode |= 2;
-
-		if (do_page_fault(&fp->ptregs, addr, errorcode)) {
-#ifdef DEBUG
-			printk("do_page_fault() !=0\n");
-#endif
-			if (user_mode(&fp->ptregs)){
-				/* delay writebacks after signal delivery */
-#ifdef DEBUG
-			        printk(".. was usermode - return\n");
-#endif
-				return;
-			}
-			/* disable writeback into user space from kernel
-			 * (if do_page_fault didn't fix the mapping,
-                         * the writeback won't do good)
-			 */
-disable_wb:
-#ifdef DEBUG
-			printk(".. disabling wb2\n");
-#endif
-			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
-				fp->un.fmt7.wb2s &= ~WBV_040;
-			if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
-				fp->un.fmt7.wb3s &= ~WBV_040;
-		}
-	} else {
-		/* In case of a bus error we either kill the process or expect
-		 * the kernel to catch the fault, which then is also responsible
-		 * for cleaning up the mess.
-		 */
-		current->thread.signo = SIGBUS;
-		current->thread.faddr = fp->un.fmt7.faddr;
-		if (send_fault_sig(&fp->ptregs) >= 0)
-			printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
-			       fp->un.fmt7.faddr);
-		goto disable_wb;
-	}
-
-	do_040writebacks(fp);
-}
-#endif /* CONFIG_M68040 */
-
-#if defined(CONFIG_SUN3)
-#include <asm/sun3mmu.h>
-
-extern int mmu_emu_handle_fault (unsigned long, int, int);
-
-/* sun3 version of bus_error030 */
-
-static inline void bus_error030 (struct frame *fp)
-{
-	unsigned char buserr_type = sun3_get_buserr ();
-	unsigned long addr, errorcode;
-	unsigned short ssw = fp->un.fmtb.ssw;
-	extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
-
-#ifdef DEBUG
-	if (ssw & (FC | FB))
-		printk ("Instruction fault at %#010lx\n",
-			ssw & FC ?
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
-			:
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
-	if (ssw & DF)
-		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-			ssw & RW ? "read" : "write",
-			fp->un.fmtb.daddr,
-			space_names[ssw & DFC], fp->ptregs.pc);
-#endif
-
-	/*
-	 * Check if this page should be demand-mapped. This needs to go before
-	 * the testing for a bad kernel-space access (demand-mapping applies
-	 * to kernel accesses too).
-	 */
-
-	if ((ssw & DF)
-	    && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
-		if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
-			return;
-	}
-
-	/* Check for kernel-space pagefault (BAD). */
-	if (fp->ptregs.sr & PS_S) {
-		/* kernel fault must be a data fault to user space */
-		if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
-		     // try checking the kernel mappings before surrender
-		     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
-			  return;
-			/* instruction fault or kernel data fault! */
-			if (ssw & (FC | FB))
-				printk ("Instruction fault at %#010lx\n",
-					fp->ptregs.pc);
-			if (ssw & DF) {
-				/* was this fault incurred testing bus mappings? */
-				if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
-				   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
-					send_fault_sig(&fp->ptregs);
-					return;
-				}
-
-				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-					ssw & RW ? "read" : "write",
-					fp->un.fmtb.daddr,
-					space_names[ssw & DFC], fp->ptregs.pc);
-			}
-			printk ("BAD KERNEL BUSERR\n");
-
-			die_if_kernel("Oops", &fp->ptregs,0);
-			force_sig(SIGKILL, current);
-			return;
-		}
-	} else {
-		/* user fault */
-		if (!(ssw & (FC | FB)) && !(ssw & DF))
-			/* not an instruction fault or data fault! BAD */
-			panic ("USER BUSERR w/o instruction or data fault");
-	}
-
-
-	/* First handle the data fault, if any.  */
-	if (ssw & DF) {
-		addr = fp->un.fmtb.daddr;
-
-// errorcode bit 0:	0 -> no page		1 -> protection fault
-// errorcode bit 1:	0 -> read fault		1 -> write fault
-
-// (buserr_type & SUN3_BUSERR_PROTERR)	-> protection fault
-// (buserr_type & SUN3_BUSERR_INVALID)	-> invalid page fault
-
-		if (buserr_type & SUN3_BUSERR_PROTERR)
-			errorcode = 0x01;
-		else if (buserr_type & SUN3_BUSERR_INVALID)
-			errorcode = 0x00;
-		else {
-#ifdef DEBUG
-			printk ("*** unexpected busfault type=%#04x\n", buserr_type);
-			printk ("invalid %s access at %#lx from pc %#lx\n",
-				!(ssw & RW) ? "write" : "read", addr,
-				fp->ptregs.pc);
-#endif
-			die_if_kernel ("Oops", &fp->ptregs, buserr_type);
-			force_sig (SIGBUS, current);
-			return;
-		}
-
-//todo: wtf is RM bit? --m
-		if (!(ssw & RW) || ssw & RM)
-			errorcode |= 0x02;
-
-		/* Handle page fault. */
-		do_page_fault (&fp->ptregs, addr, errorcode);
-
-		/* Retry the data fault now. */
-		return;
-	}
-
-	/* Now handle the instruction fault. */
-
-	/* Get the fault address. */
-	if (fp->ptregs.format == 0xA)
-		addr = fp->ptregs.pc + 4;
-	else
-		addr = fp->un.fmtb.baddr;
-	if (ssw & FC)
-		addr -= 2;
-
-	if (buserr_type & SUN3_BUSERR_INVALID) {
-		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
-			do_page_fault (&fp->ptregs, addr, 0);
-       } else {
-#ifdef DEBUG
-		printk ("protection fault on insn access (segv).\n");
-#endif
-		force_sig (SIGSEGV, current);
-       }
-}
-#else
-#if defined(CPU_M68020_OR_M68030)
-static inline void bus_error030 (struct frame *fp)
-{
-	volatile unsigned short temp;
-	unsigned short mmusr;
-	unsigned long addr, errorcode;
-	unsigned short ssw = fp->un.fmtb.ssw;
-#ifdef DEBUG
-	unsigned long desc;
-
-	printk ("pid = %x  ", current->pid);
-	printk ("SSW=%#06x  ", ssw);
-
-	if (ssw & (FC | FB))
-		printk ("Instruction fault at %#010lx\n",
-			ssw & FC ?
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
-			:
-			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
-	if (ssw & DF)
-		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-			ssw & RW ? "read" : "write",
-			fp->un.fmtb.daddr,
-			space_names[ssw & DFC], fp->ptregs.pc);
-#endif
-
-	/* ++andreas: If a data fault and an instruction fault happen
-	   at the same time map in both pages.  */
-
-	/* First handle the data fault, if any.  */
-	if (ssw & DF) {
-		addr = fp->un.fmtb.daddr;
-
-#ifdef DEBUG
-		asm volatile ("ptestr %3,%2@,#7,%0\n\t"
-			      "pmove %%psr,%1@"
-			      : "=a&" (desc)
-			      : "a" (&temp), "a" (addr), "d" (ssw));
-#else
-		asm volatile ("ptestr %2,%1@,#7\n\t"
-			      "pmove %%psr,%0@"
-			      : : "a" (&temp), "a" (addr), "d" (ssw));
-#endif
-		mmusr = temp;
-
-#ifdef DEBUG
-		printk("mmusr is %#x for addr %#lx in task %p\n",
-		       mmusr, addr, current);
-		printk("descriptor address is %#lx, contents %#lx\n",
-		       __va(desc), *(unsigned long *)__va(desc));
-#endif
-
-		errorcode = (mmusr & MMU_I) ? 0 : 1;
-		if (!(ssw & RW) || (ssw & RM))
-			errorcode |= 2;
-
-		if (mmusr & (MMU_I | MMU_WP)) {
-			if (ssw & 4) {
-				printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-				       ssw & RW ? "read" : "write",
-				       fp->un.fmtb.daddr,
-				       space_names[ssw & DFC], fp->ptregs.pc);
-				goto buserr;
-			}
-			/* Don't try to do anything further if an exception was
-			   handled. */
-			if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
-				return;
-		} else if (!(mmusr & MMU_I)) {
-			/* probably a 020 cas fault */
-			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
-				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
-		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
-			printk("invalid %s access at %#lx from pc %#lx\n",
-			       !(ssw & RW) ? "write" : "read", addr,
-			       fp->ptregs.pc);
-			die_if_kernel("Oops",&fp->ptregs,mmusr);
-			force_sig(SIGSEGV, current);
-			return;
-		} else {
-#if 0
-			static volatile long tlong;
-#endif
-
-			printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
-			       !(ssw & RW) ? "write" : "read", addr,
-			       fp->ptregs.pc, ssw);
-			asm volatile ("ptestr #1,%1@,#0\n\t"
-				      "pmove %%psr,%0@"
-				      : /* no outputs */
-				      : "a" (&temp), "a" (addr));
-			mmusr = temp;
-
-			printk ("level 0 mmusr is %#x\n", mmusr);
-#if 0
-			asm volatile ("pmove %%tt0,%0@"
-				      : /* no outputs */
-				      : "a" (&tlong));
-			printk("tt0 is %#lx, ", tlong);
-			asm volatile ("pmove %%tt1,%0@"
-				      : /* no outputs */
-				      : "a" (&tlong));
-			printk("tt1 is %#lx\n", tlong);
-#endif
-#ifdef DEBUG
-			printk("Unknown SIGSEGV - 1\n");
-#endif
-			die_if_kernel("Oops",&fp->ptregs,mmusr);
-			force_sig(SIGSEGV, current);
-			return;
-		}
-
-		/* setup an ATC entry for the access about to be retried */
-		if (!(ssw & RW) || (ssw & RM))
-			asm volatile ("ploadw %1,%0@" : /* no outputs */
-				      : "a" (addr), "d" (ssw));
-		else
-			asm volatile ("ploadr %1,%0@" : /* no outputs */
-				      : "a" (addr), "d" (ssw));
-	}
-
-	/* Now handle the instruction fault. */
-
-	if (!(ssw & (FC|FB)))
-		return;
-
-	if (fp->ptregs.sr & PS_S) {
-		printk("Instruction fault at %#010lx\n",
-			fp->ptregs.pc);
-	buserr:
-		printk ("BAD KERNEL BUSERR\n");
-		die_if_kernel("Oops",&fp->ptregs,0);
-		force_sig(SIGKILL, current);
-		return;
-	}
-
-	/* get the fault address */
-	if (fp->ptregs.format == 10)
-		addr = fp->ptregs.pc + 4;
-	else
-		addr = fp->un.fmtb.baddr;
-	if (ssw & FC)
-		addr -= 2;
-
-	if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
-		/* Insn fault on same page as data fault.  But we
-		   should still create the ATC entry.  */
-		goto create_atc_entry;
-
-#ifdef DEBUG
-	asm volatile ("ptestr #1,%2@,#7,%0\n\t"
-		      "pmove %%psr,%1@"
-		      : "=a&" (desc)
-		      : "a" (&temp), "a" (addr));
+#ifdef CONFIG_MMU
+#include "traps_mm.c"
 #else
-	asm volatile ("ptestr #1,%1@,#7\n\t"
-		      "pmove %%psr,%0@"
-		      : : "a" (&temp), "a" (addr));
-#endif
-	mmusr = temp;
-
-#ifdef DEBUG
-	printk ("mmusr is %#x for addr %#lx in task %p\n",
-		mmusr, addr, current);
-	printk ("descriptor address is %#lx, contents %#lx\n",
-		__va(desc), *(unsigned long *)__va(desc));
-#endif
-
-	if (mmusr & MMU_I)
-		do_page_fault (&fp->ptregs, addr, 0);
-	else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
-		printk ("invalid insn access at %#lx from pc %#lx\n",
-			addr, fp->ptregs.pc);
-#ifdef DEBUG
-		printk("Unknown SIGSEGV - 2\n");
-#endif
-		die_if_kernel("Oops",&fp->ptregs,mmusr);
-		force_sig(SIGSEGV, current);
-		return;
-	}
-
-create_atc_entry:
-	/* setup an ATC entry for the access about to be retried */
-	asm volatile ("ploadr #2,%0@" : /* no outputs */
-		      : "a" (addr));
-}
-#endif /* CPU_M68020_OR_M68030 */
-#endif /* !CONFIG_SUN3 */
-
-asmlinkage void buserr_c(struct frame *fp)
-{
-	/* Only set esp0 if coming from user mode */
-	if (user_mode(&fp->ptregs))
-		current->thread.esp0 = (unsigned long) fp;
-
-#ifdef DEBUG
-	printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
-
-	switch (fp->ptregs.format) {
-#if defined (CONFIG_M68060)
-	case 4:				/* 68060 access error */
-	  access_error060 (fp);
-	  break;
-#endif
-#if defined (CONFIG_M68040)
-	case 0x7:			/* 68040 access error */
-	  access_error040 (fp);
-	  break;
-#endif
-#if defined (CPU_M68020_OR_M68030)
-	case 0xa:
-	case 0xb:
-	  bus_error030 (fp);
-	  break;
-#endif
-	default:
-	  die_if_kernel("bad frame format",&fp->ptregs,0);
-#ifdef DEBUG
-	  printk("Unknown SIGSEGV - 4\n");
-#endif
-	  force_sig(SIGSEGV, current);
-	}
-}
-
-
-static int kstack_depth_to_print = 48;
-
-void show_trace(unsigned long *stack)
-{
-	unsigned long *endstack;
-	unsigned long addr;
-	int i;
-
-	printk("Call Trace:");
-	addr = (unsigned long)stack + THREAD_SIZE - 1;
-	endstack = (unsigned long *)(addr & -THREAD_SIZE);
-	i = 0;
-	while (stack + 1 <= endstack) {
-		addr = *stack++;
-		/*
-		 * If the address is either in the text segment of the
-		 * kernel, or in the region which contains vmalloc'ed
-		 * memory, it *may* be the address of a calling
-		 * routine; if so, print it so that someone tracing
-		 * down the cause of the crash will be able to figure
-		 * out the call path that was taken.
-		 */
-		if (__kernel_text_address(addr)) {
-#ifndef CONFIG_KALLSYMS
-			if (i % 5 == 0)
-				printk("\n       ");
-#endif
-			printk(" [<%08lx>] %pS\n", addr, (void *)addr);
-			i++;
-		}
-	}
-	printk("\n");
-}
-
-void show_registers(struct pt_regs *regs)
-{
-	struct frame *fp = (struct frame *)regs;
-	mm_segment_t old_fs = get_fs();
-	u16 c, *cp;
-	unsigned long addr;
-	int i;
-
-	print_modules();
-	printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
-	printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
-	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-	       regs->d0, regs->d1, regs->d2, regs->d3);
-	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
-	       regs->d4, regs->d5, regs->a0, regs->a1);
-
-	printk("Process %s (pid: %d, task=%p)\n",
-		current->comm, task_pid_nr(current), current);
-	addr = (unsigned long)&fp->un;
-	printk("Frame format=%X ", regs->format);
-	switch (regs->format) {
-	case 0x2:
-		printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
-		addr += sizeof(fp->un.fmt2);
-		break;
-	case 0x3:
-		printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
-		addr += sizeof(fp->un.fmt3);
-		break;
-	case 0x4:
-		printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
-			: "eff addr=%08lx pc=%08lx\n"),
-			fp->un.fmt4.effaddr, fp->un.fmt4.pc);
-		addr += sizeof(fp->un.fmt4);
-		break;
-	case 0x7:
-		printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
-			fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
-		printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
-			fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
-		printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
-			fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
-		printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
-			fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
-		printk("push data: %08lx %08lx %08lx %08lx\n",
-			fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
-			fp->un.fmt7.pd3);
-		addr += sizeof(fp->un.fmt7);
-		break;
-	case 0x9:
-		printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
-		addr += sizeof(fp->un.fmt9);
-		break;
-	case 0xa:
-		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
-			fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
-			fp->un.fmta.daddr, fp->un.fmta.dobuf);
-		addr += sizeof(fp->un.fmta);
-		break;
-	case 0xb:
-		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
-			fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
-			fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
-		printk("baddr=%08lx dibuf=%08lx ver=%x\n",
-			fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
-		addr += sizeof(fp->un.fmtb);
-		break;
-	default:
-		printk("\n");
-	}
-	show_stack(NULL, (unsigned long *)addr);
-
-	printk("Code:");
-	set_fs(KERNEL_DS);
-	cp = (u16 *)regs->pc;
-	for (i = -8; i < 16; i++) {
-		if (get_user(c, cp + i) && i >= 0) {
-			printk(" Bad PC value.");
-			break;
-		}
-		printk(i ? " %04x" : " <%04x>", c);
-	}
-	set_fs(old_fs);
-	printk ("\n");
-}
-
-void show_stack(struct task_struct *task, unsigned long *stack)
-{
-	unsigned long *p;
-	unsigned long *endstack;
-	int i;
-
-	if (!stack) {
-		if (task)
-			stack = (unsigned long *)task->thread.esp0;
-		else
-			stack = (unsigned long *)&stack;
-	}
-	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
-
-	printk("Stack from %08lx:", (unsigned long)stack);
-	p = stack;
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (p + 1 > endstack)
-			break;
-		if (i % 8 == 0)
-			printk("\n       ");
-		printk(" %08lx", *p++);
-	}
-	printk("\n");
-	show_trace(stack);
-}
-
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
-	unsigned long stack;
-
-	show_trace(&stack);
-}
-
-EXPORT_SYMBOL(dump_stack);
-
-void bad_super_trap (struct frame *fp)
-{
-	console_verbose();
-	if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
-		printk ("*** %s ***   FORMAT=%X\n",
-			vec_names[(fp->ptregs.vector) >> 2],
-			fp->ptregs.format);
-	else
-		printk ("*** Exception %d ***   FORMAT=%X\n",
-			(fp->ptregs.vector) >> 2,
-			fp->ptregs.format);
-	if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
-		unsigned short ssw = fp->un.fmtb.ssw;
-
-		printk ("SSW=%#06x  ", ssw);
-
-		if (ssw & RC)
-			printk ("Pipe stage C instruction fault at %#010lx\n",
-				(fp->ptregs.format) == 0xA ?
-				fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
-		if (ssw & RB)
-			printk ("Pipe stage B instruction fault at %#010lx\n",
-				(fp->ptregs.format) == 0xA ?
-				fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
-		if (ssw & DF)
-			printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
-				ssw & RW ? "read" : "write",
-				fp->un.fmtb.daddr, space_names[ssw & DFC],
-				fp->ptregs.pc);
-	}
-	printk ("Current process id is %d\n", task_pid_nr(current));
-	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
-}
-
-asmlinkage void trap_c(struct frame *fp)
-{
-	int sig;
-	siginfo_t info;
-
-	if (fp->ptregs.sr & PS_S) {
-		if ((fp->ptregs.vector >> 2) == VEC_TRACE) {
-			/* traced a trapping instruction */
-		} else
-			bad_super_trap(fp);
-		return;
-	}
-
-	/* send the appropriate signal to the user program */
-	switch ((fp->ptregs.vector) >> 2) {
-	    case VEC_ADDRERR:
-		info.si_code = BUS_ADRALN;
-		sig = SIGBUS;
-		break;
-	    case VEC_ILLEGAL:
-	    case VEC_LINE10:
-	    case VEC_LINE11:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_PRIV:
-		info.si_code = ILL_PRVOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_COPROC:
-		info.si_code = ILL_COPROC;
-		sig = SIGILL;
-		break;
-	    case VEC_TRAP1:
-	    case VEC_TRAP2:
-	    case VEC_TRAP3:
-	    case VEC_TRAP4:
-	    case VEC_TRAP5:
-	    case VEC_TRAP6:
-	    case VEC_TRAP7:
-	    case VEC_TRAP8:
-	    case VEC_TRAP9:
-	    case VEC_TRAP10:
-	    case VEC_TRAP11:
-	    case VEC_TRAP12:
-	    case VEC_TRAP13:
-	    case VEC_TRAP14:
-		info.si_code = ILL_ILLTRP;
-		sig = SIGILL;
-		break;
-	    case VEC_FPBRUC:
-	    case VEC_FPOE:
-	    case VEC_FPNAN:
-		info.si_code = FPE_FLTINV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPIR:
-		info.si_code = FPE_FLTRES;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPDIVZ:
-		info.si_code = FPE_FLTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPUNDER:
-		info.si_code = FPE_FLTUND;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPOVER:
-		info.si_code = FPE_FLTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_ZERODIV:
-		info.si_code = FPE_INTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_CHK:
-	    case VEC_TRAP:
-		info.si_code = FPE_INTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_TRACE:		/* ptrace single step */
-		info.si_code = TRAP_TRACE;
-		sig = SIGTRAP;
-		break;
-	    case VEC_TRAP15:		/* breakpoint */
-		info.si_code = TRAP_BRKPT;
-		sig = SIGTRAP;
-		break;
-	    default:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	}
-	info.si_signo = sig;
-	info.si_errno = 0;
-	switch (fp->ptregs.format) {
-	    default:
-		info.si_addr = (void *) fp->ptregs.pc;
-		break;
-	    case 2:
-		info.si_addr = (void *) fp->un.fmt2.iaddr;
-		break;
-	    case 7:
-		info.si_addr = (void *) fp->un.fmt7.effaddr;
-		break;
-	    case 9:
-		info.si_addr = (void *) fp->un.fmt9.iaddr;
-		break;
-	    case 10:
-		info.si_addr = (void *) fp->un.fmta.daddr;
-		break;
-	    case 11:
-		info.si_addr = (void *) fp->un.fmtb.daddr;
-		break;
-	}
-	force_sig_info (sig, &info, current);
-}
-
-void die_if_kernel (char *str, struct pt_regs *fp, int nr)
-{
-	if (!(fp->sr & PS_S))
-		return;
-
-	console_verbose();
-	printk("%s: %08x\n",str,nr);
-	show_registers(fp);
-	add_taint(TAINT_DIE);
-	do_exit(SIGSEGV);
-}
-
-/*
- * This function is called if an error occur while accessing
- * user-space from the fpsp040 code.
- */
-asmlinkage void fpsp040_die(void)
-{
-	do_exit(SIGSEGV);
-}
-
-#ifdef CONFIG_M68KFPU_EMU
-asmlinkage void fpemu_signal(int signal, int code, void *addr)
-{
-	siginfo_t info;
-
-	info.si_signo = signal;
-	info.si_errno = 0;
-	info.si_code = code;
-	info.si_addr = addr;
-	force_sig_info(signal, &info, current);
-}
+#include "traps_no.c"
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/traps_mm.c linux-libre-2.6.39-gnu/arch/m68k/kernel/traps_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/traps_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/traps_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1207 @@
+/*
+ *  linux/arch/m68k/kernel/traps.c
+ *
+ *  Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ *  68040 fixes by Michael Rausch
+ *  68040 fixes by Martin Apel
+ *  68040 fixes and writeback by Richard Zidlicky
+ *  68060 fixes by Roman Hodek
+ *  68060 fixes by Jesper Skov
+ *
+ * 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.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/pgalloc.h>
+#include <asm/machdep.h>
+#include <asm/siginfo.h>
+
+/* assembler routines */
+asmlinkage void system_call(void);
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void nmihandler(void);
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpu_emu(void);
+#endif
+
+e_vector vectors[256];
+
+/* nmi handler for the Amiga */
+asm(".text\n"
+    __ALIGN_STR "\n"
+    "nmihandler: rte");
+
+/*
+ * this must be called very early as the kernel might
+ * use some instruction that are emulated on the 060
+ * and so we're prepared for early probe attempts (e.g. nf_init).
+ */
+void __init base_trap_init(void)
+{
+	if (MACH_IS_SUN3X) {
+		extern e_vector *sun3x_prom_vbr;
+
+		__asm__ volatile ("movec %%vbr, %0" : "=r" (sun3x_prom_vbr));
+	}
+
+	/* setup the exception vector table */
+	__asm__ volatile ("movec %0,%%vbr" : : "r" ((void*)vectors));
+
+	if (CPU_IS_060) {
+		/* set up ISP entry points */
+		asmlinkage void unimp_vec(void) asm ("_060_isp_unimp");
+
+		vectors[VEC_UNIMPII] = unimp_vec;
+	}
+
+	vectors[VEC_BUSERR] = buserr;
+	vectors[VEC_ILLEGAL] = trap;
+	vectors[VEC_SYS] = system_call;
+}
+
+void __init trap_init (void)
+{
+	int i;
+
+	for (i = VEC_SPUR; i <= VEC_INT7; i++)
+		vectors[i] = bad_inthandler;
+
+	for (i = 0; i < VEC_USER; i++)
+		if (!vectors[i])
+			vectors[i] = trap;
+
+	for (i = VEC_USER; i < 256; i++)
+		vectors[i] = bad_inthandler;
+
+#ifdef CONFIG_M68KFPU_EMU
+	if (FPU_IS_EMU)
+		vectors[VEC_LINE11] = fpu_emu;
+#endif
+
+	if (CPU_IS_040 && !FPU_IS_EMU) {
+		/* set up FPSP entry points */
+		asmlinkage void dz_vec(void) asm ("dz");
+		asmlinkage void inex_vec(void) asm ("inex");
+		asmlinkage void ovfl_vec(void) asm ("ovfl");
+		asmlinkage void unfl_vec(void) asm ("unfl");
+		asmlinkage void snan_vec(void) asm ("snan");
+		asmlinkage void operr_vec(void) asm ("operr");
+		asmlinkage void bsun_vec(void) asm ("bsun");
+		asmlinkage void fline_vec(void) asm ("fline");
+		asmlinkage void unsupp_vec(void) asm ("unsupp");
+
+		vectors[VEC_FPDIVZ] = dz_vec;
+		vectors[VEC_FPIR] = inex_vec;
+		vectors[VEC_FPOVER] = ovfl_vec;
+		vectors[VEC_FPUNDER] = unfl_vec;
+		vectors[VEC_FPNAN] = snan_vec;
+		vectors[VEC_FPOE] = operr_vec;
+		vectors[VEC_FPBRUC] = bsun_vec;
+		vectors[VEC_LINE11] = fline_vec;
+		vectors[VEC_FPUNSUP] = unsupp_vec;
+	}
+
+	if (CPU_IS_060 && !FPU_IS_EMU) {
+		/* set up IFPSP entry points */
+		asmlinkage void snan_vec6(void) asm ("_060_fpsp_snan");
+		asmlinkage void operr_vec6(void) asm ("_060_fpsp_operr");
+		asmlinkage void ovfl_vec6(void) asm ("_060_fpsp_ovfl");
+		asmlinkage void unfl_vec6(void) asm ("_060_fpsp_unfl");
+		asmlinkage void dz_vec6(void) asm ("_060_fpsp_dz");
+		asmlinkage void inex_vec6(void) asm ("_060_fpsp_inex");
+		asmlinkage void fline_vec6(void) asm ("_060_fpsp_fline");
+		asmlinkage void unsupp_vec6(void) asm ("_060_fpsp_unsupp");
+		asmlinkage void effadd_vec6(void) asm ("_060_fpsp_effadd");
+
+		vectors[VEC_FPNAN] = snan_vec6;
+		vectors[VEC_FPOE] = operr_vec6;
+		vectors[VEC_FPOVER] = ovfl_vec6;
+		vectors[VEC_FPUNDER] = unfl_vec6;
+		vectors[VEC_FPDIVZ] = dz_vec6;
+		vectors[VEC_FPIR] = inex_vec6;
+		vectors[VEC_LINE11] = fline_vec6;
+		vectors[VEC_FPUNSUP] = unsupp_vec6;
+		vectors[VEC_UNIMPEA] = effadd_vec6;
+	}
+
+        /* if running on an amiga, make the NMI interrupt do nothing */
+	if (MACH_IS_AMIGA) {
+		vectors[VEC_INT7] = nmihandler;
+	}
+}
+
+
+static const char *vec_names[] = {
+	[VEC_RESETSP]	= "RESET SP",
+	[VEC_RESETPC]	= "RESET PC",
+	[VEC_BUSERR]	= "BUS ERROR",
+	[VEC_ADDRERR]	= "ADDRESS ERROR",
+	[VEC_ILLEGAL]	= "ILLEGAL INSTRUCTION",
+	[VEC_ZERODIV]	= "ZERO DIVIDE",
+	[VEC_CHK]	= "CHK",
+	[VEC_TRAP]	= "TRAPcc",
+	[VEC_PRIV]	= "PRIVILEGE VIOLATION",
+	[VEC_TRACE]	= "TRACE",
+	[VEC_LINE10]	= "LINE 1010",
+	[VEC_LINE11]	= "LINE 1111",
+	[VEC_RESV12]	= "UNASSIGNED RESERVED 12",
+	[VEC_COPROC]	= "COPROCESSOR PROTOCOL VIOLATION",
+	[VEC_FORMAT]	= "FORMAT ERROR",
+	[VEC_UNINT]	= "UNINITIALIZED INTERRUPT",
+	[VEC_RESV16]	= "UNASSIGNED RESERVED 16",
+	[VEC_RESV17]	= "UNASSIGNED RESERVED 17",
+	[VEC_RESV18]	= "UNASSIGNED RESERVED 18",
+	[VEC_RESV19]	= "UNASSIGNED RESERVED 19",
+	[VEC_RESV20]	= "UNASSIGNED RESERVED 20",
+	[VEC_RESV21]	= "UNASSIGNED RESERVED 21",
+	[VEC_RESV22]	= "UNASSIGNED RESERVED 22",
+	[VEC_RESV23]	= "UNASSIGNED RESERVED 23",
+	[VEC_SPUR]	= "SPURIOUS INTERRUPT",
+	[VEC_INT1]	= "LEVEL 1 INT",
+	[VEC_INT2]	= "LEVEL 2 INT",
+	[VEC_INT3]	= "LEVEL 3 INT",
+	[VEC_INT4]	= "LEVEL 4 INT",
+	[VEC_INT5]	= "LEVEL 5 INT",
+	[VEC_INT6]	= "LEVEL 6 INT",
+	[VEC_INT7]	= "LEVEL 7 INT",
+	[VEC_SYS]	= "SYSCALL",
+	[VEC_TRAP1]	= "TRAP #1",
+	[VEC_TRAP2]	= "TRAP #2",
+	[VEC_TRAP3]	= "TRAP #3",
+	[VEC_TRAP4]	= "TRAP #4",
+	[VEC_TRAP5]	= "TRAP #5",
+	[VEC_TRAP6]	= "TRAP #6",
+	[VEC_TRAP7]	= "TRAP #7",
+	[VEC_TRAP8]	= "TRAP #8",
+	[VEC_TRAP9]	= "TRAP #9",
+	[VEC_TRAP10]	= "TRAP #10",
+	[VEC_TRAP11]	= "TRAP #11",
+	[VEC_TRAP12]	= "TRAP #12",
+	[VEC_TRAP13]	= "TRAP #13",
+	[VEC_TRAP14]	= "TRAP #14",
+	[VEC_TRAP15]	= "TRAP #15",
+	[VEC_FPBRUC]	= "FPCP BSUN",
+	[VEC_FPIR]	= "FPCP INEXACT",
+	[VEC_FPDIVZ]	= "FPCP DIV BY 0",
+	[VEC_FPUNDER]	= "FPCP UNDERFLOW",
+	[VEC_FPOE]	= "FPCP OPERAND ERROR",
+	[VEC_FPOVER]	= "FPCP OVERFLOW",
+	[VEC_FPNAN]	= "FPCP SNAN",
+	[VEC_FPUNSUP]	= "FPCP UNSUPPORTED OPERATION",
+	[VEC_MMUCFG]	= "MMU CONFIGURATION ERROR",
+	[VEC_MMUILL]	= "MMU ILLEGAL OPERATION ERROR",
+	[VEC_MMUACC]	= "MMU ACCESS LEVEL VIOLATION ERROR",
+	[VEC_RESV59]	= "UNASSIGNED RESERVED 59",
+	[VEC_UNIMPEA]	= "UNASSIGNED RESERVED 60",
+	[VEC_UNIMPII]	= "UNASSIGNED RESERVED 61",
+	[VEC_RESV62]	= "UNASSIGNED RESERVED 62",
+	[VEC_RESV63]	= "UNASSIGNED RESERVED 63",
+};
+
+static const char *space_names[] = {
+	[0]		= "Space 0",
+	[USER_DATA]	= "User Data",
+	[USER_PROGRAM]	= "User Program",
+#ifndef CONFIG_SUN3
+	[3]		= "Space 3",
+#else
+	[FC_CONTROL]	= "Control",
+#endif
+	[4]		= "Space 4",
+	[SUPER_DATA]	= "Super Data",
+	[SUPER_PROGRAM]	= "Super Program",
+	[CPU_SPACE]	= "CPU"
+};
+
+void die_if_kernel(char *,struct pt_regs *,int);
+asmlinkage int do_page_fault(struct pt_regs *regs, unsigned long address,
+                             unsigned long error_code);
+int send_fault_sig(struct pt_regs *regs);
+
+asmlinkage void trap_c(struct frame *fp);
+
+#if defined (CONFIG_M68060)
+static inline void access_error060 (struct frame *fp)
+{
+	unsigned long fslw = fp->un.fmt4.pc; /* is really FSLW for access error */
+
+#ifdef DEBUG
+	printk("fslw=%#lx, fa=%#lx\n", fslw, fp->un.fmt4.effaddr);
+#endif
+
+	if (fslw & MMU060_BPE) {
+		/* branch prediction error -> clear branch cache */
+		__asm__ __volatile__ ("movec %/cacr,%/d0\n\t"
+				      "orl   #0x00400000,%/d0\n\t"
+				      "movec %/d0,%/cacr"
+				      : : : "d0" );
+		/* return if there's no other error */
+		if (!(fslw & MMU060_ERR_BITS) && !(fslw & MMU060_SEE))
+			return;
+	}
+
+	if (fslw & (MMU060_DESC_ERR | MMU060_WP | MMU060_SP)) {
+		unsigned long errorcode;
+		unsigned long addr = fp->un.fmt4.effaddr;
+
+		if (fslw & MMU060_MA)
+			addr = (addr + PAGE_SIZE - 1) & PAGE_MASK;
+
+		errorcode = 1;
+		if (fslw & MMU060_DESC_ERR) {
+			__flush_tlb040_one(addr);
+			errorcode = 0;
+		}
+		if (fslw & MMU060_W)
+			errorcode |= 2;
+#ifdef DEBUG
+		printk("errorcode = %d\n", errorcode );
+#endif
+		do_page_fault(&fp->ptregs, addr, errorcode);
+	} else if (fslw & (MMU060_SEE)){
+		/* Software Emulation Error.
+		 * fault during mem_read/mem_write in ifpsp060/os.S
+		 */
+		send_fault_sig(&fp->ptregs);
+	} else if (!(fslw & (MMU060_RE|MMU060_WE)) ||
+		   send_fault_sig(&fp->ptregs) > 0) {
+		printk("pc=%#lx, fa=%#lx\n", fp->ptregs.pc, fp->un.fmt4.effaddr);
+		printk( "68060 access error, fslw=%lx\n", fslw );
+		trap_c( fp );
+	}
+}
+#endif /* CONFIG_M68060 */
+
+#if defined (CONFIG_M68040)
+static inline unsigned long probe040(int iswrite, unsigned long addr, int wbs)
+{
+	unsigned long mmusr;
+	mm_segment_t old_fs = get_fs();
+
+	set_fs(MAKE_MM_SEG(wbs));
+
+	if (iswrite)
+		asm volatile (".chip 68040; ptestw (%0); .chip 68k" : : "a" (addr));
+	else
+		asm volatile (".chip 68040; ptestr (%0); .chip 68k" : : "a" (addr));
+
+	asm volatile (".chip 68040; movec %%mmusr,%0; .chip 68k" : "=r" (mmusr));
+
+	set_fs(old_fs);
+
+	return mmusr;
+}
+
+static inline int do_040writeback1(unsigned short wbs, unsigned long wba,
+				   unsigned long wbd)
+{
+	int res = 0;
+	mm_segment_t old_fs = get_fs();
+
+	/* set_fs can not be moved, otherwise put_user() may oops */
+	set_fs(MAKE_MM_SEG(wbs));
+
+	switch (wbs & WBSIZ_040) {
+	case BA_SIZE_BYTE:
+		res = put_user(wbd & 0xff, (char __user *)wba);
+		break;
+	case BA_SIZE_WORD:
+		res = put_user(wbd & 0xffff, (short __user *)wba);
+		break;
+	case BA_SIZE_LONG:
+		res = put_user(wbd, (int __user *)wba);
+		break;
+	}
+
+	/* set_fs can not be moved, otherwise put_user() may oops */
+	set_fs(old_fs);
+
+
+#ifdef DEBUG
+	printk("do_040writeback1, res=%d\n",res);
+#endif
+
+	return res;
+}
+
+/* after an exception in a writeback the stack frame corresponding
+ * to that exception is discarded, set a few bits in the old frame
+ * to simulate what it should look like
+ */
+static inline void fix_xframe040(struct frame *fp, unsigned long wba, unsigned short wbs)
+{
+	fp->un.fmt7.faddr = wba;
+	fp->un.fmt7.ssw = wbs & 0xff;
+	if (wba != current->thread.faddr)
+	    fp->un.fmt7.ssw |= MA_040;
+}
+
+static inline void do_040writebacks(struct frame *fp)
+{
+	int res = 0;
+#if 0
+	if (fp->un.fmt7.wb1s & WBV_040)
+		printk("access_error040: cannot handle 1st writeback. oops.\n");
+#endif
+
+	if ((fp->un.fmt7.wb2s & WBV_040) &&
+	    !(fp->un.fmt7.wb2s & WBTT_040)) {
+		res = do_040writeback1(fp->un.fmt7.wb2s, fp->un.fmt7.wb2a,
+				       fp->un.fmt7.wb2d);
+		if (res)
+			fix_xframe040(fp, fp->un.fmt7.wb2a, fp->un.fmt7.wb2s);
+		else
+			fp->un.fmt7.wb2s = 0;
+	}
+
+	/* do the 2nd wb only if the first one was successful (except for a kernel wb) */
+	if (fp->un.fmt7.wb3s & WBV_040 && (!res || fp->un.fmt7.wb3s & 4)) {
+		res = do_040writeback1(fp->un.fmt7.wb3s, fp->un.fmt7.wb3a,
+				       fp->un.fmt7.wb3d);
+		if (res)
+		    {
+			fix_xframe040(fp, fp->un.fmt7.wb3a, fp->un.fmt7.wb3s);
+
+			fp->un.fmt7.wb2s = fp->un.fmt7.wb3s;
+			fp->un.fmt7.wb3s &= (~WBV_040);
+			fp->un.fmt7.wb2a = fp->un.fmt7.wb3a;
+			fp->un.fmt7.wb2d = fp->un.fmt7.wb3d;
+		    }
+		else
+			fp->un.fmt7.wb3s = 0;
+	}
+
+	if (res)
+		send_fault_sig(&fp->ptregs);
+}
+
+/*
+ * called from sigreturn(), must ensure userspace code didn't
+ * manipulate exception frame to circumvent protection, then complete
+ * pending writebacks
+ * we just clear TM2 to turn it into a userspace access
+ */
+asmlinkage void berr_040cleanup(struct frame *fp)
+{
+	fp->un.fmt7.wb2s &= ~4;
+	fp->un.fmt7.wb3s &= ~4;
+
+	do_040writebacks(fp);
+}
+
+static inline void access_error040(struct frame *fp)
+{
+	unsigned short ssw = fp->un.fmt7.ssw;
+	unsigned long mmusr;
+
+#ifdef DEBUG
+	printk("ssw=%#x, fa=%#lx\n", ssw, fp->un.fmt7.faddr);
+        printk("wb1s=%#x, wb2s=%#x, wb3s=%#x\n", fp->un.fmt7.wb1s,
+		fp->un.fmt7.wb2s, fp->un.fmt7.wb3s);
+	printk ("wb2a=%lx, wb3a=%lx, wb2d=%lx, wb3d=%lx\n",
+		fp->un.fmt7.wb2a, fp->un.fmt7.wb3a,
+		fp->un.fmt7.wb2d, fp->un.fmt7.wb3d);
+#endif
+
+	if (ssw & ATC_040) {
+		unsigned long addr = fp->un.fmt7.faddr;
+		unsigned long errorcode;
+
+		/*
+		 * The MMU status has to be determined AFTER the address
+		 * has been corrected if there was a misaligned access (MA).
+		 */
+		if (ssw & MA_040)
+			addr = (addr + 7) & -8;
+
+		/* MMU error, get the MMUSR info for this access */
+		mmusr = probe040(!(ssw & RW_040), addr, ssw);
+#ifdef DEBUG
+		printk("mmusr = %lx\n", mmusr);
+#endif
+		errorcode = 1;
+		if (!(mmusr & MMU_R_040)) {
+			/* clear the invalid atc entry */
+			__flush_tlb040_one(addr);
+			errorcode = 0;
+		}
+
+		/* despite what documentation seems to say, RMW
+		 * accesses have always both the LK and RW bits set */
+		if (!(ssw & RW_040) || (ssw & LK_040))
+			errorcode |= 2;
+
+		if (do_page_fault(&fp->ptregs, addr, errorcode)) {
+#ifdef DEBUG
+			printk("do_page_fault() !=0\n");
+#endif
+			if (user_mode(&fp->ptregs)){
+				/* delay writebacks after signal delivery */
+#ifdef DEBUG
+			        printk(".. was usermode - return\n");
+#endif
+				return;
+			}
+			/* disable writeback into user space from kernel
+			 * (if do_page_fault didn't fix the mapping,
+                         * the writeback won't do good)
+			 */
+disable_wb:
+#ifdef DEBUG
+			printk(".. disabling wb2\n");
+#endif
+			if (fp->un.fmt7.wb2a == fp->un.fmt7.faddr)
+				fp->un.fmt7.wb2s &= ~WBV_040;
+			if (fp->un.fmt7.wb3a == fp->un.fmt7.faddr)
+				fp->un.fmt7.wb3s &= ~WBV_040;
+		}
+	} else {
+		/* In case of a bus error we either kill the process or expect
+		 * the kernel to catch the fault, which then is also responsible
+		 * for cleaning up the mess.
+		 */
+		current->thread.signo = SIGBUS;
+		current->thread.faddr = fp->un.fmt7.faddr;
+		if (send_fault_sig(&fp->ptregs) >= 0)
+			printk("68040 bus error (ssw=%x, faddr=%lx)\n", ssw,
+			       fp->un.fmt7.faddr);
+		goto disable_wb;
+	}
+
+	do_040writebacks(fp);
+}
+#endif /* CONFIG_M68040 */
+
+#if defined(CONFIG_SUN3)
+#include <asm/sun3mmu.h>
+
+extern int mmu_emu_handle_fault (unsigned long, int, int);
+
+/* sun3 version of bus_error030 */
+
+static inline void bus_error030 (struct frame *fp)
+{
+	unsigned char buserr_type = sun3_get_buserr ();
+	unsigned long addr, errorcode;
+	unsigned short ssw = fp->un.fmtb.ssw;
+	extern unsigned long _sun3_map_test_start, _sun3_map_test_end;
+
+#ifdef DEBUG
+	if (ssw & (FC | FB))
+		printk ("Instruction fault at %#010lx\n",
+			ssw & FC ?
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+			:
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+	if (ssw & DF)
+		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+			ssw & RW ? "read" : "write",
+			fp->un.fmtb.daddr,
+			space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+	/*
+	 * Check if this page should be demand-mapped. This needs to go before
+	 * the testing for a bad kernel-space access (demand-mapping applies
+	 * to kernel accesses too).
+	 */
+
+	if ((ssw & DF)
+	    && (buserr_type & (SUN3_BUSERR_PROTERR | SUN3_BUSERR_INVALID))) {
+		if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 0))
+			return;
+	}
+
+	/* Check for kernel-space pagefault (BAD). */
+	if (fp->ptregs.sr & PS_S) {
+		/* kernel fault must be a data fault to user space */
+		if (! ((ssw & DF) && ((ssw & DFC) == USER_DATA))) {
+		     // try checking the kernel mappings before surrender
+		     if (mmu_emu_handle_fault (fp->un.fmtb.daddr, ssw & RW, 1))
+			  return;
+			/* instruction fault or kernel data fault! */
+			if (ssw & (FC | FB))
+				printk ("Instruction fault at %#010lx\n",
+					fp->ptregs.pc);
+			if (ssw & DF) {
+				/* was this fault incurred testing bus mappings? */
+				if((fp->ptregs.pc >= (unsigned long)&_sun3_map_test_start) &&
+				   (fp->ptregs.pc <= (unsigned long)&_sun3_map_test_end)) {
+					send_fault_sig(&fp->ptregs);
+					return;
+				}
+
+				printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+					ssw & RW ? "read" : "write",
+					fp->un.fmtb.daddr,
+					space_names[ssw & DFC], fp->ptregs.pc);
+			}
+			printk ("BAD KERNEL BUSERR\n");
+
+			die_if_kernel("Oops", &fp->ptregs,0);
+			force_sig(SIGKILL, current);
+			return;
+		}
+	} else {
+		/* user fault */
+		if (!(ssw & (FC | FB)) && !(ssw & DF))
+			/* not an instruction fault or data fault! BAD */
+			panic ("USER BUSERR w/o instruction or data fault");
+	}
+
+
+	/* First handle the data fault, if any.  */
+	if (ssw & DF) {
+		addr = fp->un.fmtb.daddr;
+
+// errorcode bit 0:	0 -> no page		1 -> protection fault
+// errorcode bit 1:	0 -> read fault		1 -> write fault
+
+// (buserr_type & SUN3_BUSERR_PROTERR)	-> protection fault
+// (buserr_type & SUN3_BUSERR_INVALID)	-> invalid page fault
+
+		if (buserr_type & SUN3_BUSERR_PROTERR)
+			errorcode = 0x01;
+		else if (buserr_type & SUN3_BUSERR_INVALID)
+			errorcode = 0x00;
+		else {
+#ifdef DEBUG
+			printk ("*** unexpected busfault type=%#04x\n", buserr_type);
+			printk ("invalid %s access at %#lx from pc %#lx\n",
+				!(ssw & RW) ? "write" : "read", addr,
+				fp->ptregs.pc);
+#endif
+			die_if_kernel ("Oops", &fp->ptregs, buserr_type);
+			force_sig (SIGBUS, current);
+			return;
+		}
+
+//todo: wtf is RM bit? --m
+		if (!(ssw & RW) || ssw & RM)
+			errorcode |= 0x02;
+
+		/* Handle page fault. */
+		do_page_fault (&fp->ptregs, addr, errorcode);
+
+		/* Retry the data fault now. */
+		return;
+	}
+
+	/* Now handle the instruction fault. */
+
+	/* Get the fault address. */
+	if (fp->ptregs.format == 0xA)
+		addr = fp->ptregs.pc + 4;
+	else
+		addr = fp->un.fmtb.baddr;
+	if (ssw & FC)
+		addr -= 2;
+
+	if (buserr_type & SUN3_BUSERR_INVALID) {
+		if (!mmu_emu_handle_fault (fp->un.fmtb.daddr, 1, 0))
+			do_page_fault (&fp->ptregs, addr, 0);
+       } else {
+#ifdef DEBUG
+		printk ("protection fault on insn access (segv).\n");
+#endif
+		force_sig (SIGSEGV, current);
+       }
+}
+#else
+#if defined(CPU_M68020_OR_M68030)
+static inline void bus_error030 (struct frame *fp)
+{
+	volatile unsigned short temp;
+	unsigned short mmusr;
+	unsigned long addr, errorcode;
+	unsigned short ssw = fp->un.fmtb.ssw;
+#ifdef DEBUG
+	unsigned long desc;
+
+	printk ("pid = %x  ", current->pid);
+	printk ("SSW=%#06x  ", ssw);
+
+	if (ssw & (FC | FB))
+		printk ("Instruction fault at %#010lx\n",
+			ssw & FC ?
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2
+			:
+			fp->ptregs.format == 0xa ? fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+	if (ssw & DF)
+		printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+			ssw & RW ? "read" : "write",
+			fp->un.fmtb.daddr,
+			space_names[ssw & DFC], fp->ptregs.pc);
+#endif
+
+	/* ++andreas: If a data fault and an instruction fault happen
+	   at the same time map in both pages.  */
+
+	/* First handle the data fault, if any.  */
+	if (ssw & DF) {
+		addr = fp->un.fmtb.daddr;
+
+#ifdef DEBUG
+		asm volatile ("ptestr %3,%2@,#7,%0\n\t"
+			      "pmove %%psr,%1@"
+			      : "=a&" (desc)
+			      : "a" (&temp), "a" (addr), "d" (ssw));
+#else
+		asm volatile ("ptestr %2,%1@,#7\n\t"
+			      "pmove %%psr,%0@"
+			      : : "a" (&temp), "a" (addr), "d" (ssw));
+#endif
+		mmusr = temp;
+
+#ifdef DEBUG
+		printk("mmusr is %#x for addr %#lx in task %p\n",
+		       mmusr, addr, current);
+		printk("descriptor address is %#lx, contents %#lx\n",
+		       __va(desc), *(unsigned long *)__va(desc));
+#endif
+
+		errorcode = (mmusr & MMU_I) ? 0 : 1;
+		if (!(ssw & RW) || (ssw & RM))
+			errorcode |= 2;
+
+		if (mmusr & (MMU_I | MMU_WP)) {
+			if (ssw & 4) {
+				printk("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+				       ssw & RW ? "read" : "write",
+				       fp->un.fmtb.daddr,
+				       space_names[ssw & DFC], fp->ptregs.pc);
+				goto buserr;
+			}
+			/* Don't try to do anything further if an exception was
+			   handled. */
+			if (do_page_fault (&fp->ptregs, addr, errorcode) < 0)
+				return;
+		} else if (!(mmusr & MMU_I)) {
+			/* probably a 020 cas fault */
+			if (!(ssw & RM) && send_fault_sig(&fp->ptregs) > 0)
+				printk("unexpected bus error (%#x,%#x)\n", ssw, mmusr);
+		} else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
+			printk("invalid %s access at %#lx from pc %#lx\n",
+			       !(ssw & RW) ? "write" : "read", addr,
+			       fp->ptregs.pc);
+			die_if_kernel("Oops",&fp->ptregs,mmusr);
+			force_sig(SIGSEGV, current);
+			return;
+		} else {
+#if 0
+			static volatile long tlong;
+#endif
+
+			printk("weird %s access at %#lx from pc %#lx (ssw is %#x)\n",
+			       !(ssw & RW) ? "write" : "read", addr,
+			       fp->ptregs.pc, ssw);
+			asm volatile ("ptestr #1,%1@,#0\n\t"
+				      "pmove %%psr,%0@"
+				      : /* no outputs */
+				      : "a" (&temp), "a" (addr));
+			mmusr = temp;
+
+			printk ("level 0 mmusr is %#x\n", mmusr);
+#if 0
+			asm volatile ("pmove %%tt0,%0@"
+				      : /* no outputs */
+				      : "a" (&tlong));
+			printk("tt0 is %#lx, ", tlong);
+			asm volatile ("pmove %%tt1,%0@"
+				      : /* no outputs */
+				      : "a" (&tlong));
+			printk("tt1 is %#lx\n", tlong);
+#endif
+#ifdef DEBUG
+			printk("Unknown SIGSEGV - 1\n");
+#endif
+			die_if_kernel("Oops",&fp->ptregs,mmusr);
+			force_sig(SIGSEGV, current);
+			return;
+		}
+
+		/* setup an ATC entry for the access about to be retried */
+		if (!(ssw & RW) || (ssw & RM))
+			asm volatile ("ploadw %1,%0@" : /* no outputs */
+				      : "a" (addr), "d" (ssw));
+		else
+			asm volatile ("ploadr %1,%0@" : /* no outputs */
+				      : "a" (addr), "d" (ssw));
+	}
+
+	/* Now handle the instruction fault. */
+
+	if (!(ssw & (FC|FB)))
+		return;
+
+	if (fp->ptregs.sr & PS_S) {
+		printk("Instruction fault at %#010lx\n",
+			fp->ptregs.pc);
+	buserr:
+		printk ("BAD KERNEL BUSERR\n");
+		die_if_kernel("Oops",&fp->ptregs,0);
+		force_sig(SIGKILL, current);
+		return;
+	}
+
+	/* get the fault address */
+	if (fp->ptregs.format == 10)
+		addr = fp->ptregs.pc + 4;
+	else
+		addr = fp->un.fmtb.baddr;
+	if (ssw & FC)
+		addr -= 2;
+
+	if ((ssw & DF) && ((addr ^ fp->un.fmtb.daddr) & PAGE_MASK) == 0)
+		/* Insn fault on same page as data fault.  But we
+		   should still create the ATC entry.  */
+		goto create_atc_entry;
+
+#ifdef DEBUG
+	asm volatile ("ptestr #1,%2@,#7,%0\n\t"
+		      "pmove %%psr,%1@"
+		      : "=a&" (desc)
+		      : "a" (&temp), "a" (addr));
+#else
+	asm volatile ("ptestr #1,%1@,#7\n\t"
+		      "pmove %%psr,%0@"
+		      : : "a" (&temp), "a" (addr));
+#endif
+	mmusr = temp;
+
+#ifdef DEBUG
+	printk ("mmusr is %#x for addr %#lx in task %p\n",
+		mmusr, addr, current);
+	printk ("descriptor address is %#lx, contents %#lx\n",
+		__va(desc), *(unsigned long *)__va(desc));
+#endif
+
+	if (mmusr & MMU_I)
+		do_page_fault (&fp->ptregs, addr, 0);
+	else if (mmusr & (MMU_B|MMU_L|MMU_S)) {
+		printk ("invalid insn access at %#lx from pc %#lx\n",
+			addr, fp->ptregs.pc);
+#ifdef DEBUG
+		printk("Unknown SIGSEGV - 2\n");
+#endif
+		die_if_kernel("Oops",&fp->ptregs,mmusr);
+		force_sig(SIGSEGV, current);
+		return;
+	}
+
+create_atc_entry:
+	/* setup an ATC entry for the access about to be retried */
+	asm volatile ("ploadr #2,%0@" : /* no outputs */
+		      : "a" (addr));
+}
+#endif /* CPU_M68020_OR_M68030 */
+#endif /* !CONFIG_SUN3 */
+
+asmlinkage void buserr_c(struct frame *fp)
+{
+	/* Only set esp0 if coming from user mode */
+	if (user_mode(&fp->ptregs))
+		current->thread.esp0 = (unsigned long) fp;
+
+#ifdef DEBUG
+	printk ("*** Bus Error *** Format is %x\n", fp->ptregs.format);
+#endif
+
+	switch (fp->ptregs.format) {
+#if defined (CONFIG_M68060)
+	case 4:				/* 68060 access error */
+	  access_error060 (fp);
+	  break;
+#endif
+#if defined (CONFIG_M68040)
+	case 0x7:			/* 68040 access error */
+	  access_error040 (fp);
+	  break;
+#endif
+#if defined (CPU_M68020_OR_M68030)
+	case 0xa:
+	case 0xb:
+	  bus_error030 (fp);
+	  break;
+#endif
+	default:
+	  die_if_kernel("bad frame format",&fp->ptregs,0);
+#ifdef DEBUG
+	  printk("Unknown SIGSEGV - 4\n");
+#endif
+	  force_sig(SIGSEGV, current);
+	}
+}
+
+
+static int kstack_depth_to_print = 48;
+
+void show_trace(unsigned long *stack)
+{
+	unsigned long *endstack;
+	unsigned long addr;
+	int i;
+
+	printk("Call Trace:");
+	addr = (unsigned long)stack + THREAD_SIZE - 1;
+	endstack = (unsigned long *)(addr & -THREAD_SIZE);
+	i = 0;
+	while (stack + 1 <= endstack) {
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the
+		 * kernel, or in the region which contains vmalloc'ed
+		 * memory, it *may* be the address of a calling
+		 * routine; if so, print it so that someone tracing
+		 * down the cause of the crash will be able to figure
+		 * out the call path that was taken.
+		 */
+		if (__kernel_text_address(addr)) {
+#ifndef CONFIG_KALLSYMS
+			if (i % 5 == 0)
+				printk("\n       ");
+#endif
+			printk(" [<%08lx>] %pS\n", addr, (void *)addr);
+			i++;
+		}
+	}
+	printk("\n");
+}
+
+void show_registers(struct pt_regs *regs)
+{
+	struct frame *fp = (struct frame *)regs;
+	mm_segment_t old_fs = get_fs();
+	u16 c, *cp;
+	unsigned long addr;
+	int i;
+
+	print_modules();
+	printk("PC: [<%08lx>] %pS\n", regs->pc, (void *)regs->pc);
+	printk("SR: %04x  SP: %p  a2: %08lx\n", regs->sr, regs, regs->a2);
+	printk("d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
+	       regs->d0, regs->d1, regs->d2, regs->d3);
+	printk("d4: %08lx    d5: %08lx    a0: %08lx    a1: %08lx\n",
+	       regs->d4, regs->d5, regs->a0, regs->a1);
+
+	printk("Process %s (pid: %d, task=%p)\n",
+		current->comm, task_pid_nr(current), current);
+	addr = (unsigned long)&fp->un;
+	printk("Frame format=%X ", regs->format);
+	switch (regs->format) {
+	case 0x2:
+		printk("instr addr=%08lx\n", fp->un.fmt2.iaddr);
+		addr += sizeof(fp->un.fmt2);
+		break;
+	case 0x3:
+		printk("eff addr=%08lx\n", fp->un.fmt3.effaddr);
+		addr += sizeof(fp->un.fmt3);
+		break;
+	case 0x4:
+		printk((CPU_IS_060 ? "fault addr=%08lx fslw=%08lx\n"
+			: "eff addr=%08lx pc=%08lx\n"),
+			fp->un.fmt4.effaddr, fp->un.fmt4.pc);
+		addr += sizeof(fp->un.fmt4);
+		break;
+	case 0x7:
+		printk("eff addr=%08lx ssw=%04x faddr=%08lx\n",
+			fp->un.fmt7.effaddr, fp->un.fmt7.ssw, fp->un.fmt7.faddr);
+		printk("wb 1 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb1s, fp->un.fmt7.wb1a, fp->un.fmt7.wb1dpd0);
+		printk("wb 2 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb2s, fp->un.fmt7.wb2a, fp->un.fmt7.wb2d);
+		printk("wb 3 stat/addr/data: %04x %08lx %08lx\n",
+			fp->un.fmt7.wb3s, fp->un.fmt7.wb3a, fp->un.fmt7.wb3d);
+		printk("push data: %08lx %08lx %08lx %08lx\n",
+			fp->un.fmt7.wb1dpd0, fp->un.fmt7.pd1, fp->un.fmt7.pd2,
+			fp->un.fmt7.pd3);
+		addr += sizeof(fp->un.fmt7);
+		break;
+	case 0x9:
+		printk("instr addr=%08lx\n", fp->un.fmt9.iaddr);
+		addr += sizeof(fp->un.fmt9);
+		break;
+	case 0xa:
+		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+			fp->un.fmta.ssw, fp->un.fmta.isc, fp->un.fmta.isb,
+			fp->un.fmta.daddr, fp->un.fmta.dobuf);
+		addr += sizeof(fp->un.fmta);
+		break;
+	case 0xb:
+		printk("ssw=%04x isc=%04x isb=%04x daddr=%08lx dobuf=%08lx\n",
+			fp->un.fmtb.ssw, fp->un.fmtb.isc, fp->un.fmtb.isb,
+			fp->un.fmtb.daddr, fp->un.fmtb.dobuf);
+		printk("baddr=%08lx dibuf=%08lx ver=%x\n",
+			fp->un.fmtb.baddr, fp->un.fmtb.dibuf, fp->un.fmtb.ver);
+		addr += sizeof(fp->un.fmtb);
+		break;
+	default:
+		printk("\n");
+	}
+	show_stack(NULL, (unsigned long *)addr);
+
+	printk("Code:");
+	set_fs(KERNEL_DS);
+	cp = (u16 *)regs->pc;
+	for (i = -8; i < 16; i++) {
+		if (get_user(c, cp + i) && i >= 0) {
+			printk(" Bad PC value.");
+			break;
+		}
+		printk(i ? " %04x" : " <%04x>", c);
+	}
+	set_fs(old_fs);
+	printk ("\n");
+}
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	unsigned long *p;
+	unsigned long *endstack;
+	int i;
+
+	if (!stack) {
+		if (task)
+			stack = (unsigned long *)task->thread.esp0;
+		else
+			stack = (unsigned long *)&stack;
+	}
+	endstack = (unsigned long *)(((unsigned long)stack + THREAD_SIZE - 1) & -THREAD_SIZE);
+
+	printk("Stack from %08lx:", (unsigned long)stack);
+	p = stack;
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (p + 1 > endstack)
+			break;
+		if (i % 8 == 0)
+			printk("\n       ");
+		printk(" %08lx", *p++);
+	}
+	printk("\n");
+	show_trace(stack);
+}
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+	unsigned long stack;
+
+	show_trace(&stack);
+}
+
+EXPORT_SYMBOL(dump_stack);
+
+void bad_super_trap (struct frame *fp)
+{
+	console_verbose();
+	if (fp->ptregs.vector < 4 * ARRAY_SIZE(vec_names))
+		printk ("*** %s ***   FORMAT=%X\n",
+			vec_names[(fp->ptregs.vector) >> 2],
+			fp->ptregs.format);
+	else
+		printk ("*** Exception %d ***   FORMAT=%X\n",
+			(fp->ptregs.vector) >> 2,
+			fp->ptregs.format);
+	if (fp->ptregs.vector >> 2 == VEC_ADDRERR && CPU_IS_020_OR_030) {
+		unsigned short ssw = fp->un.fmtb.ssw;
+
+		printk ("SSW=%#06x  ", ssw);
+
+		if (ssw & RC)
+			printk ("Pipe stage C instruction fault at %#010lx\n",
+				(fp->ptregs.format) == 0xA ?
+				fp->ptregs.pc + 2 : fp->un.fmtb.baddr - 2);
+		if (ssw & RB)
+			printk ("Pipe stage B instruction fault at %#010lx\n",
+				(fp->ptregs.format) == 0xA ?
+				fp->ptregs.pc + 4 : fp->un.fmtb.baddr);
+		if (ssw & DF)
+			printk ("Data %s fault at %#010lx in %s (pc=%#lx)\n",
+				ssw & RW ? "read" : "write",
+				fp->un.fmtb.daddr, space_names[ssw & DFC],
+				fp->ptregs.pc);
+	}
+	printk ("Current process id is %d\n", task_pid_nr(current));
+	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
+}
+
+asmlinkage void trap_c(struct frame *fp)
+{
+	int sig;
+	siginfo_t info;
+
+	if (fp->ptregs.sr & PS_S) {
+		if (fp->ptregs.vector == VEC_TRACE << 2) {
+			/* traced a trapping instruction on a 68020/30,
+			 * real exception will be executed afterwards.
+			 */
+		} else if (!handle_kernel_fault(&fp->ptregs))
+			bad_super_trap(fp);
+		return;
+	}
+
+	/* send the appropriate signal to the user program */
+	switch ((fp->ptregs.vector) >> 2) {
+	    case VEC_ADDRERR:
+		info.si_code = BUS_ADRALN;
+		sig = SIGBUS;
+		break;
+	    case VEC_ILLEGAL:
+	    case VEC_LINE10:
+	    case VEC_LINE11:
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+		break;
+	    case VEC_PRIV:
+		info.si_code = ILL_PRVOPC;
+		sig = SIGILL;
+		break;
+	    case VEC_COPROC:
+		info.si_code = ILL_COPROC;
+		sig = SIGILL;
+		break;
+	    case VEC_TRAP1:
+	    case VEC_TRAP2:
+	    case VEC_TRAP3:
+	    case VEC_TRAP4:
+	    case VEC_TRAP5:
+	    case VEC_TRAP6:
+	    case VEC_TRAP7:
+	    case VEC_TRAP8:
+	    case VEC_TRAP9:
+	    case VEC_TRAP10:
+	    case VEC_TRAP11:
+	    case VEC_TRAP12:
+	    case VEC_TRAP13:
+	    case VEC_TRAP14:
+		info.si_code = ILL_ILLTRP;
+		sig = SIGILL;
+		break;
+	    case VEC_FPBRUC:
+	    case VEC_FPOE:
+	    case VEC_FPNAN:
+		info.si_code = FPE_FLTINV;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPIR:
+		info.si_code = FPE_FLTRES;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPDIVZ:
+		info.si_code = FPE_FLTDIV;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPUNDER:
+		info.si_code = FPE_FLTUND;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPOVER:
+		info.si_code = FPE_FLTOVF;
+		sig = SIGFPE;
+		break;
+	    case VEC_ZERODIV:
+		info.si_code = FPE_INTDIV;
+		sig = SIGFPE;
+		break;
+	    case VEC_CHK:
+	    case VEC_TRAP:
+		info.si_code = FPE_INTOVF;
+		sig = SIGFPE;
+		break;
+	    case VEC_TRACE:		/* ptrace single step */
+		info.si_code = TRAP_TRACE;
+		sig = SIGTRAP;
+		break;
+	    case VEC_TRAP15:		/* breakpoint */
+		info.si_code = TRAP_BRKPT;
+		sig = SIGTRAP;
+		break;
+	    default:
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+		break;
+	}
+	info.si_signo = sig;
+	info.si_errno = 0;
+	switch (fp->ptregs.format) {
+	    default:
+		info.si_addr = (void *) fp->ptregs.pc;
+		break;
+	    case 2:
+		info.si_addr = (void *) fp->un.fmt2.iaddr;
+		break;
+	    case 7:
+		info.si_addr = (void *) fp->un.fmt7.effaddr;
+		break;
+	    case 9:
+		info.si_addr = (void *) fp->un.fmt9.iaddr;
+		break;
+	    case 10:
+		info.si_addr = (void *) fp->un.fmta.daddr;
+		break;
+	    case 11:
+		info.si_addr = (void *) fp->un.fmtb.daddr;
+		break;
+	}
+	force_sig_info (sig, &info, current);
+}
+
+void die_if_kernel (char *str, struct pt_regs *fp, int nr)
+{
+	if (!(fp->sr & PS_S))
+		return;
+
+	console_verbose();
+	printk("%s: %08x\n",str,nr);
+	show_registers(fp);
+	add_taint(TAINT_DIE);
+	do_exit(SIGSEGV);
+}
+
+/*
+ * This function is called if an error occur while accessing
+ * user-space from the fpsp040 code.
+ */
+asmlinkage void fpsp040_die(void)
+{
+	do_exit(SIGSEGV);
+}
+
+#ifdef CONFIG_M68KFPU_EMU
+asmlinkage void fpemu_signal(int signal, int code, void *addr)
+{
+	siginfo_t info;
+
+	info.si_signo = signal;
+	info.si_errno = 0;
+	info.si_code = code;
+	info.si_addr = addr;
+	force_sig_info(signal, &info, current);
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/traps_no.c linux-libre-2.6.39-gnu/arch/m68k/kernel/traps_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/traps_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/traps_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,365 @@
+/*
+ *  linux/arch/m68knommu/kernel/traps.c
+ *
+ *  Copyright (C) 1993, 1994 by Hamish Macdonald
+ *
+ *  68040 fixes by Michael Rausch
+ *  68040 fixes by Martin Apel
+ *  68060 fixes by Roman Hodek
+ *  68060 fixes by Jesper Skov
+ *
+ * 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.
+ */
+
+/*
+ * Sets up all exception vectors
+ */
+#include <linux/sched.h>
+#include <linux/signal.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/user.h>
+#include <linux/string.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <linux/ptrace.h>
+#include <linux/kallsyms.h>
+
+#include <asm/setup.h>
+#include <asm/fpu.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/traps.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/siginfo.h>
+
+static char const * const vec_names[] = {
+	"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
+	"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
+	"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
+	"UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
+	"FORMAT ERROR", "UNINITIALIZED INTERRUPT",
+	"UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
+	"UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
+	"UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
+	"UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
+	"SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
+	"LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
+	"SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
+	"TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
+	"TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
+	"TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
+	"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
+	"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
+	"FPCP UNSUPPORTED OPERATION",
+	"MMU CONFIGURATION ERROR"
+};
+
+void __init trap_init(void)
+{
+}
+
+void die_if_kernel(char *str, struct pt_regs *fp, int nr)
+{
+	if (!(fp->sr & PS_S))
+		return;
+
+	console_verbose();
+	printk(KERN_EMERG "%s: %08x\n",str,nr);
+	printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
+	       fp->pc, fp->sr, fp, fp->a2);
+	printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
+	       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 "Process %s (pid: %d, stackpage=%08lx)\n",
+		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
+	show_stack(NULL, (unsigned long *)(fp + 1));
+	add_taint(TAINT_DIE);
+	do_exit(SIGSEGV);
+}
+
+asmlinkage void buserr_c(struct frame *fp)
+{
+	/* Only set esp0 if coming from user mode */
+	if (user_mode(&fp->ptregs))
+		current->thread.esp0 = (unsigned long) fp;
+
+#if defined(DEBUG)
+	printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
+#endif
+
+	die_if_kernel("bad frame format",&fp->ptregs,0);
+#if defined(DEBUG)
+	printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
+#endif
+	force_sig(SIGSEGV, current);
+}
+
+static void print_this_address(unsigned long addr, int i)
+{
+#ifdef CONFIG_KALLSYMS
+	printk(KERN_EMERG " [%08lx] ", addr);
+	print_symbol(KERN_CONT "%s\n", addr);
+#else
+	if (i % 5)
+		printk(KERN_CONT " [%08lx] ", addr);
+	else
+		printk(KERN_EMERG " [%08lx] ", addr);
+	i++;
+#endif
+}
+
+int kstack_depth_to_print = 48;
+
+static void __show_stack(struct task_struct *task, unsigned long *stack)
+{
+	unsigned long *endstack, addr;
+#ifdef CONFIG_FRAME_POINTER
+	unsigned long *last_stack;
+#endif
+	int i;
+
+	if (!stack)
+		stack = (unsigned long *)task->thread.ksp;
+
+	addr = (unsigned long) stack;
+	endstack = (unsigned long *) PAGE_ALIGN(addr);
+
+	printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
+	for (i = 0; i < kstack_depth_to_print; i++) {
+		if (stack + 1 + i > endstack)
+			break;
+		if (i % 8 == 0)
+			printk(KERN_EMERG "       ");
+		printk(KERN_CONT " %08lx", *(stack + i));
+	}
+	printk("\n");
+	i = 0;
+
+#ifdef CONFIG_FRAME_POINTER
+	printk(KERN_EMERG "Call Trace:\n");
+
+	last_stack = stack - 1;
+	while (stack <= endstack && stack > last_stack) {
+
+		addr = *(stack + 1);
+		print_this_address(addr, i);
+		i++;
+
+		last_stack = stack;
+		stack = (unsigned long *)*stack;
+	}
+	printk("\n");
+#else
+	printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
+	while (stack <= endstack) {
+		addr = *stack++;
+		/*
+		 * If the address is either in the text segment of the kernel,
+		 * or in a region which is occupied by a module then it *may*
+		 * be the address of a calling routine; if so, print it so that
+		 * someone tracing down the cause of the crash will be able to
+		 * figure out the call path that was taken.
+		 */
+		if (__kernel_text_address(addr)) {
+			print_this_address(addr, i);
+			i++;
+		}
+	}
+	printk(KERN_CONT "\n");
+#endif
+}
+
+void bad_super_trap(struct frame *fp)
+{
+	int vector = (fp->ptregs.vector >> 2) & 0xff;
+
+	console_verbose();
+	if (vector < ARRAY_SIZE(vec_names))
+		printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
+			vec_names[vector],
+			fp->ptregs.format);
+	else
+		printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
+			vector,
+			fp->ptregs.format);
+	printk (KERN_WARNING "Current process id is %d\n", current->pid);
+	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
+}
+
+asmlinkage void trap_c(struct frame *fp)
+{
+	int sig;
+	int vector = (fp->ptregs.vector >> 2) & 0xff;
+	siginfo_t info;
+
+	if (fp->ptregs.sr & PS_S) {
+		if (vector == VEC_TRACE) {
+			/* traced a trapping instruction */
+		} else
+			bad_super_trap(fp);
+		return;
+	}
+
+	/* send the appropriate signal to the user program */
+	switch (vector) {
+	    case VEC_ADDRERR:
+		info.si_code = BUS_ADRALN;
+		sig = SIGBUS;
+		break;
+	    case VEC_ILLEGAL:
+	    case VEC_LINE10:
+	    case VEC_LINE11:
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+		break;
+	    case VEC_PRIV:
+		info.si_code = ILL_PRVOPC;
+		sig = SIGILL;
+		break;
+	    case VEC_COPROC:
+		info.si_code = ILL_COPROC;
+		sig = SIGILL;
+		break;
+	    case VEC_TRAP1: /* gdbserver breakpoint */
+		fp->ptregs.pc -= 2;
+		info.si_code = TRAP_TRACE;
+		sig = SIGTRAP;
+		break;
+	    case VEC_TRAP2:
+	    case VEC_TRAP3:
+	    case VEC_TRAP4:
+	    case VEC_TRAP5:
+	    case VEC_TRAP6:
+	    case VEC_TRAP7:
+	    case VEC_TRAP8:
+	    case VEC_TRAP9:
+	    case VEC_TRAP10:
+	    case VEC_TRAP11:
+	    case VEC_TRAP12:
+	    case VEC_TRAP13:
+	    case VEC_TRAP14:
+		info.si_code = ILL_ILLTRP;
+		sig = SIGILL;
+		break;
+	    case VEC_FPBRUC:
+	    case VEC_FPOE:
+	    case VEC_FPNAN:
+		info.si_code = FPE_FLTINV;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPIR:
+		info.si_code = FPE_FLTRES;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPDIVZ:
+		info.si_code = FPE_FLTDIV;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPUNDER:
+		info.si_code = FPE_FLTUND;
+		sig = SIGFPE;
+		break;
+	    case VEC_FPOVER:
+		info.si_code = FPE_FLTOVF;
+		sig = SIGFPE;
+		break;
+	    case VEC_ZERODIV:
+		info.si_code = FPE_INTDIV;
+		sig = SIGFPE;
+		break;
+	    case VEC_CHK:
+	    case VEC_TRAP:
+		info.si_code = FPE_INTOVF;
+		sig = SIGFPE;
+		break;
+	    case VEC_TRACE:		/* ptrace single step */
+		info.si_code = TRAP_TRACE;
+		sig = SIGTRAP;
+		break;
+	    case VEC_TRAP15:		/* breakpoint */
+		info.si_code = TRAP_BRKPT;
+		sig = SIGTRAP;
+		break;
+	    default:
+		info.si_code = ILL_ILLOPC;
+		sig = SIGILL;
+		break;
+	}
+	info.si_signo = sig;
+	info.si_errno = 0;
+	switch (fp->ptregs.format) {
+	    default:
+		info.si_addr = (void *) fp->ptregs.pc;
+		break;
+	    case 2:
+		info.si_addr = (void *) fp->un.fmt2.iaddr;
+		break;
+	    case 7:
+		info.si_addr = (void *) fp->un.fmt7.effaddr;
+		break;
+	    case 9:
+		info.si_addr = (void *) fp->un.fmt9.iaddr;
+		break;
+	    case 10:
+		info.si_addr = (void *) fp->un.fmta.daddr;
+		break;
+	    case 11:
+		info.si_addr = (void *) fp->un.fmtb.daddr;
+		break;
+	}
+	force_sig_info (sig, &info, current);
+}
+
+asmlinkage void set_esp0(unsigned long ssp)
+{
+	current->thread.esp0 = ssp;
+}
+
+/*
+ * The architecture-independent backtrace generator
+ */
+void dump_stack(void)
+{
+	/*
+	 * We need frame pointers for this little trick, which works as follows:
+	 *
+	 * +------------+ 0x00
+	 * | Next SP	|	-> 0x0c
+	 * +------------+ 0x04
+	 * | Caller	|
+	 * +------------+ 0x08
+	 * | Local vars	|	-> our stack var
+	 * +------------+ 0x0c
+	 * | Next SP	|	-> 0x18, that is what we pass to show_stack()
+	 * +------------+ 0x10
+	 * | Caller	|
+	 * +------------+ 0x14
+	 * | Local vars	|
+	 * +------------+ 0x18
+	 * | ...	|
+	 * +------------+
+	 */
+
+	unsigned long *stack;
+
+	stack = (unsigned long *)&stack;
+	stack++;
+	__show_stack(current, stack);
+}
+EXPORT_SYMBOL(dump_stack);
+
+void show_stack(struct task_struct *task, unsigned long *stack)
+{
+	if (!stack && !task)
+		dump_stack();
+	else
+		__show_stack(task, stack);
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/vmlinux.lds_mm.S linux-libre-2.6.39-gnu/arch/m68k/kernel/vmlinux.lds_mm.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/vmlinux.lds_mm.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/vmlinux.lds_mm.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+PHDRS
+{
+  text PT_LOAD FILEHDR PHDRS FLAGS (7);
+  data PT_LOAD FLAGS (7);
+}
+#ifdef CONFIG_SUN3
+#include "vmlinux-sun3.lds"
+#else
+#include "vmlinux-std.lds"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/vmlinux.lds_no.S linux-libre-2.6.39-gnu/arch/m68k/kernel/vmlinux.lds_no.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/vmlinux.lds_no.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/vmlinux.lds_no.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,188 @@
+/*
+ *	vmlinux.lds.S -- master linker script for m68knommu arch
+ *
+ *	(C) Copyright 2002-2006, Greg Ungerer <gerg@snapgear.com>
+ *
+ *	This linker script is equipped to build either ROM loaded or RAM
+ *	run kernels.
+ */
+
+#include <asm-generic/vmlinux.lds.h>
+#include <asm/page.h>
+#include <asm/thread_info.h>
+
+#if defined(CONFIG_RAMKERNEL)
+#define	RAM_START	CONFIG_KERNELBASE
+#define	RAM_LENGTH	(CONFIG_RAMBASE + CONFIG_RAMSIZE - CONFIG_KERNELBASE)
+#define	TEXT		ram
+#define	DATA		ram
+#define	INIT		ram
+#define	BSSS		ram
+#endif
+#if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL)
+#define	RAM_START	CONFIG_RAMBASE
+#define	RAM_LENGTH	CONFIG_RAMSIZE
+#define	ROMVEC_START	CONFIG_ROMVEC
+#define	ROMVEC_LENGTH	CONFIG_ROMVECSIZE
+#define	ROM_START	CONFIG_ROMSTART
+#define	ROM_LENGTH	CONFIG_ROMSIZE
+#define	TEXT		rom
+#define	DATA		ram
+#define	INIT		ram
+#define	BSSS		ram
+#endif
+
+#ifndef DATA_ADDR
+#define	DATA_ADDR
+#endif
+
+
+OUTPUT_ARCH(m68k)
+ENTRY(_start)
+
+MEMORY {
+	ram	: ORIGIN = RAM_START, LENGTH = RAM_LENGTH
+#ifdef ROM_START
+	romvec	: ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH
+	rom	: ORIGIN = ROM_START, LENGTH = ROM_LENGTH
+#endif
+}
+
+jiffies = jiffies_64 + 4;
+
+SECTIONS {
+
+#ifdef ROMVEC_START
+	. = ROMVEC_START ;
+	.romvec : {
+		__rom_start = . ;
+		_romvec = .;
+		*(.data..initvect)
+	} > romvec
+#endif
+
+	.text : {
+		_text = .;
+		_stext = . ;
+		HEAD_TEXT
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+		*(.text..lock)
+
+		. = ALIGN(16);          /* Exception table              */
+		__start___ex_table = .;
+		*(__ex_table)
+		__stop___ex_table = .;
+
+		*(.rodata) *(.rodata.*)
+		*(__vermagic)		/* Kernel version magic */
+		*(__markers_strings)
+		*(.rodata1)
+		*(.rodata.str1.1)
+
+		/* Kernel symbol table: Normal symbols */
+		. = ALIGN(4);
+		__start___ksymtab = .;
+		*(__ksymtab)
+		__stop___ksymtab = .;
+
+		/* Kernel symbol table: GPL-only symbols */
+		__start___ksymtab_gpl = .;
+		*(__ksymtab_gpl)
+		__stop___ksymtab_gpl = .;
+
+		/* Kernel symbol table: Normal unused symbols */
+		__start___ksymtab_unused = .;
+		*(__ksymtab_unused)
+		__stop___ksymtab_unused = .;
+
+		/* Kernel symbol table: GPL-only unused symbols */
+		__start___ksymtab_unused_gpl = .;
+		*(__ksymtab_unused_gpl)
+		__stop___ksymtab_unused_gpl = .;
+
+		/* Kernel symbol table: GPL-future symbols */
+		__start___ksymtab_gpl_future = .;
+		*(__ksymtab_gpl_future)
+		__stop___ksymtab_gpl_future = .;
+
+		/* Kernel symbol table: Normal symbols */
+		__start___kcrctab = .;
+		*(__kcrctab)
+		__stop___kcrctab = .;
+
+		/* Kernel symbol table: GPL-only symbols */
+		__start___kcrctab_gpl = .;
+		*(__kcrctab_gpl)
+		__stop___kcrctab_gpl = .;
+
+		/* Kernel symbol table: Normal unused symbols */
+		__start___kcrctab_unused = .;
+		*(__kcrctab_unused)
+		__stop___kcrctab_unused = .;
+
+		/* Kernel symbol table: GPL-only unused symbols */
+		__start___kcrctab_unused_gpl = .;
+		*(__kcrctab_unused_gpl)
+		__stop___kcrctab_unused_gpl = .;
+
+		/* Kernel symbol table: GPL-future symbols */
+		__start___kcrctab_gpl_future = .;
+		*(__kcrctab_gpl_future)
+		__stop___kcrctab_gpl_future = .;
+
+		/* Kernel symbol table: strings */
+		*(__ksymtab_strings)
+
+		/* Built-in module parameters */
+		. = ALIGN(4) ;
+		__start___param = .;
+		*(__param)
+		__stop___param = .;
+
+		/* Built-in module versions */
+		. = ALIGN(4) ;
+		__start___modver = .;
+		*(__modver)
+		__stop___modver = .;
+
+		. = ALIGN(4) ;
+		_etext = . ;
+	} > TEXT
+
+	.data DATA_ADDR : {
+		. = ALIGN(4);
+		_sdata = . ;
+		DATA_DATA
+		CACHELINE_ALIGNED_DATA(32)
+		PAGE_ALIGNED_DATA(PAGE_SIZE)
+		*(.data..shared_aligned)
+		INIT_TASK_DATA(THREAD_SIZE)
+		_edata = . ;
+	} > DATA
+
+	.init.text : {
+		. = ALIGN(PAGE_SIZE);
+		__init_begin = .;
+	} > INIT
+	INIT_TEXT_SECTION(PAGE_SIZE) > INIT
+	INIT_DATA_SECTION(16) > INIT
+	.init.data : {
+		. = ALIGN(PAGE_SIZE);
+		__init_end = .;
+	} > INIT
+
+	.bss : {
+		. = ALIGN(4);
+		_sbss = . ;
+		*(.bss)
+		*(COMMON)
+		. = ALIGN(4) ;
+		_ebss = . ;
+	 	_end = . ;
+	} > BSSS
+
+	DISCARDS
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/m68k/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/m68k/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -1,10 +1,5 @@
-PHDRS
-{
-  text PT_LOAD FILEHDR PHDRS FLAGS (7);
-  data PT_LOAD FLAGS (7);
-}
-#ifdef CONFIG_SUN3
-#include "vmlinux-sun3.lds"
+#ifdef CONFIG_MMU
+#include "vmlinux.lds_mm.S"
 #else
-#include "vmlinux-std.lds"
+#include "vmlinux.lds_no.S"
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/checksum.c linux-libre-2.6.39-gnu/arch/m68k/lib/checksum.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/checksum.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/checksum.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,425 +1,5 @@
-/*
- * 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.
- *
- * 1998/8/31	Andreas Schwab:
- *		Zero out rest of buffer on exception in
- *		csum_partial_copy_from_user.
- */
-
-#include <linux/module.h>
-#include <net/checksum.h>
-
-/*
- * computes a partial checksum, e.g. for TCP/UDP fragments
- */
-
-__wsum csum_partial(const void *buff, int len, __wsum sum)
-{
-	unsigned long tmp1, tmp2;
-	  /*
-	   * Experiments with ethernet and slip connections show that buff
-	   * is aligned on either a 2-byte or 4-byte boundary.
-	   */
-	__asm__("movel %2,%3\n\t"
-		"btst #1,%3\n\t"	/* Check alignment */
-		"jeq 2f\n\t"
-		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
-		"jgt 1f\n\t"
-		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
-		"jra 4f\n"
-	     "1:\t"
-		"addw %2@+,%0\n\t"	/* add first word to sum */
-		"clrl %3\n\t"
-		"addxl %3,%0\n"		/* add X bit */
-	     "2:\t"
-		/* unrolled loop for the main part: do 8 longs at once */
-		"movel %1,%3\n\t"	/* save len in tmp1 */
-		"lsrl #5,%1\n\t"	/* len/32 */
-		"jeq 2f\n\t"		/* not enough... */
-		"subql #1,%1\n"
-	     "1:\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"dbra %1,1b\n\t"
-		"clrl %4\n\t"
-		"addxl %4,%0\n\t"	/* add X bit */
-		"clrw %1\n\t"
-		"subql #1,%1\n\t"
-		"jcc 1b\n"
-	     "2:\t"
-		"movel %3,%1\n\t"	/* restore len from tmp1 */
-		"andw #0x1c,%3\n\t"	/* number of rest longs */
-		"jeq 4f\n\t"
-		"lsrw #2,%3\n\t"
-		"subqw #1,%3\n"
-	     "3:\t"
-		/* loop for rest longs */
-		"movel %2@+,%4\n\t"
-		"addxl %4,%0\n\t"
-		"dbra %3,3b\n\t"
-		"clrl %4\n\t"
-		"addxl %4,%0\n"		/* add X bit */
-	     "4:\t"
-		/* now check for rest bytes that do not fit into longs */
-		"andw #3,%1\n\t"
-		"jeq 7f\n\t"
-		"clrl %4\n\t"		/* clear tmp2 for rest bytes */
-		"subqw #2,%1\n\t"
-		"jlt 5f\n\t"
-		"movew %2@+,%4\n\t"	/* have rest >= 2: get word */
-		"swap %4\n\t"		/* into bits 16..31 */
-		"tstw %1\n\t"		/* another byte? */
-		"jeq 6f\n"
-	     "5:\t"
-		"moveb %2@,%4\n\t"	/* have odd rest: get byte */
-		"lslw #8,%4\n\t"	/* into bits 8..15; 16..31 untouched */
-	     "6:\t"
-		"addl %4,%0\n\t"	/* now add rest long to sum */
-		"clrl %4\n\t"
-		"addxl %4,%0\n"		/* add X bit */
-	     "7:\t"
-		: "=d" (sum), "=d" (len), "=a" (buff),
-		  "=&d" (tmp1), "=&d" (tmp2)
-		: "0" (sum), "1" (len), "2" (buff)
-	    );
-	return(sum);
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-
-/*
- * copy from user space while checksumming, with exception handling.
- */
-
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst,
-			    int len, __wsum sum, int *csum_err)
-{
-	/*
-	 * GCC doesn't like more than 10 operands for the asm
-	 * statements so we have to use tmp2 for the error
-	 * code.
-	 */
-	unsigned long tmp1, tmp2;
-
-	__asm__("movel %2,%4\n\t"
-		"btst #1,%4\n\t"	/* Check alignment */
-		"jeq 2f\n\t"
-		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
-		"jgt 1f\n\t"
-		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
-		"jra 4f\n"
-	     "1:\n"
-	     "10:\t"
-		"movesw %2@+,%4\n\t"	/* add first word to sum */
-		"addw %4,%0\n\t"
-		"movew %4,%3@+\n\t"
-		"clrl %4\n\t"
-		"addxl %4,%0\n"		/* add X bit */
-	     "2:\t"
-		/* unrolled loop for the main part: do 8 longs at once */
-		"movel %1,%4\n\t"	/* save len in tmp1 */
-		"lsrl #5,%1\n\t"	/* len/32 */
-		"jeq 2f\n\t"		/* not enough... */
-		"subql #1,%1\n"
-	     "1:\n"
-	     "11:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "12:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "13:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "14:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "15:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "16:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "17:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-	     "18:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"dbra %1,1b\n\t"
-		"clrl %5\n\t"
-		"addxl %5,%0\n\t"	/* add X bit */
-		"clrw %1\n\t"
-		"subql #1,%1\n\t"
-		"jcc 1b\n"
-	     "2:\t"
-		"movel %4,%1\n\t"	/* restore len from tmp1 */
-		"andw #0x1c,%4\n\t"	/* number of rest longs */
-		"jeq 4f\n\t"
-		"lsrw #2,%4\n\t"
-		"subqw #1,%4\n"
-	     "3:\n"
-		/* loop for rest longs */
-	     "19:\t"
-		"movesl %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"dbra %4,3b\n\t"
-		"clrl %5\n\t"
-		"addxl %5,%0\n"		/* add X bit */
-	     "4:\t"
-		/* now check for rest bytes that do not fit into longs */
-		"andw #3,%1\n\t"
-		"jeq 7f\n\t"
-		"clrl %5\n\t"		/* clear tmp2 for rest bytes */
-		"subqw #2,%1\n\t"
-		"jlt 5f\n\t"
-	     "20:\t"
-		"movesw %2@+,%5\n\t"	/* have rest >= 2: get word */
-		"movew %5,%3@+\n\t"
-		"swap %5\n\t"		/* into bits 16..31 */
-		"tstw %1\n\t"		/* another byte? */
-		"jeq 6f\n"
-	     "5:\n"
-	     "21:\t"
-		"movesb %2@,%5\n\t"	/* have odd rest: get byte */
-		"moveb %5,%3@+\n\t"
-		"lslw #8,%5\n\t"	/* into bits 8..15; 16..31 untouched */
-	     "6:\t"
-		"addl %5,%0\n\t"	/* now add rest long to sum */
-		"clrl %5\n\t"
-		"addxl %5,%0\n\t"	/* add X bit */
-	     "7:\t"
-		"clrl %5\n"		/* no error - clear return value */
-	     "8:\n"
-		".section .fixup,\"ax\"\n"
-		".even\n"
-		/* If any exception occurs zero out the rest.
-		   Similarities with the code above are intentional :-) */
-	     "90:\t"
-		"clrw %3@+\n\t"
-		"movel %1,%4\n\t"
-		"lsrl #5,%1\n\t"
-		"jeq 1f\n\t"
-		"subql #1,%1\n"
-	     "91:\t"
-		"clrl %3@+\n"
-	     "92:\t"
-		"clrl %3@+\n"
-	     "93:\t"
-		"clrl %3@+\n"
-	     "94:\t"
-		"clrl %3@+\n"
-	     "95:\t"
-		"clrl %3@+\n"
-	     "96:\t"
-		"clrl %3@+\n"
-	     "97:\t"
-		"clrl %3@+\n"
-	     "98:\t"
-		"clrl %3@+\n\t"
-		"dbra %1,91b\n\t"
-		"clrw %1\n\t"
-		"subql #1,%1\n\t"
-		"jcc 91b\n"
-	     "1:\t"
-		"movel %4,%1\n\t"
-		"andw #0x1c,%4\n\t"
-		"jeq 1f\n\t"
-		"lsrw #2,%4\n\t"
-		"subqw #1,%4\n"
-	     "99:\t"
-		"clrl %3@+\n\t"
-		"dbra %4,99b\n\t"
-	     "1:\t"
-		"andw #3,%1\n\t"
-		"jeq 9f\n"
-	     "100:\t"
-		"clrw %3@+\n\t"
-		"tstw %1\n\t"
-		"jeq 9f\n"
-	     "101:\t"
-		"clrb %3@+\n"
-	     "9:\t"
-#define STR(X) STR1(X)
-#define STR1(X) #X
-		"moveq #-" STR(EFAULT) ",%5\n\t"
-		"jra 8b\n"
-		".previous\n"
-		".section __ex_table,\"a\"\n"
-		".long 10b,90b\n"
-		".long 11b,91b\n"
-		".long 12b,92b\n"
-		".long 13b,93b\n"
-		".long 14b,94b\n"
-		".long 15b,95b\n"
-		".long 16b,96b\n"
-		".long 17b,97b\n"
-		".long 18b,98b\n"
-		".long 19b,99b\n"
-		".long 20b,100b\n"
-		".long 21b,101b\n"
-		".previous"
-		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
-		  "=&d" (tmp1), "=d" (tmp2)
-		: "0" (sum), "1" (len), "2" (src), "3" (dst)
-	    );
-
-	*csum_err = tmp2;
-
-	return(sum);
-}
-
-EXPORT_SYMBOL(csum_partial_copy_from_user);
-
-
-/*
- * copy from kernel space while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
-{
-	unsigned long tmp1, tmp2;
-	__asm__("movel %2,%4\n\t"
-		"btst #1,%4\n\t"	/* Check alignment */
-		"jeq 2f\n\t"
-		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
-		"jgt 1f\n\t"
-		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
-		"jra 4f\n"
-	     "1:\t"
-		"movew %2@+,%4\n\t"	/* add first word to sum */
-		"addw %4,%0\n\t"
-		"movew %4,%3@+\n\t"
-		"clrl %4\n\t"
-		"addxl %4,%0\n"		/* add X bit */
-	     "2:\t"
-		/* unrolled loop for the main part: do 8 longs at once */
-		"movel %1,%4\n\t"	/* save len in tmp1 */
-		"lsrl #5,%1\n\t"	/* len/32 */
-		"jeq 2f\n\t"		/* not enough... */
-		"subql #1,%1\n"
-	     "1:\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"dbra %1,1b\n\t"
-		"clrl %5\n\t"
-		"addxl %5,%0\n\t"	/* add X bit */
-		"clrw %1\n\t"
-		"subql #1,%1\n\t"
-		"jcc 1b\n"
-	     "2:\t"
-		"movel %4,%1\n\t"	/* restore len from tmp1 */
-		"andw #0x1c,%4\n\t"	/* number of rest longs */
-		"jeq 4f\n\t"
-		"lsrw #2,%4\n\t"
-		"subqw #1,%4\n"
-	     "3:\t"
-		/* loop for rest longs */
-		"movel %2@+,%5\n\t"
-		"addxl %5,%0\n\t"
-		"movel %5,%3@+\n\t"
-		"dbra %4,3b\n\t"
-		"clrl %5\n\t"
-		"addxl %5,%0\n"		/* add X bit */
-	     "4:\t"
-		/* now check for rest bytes that do not fit into longs */
-		"andw #3,%1\n\t"
-		"jeq 7f\n\t"
-		"clrl %5\n\t"		/* clear tmp2 for rest bytes */
-		"subqw #2,%1\n\t"
-		"jlt 5f\n\t"
-		"movew %2@+,%5\n\t"	/* have rest >= 2: get word */
-		"movew %5,%3@+\n\t"
-		"swap %5\n\t"		/* into bits 16..31 */
-		"tstw %1\n\t"		/* another byte? */
-		"jeq 6f\n"
-	     "5:\t"
-		"moveb %2@,%5\n\t"	/* have odd rest: get byte */
-		"moveb %5,%3@+\n\t"
-		"lslw #8,%5\n"		/* into bits 8..15; 16..31 untouched */
-	     "6:\t"
-		"addl %5,%0\n\t"	/* now add rest long to sum */
-		"clrl %5\n\t"
-		"addxl %5,%0\n"		/* add X bit */
-	     "7:\t"
-		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
-		  "=&d" (tmp1), "=&d" (tmp2)
-		: "0" (sum), "1" (len), "2" (src), "3" (dst)
-	    );
-    return(sum);
-}
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
+#ifdef CONFIG_MMU
+#include "checksum_mm.c"
+#else
+#include "checksum_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/checksum_mm.c linux-libre-2.6.39-gnu/arch/m68k/lib/checksum_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/checksum_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/checksum_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,425 @@
+/*
+ * 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.
+ *
+ * 1998/8/31	Andreas Schwab:
+ *		Zero out rest of buffer on exception in
+ *		csum_partial_copy_from_user.
+ */
+
+#include <linux/module.h>
+#include <net/checksum.h>
+
+/*
+ * computes a partial checksum, e.g. for TCP/UDP fragments
+ */
+
+__wsum csum_partial(const void *buff, int len, __wsum sum)
+{
+	unsigned long tmp1, tmp2;
+	  /*
+	   * Experiments with ethernet and slip connections show that buff
+	   * is aligned on either a 2-byte or 4-byte boundary.
+	   */
+	__asm__("movel %2,%3\n\t"
+		"btst #1,%3\n\t"	/* Check alignment */
+		"jeq 2f\n\t"
+		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
+		"jgt 1f\n\t"
+		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
+		"jra 4f\n"
+	     "1:\t"
+		"addw %2@+,%0\n\t"	/* add first word to sum */
+		"clrl %3\n\t"
+		"addxl %3,%0\n"		/* add X bit */
+	     "2:\t"
+		/* unrolled loop for the main part: do 8 longs at once */
+		"movel %1,%3\n\t"	/* save len in tmp1 */
+		"lsrl #5,%1\n\t"	/* len/32 */
+		"jeq 2f\n\t"		/* not enough... */
+		"subql #1,%1\n"
+	     "1:\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"dbra %1,1b\n\t"
+		"clrl %4\n\t"
+		"addxl %4,%0\n\t"	/* add X bit */
+		"clrw %1\n\t"
+		"subql #1,%1\n\t"
+		"jcc 1b\n"
+	     "2:\t"
+		"movel %3,%1\n\t"	/* restore len from tmp1 */
+		"andw #0x1c,%3\n\t"	/* number of rest longs */
+		"jeq 4f\n\t"
+		"lsrw #2,%3\n\t"
+		"subqw #1,%3\n"
+	     "3:\t"
+		/* loop for rest longs */
+		"movel %2@+,%4\n\t"
+		"addxl %4,%0\n\t"
+		"dbra %3,3b\n\t"
+		"clrl %4\n\t"
+		"addxl %4,%0\n"		/* add X bit */
+	     "4:\t"
+		/* now check for rest bytes that do not fit into longs */
+		"andw #3,%1\n\t"
+		"jeq 7f\n\t"
+		"clrl %4\n\t"		/* clear tmp2 for rest bytes */
+		"subqw #2,%1\n\t"
+		"jlt 5f\n\t"
+		"movew %2@+,%4\n\t"	/* have rest >= 2: get word */
+		"swap %4\n\t"		/* into bits 16..31 */
+		"tstw %1\n\t"		/* another byte? */
+		"jeq 6f\n"
+	     "5:\t"
+		"moveb %2@,%4\n\t"	/* have odd rest: get byte */
+		"lslw #8,%4\n\t"	/* into bits 8..15; 16..31 untouched */
+	     "6:\t"
+		"addl %4,%0\n\t"	/* now add rest long to sum */
+		"clrl %4\n\t"
+		"addxl %4,%0\n"		/* add X bit */
+	     "7:\t"
+		: "=d" (sum), "=d" (len), "=a" (buff),
+		  "=&d" (tmp1), "=&d" (tmp2)
+		: "0" (sum), "1" (len), "2" (buff)
+	    );
+	return(sum);
+}
+
+EXPORT_SYMBOL(csum_partial);
+
+
+/*
+ * copy from user space while checksumming, with exception handling.
+ */
+
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+			    int len, __wsum sum, int *csum_err)
+{
+	/*
+	 * GCC doesn't like more than 10 operands for the asm
+	 * statements so we have to use tmp2 for the error
+	 * code.
+	 */
+	unsigned long tmp1, tmp2;
+
+	__asm__("movel %2,%4\n\t"
+		"btst #1,%4\n\t"	/* Check alignment */
+		"jeq 2f\n\t"
+		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
+		"jgt 1f\n\t"
+		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
+		"jra 4f\n"
+	     "1:\n"
+	     "10:\t"
+		"movesw %2@+,%4\n\t"	/* add first word to sum */
+		"addw %4,%0\n\t"
+		"movew %4,%3@+\n\t"
+		"clrl %4\n\t"
+		"addxl %4,%0\n"		/* add X bit */
+	     "2:\t"
+		/* unrolled loop for the main part: do 8 longs at once */
+		"movel %1,%4\n\t"	/* save len in tmp1 */
+		"lsrl #5,%1\n\t"	/* len/32 */
+		"jeq 2f\n\t"		/* not enough... */
+		"subql #1,%1\n"
+	     "1:\n"
+	     "11:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "12:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "13:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "14:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "15:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "16:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "17:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+	     "18:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"dbra %1,1b\n\t"
+		"clrl %5\n\t"
+		"addxl %5,%0\n\t"	/* add X bit */
+		"clrw %1\n\t"
+		"subql #1,%1\n\t"
+		"jcc 1b\n"
+	     "2:\t"
+		"movel %4,%1\n\t"	/* restore len from tmp1 */
+		"andw #0x1c,%4\n\t"	/* number of rest longs */
+		"jeq 4f\n\t"
+		"lsrw #2,%4\n\t"
+		"subqw #1,%4\n"
+	     "3:\n"
+		/* loop for rest longs */
+	     "19:\t"
+		"movesl %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"dbra %4,3b\n\t"
+		"clrl %5\n\t"
+		"addxl %5,%0\n"		/* add X bit */
+	     "4:\t"
+		/* now check for rest bytes that do not fit into longs */
+		"andw #3,%1\n\t"
+		"jeq 7f\n\t"
+		"clrl %5\n\t"		/* clear tmp2 for rest bytes */
+		"subqw #2,%1\n\t"
+		"jlt 5f\n\t"
+	     "20:\t"
+		"movesw %2@+,%5\n\t"	/* have rest >= 2: get word */
+		"movew %5,%3@+\n\t"
+		"swap %5\n\t"		/* into bits 16..31 */
+		"tstw %1\n\t"		/* another byte? */
+		"jeq 6f\n"
+	     "5:\n"
+	     "21:\t"
+		"movesb %2@,%5\n\t"	/* have odd rest: get byte */
+		"moveb %5,%3@+\n\t"
+		"lslw #8,%5\n\t"	/* into bits 8..15; 16..31 untouched */
+	     "6:\t"
+		"addl %5,%0\n\t"	/* now add rest long to sum */
+		"clrl %5\n\t"
+		"addxl %5,%0\n\t"	/* add X bit */
+	     "7:\t"
+		"clrl %5\n"		/* no error - clear return value */
+	     "8:\n"
+		".section .fixup,\"ax\"\n"
+		".even\n"
+		/* If any exception occurs zero out the rest.
+		   Similarities with the code above are intentional :-) */
+	     "90:\t"
+		"clrw %3@+\n\t"
+		"movel %1,%4\n\t"
+		"lsrl #5,%1\n\t"
+		"jeq 1f\n\t"
+		"subql #1,%1\n"
+	     "91:\t"
+		"clrl %3@+\n"
+	     "92:\t"
+		"clrl %3@+\n"
+	     "93:\t"
+		"clrl %3@+\n"
+	     "94:\t"
+		"clrl %3@+\n"
+	     "95:\t"
+		"clrl %3@+\n"
+	     "96:\t"
+		"clrl %3@+\n"
+	     "97:\t"
+		"clrl %3@+\n"
+	     "98:\t"
+		"clrl %3@+\n\t"
+		"dbra %1,91b\n\t"
+		"clrw %1\n\t"
+		"subql #1,%1\n\t"
+		"jcc 91b\n"
+	     "1:\t"
+		"movel %4,%1\n\t"
+		"andw #0x1c,%4\n\t"
+		"jeq 1f\n\t"
+		"lsrw #2,%4\n\t"
+		"subqw #1,%4\n"
+	     "99:\t"
+		"clrl %3@+\n\t"
+		"dbra %4,99b\n\t"
+	     "1:\t"
+		"andw #3,%1\n\t"
+		"jeq 9f\n"
+	     "100:\t"
+		"clrw %3@+\n\t"
+		"tstw %1\n\t"
+		"jeq 9f\n"
+	     "101:\t"
+		"clrb %3@+\n"
+	     "9:\t"
+#define STR(X) STR1(X)
+#define STR1(X) #X
+		"moveq #-" STR(EFAULT) ",%5\n\t"
+		"jra 8b\n"
+		".previous\n"
+		".section __ex_table,\"a\"\n"
+		".long 10b,90b\n"
+		".long 11b,91b\n"
+		".long 12b,92b\n"
+		".long 13b,93b\n"
+		".long 14b,94b\n"
+		".long 15b,95b\n"
+		".long 16b,96b\n"
+		".long 17b,97b\n"
+		".long 18b,98b\n"
+		".long 19b,99b\n"
+		".long 20b,100b\n"
+		".long 21b,101b\n"
+		".previous"
+		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
+		  "=&d" (tmp1), "=d" (tmp2)
+		: "0" (sum), "1" (len), "2" (src), "3" (dst)
+	    );
+
+	*csum_err = tmp2;
+
+	return(sum);
+}
+
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+
+
+/*
+ * copy from kernel space while checksumming, otherwise like csum_partial
+ */
+
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+	unsigned long tmp1, tmp2;
+	__asm__("movel %2,%4\n\t"
+		"btst #1,%4\n\t"	/* Check alignment */
+		"jeq 2f\n\t"
+		"subql #2,%1\n\t"	/* buff%4==2: treat first word */
+		"jgt 1f\n\t"
+		"addql #2,%1\n\t"	/* len was == 2, treat only rest */
+		"jra 4f\n"
+	     "1:\t"
+		"movew %2@+,%4\n\t"	/* add first word to sum */
+		"addw %4,%0\n\t"
+		"movew %4,%3@+\n\t"
+		"clrl %4\n\t"
+		"addxl %4,%0\n"		/* add X bit */
+	     "2:\t"
+		/* unrolled loop for the main part: do 8 longs at once */
+		"movel %1,%4\n\t"	/* save len in tmp1 */
+		"lsrl #5,%1\n\t"	/* len/32 */
+		"jeq 2f\n\t"		/* not enough... */
+		"subql #1,%1\n"
+	     "1:\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"dbra %1,1b\n\t"
+		"clrl %5\n\t"
+		"addxl %5,%0\n\t"	/* add X bit */
+		"clrw %1\n\t"
+		"subql #1,%1\n\t"
+		"jcc 1b\n"
+	     "2:\t"
+		"movel %4,%1\n\t"	/* restore len from tmp1 */
+		"andw #0x1c,%4\n\t"	/* number of rest longs */
+		"jeq 4f\n\t"
+		"lsrw #2,%4\n\t"
+		"subqw #1,%4\n"
+	     "3:\t"
+		/* loop for rest longs */
+		"movel %2@+,%5\n\t"
+		"addxl %5,%0\n\t"
+		"movel %5,%3@+\n\t"
+		"dbra %4,3b\n\t"
+		"clrl %5\n\t"
+		"addxl %5,%0\n"		/* add X bit */
+	     "4:\t"
+		/* now check for rest bytes that do not fit into longs */
+		"andw #3,%1\n\t"
+		"jeq 7f\n\t"
+		"clrl %5\n\t"		/* clear tmp2 for rest bytes */
+		"subqw #2,%1\n\t"
+		"jlt 5f\n\t"
+		"movew %2@+,%5\n\t"	/* have rest >= 2: get word */
+		"movew %5,%3@+\n\t"
+		"swap %5\n\t"		/* into bits 16..31 */
+		"tstw %1\n\t"		/* another byte? */
+		"jeq 6f\n"
+	     "5:\t"
+		"moveb %2@,%5\n\t"	/* have odd rest: get byte */
+		"moveb %5,%3@+\n\t"
+		"lslw #8,%5\n"		/* into bits 8..15; 16..31 untouched */
+	     "6:\t"
+		"addl %5,%0\n\t"	/* now add rest long to sum */
+		"clrl %5\n\t"
+		"addxl %5,%0\n"		/* add X bit */
+	     "7:\t"
+		: "=d" (sum), "=d" (len), "=a" (src), "=a" (dst),
+		  "=&d" (tmp1), "=&d" (tmp2)
+		: "0" (sum), "1" (len), "2" (src), "3" (dst)
+	    );
+    return(sum);
+}
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/checksum_no.c linux-libre-2.6.39-gnu/arch/m68k/lib/checksum_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/checksum_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/checksum_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,153 @@
+/*
+ * 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 <linux/module.h>
+#include <net/checksum.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 long 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;
+}
+
+#ifdef CONFIG_COLDFIRE
+/*
+ *	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);
+}
+#endif
+
+/*
+ * 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 += (__force u32)sum;
+	if ((__force u32)sum > result)
+		result += 1;
+	return (__force __wsum)result;
+}
+
+EXPORT_SYMBOL(csum_partial);
+
+/*
+ * copy from fs while checksumming, otherwise like csum_partial
+ */
+
+__wsum
+csum_partial_copy_from_user(const void __user *src, void *dst,
+			    int len, __wsum sum, int *csum_err)
+{
+	if (csum_err) *csum_err = 0;
+	memcpy(dst, (__force const void *)src, len);
+	return csum_partial(dst, len, sum);
+}
+
+/*
+ * copy from ds while checksumming, otherwise like csum_partial
+ */
+
+__wsum
+csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
+{
+	memcpy(dst, src, len);
+	return csum_partial(dst, len, sum);
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/delay.c linux-libre-2.6.39-gnu/arch/m68k/lib/delay.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/delay.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/delay.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ *	arch/m68knommu/lib/delay.c
+ *
+ *	(C) Copyright 2004, Greg Ungerer <gerg@snapgear.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 <asm/param.h>
+#include <asm/delay.h>
+
+EXPORT_SYMBOL(udelay);
+
+void udelay(unsigned long usecs)
+{
+	_udelay(usecs);
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/divsi3.S linux-libre-2.6.39-gnu/arch/m68k/lib/divsi3.S
--- linux-libre-2.6.38-gnu/arch/m68k/lib/divsi3.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/divsi3.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,125 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+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; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* Use this one for any 680x0; assumes no floating point hardware.
+   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
+   Some of this code comes from MINIX, via the folks at ericsson.
+   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
+*/
+
+/* These are predefined by new versions of GNU cpp.  */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __IMMEDIATE_PREFIX__
+#define __IMMEDIATE_PREFIX__ #
+#endif
+
+/* ANSI concatenation macros.  */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers.  */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for immediate values.  */
+
+#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define fp REG (fp)
+#define sp REG (sp)
+
+	.text
+	.proc
+	.globl	SYM (__divsi3)
+SYM (__divsi3):
+	movel	d2, sp@-
+
+	moveq	IMM (1), d2	/* sign of result stored in d2 (=1 or =-1) */
+	movel	sp@(12), d1	/* d1 = divisor */
+	jpl	L1
+	negl	d1
+#if !(defined(__mcf5200__) || defined(__mcoldfire__))
+	negb	d2		/* change sign because divisor <0  */
+#else
+	negl	d2		/* change sign because divisor <0  */
+#endif
+L1:	movel	sp@(8), d0	/* d0 = dividend */
+	jpl	L2
+	negl	d0
+#if !(defined(__mcf5200__) || defined(__mcoldfire__))
+	negb	d2
+#else
+	negl	d2
+#endif
+
+L2:	movel	d1, sp@-
+	movel	d0, sp@-
+	jbsr	SYM (__udivsi3)	/* divide abs(dividend) by abs(divisor) */
+	addql	IMM (8), sp
+
+	tstb	d2
+	jpl	L3
+	negl	d0
+
+L3:	movel	sp@+, d2
+	rts
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/Makefile linux-libre-2.6.39-gnu/arch/m68k/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,5 @@
-#
-# Makefile for m68k-specific library files..
-#
-
-lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
-	   checksum.o string.o uaccess.o
+ifdef CONFIG_MMU
+include arch/m68k/lib/Makefile_mm
+else
+include arch/m68k/lib/Makefile_no
+endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/Makefile_mm linux-libre-2.6.39-gnu/arch/m68k/lib/Makefile_mm
--- linux-libre-2.6.38-gnu/arch/m68k/lib/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/Makefile_mm	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+#
+# Makefile for m68k-specific library files..
+#
+
+lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o muldi3.o \
+	   checksum.o string.o uaccess.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/Makefile_no linux-libre-2.6.39-gnu/arch/m68k/lib/Makefile_no
--- linux-libre-2.6.38-gnu/arch/m68k/lib/Makefile_no	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/Makefile_no	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,7 @@
+#
+# Makefile for m68knommu specific library files..
+#
+
+lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o \
+	   muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
+	   checksum.o memcpy.o memmove.o memset.o delay.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/memcpy.c linux-libre-2.6.39-gnu/arch/m68k/lib/memcpy.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/memcpy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/memcpy.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+
+#include <linux/types.h>
+
+void * memcpy(void * to, const void * from, size_t n)
+{
+#ifdef CONFIG_COLDFIRE
+  void *xto = to;
+  size_t temp;
+
+  if (!n)
+    return xto;
+  if ((long) to & 1)
+    {
+      char *cto = to;
+      const char *cfrom = from;
+      *cto++ = *cfrom++;
+      to = cto;
+      from = cfrom;
+      n--;
+    }
+  if (n > 2 && (long) to & 2)
+    {
+      short *sto = to;
+      const short *sfrom = from;
+      *sto++ = *sfrom++;
+      to = sto;
+      from = sfrom;
+      n -= 2;
+    }
+  temp = n >> 2;
+  if (temp)
+    {
+      long *lto = to;
+      const long *lfrom = from;
+      for (; temp; temp--)
+	*lto++ = *lfrom++;
+      to = lto;
+      from = lfrom;
+    }
+  if (n & 2)
+    {
+      short *sto = to;
+      const short *sfrom = from;
+      *sto++ = *sfrom++;
+      to = sto;
+      from = sfrom;
+    }
+  if (n & 1)
+    {
+      char *cto = to;
+      const char *cfrom = from;
+      *cto = *cfrom;
+    }
+  return xto;
+#else
+  const char *c_from = from;
+  char *c_to = to;
+  while (n-- > 0)
+    *c_to++ = *c_from++;
+  return((void *) to);
+#endif
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/memmove.c linux-libre-2.6.39-gnu/arch/m68k/lib/memmove.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/memmove.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/memmove.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * 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.
+ */
+
+#define __IN_STRING_C
+
+#include <linux/module.h>
+#include <linux/string.h>
+
+void *memmove(void *dest, const void *src, size_t n)
+{
+	void *xdest = dest;
+	size_t temp;
+
+	if (!n)
+		return xdest;
+
+	if (dest < src) {
+		if ((long)dest & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*cdest++ = *csrc++;
+			dest = cdest;
+			src = csrc;
+			n--;
+		}
+		if (n > 2 && (long)dest & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*sdest++ = *ssrc++;
+			dest = sdest;
+			src = ssrc;
+			n -= 2;
+		}
+		temp = n >> 2;
+		if (temp) {
+			long *ldest = dest;
+			const long *lsrc = src;
+			temp--;
+			do
+				*ldest++ = *lsrc++;
+			while (temp--);
+			dest = ldest;
+			src = lsrc;
+		}
+		if (n & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*sdest++ = *ssrc++;
+			dest = sdest;
+			src = ssrc;
+		}
+		if (n & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*cdest = *csrc;
+		}
+	} else {
+		dest = (char *)dest + n;
+		src = (const char *)src + n;
+		if ((long)dest & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*--cdest = *--csrc;
+			dest = cdest;
+			src = csrc;
+			n--;
+		}
+		if (n > 2 && (long)dest & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*--sdest = *--ssrc;
+			dest = sdest;
+			src = ssrc;
+			n -= 2;
+		}
+		temp = n >> 2;
+		if (temp) {
+			long *ldest = dest;
+			const long *lsrc = src;
+			temp--;
+			do
+				*--ldest = *--lsrc;
+			while (temp--);
+			dest = ldest;
+			src = lsrc;
+		}
+		if (n & 2) {
+			short *sdest = dest;
+			const short *ssrc = src;
+			*--sdest = *--ssrc;
+			dest = sdest;
+			src = ssrc;
+		}
+		if (n & 1) {
+			char *cdest = dest;
+			const char *csrc = src;
+			*--cdest = *--csrc;
+		}
+	}
+	return xdest;
+}
+EXPORT_SYMBOL(memmove);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/memset.c linux-libre-2.6.39-gnu/arch/m68k/lib/memset.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/memset.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/memset.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+#include <linux/types.h>
+
+void * memset(void * s, int c, size_t count)
+{
+  void *xs = s;
+  size_t temp;
+
+  if (!count)
+    return xs;
+  c &= 0xff;
+  c |= c << 8;
+  c |= c << 16;
+  if ((long) s & 1)
+    {
+      char *cs = s;
+      *cs++ = c;
+      s = cs;
+      count--;
+    }
+  if (count > 2 && (long) s & 2)
+    {
+      short *ss = s;
+      *ss++ = c;
+      s = ss;
+      count -= 2;
+    }
+  temp = count >> 2;
+  if (temp)
+    {
+      long *ls = s;
+      for (; temp; temp--)
+	*ls++ = c;
+      s = ls;
+    }
+  if (count & 2)
+    {
+      short *ss = s;
+      *ss++ = c;
+      s = ss;
+    }
+  if (count & 1)
+    {
+      char *cs = s;
+      *cs = c;
+    }
+  return xs;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/modsi3.S linux-libre-2.6.39-gnu/arch/m68k/lib/modsi3.S
--- linux-libre-2.6.38-gnu/arch/m68k/lib/modsi3.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/modsi3.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,113 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+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; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* Use this one for any 680x0; assumes no floating point hardware.
+   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
+   Some of this code comes from MINIX, via the folks at ericsson.
+   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
+*/
+
+/* These are predefined by new versions of GNU cpp.  */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __IMMEDIATE_PREFIX__
+#define __IMMEDIATE_PREFIX__ #
+#endif
+
+/* ANSI concatenation macros.  */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers.  */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for immediate values.  */
+
+#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define fp REG (fp)
+#define sp REG (sp)
+
+	.text
+	.proc
+	.globl	SYM (__modsi3)
+SYM (__modsi3):
+	movel	sp@(8), d1	/* d1 = divisor */
+	movel	sp@(4), d0	/* d0 = dividend */
+	movel	d1, sp@-
+	movel	d0, sp@-
+	jbsr	SYM (__divsi3)
+	addql	IMM (8), sp
+	movel	sp@(8), d1	/* d1 = divisor */
+#if !(defined(__mcf5200__) || defined(__mcoldfire__))
+	movel	d1, sp@-
+	movel	d0, sp@-
+	jbsr	SYM (__mulsi3)	/* d0 = (a/b)*b */
+	addql	IMM (8), sp
+#else
+	mulsl	d1,d0
+#endif
+	movel	sp@(4), d1	/* d1 = dividend */
+	subl	d0, d1		/* d1 = a - (a/b)*b */
+	movel	d1, d0
+	rts
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/muldi3.c linux-libre-2.6.39-gnu/arch/m68k/lib/muldi3.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/muldi3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/muldi3.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,63 +1,5 @@
-/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
-			   gcc-2.7.2.3/longlong.h which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define BITS_PER_UNIT 8
-
-#define umul_ppmm(w1, w0, u, v) \
-  __asm__ ("mulu%.l %3,%1:%0"						\
-           : "=d" ((USItype)(w0)),					\
-             "=d" ((USItype)(w1))					\
-           : "%0" ((USItype)(u)),					\
-             "dmi" ((USItype)(v)))
-
-#define __umulsidi3(u, v) \
-  ({DIunion __w;							\
-    umul_ppmm (__w.s.high, __w.s.low, u, v);				\
-    __w.ll; })
-
-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;
-
-DItype
-__muldi3 (DItype u, DItype v)
-{
-  DIunion w;
-  DIunion uu, vv;
-
-  uu.ll = u,
-  vv.ll = v;
-
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-	       + (USItype) uu.s.high * (USItype) vv.s.low);
-
-  return w.ll;
-}
+#ifdef CONFIG_MMU
+#include "muldi3_mm.c"
+#else
+#include "muldi3_no.c"
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/muldi3_mm.c linux-libre-2.6.39-gnu/arch/m68k/lib/muldi3_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/muldi3_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/muldi3_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and
+			   gcc-2.7.2.3/longlong.h which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#define BITS_PER_UNIT 8
+
+#define umul_ppmm(w1, w0, u, v) \
+  __asm__ ("mulu%.l %3,%1:%0"						\
+           : "=d" ((USItype)(w0)),					\
+             "=d" ((USItype)(w1))					\
+           : "%0" ((USItype)(u)),					\
+             "dmi" ((USItype)(v)))
+
+#define __umulsidi3(u, v) \
+  ({DIunion __w;							\
+    umul_ppmm (__w.s.high, __w.s.low, u, v);				\
+    __w.ll; })
+
+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;
+
+DItype
+__muldi3 (DItype u, DItype v)
+{
+  DIunion w;
+  DIunion uu, vv;
+
+  uu.ll = u,
+  vv.ll = v;
+
+  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
+  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+	       + (USItype) uu.s.high * (USItype) vv.s.low);
+
+  return w.ll;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/muldi3_no.c linux-libre-2.6.39-gnu/arch/m68k/lib/muldi3_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/lib/muldi3_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/muldi3_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,86 @@
+/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and 
+			   gcc-2.7.2.3/longlong.h which is: */
+/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+GNU CC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with GNU CC; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+#define BITS_PER_UNIT 8
+#define SI_TYPE_SIZE 32
+
+#define __BITS4 (SI_TYPE_SIZE / 4)
+#define __ll_B (1L << (SI_TYPE_SIZE / 2))
+#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
+#define __ll_highpart(t) ((USItype) (t) / __ll_B)
+
+#define umul_ppmm(w1, w0, u, v)						\
+  do {									\
+    USItype __x0, __x1, __x2, __x3;					\
+    USItype __ul, __vl, __uh, __vh;					\
+									\
+    __ul = __ll_lowpart (u);						\
+    __uh = __ll_highpart (u);						\
+    __vl = __ll_lowpart (v);						\
+    __vh = __ll_highpart (v);						\
+									\
+    __x0 = (USItype) __ul * __vl;					\
+    __x1 = (USItype) __ul * __vh;					\
+    __x2 = (USItype) __uh * __vl;					\
+    __x3 = (USItype) __uh * __vh;					\
+									\
+    __x1 += __ll_highpart (__x0);/* this can't give carry */		\
+    __x1 += __x2;		/* but this indeed can */		\
+    if (__x1 < __x2)		/* did we get it? */			\
+      __x3 += __ll_B;		/* yes, add it in the proper pos. */	\
+									\
+    (w1) = __x3 + __ll_highpart (__x1);					\
+    (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);		\
+  } while (0)
+
+#define __umulsidi3(u, v) \
+  ({DIunion __w;							\
+    umul_ppmm (__w.s.high, __w.s.low, u, v);				\
+    __w.ll; })
+
+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;
+
+DItype
+__muldi3 (DItype u, DItype v)
+{
+  DIunion w;
+  DIunion uu, vv;
+
+  uu.ll = u,
+  vv.ll = v;
+
+  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
+  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
+	       + (USItype) uu.s.high * (USItype) vv.s.low);
+
+  return w.ll;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/mulsi3.S linux-libre-2.6.39-gnu/arch/m68k/lib/mulsi3.S
--- linux-libre-2.6.38-gnu/arch/m68k/lib/mulsi3.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/mulsi3.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,110 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+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; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* Use this one for any 680x0; assumes no floating point hardware.
+   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
+   Some of this code comes from MINIX, via the folks at ericsson.
+   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
+*/
+
+/* These are predefined by new versions of GNU cpp.  */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __IMMEDIATE_PREFIX__
+#define __IMMEDIATE_PREFIX__ #
+#endif
+
+/* ANSI concatenation macros.  */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers.  */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for immediate values.  */
+
+#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define fp REG (fp)
+#define sp REG (sp)
+
+	.text
+	.proc
+	.globl	SYM (__mulsi3)
+SYM (__mulsi3):
+	movew	sp@(4), d0	/* x0 -> d0 */
+	muluw	sp@(10), d0	/* x0*y1 */
+	movew	sp@(6), d1	/* x1 -> d1 */
+	muluw	sp@(8), d1	/* x1*y0 */
+#if !(defined(__mcf5200__) || defined(__mcoldfire__))
+	addw	d1, d0
+#else
+	addl	d1, d0
+#endif
+	swap	d0
+	clrw	d0
+	movew	sp@(6), d1	/* x1 -> d1 */
+	muluw	sp@(10), d1	/* x1*y1 */
+	addl	d1, d0
+
+	rts
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/udivsi3.S linux-libre-2.6.39-gnu/arch/m68k/lib/udivsi3.S
--- linux-libre-2.6.38-gnu/arch/m68k/lib/udivsi3.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/udivsi3.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,162 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+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; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* Use this one for any 680x0; assumes no floating point hardware.
+   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
+   Some of this code comes from MINIX, via the folks at ericsson.
+   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
+*/
+
+/* These are predefined by new versions of GNU cpp.  */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __IMMEDIATE_PREFIX__
+#define __IMMEDIATE_PREFIX__ #
+#endif
+
+/* ANSI concatenation macros.  */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers.  */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for immediate values.  */
+
+#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define fp REG (fp)
+#define sp REG (sp)
+
+	.text
+	.proc
+	.globl	SYM (__udivsi3)
+SYM (__udivsi3):
+#if !(defined(__mcf5200__) || defined(__mcoldfire__))
+	movel	d2, sp@-
+	movel	sp@(12), d1	/* d1 = divisor */
+	movel	sp@(8), d0	/* d0 = dividend */
+
+	cmpl	IMM (0x10000), d1 /* divisor >= 2 ^ 16 ?   */
+	jcc	L3		/* then try next algorithm */
+	movel	d0, d2
+	clrw	d2
+	swap	d2
+	divu	d1, d2          /* high quotient in lower word */
+	movew	d2, d0		/* save high quotient */
+	swap	d0
+	movew	sp@(10), d2	/* get low dividend + high rest */
+	divu	d1, d2		/* low quotient */
+	movew	d2, d0
+	jra	L6
+
+L3:	movel	d1, d2		/* use d2 as divisor backup */
+L4:	lsrl	IMM (1), d1	/* shift divisor */
+	lsrl	IMM (1), d0	/* shift dividend */
+	cmpl	IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ?  */
+	jcc	L4
+	divu	d1, d0		/* now we have 16 bit divisor */
+	andl	IMM (0xffff), d0 /* mask out divisor, ignore remainder */
+
+/* Multiply the 16 bit tentative quotient with the 32 bit divisor.  Because of
+   the operand ranges, this might give a 33 bit product.  If this product is
+   greater than the dividend, the tentative quotient was too large. */
+	movel	d2, d1
+	mulu	d0, d1		/* low part, 32 bits */
+	swap	d2
+	mulu	d0, d2		/* high part, at most 17 bits */
+	swap	d2		/* align high part with low part */
+	tstw	d2		/* high part 17 bits? */
+	jne	L5		/* if 17 bits, quotient was too large */
+	addl	d2, d1		/* add parts */
+	jcs	L5		/* if sum is 33 bits, quotient was too large */
+	cmpl	sp@(8), d1	/* compare the sum with the dividend */
+	jls	L6		/* if sum > dividend, quotient was too large */
+L5:	subql	IMM (1), d0	/* adjust quotient */
+
+L6:	movel	sp@+, d2
+	rts
+
+#else /* __mcf5200__ || __mcoldfire__ */
+
+/* Coldfire implementation of non-restoring division algorithm from
+   Hennessy & Patterson, Appendix A. */
+	link	a6,IMM (-12)
+	moveml	d2-d4,sp@
+	movel	a6@(8),d0
+	movel	a6@(12),d1
+	clrl	d2		| clear p
+	moveq	IMM (31),d4
+L1:	addl	d0,d0		| shift reg pair (p,a) one bit left
+	addxl	d2,d2
+	movl	d2,d3		| subtract b from p, store in tmp.
+	subl	d1,d3
+	jcs	L2		| if no carry,
+	bset	IMM (0),d0	| set the low order bit of a to 1,
+	movl	d3,d2		| and store tmp in p.
+L2:	subql	IMM (1),d4
+	jcc	L1
+	moveml	sp@,d2-d4	| restore data registers
+	unlk	a6		| and return
+	rts
+#endif /* __mcf5200__ || __mcoldfire__ */
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/lib/umodsi3.S linux-libre-2.6.39-gnu/arch/m68k/lib/umodsi3.S
--- linux-libre-2.6.38-gnu/arch/m68k/lib/umodsi3.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/lib/umodsi3.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,113 @@
+/* libgcc1 routines for 68000 w/o floating-point hardware.
+   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
+
+This file is part of GNU CC.
+
+GNU CC is free software; you can redistribute 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.
+
+In addition to the permissions in the GNU General Public License, the
+Free Software Foundation gives you unlimited permission to link the
+compiled version of this file with other programs, and to distribute
+those programs without any restriction coming from the use of this
+file.  (The General Public License restrictions do apply in other
+respects; for example, they cover modification of the file, and
+distribution when not linked into another program.)
+
+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; see the file COPYING.  If not, write to
+the Free Software Foundation, 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA.  */
+
+/* As a special exception, if you link this library with files
+   compiled with GCC to produce an executable, this does not cause
+   the resulting executable to be covered by the GNU General Public License.
+   This exception does not however invalidate any other reasons why
+   the executable file might be covered by the GNU General Public License.  */
+
+/* Use this one for any 680x0; assumes no floating point hardware.
+   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
+   Some of this code comes from MINIX, via the folks at ericsson.
+   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
+*/
+
+/* These are predefined by new versions of GNU cpp.  */
+
+#ifndef __USER_LABEL_PREFIX__
+#define __USER_LABEL_PREFIX__ _
+#endif
+
+#ifndef __REGISTER_PREFIX__
+#define __REGISTER_PREFIX__
+#endif
+
+#ifndef __IMMEDIATE_PREFIX__
+#define __IMMEDIATE_PREFIX__ #
+#endif
+
+/* ANSI concatenation macros.  */
+
+#define CONCAT1(a, b) CONCAT2(a, b)
+#define CONCAT2(a, b) a ## b
+
+/* Use the right prefix for global labels.  */
+
+#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
+
+/* Use the right prefix for registers.  */
+
+#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
+
+/* Use the right prefix for immediate values.  */
+
+#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
+
+#define d0 REG (d0)
+#define d1 REG (d1)
+#define d2 REG (d2)
+#define d3 REG (d3)
+#define d4 REG (d4)
+#define d5 REG (d5)
+#define d6 REG (d6)
+#define d7 REG (d7)
+#define a0 REG (a0)
+#define a1 REG (a1)
+#define a2 REG (a2)
+#define a3 REG (a3)
+#define a4 REG (a4)
+#define a5 REG (a5)
+#define a6 REG (a6)
+#define fp REG (fp)
+#define sp REG (sp)
+
+	.text
+	.proc
+	.globl	SYM (__umodsi3)
+SYM (__umodsi3):
+	movel	sp@(8), d1	/* d1 = divisor */
+	movel	sp@(4), d0	/* d0 = dividend */
+	movel	d1, sp@-
+	movel	d0, sp@-
+	jbsr	SYM (__udivsi3)
+	addql	IMM (8), sp
+	movel	sp@(8), d1	/* d1 = divisor */
+#if !(defined(__mcf5200__) || defined(__mcoldfire__))
+	movel	d1, sp@-
+	movel	d0, sp@-
+	jbsr	SYM (__mulsi3)	/* d0 = (a/b)*b */
+	addql	IMM (8), sp
+#else
+	mulsl	d1,d0
+#endif
+	movel	sp@(4), d1	/* d1 = dividend */
+	subl	d0, d1		/* d1 = a - (a/b)*b */
+	movel	d1, d0
+	rts
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Makefile linux-libre-2.6.39-gnu/arch/m68k/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,122 +1,7 @@
-#
-# m68k/Makefile
-#
-# This file is included by the global makefile so that you can add your own
-# architecture-specific flags and dependencies. Remember to do have actions
-# for "archclean" and "archdep" for cleaning up and making dependencies for
-# this architecture
-#
-# 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 by Hamish Macdonald
-#
-
 KBUILD_DEFCONFIG := multi_defconfig
 
-# override top level makefile
-AS += -m68020
-LDFLAGS := -m m68kelf
-KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
-ifneq ($(SUBARCH),$(ARCH))
-	ifeq ($(CROSS_COMPILE),)
-		CROSS_COMPILE := $(call cc-cross-prefix, \
-			m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
-	endif
-endif
-
-ifdef CONFIG_SUN3
-LDFLAGS_vmlinux = -N
-endif
-
-CHECKFLAGS += -D__mc68000__
-
-# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
-KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
-
-# enable processor switch if compiled only for a single cpu
-ifndef CONFIG_M68020
-ifndef CONFIG_M68030
-
-ifndef CONFIG_M68060
-KBUILD_CFLAGS += -m68040
-endif
-
-ifndef CONFIG_M68040
-KBUILD_CFLAGS += -m68060
-endif
-
-endif
-endif
-
-ifdef CONFIG_KGDB
-# If configured for kgdb support, include debugging infos and keep the
-# frame pointer
-KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
-endif
-
-ifndef CONFIG_SUN3
-head-y := arch/m68k/kernel/head.o
-else
-head-y := arch/m68k/kernel/sun3-head.o
-endif
-
-core-y				+= arch/m68k/kernel/	arch/m68k/mm/
-libs-y				+= arch/m68k/lib/
-
-core-$(CONFIG_Q40)		+= arch/m68k/q40/
-core-$(CONFIG_AMIGA)		+= arch/m68k/amiga/
-core-$(CONFIG_ATARI)		+= arch/m68k/atari/
-core-$(CONFIG_MAC)		+= arch/m68k/mac/
-core-$(CONFIG_HP300)		+= arch/m68k/hp300/
-core-$(CONFIG_APOLLO)		+= arch/m68k/apollo/
-core-$(CONFIG_MVME147)		+= arch/m68k/mvme147/
-core-$(CONFIG_MVME16x)		+= arch/m68k/mvme16x/
-core-$(CONFIG_BVME6000)		+= arch/m68k/bvme6000/
-core-$(CONFIG_SUN3X)		+= arch/m68k/sun3x/	arch/m68k/sun3/
-core-$(CONFIG_SUN3)		+= arch/m68k/sun3/	arch/m68k/sun3/prom/
-core-$(CONFIG_M68040)		+= arch/m68k/fpsp040/
-core-$(CONFIG_M68060)		+= arch/m68k/ifpsp060/
-core-$(CONFIG_M68KFPU_EMU)	+= arch/m68k/math-emu/
-
-all:	zImage
-
-lilo:	vmlinux
-	if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
-	if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
-	cat vmlinux > $(INSTALL_PATH)/vmlinux
-	cp System.map $(INSTALL_PATH)/System.map
-	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
-
-zImage compressed: vmlinux.gz
-
-vmlinux.gz: vmlinux
-
-ifndef CONFIG_KGDB
-	cp vmlinux vmlinux.tmp
-	$(STRIP) vmlinux.tmp
-	gzip -9c vmlinux.tmp >vmlinux.gz
-	rm vmlinux.tmp
-else
-	gzip -9c vmlinux >vmlinux.gz
-endif
-
-bzImage: vmlinux.bz2
-
-vmlinux.bz2: vmlinux
-
-ifndef CONFIG_KGDB
-	cp vmlinux vmlinux.tmp
-	$(STRIP) vmlinux.tmp
-	bzip2 -1c vmlinux.tmp >vmlinux.bz2
-	rm vmlinux.tmp
+ifdef CONFIG_MMU
+include $(srctree)/arch/m68k/Makefile_mm
 else
-	bzip2 -1c vmlinux >vmlinux.bz2
+include $(srctree)/arch/m68k/Makefile_no
 endif
-
-archclean:
-	rm -f vmlinux.gz vmlinux.bz2
-
-install:
-	sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Makefile_mm linux-libre-2.6.39-gnu/arch/m68k/Makefile_mm
--- linux-libre-2.6.38-gnu/arch/m68k/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/Makefile_mm	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,121 @@
+#
+# m68k/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies. Remember to do have actions
+# for "archclean" and "archdep" for cleaning up and making dependencies for
+# this architecture
+#
+# 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 by Hamish Macdonald
+#
+
+# override top level makefile
+AS += -m68020
+LDFLAGS := -m m68kelf
+KBUILD_LDFLAGS_MODULE += -T $(srctree)/arch/m68k/kernel/module.lds
+ifneq ($(SUBARCH),$(ARCH))
+	ifeq ($(CROSS_COMPILE),)
+		CROSS_COMPILE := $(call cc-cross-prefix, \
+			m68k-linux-gnu- m68k-linux- m68k-unknown-linux-gnu-)
+	endif
+endif
+
+ifdef CONFIG_SUN3
+LDFLAGS_vmlinux = -N
+endif
+
+CHECKFLAGS += -D__mc68000__
+
+# without -fno-strength-reduce the 53c7xx.c driver fails ;-(
+KBUILD_CFLAGS += -pipe -fno-strength-reduce -ffixed-a2
+
+# enable processor switch if compiled only for a single cpu
+ifndef CONFIG_M68020
+ifndef CONFIG_M68030
+
+ifndef CONFIG_M68060
+KBUILD_CFLAGS += -m68040
+endif
+
+ifndef CONFIG_M68040
+KBUILD_CFLAGS += -m68060
+endif
+
+endif
+endif
+
+ifdef CONFIG_KGDB
+# If configured for kgdb support, include debugging infos and keep the
+# frame pointer
+KBUILD_CFLAGS := $(subst -fomit-frame-pointer,,$(KBUILD_CFLAGS)) -g
+endif
+
+ifndef CONFIG_SUN3
+head-y := arch/m68k/kernel/head.o
+else
+head-y := arch/m68k/kernel/sun3-head.o
+endif
+
+core-y				+= arch/m68k/kernel/	arch/m68k/mm/
+libs-y				+= arch/m68k/lib/
+
+core-$(CONFIG_Q40)		+= arch/m68k/q40/
+core-$(CONFIG_AMIGA)		+= arch/m68k/amiga/
+core-$(CONFIG_ATARI)		+= arch/m68k/atari/
+core-$(CONFIG_MAC)		+= arch/m68k/mac/
+core-$(CONFIG_HP300)		+= arch/m68k/hp300/
+core-$(CONFIG_APOLLO)		+= arch/m68k/apollo/
+core-$(CONFIG_MVME147)		+= arch/m68k/mvme147/
+core-$(CONFIG_MVME16x)		+= arch/m68k/mvme16x/
+core-$(CONFIG_BVME6000)		+= arch/m68k/bvme6000/
+core-$(CONFIG_SUN3X)		+= arch/m68k/sun3x/	arch/m68k/sun3/
+core-$(CONFIG_SUN3)		+= arch/m68k/sun3/	arch/m68k/sun3/prom/
+core-$(CONFIG_NATFEAT)		+= arch/m68k/emu/
+core-$(CONFIG_M68040)		+= arch/m68k/fpsp040/
+core-$(CONFIG_M68060)		+= arch/m68k/ifpsp060/
+core-$(CONFIG_M68KFPU_EMU)	+= arch/m68k/math-emu/
+
+all:	zImage
+
+lilo:	vmlinux
+	if [ -f $(INSTALL_PATH)/vmlinux ]; then mv -f $(INSTALL_PATH)/vmlinux $(INSTALL_PATH)/vmlinux.old; fi
+	if [ -f $(INSTALL_PATH)/System.map ]; then mv -f $(INSTALL_PATH)/System.map $(INSTALL_PATH)/System.old; fi
+	cat vmlinux > $(INSTALL_PATH)/vmlinux
+	cp System.map $(INSTALL_PATH)/System.map
+	if [ -x /sbin/lilo ]; then /sbin/lilo; else /etc/lilo/install; fi
+
+zImage compressed: vmlinux.gz
+
+vmlinux.gz: vmlinux
+
+ifndef CONFIG_KGDB
+	cp vmlinux vmlinux.tmp
+	$(STRIP) vmlinux.tmp
+	gzip -9c vmlinux.tmp >vmlinux.gz
+	rm vmlinux.tmp
+else
+	gzip -9c vmlinux >vmlinux.gz
+endif
+
+bzImage: vmlinux.bz2
+
+vmlinux.bz2: vmlinux
+
+ifndef CONFIG_KGDB
+	cp vmlinux vmlinux.tmp
+	$(STRIP) vmlinux.tmp
+	bzip2 -1c vmlinux.tmp >vmlinux.bz2
+	rm vmlinux.tmp
+else
+	bzip2 -1c vmlinux >vmlinux.bz2
+endif
+
+archclean:
+	rm -f vmlinux.gz vmlinux.bz2
+
+install:
+	sh $(srctree)/arch/m68k/install.sh $(KERNELRELEASE) vmlinux.gz System.map "$(INSTALL_PATH)"
diff -druN linux-libre-2.6.38-gnu/arch/m68k/Makefile_no linux-libre-2.6.39-gnu/arch/m68k/Makefile_no
--- linux-libre-2.6.38-gnu/arch/m68k/Makefile_no	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/Makefile_no	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,124 @@
+#
+# arch/m68k/Makefile
+#
+# 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.
+#
+# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
+#
+
+platform-$(CONFIG_M68328)	:= 68328
+platform-$(CONFIG_M68EZ328)	:= 68EZ328
+platform-$(CONFIG_M68VZ328)	:= 68VZ328
+platform-$(CONFIG_M68360)	:= 68360
+platform-$(CONFIG_M5206)	:= 5206
+platform-$(CONFIG_M5206e)	:= 5206e
+platform-$(CONFIG_M520x)	:= 520x
+platform-$(CONFIG_M523x)	:= 523x
+platform-$(CONFIG_M5249)	:= 5249
+platform-$(CONFIG_M527x)	:= 527x
+platform-$(CONFIG_M5272)	:= 5272
+platform-$(CONFIG_M528x)	:= 528x
+platform-$(CONFIG_M5307)	:= 5307
+platform-$(CONFIG_M532x)	:= 532x
+platform-$(CONFIG_M5407)	:= 5407
+platform-$(CONFIG_M54xx)	:= 54xx
+PLATFORM := $(platform-y)
+
+board-$(CONFIG_PILOT)		:= pilot
+board-$(CONFIG_UC5272)          := UC5272
+board-$(CONFIG_UC5282)          := UC5282
+board-$(CONFIG_UCSIMM)		:= ucsimm
+board-$(CONFIG_UCDIMM)		:= ucdimm
+board-$(CONFIG_UCQUICC)		:= uCquicc
+board-$(CONFIG_DRAGEN2)		:= de2
+board-$(CONFIG_ARNEWSH)		:= ARNEWSH
+board-$(CONFIG_FREESCALE)	:= FREESCALE
+board-$(CONFIG_M5235EVB)	:= M5235EVB
+board-$(CONFIG_M5271EVB)	:= M5271EVB
+board-$(CONFIG_M5275EVB)	:= M5275EVB
+board-$(CONFIG_M5282EVB)	:= M5282EVB
+board-$(CONFIG_ELITE)		:= eLITE
+board-$(CONFIG_NETtel)		:= NETtel
+board-$(CONFIG_SECUREEDGEMP3)	:= MP3
+board-$(CONFIG_CLEOPATRA)	:= CLEOPATRA
+board-$(CONFIG_senTec)		:= senTec
+board-$(CONFIG_SNEHA) 	        := SNEHA
+board-$(CONFIG_M5208EVB)	:= M5208EVB
+board-$(CONFIG_MOD5272)		:= MOD5272
+board-$(CONFIG_AVNET)           := AVNET
+board-$(CONFIG_SAVANT)		:= SAVANT
+BOARD := $(board-y)
+
+model-$(CONFIG_RAMKERNEL)	:= ram
+model-$(CONFIG_ROMKERNEL)	:= rom
+MODEL := $(model-y)
+
+#
+# Some code support is grouped together for a common cpu-subclass (for
+# example all ColdFire cpu's are very similar). Determine the sub-class
+# for the selected cpu. ONLY need to define this for the non-base member
+# of the family.
+#
+cpuclass-$(CONFIG_M5206)	:= coldfire
+cpuclass-$(CONFIG_M5206e)	:= coldfire
+cpuclass-$(CONFIG_M520x)	:= coldfire
+cpuclass-$(CONFIG_M523x)	:= coldfire
+cpuclass-$(CONFIG_M5249)	:= coldfire
+cpuclass-$(CONFIG_M527x)	:= coldfire
+cpuclass-$(CONFIG_M5272)	:= coldfire
+cpuclass-$(CONFIG_M528x)	:= coldfire
+cpuclass-$(CONFIG_M5307)	:= coldfire
+cpuclass-$(CONFIG_M532x)	:= coldfire
+cpuclass-$(CONFIG_M5407)	:= coldfire
+cpuclass-$(CONFIG_M54xx)	:= coldfire
+cpuclass-$(CONFIG_M68328)	:= 68328
+cpuclass-$(CONFIG_M68EZ328)	:= 68328
+cpuclass-$(CONFIG_M68VZ328)	:= 68328
+cpuclass-$(CONFIG_M68360)	:= 68360
+CPUCLASS := $(cpuclass-y)
+
+ifneq ($(CPUCLASS),$(PLATFORM))
+CLASSDIR := arch/m68k/platform/$(cpuclass-y)/
+endif
+
+export PLATFORM BOARD MODEL CPUCLASS
+
+#
+# Some CFLAG additions based on specific CPU type.
+#
+cflags-$(CONFIG_M5206)		:= $(call cc-option,-mcpu=5206,-m5200)
+cflags-$(CONFIG_M5206e)		:= $(call cc-option,-mcpu=5206e,-m5200)
+cflags-$(CONFIG_M520x)		:= $(call cc-option,-mcpu=5208,-m5200)
+cflags-$(CONFIG_M523x)		:= $(call cc-option,-mcpu=523x,-m5307)
+cflags-$(CONFIG_M5249)		:= $(call cc-option,-mcpu=5249,-m5200)
+cflags-$(CONFIG_M5271)		:= $(call cc-option,-mcpu=5271,-m5307)
+cflags-$(CONFIG_M5272)		:= $(call cc-option,-mcpu=5272,-m5307)
+cflags-$(CONFIG_M5275)		:= $(call cc-option,-mcpu=5275,-m5307)
+cflags-$(CONFIG_M528x)		:= $(call cc-option,-mcpu=528x,-m5307)
+cflags-$(CONFIG_M5307)		:= $(call cc-option,-mcpu=5307,-m5200)
+cflags-$(CONFIG_M532x)		:= $(call cc-option,-mcpu=532x,-m5307)
+cflags-$(CONFIG_M5407)		:= $(call cc-option,-mcpu=5407,-m5200)
+cflags-$(CONFIG_M54xx)		:= $(call cc-option,-mcpu=5475,-m5200)
+cflags-$(CONFIG_M68328)		:= -m68000
+cflags-$(CONFIG_M68EZ328)	:= -m68000
+cflags-$(CONFIG_M68VZ328)	:= -m68000
+cflags-$(CONFIG_M68360)		:= -m68332
+
+KBUILD_AFLAGS += $(cflags-y)
+
+KBUILD_CFLAGS += $(cflags-y)
+KBUILD_CFLAGS += -D__linux__
+KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
+
+head-y := arch/m68k/platform/$(cpuclass-y)/head.o
+
+core-y	+= arch/m68k/kernel/ \
+	   arch/m68k/mm/ \
+	   $(CLASSDIR) \
+	   arch/m68k/platform/$(PLATFORM)/
+libs-y	+= arch/m68k/lib/
+
+archclean:
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/math-emu/Makefile linux-libre-2.6.39-gnu/arch/m68k/math-emu/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/math-emu/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/math-emu/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,8 +2,8 @@
 # Makefile for the linux kernel.
 #
 
-#EXTRA_AFLAGS += -DFPU_EMU_DEBUG
-#EXTRA_CFLAGS += -DFPU_EMU_DEBUG
+#asflags-y := -DFPU_EMU_DEBUG
+#ccflags-y := -DFPU_EMU_DEBUG
 
 obj-y		:= fp_entry.o fp_scan.o fp_util.o fp_move.o fp_movem.o \
 			fp_cond.o fp_arith.o fp_log.o fp_trig.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/fault.c linux-libre-2.6.39-gnu/arch/m68k/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,6 @@
 #include <asm/pgalloc.h>
 
 extern void die_if_kernel(char *, struct pt_regs *, long);
-extern const int frame_extra_sizes[]; /* in m68k/kernel/signal.c */
 
 int send_fault_sig(struct pt_regs *regs)
 {
@@ -35,21 +34,8 @@
 		force_sig_info(siginfo.si_signo,
 			       &siginfo, current);
 	} else {
-		const struct exception_table_entry *fixup;
-
-		/* Are we prepared to handle this kernel fault? */
-		if ((fixup = search_exception_tables(regs->pc))) {
-			struct pt_regs *tregs;
-			/* Create a new four word stack frame, discarding the old
-			   one.  */
-			regs->stkadj = frame_extra_sizes[regs->format];
-			tregs =	(struct pt_regs *)((ulong)regs + regs->stkadj);
-			tregs->vector = regs->vector;
-			tregs->format = 0;
-			tregs->pc = fixup->fixup;
-			tregs->sr = regs->sr;
+		if (handle_kernel_fault(regs))
 			return -1;
-		}
 
 		//if (siginfo.si_signo == SIGBUS)
 		//	force_sig_info(siginfo.si_signo,
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/init.c linux-libre-2.6.39-gnu/arch/m68k/mm/init.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,150 +1,5 @@
-/*
- *  linux/arch/m68k/mm/init.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  Contains common initialization routines, specific init code moved
- *  to motorola.c and sun3mmu.c
- */
-
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/system.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#ifdef CONFIG_ATARI
-#include <asm/atari_stram.h>
-#endif
-#include <asm/sections.h>
-#include <asm/tlb.h>
-
-DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
-
-pg_data_t pg_data_map[MAX_NUMNODES];
-EXPORT_SYMBOL(pg_data_map);
-
-int m68k_virt_to_node_shift;
-
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-pg_data_t *pg_data_table[65];
-EXPORT_SYMBOL(pg_data_table);
-#endif
-
-void __init m68k_setup_node(int node)
-{
-#ifndef CONFIG_SINGLE_MEMORY_CHUNK
-	struct mem_info *info = m68k_memory + node;
-	int i, end;
-
-	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
-	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
-	for (; i <= end; i++) {
-		if (pg_data_table[i])
-			printk("overlap at %u for chunk %u\n", i, node);
-		pg_data_table[i] = pg_data_map + node;
-	}
-#endif
-	pg_data_map[node].bdata = bootmem_node_data + node;
-	node_set_online(node);
-}
-
-
-/*
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-
-void *empty_zero_page;
-EXPORT_SYMBOL(empty_zero_page);
-
-extern void init_pointer_table(unsigned long ptable);
-
-/* References to section boundaries */
-
-extern pmd_t *zero_pgtable;
-
-void __init mem_init(void)
-{
-	pg_data_t *pgdat;
-	int codepages = 0;
-	int datapages = 0;
-	int initpages = 0;
-	int i;
-
-#ifdef CONFIG_ATARI
-	if (MACH_IS_ATARI)
-		atari_stram_mem_init_hook();
-#endif
-
-	/* this will put all memory onto the freelists */
-	totalram_pages = num_physpages = 0;
-	for_each_online_pgdat(pgdat) {
-		num_physpages += pgdat->node_present_pages;
-
-		totalram_pages += free_all_bootmem_node(pgdat);
-		for (i = 0; i < pgdat->node_spanned_pages; i++) {
-			struct page *page = pgdat->node_mem_map + i;
-			char *addr = page_to_virt(page);
-
-			if (!PageReserved(page))
-				continue;
-			if (addr >= _text &&
-			    addr < _etext)
-				codepages++;
-			else if (addr >= __init_begin &&
-				 addr < __init_end)
-				initpages++;
-			else
-				datapages++;
-		}
-	}
-
-#ifndef CONFIG_SUN3
-	/* insert pointer tables allocated so far into the tablelist */
-	init_pointer_table((unsigned long)kernel_pg_dir);
-	for (i = 0; i < PTRS_PER_PGD; i++) {
-		if (pgd_present(kernel_pg_dir[i]))
-			init_pointer_table(__pgd_page(kernel_pg_dir[i]));
-	}
-
-	/* insert also pointer table that we used to unmap the zero page */
-	if (zero_pgtable)
-		init_pointer_table((unsigned long)zero_pgtable);
-#endif
-
-	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
-	       nr_free_pages() << (PAGE_SHIFT-10),
-	       totalram_pages << (PAGE_SHIFT-10),
-	       codepages << (PAGE_SHIFT-10),
-	       datapages << (PAGE_SHIFT-10),
-	       initpages << (PAGE_SHIFT-10));
-}
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk ("Freeing initrd memory: %dk freed\n", pages);
-}
+#ifdef CONFIG_MMU
+#include "init_mm.c"
+#else
+#include "init_no.c"
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/init_mm.c linux-libre-2.6.39-gnu/arch/m68k/mm/init_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/init_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/init_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,150 @@
+/*
+ *  linux/arch/m68k/mm/init.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  Contains common initialization routines, specific init code moved
+ *  to motorola.c and sun3mmu.c
+ */
+
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/mm.h>
+#include <linux/swap.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+
+#include <asm/setup.h>
+#include <asm/uaccess.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#ifdef CONFIG_ATARI
+#include <asm/atari_stram.h>
+#endif
+#include <asm/sections.h>
+#include <asm/tlb.h>
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+pg_data_t pg_data_map[MAX_NUMNODES];
+EXPORT_SYMBOL(pg_data_map);
+
+int m68k_virt_to_node_shift;
+
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+pg_data_t *pg_data_table[65];
+EXPORT_SYMBOL(pg_data_table);
+#endif
+
+void __init m68k_setup_node(int node)
+{
+#ifndef CONFIG_SINGLE_MEMORY_CHUNK
+	struct mem_info *info = m68k_memory + node;
+	int i, end;
+
+	i = (unsigned long)phys_to_virt(info->addr) >> __virt_to_node_shift();
+	end = (unsigned long)phys_to_virt(info->addr + info->size - 1) >> __virt_to_node_shift();
+	for (; i <= end; i++) {
+		if (pg_data_table[i])
+			printk("overlap at %u for chunk %u\n", i, node);
+		pg_data_table[i] = pg_data_map + node;
+	}
+#endif
+	pg_data_map[node].bdata = bootmem_node_data + node;
+	node_set_online(node);
+}
+
+
+/*
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+
+void *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
+extern void init_pointer_table(unsigned long ptable);
+
+/* References to section boundaries */
+
+extern pmd_t *zero_pgtable;
+
+void __init mem_init(void)
+{
+	pg_data_t *pgdat;
+	int codepages = 0;
+	int datapages = 0;
+	int initpages = 0;
+	int i;
+
+#ifdef CONFIG_ATARI
+	if (MACH_IS_ATARI)
+		atari_stram_mem_init_hook();
+#endif
+
+	/* this will put all memory onto the freelists */
+	totalram_pages = num_physpages = 0;
+	for_each_online_pgdat(pgdat) {
+		num_physpages += pgdat->node_present_pages;
+
+		totalram_pages += free_all_bootmem_node(pgdat);
+		for (i = 0; i < pgdat->node_spanned_pages; i++) {
+			struct page *page = pgdat->node_mem_map + i;
+			char *addr = page_to_virt(page);
+
+			if (!PageReserved(page))
+				continue;
+			if (addr >= _text &&
+			    addr < _etext)
+				codepages++;
+			else if (addr >= __init_begin &&
+				 addr < __init_end)
+				initpages++;
+			else
+				datapages++;
+		}
+	}
+
+#ifndef CONFIG_SUN3
+	/* insert pointer tables allocated so far into the tablelist */
+	init_pointer_table((unsigned long)kernel_pg_dir);
+	for (i = 0; i < PTRS_PER_PGD; i++) {
+		if (pgd_present(kernel_pg_dir[i]))
+			init_pointer_table(__pgd_page(kernel_pg_dir[i]));
+	}
+
+	/* insert also pointer table that we used to unmap the zero page */
+	if (zero_pgtable)
+		init_pointer_table((unsigned long)zero_pgtable);
+#endif
+
+	printk("Memory: %luk/%luk available (%dk kernel code, %dk data, %dk init)\n",
+	       nr_free_pages() << (PAGE_SHIFT-10),
+	       totalram_pages << (PAGE_SHIFT-10),
+	       codepages << (PAGE_SHIFT-10),
+	       datapages << (PAGE_SHIFT-10),
+	       initpages << (PAGE_SHIFT-10));
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	int pages = 0;
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		init_page_count(virt_to_page(start));
+		free_page(start);
+		totalram_pages++;
+		pages++;
+	}
+	printk ("Freeing initrd memory: %dk freed\n", pages);
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/init_no.c linux-libre-2.6.39-gnu/arch/m68k/mm/init_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/init_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/init_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,193 @@
+/*
+ *  linux/arch/m68knommu/mm/init.c
+ *
+ *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
+ *                      Kenneth Albanowski <kjahds@kjahds.com>,
+ *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com) 
+ *
+ *  Based on:
+ *
+ *  linux/arch/m68k/mm/init.c
+ *
+ *  Copyright (C) 1995  Hamish Macdonald
+ *
+ *  JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
+ *  DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
+ */
+
+#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/swap.h>
+#include <linux/init.h>
+#include <linux/highmem.h>
+#include <linux/pagemap.h>
+#include <linux/bootmem.h>
+#include <linux/gfp.h>
+
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+
+#undef DEBUG
+
+extern void die_if_kernel(char *,struct pt_regs *,long);
+extern void free_initmem(void);
+
+/*
+ * BAD_PAGE is the page that is used for page faults when linux
+ * is out-of-memory. Older versions of linux just did a
+ * do_exit(), but using this instead means there is less risk
+ * for a process dying in kernel mode, possibly leaving a inode
+ * unused etc..
+ *
+ * BAD_PAGETABLE is the accompanying page-table: it is initialized
+ * to point to BAD_PAGE entries.
+ *
+ * ZERO_PAGE is a special page that is used for zero-initialized
+ * data and COW.
+ */
+static unsigned long empty_bad_page_table;
+
+static unsigned long empty_bad_page;
+
+unsigned long empty_zero_page;
+
+extern unsigned long memory_start;
+extern unsigned long memory_end;
+
+/*
+ * paging_init() continues the virtual memory environment setup which
+ * was begun by the code in arch/head.S.
+ * The parameters are pointers to where to stick the starting and ending
+ * addresses of available kernel virtual memory.
+ */
+void __init paging_init(void)
+{
+	/*
+	 * Make sure start_mem is page aligned, otherwise bootmem and
+	 * page_alloc get different views of the world.
+	 */
+#ifdef DEBUG
+	unsigned long start_mem = PAGE_ALIGN(memory_start);
+#endif
+	unsigned long end_mem   = memory_end & PAGE_MASK;
+
+#ifdef DEBUG
+	printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
+		start_mem, end_mem);
+#endif
+
+	/*
+	 * Initialize the bad page table and bad page to point
+	 * to a couple of allocated pages.
+	 */
+	empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+	empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+	empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
+	memset((void *)empty_zero_page, 0, PAGE_SIZE);
+
+	/*
+	 * Set up SFC/DFC registers (user data space).
+	 */
+	set_fs (USER_DS);
+
+#ifdef DEBUG
+	printk (KERN_DEBUG "before free_area_init\n");
+
+	printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
+		start_mem, end_mem);
+#endif
+
+	{
+		unsigned long zones_size[MAX_NR_ZONES] = {0, };
+
+		zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
+		free_area_init(zones_size);
+	}
+}
+
+void __init mem_init(void)
+{
+	int codek = 0, datak = 0, initk = 0;
+	unsigned long tmp;
+	extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
+	extern unsigned int _ramend, _rambase;
+	unsigned long len = _ramend - _rambase;
+	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 */
+
+	pr_debug("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
+
+	end_mem &= PAGE_MASK;
+	high_memory = (void *) end_mem;
+
+	start_mem = PAGE_ALIGN(start_mem);
+	max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
+
+	/* this will put all memory onto the freelists */
+	totalram_pages = free_all_bootmem();
+
+	codek = (&_etext - &_stext) >> 10;
+	datak = (&_ebss - &_sdata) >> 10;
+	initk = (&__init_begin - &__init_end) >> 10;
+
+	tmp = nr_free_pages() << PAGE_SHIFT;
+	printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
+	       tmp >> 10,
+	       len >> 10,
+	       codek,
+	       datak
+	       );
+}
+
+
+#ifdef CONFIG_BLK_DEV_INITRD
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	int pages = 0;
+	for (; start < end; start += PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(start));
+		init_page_count(virt_to_page(start));
+		free_page(start);
+		totalram_pages++;
+		pages++;
+	}
+	printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024));
+}
+#endif
+
+void
+free_initmem()
+{
+#ifdef CONFIG_RAMKERNEL
+	unsigned long addr;
+	extern char __init_begin, __init_end;
+	/*
+	 * The following code should be cool even if these sections
+	 * are not page aligned.
+	 */
+	addr = PAGE_ALIGN((unsigned long)(&__init_begin));
+	/* next to check that the page we free is not a partial page */
+	for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
+		ClearPageReserved(virt_to_page(addr));
+		init_page_count(virt_to_page(addr));
+		free_page(addr);
+		totalram_pages++;
+	}
+	printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
+			(addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
+			(int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
+			(int)(addr - PAGE_SIZE));
+#endif
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/kmap.c linux-libre-2.6.39-gnu/arch/m68k/mm/kmap.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/kmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/kmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,367 +1,5 @@
-/*
- *  linux/arch/m68k/mm/kmap.c
- *
- *  Copyright (C) 1997 Roman Hodek
- *
- *  10/01/99 cleaned up the code and changing to the same interface
- *	     used by other architectures		/Roman Zippel
- */
-
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#undef DEBUG
-
-#define PTRTREESIZE	(256*1024)
-
-/*
- * For 040/060 we can use the virtual memory area like other architectures,
- * but for 020/030 we want to use early termination page descriptor and we
- * can't mix this with normal page descriptors, so we have to copy that code
- * (mm/vmalloc.c) and return appriorate aligned addresses.
- */
-
-#ifdef CPU_M68040_OR_M68060_ONLY
-
-#define IO_SIZE		PAGE_SIZE
-
-static inline struct vm_struct *get_io_area(unsigned long size)
-{
-	return get_vm_area(size, VM_IOREMAP);
-}
-
-
-static inline void free_io_area(void *addr)
-{
-	vfree((void *)(PAGE_MASK & (unsigned long)addr));
-}
-
-#else
-
-#define IO_SIZE		(256*1024)
-
-static struct vm_struct *iolist;
-
-static struct vm_struct *get_io_area(unsigned long size)
-{
-	unsigned long addr;
-	struct vm_struct **p, *tmp, *area;
-
-	area = kmalloc(sizeof(*area), GFP_KERNEL);
-	if (!area)
-		return NULL;
-	addr = KMAP_START;
-	for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
-		if (size + addr < (unsigned long)tmp->addr)
-			break;
-		if (addr > KMAP_END-size) {
-			kfree(area);
-			return NULL;
-		}
-		addr = tmp->size + (unsigned long)tmp->addr;
-	}
-	area->addr = (void *)addr;
-	area->size = size + IO_SIZE;
-	area->next = *p;
-	*p = area;
-	return area;
-}
-
-static inline void free_io_area(void *addr)
-{
-	struct vm_struct **p, *tmp;
-
-	if (!addr)
-		return;
-	addr = (void *)((unsigned long)addr & -IO_SIZE);
-	for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
-		if (tmp->addr == addr) {
-			*p = tmp->next;
-			__iounmap(tmp->addr, tmp->size);
-			kfree(tmp);
-			return;
-		}
-	}
-}
-
-#endif
-
-/*
- * Map some physical address range into the kernel address space.
- */
-/* Rewritten by Andreas Schwab to remove all races. */
-
-void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
-{
-	struct vm_struct *area;
-	unsigned long virtaddr, retaddr;
-	long offset;
-	pgd_t *pgd_dir;
-	pmd_t *pmd_dir;
-	pte_t *pte_dir;
-
-	/*
-	 * Don't allow mappings that wrap..
-	 */
-	if (!size || physaddr > (unsigned long)(-size))
-		return NULL;
-
-#ifdef CONFIG_AMIGA
-	if (MACH_IS_AMIGA) {
-		if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
-		    && (cacheflag == IOMAP_NOCACHE_SER))
-			return (void __iomem *)physaddr;
-	}
-#endif
-
-#ifdef DEBUG
-	printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
-#endif
-	/*
-	 * Mappings have to be aligned
-	 */
-	offset = physaddr & (IO_SIZE - 1);
-	physaddr &= -IO_SIZE;
-	size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
-
-	/*
-	 * Ok, go for it..
-	 */
-	area = get_io_area(size);
-	if (!area)
-		return NULL;
-
-	virtaddr = (unsigned long)area->addr;
-	retaddr = virtaddr + offset;
-#ifdef DEBUG
-	printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
-#endif
-
-	/*
-	 * add cache and table flags to physical address
-	 */
-	if (CPU_IS_040_OR_060) {
-		physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
-			     _PAGE_ACCESSED | _PAGE_DIRTY);
-		switch (cacheflag) {
-		case IOMAP_FULL_CACHING:
-			physaddr |= _PAGE_CACHE040;
-			break;
-		case IOMAP_NOCACHE_SER:
-		default:
-			physaddr |= _PAGE_NOCACHE_S;
-			break;
-		case IOMAP_NOCACHE_NONSER:
-			physaddr |= _PAGE_NOCACHE;
-			break;
-		case IOMAP_WRITETHROUGH:
-			physaddr |= _PAGE_CACHE040W;
-			break;
-		}
-	} else {
-		physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
-		switch (cacheflag) {
-		case IOMAP_NOCACHE_SER:
-		case IOMAP_NOCACHE_NONSER:
-		default:
-			physaddr |= _PAGE_NOCACHE030;
-			break;
-		case IOMAP_FULL_CACHING:
-		case IOMAP_WRITETHROUGH:
-			break;
-		}
-	}
-
-	while ((long)size > 0) {
-#ifdef DEBUG
-		if (!(virtaddr & (PTRTREESIZE-1)))
-			printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
-#endif
-		pgd_dir = pgd_offset_k(virtaddr);
-		pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
-		if (!pmd_dir) {
-			printk("ioremap: no mem for pmd_dir\n");
-			return NULL;
-		}
-
-		if (CPU_IS_020_OR_030) {
-			pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
-			physaddr += PTRTREESIZE;
-			virtaddr += PTRTREESIZE;
-			size -= PTRTREESIZE;
-		} else {
-			pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
-			if (!pte_dir) {
-				printk("ioremap: no mem for pte_dir\n");
-				return NULL;
-			}
-
-			pte_val(*pte_dir) = physaddr;
-			virtaddr += PAGE_SIZE;
-			physaddr += PAGE_SIZE;
-			size -= PAGE_SIZE;
-		}
-	}
-#ifdef DEBUG
-	printk("\n");
-#endif
-	flush_tlb_all();
-
-	return (void __iomem *)retaddr;
-}
-EXPORT_SYMBOL(__ioremap);
-
-/*
- * Unmap a ioremap()ed region again
- */
-void iounmap(void __iomem *addr)
-{
-#ifdef CONFIG_AMIGA
-	if ((!MACH_IS_AMIGA) ||
-	    (((unsigned long)addr < 0x40000000) ||
-	     ((unsigned long)addr > 0x60000000)))
-			free_io_area((__force void *)addr);
+#ifdef CONFIG_MMU
+#include "kmap_mm.c"
 #else
-	free_io_area((__force void *)addr);
+#include "kmap_no.c"
 #endif
-}
-EXPORT_SYMBOL(iounmap);
-
-/*
- * __iounmap unmaps nearly everything, so be careful
- * it doesn't free currently pointer/page tables anymore but it
- * wans't used anyway and might be added later.
- */
-void __iounmap(void *addr, unsigned long size)
-{
-	unsigned long virtaddr = (unsigned long)addr;
-	pgd_t *pgd_dir;
-	pmd_t *pmd_dir;
-	pte_t *pte_dir;
-
-	while ((long)size > 0) {
-		pgd_dir = pgd_offset_k(virtaddr);
-		if (pgd_bad(*pgd_dir)) {
-			printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
-			pgd_clear(pgd_dir);
-			return;
-		}
-		pmd_dir = pmd_offset(pgd_dir, virtaddr);
-
-		if (CPU_IS_020_OR_030) {
-			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
-			int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
-
-			if (pmd_type == _PAGE_PRESENT) {
-				pmd_dir->pmd[pmd_off] = 0;
-				virtaddr += PTRTREESIZE;
-				size -= PTRTREESIZE;
-				continue;
-			} else if (pmd_type == 0)
-				continue;
-		}
-
-		if (pmd_bad(*pmd_dir)) {
-			printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
-			pmd_clear(pmd_dir);
-			return;
-		}
-		pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
-
-		pte_val(*pte_dir) = 0;
-		virtaddr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	flush_tlb_all();
-}
-
-/*
- * Set new cache mode for some kernel address space.
- * The caller must push data for that range itself, if such data may already
- * be in the cache.
- */
-void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
-{
-	unsigned long virtaddr = (unsigned long)addr;
-	pgd_t *pgd_dir;
-	pmd_t *pmd_dir;
-	pte_t *pte_dir;
-
-	if (CPU_IS_040_OR_060) {
-		switch (cmode) {
-		case IOMAP_FULL_CACHING:
-			cmode = _PAGE_CACHE040;
-			break;
-		case IOMAP_NOCACHE_SER:
-		default:
-			cmode = _PAGE_NOCACHE_S;
-			break;
-		case IOMAP_NOCACHE_NONSER:
-			cmode = _PAGE_NOCACHE;
-			break;
-		case IOMAP_WRITETHROUGH:
-			cmode = _PAGE_CACHE040W;
-			break;
-		}
-	} else {
-		switch (cmode) {
-		case IOMAP_NOCACHE_SER:
-		case IOMAP_NOCACHE_NONSER:
-		default:
-			cmode = _PAGE_NOCACHE030;
-			break;
-		case IOMAP_FULL_CACHING:
-		case IOMAP_WRITETHROUGH:
-			cmode = 0;
-		}
-	}
-
-	while ((long)size > 0) {
-		pgd_dir = pgd_offset_k(virtaddr);
-		if (pgd_bad(*pgd_dir)) {
-			printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
-			pgd_clear(pgd_dir);
-			return;
-		}
-		pmd_dir = pmd_offset(pgd_dir, virtaddr);
-
-		if (CPU_IS_020_OR_030) {
-			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
-
-			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
-				pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
-							 _CACHEMASK040) | cmode;
-				virtaddr += PTRTREESIZE;
-				size -= PTRTREESIZE;
-				continue;
-			}
-		}
-
-		if (pmd_bad(*pmd_dir)) {
-			printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
-			pmd_clear(pmd_dir);
-			return;
-		}
-		pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
-
-		pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
-		virtaddr += PAGE_SIZE;
-		size -= PAGE_SIZE;
-	}
-
-	flush_tlb_all();
-}
-EXPORT_SYMBOL(kernel_set_cachemode);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/kmap_mm.c linux-libre-2.6.39-gnu/arch/m68k/mm/kmap_mm.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/kmap_mm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/kmap_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,367 @@
+/*
+ *  linux/arch/m68k/mm/kmap.c
+ *
+ *  Copyright (C) 1997 Roman Hodek
+ *
+ *  10/01/99 cleaned up the code and changing to the same interface
+ *	     used by other architectures		/Roman Zippel
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#undef DEBUG
+
+#define PTRTREESIZE	(256*1024)
+
+/*
+ * For 040/060 we can use the virtual memory area like other architectures,
+ * but for 020/030 we want to use early termination page descriptor and we
+ * can't mix this with normal page descriptors, so we have to copy that code
+ * (mm/vmalloc.c) and return appriorate aligned addresses.
+ */
+
+#ifdef CPU_M68040_OR_M68060_ONLY
+
+#define IO_SIZE		PAGE_SIZE
+
+static inline struct vm_struct *get_io_area(unsigned long size)
+{
+	return get_vm_area(size, VM_IOREMAP);
+}
+
+
+static inline void free_io_area(void *addr)
+{
+	vfree((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+#else
+
+#define IO_SIZE		(256*1024)
+
+static struct vm_struct *iolist;
+
+static struct vm_struct *get_io_area(unsigned long size)
+{
+	unsigned long addr;
+	struct vm_struct **p, *tmp, *area;
+
+	area = kmalloc(sizeof(*area), GFP_KERNEL);
+	if (!area)
+		return NULL;
+	addr = KMAP_START;
+	for (p = &iolist; (tmp = *p) ; p = &tmp->next) {
+		if (size + addr < (unsigned long)tmp->addr)
+			break;
+		if (addr > KMAP_END-size) {
+			kfree(area);
+			return NULL;
+		}
+		addr = tmp->size + (unsigned long)tmp->addr;
+	}
+	area->addr = (void *)addr;
+	area->size = size + IO_SIZE;
+	area->next = *p;
+	*p = area;
+	return area;
+}
+
+static inline void free_io_area(void *addr)
+{
+	struct vm_struct **p, *tmp;
+
+	if (!addr)
+		return;
+	addr = (void *)((unsigned long)addr & -IO_SIZE);
+	for (p = &iolist ; (tmp = *p) ; p = &tmp->next) {
+		if (tmp->addr == addr) {
+			*p = tmp->next;
+			__iounmap(tmp->addr, tmp->size);
+			kfree(tmp);
+			return;
+		}
+	}
+}
+
+#endif
+
+/*
+ * Map some physical address range into the kernel address space.
+ */
+/* Rewritten by Andreas Schwab to remove all races. */
+
+void __iomem *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
+{
+	struct vm_struct *area;
+	unsigned long virtaddr, retaddr;
+	long offset;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
+
+	/*
+	 * Don't allow mappings that wrap..
+	 */
+	if (!size || physaddr > (unsigned long)(-size))
+		return NULL;
+
+#ifdef CONFIG_AMIGA
+	if (MACH_IS_AMIGA) {
+		if ((physaddr >= 0x40000000) && (physaddr + size < 0x60000000)
+		    && (cacheflag == IOMAP_NOCACHE_SER))
+			return (void __iomem *)physaddr;
+	}
+#endif
+
+#ifdef DEBUG
+	printk("ioremap: 0x%lx,0x%lx(%d) - ", physaddr, size, cacheflag);
+#endif
+	/*
+	 * Mappings have to be aligned
+	 */
+	offset = physaddr & (IO_SIZE - 1);
+	physaddr &= -IO_SIZE;
+	size = (size + offset + IO_SIZE - 1) & -IO_SIZE;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_io_area(size);
+	if (!area)
+		return NULL;
+
+	virtaddr = (unsigned long)area->addr;
+	retaddr = virtaddr + offset;
+#ifdef DEBUG
+	printk("0x%lx,0x%lx,0x%lx", physaddr, virtaddr, retaddr);
+#endif
+
+	/*
+	 * add cache and table flags to physical address
+	 */
+	if (CPU_IS_040_OR_060) {
+		physaddr |= (_PAGE_PRESENT | _PAGE_GLOBAL040 |
+			     _PAGE_ACCESSED | _PAGE_DIRTY);
+		switch (cacheflag) {
+		case IOMAP_FULL_CACHING:
+			physaddr |= _PAGE_CACHE040;
+			break;
+		case IOMAP_NOCACHE_SER:
+		default:
+			physaddr |= _PAGE_NOCACHE_S;
+			break;
+		case IOMAP_NOCACHE_NONSER:
+			physaddr |= _PAGE_NOCACHE;
+			break;
+		case IOMAP_WRITETHROUGH:
+			physaddr |= _PAGE_CACHE040W;
+			break;
+		}
+	} else {
+		physaddr |= (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_DIRTY);
+		switch (cacheflag) {
+		case IOMAP_NOCACHE_SER:
+		case IOMAP_NOCACHE_NONSER:
+		default:
+			physaddr |= _PAGE_NOCACHE030;
+			break;
+		case IOMAP_FULL_CACHING:
+		case IOMAP_WRITETHROUGH:
+			break;
+		}
+	}
+
+	while ((long)size > 0) {
+#ifdef DEBUG
+		if (!(virtaddr & (PTRTREESIZE-1)))
+			printk ("\npa=%#lx va=%#lx ", physaddr, virtaddr);
+#endif
+		pgd_dir = pgd_offset_k(virtaddr);
+		pmd_dir = pmd_alloc(&init_mm, pgd_dir, virtaddr);
+		if (!pmd_dir) {
+			printk("ioremap: no mem for pmd_dir\n");
+			return NULL;
+		}
+
+		if (CPU_IS_020_OR_030) {
+			pmd_dir->pmd[(virtaddr/PTRTREESIZE) & 15] = physaddr;
+			physaddr += PTRTREESIZE;
+			virtaddr += PTRTREESIZE;
+			size -= PTRTREESIZE;
+		} else {
+			pte_dir = pte_alloc_kernel(pmd_dir, virtaddr);
+			if (!pte_dir) {
+				printk("ioremap: no mem for pte_dir\n");
+				return NULL;
+			}
+
+			pte_val(*pte_dir) = physaddr;
+			virtaddr += PAGE_SIZE;
+			physaddr += PAGE_SIZE;
+			size -= PAGE_SIZE;
+		}
+	}
+#ifdef DEBUG
+	printk("\n");
+#endif
+	flush_tlb_all();
+
+	return (void __iomem *)retaddr;
+}
+EXPORT_SYMBOL(__ioremap);
+
+/*
+ * Unmap a ioremap()ed region again
+ */
+void iounmap(void __iomem *addr)
+{
+#ifdef CONFIG_AMIGA
+	if ((!MACH_IS_AMIGA) ||
+	    (((unsigned long)addr < 0x40000000) ||
+	     ((unsigned long)addr > 0x60000000)))
+			free_io_area((__force void *)addr);
+#else
+	free_io_area((__force void *)addr);
+#endif
+}
+EXPORT_SYMBOL(iounmap);
+
+/*
+ * __iounmap unmaps nearly everything, so be careful
+ * it doesn't free currently pointer/page tables anymore but it
+ * wans't used anyway and might be added later.
+ */
+void __iounmap(void *addr, unsigned long size)
+{
+	unsigned long virtaddr = (unsigned long)addr;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
+
+	while ((long)size > 0) {
+		pgd_dir = pgd_offset_k(virtaddr);
+		if (pgd_bad(*pgd_dir)) {
+			printk("iounmap: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
+			pgd_clear(pgd_dir);
+			return;
+		}
+		pmd_dir = pmd_offset(pgd_dir, virtaddr);
+
+		if (CPU_IS_020_OR_030) {
+			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
+			int pmd_type = pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK;
+
+			if (pmd_type == _PAGE_PRESENT) {
+				pmd_dir->pmd[pmd_off] = 0;
+				virtaddr += PTRTREESIZE;
+				size -= PTRTREESIZE;
+				continue;
+			} else if (pmd_type == 0)
+				continue;
+		}
+
+		if (pmd_bad(*pmd_dir)) {
+			printk("iounmap: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
+			pmd_clear(pmd_dir);
+			return;
+		}
+		pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
+
+		pte_val(*pte_dir) = 0;
+		virtaddr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	flush_tlb_all();
+}
+
+/*
+ * Set new cache mode for some kernel address space.
+ * The caller must push data for that range itself, if such data may already
+ * be in the cache.
+ */
+void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
+{
+	unsigned long virtaddr = (unsigned long)addr;
+	pgd_t *pgd_dir;
+	pmd_t *pmd_dir;
+	pte_t *pte_dir;
+
+	if (CPU_IS_040_OR_060) {
+		switch (cmode) {
+		case IOMAP_FULL_CACHING:
+			cmode = _PAGE_CACHE040;
+			break;
+		case IOMAP_NOCACHE_SER:
+		default:
+			cmode = _PAGE_NOCACHE_S;
+			break;
+		case IOMAP_NOCACHE_NONSER:
+			cmode = _PAGE_NOCACHE;
+			break;
+		case IOMAP_WRITETHROUGH:
+			cmode = _PAGE_CACHE040W;
+			break;
+		}
+	} else {
+		switch (cmode) {
+		case IOMAP_NOCACHE_SER:
+		case IOMAP_NOCACHE_NONSER:
+		default:
+			cmode = _PAGE_NOCACHE030;
+			break;
+		case IOMAP_FULL_CACHING:
+		case IOMAP_WRITETHROUGH:
+			cmode = 0;
+		}
+	}
+
+	while ((long)size > 0) {
+		pgd_dir = pgd_offset_k(virtaddr);
+		if (pgd_bad(*pgd_dir)) {
+			printk("iocachemode: bad pgd(%08lx)\n", pgd_val(*pgd_dir));
+			pgd_clear(pgd_dir);
+			return;
+		}
+		pmd_dir = pmd_offset(pgd_dir, virtaddr);
+
+		if (CPU_IS_020_OR_030) {
+			int pmd_off = (virtaddr/PTRTREESIZE) & 15;
+
+			if ((pmd_dir->pmd[pmd_off] & _DESCTYPE_MASK) == _PAGE_PRESENT) {
+				pmd_dir->pmd[pmd_off] = (pmd_dir->pmd[pmd_off] &
+							 _CACHEMASK040) | cmode;
+				virtaddr += PTRTREESIZE;
+				size -= PTRTREESIZE;
+				continue;
+			}
+		}
+
+		if (pmd_bad(*pmd_dir)) {
+			printk("iocachemode: bad pmd (%08lx)\n", pmd_val(*pmd_dir));
+			pmd_clear(pmd_dir);
+			return;
+		}
+		pte_dir = pte_offset_kernel(pmd_dir, virtaddr);
+
+		pte_val(*pte_dir) = (pte_val(*pte_dir) & _CACHEMASK040) | cmode;
+		virtaddr += PAGE_SIZE;
+		size -= PAGE_SIZE;
+	}
+
+	flush_tlb_all();
+}
+EXPORT_SYMBOL(kernel_set_cachemode);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/kmap_no.c linux-libre-2.6.39-gnu/arch/m68k/mm/kmap_no.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/kmap_no.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/kmap_no.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ *  linux/arch/m68knommu/mm/kmap.c
+ *
+ *  Copyright (C) 2000 Lineo, <davidm@snapgear.com>
+ *  Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
+ */
+
+#include <linux/mm.h>
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/vmalloc.h>
+
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+#include <asm/pgalloc.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+#undef DEBUG
+
+/*
+ * Map some physical address range into the kernel address space.
+ */
+void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
+{
+	return (void *)physaddr;
+}
+
+/*
+ * Unmap a ioremap()ed region again.
+ */
+void iounmap(void *addr)
+{
+}
+
+/*
+ * Set new cache mode for some kernel address space.
+ * The caller must push data for that range itself, if such data may already
+ * be in the cache.
+ */
+void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
+{
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/Makefile linux-libre-2.6.39-gnu/arch/m68k/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,5 @@
-#
-# Makefile for the linux m68k-specific parts of the memory manager.
-#
-
-obj-y		:= cache.o init.o fault.o hwtest.o
-
-obj-$(CONFIG_MMU_MOTOROLA)	+= kmap.o memory.o motorola.o
-obj-$(CONFIG_MMU_SUN3)		+= sun3kmap.o sun3mmu.o
+ifdef CONFIG_MMU
+include arch/m68k/mm/Makefile_mm
+else
+include arch/m68k/mm/Makefile_no
+endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/Makefile_mm linux-libre-2.6.39-gnu/arch/m68k/mm/Makefile_mm
--- linux-libre-2.6.38-gnu/arch/m68k/mm/Makefile_mm	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/Makefile_mm	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,8 @@
+#
+# Makefile for the linux m68k-specific parts of the memory manager.
+#
+
+obj-y		:= cache.o init.o fault.o hwtest.o
+
+obj-$(CONFIG_MMU_MOTOROLA)	+= kmap.o memory.o motorola.o
+obj-$(CONFIG_MMU_SUN3)		+= sun3kmap.o sun3mmu.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/Makefile_no linux-libre-2.6.39-gnu/arch/m68k/mm/Makefile_no
--- linux-libre-2.6.38-gnu/arch/m68k/mm/Makefile_no	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/Makefile_no	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,5 @@
+#
+# Makefile for the linux m68knommu specific parts of the memory manager.
+#
+
+obj-y += init.o kmap.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mm/motorola.c linux-libre-2.6.39-gnu/arch/m68k/mm/motorola.c
--- linux-libre-2.6.38-gnu/arch/m68k/mm/motorola.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mm/motorola.c	2011-05-19 00:06:34.000000000 -0400
@@ -300,6 +300,8 @@
 		zones_size[ZONE_DMA] = m68k_memory[i].size >> PAGE_SHIFT;
 		free_area_init_node(i, zones_size,
 				    m68k_memory[i].addr >> PAGE_SHIFT, NULL);
+		if (node_present_pages(i))
+			node_set_state(i, N_NORMAL_MEMORY);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mvme147/config.c linux-libre-2.6.39-gnu/arch/m68k/mvme147/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/mvme147/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mvme147/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,8 +46,8 @@
 
 static int bcd2int (unsigned char b);
 
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c, called via mvme147_process_int() */
+/* Save tick handler routine pointer, will point to xtime_update() in
+ * kernel/time/timekeeping.c, called via mvme147_process_int() */
 
 irq_handler_t tick_handler;
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/mvme16x/config.c linux-libre-2.6.39-gnu/arch/m68k/mvme16x/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/mvme16x/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/mvme16x/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,8 +51,8 @@
 
 int bcd2int (unsigned char b);
 
-/* Save tick handler routine pointer, will point to do_timer() in
- * kernel/sched.c, called via mvme16x_process_int() */
+/* Save tick handler routine pointer, will point to xtime_update() in
+ * kernel/time/timekeeping.c, called via mvme16x_process_int() */
 
 static irq_handler_t tick_handler;
 
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5206/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/5206/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5206/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5206/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,121 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5206/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ * 	Copyright (C) 2000-2001, Lineo Inc. (www.lineo.com) 
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m5206_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 73,
+	},
+	{
+		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 74,
+	},
+	{ },
+};
+
+static struct platform_device m5206_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m5206_uart_platform,
+};
+
+static struct platform_device *m5206_devices[] __initdata = {
+	&m5206_uart,
+};
+
+/***************************************************************************/
+
+static void __init m5206_uart_init_line(int line, int irq)
+{
+	if (line == 0) {
+		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
+		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
+	} else if (line == 1) {
+		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
+		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
+	}
+}
+
+static void __init m5206_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m5206_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m5206_uart_init_line(line, m5206_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m5206_timers_init(void)
+{
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
+
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
+}
+
+/***************************************************************************/
+
+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)
+{
+	mach_reset = m5206_cpu_reset;
+	m5206_timers_init();
+	m5206_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(28, MCFINTC_EINT4);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m5206_devices, ARRAY_SIZE(m5206_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5206/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/5206/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5206/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5206/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5206/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/5206/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5206/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5206/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5206e/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/5206e/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5206e/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5206e/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,127 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5206e/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfdma.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m5206e_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 73,
+	},
+	{
+		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 74,
+	},
+	{ },
+};
+
+static struct platform_device m5206e_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m5206e_uart_platform,
+};
+
+static struct platform_device *m5206e_devices[] __initdata = {
+	&m5206e_uart,
+};
+
+/***************************************************************************/
+
+static void __init m5206e_uart_init_line(int line, int irq)
+{
+	if (line == 0) {
+		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
+		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
+	} else if (line == 1) {
+		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
+		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
+	}
+}
+
+static void __init m5206e_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m5206e_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m5206e_uart_init_line(line, m5206e_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m5206e_timers_init(void)
+{
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
+
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
+}
+
+/***************************************************************************/
+
+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)
+{
+#if defined(CONFIG_NETtel)
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0xf0004000, size);
+	commandp[size-1] = 0;
+#endif /* CONFIG_NETtel */
+
+	mach_reset = m5206e_cpu_reset;
+	m5206e_timers_init();
+	m5206e_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(28, MCFINTC_EINT4);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m5206e_devices, ARRAY_SIZE(m5206e_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5206e/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/5206e/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5206e/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5206e/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5206e/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/5206e/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5206e/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5206e/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/520x/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/520x/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/520x/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/520x/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,311 @@
+/***************************************************************************/
+
+/*
+ *  linux/arch/m68knommu/platform/520x/config.c
+ *
+ *  Copyright (C) 2005,      Freescale (www.freescale.com)
+ *  Copyright (C) 2005,      Intec Automation (mike@steroidmicros.com)
+ *  Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m520x_uart_platform[] = {
+	{
+		.mapbase	= MCFUART_BASE1,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0,
+	},
+	{
+		.mapbase 	= MCFUART_BASE2,
+		.irq		= MCFINT_VECBASE + MCFINT_UART1,
+	},
+	{
+		.mapbase 	= MCFUART_BASE3,
+		.irq		= MCFINT_VECBASE + MCFINT_UART2,
+	},
+	{ },
+};
+
+static struct platform_device m520x_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m520x_uart_platform,
+};
+
+static struct resource m520x_fec_resources[] = {
+	{
+		.start		= MCFFEC_BASE,
+		.end		= MCFFEC_BASE + MCFFEC_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= 64 + 36,
+		.end		= 64 + 36,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 40,
+		.end		= 64 + 40,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 42,
+		.end		= 64 + 42,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m520x_fec = {
+	.name			= "fec",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m520x_fec_resources),
+	.resource		= m520x_fec_resources,
+};
+
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m520x_qspi_resources[] = {
+	{
+		.start		= MCFQSPI_IOBASE,
+		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCFINT_VECBASE + MCFINT_QSPI,
+		.end		= MCFINT_VECBASE + MCFINT_QSPI,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+#define MCFQSPI_CS0    62
+#define MCFQSPI_CS1    63
+#define MCFQSPI_CS2    44
+
+static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+	int status;
+
+	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+		goto fail0;
+	}
+	status = gpio_direction_output(MCFQSPI_CS0, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+		goto fail1;
+	}
+
+	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+		goto fail1;
+	}
+	status = gpio_direction_output(MCFQSPI_CS1, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+		goto fail2;
+	}
+
+	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+		goto fail2;
+	}
+	status = gpio_direction_output(MCFQSPI_CS2, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+		goto fail3;
+	}
+
+	return 0;
+
+fail3:
+	gpio_free(MCFQSPI_CS2);
+fail2:
+	gpio_free(MCFQSPI_CS1);
+fail1:
+	gpio_free(MCFQSPI_CS0);
+fail0:
+	return status;
+}
+
+static void m520x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+	gpio_free(MCFQSPI_CS2);
+	gpio_free(MCFQSPI_CS1);
+	gpio_free(MCFQSPI_CS0);
+}
+
+static void m520x_cs_select(struct mcfqspi_cs_control *cs_control,
+			    u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, cs_high);
+		break;
+	}
+}
+
+static void m520x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+			      u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, !cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, !cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, !cs_high);
+		break;
+	}
+}
+
+static struct mcfqspi_cs_control m520x_cs_control = {
+	.setup                  = m520x_cs_setup,
+	.teardown               = m520x_cs_teardown,
+	.select                 = m520x_cs_select,
+	.deselect               = m520x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m520x_qspi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 3,
+	.cs_control		= &m520x_cs_control,
+};
+
+static struct platform_device m520x_qspi = {
+	.name			= "mcfqspi",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m520x_qspi_resources),
+	.resource		= m520x_qspi_resources,
+	.dev.platform_data	= &m520x_qspi_data,
+};
+
+static void __init m520x_qspi_init(void)
+{
+	u16 par;
+	/* setup Port QS for QSPI with gpio CS control */
+	writeb(0x3f, MCF_GPIO_PAR_QSPI);
+	/* make U1CTS and U2RTS gpio for cs_control */
+	par = readw(MCF_GPIO_PAR_UART);
+	par &= 0x00ff;
+	writew(par, MCF_GPIO_PAR_UART);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+
+static struct platform_device *m520x_devices[] __initdata = {
+	&m520x_uart,
+	&m520x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	&m520x_qspi,
+#endif
+};
+
+/***************************************************************************/
+
+static void __init m520x_uart_init_line(int line, int irq)
+{
+	u16 par;
+	u8 par2;
+
+	switch (line) {
+	case 0:
+		par = readw(MCF_GPIO_PAR_UART);
+		par |= MCF_GPIO_PAR_UART_PAR_UTXD0 |
+		       MCF_GPIO_PAR_UART_PAR_URXD0;
+		writew(par, MCF_GPIO_PAR_UART);
+		break;
+	case 1:
+		par = readw(MCF_GPIO_PAR_UART);
+		par |= MCF_GPIO_PAR_UART_PAR_UTXD1 |
+		       MCF_GPIO_PAR_UART_PAR_URXD1;
+		writew(par, MCF_GPIO_PAR_UART);
+		break;
+	case 2:
+		par2 = readb(MCF_GPIO_PAR_FECI2C);
+		par2 &= ~0x0F;
+		par2 |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 |
+			MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
+		writeb(par2, MCF_GPIO_PAR_FECI2C);
+		break;
+	}
+}
+
+static void __init m520x_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m520x_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m520x_uart_init_line(line, m520x_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m520x_fec_init(void)
+{
+	u8 v;
+
+	/* Set multi-function pins to ethernet mode */
+	v = readb(MCF_GPIO_PAR_FEC);
+	writeb(v | 0xf0, MCF_GPIO_PAR_FEC);
+
+	v = readb(MCF_GPIO_PAR_FECI2C);
+	writeb(v | 0x0f, MCF_GPIO_PAR_FECI2C);
+}
+
+/***************************************************************************/
+
+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 = m520x_cpu_reset;
+	m520x_uarts_init();
+	m520x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	m520x_qspi_init();
+#endif
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m520x_devices, ARRAY_SIZE(m520x_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/520x/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/520x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/520x/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/520x/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BE",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BE,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BE,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BE,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 25,
+			.ngpio			= 3,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 48,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UART",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UART,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UART,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECL,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/520x/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/520x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/520x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/520x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+#
+# Makefile for the M5208 specific file.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/523x/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/523x/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/523x/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/523x/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,293 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/523x/config.c
+ *
+ *	Sub-architcture dependent initialization code for the Freescale
+ *	523x CPUs.
+ *
+ *	Copyright (C) 1999-2005, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m523x_uart_platform[] = {
+	{
+		.mapbase	= MCFUART_BASE1,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0,
+	},
+	{
+		.mapbase 	= MCFUART_BASE2,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 1,
+	},
+	{
+		.mapbase 	= MCFUART_BASE3,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 2,
+	},
+	{ },
+};
+
+static struct platform_device m523x_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m523x_uart_platform,
+};
+
+static struct resource m523x_fec_resources[] = {
+	{
+		.start		= MCFFEC_BASE,
+		.end		= MCFFEC_BASE + MCFFEC_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= 64 + 23,
+		.end		= 64 + 23,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 27,
+		.end		= 64 + 27,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 29,
+		.end		= 64 + 29,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m523x_fec = {
+	.name			= "fec",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m523x_fec_resources),
+	.resource		= m523x_fec_resources,
+};
+
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m523x_qspi_resources[] = {
+	{
+		.start		= MCFQSPI_IOBASE,
+		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCFINT_VECBASE + MCFINT_QSPI,
+		.end		= MCFINT_VECBASE + MCFINT_QSPI,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+#define MCFQSPI_CS0    91
+#define MCFQSPI_CS1    92
+#define MCFQSPI_CS2    103
+#define MCFQSPI_CS3    99
+
+static int m523x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+	int status;
+
+	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+		goto fail0;
+	}
+	status = gpio_direction_output(MCFQSPI_CS0, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+		goto fail1;
+	}
+
+	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+		goto fail1;
+	}
+	status = gpio_direction_output(MCFQSPI_CS1, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+		goto fail2;
+	}
+
+	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+		goto fail2;
+	}
+	status = gpio_direction_output(MCFQSPI_CS2, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+		goto fail3;
+	}
+
+	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+		goto fail3;
+	}
+	status = gpio_direction_output(MCFQSPI_CS3, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+		goto fail4;
+	}
+
+	return 0;
+
+fail4:
+	gpio_free(MCFQSPI_CS3);
+fail3:
+	gpio_free(MCFQSPI_CS2);
+fail2:
+	gpio_free(MCFQSPI_CS1);
+fail1:
+	gpio_free(MCFQSPI_CS0);
+fail0:
+	return status;
+}
+
+static void m523x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+	gpio_free(MCFQSPI_CS3);
+	gpio_free(MCFQSPI_CS2);
+	gpio_free(MCFQSPI_CS1);
+	gpio_free(MCFQSPI_CS0);
+}
+
+static void m523x_cs_select(struct mcfqspi_cs_control *cs_control,
+			    u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, cs_high);
+		break;
+	case 3:
+		gpio_set_value(MCFQSPI_CS3, cs_high);
+		break;
+	}
+}
+
+static void m523x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+			      u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, !cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, !cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, !cs_high);
+		break;
+	case 3:
+		gpio_set_value(MCFQSPI_CS3, !cs_high);
+		break;
+	}
+}
+
+static struct mcfqspi_cs_control m523x_cs_control = {
+	.setup                  = m523x_cs_setup,
+	.teardown               = m523x_cs_teardown,
+	.select                 = m523x_cs_select,
+	.deselect               = m523x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m523x_qspi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 4,
+	.cs_control		= &m523x_cs_control,
+};
+
+static struct platform_device m523x_qspi = {
+	.name			= "mcfqspi",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m523x_qspi_resources),
+	.resource		= m523x_qspi_resources,
+	.dev.platform_data	= &m523x_qspi_data,
+};
+
+static void __init m523x_qspi_init(void)
+{
+	u16 par;
+
+	/* setup QSPS pins for QSPI with gpio CS control */
+	writeb(0x1f, MCFGPIO_PAR_QSPI);
+	/* and CS2 & CS3 as gpio */
+	par = readw(MCFGPIO_PAR_TIMER);
+	par &= 0x3f3f;
+	writew(par, MCFGPIO_PAR_TIMER);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+static struct platform_device *m523x_devices[] __initdata = {
+	&m523x_uart,
+	&m523x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	&m523x_qspi,
+#endif
+};
+
+/***************************************************************************/
+
+static void __init m523x_fec_init(void)
+{
+	u16 par;
+	u8 v;
+
+	/* Set multi-function pins to ethernet use */
+	par = readw(MCF_IPSBAR + 0x100082);
+	writew(par | 0xf00, MCF_IPSBAR + 0x100082);
+	v = readb(MCF_IPSBAR + 0x100078);
+	writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
+}
+
+/***************************************************************************/
+
+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)
+{
+	mach_reset = m523x_cpu_reset;
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	m523x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	m523x_qspi_init();
+#endif
+	platform_add_devices(m523x_devices, ARRAY_SIZE(m523x_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/523x/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/523x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/523x/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/523x/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,284 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 1,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ADDR",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 13,
+			.ngpio			= 3,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ADDR,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ADDR,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ADDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 49,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SDRAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 6,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SDRAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SDRAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SDRAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 2,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 5,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ETPU",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 3,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ETPU,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ETPU,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ETPU,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ETPU,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ETPU,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/523x/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/523x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/523x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/523x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5249/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/5249/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5249/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5249/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,330 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5249/config.c
+ *
+ *	Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m5249_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 73,
+	},
+	{
+		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 74,
+	},
+	{ },
+};
+
+static struct platform_device m5249_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m5249_uart_platform,
+};
+
+#ifdef CONFIG_M5249C3
+
+static struct resource m5249_smc91x_resources[] = {
+	{
+		.start		= 0xe0000300,
+		.end		= 0xe0000300 + 0x100,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCFINTC2_GPIOIRQ6,
+		.end		= MCFINTC2_GPIOIRQ6,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m5249_smc91x = {
+	.name			= "smc91x",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m5249_smc91x_resources),
+	.resource		= m5249_smc91x_resources,
+};
+
+#endif /* CONFIG_M5249C3 */
+
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m5249_qspi_resources[] = {
+	{
+		.start		= MCFQSPI_IOBASE,
+		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCF_IRQ_QSPI,
+		.end		= MCF_IRQ_QSPI,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+#define MCFQSPI_CS0    29
+#define MCFQSPI_CS1    24
+#define MCFQSPI_CS2    21
+#define MCFQSPI_CS3    22
+
+static int m5249_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+	int status;
+
+	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+		goto fail0;
+	}
+	status = gpio_direction_output(MCFQSPI_CS0, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+		goto fail1;
+	}
+
+	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+		goto fail1;
+	}
+	status = gpio_direction_output(MCFQSPI_CS1, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+		goto fail2;
+	}
+
+	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+		goto fail2;
+	}
+	status = gpio_direction_output(MCFQSPI_CS2, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+		goto fail3;
+	}
+
+	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+		goto fail3;
+	}
+	status = gpio_direction_output(MCFQSPI_CS3, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+		goto fail4;
+	}
+
+	return 0;
+
+fail4:
+	gpio_free(MCFQSPI_CS3);
+fail3:
+	gpio_free(MCFQSPI_CS2);
+fail2:
+	gpio_free(MCFQSPI_CS1);
+fail1:
+	gpio_free(MCFQSPI_CS0);
+fail0:
+	return status;
+}
+
+static void m5249_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+	gpio_free(MCFQSPI_CS3);
+	gpio_free(MCFQSPI_CS2);
+	gpio_free(MCFQSPI_CS1);
+	gpio_free(MCFQSPI_CS0);
+}
+
+static void m5249_cs_select(struct mcfqspi_cs_control *cs_control,
+			    u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, cs_high);
+		break;
+	case 3:
+		gpio_set_value(MCFQSPI_CS3, cs_high);
+		break;
+	}
+}
+
+static void m5249_cs_deselect(struct mcfqspi_cs_control *cs_control,
+			      u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, !cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, !cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, !cs_high);
+		break;
+	case 3:
+		gpio_set_value(MCFQSPI_CS3, !cs_high);
+		break;
+	}
+}
+
+static struct mcfqspi_cs_control m5249_cs_control = {
+	.setup                  = m5249_cs_setup,
+	.teardown               = m5249_cs_teardown,
+	.select                 = m5249_cs_select,
+	.deselect               = m5249_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m5249_qspi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 4,
+	.cs_control		= &m5249_cs_control,
+};
+
+static struct platform_device m5249_qspi = {
+	.name			= "mcfqspi",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m5249_qspi_resources),
+	.resource		= m5249_qspi_resources,
+	.dev.platform_data	= &m5249_qspi_data,
+};
+
+static void __init m5249_qspi_init(void)
+{
+	/* QSPI irq setup */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI0,
+	       MCF_MBAR + MCFSIM_QSPIICR);
+	mcf_mapirq2imr(MCF_IRQ_QSPI, MCFINTC_QSPI);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+
+static struct platform_device *m5249_devices[] __initdata = {
+	&m5249_uart,
+#ifdef CONFIG_M5249C3
+	&m5249_smc91x,
+#endif
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	&m5249_qspi,
+#endif
+};
+
+/***************************************************************************/
+
+static void __init m5249_uart_init_line(int line, int irq)
+{
+	if (line == 0) {
+		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
+		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
+	} else if (line == 1) {
+		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
+		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
+	}
+}
+
+static void __init m5249_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m5249_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m5249_uart_init_line(line, m5249_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+#ifdef CONFIG_M5249C3
+
+static void __init m5249_smc91x_init(void)
+{
+	u32  gpio;
+
+	/* Set the GPIO line as interrupt source for smc91x device */
+	gpio = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+	writel(gpio | 0x40, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+
+	gpio = readl(MCF_MBAR2 + MCFSIM2_INTLEVEL5);
+	writel(gpio | 0x04000000, MCF_MBAR2 + MCFSIM2_INTLEVEL5);
+}
+
+#endif /* CONFIG_M5249C3 */
+
+/***************************************************************************/
+
+static void __init m5249_timers_init(void)
+{
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
+
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
+}
+
+/***************************************************************************/
+
+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)
+{
+	mach_reset = m5249_cpu_reset;
+	m5249_timers_init();
+	m5249_uarts_init();
+#ifdef CONFIG_M5249C3
+	m5249_smc91x_init();
+#endif
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	m5249_qspi_init();
+#endif
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m5249_devices, ARRAY_SIZE(m5249_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5249/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/5249/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5249/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5249/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,65 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "GPIO0",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 32,
+		},
+		.pddr				= (void __iomem *) MCFSIM2_GPIOENABLE,
+		.podr				= (void __iomem *) MCFSIM2_GPIOWRITE,
+		.ppdr				= (void __iomem *) MCFSIM2_GPIOREAD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "GPIO1",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 32,
+			.ngpio			= 32,
+		},
+		.pddr				= (void __iomem *) MCFSIM2_GPIO1ENABLE,
+		.podr				= (void __iomem *) MCFSIM2_GPIO1WRITE,
+		.ppdr				= (void __iomem *) MCFSIM2_GPIO1READ,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5249/intc2.c linux-libre-2.6.39-gnu/arch/m68k/platform/5249/intc2.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5249/intc2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5249/intc2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * intc2.c  -- support for the 2nd INTC controller of the 5249
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+static void intc2_irq_gpio_mask(struct irq_data *d)
+{
+	u32 imr;
+	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+	imr &= ~(0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
+	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+}
+
+static void intc2_irq_gpio_unmask(struct irq_data *d)
+{
+	u32 imr;
+	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+	imr |= (0x1 << (d->irq - MCFINTC2_GPIOIRQ0));
+	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
+}
+
+static void intc2_irq_gpio_ack(struct irq_data *d)
+{
+	writel(0x1 << (d->irq - MCFINTC2_GPIOIRQ0), MCF_MBAR2 + MCFSIM2_GPIOINTCLEAR);
+}
+
+static struct irq_chip intc2_irq_gpio_chip = {
+	.name		= "CF-INTC2",
+	.irq_mask	= intc2_irq_gpio_mask,
+	.irq_unmask	= intc2_irq_gpio_unmask,
+	.irq_ack	= intc2_irq_gpio_ack,
+};
+
+static int __init mcf_intc2_init(void)
+{
+	int irq;
+
+	/* GPIO interrupt sources */
+	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) {
+		irq_set_chip(irq, &intc2_irq_gpio_chip);
+		irq_set_handler(irq, handle_edge_irq);
+	}
+
+	return 0;
+}
+
+arch_initcall(mcf_intc2_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5249/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/5249/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5249/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5249/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o intc2.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5272/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/5272/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5272/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5272/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,176 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5272/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2002, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/phy.h>
+#include <linux/phy_fixed.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+
+/***************************************************************************/
+
+/*
+ *	Some platforms need software versions of the GPIO data registers.
+ */
+unsigned short ppdata;
+unsigned char ledbank = 0xff;
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m5272_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= MCF_IRQ_UART1,
+	},
+	{
+		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= MCF_IRQ_UART2,
+	},
+	{ },
+};
+
+static struct platform_device m5272_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m5272_uart_platform,
+};
+
+static struct resource m5272_fec_resources[] = {
+	{
+		.start		= MCF_MBAR + 0x840,
+		.end		= MCF_MBAR + 0x840 + 0x1cf,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCF_IRQ_ERX,
+		.end		= MCF_IRQ_ERX,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= MCF_IRQ_ETX,
+		.end		= MCF_IRQ_ETX,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= MCF_IRQ_ENTC,
+		.end		= MCF_IRQ_ENTC,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m5272_fec = {
+	.name			= "fec",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m5272_fec_resources),
+	.resource		= m5272_fec_resources,
+};
+
+static struct platform_device *m5272_devices[] __initdata = {
+	&m5272_uart,
+	&m5272_fec,
+};
+
+/***************************************************************************/
+
+static void __init m5272_uart_init_line(int line, int irq)
+{
+	u32 v;
+
+	if ((line >= 0) && (line < 2)) {
+		/* Enable the output lines for the serial ports */
+		v = readl(MCF_MBAR + MCFSIM_PBCNT);
+		v = (v & ~0x000000ff) | 0x00000055;
+		writel(v, MCF_MBAR + MCFSIM_PBCNT);
+
+		v = readl(MCF_MBAR + MCFSIM_PDCNT);
+		v = (v & ~0x000003fc) | 0x000002a8;
+		writel(v, MCF_MBAR + MCFSIM_PDCNT);
+	}
+}
+
+static void __init m5272_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m5272_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m5272_uart_init_line(line, m5272_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+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)
+	volatile unsigned char	*pivrp;
+
+	/* Set base of device vectors to be 64 */
+	pivrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_PIVR);
+	*pivrp = 0x40;
+#endif
+
+#if defined(CONFIG_NETtel) || defined(CONFIG_SCALES)
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0xf0004000, size);
+	commandp[size-1] = 0;
+#elif defined(CONFIG_CANCam)
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0xf0010000, size);
+	commandp[size-1] = 0;
+#endif
+
+	mach_reset = m5272_cpu_reset;
+}
+
+/***************************************************************************/
+
+/*
+ * Some 5272 based boards have the FEC ethernet diectly connected to
+ * an ethernet switch. In this case we need to use the fixed phy type,
+ * and we need to declare it early in boot.
+ */
+static struct fixed_phy_status nettel_fixed_phy_status __initdata = {
+	.link	= 1,
+	.speed	= 100,
+	.duplex	= 0,
+};
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	m5272_uarts_init();
+	fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status);
+	platform_add_devices(m5272_devices, ARRAY_SIZE(m5272_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5272/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/5272/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5272/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5272/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,81 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 16,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "PB",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 16,
+			.ngpio			= 16,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PBDDR,
+		.podr				= (void __iomem *) MCFSIM_PBDAT,
+		.ppdr				= (void __iomem *) MCFSIM_PBDAT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "PC",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 32,
+			.ngpio			= 16,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PCDDR,
+		.podr				= (void __iomem *) MCFSIM_PCDAT,
+		.ppdr				= (void __iomem *) MCFSIM_PCDAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5272/intc.c linux-libre-2.6.39-gnu/arch/m68k/platform/5272/intc.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5272/intc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5272/intc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ * intc.c  --  interrupt controller or ColdFire 5272 SoC
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/kernel_stat.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+/*
+ * The 5272 ColdFire interrupt controller is nothing like any other
+ * ColdFire interrupt controller - it truly is completely different.
+ * Given its age it is unlikely to be used on any other ColdFire CPU.
+ */
+
+/*
+ * The masking and priproty setting of interrupts on the 5272 is done
+ * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
+ * loose mapping of vector number to register and internal bits, but
+ * a table is the easiest and quickest way to map them.
+ *
+ * Note that the external interrupts are edge triggered (unlike the
+ * internal interrupt sources which are level triggered). Which means
+ * they also need acknowledging via acknowledge bits.
+ */
+struct irqmap {
+	unsigned char	icr;
+	unsigned char	index;
+	unsigned char	ack;
+};
+
+static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
+	/*MCF_IRQ_SPURIOUS*/	{ .icr = 0,           .index = 0,  .ack = 0, },
+	/*MCF_IRQ_EINT1*/	{ .icr = MCFSIM_ICR1, .index = 28, .ack = 1, },
+	/*MCF_IRQ_EINT2*/	{ .icr = MCFSIM_ICR1, .index = 24, .ack = 1, },
+	/*MCF_IRQ_EINT3*/	{ .icr = MCFSIM_ICR1, .index = 20, .ack = 1, },
+	/*MCF_IRQ_EINT4*/	{ .icr = MCFSIM_ICR1, .index = 16, .ack = 1, },
+	/*MCF_IRQ_TIMER1*/	{ .icr = MCFSIM_ICR1, .index = 12, .ack = 0, },
+	/*MCF_IRQ_TIMER2*/	{ .icr = MCFSIM_ICR1, .index = 8,  .ack = 0, },
+	/*MCF_IRQ_TIMER3*/	{ .icr = MCFSIM_ICR1, .index = 4,  .ack = 0, },
+	/*MCF_IRQ_TIMER4*/	{ .icr = MCFSIM_ICR1, .index = 0,  .ack = 0, },
+	/*MCF_IRQ_UART1*/	{ .icr = MCFSIM_ICR2, .index = 28, .ack = 0, },
+	/*MCF_IRQ_UART2*/	{ .icr = MCFSIM_ICR2, .index = 24, .ack = 0, },
+	/*MCF_IRQ_PLIP*/	{ .icr = MCFSIM_ICR2, .index = 20, .ack = 0, },
+	/*MCF_IRQ_PLIA*/	{ .icr = MCFSIM_ICR2, .index = 16, .ack = 0, },
+	/*MCF_IRQ_USB0*/	{ .icr = MCFSIM_ICR2, .index = 12, .ack = 0, },
+	/*MCF_IRQ_USB1*/	{ .icr = MCFSIM_ICR2, .index = 8,  .ack = 0, },
+	/*MCF_IRQ_USB2*/	{ .icr = MCFSIM_ICR2, .index = 4,  .ack = 0, },
+	/*MCF_IRQ_USB3*/	{ .icr = MCFSIM_ICR2, .index = 0,  .ack = 0, },
+	/*MCF_IRQ_USB4*/	{ .icr = MCFSIM_ICR3, .index = 28, .ack = 0, },
+	/*MCF_IRQ_USB5*/	{ .icr = MCFSIM_ICR3, .index = 24, .ack = 0, },
+	/*MCF_IRQ_USB6*/	{ .icr = MCFSIM_ICR3, .index = 20, .ack = 0, },
+	/*MCF_IRQ_USB7*/	{ .icr = MCFSIM_ICR3, .index = 16, .ack = 0, },
+	/*MCF_IRQ_DMA*/		{ .icr = MCFSIM_ICR3, .index = 12, .ack = 0, },
+	/*MCF_IRQ_ERX*/		{ .icr = MCFSIM_ICR3, .index = 8,  .ack = 0, },
+	/*MCF_IRQ_ETX*/		{ .icr = MCFSIM_ICR3, .index = 4,  .ack = 0, },
+	/*MCF_IRQ_ENTC*/	{ .icr = MCFSIM_ICR3, .index = 0,  .ack = 0, },
+	/*MCF_IRQ_QSPI*/	{ .icr = MCFSIM_ICR4, .index = 28, .ack = 0, },
+	/*MCF_IRQ_EINT5*/	{ .icr = MCFSIM_ICR4, .index = 24, .ack = 1, },
+	/*MCF_IRQ_EINT6*/	{ .icr = MCFSIM_ICR4, .index = 20, .ack = 1, },
+	/*MCF_IRQ_SWTO*/	{ .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
+};
+
+/*
+ * The act of masking the interrupt also has a side effect of 'ack'ing
+ * an interrupt on this irq (for the external irqs). So this mask function
+ * is also an ack_mask function.
+ */
+static void intc_irq_mask(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		u32 v;
+		irq -= MCFINT_VECBASE;
+		v = 0x8 << intc_irqmap[irq].index;
+		writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+	}
+}
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		u32 v;
+		irq -= MCFINT_VECBASE;
+		v = 0xd << intc_irqmap[irq].index;
+		writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+	}
+}
+
+static void intc_irq_ack(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	/* Only external interrupts are acked */
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		irq -= MCFINT_VECBASE;
+		if (intc_irqmap[irq].ack) {
+			u32 v;
+			v = readl(MCF_MBAR + intc_irqmap[irq].icr);
+			v &= (0x7 << intc_irqmap[irq].index);
+			v |= (0x8 << intc_irqmap[irq].index);
+			writel(v, MCF_MBAR + intc_irqmap[irq].icr);
+		}
+	}
+}
+
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int irq = d->irq;
+
+	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
+		irq -= MCFINT_VECBASE;
+		if (intc_irqmap[irq].ack) {
+			u32 v;
+			v = readl(MCF_MBAR + MCFSIM_PITR);
+			if (type == IRQ_TYPE_EDGE_FALLING)
+				v &= ~(0x1 << (32 - irq));
+			else
+				v |= (0x1 << (32 - irq));
+			writel(v, MCF_MBAR + MCFSIM_PITR);
+		}
+	}
+	return 0;
+}
+
+/*
+ * Simple flow handler to deal with the external edge triggered interrupts.
+ * We need to be careful with the masking/acking due to the side effects
+ * of masking an interrupt.
+ */
+static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
+{
+	irq_desc_get_chip(desc)->irq_ack(&desc->irq_data);
+	handle_simple_irq(irq, desc);
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_mask_ack	= intc_irq_mask,
+	.irq_ack	= intc_irq_ack,
+	.irq_set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq, edge;
+
+	init_vectors();
+
+	/* Mask all interrupt sources */
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR3);
+	writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
+
+	for (irq = 0; (irq < NR_IRQS); irq++) {
+		irq_set_chip(irq, &intc_irq_chip);
+		edge = 0;
+		if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX))
+			edge = intc_irqmap[irq - MCFINT_VECBASE].ack;
+		if (edge) {
+			irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+			irq_set_handler(irq, intc_external_irq);
+		} else {
+			irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+			irq_set_handler(irq, handle_level_irq);
+		}
+	}
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5272/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/5272/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5272/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5272/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o intc.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/527x/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/527x/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/527x/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/527x/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,384 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/527x/config.c
+ *
+ *	Sub-architcture dependent initialization code for the Freescale
+ *	5270/5271 CPUs.
+ *
+ *	Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m527x_uart_platform[] = {
+	{
+		.mapbase	= MCFUART_BASE1,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0,
+	},
+	{
+		.mapbase 	= MCFUART_BASE2,
+		.irq		= MCFINT_VECBASE + MCFINT_UART1,
+	},
+	{
+		.mapbase 	= MCFUART_BASE3,
+		.irq		= MCFINT_VECBASE + MCFINT_UART2,
+	},
+	{ },
+};
+
+static struct platform_device m527x_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m527x_uart_platform,
+};
+
+static struct resource m527x_fec0_resources[] = {
+	{
+		.start		= MCFFEC_BASE0,
+		.end		= MCFFEC_BASE0 + MCFFEC_SIZE0 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= 64 + 23,
+		.end		= 64 + 23,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 27,
+		.end		= 64 + 27,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 29,
+		.end		= 64 + 29,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource m527x_fec1_resources[] = {
+	{
+		.start		= MCFFEC_BASE1,
+		.end		= MCFFEC_BASE1 + MCFFEC_SIZE1 - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= 128 + 23,
+		.end		= 128 + 23,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 128 + 27,
+		.end		= 128 + 27,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 128 + 29,
+		.end		= 128 + 29,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m527x_fec[] = {
+	{
+		.name		= "fec",
+		.id		= 0,
+		.num_resources	= ARRAY_SIZE(m527x_fec0_resources),
+		.resource	= m527x_fec0_resources,
+	},
+	{
+		.name		= "fec",
+		.id		= 1,
+		.num_resources	= ARRAY_SIZE(m527x_fec1_resources),
+		.resource	= m527x_fec1_resources,
+	},
+};
+
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m527x_qspi_resources[] = {
+	{
+		.start		= MCFQSPI_IOBASE,
+		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCFINT_VECBASE + MCFINT_QSPI,
+		.end		= MCFINT_VECBASE + MCFINT_QSPI,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+#if defined(CONFIG_M5271)
+#define MCFQSPI_CS0    91
+#define MCFQSPI_CS1    92
+#define MCFQSPI_CS2    99
+#define MCFQSPI_CS3    103
+#elif defined(CONFIG_M5275)
+#define MCFQSPI_CS0    59
+#define MCFQSPI_CS1    60
+#define MCFQSPI_CS2    61
+#define MCFQSPI_CS3    62
+#endif
+
+static int m527x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+	int status;
+
+	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+		goto fail0;
+	}
+	status = gpio_direction_output(MCFQSPI_CS0, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+		goto fail1;
+	}
+
+	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+		goto fail1;
+	}
+	status = gpio_direction_output(MCFQSPI_CS1, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+		goto fail2;
+	}
+
+	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+		goto fail2;
+	}
+	status = gpio_direction_output(MCFQSPI_CS2, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+		goto fail3;
+	}
+
+	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+		goto fail3;
+	}
+	status = gpio_direction_output(MCFQSPI_CS3, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+		goto fail4;
+	}
+
+	return 0;
+
+fail4:
+	gpio_free(MCFQSPI_CS3);
+fail3:
+	gpio_free(MCFQSPI_CS2);
+fail2:
+	gpio_free(MCFQSPI_CS1);
+fail1:
+	gpio_free(MCFQSPI_CS0);
+fail0:
+	return status;
+}
+
+static void m527x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+	gpio_free(MCFQSPI_CS3);
+	gpio_free(MCFQSPI_CS2);
+	gpio_free(MCFQSPI_CS1);
+	gpio_free(MCFQSPI_CS0);
+}
+
+static void m527x_cs_select(struct mcfqspi_cs_control *cs_control,
+			    u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, cs_high);
+		break;
+	case 3:
+		gpio_set_value(MCFQSPI_CS3, cs_high);
+		break;
+	}
+}
+
+static void m527x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+			      u8 chip_select, bool cs_high)
+{
+	switch (chip_select) {
+	case 0:
+		gpio_set_value(MCFQSPI_CS0, !cs_high);
+		break;
+	case 1:
+		gpio_set_value(MCFQSPI_CS1, !cs_high);
+		break;
+	case 2:
+		gpio_set_value(MCFQSPI_CS2, !cs_high);
+		break;
+	case 3:
+		gpio_set_value(MCFQSPI_CS3, !cs_high);
+		break;
+	}
+}
+
+static struct mcfqspi_cs_control m527x_cs_control = {
+	.setup                  = m527x_cs_setup,
+	.teardown               = m527x_cs_teardown,
+	.select                 = m527x_cs_select,
+	.deselect               = m527x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m527x_qspi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 4,
+	.cs_control		= &m527x_cs_control,
+};
+
+static struct platform_device m527x_qspi = {
+	.name			= "mcfqspi",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m527x_qspi_resources),
+	.resource		= m527x_qspi_resources,
+	.dev.platform_data	= &m527x_qspi_data,
+};
+
+static void __init m527x_qspi_init(void)
+{
+#if defined(CONFIG_M5271)
+	u16 par;
+
+	/* setup QSPS pins for QSPI with gpio CS control */
+	writeb(0x1f, MCFGPIO_PAR_QSPI);
+	/* and CS2 & CS3 as gpio */
+	par = readw(MCFGPIO_PAR_TIMER);
+	par &= 0x3f3f;
+	writew(par, MCFGPIO_PAR_TIMER);
+#elif defined(CONFIG_M5275)
+	/* setup QSPS pins for QSPI with gpio CS control */
+	writew(0x003e, MCFGPIO_PAR_QSPI);
+#endif
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+static struct platform_device *m527x_devices[] __initdata = {
+	&m527x_uart,
+	&m527x_fec[0],
+#ifdef CONFIG_FEC2
+	&m527x_fec[1],
+#endif
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	&m527x_qspi,
+#endif
+};
+
+/***************************************************************************/
+
+static void __init m527x_uart_init_line(int line, int irq)
+{
+	u16 sepmask;
+
+	if ((line < 0) || (line > 2))
+		return;
+
+	/*
+	 * External Pin Mask Setting & Enable External Pin for Interface
+	 */
+	sepmask = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
+	if (line == 0)
+		sepmask |= UART0_ENABLE_MASK;
+	else if (line == 1)
+		sepmask |= UART1_ENABLE_MASK;
+	else if (line == 2)
+		sepmask |= UART2_ENABLE_MASK;
+	writew(sepmask, MCF_IPSBAR + MCF_GPIO_PAR_UART);
+}
+
+static void __init m527x_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m527x_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m527x_uart_init_line(line, m527x_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m527x_fec_init(void)
+{
+	u16 par;
+	u8 v;
+
+	/* Set multi-function pins to ethernet mode for fec0 */
+#if defined(CONFIG_M5271)
+	v = readb(MCF_IPSBAR + 0x100047);
+	writeb(v | 0xf0, MCF_IPSBAR + 0x100047);
+#else
+	par = readw(MCF_IPSBAR + 0x100082);
+	writew(par | 0xf00, MCF_IPSBAR + 0x100082);
+	v = readb(MCF_IPSBAR + 0x100078);
+	writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
+#endif
+
+#ifdef CONFIG_FEC2
+	/* Set multi-function pins to ethernet mode for fec1 */
+	par = readw(MCF_IPSBAR + 0x100082);
+	writew(par | 0xa0, MCF_IPSBAR + 0x100082);
+	v = readb(MCF_IPSBAR + 0x100079);
+	writeb(v | 0xc0, MCF_IPSBAR + 0x100079);
+#endif
+}
+
+/***************************************************************************/
+
+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)
+{
+	mach_reset = m527x_cpu_reset;
+	m527x_uarts_init();
+	m527x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	m527x_qspi_init();
+#endif
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m527x_devices, ARRAY_SIZE(m527x_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/527x/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/527x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/527x/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/527x/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,609 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+#if defined(CONFIG_M5271)
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 1,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ADDR",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 13,
+			.ngpio			= 3,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ADDR,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ADDR,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ADDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DATAL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_DATAL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_DATAL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_DATAL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_DATAL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 49,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SDRAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 6,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SDRAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SDRAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SDRAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 2,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 5,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
+	},
+#elif defined(CONFIG_M5275)
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 1,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "ADDR",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 21,
+			.ngpio			= 3,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_ADDR,
+		.podr				= (void __iomem *) MCFGPIO_PODR_ADDR,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_ADDR,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_ADDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 25,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC0H",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC0H,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC0H,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0H,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0H,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC0H,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC0L",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC0L,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC0L,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0L,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC0L,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC0L,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 48,
+			.ngpio			= 6,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SDRAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SDRAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SDRAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SDRAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SDRAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMERH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMERH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMERH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMERH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMERL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMERL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMERL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMERL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMERL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC1H",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC1H,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC1H,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1H,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1H,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC1H,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FEC1L",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FEC1L,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FEC1L,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1L,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FEC1L,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FEC1L,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 114,
+			.ngpio			= 2,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "IRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 121,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_IRQ,
+		.podr				= (void __iomem *) MCFGPIO_PODR_IRQ,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_IRQ,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_IRQ,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_IRQ,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "USBH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 128,
+			.ngpio			= 1,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_USBH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_USBH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_USBH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_USBH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_USBH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "USBL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 136,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_USBL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_USBL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_USBL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_USBL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_USBL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UARTH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 144,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UARTH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UARTH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UARTH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UARTH,
+	},
+#endif
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/527x/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/527x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/527x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/527x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/528x/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/528x/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/528x/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/528x/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,320 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/528x/config.c
+ *
+ *	Sub-architcture dependent initialization code for the Freescale
+ *	5280, 5281 and 5282 CPUs.
+ *
+ *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfqspi.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m528x_uart_platform[] = {
+	{
+		.mapbase	= MCFUART_BASE1,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0,
+	},
+	{
+		.mapbase 	= MCFUART_BASE2,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 1,
+	},
+	{
+		.mapbase 	= MCFUART_BASE3,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 2,
+	},
+	{ },
+};
+
+static struct platform_device m528x_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m528x_uart_platform,
+};
+
+static struct resource m528x_fec_resources[] = {
+	{
+		.start		= MCFFEC_BASE,
+		.end		= MCFFEC_BASE + MCFFEC_SIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= 64 + 23,
+		.end		= 64 + 23,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 27,
+		.end		= 64 + 27,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 29,
+		.end		= 64 + 29,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m528x_fec = {
+	.name			= "fec",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m528x_fec_resources),
+	.resource		= m528x_fec_resources,
+};
+
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m528x_qspi_resources[] = {
+	{
+		.start		= MCFQSPI_IOBASE,
+		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCFINT_VECBASE + MCFINT_QSPI,
+		.end		= MCFINT_VECBASE + MCFINT_QSPI,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+#define MCFQSPI_CS0    147
+#define MCFQSPI_CS1    148
+#define MCFQSPI_CS2    149
+#define MCFQSPI_CS3    150
+
+static int m528x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+	int status;
+
+	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+		goto fail0;
+	}
+	status = gpio_direction_output(MCFQSPI_CS0, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+		goto fail1;
+	}
+
+	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+		goto fail1;
+	}
+	status = gpio_direction_output(MCFQSPI_CS1, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+		goto fail2;
+	}
+
+	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+		goto fail2;
+	}
+	status = gpio_direction_output(MCFQSPI_CS2, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+		goto fail3;
+	}
+
+	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
+		goto fail3;
+	}
+	status = gpio_direction_output(MCFQSPI_CS3, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
+		goto fail4;
+	}
+
+	return 0;
+
+fail4:
+	gpio_free(MCFQSPI_CS3);
+fail3:
+	gpio_free(MCFQSPI_CS2);
+fail2:
+	gpio_free(MCFQSPI_CS1);
+fail1:
+	gpio_free(MCFQSPI_CS0);
+fail0:
+	return status;
+}
+
+static void m528x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+	gpio_free(MCFQSPI_CS3);
+	gpio_free(MCFQSPI_CS2);
+	gpio_free(MCFQSPI_CS1);
+	gpio_free(MCFQSPI_CS0);
+}
+
+static void m528x_cs_select(struct mcfqspi_cs_control *cs_control,
+			    u8 chip_select, bool cs_high)
+{
+	gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
+}
+
+static void m528x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+			      u8 chip_select, bool cs_high)
+{
+	gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
+}
+
+static struct mcfqspi_cs_control m528x_cs_control = {
+	.setup                  = m528x_cs_setup,
+	.teardown               = m528x_cs_teardown,
+	.select                 = m528x_cs_select,
+	.deselect               = m528x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m528x_qspi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 4,
+	.cs_control		= &m528x_cs_control,
+};
+
+static struct platform_device m528x_qspi = {
+	.name			= "mcfqspi",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m528x_qspi_resources),
+	.resource		= m528x_qspi_resources,
+	.dev.platform_data	= &m528x_qspi_data,
+};
+
+static void __init m528x_qspi_init(void)
+{
+	/* setup Port QS for QSPI with gpio CS control */
+	__raw_writeb(0x07, MCFGPIO_PQSPAR);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+static struct platform_device *m528x_devices[] __initdata = {
+	&m528x_uart,
+	&m528x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	&m528x_qspi,
+#endif
+};
+
+/***************************************************************************/
+
+static void __init m528x_uart_init_line(int line, int irq)
+{
+	u8 port;
+
+	if ((line < 0) || (line > 2))
+		return;
+
+	/* make sure PUAPAR is set for UART0 and UART1 */
+	if (line < 2) {
+		port = readb(MCF5282_GPIO_PUAPAR);
+		port |= (0x03 << (line * 2));
+		writeb(port, MCF5282_GPIO_PUAPAR);
+	}
+}
+
+static void __init m528x_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m528x_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m528x_uart_init_line(line, m528x_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m528x_fec_init(void)
+{
+	u16 v16;
+
+	/* Set multi-function pins to ethernet mode for fec0 */
+	v16 = readw(MCF_IPSBAR + 0x100056);
+	writew(v16 | 0xf00, MCF_IPSBAR + 0x100056);
+	writeb(0xc0, MCF_IPSBAR + 0x100058);
+}
+
+/***************************************************************************/
+
+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)
+{
+	writeb(0, 0x30000007);
+	writeb(0x2, 0x30000007);
+}
+#endif
+
+#ifdef CONFIG_WILDFIREMOD
+void wildfiremod_halt(void)
+{
+	printk(KERN_INFO "WildFireMod hibernating...\n");
+
+	/* Set portE.5 to Digital IO */
+	MCF5282_GPIO_PEPAR &= ~(1 << (5 * 2));
+
+	/* Make portE.5 an output */
+	MCF5282_GPIO_DDRE |= (1 << 5);
+
+	/* Now toggle portE.5 from low to high */
+	MCF5282_GPIO_PORTE &= ~(1 << 5);
+	MCF5282_GPIO_PORTE |= (1 << 5);
+
+	printk(KERN_EMERG "Failed to hibernate. Halting!\n");
+}
+#endif
+
+void __init config_BSP(char *commandp, int size)
+{
+#ifdef CONFIG_WILDFIRE
+	mach_halt = wildfire_halt;
+#endif
+#ifdef CONFIG_WILDFIREMOD
+	mach_halt = wildfiremod_halt;
+#endif
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	mach_reset = m528x_cpu_reset;
+	m528x_uarts_init();
+	m528x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	m528x_qspi_init();
+#endif
+	platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/528x/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/528x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/528x/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/528x/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,438 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "NQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.base			= 1,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *)MCFEPORT_EPDDR,
+		.podr				= (void __iomem *)MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *)MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFGPTA_GPTDDR,
+		.podr				= (void __iomem *)MCFGPTA_GPTPORT,
+		.ppdr				= (void __iomem *)MCFGPTB_GPTPORT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TB",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFGPTB_GPTDDR,
+		.podr				= (void __iomem *)MCFGPTB_GPTPORT,
+		.ppdr				= (void __iomem *)MCFGPTB_GPTPORT,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFQADC_DDRQA,
+		.podr				= (void __iomem *)MCFQADC_PORTQA,
+		.ppdr				= (void __iomem *)MCFQADC_PORTQA,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QB",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFQADC_DDRQB,
+		.podr				= (void __iomem *)MCFQADC_PORTQB,
+		.ppdr				= (void __iomem *)MCFQADC_PORTQB,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "A",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRA,
+		.podr				= (void __iomem *)MCFGPIO_PORTA,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTAP,
+		.setr				= (void __iomem *)MCFGPIO_SETA,
+		.clrr				= (void __iomem *)MCFGPIO_CLRA,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "B",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 48,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRB,
+		.podr				= (void __iomem *)MCFGPIO_PORTB,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTBP,
+		.setr				= (void __iomem *)MCFGPIO_SETB,
+		.clrr				= (void __iomem *)MCFGPIO_CLRB,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 56,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRC,
+		.podr				= (void __iomem *)MCFGPIO_PORTC,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTCP,
+		.setr				= (void __iomem *)MCFGPIO_SETC,
+		.clrr				= (void __iomem *)MCFGPIO_CLRC,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "D",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRD,
+		.podr				= (void __iomem *)MCFGPIO_PORTD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTDP,
+		.setr				= (void __iomem *)MCFGPIO_SETD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "E",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRE,
+		.podr				= (void __iomem *)MCFGPIO_PORTE,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTEP,
+		.setr				= (void __iomem *)MCFGPIO_SETE,
+		.clrr				= (void __iomem *)MCFGPIO_CLRE,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "F",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRF,
+		.podr				= (void __iomem *)MCFGPIO_PORTF,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTFP,
+		.setr				= (void __iomem *)MCFGPIO_SETF,
+		.clrr				= (void __iomem *)MCFGPIO_CLRF,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "G",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRG,
+		.podr				= (void __iomem *)MCFGPIO_PORTG,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTGP,
+		.setr				= (void __iomem *)MCFGPIO_SETG,
+		.clrr				= (void __iomem *)MCFGPIO_CLRG,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "H",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRH,
+		.podr				= (void __iomem *)MCFGPIO_PORTH,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTHP,
+		.setr				= (void __iomem *)MCFGPIO_SETH,
+		.clrr				= (void __iomem *)MCFGPIO_CLRH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "J",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRJ,
+		.podr				= (void __iomem *)MCFGPIO_PORTJ,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTJP,
+		.setr				= (void __iomem *)MCFGPIO_SETJ,
+		.clrr				= (void __iomem *)MCFGPIO_CLRJ,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "DD",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 112,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRDD,
+		.podr				= (void __iomem *)MCFGPIO_PORTDD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTDDP,
+		.setr				= (void __iomem *)MCFGPIO_SETDD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRDD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "EH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 120,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDREH,
+		.podr				= (void __iomem *)MCFGPIO_PORTEH,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTEHP,
+		.setr				= (void __iomem *)MCFGPIO_SETEH,
+		.clrr				= (void __iomem *)MCFGPIO_CLREH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "EL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 128,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDREL,
+		.podr				= (void __iomem *)MCFGPIO_PORTEL,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTELP,
+		.setr				= (void __iomem *)MCFGPIO_SETEL,
+		.clrr				= (void __iomem *)MCFGPIO_CLREL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "AS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 136,
+			.ngpio			= 6,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRAS,
+		.podr				= (void __iomem *)MCFGPIO_PORTAS,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTASP,
+		.setr				= (void __iomem *)MCFGPIO_SETAS,
+		.clrr				= (void __iomem *)MCFGPIO_CLRAS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 144,
+			.ngpio			= 7,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRQS,
+		.podr				= (void __iomem *)MCFGPIO_PORTQS,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTQSP,
+		.setr				= (void __iomem *)MCFGPIO_SETQS,
+		.clrr				= (void __iomem *)MCFGPIO_CLRQS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SD",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 152,
+			.ngpio			= 6,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRSD,
+		.podr				= (void __iomem *)MCFGPIO_PORTSD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTSDP,
+		.setr				= (void __iomem *)MCFGPIO_SETSD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRSD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TC",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 160,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRTC,
+		.podr				= (void __iomem *)MCFGPIO_PORTTC,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTTCP,
+		.setr				= (void __iomem *)MCFGPIO_SETTC,
+		.clrr				= (void __iomem *)MCFGPIO_CLRTC,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TD",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 168,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRTD,
+		.podr				= (void __iomem *)MCFGPIO_PORTTD,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTTDP,
+		.setr				= (void __iomem *)MCFGPIO_SETTD,
+		.clrr				= (void __iomem *)MCFGPIO_CLRTD,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UA",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 176,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *)MCFGPIO_DDRUA,
+		.podr				= (void __iomem *)MCFGPIO_PORTUA,
+		.ppdr				= (void __iomem *)MCFGPIO_PORTUAP,
+		.setr				= (void __iomem *)MCFGPIO_SETUA,
+		.clrr				= (void __iomem *)MCFGPIO_CLRUA,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/528x/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/528x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/528x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/528x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs.  You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5307/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/5307/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5307/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5307/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,147 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5307/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2000, Lineo (www.lineo.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+/*
+ *	Some platforms need software versions of the GPIO data registers.
+ */
+unsigned short ppdata;
+unsigned char ledbank = 0xff;
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m5307_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 73,
+	},
+	{
+		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 74,
+	},
+	{ },
+};
+
+static struct platform_device m5307_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m5307_uart_platform,
+};
+
+static struct platform_device *m5307_devices[] __initdata = {
+	&m5307_uart,
+};
+
+/***************************************************************************/
+
+static void __init m5307_uart_init_line(int line, int irq)
+{
+	if (line == 0) {
+		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
+		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
+	} else if (line == 1) {
+		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
+		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
+	}
+}
+
+static void __init m5307_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m5307_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m5307_uart_init_line(line, m5307_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m5307_timers_init(void)
+{
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
+
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
+}
+
+/***************************************************************************/
+
+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)
+{
+#if defined(CONFIG_NETtel) || \
+    defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0xf0004000, size);
+	commandp[size-1] = 0;
+#endif
+
+	mach_reset = m5307_cpu_reset;
+	m5307_timers_init();
+	m5307_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(27, MCFINTC_EINT3);
+	mcf_mapirq2imr(29, MCFINTC_EINT5);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
+
+#ifdef CONFIG_BDM_DISABLE
+	/*
+	 * Disable the BDM clocking.  This also turns off most of the rest of
+	 * the BDM device.  This is good for EMC reasons. This option is not
+	 * incompatible with the memory protection option.
+	 */
+	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m5307_devices, ARRAY_SIZE(m5307_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5307/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/5307/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5307/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5307/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 16,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5307/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/5307/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5307/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5307/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+#
+# Makefile for the m68knommu kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y			+= config.o gpio.o
+obj-$(CONFIG_NETtel)	+= nettel.o
+obj-$(CONFIG_CLEOPATRA)	+= nettel.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5307/nettel.c linux-libre-2.6.39-gnu/arch/m68k/platform/5307/nettel.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5307/nettel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5307/nettel.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,153 @@
+/***************************************************************************/
+
+/*
+ *	nettel.c -- startup code support for the NETtel boards
+ *
+ *	Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/nettel.h>
+
+/***************************************************************************/
+
+/*
+ * Define the IO and interrupt resources of the 2 SMC9196 interfaces.
+ */
+#define	NETTEL_SMC0_ADDR	0x30600300
+#define	NETTEL_SMC0_IRQ		29
+
+#define	NETTEL_SMC1_ADDR	0x30600000
+#define	NETTEL_SMC1_IRQ		27
+
+/*
+ * We need some access into the SMC9196 registers. Define those registers
+ * we will need here (including the smc91x.h doesn't seem to give us these
+ * in a simple form).
+ */
+#define	SMC91xx_BANKSELECT	14
+#define	SMC91xx_BASEADDR	2
+#define	SMC91xx_BASEMAC		4
+
+/***************************************************************************/
+
+static struct resource nettel_smc91x_0_resources[] = {
+	{
+		.start		= NETTEL_SMC0_ADDR,
+		.end		= NETTEL_SMC0_ADDR + 0x20,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= NETTEL_SMC0_IRQ,
+		.end		= NETTEL_SMC0_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource nettel_smc91x_1_resources[] = {
+	{
+		.start		= NETTEL_SMC1_ADDR,
+		.end		= NETTEL_SMC1_ADDR + 0x20,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= NETTEL_SMC1_IRQ,
+		.end		= NETTEL_SMC1_IRQ,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device nettel_smc91x[] = {
+	{
+		.name			= "smc91x",
+		.id			= 0,
+		.num_resources		= ARRAY_SIZE(nettel_smc91x_0_resources),
+		.resource		= nettel_smc91x_0_resources,
+	},
+	{
+		.name			= "smc91x",
+		.id			= 1,
+		.num_resources		= ARRAY_SIZE(nettel_smc91x_1_resources),
+		.resource		= nettel_smc91x_1_resources,
+	},
+};
+
+static struct platform_device *nettel_devices[] __initdata = {
+	&nettel_smc91x[0],
+	&nettel_smc91x[1],
+};
+
+/***************************************************************************/
+
+static u8 nettel_macdefault[] __initdata = {
+	0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01,
+};
+
+/*
+ * Set flash contained MAC address into SMC9196 core. Make sure the flash
+ * MAC address is sane, and not an empty flash. If no good use the Moreton
+ * Bay default MAC address instead.
+ */
+
+static void __init nettel_smc91x_setmac(unsigned int ioaddr, unsigned int flashaddr)
+{
+	u16 *macp;
+
+	macp = (u16 *) flashaddr;
+	if ((macp[0] == 0xffff) && (macp[1] == 0xffff) && (macp[2] == 0xffff))
+		macp = (u16 *) &nettel_macdefault[0];
+
+	writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
+	writew(macp[0], ioaddr + SMC91xx_BASEMAC);
+	writew(macp[1], ioaddr + SMC91xx_BASEMAC + 2);
+	writew(macp[2], ioaddr + SMC91xx_BASEMAC + 4);
+}
+
+/***************************************************************************/
+
+/*
+ * Re-map the address space of at least one of the SMC ethernet
+ * parts. Both parts power up decoding the same address, so we
+ * need to move one of them first, before doing anything else.
+ */
+
+static void __init nettel_smc91x_init(void)
+{
+	writew(0x00ec, MCF_MBAR + MCFSIM_PADDR);
+	mcf_setppdata(0, 0x0080);
+	writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
+	writew(0x0067, NETTEL_SMC0_ADDR + SMC91xx_BASEADDR);
+	mcf_setppdata(0x0080, 0);
+
+	/* Set correct chip select timing for SMC9196 accesses */
+	writew(0x1180, MCF_MBAR + MCFSIM_CSCR3);
+
+	/* Set the SMC interrupts to be auto-vectored */
+	mcf_autovector(NETTEL_SMC0_IRQ);
+	mcf_autovector(NETTEL_SMC1_IRQ);
+
+	/* Set MAC addresses from flash for both interfaces */
+	nettel_smc91x_setmac(NETTEL_SMC0_ADDR, 0xf0006000);
+	nettel_smc91x_setmac(NETTEL_SMC1_ADDR, 0xf0006006);
+}
+
+/***************************************************************************/
+
+static int __init init_nettel(void)
+{
+	nettel_smc91x_init();
+	platform_add_devices(nettel_devices, ARRAY_SIZE(nettel_devices));
+	return 0;
+}
+
+arch_initcall(init_nettel);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/532x/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/532x/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/532x/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/532x/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,648 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/532x/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2000, Lineo (www.lineo.com)
+ *	Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
+ *	Copyright Freescale Semiconductor, Inc 2006
+ *	Copyright (c) 2006, emlix, Sebastian Hess <sh@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/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+#include <linux/gpio.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+#include <asm/mcfdma.h>
+#include <asm/mcfwdebug.h>
+#include <asm/mcfqspi.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m532x_uart_platform[] = {
+	{
+		.mapbase	= MCFUART_BASE1,
+		.irq		= MCFINT_VECBASE + MCFINT_UART0,
+	},
+	{
+		.mapbase 	= MCFUART_BASE2,
+		.irq		= MCFINT_VECBASE + MCFINT_UART1,
+	},
+	{
+		.mapbase 	= MCFUART_BASE3,
+		.irq		= MCFINT_VECBASE + MCFINT_UART2,
+	},
+	{ },
+};
+
+static struct platform_device m532x_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m532x_uart_platform,
+};
+
+static struct resource m532x_fec_resources[] = {
+	{
+		.start		= 0xfc030000,
+		.end		= 0xfc0307ff,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= 64 + 36,
+		.end		= 64 + 36,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 40,
+		.end		= 64 + 40,
+		.flags		= IORESOURCE_IRQ,
+	},
+	{
+		.start		= 64 + 42,
+		.end		= 64 + 42,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device m532x_fec = {
+	.name			= "fec",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m532x_fec_resources),
+	.resource		= m532x_fec_resources,
+};
+
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+static struct resource m532x_qspi_resources[] = {
+	{
+		.start		= MCFQSPI_IOBASE,
+		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
+		.flags		= IORESOURCE_MEM,
+	},
+	{
+		.start		= MCFINT_VECBASE + MCFINT_QSPI,
+		.end		= MCFINT_VECBASE + MCFINT_QSPI,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+#define MCFQSPI_CS0    84
+#define MCFQSPI_CS1    85
+#define MCFQSPI_CS2    86
+
+static int m532x_cs_setup(struct mcfqspi_cs_control *cs_control)
+{
+	int status;
+
+	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
+		goto fail0;
+	}
+	status = gpio_direction_output(MCFQSPI_CS0, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
+		goto fail1;
+	}
+
+	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
+		goto fail1;
+	}
+	status = gpio_direction_output(MCFQSPI_CS1, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
+		goto fail2;
+	}
+
+	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
+	if (status) {
+		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
+		goto fail2;
+	}
+	status = gpio_direction_output(MCFQSPI_CS2, 1);
+	if (status) {
+		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
+		goto fail3;
+	}
+
+	return 0;
+
+fail3:
+	gpio_free(MCFQSPI_CS2);
+fail2:
+	gpio_free(MCFQSPI_CS1);
+fail1:
+	gpio_free(MCFQSPI_CS0);
+fail0:
+	return status;
+}
+
+static void m532x_cs_teardown(struct mcfqspi_cs_control *cs_control)
+{
+	gpio_free(MCFQSPI_CS2);
+	gpio_free(MCFQSPI_CS1);
+	gpio_free(MCFQSPI_CS0);
+}
+
+static void m532x_cs_select(struct mcfqspi_cs_control *cs_control,
+			    u8 chip_select, bool cs_high)
+{
+	gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
+}
+
+static void m532x_cs_deselect(struct mcfqspi_cs_control *cs_control,
+			      u8 chip_select, bool cs_high)
+{
+	gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
+}
+
+static struct mcfqspi_cs_control m532x_cs_control = {
+	.setup                  = m532x_cs_setup,
+	.teardown               = m532x_cs_teardown,
+	.select                 = m532x_cs_select,
+	.deselect               = m532x_cs_deselect,
+};
+
+static struct mcfqspi_platform_data m532x_qspi_data = {
+	.bus_num		= 0,
+	.num_chipselect		= 3,
+	.cs_control		= &m532x_cs_control,
+};
+
+static struct platform_device m532x_qspi = {
+	.name			= "mcfqspi",
+	.id			= 0,
+	.num_resources		= ARRAY_SIZE(m532x_qspi_resources),
+	.resource		= m532x_qspi_resources,
+	.dev.platform_data	= &m532x_qspi_data,
+};
+
+static void __init m532x_qspi_init(void)
+{
+	/* setup QSPS pins for QSPI with gpio CS control */
+	writew(0x01f0, MCF_GPIO_PAR_QSPI);
+}
+#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
+
+
+static struct platform_device *m532x_devices[] __initdata = {
+	&m532x_uart,
+	&m532x_fec,
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	&m532x_qspi,
+#endif
+};
+
+/***************************************************************************/
+
+static void __init m532x_uart_init_line(int line, int irq)
+{
+	if (line == 0) {
+		/* GPIO initialization */
+		MCF_GPIO_PAR_UART |= 0x000F;
+	} else if (line == 1) {
+		/* GPIO initialization */
+		MCF_GPIO_PAR_UART |= 0x0FF0;
+	}
+}
+
+static void __init m532x_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m532x_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m532x_uart_init_line(line, m532x_uart_platform[line].irq);
+}
+/***************************************************************************/
+
+static void __init m532x_fec_init(void)
+{
+	/* Set multi-function pins to ethernet mode for fec0 */
+	MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
+		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
+	MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
+		MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
+}
+
+/***************************************************************************/
+
+static void m532x_cpu_reset(void)
+{
+	local_irq_disable();
+	__raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
+}
+
+/***************************************************************************/
+
+void __init config_BSP(char *commandp, int size)
+{
+#if !defined(CONFIG_BOOTPARAM)
+	/* Copy command line from FLASH to local buffer... */
+	memcpy(commandp, (char *) 0x4000, 4);
+	if(strncmp(commandp, "kcl ", 4) == 0){
+		memcpy(commandp, (char *) 0x4004, size);
+		commandp[size-1] = 0;
+	} else {
+		memset(commandp, 0, size);
+	}
+#endif
+
+#ifdef CONFIG_BDM_DISABLE
+	/*
+	 * Disable the BDM clocking.  This also turns off most of the rest of
+	 * the BDM device.  This is good for EMC reasons. This option is not
+	 * incompatible with the memory protection option.
+	 */
+	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
+#endif
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	m532x_uarts_init();
+	m532x_fec_init();
+#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
+	m532x_qspi_init();
+#endif
+	platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
+/* Board initialization */
+/***************************************************************************/
+/* 
+ * PLL min/max specifications
+ */
+#define MAX_FVCO	500000	/* KHz */
+#define MAX_FSYS	80000 	/* KHz */
+#define MIN_FSYS	58333 	/* KHz */
+#define FREF		16000   /* KHz */
+
+
+#define MAX_MFD		135     /* Multiplier */
+#define MIN_MFD		88      /* Multiplier */
+#define BUSDIV		6       /* Divider */
+
+/*
+ * Low Power Divider specifications
+ */
+#define MIN_LPD		(1 << 0)    /* Divider (not encoded) */
+#define MAX_LPD		(1 << 15)   /* Divider (not encoded) */
+#define DEFAULT_LPD	(1 << 1)	/* Divider (not encoded) */
+
+#define SYS_CLK_KHZ	80000
+#define SYSTEM_PERIOD	12.5
+/*
+ *  SDRAM Timing Parameters
+ */  
+#define SDRAM_BL	8	/* # of beats in a burst */
+#define SDRAM_TWR	2	/* in clocks */
+#define SDRAM_CASL	2.5	/* CASL in clocks */
+#define SDRAM_TRCD	2	/* in clocks */
+#define SDRAM_TRP	2	/* in clocks */
+#define SDRAM_TRFC	7	/* in clocks */
+#define SDRAM_TREFI	7800	/* in ns */
+
+#define EXT_SRAM_ADDRESS	(0xC0000000)
+#define FLASH_ADDRESS		(0x00000000)
+#define SDRAM_ADDRESS		(0x40000000)
+
+#define NAND_FLASH_ADDRESS	(0xD0000000)
+
+int sys_clk_khz = 0;
+int sys_clk_mhz = 0;
+
+void wtm_init(void);
+void scm_init(void);
+void gpio_init(void);
+void fbcs_init(void);
+void sdramc_init(void);
+int  clock_pll (int fsys, int flags);
+int  clock_limp (int);
+int  clock_exit_limp (void);
+int  get_sys_clock (void);
+
+asmlinkage void __init sysinit(void)
+{
+	sys_clk_khz = clock_pll(0, 0);
+	sys_clk_mhz = sys_clk_khz/1000;
+	
+	wtm_init();
+	scm_init();
+	gpio_init();
+	fbcs_init();
+	sdramc_init();
+}
+
+void wtm_init(void)
+{
+	/* Disable watchdog timer */
+	MCF_WTM_WCR = 0;
+}
+
+#define MCF_SCM_BCR_GBW		(0x00000100)
+#define MCF_SCM_BCR_GBR		(0x00000200)
+
+void scm_init(void)
+{
+	/* All masters are trusted */
+	MCF_SCM_MPR = 0x77777777;
+    
+	/* Allow supervisor/user, read/write, and trusted/untrusted
+	   access to all slaves */
+	MCF_SCM_PACRA = 0;
+	MCF_SCM_PACRB = 0;
+	MCF_SCM_PACRC = 0;
+	MCF_SCM_PACRD = 0;
+	MCF_SCM_PACRE = 0;
+	MCF_SCM_PACRF = 0;
+
+	/* Enable bursts */
+	MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
+}
+
+
+void fbcs_init(void)
+{
+	MCF_GPIO_PAR_CS = 0x0000003E;
+
+	/* Latch chip select */
+	MCF_FBCS1_CSAR = 0x10080000;
+
+	MCF_FBCS1_CSCR = 0x002A3780;
+	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
+
+	/* Initialize latch to drive signals to inactive states */
+	*((u16 *)(0x10080000)) = 0xFFFF;
+
+	/* External SRAM */
+	MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
+	MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
+			| MCF_FBCS_CSCR_AA
+			| MCF_FBCS_CSCR_SBM
+			| MCF_FBCS_CSCR_WS(1));
+	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
+			| MCF_FBCS_CSMR_V);
+
+	/* Boot Flash connected to FBCS0 */
+	MCF_FBCS0_CSAR = FLASH_ADDRESS;
+	MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
+			| MCF_FBCS_CSCR_BEM
+			| MCF_FBCS_CSCR_AA
+			| MCF_FBCS_CSCR_SBM
+			| MCF_FBCS_CSCR_WS(7));
+	MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
+			| MCF_FBCS_CSMR_V);
+}
+
+void sdramc_init(void)
+{
+	/*
+	 * Check to see if the SDRAM has already been initialized
+	 * by a run control tool
+	 */
+	if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
+		/* SDRAM chip select initialization */
+		
+		/* Initialize SDRAM chip select */
+		MCF_SDRAMC_SDCS0 = (0
+			| MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
+			| MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
+
+	/*
+	 * Basic configuration and initialization
+	 */
+	MCF_SDRAMC_SDCFG1 = (0
+		| MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
+		| MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
+		| MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
+		| MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
+		| MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
+		| MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
+		| MCF_SDRAMC_SDCFG1_WTLAT(3));
+	MCF_SDRAMC_SDCFG2 = (0
+		| MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
+		| MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
+		| MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
+		| MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
+
+            
+	/*
+	 * Precharge and enable write to SDMR
+	 */
+        MCF_SDRAMC_SDCR = (0
+		| MCF_SDRAMC_SDCR_MODE_EN
+		| MCF_SDRAMC_SDCR_CKE
+		| MCF_SDRAMC_SDCR_DDR
+		| MCF_SDRAMC_SDCR_MUX(1)
+		| MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
+		| MCF_SDRAMC_SDCR_PS_16
+		| MCF_SDRAMC_SDCR_IPALL);            
+
+	/*
+	 * Write extended mode register
+	 */
+	MCF_SDRAMC_SDMR = (0
+		| MCF_SDRAMC_SDMR_BNKAD_LEMR
+		| MCF_SDRAMC_SDMR_AD(0x0)
+		| MCF_SDRAMC_SDMR_CMD);
+
+	/*
+	 * Write mode register and reset DLL
+	 */
+	MCF_SDRAMC_SDMR = (0
+		| MCF_SDRAMC_SDMR_BNKAD_LMR
+		| MCF_SDRAMC_SDMR_AD(0x163)
+		| MCF_SDRAMC_SDMR_CMD);
+
+	/*
+	 * Execute a PALL command
+	 */
+	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
+
+	/*
+	 * Perform two REF cycles
+	 */
+	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
+
+	/*
+	 * Write mode register and clear reset DLL
+	 */
+	MCF_SDRAMC_SDMR = (0
+		| MCF_SDRAMC_SDMR_BNKAD_LMR
+		| MCF_SDRAMC_SDMR_AD(0x063)
+		| MCF_SDRAMC_SDMR_CMD);
+				
+	/*
+	 * Enable auto refresh and lock SDMR
+	 */
+	MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
+	MCF_SDRAMC_SDCR |= (0
+		| MCF_SDRAMC_SDCR_REF
+		| MCF_SDRAMC_SDCR_DQS_OE(0xC));
+	}
+}
+
+void gpio_init(void)
+{
+	/* Enable UART0 pins */
+	MCF_GPIO_PAR_UART = ( 0
+		| MCF_GPIO_PAR_UART_PAR_URXD0
+		| MCF_GPIO_PAR_UART_PAR_UTXD0);
+
+	/* Initialize TIN3 as a GPIO output to enable the write
+	   half of the latch */
+	MCF_GPIO_PAR_TIMER = 0x00;
+	__raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
+	__raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
+
+}
+
+int clock_pll(int fsys, int flags)
+{
+	int fref, temp, fout, mfd;
+	u32 i;
+
+	fref = FREF;
+        
+	if (fsys == 0) {
+		/* Return current PLL output */
+		mfd = MCF_PLL_PFDR;
+
+		return (fref * mfd / (BUSDIV * 4));
+	}
+
+	/* Check bounds of requested system clock */
+	if (fsys > MAX_FSYS)
+		fsys = MAX_FSYS;
+	if (fsys < MIN_FSYS)
+		fsys = MIN_FSYS;
+
+	/* Multiplying by 100 when calculating the temp value,
+	   and then dividing by 100 to calculate the mfd allows
+	   for exact values without needing to include floating
+	   point libraries. */
+	temp = 100 * fsys / fref;
+	mfd = 4 * BUSDIV * temp / 100;
+    	    	    	
+	/* Determine the output frequency for selected values */
+	fout = (fref * mfd / (BUSDIV * 4));
+
+	/*
+	 * Check to see if the SDRAM has already been initialized.
+	 * If it has then the SDRAM needs to be put into self refresh
+	 * mode before reprogramming the PLL.
+	 */
+	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+		/* Put SDRAM into self refresh mode */
+		MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
+
+	/*
+	 * Initialize the PLL to generate the new system clock frequency.
+	 * The device must be put into LIMP mode to reprogram the PLL.
+	 */
+
+	/* Enter LIMP mode */
+	clock_limp(DEFAULT_LPD);
+     					
+	/* Reprogram PLL for desired fsys */
+	MCF_PLL_PODR = (0
+		| MCF_PLL_PODR_CPUDIV(BUSDIV/3)
+		| MCF_PLL_PODR_BUSDIV(BUSDIV));
+						
+	MCF_PLL_PFDR = mfd;
+		
+	/* Exit LIMP mode */
+	clock_exit_limp();
+	
+	/*
+	 * Return the SDRAM to normal operation if it is in use.
+	 */
+	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
+		/* Exit self refresh mode */
+		MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
+
+	/* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
+	MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
+
+	/* wait for DQS logic to relock */
+	for (i = 0; i < 0x200; i++)
+		;
+
+	return fout;
+}
+
+int clock_limp(int div)
+{
+	u32 temp;
+
+	/* Check bounds of divider */
+	if (div < MIN_LPD)
+		div = MIN_LPD;
+	if (div > MAX_LPD)
+		div = MAX_LPD;
+    
+	/* Save of the current value of the SSIDIV so we don't
+	   overwrite the value*/
+	temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
+      
+	/* Apply the divider to the system clock */
+	MCF_CCM_CDR = ( 0
+		| MCF_CCM_CDR_LPDIV(div)
+		| MCF_CCM_CDR_SSIDIV(temp));
+    
+	MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
+    
+	return (FREF/(3*(1 << div)));
+}
+
+int clock_exit_limp(void)
+{
+	int fout;
+	
+	/* Exit LIMP mode */
+	MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
+
+	/* Wait for PLL to lock */
+	while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
+		;
+	
+	fout = get_sys_clock();
+
+	return fout;
+}
+
+int get_sys_clock(void)
+{
+	int divider;
+	
+	/* Test to see if device is in LIMP mode */
+	if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
+		divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
+		return (FREF/(2 << divider));
+	}
+	else
+		return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/532x/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/532x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/532x/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/532x/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,337 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PIRQ",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFEPORT_EPDDR,
+		.podr				= (void __iomem *) MCFEPORT_EPDR,
+		.ppdr				= (void __iomem *) MCFEPORT_EPPDR,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 8,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 16,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "SSI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 24,
+			.ngpio			= 5,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_SSI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_SSI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_SSI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_SSI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_SSI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BUSCTL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 32,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BUSCTL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BUSCTL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BUSCTL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BUSCTL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "BE",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 40,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_BE,
+		.podr				= (void __iomem *) MCFGPIO_PODR_BE,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_BE,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_BE,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "CS",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 49,
+			.ngpio			= 5,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_CS,
+		.podr				= (void __iomem *) MCFGPIO_PODR_CS,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_CS,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_CS,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "PWM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 58,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_PWM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_PWM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_PWM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_PWM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_PWM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "FECI2C",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 64,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_FECI2C,
+		.podr				= (void __iomem *) MCFGPIO_PODR_FECI2C,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_FECI2C,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_FECI2C,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "UART",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 72,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_UART,
+		.podr				= (void __iomem *) MCFGPIO_PODR_UART,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_UART,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_UART,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "QSPI",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 80,
+			.ngpio			= 6,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_QSPI,
+		.podr				= (void __iomem *) MCFGPIO_PODR_QSPI,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_QSPI,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_QSPI,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "TIMER",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 88,
+			.ngpio			= 4,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_TIMER,
+		.podr				= (void __iomem *) MCFGPIO_PODR_TIMER,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_TIMER,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_TIMER,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDDATAH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 96,
+			.ngpio			= 2,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDDATAM",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 104,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAM,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAM,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAM,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAM,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDDATAL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 112,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDDATAL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDDATAL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDDATAL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDDATAL,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDCTLH",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 120,
+			.ngpio			= 1,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDCTLH,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDCTLH,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLH,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDCTLH,
+	},
+	{
+		.gpio_chip			= {
+			.label			= "LCDCTLL",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value_fast,
+			.base			= 128,
+			.ngpio			= 8,
+		},
+		.pddr				= (void __iomem *) MCFGPIO_PDDR_LCDCTLL,
+		.podr				= (void __iomem *) MCFGPIO_PODR_LCDCTLL,
+		.ppdr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
+		.setr				= (void __iomem *) MCFGPIO_PPDSDR_LCDCTLL,
+		.clrr				= (void __iomem *) MCFGPIO_PCLRR_LCDCTLL,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/532x/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/532x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/532x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/532x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
+obj-y := config.o gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5407/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/5407/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5407/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5407/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,122 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/5407/config.c
+ *
+ *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2000, Lineo (www.lineo.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfuart.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m5407_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 73,
+	},
+	{
+		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 74,
+	},
+	{ },
+};
+
+static struct platform_device m5407_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m5407_uart_platform,
+};
+
+static struct platform_device *m5407_devices[] __initdata = {
+	&m5407_uart,
+};
+
+/***************************************************************************/
+
+static void __init m5407_uart_init_line(int line, int irq)
+{
+	if (line == 0) {
+		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
+		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART0);
+	} else if (line == 1) {
+		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
+		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
+		mcf_mapirq2imr(irq, MCFINTC_UART1);
+	}
+}
+
+static void __init m5407_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m5407_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m5407_uart_init_line(line, m5407_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void __init m5407_timers_init(void)
+{
+	/* Timer1 is always used as system timer */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER1ICR);
+	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
+
+#ifdef CONFIG_HIGHPROFILE
+	/* Timer2 is to be used as a high speed profile timer  */
+	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
+		MCF_MBAR + MCFSIM_TIMER2ICR);
+	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
+#endif
+}
+
+/***************************************************************************/
+
+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)
+{
+	mach_reset = m5407_cpu_reset;
+	m5407_timers_init();
+	m5407_uarts_init();
+
+	/* Only support the external interrupts on their primary level */
+	mcf_mapirq2imr(25, MCFINTC_EINT1);
+	mcf_mapirq2imr(27, MCFINTC_EINT3);
+	mcf_mapirq2imr(29, MCFINTC_EINT5);
+	mcf_mapirq2imr(31, MCFINTC_EINT7);
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+	platform_add_devices(m5407_devices, ARRAY_SIZE(m5407_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5407/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/5407/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5407/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5407/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+/*
+ * Coldfire generic GPIO support
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfgpio.h>
+
+static struct mcf_gpio_chip mcf_gpio_chips[] = {
+	{
+		.gpio_chip			= {
+			.label			= "PP",
+			.request		= mcf_gpio_request,
+			.free			= mcf_gpio_free,
+			.direction_input	= mcf_gpio_direction_input,
+			.direction_output	= mcf_gpio_direction_output,
+			.get			= mcf_gpio_get_value,
+			.set			= mcf_gpio_set_value,
+			.ngpio			= 16,
+		},
+		.pddr				= (void __iomem *) MCFSIM_PADDR,
+		.podr				= (void __iomem *) MCFSIM_PADAT,
+		.ppdr				= (void __iomem *) MCFSIM_PADAT,
+	},
+};
+
+static int __init mcf_gpio_init(void)
+{
+	unsigned i = 0;
+	while (i < ARRAY_SIZE(mcf_gpio_chips))
+		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
+	return 0;
+}
+
+core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/5407/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/5407/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/5407/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/5407/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o gpio.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/54xx/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/54xx/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/54xx/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/54xx/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,115 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/54xx/config.c
+ *
+ *	Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
+ */
+
+/***************************************************************************/
+
+#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>
+#include <asm/m54xxsim.h>
+#include <asm/mcfuart.h>
+#include <asm/m54xxgpt.h>
+
+/***************************************************************************/
+
+static struct mcf_platform_uart m54xx_uart_platform[] = {
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE1,
+		.irq		= 64 + 35,
+	},
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE2,
+		.irq		= 64 + 34,
+	},
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE3,
+		.irq		= 64 + 33,
+	},
+	{
+		.mapbase	= MCF_MBAR + MCFUART_BASE4,
+		.irq		= 64 + 32,
+	},
+};
+
+static struct platform_device m54xx_uart = {
+	.name			= "mcfuart",
+	.id			= 0,
+	.dev.platform_data	= m54xx_uart_platform,
+};
+
+static struct platform_device *m54xx_devices[] __initdata = {
+	&m54xx_uart,
+};
+
+
+/***************************************************************************/
+
+static void __init m54xx_uart_init_line(int line, int irq)
+{
+	int rts_cts;
+
+	/* enable io pins */
+	switch (line) {
+	case 0:
+		rts_cts = 0; break;
+	case 1:
+		rts_cts = MCF_PAR_PSC_RTS_RTS; break;
+	case 2:
+		rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
+	case 3:
+		rts_cts = 0; break;
+	}
+	__raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
+						MCF_MBAR + MCF_PAR_PSC(line));
+}
+
+static void __init m54xx_uarts_init(void)
+{
+	const int nrlines = ARRAY_SIZE(m54xx_uart_platform);
+	int line;
+
+	for (line = 0; (line < nrlines); line++)
+		m54xx_uart_init_line(line, m54xx_uart_platform[line].irq);
+}
+
+/***************************************************************************/
+
+static void mcf54xx_reset(void)
+{
+	/* disable interrupts and enable the watchdog */
+	asm("movew #0x2700, %sr\n");
+	__raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
+	__raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
+	__raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
+						MCF_MBAR + MCF_GPT_GMS0);
+}
+
+/***************************************************************************/
+
+void __init config_BSP(char *commandp, int size)
+{
+	mach_reset = mcf54xx_reset;
+	m54xx_uarts_init();
+}
+
+/***************************************************************************/
+
+static int __init init_BSP(void)
+{
+
+	platform_add_devices(m54xx_devices, ARRAY_SIZE(m54xx_devices));
+	return 0;
+}
+
+arch_initcall(init_BSP);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/54xx/firebee.c linux-libre-2.6.39-gnu/arch/m68k/platform/54xx/firebee.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/54xx/firebee.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/54xx/firebee.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,86 @@
+/***************************************************************************/
+
+/*
+ *	firebee.c -- extra startup code support for the FireBee boards
+ *
+ *	Copyright (C) 2011, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/partitions.h>
+#include <linux/mtd/physmap.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+/*
+ *	8MB of NOR flash fitted to the FireBee board.
+ */
+#define	FLASH_PHYS_ADDR		0xe0000000	/* Physical address of flash */
+#define	FLASH_PHYS_SIZE		0x00800000	/* Size of flash */
+
+#define	PART_BOOT_START		0x00000000	/* Start at bottom of flash */
+#define	PART_BOOT_SIZE		0x00040000	/* 256k in size */
+#define	PART_IMAGE_START	0x00040000	/* Start after boot loader */
+#define	PART_IMAGE_SIZE		0x006c0000	/* Most of flash */
+#define	PART_FPGA_START		0x00700000	/* Start at offset 7MB */
+#define	PART_FPGA_SIZE		0x00100000	/* 1MB in size */
+
+static struct mtd_partition firebee_flash_parts[] = {
+	{
+		.name	= "dBUG",
+		.offset	= PART_BOOT_START,
+		.size	= PART_BOOT_SIZE,
+	},
+	{
+		.name	= "FPGA",
+		.offset	= PART_FPGA_START,
+		.size	= PART_FPGA_SIZE,
+	},
+	{
+		.name	= "image",
+		.offset	= PART_IMAGE_START,
+		.size	= PART_IMAGE_SIZE,
+	},
+};
+
+static struct physmap_flash_data firebee_flash_data = {
+	.width		= 2,
+	.nr_parts	= ARRAY_SIZE(firebee_flash_parts),
+	.parts		= firebee_flash_parts,
+};
+
+static struct resource firebee_flash_resource = {
+	.start		= FLASH_PHYS_ADDR,
+	.end		= FLASH_PHYS_ADDR + FLASH_PHYS_SIZE,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct platform_device firebee_flash = {
+	.name		= "physmap-flash",
+	.id		= 0,
+	.dev		= {
+		.platform_data = &firebee_flash_data,
+	},
+	.num_resources	= 1,
+	.resource	= &firebee_flash_resource,
+};
+
+/***************************************************************************/
+
+static int __init init_firebee(void)
+{
+	platform_device_register(&firebee_flash);
+	return 0;
+}
+
+arch_initcall(init_firebee);
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/54xx/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/54xx/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/54xx/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/54xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,19 @@
+#
+# Makefile for the m68knommu linux kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
+# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-y := config.o
+obj-$(CONFIG_FIREBEE) += firebee.o
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/bootlogo.h linux-libre-2.6.39-gnu/arch/m68k/platform/68328/bootlogo.h
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/bootlogo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/bootlogo.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,270 @@
+#define bootlogo_width 160
+#define bootlogo_height 160
+static unsigned char bootlogo_bits[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x08, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00,
+  0x00, 0xff, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0xf8, 0x80, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x50, 0x04, 0x00, 0x00, 0x00, 0x78, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x00, 0x00,
+  0x00, 0x78, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x40,
+  0xa8, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x28, 0x01, 0x00, 0x00,
+  0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x20, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70,
+  0x54, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x80, 0x01, 0x3a, 0x78, 0x80, 0x0e,
+  0x50, 0xc0, 0x03, 0x0e, 0x00, 0x20, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
+  0x00, 0x3e, 0xf0, 0x83, 0x1f, 0xfc, 0xe0, 0x0f, 0x78, 0xf8, 0x87, 0x1f,
+  0x00, 0x18, 0x00, 0x30, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0xc3,
+  0x1f, 0xfc, 0xe0, 0x0f, 0x78, 0xf8, 0x87, 0x0f, 0x00, 0x20, 0x00, 0x10,
+  0x55, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xc0, 0x03, 0x9f, 0xf3, 0x80, 0x0f,
+  0x78, 0x80, 0xc7, 0x0e, 0x00, 0x18, 0x00, 0x20, 0xaa, 0x00, 0x00, 0x00,
+  0x00, 0x1e, 0xe0, 0x03, 0x9f, 0xf1, 0x80, 0x07, 0x78, 0x80, 0x67, 0x00,
+  0x00, 0x24, 0x00, 0x18, 0x55, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x01,
+  0x5e, 0xf0, 0x80, 0x07, 0x3c, 0x00, 0x2f, 0x00, 0x00, 0x14, 0x00, 0x20,
+  0xaa, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x01, 0x7f, 0xf0, 0x80, 0x07,
+  0x3c, 0x00, 0x3f, 0x00, 0x00, 0x08, 0x00, 0x18, 0x55, 0x00, 0x00, 0x00,
+  0x00, 0x0f, 0xe0, 0x00, 0x3f, 0xf0, 0xc0, 0x03, 0x1e, 0x00, 0x1f, 0x00,
+  0x00, 0x14, 0x00, 0x28, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xf0, 0x00,
+  0x1f, 0xf0, 0xc0, 0x03, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x00, 0x0c,
+  0x54, 0x00, 0x00, 0x00, 0x80, 0x07, 0x78, 0x00, 0x1f, 0x78, 0xc0, 0x03,
+  0x1f, 0x00, 0x1e, 0x00, 0x00, 0x0a, 0x00, 0x12, 0xa8, 0x00, 0x00, 0x00,
+  0x80, 0x07, 0x78, 0x00, 0x1f, 0x78, 0xe0, 0x03, 0x1f, 0x00, 0x1f, 0x00,
+  0x00, 0x04, 0x00, 0x0a, 0x54, 0x00, 0x00, 0x00, 0x80, 0x07, 0x78, 0x80,
+  0x0f, 0x78, 0xe0, 0x03, 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x0a, 0x00, 0x08,
+  0x50, 0x01, 0x00, 0x00, 0x84, 0x03, 0x78, 0x80, 0x07, 0x3c, 0xe0, 0xc1,
+  0x0f, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x00, 0x06, 0xa8, 0x00, 0x00, 0x00,
+  0xc0, 0x03, 0x78, 0xc0, 0x07, 0x3c, 0xe0, 0xc1, 0x0f, 0x00, 0x1f, 0x00,
+  0x00, 0x0a, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0xc2, 0x01, 0x38, 0xc0,
+  0x07, 0x3c, 0xe0, 0x60, 0x0f, 0x80, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x07,
+  0xa0, 0x00, 0x00, 0x80, 0xe0, 0x01, 0x3c, 0xc0, 0x07, 0x3c, 0xf0, 0xa0,
+  0x07, 0xc0, 0x1c, 0x00, 0x00, 0x0a, 0x80, 0x08, 0xa0, 0x02, 0x00, 0xa0,
+  0xe0, 0x21, 0x1c, 0xc0, 0x03, 0x1c, 0x71, 0x90, 0x47, 0x40, 0x3c, 0x04,
+  0x00, 0x05, 0x80, 0x06, 0xa0, 0x02, 0x00, 0x20, 0xe0, 0x31, 0x1e, 0xc3,
+  0x03, 0x1e, 0x79, 0x98, 0x47, 0x60, 0x38, 0x04, 0x00, 0x15, 0x40, 0x0a,
+  0xa0, 0x0a, 0x00, 0x1a, 0xe0, 0x19, 0x9e, 0xe1, 0x01, 0x9e, 0x78, 0xcc,
+  0xa7, 0x32, 0x78, 0x02, 0x80, 0x2a, 0x40, 0x05, 0x80, 0x2a, 0x00, 0x05,
+  0xe0, 0x0d, 0x9e, 0xe0, 0x01, 0xde, 0x78, 0xc6, 0x97, 0x1b, 0x78, 0x03,
+  0x80, 0x52, 0x30, 0x0a, 0x00, 0x95, 0xd2, 0x0a, 0xe0, 0x0f, 0xfe, 0xe0,
+  0x00, 0x7e, 0xf8, 0x87, 0x9f, 0x0f, 0xf8, 0x01, 0x00, 0xa1, 0x0e, 0x15,
+  0x80, 0x55, 0x55, 0x01, 0xe0, 0x01, 0x3c, 0xf0, 0x00, 0x3c, 0xf0, 0x80,
+  0x8f, 0x0f, 0x70, 0x00, 0x00, 0x81, 0x02, 0x14, 0x00, 0x54, 0x55, 0x00,
+  0xc0, 0x01, 0x3c, 0x00, 0x00, 0x0c, 0x60, 0x00, 0x07, 0x03, 0x70, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x01, 0x00, 0x11, 0x09, 0x00, 0x04, 0x00, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
+  0x00, 0x20, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0x32, 0x49, 0x49, 0x91,
+  0x24, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x49, 0x0a, 0x09, 0xc9, 0x92, 0x14, 0x81, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x49,
+  0x18, 0x01, 0x49, 0x92, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x30, 0x01, 0x49, 0x92,
+  0x14, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x08, 0x69, 0x22, 0x09, 0x49, 0xd2, 0x24, 0x24, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51,
+  0x1a, 0x09, 0x49, 0xa2, 0x44, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x87, 0x08, 0x00, 0x00, 0x00,
+  0xf2, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0xf0, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x88, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09,
+  0x09, 0x01, 0x10, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80,
+  0x88, 0x86, 0x48, 0x04, 0x09, 0x08, 0x01, 0x01, 0x09, 0x01, 0x10, 0x71,
+  0x88, 0x66, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, 0x88, 0x89, 0x48, 0x84,
+  0x08, 0x08, 0x01, 0x01, 0x09, 0x01, 0x10, 0x89, 0x88, 0x99, 0x00, 0x00,
+  0x00, 0x40, 0x24, 0x80, 0x88, 0x88, 0x88, 0x82, 0xf8, 0xf0, 0xe0, 0x80,
+  0xf0, 0xf8, 0x13, 0x81, 0x88, 0x88, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80,
+  0x88, 0x88, 0x08, 0x81, 0x08, 0x09, 0x01, 0x41, 0x08, 0x01, 0xf0, 0xf0,
+  0x88, 0x88, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, 0x88, 0x88, 0x88, 0x42,
+  0x08, 0x09, 0x01, 0x21, 0x08, 0x01, 0x10, 0x88, 0x88, 0x88, 0x00, 0x00,
+  0x00, 0x40, 0x46, 0x88, 0x88, 0x88, 0x4c, 0x44, 0x08, 0x09, 0x09, 0x11,
+  0x08, 0x01, 0x10, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x80, 0x85, 0x87,
+  0x88, 0x08, 0x4b, 0x24, 0xf0, 0xf0, 0xf0, 0xf8, 0xf1, 0x00, 0x10, 0x70,
+  0x89, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x08, 0x02, 0x04, 0x00,
+  0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x1f, 0x00, 0x00, 0x48, 0x62, 0xc4, 0x31, 0x4a, 0x18, 0x3c, 0x03,
+  0x21, 0x45, 0x92, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x1f, 0x00, 0x00,
+  0x48, 0x92, 0x24, 0x48, 0xb6, 0x24, 0x88, 0x04, 0x21, 0x4b, 0x92, 0x00,
+  0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xa8, 0xf2, 0x24, 0x48,
+  0x92, 0x3c, 0x88, 0x04, 0x21, 0x49, 0x62, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x10, 0x11, 0x24, 0x48, 0x92, 0x04, 0x88, 0x04,
+  0x21, 0x49, 0x62, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00,
+  0x10, 0x11, 0x24, 0x48, 0x92, 0x04, 0x88, 0x04, 0x21, 0x49, 0x93, 0x00,
+  0x00, 0x00, 0x80, 0xff, 0xcf, 0x7e, 0x00, 0x00, 0x10, 0xe1, 0xc4, 0x31,
+  0x92, 0x38, 0x30, 0x03, 0x2f, 0x89, 0x92, 0x00, 0x00, 0x00, 0x80, 0xe3,
+  0x07, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x03, 0x7e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0xc9, 0x23, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95,
+  0x33, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdd, 0xfb, 0x7e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x1d, 0xf8, 0x7e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x40, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9b,
+  0x70, 0x7e, 0x00, 0x00, 0x08, 0x00, 0xe0, 0x00, 0x02, 0x00, 0x47, 0x80,
+  0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x80, 0x03, 0x00, 0x7e, 0x00, 0x00,
+  0x3c, 0xa3, 0x20, 0x31, 0x52, 0x02, 0x49, 0xcc, 0x3f, 0xa3, 0x94, 0x08,
+  0x00, 0x00, 0x00, 0x27, 0x02, 0x7e, 0x00, 0x00, 0x88, 0xe4, 0x20, 0x41,
+  0xb2, 0x05, 0x49, 0x90, 0x88, 0xe4, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x7e, 0x00, 0x00, 0x88, 0x24, 0xe0, 0x70, 0x92, 0x04, 0x47, 0x9c,
+  0x88, 0x24, 0x24, 0x09, 0x00, 0x00, 0x00, 0x13, 0x48, 0x7e, 0x00, 0x00,
+  0x88, 0x24, 0x20, 0x48, 0x92, 0x04, 0x41, 0x92, 0x88, 0x24, 0x24, 0x01,
+  0x00, 0x00, 0x00, 0x43, 0x00, 0xfe, 0x00, 0x00, 0x88, 0x24, 0x20, 0x48,
+  0x92, 0x04, 0x41, 0x92, 0x88, 0x24, 0x24, 0x09, 0x00, 0x00, 0x00, 0x07,
+  0x94, 0xce, 0x00, 0x00, 0x08, 0x23, 0x20, 0xb0, 0x92, 0x04, 0x41, 0x2c,
+  0x0b, 0x23, 0x24, 0x09, 0x00, 0x00, 0x00, 0x49, 0x02, 0xce, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x11, 0x08, 0xdc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+  0x01, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x01, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01,
+  0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf0, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x70, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00,
+  0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
+  0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x1f, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
+  0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00,
+  0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0xfe, 0x0f,
+  0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x08, 0x00,
+  0x00, 0xc0, 0x03, 0x00, 0x78, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x40, 0x10,
+  0x12, 0x10, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
+  0x84, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x20, 0x26, 0x0a, 0x10, 0x9d, 0x39,
+  0xa6, 0xb2, 0x0a, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x02, 0x00, 0xfe, 0x0f,
+  0x00, 0x00, 0x20, 0x21, 0x06, 0x28, 0x25, 0x4a, 0xa9, 0x8a, 0x09, 0x00,
+  0x00, 0xe0, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x20, 0x21,
+  0x0e, 0x38, 0xa5, 0x4b, 0xa9, 0xb2, 0x09, 0x00, 0x00, 0xf0, 0x01, 0x22,
+  0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x20, 0x21, 0x12, 0x44, 0xa5, 0x4a,
+  0x49, 0xa1, 0x0a, 0x00, 0x00, 0xf8, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f,
+  0x00, 0x00, 0x20, 0x26, 0x52, 0x44, 0x9d, 0x4d, 0x46, 0x99, 0x0a, 0x00,
+  0x00, 0xfc, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x40, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0xb2,
+  0x84, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x6e, 0x78, 0x00, 0xfc, 0x1f,
+  0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfc, 0x01, 0x02, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x02,
+  0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0xfc, 0x0f,
+  0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x24, 0x06, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x40, 0x10,
+  0x1e, 0x20, 0x90, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
+  0x00, 0x80, 0xfc, 0x03, 0x00, 0x00, 0x20, 0x26, 0x22, 0x20, 0xf9, 0x89,
+  0x32, 0xe7, 0x08, 0x00, 0x00, 0x92, 0x38, 0x00, 0x00, 0x00, 0xfc, 0x01,
+  0x00, 0x00, 0x20, 0x21, 0x22, 0xa0, 0x92, 0x88, 0x4a, 0x29, 0x15, 0x00,
+  0x00, 0x00, 0x78, 0x00, 0x00, 0x40, 0xfa, 0x04, 0x00, 0x00, 0x20, 0x21,
+  0x22, 0xa0, 0x93, 0x88, 0x4a, 0x29, 0x1d, 0x00, 0x00, 0x11, 0xf2, 0x00,
+  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0x21, 0x22, 0xa8, 0x90, 0x88,
+  0x4a, 0x29, 0x05, 0x00, 0x48, 0x40, 0xf0, 0x01, 0x00, 0x80, 0x14, 0x04,
+  0x00, 0x00, 0x20, 0x26, 0x9e, 0x10, 0x93, 0x78, 0x32, 0x29, 0x19, 0x00,
+  0x00, 0x09, 0xe0, 0x03, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x40, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc5, 0x03,
+  0x00, 0x40, 0x22, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0xc0, 0x07, 0x00, 0x20, 0x08, 0x04,
+  0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x50, 0x90, 0x03, 0x00, 0xb0, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+  0x00, 0x38, 0x22, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x48, 0x04, 0x44, 0x00, 0x00, 0x3c, 0x08, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0xbf, 0x40, 0x42, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x24, 0x80, 0x48, 0x02,
+  0xc0, 0x1f, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0xf0, 0x3f, 0x09, 0x00,
+  0x00, 0x10, 0x24, 0x48, 0x10, 0x12, 0x41, 0x52, 0x24, 0x09, 0x46, 0x71,
+  0x90, 0x20, 0x02, 0xfc, 0xff, 0x1f, 0x80, 0x22, 0x00, 0x90, 0x24, 0x49,
+  0x12, 0x92, 0x40, 0xb2, 0x24, 0x09, 0xc9, 0x49, 0x04, 0x80, 0x90, 0xfc,
+  0xff, 0xbf, 0x24, 0x00, 0x00, 0x90, 0x24, 0x49, 0x12, 0x92, 0x40, 0x92,
+  0x24, 0x06, 0x49, 0x48, 0x50, 0x0a, 0x02, 0xfe, 0xff, 0x3f, 0x00, 0x05,
+  0x00, 0x50, 0xa5, 0x4a, 0x15, 0x92, 0x40, 0x92, 0x24, 0x06, 0x49, 0x48,
+  0x80, 0x40, 0x48, 0xfe, 0xff, 0x3f, 0x49, 0x00, 0x00, 0x20, 0x42, 0x84,
+  0x88, 0x1a, 0x41, 0x92, 0x34, 0x49, 0x49, 0x68, 0x00, 0x38, 0x10, 0x07,
+  0x00, 0x60, 0x80, 0x00, 0x00, 0x20, 0x42, 0x84, 0x88, 0x14, 0x4e, 0x92,
+  0x28, 0x49, 0x46, 0x50, 0x00, 0x80, 0x83, 0x01, 0x00, 0xa0, 0x6a, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
+  0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, };
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/bootlogo.pl linux-libre-2.6.39-gnu/arch/m68k/platform/68328/bootlogo.pl
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/bootlogo.pl	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/bootlogo.pl	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+
+$_ = join("", <>);
+
+s/(0x[0-9a-f]{2})/sprintf("0x%.2x",ord(pack("b8",unpack("B8",chr(hex($1))))))/gei;
+
+s/^ /	.byte /gm;
+s/[,};]+$//gm;
+s/^static.*//gm;
+
+print $_;
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/68328/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,52 @@
+/***************************************************************************/
+
+/*
+ *  linux/arch/m68knommu/platform/68328/config.c
+ *
+ *  Copyright (C) 1993 Hamish Macdonald
+ *  Copyright (C) 1999 D. Jeff Dionne
+ *
+ * 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.
+ *
+ * VZ Support/Fixes             Evan Stawnyczy <e@lineo.ca>
+ */
+
+/***************************************************************************/
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <asm/machdep.h>
+#include <asm/MC68328.h>
+
+/***************************************************************************/
+
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
+
+/***************************************************************************/
+
+void m68328_reset (void)
+{
+  local_irq_disable();
+  asm volatile ("moveal #0x10c00000, %a0;\n\t"
+		"moveb #0, 0xFFFFF300;\n\t"
+		"moveal 0(%a0), %sp;\n\t"
+		"moveal 4(%a0), %a0;\n\t"
+		"jmp (%a0);");
+}
+
+/***************************************************************************/
+
+void config_BSP(char *command, int len)
+{
+  printk(KERN_INFO "\n68328 support D. Jeff Dionne <jeff@uclinux.org>\n");
+  printk(KERN_INFO "68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
+  printk(KERN_INFO "68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n");
+
+  mach_gettod = m68328_timer_gettod;
+  mach_reset = m68328_reset;
+}
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/entry.S linux-libre-2.6.39-gnu/arch/m68k/platform/68328/entry.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,263 @@
+/*
+ *  linux/arch/m68knommu/platform/68328/entry.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/traps.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+
+.text
+
+.globl system_call
+.globl resume
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_call_table
+.globl ret_from_interrupt
+.globl bad_interrupt
+.globl inthandler1
+.globl inthandler2
+.globl inthandler3
+.globl inthandler4
+.globl inthandler5
+.globl inthandler6
+.globl inthandler7
+
+badsys:
+	movel	#-ENOSYS,%sp@(PT_OFF_D0)
+	jra	ret_from_exception
+
+do_trace:
+	movel	#-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
+	subql	#4,%sp
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_enter
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	movel	%sp@(PT_OFF_ORIG_D0),%d1
+	movel	#-ENOSYS,%d0
+	cmpl	#NR_syscalls,%d1
+	jcc	1f
+	lsl	#2,%d1
+	lea	sys_call_table, %a0
+	jbsr	%a0@(%d1)
+
+1:	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
+	subql	#4,%sp			/* dummy return address */
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_leave
+
+ret_from_signal:
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jra	ret_from_exception
+
+ENTRY(system_call)
+	SAVE_ALL
+
+	/* save top of frame*/
+	pea	%sp@
+	jbsr	set_esp0
+	addql	#4,%sp
+
+	movel	%sp@(PT_OFF_ORIG_D0),%d0
+
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1
+	movel	%d1,%a2
+	btst	#(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
+	jne	do_trace
+	cmpl	#NR_syscalls,%d0
+	jcc	badsys
+	lsl	#2,%d0
+	lea	sys_call_table,%a0
+	movel	%a0@(%d0), %a0
+	jbsr	%a0@
+	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/
+
+ret_from_exception:
+	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
+	jeq	Luser_return		/* if so, skip resched, signals*/
+
+Lkernel_return:
+	RESTORE_ALL
+
+Luser_return:
+	/* only allow interrupts when we are really the last one on the*/
+	/* kernel stack, otherwise stack overflow can occur during*/
+	/* heavy interrupt load*/
+	andw	#ALLOWINT,%sr
+
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1
+	movel	%d1,%a2
+1:
+	move	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
+	jne	Lwork_to_do
+	RESTORE_ALL
+
+Lwork_to_do:
+	movel	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
+	btst	#TIF_NEED_RESCHED,%d1
+	jne	reschedule
+
+Lsignal_return:
+	subql	#4,%sp			/* dummy return address*/
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	bsrw	do_signal
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jra	1b
+
+/*
+ * This is the main interrupt handler, responsible for calling process_int()
+ */
+inthandler1:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#65,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler2:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#66,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler3:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#67,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler4:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#68,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler5:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#69,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler6:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#70,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler7:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	#71,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+inthandler:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and	#0x3ff, %d0
+
+	movel	%sp,%sp@-
+	movel	%d0,%sp@- 		/*  put vector # on stack*/
+	jbsr	process_int		/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+ret_from_interrupt:
+	jeq	1f
+2:
+	RESTORE_ALL
+1:
+	moveb	%sp@(PT_OFF_SR), %d0
+	and	#7, %d0
+	jhi	2b
+
+	/* check if we need to do software interrupts */
+	jeq	ret_from_exception
+
+	pea	ret_from_exception
+	jra	do_softirq
+
+
+/*
+ * Handler for uninitialized and spurious interrupts.
+ */
+ENTRY(bad_interrupt)
+	addql	#1,num_spurious
+	rte
+
+/*
+ * Beware - when entering resume, prev (the current task) is
+ * in a0, next (the new task) is in a1,so don't change these
+ * registers until their contents are no longer needed.
+ */
+ENTRY(resume)
+	movel	%a0,%d1				/* save prev thread in d1 */
+	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
+	movel	%usp,%a2			/* save usp */
+	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
+
+	SAVE_SWITCH_STACK
+	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+	RESTORE_SWITCH_STACK
+
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
+	movel	%a0,%usp
+	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
+	rts
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-de2.S linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-de2.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-de2.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-de2.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,128 @@
+
+#define	MEM_END	0x00800000	/* Memory size 8Mb */
+
+#undef CRT_DEBUG
+
+.macro	PUTC CHAR
+#ifdef CRT_DEBUG
+	moveq	#\CHAR, %d7
+	jsr	putc
+#endif
+.endm
+
+	.global	_start
+	.global _rambase
+	.global _ramvec
+	.global	_ramstart
+	.global	_ramend
+	
+	.data
+
+/*
+ *	Set up the usable of RAM stuff
+ */
+_rambase:
+	.long	0
+_ramvec:
+	.long	0
+_ramstart:
+	.long	0
+_ramend:
+	.long	0
+
+	.text
+
+_start:
+
+/*
+ * Setup initial stack
+ */
+	/* disable all interrupts */
+	movew	#0x2700, %sr
+	movel	#-1, 0xfffff304
+	movel	#MEM_END-4, %sp
+
+	PUTC	'\r'
+	PUTC	'\n'
+	PUTC	'A'
+	PUTC	'B'
+
+/*
+ *	Determine end of RAM
+ */
+
+	movel	#MEM_END, %a0
+	movel	%a0, _ramend
+
+	PUTC	'C'
+
+/*
+ *	Move ROM filesystem above bss :-)
+ */
+
+	moveal	#_sbss, %a0			/* romfs at the start of bss */
+	moveal	#_ebss, %a1			/* Set up destination  */
+	movel	%a0, %a2			/* Copy of bss start */
+
+	movel	8(%a0), %d1			/* Get size of ROMFS */
+	addql	#8, %d1				/* Allow for rounding */
+	andl	#0xfffffffc, %d1	/* Whole words */
+
+	addl	%d1, %a0			/* Copy from end */
+	addl	%d1, %a1			/* Copy from end */
+	movel	%a1, _ramstart		/* Set start of ram */
+
+1:
+	movel	-(%a0), %d0			/* Copy dword */
+	movel	%d0, -(%a1)
+	cmpl	%a0, %a2			/* Check if at end */
+	bne	1b
+
+	PUTC	'D'
+
+/*
+ * Initialize BSS segment to 0
+ */
+
+	lea	_sbss, %a0
+	lea	_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+2:	cmpal	%a0, %a1
+	beq	1f
+	clrl	(%a0)+
+	bra	2b
+1:
+
+	PUTC	'E'
+
+/*
+ * Load the current task pointer and stack
+ */
+
+	lea	init_thread_union, %a0
+	lea	0x2000(%a0), %sp
+
+	PUTC	'F'
+	PUTC	'\r'
+	PUTC	'\n'
+
+/*
+ * Go
+ */
+
+	jmp	start_kernel
+
+/*
+ * Local functions
+ */
+ 
+#ifdef CRT_DEBUG
+putc:
+	moveb	%d7, 0xfffff907
+1:
+	movew	0xfffff906, %d7
+	andw	#0x2000, %d7
+	beq	1b
+	rts
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-pilot.S linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-pilot.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-pilot.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-pilot.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,222 @@
+/*
+ * linux/arch/m68knommu/platform/68328/head-pilot.S
+ * - A startup file for the MC68328
+ *
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
+ *                     Kenneth Albanowski <kjahds@kjahds.com>,
+ *                     The Silver Hammer Group, Ltd.
+ *
+ * (c) 1995, Dionne & Associates
+ * (c) 1995, DKG Display Tech.
+ */
+
+#define ASSEMBLY
+
+#define IMMED #
+#define	DBG_PUTC(x)	moveb IMMED x, 0xfffff907
+
+
+.global _stext
+.global _start
+
+.global _rambase
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global penguin_bits
+
+#ifdef CONFIG_PILOT
+
+#define IMR 0xFFFFF304
+
+	.data
+	.align 16
+
+penguin_bits:	
+#include "bootlogo.rh"
+
+#endif
+
+/*****************************************************************************/
+
+.data
+
+/*
+ *      Set up the usable of RAM stuff. Size of RAM is determined then
+ *      an initial stack set up at the end.
+ */
+.align 4
+_ramvec:
+.long   0
+_rambase:
+.long   0
+_ramstart:
+.long   0
+_ramend:
+.long   0
+
+.text
+	
+_start:
+_stext:
+
+
+#ifdef CONFIG_M68328
+
+#ifdef CONFIG_PILOT
+	.byte 0x4e, 0xfa, 0x00, 0x0a /* Jmp +X bytes */
+	.byte 'b', 'o', 'o', 't'
+	.word 10000
+
+	nop
+#endif
+
+	moveq	#0, %d0
+	movew   %d0, 0xfffff618 /* Watchdog off */
+	movel	#0x00011f07, 0xfffff114 /* CS A1 Mask */
+
+	movew	#0x0800, 0xfffff906 /* Ignore CTS */
+	movew	#0x010b, 0xfffff902 /* BAUD to 9600 */
+
+	movew	#0x2410, 0xfffff200 /* PLLCR */
+	movew	#0x123, 0xfffff202 /* PLLFSR */
+
+#ifdef CONFIG_PILOT
+	moveb	#0, 0xfffffA27 /* LCKCON */
+	movel   #_start, 0xfffffA00 /* LSSA */
+	moveb   #0xa, 0xfffffA05 /* LVPW */
+	movew	#0x9f, 0xFFFFFa08 /* LXMAX */
+	movew	#0x9f, 0xFFFFFa0a /* LYMAX */
+	moveb   #9, 0xfffffa29 /* LBAR */
+	moveb   #0, 0xfffffa25 /* LPXCD */
+	moveb	#0x04, 0xFFFFFa20 /* LPICF */
+	moveb	#0x58, 0xfffffA27 /* LCKCON */
+	moveb	#0x85, 0xfffff429 /* PFDATA */
+	moveb	#0xd8, 0xfffffA27 /* LCKCON */
+	moveb	#0xc5, 0xfffff429 /* PFDATA */
+	moveb	#0xd5, 0xfffff429 /* PFDATA */
+
+	moveal	#0x00100000, %a3
+	moveal	#0x100ffc00, %a4
+#endif /* CONFIG_PILOT */
+
+#endif /* CONFIG_M68328 */
+
+	movew   #0x2700, %sr
+	lea	%a4@(-4), %sp
+
+	DBG_PUTC('\r')
+	DBG_PUTC('\n')
+	DBG_PUTC('A')
+
+   	moveq   #0,%d0
+	movew	#16384, %d0  /* PLL settle wait loop */
+L0:
+	subw	#1, %d0
+	bne	L0
+
+	DBG_PUTC('B')
+
+	/* Copy command line from beginning of RAM (+16) to end of bss */
+	movel	#CONFIG_VECTORBASE, %d7
+	addl	#16, %d7
+	moveal	%d7, %a0
+	moveal	#_ebss, %a1
+	lea	%a1@(512), %a2
+
+	DBG_PUTC('C')
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+L2:
+	movel	%a0@+, %d0
+	movel	%d0, %a1@+
+	cmpal	%a1, %a2
+	bhi	L2
+
+	/* Copy data+init segment from ROM to RAM */
+	moveal	#_etext, %a0
+	moveal	#_sdata, %a1
+	moveal	#__init_end, %a2
+
+	DBG_PUTC('D')
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+	movel	%a0@+, %d0
+	movel	%d0, %a1@+
+	cmpal	%a1, %a2
+	bhi	LD1
+
+	DBG_PUTC('E')
+
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	L1
+
+	DBG_PUTC('F')
+
+	/* Copy command line from end of bss to command line */
+	moveal	#_ebss, %a0
+	moveal	#command_line, %a1
+	lea	%a1@(512), %a2
+
+	DBG_PUTC('G')
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+L3:
+	movel	%a0@+, %d0
+	movel	%d0, %a1@+
+	cmpal	%a1, %a2
+	bhi	L3
+
+	movel	#_sdata, %d0	
+	movel	%d0, _rambase	
+	movel	#_ebss,	%d0
+	movel	%d0, _ramstart
+
+	movel	%a4, %d0
+	subl	#4096, %d0	/* Reserve 4K of stack */
+	moveq	#79, %d7
+	movel	%d0, _ramend
+
+	movel	%a3, %d0
+	movel	%d0, rom_length
+
+	pea	0
+	pea	env
+	pea	%sp@(4)
+	pea	0
+
+	DBG_PUTC('H')
+
+#ifdef CONFIG_PILOT
+	movel	#penguin_bits, 0xFFFFFA00
+	moveb	#10, 0xFFFFFA05
+	movew	#160, 0xFFFFFA08
+	movew	#160, 0xFFFFFA0A
+#endif /* CONFIG_PILOT */
+
+	DBG_PUTC('I')
+
+	lea	init_thread_union, %a0
+	lea	0x2000(%a0), %sp
+
+	DBG_PUTC('J')
+	DBG_PUTC('\r')
+	DBG_PUTC('\n')
+
+	jsr	start_kernel
+_exit:
+
+	jmp	_exit
+
+
+	.data
+env:
+	.long	0
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-ram.S linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-ram.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-ram.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-ram.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,141 @@
+
+	.global __main
+	.global __rom_start
+
+        .global _rambase
+        .global _ramstart
+	
+	.global splash_bits
+	.global _start
+	.global _stext
+	.global _edata
+
+#define DEBUG
+#define ROM_OFFSET 0x10C00000
+#define STACK_GAURD 0x10
+
+	.text
+	
+_start:
+_stext:
+	movew	#0x2700, %sr            /* Exceptions off! */
+
+#if 0
+	/* Init chip registers.  uCsimm specific */
+	moveb	#0x00,   0xfffffb0b	/* Watchdog off */
+	moveb	#0x10,   0xfffff000	/* SCR */
+
+	movew   #0x2400, 0xfffff200	/* PLLCR */
+	movew   #0x0123, 0xfffff202	/* PLLFSR */
+
+	moveb	#0x00,   0xfffff40b	/* enable chip select */
+	moveb	#0x00,   0xfffff423	/* enable /DWE */
+	moveb	#0x08,   0xfffffd0d	/* disable hardmap */
+	moveb	#0x07,   0xfffffd0e	/* level 7 interrupt clear */
+
+	movew	#0x8600, 0xfffff100	/* FLASH at 0x10c00000 */
+	movew	#0x018b, 0xfffff110	/* 2Meg, enable, 0ws */
+
+	movew	#0x8f00, 0xfffffc00	/* DRAM configuration */
+	movew	#0x9667, 0xfffffc02	/* DRAM control */
+	movew	#0x0000, 0xfffff106	/* DRAM at 0x00000000 */
+	movew	#0x068f, 0xfffff116	/* 8Meg, enable, 0ws */
+
+	moveb	#0x40,   0xfffff300	/* IVR */
+	movel	#0x007FFFFF, %d0	/* IMR */
+	movel	%d0,     0xfffff304
+
+	moveb	0xfffff42b, %d0
+	andb	#0xe0,	 %d0
+	moveb	%d0,	 0xfffff42b
+
+	moveb	#0x08,   0xfffff907	/* Ignore CTS */
+	movew	#0x010b, 0xfffff902	/* BAUD to 9600 */
+	movew	#0xe100, 0xfffff900	/* enable */
+#endif
+
+	movew	#16384, %d0  /* PLL settle wait loop */
+L0:
+	subw	#1, %d0
+	bne	L0
+#ifdef DEBUG
+	moveq	#70, %d7		/* 'F' */
+	moveb	%d7,0xfffff907          /* No absolute addresses */
+pclp1:
+	movew	0xfffff906, %d7
+	andw	#0x2000, %d7
+	beq	pclp1
+#endif /* DEBUG */
+
+#ifdef DEBUG
+	moveq	#82, %d7		/* 'R' */
+	moveb	%d7,0xfffff907          /* No absolute addresses */
+pclp3:
+	movew	0xfffff906, %d7
+	andw	#0x2000, %d7
+	beq	pclp3
+#endif /* DEBUG */
+	moveal	#0x007ffff0, %ssp
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 >= %a1 */
+L1:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	L1
+
+#ifdef DEBUG
+	moveq	#67, %d7                /* 'C' */
+	jsr	putc
+#endif /* DEBUG */
+
+	pea	0
+	pea	env
+	pea	%sp@(4)
+	pea	0
+
+#ifdef DEBUG
+	moveq	#70, %d7		/* 'F' */
+	jsr	putc
+#endif /* DEBUG */
+
+lp:
+	jsr	start_kernel
+        jmp lp
+_exit:
+
+	jmp	_exit
+
+__main:
+	/* nothing */
+	rts
+
+#ifdef DEBUG
+putc:
+	moveb	%d7,0xfffff907
+pclp:
+	movew	0xfffff906, %d7
+	andw	#0x2000, %d7
+	beq	pclp
+	rts
+#endif /* DEBUG */
+
+	.data
+
+/*
+ *      Set up the usable of RAM stuff. Size of RAM is determined then
+ *      an initial stack set up at the end.
+ */
+.align 4
+_ramvec:
+.long   0
+_rambase:
+.long   0
+_ramstart:
+.long   0
+_ramend:
+.long   0
+
+env:
+	.long	0
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-rom.S linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-rom.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/head-rom.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/head-rom.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,110 @@
+	
+	.global _start
+	.global _stext
+
+	.global _rambase
+	.global _ramvec
+	.global _ramstart
+	.global _ramend
+
+#ifdef CONFIG_INIT_LCD
+	.global splash_bits
+#endif
+
+	.data
+
+/*
+ *      Set up the usable of RAM stuff. Size of RAM is determined then
+ *      an initial stack set up at the end.
+ */
+.align 4
+_ramvec:
+.long   0
+_rambase:
+.long   0
+_ramstart:
+.long   0
+_ramend:
+.long   0
+
+#define	RAMEND	(CONFIG_RAMBASE + CONFIG_RAMSIZE)
+
+#ifdef CONFIG_INIT_LCD
+splash_bits:
+#include "bootlogo.rh"
+#endif
+	
+	.text
+_start:
+_stext:	movew	#0x2700,%sr
+#ifdef CONFIG_INIT_LCD
+	movel	#splash_bits, 0xfffffA00 /* LSSA */
+	moveb	#0x28,   0xfffffA05	/* LVPW */
+	movew	#0x280,  0xFFFFFa08	/* LXMAX */
+	movew	#0x1df,  0xFFFFFa0a	/* LYMAX */
+	moveb	#0,      0xfffffa29	/* LBAR */
+	moveb	#0,      0xfffffa25	/* LPXCD */
+	moveb	#0x08,   0xFFFFFa20	/* LPICF */
+	moveb	#0x01,   0xFFFFFA21	/* -ve pol */
+	moveb	#0x81,   0xfffffA27	/* LCKCON */
+	movew	#0xff00, 0xfffff412	/* LCD pins */
+#endif
+	moveal  #RAMEND-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp
+	movew	#32767, %d0  /* PLL settle wait loop */
+1:	subq	#1, %d0
+	bne	1b
+
+	/* Copy data segment from ROM to RAM */
+	moveal	#_etext, %a0
+	moveal	#_sdata, %a1
+	moveal	#_edata, %a2
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+1:	movel	%a0@+, %a1@+
+	cmpal	%a1, %a2
+	bhi	1b
+
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+	/* Copy 0 to %a0 until %a0 == %a1 */
+	
+1:
+	clrl	%a0@+
+	cmpal	%a0, %a1
+	bhi	1b
+
+        movel   #_sdata, %d0    
+        movel   %d0, _rambase        
+        movel   #_ebss, %d0
+        movel   %d0, _ramstart
+	movel	#RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0
+	movel	%d0, _ramend
+	movel	#CONFIG_VECTORBASE,	%d0
+	movel	%d0, _ramvec
+	
+/*
+ * load the current task pointer and stack
+ */
+	lea	init_thread_union, %a0
+	lea	0x2000(%a0), %sp
+
+1:	jsr	start_kernel
+        bra 1b
+_exit:
+
+	jmp	_exit
+
+
+putc:
+	moveb	%d7,0xfffff907
+1:
+	movew	0xfffff906, %d7
+	andw	#0x2000, %d7
+	beq	1b
+	rts
+
+	.data
+env:
+	.long	0
+	.text
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/ints.c linux-libre-2.6.39-gnu/arch/m68k/platform/68328/ints.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/ints.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/ints.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,186 @@
+/*
+ * linux/arch/m68knommu/platform/68328/ints.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 1996 Roman Zippel
+ * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/traps.h>
+#include <asm/io.h>
+#include <asm/machdep.h>
+
+#if defined(CONFIG_M68328)
+#include <asm/MC68328.h>
+#elif defined(CONFIG_M68EZ328)
+#include <asm/MC68EZ328.h>
+#elif defined(CONFIG_M68VZ328)
+#include <asm/MC68VZ328.h>
+#endif
+
+/* assembler routines */
+asmlinkage void system_call(void);
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void trap3(void);
+asmlinkage void trap4(void);
+asmlinkage void trap5(void);
+asmlinkage void trap6(void);
+asmlinkage void trap7(void);
+asmlinkage void trap8(void);
+asmlinkage void trap9(void);
+asmlinkage void trap10(void);
+asmlinkage void trap11(void);
+asmlinkage void trap12(void);
+asmlinkage void trap13(void);
+asmlinkage void trap14(void);
+asmlinkage void trap15(void);
+asmlinkage void trap33(void);
+asmlinkage void trap34(void);
+asmlinkage void trap35(void);
+asmlinkage void trap36(void);
+asmlinkage void trap37(void);
+asmlinkage void trap38(void);
+asmlinkage void trap39(void);
+asmlinkage void trap40(void);
+asmlinkage void trap41(void);
+asmlinkage void trap42(void);
+asmlinkage void trap43(void);
+asmlinkage void trap44(void);
+asmlinkage void trap45(void);
+asmlinkage void trap46(void);
+asmlinkage void trap47(void);
+asmlinkage irqreturn_t bad_interrupt(int, void *);
+asmlinkage irqreturn_t inthandler(void);
+asmlinkage irqreturn_t inthandler1(void);
+asmlinkage irqreturn_t inthandler2(void);
+asmlinkage irqreturn_t inthandler3(void);
+asmlinkage irqreturn_t inthandler4(void);
+asmlinkage irqreturn_t inthandler5(void);
+asmlinkage irqreturn_t inthandler6(void);
+asmlinkage irqreturn_t inthandler7(void);
+
+extern e_vector *_ramvec;
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+/* The 68k family did not have a good way to determine the source
+ * of interrupts until later in the family.  The EC000 core does
+ * not provide the vector number on the stack, we vector everything
+ * into one vector and look in the blasted mask register...
+ * This code is designed to be fast, almost constant time, not clean!
+ */
+void process_int(int vec, struct pt_regs *fp)
+{
+	int irq;
+	int mask;
+
+	unsigned long pend = ISR;
+
+	while (pend) {
+		if (pend & 0x0000ffff) {
+			if (pend & 0x000000ff) {
+				if (pend & 0x0000000f) {
+					mask = 0x00000001;
+					irq = 0;
+				} else {
+					mask = 0x00000010;
+					irq = 4;
+				}
+			} else {
+				if (pend & 0x00000f00) {
+					mask = 0x00000100;
+					irq = 8;
+				} else {
+					mask = 0x00001000;
+					irq = 12;
+				}
+			}
+		} else {
+			if (pend & 0x00ff0000) {
+				if (pend & 0x000f0000) {
+					mask = 0x00010000;
+					irq = 16;
+				} else {
+					mask = 0x00100000;
+					irq = 20;
+				}
+			} else {
+				if (pend & 0x0f000000) {
+					mask = 0x01000000;
+					irq = 24;
+				} else {
+					mask = 0x10000000;
+					irq = 28;
+				}
+			}
+		}
+
+		while (! (mask & pend)) {
+			mask <<=1;
+			irq++;
+		}
+
+		do_IRQ(irq, fp);
+		pend &= ~mask;
+	}
+}
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	IMR &= ~(1 << d->irq);
+}
+
+static void intc_irq_mask(struct irq_data *d)
+{
+	IMR |= (1 << d->irq);
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "M68K-INTC",
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+};
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the machine vector table.
+ */
+void __init init_IRQ(void)
+{
+	int i;
+
+	/* set up the vectors */
+	for (i = 72; i < 256; ++i)
+		_ramvec[i] = (e_vector) bad_interrupt;
+
+	_ramvec[32] = system_call;
+
+	_ramvec[65] = (e_vector) inthandler1;
+	_ramvec[66] = (e_vector) inthandler2;
+	_ramvec[67] = (e_vector) inthandler3;
+	_ramvec[68] = (e_vector) inthandler4;
+	_ramvec[69] = (e_vector) inthandler5;
+	_ramvec[70] = (e_vector) inthandler6;
+	_ramvec[71] = (e_vector) inthandler7;
+
+	IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
+
+	/* turn off all interrupts */
+	IMR = ~0;
+
+	for (i = 0; (i < NR_IRQS); i++) {
+		irq_set_chip(i, &intc_irq_chip);
+		irq_set_handler(i, handle_level_irq);
+	}
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/68328/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+#
+# Makefile for arch/m68knommu/platform/68328.
+#
+
+head-y			= head-$(MODEL).o
+head-$(CONFIG_PILOT)	= head-pilot.o
+head-$(CONFIG_DRAGEN2)	= head-de2.o
+
+obj-y			+= entry.o ints.o timers.o
+obj-$(CONFIG_M68328)	+= config.o
+obj-$(CONFIG_ROM)	+= romvec.o
+
+extra-y			:= head.o
+extra-$(CONFIG_M68328)	+= bootlogo.rh head.o
+
+$(obj)/bootlogo.rh: $(src)/bootlogo.h
+	perl $(src)/bootlogo.pl < $(src)/bootlogo.h > $(obj)/bootlogo.rh
+
+$(obj)/head.o: $(obj)/$(head-y)
+	ln -sf $(head-y) $(obj)/head.o
+
+clean-files := $(obj)/bootlogo.rh $(obj)/head.o $(head-y)
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/romvec.S linux-libre-2.6.39-gnu/arch/m68k/platform/68328/romvec.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/romvec.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/romvec.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,35 @@
+/*
+ * linux/arch/m68knommu/platform/68328/romvec.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.
+ *
+ * Copyright 1996 Roman Zippel
+ * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
+ * Copyright 2006 Greg Ungerer <gerg@snapgear.com>
+ */
+
+.global _start
+.global _buserr
+.global trap
+.global system_call
+
+.section .romvec
+
+e_vectors:
+.long CONFIG_RAMBASE+CONFIG_RAMSIZE-4, _start, buserr, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+/* TRAP #0-15 */
+.long system_call, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long trap, trap, trap, trap
+.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68328/timers.c linux-libre-2.6.39-gnu/arch/m68k/platform/68328/timers.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68328/timers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68328/timers.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,134 @@
+/***************************************************************************/
+
+/*
+ *  linux/arch/m68knommu/platform/68328/timers.c
+ *
+ *  Copyright (C) 1993 Hamish Macdonald
+ *  Copyright (C) 1999 D. Jeff Dionne
+ *  Copyright (C) 2001 Georges Menie, Ken Desmet
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clocksource.h>
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/MC68VZ328.h>
+
+/***************************************************************************/
+
+#if defined(CONFIG_DRAGEN2)
+/* with a 33.16 MHz clock, this will give usec resolution to the time functions */
+#define CLOCK_SOURCE	TCTL_CLKSOURCE_SYSCLK
+#define CLOCK_PRE	7
+#define TICKS_PER_JIFFY	41450
+
+#elif defined(CONFIG_XCOPILOT_BUGS)
+/*
+ * The only thing I know is that CLK32 is not available on Xcopilot
+ * I have little idea about what frequency SYSCLK has on Xcopilot.
+ * The values for prescaler and compare registers were simply
+ * taken from the original source
+ */
+#define CLOCK_SOURCE	TCTL_CLKSOURCE_SYSCLK
+#define CLOCK_PRE	2
+#define TICKS_PER_JIFFY	0xd7e4
+
+#else
+/* default to using the 32Khz clock */
+#define CLOCK_SOURCE	TCTL_CLKSOURCE_32KHZ
+#define CLOCK_PRE	31
+#define TICKS_PER_JIFFY	10
+#endif
+
+static u32 m68328_tick_cnt;
+
+/***************************************************************************/
+
+static irqreturn_t hw_tick(int irq, void *dummy)
+{
+	/* Reset Timer1 */
+	TSTAT &= 0;
+
+	m68328_tick_cnt += TICKS_PER_JIFFY;
+	return arch_timer_interrupt(irq, dummy);
+}
+
+/***************************************************************************/
+
+static struct irqaction m68328_timer_irq = {
+	.name	 = "timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = hw_tick,
+};
+
+/***************************************************************************/
+
+static cycle_t m68328_read_clk(struct clocksource *cs)
+{
+	unsigned long flags;
+	u32 cycles;
+
+	local_irq_save(flags);
+	cycles = m68328_tick_cnt + TCN;
+	local_irq_restore(flags);
+
+	return cycles;
+}
+
+/***************************************************************************/
+
+static struct clocksource m68328_clk = {
+	.name	= "timer",
+	.rating	= 250,
+	.read	= m68328_read_clk,
+	.shift	= 20,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/***************************************************************************/
+
+void hw_timer_init(void)
+{
+	/* disable timer 1 */
+	TCTL = 0;
+
+	/* set ISR */
+	setup_irq(TMR_IRQ_NUM, &m68328_timer_irq);
+
+	/* Restart mode, Enable int, Set clock source */
+	TCTL = TCTL_OM | TCTL_IRQEN | CLOCK_SOURCE;
+	TPRER = CLOCK_PRE;
+	TCMP = TICKS_PER_JIFFY;
+
+	/* Enable timer 1 */
+	TCTL |= TCTL_TEN;
+	m68328_clk.mult = clocksource_hz2mult(TICKS_PER_JIFFY*HZ, m68328_clk.shift);
+	clocksource_register(&m68328_clk);
+}
+
+/***************************************************************************/
+
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec)
+{
+	long now = RTCTIME;
+
+	*year = *mon = *day = 1;
+	*hour = (now >> 24) % 24;
+	*min = (now >> 16) % 60;
+	*sec = now % 60;
+}
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/commproc.c linux-libre-2.6.39-gnu/arch/m68k/platform/68360/commproc.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/commproc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/commproc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,308 @@
+/*
+ * General Purpose functions for the global management of the
+ * Communication Processor Module.
+ *
+ * Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
+ * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
+ *
+ * In addition to the individual control of the communication
+ * channels, there are a few functions that globally affect the
+ * communication processor.
+ *
+ * Buffer descriptors must be allocated from the dual ported memory
+ * space.  The allocator for that is here.  When the communication
+ * process is reset, we reclaim the memory available.  There is
+ * currently no deallocator for this memory.
+ * The amount of space available is platform dependent.  On the
+ * MBX, the EPPC software loads additional microcode into the
+ * communication processor, and uses some of the DP ram for this
+ * purpose.  Current, the first 512 bytes and the last 256 bytes of
+ * memory are used.  Right now I am conservative and only use the
+ * memory that can never be used for microcode.  If there are
+ * applications that require more DP ram, we can expand the boundaries
+ * but then we have to be careful of any downloaded microcode.
+ *
+ */
+
+/*
+ * Michael Leslie <mleslie@lineo.com>
+ * adapted Dan Malek's ppc8xx drivers to M68360
+ *
+ */
+
+#include <linux/errno.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 <asm/irq.h>
+#include <asm/m68360.h>
+#include <asm/commproc.h>
+
+/* #include <asm/page.h> */
+/* #include <asm/pgtable.h> */
+extern void *_quicc_base;
+extern unsigned int system_clock;
+
+
+static uint dp_alloc_base;	/* Starting offset in DP ram */
+static uint dp_alloc_top;	/* Max offset + 1 */
+
+#if 0
+static	void	*host_buffer;	/* One page of host buffer */
+static	void	*host_end;	    /* end + 1 */
+#endif
+
+/* struct  cpm360_t *cpmp; */         /* Pointer to comm processor space */
+
+QUICC  *pquicc;
+/* QUICC  *quicc_dpram; */ /* mleslie - temporary; use extern pquicc elsewhere instead */
+
+
+/* CPM interrupt vector functions. */
+struct	cpm_action {
+	void	(*handler)(void *);
+	void	*dev_id;
+};
+static	struct	cpm_action cpm_vecs[CPMVEC_NR];
+static	void	cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
+static	void	cpm_error_interrupt(void *);
+
+/* prototypes: */
+void cpm_install_handler(int vec, void (*handler)(), void *dev_id);
+void m360_cpm_reset(void);
+
+
+
+
+void m360_cpm_reset()
+{
+/* 	pte_t		   *pte; */
+
+	pquicc = (struct quicc *)(_quicc_base); /* initialized in crt0_rXm.S */
+
+	/* Perform a CPM reset. */
+	pquicc->cp_cr = (SOFTWARE_RESET | CMD_FLAG);
+
+	/* Wait for CPM to become ready (should be 2 clocks). */
+	while (pquicc->cp_cr & CMD_FLAG);
+
+	/* On the recommendation of the 68360 manual, p. 7-60
+	 * - Set sdma interrupt service mask to 7
+	 * - Set sdma arbitration ID to 4
+	 */
+	pquicc->sdma_sdcr = 0x0740;
+
+
+	/* Claim the DP memory for our use.
+	 */
+	dp_alloc_base = CPM_DATAONLY_BASE;
+	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
+
+
+	/* Set the host page for allocation.
+	 */
+	/* 	host_buffer = host_page_addr; */
+	/* 	host_end = host_page_addr + PAGE_SIZE; */
+
+	/* 	pte = find_pte(&init_mm, host_page_addr); */
+	/* 	pte_val(*pte) |= _PAGE_NO_CACHE; */
+	/* 	flush_tlb_page(current->mm->mmap, host_buffer); */
+
+	/* Tell everyone where the comm processor resides.
+	*/
+/* 	cpmp = (cpm360_t *)commproc; */
+}
+
+
+/* This is called during init_IRQ.  We used to do it above, but this
+ * was too early since init_IRQ was not yet called.
+ */
+void
+cpm_interrupt_init(void)
+{
+	/* Initialize the CPM interrupt controller.
+	 * NOTE THAT pquicc had better have been initialized!
+	 * reference: MC68360UM p. 7-377
+	 */
+	pquicc->intr_cicr =
+		(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
+		(CPM_INTERRUPT << 13) |
+		CICR_HP_MASK |
+		(CPM_VECTOR_BASE << 5) |
+		CICR_SPS;
+
+	/* mask all CPM interrupts from reaching the cpu32 core: */
+	pquicc->intr_cimr = 0;
+
+
+	/* mles - If I understand correctly, the 360 just pops over to the CPM
+	 * specific vector, obviating the necessity to vector through the IRQ
+	 * whose priority the CPM is set to. This needs a closer look, though.
+	 */
+
+	/* Set our interrupt handler with the core CPU. */
+/* 	if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) */
+/* 		panic("Could not allocate CPM IRQ!"); */
+
+	/* Install our own error handler.
+	 */
+	/* I think we want to hold off on this one for the moment - mles */
+	/* cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); */
+
+	/* master CPM interrupt enable */
+	/* pquicc->intr_cicr |= CICR_IEN; */ /* no such animal for 360 */
+}
+
+
+
+/* CPM interrupt controller interrupt.
+*/
+static	void
+cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
+{
+	/* uint	vec; */
+
+	/* mles: Note that this stuff is currently being performed by
+	 * M68360_do_irq(int vec, struct pt_regs *fp), in ../ints.c  */
+
+	/* figure out the vector */
+	/* call that vector's handler */
+	/* clear the irq's bit in the service register */
+
+#if 0 /* old 860 stuff: */
+	/* Get the vector by setting the ACK bit and then reading
+	 * the register.
+	 */
+	((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
+	vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
+	vec >>= 11;
+
+
+	if (cpm_vecs[vec].handler != 0)
+		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
+	else
+		((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
+
+	/* After servicing the interrupt, we have to remove the status
+	 * indicator.
+	 */
+	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
+#endif
+
+}
+
+/* The CPM can generate the error interrupt when there is a race condition
+ * between generating and masking interrupts.  All we have to do is ACK it
+ * and return.  This is a no-op function so we don't need any special
+ * tests in the interrupt handler.
+ */
+static	void
+cpm_error_interrupt(void *dev)
+{
+}
+
+/* Install a CPM interrupt handler.
+*/
+void
+cpm_install_handler(int vec, void (*handler)(), void *dev_id)
+{
+
+	request_irq(vec, handler, 0, "timer", dev_id);
+
+/* 	if (cpm_vecs[vec].handler != 0) */
+/* 		printk(KERN_INFO "CPM interrupt %x replacing %x\n", */
+/* 			(uint)handler, (uint)cpm_vecs[vec].handler); */
+/* 	cpm_vecs[vec].handler = handler; */
+/* 	cpm_vecs[vec].dev_id = dev_id; */
+
+	/*              ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); */
+/* 	pquicc->intr_cimr |= (1 << vec); */
+
+}
+
+/* Free a CPM interrupt handler.
+*/
+void
+cpm_free_handler(int vec)
+{
+	cpm_vecs[vec].handler = NULL;
+	cpm_vecs[vec].dev_id = NULL;
+	/* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); */
+	pquicc->intr_cimr &= ~(1 << vec);
+}
+
+
+
+
+/* Allocate some memory from the dual ported ram.  We may want to
+ * enforce alignment restrictions, but right now everyone is a good
+ * citizen.
+ */
+uint
+m360_cpm_dpalloc(uint size)
+{
+        uint    retloc;
+
+        if ((dp_alloc_base + size) >= dp_alloc_top)
+                return(CPM_DP_NOSPACE);
+
+        retloc = dp_alloc_base;
+        dp_alloc_base += size;
+
+        return(retloc);
+}
+
+
+#if 0 /* mleslie - for now these are simply kmalloc'd */
+/* We also own one page of host buffer space for the allocation of
+ * UART "fifos" and the like.
+ */
+uint
+m360_cpm_hostalloc(uint size)
+{
+	uint	retloc;
+
+	if ((host_buffer + size) >= host_end)
+		return(0);
+
+	retloc = host_buffer;
+	host_buffer += size;
+
+	return(retloc);
+}
+#endif
+
+
+/* Set a baud rate generator.  This needs lots of work.  There are
+ * four BRGs, any of which can be wired to any channel.
+ * The internal baud rate clock is the system clock divided by 16.
+ * This assumes the baudrate is 16x oversampled by the uart.
+ */
+/* #define BRG_INT_CLK	(((bd_t *)__res)->bi_intfreq * 1000000) */
+#define BRG_INT_CLK		system_clock
+#define BRG_UART_CLK	(BRG_INT_CLK/16)
+
+void
+m360_cpm_setbrg(uint brg, uint rate)
+{
+	volatile uint	*bp;
+
+	/* This is good enough to get SMCs running.....
+	 */
+	/* bp = (uint *)&cpmp->cp_brgc1; */
+	bp = (volatile uint *)(&pquicc->brgc[0].l);
+	bp += brg;
+	*bp = ((BRG_UART_CLK / rate - 1) << 1) | CPM_BRG_EN;
+}
+
+
+/*
+ * Local variables:
+ *  c-indent-level: 4
+ *  c-basic-offset: 4
+ *  tab-width: 4
+ * End:
+ */
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/68360/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,186 @@
+/*
+ *  linux/arch/m68knommu/platform/68360/config.c
+ *
+ *  Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
+ *  Copyright (C) 1993 Hamish Macdonald
+ *  Copyright (C) 1999 D. Jeff Dionne <jeff@uclinux.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 <stdarg.h>
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/setup.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/m68360.h>
+
+#ifdef CONFIG_UCQUICC
+#include <asm/bootstd.h>
+#endif
+
+extern void m360_cpm_reset(void);
+
+// Mask to select if the PLL prescaler is enabled.
+#define MCU_PREEN   ((unsigned short)(0x0001 << 13))
+
+#if defined(CONFIG_UCQUICC)
+#define OSCILLATOR  (unsigned long int)33000000
+#endif
+
+unsigned long int system_clock;
+
+extern QUICC *pquicc;
+
+/* TODO  DON"T Hard Code this */
+/* calculate properly using the right PLL and prescaller */
+// unsigned int system_clock = 33000000l;
+extern unsigned long int system_clock; //In kernel setup.c
+
+
+static irqreturn_t hw_tick(int irq, void *dummy)
+{
+  /* Reset Timer1 */
+  /* TSTAT &= 0; */
+
+  pquicc->timer_ter1 = 0x0002; /* clear timer event */
+
+  return arch_timer_interrupt(irq, dummy);
+}
+
+static struct irqaction m68360_timer_irq = {
+	.name	 = "timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = hw_tick,
+};
+
+void hw_timer_init(void)
+{
+  unsigned char prescaler;
+  unsigned short tgcr_save;
+
+#if 0
+  /* Restart mode, Enable int, 32KHz, Enable timer */
+  TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN;
+  /* Set prescaler (Divide 32KHz by 32)*/
+  TPRER = 31;
+  /* Set compare register  32Khz / 32 / 10 = 100 */
+  TCMP = 10;                                                              
+
+  request_irq(IRQ_MACHSPEC | 1, timer_routine, 0, "timer", NULL);
+#endif
+
+  /* General purpose quicc timers: MC68360UM p7-20 */
+
+  /* Set up timer 1 (in [1..4]) to do 100Hz */
+  tgcr_save = pquicc->timer_tgcr & 0xfff0;
+  pquicc->timer_tgcr  = tgcr_save; /* stop and reset timer 1 */
+  /* pquicc->timer_tgcr |= 0x4444; */ /* halt timers when FREEZE (ie bdm freeze) */
+
+  prescaler = 8;
+  pquicc->timer_tmr1 = 0x001a | /* or=1, frr=1, iclk=01b */
+                           (unsigned short)((prescaler - 1) << 8);
+    
+  pquicc->timer_tcn1 = 0x0000; /* initial count */
+  /* calculate interval for 100Hz based on the _system_clock: */
+  pquicc->timer_trr1 = (system_clock/ prescaler) / HZ; /* reference count */
+
+  pquicc->timer_ter1 = 0x0003; /* clear timer events */
+
+  /* enable timer 1 interrupt in CIMR */
+  setup_irq(CPMVEC_TIMER1, &m68360_timer_irq);
+
+  /* Start timer 1: */
+  tgcr_save = (pquicc->timer_tgcr & 0xfff0) | 0x0001;
+  pquicc->timer_tgcr  = tgcr_save;
+}
+
+void BSP_gettod (int *yearp, int *monp, int *dayp,
+		   int *hourp, int *minp, int *secp)
+{
+}
+
+int BSP_set_clock_mmss(unsigned long nowtime)
+{
+#if 0
+  short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
+
+  tod->second1 = real_seconds / 10;
+  tod->second2 = real_seconds % 10;
+  tod->minute1 = real_minutes / 10;
+  tod->minute2 = real_minutes % 10;
+#endif
+  return 0;
+}
+
+void BSP_reset (void)
+{
+  local_irq_disable();
+  asm volatile (
+    "moveal #_start, %a0;\n"
+    "moveb #0, 0xFFFFF300;\n"
+    "moveal 0(%a0), %sp;\n"
+    "moveal 4(%a0), %a0;\n"
+    "jmp (%a0);\n"
+    );
+}
+
+unsigned char *scc1_hwaddr;
+static int errno;
+
+#if defined (CONFIG_UCQUICC)
+_bsc0(char *, getserialnum)
+_bsc1(unsigned char *, gethwaddr, int, a)
+_bsc1(char *, getbenv, char *, a)
+#endif
+
+
+void config_BSP(char *command, int len)
+{
+  unsigned char *p;
+
+  m360_cpm_reset();
+
+  /* Calculate the real system clock value. */
+  {
+     unsigned int local_pllcr = (unsigned int)(pquicc->sim_pllcr);
+     if( local_pllcr & MCU_PREEN ) // If the prescaler is dividing by 128
+     {
+         int mf = (int)(pquicc->sim_pllcr & 0x0fff);
+         system_clock = (OSCILLATOR / 128) * (mf + 1);
+     }
+     else
+     {
+         int mf = (int)(pquicc->sim_pllcr & 0x0fff);
+         system_clock = (OSCILLATOR) * (mf + 1);
+     }
+  }
+
+  printk(KERN_INFO "\n68360 QUICC support (C) 2000 Lineo Inc.\n");
+
+#if defined(CONFIG_UCQUICC) && 0
+  printk(KERN_INFO "uCquicc serial string [%s]\n",getserialnum());
+  p = scc1_hwaddr = gethwaddr(0);
+  printk(KERN_INFO "uCquicc hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+         p[0], p[1], p[2], p[3], p[4], p[5]);
+
+  p = getbenv("APPEND");
+  if (p)
+    strcpy(p,command);
+  else
+    command[0] = 0;
+#else
+  scc1_hwaddr = "\00\01\02\03\04\05";
+#endif
+ 
+  mach_gettod          = BSP_gettod;
+  mach_reset           = BSP_reset;
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/entry.S linux-libre-2.6.39-gnu/arch/m68k/platform/68360/entry.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,184 @@
+/*
+ *  linux/arch/m68knommu/platform/68360/entry.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *  Copyright (C) 2001 SED Systems, a Division of Calian Ltd.
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ * M68360 Port by SED Systems, and Lineo.
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/thread_info.h>
+#include <asm/unistd.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/traps.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+
+.text
+
+.globl system_call
+.globl resume
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_call_table
+.globl ret_from_interrupt
+.globl bad_interrupt
+.globl inthandler
+
+badsys:
+	movel	#-ENOSYS,%sp@(PT_OFF_D0)
+	jra	ret_from_exception
+
+do_trace:
+	movel	#-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
+	subql	#4,%sp
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_enter
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	movel	%sp@(PT_OFF_ORIG_D0),%d1
+	movel	#-ENOSYS,%d0
+	cmpl	#NR_syscalls,%d1
+	jcc	1f
+	lsl	#2,%d1
+	lea	sys_call_table, %a0
+	jbsr	%a0@(%d1)
+
+1:	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
+	subql	#4,%sp			/* dummy return address */
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_leave
+
+ret_from_signal:
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jra	ret_from_exception
+
+ENTRY(system_call)
+	SAVE_ALL
+
+	/* save top of frame*/
+	pea	%sp@
+	jbsr	set_esp0
+	addql	#4,%sp
+
+	movel	%sp@(PT_OFF_ORIG_D0),%d0
+
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1
+	movel	%d1,%a2
+	btst	#(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
+	jne	do_trace
+	cmpl	#NR_syscalls,%d0
+	jcc	badsys
+	lsl	#2,%d0
+	lea	sys_call_table,%a0
+	movel	%a0@(%d0), %a0
+	jbsr	%a0@
+	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/
+
+ret_from_exception:
+	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
+	jeq	Luser_return		/* if so, skip resched, signals*/
+
+Lkernel_return:
+	RESTORE_ALL
+
+Luser_return:
+	/* only allow interrupts when we are really the last one on the*/
+	/* kernel stack, otherwise stack overflow can occur during*/
+	/* heavy interrupt load*/
+	andw	#ALLOWINT,%sr
+
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1
+	movel	%d1,%a2
+1:
+	move	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
+	jne	Lwork_to_do
+	RESTORE_ALL
+
+Lwork_to_do:
+	movel	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
+	btst	#TIF_NEED_RESCHED,%d1
+	jne	reschedule
+
+Lsignal_return:
+	subql	#4,%sp			/* dummy return address*/
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	bsrw	do_signal
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jra	1b
+
+/*
+ * This is the main interrupt handler, responsible for calling do_IRQ()
+ */
+inthandler:
+	SAVE_ALL
+	movew	%sp@(PT_OFF_FORMATVEC), %d0
+	and.l	#0x3ff, %d0
+	lsr.l   #0x02,  %d0
+
+	movel	%sp,%sp@-
+	movel	%d0,%sp@- 		/*  put vector # on stack*/
+	jbsr	do_IRQ			/*  process the IRQ*/
+3:     	addql	#8,%sp			/*  pop parameters off stack*/
+	bra	ret_from_interrupt
+
+ret_from_interrupt:
+	jeq	1f
+2:
+	RESTORE_ALL
+1:
+	moveb	%sp@(PT_OFF_SR), %d0
+	and	#7, %d0
+	jhi	2b
+	/* check if we need to do software interrupts */
+
+	movel	irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
+	jeq	ret_from_exception
+
+	pea	ret_from_exception
+	jra	do_softirq
+
+
+/*
+ * Handler for uninitialized and spurious interrupts.
+ */
+bad_interrupt:
+	addql	#1,num_spurious
+	rte
+
+/*
+ * Beware - when entering resume, prev (the current task) is
+ * in a0, next (the new task) is in a1,so don't change these
+ * registers until their contents are no longer needed.
+ */
+ENTRY(resume)
+	movel	%a0,%d1				/* save prev thread in d1 */
+	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
+	movel	%usp,%a2			/* save usp */
+	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
+
+	SAVE_SWITCH_STACK
+	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
+	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+	RESTORE_SWITCH_STACK
+
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
+	movel	%a0,%usp
+	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
+	rts
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/head-ram.S linux-libre-2.6.39-gnu/arch/m68k/platform/68360/head-ram.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/head-ram.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/head-ram.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,403 @@
+/* arch/m68knommu/platform/68360/head-ram.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+#define ASSEMBLY
+
+.global _stext
+.global _start
+
+.global _rambase
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define	RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
+#define	ROMEND                      (CONFIG_ROMBASE + CONFIG_ROMSIZE)
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000002
+#define SIM_BR0_MASK                0x00000001
+
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+	
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+	.text
+_start:
+_stext:
+	nop
+	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
+	/* We should not need to setup the boot stack the reset should do it. */
+	movea.l	#RAMEND, %sp			/*set up stack at the end of DRAM:*/
+
+set_mbar_register:
+	moveq.l	#0x07, %d1			/* Setup MBAR */
+	movec	%d1, %dfc
+
+	lea.l	MCU_SIM_MBAR_ADRS, %a0
+	move.l	#_dprbase, %d0
+	andi.l	#MCU_SIM_MBAR_BA_MASK, %d0
+	ori.l	#MCU_SIM_MBAR_AS_MASK, %d0
+	moves.l	%d0, %a0@
+
+	moveq.l	#0x05, %d1
+	movec.l	%d1, %dfc
+
+	/* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+	/* Set Module Configuration Register */
+	move.l	#MCU_SIM_MCR, MCR
+
+	/* to do:	Determine cause of reset */
+
+	/*
+	 *       configure system clock MC68360 p. 6-40
+	 *       (value +1)*osc/128 = system clock
+	 */
+set_sim_clock:
+	move.w	#MCU_SIM_PLLCR, PLLCR
+	move.b	#MCU_SIM_CLKOCR, CLKOCR
+	move.w	#MCU_SIM_CDVCR, CDVCR
+
+	/* Wait for the PLL to settle */
+	move.w	#16384, %d0
+pll_settle_wait:
+	subi.w	#1, %d0
+	bne	pll_settle_wait
+
+	/* Setup the system protection register, and watchdog timer register */
+	move.b	#MCU_SIM_SWIV, SWIV
+	move.w	#MCU_SIM_PICR, PICR
+	move.w	#MCU_SIM_PITR, PITR
+	move.w	#MCU_SIM_SYPCR, SYPCR
+
+	/* Clear DPRAM - system + parameter */
+	movea.l	#_dprbase, %a0
+	movea.l	#_dprbase+0x2000, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	clear_dpram
+
+configure_memory_controller:    
+	/* Set up Global Memory Register (GMR) */
+	move.l	#MCU_SIM_GMR, %d0
+	move.l	%d0, GMR
+
+configure_chip_select_0:
+	move.l	#RAMEND, %d0
+	subi.l	#__ramstart, %d0
+	subq.l	#0x01, %d0
+	eori.l	#SIM_OR_MASK, %d0
+	ori.l	#SIM_OR0_MASK, %d0
+	move.l	%d0, OR0
+
+	move.l	#__ramstart, %d0
+	ori.l	#SIM_BR0_MASK, %d0
+	move.l	%d0, BR0
+
+configure_chip_select_1:
+	move.l	#ROMEND, %d0
+	subi.l	#__rom_start, %d0
+	subq.l	#0x01, %d0
+	eori.l	#SIM_OR_MASK, %d0
+	ori.l	#SIM_OR1_MASK, %d0
+	move.l	%d0, OR1
+
+	move.l	#__rom_start, %d0
+	ori.l	#SIM_BR1_MASK, %d0
+	move.l	%d0, BR1
+
+	move.w	#MCU_SIM_PEPAR, PEPAR 
+
+	/* point to vector table: */
+	move.l	#_romvec, %a0
+	move.l	#_ramvec, %a1
+copy_vectors:
+	move.l	%a0@, %d0
+	move.l	%d0, %a1@
+	move.l	%a0@, %a1@
+	addq.l	#0x04, %a0
+	addq.l	#0x04, %a1
+	cmp.l	#_start, %a0
+	blt	copy_vectors
+
+	move.l	#_ramvec, %a1
+	movec	%a1, %vbr
+
+
+	/* Copy data segment from ROM to RAM */
+	moveal	#_stext, %a0
+	moveal	#_sdata, %a1
+	moveal	#_edata, %a2
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+	move.l	%a0@, %d0
+	addq.l	#0x04, %a0
+	move.l	%d0, %a1@
+	addq.l	#0x04, %a1
+	cmp.l	#_edata, %a1
+	blt     LD1
+
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	L1
+
+load_quicc:
+	move.l	#_dprbase, _quicc_base
+
+store_ram_size:
+	/* Set ram size information */
+	move.l	#_sdata, _rambase
+	move.l	#_ebss, _ramstart
+	move.l	#RAMEND, %d0
+	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
+	move.l	%d0, _ramend			/* Different from RAMEND.*/
+
+	pea	0
+	pea	env
+	pea	%sp@(4)
+	pea	0
+
+	lea	init_thread_union, %a2
+	lea	0x2000(%a2), %sp
+
+lp:
+	jsr	start_kernel
+
+_exit:
+	jmp	_exit
+
+
+	.data
+	.align 4
+env:
+	.long	0
+_quicc_base:
+	.long	0
+_periph_base:
+	.long	0
+_ramvec:
+	.long   0
+_rambase:
+	.long   0
+_ramstart:
+	.long   0
+_ramend:
+	.long   0
+_dprbase:
+	.long	0xffffe000
+
+	.text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+ 
+.section ".data..initvect","awx"
+    .long   RAMEND	/* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/head-rom.S linux-libre-2.6.39-gnu/arch/m68k/platform/68360/head-rom.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/head-rom.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/head-rom.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,414 @@
+/* arch/m68knommu/platform/68360/head-rom.S
+ *
+ * Startup code for Motorola 68360
+ *
+ * Copyright (C) SED Systems, a Division of Calian Ltd.
+ * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
+ * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
+ *           uClinux Kernel
+ * Copyright (C) Michael Leslie <mleslie@lineo.com>
+ * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
+ * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
+ *
+ */
+
+.global _stext
+.global _sbss
+.global _start
+
+.global _rambase
+.global _ramvec
+.global _ramstart
+.global _ramend
+
+.global _quicc_base
+.global _periph_base
+
+#define	RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
+
+#define REGB                        0x1000
+#define PEPAR                       (_dprbase + REGB + 0x0016)
+#define GMR                         (_dprbase + REGB + 0x0040)
+#define OR0                         (_dprbase + REGB + 0x0054)
+#define BR0                         (_dprbase + REGB + 0x0050)
+
+#define OR1                         (_dprbase + REGB + 0x0064)
+#define BR1                         (_dprbase + REGB + 0x0060)
+
+#define OR2                         (_dprbase + REGB + 0x0074)
+#define BR2                         (_dprbase + REGB + 0x0070)
+
+#define OR3                         (_dprbase + REGB + 0x0084)
+#define BR3                         (_dprbase + REGB + 0x0080)
+
+#define OR4                         (_dprbase + REGB + 0x0094)
+#define BR4                         (_dprbase + REGB + 0x0090)
+
+#define OR5                         (_dprbase + REGB + 0x00A4)
+#define BR5                         (_dprbase + REGB + 0x00A0)
+
+#define OR6                         (_dprbase + REGB + 0x00b4)
+#define BR6                         (_dprbase + REGB + 0x00b0)
+
+#define OR7                         (_dprbase + REGB + 0x00c4)
+#define BR7                         (_dprbase + REGB + 0x00c0)
+
+#define MCR                         (_dprbase + REGB + 0x0000)
+#define AVR                         (_dprbase + REGB + 0x0008)
+
+#define SYPCR                       (_dprbase + REGB + 0x0022)
+
+#define PLLCR                       (_dprbase + REGB + 0x0010)
+#define CLKOCR                      (_dprbase + REGB + 0x000C)
+#define CDVCR                       (_dprbase + REGB + 0x0014)
+
+#define BKAR                        (_dprbase + REGB + 0x0030)
+#define BKCR                        (_dprbase + REGB + 0x0034)
+#define SWIV                        (_dprbase + REGB + 0x0023)
+#define PICR                        (_dprbase + REGB + 0x0026)
+#define PITR                        (_dprbase + REGB + 0x002A)
+
+/* Define for all memory configuration */
+#define MCU_SIM_GMR                 0x00000000
+#define SIM_OR_MASK                 0x0fffffff
+
+/* Defines for chip select zero - the flash */
+#define SIM_OR0_MASK                0x20000000
+#define SIM_BR0_MASK                0x00000001
+
+/* Defines for chip select one - the RAM */
+#define SIM_OR1_MASK                0x10000000
+#define SIM_BR1_MASK                0x00000001
+
+#define MCU_SIM_MBAR_ADRS           0x0003ff00
+#define MCU_SIM_MBAR_BA_MASK        0xfffff000
+#define MCU_SIM_MBAR_AS_MASK        0x00000001
+
+#define MCU_SIM_PEPAR               0x00B4
+    
+#define MCU_DISABLE_INTRPTS         0x2700
+#define MCU_SIM_AVR                 0x00
+    
+#define MCU_SIM_MCR                 0x00005cff
+
+#define MCU_SIM_CLKOCR              0x00
+#define MCU_SIM_PLLCR               0x8000
+#define MCU_SIM_CDVCR               0x0000
+
+#define MCU_SIM_SYPCR               0x0000
+#define MCU_SIM_SWIV                0x00
+#define MCU_SIM_PICR                0x0000
+#define MCU_SIM_PITR                0x0000
+
+
+#include <asm/m68360_regs.h>
+
+	
+/*
+ * By the time this RAM specific code begins to execute, DPRAM
+ * and DRAM should already be mapped and accessible.
+ */
+
+	.text
+_start:
+_stext:
+	nop
+	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
+	/* We should not need to setup the boot stack the reset should do it. */
+	movea.l	#RAMEND, %sp		/* set up stack at the end of DRAM:*/
+
+
+set_mbar_register:
+	moveq.l	#0x07, %d1			/* Setup MBAR */
+	movec	%d1, %dfc
+
+	lea.l	MCU_SIM_MBAR_ADRS, %a0
+	move.l	#_dprbase, %d0
+	andi.l	#MCU_SIM_MBAR_BA_MASK, %d0
+	ori.l	#MCU_SIM_MBAR_AS_MASK, %d0
+	moves.l	%d0, %a0@
+
+	moveq.l	#0x05, %d1
+	movec.l	%d1, %dfc
+
+	/* Now we can begin to access registers in DPRAM */
+
+set_sim_mcr:
+	/* Set Module Configuration Register */
+	move.l	#MCU_SIM_MCR, MCR
+
+	/* to do:	Determine cause of reset */
+
+	/*
+	 *	configure system clock MC68360 p. 6-40
+	 *	(value +1)*osc/128 = system clock
+	 *                    or
+	 *	(value + 1)*osc = system clock
+	 *	You do not need to divide the oscillator by 128 unless you want to.
+	 */
+set_sim_clock:
+	move.w	#MCU_SIM_PLLCR, PLLCR
+	move.b	#MCU_SIM_CLKOCR, CLKOCR
+	move.w	#MCU_SIM_CDVCR, CDVCR
+
+	/* Wait for the PLL to settle */
+	move.w	#16384, %d0
+pll_settle_wait:
+	subi.w	#1, %d0
+	bne	pll_settle_wait
+
+	/* Setup the system protection register, and watchdog timer register */
+	move.b	#MCU_SIM_SWIV, SWIV
+	move.w	#MCU_SIM_PICR, PICR
+	move.w	#MCU_SIM_PITR, PITR
+	move.w	#MCU_SIM_SYPCR, SYPCR
+
+	/* Clear DPRAM - system + parameter */
+	movea.l	#_dprbase, %a0
+	movea.l	#_dprbase+0x2000, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+clear_dpram:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	clear_dpram
+
+configure_memory_controller:    
+	/* Set up Global Memory Register (GMR) */
+	move.l	#MCU_SIM_GMR, %d0
+	move.l	%d0, GMR
+
+configure_chip_select_0:
+	move.l	#0x00400000, %d0
+	subq.l	#0x01, %d0
+	eori.l	#SIM_OR_MASK, %d0
+	ori.l	#SIM_OR0_MASK, %d0
+	move.l	%d0, OR0
+
+	move.l	#__rom_start, %d0
+	ori.l	#SIM_BR0_MASK, %d0
+	move.l	%d0, BR0
+
+	move.l	#0x0, BR1
+	move.l	#0x0, BR2
+	move.l	#0x0, BR3
+	move.l	#0x0, BR4
+	move.l	#0x0, BR5
+	move.l	#0x0, BR6
+	move.l	#0x0, BR7
+
+	move.w	#MCU_SIM_PEPAR, PEPAR 
+
+	/* point to vector table: */
+	move.l	#_romvec, %a0
+	move.l	#_ramvec, %a1
+copy_vectors:
+	move.l	%a0@, %d0
+	move.l	%d0, %a1@
+	move.l	%a0@, %a1@
+	addq.l	#0x04, %a0
+	addq.l	#0x04, %a1
+	cmp.l	#_start, %a0
+	blt	copy_vectors
+
+	move.l	#_ramvec, %a1
+	movec	%a1, %vbr
+
+
+	/* Copy data segment from ROM to RAM */
+	moveal	#_etext, %a0
+	moveal	#_sdata, %a1
+	moveal	#_edata, %a2
+
+	/* Copy %a0 to %a1 until %a1 == %a2 */
+LD1:
+	move.l	%a0@, %d0
+	addq.l	#0x04, %a0
+	move.l	%d0, %a1@
+	addq.l	#0x04, %a1
+	cmp.l	#_edata, %a1
+	blt	LD1
+
+	moveal	#_sbss, %a0
+	moveal	#_ebss, %a1
+
+	/* Copy 0 to %a0 until %a0 == %a1 */
+L1:
+	movel	#0, %a0@+
+	cmpal	%a0, %a1
+	bhi	L1
+
+load_quicc:
+	move.l	#_dprbase, _quicc_base
+
+store_ram_size:
+	/* Set ram size information */
+	move.l	#_sdata, _rambase
+	move.l	#_ebss, _ramstart
+	move.l	#RAMEND, %d0
+	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
+	move.l	%d0, _ramend			/* Different from RAMEND.*/
+
+	pea	0
+	pea	env
+	pea	%sp@(4)
+	pea	0
+
+	lea	init_thread_union, %a2
+	lea	0x2000(%a2), %sp
+
+lp:
+	jsr	start_kernel
+
+_exit:
+	jmp	_exit
+
+
+	.data
+	.align 4
+env:
+	.long	0
+_quicc_base:
+	.long	0
+_periph_base:
+	.long	0
+_ramvec:
+	.long   0
+_rambase:
+	.long   0
+_ramstart:
+	.long   0
+_ramend:
+	.long   0
+_dprbase:
+	.long	0xffffe000
+
+
+	.text
+
+    /*
+     * These are the exception vectors at boot up, they are copied into RAM
+     * and then overwritten as needed.
+     */
+ 
+.section ".data..initvect","awx"
+    .long   RAMEND	/* Reset: Initial Stack Pointer                 - 0.  */
+    .long   _start      /* Reset: Initial Program Counter               - 1.  */
+    .long   buserr      /* Bus Error                                    - 2.  */
+    .long   trap        /* Address Error                                - 3.  */
+    .long   trap        /* Illegal Instruction                          - 4.  */
+    .long   trap        /* Divide by zero                               - 5.  */
+    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
+    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
+    .long   trap        /* Privilege Violation                          - 8.  */
+    .long   trap        /* Trace                                        - 9.  */
+    .long   trap        /* Line 1010 Emulator                           - 10. */
+    .long   trap        /* Line 1111 Emualtor                           - 11. */
+    .long   trap        /* Harware Breakpoint                           - 12. */
+    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
+    .long   trap        /* Format Error                                 - 14. */
+    .long   trap        /* Uninitialized Interrupt                      - 15. */
+    .long   trap        /* (Unassigned, Reserver)                       - 16. */
+    .long   trap        /* (Unassigned, Reserver)                       - 17. */
+    .long   trap        /* (Unassigned, Reserver)                       - 18. */
+    .long   trap        /* (Unassigned, Reserver)                       - 19. */
+    .long   trap        /* (Unassigned, Reserver)                       - 20. */
+    .long   trap        /* (Unassigned, Reserver)                       - 21. */
+    .long   trap        /* (Unassigned, Reserver)                       - 22. */
+    .long   trap        /* (Unassigned, Reserver)                       - 23. */
+    .long   trap        /* Spurious Interrupt                           - 24. */
+    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
+    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
+    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
+    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
+    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
+    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
+    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
+    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
+    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
+    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
+    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
+    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
+    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
+    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
+    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
+    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
+    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
+    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
+    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
+    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
+    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
+    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
+    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
+    .long   0           /* (Reserved for Coprocessor)                   - 48. */
+    .long   0           /* (Reserved for Coprocessor)                   - 49. */
+    .long   0           /* (Reserved for Coprocessor)                   - 50. */
+    .long   0           /* (Reserved for Coprocessor)                   - 51. */
+    .long   0           /* (Reserved for Coprocessor)                   - 52. */
+    .long   0           /* (Reserved for Coprocessor)                   - 53. */
+    .long   0           /* (Reserved for Coprocessor)                   - 54. */
+    .long   0           /* (Reserved for Coprocessor)                   - 55. */
+    .long   0           /* (Reserved for Coprocessor)                   - 56. */
+    .long   0           /* (Reserved for Coprocessor)                   - 57. */
+    .long   0           /* (Reserved for Coprocessor)                   - 58. */
+    .long   0           /* (Unassigned, Reserved)                       - 59. */
+    .long   0           /* (Unassigned, Reserved)                       - 60. */
+    .long   0           /* (Unassigned, Reserved)                       - 61. */
+    .long   0           /* (Unassigned, Reserved)                       - 62. */
+    .long   0           /* (Unassigned, Reserved)                       - 63. */
+    /*                  The assignment of these vectors to the CPM is         */
+    /*                  dependent on the configuration of the CPM vba         */
+    /*                          fields.                                       */
+    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
+    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
+    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
+    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
+    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
+    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
+    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
+    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
+    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
+    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
+    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
+    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
+    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
+    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
+    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
+    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
+    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
+    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
+    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
+    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
+    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
+    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
+    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
+    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
+    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
+    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
+    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
+    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
+    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
+    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
+    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
+    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
+    /*                  I don't think anything uses the vectors after here.   */
+    .long   0           /* (User-Defined Vectors 34)                    - 96. */
+    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
+    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
+    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
+.text
+ignore: rte
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/ints.c linux-libre-2.6.39-gnu/arch/m68k/platform/68360/ints.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/ints.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/ints.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,139 @@
+/*
+ * linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.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) 2000  Michael Leslie <mleslie@lineo.com>
+ * Copyright (c) 1996 Roman Zippel
+ * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/m68360.h>
+
+/* from quicc/commproc.c: */
+extern QUICC *pquicc;
+extern void cpm_interrupt_init(void);
+
+#define INTERNAL_IRQS (96)
+
+/* assembler routines */
+asmlinkage void system_call(void);
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void bad_interrupt(void);
+asmlinkage void inthandler(void);
+
+extern void *_ramvec[];
+
+/* The number of spurious interrupts */
+volatile unsigned int num_spurious;
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	pquicc->intr_cimr |= (1 << d->irq);
+}
+
+static void intc_irq_mask(struct irq_data *d)
+{
+	pquicc->intr_cimr &= ~(1 << d->irq);
+}
+
+static void intc_irq_ack(struct irq_data *d)
+{
+	pquicc->intr_cisr = (1 << d->irq);
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "M68K-INTC",
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_ack	= intc_irq_ack,
+};
+
+/*
+ * This function should be called during kernel startup to initialize
+ * the vector table.
+ */
+void init_IRQ(void)
+{
+	int i;
+	int vba = (CPM_VECTOR_BASE<<4);
+
+	/* set up the vectors */
+	_ramvec[2] = buserr;
+	_ramvec[3] = trap;
+	_ramvec[4] = trap;
+	_ramvec[5] = trap;
+	_ramvec[6] = trap;
+	_ramvec[7] = trap;
+	_ramvec[8] = trap;
+	_ramvec[9] = trap;
+	_ramvec[10] = trap;
+	_ramvec[11] = trap;
+	_ramvec[12] = trap;
+	_ramvec[13] = trap;
+	_ramvec[14] = trap;
+	_ramvec[15] = trap;
+
+	_ramvec[32] = system_call;
+	_ramvec[33] = trap;
+
+	cpm_interrupt_init();
+
+	/* set up CICR for vector base address and irq level */
+	/* irl = 4, hp = 1f - see MC68360UM p 7-377 */
+	pquicc->intr_cicr = 0x00e49f00 | vba;
+
+	/* CPM interrupt vectors: (p 7-376) */
+	_ramvec[vba+CPMVEC_ERROR]       = bad_interrupt; /* Error */
+	_ramvec[vba+CPMVEC_PIO_PC11]    = inthandler;   /* pio - pc11 */
+	_ramvec[vba+CPMVEC_PIO_PC10]    = inthandler;   /* pio - pc10 */
+	_ramvec[vba+CPMVEC_SMC2]        = inthandler;   /* smc2/pip */
+	_ramvec[vba+CPMVEC_SMC1]        = inthandler;   /* smc1 */
+	_ramvec[vba+CPMVEC_SPI]         = inthandler;   /* spi */
+	_ramvec[vba+CPMVEC_PIO_PC9]     = inthandler;   /* pio - pc9 */
+	_ramvec[vba+CPMVEC_TIMER4]      = inthandler;   /* timer 4 */
+	_ramvec[vba+CPMVEC_RESERVED1]   = inthandler;   /* reserved */
+	_ramvec[vba+CPMVEC_PIO_PC8]     = inthandler;   /* pio - pc8 */
+	_ramvec[vba+CPMVEC_PIO_PC7]     = inthandler;  /* pio - pc7 */
+	_ramvec[vba+CPMVEC_PIO_PC6]     = inthandler;  /* pio - pc6 */
+	_ramvec[vba+CPMVEC_TIMER3]      = inthandler;  /* timer 3 */
+	_ramvec[vba+CPMVEC_PIO_PC5]     = inthandler;  /* pio - pc5 */
+	_ramvec[vba+CPMVEC_PIO_PC4]     = inthandler;  /* pio - pc4 */
+	_ramvec[vba+CPMVEC_RESERVED2]   = inthandler;  /* reserved */
+	_ramvec[vba+CPMVEC_RISCTIMER]   = inthandler;  /* timer table */
+	_ramvec[vba+CPMVEC_TIMER2]      = inthandler;  /* timer 2 */
+	_ramvec[vba+CPMVEC_RESERVED3]   = inthandler;  /* reserved */
+	_ramvec[vba+CPMVEC_IDMA2]       = inthandler;  /* idma 2 */
+	_ramvec[vba+CPMVEC_IDMA1]       = inthandler;  /* idma 1 */
+	_ramvec[vba+CPMVEC_SDMA_CB_ERR] = inthandler;  /* sdma channel bus error */
+	_ramvec[vba+CPMVEC_PIO_PC3]     = inthandler;  /* pio - pc3 */
+	_ramvec[vba+CPMVEC_PIO_PC2]     = inthandler;  /* pio - pc2 */
+	/* _ramvec[vba+CPMVEC_TIMER1]      = cpm_isr_timer1; */  /* timer 1 */
+	_ramvec[vba+CPMVEC_TIMER1]      = inthandler;  /* timer 1 */
+	_ramvec[vba+CPMVEC_PIO_PC1]     = inthandler;  /* pio - pc1 */
+	_ramvec[vba+CPMVEC_SCC4]        = inthandler;  /* scc 4 */
+	_ramvec[vba+CPMVEC_SCC3]        = inthandler;  /* scc 3 */
+	_ramvec[vba+CPMVEC_SCC2]        = inthandler;  /* scc 2 */
+	_ramvec[vba+CPMVEC_SCC1]        = inthandler;  /* scc 1 */
+	_ramvec[vba+CPMVEC_PIO_PC0]     = inthandler;  /* pio - pc0 */
+
+
+	/* turn off all CPM interrupts */
+	pquicc->intr_cimr = 0x00000000;
+
+	for (i = 0; (i < NR_IRQS); i++) {
+		irq_set_chip(i, &intc_irq_chip);
+		irq_set_handler(i, handle_level_irq);
+	}
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68360/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/68360/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68360/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68360/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+#
+# Makefile for arch/m68knommu/platform/68360.
+#
+
+obj-y := config.o commproc.o entry.o ints.o
+
+extra-y := head.o
+
+$(obj)/head.o: $(obj)/head-$(MODEL).o
+	ln -sf head-$(MODEL).o $(obj)/head.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68EZ328/bootlogo.h linux-libre-2.6.39-gnu/arch/m68k/platform/68EZ328/bootlogo.h
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68EZ328/bootlogo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68EZ328/bootlogo.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3204 @@
+#define splash_width 640
+#define splash_height 480
+static unsigned char splash_bits[] = {
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfe, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x7c, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0xe0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3e, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
+  0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xfe, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xe0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0x07, 0xfe, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
+  0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0xe0, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03,
+  0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
+  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xff, 0xff, 0x3f, 0xf0, 0x01, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xc0, 0xff,
+  0xc1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x07, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
+  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0x00, 0xe0, 0x07, 0x0e, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
+  0x3f, 0x1c, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
+  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
+  0x00, 0x00, 0x00, 0x00, 0x78, 0x70, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xe0, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc3, 0x01, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
+  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0xc7, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x87, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00,
+  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f,
+  0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0xf0, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xf0, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0x0c, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1c, 0x00,
+  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00,
+  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe2, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
+  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
+  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03,
+  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xfe, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0xf0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x9f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+  0xf8, 0xff, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0xff, 0xff, 0x00,
+  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x0f, 0x20, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0xf8, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x03, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+  0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0xf8, 0xff, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0x01,
+  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xfc, 0x01, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0xe0, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xf8,
+  0x41, 0xc6, 0x84, 0x0c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xf8, 0x41, 0xc6, 0x84, 0x0c,
+  0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x0f, 0x00, 0x00, 0x18, 0x0c, 0x08, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xe4,
+  0xb1, 0xc1, 0x98, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0xe4, 0xb1, 0xc1, 0x98, 0x00,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x08, 0x00, 0x00, 0x1c, 0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c,
+  0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00,
+  0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x09, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x9c,
+  0x01, 0x08, 0x83, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40,
+  0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40, 0x30, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x03, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x9b,
+  0x01, 0xc0, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0x9b, 0x01, 0xc0, 0x00, 0x00,
+  0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0x00, 0x00, 0x00, 0x07, 0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x07,
+  0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x10, 0xe0,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x7b, 0x00, 0x30, 0x03, 0x0c,
+  0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x07, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x09, 0x00, 0xc0, 0x84, 0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xfd, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x84,
+  0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x03, 0xf0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40,
+  0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xfc, 0x01, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40, 0x08, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x07, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
+  0xf8, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x64,
+  0x42, 0x06, 0x1b, 0x03, 0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x10, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x64, 0x42, 0x06, 0x1b, 0x03,
+  0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x0f, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x3f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x1b,
+  0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xc3, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xe0, 0x84, 0x31, 0x30, 0x04, 0x80,
+  0xc1, 0x18, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x09, 0x00, 0xc0, 0x63, 0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0xc0, 0x63,
+  0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c,
+  0x06, 0x81, 0x80, 0xfd, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c, 0x06, 0x81, 0x80, 0xfd,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x20, 0x63,
+  0x0c, 0x08, 0x80, 0x00, 0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x20, 0x63, 0x0c, 0x08, 0x80, 0x00,
+  0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x0f, 0x00, 0xd8, 0x84, 0x01, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x80, 0xf1,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf8, 0x1b,
+  0x40, 0x08, 0x84, 0x0c, 0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xe0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xf8, 0x1b, 0x40, 0x08, 0x84, 0x0c,
+  0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0xe4, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x09, 0x00, 0x38, 0x80, 0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x38, 0x80,
+  0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x10, 0x84,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00,
+  0x00, 0x00, 0x03, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x08, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00, 0x00, 0x00, 0x03, 0xf2,
+  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
+  0x08, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x3e, 0x00,
+  0x82, 0x01, 0x03, 0x40, 0x30, 0x98, 0x10, 0xf0, 0xe7, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x10, 0xe4,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c,
+  0x00, 0x00, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x30, 0x7c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0xfc,
+  0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+  0x08, 0x00, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64,
+  0x30, 0xc6, 0x80, 0x80, 0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf8, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0e, 0x00, 0xc0, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64, 0x30, 0xc6, 0x80, 0x80,
+  0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc3, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x00, 0x39, 0x03, 0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x39, 0x03,
+  0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0xe7, 0x04, 0x42, 0xc6, 0x00, 0x00,
+  0x00, 0x00, 0xec, 0xcf, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x0f, 0xc0, 0x1f, 0x80, 0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01,
+  0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x01, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x1f, 0x80,
+  0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01, 0x00, 0xe0, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3f, 0x08, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00,
+  0xc0, 0x60, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x1f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x00, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00, 0xc0, 0x60, 0x7c, 0x00,
+  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xc0, 0x19, 0x60,
+  0x40, 0x00, 0x63, 0x30, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xf3, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x09, 0xc0, 0x19, 0x60, 0x40, 0x00, 0x63, 0x30,
+  0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xf3, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0xc0, 0x27, 0x03, 0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0xcf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x27, 0x03,
+  0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x0f, 0xc0, 0xde, 0x04, 0x0c, 0x06, 0x03, 0x80,
+  0xc1, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x0f, 0xc0, 0x19, 0x00, 0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f,
+  0x07, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x19, 0x00,
+  0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x07, 0x00, 0x18, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03,
+  0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x1f, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
+  0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03, 0xf0, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
+  0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31,
+  0x04, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0xd9, 0x04,
+  0x00, 0x08, 0x00, 0x80, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x60, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0xd9, 0x04, 0x00, 0x08, 0x00, 0x80,
+  0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x78, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0xc0, 0x27, 0x00, 0x30, 0xc0, 0x60, 0xb0, 0xff, 0x7f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b,
+  0x8d, 0x01, 0x04, 0xc3, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0xf1, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x03, 0x00, 0xf0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b, 0x8d, 0x01, 0x04, 0xc3,
+  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf1, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0x39, 0x04, 0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x39, 0x04,
+  0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xff, 0x07,
+  0xb0, 0x09, 0xe4, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x30, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff,
+  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08,
+  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07,
+  0xb0, 0xc9, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07, 0xb0, 0xc9, 0xf8, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x0f, 0x00, 0xe7, 0xfb, 0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0xe7, 0xfb,
+  0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xe0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xfe, 0x1c, 0xb2, 0x0f, 0xe0, 0xff,
+  0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0xf8, 0xe7, 0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0,
+  0xb1, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf8, 0xe7,
+  0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0xb1, 0x3f, 0x00, 0x00,
+  0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff,
+  0x01, 0x00, 0xe0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x98, 0x4f, 0x0e, 0x18, 0x00, 0xf8, 0xff, 0xff, 0xff,
+  0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff, 0x01, 0x00, 0xe0, 0x03,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+  0x4f, 0x0e, 0xf8, 0x1f, 0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf8, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x1f,
+  0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
+  0x00, 0xce, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0xe3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xe0, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xce, 0xff, 0x7f,
+  0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x1b, 0xb2, 0x31, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0xe0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c,
+  0x00, 0xc0, 0xff, 0x73, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
+  0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c, 0x00, 0xc0, 0x7f, 0x1c,
+  0x30, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x38, 0x87, 0x31, 0x06, 0x7c, 0x1c, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x87,
+  0x31, 0x06, 0xfc, 0x0f, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x38,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0xe3, 0x0f,
+  0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xe0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0x03, 0x00, 0xf0, 0xff, 0xff, 0xff,
+  0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b,
+  0x4c, 0x00, 0x04, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x01, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xc0, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x18, 0x80,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x78, 0xf3, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x08, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04,
+  0x02, 0x30, 0x60, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc0, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04, 0x02, 0x30, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc6, 0x04, 0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x04,
+  0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x67, 0x00, 0x06, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x04, 0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04,
+  0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08,
+  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x1c, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x02, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c,
+  0x0c, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
+  0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe0,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c, 0x0c, 0x06, 0xfb, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x68, 0x7c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf8, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x18, 0xfe, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b,
+  0x81, 0x01, 0x60, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80,
+  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b, 0x81, 0x01, 0x00, 0x00,
+  0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x38, 0x78, 0x0c, 0x30, 0x04, 0x00, 0xf6, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78,
+  0x0c, 0x30, 0x04, 0x00, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8,
+  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0x1c, 0x00,
+  0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0x58, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
+  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0,
+  0x01, 0x36, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
+  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
+  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0x36, 0xfc, 0x1f,
+  0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc6, 0x87, 0x0f, 0x00, 0xff, 0x1f, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xcf, 0x03, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0x40, 0xc0, 0xff, 0x7f, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0x03, 0x00, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0xc0, 0xff, 0x7f,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
+  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x7f,
+  0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0x07, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0x4c, 0x00, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x1f,
+  0x00, 0xff, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x0f, 0x00, 0xff, 0xff, 0x03,
+  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
+  0x41, 0x00, 0xe0, 0x0f, 0x00, 0xff, 0xff, 0x03, 0xff, 0x03, 0x00, 0x38,
+  0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 0x00, 0x00, 0x80,
+  0xc9, 0xf9, 0xff, 0x3d, 0xff, 0x03, 0x00, 0x78, 0xc0, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0x32, 0x08, 0x00, 0x80, 0xc9, 0xf9, 0xff, 0x3d,
+  0xff, 0x03, 0x00, 0xf8, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x02, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0x32, 0x08, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0xf8,
+  0x81, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xff,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0xf8, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0x38, 0x03, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff,
+  0x3f, 0x00, 0x00, 0x38, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38,
+  0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0xfc,
+  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38, 0xfc, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x00, 0x38, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
+  0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x78,
+  0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff,
+  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0xc1, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x60, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
+  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x08, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x67,
+  0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x13, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0xff,
+  0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x67, 0xfe, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf0, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
+  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x0f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x98,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xf8, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x00, 0xc0, 0xff, 0x67, 0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf8,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0xff, 0x67,
+  0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c,
+  0x37, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
+  0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
+  0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c, 0x37, 0x80, 0x0c, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfc,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0xc0, 0xfe, 0x03,
+  0x8c, 0x09, 0xe3, 0x73, 0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xfe, 0x03, 0x8c, 0x09, 0xe3, 0x73,
+  0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0xc0, 0x27, 0xe7, 0x31, 0x36, 0x04, 0x8c, 0x01, 0x60, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18,
+  0x42, 0xc0, 0x98, 0x30, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18, 0x42, 0xc0, 0x98, 0x30,
+  0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0xc0, 0x27, 0x63, 0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x27, 0x63,
+  0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0,
+  0x31, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff,
+  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0, 0x31, 0x19, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x07,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0xc0, 0x1e, 0x63,
+  0x00, 0x30, 0x04, 0x03, 0xc8, 0x60, 0x00, 0x0e, 0x00, 0x00, 0xfc, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0,
+  0x01, 0xe7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x0f, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0, 0x01, 0xe7, 0xf3, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x0f, 0xc0, 0x1e, 0x03,
+  0x02, 0x08, 0x04, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xd8, 0x0f, 0xc0, 0x1e, 0x03, 0x02, 0x08, 0x04, 0x00,
+  0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xc0, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x0b, 0x00, 0x21, 0x64, 0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfb, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x21, 0x64,
+  0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfd, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00,
+  0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf,
+  0x01, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00, 0x0e, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
+  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf0, 0x03, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x0b, 0xc0, 0xc0, 0x84,
+  0x31, 0xc0, 0x00, 0x4c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0f, 0x0e, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80,
+  0x09, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0xc3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x0c, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80, 0x09, 0xff, 0xff, 0x3f,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
+  0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0xc0, 0xc1, 0x03,
+  0x4c, 0x00, 0x00, 0x30, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x90, 0x13, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0xc0, 0xc1, 0x03, 0x4c, 0x00, 0x00, 0x30,
+  0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x00, 0xc0, 0x3f, 0x98, 0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
+  0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x98,
+  0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xc6, 0x03, 0x40, 0x00, 0x00, 0x80,
+  0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
+  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xef, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
+  0x00, 0x00, 0x3f, 0x18, 0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xef, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x18,
+  0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xc7, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30,
+  0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
+  0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30, 0x30, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04,
+  0x02, 0x00, 0x00, 0x83, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x04, 0x02, 0x00, 0x00, 0x83,
+  0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
+  0x03, 0x00, 0xe0, 0x1b, 0x0c, 0x08, 0x18, 0x40, 0x30, 0xfe, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84,
+  0x81, 0x01, 0x03, 0x0c, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84, 0x81, 0x01, 0x03, 0x0c,
+  0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
+  0x0e, 0x00, 0x00, 0x1b, 0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x1b,
+  0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40,
+  0x00, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40, 0x00, 0xe1, 0xff, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
+  0x30, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x9c,
+  0x01, 0x08, 0x60, 0x0c, 0x06, 0x86, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff,
+  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00,
+  0xc0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xf0, 0x9f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
+  0x07, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00, 0xc0, 0x00, 0xfc, 0xff,
+  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0xe0,
+  0x01, 0x06, 0x00, 0x30, 0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
+  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x06, 0x00, 0x30,
+  0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
+  0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff,
+  0xff, 0xff, 0xff, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
+  0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00,
+  0x00, 0x06, 0x83, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00, 0x00, 0x06, 0x83, 0xff,
+  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x00, 0xc0, 0x00, 0x8c, 0xc9, 0x60, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
+  0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
+  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+  0x04, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
+  0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x0c,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0f, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
+  0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc6,
+  0x03, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xef, 0x07, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xd8, 0xef, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x1c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3,
+  0x0f, 0x00, 0x00, 0x00, 0x80, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x88, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x13,
+  0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
+  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x88, 0xf3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3,
+  0x0f, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe1, 0x1f, 0x00, 0x00, 0x00,
+  0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0xf0, 0xc1, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+  };
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68EZ328/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/68EZ328/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68EZ328/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68EZ328/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,76 @@
+/***************************************************************************/
+
+/*
+ *  linux/arch/m68knommu/platform/68EZ328/config.c
+ *
+ *  Copyright (C) 1993 Hamish Macdonald
+ *  Copyright (C) 1999 D. Jeff Dionne
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/MC68EZ328.h>
+#ifdef CONFIG_UCSIMM
+#include <asm/bootstd.h>
+#endif
+
+/***************************************************************************/
+
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
+
+/***************************************************************************/
+
+void m68ez328_reset(void)
+{
+  local_irq_disable();
+  asm volatile (
+    "moveal #0x10c00000, %a0;\n"
+    "moveb #0, 0xFFFFF300;\n"
+    "moveal 0(%a0), %sp;\n"
+    "moveal 4(%a0), %a0;\n"
+    "jmp (%a0);\n"
+    );
+}
+
+/***************************************************************************/
+
+unsigned char *cs8900a_hwaddr;
+static int errno;
+
+#ifdef CONFIG_UCSIMM
+_bsc0(char *, getserialnum)
+_bsc1(unsigned char *, gethwaddr, int, a)
+_bsc1(char *, getbenv, char *, a)
+#endif
+
+void config_BSP(char *command, int len)
+{
+  unsigned char *p;
+
+  printk(KERN_INFO "\n68EZ328 DragonBallEZ support (C) 1999 Rt-Control, Inc\n");
+
+#ifdef CONFIG_UCSIMM
+  printk(KERN_INFO "uCsimm serial string [%s]\n",getserialnum());
+  p = cs8900a_hwaddr = gethwaddr(0);
+  printk(KERN_INFO "uCsimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+         p[0], p[1], p[2], p[3], p[4], p[5]);
+
+  p = getbenv("APPEND");
+  if (p) strcpy(p,command);
+  else command[0] = 0;
+#endif
+ 
+  mach_gettod = m68328_timer_gettod;
+  mach_reset = m68ez328_reset;
+}
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68EZ328/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/68EZ328/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68EZ328/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68EZ328/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,11 @@
+#
+# Makefile for arch/m68knommu/platform/68EZ328.
+#
+
+obj-y := config.o
+
+extra-y := bootlogo.rh
+
+$(obj)/bootlogo.rh: $(src)/bootlogo.h
+	perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \
+		> $(obj)/bootlogo.rh
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68VZ328/config.c linux-libre-2.6.39-gnu/arch/m68k/platform/68VZ328/config.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68VZ328/config.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68VZ328/config.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,188 @@
+/***************************************************************************/
+
+/*
+ *  linux/arch/m68knommu/platform/68VZ328/config.c
+ *
+ *  Copyright (C) 1993 Hamish Macdonald
+ *  Copyright (C) 1999 D. Jeff Dionne
+ *  Copyright (C) 2001 Georges Menie, Ken Desmet
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/kd.h>
+#include <linux/netdevice.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/machdep.h>
+#include <asm/MC68VZ328.h>
+#include <asm/bootstd.h>
+
+#ifdef CONFIG_INIT_LCD
+#include "bootlogo.h"
+#endif
+
+/***************************************************************************/
+
+void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
+
+/***************************************************************************/
+/*                        Init Drangon Engine hardware                     */
+/***************************************************************************/
+#if defined(CONFIG_DRAGEN2)
+
+static void m68vz328_reset(void)
+{
+	local_irq_disable();
+
+#ifdef CONFIG_INIT_LCD
+	PBDATA |= 0x20;				/* disable CCFL light */
+	PKDATA |= 0x4;				/* disable LCD controller */
+	LCKCON = 0;
+#endif
+
+	__asm__ __volatile__(
+		"reset\n\t"
+		"moveal #0x04000000, %a0\n\t"
+		"moveal 0(%a0), %sp\n\t"
+		"moveal 4(%a0), %a0\n\t"
+		"jmp (%a0)"
+	);
+}
+
+static void init_hardware(char *command, int size)
+{
+#ifdef CONFIG_DIRECT_IO_ACCESS
+	SCR = 0x10;					/* allow user access to internal registers */
+#endif
+
+	/* CSGB Init */
+	CSGBB = 0x4000;
+	CSB = 0x1a1;
+
+	/* CS8900 init */
+	/* PK3: hardware sleep function pin, active low */
+	PKSEL |= PK(3);				/* select pin as I/O */
+	PKDIR |= PK(3);				/* select pin as output */
+	PKDATA |= PK(3);			/* set pin high */
+
+	/* PF5: hardware reset function pin, active high */
+	PFSEL |= PF(5);				/* select pin as I/O */
+	PFDIR |= PF(5);				/* select pin as output */
+	PFDATA &= ~PF(5);			/* set pin low */
+
+	/* cs8900 hardware reset */
+	PFDATA |= PF(5);
+	{ int i; for (i = 0; i < 32000; ++i); }
+	PFDATA &= ~PF(5);
+
+	/* INT1 enable (cs8900 IRQ) */
+	PDPOL &= ~PD(1);			/* active high signal */
+	PDIQEG &= ~PD(1);
+	PDIRQEN |= PD(1);			/* IRQ enabled */
+
+#ifdef CONFIG_INIT_LCD
+	/* initialize LCD controller */
+	LSSA = (long) screen_bits;
+	LVPW = 0x14;
+	LXMAX = 0x140;
+	LYMAX = 0xef;
+	LRRA = 0;
+	LPXCD = 3;
+	LPICF = 0x08;
+	LPOLCF = 0;
+	LCKCON = 0x80;
+	PCPDEN = 0xff;
+	PCSEL = 0;
+
+	/* Enable LCD controller */
+	PKDIR |= 0x4;
+	PKSEL |= 0x4;
+	PKDATA &= ~0x4;
+
+	/* Enable CCFL backlighting circuit */
+	PBDIR |= 0x20;
+	PBSEL |= 0x20;
+	PBDATA &= ~0x20;
+
+	/* contrast control register */
+	PFDIR |= 0x1;
+	PFSEL &= ~0x1;
+	PWMR = 0x037F;
+#endif
+}
+
+/***************************************************************************/
+/*                      Init RT-Control uCdimm hardware                    */
+/***************************************************************************/
+#elif defined(CONFIG_UCDIMM)
+
+static void m68vz328_reset(void)
+{
+	local_irq_disable();
+	asm volatile (
+		"moveal #0x10c00000, %a0;\n\t"
+		"moveb #0, 0xFFFFF300;\n\t"
+		"moveal 0(%a0), %sp;\n\t"
+		"moveal 4(%a0), %a0;\n\t"
+		"jmp (%a0);\n"
+	);
+}
+
+unsigned char *cs8900a_hwaddr;
+static int errno;
+
+_bsc0(char *, getserialnum)
+_bsc1(unsigned char *, gethwaddr, int, a)
+_bsc1(char *, getbenv, char *, a)
+
+static void init_hardware(char *command, int size)
+{
+	char *p;
+
+	printk(KERN_INFO "uCdimm serial string [%s]\n", getserialnum());
+	p = cs8900a_hwaddr = gethwaddr(0);
+	printk(KERN_INFO "uCdimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+		p[0], p[1], p[2], p[3], p[4], p[5]);
+	p = getbenv("APPEND");
+	if (p)
+		strcpy(p, command);
+	else
+		command[0] = 0;
+}
+
+/***************************************************************************/
+#else
+
+static void m68vz328_reset(void)
+{
+}
+
+static void init_hardware(char *command, int size)
+{
+}
+
+/***************************************************************************/
+#endif
+/***************************************************************************/
+
+void config_BSP(char *command, int size)
+{
+	printk(KERN_INFO "68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
+
+	init_hardware(command, size);
+
+	mach_gettod = m68328_timer_gettod;
+	mach_reset = m68vz328_reset;
+}
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/68VZ328/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/68VZ328/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/68VZ328/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/68VZ328/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,16 @@
+#
+# Makefile for arch/m68knommu/platform/68VZ328.
+#
+
+obj-y		:= config.o
+logo-$(UCDIMM)	:= bootlogo.rh
+logo-$(DRAGEN2)	:= screen.h
+extra-y		:= $(logo-y)
+
+$(obj)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h
+	perl $(src)/bootlogo.pl < $(src)/../68328/bootlogo.h > $(obj)/bootlogo.rh
+
+$(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
+	perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
+
+clean-files := $(obj)/screen.h $(obj)/bootlogo.rh
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/cache.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/cache.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/cache.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/cache.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,48 @@
+/***************************************************************************/
+
+/*
+ *	cache.c -- general ColdFire Cache maintenance code
+ *
+ *	Copyright (C) 2010, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+#ifdef CACHE_PUSH
+/***************************************************************************/
+
+/*
+ *	Use cpushl to push all dirty cache lines back to memory.
+ *	Older versions of GAS don't seem to know how to generate the
+ *	ColdFire cpushl instruction... Oh well, bit stuff it for now.
+ */
+
+void mcf_cache_push(void)
+{
+	__asm__ __volatile__ (
+		"clrl	%%d0\n\t"
+		"1:\n\t"
+		"movel	%%d0,%%a0\n\t"
+		"2:\n\t"
+		".word	0xf468\n\t"
+		"addl	%0,%%a0\n\t"
+		"cmpl	%1,%%a0\n\t"
+		"blt	2b\n\t"
+		"addql	#1,%%d0\n\t"
+		"cmpil	%2,%%d0\n\t"
+		"bne	1b\n\t"
+		: /* No output */
+		: "i" (CACHE_LINE_SIZE),
+		  "i" (DCACHE_SIZE / CACHE_WAYS),
+		  "i" (CACHE_WAYS)
+		: "d0", "a0" );
+}
+
+/***************************************************************************/
+#endif /* CACHE_PUSH */
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/clk.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/clk.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/clk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/clk.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,45 @@
+/***************************************************************************/
+
+/*
+ *	clk.c -- general ColdFire CPU kernel clk handling
+ *
+ *	Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/clk.h>
+#include <asm/coldfire.h>
+
+/***************************************************************************/
+
+struct clk *clk_get(struct device *dev, const char *id)
+{
+	return NULL;
+}
+EXPORT_SYMBOL(clk_get);
+
+int clk_enable(struct clk *clk)
+{
+	return 0;
+}
+EXPORT_SYMBOL(clk_enable);
+
+void clk_disable(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_disable);
+
+void clk_put(struct clk *clk)
+{
+}
+EXPORT_SYMBOL(clk_put);
+
+unsigned long clk_get_rate(struct clk *clk)
+{
+	return MCF_CLK;
+}
+EXPORT_SYMBOL(clk_get_rate);
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/dma.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/dma.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,39 @@
+/***************************************************************************/
+
+/*
+ *	dma.c -- Freescale ColdFire DMA support
+ *
+ *	Copyright (C) 2007, Greg Ungerer (gerg@snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <asm/dma.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfdma.h>
+
+/***************************************************************************/
+
+/*
+ *      DMA channel base address table.
+ */
+unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
+#ifdef MCFDMA_BASE0
+	MCFDMA_BASE0,
+#endif
+#ifdef MCFDMA_BASE1
+	MCFDMA_BASE1,
+#endif
+#ifdef MCFDMA_BASE2
+	MCFDMA_BASE2,
+#endif
+#ifdef MCFDMA_BASE3
+	MCFDMA_BASE3,
+#endif
+};
+
+unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/dma_timer.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/dma_timer.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/dma_timer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/dma_timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ * dma_timer.c -- Freescale ColdFire DMA Timer.
+ *
+ * Copyright (C) 2007, Benedikt Spranger <b.spranger@linutronix.de>
+ * Copyright (C) 2008. Sebastian Siewior, Linutronix
+ *
+ */
+
+#include <linux/clocksource.h>
+#include <linux/io.h>
+
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfpit.h>
+#include <asm/mcfsim.h>
+
+#define DMA_TIMER_0	(0x00)
+#define DMA_TIMER_1	(0x40)
+#define DMA_TIMER_2	(0x80)
+#define DMA_TIMER_3	(0xc0)
+
+#define DTMR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x400)
+#define DTXMR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x402)
+#define DTER0	(MCF_IPSBAR + DMA_TIMER_0 + 0x403)
+#define DTRR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x404)
+#define DTCR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x408)
+#define DTCN0	(MCF_IPSBAR + DMA_TIMER_0 + 0x40c)
+
+#define DMA_FREQ    ((MCF_CLK / 2) / 16)
+
+/* DTMR */
+#define DMA_DTMR_RESTART	(1 << 3)
+#define DMA_DTMR_CLK_DIV_1	(1 << 1)
+#define DMA_DTMR_CLK_DIV_16	(2 << 1)
+#define DMA_DTMR_ENABLE		(1 << 0)
+
+static cycle_t cf_dt_get_cycles(struct clocksource *cs)
+{
+	return __raw_readl(DTCN0);
+}
+
+static struct clocksource clocksource_cf_dt = {
+	.name		= "coldfire_dma_timer",
+	.rating		= 200,
+	.read		= cf_dt_get_cycles,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.shift		= 20,
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static int __init  init_cf_dt_clocksource(void)
+{
+	/*
+	 * We setup DMA timer 0 in free run mode. This incrementing counter is
+	 * used as a highly precious clock source. With MCF_CLOCK = 150 MHz we
+	 * get a ~213 ns resolution and the 32bit register will overflow almost
+	 * every 15 minutes.
+	 */
+	__raw_writeb(0x00, DTXMR0);
+	__raw_writeb(0x00, DTER0);
+	__raw_writel(0x00000000, DTRR0);
+	__raw_writew(DMA_DTMR_CLK_DIV_16 | DMA_DTMR_ENABLE, DTMR0);
+	clocksource_cf_dt.mult = clocksource_hz2mult(DMA_FREQ,
+						     clocksource_cf_dt.shift);
+	return clocksource_register(&clocksource_cf_dt);
+}
+
+arch_initcall(init_cf_dt_clocksource);
+
+#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
+#define CYC2NS_SCALE	((1000000 << CYC2NS_SCALE_FACTOR) / (DMA_FREQ / 1000))
+
+static unsigned long long cycles2ns(unsigned long cycl)
+{
+	return (unsigned long long) ((unsigned long long)cycl *
+			CYC2NS_SCALE) >> CYC2NS_SCALE_FACTOR;
+}
+
+unsigned long long sched_clock(void)
+{
+	unsigned long cycl = __raw_readl(DTCN0);
+
+	return cycles2ns(cycl);
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/entry.S linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/entry.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,203 @@
+/*
+ *  linux/arch/m68knommu/platform/5307/entry.S
+ *
+ *  Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
+ *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
+ *                      Kenneth Albanowski <kjahds@kjahds.com>,
+ *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
+ *  Copyright (C) 2004-2006  Macq Electronique SA. (www.macqel.com)
+ *
+ * Based on:
+ *
+ *  linux/arch/m68k/kernel/entry.S
+ *
+ *  Copyright (C) 1991, 1992  Linus Torvalds
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file README.legal in the main directory of this archive
+ * for more details.
+ *
+ * Linux/m68k support by Hamish Macdonald
+ *
+ * 68060 fixes by Jesper Skov
+ * ColdFire support by Greg Ungerer (gerg@snapgear.com)
+ * 5307 fixes by David W. Miller
+ * linux 2.4 support David McCullough <davidm@snapgear.com>
+ * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be>
+ */
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <asm/unistd.h>
+#include <asm/thread_info.h>
+#include <asm/errno.h>
+#include <asm/setup.h>
+#include <asm/segment.h>
+#include <asm/asm-offsets.h>
+#include <asm/entry.h>
+
+#ifdef CONFIG_COLDFIRE_SW_A7
+/*
+ *	Define software copies of the supervisor and user stack pointers.
+ */
+.bss
+sw_ksp:
+.long	0
+sw_usp:
+.long	0
+#endif /* CONFIG_COLDFIRE_SW_A7 */
+
+.text
+
+.globl system_call
+.globl resume
+.globl ret_from_exception
+.globl ret_from_signal
+.globl sys_call_table
+.globl inthandler
+.globl fasthandler
+
+enosys:
+	mov.l	#sys_ni_syscall,%d3
+	bra	1f
+
+ENTRY(system_call)
+	SAVE_ALL
+	move	#0x2000,%sr		/* enable intrs again */
+
+	cmpl	#NR_syscalls,%d0
+	jcc	enosys
+	lea	sys_call_table,%a0
+	lsll	#2,%d0			/* movel %a0@(%d0:l:4),%d3 */
+	movel	%a0@(%d0),%d3
+	jeq	enosys
+
+1:
+	movel	%sp,%d2			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d2	/* at start of kernel stack */
+	movel	%d2,%a0
+	movel	%a0@,%a1		/* save top of frame */
+	movel	%sp,%a1@(TASK_THREAD+THREAD_ESP0)
+	btst	#(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
+	bnes	1f
+
+	movel	%d3,%a0
+	jbsr	%a0@
+	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
+	jra	ret_from_exception
+1:
+	movel	#-ENOSYS,%d2		/* strace needs -ENOSYS in PT_OFF_D0 */
+	movel	%d2,PT_OFF_D0(%sp)	/* on syscall entry */
+	subql	#4,%sp
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_enter
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	movel	%d3,%a0
+	jbsr	%a0@
+	movel	%d0,%sp@(PT_OFF_D0)		/* save the return value */
+	subql	#4,%sp			/* dummy return address */
+	SAVE_SWITCH_STACK
+	jbsr	syscall_trace_leave
+
+ret_from_signal:
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+
+ret_from_exception:
+	move	#0x2700,%sr		/* disable intrs */
+	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel */
+	jeq	Luser_return		/* if so, skip resched, signals */
+
+#ifdef CONFIG_PREEMPT
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
+	movel	%d1,%a0
+	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
+	andl	#(1<<TIF_NEED_RESCHED),%d1
+	jeq	Lkernel_return
+
+	movel	%a0@(TI_PREEMPTCOUNT),%d1
+	cmpl	#0,%d1
+	jne	Lkernel_return
+
+	pea	Lkernel_return
+	jmp	preempt_schedule_irq	/* preempt the kernel */
+#endif
+
+Lkernel_return:
+	moveml	%sp@,%d1-%d5/%a0-%a2
+	lea	%sp@(32),%sp		/* space for 8 regs */
+	movel	%sp@+,%d0
+	addql	#4,%sp			/* orig d0 */
+	addl	%sp@+,%sp		/* stk adj */
+	rte
+
+Luser_return:
+	movel	%sp,%d1			/* get thread_info pointer */
+	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
+	movel	%d1,%a0
+	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
+	jne	Lwork_to_do		/* still work to do */
+
+Lreturn:
+	RESTORE_USER
+
+Lwork_to_do:
+	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
+	move	#0x2000,%sr		/* enable intrs again */
+	btst	#TIF_NEED_RESCHED,%d1
+	jne	reschedule
+
+	/* GERG: do we need something here for TRACEing?? */
+
+Lsignal_return:
+	subql	#4,%sp			/* dummy return address */
+	SAVE_SWITCH_STACK
+	pea	%sp@(SWITCH_STACK_SIZE)
+	jsr	do_signal
+	addql	#4,%sp
+	RESTORE_SWITCH_STACK
+	addql	#4,%sp
+	jmp	Luser_return
+
+/*
+ * This is the generic interrupt handler (for all hardware interrupt
+ * sources). Calls up to high level code to do all the work.
+ */
+ENTRY(inthandler)
+	SAVE_ALL
+	moveq	#-1,%d0
+	movel	%d0,%sp@(PT_OFF_ORIG_D0)
+
+	movew	%sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */
+	andl	#0x03fc,%d0		/* mask out vector only */
+
+	movel	%sp,%sp@-		/* push regs arg */
+	lsrl	#2,%d0			/* calculate real vector # */
+	movel	%d0,%sp@-		/* push vector number */
+	jbsr	do_IRQ			/* call high level irq handler */
+	lea	%sp@(8),%sp		/* pop args off stack */
+
+	bra	ret_from_exception
+
+/*
+ * Beware - when entering resume, prev (the current task) is
+ * in a0, next (the new task) is in a1,so don't change these
+ * registers until their contents are no longer needed.
+ * This is always called in supervisor mode, so don't bother to save
+ * and restore sr; user's process sr is actually in the stack.
+ */
+ENTRY(resume)
+	movel	%a0, %d1			/* get prev thread in d1 */
+	RDUSP
+	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
+
+	SAVE_SWITCH_STACK
+	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
+	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
+	RESTORE_SWITCH_STACK
+
+	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
+	WRUSP
+	rts
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/gpio.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,127 @@
+/*
+ * Coldfire generic GPIO support.
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/sysdev.h>
+
+#include <asm/gpio.h>
+#include <asm/pinmux.h>
+#include <asm/mcfgpio.h>
+
+#define MCF_CHIP(chip) container_of(chip, struct mcf_gpio_chip, gpio_chip)
+
+int mcf_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long flags;
+	MCFGPIO_PORTTYPE dir;
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	local_irq_save(flags);
+	dir = mcfgpio_read(mcf_chip->pddr);
+	dir &= ~mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(dir, mcf_chip->pddr);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+int mcf_gpio_get_value(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	return mcfgpio_read(mcf_chip->ppdr) & mcfgpio_bit(chip->base + offset);
+}
+
+int mcf_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	unsigned long flags;
+	MCFGPIO_PORTTYPE data;
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	local_irq_save(flags);
+	/* write the value to the output latch */
+	data = mcfgpio_read(mcf_chip->podr);
+	if (value)
+		data |= mcfgpio_bit(chip->base + offset);
+	else
+		data &= ~mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(data, mcf_chip->podr);
+
+	/* now set the direction to output */
+	data = mcfgpio_read(mcf_chip->pddr);
+	data |= mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(data, mcf_chip->pddr);
+	local_irq_restore(flags);
+
+	return 0;
+}
+
+void mcf_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	unsigned long flags;
+	MCFGPIO_PORTTYPE data;
+
+	local_irq_save(flags);
+	data = mcfgpio_read(mcf_chip->podr);
+	if (value)
+		data |= mcfgpio_bit(chip->base + offset);
+	else
+		data &= ~mcfgpio_bit(chip->base + offset);
+	mcfgpio_write(data, mcf_chip->podr);
+	local_irq_restore(flags);
+}
+
+void mcf_gpio_set_value_fast(struct gpio_chip *chip, unsigned offset, int value)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	if (value)
+		mcfgpio_write(mcfgpio_bit(chip->base + offset), mcf_chip->setr);
+	else
+		mcfgpio_write(~mcfgpio_bit(chip->base + offset), mcf_chip->clrr);
+}
+
+int mcf_gpio_request(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	return mcf_chip->gpio_to_pinmux ?
+		mcf_pinmux_request(mcf_chip->gpio_to_pinmux[offset], 0) : 0;
+}
+
+void mcf_gpio_free(struct gpio_chip *chip, unsigned offset)
+{
+	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
+
+	mcf_gpio_direction_input(chip, offset);
+
+	if (mcf_chip->gpio_to_pinmux)
+		mcf_pinmux_release(mcf_chip->gpio_to_pinmux[offset], 0);
+}
+
+struct sysdev_class mcf_gpio_sysclass = {
+	.name	= "gpio",
+};
+
+static int __init mcf_gpio_sysinit(void)
+{
+	return sysdev_class_register(&mcf_gpio_sysclass);
+}
+
+core_initcall(mcf_gpio_sysinit);
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/head.S linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/head.S
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/head.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,250 @@
+/*****************************************************************************/
+
+/*
+ *	head.S -- common startup code for ColdFire CPUs.
+ *
+ *	(C) Copyright 1999-2010, Greg Ungerer <gerg@snapgear.com>.
+ */
+
+/*****************************************************************************/
+
+#include <linux/sys.h>
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/asm-offsets.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/thread_info.h>
+
+/*****************************************************************************/
+
+/*
+ *	If we don't have a fixed memory size, then lets build in code
+ *	to auto detect the DRAM size. Obviously this is the preferred
+ *	method, and should work for most boards. It won't work for those
+ *	that do not have their RAM starting at address 0, and it only
+ *	works on SDRAM (not boards fitted with SRAM).
+ */
+#if CONFIG_RAMSIZE != 0
+.macro GET_MEM_SIZE
+	movel	#CONFIG_RAMSIZE,%d0	/* hard coded memory size */
+.endm
+
+#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
+      defined(CONFIG_M5249) || defined(CONFIG_M527x) || \
+      defined(CONFIG_M528x) || defined(CONFIG_M5307) || \
+      defined(CONFIG_M5407)
+/*
+ *	Not all these devices have exactly the same DRAM controller,
+ *	but the DCMR register is virtually identical - give or take
+ *	a couple of bits. The only exception is the 5272 devices, their
+ *	DRAM controller is quite different.
+ */
+.macro GET_MEM_SIZE
+	movel	MCFSIM_DMR0,%d0		/* get mask for 1st bank */
+	btst	#0,%d0			/* check if region enabled */
+	beq	1f
+	andl	#0xfffc0000,%d0
+	beq	1f
+	addl	#0x00040000,%d0		/* convert mask to size */
+1:
+	movel	MCFSIM_DMR1,%d1		/* get mask for 2nd bank */
+	btst	#0,%d1			/* check if region enabled */
+	beq	2f
+	andl	#0xfffc0000,%d1
+	beq	2f
+	addl	#0x00040000,%d1
+	addl	%d1,%d0			/* total mem size in d0 */
+2:
+.endm
+
+#elif defined(CONFIG_M5272)
+.macro GET_MEM_SIZE
+	movel	MCF_MBAR+MCFSIM_CSOR7,%d0 /* get SDRAM address mask */
+	andil	#0xfffff000,%d0		/* mask out chip select options */
+	negl	%d0			/* negate bits */
+.endm
+
+#elif defined(CONFIG_M520x)
+.macro GET_MEM_SIZE
+	clrl	%d0
+	movel	MCFSIM_SDCS0, %d2	/* Get SDRAM chip select 0 config */
+	andl	#0x1f, %d2		/* Get only the chip select size */
+	beq	3f			/* Check if it is enabled */
+	addql	#1, %d2			/* Form exponent */
+	moveql	#1, %d0
+	lsll	%d2, %d0		/* 2 ^ exponent */
+3:
+	movel	MCFSIM_SDCS1, %d2	/* Get SDRAM chip select 1 config */
+	andl	#0x1f, %d2		/* Get only the chip select size */
+	beq	4f			/* Check if it is enabled */
+	addql	#1, %d2			/* Form exponent */
+	moveql	#1, %d1
+	lsll	%d2, %d1		/* 2 ^ exponent */
+	addl	%d1, %d0		/* Total size of SDRAM in d0 */
+4:
+.endm
+
+#else
+#error "ERROR: I don't know how to probe your boards memory size?"
+#endif
+
+/*****************************************************************************/
+
+/*
+ *	Boards and platforms can do specific early hardware setup if
+ *	they need to. Most don't need this, define away if not required.
+ */
+#ifndef PLATFORM_SETUP
+#define	PLATFORM_SETUP
+#endif
+
+/*****************************************************************************/
+
+.global	_start
+.global _rambase
+.global _ramvec
+.global	_ramstart
+.global	_ramend
+#if defined(CONFIG_UBOOT)
+.global	_init_sp
+#endif
+
+/*****************************************************************************/
+
+.data
+
+/*
+ *	During startup we store away the RAM setup. These are not in the
+ *	bss, since their values are determined and written before the bss
+ *	has been cleared.
+ */
+_rambase:
+.long	0
+_ramvec:
+.long	0
+_ramstart:
+.long	0
+_ramend:
+.long	0
+#if defined(CONFIG_UBOOT)
+_init_sp:
+.long	0
+#endif
+
+/*****************************************************************************/
+
+__HEAD
+
+/*
+ *	This is the codes first entry point. This is where it all
+ *	begins...
+ */
+
+_start:
+	nop					/* filler */
+	movew	#0x2700, %sr			/* no interrupts */
+#if defined(CONFIG_UBOOT)
+	movel	%sp,_init_sp			/* save initial stack pointer */
+#endif
+
+	/*
+	 *	Do any platform or board specific setup now. Most boards
+	 *	don't need anything. Those exceptions are define this in
+	 *	their board specific includes.
+	 */
+	PLATFORM_SETUP
+
+	/*
+	 *	Create basic memory configuration. Set VBR accordingly,
+	 *	and size memory.
+	 */
+	movel	#CONFIG_VECTORBASE,%a7
+	movec   %a7,%VBR			/* set vectors addr */
+	movel	%a7,_ramvec
+
+	movel	#CONFIG_RAMBASE,%a7		/* mark the base of RAM */
+	movel	%a7,_rambase
+
+	GET_MEM_SIZE				/* macro code determines size */
+	addl	%a7,%d0
+	movel	%d0,_ramend			/* set end ram addr */
+
+	/*
+	 *	Now that we know what the memory is, lets enable cache
+	 *	and get things moving. This is Coldfire CPU specific. Not
+	 *	all version cores have identical cache register setup. But
+	 *	it is very similar. Define the exact settings in the headers
+	 *	then the code here is the same for all.
+	 */
+	movel	#CACHE_INIT,%d0			/* invalidate whole cache */
+	movec	%d0,%CACR
+	nop
+	movel	#ACR0_MODE,%d0			/* set RAM region for caching */
+	movec	%d0,%ACR0
+	movel	#ACR1_MODE,%d0			/* anything else to cache? */
+	movec	%d0,%ACR1
+#ifdef ACR2_MODE
+	movel	#ACR2_MODE,%d0
+	movec	%d0,%ACR2
+	movel	#ACR3_MODE,%d0
+	movec	%d0,%ACR3
+#endif
+	movel	#CACHE_MODE,%d0			/* enable cache */
+	movec	%d0,%CACR
+	nop
+
+#ifdef CONFIG_ROMFS_FS
+	/*
+	 *	Move ROM filesystem above bss :-)
+	 */
+	lea	_sbss,%a0			/* get start of bss */
+	lea	_ebss,%a1			/* set up destination  */
+	movel	%a0,%a2				/* copy of bss start */
+
+	movel	8(%a0),%d0			/* get size of ROMFS */
+	addql	#8,%d0				/* allow for rounding */
+	andl	#0xfffffffc, %d0		/* whole words */
+
+	addl	%d0,%a0				/* copy from end */
+	addl	%d0,%a1				/* copy from end */
+	movel	%a1,_ramstart			/* set start of ram */
+
+_copy_romfs:
+	movel	-(%a0),%d0			/* copy dword */
+	movel	%d0,-(%a1)
+	cmpl	%a0,%a2				/* check if at end */
+	bne	_copy_romfs
+
+#else /* CONFIG_ROMFS_FS */
+	lea	_ebss,%a1
+	movel	%a1,_ramstart
+#endif /* CONFIG_ROMFS_FS */
+
+
+	/*
+	 *	Zero out the bss region.
+	 */
+	lea	_sbss,%a0			/* get start of bss */
+	lea	_ebss,%a1			/* get end of bss */
+	clrl	%d0				/* set value */
+_clear_bss:
+	movel	%d0,(%a0)+			/* clear each word */
+	cmpl	%a0,%a1				/* check if at end */
+	bne	_clear_bss
+
+	/*
+	 *	Load the current task pointer and stack.
+	 */
+	lea	init_thread_union,%a0
+	lea	THREAD_SIZE(%a0),%sp
+
+	/*
+	 *	Assember start up done, start code proper.
+	 */
+	jsr	start_kernel			/* start Linux kernel */
+
+_exit:
+	jmp	_exit				/* should never get here */
+
+/*****************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/intc-2.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/intc-2.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/intc-2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/intc-2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,214 @@
+/*
+ * intc-2.c
+ *
+ * General interrupt controller code for the many ColdFire cores that use
+ * interrupt controllers with 63 interrupt sources, organized as 56 fully-
+ * programmable + 7 fixed-level interrupt sources. This includes the 523x
+ * family, the 5270, 5271, 5274, 5275, and the 528x family which have two such
+ * controllers, and the 547x and 548x families which have only one of them.
+ *
+ * The external 7 fixed interrupts are part the the Edge Port unit of these
+ * ColdFire parts. They can be configured as level or edge triggered.
+ *
+ * (C) Copyright 2009-2011, Greg Ungerer <gerg@snapgear.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+/*
+ * Bit definitions for the ICR family of registers.
+ */
+#define MCFSIM_ICR_LEVEL(l)	((l)<<3)	/* Level l intr */
+#define MCFSIM_ICR_PRI(p)	(p)		/* Priority p intr */
+
+/*
+ *	The EDGE Port interrupts are the fixed 7 external interrupts.
+ *	They need some special treatment, for example they need to be acked.
+ */
+#define	EINT0	64	/* Is not actually used, but spot reserved for it */
+#define	EINT1	65	/* EDGE Port interrupt 1 */
+#define	EINT7	71	/* EDGE Port interrupt 7 */
+
+#ifdef MCFICM_INTC1
+#define NR_VECS	128
+#else
+#define NR_VECS	64
+#endif
+
+static void intc_irq_mask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long imraddr;
+	u32 val, imrbit;
+
+#ifdef MCFICM_INTC1
+	imraddr = (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+	imraddr = MCFICM_INTC0;
+#endif
+	imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
+	imrbit = 0x1 << (irq & 0x1f);
+
+	val = __raw_readl(imraddr);
+	__raw_writel(val | imrbit, imraddr);
+}
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long imraddr;
+	u32 val, imrbit;
+
+#ifdef MCFICM_INTC1
+	imraddr = (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+	imraddr = MCFICM_INTC0;
+#endif
+	imraddr += ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
+	imrbit = 0x1 << (irq & 0x1f);
+
+	/* Don't set the "maskall" bit! */
+	if ((irq & 0x20) == 0)
+		imrbit |= 0x1;
+
+	val = __raw_readl(imraddr);
+	__raw_writel(val & ~imrbit, imraddr);
+}
+
+/*
+ *	Only the external (or EDGE Port) interrupts need to be acknowledged
+ *	here, as part of the IRQ handler. They only really need to be ack'ed
+ *	if they are in edge triggered mode, but there is no harm in doing it
+ *	for all types.
+ */
+static void intc_irq_ack(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	__raw_writeb(0x1 << (irq - EINT0), MCFEPORT_EPFR);
+}
+
+/*
+ *	Each vector needs a unique priority and level associated with it.
+ *	We don't really care so much what they are, we don't rely on the
+ *	traditional priority interrupt scheme of the m68k/ColdFire. This
+ *	only needs to be set once for an interrupt, and we will never change
+ *	these values once we have set them.
+ */
+static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
+
+static unsigned int intc_irq_startup(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+	unsigned long icraddr;
+
+#ifdef MCFICM_INTC1
+	icraddr = (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
+#else
+	icraddr = MCFICM_INTC0;
+#endif
+	icraddr += MCFINTC_ICR0 + (irq & 0x3f);
+	if (__raw_readb(icraddr) == 0)
+		__raw_writeb(intc_intpri--, icraddr);
+
+	irq = d->irq;
+	if ((irq >= EINT1) && (irq <= EINT7)) {
+		u8 v;
+
+		irq -= EINT0;
+
+		/* Set EPORT line as input */
+		v = __raw_readb(MCFEPORT_EPDDR);
+		__raw_writeb(v & ~(0x1 << irq), MCFEPORT_EPDDR);
+
+		/* Set EPORT line as interrupt source */
+		v = __raw_readb(MCFEPORT_EPIER);
+		__raw_writeb(v | (0x1 << irq), MCFEPORT_EPIER);
+	}
+
+	intc_irq_unmask(d);
+	return 0;
+}
+
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int irq = d->irq;
+	u16 pa, tb;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		tb = 0x1;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		tb = 0x2;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		tb = 0x3;
+		break;
+	default:
+		/* Level triggered */
+		tb = 0;
+		break;
+	}
+
+	if (tb)
+		irq_set_handler(irq, handle_edge_irq);
+
+	irq -= EINT0;
+	pa = __raw_readw(MCFEPORT_EPPAR);
+	pa = (pa & ~(0x3 << (irq * 2))) | (tb << (irq * 2));
+	__raw_writew(pa, MCFEPORT_EPPAR);
+	
+	return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+};
+
+static struct irq_chip intc_irq_chip_edge_port = {
+	.name		= "CF-INTC-EP",
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_ack	= intc_irq_ack,
+	.irq_set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq;
+
+	init_vectors();
+
+	/* Mask all interrupt sources */
+	__raw_writel(0x1, MCFICM_INTC0 + MCFINTC_IMRL);
+#ifdef MCFICM_INTC1
+	__raw_writel(0x1, MCFICM_INTC1 + MCFINTC_IMRL);
+#endif
+
+	for (irq = MCFINT_VECBASE; (irq < MCFINT_VECBASE + NR_VECS); irq++) {
+		if ((irq >= EINT1) && (irq <=EINT7))
+			irq_set_chip(irq, &intc_irq_chip_edge_port);
+		else
+			irq_set_chip(irq, &intc_irq_chip);
+		irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_handler(irq, handle_level_irq);
+	}
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/intc.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/intc.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/intc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/intc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,151 @@
+/*
+ * intc.c  -- support for the old ColdFire interrupt controller
+ *
+ * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/traps.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+
+/*
+ * The mapping of irq number to a mask register bit is not one-to-one.
+ * The irq numbers are either based on "level" of interrupt or fixed
+ * for an autovector-able interrupt. So we keep a local data structure
+ * that maps from irq to mask register. Not all interrupts will have
+ * an IMR bit.
+ */
+unsigned char mcf_irq2imr[NR_IRQS];
+
+/*
+ * Define the miniumun and maximum external interrupt numbers.
+ * This is also used as the "level" interrupt numbers.
+ */
+#define	EIRQ1	25
+#define	EIRQ7	31
+
+/*
+ * In the early version 2 core ColdFire parts the IMR register was 16 bits
+ * in size. Version 3 (and later version 2) core parts have a 32 bit
+ * sized IMR register. Provide some size independent methods to access the
+ * IMR register.
+ */
+#ifdef MCFSIM_IMR_IS_16BITS
+
+void mcf_setimr(int index)
+{
+	u16 imr;
+	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+	__raw_writew(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_clrimr(int index)
+{
+	u16 imr;
+	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+	__raw_writew(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_maskimr(unsigned int mask)
+{
+	u16 imr;
+	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
+	imr |= mask;
+	__raw_writew(imr, MCF_MBAR + MCFSIM_IMR);
+}
+
+#else
+
+void mcf_setimr(int index)
+{
+	u32 imr;
+	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+	__raw_writel(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_clrimr(int index)
+{
+	u32 imr;
+	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+	__raw_writel(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
+}
+
+void mcf_maskimr(unsigned int mask)
+{
+	u32 imr;
+	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
+	imr |= mask;
+	__raw_writel(imr, MCF_MBAR + MCFSIM_IMR);
+}
+
+#endif
+
+/*
+ * Interrupts can be "vectored" on the ColdFire cores that support this old
+ * interrupt controller. That is, the device raising the interrupt can also
+ * supply the vector number to interrupt through. The AVR register of the
+ * interrupt controller enables or disables this for each external interrupt,
+ * so provide generic support for this. Setting this up is out-of-band for
+ * the interrupt system API's, and needs to be done by the driver that
+ * supports this device. Very few devices actually use this.
+ */
+void mcf_autovector(int irq)
+{
+#ifdef MCFSIM_AVR
+	if ((irq >= EIRQ1) && (irq <= EIRQ7)) {
+		u8 avec;
+		avec = __raw_readb(MCF_MBAR + MCFSIM_AVR);
+		avec |= (0x1 << (irq - EIRQ1 + 1));
+		__raw_writeb(avec, MCF_MBAR + MCFSIM_AVR);
+	}
+#endif
+}
+
+static void intc_irq_mask(struct irq_data *d)
+{
+	if (mcf_irq2imr[d->irq])
+		mcf_setimr(mcf_irq2imr[d->irq]);
+}
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	if (mcf_irq2imr[d->irq])
+		mcf_clrimr(mcf_irq2imr[d->irq]);
+}
+
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq;
+
+	init_vectors();
+	mcf_maskimr(0xffffffff);
+
+	for (irq = 0; (irq < NR_IRQS); irq++) {
+		irq_set_chip(irq, &intc_irq_chip);
+		irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_handler(irq, handle_level_irq);
+	}
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/intc-simr.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/intc-simr.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/intc-simr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/intc-simr.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,191 @@
+/*
+ * intc-simr.c
+ *
+ * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts.
+ *
+ * (C) Copyright 2009-2011, Greg Ungerer <gerg@snapgear.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/types.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/traps.h>
+
+/*
+ *	The EDGE Port interrupts are the fixed 7 external interrupts.
+ *	They need some special treatment, for example they need to be acked.
+ */
+#ifdef CONFIG_M520x
+/*
+ *	The 520x parts only support a limited range of these external
+ *	interrupts, only 1, 4 and 7 (as interrupts 65, 66 and 67).
+ */
+#define	EINT0	64	/* Is not actually used, but spot reserved for it */
+#define	EINT1	65	/* EDGE Port interrupt 1 */
+#define	EINT4	66	/* EDGE Port interrupt 4 */
+#define	EINT7	67	/* EDGE Port interrupt 7 */
+
+static unsigned int irqebitmap[] = { 0, 1, 4, 7 };
+static unsigned int inline irq2ebit(unsigned int irq)
+{
+	return irqebitmap[irq - EINT0];
+}
+
+#else
+
+/*
+ *	Most of the ColdFire parts with the EDGE Port module just have
+ *	a strait direct mapping of the 7 external interrupts. Although
+ *	there is a bit reserved for 0, it is not used.
+ */
+#define	EINT0	64	/* Is not actually used, but spot reserved for it */
+#define	EINT1	65	/* EDGE Port interrupt 1 */
+#define	EINT7	71	/* EDGE Port interrupt 7 */
+
+static unsigned int inline irq2ebit(unsigned int irq)
+{
+	return irq - EINT0;
+}
+
+#endif
+
+/*
+ *	There maybe one or two interrupt control units, each has 64
+ *	interrupts. If there is no second unit then MCFINTC1_* defines
+ *	will be 0 (and code for them optimized away).
+ */
+
+static void intc_irq_mask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+
+	if (MCFINTC1_SIMR && (irq > 64))
+		__raw_writeb(irq - 64, MCFINTC1_SIMR);
+	else
+		__raw_writeb(irq, MCFINTC0_SIMR);
+}
+
+static void intc_irq_unmask(struct irq_data *d)
+{
+	unsigned int irq = d->irq - MCFINT_VECBASE;
+
+	if (MCFINTC1_CIMR && (irq > 64))
+		__raw_writeb(irq - 64, MCFINTC1_CIMR);
+	else
+		__raw_writeb(irq, MCFINTC0_CIMR);
+}
+
+static void intc_irq_ack(struct irq_data *d)
+{
+	unsigned int ebit = irq2ebit(d->irq);
+
+	__raw_writeb(0x1 << ebit, MCFEPORT_EPFR);
+}
+
+static unsigned int intc_irq_startup(struct irq_data *d)
+{
+	unsigned int irq = d->irq;
+
+	if ((irq >= EINT1) && (irq <= EINT7)) {
+		unsigned int ebit = irq2ebit(irq);
+		u8 v;
+
+		/* Set EPORT line as input */
+		v = __raw_readb(MCFEPORT_EPDDR);
+		__raw_writeb(v & ~(0x1 << ebit), MCFEPORT_EPDDR);
+
+		/* Set EPORT line as interrupt source */
+		v = __raw_readb(MCFEPORT_EPIER);
+		__raw_writeb(v | (0x1 << ebit), MCFEPORT_EPIER);
+	}
+
+	irq -= MCFINT_VECBASE;
+	if (MCFINTC1_ICR0 && (irq > 64))
+		__raw_writeb(5, MCFINTC1_ICR0 + irq - 64);
+	else
+		__raw_writeb(5, MCFINTC0_ICR0 + irq);
+
+
+	intc_irq_unmask(d);
+	return 0;
+}
+
+static int intc_irq_set_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int ebit, irq = d->irq;
+	u16 pa, tb;
+
+	switch (type) {
+	case IRQ_TYPE_EDGE_RISING:
+		tb = 0x1;
+		break;
+	case IRQ_TYPE_EDGE_FALLING:
+		tb = 0x2;
+		break;
+	case IRQ_TYPE_EDGE_BOTH:
+		tb = 0x3;
+		break;
+	default:
+		/* Level triggered */
+		tb = 0;
+		break;
+	}
+
+	if (tb)
+		irq_set_handler(irq, handle_edge_irq);
+
+	ebit = irq2ebit(irq) * 2;
+	pa = __raw_readw(MCFEPORT_EPPAR);
+	pa = (pa & ~(0x3 << ebit)) | (tb << ebit);
+	__raw_writew(pa, MCFEPORT_EPPAR);
+	
+	return 0;
+}
+
+static struct irq_chip intc_irq_chip = {
+	.name		= "CF-INTC",
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+};
+
+static struct irq_chip intc_irq_chip_edge_port = {
+	.name		= "CF-INTC-EP",
+	.irq_startup	= intc_irq_startup,
+	.irq_mask	= intc_irq_mask,
+	.irq_unmask	= intc_irq_unmask,
+	.irq_ack	= intc_irq_ack,
+	.irq_set_type	= intc_irq_set_type,
+};
+
+void __init init_IRQ(void)
+{
+	int irq, eirq;
+
+	init_vectors();
+
+	/* Mask all interrupt sources */
+	__raw_writeb(0xff, MCFINTC0_SIMR);
+	if (MCFINTC1_SIMR)
+		__raw_writeb(0xff, MCFINTC1_SIMR);
+
+	eirq = MCFINT_VECBASE + 64 + (MCFINTC1_ICR0 ? 64 : 0);
+	for (irq = MCFINT_VECBASE; (irq < eirq); irq++) {
+		if ((irq >= EINT1) && (irq <= EINT7))
+			irq_set_chip(irq, &intc_irq_chip_edge_port);
+		else
+			irq_set_chip(irq, &intc_irq_chip);
+		irq_set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_handler(irq, handle_level_irq);
+	}
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+#
+# Makefile for the m68knommu kernel.
+#
+
+#
+# If you want to play with the HW breakpoints then you will
+# need to add define this,  which will give you a stack backtrace
+# on the console port whenever a DBG interrupt occurs. You have to
+# set up you HW breakpoints to trigger a DBG interrupt:
+#
+# ccflags-y := -DTRAP_DBG_INTERRUPT
+# asflags-y := -DTRAP_DBG_INTERRUPT
+#
+
+asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
+
+obj-$(CONFIG_COLDFIRE)	+= cache.o clk.o dma.o entry.o vectors.o
+obj-$(CONFIG_M5206)	+= timers.o intc.o
+obj-$(CONFIG_M5206e)	+= timers.o intc.o
+obj-$(CONFIG_M520x)	+= pit.o intc-simr.o
+obj-$(CONFIG_M523x)	+= pit.o dma_timer.o intc-2.o
+obj-$(CONFIG_M5249)	+= timers.o intc.o
+obj-$(CONFIG_M527x)	+= pit.o intc-2.o
+obj-$(CONFIG_M5272)	+= timers.o
+obj-$(CONFIG_M528x)	+= pit.o intc-2.o
+obj-$(CONFIG_M5307)	+= timers.o intc.o
+obj-$(CONFIG_M532x)	+= timers.o intc-simr.o
+obj-$(CONFIG_M5407)	+= timers.o intc.o
+obj-$(CONFIG_M54xx)	+= sltimers.o intc-2.o
+
+obj-y			+= pinmux.o gpio.o
+extra-y := head.o
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/pinmux.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/pinmux.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/pinmux.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/pinmux.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * Coldfire generic GPIO pinmux support.
+ *
+ * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
+ *
+ *   This program is distributed in the hope that it will be useful,
+ *   but WITHOUT ANY WARRANTY; 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 <asm/pinmux.h>
+
+int mcf_pinmux_request(unsigned pinmux, unsigned func)
+{
+	return 0;
+}
+
+void mcf_pinmux_release(unsigned pinmux, unsigned func)
+{
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/pit.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/pit.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/pit.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/pit.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,169 @@
+/***************************************************************************/
+
+/*
+ *	pit.c -- Freescale ColdFire PIT timer. Currently this type of
+ *	         hardware timer only exists in the Freescale ColdFire
+ *		 5270/5271, 5282 and 5208 CPUs. No doubt newer ColdFire
+ *		 family members will probably use it too.
+ *
+ *	Copyright (C) 1999-2008, Greg Ungerer (gerg@snapgear.com)
+ *	Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/param.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/clockchips.h>
+#include <asm/machdep.h>
+#include <asm/io.h>
+#include <asm/coldfire.h>
+#include <asm/mcfpit.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+/*
+ *	By default use timer1 as the system clock timer.
+ */
+#define	FREQ	((MCF_CLK / 2) / 64)
+#define	TA(a)	(MCFPIT_BASE1 + (a))
+#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
+
+static u32 pit_cnt;
+
+/*
+ * Initialize the PIT timer.
+ *
+ * This is also called after resume to bring the PIT into operation again.
+ */
+
+static void init_cf_pit_timer(enum clock_event_mode mode,
+                             struct clock_event_device *evt)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_PERIODIC:
+
+		__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+		__raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR));
+		__raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
+				MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \
+				MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
+		break;
+
+	case CLOCK_EVT_MODE_SHUTDOWN:
+	case CLOCK_EVT_MODE_UNUSED:
+
+		__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+		break;
+
+	case CLOCK_EVT_MODE_ONESHOT:
+
+		__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
+		__raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
+				MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \
+				TA(MCFPIT_PCSR));
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+		/* Nothing to do here */
+		break;
+	}
+}
+
+/*
+ * Program the next event in oneshot mode
+ *
+ * Delta is given in PIT ticks
+ */
+static int cf_pit_next_event(unsigned long delta,
+		struct clock_event_device *evt)
+{
+	__raw_writew(delta, TA(MCFPIT_PMR));
+	return 0;
+}
+
+struct clock_event_device cf_pit_clockevent = {
+	.name		= "pit",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode	= init_cf_pit_timer,
+	.set_next_event	= cf_pit_next_event,
+	.shift		= 32,
+	.irq		= MCFINT_VECBASE + MCFINT_PIT1,
+};
+
+
+
+/***************************************************************************/
+
+static irqreturn_t pit_tick(int irq, void *dummy)
+{
+	struct clock_event_device *evt = &cf_pit_clockevent;
+	u16 pcsr;
+
+	/* Reset the ColdFire timer */
+	pcsr = __raw_readw(TA(MCFPIT_PCSR));
+	__raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
+
+	pit_cnt += PIT_CYCLES_PER_JIFFY;
+	evt->event_handler(evt);
+	return IRQ_HANDLED;
+}
+
+/***************************************************************************/
+
+static struct irqaction pit_irq = {
+	.name	 = "timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = pit_tick,
+};
+
+/***************************************************************************/
+
+static cycle_t pit_read_clk(struct clocksource *cs)
+{
+	unsigned long flags;
+	u32 cycles;
+	u16 pcntr;
+
+	local_irq_save(flags);
+	pcntr = __raw_readw(TA(MCFPIT_PCNTR));
+	cycles = pit_cnt;
+	local_irq_restore(flags);
+
+	return cycles + PIT_CYCLES_PER_JIFFY - pcntr;
+}
+
+/***************************************************************************/
+
+static struct clocksource pit_clk = {
+	.name	= "pit",
+	.rating	= 100,
+	.read	= pit_read_clk,
+	.shift	= 20,
+	.mask	= CLOCKSOURCE_MASK(32),
+};
+
+/***************************************************************************/
+
+void hw_timer_init(void)
+{
+	cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id());
+	cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
+	cf_pit_clockevent.max_delta_ns =
+		clockevent_delta2ns(0xFFFF, &cf_pit_clockevent);
+	cf_pit_clockevent.min_delta_ns =
+		clockevent_delta2ns(0x3f, &cf_pit_clockevent);
+	clockevents_register_device(&cf_pit_clockevent);
+
+	setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
+
+	pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
+	clocksource_register(&pit_clk);
+}
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/sltimers.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/sltimers.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/sltimers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/sltimers.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,145 @@
+/***************************************************************************/
+
+/*
+ *	sltimers.c -- generic ColdFire slice timer support.
+ *
+ *	Copyright (C) 2009-2010, Philippe De Muyter <phdm@macqel.be>
+ *	based on
+ *	timers.c -- generic ColdFire hardware timer support.
+ *	Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/clocksource.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfslt.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+#ifdef CONFIG_HIGHPROFILE
+
+/*
+ *	By default use Slice Timer 1 as the profiler clock timer.
+ */
+#define	PA(a)	(MCF_MBAR + MCFSLT_TIMER1 + (a))
+
+/*
+ *	Choose a reasonably fast profile timer. Make it an odd value to
+ *	try and get good coverage of kernel operations.
+ */
+#define	PROFILEHZ	1013
+
+irqreturn_t mcfslt_profile_tick(int irq, void *dummy)
+{
+	/* Reset Slice Timer 1 */
+	__raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, PA(MCFSLT_SSR));
+	if (current->pid)
+		profile_tick(CPU_PROFILING);
+	return IRQ_HANDLED;
+}
+
+static struct irqaction mcfslt_profile_irq = {
+	.name	 = "profile timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = mcfslt_profile_tick,
+};
+
+void mcfslt_profile_init(void)
+{
+	printk(KERN_INFO "PROFILE: lodging TIMER 1 @ %dHz as profile timer\n",
+	       PROFILEHZ);
+
+	setup_irq(MCF_IRQ_PROFILER, &mcfslt_profile_irq);
+
+	/* Set up TIMER 2 as high speed profile clock */
+	__raw_writel(MCF_BUSCLK / PROFILEHZ - 1, PA(MCFSLT_STCNT));
+	__raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+								PA(MCFSLT_SCR));
+
+}
+
+#endif	/* CONFIG_HIGHPROFILE */
+
+/***************************************************************************/
+
+/*
+ *	By default use Slice Timer 0 as the system clock timer.
+ */
+#define	TA(a)	(MCF_MBAR + MCFSLT_TIMER0 + (a))
+
+static u32 mcfslt_cycles_per_jiffy;
+static u32 mcfslt_cnt;
+
+static irqreturn_t mcfslt_tick(int irq, void *dummy)
+{
+	/* Reset Slice Timer 0 */
+	__raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
+	mcfslt_cnt += mcfslt_cycles_per_jiffy;
+	return arch_timer_interrupt(irq, dummy);
+}
+
+static struct irqaction mcfslt_timer_irq = {
+	.name	 = "timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = mcfslt_tick,
+};
+
+static cycle_t mcfslt_read_clk(struct clocksource *cs)
+{
+	unsigned long flags;
+	u32 cycles;
+	u16 scnt;
+
+	local_irq_save(flags);
+	scnt = __raw_readl(TA(MCFSLT_SCNT));
+	cycles = mcfslt_cnt;
+	local_irq_restore(flags);
+
+	/* subtract because slice timers count down */
+	return cycles - scnt;
+}
+
+static struct clocksource mcfslt_clk = {
+	.name	= "slt",
+	.rating	= 250,
+	.read	= mcfslt_read_clk,
+	.shift	= 20,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+void hw_timer_init(void)
+{
+	mcfslt_cycles_per_jiffy = MCF_BUSCLK / HZ;
+	/*
+	 *	The coldfire slice timer (SLT) runs from STCNT to 0 included,
+	 *	then STCNT again and so on.  It counts thus actually
+	 *	STCNT + 1 steps for 1 tick, not STCNT.  So if you want
+	 *	n cycles, initialize STCNT with n - 1.
+	 */
+	__raw_writel(mcfslt_cycles_per_jiffy - 1, TA(MCFSLT_STCNT));
+	__raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
+								TA(MCFSLT_SCR));
+	/* initialize mcfslt_cnt knowing that slice timers count down */
+	mcfslt_cnt = mcfslt_cycles_per_jiffy;
+
+	setup_irq(MCF_IRQ_TIMER, &mcfslt_timer_irq);
+
+	mcfslt_clk.mult = clocksource_hz2mult(MCF_BUSCLK, mcfslt_clk.shift);
+	clocksource_register(&mcfslt_clk);
+
+#ifdef CONFIG_HIGHPROFILE
+	mcfslt_profile_init();
+#endif
+}
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/timers.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/timers.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/timers.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/timers.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,174 @@
+/***************************************************************************/
+
+/*
+ *	timers.c -- generic ColdFire hardware timer support.
+ *
+ *	Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/profile.h>
+#include <linux/clocksource.h>
+#include <asm/io.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcftimer.h>
+#include <asm/mcfsim.h>
+
+/***************************************************************************/
+
+/*
+ *	By default use timer1 as the system clock timer.
+ */
+#define	FREQ	(MCF_BUSCLK / 16)
+#define	TA(a)	(MCFTIMER_BASE1 + (a))
+
+/*
+ *	These provide the underlying interrupt vector support.
+ *	Unfortunately it is a little different on each ColdFire.
+ */
+void coldfire_profile_init(void);
+
+#if defined(CONFIG_M532x)
+#define	__raw_readtrr	__raw_readl
+#define	__raw_writetrr	__raw_writel
+#else
+#define	__raw_readtrr	__raw_readw
+#define	__raw_writetrr	__raw_writew
+#endif
+
+static u32 mcftmr_cycles_per_jiffy;
+static u32 mcftmr_cnt;
+
+/***************************************************************************/
+
+static irqreturn_t mcftmr_tick(int irq, void *dummy)
+{
+	/* Reset the ColdFire timer */
+	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
+
+	mcftmr_cnt += mcftmr_cycles_per_jiffy;
+	return arch_timer_interrupt(irq, dummy);
+}
+
+/***************************************************************************/
+
+static struct irqaction mcftmr_timer_irq = {
+	.name	 = "timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = mcftmr_tick,
+};
+
+/***************************************************************************/
+
+static cycle_t mcftmr_read_clk(struct clocksource *cs)
+{
+	unsigned long flags;
+	u32 cycles;
+	u16 tcn;
+
+	local_irq_save(flags);
+	tcn = __raw_readw(TA(MCFTIMER_TCN));
+	cycles = mcftmr_cnt;
+	local_irq_restore(flags);
+
+	return cycles + tcn;
+}
+
+/***************************************************************************/
+
+static struct clocksource mcftmr_clk = {
+	.name	= "tmr",
+	.rating	= 250,
+	.read	= mcftmr_read_clk,
+	.shift	= 20,
+	.mask	= CLOCKSOURCE_MASK(32),
+	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+/***************************************************************************/
+
+void hw_timer_init(void)
+{
+	__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
+	mcftmr_cycles_per_jiffy = FREQ / HZ;
+	/*
+	 *	The coldfire timer runs from 0 to TRR included, then 0
+	 *	again and so on.  It counts thus actually TRR + 1 steps
+	 *	for 1 tick, not TRR.  So if you want n cycles,
+	 *	initialize TRR with n - 1.
+	 */
+	__raw_writetrr(mcftmr_cycles_per_jiffy - 1, TA(MCFTIMER_TRR));
+	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
+
+	mcftmr_clk.mult = clocksource_hz2mult(FREQ, mcftmr_clk.shift);
+	clocksource_register(&mcftmr_clk);
+
+	setup_irq(MCF_IRQ_TIMER, &mcftmr_timer_irq);
+
+#ifdef CONFIG_HIGHPROFILE
+	coldfire_profile_init();
+#endif
+}
+
+/***************************************************************************/
+#ifdef CONFIG_HIGHPROFILE
+/***************************************************************************/
+
+/*
+ *	By default use timer2 as the profiler clock timer.
+ */
+#define	PA(a)	(MCFTIMER_BASE2 + (a))
+
+/*
+ *	Choose a reasonably fast profile timer. Make it an odd value to
+ *	try and get good coverage of kernel operations.
+ */
+#define	PROFILEHZ	1013
+
+/*
+ *	Use the other timer to provide high accuracy profiling info.
+ */
+irqreturn_t coldfire_profile_tick(int irq, void *dummy)
+{
+	/* Reset ColdFire timer2 */
+	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
+	if (current->pid)
+		profile_tick(CPU_PROFILING);
+	return IRQ_HANDLED;
+}
+
+/***************************************************************************/
+
+static struct irqaction coldfire_profile_irq = {
+	.name	 = "profile timer",
+	.flags	 = IRQF_DISABLED | IRQF_TIMER,
+	.handler = coldfire_profile_tick,
+};
+
+void coldfire_profile_init(void)
+{
+	printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n",
+	       PROFILEHZ);
+
+	/* Set up TIMER 2 as high speed profile clock */
+	__raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
+
+	__raw_writetrr(((MCF_BUSCLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
+	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
+		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
+
+	setup_irq(MCF_IRQ_PROFILER, &coldfire_profile_irq);
+}
+
+/***************************************************************************/
+#endif	/* CONFIG_HIGHPROFILE */
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/vectors.c linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/vectors.c
--- linux-libre-2.6.38-gnu/arch/m68k/platform/coldfire/vectors.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/coldfire/vectors.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,80 @@
+/***************************************************************************/
+
+/*
+ *	linux/arch/m68knommu/platform/coldfire/vectors.c
+ *
+ *	Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com>
+ */
+
+/***************************************************************************/
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <asm/traps.h>
+#include <asm/machdep.h>
+#include <asm/coldfire.h>
+#include <asm/mcfsim.h>
+#include <asm/mcfwdebug.h>
+
+/***************************************************************************/
+
+#ifdef TRAP_DBG_INTERRUPT
+
+asmlinkage void dbginterrupt_c(struct frame *fp)
+{
+	extern void dump(struct pt_regs *fp);
+	printk(KERN_DEBUG "%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__);
+	dump((struct pt_regs *) fp);
+	asm("halt");
+}
+
+#endif
+
+/***************************************************************************/
+
+extern e_vector	*_ramvec;
+
+void set_evector(int vecnum, void (*handler)(void))
+{
+	if (vecnum >= 0 && vecnum <= 255)
+		_ramvec[vecnum] = handler;
+}
+
+/***************************************************************************/
+
+/* Assembler routines */
+asmlinkage void buserr(void);
+asmlinkage void trap(void);
+asmlinkage void system_call(void);
+asmlinkage void inthandler(void);
+
+void __init init_vectors(void)
+{
+	int i;
+
+	/*
+	 *	There is a common trap handler and common interrupt
+	 *	handler that handle almost every vector. We treat
+	 *	the system call and bus error special, they get their
+	 *	own first level handlers.
+	 */
+	for (i = 3; (i <= 23); i++)
+		_ramvec[i] = trap;
+	for (i = 33; (i <= 63); i++)
+		_ramvec[i] = trap;
+	for (i = 24; (i <= 31); i++)
+		_ramvec[i] = inthandler;
+	for (i = 64; (i < 255); i++)
+		_ramvec[i] = inthandler;
+	_ramvec[255] = 0;
+
+	_ramvec[2] = buserr;
+	_ramvec[32] = system_call;
+
+#ifdef TRAP_DBG_INTERRUPT
+	_ramvec[12] = dbginterrupt;
+#endif
+}
+
+/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68k/platform/Makefile linux-libre-2.6.39-gnu/arch/m68k/platform/Makefile
--- linux-libre-2.6.38-gnu/arch/m68k/platform/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/m68k/platform/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3 @@
+#
+# Makefile for the arch/m68knommu/platform.
+#
diff -druN linux-libre-2.6.38-gnu/arch/m68k/q40/README linux-libre-2.6.39-gnu/arch/m68k/q40/README
--- linux-libre-2.6.38-gnu/arch/m68k/q40/README	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/q40/README	2011-05-19 00:06:34.000000000 -0400
@@ -89,7 +89,7 @@
 or from some ISA devices, EIRQ_REG can distinguish up to 8 ISA IRQs.
 
 The Q40 custom chip is programmable to provide 2 periodic timers:
-	- 50 or 200 Hz - level 2, !!THIS CANT BE DISABLED!!
+	- 50 or 200 Hz - level 2, !!THIS CAN'T BE DISABLED!!
 	- 10 or 20 KHz - level 4, used for dma-sound
 
 Linux uses the 200 Hz interrupt for timer and beep by default.
diff -druN linux-libre-2.6.38-gnu/arch/m68k/sun3/sun3ints.c linux-libre-2.6.39-gnu/arch/m68k/sun3/sun3ints.c
--- linux-libre-2.6.38-gnu/arch/m68k/sun3/sun3ints.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68k/sun3/sun3ints.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
 #ifdef CONFIG_SUN3
 	intersil_clear();
 #endif
-        do_timer(1);
+	xtime_update(1);
 	update_process_times(user_mode(get_irq_regs()));
         if (!(kstat_cpu(0).irqs[irq] % 20))
                 sun3_leds(led_pattern[(kstat_cpu(0).irqs[irq] % 160) / 20]);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5208evb_defconfig linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5208evb_defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5208evb_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5208evb_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M520x=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=166666666
-CONFIG_CLOCK_DIV=2
-CONFIG_M5208EVB=y
-# CONFIG_4KSTACKS is not set
-CONFIG_RAMBASE=0x40000000
-CONFIG_RAMSIZE=0x2000000
-CONFIG_VECTORBASE=0x40000000
-CONFIG_KERNELBASE=0x40020000
-CONFIG_RAM16BIT=y
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_BAUDRATE=115200
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_FILE_LOCKING is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_SYSFS is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_FULLDEBUG=y
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5249evb_defconfig linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5249evb_defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5249evb_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5249evb_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,67 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M5249=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=140000000
-CONFIG_CLOCK_DIV=2
-CONFIG_M5249C3=y
-CONFIG_RAMBASE=0x00000000
-CONFIG_RAMSIZE=0x00800000
-CONFIG_VECTORBASE=0x00000000
-CONFIG_KERNELBASE=0x00020000
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_FILE_LOCKING is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5272c3_defconfig linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5272c3_defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5272c3_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5272c3_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M5272=y
-CONFIG_CLOCK_SET=y
-CONFIG_M5272C3=y
-CONFIG_RAMBASE=0x00000000
-CONFIG_RAMSIZE=0x00800000
-CONFIG_VECTORBASE=0x00000000
-CONFIG_KERNELBASE=0x00020000
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_FILE_LOCKING is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5275evb_defconfig linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5275evb_defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5275evb_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5275evb_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M5275=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=150000000
-CONFIG_CLOCK_DIV=2
-CONFIG_M5275EVB=y
-# CONFIG_4KSTACKS is not set
-CONFIG_RAMBASE=0x00000000
-CONFIG_RAMSIZE=0x00000000
-CONFIG_VECTORBASE=0x00000000
-CONFIG_KERNELBASE=0x00020000
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-CONFIG_FEC2=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_FILE_LOCKING is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5307c3_defconfig linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5307c3_defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5307c3_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5307c3_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,75 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_SLUB_DEBUG is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M5307=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=90000000
-CONFIG_CLOCK_DIV=2
-CONFIG_M5307C3=y
-CONFIG_RAMBASE=0x00000000
-CONFIG_RAMSIZE=0x00800000
-CONFIG_VECTORBASE=0x00000000
-CONFIG_KERNELBASE=0x00020000
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-CONFIG_SLIP=y
-CONFIG_SLIP_COMPRESSED=y
-# CONFIG_INPUT_MOUSEDEV is not set
-# CONFIG_INPUT_KEYBOARD is not set
-# CONFIG_INPUT_MOUSE is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_HID_SUPPORT is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_FULLDEBUG=y
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5407c3_defconfig linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5407c3_defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/configs/m5407c3_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/configs/m5407c3_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_MODULES=y
-CONFIG_MODULE_UNLOAD=y
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M5407=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=50000000
-CONFIG_M5407C3=y
-CONFIG_RAMBASE=0x00000000
-CONFIG_RAMSIZE=0x00000000
-CONFIG_VECTORBASE=0x00000000
-CONFIG_KERNELBASE=0x00020000
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-CONFIG_PPP=y
-# CONFIG_INPUT is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_FILE_LOCKING is not set
-# CONFIG_DNOTIFY is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
-# CONFIG_CRC32 is not set
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/defconfig linux-libre-2.6.39-gnu/arch/m68knommu/defconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-CONFIG_EXPERIMENTAL=y
-CONFIG_LOG_BUF_SHIFT=14
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_KALLSYMS is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_FUTEX is not set
-# CONFIG_EPOLL is not set
-# CONFIG_SIGNALFD is not set
-# CONFIG_TIMERFD is not set
-# CONFIG_EVENTFD is not set
-# CONFIG_AIO is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-# CONFIG_COMPAT_BRK is not set
-# CONFIG_BLK_DEV_BSG is not set
-# CONFIG_IOSCHED_DEADLINE is not set
-# CONFIG_IOSCHED_CFQ is not set
-CONFIG_M520x=y
-CONFIG_CLOCK_SET=y
-CONFIG_CLOCK_FREQ=166666666
-CONFIG_CLOCK_DIV=2
-CONFIG_M5208EVB=y
-# CONFIG_4KSTACKS is not set
-CONFIG_RAMBASE=0x40000000
-CONFIG_RAMSIZE=0x2000000
-CONFIG_VECTORBASE=0x40000000
-CONFIG_KERNELBASE=0x40020000
-CONFIG_RAM16BIT=y
-CONFIG_BINFMT_FLAT=y
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=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_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_RAM=y
-CONFIG_MTD_UCLINUX=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FEC=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_MCF=y
-CONFIG_SERIAL_MCF_BAUDRATE=115200
-CONFIG_SERIAL_MCF_CONSOLE=y
-# CONFIG_UNIX98_PTYS is not set
-# CONFIG_HW_RANDOM is not set
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-# CONFIG_FILE_LOCKING is not set
-# CONFIG_DNOTIFY is not set
-# CONFIG_SYSFS is not set
-CONFIG_ROMFS_FS=y
-CONFIG_ROMFS_BACKED_BY_MTD=y
-# CONFIG_NETWORK_FILESYSTEMS is not set
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_FULLDEBUG=y
-CONFIG_BOOTPARAM=y
-CONFIG_BOOTPARAM_STRING="root=/dev/mtdblock0"
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/Kconfig linux-libre-2.6.39-gnu/arch/m68knommu/Kconfig
--- linux-libre-2.6.38-gnu/arch/m68knommu/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,808 +0,0 @@
-config M68K
-	bool
-	default y
-	select HAVE_IDE
-	select HAVE_GENERIC_HARDIRQS
-
-config MMU
-	bool
-	default n
-
-config NO_DMA
-	bool
-	depends on !COLDFIRE
-	default y
-
-config FPU
-	bool
-	default n
-
-config ZONE_DMA
-	bool
-	default y
-
-config RWSEM_GENERIC_SPINLOCK
-	bool
-	default y
-
-config RWSEM_XCHGADD_ALGORITHM
-	bool
-	default n
-
-config ARCH_HAS_ILOG2_U32
-	bool
-	default n
-
-config ARCH_HAS_ILOG2_U64
-	bool
-	default n
-
-config GENERIC_FIND_NEXT_BIT
-	bool
-	default y
-
-config GENERIC_GPIO
-	bool
-	default n
-
-config GENERIC_HWEIGHT
-	bool
-	default y
-
-config GENERIC_CALIBRATE_DELAY
-	bool
-	default y
-
-config GENERIC_CMOS_UPDATE
-	bool
-	default y
-
-config TIME_LOW_RES
-	bool
-	default y
-
-config GENERIC_CLOCKEVENTS
-	bool
-	default n
-
-config NO_IOPORT
-	def_bool y
-
-config COLDFIRE_SW_A7
-	bool
-	default n
-
-config HAVE_CACHE_SPLIT
-	bool
-
-config HAVE_CACHE_CB
-	bool
-
-source "init/Kconfig"
-
-source "kernel/Kconfig.freezer"
-
-menu "Processor type and features"
-
-choice
-	prompt "CPU"
-	default M68EZ328
-
-config M68328
-	bool "MC68328"
-	help
-	  Motorola 68328 processor support.
-
-config M68EZ328
-	bool "MC68EZ328"
-	help
-	  Motorola 68EX328 processor support.
-
-config M68VZ328
-	bool "MC68VZ328"
-	help
-	  Motorola 68VZ328 processor support.
-
-config M68360
-	bool "MC68360"
-	help
-	  Motorola 68360 processor support.
-
-config M5206
-	bool "MCF5206"
-	select COLDFIRE_SW_A7
-	help
-	  Motorola ColdFire 5206 processor support.
-
-config M5206e
-	bool "MCF5206e"
-	select COLDFIRE_SW_A7
-	help
-	  Motorola ColdFire 5206e processor support.
-
-config M520x
-	bool "MCF520x"
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	help
-	   Freescale Coldfire 5207/5208 processor support.
-
-config M523x
-	bool "MCF523x"
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	help
-	  Freescale Coldfire 5230/1/2/4/5 processor support
-
-config M5249
-	bool "MCF5249"
-	select COLDFIRE_SW_A7
-	help
-	  Motorola ColdFire 5249 processor support.
-
-config M5271
-	bool "MCF5271"
-	select HAVE_CACHE_SPLIT
-	help
-	  Freescale (Motorola) ColdFire 5270/5271 processor support.
-
-config M5272
-	bool "MCF5272"
-	select COLDFIRE_SW_A7
-	help
-	  Motorola ColdFire 5272 processor support.
-
-config M5275
-	bool "MCF5275"
-	select HAVE_CACHE_SPLIT
-	help
-	  Freescale (Motorola) ColdFire 5274/5275 processor support.
-
-config M528x
-	bool "MCF528x"
-	select GENERIC_CLOCKEVENTS
-	select HAVE_CACHE_SPLIT
-	help
-	  Motorola ColdFire 5280/5282 processor support.
-
-config M5307
-	bool "MCF5307"
-	select COLDFIRE_SW_A7
-	select HAVE_CACHE_CB
-	help
-	  Motorola ColdFire 5307 processor support.
-
-config M532x
-	bool "MCF532x"
-	select HAVE_CACHE_CB
-	help
-	  Freescale (Motorola) ColdFire 532x processor support.
-
-config M5407
-	bool "MCF5407"
-	select COLDFIRE_SW_A7
-	select HAVE_CACHE_CB
-	help
-	  Motorola ColdFire 5407 processor support.
-
-config M547x
-	bool "MCF547x"
-	select HAVE_CACHE_CB
-	help
-	  Freescale ColdFire 5470/5471/5472/5473/5474/5475 processor support.
-
-config M548x
-	bool "MCF548x"
-	select HAVE_CACHE_CB
-	help
-	  Freescale ColdFire 5480/5481/5482/5483/5484/5485 processor support.
-
-endchoice
-
-config M527x
-	bool
-	depends on (M5271 || M5275)
-	select GENERIC_CLOCKEVENTS
-	default y
-
-config M54xx
-	bool
-	depends on (M548x || M547x)
-	default y
-
-config COLDFIRE
-	bool
-	depends on (M5206 || M5206e || M520x || M523x || M5249 || M527x || M5272 || M528x || M5307 || M532x || M5407 || M54xx)
-	select GENERIC_GPIO
-	select ARCH_REQUIRE_GPIOLIB
-	default y
-
-config CLOCK_SET
-	bool "Enable setting the CPU clock frequency"
-	default n
-	help
-	  On some CPU's you do not need to know what the core CPU clock
-	  frequency is. On these you can disable clock setting. On some
-	  traditional 68K parts, and on all ColdFire parts you need to set
-	  the appropriate CPU clock frequency. On these devices many of the
-	  onboard peripherals derive their timing from the master CPU clock
-	  frequency.
-
-config CLOCK_FREQ
-	int "Set the core clock frequency"
-	default "66666666"
-	depends on CLOCK_SET
-	help
-	  Define the CPU clock frequency in use. This is the core clock
-	  frequency, it may or may not be the same as the external clock
-	  crystal fitted to your board. Some processors have an internal
-	  PLL and can have their frequency programmed at run time, others
-	  use internal dividers. In general the kernel won't setup a PLL
-	  if it is fitted (there are some exceptions). This value will be
-	  specific to the exact CPU that you are using.
-
-config CLOCK_DIV
-	int "Set the core/bus clock divide ratio"
-	default "1"
-	depends on CLOCK_SET
-	help
-	  On many SoC style CPUs the master CPU clock is also used to drive 
-	  on-chip peripherals. The clock that is distributed to these
-	  peripherals is sometimes a fixed ratio of the master clock
-	  frequency. If so then set this to the divider ratio of the
-	  master clock to the peripheral clock. If not sure then select 1.
-
-config OLDMASK
-	bool "Old mask 5307 (1H55J) silicon"
-	depends on M5307
-	help
-	  Build support for the older revision ColdFire 5307 silicon.
-	  Specifically this is the 1H55J mask revision.
-
-if HAVE_CACHE_SPLIT
-choice
-	prompt "Split Cache Configuration"
-	default CACHE_I
-
-config CACHE_I
-	bool "Instruction"
-	help
-	  Use all of the ColdFire CPU cache memory as an instruction cache.
-
-config CACHE_D
-	bool "Data"
-	help
-	  Use all of the ColdFire CPU cache memory as a data cache.
-
-config CACHE_BOTH
-	bool "Both"
-	help
-	  Split the ColdFire CPU cache, and use half as an instruction cache
-	  and half as a data cache.
-endchoice
-endif
-
-if HAVE_CACHE_CB
-choice
-	prompt "Data cache mode"
-	default CACHE_WRITETHRU
-
-config CACHE_WRITETHRU
-	bool "Write-through"
-	help
-	  The ColdFire CPU cache is set into Write-through mode.
-
-config CACHE_COPYBACK
-	bool "Copy-back"
-	help
-	  The ColdFire CPU cache is set into Copy-back mode.
-endchoice
-endif
-
-comment "Platform"
-
-config PILOT3
-	bool "Pilot 1000/5000, PalmPilot Personal/Pro, or PalmIII support"
-	depends on M68328
-	help
-	  Support for the Palm Pilot 1000/5000, Personal/Pro and PalmIII.
-
-config XCOPILOT_BUGS
-	bool "(X)Copilot support"
-	depends on PILOT3
-	help
-	  Support the bugs of Xcopilot.
-
-config UC5272
-	bool 'Arcturus Networks uC5272 dimm board support'
-	depends on M5272
-	help
-	  Support for the Arcturus Networks uC5272 dimm board.
-
-config UC5282
-	bool "Arcturus Networks uC5282 board support"
-	depends on M528x
-	help
-	  Support for the Arcturus Networks uC5282 dimm board.
-
-config UCSIMM
-	bool "uCsimm module support"
-	depends on M68EZ328
-	help
-	  Support for the Arcturus Networks uCsimm module.
-
-config UCDIMM
-	bool "uDsimm module support"
-	depends on M68VZ328
-	help
-	  Support for the Arcturus Networks uDsimm module.
-
-config DRAGEN2
-	bool "DragenEngine II board support"
-	depends on M68VZ328
-	help
-	  Support for the DragenEngine II board.
-
-config DIRECT_IO_ACCESS
-	bool "Allow user to access IO directly"
-	depends on (UCSIMM || UCDIMM || DRAGEN2)
-	help
-	  Disable the CPU internal registers protection in user mode,
-	  to allow a user application to read/write them.
-
-config INIT_LCD
-	bool "Initialize LCD"
-	depends on (UCSIMM || UCDIMM || DRAGEN2)
-	help
-	  Initialize the LCD controller of the 68x328 processor.
-
-config MEMORY_RESERVE
-	int "Memory reservation (MiB)"
-	depends on (UCSIMM || UCDIMM)
-	help
-	  Reserve certain memory regions on 68x328 based boards.
-
-config UCQUICC
-	bool "Lineo uCquicc board support"
-	depends on M68360
-	help
-	  Support for the Lineo uCquicc board.
-
-config ARN5206
-	bool "Arnewsh 5206 board support"
-	depends on M5206
-	help
-	  Support for the Arnewsh 5206 board.
-
-config M5206eC3
-	bool "Motorola M5206eC3 board support"
-	depends on M5206e
-	help
-	  Support for the Motorola M5206eC3 board.
-
-config ELITE
-	bool "Motorola M5206eLITE board support"
-	depends on M5206e
-	help
-	  Support for the Motorola M5206eLITE board.
-
-config M5208EVB
-	bool "Freescale M5208EVB board support"
-	depends on M520x
-	help
-	  Support for the Freescale Coldfire M5208EVB.
-
-config M5235EVB
-	bool "Freescale M5235EVB support"
-	depends on M523x
-	help
-	  Support for the Freescale M5235EVB board.
-
-config M5249C3
-	bool "Motorola M5249C3 board support"
-	depends on M5249
-	help
-	  Support for the Motorola M5249C3 board.
-
-config M5271EVB
-	bool "Freescale (Motorola) M5271EVB board support"
-	depends on M5271
-	help
-	  Support for the Freescale (Motorola) M5271EVB board.
-
-config M5275EVB
-	bool "Freescale (Motorola) M5275EVB board support"
-	depends on M5275
-	help
-	  Support for the Freescale (Motorola) M5275EVB board.
-
-config M5272C3
-	bool "Motorola M5272C3 board support"
-	depends on M5272
-	help
-	  Support for the Motorola M5272C3 board.
-
-config COBRA5272
-	bool "senTec COBRA5272 board support"
-	depends on M5272
-	help
-	  Support for the senTec COBRA5272 board.
-
-config AVNET5282
-	bool "Avnet 5282 board support"
-	depends on M528x
-	help
-	  Support for the Avnet 5282 board.  
-	  
-config M5282EVB
-	bool "Motorola M5282EVB board support"
-	depends on M528x
-	help
-	  Support for the Motorola M5282EVB board.
-
-config COBRA5282
-	bool "senTec COBRA5282 board support"
-	depends on M528x
-	help
-	  Support for the senTec COBRA5282 board.
-	  
-config SOM5282EM
-	bool "EMAC.Inc SOM5282EM board support"
-	depends on M528x
-	help
-	  Support for the EMAC.Inc SOM5282EM module.  
-	  
-config WILDFIRE
-	bool "Intec Automation Inc. WildFire board support"
-	depends on M528x
-	help
-	  Support for the Intec Automation Inc. WildFire.
-	  
-config WILDFIREMOD
-	bool "Intec Automation Inc. WildFire module support"
-	depends on M528x
-	help
-	  Support for the Intec Automation Inc. WildFire module.
-
-config ARN5307
-	bool "Arnewsh 5307 board support"
-	depends on M5307
-	help
-	  Support for the Arnewsh 5307 board.
-
-config M5307C3
-	bool "Motorola M5307C3 board support"
-	depends on M5307
-	help
-	  Support for the Motorola M5307C3 board.
-
-config SECUREEDGEMP3
-	bool "SnapGear SecureEdge/MP3 platform support"
-	depends on M5307
-	help
-	  Support for the SnapGear SecureEdge/MP3 platform.
-
-config M5329EVB
-	bool "Freescale (Motorola) M5329EVB board support"
-	depends on M532x
-	help
-	  Support for the Freescale (Motorola) M5329EVB board.
-
-config COBRA5329
-	bool "senTec COBRA5329 board support"
-	depends on M532x
-	help
-	  Support for the senTec COBRA5329 board.
-
-config M5407C3
-	bool "Motorola M5407C3 board support"
-	depends on M5407
-	help
-	  Support for the Motorola M5407C3 board.
-
-config CLEOPATRA
-	bool "Feith CLEOPATRA board support"
-	depends on (M5307 || M5407)
-	help
-	  Support for the Feith Cleopatra boards.
-
-config CANCam
-	bool "Feith CANCam board support"
-	depends on M5272
-	help
-	  Support for the Feith CANCam board.
-
-config SCALES
-	bool "Feith SCALES board support"
-	depends on M5272
-	help
-	  Support for the Feith SCALES board.
-
-config NETtel
-	bool "SecureEdge/NETtel board support"
-	depends on (M5206e || M5272 || M5307)
-	help
-	  Support for the SnapGear NETtel/SecureEdge/SnapGear boards.
-
-config SNAPGEAR
-	bool "SnapGear router board support"
-	depends on NETtel
-	help
-	  Special additional support for SnapGear router boards.
-
-config CPU16B
-	bool "Sneha Technologies S.L. Sarasvati board support"
-	depends on M5272
-	help
-	  Support for the SNEHA CPU16B board.
-
-config MOD5272
-	bool "Netburner MOD-5272 board support"
-	depends on M5272
-	help
-	  Support for the Netburner MOD-5272 board.
-
-config SAVANTrosie1
-	bool "Savant Rosie1 board support"
-	depends on M523x
-	help
-	  Support for the Savant Rosie1 board.
-
-config ROMFS_FROM_ROM
-	bool "ROMFS image not RAM resident"
-	depends on (NETtel || SNAPGEAR)
-	help
-	  The ROMfs filesystem will stay resident in the FLASH/ROM, not be
-	  moved into RAM.
-
-config PILOT
-	bool
-	default y
-	depends on (PILOT3 || PILOT5)
-
-config ARNEWSH
-	bool
-	default y
-	depends on (ARN5206 || ARN5307)
-
-config FREESCALE
-	bool
-	default y
-	depends on (M5206eC3 || M5208EVB || M5235EVB || M5249C3 || M5271EVB || M5272C3 || M5275EVB || M5282EVB || M5307C3 || M5329EVB || M5407C3)
-
-config HW_FEITH
-	bool
-	default y
-	depends on (CLEOPATRA || CANCam || SCALES)
-
-config senTec
-	bool
-	default y
-	depends on (COBRA5272 || COBRA5282)
-	
-config EMAC_INC
-	bool
-	default y
-	depends on (SOM5282EM)
-
-config SNEHA
-	bool
-	default y
-	depends on CPU16B
-
-config SAVANT
-	bool
-	default y
-	depends on SAVANTrosie1
-
-config AVNET
-	bool
-	default y
-	depends on (AVNET5282)
-
-config UBOOT
-	bool "Support for U-Boot command line parameters"
-	help
-	  If you say Y here kernel will try to collect command
-	  line parameters from the initial u-boot stack.
-	default n
-
-config 4KSTACKS
-	bool "Use 4Kb for kernel stacks instead of 8Kb"
-	default y
-	help
-	  If you say Y here the kernel will use a 4Kb stacksize for the
-	  kernel stack attached to each process/thread. This facilitates
-	  running more threads on a system and also reduces the pressure
-	  on the VM subsystem for higher order allocations.
-
-config HZ
-	int
-	default 1000 if CLEOPATRA
-	default 100
-
-comment "RAM configuration"
-
-config RAMBASE
-	hex "Address of the base of RAM"
-	default "0"
-	help
-	  Define the address that RAM starts at. On many platforms this is
-	  0, the base of the address space. And this is the default. Some
-	  platforms choose to setup their RAM at other addresses within the
-	  processor address space.
-
-config RAMSIZE
-	hex "Size of RAM (in bytes), or 0 for automatic"
-	default "0x400000"
-	help
-	  Define the size of the system RAM. If you select 0 then the
-	  kernel will try to probe the RAM size at runtime. This is not
-	  supported on all CPU types.
-
-config VECTORBASE
-	hex "Address of the base of system vectors"
-	default "0"
-	help
-	  Define the address of the system vectors. Commonly this is
-	  put at the start of RAM, but it doesn't have to be. On ColdFire
-	  platforms this address is programmed into the VBR register, thus
-	  actually setting the address to use.
-
-config KERNELBASE
-	hex "Address of the base of kernel code"
-	default "0x400"
-	help
-	  Typically on m68k systems the kernel will not start at the base
-	  of RAM, but usually some small offset from it. Define the start
-	  address of the kernel here. The most common setup will have the
-	  processor vectors at the base of RAM and then the start of the
-	  kernel. On some platforms some RAM is reserved for boot loaders
-	  and the kernel starts after that. The 0x400 default was based on
-	  a system with the RAM based at address 0, and leaving enough room
-	  for the theoretical maximum number of 256 vectors.
-
-choice
-	prompt "RAM bus width"
-	default RAMAUTOBIT
-
-config RAMAUTOBIT
-	bool "AUTO"
-	help
-	  Select the physical RAM data bus size. Not needed on most platforms,
-	  so you can generally choose AUTO.
-
-config RAM8BIT
-	bool "8bit"
-	help
-	  Configure RAM bus to be 8 bits wide.
-
-config RAM16BIT
-	bool "16bit"
-	help
-	  Configure RAM bus to be 16 bits wide.
-
-config RAM32BIT
-	bool "32bit"
-	help
-	  Configure RAM bus to be 32 bits wide.
-
-endchoice
-
-comment "ROM configuration"
-
-config ROM
-	bool "Specify ROM linker regions"
-	default n
-	help
-	  Define a ROM region for the linker script. This creates a kernel
-	  that can be stored in flash, with possibly the text, and data
-	  regions being copied out to RAM at startup.
-
-config ROMBASE
-	hex "Address of the base of ROM device"
-	default "0"
-	depends on ROM
-	help
-	  Define the address that the ROM region starts at. Some platforms
-	  use this to set their chip select region accordingly for the boot
-	  device.
-
-config ROMVEC
-	hex "Address of the base of the ROM vectors"
-	default "0"
-	depends on ROM
-	help
-	  This is almost always the same as the base of the ROM. Since on all
-	  68000 type variants the vectors are at the base of the boot device
-	  on system startup.
-
-config ROMVECSIZE
-	hex "Size of ROM vector region (in bytes)"
-	default "0x400"
-	depends on ROM
-	help
-	  Define the size of the vector region in ROM. For most 68000
-	  variants this would be 0x400 bytes in size. Set to 0 if you do
-	  not want a vector region at the start of the ROM.
-
-config ROMSTART
-	hex "Address of the base of system image in ROM"
-	default "0x400"
-	depends on ROM
-	help
-	  Define the start address of the system image in ROM. Commonly this
-	  is strait after the ROM vectors.
-
-config ROMSIZE
-	hex "Size of the ROM device"
-	default "0x100000"
-	depends on ROM
-	help
-	  Size of the ROM device. On some platforms this is used to setup
-	  the chip select that controls the boot ROM device.
-
-choice
-	prompt "Kernel executes from"
-	---help---
-	  Choose the memory type that the kernel will be running in.
-
-config RAMKERNEL
-	bool "RAM"
-	help
-	  The kernel will be resident in RAM when running.
-
-config ROMKERNEL
-	bool "ROM"
-	help
-	  The kernel will be resident in FLASH/ROM when running. This is
-	  often referred to as Execute-in-Place (XIP), since the kernel
-	  code executes from the position it is stored in the FLASH/ROM.
-
-endchoice
-
-if COLDFIRE
-source "kernel/Kconfig.preempt"
-endif
-
-source "kernel/time/Kconfig"
-
-source "mm/Kconfig"
-
-endmenu
-
-config ISA_DMA_API
-	bool
-	depends on !M5272
-	default y
-
-source "drivers/pcmcia/Kconfig"
-
-menu "Executable file formats"
-
-source "fs/Kconfig.binfmt"
-
-endmenu
-
-menu "Power management options"
-
-config PM
-	bool "Power Management support"
-	help
-	  Support processor power management modes
-
-endmenu
-
-source "net/Kconfig"
-
-source "drivers/Kconfig"
-
-source "fs/Kconfig"
-
-source "arch/m68knommu/Kconfig.debug"
-
-source "security/Kconfig"
-
-source "crypto/Kconfig"
-
-source "lib/Kconfig"
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/Kconfig.debug linux-libre-2.6.39-gnu/arch/m68knommu/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/m68knommu/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/Kconfig.debug	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-menu "Kernel hacking"
-
-source "lib/Kconfig.debug"
-
-config FULLDEBUG
-	bool "Full Symbolic/Source Debugging support"
-	help
-	  Enable debugging symbols on kernel build.
-
-config HIGHPROFILE
-	bool "Use fast second timer for profiling"
-	depends on COLDFIRE
-	help
-	  Use a fast secondary clock to produce profiling information.
-
-config BOOTPARAM
-	bool 'Compiled-in Kernel Boot Parameter'
-
-config BOOTPARAM_STRING
-	string 'Kernel Boot Parameter'
-	default 'console=ttyS0,19200'
-	depends on BOOTPARAM
-
-config NO_KERNEL_MSG
-	bool "Suppress Kernel BUG Messages"
-	help
-	  Do not output any debug BUG messages within the kernel.
-
-config BDM_DISABLE
-	bool "Disable BDM signals"
-	depends on (EXPERIMENTAL && COLDFIRE)
-	help
-	  Disable the ColdFire CPU's BDM signals.
-
-endmenu
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/asm-offsets.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/asm-offsets.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/asm-offsets.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/asm-offsets.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/*
- * This program is used to generate definitions needed by
- * assembly language modules.
- *
- * We use the technique used in the OSF Mach kernel code:
- * generate asm statements containing #defines,
- * compile this file to assembler, and then extract the
- * #defines from the assembly-language output.
- */
-
-#include <linux/stddef.h>
-#include <linux/sched.h>
-#include <linux/kernel_stat.h>
-#include <linux/ptrace.h>
-#include <linux/hardirq.h>
-#include <linux/kbuild.h>
-#include <asm/bootinfo.h>
-#include <asm/irq.h>
-#include <asm/thread_info.h>
-
-int main(void)
-{
-	/* offsets into the task struct */
-	DEFINE(TASK_THREAD, offsetof(struct task_struct, thread));
-	DEFINE(TASK_MM, offsetof(struct task_struct, mm));
-
-	/* offsets into the irq_cpustat_t struct */
-	DEFINE(CPUSTAT_SOFTIRQ_PENDING, offsetof(irq_cpustat_t, __softirq_pending));
-
-	/* offsets into the thread struct */
-	DEFINE(THREAD_KSP, offsetof(struct thread_struct, ksp));
-	DEFINE(THREAD_USP, offsetof(struct thread_struct, usp));
-	DEFINE(THREAD_SR, offsetof(struct thread_struct, sr));
-	DEFINE(THREAD_FS, offsetof(struct thread_struct, fs));
-	DEFINE(THREAD_CRP, offsetof(struct thread_struct, crp));
-	DEFINE(THREAD_ESP0, offsetof(struct thread_struct, esp0));
-	DEFINE(THREAD_FPREG, offsetof(struct thread_struct, fp));
-	DEFINE(THREAD_FPCNTL, offsetof(struct thread_struct, fpcntl));
-	DEFINE(THREAD_FPSTATE, offsetof(struct thread_struct, fpstate));
-
-	/* offsets into the pt_regs */
-	DEFINE(PT_OFF_D0, offsetof(struct pt_regs, d0));
-	DEFINE(PT_OFF_ORIG_D0, offsetof(struct pt_regs, orig_d0));
-	DEFINE(PT_OFF_D1, offsetof(struct pt_regs, d1));
-	DEFINE(PT_OFF_D2, offsetof(struct pt_regs, d2));
-	DEFINE(PT_OFF_D3, offsetof(struct pt_regs, d3));
-	DEFINE(PT_OFF_D4, offsetof(struct pt_regs, d4));
-	DEFINE(PT_OFF_D5, offsetof(struct pt_regs, d5));
-	DEFINE(PT_OFF_A0, offsetof(struct pt_regs, a0));
-	DEFINE(PT_OFF_A1, offsetof(struct pt_regs, a1));
-	DEFINE(PT_OFF_A2, offsetof(struct pt_regs, a2));
-	DEFINE(PT_OFF_PC, offsetof(struct pt_regs, pc));
-	DEFINE(PT_OFF_SR, offsetof(struct pt_regs, sr));
-
-#ifdef CONFIG_COLDFIRE
-	/* bitfields are a bit difficult */
-	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, sr) - 2);
-#else
-	/* bitfields are a bit difficult */
-	DEFINE(PT_OFF_FORMATVEC, offsetof(struct pt_regs, pc) + 4);
-#endif
-
-	/* signal defines */
-	DEFINE(SIGSEGV, SIGSEGV);
-	DEFINE(SEGV_MAPERR, SEGV_MAPERR);
-	DEFINE(SIGTRAP, SIGTRAP);
-	DEFINE(TRAP_TRACE, TRAP_TRACE);
-
-	DEFINE(PT_PTRACED, PT_PTRACED);
-
-	/* Offsets in thread_info structure */
-	DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
-	DEFINE(TI_PREEMPTCOUNT, offsetof(struct thread_info, preempt_count));
-
-	return 0;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/dma.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/dma.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,74 +0,0 @@
-/*
- * Dynamic DMA mapping support.
- *
- * We never have any address translations to worry about, so this
- * is just alloc/free.
- */
-
-#include <linux/types.h>
-#include <linux/gfp.h>
-#include <linux/mm.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <asm/cacheflush.h>
-
-void *dma_alloc_coherent(struct device *dev, size_t size,
-			   dma_addr_t *dma_handle, gfp_t gfp)
-{
-	void *ret;
-	/* ignore region specifiers */
-	gfp &= ~(__GFP_DMA | __GFP_HIGHMEM);
-
-	if (dev == NULL || (*dev->dma_mask < 0xffffffff))
-		gfp |= GFP_DMA;
-	ret = (void *)__get_free_pages(gfp, get_order(size));
-
-	if (ret != NULL) {
-		memset(ret, 0, size);
-		*dma_handle = virt_to_phys(ret);
-	}
-	return ret;
-}
-
-void dma_free_coherent(struct device *dev, size_t size,
-			 void *vaddr, dma_addr_t dma_handle)
-{
-	free_pages((unsigned long)vaddr, get_order(size));
-}
-
-void dma_sync_single_for_device(struct device *dev, dma_addr_t handle,
-				size_t size, enum dma_data_direction dir)
-{
-	switch (dir) {
-	case DMA_TO_DEVICE:
-		flush_dcache_range(handle, size);
-		break;
-	case DMA_FROM_DEVICE:
-		/* Should be clear already */
-		break;
-	default:
-		if (printk_ratelimit())
-			printk("dma_sync_single_for_device: unsupported dir %u\n", dir);
-		break;
-	}
-}
-
-EXPORT_SYMBOL(dma_sync_single_for_device);
-dma_addr_t dma_map_single(struct device *dev, void *addr, size_t size,
-			  enum dma_data_direction dir)
-{
-	dma_addr_t handle = virt_to_phys(addr);
-	flush_dcache_range(handle, size);
-	return handle;
-}
-EXPORT_SYMBOL(dma_map_single);
-
-dma_addr_t dma_map_page(struct device *dev, struct page *page,
-			unsigned long offset, size_t size,
-			enum dma_data_direction dir)
-{
-	dma_addr_t handle = page_to_phys(page) + offset;
-	dma_sync_single_for_device(dev, handle, size, dir);
-	return handle;
-}
-EXPORT_SYMBOL(dma_map_page);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/entry.S linux-libre-2.6.39-gnu/arch/m68knommu/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/entry.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/entry.S
- *
- *  Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo Inc. (www.lineo.com) 
- *
- * Based on:
- *
- *  linux/arch/m68k/kernel/entry.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- * ColdFire support by Greg Ungerer (gerg@snapgear.com)
- * 5307 fixes by David W. Miller
- * linux 2.4 support David McCullough <davidm@snapgear.com>
- */
-
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/errno.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/asm-offsets.h>
-#include <asm/entry.h>
-#include <asm/unistd.h>
-
-.text
-
-.globl buserr
-.globl trap
-.globl ret_from_exception
-.globl ret_from_signal
-.globl sys_fork
-.globl sys_clone
-.globl sys_vfork
-
-ENTRY(buserr)
-	SAVE_ALL
-	moveq	#-1,%d0
-	movel	%d0,%sp@(PT_OFF_ORIG_D0)
-	movel	%sp,%sp@- 		/* stack frame pointer argument */
-	jsr	buserr_c
-	addql	#4,%sp
-	jra	ret_from_exception
-
-ENTRY(trap)
-	SAVE_ALL
-	moveq	#-1,%d0
-	movel	%d0,%sp@(PT_OFF_ORIG_D0)
-	movel	%sp,%sp@- 		/* stack frame pointer argument */
-	jsr	trap_c
-	addql	#4,%sp
-	jra	ret_from_exception
-
-#ifdef TRAP_DBG_INTERRUPT
-
-.globl dbginterrupt
-ENTRY(dbginterrupt)
-	SAVE_ALL
-	moveq	#-1,%d0
-	movel	%d0,%sp@(PT_OFF_ORIG_D0)
-	movel	%sp,%sp@- 		/* stack frame pointer argument */
-	jsr	dbginterrupt_c
-	addql	#4,%sp
-	jra	ret_from_exception
-#endif
-
-ENTRY(reschedule)
-	/* save top of frame */
-	pea	%sp@
-	jbsr	set_esp0
-	addql	#4,%sp
-	pea	ret_from_exception
-	jmp	schedule
-
-ENTRY(ret_from_fork)
-	movel	%d1,%sp@-
-	jsr	schedule_tail
-	addql	#4,%sp
-	jra	ret_from_exception
-
-ENTRY(sys_fork)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_fork
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_vfork)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_vfork
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_clone)
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jbsr	m68k_clone
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_sigreturn)
-	SAVE_SWITCH_STACK
-	jbsr	do_sigreturn
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(sys_rt_sigreturn)
-	SAVE_SWITCH_STACK
-	jbsr	do_rt_sigreturn
-	RESTORE_SWITCH_STACK
-	rts
-
-ENTRY(ret_from_user_signal)
-	moveq #__NR_sigreturn,%d0
-	trap #0
-
-ENTRY(ret_from_user_rt_signal)
-	movel #__NR_rt_sigreturn,%d0
-	trap #0
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/.gitignore linux-libre-2.6.39-gnu/arch/m68knommu/kernel/.gitignore
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/.gitignore	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/.gitignore	1969-12-31 19:00:00.000000000 -0500
@@ -1 +0,0 @@
-vmlinux.lds
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/init_task.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/init_task.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/init_task.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/init_task.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,36 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/init_task.c
- */
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init.h>
-#include <linux/init_task.h>
-#include <linux/fs.h>
-#include <linux/mqueue.h>
-
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * All other task structs will be allocated on slabs in fork.c
- */
-__asm__(".align 4");
-struct task_struct init_task = INIT_TASK(init_task);
-
-EXPORT_SYMBOL(init_task);
-
-/*
- * Initial thread structure.
- *
- * We need to make sure that this is 8192-byte aligned due to the
- * way process stacks are handled. This is done by having a special
- * "init_task" linker map entry..
- */
-union thread_union init_thread_union __init_task_data =
-	{ INIT_THREAD_INFO(init_task) };
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/irq.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,56 +0,0 @@
-/*
- * irq.c
- *
- * (C) Copyright 2007, Greg Ungerer <gerg@snapgear.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/kernel_stat.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/seq_file.h>
-#include <asm/system.h>
-#include <asm/traps.h>
-
-asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
-{
-	struct pt_regs *oldregs = set_irq_regs(regs);
-
-	irq_enter();
-	generic_handle_irq(irq);
-	irq_exit();
-
-	set_irq_regs(oldregs);
-}
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	struct irqaction *ap;
-	int irq = *((loff_t *) v);
-
-	if (irq == 0)
-		seq_puts(p, "           CPU0\n");
-
-	if (irq < NR_IRQS) {
-		ap = irq_desc[irq].action;
-		if (ap) {
-			seq_printf(p, "%3d: ", irq);
-			seq_printf(p, "%10u ", kstat_irqs(irq));
-			seq_printf(p, "%14s  ", irq_desc[irq].chip->name);
-
-			seq_printf(p, "%s", ap->name);
-			for (ap = ap->next; ap; ap = ap->next)
-				seq_printf(p, ", %s", ap->name);
-			seq_putc(p, '\n');
-		}
-	}
-
-	return 0;
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/m68k_ksyms.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/m68k_ksyms.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/m68k_ksyms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/m68k_ksyms.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-#include <linux/module.h>
-#include <linux/linkage.h>
-#include <linux/sched.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/user.h>
-#include <linux/elfcore.h>
-#include <linux/in6.h>
-#include <linux/interrupt.h>
-
-#include <asm/setup.h>
-#include <asm/machdep.h>
-#include <asm/pgalloc.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/checksum.h>
-#include <asm/current.h>
-
-extern int dump_fpu(struct pt_regs *, elf_fpregset_t *);
-
-/* platform dependent support */
-
-EXPORT_SYMBOL(__ioremap);
-EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(dump_fpu);
-
-EXPORT_SYMBOL(ip_fast_csum);
-
-EXPORT_SYMBOL(kernel_thread);
-
-/* Networking helper routines. */
-EXPORT_SYMBOL(csum_partial_copy_nocheck);
-
-/* The following are special because they're not called
-   explicitly (the C compiler generates them).  Fortunately,
-   their interface isn't gonna change any time soon now, so
-   it's OK to leave it out of version control.  */
-EXPORT_SYMBOL(memcpy);
-EXPORT_SYMBOL(memset);
-
-/*
- * libgcc functions - functions that are used internally by the
- * compiler...  (prototypes are not correct though, but that
- * doesn't really matter since they're not versioned).
- */
-extern void __ashldi3(void);
-extern void __ashrdi3(void);
-extern void __divsi3(void);
-extern void __lshrdi3(void);
-extern void __modsi3(void);
-extern void __muldi3(void);
-extern void __mulsi3(void);
-extern void __udivsi3(void);
-extern void __umodsi3(void);
-
-        /* gcc lib functions */
-EXPORT_SYMBOL(__ashldi3);
-EXPORT_SYMBOL(__ashrdi3);
-EXPORT_SYMBOL(__divsi3);
-EXPORT_SYMBOL(__lshrdi3);
-EXPORT_SYMBOL(__modsi3);
-EXPORT_SYMBOL(__muldi3);
-EXPORT_SYMBOL(__mulsi3);
-EXPORT_SYMBOL(__udivsi3);
-EXPORT_SYMBOL(__umodsi3);
-
-#ifdef CONFIG_COLDFIRE
-extern unsigned int *dma_device_address;
-extern unsigned long dma_base_addr, _ramend;
-EXPORT_SYMBOL(dma_base_addr);
-EXPORT_SYMBOL(dma_device_address);
-EXPORT_SYMBOL(_ramend);
-
-extern asmlinkage void trap(void);
-extern void	*_ramvec;
-EXPORT_SYMBOL(trap);
-EXPORT_SYMBOL(_ramvec);
-#endif /* CONFIG_COLDFIRE */
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Makefile for arch/m68knommu/kernel.
-#
-
-extra-y := vmlinux.lds
-
-obj-y += dma.o entry.o init_task.o irq.o m68k_ksyms.o process.o ptrace.o \
-	 setup.o signal.o syscalltable.o sys_m68k.o time.o traps.o
-
-obj-$(CONFIG_MODULES)	+= module.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/module.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/module.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/module.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/module.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,126 +0,0 @@
-#include <linux/moduleloader.h>
-#include <linux/elf.h>
-#include <linux/vmalloc.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-#include <linux/kernel.h>
-
-#if 0
-#define DEBUGP printk
-#else
-#define DEBUGP(fmt...)
-#endif
-
-void *module_alloc(unsigned long size)
-{
-	if (size == 0)
-		return NULL;
-	return vmalloc(size);
-}
-
-
-/* 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;
-}
-
-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_68K_32:
-			/* We add the value into the location given */
-			*location += sym->st_value;
-			break;
-		case R_68K_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)
-{
-	unsigned int i;
-	Elf32_Rela *rel = (void *)sechdrs[relsec].sh_addr;
-	Elf32_Sym *sym;
-	uint32_t *location;
-
-	DEBUGP("Applying relocate_add 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_68K_32:
-			/* We add the value into the location given */
-			*location = rel[i].r_addend + sym->st_value;
-			break;
-		case R_68K_PC32:
-			/* Add the value, subtract its postition */
-			*location = rel[i].r_addend + 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 module_finalize(const Elf_Ehdr *hdr,
-		    const Elf_Shdr *sechdrs,
-		    struct module *me)
-{
-	return 0;
-}
-
-void module_arch_cleanup(struct module *mod)
-{
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/process.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/process.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,404 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/process.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  68060 fixes by Jesper Skov
- *
- *  uClinux changes
- *  Copyright (C) 2000-2002, David McCullough <davidm@snapgear.com>
- */
-
-/*
- * This file handles the architecture-dependent parts of process handling..
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/stddef.h>
-#include <linux/unistd.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/fs.h>
-#include <linux/slab.h>
-
-#include <asm/uaccess.h>
-#include <asm/system.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/setup.h>
-#include <asm/pgtable.h>
-
-asmlinkage void ret_from_fork(void);
-
-/*
- * The following aren't currently used.
- */
-void (*pm_idle)(void);
-EXPORT_SYMBOL(pm_idle);
-
-void (*pm_power_off)(void);
-EXPORT_SYMBOL(pm_power_off);
-
-/*
- * The idle loop on an m68knommu..
- */
-static void default_idle(void)
-{
-	local_irq_disable();
- 	while (!need_resched()) {
-		/* This stop will re-enable interrupts */
- 		__asm__("stop #0x2000" : : : "cc");
-		local_irq_disable();
-	}
-	local_irq_enable();
-}
-
-void (*idle)(void) = default_idle;
-
-/*
- * The idle thread. There's no useful work to be
- * done, so just try to conserve power and have a
- * low exit latency (ie sit in a loop waiting for
- * somebody to say that they'd like to reschedule)
- */
-void cpu_idle(void)
-{
-	/* endless idle loop with no priority at all */
-	while (1) {
-		idle();
-		preempt_enable_no_resched();
-		schedule();
-		preempt_disable();
-	}
-}
-
-void machine_restart(char * __unused)
-{
-	if (mach_reset)
-		mach_reset();
-	for (;;);
-}
-
-void machine_halt(void)
-{
-	if (mach_halt)
-		mach_halt();
-	for (;;);
-}
-
-void machine_power_off(void)
-{
-	if (mach_power_off)
-		mach_power_off();
-	for (;;);
-}
-
-void show_regs(struct pt_regs * regs)
-{
-	printk(KERN_NOTICE "\n");
-	printk(KERN_NOTICE "Format %02x  Vector: %04x  PC: %08lx  Status: %04x    %s\n",
-	       regs->format, regs->vector, regs->pc, regs->sr, print_tainted());
-	printk(KERN_NOTICE "ORIG_D0: %08lx  D0: %08lx  A2: %08lx  A1: %08lx\n",
-	       regs->orig_d0, regs->d0, regs->a2, regs->a1);
-	printk(KERN_NOTICE "A0: %08lx  D5: %08lx  D4: %08lx\n",
-	       regs->a0, regs->d5, regs->d4);
-	printk(KERN_NOTICE "D3: %08lx  D2: %08lx  D1: %08lx\n",
-	       regs->d3, regs->d2, regs->d1);
-	if (!(regs->sr & PS_S))
-		printk(KERN_NOTICE "USP: %08lx\n", rdusp());
-}
-
-/*
- * Create a kernel thread
- */
-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
-{
-	int retval;
-	long clone_arg = flags | CLONE_VM;
-	mm_segment_t fs;
-
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	__asm__ __volatile__ (
-			"movel	%%sp, %%d2\n\t"
-			"movel	%5, %%d1\n\t"
-			"movel	%1, %%d0\n\t"
-			"trap	#0\n\t"
-			"cmpl	%%sp, %%d2\n\t"
-			"jeq	1f\n\t"
-			"movel	%3, %%sp@-\n\t"
-			"jsr	%4@\n\t"
-			"movel	%2, %%d0\n\t"
-			"trap	#0\n"
-			"1:\n\t"
-			"movel	%%d0, %0\n"
-		: "=d" (retval)
-		: "i" (__NR_clone),
-		  "i" (__NR_exit),
-		  "a" (arg),
-		  "a" (fn),
-		  "a" (clone_arg)
-		: "cc", "%d0", "%d1", "%d2");
-
-	set_fs(fs);
-	return retval;
-}
-
-void flush_thread(void)
-{
-#ifdef CONFIG_FPU
-	unsigned long zero = 0;
-#endif
-	set_fs(USER_DS);
-	current->thread.fs = __USER_DS;
-#ifdef CONFIG_FPU
-	if (!FPU_IS_EMU)
-		asm volatile (".chip 68k/68881\n\t"
-			      "frestore %0@\n\t"
-			      ".chip 68k" : : "a" (&zero));
-#endif
-}
-
-/*
- * "m68k_fork()".. By the time we get here, the
- * non-volatile registers have also been saved on the
- * stack. We do some ugly pointer stuff here.. (see
- * also copy_thread)
- */
-
-asmlinkage int m68k_fork(struct pt_regs *regs)
-{
-	/* fork almost works, enough to trick you into looking elsewhere :-( */
-	return(-EINVAL);
-}
-
-asmlinkage int m68k_vfork(struct pt_regs *regs)
-{
-	return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);
-}
-
-asmlinkage int m68k_clone(struct pt_regs *regs)
-{
-	unsigned long clone_flags;
-	unsigned long newsp;
-
-	/* syscall2 puts clone_flags in d1 and usp in d2 */
-	clone_flags = regs->d1;
-	newsp = regs->d2;
-	if (!newsp)
-		newsp = rdusp();
-        return do_fork(clone_flags, newsp, regs, 0, NULL, NULL);
-}
-
-int copy_thread(unsigned long clone_flags,
-		unsigned long usp, unsigned long topstk,
-		struct task_struct * p, struct pt_regs * regs)
-{
-	struct pt_regs * childregs;
-	struct switch_stack * childstack, *stack;
-	unsigned long *retp;
-
-	childregs = (struct pt_regs *) (task_stack_page(p) + THREAD_SIZE) - 1;
-
-	*childregs = *regs;
-	childregs->d0 = 0;
-
-	retp = ((unsigned long *) regs);
-	stack = ((struct switch_stack *) retp) - 1;
-
-	childstack = ((struct switch_stack *) childregs) - 1;
-	*childstack = *stack;
-	childstack->retpc = (unsigned long)ret_from_fork;
-
-	p->thread.usp = usp;
-	p->thread.ksp = (unsigned long)childstack;
-
-	if (clone_flags & CLONE_SETTLS)
-		task_thread_info(p)->tp_value = regs->d5;
-
-	/*
-	 * Must save the current SFC/DFC value, NOT the value when
-	 * the parent was last descheduled - RGH  10-08-96
-	 */
-	p->thread.fs = get_fs().seg;
-
-#ifdef CONFIG_FPU
-	if (!FPU_IS_EMU) {
-		/* Copy the current fpu state */
-		asm volatile ("fsave %0" : : "m" (p->thread.fpstate[0]) : "memory");
-
-		if (p->thread.fpstate[0])
-		  asm volatile ("fmovemx %/fp0-%/fp7,%0\n\t"
-				"fmoveml %/fpiar/%/fpcr/%/fpsr,%1"
-				: : "m" (p->thread.fp[0]), "m" (p->thread.fpcntl[0])
-				: "memory");
-		/* Restore the state in case the fpu was busy */
-		asm volatile ("frestore %0" : : "m" (p->thread.fpstate[0]));
-	}
-#endif
-
-	return 0;
-}
-
-/* Fill in the fpu structure for a core dump.  */
-
-int dump_fpu(struct pt_regs *regs, struct user_m68kfp_struct *fpu)
-{
-#ifdef CONFIG_FPU
-	char fpustate[216];
-
-	if (FPU_IS_EMU) {
-		int i;
-
-		memcpy(fpu->fpcntl, current->thread.fpcntl, 12);
-		memcpy(fpu->fpregs, current->thread.fp, 96);
-		/* Convert internal fpu reg representation
-		 * into long double format
-		 */
-		for (i = 0; i < 24; i += 3)
-			fpu->fpregs[i] = ((fpu->fpregs[i] & 0xffff0000) << 15) |
-			                 ((fpu->fpregs[i] & 0x0000ffff) << 16);
-		return 1;
-	}
-
-	/* First dump the fpu context to avoid protocol violation.  */
-	asm volatile ("fsave %0" :: "m" (fpustate[0]) : "memory");
-	if (!fpustate[0])
-		return 0;
-
-	asm volatile ("fmovem %/fpiar/%/fpcr/%/fpsr,%0"
-		:: "m" (fpu->fpcntl[0])
-		: "memory");
-	asm volatile ("fmovemx %/fp0-%/fp7,%0"
-		:: "m" (fpu->fpregs[0])
-		: "memory");
-#endif
-	return 1;
-}
-
-/*
- *	Generic dumping code. Used for panic and debug.
- */
-void dump(struct pt_regs *fp)
-{
-	unsigned long	*sp;
-	unsigned char	*tp;
-	int		i;
-
-	printk(KERN_EMERG "\nCURRENT PROCESS:\n\n");
-	printk(KERN_EMERG "COMM=%s PID=%d\n", current->comm, current->pid);
-
-	if (current->mm) {
-		printk(KERN_EMERG "TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
-			(int) current->mm->start_code,
-			(int) current->mm->end_code,
-			(int) current->mm->start_data,
-			(int) current->mm->end_data,
-			(int) current->mm->end_data,
-			(int) current->mm->brk);
-		printk(KERN_EMERG "USER-STACK=%08x KERNEL-STACK=%08x\n\n",
-			(int) current->mm->start_stack,
-			(int)(((unsigned long) current) + THREAD_SIZE));
-	}
-
-	printk(KERN_EMERG "PC: %08lx\n", fp->pc);
-	printk(KERN_EMERG "SR: %08lx    SP: %08lx\n", (long) fp->sr, (long) fp);
-	printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-		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 "\nUSP: %08x   TRAPFRAME: %p\n",
-		(unsigned int) rdusp(), fp);
-
-	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(KERN_EMERG "%p: ", tp + i);
-		printk("%08x ", (int) *sp++);
-	}
-	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(KERN_EMERG "%p: ", tp + i);
-		printk("%08x ", (int) *sp++);
-	}
-	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(KERN_EMERG "%p: ", tp + i);
-		printk("%08x ", (int) *sp++);
-	}
-	printk(KERN_EMERG "\n");
-}
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int sys_execve(const char *name,
-			  const char *const *argv,
-			  const char *const *envp)
-{
-	int error;
-	char * filename;
-	struct pt_regs *regs = (struct pt_regs *) &name;
-
-	filename = getname(name);
-	error = PTR_ERR(filename);
-	if (IS_ERR(filename))
-		return error;
-	error = do_execve(filename, argv, envp, regs);
-	putname(filename);
-	return error;
-}
-
-unsigned long get_wchan(struct task_struct *p)
-{
-	unsigned long fp, pc;
-	unsigned long stack_page;
-	int count = 0;
-	if (!p || p == current || p->state == TASK_RUNNING)
-		return 0;
-
-	stack_page = (unsigned long)p;
-	fp = ((struct switch_stack *)p->thread.ksp)->a6;
-	do {
-		if (fp < stack_page+sizeof(struct thread_info) ||
-		    fp >= THREAD_SIZE-8+stack_page)
-			return 0;
-		pc = ((unsigned long *)fp)[1];
-		if (!in_sched_functions(pc))
-			return pc;
-		fp = *(unsigned long *) fp;
-	} while (count++ < 16);
-	return 0;
-}
-
-/*
- * Return saved PC of a blocked thread.
- */
-unsigned long thread_saved_pc(struct task_struct *tsk)
-{
-	struct switch_stack *sw = (struct switch_stack *)tsk->thread.ksp;
-
-	/* Check whether the thread is blocked in resume() */
-	if (in_sched_functions(sw->retpc))
-		return ((unsigned long *)sw->a6)[1];
-	else
-		return sw->retpc;
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/ptrace.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,255 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/ptrace.c
- *
- *  Copyright (C) 1994 by Hamish Macdonald
- *  Taken from linux/kernel/ptrace.c and modified for M680x0.
- *  linux/kernel/ptrace.c is by Ross Biro 1/23/92, edited by 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/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/errno.h>
-#include <linux/ptrace.h>
-#include <linux/user.h>
-#include <linux/signal.h>
-#include <linux/tracehook.h>
-
-#include <asm/uaccess.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/processor.h>
-
-/*
- * does not yet catch signals sent when the child dies.
- * in exit.c or in signal.c.
- */
-
-/* determines which bits in the SR the user has access to. */
-/* 1 = access 0 = no access */
-#define SR_MASK 0x001f
-
-/* sets the trace bits. */
-#define TRACE_BITS 0x8000
-
-/* Find the stack offset for a register, relative to thread.esp0. */
-#define PT_REG(reg)	((long)&((struct pt_regs *)0)->reg)
-#define SW_REG(reg)	((long)&((struct switch_stack *)0)->reg \
-			 - sizeof(struct switch_stack))
-/* Mapping from PT_xxx to the stack offset at which the register is
-   saved.  Notice that usp has no stack-slot and needs to be treated
-   specially (see get_reg/put_reg below). */
-static int regoff[] = {
-	PT_REG(d1), PT_REG(d2), PT_REG(d3), PT_REG(d4),
-	PT_REG(d5), SW_REG(d6), SW_REG(d7), PT_REG(a0),
-	PT_REG(a1), PT_REG(a2), SW_REG(a3), SW_REG(a4),
-	SW_REG(a5), SW_REG(a6), PT_REG(d0), -1,
-	PT_REG(orig_d0), PT_REG(sr), PT_REG(pc),
-};
-
-/*
- * Get contents of register REGNO in task TASK.
- */
-static inline long get_reg(struct task_struct *task, int regno)
-{
-	unsigned long *addr;
-
-	if (regno == PT_USP)
-		addr = &task->thread.usp;
-	else if (regno < ARRAY_SIZE(regoff))
-		addr = (unsigned long *)(task->thread.esp0 + regoff[regno]);
-	else
-		return 0;
-	return *addr;
-}
-
-/*
- * Write contents of register REGNO in task TASK.
- */
-static inline int put_reg(struct task_struct *task, int regno,
-			  unsigned long data)
-{
-	unsigned long *addr;
-
-	if (regno == PT_USP)
-		addr = &task->thread.usp;
-	else if (regno < ARRAY_SIZE(regoff))
-		addr = (unsigned long *) (task->thread.esp0 + regoff[regno]);
-	else
-		return -1;
-	*addr = data;
-	return 0;
-}
-
-void user_enable_single_step(struct task_struct *task)
-{
-	unsigned long srflags;
-	srflags = get_reg(task, PT_SR) | (TRACE_BITS << 16);
-	put_reg(task, PT_SR, srflags);
-}
-
-void user_disable_single_step(struct task_struct *task)
-{
-	unsigned long srflags;
-	srflags = get_reg(task, PT_SR) & ~(TRACE_BITS << 16);
-	put_reg(task, PT_SR, srflags);
-}
-
-/*
- * Called by kernel/ptrace.c when detaching..
- *
- * Make sure the single step bit is not set.
- */
-void ptrace_disable(struct task_struct *child)
-{
-	/* make sure the single step bit is not set. */
-	user_disable_single_step(child);
-}
-
-long arch_ptrace(struct task_struct *child, long request,
-		 unsigned long addr, unsigned long data)
-{
-	int ret;
-	int regno = addr >> 2;
-	unsigned long __user *datap = (unsigned long __user *) data;
-
-	switch (request) {
-		/* read the word at location addr in the USER area. */
-		case PTRACE_PEEKUSR: {
-			unsigned long tmp;
-			
-			ret = -EIO;
-			if ((addr & 3) || addr > sizeof(struct user) - 3)
-				break;
-			
-			tmp = 0;  /* Default return condition */
-			ret = -EIO;
-			if (regno < 19) {
-				tmp = get_reg(child, regno);
-				if (regno == PT_SR)
-					tmp >>= 16;
-			} else if (regno >= 21 && regno < 49) {
-				tmp = child->thread.fp[regno - 21];
-			} else if (regno == 49) {
-				tmp = child->mm->start_code;
-			} else if (regno == 50) {
-				tmp = child->mm->start_data;
-			} else if (regno == 51) {
-				tmp = child->mm->end_code;
-			} else
-				break;
-			ret = put_user(tmp, datap);
-			break;
-		}
-
-		case PTRACE_POKEUSR: /* write the word at location addr in the USER area */
-			ret = -EIO;
-			if ((addr & 3) || addr > sizeof(struct user) - 3)
-				break;
-
-			if (regno == PT_SR) {
-				data &= SR_MASK;
-				data <<= 16;
-				data |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
-			}
-			if (regno < 19) {
-				if (put_reg(child, regno, data))
-					break;
-				ret = 0;
-				break;
-			}
-			if (regno >= 21 && regno < 48)
-			{
-				child->thread.fp[regno - 21] = data;
-				ret = 0;
-			}
-			break;
-
-		case PTRACE_GETREGS: { /* Get all gp regs from the child. */
-		  	int i;
-			unsigned long tmp;
-			for (i = 0; i < 19; i++) {
-			    tmp = get_reg(child, i);
-			    if (i == PT_SR)
-				tmp >>= 16;
-			    if (put_user(tmp, datap)) {
-				ret = -EFAULT;
-				break;
-			    }
-			    datap++;
-			}
-			ret = 0;
-			break;
-		}
-
-		case PTRACE_SETREGS: { /* Set all gp regs in the child. */
-			int i;
-			unsigned long tmp;
-			for (i = 0; i < 19; i++) {
-			    if (get_user(tmp, datap)) {
-				ret = -EFAULT;
-				break;
-			    }
-			    if (i == PT_SR) {
-				tmp &= SR_MASK;
-				tmp <<= 16;
-				tmp |= get_reg(child, PT_SR) & ~(SR_MASK << 16);
-			    }
-			    put_reg(child, i, tmp);
-			    datap++;
-			}
-			ret = 0;
-			break;
-		}
-
-#ifdef PTRACE_GETFPREGS
-		case PTRACE_GETFPREGS: { /* Get the child FPU state. */
-			ret = 0;
-			if (copy_to_user(datap, &child->thread.fp,
-					 sizeof(struct user_m68kfp_struct)))
-				ret = -EFAULT;
-			break;
-		}
-#endif
-
-#ifdef PTRACE_SETFPREGS
-		case PTRACE_SETFPREGS: { /* Set the child FPU state. */
-			ret = 0;
-			if (copy_from_user(&child->thread.fp, datap,
-					   sizeof(struct user_m68kfp_struct)))
-				ret = -EFAULT;
-			break;
-		}
-#endif
-
-	case PTRACE_GET_THREAD_AREA:
-		ret = put_user(task_thread_info(child)->tp_value, datap);
-		break;
-
-		default:
-			ret = ptrace_request(child, request, addr, data);
-			break;
-	}
-	return ret;
-}
-
-asmlinkage int syscall_trace_enter(void)
-{
-	int ret = 0;
-
-	if (test_thread_flag(TIF_SYSCALL_TRACE))
-		ret = tracehook_report_syscall_entry(task_pt_regs(current));
-	return ret;
-}
-
-asmlinkage void syscall_trace_leave(void)
-{
-	if (test_thread_flag(TIF_SYSCALL_TRACE))
-		tracehook_report_syscall_exit(task_pt_regs(current), 0);
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/setup.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/setup.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,317 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/setup.c
- *
- *  Copyright (C) 1999-2007  Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 1998,1999  D. Jeff Dionne <jeff@uClinux.org>
- *  Copyleft  ()) 2000       James D. Schettine {james@telos-systems.com}
- *  Copyright (C) 1998       Kenneth Albanowski <kjahds@kjahds.com>
- *  Copyright (C) 1995       Hamish Macdonald
- *  Copyright (C) 2000       Lineo Inc. (www.lineo.com)
- *  Copyright (C) 2001 	     Lineo, Inc. <www.lineo.com>
- *
- *  68VZ328 Fixes/support    Evan Stawnyczy <e@lineo.ca>
- */
-
-/*
- * This file handles the architecture-dependent parts of system setup
- */
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/delay.h>
-#include <linux/interrupt.h>
-#include <linux/fb.h>
-#include <linux/module.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/bootmem.h>
-#include <linux/seq_file.h>
-#include <linux/init.h>
-#include <linux/initrd.h>
-#include <linux/root_dev.h>
-
-#include <asm/setup.h>
-#include <asm/irq.h>
-#include <asm/machdep.h>
-#include <asm/pgtable.h>
-
-unsigned long memory_start;
-unsigned long memory_end;
-
-EXPORT_SYMBOL(memory_start);
-EXPORT_SYMBOL(memory_end);
-
-char __initdata command_line[COMMAND_LINE_SIZE];
-
-/* machine dependent timer functions */
-void (*mach_gettod)(int*, int*, int*, int*, int*, int*);
-int (*mach_set_clock_mmss)(unsigned long);
-
-/* machine dependent reboot functions */
-void (*mach_reset)(void);
-void (*mach_halt)(void);
-void (*mach_power_off)(void);
-
-#ifdef CONFIG_M68328
-#define CPU_NAME	"MC68328"
-#endif
-#ifdef CONFIG_M68EZ328
-#define CPU_NAME	"MC68EZ328"
-#endif
-#ifdef CONFIG_M68VZ328
-#define CPU_NAME	"MC68VZ328"
-#endif
-#ifdef CONFIG_M68360
-#define CPU_NAME	"MC68360"
-#endif
-#ifndef CPU_NAME
-#define	CPU_NAME	"UNKNOWN"
-#endif
-
-/*
- * Different cores have different instruction execution timings.
- * The old/traditional 68000 cores are basically all the same, at 16.
- * The ColdFire cores vary a little, their values are defined in their
- * headers. We default to the standard 68000 value here.
- */
-#ifndef CPU_INSTR_PER_JIFFY
-#define	CPU_INSTR_PER_JIFFY	16
-#endif
-
-extern int _stext, _etext, _sdata, _edata, _sbss, _ebss, _end;
-extern int _ramstart, _ramend;
-
-#if defined(CONFIG_UBOOT)
-/*
- * parse_uboot_commandline
- *
- * Copies u-boot commandline arguments and store them in the proper linux
- * variables.
- *
- * Assumes:
- *	_init_sp global contains the address in the stack pointer when the
- *	kernel starts (see head.S::_start)
- *
- *	U-Boot calling convention:
- *	(*kernel) (kbd, initrd_start, initrd_end, cmd_start, cmd_end);
- *
- *	_init_sp can be parsed as such
- *
- *	_init_sp+00 = u-boot cmd after jsr into kernel (skip)
- *	_init_sp+04 = &kernel board_info (residual data)
- *	_init_sp+08 = &initrd_start
- *	_init_sp+12 = &initrd_end
- *	_init_sp+16 = &cmd_start
- *	_init_sp+20 = &cmd_end
- *
- *	This also assumes that the memory locations pointed to are still
- *	unmodified. U-boot places them near the end of external SDRAM.
- *
- * Argument(s):
- *	commandp = the linux commandline arg container to fill.
- *	size     = the sizeof commandp.
- *
- * Returns:
- */
-void parse_uboot_commandline(char *commandp, int size)
-{
-	extern unsigned long _init_sp;
-	unsigned long *sp;
-	unsigned long uboot_kbd;
-	unsigned long uboot_initrd_start, uboot_initrd_end;
-	unsigned long uboot_cmd_start, uboot_cmd_end;
-
-
-	sp = (unsigned long *)_init_sp;
-	uboot_kbd = sp[1];
-	uboot_initrd_start = sp[2];
-	uboot_initrd_end = sp[3];
-	uboot_cmd_start = sp[4];
-	uboot_cmd_end = sp[5];
-
-	if (uboot_cmd_start && uboot_cmd_end)
-		strncpy(commandp, (const char *)uboot_cmd_start, size);
-#if defined(CONFIG_BLK_DEV_INITRD)
-	if (uboot_initrd_start && uboot_initrd_end &&
-		(uboot_initrd_end > uboot_initrd_start)) {
-		initrd_start = uboot_initrd_start;
-		initrd_end = uboot_initrd_end;
-		ROOT_DEV = Root_RAM0;
-		printk(KERN_INFO "initrd at 0x%lx:0x%lx\n",
-			initrd_start, initrd_end);
-	}
-#endif /* if defined(CONFIG_BLK_DEV_INITRD) */
-}
-#endif /* #if defined(CONFIG_UBOOT) */
-
-void __init setup_arch(char **cmdline_p)
-{
-	int bootmap_size;
-
-	memory_start = PAGE_ALIGN(_ramstart);
-	memory_end = _ramend;
-
-	init_mm.start_code = (unsigned long) &_stext;
-	init_mm.end_code = (unsigned long) &_etext;
-	init_mm.end_data = (unsigned long) &_edata;
-	init_mm.brk = (unsigned long) 0;
-
-	config_BSP(&command_line[0], sizeof(command_line));
-
-#if defined(CONFIG_BOOTPARAM)
-	strncpy(&command_line[0], CONFIG_BOOTPARAM_STRING, sizeof(command_line));
-	command_line[sizeof(command_line) - 1] = 0;
-#endif /* CONFIG_BOOTPARAM */
-
-#if defined(CONFIG_UBOOT)
-	/* CONFIG_UBOOT and CONFIG_BOOTPARAM defined, concatenate cmdline */
-	#if defined(CONFIG_BOOTPARAM)
-		/* Add the whitespace separator */
-		command_line[strlen(CONFIG_BOOTPARAM_STRING)] = ' ';
-		/* Parse uboot command line into the rest of the buffer */
-		parse_uboot_commandline(
-			&command_line[(strlen(CONFIG_BOOTPARAM_STRING)+1)],
-			(sizeof(command_line) -
-			(strlen(CONFIG_BOOTPARAM_STRING)+1)));
-	/* Only CONFIG_UBOOT defined, create cmdline */
-	#else
-		parse_uboot_commandline(&command_line[0], sizeof(command_line));
-	#endif /* CONFIG_BOOTPARAM */
-	command_line[sizeof(command_line) - 1] = 0;
-#endif /* CONFIG_UBOOT */
-
-	printk(KERN_INFO "\x0F\r\n\nuClinux/" CPU_NAME "\n");
-
-#ifdef CONFIG_UCDIMM
-	printk(KERN_INFO "uCdimm by Lineo, Inc. <www.lineo.com>\n");
-#endif
-#ifdef CONFIG_M68VZ328
-	printk(KERN_INFO "M68VZ328 support by Evan Stawnyczy <e@lineo.ca>\n");
-#endif
-#ifdef CONFIG_COLDFIRE
-	printk(KERN_INFO "COLDFIRE port done by Greg Ungerer, gerg@snapgear.com\n");
-#ifdef CONFIG_M5307
-	printk(KERN_INFO "Modified for M5307 by Dave Miller, dmiller@intellistor.com\n");
-#endif
-#ifdef CONFIG_ELITE
-	printk(KERN_INFO "Modified for M5206eLITE by Rob Scott, rscott@mtrob.fdns.net\n");
-#endif
-#endif
-	printk(KERN_INFO "Flat model support (C) 1998,1999 Kenneth Albanowski, D. Jeff Dionne\n");
-
-#if defined( CONFIG_PILOT ) && defined( CONFIG_M68328 )
-	printk(KERN_INFO "TRG SuperPilot FLASH card support <info@trgnet.com>\n");
-#endif
-#if defined( CONFIG_PILOT ) && defined( CONFIG_M68EZ328 )
-	printk(KERN_INFO "PalmV support by Lineo Inc. <jeff@uclinux.com>\n");
-#endif
-#if defined (CONFIG_M68360)
-	printk(KERN_INFO "QUICC port done by SED Systems <hamilton@sedsystems.ca>,\n");
-	printk(KERN_INFO "based on 2.0.38 port by Lineo Inc. <mleslie@lineo.com>.\n");
-#endif
-#ifdef CONFIG_DRAGEN2
-	printk(KERN_INFO "DragonEngine II board support by Georges Menie\n");
-#endif
-#ifdef CONFIG_M5235EVB
-	printk(KERN_INFO "Motorola M5235EVB support (C)2005 Syn-tech Systems, Inc. (Jate Sujjavanich)\n");
-#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];
-	memcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
-	boot_command_line[COMMAND_LINE_SIZE-1] = 0;
-
-#if defined(CONFIG_FRAMEBUFFER_CONSOLE) && defined(CONFIG_DUMMY_CONSOLE)
-	conswitchp = &dummy_con;
-#endif
-
-	/*
-	 * Give all the memory to the bootmap allocator, tell it to put the
-	 * boot mem_map at the start of memory.
-	 */
-	bootmap_size = init_bootmem_node(
-			NODE_DATA(0),
-			memory_start >> PAGE_SHIFT, /* map goes here */
-			PAGE_OFFSET >> PAGE_SHIFT,	/* 0 on coldfire */
-			memory_end >> PAGE_SHIFT);
-	/*
-	 * Free the usable memory, we have to make sure we do not free
-	 * the bootmem bitmap so we then reserve it after freeing it :-)
-	 */
-	free_bootmem(memory_start, memory_end - memory_start);
-	reserve_bootmem(memory_start, bootmap_size, BOOTMEM_DEFAULT);
-
-#if defined(CONFIG_UBOOT) && defined(CONFIG_BLK_DEV_INITRD)
-	if ((initrd_start > 0) && (initrd_start < initrd_end) &&
-			(initrd_end < memory_end))
-		reserve_bootmem(initrd_start, initrd_end - initrd_start,
-				 BOOTMEM_DEFAULT);
-#endif /* if defined(CONFIG_BLK_DEV_INITRD) */
-
-	/*
-	 * Get kmalloc into gear.
-	 */
-	paging_init();
-}
-
-/*
- *	Get CPU information for use by the procfs.
- */
-static int show_cpuinfo(struct seq_file *m, void *v)
-{
-	char *cpu, *mmu, *fpu;
-	u_long clockfreq;
-
-	cpu = CPU_NAME;
-	mmu = "none";
-	fpu = "none";
-	clockfreq = (loops_per_jiffy * HZ) * CPU_INSTR_PER_JIFFY;
-
-	seq_printf(m, "CPU:\t\t%s\n"
-		      "MMU:\t\t%s\n"
-		      "FPU:\t\t%s\n"
-		      "Clocking:\t%lu.%1luMHz\n"
-		      "BogoMips:\t%lu.%02lu\n"
-		      "Calibration:\t%lu loops\n",
-		      cpu, mmu, fpu,
-		      clockfreq / 1000000,
-		      (clockfreq / 100000) % 10,
-		      (loops_per_jiffy * HZ) / 500000,
-		      ((loops_per_jiffy * HZ) / 5000) % 100,
-		      (loops_per_jiffy * HZ));
-
-	return 0;
-}
-
-static void *c_start(struct seq_file *m, loff_t *pos)
-{
-	return *pos < NR_CPUS ? ((void *) 0x12345678) : NULL;
-}
-
-static void *c_next(struct seq_file *m, void *v, loff_t *pos)
-{
-	++*pos;
-	return c_start(m, pos);
-}
-
-static void c_stop(struct seq_file *m, void *v)
-{
-}
-
-const struct seq_operations cpuinfo_op = {
-	.start	= c_start,
-	.next	= c_next,
-	.stop	= c_stop,
-	.show	= show_cpuinfo,
-};
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/signal.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/signal.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,765 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/signal.c
- *
- *  Copyright (C) 1991, 1992  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.
- */
-
-/*
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- *
- * 1997-12-01  Modified for POSIX.1b signals by Andreas Schwab
- *
- * mathemu support by Roman Zippel
- *  (Note: fpstate in the signal context is completely ignored for the emulator
- *         and the internal floating point format is put on stack)
- */
-
-/*
- * ++roman (07/09/96): implemented signal stacks (specially for tosemu on
- * Atari :-) Current limitation: Only one sigstack can be active at one time.
- * If a second signal with SA_ONSTACK set arrives while working on a sigstack,
- * SA_ONSTACK is ignored. This behaviour avoids lots of trouble with nested
- * signal handlers!
- */
-
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/syscalls.h>
-#include <linux/errno.h>
-#include <linux/wait.h>
-#include <linux/ptrace.h>
-#include <linux/unistd.h>
-#include <linux/stddef.h>
-#include <linux/highuid.h>
-#include <linux/tty.h>
-#include <linux/personality.h>
-#include <linux/binfmts.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/pgtable.h>
-#include <asm/traps.h>
-#include <asm/ucontext.h>
-
-#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
-
-void ret_from_user_signal(void);
-void ret_from_user_rt_signal(void);
-
-/*
- * Atomically swap in the new signal mask, and wait for a signal.
- */
-asmlinkage int
-sys_sigsuspend(int unused0, int unused1, old_sigset_t mask)
-{
-	mask &= _BLOCKABLE;
-	spin_lock_irq(&current->sighand->siglock);
-	current->saved_sigmask = current->blocked;
-	siginitset(&current->blocked, mask);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	current->state = TASK_INTERRUPTIBLE;
-	schedule();
-	set_restore_sigmask();
-
-	return -ERESTARTNOHAND;
-}
-
-asmlinkage int
-sys_sigaction(int sig, const struct old_sigaction __user *act,
-	      struct old_sigaction __user *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) ||
-		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||
-		    __get_user(mask, &act->sa_mask))
-			return -EFAULT;
-		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) ||
-		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||
-		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))
-			return -EFAULT;
-	}
-
-	return ret;
-}
-
-asmlinkage int
-sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss)
-{
-	return do_sigaltstack(uss, uoss, rdusp());
-}
-
-
-/*
- * Do a signal return; undo the signal stack.
- *
- * Keep the return code on the stack quadword aligned!
- * That makes the cache flush below easier.
- */
-
-struct sigframe
-{
-	char __user *pretcode;
-	int sig;
-	int code;
-	struct sigcontext __user *psc;
-	char retcode[8];
-	unsigned long extramask[_NSIG_WORDS-1];
-	struct sigcontext sc;
-};
-
-struct rt_sigframe
-{
-	char __user *pretcode;
-	int sig;
-	struct siginfo __user *pinfo;
-	void __user *puc;
-	char retcode[8];
-	struct siginfo info;
-	struct ucontext uc;
-};
-
-#ifdef CONFIG_FPU
-
-static unsigned char fpu_version = 0;	/* version number of fpu, set by setup_frame */
-
-static inline int restore_fpu_state(struct sigcontext *sc)
-{
-	int err = 1;
-
-	if (FPU_IS_EMU) {
-	    /* restore registers */
-	    memcpy(current->thread.fpcntl, sc->sc_fpcntl, 12);
-	    memcpy(current->thread.fp, sc->sc_fpregs, 24);
-	    return 0;
-	}
-
-	if (sc->sc_fpstate[0]) {
-	    /* Verify the frame format.  */
-	    if (sc->sc_fpstate[0] != fpu_version)
-		goto out;
-
-	    __asm__ volatile (".chip 68k/68881\n\t"
-			      "fmovemx %0,%%fp0-%%fp1\n\t"
-			      "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
-			      ".chip 68k"
-			      : /* no outputs */
-			      : "m" (*sc->sc_fpregs), "m" (*sc->sc_fpcntl));
-	}
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "frestore %0\n\t"
-			  ".chip 68k" : : "m" (*sc->sc_fpstate));
-	err = 0;
-
-out:
-	return err;
-}
-
-#define FPCONTEXT_SIZE	216
-#define uc_fpstate	uc_filler[0]
-#define uc_formatvec	uc_filler[FPCONTEXT_SIZE/4]
-#define uc_extra	uc_filler[FPCONTEXT_SIZE/4+1]
-
-static inline int rt_restore_fpu_state(struct ucontext __user *uc)
-{
-	unsigned char fpstate[FPCONTEXT_SIZE];
-	int context_size = 0;
-	fpregset_t fpregs;
-	int err = 1;
-
-	if (FPU_IS_EMU) {
-		/* restore fpu control register */
-		if (__copy_from_user(current->thread.fpcntl,
-				uc->uc_mcontext.fpregs.f_fpcntl, 12))
-			goto out;
-		/* restore all other fpu register */
-		if (__copy_from_user(current->thread.fp,
-				uc->uc_mcontext.fpregs.f_fpregs, 96))
-			goto out;
-		return 0;
-	}
-
-	if (__get_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate))
-		goto out;
-	if (fpstate[0]) {
-		context_size = fpstate[1];
-
-		/* Verify the frame format.  */
-		if (fpstate[0] != fpu_version)
-			goto out;
-		if (__copy_from_user(&fpregs, &uc->uc_mcontext.fpregs,
-		     sizeof(fpregs)))
-			goto out;
-		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %0,%%fp0-%%fp7\n\t"
-				  "fmoveml %1,%%fpcr/%%fpsr/%%fpiar\n\t"
-				  ".chip 68k"
-				  : /* no outputs */
-				  : "m" (*fpregs.f_fpregs),
-				    "m" (*fpregs.f_fpcntl));
-	}
-	if (context_size &&
-	    __copy_from_user(fpstate + 4, (long __user *)&uc->uc_fpstate + 1,
-			     context_size))
-		goto out;
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "frestore %0\n\t"
-			  ".chip 68k" : : "m" (*fpstate));
-	err = 0;
-
-out:
-	return err;
-}
-
-#endif
-
-static inline int
-restore_sigcontext(struct pt_regs *regs, struct sigcontext __user *usc, void __user *fp,
-		   int *pd0)
-{
-	int formatvec;
-	struct sigcontext context;
-	int err = 0;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	/* get previous context */
-	if (copy_from_user(&context, usc, sizeof(context)))
-		goto badframe;
-	
-	/* restore passed registers */
-	regs->d1 = context.sc_d1;
-	regs->a0 = context.sc_a0;
-	regs->a1 = context.sc_a1;
-	((struct switch_stack *)regs - 1)->a5 = context.sc_a5;
-	regs->sr = (regs->sr & 0xff00) | (context.sc_sr & 0xff);
-	regs->pc = context.sc_pc;
-	regs->orig_d0 = -1;		/* disable syscall checks */
-	wrusp(context.sc_usp);
-	formatvec = context.sc_formatvec;
-	regs->format = formatvec >> 12;
-	regs->vector = formatvec & 0xfff;
-
-#ifdef CONFIG_FPU
-	err = restore_fpu_state(&context);
-#endif
-
-	*pd0 = context.sc_d0;
-	return err;
-
-badframe:
-	return 1;
-}
-
-static inline int
-rt_restore_ucontext(struct pt_regs *regs, struct switch_stack *sw,
-		    struct ucontext __user *uc, int *pd0)
-{
-	int temp;
-	greg_t __user *gregs = uc->uc_mcontext.gregs;
-	unsigned long usp;
-	int err;
-
-	/* Always make any pending restarted system calls return -EINTR */
-	current_thread_info()->restart_block.fn = do_no_restart_syscall;
-
-	err = __get_user(temp, &uc->uc_mcontext.version);
-	if (temp != MCONTEXT_VERSION)
-		goto badframe;
-	/* restore passed registers */
-	err |= __get_user(regs->d0, &gregs[0]);
-	err |= __get_user(regs->d1, &gregs[1]);
-	err |= __get_user(regs->d2, &gregs[2]);
-	err |= __get_user(regs->d3, &gregs[3]);
-	err |= __get_user(regs->d4, &gregs[4]);
-	err |= __get_user(regs->d5, &gregs[5]);
-	err |= __get_user(sw->d6, &gregs[6]);
-	err |= __get_user(sw->d7, &gregs[7]);
-	err |= __get_user(regs->a0, &gregs[8]);
-	err |= __get_user(regs->a1, &gregs[9]);
-	err |= __get_user(regs->a2, &gregs[10]);
-	err |= __get_user(sw->a3, &gregs[11]);
-	err |= __get_user(sw->a4, &gregs[12]);
-	err |= __get_user(sw->a5, &gregs[13]);
-	err |= __get_user(sw->a6, &gregs[14]);
-	err |= __get_user(usp, &gregs[15]);
-	wrusp(usp);
-	err |= __get_user(regs->pc, &gregs[16]);
-	err |= __get_user(temp, &gregs[17]);
-	regs->sr = (regs->sr & 0xff00) | (temp & 0xff);
-	regs->orig_d0 = -1;		/* disable syscall checks */
-	regs->format = temp >> 12;
-	regs->vector = temp & 0xfff;
-
-	if (do_sigaltstack(&uc->uc_stack, NULL, usp) == -EFAULT)
-		goto badframe;
-
-	*pd0 = regs->d0;
-	return err;
-
-badframe:
-	return 1;
-}
-
-asmlinkage int do_sigreturn(unsigned long __unused)
-{
-	struct switch_stack *sw = (struct switch_stack *) &__unused;
-	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
-	unsigned long usp = rdusp();
-	struct sigframe __user *frame = (struct sigframe __user *)(usp - 4);
-	sigset_t set;
-	int d0;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-	if (__get_user(set.sig[0], &frame->sc.sc_mask) ||
-	    (_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, frame + 1, &d0))
-		goto badframe;
-	return d0;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-asmlinkage int do_rt_sigreturn(unsigned long __unused)
-{
-	struct switch_stack *sw = (struct switch_stack *) &__unused;
-	struct pt_regs *regs = (struct pt_regs *) (sw + 1);
-	unsigned long usp = rdusp();
-	struct rt_sigframe __user *frame = (struct rt_sigframe __user *)(usp - 4);
-	sigset_t set;
-	int d0;
-
-	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
-		goto badframe;
-	if (__copy_from_user(&set, &frame->uc.uc_sigmask, sizeof(set)))
-		goto badframe;
-
-	sigdelsetmask(&set, ~_BLOCKABLE);
-	spin_lock_irq(&current->sighand->siglock);
-	current->blocked = set;
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-	
-	if (rt_restore_ucontext(regs, sw, &frame->uc, &d0))
-		goto badframe;
-	return d0;
-
-badframe:
-	force_sig(SIGSEGV, current);
-	return 0;
-}
-
-#ifdef CONFIG_FPU
-/*
- * Set up a signal frame.
- */
-
-static inline void save_fpu_state(struct sigcontext *sc, struct pt_regs *regs)
-{
-	if (FPU_IS_EMU) {
-		/* save registers */
-		memcpy(sc->sc_fpcntl, current->thread.fpcntl, 12);
-		memcpy(sc->sc_fpregs, current->thread.fp, 24);
-		return;
-	}
-
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "fsave %0\n\t"
-			  ".chip 68k"
-			  : : "m" (*sc->sc_fpstate) : "memory");
-
-	if (sc->sc_fpstate[0]) {
-		fpu_version = sc->sc_fpstate[0];
-		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %%fp0-%%fp1,%0\n\t"
-				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
-				  ".chip 68k"
-				  : "=m" (*sc->sc_fpregs),
-				    "=m" (*sc->sc_fpcntl)
-				  : /* no inputs */
-				  : "memory");
-	}
-}
-
-static inline int rt_save_fpu_state(struct ucontext __user *uc, struct pt_regs *regs)
-{
-	unsigned char fpstate[FPCONTEXT_SIZE];
-	int context_size = 0;
-	int err = 0;
-
-	if (FPU_IS_EMU) {
-		/* save fpu control register */
-		err |= copy_to_user(uc->uc_mcontext.fpregs.f_pcntl,
-				current->thread.fpcntl, 12);
-		/* save all other fpu register */
-		err |= copy_to_user(uc->uc_mcontext.fpregs.f_fpregs,
-				current->thread.fp, 96);
-		return err;
-	}
-
-	__asm__ volatile (".chip 68k/68881\n\t"
-			  "fsave %0\n\t"
-			  ".chip 68k"
-			  : : "m" (*fpstate) : "memory");
-
-	err |= __put_user(*(long *)fpstate, (long __user *)&uc->uc_fpstate);
-	if (fpstate[0]) {
-		fpregset_t fpregs;
-		context_size = fpstate[1];
-		fpu_version = fpstate[0];
-		__asm__ volatile (".chip 68k/68881\n\t"
-				  "fmovemx %%fp0-%%fp7,%0\n\t"
-				  "fmoveml %%fpcr/%%fpsr/%%fpiar,%1\n\t"
-				  ".chip 68k"
-				  : "=m" (*fpregs.f_fpregs),
-				    "=m" (*fpregs.f_fpcntl)
-				  : /* no inputs */
-				  : "memory");
-		err |= copy_to_user(&uc->uc_mcontext.fpregs, &fpregs,
-				    sizeof(fpregs));
-	}
-	if (context_size)
-		err |= copy_to_user((long __user *)&uc->uc_fpstate + 1, fpstate + 4,
-				    context_size);
-	return err;
-}
-
-#endif
-
-static void setup_sigcontext(struct sigcontext *sc, struct pt_regs *regs,
-			     unsigned long mask)
-{
-	sc->sc_mask = mask;
-	sc->sc_usp = rdusp();
-	sc->sc_d0 = regs->d0;
-	sc->sc_d1 = regs->d1;
-	sc->sc_a0 = regs->a0;
-	sc->sc_a1 = regs->a1;
-	sc->sc_a5 = ((struct switch_stack *)regs - 1)->a5;
-	sc->sc_sr = regs->sr;
-	sc->sc_pc = regs->pc;
-	sc->sc_formatvec = regs->format << 12 | regs->vector;
-#ifdef CONFIG_FPU
-	save_fpu_state(sc, regs);
-#endif
-}
-
-static inline int rt_setup_ucontext(struct ucontext __user *uc, struct pt_regs *regs)
-{
-	struct switch_stack *sw = (struct switch_stack *)regs - 1;
-	greg_t __user *gregs = uc->uc_mcontext.gregs;
-	int err = 0;
-
-	err |= __put_user(MCONTEXT_VERSION, &uc->uc_mcontext.version);
-	err |= __put_user(regs->d0, &gregs[0]);
-	err |= __put_user(regs->d1, &gregs[1]);
-	err |= __put_user(regs->d2, &gregs[2]);
-	err |= __put_user(regs->d3, &gregs[3]);
-	err |= __put_user(regs->d4, &gregs[4]);
-	err |= __put_user(regs->d5, &gregs[5]);
-	err |= __put_user(sw->d6, &gregs[6]);
-	err |= __put_user(sw->d7, &gregs[7]);
-	err |= __put_user(regs->a0, &gregs[8]);
-	err |= __put_user(regs->a1, &gregs[9]);
-	err |= __put_user(regs->a2, &gregs[10]);
-	err |= __put_user(sw->a3, &gregs[11]);
-	err |= __put_user(sw->a4, &gregs[12]);
-	err |= __put_user(sw->a5, &gregs[13]);
-	err |= __put_user(sw->a6, &gregs[14]);
-	err |= __put_user(rdusp(), &gregs[15]);
-	err |= __put_user(regs->pc, &gregs[16]);
-	err |= __put_user(regs->sr, &gregs[17]);
-#ifdef CONFIG_FPU
-	err |= rt_save_fpu_state(uc, regs);
-#endif
-	return err;
-}
-
-static inline void __user *
-get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size)
-{
-	unsigned long usp;
-
-	/* Default to using normal stack.  */
-	usp = rdusp();
-
-	/* This is the X/Open sanctioned signal stack switching.  */
-	if (ka->sa.sa_flags & SA_ONSTACK) {
-		if (!sas_ss_flags(usp))
-			usp = current->sas_ss_sp + current->sas_ss_size;
-	}
-	return (void __user *)((usp - frame_size) & -8UL);
-}
-
-static int setup_frame (int sig, struct k_sigaction *ka,
-			 sigset_t *set, struct pt_regs *regs)
-{
-	struct sigframe __user *frame;
-	struct sigcontext context;
-	int err = 0;
-
-	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	err |= __put_user((current_thread_info()->exec_domain
-			   && current_thread_info()->exec_domain->signal_invmap
-			   && sig < 32
-			   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
-
-	err |= __put_user(regs->vector, &frame->code);
-	err |= __put_user(&frame->sc, &frame->psc);
-
-	if (_NSIG_WORDS > 1)
-		err |= copy_to_user(frame->extramask, &set->sig[1],
-				    sizeof(frame->extramask));
-
-	setup_sigcontext(&context, regs, set->sig[0]);
-	err |= copy_to_user (&frame->sc, &context, sizeof(context));
-
-	/* Set up to return from userspace.  */
-	err |= __put_user((void *) ret_from_user_signal, &frame->pretcode);
-
-	if (err)
-		goto give_sigsegv;
-
-	/* Set up registers for signal handler */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
-	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
-	regs->format = 0x4; /*set format byte to make stack appear modulo 4 
-						which it will be when doing the rte */
-
-adjust_stack:
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
-#if defined(DEBUG)
-		printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
-#endif
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
-		tregs->vector = 0;
-		tregs->format = 0;
-		tregs->pc = regs->pc;
-		tregs->sr = regs->sr;
-	}
-	return err;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	goto adjust_stack;
-}
-
-static int setup_rt_frame (int sig, struct k_sigaction *ka, siginfo_t *info,
-			    sigset_t *set, struct pt_regs *regs)
-{
-	struct rt_sigframe __user *frame;
-	int err = 0;
-
-	frame = get_sigframe(ka, regs, sizeof(*frame));
-
-	err |= __put_user((current_thread_info()->exec_domain
-			   && current_thread_info()->exec_domain->signal_invmap
-			   && sig < 32
-			   ? current_thread_info()->exec_domain->signal_invmap[sig]
-			   : sig),
-			  &frame->sig);
-	err |= __put_user(&frame->info, &frame->pinfo);
-	err |= __put_user(&frame->uc, &frame->puc);
-	err |= copy_siginfo_to_user(&frame->info, info);
-
-	/* Create the ucontext.  */
-	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(NULL, &frame->uc.uc_link);
-	err |= __put_user((void __user *)current->sas_ss_sp,
-			  &frame->uc.uc_stack.ss_sp);
-	err |= __put_user(sas_ss_flags(rdusp()),
-			  &frame->uc.uc_stack.ss_flags);
-	err |= __put_user(current->sas_ss_size, &frame->uc.uc_stack.ss_size);
-	err |= rt_setup_ucontext(&frame->uc, regs);
-	err |= copy_to_user (&frame->uc.uc_sigmask, set, sizeof(*set));
-
-	/* Set up to return from userspace.  */
-	err |= __put_user((void *) ret_from_user_rt_signal, &frame->pretcode);
-
-	if (err)
-		goto give_sigsegv;
-
-	/* Set up registers for signal handler */
-	wrusp ((unsigned long) frame);
-	regs->pc = (unsigned long) ka->sa.sa_handler;
-	((struct switch_stack *)regs - 1)->a5 = current->mm->start_data;
-	regs->format = 0x4; /*set format byte to make stack appear modulo 4 
-						which it will be when doing the rte */
-
-adjust_stack:
-	/* Prepare to skip over the extra stuff in the exception frame.  */
-	if (regs->stkadj) {
-		struct pt_regs *tregs =
-			(struct pt_regs *)((ulong)regs + regs->stkadj);
-#if defined(DEBUG)
-		printk(KERN_DEBUG "Performing stackadjust=%04x\n", regs->stkadj);
-#endif
-		/* This must be copied with decreasing addresses to
-                   handle overlaps.  */
-		tregs->vector = 0;
-		tregs->format = 0;
-		tregs->pc = regs->pc;
-		tregs->sr = regs->sr;
-	}
-	return err;
-
-give_sigsegv:
-	force_sigsegv(sig, current);
-	goto adjust_stack;
-}
-
-static inline void
-handle_restart(struct pt_regs *regs, struct k_sigaction *ka, int has_handler)
-{
-	switch (regs->d0) {
-	case -ERESTARTNOHAND:
-		if (!has_handler)
-			goto do_restart;
-		regs->d0 = -EINTR;
-		break;
-
-	case -ERESTART_RESTARTBLOCK:
-		if (!has_handler) {
-			regs->d0 = __NR_restart_syscall;
-			regs->pc -= 2;
-			break;
-		}
-		regs->d0 = -EINTR;
-		break;
-
-	case -ERESTARTSYS:
-		if (has_handler && !(ka->sa.sa_flags & SA_RESTART)) {
-			regs->d0 = -EINTR;
-			break;
-		}
-	/* fallthrough */
-	case -ERESTARTNOINTR:
-	do_restart:
-		regs->d0 = regs->orig_d0;
-		regs->pc -= 2;
-		break;
-	}
-}
-
-/*
- * OK, we're invoking a handler
- */
-static void
-handle_signal(int sig, struct k_sigaction *ka, siginfo_t *info,
-	      sigset_t *oldset, struct pt_regs *regs)
-{
-	int err;
-	/* are we from a system call? */
-	if (regs->orig_d0 >= 0)
-		/* If so, check system call restarting.. */
-		handle_restart(regs, ka, 1);
-
-	/* set up the stack frame */
-	if (ka->sa.sa_flags & SA_SIGINFO)
-		err = setup_rt_frame(sig, ka, info, oldset, regs);
-	else
-		err = setup_frame(sig, ka, oldset, regs);
-
-	if (err)
-		return;
-
-	spin_lock_irq(&current->sighand->siglock);
-	sigorsets(&current->blocked,&current->blocked,&ka->sa.sa_mask);
-	if (!(ka->sa.sa_flags & SA_NODEFER))
-		sigaddset(&current->blocked,sig);
-	recalc_sigpending();
-	spin_unlock_irq(&current->sighand->siglock);
-
-	clear_thread_flag(TIF_RESTORE_SIGMASK);
-}
-
-/*
- * Note that 'init' is a special process: it doesn't get signals it doesn't
- * want to handle. Thus you cannot kill init even with a SIGKILL even by
- * mistake.
- */
-asmlinkage void do_signal(struct pt_regs *regs)
-{
-	struct k_sigaction ka;
-	siginfo_t info;
-	int signr;
-	sigset_t *oldset;
-
-	/*
-	 * We want the common case to go fast, which
-	 * is why we may in certain cases get here from
-	 * kernel mode. Just return without doing anything
-	 * if so.
-	 */
-	if (!user_mode(regs))
-		return;
-
-	if (test_thread_flag(TIF_RESTORE_SIGMASK))
-		oldset = &current->saved_sigmask;
-	else
-		oldset = &current->blocked;
-
-	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
-	if (signr > 0) {
-		/* Whee!  Actually deliver the signal.  */
-		handle_signal(signr, &ka, &info, oldset, regs);
-		return;
-	}
-
-	/* Did we come from a system call? */
-	if (regs->orig_d0 >= 0) {
-		/* Restart the system call - no handlers present */
-		handle_restart(regs, NULL, 0);
-	}
-
-	/* If there's no signal to deliver, we just restore the saved mask.  */
-	if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
-		clear_thread_flag(TIF_RESTORE_SIGMASK);
-		sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/syscalltable.S linux-libre-2.6.39-gnu/arch/m68knommu/kernel/syscalltable.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/syscalltable.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/syscalltable.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,365 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/syscalltable.S
- *
- *  Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
- *
- *  Based on older entry.S files, the following copyrights apply:
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo Inc. (www.lineo.com) 
- *  Copyright (C) 1991, 1992  Linus Torvalds
- */
-
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-
-.text
-ALIGN
-ENTRY(sys_call_table)
-	.long sys_restart_syscall	/* 0  -  old "setup()" system call */
-	.long sys_exit
-	.long sys_fork
-	.long sys_read
-	.long sys_write
-	.long sys_open		/* 5 */
-	.long sys_close
-	.long sys_waitpid
-	.long sys_creat
-	.long sys_link
-	.long sys_unlink	/* 10 */
-	.long sys_execve
-	.long sys_chdir
-	.long sys_time
-	.long sys_mknod
-	.long sys_chmod		/* 15 */
-	.long sys_chown16
-	.long sys_ni_syscall	/* old break syscall holder */
-	.long sys_stat
-	.long sys_lseek
-	.long sys_getpid	/* 20 */
-	.long sys_mount
-	.long sys_oldumount
-	.long sys_setuid16
-	.long sys_getuid16
-	.long sys_stime		/* 25 */
-	.long sys_ptrace
-	.long sys_alarm
-	.long sys_fstat
-	.long sys_pause
-	.long sys_utime		/* 30 */
-	.long sys_ni_syscall	/* old stty syscall holder */
-	.long sys_ni_syscall	/* old gtty syscall holder */
-	.long sys_access
-	.long sys_nice
-	.long sys_ni_syscall	/* 35 */ /* old ftime syscall holder */
-	.long sys_sync
-	.long sys_kill
-	.long sys_rename
-	.long sys_mkdir
-	.long sys_rmdir		/* 40 */
-	.long sys_dup
-	.long sys_pipe
-	.long sys_times
-	.long sys_ni_syscall	/* old prof syscall holder */
-	.long sys_brk		/* 45 */
-	.long sys_setgid16
-	.long sys_getgid16
-	.long sys_signal
-	.long sys_geteuid16
-	.long sys_getegid16	/* 50 */
-	.long sys_acct
-	.long sys_umount	/* recycled never used phys() */
-	.long sys_ni_syscall	/* old lock syscall holder */
-	.long sys_ioctl
-	.long sys_fcntl		/* 55 */
-	.long sys_ni_syscall	/* old mpx syscall holder */
-	.long sys_setpgid
-	.long sys_ni_syscall	/* old ulimit syscall holder */
-	.long sys_ni_syscall
-	.long sys_umask		/* 60 */
-	.long sys_chroot
-	.long sys_ustat
-	.long sys_dup2
-	.long sys_getppid
-	.long sys_getpgrp	/* 65 */
-	.long sys_setsid
-	.long sys_sigaction
-	.long sys_sgetmask
-	.long sys_ssetmask
-	.long sys_setreuid16	/* 70 */
-	.long sys_setregid16
-	.long sys_sigsuspend
-	.long sys_sigpending
-	.long sys_sethostname
-	.long sys_setrlimit	/* 75 */
-	.long sys_old_getrlimit
-	.long sys_getrusage
-	.long sys_gettimeofday
-	.long sys_settimeofday
-	.long sys_getgroups16	/* 80 */
-	.long sys_setgroups16
-	.long sys_old_select
-	.long sys_symlink
-	.long sys_lstat
-	.long sys_readlink	/* 85 */
-	.long sys_uselib
-	.long sys_ni_syscall	/* sys_swapon */
-	.long sys_reboot
-	.long sys_old_readdir
-	.long sys_old_mmap	/* 90 */
-	.long sys_munmap
-	.long sys_truncate
-	.long sys_ftruncate
-	.long sys_fchmod
-	.long sys_fchown16	/* 95 */
-	.long sys_getpriority
-	.long sys_setpriority
-	.long sys_ni_syscall	/* old profil syscall holder */
-	.long sys_statfs
-	.long sys_fstatfs	/* 100 */
-	.long sys_ni_syscall	/* ioperm for i386 */
-	.long sys_socketcall
-	.long sys_syslog
-	.long sys_setitimer
-	.long sys_getitimer	/* 105 */
-	.long sys_newstat
-	.long sys_newlstat
-	.long sys_newfstat
-	.long sys_ni_syscall
-	.long sys_ni_syscall	/* iopl for i386 */ /* 110 */
-	.long sys_vhangup
-	.long sys_ni_syscall	/* obsolete idle() syscall */
-	.long sys_ni_syscall	/* vm86old for i386 */
-	.long sys_wait4
-	.long sys_ni_syscall	/* 115 */ /* sys_swapoff */
-	.long sys_sysinfo
-	.long sys_ipc
-	.long sys_fsync
-	.long sys_sigreturn
-	.long sys_clone		/* 120 */
-	.long sys_setdomainname
-	.long sys_newuname
-	.long sys_cacheflush	/* modify_ldt for i386 */
-	.long sys_adjtimex
-	.long sys_ni_syscall	/* 125 */ /* sys_mprotect */
-	.long sys_sigprocmask
-	.long sys_ni_syscall	/* old "creat_module" */
-	.long sys_init_module
-	.long sys_delete_module
-	.long sys_ni_syscall	/* 130: old "get_kernel_syms" */
-	.long sys_quotactl
-	.long sys_getpgid
-	.long sys_fchdir
-	.long sys_bdflush
-	.long sys_sysfs		/* 135 */
-	.long sys_personality
-	.long sys_ni_syscall	/* for afs_syscall */
-	.long sys_setfsuid16
-	.long sys_setfsgid16
-	.long sys_llseek	/* 140 */
-	.long sys_getdents
-	.long sys_select
-	.long sys_flock
-	.long sys_ni_syscall	/* sys_msync */
-	.long sys_readv		/* 145 */
-	.long sys_writev
-	.long sys_getsid
-	.long sys_fdatasync
-	.long sys_sysctl
-	.long sys_ni_syscall	/* 150 */ /* sys_mlock */
-	.long sys_ni_syscall	/* sys_munlock */
-	.long sys_ni_syscall	/* sys_mlockall */
-	.long sys_ni_syscall	/* sys_munlockall */
-	.long sys_sched_setparam
-	.long sys_sched_getparam /* 155 */
-	.long sys_sched_setscheduler
-	.long sys_sched_getscheduler
-	.long sys_sched_yield
-	.long sys_sched_get_priority_max
-	.long sys_sched_get_priority_min  /* 160 */
-	.long sys_sched_rr_get_interval
-	.long sys_nanosleep
-	.long sys_ni_syscall	/* sys_mremap */
-	.long sys_setresuid16
-	.long sys_getresuid16	/* 165 */
-	.long sys_getpagesize	/* sys_getpagesize */
-	.long sys_ni_syscall	/* old "query_module" */
-	.long sys_poll
-	.long sys_ni_syscall	/* sys_nfsservctl */
-	.long sys_setresgid16	/* 170 */
-	.long sys_getresgid16
-	.long sys_prctl
-	.long sys_rt_sigreturn
-	.long sys_rt_sigaction
-	.long sys_rt_sigprocmask /* 175 */
-	.long sys_rt_sigpending
-	.long sys_rt_sigtimedwait
-	.long sys_rt_sigqueueinfo
-	.long sys_rt_sigsuspend
-	.long sys_pread64	/* 180 */
-	.long sys_pwrite64
-	.long sys_lchown16
-	.long sys_getcwd
-	.long sys_capget
-	.long sys_capset	/* 185 */
-	.long sys_sigaltstack
-	.long sys_sendfile
-	.long sys_ni_syscall	/* streams1 */
-	.long sys_ni_syscall	/* streams2 */
-	.long sys_vfork		/* 190 */
-	.long sys_getrlimit
-	.long sys_mmap_pgoff
-	.long sys_truncate64
-	.long sys_ftruncate64
-	.long sys_stat64	/* 195 */
-	.long sys_lstat64
-	.long sys_fstat64
-	.long sys_chown
-	.long sys_getuid
-	.long sys_getgid	/* 200 */
-	.long sys_geteuid
-	.long sys_getegid
-	.long sys_setreuid
-	.long sys_setregid
-	.long sys_getgroups	/* 205 */
-	.long sys_setgroups
-	.long sys_fchown
-	.long sys_setresuid
-	.long sys_getresuid
-	.long sys_setresgid	/* 210 */
-	.long sys_getresgid
-	.long sys_lchown
-	.long sys_setuid
-	.long sys_setgid
-	.long sys_setfsuid	/* 215 */
-	.long sys_setfsgid
-	.long sys_pivot_root
-	.long sys_ni_syscall
-	.long sys_ni_syscall
-	.long sys_getdents64	/* 220 */
-	.long sys_gettid
-	.long sys_tkill
-	.long sys_setxattr
-	.long sys_lsetxattr
-	.long sys_fsetxattr	/* 225 */
-	.long sys_getxattr
-	.long sys_lgetxattr
-	.long sys_fgetxattr
-	.long sys_listxattr
-	.long sys_llistxattr	/* 230 */
-	.long sys_flistxattr
-	.long sys_removexattr
-	.long sys_lremovexattr
-	.long sys_fremovexattr
-	.long sys_futex		/* 235 */
-	.long sys_sendfile64
-	.long sys_ni_syscall	/* sys_mincore */
-	.long sys_ni_syscall	/* sys_madvise */
-	.long sys_fcntl64
-	.long sys_readahead	/* 240 */
-	.long sys_io_setup
-	.long sys_io_destroy
-	.long sys_io_getevents
-	.long sys_io_submit
-	.long sys_io_cancel	/* 245 */
-	.long sys_fadvise64
-	.long sys_exit_group
-	.long sys_lookup_dcookie
-	.long sys_epoll_create
-	.long sys_epoll_ctl	/* 250 */
-	.long sys_epoll_wait
-	.long sys_ni_syscall	/* sys_remap_file_pages */
-	.long sys_set_tid_address
-	.long sys_timer_create
-	.long sys_timer_settime	/* 255 */
-	.long sys_timer_gettime
-	.long sys_timer_getoverrun
-	.long sys_timer_delete
-	.long sys_clock_settime
-	.long sys_clock_gettime	/* 260 */
-	.long sys_clock_getres
-	.long sys_clock_nanosleep
-	.long sys_statfs64
-	.long sys_fstatfs64
-	.long sys_tgkill	/* 265 */
-	.long sys_utimes
-	.long sys_fadvise64_64
-	.long sys_mbind	
-	.long sys_get_mempolicy
-	.long sys_set_mempolicy	/* 270 */
-	.long sys_mq_open
-	.long sys_mq_unlink
-	.long sys_mq_timedsend
-	.long sys_mq_timedreceive
-	.long sys_mq_notify	/* 275 */
-	.long sys_mq_getsetattr
-	.long sys_waitid
-	.long sys_ni_syscall	/* for sys_vserver */
-	.long sys_add_key
-	.long sys_request_key	/* 280 */
-	.long sys_keyctl
-	.long sys_ioprio_set
-	.long sys_ioprio_get
-	.long sys_inotify_init
-	.long sys_inotify_add_watch	/* 285 */
-	.long sys_inotify_rm_watch
-	.long sys_migrate_pages
-	.long sys_openat
-	.long sys_mkdirat
-	.long sys_mknodat		/* 290 */
-	.long sys_fchownat
-	.long sys_futimesat
-	.long sys_fstatat64
-	.long sys_unlinkat
-	.long sys_renameat		/* 295 */
-	.long sys_linkat
-	.long sys_symlinkat
-	.long sys_readlinkat
-	.long sys_fchmodat
-	.long sys_faccessat		/* 300 */
-	.long sys_ni_syscall		/* Reserved for pselect6 */
-	.long sys_ni_syscall		/* Reserved for ppoll */
-	.long sys_unshare
-	.long sys_set_robust_list
-	.long sys_get_robust_list	/* 305 */
-	.long sys_splice
-	.long sys_sync_file_range
-	.long sys_tee
-	.long sys_vmsplice
-	.long sys_move_pages		/* 310 */
-	.long sys_sched_setaffinity
-	.long sys_sched_getaffinity
-	.long sys_kexec_load
-	.long sys_getcpu
-	.long sys_epoll_pwait		/* 315 */
-	.long sys_utimensat
-	.long sys_signalfd
-	.long sys_timerfd_create
-	.long sys_eventfd
-	.long sys_fallocate		/* 320 */
-	.long sys_timerfd_settime
-	.long sys_timerfd_gettime
-	.long sys_signalfd4
-	.long sys_eventfd2
-	.long sys_epoll_create1		/* 325 */
-	.long sys_dup3
-	.long sys_pipe2
-	.long sys_inotify_init1
-	.long sys_preadv
-	.long sys_pwritev		/* 330 */
-	.long sys_rt_tgsigqueueinfo
-	.long sys_perf_event_open
-	.long sys_get_thread_area
-	.long sys_set_thread_area
-	.long sys_atomic_cmpxchg_32	/* 335 */
-	.long sys_atomic_barrier
-	.long sys_fanotify_init
-	.long sys_fanotify_mark
-	.long sys_prlimit64
-
-	.rept NR_syscalls-(.-sys_call_table)/4
-		.long sys_ni_syscall
-	.endr
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/sys_m68k.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/sys_m68k.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/sys_m68k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/sys_m68k.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,94 +0,0 @@
-/*
- * linux/arch/m68knommu/kernel/sys_m68k.c
- *
- * This file contains various random system calls that
- * have a non-standard calling sequence on the Linux/m68k
- * platform.
- */
-
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/smp.h>
-#include <linux/sem.h>
-#include <linux/msg.h>
-#include <linux/shm.h>
-#include <linux/stat.h>
-#include <linux/syscalls.h>
-#include <linux/mman.h>
-#include <linux/file.h>
-#include <linux/ipc.h>
-#include <linux/fs.h>
-
-#include <asm/setup.h>
-#include <asm/uaccess.h>
-#include <asm/cachectl.h>
-#include <asm/traps.h>
-#include <asm/cacheflush.h>
-#include <asm/unistd.h>
-
-/* sys_cacheflush -- flush (part of) the processor cache.  */
-asmlinkage int
-sys_cacheflush (unsigned long addr, int scope, int cache, unsigned long len)
-{
-	flush_cache_all();
-	return(0);
-}
-
-asmlinkage int sys_getpagesize(void)
-{
-	return PAGE_SIZE;
-}
-
-/*
- * Do a system call from kernel instead of calling sys_execve so we
- * end up with proper pt_regs.
- */
-int kernel_execve(const char *filename,
-		  const char *const argv[],
-		  const char *const envp[])
-{
-	register long __res asm ("%d0") = __NR_execve;
-	register long __a asm ("%d1") = (long)(filename);
-	register long __b asm ("%d2") = (long)(argv);
-	register long __c asm ("%d3") = (long)(envp);
-	asm volatile ("trap  #0" : "+d" (__res)
-			: "d" (__a), "d" (__b), "d" (__c));
-	return __res;
-}
-
-asmlinkage unsigned long sys_get_thread_area(void)
-{
-	return current_thread_info()->tp_value;
-}
-
-asmlinkage int sys_set_thread_area(unsigned long tp)
-{
-	current_thread_info()->tp_value = tp;
-	return 0;
-}
-
-/* This syscall gets its arguments in A0 (mem), D2 (oldval) and
-   D1 (newval).  */
-asmlinkage int
-sys_atomic_cmpxchg_32(unsigned long newval, int oldval, int d3, int d4, int d5,
-		      unsigned long __user * mem)
-{
-	struct mm_struct *mm = current->mm;
-	unsigned long mem_value;
-
-	down_read(&mm->mmap_sem);
-
-	mem_value = *mem;
-	if (mem_value == oldval)
-		*mem = newval;
-
-	up_read(&mm->mmap_sem);
-	return mem_value;
-}
-
-asmlinkage int sys_atomic_barrier(void)
-{
-	/* no code needed for uniprocs */
-	return 0;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/time.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/time.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/time.c
- *
- *  Copyright (C) 1991, 1992, 1995  Linus Torvalds
- *
- * This file contains the m68k-specific time handling details.
- * Most of the stuff is located in the machine specific files.
- *
- * 1997-09-10	Updated NTP code according to technical memorandum Jan '96
- *		"A Kernel Model for Precision Timekeeping" by Dave Mills
- */
-
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/profile.h>
-#include <linux/time.h>
-#include <linux/timex.h>
-
-#include <asm/machdep.h>
-#include <asm/irq_regs.h>
-
-#define	TICK_SIZE (tick_nsec / 1000)
-
-static inline int set_rtc_mmss(unsigned long nowtime)
-{
-	if (mach_set_clock_mmss)
-		return mach_set_clock_mmss (nowtime);
-	return -1;
-}
-
-#ifndef CONFIG_GENERIC_CLOCKEVENTS
-/*
- * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
- */
-irqreturn_t arch_timer_interrupt(int irq, void *dummy)
-{
-
-	if (current->pid)
-		profile_tick(CPU_PROFILING);
-
-	write_seqlock(&xtime_lock);
-
-	do_timer(1);
-
-	write_sequnlock(&xtime_lock);
-
-	update_process_times(user_mode(get_irq_regs()));
-
-	return(IRQ_HANDLED);
-}
-#endif
-
-static unsigned long read_rtc_mmss(void)
-{
-	unsigned int year, mon, day, hour, min, sec;
-
-	if (mach_gettod) {
-		mach_gettod(&year, &mon, &day, &hour, &min, &sec);
-		if ((year += 1900) < 1970)
-			year += 100;
-	} else {
-		year = 1970;
-		mon = day = 1;
-		hour = min = sec = 0;
-	}
-
-
-	return  mktime(year, mon, day, hour, min, sec);
-}
-
-void read_persistent_clock(struct timespec *ts)
-{
-	ts->tv_sec = read_rtc_mmss();
-	ts->tv_nsec = 0;
-}
-
-int update_persistent_clock(struct timespec now)
-{
-	return set_rtc_mmss(now.tv_sec);
-}
-
-void time_init(void)
-{
-	hw_timer_init();
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/traps.c linux-libre-2.6.39-gnu/arch/m68knommu/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/traps.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,365 +0,0 @@
-/*
- *  linux/arch/m68knommu/kernel/traps.c
- *
- *  Copyright (C) 1993, 1994 by Hamish Macdonald
- *
- *  68040 fixes by Michael Rausch
- *  68040 fixes by Martin Apel
- *  68060 fixes by Roman Hodek
- *  68060 fixes by Jesper Skov
- *
- * 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.
- */
-
-/*
- * Sets up all exception vectors
- */
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/user.h>
-#include <linux/string.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <linux/ptrace.h>
-#include <linux/kallsyms.h>
-
-#include <asm/setup.h>
-#include <asm/fpu.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/traps.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/siginfo.h>
-
-static char const * const vec_names[] = {
-	"RESET SP", "RESET PC", "BUS ERROR", "ADDRESS ERROR",
-	"ILLEGAL INSTRUCTION", "ZERO DIVIDE", "CHK", "TRAPcc",
-	"PRIVILEGE VIOLATION", "TRACE", "LINE 1010", "LINE 1111",
-	"UNASSIGNED RESERVED 12", "COPROCESSOR PROTOCOL VIOLATION",
-	"FORMAT ERROR", "UNINITIALIZED INTERRUPT",
-	"UNASSIGNED RESERVED 16", "UNASSIGNED RESERVED 17",
-	"UNASSIGNED RESERVED 18", "UNASSIGNED RESERVED 19",
-	"UNASSIGNED RESERVED 20", "UNASSIGNED RESERVED 21",
-	"UNASSIGNED RESERVED 22", "UNASSIGNED RESERVED 23",
-	"SPURIOUS INTERRUPT", "LEVEL 1 INT", "LEVEL 2 INT", "LEVEL 3 INT",
-	"LEVEL 4 INT", "LEVEL 5 INT", "LEVEL 6 INT", "LEVEL 7 INT",
-	"SYSCALL", "TRAP #1", "TRAP #2", "TRAP #3",
-	"TRAP #4", "TRAP #5", "TRAP #6", "TRAP #7",
-	"TRAP #8", "TRAP #9", "TRAP #10", "TRAP #11",
-	"TRAP #12", "TRAP #13", "TRAP #14", "TRAP #15",
-	"FPCP BSUN", "FPCP INEXACT", "FPCP DIV BY 0", "FPCP UNDERFLOW",
-	"FPCP OPERAND ERROR", "FPCP OVERFLOW", "FPCP SNAN",
-	"FPCP UNSUPPORTED OPERATION",
-	"MMU CONFIGURATION ERROR"
-};
-
-void __init trap_init(void)
-{
-}
-
-void die_if_kernel(char *str, struct pt_regs *fp, int nr)
-{
-	if (!(fp->sr & PS_S))
-		return;
-
-	console_verbose();
-	printk(KERN_EMERG "%s: %08x\n",str,nr);
-	printk(KERN_EMERG "PC: [<%08lx>]\nSR: %04x  SP: %p  a2: %08lx\n",
-	       fp->pc, fp->sr, fp, fp->a2);
-	printk(KERN_EMERG "d0: %08lx    d1: %08lx    d2: %08lx    d3: %08lx\n",
-	       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 "Process %s (pid: %d, stackpage=%08lx)\n",
-		current->comm, current->pid, PAGE_SIZE+(unsigned long)current);
-	show_stack(NULL, (unsigned long *)(fp + 1));
-	add_taint(TAINT_DIE);
-	do_exit(SIGSEGV);
-}
-
-asmlinkage void buserr_c(struct frame *fp)
-{
-	/* Only set esp0 if coming from user mode */
-	if (user_mode(&fp->ptregs))
-		current->thread.esp0 = (unsigned long) fp;
-
-#if defined(DEBUG)
-	printk (KERN_DEBUG "*** Bus Error *** Format is %x\n", fp->ptregs.format);
-#endif
-
-	die_if_kernel("bad frame format",&fp->ptregs,0);
-#if defined(DEBUG)
-	printk(KERN_DEBUG "Unknown SIGSEGV - 4\n");
-#endif
-	force_sig(SIGSEGV, current);
-}
-
-static void print_this_address(unsigned long addr, int i)
-{
-#ifdef CONFIG_KALLSYMS
-	printk(KERN_EMERG " [%08lx] ", addr);
-	print_symbol(KERN_CONT "%s\n", addr);
-#else
-	if (i % 5)
-		printk(KERN_CONT " [%08lx] ", addr);
-	else
-		printk(KERN_EMERG " [%08lx] ", addr);
-	i++;
-#endif
-}
-
-int kstack_depth_to_print = 48;
-
-static void __show_stack(struct task_struct *task, unsigned long *stack)
-{
-	unsigned long *endstack, addr;
-#ifdef CONFIG_FRAME_POINTER
-	unsigned long *last_stack;
-#endif
-	int i;
-
-	if (!stack)
-		stack = (unsigned long *)task->thread.ksp;
-
-	addr = (unsigned long) stack;
-	endstack = (unsigned long *) PAGE_ALIGN(addr);
-
-	printk(KERN_EMERG "Stack from %08lx:", (unsigned long)stack);
-	for (i = 0; i < kstack_depth_to_print; i++) {
-		if (stack + 1 + i > endstack)
-			break;
-		if (i % 8 == 0)
-			printk(KERN_EMERG "       ");
-		printk(KERN_CONT " %08lx", *(stack + i));
-	}
-	printk("\n");
-	i = 0;
-
-#ifdef CONFIG_FRAME_POINTER
-	printk(KERN_EMERG "Call Trace:\n");
-
-	last_stack = stack - 1;
-	while (stack <= endstack && stack > last_stack) {
-
-		addr = *(stack + 1);
-		print_this_address(addr, i);
-		i++;
-
-		last_stack = stack;
-		stack = (unsigned long *)*stack;
-	}
-	printk("\n");
-#else
-	printk(KERN_EMERG "Call Trace with CONFIG_FRAME_POINTER disabled:\n");
-	while (stack <= endstack) {
-		addr = *stack++;
-		/*
-		 * If the address is either in the text segment of the kernel,
-		 * or in a region which is occupied by a module then it *may*
-		 * be the address of a calling routine; if so, print it so that
-		 * someone tracing down the cause of the crash will be able to
-		 * figure out the call path that was taken.
-		 */
-		if (__kernel_text_address(addr)) {
-			print_this_address(addr, i);
-			i++;
-		}
-	}
-	printk(KERN_CONT "\n");
-#endif
-}
-
-void bad_super_trap(struct frame *fp)
-{
-	int vector = (fp->ptregs.vector >> 2) & 0xff;
-
-	console_verbose();
-	if (vector < ARRAY_SIZE(vec_names))
-		printk (KERN_WARNING "*** %s ***   FORMAT=%X\n",
-			vec_names[vector],
-			fp->ptregs.format);
-	else
-		printk (KERN_WARNING "*** Exception %d ***   FORMAT=%X\n",
-			vector,
-			fp->ptregs.format);
-	printk (KERN_WARNING "Current process id is %d\n", current->pid);
-	die_if_kernel("BAD KERNEL TRAP", &fp->ptregs, 0);
-}
-
-asmlinkage void trap_c(struct frame *fp)
-{
-	int sig;
-	int vector = (fp->ptregs.vector >> 2) & 0xff;
-	siginfo_t info;
-
-	if (fp->ptregs.sr & PS_S) {
-		if (vector == VEC_TRACE) {
-			/* traced a trapping instruction */
-		} else
-			bad_super_trap(fp);
-		return;
-	}
-
-	/* send the appropriate signal to the user program */
-	switch (vector) {
-	    case VEC_ADDRERR:
-		info.si_code = BUS_ADRALN;
-		sig = SIGBUS;
-		break;
-	    case VEC_ILLEGAL:
-	    case VEC_LINE10:
-	    case VEC_LINE11:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_PRIV:
-		info.si_code = ILL_PRVOPC;
-		sig = SIGILL;
-		break;
-	    case VEC_COPROC:
-		info.si_code = ILL_COPROC;
-		sig = SIGILL;
-		break;
-	    case VEC_TRAP1: /* gdbserver breakpoint */
-		fp->ptregs.pc -= 2;
-		info.si_code = TRAP_TRACE;
-		sig = SIGTRAP;
-		break;
-	    case VEC_TRAP2:
-	    case VEC_TRAP3:
-	    case VEC_TRAP4:
-	    case VEC_TRAP5:
-	    case VEC_TRAP6:
-	    case VEC_TRAP7:
-	    case VEC_TRAP8:
-	    case VEC_TRAP9:
-	    case VEC_TRAP10:
-	    case VEC_TRAP11:
-	    case VEC_TRAP12:
-	    case VEC_TRAP13:
-	    case VEC_TRAP14:
-		info.si_code = ILL_ILLTRP;
-		sig = SIGILL;
-		break;
-	    case VEC_FPBRUC:
-	    case VEC_FPOE:
-	    case VEC_FPNAN:
-		info.si_code = FPE_FLTINV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPIR:
-		info.si_code = FPE_FLTRES;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPDIVZ:
-		info.si_code = FPE_FLTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPUNDER:
-		info.si_code = FPE_FLTUND;
-		sig = SIGFPE;
-		break;
-	    case VEC_FPOVER:
-		info.si_code = FPE_FLTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_ZERODIV:
-		info.si_code = FPE_INTDIV;
-		sig = SIGFPE;
-		break;
-	    case VEC_CHK:
-	    case VEC_TRAP:
-		info.si_code = FPE_INTOVF;
-		sig = SIGFPE;
-		break;
-	    case VEC_TRACE:		/* ptrace single step */
-		info.si_code = TRAP_TRACE;
-		sig = SIGTRAP;
-		break;
-	    case VEC_TRAP15:		/* breakpoint */
-		info.si_code = TRAP_BRKPT;
-		sig = SIGTRAP;
-		break;
-	    default:
-		info.si_code = ILL_ILLOPC;
-		sig = SIGILL;
-		break;
-	}
-	info.si_signo = sig;
-	info.si_errno = 0;
-	switch (fp->ptregs.format) {
-	    default:
-		info.si_addr = (void *) fp->ptregs.pc;
-		break;
-	    case 2:
-		info.si_addr = (void *) fp->un.fmt2.iaddr;
-		break;
-	    case 7:
-		info.si_addr = (void *) fp->un.fmt7.effaddr;
-		break;
-	    case 9:
-		info.si_addr = (void *) fp->un.fmt9.iaddr;
-		break;
-	    case 10:
-		info.si_addr = (void *) fp->un.fmta.daddr;
-		break;
-	    case 11:
-		info.si_addr = (void *) fp->un.fmtb.daddr;
-		break;
-	}
-	force_sig_info (sig, &info, current);
-}
-
-asmlinkage void set_esp0(unsigned long ssp)
-{
-	current->thread.esp0 = ssp;
-}
-
-/*
- * The architecture-independent backtrace generator
- */
-void dump_stack(void)
-{
-	/*
-	 * We need frame pointers for this little trick, which works as follows:
-	 *
-	 * +------------+ 0x00
-	 * | Next SP	|	-> 0x0c
-	 * +------------+ 0x04
-	 * | Caller	|
-	 * +------------+ 0x08
-	 * | Local vars	|	-> our stack var
-	 * +------------+ 0x0c
-	 * | Next SP	|	-> 0x18, that is what we pass to show_stack()
-	 * +------------+ 0x10
-	 * | Caller	|
-	 * +------------+ 0x14
-	 * | Local vars	|
-	 * +------------+ 0x18
-	 * | ...	|
-	 * +------------+
-	 */
-
-	unsigned long *stack;
-
-	stack = (unsigned long *)&stack;
-	stack++;
-	__show_stack(current, stack);
-}
-EXPORT_SYMBOL(dump_stack);
-
-void show_stack(struct task_struct *task, unsigned long *stack)
-{
-	if (!stack && !task)
-		dump_stack();
-	else
-		__show_stack(task, stack);
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/m68knommu/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/kernel/vmlinux.lds.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,188 +0,0 @@
-/*
- *	vmlinux.lds.S -- master linker script for m68knommu arch
- *
- *	(C) Copyright 2002-2006, Greg Ungerer <gerg@snapgear.com>
- *
- *	This linker script is equiped to build either ROM loaded or RAM
- *	run kernels.
- */
-
-#include <asm-generic/vmlinux.lds.h>
-#include <asm/page.h>
-#include <asm/thread_info.h>
-
-#if defined(CONFIG_RAMKERNEL)
-#define	RAM_START	CONFIG_KERNELBASE
-#define	RAM_LENGTH	(CONFIG_RAMBASE + CONFIG_RAMSIZE - CONFIG_KERNELBASE)
-#define	TEXT		ram
-#define	DATA		ram
-#define	INIT		ram
-#define	BSSS		ram
-#endif
-#if defined(CONFIG_ROMKERNEL) || defined(CONFIG_HIMEMKERNEL)
-#define	RAM_START	CONFIG_RAMBASE
-#define	RAM_LENGTH	CONFIG_RAMSIZE
-#define	ROMVEC_START	CONFIG_ROMVEC
-#define	ROMVEC_LENGTH	CONFIG_ROMVECSIZE
-#define	ROM_START	CONFIG_ROMSTART
-#define	ROM_LENGTH	CONFIG_ROMSIZE
-#define	TEXT		rom
-#define	DATA		ram
-#define	INIT		ram
-#define	BSSS		ram
-#endif
-
-#ifndef DATA_ADDR
-#define	DATA_ADDR
-#endif
-
-
-OUTPUT_ARCH(m68k)
-ENTRY(_start)
-
-MEMORY {
-	ram	: ORIGIN = RAM_START, LENGTH = RAM_LENGTH
-#ifdef ROM_START
-	romvec	: ORIGIN = ROMVEC_START, LENGTH = ROMVEC_LENGTH
-	rom	: ORIGIN = ROM_START, LENGTH = ROM_LENGTH
-#endif
-}
-
-jiffies = jiffies_64 + 4;
-
-SECTIONS {
-
-#ifdef ROMVEC_START
-	. = ROMVEC_START ;
-	.romvec : {
-		__rom_start = . ;
-		_romvec = .;
-		*(.data..initvect)
-	} > romvec
-#endif
-
-	.text : {
-		_text = .;
-		_stext = . ;
-		HEAD_TEXT
-		TEXT_TEXT
-		SCHED_TEXT
-		LOCK_TEXT
-		*(.text..lock)
-
-		. = ALIGN(16);          /* Exception table              */
-		__start___ex_table = .;
-		*(__ex_table)
-		__stop___ex_table = .;
-
-		*(.rodata) *(.rodata.*)
-		*(__vermagic)		/* Kernel version magic */
-		*(__markers_strings)
-		*(.rodata1)
-		*(.rodata.str1.1)
-
-		/* Kernel symbol table: Normal symbols */
-		. = ALIGN(4);
-		__start___ksymtab = .;
-		*(__ksymtab)
-		__stop___ksymtab = .;
-
-		/* Kernel symbol table: GPL-only symbols */
-		__start___ksymtab_gpl = .;
-		*(__ksymtab_gpl)
-		__stop___ksymtab_gpl = .;
-
-		/* Kernel symbol table: Normal unused symbols */
-		__start___ksymtab_unused = .;
-		*(__ksymtab_unused)
-		__stop___ksymtab_unused = .;
-
-		/* Kernel symbol table: GPL-only unused symbols */
-		__start___ksymtab_unused_gpl = .;
-		*(__ksymtab_unused_gpl)
-		__stop___ksymtab_unused_gpl = .;
-
-		/* Kernel symbol table: GPL-future symbols */
-		__start___ksymtab_gpl_future = .;
-		*(__ksymtab_gpl_future)
-		__stop___ksymtab_gpl_future = .;
-
-		/* Kernel symbol table: Normal symbols */
-		__start___kcrctab = .;
-		*(__kcrctab)
-		__stop___kcrctab = .;
-
-		/* Kernel symbol table: GPL-only symbols */
-		__start___kcrctab_gpl = .;
-		*(__kcrctab_gpl)
-		__stop___kcrctab_gpl = .;
-
-		/* Kernel symbol table: Normal unused symbols */
-		__start___kcrctab_unused = .;
-		*(__kcrctab_unused)
-		__stop___kcrctab_unused = .;
-
-		/* Kernel symbol table: GPL-only unused symbols */
-		__start___kcrctab_unused_gpl = .;
-		*(__kcrctab_unused_gpl)
-		__stop___kcrctab_unused_gpl = .;
-
-		/* Kernel symbol table: GPL-future symbols */
-		__start___kcrctab_gpl_future = .;
-		*(__kcrctab_gpl_future)
-		__stop___kcrctab_gpl_future = .;
-
-		/* Kernel symbol table: strings */
-		*(__ksymtab_strings)
-
-		/* Built-in module parameters */
-		. = ALIGN(4) ;
-		__start___param = .;
-		*(__param)
-		__stop___param = .;
-
-		/* Built-in module versions */
-		. = ALIGN(4) ;
-		__start___modver = .;
-		*(__modver)
-		__stop___modver = .;
-
-		. = ALIGN(4) ;
-		_etext = . ;
-	} > TEXT
-
-	.data DATA_ADDR : {
-		. = ALIGN(4);
-		_sdata = . ;
-		DATA_DATA
-		CACHELINE_ALIGNED_DATA(32)
-		PAGE_ALIGNED_DATA(PAGE_SIZE)
-		*(.data..shared_aligned)
-		INIT_TASK_DATA(THREAD_SIZE)
-		_edata = . ;
-	} > DATA
-
-	.init.text : {
-		. = ALIGN(PAGE_SIZE);
-		__init_begin = .;
-	} > INIT
-	INIT_TEXT_SECTION(PAGE_SIZE) > INIT
-	INIT_DATA_SECTION(16) > INIT
-	.init.data : {
-		. = ALIGN(PAGE_SIZE);
-		__init_end = .;
-	} > INIT
-
-	.bss : {
-		. = ALIGN(4);
-		_sbss = . ;
-		*(.bss)
-		*(COMMON)
-		. = ALIGN(4) ;
-		_ebss = . ;
-	 	_end = . ;
-	} > BSSS
-
-	DISCARDS
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/ashldi3.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/ashldi3.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/ashldi3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/ashldi3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.95.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 92-98, 1999 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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;
-
-DItype
-__ashldi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.low = 0;
-      w.s.high = (USItype)uu.s.low << -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.low >> bm;
-      w.s.low = (USItype)uu.s.low << b;
-      w.s.high = ((USItype)uu.s.high << b) | carries;
-    }
-
-  return w.ll;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/ashrdi3.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/ashrdi3.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/ashrdi3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/ashrdi3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,63 +0,0 @@
-/* ashrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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;
-
-DItype
-__ashrdi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      /* w.s.high = 1..1 or 0..0 */
-      w.s.high = uu.s.high >> (sizeof (SItype) * BITS_PER_UNIT - 1);
-      w.s.low = uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/checksum.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/checksum.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/checksum.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/checksum.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +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 <linux/module.h>
-#include <net/checksum.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 long 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;
-}
-
-#ifdef CONFIG_COLDFIRE
-/*
- *	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);
-}
-#endif
-
-/*
- * 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 += (__force u32)sum;
-	if ((__force u32)sum > result)
-		result += 1;
-	return (__force __wsum)result;
-}
-
-EXPORT_SYMBOL(csum_partial);
-
-/*
- * copy from fs while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_from_user(const void __user *src, void *dst,
-			    int len, __wsum sum, int *csum_err)
-{
-	if (csum_err) *csum_err = 0;
-	memcpy(dst, (__force const void *)src, len);
-	return csum_partial(dst, len, sum);
-}
-
-/*
- * copy from ds while checksumming, otherwise like csum_partial
- */
-
-__wsum
-csum_partial_copy_nocheck(const void *src, void *dst, int len, __wsum sum)
-{
-	memcpy(dst, src, len);
-	return csum_partial(dst, len, sum);
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/delay.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/delay.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/delay.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/delay.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,21 +0,0 @@
-/*
- *	arch/m68knommu/lib/delay.c
- *
- *	(C) Copyright 2004, Greg Ungerer <gerg@snapgear.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 <asm/param.h>
-#include <asm/delay.h>
-
-EXPORT_SYMBOL(udelay);
-
-void udelay(unsigned long usecs)
-{
-	_udelay(usecs);
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/divsi3.S linux-libre-2.6.39-gnu/arch/m68knommu/lib/divsi3.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/divsi3.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/divsi3.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,125 +0,0 @@
-/* libgcc1 routines for 68000 w/o floating-point hardware.
-   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file.  (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-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; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files
-   compiled with GCC to produce an executable, this does not cause
-   the resulting executable to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.  */
-
-/* Use this one for any 680x0; assumes no floating point hardware.
-   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
-   Some of this code comes from MINIX, via the folks at ericsson.
-   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
-*/
-
-/* These are predefined by new versions of GNU cpp.  */
-
-#ifndef __USER_LABEL_PREFIX__
-#define __USER_LABEL_PREFIX__ _
-#endif
-
-#ifndef __REGISTER_PREFIX__
-#define __REGISTER_PREFIX__
-#endif
-
-#ifndef __IMMEDIATE_PREFIX__
-#define __IMMEDIATE_PREFIX__ #
-#endif
-
-/* ANSI concatenation macros.  */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-/* Use the right prefix for registers.  */
-
-#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
-
-/* Use the right prefix for immediate values.  */
-
-#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
-
-#define d0 REG (d0)
-#define d1 REG (d1)
-#define d2 REG (d2)
-#define d3 REG (d3)
-#define d4 REG (d4)
-#define d5 REG (d5)
-#define d6 REG (d6)
-#define d7 REG (d7)
-#define a0 REG (a0)
-#define a1 REG (a1)
-#define a2 REG (a2)
-#define a3 REG (a3)
-#define a4 REG (a4)
-#define a5 REG (a5)
-#define a6 REG (a6)
-#define fp REG (fp)
-#define sp REG (sp)
-
-	.text
-	.proc
-	.globl	SYM (__divsi3)
-SYM (__divsi3):
-	movel	d2, sp@-
-
-	moveq	IMM (1), d2	/* sign of result stored in d2 (=1 or =-1) */
-	movel	sp@(12), d1	/* d1 = divisor */
-	jpl	L1
-	negl	d1
-#if !(defined(__mcf5200__) || defined(__mcoldfire__))
-	negb	d2		/* change sign because divisor <0  */
-#else
-	negl	d2		/* change sign because divisor <0  */
-#endif
-L1:	movel	sp@(8), d0	/* d0 = dividend */
-	jpl	L2
-	negl	d0
-#if !(defined(__mcf5200__) || defined(__mcoldfire__))
-	negb	d2
-#else
-	negl	d2
-#endif
-
-L2:	movel	d1, sp@-
-	movel	d0, sp@-
-	jbsr	SYM (__udivsi3)	/* divide abs(dividend) by abs(divisor) */
-	addql	IMM (8), sp
-
-	tstb	d2
-	jpl	L3
-	negl	d0
-
-L3:	movel	sp@+, d2
-	rts
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/lshrdi3.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/lshrdi3.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/lshrdi3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/lshrdi3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/* lshrdi3.c extracted from gcc-2.7.2/libgcc2.c which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, 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;
-
-DItype
-__lshrdi3 (DItype u, word_type b)
-{
-  DIunion w;
-  word_type bm;
-  DIunion uu;
-
-  if (b == 0)
-    return u;
-
-  uu.ll = u;
-
-  bm = (sizeof (SItype) * BITS_PER_UNIT) - b;
-  if (bm <= 0)
-    {
-      w.s.high = 0;
-      w.s.low = (USItype)uu.s.high >> -bm;
-    }
-  else
-    {
-      USItype carries = (USItype)uu.s.high << bm;
-      w.s.high = (USItype)uu.s.high >> b;
-      w.s.low = ((USItype)uu.s.low >> b) | carries;
-    }
-
-  return w.ll;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#
-# Makefile for m68knommu specific library files..
-#
-
-lib-y	:= ashldi3.o ashrdi3.o lshrdi3.o \
-	   muldi3.o mulsi3.o divsi3.o udivsi3.o modsi3.o umodsi3.o \
-	   checksum.o memcpy.o memmove.o memset.o delay.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/memcpy.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/memcpy.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/memcpy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/memcpy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-
-#include <linux/types.h>
-
-void * memcpy(void * to, const void * from, size_t n)
-{
-#ifdef CONFIG_COLDFIRE
-  void *xto = to;
-  size_t temp;
-
-  if (!n)
-    return xto;
-  if ((long) to & 1)
-    {
-      char *cto = to;
-      const char *cfrom = from;
-      *cto++ = *cfrom++;
-      to = cto;
-      from = cfrom;
-      n--;
-    }
-  if (n > 2 && (long) to & 2)
-    {
-      short *sto = to;
-      const short *sfrom = from;
-      *sto++ = *sfrom++;
-      to = sto;
-      from = sfrom;
-      n -= 2;
-    }
-  temp = n >> 2;
-  if (temp)
-    {
-      long *lto = to;
-      const long *lfrom = from;
-      for (; temp; temp--)
-	*lto++ = *lfrom++;
-      to = lto;
-      from = lfrom;
-    }
-  if (n & 2)
-    {
-      short *sto = to;
-      const short *sfrom = from;
-      *sto++ = *sfrom++;
-      to = sto;
-      from = sfrom;
-    }
-  if (n & 1)
-    {
-      char *cto = to;
-      const char *cfrom = from;
-      *cto = *cfrom;
-    }
-  return xto;
-#else
-  const char *c_from = from;
-  char *c_to = to;
-  while (n-- > 0)
-    *c_to++ = *c_from++;
-  return((void *) to);
-#endif
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/memmove.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/memmove.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/memmove.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/memmove.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,105 +0,0 @@
-/*
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file COPYING in the main directory of this archive
- * for more details.
- */
-
-#define __IN_STRING_C
-
-#include <linux/module.h>
-#include <linux/string.h>
-
-void *memmove(void *dest, const void *src, size_t n)
-{
-	void *xdest = dest;
-	size_t temp;
-
-	if (!n)
-		return xdest;
-
-	if (dest < src) {
-		if ((long)dest & 1) {
-			char *cdest = dest;
-			const char *csrc = src;
-			*cdest++ = *csrc++;
-			dest = cdest;
-			src = csrc;
-			n--;
-		}
-		if (n > 2 && (long)dest & 2) {
-			short *sdest = dest;
-			const short *ssrc = src;
-			*sdest++ = *ssrc++;
-			dest = sdest;
-			src = ssrc;
-			n -= 2;
-		}
-		temp = n >> 2;
-		if (temp) {
-			long *ldest = dest;
-			const long *lsrc = src;
-			temp--;
-			do
-				*ldest++ = *lsrc++;
-			while (temp--);
-			dest = ldest;
-			src = lsrc;
-		}
-		if (n & 2) {
-			short *sdest = dest;
-			const short *ssrc = src;
-			*sdest++ = *ssrc++;
-			dest = sdest;
-			src = ssrc;
-		}
-		if (n & 1) {
-			char *cdest = dest;
-			const char *csrc = src;
-			*cdest = *csrc;
-		}
-	} else {
-		dest = (char *)dest + n;
-		src = (const char *)src + n;
-		if ((long)dest & 1) {
-			char *cdest = dest;
-			const char *csrc = src;
-			*--cdest = *--csrc;
-			dest = cdest;
-			src = csrc;
-			n--;
-		}
-		if (n > 2 && (long)dest & 2) {
-			short *sdest = dest;
-			const short *ssrc = src;
-			*--sdest = *--ssrc;
-			dest = sdest;
-			src = ssrc;
-			n -= 2;
-		}
-		temp = n >> 2;
-		if (temp) {
-			long *ldest = dest;
-			const long *lsrc = src;
-			temp--;
-			do
-				*--ldest = *--lsrc;
-			while (temp--);
-			dest = ldest;
-			src = lsrc;
-		}
-		if (n & 2) {
-			short *sdest = dest;
-			const short *ssrc = src;
-			*--sdest = *--ssrc;
-			dest = sdest;
-			src = ssrc;
-		}
-		if (n & 1) {
-			char *cdest = dest;
-			const char *csrc = src;
-			*--cdest = *--csrc;
-		}
-	}
-	return xdest;
-}
-EXPORT_SYMBOL(memmove);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/memset.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/memset.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/memset.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/memset.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,47 +0,0 @@
-#include <linux/types.h>
-
-void * memset(void * s, int c, size_t count)
-{
-  void *xs = s;
-  size_t temp;
-
-  if (!count)
-    return xs;
-  c &= 0xff;
-  c |= c << 8;
-  c |= c << 16;
-  if ((long) s & 1)
-    {
-      char *cs = s;
-      *cs++ = c;
-      s = cs;
-      count--;
-    }
-  if (count > 2 && (long) s & 2)
-    {
-      short *ss = s;
-      *ss++ = c;
-      s = ss;
-      count -= 2;
-    }
-  temp = count >> 2;
-  if (temp)
-    {
-      long *ls = s;
-      for (; temp; temp--)
-	*ls++ = c;
-      s = ls;
-    }
-  if (count & 2)
-    {
-      short *ss = s;
-      *ss++ = c;
-      s = ss;
-    }
-  if (count & 1)
-    {
-      char *cs = s;
-      *cs = c;
-    }
-  return xs;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/modsi3.S linux-libre-2.6.39-gnu/arch/m68knommu/lib/modsi3.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/modsi3.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/modsi3.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,113 +0,0 @@
-/* libgcc1 routines for 68000 w/o floating-point hardware.
-   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file.  (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-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; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files
-   compiled with GCC to produce an executable, this does not cause
-   the resulting executable to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.  */
-
-/* Use this one for any 680x0; assumes no floating point hardware.
-   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
-   Some of this code comes from MINIX, via the folks at ericsson.
-   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
-*/
-
-/* These are predefined by new versions of GNU cpp.  */
-
-#ifndef __USER_LABEL_PREFIX__
-#define __USER_LABEL_PREFIX__ _
-#endif
-
-#ifndef __REGISTER_PREFIX__
-#define __REGISTER_PREFIX__
-#endif
-
-#ifndef __IMMEDIATE_PREFIX__
-#define __IMMEDIATE_PREFIX__ #
-#endif
-
-/* ANSI concatenation macros.  */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-/* Use the right prefix for registers.  */
-
-#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
-
-/* Use the right prefix for immediate values.  */
-
-#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
-
-#define d0 REG (d0)
-#define d1 REG (d1)
-#define d2 REG (d2)
-#define d3 REG (d3)
-#define d4 REG (d4)
-#define d5 REG (d5)
-#define d6 REG (d6)
-#define d7 REG (d7)
-#define a0 REG (a0)
-#define a1 REG (a1)
-#define a2 REG (a2)
-#define a3 REG (a3)
-#define a4 REG (a4)
-#define a5 REG (a5)
-#define a6 REG (a6)
-#define fp REG (fp)
-#define sp REG (sp)
-
-	.text
-	.proc
-	.globl	SYM (__modsi3)
-SYM (__modsi3):
-	movel	sp@(8), d1	/* d1 = divisor */
-	movel	sp@(4), d0	/* d0 = dividend */
-	movel	d1, sp@-
-	movel	d0, sp@-
-	jbsr	SYM (__divsi3)
-	addql	IMM (8), sp
-	movel	sp@(8), d1	/* d1 = divisor */
-#if !(defined(__mcf5200__) || defined(__mcoldfire__))
-	movel	d1, sp@-
-	movel	d0, sp@-
-	jbsr	SYM (__mulsi3)	/* d0 = (a/b)*b */
-	addql	IMM (8), sp
-#else
-	mulsl	d1,d0
-#endif
-	movel	sp@(4), d1	/* d1 = dividend */
-	subl	d0, d1		/* d1 = a - (a/b)*b */
-	movel	d1, d0
-	rts
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/muldi3.c linux-libre-2.6.39-gnu/arch/m68knommu/lib/muldi3.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/muldi3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/muldi3.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,86 +0,0 @@
-/* muldi3.c extracted from gcc-2.7.2.3/libgcc2.c and 
-			   gcc-2.7.2.3/longlong.h which is: */
-/* Copyright (C) 1989, 1992, 1993, 1994, 1995 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-#define BITS_PER_UNIT 8
-#define SI_TYPE_SIZE 32
-
-#define __BITS4 (SI_TYPE_SIZE / 4)
-#define __ll_B (1L << (SI_TYPE_SIZE / 2))
-#define __ll_lowpart(t) ((USItype) (t) % __ll_B)
-#define __ll_highpart(t) ((USItype) (t) / __ll_B)
-
-#define umul_ppmm(w1, w0, u, v)						\
-  do {									\
-    USItype __x0, __x1, __x2, __x3;					\
-    USItype __ul, __vl, __uh, __vh;					\
-									\
-    __ul = __ll_lowpart (u);						\
-    __uh = __ll_highpart (u);						\
-    __vl = __ll_lowpart (v);						\
-    __vh = __ll_highpart (v);						\
-									\
-    __x0 = (USItype) __ul * __vl;					\
-    __x1 = (USItype) __ul * __vh;					\
-    __x2 = (USItype) __uh * __vl;					\
-    __x3 = (USItype) __uh * __vh;					\
-									\
-    __x1 += __ll_highpart (__x0);/* this can't give carry */		\
-    __x1 += __x2;		/* but this indeed can */		\
-    if (__x1 < __x2)		/* did we get it? */			\
-      __x3 += __ll_B;		/* yes, add it in the proper pos. */	\
-									\
-    (w1) = __x3 + __ll_highpart (__x1);					\
-    (w0) = __ll_lowpart (__x1) * __ll_B + __ll_lowpart (__x0);		\
-  } while (0)
-
-#define __umulsidi3(u, v) \
-  ({DIunion __w;							\
-    umul_ppmm (__w.s.high, __w.s.low, u, v);				\
-    __w.ll; })
-
-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;
-
-DItype
-__muldi3 (DItype u, DItype v)
-{
-  DIunion w;
-  DIunion uu, vv;
-
-  uu.ll = u,
-  vv.ll = v;
-
-  w.ll = __umulsidi3 (uu.s.low, vv.s.low);
-  w.s.high += ((USItype) uu.s.low * (USItype) vv.s.high
-	       + (USItype) uu.s.high * (USItype) vv.s.low);
-
-  return w.ll;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/mulsi3.S linux-libre-2.6.39-gnu/arch/m68knommu/lib/mulsi3.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/mulsi3.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/mulsi3.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-/* libgcc1 routines for 68000 w/o floating-point hardware.
-   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file.  (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-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; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files
-   compiled with GCC to produce an executable, this does not cause
-   the resulting executable to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.  */
-
-/* Use this one for any 680x0; assumes no floating point hardware.
-   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
-   Some of this code comes from MINIX, via the folks at ericsson.
-   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
-*/
-
-/* These are predefined by new versions of GNU cpp.  */
-
-#ifndef __USER_LABEL_PREFIX__
-#define __USER_LABEL_PREFIX__ _
-#endif
-
-#ifndef __REGISTER_PREFIX__
-#define __REGISTER_PREFIX__
-#endif
-
-#ifndef __IMMEDIATE_PREFIX__
-#define __IMMEDIATE_PREFIX__ #
-#endif
-
-/* ANSI concatenation macros.  */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-/* Use the right prefix for registers.  */
-
-#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
-
-/* Use the right prefix for immediate values.  */
-
-#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
-
-#define d0 REG (d0)
-#define d1 REG (d1)
-#define d2 REG (d2)
-#define d3 REG (d3)
-#define d4 REG (d4)
-#define d5 REG (d5)
-#define d6 REG (d6)
-#define d7 REG (d7)
-#define a0 REG (a0)
-#define a1 REG (a1)
-#define a2 REG (a2)
-#define a3 REG (a3)
-#define a4 REG (a4)
-#define a5 REG (a5)
-#define a6 REG (a6)
-#define fp REG (fp)
-#define sp REG (sp)
-
-	.text
-	.proc
-	.globl	SYM (__mulsi3)
-SYM (__mulsi3):
-	movew	sp@(4), d0	/* x0 -> d0 */
-	muluw	sp@(10), d0	/* x0*y1 */
-	movew	sp@(6), d1	/* x1 -> d1 */
-	muluw	sp@(8), d1	/* x1*y0 */
-#if !(defined(__mcf5200__) || defined(__mcoldfire__))
-	addw	d1, d0
-#else
-	addl	d1, d0
-#endif
-	swap	d0
-	clrw	d0
-	movew	sp@(6), d1	/* x1 -> d1 */
-	muluw	sp@(10), d1	/* x1*y1 */
-	addl	d1, d0
-
-	rts
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/udivsi3.S linux-libre-2.6.39-gnu/arch/m68knommu/lib/udivsi3.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/udivsi3.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/udivsi3.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,162 +0,0 @@
-/* libgcc1 routines for 68000 w/o floating-point hardware.
-   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file.  (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-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; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files
-   compiled with GCC to produce an executable, this does not cause
-   the resulting executable to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.  */
-
-/* Use this one for any 680x0; assumes no floating point hardware.
-   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
-   Some of this code comes from MINIX, via the folks at ericsson.
-   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
-*/
-
-/* These are predefined by new versions of GNU cpp.  */
-
-#ifndef __USER_LABEL_PREFIX__
-#define __USER_LABEL_PREFIX__ _
-#endif
-
-#ifndef __REGISTER_PREFIX__
-#define __REGISTER_PREFIX__
-#endif
-
-#ifndef __IMMEDIATE_PREFIX__
-#define __IMMEDIATE_PREFIX__ #
-#endif
-
-/* ANSI concatenation macros.  */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-/* Use the right prefix for registers.  */
-
-#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
-
-/* Use the right prefix for immediate values.  */
-
-#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
-
-#define d0 REG (d0)
-#define d1 REG (d1)
-#define d2 REG (d2)
-#define d3 REG (d3)
-#define d4 REG (d4)
-#define d5 REG (d5)
-#define d6 REG (d6)
-#define d7 REG (d7)
-#define a0 REG (a0)
-#define a1 REG (a1)
-#define a2 REG (a2)
-#define a3 REG (a3)
-#define a4 REG (a4)
-#define a5 REG (a5)
-#define a6 REG (a6)
-#define fp REG (fp)
-#define sp REG (sp)
-
-	.text
-	.proc
-	.globl	SYM (__udivsi3)
-SYM (__udivsi3):
-#if !(defined(__mcf5200__) || defined(__mcoldfire__))
-	movel	d2, sp@-
-	movel	sp@(12), d1	/* d1 = divisor */
-	movel	sp@(8), d0	/* d0 = dividend */
-
-	cmpl	IMM (0x10000), d1 /* divisor >= 2 ^ 16 ?   */
-	jcc	L3		/* then try next algorithm */
-	movel	d0, d2
-	clrw	d2
-	swap	d2
-	divu	d1, d2          /* high quotient in lower word */
-	movew	d2, d0		/* save high quotient */
-	swap	d0
-	movew	sp@(10), d2	/* get low dividend + high rest */
-	divu	d1, d2		/* low quotient */
-	movew	d2, d0
-	jra	L6
-
-L3:	movel	d1, d2		/* use d2 as divisor backup */
-L4:	lsrl	IMM (1), d1	/* shift divisor */
-	lsrl	IMM (1), d0	/* shift dividend */
-	cmpl	IMM (0x10000), d1 /* still divisor >= 2 ^ 16 ?  */
-	jcc	L4
-	divu	d1, d0		/* now we have 16 bit divisor */
-	andl	IMM (0xffff), d0 /* mask out divisor, ignore remainder */
-
-/* Multiply the 16 bit tentative quotient with the 32 bit divisor.  Because of
-   the operand ranges, this might give a 33 bit product.  If this product is
-   greater than the dividend, the tentative quotient was too large. */
-	movel	d2, d1
-	mulu	d0, d1		/* low part, 32 bits */
-	swap	d2
-	mulu	d0, d2		/* high part, at most 17 bits */
-	swap	d2		/* align high part with low part */
-	tstw	d2		/* high part 17 bits? */
-	jne	L5		/* if 17 bits, quotient was too large */
-	addl	d2, d1		/* add parts */
-	jcs	L5		/* if sum is 33 bits, quotient was too large */
-	cmpl	sp@(8), d1	/* compare the sum with the dividend */
-	jls	L6		/* if sum > dividend, quotient was too large */
-L5:	subql	IMM (1), d0	/* adjust quotient */
-
-L6:	movel	sp@+, d2
-	rts
-
-#else /* __mcf5200__ || __mcoldfire__ */
-
-/* Coldfire implementation of non-restoring division algorithm from
-   Hennessy & Patterson, Appendix A. */
-	link	a6,IMM (-12)
-	moveml	d2-d4,sp@
-	movel	a6@(8),d0
-	movel	a6@(12),d1
-	clrl	d2		| clear p
-	moveq	IMM (31),d4
-L1:	addl	d0,d0		| shift reg pair (p,a) one bit left
-	addxl	d2,d2
-	movl	d2,d3		| subtract b from p, store in tmp.
-	subl	d1,d3
-	jcs	L2		| if no carry,
-	bset	IMM (0),d0	| set the low order bit of a to 1,
-	movl	d3,d2		| and store tmp in p.
-L2:	subql	IMM (1),d4
-	jcc	L1
-	moveml	sp@,d2-d4	| restore data registers
-	unlk	a6		| and return
-	rts
-#endif /* __mcf5200__ || __mcoldfire__ */
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/lib/umodsi3.S linux-libre-2.6.39-gnu/arch/m68knommu/lib/umodsi3.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/lib/umodsi3.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/lib/umodsi3.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,113 +0,0 @@
-/* libgcc1 routines for 68000 w/o floating-point hardware.
-   Copyright (C) 1994, 1996, 1997, 1998 Free Software Foundation, Inc.
-
-This file is part of GNU CC.
-
-GNU CC is free software; you can redistribute 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.
-
-In addition to the permissions in the GNU General Public License, the
-Free Software Foundation gives you unlimited permission to link the
-compiled version of this file with other programs, and to distribute
-those programs without any restriction coming from the use of this
-file.  (The General Public License restrictions do apply in other
-respects; for example, they cover modification of the file, and
-distribution when not linked into another program.)
-
-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; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
-
-/* As a special exception, if you link this library with files
-   compiled with GCC to produce an executable, this does not cause
-   the resulting executable to be covered by the GNU General Public License.
-   This exception does not however invalidate any other reasons why
-   the executable file might be covered by the GNU General Public License.  */
-
-/* Use this one for any 680x0; assumes no floating point hardware.
-   The trailing " '" appearing on some lines is for ANSI preprocessors.  Yuk.
-   Some of this code comes from MINIX, via the folks at ericsson.
-   D. V. Henkel-Wallace (gumby@cygnus.com) Fete Bastille, 1992
-*/
-
-/* These are predefined by new versions of GNU cpp.  */
-
-#ifndef __USER_LABEL_PREFIX__
-#define __USER_LABEL_PREFIX__ _
-#endif
-
-#ifndef __REGISTER_PREFIX__
-#define __REGISTER_PREFIX__
-#endif
-
-#ifndef __IMMEDIATE_PREFIX__
-#define __IMMEDIATE_PREFIX__ #
-#endif
-
-/* ANSI concatenation macros.  */
-
-#define CONCAT1(a, b) CONCAT2(a, b)
-#define CONCAT2(a, b) a ## b
-
-/* Use the right prefix for global labels.  */
-
-#define SYM(x) CONCAT1 (__USER_LABEL_PREFIX__, x)
-
-/* Use the right prefix for registers.  */
-
-#define REG(x) CONCAT1 (__REGISTER_PREFIX__, x)
-
-/* Use the right prefix for immediate values.  */
-
-#define IMM(x) CONCAT1 (__IMMEDIATE_PREFIX__, x)
-
-#define d0 REG (d0)
-#define d1 REG (d1)
-#define d2 REG (d2)
-#define d3 REG (d3)
-#define d4 REG (d4)
-#define d5 REG (d5)
-#define d6 REG (d6)
-#define d7 REG (d7)
-#define a0 REG (a0)
-#define a1 REG (a1)
-#define a2 REG (a2)
-#define a3 REG (a3)
-#define a4 REG (a4)
-#define a5 REG (a5)
-#define a6 REG (a6)
-#define fp REG (fp)
-#define sp REG (sp)
-
-	.text
-	.proc
-	.globl	SYM (__umodsi3)
-SYM (__umodsi3):
-	movel	sp@(8), d1	/* d1 = divisor */
-	movel	sp@(4), d0	/* d0 = dividend */
-	movel	d1, sp@-
-	movel	d0, sp@-
-	jbsr	SYM (__udivsi3)
-	addql	IMM (8), sp
-	movel	sp@(8), d1	/* d1 = divisor */
-#if !(defined(__mcf5200__) || defined(__mcoldfire__))
-	movel	d1, sp@-
-	movel	d0, sp@-
-	jbsr	SYM (__mulsi3)	/* d0 = (a/b)*b */
-	addql	IMM (8), sp
-#else
-	mulsl	d1,d0
-#endif
-	movel	sp@(4), d1	/* d1 = dividend */
-	subl	d0, d1		/* d1 = a - (a/b)*b */
-	movel	d1, d0
-	rts
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,126 +0,0 @@
-#
-# arch/m68knommu/Makefile
-#
-# 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.
-#
-# (C) Copyright 2002, Greg Ungerer <gerg@snapgear.com>
-#
-
-KBUILD_DEFCONFIG := m5208evb_defconfig
-
-platform-$(CONFIG_M68328)	:= 68328
-platform-$(CONFIG_M68EZ328)	:= 68EZ328
-platform-$(CONFIG_M68VZ328)	:= 68VZ328
-platform-$(CONFIG_M68360)	:= 68360
-platform-$(CONFIG_M5206)	:= 5206
-platform-$(CONFIG_M5206e)	:= 5206e
-platform-$(CONFIG_M520x)	:= 520x
-platform-$(CONFIG_M523x)	:= 523x
-platform-$(CONFIG_M5249)	:= 5249
-platform-$(CONFIG_M527x)	:= 527x
-platform-$(CONFIG_M5272)	:= 5272
-platform-$(CONFIG_M528x)	:= 528x
-platform-$(CONFIG_M5307)	:= 5307
-platform-$(CONFIG_M532x)	:= 532x
-platform-$(CONFIG_M5407)	:= 5407
-platform-$(CONFIG_M54xx)	:= 54xx
-PLATFORM := $(platform-y)
-
-board-$(CONFIG_PILOT)		:= pilot
-board-$(CONFIG_UC5272)          := UC5272
-board-$(CONFIG_UC5282)          := UC5282
-board-$(CONFIG_UCSIMM)		:= ucsimm
-board-$(CONFIG_UCDIMM)		:= ucdimm
-board-$(CONFIG_UCQUICC)		:= uCquicc
-board-$(CONFIG_DRAGEN2)		:= de2
-board-$(CONFIG_ARNEWSH)		:= ARNEWSH
-board-$(CONFIG_FREESCALE)	:= FREESCALE
-board-$(CONFIG_M5235EVB)	:= M5235EVB
-board-$(CONFIG_M5271EVB)	:= M5271EVB
-board-$(CONFIG_M5275EVB)	:= M5275EVB
-board-$(CONFIG_M5282EVB)	:= M5282EVB
-board-$(CONFIG_ELITE)		:= eLITE
-board-$(CONFIG_NETtel)		:= NETtel
-board-$(CONFIG_SECUREEDGEMP3)	:= MP3
-board-$(CONFIG_CLEOPATRA)	:= CLEOPATRA
-board-$(CONFIG_senTec)		:= senTec
-board-$(CONFIG_SNEHA) 	        := SNEHA
-board-$(CONFIG_M5208EVB)	:= M5208EVB
-board-$(CONFIG_MOD5272)		:= MOD5272
-board-$(CONFIG_AVNET)           := AVNET
-board-$(CONFIG_SAVANT)		:= SAVANT
-BOARD := $(board-y)
-
-model-$(CONFIG_RAMKERNEL)	:= ram
-model-$(CONFIG_ROMKERNEL)	:= rom
-MODEL := $(model-y)
-
-#
-# Some code support is grouped together for a common cpu-subclass (for
-# example all ColdFire cpu's are very similar). Determine the sub-class
-# for the selected cpu. ONLY need to define this for the non-base member
-# of the family.
-#
-cpuclass-$(CONFIG_M5206)	:= coldfire
-cpuclass-$(CONFIG_M5206e)	:= coldfire
-cpuclass-$(CONFIG_M520x)	:= coldfire
-cpuclass-$(CONFIG_M523x)	:= coldfire
-cpuclass-$(CONFIG_M5249)	:= coldfire
-cpuclass-$(CONFIG_M527x)	:= coldfire
-cpuclass-$(CONFIG_M5272)	:= coldfire
-cpuclass-$(CONFIG_M528x)	:= coldfire
-cpuclass-$(CONFIG_M5307)	:= coldfire
-cpuclass-$(CONFIG_M532x)	:= coldfire
-cpuclass-$(CONFIG_M5407)	:= coldfire
-cpuclass-$(CONFIG_M54xx)	:= coldfire
-cpuclass-$(CONFIG_M68328)	:= 68328
-cpuclass-$(CONFIG_M68EZ328)	:= 68328
-cpuclass-$(CONFIG_M68VZ328)	:= 68328
-cpuclass-$(CONFIG_M68360)	:= 68360
-CPUCLASS := $(cpuclass-y)
-
-ifneq ($(CPUCLASS),$(PLATFORM))
-CLASSDIR := arch/m68knommu/platform/$(cpuclass-y)/
-endif
-
-export PLATFORM BOARD MODEL CPUCLASS
-
-#
-# Some CFLAG additions based on specific CPU type.
-#
-cflags-$(CONFIG_M5206)		:= $(call cc-option,-mcpu=5206,-m5200)
-cflags-$(CONFIG_M5206e)		:= $(call cc-option,-mcpu=5206e,-m5200)
-cflags-$(CONFIG_M520x)		:= $(call cc-option,-mcpu=5208,-m5200)
-cflags-$(CONFIG_M523x)		:= $(call cc-option,-mcpu=523x,-m5307)
-cflags-$(CONFIG_M5249)		:= $(call cc-option,-mcpu=5249,-m5200)
-cflags-$(CONFIG_M5271)		:= $(call cc-option,-mcpu=5271,-m5307)
-cflags-$(CONFIG_M5272)		:= $(call cc-option,-mcpu=5272,-m5307)
-cflags-$(CONFIG_M5275)		:= $(call cc-option,-mcpu=5275,-m5307)
-cflags-$(CONFIG_M528x)		:= $(call cc-option,-mcpu=528x,-m5307)
-cflags-$(CONFIG_M5307)		:= $(call cc-option,-mcpu=5307,-m5200)
-cflags-$(CONFIG_M532x)		:= $(call cc-option,-mcpu=532x,-m5307)
-cflags-$(CONFIG_M5407)		:= $(call cc-option,-mcpu=5407,-m5200)
-cflags-$(CONFIG_M54xx)		:= $(call cc-option,-mcpu=5475,-m5200)
-cflags-$(CONFIG_M68328)		:= -m68000
-cflags-$(CONFIG_M68EZ328)	:= -m68000
-cflags-$(CONFIG_M68VZ328)	:= -m68000
-cflags-$(CONFIG_M68360)		:= -m68332
-
-KBUILD_AFLAGS += $(cflags-y)
-
-KBUILD_CFLAGS += $(cflags-y)
-KBUILD_CFLAGS += -D__linux__
-KBUILD_CFLAGS += -DUTS_SYSNAME=\"uClinux\"
-
-head-y := arch/m68knommu/platform/$(cpuclass-y)/head.o
-
-core-y	+= arch/m68knommu/kernel/ \
-	   arch/m68knommu/mm/ \
-	   $(CLASSDIR) \
-	   arch/m68knommu/platform/$(PLATFORM)/
-libs-y	+= arch/m68knommu/lib/
-
-archclean:
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/mm/init.c linux-libre-2.6.39-gnu/arch/m68knommu/mm/init.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/mm/init.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,193 +0,0 @@
-/*
- *  linux/arch/m68knommu/mm/init.c
- *
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo, Inc.  (www.lineo.com) 
- *
- *  Based on:
- *
- *  linux/arch/m68k/mm/init.c
- *
- *  Copyright (C) 1995  Hamish Macdonald
- *
- *  JAN/1999 -- hacked to support ColdFire (gerg@snapgear.com)
- *  DEC/2000 -- linux 2.4 support <davidm@snapgear.com>
- */
-
-#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/swap.h>
-#include <linux/init.h>
-#include <linux/highmem.h>
-#include <linux/pagemap.h>
-#include <linux/bootmem.h>
-#include <linux/gfp.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgtable.h>
-#include <asm/system.h>
-#include <asm/machdep.h>
-
-#undef DEBUG
-
-extern void die_if_kernel(char *,struct pt_regs *,long);
-extern void free_initmem(void);
-
-/*
- * BAD_PAGE is the page that is used for page faults when linux
- * is out-of-memory. Older versions of linux just did a
- * do_exit(), but using this instead means there is less risk
- * for a process dying in kernel mode, possibly leaving a inode
- * unused etc..
- *
- * BAD_PAGETABLE is the accompanying page-table: it is initialized
- * to point to BAD_PAGE entries.
- *
- * ZERO_PAGE is a special page that is used for zero-initialized
- * data and COW.
- */
-static unsigned long empty_bad_page_table;
-
-static unsigned long empty_bad_page;
-
-unsigned long empty_zero_page;
-
-extern unsigned long memory_start;
-extern unsigned long memory_end;
-
-/*
- * paging_init() continues the virtual memory environment setup which
- * was begun by the code in arch/head.S.
- * The parameters are pointers to where to stick the starting and ending
- * addresses of available kernel virtual memory.
- */
-void __init paging_init(void)
-{
-	/*
-	 * Make sure start_mem is page aligned, otherwise bootmem and
-	 * page_alloc get different views of the world.
-	 */
-#ifdef DEBUG
-	unsigned long start_mem = PAGE_ALIGN(memory_start);
-#endif
-	unsigned long end_mem   = memory_end & PAGE_MASK;
-
-#ifdef DEBUG
-	printk (KERN_DEBUG "start_mem is %#lx\nvirtual_end is %#lx\n",
-		start_mem, end_mem);
-#endif
-
-	/*
-	 * Initialize the bad page table and bad page to point
-	 * to a couple of allocated pages.
-	 */
-	empty_bad_page_table = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	empty_bad_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	empty_zero_page = (unsigned long)alloc_bootmem_pages(PAGE_SIZE);
-	memset((void *)empty_zero_page, 0, PAGE_SIZE);
-
-	/*
-	 * Set up SFC/DFC registers (user data space).
-	 */
-	set_fs (USER_DS);
-
-#ifdef DEBUG
-	printk (KERN_DEBUG "before free_area_init\n");
-
-	printk (KERN_DEBUG "free_area_init -> start_mem is %#lx\nvirtual_end is %#lx\n",
-		start_mem, end_mem);
-#endif
-
-	{
-		unsigned long zones_size[MAX_NR_ZONES] = {0, };
-
-		zones_size[ZONE_DMA] = (end_mem - PAGE_OFFSET) >> PAGE_SHIFT;
-		free_area_init(zones_size);
-	}
-}
-
-void __init mem_init(void)
-{
-	int codek = 0, datak = 0, initk = 0;
-	unsigned long tmp;
-	extern char _etext, _stext, _sdata, _ebss, __init_begin, __init_end;
-	extern unsigned int _ramend, _rambase;
-	unsigned long len = _ramend - _rambase;
-	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 */
-
-	pr_debug("Mem_init: start=%lx, end=%lx\n", start_mem, end_mem);
-
-	end_mem &= PAGE_MASK;
-	high_memory = (void *) end_mem;
-
-	start_mem = PAGE_ALIGN(start_mem);
-	max_mapnr = num_physpages = (((unsigned long) high_memory) - PAGE_OFFSET) >> PAGE_SHIFT;
-
-	/* this will put all memory onto the freelists */
-	totalram_pages = free_all_bootmem();
-
-	codek = (&_etext - &_stext) >> 10;
-	datak = (&_ebss - &_sdata) >> 10;
-	initk = (&__init_begin - &__init_end) >> 10;
-
-	tmp = nr_free_pages() << PAGE_SHIFT;
-	printk(KERN_INFO "Memory available: %luk/%luk RAM, (%dk kernel code, %dk data)\n",
-	       tmp >> 10,
-	       len >> 10,
-	       codek,
-	       datak
-	       );
-}
-
-
-#ifdef CONFIG_BLK_DEV_INITRD
-void free_initrd_mem(unsigned long start, unsigned long end)
-{
-	int pages = 0;
-	for (; start < end; start += PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(start));
-		init_page_count(virt_to_page(start));
-		free_page(start);
-		totalram_pages++;
-		pages++;
-	}
-	printk (KERN_NOTICE "Freeing initrd memory: %dk freed\n", pages * (PAGE_SIZE / 1024));
-}
-#endif
-
-void
-free_initmem()
-{
-#ifdef CONFIG_RAMKERNEL
-	unsigned long addr;
-	extern char __init_begin, __init_end;
-	/*
-	 * The following code should be cool even if these sections
-	 * are not page aligned.
-	 */
-	addr = PAGE_ALIGN((unsigned long)(&__init_begin));
-	/* next to check that the page we free is not a partial page */
-	for (; addr + PAGE_SIZE < (unsigned long)(&__init_end); addr +=PAGE_SIZE) {
-		ClearPageReserved(virt_to_page(addr));
-		init_page_count(virt_to_page(addr));
-		free_page(addr);
-		totalram_pages++;
-	}
-	printk(KERN_NOTICE "Freeing unused kernel memory: %ldk freed (0x%x - 0x%x)\n",
-			(addr - PAGE_ALIGN((long) &__init_begin)) >> 10,
-			(int)(PAGE_ALIGN((unsigned long)(&__init_begin))),
-			(int)(addr - PAGE_SIZE));
-#endif
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/mm/kmap.c linux-libre-2.6.39-gnu/arch/m68knommu/mm/kmap.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/mm/kmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/mm/kmap.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- *  linux/arch/m68knommu/mm/kmap.c
- *
- *  Copyright (C) 2000 Lineo, <davidm@snapgear.com>
- *  Copyright (C) 2000-2002 David McCullough <davidm@snapgear.com>
- */
-
-#include <linux/mm.h>
-#include <linux/kernel.h>
-#include <linux/string.h>
-#include <linux/types.h>
-#include <linux/vmalloc.h>
-
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/io.h>
-#include <asm/system.h>
-
-#undef DEBUG
-
-/*
- * Map some physical address range into the kernel address space.
- */
-void *__ioremap(unsigned long physaddr, unsigned long size, int cacheflag)
-{
-	return (void *)physaddr;
-}
-
-/*
- * Unmap a ioremap()ed region again.
- */
-void iounmap(void *addr)
-{
-}
-
-/*
- * Set new cache mode for some kernel address space.
- * The caller must push data for that range itself, if such data may already
- * be in the cache.
- */
-void kernel_set_cachemode(void *addr, unsigned long size, int cmode)
-{
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/mm/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/mm/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,5 +0,0 @@
-#
-# Makefile for the linux m68knommu specific parts of the memory manager.
-#
-
-obj-y += init.o kmap.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,121 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5206/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- * 	Copyright (C) 2000-2001, Lineo Inc. (www.lineo.com) 
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5206_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
-	},
-	{ },
-};
-
-static struct platform_device m5206_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5206_uart_platform,
-};
-
-static struct platform_device *m5206_devices[] __initdata = {
-	&m5206_uart,
-};
-
-/***************************************************************************/
-
-static void __init m5206_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
-		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART0);
-	} else if (line == 1) {
-		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
-		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART1);
-	}
-}
-
-static void __init m5206_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5206_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5206_uart_init_line(line, m5206_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m5206_timers_init(void)
-{
-	/* Timer1 is always used as system timer */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER1ICR);
-	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
-	/* Timer2 is to be used as a high speed profile timer  */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER2ICR);
-	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-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)
-{
-	mach_reset = m5206_cpu_reset;
-	m5206_timers_init();
-	m5206_uarts_init();
-
-	/* Only support the external interrupts on their primary level */
-	mcf_mapirq2imr(25, MCFINTC_EINT1);
-	mcf_mapirq2imr(28, MCFINTC_EINT4);
-	mcf_mapirq2imr(31, MCFINTC_EINT7);
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m5206_devices, ARRAY_SIZE(m5206_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PP",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206e/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206e/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206e/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206e/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,127 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5206e/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfdma.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5206e_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
-	},
-	{ },
-};
-
-static struct platform_device m5206e_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5206e_uart_platform,
-};
-
-static struct platform_device *m5206e_devices[] __initdata = {
-	&m5206e_uart,
-};
-
-/***************************************************************************/
-
-static void __init m5206e_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
-		writeb(irq, MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART0);
-	} else if (line == 1) {
-		writel(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
-		writeb(irq, MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART1);
-	}
-}
-
-static void __init m5206e_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5206e_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5206e_uart_init_line(line, m5206e_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m5206e_timers_init(void)
-{
-	/* Timer1 is always used as system timer */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER1ICR);
-	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
-	/* Timer2 is to be used as a high speed profile timer  */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER2ICR);
-	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-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)
-{
-#if defined(CONFIG_NETtel)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0xf0004000, size);
-	commandp[size-1] = 0;
-#endif /* CONFIG_NETtel */
-
-	mach_reset = m5206e_cpu_reset;
-	m5206e_timers_init();
-	m5206e_uarts_init();
-
-	/* Only support the external interrupts on their primary level */
-	mcf_mapirq2imr(25, MCFINTC_EINT1);
-	mcf_mapirq2imr(28, MCFINTC_EINT4);
-	mcf_mapirq2imr(31, MCFINTC_EINT7);
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m5206e_devices, ARRAY_SIZE(m5206e_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206e/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206e/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206e/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206e/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PP",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206e/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206e/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5206e/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5206e/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/520x/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/520x/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/520x/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/520x/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,311 +0,0 @@
-/***************************************************************************/
-
-/*
- *  linux/arch/m68knommu/platform/520x/config.c
- *
- *  Copyright (C) 2005,      Freescale (www.freescale.com)
- *  Copyright (C) 2005,      Intec Automation (mike@steroidmicros.com)
- *  Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfqspi.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m520x_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= MCFINT_VECBASE + MCFINT_UART1,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
-		.irq		= MCFINT_VECBASE + MCFINT_UART2,
-	},
-	{ },
-};
-
-static struct platform_device m520x_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m520x_uart_platform,
-};
-
-static struct resource m520x_fec_resources[] = {
-	{
-		.start		= MCF_MBAR + 0x30000,
-		.end		= MCF_MBAR + 0x30000 + 0x7ff,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= 64 + 36,
-		.end		= 64 + 36,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 40,
-		.end		= 64 + 40,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 42,
-		.end		= 64 + 42,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m520x_fec = {
-	.name			= "fec",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m520x_fec_resources),
-	.resource		= m520x_fec_resources,
-};
-
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-static struct resource m520x_qspi_resources[] = {
-	{
-		.start		= MCFQSPI_IOBASE,
-		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCFINT_VECBASE + MCFINT_QSPI,
-		.end		= MCFINT_VECBASE + MCFINT_QSPI,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-#define MCFQSPI_CS0    62
-#define MCFQSPI_CS1    63
-#define MCFQSPI_CS2    44
-
-static int m520x_cs_setup(struct mcfqspi_cs_control *cs_control)
-{
-	int status;
-
-	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
-		goto fail0;
-	}
-	status = gpio_direction_output(MCFQSPI_CS0, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
-		goto fail1;
-	}
-
-	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
-		goto fail1;
-	}
-	status = gpio_direction_output(MCFQSPI_CS1, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
-		goto fail2;
-	}
-
-	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
-		goto fail2;
-	}
-	status = gpio_direction_output(MCFQSPI_CS2, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
-		goto fail3;
-	}
-
-	return 0;
-
-fail3:
-	gpio_free(MCFQSPI_CS2);
-fail2:
-	gpio_free(MCFQSPI_CS1);
-fail1:
-	gpio_free(MCFQSPI_CS0);
-fail0:
-	return status;
-}
-
-static void m520x_cs_teardown(struct mcfqspi_cs_control *cs_control)
-{
-	gpio_free(MCFQSPI_CS2);
-	gpio_free(MCFQSPI_CS1);
-	gpio_free(MCFQSPI_CS0);
-}
-
-static void m520x_cs_select(struct mcfqspi_cs_control *cs_control,
-			    u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, cs_high);
-		break;
-	}
-}
-
-static void m520x_cs_deselect(struct mcfqspi_cs_control *cs_control,
-			      u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, !cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, !cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, !cs_high);
-		break;
-	}
-}
-
-static struct mcfqspi_cs_control m520x_cs_control = {
-	.setup                  = m520x_cs_setup,
-	.teardown               = m520x_cs_teardown,
-	.select                 = m520x_cs_select,
-	.deselect               = m520x_cs_deselect,
-};
-
-static struct mcfqspi_platform_data m520x_qspi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 3,
-	.cs_control		= &m520x_cs_control,
-};
-
-static struct platform_device m520x_qspi = {
-	.name			= "mcfqspi",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m520x_qspi_resources),
-	.resource		= m520x_qspi_resources,
-	.dev.platform_data	= &m520x_qspi_data,
-};
-
-static void __init m520x_qspi_init(void)
-{
-	u16 par;
-	/* setup Port QS for QSPI with gpio CS control */
-	writeb(0x3f, MCF_IPSBAR + MCF_GPIO_PAR_QSPI);
-	/* make U1CTS and U2RTS gpio for cs_control */
-	par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
-	par &= 0x00ff;
-	writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
-}
-#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
-
-
-static struct platform_device *m520x_devices[] __initdata = {
-	&m520x_uart,
-	&m520x_fec,
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	&m520x_qspi,
-#endif
-};
-
-/***************************************************************************/
-
-static void __init m520x_uart_init_line(int line, int irq)
-{
-	u16 par;
-	u8 par2;
-
-	switch (line) {
-	case 0:
-		par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
-		par |= MCF_GPIO_PAR_UART_PAR_UTXD0 |
-		       MCF_GPIO_PAR_UART_PAR_URXD0;
-		writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
-		break;
-	case 1:
-		par = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
-		par |= MCF_GPIO_PAR_UART_PAR_UTXD1 |
-		       MCF_GPIO_PAR_UART_PAR_URXD1;
-		writew(par, MCF_IPSBAR + MCF_GPIO_PAR_UART);
-		break;
-	case 2:
-		par2 = readb(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
-		par2 &= ~0x0F;
-		par2 |= MCF_GPIO_PAR_FECI2C_PAR_SCL_UTXD2 |
-			MCF_GPIO_PAR_FECI2C_PAR_SDA_URXD2;
-		writeb(par2, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
-		break;
-	}
-}
-
-static void __init m520x_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m520x_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m520x_uart_init_line(line, m520x_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m520x_fec_init(void)
-{
-	u8 v;
-
-	/* Set multi-function pins to ethernet mode */
-	v = readb(MCF_IPSBAR + MCF_GPIO_PAR_FEC);
-	writeb(v | 0xf0, MCF_IPSBAR + MCF_GPIO_PAR_FEC);
-
-	v = readb(MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
-	writeb(v | 0x0f, MCF_IPSBAR + MCF_GPIO_PAR_FECI2C);
-}
-
-/***************************************************************************/
-
-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 = m520x_cpu_reset;
-	m520x_uarts_init();
-	m520x_fec_init();
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	m520x_qspi_init();
-#endif
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m520x_devices, ARRAY_SIZE(m520x_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/520x/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/520x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/520x/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/520x/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,211 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PIRQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BUSCTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 8,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BE",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 16,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_BE,
-		.podr				= MCFGPIO_PODR_BE,
-		.ppdr				= MCFGPIO_PPDSDR_BE,
-		.setr				= MCFGPIO_PPDSDR_BE,
-		.clrr				= MCFGPIO_PCLRR_BE,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "CS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 25,
-			.ngpio			= 3,
-		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECI2C",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QSPI",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TIMER",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 48,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UART",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_UART,
-		.podr				= MCFGPIO_PODR_UART,
-		.ppdr				= MCFGPIO_PPDSDR_UART,
-		.setr				= MCFGPIO_PPDSDR_UART,
-		.clrr				= MCFGPIO_PCLRR_UART,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FECH,
-		.podr				= MCFGPIO_PODR_FECH,
-		.ppdr				= MCFGPIO_PPDSDR_FECH,
-		.setr				= MCFGPIO_PPDSDR_FECH,
-		.clrr				= MCFGPIO_PCLRR_FECH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FECL,
-		.podr				= MCFGPIO_PODR_FECL,
-		.ppdr				= MCFGPIO_PPDSDR_FECL,
-		.setr				= MCFGPIO_PPDSDR_FECL,
-		.clrr				= MCFGPIO_PCLRR_FECL,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/520x/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/520x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/520x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/520x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#
-# Makefile for the M5208 specific file.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/523x/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/523x/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/523x/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/523x/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,293 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/523x/config.c
- *
- *	Sub-architcture dependant initialization code for the Freescale
- *	523x CPUs.
- *
- *	Copyright (C) 1999-2005, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfqspi.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m523x_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 1,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 2,
-	},
-	{ },
-};
-
-static struct platform_device m523x_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m523x_uart_platform,
-};
-
-static struct resource m523x_fec_resources[] = {
-	{
-		.start		= MCF_MBAR + 0x1000,
-		.end		= MCF_MBAR + 0x1000 + 0x7ff,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= 64 + 23,
-		.end		= 64 + 23,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 27,
-		.end		= 64 + 27,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 29,
-		.end		= 64 + 29,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m523x_fec = {
-	.name			= "fec",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m523x_fec_resources),
-	.resource		= m523x_fec_resources,
-};
-
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-static struct resource m523x_qspi_resources[] = {
-	{
-		.start		= MCFQSPI_IOBASE,
-		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCFINT_VECBASE + MCFINT_QSPI,
-		.end		= MCFINT_VECBASE + MCFINT_QSPI,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-#define MCFQSPI_CS0    91
-#define MCFQSPI_CS1    92
-#define MCFQSPI_CS2    103
-#define MCFQSPI_CS3    99
-
-static int m523x_cs_setup(struct mcfqspi_cs_control *cs_control)
-{
-	int status;
-
-	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
-		goto fail0;
-	}
-	status = gpio_direction_output(MCFQSPI_CS0, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
-		goto fail1;
-	}
-
-	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
-		goto fail1;
-	}
-	status = gpio_direction_output(MCFQSPI_CS1, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
-		goto fail2;
-	}
-
-	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
-		goto fail2;
-	}
-	status = gpio_direction_output(MCFQSPI_CS2, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
-		goto fail3;
-	}
-
-	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
-		goto fail3;
-	}
-	status = gpio_direction_output(MCFQSPI_CS3, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
-		goto fail4;
-	}
-
-	return 0;
-
-fail4:
-	gpio_free(MCFQSPI_CS3);
-fail3:
-	gpio_free(MCFQSPI_CS2);
-fail2:
-	gpio_free(MCFQSPI_CS1);
-fail1:
-	gpio_free(MCFQSPI_CS0);
-fail0:
-	return status;
-}
-
-static void m523x_cs_teardown(struct mcfqspi_cs_control *cs_control)
-{
-	gpio_free(MCFQSPI_CS3);
-	gpio_free(MCFQSPI_CS2);
-	gpio_free(MCFQSPI_CS1);
-	gpio_free(MCFQSPI_CS0);
-}
-
-static void m523x_cs_select(struct mcfqspi_cs_control *cs_control,
-			    u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, cs_high);
-		break;
-	case 3:
-		gpio_set_value(MCFQSPI_CS3, cs_high);
-		break;
-	}
-}
-
-static void m523x_cs_deselect(struct mcfqspi_cs_control *cs_control,
-			      u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, !cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, !cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, !cs_high);
-		break;
-	case 3:
-		gpio_set_value(MCFQSPI_CS3, !cs_high);
-		break;
-	}
-}
-
-static struct mcfqspi_cs_control m523x_cs_control = {
-	.setup                  = m523x_cs_setup,
-	.teardown               = m523x_cs_teardown,
-	.select                 = m523x_cs_select,
-	.deselect               = m523x_cs_deselect,
-};
-
-static struct mcfqspi_platform_data m523x_qspi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 4,
-	.cs_control		= &m523x_cs_control,
-};
-
-static struct platform_device m523x_qspi = {
-	.name			= "mcfqspi",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m523x_qspi_resources),
-	.resource		= m523x_qspi_resources,
-	.dev.platform_data	= &m523x_qspi_data,
-};
-
-static void __init m523x_qspi_init(void)
-{
-	u16 par;
-
-	/* setup QSPS pins for QSPI with gpio CS control */
-	writeb(0x1f, MCFGPIO_PAR_QSPI);
-	/* and CS2 & CS3 as gpio */
-	par = readw(MCFGPIO_PAR_TIMER);
-	par &= 0x3f3f;
-	writew(par, MCFGPIO_PAR_TIMER);
-}
-#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
-
-static struct platform_device *m523x_devices[] __initdata = {
-	&m523x_uart,
-	&m523x_fec,
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	&m523x_qspi,
-#endif
-};
-
-/***************************************************************************/
-
-static void __init m523x_fec_init(void)
-{
-	u16 par;
-	u8 v;
-
-	/* Set multi-function pins to ethernet use */
-	par = readw(MCF_IPSBAR + 0x100082);
-	writew(par | 0xf00, MCF_IPSBAR + 0x100082);
-	v = readb(MCF_IPSBAR + 0x100078);
-	writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
-}
-
-/***************************************************************************/
-
-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)
-{
-	mach_reset = m523x_cpu_reset;
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	m523x_fec_init();
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	m523x_qspi_init();
-#endif
-	platform_add_devices(m523x_devices, ARRAY_SIZE(m523x_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/523x/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/523x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/523x/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/523x/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,284 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PIRQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 1,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "ADDR",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 13,
-			.ngpio			= 3,
-		},
-		.pddr				= MCFGPIO_PDDR_ADDR,
-		.podr				= MCFGPIO_PODR_ADDR,
-		.ppdr				= MCFGPIO_PPDSDR_ADDR,
-		.setr				= MCFGPIO_PPDSDR_ADDR,
-		.clrr				= MCFGPIO_PCLRR_ADDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "DATAH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 16,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_DATAH,
-		.podr				= MCFGPIO_PODR_DATAH,
-		.ppdr				= MCFGPIO_PPDSDR_DATAH,
-		.setr				= MCFGPIO_PPDSDR_DATAH,
-		.clrr				= MCFGPIO_PCLRR_DATAH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "DATAL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 24,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_DATAL,
-		.podr				= MCFGPIO_PODR_DATAL,
-		.ppdr				= MCFGPIO_PPDSDR_DATAL,
-		.setr				= MCFGPIO_PPDSDR_DATAL,
-		.clrr				= MCFGPIO_PCLRR_DATAL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BUSCTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_BS,
-		.podr				= MCFGPIO_PODR_BS,
-		.ppdr				= MCFGPIO_PPDSDR_BS,
-		.setr				= MCFGPIO_PPDSDR_BS,
-		.clrr				= MCFGPIO_PCLRR_BS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "CS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 49,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "SDRAM",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
-			.ngpio			= 6,
-		},
-		.pddr				= MCFGPIO_PDDR_SDRAM,
-		.podr				= MCFGPIO_PODR_SDRAM,
-		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
-		.setr				= MCFGPIO_PPDSDR_SDRAM,
-		.clrr				= MCFGPIO_PCLRR_SDRAM,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECI2C",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UARTH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
-			.ngpio			= 2,
-		},
-		.pddr				= MCFGPIO_PDDR_UARTH,
-		.podr				= MCFGPIO_PODR_UARTH,
-		.ppdr				= MCFGPIO_PPDSDR_UARTH,
-		.setr				= MCFGPIO_PPDSDR_UARTH,
-		.clrr				= MCFGPIO_PCLRR_UARTH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UARTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 80,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_UARTL,
-		.podr				= MCFGPIO_PODR_UARTL,
-		.ppdr				= MCFGPIO_PPDSDR_UARTL,
-		.setr				= MCFGPIO_PPDSDR_UARTL,
-		.clrr				= MCFGPIO_PCLRR_UARTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QSPI",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 88,
-			.ngpio			= 5,
-		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TIMER",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 96,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "ETPU",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 104,
-			.ngpio			= 3,
-		},
-		.pddr				= MCFGPIO_PDDR_ETPU,
-		.podr				= MCFGPIO_PODR_ETPU,
-		.ppdr				= MCFGPIO_PPDSDR_ETPU,
-		.setr				= MCFGPIO_PPDSDR_ETPU,
-		.clrr				= MCFGPIO_PCLRR_ETPU,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/523x/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/523x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/523x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/523x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,17 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,330 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5249/config.c
- *
- *	Copyright (C) 2002, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfqspi.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5249_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
-	},
-	{ },
-};
-
-static struct platform_device m5249_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5249_uart_platform,
-};
-
-#ifdef CONFIG_M5249C3
-
-static struct resource m5249_smc91x_resources[] = {
-	{
-		.start		= 0xe0000300,
-		.end		= 0xe0000300 + 0x100,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCFINTC2_GPIOIRQ6,
-		.end		= MCFINTC2_GPIOIRQ6,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m5249_smc91x = {
-	.name			= "smc91x",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m5249_smc91x_resources),
-	.resource		= m5249_smc91x_resources,
-};
-
-#endif /* CONFIG_M5249C3 */
-
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-static struct resource m5249_qspi_resources[] = {
-	{
-		.start		= MCFQSPI_IOBASE,
-		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCF_IRQ_QSPI,
-		.end		= MCF_IRQ_QSPI,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-#define MCFQSPI_CS0    29
-#define MCFQSPI_CS1    24
-#define MCFQSPI_CS2    21
-#define MCFQSPI_CS3    22
-
-static int m5249_cs_setup(struct mcfqspi_cs_control *cs_control)
-{
-	int status;
-
-	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
-		goto fail0;
-	}
-	status = gpio_direction_output(MCFQSPI_CS0, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
-		goto fail1;
-	}
-
-	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
-		goto fail1;
-	}
-	status = gpio_direction_output(MCFQSPI_CS1, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
-		goto fail2;
-	}
-
-	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
-		goto fail2;
-	}
-	status = gpio_direction_output(MCFQSPI_CS2, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
-		goto fail3;
-	}
-
-	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
-		goto fail3;
-	}
-	status = gpio_direction_output(MCFQSPI_CS3, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
-		goto fail4;
-	}
-
-	return 0;
-
-fail4:
-	gpio_free(MCFQSPI_CS3);
-fail3:
-	gpio_free(MCFQSPI_CS2);
-fail2:
-	gpio_free(MCFQSPI_CS1);
-fail1:
-	gpio_free(MCFQSPI_CS0);
-fail0:
-	return status;
-}
-
-static void m5249_cs_teardown(struct mcfqspi_cs_control *cs_control)
-{
-	gpio_free(MCFQSPI_CS3);
-	gpio_free(MCFQSPI_CS2);
-	gpio_free(MCFQSPI_CS1);
-	gpio_free(MCFQSPI_CS0);
-}
-
-static void m5249_cs_select(struct mcfqspi_cs_control *cs_control,
-			    u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, cs_high);
-		break;
-	case 3:
-		gpio_set_value(MCFQSPI_CS3, cs_high);
-		break;
-	}
-}
-
-static void m5249_cs_deselect(struct mcfqspi_cs_control *cs_control,
-			      u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, !cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, !cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, !cs_high);
-		break;
-	case 3:
-		gpio_set_value(MCFQSPI_CS3, !cs_high);
-		break;
-	}
-}
-
-static struct mcfqspi_cs_control m5249_cs_control = {
-	.setup                  = m5249_cs_setup,
-	.teardown               = m5249_cs_teardown,
-	.select                 = m5249_cs_select,
-	.deselect               = m5249_cs_deselect,
-};
-
-static struct mcfqspi_platform_data m5249_qspi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 4,
-	.cs_control		= &m5249_cs_control,
-};
-
-static struct platform_device m5249_qspi = {
-	.name			= "mcfqspi",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m5249_qspi_resources),
-	.resource		= m5249_qspi_resources,
-	.dev.platform_data	= &m5249_qspi_data,
-};
-
-static void __init m5249_qspi_init(void)
-{
-	/* QSPI irq setup */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL4 | MCFSIM_ICR_PRI0,
-	       MCF_MBAR + MCFSIM_QSPIICR);
-	mcf_mapirq2imr(MCF_IRQ_QSPI, MCFINTC_QSPI);
-}
-#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
-
-
-static struct platform_device *m5249_devices[] __initdata = {
-	&m5249_uart,
-#ifdef CONFIG_M5249C3
-	&m5249_smc91x,
-#endif
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	&m5249_qspi,
-#endif
-};
-
-/***************************************************************************/
-
-static void __init m5249_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
-		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART0);
-	} else if (line == 1) {
-		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
-		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART1);
-	}
-}
-
-static void __init m5249_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5249_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5249_uart_init_line(line, m5249_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-#ifdef CONFIG_M5249C3
-
-static void __init m5249_smc91x_init(void)
-{
-	u32  gpio;
-
-	/* Set the GPIO line as interrupt source for smc91x device */
-	gpio = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-	writel(gpio | 0x40, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-
-	gpio = readl(MCF_MBAR2 + MCFSIM2_INTLEVEL5);
-	writel(gpio | 0x04000000, MCF_MBAR2 + MCFSIM2_INTLEVEL5);
-}
-
-#endif /* CONFIG_M5249C3 */
-
-/***************************************************************************/
-
-static void __init m5249_timers_init(void)
-{
-	/* Timer1 is always used as system timer */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER1ICR);
-	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
-	/* Timer2 is to be used as a high speed profile timer  */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER2ICR);
-	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-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)
-{
-	mach_reset = m5249_cpu_reset;
-	m5249_timers_init();
-	m5249_uarts_init();
-#ifdef CONFIG_M5249C3
-	m5249_smc91x_init();
-#endif
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	m5249_qspi_init();
-#endif
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m5249_devices, ARRAY_SIZE(m5249_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,65 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "GPIO0",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 32,
-		},
-		.pddr				= MCFSIM2_GPIOENABLE,
-		.podr				= MCFSIM2_GPIOWRITE,
-		.ppdr				= MCFSIM2_GPIOREAD,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "GPIO1",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 32,
-			.ngpio			= 32,
-		},
-		.pddr				= MCFSIM2_GPIO1ENABLE,
-		.podr				= MCFSIM2_GPIO1WRITE,
-		.ppdr				= MCFSIM2_GPIO1READ,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/intc2.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/intc2.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/intc2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/intc2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-/*
- * intc2.c  -- support for the 2nd INTC controller of the 5249
- *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-static void intc2_irq_gpio_mask(unsigned int irq)
-{
-	u32 imr;
-	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-	imr &= ~(0x1 << (irq - MCFINTC2_GPIOIRQ0));
-	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-}
-
-static void intc2_irq_gpio_unmask(unsigned int irq)
-{
-	u32 imr;
-	imr = readl(MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-	imr |= (0x1 << (irq - MCFINTC2_GPIOIRQ0));
-	writel(imr, MCF_MBAR2 + MCFSIM2_GPIOINTENABLE);
-}
-
-static void intc2_irq_gpio_ack(unsigned int irq)
-{
-	writel(0x1 << (irq - MCFINTC2_GPIOIRQ0), MCF_MBAR2 + MCFSIM2_GPIOINTCLEAR);
-}
-
-static struct irq_chip intc2_irq_gpio_chip = {
-	.name		= "CF-INTC2",
-	.mask		= intc2_irq_gpio_mask,
-	.unmask		= intc2_irq_gpio_unmask,
-	.ack		= intc2_irq_gpio_ack,
-};
-
-static int __init mcf_intc2_init(void)
-{
-	int irq;
-
-	/* GPIO interrupt sources */
-	for (irq = MCFINTC2_GPIOIRQ0; (irq <= MCFINTC2_GPIOIRQ7); irq++) {
-		irq_desc[irq].chip = &intc2_irq_gpio_chip;
-		set_irq_handler(irq, handle_edge_irq);
-	}
-
-	return 0;
-}
-
-arch_initcall(mcf_intc2_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5249/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5249/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o intc2.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,176 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5272/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2001-2002, SnapGear Inc. (www.snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/phy.h>
-#include <linux/phy_fixed.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-
-/***************************************************************************/
-
-/*
- *	Some platforms need software versions of the GPIO data registers.
- */
-unsigned short ppdata;
-unsigned char ledbank = 0xff;
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5272_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= MCF_IRQ_UART1,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= MCF_IRQ_UART2,
-	},
-	{ },
-};
-
-static struct platform_device m5272_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5272_uart_platform,
-};
-
-static struct resource m5272_fec_resources[] = {
-	{
-		.start		= MCF_MBAR + 0x840,
-		.end		= MCF_MBAR + 0x840 + 0x1cf,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCF_IRQ_ERX,
-		.end		= MCF_IRQ_ERX,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= MCF_IRQ_ETX,
-		.end		= MCF_IRQ_ETX,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= MCF_IRQ_ENTC,
-		.end		= MCF_IRQ_ENTC,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m5272_fec = {
-	.name			= "fec",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m5272_fec_resources),
-	.resource		= m5272_fec_resources,
-};
-
-static struct platform_device *m5272_devices[] __initdata = {
-	&m5272_uart,
-	&m5272_fec,
-};
-
-/***************************************************************************/
-
-static void __init m5272_uart_init_line(int line, int irq)
-{
-	u32 v;
-
-	if ((line >= 0) && (line < 2)) {
-		/* Enable the output lines for the serial ports */
-		v = readl(MCF_MBAR + MCFSIM_PBCNT);
-		v = (v & ~0x000000ff) | 0x00000055;
-		writel(v, MCF_MBAR + MCFSIM_PBCNT);
-
-		v = readl(MCF_MBAR + MCFSIM_PDCNT);
-		v = (v & ~0x000003fc) | 0x000002a8;
-		writel(v, MCF_MBAR + MCFSIM_PDCNT);
-	}
-}
-
-static void __init m5272_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5272_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5272_uart_init_line(line, m5272_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-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)
-	volatile unsigned char	*pivrp;
-
-	/* Set base of device vectors to be 64 */
-	pivrp = (volatile unsigned char *) (MCF_MBAR + MCFSIM_PIVR);
-	*pivrp = 0x40;
-#endif
-
-#if defined(CONFIG_NETtel) || defined(CONFIG_SCALES)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0xf0004000, size);
-	commandp[size-1] = 0;
-#elif defined(CONFIG_CANCam)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0xf0010000, size);
-	commandp[size-1] = 0;
-#endif
-
-	mach_reset = m5272_cpu_reset;
-}
-
-/***************************************************************************/
-
-/*
- * Some 5272 based boards have the FEC ethernet diectly connected to
- * an ethernet switch. In this case we need to use the fixed phy type,
- * and we need to declare it early in boot.
- */
-static struct fixed_phy_status nettel_fixed_phy_status __initdata = {
-	.link	= 1,
-	.speed	= 100,
-	.duplex	= 0,
-};
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	m5272_uarts_init();
-	fixed_phy_add(PHY_POLL, 0, &nettel_fixed_phy_status);
-	platform_add_devices(m5272_devices, ARRAY_SIZE(m5272_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PA",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 16,
-		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "PB",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 16,
-			.ngpio			= 16,
-		},
-		.pddr				= MCFSIM_PBDDR,
-		.podr				= MCFSIM_PBDAT,
-		.ppdr				= MCFSIM_PBDAT,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "PC",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 32,
-			.ngpio			= 16,
-		},
-		.pddr				= MCFSIM_PCDDR,
-		.podr				= MCFSIM_PCDAT,
-		.ppdr				= MCFSIM_PCDAT,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/intc.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/intc.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/intc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/intc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,182 +0,0 @@
-/*
- * intc.c  --  interrupt controller or ColdFire 5272 SoC
- *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/traps.h>
-
-/*
- * The 5272 ColdFire interrupt controller is nothing like any other
- * ColdFire interrupt controller - it truly is completely different.
- * Given its age it is unlikely to be used on any other ColdFire CPU.
- */
-
-/*
- * The masking and priproty setting of interrupts on the 5272 is done
- * via a set of 4 "Interrupt Controller Registers" (ICR). There is a
- * loose mapping of vector number to register and internal bits, but
- * a table is the easiest and quickest way to map them.
- *
- * Note that the external interrupts are edge triggered (unlike the
- * internal interrupt sources which are level triggered). Which means
- * they also need acknowledgeing via acknowledge bits.
- */
-struct irqmap {
-	unsigned char	icr;
-	unsigned char	index;
-	unsigned char	ack;
-};
-
-static struct irqmap intc_irqmap[MCFINT_VECMAX - MCFINT_VECBASE] = {
-	/*MCF_IRQ_SPURIOUS*/	{ .icr = 0,           .index = 0,  .ack = 0, },
-	/*MCF_IRQ_EINT1*/	{ .icr = MCFSIM_ICR1, .index = 28, .ack = 1, },
-	/*MCF_IRQ_EINT2*/	{ .icr = MCFSIM_ICR1, .index = 24, .ack = 1, },
-	/*MCF_IRQ_EINT3*/	{ .icr = MCFSIM_ICR1, .index = 20, .ack = 1, },
-	/*MCF_IRQ_EINT4*/	{ .icr = MCFSIM_ICR1, .index = 16, .ack = 1, },
-	/*MCF_IRQ_TIMER1*/	{ .icr = MCFSIM_ICR1, .index = 12, .ack = 0, },
-	/*MCF_IRQ_TIMER2*/	{ .icr = MCFSIM_ICR1, .index = 8,  .ack = 0, },
-	/*MCF_IRQ_TIMER3*/	{ .icr = MCFSIM_ICR1, .index = 4,  .ack = 0, },
-	/*MCF_IRQ_TIMER4*/	{ .icr = MCFSIM_ICR1, .index = 0,  .ack = 0, },
-	/*MCF_IRQ_UART1*/	{ .icr = MCFSIM_ICR2, .index = 28, .ack = 0, },
-	/*MCF_IRQ_UART2*/	{ .icr = MCFSIM_ICR2, .index = 24, .ack = 0, },
-	/*MCF_IRQ_PLIP*/	{ .icr = MCFSIM_ICR2, .index = 20, .ack = 0, },
-	/*MCF_IRQ_PLIA*/	{ .icr = MCFSIM_ICR2, .index = 16, .ack = 0, },
-	/*MCF_IRQ_USB0*/	{ .icr = MCFSIM_ICR2, .index = 12, .ack = 0, },
-	/*MCF_IRQ_USB1*/	{ .icr = MCFSIM_ICR2, .index = 8,  .ack = 0, },
-	/*MCF_IRQ_USB2*/	{ .icr = MCFSIM_ICR2, .index = 4,  .ack = 0, },
-	/*MCF_IRQ_USB3*/	{ .icr = MCFSIM_ICR2, .index = 0,  .ack = 0, },
-	/*MCF_IRQ_USB4*/	{ .icr = MCFSIM_ICR3, .index = 28, .ack = 0, },
-	/*MCF_IRQ_USB5*/	{ .icr = MCFSIM_ICR3, .index = 24, .ack = 0, },
-	/*MCF_IRQ_USB6*/	{ .icr = MCFSIM_ICR3, .index = 20, .ack = 0, },
-	/*MCF_IRQ_USB7*/	{ .icr = MCFSIM_ICR3, .index = 16, .ack = 0, },
-	/*MCF_IRQ_DMA*/		{ .icr = MCFSIM_ICR3, .index = 12, .ack = 0, },
-	/*MCF_IRQ_ERX*/		{ .icr = MCFSIM_ICR3, .index = 8,  .ack = 0, },
-	/*MCF_IRQ_ETX*/		{ .icr = MCFSIM_ICR3, .index = 4,  .ack = 0, },
-	/*MCF_IRQ_ENTC*/	{ .icr = MCFSIM_ICR3, .index = 0,  .ack = 0, },
-	/*MCF_IRQ_QSPI*/	{ .icr = MCFSIM_ICR4, .index = 28, .ack = 0, },
-	/*MCF_IRQ_EINT5*/	{ .icr = MCFSIM_ICR4, .index = 24, .ack = 1, },
-	/*MCF_IRQ_EINT6*/	{ .icr = MCFSIM_ICR4, .index = 20, .ack = 1, },
-	/*MCF_IRQ_SWTO*/	{ .icr = MCFSIM_ICR4, .index = 16, .ack = 0, },
-};
-
-/*
- * The act of masking the interrupt also has a side effect of 'ack'ing
- * an interrupt on this irq (for the external irqs). So this mask function
- * is also an ack_mask function.
- */
-static void intc_irq_mask(unsigned int irq)
-{
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
-		u32 v;
-		irq -= MCFINT_VECBASE;
-		v = 0x8 << intc_irqmap[irq].index;
-		writel(v, MCF_MBAR + intc_irqmap[irq].icr);
-	}
-}
-
-static void intc_irq_unmask(unsigned int irq)
-{
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
-		u32 v;
-		irq -= MCFINT_VECBASE;
-		v = 0xd << intc_irqmap[irq].index;
-		writel(v, MCF_MBAR + intc_irqmap[irq].icr);
-	}
-}
-
-static void intc_irq_ack(unsigned int irq)
-{
-	/* Only external interrupts are acked */
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
-		irq -= MCFINT_VECBASE;
-		if (intc_irqmap[irq].ack) {
-			u32 v;
-			v = readl(MCF_MBAR + intc_irqmap[irq].icr);
-			v &= (0x7 << intc_irqmap[irq].index);
-			v |= (0x8 << intc_irqmap[irq].index);
-			writel(v, MCF_MBAR + intc_irqmap[irq].icr);
-		}
-	}
-}
-
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
-{
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX)) {
-		irq -= MCFINT_VECBASE;
-		if (intc_irqmap[irq].ack) {
-			u32 v;
-			v = readl(MCF_MBAR + MCFSIM_PITR);
-			if (type == IRQ_TYPE_EDGE_FALLING)
-				v &= ~(0x1 << (32 - irq));
-			else
-				v |= (0x1 << (32 - irq));
-			writel(v, MCF_MBAR + MCFSIM_PITR);
-		}
-	}
-	return 0;
-}
-
-/*
- * Simple flow handler to deal with the external edge triggered interrupts.
- * We need to be careful with the masking/acking due to the side effects
- * of masking an interrupt.
- */
-static void intc_external_irq(unsigned int irq, struct irq_desc *desc)
-{
-	kstat_incr_irqs_this_cpu(irq, desc);
-	desc->status |= IRQ_INPROGRESS;
-	desc->chip->ack(irq);
-	handle_IRQ_event(irq, desc->action);
-	desc->status &= ~IRQ_INPROGRESS;
-}
-
-static struct irq_chip intc_irq_chip = {
-	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.mask_ack	= intc_irq_mask,
-	.ack		= intc_irq_ack,
-	.set_type	= intc_irq_set_type,
-};
-
-void __init init_IRQ(void)
-{
-	int irq, edge;
-
-	init_vectors();
-
-	/* Mask all interrupt sources */
-	writel(0x88888888, MCF_MBAR + MCFSIM_ICR1);
-	writel(0x88888888, MCF_MBAR + MCFSIM_ICR2);
-	writel(0x88888888, MCF_MBAR + MCFSIM_ICR3);
-	writel(0x88888888, MCF_MBAR + MCFSIM_ICR4);
-
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		set_irq_chip(irq, &intc_irq_chip);
-		edge = 0;
-		if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECMAX))
-			edge = intc_irqmap[irq - MCFINT_VECBASE].ack;
-		if (edge) {
-			set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
-			set_irq_handler(irq, intc_external_irq);
-		} else {
-			set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-			set_irq_handler(irq, handle_level_irq);
-		}
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5272/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5272/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o intc.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/527x/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/527x/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/527x/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/527x/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,384 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/527x/config.c
- *
- *	Sub-architcture dependant initialization code for the Freescale
- *	5270/5271 CPUs.
- *
- *	Copyright (C) 1999-2004, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfqspi.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m527x_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= MCFINT_VECBASE + MCFINT_UART1,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
-		.irq		= MCFINT_VECBASE + MCFINT_UART2,
-	},
-	{ },
-};
-
-static struct platform_device m527x_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m527x_uart_platform,
-};
-
-static struct resource m527x_fec0_resources[] = {
-	{
-		.start		= MCF_MBAR + 0x1000,
-		.end		= MCF_MBAR + 0x1000 + 0x7ff,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= 64 + 23,
-		.end		= 64 + 23,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 27,
-		.end		= 64 + 27,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 29,
-		.end		= 64 + 29,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource m527x_fec1_resources[] = {
-	{
-		.start		= MCF_MBAR + 0x1800,
-		.end		= MCF_MBAR + 0x1800 + 0x7ff,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= 128 + 23,
-		.end		= 128 + 23,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 128 + 27,
-		.end		= 128 + 27,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 128 + 29,
-		.end		= 128 + 29,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m527x_fec[] = {
-	{
-		.name		= "fec",
-		.id		= 0,
-		.num_resources	= ARRAY_SIZE(m527x_fec0_resources),
-		.resource	= m527x_fec0_resources,
-	},
-	{
-		.name		= "fec",
-		.id		= 1,
-		.num_resources	= ARRAY_SIZE(m527x_fec1_resources),
-		.resource	= m527x_fec1_resources,
-	},
-};
-
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-static struct resource m527x_qspi_resources[] = {
-	{
-		.start		= MCFQSPI_IOBASE,
-		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCFINT_VECBASE + MCFINT_QSPI,
-		.end		= MCFINT_VECBASE + MCFINT_QSPI,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-#if defined(CONFIG_M5271)
-#define MCFQSPI_CS0    91
-#define MCFQSPI_CS1    92
-#define MCFQSPI_CS2    99
-#define MCFQSPI_CS3    103
-#elif defined(CONFIG_M5275)
-#define MCFQSPI_CS0    59
-#define MCFQSPI_CS1    60
-#define MCFQSPI_CS2    61
-#define MCFQSPI_CS3    62
-#endif
-
-static int m527x_cs_setup(struct mcfqspi_cs_control *cs_control)
-{
-	int status;
-
-	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
-		goto fail0;
-	}
-	status = gpio_direction_output(MCFQSPI_CS0, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
-		goto fail1;
-	}
-
-	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
-		goto fail1;
-	}
-	status = gpio_direction_output(MCFQSPI_CS1, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
-		goto fail2;
-	}
-
-	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
-		goto fail2;
-	}
-	status = gpio_direction_output(MCFQSPI_CS2, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
-		goto fail3;
-	}
-
-	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
-		goto fail3;
-	}
-	status = gpio_direction_output(MCFQSPI_CS3, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
-		goto fail4;
-	}
-
-	return 0;
-
-fail4:
-	gpio_free(MCFQSPI_CS3);
-fail3:
-	gpio_free(MCFQSPI_CS2);
-fail2:
-	gpio_free(MCFQSPI_CS1);
-fail1:
-	gpio_free(MCFQSPI_CS0);
-fail0:
-	return status;
-}
-
-static void m527x_cs_teardown(struct mcfqspi_cs_control *cs_control)
-{
-	gpio_free(MCFQSPI_CS3);
-	gpio_free(MCFQSPI_CS2);
-	gpio_free(MCFQSPI_CS1);
-	gpio_free(MCFQSPI_CS0);
-}
-
-static void m527x_cs_select(struct mcfqspi_cs_control *cs_control,
-			    u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, cs_high);
-		break;
-	case 3:
-		gpio_set_value(MCFQSPI_CS3, cs_high);
-		break;
-	}
-}
-
-static void m527x_cs_deselect(struct mcfqspi_cs_control *cs_control,
-			      u8 chip_select, bool cs_high)
-{
-	switch (chip_select) {
-	case 0:
-		gpio_set_value(MCFQSPI_CS0, !cs_high);
-		break;
-	case 1:
-		gpio_set_value(MCFQSPI_CS1, !cs_high);
-		break;
-	case 2:
-		gpio_set_value(MCFQSPI_CS2, !cs_high);
-		break;
-	case 3:
-		gpio_set_value(MCFQSPI_CS3, !cs_high);
-		break;
-	}
-}
-
-static struct mcfqspi_cs_control m527x_cs_control = {
-	.setup                  = m527x_cs_setup,
-	.teardown               = m527x_cs_teardown,
-	.select                 = m527x_cs_select,
-	.deselect               = m527x_cs_deselect,
-};
-
-static struct mcfqspi_platform_data m527x_qspi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 4,
-	.cs_control		= &m527x_cs_control,
-};
-
-static struct platform_device m527x_qspi = {
-	.name			= "mcfqspi",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m527x_qspi_resources),
-	.resource		= m527x_qspi_resources,
-	.dev.platform_data	= &m527x_qspi_data,
-};
-
-static void __init m527x_qspi_init(void)
-{
-#if defined(CONFIG_M5271)
-	u16 par;
-
-	/* setup QSPS pins for QSPI with gpio CS control */
-	writeb(0x1f, MCFGPIO_PAR_QSPI);
-	/* and CS2 & CS3 as gpio */
-	par = readw(MCFGPIO_PAR_TIMER);
-	par &= 0x3f3f;
-	writew(par, MCFGPIO_PAR_TIMER);
-#elif defined(CONFIG_M5275)
-	/* setup QSPS pins for QSPI with gpio CS control */
-	writew(0x003e, MCFGPIO_PAR_QSPI);
-#endif
-}
-#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
-
-static struct platform_device *m527x_devices[] __initdata = {
-	&m527x_uart,
-	&m527x_fec[0],
-#ifdef CONFIG_FEC2
-	&m527x_fec[1],
-#endif
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	&m527x_qspi,
-#endif
-};
-
-/***************************************************************************/
-
-static void __init m527x_uart_init_line(int line, int irq)
-{
-	u16 sepmask;
-
-	if ((line < 0) || (line > 2))
-		return;
-
-	/*
-	 * External Pin Mask Setting & Enable External Pin for Interface
-	 */
-	sepmask = readw(MCF_IPSBAR + MCF_GPIO_PAR_UART);
-	if (line == 0)
-		sepmask |= UART0_ENABLE_MASK;
-	else if (line == 1)
-		sepmask |= UART1_ENABLE_MASK;
-	else if (line == 2)
-		sepmask |= UART2_ENABLE_MASK;
-	writew(sepmask, MCF_IPSBAR + MCF_GPIO_PAR_UART);
-}
-
-static void __init m527x_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m527x_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m527x_uart_init_line(line, m527x_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m527x_fec_init(void)
-{
-	u16 par;
-	u8 v;
-
-	/* Set multi-function pins to ethernet mode for fec0 */
-#if defined(CONFIG_M5271)
-	v = readb(MCF_IPSBAR + 0x100047);
-	writeb(v | 0xf0, MCF_IPSBAR + 0x100047);
-#else
-	par = readw(MCF_IPSBAR + 0x100082);
-	writew(par | 0xf00, MCF_IPSBAR + 0x100082);
-	v = readb(MCF_IPSBAR + 0x100078);
-	writeb(v | 0xc0, MCF_IPSBAR + 0x100078);
-#endif
-
-#ifdef CONFIG_FEC2
-	/* Set multi-function pins to ethernet mode for fec1 */
-	par = readw(MCF_IPSBAR + 0x100082);
-	writew(par | 0xa0, MCF_IPSBAR + 0x100082);
-	v = readb(MCF_IPSBAR + 0x100079);
-	writeb(v | 0xc0, MCF_IPSBAR + 0x100079);
-#endif
-}
-
-/***************************************************************************/
-
-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)
-{
-	mach_reset = m527x_cpu_reset;
-	m527x_uarts_init();
-	m527x_fec_init();
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	m527x_qspi_init();
-#endif
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m527x_devices, ARRAY_SIZE(m527x_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/527x/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/527x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/527x/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/527x/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,609 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-#if defined(CONFIG_M5271)
-	{
-		.gpio_chip			= {
-			.label			= "PIRQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 1,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "ADDR",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 13,
-			.ngpio			= 3,
-		},
-		.pddr				= MCFGPIO_PDDR_ADDR,
-		.podr				= MCFGPIO_PODR_ADDR,
-		.ppdr				= MCFGPIO_PPDSDR_ADDR,
-		.setr				= MCFGPIO_PPDSDR_ADDR,
-		.clrr				= MCFGPIO_PCLRR_ADDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "DATAH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 16,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_DATAH,
-		.podr				= MCFGPIO_PODR_DATAH,
-		.ppdr				= MCFGPIO_PPDSDR_DATAH,
-		.setr				= MCFGPIO_PPDSDR_DATAH,
-		.clrr				= MCFGPIO_PCLRR_DATAH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "DATAL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 24,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_DATAL,
-		.podr				= MCFGPIO_PODR_DATAL,
-		.ppdr				= MCFGPIO_PPDSDR_DATAL,
-		.setr				= MCFGPIO_PPDSDR_DATAL,
-		.clrr				= MCFGPIO_PCLRR_DATAL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BUSCTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_BS,
-		.podr				= MCFGPIO_PODR_BS,
-		.ppdr				= MCFGPIO_PPDSDR_BS,
-		.setr				= MCFGPIO_PPDSDR_BS,
-		.clrr				= MCFGPIO_PCLRR_BS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "CS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 49,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "SDRAM",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
-			.ngpio			= 6,
-		},
-		.pddr				= MCFGPIO_PDDR_SDRAM,
-		.podr				= MCFGPIO_PODR_SDRAM,
-		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
-		.setr				= MCFGPIO_PPDSDR_SDRAM,
-		.clrr				= MCFGPIO_PCLRR_SDRAM,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECI2C",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UARTH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
-			.ngpio			= 2,
-		},
-		.pddr				= MCFGPIO_PDDR_UARTH,
-		.podr				= MCFGPIO_PODR_UARTH,
-		.ppdr				= MCFGPIO_PPDSDR_UARTH,
-		.setr				= MCFGPIO_PPDSDR_UARTH,
-		.clrr				= MCFGPIO_PCLRR_UARTH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UARTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 80,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_UARTL,
-		.podr				= MCFGPIO_PODR_UARTL,
-		.ppdr				= MCFGPIO_PPDSDR_UARTL,
-		.setr				= MCFGPIO_PPDSDR_UARTL,
-		.clrr				= MCFGPIO_PCLRR_UARTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QSPI",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 88,
-			.ngpio			= 5,
-		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TIMER",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 96,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
-	},
-#elif defined(CONFIG_M5275)
-	{
-		.gpio_chip			= {
-			.label			= "PIRQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 1,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BUSCTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 8,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "ADDR",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 21,
-			.ngpio			= 3,
-		},
-		.pddr				= MCFGPIO_PDDR_ADDR,
-		.podr				= MCFGPIO_PODR_ADDR,
-		.ppdr				= MCFGPIO_PPDSDR_ADDR,
-		.setr				= MCFGPIO_PPDSDR_ADDR,
-		.clrr				= MCFGPIO_PCLRR_ADDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "CS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 25,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FEC0H",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FEC0H,
-		.podr				= MCFGPIO_PODR_FEC0H,
-		.ppdr				= MCFGPIO_PPDSDR_FEC0H,
-		.setr				= MCFGPIO_PPDSDR_FEC0H,
-		.clrr				= MCFGPIO_PCLRR_FEC0H,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FEC0L",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FEC0L,
-		.podr				= MCFGPIO_PODR_FEC0L,
-		.ppdr				= MCFGPIO_PPDSDR_FEC0L,
-		.setr				= MCFGPIO_PPDSDR_FEC0L,
-		.clrr				= MCFGPIO_PCLRR_FEC0L,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECI2C",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 48,
-			.ngpio			= 6,
-		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QSPI",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "SDRAM",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_SDRAM,
-		.podr				= MCFGPIO_PODR_SDRAM,
-		.ppdr				= MCFGPIO_PPDSDR_SDRAM,
-		.setr				= MCFGPIO_PPDSDR_SDRAM,
-		.clrr				= MCFGPIO_PCLRR_SDRAM,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TIMERH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_TIMERH,
-		.podr				= MCFGPIO_PODR_TIMERH,
-		.ppdr				= MCFGPIO_PPDSDR_TIMERH,
-		.setr				= MCFGPIO_PPDSDR_TIMERH,
-		.clrr				= MCFGPIO_PCLRR_TIMERH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TIMERL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 80,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_TIMERL,
-		.podr				= MCFGPIO_PODR_TIMERL,
-		.ppdr				= MCFGPIO_PPDSDR_TIMERL,
-		.setr				= MCFGPIO_PPDSDR_TIMERL,
-		.clrr				= MCFGPIO_PCLRR_TIMERL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UARTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 88,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_UARTL,
-		.podr				= MCFGPIO_PODR_UARTL,
-		.ppdr				= MCFGPIO_PPDSDR_UARTL,
-		.setr				= MCFGPIO_PPDSDR_UARTL,
-		.clrr				= MCFGPIO_PCLRR_UARTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FEC1H",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 96,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FEC1H,
-		.podr				= MCFGPIO_PODR_FEC1H,
-		.ppdr				= MCFGPIO_PPDSDR_FEC1H,
-		.setr				= MCFGPIO_PPDSDR_FEC1H,
-		.clrr				= MCFGPIO_PCLRR_FEC1H,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FEC1L",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 104,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FEC1L,
-		.podr				= MCFGPIO_PODR_FEC1L,
-		.ppdr				= MCFGPIO_PPDSDR_FEC1L,
-		.setr				= MCFGPIO_PPDSDR_FEC1L,
-		.clrr				= MCFGPIO_PCLRR_FEC1L,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 114,
-			.ngpio			= 2,
-		},
-		.pddr				= MCFGPIO_PDDR_BS,
-		.podr				= MCFGPIO_PODR_BS,
-		.ppdr				= MCFGPIO_PPDSDR_BS,
-		.setr				= MCFGPIO_PPDSDR_BS,
-		.clrr				= MCFGPIO_PCLRR_BS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "IRQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 121,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFGPIO_PDDR_IRQ,
-		.podr				= MCFGPIO_PODR_IRQ,
-		.ppdr				= MCFGPIO_PPDSDR_IRQ,
-		.setr				= MCFGPIO_PPDSDR_IRQ,
-		.clrr				= MCFGPIO_PCLRR_IRQ,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "USBH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 128,
-			.ngpio			= 1,
-		},
-		.pddr				= MCFGPIO_PDDR_USBH,
-		.podr				= MCFGPIO_PODR_USBH,
-		.ppdr				= MCFGPIO_PPDSDR_USBH,
-		.setr				= MCFGPIO_PPDSDR_USBH,
-		.clrr				= MCFGPIO_PCLRR_USBH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "USBL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 136,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_USBL,
-		.podr				= MCFGPIO_PODR_USBL,
-		.ppdr				= MCFGPIO_PPDSDR_USBL,
-		.setr				= MCFGPIO_PPDSDR_USBL,
-		.clrr				= MCFGPIO_PCLRR_USBL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UARTH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 144,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_UARTH,
-		.podr				= MCFGPIO_PODR_UARTH,
-		.ppdr				= MCFGPIO_PPDSDR_UARTH,
-		.setr				= MCFGPIO_PPDSDR_UARTH,
-		.clrr				= MCFGPIO_PCLRR_UARTH,
-	},
-#endif
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/527x/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/527x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/527x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/527x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/528x/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/528x/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/528x/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/528x/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,320 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/528x/config.c
- *
- *	Sub-architcture dependant initialization code for the Freescale
- *	5280, 5281 and 5282 CPUs.
- *
- *	Copyright (C) 1999-2003, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2001-2003, SnapGear Inc. (www.snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfqspi.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m528x_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 1,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE3,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0 + 2,
-	},
-	{ },
-};
-
-static struct platform_device m528x_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m528x_uart_platform,
-};
-
-static struct resource m528x_fec_resources[] = {
-	{
-		.start		= MCF_MBAR + 0x1000,
-		.end		= MCF_MBAR + 0x1000 + 0x7ff,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= 64 + 23,
-		.end		= 64 + 23,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 27,
-		.end		= 64 + 27,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 29,
-		.end		= 64 + 29,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m528x_fec = {
-	.name			= "fec",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m528x_fec_resources),
-	.resource		= m528x_fec_resources,
-};
-
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-static struct resource m528x_qspi_resources[] = {
-	{
-		.start		= MCFQSPI_IOBASE,
-		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCFINT_VECBASE + MCFINT_QSPI,
-		.end		= MCFINT_VECBASE + MCFINT_QSPI,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-#define MCFQSPI_CS0    147
-#define MCFQSPI_CS1    148
-#define MCFQSPI_CS2    149
-#define MCFQSPI_CS3    150
-
-static int m528x_cs_setup(struct mcfqspi_cs_control *cs_control)
-{
-	int status;
-
-	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
-		goto fail0;
-	}
-	status = gpio_direction_output(MCFQSPI_CS0, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
-		goto fail1;
-	}
-
-	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
-		goto fail1;
-	}
-	status = gpio_direction_output(MCFQSPI_CS1, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
-		goto fail2;
-	}
-
-	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
-		goto fail2;
-	}
-	status = gpio_direction_output(MCFQSPI_CS2, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
-		goto fail3;
-	}
-
-	status = gpio_request(MCFQSPI_CS3, "MCFQSPI_CS3");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS3 failed\n");
-		goto fail3;
-	}
-	status = gpio_direction_output(MCFQSPI_CS3, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS3 failed\n");
-		goto fail4;
-	}
-
-	return 0;
-
-fail4:
-	gpio_free(MCFQSPI_CS3);
-fail3:
-	gpio_free(MCFQSPI_CS2);
-fail2:
-	gpio_free(MCFQSPI_CS1);
-fail1:
-	gpio_free(MCFQSPI_CS0);
-fail0:
-	return status;
-}
-
-static void m528x_cs_teardown(struct mcfqspi_cs_control *cs_control)
-{
-	gpio_free(MCFQSPI_CS3);
-	gpio_free(MCFQSPI_CS2);
-	gpio_free(MCFQSPI_CS1);
-	gpio_free(MCFQSPI_CS0);
-}
-
-static void m528x_cs_select(struct mcfqspi_cs_control *cs_control,
-			    u8 chip_select, bool cs_high)
-{
-	gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
-}
-
-static void m528x_cs_deselect(struct mcfqspi_cs_control *cs_control,
-			      u8 chip_select, bool cs_high)
-{
-	gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
-}
-
-static struct mcfqspi_cs_control m528x_cs_control = {
-	.setup                  = m528x_cs_setup,
-	.teardown               = m528x_cs_teardown,
-	.select                 = m528x_cs_select,
-	.deselect               = m528x_cs_deselect,
-};
-
-static struct mcfqspi_platform_data m528x_qspi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 4,
-	.cs_control		= &m528x_cs_control,
-};
-
-static struct platform_device m528x_qspi = {
-	.name			= "mcfqspi",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m528x_qspi_resources),
-	.resource		= m528x_qspi_resources,
-	.dev.platform_data	= &m528x_qspi_data,
-};
-
-static void __init m528x_qspi_init(void)
-{
-	/* setup Port QS for QSPI with gpio CS control */
-	__raw_writeb(0x07, MCFGPIO_PQSPAR);
-}
-#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
-
-static struct platform_device *m528x_devices[] __initdata = {
-	&m528x_uart,
-	&m528x_fec,
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	&m528x_qspi,
-#endif
-};
-
-/***************************************************************************/
-
-static void __init m528x_uart_init_line(int line, int irq)
-{
-	u8 port;
-
-	if ((line < 0) || (line > 2))
-		return;
-
-	/* make sure PUAPAR is set for UART0 and UART1 */
-	if (line < 2) {
-		port = readb(MCF_MBAR + MCF5282_GPIO_PUAPAR);
-		port |= (0x03 << (line * 2));
-		writeb(port, MCF_MBAR + MCF5282_GPIO_PUAPAR);
-	}
-}
-
-static void __init m528x_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m528x_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m528x_uart_init_line(line, m528x_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m528x_fec_init(void)
-{
-	u16 v16;
-
-	/* Set multi-function pins to ethernet mode for fec0 */
-	v16 = readw(MCF_IPSBAR + 0x100056);
-	writew(v16 | 0xf00, MCF_IPSBAR + 0x100056);
-	writeb(0xc0, MCF_IPSBAR + 0x100058);
-}
-
-/***************************************************************************/
-
-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)
-{
-	writeb(0, 0x30000007);
-	writeb(0x2, 0x30000007);
-}
-#endif
-
-#ifdef CONFIG_WILDFIREMOD
-void wildfiremod_halt(void)
-{
-	printk(KERN_INFO "WildFireMod hibernating...\n");
-
-	/* Set portE.5 to Digital IO */
-	MCF5282_GPIO_PEPAR &= ~(1 << (5 * 2));
-
-	/* Make portE.5 an output */
-	MCF5282_GPIO_DDRE |= (1 << 5);
-
-	/* Now toggle portE.5 from low to high */
-	MCF5282_GPIO_PORTE &= ~(1 << 5);
-	MCF5282_GPIO_PORTE |= (1 << 5);
-
-	printk(KERN_EMERG "Failed to hibernate. Halting!\n");
-}
-#endif
-
-void __init config_BSP(char *commandp, int size)
-{
-#ifdef CONFIG_WILDFIRE
-	mach_halt = wildfire_halt;
-#endif
-#ifdef CONFIG_WILDFIREMOD
-	mach_halt = wildfiremod_halt;
-#endif
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	mach_reset = m528x_cpu_reset;
-	m528x_uarts_init();
-	m528x_fec_init();
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	m528x_qspi_init();
-#endif
-	platform_add_devices(m528x_devices, ARRAY_SIZE(m528x_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/528x/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/528x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/528x/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/528x/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,438 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "NQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.base			= 1,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TA",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 8,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPTA_GPTDDR,
-		.podr				= MCFGPTA_GPTPORT,
-		.ppdr				= MCFGPTB_GPTPORT,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TB",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 16,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPTB_GPTDDR,
-		.podr				= MCFGPTB_GPTPORT,
-		.ppdr				= MCFGPTB_GPTPORT,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QA",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 24,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFQADC_DDRQA,
-		.podr				= MCFQADC_PORTQA,
-		.ppdr				= MCFQADC_PORTQA,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QB",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFQADC_DDRQB,
-		.podr				= MCFQADC_PORTQB,
-		.ppdr				= MCFQADC_PORTQB,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "A",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRA,
-		.podr				= MCFGPIO_PORTA,
-		.ppdr				= MCFGPIO_PORTAP,
-		.setr				= MCFGPIO_SETA,
-		.clrr				= MCFGPIO_CLRA,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "B",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 48,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRB,
-		.podr				= MCFGPIO_PORTB,
-		.ppdr				= MCFGPIO_PORTBP,
-		.setr				= MCFGPIO_SETB,
-		.clrr				= MCFGPIO_CLRB,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "C",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 56,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRC,
-		.podr				= MCFGPIO_PORTC,
-		.ppdr				= MCFGPIO_PORTCP,
-		.setr				= MCFGPIO_SETC,
-		.clrr				= MCFGPIO_CLRC,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "D",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRD,
-		.podr				= MCFGPIO_PORTD,
-		.ppdr				= MCFGPIO_PORTDP,
-		.setr				= MCFGPIO_SETD,
-		.clrr				= MCFGPIO_CLRD,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "E",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRE,
-		.podr				= MCFGPIO_PORTE,
-		.ppdr				= MCFGPIO_PORTEP,
-		.setr				= MCFGPIO_SETE,
-		.clrr				= MCFGPIO_CLRE,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "F",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 80,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRF,
-		.podr				= MCFGPIO_PORTF,
-		.ppdr				= MCFGPIO_PORTFP,
-		.setr				= MCFGPIO_SETF,
-		.clrr				= MCFGPIO_CLRF,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "G",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 88,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRG,
-		.podr				= MCFGPIO_PORTG,
-		.ppdr				= MCFGPIO_PORTGP,
-		.setr				= MCFGPIO_SETG,
-		.clrr				= MCFGPIO_CLRG,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "H",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 96,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRH,
-		.podr				= MCFGPIO_PORTH,
-		.ppdr				= MCFGPIO_PORTHP,
-		.setr				= MCFGPIO_SETH,
-		.clrr				= MCFGPIO_CLRH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "J",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 104,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRJ,
-		.podr				= MCFGPIO_PORTJ,
-		.ppdr				= MCFGPIO_PORTJP,
-		.setr				= MCFGPIO_SETJ,
-		.clrr				= MCFGPIO_CLRJ,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "DD",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 112,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDRDD,
-		.podr				= MCFGPIO_PORTDD,
-		.ppdr				= MCFGPIO_PORTDDP,
-		.setr				= MCFGPIO_SETDD,
-		.clrr				= MCFGPIO_CLRDD,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "EH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 120,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDREH,
-		.podr				= MCFGPIO_PORTEH,
-		.ppdr				= MCFGPIO_PORTEHP,
-		.setr				= MCFGPIO_SETEH,
-		.clrr				= MCFGPIO_CLREH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "EL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 128,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_DDREL,
-		.podr				= MCFGPIO_PORTEL,
-		.ppdr				= MCFGPIO_PORTELP,
-		.setr				= MCFGPIO_SETEL,
-		.clrr				= MCFGPIO_CLREL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "AS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 136,
-			.ngpio			= 6,
-		},
-		.pddr				= MCFGPIO_DDRAS,
-		.podr				= MCFGPIO_PORTAS,
-		.ppdr				= MCFGPIO_PORTASP,
-		.setr				= MCFGPIO_SETAS,
-		.clrr				= MCFGPIO_CLRAS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 144,
-			.ngpio			= 7,
-		},
-		.pddr				= MCFGPIO_DDRQS,
-		.podr				= MCFGPIO_PORTQS,
-		.ppdr				= MCFGPIO_PORTQSP,
-		.setr				= MCFGPIO_SETQS,
-		.clrr				= MCFGPIO_CLRQS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "SD",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 152,
-			.ngpio			= 6,
-		},
-		.pddr				= MCFGPIO_DDRSD,
-		.podr				= MCFGPIO_PORTSD,
-		.ppdr				= MCFGPIO_PORTSDP,
-		.setr				= MCFGPIO_SETSD,
-		.clrr				= MCFGPIO_CLRSD,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TC",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 160,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_DDRTC,
-		.podr				= MCFGPIO_PORTTC,
-		.ppdr				= MCFGPIO_PORTTCP,
-		.setr				= MCFGPIO_SETTC,
-		.clrr				= MCFGPIO_CLRTC,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TD",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 168,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_DDRTD,
-		.podr				= MCFGPIO_PORTTD,
-		.ppdr				= MCFGPIO_PORTTDP,
-		.setr				= MCFGPIO_SETTD,
-		.clrr				= MCFGPIO_CLRTD,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UA",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 176,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_DDRUA,
-		.podr				= MCFGPIO_PORTUA,
-		.ppdr				= MCFGPIO_PORTUAP,
-		.setr				= MCFGPIO_SETUA,
-		.clrr				= MCFGPIO_CLRUA,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/528x/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/528x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/528x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/528x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs.  You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,147 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5307/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2000, Lineo (www.lineo.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfwdebug.h>
-
-/***************************************************************************/
-
-/*
- *	Some platforms need software versions of the GPIO data registers.
- */
-unsigned short ppdata;
-unsigned char ledbank = 0xff;
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5307_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
-	},
-	{ },
-};
-
-static struct platform_device m5307_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5307_uart_platform,
-};
-
-static struct platform_device *m5307_devices[] __initdata = {
-	&m5307_uart,
-};
-
-/***************************************************************************/
-
-static void __init m5307_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
-		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART0);
-	} else if (line == 1) {
-		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
-		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART1);
-	}
-}
-
-static void __init m5307_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5307_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5307_uart_init_line(line, m5307_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m5307_timers_init(void)
-{
-	/* Timer1 is always used as system timer */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER1ICR);
-	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
-	/* Timer2 is to be used as a high speed profile timer  */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER2ICR);
-	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-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)
-{
-#if defined(CONFIG_NETtel) || \
-    defined(CONFIG_SECUREEDGEMP3) || defined(CONFIG_CLEOPATRA)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0xf0004000, size);
-	commandp[size-1] = 0;
-#endif
-
-	mach_reset = m5307_cpu_reset;
-	m5307_timers_init();
-	m5307_uarts_init();
-
-	/* Only support the external interrupts on their primary level */
-	mcf_mapirq2imr(25, MCFINTC_EINT1);
-	mcf_mapirq2imr(27, MCFINTC_EINT3);
-	mcf_mapirq2imr(29, MCFINTC_EINT5);
-	mcf_mapirq2imr(31, MCFINTC_EINT7);
-
-#ifdef CONFIG_BDM_DISABLE
-	/*
-	 * Disable the BDM clocking.  This also turns off most of the rest of
-	 * the BDM device.  This is good for EMC reasons. This option is not
-	 * incompatible with the memory protection option.
-	 */
-	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
-#endif
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m5307_devices, ARRAY_SIZE(m5307_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PP",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 16,
-		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,20 +0,0 @@
-#
-# Makefile for the m68knommu kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y			+= config.o gpio.o
-obj-$(CONFIG_NETtel)	+= nettel.o
-obj-$(CONFIG_CLEOPATRA)	+= nettel.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/nettel.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/nettel.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5307/nettel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5307/nettel.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,153 +0,0 @@
-/***************************************************************************/
-
-/*
- *	nettel.c -- startup code support for the NETtel boards
- *
- *	Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/platform_device.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/nettel.h>
-
-/***************************************************************************/
-
-/*
- * Define the IO and interrupt resources of the 2 SMC9196 interfaces.
- */
-#define	NETTEL_SMC0_ADDR	0x30600300
-#define	NETTEL_SMC0_IRQ		29
-
-#define	NETTEL_SMC1_ADDR	0x30600000
-#define	NETTEL_SMC1_IRQ		27
-
-/*
- * We need some access into the SMC9196 registers. Define those registers
- * we will need here (including the smc91x.h doesn't seem to give us these
- * in a simple form).
- */
-#define	SMC91xx_BANKSELECT	14
-#define	SMC91xx_BASEADDR	2
-#define	SMC91xx_BASEMAC		4
-
-/***************************************************************************/
-
-static struct resource nettel_smc91x_0_resources[] = {
-	{
-		.start		= NETTEL_SMC0_ADDR,
-		.end		= NETTEL_SMC0_ADDR + 0x20,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= NETTEL_SMC0_IRQ,
-		.end		= NETTEL_SMC0_IRQ,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct resource nettel_smc91x_1_resources[] = {
-	{
-		.start		= NETTEL_SMC1_ADDR,
-		.end		= NETTEL_SMC1_ADDR + 0x20,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= NETTEL_SMC1_IRQ,
-		.end		= NETTEL_SMC1_IRQ,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device nettel_smc91x[] = {
-	{
-		.name			= "smc91x",
-		.id			= 0,
-		.num_resources		= ARRAY_SIZE(nettel_smc91x_0_resources),
-		.resource		= nettel_smc91x_0_resources,
-	},
-	{
-		.name			= "smc91x",
-		.id			= 1,
-		.num_resources		= ARRAY_SIZE(nettel_smc91x_1_resources),
-		.resource		= nettel_smc91x_1_resources,
-	},
-};
-
-static struct platform_device *nettel_devices[] __initdata = {
-	&nettel_smc91x[0],
-	&nettel_smc91x[1],
-};
-
-/***************************************************************************/
-
-static u8 nettel_macdefault[] __initdata = {
-	0x00, 0xd0, 0xcf, 0x00, 0x00, 0x01,
-};
-
-/*
- * Set flash contained MAC address into SMC9196 core. Make sure the flash
- * MAC address is sane, and not an empty flash. If no good use the Moreton
- * Bay default MAC address instead.
- */
-
-static void __init nettel_smc91x_setmac(unsigned int ioaddr, unsigned int flashaddr)
-{
-	u16 *macp;
-
-	macp = (u16 *) flashaddr;
-	if ((macp[0] == 0xffff) && (macp[1] == 0xffff) && (macp[2] == 0xffff))
-		macp = (u16 *) &nettel_macdefault[0];
-
-	writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
-	writew(macp[0], ioaddr + SMC91xx_BASEMAC);
-	writew(macp[1], ioaddr + SMC91xx_BASEMAC + 2);
-	writew(macp[2], ioaddr + SMC91xx_BASEMAC + 4);
-}
-
-/***************************************************************************/
-
-/*
- * Re-map the address space of at least one of the SMC ethernet
- * parts. Both parts power up decoding the same address, so we
- * need to move one of them first, before doing anything else.
- */
-
-static void __init nettel_smc91x_init(void)
-{
-	writew(0x00ec, MCF_MBAR + MCFSIM_PADDR);
-	mcf_setppdata(0, 0x0080);
-	writew(1, NETTEL_SMC0_ADDR + SMC91xx_BANKSELECT);
-	writew(0x0067, NETTEL_SMC0_ADDR + SMC91xx_BASEADDR);
-	mcf_setppdata(0x0080, 0);
-
-	/* Set correct chip select timing for SMC9196 accesses */
-	writew(0x1180, MCF_MBAR + MCFSIM_CSCR3);
-
-	/* Set the SMC interrupts to be auto-vectored */
-	mcf_autovector(NETTEL_SMC0_IRQ);
-	mcf_autovector(NETTEL_SMC1_IRQ);
-
-	/* Set MAC addresses from flash for both interfaces */
-	nettel_smc91x_setmac(NETTEL_SMC0_ADDR, 0xf0006000);
-	nettel_smc91x_setmac(NETTEL_SMC1_ADDR, 0xf0006006);
-}
-
-/***************************************************************************/
-
-static int __init init_nettel(void)
-{
-	nettel_smc91x_init();
-	platform_add_devices(nettel_devices, ARRAY_SIZE(nettel_devices));
-	return 0;
-}
-
-arch_initcall(init_nettel);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/532x/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/532x/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/532x/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/532x/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,648 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/532x/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2000, Lineo (www.lineo.com)
- *	Yaroslav Vinogradov yaroslav.vinogradov@freescale.com
- *	Copyright Freescale Semiconductor, Inc 2006
- *	Copyright (c) 2006, emlix, Sebastian Hess <sh@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/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-#include <asm/mcfdma.h>
-#include <asm/mcfwdebug.h>
-#include <asm/mcfqspi.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m532x_uart_platform[] = {
-	{
-		.mapbase	= MCFUART_BASE1,
-		.irq		= MCFINT_VECBASE + MCFINT_UART0,
-	},
-	{
-		.mapbase 	= MCFUART_BASE2,
-		.irq		= MCFINT_VECBASE + MCFINT_UART1,
-	},
-	{
-		.mapbase 	= MCFUART_BASE3,
-		.irq		= MCFINT_VECBASE + MCFINT_UART2,
-	},
-	{ },
-};
-
-static struct platform_device m532x_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m532x_uart_platform,
-};
-
-static struct resource m532x_fec_resources[] = {
-	{
-		.start		= 0xfc030000,
-		.end		= 0xfc0307ff,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= 64 + 36,
-		.end		= 64 + 36,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 40,
-		.end		= 64 + 40,
-		.flags		= IORESOURCE_IRQ,
-	},
-	{
-		.start		= 64 + 42,
-		.end		= 64 + 42,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-static struct platform_device m532x_fec = {
-	.name			= "fec",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m532x_fec_resources),
-	.resource		= m532x_fec_resources,
-};
-
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-static struct resource m532x_qspi_resources[] = {
-	{
-		.start		= MCFQSPI_IOBASE,
-		.end		= MCFQSPI_IOBASE + MCFQSPI_IOSIZE - 1,
-		.flags		= IORESOURCE_MEM,
-	},
-	{
-		.start		= MCFINT_VECBASE + MCFINT_QSPI,
-		.end		= MCFINT_VECBASE + MCFINT_QSPI,
-		.flags		= IORESOURCE_IRQ,
-	},
-};
-
-#define MCFQSPI_CS0    84
-#define MCFQSPI_CS1    85
-#define MCFQSPI_CS2    86
-
-static int m532x_cs_setup(struct mcfqspi_cs_control *cs_control)
-{
-	int status;
-
-	status = gpio_request(MCFQSPI_CS0, "MCFQSPI_CS0");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS0 failed\n");
-		goto fail0;
-	}
-	status = gpio_direction_output(MCFQSPI_CS0, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS0 failed\n");
-		goto fail1;
-	}
-
-	status = gpio_request(MCFQSPI_CS1, "MCFQSPI_CS1");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS1 failed\n");
-		goto fail1;
-	}
-	status = gpio_direction_output(MCFQSPI_CS1, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS1 failed\n");
-		goto fail2;
-	}
-
-	status = gpio_request(MCFQSPI_CS2, "MCFQSPI_CS2");
-	if (status) {
-		pr_debug("gpio_request for MCFQSPI_CS2 failed\n");
-		goto fail2;
-	}
-	status = gpio_direction_output(MCFQSPI_CS2, 1);
-	if (status) {
-		pr_debug("gpio_direction_output for MCFQSPI_CS2 failed\n");
-		goto fail3;
-	}
-
-	return 0;
-
-fail3:
-	gpio_free(MCFQSPI_CS2);
-fail2:
-	gpio_free(MCFQSPI_CS1);
-fail1:
-	gpio_free(MCFQSPI_CS0);
-fail0:
-	return status;
-}
-
-static void m532x_cs_teardown(struct mcfqspi_cs_control *cs_control)
-{
-	gpio_free(MCFQSPI_CS2);
-	gpio_free(MCFQSPI_CS1);
-	gpio_free(MCFQSPI_CS0);
-}
-
-static void m532x_cs_select(struct mcfqspi_cs_control *cs_control,
-			    u8 chip_select, bool cs_high)
-{
-	gpio_set_value(MCFQSPI_CS0 + chip_select, cs_high);
-}
-
-static void m532x_cs_deselect(struct mcfqspi_cs_control *cs_control,
-			      u8 chip_select, bool cs_high)
-{
-	gpio_set_value(MCFQSPI_CS0 + chip_select, !cs_high);
-}
-
-static struct mcfqspi_cs_control m532x_cs_control = {
-	.setup                  = m532x_cs_setup,
-	.teardown               = m532x_cs_teardown,
-	.select                 = m532x_cs_select,
-	.deselect               = m532x_cs_deselect,
-};
-
-static struct mcfqspi_platform_data m532x_qspi_data = {
-	.bus_num		= 0,
-	.num_chipselect		= 3,
-	.cs_control		= &m532x_cs_control,
-};
-
-static struct platform_device m532x_qspi = {
-	.name			= "mcfqspi",
-	.id			= 0,
-	.num_resources		= ARRAY_SIZE(m532x_qspi_resources),
-	.resource		= m532x_qspi_resources,
-	.dev.platform_data	= &m532x_qspi_data,
-};
-
-static void __init m532x_qspi_init(void)
-{
-	/* setup QSPS pins for QSPI with gpio CS control */
-	writew(0x01f0, MCF_GPIO_PAR_QSPI);
-}
-#endif /* defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE) */
-
-
-static struct platform_device *m532x_devices[] __initdata = {
-	&m532x_uart,
-	&m532x_fec,
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	&m532x_qspi,
-#endif
-};
-
-/***************************************************************************/
-
-static void __init m532x_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		/* GPIO initialization */
-		MCF_GPIO_PAR_UART |= 0x000F;
-	} else if (line == 1) {
-		/* GPIO initialization */
-		MCF_GPIO_PAR_UART |= 0x0FF0;
-	}
-}
-
-static void __init m532x_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m532x_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m532x_uart_init_line(line, m532x_uart_platform[line].irq);
-}
-/***************************************************************************/
-
-static void __init m532x_fec_init(void)
-{
-	/* Set multi-function pins to ethernet mode for fec0 */
-	MCF_GPIO_PAR_FECI2C |= (MCF_GPIO_PAR_FECI2C_PAR_MDC_EMDC |
-		MCF_GPIO_PAR_FECI2C_PAR_MDIO_EMDIO);
-	MCF_GPIO_PAR_FEC = (MCF_GPIO_PAR_FEC_PAR_FEC_7W_FEC |
-		MCF_GPIO_PAR_FEC_PAR_FEC_MII_FEC);
-}
-
-/***************************************************************************/
-
-static void m532x_cpu_reset(void)
-{
-	local_irq_disable();
-	__raw_writeb(MCF_RCR_SWRESET, MCF_RCR);
-}
-
-/***************************************************************************/
-
-void __init config_BSP(char *commandp, int size)
-{
-#if !defined(CONFIG_BOOTPARAM)
-	/* Copy command line from FLASH to local buffer... */
-	memcpy(commandp, (char *) 0x4000, 4);
-	if(strncmp(commandp, "kcl ", 4) == 0){
-		memcpy(commandp, (char *) 0x4004, size);
-		commandp[size-1] = 0;
-	} else {
-		memset(commandp, 0, size);
-	}
-#endif
-
-#ifdef CONFIG_BDM_DISABLE
-	/*
-	 * Disable the BDM clocking.  This also turns off most of the rest of
-	 * the BDM device.  This is good for EMC reasons. This option is not
-	 * incompatible with the memory protection option.
-	 */
-	wdebug(MCFDEBUG_CSR, MCFDEBUG_CSR_PSTCLK);
-#endif
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	m532x_uarts_init();
-	m532x_fec_init();
-#if defined(CONFIG_SPI_COLDFIRE_QSPI) || defined(CONFIG_SPI_COLDFIRE_QSPI_MODULE)
-	m532x_qspi_init();
-#endif
-	platform_add_devices(m532x_devices, ARRAY_SIZE(m532x_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
-/* Board initialization */
-/***************************************************************************/
-/* 
- * PLL min/max specifications
- */
-#define MAX_FVCO	500000	/* KHz */
-#define MAX_FSYS	80000 	/* KHz */
-#define MIN_FSYS	58333 	/* KHz */
-#define FREF		16000   /* KHz */
-
-
-#define MAX_MFD		135     /* Multiplier */
-#define MIN_MFD		88      /* Multiplier */
-#define BUSDIV		6       /* Divider */
-
-/*
- * Low Power Divider specifications
- */
-#define MIN_LPD		(1 << 0)    /* Divider (not encoded) */
-#define MAX_LPD		(1 << 15)   /* Divider (not encoded) */
-#define DEFAULT_LPD	(1 << 1)	/* Divider (not encoded) */
-
-#define SYS_CLK_KHZ	80000
-#define SYSTEM_PERIOD	12.5
-/*
- *  SDRAM Timing Parameters
- */  
-#define SDRAM_BL	8	/* # of beats in a burst */
-#define SDRAM_TWR	2	/* in clocks */
-#define SDRAM_CASL	2.5	/* CASL in clocks */
-#define SDRAM_TRCD	2	/* in clocks */
-#define SDRAM_TRP	2	/* in clocks */
-#define SDRAM_TRFC	7	/* in clocks */
-#define SDRAM_TREFI	7800	/* in ns */
-
-#define EXT_SRAM_ADDRESS	(0xC0000000)
-#define FLASH_ADDRESS		(0x00000000)
-#define SDRAM_ADDRESS		(0x40000000)
-
-#define NAND_FLASH_ADDRESS	(0xD0000000)
-
-int sys_clk_khz = 0;
-int sys_clk_mhz = 0;
-
-void wtm_init(void);
-void scm_init(void);
-void gpio_init(void);
-void fbcs_init(void);
-void sdramc_init(void);
-int  clock_pll (int fsys, int flags);
-int  clock_limp (int);
-int  clock_exit_limp (void);
-int  get_sys_clock (void);
-
-asmlinkage void __init sysinit(void)
-{
-	sys_clk_khz = clock_pll(0, 0);
-	sys_clk_mhz = sys_clk_khz/1000;
-	
-	wtm_init();
-	scm_init();
-	gpio_init();
-	fbcs_init();
-	sdramc_init();
-}
-
-void wtm_init(void)
-{
-	/* Disable watchdog timer */
-	MCF_WTM_WCR = 0;
-}
-
-#define MCF_SCM_BCR_GBW		(0x00000100)
-#define MCF_SCM_BCR_GBR		(0x00000200)
-
-void scm_init(void)
-{
-	/* All masters are trusted */
-	MCF_SCM_MPR = 0x77777777;
-    
-	/* Allow supervisor/user, read/write, and trusted/untrusted
-	   access to all slaves */
-	MCF_SCM_PACRA = 0;
-	MCF_SCM_PACRB = 0;
-	MCF_SCM_PACRC = 0;
-	MCF_SCM_PACRD = 0;
-	MCF_SCM_PACRE = 0;
-	MCF_SCM_PACRF = 0;
-
-	/* Enable bursts */
-	MCF_SCM_BCR = (MCF_SCM_BCR_GBR | MCF_SCM_BCR_GBW);
-}
-
-
-void fbcs_init(void)
-{
-	MCF_GPIO_PAR_CS = 0x0000003E;
-
-	/* Latch chip select */
-	MCF_FBCS1_CSAR = 0x10080000;
-
-	MCF_FBCS1_CSCR = 0x002A3780;
-	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_2M | MCF_FBCS_CSMR_V);
-
-	/* Initialize latch to drive signals to inactive states */
-	*((u16 *)(0x10080000)) = 0xFFFF;
-
-	/* External SRAM */
-	MCF_FBCS1_CSAR = EXT_SRAM_ADDRESS;
-	MCF_FBCS1_CSCR = (MCF_FBCS_CSCR_PS_16
-			| MCF_FBCS_CSCR_AA
-			| MCF_FBCS_CSCR_SBM
-			| MCF_FBCS_CSCR_WS(1));
-	MCF_FBCS1_CSMR = (MCF_FBCS_CSMR_BAM_512K
-			| MCF_FBCS_CSMR_V);
-
-	/* Boot Flash connected to FBCS0 */
-	MCF_FBCS0_CSAR = FLASH_ADDRESS;
-	MCF_FBCS0_CSCR = (MCF_FBCS_CSCR_PS_16
-			| MCF_FBCS_CSCR_BEM
-			| MCF_FBCS_CSCR_AA
-			| MCF_FBCS_CSCR_SBM
-			| MCF_FBCS_CSCR_WS(7));
-	MCF_FBCS0_CSMR = (MCF_FBCS_CSMR_BAM_32M
-			| MCF_FBCS_CSMR_V);
-}
-
-void sdramc_init(void)
-{
-	/*
-	 * Check to see if the SDRAM has already been initialized
-	 * by a run control tool
-	 */
-	if (!(MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)) {
-		/* SDRAM chip select initialization */
-		
-		/* Initialize SDRAM chip select */
-		MCF_SDRAMC_SDCS0 = (0
-			| MCF_SDRAMC_SDCS_BA(SDRAM_ADDRESS)
-			| MCF_SDRAMC_SDCS_CSSZ(MCF_SDRAMC_SDCS_CSSZ_32MBYTE));
-
-	/*
-	 * Basic configuration and initialization
-	 */
-	MCF_SDRAMC_SDCFG1 = (0
-		| MCF_SDRAMC_SDCFG1_SRD2RW((int)((SDRAM_CASL + 2) + 0.5 ))
-		| MCF_SDRAMC_SDCFG1_SWT2RD(SDRAM_TWR + 1)
-		| MCF_SDRAMC_SDCFG1_RDLAT((int)((SDRAM_CASL*2) + 2))
-		| MCF_SDRAMC_SDCFG1_ACT2RW((int)((SDRAM_TRCD ) + 0.5))
-		| MCF_SDRAMC_SDCFG1_PRE2ACT((int)((SDRAM_TRP ) + 0.5))
-		| MCF_SDRAMC_SDCFG1_REF2ACT((int)(((SDRAM_TRFC) ) + 0.5))
-		| MCF_SDRAMC_SDCFG1_WTLAT(3));
-	MCF_SDRAMC_SDCFG2 = (0
-		| MCF_SDRAMC_SDCFG2_BRD2PRE(SDRAM_BL/2 + 1)
-		| MCF_SDRAMC_SDCFG2_BWT2RW(SDRAM_BL/2 + SDRAM_TWR)
-		| MCF_SDRAMC_SDCFG2_BRD2WT((int)((SDRAM_CASL+SDRAM_BL/2-1.0)+0.5))
-		| MCF_SDRAMC_SDCFG2_BL(SDRAM_BL-1));
-
-            
-	/*
-	 * Precharge and enable write to SDMR
-	 */
-        MCF_SDRAMC_SDCR = (0
-		| MCF_SDRAMC_SDCR_MODE_EN
-		| MCF_SDRAMC_SDCR_CKE
-		| MCF_SDRAMC_SDCR_DDR
-		| MCF_SDRAMC_SDCR_MUX(1)
-		| MCF_SDRAMC_SDCR_RCNT((int)(((SDRAM_TREFI/(SYSTEM_PERIOD*64)) - 1) + 0.5))
-		| MCF_SDRAMC_SDCR_PS_16
-		| MCF_SDRAMC_SDCR_IPALL);            
-
-	/*
-	 * Write extended mode register
-	 */
-	MCF_SDRAMC_SDMR = (0
-		| MCF_SDRAMC_SDMR_BNKAD_LEMR
-		| MCF_SDRAMC_SDMR_AD(0x0)
-		| MCF_SDRAMC_SDMR_CMD);
-
-	/*
-	 * Write mode register and reset DLL
-	 */
-	MCF_SDRAMC_SDMR = (0
-		| MCF_SDRAMC_SDMR_BNKAD_LMR
-		| MCF_SDRAMC_SDMR_AD(0x163)
-		| MCF_SDRAMC_SDMR_CMD);
-
-	/*
-	 * Execute a PALL command
-	 */
-	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IPALL;
-
-	/*
-	 * Perform two REF cycles
-	 */
-	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
-	MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_IREF;
-
-	/*
-	 * Write mode register and clear reset DLL
-	 */
-	MCF_SDRAMC_SDMR = (0
-		| MCF_SDRAMC_SDMR_BNKAD_LMR
-		| MCF_SDRAMC_SDMR_AD(0x063)
-		| MCF_SDRAMC_SDMR_CMD);
-				
-	/*
-	 * Enable auto refresh and lock SDMR
-	 */
-	MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_MODE_EN;
-	MCF_SDRAMC_SDCR |= (0
-		| MCF_SDRAMC_SDCR_REF
-		| MCF_SDRAMC_SDCR_DQS_OE(0xC));
-	}
-}
-
-void gpio_init(void)
-{
-	/* Enable UART0 pins */
-	MCF_GPIO_PAR_UART = ( 0
-		| MCF_GPIO_PAR_UART_PAR_URXD0
-		| MCF_GPIO_PAR_UART_PAR_UTXD0);
-
-	/* Initialize TIN3 as a GPIO output to enable the write
-	   half of the latch */
-	MCF_GPIO_PAR_TIMER = 0x00;
-	__raw_writeb(0x08, MCFGPIO_PDDR_TIMER);
-	__raw_writeb(0x00, MCFGPIO_PCLRR_TIMER);
-
-}
-
-int clock_pll(int fsys, int flags)
-{
-	int fref, temp, fout, mfd;
-	u32 i;
-
-	fref = FREF;
-        
-	if (fsys == 0) {
-		/* Return current PLL output */
-		mfd = MCF_PLL_PFDR;
-
-		return (fref * mfd / (BUSDIV * 4));
-	}
-
-	/* Check bounds of requested system clock */
-	if (fsys > MAX_FSYS)
-		fsys = MAX_FSYS;
-	if (fsys < MIN_FSYS)
-		fsys = MIN_FSYS;
-
-	/* Multiplying by 100 when calculating the temp value,
-	   and then dividing by 100 to calculate the mfd allows
-	   for exact values without needing to include floating
-	   point libraries. */
-	temp = 100 * fsys / fref;
-	mfd = 4 * BUSDIV * temp / 100;
-    	    	    	
-	/* Determine the output frequency for selected values */
-	fout = (fref * mfd / (BUSDIV * 4));
-
-	/*
-	 * Check to see if the SDRAM has already been initialized.
-	 * If it has then the SDRAM needs to be put into self refresh
-	 * mode before reprogramming the PLL.
-	 */
-	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
-		/* Put SDRAM into self refresh mode */
-		MCF_SDRAMC_SDCR &= ~MCF_SDRAMC_SDCR_CKE;
-
-	/*
-	 * Initialize the PLL to generate the new system clock frequency.
-	 * The device must be put into LIMP mode to reprogram the PLL.
-	 */
-
-	/* Enter LIMP mode */
-	clock_limp(DEFAULT_LPD);
-     					
-	/* Reprogram PLL for desired fsys */
-	MCF_PLL_PODR = (0
-		| MCF_PLL_PODR_CPUDIV(BUSDIV/3)
-		| MCF_PLL_PODR_BUSDIV(BUSDIV));
-						
-	MCF_PLL_PFDR = mfd;
-		
-	/* Exit LIMP mode */
-	clock_exit_limp();
-	
-	/*
-	 * Return the SDRAM to normal operation if it is in use.
-	 */
-	if (MCF_SDRAMC_SDCR & MCF_SDRAMC_SDCR_REF)
-		/* Exit self refresh mode */
-		MCF_SDRAMC_SDCR |= MCF_SDRAMC_SDCR_CKE;
-
-	/* Errata - workaround for SDRAM opeartion after exiting LIMP mode */
-	MCF_SDRAMC_LIMP_FIX = MCF_SDRAMC_REFRESH;
-
-	/* wait for DQS logic to relock */
-	for (i = 0; i < 0x200; i++)
-		;
-
-	return fout;
-}
-
-int clock_limp(int div)
-{
-	u32 temp;
-
-	/* Check bounds of divider */
-	if (div < MIN_LPD)
-		div = MIN_LPD;
-	if (div > MAX_LPD)
-		div = MAX_LPD;
-    
-	/* Save of the current value of the SSIDIV so we don't
-	   overwrite the value*/
-	temp = (MCF_CCM_CDR & MCF_CCM_CDR_SSIDIV(0xF));
-      
-	/* Apply the divider to the system clock */
-	MCF_CCM_CDR = ( 0
-		| MCF_CCM_CDR_LPDIV(div)
-		| MCF_CCM_CDR_SSIDIV(temp));
-    
-	MCF_CCM_MISCCR |= MCF_CCM_MISCCR_LIMP;
-    
-	return (FREF/(3*(1 << div)));
-}
-
-int clock_exit_limp(void)
-{
-	int fout;
-	
-	/* Exit LIMP mode */
-	MCF_CCM_MISCCR = (MCF_CCM_MISCCR & ~ MCF_CCM_MISCCR_LIMP);
-
-	/* Wait for PLL to lock */
-	while (!(MCF_CCM_MISCCR & MCF_CCM_MISCCR_PLL_LOCK))
-		;
-	
-	fout = get_sys_clock();
-
-	return fout;
-}
-
-int get_sys_clock(void)
-{
-	int divider;
-	
-	/* Test to see if device is in LIMP mode */
-	if (MCF_CCM_MISCCR & MCF_CCM_MISCCR_LIMP) {
-		divider = MCF_CCM_CDR & MCF_CCM_CDR_LPDIV(0xF);
-		return (FREF/(2 << divider));
-	}
-	else
-		return ((FREF * MCF_PLL_PFDR) / (BUSDIV * 4));
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/532x/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/532x/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/532x/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/532x/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,337 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PIRQ",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFEPORT_EPDDR,
-		.podr				= MCFEPORT_EPDR,
-		.ppdr				= MCFEPORT_EPPDR,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 8,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FECH,
-		.podr				= MCFGPIO_PODR_FECH,
-		.ppdr				= MCFGPIO_PPDSDR_FECH,
-		.setr				= MCFGPIO_PPDSDR_FECH,
-		.clrr				= MCFGPIO_PCLRR_FECH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 16,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_FECL,
-		.podr				= MCFGPIO_PODR_FECL,
-		.ppdr				= MCFGPIO_PPDSDR_FECL,
-		.setr				= MCFGPIO_PPDSDR_FECL,
-		.clrr				= MCFGPIO_PCLRR_FECL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "SSI",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 24,
-			.ngpio			= 5,
-		},
-		.pddr				= MCFGPIO_PDDR_SSI,
-		.podr				= MCFGPIO_PODR_SSI,
-		.ppdr				= MCFGPIO_PPDSDR_SSI,
-		.setr				= MCFGPIO_PPDSDR_SSI,
-		.clrr				= MCFGPIO_PCLRR_SSI,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BUSCTL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 32,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_BUSCTL,
-		.podr				= MCFGPIO_PODR_BUSCTL,
-		.ppdr				= MCFGPIO_PPDSDR_BUSCTL,
-		.setr				= MCFGPIO_PPDSDR_BUSCTL,
-		.clrr				= MCFGPIO_PCLRR_BUSCTL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "BE",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 40,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_BE,
-		.podr				= MCFGPIO_PODR_BE,
-		.ppdr				= MCFGPIO_PPDSDR_BE,
-		.setr				= MCFGPIO_PPDSDR_BE,
-		.clrr				= MCFGPIO_PCLRR_BE,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "CS",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 49,
-			.ngpio			= 5,
-		},
-		.pddr				= MCFGPIO_PDDR_CS,
-		.podr				= MCFGPIO_PODR_CS,
-		.ppdr				= MCFGPIO_PPDSDR_CS,
-		.setr				= MCFGPIO_PPDSDR_CS,
-		.clrr				= MCFGPIO_PCLRR_CS,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "PWM",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 58,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_PWM,
-		.podr				= MCFGPIO_PODR_PWM,
-		.ppdr				= MCFGPIO_PPDSDR_PWM,
-		.setr				= MCFGPIO_PPDSDR_PWM,
-		.clrr				= MCFGPIO_PCLRR_PWM,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "FECI2C",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 64,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_FECI2C,
-		.podr				= MCFGPIO_PODR_FECI2C,
-		.ppdr				= MCFGPIO_PPDSDR_FECI2C,
-		.setr				= MCFGPIO_PPDSDR_FECI2C,
-		.clrr				= MCFGPIO_PCLRR_FECI2C,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "UART",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 72,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_UART,
-		.podr				= MCFGPIO_PODR_UART,
-		.ppdr				= MCFGPIO_PPDSDR_UART,
-		.setr				= MCFGPIO_PPDSDR_UART,
-		.clrr				= MCFGPIO_PCLRR_UART,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "QSPI",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 80,
-			.ngpio			= 6,
-		},
-		.pddr				= MCFGPIO_PDDR_QSPI,
-		.podr				= MCFGPIO_PODR_QSPI,
-		.ppdr				= MCFGPIO_PPDSDR_QSPI,
-		.setr				= MCFGPIO_PPDSDR_QSPI,
-		.clrr				= MCFGPIO_PCLRR_QSPI,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "TIMER",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 88,
-			.ngpio			= 4,
-		},
-		.pddr				= MCFGPIO_PDDR_TIMER,
-		.podr				= MCFGPIO_PODR_TIMER,
-		.ppdr				= MCFGPIO_PPDSDR_TIMER,
-		.setr				= MCFGPIO_PPDSDR_TIMER,
-		.clrr				= MCFGPIO_PCLRR_TIMER,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "LCDDATAH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 96,
-			.ngpio			= 2,
-		},
-		.pddr				= MCFGPIO_PDDR_LCDDATAH,
-		.podr				= MCFGPIO_PODR_LCDDATAH,
-		.ppdr				= MCFGPIO_PPDSDR_LCDDATAH,
-		.setr				= MCFGPIO_PPDSDR_LCDDATAH,
-		.clrr				= MCFGPIO_PCLRR_LCDDATAH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "LCDDATAM",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 104,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_LCDDATAM,
-		.podr				= MCFGPIO_PODR_LCDDATAM,
-		.ppdr				= MCFGPIO_PPDSDR_LCDDATAM,
-		.setr				= MCFGPIO_PPDSDR_LCDDATAM,
-		.clrr				= MCFGPIO_PCLRR_LCDDATAM,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "LCDDATAL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 112,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_LCDDATAL,
-		.podr				= MCFGPIO_PODR_LCDDATAL,
-		.ppdr				= MCFGPIO_PPDSDR_LCDDATAL,
-		.setr				= MCFGPIO_PPDSDR_LCDDATAL,
-		.clrr				= MCFGPIO_PCLRR_LCDDATAL,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "LCDCTLH",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 120,
-			.ngpio			= 1,
-		},
-		.pddr				= MCFGPIO_PDDR_LCDCTLH,
-		.podr				= MCFGPIO_PODR_LCDCTLH,
-		.ppdr				= MCFGPIO_PPDSDR_LCDCTLH,
-		.setr				= MCFGPIO_PPDSDR_LCDCTLH,
-		.clrr				= MCFGPIO_PCLRR_LCDCTLH,
-	},
-	{
-		.gpio_chip			= {
-			.label			= "LCDCTLL",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value_fast,
-			.base			= 128,
-			.ngpio			= 8,
-		},
-		.pddr				= MCFGPIO_PDDR_LCDCTLL,
-		.podr				= MCFGPIO_PODR_LCDCTLL,
-		.ppdr				= MCFGPIO_PPDSDR_LCDCTLL,
-		.setr				= MCFGPIO_PPDSDR_LCDCTLL,
-		.clrr				= MCFGPIO_PCLRR_LCDCTLL,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/532x/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/532x/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/532x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/532x/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-#obj-y := config.o usb-mcf532x.o spi-mcf532x.o
-obj-y := config.o gpio.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5407/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5407/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5407/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5407/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,122 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/5407/config.c
- *
- *	Copyright (C) 1999-2002, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2000, Lineo (www.lineo.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfuart.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m5407_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 73,
-	},
-	{
-		.mapbase 	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 74,
-	},
-	{ },
-};
-
-static struct platform_device m5407_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m5407_uart_platform,
-};
-
-static struct platform_device *m5407_devices[] __initdata = {
-	&m5407_uart,
-};
-
-/***************************************************************************/
-
-static void __init m5407_uart_init_line(int line, int irq)
-{
-	if (line == 0) {
-		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI1, MCF_MBAR + MCFSIM_UART1ICR);
-		writeb(irq, MCF_MBAR + MCFUART_BASE1 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART0);
-	} else if (line == 1) {
-		writeb(MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI2, MCF_MBAR + MCFSIM_UART2ICR);
-		writeb(irq, MCF_MBAR + MCFUART_BASE2 + MCFUART_UIVR);
-		mcf_mapirq2imr(irq, MCFINTC_UART1);
-	}
-}
-
-static void __init m5407_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m5407_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m5407_uart_init_line(line, m5407_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void __init m5407_timers_init(void)
-{
-	/* Timer1 is always used as system timer */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL6 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER1ICR);
-	mcf_mapirq2imr(MCF_IRQ_TIMER, MCFINTC_TIMER1);
-
-#ifdef CONFIG_HIGHPROFILE
-	/* Timer2 is to be used as a high speed profile timer  */
-	writeb(MCFSIM_ICR_AUTOVEC | MCFSIM_ICR_LEVEL7 | MCFSIM_ICR_PRI3,
-		MCF_MBAR + MCFSIM_TIMER2ICR);
-	mcf_mapirq2imr(MCF_IRQ_PROFILER, MCFINTC_TIMER2);
-#endif
-}
-
-/***************************************************************************/
-
-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)
-{
-	mach_reset = m5407_cpu_reset;
-	m5407_timers_init();
-	m5407_uarts_init();
-
-	/* Only support the external interrupts on their primary level */
-	mcf_mapirq2imr(25, MCFINTC_EINT1);
-	mcf_mapirq2imr(27, MCFINTC_EINT3);
-	mcf_mapirq2imr(29, MCFINTC_EINT5);
-	mcf_mapirq2imr(31, MCFINTC_EINT7);
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-	platform_add_devices(m5407_devices, ARRAY_SIZE(m5407_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5407/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/5407/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5407/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5407/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,49 +0,0 @@
-/*
- * Coldfire generic GPIO support
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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 <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfgpio.h>
-
-static struct mcf_gpio_chip mcf_gpio_chips[] = {
-	{
-		.gpio_chip			= {
-			.label			= "PP",
-			.request		= mcf_gpio_request,
-			.free			= mcf_gpio_free,
-			.direction_input	= mcf_gpio_direction_input,
-			.direction_output	= mcf_gpio_direction_output,
-			.get			= mcf_gpio_get_value,
-			.set			= mcf_gpio_set_value,
-			.ngpio			= 16,
-		},
-		.pddr				= MCFSIM_PADDR,
-		.podr				= MCFSIM_PADAT,
-		.ppdr				= MCFSIM_PADAT,
-	},
-};
-
-static int __init mcf_gpio_init(void)
-{
-	unsigned i = 0;
-	while (i < ARRAY_SIZE(mcf_gpio_chips))
-		(void)gpiochip_add((struct gpio_chip *)&mcf_gpio_chips[i++]);
-	return 0;
-}
-
-core_initcall(mcf_gpio_init);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/5407/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/5407/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/5407/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/5407/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o gpio.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/54xx/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/54xx/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/54xx/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/54xx/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,115 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/54xx/config.c
- *
- *	Copyright (C) 2010, Philippe De Muyter <phdm@macqel.be>
- */
-
-/***************************************************************************/
-
-#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>
-#include <asm/m54xxsim.h>
-#include <asm/mcfuart.h>
-#include <asm/m54xxgpt.h>
-
-/***************************************************************************/
-
-static struct mcf_platform_uart m54xx_uart_platform[] = {
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE1,
-		.irq		= 64 + 35,
-	},
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE2,
-		.irq		= 64 + 34,
-	},
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE3,
-		.irq		= 64 + 33,
-	},
-	{
-		.mapbase	= MCF_MBAR + MCFUART_BASE4,
-		.irq		= 64 + 32,
-	},
-};
-
-static struct platform_device m54xx_uart = {
-	.name			= "mcfuart",
-	.id			= 0,
-	.dev.platform_data	= m54xx_uart_platform,
-};
-
-static struct platform_device *m54xx_devices[] __initdata = {
-	&m54xx_uart,
-};
-
-
-/***************************************************************************/
-
-static void __init m54xx_uart_init_line(int line, int irq)
-{
-	int rts_cts;
-
-	/* enable io pins */
-	switch (line) {
-	case 0:
-		rts_cts = 0; break;
-	case 1:
-		rts_cts = MCF_PAR_PSC_RTS_RTS; break;
-	case 2:
-		rts_cts = MCF_PAR_PSC_RTS_RTS | MCF_PAR_PSC_CTS_CTS; break;
-	case 3:
-		rts_cts = 0; break;
-	}
-	__raw_writeb(MCF_PAR_PSC_TXD | rts_cts | MCF_PAR_PSC_RXD,
-						MCF_MBAR + MCF_PAR_PSC(line));
-}
-
-static void __init m54xx_uarts_init(void)
-{
-	const int nrlines = ARRAY_SIZE(m54xx_uart_platform);
-	int line;
-
-	for (line = 0; (line < nrlines); line++)
-		m54xx_uart_init_line(line, m54xx_uart_platform[line].irq);
-}
-
-/***************************************************************************/
-
-static void mcf54xx_reset(void)
-{
-	/* disable interrupts and enable the watchdog */
-	asm("movew #0x2700, %sr\n");
-	__raw_writel(0, MCF_MBAR + MCF_GPT_GMS0);
-	__raw_writel(MCF_GPT_GCIR_CNT(1), MCF_MBAR + MCF_GPT_GCIR0);
-	__raw_writel(MCF_GPT_GMS_WDEN | MCF_GPT_GMS_CE | MCF_GPT_GMS_TMS(4),
-						MCF_MBAR + MCF_GPT_GMS0);
-}
-
-/***************************************************************************/
-
-void __init config_BSP(char *commandp, int size)
-{
-	mach_reset = mcf54xx_reset;
-	m54xx_uarts_init();
-}
-
-/***************************************************************************/
-
-static int __init init_BSP(void)
-{
-
-	platform_add_devices(m54xx_devices, ARRAY_SIZE(m54xx_devices));
-	return 0;
-}
-
-arch_initcall(init_BSP);
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/54xx/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/54xx/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/54xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/54xx/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,18 +0,0 @@
-#
-# Makefile for the m68knommu linux kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# EXTRA_CFLAGS += -DTRAP_DBG_INTERRUPT
-# EXTRA_AFLAGS += -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-y := config.o
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/bootlogo.h linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/bootlogo.h
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/bootlogo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/bootlogo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,270 +0,0 @@
-#define bootlogo_width 160
-#define bootlogo_height 160
-static unsigned char bootlogo_bits[] = {
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x55, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x40, 0x55, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x55,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xac, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x10, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x82, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x08, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x00, 0x00,
-  0x00, 0xff, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0xf8, 0x80, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x50, 0x04, 0x00, 0x00, 0x00, 0x78, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x03, 0x00, 0x00,
-  0x00, 0x78, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x40,
-  0xa8, 0x02, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70, 0x28, 0x01, 0x00, 0x00,
-  0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x20, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x70,
-  0x54, 0x01, 0x00, 0x00, 0x00, 0x3e, 0x80, 0x01, 0x3a, 0x78, 0x80, 0x0e,
-  0x50, 0xc0, 0x03, 0x0e, 0x00, 0x20, 0x00, 0x00, 0xaa, 0x00, 0x00, 0x00,
-  0x00, 0x3e, 0xf0, 0x83, 0x1f, 0xfc, 0xe0, 0x0f, 0x78, 0xf8, 0x87, 0x1f,
-  0x00, 0x18, 0x00, 0x30, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xf8, 0xc3,
-  0x1f, 0xfc, 0xe0, 0x0f, 0x78, 0xf8, 0x87, 0x0f, 0x00, 0x20, 0x00, 0x10,
-  0x55, 0x00, 0x00, 0x00, 0x00, 0x1e, 0xc0, 0x03, 0x9f, 0xf3, 0x80, 0x0f,
-  0x78, 0x80, 0xc7, 0x0e, 0x00, 0x18, 0x00, 0x20, 0xaa, 0x00, 0x00, 0x00,
-  0x00, 0x1e, 0xe0, 0x03, 0x9f, 0xf1, 0x80, 0x07, 0x78, 0x80, 0x67, 0x00,
-  0x00, 0x24, 0x00, 0x18, 0x55, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x01,
-  0x5e, 0xf0, 0x80, 0x07, 0x3c, 0x00, 0x2f, 0x00, 0x00, 0x14, 0x00, 0x20,
-  0xaa, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xe0, 0x01, 0x7f, 0xf0, 0x80, 0x07,
-  0x3c, 0x00, 0x3f, 0x00, 0x00, 0x08, 0x00, 0x18, 0x55, 0x00, 0x00, 0x00,
-  0x00, 0x0f, 0xe0, 0x00, 0x3f, 0xf0, 0xc0, 0x03, 0x1e, 0x00, 0x1f, 0x00,
-  0x00, 0x14, 0x00, 0x28, 0xaa, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xf0, 0x00,
-  0x1f, 0xf0, 0xc0, 0x03, 0x1f, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x00, 0x0c,
-  0x54, 0x00, 0x00, 0x00, 0x80, 0x07, 0x78, 0x00, 0x1f, 0x78, 0xc0, 0x03,
-  0x1f, 0x00, 0x1e, 0x00, 0x00, 0x0a, 0x00, 0x12, 0xa8, 0x00, 0x00, 0x00,
-  0x80, 0x07, 0x78, 0x00, 0x1f, 0x78, 0xe0, 0x03, 0x1f, 0x00, 0x1f, 0x00,
-  0x00, 0x04, 0x00, 0x0a, 0x54, 0x00, 0x00, 0x00, 0x80, 0x07, 0x78, 0x80,
-  0x0f, 0x78, 0xe0, 0x03, 0x1f, 0x00, 0x1e, 0x00, 0x00, 0x0a, 0x00, 0x08,
-  0x50, 0x01, 0x00, 0x00, 0x84, 0x03, 0x78, 0x80, 0x07, 0x3c, 0xe0, 0xc1,
-  0x0f, 0x00, 0x1f, 0x00, 0x00, 0x04, 0x00, 0x06, 0xa8, 0x00, 0x00, 0x00,
-  0xc0, 0x03, 0x78, 0xc0, 0x07, 0x3c, 0xe0, 0xc1, 0x0f, 0x00, 0x1f, 0x00,
-  0x00, 0x0a, 0x00, 0x08, 0x50, 0x01, 0x00, 0x00, 0xc2, 0x01, 0x38, 0xc0,
-  0x07, 0x3c, 0xe0, 0x60, 0x0f, 0x80, 0x1e, 0x00, 0x00, 0x05, 0x00, 0x07,
-  0xa0, 0x00, 0x00, 0x80, 0xe0, 0x01, 0x3c, 0xc0, 0x07, 0x3c, 0xf0, 0xa0,
-  0x07, 0xc0, 0x1c, 0x00, 0x00, 0x0a, 0x80, 0x08, 0xa0, 0x02, 0x00, 0xa0,
-  0xe0, 0x21, 0x1c, 0xc0, 0x03, 0x1c, 0x71, 0x90, 0x47, 0x40, 0x3c, 0x04,
-  0x00, 0x05, 0x80, 0x06, 0xa0, 0x02, 0x00, 0x20, 0xe0, 0x31, 0x1e, 0xc3,
-  0x03, 0x1e, 0x79, 0x98, 0x47, 0x60, 0x38, 0x04, 0x00, 0x15, 0x40, 0x0a,
-  0xa0, 0x0a, 0x00, 0x1a, 0xe0, 0x19, 0x9e, 0xe1, 0x01, 0x9e, 0x78, 0xcc,
-  0xa7, 0x32, 0x78, 0x02, 0x80, 0x2a, 0x40, 0x05, 0x80, 0x2a, 0x00, 0x05,
-  0xe0, 0x0d, 0x9e, 0xe0, 0x01, 0xde, 0x78, 0xc6, 0x97, 0x1b, 0x78, 0x03,
-  0x80, 0x52, 0x30, 0x0a, 0x00, 0x95, 0xd2, 0x0a, 0xe0, 0x0f, 0xfe, 0xe0,
-  0x00, 0x7e, 0xf8, 0x87, 0x9f, 0x0f, 0xf8, 0x01, 0x00, 0xa1, 0x0e, 0x15,
-  0x80, 0x55, 0x55, 0x01, 0xe0, 0x01, 0x3c, 0xf0, 0x00, 0x3c, 0xf0, 0x80,
-  0x8f, 0x0f, 0x70, 0x00, 0x00, 0x81, 0x02, 0x14, 0x00, 0x54, 0x55, 0x00,
-  0xc0, 0x01, 0x3c, 0x00, 0x00, 0x0c, 0x60, 0x00, 0x07, 0x03, 0x70, 0x00,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x40, 0x01, 0x00, 0x11, 0x09, 0x00, 0x04, 0x00, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00,
-  0x00, 0x20, 0x01, 0x00, 0x04, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x49, 0x32, 0x49, 0x49, 0x91,
-  0x24, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x20, 0x49, 0x0a, 0x09, 0xc9, 0x92, 0x14, 0x81, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x49,
-  0x18, 0x01, 0x49, 0x92, 0x0c, 0x43, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x49, 0x30, 0x01, 0x49, 0x92,
-  0x14, 0x26, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x08, 0x69, 0x22, 0x09, 0x49, 0xd2, 0x24, 0x24, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x51,
-  0x1a, 0x09, 0x49, 0xa2, 0x44, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x87, 0x08, 0x00, 0x00, 0x00,
-  0xf2, 0xf0, 0xf0, 0xf0, 0xf0, 0x00, 0xf0, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x40, 0x88, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09, 0x09, 0x09,
-  0x09, 0x01, 0x10, 0x01, 0x08, 0x00, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80,
-  0x88, 0x86, 0x48, 0x04, 0x09, 0x08, 0x01, 0x01, 0x09, 0x01, 0x10, 0x71,
-  0x88, 0x66, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, 0x88, 0x89, 0x48, 0x84,
-  0x08, 0x08, 0x01, 0x01, 0x09, 0x01, 0x10, 0x89, 0x88, 0x99, 0x00, 0x00,
-  0x00, 0x40, 0x24, 0x80, 0x88, 0x88, 0x88, 0x82, 0xf8, 0xf0, 0xe0, 0x80,
-  0xf0, 0xf8, 0x13, 0x81, 0x88, 0x88, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80,
-  0x88, 0x88, 0x08, 0x81, 0x08, 0x09, 0x01, 0x41, 0x08, 0x01, 0xf0, 0xf0,
-  0x88, 0x88, 0x00, 0x00, 0x00, 0x40, 0x24, 0x80, 0x88, 0x88, 0x88, 0x42,
-  0x08, 0x09, 0x01, 0x21, 0x08, 0x01, 0x10, 0x88, 0x88, 0x88, 0x00, 0x00,
-  0x00, 0x40, 0x46, 0x88, 0x88, 0x88, 0x4c, 0x44, 0x08, 0x09, 0x09, 0x11,
-  0x08, 0x01, 0x10, 0x88, 0x88, 0x88, 0x00, 0x00, 0x00, 0x80, 0x85, 0x87,
-  0x88, 0x08, 0x4b, 0x24, 0xf0, 0xf0, 0xf0, 0xf8, 0xf1, 0x00, 0x10, 0x70,
-  0x89, 0x88, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x3f, 0x0f, 0x00, 0x00, 0x08, 0x02, 0x04, 0x00,
-  0x00, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x1f, 0x00, 0x00, 0x48, 0x62, 0xc4, 0x31, 0x4a, 0x18, 0x3c, 0x03,
-  0x21, 0x45, 0x92, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x1f, 0x00, 0x00,
-  0x48, 0x92, 0x24, 0x48, 0xb6, 0x24, 0x88, 0x04, 0x21, 0x4b, 0x92, 0x00,
-  0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00, 0xa8, 0xf2, 0x24, 0x48,
-  0x92, 0x3c, 0x88, 0x04, 0x21, 0x49, 0x62, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x10, 0x11, 0x24, 0x48, 0x92, 0x04, 0x88, 0x04,
-  0x21, 0x49, 0x62, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0x00, 0x00,
-  0x10, 0x11, 0x24, 0x48, 0x92, 0x04, 0x88, 0x04, 0x21, 0x49, 0x93, 0x00,
-  0x00, 0x00, 0x80, 0xff, 0xcf, 0x7e, 0x00, 0x00, 0x10, 0xe1, 0xc4, 0x31,
-  0x92, 0x38, 0x30, 0x03, 0x2f, 0x89, 0x92, 0x00, 0x00, 0x00, 0x80, 0xe3,
-  0x07, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x03, 0x7e, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0xc9, 0x23, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x95,
-  0x33, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xdd, 0xfb, 0x7e, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x1d, 0xf8, 0x7e, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x40, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9b,
-  0x70, 0x7e, 0x00, 0x00, 0x08, 0x00, 0xe0, 0x00, 0x02, 0x00, 0x47, 0x80,
-  0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x80, 0x03, 0x00, 0x7e, 0x00, 0x00,
-  0x3c, 0xa3, 0x20, 0x31, 0x52, 0x02, 0x49, 0xcc, 0x3f, 0xa3, 0x94, 0x08,
-  0x00, 0x00, 0x00, 0x27, 0x02, 0x7e, 0x00, 0x00, 0x88, 0xe4, 0x20, 0x41,
-  0xb2, 0x05, 0x49, 0x90, 0x88, 0xe4, 0x6c, 0x09, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x7e, 0x00, 0x00, 0x88, 0x24, 0xe0, 0x70, 0x92, 0x04, 0x47, 0x9c,
-  0x88, 0x24, 0x24, 0x09, 0x00, 0x00, 0x00, 0x13, 0x48, 0x7e, 0x00, 0x00,
-  0x88, 0x24, 0x20, 0x48, 0x92, 0x04, 0x41, 0x92, 0x88, 0x24, 0x24, 0x01,
-  0x00, 0x00, 0x00, 0x43, 0x00, 0xfe, 0x00, 0x00, 0x88, 0x24, 0x20, 0x48,
-  0x92, 0x04, 0x41, 0x92, 0x88, 0x24, 0x24, 0x09, 0x00, 0x00, 0x00, 0x07,
-  0x94, 0xce, 0x00, 0x00, 0x08, 0x23, 0x20, 0xb0, 0x92, 0x04, 0x41, 0x2c,
-  0x0b, 0x23, 0x24, 0x09, 0x00, 0x00, 0x00, 0x49, 0x02, 0xce, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x11, 0x08, 0xdc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
-  0x01, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0xf8, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x01, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01,
-  0x00, 0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xf0, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x70, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00,
-  0x00, 0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x3c, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00,
-  0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xc0, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x1f, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00,
-  0x00, 0x80, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00,
-  0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0xfe, 0x0f,
-  0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x05, 0x00, 0x00, 0x80, 0x08, 0x00,
-  0x00, 0xc0, 0x03, 0x00, 0x78, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x40, 0x10,
-  0x12, 0x10, 0x05, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00,
-  0x84, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x20, 0x26, 0x0a, 0x10, 0x9d, 0x39,
-  0xa6, 0xb2, 0x0a, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x02, 0x00, 0xfe, 0x0f,
-  0x00, 0x00, 0x20, 0x21, 0x06, 0x28, 0x25, 0x4a, 0xa9, 0x8a, 0x09, 0x00,
-  0x00, 0xe0, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x20, 0x21,
-  0x0e, 0x38, 0xa5, 0x4b, 0xa9, 0xb2, 0x09, 0x00, 0x00, 0xf0, 0x01, 0x22,
-  0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x20, 0x21, 0x12, 0x44, 0xa5, 0x4a,
-  0x49, 0xa1, 0x0a, 0x00, 0x00, 0xf8, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f,
-  0x00, 0x00, 0x20, 0x26, 0x52, 0x44, 0x9d, 0x4d, 0x46, 0x99, 0x0a, 0x00,
-  0x00, 0xfc, 0x01, 0x22, 0x02, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x40, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x01, 0xb2,
-  0x84, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x7c, 0x01, 0x6e, 0x78, 0x00, 0xfc, 0x1f,
-  0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfc, 0x01, 0x02, 0x00, 0x00, 0xfc, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x01, 0x02,
-  0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x06, 0x00, 0x00, 0xfc, 0x0f,
-  0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x20, 0x01, 0x02, 0x00, 0x00, 0x00,
-  0x00, 0x24, 0x06, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x40, 0x10,
-  0x1e, 0x20, 0x90, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00,
-  0x00, 0x80, 0xfc, 0x03, 0x00, 0x00, 0x20, 0x26, 0x22, 0x20, 0xf9, 0x89,
-  0x32, 0xe7, 0x08, 0x00, 0x00, 0x92, 0x38, 0x00, 0x00, 0x00, 0xfc, 0x01,
-  0x00, 0x00, 0x20, 0x21, 0x22, 0xa0, 0x92, 0x88, 0x4a, 0x29, 0x15, 0x00,
-  0x00, 0x00, 0x78, 0x00, 0x00, 0x40, 0xfa, 0x04, 0x00, 0x00, 0x20, 0x21,
-  0x22, 0xa0, 0x93, 0x88, 0x4a, 0x29, 0x1d, 0x00, 0x00, 0x11, 0xf2, 0x00,
-  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x20, 0x21, 0x22, 0xa8, 0x90, 0x88,
-  0x4a, 0x29, 0x05, 0x00, 0x48, 0x40, 0xf0, 0x01, 0x00, 0x80, 0x14, 0x04,
-  0x00, 0x00, 0x20, 0x26, 0x9e, 0x10, 0x93, 0x78, 0x32, 0x29, 0x19, 0x00,
-  0x00, 0x09, 0xe0, 0x03, 0x00, 0x00, 0x80, 0x10, 0x00, 0x00, 0x40, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0xc5, 0x03,
-  0x00, 0x40, 0x22, 0x00, 0x00, 0x00, 0x80, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0xc0, 0x07, 0x00, 0x20, 0x08, 0x04,
-  0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x50, 0x90, 0x03, 0x00, 0xb0, 0x00, 0x41, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
-  0x00, 0x38, 0x22, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x48, 0x04, 0x44, 0x00, 0x00, 0x3c, 0x08, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x20, 0x00, 0x00, 0x00, 0xbf, 0x40, 0x42, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x24, 0x80, 0x48, 0x02,
-  0xc0, 0x1f, 0x00, 0x08, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4e, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x0a, 0x00, 0x05, 0xf0, 0x3f, 0x09, 0x00,
-  0x00, 0x10, 0x24, 0x48, 0x10, 0x12, 0x41, 0x52, 0x24, 0x09, 0x46, 0x71,
-  0x90, 0x20, 0x02, 0xfc, 0xff, 0x1f, 0x80, 0x22, 0x00, 0x90, 0x24, 0x49,
-  0x12, 0x92, 0x40, 0xb2, 0x24, 0x09, 0xc9, 0x49, 0x04, 0x80, 0x90, 0xfc,
-  0xff, 0xbf, 0x24, 0x00, 0x00, 0x90, 0x24, 0x49, 0x12, 0x92, 0x40, 0x92,
-  0x24, 0x06, 0x49, 0x48, 0x50, 0x0a, 0x02, 0xfe, 0xff, 0x3f, 0x00, 0x05,
-  0x00, 0x50, 0xa5, 0x4a, 0x15, 0x92, 0x40, 0x92, 0x24, 0x06, 0x49, 0x48,
-  0x80, 0x40, 0x48, 0xfe, 0xff, 0x3f, 0x49, 0x00, 0x00, 0x20, 0x42, 0x84,
-  0x88, 0x1a, 0x41, 0x92, 0x34, 0x49, 0x49, 0x68, 0x00, 0x38, 0x10, 0x07,
-  0x00, 0x60, 0x80, 0x00, 0x00, 0x20, 0x42, 0x84, 0x88, 0x14, 0x4e, 0x92,
-  0x28, 0x49, 0x46, 0x50, 0x00, 0x80, 0x83, 0x01, 0x00, 0xa0, 0x6a, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40,
-  0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x3b, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, };
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/bootlogo.pl linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/bootlogo.pl
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/bootlogo.pl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/bootlogo.pl	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-
-$_ = join("", <>);
-
-s/(0x[0-9a-f]{2})/sprintf("0x%.2x",ord(pack("b8",unpack("B8",chr(hex($1))))))/gei;
-
-s/^ /	.byte /gm;
-s/[,};]+$//gm;
-s/^static.*//gm;
-
-print $_;
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/***************************************************************************/
-
-/*
- *  linux/arch/m68knommu/platform/68328/config.c
- *
- *  Copyright (C) 1993 Hamish Macdonald
- *  Copyright (C) 1999 D. Jeff Dionne
- *
- * 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.
- *
- * VZ Support/Fixes             Evan Stawnyczy <e@lineo.ca>
- */
-
-/***************************************************************************/
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/machdep.h>
-#include <asm/MC68328.h>
-
-/***************************************************************************/
-
-void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
-
-/***************************************************************************/
-
-void m68328_reset (void)
-{
-  local_irq_disable();
-  asm volatile ("moveal #0x10c00000, %a0;\n\t"
-		"moveb #0, 0xFFFFF300;\n\t"
-		"moveal 0(%a0), %sp;\n\t"
-		"moveal 4(%a0), %a0;\n\t"
-		"jmp (%a0);");
-}
-
-/***************************************************************************/
-
-void config_BSP(char *command, int len)
-{
-  printk(KERN_INFO "\n68328 support D. Jeff Dionne <jeff@uclinux.org>\n");
-  printk(KERN_INFO "68328 support Kenneth Albanowski <kjahds@kjshds.com>\n");
-  printk(KERN_INFO "68328/Pilot support Bernhard Kuhn <kuhn@lpr.e-technik.tu-muenchen.de>\n");
-
-  mach_gettod = m68328_timer_gettod;
-  mach_reset = m68328_reset;
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/entry.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/entry.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/entry.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-/*
- *  linux/arch/m68knommu/platform/68328/entry.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- * Linux/m68k support by Hamish Macdonald
- */
-
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/traps.h>
-#include <asm/asm-offsets.h>
-#include <asm/entry.h>
-
-.text
-
-.globl system_call
-.globl resume
-.globl ret_from_exception
-.globl ret_from_signal
-.globl sys_call_table
-.globl ret_from_interrupt
-.globl bad_interrupt
-.globl inthandler1
-.globl inthandler2
-.globl inthandler3
-.globl inthandler4
-.globl inthandler5
-.globl inthandler6
-.globl inthandler7
-
-badsys:
-	movel	#-ENOSYS,%sp@(PT_OFF_D0)
-	jra	ret_from_exception
-
-do_trace:
-	movel	#-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
-	subql	#4,%sp
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace_enter
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	movel	%sp@(PT_OFF_ORIG_D0),%d1
-	movel	#-ENOSYS,%d0
-	cmpl	#NR_syscalls,%d1
-	jcc	1f
-	lsl	#2,%d1
-	lea	sys_call_table, %a0
-	jbsr	%a0@(%d1)
-
-1:	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
-	subql	#4,%sp			/* dummy return address */
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace_leave
-
-ret_from_signal:
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jra	ret_from_exception
-
-ENTRY(system_call)
-	SAVE_ALL
-
-	/* save top of frame*/
-	pea	%sp@
-	jbsr	set_esp0
-	addql	#4,%sp
-
-	movel	%sp@(PT_OFF_ORIG_D0),%d0
-
-	movel	%sp,%d1			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d1
-	movel	%d1,%a2
-	btst	#(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
-	jne	do_trace
-	cmpl	#NR_syscalls,%d0
-	jcc	badsys
-	lsl	#2,%d0
-	lea	sys_call_table,%a0
-	movel	%a0@(%d0), %a0
-	jbsr	%a0@
-	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/
-
-ret_from_exception:
-	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
-	jeq	Luser_return		/* if so, skip resched, signals*/
-
-Lkernel_return:
-	RESTORE_ALL
-
-Luser_return:
-	/* only allow interrupts when we are really the last one on the*/
-	/* kernel stack, otherwise stack overflow can occur during*/
-	/* heavy interrupt load*/
-	andw	#ALLOWINT,%sr
-
-	movel	%sp,%d1			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d1
-	movel	%d1,%a2
-1:
-	move	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
-	jne	Lwork_to_do
-	RESTORE_ALL
-
-Lwork_to_do:
-	movel	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
-	btst	#TIF_NEED_RESCHED,%d1
-	jne	reschedule
-
-Lsignal_return:
-	subql	#4,%sp			/* dummy return address*/
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	bsrw	do_signal
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jra	1b
-
-/*
- * This is the main interrupt handler, responsible for calling process_int()
- */
-inthandler1:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#65,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler2:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#66,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler3:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#67,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler4:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#68,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler5:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#69,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler6:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#70,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler7:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	#71,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-inthandler:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and	#0x3ff, %d0
-
-	movel	%sp,%sp@-
-	movel	%d0,%sp@- 		/*  put vector # on stack*/
-	jbsr	process_int		/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-ret_from_interrupt:
-	jeq	1f
-2:
-	RESTORE_ALL
-1:
-	moveb	%sp@(PT_OFF_SR), %d0
-	and	#7, %d0
-	jhi	2b
-
-	/* check if we need to do software interrupts */
-	jeq	ret_from_exception
-
-	pea	ret_from_exception
-	jra	do_softirq
-
-
-/*
- * Handler for uninitialized and spurious interrupts.
- */
-ENTRY(bad_interrupt)
-	addql	#1,num_spurious
-	rte
-
-/*
- * Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
- * registers until their contents are no longer needed.
- */
-ENTRY(resume)
-	movel	%a0,%d1				/* save prev thread in d1 */
-	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
-	movel	%usp,%a2			/* save usp */
-	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
-
-	SAVE_SWITCH_STACK
-	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
-	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
-	RESTORE_SWITCH_STACK
-
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
-	movel	%a0,%usp
-	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
-	rts
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-de2.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-de2.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-de2.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-de2.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,128 +0,0 @@
-
-#define	MEM_END	0x00800000	/* Memory size 8Mb */
-
-#undef CRT_DEBUG
-
-.macro	PUTC CHAR
-#ifdef CRT_DEBUG
-	moveq	#\CHAR, %d7
-	jsr	putc
-#endif
-.endm
-
-	.global	_start
-	.global _rambase
-	.global _ramvec
-	.global	_ramstart
-	.global	_ramend
-	
-	.data
-
-/*
- *	Set up the usable of RAM stuff
- */
-_rambase:
-	.long	0
-_ramvec:
-	.long	0
-_ramstart:
-	.long	0
-_ramend:
-	.long	0
-
-	.text
-
-_start:
-
-/*
- * Setup initial stack
- */
-	/* disable all interrupts */
-	movew	#0x2700, %sr
-	movel	#-1, 0xfffff304
-	movel	#MEM_END-4, %sp
-
-	PUTC	'\r'
-	PUTC	'\n'
-	PUTC	'A'
-	PUTC	'B'
-
-/*
- *	Determine end of RAM
- */
-
-	movel	#MEM_END, %a0
-	movel	%a0, _ramend
-
-	PUTC	'C'
-
-/*
- *	Move ROM filesystem above bss :-)
- */
-
-	moveal	#_sbss, %a0			/* romfs at the start of bss */
-	moveal	#_ebss, %a1			/* Set up destination  */
-	movel	%a0, %a2			/* Copy of bss start */
-
-	movel	8(%a0), %d1			/* Get size of ROMFS */
-	addql	#8, %d1				/* Allow for rounding */
-	andl	#0xfffffffc, %d1	/* Whole words */
-
-	addl	%d1, %a0			/* Copy from end */
-	addl	%d1, %a1			/* Copy from end */
-	movel	%a1, _ramstart		/* Set start of ram */
-
-1:
-	movel	-(%a0), %d0			/* Copy dword */
-	movel	%d0, -(%a1)
-	cmpl	%a0, %a2			/* Check if at end */
-	bne	1b
-
-	PUTC	'D'
-
-/*
- * Initialize BSS segment to 0
- */
-
-	lea	_sbss, %a0
-	lea	_ebss, %a1
-
-	/* Copy 0 to %a0 until %a0 == %a1 */
-2:	cmpal	%a0, %a1
-	beq	1f
-	clrl	(%a0)+
-	bra	2b
-1:
-
-	PUTC	'E'
-
-/*
- * Load the current task pointer and stack
- */
-
-	lea	init_thread_union, %a0
-	lea	0x2000(%a0), %sp
-
-	PUTC	'F'
-	PUTC	'\r'
-	PUTC	'\n'
-
-/*
- * Go
- */
-
-	jmp	start_kernel
-
-/*
- * Local functions
- */
- 
-#ifdef CRT_DEBUG
-putc:
-	moveb	%d7, 0xfffff907
-1:
-	movew	0xfffff906, %d7
-	andw	#0x2000, %d7
-	beq	1b
-	rts
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-pilot.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-pilot.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-pilot.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-pilot.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,222 +0,0 @@
-/*
- * linux/arch/m68knommu/platform/68328/head-pilot.S
- * - A startup file for the MC68328
- *
- * Copyright (C) 1998  D. Jeff Dionne <jeff@ryeham.ee.ryerson.ca>,
- *                     Kenneth Albanowski <kjahds@kjahds.com>,
- *                     The Silver Hammer Group, Ltd.
- *
- * (c) 1995, Dionne & Associates
- * (c) 1995, DKG Display Tech.
- */
-
-#define ASSEMBLY
-
-#define IMMED #
-#define	DBG_PUTC(x)	moveb IMMED x, 0xfffff907
-
-
-.global _stext
-.global _start
-
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-.global penguin_bits
-
-#ifdef CONFIG_PILOT
-
-#define IMR 0xFFFFF304
-
-	.data
-	.align 16
-
-penguin_bits:	
-#include "bootlogo.rh"
-
-#endif
-
-/*****************************************************************************/
-
-.data
-
-/*
- *      Set up the usable of RAM stuff. Size of RAM is determined then
- *      an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long   0
-_rambase:
-.long   0
-_ramstart:
-.long   0
-_ramend:
-.long   0
-
-.text
-	
-_start:
-_stext:
-
-
-#ifdef CONFIG_M68328
-
-#ifdef CONFIG_PILOT
-	.byte 0x4e, 0xfa, 0x00, 0x0a /* Jmp +X bytes */
-	.byte 'b', 'o', 'o', 't'
-	.word 10000
-
-	nop
-#endif
-
-	moveq	#0, %d0
-	movew   %d0, 0xfffff618 /* Watchdog off */
-	movel	#0x00011f07, 0xfffff114 /* CS A1 Mask */
-
-	movew	#0x0800, 0xfffff906 /* Ignore CTS */
-	movew	#0x010b, 0xfffff902 /* BAUD to 9600 */
-
-	movew	#0x2410, 0xfffff200 /* PLLCR */
-	movew	#0x123, 0xfffff202 /* PLLFSR */
-
-#ifdef CONFIG_PILOT
-	moveb	#0, 0xfffffA27 /* LCKCON */
-	movel   #_start, 0xfffffA00 /* LSSA */
-	moveb   #0xa, 0xfffffA05 /* LVPW */
-	movew	#0x9f, 0xFFFFFa08 /* LXMAX */
-	movew	#0x9f, 0xFFFFFa0a /* LYMAX */
-	moveb   #9, 0xfffffa29 /* LBAR */
-	moveb   #0, 0xfffffa25 /* LPXCD */
-	moveb	#0x04, 0xFFFFFa20 /* LPICF */
-	moveb	#0x58, 0xfffffA27 /* LCKCON */
-	moveb	#0x85, 0xfffff429 /* PFDATA */
-	moveb	#0xd8, 0xfffffA27 /* LCKCON */
-	moveb	#0xc5, 0xfffff429 /* PFDATA */
-	moveb	#0xd5, 0xfffff429 /* PFDATA */
-
-	moveal	#0x00100000, %a3
-	moveal	#0x100ffc00, %a4
-#endif /* CONFIG_PILOT */
-
-#endif /* CONFIG_M68328 */
-
-	movew   #0x2700, %sr
-	lea	%a4@(-4), %sp
-
-	DBG_PUTC('\r')
-	DBG_PUTC('\n')
-	DBG_PUTC('A')
-
-   	moveq   #0,%d0
-	movew	#16384, %d0  /* PLL settle wait loop */
-L0:
-	subw	#1, %d0
-	bne	L0
-
-	DBG_PUTC('B')
-
-	/* Copy command line from beginning of RAM (+16) to end of bss */
-	movel	#CONFIG_VECTORBASE, %d7
-	addl	#16, %d7
-	moveal	%d7, %a0
-	moveal	#_ebss, %a1
-	lea	%a1@(512), %a2
-
-	DBG_PUTC('C')
-
-	/* Copy %a0 to %a1 until %a1 == %a2 */
-L2:
-	movel	%a0@+, %d0
-	movel	%d0, %a1@+
-	cmpal	%a1, %a2
-	bhi	L2
-
-	/* Copy data+init segment from ROM to RAM */
-	moveal	#_etext, %a0
-	moveal	#_sdata, %a1
-	moveal	#__init_end, %a2
-
-	DBG_PUTC('D')
-
-	/* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
-	movel	%a0@+, %d0
-	movel	%d0, %a1@+
-	cmpal	%a1, %a2
-	bhi	LD1
-
-	DBG_PUTC('E')
-
-	moveal	#_sbss, %a0
-	moveal	#_ebss, %a1
-
-	/* Copy 0 to %a0 until %a0 == %a1 */
-L1:
-	movel	#0, %a0@+
-	cmpal	%a0, %a1
-	bhi	L1
-
-	DBG_PUTC('F')
-
-	/* Copy command line from end of bss to command line */
-	moveal	#_ebss, %a0
-	moveal	#command_line, %a1
-	lea	%a1@(512), %a2
-
-	DBG_PUTC('G')
-
-	/* Copy %a0 to %a1 until %a1 == %a2 */
-L3:
-	movel	%a0@+, %d0
-	movel	%d0, %a1@+
-	cmpal	%a1, %a2
-	bhi	L3
-
-	movel	#_sdata, %d0	
-	movel	%d0, _rambase	
-	movel	#_ebss,	%d0
-	movel	%d0, _ramstart
-
-	movel	%a4, %d0
-	subl	#4096, %d0	/* Reserve 4K of stack */
-	moveq	#79, %d7
-	movel	%d0, _ramend
-
-	movel	%a3, %d0
-	movel	%d0, rom_length
-
-	pea	0
-	pea	env
-	pea	%sp@(4)
-	pea	0
-
-	DBG_PUTC('H')
-
-#ifdef CONFIG_PILOT
-	movel	#penguin_bits, 0xFFFFFA00
-	moveb	#10, 0xFFFFFA05
-	movew	#160, 0xFFFFFA08
-	movew	#160, 0xFFFFFA0A
-#endif /* CONFIG_PILOT */
-
-	DBG_PUTC('I')
-
-	lea	init_thread_union, %a0
-	lea	0x2000(%a0), %sp
-
-	DBG_PUTC('J')
-	DBG_PUTC('\r')
-	DBG_PUTC('\n')
-
-	jsr	start_kernel
-_exit:
-
-	jmp	_exit
-
-
-	.data
-env:
-	.long	0
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-ram.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-ram.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-ram.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-ram.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,141 +0,0 @@
-
-	.global __main
-	.global __rom_start
-
-        .global _rambase
-        .global _ramstart
-	
-	.global splash_bits
-	.global _start
-	.global _stext
-	.global _edata
-
-#define DEBUG
-#define ROM_OFFSET 0x10C00000
-#define STACK_GAURD 0x10
-
-	.text
-	
-_start:
-_stext:
-	movew	#0x2700, %sr            /* Exceptions off! */
-
-#if 0
-	/* Init chip registers.  uCsimm specific */
-	moveb	#0x00,   0xfffffb0b	/* Watchdog off */
-	moveb	#0x10,   0xfffff000	/* SCR */
-
-	movew   #0x2400, 0xfffff200	/* PLLCR */
-	movew   #0x0123, 0xfffff202	/* PLLFSR */
-
-	moveb	#0x00,   0xfffff40b	/* enable chip select */
-	moveb	#0x00,   0xfffff423	/* enable /DWE */
-	moveb	#0x08,   0xfffffd0d	/* disable hardmap */
-	moveb	#0x07,   0xfffffd0e	/* level 7 interrupt clear */
-
-	movew	#0x8600, 0xfffff100	/* FLASH at 0x10c00000 */
-	movew	#0x018b, 0xfffff110	/* 2Meg, enable, 0ws */
-
-	movew	#0x8f00, 0xfffffc00	/* DRAM configuration */
-	movew	#0x9667, 0xfffffc02	/* DRAM control */
-	movew	#0x0000, 0xfffff106	/* DRAM at 0x00000000 */
-	movew	#0x068f, 0xfffff116	/* 8Meg, enable, 0ws */
-
-	moveb	#0x40,   0xfffff300	/* IVR */
-	movel	#0x007FFFFF, %d0	/* IMR */
-	movel	%d0,     0xfffff304
-
-	moveb	0xfffff42b, %d0
-	andb	#0xe0,	 %d0
-	moveb	%d0,	 0xfffff42b
-
-	moveb	#0x08,   0xfffff907	/* Ignore CTS */
-	movew	#0x010b, 0xfffff902	/* BAUD to 9600 */
-	movew	#0xe100, 0xfffff900	/* enable */
-#endif
-
-	movew	#16384, %d0  /* PLL settle wait loop */
-L0:
-	subw	#1, %d0
-	bne	L0
-#ifdef DEBUG
-	moveq	#70, %d7		/* 'F' */
-	moveb	%d7,0xfffff907          /* No absolute addresses */
-pclp1:
-	movew	0xfffff906, %d7
-	andw	#0x2000, %d7
-	beq	pclp1
-#endif /* DEBUG */
-
-#ifdef DEBUG
-	moveq	#82, %d7		/* 'R' */
-	moveb	%d7,0xfffff907          /* No absolute addresses */
-pclp3:
-	movew	0xfffff906, %d7
-	andw	#0x2000, %d7
-	beq	pclp3
-#endif /* DEBUG */
-	moveal	#0x007ffff0, %ssp
-	moveal	#_sbss, %a0
-	moveal	#_ebss, %a1
-
-	/* Copy 0 to %a0 until %a0 >= %a1 */
-L1:
-	movel	#0, %a0@+
-	cmpal	%a0, %a1
-	bhi	L1
-
-#ifdef DEBUG
-	moveq	#67, %d7                /* 'C' */
-	jsr	putc
-#endif /* DEBUG */
-
-	pea	0
-	pea	env
-	pea	%sp@(4)
-	pea	0
-
-#ifdef DEBUG
-	moveq	#70, %d7		/* 'F' */
-	jsr	putc
-#endif /* DEBUG */
-
-lp:
-	jsr	start_kernel
-        jmp lp
-_exit:
-
-	jmp	_exit
-
-__main:
-	/* nothing */
-	rts
-
-#ifdef DEBUG
-putc:
-	moveb	%d7,0xfffff907
-pclp:
-	movew	0xfffff906, %d7
-	andw	#0x2000, %d7
-	beq	pclp
-	rts
-#endif /* DEBUG */
-
-	.data
-
-/*
- *      Set up the usable of RAM stuff. Size of RAM is determined then
- *      an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long   0
-_rambase:
-.long   0
-_ramstart:
-.long   0
-_ramend:
-.long   0
-
-env:
-	.long	0
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-rom.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-rom.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/head-rom.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/head-rom.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-	
-	.global _start
-	.global _stext
-
-	.global _rambase
-	.global _ramvec
-	.global _ramstart
-	.global _ramend
-
-#ifdef CONFIG_INIT_LCD
-	.global splash_bits
-#endif
-
-	.data
-
-/*
- *      Set up the usable of RAM stuff. Size of RAM is determined then
- *      an initial stack set up at the end.
- */
-.align 4
-_ramvec:
-.long   0
-_rambase:
-.long   0
-_ramstart:
-.long   0
-_ramend:
-.long   0
-
-#define	RAMEND	(CONFIG_RAMBASE + CONFIG_RAMSIZE)
-
-#ifdef CONFIG_INIT_LCD
-splash_bits:
-#include "bootlogo.rh"
-#endif
-	
-	.text
-_start:
-_stext:	movew	#0x2700,%sr
-#ifdef CONFIG_INIT_LCD
-	movel	#splash_bits, 0xfffffA00 /* LSSA */
-	moveb	#0x28,   0xfffffA05	/* LVPW */
-	movew	#0x280,  0xFFFFFa08	/* LXMAX */
-	movew	#0x1df,  0xFFFFFa0a	/* LYMAX */
-	moveb	#0,      0xfffffa29	/* LBAR */
-	moveb	#0,      0xfffffa25	/* LPXCD */
-	moveb	#0x08,   0xFFFFFa20	/* LPICF */
-	moveb	#0x01,   0xFFFFFA21	/* -ve pol */
-	moveb	#0x81,   0xfffffA27	/* LCKCON */
-	movew	#0xff00, 0xfffff412	/* LCD pins */
-#endif
-	moveal  #RAMEND-CONFIG_MEMORY_RESERVE*0x100000 - 0x10, %sp
-	movew	#32767, %d0  /* PLL settle wait loop */
-1:	subq	#1, %d0
-	bne	1b
-
-	/* Copy data segment from ROM to RAM */
-	moveal	#_etext, %a0
-	moveal	#_sdata, %a1
-	moveal	#_edata, %a2
-
-	/* Copy %a0 to %a1 until %a1 == %a2 */
-1:	movel	%a0@+, %a1@+
-	cmpal	%a1, %a2
-	bhi	1b
-
-	moveal	#_sbss, %a0
-	moveal	#_ebss, %a1
-	/* Copy 0 to %a0 until %a0 == %a1 */
-	
-1:
-	clrl	%a0@+
-	cmpal	%a0, %a1
-	bhi	1b
-
-        movel   #_sdata, %d0    
-        movel   %d0, _rambase        
-        movel   #_ebss, %d0
-        movel   %d0, _ramstart
-	movel	#RAMEND-CONFIG_MEMORY_RESERVE*0x100000, %d0
-	movel	%d0, _ramend
-	movel	#CONFIG_VECTORBASE,	%d0
-	movel	%d0, _ramvec
-	
-/*
- * load the current task pointer and stack
- */
-	lea	init_thread_union, %a0
-	lea	0x2000(%a0), %sp
-
-1:	jsr	start_kernel
-        bra 1b
-_exit:
-
-	jmp	_exit
-
-
-putc:
-	moveb	%d7,0xfffff907
-1:
-	movew	0xfffff906, %d7
-	andw	#0x2000, %d7
-	beq	1b
-	rts
-
-	.data
-env:
-	.long	0
-	.text
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/ints.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/ints.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/ints.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/ints.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,186 +0,0 @@
-/*
- * linux/arch/m68knommu/platform/68328/ints.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 1996 Roman Zippel
- * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <asm/traps.h>
-#include <asm/io.h>
-#include <asm/machdep.h>
-
-#if defined(CONFIG_M68328)
-#include <asm/MC68328.h>
-#elif defined(CONFIG_M68EZ328)
-#include <asm/MC68EZ328.h>
-#elif defined(CONFIG_M68VZ328)
-#include <asm/MC68VZ328.h>
-#endif
-
-/* assembler routines */
-asmlinkage void system_call(void);
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void trap3(void);
-asmlinkage void trap4(void);
-asmlinkage void trap5(void);
-asmlinkage void trap6(void);
-asmlinkage void trap7(void);
-asmlinkage void trap8(void);
-asmlinkage void trap9(void);
-asmlinkage void trap10(void);
-asmlinkage void trap11(void);
-asmlinkage void trap12(void);
-asmlinkage void trap13(void);
-asmlinkage void trap14(void);
-asmlinkage void trap15(void);
-asmlinkage void trap33(void);
-asmlinkage void trap34(void);
-asmlinkage void trap35(void);
-asmlinkage void trap36(void);
-asmlinkage void trap37(void);
-asmlinkage void trap38(void);
-asmlinkage void trap39(void);
-asmlinkage void trap40(void);
-asmlinkage void trap41(void);
-asmlinkage void trap42(void);
-asmlinkage void trap43(void);
-asmlinkage void trap44(void);
-asmlinkage void trap45(void);
-asmlinkage void trap46(void);
-asmlinkage void trap47(void);
-asmlinkage irqreturn_t bad_interrupt(int, void *);
-asmlinkage irqreturn_t inthandler(void);
-asmlinkage irqreturn_t inthandler1(void);
-asmlinkage irqreturn_t inthandler2(void);
-asmlinkage irqreturn_t inthandler3(void);
-asmlinkage irqreturn_t inthandler4(void);
-asmlinkage irqreturn_t inthandler5(void);
-asmlinkage irqreturn_t inthandler6(void);
-asmlinkage irqreturn_t inthandler7(void);
-
-extern e_vector *_ramvec;
-
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
-/* The 68k family did not have a good way to determine the source
- * of interrupts until later in the family.  The EC000 core does
- * not provide the vector number on the stack, we vector everything
- * into one vector and look in the blasted mask register...
- * This code is designed to be fast, almost constant time, not clean!
- */
-void process_int(int vec, struct pt_regs *fp)
-{
-	int irq;
-	int mask;
-
-	unsigned long pend = ISR;
-
-	while (pend) {
-		if (pend & 0x0000ffff) {
-			if (pend & 0x000000ff) {
-				if (pend & 0x0000000f) {
-					mask = 0x00000001;
-					irq = 0;
-				} else {
-					mask = 0x00000010;
-					irq = 4;
-				}
-			} else {
-				if (pend & 0x00000f00) {
-					mask = 0x00000100;
-					irq = 8;
-				} else {
-					mask = 0x00001000;
-					irq = 12;
-				}
-			}
-		} else {
-			if (pend & 0x00ff0000) {
-				if (pend & 0x000f0000) {
-					mask = 0x00010000;
-					irq = 16;
-				} else {
-					mask = 0x00100000;
-					irq = 20;
-				}
-			} else {
-				if (pend & 0x0f000000) {
-					mask = 0x01000000;
-					irq = 24;
-				} else {
-					mask = 0x10000000;
-					irq = 28;
-				}
-			}
-		}
-
-		while (! (mask & pend)) {
-			mask <<=1;
-			irq++;
-		}
-
-		do_IRQ(irq, fp);
-		pend &= ~mask;
-	}
-}
-
-static void intc_irq_unmask(unsigned int irq)
-{
-	IMR &= ~(1<<irq);
-}
-
-static void intc_irq_mask(unsigned int irq)
-{
-	IMR |= (1<<irq);
-}
-
-static struct irq_chip intc_irq_chip = {
-	.name		= "M68K-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-};
-
-/*
- * This function should be called during kernel startup to initialize
- * the machine vector table.
- */
-void __init init_IRQ(void)
-{
-	int i;
-
-	/* set up the vectors */
-	for (i = 72; i < 256; ++i)
-		_ramvec[i] = (e_vector) bad_interrupt;
-
-	_ramvec[32] = system_call;
-
-	_ramvec[65] = (e_vector) inthandler1;
-	_ramvec[66] = (e_vector) inthandler2;
-	_ramvec[67] = (e_vector) inthandler3;
-	_ramvec[68] = (e_vector) inthandler4;
-	_ramvec[69] = (e_vector) inthandler5;
-	_ramvec[70] = (e_vector) inthandler6;
-	_ramvec[71] = (e_vector) inthandler7;
-
-	IVR = 0x40; /* Set DragonBall IVR (interrupt base) to 64 */
-
-	/* turn off all interrupts */
-	IMR = ~0;
-
-	for (i = 0; (i < NR_IRQS); i++) {
-		set_irq_chip(i, &intc_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68328.
-#
-
-head-y			= head-$(MODEL).o
-head-$(CONFIG_PILOT)	= head-pilot.o
-head-$(CONFIG_DRAGEN2)	= head-de2.o
-
-obj-y			+= entry.o ints.o timers.o
-obj-$(CONFIG_M68328)	+= config.o
-obj-$(CONFIG_ROM)	+= romvec.o
-
-extra-y			:= head.o
-extra-$(CONFIG_M68328)	+= bootlogo.rh head.o
-
-$(obj)/bootlogo.rh: $(src)/bootlogo.h
-	perl $(src)/bootlogo.pl < $(src)/bootlogo.h > $(obj)/bootlogo.rh
-
-$(obj)/head.o: $(obj)/$(head-y)
-	ln -sf $(head-y) $(obj)/head.o
-
-clean-files := $(obj)/bootlogo.rh $(obj)/head.o $(head-y)
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/romvec.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/romvec.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/romvec.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/romvec.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*
- * linux/arch/m68knommu/platform/68328/romvec.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.
- *
- * Copyright 1996 Roman Zippel
- * Copyright 1999 D. Jeff Dionne <jeff@rt-control.com>
- * Copyright 2006 Greg Ungerer <gerg@snapgear.com>
- */
-
-.global _start
-.global _buserr
-.global trap
-.global system_call
-
-.section .romvec
-
-e_vectors:
-.long CONFIG_RAMBASE+CONFIG_RAMSIZE-4, _start, buserr, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-/* TRAP #0-15 */
-.long system_call, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long trap, trap, trap, trap
-.long 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/timers.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/timers.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68328/timers.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68328/timers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,134 +0,0 @@
-/***************************************************************************/
-
-/*
- *  linux/arch/m68knommu/platform/68328/timers.c
- *
- *  Copyright (C) 1993 Hamish Macdonald
- *  Copyright (C) 1999 D. Jeff Dionne
- *  Copyright (C) 2001 Georges Menie, Ken Desmet
- *
- * 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/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clocksource.h>
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/MC68VZ328.h>
-
-/***************************************************************************/
-
-#if defined(CONFIG_DRAGEN2)
-/* with a 33.16 MHz clock, this will give usec resolution to the time functions */
-#define CLOCK_SOURCE	TCTL_CLKSOURCE_SYSCLK
-#define CLOCK_PRE	7
-#define TICKS_PER_JIFFY	41450
-
-#elif defined(CONFIG_XCOPILOT_BUGS)
-/*
- * The only thing I know is that CLK32 is not available on Xcopilot
- * I have little idea about what frequency SYSCLK has on Xcopilot.
- * The values for prescaler and compare registers were simply
- * taken from the original source
- */
-#define CLOCK_SOURCE	TCTL_CLKSOURCE_SYSCLK
-#define CLOCK_PRE	2
-#define TICKS_PER_JIFFY	0xd7e4
-
-#else
-/* default to using the 32Khz clock */
-#define CLOCK_SOURCE	TCTL_CLKSOURCE_32KHZ
-#define CLOCK_PRE	31
-#define TICKS_PER_JIFFY	10
-#endif
-
-static u32 m68328_tick_cnt;
-
-/***************************************************************************/
-
-static irqreturn_t hw_tick(int irq, void *dummy)
-{
-	/* Reset Timer1 */
-	TSTAT &= 0;
-
-	m68328_tick_cnt += TICKS_PER_JIFFY;
-	return arch_timer_interrupt(irq, dummy);
-}
-
-/***************************************************************************/
-
-static struct irqaction m68328_timer_irq = {
-	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = hw_tick,
-};
-
-/***************************************************************************/
-
-static cycle_t m68328_read_clk(struct clocksource *cs)
-{
-	unsigned long flags;
-	u32 cycles;
-
-	local_irq_save(flags);
-	cycles = m68328_tick_cnt + TCN;
-	local_irq_restore(flags);
-
-	return cycles;
-}
-
-/***************************************************************************/
-
-static struct clocksource m68328_clk = {
-	.name	= "timer",
-	.rating	= 250,
-	.read	= m68328_read_clk,
-	.shift	= 20,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/***************************************************************************/
-
-void hw_timer_init(void)
-{
-	/* disable timer 1 */
-	TCTL = 0;
-
-	/* set ISR */
-	setup_irq(TMR_IRQ_NUM, &m68328_timer_irq);
-
-	/* Restart mode, Enable int, Set clock source */
-	TCTL = TCTL_OM | TCTL_IRQEN | CLOCK_SOURCE;
-	TPRER = CLOCK_PRE;
-	TCMP = TICKS_PER_JIFFY;
-
-	/* Enable timer 1 */
-	TCTL |= TCTL_TEN;
-	m68328_clk.mult = clocksource_hz2mult(TICKS_PER_JIFFY*HZ, m68328_clk.shift);
-	clocksource_register(&m68328_clk);
-}
-
-/***************************************************************************/
-
-void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec)
-{
-	long now = RTCTIME;
-
-	*year = *mon = *day = 1;
-	*hour = (now >> 24) % 24;
-	*min = (now >> 16) % 60;
-	*sec = now % 60;
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/commproc.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/commproc.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/commproc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/commproc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,308 +0,0 @@
-/*
- * General Purpose functions for the global management of the
- * Communication Processor Module.
- *
- * Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
- * Copyright (c) 1997 Dan Malek (dmalek@jlc.net)
- *
- * In addition to the individual control of the communication
- * channels, there are a few functions that globally affect the
- * communication processor.
- *
- * Buffer descriptors must be allocated from the dual ported memory
- * space.  The allocator for that is here.  When the communication
- * process is reset, we reclaim the memory available.  There is
- * currently no deallocator for this memory.
- * The amount of space available is platform dependent.  On the
- * MBX, the EPPC software loads additional microcode into the
- * communication processor, and uses some of the DP ram for this
- * purpose.  Current, the first 512 bytes and the last 256 bytes of
- * memory are used.  Right now I am conservative and only use the
- * memory that can never be used for microcode.  If there are
- * applications that require more DP ram, we can expand the boundaries
- * but then we have to be careful of any downloaded microcode.
- *
- */
-
-/*
- * Michael Leslie <mleslie@lineo.com>
- * adapted Dan Malek's ppc8xx drivers to M68360
- *
- */
-
-#include <linux/errno.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 <asm/irq.h>
-#include <asm/m68360.h>
-#include <asm/commproc.h>
-
-/* #include <asm/page.h> */
-/* #include <asm/pgtable.h> */
-extern void *_quicc_base;
-extern unsigned int system_clock;
-
-
-static uint dp_alloc_base;	/* Starting offset in DP ram */
-static uint dp_alloc_top;	/* Max offset + 1 */
-
-#if 0
-static	void	*host_buffer;	/* One page of host buffer */
-static	void	*host_end;	    /* end + 1 */
-#endif
-
-/* struct  cpm360_t *cpmp; */         /* Pointer to comm processor space */
-
-QUICC  *pquicc;
-/* QUICC  *quicc_dpram; */ /* mleslie - temporary; use extern pquicc elsewhere instead */
-
-
-/* CPM interrupt vector functions. */
-struct	cpm_action {
-	void	(*handler)(void *);
-	void	*dev_id;
-};
-static	struct	cpm_action cpm_vecs[CPMVEC_NR];
-static	void	cpm_interrupt(int irq, void * dev, struct pt_regs * regs);
-static	void	cpm_error_interrupt(void *);
-
-/* prototypes: */
-void cpm_install_handler(int vec, void (*handler)(), void *dev_id);
-void m360_cpm_reset(void);
-
-
-
-
-void m360_cpm_reset()
-{
-/* 	pte_t		   *pte; */
-
-	pquicc = (struct quicc *)(_quicc_base); /* initialized in crt0_rXm.S */
-
-	/* Perform a CPM reset. */
-	pquicc->cp_cr = (SOFTWARE_RESET | CMD_FLAG);
-
-	/* Wait for CPM to become ready (should be 2 clocks). */
-	while (pquicc->cp_cr & CMD_FLAG);
-
-	/* On the recommendation of the 68360 manual, p. 7-60
-	 * - Set sdma interrupt service mask to 7
-	 * - Set sdma arbitration ID to 4
-	 */
-	pquicc->sdma_sdcr = 0x0740;
-
-
-	/* Claim the DP memory for our use.
-	 */
-	dp_alloc_base = CPM_DATAONLY_BASE;
-	dp_alloc_top = dp_alloc_base + CPM_DATAONLY_SIZE;
-
-
-	/* Set the host page for allocation.
-	 */
-	/* 	host_buffer = host_page_addr; */
-	/* 	host_end = host_page_addr + PAGE_SIZE; */
-
-	/* 	pte = find_pte(&init_mm, host_page_addr); */
-	/* 	pte_val(*pte) |= _PAGE_NO_CACHE; */
-	/* 	flush_tlb_page(current->mm->mmap, host_buffer); */
-
-	/* Tell everyone where the comm processor resides.
-	*/
-/* 	cpmp = (cpm360_t *)commproc; */
-}
-
-
-/* This is called during init_IRQ.  We used to do it above, but this
- * was too early since init_IRQ was not yet called.
- */
-void
-cpm_interrupt_init(void)
-{
-	/* Initialize the CPM interrupt controller.
-	 * NOTE THAT pquicc had better have been initialized!
-	 * reference: MC68360UM p. 7-377
-	 */
-	pquicc->intr_cicr =
-		(CICR_SCD_SCC4 | CICR_SCC_SCC3 | CICR_SCB_SCC2 | CICR_SCA_SCC1) |
-		(CPM_INTERRUPT << 13) |
-		CICR_HP_MASK |
-		(CPM_VECTOR_BASE << 5) |
-		CICR_SPS;
-
-	/* mask all CPM interrupts from reaching the cpu32 core: */
-	pquicc->intr_cimr = 0;
-
-
-	/* mles - If I understand correctly, the 360 just pops over to the CPM
-	 * specific vector, obviating the necessity to vector through the IRQ
-	 * whose priority the CPM is set to. This needs a closer look, though.
-	 */
-
-	/* Set our interrupt handler with the core CPU. */
-/* 	if (request_irq(CPM_INTERRUPT, cpm_interrupt, 0, "cpm", NULL) != 0) */
-/* 		panic("Could not allocate CPM IRQ!"); */
-
-	/* Install our own error handler.
-	 */
-	/* I think we want to hold off on this one for the moment - mles */
-	/* cpm_install_handler(CPMVEC_ERROR, cpm_error_interrupt, NULL); */
-
-	/* master CPM interrupt enable */
-	/* pquicc->intr_cicr |= CICR_IEN; */ /* no such animal for 360 */
-}
-
-
-
-/* CPM interrupt controller interrupt.
-*/
-static	void
-cpm_interrupt(int irq, void * dev, struct pt_regs * regs)
-{
-	/* uint	vec; */
-
-	/* mles: Note that this stuff is currently being performed by
-	 * M68360_do_irq(int vec, struct pt_regs *fp), in ../ints.c  */
-
-	/* figure out the vector */
-	/* call that vector's handler */
-	/* clear the irq's bit in the service register */
-
-#if 0 /* old 860 stuff: */
-	/* Get the vector by setting the ACK bit and then reading
-	 * the register.
-	 */
-	((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr = 1;
-	vec = ((volatile immap_t *)IMAP_ADDR)->im_cpic.cpic_civr;
-	vec >>= 11;
-
-
-	if (cpm_vecs[vec].handler != 0)
-		(*cpm_vecs[vec].handler)(cpm_vecs[vec].dev_id);
-	else
-		((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec);
-
-	/* After servicing the interrupt, we have to remove the status
-	 * indicator.
-	 */
-	((immap_t *)IMAP_ADDR)->im_cpic.cpic_cisr |= (1 << vec);
-#endif
-
-}
-
-/* The CPM can generate the error interrupt when there is a race condition
- * between generating and masking interrupts.  All we have to do is ACK it
- * and return.  This is a no-op function so we don't need any special
- * tests in the interrupt handler.
- */
-static	void
-cpm_error_interrupt(void *dev)
-{
-}
-
-/* Install a CPM interrupt handler.
-*/
-void
-cpm_install_handler(int vec, void (*handler)(), void *dev_id)
-{
-
-	request_irq(vec, handler, 0, "timer", dev_id);
-
-/* 	if (cpm_vecs[vec].handler != 0) */
-/* 		printk(KERN_INFO "CPM interrupt %x replacing %x\n", */
-/* 			(uint)handler, (uint)cpm_vecs[vec].handler); */
-/* 	cpm_vecs[vec].handler = handler; */
-/* 	cpm_vecs[vec].dev_id = dev_id; */
-
-	/*              ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr |= (1 << vec); */
-/* 	pquicc->intr_cimr |= (1 << vec); */
-
-}
-
-/* Free a CPM interrupt handler.
-*/
-void
-cpm_free_handler(int vec)
-{
-	cpm_vecs[vec].handler = NULL;
-	cpm_vecs[vec].dev_id = NULL;
-	/* ((immap_t *)IMAP_ADDR)->im_cpic.cpic_cimr &= ~(1 << vec); */
-	pquicc->intr_cimr &= ~(1 << vec);
-}
-
-
-
-
-/* Allocate some memory from the dual ported ram.  We may want to
- * enforce alignment restrictions, but right now everyone is a good
- * citizen.
- */
-uint
-m360_cpm_dpalloc(uint size)
-{
-        uint    retloc;
-
-        if ((dp_alloc_base + size) >= dp_alloc_top)
-                return(CPM_DP_NOSPACE);
-
-        retloc = dp_alloc_base;
-        dp_alloc_base += size;
-
-        return(retloc);
-}
-
-
-#if 0 /* mleslie - for now these are simply kmalloc'd */
-/* We also own one page of host buffer space for the allocation of
- * UART "fifos" and the like.
- */
-uint
-m360_cpm_hostalloc(uint size)
-{
-	uint	retloc;
-
-	if ((host_buffer + size) >= host_end)
-		return(0);
-
-	retloc = host_buffer;
-	host_buffer += size;
-
-	return(retloc);
-}
-#endif
-
-
-/* Set a baud rate generator.  This needs lots of work.  There are
- * four BRGs, any of which can be wired to any channel.
- * The internal baud rate clock is the system clock divided by 16.
- * This assumes the baudrate is 16x oversampled by the uart.
- */
-/* #define BRG_INT_CLK	(((bd_t *)__res)->bi_intfreq * 1000000) */
-#define BRG_INT_CLK		system_clock
-#define BRG_UART_CLK	(BRG_INT_CLK/16)
-
-void
-m360_cpm_setbrg(uint brg, uint rate)
-{
-	volatile uint	*bp;
-
-	/* This is good enough to get SMCs running.....
-	 */
-	/* bp = (uint *)&cpmp->cp_brgc1; */
-	bp = (volatile uint *)(&pquicc->brgc[0].l);
-	bp += brg;
-	*bp = ((BRG_UART_CLK / rate - 1) << 1) | CPM_BRG_EN;
-}
-
-
-/*
- * Local variables:
- *  c-indent-level: 4
- *  c-basic-offset: 4
- *  tab-width: 4
- * End:
- */
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,186 +0,0 @@
-/*
- *  linux/arch/m68knommu/platform/68360/config.c
- *
- *  Copyright (c) 2000 Michael Leslie <mleslie@lineo.com>
- *  Copyright (C) 1993 Hamish Macdonald
- *  Copyright (C) 1999 D. Jeff Dionne <jeff@uclinux.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 <stdarg.h>
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <asm/setup.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/m68360.h>
-
-#ifdef CONFIG_UCQUICC
-#include <asm/bootstd.h>
-#endif
-
-extern void m360_cpm_reset(void);
-
-// Mask to select if the PLL prescaler is enabled.
-#define MCU_PREEN   ((unsigned short)(0x0001 << 13))
-
-#if defined(CONFIG_UCQUICC)
-#define OSCILLATOR  (unsigned long int)33000000
-#endif
-
-unsigned long int system_clock;
-
-extern QUICC *pquicc;
-
-/* TODO  DON"T Hard Code this */
-/* calculate properly using the right PLL and prescaller */
-// unsigned int system_clock = 33000000l;
-extern unsigned long int system_clock; //In kernel setup.c
-
-
-static irqreturn_t hw_tick(int irq, void *dummy)
-{
-  /* Reset Timer1 */
-  /* TSTAT &= 0; */
-
-  pquicc->timer_ter1 = 0x0002; /* clear timer event */
-
-  return arch_timer_interrupt(irq, dummy);
-}
-
-static struct irqaction m68360_timer_irq = {
-	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = hw_tick,
-};
-
-void hw_timer_init(void)
-{
-  unsigned char prescaler;
-  unsigned short tgcr_save;
-
-#if 0
-  /* Restart mode, Enable int, 32KHz, Enable timer */
-  TCTL = TCTL_OM | TCTL_IRQEN | TCTL_CLKSOURCE_32KHZ | TCTL_TEN;
-  /* Set prescaler (Divide 32KHz by 32)*/
-  TPRER = 31;
-  /* Set compare register  32Khz / 32 / 10 = 100 */
-  TCMP = 10;                                                              
-
-  request_irq(IRQ_MACHSPEC | 1, timer_routine, 0, "timer", NULL);
-#endif
-
-  /* General purpose quicc timers: MC68360UM p7-20 */
-
-  /* Set up timer 1 (in [1..4]) to do 100Hz */
-  tgcr_save = pquicc->timer_tgcr & 0xfff0;
-  pquicc->timer_tgcr  = tgcr_save; /* stop and reset timer 1 */
-  /* pquicc->timer_tgcr |= 0x4444; */ /* halt timers when FREEZE (ie bdm freeze) */
-
-  prescaler = 8;
-  pquicc->timer_tmr1 = 0x001a | /* or=1, frr=1, iclk=01b */
-                           (unsigned short)((prescaler - 1) << 8);
-    
-  pquicc->timer_tcn1 = 0x0000; /* initial count */
-  /* calculate interval for 100Hz based on the _system_clock: */
-  pquicc->timer_trr1 = (system_clock/ prescaler) / HZ; /* reference count */
-
-  pquicc->timer_ter1 = 0x0003; /* clear timer events */
-
-  /* enable timer 1 interrupt in CIMR */
-  setup_irq(CPMVEC_TIMER1, &m68360_timer_irq);
-
-  /* Start timer 1: */
-  tgcr_save = (pquicc->timer_tgcr & 0xfff0) | 0x0001;
-  pquicc->timer_tgcr  = tgcr_save;
-}
-
-void BSP_gettod (int *yearp, int *monp, int *dayp,
-		   int *hourp, int *minp, int *secp)
-{
-}
-
-int BSP_set_clock_mmss(unsigned long nowtime)
-{
-#if 0
-  short real_seconds = nowtime % 60, real_minutes = (nowtime / 60) % 60;
-
-  tod->second1 = real_seconds / 10;
-  tod->second2 = real_seconds % 10;
-  tod->minute1 = real_minutes / 10;
-  tod->minute2 = real_minutes % 10;
-#endif
-  return 0;
-}
-
-void BSP_reset (void)
-{
-  local_irq_disable();
-  asm volatile (
-    "moveal #_start, %a0;\n"
-    "moveb #0, 0xFFFFF300;\n"
-    "moveal 0(%a0), %sp;\n"
-    "moveal 4(%a0), %a0;\n"
-    "jmp (%a0);\n"
-    );
-}
-
-unsigned char *scc1_hwaddr;
-static int errno;
-
-#if defined (CONFIG_UCQUICC)
-_bsc0(char *, getserialnum)
-_bsc1(unsigned char *, gethwaddr, int, a)
-_bsc1(char *, getbenv, char *, a)
-#endif
-
-
-void config_BSP(char *command, int len)
-{
-  unsigned char *p;
-
-  m360_cpm_reset();
-
-  /* Calculate the real system clock value. */
-  {
-     unsigned int local_pllcr = (unsigned int)(pquicc->sim_pllcr);
-     if( local_pllcr & MCU_PREEN ) // If the prescaler is dividing by 128
-     {
-         int mf = (int)(pquicc->sim_pllcr & 0x0fff);
-         system_clock = (OSCILLATOR / 128) * (mf + 1);
-     }
-     else
-     {
-         int mf = (int)(pquicc->sim_pllcr & 0x0fff);
-         system_clock = (OSCILLATOR) * (mf + 1);
-     }
-  }
-
-  printk(KERN_INFO "\n68360 QUICC support (C) 2000 Lineo Inc.\n");
-
-#if defined(CONFIG_UCQUICC) && 0
-  printk(KERN_INFO "uCquicc serial string [%s]\n",getserialnum());
-  p = scc1_hwaddr = gethwaddr(0);
-  printk(KERN_INFO "uCquicc hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-         p[0], p[1], p[2], p[3], p[4], p[5]);
-
-  p = getbenv("APPEND");
-  if (p)
-    strcpy(p,command);
-  else
-    command[0] = 0;
-#else
-  scc1_hwaddr = "\00\01\02\03\04\05";
-#endif
- 
-  mach_gettod          = BSP_gettod;
-  mach_reset           = BSP_reset;
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/entry.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/entry.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/entry.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,184 +0,0 @@
-/*
- *  linux/arch/m68knommu/platform/68360/entry.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 2001 SED Systems, a Division of Calian Ltd.
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- * Linux/m68k support by Hamish Macdonald
- * M68360 Port by SED Systems, and Lineo.
- */
-
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/thread_info.h>
-#include <asm/unistd.h>
-#include <asm/errno.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/traps.h>
-#include <asm/asm-offsets.h>
-#include <asm/entry.h>
-
-.text
-
-.globl system_call
-.globl resume
-.globl ret_from_exception
-.globl ret_from_signal
-.globl sys_call_table
-.globl ret_from_interrupt
-.globl bad_interrupt
-.globl inthandler
-
-badsys:
-	movel	#-ENOSYS,%sp@(PT_OFF_D0)
-	jra	ret_from_exception
-
-do_trace:
-	movel	#-ENOSYS,%sp@(PT_OFF_D0) /* needed for strace*/
-	subql	#4,%sp
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace_enter
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	movel	%sp@(PT_OFF_ORIG_D0),%d1
-	movel	#-ENOSYS,%d0
-	cmpl	#NR_syscalls,%d1
-	jcc	1f
-	lsl	#2,%d1
-	lea	sys_call_table, %a0
-	jbsr	%a0@(%d1)
-
-1:	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
-	subql	#4,%sp			/* dummy return address */
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace_leave
-
-ret_from_signal:
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jra	ret_from_exception
-
-ENTRY(system_call)
-	SAVE_ALL
-
-	/* save top of frame*/
-	pea	%sp@
-	jbsr	set_esp0
-	addql	#4,%sp
-
-	movel	%sp@(PT_OFF_ORIG_D0),%d0
-
-	movel	%sp,%d1			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d1
-	movel	%d1,%a2
-	btst	#(TIF_SYSCALL_TRACE%8),%a2@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
-	jne	do_trace
-	cmpl	#NR_syscalls,%d0
-	jcc	badsys
-	lsl	#2,%d0
-	lea	sys_call_table,%a0
-	movel	%a0@(%d0), %a0
-	jbsr	%a0@
-	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value*/
-
-ret_from_exception:
-	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel*/
-	jeq	Luser_return		/* if so, skip resched, signals*/
-
-Lkernel_return:
-	RESTORE_ALL
-
-Luser_return:
-	/* only allow interrupts when we are really the last one on the*/
-	/* kernel stack, otherwise stack overflow can occur during*/
-	/* heavy interrupt load*/
-	andw	#ALLOWINT,%sr
-
-	movel	%sp,%d1			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d1
-	movel	%d1,%a2
-1:
-	move	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
-	jne	Lwork_to_do
-	RESTORE_ALL
-
-Lwork_to_do:
-	movel	%a2@(TI_FLAGS),%d1	/* thread_info->flags */
-	btst	#TIF_NEED_RESCHED,%d1
-	jne	reschedule
-
-Lsignal_return:
-	subql	#4,%sp			/* dummy return address*/
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	bsrw	do_signal
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jra	1b
-
-/*
- * This is the main interrupt handler, responsible for calling do_IRQ()
- */
-inthandler:
-	SAVE_ALL
-	movew	%sp@(PT_OFF_FORMATVEC), %d0
-	and.l	#0x3ff, %d0
-	lsr.l   #0x02,  %d0
-
-	movel	%sp,%sp@-
-	movel	%d0,%sp@- 		/*  put vector # on stack*/
-	jbsr	do_IRQ			/*  process the IRQ*/
-3:     	addql	#8,%sp			/*  pop parameters off stack*/
-	bra	ret_from_interrupt
-
-ret_from_interrupt:
-	jeq	1f
-2:
-	RESTORE_ALL
-1:
-	moveb	%sp@(PT_OFF_SR), %d0
-	and	#7, %d0
-	jhi	2b
-	/* check if we need to do software interrupts */
-
-	movel	irq_stat+CPUSTAT_SOFTIRQ_PENDING,%d0
-	jeq	ret_from_exception
-
-	pea	ret_from_exception
-	jra	do_softirq
-
-
-/*
- * Handler for uninitialized and spurious interrupts.
- */
-bad_interrupt:
-	addql	#1,num_spurious
-	rte
-
-/*
- * Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
- * registers until their contents are no longer needed.
- */
-ENTRY(resume)
-	movel	%a0,%d1				/* save prev thread in d1 */
-	movew	%sr,%a0@(TASK_THREAD+THREAD_SR)	/* save sr */
-	movel	%usp,%a2			/* save usp */
-	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
-
-	SAVE_SWITCH_STACK
-	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack */
-	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
-	RESTORE_SWITCH_STACK
-
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore user stack */
-	movel	%a0,%usp
-	movew	%a1@(TASK_THREAD+THREAD_SR),%sr	/* restore thread status reg */
-	rts
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/head-ram.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/head-ram.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/head-ram.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/head-ram.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,403 +0,0 @@
-/* arch/m68knommu/platform/68360/head-ram.S
- *
- * Startup code for Motorola 68360
- *
- * Copyright 2001 (C) SED Systems, a Division of Calian Ltd.
- * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
- * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
- *           uClinux Kernel
- * Copyright (C) Michael Leslie <mleslie@lineo.com>
- * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
- * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
- *
- */
-#define ASSEMBLY
-
-.global _stext
-.global _start
-
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-.global _quicc_base
-.global _periph_base
-
-#define	RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
-#define	ROMEND                      (CONFIG_ROMBASE + CONFIG_ROMSIZE)
-
-#define REGB                        0x1000
-#define PEPAR                       (_dprbase + REGB + 0x0016)
-#define GMR                         (_dprbase + REGB + 0x0040)
-#define OR0                         (_dprbase + REGB + 0x0054)
-#define BR0                         (_dprbase + REGB + 0x0050)
-#define OR1                         (_dprbase + REGB + 0x0064)
-#define BR1                         (_dprbase + REGB + 0x0060)
-#define OR4                         (_dprbase + REGB + 0x0094)
-#define BR4                         (_dprbase + REGB + 0x0090)
-#define OR6                         (_dprbase + REGB + 0x00b4)
-#define BR6                         (_dprbase + REGB + 0x00b0)
-#define OR7                         (_dprbase + REGB + 0x00c4)
-#define BR7                         (_dprbase + REGB + 0x00c0)
-
-#define MCR                         (_dprbase + REGB + 0x0000)
-#define AVR                         (_dprbase + REGB + 0x0008)
-
-#define SYPCR                       (_dprbase + REGB + 0x0022)
-
-#define PLLCR                       (_dprbase + REGB + 0x0010)
-#define CLKOCR                      (_dprbase + REGB + 0x000C)
-#define CDVCR                       (_dprbase + REGB + 0x0014)
-
-#define BKAR                        (_dprbase + REGB + 0x0030)
-#define BKCR                        (_dprbase + REGB + 0x0034)
-#define SWIV                        (_dprbase + REGB + 0x0023)
-#define PICR                        (_dprbase + REGB + 0x0026)
-#define PITR                        (_dprbase + REGB + 0x002A)
-
-/* Define for all memory configuration */
-#define MCU_SIM_GMR                 0x00000000
-#define SIM_OR_MASK                 0x0fffffff
-
-/* Defines for chip select zero - the flash */
-#define SIM_OR0_MASK                0x20000002
-#define SIM_BR0_MASK                0x00000001
-
-
-/* Defines for chip select one - the RAM */
-#define SIM_OR1_MASK                0x10000000
-#define SIM_BR1_MASK                0x00000001
-
-#define MCU_SIM_MBAR_ADRS           0x0003ff00
-#define MCU_SIM_MBAR_BA_MASK        0xfffff000
-#define MCU_SIM_MBAR_AS_MASK        0x00000001
-
-#define MCU_SIM_PEPAR               0x00B4
-    
-#define MCU_DISABLE_INTRPTS         0x2700
-#define MCU_SIM_AVR                 0x00
-    
-#define MCU_SIM_MCR                 0x00005cff
-
-#define MCU_SIM_CLKOCR              0x00
-#define MCU_SIM_PLLCR               0x8000
-#define MCU_SIM_CDVCR               0x0000
-
-#define MCU_SIM_SYPCR               0x0000
-#define MCU_SIM_SWIV                0x00
-#define MCU_SIM_PICR                0x0000
-#define MCU_SIM_PITR                0x0000
-
-
-#include <asm/m68360_regs.h>
-
-	
-/*
- * By the time this RAM specific code begins to execute, DPRAM
- * and DRAM should already be mapped and accessible.
- */
-
-	.text
-_start:
-_stext:
-	nop
-	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
-	/* We should not need to setup the boot stack the reset should do it. */
-	movea.l	#RAMEND, %sp			/*set up stack at the end of DRAM:*/
-
-set_mbar_register:
-	moveq.l	#0x07, %d1			/* Setup MBAR */
-	movec	%d1, %dfc
-
-	lea.l	MCU_SIM_MBAR_ADRS, %a0
-	move.l	#_dprbase, %d0
-	andi.l	#MCU_SIM_MBAR_BA_MASK, %d0
-	ori.l	#MCU_SIM_MBAR_AS_MASK, %d0
-	moves.l	%d0, %a0@
-
-	moveq.l	#0x05, %d1
-	movec.l	%d1, %dfc
-
-	/* Now we can begin to access registers in DPRAM */
-
-set_sim_mcr:
-	/* Set Module Configuration Register */
-	move.l	#MCU_SIM_MCR, MCR
-
-	/* to do:	Determine cause of reset */
-
-	/*
-	 *       configure system clock MC68360 p. 6-40
-	 *       (value +1)*osc/128 = system clock
-	 */
-set_sim_clock:
-	move.w	#MCU_SIM_PLLCR, PLLCR
-	move.b	#MCU_SIM_CLKOCR, CLKOCR
-	move.w	#MCU_SIM_CDVCR, CDVCR
-
-	/* Wait for the PLL to settle */
-	move.w	#16384, %d0
-pll_settle_wait:
-	subi.w	#1, %d0
-	bne	pll_settle_wait
-
-	/* Setup the system protection register, and watchdog timer register */
-	move.b	#MCU_SIM_SWIV, SWIV
-	move.w	#MCU_SIM_PICR, PICR
-	move.w	#MCU_SIM_PITR, PITR
-	move.w	#MCU_SIM_SYPCR, SYPCR
-
-	/* Clear DPRAM - system + parameter */
-	movea.l	#_dprbase, %a0
-	movea.l	#_dprbase+0x2000, %a1
-
-	/* Copy 0 to %a0 until %a0 == %a1 */
-clear_dpram:
-	movel	#0, %a0@+
-	cmpal	%a0, %a1
-	bhi	clear_dpram
-
-configure_memory_controller:    
-	/* Set up Global Memory Register (GMR) */
-	move.l	#MCU_SIM_GMR, %d0
-	move.l	%d0, GMR
-
-configure_chip_select_0:
-	move.l	#RAMEND, %d0
-	subi.l	#__ramstart, %d0
-	subq.l	#0x01, %d0
-	eori.l	#SIM_OR_MASK, %d0
-	ori.l	#SIM_OR0_MASK, %d0
-	move.l	%d0, OR0
-
-	move.l	#__ramstart, %d0
-	ori.l	#SIM_BR0_MASK, %d0
-	move.l	%d0, BR0
-
-configure_chip_select_1:
-	move.l	#ROMEND, %d0
-	subi.l	#__rom_start, %d0
-	subq.l	#0x01, %d0
-	eori.l	#SIM_OR_MASK, %d0
-	ori.l	#SIM_OR1_MASK, %d0
-	move.l	%d0, OR1
-
-	move.l	#__rom_start, %d0
-	ori.l	#SIM_BR1_MASK, %d0
-	move.l	%d0, BR1
-
-	move.w	#MCU_SIM_PEPAR, PEPAR 
-
-	/* point to vector table: */
-	move.l	#_romvec, %a0
-	move.l	#_ramvec, %a1
-copy_vectors:
-	move.l	%a0@, %d0
-	move.l	%d0, %a1@
-	move.l	%a0@, %a1@
-	addq.l	#0x04, %a0
-	addq.l	#0x04, %a1
-	cmp.l	#_start, %a0
-	blt	copy_vectors
-
-	move.l	#_ramvec, %a1
-	movec	%a1, %vbr
-
-
-	/* Copy data segment from ROM to RAM */
-	moveal	#_stext, %a0
-	moveal	#_sdata, %a1
-	moveal	#_edata, %a2
-
-	/* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
-	move.l	%a0@, %d0
-	addq.l	#0x04, %a0
-	move.l	%d0, %a1@
-	addq.l	#0x04, %a1
-	cmp.l	#_edata, %a1
-	blt     LD1
-
-	moveal	#_sbss, %a0
-	moveal	#_ebss, %a1
-
-	/* Copy 0 to %a0 until %a0 == %a1 */
-L1:
-	movel	#0, %a0@+
-	cmpal	%a0, %a1
-	bhi	L1
-
-load_quicc:
-	move.l	#_dprbase, _quicc_base
-
-store_ram_size:
-	/* Set ram size information */
-	move.l	#_sdata, _rambase
-	move.l	#_ebss, _ramstart
-	move.l	#RAMEND, %d0
-	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
-	move.l	%d0, _ramend			/* Different from RAMEND.*/
-
-	pea	0
-	pea	env
-	pea	%sp@(4)
-	pea	0
-
-	lea	init_thread_union, %a2
-	lea	0x2000(%a2), %sp
-
-lp:
-	jsr	start_kernel
-
-_exit:
-	jmp	_exit
-
-
-	.data
-	.align 4
-env:
-	.long	0
-_quicc_base:
-	.long	0
-_periph_base:
-	.long	0
-_ramvec:
-	.long   0
-_rambase:
-	.long   0
-_ramstart:
-	.long   0
-_ramend:
-	.long   0
-_dprbase:
-	.long	0xffffe000
-
-	.text
-
-    /*
-     * These are the exception vectors at boot up, they are copied into RAM
-     * and then overwritten as needed.
-     */
- 
-.section ".data..initvect","awx"
-    .long   RAMEND	/* Reset: Initial Stack Pointer                 - 0.  */
-    .long   _start      /* Reset: Initial Program Counter               - 1.  */
-    .long   buserr      /* Bus Error                                    - 2.  */
-    .long   trap        /* Address Error                                - 3.  */
-    .long   trap        /* Illegal Instruction                          - 4.  */
-    .long   trap        /* Divide by zero                               - 5.  */
-    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
-    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
-    .long   trap        /* Privilege Violation                          - 8.  */
-    .long   trap        /* Trace                                        - 9.  */
-    .long   trap        /* Line 1010 Emulator                           - 10. */
-    .long   trap        /* Line 1111 Emualtor                           - 11. */
-    .long   trap        /* Harware Breakpoint                           - 12. */
-    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
-    .long   trap        /* Format Error                                 - 14. */
-    .long   trap        /* Uninitialized Interrupt                      - 15. */
-    .long   trap        /* (Unassigned, Reserver)                       - 16. */
-    .long   trap        /* (Unassigned, Reserver)                       - 17. */
-    .long   trap        /* (Unassigned, Reserver)                       - 18. */
-    .long   trap        /* (Unassigned, Reserver)                       - 19. */
-    .long   trap        /* (Unassigned, Reserver)                       - 20. */
-    .long   trap        /* (Unassigned, Reserver)                       - 21. */
-    .long   trap        /* (Unassigned, Reserver)                       - 22. */
-    .long   trap        /* (Unassigned, Reserver)                       - 23. */
-    .long   trap        /* Spurious Interrupt                           - 24. */
-    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
-    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
-    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
-    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
-    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
-    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
-    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
-    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
-    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
-    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
-    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
-    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
-    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
-    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
-    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
-    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
-    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
-    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
-    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
-    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
-    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
-    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
-    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
-    .long   0           /* (Reserved for Coprocessor)                   - 48. */
-    .long   0           /* (Reserved for Coprocessor)                   - 49. */
-    .long   0           /* (Reserved for Coprocessor)                   - 50. */
-    .long   0           /* (Reserved for Coprocessor)                   - 51. */
-    .long   0           /* (Reserved for Coprocessor)                   - 52. */
-    .long   0           /* (Reserved for Coprocessor)                   - 53. */
-    .long   0           /* (Reserved for Coprocessor)                   - 54. */
-    .long   0           /* (Reserved for Coprocessor)                   - 55. */
-    .long   0           /* (Reserved for Coprocessor)                   - 56. */
-    .long   0           /* (Reserved for Coprocessor)                   - 57. */
-    .long   0           /* (Reserved for Coprocessor)                   - 58. */
-    .long   0           /* (Unassigned, Reserved)                       - 59. */
-    .long   0           /* (Unassigned, Reserved)                       - 60. */
-    .long   0           /* (Unassigned, Reserved)                       - 61. */
-    .long   0           /* (Unassigned, Reserved)                       - 62. */
-    .long   0           /* (Unassigned, Reserved)                       - 63. */
-    /*                  The assignment of these vectors to the CPM is         */
-    /*                  dependent on the configuration of the CPM vba         */
-    /*                          fields.                                       */
-    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
-    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
-    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
-    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
-    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
-    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
-    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
-    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
-    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
-    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
-    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
-    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
-    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
-    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
-    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
-    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
-    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
-    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
-    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
-    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
-    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
-    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
-    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
-    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
-    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
-    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
-    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
-    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
-    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
-    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
-    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
-    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
-    /*                  I don't think anything uses the vectors after here.   */
-    .long   0           /* (User-Defined Vectors 34)                    - 96. */
-    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
-    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
-.text
-ignore: rte
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/head-rom.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/head-rom.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/head-rom.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/head-rom.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,414 +0,0 @@
-/* arch/m68knommu/platform/68360/head-rom.S
- *
- * Startup code for Motorola 68360
- *
- * Copyright (C) SED Systems, a Division of Calian Ltd.
- * Based on: arch/m68knommu/platform/68328/pilot/crt0_rom.S
- * Based on: arch/m68knommu/platform/68360/uCquicc/crt0_rom.S, 2.0.38.1.pre7
- *           uClinux Kernel
- * Copyright (C) Michael Leslie <mleslie@lineo.com>
- * Based on: arch/m68knommu/platform/68EZ328/ucsimm/crt0_rom.S
- * Copyright (C) 1998  D. Jeff Dionne <jeff@uclinux.org>,
- *
- */
-
-.global _stext
-.global _sbss
-.global _start
-
-.global _rambase
-.global _ramvec
-.global _ramstart
-.global _ramend
-
-.global _quicc_base
-.global _periph_base
-
-#define	RAMEND                      (CONFIG_RAMBASE + CONFIG_RAMSIZE)
-
-#define REGB                        0x1000
-#define PEPAR                       (_dprbase + REGB + 0x0016)
-#define GMR                         (_dprbase + REGB + 0x0040)
-#define OR0                         (_dprbase + REGB + 0x0054)
-#define BR0                         (_dprbase + REGB + 0x0050)
-
-#define OR1                         (_dprbase + REGB + 0x0064)
-#define BR1                         (_dprbase + REGB + 0x0060)
-
-#define OR2                         (_dprbase + REGB + 0x0074)
-#define BR2                         (_dprbase + REGB + 0x0070)
-
-#define OR3                         (_dprbase + REGB + 0x0084)
-#define BR3                         (_dprbase + REGB + 0x0080)
-
-#define OR4                         (_dprbase + REGB + 0x0094)
-#define BR4                         (_dprbase + REGB + 0x0090)
-
-#define OR5                         (_dprbase + REGB + 0x00A4)
-#define BR5                         (_dprbase + REGB + 0x00A0)
-
-#define OR6                         (_dprbase + REGB + 0x00b4)
-#define BR6                         (_dprbase + REGB + 0x00b0)
-
-#define OR7                         (_dprbase + REGB + 0x00c4)
-#define BR7                         (_dprbase + REGB + 0x00c0)
-
-#define MCR                         (_dprbase + REGB + 0x0000)
-#define AVR                         (_dprbase + REGB + 0x0008)
-
-#define SYPCR                       (_dprbase + REGB + 0x0022)
-
-#define PLLCR                       (_dprbase + REGB + 0x0010)
-#define CLKOCR                      (_dprbase + REGB + 0x000C)
-#define CDVCR                       (_dprbase + REGB + 0x0014)
-
-#define BKAR                        (_dprbase + REGB + 0x0030)
-#define BKCR                        (_dprbase + REGB + 0x0034)
-#define SWIV                        (_dprbase + REGB + 0x0023)
-#define PICR                        (_dprbase + REGB + 0x0026)
-#define PITR                        (_dprbase + REGB + 0x002A)
-
-/* Define for all memory configuration */
-#define MCU_SIM_GMR                 0x00000000
-#define SIM_OR_MASK                 0x0fffffff
-
-/* Defines for chip select zero - the flash */
-#define SIM_OR0_MASK                0x20000000
-#define SIM_BR0_MASK                0x00000001
-
-/* Defines for chip select one - the RAM */
-#define SIM_OR1_MASK                0x10000000
-#define SIM_BR1_MASK                0x00000001
-
-#define MCU_SIM_MBAR_ADRS           0x0003ff00
-#define MCU_SIM_MBAR_BA_MASK        0xfffff000
-#define MCU_SIM_MBAR_AS_MASK        0x00000001
-
-#define MCU_SIM_PEPAR               0x00B4
-    
-#define MCU_DISABLE_INTRPTS         0x2700
-#define MCU_SIM_AVR                 0x00
-    
-#define MCU_SIM_MCR                 0x00005cff
-
-#define MCU_SIM_CLKOCR              0x00
-#define MCU_SIM_PLLCR               0x8000
-#define MCU_SIM_CDVCR               0x0000
-
-#define MCU_SIM_SYPCR               0x0000
-#define MCU_SIM_SWIV                0x00
-#define MCU_SIM_PICR                0x0000
-#define MCU_SIM_PITR                0x0000
-
-
-#include <asm/m68360_regs.h>
-
-	
-/*
- * By the time this RAM specific code begins to execute, DPRAM
- * and DRAM should already be mapped and accessible.
- */
-
-	.text
-_start:
-_stext:
-	nop
-	ori.w	#MCU_DISABLE_INTRPTS, %sr	/* disable interrupts: */
-	/* We should not need to setup the boot stack the reset should do it. */
-	movea.l	#RAMEND, %sp		/* set up stack at the end of DRAM:*/
-
-
-set_mbar_register:
-	moveq.l	#0x07, %d1			/* Setup MBAR */
-	movec	%d1, %dfc
-
-	lea.l	MCU_SIM_MBAR_ADRS, %a0
-	move.l	#_dprbase, %d0
-	andi.l	#MCU_SIM_MBAR_BA_MASK, %d0
-	ori.l	#MCU_SIM_MBAR_AS_MASK, %d0
-	moves.l	%d0, %a0@
-
-	moveq.l	#0x05, %d1
-	movec.l	%d1, %dfc
-
-	/* Now we can begin to access registers in DPRAM */
-
-set_sim_mcr:
-	/* Set Module Configuration Register */
-	move.l	#MCU_SIM_MCR, MCR
-
-	/* to do:	Determine cause of reset */
-
-	/*
-	 *	configure system clock MC68360 p. 6-40
-	 *	(value +1)*osc/128 = system clock
-	 *                    or
-	 *	(value + 1)*osc = system clock
-	 *	You do not need to divide the oscillator by 128 unless you want to.
-	 */
-set_sim_clock:
-	move.w	#MCU_SIM_PLLCR, PLLCR
-	move.b	#MCU_SIM_CLKOCR, CLKOCR
-	move.w	#MCU_SIM_CDVCR, CDVCR
-
-	/* Wait for the PLL to settle */
-	move.w	#16384, %d0
-pll_settle_wait:
-	subi.w	#1, %d0
-	bne	pll_settle_wait
-
-	/* Setup the system protection register, and watchdog timer register */
-	move.b	#MCU_SIM_SWIV, SWIV
-	move.w	#MCU_SIM_PICR, PICR
-	move.w	#MCU_SIM_PITR, PITR
-	move.w	#MCU_SIM_SYPCR, SYPCR
-
-	/* Clear DPRAM - system + parameter */
-	movea.l	#_dprbase, %a0
-	movea.l	#_dprbase+0x2000, %a1
-
-	/* Copy 0 to %a0 until %a0 == %a1 */
-clear_dpram:
-	movel	#0, %a0@+
-	cmpal	%a0, %a1
-	bhi	clear_dpram
-
-configure_memory_controller:    
-	/* Set up Global Memory Register (GMR) */
-	move.l	#MCU_SIM_GMR, %d0
-	move.l	%d0, GMR
-
-configure_chip_select_0:
-	move.l	#0x00400000, %d0
-	subq.l	#0x01, %d0
-	eori.l	#SIM_OR_MASK, %d0
-	ori.l	#SIM_OR0_MASK, %d0
-	move.l	%d0, OR0
-
-	move.l	#__rom_start, %d0
-	ori.l	#SIM_BR0_MASK, %d0
-	move.l	%d0, BR0
-
-	move.l	#0x0, BR1
-	move.l	#0x0, BR2
-	move.l	#0x0, BR3
-	move.l	#0x0, BR4
-	move.l	#0x0, BR5
-	move.l	#0x0, BR6
-	move.l	#0x0, BR7
-
-	move.w	#MCU_SIM_PEPAR, PEPAR 
-
-	/* point to vector table: */
-	move.l	#_romvec, %a0
-	move.l	#_ramvec, %a1
-copy_vectors:
-	move.l	%a0@, %d0
-	move.l	%d0, %a1@
-	move.l	%a0@, %a1@
-	addq.l	#0x04, %a0
-	addq.l	#0x04, %a1
-	cmp.l	#_start, %a0
-	blt	copy_vectors
-
-	move.l	#_ramvec, %a1
-	movec	%a1, %vbr
-
-
-	/* Copy data segment from ROM to RAM */
-	moveal	#_etext, %a0
-	moveal	#_sdata, %a1
-	moveal	#_edata, %a2
-
-	/* Copy %a0 to %a1 until %a1 == %a2 */
-LD1:
-	move.l	%a0@, %d0
-	addq.l	#0x04, %a0
-	move.l	%d0, %a1@
-	addq.l	#0x04, %a1
-	cmp.l	#_edata, %a1
-	blt	LD1
-
-	moveal	#_sbss, %a0
-	moveal	#_ebss, %a1
-
-	/* Copy 0 to %a0 until %a0 == %a1 */
-L1:
-	movel	#0, %a0@+
-	cmpal	%a0, %a1
-	bhi	L1
-
-load_quicc:
-	move.l	#_dprbase, _quicc_base
-
-store_ram_size:
-	/* Set ram size information */
-	move.l	#_sdata, _rambase
-	move.l	#_ebss, _ramstart
-	move.l	#RAMEND, %d0
-	sub.l	#0x1000, %d0			/* Reserve 4K for stack space.*/
-	move.l	%d0, _ramend			/* Different from RAMEND.*/
-
-	pea	0
-	pea	env
-	pea	%sp@(4)
-	pea	0
-
-	lea	init_thread_union, %a2
-	lea	0x2000(%a2), %sp
-
-lp:
-	jsr	start_kernel
-
-_exit:
-	jmp	_exit
-
-
-	.data
-	.align 4
-env:
-	.long	0
-_quicc_base:
-	.long	0
-_periph_base:
-	.long	0
-_ramvec:
-	.long   0
-_rambase:
-	.long   0
-_ramstart:
-	.long   0
-_ramend:
-	.long   0
-_dprbase:
-	.long	0xffffe000
-
-
-	.text
-
-    /*
-     * These are the exception vectors at boot up, they are copied into RAM
-     * and then overwritten as needed.
-     */
- 
-.section ".data..initvect","awx"
-    .long   RAMEND	/* Reset: Initial Stack Pointer                 - 0.  */
-    .long   _start      /* Reset: Initial Program Counter               - 1.  */
-    .long   buserr      /* Bus Error                                    - 2.  */
-    .long   trap        /* Address Error                                - 3.  */
-    .long   trap        /* Illegal Instruction                          - 4.  */
-    .long   trap        /* Divide by zero                               - 5.  */
-    .long   trap        /* CHK, CHK2 Instructions                       - 6.  */
-    .long   trap        /* TRAPcc, TRAPV Instructions                   - 7.  */
-    .long   trap        /* Privilege Violation                          - 8.  */
-    .long   trap        /* Trace                                        - 9.  */
-    .long   trap        /* Line 1010 Emulator                           - 10. */
-    .long   trap        /* Line 1111 Emualtor                           - 11. */
-    .long   trap        /* Harware Breakpoint                           - 12. */
-    .long   trap        /* (Reserved for Coprocessor Protocol Violation)- 13. */
-    .long   trap        /* Format Error                                 - 14. */
-    .long   trap        /* Uninitialized Interrupt                      - 15. */
-    .long   trap        /* (Unassigned, Reserver)                       - 16. */
-    .long   trap        /* (Unassigned, Reserver)                       - 17. */
-    .long   trap        /* (Unassigned, Reserver)                       - 18. */
-    .long   trap        /* (Unassigned, Reserver)                       - 19. */
-    .long   trap        /* (Unassigned, Reserver)                       - 20. */
-    .long   trap        /* (Unassigned, Reserver)                       - 21. */
-    .long   trap        /* (Unassigned, Reserver)                       - 22. */
-    .long   trap        /* (Unassigned, Reserver)                       - 23. */
-    .long   trap        /* Spurious Interrupt                           - 24. */
-    .long   trap        /* Level 1 Interrupt Autovector                 - 25. */
-    .long   trap        /* Level 2 Interrupt Autovector                 - 26. */
-    .long   trap        /* Level 3 Interrupt Autovector                 - 27. */
-    .long   trap        /* Level 4 Interrupt Autovector                 - 28. */
-    .long   trap        /* Level 5 Interrupt Autovector                 - 29. */
-    .long   trap        /* Level 6 Interrupt Autovector                 - 30. */
-    .long   trap        /* Level 7 Interrupt Autovector                 - 31. */
-    .long   system_call /* Trap Instruction Vectors 0                   - 32. */
-    .long   trap        /* Trap Instruction Vectors 1                   - 33. */
-    .long   trap        /* Trap Instruction Vectors 2                   - 34. */
-    .long   trap        /* Trap Instruction Vectors 3                   - 35. */
-    .long   trap        /* Trap Instruction Vectors 4                   - 36. */
-    .long   trap        /* Trap Instruction Vectors 5                   - 37. */
-    .long   trap        /* Trap Instruction Vectors 6                   - 38. */
-    .long   trap        /* Trap Instruction Vectors 7                   - 39. */
-    .long   trap        /* Trap Instruction Vectors 8                   - 40. */
-    .long   trap        /* Trap Instruction Vectors 9                   - 41. */
-    .long   trap        /* Trap Instruction Vectors 10                  - 42. */
-    .long   trap        /* Trap Instruction Vectors 11                  - 43. */
-    .long   trap        /* Trap Instruction Vectors 12                  - 44. */
-    .long   trap        /* Trap Instruction Vectors 13                  - 45. */
-    .long   trap        /* Trap Instruction Vectors 14                  - 46. */
-    .long   trap        /* Trap Instruction Vectors 15                  - 47. */
-    .long   0           /* (Reserved for Coprocessor)                   - 48. */
-    .long   0           /* (Reserved for Coprocessor)                   - 49. */
-    .long   0           /* (Reserved for Coprocessor)                   - 50. */
-    .long   0           /* (Reserved for Coprocessor)                   - 51. */
-    .long   0           /* (Reserved for Coprocessor)                   - 52. */
-    .long   0           /* (Reserved for Coprocessor)                   - 53. */
-    .long   0           /* (Reserved for Coprocessor)                   - 54. */
-    .long   0           /* (Reserved for Coprocessor)                   - 55. */
-    .long   0           /* (Reserved for Coprocessor)                   - 56. */
-    .long   0           /* (Reserved for Coprocessor)                   - 57. */
-    .long   0           /* (Reserved for Coprocessor)                   - 58. */
-    .long   0           /* (Unassigned, Reserved)                       - 59. */
-    .long   0           /* (Unassigned, Reserved)                       - 60. */
-    .long   0           /* (Unassigned, Reserved)                       - 61. */
-    .long   0           /* (Unassigned, Reserved)                       - 62. */
-    .long   0           /* (Unassigned, Reserved)                       - 63. */
-    /*                  The assignment of these vectors to the CPM is         */
-    /*                  dependent on the configuration of the CPM vba         */
-    /*                          fields.                                       */
-    .long   0           /* (User-Defined Vectors 1) CPM Error           - 64. */
-    .long   0           /* (User-Defined Vectors 2) CPM Parallel IO PC11- 65. */
-    .long   0           /* (User-Defined Vectors 3) CPM Parallel IO PC10- 66. */
-    .long   0           /* (User-Defined Vectors 4) CPM SMC2 / PIP      - 67. */
-    .long   0           /* (User-Defined Vectors 5) CPM SMC1            - 68. */
-    .long   0           /* (User-Defined Vectors 6) CPM SPI             - 69. */
-    .long   0           /* (User-Defined Vectors 7) CPM Parallel IO PC9 - 70. */
-    .long   0           /* (User-Defined Vectors 8) CPM Timer 4         - 71. */
-    .long   0           /* (User-Defined Vectors 9) CPM Reserved        - 72. */
-    .long   0           /* (User-Defined Vectors 10) CPM Parallel IO PC8- 73. */
-    .long   0           /* (User-Defined Vectors 11) CPM Parallel IO PC7- 74. */
-    .long   0           /* (User-Defined Vectors 12) CPM Parallel IO PC6- 75. */
-    .long   0           /* (User-Defined Vectors 13) CPM Timer 3        - 76. */
-    .long   0           /* (User-Defined Vectors 14) CPM Reserved       - 77. */
-    .long   0           /* (User-Defined Vectors 15) CPM Parallel IO PC5- 78. */
-    .long   0           /* (User-Defined Vectors 16) CPM Parallel IO PC4- 79. */
-    .long   0           /* (User-Defined Vectors 17) CPM Reserved       - 80. */
-    .long   0           /* (User-Defined Vectors 18) CPM RISC Timer Tbl - 81. */
-    .long   0           /* (User-Defined Vectors 19) CPM Timer 2        - 82. */
-    .long   0           /* (User-Defined Vectors 21) CPM Reserved       - 83. */
-    .long   0           /* (User-Defined Vectors 22) CPM IDMA2          - 84. */
-    .long   0           /* (User-Defined Vectors 23) CPM IDMA1          - 85. */
-    .long   0           /* (User-Defined Vectors 24) CPM SDMA Bus Err   - 86. */
-    .long   0           /* (User-Defined Vectors 25) CPM Parallel IO PC3- 87. */
-    .long   0           /* (User-Defined Vectors 26) CPM Parallel IO PC2- 88. */
-    .long   0           /* (User-Defined Vectors 27) CPM Timer 1        - 89. */
-    .long   0           /* (User-Defined Vectors 28) CPM Parallel IO PC1- 90. */
-    .long   0           /* (User-Defined Vectors 29) CPM SCC 4          - 91. */
-    .long   0           /* (User-Defined Vectors 30) CPM SCC 3          - 92. */
-    .long   0           /* (User-Defined Vectors 31) CPM SCC 2          - 93. */
-    .long   0           /* (User-Defined Vectors 32) CPM SCC 1          - 94. */
-    .long   0           /* (User-Defined Vectors 33) CPM Parallel IO PC0- 95. */
-    /*                  I don't think anything uses the vectors after here.   */
-    .long   0           /* (User-Defined Vectors 34)                    - 96. */
-    .long   0,0,0,0,0               /* (User-Defined Vectors 35  -  39). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 40  -  49). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 50  -  59). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 60  -  69). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 70  -  79). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 80  -  89). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 90  -  99). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 100 - 109). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 110 - 119). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 120 - 129). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 130 - 139). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 140 - 149). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 150 - 159). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 160 - 169). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 170 - 179). */
-    .long   0,0,0,0,0,0,0,0,0,0     /* (User-Defined Vectors 180 - 189). */
-    .long   0,0,0                   /* (User-Defined Vectors 190 - 192). */
-.text
-ignore: rte
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/ints.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/ints.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/ints.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/ints.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,139 +0,0 @@
-/*
- * linux/arch/$(ARCH)/platform/$(PLATFORM)/ints.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) 2000  Michael Leslie <mleslie@lineo.com>
- * Copyright (c) 1996 Roman Zippel
- * Copyright (c) 1999 D. Jeff Dionne <jeff@uclinux.org>
- */
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/m68360.h>
-
-/* from quicc/commproc.c: */
-extern QUICC *pquicc;
-extern void cpm_interrupt_init(void);
-
-#define INTERNAL_IRQS (96)
-
-/* assembler routines */
-asmlinkage void system_call(void);
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void bad_interrupt(void);
-asmlinkage void inthandler(void);
-
-extern void *_ramvec[];
-
-/* The number of spurious interrupts */
-volatile unsigned int num_spurious;
-
-static void intc_irq_unmask(unsigned int irq)
-{
-	pquicc->intr_cimr |= (1 << irq);
-}
-
-static void intc_irq_mask(unsigned int irq)
-{
-	pquicc->intr_cimr &= ~(1 << irq);
-}
-
-static void intc_irq_ack(unsigned int irq)
-{
-	pquicc->intr_cisr = (1 << irq);
-}
-
-static struct irq_chip intc_irq_chip = {
-	.name		= "M68K-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.ack		= intc_irq_ack,
-};
-
-/*
- * This function should be called during kernel startup to initialize
- * the vector table.
- */
-void init_IRQ(void)
-{
-	int i;
-	int vba = (CPM_VECTOR_BASE<<4);
-
-	/* set up the vectors */
-	_ramvec[2] = buserr;
-	_ramvec[3] = trap;
-	_ramvec[4] = trap;
-	_ramvec[5] = trap;
-	_ramvec[6] = trap;
-	_ramvec[7] = trap;
-	_ramvec[8] = trap;
-	_ramvec[9] = trap;
-	_ramvec[10] = trap;
-	_ramvec[11] = trap;
-	_ramvec[12] = trap;
-	_ramvec[13] = trap;
-	_ramvec[14] = trap;
-	_ramvec[15] = trap;
-
-	_ramvec[32] = system_call;
-	_ramvec[33] = trap;
-
-	cpm_interrupt_init();
-
-	/* set up CICR for vector base address and irq level */
-	/* irl = 4, hp = 1f - see MC68360UM p 7-377 */
-	pquicc->intr_cicr = 0x00e49f00 | vba;
-
-	/* CPM interrupt vectors: (p 7-376) */
-	_ramvec[vba+CPMVEC_ERROR]       = bad_interrupt; /* Error */
-	_ramvec[vba+CPMVEC_PIO_PC11]    = inthandler;   /* pio - pc11 */
-	_ramvec[vba+CPMVEC_PIO_PC10]    = inthandler;   /* pio - pc10 */
-	_ramvec[vba+CPMVEC_SMC2]        = inthandler;   /* smc2/pip */
-	_ramvec[vba+CPMVEC_SMC1]        = inthandler;   /* smc1 */
-	_ramvec[vba+CPMVEC_SPI]         = inthandler;   /* spi */
-	_ramvec[vba+CPMVEC_PIO_PC9]     = inthandler;   /* pio - pc9 */
-	_ramvec[vba+CPMVEC_TIMER4]      = inthandler;   /* timer 4 */
-	_ramvec[vba+CPMVEC_RESERVED1]   = inthandler;   /* reserved */
-	_ramvec[vba+CPMVEC_PIO_PC8]     = inthandler;   /* pio - pc8 */
-	_ramvec[vba+CPMVEC_PIO_PC7]     = inthandler;  /* pio - pc7 */
-	_ramvec[vba+CPMVEC_PIO_PC6]     = inthandler;  /* pio - pc6 */
-	_ramvec[vba+CPMVEC_TIMER3]      = inthandler;  /* timer 3 */
-	_ramvec[vba+CPMVEC_PIO_PC5]     = inthandler;  /* pio - pc5 */
-	_ramvec[vba+CPMVEC_PIO_PC4]     = inthandler;  /* pio - pc4 */
-	_ramvec[vba+CPMVEC_RESERVED2]   = inthandler;  /* reserved */
-	_ramvec[vba+CPMVEC_RISCTIMER]   = inthandler;  /* timer table */
-	_ramvec[vba+CPMVEC_TIMER2]      = inthandler;  /* timer 2 */
-	_ramvec[vba+CPMVEC_RESERVED3]   = inthandler;  /* reserved */
-	_ramvec[vba+CPMVEC_IDMA2]       = inthandler;  /* idma 2 */
-	_ramvec[vba+CPMVEC_IDMA1]       = inthandler;  /* idma 1 */
-	_ramvec[vba+CPMVEC_SDMA_CB_ERR] = inthandler;  /* sdma channel bus error */
-	_ramvec[vba+CPMVEC_PIO_PC3]     = inthandler;  /* pio - pc3 */
-	_ramvec[vba+CPMVEC_PIO_PC2]     = inthandler;  /* pio - pc2 */
-	/* _ramvec[vba+CPMVEC_TIMER1]      = cpm_isr_timer1; */  /* timer 1 */
-	_ramvec[vba+CPMVEC_TIMER1]      = inthandler;  /* timer 1 */
-	_ramvec[vba+CPMVEC_PIO_PC1]     = inthandler;  /* pio - pc1 */
-	_ramvec[vba+CPMVEC_SCC4]        = inthandler;  /* scc 4 */
-	_ramvec[vba+CPMVEC_SCC3]        = inthandler;  /* scc 3 */
-	_ramvec[vba+CPMVEC_SCC2]        = inthandler;  /* scc 2 */
-	_ramvec[vba+CPMVEC_SCC1]        = inthandler;  /* scc 1 */
-	_ramvec[vba+CPMVEC_PIO_PC0]     = inthandler;  /* pio - pc0 */
-
-
-	/* turn off all CPM interrupts */
-	pquicc->intr_cimr = 0x00000000;
-
-	for (i = 0; (i < NR_IRQS); i++) {
-		set_irq_chip(i, &intc_irq_chip);
-		set_irq_handler(i, handle_level_irq);
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68360/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68360/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68360.
-#
-
-obj-y := config.o commproc.o entry.o ints.o
-
-extra-y := head.o
-
-$(obj)/head.o: $(obj)/head-$(MODEL).o
-	ln -sf head-$(MODEL).o $(obj)/head.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68EZ328/bootlogo.h linux-libre-2.6.39-gnu/arch/m68knommu/platform/68EZ328/bootlogo.h
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68EZ328/bootlogo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68EZ328/bootlogo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,3204 +0,0 @@
-#define splash_width 640
-#define splash_height 480
-static unsigned char splash_bits[] = {
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x03, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0xfe, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x7c, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0xe0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3e, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e,
-  0x00, 0xfe, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0xfe, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xe0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0xe0, 0xff, 0x07, 0xfe, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff,
-  0x00, 0xf0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0xe0, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03,
-  0x3f, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x0f, 0xfc, 0x00, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
-  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xff, 0xff, 0x3f, 0xf0, 0x01, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0xc0, 0xff,
-  0xc1, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0xfc, 0x07, 0x07, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
-  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0x00, 0xe0, 0x07, 0x0e, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
-  0x3f, 0x1c, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x38, 0x00, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f,
-  0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e,
-  0x00, 0x00, 0x00, 0x00, 0x78, 0x70, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xe0, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc3, 0x01, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f,
-  0x00, 0x80, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0xc7, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x1f, 0x00, 0x80, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x87, 0x03, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x3f, 0x00, 0xc0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x07, 0x00,
-  0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f,
-  0x00, 0xe0, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0e, 0x00, 0xf0, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x00, 0xf0, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0x0c, 0x00, 0xf0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0x01, 0xf8, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x1c, 0x00,
-  0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x07, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0x38, 0x00, 0xf0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x71, 0x00,
-  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x72, 0x00, 0xe0, 0xff, 0x7f, 0xe0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe2, 0x00, 0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
-  0xe0, 0xff, 0x7f, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x01, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01,
-  0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x03,
-  0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xfe, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0xf0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x10, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x9f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
-  0xf8, 0xff, 0x1f, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x80, 0xff, 0xff, 0x00,
-  0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x0f, 0x20, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0xf8, 0xff, 0xff, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x03, 0x00, 0xe0, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x3f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xfc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
-  0xfe, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf0, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0xf8, 0xff, 0x01, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00, 0xc0, 0xff, 0x01,
-  0xfe, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xfc, 0x01, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0xe0, 0x03, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x41, 0x08, 0x04, 0xb3, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0x00, 0x18, 0x8e, 0x31, 0x7b, 0x30, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0xf8,
-  0x41, 0xc6, 0x84, 0x0c, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0xf8, 0x41, 0xc6, 0x84, 0x0c,
-  0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x0f, 0x00, 0x00, 0x18, 0x0c, 0x08, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0xe4,
-  0xb1, 0xc1, 0x98, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0xe4, 0xb1, 0xc1, 0x98, 0x00,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0x08, 0x00, 0x00, 0x1c, 0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0x01, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x1c,
-  0x02, 0x08, 0x04, 0x4c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x1f, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x10, 0x80,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00,
-  0x36, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x09, 0x00, 0x00, 0x64, 0x4c, 0x00, 0x00, 0x00, 0x36, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x9c,
-  0x01, 0x08, 0x83, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40,
-  0x30, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x0f, 0x00, 0x00, 0x64, 0x8c, 0x01, 0x18, 0x40, 0x30, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x03, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x9b,
-  0x01, 0xc0, 0x00, 0x00, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x40,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x09, 0x00, 0x00, 0x9b, 0x01, 0xc0, 0x00, 0x00,
-  0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0x00, 0x00, 0x00, 0x07, 0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xc1, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x02, 0x02, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x07,
-  0x32, 0x06, 0x18, 0x43, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x02, 0x10, 0xe0,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, 0x7b, 0x00, 0x30, 0x03, 0x0c,
-  0x08, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x07, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x09, 0x00, 0xc0, 0x84, 0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xfd, 0x03, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xc0, 0x84,
-  0x8d, 0x01, 0x80, 0x00, 0xc0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xfd, 0x03, 0xf0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40,
-  0x08, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xfc, 0x01, 0xf0, 0x3f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0xc0, 0x1b, 0x00, 0x30, 0x00, 0x40, 0x08, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x07, 0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f,
-  0xf8, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0x64,
-  0x42, 0x06, 0x1b, 0x03, 0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x7f, 0x00, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0xf0, 0x00, 0x10, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x64, 0x42, 0x06, 0x1b, 0x03,
-  0x00, 0x61, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x0f, 0x00, 0x00, 0x1b, 0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x3f, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0x1b,
-  0x00, 0x00, 0x80, 0x30, 0x08, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xc3, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xe0, 0x84, 0x31, 0x30, 0x04, 0x80,
-  0xc1, 0x18, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x09, 0x00, 0xc0, 0x63, 0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0xe0, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x08, 0x00, 0xc0, 0x63,
-  0x02, 0x06, 0x00, 0x00, 0x00, 0x60, 0x6c, 0xfc, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c,
-  0x06, 0x81, 0x80, 0xfd, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0xe0, 0x1c, 0x40, 0x00, 0x1b, 0x4c, 0x06, 0x81, 0x80, 0xfd,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x00, 0x80, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x20, 0x63,
-  0x0c, 0x08, 0x80, 0x00, 0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x30, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x20, 0x63, 0x0c, 0x08, 0x80, 0x00,
-  0x30, 0x06, 0x0c, 0xfc, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x0f, 0x00, 0xd8, 0x84, 0x01, 0xc0, 0x00, 0x00, 0x06, 0x00, 0x80, 0xf1,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x0f, 0x00, 0xf8, 0x1b,
-  0x40, 0x08, 0x84, 0x0c, 0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xe0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xf8, 0x1b, 0x40, 0x08, 0x84, 0x0c,
-  0xc0, 0x18, 0x13, 0xcc, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xf0, 0xe4, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x09, 0x00, 0x38, 0x80, 0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-  0x00, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0x30, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x38, 0x80,
-  0x01, 0x00, 0x18, 0x30, 0x06, 0x01, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x10, 0x84,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00,
-  0x00, 0x00, 0x03, 0xf2, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x10, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x4f, 0x0e, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x08, 0x00, 0xd8, 0x1f, 0x30, 0x36, 0x80, 0x00, 0x00, 0x00, 0x03, 0xf2,
-  0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0x03, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x43,
-  0x08, 0x00, 0x10, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0x3e, 0x00,
-  0x82, 0x01, 0x03, 0x40, 0x30, 0x98, 0x10, 0xf0, 0xe7, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x1f, 0xc0, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x10, 0xe4,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c,
-  0x00, 0x00, 0x00, 0xfc, 0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xc1, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x41, 0x08, 0x00, 0x30, 0x7c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0xe6, 0x1b, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0xfc,
-  0xff, 0xfb, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9e,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
-  0x08, 0x00, 0x20, 0x7c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64,
-  0x30, 0xc6, 0x80, 0x80, 0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x30, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0xf8, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0e, 0x00, 0xc0, 0x3c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x1e, 0x64, 0x30, 0xc6, 0x80, 0x80,
-  0x09, 0x06, 0x63, 0xfe, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x20, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc3, 0x07, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0e, 0x00, 0x39, 0x03, 0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0xfc, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc2,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x39, 0x03,
-  0x00, 0x00, 0x04, 0x0c, 0xc0, 0x60, 0x80, 0x3f, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3e, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x80, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xcc, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0xe7, 0x04, 0x42, 0xc6, 0x00, 0x00,
-  0x00, 0x00, 0xec, 0xcf, 0xff, 0xff, 0xff, 0x3f, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0xfc, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x0f, 0xc0, 0x1f, 0x80, 0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01,
-  0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x01, 0x00, 0xc0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x1f, 0x80,
-  0x01, 0x00, 0x98, 0x4c, 0x06, 0x06, 0xf0, 0x01, 0x00, 0xe0, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x20, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x08, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00,
-  0xc0, 0x60, 0x7c, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x1f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
-  0x00, 0xc0, 0xe6, 0x04, 0x0c, 0x08, 0x00, 0x00, 0xc0, 0x60, 0x7c, 0x00,
-  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0xc0, 0x19, 0x60,
-  0x40, 0x00, 0x63, 0x30, 0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xf3, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x09, 0xc0, 0x19, 0x60, 0x40, 0x00, 0x63, 0x30,
-  0x08, 0x00, 0x7f, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xf3, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0xc0, 0x27, 0x03, 0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0xe0, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0xcf, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x0f, 0xc0, 0x27, 0x03,
-  0x00, 0x30, 0x00, 0x03, 0x00, 0xe6, 0x1f, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x0f, 0xc0, 0xde, 0x04, 0x0c, 0x06, 0x03, 0x80,
-  0xc1, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x03, 0x00, 0xf8, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x0f, 0xc0, 0x19, 0x00, 0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f,
-  0x07, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x09, 0xc0, 0x19, 0x00,
-  0x32, 0x00, 0x60, 0x30, 0x08, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x9f, 0x07, 0x00, 0x18, 0x40,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3f, 0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03,
-  0xf0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1c, 0xfe, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x1f, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c,
-  0x00, 0xc0, 0x27, 0x63, 0x80, 0x31, 0x04, 0x03, 0xf0, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x7f, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c,
-  0xe0, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x31,
-  0x04, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x08, 0x00, 0xd9, 0x04,
-  0x00, 0x08, 0x00, 0x80, 0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0xfe, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x60, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x09, 0x00, 0xd9, 0x04, 0x00, 0x08, 0x00, 0x80,
-  0xf9, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x78, 0x00, 0xf0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x20, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0xc0, 0x27, 0x00, 0x30, 0xc0, 0x60, 0xb0, 0xff, 0x7f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x60, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x00, 0x00, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b,
-  0x8d, 0x01, 0x04, 0xc3, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0xf1, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbc, 0x03, 0x00, 0xf0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xde, 0x9b, 0x8d, 0x01, 0x04, 0xc3,
-  0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xf1, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3e, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0x39, 0x04, 0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0x39, 0x04,
-  0x00, 0xc8, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc6, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0xc0, 0xc7, 0x60, 0x42, 0x00, 0x60, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0xc0, 0xff, 0x07,
-  0xb0, 0x09, 0xe4, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x30, 0x00, 0xfc, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff,
-  0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0xff, 0x1f, 0xf8, 0xff, 0xff, 0x1f, 0xf0, 0xff, 0xff, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0xde, 0x78, 0x02, 0x00, 0xfb, 0xff, 0xff, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0x1f, 0xf8,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x08,
-  0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07,
-  0xb0, 0xc9, 0xf8, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0x3f, 0x07, 0xb0, 0xc9, 0xf8, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x03, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x0f, 0x00, 0xe7, 0xfb, 0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0xe7, 0xfb,
-  0x43, 0x30, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x08, 0x70, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0xe0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xfe, 0x1c, 0xb2, 0x0f, 0xe0, 0xff,
-  0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0xff, 0xff, 0xcf, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x00, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0xfc, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0xf8, 0xe7, 0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0,
-  0xb1, 0x3f, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0xf8,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xc0, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0xf8, 0xe7,
-  0xfd, 0x01, 0xe0, 0xff, 0x07, 0x00, 0xe0, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc1, 0xe0, 0xb1, 0x3f, 0x00, 0x00,
-  0xf8, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff,
-  0x01, 0x00, 0xe0, 0x03, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x98, 0x4f, 0x0e, 0x18, 0x00, 0xf8, 0xff, 0xff, 0xff,
-  0x07, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x80, 0xff, 0x01, 0x00, 0xe0, 0x03,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-  0x4f, 0x0e, 0xf8, 0x1f, 0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0xf8, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x1f,
-  0xf6, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x03, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x04, 0x08, 0x00, 0xf8, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xb1, 0x01, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0xe0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f,
-  0x00, 0xce, 0xff, 0x7f, 0xc0, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0xe3, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xe0, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0xce, 0xff, 0x7f,
-  0x00, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x20, 0x1b, 0xb2, 0x31, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0xe0, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x03, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x01, 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0xc0, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c,
-  0x00, 0xc0, 0xff, 0x73, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf0,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3e,
-  0x00, 0x00, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc0, 0x1c, 0x00, 0xc0, 0x7f, 0x1c,
-  0x30, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x78, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x38, 0x87, 0x31, 0x06, 0x7c, 0x1c, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0x00, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x87,
-  0x31, 0x06, 0xfc, 0x0f, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x38,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0xe3, 0x0f,
-  0xc8, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60, 0x00, 0x00, 0xe0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0xe6, 0x04, 0x00, 0x30, 0x03, 0x00, 0xf0, 0xff, 0xff, 0xff,
-  0xff, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x1b,
-  0x4c, 0x00, 0x04, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x10,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x01, 0x00, 0xf0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0xc0, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x18, 0x80,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x0e, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x02, 0x07, 0x04, 0x00, 0x06, 0x78, 0xf3, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0xf8, 0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x08, 0x00, 0xc0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04,
-  0x02, 0x30, 0x60, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0xc0, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x04, 0x02, 0x30, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc6, 0x04, 0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0xf8, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x04,
-  0x40, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x39, 0x67, 0x00, 0x06, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x06, 0x04, 0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x18, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0x0f, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04,
-  0x30, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08,
-  0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x06, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x08, 0x60, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x30, 0x3e, 0x9b, 0x01, 0x30, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x18, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x1c, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x02, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c,
-  0x0c, 0x06, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
-  0x78, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0xe0,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc6, 0x1c, 0x0c, 0x06, 0xfb, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x68, 0x7c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0xf8, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x38, 0x18, 0x00, 0x00, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0xc0, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x18, 0xfe, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b,
-  0x81, 0x01, 0x60, 0x00, 0xfe, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x80,
-  0x5f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xc6, 0x9b, 0x81, 0x01, 0x00, 0x00,
-  0xf6, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xc0, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0x03, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x38, 0x78, 0x0c, 0x30, 0x04, 0x00, 0xf6, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0xe8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x78,
-  0x0c, 0x30, 0x04, 0x00, 0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8,
-  0x0d, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0x1c, 0x00,
-  0xc8, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0xf8, 0x58, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0x64, 0x40, 0x00, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c,
-  0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0,
-  0x01, 0x36, 0xfc, 0x03, 0xc0, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x38,
-  0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
-  0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0x36, 0xfc, 0x1f,
-  0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x18, 0x40, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x3f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x80, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc6, 0x87, 0x0f, 0x00, 0xff, 0x1f, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xcf, 0x03, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0x40, 0xc0, 0xff, 0x7f, 0xc0, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x08,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xcf, 0x03, 0x00, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0xc0, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40, 0xc0, 0xff, 0x7f,
-  0x00, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x8f, 0x01, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x0e, 0xc6, 0xff, 0x7f, 0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x0c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xff,
-  0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x7f,
-  0x00, 0xfe, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x01, 0x00, 0xf0, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x20, 0x9c, 0x01, 0x30, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0x07, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-  0x4c, 0x00, 0xff, 0x63, 0x30, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x1f,
-  0x00, 0xff, 0xff, 0xfd, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xb2, 0x31, 0xfc, 0x0f, 0x00, 0xff, 0xff, 0x03,
-  0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98,
-  0x41, 0x00, 0xe0, 0x0f, 0x00, 0xff, 0xff, 0x03, 0xff, 0x03, 0x00, 0x38,
-  0x80, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0x41, 0x00, 0x00, 0x80,
-  0xc9, 0xf9, 0xff, 0x3d, 0xff, 0x03, 0x00, 0x78, 0xc0, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x60, 0x32, 0x08, 0x00, 0x80, 0xc9, 0xf9, 0xff, 0x3d,
-  0xff, 0x03, 0x00, 0xf8, 0xc0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x02, 0x00, 0x00, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-  0x32, 0x08, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0xf8,
-  0x81, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0xff,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x01, 0xf8, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0xcf, 0xff, 0x00, 0x00, 0x38, 0x03, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x60, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0x80, 0xff, 0xff, 0xff, 0xff,
-  0x3f, 0x00, 0x00, 0x38, 0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0c, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0xff, 0xff, 0x03, 0xfc, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38,
-  0x1e, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0e, 0x00, 0x00, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0x03, 0xfc,
-  0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x38, 0xfc, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0xff, 0xff, 0x3f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x1f, 0x00, 0x00, 0x38, 0xf8, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30,
-  0x80, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x78,
-  0xf0, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xe0, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, 0xff,
-  0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0xf8, 0xc1, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x60, 0xf8, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x03, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0xc0, 0xff,
-  0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x01, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x08, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x67,
-  0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x13, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0xc0, 0xff,
-  0xff, 0xff, 0x1f, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0x67, 0xfe, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf0, 0xff, 0xff, 0x98, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f,
-  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x0f, 0x00, 0xf8, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0xff, 0x98,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xf8, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0xff, 0xfc, 0xff, 0xff, 0xff, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0xff, 0xff, 0x3f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x00, 0xc0, 0xff, 0x67, 0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0xff, 0xf8,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x80,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0xff, 0x67,
-  0x8c, 0xf9, 0xfb, 0x73, 0x00, 0x67, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xc0, 0xff, 0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c,
-  0x37, 0x80, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff,
-  0xff, 0xff, 0x1f, 0xe7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,
-  0x00, 0xc0, 0x27, 0xfc, 0x73, 0xc6, 0x1c, 0x8c, 0x37, 0x80, 0x0c, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xfc,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x08, 0xc0, 0xfe, 0x03,
-  0x8c, 0x09, 0xe3, 0x73, 0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x80, 0xff, 0xff, 0xff, 0xff, 0xff, 0xfc, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xfe, 0x03, 0x8c, 0x09, 0xe3, 0x73,
-  0xc8, 0x06, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x08, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0xc0, 0x27, 0xe7, 0x31, 0x36, 0x04, 0x8c, 0x01, 0x60, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18,
-  0x42, 0xc0, 0x98, 0x30, 0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0xc0, 0xde, 0x18, 0x42, 0xc0, 0x98, 0x30,
-  0x08, 0x01, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0xc0, 0x27, 0x63, 0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0xc0, 0x27, 0x63,
-  0x00, 0x08, 0x63, 0x03, 0x06, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0xff, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0,
-  0x31, 0x19, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff,
-  0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x80, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0xc0, 0xd9, 0x04, 0xb2, 0x01, 0x00, 0xb0, 0x31, 0x19, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xf9, 0xff, 0xff, 0xff, 0xff, 0x07,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0c, 0xc0, 0x1e, 0x63,
-  0x00, 0x30, 0x04, 0x03, 0xc8, 0x60, 0x00, 0x0e, 0x00, 0x00, 0xfc, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x0e, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0,
-  0x01, 0xe7, 0xf3, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x04, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x0f, 0xc0, 0xe1, 0x18, 0x80, 0x01, 0x60, 0xb0, 0x01, 0xe7, 0xf3, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8d, 0x0f, 0xc0, 0x1e, 0x03,
-  0x02, 0x08, 0x04, 0x00, 0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xd8, 0x0f, 0xc0, 0x1e, 0x03, 0x02, 0x08, 0x04, 0x00,
-  0xc8, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xc0, 0x0f, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x0b, 0x00, 0x21, 0x64, 0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xfb, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xfb, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0x00, 0x21, 0x64,
-  0x40, 0xc0, 0x00, 0xb3, 0xf1, 0xfe, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xfb, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0xfb, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfd, 0x00, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00,
-  0x0e, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xf9, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xbf,
-  0x01, 0xc0, 0xdf, 0x00, 0x00, 0x06, 0x60, 0x00, 0x0e, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0,
-  0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0xf0, 0x03, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x0b, 0xc0, 0xc0, 0x84,
-  0x31, 0xc0, 0x00, 0x4c, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x83, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x1e, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0f, 0x0e, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80,
-  0x09, 0xff, 0xff, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0xc3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x0c, 0xc0, 0x3f, 0x18, 0x00, 0x06, 0x84, 0x80, 0x09, 0xff, 0xff, 0x3f,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc8,
-  0xc1, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x08, 0xc0, 0xc1, 0x03,
-  0x4c, 0x00, 0x00, 0x30, 0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x90, 0x13, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0xc0, 0xc1, 0x03, 0x4c, 0x00, 0x00, 0x30,
-  0xf6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x08, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x00, 0xc0, 0x3f, 0x98, 0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08,
-  0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x3f, 0x98,
-  0x01, 0x08, 0x1b, 0x43, 0xc8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x38, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x0e, 0x00, 0xc0, 0xc6, 0x03, 0x40, 0x00, 0x00, 0x80,
-  0x31, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xf7, 0xff, 0xff, 0xff, 0xff,
-  0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xef, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f,
-  0x00, 0x00, 0x3f, 0x18, 0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xef, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x3f, 0x18,
-  0x0c, 0x30, 0x60, 0x0c, 0xce, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xc7, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30,
-  0x30, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0x83, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e,
-  0x00, 0x00, 0xde, 0x63, 0x40, 0x06, 0x03, 0x30, 0x30, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0x04,
-  0x02, 0x00, 0x00, 0x83, 0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x00, 0x00, 0x38, 0x04, 0x02, 0x00, 0x00, 0x83,
-  0xc9, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xc0, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc,
-  0x03, 0x00, 0xe0, 0x1b, 0x0c, 0x08, 0x18, 0x40, 0x30, 0xfe, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84,
-  0x81, 0x01, 0x03, 0x0c, 0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0, 0xff, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0xc0, 0x84, 0x81, 0x01, 0x03, 0x0c,
-  0xc6, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf8, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07,
-  0x0e, 0x00, 0x00, 0x1b, 0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0x10, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x1b,
-  0x0c, 0x30, 0x80, 0x00, 0x30, 0xf8, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40,
-  0x00, 0xe1, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x08, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0x67, 0xc0, 0x01, 0x04, 0x40, 0x00, 0xe1, 0xff, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18,
-  0x30, 0x17, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x9c,
-  0x01, 0x08, 0x60, 0x0c, 0x06, 0x86, 0xff, 0xfd, 0xff, 0xff, 0xff, 0xff,
-  0xff, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xbf, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x07, 0x0e, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00,
-  0xc0, 0x00, 0xfc, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x03, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xf0, 0x9f, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe,
-  0x07, 0x00, 0x00, 0x18, 0x0c, 0xc0, 0x00, 0x00, 0xc0, 0x00, 0xfc, 0xff,
-  0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x1f, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x07, 0x00, 0x00, 0xe0,
-  0x01, 0x06, 0x00, 0x30, 0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff,
-  0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xfc, 0x03, 0x00, 0x00, 0xe0, 0x01, 0x06, 0x00, 0x30,
-  0x06, 0x86, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0,
-  0x00, 0x00, 0x00, 0x60, 0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff,
-  0xff, 0xff, 0xff, 0x8f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x60,
-  0x30, 0x00, 0x63, 0x03, 0x30, 0x00, 0xe0, 0xff, 0xff, 0xff, 0xff, 0x0f,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00,
-  0x00, 0x06, 0x83, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x08, 0x00, 0x00, 0x80, 0x83, 0x09, 0x18, 0x00, 0x00, 0x06, 0x83, 0xff,
-  0xff, 0xff, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x00, 0xc0, 0x00, 0x8c, 0xc9, 0x60, 0x00, 0xfe, 0xff, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
-  0x0f, 0x00, 0x00, 0x00, 0x8e, 0x01, 0x84, 0x40, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x0f, 0x00, 0x00, 0x00,
-  0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
-  0x04, 0x00, 0x00, 0x00, 0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00,
-  0x00, 0xc8, 0x60, 0x83, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00, 0x30, 0x06, 0x00, 0x0c,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0f, 0x00, 0x00, 0x00, 0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00,
-  0x80, 0xc1, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf8, 0xff, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0xc6,
-  0x03, 0x00, 0x00, 0x00, 0x40, 0x08, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0xef, 0x07, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xd8, 0xef, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x1c, 0x80, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xf3,
-  0x0f, 0x00, 0x00, 0x00, 0x80, 0x09, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x88, 0x13, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x13,
-  0x08, 0x00, 0x00, 0x00, 0x00, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x33, 0x0c, 0x00, 0x00, 0x00,
-  0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x88, 0xf3, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0xe3,
-  0x0f, 0x00, 0x00, 0x00, 0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x06, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd8, 0xe1, 0x1f, 0x00, 0x00, 0x00,
-  0x00, 0x86, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0xf0, 0xc1, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x04, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0xc0, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x60, 0xf0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x01, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x06, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x04, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x1e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x10, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x0e, 0x1c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfc, 0x0f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x0f, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xf8, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xe0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0xfe, 0xff, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfe, 0xff, 0x07, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-  };
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68EZ328/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68EZ328/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68EZ328/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68EZ328/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,76 +0,0 @@
-/***************************************************************************/
-
-/*
- *  linux/arch/m68knommu/platform/68EZ328/config.c
- *
- *  Copyright (C) 1993 Hamish Macdonald
- *  Copyright (C) 1999 D. Jeff Dionne
- *
- * 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/types.h>
-#include <linux/kernel.h>
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/MC68EZ328.h>
-#ifdef CONFIG_UCSIMM
-#include <asm/bootstd.h>
-#endif
-
-/***************************************************************************/
-
-void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
-
-/***************************************************************************/
-
-void m68ez328_reset(void)
-{
-  local_irq_disable();
-  asm volatile (
-    "moveal #0x10c00000, %a0;\n"
-    "moveb #0, 0xFFFFF300;\n"
-    "moveal 0(%a0), %sp;\n"
-    "moveal 4(%a0), %a0;\n"
-    "jmp (%a0);\n"
-    );
-}
-
-/***************************************************************************/
-
-unsigned char *cs8900a_hwaddr;
-static int errno;
-
-#ifdef CONFIG_UCSIMM
-_bsc0(char *, getserialnum)
-_bsc1(unsigned char *, gethwaddr, int, a)
-_bsc1(char *, getbenv, char *, a)
-#endif
-
-void config_BSP(char *command, int len)
-{
-  unsigned char *p;
-
-  printk(KERN_INFO "\n68EZ328 DragonBallEZ support (C) 1999 Rt-Control, Inc\n");
-
-#ifdef CONFIG_UCSIMM
-  printk(KERN_INFO "uCsimm serial string [%s]\n",getserialnum());
-  p = cs8900a_hwaddr = gethwaddr(0);
-  printk(KERN_INFO "uCsimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-         p[0], p[1], p[2], p[3], p[4], p[5]);
-
-  p = getbenv("APPEND");
-  if (p) strcpy(p,command);
-  else command[0] = 0;
-#endif
- 
-  mach_gettod = m68328_timer_gettod;
-  mach_reset = m68ez328_reset;
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68EZ328/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/68EZ328/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68EZ328/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68EZ328/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,11 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68EZ328.
-#
-
-obj-y := config.o
-
-extra-y := bootlogo.rh
-
-$(obj)/bootlogo.rh: $(src)/bootlogo.h
-	perl $(src)/../68328/bootlogo.pl < $(src)/bootlogo.h \
-		> $(obj)/bootlogo.rh
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68VZ328/config.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/68VZ328/config.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68VZ328/config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68VZ328/config.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,188 +0,0 @@
-/***************************************************************************/
-
-/*
- *  linux/arch/m68knommu/platform/68VZ328/config.c
- *
- *  Copyright (C) 1993 Hamish Macdonald
- *  Copyright (C) 1999 D. Jeff Dionne
- *  Copyright (C) 2001 Georges Menie, Ken Desmet
- *
- * 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/types.h>
-#include <linux/kernel.h>
-#include <linux/kd.h>
-#include <linux/netdevice.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-
-#include <asm/system.h>
-#include <asm/pgtable.h>
-#include <asm/machdep.h>
-#include <asm/MC68VZ328.h>
-#include <asm/bootstd.h>
-
-#ifdef CONFIG_INIT_LCD
-#include "bootlogo.h"
-#endif
-
-/***************************************************************************/
-
-void m68328_timer_gettod(int *year, int *mon, int *day, int *hour, int *min, int *sec);
-
-/***************************************************************************/
-/*                        Init Drangon Engine hardware                     */
-/***************************************************************************/
-#if defined(CONFIG_DRAGEN2)
-
-static void m68vz328_reset(void)
-{
-	local_irq_disable();
-
-#ifdef CONFIG_INIT_LCD
-	PBDATA |= 0x20;				/* disable CCFL light */
-	PKDATA |= 0x4;				/* disable LCD controller */
-	LCKCON = 0;
-#endif
-
-	__asm__ __volatile__(
-		"reset\n\t"
-		"moveal #0x04000000, %a0\n\t"
-		"moveal 0(%a0), %sp\n\t"
-		"moveal 4(%a0), %a0\n\t"
-		"jmp (%a0)"
-	);
-}
-
-static void init_hardware(char *command, int size)
-{
-#ifdef CONFIG_DIRECT_IO_ACCESS
-	SCR = 0x10;					/* allow user access to internal registers */
-#endif
-
-	/* CSGB Init */
-	CSGBB = 0x4000;
-	CSB = 0x1a1;
-
-	/* CS8900 init */
-	/* PK3: hardware sleep function pin, active low */
-	PKSEL |= PK(3);				/* select pin as I/O */
-	PKDIR |= PK(3);				/* select pin as output */
-	PKDATA |= PK(3);			/* set pin high */
-
-	/* PF5: hardware reset function pin, active high */
-	PFSEL |= PF(5);				/* select pin as I/O */
-	PFDIR |= PF(5);				/* select pin as output */
-	PFDATA &= ~PF(5);			/* set pin low */
-
-	/* cs8900 hardware reset */
-	PFDATA |= PF(5);
-	{ int i; for (i = 0; i < 32000; ++i); }
-	PFDATA &= ~PF(5);
-
-	/* INT1 enable (cs8900 IRQ) */
-	PDPOL &= ~PD(1);			/* active high signal */
-	PDIQEG &= ~PD(1);
-	PDIRQEN |= PD(1);			/* IRQ enabled */
-
-#ifdef CONFIG_INIT_LCD
-	/* initialize LCD controller */
-	LSSA = (long) screen_bits;
-	LVPW = 0x14;
-	LXMAX = 0x140;
-	LYMAX = 0xef;
-	LRRA = 0;
-	LPXCD = 3;
-	LPICF = 0x08;
-	LPOLCF = 0;
-	LCKCON = 0x80;
-	PCPDEN = 0xff;
-	PCSEL = 0;
-
-	/* Enable LCD controller */
-	PKDIR |= 0x4;
-	PKSEL |= 0x4;
-	PKDATA &= ~0x4;
-
-	/* Enable CCFL backlighting circuit */
-	PBDIR |= 0x20;
-	PBSEL |= 0x20;
-	PBDATA &= ~0x20;
-
-	/* contrast control register */
-	PFDIR |= 0x1;
-	PFSEL &= ~0x1;
-	PWMR = 0x037F;
-#endif
-}
-
-/***************************************************************************/
-/*                      Init RT-Control uCdimm hardware                    */
-/***************************************************************************/
-#elif defined(CONFIG_UCDIMM)
-
-static void m68vz328_reset(void)
-{
-	local_irq_disable();
-	asm volatile (
-		"moveal #0x10c00000, %a0;\n\t"
-		"moveb #0, 0xFFFFF300;\n\t"
-		"moveal 0(%a0), %sp;\n\t"
-		"moveal 4(%a0), %a0;\n\t"
-		"jmp (%a0);\n"
-	);
-}
-
-unsigned char *cs8900a_hwaddr;
-static int errno;
-
-_bsc0(char *, getserialnum)
-_bsc1(unsigned char *, gethwaddr, int, a)
-_bsc1(char *, getbenv, char *, a)
-
-static void init_hardware(char *command, int size)
-{
-	char *p;
-
-	printk(KERN_INFO "uCdimm serial string [%s]\n", getserialnum());
-	p = cs8900a_hwaddr = gethwaddr(0);
-	printk(KERN_INFO "uCdimm hwaddr %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
-		p[0], p[1], p[2], p[3], p[4], p[5]);
-	p = getbenv("APPEND");
-	if (p)
-		strcpy(p, command);
-	else
-		command[0] = 0;
-}
-
-/***************************************************************************/
-#else
-
-static void m68vz328_reset(void)
-{
-}
-
-static void init_hardware(char *command, int size)
-{
-}
-
-/***************************************************************************/
-#endif
-/***************************************************************************/
-
-void config_BSP(char *command, int size)
-{
-	printk(KERN_INFO "68VZ328 DragonBallVZ support (c) 2001 Lineo, Inc.\n");
-
-	init_hardware(command, size);
-
-	mach_gettod = m68328_timer_gettod;
-	mach_reset = m68vz328_reset;
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/68VZ328/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/68VZ328/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/68VZ328/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/68VZ328/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-#
-# Makefile for arch/m68knommu/platform/68VZ328.
-#
-
-obj-y		:= config.o
-logo-$(UCDIMM)	:= bootlogo.rh
-logo-$(DRAGEN2)	:= screen.h
-extra-y		:= $(logo-y)
-
-$(obj)/bootlogo.rh: $(src)/../68EZ328/bootlogo.h
-	perl $(src)/bootlogo.pl < $(src)/../68328/bootlogo.h > $(obj)/bootlogo.rh
-
-$(obj)/screen.h: $(src)/screen.xbm $(src)/xbm2lcd.pl
-	perl $(src)/xbm2lcd.pl < $(src)/screen.xbm > $(obj)/screen.h
-
-clean-files := $(obj)/screen.h $(obj)/bootlogo.rh
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/cache.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/cache.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/cache.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/cache.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,48 +0,0 @@
-/***************************************************************************/
-
-/*
- *	cache.c -- general ColdFire Cache maintainence code
- *
- *	Copyright (C) 2010, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/***************************************************************************/
-#ifdef CACHE_PUSH
-/***************************************************************************/
-
-/*
- *	Use cpushl to push all dirty cache lines back to memory.
- *	Older versions of GAS don't seem to know how to generate the
- *	ColdFire cpushl instruction... Oh well, bit stuff it for now.
- */
-
-void mcf_cache_push(void)
-{
-	__asm__ __volatile__ (
-		"clrl	%%d0\n\t"
-		"1:\n\t"
-		"movel	%%d0,%%a0\n\t"
-		"2:\n\t"
-		".word	0xf468\n\t"
-		"addl	%0,%%a0\n\t"
-		"cmpl	%1,%%a0\n\t"
-		"blt	2b\n\t"
-		"addql	#1,%%d0\n\t"
-		"cmpil	%2,%%d0\n\t"
-		"bne	1b\n\t"
-		: /* No output */
-		: "i" (CACHE_LINE_SIZE),
-		  "i" (DCACHE_SIZE / CACHE_WAYS),
-		  "i" (CACHE_WAYS)
-		: "d0", "a0" );
-}
-
-/***************************************************************************/
-#endif /* CACHE_PUSH */
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/clk.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/clk.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/clk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/clk.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/***************************************************************************/
-
-/*
- *	clk.c -- general ColdFire CPU kernel clk handling
- *
- *	Copyright (C) 2009, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/clk.h>
-#include <asm/coldfire.h>
-
-/***************************************************************************/
-
-struct clk *clk_get(struct device *dev, const char *id)
-{
-	return NULL;
-}
-EXPORT_SYMBOL(clk_get);
-
-int clk_enable(struct clk *clk)
-{
-	return 0;
-}
-EXPORT_SYMBOL(clk_enable);
-
-void clk_disable(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_disable);
-
-void clk_put(struct clk *clk)
-{
-}
-EXPORT_SYMBOL(clk_put);
-
-unsigned long clk_get_rate(struct clk *clk)
-{
-	return MCF_CLK;
-}
-EXPORT_SYMBOL(clk_get_rate);
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/dma.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/dma.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/***************************************************************************/
-
-/*
- *	dma.c -- Freescale ColdFire DMA support
- *
- *	Copyright (C) 2007, Greg Ungerer (gerg@snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <asm/dma.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfdma.h>
-
-/***************************************************************************/
-
-/*
- *      DMA channel base address table.
- */
-unsigned int dma_base_addr[MAX_M68K_DMA_CHANNELS] = {
-#ifdef MCFDMA_BASE0
-	MCF_MBAR + MCFDMA_BASE0,
-#endif
-#ifdef MCFDMA_BASE1
-	MCF_MBAR + MCFDMA_BASE1,
-#endif
-#ifdef MCFDMA_BASE2
-	MCF_MBAR + MCFDMA_BASE2,
-#endif
-#ifdef MCFDMA_BASE3
-	MCF_MBAR + MCFDMA_BASE3,
-#endif
-};
-
-unsigned int dma_device_address[MAX_M68K_DMA_CHANNELS];
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/dma_timer.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/dma_timer.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/dma_timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/dma_timer.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,84 +0,0 @@
-/*
- * dma_timer.c -- Freescale ColdFire DMA Timer.
- *
- * Copyright (C) 2007, Benedikt Spranger <b.spranger@linutronix.de>
- * Copyright (C) 2008. Sebastian Siewior, Linutronix
- *
- */
-
-#include <linux/clocksource.h>
-#include <linux/io.h>
-
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfpit.h>
-#include <asm/mcfsim.h>
-
-#define DMA_TIMER_0	(0x00)
-#define DMA_TIMER_1	(0x40)
-#define DMA_TIMER_2	(0x80)
-#define DMA_TIMER_3	(0xc0)
-
-#define DTMR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x400)
-#define DTXMR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x402)
-#define DTER0	(MCF_IPSBAR + DMA_TIMER_0 + 0x403)
-#define DTRR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x404)
-#define DTCR0	(MCF_IPSBAR + DMA_TIMER_0 + 0x408)
-#define DTCN0	(MCF_IPSBAR + DMA_TIMER_0 + 0x40c)
-
-#define DMA_FREQ    ((MCF_CLK / 2) / 16)
-
-/* DTMR */
-#define DMA_DTMR_RESTART	(1 << 3)
-#define DMA_DTMR_CLK_DIV_1	(1 << 1)
-#define DMA_DTMR_CLK_DIV_16	(2 << 1)
-#define DMA_DTMR_ENABLE		(1 << 0)
-
-static cycle_t cf_dt_get_cycles(struct clocksource *cs)
-{
-	return __raw_readl(DTCN0);
-}
-
-static struct clocksource clocksource_cf_dt = {
-	.name		= "coldfire_dma_timer",
-	.rating		= 200,
-	.read		= cf_dt_get_cycles,
-	.mask		= CLOCKSOURCE_MASK(32),
-	.shift		= 20,
-	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-static int __init  init_cf_dt_clocksource(void)
-{
-	/*
-	 * We setup DMA timer 0 in free run mode. This incrementing counter is
-	 * used as a highly precious clock source. With MCF_CLOCK = 150 MHz we
-	 * get a ~213 ns resolution and the 32bit register will overflow almost
-	 * every 15 minutes.
-	 */
-	__raw_writeb(0x00, DTXMR0);
-	__raw_writeb(0x00, DTER0);
-	__raw_writel(0x00000000, DTRR0);
-	__raw_writew(DMA_DTMR_CLK_DIV_16 | DMA_DTMR_ENABLE, DTMR0);
-	clocksource_cf_dt.mult = clocksource_hz2mult(DMA_FREQ,
-						     clocksource_cf_dt.shift);
-	return clocksource_register(&clocksource_cf_dt);
-}
-
-arch_initcall(init_cf_dt_clocksource);
-
-#define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
-#define CYC2NS_SCALE	((1000000 << CYC2NS_SCALE_FACTOR) / (DMA_FREQ / 1000))
-
-static unsigned long long cycles2ns(unsigned long cycl)
-{
-	return (unsigned long long) ((unsigned long long)cycl *
-			CYC2NS_SCALE) >> CYC2NS_SCALE_FACTOR;
-}
-
-unsigned long long sched_clock(void)
-{
-	unsigned long cycl = __raw_readl(DTCN0);
-
-	return cycles2ns(cycl);
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/entry.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/entry.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/entry.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,203 +0,0 @@
-/*
- *  linux/arch/m68knommu/platform/5307/entry.S
- *
- *  Copyright (C) 1999-2007, Greg Ungerer (gerg@snapgear.com)
- *  Copyright (C) 1998  D. Jeff Dionne <jeff@lineo.ca>,
- *                      Kenneth Albanowski <kjahds@kjahds.com>,
- *  Copyright (C) 2000  Lineo Inc. (www.lineo.com)
- *  Copyright (C) 2004-2006  Macq Electronique SA. (www.macqel.com)
- *
- * Based on:
- *
- *  linux/arch/m68k/kernel/entry.S
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *
- * This file is subject to the terms and conditions of the GNU General Public
- * License.  See the file README.legal in the main directory of this archive
- * for more details.
- *
- * Linux/m68k support by Hamish Macdonald
- *
- * 68060 fixes by Jesper Skov
- * ColdFire support by Greg Ungerer (gerg@snapgear.com)
- * 5307 fixes by David W. Miller
- * linux 2.4 support David McCullough <davidm@snapgear.com>
- * Bug, speed and maintainability fixes by Philippe De Muyter <phdm@macqel.be>
- */
-
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/unistd.h>
-#include <asm/thread_info.h>
-#include <asm/errno.h>
-#include <asm/setup.h>
-#include <asm/segment.h>
-#include <asm/asm-offsets.h>
-#include <asm/entry.h>
-
-#ifdef CONFIG_COLDFIRE_SW_A7
-/*
- *	Define software copies of the supervisor and user stack pointers.
- */
-.bss
-sw_ksp:
-.long	0
-sw_usp:
-.long	0
-#endif /* CONFIG_COLDFIRE_SW_A7 */
-
-.text
-
-.globl system_call
-.globl resume
-.globl ret_from_exception
-.globl ret_from_signal
-.globl sys_call_table
-.globl inthandler
-.globl fasthandler
-
-enosys:
-	mov.l	#sys_ni_syscall,%d3
-	bra	1f
-
-ENTRY(system_call)
-	SAVE_ALL
-	move	#0x2000,%sr		/* enable intrs again */
-
-	cmpl	#NR_syscalls,%d0
-	jcc	enosys
-	lea	sys_call_table,%a0
-	lsll	#2,%d0			/* movel %a0@(%d0:l:4),%d3 */
-	movel	%a0@(%d0),%d3
-	jeq	enosys
-
-1:
-	movel	%sp,%d2			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d2	/* at start of kernel stack */
-	movel	%d2,%a0
-	movel	%a0@,%a1		/* save top of frame */
-	movel	%sp,%a1@(TASK_THREAD+THREAD_ESP0)
-	btst	#(TIF_SYSCALL_TRACE%8),%a0@(TI_FLAGS+(31-TIF_SYSCALL_TRACE)/8)
-	bnes	1f
-
-	movel	%d3,%a0
-	jbsr	%a0@
-	movel	%d0,%sp@(PT_OFF_D0)	/* save the return value */
-	jra	ret_from_exception
-1:
-	movel	#-ENOSYS,%d2		/* strace needs -ENOSYS in PT_OFF_D0 */
-	movel	%d2,PT_OFF_D0(%sp)	/* on syscall entry */
-	subql	#4,%sp
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace_enter
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	movel	%d3,%a0
-	jbsr	%a0@
-	movel	%d0,%sp@(PT_OFF_D0)		/* save the return value */
-	subql	#4,%sp			/* dummy return address */
-	SAVE_SWITCH_STACK
-	jbsr	syscall_trace_leave
-
-ret_from_signal:
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-
-ret_from_exception:
-	move	#0x2700,%sr		/* disable intrs */
-	btst	#5,%sp@(PT_OFF_SR)	/* check if returning to kernel */
-	jeq	Luser_return		/* if so, skip resched, signals */
-
-#ifdef CONFIG_PREEMPT
-	movel	%sp,%d1			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
-	movel	%d1,%a0
-	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	andl	#(1<<TIF_NEED_RESCHED),%d1
-	jeq	Lkernel_return
-
-	movel	%a0@(TI_PREEMPTCOUNT),%d1
-	cmpl	#0,%d1
-	jne	Lkernel_return
-
-	pea	Lkernel_return
-	jmp	preempt_schedule_irq	/* preempt the kernel */
-#endif
-
-Lkernel_return:
-	moveml	%sp@,%d1-%d5/%a0-%a2
-	lea	%sp@(32),%sp		/* space for 8 regs */
-	movel	%sp@+,%d0
-	addql	#4,%sp			/* orig d0 */
-	addl	%sp@+,%sp		/* stk adj */
-	rte
-
-Luser_return:
-	movel	%sp,%d1			/* get thread_info pointer */
-	andl	#-THREAD_SIZE,%d1	/* at base of kernel stack */
-	movel	%d1,%a0
-	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	jne	Lwork_to_do		/* still work to do */
-
-Lreturn:
-	RESTORE_USER
-
-Lwork_to_do:
-	movel	%a0@(TI_FLAGS),%d1	/* get thread_info->flags */
-	move	#0x2000,%sr		/* enable intrs again */
-	btst	#TIF_NEED_RESCHED,%d1
-	jne	reschedule
-
-	/* GERG: do we need something here for TRACEing?? */
-
-Lsignal_return:
-	subql	#4,%sp			/* dummy return address */
-	SAVE_SWITCH_STACK
-	pea	%sp@(SWITCH_STACK_SIZE)
-	jsr	do_signal
-	addql	#4,%sp
-	RESTORE_SWITCH_STACK
-	addql	#4,%sp
-	jmp	Luser_return
-
-/*
- * This is the generic interrupt handler (for all hardware interrupt
- * sources). Calls upto high level code to do all the work.
- */
-ENTRY(inthandler)
-	SAVE_ALL
-	moveq	#-1,%d0
-	movel	%d0,%sp@(PT_OFF_ORIG_D0)
-
-	movew	%sp@(PT_OFF_FORMATVEC),%d0 /* put exception # in d0 */
-	andl	#0x03fc,%d0		/* mask out vector only */
-
-	movel	%sp,%sp@-		/* push regs arg */
-	lsrl	#2,%d0			/* calculate real vector # */
-	movel	%d0,%sp@-		/* push vector number */
-	jbsr	do_IRQ			/* call high level irq handler */
-	lea	%sp@(8),%sp		/* pop args off stack */
-
-	bra	ret_from_exception
-
-/*
- * Beware - when entering resume, prev (the current task) is
- * in a0, next (the new task) is in a1,so don't change these
- * registers until their contents are no longer needed.
- * This is always called in supervisor mode, so don't bother to save
- * and restore sr; user's process sr is actually in the stack.
- */
-ENTRY(resume)
-	movel	%a0, %d1			/* get prev thread in d1 */
-	RDUSP
-	movel	%a2,%a0@(TASK_THREAD+THREAD_USP)
-
-	SAVE_SWITCH_STACK
-	movel	%sp,%a0@(TASK_THREAD+THREAD_KSP) /* save kernel stack pointer */
-	movel	%a1@(TASK_THREAD+THREAD_KSP),%sp /* restore new thread stack */
-	RESTORE_SWITCH_STACK
-
-	movel	%a1@(TASK_THREAD+THREAD_USP),%a0 /* restore thread user stack */
-	WRUSP
-	rts
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/gpio.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/gpio.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/gpio.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,127 +0,0 @@
-/*
- * Coldfire generic GPIO support.
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; 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/sysdev.h>
-
-#include <asm/gpio.h>
-#include <asm/pinmux.h>
-#include <asm/mcfgpio.h>
-
-#define MCF_CHIP(chip) container_of(chip, struct mcf_gpio_chip, gpio_chip)
-
-int mcf_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
-{
-	unsigned long flags;
-	MCFGPIO_PORTTYPE dir;
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	local_irq_save(flags);
-	dir = mcfgpio_read(mcf_chip->pddr);
-	dir &= ~mcfgpio_bit(chip->base + offset);
-	mcfgpio_write(dir, mcf_chip->pddr);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-int mcf_gpio_get_value(struct gpio_chip *chip, unsigned offset)
-{
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	return mcfgpio_read(mcf_chip->ppdr) & mcfgpio_bit(chip->base + offset);
-}
-
-int mcf_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
-		int value)
-{
-	unsigned long flags;
-	MCFGPIO_PORTTYPE data;
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	local_irq_save(flags);
-	/* write the value to the output latch */
-	data = mcfgpio_read(mcf_chip->podr);
-	if (value)
-		data |= mcfgpio_bit(chip->base + offset);
-	else
-		data &= ~mcfgpio_bit(chip->base + offset);
-	mcfgpio_write(data, mcf_chip->podr);
-
-	/* now set the direction to output */
-	data = mcfgpio_read(mcf_chip->pddr);
-	data |= mcfgpio_bit(chip->base + offset);
-	mcfgpio_write(data, mcf_chip->pddr);
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-void mcf_gpio_set_value(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	unsigned long flags;
-	MCFGPIO_PORTTYPE data;
-
-	local_irq_save(flags);
-	data = mcfgpio_read(mcf_chip->podr);
-	if (value)
-		data |= mcfgpio_bit(chip->base + offset);
-	else
-		data &= ~mcfgpio_bit(chip->base + offset);
-	mcfgpio_write(data, mcf_chip->podr);
-	local_irq_restore(flags);
-}
-
-void mcf_gpio_set_value_fast(struct gpio_chip *chip, unsigned offset, int value)
-{
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	if (value)
-		mcfgpio_write(mcfgpio_bit(chip->base + offset), mcf_chip->setr);
-	else
-		mcfgpio_write(~mcfgpio_bit(chip->base + offset), mcf_chip->clrr);
-}
-
-int mcf_gpio_request(struct gpio_chip *chip, unsigned offset)
-{
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	return mcf_chip->gpio_to_pinmux ?
-		mcf_pinmux_request(mcf_chip->gpio_to_pinmux[offset], 0) : 0;
-}
-
-void mcf_gpio_free(struct gpio_chip *chip, unsigned offset)
-{
-	struct mcf_gpio_chip *mcf_chip = MCF_CHIP(chip);
-
-	mcf_gpio_direction_input(chip, offset);
-
-	if (mcf_chip->gpio_to_pinmux)
-		mcf_pinmux_release(mcf_chip->gpio_to_pinmux[offset], 0);
-}
-
-struct sysdev_class mcf_gpio_sysclass = {
-	.name	= "gpio",
-};
-
-static int __init mcf_gpio_sysinit(void)
-{
-	return sysdev_class_register(&mcf_gpio_sysclass);
-}
-
-core_initcall(mcf_gpio_sysinit);
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/head.S linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/head.S
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/head.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,250 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	head.S -- common startup code for ColdFire CPUs.
- *
- *	(C) Copyright 1999-2010, Greg Ungerer <gerg@snapgear.com>.
- */
-
-/*****************************************************************************/
-
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <linux/init.h>
-#include <asm/asm-offsets.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/thread_info.h>
-
-/*****************************************************************************/
-
-/*
- *	If we don't have a fixed memory size, then lets build in code
- *	to auto detect the DRAM size. Obviously this is the prefered
- *	method, and should work for most boards. It won't work for those
- *	that do not have their RAM starting at address 0, and it only
- *	works on SDRAM (not boards fitted with SRAM).
- */
-#if CONFIG_RAMSIZE != 0
-.macro GET_MEM_SIZE
-	movel	#CONFIG_RAMSIZE,%d0	/* hard coded memory size */
-.endm
-
-#elif defined(CONFIG_M5206) || defined(CONFIG_M5206e) || \
-      defined(CONFIG_M5249) || defined(CONFIG_M527x) || \
-      defined(CONFIG_M528x) || defined(CONFIG_M5307) || \
-      defined(CONFIG_M5407)
-/*
- *	Not all these devices have exactly the same DRAM controller,
- *	but the DCMR register is virtually identical - give or take
- *	a couple of bits. The only exception is the 5272 devices, their
- *	DRAM controller is quite different.
- */
-.macro GET_MEM_SIZE
-	movel	MCF_MBAR+MCFSIM_DMR0,%d0 /* get mask for 1st bank */
-	btst	#0,%d0			/* check if region enabled */
-	beq	1f
-	andl	#0xfffc0000,%d0
-	beq	1f
-	addl	#0x00040000,%d0		/* convert mask to size */
-1:
-	movel	MCF_MBAR+MCFSIM_DMR1,%d1 /* get mask for 2nd bank */
-	btst	#0,%d1			/* check if region enabled */
-	beq	2f
-	andl	#0xfffc0000, %d1
-	beq	2f
-	addl	#0x00040000,%d1
-	addl	%d1,%d0			/* total mem size in d0 */
-2:
-.endm
-
-#elif defined(CONFIG_M5272)
-.macro GET_MEM_SIZE
-	movel	MCF_MBAR+MCFSIM_CSOR7,%d0 /* get SDRAM address mask */
-	andil	#0xfffff000,%d0		/* mask out chip select options */
-	negl	%d0			/* negate bits */
-.endm
-
-#elif defined(CONFIG_M520x)
-.macro GET_MEM_SIZE
-	clrl	%d0
-	movel	MCF_MBAR+MCFSIM_SDCS0, %d2 /* Get SDRAM chip select 0 config */
-	andl	#0x1f, %d2		/* Get only the chip select size */
-	beq	3f			/* Check if it is enabled */
-	addql	#1, %d2			/* Form exponent */
-	moveql	#1, %d0
-	lsll	%d2, %d0		/* 2 ^ exponent */
-3:
-	movel	MCF_MBAR+MCFSIM_SDCS1, %d2 /* Get SDRAM chip select 1 config */
-	andl	#0x1f, %d2		/* Get only the chip select size */
-	beq	4f			/* Check if it is enabled */
-	addql	#1, %d2			/* Form exponent */
-	moveql	#1, %d1
-	lsll	%d2, %d1		/* 2 ^ exponent */
-	addl	%d1, %d0		/* Total size of SDRAM in d0 */
-4:
-.endm
-
-#else
-#error "ERROR: I don't know how to probe your boards memory size?"
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Boards and platforms can do specific early hardware setup if
- *	they need to. Most don't need this, define away if not required.
- */
-#ifndef PLATFORM_SETUP
-#define	PLATFORM_SETUP
-#endif
-
-/*****************************************************************************/
-
-.global	_start
-.global _rambase
-.global _ramvec
-.global	_ramstart
-.global	_ramend
-#if defined(CONFIG_UBOOT)
-.global	_init_sp
-#endif
-
-/*****************************************************************************/
-
-.data
-
-/*
- *	During startup we store away the RAM setup. These are not in the
- *	bss, since their values are determined and written before the bss
- *	has been cleared.
- */
-_rambase:
-.long	0
-_ramvec:
-.long	0
-_ramstart:
-.long	0
-_ramend:
-.long	0
-#if defined(CONFIG_UBOOT)
-_init_sp:
-.long	0
-#endif
-
-/*****************************************************************************/
-
-__HEAD
-
-/*
- *	This is the codes first entry point. This is where it all
- *	begins...
- */
-
-_start:
-	nop					/* filler */
-	movew	#0x2700, %sr			/* no interrupts */
-#if defined(CONFIG_UBOOT)
-	movel	%sp,_init_sp			/* save initial stack pointer */
-#endif
-
-	/*
-	 *	Do any platform or board specific setup now. Most boards
-	 *	don't need anything. Those exceptions are define this in
-	 *	their board specific includes.
-	 */
-	PLATFORM_SETUP
-
-	/*
-	 *	Create basic memory configuration. Set VBR accordingly,
-	 *	and size memory.
-	 */
-	movel	#CONFIG_VECTORBASE,%a7
-	movec   %a7,%VBR			/* set vectors addr */
-	movel	%a7,_ramvec
-
-	movel	#CONFIG_RAMBASE,%a7		/* mark the base of RAM */
-	movel	%a7,_rambase
-
-	GET_MEM_SIZE				/* macro code determines size */
-	addl	%a7,%d0
-	movel	%d0,_ramend			/* set end ram addr */
-
-	/*
-	 *	Now that we know what the memory is, lets enable cache
-	 *	and get things moving. This is Coldfire CPU specific. Not
-	 *	all version cores have identical cache register setup. But
-	 *	it is very similar. Define the exact settings in the headers
-	 *	then the code here is the same for all.
-	 */
-	movel	#CACHE_INIT,%d0			/* invalidate whole cache */
-	movec	%d0,%CACR
-	nop
-	movel	#ACR0_MODE,%d0			/* set RAM region for caching */
-	movec	%d0,%ACR0
-	movel	#ACR1_MODE,%d0			/* anything else to cache? */
-	movec	%d0,%ACR1
-#ifdef ACR2_MODE
-	movel	#ACR2_MODE,%d0
-	movec	%d0,%ACR2
-	movel	#ACR3_MODE,%d0
-	movec	%d0,%ACR3
-#endif
-	movel	#CACHE_MODE,%d0			/* enable cache */
-	movec	%d0,%CACR
-	nop
-
-#ifdef CONFIG_ROMFS_FS
-	/*
-	 *	Move ROM filesystem above bss :-)
-	 */
-	lea	_sbss,%a0			/* get start of bss */
-	lea	_ebss,%a1			/* set up destination  */
-	movel	%a0,%a2				/* copy of bss start */
-
-	movel	8(%a0),%d0			/* get size of ROMFS */
-	addql	#8,%d0				/* allow for rounding */
-	andl	#0xfffffffc, %d0		/* whole words */
-
-	addl	%d0,%a0				/* copy from end */
-	addl	%d0,%a1				/* copy from end */
-	movel	%a1,_ramstart			/* set start of ram */
-
-_copy_romfs:
-	movel	-(%a0),%d0			/* copy dword */
-	movel	%d0,-(%a1)
-	cmpl	%a0,%a2				/* check if at end */
-	bne	_copy_romfs
-
-#else /* CONFIG_ROMFS_FS */
-	lea	_ebss,%a1
-	movel	%a1,_ramstart
-#endif /* CONFIG_ROMFS_FS */
-
-
-	/*
-	 *	Zero out the bss region.
-	 */
-	lea	_sbss,%a0			/* get start of bss */
-	lea	_ebss,%a1			/* get end of bss */
-	clrl	%d0				/* set value */
-_clear_bss:
-	movel	%d0,(%a0)+			/* clear each word */
-	cmpl	%a0,%a1				/* check if at end */
-	bne	_clear_bss
-
-	/*
-	 *	Load the current task pointer and stack.
-	 */
-	lea	init_thread_union,%a0
-	lea	THREAD_SIZE(%a0),%sp
-
-	/*
-	 *	Assember start up done, start code proper.
-	 */
-	jsr	start_kernel			/* start Linux kernel */
-
-_exit:
-	jmp	_exit				/* should never get here */
-
-/*****************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/intc-2.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/intc-2.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/intc-2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/intc-2.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,126 +0,0 @@
-/*
- * intc-2.c
- *
- * General interrupt controller code for the many ColdFire cores that use
- * interrupt controllers with 63 interrupt sources, organized as 56 fully-
- * programmable + 7 fixed-level interrupt sources. This includes the 523x
- * family, the 5270, 5271, 5274, 5275, and the 528x family which have two such
- * controllers, and the 547x and 548x families which have only one of them.
- *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/traps.h>
-
-/*
- * Bit definitions for the ICR family of registers.
- */
-#define MCFSIM_ICR_LEVEL(l)	((l)<<3)	/* Level l intr */
-#define MCFSIM_ICR_PRI(p)	(p)		/* Priority p intr */
-
-/*
- *	Each vector needs a unique priority and level associated with it.
- *	We don't really care so much what they are, we don't rely on the
- *	traditional priority interrupt scheme of the m68k/ColdFire.
- */
-static u8 intc_intpri = MCFSIM_ICR_LEVEL(6) | MCFSIM_ICR_PRI(6);
-
-#ifdef MCFICM_INTC1
-#define NR_VECS	128
-#else
-#define NR_VECS	64
-#endif
-
-static void intc_irq_mask(unsigned int irq)
-{
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
-		unsigned long imraddr;
-		u32 val, imrbit;
-
-		irq -= MCFINT_VECBASE;
-		imraddr = MCF_IPSBAR;
-#ifdef MCFICM_INTC1
-		imraddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
-#else
-		imraddr += MCFICM_INTC0;
-#endif
-		imraddr += (irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL;
-		imrbit = 0x1 << (irq & 0x1f);
-
-		val = __raw_readl(imraddr);
-		__raw_writel(val | imrbit, imraddr);
-	}
-}
-
-static void intc_irq_unmask(unsigned int irq)
-{
-	if ((irq >= MCFINT_VECBASE) && (irq <= MCFINT_VECBASE + NR_VECS)) {
-		unsigned long intaddr, imraddr, icraddr;
-		u32 val, imrbit;
-
-		irq -= MCFINT_VECBASE;
-		intaddr = MCF_IPSBAR;
-#ifdef MCFICM_INTC1
-		intaddr += (irq & 0x40) ? MCFICM_INTC1 : MCFICM_INTC0;
-#else
-		intaddr += MCFICM_INTC0;
-#endif
-		imraddr = intaddr + ((irq & 0x20) ? MCFINTC_IMRH : MCFINTC_IMRL);
-		icraddr = intaddr + MCFINTC_ICR0 + (irq & 0x3f);
-		imrbit = 0x1 << (irq & 0x1f);
-
-		/* Don't set the "maskall" bit! */
-		if ((irq & 0x20) == 0)
-			imrbit |= 0x1;
-
-		if (__raw_readb(icraddr) == 0)
-			__raw_writeb(intc_intpri--, icraddr);
-
-		val = __raw_readl(imraddr);
-		__raw_writel(val & ~imrbit, imraddr);
-	}
-}
-
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
-{
-	return 0;
-}
-
-static struct irq_chip intc_irq_chip = {
-	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.set_type	= intc_irq_set_type,
-};
-
-void __init init_IRQ(void)
-{
-	int irq;
-
-	init_vectors();
-
-	/* Mask all interrupt sources */
-	__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC0 + MCFINTC_IMRL);
-#ifdef MCFICM_INTC1
-	__raw_writel(0x1, MCF_IPSBAR + MCFICM_INTC1 + MCFINTC_IMRL);
-#endif
-
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		set_irq_chip(irq, &intc_irq_chip);
-		set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-		set_irq_handler(irq, handle_level_irq);
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/intc.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/intc.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/intc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/intc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,151 +0,0 @@
-/*
- * intc.c  -- support for the old ColdFire interrupt controller
- *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/traps.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-
-/*
- * The mapping of irq number to a mask register bit is not one-to-one.
- * The irq numbers are either based on "level" of interrupt or fixed
- * for an autovector-able interrupt. So we keep a local data structure
- * that maps from irq to mask register. Not all interrupts will have
- * an IMR bit.
- */
-unsigned char mcf_irq2imr[NR_IRQS];
-
-/*
- * Define the miniumun and maximum external interrupt numbers.
- * This is also used as the "level" interrupt numbers.
- */
-#define	EIRQ1	25
-#define	EIRQ7	31
-
-/*
- * In the early version 2 core ColdFire parts the IMR register was 16 bits
- * in size. Version 3 (and later version 2) core parts have a 32 bit
- * sized IMR register. Provide some size independant methods to access the
- * IMR register.
- */
-#ifdef MCFSIM_IMR_IS_16BITS
-
-void mcf_setimr(int index)
-{
-	u16 imr;
-	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
-	__raw_writew(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
-}
-
-void mcf_clrimr(int index)
-{
-	u16 imr;
-	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
-	__raw_writew(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
-}
-
-void mcf_maskimr(unsigned int mask)
-{
-	u16 imr;
-	imr = __raw_readw(MCF_MBAR + MCFSIM_IMR);
-	imr |= mask;
-	__raw_writew(imr, MCF_MBAR + MCFSIM_IMR);
-}
-
-#else
-
-void mcf_setimr(int index)
-{
-	u32 imr;
-	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
-	__raw_writel(imr | (0x1 << index), MCF_MBAR + MCFSIM_IMR);
-}
-
-void mcf_clrimr(int index)
-{
-	u32 imr;
-	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
-	__raw_writel(imr & ~(0x1 << index), MCF_MBAR + MCFSIM_IMR);
-}
-
-void mcf_maskimr(unsigned int mask)
-{
-	u32 imr;
-	imr = __raw_readl(MCF_MBAR + MCFSIM_IMR);
-	imr |= mask;
-	__raw_writel(imr, MCF_MBAR + MCFSIM_IMR);
-}
-
-#endif
-
-/*
- * Interrupts can be "vectored" on the ColdFire cores that support this old
- * interrupt controller. That is, the device raising the interrupt can also
- * supply the vector number to interrupt through. The AVR register of the
- * interrupt controller enables or disables this for each external interrupt,
- * so provide generic support for this. Setting this up is out-of-band for
- * the interrupt system API's, and needs to be done by the driver that
- * supports this device. Very few devices actually use this.
- */
-void mcf_autovector(int irq)
-{
-#ifdef MCFSIM_AVR
-	if ((irq >= EIRQ1) && (irq <= EIRQ7)) {
-		u8 avec;
-		avec = __raw_readb(MCF_MBAR + MCFSIM_AVR);
-		avec |= (0x1 << (irq - EIRQ1 + 1));
-		__raw_writeb(avec, MCF_MBAR + MCFSIM_AVR);
-	}
-#endif
-}
-
-static void intc_irq_mask(unsigned int irq)
-{
-	if (mcf_irq2imr[irq])
-		mcf_setimr(mcf_irq2imr[irq]);
-}
-
-static void intc_irq_unmask(unsigned int irq)
-{
-	if (mcf_irq2imr[irq])
-		mcf_clrimr(mcf_irq2imr[irq]);
-}
-
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
-{
-	return 0;
-}
-
-static struct irq_chip intc_irq_chip = {
-	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.set_type	= intc_irq_set_type,
-};
-
-void __init init_IRQ(void)
-{
-	int irq;
-
-	init_vectors();
-	mcf_maskimr(0xffffffff);
-
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		set_irq_chip(irq, &intc_irq_chip);
-		set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-		set_irq_handler(irq, handle_level_irq);
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/intc-simr.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/intc-simr.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/intc-simr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/intc-simr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,78 +0,0 @@
-/*
- * intc-simr.c
- *
- * Interrupt controller code for the ColdFire 5208, 5207 & 532x parts.
- *
- * (C) Copyright 2009, Greg Ungerer <gerg@snapgear.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/types.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/io.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/traps.h>
-
-static void intc_irq_mask(unsigned int irq)
-{
-	if (irq >= MCFINT_VECBASE) {
-		if (irq < MCFINT_VECBASE + 64)
-			__raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_SIMR);
-		else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_SIMR)
-			__raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_SIMR);
-	}
-}
-
-static void intc_irq_unmask(unsigned int irq)
-{
-	if (irq >= MCFINT_VECBASE) {
-		if (irq < MCFINT_VECBASE + 64)
-			__raw_writeb(irq - MCFINT_VECBASE, MCFINTC0_CIMR);
-		else if ((irq < MCFINT_VECBASE + 128) && MCFINTC1_CIMR)
-			__raw_writeb(irq - MCFINT_VECBASE - 64, MCFINTC1_CIMR);
-	}
-}
-
-static int intc_irq_set_type(unsigned int irq, unsigned int type)
-{
-	if (irq >= MCFINT_VECBASE) {
-		if (irq < MCFINT_VECBASE + 64)
-			__raw_writeb(5, MCFINTC0_ICR0 + irq - MCFINT_VECBASE);
-		else if ((irq < MCFINT_VECBASE) && MCFINTC1_ICR0)
-			__raw_writeb(5, MCFINTC1_ICR0 + irq - MCFINT_VECBASE - 64);
-	}
-	return 0;
-}
-
-static struct irq_chip intc_irq_chip = {
-	.name		= "CF-INTC",
-	.mask		= intc_irq_mask,
-	.unmask		= intc_irq_unmask,
-	.set_type	= intc_irq_set_type,
-};
-
-void __init init_IRQ(void)
-{
-	int irq;
-
-	init_vectors();
-
-	/* Mask all interrupt sources */
-	__raw_writeb(0xff, MCFINTC0_SIMR);
-	if (MCFINTC1_SIMR)
-		__raw_writeb(0xff, MCFINTC1_SIMR);
-
-	for (irq = 0; (irq < NR_IRQS); irq++) {
-		set_irq_chip(irq, &intc_irq_chip);
-		set_irq_type(irq, IRQ_TYPE_LEVEL_HIGH);
-		set_irq_handler(irq, handle_level_irq);
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-#
-# Makefile for the m68knommu kernel.
-#
-
-#
-# If you want to play with the HW breakpoints then you will
-# need to add define this,  which will give you a stack backtrace
-# on the console port whenever a DBG interrupt occurs. You have to
-# set up you HW breakpoints to trigger a DBG interrupt:
-#
-# ccflags-y := -DTRAP_DBG_INTERRUPT
-# asflags-y := -DTRAP_DBG_INTERRUPT
-#
-
-asflags-$(CONFIG_FULLDEBUG) := -DDEBUGGER_COMPATIBLE_CACHE=1
-
-obj-$(CONFIG_COLDFIRE)	+= cache.o clk.o dma.o entry.o vectors.o
-obj-$(CONFIG_M5206)	+= timers.o intc.o
-obj-$(CONFIG_M5206e)	+= timers.o intc.o
-obj-$(CONFIG_M520x)	+= pit.o intc-simr.o
-obj-$(CONFIG_M523x)	+= pit.o dma_timer.o intc-2.o
-obj-$(CONFIG_M5249)	+= timers.o intc.o
-obj-$(CONFIG_M527x)	+= pit.o intc-2.o
-obj-$(CONFIG_M5272)	+= timers.o
-obj-$(CONFIG_M528x)	+= pit.o intc-2.o
-obj-$(CONFIG_M5307)	+= timers.o intc.o
-obj-$(CONFIG_M532x)	+= timers.o intc-simr.o
-obj-$(CONFIG_M5407)	+= timers.o intc.o
-obj-$(CONFIG_M54xx)	+= sltimers.o intc-2.o
-
-obj-y			+= pinmux.o gpio.o
-extra-y := head.o
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/pinmux.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/pinmux.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/pinmux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/pinmux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,28 +0,0 @@
-/*
- * Coldfire generic GPIO pinmux support.
- *
- * (C) Copyright 2009, Steven King <sfking@fdwdc.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.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY; 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 <asm/pinmux.h>
-
-int mcf_pinmux_request(unsigned pinmux, unsigned func)
-{
-	return 0;
-}
-
-void mcf_pinmux_release(unsigned pinmux, unsigned func)
-{
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/pit.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/pit.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/pit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/pit.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,169 +0,0 @@
-/***************************************************************************/
-
-/*
- *	pit.c -- Freescale ColdFire PIT timer. Currently this type of
- *	         hardware timer only exists in the Freescale ColdFire
- *		 5270/5271, 5282 and 5208 CPUs. No doubt newer ColdFire
- *		 family members will probably use it too.
- *
- *	Copyright (C) 1999-2008, Greg Ungerer (gerg@snapgear.com)
- *	Copyright (C) 2001-2004, SnapGear Inc. (www.snapgear.com)
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/param.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/clockchips.h>
-#include <asm/machdep.h>
-#include <asm/io.h>
-#include <asm/coldfire.h>
-#include <asm/mcfpit.h>
-#include <asm/mcfsim.h>
-
-/***************************************************************************/
-
-/*
- *	By default use timer1 as the system clock timer.
- */
-#define	FREQ	((MCF_CLK / 2) / 64)
-#define	TA(a)	(MCF_IPSBAR + MCFPIT_BASE1 + (a))
-#define PIT_CYCLES_PER_JIFFY (FREQ / HZ)
-
-static u32 pit_cnt;
-
-/*
- * Initialize the PIT timer.
- *
- * This is also called after resume to bring the PIT into operation again.
- */
-
-static void init_cf_pit_timer(enum clock_event_mode mode,
-                             struct clock_event_device *evt)
-{
-	switch (mode) {
-	case CLOCK_EVT_MODE_PERIODIC:
-
-		__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
-		__raw_writew(PIT_CYCLES_PER_JIFFY, TA(MCFPIT_PMR));
-		__raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
-				MCFPIT_PCSR_OVW | MCFPIT_PCSR_RLD | \
-				MCFPIT_PCSR_CLK64, TA(MCFPIT_PCSR));
-		break;
-
-	case CLOCK_EVT_MODE_SHUTDOWN:
-	case CLOCK_EVT_MODE_UNUSED:
-
-		__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
-		break;
-
-	case CLOCK_EVT_MODE_ONESHOT:
-
-		__raw_writew(MCFPIT_PCSR_DISABLE, TA(MCFPIT_PCSR));
-		__raw_writew(MCFPIT_PCSR_EN | MCFPIT_PCSR_PIE | \
-				MCFPIT_PCSR_OVW | MCFPIT_PCSR_CLK64, \
-				TA(MCFPIT_PCSR));
-		break;
-
-	case CLOCK_EVT_MODE_RESUME:
-		/* Nothing to do here */
-		break;
-	}
-}
-
-/*
- * Program the next event in oneshot mode
- *
- * Delta is given in PIT ticks
- */
-static int cf_pit_next_event(unsigned long delta,
-		struct clock_event_device *evt)
-{
-	__raw_writew(delta, TA(MCFPIT_PMR));
-	return 0;
-}
-
-struct clock_event_device cf_pit_clockevent = {
-	.name		= "pit",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
-	.set_mode	= init_cf_pit_timer,
-	.set_next_event	= cf_pit_next_event,
-	.shift		= 32,
-	.irq		= MCFINT_VECBASE + MCFINT_PIT1,
-};
-
-
-
-/***************************************************************************/
-
-static irqreturn_t pit_tick(int irq, void *dummy)
-{
-	struct clock_event_device *evt = &cf_pit_clockevent;
-	u16 pcsr;
-
-	/* Reset the ColdFire timer */
-	pcsr = __raw_readw(TA(MCFPIT_PCSR));
-	__raw_writew(pcsr | MCFPIT_PCSR_PIF, TA(MCFPIT_PCSR));
-
-	pit_cnt += PIT_CYCLES_PER_JIFFY;
-	evt->event_handler(evt);
-	return IRQ_HANDLED;
-}
-
-/***************************************************************************/
-
-static struct irqaction pit_irq = {
-	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = pit_tick,
-};
-
-/***************************************************************************/
-
-static cycle_t pit_read_clk(struct clocksource *cs)
-{
-	unsigned long flags;
-	u32 cycles;
-	u16 pcntr;
-
-	local_irq_save(flags);
-	pcntr = __raw_readw(TA(MCFPIT_PCNTR));
-	cycles = pit_cnt;
-	local_irq_restore(flags);
-
-	return cycles + PIT_CYCLES_PER_JIFFY - pcntr;
-}
-
-/***************************************************************************/
-
-static struct clocksource pit_clk = {
-	.name	= "pit",
-	.rating	= 100,
-	.read	= pit_read_clk,
-	.shift	= 20,
-	.mask	= CLOCKSOURCE_MASK(32),
-};
-
-/***************************************************************************/
-
-void hw_timer_init(void)
-{
-	cf_pit_clockevent.cpumask = cpumask_of(smp_processor_id());
-	cf_pit_clockevent.mult = div_sc(FREQ, NSEC_PER_SEC, 32);
-	cf_pit_clockevent.max_delta_ns =
-		clockevent_delta2ns(0xFFFF, &cf_pit_clockevent);
-	cf_pit_clockevent.min_delta_ns =
-		clockevent_delta2ns(0x3f, &cf_pit_clockevent);
-	clockevents_register_device(&cf_pit_clockevent);
-
-	setup_irq(MCFINT_VECBASE + MCFINT_PIT1, &pit_irq);
-
-	pit_clk.mult = clocksource_hz2mult(FREQ, pit_clk.shift);
-	clocksource_register(&pit_clk);
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/sltimers.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/sltimers.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/sltimers.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/sltimers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,145 +0,0 @@
-/***************************************************************************/
-
-/*
- *	sltimers.c -- generic ColdFire slice timer support.
- *
- *	Copyright (C) 2009-2010, Philippe De Muyter <phdm@macqel.be>
- *	based on
- *	timers.c -- generic ColdFire hardware timer support.
- *	Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/profile.h>
-#include <linux/clocksource.h>
-#include <asm/io.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfslt.h>
-#include <asm/mcfsim.h>
-
-/***************************************************************************/
-
-#ifdef CONFIG_HIGHPROFILE
-
-/*
- *	By default use Slice Timer 1 as the profiler clock timer.
- */
-#define	PA(a)	(MCF_MBAR + MCFSLT_TIMER1 + (a))
-
-/*
- *	Choose a reasonably fast profile timer. Make it an odd value to
- *	try and get good coverage of kernel operations.
- */
-#define	PROFILEHZ	1013
-
-irqreturn_t mcfslt_profile_tick(int irq, void *dummy)
-{
-	/* Reset Slice Timer 1 */
-	__raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, PA(MCFSLT_SSR));
-	if (current->pid)
-		profile_tick(CPU_PROFILING);
-	return IRQ_HANDLED;
-}
-
-static struct irqaction mcfslt_profile_irq = {
-	.name	 = "profile timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = mcfslt_profile_tick,
-};
-
-void mcfslt_profile_init(void)
-{
-	printk(KERN_INFO "PROFILE: lodging TIMER 1 @ %dHz as profile timer\n",
-	       PROFILEHZ);
-
-	setup_irq(MCF_IRQ_PROFILER, &mcfslt_profile_irq);
-
-	/* Set up TIMER 2 as high speed profile clock */
-	__raw_writel(MCF_BUSCLK / PROFILEHZ - 1, PA(MCFSLT_STCNT));
-	__raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
-								PA(MCFSLT_SCR));
-
-}
-
-#endif	/* CONFIG_HIGHPROFILE */
-
-/***************************************************************************/
-
-/*
- *	By default use Slice Timer 0 as the system clock timer.
- */
-#define	TA(a)	(MCF_MBAR + MCFSLT_TIMER0 + (a))
-
-static u32 mcfslt_cycles_per_jiffy;
-static u32 mcfslt_cnt;
-
-static irqreturn_t mcfslt_tick(int irq, void *dummy)
-{
-	/* Reset Slice Timer 0 */
-	__raw_writel(MCFSLT_SSR_BE | MCFSLT_SSR_TE, TA(MCFSLT_SSR));
-	mcfslt_cnt += mcfslt_cycles_per_jiffy;
-	return arch_timer_interrupt(irq, dummy);
-}
-
-static struct irqaction mcfslt_timer_irq = {
-	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = mcfslt_tick,
-};
-
-static cycle_t mcfslt_read_clk(struct clocksource *cs)
-{
-	unsigned long flags;
-	u32 cycles;
-	u16 scnt;
-
-	local_irq_save(flags);
-	scnt = __raw_readl(TA(MCFSLT_SCNT));
-	cycles = mcfslt_cnt;
-	local_irq_restore(flags);
-
-	/* substract because slice timers count down */
-	return cycles - scnt;
-}
-
-static struct clocksource mcfslt_clk = {
-	.name	= "slt",
-	.rating	= 250,
-	.read	= mcfslt_read_clk,
-	.shift	= 20,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-void hw_timer_init(void)
-{
-	mcfslt_cycles_per_jiffy = MCF_BUSCLK / HZ;
-	/*
-	 *	The coldfire slice timer (SLT) runs from STCNT to 0 included,
-	 *	then STCNT again and so on.  It counts thus actually
-	 *	STCNT + 1 steps for 1 tick, not STCNT.  So if you want
-	 *	n cycles, initialize STCNT with n - 1.
-	 */
-	__raw_writel(mcfslt_cycles_per_jiffy - 1, TA(MCFSLT_STCNT));
-	__raw_writel(MCFSLT_SCR_RUN | MCFSLT_SCR_IEN | MCFSLT_SCR_TEN,
-								TA(MCFSLT_SCR));
-	/* initialize mcfslt_cnt knowing that slice timers count down */
-	mcfslt_cnt = mcfslt_cycles_per_jiffy;
-
-	setup_irq(MCF_IRQ_TIMER, &mcfslt_timer_irq);
-
-	mcfslt_clk.mult = clocksource_hz2mult(MCF_BUSCLK, mcfslt_clk.shift);
-	clocksource_register(&mcfslt_clk);
-
-#ifdef CONFIG_HIGHPROFILE
-	mcfslt_profile_init();
-#endif
-}
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/timers.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/timers.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/timers.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/timers.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,174 +0,0 @@
-/***************************************************************************/
-
-/*
- *	timers.c -- generic ColdFire hardware timer support.
- *
- *	Copyright (C) 1999-2008, Greg Ungerer <gerg@snapgear.com>
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-#include <linux/irq.h>
-#include <linux/profile.h>
-#include <linux/clocksource.h>
-#include <asm/io.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcftimer.h>
-#include <asm/mcfsim.h>
-
-/***************************************************************************/
-
-/*
- *	By default use timer1 as the system clock timer.
- */
-#define	FREQ	(MCF_BUSCLK / 16)
-#define	TA(a)	(MCF_MBAR + MCFTIMER_BASE1 + (a))
-
-/*
- *	These provide the underlying interrupt vector support.
- *	Unfortunately it is a little different on each ColdFire.
- */
-void coldfire_profile_init(void);
-
-#if defined(CONFIG_M532x)
-#define	__raw_readtrr	__raw_readl
-#define	__raw_writetrr	__raw_writel
-#else
-#define	__raw_readtrr	__raw_readw
-#define	__raw_writetrr	__raw_writew
-#endif
-
-static u32 mcftmr_cycles_per_jiffy;
-static u32 mcftmr_cnt;
-
-/***************************************************************************/
-
-static irqreturn_t mcftmr_tick(int irq, void *dummy)
-{
-	/* Reset the ColdFire timer */
-	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, TA(MCFTIMER_TER));
-
-	mcftmr_cnt += mcftmr_cycles_per_jiffy;
-	return arch_timer_interrupt(irq, dummy);
-}
-
-/***************************************************************************/
-
-static struct irqaction mcftmr_timer_irq = {
-	.name	 = "timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = mcftmr_tick,
-};
-
-/***************************************************************************/
-
-static cycle_t mcftmr_read_clk(struct clocksource *cs)
-{
-	unsigned long flags;
-	u32 cycles;
-	u16 tcn;
-
-	local_irq_save(flags);
-	tcn = __raw_readw(TA(MCFTIMER_TCN));
-	cycles = mcftmr_cnt;
-	local_irq_restore(flags);
-
-	return cycles + tcn;
-}
-
-/***************************************************************************/
-
-static struct clocksource mcftmr_clk = {
-	.name	= "tmr",
-	.rating	= 250,
-	.read	= mcftmr_read_clk,
-	.shift	= 20,
-	.mask	= CLOCKSOURCE_MASK(32),
-	.flags	= CLOCK_SOURCE_IS_CONTINUOUS,
-};
-
-/***************************************************************************/
-
-void hw_timer_init(void)
-{
-	__raw_writew(MCFTIMER_TMR_DISABLE, TA(MCFTIMER_TMR));
-	mcftmr_cycles_per_jiffy = FREQ / HZ;
-	/*
-	 *	The coldfire timer runs from 0 to TRR included, then 0
-	 *	again and so on.  It counts thus actually TRR + 1 steps
-	 *	for 1 tick, not TRR.  So if you want n cycles,
-	 *	initialize TRR with n - 1.
-	 */
-	__raw_writetrr(mcftmr_cycles_per_jiffy - 1, TA(MCFTIMER_TRR));
-	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, TA(MCFTIMER_TMR));
-
-	mcftmr_clk.mult = clocksource_hz2mult(FREQ, mcftmr_clk.shift);
-	clocksource_register(&mcftmr_clk);
-
-	setup_irq(MCF_IRQ_TIMER, &mcftmr_timer_irq);
-
-#ifdef CONFIG_HIGHPROFILE
-	coldfire_profile_init();
-#endif
-}
-
-/***************************************************************************/
-#ifdef CONFIG_HIGHPROFILE
-/***************************************************************************/
-
-/*
- *	By default use timer2 as the profiler clock timer.
- */
-#define	PA(a)	(MCF_MBAR + MCFTIMER_BASE2 + (a))
-
-/*
- *	Choose a reasonably fast profile timer. Make it an odd value to
- *	try and get good coverage of kernel operations.
- */
-#define	PROFILEHZ	1013
-
-/*
- *	Use the other timer to provide high accuracy profiling info.
- */
-irqreturn_t coldfire_profile_tick(int irq, void *dummy)
-{
-	/* Reset ColdFire timer2 */
-	__raw_writeb(MCFTIMER_TER_CAP | MCFTIMER_TER_REF, PA(MCFTIMER_TER));
-	if (current->pid)
-		profile_tick(CPU_PROFILING);
-	return IRQ_HANDLED;
-}
-
-/***************************************************************************/
-
-static struct irqaction coldfire_profile_irq = {
-	.name	 = "profile timer",
-	.flags	 = IRQF_DISABLED | IRQF_TIMER,
-	.handler = coldfire_profile_tick,
-};
-
-void coldfire_profile_init(void)
-{
-	printk(KERN_INFO "PROFILE: lodging TIMER2 @ %dHz as profile timer\n",
-	       PROFILEHZ);
-
-	/* Set up TIMER 2 as high speed profile clock */
-	__raw_writew(MCFTIMER_TMR_DISABLE, PA(MCFTIMER_TMR));
-
-	__raw_writetrr(((MCF_BUSCLK / 16) / PROFILEHZ), PA(MCFTIMER_TRR));
-	__raw_writew(MCFTIMER_TMR_ENORI | MCFTIMER_TMR_CLK16 |
-		MCFTIMER_TMR_RESTART | MCFTIMER_TMR_ENABLE, PA(MCFTIMER_TMR));
-
-	setup_irq(MCF_IRQ_PROFILER, &coldfire_profile_irq);
-}
-
-/***************************************************************************/
-#endif	/* CONFIG_HIGHPROFILE */
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/vectors.c linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/vectors.c
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/coldfire/vectors.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/coldfire/vectors.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-/***************************************************************************/
-
-/*
- *	linux/arch/m68knommu/platform/coldfire/vectors.c
- *
- *	Copyright (C) 1999-2007, Greg Ungerer <gerg@snapgear.com>
- */
-
-/***************************************************************************/
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/irq.h>
-#include <asm/traps.h>
-#include <asm/machdep.h>
-#include <asm/coldfire.h>
-#include <asm/mcfsim.h>
-#include <asm/mcfwdebug.h>
-
-/***************************************************************************/
-
-#ifdef TRAP_DBG_INTERRUPT
-
-asmlinkage void dbginterrupt_c(struct frame *fp)
-{
-	extern void dump(struct pt_regs *fp);
-	printk(KERN_DEBUG "%s(%d): BUS ERROR TRAP\n", __FILE__, __LINE__);
-	dump((struct pt_regs *) fp);
-	asm("halt");
-}
-
-#endif
-
-/***************************************************************************/
-
-extern e_vector	*_ramvec;
-
-void set_evector(int vecnum, void (*handler)(void))
-{
-	if (vecnum >= 0 && vecnum <= 255)
-		_ramvec[vecnum] = handler;
-}
-
-/***************************************************************************/
-
-/* Assembler routines */
-asmlinkage void buserr(void);
-asmlinkage void trap(void);
-asmlinkage void system_call(void);
-asmlinkage void inthandler(void);
-
-void __init init_vectors(void)
-{
-	int i;
-
-	/*
-	 *	There is a common trap handler and common interrupt
-	 *	handler that handle almost every vector. We treat
-	 *	the system call and bus error special, they get their
-	 *	own first level handlers.
-	 */
-	for (i = 3; (i <= 23); i++)
-		_ramvec[i] = trap;
-	for (i = 33; (i <= 63); i++)
-		_ramvec[i] = trap;
-	for (i = 24; (i <= 31); i++)
-		_ramvec[i] = inthandler;
-	for (i = 64; (i < 255); i++)
-		_ramvec[i] = inthandler;
-	_ramvec[255] = 0;
-
-	_ramvec[2] = buserr;
-	_ramvec[32] = system_call;
-
-#ifdef TRAP_DBG_INTERRUPT
-	_ramvec[12] = dbginterrupt;
-#endif
-}
-
-/***************************************************************************/
diff -druN linux-libre-2.6.38-gnu/arch/m68knommu/platform/Makefile linux-libre-2.6.39-gnu/arch/m68knommu/platform/Makefile
--- linux-libre-2.6.38-gnu/arch/m68knommu/platform/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/m68knommu/platform/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,3 +0,0 @@
-#
-# Makefile for the arch/m68knommu/platform.
-#
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -84,12 +84,13 @@
 #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)
 #define flush_cache_vmap(start, end)			do { } while (0)
 #define flush_cache_vunmap(start, end)			do { } while (0)
 #define flush_cache_mm(mm)			do { } while (0)
-#define flush_cache_page(vma, vmaddr, pfn)	do { } while (0)
+
+#define flush_cache_page(vma, vmaddr, pfn) \
+	flush_dcache_range(pfn << PAGE_SHIFT, (pfn << PAGE_SHIFT) + PAGE_SIZE);
 
 /* MS: kgdb code use this macro, wrong len with FLASH */
 #if 0
@@ -104,9 +105,13 @@
 #define copy_to_user_page(vma, page, vaddr, dst, src, len)		\
 do {									\
 	u32 addr = virt_to_phys(dst);					\
-	invalidate_icache_range((unsigned) (addr), (unsigned) (addr) + (len));\
 	memcpy((dst), (src), (len));					\
-	flush_dcache_range((unsigned) (addr), (unsigned) (addr) + (len));\
+	if (vma->vm_flags & VM_EXEC) {					\
+		invalidate_icache_range((unsigned) (addr),		\
+					(unsigned) (addr) + PAGE_SIZE);	\
+		flush_dcache_range((unsigned) (addr),			\
+					(unsigned) (addr) + PAGE_SIZE);	\
+	}								\
 } while (0)
 
 #define copy_from_user_page(vma, page, vaddr, dst, src, len)		\
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/cpuinfo.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/cpuinfo.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/cpuinfo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/cpuinfo.h	2011-05-19 00:06:34.000000000 -0400
@@ -96,8 +96,8 @@
 
 static inline unsigned int fcpu(struct device_node *cpu, char *n)
 {
-	int *val;
-	return (val = (int *) of_get_property(cpu, n, NULL)) ?
+	const __be32 *val;
+	return (val = of_get_property(cpu, n, NULL)) ?
 							be32_to_cpup(val) : 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/entry.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/entry.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/entry.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/entry.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,40 +31,4 @@
 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.38-gnu/arch/microblaze/include/asm/exceptions.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/exceptions.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/exceptions.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/exceptions.h	2011-05-19 00:06:34.000000000 -0400
@@ -66,6 +66,9 @@
 asmlinkage void full_exception(struct pt_regs *regs, unsigned int type,
 							int fsr, int addr);
 
+asmlinkage void sw_exception(struct pt_regs *regs);
+void bad_page_fault(struct pt_regs *regs, unsigned long address, int sig);
+
 void die(const char *str, struct pt_regs *fp, long err);
 void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr);
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/futex.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 })
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -39,7 +39,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -94,31 +94,34 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev, cmp;
+	int ret = 0, cmp;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	__asm__ __volatile__ ("1:	lwx	%0, %2, r0;		\
-					cmp	%1, %0, %3;		\
-					beqi	%1, 3f;			\
-				2:	swx	%4, %2, r0;		\
-					addic	%1, r0, 0;		\
-					bnei	%1, 1b;			\
+	__asm__ __volatile__ ("1:	lwx	%1, %3, r0;		\
+					cmp	%2, %1, %4;		\
+					beqi	%2, 3f;			\
+				2:	swx	%5, %3, r0;		\
+					addic	%2, r0, 0;		\
+					bnei	%2, 1b;			\
 				3:					\
 				.section .fixup,\"ax\";			\
 				4:	brid	3b;			\
-					addik	%0, r0, %5;		\
+					addik	%0, r0, %6;		\
 				.previous;				\
 				.section __ex_table,\"a\";		\
 				.word	1b,4b,2b,4b;			\
 				.previous;"				\
-		: "=&r" (prev), "=&r"(cmp)				\
+		: "+r" (ret), "=&r" (prev), "=&r"(cmp)	\
 		: "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT));
 
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/io.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/io.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -70,7 +70,7 @@
 
 /*
  * read (readb, readw, readl, readq) and write (writeb, writew,
- * writel, writeq) accessors are for PCI and thus littel endian.
+ * writel, writeq) accessors are for PCI and thus little endian.
  * Linux 2.4 for Microblaze had this wrong.
  */
 static inline unsigned char readb(const volatile void __iomem *addr)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/irq.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/irq.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,8 +12,6 @@
 #define NR_IRQS 32
 #include <asm-generic/irq.h>
 
-#include <linux/interrupt.h>
-
 /* This type is the placeholder for a hardware interrupt number. It has to
  * be big enough to enclose whatever representation is used by a given
  * platform.
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/pci-bridge.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/pci-bridge.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/pci-bridge.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/pci-bridge.h	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
 	 * Used for variants of PCI indirect handling and possible quirks:
 	 *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
 	 *  EXT_REG - provides access to PCI-e extended registers
-	 *  SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS
+	 *  SURPRESS_PRIMARY_BUS - we suppress the setting of PCI_PRIMARY_BUS
 	 *   on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
 	 *   to determine which bus number to match on when generating type0
 	 *   config cycles
@@ -104,11 +104,22 @@
 	int global_number;	/* PCI domain number */
 };
 
+#ifdef CONFIG_PCI
 static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 {
 	return bus->sysdata;
 }
 
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	struct pci_controller *host;
+
+	if (bus->self)
+		return pci_device_to_OF_node(bus->self);
+	host = pci_bus_to_host(bus);
+	return host ? host->dn : NULL;
+}
+
 static inline int isa_vaddr_is_ioport(void __iomem *address)
 {
 	/* No specific ISA handling on ppc32 at this stage, it
@@ -116,6 +127,7 @@
 	 */
 	return 0;
 }
+#endif /* CONFIG_PCI */
 
 /* These are used for config access before all the PCI probing
    has been done. */
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/pci.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/pci.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -158,7 +158,7 @@
 extern void pcibios_setup_bus_devices(struct pci_bus *bus);
 extern void pcibios_setup_bus_self(struct pci_bus *bus);
 
-/* This part of code was originaly in xilinx-pci.h */
+/* This part of code was originally in xilinx-pci.h */
 #ifdef CONFIG_PCI_XILINX
 extern void __init xilinx_pci_init(void);
 #else
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -572,7 +572,7 @@
 
 extern unsigned long ioremap_bot, ioremap_base;
 
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle);
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle);
 void consistent_free(size_t size, void *vaddr);
 void consistent_sync(void *vaddr, size_t size, int direction);
 void consistent_sync_page(struct page *page, unsigned long offset,
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/processor.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -155,7 +155,7 @@
 #  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)
+	((void *)task_pt_regs(tsk))
 
 #  define task_sp(task)	(task_regs(task)->r1)
 #  define task_pc(task)	(task_regs(task)->pc)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/prom.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/prom.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/prom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/prom.h	2011-05-19 00:06:34.000000000 -0400
@@ -64,21 +64,6 @@
 /* CPU OF node matching */
 struct device_node *of_get_cpu_node(int cpu, unsigned int *thread);
 
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev:	the device whose interrupt is to be resolved
- * @out_irq:	structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-struct pci_dev;
-struct of_irq;
-extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
-
 #endif /* __ASSEMBLY__ */
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -66,13 +66,13 @@
 #else /* __KERNEL__ */
 
 /* pt_regs offsets used by gdbserver etc in ptrace syscalls */
-#define PT_GPR(n)       ((n) * sizeof(microblaze_reg_t))
-#define PT_PC           (32 * sizeof(microblaze_reg_t))
-#define PT_MSR          (33 * sizeof(microblaze_reg_t))
-#define PT_EAR          (34 * sizeof(microblaze_reg_t))
-#define PT_ESR          (35 * sizeof(microblaze_reg_t))
-#define PT_FSR          (36 * sizeof(microblaze_reg_t))
-#define PT_KERNEL_MODE  (37 * sizeof(microblaze_reg_t))
+#define PT_GPR(n)	((n) * sizeof(microblaze_reg_t))
+#define PT_PC		(32 * sizeof(microblaze_reg_t))
+#define PT_MSR		(33 * sizeof(microblaze_reg_t))
+#define PT_EAR		(34 * sizeof(microblaze_reg_t))
+#define PT_ESR		(35 * sizeof(microblaze_reg_t))
+#define PT_FSR		(36 * sizeof(microblaze_reg_t))
+#define PT_KERNEL_MODE	(37 * sizeof(microblaze_reg_t))
 
 #endif /* __KERNEL */
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/syscall.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/syscall.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/syscall.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/syscall.h	2011-05-19 00:06:34.000000000 -0400
@@ -96,4 +96,7 @@
 		microblaze_set_syscall_arg(regs, i++, *args++);
 }
 
+asmlinkage long do_syscall_trace_enter(struct pt_regs *regs);
+asmlinkage void do_syscall_trace_leave(struct pt_regs *regs);
+
 #endif /* __ASM_MICROBLAZE_SYSCALL_H */
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/syscalls.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/syscalls.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/syscalls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/syscalls.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,13 @@
 #ifndef __ASM_MICROBLAZE_SYSCALLS_H
 
+asmlinkage long microblaze_vfork(struct pt_regs *regs);
+asmlinkage long microblaze_clone(int flags, unsigned long stack,
+							struct pt_regs *regs);
+asmlinkage long microblaze_execve(const char __user *filenamei,
+				  const char __user *const __user *argv,
+				  const char __user *const __user *envp,
+				  struct pt_regs *regs);
+
 asmlinkage long sys_clone(int flags, unsigned long stack, struct pt_regs *regs);
 #define sys_clone sys_clone
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/uaccess.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/uaccess.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/uaccess.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/uaccess.h	2011-05-19 00:06:34.000000000 -0400
@@ -120,16 +120,16 @@
 {
 	/* normal memset with two words to __ex_table */
 	__asm__ __volatile__ (				\
-			"1:	sb	r0, %2, r0;"	\
+			"1:	sb	r0, %1, r0;"	\
 			"	addik	%0, %0, -1;"	\
 			"	bneid	%0, 1b;"	\
-			"	addik	%2, %2, 1;"	\
+			"	addik	%1, %1, 1;"	\
 			"2:			"	\
 			__EX_TABLE_SECTION		\
 			".word	1b,2b;"			\
 			".previous;"			\
-		: "=r"(n)				\
-		: "0"(n), "r"(to)
+		: "=r"(n), "=r"(to)			\
+		: "0"(n), "1"(to)
 	);
 	return n;
 }
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/unaligned.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/unaligned.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/unaligned.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/unaligned.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,18 +12,19 @@
 
 # ifdef __KERNEL__
 
-# include <linux/unaligned/be_byteshift.h>
-# include <linux/unaligned/le_byteshift.h>
-# include <linux/unaligned/generic.h>
-
-
 #  ifdef __MICROBLAZEEL__
+#   include <linux/unaligned/le_struct.h>
+#   include <linux/unaligned/be_byteshift.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>
 #   define get_unaligned	__get_unaligned_be
 #   define put_unaligned	__put_unaligned_be
 #  endif
 
+# include <linux/unaligned/generic.h>
+
 # endif	/* __KERNEL__ */
 #endif /* _ASM_MICROBLAZE_UNALIGNED_H */
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/microblaze/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/microblaze/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -386,8 +386,12 @@
 #define __NR_fanotify_init	368
 #define __NR_fanotify_mark	369
 #define __NR_prlimit64		370
+#define __NR_name_to_handle_at	371
+#define __NR_open_by_handle_at	372
+#define __NR_clock_adjtime	373
+#define __NR_syncfs		374
 
-#define __NR_syscalls		371
+#define __NR_syscalls		375
 
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/Kconfig linux-libre-2.6.39-gnu/arch/microblaze/Kconfig
--- linux-libre-2.6.38-gnu/arch/microblaze/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,6 @@
 	select HAVE_FUNCTION_GRAPH_TRACER
 	select HAVE_DYNAMIC_FTRACE
 	select HAVE_FTRACE_MCOUNT_RECORD
-	select USB_ARCH_HAS_EHCI
 	select ARCH_WANT_OPTIONAL_GPIOLIB
 	select HAVE_OPROFILE
 	select HAVE_ARCH_KGDB
@@ -17,6 +16,7 @@
 	select OF_EARLY_FLATTREE
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
 
 config SWAP
 	def_bool n
@@ -36,6 +36,9 @@
 config GENERIC_FIND_NEXT_BIT
 	def_bool y
 
+config GENERIC_FIND_BIT_LE
+	def_bool y
+
 config GENERIC_HWEIGHT
 	def_bool y
 
@@ -183,6 +186,17 @@
 	hex "Maximum low memory size (in bytes)" if LOWMEM_SIZE_BOOL
 	default "0x30000000"
 
+config MANUAL_RESET_VECTOR
+	hex "Microblaze reset vector address setup"
+	default "0x0"
+	help
+	  Set this option to have the kernel override the CPU Reset vector.
+	  If zero, no change will be made to the MicroBlaze reset vector at
+	  address 0x0.
+	  If non-zero, a jump instruction to this address, will be written
+	  to the reset vector at address 0x0.
+	  If you are unsure, set it to default value 0x0.
+
 config KERNEL_START_BOOL
 	bool "Set custom kernel base address"
 	depends on ADVANCED_OPTIONS
@@ -247,7 +261,7 @@
 
 source "mm/Kconfig"
 
-menu "Exectuable file formats"
+menu "Executable file formats"
 
 source "fs/Kconfig.binfmt"
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/cpu/cache.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/cpu/cache.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/cpu/cache.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/cpu/cache.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,7 +129,7 @@
  * to use for simple wdc or wic.
  *
  * start address is cache aligned
- * end address is not aligned, if end is aligned then I have to substract
+ * end address is not aligned, if end is aligned then I have to subtract
  * cacheline length because I can't flush/invalidate the next cacheline.
  * If is not, I align it because I will flush/invalidate whole line.
  */
@@ -519,7 +519,7 @@
 struct scache *mbc;
 
 /* new wb cache model */
-const struct scache wb_msr = {
+static const struct scache wb_msr = {
 	.ie = __enable_icache_msr,
 	.id = __disable_icache_msr,
 	.ifl = __flush_icache_all_noirq,
@@ -535,7 +535,7 @@
 };
 
 /* There is only difference in ie, id, de, dd functions */
-const struct scache wb_nomsr = {
+static const struct scache wb_nomsr = {
 	.ie = __enable_icache_nomsr,
 	.id = __disable_icache_nomsr,
 	.ifl = __flush_icache_all_noirq,
@@ -551,7 +551,7 @@
 };
 
 /* Old wt cache model with disabling irq and turn off cache */
-const struct scache wt_msr = {
+static const struct scache wt_msr = {
 	.ie = __enable_icache_msr,
 	.id = __disable_icache_msr,
 	.ifl = __flush_icache_all_msr_irq,
@@ -566,7 +566,7 @@
 	.dinr = __invalidate_dcache_range_msr_irq_wt,
 };
 
-const struct scache wt_nomsr = {
+static const struct scache wt_nomsr = {
 	.ie = __enable_icache_nomsr,
 	.id = __disable_icache_nomsr,
 	.ifl = __flush_icache_all_nomsr_irq,
@@ -582,7 +582,7 @@
 };
 
 /* New wt cache model for newer Microblaze versions */
-const struct scache wt_msr_noirq = {
+static const struct scache wt_msr_noirq = {
 	.ie = __enable_icache_msr,
 	.id = __disable_icache_msr,
 	.ifl = __flush_icache_all_noirq,
@@ -597,7 +597,7 @@
 	.dinr = __invalidate_dcache_range_nomsr_wt,
 };
 
-const struct scache wt_nomsr_noirq = {
+static const struct scache wt_nomsr_noirq = {
 	.ie = __enable_icache_nomsr,
 	.id = __disable_icache_nomsr,
 	.ifl = __flush_icache_all_noirq,
@@ -624,7 +624,7 @@
 		if (cpuinfo.dcache_wb) {
 			INFO("wb_msr");
 			mbc = (struct scache *)&wb_msr;
-			if (cpuinfo.ver_code < CPUVER_7_20_D) {
+			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
 				/* MS: problem with signal handling - hw bug */
 				INFO("WB won't work properly");
 			}
@@ -641,7 +641,7 @@
 		if (cpuinfo.dcache_wb) {
 			INFO("wb_nomsr");
 			mbc = (struct scache *)&wb_nomsr;
-			if (cpuinfo.ver_code < CPUVER_7_20_D) {
+			if (cpuinfo.ver_code <= CPUVER_7_20_D) {
 				/* MS: problem with signal handling - hw bug */
 				INFO("WB won't work properly");
 			}
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/cpu/cpuinfo.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/cpu/cpuinfo.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/cpu/cpuinfo.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,7 @@
 	{"7.30.b", 0x11},
 	{"8.00.a", 0x12},
 	{"8.00.b", 0x13},
+	{"8.10.a", 0x14},
 	{NULL, 0},
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/cpu/Makefile linux-libre-2.6.39-gnu/arch/microblaze/kernel/cpu/Makefile
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/cpu/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/cpu/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 CFLAGS_REMOVE_cache.o = -pg
 endif
 
-EXTRA_CFLAGS += -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
+ccflags-y := -DCPU_MAJOR=$(CPU_MAJOR) -DCPU_MINOR=$(CPU_MINOR) \
 		-DCPU_REV=$(CPU_REV)
 
 obj-y += cache.o cpuinfo.o cpuinfo-pvr-full.o cpuinfo-static.o mb.o pvr.o
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/dma.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/dma.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 {
 	switch (direction) {
 	case DMA_TO_DEVICE:
+	case DMA_BIDIRECTIONAL:
 		flush_dcache_range(paddr + offset, paddr + offset + size);
 		break;
 	case DMA_FROM_DEVICE:
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/entry-nommu.S linux-libre-2.6.39-gnu/arch/microblaze/kernel/entry-nommu.S
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/entry-nommu.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/entry-nommu.S	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,7 @@
 	/* restore r31 */
 	lwi	r31, r0, PER_CPU(CURRENT_SAVE)
 	/* prepare the link register, the argument and jump */
-	la	r15, r0, ret_from_intr - 8
+	addik	r15, r0, ret_from_intr - 8
 	addk	r6, r0, r15
 	braid	do_IRQ
 	add	r5, r0, r1
@@ -283,7 +283,7 @@
 	add	r12, r12, r12			/* convert num -> ptr */
 	add	r12, r12, r12
 	lwi	r12, r12, sys_call_table	/* Get function pointer */
-	la	r15, r0, ret_to_user-8		/* set return address */
+	addik	r15, r0, ret_to_user-8		/* set return address */
 	bra	r12				/* Make the system call. */
 	bri	0				/* won't reach here */
 1:
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/entry.S linux-libre-2.6.39-gnu/arch/microblaze/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -33,11 +33,14 @@
 
 #undef DEBUG
 
-/* 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 */
+#ifdef DEBUG
+/* Create space for syscalls counting. */
+.section .data
+.global syscall_debug_table
+.align 4
+syscall_debug_table:
+	.space	(__NR_syscalls * 4)
+#endif /* DEBUG */
 
 #define C_ENTRY(name)	.globl name; .align 4; name
 
@@ -172,72 +175,72 @@
 1:
 
 #define SAVE_REGS \
-	swi	r2, r1, PTO+PT_R2;	/* Save SDA */			\
-	swi	r3, r1, PTO+PT_R3;					\
-	swi	r4, r1, PTO+PT_R4;					\
-	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	r16, r1, PTO+PT_R16;					\
-	swi	r17, r1, PTO+PT_R17;					\
-	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 */	\
+	swi	r2, r1, PT_R2;	/* Save SDA */			\
+	swi	r3, r1, PT_R3;					\
+	swi	r4, r1, PT_R4;					\
+	swi	r5, r1, PT_R5;					\
+	swi	r6, r1, PT_R6;					\
+	swi	r7, r1, PT_R7;					\
+	swi	r8, r1, PT_R8;					\
+	swi	r9, r1, PT_R9;					\
+	swi	r10, r1, PT_R10;					\
+	swi	r11, r1, PT_R11;	/* save clobbered regs after rval */\
+	swi	r12, r1, PT_R12;					\
+	swi	r13, r1, PT_R13;	/* Save SDA2 */			\
+	swi	r14, r1, PT_PC;	/* PC, before IRQ/trap */	\
+	swi	r15, r1, PT_R15;	/* Save LP */			\
+	swi	r16, r1, PT_R16;					\
+	swi	r17, r1, PT_R17;					\
+	swi	r18, r1, PT_R18;	/* Save asm scratch reg */	\
+	swi	r19, r1, PT_R19;					\
+	swi	r20, r1, PT_R20;					\
+	swi	r21, r1, PT_R21;					\
+	swi	r22, r1, PT_R22;					\
+	swi	r23, r1, PT_R23;					\
+	swi	r24, r1, PT_R24;					\
+	swi	r25, r1, PT_R25;					\
+	swi	r26, r1, PT_R26;					\
+	swi	r27, r1, PT_R27;					\
+	swi	r28, r1, PT_R28;					\
+	swi	r29, r1, PT_R29;					\
+	swi	r30, r1, PT_R30;					\
+	swi	r31, r1, PT_R31;	/* Save current task reg */	\
 	mfs	r11, rmsr;		/* save MSR */			\
-	swi	r11, r1, PTO+PT_MSR;
+	swi	r11, r1, PT_MSR;
 
 #define RESTORE_REGS \
-	lwi	r11, r1, PTO+PT_MSR;					\
+	lwi	r11, r1, PT_MSR;					\
 	mts	rmsr , r11;						\
-	lwi	r2, r1, PTO+PT_R2;	/* restore SDA */		\
-	lwi	r3, r1, PTO+PT_R3;					\
-	lwi	r4, r1, PTO+PT_R4;					\
-	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	r16, r1, PTO+PT_R16;					\
-	lwi	r17, r1, PTO+PT_R17;					\
-	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 */
+	lwi	r2, r1, PT_R2;	/* restore SDA */		\
+	lwi	r3, r1, PT_R3;					\
+	lwi	r4, r1, PT_R4;					\
+	lwi	r5, r1, PT_R5;					\
+	lwi	r6, r1, PT_R6;					\
+	lwi	r7, r1, PT_R7;					\
+	lwi	r8, r1, PT_R8;					\
+	lwi	r9, r1, PT_R9;					\
+	lwi	r10, r1, PT_R10;					\
+	lwi	r11, r1, PT_R11;	/* restore clobbered regs after rval */\
+	lwi	r12, r1, PT_R12;					\
+	lwi	r13, r1, PT_R13;	/* restore SDA2 */		\
+	lwi	r14, r1, PT_PC;	/* RESTORE_LINK PC, before IRQ/trap */\
+	lwi	r15, r1, PT_R15;	/* restore LP */		\
+	lwi	r16, r1, PT_R16;					\
+	lwi	r17, r1, PT_R17;					\
+	lwi	r18, r1, PT_R18;	/* restore asm scratch reg */	\
+	lwi	r19, r1, PT_R19;					\
+	lwi	r20, r1, PT_R20;					\
+	lwi	r21, r1, PT_R21;					\
+	lwi	r22, r1, PT_R22;					\
+	lwi	r23, r1, PT_R23;					\
+	lwi	r24, r1, PT_R24;					\
+	lwi	r25, r1, PT_R25;					\
+	lwi	r26, r1, PT_R26;					\
+	lwi	r27, r1, PT_R27;					\
+	lwi	r28, r1, PT_R28;					\
+	lwi	r29, r1, PT_R29;					\
+	lwi	r30, r1, PT_R30;					\
+	lwi	r31, r1, PT_R31;	/* Restore cur task reg */
 
 #define SAVE_STATE	\
 	swi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* save stack */	\
@@ -250,11 +253,11 @@
 	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
 	/* FIXME: I can add these two lines to one */			\
 	/* tophys(r1,r1); */						\
-	/* addik	r1, r1, -STATE_SAVE_SIZE; */			\
-	addik	r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
+	/* addik	r1, r1, -PT_SIZE; */				\
+	addik	r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
 	SAVE_REGS							\
 	brid	2f;							\
-	swi	r1, r1, PTO+PT_MODE; 	 				\
+	swi	r1, r1, PT_MODE; 	 				\
 1:	/* User-mode state save.  */					\
 	lwi	r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */\
 	tophys(r1,r1);							\
@@ -262,12 +265,12 @@
 	/* MS these three instructions can be added to one */		\
 	/* addik	r1, r1, THREAD_SIZE; */				\
 	/* tophys(r1,r1); */						\
-	/* addik	r1, r1, -STATE_SAVE_SIZE; */			\
-	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE; \
+	/* addik	r1, r1, -PT_SIZE; */			\
+	addik r1, r1, THREAD_SIZE + CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE; \
 	SAVE_REGS							\
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));			\
-	swi	r11, r1, PTO+PT_R1; /* Store user SP.  */		\
-	swi	r0, r1, PTO + PT_MODE; /* Was in user-mode.  */		\
+	swi	r11, r1, PT_R1; /* Store user SP.  */		\
+	swi	r0, r1, PT_MODE; /* Was in user-mode.  */		\
 	/* MS: I am clearing UMS even in case when I come from kernel space */ \
 	clear_ums; 							\
 2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
@@ -299,10 +302,10 @@
 	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
 	tophys(r1,r1);
 
-	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack. */
+	addik	r1, r1, -PT_SIZE; /* Make room on the stack. */
 	SAVE_REGS
 
-	swi	r1, r1, PTO + PT_MODE; /* pt_regs -> kernel mode */
+	swi	r1, r1, PT_MODE; /* pt_regs -> kernel mode */
 	brid	2f;
 	nop;				/* Fill delay slot */
 
@@ -315,18 +318,18 @@
 	addik	r1, r1, THREAD_SIZE;
 	tophys(r1,r1);
 
-	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	addik	r1, r1, -PT_SIZE; /* Make room on the stack.  */
 	SAVE_REGS
-	swi	r0, r1, PTO + PT_R3
-	swi	r0, r1, PTO + PT_R4
+	swi	r0, r1, PT_R3
+	swi	r0, r1, PT_R4
 
-	swi	r0, r1, PTO + PT_MODE;			/* Was in user-mode. */
+	swi	r0, r1, PT_MODE;			/* Was in user-mode. */
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
-	swi	r11, r1, PTO+PT_R1;		/* Store user SP.  */
+	swi	r11, r1, PT_R1;		/* Store user SP.  */
 	clear_ums;
 2:	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	/* Save away the syscall number.  */
-	swi	r12, r1, PTO+PT_R0;
+	swi	r12, r1, PT_R0;
 	tovirt(r1,r1)
 
 /* where the trap should return need -8 to adjust for rtsd r15, 8*/
@@ -345,18 +348,18 @@
 	beqi	r11, 4f
 
 	addik	r3, r0, -ENOSYS
-	swi	r3, r1, PTO + PT_R3
+	swi	r3, r1, PT_R3
 	brlid	r15, do_syscall_trace_enter
-	addik	r5, r1, PTO + PT_R0
+	addik	r5, r1, PT_R0
 
 	# do_syscall_trace_enter returns the new syscall nr.
 	addk	r12, r0, r3
-	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	r5, r1, PT_R5;
+	lwi	r6, r1, PT_R6;
+	lwi	r7, r1, PT_R7;
+	lwi	r8, r1, PT_R8;
+	lwi	r9, r1, PT_R9;
+	lwi	r10, r1, PT_R10;
 4:
 /* 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.
@@ -371,10 +374,14 @@
 	add	r12, r12, r12;
 
 #ifdef DEBUG
-	/* Trac syscalls and stored them to r0_ram */
-	lwi	r3, r12, 0x400 + r0_ram
+	/* Trac syscalls and stored them to syscall_debug_table */
+	/* The first syscall location stores total syscall number */
+	lwi	r3, r0, syscall_debug_table
 	addi	r3, r3, 1
-	swi	r3, r12, 0x400 + r0_ram
+	swi	r3, r0, syscall_debug_table
+	lwi	r3, r12, syscall_debug_table
+	addi	r3, r3, 1
+	swi	r3, r12, syscall_debug_table
 #endif
 
 	# Find and jump into the syscall handler.
@@ -391,10 +398,10 @@
 /* Entry point used to return from a syscall/trap */
 /* We re-enable BIP bit before state restore */
 C_ENTRY(ret_from_trap):
-	swi	r3, r1, PTO + PT_R3
-	swi	r4, r1, PTO + PT_R4
+	swi	r3, r1, PT_R3
+	swi	r4, r1, PT_R4
 
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, 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
@@ -406,7 +413,7 @@
 	beqi	r11, 1f
 
 	brlid	r15, do_syscall_trace_leave
-	addik	r5, r1, PTO + PT_R0
+	addik	r5, r1, PT_R0
 1:
 	/* We're returning to user mode, so check for various conditions that
 	 * trigger rescheduling. */
@@ -426,7 +433,7 @@
 	andi	r11, r11, _TIF_SIGPENDING;
 	beqi	r11, 1f;		/* Signals to handle, handle them */
 
-	addik	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	addi	r7, r0, 1;		/* Arg 3: int in_syscall */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
@@ -437,7 +444,7 @@
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 	lwi	r1, r1, PT_R1 - PT_SIZE;/* Restore user stack pointer. */
 	bri	6f;
 
@@ -446,7 +453,7 @@
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 	tovirt(r1,r1);
 6:
 TRAP_return:		/* Make global symbol for debugging */
@@ -459,8 +466,8 @@
 
 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) */
-	addik	r7, r1, PTO			/* Arg 2: parent context */
+	lwi	r6, r1, PT_R1	/* Arg 1: child SP (use parent's) */
+	addik	r7, r1, 0			/* Arg 2: parent context */
 	add	r8. r0, r0			/* Arg 3: (unused) */
 	add	r9, r0, r0;			/* Arg 4: (unused) */
 	brid	do_fork		/* Do real work (tail-call) */
@@ -480,12 +487,12 @@
 
 C_ENTRY(sys_vfork):
 	brid	microblaze_vfork	/* Do real work (tail-call) */
-	addik	r5, r1, PTO
+	addik	r5, r1, 0
 
 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:	addik	r7, r1, PTO;			/* Arg 2: parent context */
+	lwi	r6, r1, PT_R1;	/* If so, use paret's stack ptr */
+1:	addik	r7, r1, 0;			/* Arg 2: parent context */
 	add	r8, r0, r0;			/* Arg 3: (unused) */
 	add	r9, r0, r0;			/* Arg 4: (unused) */
 	brid	do_fork		/* Do real work (tail-call) */
@@ -493,11 +500,11 @@
 
 C_ENTRY(sys_execve):
 	brid	microblaze_execve;	/* Do real work (tail-call).*/
-	addik	r8, r1, PTO;		/* add user context as 4th arg */
+	addik	r8, r1, 0;		/* add user context as 4th arg */
 
 C_ENTRY(sys_rt_sigreturn_wrapper):
 	brid	sys_rt_sigreturn	/* Do real work */
-	addik	r5, r1, PTO;		/* add user context as 1st arg */
+	addik	r5, r1, 0;		/* add user context as 1st arg */
 
 /*
  * HW EXCEPTION rutine start
@@ -508,7 +515,7 @@
 	addik	r17, r17, -4
 	SAVE_STATE /* Save registers */
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* FIXME this can be store directly in PT_ESR reg.
 	 * I tested it but there is a fault */
@@ -518,7 +525,7 @@
 	mfs	r7, rfsr;		/* save FSR */
 	mts	rfsr, r0;	/* Clear sticky fsr */
 	rted	r0, full_exception
-	addik	r5, r1, PTO		 /* parameter struct pt_regs * regs */
+	addik	r5, r1, 0		 /* parameter struct pt_regs * regs */
 
 /*
  * Unaligned data trap.
@@ -544,14 +551,14 @@
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
 	addik	r15, r0, ret_from_exc-8
 	mfs	r3, resr		/* ESR */
 	mfs	r4, rear		/* EAR */
 	rtbd	r0, _unaligned_data_exception
-	addik	r7, r1, PTO		/* parameter struct pt_regs * regs */
+	addik	r7, r1, 0		/* parameter struct pt_regs * regs */
 
 /*
  * Page fault traps.
@@ -574,30 +581,30 @@
 C_ENTRY(page_fault_data_trap):
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
 	addik	r15, r0, ret_from_exc-8
 	mfs	r6, rear		/* parameter unsigned long address */
 	mfs	r7, resr		/* parameter unsigned long error_code */
 	rted	r0, do_page_fault
-	addik	r5, r1, PTO		/* parameter struct pt_regs * regs */
+	addik	r5, r1, 0		/* parameter struct pt_regs * regs */
 
 C_ENTRY(page_fault_instr_trap):
 	SAVE_STATE		/* Save registers.*/
 	/* PC, before IRQ/trap - this is one instruction above */
-	swi	r17, r1, PTO+PT_PC;
+	swi	r17, r1, PT_PC;
 	tovirt(r1,r1)
 	/* where the trap should return need -8 to adjust for rtsd r15, 8 */
 	addik	r15, r0, ret_from_exc-8
 	mfs	r6, rear		/* parameter unsigned long address */
 	ori	r7, r0, 0		/* parameter unsigned long error_code */
 	rted	r0, do_page_fault
-	addik	r5, r1, PTO		/* parameter struct pt_regs * regs */
+	addik	r5, r1, 0		/* parameter struct pt_regs * regs */
 
 /* Entry point used to return from an exception.  */
 C_ENTRY(ret_from_exc):
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 	bnei	r11, 2f;		/* See if returning to kernel mode, */
 					/* ... if so, skip resched &c.  */
 
@@ -629,7 +636,7 @@
 	 * 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. */
-	addik	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	addi	r7, r0, 0;		/* Arg 3: int in_syscall */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
@@ -641,7 +648,7 @@
 	tophys(r1,r1);
 
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 
 	lwi	r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer. */
 	bri	6f;
@@ -650,7 +657,7 @@
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS;
-	addik	r1, r1, STATE_SAVE_SIZE		/* Clean up stack space.  */
+	addik	r1, r1, PT_SIZE		/* Clean up stack space.  */
 
 	tovirt(r1,r1);
 6:
@@ -683,10 +690,10 @@
 	tophys(r1,r1); /* MS: I have in r1 physical address where stack is */
 	/* save registers */
 /* MS: Make room on the stack -> activation record */
-	addik	r1, r1, -STATE_SAVE_SIZE;
+	addik	r1, r1, -PT_SIZE;
 	SAVE_REGS
 	brid	2f;
-	swi	r1, r1, PTO + PT_MODE; /* 0 - user mode, 1 - kernel mode */
+	swi	r1, r1, PT_MODE; /* 0 - user mode, 1 - kernel mode */
 1:
 /* User-mode state save. */
  /* MS: get the saved current */
@@ -696,23 +703,23 @@
 	addik	r1, r1, THREAD_SIZE;
 	tophys(r1,r1);
 	/* save registers */
-	addik	r1, r1, -STATE_SAVE_SIZE;
+	addik	r1, r1, -PT_SIZE;
 	SAVE_REGS
 	/* calculate mode */
-	swi	r0, r1, PTO + PT_MODE;
+	swi	r0, r1, PT_MODE;
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
-	swi	r11, r1, PTO+PT_R1;
+	swi	r11, r1, PT_R1;
 	clear_ums;
 2:
 	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	tovirt(r1,r1)
 	addik	r15, r0, irq_call;
 irq_call:rtbd	r0, do_IRQ;
-	addik	r5, r1, PTO;
+	addik	r5, r1, 0;
 
 /* MS: we are in virtual mode */
 ret_from_irq:
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 	bnei	r11, 2f;
 
 	lwi	r11, CURRENT_TASK, TS_THREAD_INFO;
@@ -729,7 +736,7 @@
 	beqid	r11, no_intr_resched
 /* Handle a signal return; Pending signals should be in r18. */
 	addi	r7, r0, 0; /* Arg 3: int in_syscall */
-	addik	r5, r1, PTO; /* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0; /* Arg 1: struct pt_regs *regs */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0; /* Arg 2: sigset_t *oldset */
 
@@ -741,7 +748,7 @@
 	VM_OFF;
 	tophys(r1,r1);
 	RESTORE_REGS
-	addik	r1, r1, STATE_SAVE_SIZE /* MS: Clean up stack space. */
+	addik	r1, r1, PT_SIZE /* MS: Clean up stack space. */
 	lwi	r1, r1, PT_R1 - PT_SIZE;
 	bri	6f;
 /* MS: Return to kernel state. */
@@ -769,7 +776,7 @@
 	VM_OFF /* MS: turn off MMU */
 	tophys(r1,r1)
 	RESTORE_REGS
-	addik	r1, r1, STATE_SAVE_SIZE	/* MS: Clean up stack space. */
+	addik	r1, r1, PT_SIZE	/* MS: Clean up stack space. */
 	tovirt(r1,r1);
 6:
 IRQ_return: /* MS: Make global symbol for debugging */
@@ -792,29 +799,29 @@
 	lwi	r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/
 
 	/* BIP bit is set on entry, no interrupts can occur */
-	addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - STATE_SAVE_SIZE;
+	addik   r1, r1, CONFIG_KERNEL_BASE_ADDR - CONFIG_KERNEL_START - PT_SIZE;
 	SAVE_REGS;
 	/* save all regs to pt_reg structure */
-	swi	r0, r1, PTO+PT_R0;	/* R0 must be saved too */
-	swi	r14, r1, PTO+PT_R14	/* rewrite saved R14 value */
-	swi	r16, r1, PTO+PT_PC; /* PC and r16 are the same */
+	swi	r0, r1, PT_R0;	/* R0 must be saved too */
+	swi	r14, r1, PT_R14	/* rewrite saved R14 value */
+	swi	r16, r1, PT_PC; /* PC and r16 are the same */
 	/* save special purpose registers to pt_regs */
 	mfs	r11, rear;
-	swi	r11, r1, PTO+PT_EAR;
+	swi	r11, r1, PT_EAR;
 	mfs	r11, resr;
-	swi	r11, r1, PTO+PT_ESR;
+	swi	r11, r1, PT_ESR;
 	mfs	r11, rfsr;
-	swi	r11, r1, PTO+PT_FSR;
+	swi	r11, r1, PT_FSR;
 
 	/* stack pointer is in physical address at it is decrease
-	 * by STATE_SAVE_SIZE but we need to get correct R1 value */
-	addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + STATE_SAVE_SIZE;
-	swi	r11, r1, PTO+PT_R1
+	 * by PT_SIZE but we need to get correct R1 value */
+	addik   r11, r1, CONFIG_KERNEL_START - CONFIG_KERNEL_BASE_ADDR + PT_SIZE;
+	swi	r11, r1, PT_R1
 	/* MS: r31 - current pointer isn't changed */
 	tovirt(r1,r1)
 #ifdef CONFIG_KGDB
-	addi	r5, r1, PTO /* pass pt_reg address as the first arg */
-	la	r15, r0, dbtrap_call; /* return address */
+	addi	r5, r1, 0 /* pass pt_reg address as the first arg */
+	addik	r15, r0, dbtrap_call; /* return address */
 	rtbd	r0, microblaze_kgdb_break
 	nop;
 #endif
@@ -829,16 +836,16 @@
 	addik	r1, r1, THREAD_SIZE;	/* calculate kernel stack pointer */
 	tophys(r1,r1);
 
-	addik	r1, r1, -STATE_SAVE_SIZE; /* Make room on the stack.  */
+	addik	r1, r1, -PT_SIZE; /* Make room on the stack.  */
 	SAVE_REGS;
-	swi	r16, r1, PTO+PT_PC;	/* Save LP */
-	swi	r0, r1, PTO + PT_MODE; /* Was in user-mode.  */
+	swi	r16, r1, PT_PC;	/* Save LP */
+	swi	r0, r1, PT_MODE; /* Was in user-mode.  */
 	lwi	r11, r0, TOPHYS(PER_CPU(ENTRY_SP));
-	swi	r11, r1, PTO+PT_R1; /* Store user SP.  */
+	swi	r11, r1, PT_R1; /* Store user SP.  */
 	lwi	CURRENT_TASK, r0, TOPHYS(PER_CPU(CURRENT_SAVE));
 	tovirt(r1,r1)
 	set_vms;
-	addik	r5, r1, PTO;
+	addik	r5, r1, 0;
 	addik	r15, r0, dbtrap_call;
 dbtrap_call: /* Return point for kernel/user entry + 8 because of rtsd r15, 8 */
 	rtbd	r0, sw_exception
@@ -846,7 +853,7 @@
 
 	/* MS: The first instruction for the second part of the gdb/kgdb */
 	set_bip; /* Ints masked for state restore */
-	lwi	r11, r1, PTO + PT_MODE;
+	lwi	r11, r1, PT_MODE;
 	bnei	r11, 2f;
 /* MS: Return to user space - gdb */
 	/* Get current task ptr into r11 */
@@ -865,7 +872,7 @@
 	andi	r11, r11, _TIF_SIGPENDING;
 	beqi	r11, 1f;		/* Signals to handle, handle them */
 
-	addik	r5, r1, PTO;		/* Arg 1: struct pt_regs *regs */
+	addik	r5, r1, 0;		/* Arg 1: struct pt_regs *regs */
 	addi  r7, r0, 0;	/* Arg 3: int in_syscall */
 	bralid	r15, do_signal;	/* Handle any signals */
 	add	r6, r0, r0;		/* Arg 2: sigset_t *oldset */
@@ -876,7 +883,7 @@
 	tophys(r1,r1);
 	/* MS: Restore all regs */
 	RESTORE_REGS
-	addik	r1, r1, STATE_SAVE_SIZE	 /* Clean up stack space */
+	addik	r1, r1, PT_SIZE	 /* Clean up stack space */
 	lwi	r1, r1, PT_R1 - PT_SIZE; /* Restore user stack pointer */
 DBTRAP_return_user: /* MS: Make global symbol for debugging */
 	rtbd	r16, 0; /* MS: Instructions to return from a debug trap */
@@ -887,9 +894,9 @@
 	tophys(r1,r1);
 	/* MS: Restore all regs */
 	RESTORE_REGS
-	lwi	r14, r1, PTO+PT_R14;
-	lwi	r16, r1, PTO+PT_PC;
-	addik	r1, r1, STATE_SAVE_SIZE; /* MS: Clean up stack space */
+	lwi	r14, r1, PT_R14;
+	lwi	r16, r1, PT_PC;
+	addik	r1, r1, PT_SIZE; /* MS: Clean up stack space */
 	tovirt(r1,r1);
 DBTRAP_return_kernel: /* MS: Make global symbol for debugging */
 	rtbd	r16, 0; /* MS: Instructions to return from a debug trap */
@@ -981,20 +988,22 @@
 	nop
 
 ENTRY(_reset)
-	brai	0x70; /* Jump back to FS-boot */
+	brai	0; /* Jump to reset vector */
 
 	/* These are compiled and loaded into high memory, then
 	 * copied into place in mach_early_setup */
 	.section	.init.ivt, "ax"
+#if CONFIG_MANUAL_RESET_VECTOR
 	.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	CONFIG_MANUAL_RESET_VECTOR
+#endif
+	.org	0x8
 	brai	TOPHYS(_user_exception); /* syscall handler */
+	.org	0x10
 	brai	TOPHYS(_interrupt);	/* Interrupt handler */
+	.org	0x18
 	brai	TOPHYS(_debug_exception);	/* debug trap handler */
+	.org	0x20
 	brai	TOPHYS(_hw_exception_handler);	/* HW exception handler */
 
 .section .rodata,"a"
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/exceptions.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/exceptions.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/exceptions.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/exceptions.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 }
 
 /* for user application debugging */
-void sw_exception(struct pt_regs *regs)
+asmlinkage void sw_exception(struct pt_regs *regs)
 {
 	_exception(SIGTRAP, regs, TRAP_BRKPT, regs->r16);
 	flush_dcache_range(regs->r16, regs->r16 + 0x4);
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/ftrace.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/ftrace.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/ftrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,9 @@
 			: "r" (parent), "r" (return_hooker)
 	);
 
+	flush_dcache_range((u32)parent, (u32)parent + 4);
+	flush_icache_range((u32)parent, (u32)parent + 4);
+
 	if (unlikely(faulted)) {
 		ftrace_graph_stop();
 		WARN_ON(1);
@@ -95,6 +98,9 @@
 	if (unlikely(faulted))
 		return -EFAULT;
 
+	flush_dcache_range(addr, addr + 4);
+	flush_icache_range(addr, addr + 4);
+
 	return 0;
 }
 
@@ -195,8 +201,6 @@
 	ret += ftrace_modify_code((unsigned long)&ftrace_caller,
 				  MICROBLAZE_NOP);
 
-	/* All changes are done - lets do caches consistent */
-	flush_icache();
 	return ret;
 }
 
@@ -210,7 +214,6 @@
 
 	old_jump = *(unsigned int *)ip; /* save jump over instruction */
 	ret = ftrace_modify_code(ip, MICROBLAZE_NOP);
-	flush_icache();
 
 	pr_debug("%s: Replace instruction: 0x%x\n", __func__, old_jump);
 	return ret;
@@ -222,7 +225,6 @@
 	unsigned long ip = (unsigned long)(&ftrace_call_graph);
 
 	ret = ftrace_modify_code(ip, old_jump);
-	flush_icache();
 
 	pr_debug("%s\n", __func__);
 	return ret;
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/head.S linux-libre-2.6.39-gnu/arch/microblaze/kernel/head.S
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 #include <asm/mmu.h>
 #include <asm/processor.h>
 
-.data
+.section .data
 .global empty_zero_page
 .align 12
 empty_zero_page:
@@ -50,6 +50,11 @@
 
 #endif /* CONFIG_MMU */
 
+.section .rodata
+.align 4
+endian_check:
+	.word	1
+
 	__HEAD
 ENTRY(_start)
 #if CONFIG_KERNEL_BASE_ADDR == 0
@@ -79,10 +84,7 @@
 /* Does r7 point to a valid FDT? Load HEADER magic number */
 	/* Run time Big/Little endian platform */
 	/* Save 1 as word and load byte - 0 - BIG, 1 - LITTLE */
-	addik	r11, r0, 0x1 /* BIG/LITTLE checking value */
-	/* __bss_start will be zeroed later - it is just temp location */
-	swi	r11, r0, TOPHYS(__bss_start)
-	lbui	r11, r0, TOPHYS(__bss_start)
+	lbui	r11, r0, TOPHYS(endian_check)
 	beqid	r11, big_endian /* DO NOT break delay stop dependency */
 	lw	r11, r0, r7 /* Big endian load in delay slot */
 	lwr	r11, r0, r7 /* Little endian load */
@@ -222,26 +224,26 @@
 #endif /* CONFIG_MMU */
 
 	/* Initialize small data anchors */
-	la	r13, r0, _KERNEL_SDA_BASE_
-	la	r2, r0, _KERNEL_SDA2_BASE_
+	addik	r13, r0, _KERNEL_SDA_BASE_
+	addik	r2, r0, _KERNEL_SDA2_BASE_
 
 	/* Initialize stack pointer */
-	la	r1, r0, init_thread_union + THREAD_SIZE - 4
+	addik	r1, r0, init_thread_union + THREAD_SIZE - 4
 
 	/* Initialize r31 with current task address */
-	la	r31, r0, init_task
+	addik	r31, r0, init_task
 
 	/*
 	 * Call platform dependent initialize function.
 	 * Please see $(ARCH)/mach-$(SUBARCH)/setup.c for
 	 * the function.
 	 */
-	la	r9, r0, machine_early_init
+	addik	r9, r0, machine_early_init
 	brald	r15, r9
 	nop
 
 #ifndef CONFIG_MMU
-	la	r15, r0, machine_halt
+	addik	r15, r0, machine_halt
 	braid	start_kernel
 	nop
 #else
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/hw_exception_handler.S linux-libre-2.6.39-gnu/arch/microblaze/kernel/hw_exception_handler.S
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/hw_exception_handler.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/hw_exception_handler.S	2011-05-19 00:06:34.000000000 -0400
@@ -77,6 +77,8 @@
 #include <asm/signal.h>
 #include <asm/asm-offsets.h>
 
+#undef DEBUG
+
 /* Helpful Macros */
 #define NUM_TO_REG(num)		r ## num
 
@@ -91,7 +93,7 @@
 		lwi	r6, r1, PT_R6;		\
 		lwi	r11, r1, PT_R11;	\
 		lwi	r31, r1, PT_R31;	\
-		lwi	r1, r0, TOPHYS(r0_ram + 0);
+		lwi	r1, r1, PT_R1;
 #endif /* CONFIG_MMU */
 
 #define LWREG_NOP			\
@@ -206,8 +208,8 @@
  *      |      .      |
  *      |      .      |
  *
- * NO_MMU kernel use the same r0_ram pointed space - look to vmlinux.lds.S
- * which is used for storing register values - old style was, that value were
+ * MMU kernel uses the same 'pt_pool_space' pointed space
+ * which is used for storing register values - noMMu style was, that values were
  * stored in stack but in case of failure you lost information about register.
  * Currently you can see register value in memory in specific place.
  * In compare to with previous solution the speed should be the same.
@@ -226,8 +228,22 @@
  */
 
 /* wrappers to restore state before coming to entry.S */
-
 #ifdef CONFIG_MMU
+.section .data
+.align 4
+pt_pool_space:
+	.space	PT_SIZE
+
+#ifdef DEBUG
+/* Create space for exception counting. */
+.section .data
+.global exception_debug_table
+.align 4
+exception_debug_table:
+	/* Look at exception vector table. There is 32 exceptions * word size */
+	.space	(32 * 4)
+#endif /* DEBUG */
+
 .section .rodata
 .align 4
 _MB_HW_ExceptionVectorTable:
@@ -287,10 +303,10 @@
 #ifndef CONFIG_MMU
 	addik	r1, r1, -(EX_HANDLER_STACK_SIZ); /* Create stack frame */
 #else
-	swi	r1, r0, TOPHYS(r0_ram + 0); /* GET_SP */
+	swi	r1, r0, TOPHYS(pt_pool_space + PT_R1); /* GET_SP */
 	/* Save date to kernel memory. Here is the problem
 	 * when you came from user space */
-	ori	r1, r0, TOPHYS(r0_ram + 28);
+	ori	r1, r0, TOPHYS(pt_pool_space);
 #endif
 	swi	r3, r1, PT_R3
 	swi	r4, r1, PT_R4
@@ -329,12 +345,12 @@
 
 #ifdef DEBUG
 /* counting which exception happen */
-	lwi	r5, r0, 0x200 + TOPHYS(r0_ram)
+	lwi	r5, r0, TOPHYS(exception_debug_table)
 	addi	r5, r5, 1
-	swi	r5, r0, 0x200 + TOPHYS(r0_ram)
-	lwi	r5, r6, 0x200 + TOPHYS(r0_ram)
+	swi	r5, r0, TOPHYS(exception_debug_table)
+	lwi	r5, r6, TOPHYS(exception_debug_table)
 	addi	r5, r5, 1
-	swi	r5, r6, 0x200 + TOPHYS(r0_ram)
+	swi	r5, r6, TOPHYS(exception_debug_table)
 #endif
 /* end */
 	/* Load the HW Exception vector */
@@ -474,7 +490,7 @@
 	/* Get the destination register number into r5 */
 	lbui	r5, r0, TOPHYS(ex_reg_op);
 	/* Form load_word jump table offset (lw_table + (8 * regnum)) */
-	la	r6, r0, TOPHYS(lw_table);
+	addik	r6, r0, TOPHYS(lw_table);
 	addk	r5, r5, r5;
 	addk	r5, r5, r5;
 	addk	r5, r5, r5;
@@ -485,7 +501,7 @@
 	/* Get the destination register number into r5 */
 	lbui	r5, r0, TOPHYS(ex_reg_op);
 	/* Form store_word jump table offset (sw_table + (8 * regnum)) */
-	la	r6, r0, TOPHYS(sw_table);
+	addik	r6, r0, TOPHYS(sw_table);
 	add	r5, r5, r5;
 	add	r5, r5, r5;
 	add	r5, r5, r5;
@@ -896,7 +912,7 @@
 	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;
+	addik	r6, r0, ex_tmp_data_loc_0;
 	sbi	r5, r6, 0;
 load2:	lbui	r5, r4, 1;
 	sbi	r5, r6, 1;
@@ -910,7 +926,7 @@
 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;
+	addik	r6, r0, ex_tmp_data_loc_0;
 	sbi	r5, r6, 0;
 load5:	lbui	r5, r4, 1;
 	sbi	r5, r6, 1;
@@ -926,7 +942,7 @@
 	addik	r5, r8, sw_table_vm;
 	bra	r5;
 ex_sw_tail_vm:
-	la	r5, r0, ex_tmp_data_loc_0;
+	addik	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 */
@@ -969,7 +985,7 @@
 	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 */
+	addik	r15, r0, ret_from_exc-8 /* setup return address */
 	brid	bad_page_fault
 	nop
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/intc.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/intc.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/intc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/intc.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,59 +40,46 @@
 #define MER_ME (1<<0)
 #define MER_HIE (1<<1)
 
-static void intc_enable_or_unmask(unsigned int irq)
+static void intc_enable_or_unmask(struct irq_data *d)
 {
-	unsigned long mask = 1 << irq;
-	pr_debug("enable_or_unmask: %d\n", irq);
+	unsigned long mask = 1 << d->irq;
+	pr_debug("enable_or_unmask: %d\n", d->irq);
 	out_be32(INTC_BASE + SIE, mask);
 
 	/* ack level irqs because they can't be acked during
 	 * ack function since the handle_level_irq function
 	 * acks the irq before calling the interrupt handler
 	 */
-	if (irq_desc[irq].status & IRQ_LEVEL)
+	if (irqd_is_level_type(d))
 		out_be32(INTC_BASE + IAR, mask);
 }
 
-static void intc_disable_or_mask(unsigned int irq)
+static void intc_disable_or_mask(struct irq_data *d)
 {
-	pr_debug("disable: %d\n", irq);
-	out_be32(INTC_BASE + CIE, 1 << irq);
+	pr_debug("disable: %d\n", d->irq);
+	out_be32(INTC_BASE + CIE, 1 << d->irq);
 }
 
-static void intc_ack(unsigned int irq)
+static void intc_ack(struct irq_data *d)
 {
-	pr_debug("ack: %d\n", irq);
-	out_be32(INTC_BASE + IAR, 1 << irq);
+	pr_debug("ack: %d\n", d->irq);
+	out_be32(INTC_BASE + IAR, 1 << d->irq);
 }
 
-static void intc_mask_ack(unsigned int irq)
+static void intc_mask_ack(struct irq_data *d)
 {
-	unsigned long mask = 1 << irq;
-	pr_debug("disable_and_ack: %d\n", irq);
+	unsigned long mask = 1 << d->irq;
+	pr_debug("disable_and_ack: %d\n", d->irq);
 	out_be32(INTC_BASE + CIE, mask);
 	out_be32(INTC_BASE + IAR, mask);
 }
 
-static void intc_end(unsigned int irq)
-{
-	unsigned long mask = 1 << irq;
-	pr_debug("end: %d\n", irq);
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		out_be32(INTC_BASE + SIE, mask);
-		/* ack level sensitive intr */
-		if (irq_desc[irq].status & IRQ_LEVEL)
-			out_be32(INTC_BASE + IAR, mask);
-	}
-}
-
 static struct irq_chip intc_dev = {
 	.name = "Xilinx INTC",
-	.unmask = intc_enable_or_unmask,
-	.mask = intc_disable_or_mask,
-	.ack = intc_ack,
-	.mask_ack = intc_mask_ack,
-	.end = intc_end,
+	.irq_unmask = intc_enable_or_unmask,
+	.irq_mask = intc_disable_or_mask,
+	.irq_ack = intc_ack,
+	.irq_mask_ack = intc_mask_ack,
 };
 
 unsigned int get_irq(struct pt_regs *regs)
@@ -170,13 +157,13 @@
 
 	for (i = 0; i < nr_irq; ++i) {
 		if (intr_type & (0x00000001 << i)) {
-			set_irq_chip_and_handler_name(i, &intc_dev,
-				handle_edge_irq, intc_dev.name);
-			irq_desc[i].status &= ~IRQ_LEVEL;
+			irq_set_chip_and_handler_name(i, &intc_dev,
+				handle_edge_irq, "edge");
+			irq_clear_status_flags(i, IRQ_LEVEL);
 		} else {
-			set_irq_chip_and_handler_name(i, &intc_dev,
-				handle_level_irq, intc_dev.name);
-			irq_desc[i].status |= IRQ_LEVEL;
+			irq_set_chip_and_handler_name(i, &intc_dev,
+				handle_level_irq, "level");
+			irq_set_status_flags(i, IRQ_LEVEL);
 		}
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/irq.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,46 +47,6 @@
 	trace_hardirqs_on();
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v, j;
-	struct irqaction *action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "		");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < nr_irq) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ", i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
-#endif
-		seq_printf(p, " %8s", irq_desc[i].status &
-					IRQ_LEVEL ? "level" : "edge");
-		seq_printf(p, " %8s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	return 0;
-}
-
 /* MS: There is no any advance mapping mechanism. We are using simple 32bit
   intc without any cascades or any connection that's why mapping is 1:1 */
 unsigned int irq_create_mapping(struct irq_host *host, irq_hw_number_t hwirq)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/Makefile linux-libre-2.6.39-gnu/arch/microblaze/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -10,6 +10,7 @@
 CFLAGS_REMOVE_selfmod.o = -pg
 CFLAGS_REMOVE_heartbeat.o = -pg
 CFLAGS_REMOVE_ftrace.o = -pg
+CFLAGS_REMOVE_process.o = -pg
 endif
 
 extra-y := head.o vmlinux.lds
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/microblaze_ksyms.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/microblaze_ksyms.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/microblaze_ksyms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/microblaze_ksyms.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 
 extern char *_ebss;
 EXPORT_SYMBOL_GPL(_ebss);
+
 #ifdef CONFIG_FUNCTION_TRACER
 extern void _mcount(void);
 EXPORT_SYMBOL(_mcount);
@@ -45,3 +46,14 @@
 #endif
 
 EXPORT_SYMBOL(mbc);
+
+extern void __divsi3(void);
+EXPORT_SYMBOL(__divsi3);
+extern void __modsi3(void);
+EXPORT_SYMBOL(__modsi3);
+extern void __mulsi3(void);
+EXPORT_SYMBOL(__mulsi3);
+extern void __udivsi3(void);
+EXPORT_SYMBOL(__udivsi3);
+extern void __umodsi3(void);
+EXPORT_SYMBOL(__umodsi3);
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/process.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -159,7 +159,7 @@
 	}
 
 	/* FIXME STATE_SAVE_PT_OFFSET; */
-	ti->cpu_context.r1  = (unsigned long)childregs - STATE_SAVE_ARG_SPACE;
+	ti->cpu_context.r1  = (unsigned long)childregs;
 	/* 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
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/prom.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/prom.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/prom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/prom.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,7 +59,7 @@
 {
 	unsigned long l;
 	char *p;
-	int *addr;
+	const __be32 *addr;
 
 	pr_debug("search \"serial\", depth: %d, uname: %s\n", depth, uname);
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/prom_parse.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/prom_parse.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/prom_parse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/prom_parse.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,88 +2,11 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/pci_regs.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	u32 lspec;
-	u32 laddr[3];
-	u8 pin;
-	int rc;
-
-	/* Check if we have a device node, if yes, fallback to standard OF
-	 * parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn)
-		return of_irq_map_one(dn, 0, out_irq);
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		return rc;
-	/* No pin, exit */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	lspec = pin;
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-			struct pci_controller *host;
-			host = pci_bus_to_host(pdev->bus);
-			ppnode = host ? host->dn : NULL;
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL)
-				return -EINVAL;
-		} else
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't
-		 * include the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
-
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
-		 */
-		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
-		pdev = ppdev;
-	}
-
-	laddr[0] = (pdev->bus->number << 16)
-		| (pdev->devfn << 8);
-	laddr[1]  = laddr[2] = 0;
-	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
 
 void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
 		unsigned long *busno, unsigned long *phys, unsigned long *size)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 #include <linux/uaccess.h>
 #include <asm/asm-offsets.h>
 #include <asm/cacheflush.h>
+#include <asm/syscall.h>
 #include <asm/io.h>
 
 /* Returns the address where the register at REG_OFFS in P is stashed away. */
@@ -123,7 +124,7 @@
 			rval = -EIO;
 
 		if (rval == 0 && request == PTRACE_PEEKUSR)
-			rval = put_user(val, (unsigned long *)data);
+			rval = put_user(val, (unsigned long __user *)data);
 		break;
 	default:
 		rval = ptrace_request(child, request, addr, data);
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/setup.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,8 @@
 void __init machine_early_init(const char *cmdline, unsigned int ram,
 		unsigned int fdt, unsigned int msr)
 {
-	unsigned long *src, *dst = (unsigned long *)0x0;
+	unsigned long *src, *dst;
+	unsigned int offset = 0;
 
 	/* If CONFIG_MTD_UCLINUX is defined, assume ROMFS is at the
 	 * end of kernel. There are two position which we want to check.
@@ -168,7 +169,14 @@
 				"CPU have it %x\n", msr);
 #endif
 
-	for (src = __ivt_start; src < __ivt_end; src++, dst++)
+	/* Do not copy reset vectors. offset = 0x2 means skip the first
+	 * two instructions. dst is pointer to MB vectors which are placed
+	 * in block ram. If you want to copy reset vector setup offset to 0x0 */
+#if !CONFIG_MANUAL_RESET_VECTOR
+	offset = 0x2;
+#endif
+	dst = (unsigned long *) (offset * sizeof(u32));
+	for (src = __ivt_start + offset; src < __ivt_end; src++, dst++)
 		*dst = *src;
 
 	/* Initialize global data */
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/signal.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 asmlinkage long sys_rt_sigreturn(struct pt_regs *regs)
 {
 	struct rt_sigframe __user *frame =
-		(struct rt_sigframe __user *)(regs->r1 + STATE_SAVE_ARG_SPACE);
+		(struct rt_sigframe __user *)(regs->r1);
 
 	sigset_t set;
 	int rval;
@@ -197,8 +197,8 @@
 
 	/* Create the ucontext. */
 	err |= __put_user(0, &frame->uc.uc_flags);
-	err |= __put_user(0, &frame->uc.uc_link);
-	err |= __put_user((void *)current->sas_ss_sp,
+	err |= __put_user(NULL, &frame->uc.uc_link);
+	err |= __put_user((void __user *)current->sas_ss_sp,
 			&frame->uc.uc_stack.ss_sp);
 	err |= __put_user(sas_ss_flags(regs->r1),
 			&frame->uc.uc_stack.ss_flags);
@@ -247,7 +247,7 @@
 		goto give_sigsegv;
 
 	/* Set up registers for signal handler */
-	regs->r1 = (unsigned long) frame - STATE_SAVE_ARG_SPACE;
+	regs->r1 = (unsigned long) frame;
 
 	/* Signal handler args: */
 	regs->r5 = signal; /* arg 0: signum */
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/syscall_table.S linux-libre-2.6.39-gnu/arch/microblaze/kernel/syscall_table.S
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/syscall_table.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/syscall_table.S	2011-05-19 00:06:34.000000000 -0400
@@ -375,3 +375,7 @@
 	.long sys_fanotify_init
 	.long sys_fanotify_mark
 	.long sys_prlimit64	/* 370 */
+	.long sys_name_to_handle_at
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
+	.long sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/sys_microblaze.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/sys_microblaze.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/sys_microblaze.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/sys_microblaze.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,8 @@
 						regs, 0, NULL, NULL);
 }
 
-asmlinkage long microblaze_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;
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/timer.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/timer.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,8 +38,8 @@
 #define TIMER_BASE	timer_baseaddr
 #endif
 
-unsigned int freq_div_hz;
-unsigned int timer_clock_freq;
+static unsigned int freq_div_hz;
+static unsigned int timer_clock_freq;
 
 #define TCSR0	(0x00)
 #define TLR0	(0x04)
@@ -202,7 +202,7 @@
 	.shift = 8,
 };
 
-int __init init_microblaze_timecounter(void)
+static int __init init_microblaze_timecounter(void)
 {
 	microblaze_cc.mult = div_sc(timer_clock_freq, NSEC_PER_SEC,
 				microblaze_cc.shift);
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/unwind.c linux-libre-2.6.39-gnu/arch/microblaze/kernel/unwind.c
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/unwind.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/unwind.c	2011-05-19 00:06:34.000000000 -0400
@@ -183,7 +183,7 @@
  * @trace : Where to store stack backtrace (PC values).
  *	    NULL == print backtrace to kernel log
  */
-void microblaze_unwind_inner(struct task_struct *task,
+static void microblaze_unwind_inner(struct task_struct *task,
 			     unsigned long pc, unsigned long fp,
 			     unsigned long leaf_return,
 			     struct stack_trace *trace)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/microblaze/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/microblaze/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -70,11 +70,6 @@
 	RW_DATA_SECTION(32, PAGE_SIZE, THREAD_SIZE)
 	_edata = . ;
 
-	/* Reserve some low RAM for r0 based memory references */
-	. = ALIGN(0x4) ;
-	r0_ram = . ;
-	. = . +  PAGE_SIZE;	/* a page should be enough */
-
 	/* Under the microblaze ABI, .sdata and .sbss must be contiguous */
 	. = ALIGN(8);
 	.sdata : AT(ADDR(.sdata) - LOAD_OFFSET) {
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/lib/Makefile linux-libre-2.6.39-gnu/arch/microblaze/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/microblaze/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/lib/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,12 @@
 # Makefile
 #
 
+ifdef CONFIG_FUNCTION_TRACER
+CFLAGS_REMOVE_ashldi3.o = -pg
+CFLAGS_REMOVE_ashrdi3.o = -pg
+CFLAGS_REMOVE_lshrdi3.o = -pg
+endif
+
 lib-y :=  memset.o
 
 ifeq ($(CONFIG_OPT_LIB_ASM),y)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/lib/memcpy.c linux-libre-2.6.39-gnu/arch/microblaze/lib/memcpy.c
--- linux-libre-2.6.38-gnu/arch/microblaze/lib/memcpy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/lib/memcpy.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,8 +63,8 @@
 	if (likely(c >= 4)) {
 		unsigned  value, buf_hold;
 
-		/* Align the dstination to a word boundry. */
-		/* This is done in an endian independant manner. */
+		/* Align the destination to a word boundary. */
+		/* This is done in an endian independent manner. */
 		switch ((unsigned long)dst & 3) {
 		case 1:
 			*dst++ = *src++;
@@ -80,7 +80,7 @@
 		i_dst = (void *)dst;
 
 		/* Choose a copy scheme based on the source */
-		/* alignment relative to dstination. */
+		/* alignment relative to destination. */
 		switch ((unsigned long)src & 3) {
 		case 0x0:	/* Both byte offsets are aligned */
 			i_src  = (const void *)src;
@@ -173,7 +173,7 @@
 	}
 
 	/* Finish off any remaining bytes */
-	/* simple fast copy, ... unless a cache boundry is crossed */
+	/* simple fast copy, ... unless a cache boundary is crossed */
 	switch (c) {
 	case 3:
 		*dst++ = *src++;
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/lib/memmove.c linux-libre-2.6.39-gnu/arch/microblaze/lib/memmove.c
--- linux-libre-2.6.38-gnu/arch/microblaze/lib/memmove.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/lib/memmove.c	2011-05-19 00:06:34.000000000 -0400
@@ -83,8 +83,8 @@
 	if (c >= 4) {
 		unsigned  value, buf_hold;
 
-		/* Align the destination to a word boundry. */
-		/* This is done in an endian independant manner. */
+		/* Align the destination to a word boundary. */
+		/* This is done in an endian independent manner. */
 
 		switch ((unsigned long)dst & 3) {
 		case 3:
@@ -193,7 +193,7 @@
 		dst = (void *)i_dst;
 	}
 
-	/* simple fast copy, ... unless a cache boundry is crossed */
+	/* simple fast copy, ... unless a cache boundary is crossed */
 	/* Finish off any remaining bytes */
 	switch (c) {
 	case 4:
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/lib/memset.c linux-libre-2.6.39-gnu/arch/microblaze/lib/memset.c
--- linux-libre-2.6.38-gnu/arch/microblaze/lib/memset.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/lib/memset.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 
 	if (likely(n >= 4)) {
 		/* Align the destination to a word boundary */
-		/* This is done in an endian independant manner */
+		/* This is done in an endian independent manner */
 		switch ((unsigned) src & 3) {
 		case 1:
 			*src++ = c;
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/lib/muldi3.c linux-libre-2.6.39-gnu/arch/microblaze/lib/muldi3.c
--- linux-libre-2.6.38-gnu/arch/microblaze/lib/muldi3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/lib/muldi3.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,3 +58,4 @@
 
 	return w.ll;
 }
+EXPORT_SYMBOL(__muldi3);
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/Makefile linux-libre-2.6.39-gnu/arch/microblaze/Makefile
--- linux-libre-2.6.38-gnu/arch/microblaze/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
 # rather than bools y/n
 
 # Work out HW multipler support. This is tricky.
-# 1. Spartan2 has no HW multiplers.
+# 1. Spartan2 has no HW multipliers.
 # 2. MicroBlaze v3.x always uses them, except in Spartan 2
 # 3. All other FPGa/CPU ver combos, we can trust the CONFIG_ settings
 ifeq (,$(findstring spartan2,$(CONFIG_XILINX_MICROBLAZE0_FAMILY)))
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/mm/consistent.c linux-libre-2.6.39-gnu/arch/microblaze/mm/consistent.c
--- linux-libre-2.6.38-gnu/arch/microblaze/mm/consistent.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/mm/consistent.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,7 +59,7 @@
  * uncached region.  This will no doubt cause big problems if memory allocated
  * here is not also freed properly. -- JW
  */
-void *consistent_alloc(int gfp, size_t size, dma_addr_t *dma_handle)
+void *consistent_alloc(gfp_t gfp, size_t size, dma_addr_t *dma_handle)
 {
 	unsigned long order, vaddr;
 	void *ret;
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/mm/fault.c linux-libre-2.6.39-gnu/arch/microblaze/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/microblaze/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
 {
 	unsigned int inst;
 
-	if (get_user(inst, (unsigned int *)regs->pc))
+	if (get_user(inst, (unsigned int __user *)regs->pc))
 		return 0;
 	/* check for 1 in the rD field */
 	if (((inst >> 21) & 0x1f) != 1)
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/pci/indirect_pci.c linux-libre-2.6.39-gnu/arch/microblaze/pci/indirect_pci.c
--- linux-libre-2.6.38-gnu/arch/microblaze/pci/indirect_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/pci/indirect_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -108,7 +108,7 @@
 		out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
 			 (devfn << 8) | reg | cfg_type));
 
-	/* surpress setting of PCI_PRIMARY_BUS */
+	/* suppress setting of PCI_PRIMARY_BUS */
 	if (hose->indirect_type & INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
 		if ((offset == PCI_PRIMARY_BUS) &&
 			(bus->number == hose->first_busno))
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/pci/pci_32.c linux-libre-2.6.39-gnu/arch/microblaze/pci/pci_32.c
--- linux-libre-2.6.38-gnu/arch/microblaze/pci/pci_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/pci/pci_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -332,6 +332,7 @@
 		       hose->global_number);
 		return;
 	}
+	bus.dev->of_node = of_node_get(node);
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/pci/pci-common.c linux-libre-2.6.39-gnu/arch/microblaze/pci/pci-common.c
--- linux-libre-2.6.38-gnu/arch/microblaze/pci/pci-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/pci/pci-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/of_pci.h>
 
 #include <asm/processor.h>
 #include <asm/io.h>
@@ -236,7 +237,7 @@
 
 		virq = irq_create_mapping(NULL, line);
 		if (virq != NO_IRQ)
-			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
 	} else {
 		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
 			 oirq.size, oirq.specifier[0], oirq.specifier[1],
diff -druN linux-libre-2.6.38-gnu/arch/microblaze/platform/generic/Kconfig.auto linux-libre-2.6.39-gnu/arch/microblaze/platform/generic/Kconfig.auto
--- linux-libre-2.6.38-gnu/arch/microblaze/platform/generic/Kconfig.auto	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/microblaze/platform/generic/Kconfig.auto	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 	  BASE Address for kernel
 
 config XILINX_MICROBLAZE0_FAMILY
-	string "Targetted FPGA family"
+	string "Targeted FPGA family"
 	default "virtex5"
 
 config XILINX_MICROBLAZE0_USE_MSR_INSTR
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/common/clocks.c linux-libre-2.6.39-gnu/arch/mips/alchemy/common/clocks.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/common/clocks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/common/clocks.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
  * counter, if it exists.  If we don't have an accurate processor
  * speed, all of the peripherals that derive their clocks based on
  * this advertised speed will introduce error and sometimes not work
- * properly.  This function is futher convoluted to still allow configurations
+ * properly.  This function is further convoluted to still allow configurations
  * to do that in case they have really, really old silicon with a
  * write-only PLL register.			-- Dan
  */
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/common/irq.c linux-libre-2.6.39-gnu/arch/mips/alchemy/common/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/common/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/common/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 #include <asm/mach-pb1x00/pb1000.h>
 #endif
 
-static int au1x_ic_settype(unsigned int irq, unsigned int flow_type);
+static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type);
 
 /* NOTE on interrupt priorities: The original writers of this code said:
  *
@@ -218,17 +218,17 @@
 };
 
 
-static void au1x_ic0_unmask(unsigned int irq_nr)
+static void au1x_ic0_unmask(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 	au_writel(1 << bit, IC0_MASKSET);
 	au_writel(1 << bit, IC0_WAKESET);
 	au_sync();
 }
 
-static void au1x_ic1_unmask(unsigned int irq_nr)
+static void au1x_ic1_unmask(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 	au_writel(1 << bit, IC1_MASKSET);
 	au_writel(1 << bit, IC1_WAKESET);
 
@@ -236,31 +236,31 @@
  * nowhere in the current kernel sources is it disabled.	--mlau
  */
 #if defined(CONFIG_MIPS_PB1000)
-	if (irq_nr == AU1000_GPIO15_INT)
+	if (d->irq == AU1000_GPIO15_INT)
 		au_writel(0x4000, PB1000_MDR); /* enable int */
 #endif
 	au_sync();
 }
 
-static void au1x_ic0_mask(unsigned int irq_nr)
+static void au1x_ic0_mask(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 	au_writel(1 << bit, IC0_MASKCLR);
 	au_writel(1 << bit, IC0_WAKECLR);
 	au_sync();
 }
 
-static void au1x_ic1_mask(unsigned int irq_nr)
+static void au1x_ic1_mask(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 	au_writel(1 << bit, IC1_MASKCLR);
 	au_writel(1 << bit, IC1_WAKECLR);
 	au_sync();
 }
 
-static void au1x_ic0_ack(unsigned int irq_nr)
+static void au1x_ic0_ack(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 
 	/*
 	 * This may assume that we don't get interrupts from
@@ -271,9 +271,9 @@
 	au_sync();
 }
 
-static void au1x_ic1_ack(unsigned int irq_nr)
+static void au1x_ic1_ack(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 
 	/*
 	 * This may assume that we don't get interrupts from
@@ -284,9 +284,9 @@
 	au_sync();
 }
 
-static void au1x_ic0_maskack(unsigned int irq_nr)
+static void au1x_ic0_maskack(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC0_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC0_INT_BASE;
 
 	au_writel(1 << bit, IC0_WAKECLR);
 	au_writel(1 << bit, IC0_MASKCLR);
@@ -295,9 +295,9 @@
 	au_sync();
 }
 
-static void au1x_ic1_maskack(unsigned int irq_nr)
+static void au1x_ic1_maskack(struct irq_data *d)
 {
-	unsigned int bit = irq_nr - AU1000_INTC1_INT_BASE;
+	unsigned int bit = d->irq - AU1000_INTC1_INT_BASE;
 
 	au_writel(1 << bit, IC1_WAKECLR);
 	au_writel(1 << bit, IC1_MASKCLR);
@@ -306,9 +306,9 @@
 	au_sync();
 }
 
-static int au1x_ic1_setwake(unsigned int irq, unsigned int on)
+static int au1x_ic1_setwake(struct irq_data *d, unsigned int on)
 {
-	int bit = irq - AU1000_INTC1_INT_BASE;
+	int bit = d->irq - AU1000_INTC1_INT_BASE;
 	unsigned long wakemsk, flags;
 
 	/* only GPIO 0-7 can act as wakeup source.  Fortunately these
@@ -336,28 +336,30 @@
  */
 static struct irq_chip au1x_ic0_chip = {
 	.name		= "Alchemy-IC0",
-	.ack		= au1x_ic0_ack,
-	.mask		= au1x_ic0_mask,
-	.mask_ack	= au1x_ic0_maskack,
-	.unmask		= au1x_ic0_unmask,
-	.set_type	= au1x_ic_settype,
+	.irq_ack	= au1x_ic0_ack,
+	.irq_mask	= au1x_ic0_mask,
+	.irq_mask_ack	= au1x_ic0_maskack,
+	.irq_unmask	= au1x_ic0_unmask,
+	.irq_set_type	= au1x_ic_settype,
 };
 
 static struct irq_chip au1x_ic1_chip = {
 	.name		= "Alchemy-IC1",
-	.ack		= au1x_ic1_ack,
-	.mask		= au1x_ic1_mask,
-	.mask_ack	= au1x_ic1_maskack,
-	.unmask		= au1x_ic1_unmask,
-	.set_type	= au1x_ic_settype,
-	.set_wake	= au1x_ic1_setwake,
+	.irq_ack	= au1x_ic1_ack,
+	.irq_mask	= au1x_ic1_mask,
+	.irq_mask_ack	= au1x_ic1_maskack,
+	.irq_unmask	= au1x_ic1_unmask,
+	.irq_set_type	= au1x_ic_settype,
+	.irq_set_wake	= au1x_ic1_setwake,
 };
 
-static int au1x_ic_settype(unsigned int irq, unsigned int flow_type)
+static int au1x_ic_settype(struct irq_data *d, unsigned int flow_type)
 {
 	struct irq_chip *chip;
 	unsigned long icr[6];
-	unsigned int bit, ic;
+	unsigned int bit, ic, irq = d->irq;
+	irq_flow_handler_t handler = NULL;
+	unsigned char *name = NULL;
 	int ret;
 
 	if (irq >= AU1000_INTC1_INT_BASE) {
@@ -387,47 +389,47 @@
 		au_writel(1 << bit, icr[5]);
 		au_writel(1 << bit, icr[4]);
 		au_writel(1 << bit, icr[0]);
-		set_irq_chip_and_handler_name(irq, chip,
-				handle_edge_irq, "riseedge");
+		handler = handle_edge_irq;
+		name = "riseedge";
 		break;
 	case IRQ_TYPE_EDGE_FALLING:	/* 0:1:0 */
 		au_writel(1 << bit, icr[5]);
 		au_writel(1 << bit, icr[1]);
 		au_writel(1 << bit, icr[3]);
-		set_irq_chip_and_handler_name(irq, chip,
-				handle_edge_irq, "falledge");
+		handler = handle_edge_irq;
+		name = "falledge";
 		break;
 	case IRQ_TYPE_EDGE_BOTH:	/* 0:1:1 */
 		au_writel(1 << bit, icr[5]);
 		au_writel(1 << bit, icr[1]);
 		au_writel(1 << bit, icr[0]);
-		set_irq_chip_and_handler_name(irq, chip,
-				handle_edge_irq, "bothedge");
+		handler = handle_edge_irq;
+		name = "bothedge";
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:	/* 1:0:1 */
 		au_writel(1 << bit, icr[2]);
 		au_writel(1 << bit, icr[4]);
 		au_writel(1 << bit, icr[0]);
-		set_irq_chip_and_handler_name(irq, chip,
-				handle_level_irq, "hilevel");
+		handler = handle_level_irq;
+		name = "hilevel";
 		break;
 	case IRQ_TYPE_LEVEL_LOW:	/* 1:1:0 */
 		au_writel(1 << bit, icr[2]);
 		au_writel(1 << bit, icr[1]);
 		au_writel(1 << bit, icr[3]);
-		set_irq_chip_and_handler_name(irq, chip,
-				handle_level_irq, "lowlevel");
+		handler = handle_level_irq;
+		name = "lowlevel";
 		break;
 	case IRQ_TYPE_NONE:		/* 0:0:0 */
 		au_writel(1 << bit, icr[5]);
 		au_writel(1 << bit, icr[4]);
 		au_writel(1 << bit, icr[3]);
-		/* set at least chip so we can call set_irq_type() on it */
-		set_irq_chip(irq, chip);
 		break;
 	default:
 		ret = -EINVAL;
 	}
+	__irq_set_chip_handler_name_locked(d->irq, chip, handler, name);
+
 	au_sync();
 
 	return ret;
@@ -504,11 +506,11 @@
 	 */
 	for (i = AU1000_INTC0_INT_BASE;
 	     (i < AU1000_INTC0_INT_BASE + 32); i++)
-		au1x_ic_settype(i, IRQ_TYPE_NONE);
+		au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE);
 
 	for (i = AU1000_INTC1_INT_BASE;
 	     (i < AU1000_INTC1_INT_BASE + 32); i++)
-		au1x_ic_settype(i, IRQ_TYPE_NONE);
+		au1x_ic_settype(irq_get_irq_data(i), IRQ_TYPE_NONE);
 
 	/*
 	 * Initialize IC0, which is fixed per processor.
@@ -526,7 +528,7 @@
 				au_writel(1 << bit, IC0_ASSIGNSET);
 		}
 
-		au1x_ic_settype(irq_nr, map->im_type);
+		au1x_ic_settype(irq_get_irq_data(irq_nr), map->im_type);
 		++map;
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/bcsr.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/bcsr.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/bcsr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/bcsr.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,26 +97,26 @@
  * CPLD generates tons of spurious interrupts (at least on my DB1200).
  *	-- mlau
  */
-static void bcsr_irq_mask(unsigned int irq_nr)
+static void bcsr_irq_mask(struct irq_data *d)
 {
-	unsigned short v = 1 << (irq_nr - bcsr_csc_base);
+	unsigned short v = 1 << (d->irq - bcsr_csc_base);
 	__raw_writew(v, bcsr_virt + BCSR_REG_INTCLR);
 	__raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR);
 	wmb();
 }
 
-static void bcsr_irq_maskack(unsigned int irq_nr)
+static void bcsr_irq_maskack(struct irq_data *d)
 {
-	unsigned short v = 1 << (irq_nr - bcsr_csc_base);
+	unsigned short v = 1 << (d->irq - bcsr_csc_base);
 	__raw_writew(v, bcsr_virt + BCSR_REG_INTCLR);
 	__raw_writew(v, bcsr_virt + BCSR_REG_MASKCLR);
 	__raw_writew(v, bcsr_virt + BCSR_REG_INTSTAT);	/* ack */
 	wmb();
 }
 
-static void bcsr_irq_unmask(unsigned int irq_nr)
+static void bcsr_irq_unmask(struct irq_data *d)
 {
-	unsigned short v = 1 << (irq_nr - bcsr_csc_base);
+	unsigned short v = 1 << (d->irq - bcsr_csc_base);
 	__raw_writew(v, bcsr_virt + BCSR_REG_INTSET);
 	__raw_writew(v, bcsr_virt + BCSR_REG_MASKSET);
 	wmb();
@@ -124,9 +124,9 @@
 
 static struct irq_chip bcsr_irq_type = {
 	.name		= "CPLD",
-	.mask		= bcsr_irq_mask,
-	.mask_ack	= bcsr_irq_maskack,
-	.unmask		= bcsr_irq_unmask,
+	.irq_mask	= bcsr_irq_mask,
+	.irq_mask_ack	= bcsr_irq_maskack,
+	.irq_unmask	= bcsr_irq_unmask,
 };
 
 void __init bcsr_init_irq(int csc_start, int csc_end, int hook_irq)
@@ -142,8 +142,8 @@
 	bcsr_csc_base = csc_start;
 
 	for (irq = csc_start; irq <= csc_end; irq++)
-		set_irq_chip_and_handler_name(irq, &bcsr_irq_type,
-			handle_level_irq, "level");
+		irq_set_chip_and_handler_name(irq, &bcsr_irq_type,
+					      handle_level_irq, "level");
 
-	set_irq_chained_handler(hook_irq, bcsr_csc_handler);
+	irq_set_chained_handler(hook_irq, bcsr_csc_handler);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/db1200/setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/db1200/setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/db1200/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/db1200/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,20 +63,19 @@
 static int __init db1200_arch_init(void)
 {
 	/* GPIO7 is low-level triggered CPLD cascade */
-	set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
 	bcsr_init_irq(DB1200_INT_BEGIN, DB1200_INT_END, AU1200_GPIO7_INT);
 
 	/* insert/eject pairs: one of both is always screaming.  To avoid
 	 * issues they must not be automatically enabled when initially
 	 * requested.
 	 */
-	irq_to_desc(DB1200_SD0_INSERT_INT)->status |= IRQ_NOAUTOEN;
-	irq_to_desc(DB1200_SD0_EJECT_INT)->status |= IRQ_NOAUTOEN;
-	irq_to_desc(DB1200_PC0_INSERT_INT)->status |= IRQ_NOAUTOEN;
-	irq_to_desc(DB1200_PC0_EJECT_INT)->status |= IRQ_NOAUTOEN;
-	irq_to_desc(DB1200_PC1_INSERT_INT)->status |= IRQ_NOAUTOEN;
-	irq_to_desc(DB1200_PC1_EJECT_INT)->status |= IRQ_NOAUTOEN;
-
+	irq_set_status_flags(DB1200_SD0_INSERT_INT, IRQ_NOAUTOEN);
+	irq_set_status_flags(DB1200_SD0_EJECT_INT, IRQ_NOAUTOEN);
+	irq_set_status_flags(DB1200_PC0_INSERT_INT, IRQ_NOAUTOEN);
+	irq_set_status_flags(DB1200_PC0_EJECT_INT, IRQ_NOAUTOEN);
+	irq_set_status_flags(DB1200_PC1_INSERT_INT, IRQ_NOAUTOEN);
+	irq_set_status_flags(DB1200_PC1_EJECT_INT, IRQ_NOAUTOEN);
 	return 0;
 }
 arch_initcall(db1200_arch_init);
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/db1x00/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -127,13 +127,10 @@
 void __init board_setup(void)
 {
 	unsigned long bcsr1, bcsr2;
-	u32 pin_func;
 
 	bcsr1 = DB1000_BCSR_PHYS_ADDR;
 	bcsr2 = DB1000_BCSR_PHYS_ADDR + DB1000_BCSR_HEXLED_OFS;
 
-	pin_func = 0;
-
 #ifdef CONFIG_MIPS_DB1000
 	printk(KERN_INFO "AMD Alchemy Au1000/Db1000 Board\n");
 #endif
@@ -164,12 +161,16 @@
 	/* Not valid for Au1550 */
 #if defined(CONFIG_IRDA) && \
    (defined(CONFIG_SOC_AU1000) || defined(CONFIG_SOC_AU1100))
-	/* Set IRFIRSEL instead of GPIO15 */
-	pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF;
-	au_writel(pin_func, SYS_PINFUNC);
-	/* Power off until the driver is in use */
-	bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK,
-				BCSR_RESETS_IRDA_MODE_OFF);
+	{
+		u32 pin_func;
+
+		/* Set IRFIRSEL instead of GPIO15 */
+		pin_func = au_readl(SYS_PINFUNC) | SYS_PF_IRF;
+		au_writel(pin_func, SYS_PINFUNC);
+		/* Power off until the driver is in use */
+		bcsr_mod(BCSR_RESETS, BCSR_RESETS_IRDA_MODE_MASK,
+			 BCSR_RESETS_IRDA_MODE_OFF);
+	}
 #endif
 	bcsr_write(BCSR_PCMCIA, 0);	/* turn off PCMCIA power */
 
@@ -177,31 +178,35 @@
 	alchemy_gpio1_input_enable();
 
 #ifdef CONFIG_MIPS_MIRAGE
-	/* GPIO[20] is output */
-	alchemy_gpio_direction_output(20, 0);
+	{
+		u32 pin_func;
 
-	/* Set GPIO[210:208] instead of SSI_0 */
-	pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0;
+		/* GPIO[20] is output */
+		alchemy_gpio_direction_output(20, 0);
 
-	/* Set GPIO[215:211] for LEDs */
-	pin_func |= 5 << 2;
+		/* Set GPIO[210:208] instead of SSI_0 */
+		pin_func = au_readl(SYS_PINFUNC) | SYS_PF_S0;
 
-	/* Set GPIO[214:213] for more LEDs */
-	pin_func |= 5 << 12;
+		/* Set GPIO[215:211] for LEDs */
+		pin_func |= 5 << 2;
 
-	/* Set GPIO[207:200] instead of PCMCIA/LCD */
-	pin_func |= SYS_PF_LCD | SYS_PF_PC;
-	au_writel(pin_func, SYS_PINFUNC);
+		/* Set GPIO[214:213] for more LEDs */
+		pin_func |= 5 << 12;
 
-	/*
-	 * Enable speaker amplifier.  This should
-	 * be part of the audio driver.
-	 */
-	alchemy_gpio_direction_output(209, 1);
+		/* Set GPIO[207:200] instead of PCMCIA/LCD */
+		pin_func |= SYS_PF_LCD | SYS_PF_PC;
+		au_writel(pin_func, SYS_PINFUNC);
 
-	pm_power_off = mirage_power_off;
-	_machine_halt = mirage_power_off;
-	_machine_restart = (void(*)(char *))mips_softreset;
+		/*
+		 * Enable speaker amplifier.  This should
+		 * be part of the audio driver.
+		 */
+		alchemy_gpio_direction_output(209, 1);
+
+		pm_power_off = mirage_power_off;
+		_machine_halt = mirage_power_off;
+		_machine_restart = (void(*)(char *))mips_softreset;
+	}
 #endif
 
 #ifdef CONFIG_MIPS_BOSPORUS
@@ -215,35 +220,35 @@
 static int __init db1x00_init_irq(void)
 {
 #if defined(CONFIG_MIPS_MIRAGE)
-	set_irq_type(AU1500_GPIO7_INT, IRQF_TRIGGER_RISING); /* TS pendown */
+	irq_set_irq_type(AU1500_GPIO7_INT, IRQF_TRIGGER_RISING); /* TS pendown */
 #elif defined(CONFIG_MIPS_DB1550)
-	set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);  /* CD0# */
-	set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);  /* CD1# */
-	set_irq_type(AU1550_GPIO3_INT, IRQF_TRIGGER_LOW);  /* CARD0# */
-	set_irq_type(AU1550_GPIO5_INT, IRQF_TRIGGER_LOW);  /* CARD1# */
-	set_irq_type(AU1550_GPIO21_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-	set_irq_type(AU1550_GPIO22_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+	irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);  /* CD0# */
+	irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);  /* CD1# */
+	irq_set_irq_type(AU1550_GPIO3_INT, IRQF_TRIGGER_LOW);  /* CARD0# */
+	irq_set_irq_type(AU1550_GPIO5_INT, IRQF_TRIGGER_LOW);  /* CARD1# */
+	irq_set_irq_type(AU1550_GPIO21_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+	irq_set_irq_type(AU1550_GPIO22_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #elif defined(CONFIG_MIPS_DB1500)
-	set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
-	set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
-	set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
-	set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
-	set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-	set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+	irq_set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
+	irq_set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
+	irq_set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
+	irq_set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
+	irq_set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+	irq_set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #elif defined(CONFIG_MIPS_DB1100)
-	set_irq_type(AU1100_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
-	set_irq_type(AU1100_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
-	set_irq_type(AU1100_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
-	set_irq_type(AU1100_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
-	set_irq_type(AU1100_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-	set_irq_type(AU1100_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+	irq_set_irq_type(AU1100_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
+	irq_set_irq_type(AU1100_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
+	irq_set_irq_type(AU1100_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
+	irq_set_irq_type(AU1100_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
+	irq_set_irq_type(AU1100_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+	irq_set_irq_type(AU1100_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #elif defined(CONFIG_MIPS_DB1000)
-	set_irq_type(AU1000_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
-	set_irq_type(AU1000_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
-	set_irq_type(AU1000_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
-	set_irq_type(AU1000_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
-	set_irq_type(AU1000_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
-	set_irq_type(AU1000_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
+	irq_set_irq_type(AU1000_GPIO0_INT, IRQF_TRIGGER_LOW); /* CD0# */
+	irq_set_irq_type(AU1000_GPIO3_INT, IRQF_TRIGGER_LOW); /* CD1# */
+	irq_set_irq_type(AU1000_GPIO2_INT, IRQF_TRIGGER_LOW); /* CARD0# */
+	irq_set_irq_type(AU1000_GPIO5_INT, IRQF_TRIGGER_LOW); /* CARD1# */
+	irq_set_irq_type(AU1000_GPIO1_INT, IRQF_TRIGGER_LOW); /* STSCHG0# */
+	irq_set_irq_type(AU1000_GPIO4_INT, IRQF_TRIGGER_LOW); /* STSCHG1# */
 #endif
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1000/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -197,7 +197,7 @@
 
 static int __init pb1000_init_irq(void)
 {
-	set_irq_type(AU1000_GPIO15_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1000_GPIO15_INT, IRQF_TRIGGER_LOW);
 	return 0;
 }
 arch_initcall(pb1000_init_irq);
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1100/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,10 +117,10 @@
 
 static int __init pb1100_init_irq(void)
 {
-	set_irq_type(AU1100_GPIO9_INT,  IRQF_TRIGGER_LOW); /* PCCD# */
-	set_irq_type(AU1100_GPIO10_INT, IRQF_TRIGGER_LOW); /* PCSTSCHG# */
-	set_irq_type(AU1100_GPIO11_INT, IRQF_TRIGGER_LOW); /* PCCard# */
-	set_irq_type(AU1100_GPIO13_INT, IRQF_TRIGGER_LOW); /* DC_IRQ# */
+	irq_set_irq_type(AU1100_GPIO9_INT, IRQF_TRIGGER_LOW); /* PCCD# */
+	irq_set_irq_type(AU1100_GPIO10_INT, IRQF_TRIGGER_LOW); /* PCSTSCHG# */
+	irq_set_irq_type(AU1100_GPIO11_INT, IRQF_TRIGGER_LOW); /* PCCard# */
+	irq_set_irq_type(AU1100_GPIO13_INT, IRQF_TRIGGER_LOW); /* DC_IRQ# */
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1200/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1200/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1200/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1200/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -142,7 +142,7 @@
 		panic("Game over.  Your score is 0.");
 	}
 
-	set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1200_GPIO7_INT, IRQF_TRIGGER_LOW);
 	bcsr_init_irq(PB1200_INT_BEGIN, PB1200_INT_END, AU1200_GPIO7_INT);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1500/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,14 +134,14 @@
 
 static int __init pb1500_init_irq(void)
 {
-	set_irq_type(AU1500_GPIO9_INT, IRQF_TRIGGER_LOW);   /* CD0# */
-	set_irq_type(AU1500_GPIO10_INT, IRQF_TRIGGER_LOW);  /* CARD0 */
-	set_irq_type(AU1500_GPIO11_INT, IRQF_TRIGGER_LOW);  /* STSCHG0# */
-	set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
-	set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO9_INT, IRQF_TRIGGER_LOW);   /* CD0# */
+	irq_set_irq_type(AU1500_GPIO10_INT, IRQF_TRIGGER_LOW);  /* CARD0 */
+	irq_set_irq_type(AU1500_GPIO11_INT, IRQF_TRIGGER_LOW);  /* STSCHG0# */
+	irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
+	irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/devboards/pb1550/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,9 +73,9 @@
 
 static int __init pb1550_init_irq(void)
 {
-	set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1550_GPIO201_205_INT, IRQF_TRIGGER_HIGH);
+	irq_set_irq_type(AU1550_GPIO0_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1550_GPIO1_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1550_GPIO201_205_INT, IRQF_TRIGGER_HIGH);
 
 	/* enable both PCMCIA card irqs in the shared line */
 	alchemy_gpio2_enable_int(201);
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/mtx-1/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/mtx-1/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/mtx-1/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/mtx-1/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -123,11 +123,11 @@
 
 static int __init mtx1_init_irq(void)
 {
-	set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
-	set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
+	irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/xxs1500/board_setup.c linux-libre-2.6.39-gnu/arch/mips/alchemy/xxs1500/board_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/xxs1500/board_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/xxs1500/board_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,19 +85,19 @@
 
 static int __init xxs1500_init_irq(void)
 {
-	set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
-	set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO207_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO204_INT, IRQF_TRIGGER_HIGH);
+	irq_set_irq_type(AU1500_GPIO201_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO202_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO203_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO205_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO207_INT, IRQF_TRIGGER_LOW);
 
-	set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW);
-	set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* CF irq */
-	set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO0_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO1_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO2_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO3_INT, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(AU1500_GPIO4_INT, IRQF_TRIGGER_LOW); /* CF irq */
+	irq_set_irq_type(AU1500_GPIO5_INT, IRQF_TRIGGER_LOW);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/alchemy/xxs1500/init.c linux-libre-2.6.39-gnu/arch/mips/alchemy/xxs1500/init.c
--- linux-libre-2.6.38-gnu/arch/mips/alchemy/xxs1500/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/alchemy/xxs1500/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,10 +51,9 @@
 	prom_init_cmdline();
 
 	memsize_str = prom_getenv("memsize");
-	if (!memsize_str)
+	if (!memsize_str || strict_strtoul(memsize_str, 0, &memsize))
 		memsize = 0x04000000;
-	else
-		strict_strtoul(memsize_str, 0, &memsize);
+
 	add_memory_region(0, memsize, BOOT_MEM_RAM);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/ar7/gpio.c linux-libre-2.6.39-gnu/arch/mips/ar7/gpio.c
--- linux-libre-2.6.38-gnu/arch/mips/ar7/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/ar7/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -325,9 +325,7 @@
 		size = 0x1f;
 	}
 
-	gpch->regs = ioremap_nocache(AR7_REGS_GPIO,
-					AR7_REGS_GPIO + 0x10);
-
+	gpch->regs = ioremap_nocache(AR7_REGS_GPIO, size);
 	if (!gpch->regs) {
 		printk(KERN_ERR "%s: failed to ioremap regs\n",
 					gpch->chip.label);
diff -druN linux-libre-2.6.38-gnu/arch/mips/ar7/irq.c linux-libre-2.6.39-gnu/arch/mips/ar7/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/ar7/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/ar7/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,51 +49,51 @@
 
 static int ar7_irq_base;
 
-static void ar7_unmask_irq(unsigned int irq)
+static void ar7_unmask_irq(struct irq_data *d)
 {
-	writel(1 << ((irq - ar7_irq_base) % 32),
-	       REG(ESR_OFFSET(irq - ar7_irq_base)));
+	writel(1 << ((d->irq - ar7_irq_base) % 32),
+	       REG(ESR_OFFSET(d->irq - ar7_irq_base)));
 }
 
-static void ar7_mask_irq(unsigned int irq)
+static void ar7_mask_irq(struct irq_data *d)
 {
-	writel(1 << ((irq - ar7_irq_base) % 32),
-	       REG(ECR_OFFSET(irq - ar7_irq_base)));
+	writel(1 << ((d->irq - ar7_irq_base) % 32),
+	       REG(ECR_OFFSET(d->irq - ar7_irq_base)));
 }
 
-static void ar7_ack_irq(unsigned int irq)
+static void ar7_ack_irq(struct irq_data *d)
 {
-	writel(1 << ((irq - ar7_irq_base) % 32),
-	       REG(CR_OFFSET(irq - ar7_irq_base)));
+	writel(1 << ((d->irq - ar7_irq_base) % 32),
+	       REG(CR_OFFSET(d->irq - ar7_irq_base)));
 }
 
-static void ar7_unmask_sec_irq(unsigned int irq)
+static void ar7_unmask_sec_irq(struct irq_data *d)
 {
-	writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
+	writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ESR_OFFSET));
 }
 
-static void ar7_mask_sec_irq(unsigned int irq)
+static void ar7_mask_sec_irq(struct irq_data *d)
 {
-	writel(1 << (irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
+	writel(1 << (d->irq - ar7_irq_base - 40), REG(SEC_ECR_OFFSET));
 }
 
-static void ar7_ack_sec_irq(unsigned int irq)
+static void ar7_ack_sec_irq(struct irq_data *d)
 {
-	writel(1 << (irq - ar7_irq_base - 40), REG(SEC_CR_OFFSET));
+	writel(1 << (d->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
+	.irq_unmask = ar7_unmask_irq,
+	.irq_mask = ar7_mask_irq,
+	.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,
+	.irq_unmask = ar7_unmask_sec_irq,
+	.irq_mask = ar7_mask_sec_irq,
+	.irq_ack = ar7_ack_sec_irq,
 };
 
 static struct irqaction ar7_cascade_action = {
@@ -119,11 +119,11 @@
 	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,
+		irq_set_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,
+			irq_set_chip_and_handler(base + i + 40,
 						 &ar7_sec_irq_type,
 						 handle_level_irq);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/mips/ath79/irq.c linux-libre-2.6.39-gnu/arch/mips/ath79/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/ath79/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/ath79/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,13 +62,12 @@
 		spurious_interrupt();
 }
 
-static void ar71xx_misc_irq_unmask(unsigned int irq)
+static void ar71xx_misc_irq_unmask(struct irq_data *d)
 {
+	unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
 	void __iomem *base = ath79_reset_base;
 	u32 t;
 
-	irq -= ATH79_MISC_IRQ_BASE;
-
 	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 	__raw_writel(t | (1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 
@@ -76,13 +75,12 @@
 	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 }
 
-static void ar71xx_misc_irq_mask(unsigned int irq)
+static void ar71xx_misc_irq_mask(struct irq_data *d)
 {
+	unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
 	void __iomem *base = ath79_reset_base;
 	u32 t;
 
-	irq -= ATH79_MISC_IRQ_BASE;
-
 	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 
@@ -90,13 +88,12 @@
 	__raw_readl(base + AR71XX_RESET_REG_MISC_INT_ENABLE);
 }
 
-static void ar724x_misc_irq_ack(unsigned int irq)
+static void ar724x_misc_irq_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq - ATH79_MISC_IRQ_BASE;
 	void __iomem *base = ath79_reset_base;
 	u32 t;
 
-	irq -= ATH79_MISC_IRQ_BASE;
-
 	t = __raw_readl(base + AR71XX_RESET_REG_MISC_INT_STATUS);
 	__raw_writel(t & ~(1 << irq), base + AR71XX_RESET_REG_MISC_INT_STATUS);
 
@@ -106,8 +103,8 @@
 
 static struct irq_chip ath79_misc_irq_chip = {
 	.name		= "MISC",
-	.unmask		= ar71xx_misc_irq_unmask,
-	.mask		= ar71xx_misc_irq_mask,
+	.irq_unmask	= ar71xx_misc_irq_unmask,
+	.irq_mask	= ar71xx_misc_irq_mask,
 };
 
 static void __init ath79_misc_irq_init(void)
@@ -119,20 +116,19 @@
 	__raw_writel(0, base + AR71XX_RESET_REG_MISC_INT_STATUS);
 
 	if (soc_is_ar71xx() || soc_is_ar913x())
-		ath79_misc_irq_chip.mask_ack = ar71xx_misc_irq_mask;
+		ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask;
 	else if (soc_is_ar724x())
-		ath79_misc_irq_chip.ack = ar724x_misc_irq_ack;
+		ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack;
 	else
 		BUG();
 
 	for (i = ATH79_MISC_IRQ_BASE;
 	     i < ATH79_MISC_IRQ_BASE + ATH79_MISC_IRQ_COUNT; i++) {
-		irq_desc[i].status = IRQ_DISABLED;
-		set_irq_chip_and_handler(i, &ath79_misc_irq_chip,
+		irq_set_chip_and_handler(i, &ath79_misc_irq_chip,
 					 handle_level_irq);
 	}
 
-	set_irq_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
+	irq_set_chained_handler(ATH79_CPU_IRQ_MISC, ath79_misc_irq_handler);
 }
 
 asmlinkage void plat_irq_dispatch(void)
diff -druN linux-libre-2.6.38-gnu/arch/mips/bcm63xx/boards/Makefile linux-libre-2.6.39-gnu/arch/mips/bcm63xx/boards/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/bcm63xx/boards/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/bcm63xx/boards/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,3 +1,3 @@
 obj-$(CONFIG_BOARD_BCM963XX)		+= board_bcm963xx.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
diff -druN linux-libre-2.6.38-gnu/arch/mips/bcm63xx/irq.c linux-libre-2.6.39-gnu/arch/mips/bcm63xx/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/bcm63xx/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/bcm63xx/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,88 +76,80 @@
  * internal IRQs operations: only mask/unmask on PERF irq mask
  * register.
  */
-static inline void bcm63xx_internal_irq_mask(unsigned int irq)
+static inline void bcm63xx_internal_irq_mask(struct irq_data *d)
 {
+	unsigned int irq = d->irq - IRQ_INTERNAL_BASE;
 	u32 mask;
 
-	irq -= IRQ_INTERNAL_BASE;
 	mask = bcm_perf_readl(PERF_IRQMASK_REG);
 	mask &= ~(1 << irq);
 	bcm_perf_writel(mask, PERF_IRQMASK_REG);
 }
 
-static void bcm63xx_internal_irq_unmask(unsigned int irq)
+static void bcm63xx_internal_irq_unmask(struct irq_data *d)
 {
+	unsigned int irq = d->irq - IRQ_INTERNAL_BASE;
 	u32 mask;
 
-	irq -= IRQ_INTERNAL_BASE;
 	mask = bcm_perf_readl(PERF_IRQMASK_REG);
 	mask |= (1 << irq);
 	bcm_perf_writel(mask, PERF_IRQMASK_REG);
 }
 
-static unsigned int bcm63xx_internal_irq_startup(unsigned int irq)
-{
-	bcm63xx_internal_irq_unmask(irq);
-	return 0;
-}
-
 /*
  * external IRQs operations: mask/unmask and clear on PERF external
  * irq control register.
  */
-static void bcm63xx_external_irq_mask(unsigned int irq)
+static void bcm63xx_external_irq_mask(struct irq_data *d)
 {
+	unsigned int irq = d->irq - IRQ_EXT_BASE;
 	u32 reg;
 
-	irq -= IRQ_EXT_BASE;
 	reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
 	reg &= ~EXTIRQ_CFG_MASK(irq);
 	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
 }
 
-static void bcm63xx_external_irq_unmask(unsigned int irq)
+static void bcm63xx_external_irq_unmask(struct irq_data *d)
 {
+	unsigned int irq = d->irq - IRQ_EXT_BASE;
 	u32 reg;
 
-	irq -= IRQ_EXT_BASE;
 	reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
 	reg |= EXTIRQ_CFG_MASK(irq);
 	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
 }
 
-static void bcm63xx_external_irq_clear(unsigned int irq)
+static void bcm63xx_external_irq_clear(struct irq_data *d)
 {
+	unsigned int irq = d->irq - IRQ_EXT_BASE;
 	u32 reg;
 
-	irq -= IRQ_EXT_BASE;
 	reg = bcm_perf_readl(PERF_EXTIRQ_CFG_REG);
 	reg |= EXTIRQ_CFG_CLEAR(irq);
 	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
 }
 
-static unsigned int bcm63xx_external_irq_startup(unsigned int irq)
+static unsigned int bcm63xx_external_irq_startup(struct irq_data *d)
 {
-	set_c0_status(0x100 << (irq - IRQ_MIPS_BASE));
+	set_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE));
 	irq_enable_hazard();
-	bcm63xx_external_irq_unmask(irq);
+	bcm63xx_external_irq_unmask(d);
 	return 0;
 }
 
-static void bcm63xx_external_irq_shutdown(unsigned int irq)
+static void bcm63xx_external_irq_shutdown(struct irq_data *d)
 {
-	bcm63xx_external_irq_mask(irq);
-	clear_c0_status(0x100 << (irq - IRQ_MIPS_BASE));
+	bcm63xx_external_irq_mask(d);
+	clear_c0_status(0x100 << (d->irq - IRQ_MIPS_BASE));
 	irq_disable_hazard();
 }
 
-static int bcm63xx_external_irq_set_type(unsigned int irq,
+static int bcm63xx_external_irq_set_type(struct irq_data *d,
 					 unsigned int flow_type)
 {
+	unsigned int irq = d->irq - IRQ_EXT_BASE;
 	u32 reg;
-	struct irq_desc *desc = irq_desc + irq;
-
-	irq -= IRQ_EXT_BASE;
 
 	flow_type &= IRQ_TYPE_SENSE_MASK;
 
@@ -199,37 +191,32 @@
 	}
 	bcm_perf_writel(reg, PERF_EXTIRQ_CFG_REG);
 
-	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))  {
-		desc->status |= IRQ_LEVEL;
-		desc->handle_irq = handle_level_irq;
-	} else {
-		desc->handle_irq = handle_edge_irq;
-	}
+	irqd_set_trigger_type(d, flow_type);
+	if (flow_type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+	else
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 
-	return 0;
+	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
 static struct irq_chip bcm63xx_internal_irq_chip = {
 	.name		= "bcm63xx_ipic",
-	.startup	= bcm63xx_internal_irq_startup,
-	.shutdown	= bcm63xx_internal_irq_mask,
-
-	.mask		= bcm63xx_internal_irq_mask,
-	.mask_ack	= bcm63xx_internal_irq_mask,
-	.unmask		= bcm63xx_internal_irq_unmask,
+	.irq_mask	= bcm63xx_internal_irq_mask,
+	.irq_unmask	= bcm63xx_internal_irq_unmask,
 };
 
 static struct irq_chip bcm63xx_external_irq_chip = {
 	.name		= "bcm63xx_epic",
-	.startup	= bcm63xx_external_irq_startup,
-	.shutdown	= bcm63xx_external_irq_shutdown,
+	.irq_startup	= bcm63xx_external_irq_startup,
+	.irq_shutdown	= bcm63xx_external_irq_shutdown,
 
-	.ack		= bcm63xx_external_irq_clear,
+	.irq_ack	= bcm63xx_external_irq_clear,
 
-	.mask		= bcm63xx_external_irq_mask,
-	.unmask		= bcm63xx_external_irq_unmask,
+	.irq_mask	= bcm63xx_external_irq_mask,
+	.irq_unmask	= bcm63xx_external_irq_unmask,
 
-	.set_type	= bcm63xx_external_irq_set_type,
+	.irq_set_type	= bcm63xx_external_irq_set_type,
 };
 
 static struct irqaction cpu_ip2_cascade_action = {
@@ -243,11 +230,11 @@
 
 	mips_cpu_irq_init();
 	for (i = IRQ_INTERNAL_BASE; i < NR_IRQS; ++i)
-		set_irq_chip_and_handler(i, &bcm63xx_internal_irq_chip,
+		irq_set_chip_and_handler(i, &bcm63xx_internal_irq_chip,
 					 handle_level_irq);
 
 	for (i = IRQ_EXT_BASE; i < IRQ_EXT_BASE + 4; ++i)
-		set_irq_chip_and_handler(i, &bcm63xx_external_irq_chip,
+		irq_set_chip_and_handler(i, &bcm63xx_external_irq_chip,
 					 handle_edge_irq);
 
 	setup_irq(IRQ_MIPS_BASE + 2, &cpu_ip2_cascade_action);
diff -druN linux-libre-2.6.38-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c linux-libre-2.6.39-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c
--- linux-libre-2.6.38-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/boot/compressed/calc_vmlinuz_load_addr.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,8 +16,8 @@
 
 int main(int argc, char *argv[])
 {
+	unsigned long long vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
 	struct stat sb;
-	uint64_t vmlinux_size, vmlinux_load_addr, vmlinuz_load_addr;
 
 	if (argc != 3) {
 		fprintf(stderr, "Usage: %s <pathname> <vmlinux_load_addr>\n",
diff -druN linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/executive/octeon-model.c linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/executive/octeon-model.c
--- linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/executive/octeon-model.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/executive/octeon-model.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 
 	num_cores = cvmx_octeon_num_cores();
 
-	/* Make sure the non existant devices look disabled */
+	/* Make sure the non existent devices look disabled */
 	switch ((chip_id >> 8) & 0xff) {
 	case 6:		/* CN50XX */
 	case 2:		/* CN30XX */
diff -druN linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/Kconfig linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/Kconfig
--- linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,11 +1,7 @@
-config CAVIUM_OCTEON_SPECIFIC_OPTIONS
-	bool "Enable Octeon specific options"
-	depends on CPU_CAVIUM_OCTEON
-	default "y"
+if CPU_CAVIUM_OCTEON
 
 config CAVIUM_CN63XXP1
 	bool "Enable CN63XXP1 errata worarounds"
-	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
 	default "n"
 	help
 	  The CN63XXP1 chip requires build time workarounds to
@@ -16,7 +12,6 @@
 
 config CAVIUM_OCTEON_2ND_KERNEL
 	bool "Build the kernel to be used as a 2nd kernel on the same chip"
-	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
 	default "n"
 	help
 	  This option configures this kernel to be linked at a different
@@ -26,7 +21,6 @@
 
 config CAVIUM_OCTEON_HW_FIX_UNALIGNED
 	bool "Enable hardware fixups of unaligned loads and stores"
-	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
 	default "y"
 	help
 	  Configure the Octeon hardware to automatically fix unaligned loads
@@ -38,7 +32,6 @@
 
 config CAVIUM_OCTEON_CVMSEG_SIZE
 	int "Number of L1 cache lines reserved for CVMSEG memory"
-	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
 	range 0 54
 	default 1
 	help
@@ -50,7 +43,6 @@
 
 config CAVIUM_OCTEON_LOCK_L2
 	bool "Lock often used kernel code in the L2"
-	depends on CAVIUM_OCTEON_SPECIFIC_OPTIONS
 	default "y"
 	help
 	  Enable locking parts of the kernel into the L2 cache.
@@ -93,7 +85,6 @@
 config ARCH_SPARSEMEM_ENABLE
 	def_bool y
 	select SPARSEMEM_STATIC
-	depends on CPU_CAVIUM_OCTEON
 
 config CAVIUM_OCTEON_HELPER
 	def_bool y
@@ -107,6 +98,8 @@
 
 config SWIOTLB
 	def_bool y
-	depends on CPU_CAVIUM_OCTEON
 	select IOMMU_HELPER
 	select NEED_SG_DMA_LENGTH
+
+
+endif # CPU_CAVIUM_OCTEON
diff -druN linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/octeon-irq.c linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/octeon-irq.c
--- linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/octeon-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/octeon-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,10 +3,13 @@
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  *
- * Copyright (C) 2004-2008, 2009, 2010 Cavium Networks
+ * Copyright (C) 2004-2008, 2009, 2010, 2011 Cavium Networks
  */
-#include <linux/irq.h>
+
 #include <linux/interrupt.h>
+#include <linux/bitops.h>
+#include <linux/percpu.h>
+#include <linux/irq.h>
 #include <linux/smp.h>
 
 #include <asm/octeon/octeon.h>
@@ -14,6 +17,47 @@
 static DEFINE_RAW_SPINLOCK(octeon_irq_ciu0_lock);
 static DEFINE_RAW_SPINLOCK(octeon_irq_ciu1_lock);
 
+static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu0_en_mirror);
+static DEFINE_PER_CPU(unsigned long, octeon_irq_ciu1_en_mirror);
+
+static __read_mostly u8 octeon_irq_ciu_to_irq[8][64];
+
+union octeon_ciu_chip_data {
+	void *p;
+	unsigned long l;
+	struct {
+		unsigned int line:6;
+		unsigned int bit:6;
+	} s;
+};
+
+struct octeon_core_chip_data {
+	struct mutex core_irq_mutex;
+	bool current_en;
+	bool desired_en;
+	u8 bit;
+};
+
+#define MIPS_CORE_IRQ_LINES 8
+
+static struct octeon_core_chip_data octeon_irq_core_chip_data[MIPS_CORE_IRQ_LINES];
+
+static void __init octeon_irq_set_ciu_mapping(int irq, int line, int bit,
+					      struct irq_chip *chip,
+					      irq_flow_handler_t handler)
+{
+	union octeon_ciu_chip_data cd;
+
+	irq_set_chip_and_handler(irq, chip, handler);
+
+	cd.l = 0;
+	cd.s.line = line;
+	cd.s.bit = bit;
+
+	irq_set_chip_data(irq, cd.p);
+	octeon_irq_ciu_to_irq[line][bit] = irq;
+}
+
 static int octeon_coreid_for_cpu(int cpu)
 {
 #ifdef CONFIG_SMP
@@ -23,9 +67,20 @@
 #endif
 }
 
-static void octeon_irq_core_ack(unsigned int irq)
+static int octeon_cpu_for_coreid(int coreid)
 {
-	unsigned int bit = irq - OCTEON_IRQ_SW0;
+#ifdef CONFIG_SMP
+	return cpu_number_map(coreid);
+#else
+	return smp_processor_id();
+#endif
+}
+
+static void octeon_irq_core_ack(struct irq_data *data)
+{
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+	unsigned int bit = cd->bit;
+
 	/*
 	 * We don't need to disable IRQs to make these atomic since
 	 * they are already disabled earlier in the low level
@@ -37,131 +92,121 @@
 		clear_c0_cause(0x100 << bit);
 }
 
-static void octeon_irq_core_eoi(unsigned int irq)
+static void octeon_irq_core_eoi(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	unsigned int bit = irq - OCTEON_IRQ_SW0;
-	/*
-	 * If an IRQ is being processed while we are disabling it the
-	 * handler will attempt to unmask the interrupt after it has
-	 * been disabled.
-	 */
-	if ((unlikely(desc->status & IRQ_DISABLED)))
-		return;
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
 	/*
 	 * We don't need to disable IRQs to make these atomic since
 	 * they are already disabled earlier in the low level
 	 * interrupt code.
 	 */
-	set_c0_status(0x100 << bit);
+	set_c0_status(0x100 << cd->bit);
 }
 
-static void octeon_irq_core_enable(unsigned int irq)
+static void octeon_irq_core_set_enable_local(void *arg)
 {
-	unsigned long flags;
-	unsigned int bit = irq - OCTEON_IRQ_SW0;
+	struct irq_data *data = arg;
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+	unsigned int mask = 0x100 << cd->bit;
 
 	/*
-	 * We need to disable interrupts to make sure our updates are
-	 * atomic.
+	 * Interrupts are already disabled, so these are atomic.
 	 */
-	local_irq_save(flags);
-	set_c0_status(0x100 << bit);
-	local_irq_restore(flags);
+	if (cd->desired_en)
+		set_c0_status(mask);
+	else
+		clear_c0_status(mask);
+
 }
 
-static void octeon_irq_core_disable_local(unsigned int irq)
+static void octeon_irq_core_disable(struct irq_data *data)
 {
-	unsigned long flags;
-	unsigned int bit = irq - OCTEON_IRQ_SW0;
-	/*
-	 * We need to disable interrupts to make sure our updates are
-	 * atomic.
-	 */
-	local_irq_save(flags);
-	clear_c0_status(0x100 << bit);
-	local_irq_restore(flags);
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+	cd->desired_en = false;
 }
 
-static void octeon_irq_core_disable(unsigned int irq)
+static void octeon_irq_core_enable(struct irq_data *data)
 {
-#ifdef CONFIG_SMP
-	on_each_cpu((void (*)(void *)) octeon_irq_core_disable_local,
-		    (void *) (long) irq, 1);
-#else
-	octeon_irq_core_disable_local(irq);
-#endif
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+	cd->desired_en = true;
 }
 
-static struct irq_chip octeon_irq_chip_core = {
-	.name = "Core",
-	.enable = octeon_irq_core_enable,
-	.disable = octeon_irq_core_disable,
-	.ack = octeon_irq_core_ack,
-	.eoi = octeon_irq_core_eoi,
-};
+static void octeon_irq_core_bus_lock(struct irq_data *data)
+{
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
 
+	mutex_lock(&cd->core_irq_mutex);
+}
 
-static void octeon_irq_ciu0_ack(unsigned int irq)
+static void octeon_irq_core_bus_sync_unlock(struct irq_data *data)
 {
-	switch (irq) {
-	case OCTEON_IRQ_GMX_DRP0:
-	case OCTEON_IRQ_GMX_DRP1:
-	case OCTEON_IRQ_IPD_DRP:
-	case OCTEON_IRQ_KEY_ZERO:
-	case OCTEON_IRQ_TIMER0:
-	case OCTEON_IRQ_TIMER1:
-	case OCTEON_IRQ_TIMER2:
-	case OCTEON_IRQ_TIMER3:
-	{
-		int index = cvmx_get_core_num() * 2;
-		u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-		/*
-		 * CIU timer type interrupts must be acknoleged by
-		 * writing a '1' bit to their sum0 bit.
-		 */
-		cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
-		break;
-	}
-	default:
-		break;
+	struct octeon_core_chip_data *cd = irq_data_get_irq_chip_data(data);
+
+	if (cd->desired_en != cd->current_en) {
+		on_each_cpu(octeon_irq_core_set_enable_local, data, 1);
+
+		cd->current_en = cd->desired_en;
 	}
 
-	/*
-	 * In order to avoid any locking accessing the CIU, we
-	 * acknowledge CIU interrupts by disabling all of them.  This
-	 * way we can use a per core register and avoid any out of
-	 * core locking requirements.  This has the side affect that
-	 * CIU interrupts can't be processed recursively.
-	 *
-	 * We don't need to disable IRQs to make these atomic since
-	 * they are already disabled earlier in the low level
-	 * interrupt code.
-	 */
-	clear_c0_status(0x100 << 2);
+	mutex_unlock(&cd->core_irq_mutex);
 }
 
-static void octeon_irq_ciu0_eoi(unsigned int irq)
+static struct irq_chip octeon_irq_chip_core = {
+	.name = "Core",
+	.irq_enable = octeon_irq_core_enable,
+	.irq_disable = octeon_irq_core_disable,
+	.irq_ack = octeon_irq_core_ack,
+	.irq_eoi = octeon_irq_core_eoi,
+	.irq_bus_lock = octeon_irq_core_bus_lock,
+	.irq_bus_sync_unlock = octeon_irq_core_bus_sync_unlock,
+
+	.irq_cpu_online = octeon_irq_core_eoi,
+	.irq_cpu_offline = octeon_irq_core_ack,
+	.flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+static void __init octeon_irq_init_core(void)
 {
-	/*
-	 * Enable all CIU interrupts again.  We don't need to disable
-	 * IRQs to make these atomic since they are already disabled
-	 * earlier in the low level interrupt code.
-	 */
-	set_c0_status(0x100 << 2);
+	int i;
+	int irq;
+	struct octeon_core_chip_data *cd;
+
+	for (i = 0; i < MIPS_CORE_IRQ_LINES; i++) {
+		cd = &octeon_irq_core_chip_data[i];
+		cd->current_en = false;
+		cd->desired_en = false;
+		cd->bit = i;
+		mutex_init(&cd->core_irq_mutex);
+
+		irq = OCTEON_IRQ_SW0 + i;
+		switch (irq) {
+		case OCTEON_IRQ_TIMER:
+		case OCTEON_IRQ_SW0:
+		case OCTEON_IRQ_SW1:
+		case OCTEON_IRQ_5:
+		case OCTEON_IRQ_PERF:
+			irq_set_chip_data(irq, cd);
+			irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
+						 handle_percpu_irq);
+			break;
+		default:
+			break;
+		}
+	}
 }
 
-static int next_coreid_for_irq(struct irq_desc *desc)
+static int next_cpu_for_irq(struct irq_data *data)
 {
 
 #ifdef CONFIG_SMP
-	int coreid;
-	int weight = cpumask_weight(desc->affinity);
+	int cpu;
+	int weight = cpumask_weight(data->affinity);
 
 	if (weight > 1) {
-		int cpu = smp_processor_id();
+		cpu = smp_processor_id();
 		for (;;) {
-			cpu = cpumask_next(cpu, desc->affinity);
+			cpu = cpumask_next(cpu, data->affinity);
 			if (cpu >= nr_cpu_ids) {
 				cpu = -1;
 				continue;
@@ -169,83 +214,175 @@
 				break;
 			}
 		}
-		coreid = octeon_coreid_for_cpu(cpu);
 	} else if (weight == 1) {
-		coreid = octeon_coreid_for_cpu(cpumask_first(desc->affinity));
+		cpu = cpumask_first(data->affinity);
 	} else {
-		coreid = cvmx_get_core_num();
+		cpu = smp_processor_id();
 	}
-	return coreid;
+	return cpu;
 #else
-	return cvmx_get_core_num();
+	return smp_processor_id();
 #endif
 }
 
-static void octeon_irq_ciu0_enable(unsigned int irq)
+static void octeon_irq_ciu_enable(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	int coreid = next_coreid_for_irq(desc);
+	int cpu = next_cpu_for_irq(data);
+	int coreid = octeon_coreid_for_cpu(cpu);
+	unsigned long *pen;
 	unsigned long flags;
-	uint64_t en0;
-	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+	union octeon_ciu_chip_data cd;
 
-	raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-	en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-	en0 |= 1ull << bit;
-	cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
-	cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	cd.p = irq_data_get_irq_chip_data(data);
+
+	if (cd.s.line == 0) {
+		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+		pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+		set_bit(cd.s.bit, pen);
+		cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	} else {
+		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+		pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+		set_bit(cd.s.bit, pen);
+		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	}
 }
 
-static void octeon_irq_ciu0_enable_mbox(unsigned int irq)
+static void octeon_irq_ciu_enable_local(struct irq_data *data)
 {
-	int coreid = cvmx_get_core_num();
+	unsigned long *pen;
 	unsigned long flags;
-	uint64_t en0;
-	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+	union octeon_ciu_chip_data cd;
 
-	raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-	en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-	en0 |= 1ull << bit;
-	cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
-	cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	cd.p = irq_data_get_irq_chip_data(data);
+
+	if (cd.s.line == 0) {
+		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+		pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
+		set_bit(cd.s.bit, pen);
+		cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	} else {
+		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+		pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
+		set_bit(cd.s.bit, pen);
+		cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	}
 }
 
-static void octeon_irq_ciu0_disable(unsigned int irq)
+static void octeon_irq_ciu_disable_local(struct irq_data *data)
 {
-	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+	unsigned long *pen;
 	unsigned long flags;
-	uint64_t en0;
+	union octeon_ciu_chip_data cd;
+
+	cd.p = irq_data_get_irq_chip_data(data);
+
+	if (cd.s.line == 0) {
+		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+		pen = &__get_cpu_var(octeon_irq_ciu0_en_mirror);
+		clear_bit(cd.s.bit, pen);
+		cvmx_write_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2), *pen);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	} else {
+		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+		pen = &__get_cpu_var(octeon_irq_ciu1_en_mirror);
+		clear_bit(cd.s.bit, pen);
+		cvmx_write_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1), *pen);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	}
+}
+
+static void octeon_irq_ciu_disable_all(struct irq_data *data)
+{
+	unsigned long flags;
+	unsigned long *pen;
 	int cpu;
-	raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-	for_each_online_cpu(cpu) {
-		int coreid = octeon_coreid_for_cpu(cpu);
-		en0 = cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-		en0 &= ~(1ull << bit);
-		cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
+	union octeon_ciu_chip_data cd;
+
+	wmb(); /* Make sure flag changes arrive before register updates. */
+
+	cd.p = irq_data_get_irq_chip_data(data);
+
+	if (cd.s.line == 0) {
+		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+		for_each_online_cpu(cpu) {
+			int coreid = octeon_coreid_for_cpu(cpu);
+			pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+			clear_bit(cd.s.bit, pen);
+			cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
+		}
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	} else {
+		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+		for_each_online_cpu(cpu) {
+			int coreid = octeon_coreid_for_cpu(cpu);
+			pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+			clear_bit(cd.s.bit, pen);
+			cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+		}
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	}
+}
+
+static void octeon_irq_ciu_enable_all(struct irq_data *data)
+{
+	unsigned long flags;
+	unsigned long *pen;
+	int cpu;
+	union octeon_ciu_chip_data cd;
+
+	cd.p = irq_data_get_irq_chip_data(data);
+
+	if (cd.s.line == 0) {
+		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+		for_each_online_cpu(cpu) {
+			int coreid = octeon_coreid_for_cpu(cpu);
+			pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+			set_bit(cd.s.bit, pen);
+			cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
+		}
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	} else {
+		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+		for_each_online_cpu(cpu) {
+			int coreid = octeon_coreid_for_cpu(cpu);
+			pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+			set_bit(cd.s.bit, pen);
+			cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+		}
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
 	}
-	/*
-	 * We need to do a read after the last update to make sure all
-	 * of them are done.
-	 */
-	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
 }
 
 /*
  * Enable the irq on the next core in the affinity set for chips that
  * have the EN*_W1{S,C} registers.
  */
-static void octeon_irq_ciu0_enable_v2(unsigned int irq)
+static void octeon_irq_ciu_enable_v2(struct irq_data *data)
 {
-	int index;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-	struct irq_desc *desc = irq_to_desc(irq);
+	u64 mask;
+	int cpu = next_cpu_for_irq(data);
+	union octeon_ciu_chip_data cd;
 
-	if ((desc->status & IRQ_DISABLED) == 0) {
-		index = next_coreid_for_irq(desc) * 2;
+	cd.p = irq_data_get_irq_chip_data(data);
+	mask = 1ull << (cd.s.bit);
+
+	/*
+	 * Called under the desc lock, so these should never get out
+	 * of sync.
+	 */
+	if (cd.s.line == 0) {
+		int index = octeon_coreid_for_cpu(cpu) * 2;
+		set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
 		cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+	} else {
+		int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+		set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
 	}
 }
 
@@ -253,83 +390,155 @@
  * Enable the irq on the current CPU for chips that
  * have the EN*_W1{S,C} registers.
  */
-static void octeon_irq_ciu0_enable_mbox_v2(unsigned int irq)
+static void octeon_irq_ciu_enable_local_v2(struct irq_data *data)
 {
-	int index;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+	u64 mask;
+	union octeon_ciu_chip_data cd;
 
-	index = cvmx_get_core_num() * 2;
-	cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+	cd.p = irq_data_get_irq_chip_data(data);
+	mask = 1ull << (cd.s.bit);
+
+	if (cd.s.line == 0) {
+		int index = cvmx_get_core_num() * 2;
+		set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror));
+		cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+	} else {
+		int index = cvmx_get_core_num() * 2 + 1;
+		set_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror));
+		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+	}
+}
+
+static void octeon_irq_ciu_disable_local_v2(struct irq_data *data)
+{
+	u64 mask;
+	union octeon_ciu_chip_data cd;
+
+	cd.p = irq_data_get_irq_chip_data(data);
+	mask = 1ull << (cd.s.bit);
+
+	if (cd.s.line == 0) {
+		int index = cvmx_get_core_num() * 2;
+		clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu0_en_mirror));
+		cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+	} else {
+		int index = cvmx_get_core_num() * 2 + 1;
+		clear_bit(cd.s.bit, &__get_cpu_var(octeon_irq_ciu1_en_mirror));
+		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+	}
 }
 
 /*
- * Disable the irq on the current core for chips that have the EN*_W1{S,C}
- * registers.
+ * Write to the W1C bit in CVMX_CIU_INTX_SUM0 to clear the irq.
  */
-static void octeon_irq_ciu0_ack_v2(unsigned int irq)
+static void octeon_irq_ciu_ack(struct irq_data *data)
 {
-	int index = cvmx_get_core_num() * 2;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+	u64 mask;
+	union octeon_ciu_chip_data cd;
 
-	switch (irq) {
-	case OCTEON_IRQ_GMX_DRP0:
-	case OCTEON_IRQ_GMX_DRP1:
-	case OCTEON_IRQ_IPD_DRP:
-	case OCTEON_IRQ_KEY_ZERO:
-	case OCTEON_IRQ_TIMER0:
-	case OCTEON_IRQ_TIMER1:
-	case OCTEON_IRQ_TIMER2:
-	case OCTEON_IRQ_TIMER3:
-		/*
-		 * CIU timer type interrupts must be acknoleged by
-		 * writing a '1' bit to their sum0 bit.
-		 */
+	cd.p = data->chip_data;
+	mask = 1ull << (cd.s.bit);
+
+	if (cd.s.line == 0) {
+		int index = cvmx_get_core_num() * 2;
 		cvmx_write_csr(CVMX_CIU_INTX_SUM0(index), mask);
-		break;
-	default:
-		break;
+	} else {
+		cvmx_write_csr(CVMX_CIU_INT_SUM1, mask);
 	}
-
-	cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
 }
 
 /*
- * Enable the irq on the current core for chips that have the EN*_W1{S,C}
+ * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
  * registers.
  */
-static void octeon_irq_ciu0_eoi_mbox_v2(unsigned int irq)
+static void octeon_irq_ciu_disable_all_v2(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	int index = cvmx_get_core_num() * 2;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+	int cpu;
+	u64 mask;
+	union octeon_ciu_chip_data cd;
 
-	if (likely((desc->status & IRQ_DISABLED) == 0))
-		cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+	wmb(); /* Make sure flag changes arrive before register updates. */
+
+	cd.p = data->chip_data;
+	mask = 1ull << (cd.s.bit);
+
+	if (cd.s.line == 0) {
+		for_each_online_cpu(cpu) {
+			int index = octeon_coreid_for_cpu(cpu) * 2;
+			clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
+			cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+		}
+	} else {
+		for_each_online_cpu(cpu) {
+			int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+			clear_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+			cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+		}
+	}
 }
 
 /*
- * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
+ * Enable the irq on the all cores for chips that have the EN*_W1{S,C}
  * registers.
  */
-static void octeon_irq_ciu0_disable_all_v2(unsigned int irq)
+static void octeon_irq_ciu_enable_all_v2(struct irq_data *data)
 {
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
-	int index;
 	int cpu;
-	for_each_online_cpu(cpu) {
-		index = octeon_coreid_for_cpu(cpu) * 2;
-		cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+	u64 mask;
+	union octeon_ciu_chip_data cd;
+
+	cd.p = data->chip_data;
+	mask = 1ull << (cd.s.bit);
+
+	if (cd.s.line == 0) {
+		for_each_online_cpu(cpu) {
+			int index = octeon_coreid_for_cpu(cpu) * 2;
+			set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu0_en_mirror, cpu));
+			cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+		}
+	} else {
+		for_each_online_cpu(cpu) {
+			int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+			set_bit(cd.s.bit, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+			cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+		}
 	}
 }
 
 #ifdef CONFIG_SMP
-static int octeon_irq_ciu0_set_affinity(unsigned int irq, const struct cpumask *dest)
+
+static void octeon_irq_cpu_offline_ciu(struct irq_data *data)
+{
+	int cpu = smp_processor_id();
+	cpumask_t new_affinity;
+
+	if (!cpumask_test_cpu(cpu, data->affinity))
+		return;
+
+	if (cpumask_weight(data->affinity) > 1) {
+		/*
+		 * It has multi CPU affinity, just remove this CPU
+		 * from the affinity set.
+		 */
+		cpumask_copy(&new_affinity, data->affinity);
+		cpumask_clear_cpu(cpu, &new_affinity);
+	} else {
+		/* Otherwise, put it on lowest numbered online CPU. */
+		cpumask_clear(&new_affinity);
+		cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
+	}
+	__irq_set_affinity_locked(data, &new_affinity);
+}
+
+static int octeon_irq_ciu_set_affinity(struct irq_data *data,
+				       const struct cpumask *dest, bool force)
 {
 	int cpu;
-	struct irq_desc *desc = irq_to_desc(irq);
-	int enable_one = (desc->status & IRQ_DISABLED) == 0;
+	bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
 	unsigned long flags;
-	int bit = irq - OCTEON_IRQ_WORKQ0;	/* Bit 0-63 of EN0 */
+	union octeon_ciu_chip_data cd;
+
+	cd.p = data->chip_data;
 
 	/*
 	 * For non-v2 CIU, we will allow only single CPU affinity.
@@ -339,26 +548,40 @@
 	if (cpumask_weight(dest) != 1)
 		return -EINVAL;
 
-	raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
-	for_each_online_cpu(cpu) {
-		int coreid = octeon_coreid_for_cpu(cpu);
-		uint64_t en0 =
-			cvmx_read_csr(CVMX_CIU_INTX_EN0(coreid * 2));
-		if (cpumask_test_cpu(cpu, dest) && enable_one) {
-			enable_one = 0;
-			en0 |= 1ull << bit;
-		} else {
-			en0 &= ~(1ull << bit);
+	if (!enable_one)
+		return 0;
+
+	if (cd.s.line == 0) {
+		raw_spin_lock_irqsave(&octeon_irq_ciu0_lock, flags);
+		for_each_online_cpu(cpu) {
+			int coreid = octeon_coreid_for_cpu(cpu);
+			unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+
+			if (cpumask_test_cpu(cpu, dest) && enable_one) {
+				enable_one = false;
+				set_bit(cd.s.bit, pen);
+			} else {
+				clear_bit(cd.s.bit, pen);
+			}
+			cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), *pen);
 		}
-		cvmx_write_csr(CVMX_CIU_INTX_EN0(coreid * 2), en0);
-	}
-	/*
-	 * We need to do a read after the last update to make sure all
-	 * of them are done.
-	 */
-	cvmx_read_csr(CVMX_CIU_INTX_EN0(cvmx_get_core_num() * 2));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu0_lock, flags);
+	} else {
+		raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
+		for_each_online_cpu(cpu) {
+			int coreid = octeon_coreid_for_cpu(cpu);
+			unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
 
+			if (cpumask_test_cpu(cpu, dest) && enable_one) {
+				enable_one = false;
+				set_bit(cd.s.bit, pen);
+			} else {
+				clear_bit(cd.s.bit, pen);
+			}
+			cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
+		}
+		raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	}
 	return 0;
 }
 
@@ -366,22 +589,46 @@
  * Set affinity for the irq for chips that have the EN*_W1{S,C}
  * registers.
  */
-static int octeon_irq_ciu0_set_affinity_v2(unsigned int irq,
-					   const struct cpumask *dest)
+static int octeon_irq_ciu_set_affinity_v2(struct irq_data *data,
+					  const struct cpumask *dest,
+					  bool force)
 {
 	int cpu;
-	int index;
-	struct irq_desc *desc = irq_to_desc(irq);
-	int enable_one = (desc->status & IRQ_DISABLED) == 0;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WORKQ0);
+	bool enable_one = !irqd_irq_disabled(data) && !irqd_irq_masked(data);
+	u64 mask;
+	union octeon_ciu_chip_data cd;
 
-	for_each_online_cpu(cpu) {
-		index = octeon_coreid_for_cpu(cpu) * 2;
-		if (cpumask_test_cpu(cpu, dest) && enable_one) {
-			enable_one = 0;
-			cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
-		} else {
-			cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+	if (!enable_one)
+		return 0;
+
+	cd.p = data->chip_data;
+	mask = 1ull << cd.s.bit;
+
+	if (cd.s.line == 0) {
+		for_each_online_cpu(cpu) {
+			unsigned long *pen = &per_cpu(octeon_irq_ciu0_en_mirror, cpu);
+			int index = octeon_coreid_for_cpu(cpu) * 2;
+			if (cpumask_test_cpu(cpu, dest) && enable_one) {
+				enable_one = false;
+				set_bit(cd.s.bit, pen);
+				cvmx_write_csr(CVMX_CIU_INTX_EN0_W1S(index), mask);
+			} else {
+				clear_bit(cd.s.bit, pen);
+				cvmx_write_csr(CVMX_CIU_INTX_EN0_W1C(index), mask);
+			}
+		}
+	} else {
+		for_each_online_cpu(cpu) {
+			unsigned long *pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+			int index = octeon_coreid_for_cpu(cpu) * 2 + 1;
+			if (cpumask_test_cpu(cpu, dest) && enable_one) {
+				enable_one = false;
+				set_bit(cd.s.bit, pen);
+				cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+			} else {
+				clear_bit(cd.s.bit, pen);
+				cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+			}
 		}
 	}
 	return 0;
@@ -389,80 +636,102 @@
 #endif
 
 /*
+ * The v1 CIU code already masks things, so supply a dummy version to
+ * the core chip code.
+ */
+static void octeon_irq_dummy_mask(struct irq_data *data)
+{
+}
+
+/*
  * Newer octeon chips have support for lockless CIU operation.
  */
-static struct irq_chip octeon_irq_chip_ciu0_v2 = {
-	.name = "CIU0",
-	.enable = octeon_irq_ciu0_enable_v2,
-	.disable = octeon_irq_ciu0_disable_all_v2,
-	.eoi = octeon_irq_ciu0_enable_v2,
+static struct irq_chip octeon_irq_chip_ciu_v2 = {
+	.name = "CIU",
+	.irq_enable = octeon_irq_ciu_enable_v2,
+	.irq_disable = octeon_irq_ciu_disable_all_v2,
+	.irq_mask = octeon_irq_ciu_disable_local_v2,
+	.irq_unmask = octeon_irq_ciu_enable_v2,
 #ifdef CONFIG_SMP
-	.set_affinity = octeon_irq_ciu0_set_affinity_v2,
+	.irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
+	.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
 #endif
 };
 
-static struct irq_chip octeon_irq_chip_ciu0 = {
-	.name = "CIU0",
-	.enable = octeon_irq_ciu0_enable,
-	.disable = octeon_irq_ciu0_disable,
-	.eoi = octeon_irq_ciu0_eoi,
+static struct irq_chip octeon_irq_chip_ciu_edge_v2 = {
+	.name = "CIU-E",
+	.irq_enable = octeon_irq_ciu_enable_v2,
+	.irq_disable = octeon_irq_ciu_disable_all_v2,
+	.irq_ack = octeon_irq_ciu_ack,
+	.irq_mask = octeon_irq_ciu_disable_local_v2,
+	.irq_unmask = octeon_irq_ciu_enable_v2,
 #ifdef CONFIG_SMP
-	.set_affinity = octeon_irq_ciu0_set_affinity,
+	.irq_set_affinity = octeon_irq_ciu_set_affinity_v2,
+	.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
 #endif
 };
 
-/* The mbox versions don't do any affinity or round-robin. */
-static struct irq_chip octeon_irq_chip_ciu0_mbox_v2 = {
-	.name = "CIU0-M",
-	.enable = octeon_irq_ciu0_enable_mbox_v2,
-	.disable = octeon_irq_ciu0_disable,
-	.eoi = octeon_irq_ciu0_eoi_mbox_v2,
+static struct irq_chip octeon_irq_chip_ciu = {
+	.name = "CIU",
+	.irq_enable = octeon_irq_ciu_enable,
+	.irq_disable = octeon_irq_ciu_disable_all,
+	.irq_mask = octeon_irq_dummy_mask,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = octeon_irq_ciu_set_affinity,
+	.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
+#endif
 };
 
-static struct irq_chip octeon_irq_chip_ciu0_mbox = {
-	.name = "CIU0-M",
-	.enable = octeon_irq_ciu0_enable_mbox,
-	.disable = octeon_irq_ciu0_disable,
-	.eoi = octeon_irq_ciu0_eoi,
+static struct irq_chip octeon_irq_chip_ciu_edge = {
+	.name = "CIU-E",
+	.irq_enable = octeon_irq_ciu_enable,
+	.irq_disable = octeon_irq_ciu_disable_all,
+	.irq_mask = octeon_irq_dummy_mask,
+	.irq_ack = octeon_irq_ciu_ack,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = octeon_irq_ciu_set_affinity,
+	.irq_cpu_offline = octeon_irq_cpu_offline_ciu,
+#endif
 };
 
-static void octeon_irq_ciu1_ack(unsigned int irq)
-{
-	/*
-	 * In order to avoid any locking accessing the CIU, we
-	 * acknowledge CIU interrupts by disabling all of them.  This
-	 * way we can use a per core register and avoid any out of
-	 * core locking requirements.  This has the side affect that
-	 * CIU interrupts can't be processed recursively.  We don't
-	 * need to disable IRQs to make these atomic since they are
-	 * already disabled earlier in the low level interrupt code.
-	 */
-	clear_c0_status(0x100 << 3);
-}
+/* The mbox versions don't do any affinity or round-robin. */
+static struct irq_chip octeon_irq_chip_ciu_mbox_v2 = {
+	.name = "CIU-M",
+	.irq_enable = octeon_irq_ciu_enable_all_v2,
+	.irq_disable = octeon_irq_ciu_disable_all_v2,
+	.irq_ack = octeon_irq_ciu_disable_local_v2,
+	.irq_eoi = octeon_irq_ciu_enable_local_v2,
 
-static void octeon_irq_ciu1_eoi(unsigned int irq)
-{
-	/*
-	 * Enable all CIU interrupts again.  We don't need to disable
-	 * IRQs to make these atomic since they are already disabled
-	 * earlier in the low level interrupt code.
-	 */
-	set_c0_status(0x100 << 3);
-}
+	.irq_cpu_online = octeon_irq_ciu_enable_local_v2,
+	.irq_cpu_offline = octeon_irq_ciu_disable_local_v2,
+	.flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
 
-static void octeon_irq_ciu1_enable(unsigned int irq)
+static struct irq_chip octeon_irq_chip_ciu_mbox = {
+	.name = "CIU-M",
+	.irq_enable = octeon_irq_ciu_enable_all,
+	.irq_disable = octeon_irq_ciu_disable_all,
+
+	.irq_cpu_online = octeon_irq_ciu_enable_local,
+	.irq_cpu_offline = octeon_irq_ciu_disable_local,
+	.flags = IRQCHIP_ONOFFLINE_ENABLED,
+};
+
+/*
+ * Watchdog interrupts are special.  They are associated with a single
+ * core, so we hardwire the affinity to that core.
+ */
+static void octeon_irq_ciu_wd_enable(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-	int coreid = next_coreid_for_irq(desc);
 	unsigned long flags;
-	uint64_t en1;
-	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
+	unsigned long *pen;
+	int coreid = data->irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
+	int cpu = octeon_cpu_for_coreid(coreid);
 
 	raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-	en1 |= 1ull << bit;
-	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
+	pen = &per_cpu(octeon_irq_ciu1_en_mirror, cpu);
+	set_bit(coreid, pen);
+	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), *pen);
 	raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
 }
 
@@ -470,286 +739,281 @@
  * Watchdog interrupts are special.  They are associated with a single
  * core, so we hardwire the affinity to that core.
  */
-static void octeon_irq_ciu1_wd_enable(unsigned int irq)
+static void octeon_irq_ciu1_wd_enable_v2(struct irq_data *data)
 {
-	unsigned long flags;
-	uint64_t en1;
-	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
-	int coreid = bit;
+	int coreid = data->irq - OCTEON_IRQ_WDOG0;
+	int cpu = octeon_cpu_for_coreid(coreid);
 
-	raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-	en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-	en1 |= 1ull << bit;
-	cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-	cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	set_bit(coreid, &per_cpu(octeon_irq_ciu1_en_mirror, cpu));
+	cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(coreid * 2 + 1), 1ull << coreid);
 }
 
-static void octeon_irq_ciu1_disable(unsigned int irq)
+
+static struct irq_chip octeon_irq_chip_ciu_wd_v2 = {
+	.name = "CIU-W",
+	.irq_enable = octeon_irq_ciu1_wd_enable_v2,
+	.irq_disable = octeon_irq_ciu_disable_all_v2,
+	.irq_mask = octeon_irq_ciu_disable_local_v2,
+	.irq_unmask = octeon_irq_ciu_enable_local_v2,
+};
+
+static struct irq_chip octeon_irq_chip_ciu_wd = {
+	.name = "CIU-W",
+	.irq_enable = octeon_irq_ciu_wd_enable,
+	.irq_disable = octeon_irq_ciu_disable_all,
+	.irq_mask = octeon_irq_dummy_mask,
+};
+
+static void octeon_irq_ip2_v1(void)
 {
-	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
-	unsigned long flags;
-	uint64_t en1;
-	int cpu;
-	raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-	for_each_online_cpu(cpu) {
-		int coreid = octeon_coreid_for_cpu(cpu);
-		en1 = cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-		en1 &= ~(1ull << bit);
-		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
+	const unsigned long core_id = cvmx_get_core_num();
+	u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2));
+
+	ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror);
+	clear_c0_status(STATUSF_IP2);
+	if (likely(ciu_sum)) {
+		int bit = fls64(ciu_sum) - 1;
+		int irq = octeon_irq_ciu_to_irq[0][bit];
+		if (likely(irq))
+			do_IRQ(irq);
+		else
+			spurious_interrupt();
+	} else {
+		spurious_interrupt();
 	}
-	/*
-	 * We need to do a read after the last update to make sure all
-	 * of them are done.
-	 */
-	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+	set_c0_status(STATUSF_IP2);
 }
 
-/*
- * Enable the irq on the current core for chips that have the EN*_W1{S,C}
- * registers.
- */
-static void octeon_irq_ciu1_enable_v2(unsigned int irq)
+static void octeon_irq_ip2_v2(void)
 {
-	int index;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-	struct irq_desc *desc = irq_to_desc(irq);
+	const unsigned long core_id = cvmx_get_core_num();
+	u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INTX_SUM0(core_id * 2));
 
-	if ((desc->status & IRQ_DISABLED) == 0) {
-		index = next_coreid_for_irq(desc) * 2 + 1;
-		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+	ciu_sum &= __get_cpu_var(octeon_irq_ciu0_en_mirror);
+	if (likely(ciu_sum)) {
+		int bit = fls64(ciu_sum) - 1;
+		int irq = octeon_irq_ciu_to_irq[0][bit];
+		if (likely(irq))
+			do_IRQ(irq);
+		else
+			spurious_interrupt();
+	} else {
+		spurious_interrupt();
 	}
 }
-
-/*
- * Watchdog interrupts are special.  They are associated with a single
- * core, so we hardwire the affinity to that core.
- */
-static void octeon_irq_ciu1_wd_enable_v2(unsigned int irq)
+static void octeon_irq_ip3_v1(void)
 {
-	int index;
-	int coreid = irq - OCTEON_IRQ_WDOG0;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-	struct irq_desc *desc = irq_to_desc(irq);
+	u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
 
-	if ((desc->status & IRQ_DISABLED) == 0) {
-		index = coreid * 2 + 1;
-		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
+	ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror);
+	clear_c0_status(STATUSF_IP3);
+	if (likely(ciu_sum)) {
+		int bit = fls64(ciu_sum) - 1;
+		int irq = octeon_irq_ciu_to_irq[1][bit];
+		if (likely(irq))
+			do_IRQ(irq);
+		else
+			spurious_interrupt();
+	} else {
+		spurious_interrupt();
 	}
+	set_c0_status(STATUSF_IP3);
 }
 
-/*
- * Disable the irq on the current core for chips that have the EN*_W1{S,C}
- * registers.
- */
-static void octeon_irq_ciu1_ack_v2(unsigned int irq)
+static void octeon_irq_ip3_v2(void)
 {
-	int index = cvmx_get_core_num() * 2 + 1;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
+	u64 ciu_sum = cvmx_read_csr(CVMX_CIU_INT_SUM1);
 
-	cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
+	ciu_sum &= __get_cpu_var(octeon_irq_ciu1_en_mirror);
+	if (likely(ciu_sum)) {
+		int bit = fls64(ciu_sum) - 1;
+		int irq = octeon_irq_ciu_to_irq[1][bit];
+		if (likely(irq))
+			do_IRQ(irq);
+		else
+			spurious_interrupt();
+	} else {
+		spurious_interrupt();
+	}
 }
 
-/*
- * Disable the irq on the all cores for chips that have the EN*_W1{S,C}
- * registers.
- */
-static void octeon_irq_ciu1_disable_all_v2(unsigned int irq)
+static void octeon_irq_ip4_mask(void)
 {
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-	int index;
-	int cpu;
-	for_each_online_cpu(cpu) {
-		index = octeon_coreid_for_cpu(cpu) * 2 + 1;
-		cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
-	}
+	clear_c0_status(STATUSF_IP4);
+	spurious_interrupt();
 }
 
-#ifdef CONFIG_SMP
-static int octeon_irq_ciu1_set_affinity(unsigned int irq,
-					const struct cpumask *dest)
+static void (*octeon_irq_ip2)(void);
+static void (*octeon_irq_ip3)(void);
+static void (*octeon_irq_ip4)(void);
+
+void __cpuinitdata (*octeon_irq_setup_secondary)(void);
+
+static void __cpuinit octeon_irq_percpu_enable(void)
 {
-	int cpu;
-	struct irq_desc *desc = irq_to_desc(irq);
-	int enable_one = (desc->status & IRQ_DISABLED) == 0;
-	unsigned long flags;
-	int bit = irq - OCTEON_IRQ_WDOG0;	/* Bit 0-63 of EN1 */
+	irq_cpu_online();
+}
 
+static void __cpuinit octeon_irq_init_ciu_percpu(void)
+{
+	int coreid = cvmx_get_core_num();
 	/*
-	 * For non-v2 CIU, we will allow only single CPU affinity.
-	 * This removes the need to do locking in the .ack/.eoi
-	 * functions.
+	 * Disable All CIU Interrupts. The ones we need will be
+	 * enabled later.  Read the SUM register so we know the write
+	 * completed.
 	 */
-	if (cpumask_weight(dest) != 1)
-		return -EINVAL;
+	cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0);
+	cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
+	cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
+	cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
+	cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
+}
 
-	raw_spin_lock_irqsave(&octeon_irq_ciu1_lock, flags);
-	for_each_online_cpu(cpu) {
-		int coreid = octeon_coreid_for_cpu(cpu);
-		uint64_t en1 =
-			cvmx_read_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1));
-		if (cpumask_test_cpu(cpu, dest) && enable_one) {
-			enable_one = 0;
-			en1 |= 1ull << bit;
-		} else {
-			en1 &= ~(1ull << bit);
-		}
-		cvmx_write_csr(CVMX_CIU_INTX_EN1(coreid * 2 + 1), en1);
-	}
-	/*
-	 * We need to do a read after the last update to make sure all
-	 * of them are done.
-	 */
-	cvmx_read_csr(CVMX_CIU_INTX_EN1(cvmx_get_core_num() * 2 + 1));
-	raw_spin_unlock_irqrestore(&octeon_irq_ciu1_lock, flags);
+static void __cpuinit octeon_irq_setup_secondary_ciu(void)
+{
 
-	return 0;
+	__get_cpu_var(octeon_irq_ciu0_en_mirror) = 0;
+	__get_cpu_var(octeon_irq_ciu1_en_mirror) = 0;
+
+	octeon_irq_init_ciu_percpu();
+	octeon_irq_percpu_enable();
+
+	/* Enable the CIU lines */
+	set_c0_status(STATUSF_IP3 | STATUSF_IP2);
+	clear_c0_status(STATUSF_IP4);
 }
 
-/*
- * Set affinity for the irq for chips that have the EN*_W1{S,C}
- * registers.
- */
-static int octeon_irq_ciu1_set_affinity_v2(unsigned int irq,
-					   const struct cpumask *dest)
+static void __init octeon_irq_init_ciu(void)
 {
-	int cpu;
-	int index;
-	struct irq_desc *desc = irq_to_desc(irq);
-	int enable_one = (desc->status & IRQ_DISABLED) == 0;
-	u64 mask = 1ull << (irq - OCTEON_IRQ_WDOG0);
-	for_each_online_cpu(cpu) {
-		index = octeon_coreid_for_cpu(cpu) * 2 + 1;
-		if (cpumask_test_cpu(cpu, dest) && enable_one) {
-			enable_one = 0;
-			cvmx_write_csr(CVMX_CIU_INTX_EN1_W1S(index), mask);
-		} else {
-			cvmx_write_csr(CVMX_CIU_INTX_EN1_W1C(index), mask);
-		}
+	unsigned int i;
+	struct irq_chip *chip;
+	struct irq_chip *chip_edge;
+	struct irq_chip *chip_mbox;
+	struct irq_chip *chip_wd;
+
+	octeon_irq_init_ciu_percpu();
+	octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
+
+	if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
+	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
+	    OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X) ||
+	    OCTEON_IS_MODEL(OCTEON_CN6XXX)) {
+		octeon_irq_ip2 = octeon_irq_ip2_v2;
+		octeon_irq_ip3 = octeon_irq_ip3_v2;
+		chip = &octeon_irq_chip_ciu_v2;
+		chip_edge = &octeon_irq_chip_ciu_edge_v2;
+		chip_mbox = &octeon_irq_chip_ciu_mbox_v2;
+		chip_wd = &octeon_irq_chip_ciu_wd_v2;
+	} else {
+		octeon_irq_ip2 = octeon_irq_ip2_v1;
+		octeon_irq_ip3 = octeon_irq_ip3_v1;
+		chip = &octeon_irq_chip_ciu;
+		chip_edge = &octeon_irq_chip_ciu_edge;
+		chip_mbox = &octeon_irq_chip_ciu_mbox;
+		chip_wd = &octeon_irq_chip_ciu_wd;
 	}
-	return 0;
-}
-#endif
+	octeon_irq_ip4 = octeon_irq_ip4_mask;
 
-/*
- * Newer octeon chips have support for lockless CIU operation.
- */
-static struct irq_chip octeon_irq_chip_ciu1_v2 = {
-	.name = "CIU1",
-	.enable = octeon_irq_ciu1_enable_v2,
-	.disable = octeon_irq_ciu1_disable_all_v2,
-	.eoi = octeon_irq_ciu1_enable_v2,
-#ifdef CONFIG_SMP
-	.set_affinity = octeon_irq_ciu1_set_affinity_v2,
-#endif
-};
+	/* Mips internal */
+	octeon_irq_init_core();
 
-static struct irq_chip octeon_irq_chip_ciu1 = {
-	.name = "CIU1",
-	.enable = octeon_irq_ciu1_enable,
-	.disable = octeon_irq_ciu1_disable,
-	.eoi = octeon_irq_ciu1_eoi,
-#ifdef CONFIG_SMP
-	.set_affinity = octeon_irq_ciu1_set_affinity,
-#endif
-};
+	/* CIU_0 */
+	for (i = 0; i < 16; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
+	for (i = 0; i < 16; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GPIO0, 0, i + 16, chip, handle_level_irq);
 
-static struct irq_chip octeon_irq_chip_ciu1_wd_v2 = {
-	.name = "CIU1-W",
-	.enable = octeon_irq_ciu1_wd_enable_v2,
-	.disable = octeon_irq_ciu1_disable_all_v2,
-	.eoi = octeon_irq_ciu1_wd_enable_v2,
-};
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
 
-static struct irq_chip octeon_irq_chip_ciu1_wd = {
-	.name = "CIU1-W",
-	.enable = octeon_irq_ciu1_wd_enable,
-	.disable = octeon_irq_ciu1_disable,
-	.eoi = octeon_irq_ciu1_eoi,
-};
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART0, 0, 34, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART1, 0, 35, chip, handle_level_irq);
 
-static void (*octeon_ciu0_ack)(unsigned int);
-static void (*octeon_ciu1_ack)(unsigned int);
+	for (i = 0; i < 4; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
+	for (i = 0; i < 4; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
 
-void __init arch_init_irq(void)
-{
-	unsigned int irq;
-	struct irq_chip *chip0;
-	struct irq_chip *chip0_mbox;
-	struct irq_chip *chip1;
-	struct irq_chip *chip1_wd;
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI, 0, 45, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TRACE0, 0, 47, chip, handle_level_irq);
 
-#ifdef CONFIG_SMP
-	/* Set the default affinity to the boot cpu. */
-	cpumask_clear(irq_default_affinity);
-	cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
-#endif
+	for (i = 0; i < 2; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_GMX_DRP0, 0, i + 48, chip_edge, handle_edge_irq);
 
-	if (NR_IRQS < OCTEON_IRQ_LAST)
-		pr_err("octeon_irq_init: NR_IRQS is set too low\n");
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD_DRP, 0, 50, chip_edge, handle_edge_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY_ZERO, 0, 51, chip_edge, handle_edge_irq);
 
-	if (OCTEON_IS_MODEL(OCTEON_CN58XX_PASS2_X) ||
-	    OCTEON_IS_MODEL(OCTEON_CN56XX_PASS2_X) ||
-	    OCTEON_IS_MODEL(OCTEON_CN52XX_PASS2_X)) {
-		octeon_ciu0_ack = octeon_irq_ciu0_ack_v2;
-		octeon_ciu1_ack = octeon_irq_ciu1_ack_v2;
-		chip0 = &octeon_irq_chip_ciu0_v2;
-		chip0_mbox = &octeon_irq_chip_ciu0_mbox_v2;
-		chip1 = &octeon_irq_chip_ciu1_v2;
-		chip1_wd = &octeon_irq_chip_ciu1_wd_v2;
-	} else {
-		octeon_ciu0_ack = octeon_irq_ciu0_ack;
-		octeon_ciu1_ack = octeon_irq_ciu1_ack;
-		chip0 = &octeon_irq_chip_ciu0;
-		chip0_mbox = &octeon_irq_chip_ciu0_mbox;
-		chip1 = &octeon_irq_chip_ciu1;
-		chip1_wd = &octeon_irq_chip_ciu1_wd;
-	}
+	for (i = 0; i < 4; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip_edge, handle_edge_irq);
 
-	/* 0 - 15 reserved for i8259 master and slave controller. */
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PCM, 0, 57, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MPI, 0, 58, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TWSI2, 0, 59, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POWIQ, 0, 60, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPDPPTHR, 0, 61, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII0, 0, 62, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
 
-	/* 17 - 23 Mips internal */
-	for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++) {
-		set_irq_chip_and_handler(irq, &octeon_irq_chip_core,
-					 handle_percpu_irq);
-	}
+	/* CIU_1 */
+	for (i = 0; i < 16; i++)
+		octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
 
-	/* 24 - 87 CIU_INT_SUM0 */
-	for (irq = OCTEON_IRQ_WORKQ0; irq <= OCTEON_IRQ_BOOTDMA; irq++) {
-		switch (irq) {
-		case OCTEON_IRQ_MBOX0:
-		case OCTEON_IRQ_MBOX1:
-			set_irq_chip_and_handler(irq, chip0_mbox, handle_percpu_irq);
-			break;
-		default:
-			set_irq_chip_and_handler(irq, chip0, handle_fasteoi_irq);
-			break;
-		}
-	}
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_UART2, 1, 16, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MII1, 1, 18, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_NAND, 1, 19, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_MIO, 1, 20, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IOB, 1, 21, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_FPA, 1, 22, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_POW, 1, 23, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_L2C, 1, 24, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_IPD, 1, 25, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PIP, 1, 26, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PKO, 1, 27, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_ZIP, 1, 28, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_TIM, 1, 29, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RAD, 1, 30, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_KEY, 1, 31, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFA, 1, 32, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_USBCTL, 1, 33, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SLI, 1, 34, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DPI, 1, 35, chip, handle_level_irq);
 
-	/* 88 - 151 CIU_INT_SUM1 */
-	for (irq = OCTEON_IRQ_WDOG0; irq <= OCTEON_IRQ_WDOG15; irq++)
-		set_irq_chip_and_handler(irq, chip1_wd, handle_fasteoi_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGX0, 1, 36, chip, handle_level_irq);
 
-	for (irq = OCTEON_IRQ_UART2; irq <= OCTEON_IRQ_RESERVED151; irq++)
-		set_irq_chip_and_handler(irq, chip1, handle_fasteoi_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_AGL, 1, 46, chip, handle_level_irq);
 
-	set_c0_status(0x300 << 2);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PTP, 1, 47, chip_edge, handle_edge_irq);
+
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM0, 1, 48, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_PEM1, 1, 49, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO0, 1, 50, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_SRIO1, 1, 51, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_LMC0, 1, 52, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_DFM, 1, 56, chip, handle_level_irq);
+	octeon_irq_set_ciu_mapping(OCTEON_IRQ_RST, 1, 63, chip, handle_level_irq);
+
+	/* Enable the CIU lines */
+	set_c0_status(STATUSF_IP3 | STATUSF_IP2);
+	clear_c0_status(STATUSF_IP4);
+}
+
+void __init arch_init_irq(void)
+{
+#ifdef CONFIG_SMP
+	/* Set the default affinity to the boot cpu. */
+	cpumask_clear(irq_default_affinity);
+	cpumask_set_cpu(smp_processor_id(), irq_default_affinity);
+#endif
+	octeon_irq_init_ciu();
 }
 
 asmlinkage void plat_irq_dispatch(void)
 {
-	const unsigned long core_id = cvmx_get_core_num();
-	const uint64_t ciu_sum0_address = CVMX_CIU_INTX_SUM0(core_id * 2);
-	const uint64_t ciu_en0_address = CVMX_CIU_INTX_EN0(core_id * 2);
-	const uint64_t ciu_sum1_address = CVMX_CIU_INT_SUM1;
-	const uint64_t ciu_en1_address = CVMX_CIU_INTX_EN1(core_id * 2 + 1);
 	unsigned long cop0_cause;
 	unsigned long cop0_status;
-	uint64_t ciu_en;
-	uint64_t ciu_sum;
-	unsigned int irq;
 
 	while (1) {
 		cop0_cause = read_c0_cause();
@@ -757,33 +1021,16 @@
 		cop0_cause &= cop0_status;
 		cop0_cause &= ST0_IM;
 
-		if (unlikely(cop0_cause & STATUSF_IP2)) {
-			ciu_sum = cvmx_read_csr(ciu_sum0_address);
-			ciu_en = cvmx_read_csr(ciu_en0_address);
-			ciu_sum &= ciu_en;
-			if (likely(ciu_sum)) {
-				irq = fls64(ciu_sum) + OCTEON_IRQ_WORKQ0 - 1;
-				octeon_ciu0_ack(irq);
-				do_IRQ(irq);
-			} else {
-				spurious_interrupt();
-			}
-		} else if (unlikely(cop0_cause & STATUSF_IP3)) {
-			ciu_sum = cvmx_read_csr(ciu_sum1_address);
-			ciu_en = cvmx_read_csr(ciu_en1_address);
-			ciu_sum &= ciu_en;
-			if (likely(ciu_sum)) {
-				irq = fls64(ciu_sum) + OCTEON_IRQ_WDOG0 - 1;
-				octeon_ciu1_ack(irq);
-				do_IRQ(irq);
-			} else {
-				spurious_interrupt();
-			}
-		} else if (likely(cop0_cause)) {
+		if (unlikely(cop0_cause & STATUSF_IP2))
+			octeon_irq_ip2();
+		else if (unlikely(cop0_cause & STATUSF_IP3))
+			octeon_irq_ip3();
+		else if (unlikely(cop0_cause & STATUSF_IP4))
+			octeon_irq_ip4();
+		else if (likely(cop0_cause))
 			do_IRQ(fls(cop0_cause) - 9 + MIPS_CPU_IRQ_BASE);
-		} else {
+		else
 			break;
-		}
 	}
 }
 
@@ -791,83 +1038,7 @@
 
 void fixup_irqs(void)
 {
-	int irq;
-	struct irq_desc *desc;
-	cpumask_t new_affinity;
-	unsigned long flags;
-	int do_set_affinity;
-	int cpu;
-
-	cpu = smp_processor_id();
-
-	for (irq = OCTEON_IRQ_SW0; irq <= OCTEON_IRQ_TIMER; irq++)
-		octeon_irq_core_disable_local(irq);
-
-	for (irq = OCTEON_IRQ_WORKQ0; irq < OCTEON_IRQ_LAST; irq++) {
-		desc = irq_to_desc(irq);
-		switch (irq) {
-		case OCTEON_IRQ_MBOX0:
-		case OCTEON_IRQ_MBOX1:
-			/* The eoi function will disable them on this CPU. */
-			desc->chip->eoi(irq);
-			break;
-		case OCTEON_IRQ_WDOG0:
-		case OCTEON_IRQ_WDOG1:
-		case OCTEON_IRQ_WDOG2:
-		case OCTEON_IRQ_WDOG3:
-		case OCTEON_IRQ_WDOG4:
-		case OCTEON_IRQ_WDOG5:
-		case OCTEON_IRQ_WDOG6:
-		case OCTEON_IRQ_WDOG7:
-		case OCTEON_IRQ_WDOG8:
-		case OCTEON_IRQ_WDOG9:
-		case OCTEON_IRQ_WDOG10:
-		case OCTEON_IRQ_WDOG11:
-		case OCTEON_IRQ_WDOG12:
-		case OCTEON_IRQ_WDOG13:
-		case OCTEON_IRQ_WDOG14:
-		case OCTEON_IRQ_WDOG15:
-			/*
-			 * These have special per CPU semantics and
-			 * are handled in the watchdog driver.
-			 */
-			break;
-		default:
-			raw_spin_lock_irqsave(&desc->lock, flags);
-			/*
-			 * If this irq has an action, it is in use and
-			 * must be migrated if it has affinity to this
-			 * cpu.
-			 */
-			if (desc->action && cpumask_test_cpu(cpu, desc->affinity)) {
-				if (cpumask_weight(desc->affinity) > 1) {
-					/*
-					 * It has multi CPU affinity,
-					 * just remove this CPU from
-					 * the affinity set.
-					 */
-					cpumask_copy(&new_affinity, desc->affinity);
-					cpumask_clear_cpu(cpu, &new_affinity);
-				} else {
-					/*
-					 * Otherwise, put it on lowest
-					 * numbered online CPU.
-					 */
-					cpumask_clear(&new_affinity);
-					cpumask_set_cpu(cpumask_first(cpu_online_mask), &new_affinity);
-				}
-				do_set_affinity = 1;
-			} else {
-				do_set_affinity = 0;
-			}
-			raw_spin_unlock_irqrestore(&desc->lock, flags);
-
-			if (do_set_affinity)
-				irq_set_affinity(irq, &new_affinity);
-
-			break;
-		}
-	}
+	irq_cpu_offline();
 }
 
 #endif /* CONFIG_HOTPLUG_CPU */
diff -druN linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/octeon-platform.c linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/octeon-platform.c
--- linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/octeon-platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/octeon-platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 		 * zero.
 		 */
 
-		/* Asume that CS1 immediately follows. */
+		/* Assume that CS1 immediately follows. */
 		mio_boot_reg_cfg.u64 =
 			cvmx_read_csr(CVMX_MIO_BOOT_REG_CFGX(i + 1));
 		region_base = mio_boot_reg_cfg.s.base << 16;
diff -druN linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/setup.c linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/setup.c
--- linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -420,7 +420,6 @@
 void __init prom_init(void)
 {
 	struct cvmx_sysinfo *sysinfo;
-	const int coreid = cvmx_get_core_num();
 	int i;
 	int argc;
 #ifdef CONFIG_CAVIUM_RESERVE32
@@ -537,17 +536,6 @@
 
 	octeon_uart = octeon_get_boot_uart();
 
-	/*
-	 * Disable All CIU Interrupts. The ones we need will be
-	 * enabled later.  Read the SUM register so we know the write
-	 * completed.
-	 */
-	cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), 0);
-	cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
-	cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
-	cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
-	cvmx_read_csr(CVMX_CIU_INTX_SUM0((coreid * 2)));
-
 #ifdef CONFIG_SMP
 	octeon_write_lcd("LinuxSMP");
 #else
@@ -674,7 +662,7 @@
 	 * some memory vectors. When SPARSEMEM is in use, it doesn't
 	 * verify that the size is big enough for the final
 	 * vectors. Making the smallest chuck 4MB seems to be enough
-	 * to consistantly work.
+	 * to consistently work.
 	 */
 	mem_alloc_size = 4 << 20;
 	if (mem_alloc_size > MAX_MEMORY)
diff -druN linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/smp.c linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/smp.c
--- linux-libre-2.6.38-gnu/arch/mips/cavium-octeon/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/cavium-octeon/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,41 +171,19 @@
  * After we've done initial boot, this function is called to allow the
  * board code to clean up state, if needed
  */
-static void octeon_init_secondary(void)
+static void __cpuinit octeon_init_secondary(void)
 {
-	const int coreid = cvmx_get_core_num();
-	union cvmx_ciu_intx_sum0 interrupt_enable;
 	unsigned int sr;
 
-#ifdef CONFIG_HOTPLUG_CPU
-	struct linux_app_boot_info *labi;
-
-	labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
-
-	if (labi->labi_signature != LABI_SIGNATURE)
-		panic("The bootloader version on this board is incorrect.");
-#endif
-
 	sr = set_c0_status(ST0_BEV);
 	write_c0_ebase((u32)ebase);
 	write_c0_status(sr);
 
 	octeon_check_cpu_bist();
 	octeon_init_cvmcount();
-	/*
-	pr_info("SMP: CPU%d (CoreId %lu) started\n", cpu, coreid);
-	*/
-	/* Enable Mailbox interrupts to this core. These are the only
-	   interrupts allowed on line 3 */
-	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(coreid), 0xffffffff);
-	interrupt_enable.u64 = 0;
-	interrupt_enable.s.mbox = 0x3;
-	cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2)), interrupt_enable.u64);
-	cvmx_write_csr(CVMX_CIU_INTX_EN0((coreid * 2 + 1)), 0);
-	cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2)), 0);
-	cvmx_write_csr(CVMX_CIU_INTX_EN1((coreid * 2 + 1)), 0);
-	/* Enable core interrupt processing for 2,3 and 7 */
-	set_c0_status(0x8c01);
+
+	octeon_irq_setup_secondary();
+	raw_local_irq_enable();
 }
 
 /**
@@ -214,6 +192,15 @@
  */
 void octeon_prepare_cpus(unsigned int max_cpus)
 {
+#ifdef CONFIG_HOTPLUG_CPU
+	struct linux_app_boot_info *labi;
+
+	labi = (struct linux_app_boot_info *)PHYS_TO_XKSEG_CACHED(LABI_ADDR_IN_BOOTLOADER);
+
+	if (labi->labi_signature != LABI_SIGNATURE)
+		panic("The bootloader version on this board is incorrect.");
+#endif
+
 	cvmx_write_csr(CVMX_CIU_MBOX_CLRX(cvmx_get_core_num()), 0xffffffff);
 	if (request_irq(OCTEON_IRQ_MBOX0, mailbox_interrupt, IRQF_DISABLED,
 			"mailbox0", mailbox_interrupt)) {
diff -druN linux-libre-2.6.38-gnu/arch/mips/dec/ioasic-irq.c linux-libre-2.6.39-gnu/arch/mips/dec/ioasic-irq.c
--- linux-libre-2.6.38-gnu/arch/mips/dec/ioasic-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/dec/ioasic-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,80 +17,48 @@
 #include <asm/dec/ioasic_addrs.h>
 #include <asm/dec/ioasic_ints.h>
 
-
 static int ioasic_irq_base;
 
-
-static inline void unmask_ioasic_irq(unsigned int irq)
+static void unmask_ioasic_irq(struct irq_data *d)
 {
 	u32 simr;
 
 	simr = ioasic_read(IO_REG_SIMR);
-	simr |= (1 << (irq - ioasic_irq_base));
+	simr |= (1 << (d->irq - ioasic_irq_base));
 	ioasic_write(IO_REG_SIMR, simr);
 }
 
-static inline void mask_ioasic_irq(unsigned int irq)
+static void mask_ioasic_irq(struct irq_data *d)
 {
 	u32 simr;
 
 	simr = ioasic_read(IO_REG_SIMR);
-	simr &= ~(1 << (irq - ioasic_irq_base));
+	simr &= ~(1 << (d->irq - ioasic_irq_base));
 	ioasic_write(IO_REG_SIMR, simr);
 }
 
-static inline void clear_ioasic_irq(unsigned int irq)
-{
-	u32 sir;
-
-	sir = ~(1 << (irq - ioasic_irq_base));
-	ioasic_write(IO_REG_SIR, sir);
-}
-
-static inline void ack_ioasic_irq(unsigned int irq)
+static void ack_ioasic_irq(struct irq_data *d)
 {
-	mask_ioasic_irq(irq);
+	mask_ioasic_irq(d);
 	fast_iob();
 }
 
-static inline void end_ioasic_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		unmask_ioasic_irq(irq);
-}
-
 static struct irq_chip ioasic_irq_type = {
 	.name = "IO-ASIC",
-	.ack = ack_ioasic_irq,
-	.mask = mask_ioasic_irq,
-	.mask_ack = ack_ioasic_irq,
-	.unmask = unmask_ioasic_irq,
+	.irq_ack = ack_ioasic_irq,
+	.irq_mask = mask_ioasic_irq,
+	.irq_mask_ack = ack_ioasic_irq,
+	.irq_unmask = unmask_ioasic_irq,
 };
 
-
-#define unmask_ioasic_dma_irq unmask_ioasic_irq
-
-#define mask_ioasic_dma_irq mask_ioasic_irq
-
-#define ack_ioasic_dma_irq ack_ioasic_irq
-
-static inline void end_ioasic_dma_irq(unsigned int irq)
-{
-	clear_ioasic_irq(irq);
-	fast_iob();
-	end_ioasic_irq(irq);
-}
-
 static struct irq_chip ioasic_dma_irq_type = {
 	.name = "IO-ASIC-DMA",
-	.ack = ack_ioasic_dma_irq,
-	.mask = mask_ioasic_dma_irq,
-	.mask_ack = ack_ioasic_dma_irq,
-	.unmask = unmask_ioasic_dma_irq,
-	.end = end_ioasic_dma_irq,
+	.irq_ack = ack_ioasic_irq,
+	.irq_mask = mask_ioasic_irq,
+	.irq_mask_ack = ack_ioasic_irq,
+	.irq_unmask = unmask_ioasic_irq,
 };
 
-
 void __init init_ioasic_irqs(int base)
 {
 	int i;
@@ -100,10 +68,10 @@
 	fast_iob();
 
 	for (i = base; i < base + IO_INR_DMA; i++)
-		set_irq_chip_and_handler(i, &ioasic_irq_type,
+		irq_set_chip_and_handler(i, &ioasic_irq_type,
 					 handle_level_irq);
 	for (; i < base + IO_IRQ_LINES; i++)
-		set_irq_chip(i, &ioasic_dma_irq_type);
+		irq_set_chip(i, &ioasic_dma_irq_type);
 
 	ioasic_irq_base = base;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/dec/kn02-irq.c linux-libre-2.6.39-gnu/arch/mips/dec/kn02-irq.c
--- linux-libre-2.6.38-gnu/arch/mips/dec/kn02-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/dec/kn02-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,43 +27,40 @@
  */
 u32 cached_kn02_csr;
 
-
 static int kn02_irq_base;
 
-
-static inline void unmask_kn02_irq(unsigned int irq)
+static void unmask_kn02_irq(struct irq_data *d)
 {
 	volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
 						       KN02_CSR);
 
-	cached_kn02_csr |= (1 << (irq - kn02_irq_base + 16));
+	cached_kn02_csr |= (1 << (d->irq - kn02_irq_base + 16));
 	*csr = cached_kn02_csr;
 }
 
-static inline void mask_kn02_irq(unsigned int irq)
+static void mask_kn02_irq(struct irq_data *d)
 {
 	volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
 						       KN02_CSR);
 
-	cached_kn02_csr &= ~(1 << (irq - kn02_irq_base + 16));
+	cached_kn02_csr &= ~(1 << (d->irq - kn02_irq_base + 16));
 	*csr = cached_kn02_csr;
 }
 
-static void ack_kn02_irq(unsigned int irq)
+static void ack_kn02_irq(struct irq_data *d)
 {
-	mask_kn02_irq(irq);
+	mask_kn02_irq(d);
 	iob();
 }
 
 static struct irq_chip kn02_irq_type = {
 	.name = "KN02-CSR",
-	.ack = ack_kn02_irq,
-	.mask = mask_kn02_irq,
-	.mask_ack = ack_kn02_irq,
-	.unmask = unmask_kn02_irq,
+	.irq_ack = ack_kn02_irq,
+	.irq_mask = mask_kn02_irq,
+	.irq_mask_ack = ack_kn02_irq,
+	.irq_unmask = unmask_kn02_irq,
 };
 
-
 void __init init_kn02_irqs(int base)
 {
 	volatile u32 *csr = (volatile u32 *)CKSEG1ADDR(KN02_SLOT_BASE +
@@ -76,7 +73,7 @@
 	iob();
 
 	for (i = base; i < base + KN02_IRQ_LINES; i++)
-		set_irq_chip_and_handler(i, &kn02_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &kn02_irq_type, handle_level_irq);
 
 	kn02_irq_base = base;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/emma/markeins/irq.c linux-libre-2.6.39-gnu/arch/mips/emma/markeins/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/emma/markeins/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/emma/markeins/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,13 +34,10 @@
 
 #include <asm/emma/emma2rh.h>
 
-static void emma2rh_irq_enable(unsigned int irq)
+static void emma2rh_irq_enable(struct irq_data *d)
 {
-	u32 reg_value;
-	u32 reg_bitmask;
-	u32 reg_index;
-
-	irq -= EMMA2RH_IRQ_BASE;
+	unsigned int irq = d->irq - EMMA2RH_IRQ_BASE;
+	u32 reg_value, reg_bitmask, reg_index;
 
 	reg_index = EMMA2RH_BHIF_INT_EN_0 +
 		    (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
@@ -49,13 +46,10 @@
 	emma2rh_out32(reg_index, reg_value | reg_bitmask);
 }
 
-static void emma2rh_irq_disable(unsigned int irq)
+static void emma2rh_irq_disable(struct irq_data *d)
 {
-	u32 reg_value;
-	u32 reg_bitmask;
-	u32 reg_index;
-
-	irq -= EMMA2RH_IRQ_BASE;
+	unsigned int irq = d->irq - EMMA2RH_IRQ_BASE;
+	u32 reg_value, reg_bitmask, reg_index;
 
 	reg_index = EMMA2RH_BHIF_INT_EN_0 +
 		    (EMMA2RH_BHIF_INT_EN_1 - EMMA2RH_BHIF_INT_EN_0) * (irq / 32);
@@ -66,10 +60,8 @@
 
 struct irq_chip emma2rh_irq_controller = {
 	.name = "emma2rh_irq",
-	.ack = emma2rh_irq_disable,
-	.mask = emma2rh_irq_disable,
-	.mask_ack = emma2rh_irq_disable,
-	.unmask = emma2rh_irq_enable,
+	.irq_mask = emma2rh_irq_disable,
+	.irq_unmask = emma2rh_irq_enable,
 };
 
 void emma2rh_irq_init(void)
@@ -77,28 +69,26 @@
 	u32 i;
 
 	for (i = 0; i < NUM_EMMA2RH_IRQ; i++)
-		set_irq_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
+		irq_set_chip_and_handler_name(EMMA2RH_IRQ_BASE + i,
 					      &emma2rh_irq_controller,
 					      handle_level_irq, "level");
 }
 
-static void emma2rh_sw_irq_enable(unsigned int irq)
+static void emma2rh_sw_irq_enable(struct irq_data *d)
 {
+	unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE;
 	u32 reg;
 
-	irq -= EMMA2RH_SW_IRQ_BASE;
-
 	reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
 	reg |= 1 << irq;
 	emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
 }
 
-static void emma2rh_sw_irq_disable(unsigned int irq)
+static void emma2rh_sw_irq_disable(struct irq_data *d)
 {
+	unsigned int irq = d->irq - EMMA2RH_SW_IRQ_BASE;
 	u32 reg;
 
-	irq -= EMMA2RH_SW_IRQ_BASE;
-
 	reg = emma2rh_in32(EMMA2RH_BHIF_SW_INT_EN);
 	reg &= ~(1 << irq);
 	emma2rh_out32(EMMA2RH_BHIF_SW_INT_EN, reg);
@@ -106,10 +96,8 @@
 
 struct irq_chip emma2rh_sw_irq_controller = {
 	.name = "emma2rh_sw_irq",
-	.ack = emma2rh_sw_irq_disable,
-	.mask = emma2rh_sw_irq_disable,
-	.mask_ack = emma2rh_sw_irq_disable,
-	.unmask = emma2rh_sw_irq_enable,
+	.irq_mask = emma2rh_sw_irq_disable,
+	.irq_unmask = emma2rh_sw_irq_enable,
 };
 
 void emma2rh_sw_irq_init(void)
@@ -117,44 +105,43 @@
 	u32 i;
 
 	for (i = 0; i < NUM_EMMA2RH_IRQ_SW; i++)
-		set_irq_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
+		irq_set_chip_and_handler_name(EMMA2RH_SW_IRQ_BASE + i,
 					      &emma2rh_sw_irq_controller,
 					      handle_level_irq, "level");
 }
 
-static void emma2rh_gpio_irq_enable(unsigned int irq)
+static void emma2rh_gpio_irq_enable(struct irq_data *d)
 {
+	unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
 	u32 reg;
 
-	irq -= EMMA2RH_GPIO_IRQ_BASE;
-
 	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 	reg |= 1 << irq;
 	emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
 }
 
-static void emma2rh_gpio_irq_disable(unsigned int irq)
+static void emma2rh_gpio_irq_disable(struct irq_data *d)
 {
+	unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
 	u32 reg;
 
-	irq -= EMMA2RH_GPIO_IRQ_BASE;
-
 	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
 	reg &= ~(1 << irq);
 	emma2rh_out32(EMMA2RH_GPIO_INT_MASK, reg);
 }
 
-static void emma2rh_gpio_irq_ack(unsigned int irq)
+static void emma2rh_gpio_irq_ack(struct irq_data *d)
 {
-	irq -= EMMA2RH_GPIO_IRQ_BASE;
+	unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
+
 	emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
 }
 
-static void emma2rh_gpio_irq_mask_ack(unsigned int irq)
+static void emma2rh_gpio_irq_mask_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq - EMMA2RH_GPIO_IRQ_BASE;
 	u32 reg;
 
-	irq -= EMMA2RH_GPIO_IRQ_BASE;
 	emma2rh_out32(EMMA2RH_GPIO_INT_ST, ~(1 << irq));
 
 	reg = emma2rh_in32(EMMA2RH_GPIO_INT_MASK);
@@ -164,10 +151,10 @@
 
 struct irq_chip emma2rh_gpio_irq_controller = {
 	.name = "emma2rh_gpio_irq",
-	.ack = emma2rh_gpio_irq_ack,
-	.mask = emma2rh_gpio_irq_disable,
-	.mask_ack = emma2rh_gpio_irq_mask_ack,
-	.unmask = emma2rh_gpio_irq_enable,
+	.irq_ack = emma2rh_gpio_irq_ack,
+	.irq_mask = emma2rh_gpio_irq_disable,
+	.irq_mask_ack = emma2rh_gpio_irq_mask_ack,
+	.irq_unmask = emma2rh_gpio_irq_enable,
 };
 
 void emma2rh_gpio_irq_init(void)
@@ -175,7 +162,7 @@
 	u32 i;
 
 	for (i = 0; i < NUM_EMMA2RH_IRQ_GPIO; i++)
-		set_irq_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
+		irq_set_chip_and_handler_name(EMMA2RH_GPIO_IRQ_BASE + i,
 					      &emma2rh_gpio_irq_controller,
 					      handle_edge_irq, "edge");
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/fw/arc/Makefile linux-libre-2.6.39-gnu/arch/mips/fw/arc/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/fw/arc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/fw/arc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,4 +9,4 @@
 lib-$(CONFIG_ARC_CONSOLE)	+= arc_con.o
 lib-$(CONFIG_ARC_PROMLIB)	+= promlib.o
 
-EXTRA_CFLAGS			+= -Werror
+ccflags-y			:= -Werror
diff -druN linux-libre-2.6.38-gnu/arch/mips/fw/arc/promlib.c linux-libre-2.6.39-gnu/arch/mips/fw/arc/promlib.c
--- linux-libre-2.6.38-gnu/arch/mips/fw/arc/promlib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/fw/arc/promlib.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * for more details.
  *
  * Copyright (C) 1996 David S. Miller (dm@sgi.com)
- * Compability with board caches, Ulf Carlsson
+ * Compatibility with board caches, Ulf Carlsson
  */
 #include <linux/kernel.h>
 #include <asm/sgialib.h>
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/mips/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -676,9 +676,8 @@
 #include <asm/arch_hweight.h>
 #include <asm-generic/bitops/const_hweight.h>
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/cache.h linux-libre-2.6.39-gnu/arch/mips/include/asm/cache.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/cache.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/cache.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,6 @@
 #define SMP_CACHE_SHIFT		L1_CACHE_SHIFT
 #define SMP_CACHE_BYTES		L1_CACHE_BYTES
 
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 #endif /* _ASM_CACHE_H */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/cevt-r4k.h linux-libre-2.6.39-gnu/arch/mips/include/asm/cevt-r4k.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/cevt-r4k.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/cevt-r4k.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,9 @@
 #ifndef __ASM_CEVT_R4K_H
 #define __ASM_CEVT_R4K_H
 
+#include <linux/clockchips.h>
+#include <asm/time.h>
+
 DECLARE_PER_CPU(struct clock_event_device, mips_clockevent_device);
 
 void mips_event_handler(struct clock_event_device *dev);
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/dec/prom.h linux-libre-2.6.39-gnu/arch/mips/include/asm/dec/prom.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/dec/prom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/dec/prom.h	2011-05-19 00:06:34.000000000 -0400
@@ -108,7 +108,7 @@
 
 /*
  * On MIPS64 we have to call PROM functions via a helper
- * dispatcher to accomodate ABI incompatibilities.
+ * dispatcher to accommodate ABI incompatibilities.
  */
 #define __DEC_PROM_O32(fun, arg) fun arg __asm__(#fun); \
 				 __asm__(#fun " = call_o32")
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/dma-mapping.h linux-libre-2.6.39-gnu/arch/mips/include/asm/dma-mapping.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/dma-mapping.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/dma-mapping.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,9 @@
 #include <asm/cache.h>
 #include <asm-generic/dma-coherent.h>
 
+#ifndef CONFIG_SGI_IP27	/* Kludge to fix 2.6.39 build for IP27 */
 #include <dma-coherence.h>
+#endif
 
 extern struct dma_map_ops *mips_dma_map_ops;
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/errno.h linux-libre-2.6.39-gnu/arch/mips/include/asm/errno.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/errno.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/errno.h	2011-05-19 00:06:34.000000000 -0400
@@ -121,6 +121,8 @@
 
 #define	ERFKILL		167	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	168	/* Memory page has hardware error */
+
 #define EDQUOT		1133	/* Quota exceeded */
 
 #ifdef __KERNEL__
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/floppy.h linux-libre-2.6.39-gnu/arch/mips/include/asm/floppy.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/floppy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/floppy.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
  * And on Mips's the CMOS info fails also ...
  *
  * FIXME: This information should come from the ARC configuration tree
- *        or whereever a particular machine has stored this ...
+ *        or wherever a particular machine has stored this ...
  */
 #define FLOPPY0_TYPE 		fd_drive_type(0)
 #define FLOPPY1_TYPE		fd_drive_type(1)
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/futex.h linux-libre-2.6.39-gnu/arch/mips/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 }
 
 static inline int
-futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -85,7 +85,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -132,11 +132,13 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int retval;
+	int ret = 0;
+	u32 val;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	if (cpu_has_llsc && R10000_LLSC_WAR) {
@@ -145,25 +147,25 @@
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqzl	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else if (cpu_has_llsc) {
@@ -172,31 +174,32 @@
 		"	.set	push					\n"
 		"	.set	noat					\n"
 		"	.set	mips3					\n"
-		"1:	ll	%0, %2					\n"
-		"	bne	%0, %z3, 3f				\n"
+		"1:	ll	%1, %3					\n"
+		"	bne	%1, %z4, 3f				\n"
 		"	.set	mips0					\n"
-		"	move	$1, %z4					\n"
+		"	move	$1, %z5					\n"
 		"	.set	mips3					\n"
-		"2:	sc	$1, %1					\n"
+		"2:	sc	$1, %2					\n"
 		"	beqz	$1, 1b					\n"
 		__WEAK_LLSC_MB
 		"3:							\n"
 		"	.set	pop					\n"
 		"	.section .fixup,\"ax\"				\n"
-		"4:	li	%0, %5					\n"
+		"4:	li	%0, %6					\n"
 		"	j	3b					\n"
 		"	.previous					\n"
 		"	.section __ex_table,\"a\"			\n"
 		"	"__UA_ADDR "\t1b, 4b				\n"
 		"	"__UA_ADDR "\t2b, 4b				\n"
 		"	.previous					\n"
-		: "=&r" (retval), "=R" (*uaddr)
+		: "+r" (ret), "=&r" (val), "=R" (*uaddr)
 		: "R" (*uaddr), "Jr" (oldval), "Jr" (newval), "i" (-EFAULT)
 		: "memory");
 	} else
 		return -ENOSYS;
 
-	return retval;
+	*uval = val;
+	return ret;
 }
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/hugetlb.h linux-libre-2.6.39-gnu/arch/mips/include/asm/hugetlb.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/hugetlb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/hugetlb.h	2011-05-19 00:06:34.000000000 -0400
@@ -70,6 +70,7 @@
 static inline void huge_ptep_clear_flush(struct vm_area_struct *vma,
 					 unsigned long addr, pte_t *ptep)
 {
+	flush_tlb_mm(vma->vm_mm);
 }
 
 static inline int huge_pte_none(pte_t pte)
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/hw_irq.h linux-libre-2.6.39-gnu/arch/mips/include/asm/hw_irq.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/hw_irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/hw_irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 extern atomic_t irq_err_count;
 
 /*
- * interrupt-retrigger: NOP for now. This may not be apropriate for all
+ * interrupt-retrigger: NOP for now. This may not be appropriate for all
  * machines, we'll see ...
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/mips/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 #define TIOCSPTLCK	_IOW('T', 0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T', 0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T', 0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 /* I hope the range from 0x5480 on is free ... */
 #define TIOCSCTTY	0x5480		/* become controlling tty */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/io.h linux-libre-2.6.39-gnu/arch/mips/include/asm/io.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -242,7 +242,7 @@
  * This version of ioremap ensures that the memory is marked uncachable
  * on the CPU as well as honouring existing caching rules from things like
  * the PCI bus. Note that there are other caches and buffers on many
- * busses. In paticular driver authors should read up on PCI writes
+ * busses. In particular driver authors should read up on PCI writes
  *
  * It's useful if some control registers are in such an area and
  * write combining or read caching is not desirable:
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/irqflags.h linux-libre-2.6.39-gnu/arch/mips/include/asm/irqflags.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/irqflags.h	2011-05-19 00:06:34.000000000 -0400
@@ -174,7 +174,7 @@
 	"mtc0	\\flags, $2, 1						\n"
 #elif defined(CONFIG_CPU_MIPSR2) && defined(CONFIG_IRQ_CPU)
 	/*
-	 * Slow, but doesn't suffer from a relativly unlikely race
+	 * Slow, but doesn't suffer from a relatively unlikely race
 	 * condition we're having since days 1.
 	 */
 	"	beqz	\\flags, 1f					\n"
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/irq.h linux-libre-2.6.39-gnu/arch/mips/include/asm/irq.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -55,9 +55,9 @@
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
 #include <linux/cpumask.h>
 
-extern int plat_set_irq_affinity(unsigned int irq,
-				  const struct cpumask *affinity);
-extern void smtc_forward_irq(unsigned int irq);
+extern int plat_set_irq_affinity(struct irq_data *d,
+				 const struct cpumask *affinity, bool force);
+extern void smtc_forward_irq(struct irq_data *d);
 
 /*
  * IRQ affinity hook invoked at the beginning of interrupt dispatch
@@ -70,51 +70,53 @@
  * cpumask implementations, this version is optimistically assuming
  * that cpumask.h macro overhead is reasonable during interrupt dispatch.
  */
-#define IRQ_AFFINITY_HOOK(irq)						\
-do {									\
-    if (!cpumask_test_cpu(smp_processor_id(), irq_desc[irq].affinity)) {\
-	smtc_forward_irq(irq);						\
-	irq_exit();							\
-	return;								\
-    }									\
-} while (0)
+static inline int handle_on_other_cpu(unsigned int irq)
+{
+	struct irq_data *d = irq_get_irq_data(irq);
+
+	if (cpumask_test_cpu(smp_processor_id(), d->affinity))
+		return 0;
+	smtc_forward_irq(d);
+	return 1;
+}
 
 #else /* Not doing SMTC affinity */
 
-#define IRQ_AFFINITY_HOOK(irq) do { } while (0)
+static inline int handle_on_other_cpu(unsigned int irq) { return 0; }
 
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
 
 #ifdef CONFIG_MIPS_MT_SMTC_IM_BACKSTOP
 
+static inline void smtc_im_backstop(unsigned int irq)
+{
+	if (irq_hwmask[irq] & 0x0000ff00)
+		write_c0_tccontext(read_c0_tccontext() &
+				   ~(irq_hwmask[irq] & 0x0000ff00));
+}
+
 /*
  * Clear interrupt mask handling "backstop" if irq_hwmask
  * entry so indicates. This implies that the ack() or end()
  * functions will take over re-enabling the low-level mask.
  * Otherwise it will be done on return from exception.
  */
-#define __DO_IRQ_SMTC_HOOK(irq)						\
-do {									\
-	IRQ_AFFINITY_HOOK(irq);						\
-	if (irq_hwmask[irq] & 0x0000ff00)				\
-		write_c0_tccontext(read_c0_tccontext() &		\
-				   ~(irq_hwmask[irq] & 0x0000ff00));	\
-} while (0)
+static inline int smtc_handle_on_other_cpu(unsigned int irq)
+{
+	int ret = handle_on_other_cpu(irq);
 
-#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq)				\
-do {									\
-	if (irq_hwmask[irq] & 0x0000ff00)                               \
-		write_c0_tccontext(read_c0_tccontext() &		\
-				   ~(irq_hwmask[irq] & 0x0000ff00));	\
-} while (0)
+	if (!ret)
+		smtc_im_backstop(irq);
+	return ret;
+}
 
 #else
 
-#define __DO_IRQ_SMTC_HOOK(irq)						\
-do {									\
-	IRQ_AFFINITY_HOOK(irq);						\
-} while (0)
-#define __NO_AFFINITY_IRQ_SMTC_HOOK(irq) do { } while (0)
+static inline void smtc_im_backstop(unsigned int irq) { }
+static inline int smtc_handle_on_other_cpu(unsigned int irq)
+{
+	return handle_on_other_cpu(irq);
+}
 
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-bcm63xx/bcm963xx_tag.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 #define TAGVER_LEN		4	/* Length of Tag Version */
 #define TAGLAYOUT_LEN		4	/* Length of FlashLayoutVer */
 #define SIG1_LEN		20	/* Company Signature 1 Length */
-#define SIG2_LEN		14	/* Company Signature 2 Lenght */
+#define SIG2_LEN		14	/* Company Signature 2 Length */
 #define BOARDID_LEN		16	/* Length of BoardId */
 #define ENDIANFLAG_LEN		2	/* Endian Flag Length */
 #define CHIPID_LEN		6	/* Chip Id Length */
@@ -88,7 +88,7 @@
 	char kernel_crc[CRC_LEN];
 	/* 228-235: Unused at present */
 	char reserved1[8];
-	/* 236-239: CRC32 of header excluding tagVersion */
+	/* 236-239: CRC32 of header excluding last 20 bytes */
 	char header_crc[CRC_LEN];
 	/* 240-255: Unused at present */
 	char reserved2[16];
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-cavium-octeon/irq.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-cavium-octeon/irq.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-cavium-octeon/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-cavium-octeon/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,172 +11,91 @@
 #define NR_IRQS OCTEON_IRQ_LAST
 #define MIPS_CPU_IRQ_BASE OCTEON_IRQ_SW0
 
-/* 0 - 7 represent the i8259 master */
-#define OCTEON_IRQ_I8259M0	0
-#define OCTEON_IRQ_I8259M1	1
-#define OCTEON_IRQ_I8259M2	2
-#define OCTEON_IRQ_I8259M3	3
-#define OCTEON_IRQ_I8259M4	4
-#define OCTEON_IRQ_I8259M5	5
-#define OCTEON_IRQ_I8259M6	6
-#define OCTEON_IRQ_I8259M7	7
-/* 8 - 15 represent the i8259 slave */
-#define OCTEON_IRQ_I8259S0	8
-#define OCTEON_IRQ_I8259S1	9
-#define OCTEON_IRQ_I8259S2	10
-#define OCTEON_IRQ_I8259S3	11
-#define OCTEON_IRQ_I8259S4	12
-#define OCTEON_IRQ_I8259S5	13
-#define OCTEON_IRQ_I8259S6	14
-#define OCTEON_IRQ_I8259S7	15
-/* 16 - 23 represent the 8 MIPS standard interrupt sources */
-#define OCTEON_IRQ_SW0		16
-#define OCTEON_IRQ_SW1		17
-#define OCTEON_IRQ_CIU0		18
-#define OCTEON_IRQ_CIU1		19
-#define OCTEON_IRQ_CIU4		20
-#define OCTEON_IRQ_5		21
-#define OCTEON_IRQ_PERF		22
-#define OCTEON_IRQ_TIMER	23
-/* 24 - 87 represent the sources in CIU_INTX_EN0 */
-#define OCTEON_IRQ_WORKQ0	24
-#define OCTEON_IRQ_WORKQ1	25
-#define OCTEON_IRQ_WORKQ2	26
-#define OCTEON_IRQ_WORKQ3	27
-#define OCTEON_IRQ_WORKQ4	28
-#define OCTEON_IRQ_WORKQ5	29
-#define OCTEON_IRQ_WORKQ6	30
-#define OCTEON_IRQ_WORKQ7	31
-#define OCTEON_IRQ_WORKQ8	32
-#define OCTEON_IRQ_WORKQ9	33
-#define OCTEON_IRQ_WORKQ10	34
-#define OCTEON_IRQ_WORKQ11	35
-#define OCTEON_IRQ_WORKQ12	36
-#define OCTEON_IRQ_WORKQ13	37
-#define OCTEON_IRQ_WORKQ14	38
-#define OCTEON_IRQ_WORKQ15	39
-#define OCTEON_IRQ_GPIO0	40
-#define OCTEON_IRQ_GPIO1	41
-#define OCTEON_IRQ_GPIO2	42
-#define OCTEON_IRQ_GPIO3	43
-#define OCTEON_IRQ_GPIO4	44
-#define OCTEON_IRQ_GPIO5	45
-#define OCTEON_IRQ_GPIO6	46
-#define OCTEON_IRQ_GPIO7	47
-#define OCTEON_IRQ_GPIO8	48
-#define OCTEON_IRQ_GPIO9	49
-#define OCTEON_IRQ_GPIO10	50
-#define OCTEON_IRQ_GPIO11	51
-#define OCTEON_IRQ_GPIO12	52
-#define OCTEON_IRQ_GPIO13	53
-#define OCTEON_IRQ_GPIO14	54
-#define OCTEON_IRQ_GPIO15	55
-#define OCTEON_IRQ_MBOX0	56
-#define OCTEON_IRQ_MBOX1	57
-#define OCTEON_IRQ_UART0	58
-#define OCTEON_IRQ_UART1	59
-#define OCTEON_IRQ_PCI_INT0	60
-#define OCTEON_IRQ_PCI_INT1	61
-#define OCTEON_IRQ_PCI_INT2	62
-#define OCTEON_IRQ_PCI_INT3	63
-#define OCTEON_IRQ_PCI_MSI0	64
-#define OCTEON_IRQ_PCI_MSI1	65
-#define OCTEON_IRQ_PCI_MSI2	66
-#define OCTEON_IRQ_PCI_MSI3	67
-#define OCTEON_IRQ_RESERVED68	68	/* Summary of CIU_INT_SUM1 */
-#define OCTEON_IRQ_TWSI		69
-#define OCTEON_IRQ_RML		70
-#define OCTEON_IRQ_TRACE	71
-#define OCTEON_IRQ_GMX_DRP0	72
-#define OCTEON_IRQ_GMX_DRP1	73
-#define OCTEON_IRQ_IPD_DRP	74
-#define OCTEON_IRQ_KEY_ZERO	75
-#define OCTEON_IRQ_TIMER0	76
-#define OCTEON_IRQ_TIMER1	77
-#define OCTEON_IRQ_TIMER2	78
-#define OCTEON_IRQ_TIMER3	79
-#define OCTEON_IRQ_USB0		80
-#define OCTEON_IRQ_PCM		81
-#define OCTEON_IRQ_MPI		82
-#define OCTEON_IRQ_TWSI2	83
-#define OCTEON_IRQ_POWIQ	84
-#define OCTEON_IRQ_IPDPPTHR	85
-#define OCTEON_IRQ_MII0		86
-#define OCTEON_IRQ_BOOTDMA	87
-/* 88 - 151 represent the sources in CIU_INTX_EN1 */
-#define OCTEON_IRQ_WDOG0	88
-#define OCTEON_IRQ_WDOG1	89
-#define OCTEON_IRQ_WDOG2	90
-#define OCTEON_IRQ_WDOG3	91
-#define OCTEON_IRQ_WDOG4	92
-#define OCTEON_IRQ_WDOG5	93
-#define OCTEON_IRQ_WDOG6	94
-#define OCTEON_IRQ_WDOG7	95
-#define OCTEON_IRQ_WDOG8	96
-#define OCTEON_IRQ_WDOG9	97
-#define OCTEON_IRQ_WDOG10	98
-#define OCTEON_IRQ_WDOG11	99
-#define OCTEON_IRQ_WDOG12	100
-#define OCTEON_IRQ_WDOG13	101
-#define OCTEON_IRQ_WDOG14	102
-#define OCTEON_IRQ_WDOG15	103
-#define OCTEON_IRQ_UART2	104
-#define OCTEON_IRQ_USB1		105
-#define OCTEON_IRQ_MII1		106
-#define OCTEON_IRQ_RESERVED107	107
-#define OCTEON_IRQ_RESERVED108	108
-#define OCTEON_IRQ_RESERVED109	109
-#define OCTEON_IRQ_RESERVED110	110
-#define OCTEON_IRQ_RESERVED111	111
-#define OCTEON_IRQ_RESERVED112	112
-#define OCTEON_IRQ_RESERVED113	113
-#define OCTEON_IRQ_RESERVED114	114
-#define OCTEON_IRQ_RESERVED115	115
-#define OCTEON_IRQ_RESERVED116	116
-#define OCTEON_IRQ_RESERVED117	117
-#define OCTEON_IRQ_RESERVED118	118
-#define OCTEON_IRQ_RESERVED119	119
-#define OCTEON_IRQ_RESERVED120	120
-#define OCTEON_IRQ_RESERVED121	121
-#define OCTEON_IRQ_RESERVED122	122
-#define OCTEON_IRQ_RESERVED123	123
-#define OCTEON_IRQ_RESERVED124	124
-#define OCTEON_IRQ_RESERVED125	125
-#define OCTEON_IRQ_RESERVED126	126
-#define OCTEON_IRQ_RESERVED127	127
-#define OCTEON_IRQ_RESERVED128	128
-#define OCTEON_IRQ_RESERVED129	129
-#define OCTEON_IRQ_RESERVED130	130
-#define OCTEON_IRQ_RESERVED131	131
-#define OCTEON_IRQ_RESERVED132	132
-#define OCTEON_IRQ_RESERVED133	133
-#define OCTEON_IRQ_RESERVED134	134
-#define OCTEON_IRQ_RESERVED135	135
-#define OCTEON_IRQ_RESERVED136	136
-#define OCTEON_IRQ_RESERVED137	137
-#define OCTEON_IRQ_RESERVED138	138
-#define OCTEON_IRQ_RESERVED139	139
-#define OCTEON_IRQ_RESERVED140	140
-#define OCTEON_IRQ_RESERVED141	141
-#define OCTEON_IRQ_RESERVED142	142
-#define OCTEON_IRQ_RESERVED143	143
-#define OCTEON_IRQ_RESERVED144	144
-#define OCTEON_IRQ_RESERVED145	145
-#define OCTEON_IRQ_RESERVED146	146
-#define OCTEON_IRQ_RESERVED147	147
-#define OCTEON_IRQ_RESERVED148	148
-#define OCTEON_IRQ_RESERVED149	149
-#define OCTEON_IRQ_RESERVED150	150
-#define OCTEON_IRQ_RESERVED151	151
+enum octeon_irq {
+/* 1 - 8 represent the 8 MIPS standard interrupt sources */
+	OCTEON_IRQ_SW0 = 1,
+	OCTEON_IRQ_SW1,
+/* CIU0, CUI2, CIU4 are 3, 4, 5 */
+	OCTEON_IRQ_5 = 6,
+	OCTEON_IRQ_PERF,
+	OCTEON_IRQ_TIMER,
+/* sources in CIU_INTX_EN0 */
+	OCTEON_IRQ_WORKQ0,
+	OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16,
+	OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16,
+	OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15,
+	OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16,
+	OCTEON_IRQ_MBOX1,
+	OCTEON_IRQ_UART0,
+	OCTEON_IRQ_UART1,
+	OCTEON_IRQ_UART2,
+	OCTEON_IRQ_PCI_INT0,
+	OCTEON_IRQ_PCI_INT1,
+	OCTEON_IRQ_PCI_INT2,
+	OCTEON_IRQ_PCI_INT3,
+	OCTEON_IRQ_PCI_MSI0,
+	OCTEON_IRQ_PCI_MSI1,
+	OCTEON_IRQ_PCI_MSI2,
+	OCTEON_IRQ_PCI_MSI3,
+
+	OCTEON_IRQ_TWSI,
+	OCTEON_IRQ_TWSI2,
+	OCTEON_IRQ_RML,
+	OCTEON_IRQ_TRACE0,
+	OCTEON_IRQ_GMX_DRP0 = OCTEON_IRQ_TRACE0 + 4,
+	OCTEON_IRQ_IPD_DRP = OCTEON_IRQ_GMX_DRP0 + 5,
+	OCTEON_IRQ_KEY_ZERO,
+	OCTEON_IRQ_TIMER0,
+	OCTEON_IRQ_TIMER1,
+	OCTEON_IRQ_TIMER2,
+	OCTEON_IRQ_TIMER3,
+	OCTEON_IRQ_USB0,
+	OCTEON_IRQ_USB1,
+	OCTEON_IRQ_PCM,
+	OCTEON_IRQ_MPI,
+	OCTEON_IRQ_POWIQ,
+	OCTEON_IRQ_IPDPPTHR,
+	OCTEON_IRQ_MII0,
+	OCTEON_IRQ_MII1,
+	OCTEON_IRQ_BOOTDMA,
+
+	OCTEON_IRQ_NAND,
+	OCTEON_IRQ_MIO,		/* Summary of MIO_BOOT_ERR */
+	OCTEON_IRQ_IOB,		/* Summary of IOB_INT_SUM */
+	OCTEON_IRQ_FPA,		/* Summary of FPA_INT_SUM */
+	OCTEON_IRQ_POW,		/* Summary of POW_ECC_ERR */
+	OCTEON_IRQ_L2C,		/* Summary of L2C_INT_STAT */
+	OCTEON_IRQ_IPD,		/* Summary of IPD_INT_SUM */
+	OCTEON_IRQ_PIP,		/* Summary of PIP_INT_REG */
+	OCTEON_IRQ_PKO,		/* Summary of PKO_REG_ERROR */
+	OCTEON_IRQ_ZIP,		/* Summary of ZIP_ERROR */
+	OCTEON_IRQ_TIM,		/* Summary of TIM_REG_ERROR */
+	OCTEON_IRQ_RAD,		/* Summary of RAD_REG_ERROR */
+	OCTEON_IRQ_KEY,		/* Summary of KEY_INT_SUM */
+	OCTEON_IRQ_DFA,		/* Summary of DFA */
+	OCTEON_IRQ_USBCTL,	/* Summary of USBN0_INT_SUM */
+	OCTEON_IRQ_SLI,		/* Summary of SLI_INT_SUM */
+	OCTEON_IRQ_DPI,		/* Summary of DPI_INT_SUM */
+	OCTEON_IRQ_AGX0,	/* Summary of GMX0*+PCS0_INT*_REG */
+	OCTEON_IRQ_AGL  = OCTEON_IRQ_AGX0 + 5,
+	OCTEON_IRQ_PTP,
+	OCTEON_IRQ_PEM0,
+	OCTEON_IRQ_PEM1,
+	OCTEON_IRQ_SRIO0,
+	OCTEON_IRQ_SRIO1,
+	OCTEON_IRQ_LMC0,
+	OCTEON_IRQ_DFM = OCTEON_IRQ_LMC0 + 4,		/* Summary of DFM */
+	OCTEON_IRQ_RST,
+};
 
 #ifdef CONFIG_PCI_MSI
-/* 152 - 215 represent the MSI interrupts 0-63 */
-#define OCTEON_IRQ_MSI_BIT0	152
-#define OCTEON_IRQ_MSI_LAST	(OCTEON_IRQ_MSI_BIT0 + 255)
+/* 152 - 407 represent the MSI interrupts 0-255 */
+#define OCTEON_IRQ_MSI_BIT0	(OCTEON_IRQ_RST + 1)
 
-#define OCTEON_IRQ_LAST		(OCTEON_IRQ_MSI_LAST + 1)
+#define OCTEON_IRQ_MSI_LAST      (OCTEON_IRQ_MSI_BIT0 + 255)
+#define OCTEON_IRQ_LAST          (OCTEON_IRQ_MSI_LAST + 1)
 #else
-#define OCTEON_IRQ_LAST         152
+#define OCTEON_IRQ_LAST         (OCTEON_IRQ_RST + 1)
 #endif
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-ip32/mc146818rtc.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-ip32/mc146818rtc.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-ip32/mc146818rtc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-ip32/mc146818rtc.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,7 +26,7 @@
 }
 
 /*
- * FIXME: Do it right. For now just assume that noone lives in 20th century
+ * FIXME: Do it right. For now just assume that no one lives in 20th century
  * and no O2 user in 22th century ;-)
  */
 #define mc146818_decode_year(year) ((year) + 2000)
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-jz4740/platform.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-jz4740/platform.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-jz4740/platform.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-jz4740/platform.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 extern struct platform_device jz4740_pcm_device;
 extern struct platform_device jz4740_codec_device;
 extern struct platform_device jz4740_adc_device;
+extern struct platform_device jz4740_wdt_device;
 
 void jz4740_serial_device_register(void);
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-loongson/cs5536/cs5536.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * The header file of cs5536 sourth bridge.
+ * The header file of cs5536 south bridge.
  *
  * Copyright (C) 2007 Lemote, Inc.
  * Author : jlliu <liujl@lemote.com>
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-pb1x00/pb1000.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-pb1x00/pb1000.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-pb1x00/pb1000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-pb1x00/pb1000.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Alchemy Semi Pb1000 Referrence Board
+ * Alchemy Semi Pb1000 Reference Board
  *
  * Copyright 2001, 2008 MontaVista Software Inc.
  * Author: MontaVista Software, Inc. <source@mvista.com>
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-pb1x00/pb1200.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * AMD Alchemy Pb1200 Referrence Board
+ * AMD Alchemy Pb1200 Reference Board
  * Board Registers defines.
  *
  * ########################################################################
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-pb1x00/pb1550.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * AMD Alchemy Semi PB1550 Referrence Board
+ * AMD Alchemy Semi PB1550 Reference Board
  * Board Registers defines.
  *
  * Copyright 2004 Embedded Edge LLC.
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-powertv/dma-coherence.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-powertv/dma-coherence.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mach-powertv/dma-coherence.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mach-powertv/dma-coherence.h	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
 				/* check for a valid page */
 				if (pte_present(pte)) {
 					/* get the physical address the page is
-					 * refering to */
+					 * referring to */
 					phys_addr = (unsigned long)
 						page_to_phys(pte_page(pte));
 					/* add the offset within the page */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/mipsregs.h linux-libre-2.6.39-gnu/arch/mips/include/asm/mipsregs.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/mipsregs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/mipsregs.h	2011-05-19 00:06:34.000000000 -0400
@@ -922,7 +922,7 @@
 #define write_c0_config7(val)	__write_32bit_c0_register($16, 7, val)
 
 /*
- * The WatchLo register.  There may be upto 8 of them.
+ * The WatchLo register.  There may be up to 8 of them.
  */
 #define read_c0_watchlo0()	__read_ulong_c0_register($18, 0)
 #define read_c0_watchlo1()	__read_ulong_c0_register($18, 1)
@@ -942,7 +942,7 @@
 #define write_c0_watchlo7(val)	__write_ulong_c0_register($18, 7, val)
 
 /*
- * The WatchHi register.  There may be upto 8 of them.
+ * The WatchHi register.  There may be up to 8 of them.
  */
 #define read_c0_watchhi0()	__read_32bit_c0_register($19, 0)
 #define read_c0_watchhi1()	__read_32bit_c0_register($19, 1)
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx-bootinfo.h	2011-05-19 00:06:34.000000000 -0400
@@ -200,7 +200,7 @@
 	CVMX_CHIP_TYPE_MAX,
 };
 
-/* Compatability alias for NAC38 name change, planned to be removed
+/* Compatibility alias for NAC38 name change, planned to be removed
  * from SDK 1.7 */
 #define CVMX_BOARD_TYPE_NAO38	CVMX_BOARD_TYPE_NAC38
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx-bootmem.h	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
 
 /*
  * Structure for named memory blocks.  Number of descriptors available
- * can be changed without affecting compatiblity, but name length
+ * can be changed without affecting compatibility, but name length
  * changes require a bump in the bootmem descriptor version Note: This
  * structure must be naturally 64 bit aligned, as a single memory
  * image will be used by both 32 and 64 bit programs.
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx.h linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx.h	2011-05-19 00:06:34.000000000 -0400
@@ -151,7 +151,7 @@
 #endif
 
 /**
- * Convert a memory pointer (void*) into a hardware compatable
+ * Convert a memory pointer (void*) into a hardware compatible
  * memory address (uint64_t). Octeon hardware widgets don't
  * understand logical addresses.
  *
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx-l2c.h linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx-l2c.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/cvmx-l2c.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/cvmx-l2c.h	2011-05-19 00:06:34.000000000 -0400
@@ -157,7 +157,7 @@
 
 /**
  * Configure one of the four L2 Cache performance counters to capture event
- * occurences.
+ * occurrences.
  *
  * @counter:        The counter to configure. Range 0..3.
  * @event:          The type of L2 Cache event occurrence to count.
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/octeon.h linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/octeon.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/octeon/octeon.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/octeon/octeon.h	2011-05-19 00:06:34.000000000 -0400
@@ -257,4 +257,6 @@
 
 extern uint64_t octeon_bootloader_entry_addr;
 
+extern void (*octeon_irq_setup_secondary)(void);
+
 #endif /* __ASM_OCTEON_OCTEON_H */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/paccess.h linux-libre-2.6.39-gnu/arch/mips/include/asm/paccess.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/paccess.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/paccess.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
  *
  * Protected memory access.  Used for everything that might take revenge
- * by sending a DBE error like accessing possibly non-existant memory or
+ * by sending a DBE error like accessing possibly non-existent memory or
  * devices.
  */
 #ifndef _ASM_PACCESS_H
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/pci/bridge.h linux-libre-2.6.39-gnu/arch/mips/include/asm/pci/bridge.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/pci/bridge.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/pci/bridge.h	2011-05-19 00:06:34.000000000 -0400
@@ -262,7 +262,7 @@
 } bridge_t;
 
 /*
- * Field formats for Error Command Word and Auxillary Error Command Word
+ * Field formats for Error Command Word and Auxiliary Error Command Word
  * of bridge.
  */
 typedef struct bridge_err_cmdword_s {
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/cpu-feature-overrides.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 2003, 04, 07 Ralf Baechle (ralf@linux-mips.org)
+ */
+#ifndef __ASM_MACH_MSP71XX_CPU_FEATURE_OVERRIDES_H
+#define __ASM_MACH_MSP71XX_CPU_FEATURE_OVERRIDES_H
+
+#define cpu_has_mips16		1
+#define cpu_has_dsp		1
+#define cpu_has_mipsmt		1
+#define cpu_has_fpu		0
+
+#define cpu_has_mips32r1	0
+#define cpu_has_mips32r2	1
+#define cpu_has_mips64r1	0
+#define cpu_has_mips64r2	0
+
+#endif /* __ASM_MACH_MSP71XX_CPU_FEATURE_OVERRIDES_H */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_gpio_macros.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,343 @@
+/*
+ *
+ * Macros for external SMP-safe access to the PMC MSP71xx reference
+ * board GPIO pins
+ *
+ * Copyright 2010 PMC-Sierra, 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 __MSP_GPIO_MACROS_H__
+#define __MSP_GPIO_MACROS_H__
+
+#include <msp_regops.h>
+#include <msp_regs.h>
+
+#ifdef CONFIG_PMC_MSP7120_GW
+#define MSP_NUM_GPIOS		20
+#else
+#define MSP_NUM_GPIOS		28
+#endif
+
+/* -- GPIO Enumerations -- */
+enum msp_gpio_data {
+	MSP_GPIO_LO = 0,
+	MSP_GPIO_HI = 1,
+	MSP_GPIO_NONE,		/* Special - Means pin is out of range */
+	MSP_GPIO_TOGGLE,	/* Special - Sets pin to opposite */
+};
+
+enum msp_gpio_mode {
+	MSP_GPIO_INPUT		= 0x0,
+	/* MSP_GPIO_ INTERRUPT	= 0x1,	Not supported yet */
+	MSP_GPIO_UART_INPUT	= 0x2,	/* Only GPIO 4 or 5 */
+	MSP_GPIO_OUTPUT		= 0x8,
+	MSP_GPIO_UART_OUTPUT	= 0x9,	/* Only GPIO 2 or 3 */
+	MSP_GPIO_PERIF_TIMERA	= 0x9,	/* Only GPIO 0 or 1 */
+	MSP_GPIO_PERIF_TIMERB	= 0xa,	/* Only GPIO 0 or 1 */
+	MSP_GPIO_UNKNOWN	= 0xb,  /* No such GPIO or mode */
+};
+
+/* -- Static Tables -- */
+
+/* Maps pins to data register */
+static volatile u32 * const MSP_GPIO_DATA_REGISTER[] = {
+	/* GPIO 0 and 1 on the first register */
+	GPIO_DATA1_REG, GPIO_DATA1_REG,
+	/* GPIO 2, 3, 4, and 5 on the second register */
+	GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG, GPIO_DATA2_REG,
+	/* GPIO 6, 7, 8, and 9 on the third register */
+	GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG, GPIO_DATA3_REG,
+	/* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */
+	GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG, GPIO_DATA4_REG,
+	GPIO_DATA4_REG, GPIO_DATA4_REG,
+	/* GPIO 16 - 23 on the first strange EXTENDED register */
+	EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
+	EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
+	EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
+	/* GPIO 24 - 27 on the second strange EXTENDED register */
+	EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG,
+	EXTENDED_GPIO2_REG,
+};
+
+/* Maps pins to mode register */
+static volatile u32 * const MSP_GPIO_MODE_REGISTER[] = {
+	/* GPIO 0 and 1 on the first register */
+	GPIO_CFG1_REG, GPIO_CFG1_REG,
+	/* GPIO 2, 3, 4, and 5 on the second register */
+	GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG, GPIO_CFG2_REG,
+	/* GPIO 6, 7, 8, and 9 on the third register */
+	GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG, GPIO_CFG3_REG,
+	/* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */
+	GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG, GPIO_CFG4_REG,
+	GPIO_CFG4_REG, GPIO_CFG4_REG,
+	/* GPIO 16 - 23 on the first strange EXTENDED register */
+	EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
+	EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
+	EXTENDED_GPIO1_REG, EXTENDED_GPIO1_REG,
+	/* GPIO 24 - 27 on the second strange EXTENDED register */
+	EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG, EXTENDED_GPIO2_REG,
+	EXTENDED_GPIO2_REG,
+};
+
+/* Maps 'basic' pins to relative offset from 0 per register */
+static int MSP_GPIO_OFFSET[] = {
+	/* GPIO 0 and 1 on the first register */
+	0, 0,
+	/* GPIO 2, 3, 4, and 5 on the second register */
+	2, 2, 2, 2,
+	/* GPIO 6, 7, 8, and 9 on the third register */
+	6, 6, 6, 6,
+	/* GPIO 10, 11, 12, 13, 14, and 15 on the fourth register */
+	10, 10, 10, 10, 10, 10,
+};
+
+/* Maps MODE to allowed pin mask */
+static unsigned int MSP_GPIO_MODE_ALLOWED[] = {
+	0xffffffff,	/* Mode 0 - INPUT */
+	0x00000,	/* Mode 1 - INTERRUPT */
+	0x00030,	/* Mode 2 - UART_INPUT (GPIO 4, 5)*/
+	0, 0, 0, 0, 0,	/* Modes 3, 4, 5, 6, and 7 are reserved */
+	0xffffffff,	/* Mode 8 - OUTPUT */
+	0x0000f,	/* Mode 9 - UART_OUTPUT/
+				PERF_TIMERA (GPIO 0, 1, 2, 3) */
+	0x00003,	/* Mode a - PERF_TIMERB (GPIO 0, 1) */
+	0x00000,	/* Mode b - Not really a mode! */
+};
+
+/* -- Bit masks -- */
+
+/* This gives you the 'register relative offset gpio' number */
+#define OFFSET_GPIO_NUMBER(gpio)	(gpio - MSP_GPIO_OFFSET[gpio])
+
+/* These take the 'register relative offset gpio' number */
+#define BASIC_DATA_REG_MASK(ogpio)		(1 << ogpio)
+#define BASIC_MODE_REG_VALUE(mode, ogpio)	\
+	(mode << BASIC_MODE_REG_SHIFT(ogpio))
+#define BASIC_MODE_REG_MASK(ogpio)		\
+	BASIC_MODE_REG_VALUE(0xf, ogpio)
+#define BASIC_MODE_REG_SHIFT(ogpio)		(ogpio * 4)
+#define BASIC_MODE_REG_FROM_REG(data, ogpio)	\
+	((data & BASIC_MODE_REG_MASK(ogpio)) >> BASIC_MODE_REG_SHIFT(ogpio))
+
+/* These take the actual GPIO number (0 through 15) */
+#define BASIC_DATA_MASK(gpio)	\
+	BASIC_DATA_REG_MASK(OFFSET_GPIO_NUMBER(gpio))
+#define BASIC_MODE_MASK(gpio)	\
+	BASIC_MODE_REG_MASK(OFFSET_GPIO_NUMBER(gpio))
+#define BASIC_MODE(mode, gpio)	\
+	BASIC_MODE_REG_VALUE(mode, OFFSET_GPIO_NUMBER(gpio))
+#define BASIC_MODE_SHIFT(gpio)	\
+	BASIC_MODE_REG_SHIFT(OFFSET_GPIO_NUMBER(gpio))
+#define BASIC_MODE_FROM_REG(data, gpio)	\
+	BASIC_MODE_REG_FROM_REG(data, OFFSET_GPIO_NUMBER(gpio))
+
+/*
+ * Each extended GPIO register is 32 bits long and is responsible for up to
+ * eight GPIOs. The least significant 16 bits contain the set and clear bit
+ * pair for each of the GPIOs. The most significant 16 bits contain the
+ * disable and enable bit pair for each of the GPIOs. For example, the
+ * extended GPIO reg for GPIOs 16-23 is as follows:
+ *
+ *	31: GPIO23_DISABLE
+ *	...
+ *	19: GPIO17_DISABLE
+ *	18: GPIO17_ENABLE
+ *	17: GPIO16_DISABLE
+ *	16: GPIO16_ENABLE
+ *	...
+ *	3:  GPIO17_SET
+ *	2:  GPIO17_CLEAR
+ *	1:  GPIO16_SET
+ *	0:  GPIO16_CLEAR
+ */
+
+/* This gives the 'register relative offset gpio' number */
+#define EXTENDED_OFFSET_GPIO(gpio)	(gpio < 24 ? gpio - 16 : gpio - 24)
+
+/* These take the 'register relative offset gpio' number */
+#define EXTENDED_REG_DISABLE(ogpio)	(0x2 << ((ogpio * 2) + 16))
+#define EXTENDED_REG_ENABLE(ogpio)	(0x1 << ((ogpio * 2) + 16))
+#define EXTENDED_REG_SET(ogpio)		(0x2 << (ogpio * 2))
+#define EXTENDED_REG_CLR(ogpio)		(0x1 << (ogpio * 2))
+
+/* These take the actual GPIO number (16 through 27) */
+#define EXTENDED_DISABLE(gpio)	\
+	EXTENDED_REG_DISABLE(EXTENDED_OFFSET_GPIO(gpio))
+#define EXTENDED_ENABLE(gpio)	\
+	EXTENDED_REG_ENABLE(EXTENDED_OFFSET_GPIO(gpio))
+#define EXTENDED_SET(gpio)	\
+	EXTENDED_REG_SET(EXTENDED_OFFSET_GPIO(gpio))
+#define EXTENDED_CLR(gpio)	\
+	EXTENDED_REG_CLR(EXTENDED_OFFSET_GPIO(gpio))
+
+#define EXTENDED_FULL_MASK		(0xffffffff)
+
+/* -- API inline-functions -- */
+
+/*
+ * Gets the current value of the specified pin
+ */
+static inline enum msp_gpio_data msp_gpio_pin_get(unsigned int gpio)
+{
+	u32 pinhi_mask = 0, pinhi_mask2 = 0;
+
+	if (gpio >= MSP_NUM_GPIOS)
+		return MSP_GPIO_NONE;
+
+	if (gpio < 16) {
+		pinhi_mask = BASIC_DATA_MASK(gpio);
+	} else {
+		/*
+		 * Two cases are possible with the EXTENDED register:
+		 *  - In output mode (ENABLED flag set), check the CLR bit
+		 *  - In input mode (ENABLED flag not set), check the SET bit
+		 */
+		pinhi_mask = EXTENDED_ENABLE(gpio) | EXTENDED_CLR(gpio);
+		pinhi_mask2 = EXTENDED_SET(gpio);
+	}
+	if (((*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask) == pinhi_mask) ||
+	    (*MSP_GPIO_DATA_REGISTER[gpio] & pinhi_mask2))
+		return MSP_GPIO_HI;
+	else
+		return MSP_GPIO_LO;
+}
+
+/* Sets the specified pin to the specified value */
+static inline void msp_gpio_pin_set(enum msp_gpio_data data, unsigned int gpio)
+{
+	if (gpio >= MSP_NUM_GPIOS)
+		return;
+
+	if (gpio < 16) {
+		if (data == MSP_GPIO_TOGGLE)
+			toggle_reg32(MSP_GPIO_DATA_REGISTER[gpio],
+					BASIC_DATA_MASK(gpio));
+		else if (data == MSP_GPIO_HI)
+			set_reg32(MSP_GPIO_DATA_REGISTER[gpio],
+					BASIC_DATA_MASK(gpio));
+		else
+			clear_reg32(MSP_GPIO_DATA_REGISTER[gpio],
+					BASIC_DATA_MASK(gpio));
+	} else {
+		if (data == MSP_GPIO_TOGGLE) {
+			/* Special ugly case:
+			 *   We have to read the CLR bit.
+			 *   If set, we write the CLR bit.
+			 *   If not, we write the SET bit.
+			 */
+			u32 tmpdata;
+
+			custom_read_reg32(MSP_GPIO_DATA_REGISTER[gpio],
+								tmpdata);
+			if (tmpdata & EXTENDED_CLR(gpio))
+				tmpdata = EXTENDED_CLR(gpio);
+			else
+				tmpdata = EXTENDED_SET(gpio);
+			custom_write_reg32(MSP_GPIO_DATA_REGISTER[gpio],
+								tmpdata);
+		} else {
+			u32 newdata;
+
+			if (data == MSP_GPIO_HI)
+				newdata = EXTENDED_SET(gpio);
+			else
+				newdata = EXTENDED_CLR(gpio);
+			set_value_reg32(MSP_GPIO_DATA_REGISTER[gpio],
+						EXTENDED_FULL_MASK, newdata);
+		}
+	}
+}
+
+/* Sets the specified pin to the specified value */
+static inline void msp_gpio_pin_hi(unsigned int gpio)
+{
+	msp_gpio_pin_set(MSP_GPIO_HI, gpio);
+}
+
+/* Sets the specified pin to the specified value */
+static inline void msp_gpio_pin_lo(unsigned int gpio)
+{
+	msp_gpio_pin_set(MSP_GPIO_LO, gpio);
+}
+
+/* Sets the specified pin to the opposite value */
+static inline void msp_gpio_pin_toggle(unsigned int gpio)
+{
+	msp_gpio_pin_set(MSP_GPIO_TOGGLE, gpio);
+}
+
+/* Gets the mode of the specified pin */
+static inline enum msp_gpio_mode msp_gpio_pin_get_mode(unsigned int gpio)
+{
+	enum msp_gpio_mode retval = MSP_GPIO_UNKNOWN;
+	uint32_t data;
+
+	if (gpio >= MSP_NUM_GPIOS)
+		return retval;
+
+	data = *MSP_GPIO_MODE_REGISTER[gpio];
+
+	if (gpio < 16) {
+		retval = BASIC_MODE_FROM_REG(data, gpio);
+	} else {
+		/* Extended pins can only be either INPUT or OUTPUT */
+		if (data & EXTENDED_ENABLE(gpio))
+			retval = MSP_GPIO_OUTPUT;
+		else
+			retval = MSP_GPIO_INPUT;
+	}
+
+	return retval;
+}
+
+/*
+ * Sets the specified mode on the requested pin
+ * Returns 0 on success, or -1 if that mode is not allowed on this pin
+ */
+static inline int msp_gpio_pin_mode(enum msp_gpio_mode mode, unsigned int gpio)
+{
+	u32 modemask, newmode;
+
+	if ((1 << gpio) & ~MSP_GPIO_MODE_ALLOWED[mode])
+		return -1;
+
+	if (gpio >= MSP_NUM_GPIOS)
+		return -1;
+
+	if (gpio < 16) {
+		modemask = BASIC_MODE_MASK(gpio);
+		newmode =  BASIC_MODE(mode, gpio);
+	} else {
+		modemask = EXTENDED_FULL_MASK;
+		if (mode == MSP_GPIO_INPUT)
+			newmode = EXTENDED_DISABLE(gpio);
+		else
+			newmode = EXTENDED_ENABLE(gpio);
+	}
+	/* Do the set atomically */
+	set_value_reg32(MSP_GPIO_MODE_REGISTER[gpio], modemask, newmode);
+
+	return 0;
+}
+
+#endif /* __MSP_GPIO_MACROS_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regops.h	2011-05-19 00:06:34.000000000 -0400
@@ -205,7 +205,7 @@
  *   custom_read_reg32(address, tmp);	<-- Reads the address and put the value
  *						in the 'tmp' variable given
  *
- *	From here on out, you are (basicly) atomic, so don't do anything too
+ *	From here on out, you are (basically) atomic, so don't do anything too
  *	fancy!
  *	Also, this code may loop if the end of this block fails to write
  *	everything back safely due do the other CPU, so do NOT do anything
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -91,12 +91,10 @@
 					/* MAC C device registers       */
 #define MSP_ADSL2_BASE		(MSP_MSB_BASE + 0xA80000)
 					/* ADSL2 device registers       */
-#define MSP_USB_BASE		(MSP_MSB_BASE + 0xB40000)
-					/* USB device registers         */
-#define MSP_USB_BASE_START	(MSP_MSB_BASE + 0xB40100)
-					/* USB device registers         */
-#define MSP_USB_BASE_END	(MSP_MSB_BASE + 0xB401FF)
-					/* USB device registers         */
+#define MSP_USB0_BASE		(MSP_MSB_BASE + 0xB00000)
+					/* USB0 device registers        */
+#define MSP_USB1_BASE		(MSP_MSB_BASE + 0x300000)
+					/* USB1 device registers	*/
 #define MSP_CPUIF_BASE		(MSP_MSB_BASE + 0xC00000)
 					/* CPU interface registers      */
 
@@ -319,8 +317,11 @@
 #define CPU_ERR2_REG		regptr(MSP_SLP_BASE + 0x184)
 					/* CPU/SLP Error status 1       */
 
-#define EXTENDED_GPIO_REG	regptr(MSP_SLP_BASE + 0x188)
-					/* Extended GPIO register       */
+/* Extended GPIO registers       */
+#define EXTENDED_GPIO1_REG	regptr(MSP_SLP_BASE + 0x188)
+#define EXTENDED_GPIO2_REG	regptr(MSP_SLP_BASE + 0x18c)
+#define EXTENDED_GPIO_REG	EXTENDED_GPIO1_REG
+					/* Backward-compatibility	*/
 
 /* System Error registers */
 #define SLP_ERR_STS_REG		regptr(MSP_SLP_BASE + 0x190)
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/pmc-sierra/msp71xx/msp_usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,144 @@
+/******************************************************************
+ * Copyright (c) 2000-2007 PMC-Sierra 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.
+ *
+ * PMC-SIERRA INC. DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
+ * SOFTWARE.
+ */
+#ifndef MSP_USB_H_
+#define MSP_USB_H_
+
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+#define NUM_USB_DEVS   2
+#else
+#define NUM_USB_DEVS   1
+#endif
+
+/* Register spaces for USB host 0 */
+#define MSP_USB0_MAB_START	(MSP_USB0_BASE + 0x0)
+#define MSP_USB0_MAB_END	(MSP_USB0_BASE + 0x17)
+#define MSP_USB0_ID_START	(MSP_USB0_BASE + 0x40000)
+#define MSP_USB0_ID_END		(MSP_USB0_BASE + 0x4008f)
+#define MSP_USB0_HS_START	(MSP_USB0_BASE + 0x40100)
+#define MSP_USB0_HS_END		(MSP_USB0_BASE + 0x401FF)
+
+/* Register spaces for USB host 1 */
+#define	MSP_USB1_MAB_START	(MSP_USB1_BASE + 0x0)
+#define MSP_USB1_MAB_END	(MSP_USB1_BASE + 0x17)
+#define MSP_USB1_ID_START	(MSP_USB1_BASE + 0x40000)
+#define MSP_USB1_ID_END		(MSP_USB1_BASE + 0x4008f)
+#define MSP_USB1_HS_START	(MSP_USB1_BASE + 0x40100)
+#define MSP_USB1_HS_END		(MSP_USB1_BASE + 0x401ff)
+
+/* USB Identification registers */
+struct msp_usbid_regs {
+	u32 id;		/* 0x0: Identification register */
+	u32 hwgen;	/* 0x4: General HW params */
+	u32 hwhost;	/* 0x8: Host HW params */
+	u32 hwdev;	/* 0xc: Device HW params */
+	u32 hwtxbuf;	/* 0x10: Tx buffer HW params */
+	u32 hwrxbuf;	/* 0x14: Rx buffer HW params */
+	u32 reserved[26];
+	u32 timer0_load; /* 0x80: General-purpose timer 0 load*/
+	u32 timer0_ctrl; /* 0x84: General-purpose timer 0 control */
+	u32 timer1_load; /* 0x88: General-purpose timer 1 load*/
+	u32 timer1_ctrl; /* 0x8c: General-purpose timer 1 control */
+};
+
+/* MSBus to AMBA registers */
+struct msp_mab_regs {
+	u32 isr;	/* 0x0: Interrupt status */
+	u32 imr;	/* 0x4: Interrupt mask */
+	u32 thcr0;	/* 0x8: Transaction header capture 0 */
+	u32 thcr1;	/* 0xc: Transaction header capture 1 */
+	u32 int_stat;	/* 0x10: Interrupt status summary */
+	u32 phy_cfg;	/* 0x14: USB phy config */
+};
+
+/* EHCI registers */
+struct msp_usbhs_regs {
+	u32 hciver;	/* 0x0: Version and offset to operational regs */
+	u32 hcsparams;	/* 0x4: Host control structural parameters */
+	u32 hccparams;	/* 0x8: Host control capability parameters */
+	u32 reserved0[5];
+	u32 dciver;	/* 0x20: Device interface version */
+	u32 dccparams;	/* 0x24: Device control capability parameters */
+	u32 reserved1[6];
+	u32 cmd;	/* 0x40: USB command */
+	u32 sts;	/* 0x44: USB status */
+	u32 int_ena;	/* 0x48: USB interrupt enable */
+	u32 frindex;	/* 0x4c: Frame index */
+	u32 reserved3;
+	union {
+		struct {
+			u32 flb_addr; /* 0x54: Frame list base address */
+			u32 next_async_addr; /* 0x58: next asynchronous addr */
+			u32 ttctrl; /* 0x5c: embedded transaction translator
+							async buffer status */
+			u32 burst_size; /* 0x60: Controller burst size */
+			u32 tx_fifo_ctrl; /* 0x64: Tx latency FIFO tuning */
+			u32 reserved0[4];
+			u32 endpt_nak; /* 0x78: Endpoint NAK */
+			u32 endpt_nak_ena; /* 0x7c: Endpoint NAK enable */
+			u32 cfg_flag; /* 0x80: Config flag */
+			u32 port_sc1; /* 0x84: Port status & control 1 */
+			u32 reserved1[7];
+			u32 otgsc;	/* 0xa4: OTG status & control */
+			u32 mode;	/* 0xa8: USB controller mode */
+		} host;
+
+		struct {
+			u32 dev_addr; /* 0x54: Device address */
+			u32 endpt_list_addr; /* 0x58: Endpoint list address */
+			u32 reserved0[7];
+			u32 endpt_nak;	/* 0x74 */
+			u32 endpt_nak_ctrl; /* 0x78 */
+			u32 cfg_flag; /* 0x80 */
+			u32 port_sc1; /* 0x84: Port status & control 1 */
+			u32 reserved[7];
+			u32 otgsc;	/* 0xa4: OTG status & control */
+			u32 mode;	/* 0xa8: USB controller mode */
+			u32 endpt_setup_stat; /* 0xac */
+			u32 endpt_prime; /* 0xb0 */
+			u32 endpt_flush; /* 0xb4 */
+			u32 endpt_stat; /* 0xb8 */
+			u32 endpt_complete; /* 0xbc */
+			u32 endpt_ctrl0; /* 0xc0 */
+			u32 endpt_ctrl1; /* 0xc4 */
+			u32 endpt_ctrl2; /* 0xc8 */
+			u32 endpt_ctrl3; /* 0xcc */
+		} device;
+	} u;
+};
+/*
+ * Container for the more-generic platform_device.
+ * This exists mainly as a way to map the non-standard register
+ * spaces and make them accessible to the USB ISR.
+ */
+struct mspusb_device {
+	struct msp_mab_regs   __iomem *mab_regs;
+	struct msp_usbid_regs __iomem *usbid_regs;
+	struct msp_usbhs_regs __iomem *usbhs_regs;
+	struct platform_device dev;
+};
+
+#define to_mspusb_device(x) container_of((x), struct mspusb_device, dev)
+#define TO_HOST_ID(x) ((x) & 0x3)
+#endif /*MSP_USB_H_*/
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/processor.h linux-libre-2.6.39-gnu/arch/mips/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -337,7 +337,7 @@
 /*
  * Return_address is a replacement for __builtin_return_address(count)
  * which on certain architectures cannot reasonably be implemented in GCC
- * (MIPS, Alpha) or is unuseable with -fomit-frame-pointer (i386).
+ * (MIPS, Alpha) or is unusable with -fomit-frame-pointer (i386).
  * Note that __builtin_return_address(x>=1) is forbidden because GCC
  * aborts compilation on some CPUs.  It's simply not possible to unwind
  * some CPU's stackframes.
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/sgi/ioc.h linux-libre-2.6.39-gnu/arch/mips/include/asm/sgi/ioc.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/sgi/ioc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/sgi/ioc.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
 #include <asm/sgi/pi1.h>
 
 /*
- * All registers are 8-bit wide alligned on 32-bit boundary. Bad things
+ * All registers are 8-bit wide aligned on 32-bit boundary. Bad things
  * happen if you try word access them. You have been warned.
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/sibyte/sb1250_mac.h linux-libre-2.6.39-gnu/arch/mips/include/asm/sibyte/sb1250_mac.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/sibyte/sb1250_mac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/sibyte/sb1250_mac.h	2011-05-19 00:06:34.000000000 -0400
@@ -520,7 +520,7 @@
 #define G_MAC_RX_EOP_COUNTER(x)     _SB_GETVALUE(x, S_MAC_RX_EOP_COUNTER, M_MAC_RX_EOP_COUNTER)
 
 /*
- * MAC Recieve Address Filter Exact Match Registers (Table 9-21)
+ * MAC Receive Address Filter Exact Match Registers (Table 9-21)
  * Registers: MAC_ADDR0_0 through MAC_ADDR7_0
  * Registers: MAC_ADDR0_1 through MAC_ADDR7_1
  * Registers: MAC_ADDR0_2 through MAC_ADDR7_2
@@ -538,7 +538,7 @@
 /* No bitfields */
 
 /*
- * MAC Recieve Address Filter Hash Match Registers (Table 9-22)
+ * MAC Receive Address Filter Hash Match Registers (Table 9-22)
  * Registers: MAC_HASH0_0 through MAC_HASH7_0
  * Registers: MAC_HASH0_1 through MAC_HASH7_1
  * Registers: MAC_HASH0_2 through MAC_HASH7_2
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/siginfo.h linux-libre-2.6.39-gnu/arch/mips/include/asm/siginfo.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/siginfo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/siginfo.h	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 
 /*
  * si_code values
- * Again these have been choosen to be IRIX compatible.
+ * Again these have been chosen to be IRIX compatible.
  */
 #undef SI_ASYNCIO
 #undef SI_TIMER
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/sn/klconfig.h linux-libre-2.6.39-gnu/arch/mips/include/asm/sn/klconfig.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/sn/klconfig.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/sn/klconfig.h	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
  */
 #define MAX_SLOTS_PER_NODE	(1 + 2 + 6 + 2)
 
-/* XXX if each node is guranteed to have some memory */
+/* XXX if each node is guaranteed to have some memory */
 
 #define MAX_PCI_DEVS		8
 
@@ -539,7 +539,7 @@
 #define KLSTRUCT_IOC3_TTY 	24
 
 /* Early Access IO proms are compatible
-   only with KLSTRUCT values upto 24. */
+   only with KLSTRUCT values up to 24. */
 
 #define KLSTRUCT_FIBERCHANNEL 	25
 #define KLSTRUCT_MOD_SERIAL_NUM 26
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/sn/sn0/hubio.h linux-libre-2.6.39-gnu/arch/mips/include/asm/sn/sn0/hubio.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/sn/sn0/hubio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/sn/sn0/hubio.h	2011-05-19 00:06:34.000000000 -0400
@@ -622,7 +622,7 @@
  */
 #define	IIO_ICRB_PROC0		0	/* Source of request is Proc 0 */
 #define	IIO_ICRB_PROC1		1	/* Source of request is Proc 1 */
-#define	IIO_ICRB_GB_REQ		2	/* Source is Guranteed BW request */
+#define	IIO_ICRB_GB_REQ		2	/* Source is Guaranteed BW request */
 #define	IIO_ICRB_IO_REQ		3	/* Source is Normal IO request	*/
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/spinlock.h linux-libre-2.6.39-gnu/arch/mips/include/asm/spinlock.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/spinlock.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/spinlock.h	2011-05-19 00:06:34.000000000 -0400
@@ -245,16 +245,16 @@
 		__asm__ __volatile__(
 		"	.set	noreorder	# arch_read_lock	\n"
 		"1:	ll	%1, %2					\n"
-		"	bltz	%1, 2f					\n"
+		"	bltz	%1, 3f					\n"
 		"	 addu	%1, 1					\n"
-		"	sc	%1, %0					\n"
+		"2:	sc	%1, %0					\n"
 		"	beqz	%1, 1b					\n"
 		"	 nop						\n"
 		"	.subsection 2					\n"
-		"2:	ll	%1, %2					\n"
-		"	bltz	%1, 2b					\n"
+		"3:	ll	%1, %2					\n"
+		"	bltz	%1, 3b					\n"
 		"	 addu	%1, 1					\n"
-		"	b	1b					\n"
+		"	b	2b					\n"
 		"	 nop						\n"
 		"	.previous					\n"
 		"	.set	reorder					\n"
@@ -324,16 +324,16 @@
 		__asm__ __volatile__(
 		"	.set	noreorder	# arch_write_lock	\n"
 		"1:	ll	%1, %2					\n"
-		"	bnez	%1, 2f					\n"
+		"	bnez	%1, 3f					\n"
 		"	 lui	%1, 0x8000				\n"
-		"	sc	%1, %0					\n"
-		"	beqz	%1, 2f					\n"
+		"2:	sc	%1, %0					\n"
+		"	beqz	%1, 3f					\n"
 		"	 nop						\n"
 		"	.subsection 2					\n"
-		"2:	ll	%1, %2					\n"
-		"	bnez	%1, 2b					\n"
+		"3:	ll	%1, %2					\n"
+		"	bnez	%1, 3b					\n"
 		"	 lui	%1, 0x8000				\n"
-		"	b	1b					\n"
+		"	b	2b					\n"
 		"	 nop						\n"
 		"	.previous					\n"
 		"	.set	reorder					\n"
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/stackframe.h linux-libre-2.6.39-gnu/arch/mips/include/asm/stackframe.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/stackframe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/stackframe.h	2011-05-19 00:06:34.000000000 -0400
@@ -346,7 +346,7 @@
 		 * we can't dispatch it directly without trashing
 		 * some registers, so we'll try to detect this unlikely
 		 * case and program a software interrupt in the VPE,
-		 * as would be done for a cross-VPE IPI.  To accomodate
+		 * as would be done for a cross-VPE IPI.  To accommodate
 		 * the handling of that case, we're doing a DVPE instead
 		 * of just a DMT here to protect against other threads.
 		 * This is a lot of cruft to cover a tiny window.
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/mips/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -88,9 +88,11 @@
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node) \
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node) \
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
 #define free_thread_info(info) kfree(info)
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/types.h linux-libre-2.6.39-gnu/arch/mips/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,14 +33,6 @@
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
-#if (defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) \
-    || defined(CONFIG_64BIT)
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
-typedef u64 dma64_addr_t;
-
 /*
  * Don't use phys_t.  You've been warned.
  */
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/mips/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -359,16 +359,20 @@
 #define __NR_fanotify_init		(__NR_Linux + 336)
 #define __NR_fanotify_mark		(__NR_Linux + 337)
 #define __NR_prlimit64			(__NR_Linux + 338)
+#define __NR_name_to_handle_at		(__NR_Linux + 339)
+#define __NR_open_by_handle_at		(__NR_Linux + 340)
+#define __NR_clock_adjtime		(__NR_Linux + 341)
+#define __NR_syncfs			(__NR_Linux + 342)
 
 /*
  * Offset of the last Linux o32 flavoured syscall
  */
-#define __NR_Linux_syscalls		338
+#define __NR_Linux_syscalls		342
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI32 */
 
 #define __NR_O32_Linux			4000
-#define __NR_O32_Linux_syscalls		338
+#define __NR_O32_Linux_syscalls		342
 
 #if _MIPS_SIM == _MIPS_SIM_ABI64
 
@@ -674,16 +678,20 @@
 #define __NR_fanotify_init		(__NR_Linux + 295)
 #define __NR_fanotify_mark		(__NR_Linux + 296)
 #define __NR_prlimit64			(__NR_Linux + 297)
+#define __NR_name_to_handle_at		(__NR_Linux + 298)
+#define __NR_open_by_handle_at		(__NR_Linux + 299)
+#define __NR_clock_adjtime		(__NR_Linux + 300)
+#define __NR_syncfs			(__NR_Linux + 301)
 
 /*
  * Offset of the last Linux 64-bit flavoured syscall
  */
-#define __NR_Linux_syscalls		297
+#define __NR_Linux_syscalls		301
 
 #endif /* _MIPS_SIM == _MIPS_SIM_ABI64 */
 
 #define __NR_64_Linux			5000
-#define __NR_64_Linux_syscalls		297
+#define __NR_64_Linux_syscalls		301
 
 #if _MIPS_SIM == _MIPS_SIM_NABI32
 
@@ -994,16 +1002,20 @@
 #define __NR_fanotify_init		(__NR_Linux + 300)
 #define __NR_fanotify_mark		(__NR_Linux + 301)
 #define __NR_prlimit64			(__NR_Linux + 302)
+#define __NR_name_to_handle_at		(__NR_Linux + 303)
+#define __NR_open_by_handle_at		(__NR_Linux + 304)
+#define __NR_clock_adjtime		(__NR_Linux + 305)
+#define __NR_syncfs			(__NR_Linux + 306)
 
 /*
  * Offset of the last N32 flavoured syscall
  */
-#define __NR_Linux_syscalls		302
+#define __NR_Linux_syscalls		306
 
 #endif /* _MIPS_SIM == _MIPS_SIM_NABI32 */
 
 #define __NR_N32_Linux			6000
-#define __NR_N32_Linux_syscalls		302
+#define __NR_N32_Linux_syscalls		306
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/include/asm/war.h linux-libre-2.6.39-gnu/arch/mips/include/asm/war.h
--- linux-libre-2.6.38-gnu/arch/mips/include/asm/war.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/include/asm/war.h	2011-05-19 00:06:34.000000000 -0400
@@ -227,7 +227,7 @@
 #endif
 
 /*
- * On the R10000 upto version 2.6 (not sure about 2.7) there is a bug that
+ * On the R10000 up to version 2.6 (not sure about 2.7) there is a bug that
  * may cause ll / sc and lld / scd sequences to execute non-atomically.
  */
 #ifndef R10000_LLSC_WAR
diff -druN linux-libre-2.6.38-gnu/arch/mips/jazz/irq.c linux-libre-2.6.39-gnu/arch/mips/jazz/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/jazz/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jazz/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,9 +23,9 @@
 
 static DEFINE_RAW_SPINLOCK(r4030_lock);
 
-static void enable_r4030_irq(unsigned int irq)
+static void enable_r4030_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq - JAZZ_IRQ_START);
+	unsigned int mask = 1 << (d->irq - JAZZ_IRQ_START);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&r4030_lock, flags);
@@ -34,9 +34,9 @@
 	raw_spin_unlock_irqrestore(&r4030_lock, flags);
 }
 
-void disable_r4030_irq(unsigned int irq)
+void disable_r4030_irq(struct irq_data *d)
 {
-	unsigned int mask = ~(1 << (irq - JAZZ_IRQ_START));
+	unsigned int mask = ~(1 << (d->irq - JAZZ_IRQ_START));
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&r4030_lock, flags);
@@ -47,10 +47,8 @@
 
 static struct irq_chip r4030_irq_type = {
 	.name = "R4030",
-	.ack = disable_r4030_irq,
-	.mask = disable_r4030_irq,
-	.mask_ack = disable_r4030_irq,
-	.unmask = enable_r4030_irq,
+	.irq_mask = disable_r4030_irq,
+	.irq_unmask = enable_r4030_irq,
 };
 
 void __init init_r4030_ints(void)
@@ -58,7 +56,7 @@
 	int i;
 
 	for (i = JAZZ_IRQ_START; i <= JAZZ_IRQ_END; i++)
-		set_irq_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &r4030_irq_type, handle_level_irq);
 
 	r4030_write_reg16(JAZZ_IO_IRQ_ENABLE, 0);
 	r4030_read_reg16(JAZZ_IO_IRQ_SOURCE);		/* clear pending IRQs */
diff -druN linux-libre-2.6.38-gnu/arch/mips/jazz/jazzdma.c linux-libre-2.6.39-gnu/arch/mips/jazz/jazzdma.c
--- linux-libre-2.6.38-gnu/arch/mips/jazz/jazzdma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jazz/jazzdma.c	2011-05-19 00:06:34.000000000 -0400
@@ -211,7 +211,7 @@
  */
 int vdma_remap(unsigned long laddr, unsigned long paddr, unsigned long size)
 {
-	int first, pages, npages;
+	int first, pages;
 
 	if (laddr > 0xffffff) {
 		if (vdma_debug)
@@ -228,8 +228,7 @@
 		return -EINVAL;	/* invalid physical address */
 	}
 
-	npages = pages =
-	    (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
+	pages = (((paddr & (VDMA_PAGESIZE - 1)) + size) >> 12) + 1;
 	first = laddr >> 12;
 	if (vdma_debug)
 		printk("vdma_remap: first=%x, pages=%x\n", first, pages);
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/board-qi_lb60.c linux-libre-2.6.39-gnu/arch/mips/jz4740/board-qi_lb60.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/board-qi_lb60.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/board-qi_lb60.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/spi/spi_gpio.h>
 #include <linux/power_supply.h>
 #include <linux/power/jz4740-battery.h>
+#include <linux/power/gpio-charger.h>
 
 #include <asm/mach-jz4740/jz4740_fb.h>
 #include <asm/mach-jz4740/jz4740_mmc.h>
@@ -49,14 +50,14 @@
 
 /* NAND */
 static struct nand_ecclayout qi_lb60_ecclayout_1gb = {
-/*	.eccbytes = 36,
+	.eccbytes = 36,
 	.eccpos = {
 		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
-	},*/
+	},
 	.oobfree = {
 		{ .offset = 2, .length = 4 },
 		{ .offset = 42, .length = 22 }
@@ -64,7 +65,7 @@
 };
 
 /* Early prototypes of the QI LB60 had only 1GB of NAND.
- * In order to support these devices aswell the partition and ecc layout is
+ * In order to support these devices as well the partition and ecc layout is
  * initialized depending on the NAND size */
 static struct mtd_partition qi_lb60_partitions_1gb[] = {
 	{
@@ -85,7 +86,7 @@
 };
 
 static struct nand_ecclayout qi_lb60_ecclayout_2gb = {
-/*	.eccbytes = 72,
+	.eccbytes = 72,
 	.eccpos = {
 		12, 13, 14, 15, 16, 17, 18, 19,
 		20, 21, 22, 23, 24, 25, 26, 27,
@@ -96,7 +97,7 @@
 		60, 61, 62, 63, 64, 65, 66, 67,
 		68, 69, 70, 71, 72, 73, 74, 75,
 		76, 77, 78, 79, 80, 81, 82, 83
-	},*/
+	},
 	.oobfree = {
 		{ .offset = 2, .length = 10 },
 		{ .offset = 84, .length = 44 },
@@ -396,6 +397,28 @@
 	},
 };
 
+/* charger */
+static char *qi_lb60_batteries[] = {
+	"battery",
+};
+
+static struct gpio_charger_platform_data qi_lb60_charger_pdata = {
+	.name = "usb",
+	.type = POWER_SUPPLY_TYPE_USB,
+	.gpio = JZ_GPIO_PORTD(28),
+	.gpio_active_low = 1,
+	.supplied_to = qi_lb60_batteries,
+	.num_supplicants = ARRAY_SIZE(qi_lb60_batteries),
+};
+
+static struct platform_device qi_lb60_charger_device = {
+	.name = "gpio-charger",
+	.dev = {
+		.platform_data = &qi_lb60_charger_pdata,
+	},
+};
+
+
 static struct platform_device *jz_platform_devices[] __initdata = {
 	&jz4740_udc_device,
 	&jz4740_mmc_device,
@@ -410,12 +433,13 @@
 	&jz4740_adc_device,
 	&qi_lb60_gpio_keys,
 	&qi_lb60_pwm_beeper,
+	&qi_lb60_charger_device,
 };
 
 static void __init board_gpio_setup(void)
 {
 	/* We only need to enable/disable pullup here for pins used in generic
-	 * drivers. Everything else is done by the drivers themselfs. */
+	 * drivers. Everything else is done by the drivers themselves. */
 	jz_gpio_disable_pullup(QI_LB60_GPIO_SD_VCC_EN_N);
 	jz_gpio_disable_pullup(QI_LB60_GPIO_SD_CD);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/dma.c linux-libre-2.6.39-gnu/arch/mips/jz4740/dma.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -242,9 +242,7 @@
 
 static void jz4740_dma_chan_irq(struct jz4740_dma_chan *dma)
 {
-	uint32_t status;
-
-	status = jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
+	(void) jz4740_dma_read(JZ_REG_DMA_STATUS_CTRL(dma->id));
 
 	jz4740_dma_write_mask(JZ_REG_DMA_STATUS_CTRL(dma->id), 0,
 		JZ_DMA_STATUS_CTRL_ENABLE | JZ_DMA_STATUS_CTRL_TRANSFER_DONE);
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/gpio.c linux-libre-2.6.39-gnu/arch/mips/jz4740/gpio.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,6 @@
 	spinlock_t lock;
 
 	struct gpio_chip gpio_chip;
-	struct irq_chip irq_chip;
 	struct sys_device sysdev;
 };
 
@@ -102,9 +101,9 @@
 	return container_of(gpio_chip, struct jz_gpio_chip, gpio_chip);
 }
 
-static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(unsigned int irq)
+static inline struct jz_gpio_chip *irq_to_jz_gpio_chip(struct irq_data *data)
 {
-	return get_irq_chip_data(irq);
+	return irq_data_get_irq_chip_data(data);
 }
 
 static inline void jz_gpio_write_bit(unsigned int gpio, unsigned int reg)
@@ -307,7 +306,7 @@
 	uint32_t flag;
 	unsigned int gpio_irq;
 	unsigned int gpio_bank;
-	struct jz_gpio_chip *chip = get_irq_desc_data(desc);
+	struct jz_gpio_chip *chip = irq_desc_get_handler_data(desc);
 
 	gpio_bank = JZ4740_IRQ_GPIO0 - irq;
 
@@ -325,62 +324,52 @@
 	generic_handle_irq(gpio_irq);
 };
 
-static inline void jz_gpio_set_irq_bit(unsigned int irq, unsigned int reg)
+static inline void jz_gpio_set_irq_bit(struct irq_data *data, unsigned int reg)
 {
-	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
-	writel(IRQ_TO_BIT(irq), chip->base + reg);
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
+	writel(IRQ_TO_BIT(data->irq), chip->base + reg);
 }
 
-static void jz_gpio_irq_mask(unsigned int irq)
+static void jz_gpio_irq_mask(struct irq_data *data)
 {
-	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_SET);
+	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_SET);
 };
 
-static void jz_gpio_irq_unmask(unsigned int irq)
+static void jz_gpio_irq_unmask(struct irq_data *data)
 {
-	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
 
-	jz_gpio_check_trigger_both(chip, irq);
+	jz_gpio_check_trigger_both(chip, data->irq);
 
-	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_MASK_CLEAR);
+	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_MASK_CLEAR);
 };
 
 /* TODO: Check if function is gpio */
-static unsigned int jz_gpio_irq_startup(unsigned int irq)
+static unsigned int jz_gpio_irq_startup(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_SET);
-
-	desc->status &= ~IRQ_MASKED;
-	jz_gpio_irq_unmask(irq);
-
+	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_SET);
+	jz_gpio_irq_unmask(data);
 	return 0;
 }
 
-static void jz_gpio_irq_shutdown(unsigned int irq)
+static void jz_gpio_irq_shutdown(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	jz_gpio_irq_mask(irq);
-	desc->status |= IRQ_MASKED;
+	jz_gpio_irq_mask(data);
 
 	/* Set direction to input */
-	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
-	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_SELECT_CLEAR);
+	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR);
+	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_SELECT_CLEAR);
 }
 
-static void jz_gpio_irq_ack(unsigned int irq)
+static void jz_gpio_irq_ack(struct irq_data *data)
 {
-	jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_FLAG_CLEAR);
+	jz_gpio_set_irq_bit(data, JZ_REG_GPIO_FLAG_CLEAR);
 };
 
-static int jz_gpio_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int jz_gpio_irq_set_type(struct irq_data *data, unsigned int flow_type)
 {
-	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
-	struct irq_desc *desc = irq_to_desc(irq);
-
-	jz_gpio_irq_mask(irq);
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
+	unsigned int irq = data->irq;
 
 	if (flow_type == IRQ_TYPE_EDGE_BOTH) {
 		uint32_t value = readl(chip->base + JZ_REG_GPIO_PIN);
@@ -395,45 +384,54 @@
 
 	switch (flow_type) {
 	case IRQ_TYPE_EDGE_RISING:
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET);
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_SET);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_SET);
 		break;
 	case IRQ_TYPE_EDGE_FALLING:
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_SET);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_SET);
 		break;
 	case IRQ_TYPE_LEVEL_HIGH:
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_SET);
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_SET);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_CLEAR);
 		break;
 	case IRQ_TYPE_LEVEL_LOW:
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_DIRECTION_CLEAR);
-		jz_gpio_set_irq_bit(irq, JZ_REG_GPIO_TRIGGER_CLEAR);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_DIRECTION_CLEAR);
+		jz_gpio_set_irq_bit(data, JZ_REG_GPIO_TRIGGER_CLEAR);
 		break;
 	default:
 		return -EINVAL;
 	}
 
-	if (!(desc->status & IRQ_MASKED))
-		jz_gpio_irq_unmask(irq);
-
 	return 0;
 }
 
-static int jz_gpio_irq_set_wake(unsigned int irq, unsigned int on)
+static int jz_gpio_irq_set_wake(struct irq_data *data, unsigned int on)
 {
-	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(irq);
+	struct jz_gpio_chip *chip = irq_to_jz_gpio_chip(data);
 	spin_lock(&chip->lock);
 	if (on)
-		chip->wakeup |= IRQ_TO_BIT(irq);
+		chip->wakeup |= IRQ_TO_BIT(data->irq);
 	else
-		chip->wakeup &= ~IRQ_TO_BIT(irq);
+		chip->wakeup &= ~IRQ_TO_BIT(data->irq);
 	spin_unlock(&chip->lock);
 
-	set_irq_wake(chip->irq, on);
+	irq_set_irq_wake(chip->irq, on);
 	return 0;
 }
 
+static struct irq_chip jz_gpio_irq_chip = {
+	.name = "GPIO",
+	.irq_mask = jz_gpio_irq_mask,
+	.irq_unmask = jz_gpio_irq_unmask,
+	.irq_ack = jz_gpio_irq_ack,
+	.irq_startup = jz_gpio_irq_startup,
+	.irq_shutdown = jz_gpio_irq_shutdown,
+	.irq_set_type = jz_gpio_irq_set_type,
+	.irq_set_wake = jz_gpio_irq_set_wake,
+	.flags = IRQCHIP_SET_TYPE_MASKED,
+};
+
 /*
  * This lock class tells lockdep that GPIO irqs are in a different
  * category than their parents, so it won't report false recursion.
@@ -452,16 +450,6 @@
 		.base = JZ4740_GPIO_BASE_ ## _bank, \
 		.ngpio = JZ4740_GPIO_NUM_ ## _bank, \
 	}, \
-	.irq_chip =  { \
-		.name = "GPIO Bank " # _bank, \
-		.mask = jz_gpio_irq_mask, \
-		.unmask = jz_gpio_irq_unmask, \
-		.ack = jz_gpio_irq_ack, \
-		.startup = jz_gpio_irq_startup, \
-		.shutdown = jz_gpio_irq_shutdown, \
-		.set_type = jz_gpio_irq_set_type, \
-		.set_wake = jz_gpio_irq_set_wake, \
-	}, \
 }
 
 static struct jz_gpio_chip jz4740_gpio_chips[] = {
@@ -522,13 +510,14 @@
 	gpiochip_add(&chip->gpio_chip);
 
 	chip->irq = JZ4740_IRQ_INTC_GPIO(id);
-	set_irq_data(chip->irq, chip);
-	set_irq_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
+	irq_set_handler_data(chip->irq, chip);
+	irq_set_chained_handler(chip->irq, jz_gpio_irq_demux_handler);
 
 	for (irq = chip->irq_base; irq < chip->irq_base + chip->gpio_chip.ngpio; ++irq) {
-		lockdep_set_class(&irq_desc[irq].lock, &gpio_lock_class);
-		set_irq_chip_data(irq, chip);
-		set_irq_chip_and_handler(irq, &chip->irq_chip, handle_level_irq);
+		irq_set_lockdep_class(irq, &gpio_lock_class);
+		irq_set_chip_data(irq, chip);
+		irq_set_chip_and_handler(irq, &jz_gpio_irq_chip,
+					 handle_level_irq);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/irq.c linux-libre-2.6.39-gnu/arch/mips/jz4740/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,32 +43,37 @@
 
 #define IRQ_BIT(x) BIT((x) - JZ4740_IRQ_BASE)
 
-static void intc_irq_unmask(unsigned int irq)
+static inline unsigned long intc_irq_bit(struct irq_data *data)
 {
-	writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
+	return (unsigned long)irq_data_get_irq_chip_data(data);
 }
 
-static void intc_irq_mask(unsigned int irq)
+static void intc_irq_unmask(struct irq_data *data)
 {
-	writel(IRQ_BIT(irq), jz_intc_base + JZ_REG_INTC_SET_MASK);
+	writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_CLEAR_MASK);
 }
 
-static int intc_irq_set_wake(unsigned int irq, unsigned int on)
+static void intc_irq_mask(struct irq_data *data)
+{
+	writel(intc_irq_bit(data), jz_intc_base + JZ_REG_INTC_SET_MASK);
+}
+
+static int intc_irq_set_wake(struct irq_data *data, unsigned int on)
 {
 	if (on)
-		jz_intc_wakeup |= IRQ_BIT(irq);
+		jz_intc_wakeup |= intc_irq_bit(data);
 	else
-		jz_intc_wakeup &= ~IRQ_BIT(irq);
+		jz_intc_wakeup &= ~intc_irq_bit(data);
 
 	return 0;
 }
 
 static struct irq_chip intc_irq_type = {
 	.name =		"INTC",
-	.mask =		intc_irq_mask,
-	.mask_ack =	intc_irq_mask,
-	.unmask =	intc_irq_unmask,
-	.set_wake =	intc_irq_set_wake,
+	.irq_mask =	intc_irq_mask,
+	.irq_mask_ack =	intc_irq_mask,
+	.irq_unmask =	intc_irq_unmask,
+	.irq_set_wake =	intc_irq_set_wake,
 };
 
 static irqreturn_t jz4740_cascade(int irq, void *data)
@@ -95,9 +100,12 @@
 
 	jz_intc_base = ioremap(JZ4740_INTC_BASE_ADDR, 0x14);
 
+	/* Mask all irqs */
+	writel(0xffffffff, jz_intc_base + JZ_REG_INTC_SET_MASK);
+
 	for (i = JZ4740_IRQ_BASE; i < JZ4740_IRQ_BASE + 32; i++) {
-		intc_irq_mask(i);
-		set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+		irq_set_chip_data(i, (void *)IRQ_BIT(i));
+		irq_set_chip_and_handler(i, &intc_irq_type, handle_level_irq);
 	}
 
 	setup_irq(2, &jz4740_cascade_action);
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/Makefile linux-libre-2.6.39-gnu/arch/mips/jz4740/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -17,4 +17,4 @@
 
 obj-$(CONFIG_PM) += pm.o
 
-EXTRA_CFLAGS += -Werror -Wall
+ccflags-y := -Werror -Wall
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/platform.c linux-libre-2.6.39-gnu/arch/mips/jz4740/platform.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -289,3 +289,19 @@
 
 	platform_device_register(&jz4740_uart_device);
 }
+
+/* Watchdog */
+static struct resource jz4740_wdt_resources[] = {
+	{
+		.start = JZ4740_WDT_BASE_ADDR,
+		.end   = JZ4740_WDT_BASE_ADDR + 0x10 - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+struct platform_device jz4740_wdt_device = {
+	.name          = "jz4740-wdt",
+	.id            = -1,
+	.num_resources = ARRAY_SIZE(jz4740_wdt_resources),
+	.resource      = jz4740_wdt_resources,
+};
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/time.c linux-libre-2.6.39-gnu/arch/mips/jz4740/time.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,7 +89,7 @@
 
 static struct clock_event_device jz4740_clockevent = {
 	.name = "jz4740-timer",
-	.features = CLOCK_EVT_FEAT_PERIODIC,
+	.features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
 	.set_next_event = jz4740_clockevent_set_next,
 	.set_mode = jz4740_clockevent_set_mode,
 	.rating = 200,
diff -druN linux-libre-2.6.38-gnu/arch/mips/jz4740/timer.c linux-libre-2.6.39-gnu/arch/mips/jz4740/timer.c
--- linux-libre-2.6.38-gnu/arch/mips/jz4740/timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/jz4740/timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,11 +27,13 @@
 {
 	writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_CLEAR);
 }
+EXPORT_SYMBOL_GPL(jz4740_timer_enable_watchdog);
 
 void jz4740_timer_disable_watchdog(void)
 {
 	writel(BIT(16), jz4740_timer_base + JZ_REG_TIMER_STOP_SET);
 }
+EXPORT_SYMBOL_GPL(jz4740_timer_disable_watchdog);
 
 void __init jz4740_timer_init(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/mips/Kconfig linux-libre-2.6.39-gnu/arch/mips/Kconfig
--- linux-libre-2.6.38-gnu/arch/mips/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 	select HAVE_DMA_API_DEBUG
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
 	select HAVE_ARCH_JUMP_LABEL
 
 menu "Machine selection"
@@ -777,6 +778,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_HWEIGHT
 	bool
 	default y
@@ -858,6 +863,9 @@
 config CFE
 	bool
 
+config ARCH_DMA_ADDR_T_64BIT
+	def_bool (HIGHMEM && 64BIT_PHYS_ADDR) || 64BIT
+
 config DMA_COHERENT
 	bool
 
@@ -989,9 +997,6 @@
 config IRQ_GIC
 	bool
 
-config IRQ_CPU_OCTEON
-	bool
-
 config MIPS_BOARDS_GEN
 	bool
 
@@ -1127,7 +1132,7 @@
 	  The Loongson 2E processor implements the MIPS III instruction set
 	  with many extensions.
 
-	  It has an internal FPGA northbridge, which is compatiable to
+	  It has an internal FPGA northbridge, which is compatible to
 	  bonito64.
 
 config CPU_LOONGSON2F
@@ -1351,8 +1356,6 @@
 config CPU_CAVIUM_OCTEON
 	bool "Cavium Octeon processor"
 	depends on SYS_HAS_CPU_CAVIUM_OCTEON
-	select IRQ_CPU
-	select IRQ_CPU_OCTEON
 	select CPU_HAS_PREFETCH
 	select CPU_SUPPORTS_64BIT_KERNEL
 	select SYS_SUPPORTS_SMP
@@ -2340,6 +2343,16 @@
 
 source "drivers/pci/hotplug/Kconfig"
 
+config RAPIDIO
+	bool "RapidIO support"
+	depends on PCI
+	default n
+	help
+	  If you say Y here, the kernel will include drivers and
+	  infrastructure code to support RapidIO interconnect devices.
+
+source "drivers/rapidio/Kconfig"
+
 endmenu
 
 menu "Executable file formats"
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/cpu-bugs64.c linux-libre-2.6.39-gnu/arch/mips/kernel/cpu-bugs64.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/cpu-bugs64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/cpu-bugs64.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
 		: "0" (5), "1" (8), "2" (5));
 	align_mod(align, mod);
 	/*
-	 * The trailing nop is needed to fullfill the two-instruction
+	 * The trailing nop is needed to fulfill the two-instruction
 	 * requirement between reading hi/lo and staring a mult/div.
 	 * Leaving it out may cause gas insert a nop itself breaking
 	 * the desired alignment of the next chunk.
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/ftrace.c linux-libre-2.6.39-gnu/arch/mips/kernel/ftrace.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/ftrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 
 #define JAL 0x0c000000		/* jump & link: ip --> ra, jump to target */
 #define ADDR_MASK 0x03ffffff	/*  op_code|addr : 31...26|25 ....0 */
+#define JUMP_RANGE_MASK ((1UL << 28) - 1)
 
 #define INSN_NOP 0x00000000	/* nop */
 #define INSN_JAL(addr)	\
@@ -44,12 +45,12 @@
 
 	/* jal (ftrace_caller + 8), jump over the first two instruction */
 	buf = (u32 *)&insn_jal_ftrace_caller;
-	uasm_i_jal(&buf, (FTRACE_ADDR + 8));
+	uasm_i_jal(&buf, (FTRACE_ADDR + 8) & JUMP_RANGE_MASK);
 
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
 	/* j ftrace_graph_caller */
 	buf = (u32 *)&insn_j_ftrace_graph_caller;
-	uasm_i_j(&buf, (unsigned long)ftrace_graph_caller);
+	uasm_i_j(&buf, (unsigned long)ftrace_graph_caller & JUMP_RANGE_MASK);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/i8259.c linux-libre-2.6.39-gnu/arch/mips/kernel/i8259.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/i8259.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/i8259.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,19 +31,19 @@
 
 static int i8259A_auto_eoi = -1;
 DEFINE_RAW_SPINLOCK(i8259A_lock);
-static void disable_8259A_irq(unsigned int irq);
-static void enable_8259A_irq(unsigned int irq);
-static void mask_and_ack_8259A(unsigned int irq);
+static void disable_8259A_irq(struct irq_data *d);
+static void enable_8259A_irq(struct irq_data *d);
+static void mask_and_ack_8259A(struct irq_data *d);
 static void init_8259A(int auto_eoi);
 
 static struct irq_chip i8259A_chip = {
-	.name		= "XT-PIC",
-	.mask		= disable_8259A_irq,
-	.disable	= disable_8259A_irq,
-	.unmask		= enable_8259A_irq,
-	.mask_ack	= mask_and_ack_8259A,
+	.name			= "XT-PIC",
+	.irq_mask		= disable_8259A_irq,
+	.irq_disable		= disable_8259A_irq,
+	.irq_unmask		= enable_8259A_irq,
+	.irq_mask_ack		= mask_and_ack_8259A,
 #ifdef CONFIG_MIPS_MT_SMTC_IRQAFF
-	.set_affinity	= plat_set_irq_affinity,
+	.irq_set_affinity	= plat_set_irq_affinity,
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
 };
 
@@ -59,12 +59,11 @@
 #define cached_master_mask	(cached_irq_mask)
 #define cached_slave_mask	(cached_irq_mask >> 8)
 
-static void disable_8259A_irq(unsigned int irq)
+static void disable_8259A_irq(struct irq_data *d)
 {
-	unsigned int mask;
+	unsigned int mask, irq = d->irq - I8259A_IRQ_BASE;
 	unsigned long flags;
 
-	irq -= I8259A_IRQ_BASE;
 	mask = 1 << irq;
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	cached_irq_mask |= mask;
@@ -75,12 +74,11 @@
 	raw_spin_unlock_irqrestore(&i8259A_lock, flags);
 }
 
-static void enable_8259A_irq(unsigned int irq)
+static void enable_8259A_irq(struct irq_data *d)
 {
-	unsigned int mask;
+	unsigned int mask, irq = d->irq - I8259A_IRQ_BASE;
 	unsigned long flags;
 
-	irq -= I8259A_IRQ_BASE;
 	mask = ~(1 << irq);
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	cached_irq_mask &= mask;
@@ -112,7 +110,7 @@
 void make_8259A_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	set_irq_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
+	irq_set_chip_and_handler(irq, &i8259A_chip, handle_level_irq);
 	enable_irq(irq);
 }
 
@@ -145,12 +143,11 @@
  * first, _then_ send the EOI, and the order of EOI
  * to the two 8259s is important!
  */
-static void mask_and_ack_8259A(unsigned int irq)
+static void mask_and_ack_8259A(struct irq_data *d)
 {
-	unsigned int irqmask;
+	unsigned int irqmask, irq = d->irq - I8259A_IRQ_BASE;
 	unsigned long flags;
 
-	irq -= I8259A_IRQ_BASE;
 	irqmask = 1 << irq;
 	raw_spin_lock_irqsave(&i8259A_lock, flags);
 	/*
@@ -290,9 +287,9 @@
 		 * In AEOI mode we just have to mask the interrupt
 		 * when acking.
 		 */
-		i8259A_chip.mask_ack = disable_8259A_irq;
+		i8259A_chip.irq_mask_ack = disable_8259A_irq;
 	else
-		i8259A_chip.mask_ack = mask_and_ack_8259A;
+		i8259A_chip.irq_mask_ack = mask_and_ack_8259A;
 
 	udelay(100);		/* wait for 8259A to initialize */
 
@@ -339,8 +336,8 @@
 	init_8259A(0);
 
 	for (i = I8259A_IRQ_BASE; i < I8259A_IRQ_BASE + 16; i++) {
-		set_irq_chip_and_handler(i, &i8259A_chip, handle_level_irq);
-		set_irq_probe(i);
+		irq_set_chip_and_handler(i, &i8259A_chip, handle_level_irq);
+		irq_set_probe(i);
 	}
 
 	setup_irq(I8259A_IRQ_BASE + PIC_CASCADE_IR, &irq2);
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,48 +81,9 @@
 
 atomic_t irq_err_count;
 
-/*
- * Generic, controller-independent functions:
- */
-
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ", j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ", i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
-		seq_putc(p, '\n');
-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-	}
+	seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
 	return 0;
 }
 
@@ -141,7 +102,7 @@
 #endif
 
 	for (i = 0; i < NR_IRQS; i++)
-		set_irq_noprobe(i);
+		irq_set_noprobe(i);
 
 	arch_init_irq();
 
@@ -183,8 +144,8 @@
 {
 	irq_enter();
 	check_stack_overflow();
-	__DO_IRQ_SMTC_HOOK(irq);
-	generic_handle_irq(irq);
+	if (!smtc_handle_on_other_cpu(irq))
+		generic_handle_irq(irq);
 	irq_exit();
 }
 
@@ -197,7 +158,7 @@
 void __irq_entry do_IRQ_no_affinity(unsigned int irq)
 {
 	irq_enter();
-	__NO_AFFINITY_IRQ_SMTC_HOOK(irq);
+	smtc_im_backstop(irq);
 	generic_handle_irq(irq);
 	irq_exit();
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq_cpu.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq_cpu.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq_cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq_cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,42 +37,38 @@
 #include <asm/mipsmtregs.h>
 #include <asm/system.h>
 
-static inline void unmask_mips_irq(unsigned int irq)
+static inline void unmask_mips_irq(struct irq_data *d)
 {
-	set_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE));
+	set_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
 	irq_enable_hazard();
 }
 
-static inline void mask_mips_irq(unsigned int irq)
+static inline void mask_mips_irq(struct irq_data *d)
 {
-	clear_c0_status(0x100 << (irq - MIPS_CPU_IRQ_BASE));
+	clear_c0_status(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
 	irq_disable_hazard();
 }
 
 static struct irq_chip mips_cpu_irq_controller = {
 	.name		= "MIPS",
-	.ack		= mask_mips_irq,
-	.mask		= mask_mips_irq,
-	.mask_ack	= mask_mips_irq,
-	.unmask		= unmask_mips_irq,
-	.eoi		= unmask_mips_irq,
+	.irq_ack	= mask_mips_irq,
+	.irq_mask	= mask_mips_irq,
+	.irq_mask_ack	= mask_mips_irq,
+	.irq_unmask	= unmask_mips_irq,
+	.irq_eoi	= unmask_mips_irq,
 };
 
 /*
  * Basically the same as above but taking care of all the MT stuff
  */
 
-#define unmask_mips_mt_irq	unmask_mips_irq
-#define mask_mips_mt_irq	mask_mips_irq
-
-static unsigned int mips_mt_cpu_irq_startup(unsigned int irq)
+static unsigned int mips_mt_cpu_irq_startup(struct irq_data *d)
 {
 	unsigned int vpflags = dvpe();
 
-	clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE));
+	clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
 	evpe(vpflags);
-	unmask_mips_mt_irq(irq);
-
+	unmask_mips_irq(d);
 	return 0;
 }
 
@@ -80,22 +76,22 @@
  * While we ack the interrupt interrupts are disabled and thus we don't need
  * to deal with concurrency issues.  Same for mips_cpu_irq_end.
  */
-static void mips_mt_cpu_irq_ack(unsigned int irq)
+static void mips_mt_cpu_irq_ack(struct irq_data *d)
 {
 	unsigned int vpflags = dvpe();
-	clear_c0_cause(0x100 << (irq - MIPS_CPU_IRQ_BASE));
+	clear_c0_cause(0x100 << (d->irq - MIPS_CPU_IRQ_BASE));
 	evpe(vpflags);
-	mask_mips_mt_irq(irq);
+	mask_mips_irq(d);
 }
 
 static struct irq_chip mips_mt_cpu_irq_controller = {
 	.name		= "MIPS",
-	.startup	= mips_mt_cpu_irq_startup,
-	.ack		= mips_mt_cpu_irq_ack,
-	.mask		= mask_mips_mt_irq,
-	.mask_ack	= mips_mt_cpu_irq_ack,
-	.unmask		= unmask_mips_mt_irq,
-	.eoi		= unmask_mips_mt_irq,
+	.irq_startup	= mips_mt_cpu_irq_startup,
+	.irq_ack	= mips_mt_cpu_irq_ack,
+	.irq_mask	= mask_mips_irq,
+	.irq_mask_ack	= mips_mt_cpu_irq_ack,
+	.irq_unmask	= unmask_mips_irq,
+	.irq_eoi	= unmask_mips_irq,
 };
 
 void __init mips_cpu_irq_init(void)
@@ -113,10 +109,10 @@
 	 */
 	if (cpu_has_mipsmt)
 		for (i = irq_base; i < irq_base + 2; i++)
-			set_irq_chip_and_handler(i, &mips_mt_cpu_irq_controller,
+			irq_set_chip_and_handler(i, &mips_mt_cpu_irq_controller,
 						 handle_percpu_irq);
 
 	for (i = irq_base + 2; i < irq_base + 8; i++)
-		set_irq_chip_and_handler(i, &mips_cpu_irq_controller,
+		irq_set_chip_and_handler(i, &mips_cpu_irq_controller,
 					 handle_percpu_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq-gic.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq-gic.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq-gic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq-gic.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,17 +87,10 @@
 	return i;
 }
 
-static unsigned int gic_irq_startup(unsigned int irq)
+static void gic_irq_ack(struct irq_data *d)
 {
-	irq -= _irqbase;
-	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
-	GIC_SET_INTR_MASK(irq);
-	return 0;
-}
+	unsigned int irq = d->irq - _irqbase;
 
-static void gic_irq_ack(unsigned int irq)
-{
-	irq -= _irqbase;
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	GIC_CLR_INTR_MASK(irq);
 
@@ -105,16 +98,16 @@
 		GICWRITE(GIC_REG(SHARED, GIC_SH_WEDGE), irq);
 }
 
-static void gic_mask_irq(unsigned int irq)
+static void gic_mask_irq(struct irq_data *d)
 {
-	irq -= _irqbase;
+	unsigned int irq = d->irq - _irqbase;
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	GIC_CLR_INTR_MASK(irq);
 }
 
-static void gic_unmask_irq(unsigned int irq)
+static void gic_unmask_irq(struct irq_data *d)
 {
-	irq -= _irqbase;
+	unsigned int irq = d->irq - _irqbase;
 	pr_debug("CPU%d: %s: irq%d\n", smp_processor_id(), __func__, irq);
 	GIC_SET_INTR_MASK(irq);
 }
@@ -123,13 +116,14 @@
 
 static DEFINE_SPINLOCK(gic_lock);
 
-static int gic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
+			    bool force)
 {
+	unsigned int irq = d->irq - _irqbase;
 	cpumask_t	tmp = CPU_MASK_NONE;
 	unsigned long	flags;
 	int		i;
 
-	irq -= _irqbase;
 	pr_debug("%s(%d) called\n", __func__, irq);
 	cpumask_and(&tmp, cpumask, cpu_online_mask);
 	if (cpus_empty(tmp))
@@ -147,23 +141,22 @@
 		set_bit(irq, pcpu_masks[first_cpu(tmp)].pcpu_mask);
 
 	}
-	cpumask_copy(irq_desc[irq].affinity, cpumask);
+	cpumask_copy(d->affinity, cpumask);
 	spin_unlock_irqrestore(&gic_lock, flags);
 
-	return 0;
+	return IRQ_SET_MASK_OK_NOCOPY;
 }
 #endif
 
 static struct irq_chip gic_irq_controller = {
-	.name		=	"MIPS GIC",
-	.startup	=	gic_irq_startup,
-	.ack		=	gic_irq_ack,
-	.mask		=	gic_mask_irq,
-	.mask_ack	=	gic_mask_irq,
-	.unmask		=	gic_unmask_irq,
-	.eoi		=	gic_unmask_irq,
+	.name			=	"MIPS GIC",
+	.irq_ack		=	gic_irq_ack,
+	.irq_mask		=	gic_mask_irq,
+	.irq_mask_ack		=	gic_mask_irq,
+	.irq_unmask		=	gic_unmask_irq,
+	.irq_eoi		=	gic_unmask_irq,
 #ifdef CONFIG_SMP
-	.set_affinity	=	gic_set_affinity,
+	.irq_set_affinity	=	gic_set_affinity,
 #endif
 };
 
@@ -236,7 +229,7 @@
 	vpe_local_setup(numvpes);
 
 	for (i = _irqbase; i < (_irqbase + numintrs); i++)
-		set_irq_chip(i, &gic_irq_controller);
+		irq_set_chip(i, &gic_irq_controller);
 }
 
 void __init gic_init(unsigned long gic_base_addr,
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq-gt641xx.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq-gt641xx.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq-gt641xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq-gt641xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,64 +29,64 @@
 
 static DEFINE_RAW_SPINLOCK(gt641xx_irq_lock);
 
-static void ack_gt641xx_irq(unsigned int irq)
+static void ack_gt641xx_irq(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 cause;
 
 	raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
 	cause = GT_READ(GT_INTRCAUSE_OFS);
-	cause &= ~GT641XX_IRQ_TO_BIT(irq);
+	cause &= ~GT641XX_IRQ_TO_BIT(d->irq);
 	GT_WRITE(GT_INTRCAUSE_OFS, cause);
 	raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
 }
 
-static void mask_gt641xx_irq(unsigned int irq)
+static void mask_gt641xx_irq(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 mask;
 
 	raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
 	mask = GT_READ(GT_INTRMASK_OFS);
-	mask &= ~GT641XX_IRQ_TO_BIT(irq);
+	mask &= ~GT641XX_IRQ_TO_BIT(d->irq);
 	GT_WRITE(GT_INTRMASK_OFS, mask);
 	raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
 }
 
-static void mask_ack_gt641xx_irq(unsigned int irq)
+static void mask_ack_gt641xx_irq(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 cause, mask;
 
 	raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
 	mask = GT_READ(GT_INTRMASK_OFS);
-	mask &= ~GT641XX_IRQ_TO_BIT(irq);
+	mask &= ~GT641XX_IRQ_TO_BIT(d->irq);
 	GT_WRITE(GT_INTRMASK_OFS, mask);
 
 	cause = GT_READ(GT_INTRCAUSE_OFS);
-	cause &= ~GT641XX_IRQ_TO_BIT(irq);
+	cause &= ~GT641XX_IRQ_TO_BIT(d->irq);
 	GT_WRITE(GT_INTRCAUSE_OFS, cause);
 	raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
 }
 
-static void unmask_gt641xx_irq(unsigned int irq)
+static void unmask_gt641xx_irq(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 mask;
 
 	raw_spin_lock_irqsave(&gt641xx_irq_lock, flags);
 	mask = GT_READ(GT_INTRMASK_OFS);
-	mask |= GT641XX_IRQ_TO_BIT(irq);
+	mask |= GT641XX_IRQ_TO_BIT(d->irq);
 	GT_WRITE(GT_INTRMASK_OFS, mask);
 	raw_spin_unlock_irqrestore(&gt641xx_irq_lock, flags);
 }
 
 static struct irq_chip gt641xx_irq_chip = {
 	.name		= "GT641xx",
-	.ack		= ack_gt641xx_irq,
-	.mask		= mask_gt641xx_irq,
-	.mask_ack	= mask_ack_gt641xx_irq,
-	.unmask		= unmask_gt641xx_irq,
+	.irq_ack	= ack_gt641xx_irq,
+	.irq_mask	= mask_gt641xx_irq,
+	.irq_mask_ack	= mask_ack_gt641xx_irq,
+	.irq_unmask	= unmask_gt641xx_irq,
 };
 
 void gt641xx_irq_dispatch(void)
@@ -126,6 +126,6 @@
 	 * bit31: logical or of bits[25:1].
 	 */
 	for (i = 1; i < 30; i++)
-		set_irq_chip_and_handler(GT641XX_IRQ_BASE + i,
-		                         &gt641xx_irq_chip, handle_level_irq);
+		irq_set_chip_and_handler(GT641XX_IRQ_BASE + i,
+					 &gt641xx_irq_chip, handle_level_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq-msc01.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq-msc01.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq-msc01.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq-msc01.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,8 +28,10 @@
 static unsigned int irq_base;
 
 /* mask off an interrupt */
-static inline void mask_msc_irq(unsigned int irq)
+static inline void mask_msc_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if (irq < (irq_base + 32))
 		MSCIC_WRITE(MSC01_IC_DISL, 1<<(irq - irq_base));
 	else
@@ -37,8 +39,10 @@
 }
 
 /* unmask an interrupt */
-static inline void unmask_msc_irq(unsigned int irq)
+static inline void unmask_msc_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	if (irq < (irq_base + 32))
 		MSCIC_WRITE(MSC01_IC_ENAL, 1<<(irq - irq_base));
 	else
@@ -48,9 +52,11 @@
 /*
  * Masks and ACKs an IRQ
  */
-static void level_mask_and_ack_msc_irq(unsigned int irq)
+static void level_mask_and_ack_msc_irq(struct irq_data *d)
 {
-	mask_msc_irq(irq);
+	unsigned int irq = d->irq;
+
+	mask_msc_irq(d);
 	if (!cpu_has_veic)
 		MSCIC_WRITE(MSC01_IC_EOI, 0);
 	/* This actually needs to be a call into platform code */
@@ -60,9 +66,11 @@
 /*
  * Masks and ACKs an IRQ
  */
-static void edge_mask_and_ack_msc_irq(unsigned int irq)
+static void edge_mask_and_ack_msc_irq(struct irq_data *d)
 {
-	mask_msc_irq(irq);
+	unsigned int irq = d->irq;
+
+	mask_msc_irq(d);
 	if (!cpu_has_veic)
 		MSCIC_WRITE(MSC01_IC_EOI, 0);
 	else {
@@ -75,15 +83,6 @@
 }
 
 /*
- * End IRQ processing
- */
-static void end_msc_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		unmask_msc_irq(irq);
-}
-
-/*
  * Interrupt handler for interrupts coming from SOC-it.
  */
 void ll_msc_irq(void)
@@ -107,22 +106,20 @@
 
 static struct irq_chip msc_levelirq_type = {
 	.name = "SOC-it-Level",
-	.ack = level_mask_and_ack_msc_irq,
-	.mask = mask_msc_irq,
-	.mask_ack = level_mask_and_ack_msc_irq,
-	.unmask = unmask_msc_irq,
-	.eoi = unmask_msc_irq,
-	.end = end_msc_irq,
+	.irq_ack = level_mask_and_ack_msc_irq,
+	.irq_mask = mask_msc_irq,
+	.irq_mask_ack = level_mask_and_ack_msc_irq,
+	.irq_unmask = unmask_msc_irq,
+	.irq_eoi = unmask_msc_irq,
 };
 
 static struct irq_chip msc_edgeirq_type = {
 	.name = "SOC-it-Edge",
-	.ack = edge_mask_and_ack_msc_irq,
-	.mask = mask_msc_irq,
-	.mask_ack = edge_mask_and_ack_msc_irq,
-	.unmask = unmask_msc_irq,
-	.eoi = unmask_msc_irq,
-	.end = end_msc_irq,
+	.irq_ack = edge_mask_and_ack_msc_irq,
+	.irq_mask = mask_msc_irq,
+	.irq_mask_ack = edge_mask_and_ack_msc_irq,
+	.irq_unmask = unmask_msc_irq,
+	.irq_eoi = unmask_msc_irq,
 };
 
 
@@ -140,16 +137,20 @@
 
 		switch (imp->im_type) {
 		case MSC01_IRQ_EDGE:
-			set_irq_chip_and_handler_name(irqbase + n,
-				&msc_edgeirq_type, handle_edge_irq, "edge");
+			irq_set_chip_and_handler_name(irqbase + n,
+						      &msc_edgeirq_type,
+						      handle_edge_irq,
+						      "edge");
 			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT);
 			else
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, MSC01_IC_SUP_EDGE_BIT | imp->im_lvl);
 			break;
 		case MSC01_IRQ_LEVEL:
-			set_irq_chip_and_handler_name(irqbase+n,
-				&msc_levelirq_type, handle_level_irq, "level");
+			irq_set_chip_and_handler_name(irqbase + n,
+						      &msc_levelirq_type,
+						      handle_level_irq,
+						      "level");
 			if (cpu_has_veic)
 				MSCIC_WRITE(MSC01_IC_SUP+n*8, 0);
 			else
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq-rm7000.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq-rm7000.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq-rm7000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq-rm7000.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,23 +18,23 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static inline void unmask_rm7k_irq(unsigned int irq)
+static inline void unmask_rm7k_irq(struct irq_data *d)
 {
-	set_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE));
+	set_c0_intcontrol(0x100 << (d->irq - RM7K_CPU_IRQ_BASE));
 }
 
-static inline void mask_rm7k_irq(unsigned int irq)
+static inline void mask_rm7k_irq(struct irq_data *d)
 {
-	clear_c0_intcontrol(0x100 << (irq - RM7K_CPU_IRQ_BASE));
+	clear_c0_intcontrol(0x100 << (d->irq - RM7K_CPU_IRQ_BASE));
 }
 
 static struct irq_chip rm7k_irq_controller = {
 	.name = "RM7000",
-	.ack = mask_rm7k_irq,
-	.mask = mask_rm7k_irq,
-	.mask_ack = mask_rm7k_irq,
-	.unmask = unmask_rm7k_irq,
-	.eoi	= unmask_rm7k_irq
+	.irq_ack = mask_rm7k_irq,
+	.irq_mask = mask_rm7k_irq,
+	.irq_mask_ack = mask_rm7k_irq,
+	.irq_unmask = unmask_rm7k_irq,
+	.irq_eoi = unmask_rm7k_irq
 };
 
 void __init rm7k_cpu_irq_init(void)
@@ -45,6 +45,6 @@
 	clear_c0_intcontrol(0x00000f00);		/* Mask all */
 
 	for (i = base; i < base + 4; i++)
-		set_irq_chip_and_handler(i, &rm7k_irq_controller,
+		irq_set_chip_and_handler(i, &rm7k_irq_controller,
 					 handle_percpu_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq-rm9000.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq-rm9000.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq-rm9000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq-rm9000.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,22 +19,22 @@
 #include <asm/mipsregs.h>
 #include <asm/system.h>
 
-static inline void unmask_rm9k_irq(unsigned int irq)
+static inline void unmask_rm9k_irq(struct irq_data *d)
 {
-	set_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
+	set_c0_intcontrol(0x1000 << (d->irq - RM9K_CPU_IRQ_BASE));
 }
 
-static inline void mask_rm9k_irq(unsigned int irq)
+static inline void mask_rm9k_irq(struct irq_data *d)
 {
-	clear_c0_intcontrol(0x1000 << (irq - RM9K_CPU_IRQ_BASE));
+	clear_c0_intcontrol(0x1000 << (d->irq - RM9K_CPU_IRQ_BASE));
 }
 
-static inline void rm9k_cpu_irq_enable(unsigned int irq)
+static inline void rm9k_cpu_irq_enable(struct irq_data *d)
 {
 	unsigned long flags;
 
 	local_irq_save(flags);
-	unmask_rm9k_irq(irq);
+	unmask_rm9k_irq(d);
 	local_irq_restore(flags);
 }
 
@@ -43,50 +43,47 @@
  */
 static void local_rm9k_perfcounter_irq_startup(void *args)
 {
-	unsigned int irq = (unsigned int) args;
-
-	rm9k_cpu_irq_enable(irq);
+	rm9k_cpu_irq_enable(args);
 }
 
-static unsigned int rm9k_perfcounter_irq_startup(unsigned int irq)
+static unsigned int rm9k_perfcounter_irq_startup(struct irq_data *d)
 {
-	on_each_cpu(local_rm9k_perfcounter_irq_startup, (void *) irq, 1);
+	on_each_cpu(local_rm9k_perfcounter_irq_startup, d, 1);
 
 	return 0;
 }
 
 static void local_rm9k_perfcounter_irq_shutdown(void *args)
 {
-	unsigned int irq = (unsigned int) args;
 	unsigned long flags;
 
 	local_irq_save(flags);
-	mask_rm9k_irq(irq);
+	mask_rm9k_irq(args);
 	local_irq_restore(flags);
 }
 
-static void rm9k_perfcounter_irq_shutdown(unsigned int irq)
+static void rm9k_perfcounter_irq_shutdown(struct irq_data *d)
 {
-	on_each_cpu(local_rm9k_perfcounter_irq_shutdown, (void *) irq, 1);
+	on_each_cpu(local_rm9k_perfcounter_irq_shutdown, d, 1);
 }
 
 static struct irq_chip rm9k_irq_controller = {
 	.name = "RM9000",
-	.ack = mask_rm9k_irq,
-	.mask = mask_rm9k_irq,
-	.mask_ack = mask_rm9k_irq,
-	.unmask = unmask_rm9k_irq,
-	.eoi	= unmask_rm9k_irq
+	.irq_ack = mask_rm9k_irq,
+	.irq_mask = mask_rm9k_irq,
+	.irq_mask_ack = mask_rm9k_irq,
+	.irq_unmask = unmask_rm9k_irq,
+	.irq_eoi = unmask_rm9k_irq
 };
 
 static struct irq_chip rm9k_perfcounter_irq = {
 	.name = "RM9000",
-	.startup = rm9k_perfcounter_irq_startup,
-	.shutdown = rm9k_perfcounter_irq_shutdown,
-	.ack = mask_rm9k_irq,
-	.mask = mask_rm9k_irq,
-	.mask_ack = mask_rm9k_irq,
-	.unmask = unmask_rm9k_irq,
+	.irq_startup = rm9k_perfcounter_irq_startup,
+	.irq_shutdown = rm9k_perfcounter_irq_shutdown,
+	.irq_ack = mask_rm9k_irq,
+	.irq_mask = mask_rm9k_irq,
+	.irq_mask_ack = mask_rm9k_irq,
+	.irq_unmask = unmask_rm9k_irq,
 };
 
 unsigned int rm9000_perfcount_irq;
@@ -101,10 +98,10 @@
 	clear_c0_intcontrol(0x0000f000);		/* Mask all */
 
 	for (i = base; i < base + 4; i++)
-		set_irq_chip_and_handler(i, &rm9k_irq_controller,
+		irq_set_chip_and_handler(i, &rm9k_irq_controller,
 					 handle_level_irq);
 
 	rm9000_perfcount_irq = base + 1;
-	set_irq_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
+	irq_set_chip_and_handler(rm9000_perfcount_irq, &rm9k_perfcounter_irq,
 				 handle_percpu_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/irq_txx9.c linux-libre-2.6.39-gnu/arch/mips/kernel/irq_txx9.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/irq_txx9.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/irq_txx9.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,9 +63,9 @@
 	unsigned char mode;
 } txx9irq[TXx9_MAX_IR] __read_mostly;
 
-static void txx9_irq_unmask(unsigned int irq)
+static void txx9_irq_unmask(struct irq_data *d)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 	u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16 ) / 2];
 	int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8;
 
@@ -79,9 +79,9 @@
 #endif
 }
 
-static inline void txx9_irq_mask(unsigned int irq)
+static inline void txx9_irq_mask(struct irq_data *d)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 	u32 __iomem *ilrp = &txx9_ircptr->ilr[(irq_nr % 16) / 2];
 	int ofs = irq_nr / 16 * 16 + (irq_nr & 1) * 8;
 
@@ -99,19 +99,19 @@
 #endif
 }
 
-static void txx9_irq_mask_ack(unsigned int irq)
+static void txx9_irq_mask_ack(struct irq_data *d)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 
-	txx9_irq_mask(irq);
+	txx9_irq_mask(d);
 	/* clear edge detection */
 	if (unlikely(TXx9_IRCR_EDGE(txx9irq[irq_nr].mode)))
 		__raw_writel(TXx9_IRSCR_EIClrE | irq_nr, &txx9_ircptr->scr);
 }
 
-static int txx9_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int txx9_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 	u32 cr;
 	u32 __iomem *crp;
 	int ofs;
@@ -139,11 +139,11 @@
 
 static struct irq_chip txx9_irq_chip = {
 	.name		= "TXX9",
-	.ack		= txx9_irq_mask_ack,
-	.mask		= txx9_irq_mask,
-	.mask_ack	= txx9_irq_mask_ack,
-	.unmask		= txx9_irq_unmask,
-	.set_type	= txx9_irq_set_type,
+	.irq_ack	= txx9_irq_mask_ack,
+	.irq_mask	= txx9_irq_mask,
+	.irq_mask_ack	= txx9_irq_mask_ack,
+	.irq_unmask	= txx9_irq_unmask,
+	.irq_set_type	= txx9_irq_set_type,
 };
 
 void __init txx9_irq_init(unsigned long baseaddr)
@@ -154,8 +154,8 @@
 	for (i = 0; i < TXx9_MAX_IR; i++) {
 		txx9irq[i].level = 4; /* middle level */
 		txx9irq[i].mode = TXx9_IRCR_LOW;
-		set_irq_chip_and_handler(TXX9_IRQ_BASE + i,
-					 &txx9_irq_chip, handle_level_irq);
+		irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &txx9_irq_chip,
+					 handle_level_irq);
 	}
 
 	/* mask all IRC interrupts */
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/perf_event_mipsxx.c linux-libre-2.6.39-gnu/arch/mips/kernel/perf_event_mipsxx.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/perf_event_mipsxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/perf_event_mipsxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -721,7 +721,7 @@
 
 /*
  * MIPS performance counters can be per-TC. The control registers can
- * not be directly accessed accross CPUs. Hence if we want to do global
+ * not be directly accessed across CPUs. Hence if we want to do global
  * control, we need cross CPU calls. on_each_cpu() can help us, but we
  * can not make sure this function is called with interrupts enabled. So
  * here we pause local counters and then grab a rwlock and leave the
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/process.c linux-libre-2.6.39-gnu/arch/mips/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -410,7 +410,7 @@
 	if (!kallsyms_lookup_size_offset(pc, &size, &ofs))
 		return 0;
 	/*
-	 * Return ra if an exception occured at the first instruction
+	 * Return ra if an exception occurred at the first instruction
 	 */
 	if (unlikely(ofs == 0)) {
 		pc = *ra;
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/mips/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -540,8 +540,8 @@
 		secure_computing(regs->regs[2]);
 
 	if (unlikely(current->audit_context) && entryexit)
-		audit_syscall_exit(AUDITSC_RESULT(regs->regs[2]),
-		                   regs->regs[2]);
+		audit_syscall_exit(AUDITSC_RESULT(regs->regs[7]),
+		                   -regs->regs[2]);
 
 	if (!(current->ptrace & PT_PTRACED))
 		goto out;
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/scall32-o32.S linux-libre-2.6.39-gnu/arch/mips/kernel/scall32-o32.S
--- linux-libre-2.6.38-gnu/arch/mips/kernel/scall32-o32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/scall32-o32.S	2011-05-19 00:06:34.000000000 -0400
@@ -565,7 +565,7 @@
 	sys	sys_ioprio_get		2	/* 4315 */
 	sys	sys_utimensat		4
 	sys	sys_signalfd		3
-	sys	sys_ni_syscall		0
+	sys	sys_ni_syscall		0	/* was timerfd */
 	sys	sys_eventfd		1
 	sys	sys_fallocate		6	/* 4320 */
 	sys	sys_timerfd_create	2
@@ -586,6 +586,10 @@
 	sys	sys_fanotify_init	2
 	sys	sys_fanotify_mark	6
 	sys	sys_prlimit64		4
+	sys	sys_name_to_handle_at	5
+	sys	sys_open_by_handle_at	3	/* 4340 */
+	sys	sys_clock_adjtime	2
+	sys	sys_syncfs		1
 	.endm
 
 	/* We pre-compute the number of _instruction_ bytes needed to
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/scall64-64.S linux-libre-2.6.39-gnu/arch/mips/kernel/scall64-64.S
--- linux-libre-2.6.38-gnu/arch/mips/kernel/scall64-64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/scall64-64.S	2011-05-19 00:06:34.000000000 -0400
@@ -404,7 +404,7 @@
 	PTR	sys_ioprio_get
 	PTR	sys_utimensat			/* 5275 */
 	PTR	sys_signalfd
-	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall			/* was timerfd */
 	PTR	sys_eventfd
 	PTR	sys_fallocate
 	PTR	sys_timerfd_create		/* 5280 */
@@ -425,4 +425,8 @@
 	PTR	sys_fanotify_init		/* 5295 */
 	PTR	sys_fanotify_mark
 	PTR	sys_prlimit64
+	PTR	sys_name_to_handle_at
+	PTR	sys_open_by_handle_at
+	PTR	sys_clock_adjtime		/* 5300 */
+	PTR	sys_syncfs
 	.size	sys_call_table,.-sys_call_table
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/scall64-n32.S linux-libre-2.6.39-gnu/arch/mips/kernel/scall64-n32.S
--- linux-libre-2.6.38-gnu/arch/mips/kernel/scall64-n32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/scall64-n32.S	2011-05-19 00:06:34.000000000 -0400
@@ -403,7 +403,7 @@
 	PTR	sys_ioprio_get
 	PTR	compat_sys_utimensat
 	PTR	compat_sys_signalfd		/* 6280 */
-	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall			/* was timerfd */
 	PTR	sys_eventfd
 	PTR	sys_fallocate
 	PTR	sys_timerfd_create
@@ -425,4 +425,8 @@
 	PTR	sys_fanotify_init		/* 6300 */
 	PTR	sys_fanotify_mark
 	PTR	sys_prlimit64
+	PTR	sys_name_to_handle_at
+	PTR	sys_open_by_handle_at
+	PTR	compat_sys_clock_adjtime	/* 6305 */
+	PTR	sys_syncfs
 	.size	sysn32_call_table,.-sysn32_call_table
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/scall64-o32.S linux-libre-2.6.39-gnu/arch/mips/kernel/scall64-o32.S
--- linux-libre-2.6.38-gnu/arch/mips/kernel/scall64-o32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/scall64-o32.S	2011-05-19 00:06:34.000000000 -0400
@@ -522,7 +522,7 @@
 	PTR	sys_ioprio_get			/* 4315 */
 	PTR	compat_sys_utimensat
 	PTR	compat_sys_signalfd
-	PTR	sys_ni_syscall
+	PTR	sys_ni_syscall			/* was timerfd */
 	PTR	sys_eventfd
 	PTR	sys32_fallocate			/* 4320 */
 	PTR	sys_timerfd_create
@@ -543,4 +543,8 @@
 	PTR	sys_fanotify_init
 	PTR	sys_32_fanotify_mark
 	PTR	sys_prlimit64
+	PTR	sys_name_to_handle_at
+	PTR	compat_sys_open_by_handle_at	/* 4340 */
+	PTR	compat_sys_clock_adjtime
+	PTR	sys_syncfs
 	.size	sys_call_table,.-sys_call_table
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/smp-mt.c linux-libre-2.6.39-gnu/arch/mips/kernel/smp-mt.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/smp-mt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/smp-mt.c	2011-05-19 00:06:34.000000000 -0400
@@ -120,7 +120,7 @@
 
 	local_irq_save(flags);
 
-	vpflags = dvpe();	/* cant access the other CPU's registers whilst MVPE enabled */
+	vpflags = dvpe();	/* can't access the other CPU's registers whilst MVPE enabled */
 
 	switch (action) {
 	case SMP_CALL_FUNCTION:
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/smtc.c linux-libre-2.6.39-gnu/arch/mips/kernel/smtc.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/smtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/smtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -677,8 +677,9 @@
 	 */
 }
 
-void smtc_forward_irq(unsigned int irq)
+void smtc_forward_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	int target;
 
 	/*
@@ -692,7 +693,7 @@
 	 * and efficiency, we just pick the easiest one to find.
 	 */
 
-	target = cpumask_first(irq_desc[irq].affinity);
+	target = cpumask_first(d->affinity);
 
 	/*
 	 * We depend on the platform code to have correctly processed
@@ -707,12 +708,10 @@
 	 */
 
 	/* If no one is eligible, service locally */
-	if (target >= NR_CPUS) {
+	if (target >= NR_CPUS)
 		do_IRQ_no_affinity(irq);
-		return;
-	}
-
-	smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq);
+	else
+		smtc_send_ipi(target, IRQ_AFFINITY_IPI, irq);
 }
 
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
@@ -1147,7 +1146,7 @@
 
 	setup_irq_smtc(cpu_ipi_irq, &irq_ipi, (0x100 << MIPS_CPU_IPI_IRQ));
 
-	set_irq_handler(cpu_ipi_irq, handle_percpu_irq);
+	irq_set_handler(cpu_ipi_irq, handle_percpu_irq);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/time.c linux-libre-2.6.39-gnu/arch/mips/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,7 @@
 	case CPU_R4400SC:
 	case CPU_R4400MC:
 		/*
-		 * The published errata for the R4400 upto 3.0 say the CPU
+		 * The published errata for the R4400 up to 3.0 say the CPU
 		 * has the mfc0 from count bug.
 		 */
 		if ((current_cpu_data.processor_id & 0xff) <= 0x30)
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/traps.c linux-libre-2.6.39-gnu/arch/mips/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -374,7 +374,8 @@
 	unsigned long dvpret = dvpe();
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-	notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV);
+	if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
+		sig = 0;
 
 	console_verbose();
 	spin_lock_irq(&die_lock);
@@ -383,9 +384,6 @@
 	mips_mt_regdump(dvpret);
 #endif /* CONFIG_MIPS_MT_SMTC */
 
-	if (notify_die(DIE_OOPS, str, regs, 0, regs_to_trapnr(regs), SIGSEGV) == NOTIFY_STOP)
-		sig = 0;
-
 	printk("%s[#%d]:\n", str, ++die_counter);
 	show_registers(regs);
 	add_taint(TAINT_DIE);
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/mips/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/mips/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -74,6 +74,7 @@
 		INIT_TASK_DATA(PAGE_SIZE)
 		NOSAVE_DATA
 		CACHELINE_ALIGNED_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
+		READ_MOSTLY_DATA(1 << CONFIG_MIPS_L1_CACHE_SHIFT)
 		DATA_DATA
 		CONSTRUCTORS
 	}
@@ -115,7 +116,7 @@
 		EXIT_DATA
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(1 << CONFIG_MIPS_L1_CACHE_SHIFT, PAGE_SIZE)
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
 	/* freed after init ends here */
diff -druN linux-libre-2.6.38-gnu/arch/mips/kernel/vpe.c linux-libre-2.6.39-gnu/arch/mips/kernel/vpe.c
--- linux-libre-2.6.38-gnu/arch/mips/kernel/vpe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/kernel/vpe.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
  * VPE support module
  *
  * Provides support for loading a MIPS SP program on VPE1.
- * The SP enviroment is rather simple, no tlb's.  It needs to be relocatable
+ * The SP environment is rather simple, no tlb's.  It needs to be relocatable
  * (or partially linked). You should initialise your stack in the startup
  * code. This loader looks for the symbol __start and sets up
  * execution to resume from there. The MIPS SDE kit contains suitable examples.
diff -druN linux-libre-2.6.38-gnu/arch/mips/lasat/interrupt.c linux-libre-2.6.39-gnu/arch/mips/lasat/interrupt.c
--- linux-libre-2.6.38-gnu/arch/mips/lasat/interrupt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/lasat/interrupt.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,24 +32,24 @@
 static volatile int *lasat_int_mask;
 static volatile int lasat_int_mask_shift;
 
-void disable_lasat_irq(unsigned int irq_nr)
+void disable_lasat_irq(struct irq_data *d)
 {
-	irq_nr -= LASAT_IRQ_BASE;
+	unsigned int irq_nr = d->irq - LASAT_IRQ_BASE;
+
 	*lasat_int_mask &= ~(1 << irq_nr) << lasat_int_mask_shift;
 }
 
-void enable_lasat_irq(unsigned int irq_nr)
+void enable_lasat_irq(struct irq_data *d)
 {
-	irq_nr -= LASAT_IRQ_BASE;
+	unsigned int irq_nr = d->irq - LASAT_IRQ_BASE;
+
 	*lasat_int_mask |= (1 << irq_nr) << lasat_int_mask_shift;
 }
 
 static struct irq_chip lasat_irq_type = {
 	.name = "Lasat",
-	.ack = disable_lasat_irq,
-	.mask = disable_lasat_irq,
-	.mask_ack = disable_lasat_irq,
-	.unmask = enable_lasat_irq,
+	.irq_mask = disable_lasat_irq,
+	.irq_unmask = enable_lasat_irq,
 };
 
 static inline int ls1bit32(unsigned int x)
@@ -128,7 +128,7 @@
 	mips_cpu_irq_init();
 
 	for (i = LASAT_IRQ_BASE; i <= LASAT_IRQ_END; i++)
-		set_irq_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &lasat_irq_type, handle_level_irq);
 
 	setup_irq(LASAT_CASCADE_IRQ, &cascade);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/lib/strnlen_user.S linux-libre-2.6.39-gnu/arch/mips/lib/strnlen_user.S
--- linux-libre-2.6.38-gnu/arch/mips/lib/strnlen_user.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/lib/strnlen_user.S	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
 	.previous
 
 /*
- * Return the size of a string including the ending NUL character upto a
+ * Return the size of a string including the ending NUL character up to a
  * maximum of a1 or 0 in case of error.
  *
  * Note: for performance reasons we deliberately accept that a user may
diff -druN linux-libre-2.6.38-gnu/arch/mips/loongson/common/bonito-irq.c linux-libre-2.6.39-gnu/arch/mips/loongson/common/bonito-irq.c
--- linux-libre-2.6.38-gnu/arch/mips/loongson/common/bonito-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/loongson/common/bonito-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,24 +16,22 @@
 
 #include <loongson.h>
 
-static inline void bonito_irq_enable(unsigned int irq)
+static inline void bonito_irq_enable(struct irq_data *d)
 {
-	LOONGSON_INTENSET = (1 << (irq - LOONGSON_IRQ_BASE));
+	LOONGSON_INTENSET = (1 << (d->irq - LOONGSON_IRQ_BASE));
 	mmiowb();
 }
 
-static inline void bonito_irq_disable(unsigned int irq)
+static inline void bonito_irq_disable(struct irq_data *d)
 {
-	LOONGSON_INTENCLR = (1 << (irq - LOONGSON_IRQ_BASE));
+	LOONGSON_INTENCLR = (1 << (d->irq - LOONGSON_IRQ_BASE));
 	mmiowb();
 }
 
 static struct irq_chip bonito_irq_type = {
-	.name	= "bonito_irq",
-	.ack	= bonito_irq_disable,
-	.mask	= bonito_irq_disable,
-	.mask_ack = bonito_irq_disable,
-	.unmask	= bonito_irq_enable,
+	.name		= "bonito_irq",
+	.irq_mask	= bonito_irq_disable,
+	.irq_unmask	= bonito_irq_enable,
 };
 
 static struct irqaction __maybe_unused dma_timeout_irqaction = {
@@ -46,7 +44,8 @@
 	u32 i;
 
 	for (i = LOONGSON_IRQ_BASE; i < LOONGSON_IRQ_BASE + 32; i++)
-		set_irq_chip_and_handler(i, &bonito_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &bonito_irq_type,
+					 handle_level_irq);
 
 #ifdef CONFIG_CPU_LOONGSON2E
 	setup_irq(LOONGSON_IRQ_BASE + 10, &dma_timeout_irqaction);
diff -druN linux-libre-2.6.38-gnu/arch/mips/loongson/common/env.c linux-libre-2.6.39-gnu/arch/mips/loongson/common/env.c
--- linux-libre-2.6.38-gnu/arch/mips/loongson/common/env.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/loongson/common/env.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,9 +29,10 @@
 
 #define parse_even_earlier(res, option, p)				\
 do {									\
-	int ret;							\
+	unsigned int tmp __maybe_unused;				\
+									\
 	if (strncmp(option, (char *)p, strlen(option)) == 0)		\
-		ret = strict_strtol((char *)p + strlen(option"="), 10, &res); \
+		tmp = strict_strtol((char *)p + strlen(option"="), 10, &res); \
 } while (0)
 
 void __init prom_init_env(void)
diff -druN linux-libre-2.6.38-gnu/arch/mips/Makefile linux-libre-2.6.39-gnu/arch/mips/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 # carefully avoid to add it redundantly because gcc 3.3/3.4 complains
 # when fed the toolchain default!
 #
-# Certain gcc versions upto gcc 4.1.1 (probably 4.2-subversion as of
+# Certain gcc versions up to gcc 4.1.1 (probably 4.2-subversion as of
 # 2006-10-10 don't properly change the predefined symbols if -EB / -EL
 # are used, so we kludge that here.  A bug has been filed at
 # http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29413.
@@ -286,11 +286,11 @@
 archprepare:
 ifdef CONFIG_MIPS32_N32
 	@echo '  Checking missing-syscalls for N32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=n32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=n32"
 endif
 ifdef CONFIG_MIPS32_O32
 	@echo '  Checking missing-syscalls for O32'
-	$(Q)$(MAKE) $(build)=. missing-syscalls EXTRA_CFLAGS="-mabi=32"
+	$(Q)$(MAKE) $(build)=. missing-syscalls ccflags-y="-mabi=32"
 endif
 
 install:
@@ -314,5 +314,5 @@
 	echo '  vmlinuz.bin          - Raw binary zboot image'
 	echo '  vmlinuz.srec         - SREC zboot image'
 	echo
-	echo '  These will be default as apropriate for a configured platform.'
+	echo '  These will be default as appropriate for a configured platform.'
 endef
diff -druN linux-libre-2.6.38-gnu/arch/mips/math-emu/dp_fsp.c linux-libre-2.6.39-gnu/arch/mips/math-emu/dp_fsp.c
--- linux-libre-2.6.38-gnu/arch/mips/math-emu/dp_fsp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/math-emu/dp_fsp.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 		break;
 	}
 
-	/* CANT possibly overflow,underflow, or need rounding
+	/* CAN'T possibly overflow,underflow, or need rounding
 	 */
 
 	/* drop the hidden bit */
diff -druN linux-libre-2.6.38-gnu/arch/mips/math-emu/dp_mul.c linux-libre-2.6.39-gnu/arch/mips/math-emu/dp_mul.c
--- linux-libre-2.6.38-gnu/arch/mips/math-emu/dp_mul.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/math-emu/dp_mul.c	2011-05-19 00:06:34.000000000 -0400
@@ -104,7 +104,7 @@
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
 		break;
 	}
-	/* rm = xm * ym, re = xe+ye basicly */
+	/* rm = xm * ym, re = xe+ye basically */
 	assert(xm & DP_HIDDEN_BIT);
 	assert(ym & DP_HIDDEN_BIT);
 	{
diff -druN linux-libre-2.6.38-gnu/arch/mips/math-emu/dsemul.c linux-libre-2.6.39-gnu/arch/mips/math-emu/dsemul.c
--- linux-libre-2.6.38-gnu/arch/mips/math-emu/dsemul.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/math-emu/dsemul.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
  * not change cp0_epc due to the instruction
  *
  * According to the spec:
- * 1) it shouldnt be a branch :-)
+ * 1) it shouldn't be a branch :-)
  * 2) it can be a COP instruction :-(
  * 3) if we are tring to run a protected memory space we must take
  *    special care on memory access instructions :-(
diff -druN linux-libre-2.6.38-gnu/arch/mips/math-emu/sp_mul.c linux-libre-2.6.39-gnu/arch/mips/math-emu/sp_mul.c
--- linux-libre-2.6.38-gnu/arch/mips/math-emu/sp_mul.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/math-emu/sp_mul.c	2011-05-19 00:06:34.000000000 -0400
@@ -104,7 +104,7 @@
 	case CLPAIR(IEEE754_CLASS_NORM, IEEE754_CLASS_NORM):
 		break;
 	}
-	/* rm = xm * ym, re = xe+ye basicly */
+	/* rm = xm * ym, re = xe+ye basically */
 	assert(xm & SP_HIDDEN_BIT);
 	assert(ym & SP_HIDDEN_BIT);
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/mipssim/sim_smtc.c linux-libre-2.6.39-gnu/arch/mips/mipssim/sim_smtc.c
--- linux-libre-2.6.38-gnu/arch/mips/mipssim/sim_smtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mipssim/sim_smtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <asm/atomic.h>
 #include <asm/cpu.h>
 #include <asm/processor.h>
+#include <asm/smtc.h>
 #include <asm/system.h>
 #include <asm/mmu_context.h>
 #include <asm/smtc_ipi.h>
@@ -57,8 +58,6 @@
  */
 static void __cpuinit ssmtc_init_secondary(void)
 {
-	void smtc_init_secondary(void);
-
 	smtc_init_secondary();
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/mm/cex-sb1.S linux-libre-2.6.39-gnu/arch/mips/mm/cex-sb1.S
--- linux-libre-2.6.38-gnu/arch/mips/mm/cex-sb1.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mm/cex-sb1.S	2011-05-19 00:06:34.000000000 -0400
@@ -79,7 +79,7 @@
 recovered_dcache:
 	/*
 	 * Unlock CacheErr-D (which in turn unlocks CacheErr-DPA).
-	 * Ought to log the occurence of this recovered dcache error.
+	 * Ought to log the occurrence of this recovered dcache error.
 	 */
 	b	recovered
 	 mtc0	$0,C0_CERR_D
diff -druN linux-libre-2.6.38-gnu/arch/mips/mm/c-r4k.c linux-libre-2.6.39-gnu/arch/mips/mm/c-r4k.c
--- linux-libre-2.6.38-gnu/arch/mips/mm/c-r4k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mm/c-r4k.c	2011-05-19 00:06:34.000000000 -0400
@@ -1075,7 +1075,6 @@
 	unsigned long flags, addr, begin, end, pow2;
 	unsigned int config = read_c0_config();
 	struct cpuinfo_mips *c = &current_cpu_data;
-	int tmp;
 
 	if (config & CONF_SC)
 		return 0;
@@ -1108,7 +1107,6 @@
 
 	/* Now search for the wrap around point. */
 	pow2 = (128 * 1024);
-	tmp = 0;
 	for (addr = begin + (128 * 1024); addr < end; addr = begin + pow2) {
 		cache_op(Index_Load_Tag_SD, addr);
 		__asm__ __volatile__("nop; nop; nop; nop;"); /* hazard... */
diff -druN linux-libre-2.6.38-gnu/arch/mips/mm/tlbex.c linux-libre-2.6.39-gnu/arch/mips/mm/tlbex.c
--- linux-libre-2.6.38-gnu/arch/mips/mm/tlbex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mm/tlbex.c	2011-05-19 00:06:34.000000000 -0400
@@ -352,7 +352,7 @@
 
 /*
  * Write random or indexed TLB entry, and care about the hazards from
- * the preceeding mtc0 and for the following eret.
+ * the preceding mtc0 and for the following eret.
  */
 enum tlb_write_entry { tlb_random, tlb_indexed };
 
@@ -1151,8 +1151,8 @@
 	struct uasm_reloc *r = relocs;
 	u32 *f;
 	unsigned int final_len;
-	struct mips_huge_tlb_info htlb_info;
-	enum vmalloc64_mode vmalloc_mode;
+	struct mips_huge_tlb_info htlb_info __maybe_unused;
+	enum vmalloc64_mode vmalloc_mode __maybe_unused;
 
 	memset(tlb_handler, 0, sizeof(tlb_handler));
 	memset(labels, 0, sizeof(labels));
diff -druN linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-init.c linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-init.c
--- linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-init.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,8 +193,6 @@
 
 void __init prom_init(void)
 {
-	int result;
-
 	prom_argc = fw_arg0;
 	_prom_argv = (int *) fw_arg1;
 	_prom_envp = (int *) fw_arg2;
@@ -360,20 +358,14 @@
 #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
-	if (result)
+	/* Early detection of CMP support */
+	if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ))
 		register_smp_ops(&cmp_smp_ops);
+	else
 #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);
diff -druN linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-int.c linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-int.c
--- linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-int.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-int.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,6 @@
 static inline int mips_pcibios_iack(void)
 {
 	int irq;
-	u32 dummy;
 
 	/*
 	 * Determine highest priority pending interrupt by performing
@@ -83,7 +82,7 @@
 		BONITO_PCIMAP_CFG = 0x20000;
 
 		/* Flush Bonito register block */
-		dummy = BONITO_PCIMAP_CFG;
+		(void) BONITO_PCIMAP_CFG;
 		iob();    /* sync */
 
 		irq = __raw_readl((u32 *)_pcictrl_bonito_pcicfg);
@@ -472,7 +471,7 @@
 void __init arch_init_ipiirq(int irq, struct irqaction *action)
 {
 	setup_irq(irq, action);
-	set_irq_handler(irq, handle_percpu_irq);
+	irq_set_handler(irq, handle_percpu_irq);
 }
 
 void __init arch_init_irq(void)
diff -druN linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-smtc.c linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-smtc.c
--- linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-smtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-smtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,6 @@
  */
 static void __cpuinit msmtc_init_secondary(void)
 {
-	void smtc_init_secondary(void);
 	int myvpe;
 
 	/* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
@@ -114,7 +113,8 @@
  */
 
 
-int plat_set_irq_affinity(unsigned int irq, const struct cpumask *affinity)
+int plat_set_irq_affinity(struct irq_data *d, const struct cpumask *affinity,
+			  bool force)
 {
 	cpumask_t tmask;
 	int cpu = 0;
@@ -130,7 +130,7 @@
 	 * cleared in the affinity mask, there will never be any
 	 * interrupt forwarding.  But as soon as a program or operator
 	 * sets affinity for one of the related IRQs, we need to make
-	 * sure that we don't ever try to forward across the VPE boundry,
+	 * sure that we don't ever try to forward across the VPE boundary,
 	 * at least not until we engineer a system where the interrupt
 	 * _ack() or _end() function can somehow know that it corresponds
 	 * to an interrupt taken on another VPE, and perform the appropriate
@@ -144,7 +144,7 @@
 		if ((cpu_data[cpu].vpe_id != 0) || !cpu_online(cpu))
 			cpu_clear(cpu, tmask);
 	}
-	cpumask_copy(irq_desc[irq].affinity, &tmask);
+	cpumask_copy(d->affinity, &tmask);
 
 	if (cpus_empty(tmask))
 		/*
@@ -155,8 +155,8 @@
 			"IRQ affinity leaves no legal CPU for IRQ %d\n", irq);
 
 	/* Do any generic SMTC IRQ affinity setup */
-	smtc_set_irq_affinity(irq, tmask);
+	smtc_set_irq_affinity(d->irq, tmask);
 
-	return 0;
+	return IRQ_SET_MASK_OK_NOCOPY;
 }
 #endif /* CONFIG_MIPS_MT_SMTC_IRQAFF */
diff -druN linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-time.c linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-time.c
--- linux-libre-2.6.38-gnu/arch/mips/mti-malta/malta-time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/mti-malta/malta-time.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,7 +119,7 @@
 			set_vi_handler(cp0_perfcount_irq, mips_perf_dispatch);
 		mips_cpu_perf_irq = MIPS_CPU_IRQ_BASE + cp0_perfcount_irq;
 #ifdef CONFIG_SMP
-		set_irq_handler(mips_cpu_perf_irq, handle_percpu_irq);
+		irq_set_handler(mips_cpu_perf_irq, handle_percpu_irq);
 #endif
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/oprofile/Makefile linux-libre-2.6.39-gnu/arch/mips/oprofile/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/oprofile/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/oprofile/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-EXTRA_CFLAGS := -Werror
+ccflags-y := -Werror
 
 obj-$(CONFIG_OPROFILE) += oprofile.o
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/pci/msi-octeon.c linux-libre-2.6.39-gnu/arch/mips/pci/msi-octeon.c
--- linux-libre-2.6.38-gnu/arch/mips/pci/msi-octeon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pci/msi-octeon.c	2011-05-19 00:06:34.000000000 -0400
@@ -172,7 +172,7 @@
 	pci_write_config_word(dev, desc->msi_attrib.pos + PCI_MSI_FLAGS,
 			      control);
 
-	set_irq_msi(irq, desc);
+	irq_set_msi_desc(irq, desc);
 	write_msi_msg(irq, &msg);
 	return 0;
 }
@@ -259,11 +259,11 @@
 static u64 msi_rcv_reg[4];
 static u64 mis_ena_reg[4];
 
-static void octeon_irq_msi_enable_pcie(unsigned int irq)
+static void octeon_irq_msi_enable_pcie(struct irq_data *data)
 {
 	u64 en;
 	unsigned long flags;
-	int msi_number = irq - OCTEON_IRQ_MSI_BIT0;
+	int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0;
 	int irq_index = msi_number >> 6;
 	int irq_bit = msi_number & 0x3f;
 
@@ -275,11 +275,11 @@
 	raw_spin_unlock_irqrestore(&octeon_irq_msi_lock, flags);
 }
 
-static void octeon_irq_msi_disable_pcie(unsigned int irq)
+static void octeon_irq_msi_disable_pcie(struct irq_data *data)
 {
 	u64 en;
 	unsigned long flags;
-	int msi_number = irq - OCTEON_IRQ_MSI_BIT0;
+	int msi_number = data->irq - OCTEON_IRQ_MSI_BIT0;
 	int irq_index = msi_number >> 6;
 	int irq_bit = msi_number & 0x3f;
 
@@ -293,11 +293,11 @@
 
 static struct irq_chip octeon_irq_chip_msi_pcie = {
 	.name = "MSI",
-	.enable = octeon_irq_msi_enable_pcie,
-	.disable = octeon_irq_msi_disable_pcie,
+	.irq_enable = octeon_irq_msi_enable_pcie,
+	.irq_disable = octeon_irq_msi_disable_pcie,
 };
 
-static void octeon_irq_msi_enable_pci(unsigned int irq)
+static void octeon_irq_msi_enable_pci(struct irq_data *data)
 {
 	/*
 	 * Octeon PCI doesn't have the ability to mask/unmask MSI
@@ -308,15 +308,15 @@
 	 */
 }
 
-static void octeon_irq_msi_disable_pci(unsigned int irq)
+static void octeon_irq_msi_disable_pci(struct irq_data *data)
 {
 	/* See comment in enable */
 }
 
 static struct irq_chip octeon_irq_chip_msi_pci = {
 	.name = "MSI",
-	.enable = octeon_irq_msi_enable_pci,
-	.disable = octeon_irq_msi_disable_pci,
+	.irq_enable = octeon_irq_msi_enable_pci,
+	.irq_disable = octeon_irq_msi_disable_pci,
 };
 
 /*
@@ -388,7 +388,7 @@
 	}
 
 	for (irq = OCTEON_IRQ_MSI_BIT0; irq <= OCTEON_IRQ_MSI_LAST; irq++)
-		set_irq_chip_and_handler(irq, msi, handle_simple_irq);
+		irq_set_chip_and_handler(irq, msi, handle_simple_irq);
 
 	if (octeon_has_feature(OCTEON_FEATURE_PCIE)) {
 		if (request_irq(OCTEON_IRQ_PCI_MSI0, octeon_msi_interrupt0,
diff -druN linux-libre-2.6.38-gnu/arch/mips/pci/ops-pmcmsp.c linux-libre-2.6.39-gnu/arch/mips/pci/ops-pmcmsp.c
--- linux-libre-2.6.38-gnu/arch/mips/pci/ops-pmcmsp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pci/ops-pmcmsp.c	2011-05-19 00:06:34.000000000 -0400
@@ -344,7 +344,7 @@
  *                              PCI_ACCESS_WRITE and PCI_ACCESS_READ.
  *
  *               bus          - pointer to the bus number of the device to
- *                              be targetted for the configuration cycle.
+ *                              be targeted for the configuration cycle.
  *                              The only element of the pci_bus structure
  *                              used is bus->number. This argument determines
  *                              if the configuration access will be Type 0 or
@@ -354,7 +354,7 @@
  *
  *               devfn        - this is an 8-bit field. The lower three bits
  *                              specify the function number of the device to
- *                              be targetted for the configuration cycle, with
+ *                              be targeted for the configuration cycle, with
  *                              all three-bit combinations being legal. The
  *                              upper five bits specify the device number,
  *                              with legal values being 10 to 31.
diff -druN linux-libre-2.6.38-gnu/arch/mips/pci/pci-bcm1480.c linux-libre-2.6.39-gnu/arch/mips/pci/pci-bcm1480.c
--- linux-libre-2.6.38-gnu/arch/mips/pci/pci-bcm1480.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pci/pci-bcm1480.c	2011-05-19 00:06:34.000000000 -0400
@@ -210,7 +210,7 @@
 	PCIBIOS_MIN_IO = 0x00008000UL;
 	PCIBIOS_MIN_MEM = 0x01000000UL;
 
-	/* Set I/O resource limits. - unlimited for now to accomodate HT */
+	/* Set I/O resource limits. - unlimited for now to accommodate HT */
 	ioport_resource.end = 0xffffffffUL;
 	iomem_resource.end = 0xffffffffUL;
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/pci/pci.c linux-libre-2.6.39-gnu/arch/mips/pci/pci.c
--- linux-libre-2.6.38-gnu/arch/mips/pci/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pci/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,7 +125,7 @@
 	hose_tail = &hose->next;
 
 	/*
-	 * Do not panic here but later - this might hapen before console init.
+	 * Do not panic here but later - this might happen before console init.
 	 */
 	if (!hose->io_map_base) {
 		printk(KERN_WARNING
diff -druN linux-libre-2.6.38-gnu/arch/mips/pci/pci-octeon.c linux-libre-2.6.39-gnu/arch/mips/pci/pci-octeon.c
--- linux-libre-2.6.38-gnu/arch/mips/pci/pci-octeon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pci/pci-octeon.c	2011-05-19 00:06:34.000000000 -0400
@@ -441,7 +441,7 @@
 
 	/*
 	 * 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,
+	 * in PCI-X mode to allow four outstanding 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.
@@ -515,7 +515,7 @@
 #endif	/* USE_OCTEON_INTERNAL_ARBITER */
 
 	/*
-	 * Preferrably written to 1 to set MLTD. [RDSATI,TRTAE,
+	 * Preferably written to 1 to set MLTD. [RDSATI,TRTAE,
 	 * TWTAE,TMAE,DPPMR -> must be zero. TILT -> must not be set to
 	 * 1..7.
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/Kconfig linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/Kconfig
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,8 @@
 	select SYS_SUPPORTS_MULTITHREADING
 	select IRQ_MSP_CIC
 	select HW_HAS_PCI
+	select MSP_HAS_USB
+	select MSP_ETH
 
 config PMC_MSP7120_FPGA
 	bool "PMC-Sierra MSP7120 FPGA"
@@ -35,3 +37,16 @@
 config HYPERTRANSPORT
 	bool "Hypertransport Support for PMC-Sierra Yosemite"
 	depends on PMC_YOSEMITE
+
+config MSP_HAS_USB
+	boolean
+	depends on PMC_MSP
+
+config MSP_ETH
+	boolean
+	select MSP_HAS_MAC
+	depends on PMC_MSP
+
+config MSP_HAS_MAC
+	boolean
+	depends on PMC_MSP
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/Makefile linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,9 @@
 obj-$(CONFIG_HAVE_GPIO_LIB) += gpio.o gpio_extended.o
 obj-$(CONFIG_PMC_MSP7120_GW) += msp_hwbutton.o
 obj-$(CONFIG_IRQ_MSP_SLP) += msp_irq_slp.o
-obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o
+obj-$(CONFIG_IRQ_MSP_CIC) += msp_irq_cic.o msp_irq_per.o
 obj-$(CONFIG_PCI) += msp_pci.o
-obj-$(CONFIG_MSPETH) += msp_eth.o
-obj-$(CONFIG_USB_MSP71XX) += msp_usb.o
+obj-$(CONFIG_MSP_HAS_MAC) += msp_eth.o
+obj-$(CONFIG_MSP_HAS_USB) += msp_usb.o
+obj-$(CONFIG_MIPS_MT_SMP) += msp_smp.o
+obj-$(CONFIG_MIPS_MT_SMTC) += msp_smtc.o
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_eth.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_eth.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_eth.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_eth.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ * The setup file for ethernet related hardware on PMC-Sierra MSP processors.
+ *
+ * Copyright 2010 PMC-Sierra, 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.
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <msp_regs.h>
+#include <msp_int.h>
+#include <msp_gpio_macros.h>
+
+
+#define MSP_ETHERNET_GPIO0	14
+#define MSP_ETHERNET_GPIO1	15
+#define MSP_ETHERNET_GPIO2	16
+
+#ifdef CONFIG_MSP_HAS_TSMAC
+#define MSP_TSMAC_SIZE	0x10020
+#define MSP_TSMAC_ID	"pmc_tsmac"
+
+static struct resource msp_tsmac0_resources[] = {
+	[0] = {
+		.start	= MSP_MAC0_BASE,
+		.end	= MSP_MAC0_BASE + MSP_TSMAC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_MAC0,
+		.end	= MSP_INT_MAC0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msp_tsmac1_resources[] = {
+	[0] = {
+		.start	= MSP_MAC1_BASE,
+		.end	= MSP_MAC1_BASE + MSP_TSMAC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_MAC1,
+		.end	= MSP_INT_MAC1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+static struct resource msp_tsmac2_resources[] = {
+	[0] = {
+		.start	= MSP_MAC2_BASE,
+		.end	= MSP_MAC2_BASE + MSP_TSMAC_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_SAR,
+		.end	= MSP_INT_SAR,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+static struct platform_device tsmac_device[] = {
+	[0] = {
+		.name	= MSP_TSMAC_ID,
+		.id	= 0,
+		.num_resources = ARRAY_SIZE(msp_tsmac0_resources),
+		.resource = msp_tsmac0_resources,
+	},
+	[1] = {
+		.name	= MSP_TSMAC_ID,
+		.id	= 1,
+		.num_resources = ARRAY_SIZE(msp_tsmac1_resources),
+		.resource = msp_tsmac1_resources,
+	},
+	[2] = {
+		.name	= MSP_TSMAC_ID,
+		.id	= 2,
+		.num_resources = ARRAY_SIZE(msp_tsmac2_resources),
+		.resource = msp_tsmac2_resources,
+	},
+};
+#define msp_eth_devs	tsmac_device
+
+#else
+/* If it is not TSMAC assume MSP_ETH (100Mbps) */
+#define MSP_ETH_ID	"pmc_mspeth"
+#define MSP_ETH_SIZE	0xE0
+static struct resource msp_eth0_resources[] = {
+	[0] = {
+		.start	= MSP_MAC0_BASE,
+		.end	= MSP_MAC0_BASE + MSP_ETH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_MAC0,
+		.end	= MSP_INT_MAC0,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource msp_eth1_resources[] = {
+	[0] = {
+		.start	= MSP_MAC1_BASE,
+		.end	= MSP_MAC1_BASE + MSP_ETH_SIZE - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= MSP_INT_MAC1,
+		.end	= MSP_INT_MAC1,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+
+
+static struct platform_device mspeth_device[] = {
+	[0] = {
+		.name	= MSP_ETH_ID,
+		.id	= 0,
+		.num_resources = ARRAY_SIZE(msp_eth0_resources),
+		.resource = msp_eth0_resources,
+	},
+	[1] = {
+		.name	= MSP_ETH_ID,
+		.id	= 1,
+		.num_resources = ARRAY_SIZE(msp_eth1_resources),
+		.resource = msp_eth1_resources,
+	},
+
+};
+#define msp_eth_devs	mspeth_device
+
+#endif
+int __init msp_eth_setup(void)
+{
+	int i, ret = 0;
+
+	/* Configure the GPIO and take the ethernet PHY out of reset */
+	msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO0);
+	msp_gpio_pin_hi(MSP_ETHERNET_GPIO0);
+
+#ifdef CONFIG_MSP_HAS_TSMAC
+	/* 3 phys on boards with TSMAC */
+	msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO1);
+	msp_gpio_pin_hi(MSP_ETHERNET_GPIO1);
+
+	msp_gpio_pin_mode(MSP_GPIO_OUTPUT, MSP_ETHERNET_GPIO2);
+	msp_gpio_pin_hi(MSP_ETHERNET_GPIO2);
+#endif
+	for (i = 0; i < ARRAY_SIZE(msp_eth_devs); i++) {
+		ret = platform_device_register(&msp_eth_devs[i]);
+		printk(KERN_INFO "device: %d, return value = %d\n", i, ret);
+		if (ret) {
+			platform_device_unregister(&msp_eth_devs[i]);
+			break;
+		}
+	}
+
+	if (ret)
+		printk(KERN_WARNING "Could not initialize "
+						"MSPETH device structures.\n");
+
+	return ret;
+}
+subsys_initcall(msp_eth_setup);
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,8 +19,6 @@
 
 #include <msp_int.h>
 
-extern void msp_int_handle(void);
-
 /* SLP bases systems */
 extern void msp_slp_irq_init(void);
 extern void msp_slp_irq_dispatch(void);
@@ -29,6 +27,18 @@
 extern void msp_cic_irq_init(void);
 extern void msp_cic_irq_dispatch(void);
 
+/* VSMP support init */
+extern void msp_vsmp_int_init(void);
+
+/* vectored interrupt implementation */
+
+/* SW0/1 interrupts are used for SMP/SMTC */
+static inline void mac0_int_dispatch(void) { do_IRQ(MSP_INT_MAC0); }
+static inline void mac1_int_dispatch(void) { do_IRQ(MSP_INT_MAC1); }
+static inline void mac2_int_dispatch(void) { do_IRQ(MSP_INT_SAR); }
+static inline void usb_int_dispatch(void)  { do_IRQ(MSP_INT_USB);  }
+static inline void sec_int_dispatch(void)  { do_IRQ(MSP_INT_SEC);  }
+
 /*
  * The PMC-Sierra MSP interrupts are arranged in a 3 level cascaded
  * hierarchical system.  The first level are the direct MIPS interrupts
@@ -96,29 +106,57 @@
 		do_IRQ(MSP_INT_SW1);
 }
 
-static struct irqaction cascade_msp = {
+static struct irqaction cic_cascade_msp = {
 	.handler = no_action,
-	.name	 = "MSP cascade"
+	.name	 = "MSP CIC cascade"
 };
 
+static struct irqaction per_cascade_msp = {
+	.handler = no_action,
+	.name	 = "MSP PER cascade"
+};
 
 void __init arch_init_irq(void)
 {
+	/* assume we'll be using vectored interrupt mode except in UP mode*/
+#ifdef CONFIG_MIPS_MT
+	BUG_ON(!cpu_has_vint);
+#endif
 	/* initialize the 1st-level CPU based interrupt controller */
 	mips_cpu_irq_init();
 
 #ifdef CONFIG_IRQ_MSP_CIC
 	msp_cic_irq_init();
+#ifdef CONFIG_MIPS_MT
+	set_vi_handler(MSP_INT_CIC, msp_cic_irq_dispatch);
+	set_vi_handler(MSP_INT_MAC0, mac0_int_dispatch);
+	set_vi_handler(MSP_INT_MAC1, mac1_int_dispatch);
+	set_vi_handler(MSP_INT_SAR, mac2_int_dispatch);
+	set_vi_handler(MSP_INT_USB, usb_int_dispatch);
+	set_vi_handler(MSP_INT_SEC, sec_int_dispatch);
+#ifdef CONFIG_MIPS_MT_SMP
+	msp_vsmp_int_init();
+#elif defined CONFIG_MIPS_MT_SMTC
+	/*Set hwmask for all platform devices */
+	irq_hwmask[MSP_INT_MAC0] = C_IRQ0;
+	irq_hwmask[MSP_INT_MAC1] = C_IRQ1;
+	irq_hwmask[MSP_INT_USB] = C_IRQ2;
+	irq_hwmask[MSP_INT_SAR] = C_IRQ3;
+	irq_hwmask[MSP_INT_SEC] = C_IRQ5;
 
+#endif	/* CONFIG_MIPS_MT_SMP */
+#endif	/* CONFIG_MIPS_MT */
 	/* setup the cascaded interrupts */
-	setup_irq(MSP_INT_CIC, &cascade_msp);
-	setup_irq(MSP_INT_PER, &cascade_msp);
+	setup_irq(MSP_INT_CIC, &cic_cascade_msp);
+	setup_irq(MSP_INT_PER, &per_cascade_msp);
+
 #else
 	/* setup the 2nd-level SLP register based interrupt controller */
+	/* VSMP /SMTC support support is not enabled for SLP */
 	msp_slp_irq_init();
 
 	/* setup the cascaded SLP/PER interrupts */
-	setup_irq(MSP_INT_SLP, &cascade_msp);
-	setup_irq(MSP_INT_PER, &cascade_msp);
+	setup_irq(MSP_INT_SLP, &cic_cascade_msp);
+	setup_irq(MSP_INT_PER, &per_cascade_msp);
 #endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_cic.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,7 @@
 /*
- * This file define the irq handler for MSP SLM subsystem interrupts.
+ * Copyright 2010 PMC-Sierra, Inc, derived from irq_cpu.c
  *
- * Copyright 2005-2007 PMC-Sierra, Inc, derived from irq_cpu.c
- * Author: Andrew Hughes, Andrew_Hughes@pmc-sierra.com
+ * This file define the irq handler for MSP CIC subsystem interrupts.
  *
  * This program is free software; you can redistribute  it and/or modify it
  * under  the terms of  the GNU General  Public License as published by the
@@ -16,119 +15,203 @@
 #include <linux/bitops.h>
 #include <linux/irq.h>
 
+#include <asm/mipsregs.h>
 #include <asm/system.h>
 
 #include <msp_cic_int.h>
 #include <msp_regs.h>
 
 /*
- * NOTE: We are only enabling support for VPE0 right now.
+ * External API
  */
+extern void msp_per_irq_init(void);
+extern void msp_per_irq_dispatch(void);
 
-static inline void unmask_msp_cic_irq(unsigned int irq)
+
+/*
+ * Convenience Macro.  Should be somewhere generic.
+ */
+#define get_current_vpe()   \
+	((read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE)
+
+#ifdef CONFIG_SMP
+
+#define LOCK_VPE(flags, mtflags) \
+do {				\
+	local_irq_save(flags);	\
+	mtflags = dmt();	\
+} while (0)
+
+#define UNLOCK_VPE(flags, mtflags) \
+do {				\
+	emt(mtflags);		\
+	local_irq_restore(flags);\
+} while (0)
+
+#define LOCK_CORE(flags, mtflags) \
+do {				\
+	local_irq_save(flags);	\
+	mtflags = dvpe();	\
+} while (0)
+
+#define UNLOCK_CORE(flags, mtflags)		\
+do {				\
+	evpe(mtflags);		\
+	local_irq_restore(flags);\
+} while (0)
+
+#else
+
+#define LOCK_VPE(flags, mtflags)
+#define UNLOCK_VPE(flags, mtflags)
+#endif
+
+/* ensure writes to cic are completed */
+static inline void cic_wmb(void)
 {
+	const volatile void __iomem *cic_mem = CIC_VPE0_MSK_REG;
+	volatile u32 dummy_read;
 
-	/* check for PER interrupt range */
-	if (irq < MSP_PER_INTBASE)
-		*CIC_VPE0_MSK_REG |= (1 << (irq - MSP_CIC_INTBASE));
-	else
-		*PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
+	wmb();
+	dummy_read = __raw_readl(cic_mem);
+	dummy_read++;
 }
 
-static inline void mask_msp_cic_irq(unsigned int irq)
+static void unmask_cic_irq(struct irq_data *d)
 {
-	/* check for PER interrupt range */
-	if (irq < MSP_PER_INTBASE)
-		*CIC_VPE0_MSK_REG &= ~(1 << (irq - MSP_CIC_INTBASE));
-	else
-		*PER_INT_MSK_REG &= ~(1 << (irq - MSP_PER_INTBASE));
+	volatile u32   *cic_msk_reg = CIC_VPE0_MSK_REG;
+	int vpe;
+#ifdef CONFIG_SMP
+	unsigned int mtflags;
+	unsigned long  flags;
+
+	/*
+	* Make sure we have IRQ affinity.  It may have changed while
+	* we were processing the IRQ.
+	*/
+	if (!cpumask_test_cpu(smp_processor_id(), d->affinity))
+		return;
+#endif
+
+	vpe = get_current_vpe();
+	LOCK_VPE(flags, mtflags);
+	cic_msk_reg[vpe] |= (1 << (d->irq - MSP_CIC_INTBASE));
+	UNLOCK_VPE(flags, mtflags);
+	cic_wmb();
 }
 
-/*
- * While we ack the interrupt interrupts are disabled and thus we don't need
- * to deal with concurrency issues.  Same for msp_cic_irq_end.
- */
-static inline void ack_msp_cic_irq(unsigned int irq)
+static void mask_cic_irq(struct irq_data *d)
 {
-	mask_msp_cic_irq(irq);
-
+	volatile u32 *cic_msk_reg = CIC_VPE0_MSK_REG;
+	int	vpe = get_current_vpe();
+#ifdef CONFIG_SMP
+	unsigned long flags, mtflags;
+#endif
+	LOCK_VPE(flags, mtflags);
+	cic_msk_reg[vpe] &= ~(1 << (d->irq - MSP_CIC_INTBASE));
+	UNLOCK_VPE(flags, mtflags);
+	cic_wmb();
+}
+static void msp_cic_irq_ack(struct irq_data *d)
+{
+	mask_cic_irq(d);
 	/*
-	 * 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.
-	 */
+	* 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
+	*/
+	*CIC_STS_REG = (1 << (d->irq - MSP_CIC_INTBASE));
+	smtc_im_ack_irq(d->irq);
+}
+
+/*Note: Limiting to VSMP . Not tested in SMTC */
+
+#ifdef CONFIG_MIPS_MT_SMP
+static int msp_cic_irq_set_affinity(struct irq_data *d,
+				    const struct cpumask *cpumask, bool force)
+{
+	int cpu;
+	unsigned long flags;
+	unsigned int  mtflags;
+	unsigned long imask = (1 << (irq - MSP_CIC_INTBASE));
+	volatile u32 *cic_mask = (volatile u32 *)CIC_VPE0_MSK_REG;
+
+	/* timer balancing should be disabled in kernel code */
+	BUG_ON(irq == MSP_INT_VPE0_TIMER || irq == MSP_INT_VPE1_TIMER);
+
+	LOCK_CORE(flags, mtflags);
+	/* enable if any of each VPE's TCs require this IRQ */
+	for_each_online_cpu(cpu) {
+		if (cpumask_test_cpu(cpu, cpumask))
+			cic_mask[cpu] |= imask;
+		else
+			cic_mask[cpu] &= ~imask;
+
+	}
+
+	UNLOCK_CORE(flags, mtflags);
+	return 0;
 
-	/* check for PER interrupt range */
-	if (irq < MSP_PER_INTBASE)
-		*CIC_STS_REG = (1 << (irq - MSP_CIC_INTBASE));
-	else
-		*PER_INT_STS_REG = (1 << (irq - MSP_PER_INTBASE));
 }
+#endif
 
 static struct irq_chip msp_cic_irq_controller = {
 	.name = "MSP_CIC",
-	.ack = ack_msp_cic_irq,
-	.mask = ack_msp_cic_irq,
-	.mask_ack = ack_msp_cic_irq,
-	.unmask = unmask_msp_cic_irq,
+	.irq_mask = mask_cic_irq,
+	.irq_mask_ack = msp_cic_irq_ack,
+	.irq_unmask = unmask_cic_irq,
+	.irq_ack = msp_cic_irq_ack,
+#ifdef CONFIG_MIPS_MT_SMP
+	.irq_set_affinity = msp_cic_irq_set_affinity,
+#endif
 };
 
-
 void __init msp_cic_irq_init(void)
 {
 	int i;
-
 	/* Mask/clear interrupts. */
 	*CIC_VPE0_MSK_REG = 0x00000000;
-	*PER_INT_MSK_REG  = 0x00000000;
+	*CIC_VPE1_MSK_REG = 0x00000000;
 	*CIC_STS_REG      = 0xFFFFFFFF;
-	*PER_INT_STS_REG  = 0xFFFFFFFF;
-
-#if defined(CONFIG_PMC_MSP7120_GW) || \
-    defined(CONFIG_PMC_MSP7120_EVAL)
 	/*
-	 * The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI.
-	 * These inputs map to EXT_INT_POL[6:4] inside the CIC.
-	 * They are to be active low, level sensitive.
-	 */
+	* The MSP7120 RG and EVBD boards use IRQ[6:4] for PCI.
+	* These inputs map to EXT_INT_POL[6:4] inside the CIC.
+	* They are to be active low, level sensitive.
+	*/
 	*CIC_EXT_CFG_REG &= 0xFFFF8F8F;
-#endif
 
 	/* initialize all the IRQ descriptors */
-	for (i = MSP_CIC_INTBASE; i < MSP_PER_INTBASE + 32; i++)
-		set_irq_chip_and_handler(i, &msp_cic_irq_controller,
+	for (i = MSP_CIC_INTBASE ; i < MSP_CIC_INTBASE + 32 ; i++) {
+		irq_set_chip_and_handler(i, &msp_cic_irq_controller,
 					 handle_level_irq);
+#ifdef CONFIG_MIPS_MT_SMTC
+		/* Mask of CIC interrupt */
+		irq_hwmask[i] = C_IRQ4;
+#endif
+	}
+
+	/* Initialize the PER interrupt sub-system */
+	 msp_per_irq_init();
 }
 
+/* CIC masked by CIC vector processing before dispatch called */
 void msp_cic_irq_dispatch(void)
 {
-	u32 pending;
-	int intbase;
-
-	intbase = MSP_CIC_INTBASE;
-	pending = *CIC_STS_REG & *CIC_VPE0_MSK_REG;
-
-	/* check for PER interrupt */
-	if (pending == (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) {
-		intbase = MSP_PER_INTBASE;
-		pending = *PER_INT_STS_REG & *PER_INT_MSK_REG;
-	}
-
-	/* check for spurious interrupt */
-	if (pending == 0x00000000) {
-		printk(KERN_ERR
-			"Spurious %s interrupt? status %08x, mask %08x\n",
-			(intbase == MSP_CIC_INTBASE) ? "CIC" : "PER",
-			(intbase == MSP_CIC_INTBASE) ?
-				*CIC_STS_REG : *PER_INT_STS_REG,
-			(intbase == MSP_CIC_INTBASE) ?
-				*CIC_VPE0_MSK_REG : *PER_INT_MSK_REG);
-		return;
-	}
-
-	/* check for the timer and dispatch it first */
-	if ((intbase == MSP_CIC_INTBASE) &&
-	    (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))))
+	volatile u32	*cic_msk_reg = (volatile u32 *)CIC_VPE0_MSK_REG;
+	u32	cic_mask;
+	u32	 pending;
+	int	cic_status = *CIC_STS_REG;
+	cic_mask = cic_msk_reg[get_current_vpe()];
+	pending = cic_status & cic_mask;
+	if (pending & (1 << (MSP_INT_VPE0_TIMER - MSP_CIC_INTBASE))) {
 		do_IRQ(MSP_INT_VPE0_TIMER);
-	else
-		do_IRQ(ffs(pending) + intbase - 1);
+	} else if (pending & (1 << (MSP_INT_VPE1_TIMER - MSP_CIC_INTBASE))) {
+		do_IRQ(MSP_INT_VPE1_TIMER);
+	} else if (pending & (1 << (MSP_INT_PER - MSP_CIC_INTBASE))) {
+		msp_per_irq_dispatch();
+	} else if (pending) {
+		do_IRQ(ffs(pending) + MSP_CIC_INTBASE - 1);
+	} else{
+		spurious_interrupt();
+	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_per.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2010 PMC-Sierra, Inc, derived from irq_cpu.c
+ *
+ * This file define the irq handler for MSP PER subsystem interrupts.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+
+#include <asm/mipsregs.h>
+#include <asm/system.h>
+
+#include <msp_cic_int.h>
+#include <msp_regs.h>
+
+
+/*
+ * Convenience Macro.  Should be somewhere generic.
+ */
+#define get_current_vpe()	\
+	((read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE)
+
+#ifdef CONFIG_SMP
+/*
+ * The PER registers must be protected from concurrent access.
+ */
+
+static DEFINE_SPINLOCK(per_lock);
+#endif
+
+/* ensure writes to per are completed */
+
+static inline void per_wmb(void)
+{
+	const volatile void __iomem *per_mem = PER_INT_MSK_REG;
+	volatile u32 dummy_read;
+
+	wmb();
+	dummy_read = __raw_readl(per_mem);
+	dummy_read++;
+}
+
+static inline void unmask_per_irq(struct irq_data *d)
+{
+#ifdef CONFIG_SMP
+	unsigned long flags;
+	spin_lock_irqsave(&per_lock, flags);
+	*PER_INT_MSK_REG |= (1 << (d->irq - MSP_PER_INTBASE));
+	spin_unlock_irqrestore(&per_lock, flags);
+#else
+	*PER_INT_MSK_REG |= (1 << (d->irq - MSP_PER_INTBASE));
+#endif
+	per_wmb();
+}
+
+static inline void mask_per_irq(struct irq_data *d)
+{
+#ifdef CONFIG_SMP
+	unsigned long flags;
+	spin_lock_irqsave(&per_lock, flags);
+	*PER_INT_MSK_REG &= ~(1 << (d->irq - MSP_PER_INTBASE));
+	spin_unlock_irqrestore(&per_lock, flags);
+#else
+	*PER_INT_MSK_REG &= ~(1 << (d->irq - MSP_PER_INTBASE));
+#endif
+	per_wmb();
+}
+
+static inline void msp_per_irq_ack(struct irq_data *d)
+{
+	mask_per_irq(d);
+	/*
+	 * In the PER interrupt controller, only bits 11 and 10
+	 * are write-to-clear, (SPI TX complete, SPI RX complete).
+	 * It does nothing for any others.
+	 */
+	*PER_INT_STS_REG = (1 << (d->irq - MSP_PER_INTBASE));
+}
+
+#ifdef CONFIG_SMP
+static int msp_per_irq_set_affinity(struct irq_data *d,
+				    const struct cpumask *affinity, bool force)
+{
+	/* WTF is this doing ????? */
+	unmask_per_irq(d);
+	return 0;
+}
+#endif
+
+static struct irq_chip msp_per_irq_controller = {
+	.name = "MSP_PER",
+	.irq_enable = unmask_per_irq,
+	.irq_disable = mask_per_irq,
+	.irq_ack = msp_per_irq_ack,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = msp_per_irq_set_affinity,
+#endif
+};
+
+void __init msp_per_irq_init(void)
+{
+	int i;
+	/* Mask/clear interrupts. */
+	*PER_INT_MSK_REG  = 0x00000000;
+	*PER_INT_STS_REG  = 0xFFFFFFFF;
+	/* initialize all the IRQ descriptors */
+	for (i = MSP_PER_INTBASE; i < MSP_PER_INTBASE + 32; i++) {
+		irq_set_chip(i, &msp_per_irq_controller);
+#ifdef CONFIG_MIPS_MT_SMTC
+		irq_hwmask[i] = C_IRQ4;
+#endif
+	}
+}
+
+void msp_per_irq_dispatch(void)
+{
+	u32	per_mask = *PER_INT_MSK_REG;
+	u32	per_status = *PER_INT_STS_REG;
+	u32	pending;
+
+	pending = per_status & per_mask;
+	if (pending) {
+		do_IRQ(ffs(pending) + MSP_PER_INTBASE - 1);
+	} else {
+		spurious_interrupt();
+	}
+}
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_irq_slp.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,8 +21,10 @@
 #include <msp_slp_int.h>
 #include <msp_regs.h>
 
-static inline void unmask_msp_slp_irq(unsigned int irq)
+static inline void unmask_msp_slp_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	/* check for PER interrupt range */
 	if (irq < MSP_PER_INTBASE)
 		*SLP_INT_MSK_REG |= (1 << (irq - MSP_SLP_INTBASE));
@@ -30,8 +32,10 @@
 		*PER_INT_MSK_REG |= (1 << (irq - MSP_PER_INTBASE));
 }
 
-static inline void mask_msp_slp_irq(unsigned int irq)
+static inline void mask_msp_slp_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	/* check for PER interrupt range */
 	if (irq < MSP_PER_INTBASE)
 		*SLP_INT_MSK_REG &= ~(1 << (irq - MSP_SLP_INTBASE));
@@ -43,8 +47,10 @@
  * While we ack the interrupt interrupts are disabled and thus we don't need
  * to deal with concurrency issues.  Same for msp_slp_irq_end.
  */
-static inline void ack_msp_slp_irq(unsigned int irq)
+static inline void ack_msp_slp_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	/* check for PER interrupt range */
 	if (irq < MSP_PER_INTBASE)
 		*SLP_INT_STS_REG = (1 << (irq - MSP_SLP_INTBASE));
@@ -54,9 +60,9 @@
 
 static struct irq_chip msp_slp_irq_controller = {
 	.name = "MSP_SLP",
-	.ack = ack_msp_slp_irq,
-	.mask = mask_msp_slp_irq,
-	.unmask = unmask_msp_slp_irq,
+	.irq_ack = ack_msp_slp_irq,
+	.irq_mask = mask_msp_slp_irq,
+	.irq_unmask = unmask_msp_slp_irq,
 };
 
 void __init msp_slp_irq_init(void)
@@ -71,7 +77,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,
+		irq_set_chip_and_handler(i, &msp_slp_irq_controller,
 					 handle_level_irq);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -146,6 +146,8 @@
 	pm_power_off = msp_power_off;
 }
 
+extern struct plat_smp_ops msp_smtc_smp_ops;
+
 void __init prom_init(void)
 {
 	unsigned long family;
@@ -226,10 +228,18 @@
 	 */
 	msp_serial_setup();
 
+#ifdef CONFIG_MIPS_MT_SMP
+	register_smp_ops(&vsmp_smp_ops);
+#endif
+
+#ifdef CONFIG_MIPS_MT_SMTC
+	register_smp_ops(&msp_smtc_smp_ops);
+#endif
+
 #ifdef CONFIG_PMCTWILED
 	/*
 	 * Setup LED states before the subsys_initcall loads other
-	 * dependant drivers/modules.
+	 * dependent drivers/modules.
 	 */
 	pmctwiled_setup();
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_smp.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_smp.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_smp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2000, 2001, 2004 MIPS Technologies, Inc.
+ * Copyright (C) 2001 Ralf Baechle
+ * Copyright (C) 2010 PMC-Sierra, Inc.
+ *
+ *  VSMP support for MSP platforms . Derived from malta vsmp support.
+ *
+ *  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/smp.h>
+#include <linux/interrupt.h>
+
+#ifdef CONFIG_MIPS_MT_SMP
+#define MIPS_CPU_IPI_RESCHED_IRQ 0	/* SW int 0 for resched */
+#define MIPS_CPU_IPI_CALL_IRQ 1		/* SW int 1 for call */
+
+
+static void ipi_resched_dispatch(void)
+{
+	do_IRQ(MIPS_CPU_IPI_RESCHED_IRQ);
+}
+
+static void ipi_call_dispatch(void)
+{
+	do_IRQ(MIPS_CPU_IPI_CALL_IRQ);
+}
+
+static irqreturn_t ipi_resched_interrupt(int irq, void *dev_id)
+{
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t ipi_call_interrupt(int irq, void *dev_id)
+{
+	smp_call_function_interrupt();
+
+	return IRQ_HANDLED;
+}
+
+static struct irqaction irq_resched = {
+	.handler	= ipi_resched_interrupt,
+	.flags		= IRQF_DISABLED | IRQF_PERCPU,
+	.name		= "IPI_resched"
+};
+
+static struct irqaction irq_call = {
+	.handler	= ipi_call_interrupt,
+	.flags		= IRQF_DISABLED | IRQF_PERCPU,
+	.name		= "IPI_call"
+};
+
+void __init arch_init_ipiirq(int irq, struct irqaction *action)
+{
+	setup_irq(irq, action);
+	irq_set_handler(irq, handle_percpu_irq);
+}
+
+void __init msp_vsmp_int_init(void)
+{
+	set_vi_handler(MIPS_CPU_IPI_RESCHED_IRQ, ipi_resched_dispatch);
+	set_vi_handler(MIPS_CPU_IPI_CALL_IRQ, ipi_call_dispatch);
+	arch_init_ipiirq(MIPS_CPU_IPI_RESCHED_IRQ, &irq_resched);
+	arch_init_ipiirq(MIPS_CPU_IPI_CALL_IRQ, &irq_call);
+}
+#endif /* CONFIG_MIPS_MT_SMP */
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_smtc.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_smtc.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_smtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_smtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * MSP71xx Platform-specific hooks for SMP operation
+ */
+#include <linux/irq.h>
+#include <linux/init.h>
+
+#include <asm/mipsmtregs.h>
+#include <asm/mipsregs.h>
+#include <asm/smtc.h>
+#include <asm/smtc_ipi.h>
+
+/* VPE/SMP Prototype implements platform interfaces directly */
+
+/*
+ * Cause the specified action to be performed on a targeted "CPU"
+ */
+
+static void msp_smtc_send_ipi_single(int cpu, unsigned int action)
+{
+	/* "CPU" may be TC of same VPE, VPE of same CPU, or different CPU */
+	smtc_send_ipi(cpu, LINUX_SMP_IPI, action);
+}
+
+static void msp_smtc_send_ipi_mask(const struct cpumask *mask,
+						unsigned int action)
+{
+	unsigned int i;
+
+	for_each_cpu(i, mask)
+		msp_smtc_send_ipi_single(i, action);
+}
+
+/*
+ * Post-config but pre-boot cleanup entry point
+ */
+static void __cpuinit msp_smtc_init_secondary(void)
+{
+	int myvpe;
+
+	/* Don't enable Malta I/O interrupts (IP2) for secondary VPEs */
+	myvpe = read_c0_tcbind() & TCBIND_CURVPE;
+	if (myvpe > 0)
+		change_c0_status(ST0_IM, STATUSF_IP0 | STATUSF_IP1 |
+				STATUSF_IP6 | STATUSF_IP7);
+	smtc_init_secondary();
+}
+
+/*
+ * Platform "CPU" startup hook
+ */
+static void __cpuinit msp_smtc_boot_secondary(int cpu,
+					struct task_struct *idle)
+{
+	smtc_boot_secondary(cpu, idle);
+}
+
+/*
+ * SMP initialization finalization entry point
+ */
+static void __cpuinit msp_smtc_smp_finish(void)
+{
+	smtc_smp_finish();
+}
+
+/*
+ * Hook for after all CPUs are online
+ */
+
+static void msp_smtc_cpus_done(void)
+{
+}
+
+/*
+ * Platform SMP pre-initialization
+ *
+ * As noted above, we can assume a single CPU for now
+ * but it may be multithreaded.
+ */
+
+static void __init msp_smtc_smp_setup(void)
+{
+	/*
+	 * we won't get the definitive value until
+	 * we've run smtc_prepare_cpus later, but
+	 */
+
+	if (read_c0_config3() & (1 << 2))
+		smp_num_siblings = smtc_build_cpu_map(0);
+}
+
+static void __init msp_smtc_prepare_cpus(unsigned int max_cpus)
+{
+	smtc_prepare_cpus(max_cpus);
+}
+
+struct plat_smp_ops msp_smtc_smp_ops = {
+	.send_ipi_single	= msp_smtc_send_ipi_single,
+	.send_ipi_mask		= msp_smtc_send_ipi_mask,
+	.init_secondary		= msp_smtc_init_secondary,
+	.smp_finish		= msp_smtc_smp_finish,
+	.cpus_done		= msp_smtc_cpus_done,
+	.boot_secondary		= msp_smtc_boot_secondary,
+	.smp_setup		= msp_smtc_smp_setup,
+	.prepare_cpus		= msp_smtc_prepare_cpus,
+};
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_time.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_time.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_time.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/module.h>
 #include <linux/ptrace.h>
 
+#include <asm/cevt-r4k.h>
 #include <asm/mipsregs.h>
 #include <asm/time.h>
 
@@ -36,6 +37,12 @@
 #include <msp_int.h>
 #include <msp_regs.h>
 
+#define get_current_vpe()   \
+	((read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE)
+
+static struct irqaction timer_vpe1;
+static int tim_installed;
+
 void __init plat_time_init(void)
 {
 	char    *endp, *s;
@@ -83,5 +90,12 @@
 
 unsigned int __cpuinit get_c0_compare_int(void)
 {
-	return MSP_INT_VPE0_TIMER;
+	/* MIPS_MT modes may want timer for second VPE */
+	if ((get_current_vpe()) && !tim_installed) {
+		memcpy(&timer_vpe1, &c0_compare_irqaction, sizeof(timer_vpe1));
+		setup_irq(MSP_INT_VPE1_TIMER, &timer_vpe1);
+		tim_installed++;
+	}
+
+	return get_current_vpe() ? MSP_INT_VPE1_TIMER : MSP_INT_VPE0_TIMER;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_usb.c linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_usb.c
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/msp71xx/msp_usb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/msp71xx/msp_usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * The setup file for USB related hardware on PMC-Sierra MSP processors.
  *
- * Copyright 2006-2007 PMC-Sierra, Inc.
+ * Copyright 2006 PMC-Sierra, 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
@@ -23,8 +23,8 @@
  *  with this program; if not, write  to the Free Software Foundation, Inc.,
  *  675 Mass Ave, Cambridge, MA 02139, USA.
  */
+#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
 
-#include <linux/dma-mapping.h>
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/platform_device.h>
@@ -34,40 +34,56 @@
 #include <msp_regs.h>
 #include <msp_int.h>
 #include <msp_prom.h>
+#include <msp_usb.h>
+
 
 #if defined(CONFIG_USB_EHCI_HCD)
-static struct resource msp_usbhost_resources [] = {
-	[0] = {
-		.start	= MSP_USB_BASE_START,
-		.end	= MSP_USB_BASE_END,
-		.flags 	= IORESOURCE_MEM,
+static struct resource msp_usbhost0_resources[] = {
+	[0] = { /* EHCI-HS operational and capabilities registers */
+		.start  = MSP_USB0_HS_START,
+		.end    = MSP_USB0_HS_END,
+		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
-		.start	= MSP_INT_USB,
-		.end	= MSP_INT_USB,
-		.flags	= IORESOURCE_IRQ,
+		.start  = MSP_INT_USB,
+		.end    = MSP_INT_USB,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = { /* MSBus-to-AMBA bridge register space */
+		.start	= MSP_USB0_MAB_START,
+		.end	= MSP_USB0_MAB_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = { /* Identification and general hardware parameters */
+		.start	= MSP_USB0_ID_START,
+		.end	= MSP_USB0_ID_END,
+		.flags	= IORESOURCE_MEM,
 	},
 };
 
-static u64 msp_usbhost_dma_mask = DMA_BIT_MASK(32);
+static u64 msp_usbhost0_dma_mask = 0xffffffffUL;
 
-static struct platform_device msp_usbhost_device = {
-	.name	= "pmcmsp-ehci",
-	.id	= 0,
+static struct mspusb_device msp_usbhost0_device = {
 	.dev	= {
-		.dma_mask = &msp_usbhost_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.name	= "pmcmsp-ehci",
+		.id	= 0,
+		.dev	= {
+			.dma_mask = &msp_usbhost0_dma_mask,
+			.coherent_dma_mask = 0xffffffffUL,
+		},
+		.num_resources  = ARRAY_SIZE(msp_usbhost0_resources),
+		.resource       = msp_usbhost0_resources,
 	},
-	.num_resources 	= ARRAY_SIZE(msp_usbhost_resources),
-	.resource	= msp_usbhost_resources,
 };
-#endif /* CONFIG_USB_EHCI_HCD */
 
-#if defined(CONFIG_USB_GADGET)
-static struct resource msp_usbdev_resources [] = {
-	[0] = {
-		.start	= MSP_USB_BASE,
-		.end	= MSP_USB_BASE_END,
+/* MSP7140/MSP82XX has two USB2 hosts. */
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+static u64 msp_usbhost1_dma_mask = 0xffffffffUL;
+
+static struct resource msp_usbhost1_resources[] = {
+	[0] = { /* EHCI-HS operational and capabilities registers */
+		.start	= MSP_USB1_HS_START,
+		.end	= MSP_USB1_HS_END,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -75,76 +91,173 @@
 		.end	= MSP_INT_USB,
 		.flags	= IORESOURCE_IRQ,
 	},
+	[2] = { /* MSBus-to-AMBA bridge register space */
+		.start	= MSP_USB1_MAB_START,
+		.end	= MSP_USB1_MAB_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = { /* Identification and general hardware parameters */
+		.start	= MSP_USB1_ID_START,
+		.end	= MSP_USB1_ID_END,
+		.flags	= IORESOURCE_MEM,
+	},
 };
 
-static u64 msp_usbdev_dma_mask = DMA_BIT_MASK(32);
+static struct mspusb_device msp_usbhost1_device = {
+	.dev	= {
+		.name	= "pmcmsp-ehci",
+		.id	= 1,
+		.dev	= {
+			.dma_mask = &msp_usbhost1_dma_mask,
+			.coherent_dma_mask = 0xffffffffUL,
+		},
+		.num_resources	= ARRAY_SIZE(msp_usbhost1_resources),
+		.resource	= msp_usbhost1_resources,
+	},
+};
+#endif /* CONFIG_MSP_HAS_DUAL_USB */
+#endif /* CONFIG_USB_EHCI_HCD */
 
-static struct platform_device msp_usbdev_device = {
-	.name	= "msp71xx_udc",
-	.id	= 0,
+#if defined(CONFIG_USB_GADGET)
+static struct resource msp_usbdev0_resources[] = {
+	[0] = { /* EHCI-HS operational and capabilities registers */
+		.start  = MSP_USB0_HS_START,
+		.end    = MSP_USB0_HS_END,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = MSP_INT_USB,
+		.end    = MSP_INT_USB,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = { /* MSBus-to-AMBA bridge register space */
+		.start	= MSP_USB0_MAB_START,
+		.end	= MSP_USB0_MAB_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = { /* Identification and general hardware parameters */
+		.start	= MSP_USB0_ID_START,
+		.end	= MSP_USB0_ID_END,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static u64 msp_usbdev_dma_mask = 0xffffffffUL;
+
+/* This may need to be converted to a mspusb_device, too. */
+static struct mspusb_device msp_usbdev0_device = {
 	.dev	= {
-		.dma_mask = &msp_usbdev_dma_mask,
-		.coherent_dma_mask = DMA_BIT_MASK(32),
+		.name	= "msp71xx_udc",
+		.id	= 0,
+		.dev	= {
+			.dma_mask = &msp_usbdev_dma_mask,
+			.coherent_dma_mask = 0xffffffffUL,
+		},
+		.num_resources  = ARRAY_SIZE(msp_usbdev0_resources),
+		.resource       = msp_usbdev0_resources,
 	},
-	.num_resources	= ARRAY_SIZE(msp_usbdev_resources),
-	.resource	= msp_usbdev_resources,
 };
-#endif /* CONFIG_USB_GADGET */
 
-#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
-static struct platform_device *msp_devs[1];
-#endif
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+static struct resource msp_usbdev1_resources[] = {
+	[0] = { /* EHCI-HS operational and capabilities registers */
+		.start  = MSP_USB1_HS_START,
+		.end    = MSP_USB1_HS_END,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = MSP_INT_USB,
+		.end    = MSP_INT_USB,
+		.flags  = IORESOURCE_IRQ,
+	},
+	[2] = { /* MSBus-to-AMBA bridge register space */
+		.start	= MSP_USB1_MAB_START,
+		.end	= MSP_USB1_MAB_END,
+		.flags	= IORESOURCE_MEM,
+	},
+	[3] = { /* Identification and general hardware parameters */
+		.start	= MSP_USB1_ID_START,
+		.end	= MSP_USB1_ID_END,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+/* This may need to be converted to a mspusb_device, too. */
+static struct mspusb_device msp_usbdev1_device = {
+	.dev	= {
+		.name	= "msp71xx_udc",
+		.id	= 0,
+		.dev	= {
+			.dma_mask = &msp_usbdev_dma_mask,
+			.coherent_dma_mask = 0xffffffffUL,
+		},
+		.num_resources  = ARRAY_SIZE(msp_usbdev1_resources),
+		.resource       = msp_usbdev1_resources,
+	},
+};
 
+#endif /* CONFIG_MSP_HAS_DUAL_USB */
+#endif /* CONFIG_USB_GADGET */
 
 static int __init msp_usb_setup(void)
 {
-#if defined(CONFIG_USB_EHCI_HCD) || defined(CONFIG_USB_GADGET)
-	char *strp;
-	char envstr[32];
-	unsigned int val = 0;
-	int result = 0;
+	char		*strp;
+	char		envstr[32];
+	struct platform_device *msp_devs[NUM_USB_DEVS];
+	unsigned int val;
 
+	/* construct environment name usbmode */
+	/* set usbmode <host/device> as pmon environment var */
 	/*
-	 * construct environment name usbmode
-	 * set usbmode <host/device> as pmon environment var
+	 * Could this perhaps be integrated into the "features" env var?
+	 * Use the features key "U", and follow with "H" for host-mode,
+	 * "D" for device-mode.  If it works for Ethernet, why not USB...
+	 *  -- hammtrev, 2007/03/22
 	 */
 	snprintf((char *)&envstr[0], sizeof(envstr), "usbmode");
 
-#if defined(CONFIG_USB_EHCI_HCD)
-	/* default to host mode */
+	/* set default host mode */
 	val = 1;
-#endif
 
 	/* get environment string */
 	strp = prom_getenv((char *)&envstr[0]);
 	if (strp) {
+		/* compare string */
 		if (!strcmp(strp, "device"))
 			val = 0;
 	}
 
 	if (val) {
 #if defined(CONFIG_USB_EHCI_HCD)
-		/* get host mode device */
-		msp_devs[0] = &msp_usbhost_device;
-		ppfinit("platform add USB HOST done %s.\n",
-			    msp_devs[0]->name);
-
-		result = platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs));
-#endif /* CONFIG_USB_EHCI_HCD */
-	}
+		msp_devs[0] = &msp_usbhost0_device.dev;
+		ppfinit("platform add USB HOST done %s.\n", msp_devs[0]->name);
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+		msp_devs[1] = &msp_usbhost1_device.dev;
+		ppfinit("platform add USB HOST done %s.\n", msp_devs[1]->name);
+#endif
+#else
+		ppfinit("%s: echi_hcd not supported\n", __FILE__);
+#endif  /* CONFIG_USB_EHCI_HCD */
+	} else {
 #if defined(CONFIG_USB_GADGET)
-	else {
 		/* get device mode structure */
-		msp_devs[0] = &msp_usbdev_device;
-		ppfinit("platform add USB DEVICE done %s.\n",
-			    msp_devs[0]->name);
-
-		result = platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs));
+		msp_devs[0] = &msp_usbdev0_device.dev;
+		ppfinit("platform add USB DEVICE done %s.\n"
+					, msp_devs[0]->name);
+#ifdef CONFIG_MSP_HAS_DUAL_USB
+		msp_devs[1] = &msp_usbdev1_device.dev;
+		ppfinit("platform add USB DEVICE done %s.\n"
+					, msp_devs[1]->name);
+#endif
+#else
+		ppfinit("%s: usb_gadget not supported\n", __FILE__);
+#endif  /* CONFIG_USB_GADGET */
 	}
-#endif /* CONFIG_USB_GADGET */
-#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
+	/* add device */
+	platform_add_devices(msp_devs, ARRAY_SIZE(msp_devs));
 
-	return result;
+	return 0;
 }
 
 subsys_initcall(msp_usb_setup);
+#endif /* CONFIG_USB_EHCI_HCD || CONFIG_USB_GADGET */
diff -druN linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/yosemite/Makefile linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/yosemite/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/pmc-sierra/yosemite/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pmc-sierra/yosemite/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,4 +6,4 @@
 
 obj-$(CONFIG_SMP)		+= smp.o
 
-EXTRA_CFLAGS += -Werror
+ccflags-y := -Werror
diff -druN linux-libre-2.6.38-gnu/arch/mips/pnx833x/common/interrupts.c linux-libre-2.6.39-gnu/arch/mips/pnx833x/common/interrupts.c
--- linux-libre-2.6.38-gnu/arch/mips/pnx833x/common/interrupts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pnx833x/common/interrupts.c	2011-05-19 00:06:34.000000000 -0400
@@ -152,10 +152,6 @@
 	PNX833X_PIC_INT_REG(irq) = 0;
 }
 
-static int irqflags[PNX833X_PIC_NUM_IRQ];	/* initialized by zeroes */
-#define IRQFLAG_STARTED		1
-#define IRQFLAG_DISABLED	2
-
 static DEFINE_RAW_SPINLOCK(pnx833x_irq_lock);
 
 static unsigned int pnx833x_startup_pic_irq(unsigned int irq)
@@ -164,108 +160,54 @@
 	unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
 
 	raw_spin_lock_irqsave(&pnx833x_irq_lock, flags);
-
-	irqflags[pic_irq] = IRQFLAG_STARTED;	/* started, not disabled */
 	pnx833x_hard_enable_pic_irq(pic_irq);
-
 	raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags);
 	return 0;
 }
 
-static void pnx833x_shutdown_pic_irq(unsigned int irq)
-{
-	unsigned long flags;
-	unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
-
-	raw_spin_lock_irqsave(&pnx833x_irq_lock, flags);
-
-	irqflags[pic_irq] = 0;			/* not started */
-	pnx833x_hard_disable_pic_irq(pic_irq);
-
-	raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags);
-}
-
-static void pnx833x_enable_pic_irq(unsigned int irq)
+static void pnx833x_enable_pic_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
+	unsigned int pic_irq = d->irq - PNX833X_PIC_IRQ_BASE;
 
 	raw_spin_lock_irqsave(&pnx833x_irq_lock, flags);
-
-	irqflags[pic_irq] &= ~IRQFLAG_DISABLED;
-	if (irqflags[pic_irq] == IRQFLAG_STARTED)
-		pnx833x_hard_enable_pic_irq(pic_irq);
-
+	pnx833x_hard_enable_pic_irq(pic_irq);
 	raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags);
 }
 
-static void pnx833x_disable_pic_irq(unsigned int irq)
+static void pnx833x_disable_pic_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int pic_irq = irq - PNX833X_PIC_IRQ_BASE;
+	unsigned int pic_irq = d->irq - PNX833X_PIC_IRQ_BASE;
 
 	raw_spin_lock_irqsave(&pnx833x_irq_lock, flags);
-
-	irqflags[pic_irq] |= IRQFLAG_DISABLED;
 	pnx833x_hard_disable_pic_irq(pic_irq);
-
 	raw_spin_unlock_irqrestore(&pnx833x_irq_lock, flags);
 }
 
-static void pnx833x_ack_pic_irq(unsigned int irq)
-{
-}
-
-static void pnx833x_end_pic_irq(unsigned int irq)
-{
-}
-
 static DEFINE_RAW_SPINLOCK(pnx833x_gpio_pnx833x_irq_lock);
 
-static unsigned int pnx833x_startup_gpio_irq(unsigned int irq)
-{
-	int pin = irq - PNX833X_GPIO_IRQ_BASE;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags);
-	pnx833x_gpio_enable_irq(pin);
-	raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags);
-	return 0;
-}
-
-static void pnx833x_enable_gpio_irq(unsigned int irq)
+static void pnx833x_enable_gpio_irq(struct irq_data *d)
 {
-	int pin = irq - PNX833X_GPIO_IRQ_BASE;
+	int pin = d->irq - PNX833X_GPIO_IRQ_BASE;
 	unsigned long flags;
 	raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags);
 	pnx833x_gpio_enable_irq(pin);
 	raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags);
 }
 
-static void pnx833x_disable_gpio_irq(unsigned int irq)
+static void pnx833x_disable_gpio_irq(struct irq_data *d)
 {
-	int pin = irq - PNX833X_GPIO_IRQ_BASE;
+	int pin = d->irq - PNX833X_GPIO_IRQ_BASE;
 	unsigned long flags;
 	raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags);
 	pnx833x_gpio_disable_irq(pin);
 	raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags);
 }
 
-static void pnx833x_ack_gpio_irq(unsigned int irq)
-{
-}
-
-static void pnx833x_end_gpio_irq(unsigned int irq)
-{
-	int pin = irq - PNX833X_GPIO_IRQ_BASE;
-	unsigned long flags;
-	raw_spin_lock_irqsave(&pnx833x_gpio_pnx833x_irq_lock, flags);
-	pnx833x_gpio_clear_irq(pin);
-	raw_spin_unlock_irqrestore(&pnx833x_gpio_pnx833x_irq_lock, flags);
-}
-
-static int pnx833x_set_type_gpio_irq(unsigned int irq, unsigned int flow_type)
+static int pnx833x_set_type_gpio_irq(struct irq_data *d, unsigned int flow_type)
 {
-	int pin = irq - PNX833X_GPIO_IRQ_BASE;
+	int pin = d->irq - PNX833X_GPIO_IRQ_BASE;
 	int gpio_mode;
 
 	switch (flow_type) {
@@ -296,23 +238,15 @@
 
 static struct irq_chip pnx833x_pic_irq_type = {
 	.name = "PNX-PIC",
-	.startup = pnx833x_startup_pic_irq,
-	.shutdown = pnx833x_shutdown_pic_irq,
-	.enable = pnx833x_enable_pic_irq,
-	.disable = pnx833x_disable_pic_irq,
-	.ack = pnx833x_ack_pic_irq,
-	.end = pnx833x_end_pic_irq
+	.irq_enable = pnx833x_enable_pic_irq,
+	.irq_disable = pnx833x_disable_pic_irq,
 };
 
 static struct irq_chip pnx833x_gpio_irq_type = {
 	.name = "PNX-GPIO",
-	.startup = pnx833x_startup_gpio_irq,
-	.shutdown = pnx833x_disable_gpio_irq,
-	.enable = pnx833x_enable_gpio_irq,
-	.disable = pnx833x_disable_gpio_irq,
-	.ack = pnx833x_ack_gpio_irq,
-	.end = pnx833x_end_gpio_irq,
-	.set_type = pnx833x_set_type_gpio_irq
+	.irq_enable = pnx833x_enable_gpio_irq,
+	.irq_disable = pnx833x_disable_gpio_irq,
+	.irq_set_type = pnx833x_set_type_gpio_irq,
 };
 
 void __init arch_init_irq(void)
@@ -325,11 +259,13 @@
 	/* Set IRQ information in irq_desc */
 	for (irq = PNX833X_PIC_IRQ_BASE; irq < (PNX833X_PIC_IRQ_BASE + PNX833X_PIC_NUM_IRQ); irq++) {
 		pnx833x_hard_disable_pic_irq(irq);
-		set_irq_chip_and_handler(irq, &pnx833x_pic_irq_type, handle_simple_irq);
+		irq_set_chip_and_handler(irq, &pnx833x_pic_irq_type,
+					 handle_simple_irq);
 	}
 
 	for (irq = PNX833X_GPIO_IRQ_BASE; irq < (PNX833X_GPIO_IRQ_BASE + PNX833X_GPIO_NUM_IRQ); irq++)
-		set_irq_chip_and_handler(irq, &pnx833x_gpio_irq_type, handle_simple_irq);
+		irq_set_chip_and_handler(irq, &pnx833x_gpio_irq_type,
+					 handle_simple_irq);
 
 	/* Set PIC priority limiter register to 0 */
 	PNX833X_PIC_INT_PRIORITY = 0;
diff -druN linux-libre-2.6.38-gnu/arch/mips/pnx833x/common/platform.c linux-libre-2.6.39-gnu/arch/mips/pnx833x/common/platform.c
--- linux-libre-2.6.38-gnu/arch/mips/pnx833x/common/platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pnx833x/common/platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -165,7 +165,7 @@
 	{
 		.base = PNX833X_I2C0_PORTS_START,
 		.irq = -1, /* should be PNX833X_PIC_I2C0_INT but polling is faster */
-		.clock = 6,	/* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Prefered HDCP) */
+		.clock = 6,	/* 0 == 400 kHz, 4 == 100 kHz(Maximum HDMI), 6 = 50kHz(Preferred HDCP) */
 		.bus_addr = 0,	/* no slave support */
 	},
 	{
diff -druN linux-libre-2.6.38-gnu/arch/mips/pnx8550/common/int.c linux-libre-2.6.39-gnu/arch/mips/pnx8550/common/int.c
--- linux-libre-2.6.38-gnu/arch/mips/pnx8550/common/int.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/pnx8550/common/int.c	2011-05-19 00:06:34.000000000 -0400
@@ -114,8 +114,10 @@
 	PNX8550_GIC_REQ(irq_nr) = (1<<26 | 1<<16) | (1<<28) | gic_prio[irq_nr];
 }
 
-static inline void mask_irq(unsigned int irq_nr)
+static inline void mask_irq(struct irq_data *d)
 {
+	unsigned int irq_nr = d->irq;
+
 	if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
 		modify_cp0_intmask(1 << irq_nr, 0);
 	} else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
@@ -129,8 +131,10 @@
 	}
 }
 
-static inline void unmask_irq(unsigned int irq_nr)
+static inline void unmask_irq(struct irq_data *d)
 {
+	unsigned int irq_nr = d->irq;
+
 	if ((PNX8550_INT_CP0_MIN <= irq_nr) && (irq_nr <= PNX8550_INT_CP0_MAX)) {
 		modify_cp0_intmask(0, 1 << irq_nr);
 	} else if ((PNX8550_INT_GIC_MIN <= irq_nr) &&
@@ -157,10 +161,8 @@
 
 static struct irq_chip level_irq_type = {
 	.name =		"PNX Level IRQ",
-	.ack =		mask_irq,
-	.mask =		mask_irq,
-	.mask_ack =	mask_irq,
-	.unmask =	unmask_irq,
+	.irq_mask =	mask_irq,
+	.irq_unmask =	unmask_irq,
 };
 
 static struct irqaction gic_action = {
@@ -180,10 +182,8 @@
 	int i;
 	int configPR;
 
-	for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++) {
-		set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
-		mask_irq(i);	/* mask the irq just in case  */
-	}
+	for (i = 0; i < PNX8550_INT_CP0_TOTINT; i++)
+		irq_set_chip_and_handler(i, &level_irq_type, handle_level_irq);
 
 	/* init of GIC/IPC interrupts */
 	/* should be done before cp0 since cp0 init enables the GIC int */
@@ -206,7 +206,7 @@
 		/* mask/priority is still 0 so we will not get any
 		 * interrupts until it is unmasked */
 
-		set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &level_irq_type, handle_level_irq);
 	}
 
 	/* Priority level 0 */
@@ -215,20 +215,20 @@
 	/* Set int vector table address */
 	PNX8550_GIC_VECTOR_0 = PNX8550_GIC_VECTOR_1 = 0;
 
-	set_irq_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
+	irq_set_chip_and_handler(MIPS_CPU_GIC_IRQ, &level_irq_type,
 				 handle_level_irq);
 	setup_irq(MIPS_CPU_GIC_IRQ, &gic_action);
 
 	/* init of Timer interrupts */
 	for (i = PNX8550_INT_TIMER_MIN; i <= PNX8550_INT_TIMER_MAX; i++)
-		set_irq_chip_and_handler(i, &level_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &level_irq_type, handle_level_irq);
 
 	/* Stop Timer 1-3 */
 	configPR = read_c0_config7();
 	configPR |= 0x00000038;
 	write_c0_config7(configPR);
 
-	set_irq_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
+	irq_set_chip_and_handler(MIPS_CPU_TIMER_IRQ, &level_irq_type,
 				 handle_level_irq);
 	setup_irq(MIPS_CPU_TIMER_IRQ, &timer_action);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/power/hibernate.S linux-libre-2.6.39-gnu/arch/mips/power/hibernate.S
--- linux-libre-2.6.38-gnu/arch/mips/power/hibernate.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/power/hibernate.S	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 0:
 	PTR_L t1, PBE_ADDRESS(t0)   /* source */
 	PTR_L t2, PBE_ORIG_ADDRESS(t0) /* destination */
-	PTR_ADDIU t3, t1, PAGE_SIZE
+	PTR_ADDU t3, t1, PAGE_SIZE
 1:
 	REG_L t8, (t1)
 	REG_S t8, (t2)
diff -druN linux-libre-2.6.38-gnu/arch/mips/powertv/asic/irq_asic.c linux-libre-2.6.39-gnu/arch/mips/powertv/asic/irq_asic.c
--- linux-libre-2.6.38-gnu/arch/mips/powertv/asic/irq_asic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/powertv/asic/irq_asic.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,9 +21,10 @@
 
 #include <asm/mach-powertv/asic_regs.h>
 
-static inline void unmask_asic_irq(unsigned int irq)
+static inline void unmask_asic_irq(struct irq_data *d)
 {
 	unsigned long enable_bit;
+	unsigned int irq = d->irq;
 
 	enable_bit = (1 << (irq & 0x1f));
 
@@ -45,9 +46,10 @@
 	}
 }
 
-static inline void mask_asic_irq(unsigned int irq)
+static inline void mask_asic_irq(struct irq_data *d)
 {
 	unsigned long disable_mask;
+	unsigned int irq = d->irq;
 
 	disable_mask = ~(1 << (irq & 0x1f));
 
@@ -71,11 +73,8 @@
 
 static struct irq_chip asic_irq_chip = {
 	.name = "ASIC Level",
-	.ack = mask_asic_irq,
-	.mask = mask_asic_irq,
-	.mask_ack = mask_asic_irq,
-	.unmask = unmask_asic_irq,
-	.eoi = unmask_asic_irq,
+	.irq_mask = mask_asic_irq,
+	.irq_unmask = unmask_asic_irq,
 };
 
 void __init asic_irq_init(void)
@@ -113,5 +112,5 @@
 	 * Initialize interrupt handlers.
 	 */
 	for (i = 0; i < NR_IRQS; i++)
-		set_irq_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
+		irq_set_chip_and_handler(i, &asic_irq_chip, handle_level_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/powertv/asic/Makefile linux-libre-2.6.39-gnu/arch/mips/powertv/asic/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/powertv/asic/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/powertv/asic/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -20,4 +20,4 @@
 	asic_devices.o asic_int.o irq_asic.o prealloc-calliope.o \
 	prealloc-cronus.o prealloc-cronuslite.o prealloc-gaia.o prealloc-zeus.o
 
-EXTRA_CFLAGS += -Wall -Werror
+ccflags-y := -Wall -Werror
diff -druN linux-libre-2.6.38-gnu/arch/mips/powertv/Makefile linux-libre-2.6.39-gnu/arch/mips/powertv/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/powertv/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/powertv/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -28,4 +28,4 @@
 
 obj-$(CONFIG_USB) += powertv-usb.o
 
-EXTRA_CFLAGS += -Wall
+ccflags-y := -Wall
diff -druN linux-libre-2.6.38-gnu/arch/mips/powertv/pci/Makefile linux-libre-2.6.39-gnu/arch/mips/powertv/pci/Makefile
--- linux-libre-2.6.38-gnu/arch/mips/powertv/pci/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/powertv/pci/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -18,4 +18,4 @@
 
 obj-$(CONFIG_PCI)	+= fixup-powertv.o
 
-EXTRA_CFLAGS += -Wall -Werror
+ccflags-y := -Wall -Werror
diff -druN linux-libre-2.6.38-gnu/arch/mips/rb532/gpio.c linux-libre-2.6.39-gnu/arch/mips/rb532/gpio.c
--- linux-libre-2.6.38-gnu/arch/mips/rb532/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/rb532/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,7 +185,7 @@
 	struct resource *r;
 
 	r = rb532_gpio_reg0_res;
-	rb532_gpio_chip->regbase = ioremap_nocache(r->start, r->end - r->start);
+	rb532_gpio_chip->regbase = ioremap_nocache(r->start, resource_size(r));
 
 	if (!rb532_gpio_chip->regbase) {
 		printk(KERN_ERR "rb532: cannot remap GPIO register 0\n");
diff -druN linux-libre-2.6.38-gnu/arch/mips/rb532/irq.c linux-libre-2.6.39-gnu/arch/mips/rb532/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/rb532/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/rb532/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,10 +111,10 @@
 	clear_c0_cause(ipnum);
 }
 
-static void rb532_enable_irq(unsigned int irq_nr)
+static void rb532_enable_irq(struct irq_data *d)
 {
+	unsigned int group, intr_bit, irq_nr = d->irq;
 	int ip = irq_nr - GROUP0_IRQ_BASE;
-	unsigned int group, intr_bit;
 	volatile unsigned int *addr;
 
 	if (ip < 0)
@@ -132,10 +132,10 @@
 	}
 }
 
-static void rb532_disable_irq(unsigned int irq_nr)
+static void rb532_disable_irq(struct irq_data *d)
 {
+	unsigned int group, intr_bit, mask, irq_nr = d->irq;
 	int ip = irq_nr - GROUP0_IRQ_BASE;
-	unsigned int group, intr_bit, mask;
 	volatile unsigned int *addr;
 
 	if (ip < 0) {
@@ -163,18 +163,18 @@
 	}
 }
 
-static void rb532_mask_and_ack_irq(unsigned int irq_nr)
+static void rb532_mask_and_ack_irq(struct irq_data *d)
 {
-	rb532_disable_irq(irq_nr);
-	ack_local_irq(group_to_ip(irq_to_group(irq_nr)));
+	rb532_disable_irq(d);
+	ack_local_irq(group_to_ip(irq_to_group(d->irq)));
 }
 
-static int rb532_set_type(unsigned int irq_nr, unsigned type)
+static int rb532_set_type(struct irq_data *d,  unsigned type)
 {
-	int gpio = irq_nr - GPIO_MAPPED_IRQ_BASE;
-	int group = irq_to_group(irq_nr);
+	int gpio = d->irq - GPIO_MAPPED_IRQ_BASE;
+	int group = irq_to_group(d->irq);
 
-	if (group != GPIO_MAPPED_IRQ_GROUP || irq_nr > (GROUP4_IRQ_BASE + 13))
+	if (group != GPIO_MAPPED_IRQ_GROUP || d->irq > (GROUP4_IRQ_BASE + 13))
 		return (type == IRQ_TYPE_LEVEL_HIGH) ? 0 : -EINVAL;
 
 	switch (type) {
@@ -193,11 +193,11 @@
 
 static struct irq_chip rc32434_irq_type = {
 	.name		= "RB532",
-	.ack		= rb532_disable_irq,
-	.mask		= rb532_disable_irq,
-	.mask_ack	= rb532_mask_and_ack_irq,
-	.unmask		= rb532_enable_irq,
-	.set_type	= rb532_set_type,
+	.irq_ack	= rb532_disable_irq,
+	.irq_mask	= rb532_disable_irq,
+	.irq_mask_ack	= rb532_mask_and_ack_irq,
+	.irq_unmask	= rb532_enable_irq,
+	.irq_set_type	= rb532_set_type,
 };
 
 void __init arch_init_irq(void)
@@ -207,8 +207,8 @@
 	pr_info("Initializing IRQ's: %d out of %d\n", RC32434_NR_IRQS, NR_IRQS);
 
 	for (i = 0; i < RC32434_NR_IRQS; i++)
-		set_irq_chip_and_handler(i,  &rc32434_irq_type,
-					handle_level_irq);
+		irq_set_chip_and_handler(i, &rc32434_irq_type,
+					 handle_level_irq);
 }
 
 /* Main Interrupt dispatcher */
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip22/ip22-int.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip22/ip22-int.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip22/ip22-int.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip22/ip22-int.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,88 +31,80 @@
 
 extern int ip22_eisa_init(void);
 
-static void enable_local0_irq(unsigned int irq)
+static void enable_local0_irq(struct irq_data *d)
 {
 	/* don't allow mappable interrupt to be enabled from setup_irq,
 	 * we have our own way to do so */
-	if (irq != SGI_MAP_0_IRQ)
-		sgint->imask0 |= (1 << (irq - SGINT_LOCAL0));
+	if (d->irq != SGI_MAP_0_IRQ)
+		sgint->imask0 |= (1 << (d->irq - SGINT_LOCAL0));
 }
 
-static void disable_local0_irq(unsigned int irq)
+static void disable_local0_irq(struct irq_data *d)
 {
-	sgint->imask0 &= ~(1 << (irq - SGINT_LOCAL0));
+	sgint->imask0 &= ~(1 << (d->irq - SGINT_LOCAL0));
 }
 
 static struct irq_chip ip22_local0_irq_type = {
 	.name		= "IP22 local 0",
-	.ack		= disable_local0_irq,
-	.mask		= disable_local0_irq,
-	.mask_ack	= disable_local0_irq,
-	.unmask		= enable_local0_irq,
+	.irq_mask	= disable_local0_irq,
+	.irq_unmask	= enable_local0_irq,
 };
 
-static void enable_local1_irq(unsigned int irq)
+static void enable_local1_irq(struct irq_data *d)
 {
 	/* don't allow mappable interrupt to be enabled from setup_irq,
 	 * we have our own way to do so */
-	if (irq != SGI_MAP_1_IRQ)
-		sgint->imask1 |= (1 << (irq - SGINT_LOCAL1));
+	if (d->irq != SGI_MAP_1_IRQ)
+		sgint->imask1 |= (1 << (d->irq - SGINT_LOCAL1));
 }
 
-static void disable_local1_irq(unsigned int irq)
+static void disable_local1_irq(struct irq_data *d)
 {
-	sgint->imask1 &= ~(1 << (irq - SGINT_LOCAL1));
+	sgint->imask1 &= ~(1 << (d->irq - SGINT_LOCAL1));
 }
 
 static struct irq_chip ip22_local1_irq_type = {
 	.name		= "IP22 local 1",
-	.ack		= disable_local1_irq,
-	.mask		= disable_local1_irq,
-	.mask_ack	= disable_local1_irq,
-	.unmask		= enable_local1_irq,
+	.irq_mask	= disable_local1_irq,
+	.irq_unmask	= enable_local1_irq,
 };
 
-static void enable_local2_irq(unsigned int irq)
+static void enable_local2_irq(struct irq_data *d)
 {
 	sgint->imask0 |= (1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
-	sgint->cmeimask0 |= (1 << (irq - SGINT_LOCAL2));
+	sgint->cmeimask0 |= (1 << (d->irq - SGINT_LOCAL2));
 }
 
-static void disable_local2_irq(unsigned int irq)
+static void disable_local2_irq(struct irq_data *d)
 {
-	sgint->cmeimask0 &= ~(1 << (irq - SGINT_LOCAL2));
+	sgint->cmeimask0 &= ~(1 << (d->irq - SGINT_LOCAL2));
 	if (!sgint->cmeimask0)
 		sgint->imask0 &= ~(1 << (SGI_MAP_0_IRQ - SGINT_LOCAL0));
 }
 
 static struct irq_chip ip22_local2_irq_type = {
 	.name		= "IP22 local 2",
-	.ack		= disable_local2_irq,
-	.mask		= disable_local2_irq,
-	.mask_ack	= disable_local2_irq,
-	.unmask		= enable_local2_irq,
+	.irq_mask	= disable_local2_irq,
+	.irq_unmask	= enable_local2_irq,
 };
 
-static void enable_local3_irq(unsigned int irq)
+static void enable_local3_irq(struct irq_data *d)
 {
 	sgint->imask1 |= (1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
-	sgint->cmeimask1 |= (1 << (irq - SGINT_LOCAL3));
+	sgint->cmeimask1 |= (1 << (d->irq - SGINT_LOCAL3));
 }
 
-static void disable_local3_irq(unsigned int irq)
+static void disable_local3_irq(struct irq_data *d)
 {
-	sgint->cmeimask1 &= ~(1 << (irq - SGINT_LOCAL3));
+	sgint->cmeimask1 &= ~(1 << (d->irq - SGINT_LOCAL3));
 	if (!sgint->cmeimask1)
 		sgint->imask1 &= ~(1 << (SGI_MAP_1_IRQ - SGINT_LOCAL1));
 }
 
 static struct irq_chip ip22_local3_irq_type = {
 	.name		= "IP22 local 3",
-	.ack		= disable_local3_irq,
-	.mask		= disable_local3_irq,
-	.mask_ack	= disable_local3_irq,
-	.unmask		= enable_local3_irq,
+	.irq_mask	= disable_local3_irq,
+	.irq_unmask	= enable_local3_irq,
 };
 
 static void indy_local0_irqdispatch(void)
@@ -320,7 +312,7 @@
 		else
 			handler		= &ip22_local3_irq_type;
 
-		set_irq_chip_and_handler(i, handler, handle_level_irq);
+		irq_set_chip_and_handler(i, handler, handle_level_irq);
 	}
 
 	/* vector handler. this register the IRQ as non-sharable */
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip22/ip22-platform.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip22/ip22-platform.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip22/ip22-platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip22/ip22-platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -132,7 +132,7 @@
  */
 static int __init sgiseeq_devinit(void)
 {
-	unsigned int tmp;
+	unsigned int pbdma __maybe_unused;
 	int res, i;
 
 	eth0_pd.hpc = hpc3c0;
@@ -151,7 +151,7 @@
 
 	/* Second HPC is missing? */
 	if (ip22_is_fullhouse() ||
-	    get_dbe(tmp, (unsigned int *)&hpc3c1->pbdma[1]))
+	    get_dbe(pbdma, (unsigned int *)&hpc3c1->pbdma[1]))
 		return 0;
 
 	sgimc->giopar |= SGIMC_GIOPAR_MASTEREXP1 | SGIMC_GIOPAR_EXP164 |
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip22/ip22-time.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip22/ip22-time.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip22/ip22-time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip22/ip22-time.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 static unsigned long dosample(void)
 {
 	u32 ct0, ct1;
-	u8 msb, lsb;
+	u8 msb;
 
 	/* Start the counter. */
 	sgint->tcword = (SGINT_TCWORD_CNT2 | SGINT_TCWORD_CALL |
@@ -46,7 +46,7 @@
 	/* Latch and spin until top byte of counter2 is zero */
 	do {
 		writeb(SGINT_TCWORD_CNT2 | SGINT_TCWORD_CLAT, &sgint->tcword);
-		lsb = readb(&sgint->tcnt2);
+		(void) readb(&sgint->tcnt2);
 		msb = readb(&sgint->tcnt2);
 		ct1 = read_c0_count();
 	} while (msb);
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-hubio.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-hubio.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-hubio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-hubio.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,6 @@
 			  unsigned long xtalk_addr, size_t size)
 {
 	nasid_t nasid = COMPACT_TO_NASID_NODEID(cnode);
-	volatile hubreg_t junk;
 	unsigned i;
 
 	/* use small-window mapping if possible */
@@ -64,7 +63,7 @@
 		 * after we write it.
 		 */
 		IIO_ITTE_PUT(nasid, i, HUB_PIO_MAP_TO_MEM, widget, xtalk_addr);
-		junk = HUB_L(IIO_ITTE_GET(nasid, i));
+		(void) HUB_L(IIO_ITTE_GET(nasid, i));
 
 		return NODE_BWIN_BASE(nasid, widget) + (xtalk_addr % BWIN_SIZE);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-init.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-init.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-init.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 
 	/*
 	 * Some interrupts are reserved by hardware or by software convention.
-	 * Mark these as reserved right away so they won't be used accidently
+	 * Mark these as reserved right away so they won't be used accidentally
 	 * later.
 	 */
 	for (i = 0; i <= BASE_PCI_IRQ; i++) {
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-irq.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-irq.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
  * Linux has a controller-independent x86 interrupt architecture.
  * every controller has a 'controller-template', that is used
  * by the main code to do the right thing. Each driver-visible
- * interrupt source is transparently wired to the apropriate
+ * interrupt source is transparently wired to the appropriate
  * controller. Thus drivers need not be aware of the
  * interrupt-controller.
  *
@@ -240,7 +240,7 @@
 }
 
 /* Startup one of the (PCI ...) IRQs routes over a bridge.  */
-static unsigned int startup_bridge_irq(unsigned int irq)
+static unsigned int startup_bridge_irq(struct irq_data *d)
 {
 	struct bridge_controller *bc;
 	bridgereg_t device;
@@ -248,16 +248,16 @@
 	int pin, swlevel;
 	cpuid_t cpu;
 
-	pin = SLOT_FROM_PCI_IRQ(irq);
-	bc = IRQ_TO_BRIDGE(irq);
+	pin = SLOT_FROM_PCI_IRQ(d->irq);
+	bc = IRQ_TO_BRIDGE(d->irq);
 	bridge = bc->base;
 
-	pr_debug("bridge_startup(): irq= 0x%x  pin=%d\n", irq, pin);
+	pr_debug("bridge_startup(): irq= 0x%x  pin=%d\n", d->irq, pin);
 	/*
 	 * "map" irq to a swlevel greater than 6 since the first 6 bits
 	 * of INT_PEND0 are taken
 	 */
-	swlevel = find_level(&cpu, irq);
+	swlevel = find_level(&cpu, d->irq);
 	bridge->b_int_addr[pin].addr = (0x20000 | swlevel | (bc->nasid << 8));
 	bridge->b_int_enable |= (1 << pin);
 	bridge->b_int_enable |= 0x7ffffe00;	/* more stuff in int_enable */
@@ -288,58 +288,56 @@
 }
 
 /* Shutdown one of the (PCI ...) IRQs routes over a bridge.  */
-static void shutdown_bridge_irq(unsigned int irq)
+static void shutdown_bridge_irq(struct irq_data *d)
 {
-	struct bridge_controller *bc = IRQ_TO_BRIDGE(irq);
+	struct bridge_controller *bc = IRQ_TO_BRIDGE(d->irq);
 	bridge_t *bridge = bc->base;
 	int pin, swlevel;
 	cpuid_t cpu;
 
-	pr_debug("bridge_shutdown: irq 0x%x\n", irq);
-	pin = SLOT_FROM_PCI_IRQ(irq);
+	pr_debug("bridge_shutdown: irq 0x%x\n", d->irq);
+	pin = SLOT_FROM_PCI_IRQ(d->irq);
 
 	/*
 	 * map irq to a swlevel greater than 6 since the first 6 bits
 	 * of INT_PEND0 are taken
 	 */
-	swlevel = find_level(&cpu, irq);
+	swlevel = find_level(&cpu, d->irq);
 	intr_disconnect_level(cpu, swlevel);
 
 	bridge->b_int_enable &= ~(1 << pin);
 	bridge->b_wid_tflush;
 }
 
-static inline void enable_bridge_irq(unsigned int irq)
+static inline void enable_bridge_irq(struct irq_data *d)
 {
 	cpuid_t cpu;
 	int swlevel;
 
-	swlevel = find_level(&cpu, irq);	/* Criminal offence */
+	swlevel = find_level(&cpu, d->irq);	/* Criminal offence */
 	intr_connect_level(cpu, swlevel);
 }
 
-static inline void disable_bridge_irq(unsigned int irq)
+static inline void disable_bridge_irq(struct irq_data *d)
 {
 	cpuid_t cpu;
 	int swlevel;
 
-	swlevel = find_level(&cpu, irq);	/* Criminal offence */
+	swlevel = find_level(&cpu, d->irq);	/* Criminal offence */
 	intr_disconnect_level(cpu, swlevel);
 }
 
 static struct irq_chip bridge_irq_type = {
 	.name		= "bridge",
-	.startup	= startup_bridge_irq,
-	.shutdown	= shutdown_bridge_irq,
-	.ack		= disable_bridge_irq,
-	.mask		= disable_bridge_irq,
-	.mask_ack	= disable_bridge_irq,
-	.unmask		= enable_bridge_irq,
+	.irq_startup	= startup_bridge_irq,
+	.irq_shutdown	= shutdown_bridge_irq,
+	.irq_mask	= disable_bridge_irq,
+	.irq_unmask	= enable_bridge_irq,
 };
 
 void __devinit register_bridge_irq(unsigned int irq)
 {
-	set_irq_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(irq, &bridge_irq_type, handle_level_irq);
 }
 
 int __devinit request_bridge_irq(struct bridge_controller *bc)
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-klnuma.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-klnuma.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-klnuma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-klnuma.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,11 +54,8 @@
 
 static __init void set_ktext_source(nasid_t client_nasid, nasid_t server_nasid)
 {
-	cnodeid_t client_cnode;
 	kern_vars_t *kvp;
 
-	client_cnode = NASID_TO_COMPACT_NODEID(client_nasid);
-
 	kvp = &hub_data(client_nasid)->kern_vars;
 
 	KERN_VARS_ADDR(client_nasid) = (unsigned long)kvp;
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-timer.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-timer.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/ip27-timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/ip27-timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,21 +36,18 @@
 #include <asm/sn/sn0/hubio.h>
 #include <asm/pci/bridge.h>
 
-static void enable_rt_irq(unsigned int irq)
+static void enable_rt_irq(struct irq_data *d)
 {
 }
 
-static void disable_rt_irq(unsigned int irq)
+static void disable_rt_irq(struct irq_data *d)
 {
 }
 
 static struct irq_chip rt_irq_type = {
 	.name		= "SN HUB RT timer",
-	.ack		= disable_rt_irq,
-	.mask		= disable_rt_irq,
-	.mask_ack	= disable_rt_irq,
-	.unmask		= enable_rt_irq,
-	.eoi		= enable_rt_irq,
+	.irq_mask	= disable_rt_irq,
+	.irq_unmask	= enable_rt_irq,
 };
 
 static int rt_next_event(unsigned long delta, struct clock_event_device *evt)
@@ -156,7 +153,7 @@
 			panic("Allocation of irq number for timer failed");
 	} while (xchg(&rt_timer_irq, irq));
 
-	set_irq_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
+	irq_set_chip_and_handler(irq, &rt_irq_type, handle_percpu_irq);
 	setup_irq(irq, &hub_rt_irqaction);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/Kconfig linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/Kconfig
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 #config SGI_SN0_XXL
 #	bool "IP27 XXL"
 #	depends on SGI_IP27
-#	  This options adds support for userspace processes upto 16TB size.
+#	  This options adds support for userspace processes up to 16TB size.
 #	  Normally the limit is just .5TB.
 
 choice
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/TODO linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/TODO
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip27/TODO	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip27/TODO	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 9. start_thread must turn off UX64 ... and define tlb_refill_debug.
 10. Need a bad pmd table, bad pte table. __bad_pmd_table/__bad_pagetable
 does not agree with pgd_bad/pmd_bad.
-11. All intrs (ip27_do_irq handlers) are targetted at cpu A on the node.
+11. All intrs (ip27_do_irq handlers) are targeted at cpu A on the node.
 This might need to change later. Only the timer intr is set up to be
 received on both Cpu A and B. (ip27_do_irq()/bridge_startup())
 13. Cache flushing (specially the SMP version) has to be investigated.
diff -druN linux-libre-2.6.38-gnu/arch/mips/sgi-ip32/ip32-irq.c linux-libre-2.6.39-gnu/arch/mips/sgi-ip32/ip32-irq.c
--- linux-libre-2.6.38-gnu/arch/mips/sgi-ip32/ip32-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sgi-ip32/ip32-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,70 +130,48 @@
 
 static uint64_t crime_mask;
 
-static inline void crime_enable_irq(unsigned int irq)
+static inline void crime_enable_irq(struct irq_data *d)
 {
-	unsigned int bit = irq - CRIME_IRQ_BASE;
+	unsigned int bit = d->irq - CRIME_IRQ_BASE;
 
 	crime_mask |= 1 << bit;
 	crime->imask = crime_mask;
 }
 
-static inline void crime_disable_irq(unsigned int irq)
+static inline void crime_disable_irq(struct irq_data *d)
 {
-	unsigned int bit = irq - CRIME_IRQ_BASE;
+	unsigned int bit = d->irq - CRIME_IRQ_BASE;
 
 	crime_mask &= ~(1 << bit);
 	crime->imask = crime_mask;
 	flush_crime_bus();
 }
 
-static void crime_level_mask_and_ack_irq(unsigned int irq)
-{
-	crime_disable_irq(irq);
-}
-
-static void crime_level_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		crime_enable_irq(irq);
-}
-
 static struct irq_chip crime_level_interrupt = {
 	.name		= "IP32 CRIME",
-	.ack		= crime_level_mask_and_ack_irq,
-	.mask		= crime_disable_irq,
-	.mask_ack	= crime_level_mask_and_ack_irq,
-	.unmask		= crime_enable_irq,
-	.end		= crime_level_end_irq,
+	.irq_mask	= crime_disable_irq,
+	.irq_unmask	= crime_enable_irq,
 };
 
-static void crime_edge_mask_and_ack_irq(unsigned int irq)
+static void crime_edge_mask_and_ack_irq(struct irq_data *d)
 {
-	unsigned int bit = irq - CRIME_IRQ_BASE;
+	unsigned int bit = d->irq - CRIME_IRQ_BASE;
 	uint64_t crime_int;
 
 	/* Edge triggered interrupts must be cleared. */
-
 	crime_int = crime->hard_int;
 	crime_int &= ~(1 << bit);
 	crime->hard_int = crime_int;
 
-	crime_disable_irq(irq);
-}
-
-static void crime_edge_end_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		crime_enable_irq(irq);
+	crime_disable_irq(d);
 }
 
 static struct irq_chip crime_edge_interrupt = {
 	.name		= "IP32 CRIME",
-	.ack		= crime_edge_mask_and_ack_irq,
-	.mask		= crime_disable_irq,
-	.mask_ack	= crime_edge_mask_and_ack_irq,
-	.unmask		= crime_enable_irq,
-	.end		= crime_edge_end_irq,
+	.irq_ack	= crime_edge_mask_and_ack_irq,
+	.irq_mask	= crime_disable_irq,
+	.irq_mask_ack	= crime_edge_mask_and_ack_irq,
+	.irq_unmask	= crime_enable_irq,
 };
 
 /*
@@ -204,37 +182,28 @@
 
 static unsigned long macepci_mask;
 
-static void enable_macepci_irq(unsigned int irq)
+static void enable_macepci_irq(struct irq_data *d)
 {
-	macepci_mask |= MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ);
+	macepci_mask |= MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ);
 	mace->pci.control = macepci_mask;
-	crime_mask |= 1 << (irq - CRIME_IRQ_BASE);
+	crime_mask |= 1 << (d->irq - CRIME_IRQ_BASE);
 	crime->imask = crime_mask;
 }
 
-static void disable_macepci_irq(unsigned int irq)
+static void disable_macepci_irq(struct irq_data *d)
 {
-	crime_mask &= ~(1 << (irq - CRIME_IRQ_BASE));
+	crime_mask &= ~(1 << (d->irq - CRIME_IRQ_BASE));
 	crime->imask = crime_mask;
 	flush_crime_bus();
-	macepci_mask &= ~MACEPCI_CONTROL_INT(irq - MACEPCI_SCSI0_IRQ);
+	macepci_mask &= ~MACEPCI_CONTROL_INT(d->irq - MACEPCI_SCSI0_IRQ);
 	mace->pci.control = macepci_mask;
 	flush_mace_bus();
 }
 
-static void end_macepci_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_macepci_irq(irq);
-}
-
 static struct irq_chip ip32_macepci_interrupt = {
 	.name = "IP32 MACE PCI",
-	.ack = disable_macepci_irq,
-	.mask = disable_macepci_irq,
-	.mask_ack = disable_macepci_irq,
-	.unmask = enable_macepci_irq,
-	.end = end_macepci_irq,
+	.irq_mask = disable_macepci_irq,
+	.irq_unmask = enable_macepci_irq,
 };
 
 /* This is used for MACE ISA interrupts.  That means bits 4-6 in the
@@ -276,13 +245,13 @@
 
 static unsigned long maceisa_mask;
 
-static void enable_maceisa_irq(unsigned int irq)
+static void enable_maceisa_irq(struct irq_data *d)
 {
 	unsigned int crime_int = 0;
 
-	pr_debug("maceisa enable: %u\n", irq);
+	pr_debug("maceisa enable: %u\n", d->irq);
 
-	switch (irq) {
+	switch (d->irq) {
 	case MACEISA_AUDIO_SW_IRQ ... MACEISA_AUDIO3_MERR_IRQ:
 		crime_int = MACE_AUDIO_INT;
 		break;
@@ -296,15 +265,15 @@
 	pr_debug("crime_int %08x enabled\n", crime_int);
 	crime_mask |= crime_int;
 	crime->imask = crime_mask;
-	maceisa_mask |= 1 << (irq - MACEISA_AUDIO_SW_IRQ);
+	maceisa_mask |= 1 << (d->irq - MACEISA_AUDIO_SW_IRQ);
 	mace->perif.ctrl.imask = maceisa_mask;
 }
 
-static void disable_maceisa_irq(unsigned int irq)
+static void disable_maceisa_irq(struct irq_data *d)
 {
 	unsigned int crime_int = 0;
 
-	maceisa_mask &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ));
+	maceisa_mask &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ));
         if (!(maceisa_mask & MACEISA_AUDIO_INT))
 		crime_int |= MACE_AUDIO_INT;
         if (!(maceisa_mask & MACEISA_MISC_INT))
@@ -318,76 +287,57 @@
 	flush_mace_bus();
 }
 
-static void mask_and_ack_maceisa_irq(unsigned int irq)
+static void mask_and_ack_maceisa_irq(struct irq_data *d)
 {
 	unsigned long mace_int;
 
 	/* edge triggered */
 	mace_int = mace->perif.ctrl.istat;
-	mace_int &= ~(1 << (irq - MACEISA_AUDIO_SW_IRQ));
+	mace_int &= ~(1 << (d->irq - MACEISA_AUDIO_SW_IRQ));
 	mace->perif.ctrl.istat = mace_int;
 
-	disable_maceisa_irq(irq);
-}
-
-static void end_maceisa_irq(unsigned irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS)))
-		enable_maceisa_irq(irq);
+	disable_maceisa_irq(d);
 }
 
 static struct irq_chip ip32_maceisa_level_interrupt = {
 	.name		= "IP32 MACE ISA",
-	.ack		= disable_maceisa_irq,
-	.mask		= disable_maceisa_irq,
-	.mask_ack	= disable_maceisa_irq,
-	.unmask		= enable_maceisa_irq,
-	.end		= end_maceisa_irq,
+	.irq_mask	= disable_maceisa_irq,
+	.irq_unmask	= enable_maceisa_irq,
 };
 
 static struct irq_chip ip32_maceisa_edge_interrupt = {
 	.name		= "IP32 MACE ISA",
-	.ack		= mask_and_ack_maceisa_irq,
-	.mask		= disable_maceisa_irq,
-	.mask_ack	= mask_and_ack_maceisa_irq,
-	.unmask		= enable_maceisa_irq,
-	.end		= end_maceisa_irq,
+	.irq_ack	= mask_and_ack_maceisa_irq,
+	.irq_mask	= disable_maceisa_irq,
+	.irq_mask_ack	= mask_and_ack_maceisa_irq,
+	.irq_unmask	= enable_maceisa_irq,
 };
 
 /* This is used for regular non-ISA, non-PCI MACE interrupts.  That means
  * bits 0-3 and 7 in the CRIME register.
  */
 
-static void enable_mace_irq(unsigned int irq)
+static void enable_mace_irq(struct irq_data *d)
 {
-	unsigned int bit = irq - CRIME_IRQ_BASE;
+	unsigned int bit = d->irq - CRIME_IRQ_BASE;
 
 	crime_mask |= (1 << bit);
 	crime->imask = crime_mask;
 }
 
-static void disable_mace_irq(unsigned int irq)
+static void disable_mace_irq(struct irq_data *d)
 {
-	unsigned int bit = irq - CRIME_IRQ_BASE;
+	unsigned int bit = d->irq - CRIME_IRQ_BASE;
 
 	crime_mask &= ~(1 << bit);
 	crime->imask = crime_mask;
 	flush_crime_bus();
 }
 
-static void end_mace_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_mace_irq(irq);
-}
-
 static struct irq_chip ip32_mace_interrupt = {
 	.name = "IP32 MACE",
-	.ack = disable_mace_irq,
-	.mask = disable_mace_irq,
-	.mask_ack = disable_mace_irq,
-	.unmask = enable_mace_irq,
-	.end = end_mace_irq,
+	.irq_mask = disable_mace_irq,
+	.irq_unmask = enable_mace_irq,
 };
 
 static void ip32_unknown_interrupt(void)
@@ -501,43 +451,51 @@
 	for (irq = CRIME_IRQ_BASE; irq <= IP32_IRQ_MAX; irq++) {
 		switch (irq) {
 		case MACE_VID_IN1_IRQ ... MACE_PCI_BRIDGE_IRQ:
-			set_irq_chip_and_handler_name(irq,&ip32_mace_interrupt,
-				handle_level_irq, "level");
+			irq_set_chip_and_handler_name(irq,
+						      &ip32_mace_interrupt,
+						      handle_level_irq,
+						      "level");
 			break;
 
 		case MACEPCI_SCSI0_IRQ ...  MACEPCI_SHARED2_IRQ:
-			set_irq_chip_and_handler_name(irq,
-				&ip32_macepci_interrupt, handle_level_irq,
-				"level");
+			irq_set_chip_and_handler_name(irq,
+						      &ip32_macepci_interrupt,
+						      handle_level_irq,
+						      "level");
 			break;
 
 		case CRIME_CPUERR_IRQ:
 		case CRIME_MEMERR_IRQ:
-			set_irq_chip_and_handler_name(irq,
-				&crime_level_interrupt, handle_level_irq,
-				"level");
+			irq_set_chip_and_handler_name(irq,
+						      &crime_level_interrupt,
+						      handle_level_irq,
+						      "level");
 			break;
 
 		case CRIME_GBE0_IRQ ... CRIME_GBE3_IRQ:
 		case CRIME_RE_EMPTY_E_IRQ ... CRIME_RE_IDLE_E_IRQ:
 		case CRIME_SOFT0_IRQ ... CRIME_SOFT2_IRQ:
 		case CRIME_VICE_IRQ:
-			set_irq_chip_and_handler_name(irq,
-				&crime_edge_interrupt, handle_edge_irq, "edge");
+			irq_set_chip_and_handler_name(irq,
+						      &crime_edge_interrupt,
+						      handle_edge_irq,
+						      "edge");
 			break;
 
 		case MACEISA_PARALLEL_IRQ:
 		case MACEISA_SERIAL1_TDMAPR_IRQ:
 		case MACEISA_SERIAL2_TDMAPR_IRQ:
-			set_irq_chip_and_handler_name(irq,
-				&ip32_maceisa_edge_interrupt, handle_edge_irq,
-				"edge");
+			irq_set_chip_and_handler_name(irq,
+						      &ip32_maceisa_edge_interrupt,
+						      handle_edge_irq,
+						      "edge");
 			break;
 
 		default:
-			set_irq_chip_and_handler_name(irq,
-				&ip32_maceisa_level_interrupt, handle_level_irq,
-				"level");
+			irq_set_chip_and_handler_name(irq,
+						      &ip32_maceisa_level_interrupt,
+						      handle_level_irq,
+						      "level");
 			break;
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/mips/sibyte/bcm1480/irq.c linux-libre-2.6.39-gnu/arch/mips/sibyte/bcm1480/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/sibyte/bcm1480/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sibyte/bcm1480/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,31 +44,10 @@
  * for interrupt lines
  */
 
-
-static void end_bcm1480_irq(unsigned int irq);
-static void enable_bcm1480_irq(unsigned int irq);
-static void disable_bcm1480_irq(unsigned int irq);
-static void ack_bcm1480_irq(unsigned int irq);
-#ifdef CONFIG_SMP
-static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask);
-#endif
-
 #ifdef CONFIG_PCI
 extern unsigned long ht_eoi_space;
 #endif
 
-static struct irq_chip bcm1480_irq_type = {
-	.name = "BCM1480-IMR",
-	.ack = ack_bcm1480_irq,
-	.mask = disable_bcm1480_irq,
-	.mask_ack = ack_bcm1480_irq,
-	.unmask = enable_bcm1480_irq,
-	.end = end_bcm1480_irq,
-#ifdef CONFIG_SMP
-	.set_affinity = bcm1480_set_affinity
-#endif
-};
-
 /* Store the CPU id (not the logical number) */
 int bcm1480_irq_owner[BCM1480_NR_IRQS];
 
@@ -109,12 +88,13 @@
 }
 
 #ifdef CONFIG_SMP
-static int bcm1480_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int bcm1480_set_affinity(struct irq_data *d, const struct cpumask *mask,
+				bool force)
 {
+	unsigned int irq_dirty, irq = d->irq;
 	int i = 0, old_cpu, cpu, int_on, k;
 	u64 cur_ints;
 	unsigned long flags;
-	unsigned int irq_dirty;
 
 	i = cpumask_first(mask);
 
@@ -156,21 +136,25 @@
 
 /*****************************************************************************/
 
-static void disable_bcm1480_irq(unsigned int irq)
+static void disable_bcm1480_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
 }
 
-static void enable_bcm1480_irq(unsigned int irq)
+static void enable_bcm1480_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
+
 	bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
 }
 
 
-static void ack_bcm1480_irq(unsigned int irq)
+static void ack_bcm1480_irq(struct irq_data *d)
 {
+	unsigned int irq_dirty, irq = d->irq;
 	u64 pending;
-	unsigned int irq_dirty;
 	int k;
 
 	/*
@@ -217,21 +201,23 @@
 	bcm1480_mask_irq(bcm1480_irq_owner[irq], irq);
 }
 
-
-static void end_bcm1480_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		bcm1480_unmask_irq(bcm1480_irq_owner[irq], irq);
-	}
-}
-
+static struct irq_chip bcm1480_irq_type = {
+	.name = "BCM1480-IMR",
+	.irq_mask_ack = ack_bcm1480_irq,
+	.irq_mask = disable_bcm1480_irq,
+	.irq_unmask = enable_bcm1480_irq,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = bcm1480_set_affinity
+#endif
+};
 
 void __init init_bcm1480_irqs(void)
 {
 	int i;
 
 	for (i = 0; i < BCM1480_NR_IRQS; i++) {
-		set_irq_chip_and_handler(i, &bcm1480_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &bcm1480_irq_type,
+					 handle_level_irq);
 		bcm1480_irq_owner[i] = 0;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/sibyte/sb1250/irq.c linux-libre-2.6.39-gnu/arch/mips/sibyte/sb1250/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/sibyte/sb1250/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sibyte/sb1250/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,31 +43,10 @@
  * for interrupt lines
  */
 
-
-static void end_sb1250_irq(unsigned int irq);
-static void enable_sb1250_irq(unsigned int irq);
-static void disable_sb1250_irq(unsigned int irq);
-static void ack_sb1250_irq(unsigned int irq);
-#ifdef CONFIG_SMP
-static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask);
-#endif
-
 #ifdef CONFIG_SIBYTE_HAS_LDT
 extern unsigned long ldt_eoi_space;
 #endif
 
-static struct irq_chip sb1250_irq_type = {
-	.name = "SB1250-IMR",
-	.ack = ack_sb1250_irq,
-	.mask = disable_sb1250_irq,
-	.mask_ack = ack_sb1250_irq,
-	.unmask = enable_sb1250_irq,
-	.end = end_sb1250_irq,
-#ifdef CONFIG_SMP
-	.set_affinity = sb1250_set_affinity
-#endif
-};
-
 /* Store the CPU id (not the logical number) */
 int sb1250_irq_owner[SB1250_NR_IRQS];
 
@@ -102,9 +81,11 @@
 }
 
 #ifdef CONFIG_SMP
-static int sb1250_set_affinity(unsigned int irq, const struct cpumask *mask)
+static int sb1250_set_affinity(struct irq_data *d, const struct cpumask *mask,
+			       bool force)
 {
 	int i = 0, old_cpu, cpu, int_on;
+	unsigned int irq = d->irq;
 	u64 cur_ints;
 	unsigned long flags;
 
@@ -142,21 +123,17 @@
 }
 #endif
 
-/*****************************************************************************/
-
-static void disable_sb1250_irq(unsigned int irq)
+static void enable_sb1250_irq(struct irq_data *d)
 {
-	sb1250_mask_irq(sb1250_irq_owner[irq], irq);
-}
+	unsigned int irq = d->irq;
 
-static void enable_sb1250_irq(unsigned int irq)
-{
 	sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
 }
 
 
-static void ack_sb1250_irq(unsigned int irq)
+static void ack_sb1250_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 #ifdef CONFIG_SIBYTE_HAS_LDT
 	u64 pending;
 
@@ -199,21 +176,22 @@
 	sb1250_mask_irq(sb1250_irq_owner[irq], irq);
 }
 
-
-static void end_sb1250_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		sb1250_unmask_irq(sb1250_irq_owner[irq], irq);
-	}
-}
-
+static struct irq_chip sb1250_irq_type = {
+	.name = "SB1250-IMR",
+	.irq_mask_ack = ack_sb1250_irq,
+	.irq_unmask = enable_sb1250_irq,
+#ifdef CONFIG_SMP
+	.irq_set_affinity = sb1250_set_affinity
+#endif
+};
 
 void __init init_sb1250_irqs(void)
 {
 	int i;
 
 	for (i = 0; i < SB1250_NR_IRQS; i++) {
-		set_irq_chip_and_handler(i, &sb1250_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &sb1250_irq_type,
+					 handle_level_irq);
 		sb1250_irq_owner[i] = 0;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/sni/a20r.c linux-libre-2.6.39-gnu/arch/mips/sni/a20r.c
--- linux-libre-2.6.38-gnu/arch/mips/sni/a20r.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sni/a20r.c	2011-05-19 00:06:34.000000000 -0400
@@ -168,33 +168,22 @@
 	return status;
 }
 
-static inline void unmask_a20r_irq(unsigned int irq)
+static inline void unmask_a20r_irq(struct irq_data *d)
 {
-	set_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
+	set_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 	irq_enable_hazard();
 }
 
-static inline void mask_a20r_irq(unsigned int irq)
+static inline void mask_a20r_irq(struct irq_data *d)
 {
-	clear_c0_status(0x100 << (irq - SNI_A20R_IRQ_BASE));
+	clear_c0_status(0x100 << (d->irq - SNI_A20R_IRQ_BASE));
 	irq_disable_hazard();
 }
 
-static void end_a20r_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED | IRQ_INPROGRESS))) {
-		a20r_ack_hwint();
-		unmask_a20r_irq(irq);
-	}
-}
-
 static struct irq_chip a20r_irq_type = {
 	.name		= "A20R",
-	.ack		= mask_a20r_irq,
-	.mask		= mask_a20r_irq,
-	.mask_ack	= mask_a20r_irq,
-	.unmask		= unmask_a20r_irq,
-	.end		= end_a20r_irq,
+	.irq_mask	= mask_a20r_irq,
+	.irq_unmask	= unmask_a20r_irq,
 };
 
 /*
@@ -220,7 +209,7 @@
 	int i;
 
 	for (i = SNI_A20R_IRQ_BASE + 2 ; i < SNI_A20R_IRQ_BASE + 8; i++)
-		set_irq_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &a20r_irq_type, handle_level_irq);
 	sni_hwint = a20r_hwint;
 	change_c0_status(ST0_IM, IE_IRQ0);
 	setup_irq(SNI_A20R_IRQ_BASE + 3, &sni_isa_irq);
diff -druN linux-libre-2.6.38-gnu/arch/mips/sni/pcimt.c linux-libre-2.6.39-gnu/arch/mips/sni/pcimt.c
--- linux-libre-2.6.38-gnu/arch/mips/sni/pcimt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sni/pcimt.c	2011-05-19 00:06:34.000000000 -0400
@@ -194,33 +194,24 @@
 	.io_map_base    = SNI_PORT_BASE
 };
 
-static void enable_pcimt_irq(unsigned int irq)
+static void enable_pcimt_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq - PCIMT_IRQ_INT2);
+	unsigned int mask = 1 << (d->irq - PCIMT_IRQ_INT2);
 
 	*(volatile u8 *) PCIMT_IRQSEL |= mask;
 }
 
-void disable_pcimt_irq(unsigned int irq)
+void disable_pcimt_irq(struct irq_data *d)
 {
-	unsigned int mask = ~(1 << (irq - PCIMT_IRQ_INT2));
+	unsigned int mask = ~(1 << (d->irq - PCIMT_IRQ_INT2));
 
 	*(volatile u8 *) PCIMT_IRQSEL &= mask;
 }
 
-static void end_pcimt_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_pcimt_irq(irq);
-}
-
 static struct irq_chip pcimt_irq_type = {
 	.name = "PCIMT",
-	.ack = disable_pcimt_irq,
-	.mask = disable_pcimt_irq,
-	.mask_ack = disable_pcimt_irq,
-	.unmask = enable_pcimt_irq,
-	.end = end_pcimt_irq,
+	.irq_mask = disable_pcimt_irq,
+	.irq_unmask = enable_pcimt_irq,
 };
 
 /*
@@ -305,7 +296,7 @@
 	mips_cpu_irq_init();
 	/* Actually we've got more interrupts to handle ...  */
 	for (i = PCIMT_IRQ_INT2; i <= PCIMT_IRQ_SCSI; i++)
-		set_irq_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &pcimt_irq_type, handle_level_irq);
 	sni_hwint = sni_pcimt_hwint;
 	change_c0_status(ST0_IM, IE_IRQ1|IE_IRQ3);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/sni/pcit.c linux-libre-2.6.39-gnu/arch/mips/sni/pcit.c
--- linux-libre-2.6.38-gnu/arch/mips/sni/pcit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sni/pcit.c	2011-05-19 00:06:34.000000000 -0400
@@ -156,33 +156,24 @@
 	.io_map_base    = SNI_PORT_BASE
 };
 
-static void enable_pcit_irq(unsigned int irq)
+static void enable_pcit_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
+	u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24);
 
 	*(volatile u32 *)SNI_PCIT_INT_REG |= mask;
 }
 
-void disable_pcit_irq(unsigned int irq)
+void disable_pcit_irq(struct irq_data *d)
 {
-	u32 mask = 1 << (irq - SNI_PCIT_INT_START + 24);
+	u32 mask = 1 << (d->irq - SNI_PCIT_INT_START + 24);
 
 	*(volatile u32 *)SNI_PCIT_INT_REG &= ~mask;
 }
 
-void end_pcit_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_pcit_irq(irq);
-}
-
 static struct irq_chip pcit_irq_type = {
 	.name = "PCIT",
-	.ack = disable_pcit_irq,
-	.mask = disable_pcit_irq,
-	.mask_ack = disable_pcit_irq,
-	.unmask = enable_pcit_irq,
-	.end = end_pcit_irq,
+	.irq_mask = disable_pcit_irq,
+	.irq_unmask = enable_pcit_irq,
 };
 
 static void pcit_hwint1(void)
@@ -247,7 +238,7 @@
 
 	mips_cpu_irq_init();
 	for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
-		set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
 	*(volatile u32 *)SNI_PCIT_INT_REG = 0;
 	sni_hwint = sni_pcit_hwint;
 	change_c0_status(ST0_IM, IE_IRQ1);
@@ -260,7 +251,7 @@
 
 	mips_cpu_irq_init();
 	for (i = SNI_PCIT_INT_START; i <= SNI_PCIT_INT_END; i++)
-		set_irq_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &pcit_irq_type, handle_level_irq);
 	*(volatile u32 *)SNI_PCIT_INT_REG = 0x40000000;
 	sni_hwint = sni_pcit_hwint_cplus;
 	change_c0_status(ST0_IM, IE_IRQ0);
diff -druN linux-libre-2.6.38-gnu/arch/mips/sni/rm200.c linux-libre-2.6.39-gnu/arch/mips/sni/rm200.c
--- linux-libre-2.6.38-gnu/arch/mips/sni/rm200.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sni/rm200.c	2011-05-19 00:06:34.000000000 -0400
@@ -155,12 +155,11 @@
 #define cached_master_mask	(rm200_cached_irq_mask)
 #define cached_slave_mask	(rm200_cached_irq_mask >> 8)
 
-static void sni_rm200_disable_8259A_irq(unsigned int irq)
+static void sni_rm200_disable_8259A_irq(struct irq_data *d)
 {
-	unsigned int mask;
+	unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE;
 	unsigned long flags;
 
-	irq -= RM200_I8259A_IRQ_BASE;
 	mask = 1 << irq;
 	raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
 	rm200_cached_irq_mask |= mask;
@@ -171,12 +170,11 @@
 	raw_spin_unlock_irqrestore(&sni_rm200_i8259A_lock, flags);
 }
 
-static void sni_rm200_enable_8259A_irq(unsigned int irq)
+static void sni_rm200_enable_8259A_irq(struct irq_data *d)
 {
-	unsigned int mask;
+	unsigned int mask, irq = d->irq - RM200_I8259A_IRQ_BASE;
 	unsigned long flags;
 
-	irq -= RM200_I8259A_IRQ_BASE;
 	mask = ~(1 << irq);
 	raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
 	rm200_cached_irq_mask &= mask;
@@ -210,12 +208,11 @@
  * first, _then_ send the EOI, and the order of EOI
  * to the two 8259s is important!
  */
-void sni_rm200_mask_and_ack_8259A(unsigned int irq)
+void sni_rm200_mask_and_ack_8259A(struct irq_data *d)
 {
-	unsigned int irqmask;
+	unsigned int irqmask, irq = d->irq - RM200_I8259A_IRQ_BASE;
 	unsigned long flags;
 
-	irq -= RM200_I8259A_IRQ_BASE;
 	irqmask = 1 << irq;
 	raw_spin_lock_irqsave(&sni_rm200_i8259A_lock, flags);
 	/*
@@ -285,9 +282,9 @@
 
 static struct irq_chip sni_rm200_i8259A_chip = {
 	.name		= "RM200-XT-PIC",
-	.mask		= sni_rm200_disable_8259A_irq,
-	.unmask		= sni_rm200_enable_8259A_irq,
-	.mask_ack	= sni_rm200_mask_and_ack_8259A,
+	.irq_mask	= sni_rm200_disable_8259A_irq,
+	.irq_unmask	= sni_rm200_enable_8259A_irq,
+	.irq_mask_ack	= sni_rm200_mask_and_ack_8259A,
 };
 
 /*
@@ -416,7 +413,7 @@
 	sni_rm200_init_8259A();
 
 	for (i = RM200_I8259A_IRQ_BASE; i < RM200_I8259A_IRQ_BASE + 16; i++)
-		set_irq_chip_and_handler(i, &sni_rm200_i8259A_chip,
+		irq_set_chip_and_handler(i, &sni_rm200_i8259A_chip,
 					 handle_level_irq);
 
 	setup_irq(RM200_I8259A_IRQ_BASE + PIC_CASCADE_IR, &sni_rm200_irq2);
@@ -429,33 +426,24 @@
 #define SNI_RM200_INT_START  24
 #define SNI_RM200_INT_END    28
 
-static void enable_rm200_irq(unsigned int irq)
+static void enable_rm200_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
+	unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START);
 
 	*(volatile u8 *)SNI_RM200_INT_ENA_REG &= ~mask;
 }
 
-void disable_rm200_irq(unsigned int irq)
+void disable_rm200_irq(struct irq_data *d)
 {
-	unsigned int mask = 1 << (irq - SNI_RM200_INT_START);
+	unsigned int mask = 1 << (d->irq - SNI_RM200_INT_START);
 
 	*(volatile u8 *)SNI_RM200_INT_ENA_REG |= mask;
 }
 
-void end_rm200_irq(unsigned int irq)
-{
-	if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		enable_rm200_irq(irq);
-}
-
 static struct irq_chip rm200_irq_type = {
 	.name = "RM200",
-	.ack = disable_rm200_irq,
-	.mask = disable_rm200_irq,
-	.mask_ack = disable_rm200_irq,
-	.unmask = enable_rm200_irq,
-	.end = end_rm200_irq,
+	.irq_mask = disable_rm200_irq,
+	.irq_unmask = enable_rm200_irq,
 };
 
 static void sni_rm200_hwint(void)
@@ -489,7 +477,7 @@
 	mips_cpu_irq_init();
 	/* Actually we've got more interrupts to handle ...  */
 	for (i = SNI_RM200_INT_START; i <= SNI_RM200_INT_END; i++)
-		set_irq_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
+		irq_set_chip_and_handler(i, &rm200_irq_type, handle_level_irq);
 	sni_hwint = sni_rm200_hwint;
 	change_c0_status(ST0_IM, IE_IRQ0);
 	setup_irq(SNI_RM200_INT_START + 0, &sni_rm200_i8259A_irq);
diff -druN linux-libre-2.6.38-gnu/arch/mips/sni/time.c linux-libre-2.6.39-gnu/arch/mips/sni/time.c
--- linux-libre-2.6.38-gnu/arch/mips/sni/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/sni/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 static __init unsigned long dosample(void)
 {
 	u32 ct0, ct1;
-	volatile u8 msb, lsb;
+	volatile u8 msb;
 
 	/* Start the counter. */
 	outb_p(0x34, 0x43);
@@ -108,7 +108,7 @@
 	/* Latch and spin until top byte of counter0 is zero */
 	do {
 		outb(0x00, 0x43);
-		lsb = inb(0x40);
+		(void) inb(0x40);
 		msb = inb(0x40);
 		ct1 = read_c0_count();
 	} while (msb);
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/generic/irq_tx4927.c linux-libre-2.6.39-gnu/arch/mips/txx9/generic/irq_tx4927.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/generic/irq_tx4927.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/generic/irq_tx4927.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 
 	mips_cpu_irq_init();
 	txx9_irq_init(TX4927_IRC_REG & 0xfffffffffULL);
-	set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT,
+	irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4927_IRC_INT,
 				handle_simple_irq);
 	/* raise priority for errors, timers, SIO */
 	txx9_irq_set_pri(TX4927_IR_ECCERR, 7);
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/generic/irq_tx4938.c linux-libre-2.6.39-gnu/arch/mips/txx9/generic/irq_tx4938.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/generic/irq_tx4938.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/generic/irq_tx4938.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 
 	mips_cpu_irq_init();
 	txx9_irq_init(TX4938_IRC_REG & 0xfffffffffULL);
-	set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT,
+	irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4938_IRC_INT,
 				handle_simple_irq);
 	/* raise priority for errors, timers, SIO */
 	txx9_irq_set_pri(TX4938_IR_ECCERR, 7);
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/generic/irq_tx4939.c linux-libre-2.6.39-gnu/arch/mips/txx9/generic/irq_tx4939.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/generic/irq_tx4939.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/generic/irq_tx4939.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,9 +50,9 @@
 	unsigned char mode;
 } tx4939irq[TX4939_NUM_IR] __read_mostly;
 
-static void tx4939_irq_unmask(unsigned int irq)
+static void tx4939_irq_unmask(struct irq_data *d)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 	u32 __iomem *lvlp;
 	int ofs;
 	if (irq_nr < 32) {
@@ -68,9 +68,9 @@
 		     lvlp);
 }
 
-static inline void tx4939_irq_mask(unsigned int irq)
+static inline void tx4939_irq_mask(struct irq_data *d)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 	u32 __iomem *lvlp;
 	int ofs;
 	if (irq_nr < 32) {
@@ -87,11 +87,11 @@
 	mmiowb();
 }
 
-static void tx4939_irq_mask_ack(unsigned int irq)
+static void tx4939_irq_mask_ack(struct irq_data *d)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 
-	tx4939_irq_mask(irq);
+	tx4939_irq_mask(d);
 	if (TXx9_IRCR_EDGE(tx4939irq[irq_nr].mode)) {
 		irq_nr--;
 		/* clear edge detection */
@@ -101,9 +101,9 @@
 	}
 }
 
-static int tx4939_irq_set_type(unsigned int irq, unsigned int flow_type)
+static int tx4939_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	unsigned int irq_nr = irq - TXX9_IRQ_BASE;
+	unsigned int irq_nr = d->irq - TXX9_IRQ_BASE;
 	u32 cr;
 	u32 __iomem *crp;
 	int ofs;
@@ -145,11 +145,11 @@
 
 static struct irq_chip tx4939_irq_chip = {
 	.name		= "TX4939",
-	.ack		= tx4939_irq_mask_ack,
-	.mask		= tx4939_irq_mask,
-	.mask_ack	= tx4939_irq_mask_ack,
-	.unmask		= tx4939_irq_unmask,
-	.set_type	= tx4939_irq_set_type,
+	.irq_ack	= tx4939_irq_mask_ack,
+	.irq_mask	= tx4939_irq_mask,
+	.irq_mask_ack	= tx4939_irq_mask_ack,
+	.irq_unmask	= tx4939_irq_unmask,
+	.irq_set_type	= tx4939_irq_set_type,
 };
 
 static int tx4939_irq_set_pri(int irc_irq, int new_pri)
@@ -176,8 +176,8 @@
 	for (i = 1; i < TX4939_NUM_IR; i++) {
 		tx4939irq[i].level = 4; /* middle level */
 		tx4939irq[i].mode = TXx9_IRCR_LOW;
-		set_irq_chip_and_handler(TXX9_IRQ_BASE + i,
-					 &tx4939_irq_chip, handle_level_irq);
+		irq_set_chip_and_handler(TXX9_IRQ_BASE + i, &tx4939_irq_chip,
+					 handle_level_irq);
 	}
 
 	/* mask all IRC interrupts */
@@ -193,7 +193,7 @@
 	__raw_writel(TXx9_IRCER_ICE, &tx4939_ircptr->den.r);
 	__raw_writel(irc_elevel, &tx4939_ircptr->msk.r);
 
-	set_irq_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT,
+	irq_set_chained_handler(MIPS_CPU_IRQ_BASE + TX4939_IRC_INT,
 				handle_simple_irq);
 
 	/* raise priority for errors, timers, sio */
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/jmr3927/irq.c linux-libre-2.6.39-gnu/arch/mips/txx9/jmr3927/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/jmr3927/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/jmr3927/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,20 +47,20 @@
  * CP0_STATUS is a thread's resource (saved/restored on context switch).
  * So disable_irq/enable_irq MUST handle IOC/IRC registers.
  */
-static void mask_irq_ioc(unsigned int irq)
+static void mask_irq_ioc(struct irq_data *d)
 {
 	/* 0: mask */
-	unsigned int irq_nr = irq - JMR3927_IRQ_IOC;
+	unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC;
 	unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
 	unsigned int bit = 1 << irq_nr;
 	jmr3927_ioc_reg_out(imask & ~bit, JMR3927_IOC_INTM_ADDR);
 	/* flush write buffer */
 	(void)jmr3927_ioc_reg_in(JMR3927_IOC_REV_ADDR);
 }
-static void unmask_irq_ioc(unsigned int irq)
+static void unmask_irq_ioc(struct irq_data *d)
 {
 	/* 0: mask */
-	unsigned int irq_nr = irq - JMR3927_IRQ_IOC;
+	unsigned int irq_nr = d->irq - JMR3927_IRQ_IOC;
 	unsigned char imask = jmr3927_ioc_reg_in(JMR3927_IOC_INTM_ADDR);
 	unsigned int bit = 1 << irq_nr;
 	jmr3927_ioc_reg_out(imask | bit, JMR3927_IOC_INTM_ADDR);
@@ -95,10 +95,8 @@
 
 static struct irq_chip jmr3927_irq_ioc = {
 	.name = "jmr3927_ioc",
-	.ack = mask_irq_ioc,
-	.mask = mask_irq_ioc,
-	.mask_ack = mask_irq_ioc,
-	.unmask = unmask_irq_ioc,
+	.irq_mask = mask_irq_ioc,
+	.irq_unmask = unmask_irq_ioc,
 };
 
 void __init jmr3927_irq_setup(void)
@@ -122,8 +120,9 @@
 
 	tx3927_irq_init();
 	for (i = JMR3927_IRQ_IOC; i < JMR3927_IRQ_IOC + JMR3927_NR_IRQ_IOC; i++)
-		set_irq_chip_and_handler(i, &jmr3927_irq_ioc, handle_level_irq);
+		irq_set_chip_and_handler(i, &jmr3927_irq_ioc,
+					 handle_level_irq);
 
 	/* setup IOC interrupt 1 (PCI, MODEM) */
-	set_irq_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
+	irq_set_chained_handler(JMR3927_IRQ_IOCINT, handle_simple_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/rbtx4927/irq.c linux-libre-2.6.39-gnu/arch/mips/txx9/rbtx4927/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/rbtx4927/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/rbtx4927/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,18 +117,6 @@
 #include <asm/txx9/generic.h>
 #include <asm/txx9/rbtx4927.h>
 
-static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq);
-static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq);
-
-#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
-static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
-	.name = TOSHIBA_RBTX4927_IOC_NAME,
-	.ack = toshiba_rbtx4927_irq_ioc_disable,
-	.mask = toshiba_rbtx4927_irq_ioc_disable,
-	.mask_ack = toshiba_rbtx4927_irq_ioc_disable,
-	.unmask = toshiba_rbtx4927_irq_ioc_enable,
-};
-
 static int toshiba_rbtx4927_irq_nested(int sw_irq)
 {
 	u8 level3;
@@ -139,41 +127,47 @@
 	return RBTX4927_IRQ_IOC + __fls8(level3);
 }
 
-static void __init toshiba_rbtx4927_irq_ioc_init(void)
-{
-	int i;
-
-	/* mask all IOC interrupts */
-	writeb(0, rbtx4927_imask_addr);
-	/* clear SoftInt interrupts */
-	writeb(0, rbtx4927_softint_addr);
-
-	for (i = RBTX4927_IRQ_IOC;
-	     i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++)
-		set_irq_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
-					 handle_level_irq);
-	set_irq_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq);
-}
-
-static void toshiba_rbtx4927_irq_ioc_enable(unsigned int irq)
+static void toshiba_rbtx4927_irq_ioc_enable(struct irq_data *d)
 {
 	unsigned char v;
 
 	v = readb(rbtx4927_imask_addr);
-	v |= (1 << (irq - RBTX4927_IRQ_IOC));
+	v |= (1 << (d->irq - RBTX4927_IRQ_IOC));
 	writeb(v, rbtx4927_imask_addr);
 }
 
-static void toshiba_rbtx4927_irq_ioc_disable(unsigned int irq)
+static void toshiba_rbtx4927_irq_ioc_disable(struct irq_data *d)
 {
 	unsigned char v;
 
 	v = readb(rbtx4927_imask_addr);
-	v &= ~(1 << (irq - RBTX4927_IRQ_IOC));
+	v &= ~(1 << (d->irq - RBTX4927_IRQ_IOC));
 	writeb(v, rbtx4927_imask_addr);
 	mmiowb();
 }
 
+#define TOSHIBA_RBTX4927_IOC_NAME "RBTX4927-IOC"
+static struct irq_chip toshiba_rbtx4927_irq_ioc_type = {
+	.name = TOSHIBA_RBTX4927_IOC_NAME,
+	.irq_mask = toshiba_rbtx4927_irq_ioc_disable,
+	.irq_unmask = toshiba_rbtx4927_irq_ioc_enable,
+};
+
+static void __init toshiba_rbtx4927_irq_ioc_init(void)
+{
+	int i;
+
+	/* mask all IOC interrupts */
+	writeb(0, rbtx4927_imask_addr);
+	/* clear SoftInt interrupts */
+	writeb(0, rbtx4927_softint_addr);
+
+	for (i = RBTX4927_IRQ_IOC;
+	     i < RBTX4927_IRQ_IOC + RBTX4927_NR_IRQ_IOC; i++)
+		irq_set_chip_and_handler(i, &toshiba_rbtx4927_irq_ioc_type,
+					 handle_level_irq);
+	irq_set_chained_handler(RBTX4927_IRQ_IOCINT, handle_simple_irq);
+}
 
 static int rbtx4927_irq_dispatch(int pending)
 {
@@ -200,5 +194,5 @@
 	tx4927_irq_init();
 	toshiba_rbtx4927_irq_ioc_init();
 	/* Onboard 10M Ether: High Active */
-	set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH);
+	irq_set_irq_type(RBTX4927_RTL_8019_IRQ, IRQF_TRIGGER_HIGH);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/rbtx4938/irq.c linux-libre-2.6.39-gnu/arch/mips/txx9/rbtx4938/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/rbtx4938/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/rbtx4938/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,18 +69,6 @@
 #include <asm/txx9/generic.h>
 #include <asm/txx9/rbtx4938.h>
 
-static void toshiba_rbtx4938_irq_ioc_enable(unsigned int irq);
-static void toshiba_rbtx4938_irq_ioc_disable(unsigned int irq);
-
-#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
-static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
-	.name = TOSHIBA_RBTX4938_IOC_NAME,
-	.ack = toshiba_rbtx4938_irq_ioc_disable,
-	.mask = toshiba_rbtx4938_irq_ioc_disable,
-	.mask_ack = toshiba_rbtx4938_irq_ioc_disable,
-	.unmask = toshiba_rbtx4938_irq_ioc_enable,
-};
-
 static int toshiba_rbtx4938_irq_nested(int sw_irq)
 {
 	u8 level3;
@@ -92,41 +80,33 @@
 	return RBTX4938_IRQ_IOC + __fls8(level3);
 }
 
-static void __init
-toshiba_rbtx4938_irq_ioc_init(void)
-{
-	int i;
-
-	for (i = RBTX4938_IRQ_IOC;
-	     i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++)
-		set_irq_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
-					 handle_level_irq);
-
-	set_irq_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq);
-}
-
-static void
-toshiba_rbtx4938_irq_ioc_enable(unsigned int irq)
+static void toshiba_rbtx4938_irq_ioc_enable(struct irq_data *d)
 {
 	unsigned char v;
 
 	v = readb(rbtx4938_imask_addr);
-	v |= (1 << (irq - RBTX4938_IRQ_IOC));
+	v |= (1 << (d->irq - RBTX4938_IRQ_IOC));
 	writeb(v, rbtx4938_imask_addr);
 	mmiowb();
 }
 
-static void
-toshiba_rbtx4938_irq_ioc_disable(unsigned int irq)
+static void toshiba_rbtx4938_irq_ioc_disable(struct irq_data *d)
 {
 	unsigned char v;
 
 	v = readb(rbtx4938_imask_addr);
-	v &= ~(1 << (irq - RBTX4938_IRQ_IOC));
+	v &= ~(1 << (d->irq - RBTX4938_IRQ_IOC));
 	writeb(v, rbtx4938_imask_addr);
 	mmiowb();
 }
 
+#define TOSHIBA_RBTX4938_IOC_NAME "RBTX4938-IOC"
+static struct irq_chip toshiba_rbtx4938_irq_ioc_type = {
+	.name = TOSHIBA_RBTX4938_IOC_NAME,
+	.irq_mask = toshiba_rbtx4938_irq_ioc_disable,
+	.irq_unmask = toshiba_rbtx4938_irq_ioc_enable,
+};
+
 static int rbtx4938_irq_dispatch(int pending)
 {
 	int irq;
@@ -146,6 +126,18 @@
 	return irq;
 }
 
+static void __init toshiba_rbtx4938_irq_ioc_init(void)
+{
+	int i;
+
+	for (i = RBTX4938_IRQ_IOC;
+	     i < RBTX4938_IRQ_IOC + RBTX4938_NR_IRQ_IOC; i++)
+		irq_set_chip_and_handler(i, &toshiba_rbtx4938_irq_ioc_type,
+					 handle_level_irq);
+
+	irq_set_chained_handler(RBTX4938_IRQ_IOCINT, handle_simple_irq);
+}
+
 void __init rbtx4938_irq_setup(void)
 {
 	txx9_irq_dispatch = rbtx4938_irq_dispatch;
@@ -161,5 +153,5 @@
 	tx4938_irq_init();
 	toshiba_rbtx4938_irq_ioc_init();
 	/* Onboard 10M Ether: High Active */
-	set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
+	irq_set_irq_type(RBTX4938_IRQ_ETHER, IRQF_TRIGGER_HIGH);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/txx9/rbtx4939/irq.c linux-libre-2.6.39-gnu/arch/mips/txx9/rbtx4939/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/txx9/rbtx4939/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/txx9/rbtx4939/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,16 +19,16 @@
  * RBTX4939 IOC controller definition
  */
 
-static void rbtx4939_ioc_irq_unmask(unsigned int irq)
+static void rbtx4939_ioc_irq_unmask(struct irq_data *d)
 {
-	int ioc_nr = irq - RBTX4939_IRQ_IOC;
+	int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
 
 	writeb(readb(rbtx4939_ien_addr) | (1 << ioc_nr), rbtx4939_ien_addr);
 }
 
-static void rbtx4939_ioc_irq_mask(unsigned int irq)
+static void rbtx4939_ioc_irq_mask(struct irq_data *d)
 {
-	int ioc_nr = irq - RBTX4939_IRQ_IOC;
+	int ioc_nr = d->irq - RBTX4939_IRQ_IOC;
 
 	writeb(readb(rbtx4939_ien_addr) & ~(1 << ioc_nr), rbtx4939_ien_addr);
 	mmiowb();
@@ -36,10 +36,8 @@
 
 static struct irq_chip rbtx4939_ioc_irq_chip = {
 	.name		= "IOC",
-	.ack		= rbtx4939_ioc_irq_mask,
-	.mask		= rbtx4939_ioc_irq_mask,
-	.mask_ack	= rbtx4939_ioc_irq_mask,
-	.unmask		= rbtx4939_ioc_irq_unmask,
+	.irq_mask	= rbtx4939_ioc_irq_mask,
+	.irq_unmask	= rbtx4939_ioc_irq_unmask,
 };
 
 
@@ -90,8 +88,8 @@
 	tx4939_irq_init();
 	for (i = RBTX4939_IRQ_IOC;
 	     i < RBTX4939_IRQ_IOC + RBTX4939_NR_IRQ_IOC; i++)
-		set_irq_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
+		irq_set_chip_and_handler(i, &rbtx4939_ioc_irq_chip,
 					 handle_level_irq);
 
-	set_irq_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
+	irq_set_chained_handler(RBTX4939_IRQ_IOCINT, handle_simple_irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mips/vr41xx/common/icu.c linux-libre-2.6.39-gnu/arch/mips/vr41xx/common/icu.c
--- linux-libre-2.6.38-gnu/arch/mips/vr41xx/common/icu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/vr41xx/common/icu.c	2011-05-19 00:06:34.000000000 -0400
@@ -154,7 +154,7 @@
 
 void vr41xx_enable_piuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + PIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(PIU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -169,7 +169,7 @@
 
 void vr41xx_disable_piuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + PIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(PIU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -184,7 +184,7 @@
 
 void vr41xx_enable_aiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + AIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(AIU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -199,7 +199,7 @@
 
 void vr41xx_disable_aiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + AIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(AIU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -214,7 +214,7 @@
 
 void vr41xx_enable_kiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + KIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(KIU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -229,7 +229,7 @@
 
 void vr41xx_disable_kiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + KIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(KIU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4111 ||
@@ -244,7 +244,7 @@
 
 void vr41xx_enable_macint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
+	struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
@@ -256,7 +256,7 @@
 
 void vr41xx_disable_macint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + ETHERNET_IRQ;
+	struct irq_desc *desc = irq_to_desc(ETHERNET_IRQ);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
@@ -268,7 +268,7 @@
 
 void vr41xx_enable_dsiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + DSIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(DSIU_IRQ);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
@@ -280,7 +280,7 @@
 
 void vr41xx_disable_dsiuint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + DSIU_IRQ;
+	struct irq_desc *desc = irq_to_desc(DSIU_IRQ);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
@@ -292,7 +292,7 @@
 
 void vr41xx_enable_firint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + FIR_IRQ;
+	struct irq_desc *desc = irq_to_desc(FIR_IRQ);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
@@ -304,7 +304,7 @@
 
 void vr41xx_disable_firint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + FIR_IRQ;
+	struct irq_desc *desc = irq_to_desc(FIR_IRQ);
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&desc->lock, flags);
@@ -316,7 +316,7 @@
 
 void vr41xx_enable_pciint(void)
 {
-	struct irq_desc *desc = irq_desc + PCI_IRQ;
+	struct irq_desc *desc = irq_to_desc(PCI_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -332,7 +332,7 @@
 
 void vr41xx_disable_pciint(void)
 {
-	struct irq_desc *desc = irq_desc + PCI_IRQ;
+	struct irq_desc *desc = irq_to_desc(PCI_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -348,7 +348,7 @@
 
 void vr41xx_enable_scuint(void)
 {
-	struct irq_desc *desc = irq_desc + SCU_IRQ;
+	struct irq_desc *desc = irq_to_desc(SCU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -364,7 +364,7 @@
 
 void vr41xx_disable_scuint(void)
 {
-	struct irq_desc *desc = irq_desc + SCU_IRQ;
+	struct irq_desc *desc = irq_to_desc(SCU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -380,7 +380,7 @@
 
 void vr41xx_enable_csiint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + CSI_IRQ;
+	struct irq_desc *desc = irq_to_desc(CSI_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -396,7 +396,7 @@
 
 void vr41xx_disable_csiint(uint16_t mask)
 {
-	struct irq_desc *desc = irq_desc + CSI_IRQ;
+	struct irq_desc *desc = irq_to_desc(CSI_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -412,7 +412,7 @@
 
 void vr41xx_enable_bcuint(void)
 {
-	struct irq_desc *desc = irq_desc + BCU_IRQ;
+	struct irq_desc *desc = irq_to_desc(BCU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -428,7 +428,7 @@
 
 void vr41xx_disable_bcuint(void)
 {
-	struct irq_desc *desc = irq_desc + BCU_IRQ;
+	struct irq_desc *desc = irq_to_desc(BCU_IRQ);
 	unsigned long flags;
 
 	if (current_cpu_type() == CPU_VR4122 ||
@@ -442,45 +442,41 @@
 
 EXPORT_SYMBOL(vr41xx_disable_bcuint);
 
-static void disable_sysint1_irq(unsigned int irq)
+static void disable_sysint1_irq(struct irq_data *d)
 {
-	icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
+	icu1_clear(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
 }
 
-static void enable_sysint1_irq(unsigned int irq)
+static void enable_sysint1_irq(struct irq_data *d)
 {
-	icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(irq));
+	icu1_set(MSYSINT1REG, 1 << SYSINT1_IRQ_TO_PIN(d->irq));
 }
 
 static struct irq_chip sysint1_irq_type = {
 	.name		= "SYSINT1",
-	.ack		= disable_sysint1_irq,
-	.mask		= disable_sysint1_irq,
-	.mask_ack	= disable_sysint1_irq,
-	.unmask		= enable_sysint1_irq,
+	.irq_mask	= disable_sysint1_irq,
+	.irq_unmask	= enable_sysint1_irq,
 };
 
-static void disable_sysint2_irq(unsigned int irq)
+static void disable_sysint2_irq(struct irq_data *d)
 {
-	icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
+	icu2_clear(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq));
 }
 
-static void enable_sysint2_irq(unsigned int irq)
+static void enable_sysint2_irq(struct irq_data *d)
 {
-	icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(irq));
+	icu2_set(MSYSINT2REG, 1 << SYSINT2_IRQ_TO_PIN(d->irq));
 }
 
 static struct irq_chip sysint2_irq_type = {
 	.name		= "SYSINT2",
-	.ack		= disable_sysint2_irq,
-	.mask		= disable_sysint2_irq,
-	.mask_ack	= disable_sysint2_irq,
-	.unmask		= enable_sysint2_irq,
+	.irq_mask	= disable_sysint2_irq,
+	.irq_unmask	= enable_sysint2_irq,
 };
 
 static inline int set_sysint1_assign(unsigned int irq, unsigned char assign)
 {
-	struct irq_desc *desc = irq_desc + irq;
+	struct irq_desc *desc = irq_to_desc(irq);
 	uint16_t intassign0, intassign1;
 	unsigned int pin;
 
@@ -540,7 +536,7 @@
 
 static inline int set_sysint2_assign(unsigned int irq, unsigned char assign)
 {
-	struct irq_desc *desc = irq_desc + irq;
+	struct irq_desc *desc = irq_to_desc(irq);
 	uint16_t intassign2, intassign3;
 	unsigned int pin;
 
@@ -714,11 +710,11 @@
 	icu2_write(MGIUINTHREG, 0xffff);
 
 	for (i = SYSINT1_IRQ_BASE; i <= SYSINT1_IRQ_LAST; i++)
-		set_irq_chip_and_handler(i, &sysint1_irq_type,
+		irq_set_chip_and_handler(i, &sysint1_irq_type,
 					 handle_level_irq);
 
 	for (i = SYSINT2_IRQ_BASE; i <= SYSINT2_IRQ_LAST; i++)
-		set_irq_chip_and_handler(i, &sysint2_irq_type,
+		irq_set_chip_and_handler(i, &sysint2_irq_type,
 					 handle_level_irq);
 
 	cascade_irq(INT0_IRQ, icu_get_irq);
diff -druN linux-libre-2.6.38-gnu/arch/mips/vr41xx/common/irq.c linux-libre-2.6.39-gnu/arch/mips/vr41xx/common/irq.c
--- linux-libre-2.6.38-gnu/arch/mips/vr41xx/common/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mips/vr41xx/common/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,6 @@
 static void irq_dispatch(unsigned int irq)
 {
 	irq_cascade_t *cascade;
-	struct irq_desc *desc;
 
 	if (irq >= NR_IRQS) {
 		atomic_inc(&irq_err_count);
@@ -71,14 +70,16 @@
 
 	cascade = irq_cascade + irq;
 	if (cascade->get_irq != NULL) {
-		unsigned int source_irq = irq;
+		struct irq_desc *desc = irq_to_desc(irq);
+		struct irq_data *idata = irq_desc_get_irq_data(desc);
+		struct irq_chip *chip = irq_desc_get_chip(desc);
 		int ret;
-		desc = irq_desc + source_irq;
-		if (desc->chip->mask_ack)
-			desc->chip->mask_ack(source_irq);
+
+		if (chip->irq_mask_ack)
+			chip->irq_mask_ack(idata);
 		else {
-			desc->chip->mask(source_irq);
-			desc->chip->ack(source_irq);
+			chip->irq_mask(idata);
+			chip->irq_ack(idata);
 		}
 		ret = cascade->get_irq(irq);
 		irq = ret;
@@ -86,8 +87,8 @@
 			atomic_inc(&irq_err_count);
 		else
 			irq_dispatch(irq);
-		if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-			desc->chip->unmask(source_irq);
+		if (!irqd_irq_disabled(idata) && chip->irq_unmask)
+			chip->irq_unmask(idata);
 	} else
 		do_IRQ(irq);
 }
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -233,8 +233,7 @@
 #define ext2_clear_bit_atomic(lock, nr, addr) \
 	test_and_clear_bit((nr), (addr))
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
-#include <asm-generic/bitops/minix-le.h>
+#include <asm-generic/bitops/le.h>
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/cpu-regs.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/cpu-regs.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/cpu-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/cpu-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -49,7 +49,7 @@
 #define EPSW_IM_6		0x00000600	/* interrupt mode 6 */
 #define EPSW_IM_7		0x00000700	/* interrupt mode 7 */
 #define EPSW_IE			0x00000800	/* interrupt enable */
-#define EPSW_S			0x00003000	/* software auxilliary bits */
+#define EPSW_S			0x00003000	/* software auxiliary bits */
 #define EPSW_T			0x00008000	/* trace enable */
 #define EPSW_nSL		0x00010000	/* not supervisor level */
 #define EPSW_NMID		0x00020000	/* nonmaskable interrupt disable */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/debugger.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/debugger.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/debugger.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/debugger.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,43 @@
+/* Kernel debugger for MN10300
+ *
+ * Copyright (C) 2011 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_DEBUGGER_H
+#define _ASM_DEBUGGER_H
+
+#if defined(CONFIG_KERNEL_DEBUGGER)
+
+extern int debugger_intercept(enum exception_code, int, int, struct pt_regs *);
+extern int at_debugger_breakpoint(struct pt_regs *);
+
+#ifndef CONFIG_MN10300_DEBUGGER_CACHE_NO_FLUSH
+extern void debugger_local_cache_flushinv(void);
+extern void debugger_local_cache_flushinv_one(u8 *);
+#else
+static inline void debugger_local_cache_flushinv(void) {}
+static inline void debugger_local_cache_flushinv_one(u8 *addr) {}
+#endif
+
+#else /* CONFIG_KERNEL_DEBUGGER */
+
+static inline int debugger_intercept(enum exception_code excep,
+				     int signo, int si_code,
+				     struct pt_regs *regs)
+{
+	return 0;
+}
+
+static inline int at_debugger_breakpoint(struct pt_regs *regs)
+{
+	return 0;
+}
+
+#endif /* CONFIG_KERNEL_DEBUGGER */
+#endif /* _ASM_DEBUGGER_H */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/div64.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/div64.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/div64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/div64.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,19 @@
 extern void ____unhandled_size_in_do_div___(void);
 
 /*
+ * Beginning with gcc 4.6, the MDR register is represented explicitly.  We
+ * must, therefore, at least explicitly clobber the register when we make
+ * changes to it.  The following assembly fragments *could* be rearranged in
+ * order to leave the moves to/from the MDR register to the compiler, but the
+ * gains would be minimal at best.
+ */
+#if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)
+# define CLOBBER_MDR_CC		"mdr", "cc"
+#else
+# define CLOBBER_MDR_CC		"cc"
+#endif
+
+/*
  * divide n by base, leaving the result in n and returning the remainder
  * - we can do this quite efficiently on the MN10300 by cascading the divides
  *   through the MDR register
@@ -29,7 +42,7 @@
 		    "mov	mdr,%1	\n"				\
 		    : "+r"(n), "=d"(__rem)				\
 		    : "r"(base), "1"(__rem)				\
-		    : "cc"						\
+		    : CLOBBER_MDR_CC					\
 		    );							\
 	} else if (sizeof(n) <= 8) {					\
 		union {							\
@@ -48,7 +61,7 @@
 		    : "=d"(__rem), "=r"(__quot.w[1]), "=r"(__quot.w[0])	\
 		    : "r"(base), "0"(__rem), "1"(__quot.w[1]),		\
 		      "2"(__quot.w[0])					\
-		    : "cc"						\
+		    : CLOBBER_MDR_CC					\
 		    );							\
 		n = __quot.l;						\
 	} else {							\
@@ -72,7 +85,7 @@
 					 * MDR = MDR:val%div */
 	    : "=r"(result)
 	    : "0"(val), "ir"(mult), "r"(div)
-	    : "cc"
+	    : CLOBBER_MDR_CC
 	    );
 
 	return result;
@@ -93,7 +106,7 @@
 					 * MDR = MDR:val%div */
 	    : "=r"(result)
 	    : "0"(val), "ir"(mult), "r"(div)
-	    : "cc"
+	    : CLOBBER_MDR_CC
 	    );
 
 	return result;
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/fpu.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/fpu.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/fpu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/fpu.h	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,6 @@
 
 extern asmlinkage void fpu_kill_state(struct task_struct *);
 extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code);
-extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code);
 extern asmlinkage void fpu_init_state(void);
 extern asmlinkage void fpu_save(struct fpu_state_struct *);
 extern int fpu_setup_sigcontext(struct fpucontext *buf);
@@ -113,7 +112,6 @@
 
 extern asmlinkage
 void unexpected_fpu_exception(struct pt_regs *, enum exception_code);
-#define fpu_invalid_op unexpected_fpu_exception
 #define fpu_exception unexpected_fpu_exception
 
 struct task_struct;
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/intctl-regs.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/intctl-regs.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/intctl-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/intctl-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -60,11 +60,6 @@
 
 #ifndef __ASSEMBLY__
 extern void set_intr_level(int irq, u16 level);
-extern void mn10300_intc_set_level(unsigned int irq, unsigned int level);
-extern void mn10300_intc_clear(unsigned int irq);
-extern void mn10300_intc_set(unsigned int irq);
-extern void mn10300_intc_enable(unsigned int irq);
-extern void mn10300_intc_disable(unsigned int irq);
 extern void mn10300_set_lateack_irq_type(int irq);
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/irqflags.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/irqflags.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/irqflags.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
 /*
  * interrupt control
  * - "disabled": run in IM1/2
- *   - level 0 - GDB stub
+ *   - level 0 - kernel debugger
  *   - level 1 - virtual serial DMA (if present)
  *   - level 5 - normal interrupt priority
  *   - level 6 - timer interrupt
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/kgdb.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/kgdb.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/kgdb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/kgdb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,81 @@
+/* Kernel debugger for MN10300
+ *
+ * Copyright (C) 2010 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_KGDB_H
+#define _ASM_KGDB_H
+
+/*
+ * BUFMAX defines the maximum number of characters in inbound/outbound
+ * buffers at least NUMREGBYTES*2 are needed for register packets
+ * Longer buffer is needed to list all threads
+ */
+#define BUFMAX			1024
+
+/*
+ * Note that this register image is in a different order than the register
+ * image that Linux produces at interrupt time.
+ */
+enum regnames {
+	GDB_FR_D0		= 0,
+	GDB_FR_D1		= 1,
+	GDB_FR_D2		= 2,
+	GDB_FR_D3		= 3,
+	GDB_FR_A0		= 4,
+	GDB_FR_A1		= 5,
+	GDB_FR_A2		= 6,
+	GDB_FR_A3		= 7,
+
+	GDB_FR_SP		= 8,
+	GDB_FR_PC		= 9,
+	GDB_FR_MDR		= 10,
+	GDB_FR_EPSW		= 11,
+	GDB_FR_LIR		= 12,
+	GDB_FR_LAR		= 13,
+	GDB_FR_MDRQ		= 14,
+
+	GDB_FR_E0		= 15,
+	GDB_FR_E1		= 16,
+	GDB_FR_E2		= 17,
+	GDB_FR_E3		= 18,
+	GDB_FR_E4		= 19,
+	GDB_FR_E5		= 20,
+	GDB_FR_E6		= 21,
+	GDB_FR_E7		= 22,
+
+	GDB_FR_SSP		= 23,
+	GDB_FR_MSP		= 24,
+	GDB_FR_USP		= 25,
+	GDB_FR_MCRH		= 26,
+	GDB_FR_MCRL		= 27,
+	GDB_FR_MCVF		= 28,
+
+	GDB_FR_FPCR		= 29,
+	GDB_FR_DUMMY0		= 30,
+	GDB_FR_DUMMY1		= 31,
+
+	GDB_FR_FS0		= 32,
+
+	GDB_FR_SIZE		= 64,
+};
+
+#define GDB_ORIG_D0		41
+#define NUMREGBYTES		(GDB_FR_SIZE*4)
+
+static inline void arch_kgdb_breakpoint(void)
+{
+	asm(".globl __arch_kgdb_breakpoint; __arch_kgdb_breakpoint: break");
+}
+extern u8 __arch_kgdb_breakpoint;
+
+#define BREAK_INSTR_SIZE	1
+#define CACHE_FLUSH_IS_SAFE	1
+
+#endif /* _ASM_KGDB_H */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/smp.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/smp.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/smp.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 #define LOCAL_TIMER_IPI		193
 #define FLUSH_CACHE_IPI		194
 #define CALL_FUNCTION_NMI_IPI	195
-#define GDB_NMI_IPI		196
+#define DEBUGGER_NMI_IPI	196
 
 #define SMP_BOOT_IRQ		195
 
@@ -43,6 +43,7 @@
 #define LOCAL_TIMER_GxICR_LV	GxICR_LEVEL_4
 #define FLUSH_CACHE_GxICR_LV	GxICR_LEVEL_0
 #define SMP_BOOT_GxICR_LV	GxICR_LEVEL_0
+#define DEBUGGER_GxICR_LV	CONFIG_DEBUGGER_IRQ_LEVEL
 
 #define TIME_OUT_COUNT_BOOT_IPI	100
 #define DELAY_TIME_BOOT_IPI	75000
@@ -61,8 +62,9 @@
  * An alternate way of dealing with this could be to use the EPSW.S bits to
  * cache this information for systems with up to four CPUs.
  */
+#define arch_smp_processor_id()	(CPUID)
 #if 0
-#define raw_smp_processor_id()	(CPUID)
+#define raw_smp_processor_id()	(arch_smp_processor_id())
 #else
 #define raw_smp_processor_id()	(current_thread_info()->cpu)
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -124,12 +124,18 @@
 
 /* thread information allocation */
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk) kzalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kzalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #else
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node)			\
+		kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #endif
 
+#ifndef CONFIG_KGDB
 #define free_thread_info(ti)	kfree((ti))
+#else
+extern void free_thread_info(struct thread_info *);
+#endif
 #define get_thread_info(ti)	get_task_struct((ti)->task)
 #define put_thread_info(ti)	put_task_struct((ti)->task)
 
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/include/asm/types.h linux-libre-2.6.39-gnu/arch/mn10300/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/mn10300/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,13 +26,6 @@
 
 #define BITS_PER_LONG 32
 
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-typedef u32 dma_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
 #endif /* __KERNEL__ */
 
 #endif /* _ASM_TYPES_H */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/Kconfig linux-libre-2.6.39-gnu/arch/mn10300/Kconfig
--- linux-libre-2.6.38-gnu/arch/mn10300/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,10 @@
 config MN10300
 	def_bool y
 	select HAVE_OPROFILE
-	select GENERIC_HARDIRQS
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
+	select HAVE_ARCH_TRACEHOOK
+	select HAVE_ARCH_KGDB
 
 config AM33_2
 	def_bool n
@@ -53,21 +56,6 @@
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-config GENERIC_CLOCKEVENTS_BUILD
-	def_bool y
-	depends on GENERIC_CLOCKEVENTS
-
-config GENERIC_CLOCKEVENTS_BROADCAST
-	bool
-
-config CEVT_MN10300
-       def_bool y
-       depends on GENERIC_CLOCKEVENTS
-
-config CSRC_MN10300
-       def_bool y
-       depends on GENERIC_TIME
-
 config GENERIC_BUG
 	def_bool y
 
@@ -415,9 +403,9 @@
 comment "____Non-maskable interrupt levels____"
 comment "The following must be set to a higher priority than local_irq_disable() and on-chip serial"
 
-config GDBSTUB_IRQ_LEVEL
-	int "GDBSTUB interrupt priority"
-	depends on GDBSTUB
+config DEBUGGER_IRQ_LEVEL
+	int "DEBUGGER interrupt priority"
+	depends on KERNEL_DEBUGGER
 	range 0 1 if LINUX_CLI_LEVEL = 2
 	range 0 2 if LINUX_CLI_LEVEL = 3
 	range 0 3 if LINUX_CLI_LEVEL = 4
@@ -451,7 +439,7 @@
 	  EPSW.IM from 7.  Any interrupt is permitted for which the level is
 	  lower than EPSW.IM.
 
-	  Certain interrupts, such as GDBSTUB and virtual MN10300 on-chip
+	  Certain interrupts, such as DEBUGGER and virtual MN10300 on-chip
 	  serial DMA interrupts are allowed to interrupt normal disabled
 	  sections.
 
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/Kconfig.debug linux-libre-2.6.39-gnu/arch/mn10300/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/mn10300/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 
 config GDBSTUB
 	bool "Remote GDB kernel debugging"
-	depends on DEBUG_KERNEL
+	depends on DEBUG_KERNEL && DEPRECATED
 	select DEBUG_INFO
 	select FRAME_POINTER
 	help
@@ -46,6 +46,9 @@
 	  RAM to avoid excessive linking time. This is only useful for kernel
 	  hackers. If unsure, say N.
 
+	  This is deprecated in favour of KGDB and will be removed in a later
+	  version.
+
 config GDBSTUB_IMMEDIATE
 	bool "Break into GDB stub immediately"
 	depends on GDBSTUB
@@ -54,6 +57,14 @@
 	  possible, leaving the program counter at the beginning of
 	  start_kernel() in init/main.c.
 
+config GDBSTUB_ALLOW_SINGLE_STEP
+	bool "Allow software single-stepping in GDB stub"
+	depends on GDBSTUB && !SMP && !PREEMPT
+	help
+	  Allow GDB stub to perform software single-stepping through the
+	  kernel.  This doesn't work very well on SMP or preemptible kernels as
+	  it uses temporary breakpoints to emulate single-stepping.
+
 config GDB_CONSOLE
 	bool "Console output to GDB"
 	depends on GDBSTUB
@@ -142,3 +153,7 @@
 	default y
 
 endmenu
+
+config KERNEL_DEBUGGER
+	def_bool y
+	depends on GDBSTUB || KGDB
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/cevt-mn10300.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/cevt-mn10300.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/cevt-mn10300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/cevt-mn10300.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,9 +89,10 @@
 	cd->name		= "Timestamp";
 	cd->features		= CLOCK_EVT_FEAT_ONESHOT;
 
-	/* Calculate the min / max delta */
-	clockevent_set_clock(cd, MN10300_JCCLK);
+	/* Calculate shift/mult. We want to spawn at least 1 second */
+	clockevents_calc_mult_shift(cd, MN10300_JCCLK, 1);
 
+	/* Calculate the min / max delta */
 	cd->max_delta_ns	= clockevent_delta2ns(TMJCBR_MAX, cd);
 	cd->min_delta_ns	= clockevent_delta2ns(100, cd);
 
@@ -110,9 +111,9 @@
 #if defined(CONFIG_SMP) && !defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
 	/* setup timer irq affinity so it only runs on this cpu */
 	{
-		struct irq_desc *desc;
-		desc = irq_to_desc(cd->irq);
-		cpumask_copy(desc->affinity, cpumask_of(cpu));
+		struct irq_data *data;
+		data = irq_get_irq_data(cd->irq);
+		cpumask_copy(data->affinity, cpumask_of(cpu));
 		iact->flags |= IRQF_NOBALANCING;
 	}
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/csrc-mn10300.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/csrc-mn10300.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/csrc-mn10300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/csrc-mn10300.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,6 @@
 int __init init_clocksource(void)
 {
 	startup_timestamp_counter();
-	clocksource_set_clock(&clocksource_mn10300, MN10300_TSCCLK);
-	clocksource_register(&clocksource_mn10300);
+	clocksource_register_hz(&clocksource_mn10300, MN10300_TSCCLK);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/entry.S linux-libre-2.6.39-gnu/arch/mn10300/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -266,7 +266,11 @@
 
 ###############################################################################
 #
-# Miscellaneous exception entry points
+# NMI exception entry points
+#
+# This is used by ordinary interrupt channels that have the GxICR_NMI bit set
+# in addition to the main NMI and Watchdog channels.  SMP NMI IPIs use this
+# facility.
 #
 ###############################################################################
 ENTRY(nmi_handler)
@@ -281,7 +285,7 @@
 	and	NMIAGR_GN,d0
 	lsr	0x2,d0
 	cmp	CALL_FUNCTION_NMI_IPI,d0
-	bne	5f			# if not call function, jump
+	bne	nmi_not_smp_callfunc	# if not call function, jump
 
 	# function call nmi ipi
 	add	4,sp			# no need to store TBR
@@ -295,59 +299,38 @@
 	call	smp_nmi_call_function_interrupt[],0
 	RESTORE_ALL
 
-5:
-#ifdef CONFIG_GDBSTUB
-	cmp	GDB_NMI_IPI,d0
-	bne	3f			# if not gdb nmi ipi, jump
+nmi_not_smp_callfunc:
+#ifdef CONFIG_KERNEL_DEBUGGER
+	cmp	DEBUGGER_NMI_IPI,d0
+	bne	nmi_not_debugger	# if not kernel debugger NMI IPI, jump
 
-	# gdb nmi ipi
+	# kernel debugger NMI IPI
 	add	4,sp			# no need to store TBR
 	mov	GxICR_DETECT,d0		# clear NMI
-	movbu	d0,(GxICR(GDB_NMI_IPI))
-	movhu	(GxICR(GDB_NMI_IPI)),d0
+	movbu	d0,(GxICR(DEBUGGER_NMI_IPI))
+	movhu	(GxICR(DEBUGGER_NMI_IPI)),d0
 	and	~EPSW_NMID,epsw		# enable NMI
-#ifdef CONFIG_MN10300_CACHE_ENABLED
-	mov	(gdbstub_nmi_opr_type),d0
-	cmp	GDBSTUB_NMI_CACHE_PURGE,d0
-	bne	4f			# if not gdb cache purge, jump
 
-	# gdb cache purge nmi ipi
-	add	-20,sp
-	mov	d1,(4,sp)
-	mov	a0,(8,sp)
-	mov	a1,(12,sp)
-	mov	mdr,d0
-	mov	d0,(16,sp)
-	call	gdbstub_local_purge_cache[],0
-	mov	0x1,d0
-	mov	(CPUID),d1
-	asl	d1,d0
-	mov	gdbstub_nmi_cpumask,a0
-	bclr	d0,(a0)
-	mov	(4,sp),d1
-	mov	(8,sp),a0
-	mov	(12,sp),a1
-	mov	(16,sp),d0
-	mov	d0,mdr
-	add	20,sp
-	mov	(sp),d0
-	add	4,sp
-	rti
-4:
-#endif /* CONFIG_MN10300_CACHE_ENABLED */
-	# gdb wait nmi ipi
 	mov     (sp),d0
 	SAVE_ALL
-	call    gdbstub_nmi_wait[],0
+	mov	fp,d0			# arg 0: stacked register file
+	mov	a2,d1			# arg 1: exception number
+	call    debugger_nmi_interrupt[],0
 	RESTORE_ALL
-3:
-#endif /* CONFIG_GDBSTUB */
+
+nmi_not_debugger:
+#endif /* CONFIG_KERNEL_DEBUGGER */
 	mov     (sp),d0                 # restore TBR to d0
 	add     4,sp
 #endif /* CONFIG_SMP */
 
 	bra	__common_exception_nonmi
 
+###############################################################################
+#
+# General exception entry point
+#
+###############################################################################
 ENTRY(__common_exception)
 	add	-4,sp
 	mov	d0,(sp)
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/fpu.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/fpu.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/fpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/fpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -70,24 +70,6 @@
 }
 
 /*
- * handle an FPU invalid_op exception
- * - Derived from DO_EINFO() macro in arch/mn10300/kernel/traps.c
- */
-asmlinkage void fpu_invalid_op(struct pt_regs *regs, enum exception_code code)
-{
-	siginfo_t info;
-
-	if (!user_mode(regs))
-		die_if_no_fixup("FPU invalid opcode", regs, code);
-
-	info.si_signo = SIGILL;
-	info.si_errno = 0;
-	info.si_code = ILL_COPROC;
-	info.si_addr = (void *) regs->pc;
-	force_sig_info(info.si_signo, &info, current);
-}
-
-/*
  * save the FPU state to a signal context
  */
 int fpu_setup_sigcontext(struct fpucontext *fpucontext)
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/gdb-cache.S linux-libre-2.6.39-gnu/arch/mn10300/kernel/gdb-cache.S
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/gdb-cache.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/gdb-cache.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,105 +0,0 @@
-###############################################################################
-#
-# MN10300 Low-level cache purging routines for gdbstub
-#
-# 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.
-#
-###############################################################################
-#include <linux/sys.h>
-#include <linux/linkage.h>
-#include <asm/smp.h>
-#include <asm/cache.h>
-#include <asm/cpu-regs.h>
-#include <asm/exceptions.h>
-#include <asm/frame.inc>
-#include <asm/serial-regs.h>
-
-	.text
-
-###############################################################################
-#
-# GDB stub cache purge
-#
-###############################################################################
-	.type	gdbstub_purge_cache,@function
-ENTRY(gdbstub_purge_cache)
-	#######################################################################
-	# read the addresses tagged in the cache's tag RAM and attempt to flush
-	# those addresses specifically
-	# - we rely on the hardware to filter out invalid tag entry addresses
-	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address
-	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
-	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1  # total number of entries
-
-mn10300_dcache_flush_loop:
-	mov	(a0),d0
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
-	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
-						# cache
-	mov	d0,(a1)				# conditional purge
-
-mn10300_dcache_flush_skip:
-	add	L1_CACHE_BYTES,a0
-	add	L1_CACHE_BYTES,a1
-	add	-1,d1
-	bne	mn10300_dcache_flush_loop
-
-;; 	# unconditionally flush and invalidate the dcache
-;; 	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
-;; 	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,d1	# total number of
-;;							# entries
-;;
-;; gdbstub_purge_cache__dcache_loop:
-;; 	mov	(a1),d0				# unconditional purge
-;;
-;; 	add	L1_CACHE_BYTES,a1
-;; 	add	-1,d1
-;; 	bne	gdbstub_purge_cache__dcache_loop
-
-	#######################################################################
-	# now invalidate the icache
-	mov	CHCTR,a0
-	movhu	(a0),a1
-
-	mov	epsw,d1
-	and	~EPSW_IE,epsw
-	nop
-	nop
-
-	# disable the icache
-	and	~CHCTR_ICEN,d0
-	movhu	d0,(a0)
-
-	# and wait for it to calm down
-	setlb
-	movhu	(a0),d0
-	btst	CHCTR_ICBUSY,d0
-	lne
-
-	# invalidate
-	or	CHCTR_ICINV,d0
-	movhu	d0,(a0)
-
-	# wait for the cache to finish
-	mov	CHCTR,a0
-	setlb
-	movhu	(a0),d0
-	btst	CHCTR_ICBUSY,d0
-	lne
-
-	# and reenable it
-	movhu	a1,(a0)
-	movhu	(a0),d0			# read back to flush
-					# (SIGILLs all over without this)
-
-	mov	d1,epsw
-
-	ret	[],0
-
-	.size	gdbstub_purge_cache,.-gdbstub_purge_cache
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/gdb-io-ttysm.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/gdb-io-ttysm.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/gdb-io-ttysm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/gdb-io-ttysm.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,10 +59,10 @@
 
 	/* we want to get serial receive interrupts */
 	set_intr_level(gdbstub_port->rx_irq,
-		NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
+		NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
 	set_intr_level(gdbstub_port->tx_irq,
-		NUM2GxICR_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL));
-	set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_GDBSTUB_IRQ_LEVEL),
+		NUM2GxICR_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL));
+	set_intr_stub(NUM2EXCEP_IRQ_LEVEL(CONFIG_DEBUGGER_IRQ_LEVEL),
 		gdbstub_io_rx_handler);
 
 	*gdbstub_port->rx_icr |= GxICR_ENABLE;
@@ -88,7 +88,7 @@
 
 	/* permit level 0 IRQs only */
 	arch_local_change_intr_mask_level(
-		NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+		NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/gdb-stub.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/gdb-stub.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/gdb-stub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/gdb-stub.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,7 @@
 #include <asm/system.h>
 #include <asm/gdb-stub.h>
 #include <asm/exceptions.h>
-#include <asm/cacheflush.h>
+#include <asm/debugger.h>
 #include <asm/serial-regs.h>
 #include <asm/busctl-regs.h>
 #include <unit/leds.h>
@@ -405,6 +405,7 @@
 	return (numChars);
 }
 
+#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
 /*
  * We single-step by setting breakpoints. When an exception
  * is handled, we need to restore the instructions hoisted
@@ -729,6 +730,7 @@
 	__gdbstub_restore_bp();
 	return -EFAULT;
 }
+#endif /* CONFIG_GDBSTUB_ALLOW_SINGLE_STEP */
 
 #ifdef CONFIG_GDBSTUB_CONSOLE
 
@@ -1171,7 +1173,7 @@
 
 /*
  * This function does all command processing for interfacing to gdb
- * - returns 1 if the exception should be skipped, 0 otherwise.
+ * - returns 0 if the exception should be skipped, -ERROR otherwise.
  */
 static int gdbstub(struct pt_regs *regs, enum exception_code excep)
 {
@@ -1186,7 +1188,7 @@
 	int loop;
 
 	if (excep == EXCEP_FPU_DISABLED)
-		return 0;
+		return -ENOTSUPP;
 
 	gdbstub_flush_caches = 0;
 
@@ -1195,7 +1197,7 @@
 	asm volatile("mov mdr,%0" : "=d"(mdr));
 	local_save_flags(epsw);
 	arch_local_change_intr_mask_level(
-		NUM2EPSW_IM(CONFIG_GDBSTUB_IRQ_LEVEL + 1));
+		NUM2EPSW_IM(CONFIG_DEBUGGER_IRQ_LEVEL + 1));
 
 	gdbstub_store_fpu();
 
@@ -1208,11 +1210,13 @@
 	/* if we were single stepping, restore the opcodes hoisted for the
 	 * breakpoint[s] */
 	broke = 0;
+#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
 	if ((step_bp[0].addr && step_bp[0].addr == (u8 *) regs->pc) ||
 	    (step_bp[1].addr && step_bp[1].addr == (u8 *) regs->pc))
 		broke = 1;
 
 	__gdbstub_restore_bp();
+#endif
 
 	if (gdbstub_rx_unget) {
 		sigval = SIGINT;
@@ -1548,17 +1552,21 @@
 			 * Step to next instruction
 			 */
 		case 's':
-			/*
-			 * using the T flag doesn't seem to perform single
+			/* Using the T flag doesn't seem to perform single
 			 * stepping (it seems to wind up being caught by the
 			 * JTAG unit), so we have to use breakpoints and
 			 * continue instead.
 			 */
+#ifdef CONFIG_GDBSTUB_ALLOW_SINGLE_STEP
 			if (gdbstub_single_step(regs) < 0)
 				/* ignore any fault error for now */
 				gdbstub_printk("unable to set single-step"
 					       " bp\n");
 			goto done;
+#else
+			gdbstub_strcpy(output_buffer, "E01");
+			break;
+#endif
 
 			/*
 			 * Set baud rate (bBB)
@@ -1657,7 +1665,7 @@
 	 * NB: We flush both caches, just to be sure...
 	 */
 	if (gdbstub_flush_caches)
-		gdbstub_purge_cache();
+		debugger_local_cache_flushinv();
 
 	gdbstub_load_fpu();
 	mn10300_set_gdbleds(0);
@@ -1667,14 +1675,23 @@
 	touch_softlockup_watchdog();
 
 	local_irq_restore(epsw);
-	return 1;
+	return 0;
+}
+
+/*
+ * Determine if we hit a debugger special breakpoint that needs skipping over
+ * automatically.
+ */
+int at_debugger_breakpoint(struct pt_regs *regs)
+{
+	return 0;
 }
 
 /*
  * handle event interception
  */
-asmlinkage int gdbstub_intercept(struct pt_regs *regs,
-				 enum exception_code excep)
+asmlinkage int debugger_intercept(enum exception_code excep,
+				  int signo, int si_code, struct pt_regs *regs)
 {
 	static u8 notfirst = 1;
 	int ret;
@@ -1688,7 +1705,7 @@
 		asm("mov mdr,%0" : "=d"(mdr));
 
 		gdbstub_entry(
-			"--> gdbstub_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
+			"--> debugger_intercept(%p,%04x) [MDR=%lx PC=%lx]\n",
 			regs, excep, mdr, regs->pc);
 
 		gdbstub_entry(
@@ -1722,7 +1739,7 @@
 
 	ret = gdbstub(regs, excep);
 
-	gdbstub_entry("<-- gdbstub_intercept()\n");
+	gdbstub_entry("<-- debugger_intercept()\n");
 	gdbstub_busy = 0;
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/internal.h linux-libre-2.6.39-gnu/arch/mn10300/kernel/internal.h
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,16 +30,13 @@
 #endif
 
 /*
- * time.c
+ * smp.c
  */
-extern irqreturn_t local_timer_interrupt(void);
+#ifdef CONFIG_SMP
+extern void smp_jump_to_debugger(void);
+#endif
 
 /*
  * time.c
  */
-#ifdef CONFIG_CEVT_MN10300
-extern void clockevent_set_clock(struct clock_event_device *, unsigned int);
-#endif
-#ifdef CONFIG_CSRC_MN10300
-extern void clocksource_set_clock(struct clocksource *, unsigned int);
-#endif
+extern irqreturn_t local_timer_interrupt(void);
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/irq.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,8 +37,9 @@
 /*
  * MN10300 interrupt controller operations
  */
-static void mn10300_cpupic_ack(unsigned int irq)
+static void mn10300_cpupic_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 	u16 tmp;
 
@@ -61,13 +62,14 @@
 	arch_local_irq_restore(flags);
 }
 
-static void mn10300_cpupic_mask(unsigned int irq)
+static void mn10300_cpupic_mask(struct irq_data *d)
 {
-	__mask_and_set_icr(irq, GxICR_LEVEL, 0);
+	__mask_and_set_icr(d->irq, GxICR_LEVEL, 0);
 }
 
-static void mn10300_cpupic_mask_ack(unsigned int irq)
+static void mn10300_cpupic_mask_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 #ifdef CONFIG_SMP
 	unsigned long flags;
 	u16 tmp;
@@ -85,7 +87,7 @@
 		tmp2 = GxICR(irq);
 
 		irq_affinity_online[irq] =
-			any_online_cpu(*irq_desc[irq].affinity);
+			any_online_cpu(*d->affinity);
 		CROSS_GxICR(irq, irq_affinity_online[irq]) =
 			(tmp & (GxICR_LEVEL | GxICR_ENABLE)) | GxICR_DETECT;
 		tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
@@ -97,13 +99,14 @@
 #endif /* CONFIG_SMP */
 }
 
-static void mn10300_cpupic_unmask(unsigned int irq)
+static void mn10300_cpupic_unmask(struct irq_data *d)
 {
-	__mask_and_set_icr(irq, GxICR_LEVEL, GxICR_ENABLE);
+	__mask_and_set_icr(d->irq, GxICR_LEVEL, GxICR_ENABLE);
 }
 
-static void mn10300_cpupic_unmask_clear(unsigned int irq)
+static void mn10300_cpupic_unmask_clear(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	/* the MN10300 PIC latches its interrupt request bit, even after the
 	 * device has ceased to assert its interrupt line and the interrupt
 	 * channel has been disabled in the PIC, so for level-triggered
@@ -121,7 +124,7 @@
 	} else {
 		tmp = GxICR(irq);
 
-		irq_affinity_online[irq] = any_online_cpu(*irq_desc[irq].affinity);
+		irq_affinity_online[irq] = any_online_cpu(*d->affinity);
 		CROSS_GxICR(irq, irq_affinity_online[irq]) = (tmp & GxICR_LEVEL) | GxICR_ENABLE | GxICR_DETECT;
 		tmp = CROSS_GxICR(irq, irq_affinity_online[irq]);
 	}
@@ -134,7 +137,8 @@
 
 #ifdef CONFIG_SMP
 static int
-mn10300_cpupic_setaffinity(unsigned int irq, const struct cpumask *mask)
+mn10300_cpupic_setaffinity(struct irq_data *d, const struct cpumask *mask,
+			   bool force)
 {
 	unsigned long flags;
 	int err;
@@ -142,14 +146,14 @@
 	flags = arch_local_cli_save();
 
 	/* check irq no */
-	switch (irq) {
+	switch (d->irq) {
 	case TMJCIRQ:
 	case RESCHEDULE_IPI:
 	case CALL_FUNC_SINGLE_IPI:
 	case LOCAL_TIMER_IPI:
 	case FLUSH_CACHE_IPI:
 	case CALL_FUNCTION_NMI_IPI:
-	case GDB_NMI_IPI:
+	case DEBUGGER_NMI_IPI:
 #ifdef CONFIG_MN10300_TTYSM0
 	case SC0RXIRQ:
 	case SC0TXIRQ:
@@ -181,7 +185,7 @@
 		break;
 
 	default:
-		set_bit(irq, irq_affinity_request);
+		set_bit(d->irq, irq_affinity_request);
 		err = 0;
 		break;
 	}
@@ -202,15 +206,15 @@
  * mask_ack() is provided), and mask_ack() just masks.
  */
 static struct irq_chip mn10300_cpu_pic_level = {
-	.name		= "cpu_l",
-	.disable	= mn10300_cpupic_mask,
-	.enable		= mn10300_cpupic_unmask_clear,
-	.ack		= NULL,
-	.mask		= mn10300_cpupic_mask,
-	.mask_ack	= mn10300_cpupic_mask,
-	.unmask		= mn10300_cpupic_unmask_clear,
+	.name			= "cpu_l",
+	.irq_disable		= mn10300_cpupic_mask,
+	.irq_enable		= mn10300_cpupic_unmask_clear,
+	.irq_ack		= NULL,
+	.irq_mask		= mn10300_cpupic_mask,
+	.irq_mask_ack		= mn10300_cpupic_mask,
+	.irq_unmask		= mn10300_cpupic_unmask_clear,
 #ifdef CONFIG_SMP
-	.set_affinity	= mn10300_cpupic_setaffinity,
+	.irq_set_affinity	= mn10300_cpupic_setaffinity,
 #endif
 };
 
@@ -220,15 +224,15 @@
  * We use the latch clearing function of the PIC as the 'ACK' function.
  */
 static struct irq_chip mn10300_cpu_pic_edge = {
-	.name		= "cpu_e",
-	.disable	= mn10300_cpupic_mask,
-	.enable		= mn10300_cpupic_unmask,
-	.ack		= mn10300_cpupic_ack,
-	.mask		= mn10300_cpupic_mask,
-	.mask_ack	= mn10300_cpupic_mask_ack,
-	.unmask		= mn10300_cpupic_unmask,
+	.name			= "cpu_e",
+	.irq_disable		= mn10300_cpupic_mask,
+	.irq_enable		= mn10300_cpupic_unmask,
+	.irq_ack		= mn10300_cpupic_ack,
+	.irq_mask		= mn10300_cpupic_mask,
+	.irq_mask_ack		= mn10300_cpupic_mask_ack,
+	.irq_unmask		= mn10300_cpupic_unmask,
 #ifdef CONFIG_SMP
-	.set_affinity	= mn10300_cpupic_setaffinity,
+	.irq_set_affinity	= mn10300_cpupic_setaffinity,
 #endif
 };
 
@@ -252,31 +256,6 @@
 	__mask_and_set_icr(irq, GxICR_ENABLE, level);
 }
 
-void mn10300_intc_set_level(unsigned int irq, unsigned int level)
-{
-	set_intr_level(irq, NUM2GxICR_LEVEL(level) & GxICR_LEVEL);
-}
-
-void mn10300_intc_clear(unsigned int irq)
-{
-	__mask_and_set_icr(irq, GxICR_LEVEL | GxICR_ENABLE, GxICR_DETECT);
-}
-
-void mn10300_intc_set(unsigned int irq)
-{
-	__mask_and_set_icr(irq, 0, GxICR_REQUEST | GxICR_DETECT);
-}
-
-void mn10300_intc_enable(unsigned int irq)
-{
-	mn10300_cpupic_unmask(irq);
-}
-
-void mn10300_intc_disable(unsigned int irq)
-{
-	mn10300_cpupic_mask(irq);
-}
-
 /*
  * mark an interrupt to be ACK'd after interrupt handlers have been run rather
  * than before
@@ -284,7 +263,7 @@
  */
 void mn10300_set_lateack_irq_type(int irq)
 {
-	set_irq_chip_and_handler(irq, &mn10300_cpu_pic_level,
+	irq_set_chip_and_handler(irq, &mn10300_cpu_pic_level,
 				 handle_level_irq);
 }
 
@@ -296,12 +275,12 @@
 	int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++)
-		if (irq_desc[irq].chip == &no_irq_chip)
+		if (irq_get_chip(irq) == &no_irq_chip)
 			/* due to the PIC latching interrupt requests, even
 			 * when the IRQ is disabled, IRQ_PENDING is superfluous
 			 * and we can use handle_level_irq() for edge-triggered
 			 * interrupts */
-			set_irq_chip_and_handler(irq, &mn10300_cpu_pic_edge,
+			irq_set_chip_and_handler(irq, &mn10300_cpu_pic_edge,
 						 handle_level_irq);
 
 	unit_init_IRQ();
@@ -356,91 +335,42 @@
 /*
  * Display interrupt management information through /proc/interrupts
  */
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, j, cpu;
-	struct irqaction *action;
-	unsigned long flags;
-
-	switch (i) {
-		/* display column title bar naming CPUs */
-	case 0:
-		seq_printf(p, "           ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%d       ", j);
-		seq_putc(p, '\n');
-		break;
-
-		/* display information rows, one per active CPU */
-	case 1 ... NR_IRQS - 1:
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-
-		action = irq_desc[i].action;
-		if (action) {
-			seq_printf(p, "%3d: ", i);
-			for_each_present_cpu(cpu)
-				seq_printf(p, "%10u ", kstat_irqs_cpu(i, cpu));
-
-			if (i < NR_CPU_IRQS)
-				seq_printf(p, " %14s.%u",
-					   irq_desc[i].chip->name,
-					   (GxICR(i) & GxICR_LEVEL) >>
-					   GxICR_LEVEL_SHIFT);
-			else
-				seq_printf(p, " %14s",
-					   irq_desc[i].chip->name);
-
-			seq_printf(p, "  %s", action->name);
-
-			for (action = action->next;
-			     action;
-			     action = action->next)
-				seq_printf(p, ", %s", action->name);
-
-			seq_putc(p, '\n');
-		}
-
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-		break;
-
-		/* polish off with NMI and error counters */
-	case NR_IRQS:
 #ifdef CONFIG_MN10300_WD_TIMER
-		seq_printf(p, "NMI: ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "%10u ", nmi_count(j));
-		seq_putc(p, '\n');
-#endif
+	int j;
 
-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-		break;
-	}
+	seq_printf(p, "%*s: ", prec, "NMI");
+	for (j = 0; j < NR_CPUS; j++)
+		if (cpu_online(j))
+			seq_printf(p, "%10u ", nmi_count(j));
+	seq_putc(p, '\n');
+#endif
 
+	seq_printf(p, "%*s: ", prec, "ERR");
+	seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
 	return 0;
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
 void migrate_irqs(void)
 {
-	irq_desc_t *desc;
 	int irq;
 	unsigned int self, new;
 	unsigned long flags;
 
 	self = smp_processor_id();
 	for (irq = 0; irq < NR_IRQS; irq++) {
-		desc = irq_desc + irq;
+		struct irq_data *data = irq_get_irq_data(irq);
 
-		if (desc->status == IRQ_PER_CPU)
+		if (irqd_is_per_cpu(data))
 			continue;
 
-		if (cpu_isset(self, irq_desc[irq].affinity) &&
+		if (cpu_isset(self, data->affinity) &&
 		    !cpus_intersects(irq_affinity[irq], cpu_online_map)) {
 			int cpu_id;
 			cpu_id = first_cpu(cpu_online_map);
-			cpu_set(cpu_id, irq_desc[irq].affinity);
+			cpu_set(cpu_id, data->affinity);
 		}
 		/* We need to operate irq_affinity_online atomically. */
 		arch_local_cli_save(flags);
@@ -451,7 +381,7 @@
 			GxICR(irq) = x & GxICR_LEVEL;
 			tmp = GxICR(irq);
 
-			new = any_online_cpu(irq_desc[irq].affinity);
+			new = any_online_cpu(data->affinity);
 			irq_affinity_online[irq] = new;
 
 			CROSS_GxICR(irq, new) =
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/kgdb.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/kgdb.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/kgdb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/kgdb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,502 @@
+/* kgdb support for MN10300
+ *
+ * Copyright (C) 2010 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/slab.h>
+#include <linux/ptrace.h>
+#include <linux/kgdb.h>
+#include <linux/uaccess.h>
+#include <unit/leds.h>
+#include <unit/serial.h>
+#include <asm/debugger.h>
+#include <asm/serial-regs.h>
+#include "internal.h"
+
+/*
+ * Software single-stepping breakpoint save (used by __switch_to())
+ */
+static struct thread_info *kgdb_sstep_thread;
+u8 *kgdb_sstep_bp_addr[2];
+u8 kgdb_sstep_bp[2];
+
+/*
+ * Copy kernel exception frame registers to the GDB register file
+ */
+void pt_regs_to_gdb_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	unsigned long ssp = (unsigned long) (regs + 1);
+
+	gdb_regs[GDB_FR_D0]	= regs->d0;
+	gdb_regs[GDB_FR_D1]	= regs->d1;
+	gdb_regs[GDB_FR_D2]	= regs->d2;
+	gdb_regs[GDB_FR_D3]	= regs->d3;
+	gdb_regs[GDB_FR_A0]	= regs->a0;
+	gdb_regs[GDB_FR_A1]	= regs->a1;
+	gdb_regs[GDB_FR_A2]	= regs->a2;
+	gdb_regs[GDB_FR_A3]	= regs->a3;
+	gdb_regs[GDB_FR_SP]	= (regs->epsw & EPSW_nSL) ? regs->sp : ssp;
+	gdb_regs[GDB_FR_PC]	= regs->pc;
+	gdb_regs[GDB_FR_MDR]	= regs->mdr;
+	gdb_regs[GDB_FR_EPSW]	= regs->epsw;
+	gdb_regs[GDB_FR_LIR]	= regs->lir;
+	gdb_regs[GDB_FR_LAR]	= regs->lar;
+	gdb_regs[GDB_FR_MDRQ]	= regs->mdrq;
+	gdb_regs[GDB_FR_E0]	= regs->e0;
+	gdb_regs[GDB_FR_E1]	= regs->e1;
+	gdb_regs[GDB_FR_E2]	= regs->e2;
+	gdb_regs[GDB_FR_E3]	= regs->e3;
+	gdb_regs[GDB_FR_E4]	= regs->e4;
+	gdb_regs[GDB_FR_E5]	= regs->e5;
+	gdb_regs[GDB_FR_E6]	= regs->e6;
+	gdb_regs[GDB_FR_E7]	= regs->e7;
+	gdb_regs[GDB_FR_SSP]	= ssp;
+	gdb_regs[GDB_FR_MSP]	= 0;
+	gdb_regs[GDB_FR_USP]	= regs->sp;
+	gdb_regs[GDB_FR_MCRH]	= regs->mcrh;
+	gdb_regs[GDB_FR_MCRL]	= regs->mcrl;
+	gdb_regs[GDB_FR_MCVF]	= regs->mcvf;
+	gdb_regs[GDB_FR_DUMMY0]	= 0;
+	gdb_regs[GDB_FR_DUMMY1]	= 0;
+	gdb_regs[GDB_FR_FS0]	= 0;
+}
+
+/*
+ * Extracts kernel SP/PC values understandable by gdb from the values
+ * saved by switch_to().
+ */
+void sleeping_thread_to_gdb_regs(unsigned long *gdb_regs, struct task_struct *p)
+{
+	gdb_regs[GDB_FR_SSP]	= p->thread.sp;
+	gdb_regs[GDB_FR_PC]	= p->thread.pc;
+	gdb_regs[GDB_FR_A3]	= p->thread.a3;
+	gdb_regs[GDB_FR_USP]	= p->thread.usp;
+	gdb_regs[GDB_FR_FPCR]	= p->thread.fpu_state.fpcr;
+}
+
+/*
+ * Fill kernel exception frame registers from the GDB register file
+ */
+void gdb_regs_to_pt_regs(unsigned long *gdb_regs, struct pt_regs *regs)
+{
+	regs->d0	= gdb_regs[GDB_FR_D0];
+	regs->d1	= gdb_regs[GDB_FR_D1];
+	regs->d2	= gdb_regs[GDB_FR_D2];
+	regs->d3	= gdb_regs[GDB_FR_D3];
+	regs->a0	= gdb_regs[GDB_FR_A0];
+	regs->a1	= gdb_regs[GDB_FR_A1];
+	regs->a2	= gdb_regs[GDB_FR_A2];
+	regs->a3	= gdb_regs[GDB_FR_A3];
+	regs->sp	= gdb_regs[GDB_FR_SP];
+	regs->pc	= gdb_regs[GDB_FR_PC];
+	regs->mdr	= gdb_regs[GDB_FR_MDR];
+	regs->epsw	= gdb_regs[GDB_FR_EPSW];
+	regs->lir	= gdb_regs[GDB_FR_LIR];
+	regs->lar	= gdb_regs[GDB_FR_LAR];
+	regs->mdrq	= gdb_regs[GDB_FR_MDRQ];
+	regs->e0	= gdb_regs[GDB_FR_E0];
+	regs->e1	= gdb_regs[GDB_FR_E1];
+	regs->e2	= gdb_regs[GDB_FR_E2];
+	regs->e3	= gdb_regs[GDB_FR_E3];
+	regs->e4	= gdb_regs[GDB_FR_E4];
+	regs->e5	= gdb_regs[GDB_FR_E5];
+	regs->e6	= gdb_regs[GDB_FR_E6];
+	regs->e7	= gdb_regs[GDB_FR_E7];
+	regs->sp	= gdb_regs[GDB_FR_SSP];
+	/* gdb_regs[GDB_FR_MSP]; */
+	// regs->usp	= gdb_regs[GDB_FR_USP];
+	regs->mcrh	= gdb_regs[GDB_FR_MCRH];
+	regs->mcrl	= gdb_regs[GDB_FR_MCRL];
+	regs->mcvf	= gdb_regs[GDB_FR_MCVF];
+	/* gdb_regs[GDB_FR_DUMMY0]; */
+	/* gdb_regs[GDB_FR_DUMMY1]; */
+
+	// regs->fpcr	= gdb_regs[GDB_FR_FPCR];
+	// regs->fs0	= gdb_regs[GDB_FR_FS0];
+}
+
+struct kgdb_arch arch_kgdb_ops = {
+	.gdb_bpt_instr	= { 0xff },
+	.flags		= KGDB_HW_BREAKPOINT,
+};
+
+static const unsigned char mn10300_kgdb_insn_sizes[256] =
+{
+	/* 1  2  3  4  5  6  7  8  9  a  b  c  d  e  f */
+	1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3, 1, 3, 3, 3,	/* 0 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 1 */
+	2, 2, 2, 2, 3, 3, 3, 3, 2, 2, 2, 2, 3, 3, 3, 3, /* 2 */
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 1, 1, 1, /* 3 */
+	1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, 1, 1, 2, 2, /* 4 */
+	1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, 2, /* 5 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6 */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 7 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 8 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* 9 */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* a */
+	2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, 1, 1, 1, 1, 2, /* b */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 2, 2, /* c */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* d */
+	1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* e */
+	0, 2, 2, 2, 2, 2, 2, 4, 0, 3, 0, 4, 0, 6, 7, 1  /* f */
+};
+
+/*
+ * Attempt to emulate single stepping by means of breakpoint instructions.
+ * Although there is a single-step trace flag in EPSW, its use is not
+ * sufficiently documented and is only intended for use with the JTAG debugger.
+ */
+static int kgdb_arch_do_singlestep(struct pt_regs *regs)
+{
+	unsigned long arg;
+	unsigned size;
+	u8 *pc = (u8 *)regs->pc, *sp = (u8 *)(regs + 1), cur;
+	u8 *x = NULL, *y = NULL;
+	int ret;
+
+	ret = probe_kernel_read(&cur, pc, 1);
+	if (ret < 0)
+		return ret;
+
+	size = mn10300_kgdb_insn_sizes[cur];
+	if (size > 0) {
+		x = pc + size;
+		goto set_x;
+	}
+
+	switch (cur) {
+		/* Bxx (d8,PC) */
+	case 0xc0 ... 0xca:
+		ret = probe_kernel_read(&arg, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+		x = pc + 2;
+		if (arg >= 0 && arg <= 2)
+			goto set_x;
+		y = pc + (s8)arg;
+		goto set_x_and_y;
+
+		/* LXX (d8,PC) */
+	case 0xd0 ... 0xda:
+		x = pc + 1;
+		if (regs->pc == regs->lar)
+			goto set_x;
+		y = (u8 *)regs->lar;
+		goto set_x_and_y;
+
+		/* SETLB - loads the next four bytes into the LIR register
+		 * (which mustn't include a breakpoint instruction) */
+	case 0xdb:
+		x = pc + 5;
+		goto set_x;
+
+		/* JMP (d16,PC) or CALL (d16,PC) */
+	case 0xcc:
+	case 0xcd:
+		ret = probe_kernel_read(&arg, pc + 1, 2);
+		if (ret < 0)
+			return ret;
+		x = pc + (s16)arg;
+		goto set_x;
+
+		/* JMP (d32,PC) or CALL (d32,PC) */
+	case 0xdc:
+	case 0xdd:
+		ret = probe_kernel_read(&arg, pc + 1, 4);
+		if (ret < 0)
+			return ret;
+		x = pc + (s32)arg;
+		goto set_x;
+
+		/* RETF */
+	case 0xde:
+		x = (u8 *)regs->mdr;
+		goto set_x;
+
+		/* RET */
+	case 0xdf:
+		ret = probe_kernel_read(&arg, pc + 2, 1);
+		if (ret < 0)
+			return ret;
+		ret = probe_kernel_read(&x, sp + (s8)arg, 4);
+		if (ret < 0)
+			return ret;
+		goto set_x;
+
+	case 0xf0:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+
+		if (cur >= 0xf0 && cur <= 0xf7) {
+			/* JMP (An) / CALLS (An) */
+			switch (cur & 3) {
+			case 0: x = (u8 *)regs->a0; break;
+			case 1: x = (u8 *)regs->a1; break;
+			case 2: x = (u8 *)regs->a2; break;
+			case 3: x = (u8 *)regs->a3; break;
+			}
+			goto set_x;
+		} else if (cur == 0xfc) {
+			/* RETS */
+			ret = probe_kernel_read(&x, sp, 4);
+			if (ret < 0)
+				return ret;
+			goto set_x;
+		} else if (cur == 0xfd) {
+			/* RTI */
+			ret = probe_kernel_read(&x, sp + 4, 4);
+			if (ret < 0)
+				return ret;
+			goto set_x;
+		} else {
+			x = pc + 2;
+			goto set_x;
+		}
+		break;
+
+		/* potential 3-byte conditional branches */
+	case 0xf8:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+		x = pc + 3;
+
+		if (cur >= 0xe8 && cur <= 0xeb) {
+			ret = probe_kernel_read(&arg, pc + 2, 1);
+			if (ret < 0)
+				return ret;
+			if (arg >= 0 && arg <= 3)
+				goto set_x;
+			y = pc + (s8)arg;
+			goto set_x_and_y;
+		}
+		goto set_x;
+
+	case 0xfa:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+
+		if (cur == 0xff) {
+			/* CALLS (d16,PC) */
+			ret = probe_kernel_read(&arg, pc + 2, 2);
+			if (ret < 0)
+				return ret;
+			x = pc + (s16)arg;
+			goto set_x;
+		}
+
+		x = pc + 4;
+		goto set_x;
+
+	case 0xfc:
+		ret = probe_kernel_read(&cur, pc + 1, 1);
+		if (ret < 0)
+			return ret;
+
+		if (cur == 0xff) {
+			/* CALLS (d32,PC) */
+			ret = probe_kernel_read(&arg, pc + 2, 4);
+			if (ret < 0)
+				return ret;
+			x = pc + (s32)arg;
+			goto set_x;
+		}
+
+		x = pc + 6;
+		goto set_x;
+	}
+
+	return 0;
+
+set_x:
+	kgdb_sstep_bp_addr[0] = x;
+	kgdb_sstep_bp_addr[1] = NULL;
+	ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1);
+	if (ret < 0)
+		return ret;
+	kgdb_sstep_thread = current_thread_info();
+	debugger_local_cache_flushinv_one(x);
+	return ret;
+
+set_x_and_y:
+	kgdb_sstep_bp_addr[0] = x;
+	kgdb_sstep_bp_addr[1] = y;
+	ret = probe_kernel_read(&kgdb_sstep_bp[0], x, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_read(&kgdb_sstep_bp[1], y, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_write(x, &arch_kgdb_ops.gdb_bpt_instr, 1);
+	if (ret < 0)
+		return ret;
+	ret = probe_kernel_write(y, &arch_kgdb_ops.gdb_bpt_instr, 1);
+	if (ret < 0) {
+		probe_kernel_write(kgdb_sstep_bp_addr[0],
+				   &kgdb_sstep_bp[0], 1);
+	} else {
+		kgdb_sstep_thread = current_thread_info();
+	}
+	debugger_local_cache_flushinv_one(x);
+	debugger_local_cache_flushinv_one(y);
+	return ret;
+}
+
+/*
+ * Remove emplaced single-step breakpoints, returning true if we hit one of
+ * them.
+ */
+static bool kgdb_arch_undo_singlestep(struct pt_regs *regs)
+{
+	bool hit = false;
+	u8 *x = kgdb_sstep_bp_addr[0], *y = kgdb_sstep_bp_addr[1];
+	u8 opcode;
+
+	if (kgdb_sstep_thread == current_thread_info()) {
+		if (x) {
+			if (x == (u8 *)regs->pc)
+				hit = true;
+			if (probe_kernel_read(&opcode, x,
+					      1) < 0 ||
+			    opcode != 0xff)
+				BUG();
+			probe_kernel_write(x, &kgdb_sstep_bp[0], 1);
+			debugger_local_cache_flushinv_one(x);
+		}
+		if (y) {
+			if (y == (u8 *)regs->pc)
+				hit = true;
+			if (probe_kernel_read(&opcode, y,
+					      1) < 0 ||
+			    opcode != 0xff)
+				BUG();
+			probe_kernel_write(y, &kgdb_sstep_bp[1], 1);
+			debugger_local_cache_flushinv_one(y);
+		}
+	}
+
+	kgdb_sstep_bp_addr[0] = NULL;
+	kgdb_sstep_bp_addr[1] = NULL;
+	kgdb_sstep_thread = NULL;
+	return hit;
+}
+
+/*
+ * Catch a single-step-pending thread being deleted and make sure the global
+ * single-step state is cleared.  At this point the breakpoints should have
+ * been removed by __switch_to().
+ */
+void free_thread_info(struct thread_info *ti)
+{
+	if (kgdb_sstep_thread == ti) {
+		kgdb_sstep_thread = NULL;
+
+		/* However, we may now be running in degraded mode, with most
+		 * of the CPUs disabled until such a time as KGDB is reentered,
+		 * so force immediate reentry */
+		kgdb_breakpoint();
+	}
+	kfree(ti);
+}
+
+/*
+ * Handle unknown packets and [CcsDk] packets
+ * - at this point breakpoints have been installed
+ */
+int kgdb_arch_handle_exception(int vector, int signo, int err_code,
+			       char *remcom_in_buffer, char *remcom_out_buffer,
+			       struct pt_regs *regs)
+{
+	long addr;
+	char *ptr;
+
+	switch (remcom_in_buffer[0]) {
+	case 'c':
+	case 's':
+		/* try to read optional parameter, pc unchanged if no parm */
+		ptr = &remcom_in_buffer[1];
+		if (kgdb_hex2long(&ptr, &addr))
+			regs->pc = addr;
+	case 'D':
+	case 'k':
+		atomic_set(&kgdb_cpu_doing_single_step, -1);
+
+		if (remcom_in_buffer[0] == 's') {
+			kgdb_arch_do_singlestep(regs);
+			kgdb_single_step = 1;
+			atomic_set(&kgdb_cpu_doing_single_step,
+				   raw_smp_processor_id());
+		}
+		return 0;
+	}
+	return -1; /* this means that we do not want to exit from the handler */
+}
+
+/*
+ * Handle event interception
+ * - returns 0 if the exception should be skipped, -ERROR otherwise.
+ */
+int debugger_intercept(enum exception_code excep, int signo, int si_code,
+		       struct pt_regs *regs)
+{
+	int ret;
+
+	if (kgdb_arch_undo_singlestep(regs)) {
+		excep = EXCEP_TRAP;
+		signo = SIGTRAP;
+		si_code = TRAP_TRACE;
+	}
+
+	ret = kgdb_handle_exception(excep, signo, si_code, regs);
+
+	debugger_local_cache_flushinv();
+
+	return ret;
+}
+
+/*
+ * Determine if we've hit a debugger special breakpoint
+ */
+int at_debugger_breakpoint(struct pt_regs *regs)
+{
+	return regs->pc == (unsigned long)&__arch_kgdb_breakpoint;
+}
+
+/*
+ * Initialise kgdb
+ */
+int kgdb_arch_init(void)
+{
+	return 0;
+}
+
+/*
+ * Do something, perhaps, but don't know what.
+ */
+void kgdb_arch_exit(void)
+{
+}
+
+#ifdef CONFIG_SMP
+void debugger_nmi_interrupt(struct pt_regs *regs, enum exception_code code)
+{
+	kgdb_nmicallback(arch_smp_processor_id(), regs);
+	debugger_local_cache_flushinv();
+}
+
+void kgdb_roundup_cpus(unsigned long flags)
+{
+	smp_jump_to_debugger();
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/Makefile linux-libre-2.6.39-gnu/arch/mn10300/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,8 @@
 
 obj-y   := process.o signal.o entry.o traps.o irq.o \
 	   ptrace.o setup.o time.o sys_mn10300.o io.o kthread.o \
-	   switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y)
+	   switch_to.o mn10300_ksyms.o kernel_execve.o $(fpu-obj-y) \
+	   csrc-mn10300.o cevt-mn10300.o
 
 obj-$(CONFIG_SMP) += smp.o smp-low.o
 
@@ -20,13 +21,8 @@
 obj-$(CONFIG_GDBSTUB_ON_TTYSx) += gdb-io-serial.o gdb-io-serial-low.o
 obj-$(CONFIG_GDBSTUB_ON_TTYSMx) += gdb-io-ttysm.o gdb-io-ttysm-low.o
 
-ifeq ($(CONFIG_MN10300_CACHE_ENABLED),y)
-obj-$(CONFIG_GDBSTUB) += gdb-cache.o
-endif
-
 obj-$(CONFIG_MN10300_RTC) += rtc.o
 obj-$(CONFIG_PROFILE) += profile.o profile-low.o
 obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KPROBES) += kprobes.o
-obj-$(CONFIG_CSRC_MN10300) += csrc-mn10300.o
-obj-$(CONFIG_CEVT_MN10300) += cevt-mn10300.o
+obj-$(CONFIG_KGDB) += kgdb.o
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/mn10300-serial.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/mn10300-serial.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/mn10300-serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/mn10300-serial.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,6 +119,10 @@
 static void mn10300_serial_config_port(struct uart_port *, int);
 static int mn10300_serial_verify_port(struct uart_port *,
 					struct serial_struct *);
+#ifdef CONFIG_CONSOLE_POLL
+static void mn10300_serial_poll_put_char(struct uart_port *, unsigned char);
+static int mn10300_serial_poll_get_char(struct uart_port *);
+#endif
 
 static const struct uart_ops mn10300_serial_ops = {
 	.tx_empty	= mn10300_serial_tx_empty,
@@ -138,6 +142,10 @@
 	.request_port	= mn10300_serial_request_port,
 	.config_port	= mn10300_serial_config_port,
 	.verify_port	= mn10300_serial_verify_port,
+#ifdef CONFIG_CONSOLE_POLL
+	.poll_put_char	= mn10300_serial_poll_put_char,
+	.poll_get_char	= mn10300_serial_poll_get_char,
+#endif
 };
 
 static irqreturn_t mn10300_serial_interrupt(int irq, void *dev_id);
@@ -384,17 +392,21 @@
 	arch_local_irq_restore(flags);
 }
 
-static void mn10300_serial_nop(unsigned int irq)
+static void mn10300_serial_chip_mask_ack(struct irq_data *d)
+{
+	mn10300_serial_mask_ack(d->irq);
+}
+
+static void mn10300_serial_nop(struct irq_data *d)
 {
 }
 
 static struct irq_chip mn10300_serial_pic = {
 	.name		= "mnserial",
-	.ack		= mn10300_serial_mask_ack,
-	.mask		= mn10300_serial_mask_ack,
-	.mask_ack	= mn10300_serial_mask_ack,
-	.unmask		= mn10300_serial_nop,
-	.end		= mn10300_serial_nop,
+	.irq_ack	= mn10300_serial_chip_mask_ack,
+	.irq_mask	= mn10300_serial_chip_mask_ack,
+	.irq_mask_ack	= mn10300_serial_chip_mask_ack,
+	.irq_unmask	= mn10300_serial_nop,
 };
 
 
@@ -921,7 +933,7 @@
 		NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
 	set_intr_level(port->tx_irq,
 		NUM2GxICR_LEVEL(CONFIG_MN10300_SERIAL_IRQ_LEVEL));
-	set_irq_chip(port->tm_irq, &mn10300_serial_pic);
+	irq_set_chip(port->tm_irq, &mn10300_serial_pic);
 
 	if (request_irq(port->rx_irq, mn10300_serial_interrupt,
 			IRQF_DISABLED, port->rx_name, port) < 0)
@@ -1630,3 +1642,70 @@
 
 console_initcall(mn10300_serial_console_init);
 #endif
+
+#ifdef CONFIG_CONSOLE_POLL
+/*
+ * Polled character reception for the kernel debugger
+ */
+static int mn10300_serial_poll_get_char(struct uart_port *_port)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	unsigned ix;
+	u8 st, ch;
+
+	_enter("%s", port->name);
+
+	do {
+		/* pull chars out of the hat */
+		ix = port->rx_outp;
+		if (ix == port->rx_inp)
+			return NO_POLL_CHAR;
+
+		ch = port->rx_buffer[ix++];
+		st = port->rx_buffer[ix++];
+		smp_rmb();
+		port->rx_outp = ix & (MNSC_BUFFER_SIZE - 1);
+
+	} while (st & (SC01STR_FEF | SC01STR_PEF | SC01STR_OEF));
+
+	return ch;
+}
+
+
+/*
+ * Polled character transmission for the kernel debugger
+ */
+static void mn10300_serial_poll_put_char(struct uart_port *_port,
+					 unsigned char ch)
+{
+	struct mn10300_serial_port *port =
+		container_of(_port, struct mn10300_serial_port, uart);
+	u8 intr, tmp;
+
+	/* wait for the transmitter to finish anything it might be doing (and
+	 * this includes the virtual DMA handler, so it might take a while) */
+	while (*port->_status & (SC01STR_TBF | SC01STR_TXF))
+		continue;
+
+	/* disable the Tx ready interrupt */
+	intr = *port->_intr;
+	*port->_intr = intr & ~SC01ICR_TI;
+	tmp = *port->_intr;
+
+	if (ch == 0x0a) {
+		*(u8 *) port->_txb = 0x0d;
+		while (*port->_status & SC01STR_TBF)
+			continue;
+	}
+
+	*(u8 *) port->_txb = ch;
+	while (*port->_status & SC01STR_TBF)
+		continue;
+
+	/* restore the Tx interrupt flag */
+	*port->_intr = intr;
+	tmp = *port->_intr;
+}
+
+#endif /* CONFIG_CONSOLE_POLL */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/process.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,7 +135,7 @@
 
 void machine_restart(char *cmd)
 {
-#ifdef CONFIG_GDBSTUB
+#ifdef CONFIG_KERNEL_DEBUGGER
 	gdbstub_exit(0);
 #endif
 
@@ -148,14 +148,14 @@
 
 void machine_halt(void)
 {
-#ifdef CONFIG_GDBSTUB
+#ifdef CONFIG_KERNEL_DEBUGGER
 	gdbstub_exit(0);
 #endif
 }
 
 void machine_power_off(void)
 {
-#ifdef CONFIG_GDBSTUB
+#ifdef CONFIG_KERNEL_DEBUGGER
 	gdbstub_exit(0);
 #endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/smp.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/smp.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -113,15 +113,17 @@
  */
 static void mn10300_ipi_disable(unsigned int irq);
 static void mn10300_ipi_enable(unsigned int irq);
-static void mn10300_ipi_ack(unsigned int irq);
-static void mn10300_ipi_nop(unsigned int irq);
+static void mn10300_ipi_chip_disable(struct irq_data *d);
+static void mn10300_ipi_chip_enable(struct irq_data *d);
+static void mn10300_ipi_ack(struct irq_data *d);
+static void mn10300_ipi_nop(struct irq_data *d);
 
 static struct irq_chip mn10300_ipi_type = {
 	.name		= "cpu_ipi",
-	.disable	= mn10300_ipi_disable,
-	.enable		= mn10300_ipi_enable,
-	.ack		= mn10300_ipi_ack,
-	.eoi		= mn10300_ipi_nop
+	.irq_disable	= mn10300_ipi_chip_disable,
+	.irq_enable	= mn10300_ipi_chip_enable,
+	.irq_ack	= mn10300_ipi_ack,
+	.irq_eoi	= mn10300_ipi_nop
 };
 
 static irqreturn_t smp_reschedule_interrupt(int irq, void *dev_id);
@@ -154,15 +156,15 @@
 	u16 tmp16;
 
 	/* set up the reschedule IPI */
-	set_irq_chip_and_handler(RESCHEDULE_IPI,
-				 &mn10300_ipi_type, handle_percpu_irq);
+	irq_set_chip_and_handler(RESCHEDULE_IPI, &mn10300_ipi_type,
+				 handle_percpu_irq);
 	setup_irq(RESCHEDULE_IPI, &reschedule_ipi);
 	set_intr_level(RESCHEDULE_IPI, RESCHEDULE_GxICR_LV);
 	mn10300_ipi_enable(RESCHEDULE_IPI);
 
 	/* set up the call function IPI */
-	set_irq_chip_and_handler(CALL_FUNC_SINGLE_IPI,
-				 &mn10300_ipi_type, handle_percpu_irq);
+	irq_set_chip_and_handler(CALL_FUNC_SINGLE_IPI, &mn10300_ipi_type,
+				 handle_percpu_irq);
 	setup_irq(CALL_FUNC_SINGLE_IPI, &call_function_ipi);
 	set_intr_level(CALL_FUNC_SINGLE_IPI, CALL_FUNCTION_GxICR_LV);
 	mn10300_ipi_enable(CALL_FUNC_SINGLE_IPI);
@@ -170,8 +172,8 @@
 	/* set up the local timer IPI */
 #if !defined(CONFIG_GENERIC_CLOCKEVENTS) || \
     defined(CONFIG_GENERIC_CLOCKEVENTS_BROADCAST)
-	set_irq_chip_and_handler(LOCAL_TIMER_IPI,
-				 &mn10300_ipi_type, handle_percpu_irq);
+	irq_set_chip_and_handler(LOCAL_TIMER_IPI, &mn10300_ipi_type,
+				 handle_percpu_irq);
 	setup_irq(LOCAL_TIMER_IPI, &local_timer_ipi);
 	set_intr_level(LOCAL_TIMER_IPI, LOCAL_TIMER_GxICR_LV);
 	mn10300_ipi_enable(LOCAL_TIMER_IPI);
@@ -236,6 +238,11 @@
 	arch_local_irq_restore(flags);
 }
 
+static void mn10300_ipi_chip_enable(struct irq_data *d)
+{
+	mn10300_ipi_enable(d->irq);
+}
+
 /**
  * mn10300_ipi_disable - Disable an IPI
  * @irq: The IPI to be disabled.
@@ -254,6 +261,12 @@
 	arch_local_irq_restore(flags);
 }
 
+static void mn10300_ipi_chip_disable(struct irq_data *d)
+{
+	mn10300_ipi_disable(d->irq);
+}
+
+
 /**
  * mn10300_ipi_ack - Acknowledge an IPI interrupt in the PIC
  * @irq: The IPI to be acknowledged.
@@ -261,8 +274,9 @@
  * Clear the interrupt detection flag for the IPI on the appropriate interrupt
  * channel in the PIC.
  */
-static void mn10300_ipi_ack(unsigned int irq)
+static void mn10300_ipi_ack(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 	u16 tmp;
 
@@ -276,7 +290,7 @@
  * mn10300_ipi_nop - Dummy IPI action
  * @irq: The IPI to be acted upon.
  */
-static void mn10300_ipi_nop(unsigned int irq)
+static void mn10300_ipi_nop(struct irq_data *d)
 {
 }
 
@@ -426,6 +440,22 @@
 }
 
 /**
+ * smp_jump_to_debugger - Make other CPUs enter the debugger by sending an IPI
+ *
+ * Send a non-maskable request to all other CPUs in the system, instructing
+ * them to jump into the debugger.  The caller is responsible for checking that
+ * the other CPUs responded to the instruction.
+ *
+ * The caller should make sure that this CPU's debugger IPI is disabled.
+ */
+void smp_jump_to_debugger(void)
+{
+	if (num_online_cpus() > 1)
+		/* Send a message to all other CPUs */
+		send_IPI_allbutself(DEBUGGER_NMI_IPI);
+}
+
+/**
  * stop_this_cpu - Callback to stop a CPU.
  * @unused: Callback context (ignored).
  */
@@ -589,7 +619,7 @@
 /**
  * smp_prepare_cpu_init - Initialise CPU in startup_secondary
  *
- * Set interrupt level 0-6 setting and init ICR of gdbstub.
+ * Set interrupt level 0-6 setting and init ICR of the kernel debugger.
  */
 void smp_prepare_cpu_init(void)
 {
@@ -608,15 +638,15 @@
 	for (loop = 0; loop < GxICR_NUM_IRQS; loop++)
 		GxICR(loop) = GxICR_LEVEL_6 | GxICR_DETECT;
 
-#ifdef CONFIG_GDBSTUB
-	/* initialise GDB-stub */
+#ifdef CONFIG_KERNEL_DEBUGGER
+	/* initialise the kernel debugger interrupt */
 	do {
 		unsigned long flags;
 		u16 tmp16;
 
 		flags = arch_local_cli_save();
-		GxICR(GDB_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
-		tmp16 = GxICR(GDB_NMI_IPI);
+		GxICR(DEBUGGER_NMI_IPI) = GxICR_NMI | GxICR_ENABLE | GxICR_DETECT;
+		tmp16 = GxICR(DEBUGGER_NMI_IPI);
 		arch_local_irq_restore(flags);
 	} while (0);
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/switch_to.S linux-libre-2.6.39-gnu/arch/mn10300/kernel/switch_to.S
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/switch_to.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/switch_to.S	2011-05-19 00:06:34.000000000 -0400
@@ -39,11 +39,17 @@
 
 	# save prev context
 	mov	__switch_back,d0
-	mov	d0,(THREAD_PC,a0)
 	mov	sp,a2
 	mov	a2,(THREAD_SP,a0)
 	mov	a3,(THREAD_A3,a0)
 
+#ifdef CONFIG_KGDB
+	btst	0xff,(kgdb_single_step)
+	bne	__switch_to__lift_sstep_bp
+__switch_to__continue:
+#endif
+	mov	d0,(THREAD_PC,a0)
+
 	mov	(THREAD_A3,a1),a3
 	mov	(THREAD_SP,a1),a2
 
@@ -68,3 +74,106 @@
 __switch_back:
 	and	~EPSW_NMID,epsw
 	ret	[d2,d3,a2,a3,exreg1],32
+
+#ifdef CONFIG_KGDB
+###############################################################################
+#
+# Lift the single-step breakpoints when the task being traced is switched out
+# A0 = prev
+# A1 = next
+#
+###############################################################################
+__switch_to__lift_sstep_bp:
+	add	-12,sp
+	mov	a0,e4
+	mov	a1,e5
+
+	# Clear the single-step flag to prevent us coming this way until we get
+	# switched back in
+	bclr	0xff,(kgdb_single_step)
+
+	# Remove first breakpoint
+	mov	(kgdb_sstep_bp_addr),a2
+	cmp	0,a2
+	beq	1f
+	movbu	(kgdb_sstep_bp),d0
+	movbu	d0,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+1:
+
+	# Remove second breakpoint
+	mov	(kgdb_sstep_bp_addr+4),a2
+	cmp	0,a2
+	beq	2f
+	movbu	(kgdb_sstep_bp+1),d0
+	movbu	d0,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+2:
+
+	# Change the resumption address and return
+	mov	__switch_back__reinstall_sstep_bp,d0
+	mov	e4,a0
+	mov	e5,a1
+	add	12,sp
+	bra	__switch_to__continue
+
+###############################################################################
+#
+# Reinstall the single-step breakpoints when the task being traced is switched
+# back in (A1 points to the new thread_struct).
+#
+###############################################################################
+__switch_back__reinstall_sstep_bp:
+	add	-12,sp
+	mov	a0,e4			# save the return value
+	mov	0xff,d3
+
+	# Reinstall first breakpoint
+	mov	(kgdb_sstep_bp_addr),a2
+	cmp	0,a2
+	beq	1f
+	movbu	(a2),d0
+	movbu	d0,(kgdb_sstep_bp)
+	movbu	d3,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+1:
+
+	# Reinstall second breakpoint
+	mov	(kgdb_sstep_bp_addr+4),a2
+	cmp	0,a2
+	beq	2f
+	movbu	(a2),d0
+	movbu	d0,(kgdb_sstep_bp+1)
+	movbu	d3,(a2)
+#if defined(CONFIG_MN10300_CACHE_FLUSH_ICACHE) || defined(CONFIG_MN10300_CACHE_INV_ICACHE)
+	mov	a2,d0
+	mov	a2,d1
+	add	1,d1
+	calls	flush_icache_range
+#endif
+2:
+
+	mov	d3,(kgdb_single_step)
+
+	# Restore the return value (the previous thread_struct pointer)
+	mov	e4,a0
+	mov	a0,d0
+	add	12,sp
+	bra	__switch_back
+
+#endif /* CONFIG_KGDB */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/time.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,83 +93,6 @@
 	return IRQ_HANDLED;
 }
 
-#ifndef CONFIG_GENERIC_TIME
-/*
- * advance the kernel's time keeping clocks (xtime and jiffies)
- * - we use Timer 0 & 1 cascaded as a clock to nudge us the next time
- *   there's a need to update
- */
-static irqreturn_t timer_interrupt(int irq, void *dev_id)
-{
-	unsigned tsc, elapse;
-	irqreturn_t ret;
-
-	write_seqlock(&xtime_lock);
-
-	while (tsc = get_cycles(),
-	       elapse = tsc - mn10300_last_tsc, /* time elapsed since last
-						 * tick */
-	       elapse > MN10300_TSC_PER_HZ
-	       ) {
-		mn10300_last_tsc += MN10300_TSC_PER_HZ;
-
-		/* advance the kernel's time tracking system */
-		do_timer(1);
-	}
-
-	write_sequnlock(&xtime_lock);
-
-	ret = local_timer_interrupt();
-#ifdef CONFIG_SMP
-	send_IPI_allbutself(LOCAL_TIMER_IPI);
-#endif
-	return ret;
-}
-
-static struct irqaction timer_irq = {
-	.handler	= timer_interrupt,
-	.flags		= IRQF_DISABLED | IRQF_SHARED | IRQF_TIMER,
-	.name		= "timer",
-};
-#endif /* CONFIG_GENERIC_TIME */
-
-#ifdef CONFIG_CSRC_MN10300
-void __init clocksource_set_clock(struct clocksource *cs, unsigned int clock)
-{
-	u64 temp;
-	u32 shift;
-
-	/* Find a shift value */
-	for (shift = 32; shift > 0; shift--) {
-		temp = (u64) NSEC_PER_SEC << shift;
-		do_div(temp, clock);
-		if ((temp >> 32) == 0)
-			break;
-	}
-	cs->shift = shift;
-	cs->mult = (u32) temp;
-}
-#endif
-
-#if CONFIG_CEVT_MN10300
-void __cpuinit clockevent_set_clock(struct clock_event_device *cd,
-				    unsigned int clock)
-{
-	u64 temp;
-	u32 shift;
-
-	/* Find a shift value */
-	for (shift = 32; shift > 0; shift--) {
-		temp = (u64) clock << shift;
-		do_div(temp, NSEC_PER_SEC);
-		if ((temp >> 32) == 0)
-			break;
-	}
-	cd->shift = shift;
-	cd->mult = (u32) temp;
-}
-#endif
-
 /*
  * initialise the various timers used by the main part of the kernel
  */
@@ -181,11 +104,7 @@
 	 */
 	TMPSCNT |= TMPSCNT_ENABLE;
 
-#ifdef CONFIG_GENERIC_TIME
 	init_clocksource();
-#else
-	startup_timestamp_counter();
-#endif
 
 	printk(KERN_INFO
 	       "timestamp counter I/O clock running at %lu.%02lu"
@@ -194,12 +113,7 @@
 
 	mn10300_last_tsc = read_timestamp_counter();
 
-#ifdef CONFIG_GENERIC_CLOCKEVENTS
 	init_clockevents();
-#else
-	reload_jiffies_counter(MN10300_JC_PER_HZ - 1);
-	setup_jiffies_interrupt(TMJCIRQ, &timer_irq, CONFIG_TIMER_IRQ_LEVEL);
-#endif
 
 #ifdef CONFIG_MN10300_WD_TIMER
 	/* start the watchdog timer */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/traps.c linux-libre-2.6.39-gnu/arch/mn10300/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,8 +38,9 @@
 #include <asm/busctl-regs.h>
 #include <unit/leds.h>
 #include <asm/fpu.h>
-#include <asm/gdb-stub.h>
 #include <asm/sections.h>
+#include <asm/debugger.h>
+#include "internal.h"
 
 #if (CONFIG_INTERRUPT_VECTOR_BASE & 0xffffff)
 #error "INTERRUPT_VECTOR_BASE not aligned to 16MiB boundary!"
@@ -49,63 +50,169 @@
 
 spinlock_t die_lock = __SPIN_LOCK_UNLOCKED(die_lock);
 
-ATOMIC_NOTIFIER_HEAD(mn10300_die_chain);
+struct exception_to_signal_map {
+	u8	signo;
+	u32	si_code;
+};
+
+static const struct exception_to_signal_map exception_to_signal_map[256] = {
+	/* MMU exceptions */
+	[EXCEP_ITLBMISS >> 3]	= { 0, 0 },
+	[EXCEP_DTLBMISS >> 3]	= { 0, 0 },
+	[EXCEP_IAERROR >> 3]	= { 0, 0 },
+	[EXCEP_DAERROR >> 3]	= { 0, 0 },
+
+	/* system exceptions */
+	[EXCEP_TRAP >> 3]	= { SIGTRAP,	TRAP_BRKPT },
+	[EXCEP_ISTEP >> 3]	= { SIGTRAP,	TRAP_TRACE },	/* Monitor */
+	[EXCEP_IBREAK >> 3]	= { SIGTRAP,	TRAP_HWBKPT },	/* Monitor */
+	[EXCEP_OBREAK >> 3]	= { SIGTRAP,	TRAP_HWBKPT },	/* Monitor */
+	[EXCEP_PRIVINS >> 3]	= { SIGILL,	ILL_PRVOPC },
+	[EXCEP_UNIMPINS >> 3]	= { SIGILL,	ILL_ILLOPC },
+	[EXCEP_UNIMPEXINS >> 3]	= { SIGILL,	ILL_ILLOPC },
+	[EXCEP_MEMERR >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_MISALIGN >> 3]	= { SIGBUS,	BUS_ADRALN },
+	[EXCEP_BUSERROR >> 3]	= { SIGBUS,	BUS_ADRERR },
+	[EXCEP_ILLINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_ILLDATACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_IOINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_PRIVINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR }, /* userspace */
+	[EXCEP_PRIVDATACC >> 3]	= { SIGSEGV,	SEGV_ACCERR }, /* userspace */
+	[EXCEP_DATINSACC >> 3]	= { SIGSEGV,	SEGV_ACCERR },
+	[EXCEP_DOUBLE_FAULT >> 3] = { SIGILL,	ILL_BADSTK },
+
+	/* FPU exceptions */
+	[EXCEP_FPU_DISABLED >> 3] = { SIGILL,	ILL_COPROC },
+	[EXCEP_FPU_UNIMPINS >> 3] = { SIGILL,	ILL_COPROC },
+	[EXCEP_FPU_OPERATION >> 3] = { SIGFPE,	FPE_INTDIV },
+
+	/* interrupts */
+	[EXCEP_WDT >> 3]	= { SIGALRM,	0 },
+	[EXCEP_NMI >> 3]	= { SIGQUIT,	0 },
+	[EXCEP_IRQ_LEVEL0 >> 3]	= { SIGINT,	0 },
+	[EXCEP_IRQ_LEVEL1 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL2 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL3 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL4 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL5 >> 3]	= { 0, 0 },
+	[EXCEP_IRQ_LEVEL6 >> 3]	= { 0, 0 },
+
+	/* system calls */
+	[EXCEP_SYSCALL0 >> 3]	= { 0, 0 },
+	[EXCEP_SYSCALL1 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL2 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL3 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL4 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL5 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL6 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL7 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL8 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL9 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL10 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL11 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL12 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL13 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL14 >> 3]	= { SIGILL,	ILL_ILLTRP },
+	[EXCEP_SYSCALL15 >> 3]	= { SIGABRT,	0 },
+};
 
 /*
- * These constants are for searching for possible module text
- * segments. MODULE_RANGE is a guess of how much space is likely
- * to be vmalloced.
+ * Handle kernel exceptions.
+ *
+ * See if there's a fixup handler we can force a jump to when an exception
+ * happens due to something kernel code did
  */
-#define MODULE_RANGE (8 * 1024 * 1024)
+int die_if_no_fixup(const char *str, struct pt_regs *regs,
+		    enum exception_code code)
+{
+	u8 opcode;
+	int signo, si_code;
 
-#define DO_ERROR(signr, prologue, str, name)			\
-asmlinkage void name(struct pt_regs *regs, u32 intcode)		\
-{								\
-	prologue;						\
-	if (die_if_no_fixup(str, regs, intcode))		\
-		return;						\
-	force_sig(signr, current);				\
-}
+	if (user_mode(regs))
+		return 0;
 
-#define DO_EINFO(signr, prologue, str, name, sicode)			\
-asmlinkage void name(struct pt_regs *regs, u32 intcode)			\
-{									\
-	siginfo_t info;							\
-	prologue;							\
-	if (die_if_no_fixup(str, regs, intcode))			\
-		return;							\
-	info.si_signo = signr;						\
-	if (signr == SIGILL && sicode == ILL_ILLOPC) {			\
-		uint8_t opcode;						\
-		if (get_user(opcode, (uint8_t __user *)regs->pc) == 0)	\
-			if (opcode == 0xff)				\
-				info.si_signo = SIGTRAP;		\
-	}								\
-	info.si_errno = 0;						\
-	info.si_code = sicode;						\
-	info.si_addr = (void *) regs->pc;				\
-	force_sig_info(info.si_signo, &info, current);			\
+	peripheral_leds_display_exception(code);
+
+	signo = exception_to_signal_map[code >> 3].signo;
+	si_code = exception_to_signal_map[code >> 3].si_code;
+
+	switch (code) {
+		/* see if we can fixup the kernel accessing memory */
+	case EXCEP_ITLBMISS:
+	case EXCEP_DTLBMISS:
+	case EXCEP_IAERROR:
+	case EXCEP_DAERROR:
+	case EXCEP_MEMERR:
+	case EXCEP_MISALIGN:
+	case EXCEP_BUSERROR:
+	case EXCEP_ILLDATACC:
+	case EXCEP_IOINSACC:
+	case EXCEP_PRIVINSACC:
+	case EXCEP_PRIVDATACC:
+	case EXCEP_DATINSACC:
+		if (fixup_exception(regs))
+			return 1;
+		break;
+
+	case EXCEP_TRAP:
+	case EXCEP_UNIMPINS:
+		if (get_user(opcode, (uint8_t __user *)regs->pc) != 0)
+			break;
+		if (opcode == 0xff) {
+			if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
+				return 1;
+			if (at_debugger_breakpoint(regs))
+				regs->pc++;
+			signo = SIGTRAP;
+			si_code = TRAP_BRKPT;
+		}
+		break;
+
+	case EXCEP_SYSCALL1 ... EXCEP_SYSCALL14:
+		/* syscall return addr is _after_ the instruction */
+		regs->pc -= 2;
+		break;
+
+	case EXCEP_SYSCALL15:
+		if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_WARN)
+			return 1;
+
+		/* syscall return addr is _after_ the instruction */
+		regs->pc -= 2;
+		break;
+
+	default:
+		break;
+	}
+
+	if (debugger_intercept(code, signo, si_code, regs) == 0)
+		return 1;
+
+	if (notify_die(DIE_GPF, str, regs, code, 0, 0))
+		return 1;
+
+	/* make the process die as the last resort */
+	die(str, regs, code);
 }
 
-DO_ERROR(SIGTRAP, {}, "trap",			trap);
-DO_ERROR(SIGSEGV, {}, "ibreak",			ibreak);
-DO_ERROR(SIGSEGV, {}, "obreak",			obreak);
-DO_EINFO(SIGSEGV, {}, "access error",		access_error,	SEGV_ACCERR);
-DO_EINFO(SIGSEGV, {}, "insn access error",	insn_acc_error,	SEGV_ACCERR);
-DO_EINFO(SIGSEGV, {}, "data access error",	data_acc_error,	SEGV_ACCERR);
-DO_EINFO(SIGILL,  {}, "privileged opcode",	priv_op,	ILL_PRVOPC);
-DO_EINFO(SIGILL,  {}, "invalid opcode",		invalid_op,	ILL_ILLOPC);
-DO_EINFO(SIGILL,  {}, "invalid ex opcode",	invalid_exop,	ILL_ILLOPC);
-DO_EINFO(SIGBUS,  {}, "invalid address",	mem_error,	BUS_ADRERR);
-DO_EINFO(SIGBUS,  {}, "bus error",		bus_error,	BUS_ADRERR);
+/*
+ * General exception handler
+ */
+asmlinkage void handle_exception(struct pt_regs *regs, u32 intcode)
+{
+	siginfo_t info;
 
-DO_ERROR(SIGTRAP,
-#ifndef CONFIG_MN10300_USING_JTAG
-	 DCR &= ~0x0001,
-#else
-	 {},
-#endif
-	 "single step", istep);
+	/* deal with kernel exceptions here */
+	if (die_if_no_fixup(NULL, regs, intcode))
+		return;
+
+	/* otherwise it's a userspace exception */
+	info.si_signo = exception_to_signal_map[intcode >> 3].signo;
+	info.si_code = exception_to_signal_map[intcode >> 3].si_code;
+	info.si_errno = 0;
+	info.si_addr = (void *) regs->pc;
+	force_sig_info(info.si_signo, &info, current);
+}
 
 /*
  * handle NMI
@@ -113,10 +220,8 @@
 asmlinkage void nmi(struct pt_regs *regs, enum exception_code code)
 {
 	/* see if gdbstub wants to deal with it */
-#ifdef CONFIG_GDBSTUB
-	if (gdbstub_intercept(regs, code))
+	if (debugger_intercept(code, SIGQUIT, 0, regs))
 		return;
-#endif
 
 	printk(KERN_WARNING "--- Register Dump ---\n");
 	show_registers(regs);
@@ -128,29 +233,36 @@
  */
 void show_trace(unsigned long *sp)
 {
-	unsigned long *stack, addr, module_start, module_end;
-	int i;
+	unsigned long bottom, stack, addr, fp, raslot;
 
-	printk(KERN_EMERG "\nCall Trace:");
+	printk(KERN_EMERG "\nCall Trace:\n");
 
-	stack = sp;
-	i = 0;
-	module_start = VMALLOC_START;
-	module_end = VMALLOC_END;
+	//stack = (unsigned long)sp;
+	asm("mov sp,%0" : "=a"(stack));
+	asm("mov a3,%0" : "=r"(fp));
+
+	raslot = ULONG_MAX;
+	bottom = (stack + THREAD_SIZE) & ~(THREAD_SIZE - 1);
+	for (; stack < bottom; stack += sizeof(addr)) {
+		addr = *(unsigned long *)stack;
+		if (stack == fp) {
+			if (addr > stack && addr < bottom) {
+				fp = addr;
+				raslot = stack + sizeof(addr);
+				continue;
+			}
+			fp = 0;
+			raslot = ULONG_MAX;
+		}
 
-	while (((long) stack & (THREAD_SIZE - 1)) != 0) {
-		addr = *stack++;
 		if (__kernel_text_address(addr)) {
-#if 1
 			printk(" [<%08lx>]", addr);
+			if (stack >= raslot)
+				raslot = ULONG_MAX;
+			else
+				printk(" ?");
 			print_symbol(" %s", addr);
 			printk("\n");
-#else
-			if ((i % 6) == 0)
-				printk(KERN_EMERG "  ");
-			printk("[<%08lx>] ", addr);
-			i++;
-#endif
 		}
 	}
 
@@ -323,86 +435,6 @@
 }
 
 /*
- * see if there's a fixup handler we can force a jump to when an exception
- * happens due to something kernel code did
- */
-int die_if_no_fixup(const char *str, struct pt_regs *regs,
-		    enum exception_code code)
-{
-	if (user_mode(regs))
-		return 0;
-
-	peripheral_leds_display_exception(code);
-
-	switch (code) {
-		/* see if we can fixup the kernel accessing memory */
-	case EXCEP_ITLBMISS:
-	case EXCEP_DTLBMISS:
-	case EXCEP_IAERROR:
-	case EXCEP_DAERROR:
-	case EXCEP_MEMERR:
-	case EXCEP_MISALIGN:
-	case EXCEP_BUSERROR:
-	case EXCEP_ILLDATACC:
-	case EXCEP_IOINSACC:
-	case EXCEP_PRIVINSACC:
-	case EXCEP_PRIVDATACC:
-	case EXCEP_DATINSACC:
-		if (fixup_exception(regs))
-			return 1;
-	case EXCEP_UNIMPINS:
-		if (regs->pc && *(uint8_t *)regs->pc == 0xff)
-			if (notify_die(DIE_BREAKPOINT, str, regs, code, 0, 0))
-				return 1;
-		break;
-	default:
-		break;
-	}
-
-	/* see if gdbstub wants to deal with it */
-#ifdef CONFIG_GDBSTUB
-	if (gdbstub_intercept(regs, code))
-		return 1;
-#endif
-
-	if (notify_die(DIE_GPF, str, regs, code, 0, 0))
-		return 1;
-
-	/* make the process die as the last resort */
-	die(str, regs, code);
-}
-
-/*
- * handle unsupported syscall instructions (syscall 1-15)
- */
-static asmlinkage void unsupported_syscall(struct pt_regs *regs,
-					   enum exception_code code)
-{
-	struct task_struct *tsk = current;
-	siginfo_t info;
-
-	/* catch a kernel BUG() */
-	if (code == EXCEP_SYSCALL15 && !user_mode(regs)) {
-		if (report_bug(regs->pc, regs) == BUG_TRAP_TYPE_BUG) {
-#ifdef CONFIG_GDBSTUB
-			gdbstub_intercept(regs, code);
-#endif
-		}
-	}
-
-	regs->pc -= 2; /* syscall return addr is _after_ the instruction */
-
-	die_if_no_fixup("An unsupported syscall insn was used by the kernel\n",
-			regs, code);
-
-	info.si_signo	= SIGILL;
-	info.si_errno	= ENOSYS;
-	info.si_code	= ILL_ILLTRP;
-	info.si_addr	= (void *) regs->pc;
-	force_sig_info(SIGILL, &info, tsk);
-}
-
-/*
  * display the register file when the stack pointer gets clobbered
  */
 asmlinkage void do_double_fault(struct pt_regs *regs)
@@ -481,10 +513,8 @@
 {
 
 	/* see if gdbstub wants to deal with it */
-#ifdef CONFIG_GDBSTUB
-	if (gdbstub_intercept(regs, code))
+	if (debugger_intercept(code, SIGSYS, 0, regs) == 0)
 		return;
-#endif
 
 	peripheral_leds_display_exception(code);
 	printk(KERN_EMERG "Uninitialised Exception 0x%04x\n", code & 0xFFFF);
@@ -549,43 +579,43 @@
  */
 void __init trap_init(void)
 {
-	set_excp_vector(EXCEP_TRAP,		trap);
-	set_excp_vector(EXCEP_ISTEP,		istep);
-	set_excp_vector(EXCEP_IBREAK,		ibreak);
-	set_excp_vector(EXCEP_OBREAK,		obreak);
+	set_excp_vector(EXCEP_TRAP,		handle_exception);
+	set_excp_vector(EXCEP_ISTEP,		handle_exception);
+	set_excp_vector(EXCEP_IBREAK,		handle_exception);
+	set_excp_vector(EXCEP_OBREAK,		handle_exception);
 
-	set_excp_vector(EXCEP_PRIVINS,		priv_op);
-	set_excp_vector(EXCEP_UNIMPINS,		invalid_op);
-	set_excp_vector(EXCEP_UNIMPEXINS,	invalid_exop);
-	set_excp_vector(EXCEP_MEMERR,		mem_error);
+	set_excp_vector(EXCEP_PRIVINS,		handle_exception);
+	set_excp_vector(EXCEP_UNIMPINS,		handle_exception);
+	set_excp_vector(EXCEP_UNIMPEXINS,	handle_exception);
+	set_excp_vector(EXCEP_MEMERR,		handle_exception);
 	set_excp_vector(EXCEP_MISALIGN,		misalignment);
-	set_excp_vector(EXCEP_BUSERROR,		bus_error);
-	set_excp_vector(EXCEP_ILLINSACC,	insn_acc_error);
-	set_excp_vector(EXCEP_ILLDATACC,	data_acc_error);
-	set_excp_vector(EXCEP_IOINSACC,		insn_acc_error);
-	set_excp_vector(EXCEP_PRIVINSACC,	insn_acc_error);
-	set_excp_vector(EXCEP_PRIVDATACC,	data_acc_error);
-	set_excp_vector(EXCEP_DATINSACC,	insn_acc_error);
-	set_excp_vector(EXCEP_FPU_UNIMPINS,	fpu_invalid_op);
+	set_excp_vector(EXCEP_BUSERROR,		handle_exception);
+	set_excp_vector(EXCEP_ILLINSACC,	handle_exception);
+	set_excp_vector(EXCEP_ILLDATACC,	handle_exception);
+	set_excp_vector(EXCEP_IOINSACC,		handle_exception);
+	set_excp_vector(EXCEP_PRIVINSACC,	handle_exception);
+	set_excp_vector(EXCEP_PRIVDATACC,	handle_exception);
+	set_excp_vector(EXCEP_DATINSACC,	handle_exception);
+	set_excp_vector(EXCEP_FPU_UNIMPINS,	handle_exception);
 	set_excp_vector(EXCEP_FPU_OPERATION,	fpu_exception);
 
 	set_excp_vector(EXCEP_NMI,		nmi);
 
-	set_excp_vector(EXCEP_SYSCALL1,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL2,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL3,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL4,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL5,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL6,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL7,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL8,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL9,		unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL10,	unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL11,	unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL12,	unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL13,	unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL14,	unsupported_syscall);
-	set_excp_vector(EXCEP_SYSCALL15,	unsupported_syscall);
+	set_excp_vector(EXCEP_SYSCALL1,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL2,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL3,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL4,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL5,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL6,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL7,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL8,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL9,		handle_exception);
+	set_excp_vector(EXCEP_SYSCALL10,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL11,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL12,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL13,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL14,	handle_exception);
+	set_excp_vector(EXCEP_SYSCALL15,	handle_exception);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/mn10300/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/mn10300/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -70,7 +70,7 @@
 	.exit.text : { EXIT_TEXT; }
 	.exit.data : { EXIT_DATA; }
 
-  PERCPU(PAGE_SIZE)
+  PERCPU(32, PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   __init_end = .;
   /* freed after init ends here */
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-flush-by-reg.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-flush-by-reg.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-flush-by-reg.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-flush-by-reg.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,160 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2011 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/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+# Flush the entire data cache back to RAM and invalidate the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv
+        .type	debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+	#
+	# firstly flush the dcache
+	#
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN|CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	mov	DCPGCR,a0
+
+	mov	epsw,d1
+	and	~EPSW_IE,epsw
+	or	EPSW_NMID,epsw
+	nop
+
+	btst	CHCTR_DCEN,d0
+	beq	debugger_local_cache_flushinv_no_dcache
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+	# set mask
+	clr	d0
+	mov	d0,(DCPGMR)
+
+	# area purge
+	#
+	# DCPGCR = DCPGCR_DCP
+	#
+	mov	DCPGCR_DCP,d0
+	mov	d0,(a0)
+
+	# wait for busy bit of area purge
+	setlb
+	mov	(a0),d0
+	btst	DCPGCR_DCPGBSY,d0
+	lne
+
+debugger_local_cache_flushinv_no_dcache:
+	#
+	# secondly, invalidate the icache if it is enabled
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_done
+
+	invalidate_icache 0
+
+debugger_local_cache_flushinv_done:
+	mov	d1,epsw
+
+debugger_local_cache_flushinv_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+	movhu	(CHCTR),d1
+	btst	CHCTR_DCEN|CHCTR_ICEN,d1
+	beq	debugger_local_cache_flushinv_one_end
+	btst	CHCTR_DCEN,d1
+	beq	debugger_local_cache_flushinv_one_no_dcache
+
+	# round cacheline addr down
+	and	L1_CACHE_TAG_MASK,d0
+	mov	d0,a1
+	mov	d0,d1
+
+	# determine the dcache purge control reg address
+	mov	DCACHE_PURGE(0,0),a0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0
+
+	# retain valid entries in the cache
+	or	L1_CACHE_TAG_VALID,d1
+
+	# conditionally purge this line in all ways
+	mov	d1,(L1_CACHE_WAYDISP*0,a0)
+
+debugger_local_cache_flushinv_no_dcache:
+	#
+	# now try to flush the icache
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	mn10300_local_icache_inv_range_reg_end
+
+	LOCAL_CLI_SAVE(d1)
+
+	mov	ICIVCR,a0
+
+	# wait for the invalidator to quiesce
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	# set the mask
+	mov	L1_CACHE_TAG_MASK,d0
+	mov	d0,(ICIVMR)
+
+	# invalidate the cache line at the given address
+	or	ICIVCR_ICI,a1
+	mov	a1,(a0)
+
+	# wait for the invalidator to quiesce again
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	LOCAL_IRQ_RESTORE(d1)
+
+debugger_local_cache_flushinv_one_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-flush-by-tag.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-flush-by-tag.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-flush-by-tag.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-flush-by-tag.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,114 @@
+/* MN10300 CPU cache invalidation routines, using direct tag flushing
+ *
+ * Copyright (C) 2011 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/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+#
+# Flush the entire data cache back to RAM and invalidate the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv
+        .type	debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+	#
+	# firstly flush the dcache
+	#
+	movhu	(CHCTR),d0
+	btst	CHCTR_DCEN|CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	btst	CHCTR_DCEN,d0
+	beq	debugger_local_cache_flushinv_no_dcache
+
+	# read the addresses tagged in the cache's tag RAM and attempt to flush
+	# those addresses specifically
+	# - we rely on the hardware to filter out invalid tag entry addresses
+	mov	DCACHE_TAG(0,0),a0		# dcache tag RAM access address
+	mov	DCACHE_PURGE(0,0),a1		# dcache purge request address
+	mov	L1_CACHE_NWAYS*L1_CACHE_NENTRIES,e0  # total number of entries
+
+mn10300_local_dcache_flush_loop:
+	mov	(a0),d0
+	and	L1_CACHE_TAG_MASK,d0
+	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
+						# cache
+	mov	d0,(a1)				# conditional purge
+
+	add	L1_CACHE_BYTES,a0
+	add	L1_CACHE_BYTES,a1
+	add	-1,e0
+	bne	mn10300_local_dcache_flush_loop
+
+debugger_local_cache_flushinv_no_dcache:
+	#
+	# secondly, invalidate the icache if it is enabled
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	invalidate_icache 1
+
+debugger_local_cache_flushinv_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+	movhu	(CHCTR),d1
+	btst	CHCTR_DCEN|CHCTR_ICEN,d1
+	beq	debugger_local_cache_flushinv_one_end
+	btst	CHCTR_DCEN,d1
+	beq	debugger_local_cache_flushinv_one_icache
+
+	# round cacheline addr down
+	and	L1_CACHE_TAG_MASK,d0
+	mov	d0,a1
+
+	# determine the dcache purge control reg address
+	mov	DCACHE_PURGE(0,0),a0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0
+
+	# retain valid entries in the cache
+	or	L1_CACHE_TAG_VALID,a1
+
+	# conditionally purge this line in all ways
+	mov	a1,(L1_CACHE_WAYDISP*0,a0)
+
+	# now go and do the icache
+	bra	debugger_local_cache_flushinv_one_icache
+
+debugger_local_cache_flushinv_one_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-inv-by-reg.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-inv-by-reg.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-inv-by-reg.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-inv-by-reg.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,69 @@
+/* MN10300 CPU cache invalidation routines, using automatic purge registers
+ *
+ * Copyright (C) 2011 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/sys.h>
+#include <linux/linkage.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+	.globl	debugger_local_cache_flushinv_one
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one:
+	mov	d0,a1
+
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	mn10300_local_icache_inv_range_reg_end
+
+	LOCAL_CLI_SAVE(d1)
+
+	mov	ICIVCR,a0
+
+	# wait for the invalidator to quiesce
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	# set the mask
+	mov	~L1_CACHE_TAG_MASK,d0
+	mov	d0,(ICIVMR)
+
+	# invalidate the cache line at the given address
+	and	~L1_CACHE_TAG_MASK,a1
+	or	ICIVCR_ICI,a1
+	mov	a1,(a0)
+
+	# wait for the invalidator to quiesce again
+	setlb
+	mov	(a0),d0
+	btst	ICIVCR_ICIVBSY,d0
+	lne
+
+	LOCAL_IRQ_RESTORE(d1)
+
+mn10300_local_icache_inv_range_reg_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv_one,.-debugger_local_cache_flushinv_one
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-inv-by-tag.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-inv-by-tag.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-inv-by-tag.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-inv-by-tag.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,120 @@
+/* MN10300 CPU cache invalidation routines, using direct tag flushing
+ *
+ * Copyright (C) 2011 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/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+	.globl	debugger_local_cache_flushinv_one_icache
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv_one(u8 *addr)
+#
+# Invalidate one particular cacheline if it's in the icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv_one_icache
+	.type	debugger_local_cache_flushinv_one_icache,@function
+debugger_local_cache_flushinv_one_icache:
+	movm	[d3,a2],(sp)
+
+	mov	CHCTR,a2
+	movhu	(a2),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_one_icache_end
+
+	mov	d0,a1
+	and	L1_CACHE_TAG_MASK,a1
+
+	# read the tags from the tag RAM, and if they indicate a matching valid
+	# cache line then we invalidate that line
+	mov	ICACHE_TAG(0,0),a0
+	mov	a1,d0
+	and	L1_CACHE_TAG_ENTRY,d0
+	add	d0,a0				# starting icache tag RAM
+						# access address
+
+	and	~(L1_CACHE_DISPARITY-1),a1	# determine comparator base
+	or	L1_CACHE_TAG_VALID,a1
+	mov	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_VALID,d1
+
+	LOCAL_CLI_SAVE(d3)
+
+	# disable the icache
+	movhu	(a2),d0
+	and	~CHCTR_ICEN,d0
+	movhu	d0,(a2)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a2),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# check all the way tags for this cache entry
+	mov	(a0),d0				# read the tag in the way 0 slot
+	xor	a1,d0
+	and	d1,d0
+	beq	debugger_local_icache_kill	# jump if matched
+
+	add	L1_CACHE_WAYDISP,a0
+	mov	(a0),d0				# read the tag in the way 1 slot
+	xor	a1,d0
+	and	d1,d0
+	beq	debugger_local_icache_kill	# jump if matched
+
+	add	L1_CACHE_WAYDISP,a0
+	mov	(a0),d0				# read the tag in the way 2 slot
+	xor	a1,d0
+	and	d1,d0
+	beq	debugger_local_icache_kill	# jump if matched
+
+	add	L1_CACHE_WAYDISP,a0
+	mov	(a0),d0				# read the tag in the way 3 slot
+	xor	a1,d0
+	and	d1,d0
+	bne	debugger_local_icache_finish	# jump if not matched
+
+debugger_local_icache_kill:
+	mov	d0,(a0)				# kill the tag (D0 is 0 at this point)
+
+debugger_local_icache_finish:
+	# wait for the cache to finish what it's doing
+	setlb
+	movhu	(a2),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_ICEN,d0
+	movhu	d0,(a2)
+	movhu	(a2),d0
+
+	# re-enable interrupts
+	LOCAL_IRQ_RESTORE(d3)
+
+debugger_local_cache_flushinv_one_icache_end:
+	ret	[d3,a2],8
+	.size	debugger_local_cache_flushinv_one_icache,.-debugger_local_cache_flushinv_one_icache
+
+#ifdef CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG
+	.globl	debugger_local_cache_flushinv_one
+	.type	debugger_local_cache_flushinv_one,@function
+debugger_local_cache_flushinv_one = debugger_local_cache_flushinv_one_icache
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-inv.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-inv.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-dbg-inv.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-dbg-inv.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+/* MN10300 CPU cache invalidation routines
+ *
+ * Copyright (C) 2011 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/sys.h>
+#include <linux/linkage.h>
+#include <asm/smp.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+#include <asm/irqflags.h>
+#include <asm/cacheflush.h>
+#include "cache.inc"
+
+	.am33_2
+
+	.globl	debugger_local_cache_flushinv
+
+###############################################################################
+#
+# void debugger_local_cache_flushinv(void)
+#
+# Invalidate the entire icache
+#
+###############################################################################
+	ALIGN
+	.globl	debugger_local_cache_flushinv
+        .type	debugger_local_cache_flushinv,@function
+debugger_local_cache_flushinv:
+	#
+	# we only need to invalidate the icache in this cache mode
+	#
+	mov	CHCTR,a0
+	movhu	(a0),d0
+	btst	CHCTR_ICEN,d0
+	beq	debugger_local_cache_flushinv_end
+
+	invalidate_icache 1
+
+debugger_local_cache_flushinv_end:
+	ret	[],0
+	.size	debugger_local_cache_flushinv,.-debugger_local_cache_flushinv
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-flush-by-tag.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-flush-by-tag.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-flush-by-tag.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-flush-by-tag.S	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 
 mn10300_local_dcache_flush_loop:
 	mov	(a0),d0
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+	and	L1_CACHE_TAG_MASK,d0
 	or	L1_CACHE_TAG_VALID,d0		# retain valid entries in the
 						# cache
 	mov	d0,(a1)				# conditional purge
@@ -112,11 +112,11 @@
 1:
 
 	# round start addr down
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0
+	and	L1_CACHE_TAG_MASK,d0
 	mov	d0,a1
 
 	add	L1_CACHE_BYTES,d1			# round end addr up
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+	and	L1_CACHE_TAG_MASK,d1
 
 	# write a request to flush all instances of an address from the cache
 	mov	DCACHE_PURGE(0,0),a0
@@ -215,12 +215,11 @@
 	bra	mn10300_local_dcache_flush_inv
 1:
 
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start
-								# addr down
+	and	L1_CACHE_TAG_MASK,d0		# round start addr down
 	mov	d0,a1
 
-	add	L1_CACHE_BYTES,d1			# round end addr up
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+	add	L1_CACHE_BYTES,d1		# round end addr up
+	and	L1_CACHE_TAG_MASK,d1
 
 	# write a request to flush and invalidate all instances of an address
 	# from the cache
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache.inc linux-libre-2.6.39-gnu/arch/mn10300/mm/cache.inc
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache.inc	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache.inc	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,133 @@
+/* MN10300 CPU core caching macros -*- asm -*-
+ *
+ * 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.
+ */
+
+
+###############################################################################
+#
+# Invalidate the instruction cache.
+#	A0: Should hold CHCTR
+#	D0: Should have been read from CHCTR
+#	D1: Will be clobbered
+#
+# On some cores it is necessary to disable the icache whilst we do this.
+#
+###############################################################################
+	.macro invalidate_icache,disable_irq
+
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+	.if \disable_irq
+	# don't want an interrupt routine seeing a disabled cache
+	mov	epsw,d1
+	and	~EPSW_IE,epsw
+	or	EPSW_NMID,epsw
+	nop
+	nop
+	.endif
+
+	# disable the icache
+	and	~CHCTR_ICEN,d0
+	movhu	d0,(a0)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# invalidate
+	or	CHCTR_ICINV,d0
+	movhu	d0,(a0)
+
+	# wait for the cache to finish
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_ICBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_ICEN,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+	.if \disable_irq
+	LOCAL_IRQ_RESTORE(d1)
+	.endif
+
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+
+	# invalidate
+	or	CHCTR_ICINV,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+	.endm
+
+###############################################################################
+#
+# Invalidate the data cache.
+#	A0: Should hold CHCTR
+#	D0: Should have been read from CHCTR
+#	D1: Will be clobbered
+#
+# On some cores it is necessary to disable the dcache whilst we do this.
+#
+###############################################################################
+	.macro invalidate_dcache,disable_irq
+
+#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
+	.if \disable_irq
+	# don't want an interrupt routine seeing a disabled cache
+	mov	epsw,d1
+	and	~EPSW_IE,epsw
+	or	EPSW_NMID,epsw
+	nop
+	nop
+	.endif
+	
+	# disable the dcache
+	and	~CHCTR_DCEN,d0
+	movhu	d0,(a0)
+
+	# and wait for it to calm down
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_DCBUSY,d0
+	lne
+
+	# invalidate
+	or	CHCTR_DCINV,d0
+	movhu	d0,(a0)
+
+	# wait for the cache to finish
+	setlb
+	movhu	(a0),d0
+	btst	CHCTR_DCBUSY,d0
+	lne
+
+	# and reenable it
+	or	CHCTR_DCEN,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+	.if \disable_irq
+	LOCAL_IRQ_RESTORE(d1)
+	.endif
+
+#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+
+	# invalidate
+	or	CHCTR_DCINV,d0
+	movhu	d0,(a0)
+	movhu	(a0),d0
+
+#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+	.endm
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-inv-by-reg.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-inv-by-reg.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-inv-by-reg.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-inv-by-reg.S	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <asm/cache.h>
 #include <asm/irqflags.h>
 #include <asm/cacheflush.h>
+#include "cache.inc"
 
 #define mn10300_local_dcache_inv_range_intr_interval \
 	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
@@ -62,10 +63,7 @@
 	btst	CHCTR_ICEN,d0
 	beq	mn10300_local_icache_inv_end
 
-	# invalidate
-	or	CHCTR_ICINV,d0
-	movhu	d0,(a0)
-	movhu	(a0),d0
+	invalidate_icache 1
 
 mn10300_local_icache_inv_end:
 	ret	[],0
@@ -87,11 +85,8 @@
 	btst	CHCTR_DCEN,d0
 	beq	mn10300_local_dcache_inv_end
 
-	# invalidate
-	or	CHCTR_DCINV,d0
-	movhu	d0,(a0)
-	movhu	(a0),d0
-
+	invalidate_dcache 1
+	
 mn10300_local_dcache_inv_end:
 	ret	[],0
 	.size	mn10300_local_dcache_inv,.-mn10300_local_dcache_inv
@@ -121,9 +116,9 @@
 	# and if they're not cacheline-aligned, we must flush any bits outside
 	# the range that share cachelines with stuff inside the range
 #ifdef CONFIG_MN10300_CACHE_WBACK
-	btst	~(L1_CACHE_BYTES-1),d0
+	btst	~L1_CACHE_TAG_MASK,d0
 	bne	1f
-	btst	~(L1_CACHE_BYTES-1),d1
+	btst	~L1_CACHE_TAG_MASK,d1
 	beq	2f
 1:
 	bra	mn10300_local_dcache_flush_inv_range
@@ -141,12 +136,11 @@
 	# writeback mode, in which case we would be in flush and invalidate by
 	# now
 #ifndef CONFIG_MN10300_CACHE_WBACK
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start
-								# addr down
+	and	L1_CACHE_TAG_MASK,d0	# round start addr down
 
 	mov	L1_CACHE_BYTES-1,d2
 	add	d2,d1
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1	# round end addr up
+	and	L1_CACHE_TAG_MASK,d1	# round end addr up
 #endif /* !CONFIG_MN10300_CACHE_WBACK */
 
 	sub	d0,d1,d2		# calculate the total size
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-inv-by-tag.S linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-inv-by-tag.S
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/cache-inv-by-tag.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/cache-inv-by-tag.S	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <asm/cache.h>
 #include <asm/irqflags.h>
 #include <asm/cacheflush.h>
+#include "cache.inc"
 
 #define mn10300_local_dcache_inv_range_intr_interval \
 	+((1 << MN10300_DCACHE_INV_RANGE_INTR_LOG2_INTERVAL) - 1)
@@ -70,43 +71,7 @@
 	btst	CHCTR_ICEN,d0
 	beq	mn10300_local_icache_inv_end
 
-#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
-	LOCAL_CLI_SAVE(d1)
-
-	# disable the icache
-	and	~CHCTR_ICEN,d0
-	movhu	d0,(a0)
-
-	# and wait for it to calm down
-	setlb
-	movhu	(a0),d0
-	btst	CHCTR_ICBUSY,d0
-	lne
-
-	# invalidate
-	or	CHCTR_ICINV,d0
-	movhu	d0,(a0)
-
-	# wait for the cache to finish
-	mov	CHCTR,a0
-	setlb
-	movhu	(a0),d0
-	btst	CHCTR_ICBUSY,d0
-	lne
-
-	# and reenable it
-	and	~CHCTR_ICINV,d0
-	or	CHCTR_ICEN,d0
-	movhu	d0,(a0)
-	movhu	(a0),d0
-
-	LOCAL_IRQ_RESTORE(d1)
-#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
-	# invalidate
-	or	CHCTR_ICINV,d0
-	movhu	d0,(a0)
-	movhu	(a0),d0
-#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+	invalidate_icache 1
 
 mn10300_local_icache_inv_end:
 	ret	[],0
@@ -128,43 +93,7 @@
 	btst	CHCTR_DCEN,d0
 	beq	mn10300_local_dcache_inv_end
 
-#if defined(CONFIG_AM33_2) || defined(CONFIG_AM33_3)
-	LOCAL_CLI_SAVE(d1)
-
-	# disable the dcache
-	and	~CHCTR_DCEN,d0
-	movhu	d0,(a0)
-
-	# and wait for it to calm down
-	setlb
-	movhu	(a0),d0
-	btst	CHCTR_DCBUSY,d0
-	lne
-
-	# invalidate
-	or	CHCTR_DCINV,d0
-	movhu	d0,(a0)
-
-	# wait for the cache to finish
-	mov	CHCTR,a0
-	setlb
-	movhu	(a0),d0
-	btst	CHCTR_DCBUSY,d0
-	lne
-
-	# and reenable it
-	and	~CHCTR_DCINV,d0
-	or	CHCTR_DCEN,d0
-	movhu	d0,(a0)
-	movhu	(a0),d0
-
-	LOCAL_IRQ_RESTORE(d1)
-#else /* CONFIG_AM33_2 || CONFIG_AM33_3 */
-	# invalidate
-	or	CHCTR_DCINV,d0
-	movhu	d0,(a0)
-	movhu	(a0),d0
-#endif /* CONFIG_AM33_2 || CONFIG_AM33_3 */
+	invalidate_dcache 1
 
 mn10300_local_dcache_inv_end:
 	ret	[],0
@@ -195,9 +124,9 @@
 	# and if they're not cacheline-aligned, we must flush any bits outside
 	# the range that share cachelines with stuff inside the range
 #ifdef CONFIG_MN10300_CACHE_WBACK
-	btst	~(L1_CACHE_BYTES-1),d0
+	btst	~L1_CACHE_TAG_MASK,d0
 	bne	1f
-	btst	~(L1_CACHE_BYTES-1),d1
+	btst	~L1_CACHE_TAG_MASK,d1
 	beq	2f
 1:
 	bra	mn10300_local_dcache_flush_inv_range
@@ -212,11 +141,10 @@
 	beq	mn10300_local_dcache_inv_range_end
 
 #ifndef CONFIG_MN10300_CACHE_WBACK
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d0	# round start
-								# addr down
+	and	L1_CACHE_TAG_MASK,d0		# round start addr down
 
 	add	L1_CACHE_BYTES,d1		# round end addr up
-	and	L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY,d1
+	and	L1_CACHE_TAG_MASK,d1
 #endif /* !CONFIG_MN10300_CACHE_WBACK */
 	mov	d0,a1
 
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/fault.c linux-libre-2.6.39-gnu/arch/mn10300/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,8 +28,9 @@
 #include <asm/uaccess.h>
 #include <asm/pgalloc.h>
 #include <asm/hardirq.h>
-#include <asm/gdb-stub.h>
 #include <asm/cpu-regs.h>
+#include <asm/debugger.h>
+#include <asm/gdb-stub.h>
 
 /*
  * Unlock any spinlocks which will prevent us from getting the
@@ -306,10 +307,8 @@
 	printk(" printing pc:\n");
 	printk(KERN_ALERT "%08lx\n", regs->pc);
 
-#ifdef CONFIG_GDBSTUB
-	gdbstub_intercept(
-		regs, fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR);
-#endif
+	debugger_intercept(fault_code & 0x00010000 ? EXCEP_IAERROR : EXCEP_DAERROR,
+			   SIGSEGV, SEGV_ACCERR, regs);
 
 	page = PTBR;
 	page = ((unsigned long *) __va(page))[address >> 22];
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/Kconfig.cache linux-libre-2.6.39-gnu/arch/mn10300/mm/Kconfig.cache
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/Kconfig.cache	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/Kconfig.cache	2011-05-19 00:06:34.000000000 -0400
@@ -99,3 +99,49 @@
 	help
 	  Set if we need the icache to be invalidated, even if the dcache is in
 	  write-through mode and doesn't need flushing.
+
+#
+# The kernel debugger gets its own separate cache flushing functions
+#
+config MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WBACK && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_TAG
+	help
+	  Set if the debugger needs to flush the dcache and invalidate the
+	  icache using the cache tag registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_FLUSH_BY_REG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WBACK && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_REG
+	help
+	  Set if the debugger needs to flush the dcache and invalidate the
+	  icache using automatic purge registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_INV_BY_TAG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WTHRU && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_TAG
+	help
+	  Set if the debugger needs to invalidate the icache using the cache
+	  tag registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_INV_BY_REG
+	def_bool y if KERNEL_DEBUGGER && \
+			MN10300_CACHE_WTHRU && \
+			!MN10300_CACHE_SNOOP && \
+			MN10300_CACHE_MANAGE_BY_REG
+	help
+	  Set if the debugger needs to invalidate the icache using automatic
+	  purge registers to make breakpoints work.
+
+config MN10300_DEBUGGER_CACHE_NO_FLUSH
+	def_bool y if KERNEL_DEBUGGER && \
+			(MN10300_CACHE_DISABLED || MN10300_CACHE_SNOOP)
+	help
+	  Set if the debugger does not need to flush the dcache and/or
+	  invalidate the icache to make breakpoints work.
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/mm/Makefile linux-libre-2.6.39-gnu/arch/mn10300/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/mn10300/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,15 @@
 cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_TAG) += cache-flush-by-tag.o
 cacheflush-$(CONFIG_MN10300_CACHE_FLUSH_BY_REG) += cache-flush-by-reg.o
 
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_TAG) += \
+	cache-dbg-flush-by-tag.o cache-dbg-inv-by-tag.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_FLUSH_BY_REG) += \
+	cache-dbg-flush-by-reg.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_TAG) += \
+	cache-dbg-inv-by-tag.o cache-dbg-inv.o
+cacheflush-$(CONFIG_MN10300_DEBUGGER_CACHE_INV_BY_REG) += \
+	cache-dbg-inv-by-reg.o cache-dbg-inv.o
+
 cacheflush-$(CONFIG_MN10300_CACHE_DISABLED) := cache-disabled.o
 
 obj-y := \
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/proc-mn103e010/include/proc/cache.h linux-libre-2.6.39-gnu/arch/mn10300/proc-mn103e010/include/proc/cache.h
--- linux-libre-2.6.38-gnu/arch/mn10300/proc-mn103e010/include/proc/cache.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/proc-mn103e010/include/proc/cache.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #define L1_CACHE_TAG_DIRTY	0x00000008	/* data cache tag dirty bit */
 #define L1_CACHE_TAG_ENTRY	0x00000ff0	/* cache tag entry address mask */
 #define L1_CACHE_TAG_ADDRESS	0xfffff000	/* cache tag line address mask */
+#define L1_CACHE_TAG_MASK	+(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
 
 /*
  * specification of the interval between interrupt checking intervals whilst
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/proc-mn2ws0050/include/proc/cache.h linux-libre-2.6.39-gnu/arch/mn10300/proc-mn2ws0050/include/proc/cache.h
--- linux-libre-2.6.38-gnu/arch/mn10300/proc-mn2ws0050/include/proc/cache.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/proc-mn2ws0050/include/proc/cache.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #define L1_CACHE_TAG_DIRTY	0x00000008	/* data cache tag dirty bit */
 #define L1_CACHE_TAG_ENTRY	0x00000fe0	/* cache tag entry address mask */
 #define L1_CACHE_TAG_ADDRESS	0xfffff000	/* cache tag line address mask */
+#define L1_CACHE_TAG_MASK	+(L1_CACHE_TAG_ADDRESS|L1_CACHE_TAG_ENTRY)
 
 /*
  * specification of the interval between interrupt checking intervals whilst
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h
--- linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/include/unit/fpga-regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 #define ASB2364_FPGA_REG_RESET_USB	__SYSREG(0xa900130c, u16)
 #define ASB2364_FPGA_REG_RESET_AV	__SYSREG(0xa9001310, u16)
 
-#define ASB2364_FPGA_REG_IRQ(X)		__SYSREG(0xa9001590+((X)*4), u16)
+#define ASB2364_FPGA_REG_IRQ(X)		__SYSREG(0xa9001510+((X)*4), u16)
 #define ASB2364_FPGA_REG_IRQ_LAN	ASB2364_FPGA_REG_IRQ(0)
 #define ASB2364_FPGA_REG_IRQ_UART	ASB2364_FPGA_REG_IRQ(1)
 #define ASB2364_FPGA_REG_IRQ_I2C	ASB2364_FPGA_REG_IRQ(2)
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/include/unit/serial.h linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/include/unit/serial.h
--- linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/include/unit/serial.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/include/unit/serial.h	2011-05-19 00:06:34.000000000 -0400
@@ -59,18 +59,18 @@
 #define SERIAL_PORT_DFNS /* stolen by gdb-stub */
 
 #if defined(CONFIG_GDBSTUB_ON_TTYS0)
-#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 4, u8)
-#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 4, u8)
-#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 4, u8)
-#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 4, u8)
-#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 4, u8)
-#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 4, u8)
-#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 4, u8)
-#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 4, u8)
-#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 4, u8)
-#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 4, u8)
-#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 4, u8)
-#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 4, u8)
+#define GDBPORT_SERIAL_RX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_RX  * 2, u8)
+#define GDBPORT_SERIAL_TX	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_TX  * 2, u8)
+#define GDBPORT_SERIAL_DLL	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLL * 2, u8)
+#define GDBPORT_SERIAL_DLM	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_DLM * 2, u8)
+#define GDBPORT_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define GDBPORT_SERIAL_IIR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IIR * 2, u8)
+#define GDBPORT_SERIAL_FCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_FCR * 2, u8)
+#define GDBPORT_SERIAL_LCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LCR * 2, u8)
+#define GDBPORT_SERIAL_MCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MCR * 2, u8)
+#define GDBPORT_SERIAL_LSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_LSR * 2, u8)
+#define GDBPORT_SERIAL_MSR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_MSR * 2, u8)
+#define GDBPORT_SERIAL_SCR	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_SCR * 2, u8)
 #define GDBPORT_SERIAL_IRQ	SERIAL_IRQ
 
 #elif defined(CONFIG_GDBSTUB_ON_TTYS1)
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/irq-fpga.c linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/irq-fpga.c
--- linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/irq-fpga.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/irq-fpga.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,38 +17,38 @@
 /*
  * FPGA PIC operations
  */
-static void asb2364_fpga_mask(unsigned int irq)
+static void asb2364_fpga_mask(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
 }
 
-static void asb2364_fpga_ack(unsigned int irq)
+static void asb2364_fpga_ack(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
 }
 
-static void asb2364_fpga_mask_ack(unsigned int irq)
+static void asb2364_fpga_mask_ack(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
-	ASB2364_FPGA_REG_IRQ(irq - NR_CPU_IRQS) = 0x0001;
+	ASB2364_FPGA_REG_IRQ(d->irq - NR_CPU_IRQS) = 0x0001;
 	SyncExBus();
 }
 
-static void asb2364_fpga_unmask(unsigned int irq)
+static void asb2364_fpga_unmask(struct irq_data *d)
 {
-	ASB2364_FPGA_REG_MASK(irq - NR_CPU_IRQS) = 0x0000;
+	ASB2364_FPGA_REG_MASK(d->irq - NR_CPU_IRQS) = 0x0000;
 	SyncExBus();
 }
 
 static struct irq_chip asb2364_fpga_pic = {
 	.name		= "fpga",
-	.ack		= asb2364_fpga_ack,
-	.mask		= asb2364_fpga_mask,
-	.mask_ack	= asb2364_fpga_mask_ack,
-	.unmask		= asb2364_fpga_unmask,
+	.irq_ack	= asb2364_fpga_ack,
+	.irq_mask	= asb2364_fpga_mask,
+	.irq_mask_ack	= asb2364_fpga_mask_ack,
+	.irq_unmask	= asb2364_fpga_unmask,
 };
 
 /*
@@ -88,8 +88,20 @@
 {
 	int irq;
 
+	ASB2364_FPGA_REG_MASK_LAN  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_UART = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_I2C  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_USB  = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_MASK_FPGA = 0x0001;
+	SyncExBus();
+
 	for (irq = NR_CPU_IRQS; irq < NR_IRQS; irq++)
-		set_irq_chip_and_handler(irq, &asb2364_fpga_pic, handle_level_irq);
+		irq_set_chip_and_handler(irq, &asb2364_fpga_pic,
+					 handle_level_irq);
 
 	/* the FPGA drives the XIRQ1 input on the CPU PIC */
 	setup_irq(XIRQ1, &fpga_irq[0]);
diff -druN linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/unit-init.c linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/unit-init.c
--- linux-libre-2.6.38-gnu/arch/mn10300/unit-asb2364/unit-init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/mn10300/unit-asb2364/unit-init.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,13 +20,41 @@
 #include <asm/processor.h>
 #include <asm/irq.h>
 #include <asm/intctl-regs.h>
+#include <asm/serial-regs.h>
 #include <unit/fpga-regs.h>
+#include <unit/serial.h>
+#include <unit/smsc911x.h>
+
+#define TTYS0_SERIAL_IER	__SYSREG(SERIAL_PORT0_BASE_ADDRESS + UART_IER * 2, u8)
+#define LAN_IRQ_CFG		__SYSREG(SMSC911X_BASE + 0x54, u32)
+#define LAN_INT_EN		__SYSREG(SMSC911X_BASE + 0x5c, u32)
 
 /*
  * initialise some of the unit hardware before gdbstub is set up
  */
 asmlinkage void __init unit_init(void)
 {
+	/* Make sure we aren't going to get unexpected interrupts */
+	TTYS0_SERIAL_IER = 0;
+	SC0RXICR = 0;
+	SC0TXICR = 0;
+	SC1RXICR = 0;
+	SC1TXICR = 0;
+	SC2RXICR = 0;
+	SC2TXICR = 0;
+
+	/* Attempt to reset the FPGA attached peripherals */
+	ASB2364_FPGA_REG_RESET_LAN = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_UART = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_I2C = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_USB = 0x0000;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_AV = 0x0000;
+	SyncExBus();
+
 	/* set up the external interrupts */
 
 	/* XIRQ[0]: NAND RXBY */
@@ -56,7 +84,23 @@
  */
 asmlinkage void __init unit_setup(void)
 {
+	/* Release the reset on the SMSC911X so that it is ready by the time we
+	 * need it */
+	ASB2364_FPGA_REG_RESET_LAN = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_UART = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_I2C = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_USB = 0x0001;
+	SyncExBus();
+	ASB2364_FPGA_REG_RESET_AV = 0x0001;
+	SyncExBus();
 
+	/* Make sure the ethernet chipset isn't going to give us an interrupt
+	 * storm from stuff it was doing pre-reset */
+	LAN_IRQ_CFG = 0;
+	LAN_INT_EN = 0;
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/parisc/hpux/sys_hpux.c linux-libre-2.6.39-gnu/arch/parisc/hpux/sys_hpux.c
--- linux-libre-2.6.38-gnu/arch/parisc/hpux/sys_hpux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/hpux/sys_hpux.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,26 +185,21 @@
      int16_t f_pad;
 };
 
-static int do_statfs_hpux(struct path *path, struct hpux_statfs *buf)
+static int do_statfs_hpux(struct kstatfs *st, struct hpux_statfs __user *p)
 {
-	struct kstatfs st;
-	int retval;
-	
-	retval = vfs_statfs(path, &st);
-	if (retval)
-		return retval;
-
-	memset(buf, 0, sizeof(*buf));
-	buf->f_type = st.f_type;
-	buf->f_bsize = st.f_bsize;
-	buf->f_blocks = st.f_blocks;
-	buf->f_bfree = st.f_bfree;
-	buf->f_bavail = st.f_bavail;
-	buf->f_files = st.f_files;
-	buf->f_ffree = st.f_ffree;
-	buf->f_fsid[0] = st.f_fsid.val[0];
-	buf->f_fsid[1] = st.f_fsid.val[1];
-
+	struct hpux_statfs buf;
+	memset(&buf, 0, sizeof(buf));
+	buf.f_type = st->f_type;
+	buf.f_bsize = st->f_bsize;
+	buf.f_blocks = st->f_blocks;
+	buf.f_bfree = st->f_bfree;
+	buf.f_bavail = st->f_bavail;
+	buf.f_files = st->f_files;
+	buf.f_ffree = st->f_ffree;
+	buf.f_fsid[0] = st->f_fsid.val[0];
+	buf.f_fsid[1] = st->f_fsid.val[1];
+	if (copy_to_user(p, &buf, sizeof(buf)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -212,35 +207,19 @@
 asmlinkage long hpux_statfs(const char __user *pathname,
 						struct hpux_statfs __user *buf)
 {
-	struct path path;
-	int error;
-
-	error = user_path(pathname, &path);
-	if (!error) {
-		struct hpux_statfs tmp;
-		error = do_statfs_hpux(&path, &tmp);
-		if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-			error = -EFAULT;
-		path_put(&path);
-	}
+	struct kstatfs st;
+	int error = user_statfs(pathname, &st);
+	if (!error)
+		error = do_statfs_hpux(&st, buf);
 	return error;
 }
 
 asmlinkage long hpux_fstatfs(unsigned int fd, struct hpux_statfs __user * buf)
 {
-	struct file *file;
-	struct hpux_statfs tmp;
-	int error;
-
-	error = -EBADF;
-	file = fget(fd);
-	if (!file)
-		goto out;
-	error = do_statfs_hpux(&file->f_path, &tmp);
-	if (!error && copy_to_user(buf, &tmp, sizeof(tmp)))
-		error = -EFAULT;
-	fput(file);
- out:
+	struct kstatfs st;
+	int error = fd_statfs(fd, &st);
+	if (!error)
+		error = do_statfs_hpux(&st, buf);
 	return error;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -222,7 +222,7 @@
 
 #ifdef __KERNEL__
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 /* '3' is bits per byte */
 #define LE_BYTE_ADDR ((sizeof(unsigned long) - 1) << 3)
@@ -234,6 +234,4 @@
 
 #endif	/* __KERNEL__ */
 
-#include <asm-generic/bitops/minix-le.h>
-
 #endif /* _PARISC_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,8 +26,6 @@
 void flush_kernel_dcache_range_asm(unsigned long, unsigned long);
 void flush_kernel_dcache_page_asm(void *);
 void flush_kernel_icache_page(void *);
-void flush_user_dcache_page(unsigned long);
-void flush_user_icache_page(unsigned long);
 void flush_user_dcache_range(unsigned long, unsigned long);
 void flush_user_icache_range(unsigned long, unsigned long);
 
@@ -37,6 +35,13 @@
 void flush_cache_all(void);
 void flush_cache_mm(struct mm_struct *mm);
 
+#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
+void flush_kernel_dcache_page_addr(void *addr);
+static inline void flush_kernel_dcache_page(struct page *page)
+{
+	flush_kernel_dcache_page_addr(page_address(page));
+}
+
 #define flush_kernel_dcache_range(start,size) \
 	flush_kernel_dcache_range_asm((start), (start)+(size));
 /* vmap range flushes and invalidates.  Architecturally, we don't need
@@ -50,6 +55,16 @@
 }
 static inline void invalidate_kernel_vmap_range(void *vaddr, int size)
 {
+	unsigned long start = (unsigned long)vaddr;
+	void *cursor = vaddr;
+
+	for ( ; cursor < vaddr + size; cursor += PAGE_SIZE) {
+		struct page *page = vmalloc_to_page(cursor);
+
+		if (test_and_clear_bit(PG_dcache_dirty, &page->flags))
+			flush_kernel_dcache_page(page);
+	}
+	flush_kernel_dcache_range_asm(start, start + size);
 }
 
 #define flush_cache_vmap(start, end)		flush_cache_all()
@@ -90,19 +105,15 @@
 void flush_cache_range(struct vm_area_struct *vma,
 		unsigned long start, unsigned long end);
 
+/* defined in pacache.S exported in cache.c used by flush_anon_page */
+void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+
 #define ARCH_HAS_FLUSH_ANON_PAGE
 static inline void
 flush_anon_page(struct vm_area_struct *vma, struct page *page, unsigned long vmaddr)
 {
 	if (PageAnon(page))
-		flush_user_dcache_page(vmaddr);
-}
-
-#define ARCH_HAS_FLUSH_KERNEL_DCACHE_PAGE
-void flush_kernel_dcache_page_addr(void *addr);
-static inline void flush_kernel_dcache_page(struct page *page)
-{
-	flush_kernel_dcache_page_addr(page_address(page));
+		flush_dcache_page_asm(page_to_phys(page), vmaddr);
 }
 
 #ifdef CONFIG_DEBUG_RODATA
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/eisa_eeprom.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/eisa_eeprom.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/eisa_eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/eisa_eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 	u_int8_t  ver_maj;
 	u_int8_t  ver_min;
 	u_int8_t  num_slots;        /* number of EISA slots in system */
-	u_int16_t csum;             /* checksum, I don't know how to calulate this */
+	u_int16_t csum;             /* checksum, I don't know how to calculate this */
 	u_int8_t  pad[10];
 } __attribute__ ((packed));
 
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/errno.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/errno.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/errno.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/errno.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,4 +122,6 @@
 
 #define	ERFKILL		256	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	257	/* Memory page has hardware error */
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/fcntl.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/fcntl.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/fcntl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/fcntl.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,8 @@
 #define O_NOFOLLOW	000000200 /* don't follow links */
 #define O_INVISIBLE	004000000 /* invisible I/O, for DMAPI/XDSM */
 
+#define O_PATH		020000000
+
 #define F_GETLK64	8
 #define F_SETLK64	9
 #define F_SETLKW64	10
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/futex.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
 #include <asm/errno.h>
 
 static inline int
-futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -51,10 +51,10 @@
 
 /* Non-atomic version */
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int err = 0;
-	int uval;
+	u32 val;
 
 	/* futex.c wants to do a cmpxchg_inatomic on kernel NULL, which is
 	 * our gateway page, and causes no end of trouble...
@@ -62,15 +62,15 @@
 	if (segment_eq(KERNEL_DS, get_fs()) && !uaddr)
 		return -EFAULT;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	err = get_user(uval, uaddr);
-	if (err) return -EFAULT;
-	if (uval == oldval)
-		err = put_user(newval, uaddr);
-	if (err) return -EFAULT;
-	return uval;
+	if (get_user(val, uaddr))
+		return -EFAULT;
+	if (val == oldval && put_user(newval, uaddr))
+		return -EFAULT;
+	*uval = val;
+	return 0;
 }
 
 #endif /*__KERNEL__*/
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -54,6 +54,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, int)  /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 #define FIONCLEX	0x5450  /* these numbers need to be adjusted. */
 #define FIOCLEX		0x5451
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/irq.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/irq.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,15 +32,10 @@
 }
 
 struct irq_chip;
+struct irq_data;
 
-/*
- * Some useful "we don't have to do anything here" handlers.  Should
- * probably be provided by the generic code.
- */
-void no_ack_irq(unsigned int irq);
-void no_end_irq(unsigned int irq);
-void cpu_ack_irq(unsigned int irq);
-void cpu_eoi_irq(unsigned int irq);
+void cpu_ack_irq(struct irq_data *d);
+void cpu_eoi_irq(struct irq_data *d);
 
 extern int txn_alloc_irq(unsigned int nbits);
 extern int txn_claim_irq(int);
@@ -49,7 +44,7 @@
 extern unsigned long txn_affinity_addr(unsigned int irq, int cpu);
 
 extern int cpu_claim_irq(unsigned int irq, struct irq_chip *, void *);
-extern int cpu_check_affinity(unsigned int irq, const struct cpumask *dest);
+extern int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest);
 
 /* soft power switch support (power.c) */
 extern struct tasklet_struct power_tasklet;
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -138,8 +138,7 @@
 #define _PAGE_NO_CACHE_BIT 24   /* (0x080) Uncached Page (U bit) */
 #define _PAGE_ACCESSED_BIT 23   /* (0x100) Software: Page Accessed */
 #define _PAGE_PRESENT_BIT  22   /* (0x200) Software: translation valid */
-#define _PAGE_FLUSH_BIT    21   /* (0x400) Software: translation valid */
-				/*             for cache flushing only */
+/* bit 21 was formerly the FLUSH bit but is now unused */
 #define _PAGE_USER_BIT     20   /* (0x800) Software: User accessible page */
 
 /* N.B. The bits are defined in terms of a 32 bit word above, so the */
@@ -173,7 +172,6 @@
 #define _PAGE_NO_CACHE (1 << xlate_pabit(_PAGE_NO_CACHE_BIT))
 #define _PAGE_ACCESSED (1 << xlate_pabit(_PAGE_ACCESSED_BIT))
 #define _PAGE_PRESENT  (1 << xlate_pabit(_PAGE_PRESENT_BIT))
-#define _PAGE_FLUSH    (1 << xlate_pabit(_PAGE_FLUSH_BIT))
 #define _PAGE_USER     (1 << xlate_pabit(_PAGE_USER_BIT))
 #define _PAGE_FILE     (1 << xlate_pabit(_PAGE_FILE_BIT))
 
@@ -213,7 +211,6 @@
 #define PAGE_KERNEL_RO	__pgprot(_PAGE_KERNEL & ~_PAGE_WRITE)
 #define PAGE_KERNEL_UNC	__pgprot(_PAGE_KERNEL | _PAGE_NO_CACHE)
 #define PAGE_GATEWAY    __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_GATEWAY| _PAGE_READ)
-#define PAGE_FLUSH      __pgprot(_PAGE_FLUSH)
 
 
 /*
@@ -261,7 +258,7 @@
 
 #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
 
-#define pte_none(x)     ((pte_val(x) == 0) || (pte_val(x) & _PAGE_FLUSH))
+#define pte_none(x)     (pte_val(x) == 0)
 #define pte_present(x)	(pte_val(x) & _PAGE_PRESENT)
 #define pte_clear(mm,addr,xp)	do { pte_val(*(xp)) = 0; } while (0)
 
@@ -444,13 +441,10 @@
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
 {
 	pte_t old_pte;
-	pte_t pte;
 
 	spin_lock(&pa_dbit_lock);
-	pte = old_pte = *ptep;
-	pte_val(pte) &= ~_PAGE_PRESENT;
-	pte_val(pte) |= _PAGE_FLUSH;
-	set_pte_at(mm,addr,ptep,pte);
+	old_pte = *ptep;
+	pte_clear(mm,addr,ptep);
 	spin_unlock(&pa_dbit_lock);
 
 	return old_pte;
diff -druN linux-libre-2.6.38-gnu/arch/parisc/include/asm/types.h linux-libre-2.6.39-gnu/arch/parisc/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/parisc/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,20 +9,4 @@
 
 #endif /* __ASSEMBLY__ */
 
-/*
- * These aren't exported outside the kernel to avoid name space clashes
- */
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-typedef u64 dma64_addr_t;
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/parisc/Kconfig linux-libre-2.6.39-gnu/arch/parisc/Kconfig
--- linux-libre-2.6.38-gnu/arch/parisc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_BUG
 	bool
 	default y
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/cache.c linux-libre-2.6.39-gnu/arch/parisc/kernel/cache.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/cache.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/cache.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,12 +27,17 @@
 #include <asm/pgalloc.h>
 #include <asm/processor.h>
 #include <asm/sections.h>
+#include <asm/shmparam.h>
 
 int split_tlb __read_mostly;
 int dcache_stride __read_mostly;
 int icache_stride __read_mostly;
 EXPORT_SYMBOL(dcache_stride);
 
+void flush_dcache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+EXPORT_SYMBOL(flush_dcache_page_asm);
+void flush_icache_page_asm(unsigned long phys_addr, unsigned long vaddr);
+
 
 /* On some machines (e.g. ones with the Merced bus), there can be
  * only a single PxTLB broadcast at a time; this must be guaranteed
@@ -259,81 +264,13 @@
 		panic("SpaceID hashing is still on!\n");
 }
 
-/* Simple function to work out if we have an existing address translation
- * for a user space vma. */
-static inline int translation_exists(struct vm_area_struct *vma,
-				unsigned long addr, unsigned long pfn)
-{
-	pgd_t *pgd = pgd_offset(vma->vm_mm, addr);
-	pmd_t *pmd;
-	pte_t pte;
-
-	if(pgd_none(*pgd))
-		return 0;
-
-	pmd = pmd_offset(pgd, addr);
-	if(pmd_none(*pmd) || pmd_bad(*pmd))
-		return 0;
-
-	/* We cannot take the pte lock here: flush_cache_page is usually
-	 * called with pte lock already held.  Whereas flush_dcache_page
-	 * takes flush_dcache_mmap_lock, which is lower in the hierarchy:
-	 * the vma itself is secure, but the pte might come or go racily.
-	 */
-	pte = *pte_offset_map(pmd, addr);
-	/* But pte_unmap() does nothing on this architecture */
-
-	/* Filter out coincidental file entries and swap entries */
-	if (!(pte_val(pte) & (_PAGE_FLUSH|_PAGE_PRESENT)))
-		return 0;
-
-	return pte_pfn(pte) == pfn;
-}
-
-/* Private function to flush a page from the cache of a non-current
- * process.  cr25 contains the Page Directory of the current user
- * process; we're going to hijack both it and the user space %sr3 to
- * temporarily make the non-current process current.  We have to do
- * this because cache flushing may cause a non-access tlb miss which
- * the handlers have to fill in from the pgd of the non-current
- * process. */
 static inline void
-flush_user_cache_page_non_current(struct vm_area_struct *vma,
-				  unsigned long vmaddr)
-{
-	/* save the current process space and pgd */
-	unsigned long space = mfsp(3), pgd = mfctl(25);
-
-	/* we don't mind taking interrupts since they may not
-	 * do anything with user space, but we can't
-	 * be preempted here */
-	preempt_disable();
-
-	/* make us current */
-	mtctl(__pa(vma->vm_mm->pgd), 25);
-	mtsp(vma->vm_mm->context, 3);
-
-	flush_user_dcache_page(vmaddr);
-	if(vma->vm_flags & VM_EXEC)
-		flush_user_icache_page(vmaddr);
-
-	/* put the old current process back */
-	mtsp(space, 3);
-	mtctl(pgd, 25);
-	preempt_enable();
-}
-
-
-static inline void
-__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr)
+__flush_cache_page(struct vm_area_struct *vma, unsigned long vmaddr,
+		   unsigned long physaddr)
 {
-	if (likely(vma->vm_mm->context == mfsp(3))) {
-		flush_user_dcache_page(vmaddr);
-		if (vma->vm_flags & VM_EXEC)
-			flush_user_icache_page(vmaddr);
-	} else {
-		flush_user_cache_page_non_current(vma, vmaddr);
-	}
+	flush_dcache_page_asm(physaddr, vmaddr);
+	if (vma->vm_flags & VM_EXEC)
+		flush_icache_page_asm(physaddr, vmaddr);
 }
 
 void flush_dcache_page(struct page *page)
@@ -342,10 +279,8 @@
 	struct vm_area_struct *mpnt;
 	struct prio_tree_iter iter;
 	unsigned long offset;
-	unsigned long addr;
+	unsigned long addr, old_addr = 0;
 	pgoff_t pgoff;
-	unsigned long pfn = page_to_pfn(page);
-
 
 	if (mapping && !mapping_mapped(mapping)) {
 		set_bit(PG_dcache_dirty, &page->flags);
@@ -369,20 +304,11 @@
 		offset = (pgoff - mpnt->vm_pgoff) << PAGE_SHIFT;
 		addr = mpnt->vm_start + offset;
 
-		/* Flush instructions produce non access tlb misses.
-		 * On PA, we nullify these instructions rather than
-		 * taking a page fault if the pte doesn't exist.
-		 * This is just for speed.  If the page translation
-		 * isn't there, there's no point exciting the
-		 * nadtlb handler into a nullification frenzy.
-		 *
-		 * Make sure we really have this page: the private
-		 * mappings may cover this area but have COW'd this
-		 * particular page.
-		 */
-  		if (translation_exists(mpnt, addr, pfn)) {
-			__flush_cache_page(mpnt, addr);
-			break;
+		if (old_addr == 0 || (old_addr & (SHMLBA - 1)) != (addr & (SHMLBA - 1))) {
+			__flush_cache_page(mpnt, addr, page_to_phys(page));
+			if (old_addr)
+				printk(KERN_ERR "INEQUIVALENT ALIASES 0x%lx and 0x%lx in file %s\n", old_addr, addr, mpnt->vm_file ? mpnt->vm_file->f_path.dentry->d_name.name : "(null)");
+			old_addr = addr;
 		}
 	}
 	flush_dcache_mmap_unlock(mapping);
@@ -573,7 +499,6 @@
 {
 	BUG_ON(!vma->vm_mm->context);
 
-	if (likely(translation_exists(vma, vmaddr, pfn)))
-		__flush_cache_page(vma, vmaddr);
+	__flush_cache_page(vma, vmaddr, page_to_phys(pfn_to_page(pfn)));
 
 }
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/entry.S linux-libre-2.6.39-gnu/arch/parisc/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -187,8 +187,8 @@
 
 	/* Register definitions for tlb miss handler macros */
 
-	va  = r8	/* virtual address for which the trap occured */
-	spc = r24	/* space for which the trap occured */
+	va  = r8	/* virtual address for which the trap occurred */
+	spc = r24	/* space for which the trap occurred */
 
 #ifndef CONFIG_64BIT
 
@@ -225,22 +225,13 @@
 #ifndef CONFIG_64BIT
 	/*
 	 * naitlb miss interruption handler (parisc 1.1 - 32 bit)
-	 *
-	 * Note: naitlb misses will be treated
-	 * as an ordinary itlb miss for now.
-	 * However, note that naitlb misses
-	 * have the faulting address in the
-	 * IOR/ISR.
 	 */
 
 	.macro	naitlb_11 code
 
 	mfctl	%isr,spc
-	b	itlb_miss_11
+	b	naitlb_miss_11
 	mfctl 	%ior,va
-	/* FIXME: If user causes a naitlb miss, the priv level may not be in
-	 * lower bits of va, where the itlb miss handler is expecting them
-	 */
 
 	.align		32
 	.endm
@@ -248,26 +239,17 @@
 	
 	/*
 	 * naitlb miss interruption handler (parisc 2.0)
-	 *
-	 * Note: naitlb misses will be treated
-	 * as an ordinary itlb miss for now.
-	 * However, note that naitlb misses
-	 * have the faulting address in the
-	 * IOR/ISR.
 	 */
 
 	.macro	naitlb_20 code
 
 	mfctl	%isr,spc
 #ifdef CONFIG_64BIT
-	b       itlb_miss_20w
+	b       naitlb_miss_20w
 #else
-	b	itlb_miss_20
+	b	naitlb_miss_20
 #endif
 	mfctl 	%ior,va
-	/* FIXME: If user causes a naitlb miss, the priv level may not be in
-	 * lower bits of va, where the itlb miss handler is expecting them
-	 */
 
 	.align		32
 	.endm
@@ -581,7 +563,24 @@
 	copy		\va,\tmp1
 	depi		0,31,23,\tmp1
 	cmpb,COND(<>),n	\tmp,\tmp1,\fault
-	ldi		(_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),\prot
+	mfctl		%cr19,\tmp	/* iir */
+	/* get the opcode (first six bits) into \tmp */
+	extrw,u		\tmp,5,6,\tmp
+	/*
+	 * Only setting the T bit prevents data cache movein
+	 * Setting access rights to zero prevents instruction cache movein
+	 *
+	 * Note subtlety here: _PAGE_GATEWAY, _PAGE_EXEC and _PAGE_WRITE go
+	 * to type field and _PAGE_READ goes to top bit of PL1
+	 */
+	ldi		(_PAGE_REFTRAP|_PAGE_READ|_PAGE_WRITE),\prot
+	/*
+	 * so if the opcode is one (i.e. this is a memory management
+	 * instruction) nullify the next load so \prot is only T.
+	 * Otherwise this is a normal data operation
+	 */
+	cmpiclr,=	0x01,\tmp,%r0
+	ldi		(_PAGE_DIRTY|_PAGE_READ|_PAGE_WRITE),\prot
 	depd,z		\prot,8,7,\prot
 	/*
 	 * OK, it is in the temp alias region, check whether "from" or "to".
@@ -631,11 +630,7 @@
 	def		13
 	def		14
 	dtlb_20		15
-#if 0
 	naitlb_20	16
-#else
-	def             16
-#endif
 	nadtlb_20	17
 	def		18
 	def		19
@@ -678,11 +673,7 @@
 	def		13
 	def		14
 	dtlb_11		15
-#if 0
 	naitlb_11	16
-#else
-	def             16
-#endif
 	nadtlb_11	17
 	def		18
 	def		19
@@ -891,7 +882,7 @@
 	 * (we don't store them in the sigcontext), so set them
 	 * to "proper" values now (otherwise we'll wind up restoring
 	 * whatever was last stored in the task structure, which might
-	 * be inconsistent if an interrupt occured while on the gateway
+	 * be inconsistent if an interrupt occurred while on the gateway
 	 * page). Note that we may be "trashing" values the user put in
 	 * them, but we don't support the user changing them.
 	 */
@@ -1165,11 +1156,11 @@
 	 */
 
 	t0 = r1		/* temporary register 0 */
-	va = r8		/* virtual address for which the trap occured */
+	va = r8		/* virtual address for which the trap occurred */
 	t1 = r9		/* temporary register 1 */
 	pte  = r16	/* pte/phys page # */
 	prot = r17	/* prot bits */
-	spc  = r24	/* space for which the trap occured */
+	spc  = r24	/* space for which the trap occurred */
 	ptp = r25	/* page directory/page table pointer */
 
 #ifdef CONFIG_64BIT
@@ -1203,7 +1194,7 @@
 	get_pgd		spc,ptp
 	space_check	spc,t0,nadtlb_fault
 
-	L3_ptep		ptp,pte,t0,va,nadtlb_check_flush_20w
+	L3_ptep		ptp,pte,t0,va,nadtlb_check_alias_20w
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1214,16 +1205,8 @@
 	rfir
 	nop
 
-nadtlb_check_flush_20w:
-	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-	/* Insert a "flush only" translation */
-
-	depdi,z         7,7,3,prot
-	depdi           1,10,1,prot
-
-	/* Drop prot bits from pte and convert to page addr for idtlbt */
-	convert_for_tlb_insert20 pte
+nadtlb_check_alias_20w:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_emulate
 
 	idtlbt          pte,prot
 
@@ -1255,25 +1238,7 @@
 	nop
 
 dtlb_check_alias_11:
-
-	/* Check to see if fault is in the temporary alias region */
-
-	cmpib,<>,n      0,spc,dtlb_fault /* forward */
-	ldil            L%(TMPALIAS_MAP_START),t0
-	copy            va,t1
-	depwi           0,31,23,t1
-	cmpb,<>,n       t0,t1,dtlb_fault /* forward */
-	ldi             (_PAGE_DIRTY|_PAGE_WRITE|_PAGE_READ),prot
-	depw,z          prot,8,7,prot
-
-	/*
-	 * OK, it is in the temp alias region, check whether "from" or "to".
-	 * Check "subtle" note in pacache.S re: r23/r26.
-	 */
-
-	extrw,u,=       va,9,1,r0
-	or,tr           %r23,%r0,pte    /* If "from" use "from" page */
-	or              %r26,%r0,pte    /* else "to", use "to" page  */
+	do_alias	spc,t0,t1,va,pte,prot,dtlb_fault
 
 	idtlba          pte,(va)
 	idtlbp          prot,(va)
@@ -1286,7 +1251,7 @@
 
 	space_check	spc,t0,nadtlb_fault
 
-	L2_ptep		ptp,pte,t0,va,nadtlb_check_flush_11
+	L2_ptep		ptp,pte,t0,va,nadtlb_check_alias_11
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1304,26 +1269,11 @@
 	rfir
 	nop
 
-nadtlb_check_flush_11:
-	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-	/* Insert a "flush only" translation */
-
-	zdepi           7,7,3,prot
-	depi            1,10,1,prot
-
-	/* Get rid of prot bits and convert to page addr for idtlba */
-
-	depi		0,31,ASM_PFN_PTE_SHIFT,pte
-	SHRREG		pte,(ASM_PFN_PTE_SHIFT-(31-26)),pte
-
-	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
-	mtsp		spc,%sr1
-
-	idtlba		pte,(%sr1,va)
-	idtlbp		prot,(%sr1,va)
+nadtlb_check_alias_11:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_emulate
 
-	mtsp		t0, %sr1	/* Restore sr1 */
+	idtlba          pte,(va)
+	idtlbp          prot,(va)
 
 	rfir
 	nop
@@ -1359,7 +1309,7 @@
 
 	space_check	spc,t0,nadtlb_fault
 
-	L2_ptep		ptp,pte,t0,va,nadtlb_check_flush_20
+	L2_ptep		ptp,pte,t0,va,nadtlb_check_alias_20
 
 	update_ptep	ptp,pte,t0,t1
 
@@ -1372,21 +1322,14 @@
 	rfir
 	nop
 
-nadtlb_check_flush_20:
-	bb,>=,n          pte,_PAGE_FLUSH_BIT,nadtlb_emulate
-
-	/* Insert a "flush only" translation */
-
-	depdi,z         7,7,3,prot
-	depdi           1,10,1,prot
-
-	/* Drop prot bits from pte and convert to page addr for idtlbt */
-	convert_for_tlb_insert20 pte
+nadtlb_check_alias_20:
+	do_alias	spc,t0,t1,va,pte,prot,nadtlb_emulate
 
 	idtlbt          pte,prot
 
 	rfir
 	nop
+
 #endif
 
 nadtlb_emulate:
@@ -1484,6 +1427,36 @@
 	rfir
 	nop
 
+naitlb_miss_20w:
+
+	/*
+	 * I miss is a little different, since we allow users to fault
+	 * on the gateway page which is in the kernel address space.
+	 */
+
+	space_adjust	spc,va,t0
+	get_pgd		spc,ptp
+	space_check	spc,t0,naitlb_fault
+
+	L3_ptep		ptp,pte,t0,va,naitlb_check_alias_20w
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb	spc,pte,prot
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
+naitlb_check_alias_20w:
+	do_alias	spc,t0,t1,va,pte,prot,naitlb_fault
+
+	iitlbt		pte,prot
+
+	rfir
+	nop
+
 #else
 
 itlb_miss_11:
@@ -1508,6 +1481,38 @@
 	rfir
 	nop
 
+naitlb_miss_11:
+	get_pgd		spc,ptp
+
+	space_check	spc,t0,naitlb_fault
+
+	L2_ptep		ptp,pte,t0,va,naitlb_check_alias_11
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb_11	spc,pte,prot
+
+	mfsp		%sr1,t0  /* Save sr1 so we can use it in tlb inserts */
+	mtsp		spc,%sr1
+
+	iitlba		pte,(%sr1,va)
+	iitlbp		prot,(%sr1,va)
+
+	mtsp		t0, %sr1	/* Restore sr1 */
+
+	rfir
+	nop
+
+naitlb_check_alias_11:
+	do_alias	spc,t0,t1,va,pte,prot,itlb_fault
+
+	iitlba          pte,(%sr0, va)
+	iitlbp          prot,(%sr0, va)
+
+	rfir
+	nop
+
+
 itlb_miss_20:
 	get_pgd		spc,ptp
 
@@ -1526,6 +1531,32 @@
 	rfir
 	nop
 
+naitlb_miss_20:
+	get_pgd		spc,ptp
+
+	space_check	spc,t0,naitlb_fault
+
+	L2_ptep		ptp,pte,t0,va,naitlb_check_alias_20
+
+	update_ptep	ptp,pte,t0,t1
+
+	make_insert_tlb	spc,pte,prot
+
+	f_extend	pte,t0
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
+naitlb_check_alias_20:
+	do_alias	spc,t0,t1,va,pte,prot,naitlb_fault
+
+	iitlbt          pte,prot
+
+	rfir
+	nop
+
 #endif
 
 #ifdef CONFIG_64BIT
@@ -1662,6 +1693,10 @@
 	b               intr_save
 	ldi             17,%r8
 
+naitlb_fault:
+	b               intr_save
+	ldi             16,%r8
+
 dtlb_fault:
 	b               intr_save
 	ldi             15,%r8
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/head.S linux-libre-2.6.39-gnu/arch/parisc/kernel/head.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -131,7 +131,7 @@
 	ldo             THREAD_SZ_ALGN(%r6),%sp
 
 #ifdef CONFIG_SMP
-	/* Set the smp rendevous address into page zero.
+	/* Set the smp rendezvous address into page zero.
 	** It would be safer to do this in init_smp_config() but
 	** it's just way easier to deal with here because
 	** of 64-bit function ptrs and the address is local to this file.
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/inventory.c linux-libre-2.6.39-gnu/arch/parisc/kernel/inventory.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/inventory.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/inventory.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 	case 0x6:		/* 705, 710 */
 	case 0x7:		/* 715, 725 */
 	case 0x8:		/* 745, 747, 742 */
-	case 0xA:		/* 712 and similiar */
+	case 0xA:		/* 712 and similar */
 	case 0xC:		/* 715/64, at least */
 
 		pdc_type = PDC_TYPE_SNAKE;
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/irq.c linux-libre-2.6.39-gnu/arch/parisc/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,9 +52,9 @@
 */
 static DEFINE_PER_CPU(unsigned long, local_ack_eiem) = ~0UL;
 
-static void cpu_mask_irq(unsigned int irq)
+static void cpu_mask_irq(struct irq_data *d)
 {
-	unsigned long eirr_bit = EIEM_MASK(irq);
+	unsigned long eirr_bit = EIEM_MASK(d->irq);
 
 	cpu_eiem &= ~eirr_bit;
 	/* Do nothing on the other CPUs.  If they get this interrupt,
@@ -63,7 +63,7 @@
 	 * then gets disabled */
 }
 
-static void cpu_unmask_irq(unsigned int irq)
+static void __cpu_unmask_irq(unsigned int irq)
 {
 	unsigned long eirr_bit = EIEM_MASK(irq);
 
@@ -75,9 +75,14 @@
 	smp_send_all_nop();
 }
 
-void cpu_ack_irq(unsigned int irq)
+static void cpu_unmask_irq(struct irq_data *d)
 {
-	unsigned long mask = EIEM_MASK(irq);
+	__cpu_unmask_irq(d->irq);
+}
+
+void cpu_ack_irq(struct irq_data *d)
+{
+	unsigned long mask = EIEM_MASK(d->irq);
 	int cpu = smp_processor_id();
 
 	/* Clear in EIEM so we can no longer process */
@@ -90,9 +95,9 @@
 	mtctl(mask, 23);
 }
 
-void cpu_eoi_irq(unsigned int irq)
+void cpu_eoi_irq(struct irq_data *d)
 {
-	unsigned long mask = EIEM_MASK(irq);
+	unsigned long mask = EIEM_MASK(d->irq);
 	int cpu = smp_processor_id();
 
 	/* set it in the eiems---it's no longer in process */
@@ -103,17 +108,13 @@
 }
 
 #ifdef CONFIG_SMP
-int cpu_check_affinity(unsigned int irq, const struct cpumask *dest)
+int cpu_check_affinity(struct irq_data *d, const struct cpumask *dest)
 {
 	int cpu_dest;
 
 	/* timer and ipi have to always be received on all CPUs */
-	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);
+	if (irqd_is_per_cpu(d))
 		return -EINVAL;
-	}
 
 	/* whatever mask they set, we just allow one CPU */
 	cpu_dest = first_cpu(*dest);
@@ -121,33 +122,34 @@
 	return cpu_dest;
 }
 
-static int cpu_set_affinity_irq(unsigned int irq, const struct cpumask *dest)
+static int cpu_set_affinity_irq(struct irq_data *d, const struct cpumask *dest,
+				bool force)
 {
 	int cpu_dest;
 
-	cpu_dest = cpu_check_affinity(irq, dest);
+	cpu_dest = cpu_check_affinity(d, dest);
 	if (cpu_dest < 0)
 		return -1;
 
-	cpumask_copy(irq_desc[irq].affinity, dest);
+	cpumask_copy(d->affinity, dest);
 
 	return 0;
 }
 #endif
 
 static struct irq_chip cpu_interrupt_type = {
-	.name		= "CPU",
-	.mask		= cpu_mask_irq,
-	.unmask		= cpu_unmask_irq,
-	.ack		= cpu_ack_irq,
-	.eoi		= cpu_eoi_irq,
+	.name			= "CPU",
+	.irq_mask		= cpu_mask_irq,
+	.irq_unmask		= cpu_unmask_irq,
+	.irq_ack		= cpu_ack_irq,
+	.irq_eoi		= cpu_eoi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity	= cpu_set_affinity_irq,
+	.irq_set_affinity	= cpu_set_affinity_irq,
 #endif
 	/* XXX: Needs to be written.  We managed without it so far, but
 	 * we really ought to write it.
 	 */
-	.retrigger	= NULL,
+	.irq_retrigger	= NULL,
 };
 
 int show_interrupts(struct seq_file *p, void *v)
@@ -167,10 +169,11 @@
 	}
 
 	if (i < NR_IRQS) {
+		struct irq_desc *desc = irq_to_desc(i);
 		struct irqaction *action;
 
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		action = desc->action;
 		if (!action)
 			goto skip;
 		seq_printf(p, "%3d: ", i);
@@ -181,7 +184,7 @@
 		seq_printf(p, "%10u ", kstat_irqs(i));
 #endif
 
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
+		seq_printf(p, " %14s", irq_desc_get_chip(desc)->name);
 #ifndef PARISC_IRQ_CR16_COUNTS
 		seq_printf(p, "  %s", action->name);
 
@@ -213,7 +216,7 @@
 
 		seq_putc(p, '\n');
  skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
 
 	return 0;
@@ -231,16 +234,16 @@
 
 int cpu_claim_irq(unsigned int irq, struct irq_chip *type, void *data)
 {
-	if (irq_desc[irq].action)
+	if (irq_has_action(irq))
 		return -EBUSY;
-	if (irq_desc[irq].chip != &cpu_interrupt_type)
+	if (irq_get_chip(irq) != &cpu_interrupt_type)
 		return -EBUSY;
 
 	/* for iosapic interrupts */
 	if (type) {
-		set_irq_chip_and_handler(irq, type, handle_percpu_irq);
-		set_irq_chip_data(irq, data);
-		cpu_unmask_irq(irq);
+		irq_set_chip_and_handler(irq, type, handle_percpu_irq);
+		irq_set_chip_data(irq, data);
+		__cpu_unmask_irq(irq);
 	}
 	return 0;
 }
@@ -289,7 +292,8 @@
 unsigned long txn_affinity_addr(unsigned int irq, int cpu)
 {
 #ifdef CONFIG_SMP
-	cpumask_copy(irq_desc[irq].affinity, cpumask_of(cpu));
+	struct irq_data *d = irq_get_irq_data(irq);
+	cpumask_copy(d->affinity, cpumask_of(cpu));
 #endif
 
 	return per_cpu(cpu_data, cpu).txn_addr;
@@ -333,6 +337,7 @@
 	unsigned long eirr_val;
 	int irq, cpu = smp_processor_id();
 #ifdef CONFIG_SMP
+	struct irq_desc *desc;
 	cpumask_t dest;
 #endif
 
@@ -346,8 +351,9 @@
 	irq = eirr_to_irq(eirr_val);
 
 #ifdef CONFIG_SMP
-	cpumask_copy(&dest, irq_desc[irq].affinity);
-	if (CHECK_IRQ_PER_CPU(irq_desc[irq].status) &&
+	desc = irq_to_desc(irq);
+	cpumask_copy(&dest, desc->irq_data.affinity);
+	if (irqd_is_per_cpu(&desc->irq_data) &&
 	    !cpu_isset(smp_processor_id(), dest)) {
 		int cpu = first_cpu(dest);
 
@@ -388,14 +394,14 @@
 {
 	int i;
 	for (i = CPU_IRQ_BASE; i <= CPU_IRQ_MAX; i++) {
-		set_irq_chip_and_handler(i, &cpu_interrupt_type,
+		irq_set_chip_and_handler(i, &cpu_interrupt_type,
 					 handle_percpu_irq);
 	}
 
-	set_irq_handler(TIMER_IRQ, handle_percpu_irq);
+	irq_set_handler(TIMER_IRQ, handle_percpu_irq);
 	setup_irq(TIMER_IRQ, &timer_action);
 #ifdef CONFIG_SMP
-	set_irq_handler(IPI_IRQ, handle_percpu_irq);
+	irq_set_handler(IPI_IRQ, handle_percpu_irq);
 	setup_irq(IPI_IRQ, &ipi_action);
 #endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/pacache.S linux-libre-2.6.39-gnu/arch/parisc/kernel/pacache.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/pacache.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/pacache.S	2011-05-19 00:06:34.000000000 -0400
@@ -608,93 +608,131 @@
 	.procend
 ENDPROC(__clear_user_page_asm)
 
-ENTRY(flush_kernel_dcache_page_asm)
+ENTRY(flush_dcache_page_asm)
 	.proc
 	.callinfo NO_CALLS
 	.entry
 
+	ldil		L%(TMPALIAS_MAP_START), %r28
+#ifdef CONFIG_64BIT
+#if (TMPALIAS_MAP_START >= 0x80000000)
+	depdi		0, 31,32, %r28		/* clear any sign extension */
+	/* FIXME: page size dependend */
+#endif
+	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
+	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
+#else
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
+#endif
+
+	/* Purge any old translation */
+
+	pdtlb		0(%r28)
+
 	ldil		L%dcache_stride, %r1
-	ldw		R%dcache_stride(%r1), %r23
+	ldw		R%dcache_stride(%r1), %r1
 
 #ifdef CONFIG_64BIT
 	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
 	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add		%r26, %r25, %r25
-	sub		%r25, %r23, %r25
+	add		%r28, %r25, %r25
+	sub		%r25, %r1, %r25
 
 
-1:      fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	fdc,m		%r23(%r26)
-	cmpb,COND(<<)		%r26, %r25,1b
-	fdc,m		%r23(%r26)
+1:      fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	fdc,m		%r1(%r28)
+	cmpb,COND(<<)		%r28, %r25,1b
+	fdc,m		%r1(%r28)
 
 	sync
 	bv		%r0(%r2)
-	nop
+	pdtlb		(%r25)
 	.exit
 
 	.procend
-ENDPROC(flush_kernel_dcache_page_asm)
-	
-ENTRY(flush_user_dcache_page)
+ENDPROC(flush_dcache_page_asm)
+
+ENTRY(flush_icache_page_asm)
 	.proc
 	.callinfo NO_CALLS
 	.entry
 
-	ldil		L%dcache_stride, %r1
-	ldw		R%dcache_stride(%r1), %r23
+	ldil		L%(TMPALIAS_MAP_START), %r28
+#ifdef CONFIG_64BIT
+#if (TMPALIAS_MAP_START >= 0x80000000)
+	depdi		0, 31,32, %r28		/* clear any sign extension */
+	/* FIXME: page size dependend */
+#endif
+	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
+	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
+	depdi		0, 63,12, %r28		/* Clear any offset bits */
+#else
+	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
+	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
+	depwi		0, 31,12, %r28		/* Clear any offset bits */
+#endif
+
+	/* Purge any old translation */
+
+	pitlb		(%sr0,%r28)
+
+	ldil		L%icache_stride, %r1
+	ldw		R%icache_stride(%r1), %r1
 
 #ifdef CONFIG_64BIT
-	depdi,z		1,63-PAGE_SHIFT,1, %r25
+	depdi,z		1, 63-PAGE_SHIFT,1, %r25
 #else
-	depwi,z		1,31-PAGE_SHIFT,1, %r25
+	depwi,z		1, 31-PAGE_SHIFT,1, %r25
 #endif
-	add		%r26, %r25, %r25
-	sub		%r25, %r23, %r25
+	add		%r28, %r25, %r25
+	sub		%r25, %r1, %r25
 
 
-1:      fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	fdc,m		%r23(%sr3, %r26)
-	cmpb,COND(<<)		%r26, %r25,1b
-	fdc,m		%r23(%sr3, %r26)
+1:      fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	fic,m		%r1(%r28)
+	cmpb,COND(<<)		%r28, %r25,1b
+	fic,m		%r1(%r28)
 
 	sync
 	bv		%r0(%r2)
-	nop
+	pitlb		(%sr0,%r25)
 	.exit
 
 	.procend
-ENDPROC(flush_user_dcache_page)
+ENDPROC(flush_icache_page_asm)
 
-ENTRY(flush_user_icache_page)
+ENTRY(flush_kernel_dcache_page_asm)
 	.proc
 	.callinfo NO_CALLS
 	.entry
@@ -711,23 +749,23 @@
 	sub		%r25, %r23, %r25
 
 
-1:      fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
-	fic,m		%r23(%sr3, %r26)
+1:      fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
+	fdc,m		%r23(%r26)
 	cmpb,COND(<<)		%r26, %r25,1b
-	fic,m		%r23(%sr3, %r26)
+	fdc,m		%r23(%r26)
 
 	sync
 	bv		%r0(%r2)
@@ -735,8 +773,7 @@
 	.exit
 
 	.procend
-ENDPROC(flush_user_icache_page)
-
+ENDPROC(flush_kernel_dcache_page_asm)
 
 ENTRY(purge_kernel_dcache_page)
 	.proc
@@ -780,69 +817,6 @@
 	.procend
 ENDPROC(purge_kernel_dcache_page)
 
-#if 0
-	/* Currently not used, but it still is a possible alternate
-	 * solution.
-	 */
-
-ENTRY(flush_alias_page)
-	.proc
-	.callinfo NO_CALLS
-	.entry
-
-	tophys_r1		%r26
-
-	ldil		L%(TMPALIAS_MAP_START), %r28
-#ifdef CONFIG_64BIT
-	extrd,u		%r26, 56,32, %r26	/* convert phys addr to tlb insert format */
-	depd		%r25, 63,22, %r28	/* Form aliased virtual address 'to' */
-	depdi		0, 63,12, %r28		/* Clear any offset bits */
-#else
-	extrw,u		%r26, 24,25, %r26	/* convert phys addr to tlb insert format */
-	depw		%r25, 31,22, %r28	/* Form aliased virtual address 'to' */
-	depwi		0, 31,12, %r28		/* Clear any offset bits */
-#endif
-
-	/* Purge any old translation */
-
-	pdtlb		0(%r28)
-
-	ldil		L%dcache_stride, %r1
-	ldw		R%dcache_stride(%r1), %r23
-
-#ifdef CONFIG_64BIT
-	depdi,z		1, 63-PAGE_SHIFT,1, %r29
-#else
-	depwi,z		1, 31-PAGE_SHIFT,1, %r29
-#endif
-	add		%r28, %r29, %r29
-	sub		%r29, %r23, %r29
-
-1:      fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	fdc,m		%r23(%r28)
-	cmpb,COND(<<)		%r28, %r29, 1b
-	fdc,m		%r23(%r28)
-
-	sync
-	bv		%r0(%r2)
-	nop
-	.exit
-
-	.procend
-#endif
 
 	.export flush_user_dcache_range_asm
 
@@ -865,7 +839,6 @@
 	.exit
 
 	.procend
-ENDPROC(flush_alias_page)
 
 ENTRY(flush_kernel_dcache_range_asm)
 	.proc
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/signal.c linux-libre-2.6.39-gnu/arch/parisc/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/signal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -291,7 +291,7 @@
 		DBG(1,"setup_rt_frame: frame->uc = 0x%p\n", &frame->uc);
 		DBG(1,"setup_rt_frame: frame->uc.uc_mcontext = 0x%p\n", &frame->uc.uc_mcontext);
 		err |= setup_sigcontext(&frame->uc.uc_mcontext, regs, in_syscall);
-		/* FIXME: Should probably be converted aswell for the compat case */
+		/* FIXME: Should probably be converted as well for the compat case */
 		err |= __copy_to_user(&frame->uc.uc_sigmask, set, sizeof(*set));
 	}
 	
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/syscall.S linux-libre-2.6.39-gnu/arch/parisc/kernel/syscall.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/syscall.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/syscall.S	2011-05-19 00:06:34.000000000 -0400
@@ -605,7 +605,7 @@
 	copy	%r0, %r21
 
 3:		
-	/* Error occured on load or store */
+	/* Error occurred on load or store */
 	/* Free lock */
 	stw	%r20, 0(%sr2,%r20)
 #if ENABLE_LWS_DEBUG
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/syscall_table.S linux-libre-2.6.39-gnu/arch/parisc/kernel/syscall_table.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/syscall_table.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/syscall_table.S	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 /* Use ENTRY_SAME for 32-bit syscalls which are the same on wide and
  * narrow palinux.  Use ENTRY_DIFF for those where a 32-bit specific
  * implementation is required on wide palinux.  Use ENTRY_COMP where
- * the compatability layer has a useful 32-bit implementation.
+ * the compatibility layer has a useful 32-bit implementation.
  */
 #define ENTRY_SAME(_name_) .dword sys_##_name_
 #define ENTRY_DIFF(_name_) .dword sys32_##_name_
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/time.c linux-libre-2.6.39-gnu/arch/parisc/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -162,11 +162,8 @@
 		update_process_times(user_mode(get_irq_regs()));
 	}
 
-	if (cpu == 0) {
-		write_seqlock(&xtime_lock);
-		do_timer(ticks_elapsed);
-		write_sequnlock(&xtime_lock);
-	}
+	if (cpu == 0)
+		xtime_update(ticks_elapsed);
 
 	return IRQ_HANDLED;
 }
diff -druN linux-libre-2.6.38-gnu/arch/parisc/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/parisc/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/parisc/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -145,7 +145,7 @@
 		EXIT_DATA
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
 	/* freed after init ends here */
diff -druN linux-libre-2.6.38-gnu/arch/parisc/math-emu/dfadd.c linux-libre-2.6.39-gnu/arch/parisc/math-emu/dfadd.c
--- linux-libre-2.6.38-gnu/arch/parisc/math-emu/dfadd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/math-emu/dfadd.c	2011-05-19 00:06:34.000000000 -0400
@@ -303,7 +303,7 @@
 	if(Dbl_iszero_hidden(resultp1))
 	    {
 	    /* Handle normalization */
-	    /* A straight foward algorithm would now shift the result
+	    /* A straight forward algorithm would now shift the result
 	     * and extension left until the hidden bit becomes one.  Not
 	     * all of the extension bits need participate in the shift.
 	     * Only the two most significant bits (round and guard) are
diff -druN linux-libre-2.6.38-gnu/arch/parisc/math-emu/dfsub.c linux-libre-2.6.39-gnu/arch/parisc/math-emu/dfsub.c
--- linux-libre-2.6.38-gnu/arch/parisc/math-emu/dfsub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/math-emu/dfsub.c	2011-05-19 00:06:34.000000000 -0400
@@ -306,7 +306,7 @@
 	if(Dbl_iszero_hidden(resultp1))
 	    {
 	    /* Handle normalization */
-	    /* A straight foward algorithm would now shift the result
+	    /* A straight forward algorithm would now shift the result
 	     * and extension left until the hidden bit becomes one.  Not
 	     * all of the extension bits need participate in the shift.
 	     * Only the two most significant bits (round and guard) are
diff -druN linux-libre-2.6.38-gnu/arch/parisc/math-emu/fmpyfadd.c linux-libre-2.6.39-gnu/arch/parisc/math-emu/fmpyfadd.c
--- linux-libre-2.6.38-gnu/arch/parisc/math-emu/fmpyfadd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/math-emu/fmpyfadd.c	2011-05-19 00:06:34.000000000 -0400
@@ -531,7 +531,7 @@
 		sign_save = Dbl_signextendedsign(resultp1);
 		if (Dbl_iszero_hidden(resultp1)) {
 			/* Handle normalization */
-		/* A straight foward algorithm would now shift the
+		/* A straightforward algorithm would now shift the
 		 * result and extension left until the hidden bit
 		 * becomes one.  Not all of the extension bits need
 		 * participate in the shift.  Only the two most 
@@ -1191,7 +1191,7 @@
 		sign_save = Dbl_signextendedsign(resultp1);
 		if (Dbl_iszero_hidden(resultp1)) {
 			/* Handle normalization */
-		/* A straight foward algorithm would now shift the
+		/* A straightforward algorithm would now shift the
 		 * result and extension left until the hidden bit
 		 * becomes one.  Not all of the extension bits need
 		 * participate in the shift.  Only the two most 
@@ -1841,7 +1841,7 @@
 		sign_save = Sgl_signextendedsign(resultp1);
 		if (Sgl_iszero_hidden(resultp1)) {
 			/* Handle normalization */
-		/* A straight foward algorithm would now shift the
+		/* A straightforward algorithm would now shift the
 		 * result and extension left until the hidden bit
 		 * becomes one.  Not all of the extension bits need
 		 * participate in the shift.  Only the two most 
@@ -2483,7 +2483,7 @@
 		sign_save = Sgl_signextendedsign(resultp1);
 		if (Sgl_iszero_hidden(resultp1)) {
 			/* Handle normalization */
-		/* A straight foward algorithm would now shift the
+		/* A straightforward algorithm would now shift the
 		 * result and extension left until the hidden bit
 		 * becomes one.  Not all of the extension bits need
 		 * participate in the shift.  Only the two most 
diff -druN linux-libre-2.6.38-gnu/arch/parisc/math-emu/sfadd.c linux-libre-2.6.39-gnu/arch/parisc/math-emu/sfadd.c
--- linux-libre-2.6.38-gnu/arch/parisc/math-emu/sfadd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/math-emu/sfadd.c	2011-05-19 00:06:34.000000000 -0400
@@ -298,7 +298,7 @@
 	if(Sgl_iszero_hidden(result))
 	    {
 	    /* Handle normalization */
-	    /* A straight foward algorithm would now shift the result
+	    /* A straightforward algorithm would now shift the result
 	     * and extension left until the hidden bit becomes one.  Not
 	     * all of the extension bits need participate in the shift.
 	     * Only the two most significant bits (round and guard) are
diff -druN linux-libre-2.6.38-gnu/arch/parisc/math-emu/sfsub.c linux-libre-2.6.39-gnu/arch/parisc/math-emu/sfsub.c
--- linux-libre-2.6.38-gnu/arch/parisc/math-emu/sfsub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/math-emu/sfsub.c	2011-05-19 00:06:34.000000000 -0400
@@ -301,7 +301,7 @@
 	if(Sgl_iszero_hidden(result))
 	    {
 	    /* Handle normalization */
-	    /* A straight foward algorithm would now shift the result
+	    /* A straightforward algorithm would now shift the result
 	     * and extension left until the hidden bit becomes one.  Not
 	     * all of the extension bits need participate in the shift.
 	     * Only the two most significant bits (round and guard) are
diff -druN linux-libre-2.6.38-gnu/arch/parisc/mm/init.c linux-libre-2.6.39-gnu/arch/parisc/mm/init.c
--- linux-libre-2.6.38-gnu/arch/parisc/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/parisc/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -266,8 +266,10 @@
 	}
 	memset(pfnnid_map, 0xff, sizeof(pfnnid_map));
 
-	for (i = 0; i < npmem_ranges; i++)
+	for (i = 0; i < npmem_ranges; i++) {
+		node_set_state(i, N_NORMAL_MEMORY);
 		node_set_online(i);
+	}
 #endif
 
 	/*
@@ -544,7 +546,7 @@
 unsigned long *empty_zero_page __read_mostly;
 EXPORT_SYMBOL(empty_zero_page);
 
-void show_mem(void)
+void show_mem(unsigned int filter)
 {
 	int i,free = 0,total = 0,reserved = 0;
 	int shared = 0, cached = 0;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/canyonlands.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/canyonlands.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/canyonlands.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/canyonlands.dts	2011-05-19 00:06:34.000000000 -0400
@@ -172,6 +172,19 @@
 			interrupts = <0x1e 4>;
 		};
 
+		USBOTG0: usbotg@bff80000 {
+			compatible = "amcc,dwc-otg";
+			reg = <0x4 0xbff80000 0x10000>;
+			interrupt-parent = <&USBOTG0>;
+			#interrupt-cells = <1>;
+			#address-cells = <0>;
+			#size-cells = <0>;
+			interrupts = <0x0 0x1 0x2>;
+			interrupt-map = </* USB-OTG */ 0x0 &UIC2 0x1c 0x4
+					 /* HIGH-POWER */ 0x1 &UIC1 0x1a 0x8
+					 /* DMA */ 0x2 &UIC0 0xc 0x4>;
+		};
+
 		SATA0: sata@bffd1000 {
 			compatible = "amcc,sata-460ex";
 			reg = <4 0xbffd1000 0x800 4 0xbffd0800 0x400>;
@@ -233,6 +246,11 @@
 					};
 				};
 
+				cpld@2,0 {
+					compatible = "amcc,ppc460ex-bcsr";
+					reg = <2 0x0 0x9>;
+				};
+
 				ndfc@3,0 {
 					compatible = "ibm,ndfc";
 					reg = <0x00000003 0x00000000 0x00002000>;
@@ -307,6 +325,12 @@
 				interrupts = <0x3 0x4>;
 			};
 
+			GPIO0: gpio@ef600b00 {
+				compatible = "ibm,ppc4xx-gpio";
+				reg = <0xef600b00 0x00000048>;
+				gpio-controller;
+			};
+
 			ZMII0: emac-zmii@ef600d00 {
 				compatible = "ibm,zmii-460ex", "ibm,zmii";
 				reg = <0xef600d00 0x0000000c>;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/kmeter1.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/kmeter1.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/kmeter1.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/kmeter1.dts	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Keymile KMETER1 Device Tree Source
  *
- * 2008 DENX Software Engineering GmbH
+ * 2008-2011 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
@@ -70,11 +70,11 @@
 			#address-cells = <1>;
 			#size-cells = <0>;
 			cell-index = <0>;
-			compatible = "fsl-i2c";
+			compatible = "fsl,mpc8313-i2c","fsl-i2c";
 			reg = <0x3000 0x100>;
 			interrupts = <14 0x8>;
 			interrupt-parent = <&ipic>;
-			dfsrr;
+			clock-frequency = <400000>;
 		};
 
 		serial0: serial@4500 {
@@ -137,6 +137,13 @@
 			compatible = "fsl,mpc8360-par_io";
 			num-ports = <7>;
 
+			qe_pio_c: gpio-controller@30 {
+				#gpio-cells = <2>;
+				compatible = "fsl,mpc8360-qe-pario-bank",
+					     "fsl,mpc8323-qe-pario-bank";
+				reg = <0x1430 0x18>;
+				gpio-controller;
+			};
 			pio_ucc1: ucc_pin@0 {
 				reg = <0>;
 
@@ -472,7 +479,17 @@
 				#address-cells = <0>;
 				#interrupt-cells = <1>;
 				reg = <0x80 0x80>;
-				interrupts = <32 8 33 8>;
+				big-endian;
+				interrupts = <
+					32 0x8
+					33 0x8
+					34 0x8
+					35 0x8
+					40 0x8
+					41 0x8
+					42 0x8
+					43 0x8
+				>;
 				interrupt-parent = <&ipic>;
 			};
 		};
@@ -484,43 +501,31 @@
 		compatible = "fsl,mpc8360-localbus", "fsl,pq2pro-localbus",
 			     "simple-bus";
 		reg = <0xe0005000 0xd8>;
-		ranges = <0 0 0xf0000000 0x04000000>;	/* Filled in by U-Boot */
+		ranges = <0 0 0xf0000000 0x04000000	/* LB 0 */
+			  1 0 0xe8000000 0x01000000	/* LB 1 */
+			  3 0 0xa0000000 0x10000000>;	/* LB 3 */
 
-		flash@f0000000,0 {
+		flash@0,0 {
 			compatible = "cfi-flash";
-			/*
-			 * The Intel P30 chip has 2 non-identical chips on
-			 * one die, so we need to define 2 separate regions
-			 * that are scanned by physmap_of independantly.
-			 */
-			reg = <0 0x00000000 0x02000000
-			       0 0x02000000 0x02000000>;	/* Filled in by U-Boot */
-			bank-width = <2>;
+			reg = <0 0 0x04000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
-			partition@0 {
+			bank-width = <2>;
+			partition@0 { /* 768KB */
 				label = "u-boot";
-				reg = <0 0x40000>;
+				reg = <0 0xC0000>;
 			};
-			partition@40000 {
+			partition@c0000 { /* 128KB */
 				label = "env";
-				reg = <0x40000 0x40000>;
-			};
-			partition@80000 {
-				label = "dtb";
-				reg = <0x80000 0x20000>;
-			};
-			partition@a0000 {
-				label = "kernel";
-				reg = <0xa0000 0x300000>;
+				reg = <0xC0000 0x20000>;
 			};
-			partition@3a0000 {
-				label = "ramdisk";
-				reg = <0x3a0000 0x800000>;
+			partition@e0000 { /* 128KB */
+				label = "envred";
+				reg = <0xE0000 0x20000>;
 			};
-			partition@ba0000 {
-				label = "user";
-				reg = <0xba0000 0x3460000>;
+			partition@100000 { /* 64512KB */
+				label = "ubi0";
+				reg = <0x100000 0x3F00000>;
 			};
 		};
 	};
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/mgcoge.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/mgcoge.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/mgcoge.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/mgcoge.dts	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 /dts-v1/;
 / {
 	model = "MGCOGE";
-	compatible = "keymile,mgcoge";
+	compatible = "keymile,km82xx";
 	#address-cells = <1>;
 	#size-cells = <1>;
 
@@ -48,8 +48,10 @@
 		reg = <0xf0010100 0x40>;
 
 		ranges = <0 0 0xfe000000 0x00400000
-			  5 0 0x50000000 0x20000000
-			>; /* Filled in by U-Boot */
+			  1 0 0x30000000 0x00010000
+			  2 0 0x40000000 0x00010000
+			  5 0 0x50000000 0x04000000
+			>;
 
 		flash@0,0 {
 			compatible = "cfi-flash";
@@ -60,36 +62,32 @@
 			device-width = <1>;
 			partition@0 {
 				label = "u-boot";
-				reg = <0 0x40000>;
+				reg = <0x00000 0xC0000>;
 			};
-			partition@40000 {
+			partition@1 {
 				label = "env";
-				reg = <0x40000 0x20000>;
+				reg = <0xC0000 0x20000>;
 			};
-			partition@60000 {
-				label = "kernel";
-				reg = <0x60000 0x220000>;
+			partition@2 {
+				label = "envred";
+				reg = <0xE0000 0x20000>;
 			};
-			partition@280000 {
-				label = "dtb";
-				reg = <0x280000 0x20000>;
+			partition@3 {
+				label = "free";
+				reg = <0x100000 0x300000>;
 			};
 		};
 
 		flash@5,0 {
 			compatible = "cfi-flash";
-			reg = <5 0x0 0x2000000>;
+			reg = <5 0x00000000 0x02000000
+			       5 0x02000000 0x02000000>;
 			#address-cells = <1>;
 			#size-cells = <1>;
 			bank-width = <2>;
-			device-width = <2>;
-			partition@0 {
-				label = "ramdisk";
-				reg = <0 0x7a0000>;
-			};
-			partition@7a0000 {
-				label = "user";
-				reg = <0x7a0000 0x1860000>;
+			partition@app { /* 64 MBytes */
+				label = "ubi0";
+				reg = <0x00000000 0x04000000>;
 			};
 		};
 	};
@@ -217,6 +215,13 @@
 			};
 		};
 
+		cpm2_pio_c: gpio-controller@10d40 {
+			#gpio-cells = <2>;
+			compatible = "fsl,cpm2-pario-bank";
+			reg = <0x10d40 0x14>;
+			gpio-controller;
+		};
+
 		PIC: interrupt-controller@10c00 {
 			#interrupt-cells = <2>;
 			interrupt-controller;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/mgsuvd.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/mgsuvd.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/mgsuvd.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/mgsuvd.dts	1969-12-31 19:00:00.000000000 -0500
@@ -1,163 +0,0 @@
-/*
- * MGSUVD Device Tree Source
- *
- * Copyright 2008 DENX Software Engineering GmbH
- * Heiko Schocher <hs@denx.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.
- */
-
-/dts-v1/;
-/ {
-	model = "MGSUVD";
-	compatible = "keymile,mgsuvd";
-	#address-cells = <1>;
-	#size-cells = <1>;
-
-	cpus {
-		#address-cells = <1>;
-		#size-cells = <0>;
-
-		PowerPC,852@0 {
-			device_type = "cpu";
-			reg = <0>;
-			d-cache-line-size = <16>;
-			i-cache-line-size = <16>;
-			d-cache-size = <8192>;
-			i-cache-size = <8192>;
-			timebase-frequency = <0>;	/* Filled in by u-boot */
-			bus-frequency = <0>;		/* Filled in by u-boot */
-			clock-frequency = <0>;		/* Filled in by u-boot */
-			interrupts = <15 2>;		/* decrementer interrupt */
-			interrupt-parent = <&PIC>;
-		};
-	};
-
-	memory {
-		device_type = "memory";
-		reg = <00000000 0x4000000>;  /* Filled in by u-boot */
-	};
-
-	localbus@fff00100 {
-		compatible = "fsl,mpc852-localbus", "fsl,pq1-localbus", "simple-bus";
-		#address-cells = <2>;
-		#size-cells = <1>;
-		reg = <0xfff00100 0x40>;
-
-		ranges = <0 0 0xf0000000 0x01000000>;  /* Filled in by u-boot */
-
-		flash@0,0 {
-			compatible = "cfi-flash";
-			reg = <0 0 0x1000000>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			bank-width = <1>;
-			device-width = <1>;
-			partition@0 {
-				label = "u-boot";
-				reg = <0 0x80000>;
-			};
-			partition@80000 {
-				label = "env";
-				reg = <0x80000 0x20000>;
-			};
-			partition@a0000 {
-				label = "kernel";
-				reg = <0xa0000 0x1e0000>;
-			};
-			partition@280000 {
-				label = "dtb";
-				reg = <0x280000 0x20000>;
-			};
-			partition@2a0000 {
-			        label = "root";
-			        reg = <0x2a0000 0x500000>;
-			};
-			partition@7a0000 {
-			        label = "user";
-			        reg = <0x7a0000 0x860000>;
-			};
-		};
-	};
-
-	soc@fff00000 {
-		compatible = "fsl,mpc852", "fsl,pq1-soc", "simple-bus";
-		#address-cells = <1>;
-		#size-cells = <1>;
-		device_type = "soc";
-		ranges = <0 0xfff00000 0x00004000>;
-
-		PIC: interrupt-controller@0 {
-			interrupt-controller;
-			#interrupt-cells = <2>;
-			reg = <0 24>;
-			compatible = "fsl,mpc852-pic", "fsl,pq1-pic";
-		};
-
-		cpm@9c0 {
-			#address-cells = <1>;
-			#size-cells = <1>;
-			compatible = "fsl,mpc852-cpm", "fsl,cpm1", "simple-bus";
-			interrupts = <0>;	/* cpm error interrupt */
-			interrupt-parent = <&CPM_PIC>;
-			reg = <0x9c0 10>;
-			ranges;
-
-			muram@2000 {
-				compatible = "fsl,cpm-muram";
-				#address-cells = <1>;
-				#size-cells = <1>;
-				ranges = <0 0x2000 0x2000>;
-
-				data@0 {
-					compatible = "fsl,cpm-muram-data";
-					reg = <0x800 0x1800>;
-				};
-			};
-
-			brg@9f0 {
-				compatible = "fsl,mpc852-brg",
-				             "fsl,cpm1-brg",
-				             "fsl,cpm-brg";
-				reg = <0x9f0 0x10>;
-				clock-frequency = <0>; /* Filled in by u-boot */
-			};
-
-			CPM_PIC: interrupt-controller@930 {
-				interrupt-controller;
-				#interrupt-cells = <1>;
-				interrupts = <5 2 0 2>;
-				interrupt-parent = <&PIC>;
-				reg = <0x930 0x20>;
-				compatible = "fsl,cpm1-pic";
-			};
-
-			/* MON-1 */
-			serial@a80 {
-				device_type = "serial";
-				compatible = "fsl,cpm1-smc-uart";
-				reg = <0xa80 0x10 0x3fc0 0x40>;
-				interrupts = <4>;
-				interrupt-parent = <&CPM_PIC>;
-				fsl,cpm-brg = <1>;
-				fsl,cpm-command = <0x0090>;
-				current-speed = <0>; /* Filled in by u-boot */
-			};
-
-			ethernet@a40 {
-				device_type = "network";
-				compatible  = "fsl,mpc866-scc-enet",
-				              "fsl,cpm1-scc-enet";
-				reg = <0xa40 0x18 0x3e00 0x100>;
-				local-mac-address = [ 00 00 00 00 00 00 ];  /* Filled in by u-boot */
-				interrupts = <28>;
-				interrupt-parent = <&CPM_PIC>;
-				fsl,cpm-command = <0x80>;
-				fixed-link = <0 0 10 0 0>;
-			};
-		};
-	};
-};
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p1020rdb.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p1020rdb.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p1020rdb.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p1020rdb.dts	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * P1020 RDB Device Tree Source
  *
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 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
@@ -553,7 +553,7 @@
 		reg = <0 0xffe09000 0 0x1000>;
 		bus-range = <0 255>;
 		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
-			  0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
 		interrupts = <16 2>;
@@ -580,8 +580,8 @@
 		#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>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
 		interrupts = <16 2>;
@@ -590,8 +590,8 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			ranges = <0x2000000 0x0 0xc0000000
-				  0x2000000 0x0 0xc0000000
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
 				  0x0 0x20000000
 
 				  0x1000000 0x0 0x0
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p1022ds.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p1022ds.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p1022ds.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p1022ds.dts	2011-05-19 00:06:34.000000000 -0400
@@ -475,14 +475,14 @@
 		};
 
 		sata@18000 {
-			compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
+			compatible = "fsl,p1022-sata", "fsl,pq-sata-v2";
 			reg = <0x18000 0x1000>;
 			cell-index = <1>;
 			interrupts = <74 0x2>;
 		};
 
 		sata@19000 {
-			compatible = "fsl,mpc8536-sata", "fsl,pq-sata";
+			compatible = "fsl,p1022-sata", "fsl,pq-sata-v2";
 			reg = <0x19000 0x1000>;
 			cell-index = <2>;
 			interrupts = <41 0x2>;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core0.dts	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  * This dts file allows core0 to have memory, l2, i2c, spi, gpio, dma1, usb,
  * eth1, eth2, sdhc, crypto, global-util, pci0.
  *
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 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
@@ -342,7 +342,7 @@
 		reg = <0 0xffe09000 0 0x1000>;
 		bus-range = <0 255>;
 		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
-			  0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
 		interrupts = <25 2>;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p2020rdb_camp_core1.dts	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
  *
  * Please note to add "-b 1" for core1's dts compiling.
  *
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 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
@@ -162,8 +162,8 @@
 		#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>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
 		interrupts = <26 2>;
@@ -172,8 +172,8 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			ranges = <0x2000000 0x0 0xc0000000
-				  0x2000000 0x0 0xc0000000
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
 				  0x0 0x20000000
 
 				  0x1000000 0x0 0x0
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p2020rdb.dts linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p2020rdb.dts
--- linux-libre-2.6.38-gnu/arch/powerpc/boot/dts/p2020rdb.dts	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/boot/dts/p2020rdb.dts	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * P2020 RDB Device Tree Source
  *
- * Copyright 2009 Freescale Semiconductor Inc.
+ * Copyright 2009-2011 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
@@ -537,7 +537,7 @@
 		reg = <0 0xffe09000 0 0x1000>;
 		bus-range = <0 255>;
 		ranges = <0x2000000 0x0 0xa0000000 0 0xa0000000 0x0 0x20000000
-			  0x1000000 0x0 0x00000000 0 0xffc30000 0x0 0x10000>;
+			  0x1000000 0x0 0x00000000 0 0xffc10000 0x0 0x10000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
 		interrupts = <25 2>;
@@ -564,8 +564,8 @@
 		#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>;
+		ranges = <0x2000000 0x0 0x80000000 0 0x80000000 0x0 0x20000000
+			  0x1000000 0x0 0x00000000 0 0xffc00000 0x0 0x10000>;
 		clock-frequency = <33333333>;
 		interrupt-parent = <&mpic>;
 		interrupts = <26 2>;
@@ -574,8 +574,8 @@
 			#size-cells = <2>;
 			#address-cells = <3>;
 			device_type = "pci";
-			ranges = <0x2000000 0x0 0xc0000000
-				  0x2000000 0x0 0xc0000000
+			ranges = <0x2000000 0x0 0x80000000
+				  0x2000000 0x0 0x80000000
 				  0x0 0x20000000
 
 				  0x1000000 0x0 0x0
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/44x/warp_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/44x/warp_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/44x/warp_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/44x/warp_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -47,6 +47,7 @@
 CONFIG_MTD_UBI=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/52xx/motionpro_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/52xx/motionpro_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/52xx/motionpro_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/52xx/motionpro_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/83xx/kmeter1_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,7 @@
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_EXPERT=y
 # CONFIG_HOTPLUG is not set
@@ -18,7 +19,6 @@
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_PREEMPT=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -37,7 +37,6 @@
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -49,13 +48,12 @@
 CONFIG_MTD_UBI_GLUEBI=y
 CONFIG_MTD_UBI_DEBUG=y
 CONFIG_PROC_DEVICETREE=y
-# CONFIG_MISC_DEVICES is not set
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_TUN=y
+CONFIG_MII=y
 CONFIG_MARVELL_PHY=y
 CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
 CONFIG_UCC_GETH=y
 # CONFIG_NETDEV_10000 is not set
 CONFIG_WAN=y
@@ -77,7 +75,6 @@
 # CONFIG_USB_SUPPORT is not set
 CONFIG_UIO=y
 # CONFIG_DNOTIFY is not set
-CONFIG_INOTIFY=y
 CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_NFS_FS=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/gef_ppc9a_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_DS1682=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECS=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/gef_sbc310_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_DS1682=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECS=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/gef_sbc610_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -138,6 +138,7 @@
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_DS1682=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/86xx/mpc8641_hpcn_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -63,6 +63,7 @@
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/e55xx_smp_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/e55xx_smp_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/e55xx_smp_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/e55xx_smp_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/linkstation_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/linkstation_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/linkstation_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/linkstation_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -78,6 +78,7 @@
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=2
 CONFIG_BLK_DEV_RAM_SIZE=8192
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=m
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mgcoge_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mgcoge_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mgcoge_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mgcoge_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,5 @@
 CONFIG_SYSVIPC=y
+CONFIG_SPARSE_IRQ=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -10,7 +11,6 @@
 CONFIG_PPC_82xx=y
 CONFIG_MGCOGE=y
 CONFIG_BINFMT_MISC=y
-CONFIG_SPARSE_IRQ=y
 # CONFIG_SECCOMP is not set
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -30,7 +30,6 @@
 CONFIG_MTD_CONCAT=y
 CONFIG_MTD_PARTITIONS=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLKDEVS=y
 CONFIG_MTD_CFI=y
@@ -43,7 +42,6 @@
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
 # CONFIG_MACINTOSH_DRIVERS is not set
 CONFIG_NETDEVICES=y
 CONFIG_FIXED_PHY=y
@@ -67,7 +65,6 @@
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
 # CONFIG_EXT3_FS_XATTR is not set
-CONFIG_INOTIFY=y
 CONFIG_AUTOFS4_FS=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
@@ -88,13 +85,9 @@
 CONFIG_DEBUG_KERNEL=y
 # CONFIG_SCHED_DEBUG is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_BDI_SWITCH=y
-CONFIG_CRYPTO_CBC=y
 CONFIG_CRYPTO_ECB=y
 CONFIG_CRYPTO_PCBC=y
-CONFIG_CRYPTO_MD5=y
-CONFIG_CRYPTO_DES=y
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mgsuvd_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mgsuvd_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mgsuvd_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mgsuvd_defconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-CONFIG_PPC_8xx=y
-CONFIG_EXPERIMENTAL=y
-# CONFIG_SWAP is not set
-CONFIG_SYSVIPC=y
-CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
-CONFIG_EXPERT=y
-# CONFIG_SYSCTL_SYSCALL is not set
-# CONFIG_HOTPLUG is not set
-# CONFIG_BUG is not set
-# CONFIG_BASE_FULL is not set
-# CONFIG_EPOLL is not set
-# CONFIG_VM_EVENT_COUNTERS is not set
-CONFIG_SLAB=y
-# CONFIG_BLK_DEV_BSG is not set
-CONFIG_PPC_MGSUVD=y
-CONFIG_8xx_COPYBACK=y
-CONFIG_8xx_CPU6=y
-CONFIG_I2C_SPI_SMC1_UCODE_PATCH=y
-CONFIG_HZ_1000=y
-CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
-# CONFIG_SECCOMP is not set
-CONFIG_NET=y
-CONFIG_PACKET=y
-CONFIG_UNIX=y
-CONFIG_INET=y
-CONFIG_IP_MULTICAST=y
-CONFIG_IP_PNP=y
-CONFIG_SYN_COOKIES=y
-# CONFIG_INET_LRO is not set
-# CONFIG_IPV6 is not set
-CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_OF_PARTS=y
-CONFIG_MTD_CHAR=y
-CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
-CONFIG_MTD_CFI_ADV_OPTIONS=y
-CONFIG_MTD_CFI_GEOMETRY=y
-# CONFIG_MTD_MAP_BANK_WIDTH_4 is not set
-CONFIG_MTD_CFI_INTELEXT=y
-CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_STAA=y
-CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_BLK_DEV_LOOP=y
-CONFIG_BLK_DEV_RAM=y
-# CONFIG_MISC_DEVICES is not set
-CONFIG_NETDEVICES=y
-CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FS_ENET=y
-# CONFIG_FS_ENET_HAS_FEC is not set
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
-# CONFIG_INPUT is not set
-# CONFIG_SERIO is not set
-# CONFIG_VT is not set
-CONFIG_SERIAL_CPM=y
-CONFIG_SERIAL_CPM_CONSOLE=y
-# CONFIG_LEGACY_PTYS is not set
-CONFIG_GEN_RTC=y
-# CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
-CONFIG_EXT2_FS=y
-CONFIG_EXT2_FS_XATTR=y
-CONFIG_EXT3_FS=y
-# CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
-CONFIG_TMPFS=y
-CONFIG_JFFS2_FS=y
-CONFIG_CRAMFS=y
-CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
-CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_CRC_CCITT=y
-CONFIG_DEBUG_FS=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-# CONFIG_CRYPTO_ANSI_CPRNG is not set
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc512x_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc512x_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc512x_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc512x_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,7 @@
 CONFIG_BLK_DEV_RAM_COUNT=1
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_XIP=y
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_SCSI=y
 # CONFIG_SCSI_PROC_FS is not set
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc5200_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc5200_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc5200_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc5200_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -52,6 +52,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=32768
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_SCSI_TGT=y
 CONFIG_BLK_DEV_SD=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc85xx_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc85xx_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc85xx_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc85xx_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -82,6 +82,7 @@
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc85xx_smp_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -84,6 +84,7 @@
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc86xx_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc86xx_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/mpc86xx_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/mpc86xx_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -66,6 +66,7 @@
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/pasemi_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/pasemi_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/pasemi_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/pasemi_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -59,6 +59,7 @@
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=16384
+CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/ppc6xx_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/ppc6xx_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/ppc6xx_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/ppc6xx_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -398,6 +398,7 @@
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_VIRTIO_BLK=m
 CONFIG_BLK_DEV_HD=y
+CONFIG_MISC_DEVICES=y
 CONFIG_ENCLOSURE_SERVICES=m
 CONFIG_SENSORS_TSL2550=m
 CONFIG_EEPROM_AT24=m
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/configs/pseries_defconfig linux-libre-2.6.39-gnu/arch/powerpc/configs/pseries_defconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/configs/pseries_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/configs/pseries_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -189,6 +189,7 @@
 CONFIG_BNX2=m
 CONFIG_CHELSIO_T1=m
 CONFIG_CHELSIO_T3=m
+CONFIG_CHELSIO_T4=m
 CONFIG_EHEA=y
 CONFIG_IXGBE=m
 CONFIG_IXGB=m
@@ -255,6 +256,8 @@
 CONFIG_INFINIBAND_USER_ACCESS=m
 CONFIG_INFINIBAND_MTHCA=m
 CONFIG_INFINIBAND_EHCA=m
+CONFIG_INFINIBAND_CXGB3=m
+CONFIG_INFINIBAND_CXGB4=m
 CONFIG_MLX4_INFINIBAND=m
 CONFIG_INFINIBAND_IPOIB=m
 CONFIG_INFINIBAND_IPOIB_CM=y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/8xx_immap.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/8xx_immap.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/8xx_immap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/8xx_immap.h	2011-05-19 00:06:34.000000000 -0400
@@ -393,8 +393,8 @@
 	uint	fec_addr_low;		/* lower 32 bits of station address	*/
 	ushort	fec_addr_high;		/* upper 16 bits of station address	*/
 	ushort	res1;			/* reserved				*/
-	uint	fec_hash_table_high;	/* upper 32-bits of hash table		*/
-	uint	fec_hash_table_low;	/* lower 32-bits of hash table		*/
+	uint	fec_grp_hash_table_high;	/* upper 32-bits of hash table		*/
+	uint	fec_grp_hash_table_low;	/* lower 32-bits of hash table		*/
 	uint	fec_r_des_start;	/* beginning of Rx descriptor ring	*/
 	uint	fec_x_des_start;	/* beginning of Tx descriptor ring	*/
 	uint	fec_r_buff_size;	/* Rx buffer size			*/
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -209,8 +209,8 @@
 		return BITS_PER_LONG;
 
 	/*
-	 * Calculate the bit position of the least signficant '1' bit in x
-	 * (since x has been changed this will actually be the least signficant
+	 * Calculate the bit position of the least significant '1' bit in x
+	 * (since x has been changed this will actually be the least significant
 	 * '0' bit in * the original x).  Note: (x & -x) gives us a mask that
 	 * is the least significant * (RIGHT-most) 1-bit of the value in x.
 	 */
@@ -281,68 +281,56 @@
 
 /* Little-endian versions */
 
-static __inline__ int test_le_bit(unsigned long nr,
-				  __const__ unsigned long *addr)
+static __inline__ int test_bit_le(unsigned long nr,
+				  __const__ void *addr)
 {
 	__const__ unsigned char	*tmp = (__const__ unsigned char *) addr;
 	return (tmp[nr >> 3] >> (nr & 7)) & 1;
 }
 
-#define __set_le_bit(nr, addr) \
-	__set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
-#define __clear_le_bit(nr, addr) \
-	__clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+static inline void __set_bit_le(int nr, void *addr)
+{
+	__set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
 
-#define test_and_set_le_bit(nr, addr) \
-	test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
-#define test_and_clear_le_bit(nr, addr) \
-	test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+static inline void __clear_bit_le(int nr, void *addr)
+{
+	__clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
 
-#define __test_and_set_le_bit(nr, addr) \
-	__test_and_set_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
-#define __test_and_clear_le_bit(nr, addr) \
-	__test_and_clear_bit((nr) ^ BITOP_LE_SWIZZLE, (addr))
+static inline int test_and_set_bit_le(int nr, void *addr)
+{
+	return test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
 
-#define find_first_zero_le_bit(addr, size) generic_find_next_zero_le_bit((addr), (size), 0)
-unsigned long generic_find_next_zero_le_bit(const unsigned long *addr,
+static inline int test_and_clear_bit_le(int nr, void *addr)
+{
+	return test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline int __test_and_set_bit_le(int nr, void *addr)
+{
+	return __test_and_set_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+static inline int __test_and_clear_bit_le(int nr, void *addr)
+{
+	return __test_and_clear_bit(nr ^ BITOP_LE_SWIZZLE, addr);
+}
+
+#define find_first_zero_bit_le(addr, size) \
+	find_next_zero_bit_le((addr), (size), 0)
+unsigned long find_next_zero_bit_le(const void *addr,
 				    unsigned long size, unsigned long offset);
 
-unsigned long generic_find_next_le_bit(const unsigned long *addr,
+unsigned long find_next_bit_le(const void *addr,
 				    unsigned long size, unsigned long offset);
 /* Bitmap functions for the ext2 filesystem */
 
-#define ext2_set_bit(nr,addr) \
-	__test_and_set_le_bit((nr), (unsigned long*)addr)
-#define ext2_clear_bit(nr, addr) \
-	__test_and_clear_le_bit((nr), (unsigned long*)addr)
-
 #define ext2_set_bit_atomic(lock, nr, addr) \
-	test_and_set_le_bit((nr), (unsigned long*)addr)
+	test_and_set_bit_le((nr), (unsigned long*)addr)
 #define ext2_clear_bit_atomic(lock, nr, addr) \
-	test_and_clear_le_bit((nr), (unsigned long*)addr)
-
-#define ext2_test_bit(nr, addr)      test_le_bit((nr),(unsigned long*)addr)
-
-#define ext2_find_first_zero_bit(addr, size) \
-	find_first_zero_le_bit((unsigned long*)addr, size)
-#define ext2_find_next_zero_bit(addr, size, off) \
-	generic_find_next_zero_le_bit((unsigned long*)addr, size, off)
-
-#define ext2_find_next_bit(addr, size, off) \
-	generic_find_next_le_bit((unsigned long *)addr, size, off)
-/* Bitmap functions for the minix filesystem.  */
-
-#define minix_test_and_set_bit(nr,addr) \
-	__test_and_set_le_bit(nr, (unsigned long *)addr)
-#define minix_set_bit(nr,addr) \
-	__set_le_bit(nr, (unsigned long *)addr)
-#define minix_test_and_clear_bit(nr,addr) \
-	__test_and_clear_le_bit(nr, (unsigned long *)addr)
-#define minix_test_bit(nr,addr) \
-	test_le_bit(nr, (unsigned long *)addr)
-
-#define minix_find_first_zero_bit(addr,size) \
-	find_first_zero_le_bit((unsigned long *)addr, size)
+	test_and_clear_bit_le((nr), (unsigned long*)addr)
 
 #include <asm-generic/bitops/sched.h>
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/compat.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/compat.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/compat.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/compat.h	2011-05-19 00:06:34.000000000 -0400
@@ -140,7 +140,7 @@
 	unsigned long usp = regs->gpr[1];
 
 	/*
-	 * We cant access below the stack pointer in the 32bit ABI and
+	 * We can't access below the stack pointer in the 32bit ABI and
 	 * can access 288 bytes in the 64bit ABI
 	 */
 	if (!is_32bit_task())
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/cpm1.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/cpm1.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/cpm1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/cpm1.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  *
  * This file contains structures and information for the communication
  * processor channels.  Some CPM control and status is available
- * throught the MPC8xx internal memory map.  See immap.h for details.
+ * through the MPC8xx internal memory map.  See immap.h for details.
  * This file only contains what I need for the moment, not the total
  * CPM capabilities.  I (or someone else) will add definitions as they
  * are needed.  -- Dan
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/cpm.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/cpm.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/cpm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/cpm.h	2011-05-19 00:06:34.000000000 -0400
@@ -98,7 +98,7 @@
 #define BD_SC_INTRPT	(0x1000)	/* Interrupt on change */
 #define BD_SC_LAST	(0x0800)	/* Last buffer in frame */
 #define BD_SC_TC	(0x0400)	/* Transmit CRC */
-#define BD_SC_CM	(0x0200)	/* Continous mode */
+#define BD_SC_CM	(0x0200)	/* Continuous mode */
 #define BD_SC_ID	(0x0100)	/* Rec'd too many idles */
 #define BD_SC_P		(0x0100)	/* xmt preamble */
 #define BD_SC_BR	(0x0020)	/* Break received */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/cputable.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/cputable.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/cputable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/cputable.h	2011-05-19 00:06:34.000000000 -0400
@@ -154,6 +154,7 @@
 #define CPU_FTR_NAP_DISABLE_L2_PR	ASM_CONST(0x0000000000002000)
 #define CPU_FTR_DUAL_PLL_750FX		ASM_CONST(0x0000000000004000)
 #define CPU_FTR_NO_DPM			ASM_CONST(0x0000000000008000)
+#define CPU_FTR_476_DD2			ASM_CONST(0x0000000000010000)
 #define CPU_FTR_NEED_COHERENT		ASM_CONST(0x0000000000020000)
 #define CPU_FTR_NO_BTIC			ASM_CONST(0x0000000000040000)
 #define CPU_FTR_NODSISRALIGN		ASM_CONST(0x0000000000100000)
@@ -381,10 +382,12 @@
 #define CPU_FTRS_E500_2	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
 	    CPU_FTR_SPE_COMP | CPU_FTR_MAYBE_CAN_NAP | \
 	    CPU_FTR_NODSISRALIGN | CPU_FTR_NOEXECUTE)
-#define CPU_FTRS_E500MC	(CPU_FTR_MAYBE_CAN_DOZE | CPU_FTR_USE_TB | \
-	    CPU_FTR_MAYBE_CAN_NAP | CPU_FTR_NODSISRALIGN | \
+#define CPU_FTRS_E500MC	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
 	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
 	    CPU_FTR_DBELL)
+#define CPU_FTRS_E5500	(CPU_FTR_USE_TB | CPU_FTR_NODSISRALIGN | \
+	    CPU_FTR_L2CSR | CPU_FTR_LWSYNC | CPU_FTR_NOEXECUTE | \
+	    CPU_FTR_DBELL | CPU_FTR_POPCNTB | CPU_FTR_POPCNTD)
 #define CPU_FTRS_GENERIC_32	(CPU_FTR_COMMON | CPU_FTR_NODSISRALIGN)
 
 /* 64-bit CPUs */
@@ -434,11 +437,15 @@
 #define CPU_FTRS_COMPATIBLE	(CPU_FTR_USE_TB | CPU_FTR_PPCAS_ARCH_V2)
 
 #ifdef __powerpc64__
+#ifdef CONFIG_PPC_BOOK3E
+#define CPU_FTRS_POSSIBLE	(CPU_FTRS_E5500)
+#else
 #define CPU_FTRS_POSSIBLE	\
 	    (CPU_FTRS_POWER3 | CPU_FTRS_RS64 | CPU_FTRS_POWER4 |	\
 	    CPU_FTRS_PPC970 | CPU_FTRS_POWER5 | CPU_FTRS_POWER6 |	\
 	    CPU_FTRS_POWER7 | CPU_FTRS_CELL | CPU_FTRS_PA6T |		\
 	    CPU_FTR_1T_SEGMENT | CPU_FTR_VSX)
+#endif
 #else
 enum {
 	CPU_FTRS_POSSIBLE =
@@ -465,23 +472,28 @@
 	    CPU_FTRS_44X | CPU_FTRS_440x6 |
 #endif
 #ifdef CONFIG_PPC_47x
-	    CPU_FTRS_47X |
+	    CPU_FTRS_47X | CPU_FTR_476_DD2 |
 #endif
 #ifdef CONFIG_E200
 	    CPU_FTRS_E200 |
 #endif
 #ifdef CONFIG_E500
 	    CPU_FTRS_E500 | CPU_FTRS_E500_2 | CPU_FTRS_E500MC |
+	    CPU_FTRS_E5500 |
 #endif
 	    0,
 };
 #endif /* __powerpc64__ */
 
 #ifdef __powerpc64__
+#ifdef CONFIG_PPC_BOOK3E
+#define CPU_FTRS_ALWAYS		(CPU_FTRS_E5500)
+#else
 #define CPU_FTRS_ALWAYS		\
 	    (CPU_FTRS_POWER3 & CPU_FTRS_RS64 & CPU_FTRS_POWER4 &	\
 	    CPU_FTRS_PPC970 & CPU_FTRS_POWER5 & CPU_FTRS_POWER6 &	\
 	    CPU_FTRS_POWER7 & CPU_FTRS_CELL & CPU_FTRS_PA6T & CPU_FTRS_POSSIBLE)
+#endif
 #else
 enum {
 	CPU_FTRS_ALWAYS =
@@ -512,6 +524,7 @@
 #endif
 #ifdef CONFIG_E500
 	    CPU_FTRS_E500 & CPU_FTRS_E500_2 & CPU_FTRS_E500MC &
+	    CPU_FTRS_E5500 &
 #endif
 	    CPU_FTRS_POSSIBLE,
 };
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/dma-mapping.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/dma-mapping.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/dma-mapping.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/dma-mapping.h	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,7 @@
 extern void __dma_sync(void *vaddr, size_t size, int direction);
 extern void __dma_sync_page(struct page *page, unsigned long offset,
 				 size_t size, int direction);
+extern unsigned long __dma_get_coherent_pfn(unsigned long cpu_addr);
 
 #else /* ! CONFIG_NOT_COHERENT_CACHE */
 /*
@@ -198,6 +199,11 @@
 #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)
 
+extern int dma_mmap_coherent(struct device *, struct vm_area_struct *,
+			     void *, dma_addr_t, size_t);
+#define ARCH_HAS_DMA_MMAP_COHERENT
+
+
 static inline void dma_cache_sync(struct device *dev, void *vaddr, size_t size,
 		enum dma_data_direction direction)
 {
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/futex.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 	: "b" (uaddr), "i" (-EFAULT), "r" (oparg) \
 	: "cr0", "memory")
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -40,7 +40,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -82,35 +82,38 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	int prev;
+	int ret = 0;
+	u32 prev;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
         __asm__ __volatile__ (
         PPC_RELEASE_BARRIER
-"1:     lwarx   %0,0,%2         # futex_atomic_cmpxchg_inatomic\n\
-        cmpw    0,%0,%3\n\
+"1:     lwarx   %1,0,%3         # futex_atomic_cmpxchg_inatomic\n\
+        cmpw    0,%1,%4\n\
         bne-    3f\n"
-        PPC405_ERR77(0,%2)
-"2:     stwcx.  %4,0,%2\n\
+        PPC405_ERR77(0,%3)
+"2:     stwcx.  %5,0,%3\n\
         bne-    1b\n"
         PPC_ACQUIRE_BARRIER
 "3:	.section .fixup,\"ax\"\n\
-4:	li	%0,%5\n\
+4:	li	%0,%6\n\
 	b	3b\n\
 	.previous\n\
 	.section __ex_table,\"a\"\n\
 	.align 3\n\
 	" PPC_LONG "1b,4b,2b,4b\n\
 	.previous" \
-        : "=&r" (prev), "+m" (*uaddr)
+        : "+r" (ret), "=&r" (prev), "+m" (*uaddr)
         : "r" (uaddr), "r" (oldval), "r" (newval), "i" (-EFAULT)
         : "cc", "memory");
 
-        return prev;
+	*uval = prev;
+        return ret;
 }
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/hvcall.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/hvcall.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/hvcall.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/hvcall.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,7 +122,7 @@
 #define H_DABRX_KERNEL		(1UL<<(63-62))
 #define H_DABRX_USER		(1UL<<(63-63))
 
-/* Each control block has to be on a 4K bondary */
+/* Each control block has to be on a 4K boundary */
 #define H_CB_ALIGNMENT          4096
 
 /* pSeries hypervisor opcodes */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/hw_irq.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/hw_irq.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/hw_irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/hw_irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -141,6 +141,8 @@
 
 #endif /* CONFIG_PPC64 */
 
+#define ARCH_IRQ_INIT_FLAGS	IRQ_NOREQUEST
+
 /*
  * interrupt-retrigger: should we handle this via lost interrupts and IPIs
  * or should we not care like we do now ? --BenH.
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -96,6 +96,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	0x5437
 
 #define TIOCSERCONFIG	0x5453
 #define TIOCSERGWILD	0x5454
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/kprobes.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/kprobes.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/kprobes.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/kprobes.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
  * Handle cases where:
  * 		- User passes a <.symbol> or <module:.symbol>
  * 		- User passes a <symbol> or <module:symbol>
- * 		- User passes a non-existant symbol, kallsyms_lookup_name
+ * 		- User passes a non-existent symbol, kallsyms_lookup_name
  * 		  returns 0. Don't deref the NULL pointer in that case
  */
 #define kprobe_lookup_name(name, addr)					\
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/lppaca.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/lppaca.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/lppaca.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/lppaca.h	2011-05-19 00:06:34.000000000 -0400
@@ -105,7 +105,7 @@
 	// processing of external interrupts.  Note that PLIC will store the
 	// XIRR directly into the xXirrValue field so that another XIRR will
 	// not be presented until this one clears.  The layout of the low
-	// 4-bytes of this Dword is upto SLIC - PLIC just checks whether the
+	// 4-bytes of this Dword is up to SLIC - PLIC just checks whether the
 	// entire Dword is zero or not.  A non-zero value in the low order
 	// 2-bytes will result in SLIC being granted the highest thread
 	// priority upon return.  A 0 will return to SLIC as medium priority.
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/machdep.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/machdep.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/machdep.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/machdep.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,9 +35,9 @@
 	int   (*probe)(void);
 	void  (*kick_cpu)(int nr);
 	void  (*setup_cpu)(int nr);
+	void  (*bringup_done)(void);
 	void  (*take_timebase)(void);
 	void  (*give_timebase)(void);
-	int   (*cpu_enable)(unsigned int nr);
 	int   (*cpu_disable)(void);
 	void  (*cpu_die)(unsigned int nr);
 	int   (*cpu_bootable)(unsigned int nr);
@@ -267,7 +267,6 @@
 
 extern void e500_idle(void);
 extern void power4_idle(void);
-extern void power4_cpu_offline_powersave(void);
 extern void ppc6xx_idle(void);
 extern void book3e_idle(void);
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/mmu-hash64.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/mmu-hash64.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/mmu-hash64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/mmu-hash64.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 #define STE_VSID_SHIFT	12
 
 /* Location of cpu0's segment table */
-#define STAB0_PAGE	0x6
+#define STAB0_PAGE	0x8
 #define STAB0_OFFSET	(STAB0_PAGE << 12)
 #define STAB0_PHYS_ADDR	(STAB0_OFFSET + PHYSICAL_START)
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/mpic.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/mpic.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/mpic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/mpic.h	2011-05-19 00:06:34.000000000 -0400
@@ -367,6 +367,10 @@
 #define MPIC_SINGLE_DEST_CPU		0x00001000
 /* Enable CoreInt delivery of interrupts */
 #define MPIC_ENABLE_COREINT		0x00002000
+/* Disable resetting of the MPIC.
+ * NOTE: This flag trumps MPIC_WANTS_RESET.
+ */
+#define MPIC_NO_RESET			0x00004000
 
 /* MPIC HW modification ID */
 #define MPIC_REGSET_MASK		0xf0000000
@@ -467,11 +471,11 @@
 void smp_mpic_message_pass(int target, int msg);
 
 /* Unmask a specific virq */
-extern void mpic_unmask_irq(unsigned int irq);
+extern void mpic_unmask_irq(struct irq_data *d);
 /* Mask a specific virq */
-extern void mpic_mask_irq(unsigned int irq);
+extern void mpic_mask_irq(struct irq_data *d);
 /* EOI a specific virq */
-extern void mpic_end_irq(unsigned int irq);
+extern void mpic_end_irq(struct irq_data *d);
 
 /* Fetch interrupt from a given mpic */
 extern unsigned int mpic_get_one_irq(struct mpic *mpic);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/nvram.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/nvram.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/nvram.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/nvram.h	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,8 @@
 extern int __init nvram_scan_partitions(void);
 extern loff_t nvram_create_partition(const char *name, int sig,
 				     int req_size, int min_size);
-extern int nvram_remove_partition(const char *name, int sig);
+extern int nvram_remove_partition(const char *name, int sig,
+					const char *exceptions[]);
 extern int nvram_get_partition_size(loff_t data_index);
 extern loff_t nvram_find_partition(const char *name, int sig, int *out_size);
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/page_64.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/page_64.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/page_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/page_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -169,7 +169,7 @@
 /*
  * This is the default if a program doesn't have a PT_GNU_STACK
  * program header entry. The PPC64 ELF ABI has a non executable stack
- * stack by default, so in the absense of a PT_GNU_STACK program header
+ * stack by default, so in the absence of a PT_GNU_STACK program header
  * we turn execute permission off.
  */
 #define VM_STACK_DEFAULT_FLAGS32	(VM_READ | VM_WRITE | VM_EXEC | \
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/page.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/page.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/page.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/page.h	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,7 @@
 #endif
 
 #ifdef CONFIG_FLATMEM
-#define ARCH_PFN_OFFSET		(MEMORY_START >> PAGE_SHIFT)
+#define ARCH_PFN_OFFSET		((unsigned long)(MEMORY_START >> PAGE_SHIFT))
 #define pfn_valid(pfn)		((pfn) >= ARCH_PFN_OFFSET && (pfn) < max_mapnr)
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pasemi_dma.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pasemi_dma.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pasemi_dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pasemi_dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -522,7 +522,7 @@
 extern void pasemi_dma_free_buf(struct pasemi_dmachan *chan, int size,
 				dma_addr_t *handle);
 
-/* Routines to allocate flags (events) for channel syncronization */
+/* Routines to allocate flags (events) for channel synchronization */
 extern int  pasemi_dma_alloc_flag(void);
 extern void pasemi_dma_free_flag(int flag);
 extern void pasemi_dma_set_flag(int flag);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pci-bridge.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pci-bridge.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pci-bridge.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pci-bridge.h	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 	 * Used for variants of PCI indirect handling and possible quirks:
 	 *  SET_CFG_TYPE - used on 4xx or any PHB that does explicit type0/1
 	 *  EXT_REG - provides access to PCI-e extended registers
-	 *  SURPRESS_PRIMARY_BUS - we surpress the setting of PCI_PRIMARY_BUS
+	 *  SURPRESS_PRIMARY_BUS - we suppress the setting of PCI_PRIMARY_BUS
 	 *   on Freescale PCI-e controllers since they used the PCI_PRIMARY_BUS
 	 *   to determine which bus number to match on when generating type0
 	 *   config cycles
@@ -164,13 +164,23 @@
 			       resource_size_t cfg_addr,
 			       resource_size_t cfg_data, u32 flags);
 
-#ifndef CONFIG_PPC64
-
 static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
 {
 	return bus->sysdata;
 }
 
+#ifndef CONFIG_PPC64
+
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	struct pci_controller *host;
+
+	if (bus->self)
+		return pci_device_to_OF_node(bus->self);
+	host = pci_bus_to_host(bus);
+	return host ? host->dn : NULL;
+}
+
 static inline int isa_vaddr_is_ioport(void __iomem *address)
 {
 	/* No specific ISA handling on ppc32 at this stage, it
@@ -218,19 +228,10 @@
 
 /* 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
- * up (this will only happen once).
- * In this case the sysdata will have been inherited from a PCI host
- * bridge or a PCI-PCI bridge further up the tree, so it will point
- * to a valid struct pci_dn, just not the one we want.
- */
+ * up (this will only happen once). */
 static inline struct device_node *pci_device_to_OF_node(struct pci_dev *dev)
 {
-	struct device_node *dn = dev->sysdata;
-	struct pci_dn *pdn = dn->data;
-
-	if (pdn && pdn->devfn == dev->devfn && pdn->busno == dev->bus->number)
-		return dn;	/* fast path.  sysdata is good */
-	return fetch_dev_dn(dev);
+	return dev->dev.of_node ? dev->dev.of_node : fetch_dev_dn(dev);
 }
 
 static inline int pci_device_from_OF_node(struct device_node *np,
@@ -248,7 +249,7 @@
 	if (bus->self)
 		return pci_device_to_OF_node(bus->self);
 	else
-		return bus->sysdata; /* Must be root bus (PHB) */
+		return bus->dev.of_node; /* Must be root bus (PHB) */
 }
 
 /** Find the bus corresponding to the indicated device node */
@@ -260,14 +261,6 @@
 /** Discover new pci devices under this bus, and add them */
 extern void pcibios_add_pci_devices(struct pci_bus *bus);
 
-static inline struct pci_controller *pci_bus_to_host(const struct pci_bus *bus)
-{
-	struct device_node *busdn = bus->sysdata;
-
-	BUG_ON(busdn == NULL);
-	return PCI_DN(busdn)->phb;
-}
-
 
 extern void isa_bridge_find_early(struct pci_controller *hose);
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pci.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pci.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -201,7 +201,7 @@
 extern void pcibios_setup_bus_devices(struct pci_bus *bus);
 extern void pcibios_setup_bus_self(struct pci_bus *bus);
 extern void pcibios_setup_phb_io_space(struct pci_controller *hose);
-extern void pcibios_scan_phb(struct pci_controller *hose, void *sysdata);
+extern void pcibios_scan_phb(struct pci_controller *hose);
 
 #endif	/* __KERNEL__ */
 #endif /* __ASM_POWERPC_PCI_H */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -170,6 +170,7 @@
 #define pgprot_cached_wthru(prot) (__pgprot((pgprot_val(prot) & ~_PAGE_CACHE_CTL) | \
 				            _PAGE_COHERENT | _PAGE_WRITETHRU))
 
+#define pgprot_writecombine pgprot_noncached_wc
 
 struct file;
 extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pmac_feature.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pmac_feature.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pmac_feature.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pmac_feature.h	2011-05-19 00:06:34.000000000 -0400
@@ -53,8 +53,8 @@
 
 /* Here is the infamous serie of OHare based machines
  */
-#define PMAC_TYPE_COMET			0x20	/* Beleived to be PowerBook 2400 */
-#define PMAC_TYPE_HOOPER		0x21	/* Beleived to be PowerBook 3400 */
+#define PMAC_TYPE_COMET			0x20	/* Believed to be PowerBook 2400 */
+#define PMAC_TYPE_HOOPER		0x21	/* Believed to be PowerBook 3400 */
 #define PMAC_TYPE_KANGA			0x22	/* PowerBook 3500 (first G3) */
 #define PMAC_TYPE_ALCHEMY		0x23	/* Alchemy motherboard base */
 #define PMAC_TYPE_GAZELLE		0x24	/* Spartacus, some 5xxx/6xxx */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/prom.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/prom.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/prom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/prom.h	2011-05-19 00:06:34.000000000 -0400
@@ -70,21 +70,6 @@
 #endif
 #define of_node_to_nid of_node_to_nid
 
-/**
- * of_irq_map_pci - Resolve the interrupt for a PCI device
- * @pdev:	the device whose interrupt is to be resolved
- * @out_irq:	structure of_irq filled by this function
- *
- * This function resolves the PCI interrupt for a given PCI device. If a
- * device-node exists for a given pci_dev, it will use normal OF tree
- * walking. If not, it will implement standard swizzling and walk up the
- * PCI tree until an device-node is found, at which point it will finish
- * resolving using the OF tree walking.
- */
-struct pci_dev;
-struct of_irq;
-extern int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq);
-
 extern void of_instantiate_rtc(void);
 
 /* These includes are put at the bottom because they may contain things
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pte-common.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pte-common.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/pte-common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/pte-common.h	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 #define PTE_RPN_MASK	(~((1UL<<PTE_RPN_SHIFT)-1))
 #endif
 
-/* _PAGE_CHG_MASK masks of bits that are to be preserved accross
+/* _PAGE_CHG_MASK masks of bits that are to be preserved across
  * pgprot changes
  */
 #define _PAGE_CHG_MASK	(PTE_RPN_MASK | _PAGE_HPTEFLAGS | _PAGE_DIRTY | \
@@ -162,7 +162,7 @@
  * on platforms where such control is possible.
  */
 #if defined(CONFIG_KGDB) || defined(CONFIG_XMON) || defined(CONFIG_BDI_SWITCH) ||\
-	defined(CONFIG_KPROBES)
+	defined(CONFIG_KPROBES) || defined(CONFIG_DYNAMIC_FTRACE)
 #define PAGE_KERNEL_TEXT	PAGE_KERNEL_X
 #else
 #define PAGE_KERNEL_TEXT	PAGE_KERNEL_ROX
@@ -174,7 +174,7 @@
 /*
  * Don't just check for any non zero bits in __PAGE_USER, since for book3e
  * and PTE_64BIT, PAGE_KERNEL_X contains _PAGE_BAP_SR which is also in
- * _PAGE_USER.  Need to explictly match _PAGE_BAP_UR bit in that case too.
+ * _PAGE_USER.  Need to explicitly match _PAGE_BAP_UR bit in that case too.
  */
 #define pte_user(val)		((val & _PAGE_USER) == _PAGE_USER)
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -125,8 +125,10 @@
 #endif /* ! __powerpc64__ */
 #define TRAP(regs)		((regs)->trap & ~0xF)
 #ifdef __powerpc64__
+#define NV_REG_POISON		0xdeadbeefdeadbeefUL
 #define CHECK_FULL_REGS(regs)	BUG_ON(regs->trap & 1)
 #else
+#define NV_REG_POISON		0xdeadbeef
 #define CHECK_FULL_REGS(regs)						      \
 do {									      \
 	if ((regs)->trap & 1)						      \
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/qe_ic.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/qe_ic.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/qe_ic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/qe_ic.h	2011-05-19 00:06:34.000000000 -0400
@@ -81,7 +81,7 @@
 static inline void qe_ic_cascade_low_ipic(unsigned int irq,
 					  struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
 	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
 
 	if (cascade_irq != NO_IRQ)
@@ -91,7 +91,7 @@
 static inline void qe_ic_cascade_high_ipic(unsigned int irq,
 					   struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
 	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
 
 	if (cascade_irq != NO_IRQ)
@@ -101,32 +101,35 @@
 static inline void qe_ic_cascade_low_mpic(unsigned int irq,
 					  struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
 	unsigned int cascade_irq = qe_ic_get_low_irq(qe_ic);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static inline void qe_ic_cascade_high_mpic(unsigned int irq,
 					   struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
 	unsigned int cascade_irq = qe_ic_get_high_irq(qe_ic);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static inline void qe_ic_cascade_muxed_mpic(unsigned int irq,
 					    struct irq_desc *desc)
 {
-	struct qe_ic *qe_ic = desc->handler_data;
+	struct qe_ic *qe_ic = irq_desc_get_handler_data(desc);
 	unsigned int cascade_irq;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 
 	cascade_irq = qe_ic_get_high_irq(qe_ic);
 	if (cascade_irq == NO_IRQ)
@@ -135,7 +138,7 @@
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 #endif /* _ASM_POWERPC_QE_IC_H */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/reg_booke.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/reg_booke.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/reg_booke.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/reg_booke.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * Contains register definitions common to the Book E PowerPC
  * specification.  Notice that while the IBM-40x series of CPUs
  * are not true Book E PowerPCs, they borrowed a number of features
- * before Book E was finalized, and are included here as well.  Unfortunatly,
+ * before Book E was finalized, and are included here as well.  Unfortunately,
  * they sometimes used different locations than true Book E CPUs did.
  *
  * This program is free software; you can redistribute it and/or
@@ -110,7 +110,7 @@
 #define SPRN_MAS2	0x272	/* MMU Assist Register 2 */
 #define SPRN_MAS3	0x273	/* MMU Assist Register 3 */
 #define SPRN_MAS4	0x274	/* MMU Assist Register 4 */
-#define SPRN_MAS5	0x275	/* MMU Assist Register 5 */
+#define SPRN_MAS5	0x153	/* MMU Assist Register 5 */
 #define SPRN_MAS6	0x276	/* MMU Assist Register 6 */
 #define SPRN_PID1	0x279	/* Process ID Register 1 */
 #define SPRN_PID2	0x27A	/* Process ID Register 2 */
@@ -150,8 +150,6 @@
  * or IBM 40x.
  */
 #ifdef CONFIG_BOOKE
-#define SPRN_PID	0x030	/* Process ID */
-#define SPRN_PID0	SPRN_PID/* Process ID Register 0 */
 #define SPRN_CSRR0	0x03A	/* Critical Save and Restore Register 0 */
 #define SPRN_CSRR1	0x03B	/* Critical Save and Restore Register 1 */
 #define SPRN_DEAR	0x03D	/* Data Error Address Register */
@@ -168,7 +166,6 @@
 #define SPRN_TCR	0x154	/* Timer Control Register */
 #endif /* Book E */
 #ifdef CONFIG_40x
-#define SPRN_PID	0x3B1	/* Process ID */
 #define SPRN_DBCR1	0x3BD	/* Debug Control Register 1 */		
 #define SPRN_ESR	0x3D4	/* Exception Syndrome Register */
 #define SPRN_DEAR	0x3D5	/* Data Error Address Register */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/reg.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/reg.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -170,6 +170,16 @@
 #define SPEFSCR_FRMC 	0x00000003	/* Embedded FP rounding mode control */
 
 /* Special Purpose Registers (SPRNs)*/
+
+#ifdef CONFIG_40x
+#define SPRN_PID	0x3B1	/* Process ID */
+#else
+#define SPRN_PID	0x030	/* Process ID */
+#ifdef CONFIG_BOOKE
+#define SPRN_PID0	SPRN_PID/* Process ID Register 0 */
+#endif
+#endif
+
 #define SPRN_CTR	0x009	/* Count Register */
 #define SPRN_DSCR	0x11
 #define SPRN_CTRLF	0x088
@@ -852,6 +862,8 @@
 #define PVR_7450	0x80000000
 #define PVR_8540	0x80200000
 #define PVR_8560	0x80200000
+#define PVR_VER_E500V1	0x8020
+#define PVR_VER_E500V2	0x8021
 /*
  * For the 8xx processors, all of them report the same PVR family for
  * the PowerPC core. The various versions of these processors must be
@@ -880,6 +892,7 @@
 #define PV_970		0x0039
 #define PV_POWER5	0x003A
 #define PV_POWER5p	0x003B
+#define PV_POWER7	0x003F
 #define PV_970FX	0x003C
 #define PV_630		0x0040
 #define PV_630p	0x0041
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,11 +13,6 @@
  * by Paul Mackerras <paulus@samba.org>.
  */
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
 /*
  * the semaphore definition
  */
@@ -33,47 +28,6 @@
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
-struct rw_semaphore {
-	long			count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name)				\
-{								\
-	RWSEM_UNLOCKED_VALUE,					\
-	__SPIN_LOCK_UNLOCKED((name).wait_lock),			\
-	LIST_HEAD_INIT((name).wait_list)			\
-	__RWSEM_DEP_MAP_INIT(name)				\
-}
-
-#define DECLARE_RWSEM(name)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)					\
-	do {						\
-		static struct lock_class_key __key;	\
-							\
-		__init_rwsem((sem), #sem, &__key);	\
-	} while (0)
-
 /*
  * lock for reading
  */
@@ -174,10 +128,5 @@
 	return atomic_long_add_return(delta, (atomic_long_t *)&sem->count);
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return sem->count != 0;
-}
-
 #endif	/* __KERNEL__ */
 #endif	/* _ASM_POWERPC_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/smp.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/smp.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/smp.h	2011-05-19 00:06:34.000000000 -0400
@@ -36,15 +36,16 @@
 
 extern void smp_send_debugger_break(int cpu);
 extern void smp_message_recv(int);
+extern void start_secondary_resume(void);
 
 DECLARE_PER_CPU(unsigned int, cpu_pvr);
 
 #ifdef CONFIG_HOTPLUG_CPU
-extern void fixup_irqs(const struct cpumask *map);
+extern void migrate_irqs(void);
 int generic_cpu_disable(void);
-int generic_cpu_enable(unsigned int cpu);
 void generic_cpu_die(unsigned int cpu);
 void generic_mach_cpu_die(void);
+void generic_set_cpu_dead(unsigned int cpu);
 #endif
 
 #ifdef CONFIG_PPC64
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/spu_priv1.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/spu_priv1.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/spu_priv1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/spu_priv1.h	2011-05-19 00:06:34.000000000 -0400
@@ -223,7 +223,7 @@
 }
 
 /*
- * The declarations folowing are put here for convenience
+ * The declarations following are put here for convenience
  * and only intended to be used by the platform setup code.
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/systbl.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/systbl.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/systbl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/systbl.h	2011-05-19 00:06:34.000000000 -0400
@@ -348,3 +348,7 @@
 COMPAT_SYS_SPU(recvmsg)
 COMPAT_SYS_SPU(recvmmsg)
 SYSCALL_SPU(accept4)
+SYSCALL_SPU(name_to_handle_at)
+COMPAT_SYS_SPU(open_by_handle_at)
+COMPAT_SYS_SPU(clock_adjtime)
+SYSCALL_SPU(syncfs)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -72,7 +72,7 @@
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
 extern void free_thread_info(struct thread_info *ti);
 
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/types.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,13 +44,6 @@
 
 typedef __vector128 vector128;
 
-#if defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT)
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
-typedef u64 dma64_addr_t;
-
 typedef struct {
 	unsigned long entry;
 	unsigned long toc;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/uninorth.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/uninorth.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/uninorth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/uninorth.h	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
  *
  * Obviously, the GART is not cache coherent and so any change to it
  * must be flushed to memory (or maybe just make the GART space non
- * cachable). AGP memory itself doens't seem to be cache coherent neither.
+ * cachable). AGP memory itself doesn't seem to be cache coherent neither.
  *
  * In order to invalidate the GART (which is probably necessary to inval
  * the bridge internal TLBs), the following sequence has to be written,
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -367,10 +367,14 @@
 #define __NR_recvmsg		342
 #define __NR_recvmmsg		343
 #define __NR_accept4		344
+#define __NR_name_to_handle_at	345
+#define __NR_open_by_handle_at	346
+#define __NR_clock_adjtime	347
+#define __NR_syncfs		348
 
 #ifdef __KERNEL__
 
-#define __NR_syscalls		345
+#define __NR_syscalls		349
 
 #define __NR__exit __NR_exit
 #define NR_syscalls	__NR_syscalls
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/include/asm/vdso_datapage.h linux-libre-2.6.39-gnu/arch/powerpc/include/asm/vdso_datapage.h
--- linux-libre-2.6.38-gnu/arch/powerpc/include/asm/vdso_datapage.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/include/asm/vdso_datapage.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 	} version;
 
 	/* Note about the platform flags: it now only contains the lpar
-	 * bit. The actual platform number is dead and burried
+	 * bit. The actual platform number is dead and buried
 	 */
 	__u32 platform;			/* Platform flags		0x18 */
 	__u32 processor;		/* Processor type		0x1C */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/Kconfig linux-libre-2.6.39-gnu/arch/powerpc/Kconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -95,6 +95,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_GPIO
 	bool
 	help
@@ -134,6 +138,8 @@
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
 	select IRQ_PER_CPU
+	select GENERIC_IRQ_SHOW
+	select GENERIC_IRQ_SHOW_LEVEL
 
 config EARLY_PRINTK
 	bool
@@ -203,7 +209,7 @@
 config ARCH_SUSPEND_POSSIBLE
 	def_bool y
 	depends on ADB_PMU || PPC_EFIKA || PPC_LITE5200 || PPC_83xx || \
-		   PPC_85xx || PPC_86xx || PPC_PSERIES || 44x || 40x
+		   (PPC_85xx && !SMP) || PPC_86xx || PPC_PSERIES || 44x || 40x
 
 config PPC_DCR_NATIVE
 	bool
@@ -767,11 +773,19 @@
 
 config RAPIDIO
 	bool "RapidIO support"
-	depends on HAS_RAPIDIO
+	depends on HAS_RAPIDIO || PCI
 	help
 	  If you say Y here, the kernel will include drivers and
 	  infrastructure code to support RapidIO interconnect devices.
 
+config FSL_RIO
+	bool "Freescale Embedded SRIO Controller support"
+	depends on RAPIDIO && HAS_RAPIDIO
+	default "n"
+	---help---
+	  Include support for RapidIO controller on Freescale embedded
+	  processors (MPC8548, MPC8641, etc).
+
 source "drivers/rapidio/Kconfig"
 
 endmenu
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/btext.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/btext.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/btext.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/btext.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 
 /* This function can be used to enable the early boot text when doing
  * OF booting or within bootx init. It must be followed by a btext_unmap()
- * call before the logical address becomes unuseable
+ * call before the logical address becomes unusable
  */
 void __init btext_setup_display(int width, int height, int depth, int pitch,
 				unsigned long address)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/cpu_setup_fsl_booke.S	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 	bl	__e500_icache_setup
 	bl	__e500_dcache_setup
 	bl	__setup_e500_ivors
-#ifdef CONFIG_RAPIDIO
+#ifdef CONFIG_FSL_RIO
 	/* Ensure that RFXE is set */
 	mfspr	r3,SPRN_HID1
 	oris	r3,r3,HID1_RFXE@h
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/cputable.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/cputable.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/cputable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/cputable.c	2011-05-19 00:06:34.000000000 -0400
@@ -1811,11 +1811,11 @@
 		.machine_check		= machine_check_440A,
 		.platform		= "ppc440",
 	},
-	{ /* 476 core */
-		.pvr_mask		= 0xffff0000,
-		.pvr_value		= 0x11a50000,
+	{ /* 476 DD2 core */
+		.pvr_mask		= 0xffffffff,
+		.pvr_value		= 0x11a52080,
 		.cpu_name		= "476",
-		.cpu_features		= CPU_FTRS_47X,
+		.cpu_features		= CPU_FTRS_47X | CPU_FTR_476_DD2,
 		.cpu_user_features	= COMMON_USER_BOOKE |
 			PPC_FEATURE_HAS_FPU,
 		.mmu_features		= MMU_FTR_TYPE_47x |
@@ -1839,6 +1839,20 @@
 		.machine_check		= machine_check_47x,
 		.platform		= "ppc470",
 	},
+	{ /* 476 others */
+		.pvr_mask		= 0xffff0000,
+		.pvr_value		= 0x11a50000,
+		.cpu_name		= "476",
+		.cpu_features		= CPU_FTRS_47X,
+		.cpu_user_features	= COMMON_USER_BOOKE |
+			PPC_FEATURE_HAS_FPU,
+		.mmu_features		= MMU_FTR_TYPE_47x |
+			MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
+		.icache_bsize		= 32,
+		.dcache_bsize		= 128,
+		.machine_check		= machine_check_47x,
+		.platform		= "ppc470",
+	},
 	{	/* default match */
 		.pvr_mask		= 0x00000000,
 		.pvr_value		= 0x00000000,
@@ -1959,7 +1973,7 @@
 		.pvr_mask		= 0xffff0000,
 		.pvr_value		= 0x80240000,
 		.cpu_name		= "e5500",
-		.cpu_features		= CPU_FTRS_E500MC,
+		.cpu_features		= CPU_FTRS_E5500,
 		.cpu_user_features	= COMMON_USER_BOOKE,
 		.mmu_features		= MMU_FTR_TYPE_FSL_E | MMU_FTR_BIG_PHYS |
 			MMU_FTR_USE_TLBILX,
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/crash.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/crash.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/crash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/crash.c	2011-05-19 00:06:34.000000000 -0400
@@ -188,7 +188,7 @@
 	}
 	mb();
 }
-#endif
+#endif	/* CONFIG_PPC_STD_MMU_64 */
 
 /*
  * This function will be called by secondary cpus or by kexec cpu
@@ -233,7 +233,9 @@
 	crash_ipi_callback(regs);
 }
 
-#else
+#else	/* ! CONFIG_SMP */
+static inline void crash_kexec_wait_realmode(int cpu) {}
+
 static void crash_kexec_prepare_cpus(int cpu)
 {
 	/*
@@ -253,7 +255,7 @@
 {
 	cpus_in_sr = CPU_MASK_NONE;
 }
-#endif
+#endif	/* CONFIG_SMP */
 
 /*
  * Register a function to be called on shutdown.  Only use this if you
@@ -344,9 +346,7 @@
 	crash_save_cpu(regs, crashing_cpu);
 	crash_kexec_prepare_cpus(crashing_cpu);
 	cpu_set(crashing_cpu, cpus_in_crash);
-#if defined(CONFIG_PPC_STD_MMU_64) && defined(CONFIG_SMP)
 	crash_kexec_wait_realmode(crashing_cpu);
-#endif
 
 	machine_kexec_mask_interrupts();
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/crash_dump.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/crash_dump.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/crash_dump.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/crash_dump.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,9 +28,6 @@
 #define DBG(fmt...)
 #endif
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
 #ifndef CONFIG_RELOCATABLE
 void __init reserve_kdump_trampoline(void)
 {
@@ -72,20 +69,6 @@
 }
 #endif /* CONFIG_RELOCATABLE */
 
-/*
- * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
- * is_kdump_kernel() to determine if we are booting after a panic. Hence
- * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
- */
-static int __init parse_elfcorehdr(char *p)
-{
-	if (p)
-		elfcorehdr_addr = memparse(p, &p);
-
-	return 1;
-}
-__setup("elfcorehdr=", parse_elfcorehdr);
-
 static int __init parse_savemaxmem(char *p)
 {
 	if (p)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/dma.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/dma.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,3 +179,21 @@
        return 0;
 }
 fs_initcall(dma_init);
+
+int dma_mmap_coherent(struct device *dev, struct vm_area_struct *vma,
+		      void *cpu_addr, dma_addr_t handle, size_t size)
+{
+	unsigned long pfn;
+
+#ifdef CONFIG_NOT_COHERENT_CACHE
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	pfn = __dma_get_coherent_pfn((unsigned long)cpu_addr);
+#else
+	pfn = page_to_pfn(virt_to_page(cpu_addr));
+#endif
+	return remap_pfn_range(vma, vma->vm_start,
+			       pfn + vma->vm_pgoff,
+			       vma->vm_end - vma->vm_start,
+			       vma->vm_page_prot);
+}
+EXPORT_SYMBOL_GPL(dma_mmap_coherent);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/exceptions-64e.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/exceptions-64e.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/exceptions-64e.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/exceptions-64e.S	2011-05-19 00:06:34.000000000 -0400
@@ -379,7 +379,7 @@
 	mfspr	r13,SPRN_SPRG_PACA	/* get our PACA */
 	b	system_call_common
 
-/* Auxillary Processor Unavailable Interrupt */
+/* Auxiliary Processor Unavailable Interrupt */
 	START_EXCEPTION(ap_unavailable);
 	NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE)
 	EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/exceptions-64s.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/exceptions-64s.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/exceptions-64s.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/exceptions-64s.S	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
  * handling and other fixed offset specific things.
  *
  * This file is meant to be #included from head_64.S due to
- * position dependant assembly.
+ * position dependent assembly.
  *
  * Most of this originates from head_64.S and thus has the same
  * copyright history.
@@ -977,20 +977,6 @@
 	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.
@@ -1027,3 +1013,17 @@
 #ifdef CONFIG_PPC_PSERIES
         . = 0x8000
 #endif /* CONFIG_PPC_PSERIES */
+
+/*
+ * 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 above), so this must be at a
+ * fixed address (the linker can't compute (u64)&initial_stab >>
+ * PAGE_SHIFT).
+ */
+	. = STAB0_OFFSET	/* 0x8000 */
+	.globl initial_stab
+initial_stab:
+	.space	4096
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_32.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_32.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -890,6 +890,15 @@
 	mtspr	SPRN_SRR1,r4
 	SYNC
 	RFI
+
+_GLOBAL(start_secondary_resume)
+	/* Reset stack */
+	rlwinm	r1,r1,0,0,(31-THREAD_SHIFT)	/* current_thread_info() */
+	addi	r1,r1,THREAD_SIZE-STACK_FRAME_OVERHEAD
+	li	r3,0
+	std	r3,0(r1)		/* Zero the stack frame pointer	*/
+	bl	start_secondary
+	b	.
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_KVM_BOOK3S_HANDLER
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_40x.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_40x.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_40x.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_40x.S	2011-05-19 00:06:34.000000000 -0400
@@ -766,7 +766,7 @@
 	 * miss get to this point to load the TLB.
 	 * 	r10 - TLB_TAG value
 	 * 	r11 - Linux PTE
-	 *	r12, r9 - avilable to use
+	 *	r12, r9 - available to use
 	 *	PID - loaded with proper value when we get here
 	 *	Upon exit, we reload everything and RFI.
 	 * Actually, it will fit now, but oh well.....a common place
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_44x.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_44x.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_44x.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_44x.S	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,7 @@
 	NORMAL_EXCEPTION_PROLOG
 	EXC_XFER_EE_LITE(0x0c00, DoSyscall)
 
-	/* Auxillary Processor Unavailable Interrupt */
+	/* Auxiliary Processor Unavailable Interrupt */
 	EXCEPTION(0x2020, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
 
 	/* Decrementer Interrupt */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_64.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_64.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 #include <asm/kvm_book3s_asm.h>
 #include <asm/ptrace.h>
 
-/* The physical memory is layed out such that the secondary processor
+/* The physical memory is laid 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
  */
@@ -536,6 +536,13 @@
 	add	r13,r13,r4		/* for this processor.		*/
 	mtspr	SPRN_SPRG_PACA,r13	/* Save vaddr of paca in an SPRG*/
 
+	/* Mark interrupts soft and hard disabled (they might be enabled
+	 * in the PACA when doing hotplug)
+	 */
+	li	r0,0
+	stb	r0,PACASOFTIRQEN(r13)
+	stb	r0,PACAHARDIRQEN(r13)
+
 	/* Create a temp kernel stack for use before relocation is on.	*/
 	ld	r1,PACAEMERGSP(r13)
 	subi	r1,r1,STACK_FRAME_OVERHEAD
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_fsl_booke.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_fsl_booke.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/head_fsl_booke.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/head_fsl_booke.S	2011-05-19 00:06:34.000000000 -0400
@@ -326,7 +326,7 @@
 	NORMAL_EXCEPTION_PROLOG
 	EXC_XFER_EE_LITE(0x0c00, DoSyscall)
 
-	/* Auxillary Processor Unavailable Interrupt */
+	/* Auxiliary Processor Unavailable Interrupt */
 	EXCEPTION(0x2900, AuxillaryProcessorUnavailable, unknown_exception, EXC_XFER_EE)
 
 	/* Decrementer Interrupt */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/ibmebus.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/ibmebus.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/ibmebus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/ibmebus.c	2011-05-19 00:06:34.000000000 -0400
@@ -201,13 +201,14 @@
 	/* If the driver uses devices that ibmebus doesn't know, add them */
 	ibmebus_create_devices(drv->driver.of_match_table);
 
-	return of_register_driver(drv, &ibmebus_bus_type);
+	drv->driver.bus = &ibmebus_bus_type;
+	return driver_register(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_register_driver);
 
 void ibmebus_unregister_driver(struct of_platform_driver *drv)
 {
-	of_unregister_driver(drv);
+	driver_unregister(&drv->driver);
 }
 EXPORT_SYMBOL(ibmebus_unregister_driver);
 
@@ -308,15 +309,410 @@
 	}
 }
 
+
 static struct bus_attribute ibmebus_bus_attrs[] = {
 	__ATTR(probe, S_IWUSR, NULL, ibmebus_store_probe),
 	__ATTR(remove, S_IWUSR, NULL, ibmebus_store_remove),
 	__ATTR_NULL
 };
 
+static int ibmebus_bus_bus_match(struct device *dev, struct device_driver *drv)
+{
+	const struct of_device_id *matches = drv->of_match_table;
+
+	if (!matches)
+		return 0;
+
+	return of_match_device(matches, dev) != NULL;
+}
+
+static int ibmebus_bus_device_probe(struct device *dev)
+{
+	int error = -ENODEV;
+	struct of_platform_driver *drv;
+	struct platform_device *of_dev;
+	const struct of_device_id *match;
+
+	drv = to_of_platform_driver(dev->driver);
+	of_dev = to_platform_device(dev);
+
+	if (!drv->probe)
+		return error;
+
+	of_dev_get(of_dev);
+
+	match = of_match_device(drv->driver.of_match_table, dev);
+	if (match)
+		error = drv->probe(of_dev, match);
+	if (error)
+		of_dev_put(of_dev);
+
+	return error;
+}
+
+static int ibmebus_bus_device_remove(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->remove)
+		drv->remove(of_dev);
+	return 0;
+}
+
+static void ibmebus_bus_device_shutdown(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+
+	if (dev->driver && drv->shutdown)
+		drv->shutdown(of_dev);
+}
+
+/*
+ * ibmebus_bus_device_attrs
+ */
+static ssize_t devspec_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *ofdev;
+
+	ofdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
+}
+
+static ssize_t name_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct platform_device *ofdev;
+
+	ofdev = to_platform_device(dev);
+	return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
+}
+
+static ssize_t modalias_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
+	buf[len] = '\n';
+	buf[len+1] = 0;
+	return len+1;
+}
+
+struct device_attribute ibmebus_bus_device_attrs[] = {
+	__ATTR_RO(devspec),
+	__ATTR_RO(name),
+	__ATTR_RO(modalias),
+	__ATTR_NULL
+};
+
+#ifdef CONFIG_PM_SLEEP
+static int ibmebus_bus_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+	int ret = 0;
+
+	if (dev->driver && drv->suspend)
+		ret = drv->suspend(of_dev, mesg);
+	return ret;
+}
+
+static int ibmebus_bus_legacy_resume(struct device *dev)
+{
+	struct platform_device *of_dev = to_platform_device(dev);
+	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
+	int ret = 0;
+
+	if (dev->driver && drv->resume)
+		ret = drv->resume(of_dev);
+	return ret;
+}
+
+static int ibmebus_bus_pm_prepare(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (drv && drv->pm && drv->pm->prepare)
+		ret = drv->pm->prepare(dev);
+
+	return ret;
+}
+
+static void ibmebus_bus_pm_complete(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+
+	if (drv && drv->pm && drv->pm->complete)
+		drv->pm->complete(dev);
+}
+
+#ifdef CONFIG_SUSPEND
+
+static int ibmebus_bus_pm_suspend(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend)
+			ret = drv->pm->suspend(dev);
+	} else {
+		ret = ibmebus_bus_legacy_suspend(dev, PMSG_SUSPEND);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_suspend_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend_noirq)
+			ret = drv->pm->suspend_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_resume(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume)
+			ret = drv->pm->resume(dev);
+	} else {
+		ret = ibmebus_bus_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_resume_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume_noirq)
+			ret = drv->pm->resume_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_SUSPEND */
+
+#define ibmebus_bus_pm_suspend		NULL
+#define ibmebus_bus_pm_resume		NULL
+#define ibmebus_bus_pm_suspend_noirq	NULL
+#define ibmebus_bus_pm_resume_noirq	NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+
+static int ibmebus_bus_pm_freeze(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze)
+			ret = drv->pm->freeze(dev);
+	} else {
+		ret = ibmebus_bus_legacy_suspend(dev, PMSG_FREEZE);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_freeze_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze_noirq)
+			ret = drv->pm->freeze_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_thaw(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw)
+			ret = drv->pm->thaw(dev);
+	} else {
+		ret = ibmebus_bus_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_thaw_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw_noirq)
+			ret = drv->pm->thaw_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_poweroff(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff)
+			ret = drv->pm->poweroff(dev);
+	} else {
+		ret = ibmebus_bus_legacy_suspend(dev, PMSG_HIBERNATE);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_poweroff_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff_noirq)
+			ret = drv->pm->poweroff_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_restore(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore)
+			ret = drv->pm->restore(dev);
+	} else {
+		ret = ibmebus_bus_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int ibmebus_bus_pm_restore_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore_noirq)
+			ret = drv->pm->restore_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
+
+#define ibmebus_bus_pm_freeze		NULL
+#define ibmebus_bus_pm_thaw		NULL
+#define ibmebus_bus_pm_poweroff		NULL
+#define ibmebus_bus_pm_restore		NULL
+#define ibmebus_bus_pm_freeze_noirq	NULL
+#define ibmebus_bus_pm_thaw_noirq		NULL
+#define ibmebus_bus_pm_poweroff_noirq	NULL
+#define ibmebus_bus_pm_restore_noirq	NULL
+
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
+
+static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
+	.prepare = ibmebus_bus_pm_prepare,
+	.complete = ibmebus_bus_pm_complete,
+	.suspend = ibmebus_bus_pm_suspend,
+	.resume = ibmebus_bus_pm_resume,
+	.freeze = ibmebus_bus_pm_freeze,
+	.thaw = ibmebus_bus_pm_thaw,
+	.poweroff = ibmebus_bus_pm_poweroff,
+	.restore = ibmebus_bus_pm_restore,
+	.suspend_noirq = ibmebus_bus_pm_suspend_noirq,
+	.resume_noirq = ibmebus_bus_pm_resume_noirq,
+	.freeze_noirq = ibmebus_bus_pm_freeze_noirq,
+	.thaw_noirq = ibmebus_bus_pm_thaw_noirq,
+	.poweroff_noirq = ibmebus_bus_pm_poweroff_noirq,
+	.restore_noirq = ibmebus_bus_pm_restore_noirq,
+};
+
+#define IBMEBUS_BUS_PM_OPS_PTR	(&ibmebus_bus_dev_pm_ops)
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define IBMEBUS_BUS_PM_OPS_PTR	NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
 struct bus_type ibmebus_bus_type = {
+	.name      = "ibmebus",
 	.uevent    = of_device_uevent,
-	.bus_attrs = ibmebus_bus_attrs
+	.bus_attrs = ibmebus_bus_attrs,
+	.match     = ibmebus_bus_bus_match,
+	.probe     = ibmebus_bus_device_probe,
+	.remove    = ibmebus_bus_device_remove,
+	.shutdown  = ibmebus_bus_device_shutdown,
+	.dev_attrs = ibmebus_bus_device_attrs,
+	.pm        = IBMEBUS_BUS_PM_OPS_PTR,
 };
 EXPORT_SYMBOL(ibmebus_bus_type);
 
@@ -326,7 +722,7 @@
 
 	printk(KERN_INFO "IBM eBus Device Driver\n");
 
-	err = of_bus_type_init(&ibmebus_bus_type, "ibmebus");
+	err = bus_register(&ibmebus_bus_type);
 	if (err) {
 		printk(KERN_ERR "%s: failed to register IBM eBus.\n",
 		       __func__);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/idle_power4.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/idle_power4.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/idle_power4.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/idle_power4.S	2011-05-19 00:06:34.000000000 -0400
@@ -53,24 +53,3 @@
 	isync
 	b	1b
 
-_GLOBAL(power4_cpu_offline_powersave)
-	/* Go to NAP now */
-	mfmsr	r7
-	rldicl	r0,r7,48,1
-	rotldi	r0,r0,16
-	mtmsrd	r0,1			/* hard-disable interrupts */
-	li	r0,1
-	li	r6,0
-	stb	r0,PACAHARDIRQEN(r13)	/* we'll hard-enable shortly */
-	stb	r6,PACASOFTIRQEN(r13)	/* soft-disable irqs */
-BEGIN_FTR_SECTION
-	DSSALL
-	sync
-END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
-	ori	r7,r7,MSR_EE
-	oris	r7,r7,MSR_POW@h
-	sync
-	isync
-	mtmsrd	r7
-	isync
-	blr
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/irq.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -195,7 +195,7 @@
 EXPORT_SYMBOL(arch_local_irq_restore);
 #endif /* CONFIG_PPC64 */
 
-static int show_other_interrupts(struct seq_file *p, int prec)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	int j;
 
@@ -231,63 +231,6 @@
 	return 0;
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	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);
-
-	/* print header */
-	if (i == 0) {
-		seq_printf(p, "%*s", prec + 8, "");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	desc = irq_to_desc(i);
-	if (!desc)
-		return 0;
-
-	raw_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));
-
-	if (desc->chip)
-		seq_printf(p, "  %-16s", desc->chip->name);
-	else
-		seq_printf(p, "  %-16s", "None");
-	seq_printf(p, " %-8s", (desc->status & IRQ_LEVEL) ? "Level" : "Edge");
-
-	if (action) {
-		seq_printf(p, "     %s", action->name);
-		while ((action = action->next) != NULL)
-			seq_printf(p, ", %s", action->name);
-	}
-
-	seq_putc(p, '\n');
-out:
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	return 0;
-}
-
 /*
  * /proc/stat helpers
  */
@@ -303,30 +246,37 @@
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-void fixup_irqs(const struct cpumask *map)
+void migrate_irqs(void)
 {
 	struct irq_desc *desc;
 	unsigned int irq;
 	static int warned;
 	cpumask_var_t mask;
+	const struct cpumask *map = cpu_online_mask;
 
 	alloc_cpumask_var(&mask, GFP_KERNEL);
 
 	for_each_irq(irq) {
+		struct irq_data *data;
+		struct irq_chip *chip;
+
 		desc = irq_to_desc(irq);
 		if (!desc)
 			continue;
 
-		if (desc->status & IRQ_PER_CPU)
+		data = irq_desc_get_irq_data(desc);
+		if (irqd_is_per_cpu(data))
 			continue;
 
-		cpumask_and(mask, desc->affinity, map);
+		chip = irq_data_get_irq_chip(data);
+
+		cpumask_and(mask, data->affinity, map);
 		if (cpumask_any(mask) >= nr_cpu_ids) {
 			printk("Breaking affinity for irq %i\n", irq);
 			cpumask_copy(mask, map);
 		}
-		if (desc->chip->set_affinity)
-			desc->chip->set_affinity(irq, mask);
+		if (chip->irq_set_affinity)
+			chip->irq_set_affinity(data, mask, true);
 		else if (desc->action && !(warned++))
 			printk("Cannot set affinity for irq %i\n", irq);
 	}
@@ -612,7 +562,7 @@
 			smp_wmb();
 
 			/* Clear norequest flags */
-			irq_to_desc(i)->status &= ~IRQ_NOREQUEST;
+			irq_clear_status_flags(i, IRQ_NOREQUEST);
 
 			/* Legacy flags are left to default at this point,
 			 * one can then use irq_create_mapping() to
@@ -678,16 +628,15 @@
 static int irq_setup_virq(struct irq_host *host, unsigned int virq,
 			    irq_hw_number_t hwirq)
 {
-	struct irq_desc *desc;
+	int res;
 
-	desc = irq_to_desc_alloc_node(virq, 0);
-	if (!desc) {
+	res = irq_alloc_desc_at(virq, 0);
+	if (res != virq) {
 		pr_debug("irq: -> allocating desc failed\n");
 		goto error;
 	}
 
-	/* Clear IRQ_NOREQUEST flag */
-	desc->status &= ~IRQ_NOREQUEST;
+	irq_clear_status_flags(virq, IRQ_NOREQUEST);
 
 	/* map it */
 	smp_wmb();
@@ -696,11 +645,13 @@
 
 	if (host->ops->map(host, virq, hwirq)) {
 		pr_debug("irq: -> mapping failed, freeing\n");
-		goto error;
+		goto errdesc;
 	}
 
 	return 0;
 
+errdesc:
+	irq_free_descs(virq, 1);
 error:
 	irq_free_virt(virq, 1);
 	return -1;
@@ -820,8 +771,8 @@
 
 	/* Set type if specified and different than the current one */
 	if (type != IRQ_TYPE_NONE &&
-	    type != (irq_to_desc(virq)->status & IRQF_TRIGGER_MASK))
-		set_irq_type(virq, type);
+	    type != (irqd_get_trigger_type(irq_get_irq_data(virq))))
+		irq_set_irq_type(virq, type);
 	return virq;
 }
 EXPORT_SYMBOL_GPL(irq_create_of_mapping);
@@ -844,7 +795,7 @@
 		return;
 
 	/* remove chip and handler */
-	set_irq_chip_and_handler(virq, NULL, NULL);
+	irq_set_chip_and_handler(virq, NULL, NULL);
 
 	/* Make sure it's completed */
 	synchronize_irq(virq);
@@ -879,9 +830,9 @@
 	smp_mb();
 	irq_map[virq].hwirq = host->inval_irq;
 
-	/* Set some flags */
-	irq_to_desc(virq)->status |= IRQ_NOREQUEST;
+	irq_set_status_flags(virq, IRQ_NOREQUEST);
 
+	irq_free_descs(virq, 1);
 	/* Free it */
 	irq_free_virt(virq, 1);
 }
@@ -1074,21 +1025,6 @@
 
 int arch_early_irq_init(void)
 {
-	struct irq_desc *desc;
-	int i;
-
-	for (i = 0; i < NR_IRQS; i++) {
-		desc = irq_to_desc(i);
-		if (desc)
-			desc->status |= IRQ_NOREQUEST;
-	}
-
-	return 0;
-}
-
-int arch_init_chip_data(struct irq_desc *desc, int node)
-{
-	desc->status |= IRQ_NOREQUEST;
 	return 0;
 }
 
@@ -1159,11 +1095,14 @@
 		raw_spin_lock_irqsave(&desc->lock, flags);
 
 		if (desc->action && desc->action->handler) {
+			struct irq_chip *chip;
+
 			seq_printf(m, "%5d  ", i);
 			seq_printf(m, "0x%05lx  ", virq_to_hw(i));
 
-			if (desc->chip && desc->chip->name)
-				p = desc->chip->name;
+			chip = irq_desc_get_chip(desc);
+			if (chip && chip->name)
+				p = chip->name;
 			else
 				p = none;
 			seq_printf(m, "%-15s  ", p);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/l2cr_6xx.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/l2cr_6xx.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/l2cr_6xx.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/l2cr_6xx.S	2011-05-19 00:06:34.000000000 -0400
@@ -151,7 +151,7 @@
 	 /**** Might be a good idea to set L2DO here - to prevent instructions
 	       from getting into the cache.  But since we invalidate
 	       the next time we enable the cache it doesn't really matter.
-	       Don't do this unless you accomodate all processor variations.
+	       Don't do this unless you accommodate all processor variations.
 	       The bit moved on the 7450.....
 	  ****/
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/legacy_serial.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/legacy_serial.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/legacy_serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/legacy_serial.c	2011-05-19 00:06:34.000000000 -0400
@@ -330,9 +330,11 @@
 		if (!parent)
 			continue;
 		if (of_match_node(legacy_serial_parents, parent) != NULL) {
-			index = add_legacy_soc_port(np, np);
-			if (index >= 0 && np == stdout)
-				legacy_serial_console = index;
+			if (of_device_is_available(np)) {
+				index = add_legacy_soc_port(np, np);
+				if (index >= 0 && np == stdout)
+					legacy_serial_console = index;
+			}
 		}
 		of_node_put(parent);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/lparcfg.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/lparcfg.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/lparcfg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/lparcfg.c	2011-05-19 00:06:34.000000000 -0400
@@ -262,7 +262,7 @@
 	seq_printf(m, "system_active_processors=%d\n",
 	           ppp_data.active_system_procs);
 
-	/* pool related entries are apropriate for shared configs */
+	/* pool related entries are appropriate for shared configs */
 	if (lppaca_of(0).shared_proc) {
 		unsigned long pool_idle_time, pool_procs;
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/machine_kexec.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/machine_kexec.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/machine_kexec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/machine_kexec.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,20 +26,23 @@
 
 	for_each_irq(i) {
 		struct irq_desc *desc = irq_to_desc(i);
+		struct irq_chip *chip;
 
-		if (!desc || !desc->chip)
+		if (!desc)
 			continue;
 
-		if (desc->chip->eoi &&
-		    desc->status & IRQ_INPROGRESS)
-			desc->chip->eoi(i);
+		chip = irq_desc_get_chip(desc);
+		if (!chip)
+			continue;
 
-		if (desc->chip->mask)
-			desc->chip->mask(i);
+		if (chip->irq_eoi && irqd_irq_inprogress(&desc->irq_data))
+			chip->irq_eoi(&desc->irq_data);
 
-		if (desc->chip->disable &&
-		    !(desc->status & IRQ_DISABLED))
-			desc->chip->disable(i);
+		if (chip->irq_mask)
+			chip->irq_mask(&desc->irq_data);
+
+		if (chip->irq_disable && !irqd_irq_disabled(&desc->irq_data))
+			chip->irq_disable(&desc->irq_data);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/nvram_64.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/nvram_64.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/nvram_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/nvram_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -237,22 +237,45 @@
 	return c_sum;
 }
 
+/*
+ * Per the criteria passed via nvram_remove_partition(), should this
+ * partition be removed?  1=remove, 0=keep
+ */
+static int nvram_can_remove_partition(struct nvram_partition *part,
+		const char *name, int sig, const char *exceptions[])
+{
+	if (part->header.signature != sig)
+		return 0;
+	if (name) {
+		if (strncmp(name, part->header.name, 12))
+			return 0;
+	} else if (exceptions) {
+		const char **except;
+		for (except = exceptions; *except; except++) {
+			if (!strncmp(*except, part->header.name, 12))
+				return 0;
+		}
+	}
+	return 1;
+}
+
 /**
  * nvram_remove_partition - Remove one or more partitions in nvram
  * @name: name of the partition to remove, or NULL for a
  *        signature only match
  * @sig: signature of the partition(s) to remove
+ * @exceptions: When removing all partitions with a matching signature,
+ *        leave these alone.
  */
 
-int __init nvram_remove_partition(const char *name, int sig)
+int __init nvram_remove_partition(const char *name, int sig,
+						const char *exceptions[])
 {
 	struct nvram_partition *part, *prev, *tmp;
 	int rc;
 
 	list_for_each_entry(part, &nvram_partitions, partition) {
-		if (part->header.signature != sig)
-			continue;
-		if (name && strncmp(name, part->header.name, 12))
+		if (!nvram_can_remove_partition(part, name, sig, exceptions))
 			continue;
 
 		/* Make partition a free partition */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/of_platform.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/of_platform.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/of_platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/of_platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,8 +36,7 @@
  * lacking some bits needed here.
  */
 
-static int __devinit of_pci_phb_probe(struct platform_device *dev,
-				      const struct of_device_id *match)
+static int __devinit of_pci_phb_probe(struct platform_device *dev)
 {
 	struct pci_controller *phb;
 
@@ -74,7 +73,7 @@
 #endif /* CONFIG_EEH */
 
 	/* Scan the bus */
-	pcibios_scan_phb(phb, dev->dev.of_node);
+	pcibios_scan_phb(phb);
 	if (phb->bus == NULL)
 		return -ENXIO;
 
@@ -104,7 +103,7 @@
 	{}
 };
 
-static struct of_platform_driver of_pci_phb_driver = {
+static struct platform_driver of_pci_phb_driver = {
 	.probe = of_pci_phb_probe,
 	.driver = {
 		.name = "of-pci",
@@ -115,7 +114,7 @@
 
 static __init int of_pci_phb_init(void)
 {
-	return of_register_platform_driver(&of_pci_phb_driver);
+	return platform_driver_register(&of_pci_phb_driver);
 }
 
 device_initcall(of_pci_phb_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/paca.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/paca.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/paca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/paca.c	2011-05-19 00:06:34.000000000 -0400
@@ -203,7 +203,7 @@
 {
 	int new_size;
 
-	new_size = PAGE_ALIGN(sizeof(struct paca_struct) * num_possible_cpus());
+	new_size = PAGE_ALIGN(sizeof(struct paca_struct) * nr_cpu_ids);
 
 	if (new_size >= paca_size)
 		return;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_32.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_32.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -381,7 +381,7 @@
 		if (pci_assign_all_buses)
 			hose->first_busno = next_busno;
 		hose->last_busno = 0xff;
-		pcibios_scan_phb(hose, hose);
+		pcibios_scan_phb(hose);
 		pci_bus_add_devices(hose->bus);
 		if (pci_assign_all_buses || next_busno <= hose->last_busno)
 			next_busno = hose->last_busno + pcibios_assign_bus_offset;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_64.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_64.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 
 	/* Scan all of the recorded PCI controllers.  */
 	list_for_each_entry_safe(hose, tmp, &hose_list, list_node) {
-		pcibios_scan_phb(hose, hose->dn);
+		pcibios_scan_phb(hose);
 		pci_bus_add_devices(hose->bus);
 	}
 
@@ -242,10 +242,10 @@
 			break;
 		bus = NULL;
 	}
-	if (bus == NULL || bus->sysdata == NULL)
+	if (bus == NULL || bus->dev.of_node == NULL)
 		return -ENODEV;
 
-	hose_node = (struct device_node *)bus->sysdata;
+	hose_node = bus->dev.of_node;
 	hose = PCI_DN(hose_node)->phb;
 
 	switch (which) {
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci-common.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci-common.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/init.h>
 #include <linux/bootmem.h>
 #include <linux/of_address.h>
+#include <linux/of_pci.h>
 #include <linux/mm.h>
 #include <linux/list.h>
 #include <linux/syscalls.h>
@@ -260,7 +261,7 @@
 
 		virq = irq_create_mapping(NULL, line);
 		if (virq != NO_IRQ)
-			set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
 	} else {
 		pr_debug(" Got one, spec %d cells (0x%08x 0x%08x...) on %s\n",
 			 oirq.size, oirq.specifier[0], oirq.specifier[1],
@@ -1687,13 +1688,8 @@
 /**
  * pci_scan_phb - Given a pci_controller, setup and scan the PCI bus
  * @hose: Pointer to the PCI host controller instance structure
- * @sysdata: value to use for sysdata pointer.  ppc32 and ppc64 differ here
- *
- * Note: the 'data' pointer is a temporary measure.  As 32 and 64 bit
- * pci code gets merged, this parameter should become unnecessary because
- * both will use the same value.
  */
-void __devinit pcibios_scan_phb(struct pci_controller *hose, void *sysdata)
+void __devinit pcibios_scan_phb(struct pci_controller *hose)
 {
 	struct pci_bus *bus;
 	struct device_node *node = hose->dn;
@@ -1703,13 +1699,13 @@
 		 node ? node->full_name : "<NO NAME>");
 
 	/* Create an empty bus for the toplevel */
-	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops,
-			     sysdata);
+	bus = pci_create_bus(hose->parent, hose->first_busno, hose->ops, hose);
 	if (bus == NULL) {
 		pr_err("Failed to create bus for PCI domain %04x\n",
 			hose->global_number);
 		return;
 	}
+	bus->dev.of_node = of_node_get(node);
 	bus->secondary = hose->first_busno;
 	hose->bus = bus;
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_dn.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_dn.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_dn.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_dn.c	2011-05-19 00:06:34.000000000 -0400
@@ -161,7 +161,7 @@
 /*
  * This is the "slow" path for looking up a device_node from a
  * pci_dev.  It will hunt for the device under its parent's
- * phb and then update sysdata for a future fastpath.
+ * phb and then update of_node pointer.
  *
  * It may also do fixups on the actual device since this happens
  * on the first read/write.
@@ -170,16 +170,22 @@
  * In this case it may probe for real hardware ("just in case")
  * and add a device_node to the device tree if necessary.
  *
+ * Is this function necessary anymore now that dev->dev.of_node is
+ * used to store the node pointer?
+ *
  */
 struct device_node *fetch_dev_dn(struct pci_dev *dev)
 {
-	struct device_node *orig_dn = dev->sysdata;
+	struct pci_controller *phb = dev->sysdata;
 	struct device_node *dn;
 	unsigned long searchval = (dev->bus->number << 8) | dev->devfn;
 
-	dn = traverse_pci_devices(orig_dn, is_devfn_node, (void *)searchval);
+	if (WARN_ON(!phb))
+		return NULL;
+
+	dn = traverse_pci_devices(phb->dn, is_devfn_node, (void *)searchval);
 	if (dn)
-		dev->sysdata = dn;
+		dev->dev.of_node = dn;
 	return dn;
 }
 EXPORT_SYMBOL(fetch_dev_dn);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_of_scan.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_of_scan.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/pci_of_scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/pci_of_scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,7 +135,7 @@
 	pr_debug("    create device, devfn: %x, type: %s\n", devfn, type);
 
 	dev->bus = bus;
-	dev->sysdata = node;
+	dev->dev.of_node = of_node_get(node);
 	dev->dev.parent = bus->bridge;
 	dev->dev.bus = &pci_bus_type;
 	dev->devfn = devfn;
@@ -238,7 +238,7 @@
 	bus->primary = dev->bus->number;
 	bus->subordinate = busrange[1];
 	bus->bridge_ctl = 0;
-	bus->sysdata = node;
+	bus->dev.of_node = of_node_get(node);
 
 	/* parse ranges property */
 	/* PCI #address-cells == 3 and #size-cells == 2 always */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/perf_event.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/perf_event.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/perf_event.c	2011-05-19 00:06:34.000000000 -0400
@@ -398,6 +398,25 @@
 	return 0;
 }
 
+static u64 check_and_compute_delta(u64 prev, u64 val)
+{
+	u64 delta = (val - prev) & 0xfffffffful;
+
+	/*
+	 * POWER7 can roll back counter values, if the new value is smaller
+	 * than the previous value it will cause the delta and the counter to
+	 * have bogus values unless we rolled a counter over.  If a coutner is
+	 * rolled back, it will be smaller, but within 256, which is the maximum
+	 * number of events to rollback at once.  If we dectect a rollback
+	 * return 0.  This can lead to a small lack of precision in the
+	 * counters.
+	 */
+	if (prev > val && (prev - val) < 256)
+		delta = 0;
+
+	return delta;
+}
+
 static void power_pmu_read(struct perf_event *event)
 {
 	s64 val, delta, prev;
@@ -416,10 +435,11 @@
 		prev = local64_read(&event->hw.prev_count);
 		barrier();
 		val = read_pmc(event->hw.idx);
+		delta = check_and_compute_delta(prev, val);
+		if (!delta)
+			return;
 	} while (local64_cmpxchg(&event->hw.prev_count, prev, val) != prev);
 
-	/* The counters are only 32 bits wide */
-	delta = (val - prev) & 0xfffffffful;
 	local64_add(delta, &event->count);
 	local64_sub(delta, &event->hw.period_left);
 }
@@ -449,8 +469,9 @@
 		val = (event->hw.idx == 5) ? pmc5 : pmc6;
 		prev = local64_read(&event->hw.prev_count);
 		event->hw.idx = 0;
-		delta = (val - prev) & 0xfffffffful;
-		local64_add(delta, &event->count);
+		delta = check_and_compute_delta(prev, val);
+		if (delta)
+			local64_add(delta, &event->count);
 	}
 }
 
@@ -458,14 +479,16 @@
 				  unsigned long pmc5, unsigned long pmc6)
 {
 	struct perf_event *event;
-	u64 val;
+	u64 val, prev;
 	int i;
 
 	for (i = 0; i < cpuhw->n_limited; ++i) {
 		event = cpuhw->limited_counter[i];
 		event->hw.idx = cpuhw->limited_hwidx[i];
 		val = (event->hw.idx == 5) ? pmc5 : pmc6;
-		local64_set(&event->hw.prev_count, val);
+		prev = local64_read(&event->hw.prev_count);
+		if (check_and_compute_delta(prev, val))
+			local64_set(&event->hw.prev_count, val);
 		perf_event_update_userpage(event);
 	}
 }
@@ -759,7 +782,7 @@
 
 	/*
 	 * If group events scheduling transaction was started,
-	 * skip the schedulability test here, it will be peformed
+	 * skip the schedulability test here, it will be performed
 	 * at commit time(->commit_txn) as a whole
 	 */
 	if (cpuhw->group_flag & PERF_EVENT_TXN)
@@ -1197,7 +1220,7 @@
 
 	/* we don't have to worry about interrupts here */
 	prev = local64_read(&event->hw.prev_count);
-	delta = (val - prev) & 0xfffffffful;
+	delta = check_and_compute_delta(prev, val);
 	local64_add(delta, &event->count);
 
 	/*
@@ -1269,6 +1292,28 @@
 	return ip;
 }
 
+static bool pmc_overflow(unsigned long val)
+{
+	if ((int)val < 0)
+		return true;
+
+	/*
+	 * Events on POWER7 can roll back if a speculative event doesn't
+	 * eventually complete. Unfortunately in some rare cases they will
+	 * raise a performance monitor exception. We need to catch this to
+	 * ensure we reset the PMC. In all cases the PMC will be 256 or less
+	 * cycles from overflow.
+	 *
+	 * We only do this if the first pass fails to find any overflowing
+	 * PMCs because a user might set a period of less than 256 and we
+	 * don't want to mistakenly reset them.
+	 */
+	if (__is_processor(PV_POWER7) && ((0x80000000 - val) <= 256))
+		return true;
+
+	return false;
+}
+
 /*
  * Performance monitor interrupt stuff
  */
@@ -1316,7 +1361,7 @@
 			if (is_limited_pmc(i + 1))
 				continue;
 			val = read_pmc(i + 1);
-			if ((int)val < 0)
+			if (pmc_overflow(val))
 				write_pmc(i + 1, 0);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/ppc_save_regs.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/ppc_save_regs.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/ppc_save_regs.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/ppc_save_regs.S	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 
 /*
  * Grab the register values as they are now.
- * This won't do a particularily good job because we really
+ * This won't do a particularly good job because we really
  * want our caller's caller's registers, and our caller has
  * already executed its prologue.
  * ToDo: We could reach back into the caller's save area to do
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/process.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -1218,11 +1218,11 @@
 
 static struct kmem_cache *thread_info_cache;
 
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
 {
 	struct thread_info *ti;
 
-	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
+	ti = kmem_cache_alloc_node(thread_info_cache, GFP_KERNEL, node);
 	if (unlikely(ti == NULL))
 		return NULL;
 #ifdef CONFIG_DEBUG_STACK_USAGE
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/prom.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/prom.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/prom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/prom.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 	start = __pa(initial_boot_params);
 	size = be32_to_cpu(initial_boot_params->totalsize);
 
-	if ((memory_limit && (start + size) > memory_limit) ||
+	if ((memory_limit && (start + size) > PHYSICAL_START + memory_limit) ||
 			overlaps_crashkernel(start, size)) {
 		p = __va(memblock_alloc(size, PAGE_SIZE));
 		memcpy(p, initial_boot_params, size);
@@ -683,7 +683,7 @@
 #endif
 
 #ifdef CONFIG_PHYP_DUMP
-	/* scan tree to see if dump occured during last boot */
+	/* scan tree to see if dump occurred during last boot */
 	of_scan_flat_dt(early_init_dt_scan_phyp_dump, NULL);
 #endif
 
@@ -739,7 +739,7 @@
 
 	DBG("Scanning CPUs ...\n");
 
-	/* Retreive CPU related informations from the flat tree
+	/* Retrieve CPU related informations from the flat tree
 	 * (altivec support, boot CPU ID, ...)
 	 */
 	of_scan_flat_dt(early_init_dt_scan_cpus, NULL);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/prom_parse.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/prom_parse.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/prom_parse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/prom_parse.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,95 +2,11 @@
 
 #include <linux/kernel.h>
 #include <linux/string.h>
-#include <linux/pci_regs.h>
 #include <linux/module.h>
 #include <linux/ioport.h>
 #include <linux/etherdevice.h>
 #include <linux/of_address.h>
 #include <asm/prom.h>
-#include <asm/pci-bridge.h>
-
-#ifdef CONFIG_PCI
-int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
-{
-	struct device_node *dn, *ppnode;
-	struct pci_dev *ppdev;
-	u32 lspec;
-	u32 laddr[3];
-	u8 pin;
-	int rc;
-
-	/* Check if we have a device node, if yes, fallback to standard OF
-	 * parsing
-	 */
-	dn = pci_device_to_OF_node(pdev);
-	if (dn) {
-		rc = of_irq_map_one(dn, 0, out_irq);
-		if (!rc)
-			return rc;
-	}
-
-	/* Ok, we don't, time to have fun. Let's start by building up an
-	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
-	 * for PCI. If you do different, then don't use that routine.
-	 */
-	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
-	if (rc != 0)
-		return rc;
-	/* No pin, exit */
-	if (pin == 0)
-		return -ENODEV;
-
-	/* Now we walk up the PCI tree */
-	lspec = pin;
-	for (;;) {
-		/* Get the pci_dev of our parent */
-		ppdev = pdev->bus->self;
-
-		/* Ouch, it's a host bridge... */
-		if (ppdev == NULL) {
-#ifdef CONFIG_PPC64
-			ppnode = pci_bus_to_OF_node(pdev->bus);
-#else
-			struct pci_controller *host;
-			host = pci_bus_to_host(pdev->bus);
-			ppnode = host ? host->dn : NULL;
-#endif
-			/* No node for host bridge ? give up */
-			if (ppnode == NULL)
-				return -EINVAL;
-		} else
-			/* We found a P2P bridge, check if it has a node */
-			ppnode = pci_device_to_OF_node(ppdev);
-
-		/* Ok, we have found a parent with a device-node, hand over to
-		 * the OF parsing code.
-		 * We build a unit address from the linux device to be used for
-		 * resolution. Note that we use the linux bus number which may
-		 * not match your firmware bus numbering.
-		 * Fortunately, in most cases, interrupt-map-mask doesn't include
-		 * the bus number as part of the matching.
-		 * You should still be careful about that though if you intend
-		 * to rely on this function (you ship  a firmware that doesn't
-		 * create device nodes for all PCI devices).
-		 */
-		if (ppnode)
-			break;
-
-		/* We can only get here if we hit a P2P bridge with no node,
-		 * let's do standard swizzling and try again
-		 */
-		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
-		pdev = ppdev;
-	}
-
-	laddr[0] = (pdev->bus->number << 16)
-		| (pdev->devfn << 8);
-	laddr[1]  = laddr[2] = 0;
-	return of_irq_map_raw(ppnode, &lspec, 1, laddr, out_irq);
-}
-EXPORT_SYMBOL_GPL(of_irq_map_pci);
-#endif /* CONFIG_PCI */
 
 void of_parse_dma_window(struct device_node *dn, const void *dma_window_prop,
 		unsigned long *busno, unsigned long *phys, unsigned long *size)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -229,12 +229,16 @@
 		   unsigned int pos, unsigned int count,
 		   void *kbuf, void __user *ubuf)
 {
-	int ret;
+	int i, ret;
 
 	if (target->thread.regs == NULL)
 		return -EIO;
 
-	CHECK_FULL_REGS(target->thread.regs);
+	if (!FULL_REGS(target->thread.regs)) {
+		/* We have a partial register set.  Fill 14-31 with bogus values */
+		for (i = 14; i < 32; i++)
+			target->thread.regs->gpr[i] = NV_REG_POISON;
+	}
 
 	ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf,
 				  target->thread.regs,
@@ -459,7 +463,7 @@
 #ifdef CONFIG_VSX
 /*
  * Currently to set and and get all the vsx state, you need to call
- * the fp and VMX calls aswell.  This only get/sets the lower 32
+ * the fp and VMX calls as well.  This only get/sets the lower 32
  * 128bit VSX registers.
  */
 
@@ -641,11 +645,16 @@
 	compat_ulong_t *k = kbuf;
 	compat_ulong_t __user *u = ubuf;
 	compat_ulong_t reg;
+	int i;
 
 	if (target->thread.regs == NULL)
 		return -EIO;
 
-	CHECK_FULL_REGS(target->thread.regs);
+	if (!FULL_REGS(target->thread.regs)) {
+		/* We have a partial register set.  Fill 14-31 with bogus values */
+		for (i = 14; i < 32; i++)
+			target->thread.regs->gpr[i] = NV_REG_POISON; 
+	}
 
 	pos /= sizeof(reg);
 	count /= sizeof(reg);
@@ -924,12 +933,16 @@
 	if (data && !(data & DABR_TRANSLATION))
 		return -EIO;
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
+	if (ptrace_get_breakpoints(task) < 0)
+		return -ESRCH;
+
 	bp = thread->ptrace_bps[0];
 	if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) {
 		if (bp) {
 			unregister_hw_breakpoint(bp);
 			thread->ptrace_bps[0] = NULL;
 		}
+		ptrace_put_breakpoints(task);
 		return 0;
 	}
 	if (bp) {
@@ -939,9 +952,12 @@
 					(DABR_DATA_WRITE | DABR_DATA_READ),
 							&attr.bp_type);
 		ret =  modify_user_hw_breakpoint(bp, &attr);
-		if (ret)
+		if (ret) {
+			ptrace_put_breakpoints(task);
 			return ret;
+		}
 		thread->ptrace_bps[0] = bp;
+		ptrace_put_breakpoints(task);
 		thread->dabr = data;
 		return 0;
 	}
@@ -956,9 +972,12 @@
 							ptrace_triggered, task);
 	if (IS_ERR(bp)) {
 		thread->ptrace_bps[0] = NULL;
+		ptrace_put_breakpoints(task);
 		return PTR_ERR(bp);
 	}
 
+	ptrace_put_breakpoints(task);
+
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
 	/* Move contents to the DABR register */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/rtasd.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/rtasd.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/rtasd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/rtasd.c	2011-05-19 00:06:34.000000000 -0400
@@ -412,7 +412,8 @@
 
 	get_online_cpus();
 
-	cpu = cpumask_next(smp_processor_id(), cpu_online_mask);
+	/* raw_ OK because just using CPU as starting point. */
+	cpu = cpumask_next(raw_smp_processor_id(), cpu_online_mask);
         if (cpu >= nr_cpu_ids) {
 		cpu = cpumask_first(cpu_online_mask);
 
@@ -464,7 +465,7 @@
 	pr_debug("rtasd: will sleep for %d milliseconds\n",
 		 (30000 / rtas_event_scan_rate));
 
-	/* Retreive errors from nvram if any */
+	/* Retrieve errors from nvram if any */
 	retreive_nvram_error_log();
 
 	schedule_delayed_work_on(cpumask_first(cpu_online_mask),
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/setup-common.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/setup-common.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/setup-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/setup-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -509,6 +509,9 @@
 	 */
 	cpu_init_thread_core_maps(nthreads);
 
+	/* Now that possible cpus are set, set nr_cpu_ids for later use */
+	nr_cpu_ids = find_last_bit(cpumask_bits(cpu_possible_mask),NR_CPUS) + 1;
+
 	free_unused_pacas();
 }
 #endif /* CONFIG_SMP */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/smp.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/smp.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,6 +57,25 @@
 #define DBG(fmt...)
 #endif
 
+
+/* Store all idle threads, this can be reused instead of creating
+* a new thread. Also avoids complicated thread destroy functionality
+* for idle threads.
+*/
+#ifdef CONFIG_HOTPLUG_CPU
+/*
+ * Needed only for CONFIG_HOTPLUG_CPU because __cpuinitdata is
+ * removed after init for !CONFIG_HOTPLUG_CPU.
+ */
+static DEFINE_PER_CPU(struct task_struct *, idle_thread_array);
+#define get_idle_for_cpu(x)      (per_cpu(idle_thread_array, x))
+#define set_idle_for_cpu(x, p)   (per_cpu(idle_thread_array, x) = (p))
+#else
+static struct task_struct *idle_thread_array[NR_CPUS] __cpuinitdata ;
+#define get_idle_for_cpu(x)      (idle_thread_array[(x)])
+#define set_idle_for_cpu(x, p)   (idle_thread_array[(x)] = (p))
+#endif
+
 struct thread_info *secondary_ti;
 
 DEFINE_PER_CPU(cpumask_var_t, cpu_sibling_map);
@@ -238,23 +257,6 @@
 	per_cpu(cpu_pvr, id) = mfspr(SPRN_PVR);
 }
 
-static void __init smp_create_idle(unsigned int cpu)
-{
-	struct task_struct *p;
-
-	/* create a process for the processor */
-	p = fork_idle(cpu);
-	if (IS_ERR(p))
-		panic("failed fork for CPU %u: %li", cpu, PTR_ERR(p));
-#ifdef CONFIG_PPC64
-	paca[cpu].__current = p;
-	paca[cpu].kstack = (unsigned long) task_thread_info(p)
-		+ THREAD_SIZE - STACK_FRAME_OVERHEAD;
-#endif
-	current_set[cpu] = task_thread_info(p);
-	task_thread_info(p)->cpu = cpu;
-}
-
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
 	unsigned int cpu;
@@ -288,10 +290,6 @@
 			max_cpus = NR_CPUS;
 	else
 		max_cpus = 1;
-
-	for_each_possible_cpu(cpu)
-		if (cpu != boot_cpuid)
-			smp_create_idle(cpu);
 }
 
 void __devinit smp_prepare_boot_cpu(void)
@@ -305,7 +303,7 @@
 
 #ifdef CONFIG_HOTPLUG_CPU
 /* State of each CPU during hotplug phases */
-DEFINE_PER_CPU(int, cpu_state) = { 0 };
+static DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
 int generic_cpu_disable(void)
 {
@@ -317,30 +315,8 @@
 	set_cpu_online(cpu, false);
 #ifdef CONFIG_PPC64
 	vdso_data->processorCount--;
-	fixup_irqs(cpu_online_mask);
-#endif
-	return 0;
-}
-
-int generic_cpu_enable(unsigned int cpu)
-{
-	/* Do the normal bootup if we haven't
-	 * already bootstrapped. */
-	if (system_state != SYSTEM_RUNNING)
-		return -ENOSYS;
-
-	/* get the target out of it's holding state */
-	per_cpu(cpu_state, cpu) = CPU_UP_PREPARE;
-	smp_wmb();
-
-	while (!cpu_online(cpu))
-		cpu_relax();
-
-#ifdef CONFIG_PPC64
-	fixup_irqs(cpu_online_mask);
-	/* counter the irq disable in fixup_irqs */
-	local_irq_enable();
 #endif
+	migrate_irqs();
 	return 0;
 }
 
@@ -362,37 +338,89 @@
 	unsigned int cpu;
 
 	local_irq_disable();
+	idle_task_exit();
 	cpu = smp_processor_id();
 	printk(KERN_DEBUG "CPU%d offline\n", cpu);
 	__get_cpu_var(cpu_state) = CPU_DEAD;
 	smp_wmb();
 	while (__get_cpu_var(cpu_state) != CPU_UP_PREPARE)
 		cpu_relax();
-	set_cpu_online(cpu, true);
-	local_irq_enable();
+}
+
+void generic_set_cpu_dead(unsigned int cpu)
+{
+	per_cpu(cpu_state, cpu) = CPU_DEAD;
 }
 #endif
 
-static int __devinit cpu_enable(unsigned int cpu)
+struct create_idle {
+	struct work_struct work;
+	struct task_struct *idle;
+	struct completion done;
+	int cpu;
+};
+
+static void __cpuinit do_fork_idle(struct work_struct *work)
 {
-	if (smp_ops && smp_ops->cpu_enable)
-		return smp_ops->cpu_enable(cpu);
+	struct create_idle *c_idle =
+		container_of(work, struct create_idle, work);
 
-	return -ENOSYS;
+	c_idle->idle = fork_idle(c_idle->cpu);
+	complete(&c_idle->done);
+}
+
+static int __cpuinit create_idle(unsigned int cpu)
+{
+	struct thread_info *ti;
+	struct create_idle c_idle = {
+		.cpu	= cpu,
+		.done	= COMPLETION_INITIALIZER_ONSTACK(c_idle.done),
+	};
+	INIT_WORK_ONSTACK(&c_idle.work, do_fork_idle);
+
+	c_idle.idle = get_idle_for_cpu(cpu);
+
+	/* We can't use kernel_thread since we must avoid to
+	 * reschedule the child. We use a workqueue because
+	 * we want to fork from a kernel thread, not whatever
+	 * userspace process happens to be trying to online us.
+	 */
+	if (!c_idle.idle) {
+		schedule_work(&c_idle.work);
+		wait_for_completion(&c_idle.done);
+	} else
+		init_idle(c_idle.idle, cpu);
+	if (IS_ERR(c_idle.idle)) {		
+		pr_err("Failed fork for CPU %u: %li", cpu, PTR_ERR(c_idle.idle));
+		return PTR_ERR(c_idle.idle);
+	}
+	ti = task_thread_info(c_idle.idle);
+
+#ifdef CONFIG_PPC64
+	paca[cpu].__current = c_idle.idle;
+	paca[cpu].kstack = (unsigned long)ti + THREAD_SIZE - STACK_FRAME_OVERHEAD;
+#endif
+	ti->cpu = cpu;
+	current_set[cpu] = ti;
+
+	return 0;
 }
 
 int __cpuinit __cpu_up(unsigned int cpu)
 {
-	int c;
+	int rc, c;
 
 	secondary_ti = current_set[cpu];
-	if (!cpu_enable(cpu))
-		return 0;
 
 	if (smp_ops == NULL ||
 	    (smp_ops->cpu_bootable && !smp_ops->cpu_bootable(cpu)))
 		return -EINVAL;
 
+	/* Make sure we have an idle thread */
+	rc = create_idle(cpu);
+	if (rc)
+		return rc;
+
 	/* Make sure callin-map entry is 0 (can be leftover a CPU
 	 * hotplug
 	 */
@@ -502,7 +530,7 @@
 }
 
 /* Activate a secondary processor. */
-int __devinit start_secondary(void *unused)
+void __devinit start_secondary(void *unused)
 {
 	unsigned int cpu = smp_processor_id();
 	struct device_node *l2_cache;
@@ -523,6 +551,10 @@
 
 	secondary_cpu_time_init();
 
+#ifdef CONFIG_PPC64
+	if (system_state == SYSTEM_RUNNING)
+		vdso_data->processorCount++;
+#endif
 	ipi_call_lock();
 	notify_cpu_starting(cpu);
 	set_cpu_online(cpu, true);
@@ -558,7 +590,8 @@
 	local_irq_enable();
 
 	cpu_idle();
-	return 0;
+
+	BUG();
 }
 
 int setup_profiling_timer(unsigned int multiplier)
@@ -585,7 +618,11 @@
 
 	free_cpumask_var(old_mask);
 
+	if (smp_ops && smp_ops->bringup_done)
+		smp_ops->bringup_done();
+
 	dump_numa_cpu_topology();
+
 }
 
 int arch_sd_sibling_asym_packing(void)
@@ -660,5 +697,9 @@
 {
 	if (ppc_md.cpu_die)
 		ppc_md.cpu_die();
+
+	/* If we return, we re-enter start_secondary */
+	start_secondary_resume();
 }
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/swsusp_32.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/swsusp_32.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/swsusp_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/swsusp_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -143,7 +143,7 @@
 
 	/* Disable MSR:DR to make sure we don't take a TLB or
 	 * hash miss during the copy, as our hash table will
-	 * for a while be unuseable. For .text, we assume we are
+	 * for a while be unusable. For .text, we assume we are
 	 * covered by a BAT. This works only for non-G5 at this
 	 * point. G5 will need a better approach, possibly using
 	 * a small temporary hash table filled with large mappings,
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/time.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -229,6 +229,9 @@
 	u64 stolen = 0;
 	u64 dtb;
 
+	if (!dtl)
+		return 0;
+
 	if (i == vpa->dtl_idx)
 		return 0;
 	while (i < vpa->dtl_idx) {
@@ -356,7 +359,7 @@
 	}
 	get_paca()->user_time_scaled += user_scaled;
 
-	if (in_irq() || idle_task(smp_processor_id()) != tsk) {
+	if (in_interrupt() || idle_task(smp_processor_id()) != tsk) {
 		account_system_time(tsk, 0, delta, sys_scaled);
 		if (stolen)
 			account_steal_time(stolen);
@@ -577,14 +580,21 @@
 	struct clock_event_device *evt = &decrementer->event;
 	u64 now;
 
+	/* Ensure a positive value is written to the decrementer, or else
+	 * some CPUs will continue to take decrementer exceptions.
+	 */
+	set_dec(DECREMENTER_MAX);
+
+	/* Some implementations of hotplug will get timer interrupts while
+	 * offline, just ignore these
+	 */
+	if (!cpu_online(smp_processor_id()))
+		return;
+
 	trace_timer_interrupt_entry(regs);
 
 	__get_cpu_var(irq_stat).timer_irqs++;
 
-	/* Ensure a positive value is written to the decrementer, or else
-	 * some CPUs will continuue to take decrementer exceptions */
-	set_dec(DECREMENTER_MAX);
-
 #if defined(CONFIG_PPC32) && defined(CONFIG_PMAC)
 	if (atomic_read(&ppc_n_lost_interrupts) != 0)
 		do_IRQ(regs);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/traps.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/traps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -959,7 +959,7 @@
 	 * ESR_DST (!?) or 0.  In the process of chasing this with the
 	 * hardware people - not sure if it can happen on any illegal
 	 * instruction or only on FP instructions, whether there is a
-	 * pattern to occurences etc. -dgibson 31/Mar/2003 */
+	 * pattern to occurrences etc. -dgibson 31/Mar/2003 */
 	switch (do_mathemu(regs)) {
 	case 0:
 		emulate_single_step(regs);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/udbg_16550.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/udbg_16550.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/udbg_16550.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/udbg_16550.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * udbg for NS16550 compatable serial ports
+ * udbg for NS16550 compatible serial ports
  *
  * Copyright (C) 2001-2005 PPC 64 Team, IBM Corp
  *
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/vdso32/sigtramp.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/vdso32/sigtramp.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/vdso32/sigtramp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/vdso32/sigtramp.S	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 
 /* The nop here is a hack.  The dwarf2 unwind routines subtract 1 from
    the return address to get an address in the middle of the presumed
-   call instruction.  Since we don't have a call here, we artifically
+   call instruction.  Since we don't have a call here, we artificially
    extend the range covered by the unwind info by adding a nop before
    the real start.  */
 	nop
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/vdso64/sigtramp.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/vdso64/sigtramp.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/vdso64/sigtramp.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/vdso64/sigtramp.S	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
 
 /* The nop here is a hack.  The dwarf2 unwind routines subtract 1 from
    the return address to get an address in the middle of the presumed
-   call instruction.  Since we don't have a call here, we artifically
+   call instruction.  Since we don't have a call here, we artificially
    extend the range covered by the unwind info by padding before the
    real start.  */
 	nop
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/vdso.c linux-libre-2.6.39-gnu/arch/powerpc/kernel/vdso.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/vdso.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/vdso.c	2011-05-19 00:06:34.000000000 -0400
@@ -820,17 +820,17 @@
 }
 arch_initcall(vdso_init);
 
-int in_gate_area_no_task(unsigned long addr)
+int in_gate_area_no_mm(unsigned long addr)
 {
 	return 0;
 }
 
-int in_gate_area(struct task_struct *task, unsigned long addr)
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
 {
 	return 0;
 }
 
-struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 {
 	return NULL;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/powerpc/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/powerpc/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -160,7 +160,7 @@
 		INIT_RAM_FS
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 
 	. = ALIGN(8);
 	.machine.desc : AT(ADDR(.machine.desc) - LOAD_OFFSET) {
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kvm/book3s.c linux-libre-2.6.39-gnu/arch/powerpc/kvm/book3s.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kvm/book3s.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kvm/book3s.c	2011-05-19 00:06:34.000000000 -0400
@@ -1141,9 +1141,10 @@
 	regs->sprg1 = vcpu->arch.shared->sprg1;
 	regs->sprg2 = vcpu->arch.shared->sprg2;
 	regs->sprg3 = vcpu->arch.shared->sprg3;
-	regs->sprg5 = vcpu->arch.sprg4;
-	regs->sprg6 = vcpu->arch.sprg5;
-	regs->sprg7 = vcpu->arch.sprg6;
+	regs->sprg4 = vcpu->arch.sprg4;
+	regs->sprg5 = vcpu->arch.sprg5;
+	regs->sprg6 = vcpu->arch.sprg6;
+	regs->sprg7 = vcpu->arch.sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -1167,9 +1168,10 @@
 	vcpu->arch.shared->sprg1 = regs->sprg1;
 	vcpu->arch.shared->sprg2 = regs->sprg2;
 	vcpu->arch.shared->sprg3 = regs->sprg3;
-	vcpu->arch.sprg5 = regs->sprg4;
-	vcpu->arch.sprg6 = regs->sprg5;
-	vcpu->arch.sprg7 = regs->sprg6;
+	vcpu->arch.sprg4 = regs->sprg4;
+	vcpu->arch.sprg5 = regs->sprg5;
+	vcpu->arch.sprg6 = regs->sprg6;
+	vcpu->arch.sprg7 = regs->sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/kvm/booke.c linux-libre-2.6.39-gnu/arch/powerpc/kvm/booke.c
--- linux-libre-2.6.38-gnu/arch/powerpc/kvm/booke.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/kvm/booke.c	2011-05-19 00:06:34.000000000 -0400
@@ -546,9 +546,10 @@
 	regs->sprg1 = vcpu->arch.shared->sprg1;
 	regs->sprg2 = vcpu->arch.shared->sprg2;
 	regs->sprg3 = vcpu->arch.shared->sprg3;
-	regs->sprg5 = vcpu->arch.sprg4;
-	regs->sprg6 = vcpu->arch.sprg5;
-	regs->sprg7 = vcpu->arch.sprg6;
+	regs->sprg4 = vcpu->arch.sprg4;
+	regs->sprg5 = vcpu->arch.sprg5;
+	regs->sprg6 = vcpu->arch.sprg6;
+	regs->sprg7 = vcpu->arch.sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		regs->gpr[i] = kvmppc_get_gpr(vcpu, i);
@@ -572,9 +573,10 @@
 	vcpu->arch.shared->sprg1 = regs->sprg1;
 	vcpu->arch.shared->sprg2 = regs->sprg2;
 	vcpu->arch.shared->sprg3 = regs->sprg3;
-	vcpu->arch.sprg5 = regs->sprg4;
-	vcpu->arch.sprg6 = regs->sprg5;
-	vcpu->arch.sprg7 = regs->sprg6;
+	vcpu->arch.sprg4 = regs->sprg4;
+	vcpu->arch.sprg5 = regs->sprg5;
+	vcpu->arch.sprg6 = regs->sprg6;
+	vcpu->arch.sprg7 = regs->sprg7;
 
 	for (i = 0; i < ARRAY_SIZE(regs->gpr); i++)
 		kvmppc_set_gpr(vcpu, i, regs->gpr[i]);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/math-emu/math_efp.c linux-libre-2.6.39-gnu/arch/powerpc/math-emu/math_efp.c
--- linux-libre-2.6.38-gnu/arch/powerpc/math-emu/math_efp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/math-emu/math_efp.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * arch/powerpc/math-emu/math_efp.c
  *
- * Copyright (C) 2006-2008 Freescale Semiconductor, Inc. All rights reserved.
+ * Copyright (C) 2006-2008, 2010 Freescale Semiconductor, Inc.
  *
  * Author: Ebony Zhu,	<ebony.zhu@freescale.com>
  *         Yu Liu,	<yu.liu@freescale.com>
@@ -104,6 +104,8 @@
 #define FP_EX_MASK	(FP_EX_INEXACT | FP_EX_INVALID | FP_EX_DIVZERO | \
 			FP_EX_UNDERFLOW | FP_EX_OVERFLOW)
 
+static int have_e500_cpu_a005_erratum;
+
 union dw_union {
 	u64 dp[1];
 	u32 wp[2];
@@ -320,7 +322,8 @@
 			} else {
 				_FP_ROUND_ZERO(1, SB);
 			}
-			FP_TO_INT_S(vc.wp[1], SB, 32, ((func & 0x3) != 0));
+			FP_TO_INT_S(vc.wp[1], SB, 32,
+					(((func & 0x3) != 0) || SB_s));
 			goto update_regs;
 
 		default:
@@ -458,7 +461,8 @@
 			} else {
 				_FP_ROUND_ZERO(2, DB);
 			}
-			FP_TO_INT_D(vc.wp[1], DB, 32, ((func & 0x3) != 0));
+			FP_TO_INT_D(vc.wp[1], DB, 32,
+					(((func & 0x3) != 0) || DB_s));
 			goto update_regs;
 
 		default:
@@ -589,8 +593,10 @@
 				_FP_ROUND_ZERO(1, SB0);
 				_FP_ROUND_ZERO(1, SB1);
 			}
-			FP_TO_INT_S(vc.wp[0], SB0, 32, ((func & 0x3) != 0));
-			FP_TO_INT_S(vc.wp[1], SB1, 32, ((func & 0x3) != 0));
+			FP_TO_INT_S(vc.wp[0], SB0, 32,
+					(((func & 0x3) != 0) || SB0_s));
+			FP_TO_INT_S(vc.wp[1], SB1, 32,
+					(((func & 0x3) != 0) || SB1_s));
 			goto update_regs;
 
 		default:
@@ -652,6 +658,15 @@
 	return 0;
 
 illegal:
+	if (have_e500_cpu_a005_erratum) {
+		/* according to e500 cpu a005 erratum, reissue efp inst */
+		regs->nip -= 4;
+#ifdef DEBUG
+		printk(KERN_DEBUG "re-issue efp inst: %08lx\n", speinsn);
+#endif
+		return 0;
+	}
+
 	printk(KERN_ERR "\nOoops! IEEE-754 compliance handler encountered un-supported instruction.\ninst code: %08lx\n", speinsn);
 	return -ENOSYS;
 }
@@ -718,3 +733,43 @@
 
 	return 0;
 }
+
+int __init spe_mathemu_init(void)
+{
+	u32 pvr, maj, min;
+
+	pvr = mfspr(SPRN_PVR);
+
+	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
+	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
+		maj = PVR_MAJ(pvr);
+		min = PVR_MIN(pvr);
+
+		/*
+		 * E500 revision below 1.1, 2.3, 3.1, 4.1, 5.1
+		 * need cpu a005 errata workaround
+		 */
+		switch (maj) {
+		case 1:
+			if (min < 1)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		case 2:
+			if (min < 3)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		case 3:
+		case 4:
+		case 5:
+			if (min < 1)
+				have_e500_cpu_a005_erratum = 1;
+			break;
+		default:
+			break;
+		}
+	}
+
+	return 0;
+}
+
+module_init(spe_mathemu_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/dma-noncoherent.c linux-libre-2.6.39-gnu/arch/powerpc/mm/dma-noncoherent.c
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/dma-noncoherent.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/dma-noncoherent.c	2011-05-19 00:06:34.000000000 -0400
@@ -399,3 +399,23 @@
 #endif
 }
 EXPORT_SYMBOL(__dma_sync_page);
+
+/*
+ * Return the PFN for a given cpu virtual address returned by
+ * __dma_alloc_coherent. This is used by dma_mmap_coherent()
+ */
+unsigned long __dma_get_coherent_pfn(unsigned long cpu_addr)
+{
+	/* This should always be populated, so we don't test every
+	 * level. If that fails, we'll have a nice crash which
+	 * will be as good as a BUG_ON()
+	 */
+	pgd_t *pgd = pgd_offset_k(cpu_addr);
+	pud_t *pud = pud_offset(pgd, cpu_addr);
+	pmd_t *pmd = pmd_offset(pud, cpu_addr);
+	pte_t *ptep = pte_offset_kernel(pmd, cpu_addr);
+
+	if (pte_none(*ptep) || !pte_present(*ptep))
+		return 0;
+	return pte_pfn(*ptep);
+}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/hash_low_64.S linux-libre-2.6.39-gnu/arch/powerpc/mm/hash_low_64.S
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/hash_low_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/hash_low_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -192,8 +192,8 @@
 	rldicr	r3,r0,3,63-3		/* r3 = (hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retreive new pp bits */
-	mr	r4,r29			/* Retreive va */
+	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve va */
 	li	r7,0			/* !bolted, !secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARM(r9)(r1)	/* segment size */
@@ -215,8 +215,8 @@
 	rldicr	r3,r0,3,63-3	/* r0 = (~hash & mask) << 3 */
 	
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retreive new pp bits */
-	mr	r4,r29			/* Retreive va */
+	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve va */
 	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARM(r9)(r1)	/* segment size */
@@ -495,8 +495,8 @@
 	rldicr	r3,r0,3,63-3		/* r0 = (hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retreive new pp bits */
-	mr	r4,r29			/* Retreive va */
+	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve va */
 	li	r7,0			/* !bolted, !secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARM(r9)(r1)	/* segment size */
@@ -522,8 +522,8 @@
 	rldicr	r3,r0,3,63-3		/* r0 = (~hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retreive new pp bits */
-	mr	r4,r29			/* Retreive va */
+	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve va */
 	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
 	li	r8,MMU_PAGE_4K		/* page size */
 	ld	r9,STK_PARM(r9)(r1)	/* segment size */
@@ -813,8 +813,8 @@
 	rldicr	r3,r0,3,63-3	/* r0 = (hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retreive new pp bits */
-	mr	r4,r29			/* Retreive va */
+	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve va */
 	li	r7,0			/* !bolted, !secondary */
 	li	r8,MMU_PAGE_64K
 	ld	r9,STK_PARM(r9)(r1)	/* segment size */
@@ -836,8 +836,8 @@
 	rldicr	r3,r0,3,63-3	/* r0 = (~hash & mask) << 3 */
 
 	/* Call ppc_md.hpte_insert */
-	ld	r6,STK_PARM(r4)(r1)	/* Retreive new pp bits */
-	mr	r4,r29			/* Retreive va */
+	ld	r6,STK_PARM(r4)(r1)	/* Retrieve new pp bits */
+	mr	r4,r29			/* Retrieve va */
 	li	r7,HPTE_V_SECONDARY	/* !bolted, secondary */
 	li	r8,MMU_PAGE_64K
 	ld	r9,STK_PARM(r9)(r1)	/* segment size */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/hash_utils_64.c linux-libre-2.6.39-gnu/arch/powerpc/mm/hash_utils_64.c
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/hash_utils_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/hash_utils_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -753,7 +753,7 @@
 		mtspr(SPRN_SDR1, _SDR1);
 
 	/* Initialize STAB/SLB. We use a virtual address as it works
-	 * in real mode on pSeries and we want a virutal address on
+	 * in real mode on pSeries and we want a virtual address on
 	 * iSeries anyway
 	 */
 	if (cpu_has_feature(CPU_FTR_SLB))
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/init_32.c linux-libre-2.6.39-gnu/arch/powerpc/mm/init_32.c
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/init_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/init_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,7 +148,7 @@
 		lowmem_end_addr = memstart_addr + total_lowmem;
 #ifndef CONFIG_HIGHMEM
 		total_memory = total_lowmem;
-		memblock_enforce_memory_limit(lowmem_end_addr);
+		memblock_enforce_memory_limit(total_lowmem);
 		memblock_analyze();
 #endif /* CONFIG_HIGHMEM */
 	}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/mem.c linux-libre-2.6.39-gnu/arch/powerpc/mm/mem.c
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/mem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/mem.c	2011-05-19 00:06:34.000000000 -0400
@@ -424,7 +424,7 @@
 	clear_page(page);
 
 	/*
-	 * We shouldnt have to do this, but some versions of glibc
+	 * We shouldn't have to do this, but some versions of glibc
 	 * require it (ld.so assumes zero filled pages are icache clean)
 	 * - Anton
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/numa.c linux-libre-2.6.39-gnu/arch/powerpc/mm/numa.c
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/numa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/numa.c	2011-05-19 00:06:34.000000000 -0400
@@ -440,11 +440,11 @@
 }
 
 /*
- * Retreive and validate the ibm,dynamic-memory property of the device tree.
+ * Retrieve and validate the ibm,dynamic-memory property of the device tree.
  *
  * The layout of the ibm,dynamic-memory property is a number N of memblock
  * list entries followed by N memblock list entries.  Each memblock list entry
- * contains information as layed out in the of_drconf_cell struct above.
+ * contains information as laid out in the of_drconf_cell struct above.
  */
 static int of_get_drconf_memory(struct device_node *memory, const u32 **dm)
 {
@@ -468,7 +468,7 @@
 }
 
 /*
- * Retreive and validate the ibm,lmb-size property for drconf memory
+ * Retrieve and validate the ibm,lmb-size property for drconf memory
  * from the device tree.
  */
 static u64 of_get_lmb_size(struct device_node *memory)
@@ -490,7 +490,7 @@
 };
 
 /*
- * Retreive and validate the list of associativity arrays for drconf
+ * Retrieve and validate the list of associativity arrays for drconf
  * memory from the ibm,associativity-lookup-arrays property of the
  * device tree..
  *
@@ -604,7 +604,7 @@
  * Returns the size the region should have to enforce the memory limit.
  * This will either be the original value of size, a truncated value,
  * or zero. If the returned value of size is 0 the region should be
- * discarded as it lies wholy above the memory limit.
+ * discarded as it lies wholly above the memory limit.
  */
 static unsigned long __init numa_enforce_memory_limit(unsigned long start,
 						      unsigned long size)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/tlb_low_64e.S linux-libre-2.6.39-gnu/arch/powerpc/mm/tlb_low_64e.S
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/tlb_low_64e.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/tlb_low_64e.S	2011-05-19 00:06:34.000000000 -0400
@@ -192,7 +192,7 @@
 	or	r10,r15,r14
 
 BEGIN_MMU_FTR_SECTION
-	/* Set the TLB reservation and seach for existing entry. Then load
+	/* Set the TLB reservation and search for existing entry. Then load
 	 * the entry.
 	 */
 	PPC_TLBSRX_DOT(0,r16)
@@ -425,13 +425,13 @@
 
 virt_page_table_tlb_miss_fault:
 	/* If we fault here, things are a little bit tricky. We need to call
-	 * either data or instruction store fault, and we need to retreive
+	 * either data or instruction store fault, and we need to retrieve
 	 * the original fault address and ESR (for data).
 	 *
 	 * The thing is, we know that in normal circumstances, this is
 	 * always called as a second level tlb miss for SW load or as a first
 	 * level TLB miss for HW load, so we should be able to peek at the
-	 * relevant informations in the first exception frame in the PACA.
+	 * relevant information in the first exception frame in the PACA.
 	 *
 	 * However, we do need to double check that, because we may just hit
 	 * a stray kernel pointer or a userland attack trying to hit those
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/mm/tlb_nohash_low.S linux-libre-2.6.39-gnu/arch/powerpc/mm/tlb_nohash_low.S
--- linux-libre-2.6.38-gnu/arch/powerpc/mm/tlb_nohash_low.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/mm/tlb_nohash_low.S	2011-05-19 00:06:34.000000000 -0400
@@ -189,6 +189,13 @@
 	blr
 
 #ifdef CONFIG_PPC_47x
+
+/*
+ * 47x variant of icbt
+ */
+# define ICBT(CT,RA,RB)	\
+	.long	0x7c00002c | ((CT) << 21) | ((RA) << 16) | ((RB) << 11)
+
 /*
  * _tlbivax_bcast is only on 47x. We don't bother doing a runtime
  * check though, it will blow up soon enough if we mistakenly try
@@ -206,9 +213,37 @@
 	isync
 	eieio
 	tlbsync
+BEGIN_FTR_SECTION
+	b	1f
+END_FTR_SECTION_IFSET(CPU_FTR_476_DD2)
 	sync
 	wrtee	r10
 	blr
+/*
+ * DD2 HW could hang if in instruction fetch happens before msync completes.
+ * Touch enough instruction cache lines to ensure cache hits
+ */
+1:	mflr	r9
+	bl	2f
+2:	mflr	r6
+	li	r7,32
+	ICBT(0,r6,r7)		/* touch next cache line */
+	add	r6,r6,r7
+	ICBT(0,r6,r7)		/* touch next cache line */
+	add	r6,r6,r7
+	ICBT(0,r6,r7)		/* touch next cache line */
+	sync
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	mtlr	r9
+	wrtee	r10
+	blr
 #endif /* CONFIG_PPC_47x */
 
 #elif defined(CONFIG_FSL_BOOKE)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/oprofile/op_model_cell.c linux-libre-2.6.39-gnu/arch/powerpc/oprofile/op_model_cell.c
--- linux-libre-2.6.38-gnu/arch/powerpc/oprofile/op_model_cell.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/oprofile/op_model_cell.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
 
 #define MAX_SPU_COUNT 0xFFFFFF	/* maximum 24 bit LFSR value */
 
-/* Minumum HW interval timer setting to send value to trace buffer is 10 cycle.
+/* Minimum HW interval timer setting to send value to trace buffer is 10 cycle.
  * To configure counter to send value every N cycles set counter to
  * 2^32 - 1 - N.
  */
@@ -1470,7 +1470,7 @@
  * trace buffer at the maximum rate possible.  The trace buffer is configured
  * to store the PCs, wrapping when it is full.  The performance counter is
  * initialized to the max hardware count minus the number of events, N, between
- * samples.  Once the N events have occured, a HW counter overflow occurs
+ * samples.  Once the N events have occurred, a HW counter overflow occurs
  * causing the generation of a HW counter interrupt which also stops the
  * writing of the SPU PC values to the trace buffer.  Hence the last PC
  * written to the trace buffer is the SPU PC that we want.  Unfortunately,
@@ -1656,7 +1656,7 @@
 		 * The counters were frozen by the interrupt.
 		 * Reenable the interrupt and restart the counters.
 		 * If there was a race between the interrupt handler and
-		 * the virtual counter routine.	 The virutal counter
+		 * the virtual counter routine.	 The virtual counter
 		 * routine may have cleared the interrupts.  Hence must
 		 * use the virt_cntr_inter_mask to re-enable the interrupts.
 		 */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/oprofile/op_model_power4.c linux-libre-2.6.39-gnu/arch/powerpc/oprofile/op_model_power4.c
--- linux-libre-2.6.38-gnu/arch/powerpc/oprofile/op_model_power4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/oprofile/op_model_power4.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,7 +207,7 @@
 	unsigned long mmcra;
 	unsigned long slot;
 
-	/* Cant do much about it */
+	/* Can't do much about it */
 	if (!cur_cpu_spec->oprofile_mmcra_sihv)
 		return pc;
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/44x.h linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/44x.h
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/44x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/44x.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,4 +4,8 @@
 extern u8 as1_readb(volatile u8 __iomem  *addr);
 extern void as1_writeb(u8 data, volatile u8 __iomem *addr);
 
+#define GPIO0_OSRH	0xC
+#define GPIO0_TSRH	0x14
+#define GPIO0_ISR1H	0x34
+
 #endif /* __POWERPC_PLATFORMS_44X_44X_H */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/canyonlands.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/canyonlands.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/canyonlands.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/canyonlands.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * This contain platform specific code for APM PPC460EX based Canyonlands
+ * board.
+ *
+ * Copyright (c) 2010, Applied Micro Circuits Corporation
+ * Author: Rupjyoti Sarmah <rsarmah@apm.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/kernel.h>
+#include <linux/init.h>
+#include <asm/pci-bridge.h>
+#include <asm/ppc4xx.h>
+#include <asm/udbg.h>
+#include <asm/uic.h>
+#include <linux/of_platform.h>
+#include <linux/delay.h>
+#include "44x.h"
+
+#define BCSR_USB_EN	0x11
+
+static __initdata struct of_device_id ppc460ex_of_bus[] = {
+	{ .compatible = "ibm,plb4", },
+	{ .compatible = "ibm,opb", },
+	{ .compatible = "ibm,ebc", },
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+static int __init ppc460ex_device_probe(void)
+{
+	of_platform_bus_probe(NULL, ppc460ex_of_bus, NULL);
+
+	return 0;
+}
+machine_device_initcall(canyonlands, ppc460ex_device_probe);
+
+/* Using this code only for the Canyonlands board.  */
+
+static int __init ppc460ex_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+	if (of_flat_dt_is_compatible(root, "amcc,canyonlands")) {
+		ppc_pci_set_flags(PPC_PCI_REASSIGN_ALL_RSRC);
+		return 1;
+		}
+	return 0;
+}
+
+/* USB PHY fixup code on Canyonlands kit. */
+
+static int __init ppc460ex_canyonlands_fixup(void)
+{
+	u8 __iomem *bcsr ;
+	void __iomem *vaddr;
+	struct device_node *np;
+	int ret = 0;
+
+	np = of_find_compatible_node(NULL, NULL, "amcc,ppc460ex-bcsr");
+	if (!np) {
+		printk(KERN_ERR "failed did not find amcc, ppc460ex bcsr node\n");
+		return -ENODEV;
+	}
+
+	bcsr = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!bcsr) {
+		printk(KERN_CRIT "Could not remap bcsr\n");
+		ret = -ENODEV;
+		goto err_bcsr;
+	}
+
+	np = of_find_compatible_node(NULL, NULL, "ibm,ppc4xx-gpio");
+	if (!np) {
+		printk(KERN_ERR "failed did not find ibm,ppc4xx-gpio node\n");
+		return -ENODEV;
+	}
+
+	vaddr = of_iomap(np, 0);
+	of_node_put(np);
+
+	if (!vaddr) {
+		printk(KERN_CRIT "Could not get gpio node address\n");
+		ret = -ENODEV;
+		goto err_gpio;
+	}
+	/* Disable USB, through the BCSR7 bits */
+	setbits8(&bcsr[7], BCSR_USB_EN);
+
+	/* Wait for a while after reset */
+	msleep(100);
+
+	/* Enable USB here */
+	clrbits8(&bcsr[7], BCSR_USB_EN);
+
+	/*
+	 * Configure multiplexed gpio16 and gpio19 as alternate1 output
+	 * source after USB reset. In this configuration gpio16 will be
+	 * USB2HStop and gpio19 will be USB2DStop. For more details refer to
+	 * table 34-7 of PPC460EX user manual.
+	 */
+	setbits32((vaddr + GPIO0_OSRH), 0x42000000);
+	setbits32((vaddr + GPIO0_TSRH), 0x42000000);
+err_gpio:
+	iounmap(vaddr);
+err_bcsr:
+	iounmap(bcsr);
+	return ret;
+}
+machine_device_initcall(canyonlands, ppc460ex_canyonlands_fixup);
+define_machine(canyonlands) {
+	.name = "Canyonlands",
+	.probe = ppc460ex_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.38-gnu/arch/powerpc/platforms/44x/Kconfig linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/Kconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,6 @@
 	bool "Canyonlands"
 	depends on 44x
 	default n
-	select PPC44x_SIMPLE
 	select 460EX
 	select PCI
 	select PPC4xx_PCI_EXPRESS
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/Makefile linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/Makefile
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,3 +9,4 @@
 obj-$(CONFIG_XILINX_VIRTEX_5_FXT) += virtex.o
 obj-$(CONFIG_XILINX_ML510) += virtex_ml510.o
 obj-$(CONFIG_ISS4xx)	+= iss4xx.o
+obj-$(CONFIG_CANYONLANDS)+= canyonlands.o
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/ppc44x_simple.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/ppc44x_simple.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/44x/ppc44x_simple.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/44x/ppc44x_simple.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,6 @@
 	"amcc,arches",
 	"amcc,bamboo",
 	"amcc,bluestone",
-	"amcc,canyonlands",
 	"amcc,glacier",
 	"ibm,ebony",
 	"amcc,eiger",
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/512x/mpc5121_ads_cpld.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,9 +59,9 @@
 }
 
 static void
-cpld_mask_irq(unsigned int irq)
+cpld_mask_irq(struct irq_data *d)
 {
-	unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
 	void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
 
 	out_8(pic_mask,
@@ -69,9 +69,9 @@
 }
 
 static void
-cpld_unmask_irq(unsigned int irq)
+cpld_unmask_irq(struct irq_data *d)
 {
-	unsigned int cpld_irq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpld_irq = (unsigned int)irq_map[d->irq].hwirq;
 	void __iomem *pic_mask = irq_to_pic_mask(cpld_irq);
 
 	out_8(pic_mask,
@@ -80,9 +80,9 @@
 
 static struct irq_chip cpld_pic = {
 	.name = "CPLD PIC",
-	.mask = cpld_mask_irq,
-	.ack = cpld_mask_irq,
-	.unmask = cpld_unmask_irq,
+	.irq_mask = cpld_mask_irq,
+	.irq_ack = cpld_mask_irq,
+	.irq_unmask = cpld_unmask_irq,
 };
 
 static int
@@ -132,8 +132,8 @@
 cpld_pic_host_map(struct irq_host *h, unsigned int virq,
 			     irq_hw_number_t hw)
 {
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &cpld_pic, handle_level_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &cpld_pic, handle_level_irq);
 	return 0;
 }
 
@@ -198,7 +198,7 @@
 		goto end;
 	}
 
-	set_irq_chained_handler(cascade_irq, cpld_pic_cascade);
+	irq_set_chained_handler(cascade_irq, cpld_pic_cascade);
 end:
 	of_node_put(np);
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/media5200.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/media5200.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/media5200.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/media5200.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,45 +49,46 @@
 };
 struct media5200_irq media5200_irq;
 
-static void media5200_irq_unmask(unsigned int virq)
+static void media5200_irq_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 val;
 
 	spin_lock_irqsave(&media5200_irq.lock, flags);
 	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
-	val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq);
+	val |= 1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq);
 	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
 	spin_unlock_irqrestore(&media5200_irq.lock, flags);
 }
 
-static void media5200_irq_mask(unsigned int virq)
+static void media5200_irq_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	u32 val;
 
 	spin_lock_irqsave(&media5200_irq.lock, flags);
 	val = in_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE);
-	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[virq].hwirq));
+	val &= ~(1 << (MEDIA5200_IRQ_SHIFT + irq_map[d->irq].hwirq));
 	out_be32(media5200_irq.regs + MEDIA5200_IRQ_ENABLE, val);
 	spin_unlock_irqrestore(&media5200_irq.lock, flags);
 }
 
 static struct irq_chip media5200_irq_chip = {
 	.name = "Media5200 FPGA",
-	.unmask = media5200_irq_unmask,
-	.mask = media5200_irq_mask,
-	.mask_ack = media5200_irq_mask,
+	.irq_unmask = media5200_irq_unmask,
+	.irq_mask = media5200_irq_mask,
+	.irq_mask_ack = media5200_irq_mask,
 };
 
 void media5200_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int sub_virq, val;
 	u32 status, enable;
 
 	/* Mask off the cascaded IRQ */
 	raw_spin_lock(&desc->lock);
-	desc->chip->mask(virq);
+	chip->irq_mask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 
 	/* Ask the FPGA for IRQ status.  If 'val' is 0, then no irqs
@@ -105,24 +106,19 @@
 
 	/* Processing done; can reenable the cascade now */
 	raw_spin_lock(&desc->lock);
-	desc->chip->ack(virq);
-	if (!(desc->status & IRQ_DISABLED))
-		desc->chip->unmask(virq);
+	chip->irq_ack(&desc->irq_data);
+	if (!irqd_irq_disabled(&desc->irq_data))
+		chip->irq_unmask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 }
 
 static int media5200_irq_map(struct irq_host *h, unsigned int virq,
 			     irq_hw_number_t hw)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-
 	pr_debug("%s: h=%p, virq=%i, hwirq=%i\n", __func__, h, virq, (int)hw);
-	set_irq_chip_data(virq, &media5200_irq);
-	set_irq_chip_and_handler(virq, &media5200_irq_chip, handle_level_irq);
-	set_irq_type(virq, IRQ_TYPE_LEVEL_LOW);
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= IRQ_TYPE_LEVEL_LOW | IRQ_LEVEL;
-
+	irq_set_chip_data(virq, &media5200_irq);
+	irq_set_chip_and_handler(virq, &media5200_irq_chip, handle_level_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
 	return 0;
 }
 
@@ -186,8 +182,8 @@
 
 	media5200_irq.irqhost->host_data = &media5200_irq;
 
-	set_irq_data(cascade_virq, &media5200_irq);
-	set_irq_chained_handler(cascade_virq, media5200_irq_cascade);
+	irq_set_handler_data(cascade_virq, &media5200_irq);
+	irq_set_chained_handler(cascade_virq, media5200_irq_cascade);
 
 	return;
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpio.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpio.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -147,8 +147,7 @@
 	return 0;
 }
 
-static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static int __devinit mpc52xx_wkup_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct mpc52xx_gpio_wkup __iomem *regs;
@@ -191,7 +190,7 @@
 	{}
 };
 
-static struct of_platform_driver mpc52xx_wkup_gpiochip_driver = {
+static struct platform_driver mpc52xx_wkup_gpiochip_driver = {
 	.driver = {
 		.name = "gpio_wkup",
 		.owner = THIS_MODULE,
@@ -310,8 +309,7 @@
 	return 0;
 }
 
-static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static int __devinit mpc52xx_simple_gpiochip_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpiochip *chip;
 	struct gpio_chip *gc;
@@ -349,7 +347,7 @@
 	{}
 };
 
-static struct of_platform_driver mpc52xx_simple_gpiochip_driver = {
+static struct platform_driver mpc52xx_simple_gpiochip_driver = {
 	.driver = {
 		.name = "gpio",
 		.owner = THIS_MODULE,
@@ -361,10 +359,10 @@
 
 static int __init mpc52xx_gpio_init(void)
 {
-	if (of_register_platform_driver(&mpc52xx_wkup_gpiochip_driver))
+	if (platform_driver_register(&mpc52xx_wkup_gpiochip_driver))
 		printk(KERN_ERR "Unable to register wakeup GPIO driver\n");
 
-	if (of_register_platform_driver(&mpc52xx_simple_gpiochip_driver))
+	if (platform_driver_register(&mpc52xx_simple_gpiochip_driver))
 		printk(KERN_ERR "Unable to register simple GPIO driver\n");
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_gpt.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,9 +135,9 @@
  * Cascaded interrupt controller hooks
  */
 
-static void mpc52xx_gpt_irq_unmask(unsigned int virq)
+static void mpc52xx_gpt_irq_unmask(struct irq_data *d)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&gpt->lock, flags);
@@ -145,9 +145,9 @@
 	spin_unlock_irqrestore(&gpt->lock, flags);
 }
 
-static void mpc52xx_gpt_irq_mask(unsigned int virq)
+static void mpc52xx_gpt_irq_mask(struct irq_data *d)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	spin_lock_irqsave(&gpt->lock, flags);
@@ -155,20 +155,20 @@
 	spin_unlock_irqrestore(&gpt->lock, flags);
 }
 
-static void mpc52xx_gpt_irq_ack(unsigned int virq)
+static void mpc52xx_gpt_irq_ack(struct irq_data *d)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 
 	out_be32(&gpt->regs->status, MPC52xx_GPT_STATUS_IRQMASK);
 }
 
-static int mpc52xx_gpt_irq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc52xx_gpt_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_chip_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 	u32 reg;
 
-	dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, virq, flow_type);
+	dev_dbg(gpt->dev, "%s: virq=%i type=%x\n", __func__, d->irq, flow_type);
 
 	spin_lock_irqsave(&gpt->lock, flags);
 	reg = in_be32(&gpt->regs->mode) & ~MPC52xx_GPT_MODE_ICT_MASK;
@@ -184,15 +184,15 @@
 
 static struct irq_chip mpc52xx_gpt_irq_chip = {
 	.name = "MPC52xx GPT",
-	.unmask = mpc52xx_gpt_irq_unmask,
-	.mask = mpc52xx_gpt_irq_mask,
-	.ack = mpc52xx_gpt_irq_ack,
-	.set_type = mpc52xx_gpt_irq_set_type,
+	.irq_unmask = mpc52xx_gpt_irq_unmask,
+	.irq_mask = mpc52xx_gpt_irq_mask,
+	.irq_ack = mpc52xx_gpt_irq_ack,
+	.irq_set_type = mpc52xx_gpt_irq_set_type,
 };
 
 void mpc52xx_gpt_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
-	struct mpc52xx_gpt_priv *gpt = get_irq_data(virq);
+	struct mpc52xx_gpt_priv *gpt = irq_get_handler_data(virq);
 	int sub_virq;
 	u32 status;
 
@@ -209,8 +209,8 @@
 	struct mpc52xx_gpt_priv *gpt = h->host_data;
 
 	dev_dbg(gpt->dev, "%s: h=%p, virq=%i\n", __func__, h, virq);
-	set_irq_chip_data(virq, gpt);
-	set_irq_chip_and_handler(virq, &mpc52xx_gpt_irq_chip, handle_edge_irq);
+	irq_set_chip_data(virq, gpt);
+	irq_set_chip_and_handler(virq, &mpc52xx_gpt_irq_chip, handle_edge_irq);
 
 	return 0;
 }
@@ -259,8 +259,8 @@
 	}
 
 	gpt->irqhost->host_data = gpt;
-	set_irq_data(cascade_virq, gpt);
-	set_irq_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade);
+	irq_set_handler_data(cascade_virq, gpt);
+	irq_set_chained_handler(cascade_virq, mpc52xx_gpt_irq_cascade);
 
 	/* If the GPT is currently disabled, then change it to be in Input
 	 * Capture mode.  If the mode is non-zero, then the pin could be
@@ -721,8 +721,7 @@
 /* ---------------------------------------------------------------------
  * of_platform bus binding code
  */
-static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev,
-				       const struct of_device_id *match)
+static int __devinit mpc52xx_gpt_probe(struct platform_device *ofdev)
 {
 	struct mpc52xx_gpt_priv *gpt;
 
@@ -781,7 +780,7 @@
 	{}
 };
 
-static struct of_platform_driver mpc52xx_gpt_driver = {
+static struct platform_driver mpc52xx_gpt_driver = {
 	.driver = {
 		.name = "mpc52xx-gpt",
 		.owner = THIS_MODULE,
@@ -793,10 +792,7 @@
 
 static int __init mpc52xx_gpt_init(void)
 {
-	if (of_register_platform_driver(&mpc52xx_gpt_driver))
-		pr_err("error registering MPC52xx GPT driver\n");
-
-	return 0;
+	return platform_driver_register(&mpc52xx_gpt_driver);
 }
 
 /* Make sure GPIOs and IRQs get set up before anyone tries to use them */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_lpbfifo.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 static struct mpc52xx_lpbfifo lpbfifo;
 
 /**
- * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transfered
+ * mpc52xx_lpbfifo_kick - Trigger the next block of data to be transferred
  */
 static void mpc52xx_lpbfifo_kick(struct mpc52xx_lpbfifo_request *req)
 {
@@ -179,7 +179,7 @@
  *
  * On transmit, the dma completion irq triggers before the fifo completion
  * triggers.  Handle the dma completion here instead of the LPB FIFO Bestcomm
- * task completion irq becuase everyting is not really done until the LPB FIFO
+ * task completion irq because everything is not really done until the LPB FIFO
  * completion irq triggers.
  *
  * In other words:
@@ -195,7 +195,7 @@
  * Exit conditions:
  * 1) Transfer aborted
  * 2) FIFO complete without DMA; more data to do
- * 3) FIFO complete without DMA; all data transfered
+ * 3) FIFO complete without DMA; all data transferred
  * 4) FIFO complete using DMA
  *
  * Condition 1 can occur regardless of whether or not DMA is used.
@@ -436,8 +436,7 @@
 }
 EXPORT_SYMBOL(mpc52xx_lpbfifo_abort);
 
-static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op,
-					   const struct of_device_id *match)
+static int __devinit mpc52xx_lpbfifo_probe(struct platform_device *op)
 {
 	struct resource res;
 	int rc = -ENOMEM;
@@ -536,7 +535,7 @@
 	{},
 };
 
-static struct of_platform_driver mpc52xx_lpbfifo_driver = {
+static struct platform_driver mpc52xx_lpbfifo_driver = {
 	.driver = {
 		.name = "mpc52xx-lpbfifo",
 		.owner = THIS_MODULE,
@@ -551,14 +550,12 @@
  */
 static int __init mpc52xx_lpbfifo_init(void)
 {
-	pr_debug("Registering LocalPlus bus FIFO driver\n");
-	return of_register_platform_driver(&mpc52xx_lpbfifo_driver);
+	return platform_driver_register(&mpc52xx_lpbfifo_driver);
 }
 module_init(mpc52xx_lpbfifo_init);
 
 static void __exit mpc52xx_lpbfifo_exit(void)
 {
-	pr_debug("Unregistering LocalPlus bus FIFO driver\n");
-	of_unregister_platform_driver(&mpc52xx_lpbfifo_driver);
+	platform_driver_unregister(&mpc52xx_lpbfifo_driver);
 }
 module_exit(mpc52xx_lpbfifo_exit);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/52xx/mpc52xx_pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/52xx/mpc52xx_pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -155,47 +155,47 @@
 /*
  * IRQ[0-3] interrupt irq_chip
  */
-static void mpc52xx_extirq_mask(unsigned int virq)
+static void mpc52xx_extirq_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&intr->ctrl, 11 - l2irq);
 }
 
-static void mpc52xx_extirq_unmask(unsigned int virq)
+static void mpc52xx_extirq_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->ctrl, 11 - l2irq);
 }
 
-static void mpc52xx_extirq_ack(unsigned int virq)
+static void mpc52xx_extirq_ack(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->ctrl, 27-l2irq);
 }
 
-static int mpc52xx_extirq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc52xx_extirq_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	u32 ctrl_reg, type;
 	int irq;
 	int l2irq;
 	void *handler = handle_level_irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	pr_debug("%s: irq=%x. l2=%d flow_type=%d\n", __func__, irq, l2irq, flow_type);
@@ -214,44 +214,44 @@
 	ctrl_reg |= (type << (22 - (l2irq * 2)));
 	out_be32(&intr->ctrl, ctrl_reg);
 
-	__set_irq_handler_unlocked(virq, handler);
+	__irq_set_handler_locked(d->irq, handler);
 
 	return 0;
 }
 
 static struct irq_chip mpc52xx_extirq_irqchip = {
 	.name = "MPC52xx External",
-	.mask = mpc52xx_extirq_mask,
-	.unmask = mpc52xx_extirq_unmask,
-	.ack = mpc52xx_extirq_ack,
-	.set_type = mpc52xx_extirq_set_type,
+	.irq_mask = mpc52xx_extirq_mask,
+	.irq_unmask = mpc52xx_extirq_unmask,
+	.irq_ack = mpc52xx_extirq_ack,
+	.irq_set_type = mpc52xx_extirq_set_type,
 };
 
 /*
  * Main interrupt irq_chip
  */
-static int mpc52xx_null_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc52xx_null_set_type(struct irq_data *d, unsigned int flow_type)
 {
 	return 0; /* Do nothing so that the sense mask will get updated */
 }
 
-static void mpc52xx_main_mask(unsigned int virq)
+static void mpc52xx_main_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->main_mask, 16 - l2irq);
 }
 
-static void mpc52xx_main_unmask(unsigned int virq)
+static void mpc52xx_main_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&intr->main_mask, 16 - l2irq);
@@ -259,32 +259,32 @@
 
 static struct irq_chip mpc52xx_main_irqchip = {
 	.name = "MPC52xx Main",
-	.mask = mpc52xx_main_mask,
-	.mask_ack = mpc52xx_main_mask,
-	.unmask = mpc52xx_main_unmask,
-	.set_type = mpc52xx_null_set_type,
+	.irq_mask = mpc52xx_main_mask,
+	.irq_mask_ack = mpc52xx_main_mask,
+	.irq_unmask = mpc52xx_main_unmask,
+	.irq_set_type = mpc52xx_null_set_type,
 };
 
 /*
  * Peripherals interrupt irq_chip
  */
-static void mpc52xx_periph_mask(unsigned int virq)
+static void mpc52xx_periph_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&intr->per_mask, 31 - l2irq);
 }
 
-static void mpc52xx_periph_unmask(unsigned int virq)
+static void mpc52xx_periph_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&intr->per_mask, 31 - l2irq);
@@ -292,43 +292,43 @@
 
 static struct irq_chip mpc52xx_periph_irqchip = {
 	.name = "MPC52xx Peripherals",
-	.mask = mpc52xx_periph_mask,
-	.mask_ack = mpc52xx_periph_mask,
-	.unmask = mpc52xx_periph_unmask,
-	.set_type = mpc52xx_null_set_type,
+	.irq_mask = mpc52xx_periph_mask,
+	.irq_mask_ack = mpc52xx_periph_mask,
+	.irq_unmask = mpc52xx_periph_unmask,
+	.irq_set_type = mpc52xx_null_set_type,
 };
 
 /*
  * SDMA interrupt irq_chip
  */
-static void mpc52xx_sdma_mask(unsigned int virq)
+static void mpc52xx_sdma_mask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_setbit(&sdma->IntMask, l2irq);
 }
 
-static void mpc52xx_sdma_unmask(unsigned int virq)
+static void mpc52xx_sdma_unmask(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	io_be_clrbit(&sdma->IntMask, l2irq);
 }
 
-static void mpc52xx_sdma_ack(unsigned int virq)
+static void mpc52xx_sdma_ack(struct irq_data *d)
 {
 	int irq;
 	int l2irq;
 
-	irq = irq_map[virq].hwirq;
+	irq = irq_map[d->irq].hwirq;
 	l2irq = irq & MPC52xx_IRQ_L2_MASK;
 
 	out_be32(&sdma->IntPend, 1 << l2irq);
@@ -336,10 +336,10 @@
 
 static struct irq_chip mpc52xx_sdma_irqchip = {
 	.name = "MPC52xx SDMA",
-	.mask = mpc52xx_sdma_mask,
-	.unmask = mpc52xx_sdma_unmask,
-	.ack = mpc52xx_sdma_ack,
-	.set_type = mpc52xx_null_set_type,
+	.irq_mask = mpc52xx_sdma_mask,
+	.irq_unmask = mpc52xx_sdma_unmask,
+	.irq_ack = mpc52xx_sdma_ack,
+	.irq_set_type = mpc52xx_null_set_type,
 };
 
 /**
@@ -414,7 +414,7 @@
 		else
 			hndlr = handle_level_irq;
 
-		set_irq_chip_and_handler(virq, &mpc52xx_extirq_irqchip, hndlr);
+		irq_set_chip_and_handler(virq, &mpc52xx_extirq_irqchip, hndlr);
 		pr_debug("%s: External IRQ%i virq=%x, hw=%x. type=%x\n",
 			 __func__, l2irq, virq, (int)irq, type);
 		return 0;
@@ -431,7 +431,7 @@
 		return -EINVAL;
 	}
 
-	set_irq_chip_and_handler(virq, irqchip, handle_level_irq);
+	irq_set_chip_and_handler(virq, irqchip, handle_level_irq);
 	pr_debug("%s: virq=%x, l1=%i, l2=%i\n", __func__, virq, l1irq, l2irq);
 
 	return 0;
@@ -512,7 +512,7 @@
 /**
  * mpc52xx_get_irq - Get pending interrupt number hook function
  *
- * Called by the interupt handler to determine what IRQ handler needs to be
+ * Called by the interrupt handler to determine what IRQ handler needs to be
  * executed.
  *
  * Status of pending interrupts is determined by reading the encoded status
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/ep8248e.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/ep8248e.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/ep8248e.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/ep8248e.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,8 +111,7 @@
 	.ops = &ep8248e_mdio_ops,
 };
 
-static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit ep8248e_mdio_probe(struct platform_device *ofdev)
 {
 	struct mii_bus *bus;
 	struct resource res;
@@ -167,7 +166,7 @@
 	{},
 };
 
-static struct of_platform_driver ep8248e_mdio_driver = {
+static struct platform_driver ep8248e_mdio_driver = {
 	.driver = {
 		.name = "ep8248e-mdio-bitbang",
 		.owner = THIS_MODULE,
@@ -308,7 +307,7 @@
 static int __init declare_of_platform_devices(void)
 {
 	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-	of_register_platform_driver(&ep8248e_mdio_driver);
+	platform_driver_register(&ep8248e_mdio_driver);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/km82xx.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/km82xx.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/km82xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/km82xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,206 @@
+/*
+ * Keymile km82xx support
+ * Copyright 2008-2011 DENX Software Engineering GmbH
+ * Author: Heiko Schocher <hs@denx.de>
+ *
+ * based on code from:
+ * Copyright 2007 Freescale Semiconductor, Inc.
+ * Author: Scott Wood <scottwood@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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fsl_devices.h>
+#include <linux/of_platform.h>
+
+#include <asm/io.h>
+#include <asm/cpm2.h>
+#include <asm/udbg.h>
+#include <asm/machdep.h>
+#include <asm/time.h>
+#include <asm/mpc8260.h>
+#include <asm/prom.h>
+
+#include <sysdev/fsl_soc.h>
+#include <sysdev/cpm2_pic.h>
+
+#include "pq2.h"
+
+static void __init km82xx_pic_init(void)
+{
+	struct device_node *np = of_find_compatible_node(NULL, NULL,
+							"fsl,pq2-pic");
+	if (!np) {
+		printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
+		return;
+	}
+
+	cpm2_pic_init(np);
+	of_node_put(np);
+}
+
+struct cpm_pin {
+	int port, pin, flags;
+};
+
+static __initdata struct cpm_pin km82xx_pins[] = {
+
+	/* SMC2 */
+	{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+	/* SCC1 */
+	{2, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 31, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 30, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+
+	/* SCC4 */
+	{2, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2,  9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2,  8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{3, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+	/* FCC1 */
+	{0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+	{0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+	{0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+	{0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+	{0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+	{0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
+
+	{2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 23, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+
+	/* FCC2 */
+	{1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+	{1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
+	{1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
+
+	{2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+	{2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
+
+	/* MDC */
+	{0, 13, CPM_PIN_OUTPUT | CPM_PIN_GPIO},
+
+#if defined(CONFIG_I2C_CPM)
+	/* I2C */
+	{3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
+	{3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
+#endif
+
+	/* USB */
+	{0, 10, CPM_PIN_OUTPUT | CPM_PIN_GPIO},    /* FULL_SPEED */
+	{0, 11, CPM_PIN_OUTPUT | CPM_PIN_GPIO},    /*/SLAVE */
+	{2, 10, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXN */
+	{2, 11, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXP */
+	{2, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* /OE */
+	{2, 27, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXCLK */
+	{3, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXP */
+	{3, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY}, /* TXN */
+	{3, 25, CPM_PIN_INPUT  | CPM_PIN_PRIMARY}, /* RXD */
+};
+
+static void __init init_ioports(void)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(km82xx_pins); i++) {
+		const struct cpm_pin *pin = &km82xx_pins[i];
+		cpm2_set_pin(pin->port, pin->pin, pin->flags);
+	}
+
+	cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
+	cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_SCC1, CPM_CLK11, CPM_CLK_TX);
+	cpm2_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RTX);
+	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX);
+	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9,  CPM_CLK_TX);
+	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
+	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
+
+	/* Force USB FULL SPEED bit to '1' */
+	setbits32(&cpm2_immr->im_ioport.iop_pdata, 1 << (31 - 10));
+	/* clear USB_SLAVE */
+	clrbits32(&cpm2_immr->im_ioport.iop_pdata, 1 << (31 - 11));
+}
+
+static void __init km82xx_setup_arch(void)
+{
+	if (ppc_md.progress)
+		ppc_md.progress("km82xx_setup_arch()", 0);
+
+	cpm2_reset();
+
+	/* When this is set, snooping CPM DMA from RAM causes
+	 * machine checks.  See erratum SIU18.
+	 */
+	clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
+
+	init_ioports();
+
+	if (ppc_md.progress)
+		ppc_md.progress("km82xx_setup_arch(), finish", 0);
+}
+
+static  __initdata struct of_device_id of_bus_ids[] = {
+	{ .compatible = "simple-bus", },
+	{},
+};
+
+static int __init declare_of_platform_devices(void)
+{
+	of_platform_bus_probe(NULL, of_bus_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(km82xx, declare_of_platform_devices);
+
+/*
+ * Called very early, device-tree isn't unflattened
+ */
+static int __init km82xx_probe(void)
+{
+	unsigned long root = of_get_flat_dt_root();
+	return of_flat_dt_is_compatible(root, "keymile,km82xx");
+}
+
+define_machine(km82xx)
+{
+	.name = "Keymile km82xx",
+	.probe = km82xx_probe,
+	.setup_arch = km82xx_setup_arch,
+	.init_IRQ = km82xx_pic_init,
+	.get_irq = cpm2_get_irq,
+	.calibrate_decr = generic_calibrate_decr,
+	.restart = pq2_restart,
+	.progress = udbg_progress,
+};
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/Makefile linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/Makefile
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,4 +6,4 @@
 obj-$(CONFIG_PQ2_ADS_PCI_PIC) += pq2ads-pci-pic.o
 obj-$(CONFIG_PQ2FADS) += pq2fads.o
 obj-$(CONFIG_EP8248E) += ep8248e.o
-obj-$(CONFIG_MGCOGE) += mgcoge.o
+obj-$(CONFIG_MGCOGE) += km82xx.o
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/mgcoge.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/mgcoge.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/mgcoge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/mgcoge.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,180 +0,0 @@
-/*
- * Keymile mgcoge support
- * Copyright 2008 DENX Software Engineering GmbH
- * Author: Heiko Schocher <hs@denx.de>
- *
- * based on code from:
- * Copyright 2007 Freescale Semiconductor, Inc.
- * Author: Scott Wood <scottwood@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.
- */
-
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/fsl_devices.h>
-#include <linux/of_platform.h>
-
-#include <asm/io.h>
-#include <asm/cpm2.h>
-#include <asm/udbg.h>
-#include <asm/machdep.h>
-#include <asm/time.h>
-#include <asm/mpc8260.h>
-#include <asm/prom.h>
-
-#include <sysdev/fsl_soc.h>
-#include <sysdev/cpm2_pic.h>
-
-#include "pq2.h"
-
-static void __init mgcoge_pic_init(void)
-{
-	struct device_node *np = of_find_compatible_node(NULL, NULL, "fsl,pq2-pic");
-	if (!np) {
-		printk(KERN_ERR "PIC init: can not find cpm-pic node\n");
-		return;
-	}
-
-	cpm2_pic_init(np);
-	of_node_put(np);
-}
-
-struct cpm_pin {
-	int port, pin, flags;
-};
-
-static __initdata struct cpm_pin mgcoge_pins[] = {
-
-	/* SMC2 */
-	{0, 8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 9, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-
-	/* SCC4 */
-	{2, 25, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2, 24, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2,  9, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2,  8, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{3, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{3, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-
-	/* FCC1 */
-	{0, 14, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 15, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 16, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 17, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{0, 18, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 19, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 20, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 21, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{0, 26, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-	{0, 27, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-	{0, 28, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-	{0, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-	{0, 30, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-	{0, 31, CPM_PIN_INPUT | CPM_PIN_SECONDARY},
-
-	{2, 22, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2, 23, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-
-	/* FCC2 */
-	{1, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 20, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 21, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 22, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 23, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 24, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 25, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-	{1, 26, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 27, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 28, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 29, CPM_PIN_OUTPUT | CPM_PIN_SECONDARY},
-	{1, 30, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{1, 31, CPM_PIN_OUTPUT | CPM_PIN_PRIMARY},
-
-	{2, 18, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-	{2, 19, CPM_PIN_INPUT | CPM_PIN_PRIMARY},
-
-	/* MDC */
-	{0, 13, CPM_PIN_OUTPUT | CPM_PIN_GPIO},
-
-#if defined(CONFIG_I2C_CPM)
-	/* I2C */
-	{3, 14, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
-	{3, 15, CPM_PIN_INPUT | CPM_PIN_SECONDARY | CPM_PIN_OPENDRAIN},
-#endif
-};
-
-static void __init init_ioports(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mgcoge_pins); i++) {
-		const struct cpm_pin *pin = &mgcoge_pins[i];
-		cpm2_set_pin(pin->port, pin->pin, pin->flags);
-	}
-
-	cpm2_smc_clk_setup(CPM_CLK_SMC2, CPM_BRG8);
-	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK7, CPM_CLK_RX);
-	cpm2_clk_setup(CPM_CLK_SCC4, CPM_CLK8, CPM_CLK_TX);
-	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK10, CPM_CLK_RX);
-	cpm2_clk_setup(CPM_CLK_FCC1, CPM_CLK9,  CPM_CLK_TX);
-	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK13, CPM_CLK_RX);
-	cpm2_clk_setup(CPM_CLK_FCC2, CPM_CLK14, CPM_CLK_TX);
-}
-
-static void __init mgcoge_setup_arch(void)
-{
-	if (ppc_md.progress)
-		ppc_md.progress("mgcoge_setup_arch()", 0);
-
-	cpm2_reset();
-
-	/* When this is set, snooping CPM DMA from RAM causes
-	 * machine checks.  See erratum SIU18.
-	 */
-	clrbits32(&cpm2_immr->im_siu_conf.siu_82xx.sc_bcr, MPC82XX_BCR_PLDP);
-
-	init_ioports();
-
-	if (ppc_md.progress)
-		ppc_md.progress("mgcoge_setup_arch(), finish", 0);
-}
-
-static  __initdata struct of_device_id of_bus_ids[] = {
-	{ .compatible = "simple-bus", },
-	{},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-
-	return 0;
-}
-machine_device_initcall(mgcoge, declare_of_platform_devices);
-
-/*
- * Called very early, device-tree isn't unflattened
- */
-static int __init mgcoge_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-	return of_flat_dt_is_compatible(root, "keymile,mgcoge");
-}
-
-define_machine(mgcoge)
-{
-	.name = "Keymile MGCOGE",
-	.probe = mgcoge_probe,
-	.setup_arch = mgcoge_setup_arch,
-	.init_IRQ = mgcoge_pic_init,
-	.get_irq = cpm2_get_irq,
-	.calibrate_decr = generic_calibrate_decr,
-	.restart = pq2_restart,
-	.progress = udbg_progress,
-};
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/82xx/pq2ads-pci-pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,10 +39,10 @@
 
 #define NUM_IRQS 32
 
-static void pq2ads_pci_mask_irq(unsigned int virq)
+static void pq2ads_pci_mask_irq(struct irq_data *d)
 {
-	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
-	int irq = NUM_IRQS - virq_to_hw(virq) - 1;
+	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
+	int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
 
 	if (irq != -1) {
 		unsigned long flags;
@@ -55,10 +55,10 @@
 	}
 }
 
-static void pq2ads_pci_unmask_irq(unsigned int virq)
+static void pq2ads_pci_unmask_irq(struct irq_data *d)
 {
-	struct pq2ads_pci_pic *priv = get_irq_chip_data(virq);
-	int irq = NUM_IRQS - virq_to_hw(virq) - 1;
+	struct pq2ads_pci_pic *priv = irq_data_get_irq_chip_data(d);
+	int irq = NUM_IRQS - virq_to_hw(d->irq) - 1;
 
 	if (irq != -1) {
 		unsigned long flags;
@@ -71,18 +71,17 @@
 
 static struct irq_chip pq2ads_pci_ic = {
 	.name = "PQ2 ADS PCI",
-	.end = pq2ads_pci_unmask_irq,
-	.mask = pq2ads_pci_mask_irq,
-	.mask_ack = pq2ads_pci_mask_irq,
-	.ack = pq2ads_pci_mask_irq,
-	.unmask = pq2ads_pci_unmask_irq,
-	.enable = pq2ads_pci_unmask_irq,
-	.disable = pq2ads_pci_mask_irq
+	.irq_mask = pq2ads_pci_mask_irq,
+	.irq_mask_ack = pq2ads_pci_mask_irq,
+	.irq_ack = pq2ads_pci_mask_irq,
+	.irq_unmask = pq2ads_pci_unmask_irq,
+	.irq_enable = pq2ads_pci_unmask_irq,
+	.irq_disable = pq2ads_pci_mask_irq
 };
 
 static void pq2ads_pci_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	struct pq2ads_pci_pic *priv = desc->handler_data;
+	struct pq2ads_pci_pic *priv = irq_desc_get_handler_data(desc);
 	u32 stat, mask, pend;
 	int bit;
 
@@ -107,17 +106,17 @@
 static int pci_pic_host_map(struct irq_host *h, unsigned int virq,
 			    irq_hw_number_t hw)
 {
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_data(virq, h->host_data);
-	set_irq_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_and_handler(virq, &pq2ads_pci_ic, handle_level_irq);
 	return 0;
 }
 
 static void pci_host_unmap(struct irq_host *h, unsigned int virq)
 {
 	/* remove chip and handler */
-	set_irq_chip_data(virq, NULL);
-	set_irq_chip(virq, NULL);
+	irq_set_chip_data(virq, NULL);
+	irq_set_chip(virq, NULL);
 }
 
 static struct irq_host_ops pci_pic_host_ops = {
@@ -176,8 +175,8 @@
 
 	priv->host = host;
 	host->host_data = priv;
-	set_irq_data(irq, priv);
-	set_irq_chained_handler(irq, pq2ads_pci_irq_demux);
+	irq_set_handler_data(irq, priv);
+	irq_set_chained_handler(irq, pq2ads_pci_irq_demux);
 
 	of_node_put(np);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/83xx/km83xx.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/km83xx.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/83xx/km83xx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/km83xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,207 @@
+/*
+ * Copyright 2008-2011 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 mpc83xx_km_setup_arch(void)
+{
+	struct device_node *np;
+
+	if (ppc_md.progress)
+		ppc_md.progress("kmpbec83xx_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_each_node_by_name(np, "spi")
+			par_io_of_config(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 kmpbec83xx_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, kmpbec83xx_ids, NULL);
+
+	return 0;
+}
+machine_device_initcall(mpc83xx_km, kmeter_declare_of_platform_devices);
+
+static void __init mpc83xx_km_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 */
+}
+
+/* list of the supported boards */
+static char *board[] __initdata = {
+	"Keymile,KMETER1",
+	"Keymile,kmpbec8321",
+	NULL
+};
+
+/*
+ * Called very early, MMU is off, device-tree isn't unflattened
+ */
+static int __init mpc83xx_km_probe(void)
+{
+	unsigned long node = of_get_flat_dt_root();
+	int i = 0;
+
+	while (board[i]) {
+		if (of_flat_dt_is_compatible(node, board[i]))
+			break;
+		i++;
+	}
+	return (board[i] != NULL);
+}
+
+define_machine(mpc83xx_km) {
+	.name		= "mpc83xx-km-platform",
+	.probe		= mpc83xx_km_probe,
+	.setup_arch	= mpc83xx_km_setup_arch,
+	.init_IRQ	= mpc83xx_km_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.38-gnu/arch/powerpc/platforms/83xx/kmeter1.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/kmeter1.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/83xx/kmeter1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/kmeter1.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,191 +0,0 @@
-/*
- * 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.38-gnu/arch/powerpc/platforms/83xx/Makefile linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/Makefile
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/83xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -16,4 +16,4 @@
 obj-$(CONFIG_SBC834x)		+= sbc834x.o
 obj-$(CONFIG_MPC837x_RDB)	+= mpc837x_rdb.o
 obj-$(CONFIG_ASP834x)		+= asp834x.o
-obj-$(CONFIG_KMETER1)		+= kmeter1.o
+obj-$(CONFIG_KMETER1)		+= km83xx.o
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/83xx/suspend.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/suspend.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/83xx/suspend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/83xx/suspend.c	2011-05-19 00:06:34.000000000 -0400
@@ -318,14 +318,21 @@
 	.end = mpc83xx_suspend_end,
 };
 
-static int pmc_probe(struct platform_device *ofdev,
-                     const struct of_device_id *match)
+static struct of_device_id pmc_match[];
+static int pmc_probe(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
 	struct device_node *np = ofdev->dev.of_node;
 	struct resource res;
-	struct pmc_type *type = match->data;
+	struct pmc_type *type;
 	int ret = 0;
 
+	match = of_match_device(pmc_match, &ofdev->dev);
+	if (!match)
+		return -EINVAL;
+
+	type = match->data;
+
 	if (!of_device_is_available(np))
 		return -ENODEV;
 
@@ -422,7 +429,7 @@
 	{}
 };
 
-static struct of_platform_driver pmc_driver = {
+static struct platform_driver pmc_driver = {
 	.driver = {
 		.name = "mpc83xx-pmc",
 		.owner = THIS_MODULE,
@@ -434,7 +441,7 @@
 
 static int pmc_init(void)
 {
-	return of_register_platform_driver(&pmc_driver);
+	return platform_driver_register(&pmc_driver);
 }
 
 module_init(pmc_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/ksi8560.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/ksi8560.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/ksi8560.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/ksi8560.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,12 +56,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init ksi8560_pic_init(void)
@@ -105,7 +106,7 @@
 
 	cpm2_pic_init(np);
 	of_node_put(np);
-	set_irq_chained_handler(irq, cpm2_cascade);
+	irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/mpc85xx_ads.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/mpc85xx_ads.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/mpc85xx_ads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/mpc85xx_ads.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,12 +50,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 #endif /* CONFIG_CPM2 */
@@ -100,7 +101,7 @@
 
 	cpm2_pic_init(np);
 	of_node_put(np);
-	set_irq_chained_handler(irq, cpm2_cascade);
+	irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/mpc85xx_cds.c	2011-05-19 00:06:34.000000000 -0400
@@ -255,7 +255,7 @@
 	}
 
 	/* Success. Connect our low-level cascade handler. */
-	set_irq_handler(cascade_irq, mpc85xx_8259_cascade_handler);
+	irq_set_handler(cascade_irq, mpc85xx_8259_cascade_handler);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/mpc85xx_ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,12 +47,13 @@
 #ifdef CONFIG_PPC_I8259
 static void mpc85xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
 
 	if (cascade_irq != NO_IRQ) {
 		generic_handle_irq(cascade_irq);
 	}
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif	/* CONFIG_PPC_I8259 */
 
@@ -121,7 +122,7 @@
 	i8259_init(cascade_node, 0);
 	of_node_put(cascade_node);
 
-	set_irq_chained_handler(cascade_irq, mpc85xx_8259_cascade);
+	irq_set_chained_handler(cascade_irq, mpc85xx_8259_cascade);
 #endif	/* CONFIG_PPC_I8259 */
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/sbc8560.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/sbc8560.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/sbc8560.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/sbc8560.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,12 +41,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 #endif /* CONFIG_CPM2 */
@@ -91,7 +92,7 @@
 
 	cpm2_pic_init(np);
 	of_node_put(np);
-	set_irq_chained_handler(irq, cpm2_cascade);
+	irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/smp.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/smp.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,10 +91,14 @@
 	while ((__secondary_hold_acknowledge != nr) && (++n < 1000))
 		mdelay(1);
 #else
+	smp_generic_kick_cpu(nr);
+
 	out_be64((u64 *)(bptr_vaddr + BOOT_ENTRY_ADDR_UPPER),
 		__pa((u64)*((unsigned long long *) generic_secondary_smp_init)));
 
-	smp_generic_kick_cpu(nr);
+	if (!ioremappable)
+		flush_dcache_range((ulong)bptr_vaddr,
+				(ulong)(bptr_vaddr + SIZE_BOOT_ENTRY));
 #endif
 
 	local_irq_restore(flags);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/socrates_fpga_pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/socrates_fpga_pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/socrates_fpga_pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/socrates_fpga_pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,6 +93,7 @@
 
 void socrates_fpga_pic_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq;
 
 	/*
@@ -103,17 +104,16 @@
 
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
-
+	chip->irq_eoi(&desc->irq_data);
 }
 
-static void socrates_fpga_pic_ack(unsigned int virq)
+static void socrates_fpga_pic_ack(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq, irq_line;
 	uint32_t mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -124,14 +124,14 @@
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_mask(unsigned int virq)
+static void socrates_fpga_pic_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -142,14 +142,14 @@
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_mask_ack(unsigned int virq)
+static void socrates_fpga_pic_mask_ack(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -161,14 +161,14 @@
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_unmask(unsigned int virq)
+static void socrates_fpga_pic_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -179,14 +179,14 @@
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static void socrates_fpga_pic_eoi(unsigned int virq)
+static void socrates_fpga_pic_eoi(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	int irq_line;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	irq_line = fpga_irqs[hwirq].irq_line;
 	raw_spin_lock_irqsave(&socrates_fpga_pic_lock, flags);
@@ -197,7 +197,7 @@
 	raw_spin_unlock_irqrestore(&socrates_fpga_pic_lock, flags);
 }
 
-static int socrates_fpga_pic_set_type(unsigned int virq,
+static int socrates_fpga_pic_set_type(struct irq_data *d,
 		unsigned int flow_type)
 {
 	unsigned long flags;
@@ -205,7 +205,7 @@
 	int polarity;
 	u32 mask;
 
-	hwirq = socrates_fpga_irq_to_hw(virq);
+	hwirq = socrates_fpga_irq_to_hw(d->irq);
 
 	if (fpga_irqs[hwirq].type != IRQ_TYPE_NONE)
 		return -EINVAL;
@@ -233,21 +233,21 @@
 
 static struct irq_chip socrates_fpga_pic_chip = {
 	.name		= "FPGA-PIC",
-	.ack		= socrates_fpga_pic_ack,
-	.mask           = socrates_fpga_pic_mask,
-	.mask_ack       = socrates_fpga_pic_mask_ack,
-	.unmask         = socrates_fpga_pic_unmask,
-	.eoi		= socrates_fpga_pic_eoi,
-	.set_type	= socrates_fpga_pic_set_type,
+	.irq_ack	= socrates_fpga_pic_ack,
+	.irq_mask	= socrates_fpga_pic_mask,
+	.irq_mask_ack	= socrates_fpga_pic_mask_ack,
+	.irq_unmask	= socrates_fpga_pic_unmask,
+	.irq_eoi	= socrates_fpga_pic_eoi,
+	.irq_set_type	= socrates_fpga_pic_set_type,
 };
 
 static int socrates_fpga_pic_host_map(struct irq_host *h, unsigned int virq,
 		irq_hw_number_t hwirq)
 {
 	/* All interrupts are LEVEL sensitive */
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &socrates_fpga_pic_chip,
-			handle_fasteoi_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &socrates_fpga_pic_chip,
+				 handle_fasteoi_irq);
 
 	return 0;
 }
@@ -308,8 +308,8 @@
 			pr_warning("FPGA PIC: can't get irq%d.\n", i);
 			continue;
 		}
-		set_irq_chained_handler(socrates_fpga_irqs[i],
-				socrates_fpga_pic_cascade);
+		irq_set_chained_handler(socrates_fpga_irqs[i],
+					socrates_fpga_pic_cascade);
 	}
 
 	socrates_fpga_pic_iobase = of_iomap(pic, 0);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/stx_gp3.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/stx_gp3.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/stx_gp3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/stx_gp3.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,12 +46,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif /* CONFIG_CPM2 */
 
@@ -101,7 +102,7 @@
 
 	cpm2_pic_init(np);
 	of_node_put(np);
-	set_irq_chained_handler(irq, cpm2_cascade);
+	irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/tqm85xx.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/tqm85xx.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/85xx/tqm85xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/85xx/tqm85xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,12 +44,13 @@
 
 static void cpm2_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	int cascade_irq;
 
 	while ((cascade_irq = cpm2_get_irq()) >= 0)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif /* CONFIG_CPM2 */
 
@@ -99,7 +100,7 @@
 
 	cpm2_pic_init(np);
 	of_node_put(np);
-	set_irq_chained_handler(irq, cpm2_cascade);
+	irq_set_chained_handler(irq, cpm2_cascade);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/86xx/gef_pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/86xx/gef_pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/86xx/gef_pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/86xx/gef_pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,6 +95,7 @@
 
 void gef_pic_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq;
 
 	/*
@@ -106,17 +107,16 @@
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
 
-	desc->chip->eoi(irq);
-
+	chip->irq_eoi(&desc->irq_data);
 }
 
-static void gef_pic_mask(unsigned int virq)
+static void gef_pic_mask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	u32 mask;
 
-	hwirq = gef_irq_to_hw(virq);
+	hwirq = gef_irq_to_hw(d->irq);
 
 	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
@@ -125,21 +125,21 @@
 	raw_spin_unlock_irqrestore(&gef_pic_lock, flags);
 }
 
-static void gef_pic_mask_ack(unsigned int virq)
+static void gef_pic_mask_ack(struct irq_data *d)
 {
 	/* Don't think we actually have to do anything to ack an interrupt,
 	 * we just need to clear down the devices interrupt and it will go away
 	 */
-	gef_pic_mask(virq);
+	gef_pic_mask(d);
 }
 
-static void gef_pic_unmask(unsigned int virq)
+static void gef_pic_unmask(struct irq_data *d)
 {
 	unsigned long flags;
 	unsigned int hwirq;
 	u32 mask;
 
-	hwirq = gef_irq_to_hw(virq);
+	hwirq = gef_irq_to_hw(d->irq);
 
 	raw_spin_lock_irqsave(&gef_pic_lock, flags);
 	mask = in_be32(gef_pic_irq_reg_base + GEF_PIC_INTR_MASK(0));
@@ -150,9 +150,9 @@
 
 static struct irq_chip gef_pic_chip = {
 	.name		= "gefp",
-	.mask		= gef_pic_mask,
-	.mask_ack	= gef_pic_mask_ack,
-	.unmask		= gef_pic_unmask,
+	.irq_mask	= gef_pic_mask,
+	.irq_mask_ack	= gef_pic_mask_ack,
+	.irq_unmask	= gef_pic_unmask,
 };
 
 
@@ -163,8 +163,8 @@
 			  irq_hw_number_t hwirq)
 {
 	/* All interrupts are LEVEL sensitive */
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &gef_pic_chip, handle_level_irq);
 
 	return 0;
 }
@@ -225,7 +225,7 @@
 		return;
 
 	/* Chain with parent controller */
-	set_irq_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
+	irq_set_chained_handler(gef_pic_cascade_irq, gef_pic_cascade);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/86xx/pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/86xx/pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/86xx/pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/86xx/pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,10 +19,13 @@
 #ifdef CONFIG_PPC_I8259
 static void mpc86xx_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 #endif	/* CONFIG_PPC_I8259 */
 
@@ -74,6 +77,6 @@
 	i8259_init(cascade_node, 0);
 	of_node_put(cascade_node);
 
-	set_irq_chained_handler(cascade_irq, mpc86xx_8259_cascade);
+	irq_set_chained_handler(cascade_irq, mpc86xx_8259_cascade);
 #endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/Kconfig linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/Kconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -49,12 +49,6 @@
 	  This enables support for the Analogue & Micro Adder 875
 	  board.
 
-config PPC_MGSUVD
-	bool "MGSUVD"
-	select CPM1
-	help
-	  This enables support for the Keymile MGSUVD board.
-
 config TQM8XX
 	bool "TQM8XX"
 	select CPM1
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/m8xx_setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -218,15 +218,20 @@
 
 static void cpm_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip;
 	int cascade_irq;
 
 	if ((cascade_irq = cpm_get_irq()) >= 0) {
 		struct irq_desc *cdesc = irq_to_desc(cascade_irq);
 
 		generic_handle_irq(cascade_irq);
-		cdesc->chip->eoi(cascade_irq);
+
+		chip = irq_desc_get_chip(cdesc);
+		chip->irq_eoi(&cdesc->irq_data);
 	}
-	desc->chip->eoi(irq);
+
+	chip = irq_desc_get_chip(desc);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 /* Initialize the internal interrupt controllers.  The number of
@@ -246,5 +251,5 @@
 
 	irq = cpm_pic_init();
 	if (irq != NO_IRQ)
-		set_irq_chained_handler(irq, cpm_cascade);
+		irq_set_chained_handler(irq, cpm_cascade);
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/Makefile linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/Makefile
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,5 +6,4 @@
 obj-$(CONFIG_MPC86XADS)   += mpc86xads_setup.o
 obj-$(CONFIG_PPC_EP88XC)  += ep88xc.o
 obj-$(CONFIG_PPC_ADDER875) += adder875.o
-obj-$(CONFIG_PPC_MGSUVD) += mgsuvd.o
 obj-$(CONFIG_TQM8XX)      += tqm8xx_setup.o
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/mgsuvd.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/mgsuvd.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/8xx/mgsuvd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/8xx/mgsuvd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-/*
- *
- * Platform setup for the Keymile mgsuvd board
- *
- * Heiko Schocher <hs@denx.de>
- *
- * Copyright 2008 DENX Software Engineering GmbH
- *
- * 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_platform.h>
-
-#include <asm/io.h>
-#include <asm/machdep.h>
-#include <asm/processor.h>
-#include <asm/cpm1.h>
-#include <asm/prom.h>
-#include <asm/fs_pd.h>
-
-#include "mpc8xx.h"
-
-struct cpm_pin {
-	int port, pin, flags;
-};
-
-static __initdata struct cpm_pin mgsuvd_pins[] = {
-	/* SMC1 */
-	{CPM_PORTB, 24, CPM_PIN_INPUT}, /* RX */
-	{CPM_PORTB, 25, CPM_PIN_INPUT | CPM_PIN_SECONDARY}, /* TX */
-
-	/* SCC3 */
-	{CPM_PORTA, 10, CPM_PIN_INPUT},
-	{CPM_PORTA, 11, CPM_PIN_INPUT},
-	{CPM_PORTA, 3, CPM_PIN_INPUT},
-	{CPM_PORTA, 2, CPM_PIN_INPUT},
-	{CPM_PORTC, 13, CPM_PIN_INPUT},
-};
-
-static void __init init_ioports(void)
-{
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(mgsuvd_pins); i++) {
-		struct cpm_pin *pin = &mgsuvd_pins[i];
-		cpm1_set_pin(pin->port, pin->pin, pin->flags);
-	}
-
-	setbits16(&mpc8xx_immr->im_ioport.iop_pcso, 0x300);
-	cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK5, CPM_CLK_RX);
-	cpm1_clk_setup(CPM_CLK_SCC3, CPM_CLK6, CPM_CLK_TX);
-	cpm1_clk_setup(CPM_CLK_SMC1, CPM_BRG1, CPM_CLK_RTX);
-}
-
-static void __init mgsuvd_setup_arch(void)
-{
-	cpm_reset();
-	init_ioports();
-}
-
-static __initdata struct of_device_id of_bus_ids[] = {
-	{ .compatible = "simple-bus" },
-	{},
-};
-
-static int __init declare_of_platform_devices(void)
-{
-	of_platform_bus_probe(NULL, of_bus_ids, NULL);
-	return 0;
-}
-machine_device_initcall(mgsuvd, declare_of_platform_devices);
-
-static int __init mgsuvd_probe(void)
-{
-	unsigned long root = of_get_flat_dt_root();
-	return of_flat_dt_is_compatible(root, "keymile,mgsuvd");
-}
-
-define_machine(mgsuvd) {
-	.name           = "MGSUVD",
-	.probe          = mgsuvd_probe,
-	.setup_arch     = mgsuvd_setup_arch,
-	.init_IRQ       = mpc8xx_pics_init,
-	.get_irq        = mpc8xx_get_irq,
-	.restart        = mpc8xx_restart,
-	.calibrate_decr = mpc8xx_calibrate_decr,
-	.set_rtc_time   = mpc8xx_set_rtc_time,
-	.get_rtc_time   = mpc8xx_get_rtc_time,
-};
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/axon_msi.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/axon_msi.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/axon_msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/axon_msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,8 @@
 
 static void axon_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct axon_msic *msic = get_irq_data(irq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct axon_msic *msic = irq_get_handler_data(irq);
 	u32 write_offset, msi;
 	int idx;
 	int retry = 0;
@@ -145,7 +146,7 @@
 		msic->read_offset &= MSIC_FIFO_SIZE_MASK;
 	}
 
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static struct axon_msic *find_msi_translator(struct pci_dev *dev)
@@ -286,7 +287,7 @@
 		}
 		dev_dbg(&dev->dev, "axon_msi: allocated virq 0x%x\n", virq);
 
-		set_irq_msi(virq, entry);
+		irq_set_msi_desc(virq, entry);
 		msg.data = virq;
 		write_msi_msg(virq, &msg);
 	}
@@ -304,7 +305,7 @@
 		if (entry->irq == NO_IRQ)
 			continue;
 
-		set_irq_msi(entry->irq, NULL);
+		irq_set_msi_desc(entry->irq, NULL);
 		irq_dispose_mapping(entry->irq);
 	}
 }
@@ -319,7 +320,7 @@
 static int msic_host_map(struct irq_host *h, unsigned int virq,
 			 irq_hw_number_t hw)
 {
-	set_irq_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq);
+	irq_set_chip_and_handler(virq, &msic_irq_chip, handle_simple_irq);
 
 	return 0;
 }
@@ -328,7 +329,7 @@
 	.map	= msic_host_map,
 };
 
-static int axon_msi_shutdown(struct platform_device *device)
+static void axon_msi_shutdown(struct platform_device *device)
 {
 	struct axon_msic *msic = dev_get_drvdata(&device->dev);
 	u32 tmp;
@@ -338,12 +339,9 @@
 	tmp  = dcr_read(msic->dcr_host, MSIC_CTRL_REG);
 	tmp &= ~MSIC_CTRL_ENABLE & ~MSIC_CTRL_IRQ_ENABLE;
 	msic_dcr_write(msic, MSIC_CTRL_REG, tmp);
-
-	return 0;
 }
 
-static int axon_msi_probe(struct platform_device *device,
-			  const struct of_device_id *device_id)
+static int axon_msi_probe(struct platform_device *device)
 {
 	struct device_node *dn = device->dev.of_node;
 	struct axon_msic *msic;
@@ -402,8 +400,8 @@
 
 	msic->irq_host->host_data = msic;
 
-	set_irq_data(virq, msic);
-	set_irq_chained_handler(virq, axon_msi_cascade);
+	irq_set_handler_data(virq, msic);
+	irq_set_chained_handler(virq, axon_msi_cascade);
 	pr_devel("axon_msi: irq 0x%x setup for axon_msi\n", virq);
 
 	/* Enable the MSIC hardware */
@@ -446,7 +444,7 @@
 	{}
 };
 
-static struct of_platform_driver axon_msi_driver = {
+static struct platform_driver axon_msi_driver = {
 	.probe		= axon_msi_probe,
 	.shutdown	= axon_msi_shutdown,
 	.driver = {
@@ -458,7 +456,7 @@
 
 static int __init axon_msi_init(void)
 {
-	return of_register_platform_driver(&axon_msi_driver);
+	return platform_driver_register(&axon_msi_driver);
 }
 subsys_initcall(axon_msi_init);
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/beat_interrupt.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/beat_interrupt.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/beat_interrupt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/beat_interrupt.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,59 +61,59 @@
 		panic("Failed to set mask IRQ!");
 }
 
-static void beatic_mask_irq(unsigned int irq_plug)
+static void beatic_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_enable[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_enable[d->irq/64] &= ~(1UL << (63 - (d->irq%64)));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
-static void beatic_unmask_irq(unsigned int irq_plug)
+static void beatic_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_enable[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_enable[d->irq/64] |= 1UL << (63 - (d->irq%64));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
-static void beatic_ack_irq(unsigned int irq_plug)
+static void beatic_ack_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_ack[irq_plug/64] &= ~(1UL << (63 - (irq_plug%64)));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_ack[d->irq/64] &= ~(1UL << (63 - (d->irq%64)));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
-static void beatic_end_irq(unsigned int irq_plug)
+static void beatic_end_irq(struct irq_data *d)
 {
 	s64 err;
 	unsigned long flags;
 
-	err = beat_downcount_of_interrupt(irq_plug);
+	err = beat_downcount_of_interrupt(d->irq);
 	if (err != 0) {
 		if ((err & 0xFFFFFFFF) != 0xFFFFFFF5) /* -11: wrong state */
 			panic("Failed to downcount IRQ! Error = %16llx", err);
 
-		printk(KERN_ERR "IRQ over-downcounted, plug %d\n", irq_plug);
+		printk(KERN_ERR "IRQ over-downcounted, plug %d\n", d->irq);
 	}
 	raw_spin_lock_irqsave(&beatic_irq_mask_lock, flags);
-	beatic_irq_mask_ack[irq_plug/64] |= 1UL << (63 - (irq_plug%64));
-	beatic_update_irq_mask(irq_plug);
+	beatic_irq_mask_ack[d->irq/64] |= 1UL << (63 - (d->irq%64));
+	beatic_update_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&beatic_irq_mask_lock, flags);
 }
 
 static struct irq_chip beatic_pic = {
 	.name = "CELL-BEAT",
-	.unmask = beatic_unmask_irq,
-	.mask = beatic_mask_irq,
-	.eoi = beatic_end_irq,
+	.irq_unmask = beatic_unmask_irq,
+	.irq_mask = beatic_mask_irq,
+	.irq_eoi = beatic_end_irq,
 };
 
 /*
@@ -136,15 +136,14 @@
 static int beatic_pic_host_map(struct irq_host *h, unsigned int virq,
 			       irq_hw_number_t hw)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
 	int64_t	err;
 
 	err = beat_construct_and_connect_irq_plug(virq, hw);
 	if (err < 0)
 		return -EIO;
 
-	desc->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &beatic_pic, handle_fasteoi_irq);
 	return 0;
 }
 
@@ -232,7 +231,7 @@
 
 	ret = beatic_get_irq_plug();
 	if (ret != NO_IRQ)
-		beatic_ack_irq(ret);
+		beatic_ack_irq(irq_get_irq_data(ret));
 	return ret;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/interrupt.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/interrupt.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/interrupt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/interrupt.c	2011-05-19 00:06:34.000000000 -0400
@@ -72,15 +72,15 @@
 		return (node << IIC_IRQ_NODE_SHIFT) | (class << 4) | unit;
 }
 
-static void iic_mask(unsigned int irq)
+static void iic_mask(struct irq_data *d)
 {
 }
 
-static void iic_unmask(unsigned int irq)
+static void iic_unmask(struct irq_data *d)
 {
 }
 
-static void iic_eoi(unsigned int irq)
+static void iic_eoi(struct irq_data *d)
 {
 	struct iic *iic = &__get_cpu_var(cpu_iic);
 	out_be64(&iic->regs->prio, iic->eoi_stack[--iic->eoi_ptr]);
@@ -89,19 +89,21 @@
 
 static struct irq_chip iic_chip = {
 	.name = "CELL-IIC",
-	.mask = iic_mask,
-	.unmask = iic_unmask,
-	.eoi = iic_eoi,
+	.irq_mask = iic_mask,
+	.irq_unmask = iic_unmask,
+	.irq_eoi = iic_eoi,
 };
 
 
-static void iic_ioexc_eoi(unsigned int irq)
+static void iic_ioexc_eoi(struct irq_data *d)
 {
 }
 
 static void iic_ioexc_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct cbe_iic_regs __iomem *node_iic = (void __iomem *)desc->handler_data;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct cbe_iic_regs __iomem *node_iic =
+		(void __iomem *)irq_desc_get_handler_data(desc);
 	unsigned int base = (irq & 0xffffff00) | IIC_IRQ_TYPE_IOEXC;
 	unsigned long bits, ack;
 	int cascade;
@@ -128,15 +130,15 @@
 		if (ack)
 			out_be64(&node_iic->iic_is, ack);
 	}
-	desc->chip->eoi(irq);
+	chip->irq_eoi(&desc->irq_data);
 }
 
 
 static struct irq_chip iic_ioexc_chip = {
 	.name = "CELL-IOEX",
-	.mask = iic_mask,
-	.unmask = iic_unmask,
-	.eoi = iic_ioexc_eoi,
+	.irq_mask = iic_mask,
+	.irq_unmask = iic_unmask,
+	.irq_eoi = iic_ioexc_eoi,
 };
 
 /* Get an IRQ number from the pending state register of the IIC */
@@ -233,65 +235,19 @@
 				    "IBM,CBEA-Internal-Interrupt-Controller");
 }
 
-extern int noirqdebug;
-
-static void handle_iic_irq(unsigned int irq, struct irq_desc *desc)
-{
-	raw_spin_lock(&desc->lock);
-
-	desc->status &= ~(IRQ_REPLAY | IRQ_WAITING);
-
-	/*
-	 * If we're currently running this IRQ, or its disabled,
-	 * we shouldn't process the IRQ. Mark it pending, handle
-	 * the necessary masking and go out
-	 */
-	if (unlikely((desc->status & (IRQ_INPROGRESS | IRQ_DISABLED)) ||
-		    !desc->action)) {
-		desc->status |= IRQ_PENDING;
-		goto out_eoi;
-	}
-
-	kstat_incr_irqs_this_cpu(irq, desc);
-
-	/* Mark the IRQ currently in progress.*/
-	desc->status |= IRQ_INPROGRESS;
-
-	do {
-		struct irqaction *action = desc->action;
-		irqreturn_t action_ret;
-
-		if (unlikely(!action))
-			goto out_eoi;
-
-		desc->status &= ~IRQ_PENDING;
-		raw_spin_unlock(&desc->lock);
-		action_ret = handle_IRQ_event(irq, action);
-		if (!noirqdebug)
-			note_interrupt(irq, desc, action_ret);
-		raw_spin_lock(&desc->lock);
-
-	} while ((desc->status & (IRQ_PENDING | IRQ_DISABLED)) == IRQ_PENDING);
-
-	desc->status &= ~IRQ_INPROGRESS;
-out_eoi:
-	desc->chip->eoi(irq);
-	raw_spin_unlock(&desc->lock);
-}
-
 static int iic_host_map(struct irq_host *h, unsigned int virq,
 			irq_hw_number_t hw)
 {
 	switch (hw & IIC_IRQ_TYPE_MASK) {
 	case IIC_IRQ_TYPE_IPI:
-		set_irq_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
+		irq_set_chip_and_handler(virq, &iic_chip, handle_percpu_irq);
 		break;
 	case IIC_IRQ_TYPE_IOEXC:
-		set_irq_chip_and_handler(virq, &iic_ioexc_chip,
-					 handle_iic_irq);
+		irq_set_chip_and_handler(virq, &iic_ioexc_chip,
+					 handle_edge_eoi_irq);
 		break;
 	default:
-		set_irq_chip_and_handler(virq, &iic_chip, handle_iic_irq);
+		irq_set_chip_and_handler(virq, &iic_chip, handle_edge_eoi_irq);
 	}
 	return 0;
 }
@@ -408,8 +364,8 @@
 		 * irq_data is a generic pointer that gets passed back
 		 * to us later, so the forced cast is fine.
 		 */
-		set_irq_data(cascade, (void __force *)node_iic);
-		set_irq_chained_handler(cascade , iic_ioexc_cascade);
+		irq_set_handler_data(cascade, (void __force *)node_iic);
+		irq_set_chained_handler(cascade, iic_ioexc_cascade);
 		out_be64(&node_iic->iic_ir,
 			 (1 << 12)		/* priority */ |
 			 (node << 4)		/* dest node */ |
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/Kconfig linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/Kconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
 	select PPC_INDIRECT_IO
 	select PPC_NATIVE
 	select PPC_RTAS
+	select IRQ_EDGE_EOI_HANDLER
 
 config PPC_CELL_NATIVE
 	bool
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/setup.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/setup.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -187,13 +187,15 @@
 
 static void cell_mpic_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct mpic *mpic = desc->handler_data;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct mpic *mpic = irq_desc_get_handler_data(desc);
 	unsigned int virq;
 
 	virq = mpic_get_one_irq(mpic);
 	if (virq != NO_IRQ)
 		generic_handle_irq(virq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init mpic_init_IRQ(void)
@@ -221,8 +223,8 @@
 
 		printk(KERN_INFO "%s : hooking up to IRQ %d\n",
 		       dn->full_name, virq);
-		set_irq_data(virq, mpic);
-		set_irq_chained_handler(virq, cell_mpic_cascade);
+		irq_set_handler_data(virq, mpic);
+		irq_set_chained_handler(virq, cell_mpic_cascade);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spider-pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spider-pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spider-pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spider-pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -79,30 +79,30 @@
 	return pic->regs + TIR_CFGA + 8 * src;
 }
 
-static void spider_unmask_irq(unsigned int virq)
+static void spider_unmask_irq(struct irq_data *d)
 {
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
 
 	out_be32(cfg, in_be32(cfg) | 0x30000000u);
 }
 
-static void spider_mask_irq(unsigned int virq)
+static void spider_mask_irq(struct irq_data *d)
 {
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	void __iomem *cfg = spider_get_irq_config(pic, irq_map[virq].hwirq);
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	void __iomem *cfg = spider_get_irq_config(pic, irq_map[d->irq].hwirq);
 
 	out_be32(cfg, in_be32(cfg) & ~0x30000000u);
 }
 
-static void spider_ack_irq(unsigned int virq)
+static void spider_ack_irq(struct irq_data *d)
 {
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	unsigned int src = irq_map[virq].hwirq;
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	unsigned int src = irq_map[d->irq].hwirq;
 
 	/* Reset edge detection logic if necessary
 	 */
-	if (irq_to_desc(virq)->status & IRQ_LEVEL)
+	if (irqd_is_level_type(d))
 		return;
 
 	/* Only interrupts 47 to 50 can be set to edge */
@@ -113,13 +113,12 @@
 	out_be32(pic->regs + TIR_EDC, 0x100 | (src & 0xf));
 }
 
-static int spider_set_irq_type(unsigned int virq, unsigned int type)
+static int spider_set_irq_type(struct irq_data *d, unsigned int type)
 {
 	unsigned int sense = type & IRQ_TYPE_SENSE_MASK;
-	struct spider_pic *pic = spider_virq_to_pic(virq);
-	unsigned int hw = irq_map[virq].hwirq;
+	struct spider_pic *pic = spider_virq_to_pic(d->irq);
+	unsigned int hw = irq_map[d->irq].hwirq;
 	void __iomem *cfg = spider_get_irq_config(pic, hw);
-	struct irq_desc *desc = irq_to_desc(virq);
 	u32 old_mask;
 	u32 ic;
 
@@ -147,12 +146,6 @@
 		return -EINVAL;
 	}
 
-	/* Update irq_desc */
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= type & IRQ_TYPE_SENSE_MASK;
-	if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		desc->status |= IRQ_LEVEL;
-
 	/* Configure the source. One gross hack that was there before and
 	 * that I've kept around is the priority to the BE which I set to
 	 * be the same as the interrupt source number. I don't know wether
@@ -169,19 +162,19 @@
 
 static struct irq_chip spider_pic = {
 	.name = "SPIDER",
-	.unmask = spider_unmask_irq,
-	.mask = spider_mask_irq,
-	.ack = spider_ack_irq,
-	.set_type = spider_set_irq_type,
+	.irq_unmask = spider_unmask_irq,
+	.irq_mask = spider_mask_irq,
+	.irq_ack = spider_ack_irq,
+	.irq_set_type = spider_set_irq_type,
 };
 
 static int spider_host_map(struct irq_host *h, unsigned int virq,
 			irq_hw_number_t hw)
 {
-	set_irq_chip_and_handler(virq, &spider_pic, handle_level_irq);
+	irq_set_chip_and_handler(virq, &spider_pic, handle_level_irq);
 
 	/* Set default irq type */
-	set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
 	return 0;
 }
@@ -207,7 +200,8 @@
 
 static void spider_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct spider_pic *pic = desc->handler_data;
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct spider_pic *pic = irq_desc_get_handler_data(desc);
 	unsigned int cs, virq;
 
 	cs = in_be32(pic->regs + TIR_CS) >> 24;
@@ -215,9 +209,11 @@
 		virq = NO_IRQ;
 	else
 		virq = irq_linear_revmap(pic->host, cs);
+
 	if (virq != NO_IRQ)
 		generic_handle_irq(virq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 /* For hooking up the cascace we have a problem. Our device-tree is
@@ -325,8 +321,8 @@
 	virq = spider_find_cascade_and_node(pic);
 	if (virq == NO_IRQ)
 		return;
-	set_irq_data(virq, pic);
-	set_irq_chained_handler(virq, spider_irq_cascade);
+	irq_set_handler_data(virq, pic);
+	irq_set_chained_handler(virq, spider_irq_cascade);
 
 	printk(KERN_INFO "spider_pic: node %d, addr: 0x%lx %s\n",
 	       pic->node_id, addr, of_node->full_name);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/lscsa_alloc.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,7 +90,7 @@
 	 */
 	for (i = 0; i < SPU_LSCSA_NUM_BIG_PAGES; i++) {
 		/* XXX This is likely to fail, we should use a special pool
-		 *     similiar to what hugetlbfs does.
+		 *     similar to what hugetlbfs does.
 		 */
 		csa->lscsa_pages[i] = alloc_pages(GFP_KERNEL,
 						  SPU_64K_PAGE_ORDER);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/sched.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/sched.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/sched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/sched.c	2011-05-19 00:06:34.000000000 -0400
@@ -846,7 +846,7 @@
 		struct list_head *rq = &spu_prio->runq[best];
 
 		list_for_each_entry(ctx, rq, rq) {
-			/* XXX(hch): check for affinity here aswell */
+			/* XXX(hch): check for affinity here as well */
 			if (__node_allowed(ctx, node)) {
 				__spu_del_from_rq(ctx);
 				goto found;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/spu_restore.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/spu_restore.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/spu_restore.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/spu_restore.c	2011-05-19 00:06:34.000000000 -0400
@@ -284,7 +284,7 @@
 		exit_instrs[3] = BR_INSTR;
 		break;
 	default:
-		/* SPU_Status[R]=1. No additonal instructions. */
+		/* SPU_Status[R]=1. No additional instructions. */
 		break;
 	}
 	spu_sync();
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/cell/spufs/syscalls.c	2011-05-19 00:06:34.000000000 -0400
@@ -70,7 +70,7 @@
 	if (!IS_ERR(tmp)) {
 		struct nameidata nd;
 
-		ret = path_lookup(tmp, LOOKUP_PARENT, &nd);
+		ret = kern_path_parent(tmp, &nd);
 		if (!ret) {
 			nd.flags |= LOOKUP_OPEN | LOOKUP_CREATE;
 			ret = spufs_create(&nd, flags, mode, neighbor);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/chrp/setup.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/chrp/setup.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/chrp/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/chrp/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -365,10 +365,13 @@
 
 static void chrp_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 /*
@@ -514,7 +517,7 @@
 		if (cascade_irq == NO_IRQ)
 			printk(KERN_ERR "i8259: failed to map cascade irq\n");
 		else
-			set_irq_chained_handler(cascade_irq,
+			irq_set_chained_handler(cascade_irq,
 						chrp_8259_cascade);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/flipper-pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/flipper-pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/flipper-pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/flipper-pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,10 +46,10 @@
  *
  */
 
-static void flipper_pic_mask_and_ack(unsigned int virq)
+static void flipper_pic_mask_and_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 	u32 mask = 1 << irq;
 
 	clrbits32(io_base + FLIPPER_IMR, mask);
@@ -57,27 +57,27 @@
 	out_be32(io_base + FLIPPER_ICR, mask);
 }
 
-static void flipper_pic_ack(unsigned int virq)
+static void flipper_pic_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	/* this is at least needed for RSW */
 	out_be32(io_base + FLIPPER_ICR, 1 << irq);
 }
 
-static void flipper_pic_mask(unsigned int virq)
+static void flipper_pic_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	clrbits32(io_base + FLIPPER_IMR, 1 << irq);
 }
 
-static void flipper_pic_unmask(unsigned int virq)
+static void flipper_pic_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	setbits32(io_base + FLIPPER_IMR, 1 << irq);
 }
@@ -85,10 +85,10 @@
 
 static struct irq_chip flipper_pic = {
 	.name		= "flipper-pic",
-	.ack		= flipper_pic_ack,
-	.mask_ack	= flipper_pic_mask_and_ack,
-	.mask		= flipper_pic_mask,
-	.unmask		= flipper_pic_unmask,
+	.irq_ack	= flipper_pic_ack,
+	.irq_mask_ack	= flipper_pic_mask_and_ack,
+	.irq_mask	= flipper_pic_mask,
+	.irq_unmask	= flipper_pic_unmask,
 };
 
 /*
@@ -101,16 +101,16 @@
 static int flipper_pic_map(struct irq_host *h, unsigned int virq,
 			   irq_hw_number_t hwirq)
 {
-	set_irq_chip_data(virq, h->host_data);
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &flipper_pic, handle_level_irq);
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &flipper_pic, handle_level_irq);
 	return 0;
 }
 
 static void flipper_pic_unmap(struct irq_host *h, unsigned int irq)
 {
-	set_irq_chip_data(irq, NULL);
-	set_irq_chip(irq, NULL);
+	irq_set_chip_data(irq, NULL);
+	irq_set_chip(irq, NULL);
 }
 
 static int flipper_pic_match(struct irq_host *h, struct device_node *np)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/hlwd-pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/hlwd-pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/hlwd-pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/hlwd-pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,36 +41,36 @@
  *
  */
 
-static void hlwd_pic_mask_and_ack(unsigned int virq)
+static void hlwd_pic_mask_and_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 	u32 mask = 1 << irq;
 
 	clrbits32(io_base + HW_BROADWAY_IMR, mask);
 	out_be32(io_base + HW_BROADWAY_ICR, mask);
 }
 
-static void hlwd_pic_ack(unsigned int virq)
+static void hlwd_pic_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	out_be32(io_base + HW_BROADWAY_ICR, 1 << irq);
 }
 
-static void hlwd_pic_mask(unsigned int virq)
+static void hlwd_pic_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	clrbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
 }
 
-static void hlwd_pic_unmask(unsigned int virq)
+static void hlwd_pic_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void __iomem *io_base = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void __iomem *io_base = irq_data_get_irq_chip_data(d);
 
 	setbits32(io_base + HW_BROADWAY_IMR, 1 << irq);
 }
@@ -78,10 +78,10 @@
 
 static struct irq_chip hlwd_pic = {
 	.name		= "hlwd-pic",
-	.ack		= hlwd_pic_ack,
-	.mask_ack	= hlwd_pic_mask_and_ack,
-	.mask		= hlwd_pic_mask,
-	.unmask		= hlwd_pic_unmask,
+	.irq_ack	= hlwd_pic_ack,
+	.irq_mask_ack	= hlwd_pic_mask_and_ack,
+	.irq_mask	= hlwd_pic_mask,
+	.irq_unmask	= hlwd_pic_unmask,
 };
 
 /*
@@ -94,16 +94,16 @@
 static int hlwd_pic_map(struct irq_host *h, unsigned int virq,
 			   irq_hw_number_t hwirq)
 {
-	set_irq_chip_data(virq, h->host_data);
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &hlwd_pic, handle_level_irq);
 	return 0;
 }
 
 static void hlwd_pic_unmap(struct irq_host *h, unsigned int irq)
 {
-	set_irq_chip_data(irq, NULL);
-	set_irq_chip(irq, NULL);
+	irq_set_chip_data(irq, NULL);
+	irq_set_chip(irq, NULL);
 }
 
 static struct irq_host_ops hlwd_irq_host_ops = {
@@ -129,11 +129,12 @@
 static void hlwd_pic_irq_cascade(unsigned int cascade_virq,
 				      struct irq_desc *desc)
 {
-	struct irq_host *irq_host = get_irq_data(cascade_virq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_host *irq_host = irq_get_handler_data(cascade_virq);
 	unsigned int virq;
 
 	raw_spin_lock(&desc->lock);
-	desc->chip->mask(cascade_virq); /* IRQ_LEVEL */
+	chip->irq_mask(&desc->irq_data); /* IRQ_LEVEL */
 	raw_spin_unlock(&desc->lock);
 
 	virq = __hlwd_pic_get_irq(irq_host);
@@ -143,9 +144,9 @@
 		pr_err("spurious interrupt!\n");
 
 	raw_spin_lock(&desc->lock);
-	desc->chip->ack(cascade_virq); /* IRQ_LEVEL */
-	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-		desc->chip->unmask(cascade_virq);
+	chip->irq_ack(&desc->irq_data); /* IRQ_LEVEL */
+	if (!irqd_irq_disabled(&desc->irq_data) && chip->irq_unmask)
+		chip->irq_unmask(&desc->irq_data);
 	raw_spin_unlock(&desc->lock);
 }
 
@@ -217,8 +218,8 @@
 			host = hlwd_pic_init(np);
 			BUG_ON(!host);
 			cascade_virq = irq_of_parse_and_map(np, 0);
-			set_irq_data(cascade_virq, host);
-			set_irq_chained_handler(cascade_virq,
+			irq_set_handler_data(cascade_virq, host);
+			irq_set_chained_handler(cascade_virq,
 						hlwd_pic_irq_cascade);
 			hlwd_irq_host = host;
 			break;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/holly.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/holly.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/holly.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/holly.c	2011-05-19 00:06:34.000000000 -0400
@@ -198,8 +198,8 @@
 	cascade_pci_irq = irq_of_parse_and_map(tsi_pci, 0);
 	pr_debug("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__, (u32) cascade_pci_irq);
 	tsi108_pci_int_init(cascade_node);
-	set_irq_data(cascade_pci_irq, mpic);
-	set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+	irq_set_handler_data(cascade_pci_irq, mpic);
+	irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
 #endif
 	/* Configure MPIC outputs to CPU0 */
 	tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/embedded6xx/mpc7448_hpc2.c	2011-05-19 00:06:34.000000000 -0400
@@ -153,8 +153,8 @@
 	DBG("%s: tsi108 cascade_pci_irq = 0x%x\n", __func__,
 	    (u32) cascade_pci_irq);
 	tsi108_pci_int_init(cascade_node);
-	set_irq_data(cascade_pci_irq, mpic);
-	set_irq_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
+	irq_set_handler_data(cascade_pci_irq, mpic);
+	irq_set_chained_handler(cascade_pci_irq, tsi108_irq_cascade);
 #endif
 	/* Configure MPIC outputs to CPU0 */
 	tsi108_write_reg(TSI108_MPIC_OFFSET + 0x30c, 0);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/iseries/irq.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/iseries/irq.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/iseries/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/iseries/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,11 +167,11 @@
  * This will be called by device drivers (via enable_IRQ)
  * to enable INTA in the bridge interrupt status register.
  */
-static void iseries_enable_IRQ(unsigned int irq)
+static void iseries_enable_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	/* The IRQ has already been locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -184,23 +184,23 @@
 }
 
 /* This is called by iseries_activate_IRQs */
-static unsigned int iseries_startup_IRQ(unsigned int irq)
+static unsigned int iseries_startup_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	bus = REAL_IRQ_TO_BUS(rirq);
 	function = REAL_IRQ_TO_FUNC(rirq);
 	dev_id = (REAL_IRQ_TO_IDSEL(rirq) << 4) + function;
 
 	/* Link the IRQ number to the bridge */
-	HvCallXm_connectBusUnit(bus, sub_bus, dev_id, irq);
+	HvCallXm_connectBusUnit(bus, sub_bus, dev_id, d->irq);
 
 	/* Unmask bridge interrupts in the FISR */
 	mask = 0x01010000 << function;
 	HvCallPci_unmaskFisr(bus, sub_bus, dev_id, mask);
-	iseries_enable_IRQ(irq);
+	iseries_enable_IRQ(d);
 	return 0;
 }
 
@@ -215,21 +215,26 @@
 
 	for_each_irq (irq) {
 		struct irq_desc *desc = irq_to_desc(irq);
+		struct irq_chip *chip;
 
-		if (desc && desc->chip && desc->chip->startup) {
+		if (!desc)
+			continue;
+
+		chip = irq_desc_get_chip(desc);
+		if (chip && chip->irq_startup) {
 			raw_spin_lock_irqsave(&desc->lock, flags);
-			desc->chip->startup(irq);
+			chip->irq_startup(&desc->irq_data);
 			raw_spin_unlock_irqrestore(&desc->lock, flags);
 		}
 	}
 }
 
 /*  this is not called anywhere currently */
-static void iseries_shutdown_IRQ(unsigned int irq)
+static void iseries_shutdown_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	/* irq should be locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -248,11 +253,11 @@
  * This will be called by device drivers (via disable_IRQ)
  * to disable INTA in the bridge interrupt status register.
  */
-static void iseries_disable_IRQ(unsigned int irq)
+static void iseries_disable_IRQ(struct irq_data *d)
 {
 	u32 bus, dev_id, function, mask;
 	const u32 sub_bus = 0;
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	/* The IRQ has already been locked by the caller */
 	bus = REAL_IRQ_TO_BUS(rirq);
@@ -264,9 +269,9 @@
 	HvCallPci_maskInterrupts(bus, sub_bus, dev_id, mask);
 }
 
-static void iseries_end_IRQ(unsigned int irq)
+static void iseries_end_IRQ(struct irq_data *d)
 {
-	unsigned int rirq = (unsigned int)irq_map[irq].hwirq;
+	unsigned int rirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	HvCallPci_eoi(REAL_IRQ_TO_BUS(rirq), REAL_IRQ_TO_SUBBUS(rirq),
 		(REAL_IRQ_TO_IDSEL(rirq) << 4) + REAL_IRQ_TO_FUNC(rirq));
@@ -274,11 +279,11 @@
 
 static struct irq_chip iseries_pic = {
 	.name		= "iSeries",
-	.startup	= iseries_startup_IRQ,
-	.shutdown	= iseries_shutdown_IRQ,
-	.unmask		= iseries_enable_IRQ,
-	.mask		= iseries_disable_IRQ,
-	.eoi		= iseries_end_IRQ
+	.irq_startup	= iseries_startup_IRQ,
+	.irq_shutdown	= iseries_shutdown_IRQ,
+	.irq_unmask	= iseries_enable_IRQ,
+	.irq_mask	= iseries_disable_IRQ,
+	.irq_eoi	= iseries_end_IRQ
 };
 
 /*
@@ -341,7 +346,7 @@
 static int iseries_irq_host_map(struct irq_host *h, unsigned int virq,
 				irq_hw_number_t hw)
 {
-	set_irq_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
+	irq_set_chip_and_handler(virq, &iseries_pic, handle_fasteoi_irq);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/iseries/mf.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/iseries/mf.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/iseries/mf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/iseries/mf.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
 static int mf_initialized;
 
 /*
- * This is the structure layout for the Machine Facilites LPAR event
+ * This is the structure layout for the Machine Facilities LPAR event
  * flows.
  */
 struct vsp_cmd_data {
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/iseries/viopath.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/iseries/viopath.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/iseries/viopath.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/iseries/viopath.c	2011-05-19 00:06:34.000000000 -0400
@@ -396,7 +396,7 @@
 			viopathStatus[remoteLp].mTargetInst)) {
 			printk(VIOPATH_KERN_WARN
 			       "message from invalid partition. "
-			       "int msg rcvd, source inst (%d) doesnt match (%d)\n",
+			       "int msg rcvd, source inst (%d) doesn't match (%d)\n",
 			       viopathStatus[remoteLp].mTargetInst,
 			       event->xSourceInstanceId);
 			return;
@@ -407,7 +407,7 @@
 			viopathStatus[remoteLp].mSourceInst)) {
 			printk(VIOPATH_KERN_WARN
 			       "message from invalid partition. "
-			       "int msg rcvd, target inst (%d) doesnt match (%d)\n",
+			       "int msg rcvd, target inst (%d) doesn't match (%d)\n",
 			       viopathStatus[remoteLp].mSourceInst,
 			       event->xTargetInstanceId);
 			return;
@@ -418,7 +418,7 @@
 		    viopathStatus[remoteLp].mSourceInst) {
 			printk(VIOPATH_KERN_WARN
 			       "message from invalid partition. "
-			       "ack msg rcvd, source inst (%d) doesnt match (%d)\n",
+			       "ack msg rcvd, source inst (%d) doesn't match (%d)\n",
 			       viopathStatus[remoteLp].mSourceInst,
 			       event->xSourceInstanceId);
 			return;
@@ -428,7 +428,7 @@
 		    viopathStatus[remoteLp].mTargetInst) {
 			printk(VIOPATH_KERN_WARN
 			       "message from invalid partition. "
-			       "viopath: ack msg rcvd, target inst (%d) doesnt match (%d)\n",
+			       "viopath: ack msg rcvd, target inst (%d) doesn't match (%d)\n",
 			       viopathStatus[remoteLp].mTargetInst,
 			       event->xTargetInstanceId);
 			return;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/Kconfig linux-libre-2.6.39-gnu/arch/powerpc/platforms/Kconfig
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
 	help
 	  Support from booting from Open Firmware or yaboot using an
 	  Open Firmware client interface. This enables the kernel to
-	  communicate with open firmware to retrieve system informations
+	  communicate with open firmware to retrieve system information
 	  such as the device tree.
 
 	  In case of doubt, say Y
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/maple/pci.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/maple/pci.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/maple/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/maple/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -498,7 +498,7 @@
 		printk(KERN_DEBUG "Fixup U4 PCIe IRQ\n");
 		dev->irq = irq_create_mapping(NULL, 1);
 		if (dev->irq != NO_IRQ)
-			set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+			irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
 	}
 
 	/* Hide AMD8111 IDE interrupt when in legacy mode so
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pasemi/dma_lib.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pasemi/dma_lib.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pasemi/dma_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pasemi/dma_lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -379,9 +379,9 @@
 }
 EXPORT_SYMBOL(pasemi_dma_free_buf);
 
-/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel syncronization
+/* pasemi_dma_alloc_flag - Allocate a flag (event) for channel synchronization
  *
- * Allocates a flag for use with channel syncronization (event descriptors).
+ * Allocates a flag for use with channel synchronization (event descriptors).
  * Returns allocated flag (0-63), < 0 on error.
  */
 int pasemi_dma_alloc_flag(void)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pasemi/gpio_mdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -216,8 +216,7 @@
 }
 
 
-static int __devinit gpio_mdio_probe(struct platform_device *ofdev,
-				     const struct of_device_id *match)
+static int __devinit gpio_mdio_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -299,7 +298,7 @@
 };
 MODULE_DEVICE_TABLE(of, gpio_mdio_match);
 
-static struct of_platform_driver gpio_mdio_driver =
+static struct platform_driver gpio_mdio_driver =
 {
 	.probe		= gpio_mdio_probe,
 	.remove		= gpio_mdio_remove,
@@ -326,13 +325,13 @@
 	if (!gpio_regs)
 		return -ENODEV;
 
-	return of_register_platform_driver(&gpio_mdio_driver);
+	return platform_driver_register(&gpio_mdio_driver);
 }
 module_init(gpio_mdio_init);
 
 void gpio_mdio_exit(void)
 {
-	of_unregister_platform_driver(&gpio_mdio_driver);
+	platform_driver_unregister(&gpio_mdio_driver);
 	if (gpio_regs)
 		iounmap(gpio_regs);
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pasemi/setup.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pasemi/setup.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pasemi/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pasemi/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -239,8 +239,8 @@
 	if (nmiprop) {
 		nmi_virq = irq_create_mapping(NULL, *nmiprop);
 		mpic_irq_set_priority(nmi_virq, 15);
-		set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
-		mpic_unmask_irq(nmi_virq);
+		irq_set_irq_type(nmi_virq, IRQ_TYPE_EDGE_RISING);
+		mpic_unmask_irq(irq_get_irq_data(nmi_virq));
 	}
 
 	of_node_put(mpic_node);
@@ -266,7 +266,7 @@
 	if (nmi_virq != NO_IRQ && mpic_get_mcirq() == nmi_virq) {
 		printk(KERN_ERR "NMI delivered\n");
 		debugger(regs);
-		mpic_end_irq(nmi_virq);
+		mpic_end_irq(irq_get_irq_data(nmi_virq));
 		goto out;
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/cpufreq_32.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/cpufreq_32.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/cpufreq_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/cpufreq_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -429,7 +429,7 @@
 	return offset;
 }
 
-static int pmac_cpufreq_suspend(struct cpufreq_policy *policy, pm_message_t pmsg)
+static int pmac_cpufreq_suspend(struct cpufreq_policy *policy)
 {
 	/* Ok, this could be made a bit smarter, but let's be robust for now. We
 	 * always force a speed change to high speed before sleep, to make sure
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/low_i2c.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/low_i2c.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/low_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/low_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -904,7 +904,7 @@
 	printk(KERN_INFO "SMU i2c %s\n", controller->full_name);
 
 	/* Look for childs, note that they might not be of the right
-	 * type as older device trees mix i2c busses and other thigns
+	 * type as older device trees mix i2c busses and other things
 	 * at the same level
 	 */
 	for (busnode = NULL;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/Makefile linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/Makefile
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 obj-$(CONFIG_PMAC_BACKLIGHT)	+= backlight.o
 obj-$(CONFIG_CPU_FREQ_PMAC)	+= cpufreq_32.o
 obj-$(CONFIG_CPU_FREQ_PMAC64)	+= cpufreq_64.o
-# CONFIG_NVRAM is an arch. independant tristate symbol, for pmac32 we really
+# CONFIG_NVRAM is an arch. independent tristate symbol, for pmac32 we really
 # need this to be a bool.  Cheat here and pretend CONFIG_NVRAM=m is really
 # CONFIG_NVRAM=y
 obj-$(CONFIG_NVRAM:m=y)		+= nvram.o
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/pci.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/pci.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -299,7 +299,7 @@
  * This function deals with some "special cases" devices.
  *
  *  0 -> No special case
- *  1 -> Skip the device but act as if the access was successfull
+ *  1 -> Skip the device but act as if the access was successful
  *       (return 0xff's on reads, eventually, cache config space
  *       accesses in a later version)
  * -1 -> Hide the device (unsuccessful access)
@@ -988,7 +988,7 @@
 	    dev->vendor == PCI_VENDOR_ID_DEC &&
 	    dev->device == PCI_DEVICE_ID_DEC_TULIP_PLUS) {
 		dev->irq = irq_create_mapping(NULL, 60);
-		set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
+		irq_set_irq_type(dev->irq, IRQ_TYPE_LEVEL_LOW);
 	}
 #endif /* CONFIG_PPC32 */
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/pic.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,9 +82,9 @@
 	}
 }
 
-static void pmac_mask_and_ack_irq(unsigned int virq)
+static void pmac_mask_and_ack_irq(struct irq_data *d)
 {
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
         unsigned long flags;
@@ -104,9 +104,9 @@
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
-static void pmac_ack_irq(unsigned int virq)
+static void pmac_ack_irq(struct irq_data *d)
 {
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
         unsigned long flags;
@@ -149,15 +149,15 @@
 /* When an irq gets requested for the first client, if it's an
  * edge interrupt, we clear any previous one on the controller
  */
-static unsigned int pmac_startup_irq(unsigned int virq)
+static unsigned int pmac_startup_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
         unsigned long bit = 1UL << (src & 0x1f);
         int i = src >> 5;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
-	if ((irq_to_desc(virq)->status & IRQ_LEVEL) == 0)
+	if (!irqd_is_level_type(d))
 		out_le32(&pmac_irq_hw[i]->ack, bit);
         __set_bit(src, ppc_cached_irq_mask);
         __pmac_set_irq_mask(src, 0);
@@ -166,10 +166,10 @@
 	return 0;
 }
 
-static void pmac_mask_irq(unsigned int virq)
+static void pmac_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
         __clear_bit(src, ppc_cached_irq_mask);
@@ -177,10 +177,10 @@
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
-static void pmac_unmask_irq(unsigned int virq)
+static void pmac_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	unsigned int src = irq_map[virq].hwirq;
+	unsigned int src = irq_map[d->irq].hwirq;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
 	__set_bit(src, ppc_cached_irq_mask);
@@ -188,24 +188,24 @@
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 }
 
-static int pmac_retrigger(unsigned int virq)
+static int pmac_retrigger(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&pmac_pic_lock, flags);
-	__pmac_retrigger(irq_map[virq].hwirq);
+	__pmac_retrigger(irq_map[d->irq].hwirq);
 	raw_spin_unlock_irqrestore(&pmac_pic_lock, flags);
 	return 1;
 }
 
 static struct irq_chip pmac_pic = {
 	.name		= "PMAC-PIC",
-	.startup	= pmac_startup_irq,
-	.mask		= pmac_mask_irq,
-	.ack		= pmac_ack_irq,
-	.mask_ack	= pmac_mask_and_ack_irq,
-	.unmask		= pmac_unmask_irq,
-	.retrigger	= pmac_retrigger,
+	.irq_startup	= pmac_startup_irq,
+	.irq_mask	= pmac_mask_irq,
+	.irq_ack	= pmac_ack_irq,
+	.irq_mask_ack	= pmac_mask_and_ack_irq,
+	.irq_unmask	= pmac_unmask_irq,
+	.irq_retrigger	= pmac_retrigger,
 };
 
 static irqreturn_t gatwick_action(int cpl, void *dev_id)
@@ -289,7 +289,6 @@
 static int pmac_pic_host_map(struct irq_host *h, unsigned int virq,
 			     irq_hw_number_t hw)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
 	int level;
 
 	if (hw >= max_irqs)
@@ -300,9 +299,9 @@
 	 */
 	level = !!(level_mask[hw >> 5] & (1UL << (hw & 0x1f)));
 	if (level)
-		desc->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &pmac_pic, level ?
-				 handle_level_irq : handle_edge_irq);
+		irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &pmac_pic,
+				 level ? handle_level_irq : handle_edge_irq);
 	return 0;
 }
 
@@ -472,12 +471,14 @@
 
 static void pmac_u3_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct mpic *mpic = desc->handler_data;
-
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct mpic *mpic = irq_desc_get_handler_data(desc);
 	unsigned int cascade_irq = mpic_get_one_irq(mpic);
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init pmac_pic_setup_mpic_nmi(struct mpic *mpic)
@@ -589,8 +590,8 @@
 		of_node_put(slave);
 		return 0;
 	}
-	set_irq_data(cascade, mpic2);
-	set_irq_chained_handler(cascade, pmac_u3_cascade);
+	irq_set_handler_data(cascade, mpic2);
+	irq_set_chained_handler(cascade, pmac_u3_cascade);
 
 	of_node_put(slave);
 	return 0;
@@ -707,7 +708,7 @@
 	mb();
 	for (i = 0; i < max_real_irqs; ++i)
 		if (test_bit(i, sleep_save_mask))
-			pmac_unmask_irq(i);
+			pmac_unmask_irq(irq_get_irq_data(i));
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/pmac.h linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/pmac.h
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/pmac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/pmac.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,6 @@
 extern void pmac_check_ht_link(void);
 
 extern void pmac_setup_smp(void);
-extern void pmac32_cpu_die(void);
 extern void low_cpu_die(void) __attribute__((noreturn));
 
 extern int pmac_nvram_init(void);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/setup.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/setup.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -650,51 +650,6 @@
 		return PCI_PROBE_NORMAL;
 	return PCI_PROBE_DEVTREE;
 }
-
-#ifdef CONFIG_HOTPLUG_CPU
-/* access per cpu vars from generic smp.c */
-DECLARE_PER_CPU(int, cpu_state);
-
-static void pmac64_cpu_die(void)
-{
-	/*
-	 * turn off as much as possible, we'll be
-	 * kicked out as this will only be invoked
-	 * on core99 platforms for now ...
-	 */
-
-	printk(KERN_INFO "CPU#%d offline\n", smp_processor_id());
-	__get_cpu_var(cpu_state) = CPU_DEAD;
-	smp_wmb();
-
-	/*
-	 * during the path that leads here preemption is disabled,
-	 * reenable it now so that when coming up preempt count is
-	 * zero correctly
-	 */
-	preempt_enable();
-
-	/*
-	 * hard-disable interrupts for the non-NAP case, the NAP code
-	 * needs to re-enable interrupts (but soft-disables them)
-	 */
-	hard_irq_disable();
-
-	while (1) {
-		/* let's not take timer interrupts too often ... */
-		set_dec(0x7fffffff);
-
-		/* should always be true at this point */
-		if (cpu_has_feature(CPU_FTR_CAN_NAP))
-			power4_cpu_offline_powersave();
-		else {
-			HMT_low();
-			HMT_very_low();
-		}
-	}
-}
-#endif /* CONFIG_HOTPLUG_CPU */
-
 #endif /* CONFIG_PPC64 */
 
 define_machine(powermac) {
@@ -726,15 +681,4 @@
 	.pcibios_after_init	= pmac_pcibios_after_init,
 	.phys_mem_access_prot	= pci_phys_mem_access_prot,
 #endif
-#ifdef CONFIG_HOTPLUG_CPU
-#ifdef CONFIG_PPC64
-	.cpu_die		= pmac64_cpu_die,
-#endif
-#ifdef CONFIG_PPC32
-	.cpu_die		= pmac32_cpu_die,
-#endif
-#endif
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
-	.cpu_die		= generic_mach_cpu_die,
-#endif
 };
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/smp.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/smp.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/powermac/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/powermac/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -840,92 +840,151 @@
 
 	/* Setup openpic */
 	mpic_setup_this_cpu();
+}
 
-	if (cpu_nr == 0) {
 #ifdef CONFIG_PPC64
-		extern void g5_phy_disable_cpu1(void);
+#ifdef CONFIG_HOTPLUG_CPU
+static int smp_core99_cpu_notify(struct notifier_block *self,
+				 unsigned long action, void *hcpu)
+{
+	int rc;
 
-		/* Close i2c bus if it was used for tb sync */
+	switch(action) {
+	case CPU_UP_PREPARE:
+	case CPU_UP_PREPARE_FROZEN:
+		/* Open i2c bus if it was used for tb sync */
 		if (pmac_tb_clock_chip_host) {
-			pmac_i2c_close(pmac_tb_clock_chip_host);
-			pmac_tb_clock_chip_host	= NULL;
+			rc = pmac_i2c_open(pmac_tb_clock_chip_host, 1);
+			if (rc) {
+				pr_err("Failed to open i2c bus for time sync\n");
+				return notifier_from_errno(rc);
+			}
 		}
+		break;
+	case CPU_ONLINE:
+	case CPU_UP_CANCELED:
+		/* Close i2c bus if it was used for tb sync */
+		if (pmac_tb_clock_chip_host)
+			pmac_i2c_close(pmac_tb_clock_chip_host);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
 
-		/* If we didn't start the second CPU, we must take
-		 * it off the bus
-		 */
-		if (of_machine_is_compatible("MacRISC4") &&
-		    num_online_cpus() < 2)		
-			g5_phy_disable_cpu1();
-#endif /* CONFIG_PPC64 */
+static struct notifier_block __cpuinitdata smp_core99_cpu_nb = {
+	.notifier_call	= smp_core99_cpu_notify,
+};
+#endif /* CONFIG_HOTPLUG_CPU */
 
-		if (ppc_md.progress)
-			ppc_md.progress("core99_setup_cpu 0 done", 0x349);
+static void __init smp_core99_bringup_done(void)
+{
+	extern void g5_phy_disable_cpu1(void);
+
+	/* Close i2c bus if it was used for tb sync */
+	if (pmac_tb_clock_chip_host)
+		pmac_i2c_close(pmac_tb_clock_chip_host);
+
+	/* If we didn't start the second CPU, we must take
+	 * it off the bus.
+	 */
+	if (of_machine_is_compatible("MacRISC4") &&
+	    num_online_cpus() < 2) {
+		set_cpu_present(1, false);
+		g5_phy_disable_cpu1();
 	}
-}
+#ifdef CONFIG_HOTPLUG_CPU
+	register_cpu_notifier(&smp_core99_cpu_nb);
+#endif
 
+	if (ppc_md.progress)
+		ppc_md.progress("smp_core99_bringup_done", 0x349);
+}
+#endif /* CONFIG_PPC64 */
 
-#if defined(CONFIG_HOTPLUG_CPU) && defined(CONFIG_PPC32)
+#ifdef CONFIG_HOTPLUG_CPU
 
-int smp_core99_cpu_disable(void)
+static int smp_core99_cpu_disable(void)
 {
-	set_cpu_online(smp_processor_id(), false);
+	int rc = generic_cpu_disable();
+	if (rc)
+		return rc;
 
-	/* XXX reset cpu affinity here */
 	mpic_cpu_set_priority(0xf);
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
-	mb();
-	udelay(20);
-	asm volatile("mtdec %0" : : "r" (0x7fffffff));
+
 	return 0;
 }
 
-static int cpu_dead[NR_CPUS];
+#ifdef CONFIG_PPC32
 
-void pmac32_cpu_die(void)
+static void pmac_cpu_die(void)
 {
+	int cpu = smp_processor_id();
+
 	local_irq_disable();
-	cpu_dead[smp_processor_id()] = 1;
+	idle_task_exit();
+	pr_debug("CPU%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
+	smp_wmb();
 	mb();
 	low_cpu_die();
 }
 
-void smp_core99_cpu_die(unsigned int cpu)
+#else /* CONFIG_PPC32 */
+
+static void pmac_cpu_die(void)
 {
-	int timeout;
+	int cpu = smp_processor_id();
 
-	timeout = 1000;
-	while (!cpu_dead[cpu]) {
-		if (--timeout == 0) {
-			printk("CPU %u refused to die!\n", cpu);
-			break;
-		}
-		msleep(1);
+	local_irq_disable();
+	idle_task_exit();
+
+	/*
+	 * turn off as much as possible, we'll be
+	 * kicked out as this will only be invoked
+	 * on core99 platforms for now ...
+	 */
+
+	printk(KERN_INFO "CPU#%d offline\n", cpu);
+	generic_set_cpu_dead(cpu);
+	smp_wmb();
+
+	/*
+	 * Re-enable interrupts. The NAP code needs to enable them
+	 * anyways, do it now so we deal with the case where one already
+	 * happened while soft-disabled.
+	 * We shouldn't get any external interrupts, only decrementer, and the
+	 * decrementer handler is safe for use on offline CPUs
+	 */
+	local_irq_enable();
+
+	while (1) {
+		/* let's not take timer interrupts too often ... */
+		set_dec(0x7fffffff);
+
+		/* Enter NAP mode */
+		power4_idle();
 	}
-	cpu_dead[cpu] = 0;
 }
 
-#endif /* CONFIG_HOTPLUG_CPU && CONFIG_PP32 */
+#endif /* else CONFIG_PPC32 */
+#endif /* CONFIG_HOTPLUG_CPU */
 
 /* Core99 Macs (dual G4s and G5s) */
 struct smp_ops_t core99_smp_ops = {
 	.message_pass	= smp_mpic_message_pass,
 	.probe		= smp_core99_probe,
+#ifdef CONFIG_PPC64
+	.bringup_done	= smp_core99_bringup_done,
+#endif
 	.kick_cpu	= smp_core99_kick_cpu,
 	.setup_cpu	= smp_core99_setup_cpu,
 	.give_timebase	= smp_core99_give_timebase,
 	.take_timebase	= smp_core99_take_timebase,
 #if defined(CONFIG_HOTPLUG_CPU)
-# if defined(CONFIG_PPC32)
 	.cpu_disable	= smp_core99_cpu_disable,
-	.cpu_die	= smp_core99_cpu_die,
-# endif
-# if defined(CONFIG_PPC64)
-	.cpu_disable	= generic_cpu_disable,
 	.cpu_die	= generic_cpu_die,
-	/* intentionally do *NOT* assign cpu_enable,
-	 * the generic code will use kick_cpu then! */
-# endif
 #endif
 };
 
@@ -957,5 +1016,10 @@
 		smp_ops = &psurge_smp_ops;
 	}
 #endif /* CONFIG_PPC32 */
+
+#ifdef CONFIG_HOTPLUG_CPU
+	ppc_md.cpu_die = pmac_cpu_die;
+#endif
 }
 
+
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/ps3/interrupt.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/ps3/interrupt.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/ps3/interrupt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/ps3/interrupt.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,16 +99,16 @@
  * Sets ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
  */
 
-static void ps3_chip_mask(unsigned int virq)
+static void ps3_chip_mask(struct irq_data *d)
 {
-	struct ps3_private *pd = get_irq_chip_data(virq);
+	struct ps3_private *pd = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
-		pd->thread_id, virq);
+		pd->thread_id, d->irq);
 
 	local_irq_save(flags);
-	clear_bit(63 - virq, &pd->bmp.mask);
+	clear_bit(63 - d->irq, &pd->bmp.mask);
 	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
 	local_irq_restore(flags);
 }
@@ -120,16 +120,16 @@
  * Clears ps3_bmp.mask and calls lv1_did_update_interrupt_mask().
  */
 
-static void ps3_chip_unmask(unsigned int virq)
+static void ps3_chip_unmask(struct irq_data *d)
 {
-	struct ps3_private *pd = get_irq_chip_data(virq);
+	struct ps3_private *pd = irq_data_get_irq_chip_data(d);
 	unsigned long flags;
 
 	pr_debug("%s:%d: thread_id %llu, virq %d\n", __func__, __LINE__,
-		pd->thread_id, virq);
+		pd->thread_id, d->irq);
 
 	local_irq_save(flags);
-	set_bit(63 - virq, &pd->bmp.mask);
+	set_bit(63 - d->irq, &pd->bmp.mask);
 	lv1_did_update_interrupt_mask(pd->ppe_id, pd->thread_id);
 	local_irq_restore(flags);
 }
@@ -141,10 +141,10 @@
  * Calls lv1_end_of_interrupt_ext().
  */
 
-static void ps3_chip_eoi(unsigned int virq)
+static void ps3_chip_eoi(struct irq_data *d)
 {
-	const struct ps3_private *pd = get_irq_chip_data(virq);
-	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, virq);
+	const struct ps3_private *pd = irq_data_get_irq_chip_data(d);
+	lv1_end_of_interrupt_ext(pd->ppe_id, pd->thread_id, d->irq);
 }
 
 /**
@@ -153,9 +153,9 @@
 
 static struct irq_chip ps3_irq_chip = {
 	.name = "ps3",
-	.mask = ps3_chip_mask,
-	.unmask = ps3_chip_unmask,
-	.eoi = ps3_chip_eoi,
+	.irq_mask = ps3_chip_mask,
+	.irq_unmask = ps3_chip_unmask,
+	.irq_eoi = ps3_chip_eoi,
 };
 
 /**
@@ -194,7 +194,7 @@
 	pr_debug("%s:%d: outlet %lu => cpu %u, virq %u\n", __func__, __LINE__,
 		outlet, cpu, *virq);
 
-	result = set_irq_chip_data(*virq, pd);
+	result = irq_set_chip_data(*virq, pd);
 
 	if (result) {
 		pr_debug("%s:%d: set_irq_chip_data failed\n",
@@ -202,7 +202,7 @@
 		goto fail_set;
 	}
 
-	ps3_chip_mask(*virq);
+	ps3_chip_mask(irq_get_irq_data(*virq));
 
 	return result;
 
@@ -221,12 +221,12 @@
 
 static int ps3_virq_destroy(unsigned int virq)
 {
-	const struct ps3_private *pd = get_irq_chip_data(virq);
+	const struct ps3_private *pd = irq_get_chip_data(virq);
 
 	pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
 		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
-	set_irq_chip_data(virq, NULL);
+	irq_set_chip_data(virq, NULL);
 	irq_dispose_mapping(virq);
 
 	pr_debug("%s:%d <-\n", __func__, __LINE__);
@@ -256,7 +256,7 @@
 		goto fail_setup;
 	}
 
-	pd = get_irq_chip_data(*virq);
+	pd = irq_get_chip_data(*virq);
 
 	/* Binds outlet to cpu + virq. */
 
@@ -291,12 +291,12 @@
 int ps3_irq_plug_destroy(unsigned int virq)
 {
 	int result;
-	const struct ps3_private *pd = get_irq_chip_data(virq);
+	const struct ps3_private *pd = irq_get_chip_data(virq);
 
 	pr_debug("%s:%d: ppe_id %llu, thread_id %llu, virq %u\n", __func__,
 		__LINE__, pd->ppe_id, pd->thread_id, virq);
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	result = lv1_disconnect_irq_plug_ext(pd->ppe_id, pd->thread_id, virq);
 
@@ -357,7 +357,7 @@
 
 	pr_debug(" -> %s:%d virq %u\n", __func__, __LINE__, virq);
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	result = lv1_destruct_event_receive_port(virq_to_hw(virq));
 
@@ -492,7 +492,7 @@
 	int result;
 	unsigned long outlet = virq_to_hw(virq);
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	/*
 	 * lv1_destruct_io_irq_outlet() will destroy the IRQ plug,
@@ -553,7 +553,7 @@
 {
 	int result;
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 	result = lv1_deconfigure_virtual_uart_irq();
 
 	if (result) {
@@ -605,7 +605,7 @@
 {
 	int result;
 
-	ps3_chip_mask(virq);
+	ps3_chip_mask(irq_get_irq_data(virq));
 
 	result = ps3_irq_plug_destroy(virq);
 	BUG_ON(result);
@@ -661,7 +661,7 @@
 
 static void ps3_host_unmap(struct irq_host *h, unsigned int virq)
 {
-	set_irq_chip_data(virq, NULL);
+	irq_set_chip_data(virq, NULL);
 }
 
 static int ps3_host_map(struct irq_host *h, unsigned int virq,
@@ -670,7 +670,7 @@
 	pr_debug("%s:%d: hwirq %lu, virq %u\n", __func__, __LINE__, hwirq,
 		virq);
 
-	set_irq_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
+	irq_set_chip_and_handler(virq, &ps3_irq_chip, handle_fasteoi_irq);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/cmm.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/cmm.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/cmm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/cmm.c	2011-05-19 00:06:34.000000000 -0400
@@ -508,12 +508,7 @@
 	if (action == MEM_ISOLATE_COUNT)
 		ret = cmm_count_pages(arg);
 
-	if (ret)
-		ret = notifier_from_errno(ret);
-	else
-		ret = NOTIFY_OK;
-
-	return ret;
+	return notifier_from_errno(ret);
 }
 
 static struct notifier_block cmm_mem_isolate_nb = {
@@ -635,12 +630,7 @@
 		break;
 	}
 
-	if (ret)
-		ret = notifier_from_errno(ret);
-	else
-		ret = NOTIFY_OK;
-
-	return ret;
+	return notifier_from_errno(ret);
 }
 
 static struct notifier_block cmm_mem_nb = {
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/dlpar.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/dlpar.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/dlpar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/dlpar.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,7 +74,7 @@
 		return NULL;
 
 	/* The configure connector reported name does not contain a
-	 * preceeding '/', so we allocate a buffer large enough to
+	 * preceding '/', so we allocate a buffer large enough to
 	 * prepend this to the full_name.
 	 */
 	name = (char *)ccwa + ccwa->name_offset;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/eeh.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/eeh.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/eeh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/eeh.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
  *  with EEH.
  *
  *  Ideally, a PCI device driver, when suspecting that an isolation
- *  event has occured (e.g. by reading 0xff's), will then ask EEH
+ *  event has occurred (e.g. by reading 0xff's), will then ask EEH
  *  whether this is the case, and then take appropriate steps to
  *  reset the PCI slot, the PCI device, and then resume operations.
  *  However, until that day,  the checking is done here, with the
@@ -876,7 +876,7 @@
  *
  * Save the values of the device bars. Unlike the restore
  * routine, this routine is *not* recursive. This is because
- * PCI devices are added individuallly; but, for the restore,
+ * PCI devices are added individually; but, for the restore,
  * an entire slot is reset at a time.
  */
 static void eeh_save_bars(struct pci_dn *pdn)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/hotplug-cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -216,7 +216,7 @@
 		       cpu, pcpu, cpu_status);
 	}
 
-	/* Isolation and deallocation are definatly done by
+	/* Isolation and deallocation are definitely done by
 	 * drslot_chrp_cpu.  If they were not they would be
 	 * done here.  Change isolate state to Isolate and
 	 * change allocation-state to Unusable.
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/hotplug-memory.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,54 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/sparsemem.h>
 
+static unsigned long get_memblock_size(void)
+{
+	struct device_node *np;
+	unsigned int memblock_size = 0;
+
+	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
+	if (np) {
+		const unsigned long *size;
+
+		size = of_get_property(np, "ibm,lmb-size", NULL);
+		memblock_size = size ? *size : 0;
+
+		of_node_put(np);
+	} else {
+		unsigned int memzero_size = 0;
+		const unsigned int *regs;
+
+		np = of_find_node_by_path("/memory@0");
+		if (np) {
+			regs = of_get_property(np, "reg", NULL);
+			memzero_size = regs ? regs[3] : 0;
+			of_node_put(np);
+		}
+
+		if (memzero_size) {
+			/* We now know the size of memory@0, use this to find
+			 * the first memoryblock and get its size.
+			 */
+			char buf[64];
+
+			sprintf(buf, "/memory@%x", memzero_size);
+			np = of_find_node_by_path(buf);
+			if (np) {
+				regs = of_get_property(np, "reg", NULL);
+				memblock_size = regs ? regs[3] : 0;
+				of_node_put(np);
+			}
+		}
+	}
+
+	return memblock_size;
+}
+
+unsigned long memory_block_size_bytes(void)
+{
+	return get_memblock_size();
+}
+
 static int pseries_remove_memblock(unsigned long base, unsigned int memblock_size)
 {
 	unsigned long start, start_pfn;
@@ -127,30 +175,22 @@
 
 static int pseries_drconf_memory(unsigned long *base, unsigned int action)
 {
-	struct device_node *np;
-	const unsigned long *lmb_size;
+	unsigned long memblock_size;
 	int rc;
 
-	np = of_find_node_by_path("/ibm,dynamic-reconfiguration-memory");
-	if (!np)
-		return -EINVAL;
-
-	lmb_size = of_get_property(np, "ibm,lmb-size", NULL);
-	if (!lmb_size) {
-		of_node_put(np);
+	memblock_size = get_memblock_size();
+	if (!memblock_size)
 		return -EINVAL;
-	}
 
 	if (action == PSERIES_DRCONF_MEM_ADD) {
-		rc = memblock_add(*base, *lmb_size);
+		rc = memblock_add(*base, memblock_size);
 		rc = (rc < 0) ? -EINVAL : 0;
 	} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
-		rc = pseries_remove_memblock(*base, *lmb_size);
+		rc = pseries_remove_memblock(*base, memblock_size);
 	} else {
 		rc = -EINVAL;
 	}
 
-	of_node_put(np);
 	return rc;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/iommu.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/iommu.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/iommu.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/crash_dump.h>
+#include <linux/memory.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -45,6 +46,7 @@
 #include <asm/tce.h>
 #include <asm/ppc-pci.h>
 #include <asm/udbg.h>
+#include <asm/mmzone.h>
 
 #include "plpar_wrappers.h"
 
@@ -270,6 +272,152 @@
 	return tce_ret;
 }
 
+/* this is compatible with cells for the device tree property */
+struct dynamic_dma_window_prop {
+	__be32	liobn;		/* tce table number */
+	__be64	dma_base;	/* address hi,lo */
+	__be32	tce_shift;	/* ilog2(tce_page_size) */
+	__be32	window_shift;	/* ilog2(tce_window_size) */
+};
+
+struct direct_window {
+	struct device_node *device;
+	const struct dynamic_dma_window_prop *prop;
+	struct list_head list;
+};
+
+/* Dynamic DMA Window support */
+struct ddw_query_response {
+	u32 windows_available;
+	u32 largest_available_block;
+	u32 page_size;
+	u32 migration_capable;
+};
+
+struct ddw_create_response {
+	u32 liobn;
+	u32 addr_hi;
+	u32 addr_lo;
+};
+
+static LIST_HEAD(direct_window_list);
+/* prevents races between memory on/offline and window creation */
+static DEFINE_SPINLOCK(direct_window_list_lock);
+/* protects initializing window twice for same device */
+static DEFINE_MUTEX(direct_window_init_mutex);
+#define DIRECT64_PROPNAME "linux,direct64-ddr-window-info"
+
+static int tce_clearrange_multi_pSeriesLP(unsigned long start_pfn,
+					unsigned long num_pfn, const void *arg)
+{
+	const struct dynamic_dma_window_prop *maprange = arg;
+	int rc;
+	u64 tce_size, num_tce, dma_offset, next;
+	u32 tce_shift;
+	long limit;
+
+	tce_shift = be32_to_cpu(maprange->tce_shift);
+	tce_size = 1ULL << tce_shift;
+	next = start_pfn << PAGE_SHIFT;
+	num_tce = num_pfn << PAGE_SHIFT;
+
+	/* round back to the beginning of the tce page size */
+	num_tce += next & (tce_size - 1);
+	next &= ~(tce_size - 1);
+
+	/* covert to number of tces */
+	num_tce |= tce_size - 1;
+	num_tce >>= tce_shift;
+
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, num_tce, 512);
+		dma_offset = next + be64_to_cpu(maprange->dma_base);
+
+		rc = plpar_tce_stuff((u64)be32_to_cpu(maprange->liobn),
+					     dma_offset,
+					     0, limit);
+		num_tce -= limit;
+	} while (num_tce > 0 && !rc);
+
+	return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP(unsigned long start_pfn,
+					unsigned long num_pfn, const void *arg)
+{
+	const struct dynamic_dma_window_prop *maprange = arg;
+	u64 *tcep, tce_size, num_tce, dma_offset, next, proto_tce, liobn;
+	u32 tce_shift;
+	u64 rc = 0;
+	long l, limit;
+
+	local_irq_disable();	/* to protect tcep and the page behind it */
+	tcep = __get_cpu_var(tce_page);
+
+	if (!tcep) {
+		tcep = (u64 *)__get_free_page(GFP_ATOMIC);
+		if (!tcep) {
+			local_irq_enable();
+			return -ENOMEM;
+		}
+		__get_cpu_var(tce_page) = tcep;
+	}
+
+	proto_tce = TCE_PCI_READ | TCE_PCI_WRITE;
+
+	liobn = (u64)be32_to_cpu(maprange->liobn);
+	tce_shift = be32_to_cpu(maprange->tce_shift);
+	tce_size = 1ULL << tce_shift;
+	next = start_pfn << PAGE_SHIFT;
+	num_tce = num_pfn << PAGE_SHIFT;
+
+	/* round back to the beginning of the tce page size */
+	num_tce += next & (tce_size - 1);
+	next &= ~(tce_size - 1);
+
+	/* covert to number of tces */
+	num_tce |= tce_size - 1;
+	num_tce >>= tce_shift;
+
+	/* We can map max one pageful of TCEs at a time */
+	do {
+		/*
+		 * Set up the page with TCE data, looping through and setting
+		 * the values.
+		 */
+		limit = min_t(long, num_tce, 4096/TCE_ENTRY_SIZE);
+		dma_offset = next + be64_to_cpu(maprange->dma_base);
+
+		for (l = 0; l < limit; l++) {
+			tcep[l] = proto_tce | next;
+			next += tce_size;
+		}
+
+		rc = plpar_tce_put_indirect(liobn,
+					    dma_offset,
+					    (u64)virt_to_abs(tcep),
+					    limit);
+
+		num_tce -= limit;
+	} while (num_tce > 0 && !rc);
+
+	/* error cleanup: caller will clear whole range */
+
+	local_irq_enable();
+	return rc;
+}
+
+static int tce_setrange_multi_pSeriesLP_walk(unsigned long start_pfn,
+		unsigned long num_pfn, void *arg)
+{
+	return tce_setrange_multi_pSeriesLP(start_pfn, num_pfn, arg);
+}
+
+
 #ifdef CONFIG_PCI
 static void iommu_table_setparms(struct pci_controller *phb,
 				 struct device_node *dn,
@@ -495,6 +643,329 @@
 		       pci_name(dev));
 }
 
+static int __read_mostly disable_ddw;
+
+static int __init disable_ddw_setup(char *str)
+{
+	disable_ddw = 1;
+	printk(KERN_INFO "ppc iommu: disabling ddw.\n");
+
+	return 0;
+}
+
+early_param("disable_ddw", disable_ddw_setup);
+
+static void remove_ddw(struct device_node *np)
+{
+	struct dynamic_dma_window_prop *dwp;
+	struct property *win64;
+	const u32 *ddr_avail;
+	u64 liobn;
+	int len, ret;
+
+	ddr_avail = of_get_property(np, "ibm,ddw-applicable", &len);
+	win64 = of_find_property(np, DIRECT64_PROPNAME, NULL);
+	if (!win64 || !ddr_avail || len < 3 * sizeof(u32))
+		return;
+
+	dwp = win64->value;
+	liobn = (u64)be32_to_cpu(dwp->liobn);
+
+	/* clear the whole window, note the arg is in kernel pages */
+	ret = tce_clearrange_multi_pSeriesLP(0,
+		1ULL << (be32_to_cpu(dwp->window_shift) - PAGE_SHIFT), dwp);
+	if (ret)
+		pr_warning("%s failed to clear tces in window.\n",
+			 np->full_name);
+	else
+		pr_debug("%s successfully cleared tces in window.\n",
+			 np->full_name);
+
+	ret = rtas_call(ddr_avail[2], 1, 1, NULL, liobn);
+	if (ret)
+		pr_warning("%s: failed to remove direct window: rtas returned "
+			"%d to ibm,remove-pe-dma-window(%x) %llx\n",
+			np->full_name, ret, ddr_avail[2], liobn);
+	else
+		pr_debug("%s: successfully removed direct window: rtas returned "
+			"%d to ibm,remove-pe-dma-window(%x) %llx\n",
+			np->full_name, ret, ddr_avail[2], liobn);
+}
+
+
+static int dupe_ddw_if_already_created(struct pci_dev *dev, struct device_node *pdn)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	struct direct_window *window;
+	const struct dynamic_dma_window_prop *direct64;
+	u64 dma_addr = 0;
+
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	spin_lock(&direct_window_list_lock);
+	/* check if we already created a window and dupe that config if so */
+	list_for_each_entry(window, &direct_window_list, list) {
+		if (window->device == pdn) {
+			direct64 = window->prop;
+			dma_addr = direct64->dma_base;
+			break;
+		}
+	}
+	spin_unlock(&direct_window_list_lock);
+
+	return dma_addr;
+}
+
+static u64 dupe_ddw_if_kexec(struct pci_dev *dev, struct device_node *pdn)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	int len;
+	struct direct_window *window;
+	const struct dynamic_dma_window_prop *direct64;
+	u64 dma_addr = 0;
+
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	direct64 = of_get_property(pdn, DIRECT64_PROPNAME, &len);
+	if (direct64) {
+		window = kzalloc(sizeof(*window), GFP_KERNEL);
+		if (!window) {
+			remove_ddw(pdn);
+		} else {
+			window->device = pdn;
+			window->prop = direct64;
+			spin_lock(&direct_window_list_lock);
+			list_add(&window->list, &direct_window_list);
+			spin_unlock(&direct_window_list_lock);
+			dma_addr = direct64->dma_base;
+		}
+	}
+
+	return dma_addr;
+}
+
+static int query_ddw(struct pci_dev *dev, const u32 *ddr_avail,
+			struct ddw_query_response *query)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	u32 cfg_addr;
+	u64 buid;
+	int ret;
+
+	/*
+	 * Get the config address and phb buid of the PE window.
+	 * Rely on eeh to retrieve this for us.
+	 * Retrieve them from the pci device, not the node with the
+	 * dma-window property
+	 */
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	cfg_addr = pcidn->eeh_config_addr;
+	if (pcidn->eeh_pe_config_addr)
+		cfg_addr = pcidn->eeh_pe_config_addr;
+	buid = pcidn->phb->buid;
+	ret = rtas_call(ddr_avail[0], 3, 5, (u32 *)query,
+		  cfg_addr, BUID_HI(buid), BUID_LO(buid));
+	dev_info(&dev->dev, "ibm,query-pe-dma-windows(%x) %x %x %x"
+		" returned %d\n", ddr_avail[0], cfg_addr, BUID_HI(buid),
+		BUID_LO(buid), ret);
+	return ret;
+}
+
+static int create_ddw(struct pci_dev *dev, const u32 *ddr_avail,
+			struct ddw_create_response *create, int page_shift,
+			int window_shift)
+{
+	struct device_node *dn;
+	struct pci_dn *pcidn;
+	u32 cfg_addr;
+	u64 buid;
+	int ret;
+
+	/*
+	 * Get the config address and phb buid of the PE window.
+	 * Rely on eeh to retrieve this for us.
+	 * Retrieve them from the pci device, not the node with the
+	 * dma-window property
+	 */
+	dn = pci_device_to_OF_node(dev);
+	pcidn = PCI_DN(dn);
+	cfg_addr = pcidn->eeh_config_addr;
+	if (pcidn->eeh_pe_config_addr)
+		cfg_addr = pcidn->eeh_pe_config_addr;
+	buid = pcidn->phb->buid;
+
+	do {
+		/* extra outputs are LIOBN and dma-addr (hi, lo) */
+		ret = rtas_call(ddr_avail[1], 5, 4, (u32 *)create, cfg_addr,
+				BUID_HI(buid), BUID_LO(buid), page_shift, window_shift);
+	} while (rtas_busy_delay(ret));
+	dev_info(&dev->dev,
+		"ibm,create-pe-dma-window(%x) %x %x %x %x %x returned %d "
+		"(liobn = 0x%x starting addr = %x %x)\n", ddr_avail[1],
+		 cfg_addr, BUID_HI(buid), BUID_LO(buid), page_shift,
+		 window_shift, ret, create->liobn, create->addr_hi, create->addr_lo);
+
+	return ret;
+}
+
+/*
+ * If the PE supports dynamic dma windows, and there is space for a table
+ * that can map all pages in a linear offset, then setup such a table,
+ * and record the dma-offset in the struct device.
+ *
+ * dev: the pci device we are checking
+ * pdn: the parent pe node with the ibm,dma_window property
+ * Future: also check if we can remap the base window for our base page size
+ *
+ * returns the dma offset for use by dma_set_mask
+ */
+static u64 enable_ddw(struct pci_dev *dev, struct device_node *pdn)
+{
+	int len, ret;
+	struct ddw_query_response query;
+	struct ddw_create_response create;
+	int page_shift;
+	u64 dma_addr, max_addr;
+	struct device_node *dn;
+	const u32 *uninitialized_var(ddr_avail);
+	struct direct_window *window;
+	struct property *uninitialized_var(win64);
+	struct dynamic_dma_window_prop *ddwprop;
+
+	mutex_lock(&direct_window_init_mutex);
+
+	dma_addr = dupe_ddw_if_already_created(dev, pdn);
+	if (dma_addr != 0)
+		goto out_unlock;
+
+	dma_addr = dupe_ddw_if_kexec(dev, pdn);
+	if (dma_addr != 0)
+		goto out_unlock;
+
+	/*
+	 * the ibm,ddw-applicable property holds the tokens for:
+	 * ibm,query-pe-dma-window
+	 * ibm,create-pe-dma-window
+	 * ibm,remove-pe-dma-window
+	 * for the given node in that order.
+	 * the property is actually in the parent, not the PE
+	 */
+	ddr_avail = of_get_property(pdn, "ibm,ddw-applicable", &len);
+	if (!ddr_avail || len < 3 * sizeof(u32))
+		goto out_unlock;
+
+       /*
+	 * Query if there is a second window of size to map the
+	 * whole partition.  Query returns number of windows, largest
+	 * block assigned to PE (partition endpoint), and two bitmasks
+	 * of page sizes: supported and supported for migrate-dma.
+	 */
+	dn = pci_device_to_OF_node(dev);
+	ret = query_ddw(dev, ddr_avail, &query);
+	if (ret != 0)
+		goto out_unlock;
+
+	if (query.windows_available == 0) {
+		/*
+		 * no additional windows are available for this device.
+		 * We might be able to reallocate the existing window,
+		 * trading in for a larger page size.
+		 */
+		dev_dbg(&dev->dev, "no free dynamic windows");
+		goto out_unlock;
+	}
+	if (query.page_size & 4) {
+		page_shift = 24; /* 16MB */
+	} else if (query.page_size & 2) {
+		page_shift = 16; /* 64kB */
+	} else if (query.page_size & 1) {
+		page_shift = 12; /* 4kB */
+	} else {
+		dev_dbg(&dev->dev, "no supported direct page size in mask %x",
+			  query.page_size);
+		goto out_unlock;
+	}
+	/* verify the window * number of ptes will map the partition */
+	/* check largest block * page size > max memory hotplug addr */
+	max_addr = memory_hotplug_max();
+	if (query.largest_available_block < (max_addr >> page_shift)) {
+		dev_dbg(&dev->dev, "can't map partiton max 0x%llx with %u "
+			  "%llu-sized pages\n", max_addr,  query.largest_available_block,
+			  1ULL << page_shift);
+		goto out_unlock;
+	}
+	len = order_base_2(max_addr);
+	win64 = kzalloc(sizeof(struct property), GFP_KERNEL);
+	if (!win64) {
+		dev_info(&dev->dev,
+			"couldn't allocate property for 64bit dma window\n");
+		goto out_unlock;
+	}
+	win64->name = kstrdup(DIRECT64_PROPNAME, GFP_KERNEL);
+	win64->value = ddwprop = kmalloc(sizeof(*ddwprop), GFP_KERNEL);
+	if (!win64->name || !win64->value) {
+		dev_info(&dev->dev,
+			"couldn't allocate property name and value\n");
+		goto out_free_prop;
+	}
+
+	ret = create_ddw(dev, ddr_avail, &create, page_shift, len);
+	if (ret != 0)
+		goto out_free_prop;
+
+	ddwprop->liobn = cpu_to_be32(create.liobn);
+	ddwprop->dma_base = cpu_to_be64(of_read_number(&create.addr_hi, 2));
+	ddwprop->tce_shift = cpu_to_be32(page_shift);
+	ddwprop->window_shift = cpu_to_be32(len);
+
+	dev_dbg(&dev->dev, "created tce table LIOBN 0x%x for %s\n",
+		  create.liobn, dn->full_name);
+
+	window = kzalloc(sizeof(*window), GFP_KERNEL);
+	if (!window)
+		goto out_clear_window;
+
+	ret = walk_system_ram_range(0, memblock_end_of_DRAM() >> PAGE_SHIFT,
+			win64->value, tce_setrange_multi_pSeriesLP_walk);
+	if (ret) {
+		dev_info(&dev->dev, "failed to map direct window for %s: %d\n",
+			 dn->full_name, ret);
+		goto out_clear_window;
+	}
+
+	ret = prom_add_property(pdn, win64);
+	if (ret) {
+		dev_err(&dev->dev, "unable to add dma window property for %s: %d",
+			 pdn->full_name, ret);
+		goto out_clear_window;
+	}
+
+	window->device = pdn;
+	window->prop = ddwprop;
+	spin_lock(&direct_window_list_lock);
+	list_add(&window->list, &direct_window_list);
+	spin_unlock(&direct_window_list_lock);
+
+	dma_addr = of_read_number(&create.addr_hi, 2);
+	goto out_unlock;
+
+out_clear_window:
+	remove_ddw(pdn);
+
+out_free_prop:
+	kfree(win64->name);
+	kfree(win64->value);
+	kfree(win64);
+
+out_unlock:
+	mutex_unlock(&direct_window_init_mutex);
+	return dma_addr;
+}
+
 static void pci_dma_dev_setup_pSeriesLP(struct pci_dev *dev)
 {
 	struct device_node *pdn, *dn;
@@ -505,7 +976,7 @@
 	pr_debug("pci_dma_dev_setup_pSeriesLP: %s\n", pci_name(dev));
 
 	/* dev setup for LPAR is a little tricky, since the device tree might
-	 * contain the dma-window properties per-device and not neccesarily
+	 * contain the dma-window properties per-device and not necessarily
 	 * for the bus. So we need to search upwards in the tree until we
 	 * either hit a dma-window property, OR find a parent with a table
 	 * already allocated.
@@ -541,23 +1012,137 @@
 
 	set_iommu_table_base(&dev->dev, pci->iommu_table);
 }
+
+static int dma_set_mask_pSeriesLP(struct device *dev, u64 dma_mask)
+{
+	bool ddw_enabled = false;
+	struct device_node *pdn, *dn;
+	struct pci_dev *pdev;
+	const void *dma_window = NULL;
+	u64 dma_offset;
+
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	/* only attempt to use a new window if 64-bit DMA is requested */
+	if (!disable_ddw && dma_mask == DMA_BIT_MASK(64)) {
+		pdev = to_pci_dev(dev);
+
+		dn = pci_device_to_OF_node(pdev);
+		dev_dbg(dev, "node is %s\n", dn->full_name);
+
+		/*
+		 * the device tree might contain the dma-window properties
+		 * per-device and not necessarily for the bus. So we need to
+		 * search upwards in the tree until we either hit a dma-window
+		 * property, OR find a parent with a table already allocated.
+		 */
+		for (pdn = dn; pdn && PCI_DN(pdn) && !PCI_DN(pdn)->iommu_table;
+				pdn = pdn->parent) {
+			dma_window = of_get_property(pdn, "ibm,dma-window", NULL);
+			if (dma_window)
+				break;
+		}
+		if (pdn && PCI_DN(pdn)) {
+			dma_offset = enable_ddw(pdev, pdn);
+			if (dma_offset != 0) {
+				dev_info(dev, "Using 64-bit direct DMA at offset %llx\n", dma_offset);
+				set_dma_offset(dev, dma_offset);
+				set_dma_ops(dev, &dma_direct_ops);
+				ddw_enabled = true;
+			}
+		}
+	}
+
+	/* fall-through to iommu ops */
+	if (!ddw_enabled) {
+		dev_info(dev, "Using 32-bit DMA via iommu\n");
+		set_dma_ops(dev, &dma_iommu_ops);
+	}
+
+	*dev->dma_mask = dma_mask;
+	return 0;
+}
+
 #else  /* CONFIG_PCI */
 #define pci_dma_bus_setup_pSeries	NULL
 #define pci_dma_dev_setup_pSeries	NULL
 #define pci_dma_bus_setup_pSeriesLP	NULL
 #define pci_dma_dev_setup_pSeriesLP	NULL
+#define dma_set_mask_pSeriesLP		NULL
 #endif /* !CONFIG_PCI */
 
+static int iommu_mem_notifier(struct notifier_block *nb, unsigned long action,
+		void *data)
+{
+	struct direct_window *window;
+	struct memory_notify *arg = data;
+	int ret = 0;
+
+	switch (action) {
+	case MEM_GOING_ONLINE:
+		spin_lock(&direct_window_list_lock);
+		list_for_each_entry(window, &direct_window_list, list) {
+			ret |= tce_setrange_multi_pSeriesLP(arg->start_pfn,
+					arg->nr_pages, window->prop);
+			/* XXX log error */
+		}
+		spin_unlock(&direct_window_list_lock);
+		break;
+	case MEM_CANCEL_ONLINE:
+	case MEM_OFFLINE:
+		spin_lock(&direct_window_list_lock);
+		list_for_each_entry(window, &direct_window_list, list) {
+			ret |= tce_clearrange_multi_pSeriesLP(arg->start_pfn,
+					arg->nr_pages, window->prop);
+			/* XXX log error */
+		}
+		spin_unlock(&direct_window_list_lock);
+		break;
+	default:
+		break;
+	}
+	if (ret && action != MEM_CANCEL_ONLINE)
+		return NOTIFY_BAD;
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block iommu_mem_nb = {
+	.notifier_call = iommu_mem_notifier,
+};
+
 static int iommu_reconfig_notifier(struct notifier_block *nb, unsigned long action, void *node)
 {
 	int err = NOTIFY_OK;
 	struct device_node *np = node;
 	struct pci_dn *pci = PCI_DN(np);
+	struct direct_window *window;
 
 	switch (action) {
 	case PSERIES_RECONFIG_REMOVE:
 		if (pci && pci->iommu_table)
 			iommu_free_table(pci->iommu_table, np->full_name);
+
+		spin_lock(&direct_window_list_lock);
+		list_for_each_entry(window, &direct_window_list, list) {
+			if (window->device == np) {
+				list_del(&window->list);
+				kfree(window);
+				break;
+			}
+		}
+		spin_unlock(&direct_window_list_lock);
+
+		/*
+		 * Because the notifier runs after isolation of the
+		 * slot, we are guaranteed any DMA window has already
+		 * been revoked and the TCEs have been marked invalid,
+		 * so we don't need a call to remove_ddw(np). However,
+		 * if an additional notifier action is added before the
+		 * isolate call, we should update this code for
+		 * completeness with such a call.
+		 */
 		break;
 	default:
 		err = NOTIFY_DONE;
@@ -587,6 +1172,7 @@
 		ppc_md.tce_get   = tce_get_pSeriesLP;
 		ppc_md.pci_dma_bus_setup = pci_dma_bus_setup_pSeriesLP;
 		ppc_md.pci_dma_dev_setup = pci_dma_dev_setup_pSeriesLP;
+		ppc_md.dma_set_mask = dma_set_mask_pSeriesLP;
 	} else {
 		ppc_md.tce_build = tce_build_pSeries;
 		ppc_md.tce_free  = tce_free_pSeries;
@@ -597,6 +1183,7 @@
 
 
 	pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
+	register_memory_notifier(&iommu_mem_nb);
 
 	set_pci_dma_ops(&dma_iommu_ops);
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/msi.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/msi.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,8 +93,18 @@
 	if (!pdn)
 		return;
 
-	if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0)
-		pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
+	/*
+	 * disabling MSI with the explicit interface also disables MSI-X
+	 */
+	if (rtas_change_msi(pdn, RTAS_CHANGE_MSI_FN, 0) != 0) {
+		/* 
+		 * may have failed because explicit interface is not
+		 * present
+		 */
+		if (rtas_change_msi(pdn, RTAS_CHANGE_FN, 0) != 0) {
+			pr_debug("rtas_msi: Setting MSIs to 0 failed!\n");
+		}
+	}
 }
 
 static int rtas_query_irq_number(struct pci_dn *pdn, int offset)
@@ -127,7 +137,7 @@
 		if (entry->irq == NO_IRQ)
 			continue;
 
-		set_irq_msi(entry->irq, NULL);
+		irq_set_msi_desc(entry->irq, NULL);
 		irq_dispose_mapping(entry->irq);
 	}
 
@@ -427,7 +437,7 @@
 		}
 
 		dev_dbg(&pdev->dev, "rtas_msi: allocated virq %d\n", virq);
-		set_irq_msi(virq, entry);
+		irq_set_msi_desc(virq, entry);
 
 		/* Read config space back so we can restore after reset */
 		read_msi_msg(virq, &msg);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/nvram.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/nvram.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/nvram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/nvram.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,8 @@
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/kmsg_dump.h>
 #include <asm/uaccess.h>
 #include <asm/nvram.h>
 #include <asm/rtas.h>
@@ -30,17 +32,54 @@
 static char nvram_buf[NVRW_CNT];	/* assume this is in the first 4GB */
 static DEFINE_SPINLOCK(nvram_lock);
 
-static long nvram_error_log_index = -1;
-static long nvram_error_log_size = 0;
-
 struct err_log_info {
 	int error_type;
 	unsigned int seq_num;
 };
-#define NVRAM_MAX_REQ		2079
-#define NVRAM_MIN_REQ		1055
 
-#define NVRAM_LOG_PART_NAME	"ibm,rtas-log"
+struct nvram_os_partition {
+	const char *name;
+	int req_size;	/* desired size, in bytes */
+	int min_size;	/* minimum acceptable size (0 means req_size) */
+	long size;	/* size of data portion (excluding err_log_info) */
+	long index;	/* offset of data portion of partition */
+};
+
+static struct nvram_os_partition rtas_log_partition = {
+	.name = "ibm,rtas-log",
+	.req_size = 2079,
+	.min_size = 1055,
+	.index = -1
+};
+
+static struct nvram_os_partition oops_log_partition = {
+	.name = "lnx,oops-log",
+	.req_size = 4000,
+	.min_size = 2000,
+	.index = -1
+};
+
+static const char *pseries_nvram_os_partitions[] = {
+	"ibm,rtas-log",
+	"lnx,oops-log",
+	NULL
+};
+
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason,
+		const char *old_msgs, unsigned long old_len,
+		const char *new_msgs, unsigned long new_len);
+
+static struct kmsg_dumper nvram_kmsg_dumper = {
+	.dump = oops_to_nvram
+};
+
+/* See clobbering_unread_rtas_event() */
+#define NVRAM_RTAS_READ_TIMEOUT 5		/* seconds */
+static unsigned long last_unread_rtas_event;	/* timestamp */
+
+/* We preallocate oops_buf during init to avoid kmalloc during oops/panic. */
+static char *oops_buf;
 
 static ssize_t pSeries_nvram_read(char *buf, size_t count, loff_t *index)
 {
@@ -134,7 +173,7 @@
 }
 
 
-/* nvram_write_error_log
+/* nvram_write_os_partition, nvram_write_error_log
  *
  * We need to buffer the error logs into nvram to ensure that we have
  * the failure information to decode.  If we have a severe error there
@@ -156,48 +195,58 @@
  * The 'data' section would look like (in bytes):
  * +--------------+------------+-----------------------------------+
  * | event_logged | sequence # | error log                         |
- * |0            3|4          7|8            nvram_error_log_size-1|
+ * |0            3|4          7|8                  error_log_size-1|
  * +--------------+------------+-----------------------------------+
  *
  * event_logged: 0 if event has not been logged to syslog, 1 if it has
  * sequence #: The unique sequence # for each event. (until it wraps)
  * error log: The error log from event_scan
  */
-int nvram_write_error_log(char * buff, int length,
-                          unsigned int err_type, unsigned int error_log_cnt)
+int nvram_write_os_partition(struct nvram_os_partition *part, char * buff,
+		int length, unsigned int err_type, unsigned int error_log_cnt)
 {
 	int rc;
 	loff_t tmp_index;
 	struct err_log_info info;
 	
-	if (nvram_error_log_index == -1) {
+	if (part->index == -1) {
 		return -ESPIPE;
 	}
 
-	if (length > nvram_error_log_size) {
-		length = nvram_error_log_size;
+	if (length > part->size) {
+		length = part->size;
 	}
 
 	info.error_type = err_type;
 	info.seq_num = error_log_cnt;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = part->index;
 
 	rc = ppc_md.nvram_write((char *)&info, sizeof(struct err_log_info), &tmp_index);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		pr_err("%s: Failed nvram_write (%d)\n", __FUNCTION__, rc);
 		return rc;
 	}
 
 	rc = ppc_md.nvram_write(buff, length, &tmp_index);
 	if (rc <= 0) {
-		printk(KERN_ERR "nvram_write_error_log: Failed nvram_write (%d)\n", rc);
+		pr_err("%s: Failed nvram_write (%d)\n", __FUNCTION__, rc);
 		return rc;
 	}
 	
 	return 0;
 }
 
+int nvram_write_error_log(char * buff, int length,
+                          unsigned int err_type, unsigned int error_log_cnt)
+{
+	int rc = nvram_write_os_partition(&rtas_log_partition, buff, length,
+						err_type, error_log_cnt);
+	if (!rc)
+		last_unread_rtas_event = get_seconds();
+	return rc;
+}
+
 /* nvram_read_error_log
  *
  * Reads nvram for error log for at most 'length'
@@ -209,13 +258,13 @@
 	loff_t tmp_index;
 	struct err_log_info info;
 	
-	if (nvram_error_log_index == -1)
+	if (rtas_log_partition.index == -1)
 		return -1;
 
-	if (length > nvram_error_log_size)
-		length = nvram_error_log_size;
+	if (length > rtas_log_partition.size)
+		length = rtas_log_partition.size;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = rtas_log_partition.index;
 
 	rc = ppc_md.nvram_read((char *)&info, sizeof(struct err_log_info), &tmp_index);
 	if (rc <= 0) {
@@ -244,37 +293,40 @@
 	int clear_word = ERR_FLAG_ALREADY_LOGGED;
 	int rc;
 
-	if (nvram_error_log_index == -1)
+	if (rtas_log_partition.index == -1)
 		return -1;
 
-	tmp_index = nvram_error_log_index;
+	tmp_index = rtas_log_partition.index;
 	
 	rc = ppc_md.nvram_write((char *)&clear_word, sizeof(int), &tmp_index);
 	if (rc <= 0) {
 		printk(KERN_ERR "nvram_clear_error_log: Failed nvram_write (%d)\n", rc);
 		return rc;
 	}
+	last_unread_rtas_event = 0;
 
 	return 0;
 }
 
-/* pseries_nvram_init_log_partition
+/* pseries_nvram_init_os_partition
  *
- * This will setup the partition we need for buffering the
- * error logs and cleanup partitions if needed.
+ * This sets up a partition with an "OS" signature.
  *
  * The general strategy is the following:
- * 1.) If there is log partition large enough then use it.
- * 2.) If there is none large enough, search
- * for a free partition that is large enough.
- * 3.) If there is not a free partition large enough remove 
- * _all_ OS partitions and consolidate the space.
- * 4.) Will first try getting a chunk that will satisfy the maximum
- * error log size (NVRAM_MAX_REQ).
- * 5.) If the max chunk cannot be allocated then try finding a chunk
- * that will satisfy the minum needed (NVRAM_MIN_REQ).
+ * 1.) If a partition with the indicated name already exists...
+ *	- If it's large enough, use it.
+ *	- Otherwise, recycle it and keep going.
+ * 2.) Search for a free partition that is large enough.
+ * 3.) If there's not a free partition large enough, recycle any obsolete
+ * OS partitions and try again.
+ * 4.) Will first try getting a chunk that will satisfy the requested size.
+ * 5.) If a chunk of the requested size cannot be allocated, then try finding
+ * a chunk that will satisfy the minum needed.
+ *
+ * Returns 0 on success, else -1.
  */
-static int __init pseries_nvram_init_log_partition(void)
+static int __init pseries_nvram_init_os_partition(struct nvram_os_partition
+									*part)
 {
 	loff_t p;
 	int size;
@@ -282,47 +334,76 @@
 	/* Scan nvram for partitions */
 	nvram_scan_partitions();
 
-	/* Lookg for ours */
-	p = nvram_find_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS, &size);
+	/* Look for ours */
+	p = nvram_find_partition(part->name, NVRAM_SIG_OS, &size);
 
 	/* Found one but too small, remove it */
-	if (p && size < NVRAM_MIN_REQ) {
-		pr_info("nvram: Found too small "NVRAM_LOG_PART_NAME" partition"
-			",removing it...");
-		nvram_remove_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS);
+	if (p && size < part->min_size) {
+		pr_info("nvram: Found too small %s partition,"
+					" removing it...\n", part->name);
+		nvram_remove_partition(part->name, NVRAM_SIG_OS, NULL);
 		p = 0;
 	}
 
 	/* Create one if we didn't find */
 	if (!p) {
-		p = nvram_create_partition(NVRAM_LOG_PART_NAME, NVRAM_SIG_OS,
-					   NVRAM_MAX_REQ, NVRAM_MIN_REQ);
-		/* No room for it, try to get rid of any OS partition
-		 * and try again
-		 */
+		p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+					part->req_size, part->min_size);
 		if (p == -ENOSPC) {
-			pr_info("nvram: No room to create "NVRAM_LOG_PART_NAME
-				" partition, deleting all OS partitions...");
-			nvram_remove_partition(NULL, NVRAM_SIG_OS);
-			p = nvram_create_partition(NVRAM_LOG_PART_NAME,
-						   NVRAM_SIG_OS, NVRAM_MAX_REQ,
-						   NVRAM_MIN_REQ);
+			pr_info("nvram: No room to create %s partition, "
+				"deleting any obsolete OS partitions...\n",
+				part->name);
+			nvram_remove_partition(NULL, NVRAM_SIG_OS,
+						pseries_nvram_os_partitions);
+			p = nvram_create_partition(part->name, NVRAM_SIG_OS,
+					part->req_size, part->min_size);
 		}
 	}
 
 	if (p <= 0) {
-		pr_err("nvram: Failed to find or create "NVRAM_LOG_PART_NAME
-		       " partition, err %d\n", (int)p);
-		return 0;
+		pr_err("nvram: Failed to find or create %s"
+		       " partition, err %d\n", part->name, (int)p);
+		return -1;
 	}
 
-	nvram_error_log_index = p;
-	nvram_error_log_size = nvram_get_partition_size(p) -
-		sizeof(struct err_log_info);
+	part->index = p;
+	part->size = nvram_get_partition_size(p) - sizeof(struct err_log_info);
 	
 	return 0;
 }
-machine_arch_initcall(pseries, pseries_nvram_init_log_partition);
+
+static void __init nvram_init_oops_partition(int rtas_partition_exists)
+{
+	int rc;
+
+	rc = pseries_nvram_init_os_partition(&oops_log_partition);
+	if (rc != 0) {
+		if (!rtas_partition_exists)
+			return;
+		pr_notice("nvram: Using %s partition to log both"
+			" RTAS errors and oops/panic reports\n",
+			rtas_log_partition.name);
+		memcpy(&oops_log_partition, &rtas_log_partition,
+						sizeof(rtas_log_partition));
+	}
+	oops_buf = kmalloc(oops_log_partition.size, GFP_KERNEL);
+	rc = kmsg_dump_register(&nvram_kmsg_dumper);
+	if (rc != 0) {
+		pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
+		kfree(oops_buf);
+		return;
+	}
+}
+
+static int __init pseries_nvram_init_log_partitions(void)
+{
+	int rc;
+
+	rc = pseries_nvram_init_os_partition(&rtas_log_partition);
+	nvram_init_oops_partition(rc == 0);
+	return 0;
+}
+machine_arch_initcall(pseries, pseries_nvram_init_log_partitions);
 
 int __init pSeries_nvram_init(void)
 {
@@ -353,3 +434,83 @@
 
 	return 0;
 }
+
+/*
+ * Try to capture the last capture_len bytes of the printk buffer.  Return
+ * the amount actually captured.
+ */
+static size_t capture_last_msgs(const char *old_msgs, size_t old_len,
+				const char *new_msgs, size_t new_len,
+				char *captured, size_t capture_len)
+{
+	if (new_len >= capture_len) {
+		memcpy(captured, new_msgs + (new_len - capture_len),
+								capture_len);
+		return capture_len;
+	} else {
+		/* Grab the end of old_msgs. */
+		size_t old_tail_len = min(old_len, capture_len - new_len);
+		memcpy(captured, old_msgs + (old_len - old_tail_len),
+								old_tail_len);
+		memcpy(captured + old_tail_len, new_msgs, new_len);
+		return old_tail_len + new_len;
+	}
+}
+
+/*
+ * Are we using the ibm,rtas-log for oops/panic reports?  And if so,
+ * would logging this oops/panic overwrite an RTAS event that rtas_errd
+ * hasn't had a chance to read and process?  Return 1 if so, else 0.
+ *
+ * We assume that if rtas_errd hasn't read the RTAS event in
+ * NVRAM_RTAS_READ_TIMEOUT seconds, it's probably not going to.
+ */
+static int clobbering_unread_rtas_event(void)
+{
+	return (oops_log_partition.index == rtas_log_partition.index
+		&& last_unread_rtas_event
+		&& get_seconds() - last_unread_rtas_event <=
+						NVRAM_RTAS_READ_TIMEOUT);
+}
+
+/* our kmsg_dump callback */
+static void oops_to_nvram(struct kmsg_dumper *dumper,
+		enum kmsg_dump_reason reason,
+		const char *old_msgs, unsigned long old_len,
+		const char *new_msgs, unsigned long new_len)
+{
+	static unsigned int oops_count = 0;
+	static bool panicking = false;
+	size_t text_len;
+
+	switch (reason) {
+	case KMSG_DUMP_RESTART:
+	case KMSG_DUMP_HALT:
+	case KMSG_DUMP_POWEROFF:
+		/* These are almost always orderly shutdowns. */
+		return;
+	case KMSG_DUMP_OOPS:
+	case KMSG_DUMP_KEXEC:
+		break;
+	case KMSG_DUMP_PANIC:
+		panicking = true;
+		break;
+	case KMSG_DUMP_EMERG:
+		if (panicking)
+			/* Panic report already captured. */
+			return;
+		break;
+	default:
+		pr_err("%s: ignoring unrecognized KMSG_DUMP_* reason %d\n",
+						__FUNCTION__, (int) reason);
+		return;
+	}
+
+	if (clobbering_unread_rtas_event())
+		return;
+
+	text_len = capture_last_msgs(old_msgs, old_len, new_msgs, new_len,
+					oops_buf, oops_log_partition.size);
+	(void) nvram_write_os_partition(&oops_log_partition, oops_buf,
+		(int) text_len, ERR_TYPE_KERNEL_PANIC, ++oops_count);
+}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/offline_states.h linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/offline_states.h
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/offline_states.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/offline_states.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,4 @@
 #endif
 
 extern enum cpu_state_vals get_preferred_offline_state(int cpu);
-extern int start_secondary(void);
-extern void start_secondary_resume(void);
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/pci_dlpar.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
 	if (dn->child)
 		eeh_add_device_tree_early(dn);
 
-	pcibios_scan_phb(phb, dn);
+	pcibios_scan_phb(phb);
 	pcibios_finish_adding_to_bus(phb->bus);
 
 	return phb;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/setup.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/setup.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -114,10 +114,13 @@
 
 static void pseries_8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq = i8259_irq();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
 
 static void __init pseries_setup_i8259_cascade(void)
@@ -166,7 +169,7 @@
 		printk(KERN_DEBUG "pic: PCI 8259 intack at 0x%016lx\n", intack);
 	i8259_init(found, intack);
 	of_node_put(found);
-	set_irq_chained_handler(cascade, pseries_8259_cascade);
+	irq_set_chained_handler(cascade, pseries_8259_cascade);
 }
 
 static void __init pseries_mpic_init_IRQ(void)
@@ -284,14 +287,22 @@
 	int cpu, ret;
 	struct paca_struct *pp;
 	struct dtl_entry *dtl;
+	struct kmem_cache *dtl_cache;
 
 	if (!firmware_has_feature(FW_FEATURE_SPLPAR))
 		return 0;
 
+	dtl_cache = kmem_cache_create("dtl", DISPATCH_LOG_BYTES,
+						DISPATCH_LOG_BYTES, 0, NULL);
+	if (!dtl_cache) {
+		pr_warn("Failed to create dispatch trace log buffer cache\n");
+		pr_warn("Stolen time statistics will be unreliable\n");
+		return 0;
+	}
+
 	for_each_possible_cpu(cpu) {
 		pp = &paca[cpu];
-		dtl = kmalloc_node(DISPATCH_LOG_BYTES, GFP_KERNEL,
-				   cpu_to_node(cpu));
+		dtl = kmem_cache_alloc(dtl_cache, GFP_KERNEL);
 		if (!dtl) {
 			pr_warn("Failed to allocate dispatch trace log for cpu %d\n",
 				cpu);
@@ -375,7 +386,7 @@
 
 	return 0;
 }
-arch_initcall(pSeries_init_panel);
+machine_arch_initcall(pseries, pSeries_init_panel);
 
 static int pseries_set_dabr(unsigned long dabr)
 {
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/smp.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/smp.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,8 +64,8 @@
 	int qcss_tok = rtas_token("query-cpu-stopped-state");
 
 	if (qcss_tok == RTAS_UNKNOWN_SERVICE) {
-		printk(KERN_INFO "Firmware doesn't support "
-				"query-cpu-stopped-state\n");
+		printk_once(KERN_INFO
+			"Firmware doesn't support query-cpu-stopped-state\n");
 		return QCSS_HARDWARE_ERROR;
 	}
 
@@ -112,10 +112,10 @@
 
 	/* Fixup atomic count: it exited inside IRQ handler. */
 	task_thread_info(paca[lcpu].__current)->preempt_count	= 0;
-
+#ifdef CONFIG_HOTPLUG_CPU
 	if (get_cpu_current_state(lcpu) == CPU_STATE_INACTIVE)
 		goto out;
-
+#endif
 	/* 
 	 * If the RTAS start-cpu token does not exist then presume the
 	 * cpu is already spinning.
@@ -130,7 +130,9 @@
 		return 0;
 	}
 
+#ifdef CONFIG_HOTPLUG_CPU
 out:
+#endif
 	return 1;
 }
 
@@ -144,16 +146,15 @@
 		vpa_init(cpu);
 
 	cpumask_clear_cpu(cpu, of_spin_mask);
+#ifdef CONFIG_HOTPLUG_CPU
 	set_cpu_current_state(cpu, CPU_STATE_ONLINE);
 	set_default_offline_state(cpu);
-
+#endif
 }
 #endif /* CONFIG_XICS */
 
 static void __devinit smp_pSeries_kick_cpu(int nr)
 {
-	long rc;
-	unsigned long hcpuid;
 	BUG_ON(nr < 0 || nr >= NR_CPUS);
 
 	if (!smp_startup_cpu(nr))
@@ -165,16 +166,20 @@
 	 * the processor will continue on to secondary_start
 	 */
 	paca[nr].cpu_start = 1;
-
+#ifdef CONFIG_HOTPLUG_CPU
 	set_preferred_offline_state(nr, CPU_STATE_ONLINE);
 
 	if (get_cpu_current_state(nr) == CPU_STATE_INACTIVE) {
+		long rc;
+		unsigned long hcpuid;
+
 		hcpuid = get_hard_smp_processor_id(nr);
 		rc = plpar_hcall_norets(H_PROD, hcpuid);
 		if (rc != H_SUCCESS)
 			printk(KERN_ERR "Error: Prod to wake up processor %d "
 						"Ret= %ld\n", nr, rc);
 	}
+#endif
 }
 
 static int smp_pSeries_cpu_bootable(unsigned int nr)
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/xics.c linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/xics.c
--- linux-libre-2.6.38-gnu/arch/powerpc/platforms/pseries/xics.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/platforms/pseries/xics.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,88 +202,88 @@
 #define get_irq_server(virq, cpumask, strict_check) (default_server)
 #endif
 
-static void xics_unmask_irq(unsigned int virq)
+static void xics_unmask_irq(struct irq_data *d)
 {
-	unsigned int irq;
+	unsigned int hwirq;
 	int call_status;
 	int server;
 
-	pr_devel("xics: unmask virq %d\n", virq);
+	pr_devel("xics: unmask virq %d\n", d->irq);
 
-	irq = (unsigned int)irq_map[virq].hwirq;
-	pr_devel(" -> map to hwirq 0x%x\n", irq);
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	pr_devel(" -> map to hwirq 0x%x\n", hwirq);
+	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return;
 
-	server = get_irq_server(virq, irq_to_desc(virq)->affinity, 0);
+	server = get_irq_server(d->irq, d->affinity, 0);
 
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq, server,
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hwirq, server,
 				DEFAULT_PRIORITY);
 	if (call_status != 0) {
 		printk(KERN_ERR
 			"%s: ibm_set_xive irq %u server %x returned %d\n",
-			__func__, irq, server, call_status);
+			__func__, hwirq, server, call_status);
 		return;
 	}
 
 	/* Now unmask the interrupt (often a no-op) */
-	call_status = rtas_call(ibm_int_on, 1, 1, NULL, irq);
+	call_status = rtas_call(ibm_int_on, 1, 1, NULL, hwirq);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_int_on irq=%u returned %d\n",
-			__func__, irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 }
 
-static unsigned int xics_startup(unsigned int virq)
+static unsigned int xics_startup(struct irq_data *d)
 {
 	/*
 	 * The generic MSI code returns with the interrupt disabled on the
 	 * card, using the MSI mask bits. Firmware doesn't appear to unmask
 	 * at that level, so we do it here by hand.
 	 */
-	if (irq_to_desc(virq)->msi_desc)
-		unmask_msi_irq(irq_get_irq_data(virq));
+	if (d->msi_desc)
+		unmask_msi_irq(d);
 
 	/* unmask it */
-	xics_unmask_irq(virq);
+	xics_unmask_irq(d);
 	return 0;
 }
 
-static void xics_mask_real_irq(unsigned int irq)
+static void xics_mask_real_irq(unsigned int hwirq)
 {
 	int call_status;
 
-	if (irq == XICS_IPI)
+	if (hwirq == XICS_IPI)
 		return;
 
-	call_status = rtas_call(ibm_int_off, 1, 1, NULL, irq);
+	call_status = rtas_call(ibm_int_off, 1, 1, NULL, hwirq);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_int_off irq=%u returned %d\n",
-			__func__, irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 
 	/* Have to set XIVE to 0xff to be able to remove a slot */
-	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, irq,
+	call_status = rtas_call(ibm_set_xive, 3, 1, NULL, hwirq,
 				default_server, 0xff);
 	if (call_status != 0) {
 		printk(KERN_ERR "%s: ibm_set_xive(0xff) irq=%u returned %d\n",
-			__func__, irq, call_status);
+			__func__, hwirq, call_status);
 		return;
 	}
 }
 
-static void xics_mask_irq(unsigned int virq)
+static void xics_mask_irq(struct irq_data *d)
 {
-	unsigned int irq;
+	unsigned int hwirq;
 
-	pr_devel("xics: mask virq %d\n", virq);
+	pr_devel("xics: mask virq %d\n", d->irq);
 
-	irq = (unsigned int)irq_map[virq].hwirq;
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return;
-	xics_mask_real_irq(irq);
+	xics_mask_real_irq(hwirq);
 }
 
 static void xics_mask_unknown_vec(unsigned int vec)
@@ -371,57 +371,58 @@
 	return os_cppr->stack[--os_cppr->index];
 }
 
-static void xics_eoi_direct(unsigned int virq)
+static void xics_eoi_direct(struct irq_data *d)
 {
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
+	unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	iosync();
-	direct_xirr_info_set((pop_cppr() << 24) | irq);
+	direct_xirr_info_set((pop_cppr() << 24) | hwirq);
 }
 
-static void xics_eoi_lpar(unsigned int virq)
+static void xics_eoi_lpar(struct irq_data *d)
 {
-	unsigned int irq = (unsigned int)irq_map[virq].hwirq;
+	unsigned int hwirq = (unsigned int)irq_map[d->irq].hwirq;
 
 	iosync();
-	lpar_xirr_info_set((pop_cppr() << 24) | irq);
+	lpar_xirr_info_set((pop_cppr() << 24) | hwirq);
 }
 
-static int xics_set_affinity(unsigned int virq, const struct cpumask *cpumask)
+static int
+xics_set_affinity(struct irq_data *d, const struct cpumask *cpumask, bool force)
 {
-	unsigned int irq;
+	unsigned int hwirq;
 	int status;
 	int xics_status[2];
 	int irq_server;
 
-	irq = (unsigned int)irq_map[virq].hwirq;
-	if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+	hwirq = (unsigned int)irq_map[d->irq].hwirq;
+	if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 		return -1;
 
-	status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+	status = rtas_call(ibm_get_xive, 1, 3, xics_status, hwirq);
 
 	if (status) {
 		printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
-			__func__, irq, status);
+			__func__, hwirq, status);
 		return -1;
 	}
 
-	irq_server = get_irq_server(virq, cpumask, 1);
+	irq_server = get_irq_server(d->irq, cpumask, 1);
 	if (irq_server == -1) {
 		char cpulist[128];
 		cpumask_scnprintf(cpulist, sizeof(cpulist), cpumask);
 		printk(KERN_WARNING
 			"%s: No online cpus in the mask %s for irq %d\n",
-			__func__, cpulist, virq);
+			__func__, cpulist, d->irq);
 		return -1;
 	}
 
 	status = rtas_call(ibm_set_xive, 3, 1, NULL,
-				irq, irq_server, xics_status[1]);
+				hwirq, irq_server, xics_status[1]);
 
 	if (status) {
 		printk(KERN_ERR "%s: ibm,set-xive irq=%u returns %d\n",
-			__func__, irq, status);
+			__func__, hwirq, status);
 		return -1;
 	}
 
@@ -430,20 +431,20 @@
 
 static struct irq_chip xics_pic_direct = {
 	.name = "XICS",
-	.startup = xics_startup,
-	.mask = xics_mask_irq,
-	.unmask = xics_unmask_irq,
-	.eoi = xics_eoi_direct,
-	.set_affinity = xics_set_affinity
+	.irq_startup = xics_startup,
+	.irq_mask = xics_mask_irq,
+	.irq_unmask = xics_unmask_irq,
+	.irq_eoi = xics_eoi_direct,
+	.irq_set_affinity = xics_set_affinity
 };
 
 static struct irq_chip xics_pic_lpar = {
 	.name = "XICS",
-	.startup = xics_startup,
-	.mask = xics_mask_irq,
-	.unmask = xics_unmask_irq,
-	.eoi = xics_eoi_lpar,
-	.set_affinity = xics_set_affinity
+	.irq_startup = xics_startup,
+	.irq_mask = xics_mask_irq,
+	.irq_unmask = xics_unmask_irq,
+	.irq_eoi = xics_eoi_lpar,
+	.irq_set_affinity = xics_set_affinity
 };
 
 
@@ -469,8 +470,8 @@
 	/* Insert the interrupt mapping into the radix tree for fast lookup */
 	irq_radix_revmap_insert(xics_host, virq, hw);
 
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, xics_irq_chip, handle_fasteoi_irq);
 	return 0;
 }
 
@@ -599,7 +600,7 @@
 	 * IPIs are marked IRQF_DISABLED as they must run with irqs
 	 * disabled
 	 */
-	set_irq_handler(ipi, handle_percpu_irq);
+	irq_set_handler(ipi, handle_percpu_irq);
 	if (firmware_has_feature(FW_FEATURE_LPAR))
 		rc = request_irq(ipi, xics_ipi_action_lpar,
 				IRQF_DISABLED|IRQF_PERCPU, "IPI", NULL);
@@ -873,7 +874,7 @@
 void xics_migrate_irqs_away(void)
 {
 	int cpu = smp_processor_id(), hw_cpu = hard_smp_processor_id();
-	unsigned int irq, virq;
+	int virq;
 
 	/* If we used to be the default server, move to the new "boot_cpuid" */
 	if (hw_cpu == default_server)
@@ -890,33 +891,38 @@
 
 	for_each_irq(virq) {
 		struct irq_desc *desc;
+		struct irq_chip *chip;
+		unsigned int hwirq;
 		int xics_status[2];
 		int status;
 		unsigned long flags;
 
-		/* We cant set affinity on ISA interrupts */
+		/* We can't set affinity on ISA interrupts */
 		if (virq < NUM_ISA_INTERRUPTS)
 			continue;
 		if (irq_map[virq].host != xics_host)
 			continue;
-		irq = (unsigned int)irq_map[virq].hwirq;
+		hwirq = (unsigned int)irq_map[virq].hwirq;
 		/* We need to get IPIs still. */
-		if (irq == XICS_IPI || irq == XICS_IRQ_SPURIOUS)
+		if (hwirq == XICS_IPI || hwirq == XICS_IRQ_SPURIOUS)
 			continue;
+
 		desc = irq_to_desc(virq);
 
 		/* We only need to migrate enabled IRQS */
-		if (desc == NULL || desc->chip == NULL
-		    || desc->action == NULL
-		    || desc->chip->set_affinity == NULL)
+		if (desc == NULL || desc->action == NULL)
+			continue;
+
+		chip = irq_desc_get_chip(desc);
+		if (chip == NULL || chip->irq_set_affinity == NULL)
 			continue;
 
 		raw_spin_lock_irqsave(&desc->lock, flags);
 
-		status = rtas_call(ibm_get_xive, 1, 3, xics_status, irq);
+		status = rtas_call(ibm_get_xive, 1, 3, xics_status, hwirq);
 		if (status) {
 			printk(KERN_ERR "%s: ibm,get-xive irq=%u returns %d\n",
-					__func__, irq, status);
+					__func__, hwirq, status);
 			goto unlock;
 		}
 
@@ -934,8 +940,8 @@
 			       virq, cpu);
 
 		/* Reset affinity to all cpus */
-		cpumask_setall(irq_to_desc(virq)->affinity);
-		desc->chip->set_affinity(virq, cpu_all_mask);
+		cpumask_setall(desc->irq_data.affinity);
+		chip->irq_set_affinity(&desc->irq_data, cpu_all_mask, true);
 unlock:
 		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/axonram.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/axonram.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/axonram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/axonram.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 
 	BUG_ON(!bank);
 
-	dev_err(&device->dev, "Correctable memory error occured\n");
+	dev_err(&device->dev, "Correctable memory error occurred\n");
 	bank->ecc_counter++;
 	return IRQ_HANDLED;
 }
@@ -172,10 +172,9 @@
 
 /**
  * axon_ram_probe - probe() method for platform driver
- * @device, @device_id: see of_platform_driver method
+ * @device: see platform_driver method
  */
-static int axon_ram_probe(struct platform_device *device,
-			  const struct of_device_id *device_id)
+static int axon_ram_probe(struct platform_device *device)
 {
 	static int axon_ram_bank_id = -1;
 	struct axon_ram_bank *bank;
@@ -326,7 +325,7 @@
 	{}
 };
 
-static struct of_platform_driver axon_ram_driver = {
+static struct platform_driver axon_ram_driver = {
 	.probe		= axon_ram_probe,
 	.remove		= axon_ram_remove,
 	.driver = {
@@ -350,7 +349,7 @@
 	}
 	azfs_minor = 0;
 
-	return of_register_platform_driver(&axon_ram_driver);
+	return platform_driver_register(&axon_ram_driver);
 }
 
 /**
@@ -359,7 +358,7 @@
 static void __exit
 axon_ram_exit(void)
 {
-	of_unregister_platform_driver(&axon_ram_driver);
+	platform_driver_unregister(&axon_ram_driver);
 	unregister_blkdev(azfs_major, AXON_RAM_DEVICE_NAME);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.c	2011-05-19 00:06:34.000000000 -0400
@@ -365,8 +365,7 @@
 /* OF platform driver                                                       */
 /* ======================================================================== */
 
-static int __devinit mpc52xx_bcom_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc52xx_bcom_probe(struct platform_device *op)
 {
 	struct device_node *ofn_sram;
 	struct resource res_bcom;
@@ -492,7 +491,7 @@
 MODULE_DEVICE_TABLE(of, mpc52xx_bcom_of_match);
 
 
-static struct of_platform_driver mpc52xx_bcom_of_platform_driver = {
+static struct platform_driver mpc52xx_bcom_of_platform_driver = {
 	.probe		= mpc52xx_bcom_probe,
 	.remove		= mpc52xx_bcom_remove,
 	.driver = {
@@ -510,13 +509,13 @@
 static int __init
 mpc52xx_bcom_init(void)
 {
-	return of_register_platform_driver(&mpc52xx_bcom_of_platform_driver);
+	return platform_driver_register(&mpc52xx_bcom_of_platform_driver);
 }
 
 static void __exit
 mpc52xx_bcom_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_bcom_of_platform_driver);
+	platform_driver_unregister(&mpc52xx_bcom_of_platform_driver);
 }
 
 /* If we're not a module, we must make sure everything is setup before  */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.h linux-libre-2.6.39-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.h
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/bestcomm/bestcomm.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
  * struct bcom_bd - Structure describing a generic BestComm buffer descriptor
  * @status: The current status of this buffer. Exact meaning depends on the
  *          task type
- * @data: An array of u32 extra data.  Size of array is task dependant.
+ * @data: An array of u32 extra data.  Size of array is task dependent.
  *
  * Note: Don't dereference a bcom_bd pointer as an array.  The size of the
  *       bcom_bd is variable.  Use bcom_get_bd() instead.
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h linux-libre-2.6.39-gnu/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/bestcomm/bestcomm_priv.h	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 	u8	reserved[8];
 };
 
-/* Descriptors stucture & co */
+/* Descriptors structure & co */
 #define BCOM_DESC_NOP		0x000001f8
 #define BCOM_LCD_MASK		0x80000000
 #define BCOM_DRD_EXTENDED	0x40000000
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/cpm1.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/cpm1.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/cpm1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/cpm1.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,32 +56,32 @@
 
 static struct irq_host *cpm_pic_host;
 
-static void cpm_mask_irq(unsigned int irq)
+static void cpm_mask_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
 
 	clrbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
 }
 
-static void cpm_unmask_irq(unsigned int irq)
+static void cpm_unmask_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
 
 	setbits32(&cpic_reg->cpic_cimr, (1 << cpm_vec));
 }
 
-static void cpm_end_irq(unsigned int irq)
+static void cpm_end_irq(struct irq_data *d)
 {
-	unsigned int cpm_vec = (unsigned int)irq_map[irq].hwirq;
+	unsigned int cpm_vec = (unsigned int)irq_map[d->irq].hwirq;
 
 	out_be32(&cpic_reg->cpic_cisr, (1 << cpm_vec));
 }
 
 static struct irq_chip cpm_pic = {
 	.name = "CPM PIC",
-	.mask = cpm_mask_irq,
-	.unmask = cpm_unmask_irq,
-	.eoi = cpm_end_irq,
+	.irq_mask = cpm_mask_irq,
+	.irq_unmask = cpm_unmask_irq,
+	.irq_eoi = cpm_end_irq,
 };
 
 int cpm_get_irq(void)
@@ -103,8 +103,8 @@
 {
 	pr_debug("cpm_pic_host_map(%d, 0x%lx)\n", virq, hw);
 
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &cpm_pic, handle_fasteoi_irq);
 	return 0;
 }
 
@@ -223,7 +223,7 @@
 
 	/* Set SDMA Bus Request priority 5.
 	 * On 860T, this also enables FEC priority 6.  I am not sure
-	 * this is what we realy want for some applications, but the
+	 * this is what we really want for some applications, but the
 	 * manual recommends it.
 	 * Bit 25, FAM can also be set to use FEC aggressive mode (860T).
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/cpm2_pic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/cpm2_pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/cpm2_pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/cpm2_pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,10 +78,10 @@
 	24, 25, 26, 27, 28, 29, 30, 31,
 };
 
-static void cpm2_mask_irq(unsigned int virq)
+static void cpm2_mask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -90,10 +90,10 @@
 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
 }
 
-static void cpm2_unmask_irq(unsigned int virq)
+static void cpm2_unmask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -102,10 +102,10 @@
 	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
 }
 
-static void cpm2_ack(unsigned int virq)
+static void cpm2_ack(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
 	bit = irq_to_siubit[irq_nr];
 	word = irq_to_siureg[irq_nr];
@@ -113,34 +113,27 @@
 	out_be32(&cpm2_intctl->ic_sipnrh + word, 1 << bit);
 }
 
-static void cpm2_end_irq(unsigned int virq)
+static void cpm2_end_irq(struct irq_data *d)
 {
-	struct irq_desc *desc;
 	int	bit, word;
-	unsigned int irq_nr = virq_to_hw(virq);
-
-	desc = irq_to_desc(irq_nr);
-	if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS))
-			&& desc->action) {
+	unsigned int irq_nr = virq_to_hw(d->irq);
 
-		bit = irq_to_siubit[irq_nr];
-		word = irq_to_siureg[irq_nr];
+	bit = irq_to_siubit[irq_nr];
+	word = irq_to_siureg[irq_nr];
 
-		ppc_cached_irq_mask[word] |= 1 << bit;
-		out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
+	ppc_cached_irq_mask[word] |= 1 << bit;
+	out_be32(&cpm2_intctl->ic_simrh + word, ppc_cached_irq_mask[word]);
 
-		/*
-		 * Work around large numbers of spurious IRQs on PowerPC 82xx
-		 * systems.
-		 */
-		mb();
-	}
+	/*
+	 * Work around large numbers of spurious IRQs on PowerPC 82xx
+	 * systems.
+	 */
+	mb();
 }
 
-static int cpm2_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int cpm2_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	unsigned int src = virq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	unsigned int src = virq_to_hw(d->irq);
 	unsigned int vold, vnew, edibit;
 
 	/* Port C interrupts are either IRQ_TYPE_EDGE_FALLING or
@@ -162,13 +155,11 @@
 			goto err_sense;
 	}
 
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
-		desc->status |= IRQ_LEVEL;
-		desc->handle_irq = handle_level_irq;
-	} else
-		desc->handle_irq = handle_edge_irq;
+	irqd_set_trigger_type(d, flow_type);
+	if (flow_type & IRQ_TYPE_LEVEL_LOW)
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+	else
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
 
 	/* internal IRQ senses are LEVEL_LOW
 	 * EXT IRQ and Port C IRQ senses are programmable
@@ -179,7 +170,8 @@
 		if (src >= CPM2_IRQ_PORTC15 && src <= CPM2_IRQ_PORTC0)
 			edibit = (31 - (CPM2_IRQ_PORTC0 - src));
 		else
-			return (flow_type & IRQ_TYPE_LEVEL_LOW) ? 0 : -EINVAL;
+			return (flow_type & IRQ_TYPE_LEVEL_LOW) ?
+				IRQ_SET_MASK_OK_NOCOPY : -EINVAL;
 
 	vold = in_be32(&cpm2_intctl->ic_siexr);
 
@@ -190,7 +182,7 @@
 
 	if (vold != vnew)
 		out_be32(&cpm2_intctl->ic_siexr, vnew);
-	return 0;
+	return IRQ_SET_MASK_OK_NOCOPY;
 
 err_sense:
 	pr_err("CPM2 PIC: sense type 0x%x not supported\n", flow_type);
@@ -199,11 +191,12 @@
 
 static struct irq_chip cpm2_pic = {
 	.name = "CPM2 SIU",
-	.mask = cpm2_mask_irq,
-	.unmask = cpm2_unmask_irq,
-	.ack = cpm2_ack,
-	.eoi = cpm2_end_irq,
-	.set_type = cpm2_set_irq_type,
+	.irq_mask = cpm2_mask_irq,
+	.irq_unmask = cpm2_unmask_irq,
+	.irq_ack = cpm2_ack,
+	.irq_eoi = cpm2_end_irq,
+	.irq_set_type = cpm2_set_irq_type,
+	.flags = IRQCHIP_EOI_IF_HANDLED,
 };
 
 unsigned int cpm2_get_irq(void)
@@ -226,8 +219,8 @@
 {
 	pr_debug("cpm2_pic_host_map(%d, 0x%lx)\n", virq, hw);
 
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &cpm2_pic, handle_level_irq);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_85xx_l2ctlr.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,8 +71,7 @@
 __setup("cache-sram-size=", get_size_from_cmdline);
 __setup("cache-sram-offset=", get_offset_from_cmdline);
 
-static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev,
-					  const struct of_device_id *match)
+static int __devinit mpc85xx_l2ctlr_of_probe(struct platform_device *dev)
 {
 	long rval;
 	unsigned int rem;
@@ -94,14 +93,14 @@
 	l2cache_size = *prop;
 
 	sram_params.sram_size  = get_cache_sram_size();
-	if (sram_params.sram_size <= 0) {
+	if ((int)sram_params.sram_size <= 0) {
 		dev_err(&dev->dev,
 			"Entire L2 as cache, Aborting Cache-SRAM stuff\n");
 		return -EINVAL;
 	}
 
 	sram_params.sram_offset  = get_cache_sram_offset();
-	if (sram_params.sram_offset <= 0) {
+	if ((int64_t)sram_params.sram_offset <= 0) {
 		dev_err(&dev->dev,
 			"Entire L2 as cache, provide a valid sram offset\n");
 		return -EINVAL;
@@ -204,7 +203,7 @@
 	{},
 };
 
-static struct of_platform_driver mpc85xx_l2ctlr_of_platform_driver = {
+static struct platform_driver mpc85xx_l2ctlr_of_platform_driver = {
 	.driver	= {
 		.name		= "fsl-l2ctlr",
 		.owner		= THIS_MODULE,
@@ -216,12 +215,12 @@
 
 static __init int mpc85xx_l2ctlr_of_init(void)
 {
-	return of_register_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+	return platform_driver_register(&mpc85xx_l2ctlr_of_platform_driver);
 }
 
 static void __exit mpc85xx_l2ctlr_of_exit(void)
 {
-	of_unregister_platform_driver(&mpc85xx_l2ctlr_of_platform_driver);
+	platform_driver_unregister(&mpc85xx_l2ctlr_of_platform_driver);
 }
 
 subsys_initcall(mpc85xx_l2ctlr_of_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_msi.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_msi.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright (C) 2007-2011 Freescale Semiconductor, Inc.
  *
  * Author: Tony Li <tony.li@freescale.com>
  *	   Jason Jin <Jason.jin@freescale.com>
@@ -47,14 +47,14 @@
  * We do not need this actually. The MSIR register has been read once
  * in the cascade interrupt. So, this MSI interrupt has been acked
 */
-static void fsl_msi_end_irq(unsigned int virq)
+static void fsl_msi_end_irq(struct irq_data *d)
 {
 }
 
 static struct irq_chip fsl_msi_chip = {
 	.irq_mask	= mask_msi_irq,
 	.irq_unmask	= unmask_msi_irq,
-	.ack		= fsl_msi_end_irq,
+	.irq_ack	= fsl_msi_end_irq,
 	.name		= "FSL-MSI",
 };
 
@@ -64,10 +64,10 @@
 	struct fsl_msi *msi_data = h->host_data;
 	struct irq_chip *chip = &fsl_msi_chip;
 
-	irq_to_desc(virq)->status |= IRQ_TYPE_EDGE_FALLING;
+	irq_set_status_flags(virq, IRQ_TYPE_EDGE_FALLING);
 
-	set_irq_chip_data(virq, msi_data);
-	set_irq_chip_and_handler(virq, chip, handle_edge_irq);
+	irq_set_chip_data(virq, msi_data);
+	irq_set_chip_and_handler(virq, chip, handle_edge_irq);
 
 	return 0;
 }
@@ -110,8 +110,8 @@
 	list_for_each_entry(entry, &pdev->msi_list, list) {
 		if (entry->irq == NO_IRQ)
 			continue;
-		msi_data = get_irq_data(entry->irq);
-		set_irq_msi(entry->irq, NULL);
+		msi_data = irq_get_handler_data(entry->irq);
+		irq_set_msi_desc(entry->irq, NULL);
 		msi_bitmap_free_hwirqs(&msi_data->bitmap,
 				       virq_to_hw(entry->irq), 1);
 		irq_dispose_mapping(entry->irq);
@@ -168,8 +168,8 @@
 			rc = -ENOSPC;
 			goto out_free;
 		}
-		set_irq_data(virq, msi_data);
-		set_irq_msi(virq, entry);
+		irq_set_handler_data(virq, msi_data);
+		irq_set_msi_desc(virq, entry);
 
 		fsl_compose_msi_msg(pdev, hwirq, &msg, msi_data);
 		write_msi_msg(virq, &msg);
@@ -183,6 +183,8 @@
 
 static void fsl_msi_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
 	unsigned int cascade_irq;
 	struct fsl_msi *msi_data;
 	int msir_index = -1;
@@ -191,20 +193,20 @@
 	u32 have_shift = 0;
 	struct fsl_msi_cascade_data *cascade_data;
 
-	cascade_data = (struct fsl_msi_cascade_data *)get_irq_data(irq);
+	cascade_data = (struct fsl_msi_cascade_data *)irq_get_handler_data(irq);
 	msi_data = cascade_data->msi_data;
 
 	raw_spin_lock(&desc->lock);
 	if ((msi_data->feature &  FSL_PIC_IP_MASK) == FSL_PIC_IP_IPIC) {
-		if (desc->chip->mask_ack)
-			desc->chip->mask_ack(irq);
+		if (chip->irq_mask_ack)
+			chip->irq_mask_ack(idata);
 		else {
-			desc->chip->mask(irq);
-			desc->chip->ack(irq);
+			chip->irq_mask(idata);
+			chip->irq_ack(idata);
 		}
 	}
 
-	if (unlikely(desc->status & IRQ_INPROGRESS))
+	if (unlikely(irqd_irq_inprogress(idata)))
 		goto unlock;
 
 	msir_index = cascade_data->index;
@@ -212,7 +214,7 @@
 	if (msir_index >= NR_MSI_REG)
 		cascade_irq = NO_IRQ;
 
-	desc->status |= IRQ_INPROGRESS;
+	irqd_set_chained_irq_inprogress(idata);
 	switch (msi_data->feature & FSL_PIC_IP_MASK) {
 	case FSL_PIC_IP_MPIC:
 		msir_value = fsl_msi_read(msi_data->msi_regs,
@@ -234,15 +236,15 @@
 		have_shift += intr_index + 1;
 		msir_value = msir_value >> (intr_index + 1);
 	}
-	desc->status &= ~IRQ_INPROGRESS;
+	irqd_clr_chained_irq_inprogress(idata);
 
 	switch (msi_data->feature & FSL_PIC_IP_MASK) {
 	case FSL_PIC_IP_MPIC:
-		desc->chip->eoi(irq);
+		chip->irq_eoi(idata);
 		break;
 	case FSL_PIC_IP_IPIC:
-		if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-			desc->chip->unmask(irq);
+		if (!irqd_irq_disabled(idata) && chip->irq_unmask)
+			chip->irq_unmask(idata);
 		break;
 	}
 unlock:
@@ -260,7 +262,7 @@
 	for (i = 0; i < NR_MSI_REG; i++) {
 		virq = msi->msi_virqs[i];
 		if (virq != NO_IRQ) {
-			cascade_data = get_irq_data(virq);
+			cascade_data = irq_get_handler_data(virq);
 			kfree(cascade_data);
 			irq_dispose_mapping(virq);
 		}
@@ -273,19 +275,53 @@
 	return 0;
 }
 
-static int __devinit fsl_of_msi_probe(struct platform_device *dev,
-				const struct of_device_id *match)
+static int __devinit fsl_msi_setup_hwirq(struct fsl_msi *msi,
+					 struct platform_device *dev,
+					 int offset, int irq_index)
+{
+	struct fsl_msi_cascade_data *cascade_data = NULL;
+	int virt_msir;
+
+	virt_msir = irq_of_parse_and_map(dev->dev.of_node, irq_index);
+	if (virt_msir == NO_IRQ) {
+		dev_err(&dev->dev, "%s: Cannot translate IRQ index %d\n",
+			__func__, irq_index);
+		return 0;
+	}
+
+	cascade_data = kzalloc(sizeof(struct fsl_msi_cascade_data), GFP_KERNEL);
+	if (!cascade_data) {
+		dev_err(&dev->dev, "No memory for MSI cascade data\n");
+		return -ENOMEM;
+	}
+
+	msi->msi_virqs[irq_index] = virt_msir;
+	cascade_data->index = offset + irq_index;
+	cascade_data->msi_data = msi;
+	irq_set_handler_data(virt_msir, cascade_data);
+	irq_set_chained_handler(virt_msir, fsl_msi_cascade);
+
+	return 0;
+}
+
+static const struct of_device_id fsl_of_msi_ids[];
+static int __devinit fsl_of_msi_probe(struct platform_device *dev)
 {
+	const struct of_device_id *match;
 	struct fsl_msi *msi;
 	struct resource res;
-	int err, i, count;
+	int err, i, j, irq_index, count;
 	int rc;
-	int virt_msir;
 	const u32 *p;
-	struct fsl_msi_feature *features = match->data;
-	struct fsl_msi_cascade_data *cascade_data = NULL;
+	struct fsl_msi_feature *features;
 	int len;
 	u32 offset;
+	static const u32 all_avail[] = { 0, NR_MSI_IRQS };
+
+	match = of_match_device(fsl_of_msi_ids, &dev->dev);
+	if (!match)
+		return -EINVAL;
+	features = match->data;
 
 	printk(KERN_DEBUG "Setting up Freescale MSI support\n");
 
@@ -332,42 +368,34 @@
 		goto error_out;
 	}
 
-	p = of_get_property(dev->dev.of_node, "interrupts", &count);
-	if (!p) {
-		dev_err(&dev->dev, "no interrupts property found on %s\n",
-				dev->dev.of_node->full_name);
-		err = -ENODEV;
-		goto error_out;
-	}
-	if (count % 8 != 0) {
-		dev_err(&dev->dev, "Malformed interrupts property on %s\n",
-				dev->dev.of_node->full_name);
+	p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
+	if (p && len % (2 * sizeof(u32)) != 0) {
+		dev_err(&dev->dev, "%s: Malformed msi-available-ranges property\n",
+			__func__);
 		err = -EINVAL;
 		goto error_out;
 	}
-	offset = 0;
-	p = of_get_property(dev->dev.of_node, "msi-available-ranges", &len);
-	if (p)
-		offset = *p / IRQS_PER_MSI_REG;
 
-	count /= sizeof(u32);
-	for (i = 0; i < min(count / 2, NR_MSI_REG); i++) {
-		virt_msir = irq_of_parse_and_map(dev->dev.of_node, i);
-		if (virt_msir != NO_IRQ) {
-			cascade_data = kzalloc(
-					sizeof(struct fsl_msi_cascade_data),
-					GFP_KERNEL);
-			if (!cascade_data) {
-				dev_err(&dev->dev,
-					"No memory for MSI cascade data\n");
-				err = -ENOMEM;
+	if (!p)
+		p = all_avail;
+
+	for (irq_index = 0, i = 0; i < len / (2 * sizeof(u32)); i++) {
+		if (p[i * 2] % IRQS_PER_MSI_REG ||
+		    p[i * 2 + 1] % IRQS_PER_MSI_REG) {
+			printk(KERN_WARNING "%s: %s: msi available range of %u at %u is not IRQ-aligned\n",
+			       __func__, dev->dev.of_node->full_name,
+			       p[i * 2 + 1], p[i * 2]);
+			err = -EINVAL;
+			goto error_out;
+		}
+
+		offset = p[i * 2] / IRQS_PER_MSI_REG;
+		count = p[i * 2 + 1] / IRQS_PER_MSI_REG;
+
+		for (j = 0; j < count; j++, irq_index++) {
+			err = fsl_msi_setup_hwirq(msi, dev, offset, irq_index);
+			if (err)
 				goto error_out;
-			}
-			msi->msi_virqs[i] = virt_msir;
-			cascade_data->index = i + offset;
-			cascade_data->msi_data = msi;
-			set_irq_data(virt_msir, (void *)cascade_data);
-			set_irq_chained_handler(virt_msir, fsl_msi_cascade);
 		}
 	}
 
@@ -411,7 +439,7 @@
 	{}
 };
 
-static struct of_platform_driver fsl_of_msi_driver = {
+static struct platform_driver fsl_of_msi_driver = {
 	.driver = {
 		.name = "fsl-msi",
 		.owner = THIS_MODULE,
@@ -423,7 +451,7 @@
 
 static __init int fsl_of_msi_init(void)
 {
-	return of_register_platform_driver(&fsl_of_msi_driver);
+	return platform_driver_register(&fsl_of_msi_driver);
 }
 
 subsys_initcall(fsl_of_msi_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_pci.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_pci.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * MPC83xx/85xx/86xx PCI/PCIE support routing.
  *
- * Copyright 2007-2010 Freescale Semiconductor, Inc.
+ * Copyright 2007-2011 Freescale Semiconductor, Inc.
  * Copyright 2008-2009 MontaVista Software, Inc.
  *
  * Initial author: Xianghua Xiao <x.xiao@freescale.com>
@@ -99,7 +99,7 @@
 				  struct resource *rsrc)
 {
 	struct ccsr_pci __iomem *pci;
-	int i, j, n, mem_log, win_idx = 2;
+	int i, j, n, mem_log, win_idx = 3, start_idx = 1, end_idx = 4;
 	u64 mem, sz, paddr_hi = 0;
 	u64 paddr_lo = ULLONG_MAX;
 	u32 pcicsrbar = 0, pcicsrbar_sz;
@@ -109,6 +109,13 @@
 
 	pr_debug("PCI memory map start 0x%016llx, size 0x%016llx\n",
 		    (u64)rsrc->start, (u64)rsrc->end - (u64)rsrc->start + 1);
+
+	if (of_device_is_compatible(hose->dn, "fsl,qoriq-pcie-v2.2")) {
+		win_idx = 2;
+		start_idx = 0;
+		end_idx = 3;
+	}
+
 	pci = ioremap(rsrc->start, rsrc->end - rsrc->start + 1);
 	if (!pci) {
 	    dev_err(hose->parent, "Unable to map ATMU registers\n");
@@ -118,7 +125,7 @@
 	/* Disable all windows (except powar0 since it's ignored) */
 	for(i = 1; i < 5; i++)
 		out_be32(&pci->pow[i].powar, 0);
-	for(i = 0; i < 3; i++)
+	for (i = start_idx; i < end_idx; i++)
 		out_be32(&pci->piw[i].piwar, 0);
 
 	/* Setup outbound MEM window */
@@ -204,7 +211,7 @@
 			mem_log++;
 		}
 
-		piwar |= (mem_log - 1);
+		piwar |= ((mem_log - 1) & PIWAR_SZ_MASK);
 
 		/* Setup inbound memory window */
 		out_be32(&pci->piw[win_idx].pitar,  0x00000000);
@@ -317,6 +324,11 @@
 	struct resource rsrc;
 	const int *bus_range;
 
+	if (!of_device_is_available(dev)) {
+		pr_warning("%s: disabled\n", dev->full_name);
+		return -ENODEV;
+	}
+
 	pr_debug("Adding PCI host bridge %s\n", dev->full_name);
 
 	/* Fetch host bridge registers address */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_pci.h linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_pci.h
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * MPC85xx/86xx PCI Express structure define
  *
- * Copyright 2007 Freescale Semiconductor, Inc
+ * Copyright 2007,2011 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
@@ -21,6 +21,7 @@
 #define PIWAR_TGI_LOCAL		0x00f00000	/* target - local memory */
 #define PIWAR_READ_SNOOP	0x00050000
 #define PIWAR_WRITE_SNOOP	0x00005000
+#define PIWAR_SZ_MASK          0x0000003f
 
 /* PCI/PCI Express outbound window reg */
 struct pci_outbound_window_regs {
@@ -49,7 +50,9 @@
 	__be32	int_ack;		/* 0x.008 - PCI Interrupt Acknowledge Register */
 	__be32	pex_otb_cpl_tor;	/* 0x.00c - PCIE Outbound completion timeout register */
 	__be32	pex_conf_tor;		/* 0x.010 - PCIE configuration timeout register */
-	u8	res2[12];
+	__be32	pex_config;		/* 0x.014 - PCIE CONFIG Register */
+	__be32	pex_int_status;		/* 0x.018 - PCIE interrupt status */
+	u8	res2[4];
 	__be32	pex_pme_mes_dr;		/* 0x.020 - PCIE PME and message detect register */
 	__be32	pex_pme_mes_disr;	/* 0x.024 - PCIE PME and message disable register */
 	__be32	pex_pme_mes_ier;	/* 0x.028 - PCIE PME and message interrupt enable register */
@@ -62,14 +65,14 @@
  * in all of the other outbound windows.
  */
 	struct pci_outbound_window_regs pow[5];
-
-	u8	res14[256];
-
-/* PCI/PCI Express inbound window 3-1
+	u8	res14[96];
+	struct pci_inbound_window_regs	pmit;	/* 0xd00 - 0xd9c Inbound MSI */
+	u8	res6[96];
+/* PCI/PCI Express inbound window 3-0
  * inbound window 1 supports only a 32-bit base address and does not
  * define an inbound window base extended address register.
  */
-	struct pci_inbound_window_regs piw[3];
+	struct pci_inbound_window_regs piw[4];
 
 	__be32	pex_err_dr;		/* 0x.e00 - PCI/PCIE error detect register */
 	u8	res21[4];
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_pmc.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_pmc.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_pmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_pmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,8 +58,7 @@
 	.enter = pmc_suspend_enter,
 };
 
-static int pmc_probe(struct platform_device *ofdev,
-		     const struct of_device_id *id)
+static int pmc_probe(struct platform_device *ofdev)
 {
 	pmc_regs = of_iomap(ofdev->dev.of_node, 0);
 	if (!pmc_regs)
@@ -76,7 +75,7 @@
 	{ },
 };
 
-static struct of_platform_driver pmc_driver = {
+static struct platform_driver pmc_driver = {
 	.driver = {
 		.name = "fsl-pmc",
 		.owner = THIS_MODULE,
@@ -87,6 +86,6 @@
 
 static int __init pmc_init(void)
 {
-	return of_register_platform_driver(&pmc_driver);
+	return platform_driver_register(&pmc_driver);
 }
 device_initcall(pmc_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_rio.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_rio.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/fsl_rio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/fsl_rio.c	2011-05-19 00:06:34.000000000 -0400
@@ -482,7 +482,7 @@
 }
 
 /**
- * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue
+ * fsl_add_outb_message - Add message to the MPC85xx outbound message queue
  * @mport: Master port with outbound message queue
  * @rdev: Target of outbound message
  * @mbox: Outbound mailbox
@@ -492,8 +492,8 @@
  * Adds the @buffer message to the MPC85xx outbound message queue. Returns
  * %0 on success or %-EINVAL on failure.
  */
-int
-rio_hw_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
+static int
+fsl_add_outb_message(struct rio_mport *mport, struct rio_dev *rdev, int mbox,
 			void *buffer, size_t len)
 {
 	struct rio_priv *priv = mport->priv;
@@ -502,9 +502,8 @@
 					+ priv->msg_tx_ring.tx_slot;
 	int ret = 0;
 
-	pr_debug
-	    ("RIO: rio_hw_add_outb_message(): destid %4.4x mbox %d buffer %8.8x len %8.8x\n",
-	     rdev->destid, mbox, (int)buffer, len);
+	pr_debug("RIO: fsl_add_outb_message(): destid %4.4x mbox %d buffer " \
+		 "%8.8x len %8.8x\n", rdev->destid, mbox, (int)buffer, len);
 
 	if ((len < 8) || (len > RIO_MAX_MSG_SIZE)) {
 		ret = -EINVAL;
@@ -554,8 +553,6 @@
 	return ret;
 }
 
-EXPORT_SYMBOL_GPL(rio_hw_add_outb_message);
-
 /**
  * fsl_rio_tx_handler - MPC85xx outbound message interrupt handler
  * @irq: Linux interrupt number
@@ -600,7 +597,7 @@
 }
 
 /**
- * rio_open_outb_mbox - Initialize MPC85xx outbound mailbox
+ * fsl_open_outb_mbox - Initialize MPC85xx outbound mailbox
  * @mport: Master port implementing the outbound message unit
  * @dev_id: Device specific pointer to pass on event
  * @mbox: Mailbox to open
@@ -610,7 +607,8 @@
  * and enables the outbound message unit. Returns %0 on success and
  * %-EINVAL or %-ENOMEM on failure.
  */
-int rio_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
+static int
+fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
 {
 	int i, j, rc = 0;
 	struct rio_priv *priv = mport->priv;
@@ -706,14 +704,14 @@
 }
 
 /**
- * rio_close_outb_mbox - Shut down MPC85xx outbound mailbox
+ * fsl_close_outb_mbox - Shut down MPC85xx outbound mailbox
  * @mport: Master port implementing the outbound message unit
  * @mbox: Mailbox to close
  *
  * Disables the outbound message unit, free all buffers, and
  * frees the outbound message interrupt.
  */
-void rio_close_outb_mbox(struct rio_mport *mport, int mbox)
+static void fsl_close_outb_mbox(struct rio_mport *mport, int mbox)
 {
 	struct rio_priv *priv = mport->priv;
 	/* Disable inbound message unit */
@@ -770,7 +768,7 @@
 }
 
 /**
- * rio_open_inb_mbox - Initialize MPC85xx inbound mailbox
+ * fsl_open_inb_mbox - Initialize MPC85xx inbound mailbox
  * @mport: Master port implementing the inbound message unit
  * @dev_id: Device specific pointer to pass on event
  * @mbox: Mailbox to open
@@ -780,7 +778,8 @@
  * and enables the inbound message unit. Returns %0 on success
  * and %-EINVAL or %-ENOMEM on failure.
  */
-int rio_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
+static int
+fsl_open_inb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
 {
 	int i, rc = 0;
 	struct rio_priv *priv = mport->priv;
@@ -844,14 +843,14 @@
 }
 
 /**
- * rio_close_inb_mbox - Shut down MPC85xx inbound mailbox
+ * fsl_close_inb_mbox - Shut down MPC85xx inbound mailbox
  * @mport: Master port implementing the inbound message unit
  * @mbox: Mailbox to close
  *
  * Disables the inbound message unit, free all buffers, and
  * frees the inbound message interrupt.
  */
-void rio_close_inb_mbox(struct rio_mport *mport, int mbox)
+static void fsl_close_inb_mbox(struct rio_mport *mport, int mbox)
 {
 	struct rio_priv *priv = mport->priv;
 	/* Disable inbound message unit */
@@ -866,7 +865,7 @@
 }
 
 /**
- * rio_hw_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
+ * fsl_add_inb_buffer - Add buffer to the MPC85xx inbound message queue
  * @mport: Master port implementing the inbound message unit
  * @mbox: Inbound mailbox number
  * @buf: Buffer to add to inbound queue
@@ -874,12 +873,12 @@
  * Adds the @buf buffer to the MPC85xx inbound message queue. Returns
  * %0 on success or %-EINVAL on failure.
  */
-int rio_hw_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
+static int fsl_add_inb_buffer(struct rio_mport *mport, int mbox, void *buf)
 {
 	int rc = 0;
 	struct rio_priv *priv = mport->priv;
 
-	pr_debug("RIO: rio_hw_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
+	pr_debug("RIO: fsl_add_inb_buffer(), msg_rx_ring.rx_slot %d\n",
 		 priv->msg_rx_ring.rx_slot);
 
 	if (priv->msg_rx_ring.virt_buffer[priv->msg_rx_ring.rx_slot]) {
@@ -898,17 +897,15 @@
 	return rc;
 }
 
-EXPORT_SYMBOL_GPL(rio_hw_add_inb_buffer);
-
 /**
- * rio_hw_get_inb_message - Fetch inbound message from the MPC85xx message unit
+ * fsl_get_inb_message - Fetch inbound message from the MPC85xx message unit
  * @mport: Master port implementing the inbound message unit
  * @mbox: Inbound mailbox number
  *
  * Gets the next available inbound message from the inbound message queue.
  * A pointer to the message is returned on success or NULL on failure.
  */
-void *rio_hw_get_inb_message(struct rio_mport *mport, int mbox)
+static void *fsl_get_inb_message(struct rio_mport *mport, int mbox)
 {
 	struct rio_priv *priv = mport->priv;
 	u32 phys_buf, virt_buf;
@@ -945,8 +942,6 @@
 	return buf;
 }
 
-EXPORT_SYMBOL_GPL(rio_hw_get_inb_message);
-
 /**
  * fsl_rio_dbell_handler - MPC85xx doorbell interrupt handler
  * @irq: Linux interrupt number
@@ -1293,28 +1288,6 @@
 	return rc;
 }
 
-static char *cmdline = NULL;
-
-static int fsl_rio_get_hdid(int index)
-{
-	/* XXX Need to parse multiple entries in some format */
-	if (!cmdline)
-		return -1;
-
-	return simple_strtol(cmdline, NULL, 0);
-}
-
-static int fsl_rio_get_cmdline(char *s)
-{
-	if (!s)
-		return 0;
-
-	cmdline = s;
-	return 1;
-}
-
-__setup("riohdid=", fsl_rio_get_cmdline);
-
 static inline void fsl_rio_info(struct device *dev, u32 ccsr)
 {
 	const char *str;
@@ -1431,13 +1404,19 @@
 	ops->cwrite = fsl_rio_config_write;
 	ops->dsend = fsl_rio_doorbell_send;
 	ops->pwenable = fsl_rio_pw_enable;
+	ops->open_outb_mbox = fsl_open_outb_mbox;
+	ops->open_inb_mbox = fsl_open_inb_mbox;
+	ops->close_outb_mbox = fsl_close_outb_mbox;
+	ops->close_inb_mbox = fsl_close_inb_mbox;
+	ops->add_outb_message = fsl_add_outb_message;
+	ops->add_inb_buffer = fsl_add_inb_buffer;
+	ops->get_inb_message = fsl_get_inb_message;
 
 	port = kzalloc(sizeof(struct rio_mport), GFP_KERNEL);
 	if (!port) {
 		rc = -ENOMEM;
 		goto err_port;
 	}
-	port->id = 0;
 	port->index = 0;
 
 	priv = kzalloc(sizeof(struct rio_priv), GFP_KERNEL);
@@ -1453,6 +1432,14 @@
 	port->iores.flags = IORESOURCE_MEM;
 	port->iores.name = "rio_io_win";
 
+	if (request_resource(&iomem_resource, &port->iores) < 0) {
+		dev_err(&dev->dev, "RIO: Error requesting master port region"
+			" 0x%016llx-0x%016llx\n",
+			(u64)port->iores.start, (u64)port->iores.end);
+			rc = -ENOMEM;
+			goto err_res;
+	}
+
 	priv->pwirq   = irq_of_parse_and_map(dev->dev.of_node, 0);
 	priv->bellirq = irq_of_parse_and_map(dev->dev.of_node, 2);
 	priv->txirq = irq_of_parse_and_map(dev->dev.of_node, 3);
@@ -1468,11 +1455,8 @@
 	priv->dev = &dev->dev;
 
 	port->ops = ops;
-	port->host_deviceid = fsl_rio_get_hdid(port->id);
-
 	port->priv = priv;
 	port->phys_efptr = 0x100;
-	rio_register_mport(port);
 
 	priv->regs_win = ioremap(regs.start, regs.end - regs.start + 1);
 	rio_regs_win = priv->regs_win;
@@ -1519,6 +1503,9 @@
 	dev_info(&dev->dev, "RapidIO Common Transport System size: %d\n",
 			port->sys_size ? 65536 : 256);
 
+	if (rio_register_mport(port))
+		goto err;
+
 	if (port->host_deviceid >= 0)
 		out_be32(priv->regs_win + RIO_GCCSR, RIO_PORT_GEN_HOST |
 			RIO_PORT_GEN_MASTER | RIO_PORT_GEN_DISCOVERED);
@@ -1559,6 +1546,7 @@
 	return 0;
 err:
 	iounmap(priv->regs_win);
+err_res:
 	kfree(priv);
 err_priv:
 	kfree(port);
@@ -1570,21 +1558,12 @@
 
 /* The probe function for RapidIO peer-to-peer network.
  */
-static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev,
-				     const struct of_device_id *match)
+static int __devinit fsl_of_rio_rpn_probe(struct platform_device *dev)
 {
-	int rc;
 	printk(KERN_INFO "Setting up RapidIO peer-to-peer network %s\n",
 			dev->dev.of_node->full_name);
 
-	rc = fsl_rio_setup(dev);
-	if (rc)
-		goto out;
-
-	/* Enumerate all registered ports */
-	rc = rio_init_mports();
-out:
-	return rc;
+	return fsl_rio_setup(dev);
 };
 
 static const struct of_device_id fsl_of_rio_rpn_ids[] = {
@@ -1594,7 +1573,7 @@
 	{},
 };
 
-static struct of_platform_driver fsl_of_rio_rpn_driver = {
+static struct platform_driver fsl_of_rio_rpn_driver = {
 	.driver = {
 		.name = "fsl-of-rio",
 		.owner = THIS_MODULE,
@@ -1605,7 +1584,7 @@
 
 static __init int fsl_of_rio_rpn_init(void)
 {
-	return of_register_platform_driver(&fsl_of_rio_rpn_driver);
+	return platform_driver_register(&fsl_of_rio_rpn_driver);
 }
 
 subsys_initcall(fsl_of_rio_rpn_init);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/i8259.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/i8259.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/i8259.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/i8259.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,19 +78,19 @@
 	return irq;
 }
 
-static void i8259_mask_and_ack_irq(unsigned int irq_nr)
+static void i8259_mask_and_ack_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
 	raw_spin_lock_irqsave(&i8259_lock, flags);
-	if (irq_nr > 7) {
-		cached_A1 |= 1 << (irq_nr-8);
+	if (d->irq > 7) {
+		cached_A1 |= 1 << (d->irq-8);
 		inb(0xA1); 	/* DUMMY */
 		outb(cached_A1, 0xA1);
 		outb(0x20, 0xA0);	/* Non-specific EOI */
 		outb(0x20, 0x20);	/* Non-specific EOI to cascade */
 	} else {
-		cached_21 |= 1 << irq_nr;
+		cached_21 |= 1 << d->irq;
 		inb(0x21); 	/* DUMMY */
 		outb(cached_21, 0x21);
 		outb(0x20, 0x20);	/* Non-specific EOI */
@@ -104,42 +104,42 @@
 	outb(cached_21,0x21);
 }
 
-static void i8259_mask_irq(unsigned int irq_nr)
+static void i8259_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
-	pr_debug("i8259_mask_irq(%d)\n", irq_nr);
+	pr_debug("i8259_mask_irq(%d)\n", d->irq);
 
 	raw_spin_lock_irqsave(&i8259_lock, flags);
-	if (irq_nr < 8)
-		cached_21 |= 1 << irq_nr;
+	if (d->irq < 8)
+		cached_21 |= 1 << d->irq;
 	else
-		cached_A1 |= 1 << (irq_nr-8);
-	i8259_set_irq_mask(irq_nr);
+		cached_A1 |= 1 << (d->irq-8);
+	i8259_set_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
-static void i8259_unmask_irq(unsigned int irq_nr)
+static void i8259_unmask_irq(struct irq_data *d)
 {
 	unsigned long flags;
 
-	pr_debug("i8259_unmask_irq(%d)\n", irq_nr);
+	pr_debug("i8259_unmask_irq(%d)\n", d->irq);
 
 	raw_spin_lock_irqsave(&i8259_lock, flags);
-	if (irq_nr < 8)
-		cached_21 &= ~(1 << irq_nr);
+	if (d->irq < 8)
+		cached_21 &= ~(1 << d->irq);
 	else
-		cached_A1 &= ~(1 << (irq_nr-8));
-	i8259_set_irq_mask(irq_nr);
+		cached_A1 &= ~(1 << (d->irq-8));
+	i8259_set_irq_mask(d->irq);
 	raw_spin_unlock_irqrestore(&i8259_lock, flags);
 }
 
 static struct irq_chip i8259_pic = {
 	.name		= "i8259",
-	.mask		= i8259_mask_irq,
-	.disable	= i8259_mask_irq,
-	.unmask		= i8259_unmask_irq,
-	.mask_ack	= i8259_mask_and_ack_irq,
+	.irq_mask	= i8259_mask_irq,
+	.irq_disable	= i8259_mask_irq,
+	.irq_unmask	= i8259_unmask_irq,
+	.irq_mask_ack	= i8259_mask_and_ack_irq,
 };
 
 static struct resource pic1_iores = {
@@ -175,23 +175,23 @@
 
 	/* We block the internal cascade */
 	if (hw == 2)
-		irq_to_desc(virq)->status |= IRQ_NOREQUEST;
+		irq_set_status_flags(virq, IRQ_NOREQUEST);
 
 	/* We use the level handler only for now, we might want to
 	 * be more cautious here but that works for now
 	 */
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
-	set_irq_chip_and_handler(virq, &i8259_pic, handle_level_irq);
+	irq_set_status_flags(virq, IRQ_LEVEL);
+	irq_set_chip_and_handler(virq, &i8259_pic, handle_level_irq);
 	return 0;
 }
 
 static void i8259_host_unmap(struct irq_host *h, unsigned int virq)
 {
 	/* Make sure irq is masked in hardware */
-	i8259_mask_irq(virq);
+	i8259_mask_irq(irq_get_irq_data(virq));
 
 	/* remove chip and handler */
-	set_irq_chip_and_handler(virq, NULL, NULL);
+	irq_set_chip_and_handler(virq, NULL, NULL);
 
 	/* Make sure it's completed */
 	synchronize_irq(virq);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/indirect_pci.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/indirect_pci.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/indirect_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/indirect_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,7 +117,7 @@
 		out_le32(hose->cfg_addr, (0x80000000 | (bus_no << 16) |
 			 (devfn << 8) | reg | cfg_type));
 
-	/* surpress setting of PCI_PRIMARY_BUS */
+	/* suppress setting of PCI_PRIMARY_BUS */
 	if (hose->indirect_type & PPC_INDIRECT_TYPE_SURPRESS_PRIMARY_BUS)
 		if ((offset == PCI_PRIMARY_BUS) &&
 			(bus->number == hose->first_busno))
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/ipic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/ipic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/ipic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/ipic.c	2011-05-19 00:06:34.000000000 -0400
@@ -523,10 +523,10 @@
 
 #define ipic_irq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
 
-static void ipic_unmask_irq(unsigned int virq)
+static void ipic_unmask_irq(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -539,10 +539,10 @@
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_mask_irq(unsigned int virq)
+static void ipic_mask_irq(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -559,10 +559,10 @@
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_ack_irq(unsigned int virq)
+static void ipic_ack_irq(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -578,10 +578,10 @@
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static void ipic_mask_irq_and_ack(unsigned int virq)
+static void ipic_mask_irq_and_ack(struct irq_data *d)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -601,11 +601,10 @@
 	raw_spin_unlock_irqrestore(&ipic_lock, flags);
 }
 
-static int ipic_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int ipic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct ipic *ipic = ipic_from_irq(virq);
-	unsigned int src = ipic_irq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct ipic *ipic = ipic_from_irq(d->irq);
+	unsigned int src = ipic_irq_to_hw(d->irq);
 	unsigned int vold, vnew, edibit;
 
 	if (flow_type == IRQ_TYPE_NONE)
@@ -623,17 +622,16 @@
 		printk(KERN_ERR "ipic: edge sense not supported on internal "
 				"interrupts\n");
 		return -EINVAL;
+
 	}
 
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
+	irqd_set_trigger_type(d, flow_type);
 	if (flow_type & IRQ_TYPE_LEVEL_LOW)  {
-		desc->status |= IRQ_LEVEL;
-		desc->handle_irq = handle_level_irq;
-		desc->chip = &ipic_level_irq_chip;
+		__irq_set_handler_locked(d->irq, handle_level_irq);
+		d->chip = &ipic_level_irq_chip;
 	} else {
-		desc->handle_irq = handle_edge_irq;
-		desc->chip = &ipic_edge_irq_chip;
+		__irq_set_handler_locked(d->irq, handle_edge_irq);
+		d->chip = &ipic_edge_irq_chip;
 	}
 
 	/* only EXT IRQ senses are programmable on ipic
@@ -655,25 +653,25 @@
 	}
 	if (vold != vnew)
 		ipic_write(ipic->regs, IPIC_SECNR, vnew);
-	return 0;
+	return IRQ_SET_MASK_OK_NOCOPY;
 }
 
 /* level interrupts and edge interrupts have different ack operations */
 static struct irq_chip ipic_level_irq_chip = {
 	.name		= "IPIC",
-	.unmask		= ipic_unmask_irq,
-	.mask		= ipic_mask_irq,
-	.mask_ack	= ipic_mask_irq,
-	.set_type	= ipic_set_irq_type,
+	.irq_unmask	= ipic_unmask_irq,
+	.irq_mask	= ipic_mask_irq,
+	.irq_mask_ack	= ipic_mask_irq,
+	.irq_set_type	= ipic_set_irq_type,
 };
 
 static struct irq_chip ipic_edge_irq_chip = {
 	.name		= "IPIC",
-	.unmask		= ipic_unmask_irq,
-	.mask		= ipic_mask_irq,
-	.mask_ack	= ipic_mask_irq_and_ack,
-	.ack		= ipic_ack_irq,
-	.set_type	= ipic_set_irq_type,
+	.irq_unmask	= ipic_unmask_irq,
+	.irq_mask	= ipic_mask_irq,
+	.irq_mask_ack	= ipic_mask_irq_and_ack,
+	.irq_ack	= ipic_ack_irq,
+	.irq_set_type	= ipic_set_irq_type,
 };
 
 static int ipic_host_match(struct irq_host *h, struct device_node *node)
@@ -687,11 +685,11 @@
 {
 	struct ipic *ipic = h->host_data;
 
-	set_irq_chip_data(virq, ipic);
-	set_irq_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
+	irq_set_chip_data(virq, ipic);
+	irq_set_chip_and_handler(virq, &ipic_level_irq_chip, handle_level_irq);
 
 	/* Set default irq type */
-	set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/Makefile linux-libre-2.6.39-gnu/arch/powerpc/sysdev/Makefile
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
 obj-$(CONFIG_MPC8xxx_GPIO)	+= mpc8xxx_gpio.o
 obj-$(CONFIG_FSL_85XX_CACHE_SRAM)	+= fsl_85xx_l2ctlr.o fsl_85xx_cache_sram.o
 obj-$(CONFIG_SIMPLE_GPIO)	+= simple_gpio.o
-obj-$(CONFIG_RAPIDIO)		+= fsl_rio.o
+obj-$(CONFIG_FSL_RIO)		+= fsl_rio.o
 obj-$(CONFIG_TSI108_BRIDGE)	+= tsi108_pci.o tsi108_dev.o
 obj-$(CONFIG_QUICC_ENGINE)	+= qe_lib/
 obj-$(CONFIG_PPC_BESTCOMM)	+= bestcomm/
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpc8xx_pic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpc8xx_pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpc8xx_pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpc8xx_pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,10 +25,10 @@
 
 int cpm_get_irq(struct pt_regs *regs);
 
-static void mpc8xx_unmask_irq(unsigned int virq)
+static void mpc8xx_unmask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -37,10 +37,10 @@
 	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
 }
 
-static void mpc8xx_mask_irq(unsigned int virq)
+static void mpc8xx_mask_irq(struct irq_data *d)
 {
 	int	bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -49,19 +49,19 @@
 	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
 }
 
-static void mpc8xx_ack(unsigned int virq)
+static void mpc8xx_ack(struct irq_data *d)
 {
 	int	bit;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	out_be32(&siu_reg->sc_sipend, 1 << (31-bit));
 }
 
-static void mpc8xx_end_irq(unsigned int virq)
+static void mpc8xx_end_irq(struct irq_data *d)
 {
 	int bit, word;
-	unsigned int irq_nr = (unsigned int)irq_map[virq].hwirq;
+	unsigned int irq_nr = (unsigned int)irq_map[d->irq].hwirq;
 
 	bit = irq_nr & 0x1f;
 	word = irq_nr >> 5;
@@ -70,24 +70,17 @@
 	out_be32(&siu_reg->sc_simask, ppc_cached_irq_mask[word]);
 }
 
-static int mpc8xx_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int mpc8xx_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		desc->status |= IRQ_LEVEL;
-
 	if (flow_type & IRQ_TYPE_EDGE_FALLING) {
-		irq_hw_number_t hw = (unsigned int)irq_map[virq].hwirq;
+		irq_hw_number_t hw = (unsigned int)irq_map[d->irq].hwirq;
 		unsigned int siel = in_be32(&siu_reg->sc_siel);
 
 		/* only external IRQ senses are programmable */
 		if ((hw & 1) == 0) {
 			siel |= (0x80000000 >> hw);
 			out_be32(&siu_reg->sc_siel, siel);
-			desc->handle_irq = handle_edge_irq;
+			__irq_set_handler_locked(d->irq, handle_edge_irq);
 		}
 	}
 	return 0;
@@ -95,11 +88,11 @@
 
 static struct irq_chip mpc8xx_pic = {
 	.name = "MPC8XX SIU",
-	.unmask = mpc8xx_unmask_irq,
-	.mask = mpc8xx_mask_irq,
-	.ack = mpc8xx_ack,
-	.eoi = mpc8xx_end_irq,
-	.set_type = mpc8xx_set_irq_type,
+	.irq_unmask = mpc8xx_unmask_irq,
+	.irq_mask = mpc8xx_mask_irq,
+	.irq_ack = mpc8xx_ack,
+	.irq_eoi = mpc8xx_end_irq,
+	.irq_set_type = mpc8xx_set_irq_type,
 };
 
 unsigned int mpc8xx_get_irq(void)
@@ -124,7 +117,7 @@
 	pr_debug("mpc8xx_pic_host_map(%d, 0x%lx)\n", virq, hw);
 
 	/* Set default irq handle */
-	set_irq_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
+	irq_set_chip_and_handler(virq, &mpc8xx_pic, handle_level_irq);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpc8xxx_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -145,7 +145,7 @@
 
 static void mpc8xxx_gpio_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_desc_data(desc);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_desc_get_handler_data(desc);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned int mask;
 
@@ -155,43 +155,43 @@
 						     32 - ffs(mask)));
 }
 
-static void mpc8xxx_irq_unmask(unsigned int virq)
+static void mpc8xxx_irq_unmask(struct irq_data *d)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
+	setbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 
 	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
-static void mpc8xxx_irq_mask(unsigned int virq)
+static void mpc8xxx_irq_mask(struct irq_data *d)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 
-	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(virq)));
+	clrbits32(mm->regs + GPIO_IMR, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 
 	spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 }
 
-static void mpc8xxx_irq_ack(unsigned int virq)
+static void mpc8xxx_irq_ack(struct irq_data *d)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 
-	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(virq)));
+	out_be32(mm->regs + GPIO_IER, mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 }
 
-static int mpc8xxx_irq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc8xxx_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
 	unsigned long flags;
 
@@ -199,14 +199,14 @@
 	case IRQ_TYPE_EDGE_FALLING:
 		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		setbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(virq_to_hw(virq)));
+			  mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 		break;
 
 	case IRQ_TYPE_EDGE_BOTH:
 		spin_lock_irqsave(&mpc8xxx_gc->lock, flags);
 		clrbits32(mm->regs + GPIO_ICR,
-			  mpc8xxx_gpio2mask(virq_to_hw(virq)));
+			  mpc8xxx_gpio2mask(virq_to_hw(d->irq)));
 		spin_unlock_irqrestore(&mpc8xxx_gc->lock, flags);
 		break;
 
@@ -217,11 +217,11 @@
 	return 0;
 }
 
-static int mpc512x_irq_set_type(unsigned int virq, unsigned int flow_type)
+static int mpc512x_irq_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpc8xxx_gpio_chip *mpc8xxx_gc = get_irq_chip_data(virq);
+	struct mpc8xxx_gpio_chip *mpc8xxx_gc = irq_data_get_irq_chip_data(d);
 	struct of_mm_gpio_chip *mm = &mpc8xxx_gc->mm_gc;
-	unsigned long gpio = virq_to_hw(virq);
+	unsigned long gpio = virq_to_hw(d->irq);
 	void __iomem *reg;
 	unsigned int shift;
 	unsigned long flags;
@@ -264,10 +264,10 @@
 
 static struct irq_chip mpc8xxx_irq_chip = {
 	.name		= "mpc8xxx-gpio",
-	.unmask		= mpc8xxx_irq_unmask,
-	.mask		= mpc8xxx_irq_mask,
-	.ack		= mpc8xxx_irq_ack,
-	.set_type	= mpc8xxx_irq_set_type,
+	.irq_unmask	= mpc8xxx_irq_unmask,
+	.irq_mask	= mpc8xxx_irq_mask,
+	.irq_ack	= mpc8xxx_irq_ack,
+	.irq_set_type	= mpc8xxx_irq_set_type,
 };
 
 static int mpc8xxx_gpio_irq_map(struct irq_host *h, unsigned int virq,
@@ -276,11 +276,11 @@
 	struct mpc8xxx_gpio_chip *mpc8xxx_gc = h->host_data;
 
 	if (mpc8xxx_gc->of_dev_id_data)
-		mpc8xxx_irq_chip.set_type = mpc8xxx_gc->of_dev_id_data;
+		mpc8xxx_irq_chip.irq_set_type = mpc8xxx_gc->of_dev_id_data;
 
-	set_irq_chip_data(virq, h->host_data);
-	set_irq_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
-	set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_chip_data(virq, h->host_data);
+	irq_set_chip_and_handler(virq, &mpc8xxx_irq_chip, handle_level_irq);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
 	return 0;
 }
@@ -310,6 +310,7 @@
 	{ .compatible = "fsl,mpc8572-gpio", },
 	{ .compatible = "fsl,mpc8610-gpio", },
 	{ .compatible = "fsl,mpc5121-gpio", .data = mpc512x_irq_set_type, },
+	{ .compatible = "fsl,qoriq-gpio",   },
 	{}
 };
 
@@ -368,8 +369,8 @@
 	out_be32(mm_gc->regs + GPIO_IER, 0xffffffff);
 	out_be32(mm_gc->regs + GPIO_IMR, 0);
 
-	set_irq_data(hwirq, mpc8xxx_gc);
-	set_irq_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
+	irq_set_handler_data(hwirq, mpc8xxx_gc);
+	irq_set_chained_handler(hwirq, mpc8xxx_gpio_irq_cascade);
 
 skip_irq:
 	return;
@@ -389,9 +390,6 @@
 	for_each_matching_node(np, mpc8xxx_gpio_ids)
 		mpc8xxx_add_controller(np);
 
-	for_each_compatible_node(np, NULL, "fsl,qoriq-gpio")
-		mpc8xxx_add_controller(np);
-
 	return 0;
 }
 arch_initcall(mpc8xxx_add_gpiochips);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic.c	2011-05-19 00:06:34.000000000 -0400
@@ -147,6 +147,16 @@
 
 #endif /* CONFIG_MPIC_WEIRD */
 
+static inline unsigned int mpic_processor_id(struct mpic *mpic)
+{
+	unsigned int cpu = 0;
+
+	if (mpic->flags & MPIC_PRIMARY)
+		cpu = hard_smp_processor_id();
+
+	return cpu;
+}
+
 /*
  * Register accessor functions
  */
@@ -210,19 +220,14 @@
 
 static inline u32 _mpic_cpu_read(struct mpic *mpic, unsigned int reg)
 {
-	unsigned int cpu = 0;
+	unsigned int cpu = mpic_processor_id(mpic);
 
-	if (mpic->flags & MPIC_PRIMARY)
-		cpu = hard_smp_processor_id();
 	return _mpic_read(mpic->reg_type, &mpic->cpuregs[cpu], reg);
 }
 
 static inline void _mpic_cpu_write(struct mpic *mpic, unsigned int reg, u32 value)
 {
-	unsigned int cpu = 0;
-
-	if (mpic->flags & MPIC_PRIMARY)
-		cpu = hard_smp_processor_id();
+	unsigned int cpu = mpic_processor_id(mpic);
 
 	_mpic_write(mpic->reg_type, &mpic->cpuregs[cpu], reg, value);
 }
@@ -356,7 +361,7 @@
 }
 
 static void mpic_startup_ht_interrupt(struct mpic *mpic, unsigned int source,
-				      unsigned int irqflags)
+				      bool level)
 {
 	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
 	unsigned long flags;
@@ -365,14 +370,14 @@
 	if (fixup->base == NULL)
 		return;
 
-	DBG("startup_ht_interrupt(0x%x, 0x%x) index: %d\n",
-	    source, irqflags, fixup->index);
+	DBG("startup_ht_interrupt(0x%x) index: %d\n",
+	    source, fixup->index);
 	raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
 	/* Enable and configure */
 	writeb(0x10 + 2 * fixup->index, fixup->base + 2);
 	tmp = readl(fixup->base + 4);
 	tmp &= ~(0x23U);
-	if (irqflags & IRQ_LEVEL)
+	if (level)
 		tmp |= 0x22;
 	writel(tmp, fixup->base + 4);
 	raw_spin_unlock_irqrestore(&mpic->fixup_lock, flags);
@@ -384,8 +389,7 @@
 #endif
 }
 
-static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source,
-				       unsigned int irqflags)
+static void mpic_shutdown_ht_interrupt(struct mpic *mpic, unsigned int source)
 {
 	struct mpic_irq_fixup *fixup = &mpic->fixups[source];
 	unsigned long flags;
@@ -394,7 +398,7 @@
 	if (fixup->base == NULL)
 		return;
 
-	DBG("shutdown_ht_interrupt(0x%x, 0x%x)\n", source, irqflags);
+	DBG("shutdown_ht_interrupt(0x%x)\n", source);
 
 	/* Disable */
 	raw_spin_lock_irqsave(&mpic->fixup_lock, flags);
@@ -611,7 +615,7 @@
 	if (irq < NUM_ISA_INTERRUPTS)
 		return NULL;
 
-	return irq_to_desc(irq)->chip_data;
+	return irq_get_chip_data(irq);
 }
 
 /* Determine if the linux irq is an IPI */
@@ -636,16 +640,22 @@
 
 #ifdef CONFIG_SMP
 /* Get the mpic structure from the IPI number */
-static inline struct mpic * mpic_from_ipi(unsigned int ipi)
+static inline struct mpic * mpic_from_ipi(struct irq_data *d)
 {
-	return irq_to_desc(ipi)->chip_data;
+	return irq_data_get_irq_chip_data(d);
 }
 #endif
 
 /* Get the mpic structure from the irq number */
 static inline struct mpic * mpic_from_irq(unsigned int irq)
 {
-	return irq_to_desc(irq)->chip_data;
+	return irq_get_chip_data(irq);
+}
+
+/* Get the mpic structure from the irq data */
+static inline struct mpic * mpic_from_irq_data(struct irq_data *d)
+{
+	return irq_data_get_irq_chip_data(d);
 }
 
 /* Send an EOI */
@@ -660,13 +670,13 @@
  */
 
 
-void mpic_unmask_irq(unsigned int irq)
+void mpic_unmask_irq(struct irq_data *d)
 {
 	unsigned int loops = 100000;
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, irq, src);
+	DBG("%p: %s: enable_irq: %d (src %d)\n", mpic, mpic->name, d->irq, src);
 
 	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
 		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) &
@@ -681,13 +691,13 @@
 	} while(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK);
 }
 
-void mpic_mask_irq(unsigned int irq)
+void mpic_mask_irq(struct irq_data *d)
 {
 	unsigned int loops = 100000;
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, irq, src);
+	DBG("%s: disable_irq: %d (src %d)\n", mpic->name, d->irq, src);
 
 	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI),
 		       mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) |
@@ -703,12 +713,12 @@
 	} while(!(mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI)) & MPIC_VECPRI_MASK));
 }
 
-void mpic_end_irq(unsigned int irq)
+void mpic_end_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
 
 #ifdef DEBUG_IRQ
-	DBG("%s: end_irq: %d\n", mpic->name, irq);
+	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
 #endif
 	/* We always EOI on end_irq() even for edge interrupts since that
 	 * should only lower the priority, the MPIC should have properly
@@ -720,51 +730,51 @@
 
 #ifdef CONFIG_MPIC_U3_HT_IRQS
 
-static void mpic_unmask_ht_irq(unsigned int irq)
+static void mpic_unmask_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	mpic_unmask_irq(irq);
+	mpic_unmask_irq(d);
 
-	if (irq_to_desc(irq)->status & IRQ_LEVEL)
+	if (irqd_is_level_type(d))
 		mpic_ht_end_irq(mpic, src);
 }
 
-static unsigned int mpic_startup_ht_irq(unsigned int irq)
+static unsigned int mpic_startup_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	mpic_unmask_irq(irq);
-	mpic_startup_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
+	mpic_unmask_irq(d);
+	mpic_startup_ht_interrupt(mpic, src, irqd_is_level_type(d));
 
 	return 0;
 }
 
-static void mpic_shutdown_ht_irq(unsigned int irq)
+static void mpic_shutdown_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
-	mpic_shutdown_ht_interrupt(mpic, src, irq_to_desc(irq)->status);
-	mpic_mask_irq(irq);
+	mpic_shutdown_ht_interrupt(mpic, src);
+	mpic_mask_irq(d);
 }
 
-static void mpic_end_ht_irq(unsigned int irq)
+static void mpic_end_ht_irq(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
 #ifdef DEBUG_IRQ
-	DBG("%s: end_irq: %d\n", mpic->name, irq);
+	DBG("%s: end_irq: %d\n", mpic->name, d->irq);
 #endif
 	/* We always EOI on end_irq() even for edge interrupts since that
 	 * should only lower the priority, the MPIC should have properly
 	 * latched another edge interrupt coming in anyway
 	 */
 
-	if (irq_to_desc(irq)->status & IRQ_LEVEL)
+	if (irqd_is_level_type(d))
 		mpic_ht_end_irq(mpic, src);
 	mpic_eoi(mpic);
 }
@@ -772,23 +782,23 @@
 
 #ifdef CONFIG_SMP
 
-static void mpic_unmask_ipi(unsigned int irq)
+static void mpic_unmask_ipi(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_ipi(irq);
-	unsigned int src = mpic_irq_to_hw(irq) - mpic->ipi_vecs[0];
+	struct mpic *mpic = mpic_from_ipi(d);
+	unsigned int src = mpic_irq_to_hw(d->irq) - mpic->ipi_vecs[0];
 
-	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, irq, src);
+	DBG("%s: enable_ipi: %d (ipi %d)\n", mpic->name, d->irq, src);
 	mpic_ipi_write(src, mpic_ipi_read(src) & ~MPIC_VECPRI_MASK);
 }
 
-static void mpic_mask_ipi(unsigned int irq)
+static void mpic_mask_ipi(struct irq_data *d)
 {
 	/* NEVER disable an IPI... that's just plain wrong! */
 }
 
-static void mpic_end_ipi(unsigned int irq)
+static void mpic_end_ipi(struct irq_data *d)
 {
-	struct mpic *mpic = mpic_from_ipi(irq);
+	struct mpic *mpic = mpic_from_ipi(d);
 
 	/*
 	 * IPIs are marked IRQ_PER_CPU. This has the side effect of
@@ -802,10 +812,11 @@
 
 #endif /* CONFIG_SMP */
 
-int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask)
+int mpic_set_affinity(struct irq_data *d, const struct cpumask *cpumask,
+		      bool force)
 {
-	struct mpic *mpic = mpic_from_irq(irq);
-	unsigned int src = mpic_irq_to_hw(irq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 
 	if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
 		int cpuid = irq_choose_cpu(cpumask);
@@ -848,15 +859,14 @@
 	}
 }
 
-int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
+int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct mpic *mpic = mpic_from_irq(virq);
-	unsigned int src = mpic_irq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct mpic *mpic = mpic_from_irq_data(d);
+	unsigned int src = mpic_irq_to_hw(d->irq);
 	unsigned int vecpri, vold, vnew;
 
 	DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
-	    mpic, virq, src, flow_type);
+	    mpic, d->irq, src, flow_type);
 
 	if (src >= mpic->irq_count)
 		return -EINVAL;
@@ -867,10 +877,7 @@
 	if (flow_type == IRQ_TYPE_NONE)
 		flow_type = IRQ_TYPE_LEVEL_LOW;
 
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		desc->status |= IRQ_LEVEL;
+	irqd_set_trigger_type(d, flow_type);
 
 	if (mpic_is_ht_interrupt(mpic, src))
 		vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
@@ -885,7 +892,7 @@
 	if (vold != vnew)
 		mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
 
-	return 0;
+	return IRQ_SET_MASK_OK_NOCOPY;;
 }
 
 void mpic_set_vector(unsigned int virq, unsigned int vector)
@@ -906,29 +913,43 @@
 	mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
 }
 
+void mpic_set_destination(unsigned int virq, unsigned int cpuid)
+{
+	struct mpic *mpic = mpic_from_irq(virq);
+	unsigned int src = mpic_irq_to_hw(virq);
+
+	DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
+	    mpic, virq, src, cpuid);
+
+	if (src >= mpic->irq_count)
+		return;
+
+	mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
+}
+
 static struct irq_chip mpic_irq_chip = {
-	.mask		= mpic_mask_irq,
-	.unmask		= mpic_unmask_irq,
-	.eoi		= mpic_end_irq,
-	.set_type	= mpic_set_irq_type,
+	.irq_mask	= mpic_mask_irq,
+	.irq_unmask	= mpic_unmask_irq,
+	.irq_eoi	= mpic_end_irq,
+	.irq_set_type	= mpic_set_irq_type,
 };
 
 #ifdef CONFIG_SMP
 static struct irq_chip mpic_ipi_chip = {
-	.mask		= mpic_mask_ipi,
-	.unmask		= mpic_unmask_ipi,
-	.eoi		= mpic_end_ipi,
+	.irq_mask	= mpic_mask_ipi,
+	.irq_unmask	= mpic_unmask_ipi,
+	.irq_eoi	= mpic_end_ipi,
 };
 #endif /* CONFIG_SMP */
 
 #ifdef CONFIG_MPIC_U3_HT_IRQS
 static struct irq_chip mpic_irq_ht_chip = {
-	.startup	= mpic_startup_ht_irq,
-	.shutdown	= mpic_shutdown_ht_irq,
-	.mask		= mpic_mask_irq,
-	.unmask		= mpic_unmask_ht_irq,
-	.eoi		= mpic_end_ht_irq,
-	.set_type	= mpic_set_irq_type,
+	.irq_startup	= mpic_startup_ht_irq,
+	.irq_shutdown	= mpic_shutdown_ht_irq,
+	.irq_mask	= mpic_mask_irq,
+	.irq_unmask	= mpic_unmask_ht_irq,
+	.irq_eoi	= mpic_end_ht_irq,
+	.irq_set_type	= mpic_set_irq_type,
 };
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
@@ -957,8 +978,8 @@
 		WARN_ON(!(mpic->flags & MPIC_PRIMARY));
 
 		DBG("mpic: mapping as IPI\n");
-		set_irq_chip_data(virq, mpic);
-		set_irq_chip_and_handler(virq, &mpic->hc_ipi,
+		irq_set_chip_data(virq, mpic);
+		irq_set_chip_and_handler(virq, &mpic->hc_ipi,
 					 handle_percpu_irq);
 		return 0;
 	}
@@ -980,11 +1001,21 @@
 
 	DBG("mpic: mapping to irq chip @%p\n", chip);
 
-	set_irq_chip_data(virq, mpic);
-	set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
+	irq_set_chip_data(virq, mpic);
+	irq_set_chip_and_handler(virq, chip, handle_fasteoi_irq);
 
 	/* Set default irq type */
-	set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
+
+	/* If the MPIC was reset, then all vectors have already been
+	 * initialized.  Otherwise, a per source lazy initialization
+	 * is done here.
+	 */
+	if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+		mpic_set_vector(virq, hw);
+		mpic_set_destination(virq, mpic_processor_id(mpic));
+		mpic_irq_set_priority(virq, 8);
+	}
 
 	return 0;
 }
@@ -1033,6 +1064,11 @@
 	.xlate = mpic_host_xlate,
 };
 
+static int mpic_reset_prohibited(struct device_node *node)
+{
+	return node && of_get_property(node, "pic-no-reset", NULL);
+}
+
 /*
  * Exported functions
  */
@@ -1060,12 +1096,12 @@
 	mpic->hc_irq = mpic_irq_chip;
 	mpic->hc_irq.name = name;
 	if (flags & MPIC_PRIMARY)
-		mpic->hc_irq.set_affinity = mpic_set_affinity;
+		mpic->hc_irq.irq_set_affinity = mpic_set_affinity;
 #ifdef CONFIG_MPIC_U3_HT_IRQS
 	mpic->hc_ht_irq = mpic_irq_ht_chip;
 	mpic->hc_ht_irq.name = name;
 	if (flags & MPIC_PRIMARY)
-		mpic->hc_ht_irq.set_affinity = mpic_set_affinity;
+		mpic->hc_ht_irq.irq_set_affinity = mpic_set_affinity;
 #endif /* CONFIG_MPIC_U3_HT_IRQS */
 
 #ifdef CONFIG_SMP
@@ -1153,7 +1189,15 @@
 	mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
 
 	/* Reset */
-	if (flags & MPIC_WANTS_RESET) {
+
+	/* When using a device-node, reset requests are only honored if the MPIC
+	 * is allowed to reset.
+	 */
+	if (mpic_reset_prohibited(node))
+		mpic->flags |= MPIC_NO_RESET;
+
+	if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
+		printk(KERN_DEBUG "mpic: Resetting\n");
 		mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
 			   mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
 			   | MPIC_GREG_GCONF_RESET);
@@ -1313,22 +1357,21 @@
 
 	mpic_pasemi_msi_init(mpic);
 
-	if (mpic->flags & MPIC_PRIMARY)
-		cpu = hard_smp_processor_id();
-	else
-		cpu = 0;
+	cpu = mpic_processor_id(mpic);
 
-	for (i = 0; i < mpic->num_sources; i++) {
-		/* start with vector = source number, and masked */
-		u32 vecpri = MPIC_VECPRI_MASK | i |
-			(8 << MPIC_VECPRI_PRIORITY_SHIFT);
+	if (!(mpic->flags & MPIC_NO_RESET)) {
+		for (i = 0; i < mpic->num_sources; i++) {
+			/* start with vector = source number, and masked */
+			u32 vecpri = MPIC_VECPRI_MASK | i |
+				(8 << MPIC_VECPRI_PRIORITY_SHIFT);
 		
-		/* check if protected */
-		if (mpic->protected && test_bit(i, mpic->protected))
-			continue;
-		/* init hw */
-		mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
-		mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+			/* check if protected */
+			if (mpic->protected && test_bit(i, mpic->protected))
+				continue;
+			/* init hw */
+			mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+			mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+		}
 	}
 	
 	/* Init spurious vector */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic.h linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic.h
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,9 +34,10 @@
 }
 #endif
 
-extern int mpic_set_irq_type(unsigned int virq, unsigned int flow_type);
+extern int mpic_set_irq_type(struct irq_data *d, unsigned int flow_type);
 extern void mpic_set_vector(unsigned int virq, unsigned int vector);
-extern int mpic_set_affinity(unsigned int irq, const struct cpumask *cpumask);
+extern int mpic_set_affinity(struct irq_data *d,
+			     const struct cpumask *cpumask, bool force);
 extern void mpic_reset_core(int cpu);
 
 #endif /* _POWERPC_SYSDEV_MPIC_H */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic_pasemi_msi.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic_pasemi_msi.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic_pasemi_msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic_pasemi_msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,24 +43,24 @@
 {
 	pr_debug("mpic_pasemi_msi_mask_irq %d\n", data->irq);
 	mask_msi_irq(data);
-	mpic_mask_irq(data->irq);
+	mpic_mask_irq(data);
 }
 
 static void mpic_pasemi_msi_unmask_irq(struct irq_data *data)
 {
 	pr_debug("mpic_pasemi_msi_unmask_irq %d\n", data->irq);
-	mpic_unmask_irq(data->irq);
+	mpic_unmask_irq(data);
 	unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_pasemi_msi_chip = {
-	.irq_shutdown	= mpic_pasemi_msi_mask_irq,
-	.irq_mask	= mpic_pasemi_msi_mask_irq,
-	.irq_unmask	= mpic_pasemi_msi_unmask_irq,
-	.eoi		= mpic_end_irq,
-	.set_type	= mpic_set_irq_type,
-	.set_affinity	= mpic_set_affinity,
-	.name		= "PASEMI-MSI",
+	.irq_shutdown		= mpic_pasemi_msi_mask_irq,
+	.irq_mask		= mpic_pasemi_msi_mask_irq,
+	.irq_unmask		= mpic_pasemi_msi_unmask_irq,
+	.irq_eoi		= mpic_end_irq,
+	.irq_set_type		= mpic_set_irq_type,
+	.irq_set_affinity	= mpic_set_affinity,
+	.name			= "PASEMI-MSI",
 };
 
 static int pasemi_msi_check_device(struct pci_dev *pdev, int nvec, int type)
@@ -81,7 +81,7 @@
 		if (entry->irq == NO_IRQ)
 			continue;
 
-		set_irq_msi(entry->irq, NULL);
+		irq_set_msi_desc(entry->irq, NULL);
 		msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
 				       virq_to_hw(entry->irq), ALLOC_CHUNK);
 		irq_dispose_mapping(entry->irq);
@@ -131,9 +131,9 @@
 		 */
 		mpic_set_vector(virq, 0);
 
-		set_irq_msi(virq, entry);
-		set_irq_chip(virq, &mpic_pasemi_msi_chip);
-		set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+		irq_set_msi_desc(virq, entry);
+		irq_set_chip(virq, &mpic_pasemi_msi_chip);
+		irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 
 		pr_debug("pasemi_msi: allocated virq 0x%x (hw 0x%x) " \
 			 "addr 0x%x\n", virq, hwirq, msg.address_lo);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic_u3msi.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic_u3msi.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mpic_u3msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mpic_u3msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,23 +26,23 @@
 static void mpic_u3msi_mask_irq(struct irq_data *data)
 {
 	mask_msi_irq(data);
-	mpic_mask_irq(data->irq);
+	mpic_mask_irq(data);
 }
 
 static void mpic_u3msi_unmask_irq(struct irq_data *data)
 {
-	mpic_unmask_irq(data->irq);
+	mpic_unmask_irq(data);
 	unmask_msi_irq(data);
 }
 
 static struct irq_chip mpic_u3msi_chip = {
-	.irq_shutdown	= mpic_u3msi_mask_irq,
-	.irq_mask	= mpic_u3msi_mask_irq,
-	.irq_unmask	= mpic_u3msi_unmask_irq,
-	.eoi		= mpic_end_irq,
-	.set_type	= mpic_set_irq_type,
-	.set_affinity	= mpic_set_affinity,
-	.name		= "MPIC-U3MSI",
+	.irq_shutdown		= mpic_u3msi_mask_irq,
+	.irq_mask		= mpic_u3msi_mask_irq,
+	.irq_unmask		= mpic_u3msi_unmask_irq,
+	.irq_eoi		= mpic_end_irq,
+	.irq_set_type		= mpic_set_irq_type,
+	.irq_set_affinity	= mpic_set_affinity,
+	.name			= "MPIC-U3MSI",
 };
 
 static u64 read_ht_magic_addr(struct pci_dev *pdev, unsigned int pos)
@@ -129,7 +129,7 @@
 		if (entry->irq == NO_IRQ)
 			continue;
 
-		set_irq_msi(entry->irq, NULL);
+		irq_set_msi_desc(entry->irq, NULL);
 		msi_bitmap_free_hwirqs(&msi_mpic->msi_bitmap,
 				       virq_to_hw(entry->irq), 1);
 		irq_dispose_mapping(entry->irq);
@@ -166,9 +166,9 @@
 			return -ENOSPC;
 		}
 
-		set_irq_msi(virq, entry);
-		set_irq_chip(virq, &mpic_u3msi_chip);
-		set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
+		irq_set_msi_desc(virq, entry);
+		irq_set_chip(virq, &mpic_u3msi_chip);
+		irq_set_irq_type(virq, IRQ_TYPE_EDGE_RISING);
 
 		pr_debug("u3msi: allocated virq 0x%x (hw 0x%x) addr 0x%lx\n",
 			  virq, hwirq, (unsigned long)addr);
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mv64x60_dev.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mv64x60_dev.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mv64x60_dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mv64x60_dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -346,7 +346,7 @@
 	if (prop)
 		pdata.freq_m = *prop;
 
-	pdata.freq_m = 3;	/* default */
+	pdata.freq_n = 3;	/* default */
 	prop = of_get_property(np, "freq_n", NULL);
 	if (prop)
 		pdata.freq_n = *prop;
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mv64x60_pic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mv64x60_pic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/mv64x60_pic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/mv64x60_pic.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,9 +76,9 @@
  * mv64x60_chip_low functions
  */
 
-static void mv64x60_mask_low(unsigned int virq)
+static void mv64x60_mask_low(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -89,9 +89,9 @@
 	(void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_LO);
 }
 
-static void mv64x60_unmask_low(unsigned int virq)
+static void mv64x60_unmask_low(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -104,18 +104,18 @@
 
 static struct irq_chip mv64x60_chip_low = {
 	.name		= "mv64x60_low",
-	.mask		= mv64x60_mask_low,
-	.mask_ack	= mv64x60_mask_low,
-	.unmask		= mv64x60_unmask_low,
+	.irq_mask	= mv64x60_mask_low,
+	.irq_mask_ack	= mv64x60_mask_low,
+	.irq_unmask	= mv64x60_unmask_low,
 };
 
 /*
  * mv64x60_chip_high functions
  */
 
-static void mv64x60_mask_high(unsigned int virq)
+static void mv64x60_mask_high(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -126,9 +126,9 @@
 	(void)in_le32(mv64x60_irq_reg_base + MV64X60_IC_CPU0_INTR_MASK_HI);
 }
 
-static void mv64x60_unmask_high(unsigned int virq)
+static void mv64x60_unmask_high(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -141,18 +141,18 @@
 
 static struct irq_chip mv64x60_chip_high = {
 	.name		= "mv64x60_high",
-	.mask		= mv64x60_mask_high,
-	.mask_ack	= mv64x60_mask_high,
-	.unmask		= mv64x60_unmask_high,
+	.irq_mask	= mv64x60_mask_high,
+	.irq_mask_ack	= mv64x60_mask_high,
+	.irq_unmask	= mv64x60_unmask_high,
 };
 
 /*
  * mv64x60_chip_gpp functions
  */
 
-static void mv64x60_mask_gpp(unsigned int virq)
+static void mv64x60_mask_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -163,9 +163,9 @@
 	(void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_MASK);
 }
 
-static void mv64x60_mask_ack_gpp(unsigned int virq)
+static void mv64x60_mask_ack_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -178,9 +178,9 @@
 	(void)in_le32(mv64x60_gpp_reg_base + MV64x60_GPP_INTR_CAUSE);
 }
 
-static void mv64x60_unmask_gpp(unsigned int virq)
+static void mv64x60_unmask_gpp(struct irq_data *d)
 {
-	int level2 = irq_map[virq].hwirq & MV64x60_LEVEL2_MASK;
+	int level2 = irq_map[d->irq].hwirq & MV64x60_LEVEL2_MASK;
 	unsigned long flags;
 
 	spin_lock_irqsave(&mv64x60_lock, flags);
@@ -193,9 +193,9 @@
 
 static struct irq_chip mv64x60_chip_gpp = {
 	.name		= "mv64x60_gpp",
-	.mask		= mv64x60_mask_gpp,
-	.mask_ack	= mv64x60_mask_ack_gpp,
-	.unmask		= mv64x60_unmask_gpp,
+	.irq_mask	= mv64x60_mask_gpp,
+	.irq_mask_ack	= mv64x60_mask_ack_gpp,
+	.irq_unmask	= mv64x60_unmask_gpp,
 };
 
 /*
@@ -213,11 +213,12 @@
 {
 	int level1;
 
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
+	irq_set_status_flags(virq, IRQ_LEVEL);
 
 	level1 = (hwirq & MV64x60_LEVEL1_MASK) >> MV64x60_LEVEL1_OFFSET;
 	BUG_ON(level1 > MV64x60_LEVEL1_GPP);
-	set_irq_chip_and_handler(virq, mv64x60_chips[level1], handle_level_irq);
+	irq_set_chip_and_handler(virq, mv64x60_chips[level1],
+				 handle_level_irq);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/pmi.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/pmi.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/pmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/pmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,8 +121,7 @@
 	spin_unlock(&data->handler_spinlock);
 }
 
-static int pmi_of_probe(struct platform_device *dev,
-			const struct of_device_id *match)
+static int pmi_of_probe(struct platform_device *dev)
 {
 	struct device_node *np = dev->dev.of_node;
 	int rc;
@@ -205,7 +204,7 @@
 	return 0;
 }
 
-static struct of_platform_driver pmi_of_platform_driver = {
+static struct platform_driver pmi_of_platform_driver = {
 	.probe		= pmi_of_probe,
 	.remove		= pmi_of_remove,
 	.driver = {
@@ -217,13 +216,13 @@
 
 static int __init pmi_module_init(void)
 {
-	return of_register_platform_driver(&pmi_of_platform_driver);
+	return platform_driver_register(&pmi_of_platform_driver);
 }
 module_init(pmi_module_init);
 
 static void __exit pmi_module_exit(void)
 {
-	of_unregister_platform_driver(&pmi_of_platform_driver);
+	platform_driver_unregister(&pmi_of_platform_driver);
 }
 module_exit(pmi_module_exit);
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/ppc4xx_pci.h linux-libre-2.6.39-gnu/arch/powerpc/sysdev/ppc4xx_pci.h
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/ppc4xx_pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/ppc4xx_pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -324,7 +324,7 @@
 #define PESDR0_460EX_IHS2		0x036D
 
 /*
- * 460SX addtional DCRs
+ * 460SX additional DCRs
  */
 #define PESDRn_460SX_RCEI		0x02
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/qe_lib/qe.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/qe_lib/qe.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/qe_lib/qe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/qe_lib/qe.c	2011-05-19 00:06:34.000000000 -0400
@@ -659,8 +659,7 @@
 	return 0;
 }
 
-static int qe_probe(struct platform_device *ofdev,
-		    const struct of_device_id *id)
+static int qe_probe(struct platform_device *ofdev)
 {
 	return 0;
 }
@@ -670,7 +669,7 @@
 	{ },
 };
 
-static struct of_platform_driver qe_driver = {
+static struct platform_driver qe_driver = {
 	.driver = {
 		.name = "fsl-qe",
 		.owner = THIS_MODULE,
@@ -682,7 +681,7 @@
 
 static int __init qe_drv_init(void)
 {
-	return of_register_platform_driver(&qe_driver);
+	return platform_driver_register(&qe_driver);
 }
 device_initcall(qe_drv_init);
 #endif /* defined(CONFIG_SUSPEND) && defined(CONFIG_PPC_85xx) */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/qe_lib/qe_ic.c	2011-05-19 00:06:34.000000000 -0400
@@ -189,15 +189,20 @@
 
 static inline struct qe_ic *qe_ic_from_irq(unsigned int virq)
 {
-	return irq_to_desc(virq)->chip_data;
+	return irq_get_chip_data(virq);
+}
+
+static inline struct qe_ic *qe_ic_from_irq_data(struct irq_data *d)
+{
+	return irq_data_get_irq_chip_data(d);
 }
 
 #define virq_to_hw(virq)	((unsigned int)irq_map[virq].hwirq)
 
-static void qe_ic_unmask_irq(unsigned int virq)
+static void qe_ic_unmask_irq(struct irq_data *d)
 {
-	struct qe_ic *qe_ic = qe_ic_from_irq(virq);
-	unsigned int src = virq_to_hw(virq);
+	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
+	unsigned int src = virq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -210,10 +215,10 @@
 	raw_spin_unlock_irqrestore(&qe_ic_lock, flags);
 }
 
-static void qe_ic_mask_irq(unsigned int virq)
+static void qe_ic_mask_irq(struct irq_data *d)
 {
-	struct qe_ic *qe_ic = qe_ic_from_irq(virq);
-	unsigned int src = virq_to_hw(virq);
+	struct qe_ic *qe_ic = qe_ic_from_irq_data(d);
+	unsigned int src = virq_to_hw(d->irq);
 	unsigned long flags;
 	u32 temp;
 
@@ -238,9 +243,9 @@
 
 static struct irq_chip qe_ic_irq_chip = {
 	.name = "QEIC",
-	.unmask = qe_ic_unmask_irq,
-	.mask = qe_ic_mask_irq,
-	.mask_ack = qe_ic_mask_irq,
+	.irq_unmask = qe_ic_unmask_irq,
+	.irq_mask = qe_ic_mask_irq,
+	.irq_mask_ack = qe_ic_mask_irq,
 };
 
 static int qe_ic_host_match(struct irq_host *h, struct device_node *node)
@@ -262,10 +267,10 @@
 	/* Default chip */
 	chip = &qe_ic->hc_irq;
 
-	set_irq_chip_data(virq, qe_ic);
-	irq_to_desc(virq)->status |= IRQ_LEVEL;
+	irq_set_chip_data(virq, qe_ic);
+	irq_set_status_flags(virq, IRQ_LEVEL);
 
-	set_irq_chip_and_handler(virq, chip, handle_level_irq);
+	irq_set_chip_and_handler(virq, chip, handle_level_irq);
 
 	return 0;
 }
@@ -381,13 +386,13 @@
 
 	qe_ic_write(qe_ic->regs, QEIC_CICR, temp);
 
-	set_irq_data(qe_ic->virq_low, qe_ic);
-	set_irq_chained_handler(qe_ic->virq_low, low_handler);
+	irq_set_handler_data(qe_ic->virq_low, qe_ic);
+	irq_set_chained_handler(qe_ic->virq_low, low_handler);
 
 	if (qe_ic->virq_high != NO_IRQ &&
 			qe_ic->virq_high != qe_ic->virq_low) {
-		set_irq_data(qe_ic->virq_high, qe_ic);
-		set_irq_chained_handler(qe_ic->virq_high, high_handler);
+		irq_set_handler_data(qe_ic->virq_high, qe_ic);
+		irq_set_chained_handler(qe_ic->virq_high, high_handler);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/tsi108_pci.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/tsi108_pci.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/tsi108_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/tsi108_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -343,24 +343,9 @@
  * Linux descriptor level callbacks
  */
 
-static void tsi108_pci_irq_enable(u_int irq)
-{
-	tsi108_pci_int_unmask(irq);
-}
-
-static void tsi108_pci_irq_disable(u_int irq)
-{
-	tsi108_pci_int_mask(irq);
-}
-
-static void tsi108_pci_irq_ack(u_int irq)
-{
-	tsi108_pci_int_mask(irq);
-}
-
-static void tsi108_pci_irq_end(u_int irq)
+static void tsi108_pci_irq_unmask(struct irq_data *d)
 {
-	tsi108_pci_int_unmask(irq);
+	tsi108_pci_int_unmask(d->irq);
 
 	/* Enable interrupts from PCI block */
 	tsi108_write_reg(TSI108_PCI_OFFSET + TSI108_PCI_IRP_ENABLE,
@@ -370,16 +355,25 @@
 	mb();
 }
 
+static void tsi108_pci_irq_mask(struct irq_data *d)
+{
+	tsi108_pci_int_mask(d->irq);
+}
+
+static void tsi108_pci_irq_ack(struct irq_data *d)
+{
+	tsi108_pci_int_mask(d->irq);
+}
+
 /*
  * Interrupt controller descriptor for cascaded PCI interrupt controller.
  */
 
 static struct irq_chip tsi108_pci_irq = {
 	.name = "tsi108_PCI_int",
-	.mask = tsi108_pci_irq_disable,
-	.ack = tsi108_pci_irq_ack,
-	.end = tsi108_pci_irq_end,
-	.unmask = tsi108_pci_irq_enable,
+	.irq_mask = tsi108_pci_irq_mask,
+	.irq_ack = tsi108_pci_irq_ack,
+	.irq_unmask = tsi108_pci_irq_unmask,
 };
 
 static int pci_irq_host_xlate(struct irq_host *h, struct device_node *ct,
@@ -397,8 +391,8 @@
 	DBG("%s(%d, 0x%lx)\n", __func__, virq, hw);
 	if ((virq >= 1) && (virq <= 4)){
 		irq = virq + IRQ_PCI_INTAD_BASE - 1;
-		irq_to_desc(irq)->status |= IRQ_LEVEL;
-		set_irq_chip(irq, &tsi108_pci_irq);
+		irq_set_status_flags(irq, IRQ_LEVEL);
+		irq_set_chip(irq, &tsi108_pci_irq);
 	}
 	return 0;
 }
@@ -437,8 +431,11 @@
 
 void tsi108_irq_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(desc);
 	unsigned int cascade_irq = get_pci_source();
+
 	if (cascade_irq != NO_IRQ)
 		generic_handle_irq(cascade_irq);
-	desc->chip->eoi(irq);
+
+	chip->irq_eoi(&desc->irq_data);
 }
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/uic.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/uic.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/uic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/uic.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,18 +55,17 @@
 	struct irq_host	*irqhost;
 };
 
-static void uic_unmask_irq(unsigned int virq)
+static void uic_unmask_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 er, sr;
 
 	sr = 1 << (31-src);
 	spin_lock_irqsave(&uic->lock, flags);
 	/* ack level-triggered interrupts here */
-	if (desc->status & IRQ_LEVEL)
+	if (irqd_is_level_type(d))
 		mtdcr(uic->dcrbase + UIC_SR, sr);
 	er = mfdcr(uic->dcrbase + UIC_ER);
 	er |= sr;
@@ -74,10 +73,10 @@
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static void uic_mask_irq(unsigned int virq)
+static void uic_mask_irq(struct irq_data *d)
 {
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 er;
 
@@ -88,10 +87,10 @@
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static void uic_ack_irq(unsigned int virq)
+static void uic_ack_irq(struct irq_data *d)
 {
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 
 	spin_lock_irqsave(&uic->lock, flags);
@@ -99,11 +98,10 @@
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static void uic_mask_ack_irq(unsigned int virq)
+static void uic_mask_ack_irq(struct irq_data *d)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	u32 er, sr;
 
@@ -120,23 +118,22 @@
 	 * level interrupts are ack'ed after the actual
 	 * isr call in the uic_unmask_irq()
 	 */
-	if (!(desc->status & IRQ_LEVEL))
+	if (!irqd_is_level_type(d))
 		mtdcr(uic->dcrbase + UIC_SR, sr);
 	spin_unlock_irqrestore(&uic->lock, flags);
 }
 
-static int uic_set_irq_type(unsigned int virq, unsigned int flow_type)
+static int uic_set_irq_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct uic *uic = get_irq_chip_data(virq);
-	unsigned int src = uic_irq_to_hw(virq);
-	struct irq_desc *desc = irq_to_desc(virq);
+	struct uic *uic = irq_data_get_irq_chip_data(d);
+	unsigned int src = uic_irq_to_hw(d->irq);
 	unsigned long flags;
 	int trigger, polarity;
 	u32 tr, pr, mask;
 
 	switch (flow_type & IRQ_TYPE_SENSE_MASK) {
 	case IRQ_TYPE_NONE:
-		uic_mask_irq(virq);
+		uic_mask_irq(d);
 		return 0;
 
 	case IRQ_TYPE_EDGE_RISING:
@@ -166,11 +163,6 @@
 	mtdcr(uic->dcrbase + UIC_PR, pr);
 	mtdcr(uic->dcrbase + UIC_TR, tr);
 
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-	if (!trigger)
-		desc->status |= IRQ_LEVEL;
-
 	spin_unlock_irqrestore(&uic->lock, flags);
 
 	return 0;
@@ -178,11 +170,11 @@
 
 static struct irq_chip uic_irq_chip = {
 	.name		= "UIC",
-	.unmask		= uic_unmask_irq,
-	.mask		= uic_mask_irq,
- 	.mask_ack	= uic_mask_ack_irq,
-	.ack		= uic_ack_irq,
-	.set_type	= uic_set_irq_type,
+	.irq_unmask	= uic_unmask_irq,
+	.irq_mask	= uic_mask_irq,
+	.irq_mask_ack	= uic_mask_ack_irq,
+	.irq_ack	= uic_ack_irq,
+	.irq_set_type	= uic_set_irq_type,
 };
 
 static int uic_host_map(struct irq_host *h, unsigned int virq,
@@ -190,13 +182,13 @@
 {
 	struct uic *uic = h->host_data;
 
-	set_irq_chip_data(virq, uic);
+	irq_set_chip_data(virq, uic);
 	/* Despite the name, handle_level_irq() works for both level
 	 * and edge irqs on UIC.  FIXME: check this is correct */
-	set_irq_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
+	irq_set_chip_and_handler(virq, &uic_irq_chip, handle_level_irq);
 
 	/* Set default irq type */
-	set_irq_type(virq, IRQ_TYPE_NONE);
+	irq_set_irq_type(virq, IRQ_TYPE_NONE);
 
 	return 0;
 }
@@ -220,16 +212,18 @@
 
 void uic_irq_cascade(unsigned int virq, struct irq_desc *desc)
 {
-	struct uic *uic = get_irq_data(virq);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	struct irq_data *idata = irq_desc_get_irq_data(desc);
+	struct uic *uic = irq_get_handler_data(virq);
 	u32 msr;
 	int src;
 	int subvirq;
 
 	raw_spin_lock(&desc->lock);
-	if (desc->status & IRQ_LEVEL)
-		desc->chip->mask(virq);
+	if (irqd_is_level_type(idata))
+		chip->irq_mask(idata);
 	else
-		desc->chip->mask_ack(virq);
+		chip->irq_mask_ack(idata);
 	raw_spin_unlock(&desc->lock);
 
 	msr = mfdcr(uic->dcrbase + UIC_MSR);
@@ -243,10 +237,10 @@
 
 uic_irq_ret:
 	raw_spin_lock(&desc->lock);
-	if (desc->status & IRQ_LEVEL)
-		desc->chip->ack(virq);
-	if (!(desc->status & IRQ_DISABLED) && desc->chip->unmask)
-		desc->chip->unmask(virq);
+	if (irqd_is_level_type(idata))
+		chip->irq_ack(idata);
+	if (!irqd_irq_disabled(idata) && chip->irq_unmask)
+		chip->irq_unmask(idata);
 	raw_spin_unlock(&desc->lock);
 }
 
@@ -335,8 +329,8 @@
 
 			cascade_virq = irq_of_parse_and_map(np, 0);
 
-			set_irq_data(cascade_virq, uic);
-			set_irq_chained_handler(cascade_virq, uic_irq_cascade);
+			irq_set_handler_data(cascade_virq, uic);
+			irq_set_chained_handler(cascade_virq, uic_irq_cascade);
 
 			/* FIXME: setup critical cascade?? */
 		}
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/sysdev/xilinx_intc.c linux-libre-2.6.39-gnu/arch/powerpc/sysdev/xilinx_intc.c
--- linux-libre-2.6.38-gnu/arch/powerpc/sysdev/xilinx_intc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/sysdev/xilinx_intc.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,32 +69,26 @@
  *
  * IRQ Chip common (across level and edge) operations
  */
-static void xilinx_intc_mask(unsigned int virq)
+static void xilinx_intc_mask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void * regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("mask: %d\n", irq);
 	out_be32(regs + XINTC_CIE, 1 << irq);
 }
 
-static int xilinx_intc_set_type(unsigned int virq, unsigned int flow_type)
+static int xilinx_intc_set_type(struct irq_data *d, unsigned int flow_type)
 {
-	struct irq_desc *desc = irq_to_desc(virq);
-
-	desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
-	desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
-	if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
-		desc->status |= IRQ_LEVEL;
 	return 0;
 }
 
 /*
  * IRQ Chip level operations
  */
-static void xilinx_intc_level_unmask(unsigned int virq)
+static void xilinx_intc_level_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void * regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("unmask: %d\n", irq);
 	out_be32(regs + XINTC_SIE, 1 << irq);
 
@@ -107,37 +101,37 @@
 
 static struct irq_chip xilinx_intc_level_irqchip = {
 	.name = "Xilinx Level INTC",
-	.mask = xilinx_intc_mask,
-	.mask_ack = xilinx_intc_mask,
-	.unmask = xilinx_intc_level_unmask,
-	.set_type = xilinx_intc_set_type,
+	.irq_mask = xilinx_intc_mask,
+	.irq_mask_ack = xilinx_intc_mask,
+	.irq_unmask = xilinx_intc_level_unmask,
+	.irq_set_type = xilinx_intc_set_type,
 };
 
 /*
  * IRQ Chip edge operations
  */
-static void xilinx_intc_edge_unmask(unsigned int virq)
+static void xilinx_intc_edge_unmask(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void *regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void *regs = irq_data_get_irq_chip_data(d);
 	pr_debug("unmask: %d\n", irq);
 	out_be32(regs + XINTC_SIE, 1 << irq);
 }
 
-static void xilinx_intc_edge_ack(unsigned int virq)
+static void xilinx_intc_edge_ack(struct irq_data *d)
 {
-	int irq = virq_to_hw(virq);
-	void * regs = get_irq_chip_data(virq);
+	int irq = virq_to_hw(d->irq);
+	void * regs = irq_data_get_irq_chip_data(d);
 	pr_debug("ack: %d\n", irq);
 	out_be32(regs + XINTC_IAR, 1 << irq);
 }
 
 static struct irq_chip xilinx_intc_edge_irqchip = {
 	.name = "Xilinx Edge  INTC",
-	.mask = xilinx_intc_mask,
-	.unmask = xilinx_intc_edge_unmask,
-	.ack = xilinx_intc_edge_ack,
-	.set_type = xilinx_intc_set_type,
+	.irq_mask = xilinx_intc_mask,
+	.irq_unmask = xilinx_intc_edge_unmask,
+	.irq_ack = xilinx_intc_edge_ack,
+	.irq_set_type = xilinx_intc_set_type,
 };
 
 /*
@@ -170,15 +164,15 @@
 static int xilinx_intc_map(struct irq_host *h, unsigned int virq,
 				  irq_hw_number_t irq)
 {
-	set_irq_chip_data(virq, h->host_data);
+	irq_set_chip_data(virq, h->host_data);
 
 	if (xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_HIGH ||
 	    xilinx_intc_typetable[irq] == IRQ_TYPE_LEVEL_LOW) {
-		set_irq_chip_and_handler(virq, &xilinx_intc_level_irqchip,
-			handle_level_irq);
+		irq_set_chip_and_handler(virq, &xilinx_intc_level_irqchip,
+					 handle_level_irq);
 	} else {
-		set_irq_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
-			handle_edge_irq);
+		irq_set_chip_and_handler(virq, &xilinx_intc_edge_irqchip,
+					 handle_edge_irq);
 	}
 	return 0;
 }
@@ -229,12 +223,14 @@
  */
 static void xilinx_i8259_cascade(unsigned int irq, struct irq_desc *desc)
 {
+	struct irq_chip *chip = irq_desc_get_chip(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);
+	chip->irq_unmask(&desc->irq_data);
 }
 
 static void __init xilinx_i8259_setup_cascade(void)
@@ -254,7 +250,7 @@
 	}
 
 	i8259_init(cascade_node, 0);
-	set_irq_chained_handler(cascade_irq, xilinx_i8259_cascade);
+	irq_set_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 */
diff -druN linux-libre-2.6.38-gnu/arch/powerpc/xmon/xmon.c linux-libre-2.6.39-gnu/arch/powerpc/xmon/xmon.c
--- linux-libre-2.6.38-gnu/arch/powerpc/xmon/xmon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/powerpc/xmon/xmon.c	2011-05-19 00:06:34.000000000 -0400
@@ -821,7 +821,7 @@
 				memzcan();
 				break;
 			case 'i':
-				show_mem();
+				show_mem(0);
 				break;
 			default:
 				termch = cmd;
diff -druN linux-libre-2.6.38-gnu/arch/s390/boot/compressed/Makefile linux-libre-2.6.39-gnu/arch/s390/boot/compressed/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/boot/compressed/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,8 @@
 BITS := $(if $(CONFIG_64BIT),64,31)
 
 targets	:= vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 \
-	   vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o sizes.h head$(BITS).o
+	   vmlinux.bin.xz vmlinux.bin.lzma vmlinux.bin.lzo misc.o piggy.o \
+	   sizes.h head$(BITS).o
 
 KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2
 KBUILD_CFLAGS += $(cflags-y)
@@ -48,6 +49,7 @@
 suffix-$(CONFIG_KERNEL_BZIP2) := bz2
 suffix-$(CONFIG_KERNEL_LZMA)  := lzma
 suffix-$(CONFIG_KERNEL_LZO)  := lzo
+suffix-$(CONFIG_KERNEL_XZ)  := xz
 
 $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y)
 	$(call if_changed,gzip)
@@ -57,6 +59,8 @@
 	$(call if_changed,lzma)
 $(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y)
 	$(call if_changed,lzo)
+$(obj)/vmlinux.bin.xz: $(vmlinux.bin.all-y)
+	$(call if_changed,xzkern)
 
 LDFLAGS_piggy.o := -r --format binary --oformat $(LD_BFD) -T
 $(obj)/piggy.o: $(obj)/vmlinux.scr $(obj)/vmlinux.bin.$(suffix-y)
diff -druN linux-libre-2.6.38-gnu/arch/s390/boot/compressed/misc.c linux-libre-2.6.39-gnu/arch/s390/boot/compressed/misc.c
--- linux-libre-2.6.38-gnu/arch/s390/boot/compressed/misc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/boot/compressed/misc.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,7 @@
 #undef memset
 #undef memcpy
 #undef memmove
+#define memmove memmove
 #define memzero(s, n) memset((s), 0, (n))
 
 /* Symbols defined by linker scripts */
@@ -54,6 +55,10 @@
 #include "../../../../lib/decompress_unlzo.c"
 #endif
 
+#ifdef CONFIG_KERNEL_XZ
+#include "../../../../lib/decompress_unxz.c"
+#endif
+
 extern _sclp_print_early(const char *);
 
 int puts(const char *s)
diff -druN linux-libre-2.6.38-gnu/arch/s390/boot/Makefile linux-libre-2.6.39-gnu/arch/s390/boot/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/boot/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 			tr -c '[0-9A-Za-z]' '_'`__`date | \
 			tr -c '[0-9A-Za-z]' '_'`_t
 
-EXTRA_CFLAGS  := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
+ccflags-y  := -DCOMPILE_VERSION=$(COMPILE_VERSION) -gstabs -I.
 
 targets := image
 targets += bzImage
diff -druN linux-libre-2.6.38-gnu/arch/s390/crypto/prng.c linux-libre-2.6.39-gnu/arch/s390/crypto/prng.c
--- linux-libre-2.6.38-gnu/arch/s390/crypto/prng.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/crypto/prng.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
 
 	/* Add the entropy */
 	while (nbytes >= 8) {
-		*((__u64 *)parm_block) ^= *((__u64 *)buf+i*8);
+		*((__u64 *)parm_block) ^= *((__u64 *)(buf+i));
 		prng_add_entropy();
 		i += 8;
 		nbytes -= 8;
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/atomic.h linux-libre-2.6.39-gnu/arch/s390/include/asm/atomic.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/atomic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/atomic.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
  *
  * Atomic operations that C can't guarantee us.
  * Useful for resource counting etc.
- * s390 uses 'Compare And Swap' for atomicity in SMP enviroment.
+ * s390 uses 'Compare And Swap' for atomicity in SMP environment.
  *
  */
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/s390/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -742,18 +742,42 @@
  *    23 22 21 20 19 18 17 16 31 30 29 28 27 26 25 24
  */
 
-#define ext2_set_bit(nr, addr)       \
-	__test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
-#define ext2_set_bit_atomic(lock, nr, addr)       \
-	test_and_set_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
-#define ext2_clear_bit(nr, addr)     \
-	__test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
-#define ext2_clear_bit_atomic(lock, nr, addr)     \
-	test_and_clear_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
-#define ext2_test_bit(nr, addr)      \
-	test_bit((nr)^(__BITOPS_WORDSIZE - 8), (unsigned long *)addr)
+static inline void __set_bit_le(unsigned long nr, void *addr)
+{
+	__set_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
 
-static inline int ext2_find_first_zero_bit(void *vaddr, unsigned int size)
+static inline void __clear_bit_le(unsigned long nr, void *addr)
+{
+	__clear_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
+
+static inline int __test_and_set_bit_le(unsigned long nr, void *addr)
+{
+	return __test_and_set_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
+
+static inline int test_and_set_bit_le(unsigned long nr, void *addr)
+{
+	return test_and_set_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
+
+static inline int __test_and_clear_bit_le(unsigned long nr, void *addr)
+{
+	return __test_and_clear_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
+
+static inline int test_and_clear_bit_le(unsigned long nr, void *addr)
+{
+	return test_and_clear_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
+
+static inline int test_bit_le(unsigned long nr, const void *addr)
+{
+	return test_bit(nr ^ (__BITOPS_WORDSIZE - 8), addr);
+}
+
+static inline int find_first_zero_bit_le(void *vaddr, unsigned int size)
 {
 	unsigned long bytes, bits;
 
@@ -764,7 +788,7 @@
 	return (bits < size) ? bits : size;
 }
 
-static inline int ext2_find_next_zero_bit(void *vaddr, unsigned long size,
+static inline int find_next_zero_bit_le(void *vaddr, unsigned long size,
 					  unsigned long offset)
 {
         unsigned long *addr = vaddr, *p;
@@ -790,11 +814,10 @@
 		size -= __BITOPS_WORDSIZE;
 		p++;
         }
-	return offset + ext2_find_first_zero_bit(p, size);
+	return offset + find_first_zero_bit_le(p, size);
 }
 
-static inline unsigned long ext2_find_first_bit(void *vaddr,
-						unsigned long size)
+static inline unsigned long find_first_bit_le(void *vaddr, unsigned long size)
 {
 	unsigned long bytes, bits;
 
@@ -805,7 +828,7 @@
 	return (bits < size) ? bits : size;
 }
 
-static inline int ext2_find_next_bit(void *vaddr, unsigned long size,
+static inline int find_next_bit_le(void *vaddr, unsigned long size,
 				     unsigned long offset)
 {
 	unsigned long *addr = vaddr, *p;
@@ -831,10 +854,14 @@
 		size -= __BITOPS_WORDSIZE;
 		p++;
 	}
-	return offset + ext2_find_first_bit(p, size);
+	return offset + find_first_bit_le(p, size);
 }
 
-#include <asm-generic/bitops/minix.h>
+#define ext2_set_bit_atomic(lock, nr, addr)	\
+	test_and_set_bit_le(nr, addr)
+#define ext2_clear_bit_atomic(lock, nr, addr)	\
+	test_and_clear_bit_le(nr, addr)
+
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/s390/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,4 +8,8 @@
 void kernel_map_pages(struct page *page, int numpages, int enable);
 #endif
 
+int set_memory_ro(unsigned long addr, int numpages);
+int set_memory_rw(unsigned long addr, int numpages);
+int set_memory_nx(unsigned long addr, int numpages);
+
 #endif /* _S390_CACHEFLUSH_H */
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/ccwdev.h linux-libre-2.6.39-gnu/arch/s390/include/asm/ccwdev.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/ccwdev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/ccwdev.h	2011-05-19 00:06:34.000000000 -0400
@@ -112,7 +112,6 @@
 
 /**
  * struct ccw driver - device driver for channel attached devices
- * @owner: owning module
  * @ids: ids supported by this driver
  * @probe: function called on probe
  * @remove: function called on remove
@@ -128,10 +127,8 @@
  * @restore: callback for restoring after hibernation
  * @uc_handler: callback for unit check handler
  * @driver: embedded device driver structure
- * @name: device driver name
  */
 struct ccw_driver {
-	struct module *owner;
 	struct ccw_device_id *ids;
 	int (*probe) (struct ccw_device *);
 	void (*remove) (struct ccw_device *);
@@ -147,7 +144,6 @@
 	int (*restore)(struct ccw_device *);
 	enum uc_todo (*uc_handler) (struct ccw_device *, struct irb *);
 	struct device_driver driver;
-	char *name;
 };
 
 extern struct ccw_device *get_ccwdev_by_busid(struct ccw_driver *cdrv,
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/ccwgroup.h linux-libre-2.6.39-gnu/arch/s390/include/asm/ccwgroup.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/ccwgroup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/ccwgroup.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,8 +29,6 @@
 
 /**
  * struct ccwgroup_driver - driver for ccw group devices
- * @owner: driver owner
- * @name: driver name
  * @max_slaves: maximum number of slave devices
  * @driver_id: unique id
  * @probe: function called on probe
@@ -46,8 +44,6 @@
  * @driver: embedded driver structure
  */
 struct ccwgroup_driver {
-	struct module *owner;
-	char *name;
 	int max_slaves;
 	unsigned long driver_id;
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/cio.h linux-libre-2.6.39-gnu/arch/s390/include/asm/cio.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/cio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/cio.h	2011-05-19 00:06:34.000000000 -0400
@@ -183,7 +183,7 @@
  * The irb that is handed to the device driver when an interrupt occurs. For
  * solicited interrupts, the common I/O layer already performs checks whether
  * a field is valid; a field not being valid is always passed as %0.
- * If a unit check occured, @ecw may contain sense data; this is retrieved
+ * If a unit check occurred, @ecw may contain sense data; this is retrieved
  * by the common I/O layer itself if the device doesn't support concurrent
  * sense (so that the device driver never needs to perform basic sene itself).
  * For unsolicited interrupts, the irb is passed as-is (expect for sense data,
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/cmpxchg.h linux-libre-2.6.39-gnu/arch/s390/include/asm/cmpxchg.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/cmpxchg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/cmpxchg.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,225 @@
+/*
+ * Copyright IBM Corp. 1999, 2011
+ *
+ * Author(s): Martin Schwidefsky <schwidefsky@de.ibm.com>,
+ */
+
+#ifndef __ASM_CMPXCHG_H
+#define __ASM_CMPXCHG_H
+
+#include <linux/types.h>
+
+extern void __xchg_called_with_bad_pointer(void);
+
+static inline unsigned long __xchg(unsigned long x, void *ptr, int size)
+{
+	unsigned long addr, old;
+	int shift;
+
+	switch (size) {
+	case 1:
+		addr = (unsigned long) ptr;
+		shift = (3 ^ (addr & 3)) << 3;
+		addr ^= addr & 3;
+		asm volatile(
+			"	l	%0,%4\n"
+			"0:	lr	0,%0\n"
+			"	nr	0,%3\n"
+			"	or	0,%2\n"
+			"	cs	%0,0,%4\n"
+			"	jl	0b\n"
+			: "=&d" (old), "=Q" (*(int *) addr)
+			: "d" (x << shift), "d" (~(255 << shift)),
+			  "Q" (*(int *) addr) : "memory", "cc", "0");
+		return old >> shift;
+	case 2:
+		addr = (unsigned long) ptr;
+		shift = (2 ^ (addr & 2)) << 3;
+		addr ^= addr & 2;
+		asm volatile(
+			"	l	%0,%4\n"
+			"0:	lr	0,%0\n"
+			"	nr	0,%3\n"
+			"	or	0,%2\n"
+			"	cs	%0,0,%4\n"
+			"	jl	0b\n"
+			: "=&d" (old), "=Q" (*(int *) addr)
+			: "d" (x << shift), "d" (~(65535 << shift)),
+			  "Q" (*(int *) addr) : "memory", "cc", "0");
+		return old >> shift;
+	case 4:
+		asm volatile(
+			"	l	%0,%3\n"
+			"0:	cs	%0,%2,%3\n"
+			"	jl	0b\n"
+			: "=&d" (old), "=Q" (*(int *) ptr)
+			: "d" (x), "Q" (*(int *) ptr)
+			: "memory", "cc");
+		return old;
+#ifdef CONFIG_64BIT
+	case 8:
+		asm volatile(
+			"	lg	%0,%3\n"
+			"0:	csg	%0,%2,%3\n"
+			"	jl	0b\n"
+			: "=&d" (old), "=m" (*(long *) ptr)
+			: "d" (x), "Q" (*(long *) ptr)
+			: "memory", "cc");
+		return old;
+#endif /* CONFIG_64BIT */
+	}
+	__xchg_called_with_bad_pointer();
+	return x;
+}
+
+#define xchg(ptr, x)							  \
+({									  \
+	__typeof__(*(ptr)) __ret;					  \
+	__ret = (__typeof__(*(ptr)))					  \
+		__xchg((unsigned long)(x), (void *)(ptr), sizeof(*(ptr)));\
+	__ret;								  \
+})
+
+/*
+ * Atomic compare and exchange.	 Compare OLD with MEM, if identical,
+ * store NEW in MEM.  Return the initial value in MEM.	Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+#define __HAVE_ARCH_CMPXCHG
+
+extern void __cmpxchg_called_with_bad_pointer(void);
+
+static inline unsigned long __cmpxchg(void *ptr, unsigned long old,
+				      unsigned long new, int size)
+{
+	unsigned long addr, prev, tmp;
+	int shift;
+
+	switch (size) {
+	case 1:
+		addr = (unsigned long) ptr;
+		shift = (3 ^ (addr & 3)) << 3;
+		addr ^= addr & 3;
+		asm volatile(
+			"	l	%0,%2\n"
+			"0:	nr	%0,%5\n"
+			"	lr	%1,%0\n"
+			"	or	%0,%3\n"
+			"	or	%1,%4\n"
+			"	cs	%0,%1,%2\n"
+			"	jnl	1f\n"
+			"	xr	%1,%0\n"
+			"	nr	%1,%5\n"
+			"	jnz	0b\n"
+			"1:"
+			: "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
+			: "d" (old << shift), "d" (new << shift),
+			  "d" (~(255 << shift)), "Q" (*(int *) ptr)
+			: "memory", "cc");
+		return prev >> shift;
+	case 2:
+		addr = (unsigned long) ptr;
+		shift = (2 ^ (addr & 2)) << 3;
+		addr ^= addr & 2;
+		asm volatile(
+			"	l	%0,%2\n"
+			"0:	nr	%0,%5\n"
+			"	lr	%1,%0\n"
+			"	or	%0,%3\n"
+			"	or	%1,%4\n"
+			"	cs	%0,%1,%2\n"
+			"	jnl	1f\n"
+			"	xr	%1,%0\n"
+			"	nr	%1,%5\n"
+			"	jnz	0b\n"
+			"1:"
+			: "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
+			: "d" (old << shift), "d" (new << shift),
+			  "d" (~(65535 << shift)), "Q" (*(int *) ptr)
+			: "memory", "cc");
+		return prev >> shift;
+	case 4:
+		asm volatile(
+			"	cs	%0,%3,%1\n"
+			: "=&d" (prev), "=Q" (*(int *) ptr)
+			: "0" (old), "d" (new), "Q" (*(int *) ptr)
+			: "memory", "cc");
+		return prev;
+#ifdef CONFIG_64BIT
+	case 8:
+		asm volatile(
+			"	csg	%0,%3,%1\n"
+			: "=&d" (prev), "=Q" (*(long *) ptr)
+			: "0" (old), "d" (new), "Q" (*(long *) ptr)
+			: "memory", "cc");
+		return prev;
+#endif /* CONFIG_64BIT */
+	}
+	__cmpxchg_called_with_bad_pointer();
+	return old;
+}
+
+#define cmpxchg(ptr, o, n)						\
+	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	\
+				       (unsigned long)(n), sizeof(*(ptr))))
+
+#ifdef CONFIG_64BIT
+#define cmpxchg64(ptr, o, n)						\
+({									\
+	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
+	cmpxchg((ptr), (o), (n));					\
+})
+#else /* CONFIG_64BIT */
+static inline unsigned long long __cmpxchg64(void *ptr,
+					     unsigned long long old,
+					     unsigned long long new)
+{
+	register_pair rp_old = {.pair = old};
+	register_pair rp_new = {.pair = new};
+
+	asm volatile(
+		"	cds	%0,%2,%1"
+		: "+&d" (rp_old), "=Q" (ptr)
+		: "d" (rp_new), "Q" (ptr)
+		: "cc");
+	return rp_old.pair;
+}
+#define cmpxchg64(ptr, o, n)						\
+	((__typeof__(*(ptr)))__cmpxchg64((ptr),				\
+					 (unsigned long long)(o),	\
+					 (unsigned long long)(n)))
+#endif /* CONFIG_64BIT */
+
+#include <asm-generic/cmpxchg-local.h>
+
+static inline unsigned long __cmpxchg_local(void *ptr,
+					    unsigned long old,
+					    unsigned long new, int size)
+{
+	switch (size) {
+	case 1:
+	case 2:
+	case 4:
+#ifdef CONFIG_64BIT
+	case 8:
+#endif
+		return __cmpxchg(ptr, old, new, size);
+	default:
+		return __cmpxchg_local_generic(ptr, old, new, size);
+	}
+
+	return old;
+}
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)					\
+	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\
+			(unsigned long)(n), sizeof(*(ptr))))
+
+#define cmpxchg64_local(ptr, o, n)	cmpxchg64((ptr), (o), (n))
+
+#endif /* __ASM_CMPXCHG_H */
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/diag.h linux-libre-2.6.39-gnu/arch/s390/include/asm/diag.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/diag.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/diag.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,9 +9,22 @@
 #define _ASM_S390_DIAG_H
 
 /*
- * Diagnose 10: Release pages
+ * Diagnose 10: Release page range
  */
-extern void diag10(unsigned long addr);
+static inline void diag10_range(unsigned long start_pfn, unsigned long num_pfn)
+{
+	unsigned long start_addr, end_addr;
+
+	start_addr = start_pfn << PAGE_SHIFT;
+	end_addr = (start_pfn + num_pfn - 1) << PAGE_SHIFT;
+
+	asm volatile(
+		"0:	diag	%0,%1,0x10\n"
+		"1:\n"
+		EX_TABLE(0b, 1b)
+		EX_TABLE(1b, 1b)
+		: : "a" (start_addr), "a" (end_addr));
+}
 
 /*
  * Diagnose 14: Input spool file manipulation
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/futex.h linux-libre-2.6.39-gnu/arch/s390/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 #include <linux/uaccess.h>
 #include <asm/errno.h>
 
-static inline int futex_atomic_op_inuser (int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser (int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -18,7 +18,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -39,13 +39,13 @@
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr,
-						int oldval, int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
-	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(int)))
+	if (! access_ok (VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	return uaccess.futex_atomic_cmpxchg(uaddr, oldval, newval);
+	return uaccess.futex_atomic_cmpxchg(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/mmu_context.h linux-libre-2.6.39-gnu/arch/s390/include/asm/mmu_context.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/mmu_context.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/mmu_context.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 #ifdef CONFIG_64BIT
 	mm->context.asce_bits |= _ASCE_TYPE_REGION3;
 #endif
-	if (current->mm->context.alloc_pgste) {
+	if (current->mm && current->mm->context.alloc_pgste) {
 		/*
 		 * alloc_pgste indicates, that any NEW context will be created
 		 * with extended page tables. The old context is unchanged. The
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/s390/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,29 +43,6 @@
 
 #ifdef __KERNEL__
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-struct rwsem_waiter;
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *);
-extern struct rw_semaphore *rwsem_downgrade_write(struct rw_semaphore *);
-
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	signed long		count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
 #ifndef __s390x__
 #define RWSEM_UNLOCKED_VALUE	0x00000000
 #define RWSEM_ACTIVE_BIAS	0x00000001
@@ -81,41 +58,6 @@
 #define RWSEM_ACTIVE_WRITE_BIAS	(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
 /*
- * initialisation
- */
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
- { RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait.lock), \
-   LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)				\
-do {						\
-	static struct lock_class_key __key;	\
-						\
-	__init_rwsem((sem), #sem, &__key);	\
-} while (0)
-
-
-/*
  * lock for reading
  */
 static inline void __down_read(struct rw_semaphore *sem)
@@ -377,10 +319,5 @@
 	return new;
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _S390_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/system.h linux-libre-2.6.39-gnu/arch/s390/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
 #include <asm/setup.h>
 #include <asm/processor.h>
 #include <asm/lowcore.h>
+#include <asm/cmpxchg.h>
 
 #ifdef __KERNEL__
 
@@ -120,161 +121,6 @@
 
 #define nop() asm volatile("nop")
 
-#define xchg(ptr,x)							  \
-({									  \
-	__typeof__(*(ptr)) __ret;					  \
-	__ret = (__typeof__(*(ptr)))					  \
-		__xchg((unsigned long)(x), (void *)(ptr),sizeof(*(ptr))); \
-	__ret;								  \
-})
-
-extern void __xchg_called_with_bad_pointer(void);
-
-static inline unsigned long __xchg(unsigned long x, void * ptr, int size)
-{
-	unsigned long addr, old;
-	int shift;
-
-        switch (size) {
-	case 1:
-		addr = (unsigned long) ptr;
-		shift = (3 ^ (addr & 3)) << 3;
-		addr ^= addr & 3;
-		asm volatile(
-			"	l	%0,%4\n"
-			"0:	lr	0,%0\n"
-			"	nr	0,%3\n"
-			"	or	0,%2\n"
-			"	cs	%0,0,%4\n"
-			"	jl	0b\n"
-			: "=&d" (old), "=Q" (*(int *) addr)
-			: "d" (x << shift), "d" (~(255 << shift)),
-			  "Q" (*(int *) addr) : "memory", "cc", "0");
-		return old >> shift;
-	case 2:
-		addr = (unsigned long) ptr;
-		shift = (2 ^ (addr & 2)) << 3;
-		addr ^= addr & 2;
-		asm volatile(
-			"	l	%0,%4\n"
-			"0:	lr	0,%0\n"
-			"	nr	0,%3\n"
-			"	or	0,%2\n"
-			"	cs	%0,0,%4\n"
-			"	jl	0b\n"
-			: "=&d" (old), "=Q" (*(int *) addr)
-			: "d" (x << shift), "d" (~(65535 << shift)),
-			  "Q" (*(int *) addr) : "memory", "cc", "0");
-		return old >> shift;
-	case 4:
-		asm volatile(
-			"	l	%0,%3\n"
-			"0:	cs	%0,%2,%3\n"
-			"	jl	0b\n"
-			: "=&d" (old), "=Q" (*(int *) ptr)
-			: "d" (x), "Q" (*(int *) ptr)
-			: "memory", "cc");
-		return old;
-#ifdef __s390x__
-	case 8:
-		asm volatile(
-			"	lg	%0,%3\n"
-			"0:	csg	%0,%2,%3\n"
-			"	jl	0b\n"
-			: "=&d" (old), "=m" (*(long *) ptr)
-			: "d" (x), "Q" (*(long *) ptr)
-			: "memory", "cc");
-		return old;
-#endif /* __s390x__ */
-	}
-	__xchg_called_with_bad_pointer();
-	return x;
-}
-
-/*
- * Atomic compare and exchange.  Compare OLD with MEM, if identical,
- * store NEW in MEM.  Return the initial value in MEM.  Success is
- * indicated by comparing RETURN with OLD.
- */
-
-#define __HAVE_ARCH_CMPXCHG 1
-
-#define cmpxchg(ptr, o, n)						\
-	((__typeof__(*(ptr)))__cmpxchg((ptr), (unsigned long)(o),	\
-					(unsigned long)(n), sizeof(*(ptr))))
-
-extern void __cmpxchg_called_with_bad_pointer(void);
-
-static inline unsigned long
-__cmpxchg(volatile void *ptr, unsigned long old, unsigned long new, int size)
-{
-	unsigned long addr, prev, tmp;
-	int shift;
-
-        switch (size) {
-	case 1:
-		addr = (unsigned long) ptr;
-		shift = (3 ^ (addr & 3)) << 3;
-		addr ^= addr & 3;
-		asm volatile(
-			"	l	%0,%2\n"
-			"0:	nr	%0,%5\n"
-			"	lr	%1,%0\n"
-			"	or	%0,%3\n"
-			"	or	%1,%4\n"
-			"	cs	%0,%1,%2\n"
-			"	jnl	1f\n"
-			"	xr	%1,%0\n"
-			"	nr	%1,%5\n"
-			"	jnz	0b\n"
-			"1:"
-			: "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
-			: "d" (old << shift), "d" (new << shift),
-			  "d" (~(255 << shift)), "Q" (*(int *) ptr)
-			: "memory", "cc");
-		return prev >> shift;
-	case 2:
-		addr = (unsigned long) ptr;
-		shift = (2 ^ (addr & 2)) << 3;
-		addr ^= addr & 2;
-		asm volatile(
-			"	l	%0,%2\n"
-			"0:	nr	%0,%5\n"
-			"	lr	%1,%0\n"
-			"	or	%0,%3\n"
-			"	or	%1,%4\n"
-			"	cs	%0,%1,%2\n"
-			"	jnl	1f\n"
-			"	xr	%1,%0\n"
-			"	nr	%1,%5\n"
-			"	jnz	0b\n"
-			"1:"
-			: "=&d" (prev), "=&d" (tmp), "=Q" (*(int *) ptr)
-			: "d" (old << shift), "d" (new << shift),
-			  "d" (~(65535 << shift)), "Q" (*(int *) ptr)
-			: "memory", "cc");
-		return prev >> shift;
-	case 4:
-		asm volatile(
-			"	cs	%0,%3,%1\n"
-			: "=&d" (prev), "=Q" (*(int *) ptr)
-			: "0" (old), "d" (new), "Q" (*(int *) ptr)
-			: "memory", "cc");
-		return prev;
-#ifdef __s390x__
-	case 8:
-		asm volatile(
-			"	csg	%0,%3,%1\n"
-			: "=&d" (prev), "=Q" (*(long *) ptr)
-			: "0" (old), "d" (new), "Q" (*(long *) ptr)
-			: "memory", "cc");
-		return prev;
-#endif /* __s390x__ */
-        }
-	__cmpxchg_called_with_bad_pointer();
-	return old;
-}
-
 /*
  * Force strict CPU ordering.
  * And yes, this is required on UP too when we're talking
@@ -353,46 +199,6 @@
 	__ctl_load(__dummy, cr, cr);	\
 })
 
-#include <linux/irqflags.h>
-
-#include <asm-generic/cmpxchg-local.h>
-
-static inline unsigned long __cmpxchg_local(volatile void *ptr,
-				      unsigned long old,
-				      unsigned long new, int size)
-{
-	switch (size) {
-	case 1:
-	case 2:
-	case 4:
-#ifdef __s390x__
-	case 8:
-#endif
-		return __cmpxchg(ptr, old, new, size);
-	default:
-		return __cmpxchg_local_generic(ptr, old, new, size);
-	}
-
-	return old;
-}
-
-/*
- * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
- * them available.
- */
-#define cmpxchg_local(ptr, o, n)					\
-	((__typeof__(*(ptr)))__cmpxchg_local((ptr), (unsigned long)(o),	\
-			(unsigned long)(n), sizeof(*(ptr))))
-#ifdef __s390x__
-#define cmpxchg64_local(ptr, o, n)					\
-  ({									\
-	BUILD_BUG_ON(sizeof(*(ptr)) != 8);				\
-	cmpxchg_local((ptr), (o), (n));					\
-  })
-#else
-#define cmpxchg64_local(ptr, o, n) __cmpxchg64_local_generic((ptr), (o), (n))
-#endif
-
 /*
  * Use to set psw mask except for the first byte which
  * won't be changed by this function.
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/types.h linux-libre-2.6.39-gnu/arch/s390/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,14 +30,6 @@
 
 #ifndef __ASSEMBLY__
 
-typedef u64 dma64_addr_t;
-#ifdef __s390x__
-/* DMA addresses come in 32-bit and 64-bit flavours. */
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
-
 #ifndef __s390x__
 typedef union {
 	unsigned long long pair;
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/uaccess.h linux-libre-2.6.39-gnu/arch/s390/include/asm/uaccess.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/uaccess.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/uaccess.h	2011-05-19 00:06:34.000000000 -0400
@@ -83,8 +83,8 @@
 	size_t (*clear_user)(size_t, void __user *);
 	size_t (*strnlen_user)(size_t, const char __user *);
 	size_t (*strncpy_from_user)(size_t, const char __user *, char *);
-	int (*futex_atomic_op)(int op, int __user *, int oparg, int *old);
-	int (*futex_atomic_cmpxchg)(int __user *, int old, int new);
+	int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old);
+	int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new);
 };
 
 extern struct uaccess_ops uaccess;
diff -druN linux-libre-2.6.38-gnu/arch/s390/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/s390/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/s390/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -272,7 +272,11 @@
 #define __NR_fanotify_init	332
 #define __NR_fanotify_mark	333
 #define __NR_prlimit64		334
-#define NR_syscalls 335
+#define __NR_name_to_handle_at	335
+#define __NR_open_by_handle_at	336
+#define __NR_clock_adjtime	337
+#define __NR_syncfs		338
+#define NR_syscalls 339
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff -druN linux-libre-2.6.38-gnu/arch/s390/Kconfig linux-libre-2.6.39-gnu/arch/s390/Kconfig
--- linux-libre-2.6.38-gnu/arch/s390/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 	select HAVE_KERNEL_BZIP2
 	select HAVE_KERNEL_LZMA
 	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_XZ
 	select HAVE_GET_USER_PAGES_FAST
 	select HAVE_ARCH_MUTEX_CPU_RELAX
 	select ARCH_INLINE_SPIN_TRYLOCK
@@ -341,26 +342,16 @@
 	  The minimum size for the stack guard should be 256 for 31 bit and
 	  512 for 64 bit.
 
-config WARN_STACK
+config WARN_DYNAMIC_STACK
 	def_bool n
-	prompt "Emit compiler warnings for function with broken stack usage"
+	prompt "Emit compiler warnings for function with dynamic stack usage"
 	help
-	  This option enables the compiler options -mwarn-framesize and
-	  -mwarn-dynamicstack. If the compiler supports these options it
-	  will generate warnings for function which either use alloca or
-	  create a stack frame bigger than CONFIG_WARN_STACK_SIZE.
+	  This option enables the compiler option -mwarn-dynamicstack. If the
+	  compiler supports this options generates warnings for functions
+	  that dynamically allocate stack space using alloca.
 
 	  Say N if you are unsure.
 
-config WARN_STACK_SIZE
-	int "Maximum frame size considered safe (128-2048)"
-	range 128 2048
-	depends on WARN_STACK
-	default "2048"
-	help
-	  This allows you to specify the maximum frame size a function may
-	  have without the compiler complaining about it.
-
 config ARCH_POPULATES_NODE_MAP
 	def_bool y
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/Kconfig.debug linux-libre-2.6.39-gnu/arch/s390/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/s390/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -31,4 +31,7 @@
 
 	  If unsure, or if you run an older (pre 4.4) gcc, say N.
 
+config DEBUG_SET_MODULE_RONX
+	def_bool y
+	depends on MODULES
 endmenu
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/compat_wrapper.S linux-libre-2.6.39-gnu/arch/s390/kernel/compat_wrapper.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/compat_wrapper.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/compat_wrapper.S	2011-05-19 00:06:34.000000000 -0400
@@ -1877,3 +1877,30 @@
 	llgtr	%r4,%r4			# const struct rlimit64 __user *
 	llgtr	%r5,%r5			# struct rlimit64 __user *
 	jg	sys_prlimit64		# branch to system call
+
+	.globl	sys_name_to_handle_at_wrapper
+sys_name_to_handle_at_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char __user *
+	llgtr	%r4,%r4			# struct file_handle __user *
+	llgtr	%r5,%r5			# int __user *
+	lgfr	%r6,%r6			# int
+	jg	sys_name_to_handle_at
+
+	.globl	compat_sys_open_by_handle_at_wrapper
+compat_sys_open_by_handle_at_wrapper:
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# struct file_handle __user *
+	lgfr	%r4,%r4			# int
+	jg	compat_sys_open_by_handle_at
+
+	.globl	compat_sys_clock_adjtime_wrapper
+compat_sys_clock_adjtime_wrapper:
+	lgfr	%r2,%r2			# clockid_t (int)
+	llgtr	%r3,%r3			# struct compat_timex __user *
+	jg	compat_sys_clock_adjtime
+
+	.globl	sys_syncfs_wrapper
+sys_syncfs_wrapper:
+	lgfr	%r2,%r2			# int
+	jg	sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/diag.c linux-libre-2.6.39-gnu/arch/s390/kernel/diag.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/diag.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/diag.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,27 +9,6 @@
 #include <asm/diag.h>
 
 /*
- * Diagnose 10: Release pages
- */
-void diag10(unsigned long addr)
-{
-	if (addr >= 0x7ff00000)
-		return;
-	asm volatile(
-#ifdef CONFIG_64BIT
-		"	sam31\n"
-		"	diag	%0,%0,0x10\n"
-		"0:	sam64\n"
-#else
-		"	diag	%0,%0,0x10\n"
-		"0:\n"
-#endif
-		EX_TABLE(0b, 0b)
-		: : "a" (addr));
-}
-EXPORT_SYMBOL(diag10);
-
-/*
  * Diagnose 14: Input spool file manipulation
  */
 int diag14(unsigned long rx, unsigned long ry1, unsigned long subcode)
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/dis.c linux-libre-2.6.39-gnu/arch/s390/kernel/dis.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/dis.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/dis.c	2011-05-19 00:06:34.000000000 -0400
@@ -672,6 +672,7 @@
 	{ "rp", 0x77, INSTR_S_RD },
 	{ "stcke", 0x78, INSTR_S_RD },
 	{ "sacf", 0x79, INSTR_S_RD },
+	{ "spp", 0x80, INSTR_S_RD },
 	{ "stsi", 0x7d, INSTR_S_RD },
 	{ "srnm", 0x99, INSTR_S_RD },
 	{ "stfpc", 0x9c, INSTR_S_RD },
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/early.c linux-libre-2.6.39-gnu/arch/s390/kernel/early.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/early.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/early.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,6 +94,7 @@
 	unsigned int sinitrd_pfn, einitrd_pfn;
 #endif
 	int response;
+	int hlen;
 	size_t len;
 	char *savesys_ptr;
 	char defsys_cmd[DEFSYS_CMD_SIZE];
@@ -124,24 +125,27 @@
 	end_pfn = PFN_UP(__pa(&_end));
 	min_size = end_pfn << 2;
 
-	sprintf(defsys_cmd, "DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
-		kernel_nss_name, stext_pfn - 1, stext_pfn, eshared_pfn - 1,
-		eshared_pfn, end_pfn);
+	hlen = snprintf(defsys_cmd, DEFSYS_CMD_SIZE,
+			"DEFSYS %s 00000-%.5X EW %.5X-%.5X SR %.5X-%.5X",
+			kernel_nss_name, stext_pfn - 1, stext_pfn,
+			eshared_pfn - 1, eshared_pfn, end_pfn);
 
 #ifdef CONFIG_BLK_DEV_INITRD
 	if (INITRD_START && INITRD_SIZE) {
 		sinitrd_pfn = PFN_DOWN(__pa(INITRD_START));
 		einitrd_pfn = PFN_UP(__pa(INITRD_START + INITRD_SIZE));
 		min_size = einitrd_pfn << 2;
-		sprintf(defsys_cmd, "%s EW %.5X-%.5X", defsys_cmd,
-		sinitrd_pfn, einitrd_pfn);
+		hlen += snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen,
+				 " EW %.5X-%.5X", sinitrd_pfn, einitrd_pfn);
 	}
 #endif
 
-	sprintf(defsys_cmd, "%s EW MINSIZE=%.7iK PARMREGS=0-13",
-		defsys_cmd, min_size);
-	sprintf(savesys_cmd, "SAVESYS %s \n IPL %s",
-		kernel_nss_name, kernel_nss_name);
+	snprintf(defsys_cmd + hlen, DEFSYS_CMD_SIZE - hlen,
+		 " EW MINSIZE=%.7iK PARMREGS=0-13", min_size);
+	defsys_cmd[DEFSYS_CMD_SIZE - 1] = '\0';
+	snprintf(savesys_cmd, SAVESYS_CMD_SIZE, "SAVESYS %s \n IPL %s",
+		 kernel_nss_name, kernel_nss_name);
+	savesys_cmd[SAVESYS_CMD_SIZE - 1] = '\0';
 
 	__cpcmd(defsys_cmd, NULL, 0, &response);
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/entry64.S linux-libre-2.6.39-gnu/arch/s390/kernel/entry64.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/entry64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/entry64.S	2011-05-19 00:06:34.000000000 -0400
@@ -841,7 +841,7 @@
 	mvc	__LC_SYSTEM_TIMER(8),__TI_system_timer(%r1)
 	xc	__LC_STEAL_TIMER(8),__LC_STEAL_TIMER
 	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
-	jg	start_secondary
+	brasl	%r14,start_secondary
 	.align	8
 restart_vtime:
 	.long	0x7fffffff,0xffffffff
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/entry.S linux-libre-2.6.39-gnu/arch/s390/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -836,7 +836,7 @@
 	stosm	__SF_EMPTY(%r15),0x04	# now we can turn dat on
 	basr	%r14,0
 	l	%r14,restart_addr-.(%r14)
-	br	%r14			# branch to start_secondary
+	basr	%r14,%r14		# branch to start_secondary
 restart_addr:
 	.long	start_secondary
 	.align	8
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/head.S linux-libre-2.6.39-gnu/arch/s390/kernel/head.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -460,7 +460,7 @@
 #ifndef CONFIG_MARCH_G5
 	# 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
+	.insn	s,0xb2b10000,__LC_STFL_FAC_LIST	# store facility list
 	tm	__LC_STFL_FAC_LIST,0x01	# stfle available ?
 	jz	0f
 	la	%r0,0
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/machine_kexec.c linux-libre-2.6.39-gnu/arch/s390/kernel/machine_kexec.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/machine_kexec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/machine_kexec.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 #include <linux/kexec.h>
 #include <linux/delay.h>
 #include <linux/reboot.h>
+#include <linux/ftrace.h>
 #include <asm/cio.h>
 #include <asm/setup.h>
 #include <asm/pgtable.h>
@@ -71,6 +72,7 @@
 
 void machine_kexec(struct kimage *image)
 {
+	tracer_disable();
 	smp_send_stop();
 	smp_switch_to_ipl_cpu(__machine_kexec, image);
 }
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/reipl64.S linux-libre-2.6.39-gnu/arch/s390/kernel/reipl64.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/reipl64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/reipl64.S	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
  * in the ESA psw.
  * Bit 31 of the addresses has to be 0 for the
  * 31bit lpswe instruction a fact they appear to have
- * ommited from the pop.
+ * omitted from the pop.
  */
 .Lnewpsw:	.quad	0x0000000080000000
 		.quad	.Lpg1
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/setup.c linux-libre-2.6.39-gnu/arch/s390/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,16 +102,6 @@
 
 #include <asm/setup.h>
 
-static struct resource code_resource = {
-	.name  = "Kernel code",
-	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
-};
-
-static struct resource data_resource = {
-	.name = "Kernel data",
-	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
-};
-
 /*
  * condev= and conmode= setup parameter.
  */
@@ -436,21 +426,43 @@
 	lowcore_ptr[0] = lc;
 }
 
-static void __init
-setup_resources(void)
+static struct resource code_resource = {
+	.name  = "Kernel code",
+	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource data_resource = {
+	.name = "Kernel data",
+	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource bss_resource = {
+	.name = "Kernel bss",
+	.flags = IORESOURCE_BUSY | IORESOURCE_MEM,
+};
+
+static struct resource __initdata *standard_resources[] = {
+	&code_resource,
+	&data_resource,
+	&bss_resource,
+};
+
+static void __init setup_resources(void)
 {
-	struct resource *res, *sub_res;
-	int i;
+	struct resource *res, *std_res, *sub_res;
+	int i, j;
 
 	code_resource.start = (unsigned long) &_text;
 	code_resource.end = (unsigned long) &_etext - 1;
 	data_resource.start = (unsigned long) &_etext;
 	data_resource.end = (unsigned long) &_edata - 1;
+	bss_resource.start = (unsigned long) &__bss_start;
+	bss_resource.end = (unsigned long) &__bss_stop - 1;
 
 	for (i = 0; i < MEMORY_CHUNKS; i++) {
 		if (!memory_chunk[i].size)
 			continue;
-		res = alloc_bootmem_low(sizeof(struct resource));
+		res = alloc_bootmem_low(sizeof(*res));
 		res->flags = IORESOURCE_BUSY | IORESOURCE_MEM;
 		switch (memory_chunk[i].type) {
 		case CHUNK_READ_WRITE:
@@ -464,40 +476,24 @@
 			res->name = "reserved";
 		}
 		res->start = memory_chunk[i].addr;
-		res->end = memory_chunk[i].addr +  memory_chunk[i].size - 1;
+		res->end = res->start + memory_chunk[i].size - 1;
 		request_resource(&iomem_resource, res);
 
-		if (code_resource.start >= res->start  &&
-			code_resource.start <= res->end &&
-			code_resource.end > res->end) {
-			sub_res = alloc_bootmem_low(sizeof(struct resource));
-			memcpy(sub_res, &code_resource,
-				sizeof(struct resource));
-			sub_res->end = res->end;
-			code_resource.start = res->end + 1;
-			request_resource(res, sub_res);
-		}
-
-		if (code_resource.start >= res->start &&
-			code_resource.start <= res->end &&
-			code_resource.end <= res->end)
-			request_resource(res, &code_resource);
-
-		if (data_resource.start >= res->start &&
-			data_resource.start <= res->end &&
-			data_resource.end > res->end) {
-			sub_res = alloc_bootmem_low(sizeof(struct resource));
-			memcpy(sub_res, &data_resource,
-				sizeof(struct resource));
-			sub_res->end = res->end;
-			data_resource.start = res->end + 1;
-			request_resource(res, sub_res);
+		for (j = 0; j < ARRAY_SIZE(standard_resources); j++) {
+			std_res = standard_resources[j];
+			if (std_res->start < res->start ||
+			    std_res->start > res->end)
+				continue;
+			if (std_res->end > res->end) {
+				sub_res = alloc_bootmem_low(sizeof(*sub_res));
+				*sub_res = *std_res;
+				sub_res->end = res->end;
+				std_res->start = res->end + 1;
+				request_resource(res, sub_res);
+			} else {
+				request_resource(res, std_res);
+			}
 		}
-
-		if (data_resource.start >= res->start &&
-			data_resource.start <= res->end &&
-			data_resource.end <= res->end)
-			request_resource(res, &data_resource);
 	}
 }
 
@@ -712,7 +708,7 @@
 	 * and 1ULL<<0 as bit 63. Bits 0-31 contain the same information
 	 * as stored by stfl, bits 32-xxx contain additional facilities.
 	 * How many facility words are stored depends on the number of
-	 * doublewords passed to the instruction. The additional facilites
+	 * doublewords passed to the instruction. The additional facilities
 	 * are:
 	 *   Bit 42: decimal floating point facility is installed
 	 *   Bit 44: perform floating point operation facility is installed
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/switch_cpu64.S linux-libre-2.6.39-gnu/arch/s390/kernel/switch_cpu64.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/switch_cpu64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/switch_cpu64.S	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,9 @@
 	ltgr	%r4,%r4			/* New stack ? */
 	jz	1f
 	lgr	%r15,%r4
-1:	basr	%r14,%r2
+1:	lgr	%r14,%r2		/* r14: Function to call */
+	lgr	%r2,%r3			/* r2 : Parameter for function*/
+	basr	%r14,%r14		/* Call function */
 
 	.section .data,"aw",@progbits
 .gprregs:
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/switch_cpu.S linux-libre-2.6.39-gnu/arch/s390/kernel/switch_cpu.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/switch_cpu.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/switch_cpu.S	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,9 @@
 	ltr	%r4,%r4			/* New stack ? */
 	jz	1f
 	lr	%r15,%r4
-1:	basr	%r14,%r2
+1:	lr	%r14,%r2		/* r14: Function to call */
+	lr	%r2,%r3			/* r2 : Parameter for function*/
+	basr	%r14,%r14		/* Call function */
 
 .gprregs_addr:
 	.long	.gprregs
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/syscalls.S linux-libre-2.6.39-gnu/arch/s390/kernel/syscalls.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/syscalls.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/syscalls.S	2011-05-19 00:06:34.000000000 -0400
@@ -343,3 +343,7 @@
 SYSCALL(sys_fanotify_init,sys_fanotify_init,sys_fanotify_init_wrapper)
 SYSCALL(sys_fanotify_mark,sys_fanotify_mark,sys_fanotify_mark_wrapper)
 SYSCALL(sys_prlimit64,sys_prlimit64,sys_prlimit64_wrapper)
+SYSCALL(sys_name_to_handle_at,sys_name_to_handle_at,sys_name_to_handle_at_wrapper) /* 335 */
+SYSCALL(sys_open_by_handle_at,sys_open_by_handle_at,compat_sys_open_by_handle_at_wrapper)
+SYSCALL(sys_clock_adjtime,sys_clock_adjtime,compat_sys_clock_adjtime_wrapper)
+SYSCALL(sys_syncfs,sys_syncfs,sys_syncfs_wrapper)
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/time.c linux-libre-2.6.39-gnu/arch/s390/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -724,7 +724,7 @@
 }
 
 /*
- * Sync the TOD clock using the port refered to by aibp. This port
+ * Sync the TOD clock using the port referred to by aibp. This port
  * has to be enabled and the other port has to be disabled. The
  * last eacr update has to be more than 1.6 seconds in the past.
  */
@@ -1012,7 +1012,7 @@
 		eacr = etr_handle_update(&aib, eacr);
 
 	/*
-	 * Select ports to enable. The prefered synchronization mode is PPS.
+	 * Select ports to enable. The preferred synchronization mode is PPS.
 	 * If a port can be enabled depends on a number of things:
 	 * 1) The port needs to be online and uptodate. A port is not
 	 *    disabled just because it is not uptodate, but it is only
@@ -1091,7 +1091,7 @@
 	/*
 	 * Update eacr and try to synchronize the clock. If the update
 	 * of eacr caused a stepping port switch (or if we have to
-	 * assume that a stepping port switch has occured) or the
+	 * assume that a stepping port switch has occurred) or the
 	 * clock syncing failed, reset the sync check control bit
 	 * and set up a timer to try again after 0.5 seconds
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/vdso.c linux-libre-2.6.39-gnu/arch/s390/kernel/vdso.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/vdso.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/vdso.c	2011-05-19 00:06:34.000000000 -0400
@@ -337,17 +337,17 @@
 }
 arch_initcall(vdso_init);
 
-int in_gate_area_no_task(unsigned long addr)
+int in_gate_area_no_mm(unsigned long addr)
 {
 	return 0;
 }
 
-int in_gate_area(struct task_struct *task, unsigned long addr)
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
 {
 	return 0;
 }
 
-struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 {
 	return NULL;
 }
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/s390/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/s390/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -77,7 +77,7 @@
 	. = ALIGN(PAGE_SIZE);
 	INIT_DATA_SECTION(0x100)
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(0x100, PAGE_SIZE)
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;		/* freed after init ends here */
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/kernel/vtime.c linux-libre-2.6.39-gnu/arch/s390/kernel/vtime.c
--- linux-libre-2.6.38-gnu/arch/s390/kernel/vtime.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kernel/vtime.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,7 @@
 	__u64 timer;
 
 	asm volatile ("  STPT %0\n"  /* Store current cpu timer value */
-		      "  SPT %1"     /* Set new value immediatly afterwards */
+		      "  SPT %1"     /* Set new value immediately afterwards */
 		      : "=m" (timer) : "m" (expires) );
 	S390_lowcore.system_timer += S390_lowcore.last_update_timer - timer;
 	S390_lowcore.last_update_timer = expires;
diff -druN linux-libre-2.6.38-gnu/arch/s390/kvm/kvm-s390.c linux-libre-2.6.39-gnu/arch/s390/kvm/kvm-s390.c
--- linux-libre-2.6.38-gnu/arch/s390/kvm/kvm-s390.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kvm/kvm-s390.c	2011-05-19 00:06:34.000000000 -0400
@@ -721,7 +721,7 @@
 
 	/*
 	 * 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
+	 * to hold the maximum amount of facilities. On the other hand, we
 	 * only set facilities that are known to work in KVM.
 	 */
 	facilities = (unsigned long long *) get_zeroed_page(GFP_KERNEL|GFP_DMA);
diff -druN linux-libre-2.6.38-gnu/arch/s390/kvm/Makefile linux-libre-2.6.39-gnu/arch/s390/kvm/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/kvm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kvm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
 
 common-objs = $(addprefix ../../../virt/kvm/, kvm_main.o)
 
-EXTRA_CFLAGS += -Ivirt/kvm -Iarch/s390/kvm
+ccflags-y := -Ivirt/kvm -Iarch/s390/kvm
 
 kvm-objs := $(common-objs) kvm-s390.o sie64a.o intercept.o interrupt.o priv.o sigp.o diag.o
 obj-$(CONFIG_KVM) += kvm.o
diff -druN linux-libre-2.6.38-gnu/arch/s390/kvm/priv.c linux-libre-2.6.39-gnu/arch/s390/kvm/priv.c
--- linux-libre-2.6.38-gnu/arch/s390/kvm/priv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kvm/priv.c	2011-05-19 00:06:34.000000000 -0400
@@ -311,7 +311,7 @@
 
 	/*
 	 * a lot of B2 instructions are priviledged. We first check for
-	 * the priviledges ones, that we can handle in the kernel. If the
+	 * the privileged ones, that we can handle in the kernel. If the
 	 * kernel can handle this instruction, we check for the problem
 	 * state bit and (a) handle the instruction or (b) send a code 2
 	 * program check.
diff -druN linux-libre-2.6.38-gnu/arch/s390/kvm/sie64a.S linux-libre-2.6.39-gnu/arch/s390/kvm/sie64a.S
--- linux-libre-2.6.38-gnu/arch/s390/kvm/sie64a.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/kvm/sie64a.S	2011-05-19 00:06:34.000000000 -0400
@@ -48,10 +48,10 @@
 	tm	__TI_flags+7(%r2),_TIF_EXIT_SIE
 	jz	0f
 	larl	%r2,sie_exit			# work pending, leave sie
-	stg	%r2,__LC_RETURN_PSW+8
+	stg	%r2,SPI_PSW+8(0,%r15)
 	br	%r14
 0:	larl	%r2,sie_reenter			# re-enter with guest id
-	stg	%r2,__LC_RETURN_PSW+8
+	stg	%r2,SPI_PSW+8(0,%r15)
 1:	br	%r14
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/s390/lib/uaccess.h linux-libre-2.6.39-gnu/arch/s390/lib/uaccess.h
--- linux-libre-2.6.38-gnu/arch/s390/lib/uaccess.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/lib/uaccess.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,12 +12,12 @@
 extern size_t copy_to_user_std(size_t, void __user *, const void *);
 extern size_t strnlen_user_std(size_t, const char __user *);
 extern size_t strncpy_from_user_std(size_t, const char __user *, char *);
-extern int futex_atomic_cmpxchg_std(int __user *, int, int);
-extern int futex_atomic_op_std(int, int __user *, int, int *);
+extern int futex_atomic_cmpxchg_std(u32 *, u32 __user *, u32, u32);
+extern int futex_atomic_op_std(int, u32 __user *, int, int *);
 
 extern size_t copy_from_user_pt(size_t, const void __user *, void *);
 extern size_t copy_to_user_pt(size_t, void __user *, const void *);
-extern int futex_atomic_op_pt(int, int __user *, int, int *);
-extern int futex_atomic_cmpxchg_pt(int __user *, int, int);
+extern int futex_atomic_op_pt(int, u32 __user *, int, int *);
+extern int futex_atomic_cmpxchg_pt(u32 *, u32 __user *, u32, u32);
 
 #endif /* __ARCH_S390_LIB_UACCESS_H */
diff -druN linux-libre-2.6.38-gnu/arch/s390/lib/uaccess_pt.c linux-libre-2.6.39-gnu/arch/s390/lib/uaccess_pt.c
--- linux-libre-2.6.38-gnu/arch/s390/lib/uaccess_pt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/lib/uaccess_pt.c	2011-05-19 00:06:34.000000000 -0400
@@ -302,7 +302,7 @@
 		     : "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		       "m" (*uaddr) : "cc" );
 
-static int __futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+static int __futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -335,7 +335,7 @@
 	return ret;
 }
 
-int futex_atomic_op_pt(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int ret;
 
@@ -354,26 +354,29 @@
 	return ret;
 }
 
-static int __futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+static int __futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+				     u32 oldval, u32 newval)
 {
 	int ret;
 
 	asm volatile("0: cs   %1,%4,0(%5)\n"
-		     "1: lr   %0,%1\n"
+		     "1: la   %0,0\n"
 		     "2:\n"
 		     EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		     : "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		     : "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		     : "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
-int futex_atomic_cmpxchg_pt(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
+			    u32 oldval, u32 newval)
 {
 	int ret;
 
 	if (segment_eq(get_fs(), KERNEL_DS))
-		return __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+		return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	spin_lock(&current->mm->page_table_lock);
 	uaddr = (int __user *) __dat_user_addr((unsigned long) uaddr);
 	if (!uaddr) {
@@ -382,7 +385,7 @@
 	}
 	get_page(virt_to_page(uaddr));
 	spin_unlock(&current->mm->page_table_lock);
-	ret = __futex_atomic_cmpxchg_pt(uaddr, oldval, newval);
+	ret = __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
 	put_page(virt_to_page(uaddr));
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/arch/s390/lib/uaccess_std.c linux-libre-2.6.39-gnu/arch/s390/lib/uaccess_std.c
--- linux-libre-2.6.38-gnu/arch/s390/lib/uaccess_std.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/lib/uaccess_std.c	2011-05-19 00:06:34.000000000 -0400
@@ -255,7 +255,7 @@
 		: "0" (-EFAULT), "d" (oparg), "a" (uaddr),		\
 		  "m" (*uaddr) : "cc");
 
-int futex_atomic_op_std(int op, int __user *uaddr, int oparg, int *old)
+int futex_atomic_op_std(int op, u32 __user *uaddr, int oparg, int *old)
 {
 	int oldval = 0, newval, ret;
 
@@ -287,19 +287,21 @@
 	return ret;
 }
 
-int futex_atomic_cmpxchg_std(int __user *uaddr, int oldval, int newval)
+int futex_atomic_cmpxchg_std(u32 *uval, u32 __user *uaddr,
+			     u32 oldval, u32 newval)
 {
 	int ret;
 
 	asm volatile(
 		"   sacf 256\n"
 		"0: cs   %1,%4,0(%5)\n"
-		"1: lr   %0,%1\n"
+		"1: la   %0,0\n"
 		"2: sacf 0\n"
 		EX_TABLE(0b,2b) EX_TABLE(1b,2b)
 		: "=d" (ret), "+d" (oldval), "=m" (*uaddr)
 		: "0" (-EFAULT), "d" (newval), "a" (uaddr), "m" (*uaddr)
 		: "cc", "memory" );
+	*uval = oldval;
 	return ret;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/s390/Makefile linux-libre-2.6.39-gnu/arch/s390/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -80,8 +80,7 @@
 endif
 
 ifeq ($(call cc-option-yn,-mwarn-dynamicstack),y)
-cflags-$(CONFIG_WARN_STACK) += -mwarn-dynamicstack
-cflags-$(CONFIG_WARN_STACK) += -mwarn-framesize=$(CONFIG_WARN_STACK_SIZE)
+cflags-$(CONFIG_WARN_DYNAMIC_STACK) += -mwarn-dynamicstack
 endif
 
 KBUILD_CFLAGS	+= -mbackchain -msoft-float $(cflags-y)
diff -druN linux-libre-2.6.38-gnu/arch/s390/math-emu/Makefile linux-libre-2.6.39-gnu/arch/s390/math-emu/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/math-emu/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/math-emu/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,4 +4,4 @@
 
 obj-$(CONFIG_MATHEMU) := math.o
 
-EXTRA_CFLAGS := -I$(src) -Iinclude/math-emu -w
+ccflags-y := -I$(src) -Iinclude/math-emu -w
diff -druN linux-libre-2.6.38-gnu/arch/s390/mm/cmm.c linux-libre-2.6.39-gnu/arch/s390/mm/cmm.c
--- linux-libre-2.6.38-gnu/arch/s390/mm/cmm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/mm/cmm.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
 			} else
 				free_page((unsigned long) npa);
 		}
-		diag10(addr);
+		diag10_range(addr >> PAGE_SHIFT, 1);
 		pa->pages[pa->index++] = addr;
 		(*counter)++;
 		spin_unlock(&cmm_lock);
diff -druN linux-libre-2.6.38-gnu/arch/s390/mm/fault.c linux-libre-2.6.39-gnu/arch/s390/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/s390/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -392,7 +392,7 @@
 {
 	int fault;
 
-	/* Protection exception is supressing, decrement psw address. */
+	/* Protection exception is suppressing, decrement psw address. */
 	regs->psw.addr -= (pgm_int_code >> 16);
 	/*
 	 * Check for low-address protection.  This needs to be treated
@@ -543,7 +543,6 @@
 	struct task_struct *tsk;
 	__u16 subcode;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
 	/*
 	 * Get the external interruption subcode & pfault
 	 * initial/completion signal bit. VM stores this 
@@ -553,14 +552,15 @@
 	subcode = ext_int_code >> 16;
 	if ((subcode & 0xff00) != __SUBCODE_MASK)
 		return;
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
 
 	/*
 	 * Get the token (= address of the task structure of the affected task).
 	 */
 #ifdef CONFIG_64BIT
-	tsk = *(struct task_struct **) param64;
+	tsk = (struct task_struct *) param64;
 #else
-	tsk = *(struct task_struct **) param32;
+	tsk = (struct task_struct *) param32;
 #endif
 
 	if (subcode & 0x0080) {
diff -druN linux-libre-2.6.38-gnu/arch/s390/mm/Makefile linux-libre-2.6.39-gnu/arch/s390/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,3 +6,4 @@
 	    page-states.o gup.o
 obj-$(CONFIG_CMM) += cmm.o
 obj-$(CONFIG_HUGETLB_PAGE) += hugetlbpage.o
+obj-$(CONFIG_DEBUG_SET_MODULE_RONX) += pageattr.o
diff -druN linux-libre-2.6.38-gnu/arch/s390/mm/pageattr.c linux-libre-2.6.39-gnu/arch/s390/mm/pageattr.c
--- linux-libre-2.6.38-gnu/arch/s390/mm/pageattr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/s390/mm/pageattr.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,56 @@
+/*
+ * Copyright IBM Corp. 2011
+ * Author(s): Jan Glauber <jang@linux.vnet.ibm.com>
+ */
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/hugetlb.h>
+#include <asm/pgtable.h>
+
+static void change_page_attr(unsigned long addr, int numpages,
+			     pte_t (*set) (pte_t))
+{
+	pte_t *ptep, pte;
+	pmd_t *pmdp;
+	pud_t *pudp;
+	pgd_t *pgdp;
+	int i;
+
+	for (i = 0; i < numpages; i++) {
+		pgdp = pgd_offset(&init_mm, addr);
+		pudp = pud_offset(pgdp, addr);
+		pmdp = pmd_offset(pudp, addr);
+		if (pmd_huge(*pmdp)) {
+			WARN_ON_ONCE(1);
+			continue;
+		}
+		ptep = pte_offset_kernel(pmdp, addr);
+
+		pte = *ptep;
+		pte = set(pte);
+		ptep_invalidate(&init_mm, addr, ptep);
+		*ptep = pte;
+		addr += PAGE_SIZE;
+	}
+}
+
+int set_memory_ro(unsigned long addr, int numpages)
+{
+	change_page_attr(addr, numpages, pte_wrprotect);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_ro);
+
+int set_memory_rw(unsigned long addr, int numpages)
+{
+	change_page_attr(addr, numpages, pte_mkwrite);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_rw);
+
+/* not possible */
+int set_memory_nx(unsigned long addr, int numpages)
+{
+	return 0;
+}
+EXPORT_SYMBOL_GPL(set_memory_nx);
diff -druN linux-libre-2.6.38-gnu/arch/s390/oprofile/hwsampler.c linux-libre-2.6.39-gnu/arch/s390/oprofile/hwsampler.c
--- linux-libre-2.6.38-gnu/arch/s390/oprofile/hwsampler.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/s390/oprofile/hwsampler.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1246 @@
+/**
+ * arch/s390/oprofile/hwsampler.c
+ *
+ * Copyright IBM Corp. 2010
+ * Author: Heinz Graalfs <graalfs@de.ibm.com>
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/smp.h>
+#include <linux/errno.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/notifier.h>
+#include <linux/cpu.h>
+#include <linux/semaphore.h>
+#include <linux/oom.h>
+#include <linux/oprofile.h>
+
+#include <asm/lowcore.h>
+#include <asm/s390_ext.h>
+
+#include "hwsampler.h"
+
+#define MAX_NUM_SDB 511
+#define MIN_NUM_SDB 1
+
+#define ALERT_REQ_MASK   0x4000000000000000ul
+#define BUFFER_FULL_MASK 0x8000000000000000ul
+
+#define EI_IEA      (1 << 31)	/* invalid entry address              */
+#define EI_ISE      (1 << 30)	/* incorrect SDBT entry               */
+#define EI_PRA      (1 << 29)	/* program request alert              */
+#define EI_SACA     (1 << 23)	/* sampler authorization change alert */
+#define EI_LSDA     (1 << 22)	/* loss of sample data alert          */
+
+DECLARE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
+
+struct hws_execute_parms {
+	void *buffer;
+	signed int rc;
+};
+
+DEFINE_PER_CPU(struct hws_cpu_buffer, sampler_cpu_buffer);
+EXPORT_PER_CPU_SYMBOL(sampler_cpu_buffer);
+
+static DEFINE_MUTEX(hws_sem);
+static DEFINE_MUTEX(hws_sem_oom);
+
+static unsigned char hws_flush_all;
+static unsigned int hws_oom;
+static struct workqueue_struct *hws_wq;
+
+static unsigned int hws_state;
+enum {
+	HWS_INIT = 1,
+	HWS_DEALLOCATED,
+	HWS_STOPPED,
+	HWS_STARTED,
+	HWS_STOPPING };
+
+/* set to 1 if called by kernel during memory allocation */
+static unsigned char oom_killer_was_active;
+/* size of SDBT and SDB as of allocate API */
+static unsigned long num_sdbt = 100;
+static unsigned long num_sdb = 511;
+/* sampling interval (machine cycles) */
+static unsigned long interval;
+
+static unsigned long min_sampler_rate;
+static unsigned long max_sampler_rate;
+
+static int ssctl(void *buffer)
+{
+	int cc;
+
+	/* set in order to detect a program check */
+	cc = 1;
+
+	asm volatile(
+		"0: .insn s,0xB2870000,0(%1)\n"
+		"1: ipm %0\n"
+		"   srl %0,28\n"
+		"2:\n"
+		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+		: "+d" (cc), "+a" (buffer)
+		: "m" (*((struct hws_ssctl_request_block *)buffer))
+		: "cc", "memory");
+
+	return cc ? -EINVAL : 0 ;
+}
+
+static int qsi(void *buffer)
+{
+	int cc;
+	cc = 1;
+
+	asm volatile(
+		"0: .insn s,0xB2860000,0(%1)\n"
+		"1: lhi %0,0\n"
+		"2:\n"
+		EX_TABLE(0b, 2b) EX_TABLE(1b, 2b)
+		: "=d" (cc), "+a" (buffer)
+		: "m" (*((struct hws_qsi_info_block *)buffer))
+		: "cc", "memory");
+
+	return cc ? -EINVAL : 0;
+}
+
+static void execute_qsi(void *parms)
+{
+	struct hws_execute_parms *ep = parms;
+
+	ep->rc = qsi(ep->buffer);
+}
+
+static void execute_ssctl(void *parms)
+{
+	struct hws_execute_parms *ep = parms;
+
+	ep->rc = ssctl(ep->buffer);
+}
+
+static int smp_ctl_ssctl_stop(int cpu)
+{
+	int rc;
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	cb->ssctl.es = 0;
+	cb->ssctl.cs = 0;
+
+	ep.buffer = &cb->ssctl;
+	smp_call_function_single(cpu, execute_ssctl, &ep, 1);
+	rc = ep.rc;
+	if (rc) {
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
+		dump_stack();
+	}
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+
+	if (cb->qsi.es || cb->qsi.cs) {
+		printk(KERN_EMERG "CPUMF sampling did not stop properly.\n");
+		dump_stack();
+	}
+
+	return rc;
+}
+
+static int smp_ctl_ssctl_deactivate(int cpu)
+{
+	int rc;
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	cb->ssctl.es = 1;
+	cb->ssctl.cs = 0;
+
+	ep.buffer = &cb->ssctl;
+	smp_call_function_single(cpu, execute_ssctl, &ep, 1);
+	rc = ep.rc;
+	if (rc)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+
+	if (cb->qsi.cs)
+		printk(KERN_EMERG "CPUMF sampling was not set inactive.\n");
+
+	return rc;
+}
+
+static int smp_ctl_ssctl_enable_activate(int cpu, unsigned long interval)
+{
+	int rc;
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	cb->ssctl.h = 1;
+	cb->ssctl.tear = cb->first_sdbt;
+	cb->ssctl.dear = *(unsigned long *) cb->first_sdbt;
+	cb->ssctl.interval = interval;
+	cb->ssctl.es = 1;
+	cb->ssctl.cs = 1;
+
+	ep.buffer = &cb->ssctl;
+	smp_call_function_single(cpu, execute_ssctl, &ep, 1);
+	rc = ep.rc;
+	if (rc)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF SSCTL failed.\n", cpu);
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+	if (ep.rc)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF QSI failed.\n", cpu);
+
+	return rc;
+}
+
+static int smp_ctl_qsi(int cpu)
+{
+	struct hws_execute_parms ep;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	ep.buffer = &cb->qsi;
+	smp_call_function_single(cpu, execute_qsi, &ep, 1);
+
+	return ep.rc;
+}
+
+static inline unsigned long *trailer_entry_ptr(unsigned long v)
+{
+	void *ret;
+
+	ret = (void *)v;
+	ret += PAGE_SIZE;
+	ret -= sizeof(struct hws_trailer_entry);
+
+	return (unsigned long *) ret;
+}
+
+/* prototypes for external interrupt handler and worker */
+static void hws_ext_handler(unsigned int ext_int_code,
+				unsigned int param32, unsigned long param64);
+
+static void worker(struct work_struct *work);
+
+static void add_samples_to_oprofile(unsigned cpu, unsigned long *,
+				unsigned long *dear);
+
+static void init_all_cpu_buffers(void)
+{
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		memset(cb, 0, sizeof(struct hws_cpu_buffer));
+	}
+}
+
+static int is_link_entry(unsigned long *s)
+{
+	return *s & 0x1ul ? 1 : 0;
+}
+
+static unsigned long *get_next_sdbt(unsigned long *s)
+{
+	return (unsigned long *) (*s & ~0x1ul);
+}
+
+static int prepare_cpu_buffers(void)
+{
+	int cpu;
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		atomic_set(&cb->ext_params, 0);
+		cb->worker_entry = 0;
+		cb->sample_overflow = 0;
+		cb->req_alert = 0;
+		cb->incorrect_sdbt_entry = 0;
+		cb->invalid_entry_address = 0;
+		cb->loss_of_sample_data = 0;
+		cb->sample_auth_change_alert = 0;
+		cb->finish = 0;
+		cb->oom = 0;
+		cb->stop_mode = 0;
+	}
+
+	return rc;
+}
+
+/*
+ * allocate_sdbt() - allocate sampler memory
+ * @cpu: the cpu for which sampler memory is allocated
+ *
+ * A 4K page is allocated for each requested SDBT.
+ * A maximum of 511 4K pages are allocated for the SDBs in each of the SDBTs.
+ * Set ALERT_REQ mask in each SDBs trailer.
+ * Returns zero if successful, <0 otherwise.
+ */
+static int allocate_sdbt(int cpu)
+{
+	int j, k, rc;
+	unsigned long *sdbt;
+	unsigned long  sdb;
+	unsigned long *tail;
+	unsigned long *trailer;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	if (cb->first_sdbt)
+		return -EINVAL;
+
+	sdbt = NULL;
+	tail = sdbt;
+
+	for (j = 0; j < num_sdbt; j++) {
+		sdbt = (unsigned long *)get_zeroed_page(GFP_KERNEL);
+
+		mutex_lock(&hws_sem_oom);
+		/* OOM killer might have been activated */
+		barrier();
+		if (oom_killer_was_active || !sdbt) {
+			if (sdbt)
+				free_page((unsigned long)sdbt);
+
+			goto allocate_sdbt_error;
+		}
+		if (cb->first_sdbt == 0)
+			cb->first_sdbt = (unsigned long)sdbt;
+
+		/* link current page to tail of chain */
+		if (tail)
+			*tail = (unsigned long)(void *)sdbt + 1;
+
+		mutex_unlock(&hws_sem_oom);
+
+		for (k = 0; k < num_sdb; k++) {
+			/* get and set SDB page */
+			sdb = get_zeroed_page(GFP_KERNEL);
+
+			mutex_lock(&hws_sem_oom);
+			/* OOM killer might have been activated */
+			barrier();
+			if (oom_killer_was_active || !sdb) {
+				if (sdb)
+					free_page(sdb);
+
+				goto allocate_sdbt_error;
+			}
+			*sdbt = sdb;
+			trailer = trailer_entry_ptr(*sdbt);
+			*trailer = ALERT_REQ_MASK;
+			sdbt++;
+			mutex_unlock(&hws_sem_oom);
+		}
+		tail = sdbt;
+	}
+	mutex_lock(&hws_sem_oom);
+	if (oom_killer_was_active)
+		goto allocate_sdbt_error;
+
+	rc = 0;
+	if (tail)
+		*tail = (unsigned long)
+			((void *)cb->first_sdbt) + 1;
+
+allocate_sdbt_exit:
+	mutex_unlock(&hws_sem_oom);
+	return rc;
+
+allocate_sdbt_error:
+	rc = -ENOMEM;
+	goto allocate_sdbt_exit;
+}
+
+/*
+ * deallocate_sdbt() - deallocate all sampler memory
+ *
+ * For each online CPU all SDBT trees are deallocated.
+ * Returns the number of freed pages.
+ */
+static int deallocate_sdbt(void)
+{
+	int cpu;
+	int counter;
+
+	counter = 0;
+
+	for_each_online_cpu(cpu) {
+		unsigned long start;
+		unsigned long sdbt;
+		unsigned long *curr;
+		struct hws_cpu_buffer *cb;
+
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+		if (!cb->first_sdbt)
+			continue;
+
+		sdbt = cb->first_sdbt;
+		curr = (unsigned long *) sdbt;
+		start = sdbt;
+
+		/* we'll free the SDBT after all SDBs are processed... */
+		while (1) {
+			if (!*curr || !sdbt)
+				break;
+
+			/* watch for link entry reset if found */
+			if (is_link_entry(curr)) {
+				curr = get_next_sdbt(curr);
+				if (sdbt)
+					free_page(sdbt);
+
+				/* we are done if we reach the start */
+				if ((unsigned long) curr == start)
+					break;
+				else
+					sdbt = (unsigned long) curr;
+			} else {
+				/* process SDB pointer */
+				if (*curr) {
+					free_page(*curr);
+					curr++;
+				}
+			}
+			counter++;
+		}
+		cb->first_sdbt = 0;
+	}
+	return counter;
+}
+
+static int start_sampling(int cpu)
+{
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	rc = smp_ctl_ssctl_enable_activate(cpu, interval);
+	if (rc) {
+		printk(KERN_INFO "hwsampler: CPU %d ssctl failed.\n", cpu);
+		goto start_exit;
+	}
+
+	rc = -EINVAL;
+	if (!cb->qsi.es) {
+		printk(KERN_INFO "hwsampler: CPU %d ssctl not enabled.\n", cpu);
+		goto start_exit;
+	}
+
+	if (!cb->qsi.cs) {
+		printk(KERN_INFO "hwsampler: CPU %d ssctl not active.\n", cpu);
+		goto start_exit;
+	}
+
+	printk(KERN_INFO
+		"hwsampler: CPU %d, CPUMF Sampling started, interval %lu.\n",
+		cpu, interval);
+
+	rc = 0;
+
+start_exit:
+	return rc;
+}
+
+static int stop_sampling(int cpu)
+{
+	unsigned long v;
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = smp_ctl_qsi(cpu);
+	WARN_ON(rc);
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	if (!rc && !cb->qsi.es)
+		printk(KERN_INFO "hwsampler: CPU %d, already stopped.\n", cpu);
+
+	rc = smp_ctl_ssctl_stop(cpu);
+	if (rc) {
+		printk(KERN_INFO "hwsampler: CPU %d, ssctl stop error %d.\n",
+				cpu, rc);
+		goto stop_exit;
+	}
+
+	printk(KERN_INFO "hwsampler: CPU %d, CPUMF Sampling stopped.\n", cpu);
+
+stop_exit:
+	v = cb->req_alert;
+	if (v)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF Request alert,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->loss_of_sample_data;
+	if (v)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF Loss of sample data,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->invalid_entry_address;
+	if (v)
+		printk(KERN_ERR "hwsampler: CPU %d CPUMF Invalid entry address,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->incorrect_sdbt_entry;
+	if (v)
+		printk(KERN_ERR
+				"hwsampler: CPU %d CPUMF Incorrect SDBT address,"
+				" count=%lu.\n", cpu, v);
+
+	v = cb->sample_auth_change_alert;
+	if (v)
+		printk(KERN_ERR
+				"hwsampler: CPU %d CPUMF Sample authorization change,"
+				" count=%lu.\n", cpu, v);
+
+	return rc;
+}
+
+static int check_hardware_prerequisites(void)
+{
+	if (!test_facility(68))
+		return -EOPNOTSUPP;
+	return 0;
+}
+/*
+ * hws_oom_callback() - the OOM callback function
+ *
+ * In case the callback is invoked during memory allocation for the
+ *  hw sampler, all obtained memory is deallocated and a flag is set
+ *  so main sampler memory allocation can exit with a failure code.
+ * In case the callback is invoked during sampling the hw sampler
+ *  is deactivated for all CPUs.
+ */
+static int hws_oom_callback(struct notifier_block *nfb,
+	unsigned long dummy, void *parm)
+{
+	unsigned long *freed;
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	freed = parm;
+
+	mutex_lock(&hws_sem_oom);
+
+	if (hws_state == HWS_DEALLOCATED) {
+		/* during memory allocation */
+		if (oom_killer_was_active == 0) {
+			oom_killer_was_active = 1;
+			*freed += deallocate_sdbt();
+		}
+	} else {
+		int i;
+		cpu = get_cpu();
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+		if (!cb->oom) {
+			for_each_online_cpu(i) {
+				smp_ctl_ssctl_deactivate(i);
+				cb->oom = 1;
+			}
+			cb->finish = 1;
+
+			printk(KERN_INFO
+				"hwsampler: CPU %d, OOM notify during CPUMF Sampling.\n",
+				cpu);
+		}
+	}
+
+	mutex_unlock(&hws_sem_oom);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block hws_oom_notifier = {
+	.notifier_call = hws_oom_callback
+};
+
+static int hws_cpu_callback(struct notifier_block *nfb,
+	unsigned long action, void *hcpu)
+{
+	/* We do not have sampler space available for all possible CPUs.
+	   All CPUs should be online when hw sampling is activated. */
+	return NOTIFY_BAD;
+}
+
+static struct notifier_block hws_cpu_notifier = {
+	.notifier_call = hws_cpu_callback
+};
+
+/**
+ * hwsampler_deactivate() - set hardware sampling temporarily inactive
+ * @cpu:  specifies the CPU to be set inactive.
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_deactivate(unsigned int cpu)
+{
+	/*
+	 * Deactivate hw sampling temporarily and flush the buffer
+	 * by pushing all the pending samples to oprofile buffer.
+	 *
+	 * This function can be called under one of the following conditions:
+	 *     Memory unmap, task is exiting.
+	 */
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	mutex_lock(&hws_sem);
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	if (hws_state == HWS_STARTED) {
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (cb->qsi.cs) {
+			rc = smp_ctl_ssctl_deactivate(cpu);
+			if (rc) {
+				printk(KERN_INFO
+				"hwsampler: CPU %d, CPUMF Deactivation failed.\n", cpu);
+				cb->finish = 1;
+				hws_state = HWS_STOPPING;
+			} else  {
+				hws_flush_all = 1;
+				/* Add work to queue to read pending samples.*/
+				queue_work_on(cpu, hws_wq, &cb->worker);
+			}
+		}
+	}
+	mutex_unlock(&hws_sem);
+
+	if (hws_wq)
+		flush_workqueue(hws_wq);
+
+	return rc;
+}
+
+/**
+ * hwsampler_activate() - activate/resume hardware sampling which was deactivated
+ * @cpu:  specifies the CPU to be set active.
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_activate(unsigned int cpu)
+{
+	/*
+	 * Re-activate hw sampling. This should be called in pair with
+	 * hwsampler_deactivate().
+	 */
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	mutex_lock(&hws_sem);
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	if (hws_state == HWS_STARTED) {
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (!cb->qsi.cs) {
+			hws_flush_all = 0;
+			rc = smp_ctl_ssctl_enable_activate(cpu, interval);
+			if (rc) {
+				printk(KERN_ERR
+				"CPU %d, CPUMF activate sampling failed.\n",
+					 cpu);
+			}
+		}
+	}
+
+	mutex_unlock(&hws_sem);
+
+	return rc;
+}
+
+static void hws_ext_handler(unsigned int ext_int_code,
+			    unsigned int param32, unsigned long param64)
+{
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	cpu = smp_processor_id();
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	atomic_xchg(
+			&cb->ext_params,
+			atomic_read(&cb->ext_params)
+				| S390_lowcore.ext_params);
+
+	if (hws_wq)
+		queue_work(hws_wq, &cb->worker);
+}
+
+static int check_qsi_on_setup(void)
+{
+	int rc;
+	unsigned int cpu;
+	struct hws_cpu_buffer *cb;
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (rc)
+			return -EOPNOTSUPP;
+
+		if (!cb->qsi.as) {
+			printk(KERN_INFO "hwsampler: CPUMF sampling is not authorized.\n");
+			return -EINVAL;
+		}
+
+		if (cb->qsi.es) {
+			printk(KERN_WARNING "hwsampler: CPUMF is still enabled.\n");
+			rc = smp_ctl_ssctl_stop(cpu);
+			if (rc)
+				return -EINVAL;
+
+			printk(KERN_INFO
+				"CPU %d, CPUMF Sampling stopped now.\n", cpu);
+		}
+	}
+	return 0;
+}
+
+static int check_qsi_on_start(void)
+{
+	unsigned int cpu;
+	int rc;
+	struct hws_cpu_buffer *cb;
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+
+		if (!cb->qsi.as)
+			return -EINVAL;
+
+		if (cb->qsi.es)
+			return -EINVAL;
+
+		if (cb->qsi.cs)
+			return -EINVAL;
+	}
+	return 0;
+}
+
+static void worker_on_start(unsigned int cpu)
+{
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	cb->worker_entry = cb->first_sdbt;
+}
+
+static int worker_check_error(unsigned int cpu, int ext_params)
+{
+	int rc;
+	unsigned long *sdbt;
+	struct hws_cpu_buffer *cb;
+
+	rc = 0;
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+	sdbt = (unsigned long *) cb->worker_entry;
+
+	if (!sdbt || !*sdbt)
+		return -EINVAL;
+
+	if (ext_params & EI_IEA)
+		cb->req_alert++;
+
+	if (ext_params & EI_LSDA)
+		cb->loss_of_sample_data++;
+
+	if (ext_params & EI_IEA) {
+		cb->invalid_entry_address++;
+		rc = -EINVAL;
+	}
+
+	if (ext_params & EI_ISE) {
+		cb->incorrect_sdbt_entry++;
+		rc = -EINVAL;
+	}
+
+	if (ext_params & EI_SACA) {
+		cb->sample_auth_change_alert++;
+		rc = -EINVAL;
+	}
+
+	return rc;
+}
+
+static void worker_on_finish(unsigned int cpu)
+{
+	int rc, i;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	if (cb->finish) {
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (cb->qsi.es) {
+			printk(KERN_INFO
+				"hwsampler: CPU %d, CPUMF Stop/Deactivate sampling.\n",
+				cpu);
+			rc = smp_ctl_ssctl_stop(cpu);
+			if (rc)
+				printk(KERN_INFO
+					"hwsampler: CPU %d, CPUMF Deactivation failed.\n",
+					cpu);
+
+			for_each_online_cpu(i) {
+				if (i == cpu)
+					continue;
+				if (!cb->finish) {
+					cb->finish = 1;
+					queue_work_on(i, hws_wq,
+						&cb->worker);
+				}
+			}
+		}
+	}
+}
+
+static void worker_on_interrupt(unsigned int cpu)
+{
+	unsigned long *sdbt;
+	unsigned char done;
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	sdbt = (unsigned long *) cb->worker_entry;
+
+	done = 0;
+	/* do not proceed if stop was entered,
+	 * forget the buffers not yet processed */
+	while (!done && !cb->stop_mode) {
+		unsigned long *trailer;
+		struct hws_trailer_entry *te;
+		unsigned long *dear = 0;
+
+		trailer = trailer_entry_ptr(*sdbt);
+		/* leave loop if no more work to do */
+		if (!(*trailer & BUFFER_FULL_MASK)) {
+			done = 1;
+			if (!hws_flush_all)
+				continue;
+		}
+
+		te = (struct hws_trailer_entry *)trailer;
+		cb->sample_overflow += te->overflow;
+
+		add_samples_to_oprofile(cpu, sdbt, dear);
+
+		/* reset trailer */
+		xchg((unsigned char *) te, 0x40);
+
+		/* advance to next sdb slot in current sdbt */
+		sdbt++;
+		/* in case link bit is set use address w/o link bit */
+		if (is_link_entry(sdbt))
+			sdbt = get_next_sdbt(sdbt);
+
+		cb->worker_entry = (unsigned long)sdbt;
+	}
+}
+
+static void add_samples_to_oprofile(unsigned int cpu, unsigned long *sdbt,
+		unsigned long *dear)
+{
+	struct hws_data_entry *sample_data_ptr;
+	unsigned long *trailer;
+
+	trailer = trailer_entry_ptr(*sdbt);
+	if (dear) {
+		if (dear > trailer)
+			return;
+		trailer = dear;
+	}
+
+	sample_data_ptr = (struct hws_data_entry *)(*sdbt);
+
+	while ((unsigned long *)sample_data_ptr < trailer) {
+		struct pt_regs *regs = NULL;
+		struct task_struct *tsk = NULL;
+
+		/*
+		 * Check sampling mode, 1 indicates basic (=customer) sampling
+		 * mode.
+		 */
+		if (sample_data_ptr->def != 1) {
+			/* sample slot is not yet written */
+			break;
+		} else {
+			/* make sure we don't use it twice,
+			 * the next time the sampler will set it again */
+			sample_data_ptr->def = 0;
+		}
+
+		/* Get pt_regs. */
+		if (sample_data_ptr->P == 1) {
+			/* userspace sample */
+			unsigned int pid = sample_data_ptr->prim_asn;
+			rcu_read_lock();
+			tsk = pid_task(find_vpid(pid), PIDTYPE_PID);
+			if (tsk)
+				regs = task_pt_regs(tsk);
+			rcu_read_unlock();
+		} else {
+			/* kernelspace sample */
+			regs = task_pt_regs(current);
+		}
+
+		mutex_lock(&hws_sem);
+		oprofile_add_ext_hw_sample(sample_data_ptr->ia, regs, 0,
+				!sample_data_ptr->P, tsk);
+		mutex_unlock(&hws_sem);
+
+		sample_data_ptr++;
+	}
+}
+
+static void worker(struct work_struct *work)
+{
+	unsigned int cpu;
+	int ext_params;
+	struct hws_cpu_buffer *cb;
+
+	cb = container_of(work, struct hws_cpu_buffer, worker);
+	cpu = smp_processor_id();
+	ext_params = atomic_xchg(&cb->ext_params, 0);
+
+	if (!cb->worker_entry)
+		worker_on_start(cpu);
+
+	if (worker_check_error(cpu, ext_params))
+		return;
+
+	if (!cb->finish)
+		worker_on_interrupt(cpu);
+
+	if (cb->finish)
+		worker_on_finish(cpu);
+}
+
+/**
+ * hwsampler_allocate() - allocate memory for the hardware sampler
+ * @sdbt:  number of SDBTs per online CPU (must be > 0)
+ * @sdb:   number of SDBs per SDBT (minimum 1, maximum 511)
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_allocate(unsigned long sdbt, unsigned long sdb)
+{
+	int cpu, rc;
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state != HWS_DEALLOCATED)
+		goto allocate_exit;
+
+	if (sdbt < 1)
+		goto allocate_exit;
+
+	if (sdb > MAX_NUM_SDB || sdb < MIN_NUM_SDB)
+		goto allocate_exit;
+
+	num_sdbt = sdbt;
+	num_sdb = sdb;
+
+	oom_killer_was_active = 0;
+	register_oom_notifier(&hws_oom_notifier);
+
+	for_each_online_cpu(cpu) {
+		if (allocate_sdbt(cpu)) {
+			unregister_oom_notifier(&hws_oom_notifier);
+			goto allocate_error;
+		}
+	}
+	unregister_oom_notifier(&hws_oom_notifier);
+	if (oom_killer_was_active)
+		goto allocate_error;
+
+	hws_state = HWS_STOPPED;
+	rc = 0;
+
+allocate_exit:
+	mutex_unlock(&hws_sem);
+	return rc;
+
+allocate_error:
+	rc = -ENOMEM;
+	printk(KERN_ERR "hwsampler: CPUMF Memory allocation failed.\n");
+	goto allocate_exit;
+}
+
+/**
+ * hwsampler_deallocate() - deallocate hardware sampler memory
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_deallocate()
+{
+	int rc;
+
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state != HWS_STOPPED)
+		goto deallocate_exit;
+
+	smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */
+	deallocate_sdbt();
+
+	hws_state = HWS_DEALLOCATED;
+	rc = 0;
+
+deallocate_exit:
+	mutex_unlock(&hws_sem);
+
+	return rc;
+}
+
+unsigned long hwsampler_query_min_interval(void)
+{
+	return min_sampler_rate;
+}
+
+unsigned long hwsampler_query_max_interval(void)
+{
+	return max_sampler_rate;
+}
+
+unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu)
+{
+	struct hws_cpu_buffer *cb;
+
+	cb = &per_cpu(sampler_cpu_buffer, cpu);
+
+	return cb->sample_overflow;
+}
+
+int hwsampler_setup()
+{
+	int rc;
+	int cpu;
+	struct hws_cpu_buffer *cb;
+
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state)
+		goto setup_exit;
+
+	hws_state = HWS_INIT;
+
+	init_all_cpu_buffers();
+
+	rc = check_hardware_prerequisites();
+	if (rc)
+		goto setup_exit;
+
+	rc = check_qsi_on_setup();
+	if (rc)
+		goto setup_exit;
+
+	rc = -EINVAL;
+	hws_wq = create_workqueue("hwsampler");
+	if (!hws_wq)
+		goto setup_exit;
+
+	register_cpu_notifier(&hws_cpu_notifier);
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		INIT_WORK(&cb->worker, worker);
+		rc = smp_ctl_qsi(cpu);
+		WARN_ON(rc);
+		if (min_sampler_rate != cb->qsi.min_sampl_rate) {
+			if (min_sampler_rate) {
+				printk(KERN_WARNING
+					"hwsampler: different min sampler rate values.\n");
+				if (min_sampler_rate < cb->qsi.min_sampl_rate)
+					min_sampler_rate =
+						cb->qsi.min_sampl_rate;
+			} else
+				min_sampler_rate = cb->qsi.min_sampl_rate;
+		}
+		if (max_sampler_rate != cb->qsi.max_sampl_rate) {
+			if (max_sampler_rate) {
+				printk(KERN_WARNING
+					"hwsampler: different max sampler rate values.\n");
+				if (max_sampler_rate > cb->qsi.max_sampl_rate)
+					max_sampler_rate =
+						cb->qsi.max_sampl_rate;
+			} else
+				max_sampler_rate = cb->qsi.max_sampl_rate;
+		}
+	}
+	register_external_interrupt(0x1407, hws_ext_handler);
+
+	hws_state = HWS_DEALLOCATED;
+	rc = 0;
+
+setup_exit:
+	mutex_unlock(&hws_sem);
+	return rc;
+}
+
+int hwsampler_shutdown()
+{
+	int rc;
+
+	mutex_lock(&hws_sem);
+
+	rc = -EINVAL;
+	if (hws_state == HWS_DEALLOCATED || hws_state == HWS_STOPPED) {
+		mutex_unlock(&hws_sem);
+
+		if (hws_wq)
+			flush_workqueue(hws_wq);
+
+		mutex_lock(&hws_sem);
+
+		if (hws_state == HWS_STOPPED) {
+			smp_ctl_clear_bit(0, 5); /* set bit 58 CR0 off */
+			deallocate_sdbt();
+		}
+		if (hws_wq) {
+			destroy_workqueue(hws_wq);
+			hws_wq = NULL;
+		}
+
+		unregister_external_interrupt(0x1407, hws_ext_handler);
+		hws_state = HWS_INIT;
+		rc = 0;
+	}
+	mutex_unlock(&hws_sem);
+
+	unregister_cpu_notifier(&hws_cpu_notifier);
+
+	return rc;
+}
+
+/**
+ * hwsampler_start_all() - start hardware sampling on all online CPUs
+ * @rate:  specifies the used interval when samples are taken
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_start_all(unsigned long rate)
+{
+	int rc, cpu;
+
+	mutex_lock(&hws_sem);
+
+	hws_oom = 0;
+
+	rc = -EINVAL;
+	if (hws_state != HWS_STOPPED)
+		goto start_all_exit;
+
+	interval = rate;
+
+	/* fail if rate is not valid */
+	if (interval < min_sampler_rate || interval > max_sampler_rate)
+		goto start_all_exit;
+
+	rc = check_qsi_on_start();
+	if (rc)
+		goto start_all_exit;
+
+	rc = prepare_cpu_buffers();
+	if (rc)
+		goto start_all_exit;
+
+	for_each_online_cpu(cpu) {
+		rc = start_sampling(cpu);
+		if (rc)
+			break;
+	}
+	if (rc) {
+		for_each_online_cpu(cpu) {
+			stop_sampling(cpu);
+		}
+		goto start_all_exit;
+	}
+	hws_state = HWS_STARTED;
+	rc = 0;
+
+start_all_exit:
+	mutex_unlock(&hws_sem);
+
+	if (rc)
+		return rc;
+
+	register_oom_notifier(&hws_oom_notifier);
+	hws_oom = 1;
+	hws_flush_all = 0;
+	/* now let them in, 1407 CPUMF external interrupts */
+	smp_ctl_set_bit(0, 5); /* set CR0 bit 58 */
+
+	return 0;
+}
+
+/**
+ * hwsampler_stop_all() - stop hardware sampling on all online CPUs
+ *
+ * Returns 0 on success, !0 on failure.
+ */
+int hwsampler_stop_all()
+{
+	int tmp_rc, rc, cpu;
+	struct hws_cpu_buffer *cb;
+
+	mutex_lock(&hws_sem);
+
+	rc = 0;
+	if (hws_state == HWS_INIT) {
+		mutex_unlock(&hws_sem);
+		return rc;
+	}
+	hws_state = HWS_STOPPING;
+	mutex_unlock(&hws_sem);
+
+	for_each_online_cpu(cpu) {
+		cb = &per_cpu(sampler_cpu_buffer, cpu);
+		cb->stop_mode = 1;
+		tmp_rc = stop_sampling(cpu);
+		if (tmp_rc)
+			rc = tmp_rc;
+	}
+
+	if (hws_wq)
+		flush_workqueue(hws_wq);
+
+	mutex_lock(&hws_sem);
+	if (hws_oom) {
+		unregister_oom_notifier(&hws_oom_notifier);
+		hws_oom = 0;
+	}
+	hws_state = HWS_STOPPED;
+	mutex_unlock(&hws_sem);
+
+	return rc;
+}
diff -druN linux-libre-2.6.38-gnu/arch/s390/oprofile/hwsampler.h linux-libre-2.6.39-gnu/arch/s390/oprofile/hwsampler.h
--- linux-libre-2.6.38-gnu/arch/s390/oprofile/hwsampler.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/s390/oprofile/hwsampler.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * CPUMF HW sampler functions and internal structures
+ *
+ *    Copyright IBM Corp. 2010
+ *    Author(s): Heinz Graalfs <graalfs@de.ibm.com>
+ */
+
+#ifndef HWSAMPLER_H_
+#define HWSAMPLER_H_
+
+#include <linux/workqueue.h>
+
+struct hws_qsi_info_block          /* QUERY SAMPLING information block  */
+{ /* Bit(s) */
+	unsigned int b0_13:14;      /* 0-13: zeros                       */
+	unsigned int as:1;          /* 14: sampling authorisation control*/
+	unsigned int b15_21:7;      /* 15-21: zeros                      */
+	unsigned int es:1;          /* 22: sampling enable control       */
+	unsigned int b23_29:7;      /* 23-29: zeros                      */
+	unsigned int cs:1;          /* 30: sampling activation control   */
+	unsigned int:1;             /* 31: reserved                      */
+	unsigned int bsdes:16;      /* 4-5: size of sampling entry       */
+	unsigned int:16;            /* 6-7: reserved                     */
+	unsigned long min_sampl_rate; /* 8-15: minimum sampling interval */
+	unsigned long max_sampl_rate; /* 16-23: maximum sampling interval*/
+	unsigned long tear;         /* 24-31: TEAR contents              */
+	unsigned long dear;         /* 32-39: DEAR contents              */
+	unsigned int rsvrd0;        /* 40-43: reserved                   */
+	unsigned int cpu_speed;     /* 44-47: CPU speed                  */
+	unsigned long long rsvrd1;  /* 48-55: reserved                   */
+	unsigned long long rsvrd2;  /* 56-63: reserved                   */
+};
+
+struct hws_ssctl_request_block     /* SET SAMPLING CONTROLS req block   */
+{ /* bytes 0 - 7  Bit(s) */
+	unsigned int s:1;           /* 0: maximum buffer indicator       */
+	unsigned int h:1;           /* 1: part. level reserved for VM use*/
+	unsigned long b2_53:52;     /* 2-53: zeros                       */
+	unsigned int es:1;          /* 54: sampling enable control       */
+	unsigned int b55_61:7;      /* 55-61: - zeros                    */
+	unsigned int cs:1;          /* 62: sampling activation control   */
+	unsigned int b63:1;         /* 63: zero                          */
+	unsigned long interval;     /* 8-15: sampling interval           */
+	unsigned long tear;         /* 16-23: TEAR contents              */
+	unsigned long dear;         /* 24-31: DEAR contents              */
+	/* 32-63:                                                        */
+	unsigned long rsvrd1;       /* reserved                          */
+	unsigned long rsvrd2;       /* reserved                          */
+	unsigned long rsvrd3;       /* reserved                          */
+	unsigned long rsvrd4;       /* reserved                          */
+};
+
+struct hws_cpu_buffer {
+	unsigned long first_sdbt;       /* @ of 1st SDB-Table for this CP*/
+	unsigned long worker_entry;
+	unsigned long sample_overflow;  /* taken from SDB ...            */
+	struct hws_qsi_info_block qsi;
+	struct hws_ssctl_request_block ssctl;
+	struct work_struct worker;
+	atomic_t ext_params;
+	unsigned long req_alert;
+	unsigned long loss_of_sample_data;
+	unsigned long invalid_entry_address;
+	unsigned long incorrect_sdbt_entry;
+	unsigned long sample_auth_change_alert;
+	unsigned int finish:1;
+	unsigned int oom:1;
+	unsigned int stop_mode:1;
+};
+
+struct hws_data_entry {
+	unsigned int def:16;        /* 0-15  Data Entry Format           */
+	unsigned int R:4;           /* 16-19 reserved                    */
+	unsigned int U:4;           /* 20-23 Number of unique instruct.  */
+	unsigned int z:2;           /* zeros                             */
+	unsigned int T:1;           /* 26 PSW DAT mode                   */
+	unsigned int W:1;           /* 27 PSW wait state                 */
+	unsigned int P:1;           /* 28 PSW Problem state              */
+	unsigned int AS:2;          /* 29-30 PSW address-space control   */
+	unsigned int I:1;           /* 31 entry valid or invalid         */
+	unsigned int:16;
+	unsigned int prim_asn:16;   /* primary ASN                       */
+	unsigned long long ia;      /* Instruction Address               */
+	unsigned long long lpp;     /* Logical-Partition Program Param.  */
+	unsigned long long vpp;     /* Virtual-Machine Program Param.    */
+};
+
+struct hws_trailer_entry {
+	unsigned int f:1;           /* 0 - Block Full Indicator          */
+	unsigned int a:1;           /* 1 - Alert request control         */
+	unsigned long:62;           /* 2 - 63: Reserved                  */
+	unsigned long overflow;     /* 64 - sample Overflow count        */
+	unsigned long timestamp;    /* 16 - time-stamp                   */
+	unsigned long timestamp1;   /*                                   */
+	unsigned long reserved1;    /* 32 -Reserved                      */
+	unsigned long reserved2;    /*                                   */
+	unsigned long progusage1;   /* 48 - reserved for programming use */
+	unsigned long progusage2;   /*                                   */
+};
+
+int hwsampler_setup(void);
+int hwsampler_shutdown(void);
+int hwsampler_allocate(unsigned long sdbt, unsigned long sdb);
+int hwsampler_deallocate(void);
+unsigned long hwsampler_query_min_interval(void);
+unsigned long hwsampler_query_max_interval(void);
+int hwsampler_start_all(unsigned long interval);
+int hwsampler_stop_all(void);
+int hwsampler_deactivate(unsigned int cpu);
+int hwsampler_activate(unsigned int cpu);
+unsigned long hwsampler_get_sample_overflow_count(unsigned int cpu);
+
+#endif /*HWSAMPLER_H_*/
diff -druN linux-libre-2.6.38-gnu/arch/s390/oprofile/init.c linux-libre-2.6.39-gnu/arch/s390/oprofile/init.c
--- linux-libre-2.6.38-gnu/arch/s390/oprofile/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/oprofile/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,23 +4,189 @@
  * S390 Version
  *   Copyright (C) 2003 IBM Deutschland Entwicklung GmbH, IBM Corporation
  *   Author(s): Thomas Spatzier (tspat@de.ibm.com)
+ *   Author(s): Mahesh Salgaonkar (mahesh@linux.vnet.ibm.com)
+ *   Author(s): Heinz Graalfs (graalfs@linux.vnet.ibm.com)
  *
- * @remark Copyright 2002 OProfile authors
+ * @remark Copyright 2002-2011 OProfile authors
  */
 
 #include <linux/oprofile.h>
 #include <linux/init.h>
 #include <linux/errno.h>
+#include <linux/oprofile.h>
+#include <linux/errno.h>
+#include <linux/fs.h>
 
+#include "../../../drivers/oprofile/oprof.h"
 
 extern void s390_backtrace(struct pt_regs * const regs, unsigned int depth);
 
-int __init oprofile_arch_init(struct oprofile_operations* ops)
+#ifdef CONFIG_64BIT
+
+#include "hwsampler.h"
+
+#define DEFAULT_INTERVAL	4096
+
+#define DEFAULT_SDBT_BLOCKS	1
+#define DEFAULT_SDB_BLOCKS	511
+
+static unsigned long oprofile_hw_interval = DEFAULT_INTERVAL;
+static unsigned long oprofile_min_interval;
+static unsigned long oprofile_max_interval;
+
+static unsigned long oprofile_sdbt_blocks = DEFAULT_SDBT_BLOCKS;
+static unsigned long oprofile_sdb_blocks = DEFAULT_SDB_BLOCKS;
+
+static int hwsampler_file;
+static int hwsampler_running;	/* start_mutex must be held to change */
+
+static struct oprofile_operations timer_ops;
+
+static int oprofile_hwsampler_start(void)
+{
+	int retval;
+
+	hwsampler_running = hwsampler_file;
+
+	if (!hwsampler_running)
+		return timer_ops.start();
+
+	retval = hwsampler_allocate(oprofile_sdbt_blocks, oprofile_sdb_blocks);
+	if (retval)
+		return retval;
+
+	retval = hwsampler_start_all(oprofile_hw_interval);
+	if (retval)
+		hwsampler_deallocate();
+
+	return retval;
+}
+
+static void oprofile_hwsampler_stop(void)
+{
+	if (!hwsampler_running) {
+		timer_ops.stop();
+		return;
+	}
+
+	hwsampler_stop_all();
+	hwsampler_deallocate();
+	return;
+}
+
+static ssize_t hwsampler_read(struct file *file, char __user *buf,
+		size_t count, loff_t *offset)
+{
+	return oprofilefs_ulong_to_user(hwsampler_file, buf, count, offset);
+}
+
+static ssize_t hwsampler_write(struct file *file, char const __user *buf,
+		size_t count, loff_t *offset)
+{
+	unsigned long val;
+	int retval;
+
+	if (*offset)
+		return -EINVAL;
+
+	retval = oprofilefs_ulong_from_user(&val, buf, count);
+	if (retval)
+		return retval;
+
+	if (oprofile_started)
+		/*
+		 * save to do without locking as we set
+		 * hwsampler_running in start() when start_mutex is
+		 * held
+		 */
+		return -EBUSY;
+
+	hwsampler_file = val;
+
+	return count;
+}
+
+static const struct file_operations hwsampler_fops = {
+	.read		= hwsampler_read,
+	.write		= hwsampler_write,
+};
+
+static int oprofile_create_hwsampling_files(struct super_block *sb,
+						struct dentry *root)
+{
+	struct dentry *hw_dir;
+
+	/* reinitialize default values */
+	hwsampler_file = 1;
+
+	hw_dir = oprofilefs_mkdir(sb, root, "hwsampling");
+	if (!hw_dir)
+		return -EINVAL;
+
+	oprofilefs_create_file(sb, hw_dir, "hwsampler", &hwsampler_fops);
+	oprofilefs_create_ulong(sb, hw_dir, "hw_interval",
+				&oprofile_hw_interval);
+	oprofilefs_create_ro_ulong(sb, hw_dir, "hw_min_interval",
+				&oprofile_min_interval);
+	oprofilefs_create_ro_ulong(sb, hw_dir, "hw_max_interval",
+				&oprofile_max_interval);
+	oprofilefs_create_ulong(sb, hw_dir, "hw_sdbt_blocks",
+				&oprofile_sdbt_blocks);
+
+	return 0;
+}
+
+static int oprofile_hwsampler_init(struct oprofile_operations *ops)
+{
+	if (hwsampler_setup())
+		return -ENODEV;
+
+	/*
+	 * create hwsampler files only if hwsampler_setup() succeeds.
+	 */
+	oprofile_min_interval = hwsampler_query_min_interval();
+	if (oprofile_min_interval == 0)
+		return -ENODEV;
+	oprofile_max_interval = hwsampler_query_max_interval();
+	if (oprofile_max_interval == 0)
+		return -ENODEV;
+
+	if (oprofile_timer_init(ops))
+		return -ENODEV;
+
+	printk(KERN_INFO "oprofile: using hardware sampling\n");
+
+	memcpy(&timer_ops, ops, sizeof(timer_ops));
+
+	ops->start = oprofile_hwsampler_start;
+	ops->stop = oprofile_hwsampler_stop;
+	ops->create_files = oprofile_create_hwsampling_files;
+
+	return 0;
+}
+
+static void oprofile_hwsampler_exit(void)
+{
+	oprofile_timer_exit();
+	hwsampler_shutdown();
+}
+
+#endif /* CONFIG_64BIT */
+
+int __init oprofile_arch_init(struct oprofile_operations *ops)
 {
 	ops->backtrace = s390_backtrace;
+
+#ifdef CONFIG_64BIT
+	return oprofile_hwsampler_init(ops);
+#else
 	return -ENODEV;
+#endif
 }
 
 void oprofile_arch_exit(void)
 {
+#ifdef CONFIG_64BIT
+	oprofile_hwsampler_exit();
+#endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/s390/oprofile/Makefile linux-libre-2.6.39-gnu/arch/s390/oprofile/Makefile
--- linux-libre-2.6.38-gnu/arch/s390/oprofile/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/s390/oprofile/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,4 +6,5 @@
 		oprofilefs.o oprofile_stats.o  \
 		timer_int.o )
 
-oprofile-y				:= $(DRIVER_OBJS) init.o backtrace.o
+oprofile-y :=	$(DRIVER_OBJS) init.o backtrace.o
+oprofile-$(CONFIG_64BIT)	+= hwsampler.o
diff -druN linux-libre-2.6.38-gnu/arch/score/include/asm/irqflags.h linux-libre-2.6.39-gnu/arch/score/include/asm/irqflags.h
--- linux-libre-2.6.38-gnu/arch/score/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/score/include/asm/irqflags.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 
 static inline unsigned long arch_local_irq_save(void)
 {
-	unsigned long flags
+	unsigned long flags;
 
 	asm volatile(
 		"	mfcr	r8, cr0		\n"
diff -druN linux-libre-2.6.38-gnu/arch/score/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/score/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/score/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/score/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -71,7 +71,7 @@
 register struct thread_info *__current_thread_info __asm__("r28");
 #define current_thread_info()	__current_thread_info
 
-#define alloc_thread_info(tsk) kmalloc(THREAD_SIZE, GFP_KERNEL)
+#define alloc_thread_info_node(tsk, node) kmalloc_node(THREAD_SIZE, GFP_KERNEL, node)
 #define free_thread_info(info) kfree(info)
 
 #endif /* !__ASSEMBLY__ */
diff -druN linux-libre-2.6.38-gnu/arch/score/Kconfig linux-libre-2.6.39-gnu/arch/score/Kconfig
--- linux-libre-2.6.38-gnu/arch/score/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/score/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,7 @@
 config SCORE
        def_bool y
        select HAVE_GENERIC_HARDIRQS
+       select GENERIC_IRQ_SHOW
 
 choice
 	prompt "System type"
diff -druN linux-libre-2.6.38-gnu/arch/score/kernel/irq.c linux-libre-2.6.39-gnu/arch/score/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/score/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/score/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,9 +52,9 @@
 	irq_exit();
 }
 
-static void score_mask(unsigned int irq_nr)
+static void score_mask(struct irq_data *d)
 {
-	unsigned int irq_source = 63 - irq_nr;
+	unsigned int irq_source = 63 - d->irq;
 
 	if (irq_source < 32)
 		__raw_writel((__raw_readl(SCORE_PIC + INT_MASKL) | \
@@ -64,9 +64,9 @@
 			(1 << (irq_source - 32))), SCORE_PIC + INT_MASKH);
 }
 
-static void score_unmask(unsigned int irq_nr)
+static void score_unmask(struct irq_data *d)
 {
-	unsigned int irq_source = 63 - irq_nr;
+	unsigned int irq_source = 63 - d->irq;
 
 	if (irq_source < 32)
 		__raw_writel((__raw_readl(SCORE_PIC + INT_MASKL) & \
@@ -78,9 +78,9 @@
 
 struct irq_chip score_irq_chip = {
 	.name		= "Score7-level",
-	.mask		= score_mask,
-	.mask_ack	= score_mask,
-	.unmask		= score_unmask,
+	.irq_mask	= score_mask,
+	.irq_mask_ack	= score_mask,
+	.irq_unmask	= score_unmask,
 };
 
 /*
@@ -92,7 +92,7 @@
 	unsigned long target_addr;
 
 	for (index = 0; index < NR_IRQS; ++index)
-		set_irq_chip_and_handler(index, &score_irq_chip,
+		irq_set_chip_and_handler(index, &score_irq_chip,
 					 handle_level_irq);
 
 	for (target_addr = IRQ_VECTOR_BASE_ADDR;
@@ -109,40 +109,3 @@
 		: : "r" (EXCEPTION_VECTOR_BASE_ADDR | \
 			VECTOR_ADDRESS_OFFSET_MODE16));
 }
-
-/*
- * Generic, controller-independent functions:
- */
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *)v, cpu;
-	struct irqaction *action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_puts(p, "           ");
-		for_each_online_cpu(cpu)
-			seq_printf(p, "CPU%d       ", cpu);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto unlock;
-
-		seq_printf(p, "%3d: ", i);
-		seq_printf(p, "%10u ", kstat_irqs(i));
-		seq_printf(p, " %8s", irq_desc[i].chip->name ? : "-");
-		seq_printf(p, "  %s", action->name);
-		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-unlock:
-		spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-
-	return 0;
-}
diff -druN linux-libre-2.6.38-gnu/arch/score/Makefile linux-libre-2.6.39-gnu/arch/score/Makefile
--- linux-libre-2.6.38-gnu/arch/score/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/score/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -40,5 +40,5 @@
 define archhelp
 	echo '  vmlinux.bin          - Raw binary boot image'
 	echo
-	echo '  These will be default as apropriate for a configured platform.'
+	echo '  These will be default as appropriate for a configured platform.'
 endef
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/board-edosk7760.c linux-libre-2.6.39-gnu/arch/sh/boards/board-edosk7760.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/board-edosk7760.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/board-edosk7760.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
 	}, {
 		.name = "fs",
 		.offset = MTDPART_OFS_APPEND,
-		.size = SZ_26M,
+		.size = (26 << 20),
 	}, {
 		.name = "other",
 		.offset = MTDPART_OFS_APPEND,
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/board-espt.c linux-libre-2.6.39-gnu/arch/sh/boards/board-espt.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/board-espt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/board-espt.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,6 +66,11 @@
 		.end    = 0xFEE00F7C - 1,
 		.flags  = IORESOURCE_MEM,
 	}, {
+		.start  = 0xFEE01800,   /* TSU */
+		.end    = 0xFEE01FFF,
+		.flags  = IORESOURCE_MEM,
+	}, {
+
 		.start  = 57,   /* irq number */
 		.flags  = IORESOURCE_IRQ,
 	},
@@ -74,6 +79,8 @@
 static struct sh_eth_plat_data sh7763_eth_pdata = {
 	.phy = 0,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
 };
 
 static struct platform_device espt_eth_device = {
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/board-magicpanelr2.c linux-libre-2.6.39-gnu/arch/sh/boards/board-magicpanelr2.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/board-magicpanelr2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/board-magicpanelr2.c	2011-05-19 00:06:34.000000000 -0400
@@ -388,12 +388,12 @@
 {
 	plat_irq_setup_pins(IRQ_MODE_IRQ); /* install handlers for IRQ0-5 */
 
-	set_irq_type(32, IRQ_TYPE_LEVEL_LOW);    /* IRQ0 CAN1 */
-	set_irq_type(33, IRQ_TYPE_LEVEL_LOW);    /* IRQ1 CAN2 */
-	set_irq_type(34, IRQ_TYPE_LEVEL_LOW);    /* IRQ2 CAN3 */
-	set_irq_type(35, IRQ_TYPE_LEVEL_LOW);    /* IRQ3 SMSC9115 */
-	set_irq_type(36, IRQ_TYPE_EDGE_RISING);  /* IRQ4 touchscreen */
-	set_irq_type(37, IRQ_TYPE_EDGE_FALLING); /* IRQ5 touchscreen */
+	irq_set_irq_type(32, IRQ_TYPE_LEVEL_LOW);    /* IRQ0 CAN1 */
+	irq_set_irq_type(33, IRQ_TYPE_LEVEL_LOW);    /* IRQ1 CAN2 */
+	irq_set_irq_type(34, IRQ_TYPE_LEVEL_LOW);    /* IRQ2 CAN3 */
+	irq_set_irq_type(35, IRQ_TYPE_LEVEL_LOW);    /* IRQ3 SMSC9115 */
+	irq_set_irq_type(36, IRQ_TYPE_EDGE_RISING);  /* IRQ4 touchscreen */
+	irq_set_irq_type(37, IRQ_TYPE_EDGE_FALLING); /* IRQ5 touchscreen */
 
 	intc_set_priority(32, 13);		/* IRQ0 CAN1 */
 	intc_set_priority(33, 13);		/* IRQ0 CAN2 */
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/board-sh7757lcr.c linux-libre-2.6.39-gnu/arch/sh/boards/board-sh7757lcr.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/board-sh7757lcr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/board-sh7757lcr.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,9 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/flash.h>
 #include <linux/io.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <cpu/sh7757.h>
 #include <asm/sh_eth.h>
 #include <asm/heartbeat.h>
@@ -44,6 +47,17 @@
 };
 
 /* Fast Ethernet */
+#define GBECONT		0xffc10100
+#define GBECONT_RMII1	BIT(17)
+#define GBECONT_RMII0	BIT(16)
+static void sh7757_eth_set_mdio_gate(unsigned long addr)
+{
+	if ((addr & 0x00000fff) < 0x0800)
+		writel(readl(GBECONT) | GBECONT_RMII0, GBECONT);
+	else
+		writel(readl(GBECONT) | GBECONT_RMII1, GBECONT);
+}
+
 static struct resource sh_eth0_resources[] = {
 	{
 		.start  = 0xfef00000,
@@ -59,6 +73,8 @@
 static struct sh_eth_plat_data sh7757_eth0_pdata = {
 	.phy = 1,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_FAST_SH4,
+	.set_mdio_gate = sh7757_eth_set_mdio_gate,
 };
 
 static struct platform_device sh7757_eth0_device = {
@@ -86,6 +102,8 @@
 static struct sh_eth_plat_data sh7757_eth1_pdata = {
 	.phy = 1,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_FAST_SH4,
+	.set_mdio_gate = sh7757_eth_set_mdio_gate,
 };
 
 static struct platform_device sh7757_eth1_device = {
@@ -98,10 +116,173 @@
 	},
 };
 
+static void sh7757_eth_giga_set_mdio_gate(unsigned long addr)
+{
+	if ((addr & 0x00000fff) < 0x0800) {
+		gpio_set_value(GPIO_PTT4, 1);
+		writel(readl(GBECONT) & ~GBECONT_RMII0, GBECONT);
+	} else {
+		gpio_set_value(GPIO_PTT4, 0);
+		writel(readl(GBECONT) & ~GBECONT_RMII1, GBECONT);
+	}
+}
+
+static struct resource sh_eth_giga0_resources[] = {
+	{
+		.start  = 0xfee00000,
+		.end    = 0xfee007ff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		/* TSU */
+		.start  = 0xfee01800,
+		.end    = 0xfee01fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = 315,
+		.end    = 315,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_eth_plat_data sh7757_eth_giga0_pdata = {
+	.phy = 18,
+	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
+	.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
+};
+
+static struct platform_device sh7757_eth_giga0_device = {
+	.name		= "sh-eth",
+	.resource	= sh_eth_giga0_resources,
+	.id		= 2,
+	.num_resources	= ARRAY_SIZE(sh_eth_giga0_resources),
+	.dev		= {
+		.platform_data = &sh7757_eth_giga0_pdata,
+	},
+};
+
+static struct resource sh_eth_giga1_resources[] = {
+	{
+		.start  = 0xfee00800,
+		.end    = 0xfee00fff,
+		.flags  = IORESOURCE_MEM,
+	}, {
+		.start  = 316,
+		.end    = 316,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_eth_plat_data sh7757_eth_giga1_pdata = {
+	.phy = 19,
+	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.set_mdio_gate = sh7757_eth_giga_set_mdio_gate,
+	.phy_interface = PHY_INTERFACE_MODE_RGMII_ID,
+};
+
+static struct platform_device sh7757_eth_giga1_device = {
+	.name		= "sh-eth",
+	.resource	= sh_eth_giga1_resources,
+	.id		= 3,
+	.num_resources	= ARRAY_SIZE(sh_eth_giga1_resources),
+	.dev		= {
+		.platform_data = &sh7757_eth_giga1_pdata,
+	},
+};
+
+/* SH_MMCIF */
+static struct resource sh_mmcif_resources[] = {
+	[0] = {
+		.start	= 0xffcb0000,
+		.end	= 0xffcb00ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 211,
+		.flags	= IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start	= 212,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct sh_mmcif_dma sh7757lcr_mmcif_dma = {
+	.chan_priv_tx	= SHDMA_SLAVE_MMCIF_TX,
+	.chan_priv_rx	= SHDMA_SLAVE_MMCIF_RX,
+};
+
+static struct sh_mmcif_plat_data sh_mmcif_plat = {
+	.dma		= &sh7757lcr_mmcif_dma,
+	.sup_pclk	= 0x0f,
+	.caps		= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA,
+	.ocr		= MMC_VDD_32_33 | MMC_VDD_33_34,
+};
+
+static struct platform_device sh_mmcif_device = {
+	.name		= "sh_mmcif",
+	.id		= 0,
+	.dev		= {
+		.platform_data		= &sh_mmcif_plat,
+	},
+	.num_resources	= ARRAY_SIZE(sh_mmcif_resources),
+	.resource	= sh_mmcif_resources,
+};
+
+/* SDHI0 */
+static struct sh_mobile_sdhi_info sdhi_info = {
+	.dma_slave_tx	= SHDMA_SLAVE_SDHI_TX,
+	.dma_slave_rx	= SHDMA_SLAVE_SDHI_RX,
+	.tmio_caps	= MMC_CAP_SD_HIGHSPEED,
+};
+
+static struct resource sdhi_resources[] = {
+	[0] = {
+		.start  = 0xffe50000,
+		.end    = 0xffe501ff,
+		.flags  = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start  = 20,
+		.flags  = IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device sdhi_device = {
+	.name           = "sh_mobile_sdhi",
+	.num_resources  = ARRAY_SIZE(sdhi_resources),
+	.resource       = sdhi_resources,
+	.id             = 0,
+	.dev	= {
+		.platform_data	= &sdhi_info,
+	},
+};
+
 static struct platform_device *sh7757lcr_devices[] __initdata = {
 	&heartbeat_device,
 	&sh7757_eth0_device,
 	&sh7757_eth1_device,
+	&sh7757_eth_giga0_device,
+	&sh7757_eth_giga1_device,
+	&sh_mmcif_device,
+	&sdhi_device,
+};
+
+static struct flash_platform_data spi_flash_data = {
+	.name = "m25p80",
+	.type = "m25px64",
+};
+
+static struct spi_board_info spi_board_info[] = {
+	{
+		.modalias = "m25p80",
+		.max_speed_hz = 25000000,
+		.bus_num = 0,
+		.chip_select = 1,
+		.platform_data = &spi_flash_data,
+	},
 };
 
 static int __init sh7757lcr_devices_setup(void)
@@ -332,6 +513,10 @@
 	gpio_request(GPIO_PTT5, NULL);		/* eMMC_PRST# */
 	gpio_direction_output(GPIO_PTT5, 1);
 
+	/* register SPI device information */
+	spi_register_board_info(spi_board_info,
+				ARRAY_SIZE(spi_board_info));
+
 	/* General platform */
 	return platform_add_devices(sh7757lcr_devices,
 				    ARRAY_SIZE(sh7757lcr_devices));
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-ap325rxa/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-ap325rxa/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-ap325rxa/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-ap325rxa/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,8 +14,8 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/sh_flctl.h>
 #include <linux/delay.h>
@@ -156,24 +156,34 @@
 #define PORT_DRVCRA	0xA405018A
 #define PORT_DRVCRB	0xA405018C
 
+static int ap320_wvga_set_brightness(void *board_data, int brightness)
+{
+	if (brightness) {
+		gpio_set_value(GPIO_PTS3, 0);
+		__raw_writew(0x100, FPGA_BKLREG);
+	} else {
+		__raw_writew(0, FPGA_BKLREG);
+		gpio_set_value(GPIO_PTS3, 1);
+	}
+	
+	return 0;
+}
+
+static int ap320_wvga_get_brightness(void *board_data)
+{
+	return gpio_get_value(GPIO_PTS3);
+}
+
 static void ap320_wvga_power_on(void *board_data, struct fb_info *info)
 {
 	msleep(100);
 
 	/* ASD AP-320/325 LCD ON */
 	__raw_writew(FPGA_LCDREG_VAL, FPGA_LCDREG);
-
-	/* backlight */
-	gpio_set_value(GPIO_PTS3, 0);
-	__raw_writew(0x100, FPGA_BKLREG);
 }
 
 static void ap320_wvga_power_off(void *board_data)
 {
-	/* backlight */
-	__raw_writew(0, FPGA_BKLREG);
-	gpio_set_value(GPIO_PTS3, 1);
-
 	/* ASD AP-320/325 LCD OFF */
 	__raw_writew(0, FPGA_LCDREG);
 }
@@ -209,6 +219,12 @@
 		.board_cfg = {
 			.display_on = ap320_wvga_power_on,
 			.display_off = ap320_wvga_power_off,
+			.set_brightness = ap320_wvga_set_brightness,
+			.get_brightness = ap320_wvga_get_brightness,
+		},
+		.bl_info = {
+			.name = "sh_mobile_lcdc_bl",
+			.max_brightness = 1,
 		},
 	}
 };
@@ -423,7 +439,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start	= 0x04ce0000,
-		.end	= 0x04ce01ff,
+		.end	= 0x04ce00ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
@@ -453,7 +469,7 @@
 	[0] = {
 		.name	= "SDHI1",
 		.start	= 0x04cf0000,
-		.end	= 0x04cf01ff,
+		.end	= 0x04cf00ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-cayman/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-cayman/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-cayman/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-cayman/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,8 +149,8 @@
 	}
 
 	for (i = 0; i < NR_EXT_IRQS; i++) {
-		set_irq_chip_and_handler(START_EXT_IRQS + i, &cayman_irq_type,
-					 handle_level_irq);
+		irq_set_chip_and_handler(START_EXT_IRQS + i,
+					 &cayman_irq_type, handle_level_irq);
 	}
 
 	/* Setup the SMSC interrupt */
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-dreamcast/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-dreamcast/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-dreamcast/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-dreamcast/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
  */
 #define LEVEL(event) (((event) - HW_EVENT_IRQ_BASE) / 32)
 
-/* Return the hardware event's bit positon within the EMR/ESR */
+/* Return the hardware event's bit position within the EMR/ESR */
 #define EVENT_BIT(event) (((event) - HW_EVENT_IRQ_BASE) & 31)
 
 /*
@@ -161,7 +161,6 @@
 			return;
 		}
 
-		set_irq_chip_and_handler(i, &systemasic_int,
-					 handle_level_irq);
+		irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-ecovec24/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-ecovec24/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-ecovec24/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-ecovec24/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,9 +11,9 @@
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
@@ -142,6 +142,8 @@
 static struct sh_eth_plat_data sh_eth_plat = {
 	.phy = 0x1f, /* SMSC LAN8700 */
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_FAST_SH4,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
 	.ether_link_active_low = 1
 };
 
@@ -261,6 +263,18 @@
 	},
 };
 
+static int ecovec24_set_brightness(void *board_data, int brightness)
+{
+	gpio_set_value(GPIO_PTR1, brightness);
+
+	return 0;
+}
+
+static int ecovec24_get_brightness(void *board_data)
+{
+	return gpio_get_value(GPIO_PTR1);
+}
+
 static struct sh_mobile_lcdc_info lcdc_info = {
 	.ch[0] = {
 		.interface_type = RGB18,
@@ -271,6 +285,12 @@
 			.height = 91,
 		},
 		.board_cfg = {
+			.set_brightness = ecovec24_set_brightness,
+			.get_brightness = ecovec24_get_brightness,
+		},
+		.bl_info = {
+			.name = "sh_mobile_lcdc_bl",
+			.max_brightness = 1,
 		},
 	}
 };
@@ -462,7 +482,7 @@
 	.irq		= IRQ0,
 };
 
-#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE)
 /* SDHI0 */
 static void sdhi0_set_pwr(struct platform_device *pdev, int state)
 {
@@ -480,7 +500,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start  = 0x04ce0000,
-		.end    = 0x04ce01ff,
+		.end    = 0x04ce00ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -520,7 +540,7 @@
 	[0] = {
 		.name	= "SDHI1",
 		.start  = 0x04cf0000,
-		.end    = 0x04cf01ff,
+		.end    = 0x04cf00ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -723,11 +743,7 @@
 
 /* FSI */
 static struct sh_fsi_platform_info fsi_info = {
-	.portb_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OUT_SLAVE_MODE |
-		       SH_FSI_IN_SLAVE_MODE |
-		       SH_FSI_OFMT(I2S) |
-		       SH_FSI_IFMT(I2S),
+	.portb_flags = SH_FSI_BRS_INV,
 };
 
 static struct resource fsi_resources[] = {
@@ -882,7 +898,7 @@
 	&ceu0_device,
 	&ceu1_device,
 	&keysc_device,
-#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE)
 	&sdhi0_device,
 #if !defined(CONFIG_MMC_SH_MMCIF)
 	&sdhi1_device,
@@ -938,7 +954,7 @@
 		return;
 	}
 
-	/* read MAC address frome EEPROM */
+	/* read MAC address from EEPROM */
 	for (i = 0; i < sizeof(pd->mac_addr); i++) {
 		pd->mac_addr[i] = mac_read(a, 0x10 + i);
 		msleep(10);
@@ -1104,7 +1120,7 @@
 
 		/* enable TouchScreen */
 		i2c_register_board_info(0, &ts_i2c_clients, 1);
-		set_irq_type(IRQ0, IRQ_TYPE_LEVEL_LOW);
+		irq_set_irq_type(IRQ0, IRQ_TYPE_LEVEL_LOW);
 	}
 
 	/* enable CEU0 */
@@ -1164,7 +1180,7 @@
 	gpio_direction_input(GPIO_PTR5);
 	gpio_direction_input(GPIO_PTR6);
 
-#ifdef CONFIG_MFD_SH_MOBILE_SDHI
+#if defined(CONFIG_MMC_TMIO) || defined(CONFIG_MMC_TMIO_MODULE)
 	/* enable SDHI0 on CN11 (needs DS2.4 set to ON) */
 	gpio_request(GPIO_FN_SDHI0CD,  NULL);
 	gpio_request(GPIO_FN_SDHI0WP,  NULL);
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-kfr2r09/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-kfr2r09/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-kfr2r09/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-kfr2r09/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,8 +10,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/interrupt.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/onenand.h>
@@ -354,7 +354,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start  = 0x04ce0000,
-		.end    = 0x04ce01ff,
+		.end    = 0x04ce00ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-landisk/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-landisk/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-landisk/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-landisk/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 
 static void landisk_power_off(void)
 {
-        __raw_writeb(0x01, PA_SHUTDOWN);
+	__raw_writeb(0x01, PA_SHUTDOWN);
 }
 
 static struct resource cf_ide_resources[3];
@@ -85,7 +85,7 @@
 
 static void __init landisk_setup(char **cmdline_p)
 {
-        /* LED ON */
+	/* LED ON */
 	__raw_writeb(__raw_readb(PA_LED) | 0x03, PA_LED);
 
 	printk(KERN_INFO "I-O DATA DEVICE, INC. \"LANDISK Series\" support.\n");
@@ -97,7 +97,6 @@
  */
 static struct sh_machine_vector mv_landisk __initmv = {
 	.mv_name = "LANDISK",
-	.mv_nr_irqs = 72,
 	.mv_setup = landisk_setup,
 	.mv_init_irq = init_landisk_IRQ,
 };
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-microdev/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-microdev/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-microdev/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-microdev/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,7 +117,7 @@
 static void __init make_microdev_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	set_irq_chip_and_handler(irq, &microdev_irq_type, handle_level_irq);
+	irq_set_chip_and_handler(irq, &microdev_irq_type, handle_level_irq);
 	disable_microdev_irq(irq_get_irq_data(irq));
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-migor/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-migor/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-migor/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-migor/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,8 +12,8 @@
 #include <linux/interrupt.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/nand.h>
 #include <linux/i2c.h>
@@ -399,7 +399,7 @@
 	[0] = {
 		.name	= "SDHI",
 		.start	= 0x04ce0000,
-		.end	= 0x04ce01ff,
+		.end	= 0x04ce00ff,
 		.flags	= IORESOURCE_MEM,
 	},
 	[1] = {
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7206/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7206/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7206/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7206/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -92,9 +92,8 @@
 {
 	unsigned short sts0,sts1;
 	unsigned int irq = data->irq;
-	struct irq_desc *desc = irq_to_desc(irq);
 
-	if (!(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
+	if (!irqd_irq_disabled(data) && !irqd_irq_inprogress(data))
 		enable_se7206_irq(data);
 	/* FPGA isr clear */
 	sts0 = __raw_readw(INTSTS0);
@@ -126,7 +125,7 @@
 static void make_se7206_irq(unsigned int irq)
 {
 	disable_irq_nosync(irq);
-	set_irq_chip_and_handler_name(irq, &se7206_irq_chip,
+	irq_set_chip_and_handler_name(irq, &se7206_irq_chip,
 				      handle_level_irq, "level");
 	disable_se7206_irq(irq_get_irq_data(irq));
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7343/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7343/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7343/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7343/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,19 +67,20 @@
 			return;
 		se7343_fpga_irq[i] = irq;
 
-		set_irq_chip_and_handler_name(se7343_fpga_irq[i],
+		irq_set_chip_and_handler_name(se7343_fpga_irq[i],
 					      &se7343_irq_chip,
-					      handle_level_irq, "level");
+					      handle_level_irq,
+					      "level");
 
-		set_irq_chip_data(se7343_fpga_irq[i], (void *)i);
+		irq_set_chip_data(se7343_fpga_irq[i], (void *)i);
 	}
 
-	set_irq_chained_handler(IRQ0_IRQ, se7343_irq_demux);
-	set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
-	set_irq_chained_handler(IRQ1_IRQ, se7343_irq_demux);
-	set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
-	set_irq_chained_handler(IRQ4_IRQ, se7343_irq_demux);
-	set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
-	set_irq_chained_handler(IRQ5_IRQ, se7343_irq_demux);
-	set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux);
+	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux);
+	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux);
+	irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux);
+	irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7722/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7722/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7722/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7722/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,16 +67,17 @@
 			return;
 		se7722_fpga_irq[i] = irq;
 
-		set_irq_chip_and_handler_name(se7722_fpga_irq[i],
+		irq_set_chip_and_handler_name(se7722_fpga_irq[i],
 					      &se7722_irq_chip,
-					      handle_level_irq, "level");
+					      handle_level_irq,
+					      "level");
 
-		set_irq_chip_data(se7722_fpga_irq[i], (void *)i);
+		irq_set_chip_data(se7722_fpga_irq[i], (void *)i);
 	}
 
-	set_irq_chained_handler(IRQ0_IRQ, se7722_irq_demux);
-	set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux);
+	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
 
-	set_irq_chained_handler(IRQ1_IRQ, se7722_irq_demux);
-	set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux);
+	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7724/irq.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7724/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7724/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7724/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,17 +140,16 @@
 			return;
 		}
 
-		set_irq_chip_and_handler_name(irq,
-					      &se7724_irq_chip,
+		irq_set_chip_and_handler_name(irq, &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);
+	irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);
+	irq_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);
+	irq_set_chained_handler(IRQ1_IRQ, se7724_irq_demux);
+	irq_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);
+	irq_set_chained_handler(IRQ2_IRQ, se7724_irq_demux);
+	irq_set_irq_type(IRQ2_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7724/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7724/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-se/7724/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-se/7724/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,8 +14,8 @@
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
 #include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mtd/physmap.h>
 #include <linux/delay.h>
 #include <linux/smc91x.h>
@@ -286,11 +286,7 @@
 /* FSI */
 /* change J20, J21, J22 pin to 1-2 connection to use slave mode */
 static struct sh_fsi_platform_info fsi_info = {
-	.porta_flags = SH_FSI_BRS_INV |
-		       SH_FSI_OUT_SLAVE_MODE |
-		       SH_FSI_IN_SLAVE_MODE |
-		       SH_FSI_OFMT(PCM) |
-		       SH_FSI_IFMT(PCM),
+	.porta_flags = SH_FSI_BRS_INV,
 };
 
 static struct resource fsi_resources[] = {
@@ -460,7 +456,7 @@
 	[0] = {
 		.name	= "SDHI0",
 		.start  = 0x04ce0000,
-		.end    = 0x04ce01ff,
+		.end    = 0x04ce00ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
@@ -492,7 +488,7 @@
 	[0] = {
 		.name	= "SDHI1",
 		.start  = 0x04cf0000,
-		.end    = 0x04cf01ff,
+		.end    = 0x04cf00ff,
 		.flags  = IORESOURCE_MEM,
 	},
 	[1] = {
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-sh7763rdp/setup.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-sh7763rdp/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-sh7763rdp/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-sh7763rdp/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,6 +75,10 @@
 		.end    = 0xFEE00F7C - 1,
 		.flags  = IORESOURCE_MEM,
 	}, {
+		.start  = 0xFEE01800,   /* TSU */
+		.end    = 0xFEE01FFF,
+		.flags  = IORESOURCE_MEM,
+	}, {
 		.start  = 57,   /* irq number */
 		.flags  = IORESOURCE_IRQ,
 	},
@@ -83,6 +87,8 @@
 static struct sh_eth_plat_data sh7763_eth_pdata = {
 	.phy = 1,
 	.edmac_endian = EDMAC_LITTLE_ENDIAN,
+	.register_type = SH_ETH_REG_GIGABIT,
+	.phy_interface = PHY_INTERFACE_MODE_MII,
 };
 
 static struct platform_device sh7763rdp_eth_device = {
diff -druN linux-libre-2.6.38-gnu/arch/sh/boards/mach-x3proto/gpio.c linux-libre-2.6.39-gnu/arch/sh/boards/mach-x3proto/gpio.c
--- linux-libre-2.6.38-gnu/arch/sh/boards/mach-x3proto/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boards/mach-x3proto/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,8 +102,8 @@
 
 		spin_lock_irqsave(&x3proto_gpio_lock, flags);
 		x3proto_gpio_irq_map[i] = irq;
-		set_irq_chip_and_handler_name(irq, &dummy_irq_chip,
-					handle_simple_irq, "gpio");
+		irq_set_chip_and_handler_name(irq, &dummy_irq_chip,
+					      handle_simple_irq, "gpio");
 		spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
 	}
 
@@ -113,8 +113,8 @@
 		x3proto_gpio_chip.base + x3proto_gpio_chip.ngpio,
 		ilsel);
 
-	set_irq_chained_handler(ilsel, x3proto_gpio_irq_handler);
-	set_irq_wake(ilsel, 1);
+	irq_set_chained_handler(ilsel, x3proto_gpio_irq_handler);
+	irq_set_irq_wake(ilsel, 1);
 
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/arch/sh/boot/compressed/Makefile linux-libre-2.6.39-gnu/arch/sh/boot/compressed/Makefile
--- linux-libre-2.6.38-gnu/arch/sh/boot/compressed/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boot/compressed/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,8 @@
 
 OBJECTS = $(obj)/head_$(BITS).o $(obj)/misc.o $(obj)/cache.o
 
+GCOV_PROFILE := n
+
 #
 # IMAGE_OFFSET is the load offset of the compression loader
 #
diff -druN linux-libre-2.6.38-gnu/arch/sh/boot/romimage/mmcif-sh7724.c linux-libre-2.6.39-gnu/arch/sh/boot/romimage/mmcif-sh7724.c
--- linux-libre-2.6.38-gnu/arch/sh/boot/romimage/mmcif-sh7724.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/boot/romimage/mmcif-sh7724.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
  */
 
 #include <linux/mmc/sh_mmcif.h>
+#include <linux/mmc/boot.h>
 #include <mach/romimage.h>
 
 #define MMCIF_BASE      (void __iomem *)0xa4ca0000
@@ -29,7 +30,7 @@
  */
 asmlinkage void mmcif_loader(unsigned char *buf, unsigned long no_bytes)
 {
-	mmcif_update_progress(MMCIF_PROGRESS_ENTER);
+	mmcif_update_progress(MMC_PROGRESS_ENTER);
 
 	/* enable clock to the MMCIF hardware block */
 	__raw_writel(__raw_readl(MSTPCR2) & ~0x20000000, MSTPCR2);
@@ -52,12 +53,12 @@
 	/* high drive capability for MMC pins */
 	__raw_writew(__raw_readw(DRVCRA) | 0x3000, DRVCRA);
 
-	mmcif_update_progress(MMCIF_PROGRESS_INIT);
+	mmcif_update_progress(MMC_PROGRESS_INIT);
 
 	/* setup MMCIF hardware */
 	sh_mmcif_boot_init(MMCIF_BASE);
 
-	mmcif_update_progress(MMCIF_PROGRESS_LOAD);
+	mmcif_update_progress(MMC_PROGRESS_LOAD);
 
 	/* load kernel via MMCIF interface */
 	sh_mmcif_boot_do_read(MMCIF_BASE, 512,
@@ -67,5 +68,5 @@
 	/* disable clock to the MMCIF hardware block */
 	__raw_writel(__raw_readl(MSTPCR2) | 0x20000000, MSTPCR2);
 
-	mmcif_update_progress(MMCIF_PROGRESS_DONE);
+	mmcif_update_progress(MMC_PROGRESS_DONE);
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/cchips/hd6446x/hd64461.c linux-libre-2.6.39-gnu/arch/sh/cchips/hd6446x/hd64461.c
--- linux-libre-2.6.38-gnu/arch/sh/cchips/hd6446x/hd64461.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/cchips/hd6446x/hd64461.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,12 +107,12 @@
 			return -EINVAL;
 		}
 
-		set_irq_chip_and_handler(i, &hd64461_irq_chip,
+		irq_set_chip_and_handler(i, &hd64461_irq_chip,
 					 handle_level_irq);
 	}
 
-	set_irq_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
-	set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
+	irq_set_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
+	irq_set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
 
 #ifdef CONFIG_HD64461_ENABLER
 	printk(KERN_INFO "HD64461: enabling PCMCIA devices\n");
diff -druN linux-libre-2.6.38-gnu/arch/sh/configs/sh7757lcr_defconfig linux-libre-2.6.39-gnu/arch/sh/configs/sh7757lcr_defconfig
--- linux-libre-2.6.38-gnu/arch/sh/configs/sh7757lcr_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/configs/sh7757lcr_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,15 @@
 # CONFIG_WIRELESS is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
 # CONFIG_FW_LOADER is not set
+CONFIG_MTD=y
+CONFIG_MTD_CONCAT=y
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=y
+CONFIG_MTD_BLOCK=y
+CONFIG_MTD_M25P80=y
 CONFIG_BLK_DEV_RAM=y
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
 CONFIG_NETDEVICES=y
 CONFIG_VITESSE_PHY=y
 CONFIG_NET_ETHERNET=y
@@ -53,8 +61,17 @@
 CONFIG_SERIAL_SH_SCI_CONSOLE=y
 # CONFIG_LEGACY_PTYS is not set
 # CONFIG_HW_RANDOM is not set
+CONFIG_SPI=y
+CONFIG_SPI_SH=y
 # CONFIG_HWMON is not set
-# CONFIG_USB_SUPPORT is not set
+CONFIG_MFD_SH_MOBILE_SDHI=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_STORAGE=y
+CONFIG_MMC=y
+CONFIG_MMC_TMIO=y
+CONFIG_MMC_SH_MMCIF=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 CONFIG_ISO9660_FS=y
diff -druN linux-libre-2.6.38-gnu/arch/sh/drivers/pci/pci.c linux-libre-2.6.39-gnu/arch/sh/drivers/pci/pci.c
--- linux-libre-2.6.38-gnu/arch/sh/drivers/pci/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/drivers/pci/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,7 @@
 	hose_tail = &hose->next;
 
 	/*
-	 * Do not panic here but later - this might hapen before console init.
+	 * Do not panic here but later - this might happen before console init.
 	 */
 	if (!hose->io_map_base) {
 		printk(KERN_WARNING
diff -druN linux-libre-2.6.38-gnu/arch/sh/drivers/pci/pcie-sh7786.c linux-libre-2.6.39-gnu/arch/sh/drivers/pci/pcie-sh7786.c
--- linux-libre-2.6.38-gnu/arch/sh/drivers/pci/pcie-sh7786.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/drivers/pci/pcie-sh7786.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,16 +1,19 @@
 /*
  * Low-Level PCI Express Support for the SH7786
  *
- *  Copyright (C) 2009 - 2010  Paul Mundt
+ *  Copyright (C) 2009 - 2011  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.
  */
+#define pr_fmt(fmt) "PCI: " fmt
+
 #include <linux/pci.h>
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/io.h>
+#include <linux/async.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
@@ -31,7 +34,7 @@
 
 static struct sh7786_pcie_hwops {
 	int (*core_init)(void);
-	int (*port_init_hw)(struct sh7786_pcie_port *port);
+	async_func_ptr *port_init_hw;
 } *sh7786_pcie_hwops;
 
 static struct resource sh7786_pci0_resources[] = {
@@ -474,8 +477,9 @@
 	return test_mode_pin(MODE_PIN12) ? 3 : 2;
 }
 
-static int __init sh7786_pcie_init_hw(struct sh7786_pcie_port *port)
+static void __init sh7786_pcie_init_hw(void *data, async_cookie_t cookie)
 {
+	struct sh7786_pcie_port *port = data;
 	int ret;
 
 	/*
@@ -488,18 +492,30 @@
 	 * Setup clocks, needed both for PHY and PCIe registers.
 	 */
 	ret = pcie_clk_init(port);
-	if (unlikely(ret < 0))
-		return ret;
+	if (unlikely(ret < 0)) {
+		pr_err("clock initialization failed for port#%d\n",
+		       port->index);
+		return;
+	}
 
 	ret = phy_init(port);
-	if (unlikely(ret < 0))
-		return ret;
+	if (unlikely(ret < 0)) {
+		pr_err("phy initialization failed for port#%d\n",
+		       port->index);
+		return;
+	}
 
 	ret = pcie_init(port);
-	if (unlikely(ret < 0))
-		return ret;
+	if (unlikely(ret < 0)) {
+		pr_err("core initialization failed for port#%d\n",
+			       port->index);
+		return;
+	}
 
-	return register_pci_controller(port->hose);
+	/* In the interest of preserving device ordering, synchronize */
+	async_synchronize_cookie(cookie);
+
+	register_pci_controller(port->hose);
 }
 
 static struct sh7786_pcie_hwops sh7786_65nm_pcie_hwops __initdata = {
@@ -510,7 +526,7 @@
 static int __init sh7786_pcie_init(void)
 {
 	struct clk *platclk;
-	int ret = 0, i;
+	int i;
 
 	printk(KERN_NOTICE "PCI: Starting initialization.\n");
 
@@ -552,14 +568,10 @@
 		port->hose		= sh7786_pci_channels + i;
 		port->hose->io_map_base	= port->hose->resources[0].start;
 
-		ret |= sh7786_pcie_hwops->port_init_hw(port);
+		async_schedule(sh7786_pcie_hwops->port_init_hw, port);
 	}
 
-	if (unlikely(ret)) {
-		clk_disable(platclk);
-		clk_put(platclk);
-		return ret;
-	}
+	async_synchronize_full();
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/drivers/pci/pci-sh7751.h linux-libre-2.6.39-gnu/arch/sh/drivers/pci/pci-sh7751.h
--- linux-libre-2.6.38-gnu/arch/sh/drivers/pci/pci-sh7751.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/drivers/pci/pci-sh7751.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
   #define SH7751_PCICONF3_BIST7      0x80000000  /* Bist Supported */
   #define SH7751_PCICONF3_BIST6      0x40000000  /* Bist Executing */
   #define SH7751_PCICONF3_BIST3_0    0x0F000000  /* Bist Passed */
-  #define SH7751_PCICONF3_HD7        0x00800000  /* Single Funtion device */
+  #define SH7751_PCICONF3_HD7        0x00800000  /* Single Function device */
   #define SH7751_PCICONF3_HD6_0      0x007F0000  /* Configuration Layout */
   #define SH7751_PCICONF3_LAT        0x0000FF00  /* Latency Timer */
   #define SH7751_PCICONF3_CLS        0x000000FF  /* Cache Line Size */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/sh/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,9 +94,8 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
 #include <asm-generic/bitops/fls.h>
 #include <asm-generic/bitops/__fls.h>
 #include <asm-generic/bitops/fls64.h>
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/futex.h linux-libre-2.6.39-gnu/arch/sh/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,7 @@
 /* XXX: UP variants, fix for SH-4A and SMP.. */
 #include <asm/futex-irq.h>
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -21,7 +21,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -65,12 +65,13 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	return atomic_futex_op_cmpxchg_inatomic(uaddr, oldval, newval);
+	return atomic_futex_op_cmpxchg_inatomic(uval, uaddr, oldval, newval);
 }
 
 #endif /* __KERNEL__ */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/futex-irq.h linux-libre-2.6.39-gnu/arch/sh/include/asm/futex-irq.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/futex-irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/futex-irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
 
 #include <asm/system.h>
 
-static inline int atomic_futex_op_xchg_set(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_set(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -20,7 +20,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_add(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_add(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -37,7 +37,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_or(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_or(int oparg, u32 __user *uaddr,
 					  int *oldval)
 {
 	unsigned long flags;
@@ -54,7 +54,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_and(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_and(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -71,7 +71,7 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_xchg_xor(int oparg, int __user *uaddr,
+static inline int atomic_futex_op_xchg_xor(int oparg, u32 __user *uaddr,
 					   int *oldval)
 {
 	unsigned long flags;
@@ -88,11 +88,13 @@
 	return ret;
 }
 
-static inline int atomic_futex_op_cmpxchg_inatomic(int __user *uaddr,
-						   int oldval, int newval)
+static inline int atomic_futex_op_cmpxchg_inatomic(u32 *uval,
+						   u32 __user *uaddr,
+						   u32 oldval, u32 newval)
 {
 	unsigned long flags;
-	int ret, prev = 0;
+	int ret;
+	u32 prev = 0;
 
 	local_irq_save(flags);
 
@@ -102,10 +104,8 @@
 
 	local_irq_restore(flags);
 
-	if (ret)
-		return ret;
-
-	return prev;
+	*uval = prev;
+	return ret;
 }
 
 #endif /* __ASM_SH_FUTEX_IRQ_H */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/sh/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -87,6 +87,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	_IO('T', 0x37)
 
 #define TIOCSERCONFIG	_IO('T', 83) /* 0x5453 */
 #define TIOCSERGWILD	_IOR('T', 84,  int) /* 0x5454 */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/page.h linux-libre-2.6.39-gnu/arch/sh/include/asm/page.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/page.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/page.h	2011-05-19 00:06:34.000000000 -0400
@@ -186,7 +186,7 @@
 /*
  * While BYTES_PER_WORD == 4 on the current sh64 ABI, GCC will still
  * happily generate {ld/st}.q pairs, requiring us to have 8-byte
- * alignment to avoid traps. The kmalloc alignment is gauranteed by
+ * alignment to avoid traps. The kmalloc alignment is guaranteed by
  * virtue of L1_CACHE_BYTES, requiring this to only be special cased
  * for slab caches.
  */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/pgtable_32.h linux-libre-2.6.39-gnu/arch/sh/include/asm/pgtable_32.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/pgtable_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/pgtable_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 #endif
 
 /*
- * Mask of bits that are to be preserved accross pgprot changes.
+ * Mask of bits that are to be preserved across pgprot changes.
  */
 #define _PAGE_CHG_MASK \
 	(PTE_MASK | _PAGE_ACCESSED | _PAGE_CACHABLE | \
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/sh/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,64 +11,13 @@
 #endif
 
 #ifdef __KERNEL__
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
 
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	long		count;
 #define RWSEM_UNLOCKED_VALUE		0x00000000
 #define RWSEM_ACTIVE_BIAS		0x00000001
 #define RWSEM_ACTIVE_MASK		0x0000ffff
 #define RWSEM_WAITING_BIAS		(-0x00010000)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map	dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-	  LIST_HEAD_INIT((name).wait_list) \
-	  __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)				\
-do {						\
-	static struct lock_class_key __key;	\
-						\
-	__init_rwsem((sem), #sem, &__key);	\
-} while (0)
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
 
 /*
  * lock for reading
@@ -179,10 +128,5 @@
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_SH_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/sh_eth.h linux-libre-2.6.39-gnu/arch/sh/include/asm/sh_eth.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/sh_eth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/sh_eth.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,11 +1,21 @@
 #ifndef __ASM_SH_ETH_H__
 #define __ASM_SH_ETH_H__
 
+#include <linux/phy.h>
+
 enum {EDMAC_LITTLE_ENDIAN, EDMAC_BIG_ENDIAN};
+enum {
+	SH_ETH_REG_GIGABIT,
+	SH_ETH_REG_FAST_SH4,
+	SH_ETH_REG_FAST_SH3_SH2
+};
 
 struct sh_eth_plat_data {
 	int phy;
 	int edmac_endian;
+	int register_type;
+	phy_interface_t phy_interface;
+	void (*set_mdio_gate)(unsigned long addr);
 
 	unsigned char mac_addr[6];
 	unsigned no_ether_link:1;
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/sizes.h linux-libre-2.6.39-gnu/arch/sh/include/asm/sizes.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/sizes.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/sizes.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,62 +1 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the 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
- */
-/* DO NOT EDIT!! - this file automatically generated
- *                 from .s file by awk -f s2h.awk
- */
-/*  Size definitions
- *  Copyright (C) ARM Limited 1998. All rights reserved.
- */
-
-#ifndef __sizes_h
-#define __sizes_h                       1
-
-/* handy sizes */
-#define SZ_16				0x00000010
-#define SZ_32				0x00000020
-#define SZ_64				0x00000040
-#define SZ_128				0x00000080
-#define SZ_256				0x00000100
-#define SZ_512				0x00000200
-
-#define SZ_1K                           0x00000400
-#define SZ_2K                           0x00000800
-#define SZ_4K                           0x00001000
-#define SZ_8K                           0x00002000
-#define SZ_16K                          0x00004000
-#define SZ_32K				0x00008000
-#define SZ_64K                          0x00010000
-#define SZ_128K                         0x00020000
-#define SZ_256K                         0x00040000
-#define SZ_512K                         0x00080000
-
-#define SZ_1M                           0x00100000
-#define SZ_2M                           0x00200000
-#define SZ_4M                           0x00400000
-#define SZ_8M                           0x00800000
-#define SZ_16M                          0x01000000
-#define SZ_26M				0x01a00000
-#define SZ_32M                          0x02000000
-#define SZ_64M                          0x04000000
-#define SZ_128M                         0x08000000
-#define SZ_256M                         0x10000000
-#define SZ_512M                         0x20000000
-
-#define SZ_1G                           0x40000000
-#define SZ_2G                           0x80000000
-
-#endif
-
-/*         END */
+#include <asm-generic/sizes.h>
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/sh/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 
 #endif
 
-extern struct thread_info *alloc_thread_info(struct task_struct *tsk);
+extern struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node);
 extern void free_thread_info(struct thread_info *ti);
 extern void arch_task_cache_init(void);
 #define arch_task_cache_init arch_task_cache_init
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/unaligned-sh4a.h linux-libre-2.6.39-gnu/arch/sh/include/asm/unaligned-sh4a.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/unaligned-sh4a.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/unaligned-sh4a.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
  * struct.
  *
  * The same note as with the movli.l/movco.l pair applies here, as long
- * as the load is gauranteed to be inlined, nothing else will hook in to
+ * as the load is guaranteed to be inlined, nothing else will hook in to
  * r0 and we get the return value for free.
  *
  * NOTE: Due to the fact we require r0 encoding, care should be taken to
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/unistd_32.h linux-libre-2.6.39-gnu/arch/sh/include/asm/unistd_32.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/unistd_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/unistd_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -369,8 +369,12 @@
 #define __NR_recvmsg		356
 #define __NR_recvmmsg		357
 #define __NR_accept4		358
+#define __NR_name_to_handle_at	359
+#define __NR_open_by_handle_at	360
+#define __NR_clock_adjtime	361
+#define __NR_syncfs		362
 
-#define NR_syscalls 359
+#define NR_syscalls 363
 
 #ifdef __KERNEL__
 
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/asm/unistd_64.h linux-libre-2.6.39-gnu/arch/sh/include/asm/unistd_64.h
--- linux-libre-2.6.38-gnu/arch/sh/include/asm/unistd_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/asm/unistd_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -390,10 +390,14 @@
 #define __NR_fanotify_init	367
 #define __NR_fanotify_mark	368
 #define __NR_prlimit64		369
+#define __NR_name_to_handle_at	370
+#define __NR_open_by_handle_at	371
+#define __NR_clock_adjtime	372
+#define __NR_syncfs		373
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 370
+#define NR_syscalls 374
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h linux-libre-2.6.39-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h
--- linux-libre-2.6.38-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/cpu-sh4/cpu/dma-register.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,11 @@
 #define CHCR_TS_LOW_SHIFT	3
 #define CHCR_TS_HIGH_MASK	0
 #define CHCR_TS_HIGH_SHIFT	0
+#elif defined(CONFIG_CPU_SUBTYPE_SH7757)
+#define CHCR_TS_LOW_MASK	0x00000018
+#define CHCR_TS_LOW_SHIFT	3
+#define CHCR_TS_HIGH_MASK	0x00100000
+#define CHCR_TS_HIGH_SHIFT	(20 - 2)	/* 2 bits for shifted low TS */
 #elif defined(CONFIG_CPU_SUBTYPE_SH7780)
 #define CHCR_TS_LOW_MASK	0x00000018
 #define CHCR_TS_LOW_SHIFT	3
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/cpu-sh4/cpu/sh7757.h linux-libre-2.6.39-gnu/arch/sh/include/cpu-sh4/cpu/sh7757.h
--- linux-libre-2.6.38-gnu/arch/sh/include/cpu-sh4/cpu/sh7757.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/cpu-sh4/cpu/sh7757.h	2011-05-19 00:06:34.000000000 -0400
@@ -251,4 +251,36 @@
 	GPIO_FN_ON_DQ3,	GPIO_FN_ON_DQ2,	GPIO_FN_ON_DQ1,	GPIO_FN_ON_DQ0,
 };
 
+enum {
+	SHDMA_SLAVE_SDHI_TX,
+	SHDMA_SLAVE_SDHI_RX,
+	SHDMA_SLAVE_MMCIF_TX,
+	SHDMA_SLAVE_MMCIF_RX,
+	SHDMA_SLAVE_SCIF2_TX,
+	SHDMA_SLAVE_SCIF2_RX,
+	SHDMA_SLAVE_SCIF3_TX,
+	SHDMA_SLAVE_SCIF3_RX,
+	SHDMA_SLAVE_SCIF4_TX,
+	SHDMA_SLAVE_SCIF4_RX,
+	SHDMA_SLAVE_RIIC0_TX,
+	SHDMA_SLAVE_RIIC0_RX,
+	SHDMA_SLAVE_RIIC1_TX,
+	SHDMA_SLAVE_RIIC1_RX,
+	SHDMA_SLAVE_RIIC2_TX,
+	SHDMA_SLAVE_RIIC2_RX,
+	SHDMA_SLAVE_RIIC3_TX,
+	SHDMA_SLAVE_RIIC3_RX,
+	SHDMA_SLAVE_RIIC4_TX,
+	SHDMA_SLAVE_RIIC4_RX,
+	SHDMA_SLAVE_RIIC5_TX,
+	SHDMA_SLAVE_RIIC5_RX,
+	SHDMA_SLAVE_RIIC6_TX,
+	SHDMA_SLAVE_RIIC6_RX,
+	SHDMA_SLAVE_RIIC7_TX,
+	SHDMA_SLAVE_RIIC7_RX,
+	SHDMA_SLAVE_RIIC8_TX,
+	SHDMA_SLAVE_RIIC8_RX,
+	SHDMA_SLAVE_RIIC9_TX,
+	SHDMA_SLAVE_RIIC9_RX,
+};
 #endif /* __ASM_SH7757_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/mach-common/mach/highlander.h linux-libre-2.6.39-gnu/arch/sh/include/mach-common/mach/highlander.h
--- linux-libre-2.6.38-gnu/arch/sh/include/mach-common/mach/highlander.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/mach-common/mach/highlander.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 #define PA_OBLED        (PA_BCR+0x001c) /* On Board LED control */
 #define PA_OBSW         (PA_BCR+0x001e) /* On Board Switch control */
 #define PA_AUDIOSEL     (PA_BCR+0x0020) /* Sound Interface Select control */
-#define PA_EXTPLR       (PA_BCR+0x001e) /* Extention Pin Polarity control */
+#define PA_EXTPLR       (PA_BCR+0x001e) /* Extension Pin Polarity control */
 #define PA_TPCTL        (PA_BCR+0x0100) /* Touch Panel Access control */
 #define PA_TPDCKCTL     (PA_BCR+0x0102) /* Touch Panel Access data control */
 #define PA_TPCTLCLR     (PA_BCR+0x0104) /* Touch Panel Access control */
@@ -89,7 +89,7 @@
 #define PA_OBLED	(PA_BCR+0x0018)	/* On Board LED control */
 #define PA_OBSW		(PA_BCR+0x001a)	/* On Board Switch control */
 #define PA_AUDIOSEL	(PA_BCR+0x001c)	/* Sound Interface Select control */
-#define PA_EXTPLR	(PA_BCR+0x001e)	/* Extention Pin Polarity control */
+#define PA_EXTPLR	(PA_BCR+0x001e)	/* Extension Pin Polarity control */
 #define PA_TPCTL	(PA_BCR+0x0100)	/* Touch Panel Access control */
 #define PA_TPDCKCTL	(PA_BCR+0x0102)	/* Touch Panel Access data control */
 #define PA_TPCTLCLR	(PA_BCR+0x0104)	/* Touch Panel Access control */
diff -druN linux-libre-2.6.38-gnu/arch/sh/include/mach-common/mach/r2d.h linux-libre-2.6.39-gnu/arch/sh/include/mach-common/mach/r2d.h
--- linux-libre-2.6.38-gnu/arch/sh/include/mach-common/mach/r2d.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/include/mach-common/mach/r2d.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,18 +18,18 @@
 #define PA_DISPCTL	0xa4000008	/* Display Timing control */
 #define PA_SDMPOW	0xa400000a	/* SD Power control */
 #define PA_RTCCE	0xa400000c	/* RTC(9701) Enable control */
-#define PA_PCICD	0xa400000e	/* PCI Extention detect control */
+#define PA_PCICD	0xa400000e	/* PCI Extension detect control */
 #define PA_VOYAGERRTS	0xa4000020	/* VOYAGER Reset control */
 
 #define PA_R2D1_AXRST		0xa4000022	/* AX_LAN Reset control */
 #define PA_R2D1_CFRST		0xa4000024	/* CF Reset control */
 #define PA_R2D1_ADMRTS		0xa4000026	/* SD Reset control */
-#define PA_R2D1_EXTRST		0xa4000028	/* Extention Reset control */
+#define PA_R2D1_EXTRST		0xa4000028	/* Extension Reset control */
 #define PA_R2D1_CFCDINTCLR	0xa400002a	/* CF Insert Interrupt clear */
 
 #define PA_R2DPLUS_CFRST	0xa4000022	/* CF Reset control */
 #define PA_R2DPLUS_ADMRTS	0xa4000024	/* SD Reset control */
-#define PA_R2DPLUS_EXTRST	0xa4000026	/* Extention Reset control */
+#define PA_R2DPLUS_EXTRST	0xa4000026	/* Extension Reset control */
 #define PA_R2DPLUS_CFCDINTCLR	0xa4000028	/* CF Insert Interrupt clear */
 #define PA_R2DPLUS_KEYCTLCLR	0xa400002a	/* Key Interrupt clear */
 
diff -druN linux-libre-2.6.38-gnu/arch/sh/Kconfig linux-libre-2.6.39-gnu/arch/sh/Kconfig
--- linux-libre-2.6.38-gnu/arch/sh/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -23,8 +23,8 @@
 	select HAVE_SPARSE_IRQ
 	select RTC_LIB
 	select GENERIC_ATOMIC64
-	# Support the deprecated APIs until MFD and GPIOLIB catch up.
-	select GENERIC_HARDIRQS_NO_DEPRECATED if !MFD_SUPPORT && !GPIOLIB
+	select GENERIC_IRQ_SHOW
+	select ARCH_NO_SYSDEV_OPS
 	help
 	  The SuperH is a RISC processor targeted for use in embedded systems
 	  and consumer electronics; it was also used in the Sega Dreamcast
@@ -74,6 +74,9 @@
 config GENERIC_FIND_NEXT_BIT
 	def_bool y
 
+config GENERIC_FIND_BIT_LE
+	def_bool y
+
 config GENERIC_HWEIGHT
 	def_bool y
 
@@ -434,6 +437,8 @@
 	select CPU_SH4A
 	select CPU_SHX2
 	select ARCH_WANT_OPTIONAL_GPIOLIB
+	select USB_ARCH_HAS_OHCI
+	select USB_ARCH_HAS_EHCI
 	help
 	  Select SH7757 if you have a SH4A SH7757 CPU.
 
diff -druN linux-libre-2.6.38-gnu/arch/sh/Kconfig.debug linux-libre-2.6.39-gnu/arch/sh/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/sh/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 	help
 	  If running in painfully slow environments, such as an RTL
 	  simulation or from remote memory via SHdebug, where the memory
-	  can already be gauranteed to ber zeroed on boot, say Y.
+	  can already be guaranteed to ber zeroed on boot, say Y.
 
 	  For all other cases, say N. If this option seems perplexing, or
 	  you aren't sure, say N.
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/clock-cpg.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/clock-cpg.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/clock-cpg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/clock-cpg.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
 }
 
 /*
- * Placeholder for compatability, until the lazy CPUs do this
+ * Placeholder for compatibility, until the lazy CPUs do this
  * on their own.
  */
 int __init __weak arch_clk_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/irq/imask.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/irq/imask.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/irq/imask.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/irq/imask.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,6 +80,6 @@
 
 void make_imask_irq(unsigned int irq)
 {
-	set_irq_chip_and_handler_name(irq, &imask_irq_chip,
-				      handle_level_irq, "level");
+	irq_set_chip_and_handler_name(irq, &imask_irq_chip, handle_level_irq,
+				      "level");
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/irq/intc-sh5.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,7 +135,7 @@
 
 	/* Set default: per-line enable/disable, priority driven ack/eoi */
 	for (i = 0; i < NR_INTC_IRQS; i++)
-		set_irq_chip_and_handler(i, &intc_irq_type, handle_level_irq);
+		irq_set_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.38-gnu/arch/sh/kernel/cpu/irq/ipr.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/irq/ipr.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/irq/ipr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/irq/ipr.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,9 +74,9 @@
 		}
 
 		disable_irq_nosync(p->irq);
-		set_irq_chip_and_handler_name(p->irq, &desc->chip,
-				      handle_level_irq, "level");
-		set_irq_chip_data(p->irq, p);
+		irq_set_chip_and_handler_name(p->irq, &desc->chip,
+					      handle_level_irq, "level");
+		irq_set_chip_data(p->irq, p);
 		disable_ipr_irq(irq_get_irq_data(p->irq));
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/sh4a/clock-sh7757.c	2011-05-19 00:06:34.000000000 -0400
@@ -77,9 +77,10 @@
 
 #define MSTPCR0		0xffc80030
 #define MSTPCR1		0xffc80034
+#define MSTPCR2		0xffc10028
 
 enum { MSTP004, MSTP000, MSTP114, MSTP113, MSTP112,
-       MSTP111, MSTP110, MSTP103, MSTP102,
+       MSTP111, MSTP110, MSTP103, MSTP102, MSTP220,
        MSTP_NR };
 
 static struct clk mstp_clks[MSTP_NR] = {
@@ -95,6 +96,9 @@
 	[MSTP110] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 10, 0),
 	[MSTP103] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 3, 0),
 	[MSTP102] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR1, 2, 0),
+
+	/* MSTPCR2 */
+	[MSTP220] = SH_CLK_MSTP32(&div4_clks[DIV4_P], MSTPCR2, 20, 0),
 };
 
 #define CLKDEV_CON_ID(_id, _clk) { .con_id = _id, .clk = _clk }
@@ -140,6 +144,7 @@
 		.clk		= &mstp_clks[MSTP110],
 	},
 	CLKDEV_CON_ID("usb0", &mstp_clks[MSTP102]),
+	CLKDEV_CON_ID("mmc0", &mstp_clks[MSTP220]),
 };
 
 int __init arch_clk_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7757.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * SH7757 Setup
  *
- * Copyright (C) 2009  Renesas Solutions Corp.
+ * Copyright (C) 2009, 2011  Renesas Solutions Corp.
  *
  *  based on setup-sh7785.c : Copyright (C) 2007  Paul Mundt
  *
@@ -16,6 +16,10 @@
 #include <linux/io.h>
 #include <linux/mm.h>
 #include <linux/sh_timer.h>
+#include <linux/sh_dma.h>
+
+#include <cpu/dma-register.h>
+#include <cpu/sh7757.h>
 
 static struct plat_sci_port scif2_platform_data = {
 	.mapbase	= 0xfe4b0000,		/* SCIF2 */
@@ -124,12 +128,548 @@
 	.num_resources	= ARRAY_SIZE(tmu1_resources),
 };
 
+static struct resource spi0_resources[] = {
+	[0] = {
+		.start	= 0xfe002000,
+		.end	= 0xfe0020ff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= 86,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* DMA */
+static const struct sh_dmae_slave_config sh7757_dmae0_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_SDHI_TX,
+		.addr		= 0x1fe50030,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.mid_rid	= 0xc5,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SDHI_RX,
+		.addr		= 0x1fe50030,
+		.chcr		= DM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_16BIT),
+		.mid_rid	= 0xc6,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_MMCIF_TX,
+		.addr		= 0x1fcb0034,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd3,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_MMCIF_RX,
+		.addr		= 0x1fcb0034,
+		.chcr		= DM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_32BIT),
+		.mid_rid	= 0xd7,
+	},
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae1_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF2_TX,
+		.addr		= 0x1f4b000c,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF2_RX,
+		.addr		= 0x1f4b0014,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF3_TX,
+		.addr		= 0x1f4c000c,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF3_RX,
+		.addr		= 0x1f4c0014,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF4_TX,
+		.addr		= 0x1f4d000c,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x41,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_SCIF4_RX,
+		.addr		= 0x1f4d0014,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x42,
+	},
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae2_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC0_TX,
+		.addr		= 0x1e500012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC0_RX,
+		.addr		= 0x1e500013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC1_TX,
+		.addr		= 0x1e510012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC1_RX,
+		.addr		= 0x1e510013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC2_TX,
+		.addr		= 0x1e520012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xa1,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC2_RX,
+		.addr		= 0x1e520013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xa2,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC3_TX,
+		.addr		= 0x1e530012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xab,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC3_RX,
+		.addr		= 0x1e530013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xaf,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC4_TX,
+		.addr		= 0x1e540012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xc1,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC4_RX,
+		.addr		= 0x1e540013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0xc2,
+	},
+};
+
+static const struct sh_dmae_slave_config sh7757_dmae3_slaves[] = {
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC5_TX,
+		.addr		= 0x1e550012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x21,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC5_RX,
+		.addr		= 0x1e550013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x22,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC6_TX,
+		.addr		= 0x1e560012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x29,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC6_RX,
+		.addr		= 0x1e560013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x2a,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC7_TX,
+		.addr		= 0x1e570012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x41,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC7_RX,
+		.addr		= 0x1e570013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x42,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC8_TX,
+		.addr		= 0x1e580012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x45,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC8_RX,
+		.addr		= 0x1e580013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x46,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC9_TX,
+		.addr		= 0x1e590012,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x51,
+	},
+	{
+		.slave_id	= SHDMA_SLAVE_RIIC9_RX,
+		.addr		= 0x1e590013,
+		.chcr		= SM_INC | 0x800 | 0x40000000 |
+				  TS_INDEX2VAL(XMIT_SZ_8BIT),
+		.mid_rid	= 0x52,
+	},
+};
+
+static const struct sh_dmae_channel sh7757_dmae_channels[] = {
+	{
+		.offset = 0,
+		.dmars = 0,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x10,
+		.dmars = 0,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x20,
+		.dmars = 4,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x30,
+		.dmars = 4,
+		.dmars_bit = 8,
+	}, {
+		.offset = 0x50,
+		.dmars = 8,
+		.dmars_bit = 0,
+	}, {
+		.offset = 0x60,
+		.dmars = 8,
+		.dmars_bit = 8,
+	}
+};
+
+static const unsigned int ts_shift[] = TS_SHIFT;
+
+static struct sh_dmae_pdata dma0_platform_data = {
+	.slave		= sh7757_dmae0_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae0_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma1_platform_data = {
+	.slave		= sh7757_dmae1_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae1_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma2_platform_data = {
+	.slave		= sh7757_dmae2_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae2_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+static struct sh_dmae_pdata dma3_platform_data = {
+	.slave		= sh7757_dmae3_slaves,
+	.slave_num	= ARRAY_SIZE(sh7757_dmae3_slaves),
+	.channel	= sh7757_dmae_channels,
+	.channel_num	= ARRAY_SIZE(sh7757_dmae_channels),
+	.ts_low_shift	= CHCR_TS_LOW_SHIFT,
+	.ts_low_mask	= CHCR_TS_LOW_MASK,
+	.ts_high_shift	= CHCR_TS_HIGH_SHIFT,
+	.ts_high_mask	= CHCR_TS_HIGH_MASK,
+	.ts_shift	= ts_shift,
+	.ts_shift_num	= ARRAY_SIZE(ts_shift),
+	.dmaor_init	= DMAOR_INIT,
+};
+
+/* channel 0 to 5 */
+static struct resource sh7757_dmae0_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff608020,
+		.end	= 0xff60808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff609000,
+		.end	= 0xff60900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= 34,
+		.end	= 34,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+/* channel 6 to 11 */
+static struct resource sh7757_dmae1_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff618020,
+		.end	= 0xff61808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff619000,
+		.end	= 0xff61900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error */
+		.start	= 34,
+		.end	= 34,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 4 */
+		.start	= 46,
+		.end	= 46,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 5 */
+		.start	= 46,
+		.end	= 46,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 6 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 7 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 8 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 9 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 10 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+	{
+		/* IRQ for channels 11 */
+		.start	= 88,
+		.end	= 88,
+		.flags	= IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE,
+	},
+};
+
+/* channel 12 to 17 */
+static struct resource sh7757_dmae2_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff708020,
+		.end	= 0xff70808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff709000,
+		.end	= 0xff70900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error */
+		.start	= 323,
+		.end	= 323,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 12 to 16 */
+		.start	= 272,
+		.end	= 276,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channel 17 */
+		.start	= 279,
+		.end	= 279,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+/* channel 18 to 23 */
+static struct resource sh7757_dmae3_resources[] = {
+	[0] = {
+		/* Channel registers and DMAOR */
+		.start	= 0xff718020,
+		.end	= 0xff71808f,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		/* DMARSx */
+		.start	= 0xff719000,
+		.end	= 0xff71900b,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		/* DMA error */
+		.start	= 324,
+		.end	= 324,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channels 18 to 22 */
+		.start	= 280,
+		.end	= 284,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		/* IRQ for channel 23 */
+		.start	= 288,
+		.end	= 288,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device dma0_device = {
+	.name           = "sh-dma-engine",
+	.id             = 0,
+	.resource	= sh7757_dmae0_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae0_resources),
+	.dev            = {
+		.platform_data	= &dma0_platform_data,
+	},
+};
+
+static struct platform_device dma1_device = {
+	.name		= "sh-dma-engine",
+	.id		= 1,
+	.resource	= sh7757_dmae1_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae1_resources),
+	.dev		= {
+		.platform_data	= &dma1_platform_data,
+	},
+};
+
+static struct platform_device dma2_device = {
+	.name		= "sh-dma-engine",
+	.id		= 2,
+	.resource	= sh7757_dmae2_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae2_resources),
+	.dev		= {
+		.platform_data	= &dma2_platform_data,
+	},
+};
+
+static struct platform_device dma3_device = {
+	.name		= "sh-dma-engine",
+	.id		= 3,
+	.resource	= sh7757_dmae3_resources,
+	.num_resources	= ARRAY_SIZE(sh7757_dmae3_resources),
+	.dev		= {
+		.platform_data	= &dma3_platform_data,
+	},
+};
+
+static struct platform_device spi0_device = {
+	.name	= "sh_spi",
+	.id	= 0,
+	.dev	= {
+		.dma_mask		= NULL,
+		.coherent_dma_mask	= 0xffffffff,
+	},
+	.num_resources	= ARRAY_SIZE(spi0_resources),
+	.resource	= spi0_resources,
+};
+
 static struct platform_device *sh7757_devices[] __initdata = {
 	&scif2_device,
 	&scif3_device,
 	&scif4_device,
 	&tmu0_device,
 	&tmu1_device,
+	&dma0_device,
+	&dma1_device,
+	&dma2_device,
+	&dma3_device,
+	&spi0_device,
 };
 
 static int __init sh7757_devices_setup(void)
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/sh4a/setup-sh7786.c	2011-05-19 00:06:34.000000000 -0400
@@ -648,7 +648,7 @@
 	 * The following settings are necessary
 	 * for using the USB modules.
 	 *
-	 * see "USB Inital Settings" for detail
+	 * see "USB Initial Settings" for detail
 	 */
 	__raw_writel(USBINITVAL1, USBINITREG1);
 	__raw_writel(USBINITVAL2, USBINITREG2);
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/cpu/shmobile/cpuidle.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 	i = CPUIDLE_DRIVER_STATE_START;
 
 	state = &dev->states[i++];
-	snprintf(state->name, CPUIDLE_NAME_LEN, "C0");
+	snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
 	strncpy(state->desc, "SuperH Sleep Mode", CPUIDLE_DESC_LEN);
 	state->exit_latency = 1;
 	state->target_residency = 1 * 2;
@@ -88,7 +88,7 @@
 
 	if (sh_mobile_sleep_supported & SUSP_SH_SF) {
 		state = &dev->states[i++];
-		snprintf(state->name, CPUIDLE_NAME_LEN, "C1");
+		snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
 		strncpy(state->desc, "SuperH Sleep Mode [SF]",
 			CPUIDLE_DESC_LEN);
 		state->exit_latency = 100;
@@ -101,7 +101,7 @@
 
 	if (sh_mobile_sleep_supported & SUSP_SH_STANDBY) {
 		state = &dev->states[i++];
-		snprintf(state->name, CPUIDLE_NAME_LEN, "C2");
+		snprintf(state->name, CPUIDLE_NAME_LEN, "C3");
 		strncpy(state->desc, "SuperH Mobile Standby Mode [SF]",
 			CPUIDLE_DESC_LEN);
 		state->exit_latency = 2300;
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/crash_dump.c linux-libre-2.6.39-gnu/arch/sh/kernel/crash_dump.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/crash_dump.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/crash_dump.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,28 +9,6 @@
 #include <linux/io.h>
 #include <asm/uaccess.h>
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
-/*
- * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
- * is_kdump_kernel() to determine if we are booting after a panic. Hence
- * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
- *
- * elfcorehdr= specifies the location of elf core header
- * stored by the crashed kernel.
- */
-static int __init parse_elfcorehdr(char *arg)
-{
-	if (!arg)
-		return -EINVAL;
-
-	elfcorehdr_addr = memparse(arg, &arg);
-
-	return 0;
-}
-early_param("elfcorehdr", parse_elfcorehdr);
-
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/irq.c linux-libre-2.6.39-gnu/arch/sh/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,9 +34,9 @@
 
 #if defined(CONFIG_PROC_FS)
 /*
- * /proc/interrupts printing:
+ * /proc/interrupts printing for arch specific interrupts
  */
-static int show_other_interrupts(struct seq_file *p, int prec)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	int j;
 
@@ -49,63 +49,6 @@
 
 	return 0;
 }
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	unsigned long flags, any_count = 0;
-	int i = *(loff_t *)v, j, prec;
-	struct irqaction *action;
-	struct irq_desc *desc;
-	struct irq_data *data;
-	struct irq_chip *chip;
-
-	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_printf(p, "%*s", prec + 8, "");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	desc = irq_to_desc(i);
-	if (!desc)
-		return 0;
-
-	data = irq_get_irq_data(i);
-	chip = irq_data_get_irq_chip(data);
-
-	raw_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", 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');
-out:
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	return 0;
-}
 #endif
 
 #ifdef CONFIG_IRQSTACKS
@@ -240,7 +183,7 @@
 		);
 
 		/*
-		 * Shouldnt happen, we returned above if in_interrupt():
+		 * Shouldn't happen, we returned above if in_interrupt():
 		 */
 		WARN_ON_ONCE(softirq_count());
 	}
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/process.c linux-libre-2.6.39-gnu/arch/sh/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,16 +32,16 @@
 #if THREAD_SHIFT < PAGE_SHIFT
 static struct kmem_cache *thread_info_cache;
 
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
 {
 	struct thread_info *ti;
-
-	ti = kmem_cache_alloc(thread_info_cache, GFP_KERNEL);
-	if (unlikely(ti == NULL))
-		return NULL;
 #ifdef CONFIG_DEBUG_STACK_USAGE
-	memset(ti, 0, THREAD_SIZE);
+	gfp_t mask = GFP_KERNEL | __GFP_ZERO;
+#else
+	gfp_t mask = GFP_KERNEL;
 #endif
+
+	ti = kmem_cache_alloc_node(thread_info_cache, mask, node);
 	return ti;
 }
 
@@ -57,14 +57,16 @@
 					      THREAD_SIZE, SLAB_PANIC, NULL);
 }
 #else
-struct thread_info *alloc_thread_info(struct task_struct *tsk)
+struct thread_info *alloc_thread_info_node(struct task_struct *tsk, int node)
 {
 #ifdef CONFIG_DEBUG_STACK_USAGE
 	gfp_t mask = GFP_KERNEL | __GFP_ZERO;
 #else
 	gfp_t mask = GFP_KERNEL;
 #endif
-	return (struct thread_info *)__get_free_pages(mask, THREAD_SIZE_ORDER);
+	struct page *page = alloc_pages_node(node, mask, THREAD_SIZE_ORDER);
+
+	return page ? page_address(page) : NULL;
 }
 
 void free_thread_info(struct thread_info *ti)
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_32.c linux-libre-2.6.39-gnu/arch/sh/kernel/ptrace_32.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/ptrace_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -101,6 +101,8 @@
 
 		attr = bp->attr;
 		attr.bp_addr = addr;
+		/* reenable breakpoint */
+		attr.disabled = false;
 		err = modify_user_hw_breakpoint(bp, &attr);
 		if (unlikely(err))
 			return err;
@@ -115,7 +117,11 @@
 
 	set_tsk_thread_flag(child, TIF_SINGLESTEP);
 
+	if (ptrace_get_breakpoints(child) < 0)
+		return;
+
 	set_single_step(child, pc);
+	ptrace_put_breakpoints(child);
 }
 
 void user_disable_single_step(struct task_struct *child)
@@ -392,6 +398,9 @@
 					tmp = 0;
 			} else {
 				unsigned long index;
+				ret = init_fpu(child);
+				if (ret)
+					break;
 				index = addr - offsetof(struct user, fpu);
 				tmp = ((unsigned long *)child->thread.xstate)
 					[index >> 2];
@@ -423,6 +432,9 @@
 		else if (addr >= offsetof(struct user, fpu) &&
 			 addr < offsetof(struct user, u_fpvalid)) {
 			unsigned long index;
+			ret = init_fpu(child);
+			if (ret)
+				break;
 			index = addr - offsetof(struct user, fpu);
 			set_stopped_child_used_math(child);
 			((unsigned long *)child->thread.xstate)
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_64.c linux-libre-2.6.39-gnu/arch/sh/kernel/ptrace_64.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/ptrace_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/ptrace_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -403,6 +403,9 @@
 		else if ((addr >= offsetof(struct user, fpu)) &&
 			 (addr <  offsetof(struct user, u_fpvalid))) {
 			unsigned long index;
+			ret = init_fpu(child);
+			if (ret)
+				break;
 			index = addr - offsetof(struct user, fpu);
 			tmp = get_fpu_long(child, index);
 		} else if (addr == offsetof(struct user, u_fpvalid)) {
@@ -442,6 +445,9 @@
 		else if ((addr >= offsetof(struct user, fpu)) &&
 			 (addr <  offsetof(struct user, u_fpvalid))) {
 			unsigned long index;
+			ret = init_fpu(child);
+			if (ret)
+				break;
 			index = addr - offsetof(struct user, fpu);
 			ret = put_fpu_long(child, index, data);
 		}
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/setup.c linux-libre-2.6.39-gnu/arch/sh/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -150,7 +150,7 @@
 	}
 
 	/*
-	 * If we got this far inspite of the boot loader's best efforts
+	 * If we got this far in spite of the boot loader's best efforts
 	 * to the contrary, assume we actually have a valid initrd and
 	 * fix up the root dev.
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/syscalls_32.S linux-libre-2.6.39-gnu/arch/sh/kernel/syscalls_32.S
--- linux-libre-2.6.38-gnu/arch/sh/kernel/syscalls_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/syscalls_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -376,3 +376,7 @@
 	.long sys_recvmsg
 	.long sys_recvmmsg
 	.long sys_accept4
+	.long sys_name_to_handle_at
+	.long sys_open_by_handle_at	/* 360 */
+	.long sys_clock_adjtime
+	.long sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/syscalls_64.S linux-libre-2.6.39-gnu/arch/sh/kernel/syscalls_64.S
--- linux-libre-2.6.38-gnu/arch/sh/kernel/syscalls_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/syscalls_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -396,3 +396,7 @@
 	.long sys_fanotify_init
 	.long sys_fanotify_mark
 	.long sys_prlimit64
+	.long sys_name_to_handle_at	/* 370 */
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
+	.long sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/sh/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/sh/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
 		__machvec_end = .;
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
 
 	/*
 	 * .exit.text is discarded at runtime, not link time, to deal with
diff -druN linux-libre-2.6.38-gnu/arch/sh/kernel/vsyscall/vsyscall.c linux-libre-2.6.39-gnu/arch/sh/kernel/vsyscall/vsyscall.c
--- linux-libre-2.6.38-gnu/arch/sh/kernel/vsyscall/vsyscall.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/kernel/vsyscall/vsyscall.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,17 +94,17 @@
 	return NULL;
 }
 
-struct vm_area_struct *get_gate_vma(struct task_struct *task)
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 {
 	return NULL;
 }
 
-int in_gate_area(struct task_struct *task, unsigned long address)
+int in_gate_area(struct mm_struct *mm, unsigned long address)
 {
 	return 0;
 }
 
-int in_gate_area_no_task(unsigned long address)
+int in_gate_area_no_mm(unsigned long address)
 {
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/sh/lib64/copy_user_memcpy.S linux-libre-2.6.39-gnu/arch/sh/lib64/copy_user_memcpy.S
--- linux-libre-2.6.38-gnu/arch/sh/lib64/copy_user_memcpy.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/lib64/copy_user_memcpy.S	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 ! 2.: When there are two or three bytes in the last word of an 11-or-more
 !     bytes memory chunk to b copied, the rest of the word can be read
 !     without side effects.
-!     This could be easily changed by increasing the minumum size of
+!     This could be easily changed by increasing the minimum size of
 !     a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2,
 !     however, this would cost a few extra cyles on average.
 !     For SHmedia, the assumption is that any quadword can be read in its
diff -druN linux-libre-2.6.38-gnu/arch/sh/lib64/memcpy.S linux-libre-2.6.39-gnu/arch/sh/lib64/memcpy.S
--- linux-libre-2.6.38-gnu/arch/sh/lib64/memcpy.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/lib64/memcpy.S	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 ! 2.: When there are two or three bytes in the last word of an 11-or-more
 !     bytes memory chunk to b copied, the rest of the word can be read
 !     without side effects.
-!     This could be easily changed by increasing the minumum size of
+!     This could be easily changed by increasing the minimum size of
 !     a fast memcpy and the amount subtracted from r7 before L_2l_loop be 2,
 !     however, this would cost a few extra cyles on average.
 !     For SHmedia, the assumption is that any quadword can be read in its
diff -druN linux-libre-2.6.38-gnu/arch/sh/mm/Makefile linux-libre-2.6.39-gnu/arch/sh/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/sh/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,8 @@
 obj-$(CONFIG_UNCACHED_MAPPING)	+= uncached.o
 obj-$(CONFIG_HAVE_SRAM_POOL)	+= sram.o
 
+GCOV_PROFILE_pmb.o := n
+
 # Special flags for fault_64.o.  This puts restrictions on the number of
 # caller-save registers that the compiler can target when building this file.
 # This is required because the code is called from a context in entry.S where
diff -druN linux-libre-2.6.38-gnu/arch/sh/mm/pmb.c linux-libre-2.6.39-gnu/arch/sh/mm/pmb.c
--- linux-libre-2.6.38-gnu/arch/sh/mm/pmb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sh/mm/pmb.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Privileged Space Mapping Buffer (PMB) Support.
  *
- * Copyright (C) 2005 - 2010  Paul Mundt
+ * Copyright (C) 2005 - 2011  Paul Mundt
  * Copyright (C) 2010  Matt Fleming
  *
  * This file is subject to the terms and conditions of the GNU General Public
@@ -12,7 +12,7 @@
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/cpu.h>
 #include <linux/module.h>
 #include <linux/bitops.h>
@@ -874,46 +874,31 @@
 subsys_initcall(pmb_debugfs_init);
 
 #ifdef CONFIG_PM
-static int pmb_sysdev_suspend(struct sys_device *dev, pm_message_t state)
+static void pmb_syscore_resume(void)
 {
-	static pm_message_t prev_state;
+	struct pmb_entry *pmbe;
 	int i;
 
-	/* Restore the PMB after a resume from hibernation */
-	if (state.event == PM_EVENT_ON &&
-	    prev_state.event == PM_EVENT_FREEZE) {
-		struct pmb_entry *pmbe;
-
-		read_lock(&pmb_rwlock);
+	read_lock(&pmb_rwlock);
 
-		for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
-			if (test_bit(i, pmb_map)) {
-				pmbe = &pmb_entry_list[i];
-				set_pmb_entry(pmbe);
-			}
+	for (i = 0; i < ARRAY_SIZE(pmb_entry_list); i++) {
+		if (test_bit(i, pmb_map)) {
+			pmbe = &pmb_entry_list[i];
+			set_pmb_entry(pmbe);
 		}
-
-		read_unlock(&pmb_rwlock);
 	}
 
-	prev_state = state;
-
-	return 0;
-}
-
-static int pmb_sysdev_resume(struct sys_device *dev)
-{
-	return pmb_sysdev_suspend(dev, PMSG_ON);
+	read_unlock(&pmb_rwlock);
 }
 
-static struct sysdev_driver pmb_sysdev_driver = {
-	.suspend = pmb_sysdev_suspend,
-	.resume = pmb_sysdev_resume,
+static struct syscore_ops pmb_syscore_ops = {
+	.resume = pmb_syscore_resume,
 };
 
 static int __init pmb_sysdev_init(void)
 {
-	return sysdev_driver_register(&cpu_sysdev_class, &pmb_sysdev_driver);
+	register_syscore_ops(&pmb_syscore_ops);
+	return 0;
 }
 subsys_initcall(pmb_sysdev_init);
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/boot/Makefile linux-libre-2.6.39-gnu/arch/sparc/boot/Makefile
--- linux-libre-2.6.38-gnu/arch/sparc/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/boot/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,7 @@
 
 ROOT_IMG	:= /usr/src/root.img
 ELFTOAOUT	:= elftoaout
+MKIMAGE 	:= $(srctree)/scripts/mkuboot.sh
 
 hostprogs-y	:= piggyback btfixupprep
 targets		:= tftpboot.img btfix.o btfix.S image zImage vmlinux.aout
@@ -77,6 +78,36 @@
 $(obj)/vmlinux.aout: vmlinux FORCE
 	$(call if_changed,elftoaout)
 	@echo '  kernel: $@ is ready'
+else
+
+# The following lines make a readable image for U-Boot.
+#  uImage   - Binary file read by U-boot
+#  uImage.o - object file of uImage for loading with a
+#             flash programmer understanding ELF.
+
+OBJCOPYFLAGS_image.bin := -S -O binary -R .note -R .comment
+$(obj)/image.bin: $(obj)/image FORCE
+	$(call if_changed,objcopy)
+
+$(obj)/image.gz: $(obj)/image.bin
+	$(call if_changed,gzip)
+
+quiet_cmd_uimage = UIMAGE  $@
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A sparc -O linux -T kernel \
+               -C gzip -a $(CONFIG_UBOOT_LOAD_ADDR) \
+	       -e $(CONFIG_UBOOT_ENTRY_ADDR) -n 'Linux-$(KERNELRELEASE)' \
+               -d $< $@
+
+quiet_cmd_uimage.o = UIMAGE.O $@
+      cmd_uimage.o = $(LD) -Tdata $(CONFIG_UBOOT_FLASH_ADDR) \
+                     -r -b binary $@ -o $@.o
+
+targets += uImage
+$(obj)/uImage: $(obj)/image.gz
+	$(call if_changed,uimage)
+	$(call if_changed,uimage.o)
+	@echo '  Image $@ is ready'
+
 endif
 
 $(obj)/tftpboot.img: $(obj)/image $(obj)/piggyback System.map $(ROOT_IMG) FORCE
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/bitops_32.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/bitops_32.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/bitops_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/bitops_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -103,9 +103,8 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 #include <asm-generic/bitops/ext2-atomic.h>
-#include <asm-generic/bitops/minix.h>
 
 #endif /* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/bitops_64.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/bitops_64.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/bitops_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/bitops_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -89,15 +89,13 @@
 
 #ifdef __KERNEL__
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #define ext2_set_bit_atomic(lock,nr,addr) \
 	test_and_set_bit((nr) ^ 0x38,(unsigned long *)(addr))
 #define ext2_clear_bit_atomic(lock,nr,addr) \
 	test_and_clear_bit((nr) ^ 0x38,(unsigned long *)(addr))
 
-#include <asm-generic/bitops/minix.h>
-
 #endif /* __KERNEL__ */
 
 #endif /* defined(_SPARC64_BITOPS_H) */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/errno.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/errno.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/errno.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/errno.h	2011-05-19 00:06:34.000000000 -0400
@@ -112,4 +112,6 @@
 
 #define	ERFKILL		134	/* Operation not possible due to RF-kill */
 
+#define EHWPOISON	135	/* Memory page has hardware error */
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/fcntl.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/fcntl.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/fcntl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/fcntl.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,8 @@
 #define __O_SYNC	0x800000
 #define O_SYNC		(__O_SYNC|O_DSYNC)
 
+#define O_PATH		0x1000000
+
 #define F_GETOWN	5	/*  for sockets. */
 #define F_SETOWN	6	/*  for sockets. */
 #define F_GETLK		7
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/futex_64.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/futex_64.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/futex_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/futex_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 	: "r" (uaddr), "r" (oparg), "i" (-EFAULT)	\
 	: "memory")
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -38,7 +38,7 @@
 	int cmparg = (encoded_op << 20) >> 20;
 	int oldval = 0, ret, tem;
 
-	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(int))))
+	if (unlikely(!access_ok(VERIFY_WRITE, uaddr, sizeof(u32))))
 		return -EFAULT;
 	if (unlikely((((unsigned long) uaddr) & 0x3UL)))
 		return -EINVAL;
@@ -85,26 +85,30 @@
 }
 
 static inline int
-futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval, int newval)
+futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+			      u32 oldval, u32 newval)
 {
+	int ret = 0;
+
 	__asm__ __volatile__(
-	"\n1:	casa	[%3] %%asi, %2, %0\n"
+	"\n1:	casa	[%4] %%asi, %3, %1\n"
 	"2:\n"
 	"	.section .fixup,#alloc,#execinstr\n"
 	"	.align	4\n"
 	"3:	sethi	%%hi(2b), %0\n"
 	"	jmpl	%0 + %%lo(2b), %%g0\n"
-	"	 mov	%4, %0\n"
+	"	mov	%5, %0\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
 	"	.align	4\n"
 	"	.word	1b, 3b\n"
 	"	.previous\n"
-	: "=r" (newval)
-	: "0" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
+	: "+r" (ret), "=r" (newval)
+	: "1" (newval), "r" (oldval), "r" (uaddr), "i" (-EFAULT)
 	: "memory");
 
-	return newval;
+	*uval = newval;
+	return ret;
 }
 
 #endif /* !(_SPARC64_FUTEX_H) */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/hypervisor.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/hypervisor.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/hypervisor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/hypervisor.h	2011-05-19 00:06:34.000000000 -0400
@@ -654,7 +654,7 @@
  * ARG3:	mmu context
  * ARG4:	flags (HV_MMU_{IMMU,DMMU})
  * RET0:	status
- * ERRORS:	EINVAL			Invalid virutal address, context, or
+ * ERRORS:	EINVAL			Invalid virtual address, context, or
  *					flags value
  *		ENOTSUPPORTED		ARG0 or ARG1 is non-zero
  *
@@ -721,7 +721,7 @@
  * ARG2:	TTE
  * ARG3:	flags (HV_MMU_{IMMU,DMMU})
  * RET0:	status
- * ERRORS:	EINVAL			Invalid virutal address or flags value
+ * ERRORS:	EINVAL			Invalid virtual address or flags value
  *		EBADPGSZ		Invalid page size value
  *		ENORADDR		Invalid real address in TTE
  *		ETOOMANY		Too many mappings (max of 8 reached)
@@ -800,7 +800,7 @@
  * ARG1:	reserved, must be zero
  * ARG2:	flags (HV_MMU_{IMMU,DMMU})
  * RET0:	status
- * ERRORS:	EINVAL			Invalid virutal address or flags value
+ * ERRORS:	EINVAL			Invalid virtual address or flags value
  *		ENOMAP			Specified mapping was not found
  *
  * Demaps any permanent page mapping (established via
@@ -1205,7 +1205,7 @@
  * structure contents.  Attempts to do so will result in undefined
  * behavior for the guest.
  *
- * Each trap trace buffer entry is layed out as follows:
+ * Each trap trace buffer entry is laid out as follows:
  */
 #ifndef __ASSEMBLY__
 struct hv_trap_trace_entry {
@@ -1300,7 +1300,7 @@
  * state in RET1.  Future systems may define various flags for the
  * enable argument (ARG0), for the moment a guest should pass
  * "(uint64_t) -1" to enable, and "(uint64_t) 0" to disable all
- * tracing - which will ensure future compatability.
+ * tracing - which will ensure future compatibility.
  */
 #define HV_FAST_TTRACE_ENABLE		0x92
 
@@ -1880,7 +1880,7 @@
  * pci_device, at pci_config_offset from the beginning of the device's
  * configuration space.  If there was no error, RET1 is set to zero and
  * RET2 is set to the data read.  Insignificant bits in RET2 are not
- * guarenteed to have any specific value and therefore must be ignored.
+ * guaranteed to have any specific value and therefore must be ignored.
  *
  * The data returned in RET2 is size based byte swapped.
  *
@@ -1941,9 +1941,9 @@
  * and return the actual data read in RET2.  The data returned is size based
  * byte swapped.
  *
- * Non-significant bits in RET2 are not guarenteed to have any specific value
+ * Non-significant bits in RET2 are not guaranteed to have any specific value
  * and therefore must be ignored.  If RET1 is returned as non-zero, the data
- * value is not guarenteed to have any specific value and should be ignored.
+ * value is not guaranteed to have any specific value and should be ignored.
  *
  * The caller must have permission to read from the given devhandle, real
  * address, which must be an IO address.  The argument real address must be a
@@ -2456,9 +2456,9 @@
  *
  * As receive queue configuration causes a reset of the queue's head and
  * tail pointers there is no way for a gues to determine how many entries
- * have been received between a preceeding ldc_get_rx_state() API call
+ * have been received between a preceding ldc_get_rx_state() API call
  * and the completion of the configuration operation.  It should be noted
- * that datagram delivery is not guarenteed via domain channels anyway,
+ * that datagram delivery is not guaranteed via domain channels anyway,
  * and therefore any higher protocol should be resilient to datagram
  * loss if necessary.  However, to overcome this specific race potential
  * it is recommended, for example, that a higher level protocol be employed
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #define TCSETSW2	_IOW('T', 14, struct termios2)
 #define TCSETSF2	_IOW('T', 15, struct termios2)
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
+#define TIOCVHANGUP	_IO('T', 0x37)
 
 /* Note that all the ioctls that are not available in Linux have a 
  * double underscore on the front to: a) avoid some programs to
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/irq_32.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/irq_32.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/irq_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/irq_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,4 +13,7 @@
 #define irq_canonicalize(irq)	(irq)
 
 extern void __init init_IRQ(void);
+
+#define NO_IRQ		0xffffffff
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/irq_64.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/irq_64.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/irq_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/irq_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,34 +33,34 @@
 
 /* The largest number of unique interrupt sources we support.
  * If this needs to ever be larger than 255, you need to change
- * the type of ino_bucket->virt_irq as appropriate.
+ * the type of ino_bucket->irq as appropriate.
  *
- * ino_bucket->virt_irq allocation is made during {sun4v_,}build_irq().
+ * ino_bucket->irq allocation is made during {sun4v_,}build_irq().
  */
 #define NR_IRQS    255
 
-extern void irq_install_pre_handler(int virt_irq,
+extern void irq_install_pre_handler(int irq,
 				    void (*func)(unsigned int, void *, void *),
 				    void *arg1, void *arg2);
 #define irq_canonicalize(irq)	(irq)
 extern unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap);
 extern unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino);
 extern unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino);
-extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *virt_irq_p,
+extern unsigned int sun4v_build_msi(u32 devhandle, unsigned int *irq_p,
 				    unsigned int msi_devino_start,
 				    unsigned int msi_devino_end);
-extern void sun4v_destroy_msi(unsigned int virt_irq);
-extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p,
+extern void sun4v_destroy_msi(unsigned int irq);
+extern unsigned int sun4u_build_msi(u32 portid, unsigned int *irq_p,
 				    unsigned int msi_devino_start,
 				    unsigned int msi_devino_end,
 				    unsigned long imap_base,
 				    unsigned long iclr_base);
-extern void sun4u_destroy_msi(unsigned int virt_irq);
+extern void sun4u_destroy_msi(unsigned int irq);
 
-extern unsigned char virt_irq_alloc(unsigned int dev_handle,
+extern unsigned char irq_alloc(unsigned int dev_handle,
 				    unsigned int dev_ino);
 #ifdef CONFIG_PCI_MSI
-extern void virt_irq_free(unsigned int virt_irq);
+extern void irq_free(unsigned int irq);
 #endif
 
 extern void __init init_IRQ(void);
@@ -97,4 +97,6 @@
 #define __ARCH_HAS_DO_SOFTIRQ
 #define ARCH_HAS_NMI_WATCHDOG
 
+#define NO_IRQ		0xffffffff
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/leon_amba.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/leon_amba.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/leon_amba.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/leon_amba.h	2011-05-19 00:06:34.000000000 -0400
@@ -180,6 +180,7 @@
 struct device_node;
 void _amba_init(struct device_node *dp, struct device_node ***nextp);
 
+extern unsigned long amba_system_id;
 extern struct leon3_irqctrl_regs_map *leon3_irqctrl_regs;
 extern struct leon3_gptimer_regs_map *leon3_gptimer_regs;
 extern struct amba_apb_device leon_percpu_timer_dev[16];
@@ -254,6 +255,11 @@
 #define GAISLER_L2C      0xffe	/* internal device: leon2compat */
 #define GAISLER_PLUGPLAY 0xfff	/* internal device: plug & play configarea */
 
+/* Chip IDs */
+#define AEROFLEX_UT699    0x0699
+#define LEON4_NEXTREME1   0x0102
+#define GAISLER_GR712RC   0x0712
+
 #define amba_vendor(x) (((x) >> 24) & 0xff)
 
 #define amba_device(x) (((x) >> 12) & 0xfff)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/leon.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/leon.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/leon.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/leon.h	2011-05-19 00:06:34.000000000 -0400
@@ -375,9 +375,6 @@
 
 extern unsigned int real_irq_entry[], smpleon_ticker[];
 extern unsigned int patchme_maybe_smp_msg[];
-extern unsigned long trapbase_cpu1[];
-extern unsigned long trapbase_cpu2[];
-extern unsigned long trapbase_cpu3[];
 extern unsigned int t_nmi[], linux_trap_ipi15_leon[];
 extern unsigned int linux_trap_ipi15_sun4m[];
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/mmu_32.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/mmu_32.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/mmu_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/mmu_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,4 +4,7 @@
 /* Default "unsigned long" context */
 typedef unsigned long mm_context_t;
 
+/* mm/srmmu.c */
+extern ctxd_t *srmmu_ctx_table_phys;
+
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/ns87303.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/ns87303.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/ns87303.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/ns87303.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
 /* Power and Test Register (PTR) bits */
 #define PTR_LPTB_IRQ7	0x08
 #define PTR_LEVEL_IRQ	0x80	/* When not ECP/EPP: Use level IRQ           */
-#define PTR_LPT_REG_DIR	0x80	/* When ECP/EPP: LPT CTR controlls direction */
+#define PTR_LPT_REG_DIR	0x80	/* When ECP/EPP: LPT CTR controls direction */
 				/*               of the parallel port	     */
 
 /* Function Control Register (FCR) bits */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/parport.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/parport.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/parport.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/parport.h	2011-05-19 00:06:34.000000000 -0400
@@ -103,7 +103,7 @@
 	return ebus_dma_residue(&sparc_ebus_dmas[dmanr].info);
 }
 
-static int __devinit ecpp_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ecpp_probe(struct platform_device *op)
 {
 	unsigned long base = op->resource[0].start;
 	unsigned long config = op->resource[1].start;
@@ -235,7 +235,7 @@
 	{},
 };
 
-static struct of_platform_driver ecpp_driver = {
+static struct platform_driver ecpp_driver = {
 	.driver = {
 		.name = "ecpp",
 		.owner = THIS_MODULE,
@@ -247,7 +247,7 @@
 
 static int parport_pc_find_nonpci_ports(int autoirq, int autodma)
 {
-	return of_register_platform_driver(&ecpp_driver);
+	return platform_driver_register(&ecpp_driver);
 }
 
 #endif /* !(_ASM_SPARC64_PARPORT_H */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/pcr.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/pcr.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/pcr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/pcr.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 
 /* In order to commonize as much of the implementation as
  * possible, we use PICH as our counter.  Mostly this is
- * to accomodate Niagara-1 which can only count insn cycles
+ * to accommodate Niagara-1 which can only count insn cycles
  * in PICH.
  */
 static inline u64 picl_value(unsigned int nmi_hz)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 	 * things like "in a system call" etc. for an arbitray
 	 * process.
 	 *
-	 * The PT_REGS_MAGIC is choosen such that it can be
+	 * The PT_REGS_MAGIC is chosen such that it can be
 	 * loaded completely using just a sethi instruction.
 	 */
 	unsigned int magic;
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,53 +13,12 @@
 
 #ifdef __KERNEL__
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-
-struct rwsem_waiter;
-
-struct rw_semaphore {
-	signed long			count;
 #define RWSEM_UNLOCKED_VALUE		0x00000000L
 #define RWSEM_ACTIVE_BIAS		0x00000001L
 #define RWSEM_ACTIVE_MASK		0xffffffffL
 #define RWSEM_WAITING_BIAS		(-RWSEM_ACTIVE_MASK-1)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t			wait_lock;
-	struct list_head		wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map		dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-#define __RWSEM_INITIALIZER(name) \
-{ RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-  LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) }
-
-#define DECLARE_RWSEM(name) \
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)						\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__init_rwsem((sem), #sem, &__key);			\
-} while (0)
 
 /*
  * lock for reading
@@ -160,11 +119,6 @@
 	return atomic64_add_return(delta, (atomic64_t *)(&sem->count));
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 
 #endif /* _SPARC64_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/smp_32.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/smp_32.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/smp_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/smp_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,10 +29,16 @@
  */
 
 extern unsigned char boot_cpu_id;
+extern volatile unsigned long cpu_callin_map[NR_CPUS];
+extern cpumask_t smp_commenced_mask;
+extern struct linux_prom_registers smp_penguin_ctable;
 
 typedef void (*smpfunc_t)(unsigned long, unsigned long, unsigned long,
 		       unsigned long, unsigned long);
 
+void cpu_panic(void);
+extern void smp4m_irq_rotate(int cpu);
+
 /*
  *	General functions that each host system must provide.
  */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/thread_info_32.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/thread_info_32.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/thread_info_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/thread_info_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -82,8 +82,8 @@
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info, void)
-#define alloc_thread_info(tsk) BTFIXUP_CALL(alloc_thread_info)()
+BTFIXUPDEF_CALL(struct thread_info *, alloc_thread_info_node, int)
+#define alloc_thread_info_node(tsk, node) BTFIXUP_CALL(alloc_thread_info_node)(node)
 
 BTFIXUPDEF_CALL(void, free_thread_info, struct thread_info *)
 #define free_thread_info(ti) BTFIXUP_CALL(free_thread_info)(ti)
@@ -92,7 +92,7 @@
 
 /*
  * Size of kernel stack for each process.
- * Observe the order of get_free_pages() in alloc_thread_info().
+ * Observe the order of get_free_pages() in alloc_thread_info_node().
  * The sun4 has 8K stack too, because it's short on memory, and 16K is a waste.
  */
 #define THREAD_SIZE		8192
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/thread_info_64.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/thread_info_64.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/thread_info_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/thread_info_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -146,21 +146,21 @@
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
 #ifdef CONFIG_DEBUG_STACK_USAGE
-#define alloc_thread_info(tsk)					\
-({								\
-	struct thread_info *ret;				\
-								\
-	ret = (struct thread_info *)				\
-	  __get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER);	\
-	if (ret)						\
-		memset(ret, 0, PAGE_SIZE<<__THREAD_INFO_ORDER);	\
-	ret;							\
-})
+#define THREAD_FLAGS (GFP_KERNEL | __GFP_ZERO)
 #else
-#define alloc_thread_info(tsk) \
-	((struct thread_info *)__get_free_pages(GFP_KERNEL, __THREAD_INFO_ORDER))
+#define THREAD_FLAGS (GFP_KERNEL)
 #endif
 
+#define alloc_thread_info_node(tsk, node)				\
+({									\
+	struct page *page = alloc_pages_node(node, THREAD_FLAGS,	\
+					     __THREAD_INFO_ORDER);	\
+	struct thread_info *ret;					\
+									\
+	ret = page ? page_address(page) : NULL;				\
+	ret;								\
+})
+
 #define free_thread_info(ti) \
 	free_pages((unsigned long)(ti),__THREAD_INFO_ORDER)
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/types.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,28 +18,6 @@
 
 #endif /* __ASSEMBLY__ */
 
-#ifdef __KERNEL__
-
-#ifndef __ASSEMBLY__
-
-/* Dma addresses come in generic and 64-bit flavours.  */
-
-typedef u32 dma_addr_t;
-
-#if defined(__arch64__)
-
-/*** SPARC 64 bit ***/
-typedef u64 dma64_addr_t;
-#else
-/*** SPARC 32 bit ***/
-typedef u32 dma64_addr_t;
-
-#endif /* defined(__arch64__) */
-
-#endif /* __ASSEMBLY__ */
-
-#endif /* __KERNEL__ */
-
 #endif /* defined(__sparc__) */
 
 #endif /* defined(_SPARC_TYPES_H) */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/sparc/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/sparc/include/asm/unistd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -400,8 +400,12 @@
 #define __NR_fanotify_init	329
 #define __NR_fanotify_mark	330
 #define __NR_prlimit64		331
+#define __NR_name_to_handle_at	332
+#define __NR_open_by_handle_at	333
+#define __NR_clock_adjtime	334
+#define __NR_syncfs		335
 
-#define NR_syscalls		332
+#define NR_syscalls		336
 
 #ifdef __32bit_syscall_numbers__
 /* Sparc 32-bit only has the "setresuid32", "getresuid32" variants,
diff -druN linux-libre-2.6.38-gnu/arch/sparc/Kconfig linux-libre-2.6.39-gnu/arch/sparc/Kconfig
--- linux-libre-2.6.38-gnu/arch/sparc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,8 @@
 	select HAVE_PERF_EVENTS
 	select PERF_USE_VMALLOC
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
+	select IRQ_PREFLOW_FASTEOI
 
 config ARCH_DEFCONFIG
 	string
@@ -191,6 +193,10 @@
 	bool
 	default y
 
+config GENERIC_FIND_BIT_LE
+	bool
+	default y
+
 config GENERIC_HWEIGHT
 	bool
 	default y if !ULTRA_HAS_POPULATION_COUNT
@@ -460,6 +466,39 @@
 	  from www.gaisler.com. You can download a sparc-linux cross-compilation
 	  toolchain at www.gaisler.com.
 
+if SPARC_LEON
+menu "U-Boot options"
+
+config UBOOT_LOAD_ADDR
+	hex "uImage Load Address"
+	default 0x40004000
+	---help---
+	 U-Boot kernel load address, the address in physical address space
+	 where u-boot will place the Linux kernel before booting it.
+	 This address is normally the base address of main memory + 0x4000.
+
+config UBOOT_FLASH_ADDR
+	hex "uImage.o Load Address"
+	default 0x00080000
+	---help---
+	 Optional setting only affecting the uImage.o ELF-image used to
+	 download the uImage file to the target using a ELF-loader other than
+	 U-Boot. It may for example be used to download an uImage to FLASH with
+	 the GRMON utility before even starting u-boot.
+
+config UBOOT_ENTRY_ADDR
+	hex "uImage Entry Address"
+	default 0xf0004000
+	---help---
+	 Do not change this unless you know what you're doing. This is
+	 hardcoded by the SPARC32 and LEON port.
+
+	 This is the virtual address u-boot jumps to when booting the Linux
+	 Kernel.
+
+endmenu
+endif
+
 endmenu
 
 menu "Bus options (PCI etc.)"
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/apc.c linux-libre-2.6.39-gnu/arch/sparc/kernel/apc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/apc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/apc.c	2011-05-19 00:06:34.000000000 -0400
@@ -137,8 +137,7 @@
 
 static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops };
 
-static int __devinit apc_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit apc_probe(struct platform_device *op)
 {
 	int err;
 
@@ -166,7 +165,7 @@
 	return 0;
 }
 
-static struct of_device_id __initdata apc_match[] = {
+static struct of_device_id apc_match[] = {
 	{
 		.name = APC_OBPNAME,
 	},
@@ -174,7 +173,7 @@
 };
 MODULE_DEVICE_TABLE(of, apc_match);
 
-static struct of_platform_driver apc_driver = {
+static struct platform_driver apc_driver = {
 	.driver = {
 		.name = "apc",
 		.owner = THIS_MODULE,
@@ -185,7 +184,7 @@
 
 static int __init apc_init(void)
 {
-	return of_register_platform_driver(&apc_driver);
+	return platform_driver_register(&apc_driver);
 }
 
 /* This driver is not critical to the boot process
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/auxio_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/auxio_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/auxio_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/auxio_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 }
 EXPORT_SYMBOL(auxio_set_lte);
 
-static struct of_device_id __initdata auxio_match[] = {
+static const struct of_device_id auxio_match[] = {
 	{
 		.name = "auxio",
 	},
@@ -102,8 +102,7 @@
 
 MODULE_DEVICE_TABLE(of, auxio_match);
 
-static int __devinit auxio_probe(struct platform_device *dev,
-				 const struct of_device_id *match)
+static int __devinit auxio_probe(struct platform_device *dev)
 {
 	struct device_node *dp = dev->dev.of_node;
 	unsigned long size;
@@ -132,7 +131,7 @@
 	return 0;
 }
 
-static struct of_platform_driver auxio_driver = {
+static struct platform_driver auxio_driver = {
 	.probe		= auxio_probe,
 	.driver = {
 		.name = "auxio",
@@ -143,7 +142,7 @@
 
 static int __init auxio_init(void)
 {
-	return of_register_platform_driver(&auxio_driver);
+	return platform_driver_register(&auxio_driver);
 }
 
 /* Must be after subsys_initcall() so that busses are probed.  Must
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/central.c linux-libre-2.6.39-gnu/arch/sparc/kernel/central.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/central.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/central.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,8 +59,7 @@
 	}
 }
 
-static int __devinit clock_board_probe(struct platform_device *op,
-				       const struct of_device_id *match)
+static int __devinit clock_board_probe(struct platform_device *op)
 {
 	struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -141,14 +140,14 @@
 	goto out;
 }
 
-static struct of_device_id __initdata clock_board_match[] = {
+static const struct of_device_id clock_board_match[] = {
 	{
 		.name = "clock-board",
 	},
 	{},
 };
 
-static struct of_platform_driver clock_board_driver = {
+static struct platform_driver clock_board_driver = {
 	.probe		= clock_board_probe,
 	.driver = {
 		.name = "clock_board",
@@ -157,8 +156,7 @@
 	},
 };
 
-static int __devinit fhc_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit fhc_probe(struct platform_device *op)
 {
 	struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -247,14 +245,14 @@
 	goto out;
 }
 
-static struct of_device_id __initdata fhc_match[] = {
+static const struct of_device_id fhc_match[] = {
 	{
 		.name = "fhc",
 	},
 	{},
 };
 
-static struct of_platform_driver fhc_driver = {
+static struct platform_driver fhc_driver = {
 	.probe		= fhc_probe,
 	.driver = {
 		.name = "fhc",
@@ -265,8 +263,8 @@
 
 static int __init sunfire_init(void)
 {
-	(void) of_register_platform_driver(&fhc_driver);
-	(void) of_register_platform_driver(&clock_board_driver);
+	(void) platform_driver_register(&fhc_driver);
+	(void) platform_driver_register(&clock_board_driver);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/chmc.c linux-libre-2.6.39-gnu/arch/sparc/kernel/chmc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/chmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/chmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -392,8 +392,7 @@
 	}
 }
 
-static int __devinit jbusmc_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit jbusmc_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *mem_regs;
 	struct device_node *mem_node;
@@ -690,8 +689,7 @@
 				      chmc_read_mcreg(p, CHMCTRL_DECODE4));
 }
 
-static int __devinit chmc_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit chmc_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	unsigned long ver;
@@ -765,13 +763,12 @@
 	goto out;
 }
 
-static int __devinit us3mc_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit us3mc_probe(struct platform_device *op)
 {
 	if (mc_type == MC_TYPE_SAFARI)
-		return chmc_probe(op, match);
+		return chmc_probe(op);
 	else if (mc_type == MC_TYPE_JBUS)
-		return jbusmc_probe(op, match);
+		return jbusmc_probe(op);
 	return -ENODEV;
 }
 
@@ -810,7 +807,7 @@
 };
 MODULE_DEVICE_TABLE(of, us3mc_match);
 
-static struct of_platform_driver us3mc_driver = {
+static struct platform_driver us3mc_driver = {
 	.driver = {
 		.name = "us3mc",
 		.owner = THIS_MODULE,
@@ -848,7 +845,7 @@
 	ret = register_dimm_printer(us3mc_dimm_printer);
 
 	if (!ret) {
-		ret = of_register_platform_driver(&us3mc_driver);
+		ret = platform_driver_register(&us3mc_driver);
 		if (ret)
 			unregister_dimm_printer(us3mc_dimm_printer);
 	}
@@ -859,7 +856,7 @@
 {
 	if (us3mc_platform()) {
 		unregister_dimm_printer(us3mc_dimm_printer);
-		of_unregister_platform_driver(&us3mc_driver);
+		platform_driver_unregister(&us3mc_driver);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/cpu.c linux-libre-2.6.39-gnu/arch/sparc/kernel/cpu.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/cpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/cpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -324,7 +324,7 @@
 	psr = get_psr();
 	put_psr(psr | PSR_EF);
 #ifdef CONFIG_SPARC_LEON
-	fpu_vers = 7;
+	fpu_vers = get_psr() & PSR_EF ? ((get_fsr() >> 17) & 0x7) : 7;
 #else
 	fpu_vers = ((get_fsr() >> 17) & 0x7);
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/ds.c linux-libre-2.6.39-gnu/arch/sparc/kernel/ds.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -1218,7 +1218,7 @@
 	return 0;
 }
 
-static struct vio_device_id __initdata ds_match[] = {
+static const struct vio_device_id ds_match[] = {
 	{
 		.type = "domain-services-port",
 	},
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/entry.h linux-libre-2.6.39-gnu/arch/sparc/kernel/entry.h
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/entry.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/entry.h	2011-05-19 00:06:34.000000000 -0400
@@ -213,8 +213,8 @@
 struct ino_bucket {
 /*0x00*/unsigned long __irq_chain_pa;
 
-	/* Virtual interrupt number assigned to this INO.  */
-/*0x08*/unsigned int __virt_irq;
+	/* Interrupt number assigned to this INO.  */
+/*0x08*/unsigned int __irq;
 /*0x0c*/unsigned int __pad;
 };
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/entry.S linux-libre-2.6.39-gnu/arch/sparc/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -801,7 +801,7 @@
 	.globl	vac_hwflush_patch1_on, vac_hwflush_patch2_on
 
 /*
- * Ugly, but we cant use hardware flushing on the sun4 and we'd require
+ * Ugly, but we can't use hardware flushing on the sun4 and we'd require
  * two instructions (Anton)
  */
 vac_hwflush_patch1_on:		addcc	%l7, -PAGE_SIZE, %l7
@@ -851,7 +851,7 @@
 	 sethi	%hi(~((1 << SUN4C_REAL_PGDIR_SHIFT) - 1)), %l4
 
 	/* If the kernel references a bum kernel pointer, or a pte which
-	 * points to a non existant page in ram, we will run this code
+	 * points to a non existent page in ram, we will run this code
 	 * _forever_ and lock up the machine!!!!! So we must check for
 	 * this condition, the AC_SYNC_ERR bits are what we must examine.
 	 * Also a parity error would make this happen as well.  So we just
@@ -1283,7 +1283,7 @@
 	.globl	ret_from_fork
 ret_from_fork:
 	call	schedule_tail
-	 mov	%g3, %o0
+	 ld	[%g3 + TI_TASK], %o0
 	b	ret_sys_call
 	 ld	[%sp + STACKFRAME_SZ + PT_I0], %o0
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/head_64.S linux-libre-2.6.39-gnu/arch/sparc/kernel/head_64.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/head_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/head_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -85,7 +85,7 @@
 sparc64_boot:
 	mov	%o4, %l7
 
-	/* We need to remap the kernel.  Use position independant
+	/* We need to remap the kernel.  Use position independent
 	 * code to remap us to KERNBASE.
 	 *
 	 * SILO can invoke us with 32-bit address masking enabled,
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/init_task.c linux-libre-2.6.39-gnu/arch/sparc/kernel/init_task.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/init_task.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/init_task.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 
 /* .text section in head.S is aligned at 8k boundary and this gets linked
  * right after that so that the init_thread_union is aligned properly as well.
- * If this is not aligned on a 8k boundry, then you should change code
+ * If this is not aligned on a 8k boundary, then you should change code
  * in etrap.S which assumes it.
  */
 union thread_union init_thread_union __init_task_data =
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/iommu.c linux-libre-2.6.39-gnu/arch/sparc/kernel/iommu.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/iommu.c	2011-05-19 00:06:34.000000000 -0400
@@ -333,13 +333,10 @@
 				 void *cpu, dma_addr_t dvma)
 {
 	struct iommu *iommu;
-	iopte_t *iopte;
 	unsigned long flags, order, npages;
 
 	npages = IO_PAGE_ALIGN(size) >> IO_PAGE_SHIFT;
 	iommu = dev->archdata.iommu;
-	iopte = iommu->page_table +
-		((dvma - iommu->page_table_map_base) >> IO_PAGE_SHIFT);
 
 	spin_lock_irqsave(&iommu->lock, flags);
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/ioport.c linux-libre-2.6.39-gnu/arch/sparc/kernel/ioport.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/ioport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/ioport.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,10 +50,14 @@
 #include <asm/io-unit.h>
 #include <asm/leon.h>
 
-#ifdef CONFIG_SPARC_LEON
-#define mmu_inval_dma_area(p, l) leon_flush_dcache_all()
-#else
+#ifndef CONFIG_SPARC_LEON
 #define mmu_inval_dma_area(p, l)	/* Anton pulled it out for 2.4.0-xx */
+#else
+static inline void mmu_inval_dma_area(void *va, unsigned long len)
+{
+	if (!sparc_leon3_snooping_enabled())
+		leon_flush_dcache_all();
+}
 #endif
 
 static struct resource *_sparc_find_resource(struct resource *r,
@@ -254,7 +258,7 @@
 				 dma_addr_t *dma_addrp, gfp_t gfp)
 {
 	struct platform_device *op = to_platform_device(dev);
-	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
+	unsigned long len_total = PAGE_ALIGN(len);
 	unsigned long va;
 	struct resource *res;
 	int order;
@@ -280,7 +284,8 @@
 		printk("sbus_alloc_consistent: cannot occupy 0x%lx", len_total);
 		goto err_nova;
 	}
-	mmu_inval_dma_area(va, len_total);
+	mmu_inval_dma_area((void *)va, len_total);
+
 	// XXX The mmu_map_dma_area does this for us below, see comments.
 	// sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
 	/*
@@ -297,9 +302,9 @@
 err_noiommu:
 	release_resource(res);
 err_nova:
-	free_pages(va, order);
-err_nomem:
 	kfree(res);
+err_nomem:
+	free_pages(va, order);
 err_nopages:
 	return NULL;
 }
@@ -321,7 +326,7 @@
 		return;
 	}
 
-	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	n = PAGE_ALIGN(n);
 	if ((res->end-res->start)+1 != n) {
 		printk("sbus_free_consistent: region 0x%lx asked 0x%zx\n",
 		    (long)((res->end-res->start)+1), n);
@@ -408,9 +413,6 @@
 	.sync_sg_for_device	= sbus_sync_sg_for_device,
 };
 
-struct dma_map_ops *dma_ops = &sbus_dma_ops;
-EXPORT_SYMBOL(dma_ops);
-
 static int __init sparc_register_ioport(void)
 {
 	register_proc_sparc_ioport();
@@ -422,7 +424,9 @@
 
 #endif /* CONFIG_SBUS */
 
-#ifdef CONFIG_PCI
+
+/* LEON reuses PCI DMA ops */
+#if defined(CONFIG_PCI) || defined(CONFIG_SPARC_LEON)
 
 /* Allocate and map kernel buffer using consistent mode DMA for a device.
  * hwdev should be valid struct pci_dev pointer for PCI devices.
@@ -430,8 +434,8 @@
 static void *pci32_alloc_coherent(struct device *dev, size_t len,
 				  dma_addr_t *pba, gfp_t gfp)
 {
-	unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK;
-	unsigned long va;
+	unsigned long len_total = PAGE_ALIGN(len);
+	void *va;
 	struct resource *res;
 	int order;
 
@@ -443,34 +447,34 @@
 	}
 
 	order = get_order(len_total);
-	va = __get_free_pages(GFP_KERNEL, order);
-	if (va == 0) {
+	va = (void *) __get_free_pages(GFP_KERNEL, order);
+	if (va == NULL) {
 		printk("pci_alloc_consistent: no %ld pages\n", len_total>>PAGE_SHIFT);
-		return NULL;
+		goto err_nopages;
 	}
 
 	if ((res = kzalloc(sizeof(struct resource), GFP_KERNEL)) == NULL) {
-		free_pages(va, order);
 		printk("pci_alloc_consistent: no core\n");
-		return NULL;
+		goto err_nomem;
 	}
 
 	if (allocate_resource(&_sparc_dvma, res, len_total,
 	    _sparc_dvma.start, _sparc_dvma.end, PAGE_SIZE, NULL, NULL) != 0) {
 		printk("pci_alloc_consistent: cannot occupy 0x%lx", len_total);
-		free_pages(va, order);
-		kfree(res);
-		return NULL;
+		goto err_nova;
 	}
 	mmu_inval_dma_area(va, len_total);
-#if 0
-/* P3 */ printk("pci_alloc_consistent: kva %lx uncva %lx phys %lx size %lx\n",
-  (long)va, (long)res->start, (long)virt_to_phys(va), len_total);
-#endif
 	sparc_mapiorange(0, virt_to_phys(va), res->start, len_total);
 
 	*pba = virt_to_phys(va); /* equals virt_to_bus (R.I.P.) for us. */
 	return (void *) res->start;
+
+err_nova:
+	kfree(res);
+err_nomem:
+	free_pages((unsigned long)va, order);
+err_nopages:
+	return NULL;
 }
 
 /* Free and unmap a consistent DMA buffer.
@@ -485,7 +489,7 @@
 				dma_addr_t ba)
 {
 	struct resource *res;
-	unsigned long pgp;
+	void *pgp;
 
 	if ((res = _sparc_find_resource(&_sparc_dvma,
 	    (unsigned long)p)) == NULL) {
@@ -498,21 +502,21 @@
 		return;
 	}
 
-	n = (n + PAGE_SIZE-1) & PAGE_MASK;
+	n = PAGE_ALIGN(n);
 	if ((res->end-res->start)+1 != n) {
 		printk("pci_free_consistent: region 0x%lx asked 0x%lx\n",
 		    (long)((res->end-res->start)+1), (long)n);
 		return;
 	}
 
-	pgp = (unsigned long) phys_to_virt(ba);	/* bus_to_virt actually */
+	pgp = phys_to_virt(ba);	/* bus_to_virt actually */
 	mmu_inval_dma_area(pgp, n);
 	sparc_unmapiorange((unsigned long)p, n);
 
 	release_resource(res);
 	kfree(res);
 
-	free_pages(pgp, get_order(n));
+	free_pages((unsigned long)pgp, get_order(n));
 }
 
 /*
@@ -527,6 +531,13 @@
 	return page_to_phys(page) + offset;
 }
 
+static void pci32_unmap_page(struct device *dev, dma_addr_t ba, size_t size,
+			     enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+	if (dir != PCI_DMA_TODEVICE)
+		mmu_inval_dma_area(phys_to_virt(ba), PAGE_ALIGN(size));
+}
+
 /* Map a set of buffers described by scatterlist in streaming
  * mode for DMA.  This is the scather-gather version of the
  * above pci_map_single interface.  Here the scatter gather list
@@ -572,9 +583,8 @@
 	if (dir != PCI_DMA_TODEVICE) {
 		for_each_sg(sgl, sg, nents, n) {
 			BUG_ON(page_address(sg_page(sg)) == NULL);
-			mmu_inval_dma_area(
-			    (unsigned long) page_address(sg_page(sg)),
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+			mmu_inval_dma_area(page_address(sg_page(sg)),
+					   PAGE_ALIGN(sg->length));
 		}
 	}
 }
@@ -593,8 +603,8 @@
 				      size_t size, enum dma_data_direction dir)
 {
 	if (dir != PCI_DMA_TODEVICE) {
-		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
-		    (size + PAGE_SIZE-1) & PAGE_MASK);
+		mmu_inval_dma_area(phys_to_virt(ba),
+				   PAGE_ALIGN(size));
 	}
 }
 
@@ -602,8 +612,8 @@
 					 size_t size, enum dma_data_direction dir)
 {
 	if (dir != PCI_DMA_TODEVICE) {
-		mmu_inval_dma_area((unsigned long)phys_to_virt(ba),
-		    (size + PAGE_SIZE-1) & PAGE_MASK);
+		mmu_inval_dma_area(phys_to_virt(ba),
+				   PAGE_ALIGN(size));
 	}
 }
 
@@ -622,9 +632,8 @@
 	if (dir != PCI_DMA_TODEVICE) {
 		for_each_sg(sgl, sg, nents, n) {
 			BUG_ON(page_address(sg_page(sg)) == NULL);
-			mmu_inval_dma_area(
-			    (unsigned long) page_address(sg_page(sg)),
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+			mmu_inval_dma_area(page_address(sg_page(sg)),
+					   PAGE_ALIGN(sg->length));
 		}
 	}
 }
@@ -638,9 +647,8 @@
 	if (dir != PCI_DMA_TODEVICE) {
 		for_each_sg(sgl, sg, nents, n) {
 			BUG_ON(page_address(sg_page(sg)) == NULL);
-			mmu_inval_dma_area(
-			    (unsigned long) page_address(sg_page(sg)),
-			    (sg->length + PAGE_SIZE-1) & PAGE_MASK);
+			mmu_inval_dma_area(page_address(sg_page(sg)),
+					   PAGE_ALIGN(sg->length));
 		}
 	}
 }
@@ -649,6 +657,7 @@
 	.alloc_coherent		= pci32_alloc_coherent,
 	.free_coherent		= pci32_free_coherent,
 	.map_page		= pci32_map_page,
+	.unmap_page		= pci32_unmap_page,
 	.map_sg			= pci32_map_sg,
 	.unmap_sg		= pci32_unmap_sg,
 	.sync_single_for_cpu	= pci32_sync_single_for_cpu,
@@ -658,7 +667,16 @@
 };
 EXPORT_SYMBOL(pci32_dma_ops);
 
-#endif /* CONFIG_PCI */
+#endif /* CONFIG_PCI || CONFIG_SPARC_LEON */
+
+#ifdef CONFIG_SPARC_LEON
+struct dma_map_ops *dma_ops = &pci32_dma_ops;
+#elif defined(CONFIG_SBUS)
+struct dma_map_ops *dma_ops = &sbus_dma_ops;
+#endif
+
+EXPORT_SYMBOL(dma_ops);
+
 
 /*
  * Return whether the given PCI device DMA address mask can be
@@ -717,7 +735,7 @@
 static struct resource *_sparc_find_resource(struct resource *root,
 					     unsigned long hit)
 {
-        struct resource *tmp;
+	struct resource *tmp;
 
 	for (tmp = root->child; tmp != 0; tmp = tmp->sibling) {
 		if (tmp->start <= hit && tmp->end >= hit)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/irq_32.c linux-libre-2.6.39-gnu/arch/sparc/kernel/irq_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/irq_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/irq_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,8 @@
 /*
- *  arch/sparc/kernel/irq.c:  Interrupt request handling routines. On the
- *                            Sparc the IRQs are basically 'cast in stone'
- *                            and you are supposed to probe the prom's device
- *                            node trees to find out who's got which IRQ.
+ * Interrupt request handling routines. On the
+ * Sparc the IRQs are basically 'cast in stone'
+ * and you are supposed to probe the prom's device
+ * node trees to find out who's got which IRQ.
  *
  *  Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu)
  *  Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx)
@@ -11,40 +11,11 @@
  *  Copyright (C) 1998-2000 Anton Blanchard (anton@samba.org)
  */
 
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/errno.h>
-#include <linux/linkage.h>
 #include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/delay.h>
-#include <linux/threads.h>
-#include <linux/spinlock.h>
 #include <linux/seq_file.h>
 
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/smp.h>
-#include <asm/vaddrs.h>
-#include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
-#include <asm/traps.h>
-#include <asm/irq.h>
-#include <asm/io.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/pcic.h>
 #include <asm/cacheflush.h>
-#include <asm/irq_regs.h>
+#include <asm/pcic.h>
 #include <asm/leon.h>
 
 #include "kernel.h"
@@ -57,6 +28,10 @@
 #define SMP_NOP2
 #define SMP_NOP3
 #endif /* SMP */
+
+/* platform specific irq setup */
+struct sparc_irq_config sparc_irq_config;
+
 unsigned long arch_local_irq_save(void)
 {
 	unsigned long retval;
@@ -128,15 +103,7 @@
  *
  */
 
-static void irq_panic(void)
-{
-    extern char *cputypval;
-    prom_printf("machine: %s doesn't have irq handlers defined!\n",cputypval);
-    prom_halt();
-}
 
-void (*sparc_init_timers)(irq_handler_t ) =
-    (void (*)(irq_handler_t )) irq_panic;
 
 /*
  * Dave Redman (djhr@tadpole.co.uk)
@@ -145,7 +112,7 @@
  * instead, because some of the devices attach very early, I do something
  * equally sucky but at least we'll never try to free statically allocated
  * space or call kmalloc before kmalloc_init :(.
- * 
+ *
  * In fact it's the timer10 that attaches first.. then timer14
  * then kmalloc_init is called.. then the tty interrupts attach.
  * hmmm....
@@ -166,22 +133,20 @@
 
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i = *(loff_t *) v;
-	struct irqaction * action;
+	int i = *(loff_t *)v;
+	struct irqaction *action;
 	unsigned long flags;
 #ifdef CONFIG_SMP
 	int j;
 #endif
 
-	if (sparc_cpu_model == sun4d) {
-		extern int show_sun4d_interrupts(struct seq_file *, void *);
-		
+	if (sparc_cpu_model == sun4d)
 		return show_sun4d_interrupts(p, v);
-	}
+
 	spin_lock_irqsave(&irq_action_lock, flags);
 	if (i < NR_IRQS) {
 		action = sparc_irq[i].action;
-		if (!action) 
+		if (!action)
 			goto out_unlock;
 		seq_printf(p, "%3d: ", i);
 #ifndef CONFIG_SMP
@@ -195,7 +160,7 @@
 		seq_printf(p, " %c %s",
 			(action->flags & IRQF_DISABLED) ? '+' : ' ',
 			action->name);
-		for (action=action->next; action; action = action->next) {
+		for (action = action->next; action; action = action->next) {
 			seq_printf(p, ",%s %s",
 				(action->flags & IRQF_DISABLED) ? " +" : "",
 				action->name);
@@ -209,22 +174,20 @@
 
 void free_irq(unsigned int irq, void *dev_id)
 {
-	struct irqaction * action;
+	struct irqaction *action;
 	struct irqaction **actionp;
-        unsigned long flags;
+	unsigned long flags;
 	unsigned int cpu_irq;
-	
+
 	if (sparc_cpu_model == sun4d) {
-		extern void sun4d_free_irq(unsigned int, void *);
-		
 		sun4d_free_irq(irq, dev_id);
 		return;
 	}
 	cpu_irq = irq & (NR_IRQS - 1);
-        if (cpu_irq > 14) {  /* 14 irq levels on the sparc */
-                printk("Trying to free bogus IRQ %d\n", irq);
-                return;
-        }
+	if (cpu_irq > 14) {  /* 14 irq levels on the sparc */
+		printk(KERN_ERR "Trying to free bogus IRQ %d\n", irq);
+		return;
+	}
 
 	spin_lock_irqsave(&irq_action_lock, flags);
 
@@ -232,7 +195,7 @@
 	action = *actionp;
 
 	if (!action->handler) {
-		printk("Trying to free free IRQ%d\n",irq);
+		printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
 		goto out_unlock;
 	}
 	if (dev_id) {
@@ -242,19 +205,21 @@
 			actionp = &action->next;
 		}
 		if (!action) {
-			printk("Trying to free free shared IRQ%d\n",irq);
+			printk(KERN_ERR "Trying to free free shared IRQ%d\n",
+			       irq);
 			goto out_unlock;
 		}
 	} else if (action->flags & IRQF_SHARED) {
-		printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+		printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
+		       irq);
 		goto out_unlock;
 	}
-	if (action->flags & SA_STATIC_ALLOC)
-	{
-		/* This interrupt is marked as specially allocated
+	if (action->flags & SA_STATIC_ALLOC) {
+		/*
+		 * This interrupt is marked as specially allocated
 		 * so it is a bad idea to free it.
 		 */
-		printk("Attempt to free statically allocated IRQ%d (%s)\n",
+		printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
 		       irq, action->name);
 		goto out_unlock;
 	}
@@ -275,7 +240,6 @@
 out_unlock:
 	spin_unlock_irqrestore(&irq_action_lock, flags);
 }
-
 EXPORT_SYMBOL(free_irq);
 
 /*
@@ -297,64 +261,62 @@
 EXPORT_SYMBOL(synchronize_irq);
 #endif /* SMP */
 
-void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs)
+void unexpected_irq(int irq, void *dev_id, struct pt_regs *regs)
 {
-        int i;
-	struct irqaction * action;
+	int i;
+	struct irqaction *action;
 	unsigned int cpu_irq;
-	
+
 	cpu_irq = irq & (NR_IRQS - 1);
 	action = sparc_irq[cpu_irq].action;
 
-        printk("IO device interrupt, irq = %d\n", irq);
-        printk("PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc, 
+	printk(KERN_ERR "IO device interrupt, irq = %d\n", irq);
+	printk(KERN_ERR "PC = %08lx NPC = %08lx FP=%08lx\n", regs->pc,
 		    regs->npc, regs->u_regs[14]);
 	if (action) {
-		printk("Expecting: ");
-        	for (i = 0; i < 16; i++)
-                	if (action->handler)
-                        	printk("[%s:%d:0x%x] ", action->name,
-				       (int) i, (unsigned int) action->handler);
+		printk(KERN_ERR "Expecting: ");
+		for (i = 0; i < 16; i++)
+			if (action->handler)
+				printk(KERN_CONT "[%s:%d:0x%x] ", action->name,
+				       i, (unsigned int)action->handler);
 	}
-        printk("AIEEE\n");
+	printk(KERN_ERR "AIEEE\n");
 	panic("bogus interrupt received");
 }
 
-void handler_irq(int irq, struct pt_regs * regs)
+void handler_irq(int pil, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
-	struct irqaction * action;
+	struct irqaction *action;
 	int cpu = smp_processor_id();
-#ifdef CONFIG_SMP
-	extern void smp4m_irq_rotate(int cpu);
-#endif
 
 	old_regs = set_irq_regs(regs);
 	irq_enter();
-	disable_pil_irq(irq);
+	disable_pil_irq(pil);
 #ifdef CONFIG_SMP
 	/* Only rotate on lower priority IRQs (scsi, ethernet, etc.). */
-	if((sparc_cpu_model==sun4m) && (irq < 10))
+	if ((sparc_cpu_model==sun4m) && (pil < 10))
 		smp4m_irq_rotate(cpu);
 #endif
-	action = sparc_irq[irq].action;
-	sparc_irq[irq].flags |= SPARC_IRQ_INPROGRESS;
-	kstat_cpu(cpu).irqs[irq]++;
+	action = sparc_irq[pil].action;
+	sparc_irq[pil].flags |= SPARC_IRQ_INPROGRESS;
+	kstat_cpu(cpu).irqs[pil]++;
 	do {
 		if (!action || !action->handler)
-			unexpected_irq(irq, NULL, regs);
-		action->handler(irq, action->dev_id);
+			unexpected_irq(pil, NULL, regs);
+		action->handler(pil, action->dev_id);
 		action = action->next;
 	} while (action);
-	sparc_irq[irq].flags &= ~SPARC_IRQ_INPROGRESS;
-	enable_pil_irq(irq);
+	sparc_irq[pil].flags &= ~SPARC_IRQ_INPROGRESS;
+	enable_pil_irq(pil);
 	irq_exit();
 	set_irq_regs(old_regs);
 }
 
 #if defined(CONFIG_BLK_DEV_FD) || defined(CONFIG_BLK_DEV_FD_MODULE)
 
-/* Fast IRQs on the Sparc can only have one routine attached to them,
+/*
+ * Fast IRQs on the Sparc can only have one routine attached to them,
  * thus no sharing possible.
  */
 static int request_fast_irq(unsigned int irq,
@@ -367,15 +329,13 @@
 	int ret;
 #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
 	struct tt_entry *trap_table;
-	extern struct tt_entry trapbase_cpu1, trapbase_cpu2, trapbase_cpu3;
 #endif
-	
 	cpu_irq = irq & (NR_IRQS - 1);
-	if(cpu_irq > 14) {
+	if (cpu_irq > 14) {
 		ret = -EINVAL;
 		goto out;
 	}
-	if(!handler) {
+	if (!handler) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -383,34 +343,33 @@
 	spin_lock_irqsave(&irq_action_lock, flags);
 
 	action = sparc_irq[cpu_irq].action;
-	if(action) {
-		if(action->flags & IRQF_SHARED)
+	if (action) {
+		if (action->flags & IRQF_SHARED)
 			panic("Trying to register fast irq when already shared.\n");
-		if(irqflags & IRQF_SHARED)
+		if (irqflags & IRQF_SHARED)
 			panic("Trying to register fast irq as shared.\n");
 
 		/* Anyway, someone already owns it so cannot be made fast. */
-		printk("request_fast_irq: Trying to register yet already owned.\n");
+		printk(KERN_ERR "request_fast_irq: Trying to register yet already owned.\n");
 		ret = -EBUSY;
 		goto out_unlock;
 	}
 
-	/* If this is flagged as statically allocated then we use our
+	/*
+	 * If this is flagged as statically allocated then we use our
 	 * private struct which is never freed.
 	 */
 	if (irqflags & SA_STATIC_ALLOC) {
-	    if (static_irq_count < MAX_STATIC_ALLOC)
-		action = &static_irqaction[static_irq_count++];
-	    else
-		printk("Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
-		       irq, devname);
+		if (static_irq_count < MAX_STATIC_ALLOC)
+			action = &static_irqaction[static_irq_count++];
+		else
+			printk(KERN_ERR "Fast IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
+			       irq, devname);
 	}
-	
+
 	if (action == NULL)
-	    action = kmalloc(sizeof(struct irqaction),
-						 GFP_ATOMIC);
-	
-	if (!action) { 
+		action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+	if (!action) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
@@ -426,9 +385,12 @@
 
 	INSTANTIATE(sparc_ttable)
 #if defined CONFIG_SMP && !defined CONFIG_SPARC_LEON
-	trap_table = &trapbase_cpu1; INSTANTIATE(trap_table)
-	trap_table = &trapbase_cpu2; INSTANTIATE(trap_table)
-	trap_table = &trapbase_cpu3; INSTANTIATE(trap_table)
+	trap_table = &trapbase_cpu1;
+	INSTANTIATE(trap_table)
+	trap_table = &trapbase_cpu2;
+	INSTANTIATE(trap_table)
+	trap_table = &trapbase_cpu3;
+	INSTANTIATE(trap_table)
 #endif
 #undef INSTANTIATE
 	/*
@@ -454,7 +416,8 @@
 	return ret;
 }
 
-/* These variables are used to access state from the assembler
+/*
+ * These variables are used to access state from the assembler
  * interrupt handler, floppy_hardint, so we cannot put these in
  * the floppy driver image because that would not work in the
  * modular case.
@@ -477,8 +440,6 @@
 unsigned long pdma_areasize;
 EXPORT_SYMBOL(pdma_areasize);
 
-extern void floppy_hardint(void);
-
 static irq_handler_t floppy_irq_handler;
 
 void sparc_floppy_irq(int irq, void *dev_id, struct pt_regs *regs)
@@ -494,9 +455,11 @@
 	irq_exit();
 	enable_pil_irq(irq);
 	set_irq_regs(old_regs);
-	// XXX Eek, it's totally changed with preempt_count() and such
-	// if (softirq_pending(cpu))
-	//	do_softirq();
+	/*
+	 * XXX Eek, it's totally changed with preempt_count() and such
+	 * if (softirq_pending(cpu))
+	 *	do_softirq();
+	 */
 }
 
 int sparc_floppy_request_irq(int irq, unsigned long flags,
@@ -511,21 +474,18 @@
 
 int request_irq(unsigned int irq,
 		irq_handler_t handler,
-		unsigned long irqflags, const char * devname, void *dev_id)
+		unsigned long irqflags, const char *devname, void *dev_id)
 {
-	struct irqaction * action, **actionp;
+	struct irqaction *action, **actionp;
 	unsigned long flags;
 	unsigned int cpu_irq;
 	int ret;
-	
-	if (sparc_cpu_model == sun4d) {
-		extern int sun4d_request_irq(unsigned int, 
-					     irq_handler_t ,
-					     unsigned long, const char *, void *);
+
+	if (sparc_cpu_model == sun4d)
 		return sun4d_request_irq(irq, handler, irqflags, devname, dev_id);
-	}
+
 	cpu_irq = irq & (NR_IRQS - 1);
-	if(cpu_irq > 14) {
+	if (cpu_irq > 14) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -533,7 +493,7 @@
 		ret = -EINVAL;
 		goto out;
 	}
-	    
+
 	spin_lock_irqsave(&irq_action_lock, flags);
 
 	actionp = &sparc_irq[cpu_irq].action;
@@ -544,7 +504,8 @@
 			goto out_unlock;
 		}
 		if ((action->flags & IRQF_DISABLED) != (irqflags & IRQF_DISABLED)) {
-			printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+			printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
+			       irq);
 			ret = -EBUSY;
 			goto out_unlock;
 		}
@@ -559,14 +520,12 @@
 		if (static_irq_count < MAX_STATIC_ALLOC)
 			action = &static_irqaction[static_irq_count++];
 		else
-			printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname);
+			printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
+			       irq, devname);
 	}
-	
 	if (action == NULL)
-		action = kmalloc(sizeof(struct irqaction),
-						     GFP_ATOMIC);
-	
-	if (!action) { 
+		action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+	if (!action) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
@@ -587,7 +546,6 @@
 out:
 	return ret;
 }
-
 EXPORT_SYMBOL(request_irq);
 
 void disable_irq_nosync(unsigned int irq)
@@ -606,26 +564,30 @@
 {
 	__enable_irq(irq);
 }
-
 EXPORT_SYMBOL(enable_irq);
 
-/* We really don't need these at all on the Sparc.  We only have
+/*
+ * We really don't need these at all on the Sparc.  We only have
  * stubs here because they are exported to modules.
  */
 unsigned long probe_irq_on(void)
 {
 	return 0;
 }
-
 EXPORT_SYMBOL(probe_irq_on);
 
 int probe_irq_off(unsigned long mask)
 {
 	return 0;
 }
-
 EXPORT_SYMBOL(probe_irq_off);
 
+static unsigned int build_device_irq(struct platform_device *op,
+                                     unsigned int real_irq)
+{
+	return real_irq;
+}
+
 /* djhr
  * This could probably be made indirect too and assigned in the CPU
  * bits of the code. That would be much nicer I think and would also
@@ -636,11 +598,9 @@
 
 void __init init_IRQ(void)
 {
-	extern void sun4c_init_IRQ( void );
-	extern void sun4m_init_IRQ( void );
-	extern void sun4d_init_IRQ( void );
+	sparc_irq_config.build_device_irq = build_device_irq;
 
-	switch(sparc_cpu_model) {
+	switch (sparc_cpu_model) {
 	case sun4c:
 	case sun4:
 		sun4c_init_IRQ();
@@ -656,7 +616,7 @@
 #endif
 		sun4m_init_IRQ();
 		break;
-		
+
 	case sun4d:
 		sun4d_init_IRQ();
 		break;
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/irq_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/irq_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/irq_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/irq_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 			       "i" (ASI_PHYS_USE_EC));
 }
 
-static unsigned int bucket_get_virt_irq(unsigned long bucket_pa)
+static unsigned int bucket_get_irq(unsigned long bucket_pa)
 {
 	unsigned int ret;
 
@@ -90,21 +90,20 @@
 			     : "=&r" (ret)
 			     : "r" (bucket_pa +
 				    offsetof(struct ino_bucket,
-					     __virt_irq)),
+					     __irq)),
 			       "i" (ASI_PHYS_USE_EC));
 
 	return ret;
 }
 
-static void bucket_set_virt_irq(unsigned long bucket_pa,
-				unsigned int virt_irq)
+static void bucket_set_irq(unsigned long bucket_pa, unsigned int irq)
 {
 	__asm__ __volatile__("stwa	%0, [%1] %2"
 			     : /* no outputs */
-			     : "r" (virt_irq),
+			     : "r" (irq),
 			       "r" (bucket_pa +
 				    offsetof(struct ino_bucket,
-					     __virt_irq)),
+					     __irq)),
 			       "i" (ASI_PHYS_USE_EC));
 }
 
@@ -114,97 +113,63 @@
 	unsigned int dev_handle;
 	unsigned int dev_ino;
 	unsigned int in_use;
-} virt_irq_table[NR_IRQS];
-static DEFINE_SPINLOCK(virt_irq_alloc_lock);
+} irq_table[NR_IRQS];
+static DEFINE_SPINLOCK(irq_alloc_lock);
 
-unsigned char virt_irq_alloc(unsigned int dev_handle,
-			     unsigned int dev_ino)
+unsigned char irq_alloc(unsigned int dev_handle, unsigned int dev_ino)
 {
 	unsigned long flags;
 	unsigned char ent;
 
 	BUILD_BUG_ON(NR_IRQS >= 256);
 
-	spin_lock_irqsave(&virt_irq_alloc_lock, flags);
+	spin_lock_irqsave(&irq_alloc_lock, flags);
 
 	for (ent = 1; ent < NR_IRQS; ent++) {
-		if (!virt_irq_table[ent].in_use)
+		if (!irq_table[ent].in_use)
 			break;
 	}
 	if (ent >= NR_IRQS) {
 		printk(KERN_ERR "IRQ: Out of virtual IRQs.\n");
 		ent = 0;
 	} else {
-		virt_irq_table[ent].dev_handle = dev_handle;
-		virt_irq_table[ent].dev_ino = dev_ino;
-		virt_irq_table[ent].in_use = 1;
+		irq_table[ent].dev_handle = dev_handle;
+		irq_table[ent].dev_ino = dev_ino;
+		irq_table[ent].in_use = 1;
 	}
 
-	spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
+	spin_unlock_irqrestore(&irq_alloc_lock, flags);
 
 	return ent;
 }
 
 #ifdef CONFIG_PCI_MSI
-void virt_irq_free(unsigned int virt_irq)
+void irq_free(unsigned int irq)
 {
 	unsigned long flags;
 
-	if (virt_irq >= NR_IRQS)
+	if (irq >= NR_IRQS)
 		return;
 
-	spin_lock_irqsave(&virt_irq_alloc_lock, flags);
+	spin_lock_irqsave(&irq_alloc_lock, flags);
 
-	virt_irq_table[virt_irq].in_use = 0;
+	irq_table[irq].in_use = 0;
 
-	spin_unlock_irqrestore(&virt_irq_alloc_lock, flags);
+	spin_unlock_irqrestore(&irq_alloc_lock, flags);
 }
 #endif
 
 /*
  * /proc/interrupts printing:
  */
-
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %9s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
+	int j;
 
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
-		seq_printf(p, "NMI: ");
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", cpu_data(j).__nmi_count);
-		seq_printf(p, "     Non-maskable interrupts\n");
-	}
+	seq_printf(p, "NMI: ");
+	for_each_online_cpu(j)
+		seq_printf(p, "%10u ", cpu_data(j).__nmi_count);
+	seq_printf(p, "     Non-maskable interrupts\n");
 	return 0;
 }
 
@@ -253,39 +218,38 @@
 };
 
 #ifdef CONFIG_SMP
-static int irq_choose_cpu(unsigned int virt_irq, const struct cpumask *affinity)
+static int irq_choose_cpu(unsigned int irq, const struct cpumask *affinity)
 {
 	cpumask_t mask;
 	int cpuid;
 
 	cpumask_copy(&mask, affinity);
 	if (cpus_equal(mask, cpu_online_map)) {
-		cpuid = map_to_cpu(virt_irq);
+		cpuid = map_to_cpu(irq);
 	} else {
 		cpumask_t tmp;
 
 		cpus_and(tmp, cpu_online_map, mask);
-		cpuid = cpus_empty(tmp) ? map_to_cpu(virt_irq) : first_cpu(tmp);
+		cpuid = cpus_empty(tmp) ? map_to_cpu(irq) : first_cpu(tmp);
 	}
 
 	return cpuid;
 }
 #else
-#define irq_choose_cpu(virt_irq, affinity)	\
+#define irq_choose_cpu(irq, affinity)	\
 	real_hard_smp_processor_id()
 #endif
 
-static void sun4u_irq_enable(unsigned int virt_irq)
+static void sun4u_irq_enable(struct irq_data *data)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_handler_data *handler_data = data->handler_data;
 
-	if (likely(data)) {
+	if (likely(handler_data)) {
 		unsigned long cpuid, imap, val;
 		unsigned int tid;
 
-		cpuid = irq_choose_cpu(virt_irq,
-				       irq_desc[virt_irq].affinity);
-		imap = data->imap;
+		cpuid = irq_choose_cpu(data->irq, data->affinity);
+		imap = handler_data->imap;
 
 		tid = sun4u_compute_tid(imap, cpuid);
 
@@ -294,21 +258,21 @@
 			 IMAP_AID_SAFARI | IMAP_NID_SAFARI);
 		val |= tid | IMAP_VALID;
 		upa_writeq(val, imap);
-		upa_writeq(ICLR_IDLE, data->iclr);
+		upa_writeq(ICLR_IDLE, handler_data->iclr);
 	}
 }
 
-static int sun4u_set_affinity(unsigned int virt_irq,
-			       const struct cpumask *mask)
+static int sun4u_set_affinity(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
+	struct irq_handler_data *handler_data = data->handler_data;
 
-	if (likely(data)) {
+	if (likely(handler_data)) {
 		unsigned long cpuid, imap, val;
 		unsigned int tid;
 
-		cpuid = irq_choose_cpu(virt_irq, mask);
-		imap = data->imap;
+		cpuid = irq_choose_cpu(data->irq, mask);
+		imap = handler_data->imap;
 
 		tid = sun4u_compute_tid(imap, cpuid);
 
@@ -317,7 +281,7 @@
 			 IMAP_AID_SAFARI | IMAP_NID_SAFARI);
 		val |= tid | IMAP_VALID;
 		upa_writeq(val, imap);
-		upa_writeq(ICLR_IDLE, data->iclr);
+		upa_writeq(ICLR_IDLE, handler_data->iclr);
 	}
 
 	return 0;
@@ -340,27 +304,22 @@
  * sees that, it also hooks up a default ->shutdown method which
  * invokes ->mask() which we do not want.  See irq_chip_set_defaults().
  */
-static void sun4u_irq_disable(unsigned int virt_irq)
+static void sun4u_irq_disable(struct irq_data *data)
 {
 }
 
-static void sun4u_irq_eoi(unsigned int virt_irq)
+static void sun4u_irq_eoi(struct irq_data *data)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	struct irq_desc *desc = irq_desc + virt_irq;
-
-	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		return;
+	struct irq_handler_data *handler_data = data->handler_data;
 
-	if (likely(data))
-		upa_writeq(ICLR_IDLE, data->iclr);
+	if (likely(handler_data))
+		upa_writeq(ICLR_IDLE, handler_data->iclr);
 }
 
-static void sun4v_irq_enable(unsigned int virt_irq)
+static void sun4v_irq_enable(struct irq_data *data)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	unsigned long cpuid = irq_choose_cpu(virt_irq,
-					     irq_desc[virt_irq].affinity);
+	unsigned int ino = irq_table[data->irq].dev_ino;
+	unsigned long cpuid = irq_choose_cpu(data->irq, data->affinity);
 	int err;
 
 	err = sun4v_intr_settarget(ino, cpuid);
@@ -377,11 +336,11 @@
 		       ino, err);
 }
 
-static int sun4v_set_affinity(unsigned int virt_irq,
-			       const struct cpumask *mask)
+static int sun4v_set_affinity(struct irq_data *data,
+			       const struct cpumask *mask, bool force)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	unsigned long cpuid = irq_choose_cpu(virt_irq, mask);
+	unsigned int ino = irq_table[data->irq].dev_ino;
+	unsigned long cpuid = irq_choose_cpu(data->irq, mask);
 	int err;
 
 	err = sun4v_intr_settarget(ino, cpuid);
@@ -392,9 +351,9 @@
 	return 0;
 }
 
-static void sun4v_irq_disable(unsigned int virt_irq)
+static void sun4v_irq_disable(struct irq_data *data)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+	unsigned int ino = irq_table[data->irq].dev_ino;
 	int err;
 
 	err = sun4v_intr_setenabled(ino, HV_INTR_DISABLED);
@@ -403,30 +362,26 @@
 		       "err(%d)\n", ino, err);
 }
 
-static void sun4v_irq_eoi(unsigned int virt_irq)
+static void sun4v_irq_eoi(struct irq_data *data)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-	struct irq_desc *desc = irq_desc + virt_irq;
+	unsigned int ino = irq_table[data->irq].dev_ino;
 	int err;
 
-	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		return;
-
 	err = sun4v_intr_setstate(ino, HV_INTR_STATE_IDLE);
 	if (err != HV_EOK)
 		printk(KERN_ERR "sun4v_intr_setstate(%x): "
 		       "err(%d)\n", ino, err);
 }
 
-static void sun4v_virq_enable(unsigned int virt_irq)
+static void sun4v_virq_enable(struct irq_data *data)
 {
 	unsigned long cpuid, dev_handle, dev_ino;
 	int err;
 
-	cpuid = irq_choose_cpu(virt_irq, irq_desc[virt_irq].affinity);
+	cpuid = irq_choose_cpu(data->irq, data->affinity);
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
 	if (err != HV_EOK)
@@ -447,16 +402,16 @@
 		       dev_handle, dev_ino, err);
 }
 
-static int sun4v_virt_set_affinity(unsigned int virt_irq,
-				    const struct cpumask *mask)
+static int sun4v_virt_set_affinity(struct irq_data *data,
+				    const struct cpumask *mask, bool force)
 {
 	unsigned long cpuid, dev_handle, dev_ino;
 	int err;
 
-	cpuid = irq_choose_cpu(virt_irq, mask);
+	cpuid = irq_choose_cpu(data->irq, mask);
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_target(dev_handle, dev_ino, cpuid);
 	if (err != HV_EOK)
@@ -467,13 +422,13 @@
 	return 0;
 }
 
-static void sun4v_virq_disable(unsigned int virt_irq)
+static void sun4v_virq_disable(struct irq_data *data)
 {
 	unsigned long dev_handle, dev_ino;
 	int err;
 
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_valid(dev_handle, dev_ino,
 				    HV_INTR_DISABLED);
@@ -483,17 +438,13 @@
 		       dev_handle, dev_ino, err);
 }
 
-static void sun4v_virq_eoi(unsigned int virt_irq)
+static void sun4v_virq_eoi(struct irq_data *data)
 {
-	struct irq_desc *desc = irq_desc + virt_irq;
 	unsigned long dev_handle, dev_ino;
 	int err;
 
-	if (unlikely(desc->status & (IRQ_DISABLED|IRQ_INPROGRESS)))
-		return;
-
-	dev_handle = virt_irq_table[virt_irq].dev_handle;
-	dev_ino = virt_irq_table[virt_irq].dev_ino;
+	dev_handle = irq_table[data->irq].dev_handle;
+	dev_ino = irq_table[data->irq].dev_ino;
 
 	err = sun4v_vintr_set_state(dev_handle, dev_ino,
 				    HV_INTR_STATE_IDLE);
@@ -504,132 +455,128 @@
 }
 
 static struct irq_chip sun4u_irq = {
-	.name		= "sun4u",
-	.enable		= sun4u_irq_enable,
-	.disable	= sun4u_irq_disable,
-	.eoi		= sun4u_irq_eoi,
-	.set_affinity	= sun4u_set_affinity,
+	.name			= "sun4u",
+	.irq_enable		= sun4u_irq_enable,
+	.irq_disable		= sun4u_irq_disable,
+	.irq_eoi		= sun4u_irq_eoi,
+	.irq_set_affinity	= sun4u_set_affinity,
+	.flags			= IRQCHIP_EOI_IF_HANDLED,
 };
 
 static struct irq_chip sun4v_irq = {
-	.name		= "sun4v",
-	.enable		= sun4v_irq_enable,
-	.disable	= sun4v_irq_disable,
-	.eoi		= sun4v_irq_eoi,
-	.set_affinity	= sun4v_set_affinity,
+	.name			= "sun4v",
+	.irq_enable		= sun4v_irq_enable,
+	.irq_disable		= sun4v_irq_disable,
+	.irq_eoi		= sun4v_irq_eoi,
+	.irq_set_affinity	= sun4v_set_affinity,
+	.flags			= IRQCHIP_EOI_IF_HANDLED,
 };
 
 static struct irq_chip sun4v_virq = {
-	.name		= "vsun4v",
-	.enable		= sun4v_virq_enable,
-	.disable	= sun4v_virq_disable,
-	.eoi		= sun4v_virq_eoi,
-	.set_affinity	= sun4v_virt_set_affinity,
+	.name			= "vsun4v",
+	.irq_enable		= sun4v_virq_enable,
+	.irq_disable		= sun4v_virq_disable,
+	.irq_eoi		= sun4v_virq_eoi,
+	.irq_set_affinity	= sun4v_virt_set_affinity,
+	.flags			= IRQCHIP_EOI_IF_HANDLED,
 };
 
-static void pre_flow_handler(unsigned int virt_irq,
-				      struct irq_desc *desc)
+static void pre_flow_handler(struct irq_data *d)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
-
-	data->pre_handler(ino, data->arg1, data->arg2);
+	struct irq_handler_data *handler_data = irq_data_get_irq_handler_data(d);
+	unsigned int ino = irq_table[d->irq].dev_ino;
 
-	handle_fasteoi_irq(virt_irq, desc);
+	handler_data->pre_handler(ino, handler_data->arg1, handler_data->arg2);
 }
 
-void irq_install_pre_handler(int virt_irq,
+void irq_install_pre_handler(int irq,
 			     void (*func)(unsigned int, void *, void *),
 			     void *arg1, void *arg2)
 {
-	struct irq_handler_data *data = get_irq_chip_data(virt_irq);
-	struct irq_desc *desc = irq_desc + virt_irq;
+	struct irq_handler_data *handler_data = irq_get_handler_data(irq);
 
-	data->pre_handler = func;
-	data->arg1 = arg1;
-	data->arg2 = arg2;
+	handler_data->pre_handler = func;
+	handler_data->arg1 = arg1;
+	handler_data->arg2 = arg2;
 
-	desc->handle_irq = pre_flow_handler;
+	__irq_set_preflow_handler(irq, pre_flow_handler);
 }
 
 unsigned int build_irq(int inofixup, unsigned long iclr, unsigned long imap)
 {
 	struct ino_bucket *bucket;
-	struct irq_handler_data *data;
-	unsigned int virt_irq;
+	struct irq_handler_data *handler_data;
+	unsigned int irq;
 	int ino;
 
 	BUG_ON(tlb_type == hypervisor);
 
 	ino = (upa_readq(imap) & (IMAP_IGN | IMAP_INO)) + inofixup;
 	bucket = &ivector_table[ino];
-	virt_irq = bucket_get_virt_irq(__pa(bucket));
-	if (!virt_irq) {
-		virt_irq = virt_irq_alloc(0, ino);
-		bucket_set_virt_irq(__pa(bucket), virt_irq);
-		set_irq_chip_and_handler_name(virt_irq,
-					      &sun4u_irq,
-					      handle_fasteoi_irq,
-					      "IVEC");
+	irq = bucket_get_irq(__pa(bucket));
+	if (!irq) {
+		irq = irq_alloc(0, ino);
+		bucket_set_irq(__pa(bucket), irq);
+		irq_set_chip_and_handler_name(irq, &sun4u_irq,
+					      handle_fasteoi_irq, "IVEC");
 	}
 
-	data = get_irq_chip_data(virt_irq);
-	if (unlikely(data))
+	handler_data = irq_get_handler_data(irq);
+	if (unlikely(handler_data))
 		goto out;
 
-	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
-	if (unlikely(!data)) {
+	handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!handler_data)) {
 		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
-	set_irq_chip_data(virt_irq, data);
+	irq_set_handler_data(irq, handler_data);
 
-	data->imap  = imap;
-	data->iclr  = iclr;
+	handler_data->imap  = imap;
+	handler_data->iclr  = iclr;
 
 out:
-	return virt_irq;
+	return irq;
 }
 
 static unsigned int sun4v_build_common(unsigned long sysino,
 				       struct irq_chip *chip)
 {
 	struct ino_bucket *bucket;
-	struct irq_handler_data *data;
-	unsigned int virt_irq;
+	struct irq_handler_data *handler_data;
+	unsigned int irq;
 
 	BUG_ON(tlb_type != hypervisor);
 
 	bucket = &ivector_table[sysino];
-	virt_irq = bucket_get_virt_irq(__pa(bucket));
-	if (!virt_irq) {
-		virt_irq = virt_irq_alloc(0, sysino);
-		bucket_set_virt_irq(__pa(bucket), virt_irq);
-		set_irq_chip_and_handler_name(virt_irq, chip,
-					      handle_fasteoi_irq,
+	irq = bucket_get_irq(__pa(bucket));
+	if (!irq) {
+		irq = irq_alloc(0, sysino);
+		bucket_set_irq(__pa(bucket), irq);
+		irq_set_chip_and_handler_name(irq, chip, handle_fasteoi_irq,
 					      "IVEC");
 	}
 
-	data = get_irq_chip_data(virt_irq);
-	if (unlikely(data))
+	handler_data = irq_get_handler_data(irq);
+	if (unlikely(handler_data))
 		goto out;
 
-	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
-	if (unlikely(!data)) {
+	handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!handler_data)) {
 		prom_printf("IRQ: kzalloc(irq_handler_data) failed.\n");
 		prom_halt();
 	}
-	set_irq_chip_data(virt_irq, data);
+	irq_set_handler_data(irq, handler_data);
 
 	/* Catch accidental accesses to these things.  IMAP/ICLR handling
 	 * is done by hypervisor calls on sun4v platforms, not by direct
 	 * register accesses.
 	 */
-	data->imap = ~0UL;
-	data->iclr = ~0UL;
+	handler_data->imap = ~0UL;
+	handler_data->iclr = ~0UL;
 
 out:
-	return virt_irq;
+	return irq;
 }
 
 unsigned int sun4v_build_irq(u32 devhandle, unsigned int devino)
@@ -641,11 +588,10 @@
 
 unsigned int sun4v_build_virq(u32 devhandle, unsigned int devino)
 {
-	struct irq_handler_data *data;
+	struct irq_handler_data *handler_data;
 	unsigned long hv_err, cookie;
 	struct ino_bucket *bucket;
-	struct irq_desc *desc;
-	unsigned int virt_irq;
+	unsigned int irq;
 
 	bucket = kzalloc(sizeof(struct ino_bucket), GFP_ATOMIC);
 	if (unlikely(!bucket))
@@ -662,32 +608,29 @@
 			     ((unsigned long) bucket +
 			      sizeof(struct ino_bucket)));
 
-	virt_irq = virt_irq_alloc(devhandle, devino);
-	bucket_set_virt_irq(__pa(bucket), virt_irq);
+	irq = irq_alloc(devhandle, devino);
+	bucket_set_irq(__pa(bucket), irq);
 
-	set_irq_chip_and_handler_name(virt_irq, &sun4v_virq,
-				      handle_fasteoi_irq,
+	irq_set_chip_and_handler_name(irq, &sun4v_virq, handle_fasteoi_irq,
 				      "IVEC");
 
-	data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
-	if (unlikely(!data))
+	handler_data = kzalloc(sizeof(struct irq_handler_data), GFP_ATOMIC);
+	if (unlikely(!handler_data))
 		return 0;
 
 	/* In order to make the LDC channel startup sequence easier,
 	 * especially wrt. locking, we do not let request_irq() enable
 	 * the interrupt.
 	 */
-	desc = irq_desc + virt_irq;
-	desc->status |= IRQ_NOAUTOEN;
-
-	set_irq_chip_data(virt_irq, data);
+	irq_set_status_flags(irq, IRQ_NOAUTOEN);
+	irq_set_handler_data(irq, handler_data);
 
 	/* Catch accidental accesses to these things.  IMAP/ICLR handling
 	 * is done by hypervisor calls on sun4v platforms, not by direct
 	 * register accesses.
 	 */
-	data->imap = ~0UL;
-	data->iclr = ~0UL;
+	handler_data->imap = ~0UL;
+	handler_data->iclr = ~0UL;
 
 	cookie = ~__pa(bucket);
 	hv_err = sun4v_vintr_set_cookie(devhandle, devino, cookie);
@@ -697,30 +640,30 @@
 		prom_halt();
 	}
 
-	return virt_irq;
+	return irq;
 }
 
-void ack_bad_irq(unsigned int virt_irq)
+void ack_bad_irq(unsigned int irq)
 {
-	unsigned int ino = virt_irq_table[virt_irq].dev_ino;
+	unsigned int ino = irq_table[irq].dev_ino;
 
 	if (!ino)
 		ino = 0xdeadbeef;
 
-	printk(KERN_CRIT "Unexpected IRQ from ino[%x] virt_irq[%u]\n",
-	       ino, virt_irq);
+	printk(KERN_CRIT "Unexpected IRQ from ino[%x] irq[%u]\n",
+	       ino, irq);
 }
 
 void *hardirq_stack[NR_CPUS];
 void *softirq_stack[NR_CPUS];
 
-void __irq_entry handler_irq(int irq, struct pt_regs *regs)
+void __irq_entry handler_irq(int pil, struct pt_regs *regs)
 {
 	unsigned long pstate, bucket_pa;
 	struct pt_regs *old_regs;
 	void *orig_sp;
 
-	clear_softint(1 << irq);
+	clear_softint(1 << pil);
 
 	old_regs = set_irq_regs(regs);
 	irq_enter();
@@ -739,18 +682,14 @@
 	orig_sp = set_hardirq_stack();
 
 	while (bucket_pa) {
-		struct irq_desc *desc;
 		unsigned long next_pa;
-		unsigned int virt_irq;
+		unsigned int irq;
 
 		next_pa = bucket_get_chain_pa(bucket_pa);
-		virt_irq = bucket_get_virt_irq(bucket_pa);
+		irq = bucket_get_irq(bucket_pa);
 		bucket_clear_chain_pa(bucket_pa);
 
-		desc = irq_desc + virt_irq;
-
-		if (!(desc->status & IRQ_DISABLED))
-			desc->handle_irq(virt_irq, desc);
+		generic_handle_irq(irq);
 
 		bucket_pa = next_pa;
 	}
@@ -793,16 +732,18 @@
 	unsigned int irq;
 
 	for (irq = 0; irq < NR_IRQS; irq++) {
+		struct irq_desc *desc = irq_to_desc(irq);
+		struct irq_data *data = irq_desc_get_irq_data(desc);
 		unsigned long flags;
 
-		raw_spin_lock_irqsave(&irq_desc[irq].lock, flags);
-		if (irq_desc[irq].action &&
-		    !(irq_desc[irq].status & IRQ_PER_CPU)) {
-			if (irq_desc[irq].chip->set_affinity)
-				irq_desc[irq].chip->set_affinity(irq,
-					irq_desc[irq].affinity);
+		raw_spin_lock_irqsave(&desc->lock, flags);
+		if (desc->action && !irqd_is_per_cpu(data)) {
+			if (data->chip->irq_set_affinity)
+				data->chip->irq_set_affinity(data,
+							     data->affinity,
+							     false);
 		}
-		raw_spin_unlock_irqrestore(&irq_desc[irq].lock, flags);
+		raw_spin_unlock_irqrestore(&desc->lock, flags);
 	}
 
 	tick_ops->disable_irq();
@@ -1040,5 +981,5 @@
 			     : "i" (PSTATE_IE)
 			     : "g1");
 
-	irq_desc[0].action = &timer_irq_action;
+	irq_to_desc(0)->action = &timer_irq_action;
 }
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/irq.h linux-libre-2.6.39-gnu/arch/sparc/kernel/irq.h
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,41 @@
+#include <linux/platform_device.h>
+
 #include <asm/btfixup.h>
 
+/* sun4m specific type definitions */
+
+/* This maps direct to CPU specific interrupt registers */
+struct sun4m_irq_percpu {
+	u32	pending;
+	u32	clear;
+	u32	set;
+};
+
+/* This maps direct to global interrupt registers */
+struct sun4m_irq_global {
+	u32	pending;
+	u32	mask;
+	u32	mask_clear;
+	u32	mask_set;
+	u32	interrupt_target;
+};
+
+extern struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
+extern struct sun4m_irq_global __iomem *sun4m_irq_global;
+
+/*
+ * Platform specific irq configuration
+ * The individual platforms assign their platform
+ * specifics in their init functions.
+ */
+struct sparc_irq_config {
+	void (*init_timers)(irq_handler_t);
+	unsigned int (*build_device_irq)(struct platform_device *op,
+	                                 unsigned int real_irq);
+};
+extern struct sparc_irq_config sparc_irq_config;
+
+
 /* Dave Redman (djhr@tadpole.co.uk)
  * changed these to function pointers.. it saves cycles and will allow
  * the irq dependencies to be split into different files at a later date
@@ -45,12 +81,6 @@
 	BTFIXUP_CALL(load_profile_irq)(cpu, limit);
 }
 
-extern void (*sparc_init_timers)(irq_handler_t lvl10_irq);
-
-extern void claim_ticker14(irq_handler_t irq_handler,
-			   int irq,
-			   unsigned int timeout);
-
 #ifdef CONFIG_SMP
 BTFIXUPDEF_CALL(void, set_cpu_int, int, int)
 BTFIXUPDEF_CALL(void, clear_cpu_int, int, int)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/kernel.h linux-libre-2.6.39-gnu/arch/sparc/kernel/kernel.h
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/kernel.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/kernel.h	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,8 @@
 
 #include <linux/interrupt.h>
 
+#include <asm/traps.h>
+
 /* cpu.c */
 extern const char *sparc_cpu_type;
 extern const char *sparc_pmu_type;
@@ -26,6 +28,53 @@
 extern spinlock_t irq_action_lock;
 
 extern void unexpected_irq(int irq, void *dev_id, struct pt_regs * regs);
+extern void init_IRQ(void);
+
+/* sun4c_irq.c */
+extern void sun4c_init_IRQ(void);
+
+/* sun4m_irq.c */
+extern unsigned int lvl14_resolution;
+
+extern void sun4m_init_IRQ(void);
+extern void sun4m_clear_profile_irq(int cpu);
+
+/* sun4d_irq.c */
+extern spinlock_t sun4d_imsk_lock;
+
+extern void sun4d_init_IRQ(void);
+extern int sun4d_request_irq(unsigned int irq,
+                             irq_handler_t handler,
+                             unsigned long irqflags,
+                             const char *devname, void *dev_id);
+extern int show_sun4d_interrupts(struct seq_file *, void *);
+extern void sun4d_distribute_irqs(void);
+extern void sun4d_free_irq(unsigned int irq, void *dev_id);
+
+/* head_32.S */
+extern unsigned int t_nmi[];
+extern unsigned int linux_trap_ipi15_sun4d[];
+extern unsigned int linux_trap_ipi15_sun4m[];
+
+extern struct tt_entry trapbase_cpu1;
+extern struct tt_entry trapbase_cpu2;
+extern struct tt_entry trapbase_cpu3;
+
+extern char cputypval[];
+
+/* entry.S */
+extern unsigned long lvl14_save[4];
+extern unsigned int real_irq_entry[];
+extern unsigned int smp4d_ticker[];
+extern unsigned int patchme_maybe_smp_msg[];
+
+extern void floppy_hardint(void);
+
+/* trampoline_32.S */
+extern int __smp4m_processor_id(void);
+extern int __smp4d_processor_id(void);
+extern unsigned long sun4m_cpu_startup;
+extern unsigned long sun4d_cpu_startup;
 
 #else /* CONFIG_SPARC32 */
 #endif /* CONFIG_SPARC32 */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/ldc.c linux-libre-2.6.39-gnu/arch/sparc/kernel/ldc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/ldc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/ldc.c	2011-05-19 00:06:34.000000000 -0400
@@ -790,16 +790,20 @@
 static irqreturn_t ldc_rx(int irq, void *dev_id)
 {
 	struct ldc_channel *lp = dev_id;
-	unsigned long orig_state, hv_err, flags;
+	unsigned long orig_state, flags;
 	unsigned int event_mask;
 
 	spin_lock_irqsave(&lp->lock, flags);
 
 	orig_state = lp->chan_state;
-	hv_err = sun4v_ldc_rx_get_state(lp->id,
-					&lp->rx_head,
-					&lp->rx_tail,
-					&lp->chan_state);
+
+	/* We should probably check for hypervisor errors here and
+	 * reset the LDC channel if we get one.
+	 */
+	sun4v_ldc_rx_get_state(lp->id,
+			       &lp->rx_head,
+			       &lp->rx_tail,
+			       &lp->chan_state);
 
 	ldcdbg(RX, "RX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
 	       orig_state, lp->chan_state, lp->rx_head, lp->rx_tail);
@@ -904,16 +908,20 @@
 static irqreturn_t ldc_tx(int irq, void *dev_id)
 {
 	struct ldc_channel *lp = dev_id;
-	unsigned long flags, hv_err, orig_state;
+	unsigned long flags, orig_state;
 	unsigned int event_mask = 0;
 
 	spin_lock_irqsave(&lp->lock, flags);
 
 	orig_state = lp->chan_state;
-	hv_err = sun4v_ldc_tx_get_state(lp->id,
-					&lp->tx_head,
-					&lp->tx_tail,
-					&lp->chan_state);
+
+	/* We should probably check for hypervisor errors here and
+	 * reset the LDC channel if we get one.
+	 */
+	sun4v_ldc_tx_get_state(lp->id,
+			       &lp->tx_head,
+			       &lp->tx_tail,
+			       &lp->chan_state);
 
 	ldcdbg(TX, " TX state[0x%02lx:0x%02lx] head[0x%04lx] tail[0x%04lx]\n",
 	       orig_state, lp->chan_state, lp->tx_head, lp->tx_tail);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/leon_kernel.c linux-libre-2.6.39-gnu/arch/sparc/kernel/leon_kernel.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/leon_kernel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/leon_kernel.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 int leondebug_irq_disable;
 int leon_debug_irqout;
 static int dummy_master_l10_counter;
+unsigned long amba_system_id;
 
 unsigned long leon3_gptimer_irq; /* interrupt controller irq number */
 unsigned long leon3_gptimer_idx; /* Timer Index (0..6) within Timer Core */
@@ -117,10 +118,16 @@
 	master_l10_counter = (unsigned int *)&dummy_master_l10_counter;
 	dummy_master_l10_counter = 0;
 
-	/*Find IRQMP IRQ Controller Registers base address otherwise bail out.*/
 	rootnp = of_find_node_by_path("/ambapp0");
 	if (!rootnp)
 		goto bad;
+
+	/* Find System ID: GRLIB build ID and optional CHIP ID */
+	pp = of_find_property(rootnp, "systemid", &len);
+	if (pp)
+		amba_system_id = *(unsigned long *)pp->value;
+
+	/* Find IRQMP IRQ Controller Registers base adr otherwise bail out */
 	np = of_find_node_by_name(rootnp, "GAISLER_IRQMP");
 	if (!np) {
 		np = of_find_node_by_name(rootnp, "01_00d");
@@ -340,7 +347,7 @@
 
 void __init leon_init_IRQ(void)
 {
-	sparc_init_timers = leon_init_timers;
+	sparc_irq_config.init_timers = leon_init_timers;
 
 	BTFIXUPSET_CALL(enable_irq, leon_enable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(disable_irq, leon_disable_irq, BTFIXUPCALL_NORM);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/leon_pmc.c linux-libre-2.6.39-gnu/arch/sparc/kernel/leon_pmc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/leon_pmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/leon_pmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,82 @@
+/* leon_pmc.c: LEON Power-down cpu_idle() handler
+ *
+ * Copyright (C) 2011 Daniel Hellstrom (daniel@gaisler.com) Aeroflex Gaisler AB
+ */
+
+#include <linux/init.h>
+#include <linux/pm.h>
+
+#include <asm/leon_amba.h>
+#include <asm/leon.h>
+
+/* List of Systems that need fixup instructions around power-down instruction */
+unsigned int pmc_leon_fixup_ids[] = {
+	AEROFLEX_UT699,
+	GAISLER_GR712RC,
+	LEON4_NEXTREME1,
+	0
+};
+
+int pmc_leon_need_fixup(void)
+{
+	unsigned int systemid = amba_system_id >> 16;
+	unsigned int *id;
+
+	id = &pmc_leon_fixup_ids[0];
+	while (*id != 0) {
+		if (*id == systemid)
+			return 1;
+		id++;
+	}
+
+	return 0;
+}
+
+/*
+ * CPU idle callback function for systems that need some extra handling
+ * See .../arch/sparc/kernel/process.c
+ */
+void pmc_leon_idle_fixup(void)
+{
+	/* Prepare an address to a non-cachable region. APB is always
+	 * none-cachable. One instruction is executed after the Sleep
+	 * instruction, we make sure to read the bus and throw away the
+	 * value by accessing a non-cachable area, also we make sure the
+	 * MMU does not get a TLB miss here by using the MMU BYPASS ASI.
+	 */
+	register unsigned int address = (unsigned int)leon3_irqctrl_regs;
+	__asm__ __volatile__ (
+		"mov	%%g0, %%asr19\n"
+		"lda	[%0] %1, %%g0\n"
+		:
+		: "r"(address), "i"(ASI_LEON_BYPASS));
+}
+
+/*
+ * CPU idle callback function
+ * See .../arch/sparc/kernel/process.c
+ */
+void pmc_leon_idle(void)
+{
+	/* For systems without power-down, this will be no-op */
+	__asm__ __volatile__ ("mov	%g0, %asr19\n\t");
+}
+
+/* Install LEON Power Down function */
+static int __init leon_pmc_install(void)
+{
+	/* Assign power management IDLE handler */
+	if (pmc_leon_need_fixup())
+		pm_idle = pmc_leon_idle_fixup;
+	else
+		pm_idle = pmc_leon_idle;
+
+	printk(KERN_INFO "leon: power management initialized\n");
+
+	return 0;
+}
+
+/* This driver is not critical to the boot process, don't care
+ * if initialized late.
+ */
+late_initcall(leon_pmc_install);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/leon_smp.c linux-libre-2.6.39-gnu/arch/sparc/kernel/leon_smp.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/leon_smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/leon_smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,6 +41,8 @@
 #include <asm/leon.h>
 #include <asm/leon_amba.h>
 
+#include "kernel.h"
+
 #ifdef CONFIG_SPARC_LEON
 
 #include "irq.h"
@@ -261,23 +263,23 @@
 
 	/* 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);
+		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);
+		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);
+		ClearPageReserved(virt_to_page(&trapbase_cpu3));
+		init_page_count(virt_to_page(&trapbase_cpu3));
+		free_page((unsigned long)&trapbase_cpu3);
 		totalram_pages++;
 		num_physpages++;
 	}
@@ -437,15 +439,6 @@
 
 }
 
-/*
- * CPU idle callback function
- * See .../arch/sparc/kernel/process.c
- */
-void pmc_leon_idle(void)
-{
-	__asm__ volatile ("mov %g0, %asr19");
-}
-
 void __init leon_init_smp(void)
 {
 	/* Patch ipi15 trap table */
@@ -456,13 +449,6 @@
 	BTFIXUPSET_CALL(smp_cross_call, leon_cross_call, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__hard_smp_processor_id, __leon_processor_id,
 			BTFIXUPCALL_NORM);
-
-#ifndef PMC_NO_IDLE
-	/* Assign power management IDLE handler */
-	pm_idle = pmc_leon_idle;
-	printk(KERN_INFO "leon: power management initialized\n");
-#endif
-
 }
 
 #endif /* CONFIG_SPARC_LEON */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/Makefile linux-libre-2.6.39-gnu/arch/sparc/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,6 @@
 obj-y                   += cpu.o
 obj-$(CONFIG_SPARC32)   += devices.o
 obj-$(CONFIG_SPARC32)   += tadpole.o
-obj-$(CONFIG_SPARC32)   += tick14.o
 obj-y                   += ptrace_$(BITS).o
 obj-y                   += unaligned_$(BITS).o
 obj-y                   += una_asm_$(BITS).o
@@ -54,6 +53,7 @@
 obj-$(CONFIG_SPARC64)   += prom_irqtrans.o
 
 obj-$(CONFIG_SPARC_LEON)+= leon_kernel.o
+obj-$(CONFIG_SPARC_LEON)+= leon_pmc.o
 
 obj-$(CONFIG_SPARC64)   += reboot.o
 obj-$(CONFIG_SPARC64)   += sysfs.o
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/mdesc.c linux-libre-2.6.39-gnu/arch/sparc/kernel/mdesc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/mdesc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/mdesc.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,7 +107,7 @@
 	return hp;
 }
 
-static void mdesc_memblock_free(struct mdesc_handle *hp)
+static void __init mdesc_memblock_free(struct mdesc_handle *hp)
 {
 	unsigned int alloc_size;
 	unsigned long start;
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/of_device_32.c linux-libre-2.6.39-gnu/arch/sparc/kernel/of_device_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/of_device_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/of_device_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 #include <asm/leon_amba.h>
 
 #include "of_device_common.h"
+#include "irq.h"
 
 /*
  * PCI bus specific translator
@@ -355,7 +356,8 @@
 	if (intr) {
 		op->archdata.num_irqs = len / sizeof(struct linux_prom_irqs);
 		for (i = 0; i < op->archdata.num_irqs; i++)
-			op->archdata.irqs[i] = intr[i].pri;
+			op->archdata.irqs[i] =
+			    sparc_irq_config.build_device_irq(op, intr[i].pri);
 	} else {
 		const unsigned int *irq =
 			of_get_property(dp, "interrupts", &len);
@@ -363,64 +365,13 @@
 		if (irq) {
 			op->archdata.num_irqs = len / sizeof(unsigned int);
 			for (i = 0; i < op->archdata.num_irqs; i++)
-				op->archdata.irqs[i] = irq[i];
+				op->archdata.irqs[i] =
+				    sparc_irq_config.build_device_irq(op, irq[i]);
 		} else {
 			op->archdata.num_irqs = 0;
 		}
 	}
-	if (sparc_cpu_model == sun4d) {
-		static int pil_to_sbus[] = {
-			0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
-		};
-		struct device_node *io_unit, *sbi = dp->parent;
-		const struct linux_prom_registers *regs;
-		int board, slot;
-
-		while (sbi) {
-			if (!strcmp(sbi->name, "sbi"))
-				break;
-
-			sbi = sbi->parent;
-		}
-		if (!sbi)
-			goto build_resources;
 
-		regs = of_get_property(dp, "reg", NULL);
-		if (!regs)
-			goto build_resources;
-
-		slot = regs->which_io;
-
-		/* If SBI's parent is not io-unit or the io-unit lacks
-		 * a "board#" property, something is very wrong.
-		 */
-		if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
-			printk("%s: Error, parent is not io-unit.\n",
-			       sbi->full_name);
-			goto build_resources;
-		}
-		io_unit = sbi->parent;
-		board = of_getintprop_default(io_unit, "board#", -1);
-		if (board == -1) {
-			printk("%s: Error, lacks board# property.\n",
-			       io_unit->full_name);
-			goto build_resources;
-		}
-
-		for (i = 0; i < op->archdata.num_irqs; i++) {
-			int this_irq = op->archdata.irqs[i];
-			int sbusl = pil_to_sbus[this_irq];
-
-			if (sbusl)
-				this_irq = (((board + 1) << 5) +
-					    (sbusl << 2) +
-					    slot);
-
-			op->archdata.irqs[i] = this_irq;
-		}
-	}
-
-build_resources:
 	build_device_resources(op, parent);
 
 	op->dev.parent = parent;
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/of_device_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/of_device_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/of_device_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/of_device_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -459,7 +459,7 @@
 		 *
 		 * Handle this by deciding that, if we didn't get a
 		 * match in the parent's 'interrupt-map', and the
-		 * parent is an IRQ translater, then use the parent as
+		 * parent is an IRQ translator, then use the parent as
 		 * our IRQ controller.
 		 */
 		if (pp->irq_trans)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/of_device_common.c linux-libre-2.6.39-gnu/arch/sparc/kernel/of_device_common.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/of_device_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/of_device_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,33 @@
 }
 EXPORT_SYMBOL(irq_of_parse_and_map);
 
+int of_address_to_resource(struct device_node *node, int index,
+			   struct resource *r)
+{
+	struct platform_device *op = of_find_device_by_node(node);
+
+	if (!op || index >= op->num_resources)
+		return -EINVAL;
+
+	memcpy(r, &op->archdata.resource[index], sizeof(*r));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(of_address_to_resource);
+
+void __iomem *of_iomap(struct device_node *node, int index)
+{
+	struct platform_device *op = of_find_device_by_node(node);
+	struct resource *r;
+
+	if (!op || index >= op->num_resources)
+		return NULL;
+
+	r = &op->archdata.resource[index];
+
+	return of_ioremap(r, 0, resource_size(r), (char *) r->name);
+}
+EXPORT_SYMBOL(of_iomap);
+
 /* Take the archdata values for IOMMU, STC, and HOSTDATA found in
  * BUS and propagate to all child platform_device objects.
  */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -675,6 +675,7 @@
 		 * humanoid.
 		 */
 		err = sysfs_create_file(&dev->dev.kobj, &dev_attr_obppath.attr);
+		(void) err;
 	}
 	list_for_each_entry(child_bus, &bus->children, node)
 		pci_bus_register_of_sysfs(child_bus);
@@ -1001,22 +1002,22 @@
 int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc)
 {
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
-	unsigned int virt_irq;
+	unsigned int irq;
 
 	if (!pbm->setup_msi_irq)
 		return -EINVAL;
 
-	return pbm->setup_msi_irq(&virt_irq, pdev, desc);
+	return pbm->setup_msi_irq(&irq, pdev, desc);
 }
 
-void arch_teardown_msi_irq(unsigned int virt_irq)
+void arch_teardown_msi_irq(unsigned int irq)
 {
-	struct msi_desc *entry = get_irq_msi(virt_irq);
+	struct msi_desc *entry = irq_get_msi_desc(irq);
 	struct pci_dev *pdev = entry->dev;
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
 
 	if (pbm->teardown_msi_irq)
-		pbm->teardown_msi_irq(virt_irq, pdev);
+		pbm->teardown_msi_irq(irq, pdev);
 }
 #endif /* !(CONFIG_PCI_MSI) */
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pcic.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pcic.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pcic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pcic.c	2011-05-19 00:06:34.000000000 -0400
@@ -700,10 +700,8 @@
 
 static irqreturn_t pcic_timer_handler (int irq, void *h)
 {
-	write_seqlock(&xtime_lock);	/* Dummy, to show that we remember */
 	pcic_clear_clock_irq();
-	do_timer(1);
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_common.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_common.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -295,14 +295,17 @@
 	unsigned int bus = bus_dev->number;
 	unsigned int device = PCI_SLOT(devfn);
 	unsigned int func = PCI_FUNC(devfn);
-	unsigned long ret;
 
 	if (config_out_of_range(pbm, bus, devfn, where)) {
 		/* Do nothing. */
 	} else {
-		ret = pci_sun4v_config_put(devhandle,
-				HV_PCI_DEVICE_BUILD(bus, device, func),
-				where, size, value);
+		/* We don't check for hypervisor errors here, but perhaps
+		 * we should and influence our return value depending upon
+		 * what kind of error is thrown.
+		 */
+		pci_sun4v_config_put(devhandle,
+				     HV_PCI_DEVICE_BUILD(bus, device, func),
+				     where, size, value);
 	}
 	return PCIBIOS_SUCCESSFUL;
 }
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_fire.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_fire.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_fire.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_fire.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,11 +214,9 @@
 
 static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi)
 {
-	unsigned long msiqid;
 	u64 val;
 
 	val = upa_readq(pbm->pbm_regs + MSI_MAP(msi));
-	msiqid = (val & MSI_MAP_EQNUM);
 
 	val &= ~MSI_MAP_VALID;
 
@@ -277,7 +275,7 @@
 {
 	unsigned long cregs = (unsigned long) pbm->pbm_regs;
 	unsigned long imap_reg, iclr_reg, int_ctrlr;
-	unsigned int virt_irq;
+	unsigned int irq;
 	int fixup;
 	u64 val;
 
@@ -293,14 +291,14 @@
 
 	fixup = ((pbm->portid << 6) | devino) - int_ctrlr;
 
-	virt_irq = build_irq(fixup, iclr_reg, imap_reg);
-	if (!virt_irq)
+	irq = build_irq(fixup, iclr_reg, imap_reg);
+	if (!irq)
 		return -ENOMEM;
 
 	upa_writeq(EVENT_QUEUE_CONTROL_SET_EN,
 		   pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid));
 
-	return virt_irq;
+	return irq;
 }
 
 static const struct sparc64_msiq_ops pci_fire_msiq_ops = {
@@ -455,8 +453,7 @@
 	return 0;
 }
 
-static int __devinit fire_probe(struct platform_device *op,
-				const struct of_device_id *match)
+static int __devinit fire_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct pci_pbm_info *pbm;
@@ -499,7 +496,7 @@
 	return err;
 }
 
-static struct of_device_id __initdata fire_match[] = {
+static const struct of_device_id fire_match[] = {
 	{
 		.name = "pci",
 		.compatible = "pciex108e,80f0",
@@ -507,7 +504,7 @@
 	{},
 };
 
-static struct of_platform_driver fire_driver = {
+static struct platform_driver fire_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -518,7 +515,7 @@
 
 static int __init fire_init(void)
 {
-	return of_register_platform_driver(&fire_driver);
+	return platform_driver_register(&fire_driver);
 }
 
 subsys_initcall(fire_init);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_impl.h linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_impl.h
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_impl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_impl.h	2011-05-19 00:06:34.000000000 -0400
@@ -131,9 +131,9 @@
 	void				*msi_queues;
 	unsigned long			*msi_bitmap;
 	unsigned int			*msi_irq_table;
-	int (*setup_msi_irq)(unsigned int *virt_irq_p, struct pci_dev *pdev,
+	int (*setup_msi_irq)(unsigned int *irq_p, struct pci_dev *pdev,
 			     struct msi_desc *entry);
-	void (*teardown_msi_irq)(unsigned int virt_irq, struct pci_dev *pdev);
+	void (*teardown_msi_irq)(unsigned int irq, struct pci_dev *pdev);
 	const struct sparc64_msiq_ops	*msi_ops;
 #endif /* !(CONFIG_PCI_MSI) */
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_msi.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_msi.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,13 +30,10 @@
 
 		err = ops->dequeue_msi(pbm, msiqid, &head, &msi);
 		if (likely(err > 0)) {
-			struct irq_desc *desc;
-			unsigned int virt_irq;
-
-			virt_irq = pbm->msi_irq_table[msi - pbm->msi_first];
-			desc = irq_desc + virt_irq;
+			unsigned int irq;
 
-			desc->handle_irq(virt_irq, desc);
+			irq = pbm->msi_irq_table[msi - pbm->msi_first];
+			generic_handle_irq(irq);
 		}
 
 		if (unlikely(err < 0))
@@ -121,7 +118,7 @@
 	/* XXX affinity XXX */
 };
 
-static int sparc64_setup_msi_irq(unsigned int *virt_irq_p,
+static int sparc64_setup_msi_irq(unsigned int *irq_p,
 				 struct pci_dev *pdev,
 				 struct msi_desc *entry)
 {
@@ -131,17 +128,17 @@
 	int msi, err;
 	u32 msiqid;
 
-	*virt_irq_p = virt_irq_alloc(0, 0);
+	*irq_p = irq_alloc(0, 0);
 	err = -ENOMEM;
-	if (!*virt_irq_p)
+	if (!*irq_p)
 		goto out_err;
 
-	set_irq_chip_and_handler_name(*virt_irq_p, &msi_irq,
-				      handle_simple_irq, "MSI");
+	irq_set_chip_and_handler_name(*irq_p, &msi_irq, handle_simple_irq,
+				      "MSI");
 
 	err = alloc_msi(pbm);
 	if (unlikely(err < 0))
-		goto out_virt_irq_free;
+		goto out_irq_free;
 
 	msi = err;
 
@@ -152,7 +149,7 @@
 	if (err)
 		goto out_msi_free;
 
-	pbm->msi_irq_table[msi - pbm->msi_first] = *virt_irq_p;
+	pbm->msi_irq_table[msi - pbm->msi_first] = *irq_p;
 
 	if (entry->msi_attrib.is_64) {
 		msg.address_hi = pbm->msi64_start >> 32;
@@ -163,24 +160,24 @@
 	}
 	msg.data = msi;
 
-	set_irq_msi(*virt_irq_p, entry);
-	write_msi_msg(*virt_irq_p, &msg);
+	irq_set_msi_desc(*irq_p, entry);
+	write_msi_msg(*irq_p, &msg);
 
 	return 0;
 
 out_msi_free:
 	free_msi(pbm, msi);
 
-out_virt_irq_free:
-	set_irq_chip(*virt_irq_p, NULL);
-	virt_irq_free(*virt_irq_p);
-	*virt_irq_p = 0;
+out_irq_free:
+	irq_set_chip(*irq_p, NULL);
+	irq_free(*irq_p);
+	*irq_p = 0;
 
 out_err:
 	return err;
 }
 
-static void sparc64_teardown_msi_irq(unsigned int virt_irq,
+static void sparc64_teardown_msi_irq(unsigned int irq,
 				     struct pci_dev *pdev)
 {
 	struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller;
@@ -189,12 +186,12 @@
 	int i, err;
 
 	for (i = 0; i < pbm->msi_num; i++) {
-		if (pbm->msi_irq_table[i] == virt_irq)
+		if (pbm->msi_irq_table[i] == irq)
 			break;
 	}
 	if (i >= pbm->msi_num) {
 		printk(KERN_ERR "%s: teardown: No MSI for irq %u\n",
-		       pbm->name, virt_irq);
+		       pbm->name, irq);
 		return;
 	}
 
@@ -205,14 +202,14 @@
 	if (err) {
 		printk(KERN_ERR "%s: teardown: ops->teardown() on MSI %u, "
 		       "irq %u, gives error %d\n",
-		       pbm->name, msi_num, virt_irq, err);
+		       pbm->name, msi_num, irq, err);
 		return;
 	}
 
 	free_msi(pbm, msi_num);
 
-	set_irq_chip(virt_irq, NULL);
-	virt_irq_free(virt_irq);
+	irq_set_chip(irq, NULL);
+	irq_free(irq);
 }
 
 static int msi_bitmap_alloc(struct pci_pbm_info *pbm)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_psycho.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_psycho.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_psycho.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_psycho.c	2011-05-19 00:06:34.000000000 -0400
@@ -503,8 +503,7 @@
 
 #define PSYCHO_CONFIGSPACE	0x001000000UL
 
-static int __devinit psycho_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit psycho_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *pr_regs;
 	struct device_node *dp = op->dev.of_node;
@@ -593,7 +592,7 @@
 	return err;
 }
 
-static struct of_device_id __initdata psycho_match[] = {
+static const struct of_device_id psycho_match[] = {
 	{
 		.name = "pci",
 		.compatible = "pci108e,8000",
@@ -601,7 +600,7 @@
 	{},
 };
 
-static struct of_platform_driver psycho_driver = {
+static struct platform_driver psycho_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -612,7 +611,7 @@
 
 static int __init psycho_init(void)
 {
-	return of_register_platform_driver(&psycho_driver);
+	return platform_driver_register(&psycho_driver);
 }
 
 subsys_initcall(psycho_init);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_sabre.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_sabre.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_sabre.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_sabre.c	2011-05-19 00:06:34.000000000 -0400
@@ -452,9 +452,10 @@
 	sabre_scan_bus(pbm, &op->dev);
 }
 
-static int __devinit sabre_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static const struct of_device_id sabre_match[];
+static int __devinit sabre_probe(struct platform_device *op)
 {
+	const struct of_device_id *match;
 	const struct linux_prom64_registers *pr_regs;
 	struct device_node *dp = op->dev.of_node;
 	struct pci_pbm_info *pbm;
@@ -464,7 +465,8 @@
 	const u32 *vdma;
 	u64 clear_irq;
 
-	hummingbird_p = (match->data != NULL);
+	match = of_match_device(sabre_match, &op->dev);
+	hummingbird_p = match && (match->data != NULL);
 	if (!hummingbird_p) {
 		struct device_node *cpu_dp;
 
@@ -582,7 +584,7 @@
 	return err;
 }
 
-static struct of_device_id __initdata sabre_match[] = {
+static const struct of_device_id sabre_match[] = {
 	{
 		.name = "pci",
 		.compatible = "pci108e,a001",
@@ -595,7 +597,7 @@
 	{},
 };
 
-static struct of_platform_driver sabre_driver = {
+static struct platform_driver sabre_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -606,7 +608,7 @@
 
 static int __init sabre_init(void)
 {
-	return of_register_platform_driver(&sabre_driver);
+	return platform_driver_register(&sabre_driver);
 }
 
 subsys_initcall(sabre_init);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_schizo.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_schizo.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_schizo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_schizo.c	2011-05-19 00:06:34.000000000 -0400
@@ -1313,7 +1313,7 @@
 	const struct linux_prom64_registers *regs;
 	struct device_node *dp = op->dev.of_node;
 	const char *chipset_name;
-	int is_pbm_a, err;
+	int err;
 
 	switch (chip_type) {
 	case PBM_CHIP_TYPE_TOMATILLO:
@@ -1343,8 +1343,6 @@
 	 */
 	regs = of_get_property(dp, "reg", NULL);
 
-	is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000);
-
 	pbm->next = pci_pbm_root;
 	pci_pbm_root = pbm;
 
@@ -1460,10 +1458,15 @@
 	return err;
 }
 
-static int __devinit schizo_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static const struct of_device_id schizo_match[];
+static int __devinit schizo_probe(struct platform_device *op)
 {
-	return __schizo_init(op, (unsigned long) match->data);
+	const struct of_device_id *match;
+
+	match = of_match_device(schizo_match, &op->dev);
+	if (!match)
+		return -EINVAL;
+	return __schizo_init(op, (unsigned long)match->data);
 }
 
 /* The ordering of this table is very important.  Some Tomatillo
@@ -1471,7 +1474,7 @@
  * and pci108e,8001.  So list the chips in reverse chronological
  * order.
  */
-static struct of_device_id __initdata schizo_match[] = {
+static const struct of_device_id schizo_match[] = {
 	{
 		.name = "pci",
 		.compatible = "pci108e,a801",
@@ -1490,7 +1493,7 @@
 	{},
 };
 
-static struct of_platform_driver schizo_driver = {
+static struct platform_driver schizo_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1501,7 +1504,7 @@
 
 static int __init schizo_init(void)
 {
-	return of_register_platform_driver(&schizo_driver);
+	return platform_driver_register(&schizo_driver);
 }
 
 subsys_initcall(schizo_init);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_sun4v.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_sun4v.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pci_sun4v.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pci_sun4v.c	2011-05-19 00:06:34.000000000 -0400
@@ -580,7 +580,7 @@
 {
 	static const u32 vdma_default[] = { 0x80000000, 0x80000000 };
 	struct iommu *iommu = pbm->iommu;
-	unsigned long num_tsb_entries, sz, tsbsize;
+	unsigned long num_tsb_entries, sz;
 	u32 dma_mask, dma_offset;
 	const u32 *vdma;
 
@@ -596,7 +596,6 @@
 
 	dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL);
 	num_tsb_entries = vdma[1] / IO_PAGE_SIZE;
-	tsbsize = num_tsb_entries * sizeof(iopte_t);
 
 	dma_offset = vdma[0];
 
@@ -844,9 +843,9 @@
 				    unsigned long msiqid,
 				    unsigned long devino)
 {
-	unsigned int virt_irq = sun4v_build_irq(pbm->devhandle, devino);
+	unsigned int irq = sun4v_build_irq(pbm->devhandle, devino);
 
-	if (!virt_irq)
+	if (!irq)
 		return -ENOMEM;
 
 	if (pci_sun4v_msiq_setstate(pbm->devhandle, msiqid, HV_MSIQSTATE_IDLE))
@@ -854,7 +853,7 @@
 	if (pci_sun4v_msiq_setvalid(pbm->devhandle, msiqid, HV_MSIQ_VALID))
 		return -EINVAL;
 
-	return virt_irq;
+	return irq;
 }
 
 static const struct sparc64_msiq_ops pci_sun4v_msiq_ops = {
@@ -918,8 +917,7 @@
 	return 0;
 }
 
-static int __devinit pci_sun4v_probe(struct platform_device *op,
-				     const struct of_device_id *match)
+static int __devinit pci_sun4v_probe(struct platform_device *op)
 {
 	const struct linux_prom64_registers *regs;
 	static int hvapi_negotiated = 0;
@@ -1000,7 +998,7 @@
 	return err;
 }
 
-static struct of_device_id __initdata pci_sun4v_match[] = {
+static const struct of_device_id pci_sun4v_match[] = {
 	{
 		.name = "pci",
 		.compatible = "SUNW,sun4v-pci",
@@ -1008,7 +1006,7 @@
 	{},
 };
 
-static struct of_platform_driver pci_sun4v_driver = {
+static struct platform_driver pci_sun4v_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1019,7 +1017,7 @@
 
 static int __init pci_sun4v_init(void)
 {
-	return of_register_platform_driver(&pci_sun4v_driver);
+	return platform_driver_register(&pci_sun4v_driver);
 }
 
 subsys_initcall(pci_sun4v_init);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pcr.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pcr.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pcr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pcr.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,7 +81,7 @@
 	unsigned long ret;
 
 	ret = sun4v_niagara2_setperf(HV_N2_PERF_SPARC_CTL, val);
-	if (val != HV_EOK)
+	if (ret != HV_EOK)
 		write_pcr(val);
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/perf_event.c linux-libre-2.6.39-gnu/arch/sparc/kernel/perf_event.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/perf_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/perf_event.c	2011-05-19 00:06:34.000000000 -0400
@@ -1027,7 +1027,7 @@
 
 	/*
 	 * If group events scheduling transaction was started,
-	 * skip the schedulability test here, it will be peformed
+	 * skip the schedulability test here, it will be performed
 	 * at commit time(->commit_txn) as a whole
 	 */
 	if (cpuc->group_flag & PERF_EVENT_TXN)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/pmc.c linux-libre-2.6.39-gnu/arch/sparc/kernel/pmc.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/pmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/pmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,8 +51,7 @@
 #endif
 }
 
-static int __devinit pmc_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit pmc_probe(struct platform_device *op)
 {
 	regs = of_ioremap(&op->resource[0], 0,
 			  resource_size(&op->resource[0]), PMC_OBPNAME);
@@ -70,7 +69,7 @@
 	return 0;
 }
 
-static struct of_device_id __initdata pmc_match[] = {
+static struct of_device_id pmc_match[] = {
 	{
 		.name = PMC_OBPNAME,
 	},
@@ -78,7 +77,7 @@
 };
 MODULE_DEVICE_TABLE(of, pmc_match);
 
-static struct of_platform_driver pmc_driver = {
+static struct platform_driver pmc_driver = {
 	.driver = {
 		.name = "pmc",
 		.owner = THIS_MODULE,
@@ -89,7 +88,7 @@
 
 static int __init pmc_init(void)
 {
-	return of_register_platform_driver(&pmc_driver);
+	return platform_driver_register(&pmc_driver);
 }
 
 /* This driver is not critical to the boot process
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/power.c linux-libre-2.6.39-gnu/arch/sparc/kernel/power.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/power.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/power.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 	return 1;
 }
 
-static int __devinit power_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit power_probe(struct platform_device *op)
 {
 	struct resource *res = &op->resource[0];
 	unsigned int irq = op->archdata.irqs[0];
@@ -52,14 +52,14 @@
 	return 0;
 }
 
-static struct of_device_id __initdata power_match[] = {
+static const struct of_device_id power_match[] = {
 	{
 		.name = "power",
 	},
 	{},
 };
 
-static struct of_platform_driver power_driver = {
+static struct platform_driver power_driver = {
 	.probe		= power_probe,
 	.driver = {
 		.name = "power",
@@ -70,7 +70,7 @@
 
 static int __init power_init(void)
 {
-	return of_register_platform_driver(&power_driver);
+	return platform_driver_register(&power_driver);
 }
 
 device_initcall(power_init);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/prom_irqtrans.c linux-libre-2.6.39-gnu/arch/sparc/kernel/prom_irqtrans.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/prom_irqtrans.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/prom_irqtrans.c	2011-05-19 00:06:34.000000000 -0400
@@ -227,7 +227,7 @@
 	unsigned long imap, iclr;
 	unsigned long imap_off, iclr_off;
 	int inofixup = 0;
-	int virt_irq;
+	int irq;
 
 	ino &= 0x3f;
 	if (ino < SABRE_ONBOARD_IRQ_BASE) {
@@ -247,7 +247,7 @@
 	if ((ino & 0x20) == 0)
 		inofixup = ino & 0x03;
 
-	virt_irq = build_irq(inofixup, iclr, imap);
+	irq = build_irq(inofixup, iclr, imap);
 
 	/* If the parent device is a PCI<->PCI bridge other than
 	 * APB, we have to install a pre-handler to ensure that
@@ -256,13 +256,13 @@
 	 */
 	regs = of_get_property(dp, "reg", NULL);
 	if (regs && sabre_device_needs_wsync(dp)) {
-		irq_install_pre_handler(virt_irq,
+		irq_install_pre_handler(irq,
 					sabre_wsync_handler,
 					(void *) (long) regs->phys_hi,
 					(void *) irq_data);
 	}
 
-	return virt_irq;
+	return irq;
 }
 
 static void __init sabre_irq_trans_init(struct device_node *dp)
@@ -382,7 +382,7 @@
 	unsigned long pbm_regs = irq_data->pbm_regs;
 	unsigned long imap, iclr;
 	int ign_fixup;
-	int virt_irq;
+	int irq;
 	int is_tomatillo;
 
 	ino &= 0x3f;
@@ -409,17 +409,17 @@
 			ign_fixup = (1 << 6);
 	}
 
-	virt_irq = build_irq(ign_fixup, iclr, imap);
+	irq = build_irq(ign_fixup, iclr, imap);
 
 	if (is_tomatillo) {
-		irq_install_pre_handler(virt_irq,
+		irq_install_pre_handler(irq,
 					tomatillo_wsync_handler,
 					((irq_data->chip_version <= 4) ?
 					 (void *) 1 : (void *) 0),
 					(void *) irq_data->sync_reg);
 	}
 
-	return virt_irq;
+	return irq;
 }
 
 static void __init __schizo_irq_trans_init(struct device_node *dp,
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/ptrace_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/ptrace_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/ptrace_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/ptrace_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -1086,6 +1086,7 @@
 
 asmlinkage void syscall_trace_leave(struct pt_regs *regs)
 {
+#ifdef CONFIG_AUDITSYSCALL
 	if (unlikely(current->audit_context)) {
 		unsigned long tstate = regs->tstate;
 		int result = AUDITSC_SUCCESS;
@@ -1095,7 +1096,7 @@
 
 		audit_syscall_exit(result, regs->u_regs[UREG_I0]);
 	}
-
+#endif
 	if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT)))
 		trace_sys_exit(regs, regs->u_regs[UREG_G1]);
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/setup_32.c linux-libre-2.6.39-gnu/arch/sparc/kernel/setup_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/setup_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/setup_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -184,7 +184,6 @@
  */
 
 extern void sun4c_probe_vac(void);
-extern char cputypval;
 
 extern unsigned short root_flags;
 extern unsigned short root_dev;
@@ -218,21 +217,21 @@
 
 	/* Set sparc_cpu_model */
 	sparc_cpu_model = sun_unknown;
-	if (!strcmp(&cputypval,"sun4 "))
+	if (!strcmp(&cputypval[0], "sun4 "))
 		sparc_cpu_model = sun4;
-	if (!strcmp(&cputypval,"sun4c"))
+	if (!strcmp(&cputypval[0], "sun4c"))
 		sparc_cpu_model = sun4c;
-	if (!strcmp(&cputypval,"sun4m"))
+	if (!strcmp(&cputypval[0], "sun4m"))
 		sparc_cpu_model = sun4m;
-	if (!strcmp(&cputypval,"sun4s"))
+	if (!strcmp(&cputypval[0], "sun4s"))
 		sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */
-	if (!strcmp(&cputypval,"sun4d"))
+	if (!strcmp(&cputypval[0], "sun4d"))
 		sparc_cpu_model = sun4d;
-	if (!strcmp(&cputypval,"sun4e"))
+	if (!strcmp(&cputypval[0], "sun4e"))
 		sparc_cpu_model = sun4e;
-	if (!strcmp(&cputypval,"sun4u"))
+	if (!strcmp(&cputypval[0], "sun4u"))
 		sparc_cpu_model = sun4u;
-	if (!strncmp(&cputypval, "leon" , 4))
+	if (!strncmp(&cputypval[0], "leon" , 4))
 		sparc_cpu_model = sparc_leon;
 
 	printk("ARCH: ");
@@ -335,7 +334,7 @@
 		   prom_rev,
 		   romvec->pv_printrev >> 16,
 		   romvec->pv_printrev & 0xffff,
-		   &cputypval,
+		   &cputypval[0],
 		   ncpus_probed,
 		   num_online_cpus()
 #ifndef CONFIG_SMP
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/smp_32.c linux-libre-2.6.39-gnu/arch/sparc/kernel/smp_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/smp_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/smp_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,6 +53,7 @@
 void __cpuinit smp_store_cpu_info(int id)
 {
 	int cpu_node;
+	int mid;
 
 	cpu_data(id).udelay_val = loops_per_jiffy;
 
@@ -60,10 +61,13 @@
 	cpu_data(id).clock_tick = prom_getintdefault(cpu_node,
 						     "clock-frequency", 0);
 	cpu_data(id).prom_node = cpu_node;
-	cpu_data(id).mid = cpu_get_hwmid(cpu_node);
+	mid = cpu_get_hwmid(cpu_node);
 
-	if (cpu_data(id).mid < 0)
-		panic("No MID found for CPU%d at node 0x%08d", id, cpu_node);
+	if (mid < 0) {
+		printk(KERN_NOTICE "No MID found for CPU%d at node 0x%08d", id, cpu_node);
+		mid = 0;
+	}
+	cpu_data(id).mid = mid;
 }
 
 void __init smp_cpus_done(unsigned int max_cpus)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/smp_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/smp_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/smp_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/smp_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -189,7 +189,7 @@
 void smp_synchronize_tick_client(void)
 {
 	long i, delta, adj, adjust_latency = 0, done = 0;
-	unsigned long flags, rt, master_time_stamp, bound;
+	unsigned long flags, rt, master_time_stamp;
 #if DEBUG_TICK_SYNC
 	struct {
 		long rt;	/* roundtrip time */
@@ -208,10 +208,8 @@
 	{
 		for (i = 0; i < NUM_ROUNDS; i++) {
 			delta = get_delta(&rt, &master_time_stamp);
-			if (delta == 0) {
+			if (delta == 0)
 				done = 1;	/* let's lock on to this... */
-				bound = rt;
-			}
 
 			if (!done) {
 				if (i > 0) {
@@ -933,13 +931,12 @@
 void flush_dcache_page_all(struct mm_struct *mm, struct page *page)
 {
 	void *pg_addr;
-	int this_cpu;
 	u64 data0;
 
 	if (tlb_type == hypervisor)
 		return;
 
-	this_cpu = get_cpu();
+	preempt_disable();
 
 #ifdef CONFIG_DEBUG_DCFLUSH
 	atomic_inc(&dcpage_flushes);
@@ -964,7 +961,7 @@
 	}
 	__local_flush_dcache_page(page);
 
-	put_cpu();
+	preempt_enable();
 }
 
 void __irq_entry smp_new_mmu_context_version_client(int irq, struct pt_regs *regs)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4c_irq.c linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4c_irq.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4c_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4c_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
-/*  sun4c_irq.c
- *  arch/sparc/kernel/sun4c_irq.c:
+/*
+ * sun4c irq support
  *
  *  djhr: Hacked out of irq.c into a CPU dependent version.
  *
@@ -9,31 +9,41 @@
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
-#include <linux/errno.h>
-#include <linux/linkage.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
 #include <linux/init.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-#include "irq.h"
 
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/vaddrs.h>
-#include <asm/timer.h>
-#include <asm/openprom.h>
 #include <asm/oplib.h>
-#include <asm/traps.h>
+#include <asm/timer.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/idprom.h>
-#include <asm/machines.h>
+
+#include "irq.h"
+
+/* Sun4c interrupts are typically laid out as follows:
+ *
+ *  1 - Software interrupt, SBUS level 1
+ *  2 - SBUS level 2
+ *  3 - ESP SCSI, SBUS level 3
+ *  4 - Software interrupt
+ *  5 - Lance ethernet, SBUS level 4
+ *  6 - Software interrupt
+ *  7 - Graphics card, SBUS level 5
+ *  8 - SBUS level 6
+ *  9 - SBUS level 7
+ * 10 - Counter timer
+ * 11 - Floppy
+ * 12 - Zilog uart
+ * 13 - CS4231 audio
+ * 14 - Profiling timer
+ * 15 - NMI
+ *
+ * The interrupt enable bits in the interrupt mask register are
+ * really only used to enable/disable the timer interrupts, and
+ * for signalling software interrupts.  There is also a master
+ * interrupt enable bit in this register.
+ *
+ * Interrupts are enabled by setting the SUN4C_INT_* bits, they
+ * are disabled by clearing those bits.
+ */
 
 /*
  * Bit field defines for the interrupt registers on various
@@ -49,26 +59,21 @@
 #define SUN4C_INT_E4      0x04     /* Enable level 4 IRQ. */
 #define SUN4C_INT_E1      0x02     /* Enable level 1 IRQ. */
 
-/* Pointer to the interrupt enable byte
- *
- * Dave Redman (djhr@tadpole.co.uk)
- * What you may not be aware of is that entry.S requires this variable.
- *
- *  --- linux_trap_nmi_sun4c --
- *
- * so don't go making it static, like I tried. sigh.
+/*
+ * Pointer to the interrupt enable byte
+ * Used by entry.S
  */
-unsigned char __iomem *interrupt_enable = NULL;
+unsigned char __iomem *interrupt_enable;
 
 static void sun4c_disable_irq(unsigned int irq_nr)
 {
 	unsigned long flags;
 	unsigned char current_mask, new_mask;
-    
+
 	local_irq_save(flags);
 	irq_nr &= (NR_IRQS - 1);
 	current_mask = sbus_readb(interrupt_enable);
-	switch(irq_nr) {
+	switch (irq_nr) {
 	case 1:
 		new_mask = ((current_mask) & (~(SUN4C_INT_E1)));
 		break;
@@ -93,11 +98,11 @@
 {
 	unsigned long flags;
 	unsigned char current_mask, new_mask;
-    
+
 	local_irq_save(flags);
 	irq_nr &= (NR_IRQS - 1);
 	current_mask = sbus_readb(interrupt_enable);
-	switch(irq_nr) {
+	switch (irq_nr) {
 	case 1:
 		new_mask = ((current_mask) | SUN4C_INT_E1);
 		break;
@@ -180,12 +185,14 @@
 		prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err);
 		prom_halt();
 	}
-    
+
 	sun4c_disable_irq(irq[1].pri);
 }
 
 #ifdef CONFIG_SMP
-static void sun4c_nop(void) {}
+static void sun4c_nop(void)
+{
+}
 #endif
 
 void __init sun4c_init_IRQ(void)
@@ -214,7 +221,9 @@
 	BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP);
-	sparc_init_timers = sun4c_init_timers;
+
+	sparc_irq_config.init_timers = sun4c_init_timers;
+
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
 	BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4d_irq.c linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4d_irq.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4d_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4d_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,50 +1,42 @@
 /*
- *  arch/sparc/kernel/sun4d_irq.c:
- *			SS1000/SC2000 interrupt handling.
+ * SS1000/SC2000 interrupt handling.
  *
  *  Copyright (C) 1997,1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *  Heavily based on arch/sparc/kernel/irq.c.
  */
 
-#include <linux/errno.h>
-#include <linux/linkage.h>
 #include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-#include <linux/random.h>
-#include <linux/init.h>
-#include <linux/smp.h>
-#include <linux/spinlock.h>
 #include <linux/seq_file.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
 
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/smp.h>
-#include <asm/vaddrs.h>
 #include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
 #include <asm/traps.h>
 #include <asm/irq.h>
 #include <asm/io.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
 #include <asm/sbi.h>
 #include <asm/cacheflush.h>
-#include <asm/irq_regs.h>
 
 #include "kernel.h"
 #include "irq.h"
 
-/* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */
-/* #define DISTRIBUTE_IRQS */
+/* Sun4d interrupts fall roughly into two categories.  SBUS and
+ * cpu local.  CPU local interrupts cover the timer interrupts
+ * and whatnot, and we encode those as normal PILs between
+ * 0 and 15.
+ *
+ * SBUS interrupts are encoded integers including the board number
+ * (plus one), the SBUS level, and the SBUS slot number.  Sun4D
+ * IRQ dispatch is done by:
+ *
+ * 1) Reading the BW local interrupt table in order to get the bus
+ *    interrupt mask.
+ *
+ *    This table is indexed by SBUS interrupt level which can be
+ *    derived from the PIL we got interrupted on.
+ *
+ * 2) For each bus showing interrupt pending from #1, read the
+ *    SBI interrupt state register.  This will indicate which slots
+ *    have interrupts pending for that SBUS interrupt level.
+ */
 
 struct sun4d_timer_regs {
 	u32	l10_timer_limit;
@@ -59,11 +51,9 @@
 #define TIMER_IRQ	10
 
 #define MAX_STATIC_ALLOC	4
-extern int static_irq_count;
 static unsigned char sbus_tid[32];
 
 static struct irqaction *irq_action[NR_IRQS];
-extern spinlock_t irq_action_lock;
 
 static struct sbus_action {
 	struct irqaction *action;
@@ -71,11 +61,33 @@
 } *sbus_actions;
 
 static int pil_to_sbus[] = {
-	0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
+	0,
+	0,
+	1,
+	2,
+	0,
+	3,
+	0,
+	4,
+	0,
+	5,
+	0,
+	6,
+	0,
+	7,
+	0,
+	0,
 };
 
 static int sbus_to_pil[] = {
-	0, 2, 3, 5, 7, 9, 11, 13,
+	0,
+	2,
+	3,
+	5,
+	7,
+	9,
+	11,
+	13,
 };
 
 static int nsbi;
@@ -86,7 +98,7 @@
 int show_sun4d_interrupts(struct seq_file *p, void *v)
 {
 	int i = *(loff_t *) v, j = 0, k = 0, sbusl;
-	struct irqaction * action;
+	struct irqaction *action;
 	unsigned long flags;
 #ifdef CONFIG_SMP
 	int x;
@@ -96,13 +108,14 @@
 	if (i < NR_IRQS) {
 		sbusl = pil_to_sbus[i];
 		if (!sbusl) {
-	 		action = *(i + irq_action);
-			if (!action) 
-		        	goto out_unlock;
+			action = *(i + irq_action);
+			if (!action)
+				goto out_unlock;
 		} else {
 			for (j = 0; j < nsbi; j++) {
 				for (k = 0; k < 4; k++)
-					if ((action = sbus_actions [(j << 5) + (sbusl << 2) + k].action))
+					action = sbus_actions[(j << 5) + (sbusl << 2) + k].action;
+					if (action)
 						goto found_it;
 			}
 			goto out_unlock;
@@ -125,15 +138,17 @@
 					(action->flags & IRQF_DISABLED) ? " +" : "",
 					action->name);
 			}
-			if (!sbusl) break;
+			if (!sbusl)
+				break;
 			k++;
-			if (k < 4)
-				action = sbus_actions [(j << 5) + (sbusl << 2) + k].action;
-			else {
+			if (k < 4) {
+				action = sbus_actions[(j << 5) + (sbusl << 2) + k].action;
+			} else {
 				j++;
-				if (j == nsbi) break;
+				if (j == nsbi)
+					break;
 				k = 0;
-				action = sbus_actions [(j << 5) + (sbusl << 2)].action;
+				action = sbus_actions[(j << 5) + (sbusl << 2)].action;
 			}
 		}
 		seq_putc(p, '\n');
@@ -147,7 +162,7 @@
 {
 	struct irqaction *action, **actionp;
 	struct irqaction *tmp = NULL;
-        unsigned long flags;
+	unsigned long flags;
 
 	spin_lock_irqsave(&irq_action_lock, flags);
 	if (irq < 15)
@@ -156,7 +171,7 @@
 		actionp = &(sbus_actions[irq - (1 << 5)].action);
 	action = *actionp;
 	if (!action) {
-		printk("Trying to free free IRQ%d\n",irq);
+		printk(KERN_ERR "Trying to free free IRQ%d\n", irq);
 		goto out_unlock;
 	}
 	if (dev_id) {
@@ -166,23 +181,25 @@
 			tmp = action;
 		}
 		if (!action) {
-			printk("Trying to free free shared IRQ%d\n",irq);
+			printk(KERN_ERR "Trying to free free shared IRQ%d\n",
+			       irq);
 			goto out_unlock;
 		}
 	} else if (action->flags & IRQF_SHARED) {
-		printk("Trying to free shared IRQ%d with NULL device ID\n", irq);
+		printk(KERN_ERR "Trying to free shared IRQ%d with NULL device ID\n",
+		       irq);
 		goto out_unlock;
 	}
-	if (action->flags & SA_STATIC_ALLOC)
-	{
-		/* This interrupt is marked as specially allocated
+	if (action->flags & SA_STATIC_ALLOC) {
+		/*
+		 * This interrupt is marked as specially allocated
 		 * so it is a bad idea to free it.
 		 */
-		printk("Attempt to free statically allocated IRQ%d (%s)\n",
+		printk(KERN_ERR "Attempt to free statically allocated IRQ%d (%s)\n",
 		       irq, action->name);
 		goto out_unlock;
 	}
-	
+
 	if (tmp)
 		tmp->next = action->next;
 	else
@@ -203,30 +220,28 @@
 	spin_unlock_irqrestore(&irq_action_lock, flags);
 }
 
-extern void unexpected_irq(int, void *, struct pt_regs *);
-
-void sun4d_handler_irq(int irq, struct pt_regs * regs)
+void sun4d_handler_irq(int pil, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
-	struct irqaction * action;
+	struct irqaction *action;
 	int cpu = smp_processor_id();
 	/* SBUS IRQ level (1 - 7) */
-	int sbusl = pil_to_sbus[irq];
-	
+	int sbusl = pil_to_sbus[pil];
+
 	/* FIXME: Is this necessary?? */
 	cc_get_ipen();
-	
-	cc_set_iclr(1 << irq);
-	
+
+	cc_set_iclr(1 << pil);
+
 	old_regs = set_irq_regs(regs);
 	irq_enter();
-	kstat_cpu(cpu).irqs[irq]++;
+	kstat_cpu(cpu).irqs[pil]++;
 	if (!sbusl) {
-		action = *(irq + irq_action);
+		action = *(pil + irq_action);
 		if (!action)
-			unexpected_irq(irq, NULL, regs);
+			unexpected_irq(pil, NULL, regs);
 		do {
-			action->handler(irq, action->dev_id);
+			action->handler(pil, action->dev_id);
 			action = action->next;
 		} while (action);
 	} else {
@@ -235,9 +250,9 @@
 		struct sbus_action *actionp;
 		unsigned mask, slot;
 		int sbil = (sbusl << 2);
-		
+
 		bw_clear_intr_mask(sbusl, bus_mask);
-		
+
 		/* Loop for each pending SBI */
 		for (sbino = 0; bus_mask; sbino++, bus_mask >>= 1)
 			if (bus_mask & 1) {
@@ -249,11 +264,11 @@
 					if (mask & slot) {
 						mask &= ~slot;
 						action = actionp->action;
-						
+
 						if (!action)
-							unexpected_irq(irq, NULL, regs);
+							unexpected_irq(pil, NULL, regs);
 						do {
-							action->handler(irq, action->dev_id);
+							action->handler(pil, action->dev_id);
 							action = action->next;
 						} while (action);
 						release_sbi(SBI2DEVID(sbino), slot);
@@ -266,13 +281,13 @@
 
 int sun4d_request_irq(unsigned int irq,
 		irq_handler_t handler,
-		unsigned long irqflags, const char * devname, void *dev_id)
+		unsigned long irqflags, const char *devname, void *dev_id)
 {
 	struct irqaction *action, *tmp = NULL, **actionp;
 	unsigned long flags;
 	int ret;
-	
-	if(irq > 14 && irq < (1 << 5)) {
+
+	if (irq > 14 && irq < (1 << 5)) {
 		ret = -EINVAL;
 		goto out;
 	}
@@ -289,16 +304,18 @@
 	else
 		actionp = irq + irq_action;
 	action = *actionp;
-	
+
 	if (action) {
 		if ((action->flags & IRQF_SHARED) && (irqflags & IRQF_SHARED)) {
-			for (tmp = action; tmp->next; tmp = tmp->next);
+			for (tmp = action; tmp->next; tmp = tmp->next)
+				/* find last entry - tmp used below */;
 		} else {
 			ret = -EBUSY;
 			goto out_unlock;
 		}
 		if ((action->flags & IRQF_DISABLED) ^ (irqflags & IRQF_DISABLED)) {
-			printk("Attempt to mix fast and slow interrupts on IRQ%d denied\n", irq);
+			printk(KERN_ERR "Attempt to mix fast and slow interrupts on IRQ%d denied\n",
+			       irq);
 			ret = -EBUSY;
 			goto out_unlock;
 		}
@@ -312,14 +329,14 @@
 		if (static_irq_count < MAX_STATIC_ALLOC)
 			action = &static_irqaction[static_irq_count++];
 		else
-			printk("Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n", irq, devname);
+			printk(KERN_ERR "Request for IRQ%d (%s) SA_STATIC_ALLOC failed using kmalloc\n",
+			       irq, devname);
 	}
-	
+
 	if (action == NULL)
-		action = kmalloc(sizeof(struct irqaction),
-						     GFP_ATOMIC);
-	
-	if (!action) { 
+		action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
+
+	if (!action) {
 		ret = -ENOMEM;
 		goto out_unlock;
 	}
@@ -334,7 +351,7 @@
 		tmp->next = action;
 	else
 		*actionp = action;
-		
+
 	__enable_irq(irq);
 
 	ret = 0;
@@ -348,7 +365,7 @@
 {
 	int tid = sbus_tid[(irq >> 5) - 1];
 	unsigned long flags;
-	
+
 	if (irq < NR_IRQS)
 		return;
 
@@ -361,7 +378,7 @@
 {
 	int tid = sbus_tid[(irq >> 5) - 1];
 	unsigned long flags;
-	
+
 	if (irq < NR_IRQS)
 		return;
 
@@ -389,44 +406,6 @@
 {
 	struct device_node *dp;
 
-#ifdef DISTRIBUTE_IRQS
-	cpumask_t sbus_serving_map;
-
-	sbus_serving_map = cpu_present_map;
-	for_each_node_by_name(dp, "sbi") {
-		int board = of_getintprop_default(dp, "board#", 0);
-
-		if ((board * 2) == boot_cpu_id && cpu_isset(board * 2 + 1, cpu_present_map))
-			sbus_tid[board] = (board * 2 + 1);
-		else if (cpu_isset(board * 2, cpu_present_map))
-			sbus_tid[board] = (board * 2);
-		else if (cpu_isset(board * 2 + 1, cpu_present_map))
-			sbus_tid[board] = (board * 2 + 1);
-		else
-			sbus_tid[board] = 0xff;
-		if (sbus_tid[board] != 0xff)
-			cpu_clear(sbus_tid[board], sbus_serving_map);
-	}
-	for_each_node_by_name(dp, "sbi") {
-		int board = of_getintprop_default(dp, "board#", 0);
-		if (sbus_tid[board] == 0xff) {
-			int i = 31;
-				
-			if (cpus_empty(sbus_serving_map))
-				sbus_serving_map = cpu_present_map;
-			while (cpu_isset(i, sbus_serving_map))
-				i--;
-			sbus_tid[board] = i;
-			cpu_clear(i, sbus_serving_map);
-		}
-	}
-	for_each_node_by_name(dp, "sbi") {
-		int devid = of_getintprop_default(dp, "device-id", 0);
-		int board = of_getintprop_default(dp, "board#", 0);
-		printk("sbus%d IRQs directed to CPU%d\n", board, sbus_tid[board]);
-		set_sbi_tid(devid, sbus_tid[board] << 3);
-	}
-#else
 	int cpuid = cpu_logical_map(1);
 
 	if (cpuid == -1)
@@ -437,11 +416,10 @@
 		sbus_tid[board] = cpuid;
 		set_sbi_tid(devid, cpuid << 3);
 	}
-	printk("All sbus IRQs directed to CPU%d\n", cpuid);
-#endif
+	printk(KERN_ERR "All sbus IRQs directed to CPU%d\n", cpuid);
 }
 #endif
- 
+
 static void sun4d_clear_clock_irq(void)
 {
 	sbus_readl(&sun4d_timers->l10_timer_limit);
@@ -462,14 +440,61 @@
 	}
 }
 
+unsigned int sun4d_build_device_irq(struct platform_device *op,
+                                    unsigned int real_irq)
+{
+	static int pil_to_sbus[] = {
+		0, 0, 1, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 0,
+	};
+	struct device_node *dp = op->dev.of_node;
+	struct device_node *io_unit, *sbi = dp->parent;
+	const struct linux_prom_registers *regs;
+	int board, slot;
+	int sbusl;
+
+	while (sbi) {
+		if (!strcmp(sbi->name, "sbi"))
+			break;
+
+		sbi = sbi->parent;
+	}
+	if (!sbi)
+		goto err_out;
+
+	regs = of_get_property(dp, "reg", NULL);
+	if (!regs)
+		goto err_out;
+
+	slot = regs->which_io;
+
+	/*
+	 *  If SBI's parent is not io-unit or the io-unit lacks
+	 * a "board#" property, something is very wrong.
+	 */
+	if (!sbi->parent || strcmp(sbi->parent->name, "io-unit")) {
+		printk("%s: Error, parent is not io-unit.\n", sbi->full_name);
+		goto err_out;
+	}
+	io_unit = sbi->parent;
+	board = of_getintprop_default(io_unit, "board#", -1);
+	if (board == -1) {
+		printk("%s: Error, lacks board# property.\n", io_unit->full_name);
+		goto err_out;
+	}
+
+	sbusl = pil_to_sbus[real_irq];
+	if (sbusl)
+		return (((board + 1) << 5) + (sbusl << 2) + slot);
+
+err_out:
+	return real_irq;
+}
+
 static void __init sun4d_fixup_trap_table(void)
 {
 #ifdef CONFIG_SMP
 	unsigned long flags;
-	extern unsigned long lvl14_save[4];
 	struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
-	extern unsigned int real_irq_entry[], smp4d_ticker[];
-	extern unsigned int patchme_maybe_smp_msg[];
 
 	/* Adjust so that we jump directly to smp4d_ticker */
 	lvl14_save[2] += smp4d_ticker - real_irq_entry;
@@ -531,7 +556,8 @@
 			  (IRQF_DISABLED | SA_STATIC_ALLOC),
 			  "timer", NULL);
 	if (err) {
-		prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err);
+		prom_printf("sun4d_init_timers: request_irq() failed with %d\n",
+		             err);
 		prom_halt();
 	}
 	sun4d_load_profile_irqs();
@@ -550,7 +576,7 @@
 	nsbi = 0;
 	for_each_node_by_name(dp, "sbi")
 		nsbi++;
-	sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
+	sbus_actions = kzalloc(nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC);
 	if (!sbus_actions) {
 		prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n");
 		prom_halt();
@@ -566,7 +592,8 @@
 		/* Get rid of pending irqs from PROM */
 		mask = acquire_sbi(devid, 0xffffffff);
 		if (mask) {
-			printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board);
+			printk(KERN_ERR "Clearing pending IRQs %08x on SBI %d\n",
+			       mask, board);
 			release_sbi(devid, mask);
 		}
 	}
@@ -580,7 +607,10 @@
 	BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM);
-	sparc_init_timers = sun4d_init_timers;
+
+	sparc_irq_config.init_timers = sun4d_init_timers;
+	sparc_irq_config.build_device_irq = sun4d_build_device_irq;
+
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4d_set_cpu_int, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_cpu_int, sun4d_clear_ipi, BTFIXUPCALL_NOP);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4d_smp.c linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4d_smp.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4d_smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4d_smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* sun4d_smp.c: Sparc SS1000/SC2000 SMP support.
+/* Sparc SS1000/SC2000 SMP support.
  *
  * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz)
  *
@@ -6,59 +6,23 @@
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/head.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
 #include <linux/cpu.h>
 
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-#include <asm/irq_regs.h>
-
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/oplib.h>
 #include <asm/sbi.h>
+#include <asm/mmu.h>
 #include <asm/tlbflush.h>
 #include <asm/cacheflush.h>
-#include <asm/cpudata.h>
 
+#include "kernel.h"
 #include "irq.h"
-#define IRQ_CROSS_CALL		15
 
-extern ctxd_t *srmmu_ctx_table_phys;
+#define IRQ_CROSS_CALL		15
 
-static volatile int smp_processors_ready = 0;
+static volatile int smp_processors_ready;
 static int smp_highest_cpu;
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
-extern cpuinfo_sparc cpu_data[NR_CPUS];
-extern unsigned char boot_cpu_id;
-extern volatile int smp_process_available;
-
-extern cpumask_t smp_commenced_mask;
-
-extern int __smp4d_processor_id(void);
-
-/* #define SMP_DEBUG */
-
-#ifdef SMP_DEBUG
-#define SMP_PRINTK(x)	printk x
-#else
-#define SMP_PRINTK(x)
-#endif
 
 static inline unsigned long sun4d_swap(volatile unsigned long *ptr, unsigned long val)
 {
@@ -69,8 +33,6 @@
 }
 
 static void smp_setup_percpu_timer(void);
-extern void cpu_probe(void);
-extern void sun4d_distribute_irqs(void);
 
 static unsigned char cpu_leds[32];
 
@@ -86,9 +48,8 @@
 void __cpuinit smp4d_callin(void)
 {
 	int cpuid = hard_smp4d_processor_id();
-	extern spinlock_t sun4d_imsk_lock;
 	unsigned long flags;
-	
+
 	/* Show we are alive */
 	cpu_leds[cpuid] = 0x6;
 	show_leds(cpuid);
@@ -118,15 +79,15 @@
 	sun4d_swap((unsigned long *)&cpu_callin_map[cpuid], 1);
 	local_flush_cache_all();
 	local_flush_tlb_all();
-	
+
 	cpu_probe();
 
-	while((unsigned long)current_set[cpuid] < PAGE_OFFSET)
+	while ((unsigned long)current_set[cpuid] < PAGE_OFFSET)
 		barrier();
-		
-	while(current_set[cpuid]->cpu != cpuid)
+
+	while (current_set[cpuid]->cpu != cpuid)
 		barrier();
-		
+
 	/* Fix idle thread fields. */
 	__asm__ __volatile__("ld [%0], %%g6\n\t"
 			     : : "r" (&current_set[cpuid])
@@ -134,16 +95,16 @@
 
 	cpu_leds[cpuid] = 0x9;
 	show_leds(cpuid);
-	
+
 	/* Attach to the address space of init_task. */
 	atomic_inc(&init_mm.mm_count);
 	current->active_mm = &init_mm;
 
 	local_flush_cache_all();
 	local_flush_tlb_all();
-	
+
 	local_irq_enable();	/* We don't allow PIL 14 yet */
-	
+
 	while (!cpu_isset(cpuid, smp_commenced_mask))
 		barrier();
 
@@ -154,15 +115,9 @@
 
 }
 
-extern void init_IRQ(void);
-extern void cpu_panic(void);
-
 /*
  *	Cycle through the processors asking the PROM to start each one.
  */
- 
-extern struct linux_prom_registers smp_penguin_ctable;
-
 void __init smp4d_boot_cpus(void)
 {
 	if (boot_cpu_id)
@@ -173,43 +128,42 @@
 
 int __cpuinit smp4d_boot_one_cpu(int i)
 {
-			extern unsigned long sun4d_cpu_startup;
-			unsigned long *entry = &sun4d_cpu_startup;
-			struct task_struct *p;
-			int timeout;
-			int cpu_node;
+	unsigned long *entry = &sun4d_cpu_startup;
+	struct task_struct *p;
+	int timeout;
+	int cpu_node;
 
-			cpu_find_by_instance(i, &cpu_node,NULL);
-			/* Cook up an idler for this guy. */
-			p = fork_idle(i);
-			current_set[i] = task_thread_info(p);
+	cpu_find_by_instance(i, &cpu_node, NULL);
+	/* Cook up an idler for this guy. */
+	p = fork_idle(i);
+	current_set[i] = task_thread_info(p);
 
-			/*
-			 * Initialize the contexts table
-			 * Since the call to prom_startcpu() trashes the structure,
-			 * we need to re-initialize it for each cpu
-			 */
-			smp_penguin_ctable.which_io = 0;
-			smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
-			smp_penguin_ctable.reg_size = 0;
+	/*
+	 * Initialize the contexts table
+	 * Since the call to prom_startcpu() trashes the structure,
+	 * we need to re-initialize it for each cpu
+	 */
+	smp_penguin_ctable.which_io = 0;
+	smp_penguin_ctable.phys_addr = (unsigned int) srmmu_ctx_table_phys;
+	smp_penguin_ctable.reg_size = 0;
 
-			/* whirrr, whirrr, whirrrrrrrrr... */
-			SMP_PRINTK(("Starting CPU %d at %p\n", i, entry));
-			local_flush_cache_all();
-			prom_startcpu(cpu_node,
-				      &smp_penguin_ctable, 0, (char *)entry);
-				      
-			SMP_PRINTK(("prom_startcpu returned :)\n"));
+	/* whirrr, whirrr, whirrrrrrrrr... */
+	printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
+	local_flush_cache_all();
+	prom_startcpu(cpu_node,
+		      &smp_penguin_ctable, 0, (char *)entry);
+
+	printk(KERN_INFO "prom_startcpu returned :)\n");
+
+	/* wheee... it's going... */
+	for (timeout = 0; timeout < 10000; timeout++) {
+		if (cpu_callin_map[i])
+			break;
+		udelay(200);
+	}
 
-			/* wheee... it's going... */
-			for(timeout = 0; timeout < 10000; timeout++) {
-				if(cpu_callin_map[i])
-					break;
-				udelay(200);
-			}
-			
 	if (!(cpu_callin_map[i])) {
-		printk("Processor %d is stuck.\n", i);
+		printk(KERN_ERR "Processor %d is stuck.\n", i);
 		return -ENODEV;
 
 	}
@@ -255,14 +209,17 @@
 			     unsigned long arg2, unsigned long arg3,
 			     unsigned long arg4)
 {
-	if(smp_processors_ready) {
+	if (smp_processors_ready) {
 		register int high = smp_highest_cpu;
 		unsigned long flags;
 
 		spin_lock_irqsave(&cross_call_lock, flags);
 
 		{
-			/* If you make changes here, make sure gcc generates proper code... */
+			/*
+			 * If you make changes here, make sure
+			 * gcc generates proper code...
+			 */
 			register smpfunc_t f asm("i0") = func;
 			register unsigned long a1 asm("i1") = arg1;
 			register unsigned long a2 asm("i2") = arg2;
@@ -284,7 +241,7 @@
 
 			cpu_clear(smp_processor_id(), mask);
 			cpus_and(mask, cpu_online_map, mask);
-			for(i = 0; i <= high; i++) {
+			for (i = 0; i <= high; i++) {
 				if (cpu_isset(i, mask)) {
 					ccall_info.processors_in[i] = 0;
 					ccall_info.processors_out[i] = 0;
@@ -300,17 +257,17 @@
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_in[i])
+				while (!ccall_info.processors_in[i])
 					barrier();
-			} while(++i <= high);
+			} while (++i <= high);
 
 			i = 0;
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_out[i])
+				while (!ccall_info.processors_out[i])
 					barrier();
-			} while(++i <= high);
+			} while (++i <= high);
 		}
 
 		spin_unlock_irqrestore(&cross_call_lock, flags);
@@ -336,7 +293,7 @@
 	static char led_mask[] = { 0xe, 0xd, 0xb, 0x7, 0xb, 0xd };
 
 	old_regs = set_irq_regs(regs);
-	bw_get_prof_limit(cpu);	
+	bw_get_prof_limit(cpu);
 	bw_clear_intr_mask(0, 1);	/* INTR_TABLE[0] & 1 is Profile IRQ */
 
 	cpu_tick[cpu]++;
@@ -349,7 +306,7 @@
 
 	profile_tick(CPU_PROFILING);
 
-	if(!--prof_counter(cpu)) {
+	if (!--prof_counter(cpu)) {
 		int user = user_mode(regs);
 
 		irq_enter();
@@ -361,8 +318,6 @@
 	set_irq_regs(old_regs);
 }
 
-extern unsigned int lvl14_resolution;
-
 static void __cpuinit smp_setup_percpu_timer(void)
 {
 	int cpu = hard_smp4d_processor_id();
@@ -374,16 +329,16 @@
 void __init smp4d_blackbox_id(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
-	
+
 	addr[0] = 0xc0800800 | rd;		/* lda [%g0] ASI_M_VIKING_TMP1, reg */
-	addr[1] = 0x01000000;    		/* nop */
-	addr[2] = 0x01000000;    		/* nop */
+	addr[1] = 0x01000000;			/* nop */
+	addr[2] = 0x01000000;			/* nop */
 }
 
 void __init smp4d_blackbox_current(unsigned *addr)
 {
 	int rd = *addr & 0x3e000000;
-	
+
 	addr[0] = 0xc0800800 | rd;		/* lda [%g0] ASI_M_VIKING_TMP1, reg */
 	addr[2] = 0x81282002 | rd | (rd >> 11);	/* sll reg, 2, reg */
 	addr[4] = 0x01000000;			/* nop */
@@ -392,17 +347,16 @@
 void __init sun4d_init_smp(void)
 {
 	int i;
-	extern unsigned int t_nmi[], linux_trap_ipi15_sun4d[], linux_trap_ipi15_sun4m[];
 
 	/* Patch ipi15 trap table */
 	t_nmi[1] = t_nmi[1] + (linux_trap_ipi15_sun4d - linux_trap_ipi15_sun4m);
-	
+
 	/* And set btfixup... */
 	BTFIXUPSET_BLACKBOX(hard_smp_processor_id, smp4d_blackbox_id);
 	BTFIXUPSET_BLACKBOX(load_current, smp4d_blackbox_current);
 	BTFIXUPSET_CALL(smp_cross_call, smp4d_cross_call, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__hard_smp_processor_id, __smp4d_processor_id, BTFIXUPCALL_NORM);
-	
+
 	for (i = 0; i < NR_CPUS; i++) {
 		ccall_info.processors_in[i] = 1;
 		ccall_info.processors_out[i] = 1;
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4m_irq.c linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4m_irq.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4m_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4m_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
-/*  sun4m_irq.c
- *  arch/sparc/kernel/sun4m_irq.c:
+/*
+ * sun4m irq support
  *
  *  djhr: Hacked out of irq.c into a CPU dependent version.
  *
@@ -9,101 +9,44 @@
  *  Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk)
  */
 
-#include <linux/errno.h>
-#include <linux/linkage.h>
-#include <linux/kernel_stat.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/ptrace.h>
-#include <linux/smp.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/ioport.h>
-#include <linux/of.h>
-#include <linux/of_device.h>
-
-#include <asm/ptrace.h>
-#include <asm/processor.h>
-#include <asm/system.h>
-#include <asm/psr.h>
-#include <asm/vaddrs.h>
 #include <asm/timer.h>
-#include <asm/openprom.h>
-#include <asm/oplib.h>
 #include <asm/traps.h>
 #include <asm/pgalloc.h>
 #include <asm/pgtable.h>
-#include <asm/smp.h>
 #include <asm/irq.h>
 #include <asm/io.h>
 #include <asm/cacheflush.h>
 
 #include "irq.h"
+#include "kernel.h"
 
-struct sun4m_irq_percpu {
-	u32		pending;
-	u32		clear;
-	u32		set;
-};
-
-struct sun4m_irq_global {
-	u32		pending;
-	u32		mask;
-	u32		mask_clear;
-	u32		mask_set;
-	u32		interrupt_target;
-};
-
-/* Code in entry.S needs to get at these register mappings.  */
-struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
-struct sun4m_irq_global __iomem *sun4m_irq_global;
-
-/* Dave Redman (djhr@tadpole.co.uk)
- * The sun4m interrupt registers.
- */
-#define SUN4M_INT_ENABLE  	0x80000000
-#define SUN4M_INT_E14     	0x00000080
-#define SUN4M_INT_E10     	0x00080000
-
-#define SUN4M_HARD_INT(x)	(0x000000001 << (x))
-#define SUN4M_SOFT_INT(x)	(0x000010000 << (x))
-
-#define	SUN4M_INT_MASKALL	0x80000000	  /* mask all interrupts */
-#define	SUN4M_INT_MODULE_ERR	0x40000000	  /* module error */
-#define	SUN4M_INT_M2S_WRITE_ERR	0x20000000	  /* write buffer error */
-#define	SUN4M_INT_ECC_ERR	0x10000000	  /* ecc memory error */
-#define	SUN4M_INT_VME_ERR	0x08000000	  /* vme async error */
-#define	SUN4M_INT_FLOPPY	0x00400000	  /* floppy disk */
-#define	SUN4M_INT_MODULE	0x00200000	  /* module interrupt */
-#define	SUN4M_INT_VIDEO		0x00100000	  /* onboard video */
-#define	SUN4M_INT_REALTIME	0x00080000	  /* system timer */
-#define	SUN4M_INT_SCSI		0x00040000	  /* onboard scsi */
-#define	SUN4M_INT_AUDIO		0x00020000	  /* audio/isdn */
-#define	SUN4M_INT_ETHERNET	0x00010000	  /* onboard ethernet */
-#define	SUN4M_INT_SERIAL	0x00008000	  /* serial ports */
-#define	SUN4M_INT_KBDMS		0x00004000	  /* keyboard/mouse */
-#define	SUN4M_INT_SBUSBITS	0x00003F80	  /* sbus int bits */
-#define	SUN4M_INT_VMEBITS	0x0000007F	  /* vme int bits */
-
-#define	SUN4M_INT_ERROR		(SUN4M_INT_MODULE_ERR |    \
-				 SUN4M_INT_M2S_WRITE_ERR | \
-				 SUN4M_INT_ECC_ERR |       \
-				 SUN4M_INT_VME_ERR)
-
-#define SUN4M_INT_SBUS(x)	(1 << (x+7))
-#define SUN4M_INT_VME(x)	(1 << (x))
-
-/* Interrupt levels used by OBP */
-#define	OBP_INT_LEVEL_SOFT	0x10
-#define	OBP_INT_LEVEL_ONBOARD	0x20
-#define	OBP_INT_LEVEL_SBUS	0x30
-#define	OBP_INT_LEVEL_VME	0x40
-
-/* Interrupt level assignment on sun4m:
+/* Sample sun4m IRQ layout:
+ *
+ * 0x22 - Power
+ * 0x24 - ESP SCSI
+ * 0x26 - Lance ethernet
+ * 0x2b - Floppy
+ * 0x2c - Zilog uart
+ * 0x32 - SBUS level 0
+ * 0x33 - Parallel port, SBUS level 1
+ * 0x35 - SBUS level 2
+ * 0x37 - SBUS level 3
+ * 0x39 - Audio, Graphics card, SBUS level 4
+ * 0x3b - SBUS level 5
+ * 0x3d - SBUS level 6
+ *
+ * Each interrupt source has a mask bit in the interrupt registers.
+ * When the mask bit is set, this blocks interrupt deliver.  So you
+ * clear the bit to enable the interrupt.
+ *
+ * Interrupts numbered less than 0x10 are software triggered interrupts
+ * and unused by Linux.
+ *
+ * Interrupt level assignment on sun4m:
  *
  *	level		source
  * ------------------------------------------------------------
- *        1		softint-1
+ *	  1		softint-1
  *	  2		softint-2, VME/SBUS level 1
  *	  3		softint-3, VME/SBUS level 2
  *	  4		softint-4, onboard SCSI
@@ -138,10 +81,10 @@
  * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and
  * Tadpole S3 GX systems.
  *
- * esp: 	0x24	onboard ESP SCSI
- * le:  	0x26	onboard Lance ETHERNET
+ * esp:		0x24	onboard ESP SCSI
+ * le:		0x26	onboard Lance ETHERNET
  * p9100:	0x32	SBUS level 1 P9100 video
- * bpp:  	0x33	SBUS level 2 BPP parallel port device
+ * bpp:		0x33	SBUS level 2 BPP parallel port device
  * DBRI:	0x39	SBUS level 5 DBRI ISDN audio
  * SUNW,leo:	0x39	SBUS level 5 LEO video
  * pcmcia:	0x3b	SBUS level 6 PCMCIA controller
@@ -152,8 +95,57 @@
  * power:	0x22	onboard power device (XXX unknown mask bit XXX)
  */
 
+
+/* Code in entry.S needs to get at these register mappings.  */
+struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS];
+struct sun4m_irq_global __iomem *sun4m_irq_global;
+
+/* Dave Redman (djhr@tadpole.co.uk)
+ * The sun4m interrupt registers.
+ */
+#define SUN4M_INT_ENABLE	0x80000000
+#define SUN4M_INT_E14		0x00000080
+#define SUN4M_INT_E10		0x00080000
+
+#define SUN4M_HARD_INT(x)	(0x000000001 << (x))
+#define SUN4M_SOFT_INT(x)	(0x000010000 << (x))
+
+#define	SUN4M_INT_MASKALL	0x80000000	  /* mask all interrupts */
+#define	SUN4M_INT_MODULE_ERR	0x40000000	  /* module error */
+#define	SUN4M_INT_M2S_WRITE_ERR	0x20000000	  /* write buffer error */
+#define	SUN4M_INT_ECC_ERR	0x10000000	  /* ecc memory error */
+#define	SUN4M_INT_VME_ERR	0x08000000	  /* vme async error */
+#define	SUN4M_INT_FLOPPY	0x00400000	  /* floppy disk */
+#define	SUN4M_INT_MODULE	0x00200000	  /* module interrupt */
+#define	SUN4M_INT_VIDEO		0x00100000	  /* onboard video */
+#define	SUN4M_INT_REALTIME	0x00080000	  /* system timer */
+#define	SUN4M_INT_SCSI		0x00040000	  /* onboard scsi */
+#define	SUN4M_INT_AUDIO		0x00020000	  /* audio/isdn */
+#define	SUN4M_INT_ETHERNET	0x00010000	  /* onboard ethernet */
+#define	SUN4M_INT_SERIAL	0x00008000	  /* serial ports */
+#define	SUN4M_INT_KBDMS		0x00004000	  /* keyboard/mouse */
+#define	SUN4M_INT_SBUSBITS	0x00003F80	  /* sbus int bits */
+#define	SUN4M_INT_VMEBITS	0x0000007F	  /* vme int bits */
+
+#define	SUN4M_INT_ERROR		(SUN4M_INT_MODULE_ERR |    \
+				 SUN4M_INT_M2S_WRITE_ERR | \
+				 SUN4M_INT_ECC_ERR |       \
+				 SUN4M_INT_VME_ERR)
+
+#define SUN4M_INT_SBUS(x)	(1 << (x+7))
+#define SUN4M_INT_VME(x)	(1 << (x))
+
+/* Interrupt levels used by OBP */
+#define	OBP_INT_LEVEL_SOFT	0x10
+#define	OBP_INT_LEVEL_ONBOARD	0x20
+#define	OBP_INT_LEVEL_SBUS	0x30
+#define	OBP_INT_LEVEL_VME	0x40
+
+#define SUN4M_TIMER_IRQ         (OBP_INT_LEVEL_ONBOARD | 10)
+#define SUM4M_PROFILE_IRQ       (OBP_INT_LEVEL_ONBOARD | 14)
+
 static unsigned long irq_mask[0x50] = {
-	/* SMP */
+	/* 0x00 - SMP */
 	0,  SUN4M_SOFT_INT(1),
 	SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
 	SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
@@ -162,7 +154,7 @@
 	SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
 	SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
 	SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
-	/* soft */
+	/* 0x10 - soft */
 	0,  SUN4M_SOFT_INT(1),
 	SUN4M_SOFT_INT(2),  SUN4M_SOFT_INT(3),
 	SUN4M_SOFT_INT(4),  SUN4M_SOFT_INT(5),
@@ -171,19 +163,19 @@
 	SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11),
 	SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13),
 	SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15),
-	/* onboard */
+	/* 0x20 - onboard */
 	0, 0, 0, 0,
 	SUN4M_INT_SCSI,  0, SUN4M_INT_ETHERNET, 0,
 	SUN4M_INT_VIDEO, SUN4M_INT_MODULE,
 	SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY,
 	(SUN4M_INT_SERIAL | SUN4M_INT_KBDMS),
 	SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR,
-	/* sbus */
+	/* 0x30 - sbus */
 	0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1),
 	0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3),
 	0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5),
 	0, SUN4M_INT_SBUS(6), 0, 0,
-	/* vme */
+	/* 0x40 - vme */
 	0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1),
 	0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3),
 	0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5),
@@ -193,7 +185,7 @@
 static unsigned long sun4m_get_irqmask(unsigned int irq)
 {
 	unsigned long mask;
-    
+
 	if (irq < 0x50)
 		mask = irq_mask[irq];
 	else
@@ -217,7 +209,7 @@
 		sbus_writel(mask, &sun4m_irq_global->mask_set);
 	else
 		sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
-	local_irq_restore(flags);    
+	local_irq_restore(flags);
 }
 
 static void sun4m_enable_irq(unsigned int irq_nr)
@@ -226,17 +218,17 @@
 	int cpu = smp_processor_id();
 
 	/* Dreadful floppy hack. When we use 0x2b instead of
-         * 0x0b the system blows (it starts to whistle!).
-         * So we continue to use 0x0b. Fixme ASAP. --P3
-         */
-        if (irq_nr != 0x0b) {
+	 * 0x0b the system blows (it starts to whistle!).
+	 * So we continue to use 0x0b. Fixme ASAP. --P3
+	 */
+	if (irq_nr != 0x0b) {
 		mask = sun4m_get_irqmask(irq_nr);
 		local_irq_save(flags);
 		if (irq_nr > 15)
 			sbus_writel(mask, &sun4m_irq_global->mask_clear);
 		else
 			sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
-		local_irq_restore(flags);    
+		local_irq_restore(flags);
 	} else {
 		local_irq_save(flags);
 		sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear);
@@ -260,7 +252,7 @@
 /*12*/	SUN4M_INT_SERIAL  | SUN4M_INT_KBDMS,
 /*13*/	SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO,
 /*14*/	SUN4M_INT_E14,
-/*15*/	SUN4M_INT_ERROR
+/*15*/	SUN4M_INT_ERROR,
 };
 
 /* We assume the caller has disabled local interrupts when these are called,
@@ -280,12 +272,14 @@
 static void sun4m_send_ipi(int cpu, int level)
 {
 	unsigned long mask = sun4m_get_irqmask(level);
+
 	sbus_writel(mask, &sun4m_irq_percpu[cpu]->set);
 }
 
 static void sun4m_clear_ipi(int cpu, int level)
 {
 	unsigned long mask = sun4m_get_irqmask(level);
+
 	sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear);
 }
 
@@ -314,7 +308,6 @@
 
 static struct sun4m_timer_global __iomem *timers_global;
 
-#define TIMER_IRQ  	(OBP_INT_LEVEL_ONBOARD | 10)
 
 unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10);
 
@@ -391,7 +384,7 @@
 
 	master_l10_counter = &timers_global->l10_count;
 
-	err = request_irq(TIMER_IRQ, counter_fn,
+	err = request_irq(SUN4M_TIMER_IRQ, counter_fn,
 			  (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL);
 	if (err) {
 		printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n",
@@ -407,7 +400,6 @@
 #ifdef CONFIG_SMP
 	{
 		unsigned long flags;
-		extern unsigned long lvl14_save[4];
 		struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)];
 
 		/* For SMP we use the level 14 ticker, however the bootup code
@@ -466,7 +458,9 @@
 	BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM);
-	sparc_init_timers = sun4m_init_timers;
+
+	sparc_irq_config.init_timers = sun4m_init_timers;
+
 #ifdef CONFIG_SMP
 	BTFIXUPSET_CALL(set_cpu_int, sun4m_send_ipi, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4m_smp.c linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4m_smp.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/sun4m_smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/sun4m_smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,59 +1,22 @@
-/* sun4m_smp.c: Sparc SUN4M SMP support.
+/*
+ *  sun4m SMP support.
  *
  * Copyright (C) 1996 David S. Miller (davem@caip.rutgers.edu)
  */
 
-#include <asm/head.h>
-
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/threads.h>
-#include <linux/smp.h>
 #include <linux/interrupt.h>
-#include <linux/kernel_stat.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/mm.h>
-#include <linux/swap.h>
 #include <linux/profile.h>
 #include <linux/delay.h>
 #include <linux/cpu.h>
 
 #include <asm/cacheflush.h>
 #include <asm/tlbflush.h>
-#include <asm/irq_regs.h>
-
-#include <asm/ptrace.h>
-#include <asm/atomic.h>
-
-#include <asm/irq.h>
-#include <asm/page.h>
-#include <asm/pgalloc.h>
-#include <asm/pgtable.h>
-#include <asm/oplib.h>
-#include <asm/cpudata.h>
 
 #include "irq.h"
+#include "kernel.h"
 
 #define IRQ_CROSS_CALL		15
 
-extern ctxd_t *srmmu_ctx_table_phys;
-
-extern volatile unsigned long cpu_callin_map[NR_CPUS];
-extern unsigned char boot_cpu_id;
-
-extern cpumask_t smp_commenced_mask;
-
-extern int __smp4m_processor_id(void);
-
-/*#define SMP_DEBUG*/
-
-#ifdef SMP_DEBUG
-#define SMP_PRINTK(x)	printk x
-#else
-#define SMP_PRINTK(x)
-#endif
-
 static inline unsigned long
 swap_ulong(volatile unsigned long *ptr, unsigned long val)
 {
@@ -64,7 +27,6 @@
 }
 
 static void smp_setup_percpu_timer(void);
-extern void cpu_probe(void);
 
 void __cpuinit smp4m_callin(void)
 {
@@ -96,7 +58,7 @@
 	/* XXX: What's up with all the flushes? */
 	local_flush_cache_all();
 	local_flush_tlb_all();
-	
+
 	cpu_probe();
 
 	/* Fix idle thread fields. */
@@ -119,9 +81,6 @@
 /*
  *	Cycle through the processors asking the PROM to start each one.
  */
- 
-extern struct linux_prom_registers smp_penguin_ctable;
-
 void __init smp4m_boot_cpus(void)
 {
 	smp_setup_percpu_timer();
@@ -130,7 +89,6 @@
 
 int __cpuinit smp4m_boot_one_cpu(int i)
 {
-	extern unsigned long sun4m_cpu_startup;
 	unsigned long *entry = &sun4m_cpu_startup;
 	struct task_struct *p;
 	int timeout;
@@ -142,7 +100,7 @@
 	p = fork_idle(i);
 	current_set[i] = task_thread_info(p);
 	/* See trampoline.S for details... */
-	entry += ((i-1) * 3);
+	entry += ((i - 1) * 3);
 
 	/*
 	 * Initialize the contexts table
@@ -154,20 +112,19 @@
 	smp_penguin_ctable.reg_size = 0;
 
 	/* whirrr, whirrr, whirrrrrrrrr... */
-	printk("Starting CPU %d at %p\n", i, entry);
+	printk(KERN_INFO "Starting CPU %d at %p\n", i, entry);
 	local_flush_cache_all();
-	prom_startcpu(cpu_node,
-		      &smp_penguin_ctable, 0, (char *)entry);
+	prom_startcpu(cpu_node, &smp_penguin_ctable, 0, (char *)entry);
 
 	/* wheee... it's going... */
-	for(timeout = 0; timeout < 10000; timeout++) {
-		if(cpu_callin_map[i])
+	for (timeout = 0; timeout < 10000; timeout++) {
+		if (cpu_callin_map[i])
 			break;
 		udelay(200);
 	}
 
 	if (!(cpu_callin_map[i])) {
-		printk("Processor %d is stuck.\n", i);
+		printk(KERN_ERR "Processor %d is stuck.\n", i);
 		return -ENODEV;
 	}
 
@@ -202,6 +159,7 @@
 void smp4m_irq_rotate(int cpu)
 {
 	int next = cpu_data(cpu).next;
+
 	if (next != cpu)
 		set_irq_udt(next);
 }
@@ -243,7 +201,7 @@
 
 			cpu_clear(smp_processor_id(), mask);
 			cpus_and(mask, cpu_online_map, mask);
-			for(i = 0; i < ncpus; i++) {
+			for (i = 0; i < ncpus; i++) {
 				if (cpu_isset(i, mask)) {
 					ccall_info.processors_in[i] = 0;
 					ccall_info.processors_out[i] = 0;
@@ -262,19 +220,18 @@
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_in[i])
+				while (!ccall_info.processors_in[i])
 					barrier();
-			} while(++i < ncpus);
+			} while (++i < ncpus);
 
 			i = 0;
 			do {
 				if (!cpu_isset(i, mask))
 					continue;
-				while(!ccall_info.processors_out[i])
+				while (!ccall_info.processors_out[i])
 					barrier();
-			} while(++i < ncpus);
+			} while (++i < ncpus);
 		}
-
 		spin_unlock_irqrestore(&cross_call_lock, flags);
 }
 
@@ -289,8 +246,6 @@
 	ccall_info.processors_out[i] = 1;
 }
 
-extern void sun4m_clear_profile_irq(int cpu);
-
 void smp4m_percpu_timer_interrupt(struct pt_regs *regs)
 {
 	struct pt_regs *old_regs;
@@ -302,7 +257,7 @@
 
 	profile_tick(CPU_PROFILING);
 
-	if(!--prof_counter(cpu)) {
+	if (!--prof_counter(cpu)) {
 		int user = user_mode(regs);
 
 		irq_enter();
@@ -314,8 +269,6 @@
 	set_irq_regs(old_regs);
 }
 
-extern unsigned int lvl14_resolution;
-
 static void __cpuinit smp_setup_percpu_timer(void)
 {
 	int cpu = smp_processor_id();
@@ -323,7 +276,7 @@
 	prof_counter(cpu) = prof_multiplier(cpu) = 1;
 	load_profile_irq(cpu, lvl14_resolution);
 
-	if(cpu == boot_cpu_id)
+	if (cpu == boot_cpu_id)
 		enable_pil_irq(14);
 }
 
@@ -331,9 +284,9 @@
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
-	
+
 	addr[0] = 0x81580000 | rd;		/* rd %tbr, reg */
-	addr[1] = 0x8130200c | rd | rs1;    	/* srl reg, 0xc, reg */
+	addr[1] = 0x8130200c | rd | rs1;	/* srl reg, 0xc, reg */
 	addr[2] = 0x80082003 | rd | rs1;	/* and reg, 3, reg */
 }
 
@@ -341,9 +294,9 @@
 {
 	int rd = *addr & 0x3e000000;
 	int rs1 = rd >> 11;
-	
+
 	addr[0] = 0x81580000 | rd;		/* rd %tbr, reg */
-	addr[2] = 0x8130200a | rd | rs1;    	/* srl reg, 0xa, reg */
+	addr[2] = 0x8130200a | rd | rs1;	/* srl reg, 0xa, reg */
 	addr[4] = 0x8008200c | rd | rs1;	/* and reg, 0xc, reg */
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/sys_sparc_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/sys_sparc_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/sys_sparc_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/sys_sparc_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -360,20 +360,25 @@
 }
 EXPORT_SYMBOL(get_fb_unmapped_area);
 
-/* Essentially the same as PowerPC... */
-void arch_pick_mmap_layout(struct mm_struct *mm)
+/* Essentially the same as PowerPC.  */
+static unsigned long mmap_rnd(void)
 {
-	unsigned long random_factor = 0UL;
-	unsigned long gap;
+	unsigned long rnd = 0UL;
 
 	if (current->flags & PF_RANDOMIZE) {
-		random_factor = get_random_int();
+		unsigned long val = get_random_int();
 		if (test_thread_flag(TIF_32BIT))
-			random_factor &= ((1 * 1024 * 1024) - 1);
+			rnd = (val % (1UL << (22UL-PAGE_SHIFT)));
 		else
-			random_factor = ((random_factor << PAGE_SHIFT) &
-					 0xffffffffUL);
+			rnd = (val % (1UL << (29UL-PAGE_SHIFT)));
 	}
+	return (rnd << PAGE_SHIFT) * 2;
+}
+
+void arch_pick_mmap_layout(struct mm_struct *mm)
+{
+	unsigned long random_factor = mmap_rnd();
+	unsigned long gap;
 
 	/*
 	 * Fall back to the standard layout if the personality
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/systbls_32.S linux-libre-2.6.39-gnu/arch/sparc/kernel/systbls_32.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/systbls_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/systbls_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -83,5 +83,5 @@
 /*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
 /*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
-/*330*/	.long sys_fanotify_mark, sys_prlimit64
-
+/*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
+/*335*/	.long sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/systbls_64.S linux-libre-2.6.39-gnu/arch/sparc/kernel/systbls_64.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/systbls_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/systbls_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,8 @@
 	.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
 	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
-/*330*/	.word sys32_fanotify_mark, sys_prlimit64
+/*330*/	.word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
+	.word sys_syncfs
 
 #endif /* CONFIG_COMPAT */
 
@@ -160,4 +161,5 @@
 	.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
 	.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
-/*330*/	.word sys_fanotify_mark, sys_prlimit64
+/*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
+	.word sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/tick14.c linux-libre-2.6.39-gnu/arch/sparc/kernel/tick14.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/tick14.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/tick14.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,39 +0,0 @@
-/* tick14.c
- *
- * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
- *
- * This file handles the Sparc specific level14 ticker
- * This is really useful for profiling OBP uses it for keyboard
- * aborts and other stuff.
- */
-#include <linux/kernel.h>
-
-extern unsigned long lvl14_save[5];
-static unsigned long *linux_lvl14 = NULL;
-static unsigned long obp_lvl14[4];
- 
-/*
- * Call with timer IRQ closed.
- * First time we do it with disable_irq, later prom code uses spin_lock_irq().
- */
-void install_linux_ticker(void)
-{
-
-	if (!linux_lvl14)
-		return;
-	linux_lvl14[0] =  lvl14_save[0];
-	linux_lvl14[1] =  lvl14_save[1];
-	linux_lvl14[2] =  lvl14_save[2];
-	linux_lvl14[3] =  lvl14_save[3];
-}
-
-void install_obp_ticker(void)
-{
-
-	if (!linux_lvl14)
-		return;
-	linux_lvl14[0] =  obp_lvl14[0];
-	linux_lvl14[1] =  obp_lvl14[1];
-	linux_lvl14[2] =  obp_lvl14[2];
-	linux_lvl14[3] =  obp_lvl14[3]; 
-}
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/time_32.c linux-libre-2.6.39-gnu/arch/sparc/kernel/time_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/time_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/time_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,7 +85,7 @@
 
 /*
  * timer_interrupt() needs to keep up the real-time clock,
- * as well as call the "do_timer()" routine every clocktick
+ * as well as call the "xtime_update()" routine every clocktick
  */
 
 #define TICK_SIZE (tick_nsec / 1000)
@@ -96,14 +96,9 @@
 	profile_tick(CPU_PROFILING);
 #endif
 
-	/* Protect counter clear so that do_gettimeoffset works */
-	write_seqlock(&xtime_lock);
-
 	clear_clock_irq();
 
-	do_timer(1);
-
-	write_sequnlock(&xtime_lock);
+	xtime_update(1);
 
 #ifndef CONFIG_SMP
 	update_process_times(user_mode(get_irq_regs()));
@@ -142,7 +137,7 @@
 	},
 };
 
-static int __devinit clock_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit clock_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	const char *model = of_get_property(dp, "model", NULL);
@@ -150,6 +145,10 @@
 	if (!model)
 		return -ENODEV;
 
+	/* Only the primary RTC has an address property */
+	if (!of_find_property(dp, "address", NULL))
+		return -ENODEV;
+
 	m48t59_rtc.resource = &op->resource[0];
 	if (!strcmp(model, "mk48t02")) {
 		/* Map the clock register io area read-only */
@@ -169,14 +168,14 @@
 	return 0;
 }
 
-static struct of_device_id __initdata clock_match[] = {
+static struct of_device_id clock_match[] = {
 	{
 		.name = "eeprom",
 	},
 	{},
 };
 
-static struct of_platform_driver clock_driver = {
+static struct platform_driver clock_driver = {
 	.probe		= clock_probe,
 	.driver = {
 		.name = "rtc",
@@ -189,7 +188,7 @@
 /* Probe for the mostek real time clock chip. */
 static int __init clock_init(void)
 {
-	return of_register_platform_driver(&clock_driver);
+	return platform_driver_register(&clock_driver);
 }
 /* Must be after subsys_initcall() so that busses are probed.  Must
  * be before device_initcall() because things like the RTC driver
@@ -224,7 +223,7 @@
 
 	btfixup();
 
-	sparc_init_timers(timer_interrupt);
+	sparc_irq_config.init_timers(timer_interrupt);
 }
 
 void __init time_init(void)
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/time_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/time_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/time_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/time_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -419,7 +419,7 @@
 	.num_resources	= 1,
 };
 
-static int __devinit rtc_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit rtc_probe(struct platform_device *op)
 {
 	struct resource *r;
 
@@ -442,7 +442,7 @@
 	return platform_device_register(&rtc_cmos_device);
 }
 
-static struct of_device_id __initdata rtc_match[] = {
+static const struct of_device_id rtc_match[] = {
 	{
 		.name = "rtc",
 		.compatible = "m5819",
@@ -462,7 +462,7 @@
 	{},
 };
 
-static struct of_platform_driver rtc_driver = {
+static struct platform_driver rtc_driver = {
 	.probe		= rtc_probe,
 	.driver = {
 		.name = "rtc",
@@ -477,7 +477,7 @@
 	.num_resources	= 1,
 };
 
-static int __devinit bq4802_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bq4802_probe(struct platform_device *op)
 {
 
 	printk(KERN_INFO "%s: BQ4802 regs at 0x%llx\n",
@@ -487,7 +487,7 @@
 	return platform_device_register(&rtc_bq4802_device);
 }
 
-static struct of_device_id __initdata bq4802_match[] = {
+static const struct of_device_id bq4802_match[] = {
 	{
 		.name = "rtc",
 		.compatible = "bq4802",
@@ -495,7 +495,7 @@
 	{},
 };
 
-static struct of_platform_driver bq4802_driver = {
+static struct platform_driver bq4802_driver = {
 	.probe		= bq4802_probe,
 	.driver = {
 		.name = "bq4802",
@@ -534,7 +534,7 @@
 	},
 };
 
-static int __devinit mostek_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit mostek_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -552,14 +552,14 @@
 	return platform_device_register(&m48t59_rtc);
 }
 
-static struct of_device_id __initdata mostek_match[] = {
+static const struct of_device_id mostek_match[] = {
 	{
 		.name = "eeprom",
 	},
 	{},
 };
 
-static struct of_platform_driver mostek_driver = {
+static struct platform_driver mostek_driver = {
 	.probe		= mostek_probe,
 	.driver = {
 		.name = "mostek",
@@ -586,9 +586,9 @@
 	if (tlb_type == hypervisor)
 		return platform_device_register(&rtc_sun4v_device);
 
-	(void) of_register_platform_driver(&rtc_driver);
-	(void) of_register_platform_driver(&mostek_driver);
-	(void) of_register_platform_driver(&bq4802_driver);
+	(void) platform_driver_register(&rtc_driver);
+	(void) platform_driver_register(&mostek_driver);
+	(void) platform_driver_register(&bq4802_driver);
 
 	return 0;
 }
@@ -816,14 +816,12 @@
 		clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT);
 
 	clocksource_tick.name = tick_ops->name;
-	clocksource_calc_mult_shift(&clocksource_tick, freq, 4);
 	clocksource_tick.read = clocksource_tick_read;
 
+	clocksource_register_hz(&clocksource_tick, freq);
 	printk("clocksource: mult[%x] shift[%d]\n",
 	       clocksource_tick.mult, clocksource_tick.shift);
 
-	clocksource_register(&clocksource_tick);
-
 	sparc64_clockevent.name = tick_ops->name;
 	clockevents_calc_mult_shift(&sparc64_clockevent, freq, 4);
 
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/traps_64.c linux-libre-2.6.39-gnu/arch/sparc/kernel/traps_64.c
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/traps_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/traps_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -2152,7 +2152,7 @@
 
 void show_stack(struct task_struct *tsk, unsigned long *_ksp)
 {
-	unsigned long fp, thread_base, ksp;
+	unsigned long fp, ksp;
 	struct thread_info *tp;
 	int count = 0;
 #ifdef CONFIG_FUNCTION_GRAPH_TRACER
@@ -2173,7 +2173,6 @@
 		flushw_all();
 
 	fp = ksp + STACK_BIAS;
-	thread_base = (unsigned long) tp;
 
 	printk("Call Trace:\n");
 	do {
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/una_asm_64.S linux-libre-2.6.39-gnu/arch/sparc/kernel/una_asm_64.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/una_asm_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/una_asm_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -127,7 +127,7 @@
 	wr	%o5, 0x0, %asi
 	retl
 	 mov	0, %o0
-	.size	__do_int_load, .-__do_int_load
+	.size	do_int_load, .-do_int_load
 
 	.section	__ex_table,"a"
 	.word		4b, __retl_efault
diff -druN linux-libre-2.6.38-gnu/arch/sparc/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/sparc/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/sparc/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -108,7 +108,7 @@
 		__sun4v_2insn_patch_end = .;
 	}
 
-	PERCPU(PAGE_SIZE)
+	PERCPU(SMP_CACHE_BYTES, PAGE_SIZE)
 
 	. = ALIGN(PAGE_SIZE);
 	__init_end = .;
diff -druN linux-libre-2.6.38-gnu/arch/sparc/lib/atomic32.c linux-libre-2.6.39-gnu/arch/sparc/lib/atomic32.c
--- linux-libre-2.6.38-gnu/arch/sparc/lib/atomic32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/lib/atomic32.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,7 +16,7 @@
 #define ATOMIC_HASH(a)	(&__atomic_hash[(((unsigned long)a)>>8) & (ATOMIC_HASH_SIZE-1)])
 
 spinlock_t __atomic_hash[ATOMIC_HASH_SIZE] = {
-	[0 ... (ATOMIC_HASH_SIZE-1)] = SPIN_LOCK_UNLOCKED
+	[0 ... (ATOMIC_HASH_SIZE-1)] = __SPIN_LOCK_UNLOCKED(__atomic_hash)
 };
 
 #else /* SMP */
diff -druN linux-libre-2.6.38-gnu/arch/sparc/lib/checksum_32.S linux-libre-2.6.39-gnu/arch/sparc/lib/checksum_32.S
--- linux-libre-2.6.38-gnu/arch/sparc/lib/checksum_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/lib/checksum_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -289,10 +289,16 @@
 
 	/* Also, handle the alignment code out of band. */
 cc_dword_align:
-	cmp	%g1, 6
-	bl,a	ccte
+	cmp	%g1, 16
+	bge	1f
+	 srl	%g1, 1, %o3
+2:	cmp	%o3, 0
+	be,a	ccte
 	 andcc	%g1, 0xf, %o3
-	andcc	%o0, 0x1, %g0
+	andcc	%o3, %o0, %g0	! Check %o0 only (%o1 has the same last 2 bits)
+	be,a	2b
+	 srl	%o3, 1, %o3
+1:	andcc	%o0, 0x1, %g0
 	bne	ccslow
 	 andcc	%o0, 0x2, %g0
 	be	1f
diff -druN linux-libre-2.6.38-gnu/arch/sparc/Makefile linux-libre-2.6.39-gnu/arch/sparc/Makefile
--- linux-libre-2.6.38-gnu/arch/sparc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 # Default target
 all: zImage
 
-image zImage tftpboot.img vmlinux.aout: vmlinux
+image zImage uImage tftpboot.img vmlinux.aout: vmlinux
 	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
 archclean:
@@ -102,6 +102,7 @@
 define archhelp
   echo  '* image        - kernel image ($(boot)/image)'
   echo  '* zImage       - stripped kernel image ($(boot)/zImage)'
+  echo  '  uImage       - U-Boot SPARC32 Image (only for LEON)'
   echo  '  tftpboot.img - image prepared for tftp'
 endef
 else
diff -druN linux-libre-2.6.38-gnu/arch/sparc/math-emu/Makefile linux-libre-2.6.39-gnu/arch/sparc/math-emu/Makefile
--- linux-libre-2.6.38-gnu/arch/sparc/math-emu/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/math-emu/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
 # Makefile for the FPU instruction emulation.
 #
 
-# supress all warnings - as math.c produces a lot!
+# suppress all warnings - as math.c produces a lot!
 ccflags-y := -w
 
 obj-y    := math_$(BITS).o
diff -druN linux-libre-2.6.38-gnu/arch/sparc/mm/fault_32.c linux-libre-2.6.39-gnu/arch/sparc/mm/fault_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/mm/fault_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/mm/fault_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,11 +240,10 @@
 	 * only copy the information from the master page table,
 	 * nothing more.
 	 */
+	code = SEGV_MAPERR;
 	if (!ARCH_SUN4C && address >= TASK_SIZE)
 		goto vmalloc_fault;
 
-	code = SEGV_MAPERR;
-
 	/*
 	 * If we're in an interrupt or have no user
 	 * context, we must not take the fault..
diff -druN linux-libre-2.6.38-gnu/arch/sparc/mm/init_32.c linux-libre-2.6.39-gnu/arch/sparc/mm/init_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/mm/init_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/mm/init_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 	kmap_prot = __pgprot(SRMMU_ET_PTE | SRMMU_PRIV | SRMMU_CACHE);
 }
 
-void show_mem(void)
+void show_mem(unsigned int filter)
 {
 	printk("Mem-info:\n");
 	show_free_areas();
diff -druN linux-libre-2.6.38-gnu/arch/sparc/mm/srmmu.c linux-libre-2.6.39-gnu/arch/sparc/mm/srmmu.c
--- linux-libre-2.6.38-gnu/arch/sparc/mm/srmmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/mm/srmmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -650,7 +650,7 @@
  * mappings on the kernel stack without any special code as we did
  * need on the sun4c.
  */
-static struct thread_info *srmmu_alloc_thread_info(void)
+static struct thread_info *srmmu_alloc_thread_info_node(int node)
 {
 	struct thread_info *ret;
 
@@ -2271,7 +2271,7 @@
 
 	BTFIXUPSET_CALL(mmu_info, srmmu_mmu_info, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(alloc_thread_info, srmmu_alloc_thread_info, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(alloc_thread_info_node, srmmu_alloc_thread_info_node, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(free_thread_info, srmmu_free_thread_info, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(pte_to_pgoff, srmmu_pte_to_pgoff, BTFIXUPCALL_NORM);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/mm/sun4c.c linux-libre-2.6.39-gnu/arch/sparc/mm/sun4c.c
--- linux-libre-2.6.38-gnu/arch/sparc/mm/sun4c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/mm/sun4c.c	2011-05-19 00:06:34.000000000 -0400
@@ -922,7 +922,7 @@
 	free_locked_segment(BUCKET_ADDR(entry));
 }
 
-static struct thread_info *sun4c_alloc_thread_info(void)
+static struct thread_info *sun4c_alloc_thread_info_node(int node)
 {
 	unsigned long addr, pages;
 	int entry;
@@ -2155,7 +2155,7 @@
 	BTFIXUPSET_CALL(__swp_offset, sun4c_swp_offset, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(__swp_entry, sun4c_swp_entry, BTFIXUPCALL_NORM);
 
-	BTFIXUPSET_CALL(alloc_thread_info, sun4c_alloc_thread_info, BTFIXUPCALL_NORM);
+	BTFIXUPSET_CALL(alloc_thread_info_node, sun4c_alloc_thread_info_node, BTFIXUPCALL_NORM);
 	BTFIXUPSET_CALL(free_thread_info, sun4c_free_thread_info, BTFIXUPCALL_NORM);
 
 	BTFIXUPSET_CALL(mmu_info, sun4c_mmu_info, BTFIXUPCALL_NORM);
diff -druN linux-libre-2.6.38-gnu/arch/sparc/prom/misc_32.c linux-libre-2.6.39-gnu/arch/sparc/prom/misc_32.c
--- linux-libre-2.6.38-gnu/arch/sparc/prom/misc_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/sparc/prom/misc_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,15 +54,11 @@
 void
 prom_cmdline(void)
 {
-	extern void install_obp_ticker(void);
-	extern void install_linux_ticker(void);
 	unsigned long flags;
 
 	spin_lock_irqsave(&prom_lock, flags);
-	install_obp_ticker();
 	(*(romvec->pv_abort))();
 	restore_current();
-	install_linux_ticker();
 	spin_unlock_irqrestore(&prom_lock, flags);
 	set_auxio(AUXIO_LED, 0);
 }
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/arch/interrupts_32.h linux-libre-2.6.39-gnu/arch/tile/include/arch/interrupts_32.h
--- linux-libre-2.6.38-gnu/arch/tile/include/arch/interrupts_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/arch/interrupts_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,10 +16,11 @@
 #define __ARCH_INTERRUPTS_H__
 
 /** Mask for an interrupt. */
-#ifdef __ASSEMBLER__
 /* Note: must handle breaking interrupts into high and low words manually. */
-#define INT_MASK(intno) (1 << (intno))
-#else
+#define INT_MASK_LO(intno) (1 << (intno))
+#define INT_MASK_HI(intno) (1 << ((intno) - 32))
+
+#ifndef __ASSEMBLER__
 #define INT_MASK(intno) (1ULL << (intno))
 #endif
 
@@ -89,6 +90,7 @@
 
 #define NUM_INTERRUPTS 49
 
+#ifndef __ASSEMBLER__
 #define QUEUED_INTERRUPTS ( \
     INT_MASK(INT_MEM_ERROR) | \
     INT_MASK(INT_DMATLB_MISS) | \
@@ -301,4 +303,5 @@
     INT_MASK(INT_DOUBLE_FAULT) | \
     INT_MASK(INT_AUX_PERF_COUNT) | \
     0)
+#endif /* !__ASSEMBLER__ */
 #endif /* !__ARCH_INTERRUPTS_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/arch/sim_def.h linux-libre-2.6.39-gnu/arch/tile/include/arch/sim_def.h
--- linux-libre-2.6.38-gnu/arch/tile/include/arch/sim_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/arch/sim_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -243,6 +243,9 @@
  */
 #define SIM_SYSCALL_VALIDATE_LINES_EVICTED 5
 
+/** Syscall number for sim_query_cpu_speed(). */
+#define SIM_SYSCALL_QUERY_CPU_SPEED 6
+
 
 /*
  * Bit masks which can be shifted by 8, combined with
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/arch/sim.h linux-libre-2.6.39-gnu/arch/tile/include/arch/sim.h
--- linux-libre-2.6.38-gnu/arch/tile/include/arch/sim.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/arch/sim.h	2011-05-19 00:06:34.000000000 -0400
@@ -152,16 +152,33 @@
 /**
  * Print a string to the simulator stdout.
  *
- * @param str The string to be written; a newline is automatically added.
+ * @param str The string to be written.
+ */
+static __inline void
+sim_print(const char* str)
+{
+  for ( ; *str != '\0'; str++)
+  {
+    __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+                 (*str << _SIM_CONTROL_OPERATOR_BITS));
+  }
+  __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
+               (SIM_PUTC_FLUSH_BINARY << _SIM_CONTROL_OPERATOR_BITS));
+}
+
+
+/**
+ * Print a string to the simulator stdout.
+ *
+ * @param str The string to be written (a newline is automatically added).
  */
 static __inline void
 sim_print_string(const char* str)
 {
-  int i;
-  for (i = 0; str[i] != 0; i++)
+  for ( ; *str != '\0'; str++)
   {
     __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
-                 (str[i] << _SIM_CONTROL_OPERATOR_BITS));
+                 (*str << _SIM_CONTROL_OPERATOR_BITS));
   }
   __insn_mtspr(SPR_SIM_CONTROL, SIM_CONTROL_PUTC |
                (SIM_PUTC_FLUSH_STRING << _SIM_CONTROL_OPERATOR_BITS));
@@ -203,7 +220,7 @@
  * we are passing to the simulator are actually valid in the registers
  * (i.e. returned from memory) prior to the SIM_CONTROL spr.
  */
-static __inline int _sim_syscall0(int val)
+static __inline long _sim_syscall0(int val)
 {
   long result;
   __asm__ __volatile__ ("mtspr SIM_CONTROL, r0"
@@ -211,7 +228,7 @@
   return result;
 }
 
-static __inline int _sim_syscall1(int val, long arg1)
+static __inline long _sim_syscall1(int val, long arg1)
 {
   long result;
   __asm__ __volatile__ ("{ and zero, r1, r1; mtspr SIM_CONTROL, r0 }"
@@ -219,7 +236,7 @@
   return result;
 }
 
-static __inline int _sim_syscall2(int val, long arg1, long arg2)
+static __inline long _sim_syscall2(int val, long arg1, long arg2)
 {
   long result;
   __asm__ __volatile__ ("{ and zero, r1, r2; mtspr SIM_CONTROL, r0 }"
@@ -233,7 +250,7 @@
    the register values for arguments 3 and up may still be in flight
    to the core from a stack frame reload. */
 
-static __inline int _sim_syscall3(int val, long arg1, long arg2, long arg3)
+static __inline long _sim_syscall3(int val, long arg1, long arg2, long arg3)
 {
   long result;
   __asm__ __volatile__ ("{ and zero, r3, r3 };"
@@ -244,7 +261,7 @@
   return result;
 }
 
-static __inline int _sim_syscall4(int val, long arg1, long arg2, long arg3,
+static __inline long _sim_syscall4(int val, long arg1, long arg2, long arg3,
                                   long arg4)
 {
   long result;
@@ -256,7 +273,7 @@
   return result;
 }
 
-static __inline int _sim_syscall5(int val, long arg1, long arg2, long arg3,
+static __inline long _sim_syscall5(int val, long arg1, long arg2, long arg3,
                                   long arg4, long arg5)
 {
   long result;
@@ -268,7 +285,6 @@
   return result;
 }
 
-
 /**
  * Make a special syscall to the simulator itself, if running under
  * simulation. This is used as the implementation of other functions
@@ -281,7 +297,8 @@
  */
 #define _sim_syscall(syscall_num, nr, args...) \
   _sim_syscall##nr( \
-    ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, args)
+    ((syscall_num) << _SIM_CONTROL_OPERATOR_BITS) | SIM_CONTROL_SYSCALL, \
+    ##args)
 
 
 /* Values for the "access_mask" parameters below. */
@@ -365,6 +382,13 @@
 }
 
 
+/* Return the current CPU speed in cycles per second. */
+static __inline long
+sim_query_cpu_speed(void)
+{
+  return _sim_syscall(SIM_SYSCALL_QUERY_CPU_SPEED, 0);
+}
+
 #endif /* !__DOXYGEN__ */
 
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/atomic.h linux-libre-2.6.39-gnu/arch/tile/include/asm/atomic.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/atomic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/atomic.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
  */
 static inline int atomic_read(const atomic_t *v)
 {
-       return v->counter;
+	return ACCESS_ONCE(v->counter);
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/bitops_32.h linux-libre-2.6.39-gnu/arch/tile/include/asm/bitops_32.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/bitops_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/bitops_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,7 +122,7 @@
 	return (_atomic_xor(addr, mask) & mask) != 0;
 }
 
-/* See discussion at smp_mb__before_atomic_dec() in <asm/atomic.h>. */
+/* See discussion at smp_mb__before_atomic_dec() in <asm/atomic_32.h>. */
 #define smp_mb__before_clear_bit()	smp_mb()
 #define smp_mb__after_clear_bit()	do {} while (0)
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/tile/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,7 +122,6 @@
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/find.h>
 #include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/ext2-non-atomic.h>
-#include <asm-generic/bitops/minix.h>
+#include <asm-generic/bitops/le.h>
 
 #endif /* _ASM_TILE_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/tile/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -138,55 +138,12 @@
 }
 
 /*
- * Flush & invalidate a VA range that is homed remotely on a single core,
- * waiting until the memory controller holds the flushed values.
+ * Flush and invalidate a VA range that is homed remotely, waiting
+ * until the memory controller holds the flushed values.  If "hfh" is
+ * true, we will do a more expensive flush involving additional loads
+ * to make sure we have touched all the possible home cpus of a buffer
+ * that is homed with "hash for home".
  */
-static inline void finv_buffer_remote(void *buffer, size_t size)
-{
-	char *p;
-	int i;
-
-	/*
-	 * Flush and invalidate the buffer out of the local L1/L2
-	 * and request the home cache to flush and invalidate as well.
-	 */
-	__finv_buffer(buffer, size);
-
-	/*
-	 * Wait for the home cache to acknowledge that it has processed
-	 * all the flush-and-invalidate requests.  This does not mean
-	 * that the flushed data has reached the memory controller yet,
-	 * but it does mean the home cache is processing the flushes.
-	 */
-	__insn_mf();
-
-	/*
-	 * Issue a load to the last cache line, which can't complete
-	 * until all the previously-issued flushes to the same memory
-	 * controller have also completed.  If we weren't striping
-	 * memory, that one load would be sufficient, but since we may
-	 * be, we also need to back up to the last load issued to
-	 * another memory controller, which would be the point where
-	 * we crossed an 8KB boundary (the granularity of striping
-	 * across memory controllers).  Keep backing up and doing this
-	 * until we are before the beginning of the buffer, or have
-	 * hit all the controllers.
-	 */
-	for (i = 0, p = (char *)buffer + size - 1;
-	     i < (1 << CHIP_LOG_NUM_MSHIMS()) && p >= (char *)buffer;
-	     ++i) {
-		const unsigned long STRIPE_WIDTH = 8192;
-
-		/* Force a load instruction to issue. */
-		*(volatile char *)p;
-
-		/* Jump to end of previous stripe. */
-		p -= STRIPE_WIDTH;
-		p = (char *)((unsigned long)p | (STRIPE_WIDTH - 1));
-	}
-
-	/* Wait for the loads (and thus flushes) to have completed. */
-	__insn_mf();
-}
+void finv_buffer_remote(void *buffer, size_t size, int hfh);
 
 #endif /* _ASM_TILE_CACHEFLUSH_H */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/cache.h linux-libre-2.6.39-gnu/arch/tile/include/asm/cache.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/cache.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/cache.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 #define INTERNODE_CACHE_BYTES   L2_CACHE_BYTES
 
 /* Group together read-mostly things to avoid cache false sharing */
-#define __read_mostly __attribute__((__section__(".data.read_mostly")))
+#define __read_mostly __attribute__((__section__(".data..read_mostly")))
 
 /*
  * Attribute for data that is kept read/write coherent until the end of
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/edac.h linux-libre-2.6.39-gnu/arch/tile/include/asm/edac.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/edac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/edac.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2011 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+#ifndef _ASM_TILE_EDAC_H
+#define _ASM_TILE_EDAC_H
+
+/* ECC atomic, DMA, SMP and interrupt safe scrub function */
+
+static inline void atomic_scrub(void *va, u32 size)
+{
+	/*
+	 * These is nothing to be done here because CE is
+	 * corrected by the mshim.
+	 */
+	return;
+}
+
+#endif /* _ASM_TILE_EDAC_H */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/futex.h linux-libre-2.6.39-gnu/arch/tile/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,16 +29,16 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 
-extern struct __get_user futex_set(int __user *v, int i);
-extern struct __get_user futex_add(int __user *v, int n);
-extern struct __get_user futex_or(int __user *v, int n);
-extern struct __get_user futex_andn(int __user *v, int n);
-extern struct __get_user futex_cmpxchg(int __user *v, int o, int n);
+extern struct __get_user futex_set(u32 __user *v, int i);
+extern struct __get_user futex_add(u32 __user *v, int n);
+extern struct __get_user futex_or(u32 __user *v, int n);
+extern struct __get_user futex_andn(u32 __user *v, int n);
+extern struct __get_user futex_cmpxchg(u32 __user *v, int o, int n);
 
 #ifndef __tilegx__
-extern struct __get_user futex_xor(int __user *v, int n);
+extern struct __get_user futex_xor(u32 __user *v, int n);
 #else
-static inline struct __get_user futex_xor(int __user *uaddr, int n)
+static inline struct __get_user futex_xor(u32 __user *uaddr, int n)
 {
 	struct __get_user asm_ret = __get_user_4(uaddr);
 	if (!asm_ret.err) {
@@ -53,7 +53,7 @@
 }
 #endif
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -65,7 +65,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	pagefault_disable();
@@ -119,16 +119,17 @@
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
 	struct __get_user asm_ret;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 	asm_ret = futex_cmpxchg(uaddr, oldval, newval);
-	return asm_ret.err ? asm_ret.err : asm_ret.val;
+	*uval = asm_ret.val;
+	return asm_ret.err;
 }
 
 #ifndef __tilegx__
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/hugetlb.h linux-libre-2.6.39-gnu/arch/tile/include/asm/hugetlb.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/hugetlb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/hugetlb.h	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
 				   pte_t *ptep, pte_t pte)
 {
-	set_pte_order(ptep, pte, HUGETLB_PAGE_ORDER);
+	set_pte(ptep, pte);
 }
 
 static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/irqflags.h linux-libre-2.6.39-gnu/arch/tile/include/asm/irqflags.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/irqflags.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/irqflags.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,8 @@
 #include <arch/interrupts.h>
 #include <arch/chip.h>
 
+#if !defined(__tilegx__) && defined(__ASSEMBLY__)
+
 /*
  * The set of interrupts we want to allow when interrupts are nominally
  * disabled.  The remainder are effectively "NMI" interrupts from
@@ -25,6 +27,16 @@
  * interrupts (aka "non-queued") are not blocked by the mask in any case.
  */
 #if CHIP_HAS_AUX_PERF_COUNTERS()
+#define LINUX_MASKABLE_INTERRUPTS_HI \
+       (~(INT_MASK_HI(INT_PERF_COUNT) | INT_MASK_HI(INT_AUX_PERF_COUNT)))
+#else
+#define LINUX_MASKABLE_INTERRUPTS_HI \
+       (~(INT_MASK_HI(INT_PERF_COUNT)))
+#endif
+
+#else
+
+#if CHIP_HAS_AUX_PERF_COUNTERS()
 #define LINUX_MASKABLE_INTERRUPTS \
 	(~(INT_MASK(INT_PERF_COUNT) | INT_MASK(INT_AUX_PERF_COUNT)))
 #else
@@ -32,6 +44,8 @@
 	(~(INT_MASK(INT_PERF_COUNT)))
 #endif
 
+#endif
+
 #ifndef __ASSEMBLY__
 
 /* NOTE: we can't include <linux/percpu.h> due to #include dependencies. */
@@ -224,11 +238,11 @@
 #define IRQ_DISABLE(tmp0, tmp1)					\
 	{							\
 	 movei  tmp0, -1;					\
-	 moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS)		\
+	 moveli tmp1, lo16(LINUX_MASKABLE_INTERRUPTS_HI)	\
 	};							\
 	{							\
 	 mtspr  SPR_INTERRUPT_MASK_SET_K_0, tmp0;		\
-	 auli   tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS)	\
+	 auli   tmp1, tmp1, ha16(LINUX_MASKABLE_INTERRUPTS_HI)	\
 	};							\
 	mtspr   SPR_INTERRUPT_MASK_SET_K_1, tmp1
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/Kbuild linux-libre-2.6.39-gnu/arch/tile/include/asm/Kbuild
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/Kbuild	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/Kbuild	2011-05-19 00:06:34.000000000 -0400
@@ -1,3 +1,4 @@
 include include/asm-generic/Kbuild.asm
 
 header-y += ucontext.h
+header-y += hardwall.h
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/page.h linux-libre-2.6.39-gnu/arch/tile/include/asm/page.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/page.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/page.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,10 +16,11 @@
 #define _ASM_TILE_PAGE_H
 
 #include <linux/const.h>
+#include <hv/pagesize.h>
 
 /* PAGE_SHIFT and HPAGE_SHIFT determine the page sizes. */
-#define PAGE_SHIFT	16
-#define HPAGE_SHIFT	24
+#define PAGE_SHIFT	HV_LOG2_PAGE_SIZE_SMALL
+#define HPAGE_SHIFT	HV_LOG2_PAGE_SIZE_LARGE
 
 #define PAGE_SIZE	(_AC(1, UL) << PAGE_SHIFT)
 #define HPAGE_SIZE	(_AC(1, UL) << HPAGE_SHIFT)
@@ -29,25 +30,18 @@
 
 #ifdef __KERNEL__
 
-#include <hv/hypervisor.h>
-#include <arch/chip.h>
-
 /*
- * The {,H}PAGE_SHIFT values must match the HV_LOG2_PAGE_SIZE_xxx
- * definitions in <hv/hypervisor.h>.  We validate this at build time
- * here, and again at runtime during early boot.  We provide a
- * separate definition since userspace doesn't have <hv/hypervisor.h>.
- *
- * Be careful to distinguish PAGE_SHIFT from HV_PTE_INDEX_PFN, since
- * they are the same on i386 but not TILE.
+ * If the Kconfig doesn't specify, set a maximum zone order that
+ * is enough so that we can create huge pages from small pages given
+ * the respective sizes of the two page types.  See <linux/mmzone.h>.
  */
-#if HV_LOG2_PAGE_SIZE_SMALL != PAGE_SHIFT
-# error Small page size mismatch in Linux
-#endif
-#if HV_LOG2_PAGE_SIZE_LARGE != HPAGE_SHIFT
-# error Huge page size mismatch in Linux
+#ifndef CONFIG_FORCE_MAX_ZONEORDER
+#define CONFIG_FORCE_MAX_ZONEORDER (HPAGE_SHIFT - PAGE_SHIFT + 1)
 #endif
 
+#include <hv/hypervisor.h>
+#include <arch/chip.h>
+
 #ifndef __ASSEMBLY__
 
 #include <linux/types.h>
@@ -81,12 +75,6 @@
  * Hypervisor page tables are made of the same basic structure.
  */
 
-typedef __u64 pteval_t;
-typedef __u64 pmdval_t;
-typedef __u64 pudval_t;
-typedef __u64 pgdval_t;
-typedef __u64 pgprotval_t;
-
 typedef HV_PTE pte_t;
 typedef HV_PTE pgd_t;
 typedef HV_PTE pgprot_t;
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/pgalloc.h linux-libre-2.6.39-gnu/arch/tile/include/asm/pgalloc.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/pgalloc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/pgalloc.h	2011-05-19 00:06:34.000000000 -0400
@@ -41,9 +41,9 @@
 static inline void set_pmd(pmd_t *pmdp, pmd_t pmd)
 {
 #ifdef CONFIG_64BIT
-	set_pte_order(pmdp, pmd, L2_USER_PGTABLE_ORDER);
+	set_pte(pmdp, pmd);
 #else
-	set_pte_order(&pmdp->pud.pgd, pmd.pud.pgd, L2_USER_PGTABLE_ORDER);
+	set_pte(&pmdp->pud.pgd, pmd.pud.pgd);
 #endif
 }
 
@@ -100,6 +100,9 @@
 /* During init, we can shatter kernel huge pages if needed. */
 void shatter_pmd(pmd_t *pmd);
 
+/* After init, a more complex technique is required. */
+void shatter_huge_page(unsigned long addr);
+
 #ifdef __tilegx__
 /* We share a single page allocator for both L1 and L2 page tables. */
 #if HV_L1_SIZE != HV_L2_SIZE
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/pgtable_32.h linux-libre-2.6.39-gnu/arch/tile/include/asm/pgtable_32.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/pgtable_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/pgtable_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 #define PGDIR_SIZE	HV_PAGE_SIZE_LARGE
 #define PGDIR_MASK	(~(PGDIR_SIZE-1))
 #define PTRS_PER_PGD	(1 << (32 - PGDIR_SHIFT))
+#define SIZEOF_PGD	(PTRS_PER_PGD * sizeof(pgd_t))
 
 /*
  * The level-2 index is defined by the difference between the huge
@@ -33,6 +34,7 @@
  * this nomenclature is somewhat confusing.
  */
 #define PTRS_PER_PTE (1 << (HV_LOG2_PAGE_SIZE_LARGE - HV_LOG2_PAGE_SIZE_SMALL))
+#define SIZEOF_PTE	(PTRS_PER_PTE * sizeof(pte_t))
 
 #ifndef __ASSEMBLY__
 
@@ -94,7 +96,6 @@
  */
 #define __HAVE_ARCH_PTEP_TEST_AND_CLEAR_YOUNG
 #define __HAVE_ARCH_PTEP_SET_WRPROTECT
-#define __HAVE_ARCH_PTEP_GET_AND_CLEAR
 
 extern int ptep_test_and_clear_young(struct vm_area_struct *,
 				     unsigned long addr, pte_t *);
@@ -110,6 +111,11 @@
 	return pte;
 }
 
+static inline void __set_pmd(pmd_t *pmdp, pmd_t pmdval)
+{
+	set_pte(&pmdp->pud.pgd, pmdval.pud.pgd);
+}
+
 /* Create a pmd from a PTFN. */
 static inline pmd_t ptfn_pmd(unsigned long ptfn, pgprot_t prot)
 {
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/tile/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/pgtable.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -233,15 +233,23 @@
 #define pgd_ERROR(e) \
 	pr_err("%s:%d: bad pgd 0x%016llx.\n", __FILE__, __LINE__, pgd_val(e))
 
+/* Return PA and protection info for a given kernel VA. */
+int va_to_cpa_and_pte(void *va, phys_addr_t *cpa, pte_t *pte);
+
 /*
- * set_pte_order() sets the given PTE and also sanity-checks the
+ * __set_pte() ensures we write the 64-bit PTE with 32-bit words in
+ * the right order on 32-bit platforms and also allows us to write
+ * hooks to check valid PTEs, etc., if we want.
+ */
+void __set_pte(pte_t *ptep, pte_t pte);
+
+/*
+ * set_pte() sets the given PTE and also sanity-checks the
  * requested PTE against the page homecaching.  Unspecified parts
  * of the PTE are filled in when it is written to memory, i.e. all
  * caching attributes if "!forcecache", or the home cpu if "anyhome".
  */
-extern void set_pte_order(pte_t *ptep, pte_t pte, int order);
-
-#define set_pte(ptep, pteval) set_pte_order(ptep, pteval, 0)
+extern void set_pte(pte_t *ptep, pte_t pte);
 #define set_pte_at(mm, addr, ptep, pteval) set_pte(ptep, pteval)
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
 
@@ -293,21 +301,6 @@
 #define __swp_entry_to_pte(swp)	((pte_t) { (((long long) ((swp).val)) << 32) })
 
 /*
- * clone_pgd_range(pgd_t *dst, pgd_t *src, int count);
- *
- *  dst - pointer to pgd range anwhere on a pgd page
- *  src - ""
- *  count - the number of pgds to copy.
- *
- * dst and src can be on the same page, but the range must not overlap,
- * and must not cross a page boundary.
- */
-static inline void clone_pgd_range(pgd_t *dst, pgd_t *src, int count)
-{
-       memcpy(dst, src, count * sizeof(pgd_t));
-}
-
-/*
  * Conversion functions: convert a page and protection to a page entry,
  * and a page entry and page directory to the page they refer to.
  */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/processor.h linux-libre-2.6.39-gnu/arch/tile/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -269,7 +269,6 @@
 /* Data on which physical memory controller corresponds to which NUMA node. */
 extern int node_controller[];
 
-
 /* Do we dump information to the console when a user application crashes? */
 extern int show_crashinfo;
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/tile/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -141,6 +141,9 @@
 /* Single-step the instruction at regs->pc */
 extern void single_step_once(struct pt_regs *regs);
 
+/* Clean up after execve(). */
+extern void single_step_execve(void);
+
 struct task_struct;
 
 extern void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs,
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/spinlock_32.h linux-libre-2.6.39-gnu/arch/tile/include/asm/spinlock_32.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/spinlock_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/spinlock_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -78,13 +78,6 @@
 #define _RD_COUNT_SHIFT 24
 #define _RD_COUNT_WIDTH 8
 
-/* Internal functions; do not use. */
-void arch_read_lock_slow(arch_rwlock_t *, u32);
-int arch_read_trylock_slow(arch_rwlock_t *);
-void arch_read_unlock_slow(arch_rwlock_t *);
-void arch_write_lock_slow(arch_rwlock_t *, u32);
-void arch_write_unlock_slow(arch_rwlock_t *, u32);
-
 /**
  * arch_read_can_lock() - would read_trylock() succeed?
  */
@@ -104,94 +97,32 @@
 /**
  * arch_read_lock() - acquire a read lock.
  */
-static inline void arch_read_lock(arch_rwlock_t *rwlock)
-{
-	u32 val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val << _RD_COUNT_WIDTH)) {
-		arch_read_lock_slow(rwlock, val);
-		return;
-	}
-	rwlock->lock = val + (1 << _RD_COUNT_SHIFT);
-}
+void arch_read_lock(arch_rwlock_t *rwlock);
 
 /**
- * arch_read_lock() - acquire a write lock.
+ * arch_write_lock() - acquire a write lock.
  */
-static inline void arch_write_lock(arch_rwlock_t *rwlock)
-{
-	u32 val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val != 0)) {
-		arch_write_lock_slow(rwlock, val);
-		return;
-	}
-	rwlock->lock = 1 << _WR_NEXT_SHIFT;
-}
+void arch_write_lock(arch_rwlock_t *rwlock);
 
 /**
  * arch_read_trylock() - try to acquire a read lock.
  */
-static inline int arch_read_trylock(arch_rwlock_t *rwlock)
-{
-	int locked;
-	u32 val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val & 1))
-		return arch_read_trylock_slow(rwlock);
-	locked = (val << _RD_COUNT_WIDTH) == 0;
-	rwlock->lock = val + (locked << _RD_COUNT_SHIFT);
-	return locked;
-}
+int arch_read_trylock(arch_rwlock_t *rwlock);
 
 /**
  * arch_write_trylock() - try to acquire a write lock.
  */
-static inline int arch_write_trylock(arch_rwlock_t *rwlock)
-{
-	u32 val = __insn_tns((int *)&rwlock->lock);
-
-	/*
-	 * If a tns is in progress, or there's a waiting or active locker,
-	 * or active readers, we can't take the lock, so give up.
-	 */
-	if (unlikely(val != 0)) {
-		if (!(val & 1))
-			rwlock->lock = val;
-		return 0;
-	}
-
-	/* Set the "next" field to mark it locked. */
-	rwlock->lock = 1 << _WR_NEXT_SHIFT;
-	return 1;
-}
+int arch_write_trylock(arch_rwlock_t *rwlock);
 
 /**
  * arch_read_unlock() - release a read lock.
  */
-static inline void arch_read_unlock(arch_rwlock_t *rwlock)
-{
-	u32 val;
-	mb();  /* guarantee anything modified under the lock is visible */
-	val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val & 1)) {
-		arch_read_unlock_slow(rwlock);
-		return;
-	}
-	rwlock->lock = val - (1 << _RD_COUNT_SHIFT);
-}
+void arch_read_unlock(arch_rwlock_t *rwlock);
 
 /**
  * arch_write_unlock() - release a write lock.
  */
-static inline void arch_write_unlock(arch_rwlock_t *rwlock)
-{
-	u32 val;
-	mb();  /* guarantee anything modified under the lock is visible */
-	val = __insn_tns((int *)&rwlock->lock);
-	if (unlikely(val != (1 << _WR_NEXT_SHIFT))) {
-		arch_write_unlock_slow(rwlock, val);
-		return;
-	}
-	rwlock->lock = 0;
-}
+void arch_write_unlock(arch_rwlock_t *rwlock);
 
 #define arch_read_lock_flags(lock, flags) arch_read_lock(lock)
 #define arch_write_lock_flags(lock, flags) arch_write_lock(lock)
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/stack.h linux-libre-2.6.39-gnu/arch/tile/include/asm/stack.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/stack.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/stack.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,13 +18,14 @@
 #include <linux/types.h>
 #include <linux/sched.h>
 #include <asm/backtrace.h>
+#include <asm/page.h>
 #include <hv/hypervisor.h>
 
 /* Everything we need to keep track of a backtrace iteration */
 struct KBacktraceIterator {
 	BacktraceIterator it;
 	struct task_struct *task;     /* task we are backtracing */
-	HV_PTE *pgtable;	      /* page table for user space access */
+	pte_t *pgtable;		      /* page table for user space access */
 	int end;		      /* iteration complete. */
 	int new_context;              /* new context is starting */
 	int profile;                  /* profiling, so stop on async intrpt */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/system.h linux-libre-2.6.39-gnu/arch/tile/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -90,7 +90,24 @@
 #endif
 
 #if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-int __mb_incoherent(void);  /* Helper routine for mb_incoherent(). */
+#include <hv/syscall_public.h>
+/*
+ * Issue an uncacheable load to each memory controller, then
+ * wait until those loads have completed.
+ */
+static inline void __mb_incoherent(void)
+{
+	long clobber_r10;
+	asm volatile("swint2"
+		     : "=R10" (clobber_r10)
+		     : "R10" (HV_SYS_fence_incoherent)
+		     : "r0", "r1", "r2", "r3", "r4",
+		       "r5", "r6", "r7", "r8", "r9",
+		       "r11", "r12", "r13", "r14",
+		       "r15", "r16", "r17", "r18", "r19",
+		       "r20", "r21", "r22", "r23", "r24",
+		       "r25", "r26", "r27", "r28", "r29");
+}
 #endif
 
 /* Fence to guarantee visibility of stores to incoherent memory. */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/tile/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -68,6 +68,7 @@
 #else
 #define THREAD_SIZE_ORDER (0)
 #endif
+#define THREAD_SIZE_PAGES (1 << THREAD_SIZE_ORDER)
 
 #define THREAD_SIZE (PAGE_SIZE << THREAD_SIZE_ORDER)
 #define LOG2_THREAD_SIZE (PAGE_SHIFT + THREAD_SIZE_ORDER)
@@ -83,7 +84,7 @@
   ((struct thread_info *)(stack_pointer & -THREAD_SIZE))
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
-extern struct thread_info *alloc_thread_info(struct task_struct *task);
+extern struct thread_info *alloc_thread_info_node(struct task_struct *task, int node);
 extern void free_thread_info(struct thread_info *info);
 
 /* Sit on a nap instruction until interrupted. */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/asm/timex.h linux-libre-2.6.39-gnu/arch/tile/include/asm/timex.h
--- linux-libre-2.6.38-gnu/arch/tile/include/asm/timex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/asm/timex.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,9 @@
 
 cycles_t get_clock_rate(void);
 
+/* Convert nanoseconds to core clock cycles. */
+cycles_t ns2cycles(unsigned long nsecs);
+
 /* Called at cpu initialization to set some low-level constants. */
 void setup_clock(void);
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/hv/drv_mshim_intf.h linux-libre-2.6.39-gnu/arch/tile/include/hv/drv_mshim_intf.h
--- linux-libre-2.6.38-gnu/arch/tile/include/hv/drv_mshim_intf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/tile/include/hv/drv_mshim_intf.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2011 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ */
+
+/**
+ * @file drv_mshim_intf.h
+ * Interface definitions for the Linux EDAC memory controller driver.
+ */
+
+#ifndef _SYS_HV_INCLUDE_DRV_MSHIM_INTF_H
+#define _SYS_HV_INCLUDE_DRV_MSHIM_INTF_H
+
+/** Number of memory controllers in the public API. */
+#define TILE_MAX_MSHIMS 4
+
+/** Memory info under each memory controller. */
+struct mshim_mem_info
+{
+  uint64_t mem_size;     /**< Total memory size in bytes. */
+  uint8_t mem_type;      /**< Memory type, DDR2 or DDR3. */
+  uint8_t mem_ecc;       /**< Memory supports ECC. */
+};
+
+/**
+ * DIMM error structure.
+ * For now, only correctable errors are counted and the mshim doesn't record
+ * the error PA. HV takes panic upon uncorrectable errors.
+ */
+struct mshim_mem_error
+{
+  uint32_t sbe_count;     /**< Number of single-bit errors. */
+};
+
+/** Read this offset to get the memory info per mshim. */
+#define MSHIM_MEM_INFO_OFF 0x100
+
+/** Read this offset to check DIMM error. */
+#define MSHIM_MEM_ERROR_OFF 0x200
+
+#endif /* _SYS_HV_INCLUDE_DRV_MSHIM_INTF_H */
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/hv/drv_xgbe_intf.h linux-libre-2.6.39-gnu/arch/tile/include/hv/drv_xgbe_intf.h
--- linux-libre-2.6.38-gnu/arch/tile/include/hv/drv_xgbe_intf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/hv/drv_xgbe_intf.h	2011-05-19 00:06:34.000000000 -0400
@@ -319,7 +319,7 @@
  *         is an error code, or zero if no error.  The val0 member is the
  *         updated value of seqno; it has been incremented by 1 for each
  *         packet sent.  That increment may be less than nentries if an
- *         error occured, or if some of the entries in the vector contain
+ *         error occurred, or if some of the entries in the vector contain
  *         handles equal to NETIO_PKT_HANDLE_NONE.  The val1 member is the
  *         updated value of nentries; it has been decremented by 1 for each
  *         vector entry processed.  Again, that decrement may be less than
diff -druN linux-libre-2.6.38-gnu/arch/tile/include/hv/hypervisor.h linux-libre-2.6.39-gnu/arch/tile/include/hv/hypervisor.h
--- linux-libre-2.6.38-gnu/arch/tile/include/hv/hypervisor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/include/hv/hypervisor.h	2011-05-19 00:06:34.000000000 -0400
@@ -338,9 +338,10 @@
 #define HV_ENOTREADY   -812  /**< Device not ready */
 #define HV_EIO         -813  /**< I/O error */
 #define HV_ENOMEM      -814  /**< Out of memory */
+#define HV_EAGAIN      -815  /**< Try again */
 
 #define HV_ERR_MAX     -801  /**< Largest HV error code */
-#define HV_ERR_MIN     -814  /**< Smallest HV error code */
+#define HV_ERR_MIN     -815  /**< Smallest HV error code */
 
 #ifndef __ASSEMBLER__
 
@@ -867,6 +868,43 @@
  */
 HV_PhysAddrRange hv_inquire_physical(int idx);
 
+/** Possible DIMM types. */
+typedef enum
+{
+  NO_DIMM                    = 0,  /**< No DIMM */
+  DDR2                       = 1,  /**< DDR2 */
+  DDR3                       = 2   /**< DDR3 */
+} HV_DIMM_Type;
+
+#ifdef __tilegx__
+
+/** Log2 of minimum DIMM bytes supported by the memory controller. */
+#define HV_MSH_MIN_DIMM_SIZE_SHIFT 29
+
+/** Max number of DIMMs contained by one memory controller. */
+#define HV_MSH_MAX_DIMMS 8
+
+#else
+
+/** Log2 of minimum DIMM bytes supported by the memory controller. */
+#define HV_MSH_MIN_DIMM_SIZE_SHIFT 26
+
+/** Max number of DIMMs contained by one memory controller. */
+#define HV_MSH_MAX_DIMMS 2
+
+#endif
+
+/** Number of bits to right-shift to get the DIMM type. */
+#define HV_DIMM_TYPE_SHIFT 0
+
+/** Bits to mask to get the DIMM type. */
+#define HV_DIMM_TYPE_MASK 0xf
+
+/** Number of bits to right-shift to get the DIMM size. */
+#define HV_DIMM_SIZE_SHIFT 4
+
+/** Bits to mask to get the DIMM size. */
+#define HV_DIMM_SIZE_MASK 0xf
 
 /** Memory controller information. */
 typedef struct
@@ -964,6 +1002,11 @@
 
 /** Waits for at least the specified number of nanoseconds then returns.
  *
+ * NOTE: this deprecated function currently assumes a 750 MHz clock,
+ * and is thus not generally suitable for use.  New code should call
+ * hv_sysconf(HV_SYSCONF_CPU_SPEED), compute a cycle count to wait for,
+ * and delay by looping while checking the cycle counter SPR.
+ *
  * @param nanosecs The number of nanoseconds to sleep.
  */
 void hv_nanosleep(int nanosecs);
@@ -1038,6 +1081,7 @@
  *  downcall:
  *
  *  INT_MESSAGE_RCV_DWNCL   (hypervisor message available)
+ *  INT_DEV_INTR_DWNCL      (device interrupt)
  *  INT_DMATLB_MISS_DWNCL   (DMA TLB miss)
  *  INT_SNITLB_MISS_DWNCL   (SNI TLB miss)
  *  INT_DMATLB_ACCESS_DWNCL (DMA TLB access violation)
@@ -1296,7 +1340,7 @@
  *  this operation.  If any permanent delivery errors were encountered,
  *  the routine returns HV_ERECIP.  In the event of permanent delivery
  *  errors, it may be the case that delivery was not attempted to all
- *  recipients; if any messages were succesfully delivered, however,
+ *  recipients; if any messages were successfully delivered, however,
  *  recipients' state values will be updated appropriately.
  *
  *  It is explicitly legal to specify a recipient structure whose state
@@ -1315,7 +1359,7 @@
  *  never call hv_receive_message, or could register a different state
  *  buffer, losing the message.
  *
- *  Specifiying the same recipient more than once in the recipient list
+ *  Specifying the same recipient more than once in the recipient list
  *  is an error, which will not result in an error return but which may
  *  or may not result in more than one message being delivered to the
  *  recipient tile.
diff -druN linux-libre-2.6.38-gnu/arch/tile/Kconfig linux-libre-2.6.39-gnu/arch/tile/Kconfig
--- linux-libre-2.6.38-gnu/arch/tile/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 # For a description of the syntax of this configuration file,
-# see Documentation/kbuild/config-language.txt.
+# see Documentation/kbuild/kconfig-language.txt.
 
 config TILE
 	def_bool y
@@ -11,17 +11,18 @@
 	select HAVE_GENERIC_HARDIRQS
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_IRQ_SHOW
 
 # FIXME: investigate whether we need/want these options.
 #	select HAVE_IOREMAP_PROT
-#       select HAVE_OPTPROBES
-#       select HAVE_REGS_AND_STACK_ACCESS_API
-#       select HAVE_HW_BREAKPOINT
-#       select PERF_EVENTS
-#       select HAVE_USER_RETURN_NOTIFIER
-#       config NO_BOOTMEM
-#       config ARCH_SUPPORTS_DEBUG_PAGEALLOC
-#       config HUGETLB_PAGE_SIZE_VARIABLE
+#	select HAVE_OPTPROBES
+#	select HAVE_REGS_AND_STACK_ACCESS_API
+#	select HAVE_HW_BREAKPOINT
+#	select PERF_EVENTS
+#	select HAVE_USER_RETURN_NOTIFIER
+#	config NO_BOOTMEM
+#	config ARCH_SUPPORTS_DEBUG_PAGEALLOC
+#	config HUGETLB_PAGE_SIZE_VARIABLE
 
 config MMU
 	def_bool y
@@ -39,7 +40,7 @@
 	def_bool y
 
 config NEED_PER_CPU_PAGE_FIRST_CHUNK
-        def_bool y
+	def_bool y
 
 config SYS_SUPPORTS_HUGETLBFS
 	def_bool y
@@ -50,7 +51,7 @@
 config GENERIC_CLOCKEVENTS
 	def_bool y
 
-# FIXME: tilegx can implement a more efficent rwsem.
+# FIXME: tilegx can implement a more efficient rwsem.
 config RWSEM_GENERIC_SPINLOCK
 	def_bool y
 
@@ -201,12 +202,6 @@
 	  By default, 2, i.e. 2^2 == 4 DDR2 controllers.
 	  In a system with more controllers, this value should be raised.
 
-# Need 16MB areas to enable hugetlb
-# See build-time check in arch/tile/mm/init.c.
-config FORCE_MAX_ZONEORDER
-	int
-	default 9
-
 choice
 	depends on !TILEGX
 	prompt "Memory split" if EXPERT
@@ -233,8 +228,12 @@
 		bool "3.5G/0.5G user/kernel split"
 	config VMSPLIT_3G
 		bool "3G/1G user/kernel split"
-	config VMSPLIT_3G_OPT
-		bool "3G/1G user/kernel split (for full 1G low memory)"
+	config VMSPLIT_2_75G
+		bool "2.75G/1.25G user/kernel split (for full 1G low memory)"
+	config VMSPLIT_2_5G
+		bool "2.5G/1.5G user/kernel split"
+	config VMSPLIT_2_25G
+		bool "2.25G/1.75G user/kernel split"
 	config VMSPLIT_2G
 		bool "2G/2G user/kernel split"
 	config VMSPLIT_1G
@@ -245,7 +244,9 @@
 	hex
 	default 0xF0000000 if VMSPLIT_3_75G
 	default 0xE0000000 if VMSPLIT_3_5G
-	default 0xB0000000 if VMSPLIT_3G_OPT
+	default 0xB0000000 if VMSPLIT_2_75G
+	default 0xA0000000 if VMSPLIT_2_5G
+	default 0x90000000 if VMSPLIT_2_25G
 	default 0x80000000 if VMSPLIT_2G
 	default 0x40000000 if VMSPLIT_1G
 	default 0xC0000000
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/entry.S linux-libre-2.6.39-gnu/arch/tile/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/tile/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -38,12 +38,6 @@
 	jrp lr
 	STD_ENDPROC(kernel_execve)
 
-/* Delay a fixed number of cycles. */
-STD_ENTRY(__delay)
-	{ addi r0, r0, -1; bnzt r0, . }
-	jrp lr
-	STD_ENDPROC(__delay)
-
 /*
  * We don't run this function directly, but instead copy it to a page
  * we map into every user process.  See vdso_setup().
@@ -97,23 +91,17 @@
 
 /*
  * Enable interrupts racelessly and then nap until interrupted.
+ * Architecturally, we are guaranteed that enabling interrupts via
+ * mtspr to INTERRUPT_CRITICAL_SECTION only interrupts at the next PC.
  * This function's _cpu_idle_nap address is special; see intvec.S.
  * When interrupted at _cpu_idle_nap, we bump the PC forward 8, and
  * as a result return to the function that called _cpu_idle().
  */
 STD_ENTRY(_cpu_idle)
-	{
-	 lnk r0
-	 movei r1, KERNEL_PL
-	}
-	{
-	 addli r0, r0, _cpu_idle_nap - .
-	 mtspr INTERRUPT_CRITICAL_SECTION, r1
-	}
+	movei r1, 1
+	mtspr INTERRUPT_CRITICAL_SECTION, r1
 	IRQ_ENABLE(r2, r3)             /* unmask, but still with ICS set */
-	mtspr SPR_EX_CONTEXT_K_1, r1   /* Kernel PL, ICS clear */
-	mtspr SPR_EX_CONTEXT_K_0, r0
-	iret
+	mtspr INTERRUPT_CRITICAL_SECTION, zero
 	.global _cpu_idle_nap
 _cpu_idle_nap:
 	nap
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/head_32.S linux-libre-2.6.39-gnu/arch/tile/kernel/head_32.S
--- linux-libre-2.6.38-gnu/arch/tile/kernel/head_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/head_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,7 @@
 	}
 	ENDPROC(_start)
 
-.section ".bss.page_aligned","w"
+__PAGE_ALIGNED_BSS
 	.align PAGE_SIZE
 ENTRY(empty_zero_page)
 	.fill PAGE_SIZE,1,0
@@ -145,10 +145,10 @@
 	.endif
 	.word HV_PTE_PAGE | HV_PTE_DIRTY | HV_PTE_PRESENT | HV_PTE_ACCESSED | \
 	      (HV_PTE_MODE_CACHE_NO_L3 << HV_PTE_INDEX_MODE)
-	.word (\bits1) | (HV_CPA_TO_PFN(\cpa) << HV_PTE_INDEX_PFN)
+	.word (\bits1) | (HV_CPA_TO_PFN(\cpa) << (HV_PTE_INDEX_PFN - 32))
 	.endm
 
-.section ".data.page_aligned","wa"
+__PAGE_ALIGNED_DATA
 	.align PAGE_SIZE
 ENTRY(swapper_pg_dir)
 	/*
@@ -158,12 +158,14 @@
 	 */
 	.set addr, 0
 	.rept (MEM_USER_INTRPT - PAGE_OFFSET) >> PGDIR_SHIFT
-	PTE addr + PAGE_OFFSET, addr, HV_PTE_READABLE | HV_PTE_WRITABLE
+	PTE addr + PAGE_OFFSET, addr, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
+				      (1 << (HV_PTE_INDEX_WRITABLE - 32))
 	.set addr, addr + PGDIR_SIZE
 	.endr
 
 	/* The true text VAs are mapped as VA = PA + MEM_SV_INTRPT */
-	PTE MEM_SV_INTRPT, 0, HV_PTE_READABLE | HV_PTE_EXECUTABLE
+	PTE MEM_SV_INTRPT, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
+			      (1 << (HV_PTE_INDEX_EXECUTABLE - 32))
 	.org swapper_pg_dir + HV_L1_SIZE
 	END(swapper_pg_dir)
 
@@ -176,6 +178,7 @@
 	__INITDATA
 	.align CHIP_L2_LINE_SIZE()
 ENTRY(swapper_pgprot)
-	PTE	0, 0, HV_PTE_READABLE | HV_PTE_WRITABLE, 1
+	PTE	0, 0, (1 << (HV_PTE_INDEX_READABLE - 32)) | \
+		      (1 << (HV_PTE_INDEX_WRITABLE - 32)), 1
 	.align CHIP_L2_LINE_SIZE()
 	END(swapper_pgprot)
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/intvec_32.S linux-libre-2.6.39-gnu/arch/tile/kernel/intvec_32.S
--- linux-libre-2.6.38-gnu/arch/tile/kernel/intvec_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/intvec_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -32,10 +32,6 @@
 # error "No support for kernel preemption currently"
 #endif
 
-#if INT_INTCTRL_K < 32 || INT_INTCTRL_K >= 48
-# error INT_INTCTRL_K coded to set high interrupt mask
-#endif
-
 #define PTREGS_PTR(reg, ptreg) addli reg, sp, C_ABI_SAVE_AREA_SIZE + (ptreg)
 
 #define PTREGS_OFFSET_SYSCALL PTREGS_OFFSET_REG(TREG_SYSCALL_NR)
@@ -1199,46 +1195,6 @@
 	STD_ENDPROC(interrupt_return)
 
 	/*
-	 * This interrupt variant clears the INT_INTCTRL_K interrupt mask bit
-	 * before returning, so we can properly get more downcalls.
-	 */
-	.pushsection .text.handle_interrupt_downcall,"ax"
-handle_interrupt_downcall:
-	finish_interrupt_save handle_interrupt_downcall
-	check_single_stepping normal, .Ldispatch_downcall
-.Ldispatch_downcall:
-
-	/* Clear INTCTRL_K from the set of interrupts we ever enable. */
-	GET_INTERRUPTS_ENABLED_MASK_PTR(r30)
-	{
-	 addi   r30, r30, 4
-	 movei  r31, INT_MASK(INT_INTCTRL_K)
-	}
-	{
-	 lw     r20, r30
-	 nor    r21, r31, zero
-	}
-	and     r20, r20, r21
-	sw      r30, r20
-
-	{
-	 jalr   r0
-	 PTREGS_PTR(r0, PTREGS_OFFSET_BASE)
-	}
-	FEEDBACK_REENTER(handle_interrupt_downcall)
-
-	/* Allow INTCTRL_K to be enabled next time we enable interrupts. */
-	lw      r20, r30
-	or      r20, r20, r31
-	sw      r30, r20
-
-	{
-	 movei  r30, 0   /* not an NMI */
-	 j      interrupt_return
-	}
-	STD_ENDPROC(handle_interrupt_downcall)
-
-	/*
 	 * Some interrupts don't check for single stepping
 	 */
 	.pushsection .text.handle_interrupt_no_single_step,"ax"
@@ -1600,7 +1556,10 @@
 	.align 64
 	/* Align much later jump on the start of a cache line. */
 #if !ATOMIC_LOCKS_FOUND_VIA_TABLE()
-	nop; nop
+	nop
+#if PAGE_SIZE >= 0x10000
+	nop
+#endif
 #endif
 ENTRY(sys_cmpxchg)
 
@@ -1628,9 +1587,13 @@
 	 * about aliasing among multiple mappings of the same physical page,
 	 * and we ignore the low 3 bits so we have one lock that covers
 	 * both a cmpxchg64() and a cmpxchg() on either its low or high word.
-	 * NOTE: this code must match __atomic_hashed_lock() in lib/atomic.c.
+	 * NOTE: this must match __atomic_hashed_lock() in lib/atomic_32.c.
 	 */
 
+#if (PAGE_OFFSET & 0xffff) != 0
+# error Code here assumes PAGE_OFFSET can be loaded with just hi16()
+#endif
+
 #if ATOMIC_LOCKS_FOUND_VIA_TABLE()
 	{
 	 /* Check for unaligned input. */
@@ -1723,11 +1686,14 @@
 	 lw	r26, r0
 	}
 	{
-	 /* atomic_locks is page aligned so this suffices to get its addr. */
-	 auli	r21, zero, hi16(atomic_locks)
+	 auli	r21, zero, ha16(atomic_locks)
 
 	 bbns   r23, .Lcmpxchg_badaddr
 	}
+#if PAGE_SIZE < 0x10000
+	/* atomic_locks is page-aligned so for big pages we don't need this. */
+	addli   r21, r21, lo16(atomic_locks)
+#endif
 	{
 	 /*
 	  * Insert the hash bits into the page-aligned pointer.
@@ -1762,7 +1728,7 @@
 
 	/*
 	 * Perform the actual cmpxchg or atomic_update.
-	 * Note that __futex_mark_unlocked() in uClibc relies on
+	 * Note that the system <arch/atomic.h> header relies on
 	 * atomic_update() to always perform an "mf", so don't make
 	 * it optional or conditional without modifying that code.
 	 */
@@ -2014,17 +1980,17 @@
 #endif
 	int_hand     INT_INTCTRL_0, INTCTRL_0, bad_intr
 	int_hand     INT_MESSAGE_RCV_DWNCL, MESSAGE_RCV_DWNCL, \
-		     hv_message_intr, handle_interrupt_downcall
+		     hv_message_intr
 	int_hand     INT_DEV_INTR_DWNCL, DEV_INTR_DWNCL, \
-		     tile_dev_intr, handle_interrupt_downcall
+		     tile_dev_intr
 	int_hand     INT_I_ASID, I_ASID, bad_intr
 	int_hand     INT_D_ASID, D_ASID, bad_intr
 	int_hand     INT_DMATLB_MISS_DWNCL, DMATLB_MISS_DWNCL, \
-		     do_page_fault, handle_interrupt_downcall
+		     do_page_fault
 	int_hand     INT_SNITLB_MISS_DWNCL, SNITLB_MISS_DWNCL, \
-		     do_page_fault, handle_interrupt_downcall
+		     do_page_fault
 	int_hand     INT_DMATLB_ACCESS_DWNCL, DMATLB_ACCESS_DWNCL, \
-		     do_page_fault, handle_interrupt_downcall
+		     do_page_fault
 	int_hand     INT_SN_CPL, SN_CPL, bad_intr
 	int_hand     INT_DOUBLE_FAULT, DOUBLE_FAULT, do_trap
 #if CHIP_HAS_AUX_PERF_COUNTERS()
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/irq.c linux-libre-2.6.39-gnu/arch/tile/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -176,43 +176,43 @@
 EXPORT_SYMBOL(disable_percpu_irq);
 
 /* Mask an interrupt. */
-static void tile_irq_chip_mask(unsigned int irq)
+static void tile_irq_chip_mask(struct irq_data *d)
 {
-	mask_irqs(1UL << irq);
+	mask_irqs(1UL << d->irq);
 }
 
 /* Unmask an interrupt. */
-static void tile_irq_chip_unmask(unsigned int irq)
+static void tile_irq_chip_unmask(struct irq_data *d)
 {
-	unmask_irqs(1UL << irq);
+	unmask_irqs(1UL << d->irq);
 }
 
 /*
  * Clear an interrupt before processing it so that any new assertions
  * will trigger another irq.
  */
-static void tile_irq_chip_ack(unsigned int irq)
+static void tile_irq_chip_ack(struct irq_data *d)
 {
-	if ((unsigned long)get_irq_chip_data(irq) != IS_HW_CLEARED)
-		clear_irqs(1UL << irq);
+	if ((unsigned long)irq_data_get_irq_chip_data(d) != IS_HW_CLEARED)
+		clear_irqs(1UL << d->irq);
 }
 
 /*
  * For per-cpu interrupts, we need to avoid unmasking any interrupts
  * that we disabled via disable_percpu_irq().
  */
-static void tile_irq_chip_eoi(unsigned int irq)
+static void tile_irq_chip_eoi(struct irq_data *d)
 {
-	if (!(__get_cpu_var(irq_disable_mask) & (1UL << irq)))
-		unmask_irqs(1UL << irq);
+	if (!(__get_cpu_var(irq_disable_mask) & (1UL << d->irq)))
+		unmask_irqs(1UL << d->irq);
 }
 
 static struct irq_chip tile_irq_chip = {
 	.name = "tile_irq_chip",
-	.ack = tile_irq_chip_ack,
-	.eoi = tile_irq_chip_eoi,
-	.mask = tile_irq_chip_mask,
-	.unmask = tile_irq_chip_unmask,
+	.irq_ack = tile_irq_chip_ack,
+	.irq_eoi = tile_irq_chip_eoi,
+	.irq_mask = tile_irq_chip_mask,
+	.irq_unmask = tile_irq_chip_unmask,
 };
 
 void __init init_IRQ(void)
@@ -241,14 +241,14 @@
 	irq_flow_handler_t handle = handle_level_irq;
 	if (tile_irq_type == TILE_IRQ_PERCPU)
 		handle = handle_percpu_irq;
-	set_irq_chip_and_handler(irq, &tile_irq_chip, handle);
+	irq_set_chip_and_handler(irq, &tile_irq_chip, handle);
 
 	/*
 	 * Flag interrupts that are hardware-cleared so that ack()
 	 * won't clear them.
 	 */
 	if (tile_irq_type == TILE_IRQ_HW_CLEAR)
-		set_irq_chip_data(irq, (void *)IS_HW_CLEARED);
+		irq_set_chip_data(irq, (void *)IS_HW_CLEARED);
 }
 EXPORT_SYMBOL(tile_irq_activate);
 
@@ -262,45 +262,6 @@
  * Generic, controller-independent functions:
  */
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v, j;
-	struct irqaction *action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for (j = 0; j < NR_CPUS; j++)
-			if (cpu_online(j))
-				seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ", i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action = action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	}
-	return 0;
-}
-
 #if CHIP_HAS_IPI()
 int create_irq(void)
 {
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/machine_kexec.c linux-libre-2.6.39-gnu/arch/tile/kernel/machine_kexec.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/machine_kexec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/machine_kexec.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,8 +240,11 @@
 	pte = hv_pte(_PAGE_KERNEL | _PAGE_HUGE_PAGE);
 	pte = hv_pte_set_mode(pte, HV_PTE_MODE_CACHE_NO_L3);
 
-	for (i = 0; i < pgd_index(PAGE_OFFSET); i++)
-		pgtable[i] = pfn_pte(i << (HPAGE_SHIFT - PAGE_SHIFT), pte);
+	for (i = 0; i < pgd_index(PAGE_OFFSET); i++) {
+		unsigned long pfn = i << (HPAGE_SHIFT - PAGE_SHIFT);
+		if (pfn_valid(pfn))
+			__set_pte(&pgtable[i], pfn_pte(pfn, pte));
+	}
 }
 
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/pci.c linux-libre-2.6.39-gnu/arch/tile/kernel/pci.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
  * Initialization flow and process
  * -------------------------------
  *
- * This files containes the routines to search for PCI buses,
+ * This files contains the routines to search for PCI buses,
  * enumerate the buses, and configure any attached devices.
  *
  * There are two entry points here:
@@ -519,7 +519,7 @@
 
 
 /*
- * See tile_cfg_read() for relevent comments.
+ * See tile_cfg_read() for relevant comments.
  * Note that "val" is the value to write, not a pointer to that value.
  */
 static int __devinit tile_cfg_write(struct pci_bus *bus,
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/pci-dma.c linux-libre-2.6.39-gnu/arch/tile/kernel/pci-dma.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/pci-dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/pci-dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,6 +86,21 @@
  * can count on nothing having been touched.
  */
 
+/* Flush a PA range from cache page by page. */
+static void __dma_map_pa_range(dma_addr_t dma_addr, size_t size)
+{
+	struct page *page = pfn_to_page(PFN_DOWN(dma_addr));
+	size_t bytesleft = PAGE_SIZE - (dma_addr & (PAGE_SIZE - 1));
+
+	while ((ssize_t)size > 0) {
+		/* Flush the page. */
+		homecache_flush_cache(page++, 0);
+
+		/* Figure out if we need to continue on the next page. */
+		size -= bytesleft;
+		bytesleft = PAGE_SIZE;
+	}
+}
 
 /*
  * dma_map_single can be passed any memory address, and there appear
@@ -97,26 +112,12 @@
 dma_addr_t dma_map_single(struct device *dev, void *ptr, size_t size,
 	       enum dma_data_direction direction)
 {
-	struct page *page;
-	dma_addr_t dma_addr;
-	int thispage;
+	dma_addr_t dma_addr = __pa(ptr);
 
 	BUG_ON(!valid_dma_direction(direction));
 	WARN_ON(size == 0);
 
-	dma_addr = __pa(ptr);
-
-	/* We might have been handed a buffer that wraps a page boundary */
-	while ((int)size > 0) {
-		/* The amount to flush that's on this page */
-		thispage = PAGE_SIZE - ((unsigned long)ptr & (PAGE_SIZE - 1));
-		thispage = min((int)thispage, (int)size);
-		/* Is this valid for any page we could be handed? */
-		page = pfn_to_page(kaddr_to_pfn(ptr));
-		homecache_flush_cache(page, 0);
-		ptr += thispage;
-		size -= thispage;
-	}
+	__dma_map_pa_range(dma_addr, size);
 
 	return dma_addr;
 }
@@ -140,10 +141,8 @@
 	WARN_ON(nents == 0 || sglist->length == 0);
 
 	for_each_sg(sglist, sg, nents, i) {
-		struct page *page;
 		sg->dma_address = sg_phys(sg);
-		page = pfn_to_page(sg->dma_address >> PAGE_SHIFT);
-		homecache_flush_cache(page, 0);
+		__dma_map_pa_range(sg->dma_address, sg->length);
 	}
 
 	return nents;
@@ -163,6 +162,7 @@
 {
 	BUG_ON(!valid_dma_direction(direction));
 
+	BUG_ON(offset + size > PAGE_SIZE);
 	homecache_flush_cache(page, 0);
 
 	return page_to_pa(page) + offset;
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/process.c linux-libre-2.6.39-gnu/arch/tile/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -109,7 +109,7 @@
 	}
 }
 
-struct thread_info *alloc_thread_info(struct task_struct *task)
+struct thread_info *alloc_thread_info_node(struct task_struct *task, int node)
 {
 	struct page *page;
 	gfp_t flags = GFP_KERNEL;
@@ -118,7 +118,7 @@
 	flags |= __GFP_ZERO;
 #endif
 
-	page = alloc_pages(flags, THREAD_SIZE_ORDER);
+	page = alloc_pages_node(node, flags, THREAD_SIZE_ORDER);
 	if (!page)
 		return NULL;
 
@@ -165,7 +165,7 @@
 		kfree(step_state);
 	}
 
-	free_page((unsigned long)info);
+	free_pages((unsigned long)info, THREAD_SIZE_ORDER);
 }
 
 static void save_arch_state(struct thread_struct *t);
@@ -574,6 +574,8 @@
 		goto out;
 	error = do_execve(filename, argv, envp, regs);
 	putname(filename);
+	if (error == 0)
+		single_step_execve();
 out:
 	return error;
 }
@@ -593,6 +595,8 @@
 		goto out;
 	error = compat_do_execve(filename, argv, envp, regs);
 	putname(filename);
+	if (error == 0)
+		single_step_execve();
 out:
 	return error;
 }
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/setup.c linux-libre-2.6.39-gnu/arch/tile/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,6 +59,8 @@
 unsigned long __initdata node_percpu_pfn[MAX_NUMNODES];
 unsigned long __initdata node_free_pfn[MAX_NUMNODES];
 
+static unsigned long __initdata node_percpu[MAX_NUMNODES];
+
 #ifdef CONFIG_HIGHMEM
 /* Page frame index of end of lowmem on each controller. */
 unsigned long __cpuinitdata node_lowmem_end_pfn[MAX_NUMNODES];
@@ -554,7 +556,6 @@
 		reserve_bootmem(crashk_res.start,
 			crashk_res.end - crashk_res.start + 1, 0);
 #endif
-
 }
 
 void *__init alloc_remap(int nid, unsigned long size)
@@ -568,11 +569,13 @@
 
 static int __init percpu_size(void)
 {
-	int size = ALIGN(__per_cpu_end - __per_cpu_start, PAGE_SIZE);
-#ifdef CONFIG_MODULES
-	if (size < PERCPU_ENOUGH_ROOM)
-		size = PERCPU_ENOUGH_ROOM;
-#endif
+	int size = __per_cpu_end - __per_cpu_start;
+	size += PERCPU_MODULE_RESERVE;
+	size += PERCPU_DYNAMIC_EARLY_SIZE;
+	if (size < PCPU_MIN_UNIT_SIZE)
+		size = PCPU_MIN_UNIT_SIZE;
+	size = roundup(size, PAGE_SIZE);
+
 	/* In several places we assume the per-cpu data fits on a huge page. */
 	BUG_ON(kdata_huge && size > HPAGE_SIZE);
 	return size;
@@ -589,7 +592,6 @@
 static void __init zone_sizes_init(void)
 {
 	unsigned long zones_size[MAX_NR_ZONES] = { 0 };
-	unsigned long node_percpu[MAX_NUMNODES] = { 0 };
 	int size = percpu_size();
 	int num_cpus = smp_height * smp_width;
 	int i;
@@ -674,7 +676,7 @@
 		NODE_DATA(i)->bdata = NODE_DATA(0)->bdata;
 
 		free_area_init_node(i, zones_size, start, NULL);
-		printk(KERN_DEBUG "  DMA zone: %ld per-cpu pages\n",
+		printk(KERN_DEBUG "  Normal zone: %ld per-cpu pages\n",
 		       PFN_UP(node_percpu[i]));
 
 		/* Track the type of memory on each node */
@@ -1312,6 +1314,8 @@
 
 	BUG_ON(size % PAGE_SIZE != 0);
 	pfn_offset[nid] += size / PAGE_SIZE;
+	BUG_ON(node_percpu[nid] < size);
+	node_percpu[nid] -= size;
 	if (percpu_pfn[cpu] == 0)
 		percpu_pfn[cpu] = pfn;
 	return pfn_to_kaddr(pfn);
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/single_step.c linux-libre-2.6.39-gnu/arch/tile/kernel/single_step.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/single_step.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/single_step.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
 	MEMOP_STORE_POSTINCR
 };
 
-static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, int32_t offset)
+static inline tile_bundle_bits set_BrOff_X1(tile_bundle_bits n, s32 offset)
 {
 	tile_bundle_bits result;
 
@@ -254,6 +254,18 @@
 	return bundle;
 }
 
+/*
+ * Called after execve() has started the new image.  This allows us
+ * to reset the info state.  Note that the the mmap'ed memory, if there
+ * was any, has already been unmapped by the exec.
+ */
+void single_step_execve(void)
+{
+	struct thread_info *ti = current_thread_info();
+	kfree(ti->step_state);
+	ti->step_state = NULL;
+}
+
 /**
  * single_step_once() - entry point when single stepping has been triggered.
  * @regs: The machine register state
@@ -373,7 +385,7 @@
 		/* branches */
 		case BRANCH_OPCODE_X1:
 		{
-			int32_t offset = signExtend17(get_BrOff_X1(bundle));
+			s32 offset = signExtend17(get_BrOff_X1(bundle));
 
 			/*
 			 * For branches, we use a rewriting trick to let the
@@ -731,4 +743,9 @@
 	__insn_mtspr(SPR_SINGLE_STEP_EN_K_K, 1 << USER_PL);
 }
 
+void single_step_execve(void)
+{
+	/* Nothing */
+}
+
 #endif /* !__tilegx__ */
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/smp.c linux-libre-2.6.39-gnu/arch/tile/kernel/smp.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,22 @@
 /* Set by smp_send_stop() to avoid recursive panics. */
 static int stopping_cpus;
 
+static void __send_IPI_many(HV_Recipient *recip, int nrecip, int tag)
+{
+	int sent = 0;
+	while (sent < nrecip) {
+		int rc = hv_send_message(recip, nrecip,
+					 (HV_VirtAddr)&tag, sizeof(tag));
+		if (rc < 0) {
+			if (!stopping_cpus)  /* avoid recursive panic */
+				panic("hv_send_message returned %d", rc);
+			break;
+		}
+		WARN_ONCE(rc == 0, "hv_send_message() returned zero\n");
+		sent += rc;
+	}
+}
+
 void send_IPI_single(int cpu, int tag)
 {
 	HV_Recipient recip = {
@@ -43,14 +59,13 @@
 		.x = cpu % smp_width,
 		.state = HV_TO_BE_SENT
 	};
-	int rc = hv_send_message(&recip, 1, (HV_VirtAddr)&tag, sizeof(tag));
-	BUG_ON(rc <= 0);
+	__send_IPI_many(&recip, 1, tag);
 }
 
 void send_IPI_many(const struct cpumask *mask, int tag)
 {
 	HV_Recipient recip[NR_CPUS];
-	int cpu, sent;
+	int cpu;
 	int nrecip = 0;
 	int my_cpu = smp_processor_id();
 	for_each_cpu(cpu, mask) {
@@ -61,17 +76,7 @@
 		r->x = cpu % smp_width;
 		r->state = HV_TO_BE_SENT;
 	}
-	sent = 0;
-	while (sent < nrecip) {
-		int rc = hv_send_message(recip, nrecip,
-					 (HV_VirtAddr)&tag, sizeof(tag));
-		if (rc <= 0) {
-			if (!stopping_cpus)  /* avoid recursive panic */
-				panic("hv_send_message returned %d", rc);
-			break;
-		}
-		sent += rc;
-	}
+	__send_IPI_many(recip, nrecip, tag);
 }
 
 void send_IPI_allbutself(int tag)
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/stack.c linux-libre-2.6.39-gnu/arch/tile/kernel/stack.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/stack.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/stack.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,13 +44,6 @@
 	return sp >= kstack_base && sp < kstack_base + THREAD_SIZE;
 }
 
-/* Is address in the specified kernel code? */
-static int in_kernel_text(VirtualAddress address)
-{
-	return (address >= MEM_SV_INTRPT &&
-		address < MEM_SV_INTRPT + HPAGE_SIZE);
-}
-
 /* Is address valid for reading? */
 static int valid_address(struct KBacktraceIterator *kbt, VirtualAddress address)
 {
@@ -63,6 +56,23 @@
 	if (l1_pgtable == NULL)
 		return 0;	/* can't read user space in other tasks */
 
+#ifdef CONFIG_64BIT
+	/* Find the real l1_pgtable by looking in the l0_pgtable. */
+	pte = l1_pgtable[HV_L0_INDEX(address)];
+	if (!hv_pte_get_present(pte))
+		return 0;
+	pfn = hv_pte_get_pfn(pte);
+	if (pte_huge(pte)) {
+		if (!pfn_valid(pfn)) {
+			pr_err("L0 huge page has bad pfn %#lx\n", pfn);
+			return 0;
+		}
+		return hv_pte_get_present(pte) && hv_pte_get_readable(pte);
+	}
+	page = pfn_to_page(pfn);
+	BUG_ON(PageHighMem(page));  /* No HIGHMEM on 64-bit. */
+	l1_pgtable = (HV_PTE *)pfn_to_kaddr(pfn);
+#endif
 	pte = l1_pgtable[HV_L1_INDEX(address)];
 	if (!hv_pte_get_present(pte))
 		return 0;
@@ -92,7 +102,7 @@
 {
 	int retval;
 	struct KBacktraceIterator *kbt = (struct KBacktraceIterator *)vkbt;
-	if (in_kernel_text(address)) {
+	if (__kernel_text_address(address)) {
 		/* OK to read kernel code. */
 	} else if (address >= PAGE_OFFSET) {
 		/* We only tolerate kernel-space reads of this task's stack */
@@ -132,7 +142,7 @@
 		}
 	}
 	if (EX1_PL(p->ex1) == KERNEL_PL &&
-	    in_kernel_text(p->pc) &&
+	    __kernel_text_address(p->pc) &&
 	    in_kernel_stack(kbt, p->sp) &&
 	    p->sp >= sp) {
 		if (kbt->verbose)
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/time.c linux-libre-2.6.39-gnu/arch/tile/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/tile/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -224,3 +224,13 @@
 {
 	return -EINVAL;
 }
+
+/*
+ * Use the tile timer to convert nsecs to core clock cycles, relying
+ * on it having the same frequency as SPR_CYCLE.
+ */
+cycles_t ns2cycles(unsigned long nsecs)
+{
+	struct clock_event_device *dev = &__get_cpu_var(tile_timer);
+	return ((u64)nsecs * dev->mult) >> dev->shift;
+}
diff -druN linux-libre-2.6.38-gnu/arch/tile/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/tile/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/tile/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -59,11 +59,8 @@
 
   . = ALIGN(PAGE_SIZE);
   VMLINUX_SYMBOL(_sinitdata) = .;
-  .init.page : AT (ADDR(.init.page) - LOAD_OFFSET) {
-    *(.init.page)
-  } :data =0
-  INIT_DATA_SECTION(16)
-  PERCPU(PAGE_SIZE)
+  INIT_DATA_SECTION(16) :data =0
+  PERCPU(L2_CACHE_BYTES, PAGE_SIZE)
   . = ALIGN(PAGE_SIZE);
   VMLINUX_SYMBOL(_einitdata) = .;
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/atomic_32.c linux-libre-2.6.39-gnu/arch/tile/lib/atomic_32.c
--- linux-libre-2.6.38-gnu/arch/tile/lib/atomic_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/atomic_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,14 +46,13 @@
 #else /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
 /* This page is remapped on startup to be hash-for-home. */
-int atomic_locks[PAGE_SIZE / sizeof(int) /* Only ATOMIC_HASH_SIZE is used */]
-  __attribute__((aligned(PAGE_SIZE), section(".bss.page_aligned")));
+int atomic_locks[PAGE_SIZE / sizeof(int)] __page_aligned_bss;
 
 #endif /* ATOMIC_LOCKS_FOUND_VIA_TABLE() */
 
 static inline int *__atomic_hashed_lock(volatile void *v)
 {
-	/* NOTE: this code must match "sys_cmpxchg" in kernel/intvec.S */
+	/* NOTE: this code must match "sys_cmpxchg" in kernel/intvec_32.S */
 #if ATOMIC_LOCKS_FOUND_VIA_TABLE()
 	unsigned long i =
 		(unsigned long) v & ((PAGE_SIZE-1) & -sizeof(long long));
@@ -203,32 +202,32 @@
 	return __atomic_hashed_lock((int __force *)v);
 }
 
-struct __get_user futex_set(int __user *v, int i)
+struct __get_user futex_set(u32 __user *v, int i)
 {
 	return __atomic_xchg((int __force *)v, __futex_setup(v), i);
 }
 
-struct __get_user futex_add(int __user *v, int n)
+struct __get_user futex_add(u32 __user *v, int n)
 {
 	return __atomic_xchg_add((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_or(int __user *v, int n)
+struct __get_user futex_or(u32 __user *v, int n)
 {
 	return __atomic_or((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_andn(int __user *v, int n)
+struct __get_user futex_andn(u32 __user *v, int n)
 {
 	return __atomic_andn((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_xor(int __user *v, int n)
+struct __get_user futex_xor(u32 __user *v, int n)
 {
 	return __atomic_xor((int __force *)v, __futex_setup(v), n);
 }
 
-struct __get_user futex_cmpxchg(int __user *v, int o, int n)
+struct __get_user futex_cmpxchg(u32 __user *v, int o, int n)
 {
 	return __atomic_cmpxchg((int __force *)v, __futex_setup(v), o, n);
 }
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/atomic_asm_32.S linux-libre-2.6.39-gnu/arch/tile/lib/atomic_asm_32.S
--- linux-libre-2.6.38-gnu/arch/tile/lib/atomic_asm_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/atomic_asm_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
  * Support routines for atomic operations.  Each function takes:
  *
  * r0: address to manipulate
- * r1: pointer to atomic lock guarding this operation (for FUTEX_LOCK_REG)
+ * r1: pointer to atomic lock guarding this operation (for ATOMIC_LOCK_REG)
  * r2: new value to write, or for cmpxchg/add_unless, value to compare against
  * r3: (cmpxchg/xchg_add_unless) new value to write or add;
  *     (atomic64 ops) high word of value to write
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/cacheflush.c linux-libre-2.6.39-gnu/arch/tile/lib/cacheflush.c
--- linux-libre-2.6.38-gnu/arch/tile/lib/cacheflush.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/cacheflush.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,3 +21,105 @@
 {
 	invalidate_icache((const void *)start, end - start, PAGE_SIZE);
 }
+
+
+/* Force a load instruction to issue. */
+static inline void force_load(char *p)
+{
+	*(volatile char *)p;
+}
+
+/*
+ * Flush and invalidate a VA range that is homed remotely on a single
+ * core (if "!hfh") or homed via hash-for-home (if "hfh"), waiting
+ * until the memory controller holds the flushed values.
+ */
+void finv_buffer_remote(void *buffer, size_t size, int hfh)
+{
+	char *p, *base;
+	size_t step_size, load_count;
+	const unsigned long STRIPE_WIDTH = 8192;
+
+	/*
+	 * Flush and invalidate the buffer out of the local L1/L2
+	 * and request the home cache to flush and invalidate as well.
+	 */
+	__finv_buffer(buffer, size);
+
+	/*
+	 * Wait for the home cache to acknowledge that it has processed
+	 * all the flush-and-invalidate requests.  This does not mean
+	 * that the flushed data has reached the memory controller yet,
+	 * but it does mean the home cache is processing the flushes.
+	 */
+	__insn_mf();
+
+	/*
+	 * Issue a load to the last cache line, which can't complete
+	 * until all the previously-issued flushes to the same memory
+	 * controller have also completed.  If we weren't striping
+	 * memory, that one load would be sufficient, but since we may
+	 * be, we also need to back up to the last load issued to
+	 * another memory controller, which would be the point where
+	 * we crossed an 8KB boundary (the granularity of striping
+	 * across memory controllers).  Keep backing up and doing this
+	 * until we are before the beginning of the buffer, or have
+	 * hit all the controllers.
+	 *
+	 * If we are flushing a hash-for-home buffer, it's even worse.
+	 * Each line may be homed on a different tile, and each tile
+	 * may have up to four lines that are on different
+	 * controllers.  So as we walk backwards, we have to touch
+	 * enough cache lines to satisfy these constraints.  In
+	 * practice this ends up being close enough to "load from
+	 * every cache line on a full memory stripe on each
+	 * controller" that we simply do that, to simplify the logic.
+	 *
+	 * FIXME: See bug 9535 for some issues with this code.
+	 */
+	if (hfh) {
+		step_size = L2_CACHE_BYTES;
+		load_count = (STRIPE_WIDTH / L2_CACHE_BYTES) *
+			      (1 << CHIP_LOG_NUM_MSHIMS());
+	} else {
+		step_size = STRIPE_WIDTH;
+		load_count = (1 << CHIP_LOG_NUM_MSHIMS());
+	}
+
+	/* Load the last byte of the buffer. */
+	p = (char *)buffer + size - 1;
+	force_load(p);
+
+	/* Bump down to the end of the previous stripe or cache line. */
+	p -= step_size;
+	p = (char *)((unsigned long)p | (step_size - 1));
+
+	/* Figure out how far back we need to go. */
+	base = p - (step_size * (load_count - 2));
+	if ((long)base < (long)buffer)
+		base = buffer;
+
+	/*
+	 * Fire all the loads we need.  The MAF only has eight entries
+	 * so we can have at most eight outstanding loads, so we
+	 * unroll by that amount.
+	 */
+#pragma unroll 8
+	for (; p >= base; p -= step_size)
+		force_load(p);
+
+	/*
+	 * Repeat, but with inv's instead of loads, to get rid of the
+	 * data we just loaded into our own cache and the old home L3.
+	 * No need to unroll since inv's don't target a register.
+	 */
+	p = (char *)buffer + size - 1;
+	__insn_inv(p);
+	p -= step_size;
+	p = (char *)((unsigned long)p | (step_size - 1));
+	for (; p >= base; p -= step_size)
+		__insn_inv(p);
+
+	/* Wait for the load+inv's (and thus finvs) to have completed. */
+	__insn_mf();
+}
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/delay.c linux-libre-2.6.39-gnu/arch/tile/lib/delay.c
--- linux-libre-2.6.38-gnu/arch/tile/lib/delay.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/delay.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,20 +15,31 @@
 #include <linux/module.h>
 #include <linux/delay.h>
 #include <linux/thread_info.h>
-#include <asm/fixmap.h>
-#include <hv/hypervisor.h>
+#include <asm/timex.h>
 
 void __udelay(unsigned long usecs)
 {
-	hv_nanosleep(usecs * 1000);
+	if (usecs > ULONG_MAX / 1000) {
+		WARN_ON_ONCE(usecs > ULONG_MAX / 1000);
+		usecs = ULONG_MAX / 1000;
+	}
+	__ndelay(usecs * 1000);
 }
 EXPORT_SYMBOL(__udelay);
 
 void __ndelay(unsigned long nsecs)
 {
-	hv_nanosleep(nsecs);
+	cycles_t target = get_cycles();
+	target += ns2cycles(nsecs);
+	while (get_cycles() < target)
+		cpu_relax();
 }
 EXPORT_SYMBOL(__ndelay);
 
-/* FIXME: should be declared in a header somewhere. */
+void __delay(unsigned long cycles)
+{
+	cycles_t target = get_cycles() + cycles;
+	while (get_cycles() < target)
+		cpu_relax();
+}
 EXPORT_SYMBOL(__delay);
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/exports.c linux-libre-2.6.39-gnu/arch/tile/lib/exports.c
--- linux-libre-2.6.38-gnu/arch/tile/lib/exports.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/exports.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,9 @@
 EXPORT_SYMBOL(strnlen_user_asm);
 EXPORT_SYMBOL(strncpy_from_user_asm);
 EXPORT_SYMBOL(clear_user_asm);
+EXPORT_SYMBOL(flush_user_asm);
+EXPORT_SYMBOL(inv_user_asm);
+EXPORT_SYMBOL(finv_user_asm);
 
 /* arch/tile/kernel/entry.S */
 #include <linux/kernel.h>
@@ -45,9 +48,6 @@
 EXPORT_SYMBOL(__copy_in_user_inatomic);
 #endif
 
-/* arch/tile/lib/mb_incoherent.S */
-EXPORT_SYMBOL(__mb_incoherent);
-
 /* hypervisor glue */
 #include <hv/hypervisor.h>
 EXPORT_SYMBOL(hv_dev_open);
@@ -85,4 +85,8 @@
 EXPORT_SYMBOL(__muldi3);
 uint64_t __lshrdi3(uint64_t, unsigned int);
 EXPORT_SYMBOL(__lshrdi3);
+uint64_t __ashrdi3(uint64_t, unsigned int);
+EXPORT_SYMBOL(__ashrdi3);
+uint64_t __ashldi3(uint64_t, unsigned int);
+EXPORT_SYMBOL(__ashldi3);
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/Makefile linux-libre-2.6.39-gnu/arch/tile/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/tile/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,9 +2,8 @@
 # Makefile for TILE-specific library files..
 #
 
-lib-y = cacheflush.o checksum.o cpumask.o delay.o \
-	mb_incoherent.o uaccess.o memmove.o \
-	memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
+lib-y = cacheflush.o checksum.o cpumask.o delay.o uaccess.o \
+	memmove.o memcpy_$(BITS).o memchr_$(BITS).o memset_$(BITS).o \
 	strchr_$(BITS).o strlen_$(BITS).o
 
 ifeq ($(CONFIG_TILEGX),y)
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/mb_incoherent.S linux-libre-2.6.39-gnu/arch/tile/lib/mb_incoherent.S
--- linux-libre-2.6.38-gnu/arch/tile/lib/mb_incoherent.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/mb_incoherent.S	1969-12-31 19:00:00.000000000 -0500
@@ -1,34 +0,0 @@
-/*
- * Copyright 2010 Tilera 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
- *   as published by the Free Software Foundation, version 2.
- *
- *   This program is distributed in the hope that it will be useful, but
- *   WITHOUT ANY WARRANTY; without even the implied warranty of
- *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
- *   NON INFRINGEMENT.  See the GNU General Public License for
- *   more details.
- *
- * Assembly code for invoking the HV's fence_incoherent syscall.
- */
-
-#include <linux/linkage.h>
-#include <hv/syscall_public.h>
-#include <arch/abi.h>
-#include <arch/chip.h>
-
-#if !CHIP_HAS_MF_WAITS_FOR_VICTIMS()
-
-/*
- * Invoke the hypervisor's fence_incoherent syscall, which guarantees
- * that all victims for cachelines homed on this tile have reached memory.
- */
-STD_ENTRY(__mb_incoherent)
-	moveli TREG_SYSCALL_NR_NAME, HV_SYS_fence_incoherent
-	swint2
-	jrp lr
-	STD_ENDPROC(__mb_incoherent)
-
-#endif
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/memcpy_tile64.c linux-libre-2.6.39-gnu/arch/tile/lib/memcpy_tile64.c
--- linux-libre-2.6.38-gnu/arch/tile/lib/memcpy_tile64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/memcpy_tile64.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 	newsrc = __fix_to_virt(idx) + ((unsigned long)source & (PAGE_SIZE-1));
 	pmdp = pmd_offset(pud_offset(pgd_offset_k(newsrc), newsrc), newsrc);
 	ptep = pte_offset_kernel(pmdp, newsrc);
-	*ptep = src_pte;   /* set_pte() would be confused by this */
+	__set_pte(ptep, src_pte);   /* set_pte() would be confused by this */
 	local_flush_tlb_page(NULL, newsrc, PAGE_SIZE);
 
 	/* Actually move the data. */
@@ -109,7 +109,7 @@
 	 */
 	src_pte = hv_pte_set_mode(src_pte, HV_PTE_MODE_CACHE_NO_L3);
 	src_pte = hv_pte_set_writable(src_pte); /* need write access for inv */
-	*ptep = src_pte;   /* set_pte() would be confused by this */
+	__set_pte(ptep, src_pte);   /* set_pte() would be confused by this */
 	local_flush_tlb_page(NULL, newsrc, PAGE_SIZE);
 
 	/*
diff -druN linux-libre-2.6.38-gnu/arch/tile/lib/spinlock_32.c linux-libre-2.6.39-gnu/arch/tile/lib/spinlock_32.c
--- linux-libre-2.6.38-gnu/arch/tile/lib/spinlock_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/lib/spinlock_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <asm/processor.h>
+#include <arch/spr_def.h>
 
 #include "spinlock_common.h"
 
@@ -91,75 +92,75 @@
 #define RD_COUNT_MASK   ((1 << RD_COUNT_WIDTH) - 1)
 
 
-/* Lock the word, spinning until there are no tns-ers. */
-static inline u32 get_rwlock(arch_rwlock_t *rwlock)
-{
-	u32 iterations = 0;
-	for (;;) {
-		u32 val = __insn_tns((int *)&rwlock->lock);
-		if (unlikely(val & 1)) {
-			delay_backoff(iterations++);
-			continue;
-		}
-		return val;
-	}
-}
-
-int arch_read_trylock_slow(arch_rwlock_t *rwlock)
-{
-	u32 val = get_rwlock(rwlock);
-	int locked = (val << RD_COUNT_WIDTH) == 0;
-	rwlock->lock = val + (locked << RD_COUNT_SHIFT);
-	return locked;
-}
-EXPORT_SYMBOL(arch_read_trylock_slow);
-
-void arch_read_unlock_slow(arch_rwlock_t *rwlock)
-{
-	u32 val = get_rwlock(rwlock);
-	rwlock->lock = val - (1 << RD_COUNT_SHIFT);
-}
-EXPORT_SYMBOL(arch_read_unlock_slow);
-
-void arch_write_unlock_slow(arch_rwlock_t *rwlock, u32 val)
+/*
+ * We can get the read lock if everything but the reader bits (which
+ * are in the high part of the word) is zero, i.e. no active or
+ * waiting writers, no tns.
+ *
+ * We guard the tns/store-back with an interrupt critical section to
+ * preserve the semantic that the same read lock can be acquired in an
+ * interrupt context.
+ */
+inline int arch_read_trylock(arch_rwlock_t *rwlock)
 {
-	u32 eq, mask = 1 << WR_CURR_SHIFT;
-	while (unlikely(val & 1)) {
-		/* Limited backoff since we are the highest-priority task. */
-		relax(4);
-		val = __insn_tns((int *)&rwlock->lock);
+	u32 val;
+	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1);
+	val = __insn_tns((int *)&rwlock->lock);
+	if (likely((val << _RD_COUNT_WIDTH) == 0)) {
+		val += 1 << RD_COUNT_SHIFT;
+		rwlock->lock = val;
+		__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+		BUG_ON(val == 0);  /* we don't expect wraparound */
+		return 1;
 	}
-	val = __insn_addb(val, mask);
-	eq = __insn_seqb(val, val << (WR_CURR_SHIFT - WR_NEXT_SHIFT));
-	val = __insn_mz(eq & mask, val);
-	rwlock->lock = val;
+	if ((val & 1) == 0)
+		rwlock->lock = val;
+	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+	return 0;
 }
-EXPORT_SYMBOL(arch_write_unlock_slow);
+EXPORT_SYMBOL(arch_read_trylock);
 
 /*
- * We spin until everything but the reader bits (which are in the high
- * part of the word) are zero, i.e. no active or waiting writers, no tns.
- *
+ * Spin doing arch_read_trylock() until we acquire the lock.
  * ISSUE: This approach can permanently starve readers.  A reader who sees
  * a writer could instead take a ticket lock (just like a writer would),
  * and atomically enter read mode (with 1 reader) when it gets the ticket.
- * This way both readers and writers will always make forward progress
+ * This way both readers and writers would always make forward progress
  * in a finite time.
  */
-void arch_read_lock_slow(arch_rwlock_t *rwlock, u32 val)
+void arch_read_lock(arch_rwlock_t *rwlock)
 {
 	u32 iterations = 0;
-	do {
-		if (!(val & 1))
-			rwlock->lock = val;
+	while (unlikely(!arch_read_trylock(rwlock)))
 		delay_backoff(iterations++);
+}
+EXPORT_SYMBOL(arch_read_lock);
+
+void arch_read_unlock(arch_rwlock_t *rwlock)
+{
+	u32 val, iterations = 0;
+
+	mb();  /* guarantee anything modified under the lock is visible */
+	for (;;) {
+		__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1);
 		val = __insn_tns((int *)&rwlock->lock);
-	} while ((val << RD_COUNT_WIDTH) != 0);
-	rwlock->lock = val + (1 << RD_COUNT_SHIFT);
+		if (likely(val & 1) == 0) {
+			rwlock->lock = val - (1 << _RD_COUNT_SHIFT);
+			__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+			break;
+		}
+		__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+		delay_backoff(iterations++);
+	}
 }
-EXPORT_SYMBOL(arch_read_lock_slow);
+EXPORT_SYMBOL(arch_read_unlock);
 
-void arch_write_lock_slow(arch_rwlock_t *rwlock, u32 val)
+/*
+ * We don't need an interrupt critical section here (unlike for
+ * arch_read_lock) since we should never use a bare write lock where
+ * it could be interrupted by code that could try to re-acquire it.
+ */
+void arch_write_lock(arch_rwlock_t *rwlock)
 {
 	/*
 	 * The trailing underscore on this variable (and curr_ below)
@@ -168,6 +169,12 @@
 	 */
 	u32 my_ticket_;
 	u32 iterations = 0;
+	u32 val = __insn_tns((int *)&rwlock->lock);
+
+	if (likely(val == 0)) {
+		rwlock->lock = 1 << _WR_NEXT_SHIFT;
+		return;
+	}
 
 	/*
 	 * Wait until there are no readers, then bump up the next
@@ -206,23 +213,47 @@
 			relax(4);
 	}
 }
-EXPORT_SYMBOL(arch_write_lock_slow);
+EXPORT_SYMBOL(arch_write_lock);
 
-int __tns_atomic_acquire(atomic_t *lock)
+int arch_write_trylock(arch_rwlock_t *rwlock)
 {
-	int ret;
-	u32 iterations = 0;
+	u32 val = __insn_tns((int *)&rwlock->lock);
 
-	BUG_ON(__insn_mfspr(SPR_INTERRUPT_CRITICAL_SECTION));
-	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 1);
+	/*
+	 * If a tns is in progress, or there's a waiting or active locker,
+	 * or active readers, we can't take the lock, so give up.
+	 */
+	if (unlikely(val != 0)) {
+		if (!(val & 1))
+			rwlock->lock = val;
+		return 0;
+	}
 
-	while ((ret = __insn_tns((void *)&lock->counter)) == 1)
-		delay_backoff(iterations++);
-	return ret;
+	/* Set the "next" field to mark it locked. */
+	rwlock->lock = 1 << _WR_NEXT_SHIFT;
+	return 1;
 }
+EXPORT_SYMBOL(arch_write_trylock);
 
-void __tns_atomic_release(atomic_t *p, int v)
+void arch_write_unlock(arch_rwlock_t *rwlock)
 {
-	p->counter = v;
-	__insn_mtspr(SPR_INTERRUPT_CRITICAL_SECTION, 0);
+	u32 val, eq, mask;
+
+	mb();  /* guarantee anything modified under the lock is visible */
+	val = __insn_tns((int *)&rwlock->lock);
+	if (likely(val == (1 << _WR_NEXT_SHIFT))) {
+		rwlock->lock = 0;
+		return;
+	}
+	while (unlikely(val & 1)) {
+		/* Limited backoff since we are the highest-priority task. */
+		relax(4);
+		val = __insn_tns((int *)&rwlock->lock);
+	}
+	mask = 1 << WR_CURR_SHIFT;
+	val = __insn_addb(val, mask);
+	eq = __insn_seqb(val, val << (WR_CURR_SHIFT - WR_NEXT_SHIFT));
+	val = __insn_mz(eq & mask, val);
+	rwlock->lock = val;
 }
+EXPORT_SYMBOL(arch_write_unlock);
diff -druN linux-libre-2.6.38-gnu/arch/tile/mm/fault.c linux-libre-2.6.39-gnu/arch/tile/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/tile/mm/fault.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
 	/*
 	 * Early on, we need to check for migrating PTE entries;
 	 * see homecache.c.  If we find a migrating PTE, we wait until
-	 * the backing page claims to be done migrating, then we procede.
+	 * the backing page claims to be done migrating, then we proceed.
 	 * For kernel PTEs, we rewrite the PTE and return and retry.
 	 * Otherwise, we treat the fault like a normal "no PTE" fault,
 	 * rather than trying to patch up the existing PTE.
@@ -655,14 +655,6 @@
 	}
 
 	/*
-	 * NOTE: the one other type of access that might bring us here
-	 * are the memory ops in __tns_atomic_acquire/__tns_atomic_release,
-	 * but we don't have to check specially for them since we can
-	 * always safely return to the address of the fault and retry,
-	 * since no separate atomic locks are involved.
-	 */
-
-	/*
 	 * Now that we have released the atomic lock (if necessary),
 	 * it's safe to spin if the PTE that caused the fault was migrating.
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/tile/mm/homecache.c linux-libre-2.6.39-gnu/arch/tile/mm/homecache.c
--- linux-libre-2.6.38-gnu/arch/tile/mm/homecache.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/mm/homecache.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,23 +179,46 @@
 	panic("Unsafe to continue.");
 }
 
+void flush_remote_page(struct page *page, int order)
+{
+	int i, pages = (1 << order);
+	for (i = 0; i < pages; ++i, ++page) {
+		void *p = kmap_atomic(page);
+		int hfh = 0;
+		int home = page_home(page);
+#if CHIP_HAS_CBOX_HOME_MAP()
+		if (home == PAGE_HOME_HASH)
+			hfh = 1;
+		else
+#endif
+			BUG_ON(home < 0 || home >= NR_CPUS);
+		finv_buffer_remote(p, PAGE_SIZE, hfh);
+		kunmap_atomic(p);
+	}
+}
+
 void homecache_evict(const struct cpumask *mask)
 {
 	flush_remote(0, HV_FLUSH_EVICT_L2, mask, 0, 0, 0, NULL, NULL, 0);
 }
 
-/* Return a mask of the cpus whose caches currently own these pages. */
-static void homecache_mask(struct page *page, int pages,
-			   struct cpumask *home_mask)
+/*
+ * Return a mask of the cpus whose caches currently own these pages.
+ * The return value is whether the pages are all coherently cached
+ * (i.e. none are immutable, incoherent, or uncached).
+ */
+static int homecache_mask(struct page *page, int pages,
+			  struct cpumask *home_mask)
 {
 	int i;
+	int cached_coherently = 1;
 	cpumask_clear(home_mask);
 	for (i = 0; i < pages; ++i) {
 		int home = page_home(&page[i]);
 		if (home == PAGE_HOME_IMMUTABLE ||
 		    home == PAGE_HOME_INCOHERENT) {
 			cpumask_copy(home_mask, cpu_possible_mask);
-			return;
+			return 0;
 		}
 #if CHIP_HAS_CBOX_HOME_MAP()
 		if (home == PAGE_HOME_HASH) {
@@ -203,11 +226,14 @@
 			continue;
 		}
 #endif
-		if (home == PAGE_HOME_UNCACHED)
+		if (home == PAGE_HOME_UNCACHED) {
+			cached_coherently = 0;
 			continue;
+		}
 		BUG_ON(home < 0 || home >= NR_CPUS);
 		cpumask_set_cpu(home, home_mask);
 	}
+	return cached_coherently;
 }
 
 /*
@@ -386,7 +412,7 @@
 		pte_t *ptep = virt_to_pte(NULL, kva);
 		pte_t pteval = *ptep;
 		BUG_ON(!pte_present(pteval) || pte_huge(pteval));
-		*ptep = pte_set_home(pteval, home);
+		__set_pte(ptep, pte_set_home(pteval, home));
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/tile/mm/hugetlbpage.c linux-libre-2.6.39-gnu/arch/tile/mm/hugetlbpage.c
--- linux-libre-2.6.38-gnu/arch/tile/mm/hugetlbpage.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/mm/hugetlbpage.c	2011-05-19 00:06:34.000000000 -0400
@@ -219,7 +219,7 @@
 	if (mm->free_area_cache < len)
 		goto fail;
 
-	/* either no address requested or cant fit in requested address hole */
+	/* either no address requested or can't fit in requested address hole */
 	addr = (mm->free_area_cache - len) & huge_page_mask(h);
 	do {
 		/*
diff -druN linux-libre-2.6.38-gnu/arch/tile/mm/init.c linux-libre-2.6.39-gnu/arch/tile/mm/init.c
--- linux-libre-2.6.38-gnu/arch/tile/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,22 +53,11 @@
 
 #include "migrate.h"
 
-/*
- * We could set FORCE_MAX_ZONEORDER to "(HPAGE_SHIFT - PAGE_SHIFT + 1)"
- * in the Tile Kconfig, but this generates configure warnings.
- * Do it here and force people to get it right to compile this file.
- * The problem is that with 4KB small pages and 16MB huge pages,
- * the default value doesn't allow us to group enough small pages
- * together to make up a huge page.
- */
-#if CONFIG_FORCE_MAX_ZONEORDER < HPAGE_SHIFT - PAGE_SHIFT + 1
-# error "Change FORCE_MAX_ZONEORDER in arch/tile/Kconfig to match page size"
-#endif
-
 #define clear_pgd(pmdptr) (*(pmdptr) = hv_pte(0))
 
 #ifndef __tilegx__
 unsigned long VMALLOC_RESERVE = CONFIG_VMALLOC_RESERVE;
+EXPORT_SYMBOL(VMALLOC_RESERVE);
 #endif
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
@@ -445,7 +434,7 @@
 
 /* Temporary page table we use for staging. */
 static pgd_t pgtables[PTRS_PER_PGD]
- __attribute__((section(".init.page")));
+ __attribute__((aligned(HV_PAGE_TABLE_ALIGN)));
 
 /*
  * This maps the physical memory to kernel virtual address space, a total
@@ -653,6 +642,17 @@
 	memcpy(pgd_base, pgtables, sizeof(pgtables));
 	__install_page_table(pgd_base, __get_cpu_var(current_asid),
 			     swapper_pgprot);
+
+	/*
+	 * We just read swapper_pgprot and thus brought it into the cache,
+	 * with its new home & caching mode.  When we start the other CPUs,
+	 * they're going to reference swapper_pgprot via their initial fake
+	 * VA-is-PA mappings, which cache everything locally.  At that
+	 * time, if it's in our cache with a conflicting home, the
+	 * simulator's coherence checker will complain.  So, flush it out
+	 * of our cache; we're not going to ever use it again anyway.
+	 */
+	__insn_finv(&swapper_pgprot);
 }
 
 /*
@@ -950,11 +950,7 @@
 
 void __init pgtable_cache_init(void)
 {
-	pgd_cache = kmem_cache_create("pgd",
-				PTRS_PER_PGD*sizeof(pgd_t),
-				PTRS_PER_PGD*sizeof(pgd_t),
-				0,
-				NULL);
+	pgd_cache = kmem_cache_create("pgd", SIZEOF_PGD, SIZEOF_PGD, 0, NULL);
 	if (!pgd_cache)
 		panic("pgtable_cache_init(): Cannot create pgd cache");
 }
@@ -989,7 +985,7 @@
 static int __init set_initfree(char *str)
 {
 	long val;
-	if (strict_strtol(str, 0, &val)) {
+	if (strict_strtol(str, 0, &val) == 0) {
 		initfree = val;
 		pr_info("initfree: %s free init pages\n",
 			initfree ? "will" : "won't");
diff -druN linux-libre-2.6.38-gnu/arch/tile/mm/migrate_32.S linux-libre-2.6.39-gnu/arch/tile/mm/migrate_32.S
--- linux-libre-2.6.38-gnu/arch/tile/mm/migrate_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/mm/migrate_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/linkage.h>
 #include <linux/threads.h>
 #include <asm/page.h>
+#include <asm/thread_info.h>
 #include <asm/types.h>
 #include <asm/asm-offsets.h>
 #include <hv/hypervisor.h>
diff -druN linux-libre-2.6.38-gnu/arch/tile/mm/pgtable.c linux-libre-2.6.39-gnu/arch/tile/mm/pgtable.c
--- linux-libre-2.6.38-gnu/arch/tile/mm/pgtable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/tile/mm/pgtable.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
  * The normal show_free_areas() is too verbose on Tile, with dozens
  * of processors and often four NUMA zones each with high and lowmem.
  */
-void show_mem(void)
+void show_mem(unsigned int filter)
 {
 	struct zone *zone;
 
@@ -142,6 +142,76 @@
 }
 #endif
 
+/**
+ * shatter_huge_page() - ensure a given address is mapped by a small page.
+ *
+ * This function converts a huge PTE mapping kernel LOWMEM into a bunch
+ * of small PTEs with the same caching.  No cache flush required, but we
+ * must do a global TLB flush.
+ *
+ * Any caller that wishes to modify a kernel mapping that might
+ * have been made with a huge page should call this function,
+ * since doing so properly avoids race conditions with installing the
+ * newly-shattered page and then flushing all the TLB entries.
+ *
+ * @addr: Address at which to shatter any existing huge page.
+ */
+void shatter_huge_page(unsigned long addr)
+{
+	pgd_t *pgd;
+	pud_t *pud;
+	pmd_t *pmd;
+	unsigned long flags = 0;  /* happy compiler */
+#ifdef __PAGETABLE_PMD_FOLDED
+	struct list_head *pos;
+#endif
+
+	/* Get a pointer to the pmd entry that we need to change. */
+	addr &= HPAGE_MASK;
+	BUG_ON(pgd_addr_invalid(addr));
+	BUG_ON(addr < PAGE_OFFSET);  /* only for kernel LOWMEM */
+	pgd = swapper_pg_dir + pgd_index(addr);
+	pud = pud_offset(pgd, addr);
+	BUG_ON(!pud_present(*pud));
+	pmd = pmd_offset(pud, addr);
+	BUG_ON(!pmd_present(*pmd));
+	if (!pmd_huge_page(*pmd))
+		return;
+
+	/*
+	 * Grab the pgd_lock, since we may need it to walk the pgd_list,
+	 * and since we need some kind of lock here to avoid races.
+	 */
+	spin_lock_irqsave(&pgd_lock, flags);
+	if (!pmd_huge_page(*pmd)) {
+		/* Lost the race to convert the huge page. */
+		spin_unlock_irqrestore(&pgd_lock, flags);
+		return;
+	}
+
+	/* Shatter the huge page into the preallocated L2 page table. */
+	pmd_populate_kernel(&init_mm, pmd,
+			    get_prealloc_pte(pte_pfn(*(pte_t *)pmd)));
+
+#ifdef __PAGETABLE_PMD_FOLDED
+	/* Walk every pgd on the system and update the pmd there. */
+	list_for_each(pos, &pgd_list) {
+		pmd_t *copy_pmd;
+		pgd = list_to_pgd(pos) + pgd_index(addr);
+		pud = pud_offset(pgd, addr);
+		copy_pmd = pmd_offset(pud, addr);
+		__set_pmd(copy_pmd, *pmd);
+	}
+#endif
+
+	/* Tell every cpu to notice the change. */
+	flush_remote(0, 0, NULL, addr, HPAGE_SIZE, HPAGE_SIZE,
+		     cpu_possible_mask, NULL, 0);
+
+	/* Hold the lock until the TLB flush is finished to avoid races. */
+	spin_unlock_irqrestore(&pgd_lock, flags);
+}
+
 /*
  * List of all pgd's needed so it can invalidate entries in both cached
  * and uncached pgd's. This is essentially codepath-based locking
@@ -184,9 +254,9 @@
 	BUG_ON(((u64 *)swapper_pg_dir)[pgd_index(MEM_USER_INTRPT)] != 0);
 #endif
 
-	clone_pgd_range(pgd + KERNEL_PGD_INDEX_START,
-			swapper_pg_dir + KERNEL_PGD_INDEX_START,
-			KERNEL_PGD_PTRS);
+	memcpy(pgd + KERNEL_PGD_INDEX_START,
+	       swapper_pg_dir + KERNEL_PGD_INDEX_START,
+	       KERNEL_PGD_PTRS * sizeof(pgd_t));
 
 	pgd_list_add(pgd);
 	spin_unlock_irqrestore(&pgd_lock, flags);
@@ -220,8 +290,11 @@
 
 struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 {
-	gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO|__GFP_COMP;
+	gfp_t flags = GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO;
 	struct page *p;
+#if L2_USER_PGTABLE_ORDER > 0
+	int i;
+#endif
 
 #ifdef CONFIG_HIGHPTE
 	flags |= __GFP_HIGHMEM;
@@ -231,6 +304,18 @@
 	if (p == NULL)
 		return NULL;
 
+#if L2_USER_PGTABLE_ORDER > 0
+	/*
+	 * Make every page have a page_count() of one, not just the first.
+	 * We don't use __GFP_COMP since it doesn't look like it works
+	 * correctly with tlb_remove_page().
+	 */
+	for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) {
+		init_page_count(p+i);
+		inc_zone_page_state(p+i, NR_PAGETABLE);
+	}
+#endif
+
 	pgtable_page_ctor(p);
 	return p;
 }
@@ -242,8 +327,15 @@
  */
 void pte_free(struct mm_struct *mm, struct page *p)
 {
+	int i;
+
 	pgtable_page_dtor(p);
-	__free_pages(p, L2_USER_PGTABLE_ORDER);
+	__free_page(p);
+
+	for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) {
+		__free_page(p+i);
+		dec_zone_page_state(p+i, NR_PAGETABLE);
+	}
 }
 
 void __pte_free_tlb(struct mmu_gather *tlb, struct page *pte,
@@ -252,18 +344,11 @@
 	int i;
 
 	pgtable_page_dtor(pte);
-	tlb->need_flush = 1;
-	if (tlb_fast_mode(tlb)) {
-		struct page *pte_pages[L2_USER_PGTABLE_PAGES];
-		for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i)
-			pte_pages[i] = pte + i;
-		free_pages_and_swap_cache(pte_pages, L2_USER_PGTABLE_PAGES);
-		return;
-	}
-	for (i = 0; i < L2_USER_PGTABLE_PAGES; ++i) {
-		tlb->pages[tlb->nr++] = pte + i;
-		if (tlb->nr >= FREE_PTE_NR)
-			tlb_flush_mmu(tlb, 0, 0);
+	tlb_remove_page(tlb, pte);
+
+	for (i = 1; i < L2_USER_PGTABLE_PAGES; ++i) {
+		tlb_remove_page(tlb, pte + i);
+		dec_zone_page_state(pte + i, NR_PAGETABLE);
 	}
 }
 
@@ -346,35 +431,51 @@
 	return x + y * smp_width;
 }
 
-void set_pte_order(pte_t *ptep, pte_t pte, int order)
+/*
+ * Convert a kernel VA to a PA and homing information.
+ */
+int va_to_cpa_and_pte(void *va, unsigned long long *cpa, pte_t *pte)
 {
-	unsigned long pfn = pte_pfn(pte);
-	struct page *page = pfn_to_page(pfn);
+	struct page *page = virt_to_page(va);
+	pte_t null_pte = { 0 };
 
-	/* Update the home of a PTE if necessary */
-	pte = pte_set_home(pte, page_home(page));
+	*cpa = __pa(va);
 
+	/* Note that this is not writing a page table, just returning a pte. */
+	*pte = pte_set_home(null_pte, page_home(page));
+
+	return 0; /* return non-zero if not hfh? */
+}
+EXPORT_SYMBOL(va_to_cpa_and_pte);
+
+void __set_pte(pte_t *ptep, pte_t pte)
+{
 #ifdef __tilegx__
 	*ptep = pte;
 #else
-	/*
-	 * When setting a PTE, write the high bits first, then write
-	 * the low bits.  This sets the "present" bit only after the
-	 * other bits are in place.  If a particular PTE update
-	 * involves transitioning from one valid PTE to another, it
-	 * may be necessary to call set_pte_order() more than once,
-	 * transitioning via a suitable intermediate state.
-	 * Note that this sequence also means that if we are transitioning
-	 * from any migrating PTE to a non-migrating one, we will not
-	 * see a half-updated PTE with the migrating bit off.
-	 */
-#if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32
-# error Must write the present and migrating bits last
-#endif
-	((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32);
-	barrier();
-	((u32 *)ptep)[0] = (u32)(pte_val(pte));
-#endif
+# if HV_PTE_INDEX_PRESENT >= 32 || HV_PTE_INDEX_MIGRATING >= 32
+#  error Must write the present and migrating bits last
+# endif
+	if (pte_present(pte)) {
+		((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32);
+		barrier();
+		((u32 *)ptep)[0] = (u32)(pte_val(pte));
+	} else {
+		((u32 *)ptep)[0] = (u32)(pte_val(pte));
+		barrier();
+		((u32 *)ptep)[1] = (u32)(pte_val(pte) >> 32);
+	}
+#endif /* __tilegx__ */
+}
+
+void set_pte(pte_t *ptep, pte_t pte)
+{
+	struct page *page = pfn_to_page(pte_pfn(pte));
+
+	/* Update the home of a PTE if necessary */
+	pte = pte_set_home(pte, page_home(page));
+
+	__set_pte(ptep, pte);
 }
 
 /* Can this mm load a PTE with cached_priority set? */
diff -druN linux-libre-2.6.38-gnu/arch/um/drivers/line.c linux-libre-2.6.39-gnu/arch/um/drivers/line.c
--- linux-libre-2.6.38-gnu/arch/um/drivers/line.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/drivers/line.c	2011-05-19 00:06:34.000000000 -0400
@@ -255,8 +255,8 @@
 	{ KDSIGACCEPT, KERN_INFO,  "KDSIGACCEPT" },
 };
 
-int line_ioctl(struct tty_struct *tty, struct file * file,
-	       unsigned int cmd, unsigned long arg)
+int line_ioctl(struct tty_struct *tty, unsigned int cmd,
+				unsigned long arg)
 {
 	int ret;
 	int i;
diff -druN linux-libre-2.6.38-gnu/arch/um/drivers/mconsole_kern.c linux-libre-2.6.39-gnu/arch/um/drivers/mconsole_kern.c
--- linux-libre-2.6.38-gnu/arch/um/drivers/mconsole_kern.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/drivers/mconsole_kern.c	2011-05-19 00:06:34.000000000 -0400
@@ -124,35 +124,18 @@
 #if 0
 void mconsole_proc(struct mc_request *req)
 {
-	struct nameidata nd;
 	struct vfsmount *mnt = current->nsproxy->pid_ns->proc_mnt;
 	struct file *file;
-	int n, err;
+	int n;
 	char *ptr = req->request.data, *buf;
 	mm_segment_t old_fs = get_fs();
 
 	ptr += strlen("proc");
 	ptr = skip_spaces(ptr);
 
-	err = vfs_path_lookup(mnt->mnt_root, mnt, ptr, LOOKUP_FOLLOW, &nd);
-	if (err) {
-		mconsole_reply(req, "Failed to look up file", 1, 0);
-		goto out;
-	}
-
-	err = may_open(&nd.path, MAY_READ, O_RDONLY);
-	if (result) {
-		mconsole_reply(req, "Failed to open file", 1, 0);
-		path_put(&nd.path);
-		goto out;
-	}
-
-	file = dentry_open(nd.path.dentry, nd.path.mnt, O_RDONLY,
-			   current_cred());
-	err = PTR_ERR(file);
+	file = file_open_root(mnt->mnt_root, mnt, ptr, O_RDONLY);
 	if (IS_ERR(file)) {
 		mconsole_reply(req, "Failed to open file", 1, 0);
-		path_put(&nd.path);
 		goto out;
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/um/drivers/ubd_kern.c linux-libre-2.6.39-gnu/arch/um/drivers/ubd_kern.c
--- linux-libre-2.6.38-gnu/arch/um/drivers/ubd_kern.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/drivers/ubd_kern.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,7 +185,7 @@
 	.no_cow =               0, \
 	.shared =		0, \
 	.cow =			DEFAULT_COW, \
-	.lock =			SPIN_LOCK_UNLOCKED,	\
+	.lock =			__SPIN_LOCK_UNLOCKED(ubd_devs.lock), \
 	.request =		NULL, \
 	.start_sg =		0, \
 	.end_sg =		0, \
diff -druN linux-libre-2.6.38-gnu/arch/um/include/asm/bug.h linux-libre-2.6.39-gnu/arch/um/include/asm/bug.h
--- linux-libre-2.6.38-gnu/arch/um/include/asm/bug.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/um/include/asm/bug.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+#ifndef __UM_BUG_H
+#define __UM_BUG_H
+
+#include <asm-generic/bug.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/um/include/asm/common.lds.S linux-libre-2.6.39-gnu/arch/um/include/asm/common.lds.S
--- linux-libre-2.6.38-gnu/arch/um/include/asm/common.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/include/asm/common.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,7 @@
 	INIT_SETUP(0)
   }
 
-  PERCPU(32)
+  PERCPU(32, 32)
 	
   .initcall.init : {
 	INIT_CALLS
diff -druN linux-libre-2.6.38-gnu/arch/um/include/asm/processor-generic.h linux-libre-2.6.39-gnu/arch/um/include/asm/processor-generic.h
--- linux-libre-2.6.38-gnu/arch/um/include/asm/processor-generic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/include/asm/processor-generic.h	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
 	.request		= { 0 } \
 }
 
-extern struct task_struct *alloc_task_struct(void);
+extern struct task_struct *alloc_task_struct_node(int node);
 
 static inline void release_thread(struct task_struct *task)
 {
diff -druN linux-libre-2.6.38-gnu/arch/um/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/um/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/um/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -49,7 +49,10 @@
 {
 	struct thread_info *ti;
 	unsigned long mask = THREAD_SIZE - 1;
-	ti = (struct thread_info *) (((unsigned long) &ti) & ~mask);
+	void *p;
+
+	asm volatile ("" : "=r" (p) : "0" (&ti));
+	ti = (struct thread_info *) (((unsigned long)p) & ~mask);
 	return ti;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/um/include/shared/line.h linux-libre-2.6.39-gnu/arch/um/include/shared/line.h
--- linux-libre-2.6.38-gnu/arch/um/include/shared/line.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/include/shared/line.h	2011-05-19 00:06:34.000000000 -0400
@@ -77,8 +77,8 @@
 extern void line_flush_buffer(struct tty_struct *tty);
 extern void line_flush_chars(struct tty_struct *tty);
 extern int line_write_room(struct tty_struct *tty);
-extern int line_ioctl(struct tty_struct *tty, struct file * file,
-		      unsigned int cmd, unsigned long arg);
+extern int line_ioctl(struct tty_struct *tty, unsigned int cmd,
+				unsigned long arg);
 extern void line_throttle(struct tty_struct *tty);
 extern void line_unthrottle(struct tty_struct *tty);
 
diff -druN linux-libre-2.6.38-gnu/arch/um/Kconfig.common linux-libre-2.6.39-gnu/arch/um/Kconfig.common
--- linux-libre-2.6.38-gnu/arch/um/Kconfig.common	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/Kconfig.common	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,7 @@
 	bool
 	default y
 	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
 
 config MMU
 	bool
diff -druN linux-libre-2.6.38-gnu/arch/um/Kconfig.net linux-libre-2.6.39-gnu/arch/um/Kconfig.net
--- linux-libre-2.6.38-gnu/arch/um/Kconfig.net	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/Kconfig.net	2011-05-19 00:06:34.000000000 -0400
@@ -186,7 +186,7 @@
         other transports, SLiRP works without the need of root level
         privleges, setuid binaries, or SLIP devices on the host.  This
         also means not every type of connection is possible, but most
-        situations can be accomodated with carefully crafted slirp
+        situations can be accommodated with carefully crafted slirp
         commands that can be passed along as part of the network device's
         setup string.  The effect of this transport on the UML is similar
         that of a host behind a firewall that masquerades all network
diff -druN linux-libre-2.6.38-gnu/arch/um/Kconfig.um linux-libre-2.6.39-gnu/arch/um/Kconfig.um
--- linux-libre-2.6.38-gnu/arch/um/Kconfig.um	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/Kconfig.um	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,7 @@
 
 config HPPFS
 	tristate "HoneyPot ProcFS (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
+	depends on EXPERIMENTAL && PROC_FS
 	help
 	  hppfs (HoneyPot ProcFS) is a filesystem which allows UML /proc
 	  entries to be overridden, removed, or fabricated from the host.
diff -druN linux-libre-2.6.38-gnu/arch/um/Kconfig.x86 linux-libre-2.6.39-gnu/arch/um/Kconfig.x86
--- linux-libre-2.6.38-gnu/arch/um/Kconfig.x86	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/Kconfig.x86	2011-05-19 00:06:34.000000000 -0400
@@ -4,12 +4,18 @@
 
 menu "Host processor type and features"
 
+config CMPXCHG_LOCAL
+	bool
+	default n
+
 source "arch/x86/Kconfig.cpu"
 
 endmenu
 
 config UML_X86
 	def_bool y
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_FIND_NEXT_BIT
 
 config 64BIT
 	bool
@@ -19,6 +25,9 @@
 	def_bool !64BIT
 	select HAVE_AOUT
 
+config X86_64
+	def_bool 64BIT
+
 config RWSEM_XCHGADD_ALGORITHM
 	def_bool X86_XADD
 
diff -druN linux-libre-2.6.38-gnu/arch/um/kernel/irq.c linux-libre-2.6.39-gnu/arch/um/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/um/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,50 +18,6 @@
 #include "os.h"
 
 /*
- * Generic, controller-independent functions:
- */
-
-int show_interrupts(struct seq_file *p, void *v)
-{
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS)
-		seq_putc(p, '\n');
-
-	return 0;
-}
-
-/*
  * This list is accessed under irq_lock, except in sigio_handler,
  * where it is safe from being modified.  IRQ handlers won't change it -
  * if an IRQ source has vanished, it will be freed by free_irqs just
@@ -360,10 +316,10 @@
 EXPORT_SYMBOL(reactivate_fd);
 
 /*
- * irq_chip must define (startup || enable) &&
- * (shutdown || disable) && end
+ * irq_chip must define at least enable/disable and ack when
+ * the edge handler is used.
  */
-static void dummy(unsigned int irq)
+static void dummy(struct irq_data *d)
 {
 }
 
@@ -371,31 +327,27 @@
 static struct irq_chip normal_irq_type = {
 	.name = "SIGIO",
 	.release = free_irq_by_irq_and_dev,
-	.disable = dummy,
-	.enable = dummy,
-	.ack = dummy,
-	.end = dummy
+	.irq_disable = dummy,
+	.irq_enable = dummy,
+	.irq_ack = dummy,
 };
 
 static struct irq_chip SIGVTALRM_irq_type = {
 	.name = "SIGVTALRM",
 	.release = free_irq_by_irq_and_dev,
-	.shutdown = dummy, /* never called */
-	.disable = dummy,
-	.enable = dummy,
-	.ack = dummy,
-	.end = dummy
+	.irq_disable = dummy,
+	.irq_enable = dummy,
+	.irq_ack = dummy,
 };
 
 void __init init_IRQ(void)
 {
 	int i;
 
-	set_irq_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq);
+	irq_set_chip_and_handler(TIMER_IRQ, &SIGVTALRM_irq_type, handle_edge_irq);
 
-	for (i = 1; i < NR_IRQS; i++) {
-		set_irq_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
-	}
+	for (i = 1; i < NR_IRQS; i++)
+		irq_set_chip_and_handler(i, &normal_irq_type, handle_edge_irq);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/um/os-Linux/util.c linux-libre-2.6.39-gnu/arch/um/os-Linux/util.c
--- linux-libre-2.6.38-gnu/arch/um/os-Linux/util.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/os-Linux/util.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,7 @@
 
 #include <stdio.h>
 #include <stdlib.h>
+#include <unistd.h>
 #include <errno.h>
 #include <signal.h>
 #include <string.h>
@@ -75,6 +76,26 @@
 		 host.release, host.version, host.machine);
 }
 
+/*
+ * We cannot use glibc's abort(). It makes use of tgkill() which
+ * has no effect within UML's kernel threads.
+ * After that glibc would execute an invalid instruction to kill
+ * the calling process and UML crashes with SIGSEGV.
+ */
+static inline void __attribute__ ((noreturn)) uml_abort(void)
+{
+	sigset_t sig;
+
+	fflush(NULL);
+
+	if (!sigemptyset(&sig) && !sigaddset(&sig, SIGABRT))
+		sigprocmask(SIG_UNBLOCK, &sig, 0);
+
+	for (;;)
+		if (kill(getpid(), SIGABRT) < 0)
+			exit(127);
+}
+
 void os_dump_core(void)
 {
 	int pid;
@@ -116,5 +137,5 @@
 	while ((pid = waitpid(-1, NULL, WNOHANG | __WALL)) > 0)
 		os_kill_ptraced_process(pid, 0);
 
-	abort();
+	uml_abort();
 }
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-i386/asm/elf.h linux-libre-2.6.39-gnu/arch/um/sys-i386/asm/elf.h
--- linux-libre-2.6.38-gnu/arch/um/sys-i386/asm/elf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/sys-i386/asm/elf.h	2011-05-19 00:06:34.000000000 -0400
@@ -75,6 +75,8 @@
 	pr_reg[16] = PT_REGS_SS(regs);		\
 } while (0);
 
+#define task_pt_regs(t) (&(t)->thread.regs)
+
 struct task_struct;
 
 extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-i386/atomic64_cx8_32.S linux-libre-2.6.39-gnu/arch/um/sys-i386/atomic64_cx8_32.S
--- linux-libre-2.6.38-gnu/arch/um/sys-i386/atomic64_cx8_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/um/sys-i386/atomic64_cx8_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,225 @@
+/*
+ * atomic64_t for 586+
+ *
+ * Copied from arch/x86/lib/atomic64_cx8_32.S
+ *
+ * Copyright Â© 2010  Luca Barbieri
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/dwarf2.h>
+
+.macro SAVE reg
+	pushl_cfi %\reg
+	CFI_REL_OFFSET \reg, 0
+.endm
+
+.macro RESTORE reg
+	popl_cfi %\reg
+	CFI_RESTORE \reg
+.endm
+
+.macro read64 reg
+	movl %ebx, %eax
+	movl %ecx, %edx
+/* we need LOCK_PREFIX since otherwise cmpxchg8b always does the write */
+	LOCK_PREFIX
+	cmpxchg8b (\reg)
+.endm
+
+ENTRY(atomic64_read_cx8)
+	CFI_STARTPROC
+
+	read64 %ecx
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_read_cx8)
+
+ENTRY(atomic64_set_cx8)
+	CFI_STARTPROC
+
+1:
+/* we don't need LOCK_PREFIX since aligned 64-bit writes
+ * are atomic on 586 and newer */
+	cmpxchg8b (%esi)
+	jne 1b
+
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_set_cx8)
+
+ENTRY(atomic64_xchg_cx8)
+	CFI_STARTPROC
+
+	movl %ebx, %eax
+	movl %ecx, %edx
+1:
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_xchg_cx8)
+
+.macro addsub_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+	CFI_STARTPROC
+	SAVE ebp
+	SAVE ebx
+	SAVE esi
+	SAVE edi
+
+	movl %eax, %esi
+	movl %edx, %edi
+	movl %ecx, %ebp
+
+	read64 %ebp
+1:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	\ins\()l %esi, %ebx
+	\insc\()l %edi, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%ebp)
+	jne 1b
+
+10:
+	movl %ebx, %eax
+	movl %ecx, %edx
+	RESTORE edi
+	RESTORE esi
+	RESTORE ebx
+	RESTORE ebp
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+addsub_return add add adc
+addsub_return sub sub sbb
+
+.macro incdec_return func ins insc
+ENTRY(atomic64_\func\()_return_cx8)
+	CFI_STARTPROC
+	SAVE ebx
+
+	read64 %esi
+1:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	\ins\()l $1, %ebx
+	\insc\()l $0, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+10:
+	movl %ebx, %eax
+	movl %ecx, %edx
+	RESTORE ebx
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_\func\()_return_cx8)
+.endm
+
+incdec_return inc add adc
+incdec_return dec sub sbb
+
+ENTRY(atomic64_dec_if_positive_cx8)
+	CFI_STARTPROC
+	SAVE ebx
+
+	read64 %esi
+1:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	subl $1, %ebx
+	sbb $0, %ecx
+	js 2f
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+2:
+	movl %ebx, %eax
+	movl %ecx, %edx
+	RESTORE ebx
+	ret
+	CFI_ENDPROC
+ENDPROC(atomic64_dec_if_positive_cx8)
+
+ENTRY(atomic64_add_unless_cx8)
+	CFI_STARTPROC
+	SAVE ebp
+	SAVE ebx
+/* these just push these two parameters on the stack */
+	SAVE edi
+	SAVE esi
+
+	movl %ecx, %ebp
+	movl %eax, %esi
+	movl %edx, %edi
+
+	read64 %ebp
+1:
+	cmpl %eax, 0(%esp)
+	je 4f
+2:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	addl %esi, %ebx
+	adcl %edi, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%ebp)
+	jne 1b
+
+	movl $1, %eax
+3:
+	addl $8, %esp
+	CFI_ADJUST_CFA_OFFSET -8
+	RESTORE ebx
+	RESTORE ebp
+	ret
+4:
+	cmpl %edx, 4(%esp)
+	jne 2b
+	xorl %eax, %eax
+	jmp 3b
+	CFI_ENDPROC
+ENDPROC(atomic64_add_unless_cx8)
+
+ENTRY(atomic64_inc_not_zero_cx8)
+	CFI_STARTPROC
+	SAVE ebx
+
+	read64 %esi
+1:
+	testl %eax, %eax
+	je 4f
+2:
+	movl %eax, %ebx
+	movl %edx, %ecx
+	addl $1, %ebx
+	adcl $0, %ecx
+	LOCK_PREFIX
+	cmpxchg8b (%esi)
+	jne 1b
+
+	movl $1, %eax
+3:
+	RESTORE ebx
+	ret
+4:
+	testl %edx, %edx
+	jne 2b
+	jmp 3b
+	CFI_ENDPROC
+ENDPROC(atomic64_inc_not_zero_cx8)
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-i386/Makefile linux-libre-2.6.39-gnu/arch/um/sys-i386/Makefile
--- linux-libre-2.6.38-gnu/arch/um/sys-i386/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/sys-i386/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 
 obj-y = bug.o bugs.o checksum.o delay.o fault.o ksyms.o ldt.o ptrace.o \
 	ptrace_user.o setjmp.o signal.o stub.o stub_segv.o syscalls.o sysrq.o \
-	sys_call_table.o tls.o
+	sys_call_table.o tls.o atomic64_cx8_32.o
 
 obj-$(CONFIG_BINFMT_ELF) += elfcore.o
 
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-ppc/Makefile linux-libre-2.6.39-gnu/arch/um/sys-ppc/Makefile
--- linux-libre-2.6.38-gnu/arch/um/sys-ppc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/sys-ppc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 OBJS = ptrace.o sigcontext.o checksum.o miscthings.o misc.o \
 	ptrace_user.o sysrq.o
 
-EXTRA_AFLAGS := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
+asflags-y := -DCONFIG_PPC32 -I. -I$(srctree)/arch/ppc/kernel
 
 all: $(OBJ)
 
@@ -15,10 +15,10 @@
 	$(LD) $(LINKFLAGS) --start-group $^ --end-group -o $@
 
 ptrace_user.o: ptrace_user.c
-	$(CC) -D__KERNEL__ $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+	$(CC) -D__KERNEL__ $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
 
 sigcontext.o: sigcontext.c
-	$(CC) $(USER_CFLAGS) $(EXTRA_CFLAGS) -c -o $@ $<
+	$(CC) $(USER_CFLAGS) $(ccflags-y) -c -o $@ $<
 
 checksum.S:
 	rm -f $@
@@ -53,13 +53,13 @@
 checksum.o: checksum.S
 	rm -f asm
 	ln -s $(srctree)/include/asm-ppc asm
-	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+	$(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
 misc.o: misc.S ppc_defs.h
 	rm -f asm
 	ln -s $(srctree)/include/asm-ppc asm
-	$(CC) $(EXTRA_AFLAGS) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
+	$(CC) $(asflags-y) $(KBUILD_AFLAGS) -D__ASSEMBLY__ -D__UM_PPC__ -c $< -o $*.o
 	rm -f asm
 
 clean-files := $(OBJS) ppc_defs.h checksum.S mk_defs.c
diff -druN linux-libre-2.6.38-gnu/arch/um/sys-x86_64/asm/elf.h linux-libre-2.6.39-gnu/arch/um/sys-x86_64/asm/elf.h
--- linux-libre-2.6.38-gnu/arch/um/sys-x86_64/asm/elf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/um/sys-x86_64/asm/elf.h	2011-05-19 00:06:34.000000000 -0400
@@ -95,6 +95,8 @@
 	(pr_reg)[25] = 0;					\
 	(pr_reg)[26] = 0;
 
+#define task_pt_regs(t) (&(t)->thread.regs)
+
 struct task_struct;
 
 extern int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/head.S linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/head.S
--- linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/head.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,204 @@
+/*
+ * linux/arch/unicore32/boot/compressed/head.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <mach/memory.h>
+
+#define csub	cmpsub
+#define cand	cmpand
+#define nop8	nop; nop; nop; nop; nop; nop; nop; nop
+
+		.section ".start", #alloc, #execinstr
+		.text
+start:
+		.type	start,#function
+
+		/* Initialize ASR, PRIV mode and INTR off */
+		mov	r0, #0xD3
+		mov.a	asr, r0
+
+		adr	r0, LC0
+		ldm	(r1, r2, r3, r5, r6, r7, r8), [r0]+
+		ldw	sp, [r0+], #28
+		sub.a	r0, r0, r1		@ calculate the delta offset
+
+		/*
+		 * if delta is zero, we are running at the address
+		 * we were linked at.
+		 */
+		beq	not_relocated
+
+		/*
+		 * We're running at a different address.  We need to fix
+		 * up various pointers:
+		 *   r5 - zImage base address (_start)
+		 *   r7 - GOT start
+		 *   r8 - GOT end
+		 */
+		add	r5, r5, r0
+		add	r7, r7, r0
+		add	r8, r8, r0
+
+		/*
+		 * we need to fix up pointers into the BSS region.
+		 *   r2 - BSS start
+		 *   r3 - BSS end
+		 *   sp - stack pointer
+		 */
+		add	r2, r2, r0
+		add	r3, r3, r0
+		add	sp, sp, r0
+
+		/*
+		 * Relocate all entries in the GOT table.
+		 * This fixes up the C references.
+		 *   r7 - GOT start
+		 *   r8 - GOT end
+		 */
+1001:		ldw	r1, [r7+], #0
+		add	r1, r1, r0
+		stw.w	r1, [r7]+, #4
+		csub.a	r7, r8
+		bub	1001b
+
+not_relocated:
+		/*
+		 * Clear BSS region.
+		 *   r2 - BSS start
+		 *   r3 - BSS end
+		 */
+		mov	r0, #0
+1002:		stw.w	r0, [r2]+, #4
+		csub.a	r2, r3
+		bub	1002b
+
+		/*
+		 * Turn on the cache.
+		 */
+                mov     r0, #0
+                movc    p0.c5, r0, #28		@ cache invalidate all
+                nop8
+                movc    p0.c6, r0, #6		@ tlb invalidate all
+                nop8
+
+                mov     r0, #0x1c		@ en icache and wb dcache
+                movc    p0.c1, r0, #0
+                nop8
+
+		/*
+		 * Set up some pointers, for starting decompressing.
+		 */
+
+		mov	r1, sp			@ malloc space above stack
+		add	r2, sp, #0x10000	@ 64k max
+
+		/*
+		 * Check to see if we will overwrite ourselves.
+		 *   r4 = final kernel address
+		 *   r5 = start of this image
+		 *   r6 = size of decompressed image
+		 *   r2 = end of malloc space (and therefore this image)
+		 * We basically want:
+		 *   r4 >= r2 -> OK
+		 *   r4 + image length <= r5 -> OK
+		 */
+		ldw	r4, =KERNEL_IMAGE_START
+		csub.a	r4, r2
+		bea	wont_overwrite
+		add	r0, r4, r6
+		csub.a	r0, r5
+		beb	wont_overwrite
+
+		/*
+		 * If overwrite, just print error message
+		 */
+		b	__error_overwrite
+
+		/*
+		 * We're not in danger of overwriting ourselves.
+		 * Do this the simple way.
+		 */
+wont_overwrite:
+		/*
+		 * decompress_kernel:
+		 *   r0: output_start
+		 *   r1: free_mem_ptr_p
+		 *   r2: free_mem_ptr_end_p
+		 */
+		mov	r0, r4
+		b.l	decompress_kernel	@ C functions
+
+		/*
+		 * Clean and flush the cache to maintain consistency.
+		 */
+		mov	r0, #0
+                movc    p0.c5, r0, #14		@ flush dcache
+		nop8
+                movc    p0.c5, r0, #20		@ icache invalidate all
+                nop8
+
+		/*
+		 * Turn off the Cache and MMU.
+		 */
+		mov	r0, #0			@ disable i/d cache and MMU
+		movc	p0.c1, r0, #0
+                nop8
+
+		mov	r0, #0			@ must be zero
+		ldw	r4, =KERNEL_IMAGE_START
+		mov	pc, r4			@ call kernel
+
+
+		.align	2
+		.type	LC0, #object
+LC0:		.word	LC0			@ r1
+		.word	__bss_start		@ r2
+		.word	_end			@ r3
+		.word	_start			@ r5
+		.word	_image_size		@ r6
+		.word	_got_start		@ r7
+		.word	_got_end		@ r8
+		.word	decompress_stack_end	@ sp
+		.size	LC0, . - LC0
+
+print_string:
+#ifdef CONFIG_DEBUG_OCD
+2001:		ldb.w	r1, [r0]+, #1
+		csub.a	r1, #0
+		bne	2002f
+		mov	pc, lr
+2002:
+		movc	r2, p1.c0, #0
+		cand.a	r2, #2
+		bne	2002b
+		movc	p1.c1, r1, #1
+		csub.a	r1, #'\n'
+		cmoveq	r1, #'\r'
+		beq	2002b
+		b	2001b
+#else
+		mov	pc, lr
+#endif
+
+__error_overwrite:
+		adr	r0, str_error
+		b.l	print_string
+2001:		nop8
+		b	2001b
+str_error:	.asciz	"\nError: Kernel address OVERWRITE\n"
+		.align
+
+		.ltorg
+
+		.align	4
+		.section ".stack", "aw", %nobits
+decompress_stack:	.space	4096
+decompress_stack_end:
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/Makefile linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/Makefile
--- linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,68 @@
+#
+# linux/arch/unicore32/boot/compressed/Makefile
+#
+# create a compressed vmlinuz image from the original vmlinux
+#
+# 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~2010 GUAN Xue-tao
+#
+
+EXTRA_CFLAGS	:= -fpic -fno-builtin
+EXTRA_AFLAGS	:= -Wa,-march=all
+
+OBJS		:= misc.o
+
+# font.c and font.o
+CFLAGS_font.o	:= -Dstatic=
+$(obj)/font.c: $(srctree)/drivers/video/console/font_8x8.c
+	$(call cmd,shipped)
+
+# piggy.S and piggy.o
+suffix_$(CONFIG_KERNEL_GZIP)	:= gzip
+suffix_$(CONFIG_KERNEL_BZIP2)	:= bz2
+suffix_$(CONFIG_KERNEL_LZO)	:= lzo
+suffix_$(CONFIG_KERNEL_LZMA)	:= lzma
+
+$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE
+	$(call if_changed,$(suffix_y))
+
+SEDFLAGS_piggy	= s/DECOMP_SUFFIX/$(suffix_y)/
+$(obj)/piggy.S: $(obj)/piggy.S.in
+	@sed "$(SEDFLAGS_piggy)" < $< > $@
+
+$(obj)/piggy.o:  $(obj)/piggy.$(suffix_y) $(obj)/piggy.S FORCE
+
+targets		:= vmlinux vmlinux.lds font.o font.c head.o misc.o \
+			piggy.$(suffix_y) piggy.o piggy.S \
+
+# Make sure files are removed during clean
+extra-y		+= piggy.gzip piggy.bz2 piggy.lzo piggy.lzma
+
+# ?
+LDFLAGS_vmlinux += -p
+# Report unresolved symbol references
+LDFLAGS_vmlinux += --no-undefined
+# Delete all temporary local symbols
+LDFLAGS_vmlinux += -X
+# Next argument is a linker script
+LDFLAGS_vmlinux += -T
+
+# For uidivmod
+$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/head.o $(obj)/piggy.o \
+		$(obj)/misc.o FORCE
+	$(call if_changed,ld)
+	@:
+
+# We now have a PIC decompressor implementation.  Decompressors running
+# from RAM should not define ZTEXTADDR.  Decompressors running directly
+# from ROM or Flash must define ZTEXTADDR (preferably via the config)
+ZTEXTADDR	:= 0
+ZBSSADDR	:= ALIGN(4)
+
+SEDFLAGS_lds	= s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/
+$(obj)/vmlinux.lds: $(obj)/vmlinux.lds.in arch/unicore32/boot/Makefile $(KCONFIG_CONFIG)
+	@sed "$(SEDFLAGS_lds)" < $< > $@
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/misc.c linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/misc.c
--- linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/misc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/misc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/unicore32/boot/compressed/misc.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <asm/unaligned.h>
+#include <mach/uncompress.h>
+
+/*
+ * gzip delarations
+ */
+unsigned char *output_data;
+unsigned long output_ptr;
+
+unsigned int free_mem_ptr;
+unsigned int free_mem_end_ptr;
+
+#define STATIC static
+#define STATIC_RW_DATA	/* non-static please */
+
+/*
+ * arch-dependent implementations
+ */
+#ifndef ARCH_HAVE_DECOMP_ERROR
+#define arch_decomp_error(x)
+#endif
+
+#ifndef ARCH_HAVE_DECOMP_SETUP
+#define arch_decomp_setup()
+#endif
+
+#ifndef ARCH_HAVE_DECOMP_PUTS
+#define arch_decomp_puts(p)
+#endif
+
+void *memcpy(void *dest, const void *src, size_t n)
+{
+	int i = 0;
+	unsigned char *d = (unsigned char *)dest, *s = (unsigned char *)src;
+
+	for (i = n >> 3; i > 0; i--) {
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (n & 1 << 2) {
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (n & 1 << 1) {
+		*d++ = *s++;
+		*d++ = *s++;
+	}
+
+	if (n & 1)
+		*d++ = *s++;
+
+	return dest;
+}
+
+void error(char *x)
+{
+	arch_decomp_puts("\n\n");
+	arch_decomp_puts(x);
+	arch_decomp_puts("\n\n -- System halted");
+
+	arch_decomp_error(x);
+
+	for (;;)
+		; /* Halt */
+}
+
+/* Heap size should be adjusted for different decompress method */
+#ifdef CONFIG_KERNEL_GZIP
+#include "../../../../lib/decompress_inflate.c"
+#endif
+
+#ifdef CONFIG_KERNEL_BZIP2
+#include "../../../../lib/decompress_bunzip2.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZO
+#include "../../../../lib/decompress_unlzo.c"
+#endif
+
+#ifdef CONFIG_KERNEL_LZMA
+#include "../../../../lib/decompress_unlzma.c"
+#endif
+
+unsigned long decompress_kernel(unsigned long output_start,
+		unsigned long free_mem_ptr_p,
+		unsigned long free_mem_ptr_end_p)
+{
+	unsigned char *tmp;
+
+	output_data		= (unsigned char *)output_start;
+	free_mem_ptr		= free_mem_ptr_p;
+	free_mem_end_ptr	= free_mem_ptr_end_p;
+
+	arch_decomp_setup();
+
+	tmp = (unsigned char *) (((unsigned long)input_data_end) - 4);
+	output_ptr = get_unaligned_le32(tmp);
+
+	arch_decomp_puts("Uncompressing Linux...");
+	decompress(input_data, input_data_end - input_data, NULL, NULL,
+			output_data, NULL, error);
+	arch_decomp_puts(" done, booting the kernel.\n");
+	return output_ptr;
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/piggy.S.in linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/piggy.S.in
--- linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/piggy.S.in	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/piggy.S.in	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+	.section .piggydata,#alloc
+	.globl	input_data
+input_data:
+	.incbin	"arch/unicore32/boot/compressed/piggy.DECOMP_SUFFIX"
+	.globl	input_data_end
+input_data_end:
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/vmlinux.lds.in linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/vmlinux.lds.in
--- linux-libre-2.6.38-gnu/arch/unicore32/boot/compressed/vmlinux.lds.in	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/boot/compressed/vmlinux.lds.in	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * linux/arch/unicore/boot/compressed/vmlinux.lds.in
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+OUTPUT_ARCH(unicore32)
+ENTRY(_start)
+SECTIONS
+{
+  /DISCARD/ : {
+    /*
+     * Discard any r/w data - this produces a link error if we have any,
+     * which is required for PIC decompression.  Local data generates
+     * GOTOFF relocations, which prevents it being relocated independently
+     * of the text/got segments.
+     */
+    *(.data)
+  }
+
+  . = TEXT_START;
+  _text = .;
+
+  .text : {
+    _start = .;
+    *(.start)
+    *(.text)
+    *(.text.*)
+    *(.fixup)
+    *(.gnu.warning)
+    *(.rodata)
+    *(.rodata.*)
+    *(.piggydata)
+    . = ALIGN(4);
+  }
+
+  _etext = .;
+
+  /* Assume size of decompressed image is 4x the compressed image */
+  _image_size = (_etext - _text) * 4;
+
+  _got_start = .;
+  .got			: { *(.got) }
+  _got_end = .;
+  .got.plt		: { *(.got.plt) }
+  _edata = .;
+
+  . = BSS_START;
+  __bss_start = .;
+  .bss			: { *(.bss) }
+  _end = .;
+
+  .stack		: { *(.stack) }
+  .comment 0		: { *(.comment) }
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/boot/Makefile linux-libre-2.6.39-gnu/arch/unicore32/boot/Makefile
--- linux-libre-2.6.38-gnu/arch/unicore32/boot/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/boot/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+#
+# arch/unicore32/boot/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# 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~2010 GUAN Xue-tao
+#
+
+MKIMAGE := $(srctree)/scripts/mkuboot.sh
+
+targets := Image zImage uImage
+
+$(obj)/Image: vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
+
+$(obj)/compressed/vmlinux: $(obj)/Image FORCE
+	$(Q)$(MAKE) $(build)=$(obj)/compressed $@
+
+$(obj)/zImage: $(obj)/compressed/vmlinux FORCE
+	$(call if_changed,objcopy)
+	@echo '  Kernel: $@ is ready'
+
+quiet_cmd_uimage = UIMAGE  $@
+      cmd_uimage = $(CONFIG_SHELL) $(MKIMAGE) -A unicore -O linux -T kernel \
+		   -C none -a $(LOADADDR) -e $(STARTADDR) \
+		   -n 'Linux-$(KERNELRELEASE)' -d $< $@
+
+$(obj)/uImage: LOADADDR=0x0
+
+$(obj)/uImage: STARTADDR=$(LOADADDR)
+
+$(obj)/uImage: $(obj)/zImage FORCE
+	$(call if_changed,uimage)
+	@echo '  Image $@ is ready'
+
+PHONY += initrd FORCE
+initrd:
+	@test "$(INITRD)" != "" || \
+	(echo You must specify INITRD; exit -1)
+
+subdir- := compressed
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/configs/debug_defconfig linux-libre-2.6.39-gnu/arch/unicore32/configs/debug_defconfig
--- linux-libre-2.6.38-gnu/arch/unicore32/configs/debug_defconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/configs/debug_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,215 @@
+### General setup
+CONFIG_EXPERIMENTAL=y
+CONFIG_LOCALVERSION="-debug"
+CONFIG_SWAP=y
+CONFIG_SYSVIPC=y
+CONFIG_POSIX_MQUEUE=y
+CONFIG_HOTPLUG=y
+#	Initial RAM filesystem and RAM disk (initramfs/initrd) support
+#CONFIG_BLK_DEV_INITRD=y
+#CONFIG_INITRAMFS_SOURCE="arch/unicore/ramfs/ramfs_config"
+
+### Enable loadable module support
+CONFIG_MODULES=n
+CONFIG_MODULE_UNLOAD=y
+
+### System Type
+CONFIG_ARCH_PUV3=y
+#	Board Selection
+CONFIG_PUV3_NB0916=y
+#	Processor Features
+CONFIG_CPU_DCACHE_LINE_DISABLE=y
+CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE=n
+
+### Bus support
+CONFIG_PCI=y
+CONFIG_PCI_LEGACY=n
+
+### Boot options
+#	for debug, adding: earlyprintk=ocd,keep initcall_debug
+#	others support: test_suspend=mem root=/dev/sda
+#	hibernate support: resume=/dev/sda3
+CONFIG_CMDLINE="earlyprintk=ocd,keep ignore_loglevel"
+# TODO: mem=512M video=unifb:1024x600-16@75
+# for nfs: root=/dev/nfs rw nfsroot=192.168.10.88:/home/udb/nfs/,rsize=1024,wsize=1024
+#	ip=192.168.10.83:192.168.10.88:192.168.10.1:255.255.255.0::eth0:off
+CONFIG_CMDLINE_FORCE=y
+
+### Power management options
+CONFIG_PM=y
+CONFIG_HIBERNATION=y
+CONFIG_PM_STD_PARTITION="/dev/sda3"
+CONFIG_CPU_FREQ=n
+CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE=y
+
+### Networking support
+CONFIG_NET=y
+#	Networking options
+CONFIG_PACKET=m
+CONFIG_UNIX=m
+#	TCP/IP networking
+CONFIG_INET=y
+CONFIG_IP_MULTICAST=y
+CONFIG_IP_PNP=y
+CONFIG_IPV6=n
+#	Wireless
+CONFIG_WIRELESS=y
+CONFIG_WIRELESS_EXT=y
+CONFIG_MAC80211=m
+
+### PKUnity SoC Features
+CONFIG_USB_WLAN_HED_AQ3=n
+CONFIG_USB_CMMB_INNOFIDEI=n
+CONFIG_I2C_BATTERY_BQ27200=n
+CONFIG_I2C_EEPROM_AT24=n
+CONFIG_LCD_BACKLIGHT=n
+
+CONFIG_PUV3_RTC=y
+CONFIG_PUV3_UMAL=y
+CONFIG_PUV3_MUSB=n
+CONFIG_PUV3_AC97=n
+CONFIG_PUV3_NAND=n
+CONFIG_PUV3_MMC=n
+CONFIG_PUV3_UART=n
+
+### Device Drivers
+#	Memory Technology Device (MTD) support
+CONFIG_MTD=m
+CONFIG_MTD_UBI=m
+CONFIG_MTD_PARTITIONS=y
+CONFIG_MTD_CHAR=m
+CONFIG_MTD_BLKDEVS=m
+#	RAM/ROM/Flash chip drivers
+CONFIG_MTD_CFI=m
+CONFIG_MTD_JEDECPROBE=m
+CONFIG_MTD_CFI_AMDSTD=m
+#	Mapping drivers for chip access
+CONFIG_MTD_PHYSMAP=m
+
+#	Block devices
+CONFIG_BLK_DEV_LOOP=m
+
+#	SCSI device support
+CONFIG_SCSI=y
+CONFIG_BLK_DEV_SD=y
+CONFIG_BLK_DEV_SR=m
+CONFIG_CHR_DEV_SG=m
+
+#	Serial ATA (prod) and Parallel ATA (experimental) drivers
+CONFIG_ATA=y
+CONFIG_SATA_VIA=y
+
+#	Network device support
+CONFIG_NETDEVICES=y
+CONFIG_NET_ETHERNET=y
+CONFIG_NETDEV_1000=y
+#	Wireless LAN
+CONFIG_WLAN_80211=n
+CONFIG_RT2X00=n
+CONFIG_RT73USB=n
+
+#	Input device support
+CONFIG_INPUT_EVDEV=m
+#	Keyboards
+CONFIG_KEYBOARD_GPIO=m
+
+#	I2C support
+CONFIG_I2C=y
+CONFIG_I2C_PUV3=y
+
+#	Hardware Monitoring support
+#CONFIG_SENSORS_LM75=m
+#	Generic Thermal sysfs driver
+#CONFIG_THERMAL=m
+#CONFIG_THERMAL_HWMON=y
+
+#	Multimedia support
+CONFIG_MEDIA_SUPPORT=n
+CONFIG_VIDEO_DEV=n
+CONFIG_USB_VIDEO_CLASS=n
+
+#	Graphics support
+CONFIG_FB=y
+CONFIG_FB_PUV3_UNIGFX=y
+#	Console display driver support
+CONFIG_VGA_CONSOLE=n
+CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_FONTS=y
+CONFIG_FONT_8x8=y
+CONFIG_FONT_8x16=y
+#	Bootup logo
+CONFIG_LOGO=n
+
+#	Sound card support
+CONFIG_SOUND=m
+#	Advanced Linux Sound Architecture
+CONFIG_SND=m
+CONFIG_SND_MIXER_OSS=m
+CONFIG_SND_PCM_OSS=m
+
+#	USB support
+CONFIG_USB_ARCH_HAS_HCD=n
+CONFIG_USB=n
+CONFIG_USB_DEVICEFS=n
+CONFIG_USB_PRINTER=n
+CONFIG_USB_STORAGE=n
+#	Inventra Highspeed Dual Role Controller
+CONFIG_USB_MUSB_HDRC=n
+
+#	LED Support
+CONFIG_NEW_LEDS=y
+CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_GPIO=y
+#	LED Triggers
+CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
+CONFIG_LEDS_TRIGGER_IDE_DISK=y
+CONFIG_LEDS_TRIGGER_HEARTBEAT=y
+
+#	Real Time Clock
+CONFIG_RTC_LIB=m
+CONFIG_RTC_CLASS=m
+
+### File systems
+CONFIG_EXT2_FS=m
+CONFIG_EXT3_FS=y
+CONFIG_EXT4_FS=y
+CONFIG_FUSE_FS=m
+#	CD-ROM/DVD Filesystems
+CONFIG_ISO9660_FS=m
+CONFIG_JOLIET=y
+CONFIG_UDF_FS=m
+#	DOS/FAT/NT Filesystems
+CONFIG_VFAT_FS=m
+#	Pseudo filesystems
+CONFIG_PROC_FS=y
+CONFIG_SYSFS=y
+CONFIG_TMPFS=y
+#	Miscellaneous filesystems
+CONFIG_MISC_FILESYSTEMS=y
+CONFIG_JFFS2_FS=m
+CONFIG_UBIFS_FS=m
+#	Network File Systems
+CONFIG_NETWORK_FILESYSTEMS=y
+CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
+CONFIG_ROOT_NFS=y
+#	Partition Types
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MSDOS_PARTITION=y
+#	Native language support
+CONFIG_NLS=y
+CONFIG_NLS_CODEPAGE_437=m
+CONFIG_NLS_CODEPAGE_936=m
+CONFIG_NLS_ISO8859_1=m
+CONFIG_NLS_UTF8=m
+
+### Kernel hacking
+CONFIG_FRAME_WARN=8096
+CONFIG_MAGIC_SYSRQ=y
+CONFIG_DEBUG_KERNEL=y
+CONFIG_PROVE_LOCKING=n
+CONFIG_DEBUG_BUGVERBOSE=y
+CONFIG_FRAME_POINTER=y
+CONFIG_DEBUG_LL=y
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/.gitignore linux-libre-2.6.39-gnu/arch/unicore32/.gitignore
--- linux-libre-2.6.38-gnu/arch/unicore32/.gitignore	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/.gitignore	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,21 @@
+#
+# Generated include files
+#
+include/generated
+#
+# Generated ld script file
+#
+kernel/vmlinux.lds
+#
+# Generated images in boot
+#
+boot/Image
+boot/zImage
+boot/uImage
+#
+# Generated files in boot/compressed
+#
+boot/compressed/piggy.S
+boot/compressed/piggy.gzip
+boot/compressed/vmlinux
+boot/compressed/vmlinux.lds
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/assembler.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/assembler.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/assembler.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/assembler.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/unicore32/include/asm/assembler.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  Do not include any C declarations in this file - it is included by
+ *  assembler source.
+ */
+#ifndef __ASSEMBLY__
+#error "Only include this from assembly code"
+#endif
+
+#include <asm/ptrace.h>
+
+/*
+ * Little Endian independent macros for shifting bytes within registers.
+ */
+#define pull            >>
+#define push            <<
+#define get_byte_0      << #0
+#define get_byte_1	>> #8
+#define get_byte_2	>> #16
+#define get_byte_3	>> #24
+#define put_byte_0      << #0
+#define put_byte_1	<< #8
+#define put_byte_2	<< #16
+#define put_byte_3	<< #24
+
+#define cadd		cmpadd
+#define cand		cmpand
+#define csub		cmpsub
+#define cxor		cmpxor
+
+/*
+ * Enable and disable interrupts
+ */
+	.macro disable_irq, temp
+	mov	\temp, asr
+	andn     \temp, \temp, #0xFF
+	or	\temp, \temp, #PSR_I_BIT | PRIV_MODE
+	mov.a	asr, \temp
+	.endm
+
+	.macro enable_irq, temp
+	mov	\temp, asr
+	andn     \temp, \temp, #0xFF
+	or	\temp, \temp, #PRIV_MODE
+	mov.a	asr, \temp
+	.endm
+
+#define USER(x...)				\
+9999:	x;					\
+	.pushsection __ex_table, "a";		\
+	.align	3;				\
+	.long	9999b, 9001f;			\
+	.popsection
+
+	.macro	notcond, cond, nexti = .+8
+	.ifc	\cond, eq
+		bne	\nexti
+	.else;	.ifc	\cond, ne
+		beq	\nexti
+	.else;	.ifc	\cond, ea
+		bub	\nexti
+	.else;	.ifc	\cond, ub
+		bea	\nexti
+	.else;	.ifc	\cond, fs
+		bns	\nexti
+	.else;	.ifc	\cond, ns
+		bfs	\nexti
+	.else;	.ifc	\cond, fv
+		bnv	\nexti
+	.else;	.ifc	\cond, nv
+		bfv	\nexti
+	.else;	.ifc	\cond, ua
+		beb	\nexti
+	.else;	.ifc	\cond, eb
+		bua	\nexti
+	.else;	.ifc	\cond, eg
+		bsl	\nexti
+	.else;	.ifc	\cond, sl
+		beg	\nexti
+	.else;	.ifc	\cond, sg
+		bel	\nexti
+	.else;	.ifc	\cond, el
+		bsg	\nexti
+	.else;	.ifnc	\cond, al
+		.error  "Unknown cond in notcond macro argument"
+	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
+	.endif;	.endif;	.endif;	.endif;	.endif;	.endif;	.endif
+	.endif
+	.endm
+
+	.macro	usracc, instr, reg, ptr, inc, cond, rept, abort
+	.rept	\rept
+	notcond	\cond, .+8
+9999 :
+	.if	\inc == 1
+	\instr\()b.u \reg, [\ptr], #\inc
+	.elseif	\inc == 4
+	\instr\()w.u \reg, [\ptr], #\inc
+	.else
+	.error	"Unsupported inc macro argument"
+	.endif
+
+	.pushsection __ex_table, "a"
+	.align	3
+	.long	9999b, \abort
+	.popsection
+	.endr
+	.endm
+
+	.macro	strusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
+	usracc	st, \reg, \ptr, \inc, \cond, \rept, \abort
+	.endm
+
+	.macro	ldrusr, reg, ptr, inc, cond = al, rept = 1, abort = 9001f
+	usracc	ld, \reg, \ptr, \inc, \cond, \rept, \abort
+	.endm
+
+	.macro	nop8
+	.rept	8
+		nop
+	.endr
+	.endm
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/bitops.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/unicore32/include/asm/bitops.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_BITOPS_H__
+#define __UNICORE_BITOPS_H__
+
+#define find_next_bit		__uc32_find_next_bit
+#define find_next_zero_bit	__uc32_find_next_zero_bit
+
+#define find_first_bit		__uc32_find_first_bit
+#define find_first_zero_bit	__uc32_find_first_zero_bit
+
+#define _ASM_GENERIC_BITOPS_FLS_H_
+#define _ASM_GENERIC_BITOPS___FLS_H_
+#define _ASM_GENERIC_BITOPS_FFS_H_
+#define _ASM_GENERIC_BITOPS___FFS_H_
+/*
+ * On UNICORE, those functions can be implemented around
+ * the cntlz instruction for much better code efficiency.
+ */
+
+static inline int fls(int x)
+{
+	int ret;
+
+	asm("cntlz\t%0, %1" : "=r" (ret) : "r" (x) : "cc");
+	ret = 32 - ret;
+
+	return ret;
+}
+
+#define __fls(x) (fls(x) - 1)
+#define ffs(x) ({ unsigned long __t = (x); fls(__t & -__t); })
+#define __ffs(x) (ffs(x) - 1)
+
+#include <asm-generic/bitops.h>
+
+#endif /* __UNICORE_BITOPS_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/byteorder.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/byteorder.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/byteorder.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/byteorder.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/asm/byteorder.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * UniCore ONLY support Little Endian mode, the data bus is connected such
+ * that byte accesses appear as:
+ *  0 = d0...d7, 1 = d8...d15, 2 = d16...d23, 3 = d24...d31
+ * and word accesses (data or instruction) appear as:
+ *  d0...d31
+ */
+#ifndef __UNICORE_BYTEORDER_H__
+#define __UNICORE_BYTEORDER_H__
+
+#include <linux/byteorder/little_endian.h>
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cacheflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,211 @@
+/*
+ * linux/arch/unicore32/include/asm/cacheflush.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_CACHEFLUSH_H__
+#define __UNICORE_CACHEFLUSH_H__
+
+#include <linux/mm.h>
+
+#include <asm/shmparam.h>
+
+#define CACHE_COLOUR(vaddr)	((vaddr & (SHMLBA - 1)) >> PAGE_SHIFT)
+
+/*
+ * This flag is used to indicate that the page pointed to by a pte is clean
+ * and does not require cleaning before returning it to the user.
+ */
+#define PG_dcache_clean PG_arch_1
+
+/*
+ *	MM Cache Management
+ *	===================
+ *
+ *	The arch/unicore32/mm/cache.S files implement these methods.
+ *
+ *	Start addresses are inclusive and end addresses are exclusive;
+ *	start addresses should be rounded down, end addresses up.
+ *
+ *	See Documentation/cachetlb.txt for more information.
+ *	Please note that the implementation of these, and the required
+ *	effects are cache-type (VIVT/VIPT/PIPT) specific.
+ *
+ *	flush_icache_all()
+ *
+ *		Unconditionally clean and invalidate the entire icache.
+ *		Currently only needed for cache-v6.S and cache-v7.S, see
+ *		__flush_icache_all for the generic implementation.
+ *
+ *	flush_kern_all()
+ *
+ *		Unconditionally clean and invalidate the entire cache.
+ *
+ *	flush_user_all()
+ *
+ *		Clean and invalidate all user space cache entries
+ *		before a change of page tables.
+ *
+ *	flush_user_range(start, end, flags)
+ *
+ *		Clean and invalidate a range of cache entries in the
+ *		specified address space before a change of page tables.
+ *		- start - user start address (inclusive, page aligned)
+ *		- end   - user end address   (exclusive, page aligned)
+ *		- flags - vma->vm_flags field
+ *
+ *	coherent_kern_range(start, end)
+ *
+ *		Ensure coherency between the Icache and the Dcache in the
+ *		region described by start, end.  If you have non-snooping
+ *		Harvard caches, you need to implement this function.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	coherent_user_range(start, end)
+ *
+ *		Ensure coherency between the Icache and the Dcache in the
+ *		region described by start, end.  If you have non-snooping
+ *		Harvard caches, you need to implement this function.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ *
+ *	flush_kern_dcache_area(kaddr, size)
+ *
+ *		Ensure that the data held in page is written back.
+ *		- kaddr  - page address
+ *		- size   - region size
+ *
+ *	DMA Cache Coherency
+ *	===================
+ *
+ *	dma_flush_range(start, end)
+ *
+ *		Clean and invalidate the specified virtual address range.
+ *		- start  - virtual start address
+ *		- end    - virtual end address
+ */
+
+extern void __cpuc_flush_icache_all(void);
+extern void __cpuc_flush_kern_all(void);
+extern void __cpuc_flush_user_all(void);
+extern void __cpuc_flush_user_range(unsigned long, unsigned long, unsigned int);
+extern void __cpuc_coherent_kern_range(unsigned long, unsigned long);
+extern void __cpuc_coherent_user_range(unsigned long, unsigned long);
+extern void __cpuc_flush_dcache_area(void *, size_t);
+extern void __cpuc_flush_kern_dcache_area(void *addr, size_t size);
+
+/*
+ * These are private to the dma-mapping API.  Do not use directly.
+ * Their sole purpose is to ensure that data held in the cache
+ * is visible to DMA, or data written by DMA to system memory is
+ * visible to the CPU.
+ */
+extern void __cpuc_dma_clean_range(unsigned long, unsigned long);
+extern void __cpuc_dma_flush_range(unsigned long, unsigned long);
+
+/*
+ * Copy user data from/to a page which is mapped into a different
+ * processes address space.  Really, we want to allow our "user
+ * space" model to handle this.
+ */
+extern void copy_to_user_page(struct vm_area_struct *, struct page *,
+	unsigned long, void *, const void *, unsigned long);
+#define copy_from_user_page(vma, page, vaddr, dst, src, len)	\
+	do {							\
+		memcpy(dst, src, len);				\
+	} while (0)
+
+/*
+ * Convert calls to our calling convention.
+ */
+/* Invalidate I-cache */
+static inline void __flush_icache_all(void)
+{
+	asm("movc	p0.c5, %0, #20;\n"
+	    "nop; nop; nop; nop; nop; nop; nop; nop\n"
+	    :
+	    : "r" (0));
+}
+
+#define flush_cache_all()		__cpuc_flush_kern_all()
+
+extern void flush_cache_mm(struct mm_struct *mm);
+extern void flush_cache_range(struct vm_area_struct *vma,
+		unsigned long start, unsigned long end);
+extern void flush_cache_page(struct vm_area_struct *vma,
+		unsigned long user_addr, unsigned long pfn);
+
+#define flush_cache_dup_mm(mm) flush_cache_mm(mm)
+
+/*
+ * flush_cache_user_range is used when we want to ensure that the
+ * Harvard caches are synchronised for the user space address range.
+ * This is used for the UniCore private sys_cacheflush system call.
+ */
+#define flush_cache_user_range(vma, start, end) \
+	__cpuc_coherent_user_range((start) & PAGE_MASK, PAGE_ALIGN(end))
+
+/*
+ * Perform necessary cache operations to ensure that data previously
+ * stored within this range of addresses can be executed by the CPU.
+ */
+#define flush_icache_range(s, e)	__cpuc_coherent_kern_range(s, e)
+
+/*
+ * Perform necessary cache operations to ensure that the TLB will
+ * see data written in the specified area.
+ */
+#define clean_dcache_area(start, size)	cpu_dcache_clean_area(start, size)
+
+/*
+ * flush_dcache_page is used when the kernel has written to the page
+ * cache page at virtual address page->virtual.
+ *
+ * If this page isn't mapped (ie, page_mapping == NULL), or it might
+ * have userspace mappings, then we _must_ always clean + invalidate
+ * the dcache entries associated with the kernel mapping.
+ *
+ * Otherwise we can defer the operation, and clean the cache when we are
+ * about to change to user space.  This is the same method as used on SPARC64.
+ * See update_mmu_cache for the user space part.
+ */
+#define ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE 1
+extern void flush_dcache_page(struct page *);
+
+#define flush_dcache_mmap_lock(mapping)			\
+	spin_lock_irq(&(mapping)->tree_lock)
+#define flush_dcache_mmap_unlock(mapping)		\
+	spin_unlock_irq(&(mapping)->tree_lock)
+
+#define flush_icache_user_range(vma, page, addr, len)	\
+	flush_dcache_page(page)
+
+/*
+ * We don't appear to need to do anything here.  In fact, if we did, we'd
+ * duplicate cache flushing elsewhere performed by flush_dcache_page().
+ */
+#define flush_icache_page(vma, page)	do { } while (0)
+
+/*
+ * flush_cache_vmap() is used when creating mappings (eg, via vmap,
+ * vmalloc, ioremap etc) in kernel space for pages.  On non-VIPT
+ * caches, since the direct-mappings of these pages may contain cached
+ * data, we need to do a full cache flush to ensure that writebacks
+ * don't corrupt data placed into these pages via the new mappings.
+ */
+static inline void flush_cache_vmap(unsigned long start, unsigned long end)
+{
+}
+
+static inline void flush_cache_vunmap(unsigned long start, unsigned long end)
+{
+}
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cache.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cache.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cache.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cache.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,27 @@
+/*
+ * linux/arch/unicore32/include/asm/cache.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_CACHE_H__
+#define __UNICORE_CACHE_H__
+
+#define L1_CACHE_SHIFT		(5)
+#define L1_CACHE_BYTES		(1 << L1_CACHE_SHIFT)
+
+/*
+ * Memory returned by kmalloc() may be used for DMA, so we must make
+ * sure that all such allocations are cache aligned. Otherwise,
+ * unrelated code may cause parts of the buffer to be read into the
+ * cache before the transfer is done, causing old data to be seen by
+ * the CPU.
+ */
+#define ARCH_DMA_MINALIGN	L1_CACHE_BYTES
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/checksum.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/checksum.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/checksum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/checksum.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * linux/arch/unicore32/include/asm/checksum.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * IP checksum routines
+ */
+#ifndef __UNICORE_CHECKSUM_H__
+#define __UNICORE_CHECKSUM_H__
+
+/*
+ * computes the checksum of the TCP/UDP pseudo-header
+ * returns a 16-bit checksum, already complemented
+ */
+
+static inline __wsum
+csum_tcpudp_nofold(__be32 saddr, __be32 daddr, unsigned short len,
+		   unsigned short proto, __wsum sum)
+{
+	__asm__(
+	"add.a	%0, %1, %2\n"
+	"addc.a	%0, %0, %3\n"
+	"addc.a	%0, %0, %4 << #8\n"
+	"addc.a	%0, %0, %5\n"
+	"addc	%0, %0, #0\n"
+	: "=&r"(sum)
+	: "r" (sum), "r" (daddr), "r" (saddr), "r" (len), "Ir" (htons(proto))
+	: "cc");
+	return sum;
+}
+#define csum_tcpudp_nofold	csum_tcpudp_nofold
+
+#include <asm-generic/checksum.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cpu-single.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cpu-single.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cpu-single.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cpu-single.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/unicore32/include/asm/cpu-single.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_CPU_SINGLE_H__
+#define __UNICORE_CPU_SINGLE_H__
+
+#include <asm/page.h>
+#include <asm/memory.h>
+
+#ifdef __KERNEL__
+#ifndef __ASSEMBLY__
+
+#define cpu_switch_mm(pgd, mm) cpu_do_switch_mm(virt_to_phys(pgd), mm)
+
+#define cpu_get_pgd()					\
+	({						\
+		unsigned long pg;			\
+		__asm__("movc	%0, p0.c2, #0"		\
+			 : "=r" (pg) : : "cc");		\
+		pg &= ~0x0fff;				\
+		(pgd_t *)phys_to_virt(pg);		\
+	})
+
+struct mm_struct;
+
+/* declare all the functions as extern */
+extern void cpu_proc_fin(void);
+extern int cpu_do_idle(void);
+extern void cpu_dcache_clean_area(void *, int);
+extern void cpu_do_switch_mm(unsigned long pgd_phys, struct mm_struct *mm);
+extern void cpu_set_pte(pte_t *ptep, pte_t pte);
+extern void cpu_reset(unsigned long addr) __attribute__((noreturn));
+
+#endif /* __ASSEMBLY__ */
+#endif /* __KERNEL__ */
+
+#endif /* __UNICORE_CPU_SINGLE_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cputype.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cputype.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/cputype.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/cputype.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ * linux/arch/unicore32/include/asm/cputype.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_CPUTYPE_H__
+#define __UNICORE_CPUTYPE_H__
+
+#include <linux/stringify.h>
+
+#define CPUID_CPUID	0
+#define CPUID_CACHETYPE	1
+
+#define read_cpuid(reg)							\
+	({								\
+		unsigned int __val;					\
+		asm("movc	%0, p0.c0, #" __stringify(reg)		\
+		    : "=r" (__val)					\
+		    :							\
+		    : "cc");						\
+		__val;							\
+	})
+
+#define uc32_cpuid		read_cpuid(CPUID_CPUID)
+#define uc32_cachetype		read_cpuid(CPUID_CACHETYPE)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/delay.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/delay.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/delay.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/delay.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,52 @@
+/*
+ * linux/arch/unicore32/include/asm/delay.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * Delay routines, using a pre-computed "loops_per_second" value.
+ */
+#ifndef __UNICORE_DELAY_H__
+#define __UNICORE_DELAY_H__
+
+#include <asm/param.h>	/* HZ */
+
+extern void __delay(int loops);
+
+/*
+ * This function intentionally does not exist; if you see references to
+ * it, it means that you're calling udelay() with an out of range value.
+ *
+ * With currently imposed limits, this means that we support a max delay
+ * of 2000us. Further limits: HZ<=1000 and bogomips<=3355
+ */
+extern void __bad_udelay(void);
+
+/*
+ * division by multiplication: you don't have to worry about
+ * loss of precision.
+ *
+ * Use only for very small delays ( < 1 msec).  Should probably use a
+ * lookup table, really, as the multiplications take much too long with
+ * short delays.  This is a "reasonable" implementation, though (and the
+ * first constant multiplications gets optimized away if the delay is
+ * a constant)
+ */
+extern void __udelay(unsigned long usecs);
+extern void __const_udelay(unsigned long);
+
+#define MAX_UDELAY_MS 2
+
+#define udelay(n)							\
+	(__builtin_constant_p(n) ?					\
+	  ((n) > (MAX_UDELAY_MS * 1000) ? __bad_udelay() :		\
+			__const_udelay((n) * ((2199023U*HZ)>>11))) :	\
+	  __udelay(n))
+
+#endif /* __UNICORE_DELAY_H__ */
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/dma.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/dma.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/unicore32/include/asm/dma.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_DMA_H__
+#define __UNICORE_DMA_H__
+
+#include <asm/memory.h>
+#include <asm-generic/dma.h>
+
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#endif
+
+#endif /* __UNICORE_DMA_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/dma-mapping.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/dma-mapping.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/dma-mapping.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/dma-mapping.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,124 @@
+/*
+ * linux/arch/unicore32/include/asm/dma-mapping.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_DMA_MAPPING_H__
+#define __UNICORE_DMA_MAPPING_H__
+
+#ifdef __KERNEL__
+
+#include <linux/mm_types.h>
+#include <linux/scatterlist.h>
+#include <linux/swiotlb.h>
+
+#include <asm-generic/dma-coherent.h>
+
+#include <asm/memory.h>
+#include <asm/cacheflush.h>
+
+extern struct dma_map_ops swiotlb_dma_map_ops;
+
+static inline struct dma_map_ops *get_dma_ops(struct device *dev)
+{
+	return &swiotlb_dma_map_ops;
+}
+
+static inline int dma_supported(struct device *dev, u64 mask)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (unlikely(dma_ops == NULL))
+		return 0;
+
+	return dma_ops->dma_supported(dev, mask);
+}
+
+static inline int dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	if (dma_ops->mapping_error)
+		return dma_ops->mapping_error(dev, dma_addr);
+
+	return 0;
+}
+
+#include <asm-generic/dma-mapping-common.h>
+
+static inline bool dma_capable(struct device *dev, dma_addr_t addr, size_t size)
+{
+	if (dev && dev->dma_mask)
+		return addr + size - 1 <= *dev->dma_mask;
+
+	return 1;
+}
+
+static inline dma_addr_t phys_to_dma(struct device *dev, phys_addr_t paddr)
+{
+	return paddr;
+}
+
+static inline phys_addr_t dma_to_phys(struct device *dev, dma_addr_t daddr)
+{
+	return daddr;
+}
+
+static inline void dma_mark_clean(void *addr, size_t size) {}
+
+static inline int dma_set_mask(struct device *dev, u64 dma_mask)
+{
+	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
+		return -EIO;
+
+	*dev->dma_mask = dma_mask;
+
+	return 0;
+}
+
+static inline void *dma_alloc_coherent(struct device *dev, size_t size,
+				       dma_addr_t *dma_handle, gfp_t flag)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	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)
+{
+	struct dma_map_ops *dma_ops = get_dma_ops(dev);
+
+	dma_ops->free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
+#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 void dma_cache_sync(struct device *dev, void *vaddr,
+		size_t size, enum dma_data_direction direction)
+{
+	unsigned long start = (unsigned long)vaddr;
+	unsigned long end   = start + size;
+
+	switch (direction) {
+	case DMA_NONE:
+		BUG();
+	case DMA_FROM_DEVICE:
+	case DMA_BIDIRECTIONAL:	/* writeback and invalidate */
+		__cpuc_dma_flush_range(start, end);
+		break;
+	case DMA_TO_DEVICE:		/* writeback only */
+		__cpuc_dma_clean_range(start, end);
+		break;
+	}
+}
+
+#endif /* __KERNEL__ */
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/elf.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/elf.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/elf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/elf.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * linux/arch/unicore32/include/asm/elf.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_ELF_H__
+#define __UNICORE_ELF_H__
+
+#include <asm/hwcap.h>
+
+/*
+ * ELF register definitions..
+ */
+#include <asm/ptrace.h>
+
+typedef unsigned long elf_greg_t;
+typedef unsigned long elf_freg_t[3];
+
+#define ELF_NGREG (sizeof(struct pt_regs) / sizeof(elf_greg_t))
+typedef elf_greg_t elf_gregset_t[ELF_NGREG];
+
+typedef struct fp_state elf_fpregset_t;
+
+#define EM_UNICORE		110
+
+#define R_UNICORE_NONE		0
+#define R_UNICORE_PC24		1
+#define R_UNICORE_ABS32		2
+#define R_UNICORE_CALL		28
+#define R_UNICORE_JUMP24	29
+
+/*
+ * These are used to set parameters in the core dumps.
+ */
+#define ELF_CLASS	ELFCLASS32
+#define ELF_DATA	ELFDATA2LSB
+#define ELF_ARCH	EM_UNICORE
+
+/*
+ * 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.
+ *
+ */
+#define ELF_PLATFORM_SIZE 8
+#define ELF_PLATFORM	(elf_platform)
+
+extern char elf_platform[];
+
+struct elf32_hdr;
+
+/*
+ * This is used to ensure we don't load something for the wrong architecture.
+ */
+extern int elf_check_arch(const struct elf32_hdr *);
+#define elf_check_arch elf_check_arch
+
+struct task_struct;
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs);
+#define ELF_CORE_COPY_TASK_REGS dump_task_regs
+
+#define ELF_EXEC_PAGESIZE	4096
+
+/* 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	(2 * TASK_SIZE / 3)
+
+/* When the program starts, a1 contains a pointer to a function to be
+   registered with atexit, as per the SVR4 ABI.  A value of 0 means we
+   have no such handler.  */
+#define ELF_PLAT_INIT(_r, load_addr)	{(_r)->UCreg_00 = 0; }
+
+extern void elf_set_personality(const struct elf32_hdr *);
+#define SET_PERSONALITY(ex)	elf_set_personality(&(ex))
+
+struct mm_struct;
+extern unsigned long arch_randomize_brk(struct mm_struct *mm);
+#define arch_randomize_brk arch_randomize_brk
+
+extern int vectors_user_mapping(void);
+#define arch_setup_additional_pages(bprm, uses_interp) vectors_user_mapping()
+#define ARCH_HAS_SETUP_ADDITIONAL_PAGES
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/fpstate.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/fpstate.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/fpstate.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/fpstate.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+/*
+ * linux/arch/unicore32/include/asm/fpstate.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_FPSTATE_H__
+#define __UNICORE_FPSTATE_H__
+
+#ifndef __ASSEMBLY__
+
+#define FP_REGS_NUMBER		33
+
+struct fp_state {
+	unsigned int regs[FP_REGS_NUMBER];
+} __attribute__((aligned(8)));
+
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/fpu-ucf64.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/fpu-ucf64.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/fpu-ucf64.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/fpu-ucf64.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * linux/arch/unicore32/include/asm/fpu-ucf64.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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 FPSCR			s31
+
+/* FPSCR bits */
+#define FPSCR_DEFAULT_NAN	(1<<25)
+
+#define FPSCR_CMPINSTR_BIT	(1<<31)
+
+#define FPSCR_CON		(1<<29)
+#define FPSCR_TRAP		(1<<27)
+
+/* RND mode */
+#define FPSCR_ROUND_NEAREST	(0<<0)
+#define FPSCR_ROUND_PLUSINF	(2<<0)
+#define FPSCR_ROUND_MINUSINF	(3<<0)
+#define FPSCR_ROUND_TOZERO	(1<<0)
+#define FPSCR_RMODE_BIT		(0)
+#define FPSCR_RMODE_MASK	(7 << FPSCR_RMODE_BIT)
+
+/* trap enable */
+#define FPSCR_IOE		(1<<16)
+#define FPSCR_OFE		(1<<14)
+#define FPSCR_UFE		(1<<13)
+#define FPSCR_IXE		(1<<12)
+#define FPSCR_HIE		(1<<11)
+#define FPSCR_NDE		(1<<10)	/* non denomal */
+
+/* flags */
+#define FPSCR_IDC		(1<<24)
+#define FPSCR_HIC		(1<<23)
+#define FPSCR_IXC		(1<<22)
+#define FPSCR_OFC		(1<<21)
+#define FPSCR_UFC		(1<<20)
+#define FPSCR_IOC		(1<<19)
+
+/* stick bits */
+#define FPSCR_IOS		(1<<9)
+#define FPSCR_OFS		(1<<7)
+#define FPSCR_UFS		(1<<6)
+#define FPSCR_IXS		(1<<5)
+#define FPSCR_HIS		(1<<4)
+#define FPSCR_NDS		(1<<3)	/*non denomal */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/gpio.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/gpio.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,104 @@
+/*
+ * linux/arch/unicore32/include/asm/gpio.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_GPIO_H__
+#define __UNICORE_GPIO_H__
+
+#include <linux/io.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <asm-generic/gpio.h>
+
+#define GPI_OTP_INT             0
+#define GPI_PCI_INTA            1
+#define GPI_PCI_INTB            2
+#define GPI_PCI_INTC            3
+#define GPI_PCI_INTD            4
+#define GPI_BAT_DET             5
+#define GPI_SD_CD               6
+#define GPI_SOFF_REQ            7
+#define GPI_SD_WP               8
+#define GPI_LCD_CASE_OFF        9
+#define GPO_WIFI_EN             10
+#define GPO_HDD_LED             11
+#define GPO_VGA_EN              12
+#define GPO_LCD_EN              13
+#define GPO_LED_DATA            14
+#define GPO_LED_CLK             15
+#define GPO_CAM_PWR_EN          16
+#define GPO_LCD_VCC_EN          17
+#define GPO_SOFT_OFF            18
+#define GPO_BT_EN               19
+#define GPO_FAN_ON              20
+#define GPO_SPKR                21
+#define GPO_SET_V1              23
+#define GPO_SET_V2              24
+#define GPO_CPU_HEALTH          25
+#define GPO_LAN_SEL             26
+
+#ifdef CONFIG_PUV3_NB0916
+#define GPI_BTN_TOUCH		14
+#define GPIO_IN			0x000043ff /* 1 for input */
+#define GPIO_OUT		0x0fffbc00 /* 1 for output */
+#endif	/* CONFIG_PUV3_NB0916 */
+
+#ifdef CONFIG_PUV3_SMW0919
+#define GPIO_IN			0x000003ff /* 1 for input */
+#define GPIO_OUT		0x0ffffc00 /* 1 for output */
+#endif  /* CONFIG_PUV3_SMW0919 */
+
+#ifdef CONFIG_PUV3_DB0913
+#define GPIO_IN			0x000001df /* 1 for input */
+#define GPIO_OUT		0x03fee800 /* 1 for output */
+#endif  /* CONFIG_PUV3_DB0913 */
+
+#define GPIO_DIR                (~((GPIO_IN) | 0xf0000000))
+				/* 0 input, 1 output */
+
+static inline int gpio_get_value(unsigned gpio)
+{
+	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
+		return readl(GPIO_GPLR) & GPIO_GPIO(gpio);
+	else
+		return __gpio_get_value(gpio);
+}
+
+static inline void gpio_set_value(unsigned gpio, int value)
+{
+	if (__builtin_constant_p(gpio) && (gpio <= GPIO_MAX))
+		if (value)
+			writel(GPIO_GPIO(gpio), GPIO_GPSR);
+		else
+			writel(GPIO_GPIO(gpio), GPIO_GPCR);
+	else
+		__gpio_set_value(gpio, value);
+}
+
+#define gpio_cansleep	__gpio_cansleep
+
+static inline unsigned gpio_to_irq(unsigned gpio)
+{
+	if ((gpio < IRQ_GPIOHIGH) && (FIELD(1, 1, gpio) & readl(GPIO_GPIR)))
+		return IRQ_GPIOLOW0 + gpio;
+	else
+		return IRQ_GPIO0 + gpio;
+}
+
+static inline unsigned irq_to_gpio(unsigned irq)
+{
+	if (irq < IRQ_GPIOHIGH)
+		return irq - IRQ_GPIOLOW0;
+	else
+		return irq - IRQ_GPIO0;
+}
+
+#endif /* __UNICORE_GPIO_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/hwcap.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/hwcap.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/hwcap.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/hwcap.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * linux/arch/unicore32/include/asm/hwcap.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_HWCAP_H__
+#define __UNICORE_HWCAP_H__
+
+/*
+ * HWCAP flags
+ */
+#define HWCAP_MSP		1
+#define HWCAP_UNICORE16		2
+#define HWCAP_CMOV		4
+#define HWCAP_UNICORE_F64       8
+#define HWCAP_TLS		0x80
+
+#if defined(__KERNEL__) && !defined(__ASSEMBLY__)
+/*
+ * This yields a mask that user programs can use to figure out what
+ * instruction set this cpu supports.
+ */
+#define ELF_HWCAP		(HWCAP_CMOV | HWCAP_UNICORE_F64)
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/io.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/io.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/unicore32/include/asm/io.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_IO_H__
+#define __UNICORE_IO_H__
+
+#ifdef __KERNEL__
+
+#include <asm/byteorder.h>
+#include <asm/memory.h>
+#include <asm/system.h>
+
+#define PCI_IOBASE	PKUNITY_PCILIO_BASE
+#include <asm-generic/io.h>
+
+/*
+ * __uc32_ioremap and __uc32_ioremap_cached takes CPU physical address.
+ */
+extern void __iomem *__uc32_ioremap(unsigned long, size_t);
+extern void __iomem *__uc32_ioremap_cached(unsigned long, size_t);
+extern void __uc32_iounmap(volatile void __iomem *addr);
+
+/*
+ * ioremap and friends.
+ *
+ * ioremap takes a PCI memory address, as specified in
+ * Documentation/IO-mapping.txt.
+ *
+ */
+#define ioremap(cookie, size)		__uc32_ioremap(cookie, size)
+#define ioremap_cached(cookie, size)	__uc32_ioremap_cached(cookie, size)
+#define iounmap(cookie)			__uc32_iounmap(cookie)
+
+/*
+ * Convert a physical pointer to a virtual kernel pointer for /dev/mem
+ * access
+ */
+#undef xlate_dev_mem_ptr
+#define xlate_dev_mem_ptr(p)	__va(p)
+
+#define HAVE_ARCH_PIO_SIZE
+#define PIO_OFFSET		(unsigned int)(PCI_IOBASE)
+#define PIO_MASK		(unsigned int)(IO_SPACE_LIMIT)
+#define PIO_RESERVED		(PIO_OFFSET + PIO_MASK + 1)
+
+#endif	/* __KERNEL__ */
+#endif	/* __UNICORE_IO_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/irqflags.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/irqflags.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/irqflags.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/irqflags.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,53 @@
+/*
+ * linux/arch/unicore32/include/asm/irqflags.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_IRQFLAGS_H__
+#define __UNICORE_IRQFLAGS_H__
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+
+#define ARCH_IRQ_DISABLED	(PRIV_MODE | PSR_I_BIT)
+#define ARCH_IRQ_ENABLED	(PRIV_MODE)
+
+/*
+ * Save the current interrupt enable state.
+ */
+static inline unsigned long arch_local_save_flags(void)
+{
+	unsigned long temp;
+
+	asm volatile("mov %0, asr" : "=r" (temp) : : "memory", "cc");
+
+	return temp & PSR_c;
+}
+
+/*
+ * restore saved IRQ state
+ */
+static inline void arch_local_irq_restore(unsigned long flags)
+{
+	unsigned long temp;
+
+	asm volatile(
+		"mov	%0, asr\n"
+		"mov.a	asr, %1\n"
+		"mov.f	asr, %0"
+		: "=&r" (temp)
+		: "r" (flags)
+		: "memory", "cc");
+}
+
+#include <asm-generic/irqflags.h>
+
+#endif
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/irq.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/irq.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/irq.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,105 @@
+/*
+ * linux/arch/unicore32/include/asm/irq.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_IRQ_H__
+#define __UNICORE_IRQ_H__
+
+#include <asm-generic/irq.h>
+
+#define	IRQ_GPIOLOW0		0x00
+#define	IRQ_GPIOLOW1		0x01
+#define	IRQ_GPIOLOW2		0x02
+#define	IRQ_GPIOLOW3		0x03
+#define	IRQ_GPIOLOW4		0x04
+#define	IRQ_GPIOLOW5		0x05
+#define	IRQ_GPIOLOW6		0x06
+#define	IRQ_GPIOLOW7		0x07
+#define IRQ_GPIOHIGH		0x08
+#define IRQ_USB			0x09
+#define IRQ_SDC			0x0a
+#define IRQ_AC97		0x0b
+#define IRQ_SATA		0x0c
+#define IRQ_MME			0x0d
+#define IRQ_PCI_BRIDGE		0x0e
+#define	IRQ_DDR			0x0f
+#define	IRQ_SPI			0x10
+#define	IRQ_UNIGFX		0x11
+#define	IRQ_I2C			0x11
+#define	IRQ_UART1		0x12
+#define	IRQ_UART0		0x13
+#define IRQ_UMAL		0x14
+#define IRQ_NAND		0x15
+#define IRQ_PS2_KBD		0x16
+#define IRQ_PS2_AUX		0x17
+#define IRQ_DMA			0x18
+#define IRQ_DMAERR		0x19
+#define	IRQ_TIMER0		0x1a
+#define	IRQ_TIMER1		0x1b
+#define	IRQ_TIMER2		0x1c
+#define	IRQ_TIMER3		0x1d
+#define	IRQ_RTC			0x1e
+#define	IRQ_RTCAlarm		0x1f
+
+#define	IRQ_GPIO0		0x20
+#define	IRQ_GPIO1		0x21
+#define	IRQ_GPIO2		0x22
+#define	IRQ_GPIO3		0x23
+#define	IRQ_GPIO4		0x24
+#define	IRQ_GPIO5		0x25
+#define	IRQ_GPIO6		0x26
+#define	IRQ_GPIO7		0x27
+#define IRQ_GPIO8		0x28
+#define IRQ_GPIO9		0x29
+#define IRQ_GPIO10		0x2a
+#define IRQ_GPIO11		0x2b
+#define IRQ_GPIO12		0x2c
+#define IRQ_GPIO13		0x2d
+#define IRQ_GPIO14		0x2e
+#define IRQ_GPIO15		0x2f
+#define IRQ_GPIO16		0x30
+#define IRQ_GPIO17		0x31
+#define IRQ_GPIO18		0x32
+#define IRQ_GPIO19		0x33
+#define IRQ_GPIO20		0x34
+#define IRQ_GPIO21		0x35
+#define IRQ_GPIO22		0x36
+#define IRQ_GPIO23		0x37
+#define IRQ_GPIO24		0x38
+#define IRQ_GPIO25		0x39
+#define IRQ_GPIO26		0x3a
+#define IRQ_GPIO27		0x3b
+
+#ifdef CONFIG_ARCH_FPGA
+#define IRQ_PCIINTA             IRQ_GPIOLOW2
+#define IRQ_PCIINTB             IRQ_GPIOLOW1
+#define IRQ_PCIINTC             IRQ_GPIOLOW0
+#define IRQ_PCIINTD             IRQ_GPIOLOW6
+#endif
+
+#if defined(CONFIG_PUV3_DB0913) || defined(CONFIG_PUV3_NB0916)	\
+	|| defined(CONFIG_PUV3_SMW0919)
+#define IRQ_PCIINTA             IRQ_GPIOLOW1
+#define IRQ_PCIINTB             IRQ_GPIOLOW2
+#define IRQ_PCIINTC             IRQ_GPIOLOW3
+#define IRQ_PCIINTD             IRQ_GPIOLOW4
+#endif
+
+#define IRQ_SD_CD               IRQ_GPIO6 /* falling or rising trigger */
+
+#ifndef __ASSEMBLY__
+struct pt_regs;
+
+extern void asm_do_IRQ(unsigned int, struct pt_regs *);
+
+#endif
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/Kbuild linux-libre-2.6.39-gnu/arch/unicore32/include/asm/Kbuild
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/Kbuild	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/Kbuild	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2 @@
+include include/asm-generic/Kbuild.asm
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/linkage.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/linkage.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/linkage.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/linkage.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+/*
+ * linux/arch/unicore32/include/asm/linkage.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_LINKAGE_H__
+#define __UNICORE_LINKAGE_H__
+
+#define __ALIGN .align 0
+#define __ALIGN_STR ".align 0"
+
+#define ENDPROC(name) \
+	.type name, %function; \
+	END(name)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/memblock.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/memblock.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/memblock.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/memblock.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/unicore32/include/asm/memblock.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_MEMBLOCK_H__
+#define __UNICORE_MEMBLOCK_H__
+
+/*
+ * Memory map description
+ */
+# define NR_BANKS 8
+
+struct membank {
+	unsigned long start;
+	unsigned long size;
+	unsigned int highmem;
+};
+
+struct meminfo {
+	int nr_banks;
+	struct membank bank[NR_BANKS];
+};
+
+extern struct meminfo meminfo;
+
+#define for_each_bank(iter, mi)				\
+	for (iter = 0; iter < (mi)->nr_banks; iter++)
+
+#define bank_pfn_start(bank)	__phys_to_pfn((bank)->start)
+#define bank_pfn_end(bank)	__phys_to_pfn((bank)->start + (bank)->size)
+#define bank_pfn_size(bank)	((bank)->size >> PAGE_SHIFT)
+#define bank_phys_start(bank)	((bank)->start)
+#define bank_phys_end(bank)	((bank)->start + (bank)->size)
+#define bank_phys_size(bank)	((bank)->size)
+
+extern void uc32_memblock_init(struct meminfo *);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/memory.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/memory.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/unicore32/include/asm/memory.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 file should not be included by non-asm/.h files
+ */
+#ifndef __UNICORE_MEMORY_H__
+#define __UNICORE_MEMORY_H__
+
+#include <linux/compiler.h>
+#include <linux/const.h>
+#include <asm/sizes.h>
+#include <mach/memory.h>
+
+/*
+ * Allow for constants defined here to be used from assembly code
+ * by prepending the UL suffix only with actual C code compilation.
+ */
+#define UL(x) _AC(x, UL)
+
+/*
+ * PAGE_OFFSET - the virtual address of the start of the kernel image
+ * TASK_SIZE - the maximum size of a user space task.
+ * TASK_UNMAPPED_BASE - the lower boundary of the mmap VM area
+ */
+#define PAGE_OFFSET		UL(0xC0000000)
+#define TASK_SIZE		(PAGE_OFFSET - UL(0x41000000))
+#define TASK_UNMAPPED_BASE	(PAGE_OFFSET / 3)
+
+/*
+ * The module space lives between the addresses given by TASK_SIZE
+ * and PAGE_OFFSET - it must be within 32MB of the kernel text.
+ */
+#define MODULES_VADDR		(PAGE_OFFSET - 16*1024*1024)
+#if TASK_SIZE > MODULES_VADDR
+#error Top of user space clashes with start of module space
+#endif
+
+#define MODULES_END		(PAGE_OFFSET)
+
+/*
+ * Allow 16MB-aligned ioremap pages
+ */
+#define IOREMAP_MAX_ORDER	24
+
+/*
+ * Physical vs virtual RAM address space conversion.  These are
+ * private definitions which should NOT be used outside memory.h
+ * files.  Use virt_to_phys/phys_to_virt/__pa/__va instead.
+ */
+#ifndef __virt_to_phys
+#define __virt_to_phys(x)	((x) - PAGE_OFFSET + PHYS_OFFSET)
+#define __phys_to_virt(x)	((x) - PHYS_OFFSET + PAGE_OFFSET)
+#endif
+
+/*
+ * Convert a physical address to a Page Frame Number and back
+ */
+#define	__phys_to_pfn(paddr)	((paddr) >> PAGE_SHIFT)
+#define	__pfn_to_phys(pfn)	((pfn) << PAGE_SHIFT)
+
+/*
+ * Convert a page to/from a physical address
+ */
+#define page_to_phys(page)	(__pfn_to_phys(page_to_pfn(page)))
+#define phys_to_page(phys)	(pfn_to_page(__phys_to_pfn(phys)))
+
+#ifndef __ASSEMBLY__
+
+#ifndef arch_adjust_zones
+#define arch_adjust_zones(size, holes) do { } while (0)
+#endif
+
+/*
+ * PFNs are used to describe any physical page; this means
+ * PFN 0 == physical address 0.
+ *
+ * This is the PFN of the first RAM page in the kernel
+ * direct-mapped view.  We assume this is the first page
+ * of RAM in the mem_map as well.
+ */
+#define PHYS_PFN_OFFSET	(PHYS_OFFSET >> PAGE_SHIFT)
+
+/*
+ * Drivers should NOT use these either.
+ */
+#define __pa(x)			__virt_to_phys((unsigned long)(x))
+#define __va(x)			((void *)__phys_to_virt((unsigned long)(x)))
+#define pfn_to_kaddr(pfn)	__va((pfn) << PAGE_SHIFT)
+
+/*
+ * Conversion between a struct page and a physical address.
+ *
+ * Note: when converting an unknown physical address to a
+ * struct page, the resulting pointer must be validated
+ * using VALID_PAGE().  It must return an invalid struct page
+ * for any physical address not corresponding to a system
+ * RAM address.
+ *
+ *  page_to_pfn(page)	convert a struct page * to a PFN number
+ *  pfn_to_page(pfn)	convert a _valid_ PFN number to struct page *
+ *
+ *  virt_to_page(k)	convert a _valid_ virtual address to struct page *
+ *  virt_addr_valid(k)	indicates whether a virtual address is valid
+ */
+#define ARCH_PFN_OFFSET		PHYS_PFN_OFFSET
+
+#define virt_to_page(kaddr)	pfn_to_page(__pa(kaddr) >> PAGE_SHIFT)
+#define virt_addr_valid(kaddr)	((unsigned long)(kaddr) >= PAGE_OFFSET && \
+		(unsigned long)(kaddr) < (unsigned long)high_memory)
+
+#endif
+
+#include <asm-generic/memory_model.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/mmu_context.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/mmu_context.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/mmu_context.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/mmu_context.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,87 @@
+/*
+ * linux/arch/unicore32/include/asm/mmu_context.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_MMU_CONTEXT_H__
+#define __UNICORE_MMU_CONTEXT_H__
+
+#include <linux/compiler.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <asm/cacheflush.h>
+#include <asm/cpu-single.h>
+
+#define init_new_context(tsk, mm)	0
+
+#define destroy_context(mm)		do { } while (0)
+
+/*
+ * This is called when "tsk" is about to enter lazy TLB mode.
+ *
+ * mm:  describes the currently active mm context
+ * tsk: task which is entering lazy tlb
+ * cpu: cpu number which is entering lazy tlb
+ *
+ * tsk->mm will be NULL
+ */
+static inline void
+enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk)
+{
+}
+
+/*
+ * This is the actual mm switch as far as the scheduler
+ * is concerned.  No registers are touched.  We avoid
+ * calling the CPU specific function when the mm hasn't
+ * actually changed.
+ */
+static inline void
+switch_mm(struct mm_struct *prev, struct mm_struct *next,
+	  struct task_struct *tsk)
+{
+	unsigned int cpu = smp_processor_id();
+
+	if (!cpumask_test_and_set_cpu(cpu, mm_cpumask(next)) || prev != next)
+		cpu_switch_mm(next->pgd, next);
+}
+
+#define deactivate_mm(tsk, mm)	do { } while (0)
+#define activate_mm(prev, next)	switch_mm(prev, next, NULL)
+
+/*
+ * We are inserting a "fake" vma for the user-accessible vector page so
+ * gdb and friends can get to it through ptrace and /proc/<pid>/mem.
+ * But we also want to remove it before the generic code gets to see it
+ * during process exit or the unmapping of it would  cause total havoc.
+ * (the macro is used as remove_vma() is static to mm/mmap.c)
+ */
+#define arch_exit_mmap(mm) \
+do { \
+	struct vm_area_struct *high_vma = find_vma(mm, 0xffff0000); \
+	if (high_vma) { \
+		BUG_ON(high_vma->vm_next);  /* it should be last */ \
+		if (high_vma->vm_prev) \
+			high_vma->vm_prev->vm_next = NULL; \
+		else \
+			mm->mmap = NULL; \
+		rb_erase(&high_vma->vm_rb, &mm->mm_rb); \
+		mm->mmap_cache = NULL; \
+		mm->map_count--; \
+		remove_vma(high_vma); \
+	} \
+} while (0)
+
+static inline void arch_dup_mmap(struct mm_struct *oldmm,
+				 struct mm_struct *mm)
+{
+}
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/mmu.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/mmu.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/mmu.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/mmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+/*
+ * linux/arch/unicore32/include/asm/mmu.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_MMU_H__
+#define __UNICORE_MMU_H__
+
+typedef	unsigned long mm_context_t;
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/mutex.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/mutex.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/mutex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/mutex.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/unicore32/include/asm/mutex.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * UniCore optimized mutex locking primitives
+ *
+ * Please look into asm-generic/mutex-xchg.h for a formal definition.
+ */
+#ifndef __UNICORE_MUTEX_H__
+#define __UNICORE_MUTEX_H__
+
+# include <asm-generic/mutex-xchg.h>
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/page.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/page.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/page.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/page.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * linux/arch/unicore32/include/asm/page.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PAGE_H__
+#define __UNICORE_PAGE_H__
+
+/* PAGE_SHIFT determines the page size */
+#define PAGE_SHIFT		12
+#define PAGE_SIZE		(_AC(1, UL) << PAGE_SHIFT)
+#define PAGE_MASK		(~(PAGE_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+struct page;
+struct vm_area_struct;
+
+#define clear_page(page)	memset((void *)(page), 0, PAGE_SIZE)
+extern void copy_page(void *to, const void *from);
+
+#define clear_user_page(page, vaddr, pg)	clear_page(page)
+#define copy_user_page(to, from, vaddr, pg)	copy_page(to, from)
+
+#undef STRICT_MM_TYPECHECKS
+
+#ifdef STRICT_MM_TYPECHECKS
+/*
+ * These are used to make use of C type-checking..
+ */
+typedef struct { unsigned long pte; } pte_t;
+typedef struct { unsigned long pgd; } pgd_t;
+typedef struct { unsigned long pgprot; } pgprot_t;
+
+#define pte_val(x)      ((x).pte)
+#define pgd_val(x)	((x).pgd)
+#define pgprot_val(x)   ((x).pgprot)
+
+#define __pte(x)        ((pte_t) { (x) })
+#define __pgd(x)	((pgd_t) { (x) })
+#define __pgprot(x)     ((pgprot_t) { (x) })
+
+#else
+/*
+ * .. while these make it easier on the compiler
+ */
+typedef unsigned long pte_t;
+typedef unsigned long pgd_t;
+typedef unsigned long pgprot_t;
+
+#define pte_val(x)      (x)
+#define pgd_val(x)      (x)
+#define pgprot_val(x)   (x)
+
+#define __pte(x)        (x)
+#define __pgd(x)	(x)
+#define __pgprot(x)     (x)
+
+#endif /* STRICT_MM_TYPECHECKS */
+
+typedef struct page *pgtable_t;
+
+extern int pfn_valid(unsigned long);
+
+#include <asm/memory.h>
+
+#endif /* !__ASSEMBLY__ */
+
+#define VM_DATA_DEFAULT_FLAGS \
+	(VM_READ | VM_WRITE | VM_EXEC | VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+#include <asm-generic/getorder.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pci.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pci.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,46 @@
+/*
+ * linux/arch/unicore32/include/asm/pci.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PCI_H__
+#define __UNICORE_PCI_H__
+
+#ifdef __KERNEL__
+#include <asm-generic/pci-dma-compat.h>
+#include <asm-generic/pci.h>
+#include <mach/hardware.h> /* for PCIBIOS_MIN_* */
+
+static inline void pcibios_set_master(struct pci_dev *dev)
+{
+	/* No special bus mastering setup handling */
+}
+
+static inline void pcibios_penalize_isa_irq(int irq, int active)
+{
+	/* We don't do dynamic PCI IRQ allocation */
+}
+
+#ifdef CONFIG_PCI
+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;
+}
+#endif
+
+#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);
+
+#endif /* __KERNEL__ */
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pgalloc.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pgalloc.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pgalloc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pgalloc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,110 @@
+/*
+ * linux/arch/unicore32/include/asm/pgalloc.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PGALLOC_H__
+#define __UNICORE_PGALLOC_H__
+
+#include <asm/pgtable-hwdef.h>
+#include <asm/processor.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+
+#define check_pgt_cache()		do { } while (0)
+
+#define _PAGE_USER_TABLE	(PMD_TYPE_TABLE | PMD_PRESENT)
+#define _PAGE_KERNEL_TABLE	(PMD_TYPE_TABLE | PMD_PRESENT)
+
+extern pgd_t *get_pgd_slow(struct mm_struct *mm);
+extern void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd);
+
+#define pgd_alloc(mm)			get_pgd_slow(mm)
+#define pgd_free(mm, pgd)		free_pgd_slow(mm, pgd)
+
+#define PGALLOC_GFP	(GFP_KERNEL | __GFP_NOTRACK | __GFP_REPEAT | __GFP_ZERO)
+
+/*
+ * Allocate one PTE table.
+ */
+static inline pte_t *
+pte_alloc_one_kernel(struct mm_struct *mm, unsigned long addr)
+{
+	pte_t *pte;
+
+	pte = (pte_t *)__get_free_page(PGALLOC_GFP);
+	if (pte)
+		clean_dcache_area(pte, PTRS_PER_PTE * sizeof(pte_t));
+
+	return pte;
+}
+
+static inline pgtable_t
+pte_alloc_one(struct mm_struct *mm, unsigned long addr)
+{
+	struct page *pte;
+
+	pte = alloc_pages(PGALLOC_GFP, 0);
+	if (pte) {
+		if (!PageHighMem(pte)) {
+			void *page = page_address(pte);
+			clean_dcache_area(page, PTRS_PER_PTE * sizeof(pte_t));
+		}
+		pgtable_page_ctor(pte);
+	}
+
+	return pte;
+}
+
+/*
+ * Free one PTE table.
+ */
+static inline void pte_free_kernel(struct mm_struct *mm, pte_t *pte)
+{
+	if (pte)
+		free_page((unsigned long)pte);
+}
+
+static inline void pte_free(struct mm_struct *mm, pgtable_t pte)
+{
+	pgtable_page_dtor(pte);
+	__free_page(pte);
+}
+
+static inline void __pmd_populate(pmd_t *pmdp, unsigned long pmdval)
+{
+	set_pmd(pmdp, __pmd(pmdval));
+	flush_pmd_entry(pmdp);
+}
+
+/*
+ * Populate the pmdp entry with a pointer to the pte.  This pmd is part
+ * of the mm address space.
+ */
+static inline void
+pmd_populate_kernel(struct mm_struct *mm, pmd_t *pmdp, pte_t *ptep)
+{
+	unsigned long pte_ptr = (unsigned long)ptep;
+
+	/*
+	 * The pmd must be loaded with the physical
+	 * address of the PTE table
+	 */
+	__pmd_populate(pmdp, __pa(pte_ptr) | _PAGE_KERNEL_TABLE);
+}
+
+static inline void
+pmd_populate(struct mm_struct *mm, pmd_t *pmdp, pgtable_t ptep)
+{
+	__pmd_populate(pmdp,
+			page_to_pfn(ptep) << PAGE_SHIFT | _PAGE_USER_TABLE);
+}
+#define pmd_pgtable(pmd) pmd_page(pmd)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pgtable.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pgtable.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pgtable.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pgtable.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,317 @@
+/*
+ * linux/arch/unicore32/include/asm/pgtable.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PGTABLE_H__
+#define __UNICORE_PGTABLE_H__
+
+#include <asm-generic/pgtable-nopmd.h>
+#include <asm/cpu-single.h>
+
+#include <asm/memory.h>
+#include <asm/pgtable-hwdef.h>
+
+/*
+ * Just any arbitrary offset to the start of the vmalloc VM area: the
+ * current 8MB value just means that there will be a 8MB "hole" after the
+ * physical memory until the kernel virtual memory starts.  That means that
+ * any out-of-bounds memory accesses will hopefully be caught.
+ * The vmalloc() routines leaves a hole of 4kB between each vmalloced
+ * area for the same reason. ;)
+ *
+ * Note that platforms may override VMALLOC_START, but they must provide
+ * VMALLOC_END.  VMALLOC_END defines the (exclusive) limit of this space,
+ * which may not overlap IO space.
+ */
+#ifndef VMALLOC_START
+#define VMALLOC_OFFSET		SZ_8M
+#define VMALLOC_START		(((unsigned long)high_memory + VMALLOC_OFFSET) \
+					& ~(VMALLOC_OFFSET-1))
+#define VMALLOC_END		(0xff000000UL)
+#endif
+
+#define PTRS_PER_PTE		1024
+#define PTRS_PER_PGD		1024
+
+/*
+ * PGDIR_SHIFT determines what a third-level page table entry can map
+ */
+#define PGDIR_SHIFT		22
+
+#ifndef __ASSEMBLY__
+extern void __pte_error(const char *file, int line, unsigned long val);
+extern void __pgd_error(const char *file, int line, unsigned long val);
+
+#define pte_ERROR(pte)		__pte_error(__FILE__, __LINE__, pte_val(pte))
+#define pgd_ERROR(pgd)		__pgd_error(__FILE__, __LINE__, pgd_val(pgd))
+#endif /* !__ASSEMBLY__ */
+
+#define PGDIR_SIZE		(1UL << PGDIR_SHIFT)
+#define PGDIR_MASK		(~(PGDIR_SIZE-1))
+
+/*
+ * This is the lowest virtual address we can permit any user space
+ * mapping to be mapped at.  This is particularly important for
+ * non-high vector CPUs.
+ */
+#define FIRST_USER_ADDRESS	PAGE_SIZE
+
+#define FIRST_USER_PGD_NR	1
+#define USER_PTRS_PER_PGD	((TASK_SIZE/PGDIR_SIZE) - FIRST_USER_PGD_NR)
+
+/*
+ * section address mask and size definitions.
+ */
+#define SECTION_SHIFT		22
+#define SECTION_SIZE		(1UL << SECTION_SHIFT)
+#define SECTION_MASK		(~(SECTION_SIZE-1))
+
+#ifndef __ASSEMBLY__
+
+/*
+ * The pgprot_* and protection_map entries will be fixed up in runtime
+ * to include the cachable bits based on memory policy, as well as any
+ * architecture dependent bits.
+ */
+#define _PTE_DEFAULT		(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE)
+
+extern pgprot_t pgprot_user;
+extern pgprot_t pgprot_kernel;
+
+#define PAGE_NONE		pgprot_user
+#define PAGE_SHARED		__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_WRITE)
+#define PAGE_SHARED_EXEC	__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_WRITE \
+								| PTE_EXEC)
+#define PAGE_COPY		__pgprot(pgprot_val(pgprot_user | PTE_READ)
+#define PAGE_COPY_EXEC		__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_EXEC)
+#define PAGE_READONLY		__pgprot(pgprot_val(pgprot_user | PTE_READ)
+#define PAGE_READONLY_EXEC	__pgprot(pgprot_val(pgprot_user | PTE_READ \
+								| PTE_EXEC)
+#define PAGE_KERNEL		pgprot_kernel
+#define PAGE_KERNEL_EXEC	__pgprot(pgprot_val(pgprot_kernel | PTE_EXEC))
+
+#define __PAGE_NONE		__pgprot(_PTE_DEFAULT)
+#define __PAGE_SHARED		__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_WRITE)
+#define __PAGE_SHARED_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_WRITE \
+							| PTE_EXEC)
+#define __PAGE_COPY		__pgprot(_PTE_DEFAULT | PTE_READ)
+#define __PAGE_COPY_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_EXEC)
+#define __PAGE_READONLY		__pgprot(_PTE_DEFAULT | PTE_READ)
+#define __PAGE_READONLY_EXEC	__pgprot(_PTE_DEFAULT | PTE_READ \
+							| PTE_EXEC)
+
+#endif /* __ASSEMBLY__ */
+
+/*
+ * The table below defines the page protection levels that we insert into our
+ * Linux page table version.  These get translated into the best that the
+ * architecture can perform.  Note that on UniCore hardware:
+ *  1) We cannot do execute protection
+ *  2) If we could do execute protection, then read is implied
+ *  3) write implies read permissions
+ */
+#define __P000  __PAGE_NONE
+#define __P001  __PAGE_READONLY
+#define __P010  __PAGE_COPY
+#define __P011  __PAGE_COPY
+#define __P100  __PAGE_READONLY_EXEC
+#define __P101  __PAGE_READONLY_EXEC
+#define __P110  __PAGE_COPY_EXEC
+#define __P111  __PAGE_COPY_EXEC
+
+#define __S000  __PAGE_NONE
+#define __S001  __PAGE_READONLY
+#define __S010  __PAGE_SHARED
+#define __S011  __PAGE_SHARED
+#define __S100  __PAGE_READONLY_EXEC
+#define __S101  __PAGE_READONLY_EXEC
+#define __S110  __PAGE_SHARED_EXEC
+#define __S111  __PAGE_SHARED_EXEC
+
+#ifndef __ASSEMBLY__
+/*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+extern struct page *empty_zero_page;
+#define ZERO_PAGE(vaddr)		(empty_zero_page)
+
+#define pte_pfn(pte)			(pte_val(pte) >> PAGE_SHIFT)
+#define pfn_pte(pfn, prot)		(__pte(((pfn) << PAGE_SHIFT) \
+						| pgprot_val(prot)))
+
+#define pte_none(pte)			(!pte_val(pte))
+#define pte_clear(mm, addr, ptep)	set_pte(ptep, __pte(0))
+#define pte_page(pte)			(pfn_to_page(pte_pfn(pte)))
+#define pte_offset_kernel(dir, addr)	(pmd_page_vaddr(*(dir)) \
+						+ __pte_index(addr))
+
+#define pte_offset_map(dir, addr)	(pmd_page_vaddr(*(dir)) \
+						+ __pte_index(addr))
+#define pte_unmap(pte)			do { } while (0)
+
+#define set_pte(ptep, pte)	cpu_set_pte(ptep, pte)
+
+#define set_pte_at(mm, addr, ptep, pteval)	\
+	do {					\
+		set_pte(ptep, pteval);          \
+	} while (0)
+
+/*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+#define pte_present(pte)	(pte_val(pte) & PTE_PRESENT)
+#define pte_write(pte)		(pte_val(pte) & PTE_WRITE)
+#define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
+#define pte_young(pte)		(pte_val(pte) & PTE_YOUNG)
+#define pte_exec(pte)		(pte_val(pte) & PTE_EXEC)
+#define pte_special(pte)	(0)
+
+#define PTE_BIT_FUNC(fn, op) \
+static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
+
+PTE_BIT_FUNC(wrprotect, &= ~PTE_WRITE);
+PTE_BIT_FUNC(mkwrite,   |= PTE_WRITE);
+PTE_BIT_FUNC(mkclean,   &= ~PTE_DIRTY);
+PTE_BIT_FUNC(mkdirty,   |= PTE_DIRTY);
+PTE_BIT_FUNC(mkold,     &= ~PTE_YOUNG);
+PTE_BIT_FUNC(mkyoung,   |= PTE_YOUNG);
+
+static inline pte_t pte_mkspecial(pte_t pte) { return pte; }
+
+/*
+ * Mark the prot value as uncacheable.
+ */
+#define pgprot_noncached(prot)		\
+	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
+#define pgprot_writecombine(prot)	\
+	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
+#define pgprot_dmacoherent(prot)	\
+	__pgprot(pgprot_val(prot) & ~PTE_CACHEABLE)
+
+#define pmd_none(pmd)		(!pmd_val(pmd))
+#define pmd_present(pmd)	(pmd_val(pmd) & PMD_PRESENT)
+#define pmd_bad(pmd)		(((pmd_val(pmd) &		\
+				(PMD_PRESENT | PMD_TYPE_MASK))	\
+				!= (PMD_PRESENT | PMD_TYPE_TABLE)))
+
+#define set_pmd(pmdpd, pmdval)		\
+	do {				\
+		*(pmdpd) = pmdval;	\
+	} while (0)
+
+#define pmd_clear(pmdp)			\
+	do {				\
+		set_pmd(pmdp, __pmd(0));\
+		clean_pmd_entry(pmdp);	\
+	} while (0)
+
+#define pmd_page_vaddr(pmd) ((pte_t *)__va(pmd_val(pmd) & PAGE_MASK))
+#define pmd_page(pmd)		pfn_to_page(__phys_to_pfn(pmd_val(pmd)))
+
+/*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+#define mk_pte(page, prot)	pfn_pte(page_to_pfn(page), prot)
+
+/* to find an entry in a page-table-directory */
+#define pgd_index(addr)		((addr) >> PGDIR_SHIFT)
+
+#define pgd_offset(mm, addr)	((mm)->pgd+pgd_index(addr))
+
+/* to find an entry in a kernel page-table-directory */
+#define pgd_offset_k(addr)	pgd_offset(&init_mm, addr)
+
+/* Find an entry in the third-level page table.. */
+#define __pte_index(addr)	(((addr) >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+
+static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+{
+	const unsigned long mask = PTE_EXEC | PTE_WRITE | PTE_READ;
+	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
+	return pte;
+}
+
+extern pgd_t swapper_pg_dir[PTRS_PER_PGD];
+
+/*
+ * Encode and decode a swap entry.  Swap 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 --------------> <--- type --> 0 0 0 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_SHIFT	5
+#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 0 0
+ */
+#define pte_file(pte)		(pte_val(pte) & PTE_FILE)
+#define pte_to_pgoff(x)		(pte_val(x) >> 4)
+#define pgoff_to_pte(x)		__pte(((x) << 4) | PTE_FILE)
+
+#define PTE_FILE_MAX_BITS	28
+
+/* 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)
+
+#include <asm-generic/pgtable.h>
+
+/*
+ * remap a physical page `pfn' of size `size' with page protection `prot'
+ * into virtual address `from'
+ */
+#define io_remap_pfn_range(vma, from, pfn, size, prot)	\
+		remap_pfn_range(vma, from, pfn, size, prot)
+
+#define pgtable_cache_init() do { } while (0)
+
+#endif /* !__ASSEMBLY__ */
+
+#endif /* __UNICORE_PGTABLE_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pgtable-hwdef.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pgtable-hwdef.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/pgtable-hwdef.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/pgtable-hwdef.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * linux/arch/unicore32/include/asm/pgtable-hwdef.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PGTABLE_HWDEF_H__
+#define __UNICORE_PGTABLE_HWDEF_H__
+
+/*
+ * Hardware page table definitions.
+ *
+ * + Level 1 descriptor (PMD)
+ *   - common
+ */
+#define PMD_TYPE_MASK		(3 << 0)
+#define PMD_TYPE_TABLE		(0 << 0)
+/*#define PMD_TYPE_LARGE	(1 << 0) */
+#define PMD_TYPE_INVALID	(2 << 0)
+#define PMD_TYPE_SECT		(3 << 0)
+
+#define PMD_PRESENT		(1 << 2)
+#define PMD_YOUNG		(1 << 3)
+
+/*#define PMD_SECT_DIRTY	(1 << 4) */
+#define PMD_SECT_CACHEABLE	(1 << 5)
+#define PMD_SECT_EXEC		(1 << 6)
+#define PMD_SECT_WRITE		(1 << 7)
+#define PMD_SECT_READ		(1 << 8)
+
+/*
+ * + Level 2 descriptor (PTE)
+ *   - common
+ */
+#define PTE_TYPE_MASK		(3 << 0)
+#define PTE_TYPE_SMALL		(0 << 0)
+#define PTE_TYPE_MIDDLE		(1 << 0)
+#define PTE_TYPE_LARGE		(2 << 0)
+#define PTE_TYPE_INVALID	(3 << 0)
+
+#define PTE_PRESENT		(1 << 2)
+#define PTE_FILE		(1 << 3)	/* only when !PRESENT */
+#define PTE_YOUNG		(1 << 3)
+#define PTE_DIRTY		(1 << 4)
+#define PTE_CACHEABLE		(1 << 5)
+#define PTE_EXEC		(1 << 6)
+#define PTE_WRITE		(1 << 7)
+#define PTE_READ		(1 << 8)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/processor.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/processor.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,92 @@
+/*
+ * linux/arch/unicore32/include/asm/processor.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PROCESSOR_H__
+#define __UNICORE_PROCESSOR_H__
+
+/*
+ * Default implementation of macro that returns current
+ * instruction pointer ("program counter").
+ */
+#define current_text_addr() ({ __label__ _l; _l: &&_l; })
+
+#ifdef __KERNEL__
+
+#include <asm/ptrace.h>
+#include <asm/types.h>
+
+#ifdef __KERNEL__
+#define STACK_TOP	TASK_SIZE
+#define STACK_TOP_MAX	TASK_SIZE
+#endif
+
+struct debug_entry {
+	u32			address;
+	u32			insn;
+};
+
+struct debug_info {
+	int			nsaved;
+	struct debug_entry	bp[2];
+};
+
+struct thread_struct {
+							/* fault info	  */
+	unsigned long		address;
+	unsigned long		trap_no;
+	unsigned long		error_code;
+							/* debugging	  */
+	struct debug_info	debug;
+};
+
+#define INIT_THREAD  {	}
+
+#define start_thread(regs, pc, sp)					\
+({									\
+	unsigned long *stack = (unsigned long *)sp;			\
+	set_fs(USER_DS);						\
+	memset(regs->uregs, 0, sizeof(regs->uregs));			\
+	regs->UCreg_asr = USER_MODE;					\
+	regs->UCreg_pc = pc & ~1;	/* pc */                        \
+	regs->UCreg_sp = sp;		/* sp */                        \
+	regs->UCreg_02 = stack[2];	/* r2 (envp) */                 \
+	regs->UCreg_01 = stack[1];	/* r1 (argv) */                 \
+	regs->UCreg_00 = stack[0];	/* r0 (argc) */                 \
+})
+
+/* Forward declaration, a strange C thing */
+struct task_struct;
+
+/* Free all resources held by a thread. */
+extern void release_thread(struct task_struct *);
+
+/* Prepare to copy thread state - unlazy all lazy status */
+#define prepare_to_copy(tsk)	do { } while (0)
+
+unsigned long get_wchan(struct task_struct *p);
+
+#define cpu_relax()			barrier()
+
+/*
+ * Create a new kernel thread
+ */
+extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
+
+#define task_pt_regs(p) \
+	((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)
+
+#define KSTK_EIP(tsk)	(task_pt_regs(tsk)->UCreg_pc)
+#define KSTK_ESP(tsk)	(task_pt_regs(tsk)->UCreg_sp)
+
+#endif
+
+#endif /* __UNICORE_PROCESSOR_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/ptrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,133 @@
+/*
+ * linux/arch/unicore32/include/asm/ptrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_PTRACE_H__
+#define __UNICORE_PTRACE_H__
+
+#define PTRACE_GET_THREAD_AREA	22
+
+/*
+ * PSR bits
+ */
+#define USER_MODE	0x00000010
+#define REAL_MODE	0x00000011
+#define INTR_MODE	0x00000012
+#define PRIV_MODE	0x00000013
+#define ABRT_MODE	0x00000017
+#define EXTN_MODE	0x0000001b
+#define SUSR_MODE	0x0000001f
+#define MODE_MASK	0x0000001f
+#define PSR_R_BIT	0x00000040
+#define PSR_I_BIT	0x00000080
+#define PSR_V_BIT	0x10000000
+#define PSR_C_BIT	0x20000000
+#define PSR_Z_BIT	0x40000000
+#define PSR_S_BIT	0x80000000
+
+/*
+ * Groups of PSR bits
+ */
+#define PSR_f		0xff000000	/* Flags		*/
+#define PSR_c		0x000000ff	/* Control		*/
+
+#ifndef __ASSEMBLY__
+
+/*
+ * This struct defines the way the registers are stored on the
+ * stack during a system call.  Note that sizeof(struct pt_regs)
+ * has to be a multiple of 8.
+ */
+struct pt_regs {
+	unsigned long uregs[34];
+};
+
+#define UCreg_asr		uregs[32]
+#define UCreg_pc		uregs[31]
+#define UCreg_lr		uregs[30]
+#define UCreg_sp		uregs[29]
+#define UCreg_ip		uregs[28]
+#define UCreg_fp		uregs[27]
+#define UCreg_26		uregs[26]
+#define UCreg_25		uregs[25]
+#define UCreg_24		uregs[24]
+#define UCreg_23		uregs[23]
+#define UCreg_22		uregs[22]
+#define UCreg_21		uregs[21]
+#define UCreg_20		uregs[20]
+#define UCreg_19		uregs[19]
+#define UCreg_18		uregs[18]
+#define UCreg_17		uregs[17]
+#define UCreg_16		uregs[16]
+#define UCreg_15		uregs[15]
+#define UCreg_14		uregs[14]
+#define UCreg_13		uregs[13]
+#define UCreg_12		uregs[12]
+#define UCreg_11		uregs[11]
+#define UCreg_10		uregs[10]
+#define UCreg_09		uregs[9]
+#define UCreg_08		uregs[8]
+#define UCreg_07		uregs[7]
+#define UCreg_06		uregs[6]
+#define UCreg_05		uregs[5]
+#define UCreg_04		uregs[4]
+#define UCreg_03		uregs[3]
+#define UCreg_02		uregs[2]
+#define UCreg_01		uregs[1]
+#define UCreg_00		uregs[0]
+#define UCreg_ORIG_00		uregs[33]
+
+#ifdef __KERNEL__
+
+#define user_mode(regs)	\
+	(processor_mode(regs) == USER_MODE)
+
+#define processor_mode(regs) \
+	((regs)->UCreg_asr & MODE_MASK)
+
+#define interrupts_enabled(regs) \
+	(!((regs)->UCreg_asr & PSR_I_BIT))
+
+#define fast_interrupts_enabled(regs) \
+	(!((regs)->UCreg_asr & PSR_R_BIT))
+
+/* Are the current registers suitable for user mode?
+ * (used to maintain security in signal handlers)
+ */
+static inline int valid_user_regs(struct pt_regs *regs)
+{
+	unsigned long mode = regs->UCreg_asr & MODE_MASK;
+
+	/*
+	 * Always clear the R (REAL) bits
+	 */
+	regs->UCreg_asr &= ~(PSR_R_BIT);
+
+	if ((regs->UCreg_asr & PSR_I_BIT) == 0) {
+		if (mode == USER_MODE)
+			return 1;
+	}
+
+	/*
+	 * Force ASR to something logical...
+	 */
+	regs->UCreg_asr &= PSR_f | USER_MODE;
+
+	return 0;
+}
+
+#define instruction_pointer(regs)	((regs)->UCreg_pc)
+
+#endif /* __KERNEL__ */
+
+#endif /* __ASSEMBLY__ */
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/sigcontext.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/sigcontext.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/sigcontext.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/sigcontext.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29 @@
+/*
+ * linux/arch/unicore32/include/asm/sigcontext.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_SIGCONTEXT_H__
+#define __UNICORE_SIGCONTEXT_H__
+
+#include <asm/ptrace.h>
+/*
+ * Signal context structure - contains all info to do with the state
+ * before the signal handler was invoked.  Note: only add new entries
+ * to the end of the structure.
+ */
+struct sigcontext {
+	unsigned long trap_no;
+	unsigned long error_code;
+	unsigned long oldmask;
+	unsigned long fault_address;
+	struct pt_regs regs;
+};
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/stacktrace.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/stacktrace.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/stacktrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/stacktrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+/*
+ * linux/arch/unicore32/include/asm/stacktrace.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_STACKTRACE_H__
+#define __UNICORE_STACKTRACE_H__
+
+struct stackframe {
+	unsigned long fp;
+	unsigned long sp;
+	unsigned long lr;
+	unsigned long pc;
+};
+
+#ifdef CONFIG_FRAME_POINTER
+extern int unwind_frame(struct stackframe *frame);
+#else
+#define unwind_frame(f) (-EINVAL)
+#endif
+extern void walk_stackframe(struct stackframe *frame,
+			    int (*fn)(struct stackframe *, void *), void *data);
+
+#endif	/* __UNICORE_STACKTRACE_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/string.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/string.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/string.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/string.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/unicore32/include/asm/string.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_STRING_H__
+#define __UNICORE_STRING_H__
+
+/*
+ * We don't do inline string functions, since the
+ * optimised inline asm versions are not small.
+ */
+
+#define __HAVE_ARCH_STRRCHR
+extern char *strrchr(const char *s, int c);
+
+#define __HAVE_ARCH_STRCHR
+extern char *strchr(const char *s, int c);
+
+#define __HAVE_ARCH_MEMCPY
+extern void *memcpy(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMMOVE
+extern void *memmove(void *, const void *, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMCHR
+extern void *memchr(const void *, int, __kernel_size_t);
+
+#define __HAVE_ARCH_MEMSET
+extern void *memset(void *, int, __kernel_size_t);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/suspend.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/suspend.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/suspend.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/suspend.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/unicore32/include/asm/suspend.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_SUSPEND_H__
+#define __UNICORE_SUSPEND_H__
+
+#ifndef __ASSEMBLY__
+static inline int arch_prepare_suspend(void) { return 0; }
+
+#include <asm/ptrace.h>
+
+struct swsusp_arch_regs {
+	struct cpu_context_save	cpu_context;	/* cpu context */
+#ifdef CONFIG_UNICORE_FPU_F64
+	struct fp_state		fpstate __attribute__((aligned(8)));
+#endif
+};
+#endif
+
+#endif /* __UNICORE_SUSPEND_H__ */
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/system.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/system.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * linux/arch/unicore32/include/asm/system.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_SYSTEM_H__
+#define __UNICORE_SYSTEM_H__
+
+#ifdef __KERNEL__
+
+/*
+ * CR1 bits (CP#0 CR1)
+ */
+#define CR_M	(1 << 0)	/* MMU enable				*/
+#define CR_A	(1 << 1)	/* Alignment abort enable		*/
+#define CR_D	(1 << 2)	/* Dcache enable			*/
+#define CR_I	(1 << 3)	/* Icache enable			*/
+#define CR_B	(1 << 4)	/* Dcache write mechanism: write back	*/
+#define CR_T	(1 << 5)	/* Burst enable				*/
+#define CR_V	(1 << 13)	/* Vectors relocated to 0xffff0000	*/
+
+#ifndef __ASSEMBLY__
+
+#include <linux/linkage.h>
+#include <linux/irqflags.h>
+
+struct thread_info;
+struct task_struct;
+
+struct pt_regs;
+
+void die(const char *msg, struct pt_regs *regs, int err);
+
+struct siginfo;
+void uc32_notify_die(const char *str, struct pt_regs *regs,
+		struct siginfo *info, unsigned long err, unsigned long trap);
+
+void hook_fault_code(int nr, int (*fn)(unsigned long, unsigned int,
+				       struct pt_regs *),
+		     int sig, int code, const char *name);
+
+#define xchg(ptr, x) \
+	((__typeof__(*(ptr)))__xchg((unsigned long)(x), (ptr), sizeof(*(ptr))))
+
+extern asmlinkage void __backtrace(void);
+extern asmlinkage void c_backtrace(unsigned long fp, int pmode);
+
+struct mm_struct;
+extern void show_pte(struct mm_struct *mm, unsigned long addr);
+extern void __show_regs(struct pt_regs *);
+
+extern int cpu_architecture(void);
+extern void cpu_init(void);
+
+#define vectors_high()	(cr_alignment & CR_V)
+
+#define isb() __asm__ __volatile__ ("" : : : "memory")
+#define dsb() __asm__ __volatile__ ("" : : : "memory")
+#define dmb() __asm__ __volatile__ ("" : : : "memory")
+
+#define mb()		barrier()
+#define rmb()		barrier()
+#define wmb()		barrier()
+#define smp_mb()	barrier()
+#define smp_rmb()	barrier()
+#define smp_wmb()	barrier()
+#define read_barrier_depends()		do { } while (0)
+#define smp_read_barrier_depends()	do { } while (0)
+
+#define set_mb(var, value)	do { var = value; smp_mb(); } while (0)
+#define nop() __asm__ __volatile__("mov\tr0,r0\t@ nop\n\t");
+
+extern unsigned long cr_no_alignment;	/* defined in entry-unicore.S */
+extern unsigned long cr_alignment;	/* defined in entry-unicore.S */
+
+static inline unsigned int get_cr(void)
+{
+	unsigned int val;
+	asm("movc %0, p0.c1, #0" : "=r" (val) : : "cc");
+	return val;
+}
+
+static inline void set_cr(unsigned int val)
+{
+	asm volatile("movc p0.c1, %0, #0	@set CR"
+	  : : "r" (val) : "cc");
+	isb();
+}
+
+extern void adjust_cr(unsigned long mask, unsigned long set);
+
+/*
+ * switch_to(prev, next) should switch from task `prev' to `next'
+ * `prev' will never be the same as `next'.  schedule() itself
+ * contains the memory barrier to tell GCC not to cache `current'.
+ */
+extern struct task_struct *__switch_to(struct task_struct *,
+		struct thread_info *, struct thread_info *);
+extern void panic(const char *fmt, ...);
+
+#define switch_to(prev, next, last)					\
+do {									\
+	last = __switch_to(prev,					\
+		task_thread_info(prev), task_thread_info(next));	\
+} while (0)
+
+static inline unsigned long
+__xchg(unsigned long x, volatile void *ptr, int size)
+{
+	unsigned long ret;
+
+	switch (size) {
+	case 1:
+		asm volatile("@	__xchg1\n"
+		"	swapb	%0, %1, [%2]"
+			: "=&r" (ret)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	case 4:
+		asm volatile("@	__xchg4\n"
+		"	swapw	%0, %1, [%2]"
+			: "=&r" (ret)
+			: "r" (x), "r" (ptr)
+			: "memory", "cc");
+		break;
+	default:
+		panic("xchg: bad data size: ptr 0x%p, size %d\n",
+			ptr, size);
+	}
+
+	return ret;
+}
+
+#include <asm-generic/cmpxchg-local.h>
+
+/*
+ * cmpxchg_local and cmpxchg64_local are atomic wrt current CPU. Always make
+ * them available.
+ */
+#define cmpxchg_local(ptr, o, n)					\
+		((__typeof__(*(ptr)))__cmpxchg_local_generic((ptr),	\
+		(unsigned long)(o), (unsigned long)(n), sizeof(*(ptr))))
+#define cmpxchg64_local(ptr, o, n)					\
+		__cmpxchg64_local_generic((ptr), (o), (n))
+
+#include <asm-generic/cmpxchg.h>
+
+#endif /* __ASSEMBLY__ */
+
+#define arch_align_stack(x) (x)
+
+#endif /* __KERNEL__ */
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/thread_info.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,154 @@
+/*
+ * linux/arch/unicore32/include/asm/thread_info.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_THREAD_INFO_H__
+#define __UNICORE_THREAD_INFO_H__
+
+#ifdef __KERNEL__
+
+#include <linux/compiler.h>
+#include <asm/fpstate.h>
+
+#define THREAD_SIZE_ORDER	1
+#define THREAD_SIZE		8192
+#define THREAD_START_SP		(THREAD_SIZE - 8)
+
+#ifndef __ASSEMBLY__
+
+struct task_struct;
+struct exec_domain;
+
+#include <asm/types.h>
+
+typedef struct {
+	unsigned long seg;
+} mm_segment_t;
+
+struct cpu_context_save {
+	__u32	r4;
+	__u32	r5;
+	__u32	r6;
+	__u32	r7;
+	__u32	r8;
+	__u32	r9;
+	__u32	r10;
+	__u32	r11;
+	__u32	r12;
+	__u32	r13;
+	__u32	r14;
+	__u32	r15;
+	__u32	r16;
+	__u32	r17;
+	__u32	r18;
+	__u32	r19;
+	__u32	r20;
+	__u32	r21;
+	__u32	r22;
+	__u32	r23;
+	__u32	r24;
+	__u32	r25;
+	__u32	r26;
+	__u32	fp;
+	__u32	sp;
+	__u32	pc;
+};
+
+/*
+ * low level task data that entry.S needs immediate access to.
+ * __switch_to() assumes cpu_context follows immediately after cpu_domain.
+ */
+struct thread_info {
+	unsigned long		flags;		/* low level flags */
+	int			preempt_count;	/* 0 => preemptable */
+						/* <0 => bug */
+	mm_segment_t		addr_limit;	/* address limit */
+	struct task_struct	*task;		/* main task structure */
+	struct exec_domain	*exec_domain;	/* execution domain */
+	__u32			cpu;		/* cpu */
+	struct cpu_context_save	cpu_context;	/* cpu context */
+	__u32			syscall;	/* syscall number */
+	__u8			used_cp[16];	/* thread used copro */
+#ifdef CONFIG_UNICORE_FPU_F64
+	struct fp_state		fpstate __attribute__((aligned(8)));
+#endif
+	struct restart_block	restart_block;
+};
+
+#define INIT_THREAD_INFO(tsk)						\
+{									\
+	.task		= &tsk,						\
+	.exec_domain	= &default_exec_domain,				\
+	.flags		= 0,						\
+	.preempt_count	= INIT_PREEMPT_COUNT,				\
+	.addr_limit	= KERNEL_DS,					\
+	.restart_block	= {						\
+		.fn	= do_no_restart_syscall,			\
+	},								\
+}
+
+#define init_thread_info	(init_thread_union.thread_info)
+#define init_stack		(init_thread_union.stack)
+
+/*
+ * how to get the thread information struct from C
+ */
+static inline struct thread_info *current_thread_info(void) __attribute_const__;
+
+static inline struct thread_info *current_thread_info(void)
+{
+	register unsigned long sp asm ("sp");
+	return (struct thread_info *)(sp & ~(THREAD_SIZE - 1));
+}
+
+#define thread_saved_pc(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
+#define thread_saved_sp(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.sp))
+#define thread_saved_fp(tsk)	\
+	((unsigned long)(task_thread_info(tsk)->cpu_context.fp))
+
+#endif
+
+/*
+ * We use bit 30 of the preempt_count to indicate that kernel
+ * preemption is occurring.  See <asm/hardirq.h>.
+ */
+#define PREEMPT_ACTIVE	0x40000000
+
+/*
+ * thread information flags:
+ *  TIF_SYSCALL_TRACE	- syscall trace active
+ *  TIF_SIGPENDING	- signal pending
+ *  TIF_NEED_RESCHED	- rescheduling necessary
+ *  TIF_NOTIFY_RESUME	- callback before returning to user
+ */
+#define TIF_SIGPENDING		0
+#define TIF_NEED_RESCHED	1
+#define TIF_NOTIFY_RESUME	2	/* callback before returning to user */
+#define TIF_SYSCALL_TRACE	8
+#define TIF_MEMDIE		18
+#define TIF_FREEZE		19
+#define TIF_RESTORE_SIGMASK	20
+
+#define _TIF_SIGPENDING		(1 << TIF_SIGPENDING)
+#define _TIF_NEED_RESCHED	(1 << TIF_NEED_RESCHED)
+#define _TIF_NOTIFY_RESUME	(1 << TIF_NOTIFY_RESUME)
+#define _TIF_SYSCALL_TRACE	(1 << TIF_SYSCALL_TRACE)
+#define _TIF_FREEZE		(1 << TIF_FREEZE)
+#define _TIF_RESTORE_SIGMASK	(1 << TIF_RESTORE_SIGMASK)
+
+/*
+ * Change these and you break ASM code in entry-common.S
+ */
+#define _TIF_WORK_MASK		0x000000ff
+
+#endif /* __KERNEL__ */
+#endif /* __UNICORE_THREAD_INFO_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/timex.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/timex.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/timex.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/timex.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/unicore32/include/asm/timex.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_TIMEX_H__
+#define __UNICORE_TIMEX_H__
+
+#ifdef	CONFIG_ARCH_FPGA
+
+/* in FPGA, APB clock is 33M, and OST clock is 32K, */
+/* so, 1M is selected for timer interrupt correctly */
+#define	CLOCK_TICK_RATE		(32*1024)
+
+#endif
+
+#if defined(CONFIG_PUV3_DB0913)		\
+	|| defined(CONFIG_PUV3_NB0916)	\
+	|| defined(CONFIG_PUV3_SMW0919)
+
+#define  CLOCK_TICK_RATE         (14318000)
+
+#endif
+
+#include <asm-generic/timex.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/tlbflush.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/tlbflush.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/tlbflush.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/tlbflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,195 @@
+/*
+ * linux/arch/unicore32/include/asm/tlbflush.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_TLBFLUSH_H__
+#define __UNICORE_TLBFLUSH_H__
+
+#ifndef __ASSEMBLY__
+
+#include <linux/sched.h>
+
+extern void __cpu_flush_user_tlb_range(unsigned long, unsigned long,
+					struct vm_area_struct *);
+extern void __cpu_flush_kern_tlb_range(unsigned long, unsigned long);
+
+/*
+ *	TLB Management
+ *	==============
+ *
+ *	The arch/unicore/mm/tlb-*.S files implement these methods.
+ *
+ *	The TLB specific code is expected to perform whatever tests it
+ *	needs to determine if it should invalidate the TLB for each
+ *	call.  Start addresses are inclusive and end addresses are
+ *	exclusive; it is safe to round these addresses down.
+ *
+ *	flush_tlb_all()
+ *
+ *		Invalidate the entire TLB.
+ *
+ *	flush_tlb_mm(mm)
+ *
+ *		Invalidate all TLB entries in a particular address
+ *		space.
+ *		- mm	- mm_struct describing address space
+ *
+ *	flush_tlb_range(mm,start,end)
+ *
+ *		Invalidate a range of TLB entries in the specified
+ *		address space.
+ *		- mm	- mm_struct describing address space
+ *		- start - start address (may not be aligned)
+ *		- end	- end address (exclusive, may not be aligned)
+ *
+ *	flush_tlb_page(vaddr,vma)
+ *
+ *		Invalidate the specified page in the specified address range.
+ *		- vaddr - virtual address (may not be aligned)
+ *		- vma	- vma_struct describing address range
+ *
+ *	flush_kern_tlb_page(kaddr)
+ *
+ *		Invalidate the TLB entry for the specified page.  The address
+ *		will be in the kernels virtual memory space.  Current uses
+ *		only require the D-TLB to be invalidated.
+ *		- kaddr - Kernel virtual memory address
+ */
+
+static inline void local_flush_tlb_all(void)
+{
+	const int zero = 0;
+
+	/* TLB invalidate all */
+	asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (zero) : "cc");
+}
+
+static inline void local_flush_tlb_mm(struct mm_struct *mm)
+{
+	const int zero = 0;
+
+	if (cpumask_test_cpu(get_cpu(), mm_cpumask(mm))) {
+		/* TLB invalidate all */
+		asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (zero) : "cc");
+	}
+	put_cpu();
+}
+
+static inline void
+local_flush_tlb_page(struct vm_area_struct *vma, unsigned long uaddr)
+{
+	if (cpumask_test_cpu(smp_processor_id(), mm_cpumask(vma->vm_mm))) {
+#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+		/* iTLB invalidate page */
+		asm("movc p0.c6, %0, #5; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (uaddr & PAGE_MASK) : "cc");
+		/* dTLB invalidate page */
+		asm("movc p0.c6, %0, #3; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (uaddr & PAGE_MASK) : "cc");
+#else
+		/* TLB invalidate all */
+		asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+			: : "r" (uaddr & PAGE_MASK) : "cc");
+#endif
+	}
+}
+
+static inline void local_flush_tlb_kernel_page(unsigned long kaddr)
+{
+#ifndef CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+	/* iTLB invalidate page */
+	asm("movc p0.c6, %0, #5; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (kaddr & PAGE_MASK) : "cc");
+	/* dTLB invalidate page */
+	asm("movc p0.c6, %0, #3; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (kaddr & PAGE_MASK) : "cc");
+#else
+	/* TLB invalidate all */
+	asm("movc p0.c6, %0, #6; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (kaddr & PAGE_MASK) : "cc");
+#endif
+}
+
+/*
+ *	flush_pmd_entry
+ *
+ *	Flush a PMD entry (word aligned, or double-word aligned) to
+ *	RAM if the TLB for the CPU we are running on requires this.
+ *	This is typically used when we are creating PMD entries.
+ *
+ *	clean_pmd_entry
+ *
+ *	Clean (but don't drain the write buffer) if the CPU requires
+ *	these operations.  This is typically used when we are removing
+ *	PMD entries.
+ */
+static inline void flush_pmd_entry(pmd_t *pmd)
+{
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	/* flush dcache line, see dcacheline_flush in proc-macros.S */
+	asm("mov	r1, %0 << #20\n"
+		"ldw	r2, =_stext\n"
+		"add	r2, r2, r1 >> #20\n"
+		"ldw	r1, [r2+], #0x0000\n"
+		"ldw	r1, [r2+], #0x1000\n"
+		"ldw	r1, [r2+], #0x2000\n"
+		"ldw	r1, [r2+], #0x3000\n"
+		: : "r" (pmd) : "r1", "r2");
+#else
+	/* flush dcache all */
+	asm("movc p0.c5, %0, #14; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (pmd) : "cc");
+#endif
+}
+
+static inline void clean_pmd_entry(pmd_t *pmd)
+{
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	/* clean dcache line */
+	asm("movc p0.c5, %0, #11; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (__pa(pmd) & ~(L1_CACHE_BYTES - 1)) : "cc");
+#else
+	/* clean dcache all */
+	asm("movc p0.c5, %0, #10; nop; nop; nop; nop; nop; nop; nop; nop"
+		: : "r" (pmd) : "cc");
+#endif
+}
+
+/*
+ * Convert calls to our calling convention.
+ */
+#define local_flush_tlb_range(vma, start, end)	\
+	__cpu_flush_user_tlb_range(start, end, vma)
+#define local_flush_tlb_kernel_range(s, e)	\
+	__cpu_flush_kern_tlb_range(s, e)
+
+#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_kernel_page	local_flush_tlb_kernel_page
+#define flush_tlb_range		local_flush_tlb_range
+#define flush_tlb_kernel_range	local_flush_tlb_kernel_range
+
+/*
+ * if PG_dcache_clean is not set for the page, we need to ensure that any
+ * cache entries for the kernels virtual memory range are written
+ * back to the page.
+ */
+extern void update_mmu_cache(struct vm_area_struct *vma,
+		unsigned long addr, pte_t *ptep);
+
+extern void do_bad_area(unsigned long addr, unsigned int fsr,
+		struct pt_regs *regs);
+
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/tlb.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/tlb.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/tlb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/tlb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * linux/arch/unicore32/include/asm/tlb.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_TLB_H__
+#define __UNICORE_TLB_H__
+
+#define tlb_start_vma(tlb, vma)				do { } while (0)
+#define tlb_end_vma(tlb, vma)				do { } while (0)
+#define __tlb_remove_tlb_entry(tlb, ptep, address)	do { } while (0)
+#define tlb_flush(tlb) flush_tlb_mm((tlb)->mm)
+
+#define __pte_free_tlb(tlb, pte, addr)				\
+	do {							\
+		pgtable_page_dtor(pte);				\
+		tlb_remove_page((tlb), (pte));			\
+	} while (0)
+
+#include <asm-generic/tlb.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/traps.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/traps.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/traps.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/traps.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,21 @@
+/*
+ * linux/arch/unicore32/include/asm/traps.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_TRAP_H__
+#define __UNICORE_TRAP_H__
+
+extern void __init early_trap_init(void);
+extern void dump_backtrace_entry(unsigned long where,
+		unsigned long from, unsigned long frame);
+
+extern void do_DataAbort(unsigned long addr, unsigned int fsr,
+		 struct pt_regs *regs);
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/uaccess.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/uaccess.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/uaccess.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/uaccess.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+/*
+ * linux/arch/unicore32/include/asm/uaccess.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_UACCESS_H__
+#define __UNICORE_UACCESS_H__
+
+#include <linux/thread_info.h>
+#include <linux/errno.h>
+
+#include <asm/memory.h>
+#include <asm/system.h>
+
+#define __copy_from_user	__copy_from_user
+#define __copy_to_user		__copy_to_user
+#define __strncpy_from_user	__strncpy_from_user
+#define __strnlen_user		__strnlen_user
+#define __clear_user		__clear_user
+
+#define __kernel_ok		(segment_eq(get_fs(), KERNEL_DS))
+#define __user_ok(addr, size)	(((size) <= TASK_SIZE)			\
+				&& ((addr) <= TASK_SIZE - (size)))
+#define __access_ok(addr, size)	(__kernel_ok || __user_ok((addr), (size)))
+
+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
+__clear_user(void __user *addr, unsigned long n);
+extern unsigned long __must_check
+__strncpy_from_user(char *to, const char __user *from, unsigned long count);
+extern unsigned long
+__strnlen_user(const char __user *s, long n);
+
+#include <asm-generic/uaccess.h>
+
+extern int fixup_exception(struct pt_regs *regs);
+
+#endif /* __UNICORE_UACCESS_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/asm/unistd.h linux-libre-2.6.39-gnu/arch/unicore32/include/asm/unistd.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/asm/unistd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/asm/unistd.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,18 @@
+/*
+ * linux/arch/unicore32/include/asm/unistd.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+#if !defined(__UNICORE_UNISTD_H__) || defined(__SYSCALL)
+#define __UNICORE_UNISTD_H__
+
+/* Use the standard ABI for syscalls. */
+#include <asm-generic/unistd.h>
+
+#endif /* __UNICORE_UNISTD_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/bitfield.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/bitfield.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/bitfield.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/bitfield.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/include/mach/bitfield.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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_PUV3_BITFIELD_H__
+#define __MACH_PUV3_BITFIELD_H__
+
+#ifndef __ASSEMBLY__
+#define UData(Data)	((unsigned long) (Data))
+#else
+#define UData(Data)	(Data)
+#endif
+
+#define FIELD(val, vmask, vshift)	(((val) & ((UData(1) << (vmask)) - 1)) << (vshift))
+#define FMASK(vmask, vshift)		(((UData(1) << (vmask)) - 1) << (vshift))
+
+#endif /* __MACH_PUV3_BITFIELD_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/dma.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/dma.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/dma.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,48 @@
+/*
+ * linux/arch/unicore32/include/mach/dma.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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_PUV3_DMA_H__
+#define __MACH_PUV3_DMA_H__
+
+/*
+ * The PKUnity has six internal DMA channels.
+ */
+#define MAX_DMA_CHANNELS	6
+
+typedef enum {
+	DMA_PRIO_HIGH = 0,
+	DMA_PRIO_MEDIUM = 1,
+	DMA_PRIO_LOW = 2
+} puv3_dma_prio;
+
+/*
+ * DMA registration
+ */
+
+extern int puv3_request_dma(char *name,
+			 puv3_dma_prio prio,
+			 void (*irq_handler)(int, void *),
+			 void (*err_handler)(int, void *),
+			 void *data);
+
+extern void puv3_free_dma(int dma_ch);
+
+static inline void puv3_stop_dma(int ch)
+{
+	writel(readl(DMAC_CONFIG(ch)) & ~DMAC_CONFIG_EN, DMAC_CONFIG(ch));
+}
+
+static inline void puv3_resume_dma(int ch)
+{
+	writel(readl(DMAC_CONFIG(ch)) | DMAC_CONFIG_EN, DMAC_CONFIG(ch));
+}
+
+#endif /* __MACH_PUV3_DMA_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/hardware.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/hardware.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/hardware.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/hardware.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/unicore32/include/mach/hardware.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 file contains the hardware definitions for PKUnity architecture
+ */
+
+#ifndef __MACH_PUV3_HARDWARE_H__
+#define __MACH_PUV3_HARDWARE_H__
+
+#include "PKUnity.h"
+
+#ifndef __ASSEMBLY__
+#define io_p2v(x)	(void __iomem *)((x) - PKUNITY_MMIO_BASE)
+#define io_v2p(x)	(phys_addr_t)((x) + PKUNITY_MMIO_BASE)
+#else
+#define io_p2v(x)	((x) - PKUNITY_MMIO_BASE)
+#define io_v2p(x)	((x) + PKUNITY_MMIO_BASE)
+#endif
+
+#define PCIBIOS_MIN_IO			0x4000 /* should lower than 64KB */
+#define PCIBIOS_MIN_MEM			io_v2p(PKUNITY_PCIMEM_BASE)
+
+/*
+ * We override the standard dma-mask routines for bouncing.
+ */
+#define	HAVE_ARCH_PCI_SET_DMA_MASK
+
+#define pcibios_assign_all_busses()	1
+
+#endif  /* __MACH_PUV3_HARDWARE_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/map.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/map.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/map.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/map.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * linux/arch/unicore32/include/mach/map.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  Page table mapping constructs and function prototypes
+ */
+#define MT_DEVICE		0
+#define MT_DEVICE_CACHED	2
+#define MT_KUSER		7
+#define MT_HIGH_VECTORS		8
+#define MT_MEMORY		9
+#define MT_ROM			10
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/memory.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/memory.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/memory.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/memory.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * linux/arch/unicore32/include/mach/memory.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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_PUV3_MEMORY_H__
+#define __MACH_PUV3_MEMORY_H__
+
+#include <mach/hardware.h>
+
+/* Physical DRAM offset. */
+#define PHYS_OFFSET	UL(0x00000000)
+/* The base address of exception vectors. */
+#define VECTORS_BASE	UL(0xffff0000)
+/* The base address of kuser area. */
+#define KUSER_BASE	UL(0x80000000)
+
+#ifdef __ASSEMBLY__
+/* The byte offset of the kernel image in RAM from the start of RAM. */
+#define KERNEL_IMAGE_START	0x00408000
+#endif
+
+#if !defined(__ASSEMBLY__) && defined(CONFIG_PCI)
+
+void puv3_pci_adjust_zones(unsigned long *size, unsigned long *holes);
+
+#define arch_adjust_zones(size, holes) \
+	puv3_pci_adjust_zones(size, holes)
+
+#endif
+
+/*
+ * PCI controller in PKUnity-3 masks highest 5-bit for upstream channel,
+ * so we must limit the DMA allocation within 128M physical memory for
+ * supporting PCI devices.
+ */
+#define PCI_DMA_THRESHOLD	(PHYS_OFFSET + SZ_128M - 1)
+
+#define is_pcibus_device(dev)	(dev &&			\
+				(strncmp(dev->bus->name, "pci", 3) == 0))
+
+#define __virt_to_pcibus(x)     (__virt_to_phys((x) + PKUNITY_PCIAHB_BASE))
+#define __pcibus_to_virt(x)     (__phys_to_virt(x) - PKUNITY_PCIAHB_BASE)
+
+/* kuser area */
+#define KUSER_VECPAGE_BASE	(KUSER_BASE + UL(0x3fff0000))
+/* kuser_vecpage (0xbfff0000) is ro, and vectors page (0xffff0000) is rw */
+#define kuser_vecpage_to_vectors(x)	((x) - (KUSER_VECPAGE_BASE)	\
+					+ (VECTORS_BASE))
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/ocd.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/ocd.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/ocd.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/ocd.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * linux/arch/unicore32/include/mach/ocd.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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_PUV3_OCD_H__
+#define __MACH_PUV3_OCD_H__
+
+#if defined(CONFIG_DEBUG_OCD)
+static inline void ocd_putc(unsigned int c)
+{
+	int status, i = 0x2000000;
+
+	do {
+		if (--i < 0)
+			return;
+
+		asm volatile ("movc %0, p1.c0, #0" : "=r" (status));
+	} while (status & 2);
+
+	asm("movc p1.c1, %0, #1" : : "r" (c));
+}
+
+#define putc(ch)	ocd_putc(ch)
+#else
+#define putc(ch)
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/PKUnity.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/PKUnity.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/PKUnity.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/PKUnity.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/unicore32/include/mach/PKUnity.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+
+/* Be sure that virtual mapping is defined right */
+#ifndef __MACH_PUV3_HARDWARE_H__
+#error You must include hardware.h not PKUnity.h
+#endif
+
+#include "bitfield.h"
+
+/*
+ * Memory Definitions
+ */
+#define PKUNITY_SDRAM_BASE		0x00000000 /* 0x00000000 - 0x7FFFFFFF 2GB */
+#define PKUNITY_MMIO_BASE		0x80000000 /* 0x80000000 - 0xFFFFFFFF 2GB */
+
+/*
+ * PKUNITY System Bus Addresses (PCI): 0x80000000 - 0xBFFFFFFF (1GB)
+ * 0x80000000 - 0x8000000B 12B    PCI Configuration regs
+ * 0x80010000 - 0x80010250 592B   PCI Bridge Base
+ * 0x80030000 - 0x8003FFFF 64KB   PCI Legacy IO
+ * 0x90000000 - 0x97FFFFFF 128MB  PCI AHB-PCI MEM-mapping
+ * 0x98000000 - 0x9FFFFFFF 128MB  PCI PCI-AHB MEM-mapping
+ */
+#define PKUNITY_PCI_BASE		io_p2v(0x80000000) /* 0x80000000 - 0xBFFFFFFF 1GB */
+#include "regs-pci.h"
+
+#define PKUNITY_PCICFG_BASE		(PKUNITY_PCI_BASE + 0x0)
+#define PKUNITY_PCIBRI_BASE		(PKUNITY_PCI_BASE + 0x00010000)
+#define PKUNITY_PCILIO_BASE		(PKUNITY_PCI_BASE + 0x00030000)
+#define PKUNITY_PCIMEM_BASE		(PKUNITY_PCI_BASE + 0x10000000)
+#define PKUNITY_PCIAHB_BASE		(PKUNITY_PCI_BASE + 0x18000000)
+
+/*
+ * PKUNITY System Bus Addresses (AHB): 0xC0000000 - 0xEDFFFFFF (640MB)
+ */
+#define PKUNITY_AHB_BASE		io_p2v(0xC0000000)
+
+/* AHB-0 is DDR2 SDRAM */
+/* AHB-1 is PCI Space */
+#define PKUNITY_ARBITER_BASE		(PKUNITY_AHB_BASE + 0x000000) /* AHB-2 */
+#define PKUNITY_DDR2CTRL_BASE		(PKUNITY_AHB_BASE + 0x100000) /* AHB-3 */
+#define PKUNITY_DMAC_BASE		(PKUNITY_AHB_BASE + 0x200000) /* AHB-4 */
+#include "regs-dmac.h"
+#define PKUNITY_UMAL_BASE		(PKUNITY_AHB_BASE + 0x300000) /* AHB-5 */
+#include "regs-umal.h"
+#define PKUNITY_USB_BASE		(PKUNITY_AHB_BASE + 0x400000) /* AHB-6 */
+#define PKUNITY_SATA_BASE		(PKUNITY_AHB_BASE + 0x500000) /* AHB-7 */
+#define PKUNITY_SMC_BASE		(PKUNITY_AHB_BASE + 0x600000) /* AHB-8 */
+/* AHB-9 is for APB bridge */
+#define PKUNITY_MME_BASE		(PKUNITY_AHB_BASE + 0x700000) /* AHB-10 */
+#define PKUNITY_UNIGFX_BASE		(PKUNITY_AHB_BASE + 0x800000) /* AHB-11 */
+#include "regs-unigfx.h"
+#define PKUNITY_NAND_BASE		(PKUNITY_AHB_BASE + 0x900000) /* AHB-12 */
+#include "regs-nand.h"
+#define PKUNITY_H264D_BASE		(PKUNITY_AHB_BASE + 0xA00000) /* AHB-13 */
+#define PKUNITY_H264E_BASE		(PKUNITY_AHB_BASE + 0xB00000) /* AHB-14 */
+
+/*
+ * PKUNITY Peripheral Bus Addresses (APB): 0xEE000000 - 0xEFFFFFFF (128MB)
+ */
+#define PKUNITY_APB_BASE		io_p2v(0xEE000000)
+
+#define PKUNITY_UART0_BASE		(PKUNITY_APB_BASE + 0x000000) /* APB-0 */
+#define PKUNITY_UART1_BASE		(PKUNITY_APB_BASE + 0x100000) /* APB-1 */
+#include "regs-uart.h"
+#define PKUNITY_I2C_BASE		(PKUNITY_APB_BASE + 0x200000) /* APB-2 */
+#include "regs-i2c.h"
+#define PKUNITY_SPI_BASE		(PKUNITY_APB_BASE + 0x300000) /* APB-3 */
+#include "regs-spi.h"
+#define PKUNITY_AC97_BASE		(PKUNITY_APB_BASE + 0x400000) /* APB-4 */
+#include "regs-ac97.h"
+#define PKUNITY_GPIO_BASE		(PKUNITY_APB_BASE + 0x500000) /* APB-5 */
+#include "regs-gpio.h"
+#define PKUNITY_INTC_BASE		(PKUNITY_APB_BASE + 0x600000) /* APB-6 */
+#include "regs-intc.h"
+#define PKUNITY_RTC_BASE		(PKUNITY_APB_BASE + 0x700000) /* APB-7 */
+#include "regs-rtc.h"
+#define PKUNITY_OST_BASE		(PKUNITY_APB_BASE + 0x800000) /* APB-8 */
+#include "regs-ost.h"
+#define PKUNITY_RESETC_BASE		(PKUNITY_APB_BASE + 0x900000) /* APB-9 */
+#include "regs-resetc.h"
+#define PKUNITY_PM_BASE			(PKUNITY_APB_BASE + 0xA00000) /* APB-10 */
+#include "regs-pm.h"
+#define PKUNITY_PS2_BASE		(PKUNITY_APB_BASE + 0xB00000) /* APB-11 */
+#include "regs-ps2.h"
+#define PKUNITY_SDC_BASE		(PKUNITY_APB_BASE + 0xC00000) /* APB-12 */
+#include "regs-sdc.h"
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/pm.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/pm.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/pm.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,43 @@
+/*
+ * linux/arch/unicore/include/mach/pm.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __PUV3_PM_H__
+#define __PUV3_PM_H__
+
+#include <linux/suspend.h>
+
+struct puv3_cpu_pm_fns {
+	int	save_count;
+	void	(*save)(unsigned long *);
+	void	(*restore)(unsigned long *);
+	int	(*valid)(suspend_state_t state);
+	void	(*enter)(suspend_state_t state);
+	int	(*prepare)(void);
+	void	(*finish)(void);
+};
+
+extern struct puv3_cpu_pm_fns *puv3_cpu_pm_fns;
+
+/* sleep.S */
+extern void puv3_cpu_suspend(unsigned int);
+
+extern void puv3_cpu_resume(void);
+
+extern int puv3_pm_enter(suspend_state_t state);
+
+/* Defined in hibernate_asm.S */
+extern int restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist);
+
+/* References to section boundaries */
+extern const void __nosave_begin, __nosave_end;
+
+extern struct pbe *restore_pblist;
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-ac97.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-ac97.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-ac97.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-ac97.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * PKUnity AC97 Registers
+ */
+
+#define PKUNITY_AC97_CONR		(PKUNITY_AC97_BASE + 0x0000)
+#define PKUNITY_AC97_OCR		(PKUNITY_AC97_BASE + 0x0004)
+#define PKUNITY_AC97_ICR		(PKUNITY_AC97_BASE + 0x0008)
+#define PKUNITY_AC97_CRAC		(PKUNITY_AC97_BASE + 0x000C)
+#define PKUNITY_AC97_INTR		(PKUNITY_AC97_BASE + 0x0010)
+#define PKUNITY_AC97_INTRSTAT		(PKUNITY_AC97_BASE + 0x0014)
+#define PKUNITY_AC97_INTRCLEAR		(PKUNITY_AC97_BASE + 0x0018)
+#define PKUNITY_AC97_ENABLE		(PKUNITY_AC97_BASE + 0x001C)
+#define PKUNITY_AC97_OUT_FIFO		(PKUNITY_AC97_BASE + 0x0020)
+#define PKUNITY_AC97_IN_FIFO		(PKUNITY_AC97_BASE + 0x0030)
+
+#define AC97_CODEC_REG(v)               FIELD((v), 7, 16)
+#define AC97_CODEC_VAL(v)               FIELD((v), 16, 0)
+#define AC97_CODEC_WRITECOMPLETE        FIELD(1, 1, 2)
+
+/*
+ * VAR PLAY SAMPLE RATE
+ */
+#define AC97_CMD_VPSAMPLE		(FIELD(3, 2, 16) | FIELD(3, 2, 0))
+
+/*
+ * FIX CAPTURE SAMPLE RATE
+ */
+#define AC97_CMD_FCSAMPLE		FIELD(7, 3, 0)
+
+#define AC97_CMD_RESET			FIELD(1, 1, 0)
+#define AC97_CMD_ENABLE			FIELD(1, 1, 0)
+#define AC97_CMD_DISABLE		FIELD(0, 1, 0)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-dmac.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-dmac.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-dmac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-dmac.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,81 @@
+/*
+ * PKUnity Direct Memory Access Controller (DMAC)
+ */
+
+/*
+ * Interrupt Status Reg DMAC_ISR.
+ */
+#define DMAC_ISR		(PKUNITY_DMAC_BASE + 0x0020)
+/*
+ * Interrupt Transfer Complete Status Reg DMAC_ITCSR.
+ */
+#define DMAC_ITCSR		(PKUNITY_DMAC_BASE + 0x0050)
+/*
+ * Interrupt Transfer Complete Clear Reg DMAC_ITCCR.
+ */
+#define DMAC_ITCCR		(PKUNITY_DMAC_BASE + 0x0060)
+/*
+ * Interrupt Error Status Reg DMAC_IESR.
+ */
+#define DMAC_IESR		(PKUNITY_DMAC_BASE + 0x0080)
+/*
+ * Interrupt Error Clear Reg DMAC_IECR.
+ */
+#define DMAC_IECR		(PKUNITY_DMAC_BASE + 0x0090)
+/*
+ * Enable Channels Reg DMAC_ENCH.
+ */
+#define DMAC_ENCH		(PKUNITY_DMAC_BASE + 0x00B0)
+
+/*
+ * DMA control reg. Space [byte]
+ */
+#define DMASp                   0x00000100
+
+/*
+ * Source Addr DMAC_SRCADDR(ch).
+ */
+#define DMAC_SRCADDR(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x00)
+/*
+ * Destination Addr DMAC_DESTADDR(ch).
+ */
+#define DMAC_DESTADDR(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x04)
+/*
+ * Control Reg DMAC_CONTROL(ch).
+ */
+#define DMAC_CONTROL(ch)	(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x0C)
+/*
+ * Configuration Reg DMAC_CONFIG(ch).
+ */
+#define DMAC_CONFIG(ch)		(PKUNITY_DMAC_BASE + (ch)*DMASp + 0x10)
+
+#define DMAC_IR_MASK            FMASK(6, 0)
+/*
+ * select channel (ch)
+ */
+#define DMAC_CHANNEL(ch)	FIELD(1, 1, (ch))
+
+#define DMAC_CONTROL_SIZE_BYTE(v)       (FIELD((v), 12, 14) | \
+					FIELD(0, 3, 9) | FIELD(0, 3, 6))
+#define DMAC_CONTROL_SIZE_HWORD(v)      (FIELD((v) >> 1, 12, 14) | \
+					FIELD(1, 3, 9) | FIELD(1, 3, 6))
+#define DMAC_CONTROL_SIZE_WORD(v)       (FIELD((v) >> 2, 12, 14) | \
+					FIELD(2, 3, 9) | FIELD(2, 3, 6))
+#define DMAC_CONTROL_DI                 FIELD(1, 1, 13)
+#define DMAC_CONTROL_SI                 FIELD(1, 1, 12)
+#define DMAC_CONTROL_BURST_1BYTE        (FIELD(0, 3, 3) | FIELD(0, 3, 0))
+#define DMAC_CONTROL_BURST_4BYTE        (FIELD(3, 3, 3) | FIELD(3, 3, 0))
+#define DMAC_CONTROL_BURST_8BYTE        (FIELD(5, 3, 3) | FIELD(5, 3, 0))
+#define DMAC_CONTROL_BURST_16BYTE       (FIELD(7, 3, 3) | FIELD(7, 3, 0))
+
+#define	DMAC_CONFIG_UART0_WR    (FIELD(2, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_UART0_RD    (FIELD(2, 4, 7)  | FIELD(2, 2, 1))
+#define	DMAC_CONFIG_UART1_WR    (FIELD(3, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_UART1RD     (FIELD(3, 4, 7)  | FIELD(2, 2, 1))
+#define	DMAC_CONFIG_AC97WR      (FIELD(4, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_AC97RD      (FIELD(4, 4, 7)  | FIELD(2, 2, 1))
+#define	DMAC_CONFIG_MMCWR       (FIELD(7, 4, 11) | FIELD(1, 2, 1))
+#define	DMAC_CONFIG_MMCRD       (FIELD(7, 4, 7)  | FIELD(2, 2, 1))
+#define DMAC_CONFIG_MASKITC     FIELD(1, 1, 4)
+#define DMAC_CONFIG_MASKIE      FIELD(1, 1, 3)
+#define DMAC_CONFIG_EN          FIELD(1, 1, 0)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-gpio.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-gpio.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-gpio.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-gpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * PKUnity General-Purpose Input/Output (GPIO) Registers
+ */
+
+/*
+ * Voltage Status Reg GPIO_GPLR.
+ */
+#define GPIO_GPLR	(PKUNITY_GPIO_BASE + 0x0000)
+/*
+ * Pin Direction Reg GPIO_GPDR.
+ */
+#define GPIO_GPDR	(PKUNITY_GPIO_BASE + 0x0004)
+/*
+ * Output Pin Set Reg GPIO_GPSR.
+ */
+#define GPIO_GPSR	(PKUNITY_GPIO_BASE + 0x0008)
+/*
+ * Output Pin Clear Reg GPIO_GPCR.
+ */
+#define GPIO_GPCR	(PKUNITY_GPIO_BASE + 0x000C)
+/*
+ * Raise Edge Detect Reg GPIO_GRER.
+ */
+#define GPIO_GRER	(PKUNITY_GPIO_BASE + 0x0010)
+/*
+ * Fall Edge Detect Reg GPIO_GFER.
+ */
+#define GPIO_GFER	(PKUNITY_GPIO_BASE + 0x0014)
+/*
+ * Edge Status Reg GPIO_GEDR.
+ */
+#define GPIO_GEDR	(PKUNITY_GPIO_BASE + 0x0018)
+/*
+ * Sepcial Voltage Detect Reg GPIO_GPIR.
+ */
+#define GPIO_GPIR	(PKUNITY_GPIO_BASE + 0x0020)
+
+#define GPIO_MIN	(0)
+#define GPIO_MAX	(27)
+
+#define GPIO_GPIO(Nb)	(0x00000001 << (Nb))	/* GPIO [0..27] */
+#define GPIO_GPIO0	GPIO_GPIO(0)	/* GPIO  [0] */
+#define GPIO_GPIO1	GPIO_GPIO(1)	/* GPIO  [1] */
+#define GPIO_GPIO2	GPIO_GPIO(2)	/* GPIO  [2] */
+#define GPIO_GPIO3	GPIO_GPIO(3)	/* GPIO  [3] */
+#define GPIO_GPIO4	GPIO_GPIO(4)	/* GPIO  [4] */
+#define GPIO_GPIO5	GPIO_GPIO(5)	/* GPIO  [5] */
+#define GPIO_GPIO6	GPIO_GPIO(6)	/* GPIO  [6] */
+#define GPIO_GPIO7	GPIO_GPIO(7)	/* GPIO  [7] */
+#define GPIO_GPIO8	GPIO_GPIO(8)	/* GPIO  [8] */
+#define GPIO_GPIO9	GPIO_GPIO(9)	/* GPIO  [9] */
+#define GPIO_GPIO10	GPIO_GPIO(10)	/* GPIO [10] */
+#define GPIO_GPIO11	GPIO_GPIO(11)	/* GPIO [11] */
+#define GPIO_GPIO12	GPIO_GPIO(12)	/* GPIO [12] */
+#define GPIO_GPIO13	GPIO_GPIO(13)	/* GPIO [13] */
+#define GPIO_GPIO14	GPIO_GPIO(14)	/* GPIO [14] */
+#define GPIO_GPIO15	GPIO_GPIO(15)	/* GPIO [15] */
+#define GPIO_GPIO16	GPIO_GPIO(16)	/* GPIO [16] */
+#define GPIO_GPIO17	GPIO_GPIO(17)	/* GPIO [17] */
+#define GPIO_GPIO18	GPIO_GPIO(18)	/* GPIO [18] */
+#define GPIO_GPIO19	GPIO_GPIO(19)	/* GPIO [19] */
+#define GPIO_GPIO20	GPIO_GPIO(20)	/* GPIO [20] */
+#define GPIO_GPIO21	GPIO_GPIO(21)	/* GPIO [21] */
+#define GPIO_GPIO22	GPIO_GPIO(22)	/* GPIO [22] */
+#define GPIO_GPIO23	GPIO_GPIO(23)	/* GPIO [23] */
+#define GPIO_GPIO24	GPIO_GPIO(24)	/* GPIO [24] */
+#define GPIO_GPIO25	GPIO_GPIO(25)	/* GPIO [25] */
+#define GPIO_GPIO26	GPIO_GPIO(26)	/* GPIO [26] */
+#define GPIO_GPIO27	GPIO_GPIO(27)	/* GPIO [27] */
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-i2c.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-i2c.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-i2c.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-i2c.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * PKUnity Inter-integrated Circuit (I2C) Registers
+ */
+
+/*
+ * Control Reg I2C_CON.
+ */
+#define I2C_CON		(PKUNITY_I2C_BASE + 0x0000)
+/*
+ * Target Address Reg I2C_TAR.
+ */
+#define I2C_TAR		(PKUNITY_I2C_BASE + 0x0004)
+/*
+ * Data buffer and command Reg I2C_DATACMD.
+ */
+#define I2C_DATACMD	(PKUNITY_I2C_BASE + 0x0010)
+/*
+ * Enable Reg I2C_ENABLE.
+ */
+#define I2C_ENABLE	(PKUNITY_I2C_BASE + 0x006C)
+/*
+ * Status Reg I2C_STATUS.
+ */
+#define I2C_STATUS	(PKUNITY_I2C_BASE + 0x0070)
+/*
+ * Tx FIFO Length Reg I2C_TXFLR.
+ */
+#define I2C_TXFLR	(PKUNITY_I2C_BASE + 0x0074)
+/*
+ * Rx FIFO Length Reg I2C_RXFLR.
+ */
+#define I2C_RXFLR	(PKUNITY_I2C_BASE + 0x0078)
+/*
+ * Enable Status Reg I2C_ENSTATUS.
+ */
+#define I2C_ENSTATUS	(PKUNITY_I2C_BASE + 0x009C)
+
+#define I2C_CON_MASTER          FIELD(1, 1, 0)
+#define I2C_CON_SPEED_STD       FIELD(1, 2, 1)
+#define I2C_CON_SPEED_FAST      FIELD(2, 2, 1)
+#define I2C_CON_RESTART         FIELD(1, 1, 5)
+#define I2C_CON_SLAVEDISABLE    FIELD(1, 1, 6)
+
+#define I2C_DATACMD_READ        FIELD(1, 1, 8)
+#define I2C_DATACMD_WRITE       FIELD(0, 1, 8)
+#define I2C_DATACMD_DAT_MASK    FMASK(8, 0)
+#define I2C_DATACMD_DAT(v)      FIELD((v), 8, 0)
+
+#define I2C_ENABLE_ENABLE       FIELD(1, 1, 0)
+#define I2C_ENABLE_DISABLE      FIELD(0, 1, 0)
+
+#define I2C_STATUS_RFF          FIELD(1, 1, 4)
+#define I2C_STATUS_RFNE         FIELD(1, 1, 3)
+#define I2C_STATUS_TFE          FIELD(1, 1, 2)
+#define I2C_STATUS_TFNF         FIELD(1, 1, 1)
+#define I2C_STATUS_ACTIVITY     FIELD(1, 1, 0)
+
+#define I2C_ENSTATUS_ENABLE	FIELD(1, 1, 0)
+
+#define I2C_TAR_THERMAL	0x4f
+#define I2C_TAR_SPD	0x50
+#define I2C_TAR_PWIC    0x55
+#define I2C_TAR_EEPROM	0x57
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-intc.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-intc.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-intc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-intc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+/*
+ * PKUNITY Interrupt Controller (INTC) Registers
+ */
+/*
+ * INTC Level Reg INTC_ICLR.
+ */
+#define INTC_ICLR	(PKUNITY_INTC_BASE + 0x0000)
+/*
+ * INTC Mask Reg INTC_ICMR.
+ */
+#define INTC_ICMR	(PKUNITY_INTC_BASE + 0x0004)
+/*
+ * INTC Pending Reg INTC_ICPR.
+ */
+#define INTC_ICPR	(PKUNITY_INTC_BASE + 0x0008)
+/*
+ * INTC IRQ Pending Reg INTC_ICIP.
+ */
+#define INTC_ICIP	(PKUNITY_INTC_BASE + 0x000C)
+/*
+ * INTC REAL Pending Reg INTC_ICFP.
+ */
+#define INTC_ICFP	(PKUNITY_INTC_BASE + 0x0010)
+/*
+ * INTC Control Reg INTC_ICCR.
+ */
+#define INTC_ICCR	(PKUNITY_INTC_BASE + 0x0014)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-nand.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-nand.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-nand.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-nand.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,79 @@
+/*
+ * PKUnity NAND Controller Registers
+ */
+/*
+ * ID Reg. 0 NAND_IDR0
+ */
+#define NAND_IDR0	(PKUNITY_NAND_BASE + 0x0000)
+/*
+ * ID Reg. 1 NAND_IDR1
+ */
+#define NAND_IDR1	(PKUNITY_NAND_BASE + 0x0004)
+/*
+ * ID Reg. 2 NAND_IDR2
+ */
+#define NAND_IDR2	(PKUNITY_NAND_BASE + 0x0008)
+/*
+ * ID Reg. 3 NAND_IDR3
+ */
+#define NAND_IDR3	(PKUNITY_NAND_BASE + 0x000C)
+/*
+ * Page Address Reg 0 NAND_PAR0
+ */
+#define NAND_PAR0	(PKUNITY_NAND_BASE + 0x0010)
+/*
+ * Page Address Reg 1 NAND_PAR1
+ */
+#define NAND_PAR1	(PKUNITY_NAND_BASE + 0x0014)
+/*
+ * Page Address Reg 2 NAND_PAR2
+ */
+#define NAND_PAR2	(PKUNITY_NAND_BASE + 0x0018)
+/*
+ * ECC Enable Reg NAND_ECCEN
+ */
+#define NAND_ECCEN	(PKUNITY_NAND_BASE + 0x001C)
+/*
+ * Buffer Reg NAND_BUF
+ */
+#define NAND_BUF	(PKUNITY_NAND_BASE + 0x0020)
+/*
+ * ECC Status Reg NAND_ECCSR
+ */
+#define NAND_ECCSR	(PKUNITY_NAND_BASE + 0x0024)
+/*
+ * Command Reg NAND_CMD
+ */
+#define NAND_CMD	(PKUNITY_NAND_BASE + 0x0028)
+/*
+ * DMA Configure Reg NAND_DMACR
+ */
+#define NAND_DMACR	(PKUNITY_NAND_BASE + 0x002C)
+/*
+ * Interrupt Reg NAND_IR
+ */
+#define NAND_IR		(PKUNITY_NAND_BASE + 0x0030)
+/*
+ * Interrupt Mask Reg NAND_IMR
+ */
+#define NAND_IMR	(PKUNITY_NAND_BASE + 0x0034)
+/*
+ * Chip Enable Reg NAND_CHIPEN
+ */
+#define NAND_CHIPEN	(PKUNITY_NAND_BASE + 0x0038)
+/*
+ * Address Reg NAND_ADDR
+ */
+#define NAND_ADDR	(PKUNITY_NAND_BASE + 0x003C)
+
+/*
+ * Command bits NAND_CMD_CMD_MASK
+ */
+#define NAND_CMD_CMD_MASK		FMASK(4, 4)
+#define NAND_CMD_CMD_READPAGE		FIELD(0x0, 4, 4)
+#define NAND_CMD_CMD_ERASEBLOCK		FIELD(0x6, 4, 4)
+#define NAND_CMD_CMD_READSTATUS		FIELD(0x7, 4, 4)
+#define NAND_CMD_CMD_WRITEPAGE		FIELD(0x8, 4, 4)
+#define NAND_CMD_CMD_READID		FIELD(0x9, 4, 4)
+#define NAND_CMD_CMD_RESET		FIELD(0xf, 4, 4)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-ost.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-ost.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-ost.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-ost.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,92 @@
+/*
+ * PKUnity Operating System Timer (OST) Registers
+ */
+/*
+ * Match Reg 0 OST_OSMR0
+ */
+#define OST_OSMR0	(PKUNITY_OST_BASE + 0x0000)
+/*
+ * Match Reg 1 OST_OSMR1
+ */
+#define OST_OSMR1	(PKUNITY_OST_BASE + 0x0004)
+/*
+ * Match Reg 2 OST_OSMR2
+ */
+#define OST_OSMR2	(PKUNITY_OST_BASE + 0x0008)
+/*
+ * Match Reg 3 OST_OSMR3
+ */
+#define OST_OSMR3	(PKUNITY_OST_BASE + 0x000C)
+/*
+ * Counter Reg OST_OSCR
+ */
+#define OST_OSCR	(PKUNITY_OST_BASE + 0x0010)
+/*
+ * Status Reg OST_OSSR
+ */
+#define OST_OSSR	(PKUNITY_OST_BASE + 0x0014)
+/*
+ * Watchdog Enable Reg OST_OWER
+ */
+#define OST_OWER	(PKUNITY_OST_BASE + 0x0018)
+/*
+ * Interrupt Enable Reg OST_OIER
+ */
+#define OST_OIER	(PKUNITY_OST_BASE + 0x001C)
+/*
+ * PWM Pulse Width Control Reg OST_PWMPWCR
+ */
+#define OST_PWMPWCR	(PKUNITY_OST_BASE + 0x0080)
+/*
+ * PWM Duty Cycle Control Reg OST_PWMDCCR
+ */
+#define OST_PWMDCCR	(PKUNITY_OST_BASE + 0x0084)
+/*
+ * PWM Period Control Reg OST_PWMPCR
+ */
+#define OST_PWMPCR	(PKUNITY_OST_BASE + 0x0088)
+
+/*
+ * Match detected 0 OST_OSSR_M0
+ */
+#define OST_OSSR_M0		FIELD(1, 1, 0)
+/*
+ * Match detected 1 OST_OSSR_M1
+ */
+#define OST_OSSR_M1		FIELD(1, 1, 1)
+/*
+ * Match detected 2 OST_OSSR_M2
+ */
+#define OST_OSSR_M2		FIELD(1, 1, 2)
+/*
+ * Match detected 3 OST_OSSR_M3
+ */
+#define OST_OSSR_M3		FIELD(1, 1, 3)
+
+/*
+ * Interrupt enable 0 OST_OIER_E0
+ */
+#define OST_OIER_E0		FIELD(1, 1, 0)
+/*
+ * Interrupt enable 1 OST_OIER_E1
+ */
+#define OST_OIER_E1		FIELD(1, 1, 1)
+/*
+ * Interrupt enable 2 OST_OIER_E2
+ */
+#define OST_OIER_E2		FIELD(1, 1, 2)
+/*
+ * Interrupt enable 3 OST_OIER_E3
+ */
+#define OST_OIER_E3		FIELD(1, 1, 3)
+
+/*
+ * Watchdog Match Enable OST_OWER_WME
+ */
+#define OST_OWER_WME		FIELD(1, 1, 0)
+
+/*
+ * PWM Full Duty Cycle OST_PWMDCCR_FDCYCLE
+ */
+#define OST_PWMDCCR_FDCYCLE	FIELD(1, 1, 10)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-pci.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-pci.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-pci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,94 @@
+/*
+ * PKUnity AHB-PCI Bridge Registers
+ */
+
+/*
+ * AHB/PCI fixed physical address for pci addess configuration
+ */
+/*
+ * PCICFG Bridge Base Reg.
+ */
+#define PCICFG_BRIBASE          (PKUNITY_PCICFG_BASE + 0x0000)
+/*
+ * PCICFG Address Reg.
+ */
+#define PCICFG_ADDR             (PKUNITY_PCICFG_BASE + 0x0004)
+/*
+ * PCICFG Address Reg.
+ */
+#define PCICFG_DATA             (PKUNITY_PCICFG_BASE + 0x0008)
+
+/*
+ * PCI Bridge configuration space
+ */
+#define PCIBRI_ID		(PKUNITY_PCIBRI_BASE + 0x0000)
+#define PCIBRI_CMD		(PKUNITY_PCIBRI_BASE + 0x0004)
+#define PCIBRI_CLASS		(PKUNITY_PCIBRI_BASE + 0x0008)
+#define PCIBRI_LTR		(PKUNITY_PCIBRI_BASE + 0x000C)
+#define PCIBRI_BAR0		(PKUNITY_PCIBRI_BASE + 0x0010)
+#define PCIBRI_BAR1		(PKUNITY_PCIBRI_BASE + 0x0014)
+#define PCIBRI_BAR2		(PKUNITY_PCIBRI_BASE + 0x0018)
+#define PCIBRI_BAR3		(PKUNITY_PCIBRI_BASE + 0x001C)
+#define PCIBRI_BAR4		(PKUNITY_PCIBRI_BASE + 0x0020)
+#define PCIBRI_BAR5		(PKUNITY_PCIBRI_BASE + 0x0024)
+
+#define PCIBRI_PCICTL0		(PKUNITY_PCIBRI_BASE + 0x0100)
+#define PCIBRI_PCIBAR0		(PKUNITY_PCIBRI_BASE + 0x0104)
+#define PCIBRI_PCIAMR0		(PKUNITY_PCIBRI_BASE + 0x0108)
+#define PCIBRI_PCITAR0		(PKUNITY_PCIBRI_BASE + 0x010C)
+#define PCIBRI_PCICTL1		(PKUNITY_PCIBRI_BASE + 0x0110)
+#define PCIBRI_PCIBAR1		(PKUNITY_PCIBRI_BASE + 0x0114)
+#define PCIBRI_PCIAMR1		(PKUNITY_PCIBRI_BASE + 0x0118)
+#define PCIBRI_PCITAR1		(PKUNITY_PCIBRI_BASE + 0x011C)
+#define PCIBRI_PCICTL2		(PKUNITY_PCIBRI_BASE + 0x0120)
+#define PCIBRI_PCIBAR2		(PKUNITY_PCIBRI_BASE + 0x0124)
+#define PCIBRI_PCIAMR2		(PKUNITY_PCIBRI_BASE + 0x0128)
+#define PCIBRI_PCITAR2		(PKUNITY_PCIBRI_BASE + 0x012C)
+#define PCIBRI_PCICTL3		(PKUNITY_PCIBRI_BASE + 0x0130)
+#define PCIBRI_PCIBAR3		(PKUNITY_PCIBRI_BASE + 0x0134)
+#define PCIBRI_PCIAMR3		(PKUNITY_PCIBRI_BASE + 0x0138)
+#define PCIBRI_PCITAR3		(PKUNITY_PCIBRI_BASE + 0x013C)
+#define PCIBRI_PCICTL4		(PKUNITY_PCIBRI_BASE + 0x0140)
+#define PCIBRI_PCIBAR4		(PKUNITY_PCIBRI_BASE + 0x0144)
+#define PCIBRI_PCIAMR4		(PKUNITY_PCIBRI_BASE + 0x0148)
+#define PCIBRI_PCITAR4		(PKUNITY_PCIBRI_BASE + 0x014C)
+#define PCIBRI_PCICTL5		(PKUNITY_PCIBRI_BASE + 0x0150)
+#define PCIBRI_PCIBAR5		(PKUNITY_PCIBRI_BASE + 0x0154)
+#define PCIBRI_PCIAMR5		(PKUNITY_PCIBRI_BASE + 0x0158)
+#define PCIBRI_PCITAR5		(PKUNITY_PCIBRI_BASE + 0x015C)
+
+#define PCIBRI_AHBCTL0		(PKUNITY_PCIBRI_BASE + 0x0180)
+#define PCIBRI_AHBBAR0		(PKUNITY_PCIBRI_BASE + 0x0184)
+#define PCIBRI_AHBAMR0		(PKUNITY_PCIBRI_BASE + 0x0188)
+#define PCIBRI_AHBTAR0		(PKUNITY_PCIBRI_BASE + 0x018C)
+#define PCIBRI_AHBCTL1		(PKUNITY_PCIBRI_BASE + 0x0190)
+#define PCIBRI_AHBBAR1		(PKUNITY_PCIBRI_BASE + 0x0194)
+#define PCIBRI_AHBAMR1		(PKUNITY_PCIBRI_BASE + 0x0198)
+#define PCIBRI_AHBTAR1		(PKUNITY_PCIBRI_BASE + 0x019C)
+#define PCIBRI_AHBCTL2		(PKUNITY_PCIBRI_BASE + 0x01A0)
+#define PCIBRI_AHBBAR2		(PKUNITY_PCIBRI_BASE + 0x01A4)
+#define PCIBRI_AHBAMR2		(PKUNITY_PCIBRI_BASE + 0x01A8)
+#define PCIBRI_AHBTAR2		(PKUNITY_PCIBRI_BASE + 0x01AC)
+#define PCIBRI_AHBCTL3		(PKUNITY_PCIBRI_BASE + 0x01B0)
+#define PCIBRI_AHBBAR3		(PKUNITY_PCIBRI_BASE + 0x01B4)
+#define PCIBRI_AHBAMR3		(PKUNITY_PCIBRI_BASE + 0x01B8)
+#define PCIBRI_AHBTAR3		(PKUNITY_PCIBRI_BASE + 0x01BC)
+#define PCIBRI_AHBCTL4		(PKUNITY_PCIBRI_BASE + 0x01C0)
+#define PCIBRI_AHBBAR4		(PKUNITY_PCIBRI_BASE + 0x01C4)
+#define PCIBRI_AHBAMR4		(PKUNITY_PCIBRI_BASE + 0x01C8)
+#define PCIBRI_AHBTAR4		(PKUNITY_PCIBRI_BASE + 0x01CC)
+#define PCIBRI_AHBCTL5		(PKUNITY_PCIBRI_BASE + 0x01D0)
+#define PCIBRI_AHBBAR5		(PKUNITY_PCIBRI_BASE + 0x01D4)
+#define PCIBRI_AHBAMR5		(PKUNITY_PCIBRI_BASE + 0x01D8)
+#define PCIBRI_AHBTAR5		(PKUNITY_PCIBRI_BASE + 0x01DC)
+
+#define PCIBRI_CTLx_AT          FIELD(1, 1, 2)
+#define PCIBRI_CTLx_PREF        FIELD(1, 1, 1)
+#define PCIBRI_CTLx_MRL         FIELD(1, 1, 0)
+
+#define PCIBRI_BARx_ADDR        FIELD(0xFFFFFFFC, 30, 2)
+#define PCIBRI_BARx_IO          FIELD(1, 1, 0)
+#define PCIBRI_BARx_MEM         FIELD(0, 1, 0)
+
+#define PCIBRI_CMD_IO           FIELD(1, 1, 0)
+#define PCIBRI_CMD_MEM          FIELD(1, 1, 1)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-pm.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-pm.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-pm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-pm.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,126 @@
+/*
+ * PKUNITY Power Manager (PM) Registers
+ */
+/*
+ * PM Control Reg PM_PMCR
+ */
+#define PM_PMCR                 (PKUNITY_PM_BASE + 0x0000)
+/*
+ * PM General Conf. Reg PM_PGCR
+ */
+#define PM_PGCR                 (PKUNITY_PM_BASE + 0x0004)
+/*
+ * PM PLL Conf. Reg PM_PPCR
+ */
+#define PM_PPCR                 (PKUNITY_PM_BASE + 0x0008)
+/*
+ * PM Wakeup Enable Reg PM_PWER
+ */
+#define PM_PWER                 (PKUNITY_PM_BASE + 0x000C)
+/*
+ * PM GPIO Sleep Status Reg PM_PGSR
+ */
+#define PM_PGSR                 (PKUNITY_PM_BASE + 0x0010)
+/*
+ * PM Clock Gate Reg PM_PCGR
+ */
+#define PM_PCGR                 (PKUNITY_PM_BASE + 0x0014)
+/*
+ * PM SYS PLL Conf. Reg PM_PLLSYSCFG
+ */
+#define PM_PLLSYSCFG            (PKUNITY_PM_BASE + 0x0018)
+/*
+ * PM DDR PLL Conf. Reg PM_PLLDDRCFG
+ */
+#define PM_PLLDDRCFG            (PKUNITY_PM_BASE + 0x001C)
+/*
+ * PM VGA PLL Conf. Reg PM_PLLVGACFG
+ */
+#define PM_PLLVGACFG            (PKUNITY_PM_BASE + 0x0020)
+/*
+ * PM Div Conf. Reg PM_DIVCFG
+ */
+#define PM_DIVCFG               (PKUNITY_PM_BASE + 0x0024)
+/*
+ * PM SYS PLL Status Reg PM_PLLSYSSTATUS
+ */
+#define PM_PLLSYSSTATUS         (PKUNITY_PM_BASE + 0x0028)
+/*
+ * PM DDR PLL Status Reg PM_PLLDDRSTATUS
+ */
+#define PM_PLLDDRSTATUS         (PKUNITY_PM_BASE + 0x002C)
+/*
+ * PM VGA PLL Status Reg PM_PLLVGASTATUS
+ */
+#define PM_PLLVGASTATUS         (PKUNITY_PM_BASE + 0x0030)
+/*
+ * PM Div Status Reg PM_DIVSTATUS
+ */
+#define PM_DIVSTATUS            (PKUNITY_PM_BASE + 0x0034)
+/*
+ * PM Software Reset Reg PM_SWRESET
+ */
+#define PM_SWRESET              (PKUNITY_PM_BASE + 0x0038)
+/*
+ * PM DDR2 PAD Start Reg PM_DDR2START
+ */
+#define PM_DDR2START            (PKUNITY_PM_BASE + 0x003C)
+/*
+ * PM DDR2 PAD Status Reg PM_DDR2CAL0
+ */
+#define PM_DDR2CAL0             (PKUNITY_PM_BASE + 0x0040)
+/*
+ * PM PLL DFC Done Reg PM_PLLDFCDONE
+ */
+#define PM_PLLDFCDONE           (PKUNITY_PM_BASE + 0x0044)
+
+#define PM_PMCR_SFB             FIELD(1, 1, 0)
+#define PM_PMCR_IFB             FIELD(1, 1, 1)
+#define PM_PMCR_CFBSYS          FIELD(1, 1, 2)
+#define PM_PMCR_CFBDDR          FIELD(1, 1, 3)
+#define PM_PMCR_CFBVGA          FIELD(1, 1, 4)
+#define PM_PMCR_CFBDIVBCLK      FIELD(1, 1, 5)
+
+/*
+ * GPIO 8~27 wake-up enable PM_PWER_GPIOHIGH
+ */
+#define PM_PWER_GPIOHIGH        FIELD(1, 1, 8)
+/*
+ * RTC alarm wake-up enable PM_PWER_RTC
+ */
+#define PM_PWER_RTC             FIELD(1, 1, 31)
+
+#define PM_PCGR_BCLK64DDR	FIELD(1, 1, 0)
+#define PM_PCGR_BCLK64VGA	FIELD(1, 1, 1)
+#define PM_PCGR_BCLKDDR		FIELD(1, 1, 2)
+#define PM_PCGR_BCLKPCI		FIELD(1, 1, 4)
+#define PM_PCGR_BCLKDMAC	FIELD(1, 1, 5)
+#define PM_PCGR_BCLKUMAL	FIELD(1, 1, 6)
+#define PM_PCGR_BCLKUSB		FIELD(1, 1, 7)
+#define PM_PCGR_BCLKMME		FIELD(1, 1, 10)
+#define PM_PCGR_BCLKNAND	FIELD(1, 1, 11)
+#define PM_PCGR_BCLKH264E	FIELD(1, 1, 12)
+#define PM_PCGR_BCLKVGA		FIELD(1, 1, 13)
+#define PM_PCGR_BCLKH264D	FIELD(1, 1, 14)
+#define PM_PCGR_VECLK		FIELD(1, 1, 15)
+#define PM_PCGR_HECLK		FIELD(1, 1, 16)
+#define PM_PCGR_HDCLK		FIELD(1, 1, 17)
+#define PM_PCGR_NANDCLK		FIELD(1, 1, 18)
+#define PM_PCGR_GECLK		FIELD(1, 1, 19)
+#define PM_PCGR_VGACLK          FIELD(1, 1, 20)
+#define PM_PCGR_PCICLK		FIELD(1, 1, 21)
+#define PM_PCGR_SATACLK		FIELD(1, 1, 25)
+
+/*
+ * [23:20]PM_DIVCFG_VGACLK(v)
+ */
+#define PM_DIVCFG_VGACLK_MASK   FMASK(4, 20)
+#define PM_DIVCFG_VGACLK(v)	FIELD((v), 4, 20)
+
+#define PM_SWRESET_USB          FIELD(1, 1, 6)
+#define PM_SWRESET_VGADIV       FIELD(1, 1, 26)
+#define PM_SWRESET_GEDIV        FIELD(1, 1, 27)
+
+#define PM_PLLDFCDONE_SYSDFC    FIELD(1, 1, 0)
+#define PM_PLLDFCDONE_DDRDFC    FIELD(1, 1, 1)
+#define PM_PLLDFCDONE_VGADFC    FIELD(1, 1, 2)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-ps2.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-ps2.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-ps2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-ps2.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+/*
+ * PKUnity PS2 Controller Registers
+ */
+/*
+ * the same as I8042_DATA_REG PS2_DATA
+ */
+#define PS2_DATA	(PKUNITY_PS2_BASE + 0x0060)
+/*
+ * the same as I8042_COMMAND_REG PS2_COMMAND
+ */
+#define PS2_COMMAND	(PKUNITY_PS2_BASE + 0x0064)
+/*
+ * the same as I8042_STATUS_REG PS2_STATUS
+ */
+#define PS2_STATUS	(PKUNITY_PS2_BASE + 0x0064)
+/*
+ * counter reg PS2_CNT
+ */
+#define PS2_CNT		(PKUNITY_PS2_BASE + 0x0068)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-resetc.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-resetc.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-resetc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-resetc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * PKUnity Reset Controller (RC) Registers
+ */
+/*
+ * Software Reset Register
+ */
+#define RESETC_SWRR	(PKUNITY_RESETC_BASE + 0x0000)
+/*
+ * Reset Status Register
+ */
+#define RESETC_RSSR	(PKUNITY_RESETC_BASE + 0x0004)
+
+/*
+ * Software Reset Bit
+ */
+#define RESETC_SWRR_SRB		FIELD(1, 1, 0)
+
+/*
+ * Hardware Reset
+ */
+#define RESETC_RSSR_HWR		FIELD(1, 1, 0)
+/*
+ * Software Reset
+ */
+#define RESETC_RSSR_SWR		FIELD(1, 1, 1)
+/*
+ * Watchdog Reset
+ */
+#define RESETC_RSSR_WDR		FIELD(1, 1, 2)
+/*
+ * Sleep Mode Reset
+ */
+#define RESETC_RSSR_SMR		FIELD(1, 1, 3)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-rtc.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-rtc.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-rtc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-rtc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ * PKUnity Real-Time Clock (RTC) control registers
+ */
+/*
+ * RTC Alarm Reg RTC_RTAR
+ */
+#define RTC_RTAR	(PKUNITY_RTC_BASE + 0x0000)
+/*
+ * RTC Count Reg RTC_RCNR
+ */
+#define RTC_RCNR	(PKUNITY_RTC_BASE + 0x0004)
+/*
+ * RTC Trim Reg RTC_RTTR
+ */
+#define RTC_RTTR	(PKUNITY_RTC_BASE + 0x0008)
+/*
+ * RTC Status Reg RTC_RTSR
+ */
+#define RTC_RTSR	(PKUNITY_RTC_BASE + 0x0010)
+
+/*
+ * ALarm detected RTC_RTSR_AL
+ */
+#define RTC_RTSR_AL		FIELD(1, 1, 0)
+/*
+ * 1 Hz clock detected RTC_RTSR_HZ
+ */
+#define RTC_RTSR_HZ		FIELD(1, 1, 1)
+/*
+ * ALarm interrupt Enable RTC_RTSR_ALE
+ */
+#define RTC_RTSR_ALE		FIELD(1, 1, 2)
+/*
+ * 1 Hz clock interrupt Enable RTC_RTSR_HZE
+ */
+#define RTC_RTSR_HZE		FIELD(1, 1, 3)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-sdc.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-sdc.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-sdc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-sdc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,156 @@
+/*
+ * PKUnity Multi-Media Card and Security Digital Card (MMC/SD) Registers
+ */
+/*
+ * Clock Control Reg SDC_CCR
+ */
+#define SDC_CCR		(PKUNITY_SDC_BASE + 0x0000)
+/*
+ * Software Reset Reg SDC_SRR
+ */
+#define SDC_SRR		(PKUNITY_SDC_BASE + 0x0004)
+/*
+ * Argument Reg SDC_ARGUMENT
+ */
+#define SDC_ARGUMENT	(PKUNITY_SDC_BASE + 0x0008)
+/*
+ * Command Reg SDC_COMMAND
+ */
+#define SDC_COMMAND	(PKUNITY_SDC_BASE + 0x000C)
+/*
+ * Block Size Reg SDC_BLOCKSIZE
+ */
+#define SDC_BLOCKSIZE	(PKUNITY_SDC_BASE + 0x0010)
+/*
+ * Block Cound Reg SDC_BLOCKCOUNT
+ */
+#define SDC_BLOCKCOUNT	(PKUNITY_SDC_BASE + 0x0014)
+/*
+ * Transfer Mode Reg SDC_TMR
+ */
+#define SDC_TMR		(PKUNITY_SDC_BASE + 0x0018)
+/*
+ * Response Reg. 0 SDC_RES0
+ */
+#define SDC_RES0	(PKUNITY_SDC_BASE + 0x001C)
+/*
+ * Response Reg. 1 SDC_RES1
+ */
+#define SDC_RES1	(PKUNITY_SDC_BASE + 0x0020)
+/*
+ * Response Reg. 2 SDC_RES2
+ */
+#define SDC_RES2	(PKUNITY_SDC_BASE + 0x0024)
+/*
+ * Response Reg. 3 SDC_RES3
+ */
+#define SDC_RES3	(PKUNITY_SDC_BASE + 0x0028)
+/*
+ * Read Timeout Control Reg SDC_RTCR
+ */
+#define SDC_RTCR	(PKUNITY_SDC_BASE + 0x002C)
+/*
+ * Interrupt Status Reg SDC_ISR
+ */
+#define SDC_ISR		(PKUNITY_SDC_BASE + 0x0030)
+/*
+ * Interrupt Status Mask Reg SDC_ISMR
+ */
+#define SDC_ISMR	(PKUNITY_SDC_BASE + 0x0034)
+/*
+ * RX FIFO SDC_RXFIFO
+ */
+#define SDC_RXFIFO	(PKUNITY_SDC_BASE + 0x0038)
+/*
+ * TX FIFO SDC_TXFIFO
+ */
+#define SDC_TXFIFO	(PKUNITY_SDC_BASE + 0x003C)
+
+/*
+ * SD Clock Enable SDC_CCR_CLKEN
+ */
+#define SDC_CCR_CLKEN			FIELD(1, 1, 2)
+/*
+ * [15:8] SDC_CCR_PDIV(v)
+ */
+#define SDC_CCR_PDIV(v)			FIELD((v), 8, 8)
+
+/*
+ * Software reset enable SDC_SRR_ENABLE
+ */
+#define SDC_SRR_ENABLE			FIELD(0, 1, 0)
+/*
+ * Software reset disable SDC_SRR_DISABLE
+ */
+#define SDC_SRR_DISABLE			FIELD(1, 1, 0)
+
+/*
+ * Response type SDC_COMMAND_RESTYPE_MASK
+ */
+#define SDC_COMMAND_RESTYPE_MASK	FMASK(2, 0)
+/*
+ * No response SDC_COMMAND_RESTYPE_NONE
+ */
+#define SDC_COMMAND_RESTYPE_NONE	FIELD(0, 2, 0)
+/*
+ * 136-bit long response SDC_COMMAND_RESTYPE_LONG
+ */
+#define SDC_COMMAND_RESTYPE_LONG	FIELD(1, 2, 0)
+/*
+ * 48-bit short response SDC_COMMAND_RESTYPE_SHORT
+ */
+#define SDC_COMMAND_RESTYPE_SHORT	FIELD(2, 2, 0)
+/*
+ * 48-bit short and test if busy response SDC_COMMAND_RESTYPE_SHORTBUSY
+ */
+#define SDC_COMMAND_RESTYPE_SHORTBUSY	FIELD(3, 2, 0)
+/*
+ * data ready SDC_COMMAND_DATAREADY
+ */
+#define SDC_COMMAND_DATAREADY		FIELD(1, 1, 2)
+#define SDC_COMMAND_CMDEN		FIELD(1, 1, 3)
+/*
+ * [10:5] SDC_COMMAND_CMDINDEX(v)
+ */
+#define SDC_COMMAND_CMDINDEX(v)		FIELD((v), 6, 5)
+
+/*
+ * [10:0] SDC_BLOCKSIZE_BSMASK(v)
+ */
+#define SDC_BLOCKSIZE_BSMASK(v)		FIELD((v), 11, 0)
+/*
+ * [11:0] SDC_BLOCKCOUNT_BCMASK(v)
+ */
+#define SDC_BLOCKCOUNT_BCMASK(v)	FIELD((v), 12, 0)
+
+/*
+ * Data Width 1bit SDC_TMR_WTH_1BIT
+ */
+#define SDC_TMR_WTH_1BIT		FIELD(0, 1, 0)
+/*
+ * Data Width 4bit SDC_TMR_WTH_4BIT
+ */
+#define SDC_TMR_WTH_4BIT		FIELD(1, 1, 0)
+/*
+ * Read SDC_TMR_DIR_READ
+ */
+#define SDC_TMR_DIR_READ		FIELD(0, 1, 1)
+/*
+ * Write SDC_TMR_DIR_WRITE
+ */
+#define SDC_TMR_DIR_WRITE		FIELD(1, 1, 1)
+
+#define SDC_IR_MASK			FMASK(13, 0)
+#define SDC_IR_RESTIMEOUT		FIELD(1, 1, 0)
+#define SDC_IR_WRITECRC			FIELD(1, 1, 1)
+#define SDC_IR_READCRC			FIELD(1, 1, 2)
+#define SDC_IR_TXFIFOREAD		FIELD(1, 1, 3)
+#define SDC_IR_RXFIFOWRITE		FIELD(1, 1, 4)
+#define SDC_IR_READTIMEOUT		FIELD(1, 1, 5)
+#define SDC_IR_DATACOMPLETE		FIELD(1, 1, 6)
+#define SDC_IR_CMDCOMPLETE		FIELD(1, 1, 7)
+#define SDC_IR_RXFIFOFULL		FIELD(1, 1, 8)
+#define SDC_IR_RXFIFOEMPTY		FIELD(1, 1, 9)
+#define SDC_IR_TXFIFOFULL		FIELD(1, 1, 10)
+#define SDC_IR_TXFIFOEMPTY		FIELD(1, 1, 11)
+#define SDC_IR_ENDCMDWITHRES		FIELD(1, 1, 12)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-spi.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-spi.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-spi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-spi.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * PKUnity Serial Peripheral Interface (SPI) Registers
+ */
+/*
+ * Control reg. 0 SPI_CR0
+ */
+#define SPI_CR0		(PKUNITY_SPI_BASE + 0x0000)
+/*
+ * Control reg. 1 SPI_CR1
+ */
+#define SPI_CR1		(PKUNITY_SPI_BASE + 0x0004)
+/*
+ * Enable reg SPI_SSIENR
+ */
+#define SPI_SSIENR	(PKUNITY_SPI_BASE + 0x0008)
+/*
+ * Status reg SPI_SR
+ */
+#define SPI_SR		(PKUNITY_SPI_BASE + 0x0028)
+/*
+ * Interrupt Mask reg SPI_IMR
+ */
+#define SPI_IMR		(PKUNITY_SPI_BASE + 0x002C)
+/*
+ * Interrupt Status reg SPI_ISR
+ */
+#define SPI_ISR		(PKUNITY_SPI_BASE + 0x0030)
+
+/*
+ * Enable SPI Controller SPI_SSIENR_EN
+ */
+#define SPI_SSIENR_EN		FIELD(1, 1, 0)
+
+/*
+ * SPI Busy SPI_SR_BUSY
+ */
+#define SPI_SR_BUSY		FIELD(1, 1, 0)
+/*
+ * Transmit FIFO Not Full SPI_SR_TFNF
+ */
+#define SPI_SR_TFNF		FIELD(1, 1, 1)
+/*
+ * Transmit FIFO Empty SPI_SR_TFE
+ */
+#define SPI_SR_TFE		FIELD(1, 1, 2)
+/*
+ * Receive FIFO Not Empty SPI_SR_RFNE
+ */
+#define SPI_SR_RFNE		FIELD(1, 1, 3)
+/*
+ * Receive FIFO Full SPI_SR_RFF
+ */
+#define SPI_SR_RFF		FIELD(1, 1, 4)
+
+/*
+ * Trans. FIFO Empty Interrupt Status SPI_ISR_TXEIS
+ */
+#define SPI_ISR_TXEIS		FIELD(1, 1, 0)
+/*
+ * Trans. FIFO Overflow Interrupt Status SPI_ISR_TXOIS
+ */
+#define SPI_ISR_TXOIS		FIELD(1, 1, 1)
+/*
+ * Receiv. FIFO Underflow Interrupt Status SPI_ISR_RXUIS
+ */
+#define SPI_ISR_RXUIS		FIELD(1, 1, 2)
+/*
+ * Receiv. FIFO Overflow Interrupt Status SPI_ISR_RXOIS
+ */
+#define SPI_ISR_RXOIS		FIELD(1, 1, 3)
+/*
+ * Receiv. FIFO Full Interrupt Status SPI_ISR_RXFIS
+ */
+#define SPI_ISR_RXFIS		FIELD(1, 1, 4)
+#define SPI_ISR_MSTIS		FIELD(1, 1, 5)
+
+/*
+ * Trans. FIFO Empty Interrupt Mask SPI_IMR_TXEIM
+ */
+#define SPI_IMR_TXEIM		FIELD(1, 1, 0)
+/*
+ * Trans. FIFO Overflow Interrupt Mask SPI_IMR_TXOIM
+ */
+#define SPI_IMR_TXOIM		FIELD(1, 1, 1)
+/*
+ * Receiv. FIFO Underflow Interrupt Mask SPI_IMR_RXUIM
+ */
+#define SPI_IMR_RXUIM		FIELD(1, 1, 2)
+/*
+ * Receiv. FIFO Overflow Interrupt Mask SPI_IMR_RXOIM
+ */
+#define SPI_IMR_RXOIM		FIELD(1, 1, 3)
+/*
+ * Receiv. FIFO Full Interrupt Mask SPI_IMR_RXFIM
+ */
+#define SPI_IMR_RXFIM		FIELD(1, 1, 4)
+#define SPI_IMR_MSTIM		FIELD(1, 1, 5)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-uart.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-uart.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-uart.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-uart.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3 @@
+/*
+ * PKUnity Universal Asynchronous Receiver/Transmitter (UART) Registers
+ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-umal.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-umal.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-umal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-umal.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,229 @@
+/*
+ * PKUnity Ultra Media Access Layer (UMAL) Ethernet MAC Registers
+ */
+
+/* MAC module of UMAL */
+/* UMAL's MAC module includes G/MII interface, several additional PHY
+ * interfaces, and MAC control sub-layer, which provides support for control
+ * frames (e.g. PAUSE frames).
+ */
+/*
+ * TX/RX reset and control UMAL_CFG1
+ */
+#define UMAL_CFG1		(PKUNITY_UMAL_BASE + 0x0000)
+/*
+ * MAC interface mode control UMAL_CFG2
+ */
+#define UMAL_CFG2		(PKUNITY_UMAL_BASE + 0x0004)
+/*
+ * Inter Packet/Frame Gap UMAL_IPGIFG
+ */
+#define UMAL_IPGIFG		(PKUNITY_UMAL_BASE + 0x0008)
+/*
+ * Collision retry or backoff UMAL_HALFDUPLEX
+ */
+#define UMAL_HALFDUPLEX		(PKUNITY_UMAL_BASE + 0x000c)
+/*
+ * Maximum Frame Length UMAL_MAXFRAME
+ */
+#define UMAL_MAXFRAME		(PKUNITY_UMAL_BASE + 0x0010)
+/*
+ * Test Regsiter UMAL_TESTREG
+ */
+#define UMAL_TESTREG		(PKUNITY_UMAL_BASE + 0x001c)
+/*
+ * MII Management Configure UMAL_MIICFG
+ */
+#define UMAL_MIICFG		(PKUNITY_UMAL_BASE + 0x0020)
+/*
+ * MII Management Command UMAL_MIICMD
+ */
+#define UMAL_MIICMD		(PKUNITY_UMAL_BASE + 0x0024)
+/*
+ * MII Management Address UMAL_MIIADDR
+ */
+#define UMAL_MIIADDR		(PKUNITY_UMAL_BASE + 0x0028)
+/*
+ * MII Management Control UMAL_MIICTRL
+ */
+#define UMAL_MIICTRL		(PKUNITY_UMAL_BASE + 0x002c)
+/*
+ * MII Management Status UMAL_MIISTATUS
+ */
+#define UMAL_MIISTATUS		(PKUNITY_UMAL_BASE + 0x0030)
+/*
+ * MII Management Indicator UMAL_MIIIDCT
+ */
+#define UMAL_MIIIDCT		(PKUNITY_UMAL_BASE + 0x0034)
+/*
+ * Interface Control UMAL_IFCTRL
+ */
+#define UMAL_IFCTRL		(PKUNITY_UMAL_BASE + 0x0038)
+/*
+ * Interface Status UMAL_IFSTATUS
+ */
+#define UMAL_IFSTATUS		(PKUNITY_UMAL_BASE + 0x003c)
+/*
+ * MAC address (high 4 bytes) UMAL_STADDR1
+ */
+#define UMAL_STADDR1		(PKUNITY_UMAL_BASE + 0x0040)
+/*
+ * MAC address (low 2 bytes) UMAL_STADDR2
+ */
+#define UMAL_STADDR2		(PKUNITY_UMAL_BASE + 0x0044)
+
+/* FIFO MODULE OF UMAL */
+/* UMAL's FIFO module provides data queuing for increased system level
+ * throughput
+ */
+#define UMAL_FIFOCFG0		(PKUNITY_UMAL_BASE + 0x0048)
+#define UMAL_FIFOCFG1		(PKUNITY_UMAL_BASE + 0x004c)
+#define UMAL_FIFOCFG2		(PKUNITY_UMAL_BASE + 0x0050)
+#define UMAL_FIFOCFG3		(PKUNITY_UMAL_BASE + 0x0054)
+#define UMAL_FIFOCFG4		(PKUNITY_UMAL_BASE + 0x0058)
+#define UMAL_FIFOCFG5		(PKUNITY_UMAL_BASE + 0x005c)
+#define UMAL_FIFORAM0		(PKUNITY_UMAL_BASE + 0x0060)
+#define UMAL_FIFORAM1		(PKUNITY_UMAL_BASE + 0x0064)
+#define UMAL_FIFORAM2		(PKUNITY_UMAL_BASE + 0x0068)
+#define UMAL_FIFORAM3		(PKUNITY_UMAL_BASE + 0x006c)
+#define UMAL_FIFORAM4		(PKUNITY_UMAL_BASE + 0x0070)
+#define UMAL_FIFORAM5		(PKUNITY_UMAL_BASE + 0x0074)
+#define UMAL_FIFORAM6		(PKUNITY_UMAL_BASE + 0x0078)
+#define UMAL_FIFORAM7		(PKUNITY_UMAL_BASE + 0x007c)
+
+/* MAHBE MODULE OF UMAL */
+/* UMAL's MAHBE module interfaces to the host system through 32-bit AHB Master
+ * and Slave ports.Registers within the M-AHBE provide Control and Status
+ * information concerning these transfers.
+ */
+/*
+ * Transmit Control UMAL_DMATxCtrl
+ */
+#define UMAL_DMATxCtrl		(PKUNITY_UMAL_BASE + 0x0180)
+/*
+ * Pointer to TX Descripter UMAL_DMATxDescriptor
+ */
+#define UMAL_DMATxDescriptor	(PKUNITY_UMAL_BASE + 0x0184)
+/*
+ * Status of Tx Packet Transfers UMAL_DMATxStatus
+ */
+#define UMAL_DMATxStatus	(PKUNITY_UMAL_BASE + 0x0188)
+/*
+ * Receive Control UMAL_DMARxCtrl
+ */
+#define UMAL_DMARxCtrl		(PKUNITY_UMAL_BASE + 0x018c)
+/*
+ * Pointer to Rx Descriptor UMAL_DMARxDescriptor
+ */
+#define UMAL_DMARxDescriptor	(PKUNITY_UMAL_BASE + 0x0190)
+/*
+ * Status of Rx Packet Transfers UMAL_DMARxStatus
+ */
+#define UMAL_DMARxStatus	(PKUNITY_UMAL_BASE + 0x0194)
+/*
+ * Interrupt Mask UMAL_DMAIntrMask
+ */
+#define UMAL_DMAIntrMask	(PKUNITY_UMAL_BASE + 0x0198)
+/*
+ * Interrupts, read only UMAL_DMAInterrupt
+ */
+#define UMAL_DMAInterrupt	(PKUNITY_UMAL_BASE + 0x019c)
+
+/*
+ * Commands for UMAL_CFG1 register
+ */
+#define UMAL_CFG1_TXENABLE	FIELD(1, 1, 0)
+#define UMAL_CFG1_RXENABLE	FIELD(1, 1, 2)
+#define UMAL_CFG1_TXFLOWCTL	FIELD(1, 1, 4)
+#define UMAL_CFG1_RXFLOWCTL	FIELD(1, 1, 5)
+#define UMAL_CFG1_CONFLPBK	FIELD(1, 1, 8)
+#define UMAL_CFG1_RESET		FIELD(1, 1, 31)
+#define UMAL_CFG1_CONFFLCTL	(MAC_TX_FLOW_CTL | MAC_RX_FLOW_CTL)
+
+/*
+ * Commands for UMAL_CFG2 register
+ */
+#define UMAL_CFG2_FULLDUPLEX	FIELD(1, 1, 0)
+#define UMAL_CFG2_CRCENABLE	FIELD(1, 1, 1)
+#define UMAL_CFG2_PADCRC	FIELD(1, 1, 2)
+#define UMAL_CFG2_LENGTHCHECK	FIELD(1, 1, 4)
+#define UMAL_CFG2_MODEMASK	FMASK(2, 8)
+#define UMAL_CFG2_NIBBLEMODE	FIELD(1, 2, 8)
+#define UMAL_CFG2_BYTEMODE	FIELD(2, 2, 8)
+#define UMAL_CFG2_PREAMBLENMASK	FMASK(4, 12)
+#define UMAL_CFG2_DEFPREAMBLEN	FIELD(7, 4, 12)
+#define UMAL_CFG2_FD100		(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
+				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+				| UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
+#define UMAL_CFG2_FD1000	(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_BYTEMODE \
+				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+				| UMAL_CFG2_CRCENABLE | UMAL_CFG2_FULLDUPLEX)
+#define UMAL_CFG2_HD100		(UMAL_CFG2_DEFPREAMBLEN | UMAL_CFG2_NIBBLEMODE \
+				| UMAL_CFG2_LENGTHCHECK | UMAL_CFG2_PADCRC \
+				| UMAL_CFG2_CRCENABLE)
+
+/*
+ * Command for UMAL_IFCTRL register
+ */
+#define UMAL_IFCTRL_RESET	FIELD(1, 1, 31)
+
+/*
+ * Command for UMAL_MIICFG register
+ */
+#define UMAL_MIICFG_RESET	FIELD(1, 1, 31)
+
+/*
+ * Command for UMAL_MIICMD register
+ */
+#define UMAL_MIICMD_READ	FIELD(1, 1, 0)
+
+/*
+ * Command for UMAL_MIIIDCT register
+ */
+#define UMAL_MIIIDCT_BUSY	FIELD(1, 1, 0)
+#define UMAL_MIIIDCT_NOTVALID	FIELD(1, 1, 2)
+
+/*
+ * Commands for DMATxCtrl regesters
+ */
+#define UMAL_DMA_Enable		FIELD(1, 1, 0)
+
+/*
+ * Commands for DMARxCtrl regesters
+ */
+#define UMAL_DMAIntrMask_ENABLEHALFWORD	FIELD(1, 1, 16)
+
+/*
+ * Command for DMARxStatus
+ */
+#define CLR_RX_BUS_ERR		FIELD(1, 1, 3)
+#define CLR_RX_OVERFLOW		FIELD(1, 1, 2)
+#define CLR_RX_PKT		FIELD(1, 1, 0)
+
+/*
+ * Command for DMATxStatus
+ */
+#define CLR_TX_BUS_ERR		FIELD(1, 1, 3)
+#define CLR_TX_UNDERRUN		FIELD(1, 1, 1)
+#define CLR_TX_PKT		FIELD(1, 1, 0)
+
+/*
+ * Commands for DMAIntrMask and DMAInterrupt register
+ */
+#define INT_RX_MASK		FIELD(0xd, 4, 4)
+#define INT_TX_MASK		FIELD(0xb, 4, 0)
+
+#define INT_RX_BUS_ERR		FIELD(1, 1, 7)
+#define INT_RX_OVERFLOW		FIELD(1, 1, 6)
+#define INT_RX_PKT		FIELD(1, 1, 4)
+#define INT_TX_BUS_ERR		FIELD(1, 1, 3)
+#define INT_TX_UNDERRUN		FIELD(1, 1, 1)
+#define INT_TX_PKT		FIELD(1, 1, 0)
+
+/*
+ * MARCOS of UMAL's descriptors
+ */
+#define UMAL_DESC_PACKETSIZE_EMPTY	FIELD(1, 1, 31)
+#define UMAL_DESC_PACKETSIZE_NONEMPTY	FIELD(0, 1, 31)
+#define UMAL_DESC_PACKETSIZE_SIZEMASK	FMASK(12, 0)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-unigfx.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-unigfx.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/regs-unigfx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/regs-unigfx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,200 @@
+/*
+ * PKUnity UNIGFX Registers
+ */
+
+#define UDE_BASE      (PKUNITY_UNIGFX_BASE + 0x1400)
+#define UGE_BASE      (PKUNITY_UNIGFX_BASE + 0x0000)
+
+/*
+ * command reg for UNIGFX DE
+ */
+/*
+ * control reg UDE_CFG
+ */
+#define UDE_CFG       (UDE_BASE + 0x0000)
+/*
+ * framebuffer start address reg UDE_FSA
+ */
+#define UDE_FSA       (UDE_BASE + 0x0004)
+/*
+ * line size reg UDE_LS
+ */
+#define UDE_LS        (UDE_BASE + 0x0008)
+/*
+ * pitch size reg UDE_PS
+ */
+#define UDE_PS        (UDE_BASE + 0x000C)
+/*
+ * horizontal active time reg UDE_HAT
+ */
+#define UDE_HAT       (UDE_BASE + 0x0010)
+/*
+ * horizontal blank time reg UDE_HBT
+ */
+#define UDE_HBT       (UDE_BASE + 0x0014)
+/*
+ * horizontal sync time reg UDE_HST
+ */
+#define UDE_HST       (UDE_BASE + 0x0018)
+/*
+ * vertival active time reg UDE_VAT
+ */
+#define UDE_VAT       (UDE_BASE + 0x001C)
+/*
+ * vertival blank time reg UDE_VBT
+ */
+#define UDE_VBT       (UDE_BASE + 0x0020)
+/*
+ * vertival sync time reg UDE_VST
+ */
+#define UDE_VST       (UDE_BASE + 0x0024)
+/*
+ * cursor position UDE_CXY
+ */
+#define UDE_CXY       (UDE_BASE + 0x0028)
+/*
+ * cursor front color UDE_CC0
+ */
+#define UDE_CC0       (UDE_BASE + 0x002C)
+/*
+ * cursor background color UDE_CC1
+ */
+#define UDE_CC1       (UDE_BASE + 0x0030)
+/*
+ * video position UDE_VXY
+ */
+#define UDE_VXY       (UDE_BASE + 0x0034)
+/*
+ * video start address reg UDE_VSA
+ */
+#define UDE_VSA       (UDE_BASE + 0x0040)
+/*
+ * video size reg UDE_VS
+ */
+#define UDE_VS        (UDE_BASE + 0x004C)
+
+/*
+ * command reg for UNIGFX GE
+ */
+/*
+ * src xy reg UGE_SRCXY
+ */
+#define UGE_SRCXY     (UGE_BASE + 0x0000)
+/*
+ * dst xy reg UGE_DSTXY
+ */
+#define UGE_DSTXY     (UGE_BASE + 0x0004)
+/*
+ * pitch reg UGE_PITCH
+ */
+#define UGE_PITCH     (UGE_BASE + 0x0008)
+/*
+ * src start reg UGE_SRCSTART
+ */
+#define UGE_SRCSTART  (UGE_BASE + 0x000C)
+/*
+ * dst start reg UGE_DSTSTART
+ */
+#define UGE_DSTSTART  (UGE_BASE + 0x0010)
+/*
+ * width height reg UGE_WIDHEIGHT
+ */
+#define UGE_WIDHEIGHT (UGE_BASE + 0x0014)
+/*
+ * rop alpah reg UGE_ROPALPHA
+ */
+#define UGE_ROPALPHA  (UGE_BASE + 0x0018)
+/*
+ * front color UGE_FCOLOR
+ */
+#define UGE_FCOLOR    (UGE_BASE + 0x001C)
+/*
+ * background color UGE_BCOLOR
+ */
+#define UGE_BCOLOR    (UGE_BASE + 0x0020)
+/*
+ * src color key for high value UGE_SCH
+ */
+#define UGE_SCH       (UGE_BASE + 0x0024)
+/*
+ * dst color key for high value UGE_DCH
+ */
+#define UGE_DCH       (UGE_BASE + 0x0028)
+/*
+ * src color key for low value UGE_SCL
+ */
+#define UGE_SCL       (UGE_BASE + 0x002C)
+/*
+ * dst color key for low value UGE_DCL
+ */
+#define UGE_DCL       (UGE_BASE + 0x0030)
+/*
+ * clip 0 reg UGE_CLIP0
+ */
+#define UGE_CLIP0     (UGE_BASE + 0x0034)
+/*
+ * clip 1 reg UGE_CLIP1
+ */
+#define UGE_CLIP1     (UGE_BASE + 0x0038)
+/*
+ * command reg UGE_COMMAND
+ */
+#define UGE_COMMAND   (UGE_BASE + 0x003C)
+/*
+ * pattern 0 UGE_P0
+ */
+#define UGE_P0        (UGE_BASE + 0x0040)
+#define UGE_P1        (UGE_BASE + 0x0044)
+#define UGE_P2        (UGE_BASE + 0x0048)
+#define UGE_P3        (UGE_BASE + 0x004C)
+#define UGE_P4        (UGE_BASE + 0x0050)
+#define UGE_P5        (UGE_BASE + 0x0054)
+#define UGE_P6        (UGE_BASE + 0x0058)
+#define UGE_P7        (UGE_BASE + 0x005C)
+#define UGE_P8        (UGE_BASE + 0x0060)
+#define UGE_P9        (UGE_BASE + 0x0064)
+#define UGE_P10       (UGE_BASE + 0x0068)
+#define UGE_P11       (UGE_BASE + 0x006C)
+#define UGE_P12       (UGE_BASE + 0x0070)
+#define UGE_P13       (UGE_BASE + 0x0074)
+#define UGE_P14       (UGE_BASE + 0x0078)
+#define UGE_P15       (UGE_BASE + 0x007C)
+#define UGE_P16       (UGE_BASE + 0x0080)
+#define UGE_P17       (UGE_BASE + 0x0084)
+#define UGE_P18       (UGE_BASE + 0x0088)
+#define UGE_P19       (UGE_BASE + 0x008C)
+#define UGE_P20       (UGE_BASE + 0x0090)
+#define UGE_P21       (UGE_BASE + 0x0094)
+#define UGE_P22       (UGE_BASE + 0x0098)
+#define UGE_P23       (UGE_BASE + 0x009C)
+#define UGE_P24       (UGE_BASE + 0x00A0)
+#define UGE_P25       (UGE_BASE + 0x00A4)
+#define UGE_P26       (UGE_BASE + 0x00A8)
+#define UGE_P27       (UGE_BASE + 0x00AC)
+#define UGE_P28       (UGE_BASE + 0x00B0)
+#define UGE_P29       (UGE_BASE + 0x00B4)
+#define UGE_P30       (UGE_BASE + 0x00B8)
+#define UGE_P31       (UGE_BASE + 0x00BC)
+
+#define UDE_CFG_DST_MASK	FMASK(2, 8)
+#define UDE_CFG_DST8            FIELD(0x0, 2, 8)
+#define UDE_CFG_DST16           FIELD(0x1, 2, 8)
+#define UDE_CFG_DST24           FIELD(0x2, 2, 8)
+#define UDE_CFG_DST32           FIELD(0x3, 2, 8)
+
+/*
+ * GDEN enable UDE_CFG_GDEN_ENABLE
+ */
+#define UDE_CFG_GDEN_ENABLE     FIELD(1, 1, 3)
+/*
+ * VDEN enable UDE_CFG_VDEN_ENABLE
+ */
+#define UDE_CFG_VDEN_ENABLE     FIELD(1, 1, 4)
+/*
+ * CDEN enable UDE_CFG_CDEN_ENABLE
+ */
+#define UDE_CFG_CDEN_ENABLE     FIELD(1, 1, 5)
+/*
+ * TIMEUP enable UDE_CFG_TIMEUP_ENABLE
+ */
+#define UDE_CFG_TIMEUP_ENABLE   FIELD(1, 1, 6)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/include/mach/uncompress.h linux-libre-2.6.39-gnu/arch/unicore32/include/mach/uncompress.h
--- linux-libre-2.6.38-gnu/arch/unicore32/include/mach/uncompress.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/include/mach/uncompress.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * linux/arch/unicore32/include/mach/uncompress.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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_PUV3_UNCOMPRESS_H__
+#define __MACH_PUV3_UNCOMPRESS_H__
+
+#include "hardware.h"
+#include "ocd.h"
+
+extern char input_data[];
+extern char input_data_end[];
+
+static void arch_decomp_puts(const char *ptr)
+{
+	char c;
+
+	while ((c = *ptr++) != '\0') {
+		if (c == '\n')
+			putc('\r');
+		putc(c);
+	}
+}
+#define ARCH_HAVE_DECOMP_PUTS
+
+#endif /* __MACH_PUV3_UNCOMPRESS_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/Kconfig linux-libre-2.6.39-gnu/arch/unicore32/Kconfig
--- linux-libre-2.6.38-gnu/arch/unicore32/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,275 @@
+config UNICORE32
+	def_bool y
+	select HAVE_MEMBLOCK
+	select HAVE_GENERIC_DMA_COHERENT
+	select HAVE_GENERIC_HARDIRQS
+	select HAVE_DMA_ATTRS
+	select HAVE_KERNEL_GZIP
+	select HAVE_KERNEL_BZIP2
+	select HAVE_KERNEL_LZO
+	select HAVE_KERNEL_LZMA
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_IRQ_PROBE
+	select GENERIC_IRQ_SHOW
+	select ARCH_WANT_FRAME_POINTERS
+	help
+	  UniCore-32 is 32-bit Instruction Set Architecture,
+	  including a series of low-power-consumption RISC chip
+	  designs licensed by PKUnity Ltd.
+	  Please see web page at <http://www.pkunity.com/>.
+
+config HAVE_PWM
+	bool
+
+config GENERIC_GPIO
+	def_bool y
+
+config GENERIC_CLOCKEVENTS
+	bool
+
+config GENERIC_CSUM
+	def_bool y
+
+config GENERIC_IOMAP
+	def_bool y
+
+config NO_IOPORT
+	bool
+
+config STACKTRACE_SUPPORT
+	def_bool y
+
+config HAVE_LATENCYTOP_SUPPORT
+	def_bool y
+
+config LOCKDEP_SUPPORT
+	def_bool y
+
+config RWSEM_GENERIC_SPINLOCK
+	def_bool y
+
+config RWSEM_XCHGADD_ALGORITHM
+	bool
+
+config ARCH_HAS_ILOG2_U32
+	bool
+
+config ARCH_HAS_ILOG2_U64
+	bool
+
+config ARCH_HAS_CPUFREQ
+	bool
+
+config GENERIC_HWEIGHT
+	def_bool y
+
+config GENERIC_CALIBRATE_DELAY
+	def_bool y
+
+config ARCH_MAY_HAVE_PC_FDC
+	bool
+
+config NEED_DMA_MAP_STATE
+       def_bool y
+
+source "init/Kconfig"
+
+source "kernel/Kconfig.freezer"
+
+menu "System Type"
+
+config MMU
+	def_bool y
+
+config ARCH_FPGA
+	bool
+
+config ARCH_PUV3
+	def_bool y
+	select CPU_UCV2
+	select GENERIC_CLOCKEVENTS
+	select HAVE_CLK
+	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_HAS_CPUFREQ
+
+# CONFIGs for ARCH_PUV3
+
+if ARCH_PUV3
+
+choice
+	prompt "Board Selection"
+	default PUV3_DB0913
+
+config PUV3_FPGA_DLX200
+	select ARCH_FPGA
+	bool "FPGA board"
+
+config PUV3_DB0913
+	bool "DEBUG board (0913)"
+
+config PUV3_NB0916
+	bool "NetBook board (0916)"
+	select HAVE_PWM
+
+config PUV3_SMW0919
+	bool "Security Mini-Workstation board (0919)"
+
+endchoice
+
+config PUV3_PM
+	def_bool y if !ARCH_FPGA
+
+endif
+
+source "arch/unicore32/mm/Kconfig"
+
+comment "Floating poing support"
+
+config UNICORE_FPU_F64
+	def_bool y if !ARCH_FPGA
+
+endmenu
+
+menu "Bus support"
+
+config PCI
+	bool "PCI Support"
+	help
+	  Find out whether you have a PCI motherboard. PCI is the name of a
+	  bus system, i.e. the way the CPU talks to the other stuff inside
+	  your box. Other bus systems are ISA, EISA, MicroChannel (MCA) or
+	  VESA. If you have PCI, say Y, otherwise N.
+
+source "drivers/pci/Kconfig"
+
+source "drivers/pcmcia/Kconfig"
+
+endmenu
+
+menu "Kernel Features"
+
+source "kernel/time/Kconfig"
+
+source "kernel/Kconfig.preempt"
+
+source "kernel/Kconfig.hz"
+
+source "mm/Kconfig"
+
+config LEDS
+	def_bool y
+	depends on GENERIC_GPIO
+
+config ALIGNMENT_TRAP
+	def_bool y
+	help
+	  Unicore processors can not fetch/store information which is not
+	  naturally aligned on the bus, i.e., a 4 byte fetch must start at an
+	  address divisible by 4. On 32-bit Unicore processors, these non-aligned
+	  fetch/store instructions will be emulated in software if you say
+	  here, which has a severe performance impact. This is necessary for
+	  correct operation of some network protocols. With an IP-only
+	  configuration it is safe to say N, otherwise say Y.
+
+endmenu
+
+menu "Boot options"
+
+config CMDLINE
+	string "Default kernel command string"
+	default ""
+
+config CMDLINE_FORCE
+	bool "Always use the default kernel command string"
+	depends on CMDLINE != ""
+	help
+	  Always use the default kernel command string, even if the boot
+	  loader passes other arguments to the kernel.
+	  This is useful if you cannot or don't want to change the
+	  command-line options your boot loader passes to the kernel.
+
+	  If unsure, say N.
+
+endmenu
+
+menu "Userspace binary formats"
+
+source "fs/Kconfig.binfmt"
+
+endmenu
+
+menu "Power management options"
+
+source "kernel/power/Kconfig"
+
+if ARCH_HAS_CPUFREQ
+source "drivers/cpufreq/Kconfig"
+endif
+
+config ARCH_SUSPEND_POSSIBLE
+	def_bool y if !ARCH_FPGA
+
+config ARCH_HIBERNATION_POSSIBLE
+	def_bool y if !ARCH_FPGA
+
+endmenu
+
+source "net/Kconfig"
+
+if ARCH_PUV3
+
+config PUV3_GPIO
+	bool
+	depends on !ARCH_FPGA
+	select GENERIC_GPIO
+	select GPIO_SYSFS if EXPERIMENTAL
+	default y
+
+config PUV3_PWM
+	tristate
+	default BACKLIGHT_PWM
+	help
+	  Enable support for NB0916 PWM controllers
+
+config PUV3_RTC
+	tristate "PKUnity v3 RTC Support"
+	depends on !ARCH_FPGA
+
+if PUV3_NB0916
+
+menu "PKUnity NetBook-0916 Features"
+
+config I2C_BATTERY_BQ27200
+	tristate "I2C Battery BQ27200 Support"
+	select PUV3_I2C
+	select POWER_SUPPLY
+	select BATTERY_BQ27x00
+
+config I2C_EEPROM_AT24
+	tristate "I2C EEPROMs AT24 support"
+	select PUV3_I2C
+	select MISC_DEVICES
+	select EEPROM_AT24
+
+config LCD_BACKLIGHT
+	tristate "LCD Backlight support"
+	select BACKLIGHT_LCD_SUPPORT
+	select BACKLIGHT_PWM
+
+endmenu
+
+endif
+
+endif
+
+source "drivers/Kconfig"
+
+source "fs/Kconfig"
+
+source "arch/unicore32/Kconfig.debug"
+
+source "security/Kconfig"
+
+source "crypto/Kconfig"
+
+source "lib/Kconfig"
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/Kconfig.debug linux-libre-2.6.39-gnu/arch/unicore32/Kconfig.debug
--- linux-libre-2.6.38-gnu/arch/unicore32/Kconfig.debug	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/Kconfig.debug	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,68 @@
+menu "Kernel hacking"
+
+source "lib/Kconfig.debug"
+
+config STRICT_DEVMEM
+	bool "Filter access to /dev/mem"
+	depends on MMU
+	---help---
+	  If this option is disabled, you allow userspace (root) access to all
+	  of memory, including kernel and userspace memory. Accidental
+	  access to this is obviously disastrous, but specific access can
+	  be used by people debugging the kernel.
+
+	  If this option is switched on, the /dev/mem file only allows
+	  userspace access to memory mapped peripherals.
+
+          If in doubt, say Y.
+
+config EARLY_PRINTK
+	def_bool DEBUG_OCD
+	help
+	  Write kernel log output directly into the ocd or to a serial port.
+
+	  This is useful for kernel debugging when your machine crashes very
+	  early before the console code is initialized. For normal operation
+	  it is not recommended because it looks ugly and doesn't cooperate
+	  with klogd/syslogd or the X server. You should normally N here,
+	  unless you want to debug such a crash.
+
+config DEBUG_STACK_USAGE
+	bool "Enable stack utilization instrumentation"
+	depends on DEBUG_KERNEL
+	help
+	  Enables the display of the minimum amount of free stack which each
+	  task has ever had available in the sysrq-T output.
+
+# These options are only for real kernel hackers who want to get their hands dirty.
+config DEBUG_LL
+	bool "Kernel low-level debugging functions"
+	depends on DEBUG_KERNEL
+	help
+	  Say Y here to include definitions of printascii, printch, printhex
+	  in the kernel.  This is helpful if you are debugging code that
+	  executes before the console is initialized.
+
+config DEBUG_OCD
+	bool "Kernel low-level debugging via On-Chip-Debugger"
+	depends on DEBUG_LL
+	default y
+	help
+	  Say Y here if you want the debug print routines to direct their
+	  output to the UniCore On-Chip-Debugger channel using CP #1.
+
+config DEBUG_OCD_BREAKPOINT
+	bool "Breakpoint support via On-Chip-Debugger"
+	depends on DEBUG_OCD
+
+config DEBUG_UART
+	int "Kernel low-level debugging messages via serial port"
+	depends on DEBUG_LL
+	range 0 1
+	default "0"
+	help
+	  Choice for UART for kernel low-level using PKUnity UARTS,
+	  should be between zero and one. The port must have been
+	  initialised by the boot-loader before use.
+
+endmenu
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/asm-offsets.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/asm-offsets.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/asm-offsets.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/asm-offsets.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,112 @@
+/*
+ * linux/arch/unicore32/kernel/asm-offsets.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ *
+ * 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/sched.h>
+#include <linux/mm.h>
+#include <linux/dma-mapping.h>
+#include <linux/kbuild.h>
+#include <linux/suspend.h>
+#include <linux/thread_info.h>
+#include <asm/memory.h>
+#include <asm/suspend.h>
+
+/*
+ * GCC 3.0, 3.1: general bad code generation.
+ * GCC 3.2.0: incorrect function argument offset calculation.
+ * GCC 3.2.x: miscompiles NEW_AUX_ENT in fs/binfmt_elf.c
+ *	(http://gcc.gnu.org/PR8896) and incorrect structure
+ *		initialisation in fs/jffs2/erase.c
+ */
+#if (__GNUC__ < 4)
+#error Your compiler should upgrade to uc4
+#error	Known good compilers: 4.2.2
+#endif
+
+int main(void)
+{
+	DEFINE(TSK_ACTIVE_MM,	offsetof(struct task_struct, active_mm));
+	BLANK();
+	DEFINE(TI_FLAGS,	offsetof(struct thread_info, flags));
+	DEFINE(TI_PREEMPT,	offsetof(struct thread_info, preempt_count));
+	DEFINE(TI_ADDR_LIMIT,	offsetof(struct thread_info, addr_limit));
+	DEFINE(TI_TASK,		offsetof(struct thread_info, task));
+	DEFINE(TI_EXEC_DOMAIN,	offsetof(struct thread_info, exec_domain));
+	DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
+	DEFINE(TI_CPU_SAVE,	offsetof(struct thread_info, cpu_context));
+	DEFINE(TI_USED_CP,	offsetof(struct thread_info, used_cp));
+#ifdef CONFIG_UNICORE_FPU_F64
+	DEFINE(TI_FPSTATE,	offsetof(struct thread_info, fpstate));
+#endif
+	BLANK();
+	DEFINE(S_R0,		offsetof(struct pt_regs, UCreg_00));
+	DEFINE(S_R1,		offsetof(struct pt_regs, UCreg_01));
+	DEFINE(S_R2,		offsetof(struct pt_regs, UCreg_02));
+	DEFINE(S_R3,		offsetof(struct pt_regs, UCreg_03));
+	DEFINE(S_R4,		offsetof(struct pt_regs, UCreg_04));
+	DEFINE(S_R5,		offsetof(struct pt_regs, UCreg_05));
+	DEFINE(S_R6,		offsetof(struct pt_regs, UCreg_06));
+	DEFINE(S_R7,		offsetof(struct pt_regs, UCreg_07));
+	DEFINE(S_R8,		offsetof(struct pt_regs, UCreg_08));
+	DEFINE(S_R9,		offsetof(struct pt_regs, UCreg_09));
+	DEFINE(S_R10,		offsetof(struct pt_regs, UCreg_10));
+	DEFINE(S_R11,		offsetof(struct pt_regs, UCreg_11));
+	DEFINE(S_R12,		offsetof(struct pt_regs, UCreg_12));
+	DEFINE(S_R13,		offsetof(struct pt_regs, UCreg_13));
+	DEFINE(S_R14,		offsetof(struct pt_regs, UCreg_14));
+	DEFINE(S_R15,		offsetof(struct pt_regs, UCreg_15));
+	DEFINE(S_R16,		offsetof(struct pt_regs, UCreg_16));
+	DEFINE(S_R17,		offsetof(struct pt_regs, UCreg_17));
+	DEFINE(S_R18,		offsetof(struct pt_regs, UCreg_18));
+	DEFINE(S_R19,		offsetof(struct pt_regs, UCreg_19));
+	DEFINE(S_R20,		offsetof(struct pt_regs, UCreg_20));
+	DEFINE(S_R21,		offsetof(struct pt_regs, UCreg_21));
+	DEFINE(S_R22,		offsetof(struct pt_regs, UCreg_22));
+	DEFINE(S_R23,		offsetof(struct pt_regs, UCreg_23));
+	DEFINE(S_R24,		offsetof(struct pt_regs, UCreg_24));
+	DEFINE(S_R25,		offsetof(struct pt_regs, UCreg_25));
+	DEFINE(S_R26,		offsetof(struct pt_regs, UCreg_26));
+	DEFINE(S_FP,		offsetof(struct pt_regs, UCreg_fp));
+	DEFINE(S_IP,		offsetof(struct pt_regs, UCreg_ip));
+	DEFINE(S_SP,		offsetof(struct pt_regs, UCreg_sp));
+	DEFINE(S_LR,		offsetof(struct pt_regs, UCreg_lr));
+	DEFINE(S_PC,		offsetof(struct pt_regs, UCreg_pc));
+	DEFINE(S_PSR,		offsetof(struct pt_regs, UCreg_asr));
+	DEFINE(S_OLD_R0,	offsetof(struct pt_regs, UCreg_ORIG_00));
+	DEFINE(S_FRAME_SIZE,	sizeof(struct pt_regs));
+	BLANK();
+	DEFINE(VMA_VM_MM,	offsetof(struct vm_area_struct, vm_mm));
+	DEFINE(VMA_VM_FLAGS,	offsetof(struct vm_area_struct, vm_flags));
+	BLANK();
+	DEFINE(VM_EXEC,		VM_EXEC);
+	BLANK();
+	DEFINE(PAGE_SZ,		PAGE_SIZE);
+	BLANK();
+	DEFINE(SYS_ERROR0,	0x9f0000);
+	BLANK();
+	DEFINE(PBE_ADDRESS,		offsetof(struct pbe, address));
+	DEFINE(PBE_ORIN_ADDRESS,	offsetof(struct pbe, orig_address));
+	DEFINE(PBE_NEXT,		offsetof(struct pbe, next));
+	DEFINE(SWSUSP_CPU,		offsetof(struct swsusp_arch_regs, \
+							cpu_context));
+#ifdef	CONFIG_UNICORE_FPU_F64
+	DEFINE(SWSUSP_FPSTATE,		offsetof(struct swsusp_arch_regs, \
+							fpstate));
+#endif
+	BLANK();
+	DEFINE(DMA_BIDIRECTIONAL,	DMA_BIDIRECTIONAL);
+	DEFINE(DMA_TO_DEVICE,		DMA_TO_DEVICE);
+	DEFINE(DMA_FROM_DEVICE,		DMA_FROM_DEVICE);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/clock.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/clock.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/clock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/clock.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,390 @@
+/*
+ * linux/arch/unicore32/kernel/clock.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/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/delay.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+
+/*
+ * Very simple clock implementation
+ */
+struct clk {
+	struct list_head	node;
+	unsigned long		rate;
+	const char		*name;
+};
+
+static struct clk clk_ost_clk = {
+	.name		= "OST_CLK",
+	.rate		= CLOCK_TICK_RATE,
+};
+
+static struct clk clk_mclk_clk = {
+	.name		= "MAIN_CLK",
+};
+
+static struct clk clk_bclk32_clk = {
+	.name		= "BUS32_CLK",
+};
+
+static struct clk clk_ddr_clk = {
+	.name		= "DDR_CLK",
+};
+
+static struct clk clk_vga_clk = {
+	.name		= "VGA_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(id, p->name) == 0) {
+			clk = p;
+			break;
+		}
+	}
+	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->rate;
+}
+EXPORT_SYMBOL(clk_get_rate);
+
+struct {
+	unsigned long rate;
+	unsigned long cfg;
+	unsigned long div;
+} vga_clk_table[] = {
+	{.rate =  25175000, .cfg = 0x00002001, .div = 0x9},
+	{.rate =  31500000, .cfg = 0x00002001, .div = 0x7},
+	{.rate =  40000000, .cfg = 0x00003801, .div = 0x9},
+	{.rate =  49500000, .cfg = 0x00003801, .div = 0x7},
+	{.rate =  65000000, .cfg = 0x00002c01, .div = 0x4},
+	{.rate =  78750000, .cfg = 0x00002400, .div = 0x7},
+	{.rate = 108000000, .cfg = 0x00002c01, .div = 0x2},
+	{.rate = 106500000, .cfg = 0x00003c01, .div = 0x3},
+	{.rate =  50650000, .cfg = 0x00106400, .div = 0x9},
+	{.rate =  61500000, .cfg = 0x00106400, .div = 0xa},
+	{.rate =  85500000, .cfg = 0x00002800, .div = 0x6},
+};
+
+struct {
+	unsigned long mrate;
+	unsigned long prate;
+} mclk_clk_table[] = {
+	{.mrate = 500000000, .prate = 0x00109801},
+	{.mrate = 525000000, .prate = 0x00104C00},
+	{.mrate = 550000000, .prate = 0x00105000},
+	{.mrate = 575000000, .prate = 0x00105400},
+	{.mrate = 600000000, .prate = 0x00105800},
+	{.mrate = 625000000, .prate = 0x00105C00},
+	{.mrate = 650000000, .prate = 0x00106000},
+	{.mrate = 675000000, .prate = 0x00106400},
+	{.mrate = 700000000, .prate = 0x00106800},
+	{.mrate = 725000000, .prate = 0x00106C00},
+	{.mrate = 750000000, .prate = 0x00107000},
+	{.mrate = 775000000, .prate = 0x00107400},
+	{.mrate = 800000000, .prate = 0x00107800},
+};
+
+int clk_set_rate(struct clk *clk, unsigned long rate)
+{
+	if (clk == &clk_vga_clk) {
+		unsigned long pll_vgacfg, pll_vgadiv;
+		int ret, i;
+
+		/* lookup vga_clk_table */
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(vga_clk_table); i++) {
+			if (rate == vga_clk_table[i].rate) {
+				pll_vgacfg = vga_clk_table[i].cfg;
+				pll_vgadiv = vga_clk_table[i].div;
+				ret = 0;
+				break;
+			}
+		}
+
+		if (ret)
+			return ret;
+
+		if (readl(PM_PLLVGACFG) == pll_vgacfg)
+			return 0;
+
+		/* set pll vga cfg reg. */
+		writel(pll_vgacfg, PM_PLLVGACFG);
+
+		writel(PM_PMCR_CFBVGA, PM_PMCR);
+		while ((readl(PM_PLLDFCDONE) & PM_PLLDFCDONE_VGADFC)
+				!= PM_PLLDFCDONE_VGADFC)
+			udelay(100); /* about 1ms */
+
+		/* set div cfg reg. */
+		writel(readl(PM_PCGR) | PM_PCGR_VGACLK, PM_PCGR);
+
+		writel((readl(PM_DIVCFG) & ~PM_DIVCFG_VGACLK_MASK)
+				| PM_DIVCFG_VGACLK(pll_vgadiv), PM_DIVCFG);
+
+		writel(readl(PM_SWRESET) | PM_SWRESET_VGADIV, PM_SWRESET);
+		while ((readl(PM_SWRESET) & PM_SWRESET_VGADIV)
+				== PM_SWRESET_VGADIV)
+			udelay(100); /* 65536 bclk32, about 320us */
+
+		writel(readl(PM_PCGR) & ~PM_PCGR_VGACLK, PM_PCGR);
+	}
+#ifdef CONFIG_CPU_FREQ
+	if (clk == &clk_mclk_clk) {
+		u32 pll_rate, divstatus = PM_DIVSTATUS;
+		int ret, i;
+
+		/* lookup mclk_clk_table */
+		ret = -EINVAL;
+		for (i = 0; i < ARRAY_SIZE(mclk_clk_table); i++) {
+			if (rate == mclk_clk_table[i].mrate) {
+				pll_rate = mclk_clk_table[i].prate;
+				clk_mclk_clk.rate = mclk_clk_table[i].mrate;
+				ret = 0;
+				break;
+			}
+		}
+
+		if (ret)
+			return ret;
+
+		if (clk_mclk_clk.rate)
+			clk_bclk32_clk.rate = clk_mclk_clk.rate
+				/ (((divstatus & 0x0000f000) >> 12) + 1);
+
+		/* set pll sys cfg reg. */
+		PM_PLLSYSCFG = pll_rate;
+
+		PM_PMCR = PM_PMCR_CFBSYS;
+		while ((PM_PLLDFCDONE & PM_PLLDFCDONE_SYSDFC)
+				!= PM_PLLDFCDONE_SYSDFC)
+			udelay(100);
+			/* about 1ms */
+	}
+#endif
+	return 0;
+}
+EXPORT_SYMBOL(clk_set_rate);
+
+int clk_register(struct clk *clk)
+{
+	mutex_lock(&clocks_mutex);
+	list_add(&clk->node, &clocks);
+	mutex_unlock(&clocks_mutex);
+	printk(KERN_DEFAULT "PKUnity PM: %s %lu.%02luM\n", clk->name,
+		(clk->rate)/1000000, (clk->rate)/10000 % 100);
+	return 0;
+}
+EXPORT_SYMBOL(clk_register);
+
+void clk_unregister(struct clk *clk)
+{
+	mutex_lock(&clocks_mutex);
+	list_del(&clk->node);
+	mutex_unlock(&clocks_mutex);
+}
+EXPORT_SYMBOL(clk_unregister);
+
+struct {
+	unsigned long prate;
+	unsigned long rate;
+} pllrate_table[] = {
+	{.prate = 0x00002001, .rate = 250000000},
+	{.prate = 0x00104801, .rate = 250000000},
+	{.prate = 0x00104C01, .rate = 262500000},
+	{.prate = 0x00002401, .rate = 275000000},
+	{.prate = 0x00105001, .rate = 275000000},
+	{.prate = 0x00105401, .rate = 287500000},
+	{.prate = 0x00002801, .rate = 300000000},
+	{.prate = 0x00105801, .rate = 300000000},
+	{.prate = 0x00105C01, .rate = 312500000},
+	{.prate = 0x00002C01, .rate = 325000000},
+	{.prate = 0x00106001, .rate = 325000000},
+	{.prate = 0x00106401, .rate = 337500000},
+	{.prate = 0x00003001, .rate = 350000000},
+	{.prate = 0x00106801, .rate = 350000000},
+	{.prate = 0x00106C01, .rate = 362500000},
+	{.prate = 0x00003401, .rate = 375000000},
+	{.prate = 0x00107001, .rate = 375000000},
+	{.prate = 0x00107401, .rate = 387500000},
+	{.prate = 0x00003801, .rate = 400000000},
+	{.prate = 0x00107801, .rate = 400000000},
+	{.prate = 0x00107C01, .rate = 412500000},
+	{.prate = 0x00003C01, .rate = 425000000},
+	{.prate = 0x00108001, .rate = 425000000},
+	{.prate = 0x00108401, .rate = 437500000},
+	{.prate = 0x00004001, .rate = 450000000},
+	{.prate = 0x00108801, .rate = 450000000},
+	{.prate = 0x00108C01, .rate = 462500000},
+	{.prate = 0x00004401, .rate = 475000000},
+	{.prate = 0x00109001, .rate = 475000000},
+	{.prate = 0x00109401, .rate = 487500000},
+	{.prate = 0x00004801, .rate = 500000000},
+	{.prate = 0x00109801, .rate = 500000000},
+	{.prate = 0x00104C00, .rate = 525000000},
+	{.prate = 0x00002400, .rate = 550000000},
+	{.prate = 0x00105000, .rate = 550000000},
+	{.prate = 0x00105400, .rate = 575000000},
+	{.prate = 0x00002800, .rate = 600000000},
+	{.prate = 0x00105800, .rate = 600000000},
+	{.prate = 0x00105C00, .rate = 625000000},
+	{.prate = 0x00002C00, .rate = 650000000},
+	{.prate = 0x00106000, .rate = 650000000},
+	{.prate = 0x00106400, .rate = 675000000},
+	{.prate = 0x00003000, .rate = 700000000},
+	{.prate = 0x00106800, .rate = 700000000},
+	{.prate = 0x00106C00, .rate = 725000000},
+	{.prate = 0x00003400, .rate = 750000000},
+	{.prate = 0x00107000, .rate = 750000000},
+	{.prate = 0x00107400, .rate = 775000000},
+	{.prate = 0x00003800, .rate = 800000000},
+	{.prate = 0x00107800, .rate = 800000000},
+	{.prate = 0x00107C00, .rate = 825000000},
+	{.prate = 0x00003C00, .rate = 850000000},
+	{.prate = 0x00108000, .rate = 850000000},
+	{.prate = 0x00108400, .rate = 875000000},
+	{.prate = 0x00004000, .rate = 900000000},
+	{.prate = 0x00108800, .rate = 900000000},
+	{.prate = 0x00108C00, .rate = 925000000},
+	{.prate = 0x00004400, .rate = 950000000},
+	{.prate = 0x00109000, .rate = 950000000},
+	{.prate = 0x00109400, .rate = 975000000},
+	{.prate = 0x00004800, .rate = 1000000000},
+	{.prate = 0x00109800, .rate = 1000000000},
+};
+
+struct {
+	unsigned long prate;
+	unsigned long drate;
+} pddr_table[] = {
+	{.prate = 0x00100800, .drate = 44236800},
+	{.prate = 0x00100C00, .drate = 66355200},
+	{.prate = 0x00101000, .drate = 88473600},
+	{.prate = 0x00101400, .drate = 110592000},
+	{.prate = 0x00101800, .drate = 132710400},
+	{.prate = 0x00101C01, .drate = 154828800},
+	{.prate = 0x00102001, .drate = 176947200},
+	{.prate = 0x00102401, .drate = 199065600},
+	{.prate = 0x00102801, .drate = 221184000},
+	{.prate = 0x00102C01, .drate = 243302400},
+	{.prate = 0x00103001, .drate = 265420800},
+	{.prate = 0x00103401, .drate = 287539200},
+	{.prate = 0x00103801, .drate = 309657600},
+	{.prate = 0x00103C01, .drate = 331776000},
+	{.prate = 0x00104001, .drate = 353894400},
+};
+
+static int __init clk_init(void)
+{
+#ifdef CONFIG_PUV3_PM
+	u32 pllrate, divstatus = readl(PM_DIVSTATUS);
+	u32 pcgr_val = readl(PM_PCGR);
+	int i;
+
+	pcgr_val |= PM_PCGR_BCLKMME | PM_PCGR_BCLKH264E | PM_PCGR_BCLKH264D
+			| PM_PCGR_HECLK | PM_PCGR_HDCLK;
+	writel(pcgr_val, PM_PCGR);
+
+	pllrate = readl(PM_PLLSYSSTATUS);
+
+	/* lookup pmclk_table */
+	clk_mclk_clk.rate = 0;
+	for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
+		if (pllrate == pllrate_table[i].prate) {
+			clk_mclk_clk.rate = pllrate_table[i].rate;
+			break;
+		}
+	}
+
+	if (clk_mclk_clk.rate)
+		clk_bclk32_clk.rate = clk_mclk_clk.rate /
+			(((divstatus & 0x0000f000) >> 12) + 1);
+
+	pllrate = readl(PM_PLLDDRSTATUS);
+
+	/* lookup pddr_table */
+	clk_ddr_clk.rate = 0;
+	for (i = 0; i < ARRAY_SIZE(pddr_table); i++) {
+		if (pllrate == pddr_table[i].prate) {
+			clk_ddr_clk.rate = pddr_table[i].drate;
+			break;
+		}
+	}
+
+	pllrate = readl(PM_PLLVGASTATUS);
+
+	/* lookup pvga_table */
+	clk_vga_clk.rate = 0;
+	for (i = 0; i < ARRAY_SIZE(pllrate_table); i++) {
+		if (pllrate == pllrate_table[i].prate) {
+			clk_vga_clk.rate = pllrate_table[i].rate;
+			break;
+		}
+	}
+
+	if (clk_vga_clk.rate)
+		clk_vga_clk.rate = clk_vga_clk.rate /
+			(((divstatus & 0x00f00000) >> 20) + 1);
+
+	clk_register(&clk_vga_clk);
+#endif
+#ifdef CONFIG_ARCH_FPGA
+	clk_ddr_clk.rate = 33000000;
+	clk_mclk_clk.rate = 33000000;
+	clk_bclk32_clk.rate = 33000000;
+#endif
+	clk_register(&clk_ddr_clk);
+	clk_register(&clk_mclk_clk);
+	clk_register(&clk_bclk32_clk);
+	clk_register(&clk_ost_clk);
+	return 0;
+}
+core_initcall(clk_init);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/cpu-ucv2.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/cpu-ucv2.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/cpu-ucv2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/cpu-ucv2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,93 @@
+/*
+ * linux/arch/unicore32/kernel/cpu-ucv2.c: clock scaling for the UniCore-II
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/clk.h>
+#include <linux/cpufreq.h>
+
+#include <mach/hardware.h>
+
+static struct cpufreq_driver ucv2_driver;
+
+/* make sure that only the "userspace" governor is run
+ * -- anything else wouldn't make sense on this platform, anyway.
+ */
+int ucv2_verify_speed(struct cpufreq_policy *policy)
+{
+	if (policy->cpu)
+		return -EINVAL;
+
+	cpufreq_verify_within_limits(policy,
+			policy->cpuinfo.min_freq, policy->cpuinfo.max_freq);
+
+	return 0;
+}
+
+static unsigned int ucv2_getspeed(unsigned int cpu)
+{
+	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
+
+	if (cpu)
+		return 0;
+	return clk_get_rate(mclk)/1000;
+}
+
+static int ucv2_target(struct cpufreq_policy *policy,
+			 unsigned int target_freq,
+			 unsigned int relation)
+{
+	unsigned int cur = ucv2_getspeed(0);
+	struct cpufreq_freqs freqs;
+	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+	if (!clk_set_rate(mclk, target_freq * 1000)) {
+		freqs.old = cur;
+		freqs.new = target_freq;
+		freqs.cpu = 0;
+	}
+
+	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+	return 0;
+}
+
+static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
+{
+	if (policy->cpu != 0)
+		return -EINVAL;
+	policy->cur = ucv2_getspeed(0);
+	policy->min = policy->cpuinfo.min_freq = 250000;
+	policy->max = policy->cpuinfo.max_freq = 1000000;
+	policy->cpuinfo.transition_latency = CPUFREQ_ETERNAL;
+	return 0;
+}
+
+static struct cpufreq_driver ucv2_driver = {
+	.flags		= CPUFREQ_STICKY,
+	.verify		= ucv2_verify_speed,
+	.target		= ucv2_target,
+	.get		= ucv2_getspeed,
+	.init		= ucv2_cpu_init,
+	.name		= "UniCore-II",
+};
+
+static int __init ucv2_cpufreq_init(void)
+{
+	return cpufreq_register_driver(&ucv2_driver);
+}
+
+arch_initcall(ucv2_cpufreq_init);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/debug-macro.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/debug-macro.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/debug-macro.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/debug-macro.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/unicore32/kernel/debug-macro.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * Debugging macro include header
+ */
+#include <generated/asm-offsets.h>
+#include <mach/hardware.h>
+
+		.macro	put_word_ocd, rd, rx=r16
+1001:		movc		\rx, p1.c0, #0
+		cand.a	\rx, #2
+		bne	1001b
+		movc		p1.c1, \rd, #1
+		.endm
+
+#ifdef CONFIG_DEBUG_OCD
+		/* debug using UniCore On-Chip-Debugger */
+		.macro	addruart, rx
+		.endm
+
+		.macro	senduart, rd, rx
+		put_word_ocd	\rd, \rx
+		.endm
+
+		.macro	busyuart, rd, rx
+		.endm
+
+		.macro	waituart, rd, rx
+		.endm
+#else
+#define UART_CLK_DEFAULT        3686400 * 20
+	/* Uartclk = MCLK/ 2, The MCLK on my board is 3686400 * 40  */
+#define BAUD_RATE_DEFAULT	115200
+	/* The baud rate of the serial port */
+
+#define UART_DIVISOR_DEFAULT	(UART_CLK_DEFAULT \
+				/ (16 * BAUD_RATE_DEFAULT) - 1)
+
+		.macro	addruart,rx
+		mrc	p0, #0, \rx, c1, c0
+		tst	\rx, #1			@ MMU enabled?
+		moveq	\rx, #0xee000000	@ physical base address
+		movne	\rx, #0x6e000000	@ virtual address
+
+		@ We probe for the active serial port here
+		@ However, now we assume UART0 is active:	epip4d
+		@ We assume r1 and r2 can be clobbered.
+
+		movl 	r2, #UART_DIVISOR_DEFAULT
+		mov 	r1, #0x80
+		str	r1, [\rx, #UART_LCR_OFFSET]
+		and	r1, r2, #0xff00
+		mov	r1, r1, lsr #8
+		str	r1, [\rx, #UART_DLH_OFFSET]
+		and	r1, r2, #0xff
+		str	r1, [\rx, #UART_DLL_OFFSET]
+		mov 	r1, #0x7
+		str	r1, [\rx, #UART_FCR_OFFSET]
+		mov 	r1, #0x3
+		str	r1, [\rx, #UART_LCR_OFFSET]
+		mov 	r1, #0x0
+		str	r1, [\rx, #UART_IER_OFFSET]
+		.endm
+
+		.macro	senduart,rd,rx
+		str	\rd, [\rx, #UART_THR_OFFSET]
+		.endm
+
+		.macro	waituart,rd,rx
+1001:		ldr	\rd, [\rx, #UART_LSR_OFFSET]
+		tst	\rd, #UART_LSR_THRE
+		beq	1001b
+		.endm
+
+		.macro	busyuart,rd,rx
+1001:		ldr	\rd, [\rx, #UART_LSR_OFFSET]
+		tst	\rd, #UART_LSR_TEMT
+		bne	1001b
+		.endm
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/debug.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/debug.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/debug.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/debug.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,85 @@
+/*
+ * linux/arch/unicore32/kernel/debug.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  32-bit debugging code
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+
+		.text
+
+/*
+ * Some debugging routines (useful if you've got MM problems and
+ * printk isn't working).  For DEBUGGING ONLY!!!  Do not leave
+ * references to these in a production kernel!
+ */
+#include "debug-macro.S"
+
+/*
+ * Useful debugging routines
+ */
+ENTRY(printhex8)
+		mov	r1, #8
+		b	printhex
+ENDPROC(printhex8)
+
+ENTRY(printhex4)
+		mov	r1, #4
+		b	printhex
+ENDPROC(printhex4)
+
+ENTRY(printhex2)
+		mov	r1, #2
+printhex:	adr	r2, hexbuf
+		add	r3, r2, r1
+		mov	r1, #0
+		stb	r1, [r3]
+1:		and	r1, r0, #15
+		mov	r0, r0 >> #4
+		csub.a	r1, #10
+		beg	2f
+		add	r1, r1, #'0' - 'a' + 10
+2:		add	r1, r1, #'a' - 10
+		stb.w	r1, [r3+], #-1
+		cxor.a	r3, r2
+		bne	1b
+		mov	r0, r2
+		b	printascii
+ENDPROC(printhex2)
+
+		.ltorg
+
+ENTRY(printascii)
+		addruart r3
+		b	2f
+1:		waituart r2, r3
+		senduart r1, r3
+		busyuart r2, r3
+		cxor.a	r1, #'\n'
+		cmoveq	r1, #'\r'
+		beq	1b
+2:		cxor.a	r0, #0
+		beq	3f
+		ldb.w	r1, [r0]+, #1
+		cxor.a	r1, #0
+		bne	1b
+3:		mov	pc, lr
+ENDPROC(printascii)
+
+ENTRY(printch)
+		addruart r3
+		mov	r1, r0
+		mov	r0, #0
+		b	1b
+ENDPROC(printch)
+
+hexbuf:		.space 16
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/dma.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/dma.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,183 @@
+/*
+ * linux/arch/unicore32/kernel/dma.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/init.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <mach/dma.h>
+
+struct dma_channel {
+	char *name;
+	puv3_dma_prio prio;
+	void (*irq_handler)(int, void *);
+	void (*err_handler)(int, void *);
+	void *data;
+};
+
+static struct dma_channel dma_channels[MAX_DMA_CHANNELS];
+
+int puv3_request_dma(char *name, puv3_dma_prio prio,
+			 void (*irq_handler)(int, void *),
+			 void (*err_handler)(int, void *),
+			 void *data)
+{
+	unsigned long flags;
+	int i, found = 0;
+
+	/* basic sanity checks */
+	if (!name)
+		return -EINVAL;
+
+	local_irq_save(flags);
+
+	do {
+		/* try grabbing a DMA channel with the requested priority */
+		for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+			if ((dma_channels[i].prio == prio) &&
+			    !dma_channels[i].name) {
+				found = 1;
+				break;
+			}
+		}
+		/* if requested prio group is full, try a hier priority */
+	} while (!found && prio--);
+
+	if (found) {
+		dma_channels[i].name = name;
+		dma_channels[i].irq_handler = irq_handler;
+		dma_channels[i].err_handler = err_handler;
+		dma_channels[i].data = data;
+	} else {
+		printk(KERN_WARNING "No more available DMA channels for %s\n",
+				name);
+		i = -ENODEV;
+	}
+
+	local_irq_restore(flags);
+	return i;
+}
+EXPORT_SYMBOL(puv3_request_dma);
+
+void puv3_free_dma(int dma_ch)
+{
+	unsigned long flags;
+
+	if (!dma_channels[dma_ch].name) {
+		printk(KERN_CRIT
+			"%s: trying to free channel %d which is already freed\n",
+			__func__, dma_ch);
+		return;
+	}
+
+	local_irq_save(flags);
+	dma_channels[dma_ch].name = NULL;
+	dma_channels[dma_ch].err_handler = NULL;
+	local_irq_restore(flags);
+}
+EXPORT_SYMBOL(puv3_free_dma);
+
+static irqreturn_t dma_irq_handler(int irq, void *dev_id)
+{
+	int i, dint;
+
+	dint = readl(DMAC_ITCSR);
+	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+		if (dint & DMAC_CHANNEL(i)) {
+			struct dma_channel *channel = &dma_channels[i];
+
+			/* Clear TC interrupt of channel i */
+			writel(DMAC_CHANNEL(i), DMAC_ITCCR);
+			writel(0, DMAC_ITCCR);
+
+			if (channel->name && 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 irqreturn_t dma_err_handler(int irq, void *dev_id)
+{
+	int i, dint;
+
+	dint = readl(DMAC_IESR);
+	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+		if (dint & DMAC_CHANNEL(i)) {
+			struct dma_channel *channel = &dma_channels[i];
+
+			/* Clear Err interrupt of channel i */
+			writel(DMAC_CHANNEL(i), DMAC_IECR);
+			writel(0, DMAC_IECR);
+
+			if (channel->name && channel->err_handler) {
+				channel->err_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;
+}
+
+int __init puv3_init_dma(void)
+{
+	int i, ret;
+
+	/* dma channel priorities on v8 processors:
+	 * ch 0 - 1  <--> (0) DMA_PRIO_HIGH
+	 * ch 2 - 3  <--> (1) DMA_PRIO_MEDIUM
+	 * ch 4 - 5  <--> (2) DMA_PRIO_LOW
+	 */
+	for (i = 0; i < MAX_DMA_CHANNELS; i++) {
+		puv3_stop_dma(i);
+		dma_channels[i].name = NULL;
+		dma_channels[i].prio = min((i & 0x7) >> 1, DMA_PRIO_LOW);
+	}
+
+	ret = request_irq(IRQ_DMA, dma_irq_handler, 0, "DMA", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Can't register IRQ for DMA\n");
+		return ret;
+	}
+
+	ret = request_irq(IRQ_DMAERR, dma_err_handler, 0, "DMAERR", NULL);
+	if (ret) {
+		printk(KERN_CRIT "Can't register IRQ for DMAERR\n");
+		free_irq(IRQ_DMA, "DMA");
+		return ret;
+	}
+
+	return 0;
+}
+
+postcore_initcall(puv3_init_dma);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/early_printk.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/early_printk.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/early_printk.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/early_printk.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ * linux/arch/unicore32/kernel/early_printk.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/console.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <mach/ocd.h>
+
+/* On-Chip-Debugger functions */
+
+static void early_ocd_write(struct console *con, const char *s, unsigned n)
+{
+	while (*s && n-- > 0) {
+		if (*s == '\n')
+			ocd_putc((int)'\r');
+		ocd_putc((int)*s);
+		s++;
+	}
+}
+
+static struct console early_ocd_console = {
+	.name =		"earlyocd",
+	.write =	early_ocd_write,
+	.flags =	CON_PRINTBUFFER,
+	.index =	-1,
+};
+
+/* Direct interface for emergencies */
+static struct console *early_console = &early_ocd_console;
+
+static int __initdata keep_early;
+
+static int __init setup_early_printk(char *buf)
+{
+	if (!buf)
+		return 0;
+
+	if (strstr(buf, "keep"))
+		keep_early = 1;
+
+	if (!strncmp(buf, "ocd", 3))
+		early_console = &early_ocd_console;
+
+	if (keep_early)
+		early_console->flags &= ~CON_BOOT;
+	else
+		early_console->flags |= CON_BOOT;
+	register_console(early_console);
+	return 0;
+}
+early_param("earlyprintk", setup_early_printk);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/elf.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/elf.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/elf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/elf.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * linux/arch/unicore32/kernel/elf.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/sched.h>
+#include <linux/personality.h>
+#include <linux/binfmts.h>
+#include <linux/elf.h>
+
+int elf_check_arch(const struct elf32_hdr *x)
+{
+	/* Make sure it's an UniCore executable */
+	if (x->e_machine != EM_UNICORE)
+		return 0;
+
+	/* Make sure the entry address is reasonable */
+	if (x->e_entry & 3)
+		return 0;
+
+	return 1;
+}
+EXPORT_SYMBOL(elf_check_arch);
+
+void elf_set_personality(const struct elf32_hdr *x)
+{
+	unsigned int personality = PER_LINUX;
+
+	set_personality(personality);
+}
+EXPORT_SYMBOL(elf_set_personality);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/entry.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/entry.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,824 @@
+/*
+ * linux/arch/unicore32/kernel/entry.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  Low-level vector interface routines
+ */
+#include <linux/init.h>
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <asm/errno.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/unistd.h>
+#include <generated/asm-offsets.h>
+#include "debug-macro.S"
+
+@
+@ Most of the stack format comes from struct pt_regs, but with
+@ the addition of 8 bytes for storing syscall args 5 and 6.
+@
+#define S_OFF		8
+
+/*
+ * The SWI code relies on the fact that R0 is at the bottom of the stack
+ * (due to slow/fast restore user regs).
+ */
+#if S_R0 != 0
+#error "Please fix"
+#endif
+
+	.macro	zero_fp
+#ifdef CONFIG_FRAME_POINTER
+	mov	fp, #0
+#endif
+	.endm
+
+	.macro	alignment_trap, rtemp
+#ifdef CONFIG_ALIGNMENT_TRAP
+	ldw	\rtemp, .LCcralign
+	ldw	\rtemp, [\rtemp]
+	movc	p0.c1, \rtemp, #0
+#endif
+	.endm
+
+	.macro	load_user_sp_lr, rd, rtemp, offset = 0
+	mov	\rtemp, asr
+	xor	\rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
+	mov.a	asr, \rtemp			@ switch to the SUSR mode
+
+	ldw	sp, [\rd+], #\offset		@ load sp_user
+	ldw	lr, [\rd+], #\offset + 4	@ load lr_user
+
+	xor	\rtemp, \rtemp, #(PRIV_MODE ^ SUSR_MODE)
+	mov.a	asr, \rtemp			@ switch back to the PRIV mode
+	.endm
+
+	.macro	priv_exit, rpsr
+	mov.a	bsr, \rpsr
+	ldm.w	(r0 - r15), [sp]+
+	ldm.b	(r16 - pc), [sp]+		@ load r0 - pc, asr
+	.endm
+
+	.macro	restore_user_regs, fast = 0, offset = 0
+	ldw	r1, [sp+], #\offset + S_PSR	@ get calling asr
+	ldw	lr, [sp+], #\offset + S_PC	@ get pc
+	mov.a	bsr, r1				@ save in bsr_priv
+	.if	\fast
+	add	sp, sp, #\offset + S_R1		@ r0 is syscall return value
+	ldm.w	(r1 - r15), [sp]+		@ get calling r1 - r15
+	ldur	(r16 - lr), [sp]+		@ get calling r16 - lr
+	.else
+	ldm.w	(r0 - r15), [sp]+		@ get calling r0 - r15
+	ldur	(r16 - lr), [sp]+		@ get calling r16 - lr
+	.endif
+	nop
+	add	sp, sp, #S_FRAME_SIZE - S_R16
+	mov.a	pc, lr				@ return
+						@ and move bsr_priv into asr
+	.endm
+
+	.macro	get_thread_info, rd
+	mov	\rd, sp >> #13
+	mov	\rd, \rd << #13
+	.endm
+
+	.macro	get_irqnr_and_base, irqnr, irqstat, base, tmp
+	ldw	\base, =(PKUNITY_INTC_BASE)
+	ldw	\irqstat, [\base+], #0xC	@ INTC_ICIP
+	ldw	\tmp,	  [\base+], #0x4	@ INTC_ICMR
+	and.a	\irqstat, \irqstat, \tmp
+	beq	1001f
+	cntlz	\irqnr, \irqstat
+	rsub	\irqnr, \irqnr, #31
+1001:	/* EQ will be set if no irqs pending */
+	.endm
+
+#ifdef CONFIG_DEBUG_LL
+	.macro	printreg, reg, temp
+		adr	\temp, 901f
+		stm	(r0-r3), [\temp]+
+		stw	lr, [\temp+], #0x10
+		mov	r0, \reg
+		b.l	printhex8
+		mov	r0, #':'
+		b.l	printch
+		mov	r0, pc
+		b.l	printhex8
+		adr	r0, 902f
+		b.l	printascii
+		adr	\temp, 901f
+		ldm	(r0-r3), [\temp]+
+		ldw	lr, [\temp+], #0x10
+		b	903f
+901:	.word	0, 0, 0, 0, 0	@ r0-r3, lr
+902:	.asciz	": epip4d\n"
+	.align
+903:
+	.endm
+#endif
+
+/*
+ * These are the registers used in the syscall handler, and allow us to
+ * have in theory up to 7 arguments to a function - r0 to r6.
+ *
+ * Note that tbl == why is intentional.
+ *
+ * We must set at least "tsk" and "why" when calling ret_with_reschedule.
+ */
+scno	.req	r21		@ syscall number
+tbl	.req	r22		@ syscall table pointer
+why	.req	r22		@ Linux syscall (!= 0)
+tsk	.req	r23		@ current thread_info
+
+/*
+ * Interrupt handling.  Preserves r17, r18, r19
+ */
+	.macro	intr_handler
+1:	get_irqnr_and_base r0, r6, r5, lr
+	beq	2f
+	mov	r1, sp
+	@
+	@ routine called with r0 = irq number, r1 = struct pt_regs *
+	@
+	adr	lr, 1b
+	b	asm_do_IRQ
+2:
+	.endm
+
+/*
+ * PRIV mode handlers
+ */
+	.macro	priv_entry
+	sub	sp, sp, #(S_FRAME_SIZE - 4)
+	stm	(r1 - r15), [sp]+
+	add	r5, sp, #S_R15
+	stm	(r16 - r28), [r5]+
+
+	ldm	(r1 - r3), [r0]+
+	add	r5, sp, #S_SP - 4	@ here for interlock avoidance
+	mov	r4, #-1			@  ""  ""      ""       ""
+	add	r0, sp, #(S_FRAME_SIZE - 4)
+	stw.w	r1, [sp+], #-4		@ save the "real" r0 copied
+					@ from the exception stack
+
+	mov	r1, lr
+
+	@
+	@ We are now ready to fill in the remaining blanks on the stack:
+	@
+	@  r0 - sp_priv
+	@  r1 - lr_priv
+	@  r2 - lr_<exception>, already fixed up for correct return/restart
+	@  r3 - bsr_<exception>
+	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
+	@
+	stm	(r0 - r4), [r5]+
+	.endm
+
+/*
+ * User mode handlers
+ *
+ */
+	.macro	user_entry
+	sub	sp, sp, #S_FRAME_SIZE
+	stm	(r1 - r15), [sp+]
+	add	r4, sp, #S_R16
+	stm	(r16 - r28), [r4]+
+
+	ldm	(r1 - r3), [r0]+
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r4, #-1			@  ""  ""     ""        ""
+
+	stw	r1, [sp]		@ save the "real" r0 copied
+					@ from the exception stack
+
+	@
+	@ We are now ready to fill in the remaining blanks on the stack:
+	@
+	@  r2 - lr_<exception>, already fixed up for correct return/restart
+	@  r3 - bsr_<exception>
+	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
+	@
+	@ Also, separately save sp_user and lr_user
+	@
+	stm	(r2 - r4), [r0]+
+	stur	(sp, lr), [r0-]
+
+	@
+	@ Enable the alignment trap while in kernel mode
+	@
+	alignment_trap r0
+
+	@
+	@ Clear FP to mark the first stack frame
+	@
+	zero_fp
+	.endm
+
+	.text
+
+@
+@ __invalid - generic code for failed exception
+@			(re-entrant version of handlers)
+@
+__invalid:
+	sub	sp, sp, #S_FRAME_SIZE
+	stm	(r1 - r15), [sp+]
+	add	r1, sp, #S_R16
+	stm	(r16 - r28, sp, lr), [r1]+
+
+	zero_fp
+
+	ldm	(r4 - r6), [r0]+
+	add	r0, sp, #S_PC		@ here for interlock avoidance
+	mov	r7, #-1			@  ""   ""    ""        ""
+	stw	r4, [sp]		@ save preserved r0
+	stm	(r5 - r7), [r0]+	@ lr_<exception>,
+					@ asr_<exception>, "old_r0"
+
+	mov	r0, sp
+	mov	r1, asr
+	b	bad_mode
+ENDPROC(__invalid)
+
+	.align	5
+__dabt_priv:
+	priv_entry
+
+	@
+	@ get ready to re-enable interrupts if appropriate
+	@
+	mov	r17, asr
+	cand.a	r3, #PSR_I_BIT
+	bne	1f
+	andn	r17, r17, #PSR_I_BIT
+1:
+
+	@
+	@ Call the processor-specific abort handler:
+	@
+	@  r2 - aborted context pc
+	@  r3 - aborted context asr
+	@
+	@ The abort handler must return the aborted address in r0, and
+	@ the fault status register in r1.
+	@
+	movc	r1, p0.c3, #0		@ get FSR
+	movc	r0, p0.c4, #0		@ get FAR
+
+	@
+	@ set desired INTR state, then call main handler
+	@
+	mov.a	asr, r17
+	mov	r2, sp
+	b.l	do_DataAbort
+
+	@
+	@ INTRs off again before pulling preserved data off the stack
+	@
+	disable_irq r0
+
+	@
+	@ restore BSR and restart the instruction
+	@
+	ldw	r2, [sp+], #S_PSR
+	priv_exit r2				@ return from exception
+ENDPROC(__dabt_priv)
+
+	.align	5
+__intr_priv:
+	priv_entry
+
+	intr_handler
+
+	mov	r0, #0				@ epip4d
+	movc	p0.c5, r0, #14
+	nop; nop; nop; nop; nop; nop; nop; nop
+
+	ldw	r4, [sp+], #S_PSR		@ irqs are already disabled
+
+	priv_exit r4				@ return from exception
+ENDPROC(__intr_priv)
+
+	.ltorg
+
+	.align	5
+__extn_priv:
+	priv_entry
+
+	mov	r0, sp				@ struct pt_regs *regs
+	mov	r1, asr
+	b	bad_mode			@ not supported
+ENDPROC(__extn_priv)
+
+	.align	5
+__pabt_priv:
+	priv_entry
+
+	@
+	@ re-enable interrupts if appropriate
+	@
+	mov	r17, asr
+	cand.a	r3, #PSR_I_BIT
+	bne	1f
+	andn	r17, r17, #PSR_I_BIT
+1:
+
+	@
+	@ set args, then call main handler
+	@
+	@  r0 - address of faulting instruction
+	@  r1 - pointer to registers on stack
+	@
+	mov	r0, r2			@ pass address of aborted instruction
+	mov	r1, #5
+	mov.a	asr, r17
+	mov	r2, sp			@ regs
+	b.l	do_PrefetchAbort	@ call abort handler
+
+	@
+	@ INTRs off again before pulling preserved data off the stack
+	@
+	disable_irq r0
+
+	@
+	@ restore BSR and restart the instruction
+	@
+	ldw	r2, [sp+], #S_PSR
+	priv_exit r2			@ return from exception
+ENDPROC(__pabt_priv)
+
+	.align	5
+.LCcralign:
+	.word	cr_alignment
+
+	.align	5
+__dabt_user:
+	user_entry
+
+#ifdef CONFIG_UNICORE_FPU_F64
+	cff	ip, s31
+	cand.a	ip, #0x08000000		@ FPU execption traps?
+	beq	209f
+
+	ldw	ip, [sp+], #S_PC
+	add	ip, ip, #4
+	stw	ip, [sp+], #S_PC
+	@
+	@ fall through to the emulation code, which returns using r19 if
+	@ it has emulated the instruction, or the more conventional lr
+	@ if we are to treat this as a real extended instruction
+	@
+	@  r0 - instruction
+	@
+1:	ldw.u	r0, [r2]
+	adr	r19, ret_from_exception
+	adr	lr, 209f
+	@
+	@ fallthrough to call do_uc_f64
+	@
+/*
+ * Check whether the instruction is a co-processor instruction.
+ * If yes, we need to call the relevant co-processor handler.
+ *
+ * Note that we don't do a full check here for the co-processor
+ * instructions; all instructions with bit 27 set are well
+ * defined.  The only instructions that should fault are the
+ * co-processor instructions.
+ *
+ * Emulators may wish to make use of the following registers:
+ *  r0  = instruction opcode.
+ *  r2  = PC
+ *  r19 = normal "successful" return address
+ *  r20 = this threads thread_info structure.
+ *  lr  = unrecognised instruction return address
+ */
+	get_thread_info r20			@ get current thread
+	and	r8, r0, #0x00003c00		@ mask out CP number
+	mov	r7, #1
+	stb	r7, [r20+], #TI_USED_CP + 2	@ set appropriate used_cp[]
+
+	@ F64 hardware support entry point.
+	@  r0  = faulted instruction
+	@  r19 = return address
+	@  r20 = fp_state
+	enable_irq r4
+	add	r20, r20, #TI_FPSTATE	@ r20 = workspace
+	cff	r1, s31			@ get fpu FPSCR
+	andn    r2, r1, #0x08000000
+	ctf     r2, s31			@ clear 27 bit
+	mov	r2, sp			@ nothing stacked - regdump is at TOS
+	mov	lr, r19			@ setup for a return to the user code
+
+	@ Now call the C code to package up the bounce to the support code
+	@   r0 holds the trigger instruction
+	@   r1 holds the FPSCR value
+	@   r2 pointer to register dump
+	b	ucf64_exchandler
+209:
+#endif
+	@
+	@ Call the processor-specific abort handler:
+	@
+	@  r2 - aborted context pc
+	@  r3 - aborted context asr
+	@
+	@ The abort handler must return the aborted address in r0, and
+	@ the fault status register in r1.
+	@
+	movc	r1, p0.c3, #0		@ get FSR
+	movc	r0, p0.c4, #0		@ get FAR
+
+	@
+	@ INTRs on, then call the main handler
+	@
+	enable_irq r2
+	mov	r2, sp
+	adr	lr, ret_from_exception
+	b	do_DataAbort
+ENDPROC(__dabt_user)
+
+	.align	5
+__intr_user:
+	user_entry
+
+	get_thread_info tsk
+
+	intr_handler
+
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__intr_user)
+
+	.ltorg
+
+	.align	5
+__extn_user:
+	user_entry
+
+	mov	r0, sp
+	mov	r1, asr
+	b	bad_mode
+ENDPROC(__extn_user)
+
+	.align	5
+__pabt_user:
+	user_entry
+
+	mov	r0, r2			@ pass address of aborted instruction.
+	mov	r1, #5
+	enable_irq r1			@ Enable interrupts
+	mov	r2, sp			@ regs
+	b.l	do_PrefetchAbort	@ call abort handler
+	/* fall through */
+/*
+ * This is the return code to user mode for abort handlers
+ */
+ENTRY(ret_from_exception)
+	get_thread_info tsk
+	mov	why, #0
+	b	ret_to_user
+ENDPROC(__pabt_user)
+ENDPROC(ret_from_exception)
+
+/*
+ * Register switch for UniCore V2 processors
+ * r0 = previous task_struct, r1 = previous thread_info, r2 = next thread_info
+ * previous and next are guaranteed not to be the same.
+ */
+ENTRY(__switch_to)
+	add	ip, r1, #TI_CPU_SAVE
+	stm.w	(r4 - r15), [ip]+
+	stm.w	(r16 - r27, sp, lr), [ip]+
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	add	ip, r1, #TI_FPSTATE
+	sfm.w	(f0  - f7 ), [ip]+
+	sfm.w	(f8  - f15), [ip]+
+	sfm.w	(f16 - f23), [ip]+
+	sfm.w	(f24 - f31), [ip]+
+	cff	r4, s31
+	stw	r4, [ip]
+
+	add	ip, r2, #TI_FPSTATE
+	lfm.w	(f0  - f7 ), [ip]+
+	lfm.w	(f8  - f15), [ip]+
+	lfm.w	(f16 - f23), [ip]+
+	lfm.w	(f24 - f31), [ip]+
+	ldw	r4, [ip]
+	ctf	r4, s31
+#endif
+	add	ip, r2, #TI_CPU_SAVE
+	ldm.w	(r4 - r15), [ip]+
+	ldm	(r16 - r27, sp, pc), [ip]+	@ Load all regs saved previously
+ENDPROC(__switch_to)
+
+	.align	5
+/*
+ * This is the fast syscall return path.  We do as little as
+ * possible here, and this includes saving r0 back into the PRIV
+ * stack.
+ */
+ret_fast_syscall:
+	disable_irq r1				@ disable interrupts
+	ldw	r1, [tsk+], #TI_FLAGS
+	cand.a	r1, #_TIF_WORK_MASK
+	bne	fast_work_pending
+
+	@ fast_restore_user_regs
+	restore_user_regs fast = 1, offset = S_OFF
+
+/*
+ * Ok, we need to do extra processing, enter the slow path.
+ */
+fast_work_pending:
+	stw.w	r0, [sp+], #S_R0+S_OFF		@ returned r0
+work_pending:
+	cand.a	r1, #_TIF_NEED_RESCHED
+	bne	work_resched
+	cand.a	r1, #_TIF_SIGPENDING|_TIF_NOTIFY_RESUME
+	beq	no_work_pending
+	mov	r0, sp				@ 'regs'
+	mov	r2, why				@ 'syscall'
+	cand.a	r1, #_TIF_SIGPENDING		@ delivering a signal?
+	cmovne	why, #0				@ prevent further restarts
+	b.l	do_notify_resume
+	b	ret_slow_syscall		@ Check work again
+
+work_resched:
+	b.l	schedule
+/*
+ * "slow" syscall return path.  "why" tells us if this was a real syscall.
+ */
+ENTRY(ret_to_user)
+ret_slow_syscall:
+	disable_irq r1				@ disable interrupts
+	get_thread_info tsk			@ epip4d, one path error?!
+	ldw	r1, [tsk+], #TI_FLAGS
+	cand.a	r1, #_TIF_WORK_MASK
+	bne	work_pending
+no_work_pending:
+	@ slow_restore_user_regs
+	restore_user_regs fast = 0, offset = 0
+ENDPROC(ret_to_user)
+
+/*
+ * This is how we return from a fork.
+ */
+ENTRY(ret_from_fork)
+	b.l	schedule_tail
+	get_thread_info tsk
+	ldw	r1, [tsk+], #TI_FLAGS		@ check for syscall tracing
+	mov	why, #1
+	cand.a	r1, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+	beq	ret_slow_syscall
+	mov	r1, sp
+	mov	r0, #1				@ trace exit [IP = 1]
+	b.l	syscall_trace
+	b	ret_slow_syscall
+ENDPROC(ret_from_fork)
+
+/*=============================================================================
+ * SWI handler
+ *-----------------------------------------------------------------------------
+ */
+	.align	5
+ENTRY(vector_swi)
+	sub	sp, sp, #S_FRAME_SIZE
+	stm	(r0 - r15), [sp]+		@ Calling r0 - r15
+	add	r8, sp, #S_R16
+	stm	(r16 - r28), [r8]+		@ Calling r16 - r28
+	add	r8, sp, #S_PC
+	stur	(sp, lr), [r8-]			@ Calling sp, lr
+	mov	r8, bsr				@ called from non-REAL mode
+	stw	lr, [sp+], #S_PC		@ Save calling PC
+	stw	r8, [sp+], #S_PSR		@ Save ASR
+	stw	r0, [sp+], #S_OLD_R0		@ Save OLD_R0
+	zero_fp
+
+	/*
+	 * Get the system call number.
+	 */
+	sub	ip, lr, #4
+	ldw.u	scno, [ip]			@ get SWI instruction
+
+#ifdef CONFIG_ALIGNMENT_TRAP
+	ldw	ip, __cr_alignment
+	ldw	ip, [ip]
+	movc	p0.c1, ip, #0                   @ update control register
+#endif
+	enable_irq ip
+
+	get_thread_info tsk
+	ldw	tbl, =sys_call_table		@ load syscall table pointer
+
+	andn	scno, scno, #0xff000000		@ mask off SWI op-code
+	andn	scno, scno, #0x00ff0000		@ mask off SWI op-code
+
+	stm.w	(r4, r5), [sp-]			@ push fifth and sixth args
+	ldw	ip, [tsk+], #TI_FLAGS		@ check for syscall tracing
+	cand.a	ip, #_TIF_SYSCALL_TRACE		@ are we tracing syscalls?
+	bne	__sys_trace
+
+	csub.a	scno, #__NR_syscalls		@ check upper syscall limit
+	adr	lr, ret_fast_syscall		@ return address
+	bea	1f
+	ldw	pc, [tbl+], scno << #2		@ call sys_* routine
+1:
+	add	r1, sp, #S_OFF
+2:	mov	why, #0				@ no longer a real syscall
+	b	sys_ni_syscall			@ not private func
+
+	/*
+	 * This is the really slow path.  We're going to be doing
+	 * context switches, and waiting for our parent to respond.
+	 */
+__sys_trace:
+	mov	r2, scno
+	add	r1, sp, #S_OFF
+	mov	r0, #0				@ trace entry [IP = 0]
+	b.l	syscall_trace
+
+	adr	lr, __sys_trace_return		@ return address
+	mov	scno, r0			@ syscall number (possibly new)
+	add	r1, sp, #S_R0 + S_OFF		@ pointer to regs
+	csub.a	scno, #__NR_syscalls		@ check upper syscall limit
+	bea	2b
+	ldm	(r0 - r3), [r1]+		@ have to reload r0 - r3
+	ldw	pc, [tbl+], scno << #2		@ call sys_* routine
+
+__sys_trace_return:
+	stw.w	r0, [sp+], #S_R0 + S_OFF	@ save returned r0
+	mov	r2, scno
+	mov	r1, sp
+	mov	r0, #1				@ trace exit [IP = 1]
+	b.l	syscall_trace
+	b	ret_slow_syscall
+
+	.align	5
+#ifdef CONFIG_ALIGNMENT_TRAP
+	.type	__cr_alignment, #object
+__cr_alignment:
+	.word	cr_alignment
+#endif
+	.ltorg
+
+ENTRY(sys_execve)
+		add	r3, sp, #S_OFF
+		b	__sys_execve
+ENDPROC(sys_execve)
+
+ENTRY(sys_clone)
+		add	ip, sp, #S_OFF
+		stw	ip, [sp+], #4
+		b	__sys_clone
+ENDPROC(sys_clone)
+
+ENTRY(sys_rt_sigreturn)
+		add	r0, sp, #S_OFF
+		mov	why, #0		@ prevent syscall restart handling
+		b	__sys_rt_sigreturn
+ENDPROC(sys_rt_sigreturn)
+
+ENTRY(sys_sigaltstack)
+		ldw	r2, [sp+], #S_OFF + S_SP
+		b	do_sigaltstack
+ENDPROC(sys_sigaltstack)
+
+	__INIT
+
+/*
+ * Vector stubs.
+ *
+ * This code is copied to 0xffff0200 so we can use branches in the
+ * vectors, rather than ldr's.  Note that this code must not
+ * exceed 0x300 bytes.
+ *
+ * Common stub entry macro:
+ *   Enter in INTR mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
+ *
+ * SP points to a minimal amount of processor-private memory, the address
+ * of which is copied into r0 for the mode specific abort handler.
+ */
+	.macro	vector_stub, name, mode
+	.align	5
+
+vector_\name:
+	@
+	@ Save r0, lr_<exception> (parent PC) and bsr_<exception>
+	@ (parent ASR)
+	@
+	stw	r0, [sp]
+	stw	lr, [sp+], #4		@ save r0, lr
+	mov	lr, bsr
+	stw	lr, [sp+], #8		@ save bsr
+
+	@
+	@ Prepare for PRIV mode.  INTRs remain disabled.
+	@
+	mov	r0, asr
+	xor	r0, r0, #(\mode ^ PRIV_MODE)
+	mov.a	bsr, r0
+
+	@
+	@ the branch table must immediately follow this code
+	@
+	and	lr, lr, #0x03
+	add	lr, lr, #1
+	mov	r0, sp
+	ldw	lr, [pc+], lr << #2
+	mov.a	pc, lr			@ branch to handler in PRIV mode
+ENDPROC(vector_\name)
+	.align	2
+	@ handler addresses follow this label
+	.endm
+
+	.globl	__stubs_start
+__stubs_start:
+/*
+ * Interrupt dispatcher
+ */
+	vector_stub	intr, INTR_MODE
+
+	.long	__intr_user			@  0  (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2
+	.long	__intr_priv			@  3  (PRIV)
+
+/*
+ * Data abort dispatcher
+ * Enter in ABT mode, bsr = USER ASR, lr = USER PC
+ */
+	vector_stub	dabt, ABRT_MODE
+
+	.long	__dabt_user			@  0  (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2  (INTR)
+	.long	__dabt_priv			@  3  (PRIV)
+
+/*
+ * Prefetch abort dispatcher
+ * Enter in ABT mode, bsr = USER ASR, lr = USER PC
+ */
+	vector_stub	pabt, ABRT_MODE
+
+	.long	__pabt_user			@  0 (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2 (INTR)
+	.long	__pabt_priv			@  3 (PRIV)
+
+/*
+ * Undef instr entry dispatcher
+ * Enter in EXTN mode, bsr = PRIV/USER ASR, lr = PRIV/USER PC
+ */
+	vector_stub	extn, EXTN_MODE
+
+	.long	__extn_user			@  0 (USER)
+	.long	__invalid			@  1
+	.long	__invalid			@  2 (INTR)
+	.long	__extn_priv			@  3 (PRIV)
+
+/*
+ * We group all the following data together to optimise
+ * for CPUs with separate I & D caches.
+ */
+	.align	5
+
+.LCvswi:
+	.word	vector_swi
+
+	.globl	__stubs_end
+__stubs_end:
+
+	.equ	stubs_offset, __vectors_start + 0x200 - __stubs_start
+
+	.globl	__vectors_start
+__vectors_start:
+	jepriv	SYS_ERROR0
+	b	vector_extn + stubs_offset
+	ldw	pc, .LCvswi + stubs_offset
+	b	vector_pabt + stubs_offset
+	b	vector_dabt + stubs_offset
+	jepriv	SYS_ERROR0
+	b	vector_intr + stubs_offset
+	jepriv	SYS_ERROR0
+
+	.globl	__vectors_end
+__vectors_end:
+
+	.data
+
+	.globl	cr_alignment
+	.globl	cr_no_alignment
+cr_alignment:
+	.space	4
+cr_no_alignment:
+	.space	4
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/fpu-ucf64.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/fpu-ucf64.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/fpu-ucf64.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/fpu-ucf64.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/unicore32/kernel/fpu-ucf64.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/types.h>
+#include <linux/kernel.h>
+#include <linux/signal.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+
+#include <asm/fpu-ucf64.h>
+
+/*
+ * A special flag to tell the normalisation code not to normalise.
+ */
+#define F64_NAN_FLAG	0x100
+
+/*
+ * A bit pattern used to indicate the initial (unset) value of the
+ * exception mask, in case nothing handles an instruction.  This
+ * doesn't include the NAN flag, which get masked out before
+ * we check for an error.
+ */
+#define F64_EXCEPTION_ERROR	((u32)-1 & ~F64_NAN_FLAG)
+
+/*
+ * Since we aren't building with -mfpu=f64, we need to code
+ * these instructions using their MRC/MCR equivalents.
+ */
+#define f64reg(_f64_) #_f64_
+
+#define cff(_f64_) ({			\
+	u32 __v;			\
+	asm("cff %0, " f64reg(_f64_) "@ fmrx	%0, " #_f64_	\
+	    : "=r" (__v) : : "cc");	\
+	__v;				\
+	})
+
+#define ctf(_f64_, _var_)		\
+	asm("ctf %0, " f64reg(_f64_) "@ fmxr	" #_f64_ ", %0"	\
+	   : : "r" (_var_) : "cc")
+
+/*
+ * Raise a SIGFPE for the current process.
+ * sicode describes the signal being raised.
+ */
+void ucf64_raise_sigfpe(unsigned int sicode, struct pt_regs *regs)
+{
+	siginfo_t info;
+
+	memset(&info, 0, sizeof(info));
+
+	info.si_signo = SIGFPE;
+	info.si_code = sicode;
+	info.si_addr = (void __user *)(instruction_pointer(regs) - 4);
+
+	/*
+	 * This is the same as NWFPE, because it's not clear what
+	 * this is used for
+	 */
+	current->thread.error_code = 0;
+	current->thread.trap_no = 6;
+
+	send_sig_info(SIGFPE, &info, current);
+}
+
+/*
+ * Handle exceptions of UniCore-F64.
+ */
+void ucf64_exchandler(u32 inst, u32 fpexc, struct pt_regs *regs)
+{
+	u32 tmp = fpexc;
+	u32 exc = F64_EXCEPTION_ERROR & fpexc;
+
+	pr_debug("UniCore-F64: instruction %08x fpscr %08x\n",
+			inst, fpexc);
+
+	if (exc & FPSCR_CMPINSTR_BIT) {
+		if (exc & FPSCR_CON)
+			tmp |= FPSCR_CON;
+		else
+			tmp &= ~(FPSCR_CON);
+		exc &= ~(FPSCR_CMPINSTR_BIT | FPSCR_CON);
+	} else {
+		pr_debug(KERN_ERR "UniCore-F64 Error: unhandled exceptions\n");
+		pr_debug(KERN_ERR "UniCore-F64 FPSCR 0x%08x INST 0x%08x\n",
+				cff(FPSCR), inst);
+
+		ucf64_raise_sigfpe(0, regs);
+		return;
+	}
+
+	/*
+	 * Update the FPSCR with the additional exception flags.
+	 * Comparison instructions always return at least one of
+	 * these flags set.
+	 */
+	tmp &= ~(FPSCR_TRAP | FPSCR_IOS | FPSCR_OFS | FPSCR_UFS |
+			FPSCR_IXS | FPSCR_HIS | FPSCR_IOC | FPSCR_OFC |
+			FPSCR_UFC | FPSCR_IXC | FPSCR_HIC);
+
+	tmp |= exc;
+	ctf(FPSCR, tmp);
+}
+
+/*
+ * F64 support code initialisation.
+ */
+static int __init ucf64_init(void)
+{
+	ctf(FPSCR, 0x0);     /* FPSCR_UFE | FPSCR_NDE perhaps better */
+
+	printk(KERN_INFO "Enable UniCore-F64 support.\n");
+
+	return 0;
+}
+
+late_initcall(ucf64_init);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/gpio.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/gpio.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,122 @@
+/*
+ * linux/arch/unicore32/kernel/gpio.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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.
+ */
+/* in FPGA, no GPIO support */
+
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/gpio.h>
+#include <mach/hardware.h>
+
+#ifdef CONFIG_LEDS
+#include <linux/leds.h>
+#include <linux/platform_device.h>
+
+static const struct gpio_led puv3_gpio_leds[] = {
+	{ .name = "cpuhealth", .gpio = GPO_CPU_HEALTH, .active_low = 0,
+		.default_trigger = "heartbeat",	},
+	{ .name = "hdd_led", .gpio = GPO_HDD_LED, .active_low = 1,
+		.default_trigger = "ide-disk", },
+};
+
+static const struct gpio_led_platform_data puv3_gpio_led_data = {
+	.num_leds =	ARRAY_SIZE(puv3_gpio_leds),
+	.leds =		(void *) puv3_gpio_leds,
+};
+
+static struct platform_device puv3_gpio_gpio_leds = {
+	.name =		"leds-gpio",
+	.id =		-1,
+	.dev = {
+		.platform_data = (void *) &puv3_gpio_led_data,
+	}
+};
+
+static int __init puv3_gpio_leds_init(void)
+{
+	platform_device_register(&puv3_gpio_gpio_leds);
+	return 0;
+}
+
+device_initcall(puv3_gpio_leds_init);
+#endif
+
+static int puv3_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	return readl(GPIO_GPLR) & GPIO_GPIO(offset);
+}
+
+static void puv3_gpio_set(struct gpio_chip *chip, unsigned offset, int value)
+{
+	if (value)
+		writel(GPIO_GPIO(offset), GPIO_GPSR);
+	else
+		writel(GPIO_GPIO(offset), GPIO_GPCR);
+}
+
+static int puv3_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	writel(readl(GPIO_GPDR) & ~GPIO_GPIO(offset), GPIO_GPDR);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static int puv3_direction_output(struct gpio_chip *chip, unsigned offset,
+		int value)
+{
+	unsigned long flags;
+
+	local_irq_save(flags);
+	puv3_gpio_set(chip, offset, value);
+	writel(readl(GPIO_GPDR) | GPIO_GPIO(offset), GPIO_GPDR);
+	local_irq_restore(flags);
+	return 0;
+}
+
+static struct gpio_chip puv3_gpio_chip = {
+	.label			= "gpio",
+	.direction_input	= puv3_direction_input,
+	.direction_output	= puv3_direction_output,
+	.set			= puv3_gpio_set,
+	.get			= puv3_gpio_get,
+	.base			= 0,
+	.ngpio			= GPIO_MAX + 1,
+};
+
+void __init puv3_init_gpio(void)
+{
+	writel(GPIO_DIR, GPIO_GPDR);
+#if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)	\
+	|| defined(CONFIG_PUV3_DB0913)
+	gpio_set_value(GPO_WIFI_EN, 1);
+	gpio_set_value(GPO_HDD_LED, 1);
+	gpio_set_value(GPO_VGA_EN, 1);
+	gpio_set_value(GPO_LCD_EN, 1);
+	gpio_set_value(GPO_CAM_PWR_EN, 0);
+	gpio_set_value(GPO_LCD_VCC_EN, 1);
+	gpio_set_value(GPO_SOFT_OFF, 1);
+	gpio_set_value(GPO_BT_EN, 1);
+	gpio_set_value(GPO_FAN_ON, 0);
+	gpio_set_value(GPO_SPKR, 0);
+	gpio_set_value(GPO_CPU_HEALTH, 1);
+	gpio_set_value(GPO_LAN_SEL, 1);
+/*
+ * DO NOT modify the GPO_SET_V1 and GPO_SET_V2 in kernel
+ *	gpio_set_value(GPO_SET_V1, 1);
+ *	gpio_set_value(GPO_SET_V2, 1);
+ */
+#endif
+	gpiochip_add(&puv3_gpio_chip);
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/head.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/head.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/head.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/head.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,252 @@
+/*
+ * linux/arch/unicore32/kernel/head.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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>
+
+#include <asm/assembler.h>
+#include <asm/ptrace.h>
+#include <generated/asm-offsets.h>
+#include <asm/memory.h>
+#include <asm/thread_info.h>
+#include <asm/system.h>
+#include <asm/pgtable-hwdef.h>
+
+#if (PHYS_OFFSET & 0x003fffff)
+#error "PHYS_OFFSET must be at an even 4MiB boundary!"
+#endif
+
+#define KERNEL_RAM_VADDR	(PAGE_OFFSET + KERNEL_IMAGE_START)
+#define KERNEL_RAM_PADDR	(PHYS_OFFSET + KERNEL_IMAGE_START)
+
+#define KERNEL_PGD_PADDR	(KERNEL_RAM_PADDR - 0x1000)
+#define KERNEL_PGD_VADDR	(KERNEL_RAM_VADDR - 0x1000)
+
+#define KERNEL_START		KERNEL_RAM_VADDR
+#define KERNEL_END		_end
+
+/*
+ * swapper_pg_dir is the virtual address of the initial page table.
+ * We place the page tables 4K below KERNEL_RAM_VADDR.  Therefore, we must
+ * make sure that KERNEL_RAM_VADDR is correctly set.  Currently, we expect
+ * the least significant 16 bits to be 0x8000, but we could probably
+ * relax this restriction to KERNEL_RAM_VADDR >= PAGE_OFFSET + 0x1000.
+ */
+#if (KERNEL_RAM_VADDR & 0xffff) != 0x8000
+#error KERNEL_RAM_VADDR must start at 0xXXXX8000
+#endif
+
+	.globl	swapper_pg_dir
+	.equ	swapper_pg_dir, KERNEL_RAM_VADDR - 0x1000
+
+/*
+ * Kernel startup entry point.
+ * ---------------------------
+ *
+ * This is normally called from the decompressor code.  The requirements
+ * are: MMU = off, D-cache = off, I-cache = dont care
+ *
+ * This code is mostly position independent, so if you link the kernel at
+ * 0xc0008000, you call this at __pa(0xc0008000).
+ */
+	__HEAD
+ENTRY(stext)
+	@ set asr
+	mov	r0, #PRIV_MODE			@ ensure priv mode
+	or	r0, #PSR_R_BIT | PSR_I_BIT	@ disable irqs
+	mov.a	asr, r0
+
+	@ process identify
+	movc	r0, p0.c0, #0			@ cpuid
+	movl	r1, 0xff00ffff			@ mask
+	movl	r2, 0x4d000863			@ value
+	and	r0, r1, r0
+	cxor.a	r0, r2
+	bne	__error_p			@ invalid processor id
+
+	/*
+	 * Clear the 4K level 1 swapper page table
+	 */
+	movl	r0, #KERNEL_PGD_PADDR		@ page table address
+	mov	r1, #0
+	add	r2, r0, #0x1000
+101:	stw.w	r1, [r0]+, #4
+	stw.w	r1, [r0]+, #4
+	stw.w	r1, [r0]+, #4
+	stw.w	r1, [r0]+, #4
+	cxor.a	r0, r2
+	bne	101b
+
+	movl	r4, #KERNEL_PGD_PADDR		@ page table address
+	mov	r7, #PMD_TYPE_SECT | PMD_PRESENT	@ page size: section
+	or	r7, r7, #PMD_SECT_CACHEABLE		@ cacheable
+	or	r7, r7, #PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC
+
+	/*
+	 * Create identity mapping for first 4MB of kernel to
+	 * cater for the MMU enable.  This identity mapping
+	 * will be removed by paging_init().  We use our current program
+	 * counter to determine corresponding section base address.
+	 */
+	mov	r6, pc
+	mov	r6, r6 >> #22			@ start of kernel section
+	or	r1, r7, r6 << #22		@ flags + kernel base
+	stw	r1, [r4+], r6 << #2		@ identity mapping
+
+	/*
+	 * Now setup the pagetables for our kernel direct
+	 * mapped region.
+	 */
+	add	r0, r4,  #(KERNEL_START & 0xff000000) >> 20
+	stw.w	r1, [r0+], #(KERNEL_START & 0x00c00000) >> 20
+	movl	r6, #(KERNEL_END - 1)
+	add	r0, r0, #4
+	add	r6, r4, r6 >> #20
+102:	csub.a	r0, r6
+	add	r1, r1, #1 << 22
+	bua	103f
+	stw.w	r1, [r0]+, #4
+	b	102b
+103:
+	/*
+	 * Then map first 4MB of ram in case it contains our boot params.
+	 */
+	add	r0, r4, #PAGE_OFFSET >> 20
+	or	r6, r7, #(PHYS_OFFSET & 0xffc00000)
+	stw	r6, [r0]
+
+	ldw	r15, __switch_data		@ address to jump to after
+
+	/*
+	 * Initialise TLB, Caches, and MMU state ready to switch the MMU
+	 * on.
+	 */
+	mov	r0, #0
+	movc	p0.c5, r0, #28			@ cache invalidate all
+	nop8
+	movc	p0.c6, r0, #6			@ TLB invalidate all
+	nop8
+
+	/*
+	 * ..V. .... ..TB IDAM
+	 * ..1. .... ..01 1111
+	 */
+	movl	r0, #0x201f			@ control register setting
+
+	/*
+	 * Setup common bits before finally enabling the MMU.  Essentially
+	 * this is just loading the page table pointer and domain access
+	 * registers.
+	 */
+	#ifndef CONFIG_ALIGNMENT_TRAP
+		andn	r0, r0, #CR_A
+	#endif
+	#ifdef CONFIG_CPU_DCACHE_DISABLE
+		andn	r0, r0, #CR_D
+	#endif
+	#ifdef CONFIG_CPU_DCACHE_WRITETHROUGH
+		andn	r0, r0, #CR_B
+	#endif
+	#ifdef CONFIG_CPU_ICACHE_DISABLE
+		andn	r0, r0, #CR_I
+	#endif
+
+	movc	p0.c2, r4, #0			@ set pgd
+	b	__turn_mmu_on
+ENDPROC(stext)
+
+/*
+ * Enable the MMU.  This completely changes the structure of the visible
+ * memory space.  You will not be able to trace execution through this.
+ *
+ *  r0  = cp#0 control register
+ *  r15 = *virtual* address to jump to upon completion
+ */
+	.align	5
+__turn_mmu_on:
+	mov	r0, r0
+	movc	p0.c1, r0, #0			@ write control reg
+	nop					@ fetch inst by phys addr
+	mov	pc, r15
+	nop8					@ fetch inst by phys addr
+ENDPROC(__turn_mmu_on)
+
+/*
+ * Setup the initial page tables.  We only setup the barest
+ * amount which are required to get the kernel running, which
+ * generally means mapping in the kernel code.
+ *
+ * r9  = cpuid
+ * r10 = procinfo
+ *
+ * Returns:
+ *  r0, r3, r6, r7 corrupted
+ *  r4 = physical page table address
+ */
+	.ltorg
+
+	.align	2
+	.type	__switch_data, %object
+__switch_data:
+	.long	__mmap_switched
+	.long	__bss_start			@ r6
+	.long	_end				@ r7
+	.long	cr_alignment			@ r8
+	.long	init_thread_union + THREAD_START_SP @ sp
+
+/*
+ * The following fragment of code is executed with the MMU on in MMU mode,
+ * and uses absolute addresses; this is not position independent.
+ *
+ *  r0  = cp#0 control register
+ */
+__mmap_switched:
+	adr	r3, __switch_data + 4
+
+	ldm.w	(r6, r7, r8), [r3]+
+	ldw	sp, [r3]
+
+	mov	fp, #0				@ Clear BSS (and zero fp)
+203:	csub.a	r6, r7
+	bea	204f
+	stw.w	fp, [r6]+,#4
+	b	203b
+204:
+	andn	r1, r0, #CR_A			@ Clear 'A' bit
+	stm	(r0, r1), [r8]+			@ Save control register values
+	b	start_kernel
+ENDPROC(__mmap_switched)
+
+/*
+ * Exception handling.  Something went wrong and we can't proceed.  We
+ * ought to tell the user, but since we don't have any guarantee that
+ * we're even running on the right architecture, we do virtually nothing.
+ *
+ * If CONFIG_DEBUG_LL is set we try to print out something about the error
+ * and hope for the best (useful if bootloader fails to pass a proper
+ * machine ID for example).
+ */
+__error_p:
+#ifdef CONFIG_DEBUG_LL
+	adr	r0, str_p1
+	b.l	printascii
+	mov	r0, r9
+	b.l	printhex8
+	adr	r0, str_p2
+	b.l	printascii
+901:	nop8
+	b	901b
+str_p1:	.asciz	"\nError: unrecognized processor variant (0x"
+str_p2:	.asciz	").\n"
+	.align
+#endif
+ENDPROC(__error_p)
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/hibernate_asm.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/hibernate_asm.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/hibernate_asm.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/hibernate_asm.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,117 @@
+/*
+ * linux/arch/unicore32/kernel/hibernate_asm.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/sys.h>
+#include <linux/errno.h>
+#include <linux/linkage.h>
+#include <generated/asm-offsets.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/assembler.h>
+
+@ restore_image(pgd_t *resume_pg_dir, struct pbe *restore_pblist)
+@ r0: resume_pg_dir
+@ r1: restore_pblist
+@ copy restore_pblist pages
+@ restore registers from swsusp_arch_regs_cpu0
+@
+ENTRY(restore_image)
+	sub	r0, r0, #PAGE_OFFSET
+	mov	r5, #0
+	movc	p0.c6, r5, #6	@invalidate ITLB & DTLB
+	movc	p0.c2, r0, #0
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+	.p2align 4,,7
+101:
+	csub.a	r1, #0
+	beq	109f
+
+	ldw	r6, [r1+], #PBE_ADDRESS
+	ldw	r7, [r1+], #PBE_ORIN_ADDRESS
+
+	movl	ip, #128
+102:	ldm.w	(r8 - r15), [r6]+
+	stm.w	(r8 - r15), [r7]+
+	sub.a	ip, ip, #1
+	bne	102b
+
+	ldw	r1, [r1+], #PBE_NEXT
+	b	101b
+
+	.p2align 4,,7
+109:
+	/* go back to the original page tables */
+	ldw	r0, =swapper_pg_dir
+	sub	r0, r0, #PAGE_OFFSET
+	mov	r5, #0
+	movc	p0.c6, r5, #6
+	movc	p0.c2, r0, #0
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+	nop
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_FPSTATE
+	lfm.w	(f0  - f7 ), [ip]+
+	lfm.w	(f8  - f15), [ip]+
+	lfm.w	(f16 - f23), [ip]+
+	lfm.w	(f24 - f31), [ip]+
+	ldw	r4, [ip]
+	ctf	r4, s31
+#endif
+	mov	r0, #0x0
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_CPU
+	ldm.w	(r4 - r15), [ip]+
+	ldm	(r16 - r27, sp, pc), [ip]+	@ Load all regs saved previously
+
+	.align	2
+1:	.long	swsusp_arch_regs_cpu0
+
+
+@ swsusp_arch_suspend()
+@ - prepare pc for resume, return from function without swsusp_save on resume
+@ - save registers in swsusp_arch_regs_cpu0
+@ - call swsusp_save write suspend image
+
+ENTRY(swsusp_arch_suspend)
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_CPU
+	stm.w	(r4 - r15), [ip]+
+	stm.w	(r16 - r27, sp, lr), [ip]+
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	ldw	ip, 1f
+	add	ip, ip, #SWSUSP_FPSTATE
+	sfm.w	(f0  - f7 ), [ip]+
+	sfm.w	(f8  - f15), [ip]+
+	sfm.w	(f16 - f23), [ip]+
+	sfm.w	(f24 - f31), [ip]+
+	cff	r4, s31
+	stw	r4, [ip]
+#endif
+	b	swsusp_save			@ no return
+
+1:	.long	swsusp_arch_regs_cpu0
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/hibernate.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/hibernate.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/hibernate.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/hibernate.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,160 @@
+/*
+ *  linux/arch/unicore32/kernel/hibernate.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/gfp.h>
+#include <linux/suspend.h>
+#include <linux/bootmem.h>
+
+#include <asm/system.h>
+#include <asm/page.h>
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
+#include <asm/suspend.h>
+
+#include "mach/pm.h"
+
+/* Pointer to the temporary resume page tables */
+pgd_t *resume_pg_dir;
+
+struct swsusp_arch_regs swsusp_arch_regs_cpu0;
+
+/*
+ * Create a middle page table on a resume-safe page and put a pointer to it in
+ * the given global directory entry.  This only returns the gd entry
+ * in non-PAE compilation mode, since the middle layer is folded.
+ */
+static pmd_t *resume_one_md_table_init(pgd_t *pgd)
+{
+	pud_t *pud;
+	pmd_t *pmd_table;
+
+	pud = pud_offset(pgd, 0);
+	pmd_table = pmd_offset(pud, 0);
+
+	return pmd_table;
+}
+
+/*
+ * Create a page table on a resume-safe page and place a pointer to it in
+ * a middle page directory entry.
+ */
+static pte_t *resume_one_page_table_init(pmd_t *pmd)
+{
+	if (pmd_none(*pmd)) {
+		pte_t *page_table = (pte_t *)get_safe_page(GFP_ATOMIC);
+		if (!page_table)
+			return NULL;
+
+		set_pmd(pmd, __pmd(__pa(page_table) | _PAGE_KERNEL_TABLE));
+
+		BUG_ON(page_table != pte_offset_kernel(pmd, 0));
+
+		return page_table;
+	}
+
+	return pte_offset_kernel(pmd, 0);
+}
+
+/*
+ * This maps the physical memory to kernel virtual address space, a total
+ * of max_low_pfn pages, by creating page tables starting from address
+ * PAGE_OFFSET.  The page tables are allocated out of resume-safe pages.
+ */
+static int resume_physical_mapping_init(pgd_t *pgd_base)
+{
+	unsigned long pfn;
+	pgd_t *pgd;
+	pmd_t *pmd;
+	pte_t *pte;
+	int pgd_idx, pmd_idx;
+
+	pgd_idx = pgd_index(PAGE_OFFSET);
+	pgd = pgd_base + pgd_idx;
+	pfn = 0;
+
+	for (; pgd_idx < PTRS_PER_PGD; pgd++, pgd_idx++) {
+		pmd = resume_one_md_table_init(pgd);
+		if (!pmd)
+			return -ENOMEM;
+
+		if (pfn >= max_low_pfn)
+			continue;
+
+		for (pmd_idx = 0; pmd_idx < PTRS_PER_PMD; pmd++, pmd_idx++) {
+			pte_t *max_pte;
+
+			if (pfn >= max_low_pfn)
+				break;
+
+			/* Map with normal page tables.
+			 * NOTE: We can mark everything as executable here
+			 */
+			pte = resume_one_page_table_init(pmd);
+			if (!pte)
+				return -ENOMEM;
+
+			max_pte = pte + PTRS_PER_PTE;
+			for (; pte < max_pte; pte++, pfn++) {
+				if (pfn >= max_low_pfn)
+					break;
+
+				set_pte(pte, pfn_pte(pfn, PAGE_KERNEL_EXEC));
+			}
+		}
+	}
+
+	return 0;
+}
+
+static inline void resume_init_first_level_page_table(pgd_t *pg_dir)
+{
+}
+
+int swsusp_arch_resume(void)
+{
+	int error;
+
+	resume_pg_dir = (pgd_t *)get_safe_page(GFP_ATOMIC);
+	if (!resume_pg_dir)
+		return -ENOMEM;
+
+	resume_init_first_level_page_table(resume_pg_dir);
+	error = resume_physical_mapping_init(resume_pg_dir);
+	if (error)
+		return error;
+
+	/* We have got enough memory and from now on we cannot recover */
+	restore_image(resume_pg_dir, restore_pblist);
+	return 0;
+}
+
+/*
+ *	pfn_is_nosave - check if given pfn is in the 'nosave' section
+ */
+
+int pfn_is_nosave(unsigned long pfn)
+{
+	unsigned long begin_pfn = __pa(&__nosave_begin) >> PAGE_SHIFT;
+	unsigned long end_pfn = PAGE_ALIGN(__pa(&__nosave_end)) >> PAGE_SHIFT;
+
+	return (pfn >= begin_pfn) && (pfn < end_pfn);
+}
+
+void save_processor_state(void)
+{
+}
+
+void restore_processor_state(void)
+{
+	local_flush_tlb_all();
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/init_task.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/init_task.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/init_task.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/init_task.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,44 @@
+/*
+ * linux/arch/unicore32/kernel/init_task.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/mm.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/sched.h>
+#include <linux/init.h>
+#include <linux/init_task.h>
+#include <linux/mqueue.h>
+#include <linux/uaccess.h>
+
+#include <asm/pgtable.h>
+
+static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
+static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
+/*
+ * Initial thread structure.
+ *
+ * We need to make sure that this is 8192-byte aligned due to the
+ * way process stacks are handled. This is done by making sure
+ * the linker maps this in the .text segment right after head.S,
+ * and making head.S ensure the proper alignment.
+ *
+ * The things we do for performance..
+ */
+union thread_union init_thread_union __init_task_data = {
+	INIT_THREAD_INFO(init_task) };
+
+/*
+ * Initial task structure.
+ *
+ * All other task structs will be allocated on slabs in fork.c
+ */
+struct task_struct init_task = INIT_TASK(init_task);
+EXPORT_SYMBOL(init_task);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/irq.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,384 @@
+/*
+ * linux/arch/unicore32/kernel/irq.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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_stat.h>
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/ioport.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/random.h>
+#include <linux/smp.h>
+#include <linux/init.h>
+#include <linux/seq_file.h>
+#include <linux/errno.h>
+#include <linux/list.h>
+#include <linux/kallsyms.h>
+#include <linux/proc_fs.h>
+#include <linux/sysdev.h>
+#include <linux/gpio.h>
+
+#include <asm/system.h>
+#include <mach/hardware.h>
+
+#include "setup.h"
+
+/*
+ * PKUnity GPIO edge detection for IRQs:
+ * IRQs are generated on Falling-Edge, Rising-Edge, or both.
+ * Use this instead of directly setting GRER/GFER.
+ */
+static int GPIO_IRQ_rising_edge;
+static int GPIO_IRQ_falling_edge;
+static int GPIO_IRQ_mask = 0;
+
+#define GPIO_MASK(irq)		(1 << (irq - IRQ_GPIO0))
+
+static int puv3_gpio_type(struct irq_data *d, unsigned int type)
+{
+	unsigned int mask;
+
+	if (d->irq < IRQ_GPIOHIGH)
+		mask = 1 << d->irq;
+	else
+		mask = GPIO_MASK(d->irq);
+
+	if (type == IRQ_TYPE_PROBE) {
+		if ((GPIO_IRQ_rising_edge | GPIO_IRQ_falling_edge) & mask)
+			return 0;
+		type = IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING;
+	}
+
+	if (type & IRQ_TYPE_EDGE_RISING)
+		GPIO_IRQ_rising_edge |= mask;
+	else
+		GPIO_IRQ_rising_edge &= ~mask;
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		GPIO_IRQ_falling_edge |= mask;
+	else
+		GPIO_IRQ_falling_edge &= ~mask;
+
+	writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
+	writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+
+	return 0;
+}
+
+/*
+ * GPIO IRQs must be acknowledged.  This is for IRQs from 0 to 7.
+ */
+static void puv3_low_gpio_ack(struct irq_data *d)
+{
+	writel((1 << d->irq), GPIO_GEDR);
+}
+
+static void puv3_low_gpio_mask(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
+}
+
+static void puv3_low_gpio_unmask(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
+}
+
+static int puv3_low_gpio_wake(struct irq_data *d, unsigned int on)
+{
+	if (on)
+		writel(readl(PM_PWER) | (1 << d->irq), PM_PWER);
+	else
+		writel(readl(PM_PWER) & ~(1 << d->irq), PM_PWER);
+	return 0;
+}
+
+static struct irq_chip puv3_low_gpio_chip = {
+	.name		= "GPIO-low",
+	.irq_ack	= puv3_low_gpio_ack,
+	.irq_mask	= puv3_low_gpio_mask,
+	.irq_unmask	= puv3_low_gpio_unmask,
+	.irq_set_type	= puv3_gpio_type,
+	.irq_set_wake	= puv3_low_gpio_wake,
+};
+
+/*
+ * IRQ8 (GPIO0 through 27) handler.  We enter here with the
+ * irq_controller_lock held, and IRQs disabled.  Decode the IRQ
+ * and call the handler.
+ */
+static void
+puv3_gpio_handler(unsigned int irq, struct irq_desc *desc)
+{
+	unsigned int mask;
+
+	mask = readl(GPIO_GEDR);
+	do {
+		/*
+		 * clear down all currently active IRQ sources.
+		 * We will be processing them all.
+		 */
+		writel(mask, GPIO_GEDR);
+
+		irq = IRQ_GPIO0;
+		do {
+			if (mask & 1)
+				generic_handle_irq(irq);
+			mask >>= 1;
+			irq++;
+		} while (mask);
+		mask = readl(GPIO_GEDR);
+	} while (mask);
+}
+
+/*
+ * GPIO0-27 edge IRQs need to be handled specially.
+ * In addition, the IRQs are all collected up into one bit in the
+ * interrupt controller registers.
+ */
+static void puv3_high_gpio_ack(struct irq_data *d)
+{
+	unsigned int mask = GPIO_MASK(d->irq);
+
+	writel(mask, GPIO_GEDR);
+}
+
+static void puv3_high_gpio_mask(struct irq_data *d)
+{
+	unsigned int mask = GPIO_MASK(d->irq);
+
+	GPIO_IRQ_mask &= ~mask;
+
+	writel(readl(GPIO_GRER) & ~mask, GPIO_GRER);
+	writel(readl(GPIO_GFER) & ~mask, GPIO_GFER);
+}
+
+static void puv3_high_gpio_unmask(struct irq_data *d)
+{
+	unsigned int mask = GPIO_MASK(d->irq);
+
+	GPIO_IRQ_mask |= mask;
+
+	writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
+	writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+}
+
+static int puv3_high_gpio_wake(struct irq_data *d, unsigned int on)
+{
+	if (on)
+		writel(readl(PM_PWER) | PM_PWER_GPIOHIGH, PM_PWER);
+	else
+		writel(readl(PM_PWER) & ~PM_PWER_GPIOHIGH, PM_PWER);
+	return 0;
+}
+
+static struct irq_chip puv3_high_gpio_chip = {
+	.name		= "GPIO-high",
+	.irq_ack	= puv3_high_gpio_ack,
+	.irq_mask	= puv3_high_gpio_mask,
+	.irq_unmask	= puv3_high_gpio_unmask,
+	.irq_set_type	= puv3_gpio_type,
+	.irq_set_wake	= puv3_high_gpio_wake,
+};
+
+/*
+ * We don't need to ACK IRQs on the PKUnity unless they're GPIOs
+ * this is for internal IRQs i.e. from 8 to 31.
+ */
+static void puv3_mask_irq(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) & ~(1 << d->irq), INTC_ICMR);
+}
+
+static void puv3_unmask_irq(struct irq_data *d)
+{
+	writel(readl(INTC_ICMR) | (1 << d->irq), INTC_ICMR);
+}
+
+/*
+ * Apart form GPIOs, only the RTC alarm can be a wakeup event.
+ */
+static int puv3_set_wake(struct irq_data *d, unsigned int on)
+{
+	if (d->irq == IRQ_RTCAlarm) {
+		if (on)
+			writel(readl(PM_PWER) | PM_PWER_RTC, PM_PWER);
+		else
+			writel(readl(PM_PWER) & ~PM_PWER_RTC, PM_PWER);
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static struct irq_chip puv3_normal_chip = {
+	.name		= "PKUnity-v3",
+	.irq_ack	= puv3_mask_irq,
+	.irq_mask	= puv3_mask_irq,
+	.irq_unmask	= puv3_unmask_irq,
+	.irq_set_wake	= puv3_set_wake,
+};
+
+static struct resource irq_resource = {
+	.name	= "irqs",
+	.start	= io_v2p(PKUNITY_INTC_BASE),
+	.end	= io_v2p(PKUNITY_INTC_BASE) + 0xFFFFF,
+};
+
+static struct puv3_irq_state {
+	unsigned int	saved;
+	unsigned int	icmr;
+	unsigned int	iclr;
+	unsigned int	iccr;
+} puv3_irq_state;
+
+static int puv3_irq_suspend(struct sys_device *dev, pm_message_t state)
+{
+	struct puv3_irq_state *st = &puv3_irq_state;
+
+	st->saved = 1;
+	st->icmr = readl(INTC_ICMR);
+	st->iclr = readl(INTC_ICLR);
+	st->iccr = readl(INTC_ICCR);
+
+	/*
+	 * Disable all GPIO-based interrupts.
+	 */
+	writel(readl(INTC_ICMR) & ~(0x1ff), INTC_ICMR);
+
+	/*
+	 * Set the appropriate edges for wakeup.
+	 */
+	writel(readl(PM_PWER) & GPIO_IRQ_rising_edge, GPIO_GRER);
+	writel(readl(PM_PWER) & GPIO_IRQ_falling_edge, GPIO_GFER);
+
+	/*
+	 * Clear any pending GPIO interrupts.
+	 */
+	writel(readl(GPIO_GEDR), GPIO_GEDR);
+
+	return 0;
+}
+
+static int puv3_irq_resume(struct sys_device *dev)
+{
+	struct puv3_irq_state *st = &puv3_irq_state;
+
+	if (st->saved) {
+		writel(st->iccr, INTC_ICCR);
+		writel(st->iclr, INTC_ICLR);
+
+		writel(GPIO_IRQ_rising_edge & GPIO_IRQ_mask, GPIO_GRER);
+		writel(GPIO_IRQ_falling_edge & GPIO_IRQ_mask, GPIO_GFER);
+
+		writel(st->icmr, INTC_ICMR);
+	}
+	return 0;
+}
+
+static struct sysdev_class puv3_irq_sysclass = {
+	.name		= "pkunity-irq",
+	.suspend	= puv3_irq_suspend,
+	.resume		= puv3_irq_resume,
+};
+
+static struct sys_device puv3_irq_device = {
+	.id		= 0,
+	.cls		= &puv3_irq_sysclass,
+};
+
+static int __init puv3_irq_init_devicefs(void)
+{
+	sysdev_class_register(&puv3_irq_sysclass);
+	return sysdev_register(&puv3_irq_device);
+}
+
+device_initcall(puv3_irq_init_devicefs);
+
+void __init init_IRQ(void)
+{
+	unsigned int irq;
+
+	request_resource(&iomem_resource, &irq_resource);
+
+	/* disable all IRQs */
+	writel(0, INTC_ICMR);
+
+	/* all IRQs are IRQ, not REAL */
+	writel(0, INTC_ICLR);
+
+	/* clear all GPIO edge detects */
+	writel(FMASK(8, 0) & ~FIELD(1, 1, GPI_SOFF_REQ), GPIO_GPIR);
+	writel(0, GPIO_GFER);
+	writel(0, GPIO_GRER);
+	writel(0x0FFFFFFF, GPIO_GEDR);
+
+	writel(1, INTC_ICCR);
+
+	for (irq = 0; irq < IRQ_GPIOHIGH; irq++) {
+		irq_set_chip(irq, &puv3_low_gpio_chip);
+		irq_set_handler(irq, handle_edge_irq);
+		irq_modify_status(irq,
+			IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
+			0);
+	}
+
+	for (irq = IRQ_GPIOHIGH + 1; irq < IRQ_GPIO0; irq++) {
+		irq_set_chip(irq, &puv3_normal_chip);
+		irq_set_handler(irq, handle_level_irq);
+		irq_modify_status(irq,
+			IRQ_NOREQUEST | IRQ_NOAUTOEN,
+			IRQ_NOPROBE);
+	}
+
+	for (irq = IRQ_GPIO0; irq <= IRQ_GPIO27; irq++) {
+		irq_set_chip(irq, &puv3_high_gpio_chip);
+		irq_set_handler(irq, handle_edge_irq);
+		irq_modify_status(irq,
+			IRQ_NOREQUEST | IRQ_NOPROBE | IRQ_NOAUTOEN,
+			0);
+	}
+
+	/*
+	 * Install handler for GPIO 0-27 edge detect interrupts
+	 */
+	irq_set_chip(IRQ_GPIOHIGH, &puv3_normal_chip);
+	irq_set_chained_handler(IRQ_GPIOHIGH, puv3_gpio_handler);
+
+#ifdef CONFIG_PUV3_GPIO
+	puv3_init_gpio();
+#endif
+}
+
+/*
+ * do_IRQ handles all hardware IRQ's.  Decoded IRQs should not
+ * come via this function.  Instead, they should provide their
+ * own 'handler'
+ */
+asmlinkage void asm_do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+	struct pt_regs *old_regs = set_irq_regs(regs);
+
+	irq_enter();
+
+	/*
+	 * Some hardware gives randomly wrong interrupts.  Rather
+	 * than crashing, do something sensible.
+	 */
+	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);
+	}
+
+	irq_exit();
+	set_irq_regs(old_regs);
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/ksyms.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/ksyms.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/ksyms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/ksyms.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,99 @@
+/*
+ * linux/arch/unicore32/kernel/ksyms.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/sched.h>
+#include <linux/string.h>
+#include <linux/cryptohash.h>
+#include <linux/delay.h>
+#include <linux/in6.h>
+#include <linux/syscalls.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/checksum.h>
+#include <asm/system.h>
+
+#include "ksyms.h"
+
+EXPORT_SYMBOL(__uc32_find_next_zero_bit);
+EXPORT_SYMBOL(__uc32_find_next_bit);
+
+EXPORT_SYMBOL(__backtrace);
+
+	/* platform dependent support */
+EXPORT_SYMBOL(__udelay);
+EXPORT_SYMBOL(__const_udelay);
+
+	/* networking */
+EXPORT_SYMBOL(csum_partial);
+EXPORT_SYMBOL(csum_partial_copy_from_user);
+EXPORT_SYMBOL(csum_partial_copy_nocheck);
+EXPORT_SYMBOL(__csum_ipv6_magic);
+
+	/* io */
+#ifndef __raw_readsb
+EXPORT_SYMBOL(__raw_readsb);
+#endif
+#ifndef __raw_readsw
+EXPORT_SYMBOL(__raw_readsw);
+#endif
+#ifndef __raw_readsl
+EXPORT_SYMBOL(__raw_readsl);
+#endif
+#ifndef __raw_writesb
+EXPORT_SYMBOL(__raw_writesb);
+#endif
+#ifndef __raw_writesw
+EXPORT_SYMBOL(__raw_writesw);
+#endif
+#ifndef __raw_writesl
+EXPORT_SYMBOL(__raw_writesl);
+#endif
+
+	/* string / mem functions */
+EXPORT_SYMBOL(strchr);
+EXPORT_SYMBOL(strrchr);
+EXPORT_SYMBOL(memset);
+EXPORT_SYMBOL(memcpy);
+EXPORT_SYMBOL(memmove);
+EXPORT_SYMBOL(memchr);
+
+	/* user mem (segment) */
+EXPORT_SYMBOL(__strnlen_user);
+EXPORT_SYMBOL(__strncpy_from_user);
+
+EXPORT_SYMBOL(copy_page);
+
+EXPORT_SYMBOL(__copy_from_user);
+EXPORT_SYMBOL(__copy_to_user);
+EXPORT_SYMBOL(__clear_user);
+
+EXPORT_SYMBOL(__get_user_1);
+EXPORT_SYMBOL(__get_user_2);
+EXPORT_SYMBOL(__get_user_4);
+
+EXPORT_SYMBOL(__put_user_1);
+EXPORT_SYMBOL(__put_user_2);
+EXPORT_SYMBOL(__put_user_4);
+EXPORT_SYMBOL(__put_user_8);
+
+EXPORT_SYMBOL(__ashldi3);
+EXPORT_SYMBOL(__ashrdi3);
+EXPORT_SYMBOL(__divsi3);
+EXPORT_SYMBOL(__lshrdi3);
+EXPORT_SYMBOL(__modsi3);
+EXPORT_SYMBOL(__muldi3);
+EXPORT_SYMBOL(__ucmpdi2);
+EXPORT_SYMBOL(__udivsi3);
+EXPORT_SYMBOL(__umodsi3);
+EXPORT_SYMBOL(__bswapsi2);
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/ksyms.h linux-libre-2.6.39-gnu/arch/unicore32/kernel/ksyms.h
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/ksyms.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/ksyms.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,15 @@
+/*
+ * libgcc functions - functions that are used internally by the
+ * compiler...  (prototypes are not correct though, but that
+ * doesn't really matter since they're not versioned).
+ */
+extern void __ashldi3(void);
+extern void __ashrdi3(void);
+extern void __divsi3(void);
+extern void __lshrdi3(void);
+extern void __modsi3(void);
+extern void __muldi3(void);
+extern void __ucmpdi2(void);
+extern void __udivsi3(void);
+extern void __umodsi3(void);
+extern void __bswapsi2(void);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/Makefile linux-libre-2.6.39-gnu/arch/unicore32/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,33 @@
+#
+# Makefile for the linux kernel.
+#
+
+# Object file lists.
+obj-y				:= dma.o elf.o entry.o process.o ptrace.o
+obj-y				+= setup.o signal.o sys.o stacktrace.o traps.o
+
+obj-$(CONFIG_MODULES)		+= ksyms.o module.o
+obj-$(CONFIG_EARLY_PRINTK)	+= early_printk.o
+
+obj-$(CONFIG_CPU_FREQ)		+= cpu-ucv2.o
+obj-$(CONFIG_UNICORE_FPU_F64)	+= fpu-ucf64.o
+
+# obj-y for architecture PKUnity v3
+obj-$(CONFIG_ARCH_PUV3)		+= clock.o irq.o time.o
+
+obj-$(CONFIG_PUV3_GPIO)		+= gpio.o
+obj-$(CONFIG_PUV3_RTC)		+= rtc.o
+obj-$(CONFIG_PUV3_PWM)		+= pwm.o
+obj-$(CONFIG_PUV3_PM)		+= pm.o sleep.o
+obj-$(CONFIG_HIBERNATION)	+= hibernate.o hibernate_asm.o
+
+obj-$(CONFIG_PCI)		+= pci.o
+
+# obj-y for specific machines
+obj-$(CONFIG_ARCH_PUV3)		+= puv3-core.o
+obj-$(CONFIG_PUV3_NB0916)	+= puv3-nb0916.o
+
+head-y				:= head.o
+obj-$(CONFIG_DEBUG_LL)		+= debug.o
+
+extra-y				:= $(head-y) init_task.o vmlinux.lds
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/module.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/module.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/module.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/module.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,152 @@
+/*
+ * linux/arch/unicore32/kernel/module.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/moduleloader.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/elf.h>
+#include <linux/vmalloc.h>
+#include <linux/fs.h>
+#include <linux/string.h>
+#include <linux/gfp.h>
+
+#include <asm/pgtable.h>
+#include <asm/sections.h>
+
+void *module_alloc(unsigned long size)
+{
+	struct vm_struct *area;
+
+	size = PAGE_ALIGN(size);
+	if (!size)
+		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);
+}
+
+void module_free(struct module *module, void *region)
+{
+	vfree(region);
+}
+
+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 relindex, struct module *module)
+{
+	Elf32_Shdr *symsec = sechdrs + symindex;
+	Elf32_Shdr *relsec = sechdrs + relindex;
+	Elf32_Shdr *dstsec = sechdrs + relsec->sh_info;
+	Elf32_Rel *rel = (void *)relsec->sh_addr;
+	unsigned int i;
+
+	for (i = 0; i < relsec->sh_size / sizeof(Elf32_Rel); i++, rel++) {
+		unsigned long loc;
+		Elf32_Sym *sym;
+		s32 offset;
+
+		offset = ELF32_R_SYM(rel->r_info);
+		if (offset < 0 || offset >
+				(symsec->sh_size / sizeof(Elf32_Sym))) {
+			printk(KERN_ERR "%s: bad relocation, "
+					"section %d reloc %d\n",
+					module->name, relindex, i);
+			return -ENOEXEC;
+		}
+
+		sym = ((Elf32_Sym *)symsec->sh_addr) + offset;
+
+		if (rel->r_offset < 0 || rel->r_offset >
+				dstsec->sh_size - sizeof(u32)) {
+			printk(KERN_ERR "%s: out of bounds relocation, "
+				"section %d reloc %d offset %d size %d\n",
+				module->name, relindex, i, rel->r_offset,
+				dstsec->sh_size);
+			return -ENOEXEC;
+		}
+
+		loc = dstsec->sh_addr + rel->r_offset;
+
+		switch (ELF32_R_TYPE(rel->r_info)) {
+		case R_UNICORE_NONE:
+			/* ignore */
+			break;
+
+		case R_UNICORE_ABS32:
+			*(u32 *)loc += sym->st_value;
+			break;
+
+		case R_UNICORE_PC24:
+		case R_UNICORE_CALL:
+		case R_UNICORE_JUMP24:
+			offset = (*(u32 *)loc & 0x00ffffff) << 2;
+			if (offset & 0x02000000)
+				offset -= 0x04000000;
+
+			offset += sym->st_value - loc;
+			if (offset & 3 ||
+			    offset <= (s32)0xfe000000 ||
+			    offset >= (s32)0x02000000) {
+				printk(KERN_ERR
+				       "%s: relocation out of range, section "
+				       "%d reloc %d sym '%s'\n", module->name,
+				       relindex, i, strtab + sym->st_name);
+				return -ENOEXEC;
+			}
+
+			offset >>= 2;
+
+			*(u32 *)loc &= 0xff000000;
+			*(u32 *)loc |= offset & 0x00ffffff;
+			break;
+
+		default:
+			printk(KERN_ERR "%s: unknown relocation: %u\n",
+			       module->name, ELF32_R_TYPE(rel->r_info));
+			return -ENOEXEC;
+		}
+	}
+	return 0;
+}
+
+int
+apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
+		   unsigned int symindex, unsigned int relsec,
+		   struct module *module)
+{
+	printk(KERN_ERR "module %s: ADD RELOCATION unsupported\n",
+	       module->name);
+	return -ENOEXEC;
+}
+
+int
+module_finalize(const Elf32_Ehdr *hdr, const Elf_Shdr *sechdrs,
+		struct module *module)
+{
+	return 0;
+}
+
+void
+module_arch_cleanup(struct module *mod)
+{
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/pci.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/pci.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,404 @@
+/*
+ * linux/arch/unicore32/kernel/pci.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  PCI bios-type initialisation for PCI machines
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/io.h>
+
+static int debug_pci;
+static int use_firmware;
+
+#define CONFIG_CMD(bus, devfn, where)	\
+	(0x80000000 | (bus->number << 16) | (devfn << 8) | (where & ~3))
+
+static int
+puv3_read_config(struct pci_bus *bus, unsigned int devfn, int where,
+			int size, u32 *value)
+{
+	writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR);
+	switch (size) {
+	case 1:
+		*value = (readl(PCICFG_DATA) >> ((where & 3) * 8)) & 0xFF;
+		break;
+	case 2:
+		*value = (readl(PCICFG_DATA) >> ((where & 2) * 8)) & 0xFFFF;
+		break;
+	case 4:
+		*value = readl(PCICFG_DATA);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+static int
+puv3_write_config(struct pci_bus *bus, unsigned int devfn, int where,
+			int size, u32 value)
+{
+	writel(CONFIG_CMD(bus, devfn, where), PCICFG_ADDR);
+	switch (size) {
+	case 1:
+		writel((readl(PCICFG_DATA) & ~FMASK(8, (where&3)*8))
+			| FIELD(value, 8, (where&3)*8), PCICFG_DATA);
+		break;
+	case 2:
+		writel((readl(PCICFG_DATA) & ~FMASK(16, (where&2)*8))
+			| FIELD(value, 16, (where&2)*8), PCICFG_DATA);
+		break;
+	case 4:
+		writel(value, PCICFG_DATA);
+		break;
+	}
+	return PCIBIOS_SUCCESSFUL;
+}
+
+struct pci_ops pci_puv3_ops = {
+	.read  = puv3_read_config,
+	.write = puv3_write_config,
+};
+
+void pci_puv3_preinit(void)
+{
+	printk(KERN_DEBUG "PCI: PKUnity PCI Controller Initializing ...\n");
+	/* config PCI bridge base */
+	writel(io_v2p(PKUNITY_PCIBRI_BASE), PCICFG_BRIBASE);
+
+	writel(0, PCIBRI_AHBCTL0);
+	writel(io_v2p(PKUNITY_PCIBRI_BASE) | PCIBRI_BARx_MEM, PCIBRI_AHBBAR0);
+	writel(0xFFFF0000, PCIBRI_AHBAMR0);
+	writel(0, PCIBRI_AHBTAR0);
+
+	writel(PCIBRI_CTLx_AT, PCIBRI_AHBCTL1);
+	writel(io_v2p(PKUNITY_PCILIO_BASE) | PCIBRI_BARx_IO, PCIBRI_AHBBAR1);
+	writel(0xFFFF0000, PCIBRI_AHBAMR1);
+	writel(0x00000000, PCIBRI_AHBTAR1);
+
+	writel(PCIBRI_CTLx_PREF, PCIBRI_AHBCTL2);
+	writel(io_v2p(PKUNITY_PCIMEM_BASE) | PCIBRI_BARx_MEM, PCIBRI_AHBBAR2);
+	writel(0xF8000000, PCIBRI_AHBAMR2);
+	writel(0, PCIBRI_AHBTAR2);
+
+	writel(io_v2p(PKUNITY_PCIAHB_BASE) | PCIBRI_BARx_MEM, PCIBRI_BAR1);
+
+	writel(PCIBRI_CTLx_AT | PCIBRI_CTLx_PREF, PCIBRI_PCICTL0);
+	writel(io_v2p(PKUNITY_PCIAHB_BASE) | PCIBRI_BARx_MEM, PCIBRI_PCIBAR0);
+	writel(0xF8000000, PCIBRI_PCIAMR0);
+	writel(PKUNITY_SDRAM_BASE, PCIBRI_PCITAR0);
+
+	writel(readl(PCIBRI_CMD) | PCIBRI_CMD_IO | PCIBRI_CMD_MEM, PCIBRI_CMD);
+}
+
+static int __init pci_puv3_map_irq(struct pci_dev *dev, u8 slot, u8 pin)
+{
+	if (dev->bus->number == 0) {
+#ifdef CONFIG_ARCH_FPGA /* 4 pci slots */
+		if      (dev->devfn == 0x00)
+			return IRQ_PCIINTA;
+		else if (dev->devfn == 0x08)
+			return IRQ_PCIINTB;
+		else if (dev->devfn == 0x10)
+			return IRQ_PCIINTC;
+		else if (dev->devfn == 0x18)
+			return IRQ_PCIINTD;
+#endif
+#ifdef CONFIG_PUV3_DB0913 /* 3 pci slots */
+		if      (dev->devfn == 0x30)
+			return IRQ_PCIINTB;
+		else if (dev->devfn == 0x60)
+			return IRQ_PCIINTC;
+		else if (dev->devfn == 0x58)
+			return IRQ_PCIINTD;
+#endif
+#if	defined(CONFIG_PUV3_NB0916) || defined(CONFIG_PUV3_SMW0919)
+		/* only support 2 pci devices */
+		if      (dev->devfn == 0x00)
+			return IRQ_PCIINTC; /* sata */
+#endif
+	}
+	return -1;
+}
+
+/*
+ * Only first 128MB of memory can be accessed via PCI.
+ * We use GFP_DMA to allocate safe buffers to do map/unmap.
+ * This is really ugly and we need a better way of specifying
+ * DMA-capable regions of memory.
+ */
+void __init puv3_pci_adjust_zones(unsigned long *zone_size,
+	unsigned long *zhole_size)
+{
+	unsigned int sz = SZ_128M >> PAGE_SHIFT;
+
+	/*
+	 * Only adjust if > 128M on current system
+	 */
+	if (zone_size[0] <= sz)
+		return;
+
+	zone_size[1] = zone_size[0] - sz;
+	zone_size[0] = sz;
+	zhole_size[1] = zhole_size[0];
+	zhole_size[0] = 0;
+}
+
+void __devinit pcibios_update_irq(struct pci_dev *dev, int irq)
+{
+	if (debug_pci)
+		printk(KERN_DEBUG "PCI: Assigning IRQ %02d to %s\n",
+				irq, pci_name(dev));
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, irq);
+}
+
+/*
+ * If the bus contains any of these devices, then we must not turn on
+ * parity checking of any kind.
+ */
+static inline int pdev_bad_for_parity(struct pci_dev *dev)
+{
+	return 0;
+}
+
+/*
+ * pcibios_fixup_bus - Called after each bus is probed,
+ * but before its children are examined.
+ */
+void __devinit pcibios_fixup_bus(struct pci_bus *bus)
+{
+	struct pci_dev *dev;
+	u16 features = PCI_COMMAND_SERR
+		| PCI_COMMAND_PARITY
+		| PCI_COMMAND_FAST_BACK;
+
+	bus->resource[0] = &ioport_resource;
+	bus->resource[1] = &iomem_resource;
+
+	/*
+	 * Walk the devices on this bus, working out what we can
+	 * and can't support.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 status;
+
+		pci_read_config_word(dev, PCI_STATUS, &status);
+
+		/*
+		 * If any device on this bus does not support fast back
+		 * to back transfers, then the bus as a whole is not able
+		 * to support them.  Having fast back to back transfers
+		 * on saves us one PCI cycle per transaction.
+		 */
+		if (!(status & PCI_STATUS_FAST_BACK))
+			features &= ~PCI_COMMAND_FAST_BACK;
+
+		if (pdev_bad_for_parity(dev))
+			features &= ~(PCI_COMMAND_SERR
+					| PCI_COMMAND_PARITY);
+
+		switch (dev->class >> 8) {
+		case PCI_CLASS_BRIDGE_PCI:
+			pci_read_config_word(dev, PCI_BRIDGE_CONTROL, &status);
+			status |= PCI_BRIDGE_CTL_PARITY
+				| PCI_BRIDGE_CTL_MASTER_ABORT;
+			status &= ~(PCI_BRIDGE_CTL_BUS_RESET
+				| PCI_BRIDGE_CTL_FAST_BACK);
+			pci_write_config_word(dev, PCI_BRIDGE_CONTROL, status);
+			break;
+
+		case PCI_CLASS_BRIDGE_CARDBUS:
+			pci_read_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+					&status);
+			status |= PCI_CB_BRIDGE_CTL_PARITY
+				| PCI_CB_BRIDGE_CTL_MASTER_ABORT;
+			pci_write_config_word(dev, PCI_CB_BRIDGE_CONTROL,
+					status);
+			break;
+		}
+	}
+
+	/*
+	 * Now walk the devices again, this time setting them up.
+	 */
+	list_for_each_entry(dev, &bus->devices, bus_list) {
+		u16 cmd;
+
+		pci_read_config_word(dev, PCI_COMMAND, &cmd);
+		cmd |= features;
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+
+		pci_write_config_byte(dev, PCI_CACHE_LINE_SIZE,
+				      L1_CACHE_BYTES >> 2);
+	}
+
+	/*
+	 * Propagate the flags to the PCI bridge.
+	 */
+	if (bus->self && bus->self->hdr_type == PCI_HEADER_TYPE_BRIDGE) {
+		if (features & PCI_COMMAND_FAST_BACK)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_FAST_BACK;
+		if (features & PCI_COMMAND_PARITY)
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_PARITY;
+	}
+
+	/*
+	 * Report what we did for this bus
+	 */
+	printk(KERN_INFO "PCI: bus%d: Fast back to back transfers %sabled\n",
+		bus->number, (features & PCI_COMMAND_FAST_BACK) ? "en" : "dis");
+}
+#ifdef CONFIG_HOTPLUG
+EXPORT_SYMBOL(pcibios_fixup_bus);
+#endif
+
+static int __init pci_common_init(void)
+{
+	struct pci_bus *puv3_bus;
+
+	pci_puv3_preinit();
+
+	puv3_bus = pci_scan_bus(0, &pci_puv3_ops, NULL);
+
+	if (!puv3_bus)
+		panic("PCI: unable to scan bus!");
+
+	pci_fixup_irqs(pci_common_swizzle, pci_puv3_map_irq);
+
+	if (!use_firmware) {
+		/*
+		 * Size the bridge windows.
+		 */
+		pci_bus_size_bridges(puv3_bus);
+
+		/*
+		 * Assign resources.
+		 */
+		pci_bus_assign_resources(puv3_bus);
+	}
+
+	/*
+	 * Tell drivers about devices found.
+	 */
+	pci_bus_add_devices(puv3_bus);
+
+	return 0;
+}
+subsys_initcall(pci_common_init);
+
+char * __devinit pcibios_setup(char *str)
+{
+	if (!strcmp(str, "debug")) {
+		debug_pci = 1;
+		return NULL;
+	} else if (!strcmp(str, "firmware")) {
+		use_firmware = 1;
+		return NULL;
+	}
+	return str;
+}
+
+/*
+ * From arch/i386/kernel/pci-i386.c:
+ *
+ * We need to avoid collisions with `mirrored' VGA ports
+ * and other strange ISA hardware, so we always want the
+ * addresses to be allocated in the 0x000-0x0ff region
+ * modulo 0x400.
+ *
+ * Why? Because some silly external IO cards only decode
+ * the low 10 bits of the IO address. The 0x00-0xff region
+ * is reserved for motherboard devices that decode all 16
+ * bits, so it's ok to allocate at, say, 0x2800-0x28ff,
+ * but we want to try to avoid allocating at 0x2900-0x2bff
+ * which might be mirrored at 0x0100-0x03ff..
+ */
+resource_size_t pcibios_align_resource(void *data, const struct resource *res,
+				resource_size_t size, resource_size_t align)
+{
+	resource_size_t start = res->start;
+
+	if (res->flags & IORESOURCE_IO && start & 0x300)
+		start = (start + 0x3ff) & ~0x3ff;
+
+	start = (start + align - 1) & ~(align - 1);
+
+	return start;
+}
+
+/**
+ * pcibios_enable_device - Enable I/O and memory.
+ * @dev: PCI device to be enabled
+ */
+int pcibios_enable_device(struct pci_dev *dev, int mask)
+{
+	u16 cmd, old_cmd;
+	int idx;
+	struct resource *r;
+
+	pci_read_config_word(dev, PCI_COMMAND, &cmd);
+	old_cmd = cmd;
+	for (idx = 0; idx < 6; idx++) {
+		/* Only set up the requested stuff */
+		if (!(mask & (1 << idx)))
+			continue;
+
+		r = dev->resource + idx;
+		if (!r->start && r->end) {
+			printk(KERN_ERR "PCI: Device %s not available because"
+			       " of resource collisions\n", pci_name(dev));
+			return -EINVAL;
+		}
+		if (r->flags & IORESOURCE_IO)
+			cmd |= PCI_COMMAND_IO;
+		if (r->flags & IORESOURCE_MEM)
+			cmd |= PCI_COMMAND_MEMORY;
+	}
+
+	/*
+	 * Bridges (eg, cardbus bridges) need to be fully enabled
+	 */
+	if ((dev->class >> 16) == PCI_BASE_CLASS_BRIDGE)
+		cmd |= PCI_COMMAND_IO | PCI_COMMAND_MEMORY;
+
+	if (cmd != old_cmd) {
+		printk("PCI: enabling device %s (%04x -> %04x)\n",
+		       pci_name(dev), old_cmd, cmd);
+		pci_write_config_word(dev, PCI_COMMAND, cmd);
+	}
+	return 0;
+}
+
+int pci_mmap_page_range(struct pci_dev *dev, struct vm_area_struct *vma,
+			enum pci_mmap_state mmap_state, int write_combine)
+{
+	unsigned long phys;
+
+	if (mmap_state == pci_mmap_io)
+		return -EINVAL;
+
+	phys = vma->vm_pgoff;
+
+	/*
+	 * Mark this as IO
+	 */
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+
+	if (remap_pfn_range(vma, vma->vm_start, phys,
+			     vma->vm_end - vma->vm_start,
+			     vma->vm_page_prot))
+		return -EAGAIN;
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/pm.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/pm.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/pm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * linux/arch/unicore32/kernel/pm.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/module.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+
+#include <mach/hardware.h>
+#include <mach/pm.h>
+
+#include "setup.h"
+
+struct puv3_cpu_pm_fns *puv3_cpu_pm_fns;
+static unsigned long *sleep_save;
+
+int puv3_pm_enter(suspend_state_t state)
+{
+	unsigned long sleep_save_checksum = 0, checksum = 0;
+	int i;
+
+	/* skip registers saving for standby */
+	if (state != PM_SUSPEND_STANDBY) {
+		puv3_cpu_pm_fns->save(sleep_save);
+		/* before sleeping, calculate and save a checksum */
+		for (i = 0; i < puv3_cpu_pm_fns->save_count - 1; i++)
+			sleep_save_checksum += sleep_save[i];
+	}
+
+	/* *** go zzz *** */
+	puv3_cpu_pm_fns->enter(state);
+	cpu_init();
+#ifdef CONFIG_INPUT_KEYBOARD
+	puv3_ps2_init();
+#endif
+#ifdef CONFIG_PCI
+	pci_puv3_preinit();
+#endif
+	if (state != PM_SUSPEND_STANDBY) {
+		/* after sleeping, validate the checksum */
+		for (i = 0; i < puv3_cpu_pm_fns->save_count - 1; i++)
+			checksum += sleep_save[i];
+
+		/* if invalid, display message and wait for a hardware reset */
+		if (checksum != sleep_save_checksum) {
+			while (1)
+				puv3_cpu_pm_fns->enter(state);
+		}
+		puv3_cpu_pm_fns->restore(sleep_save);
+	}
+
+	pr_debug("*** made it back from resume\n");
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(puv3_pm_enter);
+
+unsigned long sleep_phys_sp(void *sp)
+{
+	return virt_to_phys(sp);
+}
+
+static int puv3_pm_valid(suspend_state_t state)
+{
+	if (puv3_cpu_pm_fns)
+		return puv3_cpu_pm_fns->valid(state);
+
+	return -EINVAL;
+}
+
+static int puv3_pm_prepare(void)
+{
+	int ret = 0;
+
+	if (puv3_cpu_pm_fns && puv3_cpu_pm_fns->prepare)
+		ret = puv3_cpu_pm_fns->prepare();
+
+	return ret;
+}
+
+static void puv3_pm_finish(void)
+{
+	if (puv3_cpu_pm_fns && puv3_cpu_pm_fns->finish)
+		puv3_cpu_pm_fns->finish();
+}
+
+static struct platform_suspend_ops puv3_pm_ops = {
+	.valid		= puv3_pm_valid,
+	.enter		= puv3_pm_enter,
+	.prepare	= puv3_pm_prepare,
+	.finish		= puv3_pm_finish,
+};
+
+static int __init puv3_pm_init(void)
+{
+	if (!puv3_cpu_pm_fns) {
+		printk(KERN_ERR "no valid puv3_cpu_pm_fns defined\n");
+		return -EINVAL;
+	}
+
+	sleep_save = kmalloc(puv3_cpu_pm_fns->save_count
+				* sizeof(unsigned long), GFP_KERNEL);
+	if (!sleep_save) {
+		printk(KERN_ERR "failed to alloc memory for pm save\n");
+		return -ENOMEM;
+	}
+
+	suspend_set_ops(&puv3_pm_ops);
+	return 0;
+}
+
+device_initcall(puv3_pm_init);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/process.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/process.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,389 @@
+/*
+ * linux/arch/unicore32/kernel/process.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <stdarg.h>
+
+#include <linux/module.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/mm.h>
+#include <linux/stddef.h>
+#include <linux/unistd.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/kallsyms.h>
+#include <linux/init.h>
+#include <linux/cpu.h>
+#include <linux/elfcore.h>
+#include <linux/pm.h>
+#include <linux/tick.h>
+#include <linux/utsname.h>
+#include <linux/uaccess.h>
+#include <linux/random.h>
+#include <linux/gpio.h>
+#include <linux/stacktrace.h>
+
+#include <asm/cacheflush.h>
+#include <asm/processor.h>
+#include <asm/system.h>
+#include <asm/stacktrace.h>
+
+#include "setup.h"
+
+static const char * const processor_modes[] = {
+	"UK00", "UK01", "UK02", "UK03", "UK04", "UK05", "UK06", "UK07",
+	"UK08", "UK09", "UK0A", "UK0B", "UK0C", "UK0D", "UK0E", "UK0F",
+	"USER", "REAL", "INTR", "PRIV", "UK14", "UK15", "UK16", "ABRT",
+	"UK18", "UK19", "UK1A", "EXTN", "UK1C", "UK1D", "UK1E", "SUSR"
+};
+
+/*
+ * 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.
+ */
+void cpu_idle(void)
+{
+	/* endless idle loop with no priority at all */
+	while (1) {
+		tick_nohz_stop_sched_tick(1);
+		while (!need_resched()) {
+			local_irq_disable();
+			stop_critical_timings();
+			cpu_do_idle();
+			local_irq_enable();
+			start_critical_timings();
+		}
+		tick_nohz_restart_sched_tick();
+		preempt_enable_no_resched();
+		schedule();
+		preempt_disable();
+	}
+}
+
+static char reboot_mode = 'h';
+
+int __init reboot_setup(char *str)
+{
+	reboot_mode = str[0];
+	return 1;
+}
+
+__setup("reboot=", reboot_setup);
+
+void machine_halt(void)
+{
+	gpio_set_value(GPO_SOFT_OFF, 0);
+}
+
+/*
+ * Function pointers to optional machine specific functions
+ */
+void (*pm_power_off)(void) = NULL;
+
+void machine_power_off(void)
+{
+	if (pm_power_off)
+		pm_power_off();
+	machine_halt();
+}
+
+void machine_restart(char *cmd)
+{
+	/* Disable interrupts first */
+	local_irq_disable();
+
+	/*
+	 * Tell the mm system that we are going to reboot -
+	 * we may need it to insert some 1:1 mappings so that
+	 * soft boot works.
+	 */
+	setup_mm_for_reboot(reboot_mode);
+
+	/* Clean and invalidate caches */
+	flush_cache_all();
+
+	/* Turn off caching */
+	cpu_proc_fin();
+
+	/* Push out any further dirty data, and ensure cache is empty */
+	flush_cache_all();
+
+	/*
+	 * Now handle reboot code.
+	 */
+	if (reboot_mode == 's') {
+		/* Jump into ROM at address 0xffff0000 */
+		cpu_reset(VECTORS_BASE);
+	} else {
+		writel(0x00002001, PM_PLLSYSCFG); /* cpu clk = 250M */
+		writel(0x00100800, PM_PLLDDRCFG); /* ddr clk =  44M */
+		writel(0x00002001, PM_PLLVGACFG); /* vga clk = 250M */
+
+		/* Use on-chip reset capability */
+		/* following instructions must be in one icache line */
+		__asm__ __volatile__(
+			"	.align 5\n\t"
+			"	stw	%1, [%0]\n\t"
+			"201:	ldw	r0, [%0]\n\t"
+			"	cmpsub.a	r0, #0\n\t"
+			"	bne	201b\n\t"
+			"	stw	%3, [%2]\n\t"
+			"	nop; nop; nop\n\t"
+			/* prefetch 3 instructions at most */
+			:
+			: "r" (PM_PMCR),
+			  "r" (PM_PMCR_CFBSYS | PM_PMCR_CFBDDR
+				| PM_PMCR_CFBVGA),
+			  "r" (RESETC_SWRR),
+			  "r" (RESETC_SWRR_SRB)
+			: "r0", "memory");
+	}
+
+	/*
+	 * Whoops - the architecture was unable to reboot.
+	 * Tell the user!
+	 */
+	mdelay(1000);
+	printk(KERN_EMERG "Reboot failed -- System halted\n");
+	do { } while (1);
+}
+
+void __show_regs(struct pt_regs *regs)
+{
+	unsigned long flags;
+	char buf[64];
+
+	printk(KERN_DEFAULT "CPU: %d    %s  (%s %.*s)\n",
+		raw_smp_processor_id(), print_tainted(),
+		init_utsname()->release,
+		(int)strcspn(init_utsname()->version, " "),
+		init_utsname()->version);
+	print_symbol("PC is at %s\n", instruction_pointer(regs));
+	print_symbol("LR is at %s\n", regs->UCreg_lr);
+	printk(KERN_DEFAULT "pc : [<%08lx>]    lr : [<%08lx>]    psr: %08lx\n"
+	       "sp : %08lx  ip : %08lx  fp : %08lx\n",
+		regs->UCreg_pc, regs->UCreg_lr, regs->UCreg_asr,
+		regs->UCreg_sp, regs->UCreg_ip, regs->UCreg_fp);
+	printk(KERN_DEFAULT "r26: %08lx  r25: %08lx  r24: %08lx\n",
+		regs->UCreg_26, regs->UCreg_25,
+		regs->UCreg_24);
+	printk(KERN_DEFAULT "r23: %08lx  r22: %08lx  r21: %08lx  r20: %08lx\n",
+		regs->UCreg_23, regs->UCreg_22,
+		regs->UCreg_21, regs->UCreg_20);
+	printk(KERN_DEFAULT "r19: %08lx  r18: %08lx  r17: %08lx  r16: %08lx\n",
+		regs->UCreg_19, regs->UCreg_18,
+		regs->UCreg_17, regs->UCreg_16);
+	printk(KERN_DEFAULT "r15: %08lx  r14: %08lx  r13: %08lx  r12: %08lx\n",
+		regs->UCreg_15, regs->UCreg_14,
+		regs->UCreg_13, regs->UCreg_12);
+	printk(KERN_DEFAULT "r11: %08lx  r10: %08lx  r9 : %08lx  r8 : %08lx\n",
+		regs->UCreg_11, regs->UCreg_10,
+		regs->UCreg_09, regs->UCreg_08);
+	printk(KERN_DEFAULT "r7 : %08lx  r6 : %08lx  r5 : %08lx  r4 : %08lx\n",
+		regs->UCreg_07, regs->UCreg_06,
+		regs->UCreg_05, regs->UCreg_04);
+	printk(KERN_DEFAULT "r3 : %08lx  r2 : %08lx  r1 : %08lx  r0 : %08lx\n",
+		regs->UCreg_03, regs->UCreg_02,
+		regs->UCreg_01, regs->UCreg_00);
+
+	flags = regs->UCreg_asr;
+	buf[0] = flags & PSR_S_BIT ? 'S' : 's';
+	buf[1] = flags & PSR_Z_BIT ? 'Z' : 'z';
+	buf[2] = flags & PSR_C_BIT ? 'C' : 'c';
+	buf[3] = flags & PSR_V_BIT ? 'V' : 'v';
+	buf[4] = '\0';
+
+	printk(KERN_DEFAULT "Flags: %s  INTR o%s  REAL o%s  Mode %s  Segment %s\n",
+		buf, interrupts_enabled(regs) ? "n" : "ff",
+		fast_interrupts_enabled(regs) ? "n" : "ff",
+		processor_modes[processor_mode(regs)],
+		segment_eq(get_fs(), get_ds()) ? "kernel" : "user");
+	{
+		unsigned int ctrl;
+
+		buf[0] = '\0';
+		{
+			unsigned int transbase;
+			asm("movc %0, p0.c2, #0\n"
+			    : "=r" (transbase));
+			snprintf(buf, sizeof(buf), "  Table: %08x", transbase);
+		}
+		asm("movc %0, p0.c1, #0\n" : "=r" (ctrl));
+
+		printk(KERN_DEFAULT "Control: %08x%s\n", ctrl, buf);
+	}
+}
+
+void show_regs(struct pt_regs *regs)
+{
+	printk(KERN_DEFAULT "\n");
+	printk(KERN_DEFAULT "Pid: %d, comm: %20s\n",
+			task_pid_nr(current), current->comm);
+	__show_regs(regs);
+	__backtrace();
+}
+
+/*
+ * Free current thread data structures etc..
+ */
+void exit_thread(void)
+{
+}
+
+void flush_thread(void)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
+
+	memset(thread->used_cp, 0, sizeof(thread->used_cp));
+	memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
+#ifdef CONFIG_UNICORE_FPU_F64
+	memset(&thread->fpstate, 0, sizeof(struct fp_state));
+#endif
+}
+
+void release_thread(struct task_struct *dead_task)
+{
+}
+
+asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+
+int
+copy_thread(unsigned long clone_flags, unsigned long stack_start,
+	    unsigned long stk_sz, struct task_struct *p, struct pt_regs *regs)
+{
+	struct thread_info *thread = task_thread_info(p);
+	struct pt_regs *childregs = task_pt_regs(p);
+
+	*childregs = *regs;
+	childregs->UCreg_00 = 0;
+	childregs->UCreg_sp = stack_start;
+
+	memset(&thread->cpu_context, 0, sizeof(struct cpu_context_save));
+	thread->cpu_context.sp = (unsigned long)childregs;
+	thread->cpu_context.pc = (unsigned long)ret_from_fork;
+
+	if (clone_flags & CLONE_SETTLS)
+		childregs->UCreg_16 = regs->UCreg_03;
+
+	return 0;
+}
+
+/*
+ * Fill in the task's elfregs structure for a core dump.
+ */
+int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
+{
+	elf_core_copy_regs(elfregs, task_pt_regs(t));
+	return 1;
+}
+
+/*
+ * fill in the fpe structure for a core dump...
+ */
+int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fp)
+{
+	struct thread_info *thread = current_thread_info();
+	int used_math = thread->used_cp[1] | thread->used_cp[2];
+
+#ifdef CONFIG_UNICORE_FPU_F64
+	if (used_math)
+		memcpy(fp, &thread->fpstate, sizeof(*fp));
+#endif
+	return used_math != 0;
+}
+EXPORT_SYMBOL(dump_fpu);
+
+/*
+ * Shuffle the argument into the correct register before calling the
+ * thread function.  r1 is the thread argument, r2 is the pointer to
+ * the thread function, and r3 points to the exit function.
+ */
+asm(".pushsection .text\n"
+"	.align\n"
+"	.type	kernel_thread_helper, #function\n"
+"kernel_thread_helper:\n"
+"	mov.a	asr, r7\n"
+"	mov	r0, r4\n"
+"	mov	lr, r6\n"
+"	mov	pc, r5\n"
+"	.size	kernel_thread_helper, . - kernel_thread_helper\n"
+"	.popsection");
+
+/*
+ * Create a kernel thread.
+ */
+pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
+{
+	struct pt_regs regs;
+
+	memset(&regs, 0, sizeof(regs));
+
+	regs.UCreg_04 = (unsigned long)arg;
+	regs.UCreg_05 = (unsigned long)fn;
+	regs.UCreg_06 = (unsigned long)do_exit;
+	regs.UCreg_07 = PRIV_MODE;
+	regs.UCreg_pc = (unsigned long)kernel_thread_helper;
+	regs.UCreg_asr = regs.UCreg_07 | PSR_I_BIT;
+
+	return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
+
+unsigned long get_wchan(struct task_struct *p)
+{
+	struct stackframe frame;
+	int count = 0;
+	if (!p || p == current || p->state == TASK_RUNNING)
+		return 0;
+
+	frame.fp = thread_saved_fp(p);
+	frame.sp = thread_saved_sp(p);
+	frame.lr = 0;			/* recovered from the stack */
+	frame.pc = thread_saved_pc(p);
+	do {
+		int ret = unwind_frame(&frame);
+		if (ret < 0)
+			return 0;
+		if (!in_sched_functions(frame.pc))
+			return frame.pc;
+	} while ((count++) < 16);
+	return 0;
+}
+
+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;
+}
+
+/*
+ * The vectors page is always readable from user space for the
+ * atomic helpers and the signal restart code.  Let's declare a mapping
+ * for it so it is visible through ptrace and /proc/<pid>/mem.
+ */
+
+int vectors_user_mapping(void)
+{
+	struct mm_struct *mm = current->mm;
+	return install_special_mapping(mm, 0xffff0000, PAGE_SIZE,
+				       VM_READ | VM_EXEC |
+				       VM_MAYREAD | VM_MAYEXEC |
+				       VM_ALWAYSDUMP | VM_RESERVED,
+				       NULL);
+}
+
+const char *arch_vma_name(struct vm_area_struct *vma)
+{
+	return (vma->vm_start == 0xffff0000) ? "[vectors]" : NULL;
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/ptrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,149 @@
+/*
+ * linux/arch/unicore32/kernel/ptrace.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * By Ross Biro 1/23/92
+ *
+ * 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/ptrace.h>
+#include <linux/signal.h>
+#include <linux/uaccess.h>
+
+/*
+ * this routine will get a word off of the processes privileged stack.
+ * the offset is how far from the base addr as stored in the THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline long get_user_reg(struct task_struct *task, int offset)
+{
+	return task_pt_regs(task)->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 THREAD.
+ * this routine assumes that all the privileged stacks are in our
+ * data space.
+ */
+static inline int
+put_user_reg(struct task_struct *task, int offset, long data)
+{
+	struct pt_regs newregs, *regs = task_pt_regs(task);
+	int ret = -EINVAL;
+
+	newregs = *regs;
+	newregs.uregs[offset] = data;
+
+	if (valid_user_regs(&newregs)) {
+		regs->uregs[offset] = data;
+		ret = 0;
+	}
+
+	return ret;
+}
+
+/*
+ * Called by kernel/ptrace.c when detaching..
+ */
+void ptrace_disable(struct task_struct *child)
+{
+}
+
+/*
+ * We actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_read_user(struct task_struct *tsk, unsigned long off,
+			    unsigned long __user *ret)
+{
+	unsigned long tmp;
+
+	tmp = 0;
+	if (off < sizeof(struct pt_regs))
+		tmp = get_user_reg(tsk, off >> 2);
+
+	return put_user(tmp, ret);
+}
+
+/*
+ * We actually access the pt_regs stored on the kernel stack.
+ */
+static int ptrace_write_user(struct task_struct *tsk, unsigned long off,
+			     unsigned long val)
+{
+	if (off >= sizeof(struct pt_regs))
+		return 0;
+
+	return put_user_reg(tsk, off >> 2, val);
+}
+
+long arch_ptrace(struct task_struct *child, long request,
+		 unsigned long addr, unsigned long data)
+{
+	int ret;
+	unsigned long __user *datap = (unsigned long __user *) data;
+
+	switch (request) {
+	case PTRACE_PEEKUSR:
+		ret = ptrace_read_user(child, addr, datap);
+		break;
+
+	case PTRACE_POKEUSR:
+		ret = ptrace_write_user(child, addr, data);
+		break;
+
+	case PTRACE_GET_THREAD_AREA:
+		ret = put_user(task_pt_regs(child)->UCreg_16,
+			       datap);
+		break;
+
+	default:
+		ret = ptrace_request(child, request, addr, data);
+		break;
+	}
+
+	return ret;
+}
+
+asmlinkage int syscall_trace(int why, struct pt_regs *regs, int scno)
+{
+	unsigned long ip;
+
+	if (!test_thread_flag(TIF_SYSCALL_TRACE))
+		return scno;
+	if (!(current->ptrace & PT_PTRACED))
+		return scno;
+
+	/*
+	 * Save IP.  IP is used to denote syscall entry/exit:
+	 *  IP = 0 -> entry, = 1 -> exit
+	 */
+	ip = regs->UCreg_ip;
+	regs->UCreg_ip = why;
+
+	current_thread_info()->syscall = scno;
+
+	/* 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)
+				 ? 0x80 : 0));
+	/*
+	 * 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;
+	}
+	regs->UCreg_ip = ip;
+
+	return current_thread_info()->syscall;
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/puv3-core.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/puv3-core.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/puv3-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/puv3-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,280 @@
+/*
+ *  linux/arch/unicore32/kernel/puv3-core.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/sysdev.h>
+#include <linux/amba/bus.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/cnt32_to_63.h>
+#include <linux/usb/musb.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+#include <mach/pm.h>
+
+/*
+ * This is the PKUnity sched_clock implementation.  This has
+ * a resolution of 271ns, and a maximum value of 32025597s (370 days).
+ *
+ * The return value is guaranteed to be monotonic in that range as
+ * long as there is always less than 582 seconds between successive
+ * calls to this function.
+ *
+ *  ( * 1E9 / CLOCK_TICK_RATE ) -> about 2235/32
+ */
+unsigned long long sched_clock(void)
+{
+	unsigned long long v = cnt32_to_63(readl(OST_OSCR));
+
+	/* original conservative method, but overflow frequently
+	 * v *= NSEC_PER_SEC >> 12;
+	 * do_div(v, CLOCK_TICK_RATE >> 12);
+	 */
+	v = ((v & 0x7fffffffffffffffULL) * 2235) >> 5;
+
+	return v;
+}
+
+static struct resource puv3_usb_resources[] = {
+	/* order is significant! */
+	{
+		.start		= io_v2p(PKUNITY_USB_BASE),
+		.end		= io_v2p(PKUNITY_USB_BASE) + 0x3ff,
+		.flags		= IORESOURCE_MEM,
+	}, {
+		.start		= IRQ_USB,
+		.flags		= IORESOURCE_IRQ,
+	}, {
+		.start		= IRQ_USB,
+		.flags		= IORESOURCE_IRQ,
+	},
+};
+
+static struct musb_hdrc_config	puv3_usb_config[] = {
+	{
+		.num_eps = 16,
+		.multipoint = 1,
+#ifdef CONFIG_USB_INVENTRA_DMA
+		.dma = 1,
+		.dma_channels = 8,
+#endif
+	},
+};
+
+static struct musb_hdrc_platform_data puv3_usb_plat = {
+	.mode		= MUSB_HOST,
+	.min_power	= 100,
+	.clock		= 0,
+	.config		= puv3_usb_config,
+};
+
+static struct resource puv3_mmc_resources[] = {
+	[0] = {
+		.start	= io_v2p(PKUNITY_SDC_BASE),
+		.end	= io_v2p(PKUNITY_SDC_BASE) + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= IRQ_SDC,
+		.end	= IRQ_SDC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct resource puv3_unigfx_resources[] = {
+	[0] = {
+		.start	= io_v2p(PKUNITY_UNIGFX_BASE),
+		.end	= io_v2p(PKUNITY_UNIGFX_BASE) + 0xfff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource puv3_rtc_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_RTC_BASE),
+		.end   = io_v2p(PKUNITY_RTC_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_RTCAlarm,
+		.end   = IRQ_RTCAlarm,
+		.flags = IORESOURCE_IRQ,
+	},
+	[2] = {
+		.start = IRQ_RTC,
+		.end   = IRQ_RTC,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource puv3_pwm_resources[] = {
+	[0] = {
+		.start	= io_v2p(PKUNITY_OST_BASE) + 0x80,
+		.end	= io_v2p(PKUNITY_OST_BASE) + 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct resource puv3_uart0_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_UART0_BASE),
+		.end   = io_v2p(PKUNITY_UART0_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_UART0,
+		.end   = IRQ_UART0,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource puv3_uart1_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_UART1_BASE),
+		.end   = io_v2p(PKUNITY_UART1_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_UART1,
+		.end   = IRQ_UART1,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+static struct resource puv3_umal_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_UMAL_BASE),
+		.end   = io_v2p(PKUNITY_UMAL_BASE) + 0x1fff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_UMAL,
+		.end   = IRQ_UMAL,
+		.flags = IORESOURCE_IRQ
+	}
+};
+
+#ifdef CONFIG_PUV3_PM
+
+#define SAVE(x)		sleep_save[SLEEP_SAVE_##x] = x
+#define RESTORE(x)	x = sleep_save[SLEEP_SAVE_##x]
+
+/*
+ * 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.
+ */
+enum {
+	SLEEP_SAVE_PM_PLLDDRCFG,
+	SLEEP_SAVE_COUNT
+};
+
+
+static void puv3_cpu_pm_save(unsigned long *sleep_save)
+{
+/*	SAVE(PM_PLLDDRCFG); */
+}
+
+static void puv3_cpu_pm_restore(unsigned long *sleep_save)
+{
+/*	RESTORE(PM_PLLDDRCFG); */
+}
+
+static int puv3_cpu_pm_prepare(void)
+{
+	/* set resume return address */
+	writel(virt_to_phys(puv3_cpu_resume), PM_DIVCFG);
+	return 0;
+}
+
+static void puv3_cpu_pm_enter(suspend_state_t state)
+{
+	/* Clear reset status */
+	writel(RESETC_RSSR_HWR | RESETC_RSSR_WDR
+			| RESETC_RSSR_SMR | RESETC_RSSR_SWR, RESETC_RSSR);
+
+	switch (state) {
+/*	case PM_SUSPEND_ON:
+		puv3_cpu_idle();
+		break; */
+	case PM_SUSPEND_MEM:
+		puv3_cpu_pm_prepare();
+		puv3_cpu_suspend(PM_PMCR_SFB);
+		break;
+	}
+}
+
+static int puv3_cpu_pm_valid(suspend_state_t state)
+{
+	return state == PM_SUSPEND_MEM;
+}
+
+static void puv3_cpu_pm_finish(void)
+{
+	/* ensure not to come back here if it wasn't intended */
+	/* PSPR = 0; */
+}
+
+static struct puv3_cpu_pm_fns puv3_cpu_pm_fnss = {
+	.save_count	= SLEEP_SAVE_COUNT,
+	.valid		= puv3_cpu_pm_valid,
+	.save		= puv3_cpu_pm_save,
+	.restore	= puv3_cpu_pm_restore,
+	.enter		= puv3_cpu_pm_enter,
+	.prepare	= puv3_cpu_pm_prepare,
+	.finish		= puv3_cpu_pm_finish,
+};
+
+static void __init puv3_init_pm(void)
+{
+	puv3_cpu_pm_fns = &puv3_cpu_pm_fnss;
+}
+#else
+static inline void puv3_init_pm(void) {}
+#endif
+
+void puv3_ps2_init(void)
+{
+	struct clk *bclk32;
+
+	bclk32 = clk_get(NULL, "BUS32_CLK");
+	writel(clk_get_rate(bclk32) / 200000, PS2_CNT); /* should > 5us */
+}
+
+void __init puv3_core_init(void)
+{
+	puv3_init_pm();
+	puv3_ps2_init();
+
+	platform_device_register_simple("PKUnity-v3-RTC", -1,
+			puv3_rtc_resources, ARRAY_SIZE(puv3_rtc_resources));
+	platform_device_register_simple("PKUnity-v3-UMAL", -1,
+			puv3_umal_resources, ARRAY_SIZE(puv3_umal_resources));
+	platform_device_register_simple("PKUnity-v3-MMC", -1,
+			puv3_mmc_resources, ARRAY_SIZE(puv3_mmc_resources));
+	platform_device_register_simple("PKUnity-v3-UNIGFX", -1,
+			puv3_unigfx_resources, ARRAY_SIZE(puv3_unigfx_resources));
+	platform_device_register_simple("PKUnity-v3-PWM", -1,
+			puv3_pwm_resources, ARRAY_SIZE(puv3_pwm_resources));
+	platform_device_register_simple("PKUnity-v3-UART", 0,
+			puv3_uart0_resources, ARRAY_SIZE(puv3_uart0_resources));
+	platform_device_register_simple("PKUnity-v3-UART", 1,
+			puv3_uart1_resources, ARRAY_SIZE(puv3_uart1_resources));
+	platform_device_register_simple("PKUnity-v3-AC97", -1, NULL, 0);
+	platform_device_register_resndata(&platform_bus, "musb_hdrc", -1,
+			puv3_usb_resources, ARRAY_SIZE(puv3_usb_resources),
+			&puv3_usb_plat, sizeof(puv3_usb_plat));
+}
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/puv3-nb0916.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/puv3-nb0916.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/puv3-nb0916.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/puv3-nb0916.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * linux/arch/unicore32/kernel/puv3-nb0916.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/sysdev.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/physmap.h>
+#include <linux/io.h>
+#include <linux/reboot.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/pwm_backlight.h>
+#include <linux/gpio.h>
+#include <linux/gpio_keys.h>
+#include <linux/input.h>
+
+#include <mach/hardware.h>
+
+static struct physmap_flash_data physmap_flash_data = {
+	.width		= 1,
+};
+
+static struct resource physmap_flash_resource = {
+	.start		= 0xFFF80000,
+	.end		= 0xFFFFFFFF,
+	.flags		= IORESOURCE_MEM,
+};
+
+static struct resource puv3_i2c_resources[] = {
+	[0] = {
+		.start = io_v2p(PKUNITY_I2C_BASE),
+		.end   = io_v2p(PKUNITY_I2C_BASE) + 0xff,
+		.flags = IORESOURCE_MEM,
+	},
+	[1] = {
+		.start = IRQ_I2C,
+		.end   = IRQ_I2C,
+		.flags = IORESOURCE_IRQ,
+	}
+};
+
+static struct platform_pwm_backlight_data nb0916_backlight_data = {
+	.pwm_id		= 0,
+	.max_brightness	= 100,
+	.dft_brightness	= 100,
+	.pwm_period_ns	= 70 * 1024,
+};
+
+static struct gpio_keys_button nb0916_gpio_keys[] = {
+	{
+		.type	= EV_KEY,
+		.code	= KEY_POWER,
+		.gpio	= GPI_SOFF_REQ,
+		.desc	= "Power Button",
+		.wakeup = 1,
+		.active_low = 1,
+	},
+	{
+		.type	= EV_KEY,
+		.code	= BTN_TOUCH,
+		.gpio	= GPI_BTN_TOUCH,
+		.desc	= "Touchpad Button",
+		.wakeup = 1,
+		.active_low = 1,
+	},
+};
+
+static struct gpio_keys_platform_data nb0916_gpio_button_data = {
+	.buttons	= nb0916_gpio_keys,
+	.nbuttons	= ARRAY_SIZE(nb0916_gpio_keys),
+};
+
+static irqreturn_t nb0916_lcdcaseoff_handler(int irq, void *dev_id)
+{
+	if (gpio_get_value(GPI_LCD_CASE_OFF))
+		gpio_set_value(GPO_LCD_EN, 1);
+	else
+		gpio_set_value(GPO_LCD_EN, 0);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t nb0916_overheat_handler(int irq, void *dev_id)
+{
+	machine_halt();
+	/* SYSTEM HALT, NO RETURN */
+	return IRQ_HANDLED;
+}
+
+static struct i2c_board_info __initdata puv3_i2c_devices[] = {
+	{	I2C_BOARD_INFO("lm75",		I2C_TAR_THERMAL),	},
+	{	I2C_BOARD_INFO("bq27200",	I2C_TAR_PWIC),		},
+	{	I2C_BOARD_INFO("24c02",		I2C_TAR_EEPROM),	},
+};
+
+int __init mach_nb0916_init(void)
+{
+	i2c_register_board_info(0, puv3_i2c_devices,
+			ARRAY_SIZE(puv3_i2c_devices));
+
+	platform_device_register_simple("PKUnity-v3-I2C", -1,
+			puv3_i2c_resources, ARRAY_SIZE(puv3_i2c_resources));
+
+	platform_device_register_data(&platform_bus, "pwm-backlight", -1,
+			&nb0916_backlight_data, sizeof(nb0916_backlight_data));
+
+	platform_device_register_data(&platform_bus, "gpio-keys", -1,
+			&nb0916_gpio_button_data, sizeof(nb0916_gpio_button_data));
+
+	platform_device_register_resndata(&platform_bus, "physmap-flash", -1,
+			&physmap_flash_resource, 1,
+			&physmap_flash_data, sizeof(physmap_flash_data));
+
+	if (request_irq(gpio_to_irq(GPI_LCD_CASE_OFF),
+		&nb0916_lcdcaseoff_handler,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"NB0916 lcd case off", NULL) < 0) {
+
+		printk(KERN_DEBUG "LCD-Case-OFF IRQ %d not available\n",
+			gpio_to_irq(GPI_LCD_CASE_OFF));
+	}
+
+	if (request_irq(gpio_to_irq(GPI_OTP_INT), &nb0916_overheat_handler,
+		IRQF_DISABLED | IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		"NB0916 overheating protection", NULL) < 0) {
+
+		printk(KERN_DEBUG "Overheating Protection IRQ %d not available\n",
+			gpio_to_irq(GPI_OTP_INT));
+	}
+
+	return 0;
+}
+
+subsys_initcall_sync(mach_nb0916_init);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/pwm.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/pwm.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/pwm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/pwm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,263 @@
+/*
+ * linux/arch/unicore32/kernel/pwm.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/slab.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/pwm.h>
+
+#include <asm/div64.h>
+#include <mach/hardware.h>
+
+struct pwm_device {
+	struct list_head	node;
+	struct platform_device *pdev;
+
+	const char	*label;
+	struct clk	*clk;
+	int		clk_enabled;
+
+	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 = OST_PWMDCCR_FDCYCLE;
+	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);
+	OST_PWMPWCR = prescale;
+	OST_PWMDCCR = pv - dc;
+	OST_PWMPCR  = pv;
+	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(NULL, "OST_CLK");
+	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;
+
+	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, resource_size(r), pdev->name);
+	if (r == NULL) {
+		dev_err(&pdev->dev, "failed to request memory resource\n");
+		ret = -EBUSY;
+		goto err_free_clk;
+	}
+
+	__add_pwm(pwm);
+	platform_set_drvdata(pdev, pwm);
+	return pwm;
+
+err_free_clk:
+	clk_put(pwm->clk);
+err_free:
+	kfree(pwm);
+	return ERR_PTR(ret);
+}
+
+static int __devinit puv3_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 __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);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(r->start, resource_size(r));
+
+	clk_put(pwm->clk);
+	kfree(pwm);
+	return 0;
+}
+
+static struct platform_driver puv3_pwm_driver = {
+	.driver		= {
+		.name	= "PKUnity-v3-PWM",
+	},
+	.probe		= puv3_pwm_probe,
+	.remove		= __devexit_p(pwm_remove),
+};
+
+static int __init pwm_init(void)
+{
+	int ret = 0;
+
+	ret = platform_driver_register(&puv3_pwm_driver);
+	if (ret) {
+		printk(KERN_ERR "failed to register puv3_pwm_driver\n");
+		return ret;
+	}
+
+	return ret;
+}
+arch_initcall(pwm_init);
+
+static void __exit pwm_exit(void)
+{
+	platform_driver_unregister(&puv3_pwm_driver);
+}
+module_exit(pwm_exit);
+
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/rtc.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/rtc.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/rtc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/rtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,371 @@
+/*
+ * linux/arch/unicore32/kernel/rtc.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/fs.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/bcd.h>
+#include <linux/clk.h>
+#include <linux/log2.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/io.h>
+
+#include <asm/irq.h>
+#include <mach/hardware.h>
+
+static struct resource *puv3_rtc_mem;
+
+static int puv3_rtc_alarmno = IRQ_RTCAlarm;
+static int puv3_rtc_tickno  = IRQ_RTC;
+
+static DEFINE_SPINLOCK(puv3_rtc_pie_lock);
+
+/* IRQ Handlers */
+
+static irqreturn_t puv3_rtc_alarmirq(int irq, void *id)
+{
+	struct rtc_device *rdev = id;
+
+	writel(readl(RTC_RTSR) | RTC_RTSR_AL, RTC_RTSR);
+	rtc_update_irq(rdev, 1, RTC_AF | RTC_IRQF);
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t puv3_rtc_tickirq(int irq, void *id)
+{
+	struct rtc_device *rdev = id;
+
+	writel(readl(RTC_RTSR) | RTC_RTSR_HZ, RTC_RTSR);
+	rtc_update_irq(rdev, 1, RTC_PF | RTC_IRQF);
+	return IRQ_HANDLED;
+}
+
+/* Update control registers */
+static void puv3_rtc_setaie(int to)
+{
+	unsigned int tmp;
+
+	pr_debug("%s: aie=%d\n", __func__, to);
+
+	tmp = readl(RTC_RTSR) & ~RTC_RTSR_ALE;
+
+	if (to)
+		tmp |= RTC_RTSR_ALE;
+
+	writel(tmp, RTC_RTSR);
+}
+
+static int puv3_rtc_setpie(struct device *dev, int enabled)
+{
+	unsigned int tmp;
+
+	pr_debug("%s: pie=%d\n", __func__, enabled);
+
+	spin_lock_irq(&puv3_rtc_pie_lock);
+	tmp = readl(RTC_RTSR) & ~RTC_RTSR_HZE;
+
+	if (enabled)
+		tmp |= RTC_RTSR_HZE;
+
+	writel(tmp, RTC_RTSR);
+	spin_unlock_irq(&puv3_rtc_pie_lock);
+
+	return 0;
+}
+
+/* Time read/write */
+
+static int puv3_rtc_gettime(struct device *dev, struct rtc_time *rtc_tm)
+{
+	rtc_time_to_tm(readl(RTC_RCNR), rtc_tm);
+
+	pr_debug("read time %02x.%02x.%02x %02x/%02x/%02x\n",
+		 rtc_tm->tm_year, rtc_tm->tm_mon, rtc_tm->tm_mday,
+		 rtc_tm->tm_hour, rtc_tm->tm_min, rtc_tm->tm_sec);
+
+	return 0;
+}
+
+static int puv3_rtc_settime(struct device *dev, struct rtc_time *tm)
+{
+	unsigned long rtc_count = 0;
+
+	pr_debug("set time %02d.%02d.%02d %02d/%02d/%02d\n",
+		 tm->tm_year, tm->tm_mon, tm->tm_mday,
+		 tm->tm_hour, tm->tm_min, tm->tm_sec);
+
+	rtc_tm_to_time(tm, &rtc_count);
+	writel(rtc_count, RTC_RCNR);
+
+	return 0;
+}
+
+static int puv3_rtc_getalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_time *alm_tm = &alrm->time;
+
+	rtc_time_to_tm(readl(RTC_RTAR), alm_tm);
+
+	alrm->enabled = readl(RTC_RTSR) & RTC_RTSR_ALE;
+
+	pr_debug("read alarm %02x %02x.%02x.%02x %02x/%02x/%02x\n",
+		 alrm->enabled,
+		 alm_tm->tm_year, alm_tm->tm_mon, alm_tm->tm_mday,
+		 alm_tm->tm_hour, alm_tm->tm_min, alm_tm->tm_sec);
+
+	return 0;
+}
+
+static int puv3_rtc_setalarm(struct device *dev, struct rtc_wkalrm *alrm)
+{
+	struct rtc_time *tm = &alrm->time;
+	unsigned long rtcalarm_count = 0;
+
+	pr_debug("puv3_rtc_setalarm: %d, %02x/%02x/%02x %02x.%02x.%02x\n",
+		 alrm->enabled,
+		 tm->tm_mday & 0xff, tm->tm_mon & 0xff, tm->tm_year & 0xff,
+		 tm->tm_hour & 0xff, tm->tm_min & 0xff, tm->tm_sec);
+
+	rtc_tm_to_time(tm, &rtcalarm_count);
+	writel(rtcalarm_count, RTC_RTAR);
+
+	puv3_rtc_setaie(alrm->enabled);
+
+	if (alrm->enabled)
+		enable_irq_wake(puv3_rtc_alarmno);
+	else
+		disable_irq_wake(puv3_rtc_alarmno);
+
+	return 0;
+}
+
+static int puv3_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	seq_printf(seq, "periodic_IRQ\t: %s\n",
+		     (readl(RTC_RTSR) & RTC_RTSR_HZE) ? "yes" : "no");
+	return 0;
+}
+
+static int puv3_rtc_open(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = request_irq(puv3_rtc_alarmno, puv3_rtc_alarmirq,
+			  IRQF_DISABLED,  "pkunity-rtc alarm", rtc_dev);
+
+	if (ret) {
+		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_alarmno, ret);
+		return ret;
+	}
+
+	ret = request_irq(puv3_rtc_tickno, puv3_rtc_tickirq,
+			  IRQF_DISABLED,  "pkunity-rtc tick", rtc_dev);
+
+	if (ret) {
+		dev_err(dev, "IRQ%d error %d\n", puv3_rtc_tickno, ret);
+		goto tick_err;
+	}
+
+	return ret;
+
+ tick_err:
+	free_irq(puv3_rtc_alarmno, rtc_dev);
+	return ret;
+}
+
+static void puv3_rtc_release(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct rtc_device *rtc_dev = platform_get_drvdata(pdev);
+
+	/* do not clear AIE here, it may be needed for wake */
+
+	puv3_rtc_setpie(dev, 0);
+	free_irq(puv3_rtc_alarmno, rtc_dev);
+	free_irq(puv3_rtc_tickno, rtc_dev);
+}
+
+static const struct rtc_class_ops puv3_rtcops = {
+	.open		= puv3_rtc_open,
+	.release	= puv3_rtc_release,
+	.read_time	= puv3_rtc_gettime,
+	.set_time	= puv3_rtc_settime,
+	.read_alarm	= puv3_rtc_getalarm,
+	.set_alarm	= puv3_rtc_setalarm,
+	.proc	        = puv3_rtc_proc,
+};
+
+static void puv3_rtc_enable(struct platform_device *pdev, int en)
+{
+	if (!en) {
+		writel(readl(RTC_RTSR) & ~RTC_RTSR_HZE, RTC_RTSR);
+	} else {
+		/* re-enable the device, and check it is ok */
+
+		if ((readl(RTC_RTSR) & RTC_RTSR_HZE) == 0) {
+			dev_info(&pdev->dev, "rtc disabled, re-enabling\n");
+			writel(readl(RTC_RTSR) | RTC_RTSR_HZE, RTC_RTSR);
+		}
+	}
+}
+
+static int puv3_rtc_remove(struct platform_device *dev)
+{
+	struct rtc_device *rtc = platform_get_drvdata(dev);
+
+	platform_set_drvdata(dev, NULL);
+	rtc_device_unregister(rtc);
+
+	puv3_rtc_setpie(&dev->dev, 0);
+	puv3_rtc_setaie(0);
+
+	release_resource(puv3_rtc_mem);
+	kfree(puv3_rtc_mem);
+
+	return 0;
+}
+
+static int puv3_rtc_probe(struct platform_device *pdev)
+{
+	struct rtc_device *rtc;
+	struct resource *res;
+	int ret;
+
+	pr_debug("%s: probe=%p\n", __func__, pdev);
+
+	/* find the IRQs */
+
+	puv3_rtc_tickno = platform_get_irq(pdev, 1);
+	if (puv3_rtc_tickno < 0) {
+		dev_err(&pdev->dev, "no irq for rtc tick\n");
+		return -ENOENT;
+	}
+
+	puv3_rtc_alarmno = platform_get_irq(pdev, 0);
+	if (puv3_rtc_alarmno < 0) {
+		dev_err(&pdev->dev, "no irq for alarm\n");
+		return -ENOENT;
+	}
+
+	pr_debug("PKUnity_rtc: tick irq %d, alarm irq %d\n",
+		 puv3_rtc_tickno, puv3_rtc_alarmno);
+
+	/* get the memory region */
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL) {
+		dev_err(&pdev->dev, "failed to get memory region resource\n");
+		return -ENOENT;
+	}
+
+	puv3_rtc_mem = request_mem_region(res->start,
+					 res->end-res->start+1,
+					 pdev->name);
+
+	if (puv3_rtc_mem == NULL) {
+		dev_err(&pdev->dev, "failed to reserve memory region\n");
+		ret = -ENOENT;
+		goto err_nores;
+	}
+
+	puv3_rtc_enable(pdev, 1);
+
+	/* register RTC and exit */
+
+	rtc = rtc_device_register("pkunity", &pdev->dev, &puv3_rtcops,
+				  THIS_MODULE);
+
+	if (IS_ERR(rtc)) {
+		dev_err(&pdev->dev, "cannot attach rtc\n");
+		ret = PTR_ERR(rtc);
+		goto err_nortc;
+	}
+
+	/* platform setup code should have handled this; sigh */
+	if (!device_can_wakeup(&pdev->dev))
+		device_init_wakeup(&pdev->dev, 1);
+
+	platform_set_drvdata(pdev, rtc);
+	return 0;
+
+ err_nortc:
+	puv3_rtc_enable(pdev, 0);
+	release_resource(puv3_rtc_mem);
+
+ err_nores:
+	return ret;
+}
+
+#ifdef CONFIG_PM
+
+/* RTC Power management control */
+
+static int ticnt_save;
+
+static int puv3_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	/* save RTAR for anyone using periodic interrupts */
+	ticnt_save = readl(RTC_RTAR);
+	puv3_rtc_enable(pdev, 0);
+	return 0;
+}
+
+static int puv3_rtc_resume(struct platform_device *pdev)
+{
+	puv3_rtc_enable(pdev, 1);
+	writel(ticnt_save, RTC_RTAR);
+	return 0;
+}
+#else
+#define puv3_rtc_suspend NULL
+#define puv3_rtc_resume  NULL
+#endif
+
+static struct platform_driver puv3_rtcdrv = {
+	.probe		= puv3_rtc_probe,
+	.remove		= __devexit_p(puv3_rtc_remove),
+	.suspend	= puv3_rtc_suspend,
+	.resume		= puv3_rtc_resume,
+	.driver		= {
+		.name	= "PKUnity-v3-RTC",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static char __initdata banner[] = "PKUnity-v3 RTC, (c) 2009 PKUnity Co.\n";
+
+static int __init puv3_rtc_init(void)
+{
+	printk(banner);
+	return platform_driver_register(&puv3_rtcdrv);
+}
+
+static void __exit puv3_rtc_exit(void)
+{
+	platform_driver_unregister(&puv3_rtcdrv);
+}
+
+module_init(puv3_rtc_init);
+module_exit(puv3_rtc_exit);
+
+MODULE_DESCRIPTION("RTC Driver for the PKUnity v3 chip");
+MODULE_AUTHOR("Hu Dongliang");
+MODULE_LICENSE("GPL v2");
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/setup.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/setup.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,349 @@
+/*
+ * linux/arch/unicore32/kernel/setup.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/stddef.h>
+#include <linux/ioport.h>
+#include <linux/delay.h>
+#include <linux/utsname.h>
+#include <linux/initrd.h>
+#include <linux/console.h>
+#include <linux/bootmem.h>
+#include <linux/seq_file.h>
+#include <linux/screen_info.h>
+#include <linux/init.h>
+#include <linux/root_dev.h>
+#include <linux/cpu.h>
+#include <linux/interrupt.h>
+#include <linux/smp.h>
+#include <linux/fs.h>
+#include <linux/proc_fs.h>
+#include <linux/memblock.h>
+#include <linux/elf.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/traps.h>
+
+#include "setup.h"
+
+#ifndef MEM_SIZE
+#define MEM_SIZE	(16*1024*1024)
+#endif
+
+struct stack {
+	u32 irq[3];
+	u32 abt[3];
+	u32 und[3];
+} ____cacheline_aligned;
+
+static struct stack stacks[NR_CPUS];
+
+char elf_platform[ELF_PLATFORM_SIZE];
+EXPORT_SYMBOL(elf_platform);
+
+static char __initdata cmd_line[COMMAND_LINE_SIZE];
+
+static char default_command_line[COMMAND_LINE_SIZE] __initdata = CONFIG_CMDLINE;
+
+/*
+ * Standard memory resources
+ */
+static struct resource mem_res[] = {
+	{
+		.name = "Kernel text",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	},
+	{
+		.name = "Kernel data",
+		.start = 0,
+		.end = 0,
+		.flags = IORESOURCE_MEM
+	}
+};
+
+#define kernel_code mem_res[0]
+#define kernel_data mem_res[1]
+
+/*
+ * These functions re-use the assembly code in head.S, which
+ * already provide the required functionality.
+ */
+static void __init setup_processor(void)
+{
+	printk(KERN_DEFAULT "CPU: UniCore-II [%08x] revision %d, cr=%08lx\n",
+	       uc32_cpuid, (int)(uc32_cpuid >> 16) & 15, cr_alignment);
+
+	sprintf(init_utsname()->machine, "puv3");
+	sprintf(elf_platform, "ucv2");
+}
+
+/*
+ * cpu_init - initialise one CPU.
+ *
+ * cpu_init sets up the per-CPU stacks.
+ */
+void cpu_init(void)
+{
+	unsigned int cpu = smp_processor_id();
+	struct stack *stk = &stacks[cpu];
+
+	/*
+	 * setup stacks for re-entrant exception handlers
+	 */
+	__asm__ (
+	"mov.a	asr, %1\n\t"
+	"add	sp, %0, %2\n\t"
+	"mov.a	asr, %3\n\t"
+	"add	sp, %0, %4\n\t"
+	"mov.a	asr, %5\n\t"
+	"add	sp, %0, %6\n\t"
+	"mov.a	asr, %7"
+	    :
+	    : "r" (stk),
+	      "r" (PSR_R_BIT | PSR_I_BIT | INTR_MODE),
+	      "I" (offsetof(struct stack, irq[0])),
+	      "r" (PSR_R_BIT | PSR_I_BIT | ABRT_MODE),
+	      "I" (offsetof(struct stack, abt[0])),
+	      "r" (PSR_R_BIT | PSR_I_BIT | EXTN_MODE),
+	      "I" (offsetof(struct stack, und[0])),
+	      "r" (PSR_R_BIT | PSR_I_BIT | PRIV_MODE)
+	: "r30", "cc");
+}
+
+static int __init uc32_add_memory(unsigned long start, unsigned long size)
+{
+	struct membank *bank = &meminfo.bank[meminfo.nr_banks];
+
+	if (meminfo.nr_banks >= NR_BANKS) {
+		printk(KERN_CRIT "NR_BANKS too low, "
+			"ignoring memory at %#lx\n", start);
+		return -EINVAL;
+	}
+
+	/*
+	 * Ensure that start/size are aligned to a page boundary.
+	 * Size is appropriately rounded down, start is rounded up.
+	 */
+	size -= start & ~PAGE_MASK;
+
+	bank->start = PAGE_ALIGN(start);
+	bank->size  = size & PAGE_MASK;
+
+	/*
+	 * Check whether this memory region has non-zero size or
+	 * invalid node number.
+	 */
+	if (bank->size == 0)
+		return -EINVAL;
+
+	meminfo.nr_banks++;
+	return 0;
+}
+
+/*
+ * Pick out the memory size.  We look for mem=size@start,
+ * where start and size are "size[KkMm]"
+ */
+static int __init early_mem(char *p)
+{
+	static int usermem __initdata = 1;
+	unsigned long size, start;
+	char *endp;
+
+	/*
+	 * If the user specifies memory size, we
+	 * blow away any automatically generated
+	 * size.
+	 */
+	if (usermem) {
+		usermem = 0;
+		meminfo.nr_banks = 0;
+	}
+
+	start = PHYS_OFFSET;
+	size  = memparse(p, &endp);
+	if (*endp == '@')
+		start = memparse(endp + 1, NULL);
+
+	uc32_add_memory(start, size);
+
+	return 0;
+}
+early_param("mem", early_mem);
+
+static void __init
+request_standard_resources(struct meminfo *mi)
+{
+	struct resource *res;
+	int i;
+
+	kernel_code.start   = virt_to_phys(_stext);
+	kernel_code.end     = virt_to_phys(_etext - 1);
+	kernel_data.start   = virt_to_phys(_sdata);
+	kernel_data.end     = virt_to_phys(_end - 1);
+
+	for (i = 0; i < mi->nr_banks; i++) {
+		if (mi->bank[i].size == 0)
+			continue;
+
+		res = alloc_bootmem_low(sizeof(*res));
+		res->name  = "System RAM";
+		res->start = mi->bank[i].start;
+		res->end   = mi->bank[i].start + mi->bank[i].size - 1;
+		res->flags = IORESOURCE_MEM | IORESOURCE_BUSY;
+
+		request_resource(&iomem_resource, res);
+
+		if (kernel_code.start >= res->start &&
+		    kernel_code.end <= res->end)
+			request_resource(res, &kernel_code);
+		if (kernel_data.start >= res->start &&
+		    kernel_data.end <= res->end)
+			request_resource(res, &kernel_data);
+	}
+}
+
+static void (*init_machine)(void) __initdata;
+
+static int __init customize_machine(void)
+{
+	/* customizes platform devices, or adds new ones */
+	if (init_machine)
+		init_machine();
+	return 0;
+}
+arch_initcall(customize_machine);
+
+void __init setup_arch(char **cmdline_p)
+{
+	char *from = default_command_line;
+
+	setup_processor();
+
+	init_mm.start_code = (unsigned long) _stext;
+	init_mm.end_code   = (unsigned long) _etext;
+	init_mm.end_data   = (unsigned long) _edata;
+	init_mm.brk	   = (unsigned long) _end;
+
+	/* parse_early_param needs a boot_command_line */
+	strlcpy(boot_command_line, from, COMMAND_LINE_SIZE);
+
+	/* populate cmd_line too for later use, preserving boot_command_line */
+	strlcpy(cmd_line, boot_command_line, COMMAND_LINE_SIZE);
+	*cmdline_p = cmd_line;
+
+	parse_early_param();
+
+	uc32_memblock_init(&meminfo);
+
+	paging_init();
+	request_standard_resources(&meminfo);
+
+	cpu_init();
+
+	/*
+	 * Set up various architecture-specific pointers
+	 */
+	init_machine = puv3_core_init;
+
+#ifdef CONFIG_VT
+#if defined(CONFIG_VGA_CONSOLE)
+	conswitchp = &vga_con;
+#elif defined(CONFIG_DUMMY_CONSOLE)
+	conswitchp = &dummy_con;
+#endif
+#endif
+	early_trap_init();
+}
+
+static struct cpu cpuinfo_unicore;
+
+static int __init topology_init(void)
+{
+	int i;
+
+	for_each_possible_cpu(i)
+		register_cpu(&cpuinfo_unicore, i);
+
+	return 0;
+}
+subsys_initcall(topology_init);
+
+#ifdef CONFIG_HAVE_PROC_CPU
+static int __init proc_cpu_init(void)
+{
+	struct proc_dir_entry *res;
+
+	res = proc_mkdir("cpu", NULL);
+	if (!res)
+		return -ENOMEM;
+	return 0;
+}
+fs_initcall(proc_cpu_init);
+#endif
+
+static int c_show(struct seq_file *m, void *v)
+{
+	seq_printf(m, "Processor\t: UniCore-II rev %d (%s)\n",
+		   (int)(uc32_cpuid >> 16) & 15, elf_platform);
+
+	seq_printf(m, "BogoMIPS\t: %lu.%02lu\n",
+		   loops_per_jiffy / (500000/HZ),
+		   (loops_per_jiffy / (5000/HZ)) % 100);
+
+	/* dump out the processor features */
+	seq_puts(m, "Features\t: CMOV UC-F64");
+
+	seq_printf(m, "\nCPU implementer\t: 0x%02x\n", uc32_cpuid >> 24);
+	seq_printf(m, "CPU architecture: 2\n");
+	seq_printf(m, "CPU revision\t: %d\n", (uc32_cpuid >> 16) & 15);
+
+	seq_printf(m, "Cache type\t: write-back\n"
+			"Cache clean\t: cp0 c5 ops\n"
+			"Cache lockdown\t: not support\n"
+			"Cache format\t: Harvard\n");
+
+	seq_puts(m, "\n");
+
+	seq_printf(m, "Hardware\t: PKUnity v3\n");
+
+	return 0;
+}
+
+static void *c_start(struct seq_file *m, loff_t *pos)
+{
+	return *pos < 1 ? (void *)1 : NULL;
+}
+
+static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+{
+	++*pos;
+	return NULL;
+}
+
+static void c_stop(struct seq_file *m, void *v)
+{
+}
+
+const struct seq_operations cpuinfo_op = {
+	.start	= c_start,
+	.next	= c_next,
+	.stop	= c_stop,
+	.show	= c_show
+};
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/setup.h linux-libre-2.6.39-gnu/arch/unicore32/kernel/setup.h
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/setup.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/setup.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * linux/arch/unicore32/kernel/setup.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 __UNICORE_KERNEL_SETUP_H__
+#define __UNICORE_KERNEL_SETUP_H__
+
+extern void paging_init(void);
+extern void puv3_core_init(void);
+
+extern void puv3_ps2_init(void);
+extern void pci_puv3_preinit(void);
+extern void __init puv3_init_gpio(void);
+
+extern void setup_mm_for_reboot(char mode);
+
+extern char __stubs_start[], __stubs_end[];
+extern char __vectors_start[], __vectors_end[];
+
+extern void kernel_thread_helper(void);
+
+extern void __init early_signal_init(void);
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/signal.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/signal.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/signal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/signal.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,494 @@
+/*
+ * linux/arch/unicore32/kernel/signal.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/errno.h>
+#include <linux/signal.h>
+#include <linux/personality.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/tracehook.h>
+#include <linux/elf.h>
+#include <linux/unistd.h>
+
+#include <asm/cacheflush.h>
+#include <asm/ucontext.h>
+
+#define _BLOCKABLE (~(sigmask(SIGKILL) | sigmask(SIGSTOP)))
+
+/*
+ * For UniCore syscalls, we encode the syscall number into the instruction.
+ */
+#define SWI_SYS_SIGRETURN	(0xff000000) /* error number for new abi */
+#define SWI_SYS_RT_SIGRETURN	(0xff000000 | (__NR_rt_sigreturn))
+#define SWI_SYS_RESTART		(0xff000000 | (__NR_restart_syscall))
+
+#define KERN_SIGRETURN_CODE	(KUSER_VECPAGE_BASE + 0x00000500)
+#define KERN_RESTART_CODE	(KERN_SIGRETURN_CODE + sizeof(sigreturn_codes))
+
+const unsigned long sigreturn_codes[3] = {
+	SWI_SYS_SIGRETURN, SWI_SYS_RT_SIGRETURN,
+};
+
+const unsigned long syscall_restart_code[2] = {
+	SWI_SYS_RESTART,	/* swi	__NR_restart_syscall */
+	0x69efc004,		/* ldr	pc, [sp], #4 */
+};
+
+/*
+ * Do a signal return; undo the signal stack.  These are aligned to 64-bit.
+ */
+struct sigframe {
+	struct ucontext uc;
+	unsigned long retcode[2];
+};
+
+struct rt_sigframe {
+	struct siginfo info;
+	struct sigframe sig;
+};
+
+static int restore_sigframe(struct pt_regs *regs, struct sigframe __user *sf)
+{
+	sigset_t set;
+	int err;
+
+	err = __copy_from_user(&set, &sf->uc.uc_sigmask, sizeof(set));
+	if (err == 0) {
+		sigdelsetmask(&set, ~_BLOCKABLE);
+		spin_lock_irq(&current->sighand->siglock);
+		current->blocked = set;
+		recalc_sigpending();
+		spin_unlock_irq(&current->sighand->siglock);
+	}
+
+	err |= __get_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
+	err |= __get_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
+	err |= __get_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02);
+	err |= __get_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03);
+	err |= __get_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04);
+	err |= __get_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05);
+	err |= __get_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06);
+	err |= __get_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07);
+	err |= __get_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08);
+	err |= __get_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09);
+	err |= __get_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10);
+	err |= __get_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11);
+	err |= __get_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12);
+	err |= __get_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13);
+	err |= __get_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14);
+	err |= __get_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15);
+	err |= __get_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16);
+	err |= __get_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17);
+	err |= __get_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18);
+	err |= __get_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19);
+	err |= __get_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20);
+	err |= __get_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21);
+	err |= __get_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22);
+	err |= __get_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23);
+	err |= __get_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24);
+	err |= __get_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25);
+	err |= __get_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26);
+	err |= __get_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp);
+	err |= __get_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip);
+	err |= __get_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp);
+	err |= __get_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr);
+	err |= __get_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc);
+	err |= __get_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr);
+
+	err |= !valid_user_regs(regs);
+
+	return err;
+}
+
+asmlinkage int __sys_rt_sigreturn(struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame;
+
+	/* Always make any pending restarted system calls return -EINTR */
+	current_thread_info()->restart_block.fn = do_no_restart_syscall;
+
+	/*
+	 * Since we stacked the signal on a 64-bit boundary,
+	 * then 'sp' should be word aligned here.  If it's
+	 * not, then the user is trying to mess with us.
+	 */
+	if (regs->UCreg_sp & 7)
+		goto badframe;
+
+	frame = (struct rt_sigframe __user *)regs->UCreg_sp;
+
+	if (!access_ok(VERIFY_READ, frame, sizeof(*frame)))
+		goto badframe;
+
+	if (restore_sigframe(regs, &frame->sig))
+		goto badframe;
+
+	if (do_sigaltstack(&frame->sig.uc.uc_stack, NULL, regs->UCreg_sp)
+			== -EFAULT)
+		goto badframe;
+
+	return regs->UCreg_00;
+
+badframe:
+	force_sig(SIGSEGV, current);
+	return 0;
+}
+
+static int setup_sigframe(struct sigframe __user *sf, struct pt_regs *regs,
+		sigset_t *set)
+{
+	int err = 0;
+
+	err |= __put_user(regs->UCreg_00, &sf->uc.uc_mcontext.regs.UCreg_00);
+	err |= __put_user(regs->UCreg_01, &sf->uc.uc_mcontext.regs.UCreg_01);
+	err |= __put_user(regs->UCreg_02, &sf->uc.uc_mcontext.regs.UCreg_02);
+	err |= __put_user(regs->UCreg_03, &sf->uc.uc_mcontext.regs.UCreg_03);
+	err |= __put_user(regs->UCreg_04, &sf->uc.uc_mcontext.regs.UCreg_04);
+	err |= __put_user(regs->UCreg_05, &sf->uc.uc_mcontext.regs.UCreg_05);
+	err |= __put_user(regs->UCreg_06, &sf->uc.uc_mcontext.regs.UCreg_06);
+	err |= __put_user(regs->UCreg_07, &sf->uc.uc_mcontext.regs.UCreg_07);
+	err |= __put_user(regs->UCreg_08, &sf->uc.uc_mcontext.regs.UCreg_08);
+	err |= __put_user(regs->UCreg_09, &sf->uc.uc_mcontext.regs.UCreg_09);
+	err |= __put_user(regs->UCreg_10, &sf->uc.uc_mcontext.regs.UCreg_10);
+	err |= __put_user(regs->UCreg_11, &sf->uc.uc_mcontext.regs.UCreg_11);
+	err |= __put_user(regs->UCreg_12, &sf->uc.uc_mcontext.regs.UCreg_12);
+	err |= __put_user(regs->UCreg_13, &sf->uc.uc_mcontext.regs.UCreg_13);
+	err |= __put_user(regs->UCreg_14, &sf->uc.uc_mcontext.regs.UCreg_14);
+	err |= __put_user(regs->UCreg_15, &sf->uc.uc_mcontext.regs.UCreg_15);
+	err |= __put_user(regs->UCreg_16, &sf->uc.uc_mcontext.regs.UCreg_16);
+	err |= __put_user(regs->UCreg_17, &sf->uc.uc_mcontext.regs.UCreg_17);
+	err |= __put_user(regs->UCreg_18, &sf->uc.uc_mcontext.regs.UCreg_18);
+	err |= __put_user(regs->UCreg_19, &sf->uc.uc_mcontext.regs.UCreg_19);
+	err |= __put_user(regs->UCreg_20, &sf->uc.uc_mcontext.regs.UCreg_20);
+	err |= __put_user(regs->UCreg_21, &sf->uc.uc_mcontext.regs.UCreg_21);
+	err |= __put_user(regs->UCreg_22, &sf->uc.uc_mcontext.regs.UCreg_22);
+	err |= __put_user(regs->UCreg_23, &sf->uc.uc_mcontext.regs.UCreg_23);
+	err |= __put_user(regs->UCreg_24, &sf->uc.uc_mcontext.regs.UCreg_24);
+	err |= __put_user(regs->UCreg_25, &sf->uc.uc_mcontext.regs.UCreg_25);
+	err |= __put_user(regs->UCreg_26, &sf->uc.uc_mcontext.regs.UCreg_26);
+	err |= __put_user(regs->UCreg_fp, &sf->uc.uc_mcontext.regs.UCreg_fp);
+	err |= __put_user(regs->UCreg_ip, &sf->uc.uc_mcontext.regs.UCreg_ip);
+	err |= __put_user(regs->UCreg_sp, &sf->uc.uc_mcontext.regs.UCreg_sp);
+	err |= __put_user(regs->UCreg_lr, &sf->uc.uc_mcontext.regs.UCreg_lr);
+	err |= __put_user(regs->UCreg_pc, &sf->uc.uc_mcontext.regs.UCreg_pc);
+	err |= __put_user(regs->UCreg_asr, &sf->uc.uc_mcontext.regs.UCreg_asr);
+
+	err |= __put_user(current->thread.trap_no,
+			&sf->uc.uc_mcontext.trap_no);
+	err |= __put_user(current->thread.error_code,
+			&sf->uc.uc_mcontext.error_code);
+	err |= __put_user(current->thread.address,
+			&sf->uc.uc_mcontext.fault_address);
+	err |= __put_user(set->sig[0], &sf->uc.uc_mcontext.oldmask);
+
+	err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(*set));
+
+	return err;
+}
+
+static inline void __user *get_sigframe(struct k_sigaction *ka,
+		struct pt_regs *regs, int framesize)
+{
+	unsigned long sp = regs->UCreg_sp;
+	void __user *frame;
+
+	/*
+	 * This is the X/Open sanctioned signal stack switching.
+	 */
+	if ((ka->sa.sa_flags & SA_ONSTACK) && !sas_ss_flags(sp))
+		sp = current->sas_ss_sp + current->sas_ss_size;
+
+	/*
+	 * ATPCS B01 mandates 8-byte alignment
+	 */
+	frame = (void __user *)((sp - framesize) & ~7);
+
+	/*
+	 * Check that we can actually write to the signal frame.
+	 */
+	if (!access_ok(VERIFY_WRITE, frame, framesize))
+		frame = NULL;
+
+	return frame;
+}
+
+static int setup_return(struct pt_regs *regs, struct k_sigaction *ka,
+	     unsigned long __user *rc, void __user *frame, int usig)
+{
+	unsigned long handler = (unsigned long)ka->sa.sa_handler;
+	unsigned long retcode;
+	unsigned long asr = regs->UCreg_asr & ~PSR_f;
+
+	unsigned int idx = 0;
+
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		idx += 1;
+
+	if (__put_user(sigreturn_codes[idx],   rc) ||
+	    __put_user(sigreturn_codes[idx+1], rc+1))
+		return 1;
+
+	retcode = KERN_SIGRETURN_CODE + (idx << 2);
+
+	regs->UCreg_00 = usig;
+	regs->UCreg_sp = (unsigned long)frame;
+	regs->UCreg_lr = retcode;
+	regs->UCreg_pc = handler;
+	regs->UCreg_asr = asr;
+
+	return 0;
+}
+
+static int setup_frame(int usig, struct k_sigaction *ka,
+		sigset_t *set, struct pt_regs *regs)
+{
+	struct sigframe __user *frame = get_sigframe(ka, regs, sizeof(*frame));
+	int err = 0;
+
+	if (!frame)
+		return 1;
+
+	/*
+	 * Set uc.uc_flags to a value which sc.trap_no would never have.
+	 */
+	err |= __put_user(0x5ac3c35a, &frame->uc.uc_flags);
+
+	err |= setup_sigframe(frame, regs, set);
+	if (err == 0)
+		err |= setup_return(regs, ka, frame->retcode, frame, usig);
+
+	return err;
+}
+
+static int setup_rt_frame(int usig, struct k_sigaction *ka, siginfo_t *info,
+	       sigset_t *set, struct pt_regs *regs)
+{
+	struct rt_sigframe __user *frame =
+			get_sigframe(ka, regs, sizeof(*frame));
+	stack_t stack;
+	int err = 0;
+
+	if (!frame)
+		return 1;
+
+	err |= copy_siginfo_to_user(&frame->info, info);
+
+	err |= __put_user(0, &frame->sig.uc.uc_flags);
+	err |= __put_user(NULL, &frame->sig.uc.uc_link);
+
+	memset(&stack, 0, sizeof(stack));
+	stack.ss_sp = (void __user *)current->sas_ss_sp;
+	stack.ss_flags = sas_ss_flags(regs->UCreg_sp);
+	stack.ss_size = current->sas_ss_size;
+	err |= __copy_to_user(&frame->sig.uc.uc_stack, &stack, sizeof(stack));
+
+	err |= setup_sigframe(&frame->sig, regs, set);
+	if (err == 0)
+		err |= setup_return(regs, ka, frame->sig.retcode, frame, usig);
+
+	if (err == 0) {
+		/*
+		 * For realtime signals we must also set the second and third
+		 * arguments for the signal handler.
+		 */
+		regs->UCreg_01 = (unsigned long)&frame->info;
+		regs->UCreg_02 = (unsigned long)&frame->sig.uc;
+	}
+
+	return err;
+}
+
+static inline void setup_syscall_restart(struct pt_regs *regs)
+{
+	regs->UCreg_00 = regs->UCreg_ORIG_00;
+	regs->UCreg_pc -= 4;
+}
+
+/*
+ * OK, we're invoking a handler
+ */
+static int handle_signal(unsigned long sig, struct k_sigaction *ka,
+	      siginfo_t *info, sigset_t *oldset,
+	      struct pt_regs *regs, int syscall)
+{
+	struct thread_info *thread = current_thread_info();
+	struct task_struct *tsk = current;
+	int usig = sig;
+	int ret;
+
+	/*
+	 * If we were from a system call, check for system call restarting...
+	 */
+	if (syscall) {
+		switch (regs->UCreg_00) {
+		case -ERESTART_RESTARTBLOCK:
+		case -ERESTARTNOHAND:
+			regs->UCreg_00 = -EINTR;
+			break;
+		case -ERESTARTSYS:
+			if (!(ka->sa.sa_flags & SA_RESTART)) {
+				regs->UCreg_00 = -EINTR;
+				break;
+			}
+			/* fallthrough */
+		case -ERESTARTNOINTR:
+			setup_syscall_restart(regs);
+		}
+	}
+
+	/*
+	 * translate the signal
+	 */
+	if (usig < 32 && thread->exec_domain
+			&& thread->exec_domain->signal_invmap)
+		usig = thread->exec_domain->signal_invmap[usig];
+
+	/*
+	 * Set up the stack frame
+	 */
+	if (ka->sa.sa_flags & SA_SIGINFO)
+		ret = setup_rt_frame(usig, ka, info, oldset, regs);
+	else
+		ret = setup_frame(usig, ka, oldset, regs);
+
+	/*
+	 * Check that the resulting registers are actually sane.
+	 */
+	ret |= !valid_user_regs(regs);
+
+	if (ret != 0) {
+		force_sigsegv(sig, tsk);
+		return ret;
+	}
+
+	/*
+	 * Block the signal if we were successful.
+	 */
+	spin_lock_irq(&tsk->sighand->siglock);
+	sigorsets(&tsk->blocked, &tsk->blocked,
+		  &ka->sa.sa_mask);
+	if (!(ka->sa.sa_flags & SA_NODEFER))
+		sigaddset(&tsk->blocked, sig);
+	recalc_sigpending();
+	spin_unlock_irq(&tsk->sighand->siglock);
+
+	return 0;
+}
+
+/*
+ * Note that 'init' is a special process: it doesn't get signals it doesn't
+ * want to handle. Thus you cannot kill init even with a SIGKILL even by
+ * mistake.
+ *
+ * Note that we go through the signals twice: once to check the signals that
+ * the kernel can handle, and then we build all the user-level signal handling
+ * stack-frames in one go after that.
+ */
+static void do_signal(struct pt_regs *regs, int syscall)
+{
+	struct k_sigaction ka;
+	siginfo_t info;
+	int signr;
+
+	/*
+	 * We want the common case to go fast, which
+	 * is why we may in certain cases get here from
+	 * kernel mode. Just return without doing anything
+	 * if so.
+	 */
+	if (!user_mode(regs))
+		return;
+
+	if (try_to_freeze())
+		goto no_signal;
+
+	signr = get_signal_to_deliver(&info, &ka, regs, NULL);
+	if (signr > 0) {
+		sigset_t *oldset;
+
+		if (test_thread_flag(TIF_RESTORE_SIGMASK))
+			oldset = &current->saved_sigmask;
+		else
+			oldset = &current->blocked;
+		if (handle_signal(signr, &ka, &info, oldset, regs, syscall)
+				== 0) {
+			/*
+			 * 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 TIF_RESTORE_SIGMASK flag.
+			 */
+			if (test_thread_flag(TIF_RESTORE_SIGMASK))
+				clear_thread_flag(TIF_RESTORE_SIGMASK);
+		}
+		return;
+	}
+
+ no_signal:
+	/*
+	 * No signal to deliver to the process - restart the syscall.
+	 */
+	if (syscall) {
+		if (regs->UCreg_00 == -ERESTART_RESTARTBLOCK) {
+				u32 __user *usp;
+
+				regs->UCreg_sp -= 4;
+				usp = (u32 __user *)regs->UCreg_sp;
+
+				if (put_user(regs->UCreg_pc, usp) == 0) {
+					regs->UCreg_pc = KERN_RESTART_CODE;
+				} else {
+					regs->UCreg_sp += 4;
+					force_sigsegv(0, current);
+				}
+		}
+		if (regs->UCreg_00 == -ERESTARTNOHAND ||
+		    regs->UCreg_00 == -ERESTARTSYS ||
+		    regs->UCreg_00 == -ERESTARTNOINTR) {
+			setup_syscall_restart(regs);
+		}
+
+		/* If there's no signal to deliver, we just put the saved
+		 * sigmask back.
+		 */
+		if (test_thread_flag(TIF_RESTORE_SIGMASK)) {
+			clear_thread_flag(TIF_RESTORE_SIGMASK);
+			sigprocmask(SIG_SETMASK, &current->saved_sigmask, NULL);
+		}
+	}
+}
+
+asmlinkage void do_notify_resume(struct pt_regs *regs,
+		unsigned int thread_flags, int syscall)
+{
+	if (thread_flags & _TIF_SIGPENDING)
+		do_signal(regs, syscall);
+
+	if (thread_flags & _TIF_NOTIFY_RESUME) {
+		clear_thread_flag(TIF_NOTIFY_RESUME);
+		tracehook_notify_resume(regs);
+		if (current->replacement_session_keyring)
+			key_replace_session_keyring();
+	}
+}
+
+/*
+ * Copy signal return handlers into the vector page, and
+ * set sigreturn to be a pointer to these.
+ */
+void __init early_signal_init(void)
+{
+	memcpy((void *)kuser_vecpage_to_vectors(KERN_SIGRETURN_CODE),
+			sigreturn_codes, sizeof(sigreturn_codes));
+	memcpy((void *)kuser_vecpage_to_vectors(KERN_RESTART_CODE),
+			syscall_restart_code, sizeof(syscall_restart_code));
+	/* Need not to flush icache, since early_trap_init will do it last. */
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/sleep.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/sleep.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/sleep.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/sleep.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,202 @@
+/*
+ * linux/arch/unicore32/kernel/sleep.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/hardware.h>
+
+		.text
+
+pkunity_cpu_save_cp:
+
+	@ get coprocessor registers
+
+	movc	r3, p0.c7, #0			@ PID
+	movc	r4, p0.c2, #0			@ translation table base addr
+	movc	r5, p0.c1, #0			@ control reg
+
+
+	@ store them plus current virtual stack ptr on stack
+	mov	r6, sp
+	stm.w	(r3 - r6), [sp-]
+
+	mov	pc, lr
+
+pkunity_cpu_save_sp:
+	@ preserve phys address of stack
+	mov	r0, sp
+	stw.w	lr, [sp+], #-4
+	b.l	sleep_phys_sp
+	ldw	r1, =sleep_save_sp
+	stw	r0, [r1]
+	ldw.w	pc, [sp]+, #4
+
+/*
+ * puv3_cpu_suspend()
+ *
+ * Forces CPU into sleep state.
+ *
+ * r0 = value for PWRMODE M field for desired sleep state
+ */
+
+ENTRY(puv3_cpu_suspend)
+	stm.w	(r16 - r27, lr), [sp-]		@ save registers on stack
+	stm.w	(r4 - r15), [sp-]		@ save registers on stack
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	sfm.w	(f0  - f7 ), [sp-]
+	sfm.w	(f8  - f15), [sp-]
+	sfm.w	(f16 - f23), [sp-]
+	sfm.w	(f24 - f31), [sp-]
+	cff	r4, s31
+	stm.w	(r4), [sp-]
+#endif
+	b.l	pkunity_cpu_save_cp
+
+	b.l	pkunity_cpu_save_sp
+
+	@ clean data cache
+	mov	r1, #0
+	movc	p0.c5, r1, #14
+	nop
+	nop
+	nop
+	nop
+
+
+
+	@ DDR2 BaseAddr
+	ldw	r0, =(PKUNITY_DDR2CTRL_BASE)
+
+	@ PM BaseAddr
+	ldw	r1, =(PKUNITY_PM_BASE)
+
+	@ set PLL_SYS_CFG reg, 275
+	movl	r6, #0x00002401
+	stw	r6, [r1+], #0x18
+	@ set PLL_DDR_CFG reg, 66MHz
+	movl	r6, #0x00100c00
+	stw	r6, [r1+], #0x1c
+
+	@ set wake up source
+	movl	r8, #0x800001ff		@ epip4d
+	stw	r8, [r1+], #0xc
+
+	@ set PGSR
+	movl	r5, #0x40000
+	stw	r5, [r1+], #0x10
+
+	@ prepare DDR2 refresh settings
+	ldw	r5, [r0+], #0x24
+	or	r5, r5, #0x00000001
+
+	@ prepare PMCR for PLL changing
+	movl	r6, #0xc
+
+	@ prepare for closing PLL
+	movl	r7, #0x1
+
+	@ prepare sleep mode
+	mov	r8, #0x1
+
+@	movl	r0, 0x11111111
+@	put_word_ocd r0
+	b	pkunity_cpu_do_suspend
+
+	.ltorg
+	.align	5
+pkunity_cpu_do_suspend:
+	b	101f
+	@ put DDR2 into self-refresh
+100:	stw	r5, [r0+], #0x24
+	@ change PLL
+	stw	r6, [r1]
+	b	1f
+
+	.ltorg
+	.align	5
+101:	b	102f
+	@ wait for PLL changing complete
+1:	ldw	r6, [r1+], #0x44
+	csub.a	r6, #0x1
+	bne	1b
+	b	2f
+
+	.ltorg
+	.align	5
+102:	b	100b
+	@ close PLL
+2:	stw	r7, [r1+], #0x4
+	@ enter sleep mode
+	stw	r8, [r1]
+3:	b	3b
+
+
+
+
+/*
+ * puv3_cpu_resume()
+ *
+ * entry point from bootloader into kernel during resume
+ *
+ * Note: Yes, part of the following code is located into the .data section.
+ *       This is to allow sleep_save_sp to be accessed with a relative load
+ *       while we can't rely on any MMU translation.  We could have put
+ *       sleep_save_sp in the .text section as well, but some setups might
+ *       insist on it to be truly read-only.
+ */
+
+	.data
+	.align 5
+ENTRY(puv3_cpu_resume)
+@	movl	r0, 0x20202020
+@	put_word_ocd r0
+
+	ldw	r0, sleep_save_sp		@ stack phys addr
+	ldw	r2, =resume_after_mmu		@ its absolute virtual address
+	ldm	(r3 - r6), [r0]+		@ CP regs + virt stack ptr
+	mov	sp, r6				@ CP regs + virt stack ptr
+
+	mov	r1, #0
+	movc	p0.c6, r1, #6			@ invalidate I & D TLBs
+	movc	p0.c5, r1, #28			@ invalidate I & D caches, BTB
+
+	movc	p0.c7, r3, #0			@ PID
+	movc	p0.c2, r4, #0			@ translation table base addr
+	movc	p0.c1, r5, #0			@ control reg, turn on mmu
+	nop
+	jump	r2
+	nop
+	nop
+	nop
+	nop
+	nop
+
+sleep_save_sp:
+	.word	0				@ preserve stack phys ptr here
+
+	.text
+resume_after_mmu:
+@	movl	r0, 0x30303030
+@	put_word_ocd r0
+
+#ifdef	CONFIG_UNICORE_FPU_F64
+	lfm.w	(f0  - f7 ), [sp]+
+	lfm.w	(f8  - f15), [sp]+
+	lfm.w	(f16 - f23), [sp]+
+	lfm.w	(f24 - f31), [sp]+
+	ldm.w	(r4), [sp]+
+	ctf	r4, s31
+#endif
+	ldm.w	(r4 - r15), [sp]+		@ restore registers from stack
+	ldm.w	(r16 - r27, pc), [sp]+		@ return to caller
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/stacktrace.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/stacktrace.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/stacktrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/stacktrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,131 @@
+/*
+ * linux/arch/unicore32/kernel/stacktrace.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/sched.h>
+#include <linux/stacktrace.h>
+
+#include <asm/stacktrace.h>
+
+#if defined(CONFIG_FRAME_POINTER)
+/*
+ * Unwind the current stack frame and store the new register values in the
+ * structure passed as argument. Unwinding is equivalent to a function return,
+ * hence the new PC value rather than LR should be used for backtrace.
+ *
+ * With framepointer enabled, a simple function prologue looks like this:
+ *	mov	ip, sp
+ *	stmdb	sp!, {fp, ip, lr, pc}
+ *	sub	fp, ip, #4
+ *
+ * A simple function epilogue looks like this:
+ *	ldm	sp, {fp, sp, pc}
+ *
+ * Note that with framepointer enabled, even the leaf functions have the same
+ * prologue and epilogue, therefore we can ignore the LR value in this case.
+ */
+int notrace unwind_frame(struct stackframe *frame)
+{
+	unsigned long high, low;
+	unsigned long fp = frame->fp;
+
+	/* only go to a higher address on the stack */
+	low = frame->sp;
+	high = ALIGN(low, THREAD_SIZE);
+
+	/* check current frame pointer is within bounds */
+	if (fp < (low + 12) || fp + 4 >= high)
+		return -EINVAL;
+
+	/* restore the registers from the stack frame */
+	frame->fp = *(unsigned long *)(fp - 12);
+	frame->sp = *(unsigned long *)(fp - 8);
+	frame->pc = *(unsigned long *)(fp - 4);
+
+	return 0;
+}
+#endif
+
+void notrace walk_stackframe(struct stackframe *frame,
+		     int (*fn)(struct stackframe *, void *), void *data)
+{
+	while (1) {
+		int ret;
+
+		if (fn(frame, data))
+			break;
+		ret = unwind_frame(frame);
+		if (ret < 0)
+			break;
+	}
+}
+EXPORT_SYMBOL(walk_stackframe);
+
+#ifdef CONFIG_STACKTRACE
+struct stack_trace_data {
+	struct stack_trace *trace;
+	unsigned int no_sched_functions;
+	unsigned int skip;
+};
+
+static int save_trace(struct stackframe *frame, void *d)
+{
+	struct stack_trace_data *data = d;
+	struct stack_trace *trace = data->trace;
+	unsigned long addr = frame->pc;
+
+	if (data->no_sched_functions && in_sched_functions(addr))
+		return 0;
+	if (data->skip) {
+		data->skip--;
+		return 0;
+	}
+
+	trace->entries[trace->nr_entries++] = addr;
+
+	return trace->nr_entries >= trace->max_entries;
+}
+
+void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
+{
+	struct stack_trace_data data;
+	struct stackframe frame;
+
+	data.trace = trace;
+	data.skip = trace->skip;
+
+	if (tsk != current) {
+		data.no_sched_functions = 1;
+		frame.fp = thread_saved_fp(tsk);
+		frame.sp = thread_saved_sp(tsk);
+		frame.lr = 0;		/* recovered from the stack */
+		frame.pc = thread_saved_pc(tsk);
+	} else {
+		register unsigned long current_sp asm("sp");
+
+		data.no_sched_functions = 0;
+		frame.fp = (unsigned long)__builtin_frame_address(0);
+		frame.sp = current_sp;
+		frame.lr = (unsigned long)__builtin_return_address(0);
+		frame.pc = (unsigned long)save_stack_trace_tsk;
+	}
+
+	walk_stackframe(&frame, save_trace, &data);
+	if (trace->nr_entries < trace->max_entries)
+		trace->entries[trace->nr_entries++] = ULONG_MAX;
+}
+
+void save_stack_trace(struct stack_trace *trace)
+{
+	save_stack_trace_tsk(current, trace);
+}
+EXPORT_SYMBOL_GPL(save_stack_trace);
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/sys.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/sys.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/sys.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/sys.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,126 @@
+/*
+ * linux/arch/unicore32/kernel/sys.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/errno.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/sem.h>
+#include <linux/msg.h>
+#include <linux/shm.h>
+#include <linux/stat.h>
+#include <linux/syscalls.h>
+#include <linux/mman.h>
+#include <linux/fs.h>
+#include <linux/file.h>
+#include <linux/ipc.h>
+#include <linux/uaccess.h>
+
+#include <asm/syscalls.h>
+#include <asm/cacheflush.h>
+
+/* Clone a task - this clones the calling program thread.
+ * This is called indirectly via a small wrapper
+ */
+asmlinkage long __sys_clone(unsigned long clone_flags, unsigned long newsp,
+			 void __user *parent_tid, void __user *child_tid,
+			 struct pt_regs *regs)
+{
+	if (!newsp)
+		newsp = regs->UCreg_sp;
+
+	return do_fork(clone_flags, newsp, regs, 0,
+			parent_tid, child_tid);
+}
+
+/* sys_execve() executes a new program.
+ * This is called indirectly via a small wrapper
+ */
+asmlinkage long __sys_execve(const char __user *filename,
+			  const char __user *const __user *argv,
+			  const char __user *const __user *envp,
+			  struct pt_regs *regs)
+{
+	int error;
+	char *fn;
+
+	fn = getname(filename);
+	error = PTR_ERR(fn);
+	if (IS_ERR(fn))
+		goto out;
+	error = do_execve(fn, argv, envp, regs);
+	putname(fn);
+out:
+	return error;
+}
+
+int kernel_execve(const char *filename,
+		  const char *const argv[],
+		  const char *const envp[])
+{
+	struct pt_regs regs;
+	int ret;
+
+	memset(&regs, 0, sizeof(struct pt_regs));
+	ret = do_execve(filename,
+			(const char __user *const __user *)argv,
+			(const char __user *const __user *)envp, &regs);
+	if (ret < 0)
+		goto out;
+
+	/*
+	 * Save argc to the register structure for userspace.
+	 */
+	regs.UCreg_00 = ret;
+
+	/*
+	 * We were successful.  We won't be returning to our caller, but
+	 * instead to user space by manipulating the kernel stack.
+	 */
+	asm("add	r0, %0, %1\n\t"
+		"mov	r1, %2\n\t"
+		"mov	r2, %3\n\t"
+		"mov	r22, #0\n\t"	/* not a syscall */
+		"mov	r23, %0\n\t"	/* thread structure */
+		"b.l	memmove\n\t"	/* copy regs to top of stack */
+		"mov	sp, r0\n\t"	/* reposition stack pointer */
+		"b	ret_to_user"
+		:
+		: "r" (current_thread_info()),
+		  "Ir" (THREAD_START_SP - sizeof(regs)),
+		  "r" (&regs),
+		  "Ir" (sizeof(regs))
+		: "r0", "r1", "r2", "r3", "ip", "lr", "memory");
+
+ out:
+	return ret;
+}
+EXPORT_SYMBOL(kernel_execve);
+
+/* Note: used by the compat code even in 64-bit Linux. */
+SYSCALL_DEFINE6(mmap2, unsigned long, addr, unsigned long, len,
+		unsigned long, prot, unsigned long, flags,
+		unsigned long, fd, unsigned long, off_4k)
+{
+	return sys_mmap_pgoff(addr, len, prot, flags, fd,
+			      off_4k);
+}
+
+/* Provide the actual syscall number to call mapping. */
+#undef __SYSCALL
+#define __SYSCALL(nr, call)	[nr] = (call),
+
+/* Note that we don't include <linux/unistd.h> but <asm/unistd.h> */
+void *sys_call_table[__NR_syscalls] = {
+	[0 ... __NR_syscalls-1] = sys_ni_syscall,
+#include <asm/unistd.h>
+};
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/time.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/time.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,143 @@
+/*
+ * linux/arch/unicore32/kernel/time.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/errno.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/timex.h>
+#include <linux/clockchips.h>
+
+#include <mach/hardware.h>
+
+#define MIN_OSCR_DELTA 2
+
+static irqreturn_t puv3_ost0_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *c = dev_id;
+
+	/* Disarm the compare/match, signal the event. */
+	writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
+	writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
+	c->event_handler(c);
+
+	return IRQ_HANDLED;
+}
+
+static int
+puv3_osmr0_set_next_event(unsigned long delta, struct clock_event_device *c)
+{
+	unsigned long next, oscr;
+
+	writel(readl(OST_OIER) | OST_OIER_E0, OST_OIER);
+	next = readl(OST_OSCR) + delta;
+	writel(next, OST_OSMR0);
+	oscr = readl(OST_OSCR);
+
+	return (signed)(next - oscr) <= MIN_OSCR_DELTA ? -ETIME : 0;
+}
+
+static void
+puv3_osmr0_set_mode(enum clock_event_mode mode, struct clock_event_device *c)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+	case CLOCK_EVT_MODE_UNUSED:
+	case CLOCK_EVT_MODE_SHUTDOWN:
+		writel(readl(OST_OIER) & ~OST_OIER_E0, OST_OIER);
+		writel(readl(OST_OSSR) & ~OST_OSSR_M0, OST_OSSR);
+		break;
+
+	case CLOCK_EVT_MODE_RESUME:
+	case CLOCK_EVT_MODE_PERIODIC:
+		break;
+	}
+}
+
+static struct clock_event_device ckevt_puv3_osmr0 = {
+	.name		= "osmr0",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= puv3_osmr0_set_next_event,
+	.set_mode	= puv3_osmr0_set_mode,
+};
+
+static cycle_t puv3_read_oscr(struct clocksource *cs)
+{
+	return readl(OST_OSCR);
+}
+
+static struct clocksource cksrc_puv3_oscr = {
+	.name		= "oscr",
+	.rating		= 200,
+	.read		= puv3_read_oscr,
+	.mask		= CLOCKSOURCE_MASK(32),
+	.flags		= CLOCK_SOURCE_IS_CONTINUOUS,
+};
+
+static struct irqaction puv3_timer_irq = {
+	.name		= "ost0",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= puv3_ost0_interrupt,
+	.dev_id		= &ckevt_puv3_osmr0,
+};
+
+void __init time_init(void)
+{
+	writel(0, OST_OIER);		/* disable any timer interrupts */
+	writel(0, OST_OSSR);		/* clear status on all timers */
+
+	clockevents_calc_mult_shift(&ckevt_puv3_osmr0, CLOCK_TICK_RATE, 5);
+
+	ckevt_puv3_osmr0.max_delta_ns =
+		clockevent_delta2ns(0x7fffffff, &ckevt_puv3_osmr0);
+	ckevt_puv3_osmr0.min_delta_ns =
+		clockevent_delta2ns(MIN_OSCR_DELTA * 2, &ckevt_puv3_osmr0) + 1;
+	ckevt_puv3_osmr0.cpumask = cpumask_of(0);
+
+	setup_irq(IRQ_TIMER0, &puv3_timer_irq);
+
+	clocksource_register_hz(&cksrc_puv3_oscr, CLOCK_TICK_RATE);
+	clockevents_register_device(&ckevt_puv3_osmr0);
+}
+
+#ifdef CONFIG_PM
+unsigned long osmr[4], oier;
+
+void puv3_timer_suspend(void)
+{
+	osmr[0] = readl(OST_OSMR0);
+	osmr[1] = readl(OST_OSMR1);
+	osmr[2] = readl(OST_OSMR2);
+	osmr[3] = readl(OST_OSMR3);
+	oier = readl(OST_OIER);
+}
+
+void puv3_timer_resume(void)
+{
+	writel(0, OST_OSSR);
+	writel(osmr[0], OST_OSMR0);
+	writel(osmr[1], OST_OSMR1);
+	writel(osmr[2], OST_OSMR2);
+	writel(osmr[3], OST_OSMR3);
+	writel(oier, OST_OIER);
+
+	/*
+	 * OSMR0 is the system timer: make sure OSCR is sufficiently behind
+	 */
+	writel(readl(OST_OSMR0) - LATCH, OST_OSCR);
+}
+#else
+void puv3_timer_suspend(void) { };
+void puv3_timer_resume(void) { };
+#endif
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/traps.c linux-libre-2.6.39-gnu/arch/unicore32/kernel/traps.c
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/traps.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/traps.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,332 @@
+/*
+ * linux/arch/unicore32/kernel/traps.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  'traps.c' handles hardware exceptions after we have saved some state.
+ *  Mostly a debugging aid, but will probably kill the offending process.
+ */
+#include <linux/module.h>
+#include <linux/signal.h>
+#include <linux/spinlock.h>
+#include <linux/personality.h>
+#include <linux/kallsyms.h>
+#include <linux/kdebug.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+#include <linux/atomic.h>
+#include <linux/unistd.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+#include <asm/traps.h>
+
+#include "setup.h"
+
+static void dump_mem(const char *, const char *, unsigned long, unsigned long);
+
+void dump_backtrace_entry(unsigned long where,
+		unsigned long from, unsigned long frame)
+{
+#ifdef CONFIG_KALLSYMS
+	printk(KERN_DEFAULT "[<%08lx>] (%pS) from [<%08lx>] (%pS)\n",
+			where, (void *)where, from, (void *)from);
+#else
+	printk(KERN_DEFAULT "Function entered at [<%08lx>] from [<%08lx>]\n",
+			where, from);
+#endif
+}
+
+/*
+ * Stack pointers should always be within the kernels view of
+ * physical memory.  If it is not there, then we can't dump
+ * out any information relating to the stack.
+ */
+static int verify_stack(unsigned long sp)
+{
+	if (sp < PAGE_OFFSET ||
+	    (sp > (unsigned long)high_memory && high_memory != NULL))
+		return -EFAULT;
+
+	return 0;
+}
+
+/*
+ * Dump out the contents of some memory nicely...
+ */
+static void dump_mem(const char *lvl, const char *str, unsigned long bottom,
+		     unsigned long top)
+{
+	unsigned long first;
+	mm_segment_t fs;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	printk(KERN_DEFAULT "%s%s(0x%08lx to 0x%08lx)\n",
+			lvl, str, bottom, top);
+
+	for (first = bottom & ~31; first < top; first += 32) {
+		unsigned long p;
+		char str[sizeof(" 12345678") * 8 + 1];
+
+		memset(str, ' ', sizeof(str));
+		str[sizeof(str) - 1] = '\0';
+
+		for (p = first, i = 0; i < 8 && p < top; i++, p += 4) {
+			if (p >= bottom && p < top) {
+				unsigned long val;
+				if (__get_user(val, (unsigned long *)p) == 0)
+					sprintf(str + i * 9, " %08lx", val);
+				else
+					sprintf(str + i * 9, " ????????");
+			}
+		}
+		printk(KERN_DEFAULT "%s%04lx:%s\n", lvl, first & 0xffff, str);
+	}
+
+	set_fs(fs);
+}
+
+static void dump_instr(const char *lvl, struct pt_regs *regs)
+{
+	unsigned long addr = instruction_pointer(regs);
+	const int width = 8;
+	mm_segment_t fs;
+	char str[sizeof("00000000 ") * 5 + 2 + 1], *p = str;
+	int i;
+
+	/*
+	 * We need to switch to kernel mode so that we can use __get_user
+	 * to safely read from kernel space.  Note that we now dump the
+	 * code first, just in case the backtrace kills us.
+	 */
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+
+	for (i = -4; i < 1; i++) {
+		unsigned int val, bad;
+
+		bad = __get_user(val, &((u32 *)addr)[i]);
+
+		if (!bad)
+			p += sprintf(p, i == 0 ? "(%0*x) " : "%0*x ",
+					width, val);
+		else {
+			p += sprintf(p, "bad PC value");
+			break;
+		}
+	}
+	printk(KERN_DEFAULT "%sCode: %s\n", lvl, str);
+
+	set_fs(fs);
+}
+
+static void dump_backtrace(struct pt_regs *regs, struct task_struct *tsk)
+{
+	unsigned int fp, mode;
+	int ok = 1;
+
+	printk(KERN_DEFAULT "Backtrace: ");
+
+	if (!tsk)
+		tsk = current;
+
+	if (regs) {
+		fp = regs->UCreg_fp;
+		mode = processor_mode(regs);
+	} else if (tsk != current) {
+		fp = thread_saved_fp(tsk);
+		mode = 0x10;
+	} else {
+		asm("mov %0, fp" : "=r" (fp) : : "cc");
+		mode = 0x10;
+	}
+
+	if (!fp) {
+		printk("no frame pointer");
+		ok = 0;
+	} else if (verify_stack(fp)) {
+		printk("invalid frame pointer 0x%08x", fp);
+		ok = 0;
+	} else if (fp < (unsigned long)end_of_stack(tsk))
+		printk("frame pointer underflow");
+	printk("\n");
+
+	if (ok)
+		c_backtrace(fp, mode);
+}
+
+void dump_stack(void)
+{
+	dump_backtrace(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+	dump_backtrace(NULL, tsk);
+	barrier();
+}
+
+static int __die(const char *str, int err, struct thread_info *thread,
+		struct pt_regs *regs)
+{
+	struct task_struct *tsk = thread->task;
+	static int die_counter;
+	int ret;
+
+	printk(KERN_EMERG "Internal error: %s: %x [#%d]\n",
+	       str, err, ++die_counter);
+	sysfs_printk_last_file();
+
+	/* trap and error numbers are mostly meaningless on UniCore */
+	ret = notify_die(DIE_OOPS, str, regs, err, tsk->thread.trap_no, \
+			SIGSEGV);
+	if (ret == NOTIFY_STOP)
+		return ret;
+
+	print_modules();
+	__show_regs(regs);
+	printk(KERN_EMERG "Process %.*s (pid: %d, stack limit = 0x%p)\n",
+		TASK_COMM_LEN, tsk->comm, task_pid_nr(tsk), thread + 1);
+
+	if (!user_mode(regs) || in_interrupt()) {
+		dump_mem(KERN_EMERG, "Stack: ", regs->UCreg_sp,
+			 THREAD_SIZE + (unsigned long)task_stack_page(tsk));
+		dump_backtrace(regs, tsk);
+		dump_instr(KERN_EMERG, regs);
+	}
+
+	return ret;
+}
+
+DEFINE_SPINLOCK(die_lock);
+
+/*
+ * This function is protected against re-entrancy.
+ */
+void die(const char *str, struct pt_regs *regs, int err)
+{
+	struct thread_info *thread = current_thread_info();
+	int ret;
+
+	oops_enter();
+
+	spin_lock_irq(&die_lock);
+	console_verbose();
+	bust_spinlocks(1);
+	ret = __die(str, err, thread, regs);
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+	spin_unlock_irq(&die_lock);
+	oops_exit();
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+	if (panic_on_oops)
+		panic("Fatal exception");
+	if (ret != NOTIFY_STOP)
+		do_exit(SIGSEGV);
+}
+
+void uc32_notify_die(const char *str, struct pt_regs *regs,
+		struct siginfo *info, unsigned long err, unsigned long trap)
+{
+	if (user_mode(regs)) {
+		current->thread.error_code = err;
+		current->thread.trap_no = trap;
+
+		force_sig_info(info->si_signo, info, current);
+	} else
+		die(str, regs, err);
+}
+
+/*
+ * bad_mode handles the impossible case in the vectors.  If you see one of
+ * these, then it's extremely serious, and could mean you have buggy hardware.
+ * It never returns, and never tries to sync.  We hope that we can at least
+ * dump out some state information...
+ */
+asmlinkage void bad_mode(struct pt_regs *regs, unsigned int reason)
+{
+	console_verbose();
+
+	printk(KERN_CRIT "Bad mode detected with reason 0x%x\n", reason);
+
+	die("Oops - bad mode", regs, 0);
+	local_irq_disable();
+	panic("bad mode");
+}
+
+void __pte_error(const char *file, int line, unsigned long val)
+{
+	printk(KERN_DEFAULT "%s:%d: bad pte %08lx.\n", file, line, val);
+}
+
+void __pmd_error(const char *file, int line, unsigned long val)
+{
+	printk(KERN_DEFAULT "%s:%d: bad pmd %08lx.\n", file, line, val);
+}
+
+void __pgd_error(const char *file, int line, unsigned long val)
+{
+	printk(KERN_DEFAULT "%s:%d: bad pgd %08lx.\n", file, line, val);
+}
+
+asmlinkage void __div0(void)
+{
+	printk(KERN_DEFAULT "Division by zero in kernel.\n");
+	dump_stack();
+}
+EXPORT_SYMBOL(__div0);
+
+void abort(void)
+{
+	BUG();
+
+	/* if that doesn't kill us, halt */
+	panic("Oops failed to kill thread");
+}
+EXPORT_SYMBOL(abort);
+
+void __init trap_init(void)
+{
+	return;
+}
+
+void __init early_trap_init(void)
+{
+	unsigned long vectors = VECTORS_BASE;
+
+	/*
+	 * Copy the vectors, stubs (in entry-unicore.S)
+	 * into the vector page, mapped at 0xffff0000, and ensure these
+	 * are visible to the instruction stream.
+	 */
+	memcpy((void *)vectors,
+			__vectors_start,
+			__vectors_end - __vectors_start);
+	memcpy((void *)vectors + 0x200,
+			__stubs_start,
+			__stubs_end - __stubs_start);
+
+	early_signal_init();
+
+	flush_icache_range(vectors, vectors + PAGE_SIZE);
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/unicore32/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/unicore32/kernel/vmlinux.lds.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * linux/arch/unicore32/kernel/vmlinux.lds.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <asm-generic/vmlinux.lds.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+#include <asm/page.h>
+#include <asm/cache.h>
+
+OUTPUT_ARCH(unicore32)
+ENTRY(stext)
+
+jiffies = jiffies_64;
+
+SECTIONS
+{
+	. = PAGE_OFFSET + KERNEL_IMAGE_START;
+
+	_text = .;
+	__init_begin = .;
+	HEAD_TEXT_SECTION
+	INIT_TEXT_SECTION(PAGE_SIZE)
+	INIT_DATA_SECTION(16)
+	PERCPU(L1_CACHE_BYTES, PAGE_SIZE)
+	__init_end = .;
+
+	_stext = .;
+	.text : {		/* Real text segment */
+		TEXT_TEXT
+		SCHED_TEXT
+		LOCK_TEXT
+
+		*(.fixup)
+		*(.gnu.warning)
+	}
+	_etext = .;
+
+	_sdata = .;
+	RO_DATA_SECTION(PAGE_SIZE)
+	RW_DATA_SECTION(L1_CACHE_BYTES, PAGE_SIZE, THREAD_SIZE)
+	_edata = .;
+
+	EXCEPTION_TABLE(L1_CACHE_BYTES)
+	NOTES
+
+	BSS_SECTION(0, 0, 0)
+	_end = .;
+
+	STABS_DEBUG
+	DWARF_DEBUG
+
+	DISCARDS		/* Exit code and data */
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/backtrace.S linux-libre-2.6.39-gnu/arch/unicore32/lib/backtrace.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/backtrace.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/backtrace.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,163 @@
+/*
+ * linux/arch/unicore32/lib/backtrace.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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>
+		.text
+
+@ fp is 0 or stack frame
+
+#define frame	v4
+#define sv_fp	v5
+#define sv_pc	v6
+#define offset	v8
+
+ENTRY(__backtrace)
+		mov	r0, fp
+
+ENTRY(c_backtrace)
+
+#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
+		mov	pc, lr
+ENDPROC(__backtrace)
+ENDPROC(c_backtrace)
+#else
+		stm.w	(v4 - v8, lr), [sp-]	@ Save an extra register
+						@ so we have a location...
+		mov.a	frame, r0		@ if frame pointer is zero
+		beq	no_frame		@ we have no stack frames
+
+1:		stm.w	(pc), [sp-]		@ calculate offset of PC stored
+		ldw.w	r0, [sp]+, #4		@ by stmfd for this CPU
+		adr	r1, 1b
+		sub	offset, r0, r1
+
+/*
+ * Stack frame layout:
+ *             optionally saved caller registers (r4 - r10)
+ *             saved fp
+ *             saved sp
+ *             saved lr
+ *    frame => saved pc
+ *             optionally saved arguments (r0 - r3)
+ * saved sp => <next word>
+ *
+ * Functions start with the following code sequence:
+ *                  mov   ip, sp
+ *                  stm.w (r0 - r3), [sp-] (optional)
+ * corrected pc =>  stm.w sp, (..., fp, ip, lr, pc)
+ */
+for_each_frame:
+
+1001:		ldw	sv_pc, [frame+], #0	@ get saved pc
+1002:		ldw	sv_fp, [frame+], #-12	@ get saved fp
+
+		sub	sv_pc, sv_pc, offset	@ Correct PC for prefetching
+
+1003:		ldw	r2, [sv_pc+], #-4	@ if stmfd sp, {args} exists,
+		ldw	r3, .Ldsi+4		@ adjust saved 'pc' back one
+		cxor.a	r3, r2 >> #14		@ instruction
+		beq	201f
+		sub	r0, sv_pc, #4		@ allow for mov
+		b	202f
+201:
+		sub	r0, sv_pc, #8		@ allow for mov + stmia
+202:
+		ldw	r1, [frame+], #-4	@ get saved lr
+		mov	r2, frame
+		b.l	dump_backtrace_entry
+
+		ldw	r1, [sv_pc+], #-4	@ if stmfd sp, {args} exists,
+		ldw	r3, .Ldsi+4
+		cxor.a	r3, r1 >> #14
+		bne	1004f
+		ldw	r0, [frame+], #-8	@ get sp
+		sub	r0, r0, #4		@ point at the last arg
+		b.l	.Ldumpstm		@ dump saved registers
+
+1004:		ldw	r1, [sv_pc+], #0	@ if stmfd {, fp, ip, lr, pc}
+		ldw	r3, .Ldsi		@ instruction exists,
+		cxor.a	r3, r1 >> #14
+		bne	201f
+		sub	r0, frame, #16
+		b.l	.Ldumpstm		@ dump saved registers
+201:
+		cxor.a	sv_fp, #0		@ zero saved fp means
+		beq	no_frame		@ no further frames
+
+		csub.a	sv_fp, frame		@ next frame must be
+		mov	frame, sv_fp		@ above the current frame
+		bua	for_each_frame
+
+1006:		adr	r0, .Lbad
+		mov	r1, frame
+		b.l	printk
+no_frame:	ldm.w	(v4 - v8, pc), [sp]+
+ENDPROC(__backtrace)
+ENDPROC(c_backtrace)
+
+		.pushsection __ex_table,"a"
+		.align	3
+		.long	1001b, 1006b
+		.long	1002b, 1006b
+		.long	1003b, 1006b
+		.long	1004b, 1006b
+		.popsection
+
+#define instr v4
+#define reg   v5
+#define stack v6
+
+.Ldumpstm:	stm.w	(instr, reg, stack, v7, lr), [sp-]
+		mov	stack, r0
+		mov	instr, r1
+		mov	reg, #14
+		mov	v7, #0
+1:		mov	r3, #1
+		csub.a	reg, #8
+		bne	201f
+		sub	reg, reg, #3
+201:
+		cand.a	instr, r3 << reg
+		beq	2f
+		add	v7, v7, #1
+		cxor.a	v7, #6
+		cmoveq	v7, #1
+		cmoveq	r1, #'\n'
+		cmovne	r1, #' '
+		ldw.w	r3, [stack]+, #-4
+		mov	r2, reg
+		csub.a	r2, #8
+		bsl	201f
+		sub	r2, r2, #3
+201:
+		cand.a	instr, #0x40		@ if H is 1, high 16 regs
+		beq	201f
+		add	r2, r2, #0x10		@ so r2 need add 16
+201:
+		adr	r0, .Lfp
+		b.l	printk
+2:		sub.a	reg, reg, #1
+		bns	1b
+		cxor.a	v7, #0
+		beq	201f
+		adr	r0, .Lcr
+		b.l	printk
+201:		ldm.w	(instr, reg, stack, v7, pc), [sp]+
+
+.Lfp:		.asciz	"%cr%d:%08x"
+.Lcr:		.asciz	"\n"
+.Lbad:		.asciz	"Backtrace aborted due to bad frame pointer <%p>\n"
+		.align
+.Ldsi:		.word	0x92eec000 >> 14	@ stm.w sp, (... fp, ip, lr, pc)
+		.word	0x92e10000 >> 14	@ stm.w sp, ()
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/clear_user.S linux-libre-2.6.39-gnu/arch/unicore32/lib/clear_user.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/clear_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/clear_user.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,57 @@
+/*
+ * linux/arch/unicore32/lib/clear_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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>
+
+		.text
+
+/* Prototype: int __clear_user(void *addr, size_t sz)
+ * Purpose  : clear some user memory
+ * Params   : addr - user memory address to clear
+ *          : sz   - number of bytes to clear
+ * Returns  : number of bytes NOT cleared
+ */
+WEAK(__clear_user)
+		stm.w	(lr), [sp-]
+		stm.w	(r1), [sp-]
+		mov	r2, #0
+		csub.a	r1, #4
+		bsl	2f
+		and.a	ip, r0, #3
+		beq	1f
+		csub.a	ip, #2
+		strusr	r2, r0, 1
+		strusr	r2, r0, 1, el
+		strusr	r2, r0, 1, sl
+		rsub	ip, ip, #4
+		sub	r1, r1, ip		@  7  6  5  4  3  2  1
+1:		sub.a	r1, r1, #8		@ -1 -2 -3 -4 -5 -6 -7
+		strusr	r2, r0, 4, ns, rept=2
+		bns	1b
+		add.a	r1, r1, #4		@  3  2  1  0 -1 -2 -3
+		strusr	r2, r0, 4, ns
+2:		cand.a	r1, #2			@ 1x 1x 0x 0x 1x 1x 0x
+		strusr	r2, r0, 1, ne, rept=2
+		cand.a	r1, #1			@ x1 x0 x1 x0 x1 x0 x1
+		beq	3f
+USER(		stb.u	r2, [r0])
+3:		mov	r0, #0
+		ldm.w	(r1), [sp]+
+		ldm.w	(pc), [sp]+
+ENDPROC(__clear_user)
+
+		.pushsection .fixup,"ax"
+		.align	0
+9001:		ldm.w	(r0), [sp]+
+		ldm.w	(pc), [sp]+
+		.popsection
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_from_user.S linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_from_user.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_from_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_from_user.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,108 @@
+/*
+ * linux/arch/unicore32/lib/copy_from_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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>
+
+/*
+ * Prototype:
+ *
+ *	size_t __copy_from_user(void *to, const void *from, size_t n)
+ *
+ * Purpose:
+ *
+ *	copy a block to kernel memory from user memory
+ *
+ * Params:
+ *
+ *	to = kernel memory
+ *	from = user memory
+ *	n = number of bytes to copy
+ *
+ * Return value:
+ *
+ *	Number of bytes NOT copied.
+ */
+
+	.macro ldr1w ptr reg abort
+	ldrusr	\reg, \ptr, 4, abort=\abort
+	.endm
+
+	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
+100:	ldm.w	(\reg1, \reg2, \reg3, \reg4), [\ptr]+
+	.pushsection __ex_table, "a"
+	.align	3
+	.long 100b, \abort
+	.popsection
+	.endm
+
+	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+100:	ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+	.pushsection __ex_table, "a"
+	.align	3
+	.long 100b, \abort
+	.popsection
+	.endm
+
+	.macro ldr1b ptr reg cond=al abort
+	ldrusr	\reg, \ptr, 1, \cond, abort=\abort
+	.endm
+
+	.macro str1w ptr reg abort
+	stw.w \reg, [\ptr]+, #4
+	.endm
+
+	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+	stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+	.endm
+
+	.macro str1b ptr reg cond=al abort
+	.ifnc	\cond, al
+	b\cond	201f
+	b	202f
+	.endif
+201:	stb.w \reg, [\ptr]+, #1
+202:
+	.endm
+
+	.macro enter
+	mov	r3, #0
+	stm.w	(r0, r2, r3), [sp-]
+	.endm
+
+	.macro exit
+	add	sp, sp, #8
+	ldm.w	(r0), [sp]+
+	mov	pc, lr
+	.endm
+
+	.text
+
+ENTRY(__copy_from_user)
+
+#include "copy_template.S"
+
+ENDPROC(__copy_from_user)
+
+	.pushsection .fixup,"ax"
+	.align 0
+	copy_abort_preamble
+	ldm.w	(r1, r2), [sp]+
+	sub	r3, r0, r1
+	rsub	r2, r3, r2
+	stw	r2, [sp]
+	mov	r1, #0
+	b.l	memset
+	ldw.w	r0, [sp]+, #4
+	copy_abort_end
+	.popsection
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_page.S linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_page.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_page.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_page.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,39 @@
+/*
+ * linux/arch/unicore32/lib/copy_page.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *  ASM optimised string functions
+ */
+#include <linux/linkage.h>
+#include <asm/assembler.h>
+#include <generated/asm-offsets.h>
+#include <asm/cache.h>
+
+#define COPY_COUNT (PAGE_SZ/256)
+
+		.text
+		.align	5
+/*
+ * UniCore optimised copy_page routine
+ */
+ENTRY(copy_page)
+		stm.w	(r17 - r19, lr), [sp-]
+		mov	r17, r0
+		mov	r18, r1
+		mov	r19, #COPY_COUNT
+1:
+	.rept	4
+		ldm.w	(r0 - r15), [r18]+
+		stm.w	(r0 - r15), [r17]+
+	.endr
+		sub.a	r19, r19, #1
+		bne	1b
+		ldm.w	(r17 - r19, pc), [sp]+
+ENDPROC(copy_page)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_template.S linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_template.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_template.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_template.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,214 @@
+/*
+ * linux/arch/unicore32/lib/copy_template.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+
+/*
+ * Theory of operation
+ * -------------------
+ *
+ * This file provides the core code for a forward memory copy used in
+ * the implementation of memcopy(), copy_to_user() and copy_from_user().
+ *
+ * The including file must define the following accessor macros
+ * according to the need of the given function:
+ *
+ * ldr1w ptr reg abort
+ *
+ *	This loads one word from 'ptr', stores it in 'reg' and increments
+ *	'ptr' to the next word. The 'abort' argument is used for fixup tables.
+ *
+ * ldr4w ptr reg1 reg2 reg3 reg4 abort
+ * ldr8w ptr, reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ *
+ *	This loads four or eight words starting from 'ptr', stores them
+ *	in provided registers and increments 'ptr' past those words.
+ *	The'abort' argument is used for fixup tables.
+ *
+ * ldr1b ptr reg cond abort
+ *
+ *	Similar to ldr1w, but it loads a byte and increments 'ptr' one byte.
+ *	It also must apply the condition code if provided, otherwise the
+ *	"al" condition is assumed by default.
+ *
+ * str1w ptr reg abort
+ * str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+ * str1b ptr reg cond abort
+ *
+ *	Same as their ldr* counterparts, but data is stored to 'ptr' location
+ *	rather than being loaded.
+ *
+ * enter
+ *
+ *	Preserve the provided registers on the stack plus any additional
+ *	data as needed by the implementation including this code. Called
+ *	upon code entry.
+ *
+ * exit
+ *
+ *	Restore registers with the values previously saved with the
+ *	'preserv' macro. Called upon code termination.
+ */
+
+
+		enter
+
+		sub.a	r2, r2, #4
+		bsl	8f
+		and.a	ip, r0, #3
+		bne	9f
+		and.a	ip, r1, #3
+		bne	10f
+
+1:		sub.a	r2, r2, #(28)
+		stm.w	(r5 - r8), [sp-]
+		bsl	5f
+
+3:
+4:		ldr8w	r1, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
+		sub.a	r2, r2, #32
+		str8w	r0, r3, r4, r5, r6, r7, r8, r10, r11, abort=20f
+		beg	3b
+
+5:		and.a	ip, r2, #28
+		rsub	ip, ip, #32
+		beq	7f
+		add	pc, pc, ip		@ C is always clear here
+		nop
+
+		ldr1w	r1, r3, abort=20f
+		ldr1w	r1, r4, abort=20f
+		ldr1w	r1, r5, abort=20f
+		ldr1w	r1, r6, abort=20f
+		ldr1w	r1, r7, abort=20f
+		ldr1w	r1, r8, abort=20f
+		ldr1w	r1, r11, abort=20f
+
+		add	pc, pc, ip
+		nop
+
+		str1w	r0, r3, abort=20f
+		str1w	r0, r4, abort=20f
+		str1w	r0, r5, abort=20f
+		str1w	r0, r6, abort=20f
+		str1w	r0, r7, abort=20f
+		str1w	r0, r8, abort=20f
+		str1w	r0, r11, abort=20f
+
+7:		ldm.w	(r5 - r8), [sp]+
+
+8:		mov.a	r2, r2 << #31
+		ldr1b	r1, r3, ne, abort=21f
+		ldr1b	r1, r4, ea, abort=21f
+		ldr1b	r1, r10, ea, abort=21f
+		str1b	r0, r3, ne, abort=21f
+		str1b	r0, r4, ea, abort=21f
+		str1b	r0, r10, ea, abort=21f
+
+		exit
+
+9:		rsub	ip, ip, #4
+		csub.a	ip, #2
+		ldr1b	r1, r3, sg, abort=21f
+		ldr1b	r1, r4, eg, abort=21f
+		ldr1b	r1, r11, abort=21f
+		str1b	r0, r3, sg, abort=21f
+		str1b	r0, r4, eg, abort=21f
+		sub.a	r2, r2, ip
+		str1b	r0, r11, abort=21f
+		bsl	8b
+		and.a	ip, r1, #3
+		beq	1b
+
+10:		andn	r1, r1, #3
+		csub.a	ip, #2
+		ldr1w	r1, r11, abort=21f
+		beq	17f
+		bsg	18f
+
+
+		.macro	forward_copy_shift a b
+
+		sub.a	r2, r2, #28
+		bsl	14f
+
+11:		stm.w	(r5 - r9), [sp-]
+
+12:
+		ldr4w	r1, r4, r5, r6, r7, abort=19f
+		mov	r3, r11 pull #\a
+		sub.a	r2, r2, #32
+		ldr4w	r1, r8, r9, r10, r11, abort=19f
+		or	r3, r3, r4 push #\b
+		mov	r4, r4 pull #\a
+		or	r4, r4, r5 push #\b
+		mov	r5, r5 pull #\a
+		or	r5, r5, r6 push #\b
+		mov	r6, r6 pull #\a
+		or	r6, r6, r7 push #\b
+		mov	r7, r7 pull #\a
+		or	r7, r7, r8 push #\b
+		mov	r8, r8 pull #\a
+		or	r8, r8, r9 push #\b
+		mov	r9, r9 pull #\a
+		or	r9, r9, r10 push #\b
+		mov	r10, r10 pull #\a
+		or	r10, r10, r11 push #\b
+		str8w	r0, r3, r4, r5, r6, r7, r8, r9, r10, , abort=19f
+		beg	12b
+
+		ldm.w	(r5 - r9), [sp]+
+
+14:		and.a	ip, r2, #28
+		beq	16f
+
+15:		mov	r3, r11 pull #\a
+		ldr1w	r1, r11, abort=21f
+		sub.a	ip, ip, #4
+		or	r3, r3, r11 push #\b
+		str1w	r0, r3, abort=21f
+		bsg	15b
+
+16:		sub	r1, r1, #(\b / 8)
+		b	8b
+
+		.endm
+
+
+		forward_copy_shift	a=8	b=24
+
+17:		forward_copy_shift	a=16	b=16
+
+18:		forward_copy_shift	a=24	b=8
+
+
+/*
+ * Abort preamble and completion macros.
+ * If a fixup handler is required then those macros must surround it.
+ * It is assumed that the fixup code will handle the private part of
+ * the exit macro.
+ */
+
+	.macro	copy_abort_preamble
+19:	ldm.w	(r5 - r9), [sp]+
+	b	21f
+299:	.word	0			@ store lr
+					@ to avoid function call in fixup
+20:	ldm.w	(r5 - r8), [sp]+
+21:
+	adr	r1, 299b
+	stw	lr, [r1]
+	.endm
+
+	.macro	copy_abort_end
+	adr	lr, 299b
+	ldw	pc, [lr]
+	.endm
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_to_user.S linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_to_user.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/copy_to_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/copy_to_user.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,96 @@
+/*
+ * linux/arch/unicore32/lib/copy_to_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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>
+
+/*
+ * Prototype:
+ *
+ *	size_t __copy_to_user(void *to, const void *from, size_t n)
+ *
+ * Purpose:
+ *
+ *	copy a block to user memory from kernel memory
+ *
+ * Params:
+ *
+ *	to = user memory
+ *	from = kernel memory
+ *	n = number of bytes to copy
+ *
+ * Return value:
+ *
+ *	Number of bytes NOT copied.
+ */
+
+	.macro ldr1w ptr reg abort
+	ldw.w \reg, [\ptr]+, #4
+	.endm
+
+	.macro ldr4w ptr reg1 reg2 reg3 reg4 abort
+	ldm.w	(\reg1, \reg2, \reg3, \reg4), [\ptr]+
+	.endm
+
+	.macro ldr8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+	ldm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+	.endm
+
+	.macro ldr1b ptr reg cond=al abort
+	notcond	\cond, .+8
+	ldb.w \reg, [\ptr]+, #1
+	.endm
+
+	.macro str1w ptr reg abort
+	strusr	\reg, \ptr, 4, abort=\abort
+	.endm
+
+	.macro str8w ptr reg1 reg2 reg3 reg4 reg5 reg6 reg7 reg8 abort
+100:	stm.w (\reg1, \reg2, \reg3, \reg4, \reg5, \reg6, \reg7, \reg8), [\ptr]+
+
+	.pushsection __ex_table, "a"
+	.long 100b, \abort
+	.popsection
+	.endm
+
+	.macro str1b ptr reg cond=al abort
+	strusr	\reg, \ptr, 1, \cond, abort=\abort
+	.endm
+
+	.macro enter
+	mov	r3, #0
+	stm.w	(r0, r2, r3), [sp-]
+	.endm
+
+	.macro exit
+	add	sp, sp, #8
+	ldm.w	(r0), [sp]+
+	mov	pc, lr
+	.endm
+
+	.text
+
+WEAK(__copy_to_user)
+
+#include "copy_template.S"
+
+ENDPROC(__copy_to_user)
+
+	.pushsection .fixup,"ax"
+	.align 0
+	copy_abort_preamble
+	ldm.w	(r1, r2, r3), [sp]+
+	sub	r0, r0, r1
+	rsub	r0, r0, r2
+	copy_abort_end
+	.popsection
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/delay.S linux-libre-2.6.39-gnu/arch/unicore32/lib/delay.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/delay.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/delay.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,51 @@
+/*
+ * linux/arch/unicore32/lib/delay.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <asm/param.h>
+		.text
+
+.LC0:		.word	loops_per_jiffy
+.LC1:		.word	(2199023*HZ)>>11
+
+/*
+ * r0  <= 2000
+ * lpj <= 0x01ffffff (max. 3355 bogomips)
+ * HZ  <= 1000
+ */
+
+ENTRY(__udelay)
+		ldw	r2, .LC1
+		mul	r0, r2, r0
+ENTRY(__const_udelay)				@ 0 <= r0 <= 0x7fffff06
+		ldw	r2, .LC0
+		ldw	r2, [r2]		@ max = 0x01ffffff
+		mov	r0, r0 >> #14		@ max = 0x0001ffff
+		mov	r2, r2 >> #10		@ max = 0x00007fff
+		mul	r0, r2, r0		@ max = 2^32-1
+		mov.a	r0, r0 >> #6
+		cmoveq	pc, lr
+
+/*
+ * loops = r0 * HZ * loops_per_jiffy / 1000000
+ *
+ * Oh, if only we had a cycle counter...
+ */
+
+@ Delay routine
+ENTRY(__delay)
+		sub.a	r0, r0, #2
+		bua	__delay
+		mov	pc, lr
+ENDPROC(__udelay)
+ENDPROC(__const_udelay)
+ENDPROC(__delay)
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/findbit.S linux-libre-2.6.39-gnu/arch/unicore32/lib/findbit.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/findbit.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/findbit.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/unicore32/lib/findbit.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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>
+                .text
+
+/*
+ * Purpose  : Find a 'zero' bit
+ * Prototype: int find_first_zero_bit(void *addr, unsigned int maxbit);
+ */
+__uc32_find_first_zero_bit:
+		cxor.a	r1, #0
+		beq	3f
+		mov	r2, #0
+1:		ldb	r3, [r0+], r2 >> #3
+		xor.a	r3, r3, #0xff		@ invert bits
+		bne	.L_found		@ any now set - found zero bit
+		add	r2, r2, #8		@ next bit pointer
+2:		csub.a	r2, r1			@ any more?
+		bub	1b
+3:		mov	r0, r1			@ no free bits
+		mov	pc, lr
+
+/*
+ * Purpose  : Find next 'zero' bit
+ * Prototype: int find_next_zero_bit
+ *		(void *addr, unsigned int maxbit, int offset)
+ */
+ENTRY(__uc32_find_next_zero_bit)
+		cxor.a	r1, #0
+		beq	3b
+		and.a	ip, r2, #7
+		beq	1b			@ If new byte, goto old routine
+		ldb	r3, [r0+], r2 >> #3
+		xor	r3, r3, #0xff		@ now looking for a 1 bit
+		mov.a	r3, r3 >> ip		@ shift off unused bits
+		bne	.L_found
+		or	r2, r2, #7		@ if zero, then no bits here
+		add	r2, r2, #1		@ align bit pointer
+		b	2b			@ loop for next bit
+ENDPROC(__uc32_find_next_zero_bit)
+
+/*
+ * Purpose  : Find a 'one' bit
+ * Prototype: int find_first_bit
+ *		(const unsigned long *addr, unsigned int maxbit);
+ */
+__uc32_find_first_bit:
+		cxor.a	r1, #0
+		beq	3f
+		mov	r2, #0
+1:		ldb	r3, [r0+], r2 >> #3
+		mov.a	r3, r3
+		bne	.L_found		@ any now set - found zero bit
+		add	r2, r2, #8		@ next bit pointer
+2:		csub.a	r2, r1			@ any more?
+		bub	1b
+3:		mov	r0, r1			@ no free bits
+		mov	pc, lr
+
+/*
+ * Purpose  : Find next 'one' bit
+ * Prototype: int find_next_zero_bit
+ *		(void *addr, unsigned int maxbit, int offset)
+ */
+ENTRY(__uc32_find_next_bit)
+		cxor.a	r1, #0
+		beq	3b
+		and.a	ip, r2, #7
+		beq	1b			@ If new byte, goto old routine
+		ldb	r3, [r0+], r2 >> #3
+		mov.a	r3, r3 >> ip		@ shift off unused bits
+		bne	.L_found
+		or	r2, r2, #7		@ if zero, then no bits here
+		add	r2, r2, #1		@ align bit pointer
+		b	2b			@ loop for next bit
+ENDPROC(__uc32_find_next_bit)
+
+/*
+ * One or more bits in the LSB of r3 are assumed to be set.
+ */
+.L_found:
+		rsub	r1, r3, #0
+		and	r3, r3, r1
+		cntlz	r3, r3
+		rsub	r3, r3, #31
+		add	r0, r2, r3
+		mov	pc, lr
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/Makefile linux-libre-2.6.39-gnu/arch/unicore32/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,27 @@
+#
+# linux/arch/unicore32/lib/Makefile
+#
+# Copyright (C) 2001-2010 GUAN Xue-tao
+#
+
+lib-y	:= backtrace.o delay.o findbit.o
+lib-y	+= strncpy_from_user.o strnlen_user.o
+lib-y	+= clear_user.o copy_page.o
+lib-y	+= copy_from_user.o copy_to_user.o
+
+GNU_LIBC_A		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libc.a)
+GNU_LIBC_A_OBJS		:= memchr.o memcpy.o memmove.o memset.o
+GNU_LIBC_A_OBJS		+= strchr.o strrchr.o
+GNU_LIBC_A_OBJS		+= rawmemchr.o			# needed by strrchr.o
+
+GNU_LIBGCC_A		:= $(shell $(CC) $(KBUILD_CFLAGS) -print-file-name=libgcc.a)
+GNU_LIBGCC_A_OBJS	:= _ashldi3.o _ashrdi3.o _lshrdi3.o
+GNU_LIBGCC_A_OBJS	+= _divsi3.o _modsi3.o _ucmpdi2.o _umodsi3.o _udivsi3.o
+
+lib-y	+= $(GNU_LIBC_A_OBJS) $(GNU_LIBGCC_A_OBJS)
+
+$(addprefix $(obj)/, $(GNU_LIBC_A_OBJS)):
+	$(Q)$(AR) p $(GNU_LIBC_A) $(notdir $@) > $@
+
+$(addprefix $(obj)/, $(GNU_LIBGCC_A_OBJS)):
+	$(Q)$(AR) p $(GNU_LIBGCC_A) $(notdir $@) > $@
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/strncpy_from_user.S linux-libre-2.6.39-gnu/arch/unicore32/lib/strncpy_from_user.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/strncpy_from_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/strncpy_from_user.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,45 @@
+/*
+ * linux/arch/unicore32/lib/strncpy_from_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <asm/errno.h>
+
+	.text
+	.align	5
+
+/*
+ * Copy a string from user space to kernel space.
+ *  r0 = dst, r1 = src, r2 = byte length
+ * returns the number of characters copied (strlen of copied string),
+ *  -EFAULT on exception, or "len" if we fill the whole buffer
+ */
+ENTRY(__strncpy_from_user)
+	mov	ip, r1
+1:	sub.a	r2, r2, #1
+	ldrusr	r3, r1, 1, ns
+	bfs	2f
+	stb.w	r3, [r0]+, #1
+	cxor.a	r3, #0
+	bne	1b
+	sub	r1, r1, #1	@ take NUL character out of count
+2:	sub	r0, r1, ip
+	mov	pc, lr
+ENDPROC(__strncpy_from_user)
+
+	.pushsection .fixup,"ax"
+	.align	0
+9001:	mov	r3, #0
+	stb	r3, [r0+], #0	@ null terminate
+	mov	r0, #-EFAULT
+	mov	pc, lr
+	.popsection
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/lib/strnlen_user.S linux-libre-2.6.39-gnu/arch/unicore32/lib/strnlen_user.S
--- linux-libre-2.6.38-gnu/arch/unicore32/lib/strnlen_user.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/lib/strnlen_user.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * linux/arch/unicore32/lib/strnlen_user.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 <asm/errno.h>
+
+	.text
+	.align	5
+
+/* Prototype: unsigned long __strnlen_user(const char *str, long n)
+ * Purpose  : get length of a string in user memory
+ * Params   : str - address of string in user memory
+ * Returns  : length of string *including terminator*
+ *	      or zero on exception, or n + 1 if too long
+ */
+ENTRY(__strnlen_user)
+	mov	r2, r0
+1:
+	ldrusr	r3, r0, 1
+	cxor.a	r3, #0
+	beq	2f
+	sub.a	r1, r1, #1
+	bne	1b
+	add	r0, r0, #1
+2:	sub	r0, r0, r2
+	mov	pc, lr
+ENDPROC(__strnlen_user)
+
+	.pushsection .fixup,"ax"
+	.align	0
+9001:	mov	r0, #0
+	mov	pc, lr
+	.popsection
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/Makefile linux-libre-2.6.39-gnu/arch/unicore32/Makefile
--- linux-libre-2.6.38-gnu/arch/unicore32/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,95 @@
+#
+# arch/unicore32/Makefile
+#
+# This file is included by the global makefile so that you can add your own
+# architecture-specific flags and dependencies.
+#
+# 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~2010 by Guan Xue-tao
+#
+ifneq ($(SUBARCH),$(ARCH))
+	ifeq ($(CROSS_COMPILE),)
+		CROSS_COMPILE := $(call cc-cross-prefix, unicore32-linux-)
+	endif
+endif
+
+LDFLAGS_vmlinux		:= -p --no-undefined -X
+
+OBJCOPYFLAGS		:= -O binary -R .note -R .note.gnu.build-id -R .comment -S
+
+# Never generate .eh_frame
+KBUILD_CFLAGS		+= $(call cc-option,-fno-dwarf2-cfi-asm)
+
+# Never use hard float in kernel
+KBUILD_CFLAGS		+= -msoft-float
+
+ifeq ($(CONFIG_FRAME_POINTER),y)
+KBUILD_CFLAGS		+= -mno-sched-prolog
+endif
+
+CHECKFLAGS		+= -D__unicore32__
+
+head-y			:= arch/unicore32/kernel/head.o
+head-y			+= arch/unicore32/kernel/init_task.o
+
+core-y			+= arch/unicore32/kernel/
+core-y			+= arch/unicore32/mm/
+
+libs-y			+= arch/unicore32/lib/
+
+ASM_GENERATED_DIR	:= $(srctree)/arch/unicore32/include/generated
+LINUXINCLUDE		+= -I$(ASM_GENERATED_DIR)
+
+ASM_GENERIC_HEADERS	:= atomic.h auxvec.h
+ASM_GENERIC_HEADERS	+= bitsperlong.h bug.h bugs.h
+ASM_GENERIC_HEADERS	+= cputime.h current.h
+ASM_GENERIC_HEADERS	+= device.h div64.h
+ASM_GENERIC_HEADERS	+= emergency-restart.h errno.h
+ASM_GENERIC_HEADERS	+= fb.h fcntl.h ftrace.h futex.h
+ASM_GENERIC_HEADERS	+= hardirq.h hw_irq.h
+ASM_GENERIC_HEADERS	+= ioctl.h ioctls.h ipcbuf.h irq_regs.h
+ASM_GENERIC_HEADERS	+= kdebug.h kmap_types.h
+ASM_GENERIC_HEADERS	+= local.h
+ASM_GENERIC_HEADERS	+= mman.h module.h msgbuf.h
+ASM_GENERIC_HEADERS	+= param.h parport.h percpu.h poll.h posix_types.h
+ASM_GENERIC_HEADERS	+= resource.h
+ASM_GENERIC_HEADERS	+= scatterlist.h sections.h segment.h sembuf.h serial.h
+ASM_GENERIC_HEADERS	+= setup.h shmbuf.h shmparam.h
+ASM_GENERIC_HEADERS	+= siginfo.h signal.h sizes.h
+ASM_GENERIC_HEADERS	+= socket.h sockios.h stat.h statfs.h swab.h syscalls.h
+ASM_GENERIC_HEADERS	+= termbits.h termios.h topology.h types.h
+ASM_GENERIC_HEADERS	+= ucontext.h unaligned.h user.h
+ASM_GENERIC_HEADERS	+= vga.h
+ASM_GENERIC_HEADERS	+= xor.h
+
+archprepare:
+ifneq ($(ASM_GENERATED_DIR), $(wildcard $(ASM_GENERATED_DIR)))
+	$(Q)mkdir -p $(ASM_GENERATED_DIR)/asm
+	$(Q)$(foreach a, $(ASM_GENERIC_HEADERS),	\
+		echo '#include <asm-generic/$a>'	\
+			> $(ASM_GENERATED_DIR)/asm/$a; )
+endif
+
+boot			:= arch/unicore32/boot
+
+# Default target when executing plain make
+KBUILD_IMAGE		:= zImage
+
+all:	$(KBUILD_IMAGE)
+
+zImage Image uImage: vmlinux
+	$(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
+
+MRPROPER_DIRS		+= $(ASM_GENERATED_DIR)
+
+archclean:
+	$(Q)$(MAKE) $(clean)=$(boot)
+
+define archhelp
+  echo  '* zImage        - Compressed kernel image (arch/$(ARCH)/boot/zImage)'
+  echo  '  Image         - Uncompressed kernel image (arch/$(ARCH)/boot/Image)'
+  echo  '  uImage        - U-Boot wrapped zImage'
+endef
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/alignment.c linux-libre-2.6.39-gnu/arch/unicore32/mm/alignment.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/alignment.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/alignment.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,523 @@
+/*
+ * linux/arch/unicore32/mm/alignment.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+/*
+ * TODO:
+ *  FPU ldm/stm not handling
+ */
+#include <linux/compiler.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+#include <linux/uaccess.h>
+
+#include <asm/tlbflush.h>
+#include <asm/unaligned.h>
+
+#define CODING_BITS(i)	(i & 0xe0000120)
+
+#define LDST_P_BIT(i)	(i & (1 << 28))	/* Preindex             */
+#define LDST_U_BIT(i)	(i & (1 << 27))	/* Add offset           */
+#define LDST_W_BIT(i)	(i & (1 << 25))	/* Writeback            */
+#define LDST_L_BIT(i)	(i & (1 << 24))	/* Load                 */
+
+#define LDST_P_EQ_U(i)	((((i) ^ ((i) >> 1)) & (1 << 27)) == 0)
+
+#define LDSTH_I_BIT(i)	(i & (1 << 26))	/* half-word immed      */
+#define LDM_S_BIT(i)	(i & (1 << 26))	/* write ASR from BSR */
+#define LDM_H_BIT(i)	(i & (1 << 6))	/* select r0-r15 or r16-r31 */
+
+#define RN_BITS(i)	((i >> 19) & 31)	/* Rn                   */
+#define RD_BITS(i)	((i >> 14) & 31)	/* Rd                   */
+#define RM_BITS(i)	(i & 31)	/* Rm                   */
+
+#define REGMASK_BITS(i)	(((i & 0x7fe00) >> 3) | (i & 0x3f))
+#define OFFSET_BITS(i)	(i & 0x03fff)
+
+#define SHIFT_BITS(i)	((i >> 9) & 0x1f)
+#define SHIFT_TYPE(i)	(i & 0xc0)
+#define SHIFT_LSL	0x00
+#define SHIFT_LSR	0x40
+#define SHIFT_ASR	0x80
+#define SHIFT_RORRRX	0xc0
+
+union offset_union {
+	unsigned long un;
+	signed long sn;
+};
+
+#define TYPE_ERROR	0
+#define TYPE_FAULT	1
+#define TYPE_LDST	2
+#define TYPE_DONE	3
+#define TYPE_SWAP  4
+#define TYPE_COLS  5		/* Coprocessor load/store */
+
+#define get8_unaligned_check(val, addr, err)		\
+	__asm__(					\
+	"1:	ldb.u	%1, [%2], #1\n"			\
+	"2:\n"						\
+	"	.pushsection .fixup,\"ax\"\n"		\
+	"	.align	2\n"				\
+	"3:	mov	%0, #1\n"			\
+	"	b	2b\n"				\
+	"	.popsection\n"				\
+	"	.pushsection __ex_table,\"a\"\n"		\
+	"	.align	3\n"				\
+	"	.long	1b, 3b\n"			\
+	"	.popsection\n"				\
+	: "=r" (err), "=&r" (val), "=r" (addr)		\
+	: "0" (err), "2" (addr))
+
+#define get8t_unaligned_check(val, addr, err)		\
+	__asm__(					\
+	"1:	ldb.u	%1, [%2], #1\n"			\
+	"2:\n"						\
+	"	.pushsection .fixup,\"ax\"\n"		\
+	"	.align	2\n"				\
+	"3:	mov	%0, #1\n"			\
+	"	b	2b\n"				\
+	"	.popsection\n"				\
+	"	.pushsection __ex_table,\"a\"\n"		\
+	"	.align	3\n"				\
+	"	.long	1b, 3b\n"			\
+	"	.popsection\n"				\
+	: "=r" (err), "=&r" (val), "=r" (addr)		\
+	: "0" (err), "2" (addr))
+
+#define get16_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8_unaligned_check(val, a, err);		\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 8;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put16_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v = val, a = addr;	\
+		__asm__(					\
+		"1:	stb.u	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"2:	stb.u	%1, [%2]\n"			\
+		"3:\n"						\
+		"	.pushsection .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"4:	mov	%0, #1\n"			\
+		"	b	3b\n"				\
+		"	.popsection\n"				\
+		"	.pushsection __ex_table,\"a\"\n"		\
+		"	.align	3\n"				\
+		"	.long	1b, 4b\n"			\
+		"	.long	2b, 4b\n"			\
+		"	.popsection\n"				\
+		: "=r" (err), "=&r" (v), "=&r" (a)		\
+		: "0" (err), "1" (v), "2" (a));			\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define __put32_unaligned_check(ins, val, addr)			\
+	do {							\
+		unsigned int err = 0, v = val, a = addr;	\
+		__asm__(					\
+		"1:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"2:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"3:	"ins"	%1, [%2], #1\n"			\
+		"	mov	%1, %1 >> #8\n"			\
+		"4:	"ins"	%1, [%2]\n"			\
+		"5:\n"						\
+		"	.pushsection .fixup,\"ax\"\n"		\
+		"	.align	2\n"				\
+		"6:	mov	%0, #1\n"			\
+		"	b	5b\n"				\
+		"	.popsection\n"				\
+		"	.pushsection __ex_table,\"a\"\n"		\
+		"	.align	3\n"				\
+		"	.long	1b, 6b\n"			\
+		"	.long	2b, 6b\n"			\
+		"	.long	3b, 6b\n"			\
+		"	.long	4b, 6b\n"			\
+		"	.popsection\n"				\
+		: "=r" (err), "=&r" (v), "=&r" (a)		\
+		: "0" (err), "1" (v), "2" (a));			\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define get32_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8_unaligned_check(val, a, err);		\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 8;					\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 16;					\
+		get8_unaligned_check(v, a, err);		\
+		val |= v << 24;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put32_unaligned_check(val, addr)			\
+	__put32_unaligned_check("stb.u", val, addr)
+
+#define get32t_unaligned_check(val, addr)			\
+	do {							\
+		unsigned int err = 0, v, a = addr;		\
+		get8t_unaligned_check(val, a, err);		\
+		get8t_unaligned_check(v, a, err);		\
+		val |= v << 8;					\
+		get8t_unaligned_check(v, a, err);		\
+		val |= v << 16;					\
+		get8t_unaligned_check(v, a, err);		\
+		val |= v << 24;					\
+		if (err)					\
+			goto fault;				\
+	} while (0)
+
+#define put32t_unaligned_check(val, addr)			\
+	__put32_unaligned_check("stb.u", val, addr)
+
+static void
+do_alignment_finish_ldst(unsigned long addr, unsigned long instr,
+			 struct pt_regs *regs, union offset_union offset)
+{
+	if (!LDST_U_BIT(instr))
+		offset.un = -offset.un;
+
+	if (!LDST_P_BIT(instr))
+		addr += offset.un;
+
+	if (!LDST_P_BIT(instr) || LDST_W_BIT(instr))
+		regs->uregs[RN_BITS(instr)] = addr;
+}
+
+static int
+do_alignment_ldrhstrh(unsigned long addr, unsigned long instr,
+		      struct pt_regs *regs)
+{
+	unsigned int rd = RD_BITS(instr);
+
+	/* old value 0x40002120, can't judge swap instr correctly */
+	if ((instr & 0x4b003fe0) == 0x40000120)
+		goto swp;
+
+	if (LDST_L_BIT(instr)) {
+		unsigned long val;
+		get16_unaligned_check(val, addr);
+
+		/* signed half-word? */
+		if (instr & 0x80)
+			val = (signed long)((signed short)val);
+
+		regs->uregs[rd] = val;
+	} else
+		put16_unaligned_check(regs->uregs[rd], addr);
+
+	return TYPE_LDST;
+
+swp:
+	/* only handle swap word
+	 * for swap byte should not active this alignment exception */
+	get32_unaligned_check(regs->uregs[RD_BITS(instr)], addr);
+	put32_unaligned_check(regs->uregs[RM_BITS(instr)], addr);
+	return TYPE_SWAP;
+
+fault:
+	return TYPE_FAULT;
+}
+
+static int
+do_alignment_ldrstr(unsigned long addr, unsigned long instr,
+		    struct pt_regs *regs)
+{
+	unsigned int rd = RD_BITS(instr);
+
+	if (!LDST_P_BIT(instr) && LDST_W_BIT(instr))
+		goto trans;
+
+	if (LDST_L_BIT(instr))
+		get32_unaligned_check(regs->uregs[rd], addr);
+	else
+		put32_unaligned_check(regs->uregs[rd], addr);
+	return TYPE_LDST;
+
+trans:
+	if (LDST_L_BIT(instr))
+		get32t_unaligned_check(regs->uregs[rd], addr);
+	else
+		put32t_unaligned_check(regs->uregs[rd], addr);
+	return TYPE_LDST;
+
+fault:
+	return TYPE_FAULT;
+}
+
+/*
+ * LDM/STM alignment handler.
+ *
+ * There are 4 variants of this instruction:
+ *
+ * B = rn pointer before instruction, A = rn pointer after instruction
+ *              ------ increasing address ----->
+ *	        |    | r0 | r1 | ... | rx |    |
+ * PU = 01             B                    A
+ * PU = 11        B                    A
+ * PU = 00        A                    B
+ * PU = 10             A                    B
+ */
+static int
+do_alignment_ldmstm(unsigned long addr, unsigned long instr,
+		    struct pt_regs *regs)
+{
+	unsigned int rd, rn, pc_correction, reg_correction, nr_regs, regbits;
+	unsigned long eaddr, newaddr;
+
+	if (LDM_S_BIT(instr))
+		goto bad;
+
+	pc_correction = 4;	/* processor implementation defined */
+
+	/* count the number of registers in the mask to be transferred */
+	nr_regs = hweight16(REGMASK_BITS(instr)) * 4;
+
+	rn = RN_BITS(instr);
+	newaddr = eaddr = regs->uregs[rn];
+
+	if (!LDST_U_BIT(instr))
+		nr_regs = -nr_regs;
+	newaddr += nr_regs;
+	if (!LDST_U_BIT(instr))
+		eaddr = newaddr;
+
+	if (LDST_P_EQ_U(instr))	/* U = P */
+		eaddr += 4;
+
+	/*
+	 * This is a "hint" - we already have eaddr worked out by the
+	 * processor for us.
+	 */
+	if (addr != eaddr) {
+		printk(KERN_ERR "LDMSTM: PC = %08lx, instr = %08lx, "
+		       "addr = %08lx, eaddr = %08lx\n",
+		       instruction_pointer(regs), instr, addr, eaddr);
+		show_regs(regs);
+	}
+
+	if (LDM_H_BIT(instr))
+		reg_correction = 0x10;
+	else
+		reg_correction = 0x00;
+
+	for (regbits = REGMASK_BITS(instr), rd = 0; regbits;
+	     regbits >>= 1, rd += 1)
+		if (regbits & 1) {
+			if (LDST_L_BIT(instr))
+				get32_unaligned_check(regs->
+					uregs[rd + reg_correction], eaddr);
+			else
+				put32_unaligned_check(regs->
+					uregs[rd + reg_correction], eaddr);
+			eaddr += 4;
+		}
+
+	if (LDST_W_BIT(instr))
+		regs->uregs[rn] = newaddr;
+	return TYPE_DONE;
+
+fault:
+	regs->UCreg_pc -= pc_correction;
+	return TYPE_FAULT;
+
+bad:
+	printk(KERN_ERR "Alignment trap: not handling ldm with s-bit set\n");
+	return TYPE_ERROR;
+}
+
+static int
+do_alignment(unsigned long addr, unsigned int error_code, struct pt_regs *regs)
+{
+	union offset_union offset;
+	unsigned long instr, instrptr;
+	int (*handler) (unsigned long addr, unsigned long instr,
+			struct pt_regs *regs);
+	unsigned int type;
+
+	instrptr = instruction_pointer(regs);
+	if (instrptr >= PAGE_OFFSET)
+		instr = *(unsigned long *)instrptr;
+	else {
+		__asm__ __volatile__(
+				"ldw.u	%0, [%1]\n"
+				: "=&r"(instr)
+				: "r"(instrptr));
+	}
+
+	regs->UCreg_pc += 4;
+
+	switch (CODING_BITS(instr)) {
+	case 0x40000120:	/* ldrh or strh */
+		if (LDSTH_I_BIT(instr))
+			offset.un = (instr & 0x3e00) >> 4 | (instr & 31);
+		else
+			offset.un = regs->uregs[RM_BITS(instr)];
+		handler = do_alignment_ldrhstrh;
+		break;
+
+	case 0x60000000:	/* ldr or str immediate */
+	case 0x60000100:	/* ldr or str immediate */
+	case 0x60000020:	/* ldr or str immediate */
+	case 0x60000120:	/* ldr or str immediate */
+		offset.un = OFFSET_BITS(instr);
+		handler = do_alignment_ldrstr;
+		break;
+
+	case 0x40000000:	/* ldr or str register */
+		offset.un = regs->uregs[RM_BITS(instr)];
+		{
+			unsigned int shiftval = SHIFT_BITS(instr);
+
+			switch (SHIFT_TYPE(instr)) {
+			case SHIFT_LSL:
+				offset.un <<= shiftval;
+				break;
+
+			case SHIFT_LSR:
+				offset.un >>= shiftval;
+				break;
+
+			case SHIFT_ASR:
+				offset.sn >>= shiftval;
+				break;
+
+			case SHIFT_RORRRX:
+				if (shiftval == 0) {
+					offset.un >>= 1;
+					if (regs->UCreg_asr & PSR_C_BIT)
+						offset.un |= 1 << 31;
+				} else
+					offset.un = offset.un >> shiftval |
+					    offset.un << (32 - shiftval);
+				break;
+			}
+		}
+		handler = do_alignment_ldrstr;
+		break;
+
+	case 0x80000000:	/* ldm or stm */
+	case 0x80000020:	/* ldm or stm */
+		handler = do_alignment_ldmstm;
+		break;
+
+	default:
+		goto bad;
+	}
+
+	type = handler(addr, instr, regs);
+
+	if (type == TYPE_ERROR || type == TYPE_FAULT)
+		goto bad_or_fault;
+
+	if (type == TYPE_LDST)
+		do_alignment_finish_ldst(addr, instr, regs, offset);
+
+	return 0;
+
+bad_or_fault:
+	if (type == TYPE_ERROR)
+		goto bad;
+	regs->UCreg_pc -= 4;
+	/*
+	 * We got a fault - fix it up, or die.
+	 */
+	do_bad_area(addr, error_code, regs);
+	return 0;
+
+bad:
+	/*
+	 * Oops, we didn't handle the instruction.
+	 * However, we must handle fpu instr firstly.
+	 */
+#ifdef CONFIG_UNICORE_FPU_F64
+	/* handle co.load/store */
+#define CODING_COLS                0xc0000000
+#define COLS_OFFSET_BITS(i)	(i & 0x1FF)
+#define COLS_L_BITS(i)		(i & (1<<24))
+#define COLS_FN_BITS(i)		((i>>14) & 31)
+	if ((instr & 0xe0000000) == CODING_COLS) {
+		unsigned int fn = COLS_FN_BITS(instr);
+		unsigned long val = 0;
+		if (COLS_L_BITS(instr)) {
+			get32t_unaligned_check(val, addr);
+			switch (fn) {
+#define ASM_MTF(n)	case n:						\
+			__asm__ __volatile__("MTF %0, F" __stringify(n)	\
+				: : "r"(val));				\
+			break;
+			ASM_MTF(0); ASM_MTF(1); ASM_MTF(2); ASM_MTF(3);
+			ASM_MTF(4); ASM_MTF(5); ASM_MTF(6); ASM_MTF(7);
+			ASM_MTF(8); ASM_MTF(9); ASM_MTF(10); ASM_MTF(11);
+			ASM_MTF(12); ASM_MTF(13); ASM_MTF(14); ASM_MTF(15);
+			ASM_MTF(16); ASM_MTF(17); ASM_MTF(18); ASM_MTF(19);
+			ASM_MTF(20); ASM_MTF(21); ASM_MTF(22); ASM_MTF(23);
+			ASM_MTF(24); ASM_MTF(25); ASM_MTF(26); ASM_MTF(27);
+			ASM_MTF(28); ASM_MTF(29); ASM_MTF(30); ASM_MTF(31);
+#undef ASM_MTF
+			}
+		} else {
+			switch (fn) {
+#define ASM_MFF(n)	case n:						\
+			__asm__ __volatile__("MFF %0, F" __stringify(n)	\
+				: : "r"(val));				\
+			break;
+			ASM_MFF(0); ASM_MFF(1); ASM_MFF(2); ASM_MFF(3);
+			ASM_MFF(4); ASM_MFF(5); ASM_MFF(6); ASM_MFF(7);
+			ASM_MFF(8); ASM_MFF(9); ASM_MFF(10); ASM_MFF(11);
+			ASM_MFF(12); ASM_MFF(13); ASM_MFF(14); ASM_MFF(15);
+			ASM_MFF(16); ASM_MFF(17); ASM_MFF(18); ASM_MFF(19);
+			ASM_MFF(20); ASM_MFF(21); ASM_MFF(22); ASM_MFF(23);
+			ASM_MFF(24); ASM_MFF(25); ASM_MFF(26); ASM_MFF(27);
+			ASM_MFF(28); ASM_MFF(29); ASM_MFF(30); ASM_MFF(31);
+#undef ASM_MFF
+			}
+			put32t_unaligned_check(val, addr);
+		}
+		return TYPE_COLS;
+	}
+fault:
+	return TYPE_FAULT;
+#endif
+	printk(KERN_ERR "Alignment trap: not handling instruction "
+	       "%08lx at [<%08lx>]\n", instr, instrptr);
+	return 1;
+}
+
+/*
+ * This needs to be done after sysctl_init, otherwise sys/ will be
+ * overwritten.  Actually, this shouldn't be in sys/ at all since
+ * it isn't a sysctl, and it doesn't contain sysctl information.
+ */
+static int __init alignment_init(void)
+{
+	hook_fault_code(1, do_alignment, SIGBUS, BUS_ADRALN,
+			"alignment exception");
+
+	return 0;
+}
+
+fs_initcall(alignment_init);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/cache-ucv2.S linux-libre-2.6.39-gnu/arch/unicore32/mm/cache-ucv2.S
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/cache-ucv2.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/cache-ucv2.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,212 @@
+/*
+ * linux/arch/unicore32/mm/cache-ucv2.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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 is the "shell" of the UniCore-v2 processor support.
+ */
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/assembler.h>
+#include <asm/page.h>
+
+#include "proc-macros.S"
+
+/*
+ *	__cpuc_flush_icache_all()
+ *	__cpuc_flush_kern_all()
+ *	__cpuc_flush_user_all()
+ *
+ *	Flush the entire cache.
+ */
+ENTRY(__cpuc_flush_icache_all)
+	/*FALLTHROUGH*/
+ENTRY(__cpuc_flush_kern_all)
+	/*FALLTHROUGH*/
+ENTRY(__cpuc_flush_user_all)
+	mov	r0, #0
+	movc	p0.c5, r0, #14			@ Dcache flush all
+	nop8
+
+	mov	r0, #0
+	movc	p0.c5, r0, #20			@ Icache invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_flush_user_range(start, end, flags)
+ *
+ *	Flush a range of TLB entries in the specified address space.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ *	- flags	- vm_area_struct flags describing address space
+ */
+ENTRY(__cpuc_flush_user_range)
+	cxor.a	r2, #0
+	beq	__cpuc_dma_flush_range
+
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
+	sub	r1, r1, r0
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+101:	dcacheline_flush	r0, r11, r12
+
+	add	r0, r0, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	101b
+	b	3f
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #14			@ Dcache flush all
+	nop8
+
+3:	mov	ip, #0
+	movc	p0.c5, ip, #20			@ Icache invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_coherent_kern_range(start,end)
+ *	__cpuc_coherent_user_range(start,end)
+ *
+ *	Ensure that the I and D caches are coherent within specified
+ *	region.  This is typically used when code has been written to
+ *	a memory region, and will be executed.
+ *
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(__cpuc_coherent_kern_range)
+	/* FALLTHROUGH */
+ENTRY(__cpuc_coherent_user_range)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1	@ Safety check
+	sub	r1, r1, r0
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+	@ r0 va2pa r10
+	mov	r9, #PAGE_SZ
+	sub	r9, r9, #1			@ PAGE_MASK
+101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
+	b	103f
+102:	cand.a	r0, r9
+	beq	101b
+
+103:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
+	nop8
+
+	add	r0, r0, #CACHE_LINESIZE
+	add	r10, r10, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	102b
+	b	3f
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #10			@ Dcache clean all
+	nop8
+
+3:	mov	ip, #0
+	movc	p0.c5, ip, #20			@ Icache invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_flush_kern_dcache_area(void *addr, size_t size)
+ *
+ *	- addr	- kernel address
+ *	- size	- region size
+ */
+ENTRY(__cpuc_flush_kern_dcache_area)
+	mov	ip, #0
+	movc	p0.c5, ip, #14			@ Dcache flush all
+	nop8
+	mov	pc, lr
+
+/*
+ *	__cpuc_dma_clean_range(start,end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+ENTRY(__cpuc_dma_clean_range)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1
+	sub	r1, r1, r0
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	@ r0 va2pa r10
+	mov	r9, #PAGE_SZ
+	sub	r9, r9, #1			@ PAGE_MASK
+101:	va2pa	r0, r10, r11, r12, r13, 2f	@ r10 is PA
+	b	1f
+102:	cand.a	r0, r9
+	beq	101b
+
+1:	movc	p0.c5, r10, #11			@ Dcache clean line of R10
+	nop8
+	add	r0, r0, #CACHE_LINESIZE
+	add	r10, r10, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	102b
+	mov	pc, lr
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #10			@ Dcache clean all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	__cpuc_dma_inv_range(start,end)
+ *	__cpuc_dma_flush_range(start,end)
+ *	- start   - virtual start address of region
+ *	- end     - virtual end address of region
+ */
+__cpuc_dma_inv_range:
+	/* FALLTHROUGH */
+ENTRY(__cpuc_dma_flush_range)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	andn	r0, r0, #CACHE_LINESIZE - 1
+	sub	r1, r1, r0
+	andn	r1, r1, #CACHE_LINESIZE - 1
+	add	r1, r1, #CACHE_LINESIZE
+
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	2f
+
+	@ r0 va2pa r10
+101:	dcacheline_flush	r0, r11, r12
+
+	add	r0, r0, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bns	101b
+	mov	pc, lr
+#endif
+2:	mov	ip, #0
+	movc	p0.c5, ip, #14			@ Dcache flush all
+	nop8
+
+	mov	pc, lr
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/dma-swiotlb.c linux-libre-2.6.39-gnu/arch/unicore32/mm/dma-swiotlb.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/dma-swiotlb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/dma-swiotlb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+/*
+ * Contains routines needed to support swiotlb for UniCore32.
+ *
+ * Copyright (C) 2010 Guan Xuetao
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the 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/cache.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/swiotlb.h>
+#include <linux/bootmem.h>
+
+#include <asm/dma.h>
+
+struct dma_map_ops swiotlb_dma_map_ops = {
+	.alloc_coherent = swiotlb_alloc_coherent,
+	.free_coherent = swiotlb_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,
+	.sync_single_for_cpu = swiotlb_sync_single_for_cpu,
+	.sync_single_for_device = swiotlb_sync_single_for_device,
+	.sync_sg_for_cpu = swiotlb_sync_sg_for_cpu,
+	.sync_sg_for_device = swiotlb_sync_sg_for_device,
+	.mapping_error = swiotlb_dma_mapping_error,
+};
+EXPORT_SYMBOL(swiotlb_dma_map_ops);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/extable.c linux-libre-2.6.39-gnu/arch/unicore32/mm/extable.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/extable.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/extable.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,24 @@
+/*
+ * linux/arch/unicore32/mm/extable.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/uaccess.h>
+
+int fixup_exception(struct pt_regs *regs)
+{
+	const struct exception_table_entry *fixup;
+
+	fixup = search_exception_tables(instruction_pointer(regs));
+	if (fixup)
+		regs->UCreg_pc = fixup->fixup;
+
+	return fixup != NULL;
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/fault.c linux-libre-2.6.39-gnu/arch/unicore32/mm/fault.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/fault.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/fault.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,479 @@
+/*
+ * linux/arch/unicore32/mm/fault.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/signal.h>
+#include <linux/mm.h>
+#include <linux/hardirq.h>
+#include <linux/init.h>
+#include <linux/kprobes.h>
+#include <linux/uaccess.h>
+#include <linux/page-flags.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/pgtable.h>
+#include <asm/tlbflush.h>
+
+/*
+ * Fault status register encodings.  We steal bit 31 for our own purposes.
+ */
+#define FSR_LNX_PF		(1 << 31)
+
+static inline int fsr_fs(unsigned int fsr)
+{
+	/* xyabcde will be abcde+xy */
+	return (fsr & 31) + ((fsr & (3 << 5)) >> 5);
+}
+
+/*
+ * This is useful to dump out the page tables associated with
+ * 'addr' in mm 'mm'.
+ */
+void show_pte(struct mm_struct *mm, unsigned long addr)
+{
+	pgd_t *pgd;
+
+	if (!mm)
+		mm = &init_mm;
+
+	printk(KERN_ALERT "pgd = %p\n", mm->pgd);
+	pgd = pgd_offset(mm, addr);
+	printk(KERN_ALERT "[%08lx] *pgd=%08lx", addr, pgd_val(*pgd));
+
+	do {
+		pmd_t *pmd;
+		pte_t *pte;
+
+		if (pgd_none(*pgd))
+			break;
+
+		if (pgd_bad(*pgd)) {
+			printk("(bad)");
+			break;
+		}
+
+		pmd = pmd_offset((pud_t *) pgd, addr);
+		if (PTRS_PER_PMD != 1)
+			printk(", *pmd=%08lx", pmd_val(*pmd));
+
+		if (pmd_none(*pmd))
+			break;
+
+		if (pmd_bad(*pmd)) {
+			printk("(bad)");
+			break;
+		}
+
+		/* We must not map this if we have highmem enabled */
+		if (PageHighMem(pfn_to_page(pmd_val(*pmd) >> PAGE_SHIFT)))
+			break;
+
+		pte = pte_offset_map(pmd, addr);
+		printk(", *pte=%08lx", pte_val(*pte));
+		pte_unmap(pte);
+	} while (0);
+
+	printk("\n");
+}
+
+/*
+ * Oops.  The kernel tried to access some page that wasn't present.
+ */
+static void __do_kernel_fault(struct mm_struct *mm, unsigned long addr,
+		unsigned int fsr, struct pt_regs *regs)
+{
+	/*
+	 * Are we prepared to handle this kernel fault?
+	 */
+	if (fixup_exception(regs))
+		return;
+
+	/*
+	 * No handler, we'll have to terminate things with extreme prejudice.
+	 */
+	bust_spinlocks(1);
+	printk(KERN_ALERT
+	       "Unable to handle kernel %s at virtual address %08lx\n",
+	       (addr < PAGE_SIZE) ? "NULL pointer dereference" :
+	       "paging request", addr);
+
+	show_pte(mm, addr);
+	die("Oops", regs, fsr);
+	bust_spinlocks(0);
+	do_exit(SIGKILL);
+}
+
+/*
+ * Something tried to access memory that isn't in our memory map..
+ * User mode accesses just cause a SIGSEGV
+ */
+static void __do_user_fault(struct task_struct *tsk, unsigned long addr,
+		unsigned int fsr, unsigned int sig, int code,
+		struct pt_regs *regs)
+{
+	struct siginfo si;
+
+	tsk->thread.address = addr;
+	tsk->thread.error_code = fsr;
+	tsk->thread.trap_no = 14;
+	si.si_signo = sig;
+	si.si_errno = 0;
+	si.si_code = code;
+	si.si_addr = (void __user *)addr;
+	force_sig_info(sig, &si, tsk);
+}
+
+void do_bad_area(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	struct task_struct *tsk = current;
+	struct mm_struct *mm = tsk->active_mm;
+
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (user_mode(regs))
+		__do_user_fault(tsk, addr, fsr, SIGSEGV, SEGV_MAPERR, regs);
+	else
+		__do_kernel_fault(mm, addr, fsr, regs);
+}
+
+#define VM_FAULT_BADMAP		0x010000
+#define VM_FAULT_BADACCESS	0x020000
+
+/*
+ * Check that the permissions on the VMA allow for the fault which occurred.
+ * If we encountered a write fault, we must have write permission, otherwise
+ * we allow any permission.
+ */
+static inline bool access_error(unsigned int fsr, struct vm_area_struct *vma)
+{
+	unsigned int mask = VM_READ | VM_WRITE | VM_EXEC;
+
+	if (!(fsr ^ 0x12))	/* write? */
+		mask = VM_WRITE;
+	if (fsr & FSR_LNX_PF)
+		mask = VM_EXEC;
+
+	return vma->vm_flags & mask ? false : true;
+}
+
+static int __do_pf(struct mm_struct *mm, unsigned long addr, unsigned int fsr,
+		struct task_struct *tsk)
+{
+	struct vm_area_struct *vma;
+	int fault;
+
+	vma = find_vma(mm, addr);
+	fault = VM_FAULT_BADMAP;
+	if (unlikely(!vma))
+		goto out;
+	if (unlikely(vma->vm_start > addr))
+		goto check_stack;
+
+	/*
+	 * Ok, we have a good vm_area for this
+	 * memory access, so we can handle it.
+	 */
+good_area:
+	if (access_error(fsr, vma)) {
+		fault = VM_FAULT_BADACCESS;
+		goto out;
+	}
+
+	/*
+	 * 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, addr & PAGE_MASK,
+			    (!(fsr ^ 0x12)) ? FAULT_FLAG_WRITE : 0);
+	if (unlikely(fault & VM_FAULT_ERROR))
+		return fault;
+	if (fault & VM_FAULT_MAJOR)
+		tsk->maj_flt++;
+	else
+		tsk->min_flt++;
+	return fault;
+
+check_stack:
+	if (vma->vm_flags & VM_GROWSDOWN && !expand_stack(vma, addr))
+		goto good_area;
+out:
+	return fault;
+}
+
+static int do_pf(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	struct task_struct *tsk;
+	struct mm_struct *mm;
+	int fault, sig, code;
+
+	tsk = current;
+	mm = tsk->mm;
+
+	/*
+	 * If we're in an interrupt or have no user
+	 * context, we must not take the fault..
+	 */
+	if (in_atomic() || !mm)
+		goto no_context;
+
+	/*
+	 * As per x86, we may deadlock here.  However, since the kernel only
+	 * validly references user space from well defined areas of the code,
+	 * we can bug out early if this is from code which shouldn't.
+	 */
+	if (!down_read_trylock(&mm->mmap_sem)) {
+		if (!user_mode(regs)
+		    && !search_exception_tables(regs->UCreg_pc))
+			goto no_context;
+		down_read(&mm->mmap_sem);
+	} else {
+		/*
+		 * The above down_read_trylock() might have succeeded in
+		 * which case, we'll have missed the might_sleep() from
+		 * down_read()
+		 */
+		might_sleep();
+#ifdef CONFIG_DEBUG_VM
+		if (!user_mode(regs) &&
+		    !search_exception_tables(regs->UCreg_pc))
+			goto no_context;
+#endif
+	}
+
+	fault = __do_pf(mm, addr, fsr, tsk);
+	up_read(&mm->mmap_sem);
+
+	/*
+	 * Handle the "normal" case first - VM_FAULT_MAJOR / VM_FAULT_MINOR
+	 */
+	if (likely(!(fault &
+	       (VM_FAULT_ERROR | VM_FAULT_BADMAP | VM_FAULT_BADACCESS))))
+		return 0;
+
+	if (fault & VM_FAULT_OOM) {
+		/*
+		 * We ran out of memory, call the OOM killer, and return to
+		 * userspace (which will retry the fault, or kill us if we
+		 * got oom-killed)
+		 */
+		pagefault_out_of_memory();
+		return 0;
+	}
+
+	/*
+	 * If we are in kernel mode at this point, we
+	 * have no context to handle this fault with.
+	 */
+	if (!user_mode(regs))
+		goto no_context;
+
+	if (fault & VM_FAULT_SIGBUS) {
+		/*
+		 * We had some memory, but were unable to
+		 * successfully fix up this page fault.
+		 */
+		sig = SIGBUS;
+		code = BUS_ADRERR;
+	} else {
+		/*
+		 * Something tried to access memory that
+		 * isn't in our memory map..
+		 */
+		sig = SIGSEGV;
+		code = fault == VM_FAULT_BADACCESS ? SEGV_ACCERR : SEGV_MAPERR;
+	}
+
+	__do_user_fault(tsk, addr, fsr, sig, code, regs);
+	return 0;
+
+no_context:
+	__do_kernel_fault(mm, addr, fsr, regs);
+	return 0;
+}
+
+/*
+ * First Level Translation Fault Handler
+ *
+ * We enter here because the first level page table doesn't contain
+ * a valid entry for the address.
+ *
+ * If the address is in kernel space (>= TASK_SIZE), then we are
+ * probably faulting in the vmalloc() area.
+ *
+ * If the init_task's first level page tables contains the relevant
+ * entry, we copy the it to this task.  If not, we send the process
+ * a signal, fixup the exception, or oops the kernel.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may be in an
+ * interrupt or a critical region, and should only copy the information
+ * from the master page table, nothing more.
+ */
+static int do_ifault(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	unsigned int index;
+	pgd_t *pgd, *pgd_k;
+	pmd_t *pmd, *pmd_k;
+
+	if (addr < TASK_SIZE)
+		return do_pf(addr, fsr, regs);
+
+	if (user_mode(regs))
+		goto bad_area;
+
+	index = pgd_index(addr);
+
+	pgd = cpu_get_pgd() + index;
+	pgd_k = init_mm.pgd + index;
+
+	if (pgd_none(*pgd_k))
+		goto bad_area;
+
+	pmd_k = pmd_offset((pud_t *) pgd_k, addr);
+	pmd = pmd_offset((pud_t *) pgd, addr);
+
+	if (pmd_none(*pmd_k))
+		goto bad_area;
+
+	set_pmd(pmd, *pmd_k);
+	flush_pmd_entry(pmd);
+	return 0;
+
+bad_area:
+	do_bad_area(addr, fsr, regs);
+	return 0;
+}
+
+/*
+ * This abort handler always returns "fault".
+ */
+static int do_bad(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	return 1;
+}
+
+static int do_good(unsigned long addr, unsigned int fsr, struct pt_regs *regs)
+{
+	unsigned int res1, res2;
+
+	printk("dabt exception but no error!\n");
+
+	__asm__ __volatile__(
+			"mff %0,f0\n"
+			"mff %1,f1\n"
+			: "=r"(res1), "=r"(res2)
+			:
+			: "memory");
+
+	printk(KERN_EMERG "r0 :%08x  r1 :%08x\n", res1, res2);
+	panic("shut up\n");
+	return 0;
+}
+
+static struct fsr_info {
+	int (*fn) (unsigned long addr, unsigned int fsr, struct pt_regs *regs);
+	int sig;
+	int code;
+	const char *name;
+} fsr_info[] = {
+	/*
+	 * The following are the standard Unicore-I and UniCore-II aborts.
+	 */
+	{ do_good,	SIGBUS,  0,		"no error"		},
+	{ do_bad,	SIGBUS,  BUS_ADRALN,	"alignment exception"	},
+	{ do_bad,	SIGBUS,  BUS_OBJERR,	"external exception"	},
+	{ do_bad,	SIGBUS,  0,		"burst operation"	},
+	{ do_bad,	SIGBUS,  0,		"unknown 00100"		},
+	{ do_ifault,	SIGSEGV, SEGV_MAPERR,	"2nd level pt non-exist"},
+	{ do_bad,	SIGBUS,  0,		"2nd lvl large pt non-exist" },
+	{ do_bad,	SIGBUS,  0,		"invalid pte"		},
+	{ do_pf,	SIGSEGV, SEGV_MAPERR,	"page miss"		},
+	{ do_bad,	SIGBUS,  0,		"middle page miss"	},
+	{ do_bad,	SIGBUS,	 0,		"large page miss"	},
+	{ do_pf,	SIGSEGV, SEGV_MAPERR,	"super page (section) miss" },
+	{ do_bad,	SIGBUS,  0,		"unknown 01100"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 01101"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 01110"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 01111"		},
+	{ do_bad,	SIGBUS,  0,		"addr: up 3G or IO"	},
+	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"read unreadable addr"	},
+	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"write unwriteable addr"},
+	{ do_pf,	SIGSEGV, SEGV_ACCERR,	"exec unexecutable addr"},
+	{ do_bad,	SIGBUS,  0,		"unknown 10100"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 10101"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 10110"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 10111"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11000"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11001"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11010"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11011"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11100"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11101"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11110"		},
+	{ do_bad,	SIGBUS,  0,		"unknown 11111"		}
+};
+
+void __init hook_fault_code(int nr,
+		int (*fn) (unsigned long, unsigned int, struct pt_regs *),
+		int sig, int code, const char *name)
+{
+	if (nr < 0 || nr >= ARRAY_SIZE(fsr_info))
+		BUG();
+
+	fsr_info[nr].fn   = fn;
+	fsr_info[nr].sig  = sig;
+	fsr_info[nr].code = code;
+	fsr_info[nr].name = name;
+}
+
+/*
+ * Dispatch a data abort to the relevant handler.
+ */
+asmlinkage void do_DataAbort(unsigned long addr, unsigned int fsr,
+			struct pt_regs *regs)
+{
+	const struct fsr_info *inf = fsr_info + fsr_fs(fsr);
+	struct siginfo info;
+
+	if (!inf->fn(addr, fsr & ~FSR_LNX_PF, regs))
+		return;
+
+	printk(KERN_ALERT "Unhandled fault: %s (0x%03x) at 0x%08lx\n",
+	       inf->name, fsr, addr);
+
+	info.si_signo = inf->sig;
+	info.si_errno = 0;
+	info.si_code = inf->code;
+	info.si_addr = (void __user *)addr;
+	uc32_notify_die("", regs, &info, fsr, 0);
+}
+
+asmlinkage void do_PrefetchAbort(unsigned long addr,
+			unsigned int ifsr, struct pt_regs *regs)
+{
+	const struct fsr_info *inf = fsr_info + fsr_fs(ifsr);
+	struct siginfo info;
+
+	if (!inf->fn(addr, ifsr | FSR_LNX_PF, regs))
+		return;
+
+	printk(KERN_ALERT "Unhandled prefetch abort: %s (0x%03x) at 0x%08lx\n",
+	       inf->name, ifsr, addr);
+
+	info.si_signo = inf->sig;
+	info.si_errno = 0;
+	info.si_code = inf->code;
+	info.si_addr = (void __user *)addr;
+	uc32_notify_die("", regs, &info, ifsr, 0);
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/flush.c linux-libre-2.6.39-gnu/arch/unicore32/mm/flush.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/flush.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/flush.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * linux/arch/unicore32/mm/flush.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/mm.h>
+#include <linux/pagemap.h>
+
+#include <asm/cacheflush.h>
+#include <asm/system.h>
+#include <asm/tlbflush.h>
+
+void flush_cache_mm(struct mm_struct *mm)
+{
+}
+
+void flush_cache_range(struct vm_area_struct *vma, unsigned long start,
+		unsigned long end)
+{
+	if (vma->vm_flags & VM_EXEC)
+		__flush_icache_all();
+}
+
+void flush_cache_page(struct vm_area_struct *vma, unsigned long user_addr,
+		unsigned long pfn)
+{
+}
+
+static void flush_ptrace_access(struct vm_area_struct *vma, struct page *page,
+			 unsigned long uaddr, void *kaddr, unsigned long len)
+{
+	/* VIPT non-aliasing D-cache */
+	if (vma->vm_flags & VM_EXEC) {
+		unsigned long addr = (unsigned long)kaddr;
+
+		__cpuc_coherent_kern_range(addr, addr + len);
+	}
+}
+
+/*
+ * Copy user data from/to a page which is mapped into a different
+ * processes address space.  Really, we want to allow our "user
+ * space" model to handle this.
+ *
+ * Note that this code needs to run on the current CPU.
+ */
+void copy_to_user_page(struct vm_area_struct *vma, struct page *page,
+		       unsigned long uaddr, void *dst, const void *src,
+		       unsigned long len)
+{
+	memcpy(dst, src, len);
+	flush_ptrace_access(vma, page, uaddr, dst, len);
+}
+
+void __flush_dcache_page(struct address_space *mapping, struct page *page)
+{
+	/*
+	 * Writeback any data associated with the kernel mapping of this
+	 * page.  This ensures that data in the physical page is mutually
+	 * coherent with the kernels mapping.
+	 */
+	__cpuc_flush_kern_dcache_area(page_address(page), PAGE_SIZE);
+}
+
+/*
+ * Ensure cache coherency between kernel mapping and userspace mapping
+ * of this page.
+ */
+void flush_dcache_page(struct page *page)
+{
+	struct address_space *mapping;
+
+	/*
+	 * The zero page is never written to, so never has any dirty
+	 * cache lines, and therefore never needs to be flushed.
+	 */
+	if (page == ZERO_PAGE(0))
+		return;
+
+	mapping = page_mapping(page);
+
+	if (mapping && !mapping_mapped(mapping))
+		clear_bit(PG_dcache_clean, &page->flags);
+	else {
+		__flush_dcache_page(mapping, page);
+		if (mapping)
+			__flush_icache_all();
+		set_bit(PG_dcache_clean, &page->flags);
+	}
+}
+EXPORT_SYMBOL(flush_dcache_page);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/init.c linux-libre-2.6.39-gnu/arch/unicore32/mm/init.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/init.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,517 @@
+/*
+ *  linux/arch/unicore32/mm/init.c
+ *
+ *  Copyright (C) 2010 GUAN Xue-tao
+ *
+ * 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/errno.h>
+#include <linux/swap.h>
+#include <linux/init.h>
+#include <linux/bootmem.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/initrd.h>
+#include <linux/highmem.h>
+#include <linux/gfp.h>
+#include <linux/memblock.h>
+#include <linux/sort.h>
+#include <linux/dma-mapping.h>
+
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
+#include <mach/map.h>
+
+#include "mm.h"
+
+static unsigned long phys_initrd_start __initdata = 0x01000000;
+static unsigned long phys_initrd_size __initdata = SZ_8M;
+
+static int __init early_initrd(char *p)
+{
+	unsigned long start, size;
+	char *endp;
+
+	start = memparse(p, &endp);
+	if (*endp == ',') {
+		size = memparse(endp + 1, NULL);
+
+		phys_initrd_start = start;
+		phys_initrd_size = size;
+	}
+	return 0;
+}
+early_param("initrd", early_initrd);
+
+/*
+ * This keeps memory configuration data used by a couple memory
+ * initialization functions, as well as show_mem() for the skipping
+ * of holes in the memory map.  It is populated by uc32_add_memory().
+ */
+struct meminfo meminfo;
+
+void show_mem(unsigned int filter)
+{
+	int free = 0, total = 0, reserved = 0;
+	int shared = 0, cached = 0, slab = 0, i;
+	struct meminfo *mi = &meminfo;
+
+	printk(KERN_DEFAULT "Mem-info:\n");
+	show_free_areas();
+
+	for_each_bank(i, mi) {
+		struct membank *bank = &mi->bank[i];
+		unsigned int pfn1, pfn2;
+		struct page *page, *end;
+
+		pfn1 = bank_pfn_start(bank);
+		pfn2 = bank_pfn_end(bank);
+
+		page = pfn_to_page(pfn1);
+		end  = pfn_to_page(pfn2 - 1) + 1;
+
+		do {
+			total++;
+			if (PageReserved(page))
+				reserved++;
+			else if (PageSwapCache(page))
+				cached++;
+			else if (PageSlab(page))
+				slab++;
+			else if (!page_count(page))
+				free++;
+			else
+				shared += page_count(page) - 1;
+			page++;
+		} while (page < end);
+	}
+
+	printk(KERN_DEFAULT "%d pages of RAM\n", total);
+	printk(KERN_DEFAULT "%d free pages\n", free);
+	printk(KERN_DEFAULT "%d reserved pages\n", reserved);
+	printk(KERN_DEFAULT "%d slab pages\n", slab);
+	printk(KERN_DEFAULT "%d pages shared\n", shared);
+	printk(KERN_DEFAULT "%d pages swap cached\n", cached);
+}
+
+static void __init find_limits(unsigned long *min, unsigned long *max_low,
+	unsigned long *max_high)
+{
+	struct meminfo *mi = &meminfo;
+	int i;
+
+	*min = -1UL;
+	*max_low = *max_high = 0;
+
+	for_each_bank(i, mi) {
+		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;
+	}
+}
+
+static void __init uc32_bootmem_init(unsigned long start_pfn,
+	unsigned long end_pfn)
+{
+	struct memblock_region *reg;
+	unsigned int boot_pages;
+	phys_addr_t bitmap;
+	pg_data_t *pgdat;
+
+	/*
+	 * Allocate the bootmem bitmap page.  This must be in a region
+	 * of memory which has already been mapped.
+	 */
+	boot_pages = bootmem_bootmap_pages(end_pfn - start_pfn);
+	bitmap = memblock_alloc_base(boot_pages << PAGE_SHIFT, L1_CACHE_BYTES,
+				__pfn_to_phys(end_pfn));
+
+	/*
+	 * Initialise the bootmem allocator, handing the
+	 * memory banks over to bootmem.
+	 */
+	node_set_online(0);
+	pgdat = NODE_DATA(0);
+	init_bootmem_node(pgdat, __phys_to_pfn(bitmap), start_pfn, end_pfn);
+
+	/* Free the lowmem regions from memblock into bootmem. */
+	for_each_memblock(memory, reg) {
+		unsigned long start = memblock_region_memory_base_pfn(reg);
+		unsigned long end = memblock_region_memory_end_pfn(reg);
+
+		if (end >= end_pfn)
+			end = end_pfn;
+		if (start >= end)
+			break;
+
+		free_bootmem(__pfn_to_phys(start), (end - start) << PAGE_SHIFT);
+	}
+
+	/* Reserve the lowmem memblock reserved regions in bootmem. */
+	for_each_memblock(reserved, reg) {
+		unsigned long start = memblock_region_reserved_base_pfn(reg);
+		unsigned long end = memblock_region_reserved_end_pfn(reg);
+
+		if (end >= end_pfn)
+			end = end_pfn;
+		if (start >= end)
+			break;
+
+		reserve_bootmem(__pfn_to_phys(start),
+			(end - start) << PAGE_SHIFT, BOOTMEM_DEFAULT);
+	}
+}
+
+static void __init uc32_bootmem_free(unsigned long min, unsigned long max_low,
+	unsigned long max_high)
+{
+	unsigned long zone_size[MAX_NR_ZONES], zhole_size[MAX_NR_ZONES];
+	struct memblock_region *reg;
+
+	/*
+	 * initialise the zones.
+	 */
+	memset(zone_size, 0, sizeof(zone_size));
+
+	/*
+	 * The memory size 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] = max_low - min;
+
+	/*
+	 * Calculate the size of the holes.
+	 *  holes = node_size - sum(bank_sizes)
+	 */
+	memcpy(zhole_size, zone_size, sizeof(zhole_size));
+	for_each_memblock(memory, reg) {
+		unsigned long start = memblock_region_memory_base_pfn(reg);
+		unsigned long end = memblock_region_memory_end_pfn(reg);
+
+		if (start < max_low) {
+			unsigned long low_end = min(end, max_low);
+			zhole_size[0] -= low_end - start;
+		}
+	}
+
+	/*
+	 * Adjust the sizes according to any special requirements for
+	 * this machine type.
+	 */
+	arch_adjust_zones(zone_size, zhole_size);
+
+	free_area_init_node(0, zone_size, min, zhole_size);
+}
+
+int pfn_valid(unsigned long pfn)
+{
+	return memblock_is_memory(pfn << PAGE_SHIFT);
+}
+EXPORT_SYMBOL(pfn_valid);
+
+static void uc32_memory_present(void)
+{
+}
+
+static int __init meminfo_cmp(const void *_a, const void *_b)
+{
+	const struct membank *a = _a, *b = _b;
+	long cmp = bank_pfn_start(a) - bank_pfn_start(b);
+	return cmp < 0 ? -1 : cmp > 0 ? 1 : 0;
+}
+
+void __init uc32_memblock_init(struct meminfo *mi)
+{
+	int i;
+
+	sort(&meminfo.bank, meminfo.nr_banks, sizeof(meminfo.bank[0]),
+		meminfo_cmp, NULL);
+
+	memblock_init();
+	for (i = 0; i < mi->nr_banks; i++)
+		memblock_add(mi->bank[i].start, mi->bank[i].size);
+
+	/* Register the kernel text, kernel data and initrd with memblock. */
+	memblock_reserve(__pa(_text), _end - _text);
+
+#ifdef CONFIG_BLK_DEV_INITRD
+	if (phys_initrd_size) {
+		memblock_reserve(phys_initrd_start, phys_initrd_size);
+
+		/* Now convert initrd to virtual addresses */
+		initrd_start = __phys_to_virt(phys_initrd_start);
+		initrd_end = initrd_start + phys_initrd_size;
+	}
+#endif
+
+	uc32_mm_memblock_reserve();
+
+	memblock_analyze();
+	memblock_dump_all();
+}
+
+void __init bootmem_init(void)
+{
+	unsigned long min, max_low, max_high;
+
+	max_low = max_high = 0;
+
+	find_limits(&min, &max_low, &max_high);
+
+	uc32_bootmem_init(min, max_low);
+
+#ifdef CONFIG_SWIOTLB
+	swiotlb_init(1);
+#endif
+	/*
+	 * Sparsemem tries to allocate bootmem in memory_present(),
+	 * so must be done after the fixed reservations
+	 */
+	uc32_memory_present();
+
+	/*
+	 * sparse_init() needs the bootmem allocator up and running.
+	 */
+	sparse_init();
+
+	/*
+	 * Now free the memory - free_area_init_node needs
+	 * the sparse mem_map arrays initialized by sparse_init()
+	 * for memmap_init_zone(), otherwise all PFNs are invalid.
+	 */
+	uc32_bootmem_free(min, max_low, max_high);
+
+	high_memory = __va((max_low << PAGE_SHIFT) - 1) + 1;
+
+	/*
+	 * This doesn't seem to be used by the Linux memory manager any
+	 * more, but is used by ll_rw_block.  If we can get rid of it, we
+	 * also get rid of some of the stuff above as well.
+	 *
+	 * Note: max_low_pfn and max_pfn reflect the number of _pages_ in
+	 * the system, not the maximum PFN.
+	 */
+	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)
+{
+	unsigned int pages = 0, size = (end - pfn) << (PAGE_SHIFT - 10);
+
+	for (; pfn < end; pfn++) {
+		struct page *page = pfn_to_page(pfn);
+		ClearPageReserved(page);
+		init_page_count(page);
+		__free_page(page);
+		pages++;
+	}
+
+	if (size && s)
+		printk(KERN_INFO "Freeing %s memory: %dK\n", s, size);
+
+	return pages;
+}
+
+static inline void
+free_memmap(unsigned long start_pfn, unsigned long end_pfn)
+{
+	struct page *start_pg, *end_pg;
+	unsigned long pg, pgend;
+
+	/*
+	 * Convert start_pfn/end_pfn to a struct page pointer.
+	 */
+	start_pg = pfn_to_page(start_pfn - 1) + 1;
+	end_pg = pfn_to_page(end_pfn);
+
+	/*
+	 * Convert to physical addresses, and
+	 * round start upwards and end downwards.
+	 */
+	pg = PAGE_ALIGN(__pa(start_pg));
+	pgend = __pa(end_pg) & PAGE_MASK;
+
+	/*
+	 * If there are free pages between these,
+	 * free the section of the memmap array.
+	 */
+	if (pg < pgend)
+		free_bootmem(pg, pgend - pg);
+}
+
+/*
+ * The mem_map array can get very big.  Free the unused area of the memory map.
+ */
+static void __init free_unused_memmap(struct meminfo *mi)
+{
+	unsigned long bank_start, prev_bank_end = 0;
+	unsigned int i;
+
+	/*
+	 * This relies on each bank being in address order.
+	 * The banks are sorted previously in bootmem_init().
+	 */
+	for_each_bank(i, mi) {
+		struct membank *bank = &mi->bank[i];
+
+		bank_start = bank_pfn_start(bank);
+
+		/*
+		 * If we had a previous bank, and there is a space
+		 * between the current bank and the previous, free it.
+		 */
+		if (prev_bank_end && prev_bank_end < bank_start)
+			free_memmap(prev_bank_end, bank_start);
+
+		/*
+		 * Align up here since the VM subsystem insists that the
+		 * memmap entries are valid from the bank end aligned to
+		 * MAX_ORDER_NR_PAGES.
+		 */
+		prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
+	}
+}
+
+/*
+ * mem_init() marks the free areas in the mem_map and tells us how much
+ * memory is free.  This is done after various parts of the system have
+ * claimed their memory after the kernel image.
+ */
+void __init mem_init(void)
+{
+	unsigned long reserved_pages, free_pages;
+	struct memblock_region *reg;
+	int i;
+
+	max_mapnr   = pfn_to_page(max_pfn + PHYS_PFN_OFFSET) - mem_map;
+
+	/* this will put all unused low memory onto the freelists */
+	free_unused_memmap(&meminfo);
+
+	totalram_pages += free_all_bootmem();
+
+	reserved_pages = free_pages = 0;
+
+	for_each_bank(i, &meminfo) {
+		struct membank *bank = &meminfo.bank[i];
+		unsigned int pfn1, pfn2;
+		struct page *page, *end;
+
+		pfn1 = bank_pfn_start(bank);
+		pfn2 = bank_pfn_end(bank);
+
+		page = pfn_to_page(pfn1);
+		end  = pfn_to_page(pfn2 - 1) + 1;
+
+		do {
+			if (PageReserved(page))
+				reserved_pages++;
+			else if (!page_count(page))
+				free_pages++;
+			page++;
+		} while (page < end);
+	}
+
+	/*
+	 * Since our memory may not be contiguous, calculate the
+	 * real number of pages we have in this system
+	 */
+	printk(KERN_INFO "Memory:");
+	num_physpages = 0;
+	for_each_memblock(memory, reg) {
+		unsigned long pages = memblock_region_memory_end_pfn(reg) -
+			memblock_region_memory_base_pfn(reg);
+		num_physpages += pages;
+		printk(" %ldMB", pages >> (20 - PAGE_SHIFT));
+	}
+	printk(" = %luMB total\n", num_physpages >> (20 - PAGE_SHIFT));
+
+	printk(KERN_NOTICE "Memory: %luk/%luk available, %luk reserved, %luK highmem\n",
+		nr_free_pages() << (PAGE_SHIFT-10),
+		free_pages << (PAGE_SHIFT-10),
+		reserved_pages << (PAGE_SHIFT-10),
+		totalhigh_pages << (PAGE_SHIFT-10));
+
+	printk(KERN_NOTICE "Virtual kernel memory layout:\n"
+		"    vector  : 0x%08lx - 0x%08lx   (%4ld kB)\n"
+		"    vmalloc : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    lowmem  : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"    modules : 0x%08lx - 0x%08lx   (%4ld MB)\n"
+		"      .init : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		"      .text : 0x%p" " - 0x%p" "   (%4d kB)\n"
+		"      .data : 0x%p" " - 0x%p" "   (%4d kB)\n",
+
+		VECTORS_BASE, VECTORS_BASE + PAGE_SIZE,
+		DIV_ROUND_UP(PAGE_SIZE, SZ_1K),
+		VMALLOC_START, VMALLOC_END,
+		DIV_ROUND_UP((VMALLOC_END - VMALLOC_START), SZ_1M),
+		PAGE_OFFSET, (unsigned long)high_memory,
+		DIV_ROUND_UP(((unsigned long)high_memory - PAGE_OFFSET), SZ_1M),
+		MODULES_VADDR, MODULES_END,
+		DIV_ROUND_UP((MODULES_END - MODULES_VADDR), SZ_1M),
+
+		__init_begin, __init_end,
+		DIV_ROUND_UP((__init_end - __init_begin), SZ_1K),
+		_stext, _etext,
+		DIV_ROUND_UP((_etext - _stext), SZ_1K),
+		_sdata, _edata,
+		DIV_ROUND_UP((_edata - _sdata), SZ_1K));
+
+	BUILD_BUG_ON(TASK_SIZE				> MODULES_VADDR);
+	BUG_ON(TASK_SIZE				> MODULES_VADDR);
+
+	if (PAGE_SIZE >= 16384 && num_physpages <= 128) {
+		/*
+		 * On a machine this small we won't get
+		 * anywhere without overcommit, so turn
+		 * it on by default.
+		 */
+		sysctl_overcommit_memory = OVERCOMMIT_ALWAYS;
+	}
+}
+
+void free_initmem(void)
+{
+	totalram_pages += free_area(__phys_to_pfn(__pa(__init_begin)),
+				    __phys_to_pfn(__pa(__init_end)),
+				    "init");
+}
+
+#ifdef CONFIG_BLK_DEV_INITRD
+
+static int keep_initrd;
+
+void free_initrd_mem(unsigned long start, unsigned long end)
+{
+	if (!keep_initrd)
+		totalram_pages += free_area(__phys_to_pfn(__pa(start)),
+					    __phys_to_pfn(__pa(end)),
+					    "initrd");
+}
+
+static int __init keepinitrd_setup(char *__unused)
+{
+	keep_initrd = 1;
+	return 1;
+}
+
+__setup("keepinitrd", keepinitrd_setup);
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/ioremap.c linux-libre-2.6.39-gnu/arch/unicore32/mm/ioremap.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/ioremap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/ioremap.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,261 @@
+/*
+ * linux/arch/unicore32/mm/ioremap.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * This allows a driver to remap an arbitrary region of bus memory into
+ * virtual space.  One should *only* use readl, writel, memcpy_toio and
+ * so on with such remapped areas.
+ *
+ * Because UniCore only has a 32-bit address space we can't address the
+ * whole of the (physical) PCI space at once.  PCI huge-mode addressing
+ * allows us to circumvent this restriction by splitting PCI space into
+ * two 2GB chunks and mapping only one at a time into processor memory.
+ * We use MMU protection domains to trap any attempt to access the bank
+ * that is not currently mapped.  (This isn't fully implemented yet.)
+ */
+#include <linux/module.h>
+#include <linux/errno.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/cacheflush.h>
+#include <asm/mmu_context.h>
+#include <asm/pgalloc.h>
+#include <asm/tlbflush.h>
+#include <asm/sizes.h>
+
+#include <mach/map.h>
+#include "mm.h"
+
+/*
+ * Used by ioremap() and iounmap() code to mark (super)section-mapped
+ * I/O regions in vm_struct->flags field.
+ */
+#define VM_UNICORE_SECTION_MAPPING	0x80000000
+
+int ioremap_page(unsigned long virt, unsigned long phys,
+		 const struct mem_type *mtype)
+{
+	return ioremap_page_range(virt, virt + PAGE_SIZE, phys,
+				  __pgprot(mtype->prot_pte));
+}
+EXPORT_SYMBOL(ioremap_page);
+
+/*
+ * Section support is unsafe on SMP - If you iounmap and ioremap a region,
+ * the other CPUs will not see this change until their next context switch.
+ * Meanwhile, (eg) if an interrupt comes in on one of those other CPUs
+ * which requires the new ioremap'd region to be referenced, the CPU will
+ * reference the _old_ region.
+ *
+ * Note that get_vm_area_caller() allocates a guard 4K page, so we need to
+ * mask the size back to 4MB aligned or we will overflow in the loop below.
+ */
+static void unmap_area_sections(unsigned long virt, unsigned long size)
+{
+	unsigned long addr = virt, end = virt + (size & ~(SZ_4M - 1));
+	pgd_t *pgd;
+
+	flush_cache_vunmap(addr, end);
+	pgd = pgd_offset_k(addr);
+	do {
+		pmd_t pmd, *pmdp = pmd_offset((pud_t *)pgd, addr);
+
+		pmd = *pmdp;
+		if (!pmd_none(pmd)) {
+			/*
+			 * Clear the PMD from the page table, and
+			 * increment the kvm sequence so others
+			 * notice this change.
+			 *
+			 * Note: this is still racy on SMP machines.
+			 */
+			pmd_clear(pmdp);
+
+			/*
+			 * Free the page table, if there was one.
+			 */
+			if ((pmd_val(pmd) & PMD_TYPE_MASK) == PMD_TYPE_TABLE)
+				pte_free_kernel(&init_mm, pmd_page_vaddr(pmd));
+		}
+
+		addr += PGDIR_SIZE;
+		pgd++;
+	} while (addr < end);
+
+	flush_tlb_kernel_range(virt, end);
+}
+
+static int
+remap_area_sections(unsigned long virt, unsigned long pfn,
+		    size_t size, const struct mem_type *type)
+{
+	unsigned long addr = virt, end = virt + size;
+	pgd_t *pgd;
+
+	/*
+	 * Remove and free any PTE-based mapping, and
+	 * sync the current kernel mapping.
+	 */
+	unmap_area_sections(virt, size);
+
+	pgd = pgd_offset_k(addr);
+	do {
+		pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
+
+		set_pmd(pmd, __pmd(__pfn_to_phys(pfn) | type->prot_sect));
+		pfn += SZ_4M >> PAGE_SHIFT;
+		flush_pmd_entry(pmd);
+
+		addr += PGDIR_SIZE;
+		pgd++;
+	} while (addr < end);
+
+	return 0;
+}
+
+void __iomem *__uc32_ioremap_pfn_caller(unsigned long pfn,
+	unsigned long offset, size_t size, unsigned int mtype, void *caller)
+{
+	const struct mem_type *type;
+	int err;
+	unsigned long addr;
+	struct vm_struct *area;
+
+	/*
+	 * High mappings must be section aligned
+	 */
+	if (pfn >= 0x100000 && (__pfn_to_phys(pfn) & ~SECTION_MASK))
+		return NULL;
+
+	/*
+	 * Don't allow RAM to be mapped
+	 */
+	if (pfn_valid(pfn)) {
+		printk(KERN_WARNING "BUG: Your driver calls ioremap() on\n"
+			"system memory.  This leads to architecturally\n"
+			"unpredictable behaviour, and ioremap() will fail in\n"
+			"the next kernel release. Please fix your driver.\n");
+		WARN_ON(1);
+	}
+
+	type = get_mem_type(mtype);
+	if (!type)
+		return NULL;
+
+	/*
+	 * Page align the mapping size, taking account of any offset.
+	 */
+	size = PAGE_ALIGN(offset + size);
+
+	area = get_vm_area_caller(size, VM_IOREMAP, caller);
+	if (!area)
+		return NULL;
+	addr = (unsigned long)area->addr;
+
+	if (!((__pfn_to_phys(pfn) | size | addr) & ~PMD_MASK)) {
+		area->flags |= VM_UNICORE_SECTION_MAPPING;
+		err = remap_area_sections(addr, pfn, size, type);
+	} else
+		err = ioremap_page_range(addr, addr + size, __pfn_to_phys(pfn),
+					 __pgprot(type->prot_pte));
+
+	if (err) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+
+	flush_cache_vmap(addr, addr + size);
+	return (void __iomem *) (offset + addr);
+}
+
+void __iomem *__uc32_ioremap_caller(unsigned long phys_addr, size_t size,
+	unsigned int mtype, void *caller)
+{
+	unsigned long last_addr;
+	unsigned long offset = phys_addr & ~PAGE_MASK;
+	unsigned long pfn = __phys_to_pfn(phys_addr);
+
+	/*
+	 * Don't allow wraparound or zero size
+	 */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype, caller);
+}
+
+/*
+ * 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 __iomem *
+__uc32_ioremap_pfn(unsigned long pfn, unsigned long offset, size_t size,
+		  unsigned int mtype)
+{
+	return __uc32_ioremap_pfn_caller(pfn, offset, size, mtype,
+			__builtin_return_address(0));
+}
+EXPORT_SYMBOL(__uc32_ioremap_pfn);
+
+void __iomem *
+__uc32_ioremap(unsigned long phys_addr, size_t size)
+{
+	return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE,
+			__builtin_return_address(0));
+}
+EXPORT_SYMBOL(__uc32_ioremap);
+
+void __iomem *
+__uc32_ioremap_cached(unsigned long phys_addr, size_t size)
+{
+	return __uc32_ioremap_caller(phys_addr, size, MT_DEVICE_CACHED,
+			__builtin_return_address(0));
+}
+EXPORT_SYMBOL(__uc32_ioremap_cached);
+
+void __uc32_iounmap(volatile void __iomem *io_addr)
+{
+	void *addr = (void *)(PAGE_MASK & (unsigned long)io_addr);
+	struct vm_struct **p, *tmp;
+
+	/*
+	 * If this is a section based mapping we need to handle it
+	 * specially as the VM subsystem does not know how to handle
+	 * such a beast. We need the lock here b/c we need to clear
+	 * all the mappings before the area can be reclaimed
+	 * by someone else.
+	 */
+	write_lock(&vmlist_lock);
+	for (p = &vmlist ; (tmp = *p) ; p = &tmp->next) {
+		if ((tmp->flags & VM_IOREMAP) && (tmp->addr == addr)) {
+			if (tmp->flags & VM_UNICORE_SECTION_MAPPING) {
+				unmap_area_sections((unsigned long)tmp->addr,
+						    tmp->size);
+			}
+			break;
+		}
+	}
+	write_unlock(&vmlist_lock);
+
+	vunmap(addr);
+}
+EXPORT_SYMBOL(__uc32_iounmap);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/Kconfig linux-libre-2.6.39-gnu/arch/unicore32/mm/Kconfig
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,50 @@
+comment "Processor Type"
+
+# Select CPU types depending on the architecture selected.  This selects
+# which CPUs we support in the kernel image, and the compiler instruction
+# optimiser behaviour.
+
+config CPU_UCV2
+	def_bool y
+
+comment "Processor Features"
+
+config CPU_ICACHE_DISABLE
+	bool "Disable I-Cache (I-bit)"
+	help
+	  Say Y here to disable the processor instruction cache. Unless
+	  you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_DISABLE
+	bool "Disable D-Cache (D-bit)"
+	help
+	  Say Y here to disable the processor data cache. Unless
+	  you have a reason not to or are unsure, say N.
+
+config CPU_DCACHE_WRITETHROUGH
+	bool "Force write through D-cache"
+	help
+	  Say Y here to use the data cache in writethrough mode. Unless you
+	  specifically require this or are unsure, say N.
+
+config CPU_DCACHE_LINE_DISABLE
+	bool "Disable D-cache line ops"
+	default y
+	help
+	  Say Y here to disable the data cache line operations.
+
+config CPU_TLB_SINGLE_ENTRY_DISABLE
+	bool "Disable TLB single entry ops"
+	default y
+	help
+	  Say Y here to disable the TLB single entry operations.
+
+config SWIOTLB
+	def_bool y
+
+config IOMMU_HELPER
+	def_bool SWIOTLB
+
+config NEED_SG_DMA_LENGTH
+	def_bool SWIOTLB
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/Makefile linux-libre-2.6.39-gnu/arch/unicore32/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,15 @@
+#
+# Makefile for the linux unicore-specific parts of the memory manager.
+#
+
+obj-y				:= extable.o fault.o init.o pgd.o mmu.o
+obj-y				+= flush.o ioremap.o
+
+obj-$(CONFIG_SWIOTLB)		+= dma-swiotlb.o
+
+obj-$(CONFIG_MODULES)		+= proc-syms.o
+
+obj-$(CONFIG_ALIGNMENT_TRAP)	+= alignment.o
+
+obj-$(CONFIG_CPU_UCV2)		+= cache-ucv2.o tlb-ucv2.o proc-ucv2.o
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/mm.h linux-libre-2.6.39-gnu/arch/unicore32/mm/mm.h
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/mm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/mm.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,39 @@
+/*
+ * linux/arch/unicore32/mm/mm.h
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ */
+/* the upper-most page table pointer */
+extern pmd_t *top_pmd;
+extern int sysctl_overcommit_memory;
+
+#define TOP_PTE(x)	pte_offset_kernel(top_pmd, x)
+
+static inline pmd_t *pmd_off(pgd_t *pgd, unsigned long virt)
+{
+	return pmd_offset((pud_t *)pgd, virt);
+}
+
+static inline pmd_t *pmd_off_k(unsigned long virt)
+{
+	return pmd_off(pgd_offset_k(virt), virt);
+}
+
+struct mem_type {
+	unsigned int prot_pte;
+	unsigned int prot_l1;
+	unsigned int prot_sect;
+};
+
+const struct mem_type *get_mem_type(unsigned int type);
+
+extern void __flush_dcache_page(struct address_space *, struct page *);
+
+void __init bootmem_init(void);
+void uc32_mm_memblock_reserve(void);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/mmu.c linux-libre-2.6.39-gnu/arch/unicore32/mm/mmu.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/mmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/mmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,513 @@
+/*
+ * linux/arch/unicore32/mm/mmu.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/errno.h>
+#include <linux/init.h>
+#include <linux/mman.h>
+#include <linux/nodemask.h>
+#include <linux/memblock.h>
+#include <linux/fs.h>
+#include <linux/bootmem.h>
+#include <linux/io.h>
+
+#include <asm/cputype.h>
+#include <asm/sections.h>
+#include <asm/setup.h>
+#include <asm/sizes.h>
+#include <asm/tlb.h>
+
+#include <mach/map.h>
+
+#include "mm.h"
+
+DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
+
+/*
+ * empty_zero_page is a special page that is used for
+ * zero-initialized data and COW.
+ */
+struct page *empty_zero_page;
+EXPORT_SYMBOL(empty_zero_page);
+
+/*
+ * The pmd table for the upper-most set of pages.
+ */
+pmd_t *top_pmd;
+
+pgprot_t pgprot_user;
+EXPORT_SYMBOL(pgprot_user);
+
+pgprot_t pgprot_kernel;
+EXPORT_SYMBOL(pgprot_kernel);
+
+static int __init noalign_setup(char *__unused)
+{
+	cr_alignment &= ~CR_A;
+	cr_no_alignment &= ~CR_A;
+	set_cr(cr_alignment);
+	return 1;
+}
+__setup("noalign", noalign_setup);
+
+void adjust_cr(unsigned long mask, unsigned long set)
+{
+	unsigned long flags;
+
+	mask &= ~CR_A;
+
+	set &= mask;
+
+	local_irq_save(flags);
+
+	cr_no_alignment = (cr_no_alignment & ~mask) | set;
+	cr_alignment = (cr_alignment & ~mask) | set;
+
+	set_cr((get_cr() & ~mask) | set);
+
+	local_irq_restore(flags);
+}
+
+struct map_desc {
+	unsigned long virtual;
+	unsigned long pfn;
+	unsigned long length;
+	unsigned int type;
+};
+
+#define PROT_PTE_DEVICE		(PTE_PRESENT | PTE_YOUNG |	\
+				PTE_DIRTY | PTE_READ | PTE_WRITE)
+#define PROT_SECT_DEVICE	(PMD_TYPE_SECT | PMD_PRESENT |	\
+				PMD_SECT_READ | PMD_SECT_WRITE)
+
+static struct mem_type mem_types[] = {
+	[MT_DEVICE] = {		  /* Strongly ordered */
+		.prot_pte	= PROT_PTE_DEVICE,
+		.prot_l1	= PMD_TYPE_TABLE | PMD_PRESENT,
+		.prot_sect	= PROT_SECT_DEVICE,
+	},
+	/*
+	 * MT_KUSER: pte for vecpage -- cacheable,
+	 *       and sect for unigfx mmap -- noncacheable
+	 */
+	[MT_KUSER] = {
+		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
+				PTE_CACHEABLE | PTE_READ | PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
+		.prot_sect = PROT_SECT_DEVICE,
+	},
+	[MT_HIGH_VECTORS] = {
+		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
+				PTE_CACHEABLE | PTE_READ | PTE_WRITE |
+				PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
+	},
+	[MT_MEMORY] = {
+		.prot_pte  = PTE_PRESENT | PTE_YOUNG | PTE_DIRTY |
+				PTE_WRITE | PTE_EXEC,
+		.prot_l1   = PMD_TYPE_TABLE | PMD_PRESENT,
+		.prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
+				PMD_SECT_READ | PMD_SECT_WRITE | PMD_SECT_EXEC,
+	},
+	[MT_ROM] = {
+		.prot_sect = PMD_TYPE_SECT | PMD_PRESENT | PMD_SECT_CACHEABLE |
+				PMD_SECT_READ,
+	},
+};
+
+const struct mem_type *get_mem_type(unsigned int type)
+{
+	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.
+ */
+static void __init build_mem_type_table(void)
+{
+	pgprot_user   = __pgprot(PTE_PRESENT | PTE_YOUNG | PTE_CACHEABLE);
+	pgprot_kernel = __pgprot(PTE_PRESENT | PTE_YOUNG |
+				 PTE_DIRTY | PTE_READ | PTE_WRITE |
+				 PTE_EXEC | PTE_CACHEABLE);
+}
+
+#define vectors_base()	(vectors_high() ? 0xffff0000 : 0)
+
+static void __init *early_alloc(unsigned long sz)
+{
+	void *ptr = __va(memblock_alloc(sz, sz));
+	memset(ptr, 0, sz);
+	return ptr;
+}
+
+static pte_t * __init early_pte_alloc(pmd_t *pmd, unsigned long addr,
+		unsigned long prot)
+{
+	if (pmd_none(*pmd)) {
+		pte_t *pte = early_alloc(PTRS_PER_PTE * sizeof(pte_t));
+		__pmd_populate(pmd, __pa(pte) | prot);
+	}
+	BUG_ON(pmd_bad(*pmd));
+	return pte_offset_kernel(pmd, addr);
+}
+
+static void __init alloc_init_pte(pmd_t *pmd, unsigned long addr,
+				  unsigned long end, unsigned long pfn,
+				  const struct mem_type *type)
+{
+	pte_t *pte = early_pte_alloc(pmd, addr, type->prot_l1);
+	do {
+		set_pte(pte, pfn_pte(pfn, __pgprot(type->prot_pte)));
+		pfn++;
+	} while (pte++, addr += PAGE_SIZE, addr != end);
+}
+
+static void __init alloc_init_section(pgd_t *pgd, unsigned long addr,
+				      unsigned long end, unsigned long phys,
+				      const struct mem_type *type)
+{
+	pmd_t *pmd = pmd_offset((pud_t *)pgd, addr);
+
+	/*
+	 * Try a section mapping - end, addr and phys must all be aligned
+	 * to a section boundary.
+	 */
+	if (((addr | end | phys) & ~SECTION_MASK) == 0) {
+		pmd_t *p = pmd;
+
+		do {
+			set_pmd(pmd, __pmd(phys | type->prot_sect));
+			phys += SECTION_SIZE;
+		} while (pmd++, addr += SECTION_SIZE, addr != end);
+
+		flush_pmd_entry(p);
+	} else {
+		/*
+		 * No need to loop; pte's aren't interested in the
+		 * individual L1 entries.
+		 */
+		alloc_init_pte(pmd, addr, end, __phys_to_pfn(phys), type);
+	}
+}
+
+/*
+ * Create the page directory entries and any necessary
+ * page tables for the mapping specified by `md'.  We
+ * are able to cope here with varying sizes and address
+ * offsets, and we take full advantage of sections.
+ */
+static void __init create_mapping(struct map_desc *md)
+{
+	unsigned long phys, addr, length, end;
+	const struct mem_type *type;
+	pgd_t *pgd;
+
+	if (md->virtual != vectors_base() && md->virtual < TASK_SIZE) {
+		printk(KERN_WARNING "BUG: not creating mapping for "
+		       "0x%08llx at 0x%08lx in user region\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
+		return;
+	}
+
+	if ((md->type == MT_DEVICE || md->type == MT_ROM) &&
+	    md->virtual >= PAGE_OFFSET && md->virtual < VMALLOC_END) {
+		printk(KERN_WARNING "BUG: mapping for 0x%08llx at 0x%08lx "
+		       "overlaps vmalloc space\n",
+		       __pfn_to_phys((u64)md->pfn), md->virtual);
+	}
+
+	type = &mem_types[md->type];
+
+	addr = md->virtual & PAGE_MASK;
+	phys = (unsigned long)__pfn_to_phys(md->pfn);
+	length = PAGE_ALIGN(md->length + (md->virtual & ~PAGE_MASK));
+
+	if (type->prot_l1 == 0 && ((addr | phys | length) & ~SECTION_MASK)) {
+		printk(KERN_WARNING "BUG: map for 0x%08lx at 0x%08lx can not "
+		       "be mapped using pages, ignoring.\n",
+		       __pfn_to_phys(md->pfn), addr);
+		return;
+	}
+
+	pgd = pgd_offset_k(addr);
+	end = addr + length;
+	do {
+		unsigned long next = pgd_addr_end(addr, end);
+
+		alloc_init_section(pgd, addr, next, phys, type);
+
+		phys += next - addr;
+		addr = next;
+	} while (pgd++, addr != end);
+}
+
+static void * __initdata vmalloc_min = (void *)(VMALLOC_END - SZ_128M);
+
+/*
+ * vmalloc=size forces the vmalloc area to be exactly 'size'
+ * bytes. This can be used to increase (or decrease) the vmalloc
+ * area - the default is 128m.
+ */
+static int __init early_vmalloc(char *arg)
+{
+	unsigned long vmalloc_reserve = memparse(arg, NULL);
+
+	if (vmalloc_reserve < SZ_16M) {
+		vmalloc_reserve = SZ_16M;
+		printk(KERN_WARNING
+			"vmalloc area too small, limiting to %luMB\n",
+			vmalloc_reserve >> 20);
+	}
+
+	if (vmalloc_reserve > VMALLOC_END - (PAGE_OFFSET + SZ_32M)) {
+		vmalloc_reserve = VMALLOC_END - (PAGE_OFFSET + SZ_32M);
+		printk(KERN_WARNING
+			"vmalloc area is too big, limiting to %luMB\n",
+			vmalloc_reserve >> 20);
+	}
+
+	vmalloc_min = (void *)(VMALLOC_END - vmalloc_reserve);
+	return 0;
+}
+early_param("vmalloc", early_vmalloc);
+
+static phys_addr_t lowmem_limit __initdata = SZ_1G;
+
+static void __init sanity_check_meminfo(void)
+{
+	int i, j;
+
+	lowmem_limit = __pa(vmalloc_min - 1) + 1;
+	memblock_set_current_limit(lowmem_limit);
+
+	for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
+		struct membank *bank = &meminfo.bank[j];
+		*bank = meminfo.bank[i];
+		j++;
+	}
+	meminfo.nr_banks = j;
+}
+
+static inline void prepare_page_table(void)
+{
+	unsigned long addr;
+	phys_addr_t end;
+
+	/*
+	 * Clear out all the mappings below the kernel image.
+	 */
+	for (addr = 0; addr < MODULES_VADDR; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Find the end of the first block of lowmem.
+	 */
+	end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
+	if (end >= lowmem_limit)
+		end = lowmem_limit;
+
+	/*
+	 * Clear out all the kernel space mappings, except for the first
+	 * memory bank, up to the end of the vmalloc region.
+	 */
+	for (addr = __phys_to_virt(end);
+	     addr < VMALLOC_END; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+}
+
+/*
+ * Reserve the special regions of memory
+ */
+void __init uc32_mm_memblock_reserve(void)
+{
+	/*
+	 * Reserve the page tables.  These are already in use,
+	 * and can only be in node 0.
+	 */
+	memblock_reserve(__pa(swapper_pg_dir), PTRS_PER_PGD * sizeof(pgd_t));
+}
+
+/*
+ * Set up device the mappings.  Since we clear out the page tables for all
+ * mappings above VMALLOC_END, we will remove any debug device mappings.
+ * This means you have to be careful how you debug this function, or any
+ * called function.  This means you can't use any function or debugging
+ * method which may touch any device, otherwise the kernel _will_ crash.
+ */
+static void __init devicemaps_init(void)
+{
+	struct map_desc map;
+	unsigned long addr;
+	void *vectors;
+
+	/*
+	 * Allocate the vector page early.
+	 */
+	vectors = early_alloc(PAGE_SIZE);
+
+	for (addr = VMALLOC_END; addr; addr += PGDIR_SIZE)
+		pmd_clear(pmd_off_k(addr));
+
+	/*
+	 * Create a mapping for the machine vectors at the high-vectors
+	 * location (0xffff0000).  If we aren't using high-vectors, also
+	 * create a mapping at the low-vectors virtual address.
+	 */
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.virtual = VECTORS_BASE;
+	map.length = PAGE_SIZE;
+	map.type = MT_HIGH_VECTORS;
+	create_mapping(&map);
+
+	/*
+	 * Create a mapping for the kuser page at the special
+	 * location (0xbfff0000) to the same vectors location.
+	 */
+	map.pfn = __phys_to_pfn(virt_to_phys(vectors));
+	map.virtual = KUSER_VECPAGE_BASE;
+	map.length = PAGE_SIZE;
+	map.type = MT_KUSER;
+	create_mapping(&map);
+
+	/*
+	 * Finally flush the caches and tlb to ensure that we're in a
+	 * consistent state wrt the writebuffer.  This also ensures that
+	 * any write-allocated cache lines in the vector page are written
+	 * back.  After this point, we can start to touch devices again.
+	 */
+	local_flush_tlb_all();
+	flush_cache_all();
+}
+
+static void __init map_lowmem(void)
+{
+	struct memblock_region *reg;
+
+	/* Map all the lowmem memory banks. */
+	for_each_memblock(memory, reg) {
+		phys_addr_t start = reg->base;
+		phys_addr_t end = start + reg->size;
+		struct map_desc map;
+
+		if (end > lowmem_limit)
+			end = lowmem_limit;
+		if (start >= end)
+			break;
+
+		map.pfn = __phys_to_pfn(start);
+		map.virtual = __phys_to_virt(start);
+		map.length = end - start;
+		map.type = MT_MEMORY;
+
+		create_mapping(&map);
+	}
+}
+
+/*
+ * paging_init() sets up the page tables, initialises the zone memory
+ * maps, and sets up the zero page, bad page and bad page tables.
+ */
+void __init paging_init(void)
+{
+	void *zero_page;
+
+	build_mem_type_table();
+	sanity_check_meminfo();
+	prepare_page_table();
+	map_lowmem();
+	devicemaps_init();
+
+	top_pmd = pmd_off_k(0xffff0000);
+
+	/* allocate the zero page. */
+	zero_page = early_alloc(PAGE_SIZE);
+
+	bootmem_init();
+
+	empty_zero_page = virt_to_page(zero_page);
+	__flush_dcache_page(NULL, empty_zero_page);
+}
+
+/*
+ * In order to soft-boot, we need to insert a 1:1 mapping in place of
+ * the user-mode pages.  This will then ensure that we have predictable
+ * results when turning the mmu off
+ */
+void setup_mm_for_reboot(char mode)
+{
+	unsigned long base_pmdval;
+	pgd_t *pgd;
+	int i;
+
+	/*
+	 * We need to access to user-mode page tables here. For kernel threads
+	 * we don't have any user-mode mappings so we use the context that we
+	 * "borrowed".
+	 */
+	pgd = current->active_mm->pgd;
+
+	base_pmdval = PMD_SECT_WRITE | PMD_SECT_READ | PMD_TYPE_SECT;
+
+	for (i = 0; i < FIRST_USER_PGD_NR + USER_PTRS_PER_PGD; i++, pgd++) {
+		unsigned long pmdval = (i << PGDIR_SHIFT) | base_pmdval;
+		pmd_t *pmd;
+
+		pmd = pmd_off(pgd, i << PGDIR_SHIFT);
+		set_pmd(pmd, __pmd(pmdval));
+		flush_pmd_entry(pmd);
+	}
+
+	local_flush_tlb_all();
+}
+
+/*
+ * Take care of architecture specific things when placing a new PTE into
+ * a page table, or changing an existing PTE.  Basically, there are two
+ * things that we need to take care of:
+ *
+ *  1. If PG_dcache_clean is not set for the page, we need to ensure
+ *     that any cache entries for the kernels virtual memory
+ *     range are written back to the page.
+ *  2. If we have multiple shared mappings of the same space in
+ *     an object, we need to deal with the cache aliasing issues.
+ *
+ * Note that the pte lock will be held.
+ */
+void update_mmu_cache(struct vm_area_struct *vma, unsigned long addr,
+	pte_t *ptep)
+{
+	unsigned long pfn = pte_pfn(*ptep);
+	struct address_space *mapping;
+	struct page *page;
+
+	if (!pfn_valid(pfn))
+		return;
+
+	/*
+	 * The zero page is never written to, so never has any dirty
+	 * cache lines, and therefore never needs to be flushed.
+	 */
+	page = pfn_to_page(pfn);
+	if (page == ZERO_PAGE(0))
+		return;
+
+	mapping = page_mapping(page);
+	if (!test_and_set_bit(PG_dcache_clean, &page->flags))
+		__flush_dcache_page(mapping, page);
+	if (mapping)
+		if (vma->vm_flags & VM_EXEC)
+			__flush_icache_all();
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/pgd.c linux-libre-2.6.39-gnu/arch/unicore32/mm/pgd.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/pgd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/pgd.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,102 @@
+/*
+ * linux/arch/unicore32/mm/pgd.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/mm.h>
+#include <linux/gfp.h>
+#include <linux/highmem.h>
+
+#include <asm/pgalloc.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+
+#include "mm.h"
+
+#define FIRST_KERNEL_PGD_NR	(FIRST_USER_PGD_NR + USER_PTRS_PER_PGD)
+
+/*
+ * need to get a 4k page for level 1
+ */
+pgd_t *get_pgd_slow(struct mm_struct *mm)
+{
+	pgd_t *new_pgd, *init_pgd;
+	pmd_t *new_pmd, *init_pmd;
+	pte_t *new_pte, *init_pte;
+
+	new_pgd = (pgd_t *)__get_free_pages(GFP_KERNEL, 0);
+	if (!new_pgd)
+		goto no_pgd;
+
+	memset(new_pgd, 0, FIRST_KERNEL_PGD_NR * sizeof(pgd_t));
+
+	/*
+	 * Copy over the kernel and IO PGD entries
+	 */
+	init_pgd = pgd_offset_k(0);
+	memcpy(new_pgd + FIRST_KERNEL_PGD_NR, init_pgd + FIRST_KERNEL_PGD_NR,
+		       (PTRS_PER_PGD - FIRST_KERNEL_PGD_NR) * sizeof(pgd_t));
+
+	clean_dcache_area(new_pgd, PTRS_PER_PGD * sizeof(pgd_t));
+
+	if (!vectors_high()) {
+		/*
+		 * On UniCore, first page must always be allocated since it
+		 * contains the machine vectors.
+		 */
+		new_pmd = pmd_alloc(mm, (pud_t *)new_pgd, 0);
+		if (!new_pmd)
+			goto no_pmd;
+
+		new_pte = pte_alloc_map(mm, NULL, new_pmd, 0);
+		if (!new_pte)
+			goto no_pte;
+
+		init_pmd = pmd_offset((pud_t *)init_pgd, 0);
+		init_pte = pte_offset_map(init_pmd, 0);
+		set_pte(new_pte, *init_pte);
+		pte_unmap(init_pte);
+		pte_unmap(new_pte);
+	}
+
+	return new_pgd;
+
+no_pte:
+	pmd_free(mm, new_pmd);
+no_pmd:
+	free_pages((unsigned long)new_pgd, 0);
+no_pgd:
+	return NULL;
+}
+
+void free_pgd_slow(struct mm_struct *mm, pgd_t *pgd)
+{
+	pmd_t *pmd;
+	pgtable_t pte;
+
+	if (!pgd)
+		return;
+
+	/* pgd is always present and good */
+	pmd = pmd_off(pgd, 0);
+	if (pmd_none(*pmd))
+		goto free;
+	if (pmd_bad(*pmd)) {
+		pmd_ERROR(*pmd);
+		pmd_clear(pmd);
+		goto free;
+	}
+
+	pte = pmd_pgtable(*pmd);
+	pmd_clear(pmd);
+	pte_free(mm, pte);
+	pmd_free(mm, pmd);
+free:
+	free_pages((unsigned long) pgd, 0);
+}
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/proc-macros.S linux-libre-2.6.39-gnu/arch/unicore32/mm/proc-macros.S
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/proc-macros.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/proc-macros.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * linux/arch/unicore32/mm/proc-macros.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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.
+ *
+ * We need constants.h for:
+ *  VMA_VM_MM
+ *  VMA_VM_FLAGS
+ *  VM_EXEC
+ */
+#include <generated/asm-offsets.h>
+#include <asm/thread_info.h>
+#include <asm/memory.h>
+
+/*
+ * the cache line sizes of the I and D cache are the same
+ */
+#define CACHE_LINESIZE	32
+
+/*
+ * This is the maximum size of an area which will be invalidated
+ * using the single invalidate entry instructions.  Anything larger
+ * than this, and we go for the whole cache.
+ *
+ * This value should be chosen such that we choose the cheapest
+ * alternative.
+ */
+#ifdef CONFIG_CPU_UCV2
+#define MAX_AREA_SIZE	0x800		/* 64 cache line */
+#endif
+
+/*
+ * vma_vm_mm - get mm pointer from vma pointer (vma->vm_mm)
+ */
+	.macro	vma_vm_mm, rd, rn
+	ldw	\rd, [\rn+], #VMA_VM_MM
+	.endm
+
+/*
+ * vma_vm_flags - get vma->vm_flags
+ */
+	.macro	vma_vm_flags, rd, rn
+	ldw	\rd, [\rn+], #VMA_VM_FLAGS
+	.endm
+
+	.macro	tsk_mm, rd, rn
+	ldw	\rd, [\rn+], #TI_TASK
+	ldw	\rd, [\rd+], #TSK_ACTIVE_MM
+	.endm
+
+/*
+ * act_mm - get current->active_mm
+ */
+	.macro	act_mm, rd
+	andn	\rd, sp, #8128
+	andn	\rd, \rd, #63
+	ldw	\rd, [\rd+], #TI_TASK
+	ldw	\rd, [\rd+], #TSK_ACTIVE_MM
+	.endm
+
+/*
+ * mmid - get context id from mm pointer (mm->context.id)
+ */
+	.macro	mmid, rd, rn
+	ldw	\rd, [\rn+], #MM_CONTEXT_ID
+	.endm
+
+/*
+ * mask_asid - mask the ASID from the context ID
+ */
+	.macro	asid, rd, rn
+	and	\rd, \rn, #255
+	.endm
+
+	.macro	crval, clear, mmuset, ucset
+	.word	\clear
+	.word	\mmuset
+	.endm
+
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+/*
+ * va2pa va, pa, tbl, msk, off, err
+ *	This macro is used to translate virtual address to its physical address.
+ *
+ *	va: virtual address
+ *	pa: physical address, result is stored in this register
+ *	tbl, msk, off:	temp registers, will be destroyed
+ *	err: jump to error label if the physical address not exist
+ * NOTE: all regs must be different
+ */
+	.macro	va2pa, va, pa, tbl, msk, off, err=990f
+	movc	\pa, p0.c2, #0
+	mov	\off, \va >> #22		@ off <- index of 1st page table
+	adr	\tbl, 910f			@ tbl <- table of 1st page table
+900:						@ ---- handle 1, 2 page table
+	add	\pa, \pa, #PAGE_OFFSET		@ pa <- virt addr of page table
+	ldw	\pa, [\pa+], \off << #2		@ pa <- the content of pt
+	cand.a	\pa, #4				@ test exist bit
+	beq	\err				@ if not exist
+	and	\off, \pa, #3			@ off <- the last 2 bits
+	add	\tbl, \tbl, \off << #3		@ cmove table pointer
+	ldw	\msk, [\tbl+], #0		@ get the mask
+	ldw	pc, [\tbl+], #4
+930:						@ ---- handle 2nd page table
+	and	\pa, \pa, \msk			@ pa <- phys addr of 2nd pt
+	mov	\off, \va << #10
+	cntlo	\tbl, \msk			@ use tbl as temp reg
+	mov	\off, \off >> \tbl
+	mov	\off, \off >> #2		@ off <- index of 2nd pt
+	adr	\tbl, 920f			@ tbl <- table of 2nd pt
+	b	900b
+910:						@ 1st level page table
+	.word	0xfffff000, 930b		@ second level page table
+	.word	0xfffffc00, 930b		@ second level large page table
+	.word	0x00000000, \err		@ invalid
+	.word	0xffc00000, 980f		@ super page
+
+920:						@ 2nd level page table
+	.word	0xfffff000, 980f		@ page
+	.word	0xffffc000, 980f		@ middle page
+	.word	0xffff0000, 980f		@ large page
+	.word	0x00000000, \err		@ invalid
+980:
+	andn	\tbl, \va, \msk
+	and	\pa, \pa, \msk
+	or	\pa, \pa, \tbl
+990:
+	.endm
+#endif
+
+	.macro dcacheline_flush, addr, t1, t2
+	mov	\t1, \addr << #20
+	ldw	\t2, =_stext			@ _stext must ALIGN(4096)
+	add	\t2, \t2, \t1 >> #20
+	ldw	\t1, [\t2+], #0x0000
+	ldw	\t1, [\t2+], #0x1000
+	ldw	\t1, [\t2+], #0x2000
+	ldw	\t1, [\t2+], #0x3000
+	.endm
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/proc-syms.c linux-libre-2.6.39-gnu/arch/unicore32/mm/proc-syms.c
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/proc-syms.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/proc-syms.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+/*
+ * linux/arch/unicore32/mm/proc-syms.c
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/mm.h>
+
+#include <asm/cacheflush.h>
+#include <asm/tlbflush.h>
+#include <asm/page.h>
+
+EXPORT_SYMBOL(cpu_dcache_clean_area);
+EXPORT_SYMBOL(cpu_set_pte);
+
+EXPORT_SYMBOL(__cpuc_dma_flush_range);
+EXPORT_SYMBOL(__cpuc_dma_clean_range);
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/proc-ucv2.S linux-libre-2.6.39-gnu/arch/unicore32/mm/proc-ucv2.S
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/proc-ucv2.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/proc-ucv2.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * linux/arch/unicore32/mm/proc-ucv2.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/hwcap.h>
+#include <asm/pgtable-hwdef.h>
+#include <asm/pgtable.h>
+
+#include "proc-macros.S"
+
+ENTRY(cpu_proc_fin)
+	stm.w	(lr), [sp-]
+	mov	ip, #PSR_R_BIT | PSR_I_BIT | PRIV_MODE
+	mov.a	asr, ip
+	b.l	__cpuc_flush_kern_all
+	ldm.w	(pc), [sp]+
+
+/*
+ *	cpu_reset(loc)
+ *
+ *	Perform a soft reset of the system.  Put the CPU into the
+ *	same state as it would be if it had been reset, and branch
+ *	to what would be the reset vector.
+ *
+ *	- loc   - location to jump to for soft reset
+ */
+	.align	5
+ENTRY(cpu_reset)
+	mov	ip, #0
+	movc	p0.c5, ip, #28			@ Cache invalidate all
+	nop8
+
+	movc	p0.c6, ip, #6			@ TLB invalidate all
+	nop8
+
+	movc	ip, p0.c1, #0			@ ctrl register
+	or	ip, ip, #0x2000			@ vector base address
+	andn	ip, ip, #0x000f			@ ............idam
+	movc	p0.c1, ip, #0			@ disable caches and mmu
+	nop
+	mov	pc, r0				@ jump to loc
+	nop8
+
+/*
+ *	cpu_do_idle()
+ *
+ *	Idle the processor (eg, wait for interrupt).
+ *
+ *	IRQs are already disabled.
+ */
+ENTRY(cpu_do_idle)
+	mov	r0, #0				@ PCI address
+	.rept	8
+	ldw	r1, [r0]
+	.endr
+	mov	pc, lr
+
+ENTRY(cpu_dcache_clean_area)
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	csub.a	r1, #MAX_AREA_SIZE
+	bsg	101f
+	mov	r9, #PAGE_SZ
+	sub	r9, r9, #1			@ PAGE_MASK
+1:	va2pa	r0, r10, r11, r12, r13		@ r10 is PA
+	b	3f
+2:	cand.a	r0, r9
+	beq	1b
+3:	movc	p0.c5, r10, #11			@ clean D entry
+	nop8
+	add	r0, r0, #CACHE_LINESIZE
+	add	r10, r10, #CACHE_LINESIZE
+	sub.a	r1, r1, #CACHE_LINESIZE
+	bua	2b
+	mov	pc, lr
+#endif
+101:	mov	ip, #0
+	movc	p0.c5, ip, #10			@ Dcache clean all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	cpu_do_switch_mm(pgd_phys)
+ *
+ *	Set the translation table base pointer to be pgd_phys
+ *
+ *	- pgd_phys - physical address of new pgd
+ *
+ *	It is assumed that:
+ *	- we are not using split page tables
+ */
+	.align	5
+ENTRY(cpu_do_switch_mm)
+	movc	p0.c2, r0, #0			@ update page table ptr
+	nop8
+
+	movc	p0.c6, ip, #6			@ TLB invalidate all
+	nop8
+
+	mov	pc, lr
+
+/*
+ *	cpu_set_pte(ptep, pte)
+ *
+ *	Set a level 2 translation table entry.
+ *
+ *	- ptep  - pointer to level 2 translation table entry
+ *	- pte   - PTE value to store
+ */
+	.align	5
+ENTRY(cpu_set_pte)
+	stw	r1, [r0]
+#ifndef CONFIG_CPU_DCACHE_LINE_DISABLE
+	sub	r2, r0, #PAGE_OFFSET
+	movc	p0.c5, r2, #11				@ Dcache clean line
+	nop8
+#else
+	mov	ip, #0
+	movc	p0.c5, ip, #10				@ Dcache clean all
+	nop8
+	@dcacheline_flush	r0, r2, ip
+#endif
+	mov	pc, lr
+
diff -druN linux-libre-2.6.38-gnu/arch/unicore32/mm/tlb-ucv2.S linux-libre-2.6.39-gnu/arch/unicore32/mm/tlb-ucv2.S
--- linux-libre-2.6.38-gnu/arch/unicore32/mm/tlb-ucv2.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/unicore32/mm/tlb-ucv2.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,89 @@
+/*
+ * linux/arch/unicore32/mm/tlb-ucv2.S
+ *
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ * Copyright (C) 2001-2010 GUAN Xue-tao
+ *
+ * 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/linkage.h>
+#include <asm/assembler.h>
+#include <asm/page.h>
+#include <asm/tlbflush.h>
+#include "proc-macros.S"
+
+/*
+ *	__cpu_flush_user_tlb_range(start, end, vma)
+ *
+ *	Invalidate a range of TLB entries in the specified address space.
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ *	- vma   - vma_struct describing address range
+ */
+ENTRY(__cpu_flush_user_tlb_range)
+#ifndef	CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+	mov	r0, r0 >> #PAGE_SHIFT		@ align address
+	mov	r0, r0 << #PAGE_SHIFT
+	vma_vm_flags r2, r2			@ get vma->vm_flags
+1:
+	movc	p0.c6, r0, #3
+	nop8
+
+	cand.a	r2, #VM_EXEC			@ Executable area ?
+	beq	2f
+
+	movc	p0.c6, r0, #5
+	nop8
+2:
+	add	r0, r0, #PAGE_SZ
+	csub.a	r0, r1
+	beb	1b
+#else
+	movc	p0.c6, r0, #2
+	nop8
+
+	cand.a	r2, #VM_EXEC			@ Executable area ?
+	beq	2f
+
+	movc	p0.c6, r0, #4
+	nop8
+2:
+#endif
+	mov	pc, lr
+
+/*
+ *	__cpu_flush_kern_tlb_range(start,end)
+ *
+ *	Invalidate a range of kernel TLB entries
+ *
+ *	- start - start address (may not be aligned)
+ *	- end   - end address (exclusive, may not be aligned)
+ */
+ENTRY(__cpu_flush_kern_tlb_range)
+#ifndef	CONFIG_CPU_TLB_SINGLE_ENTRY_DISABLE
+	mov	r0, r0 >> #PAGE_SHIFT		@ align address
+	mov	r0, r0 << #PAGE_SHIFT
+1:
+	movc	p0.c6, r0, #3
+	nop8
+
+	movc	p0.c6, r0, #5
+	nop8
+
+	add	r0, r0, #PAGE_SZ
+	csub.a	r0, r1
+	beb	1b
+#else
+	movc	p0.c6, r0, #2
+	nop8
+
+	movc	p0.c6, r0, #4
+	nop8
+#endif
+	mov	pc, lr
+
diff -druN linux-libre-2.6.38-gnu/arch/x86/boot/memory.c linux-libre-2.6.39-gnu/arch/x86/boot/memory.c
--- linux-libre-2.6.38-gnu/arch/x86/boot/memory.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/boot/memory.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
 	if (oreg.ax > 15*1024) {
 		return -1;	/* Bogus! */
 	} else if (oreg.ax == 15*1024) {
-		boot_params.alt_mem_k = (oreg.dx << 6) + oreg.ax;
+		boot_params.alt_mem_k = (oreg.bx << 6) + oreg.ax;
 	} else {
 		/*
 		 * This ignores memory above 16MB if we have a memory
diff -druN linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_asm.S linux-libre-2.6.39-gnu/arch/x86/crypto/aesni-intel_asm.S
--- linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_asm.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/crypto/aesni-intel_asm.S	2011-05-19 00:06:34.000000000 -0400
@@ -1346,7 +1346,7 @@
 	and	$15, %r13				# %r13 = arg4 (mod 16)
 	je	_multiple_of_16_bytes_decrypt
 
-        # Handle the last <16 byte block seperately
+        # Handle the last <16 byte block separately
 
 	paddd ONE(%rip), %xmm0         # increment CNT to get Yn
         movdqa SHUF_MASK(%rip), %xmm10
@@ -1355,7 +1355,7 @@
 	ENCRYPT_SINGLE_BLOCK  %xmm0, %xmm1    # E(K, Yn)
 	sub $16, %r11
 	add %r13, %r11
-	movdqu (%arg3,%r11,1), %xmm1   # recieve the last <16 byte block
+	movdqu (%arg3,%r11,1), %xmm1   # receive the last <16 byte block
 	lea SHIFT_MASK+16(%rip), %r12
 	sub %r13, %r12
 # adjust the shuffle mask pointer to be able to shift 16-%r13 bytes
@@ -1607,11 +1607,12 @@
 	and	$15, %r13			# %r13 = arg4 (mod 16)
 	je	_multiple_of_16_bytes_encrypt
 
-         # Handle the last <16 Byte block seperately
+         # Handle the last <16 Byte block separately
 	paddd ONE(%rip), %xmm0                # INCR CNT to get Yn
         movdqa SHUF_MASK(%rip), %xmm10
 	PSHUFB_XMM %xmm10, %xmm0
 
+
 	ENCRYPT_SINGLE_BLOCK	%xmm0, %xmm1        # Encrypt(K, Yn)
 	sub $16, %r11
 	add %r13, %r11
@@ -1634,7 +1635,9 @@
 	# GHASH computation for the last <16 byte block
 	sub	%r13, %r11
 	add	$16, %r11
-	PSHUFB_XMM %xmm10, %xmm1
+
+	movdqa SHUF_MASK(%rip), %xmm10
+	PSHUFB_XMM %xmm10, %xmm0
 
 	# shuffle xmm0 back to output as ciphertext
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_glue.c linux-libre-2.6.39-gnu/arch/x86/crypto/aesni-intel_glue.c
--- linux-libre-2.6.38-gnu/arch/x86/crypto/aesni-intel_glue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/crypto/aesni-intel_glue.c	2011-05-19 00:06:34.000000000 -0400
@@ -828,9 +828,15 @@
 	struct cryptd_aead *cryptd_tfm;
 	struct aesni_rfc4106_gcm_ctx *ctx = (struct aesni_rfc4106_gcm_ctx *)
 		PTR_ALIGN((u8 *)crypto_tfm_ctx(tfm), AESNI_ALIGN);
+	struct crypto_aead *cryptd_child;
+	struct aesni_rfc4106_gcm_ctx *child_ctx;
 	cryptd_tfm = cryptd_alloc_aead("__driver-gcm-aes-aesni", 0, 0);
 	if (IS_ERR(cryptd_tfm))
 		return PTR_ERR(cryptd_tfm);
+
+	cryptd_child = cryptd_aead_child(cryptd_tfm);
+	child_ctx = aesni_rfc4106_gcm_ctx_get(cryptd_child);
+	memcpy(child_ctx, ctx, sizeof(*ctx));
 	ctx->cryptd_tfm = cryptd_tfm;
 	tfm->crt_aead.reqsize = sizeof(struct aead_request)
 		+ crypto_aead_reqsize(&cryptd_tfm->base);
@@ -873,22 +879,18 @@
 	crypto_ablkcipher_clear_flags(ctr_tfm, ~0);
 
 	ret = crypto_ablkcipher_setkey(ctr_tfm, key, key_len);
-	if (ret) {
-		crypto_free_ablkcipher(ctr_tfm);
-		return ret;
-	}
+	if (ret)
+		goto out_free_ablkcipher;
 
+	ret = -ENOMEM;
 	req = ablkcipher_request_alloc(ctr_tfm, GFP_KERNEL);
-	if (!req) {
-		crypto_free_ablkcipher(ctr_tfm);
-		return -EINVAL;
-	}
+	if (!req)
+		goto out_free_ablkcipher;
 
 	req_data = kmalloc(sizeof(*req_data), GFP_KERNEL);
-	if (!req_data) {
-		crypto_free_ablkcipher(ctr_tfm);
-		return -ENOMEM;
-	}
+	if (!req_data)
+		goto out_free_request;
+
 	memset(req_data->iv, 0, sizeof(req_data->iv));
 
 	/* Clear the data in the hash sub key container to zero.*/
@@ -913,8 +915,10 @@
 		if (!ret)
 			ret = req_data->result.err;
 	}
-	ablkcipher_request_free(req);
 	kfree(req_data);
+out_free_request:
+	ablkcipher_request_free(req);
+out_free_ablkcipher:
 	crypto_free_ablkcipher(ctr_tfm);
 	return ret;
 }
@@ -925,6 +929,9 @@
 	int ret = 0;
 	struct crypto_tfm *tfm = crypto_aead_tfm(parent);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(parent);
+	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
+	struct aesni_rfc4106_gcm_ctx *child_ctx =
+                                 aesni_rfc4106_gcm_ctx_get(cryptd_child);
 	u8 *new_key_mem = NULL;
 
 	if (key_len < 4) {
@@ -968,6 +975,7 @@
 		goto exit;
 	}
 	ret = rfc4106_set_hash_subkey(ctx->hash_subkey, key, key_len);
+	memcpy(child_ctx, ctx, sizeof(*ctx));
 exit:
 	kfree(new_key_mem);
 	return ret;
@@ -999,7 +1007,6 @@
 	int ret;
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
-	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 
 	if (!irq_fpu_usable()) {
 		struct aead_request *cryptd_req =
@@ -1008,6 +1015,7 @@
 		aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
 		return crypto_aead_encrypt(cryptd_req);
 	} else {
+		struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 		kernel_fpu_begin();
 		ret = cryptd_child->base.crt_aead.encrypt(req);
 		kernel_fpu_end();
@@ -1020,7 +1028,6 @@
 	int ret;
 	struct crypto_aead *tfm = crypto_aead_reqtfm(req);
 	struct aesni_rfc4106_gcm_ctx *ctx = aesni_rfc4106_gcm_ctx_get(tfm);
-	struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 
 	if (!irq_fpu_usable()) {
 		struct aead_request *cryptd_req =
@@ -1029,6 +1036,7 @@
 		aead_request_set_tfm(cryptd_req, &ctx->cryptd_tfm->base);
 		return crypto_aead_decrypt(cryptd_req);
 	} else {
+		struct crypto_aead *cryptd_child = cryptd_aead_child(ctx->cryptd_tfm);
 		kernel_fpu_begin();
 		ret = cryptd_child->base.crt_aead.decrypt(req);
 		kernel_fpu_end();
diff -druN linux-libre-2.6.38-gnu/arch/x86/ia32/ia32_aout.c linux-libre-2.6.39-gnu/arch/x86/ia32/ia32_aout.c
--- linux-libre-2.6.38-gnu/arch/x86/ia32/ia32_aout.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/ia32/ia32_aout.c	2011-05-19 00:06:34.000000000 -0400
@@ -298,6 +298,7 @@
 	/* OK, This is the point of no return */
 	set_personality(PER_LINUX);
 	set_thread_flag(TIF_IA32);
+	current->mm->context.ia32_compat = 1;
 
 	setup_new_exec(bprm);
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/ia32/ia32entry.S linux-libre-2.6.39-gnu/arch/x86/ia32/ia32entry.S
--- linux-libre-2.6.38-gnu/arch/x86/ia32/ia32entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/ia32/ia32entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,8 @@
 #define sysretl_audit ia32_ret_from_sys_call
 #endif
 
+	.section .entry.text, "ax"
+
 #define IA32_NR_syscalls ((ia32_syscall_end - ia32_sys_call_table)/8)
 
 	.macro IA32_ARG_FIXUP noebp=0
@@ -126,26 +128,20 @@
 	 */
 	ENABLE_INTERRUPTS(CLBR_NONE)
  	movl	%ebp,%ebp		/* zero extension */
-	pushq	$__USER32_DS
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi $__USER32_DS
 	/*CFI_REL_OFFSET ss,0*/
-	pushq	%rbp
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rbp
 	CFI_REL_OFFSET rsp,0
-	pushfq
-	CFI_ADJUST_CFA_OFFSET 8
+	pushfq_cfi
 	/*CFI_REL_OFFSET rflags,0*/
 	movl	8*3-THREAD_SIZE+TI_sysenter_return(%rsp), %r10d
 	CFI_REGISTER rip,r10
-	pushq	$__USER32_CS
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi $__USER32_CS
 	/*CFI_REL_OFFSET cs,0*/
 	movl	%eax, %eax
-	pushq	%r10
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %r10
 	CFI_REL_OFFSET rip,0
-	pushq	%rax
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rax
 	cld
 	SAVE_ARGS 0,0,1
  	/* no need to do an access_ok check here because rbp has been
@@ -182,11 +178,9 @@
 	xorq	%r9,%r9
 	xorq	%r10,%r10
 	xorq	%r11,%r11
-	popfq
-	CFI_ADJUST_CFA_OFFSET -8
+	popfq_cfi
 	/*CFI_RESTORE rflags*/
-	popq	%rcx				/* User %esp */
-	CFI_ADJUST_CFA_OFFSET -8
+	popq_cfi %rcx				/* User %esp */
 	CFI_REGISTER rsp,rcx
 	TRACE_IRQS_ON
 	ENABLE_INTERRUPTS_SYSEXIT32
@@ -421,8 +415,7 @@
 	 */
 	ENABLE_INTERRUPTS(CLBR_NONE)
 	movl %eax,%eax
-	pushq %rax
-	CFI_ADJUST_CFA_OFFSET 8
+	pushq_cfi %rax
 	cld
 	/* note the registers are not zero extended to the sf.
 	   this could be a problem. */
@@ -851,4 +844,8 @@
 	.quad sys_fanotify_init
 	.quad sys32_fanotify_mark
 	.quad sys_prlimit64		/* 340 */
+	.quad sys_name_to_handle_at
+	.quad compat_sys_open_by_handle_at
+	.quad compat_sys_clock_adjtime
+	.quad sys_syncfs
 ia32_syscall_end:
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/acpi.h linux-libre-2.6.39-gnu/arch/x86/include/asm/acpi.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/acpi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/acpi.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <asm/processor.h>
 #include <asm/mmu.h>
 #include <asm/mpspec.h>
+#include <asm/trampoline.h>
 
 #define COMPILER_DEPENDENT_INT64   long long
 #define COMPILER_DEPENDENT_UINT64  unsigned long long
@@ -113,11 +114,11 @@
 	acpi_noirq_set();
 }
 
-/* routines for saving/restoring kernel state */
-extern int acpi_save_state_mem(void);
-extern void acpi_restore_state_mem(void);
+/* Low-level suspend routine. */
+extern int acpi_suspend_lowlevel(void);
 
-extern unsigned long acpi_wakeup_address;
+extern const unsigned char acpi_wakeup_code[];
+#define acpi_wakeup_address (__pa(TRAMPOLINE_SYM(acpi_wakeup_code)))
 
 /* early initialization routine */
 extern void acpi_reserve_wakeup_memory(void);
@@ -186,15 +187,7 @@
 
 #ifdef CONFIG_ACPI_NUMA
 extern int acpi_numa;
-extern void acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
-				unsigned long end);
-extern int acpi_scan_nodes(unsigned long start, unsigned long end);
-#define NR_NODE_MEMBLKS (MAX_NUMNODES*2)
-
-#ifdef CONFIG_NUMA_EMU
-extern void acpi_fake_nodes(const struct bootnode *fake_nodes,
-				   int num_nodes);
-#endif
+extern int x86_acpi_numa_init(void);
 #endif /* CONFIG_ACPI_NUMA */
 
 #define acpi_unlazy_tlb(x)	leave_mm(x)
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/amd_nb.h linux-libre-2.6.39-gnu/arch/x86/include/asm/amd_nb.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/amd_nb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/amd_nb.h	2011-05-19 00:06:34.000000000 -0400
@@ -9,23 +9,20 @@
 	u8 dev_limit;
 };
 
-extern struct pci_device_id amd_nb_misc_ids[];
+extern const struct pci_device_id amd_nb_misc_ids[];
 extern const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[];
 struct bootnode;
 
-extern int early_is_amd_nb(u32 value);
+extern bool early_is_amd_nb(u32 value);
 extern int amd_cache_northbridges(void);
 extern void amd_flush_garts(void);
-extern int amd_numa_init(unsigned long start_pfn, unsigned long end_pfn);
-extern int amd_scan_nodes(void);
-
-#ifdef CONFIG_NUMA_EMU
-extern void amd_fake_nodes(const struct bootnode *nodes, int nr_nodes);
-extern void amd_get_nodes(struct bootnode *nodes);
-#endif
+extern int amd_numa_init(void);
+extern int amd_get_subcaches(int);
+extern int amd_set_subcaches(int, int);
 
 struct amd_northbridge {
 	struct pci_dev *misc;
+	struct pci_dev *link;
 };
 
 struct amd_northbridge_info {
@@ -35,17 +32,18 @@
 };
 extern struct amd_northbridge_info amd_northbridges;
 
-#define AMD_NB_GART			0x1
-#define AMD_NB_L3_INDEX_DISABLE		0x2
+#define AMD_NB_GART			BIT(0)
+#define AMD_NB_L3_INDEX_DISABLE		BIT(1)
+#define AMD_NB_L3_PARTITIONING		BIT(2)
 
 #ifdef CONFIG_AMD_NB
 
-static inline int amd_nb_num(void)
+static inline u16 amd_nb_num(void)
 {
 	return amd_northbridges.num;
 }
 
-static inline int amd_nb_has_feature(int feature)
+static inline bool amd_nb_has_feature(unsigned feature)
 {
 	return ((amd_northbridges.flags & feature) == feature);
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/apicdef.h linux-libre-2.6.39-gnu/arch/x86/include/asm/apicdef.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/apicdef.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/apicdef.h	2011-05-19 00:06:34.000000000 -0400
@@ -78,6 +78,7 @@
 #define		APIC_DEST_LOGICAL	0x00800
 #define		APIC_DEST_PHYSICAL	0x00000
 #define		APIC_DM_FIXED		0x00000
+#define		APIC_DM_FIXED_MASK	0x00700
 #define		APIC_DM_LOWEST		0x00100
 #define		APIC_DM_SMI		0x00200
 #define		APIC_DM_REMRD		0x00300
@@ -426,4 +427,16 @@
 #else
  #define BAD_APICID 0xFFFFu
 #endif
+
+enum ioapic_irq_destination_types {
+	dest_Fixed		= 0,
+	dest_LowestPrio		= 1,
+	dest_SMI		= 2,
+	dest__reserved_1	= 3,
+	dest_NMI		= 4,
+	dest_INIT		= 5,
+	dest__reserved_2	= 6,
+	dest_ExtINT		= 7
+};
+
 #endif /* _ASM_X86_APICDEF_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/apic.h linux-libre-2.6.39-gnu/arch/x86/include/asm/apic.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/apic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/apic.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,6 @@
 #define _ASM_X86_APIC_H
 
 #include <linux/cpumask.h>
-#include <linux/delay.h>
 #include <linux/pm.h>
 
 #include <asm/alternative.h>
@@ -220,7 +219,6 @@
 
 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);
@@ -228,7 +226,6 @@
 extern void disable_local_APIC(void);
 extern void lapic_shutdown(void);
 extern int verify_local_APIC(void);
-extern void cache_APIC_registers(void);
 extern void sync_Arb_IDs(void);
 extern void init_bsp_APIC(void);
 extern void setup_local_APIC(void);
@@ -239,8 +236,7 @@
 extern void setup_boot_APIC_clock(void);
 extern void setup_secondary_APIC_clock(void);
 extern int APIC_init_uniprocessor(void);
-extern void enable_NMI_through_LVT0(void);
-extern int apic_force_enable(void);
+extern int apic_force_enable(unsigned long addr);
 
 /*
  * On 32bit this is mach-xxx local
@@ -261,7 +257,6 @@
 #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) { }
 # define setup_boot_APIC_clock x86_init_noop
 # define setup_secondary_APIC_clock x86_init_noop
 #endif /* !CONFIG_X86_LOCAL_APIC */
@@ -307,8 +302,6 @@
 
 	void (*setup_apic_routing)(void);
 	int (*multi_timer_check)(int apic, int irq);
-	int (*apicid_to_node)(int logical_apicid);
-	int (*cpu_to_logical_apicid)(int cpu);
 	int (*cpu_present_to_apicid)(int mps_cpu);
 	void (*apicid_to_cpu_present)(int phys_apicid, physid_mask_t *retmap);
 	void (*setup_portio_remap)(void);
@@ -356,6 +349,23 @@
 	void (*icr_write)(u32 low, u32 high);
 	void (*wait_icr_idle)(void);
 	u32 (*safe_wait_icr_idle)(void);
+
+#ifdef CONFIG_X86_32
+	/*
+	 * Called very early during boot from get_smp_config().  It should
+	 * return the logical apicid.  x86_[bios]_cpu_to_apicid is
+	 * initialized before this function is called.
+	 *
+	 * If logical apicid can't be determined that early, the function
+	 * may return BAD_APICID.  Logical apicid will be configured after
+	 * init_apic_ldr() while bringing up CPUs.  Note that NUMA affinity
+	 * won't be applied properly during early boot in this case.
+	 */
+	int (*x86_32_early_logical_apicid)(int cpu);
+
+	/* determine CPU -> NUMA node mapping */
+	int (*x86_32_numa_cpu_node)(int cpu);
+#endif
 };
 
 /*
@@ -503,6 +513,11 @@
 
 extern struct apic apic_default;
 
+static inline int noop_x86_32_early_logical_apicid(int cpu)
+{
+	return BAD_APICID;
+}
+
 /*
  * Set up the logical destination ID.
  *
@@ -522,7 +537,7 @@
 	return cpuid_apic >> index_msb;
 }
 
-extern int default_apicid_to_node(int logical_apicid);
+extern int default_x86_32_numa_cpu_node(int cpu);
 
 #endif
 
@@ -558,12 +573,6 @@
 	*retmap = *phys_map;
 }
 
-/* Mapping from cpu number to logical apicid */
-static inline int default_cpu_to_logical_apicid(int cpu)
-{
-	return 1 << cpu;
-}
-
 static inline int __default_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids && cpu_present(mps_cpu))
@@ -596,8 +605,4 @@
 
 #endif /* CONFIG_X86_LOCAL_APIC */
 
-#ifdef CONFIG_X86_32
-extern u8 cpu_2_logical_apicid[NR_CPUS];
-#endif
-
 #endif /* _ASM_X86_APIC_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/x86/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -456,14 +456,12 @@
 
 #ifdef __KERNEL__
 
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #define ext2_set_bit_atomic(lock, nr, addr)			\
 	test_and_set_bit((nr), (unsigned long *)(addr))
 #define ext2_clear_bit_atomic(lock, nr, addr)			\
 	test_and_clear_bit((nr), (unsigned long *)(addr))
 
-#include <asm-generic/bitops/minix.h>
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_BITOPS_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/bootparam.h linux-libre-2.6.39-gnu/arch/x86/include/asm/bootparam.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/bootparam.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/bootparam.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 /* setup data types */
 #define SETUP_NONE			0
 #define SETUP_E820_EXT			1
+#define SETUP_DTB			2
 
 /* extensible setup data list node */
 struct setup_data {
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/cacheflush.h linux-libre-2.6.39-gnu/arch/x86/include/asm/cacheflush.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/cacheflush.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/cacheflush.h	2011-05-19 00:06:34.000000000 -0400
@@ -71,7 +71,7 @@
  * Read/Write    : ReadOnly, ReadWrite
  * Presence      : NotPresent
  *
- * Within a catagory, the attributes are mutually exclusive.
+ * Within a category, the attributes are mutually exclusive.
  *
  * The implementation of this API will take care of various aspects that
  * are associated with changing such attributes, such as:
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/cpufeature.h linux-libre-2.6.39-gnu/arch/x86/include/asm/cpufeature.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/cpufeature.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/cpufeature.h	2011-05-19 00:06:34.000000000 -0400
@@ -160,6 +160,7 @@
 #define X86_FEATURE_NODEID_MSR	(6*32+19) /* NodeId MSR */
 #define X86_FEATURE_TBM		(6*32+21) /* trailing bit manipulations */
 #define X86_FEATURE_TOPOEXT	(6*32+22) /* topology extensions CPUID leafs */
+#define X86_FEATURE_PERFCTR_CORE (6*32+23) /* core performance counter extensions */
 
 /*
  * Auxiliary flags: Linux defined - For features scattered in various
@@ -279,6 +280,7 @@
 #define cpu_has_xsave		boot_cpu_has(X86_FEATURE_XSAVE)
 #define cpu_has_hypervisor	boot_cpu_has(X86_FEATURE_HYPERVISOR)
 #define cpu_has_pclmulqdq	boot_cpu_has(X86_FEATURE_PCLMULQDQ)
+#define cpu_has_perfctr_core	boot_cpu_has(X86_FEATURE_PERFCTR_CORE)
 
 #if defined(CONFIG_X86_INVLPG) || defined(CONFIG_X86_64)
 # define cpu_has_invlpg		1
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/dma.h linux-libre-2.6.39-gnu/arch/x86/include/asm/dma.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,6 @@
 
 #include <linux/spinlock.h>	/* And spinlocks */
 #include <asm/io.h>		/* need byte IO */
-#include <linux/delay.h>
 
 #ifdef HAVE_REALLY_SLOW_DMA_CONTROLLER
 #define dma_outb	outb_p
@@ -151,6 +150,7 @@
 #define DMA_AUTOINIT		0x10
 
 
+#ifdef CONFIG_ISA_DMA_API
 extern spinlock_t  dma_spin_lock;
 
 static inline unsigned long claim_dma_lock(void)
@@ -164,6 +164,7 @@
 {
 	spin_unlock_irqrestore(&dma_spin_lock, flags);
 }
+#endif /* CONFIG_ISA_DMA_API */
 
 /* enable/disable a specific DMA channel */
 static inline void enable_dma(unsigned int dmanr)
@@ -303,9 +304,11 @@
 }
 
 
-/* These are in kernel/dma.c: */
+/* These are in kernel/dma.c because x86 uses CONFIG_GENERIC_ISA_DMA */
+#ifdef CONFIG_ISA_DMA_API
 extern int request_dma(unsigned int dmanr, const char *device_id);
 extern void free_dma(unsigned int dmanr);
+#endif
 
 /* From PCI */
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/e820.h linux-libre-2.6.39-gnu/arch/x86/include/asm/e820.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/e820.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/e820.h	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize,
 			unsigned long start_addr, unsigned long long end_addr);
 struct setup_data;
-extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data);
+extern void parse_e820_ext(struct setup_data *data);
 
 #if defined(CONFIG_X86_64) || \
 	(defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION))
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/entry_arch.h linux-libre-2.6.39-gnu/arch/x86/include/asm/entry_arch.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/entry_arch.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/entry_arch.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,10 +16,13 @@
 BUILD_INTERRUPT(irq_move_cleanup_interrupt,IRQ_MOVE_CLEANUP_VECTOR)
 BUILD_INTERRUPT(reboot_interrupt,REBOOT_VECTOR)
 
-.irpc idx, "01234567"
+.irp idx,0,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
+.if NUM_INVALIDATE_TLB_VECTORS > \idx
 BUILD_INTERRUPT3(invalidate_interrupt\idx,
 		 (INVALIDATE_TLB_VECTOR_START)+\idx,
 		 smp_invalidate_interrupt)
+.endif
 .endr
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/frame.h linux-libre-2.6.39-gnu/arch/x86/include/asm/frame.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/frame.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/frame.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,14 +7,12 @@
    frame pointer later */
 #ifdef CONFIG_FRAME_POINTER
 	.macro FRAME
-	pushl %ebp
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebp
 	CFI_REL_OFFSET ebp,0
 	movl %esp,%ebp
 	.endm
 	.macro ENDFRAME
-	popl %ebp
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebp
 	CFI_RESTORE ebp
 	.endm
 #else
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/futex.h linux-libre-2.6.39-gnu/arch/x86/include/asm/futex.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/futex.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/futex.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
 		       "+m" (*uaddr), "=&r" (tem)		\
 		     : "r" (oparg), "i" (-EFAULT), "1" (0))
 
-static inline int futex_atomic_op_inuser(int encoded_op, int __user *uaddr)
+static inline int futex_atomic_op_inuser(int encoded_op, u32 __user *uaddr)
 {
 	int op = (encoded_op >> 28) & 7;
 	int cmp = (encoded_op >> 24) & 15;
@@ -48,7 +48,7 @@
 	if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28))
 		oparg = 1 << oparg;
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
@@ -109,9 +109,10 @@
 	return ret;
 }
 
-static inline int futex_atomic_cmpxchg_inatomic(int __user *uaddr, int oldval,
-						int newval)
+static inline int futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
+						u32 oldval, u32 newval)
 {
+	int ret = 0;
 
 #if defined(CONFIG_X86_32) && !defined(CONFIG_X86_BSWAP)
 	/* Real i386 machines have no cmpxchg instruction */
@@ -119,21 +120,22 @@
 		return -ENOSYS;
 #endif
 
-	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(int)))
+	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
 
-	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %3, %1\n"
+	asm volatile("1:\t" LOCK_PREFIX "cmpxchgl %4, %2\n"
 		     "2:\t.section .fixup, \"ax\"\n"
-		     "3:\tmov     %2, %0\n"
+		     "3:\tmov     %3, %0\n"
 		     "\tjmp     2b\n"
 		     "\t.previous\n"
 		     _ASM_EXTABLE(1b, 3b)
-		     : "=a" (oldval), "+m" (*uaddr)
-		     : "i" (-EFAULT), "r" (newval), "0" (oldval)
+		     : "+r" (ret), "=a" (oldval), "+m" (*uaddr)
+		     : "i" (-EFAULT), "r" (newval), "1" (oldval)
 		     : "memory"
 	);
 
-	return oldval;
+	*uval = oldval;
+	return ret;
 }
 
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/gart.h linux-libre-2.6.39-gnu/arch/x86/include/asm/gart.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/gart.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/gart.h	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
 	 * Don't enable translation but enable GART IO and CPU accesses.
 	 * Also, set DISTLBWALKPRB since GART tables memory is UC.
 	 */
-	ctl = DISTLBWALKPRB | order << 1;
+	ctl = order << 1;
 
 	pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
@@ -75,17 +75,17 @@
 {
 	u32 tmp, ctl;
 
-        /* address of the mappings table */
-        addr >>= 12;
-        tmp = (u32) addr<<4;
-        tmp &= ~0xf;
-        pci_write_config_dword(dev, AMD64_GARTTABLEBASE, tmp);
+	/* address of the mappings table */
+	addr >>= 12;
+	tmp = (u32) addr<<4;
+	tmp &= ~0xf;
+	pci_write_config_dword(dev, AMD64_GARTTABLEBASE, tmp);
 
-        /* Enable GART translation for this hammer. */
-        pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
-        ctl |= GARTEN;
-        ctl &= ~(DISGARTCPU | DISGARTIO);
-        pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
+	/* Enable GART translation for this hammer. */
+	pci_read_config_dword(dev, AMD64_GARTAPERTURECTL, &ctl);
+	ctl |= GARTEN | DISTLBWALKPRB;
+	ctl &= ~(DISGARTCPU | DISGARTIO);
+	pci_write_config_dword(dev, AMD64_GARTAPERTURECTL, ctl);
 }
 
 static inline int aperture_valid(u64 aper_base, u32 aper_size, u32 min_size)
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/hw_irq.h linux-libre-2.6.39-gnu/arch/x86/include/asm/hw_irq.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/hw_irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/hw_irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,30 @@
 extern void invalidate_interrupt5(void);
 extern void invalidate_interrupt6(void);
 extern void invalidate_interrupt7(void);
+extern void invalidate_interrupt8(void);
+extern void invalidate_interrupt9(void);
+extern void invalidate_interrupt10(void);
+extern void invalidate_interrupt11(void);
+extern void invalidate_interrupt12(void);
+extern void invalidate_interrupt13(void);
+extern void invalidate_interrupt14(void);
+extern void invalidate_interrupt15(void);
+extern void invalidate_interrupt16(void);
+extern void invalidate_interrupt17(void);
+extern void invalidate_interrupt18(void);
+extern void invalidate_interrupt19(void);
+extern void invalidate_interrupt20(void);
+extern void invalidate_interrupt21(void);
+extern void invalidate_interrupt22(void);
+extern void invalidate_interrupt23(void);
+extern void invalidate_interrupt24(void);
+extern void invalidate_interrupt25(void);
+extern void invalidate_interrupt26(void);
+extern void invalidate_interrupt27(void);
+extern void invalidate_interrupt28(void);
+extern void invalidate_interrupt29(void);
+extern void invalidate_interrupt30(void);
+extern void invalidate_interrupt31(void);
 
 extern void irq_move_cleanup_interrupt(void);
 extern void reboot_interrupt(void);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/i387.h linux-libre-2.6.39-gnu/arch/x86/include/asm/i387.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/i387.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/i387.h	2011-05-19 00:06:34.000000000 -0400
@@ -237,7 +237,7 @@
 	} else if (use_fxsr()) {
 		fpu_fxsave(fpu);
 	} else {
-		asm volatile("fsave %[fx]; fwait"
+		asm volatile("fnsave %[fx]; fwait"
 			     : [fx] "=m" (fpu->state->fsave));
 		return;
 	}
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/init.h linux-libre-2.6.39-gnu/arch/x86/include/asm/init.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/init.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/init.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,8 +11,8 @@
 			     unsigned long page_size_mask);
 
 
-extern unsigned long __initdata e820_table_start;
-extern unsigned long __meminitdata e820_table_end;
-extern unsigned long __meminitdata e820_table_top;
+extern unsigned long __initdata pgt_buf_start;
+extern unsigned long __meminitdata pgt_buf_end;
+extern unsigned long __meminitdata pgt_buf_top;
 
 #endif /* _ASM_X86_INIT_32_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/io_apic.h linux-libre-2.6.39-gnu/arch/x86/include/asm/io_apic.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/io_apic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/io_apic.h	2011-05-19 00:06:34.000000000 -0400
@@ -63,17 +63,6 @@
 	} __attribute__ ((packed)) bits;
 };
 
-enum ioapic_irq_destination_types {
-	dest_Fixed = 0,
-	dest_LowestPrio = 1,
-	dest_SMI = 2,
-	dest__reserved_1 = 3,
-	dest_NMI = 4,
-	dest_INIT = 5,
-	dest__reserved_2 = 6,
-	dest_ExtINT = 7
-};
-
 struct IO_APIC_route_entry {
 	__u32	vector		:  8,
 		delivery_mode	:  3,	/* 000: FIXED
@@ -106,6 +95,10 @@
 		index		: 15;
 } __attribute__ ((packed));
 
+#define IOAPIC_AUTO     -1
+#define IOAPIC_EDGE     0
+#define IOAPIC_LEVEL    1
+
 #ifdef CONFIG_X86_IO_APIC
 
 /*
@@ -150,11 +143,6 @@
 #define io_apic_assign_pci_irqs \
 	(mp_irq_entries && !skip_ioapic_setup && io_apic_irqs)
 
-extern u8 io_apic_unique_id(u8 id);
-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);
-
 struct io_apic_irq_attr;
 extern int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr);
@@ -162,6 +150,8 @@
 extern void ioapic_and_gsi_init(void);
 extern void ioapic_insert_resources(void);
 
+int io_apic_setup_irq_pin_once(unsigned int irq, int node, struct io_apic_irq_attr *attr);
+
 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);
@@ -186,6 +176,8 @@
 
 extern void mp_save_irq(struct mpc_intsrc *m);
 
+extern void disable_ioapic_support(void);
+
 #else  /* !CONFIG_X86_IO_APIC */
 
 #define io_apic_assign_pci_irqs 0
@@ -199,6 +191,26 @@
 struct io_apic_irq_attr;
 static inline int io_apic_set_pci_routing(struct device *dev, int irq,
 		 struct io_apic_irq_attr *irq_attr) { return 0; }
+
+static inline struct IO_APIC_route_entry **alloc_ioapic_entries(void)
+{
+	return NULL;
+}
+
+static inline void free_ioapic_entries(struct IO_APIC_route_entry **ent) { }
+static inline int save_IO_APIC_setup(struct IO_APIC_route_entry **ent)
+{
+	return -ENOMEM;
+}
+
+static inline void mask_IO_APIC_setup(struct IO_APIC_route_entry **ent) { }
+static inline int restore_IO_APIC_setup(struct IO_APIC_route_entry **ent)
+{
+	return -ENOMEM;
+}
+
+static inline void mp_save_irq(struct mpc_intsrc *m) { };
+static inline void disable_ioapic_support(void) { }
 #endif
 
 #endif /* _ASM_X86_IO_APIC_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/ipi.h linux-libre-2.6.39-gnu/arch/x86/include/asm/ipi.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/ipi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/ipi.h	2011-05-19 00:06:34.000000000 -0400
@@ -123,10 +123,6 @@
 						 int vector);
 extern void default_send_IPI_mask_allbutself_phys(const struct cpumask *mask,
 							 int vector);
-extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
-							 int vector);
-extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
-							 int vector);
 
 /* Avoid include hell */
 #define NMI_VECTOR 0x02
@@ -150,6 +146,10 @@
 }
 
 #ifdef CONFIG_X86_32
+extern void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
+							 int vector);
+extern void default_send_IPI_mask_allbutself_logical(const struct cpumask *mask,
+							 int vector);
 extern void default_send_IPI_mask_logical(const struct cpumask *mask,
 						 int vector);
 extern void default_send_IPI_allbutself(int vector);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/irq_controller.h linux-libre-2.6.39-gnu/arch/x86/include/asm/irq_controller.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/irq_controller.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/irq_controller.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,12 @@
+#ifndef __IRQ_CONTROLLER__
+#define __IRQ_CONTROLLER__
+
+struct irq_domain {
+	int (*xlate)(struct irq_domain *h, const u32 *intspec, u32 intsize,
+			u32 *out_hwirq, u32 *out_type);
+	void *priv;
+	struct device_node *controller;
+	struct list_head l;
+};
+
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/irq.h linux-libre-2.6.39-gnu/arch/x86/include/asm/irq.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/irq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/irq.h	2011-05-19 00:06:34.000000000 -0400
@@ -10,9 +10,6 @@
 #include <asm/apicdef.h>
 #include <asm/irq_vectors.h>
 
-/* Even though we don't support this, supply it to appease OF */
-static inline void irq_dispose_mapping(unsigned int virq) { }
-
 static inline int irq_canonicalize(int irq)
 {
 	return ((irq == 2) ? 9 : irq);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/irq_vectors.h linux-libre-2.6.39-gnu/arch/x86/include/asm/irq_vectors.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/irq_vectors.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/irq_vectors.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,7 @@
 #ifndef _ASM_X86_IRQ_VECTORS_H
 #define _ASM_X86_IRQ_VECTORS_H
 
+#include <linux/threads.h>
 /*
  * Linux IRQ vector layout.
  *
@@ -16,8 +17,8 @@
  *  Vectors   0 ...  31 : system traps and exceptions - hardcoded events
  *  Vectors  32 ... 127 : device interrupts
  *  Vector  128         : legacy int80 syscall interface
- *  Vectors 129 ... 237 : device interrupts
- *  Vectors 238 ... 255 : special interrupts
+ *  Vectors 129 ... INVALIDATE_TLB_VECTOR_START-1 : device interrupts
+ *  Vectors INVALIDATE_TLB_VECTOR_START ... 255 : special interrupts
  *
  * 64-bit x86 has per CPU IDT tables, 32-bit has one shared IDT table.
  *
@@ -96,37 +97,43 @@
 #define THRESHOLD_APIC_VECTOR		0xf9
 #define REBOOT_VECTOR			0xf8
 
-/* f0-f7 used for spreading out TLB flushes: */
-#define INVALIDATE_TLB_VECTOR_END	0xf7
-#define INVALIDATE_TLB_VECTOR_START	0xf0
-#define NUM_INVALIDATE_TLB_VECTORS	   8
-
-/*
- * Local APIC timer IRQ vector is on a different priority level,
- * to work around the 'lost local interrupt if more than 2 IRQ
- * sources per level' errata.
- */
-#define LOCAL_TIMER_VECTOR		0xef
-
 /*
  * Generic system vector for platform specific use
  */
-#define X86_PLATFORM_IPI_VECTOR		0xed
+#define X86_PLATFORM_IPI_VECTOR		0xf7
 
 /*
  * IRQ work vector:
  */
-#define IRQ_WORK_VECTOR			0xec
+#define IRQ_WORK_VECTOR			0xf6
 
-#define UV_BAU_MESSAGE			0xea
+#define UV_BAU_MESSAGE			0xf5
 
 /*
  * Self IPI vector for machine checks
  */
-#define MCE_SELF_VECTOR			0xeb
+#define MCE_SELF_VECTOR			0xf4
 
 /* Xen vector callback to receive events in a HVM domain */
-#define XEN_HVM_EVTCHN_CALLBACK		0xe9
+#define XEN_HVM_EVTCHN_CALLBACK		0xf3
+
+/*
+ * Local APIC timer IRQ vector is on a different priority level,
+ * to work around the 'lost local interrupt if more than 2 IRQ
+ * sources per level' errata.
+ */
+#define LOCAL_TIMER_VECTOR		0xef
+
+/* up to 32 vectors used for spreading out TLB flushes: */
+#if NR_CPUS <= 32
+# define NUM_INVALIDATE_TLB_VECTORS	(NR_CPUS)
+#else
+# define NUM_INVALIDATE_TLB_VECTORS	(32)
+#endif
+
+#define INVALIDATE_TLB_VECTOR_END	(0xee)
+#define INVALIDATE_TLB_VECTOR_START	\
+	(INVALIDATE_TLB_VECTOR_END-NUM_INVALIDATE_TLB_VECTORS+1)
 
 #define NR_VECTORS			 256
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/kdebug.h linux-libre-2.6.39-gnu/arch/x86/include/asm/kdebug.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/kdebug.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/kdebug.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,6 @@
 	DIE_PANIC,
 	DIE_NMI,
 	DIE_DIE,
-	DIE_NMIWATCHDOG,
 	DIE_KERNELDEBUG,
 	DIE_TRAP,
 	DIE_GPF,
@@ -27,7 +26,7 @@
 extern int __must_check __die(const char *, struct pt_regs *, long);
 extern void show_registers(struct pt_regs *regs);
 extern void show_trace(struct task_struct *t, struct pt_regs *regs,
-		       unsigned long *sp);
+		       unsigned long *sp, unsigned long bp);
 extern void __show_regs(struct pt_regs *regs, int all);
 extern void show_regs(struct pt_regs *regs);
 extern unsigned long oops_begin(void);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/kvm_emulate.h linux-libre-2.6.39-gnu/arch/x86/include/asm/kvm_emulate.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/kvm_emulate.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/kvm_emulate.h	2011-05-19 00:06:34.000000000 -0400
@@ -142,9 +142,9 @@
 	int (*pio_out_emulated)(int size, unsigned short port, const void *val,
 				unsigned int count, struct kvm_vcpu *vcpu);
 
-	bool (*get_cached_descriptor)(struct desc_struct *desc,
+	bool (*get_cached_descriptor)(struct desc_struct *desc, u32 *base3,
 				      int seg, struct kvm_vcpu *vcpu);
-	void (*set_cached_descriptor)(struct desc_struct *desc,
+	void (*set_cached_descriptor)(struct desc_struct *desc, u32 base3,
 				      int seg, struct kvm_vcpu *vcpu);
 	u16 (*get_segment_selector)(int seg, struct kvm_vcpu *vcpu);
 	void (*set_segment_selector)(u16 sel, int seg, struct kvm_vcpu *vcpu);
@@ -239,6 +239,7 @@
 	int interruptibility;
 
 	bool perm_ok; /* do not check permissions if true */
+	bool only_vendor_specific_insn;
 
 	bool have_exception;
 	struct x86_exception exception;
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/kvm_host.h linux-libre-2.6.39-gnu/arch/x86/include/asm/kvm_host.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/kvm_host.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/kvm_host.h	2011-05-19 00:06:34.000000000 -0400
@@ -85,7 +85,7 @@
 
 #define ASYNC_PF_PER_VCPU 64
 
-extern spinlock_t kvm_lock;
+extern raw_spinlock_t kvm_lock;
 extern struct list_head vm_list;
 
 struct kvm_vcpu;
@@ -255,6 +255,8 @@
 	int (*sync_page)(struct kvm_vcpu *vcpu,
 			 struct kvm_mmu_page *sp);
 	void (*invlpg)(struct kvm_vcpu *vcpu, gva_t gva);
+	void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
+			u64 *spte, const void *pte, unsigned long mmu_seq);
 	hpa_t root_hpa;
 	int root_level;
 	int shadow_root_level;
@@ -335,12 +337,6 @@
 	u64  *last_pte_updated;
 	gfn_t last_pte_gfn;
 
-	struct {
-		gfn_t gfn;	/* presumed gfn during guest pte update */
-		pfn_t pfn;	/* pfn corresponding to that gfn */
-		unsigned long mmu_seq;
-	} update_pte;
-
 	struct fpu guest_fpu;
 	u64 xcr0;
 
@@ -448,7 +444,7 @@
 
 	unsigned long irq_sources_bitmap;
 	s64 kvmclock_offset;
-	spinlock_t tsc_write_lock;
+	raw_spinlock_t tsc_write_lock;
 	u64 last_tsc_nsec;
 	u64 last_tsc_offset;
 	u64 last_tsc_write;
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/mmu.h linux-libre-2.6.39-gnu/arch/x86/include/asm/mmu.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/mmu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/mmu.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,12 @@
 	int size;
 	struct mutex lock;
 	void *vdso;
+
+#ifdef CONFIG_X86_64
+	/* True if mm supports a task running in 32 bit compatibility mode. */
+	unsigned short ia32_compat;
+#endif
+
 } mm_context_t;
 
 #ifdef CONFIG_SMP
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/mpspec.h linux-libre-2.6.39-gnu/arch/x86/include/asm/mpspec.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/mpspec.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/mpspec.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,7 +25,6 @@
 #define MAX_IRQ_SOURCES		256
 
 extern unsigned int def_to_bigsmp;
-extern u8 apicid_2_node[];
 
 #ifdef CONFIG_X86_NUMAQ
 extern int mp_bus_id_to_node[MAX_MP_BUSSES];
@@ -33,8 +32,6 @@
 extern int quad_local_to_mp_bus_id [NR_CPUS/4][4];
 #endif
 
-#define MAX_APICID		256
-
 #else /* CONFIG_X86_64: */
 
 #define MAX_MP_BUSSES		256
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/msr-index.h linux-libre-2.6.39-gnu/arch/x86/include/asm/msr-index.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/msr-index.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/msr-index.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,7 @@
 
 #define MSR_MTRRcap			0x000000fe
 #define MSR_IA32_BBL_CR_CTL		0x00000119
+#define MSR_IA32_BBL_CR_CTL3		0x0000011e
 
 #define MSR_IA32_SYSENTER_CS		0x00000174
 #define MSR_IA32_SYSENTER_ESP		0x00000175
@@ -52,6 +53,9 @@
 #define MSR_IA32_MCG_STATUS		0x0000017a
 #define MSR_IA32_MCG_CTL		0x0000017b
 
+#define MSR_OFFCORE_RSP_0		0x000001a6
+#define MSR_OFFCORE_RSP_1		0x000001a7
+
 #define MSR_IA32_PEBS_ENABLE		0x000003f1
 #define MSR_IA32_DS_AREA		0x00000600
 #define MSR_IA32_PERF_CAPABILITIES	0x00000345
@@ -92,11 +96,15 @@
 #define MSR_IA32_MC0_ADDR		0x00000402
 #define MSR_IA32_MC0_MISC		0x00000403
 
+#define MSR_AMD64_MC0_MASK		0xc0010044
+
 #define MSR_IA32_MCx_CTL(x)		(MSR_IA32_MC0_CTL + 4*(x))
 #define MSR_IA32_MCx_STATUS(x)		(MSR_IA32_MC0_STATUS + 4*(x))
 #define MSR_IA32_MCx_ADDR(x)		(MSR_IA32_MC0_ADDR + 4*(x))
 #define MSR_IA32_MCx_MISC(x)		(MSR_IA32_MC0_MISC + 4*(x))
 
+#define MSR_AMD64_MCx_MASK(x)		(MSR_AMD64_MC0_MASK + (x))
+
 /* These are consecutive and not in the normal 4er MCE bank block */
 #define MSR_IA32_MC0_CTL2		0x00000280
 #define MSR_IA32_MCx_CTL2(x)		(MSR_IA32_MC0_CTL2 + (x))
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/nmi.h linux-libre-2.6.39-gnu/arch/x86/include/asm/nmi.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/nmi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/nmi.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,6 @@
 
 #ifdef CONFIG_X86_LOCAL_APIC
 
-extern void die_nmi(char *str, struct pt_regs *regs, int do_panic);
 extern int avail_to_resrv_perfctr_nmi_bit(unsigned int);
 extern int reserve_perfctr_nmi(unsigned int);
 extern void release_perfctr_nmi(unsigned int);
@@ -30,8 +29,8 @@
  * external nmis, because the local ones are more frequent.
  *
  * Also setup some default high/normal/low settings for
- * subsystems to registers with.  Using 4 bits to seperate
- * the priorities.  This can go alot higher if needed be.
+ * subsystems to registers with.  Using 4 bits to separate
+ * the priorities.  This can go a lot higher if needed be.
  */
 
 #define NMI_LOCAL_SHIFT		16	/* randomly picked */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/nops.h linux-libre-2.6.39-gnu/arch/x86/include/asm/nops.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/nops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/nops.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 #define K8_NOP8	K8_NOP4 K8_NOP4
 
 /* K7 nops
-   uses eax dependencies (arbitary choice)
+   uses eax dependencies (arbitrary choice)
    1: nop
    2: movl %eax,%eax
    3: leal (,%eax,1),%eax
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/numa_32.h linux-libre-2.6.39-gnu/arch/x86/include/asm/numa_32.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/numa_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/numa_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,12 @@
 extern int numa_off;
 
 extern int pxm_to_nid(int pxm);
-extern void numa_remove_cpu(int cpu);
+
+#ifdef CONFIG_NUMA
+extern int __cpuinit numa_cpu_node(int cpu);
+#else	/* CONFIG_NUMA */
+static inline int numa_cpu_node(int cpu)		{ return NUMA_NO_NODE; }
+#endif	/* CONFIG_NUMA */
 
 #ifdef CONFIG_HIGHMEM
 extern void set_highmem_pages_init(void);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/numa_64.h linux-libre-2.6.39-gnu/arch/x86/include/asm/numa_64.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/numa_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/numa_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,23 +2,16 @@
 #define _ASM_X86_NUMA_64_H
 
 #include <linux/nodemask.h>
-#include <asm/apicdef.h>
 
 struct bootnode {
 	u64 start;
 	u64 end;
 };
 
-extern int compute_hash_shift(struct bootnode *nodes, int numblks,
-			      int *nodeids);
-
 #define ZONE_ALIGN (1UL << (MAX_ORDER+PAGE_SHIFT))
 
-extern void numa_init_array(void);
 extern int numa_off;
 
-extern s16 apicid_to_node[MAX_LOCAL_APIC];
-
 extern unsigned long numa_free_all_bootmem(void);
 extern void setup_node_bootmem(int nodeid, unsigned long start,
 			       unsigned long end);
@@ -31,11 +24,11 @@
  */
 #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);
-extern void __cpuinit numa_add_cpu(int cpu);
-extern void __cpuinit numa_remove_cpu(int cpu);
+extern nodemask_t numa_nodes_parsed __initdata;
+
+extern int __cpuinit numa_cpu_node(int cpu);
+extern int __init numa_add_memblk(int nodeid, u64 start, u64 end);
+extern void __init numa_set_distance(int from, int to, int distance);
 
 #ifdef CONFIG_NUMA_EMU
 #define FAKE_NODE_MIN_SIZE	((u64)32 << 20)
@@ -43,11 +36,7 @@
 void numa_emu_cmdline(char *);
 #endif /* CONFIG_NUMA_EMU */
 #else
-static inline void init_cpu_to_node(void)		{ }
-static inline void numa_set_node(int cpu, int node)	{ }
-static inline void numa_clear_node(int cpu)		{ }
-static inline void numa_add_cpu(int cpu, int node)	{ }
-static inline void numa_remove_cpu(int cpu)		{ }
+static inline int numa_cpu_node(int cpu)		{ return NUMA_NO_NODE; }
 #endif
 
 #endif /* _ASM_X86_NUMA_64_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/numa.h linux-libre-2.6.39-gnu/arch/x86/include/asm/numa.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/numa.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/numa.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,57 @@
+#ifndef _ASM_X86_NUMA_H
+#define _ASM_X86_NUMA_H
+
+#include <asm/topology.h>
+#include <asm/apicdef.h>
+
+#ifdef CONFIG_NUMA
+
+#define NR_NODE_MEMBLKS		(MAX_NUMNODES*2)
+
+/*
+ * __apicid_to_node[] stores the raw mapping between physical apicid and
+ * node and is used to initialize cpu_to_node mapping.
+ *
+ * The mapping may be overridden by apic->numa_cpu_node() on 32bit and thus
+ * should be accessed by the accessors - set_apicid_to_node() and
+ * numa_cpu_node().
+ */
+extern s16 __apicid_to_node[MAX_LOCAL_APIC];
+
+static inline void set_apicid_to_node(int apicid, s16 node)
+{
+	__apicid_to_node[apicid] = node;
+}
+#else	/* CONFIG_NUMA */
+static inline void set_apicid_to_node(int apicid, s16 node)
+{
+}
+#endif	/* CONFIG_NUMA */
+
 #ifdef CONFIG_X86_32
 # include "numa_32.h"
 #else
 # include "numa_64.h"
 #endif
+
+#ifdef CONFIG_NUMA
+extern void __cpuinit numa_set_node(int cpu, int node);
+extern void __cpuinit numa_clear_node(int cpu);
+extern void __init numa_init_array(void);
+extern void __init init_cpu_to_node(void);
+extern void __cpuinit numa_add_cpu(int cpu);
+extern void __cpuinit numa_remove_cpu(int cpu);
+#else	/* CONFIG_NUMA */
+static inline void numa_set_node(int cpu, int node)	{ }
+static inline void numa_clear_node(int cpu)		{ }
+static inline void numa_init_array(void)		{ }
+static inline void init_cpu_to_node(void)		{ }
+static inline void numa_add_cpu(int cpu)		{ }
+static inline void numa_remove_cpu(int cpu)		{ }
+#endif	/* CONFIG_NUMA */
+
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+void debug_cpumask_set_cpu(int cpu, int node, bool enable);
+#endif
+
+#endif	/* _ASM_X86_NUMA_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/olpc.h linux-libre-2.6.39-gnu/arch/x86/include/asm/olpc.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/olpc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/olpc.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
 
 /*
  * OLPC board IDs contain the major build number within the mask 0x0ff0,
- * and the minor build number withing 0x000f.  Pre-builds have a minor
+ * and the minor build number within 0x000f.  Pre-builds have a minor
  * number less than 8, and normal builds start at 8.  For example, 0x0B10
  * is a PreB1, and 0x0C18 is a C1.
  */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/olpc_ofw.h linux-libre-2.6.39-gnu/arch/x86/include/asm/olpc_ofw.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/olpc_ofw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/olpc_ofw.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 
 #define OLPC_OFW_SIG 0x2057464F	/* aka "OFW " */
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE
+#ifdef CONFIG_OLPC
 
 extern bool olpc_ofw_is_installed(void);
 
@@ -26,19 +26,15 @@
 /* check if OFW was detected during boot */
 extern bool olpc_ofw_present(void);
 
-#else /* !CONFIG_OLPC_OPENFIRMWARE */
-
-static inline bool olpc_ofw_is_installed(void) { return false; }
+#else /* !CONFIG_OLPC */
 static inline void olpc_ofw_detect(void) { }
 static inline void setup_olpc_ofw_pgd(void) { }
-static inline bool olpc_ofw_present(void) { return false; }
-
-#endif /* !CONFIG_OLPC_OPENFIRMWARE */
+#endif /* !CONFIG_OLPC */
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE_DT
+#ifdef CONFIG_OF_PROMTREE
 extern void olpc_dt_build_devicetree(void);
 #else
 static inline void olpc_dt_build_devicetree(void) { }
-#endif /* CONFIG_OLPC_OPENFIRMWARE_DT */
+#endif
 
 #endif /* _ASM_X86_OLPC_OFW_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/page_types.h linux-libre-2.6.39-gnu/arch/x86/include/asm/page_types.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/page_types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/page_types.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,7 @@
 #define _ASM_X86_PAGE_DEFS_H
 
 #include <linux/const.h>
+#include <linux/types.h>
 
 /* PAGE_SHIFT determines the page size */
 #define PAGE_SHIFT	12
@@ -45,11 +46,15 @@
 extern unsigned long max_low_pfn_mapped;
 extern unsigned long max_pfn_mapped;
 
+static inline phys_addr_t get_max_mapped(void)
+{
+	return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT;
+}
+
 extern unsigned long init_memory_mapping(unsigned long start,
 					 unsigned long end);
 
-extern void initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8);
+extern void initmem_init(void);
 extern void free_initmem(void);
 
 #endif	/* !__ASSEMBLY__ */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/percpu.h linux-libre-2.6.39-gnu/arch/x86/include/asm/percpu.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/percpu.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/percpu.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 #include <linux/stringify.h>
 
 #ifdef CONFIG_SMP
-#define __percpu_arg(x)		"%%"__stringify(__percpu_seg)":%P" #x
+#define __percpu_prefix		"%%"__stringify(__percpu_seg)":"
 #define __my_cpu_offset		percpu_read(this_cpu_off)
 
 /*
@@ -62,9 +62,11 @@
 	(typeof(*(ptr)) __kernel __force *)tcp_ptr__;	\
 })
 #else
-#define __percpu_arg(x)		"%P" #x
+#define __percpu_prefix		""
 #endif
 
+#define __percpu_arg(x)		__percpu_prefix "%P" #x
+
 /*
  * Initialized pointers to per-cpu variables needed for the boot
  * processor need to use these macros to get the proper address
@@ -451,6 +453,26 @@
 #define irqsafe_cpu_cmpxchg_4(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
 #endif /* !CONFIG_M386 */
 
+#ifdef CONFIG_X86_CMPXCHG64
+#define percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)			\
+({									\
+	char __ret;							\
+	typeof(o1) __o1 = o1;						\
+	typeof(o1) __n1 = n1;						\
+	typeof(o2) __o2 = o2;						\
+	typeof(o2) __n2 = n2;						\
+	typeof(o2) __dummy = n2;					\
+	asm volatile("cmpxchg8b "__percpu_arg(1)"\n\tsetz %0\n\t"	\
+		    : "=a"(__ret), "=m" (pcp1), "=d"(__dummy)		\
+		    :  "b"(__n1), "c"(__n2), "a"(__o1), "d"(__o2));	\
+	__ret;								\
+})
+
+#define __this_cpu_cmpxchg_double_4(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)
+#define this_cpu_cmpxchg_double_4(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)
+#define irqsafe_cpu_cmpxchg_double_4(pcp1, pcp2, o1, o2, n1, n2)	percpu_cmpxchg8b_double(pcp1, o1, o2, n1, n2)
+#endif /* CONFIG_X86_CMPXCHG64 */
+
 /*
  * Per cpu atomic 64 bit operations are only available under 64 bit.
  * 32 bit must fall back to generic operations.
@@ -480,6 +502,34 @@
 #define irqsafe_cpu_xor_8(pcp, val)	percpu_to_op("xor", (pcp), val)
 #define irqsafe_cpu_xchg_8(pcp, nval)	percpu_xchg_op(pcp, nval)
 #define irqsafe_cpu_cmpxchg_8(pcp, oval, nval)	percpu_cmpxchg_op(pcp, oval, nval)
+
+/*
+ * Pretty complex macro to generate cmpxchg16 instruction.  The instruction
+ * is not supported on early AMD64 processors so we must be able to emulate
+ * it in software.  The address used in the cmpxchg16 instruction must be
+ * aligned to a 16 byte boundary.
+ */
+#define percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)			\
+({									\
+	char __ret;							\
+	typeof(o1) __o1 = o1;						\
+	typeof(o1) __n1 = n1;						\
+	typeof(o2) __o2 = o2;						\
+	typeof(o2) __n2 = n2;						\
+	typeof(o2) __dummy;						\
+	alternative_io("call this_cpu_cmpxchg16b_emu\n\t" P6_NOP4,	\
+		       "cmpxchg16b " __percpu_prefix "(%%rsi)\n\tsetz %0\n\t",	\
+		       X86_FEATURE_CX16,				\
+		       ASM_OUTPUT2("=a"(__ret), "=d"(__dummy)),		\
+		       "S" (&pcp1), "b"(__n1), "c"(__n2),		\
+		       "a"(__o1), "d"(__o2) : "memory");		\
+	__ret;								\
+})
+
+#define __this_cpu_cmpxchg_double_8(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)
+#define this_cpu_cmpxchg_double_8(pcp1, pcp2, o1, o2, n1, n2)		percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)
+#define irqsafe_cpu_cmpxchg_double_8(pcp1, pcp2, o1, o2, n1, n2)	percpu_cmpxchg16b_double(pcp1, o1, o2, n1, n2)
+
 #endif
 
 /* This is not atomic against other CPUs -- CPU preemption needs to be off */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/perf_event_p4.h linux-libre-2.6.39-gnu/arch/x86/include/asm/perf_event_p4.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/perf_event_p4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/perf_event_p4.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Netburst Perfomance Events (P4, old Xeon)
+ * Netburst Performance Events (P4, old Xeon)
  */
 
 #ifndef PERF_EVENT_P4_H
@@ -9,7 +9,7 @@
 #include <linux/bitops.h>
 
 /*
- * NetBurst has perfomance MSRs shared between
+ * NetBurst has performance MSRs shared between
  * threads if HT is turned on, ie for both logical
  * processors (mem: in turn in Atom with HT support
  * perf-MSRs are not shared and every thread has its
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/pgtable-3level.h linux-libre-2.6.39-gnu/arch/x86/include/asm/pgtable-3level.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/pgtable-3level.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/pgtable-3level.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,8 +69,6 @@
 
 static inline void pud_clear(pud_t *pudp)
 {
-	unsigned long pgd;
-
 	set_pud(pudp, __pud(0));
 
 	/*
@@ -79,13 +77,10 @@
 	 * section 8.1: in PAE mode we explicitly have to flush the
 	 * TLB via cr3 if the top-level pgd is changed...
 	 *
-	 * Make sure the pud entry we're updating is within the
-	 * current pgd to avoid unnecessary TLB flushes.
+	 * Currently all places where pud_clear() is called either have
+	 * flush_tlb_mm() followed or don't need TLB flush (x86_64 code or
+	 * pud_clear_bad()), so we don't need TLB flush here.
 	 */
-	pgd = read_cr3();
-	if (__pa(pudp) >= pgd && __pa(pudp) <
-	    (pgd + sizeof(pgd_t)*PTRS_PER_PGD))
-		write_cr3(pgd);
 }
 
 #ifdef CONFIG_SMP
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/pgtable_types.h linux-libre-2.6.39-gnu/arch/x86/include/asm/pgtable_types.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/pgtable_types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/pgtable_types.h	2011-05-19 00:06:34.000000000 -0400
@@ -299,6 +299,7 @@
 /* Install a pte for a particular vaddr in kernel space. */
 void set_pte_vaddr(unsigned long vaddr, pte_t pte);
 
+extern void native_pagetable_reserve(u64 start, u64 end);
 #ifdef CONFIG_X86_32
 extern void native_pagetable_setup_start(pgd_t *base);
 extern void native_pagetable_setup_done(pgd_t *base);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/processor-flags.h linux-libre-2.6.39-gnu/arch/x86/include/asm/processor-flags.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/processor-flags.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/processor-flags.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
  */
 #define X86_EFLAGS_CF	0x00000001 /* Carry Flag */
 #define X86_EFLAGS_PF	0x00000004 /* Parity Flag */
-#define X86_EFLAGS_AF	0x00000010 /* Auxillary carry Flag */
+#define X86_EFLAGS_AF	0x00000010 /* Auxiliary carry Flag */
 #define X86_EFLAGS_ZF	0x00000040 /* Zero Flag */
 #define X86_EFLAGS_SF	0x00000080 /* Sign Flag */
 #define X86_EFLAGS_TF	0x00000100 /* Trap Flag */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/processor.h linux-libre-2.6.39-gnu/arch/x86/include/asm/processor.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/processor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/processor.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,10 +94,6 @@
 	int			x86_cache_alignment;	/* In bytes */
 	int			x86_power;
 	unsigned long		loops_per_jiffy;
-#ifdef CONFIG_SMP
-	/* cpus sharing the last level cache: */
-	cpumask_var_t		llc_shared_map;
-#endif
 	/* cpuid returned max cores value: */
 	u16			 x86_max_cores;
 	u16			apicid;
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/prom.h linux-libre-2.6.39-gnu/arch/x86/include/asm/prom.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/prom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/prom.h	2011-05-19 00:06:34.000000000 -0400
@@ -1 +1,69 @@
-/* dummy prom.h; here to make linux/of.h's #includes happy */
+/*
+ * Definitions for Device tree / OpenFirmware handling on X86
+ *
+ * based on arch/powerpc/include/asm/prom.h which is
+ *         Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the 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_X86_PROM_H
+#define _ASM_X86_PROM_H
+#ifndef __ASSEMBLY__
+
+#include <linux/of.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+
+#include <asm/irq.h>
+#include <asm/atomic.h>
+#include <asm/setup.h>
+#include <asm/irq_controller.h>
+
+#ifdef CONFIG_OF
+extern int of_ioapic;
+extern u64 initial_dtb;
+extern void add_dtb(u64 data);
+extern void x86_add_irq_domains(void);
+void __cpuinit x86_of_pci_init(void);
+void x86_dtb_init(void);
+
+static inline struct device_node *pci_device_to_OF_node(struct pci_dev *pdev)
+{
+	return pdev ? pdev->dev.of_node : NULL;
+}
+
+static inline struct device_node *pci_bus_to_OF_node(struct pci_bus *bus)
+{
+	return pci_device_to_OF_node(bus->self);
+}
+
+#else
+static inline void add_dtb(u64 data) { }
+static inline void x86_add_irq_domains(void) { }
+static inline void x86_of_pci_init(void) { }
+static inline void x86_dtb_init(void) { }
+#define of_ioapic 0
+#endif
+
+extern char cmd_line[COMMAND_LINE_SIZE];
+
+#define pci_address_to_pio pci_address_to_pio
+unsigned long pci_address_to_pio(phys_addr_t addr);
+
+/**
+ * irq_dispose_mapping - Unmap an interrupt
+ * @virq: linux virq number of the interrupt to unmap
+ *
+ * FIXME: We really should implement proper virq handling like power,
+ * but that's going to be major surgery.
+ */
+static inline void irq_dispose_mapping(unsigned int virq) { }
+
+#define HAVE_ARCH_DEVTREE_FIXUPS
+
+#endif /* __ASSEMBLY__ */
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/ptrace-abi.h linux-libre-2.6.39-gnu/arch/x86/include/asm/ptrace-abi.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/ptrace-abi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/ptrace-abi.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #define R12 24
 #define RBP 32
 #define RBX 40
-/* arguments: interrupts/non tracing syscalls only save upto here*/
+/* arguments: interrupts/non tracing syscalls only save up to here*/
 #define R11 48
 #define R10 56
 #define R9 64
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/ptrace.h linux-libre-2.6.39-gnu/arch/x86/include/asm/ptrace.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/ptrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/ptrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
 	unsigned long r12;
 	unsigned long rbp;
 	unsigned long rbx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
+/* arguments: non interrupts/non tracing syscalls only save up to here*/
 	unsigned long r11;
 	unsigned long r10;
 	unsigned long r9;
@@ -103,7 +103,7 @@
 	unsigned long r12;
 	unsigned long bp;
 	unsigned long bx;
-/* arguments: non interrupts/non tracing syscalls only save upto here*/
+/* arguments: non interrupts/non tracing syscalls only save up to here*/
 	unsigned long r11;
 	unsigned long r10;
 	unsigned long r9;
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/reboot.h linux-libre-2.6.39-gnu/arch/x86/include/asm/reboot.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/reboot.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/reboot.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,10 @@
 
 void native_machine_crash_shutdown(struct pt_regs *regs);
 void native_machine_shutdown(void);
-void machine_real_restart(const unsigned char *code, int length);
+void machine_real_restart(unsigned int type);
+/* These must match dispatch_table in reboot_32.S */
+#define MRR_BIOS	0
+#define MRR_APM		1
 
 typedef void (*nmi_shootdown_cb)(int, struct die_args*);
 void nmi_shootdown_cpus(nmi_shootdown_cb callback);
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/x86/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,26 +37,9 @@
 #endif
 
 #ifdef __KERNEL__
-
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/lockdep.h>
 #include <asm/asm.h>
 
-struct rwsem_waiter;
-
-extern asmregparm struct rw_semaphore *
- rwsem_down_read_failed(struct rw_semaphore *sem);
-extern asmregparm struct rw_semaphore *
- rwsem_down_write_failed(struct rw_semaphore *sem);
-extern asmregparm struct rw_semaphore *
- rwsem_wake(struct rw_semaphore *);
-extern asmregparm struct rw_semaphore *
- rwsem_downgrade_wake(struct rw_semaphore *sem);
-
 /*
- * the semaphore definition
- *
  * The bias values and the counter type limits the number of
  * potential readers/writers to 32767 for 32 bits and 2147483647
  * for 64 bits.
@@ -74,43 +57,6 @@
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
 
-typedef signed long rwsem_count_t;
-
-struct rw_semaphore {
-	rwsem_count_t		count;
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-	struct lockdep_map dep_map;
-#endif
-};
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
-# define __RWSEM_DEP_MAP_INIT(lockname) , .dep_map = { .name = #lockname }
-#else
-# define __RWSEM_DEP_MAP_INIT(lockname)
-#endif
-
-
-#define __RWSEM_INITIALIZER(name)				\
-{								\
-	RWSEM_UNLOCKED_VALUE, __SPIN_LOCK_UNLOCKED((name).wait_lock), \
-	LIST_HEAD_INIT((name).wait_list) __RWSEM_DEP_MAP_INIT(name) \
-}
-
-#define DECLARE_RWSEM(name)					\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern void __init_rwsem(struct rw_semaphore *sem, const char *name,
-			 struct lock_class_key *key);
-
-#define init_rwsem(sem)						\
-do {								\
-	static struct lock_class_key __key;			\
-								\
-	__init_rwsem((sem), #sem, &__key);			\
-} while (0)
-
 /*
  * lock for reading
  */
@@ -133,7 +79,7 @@
  */
 static inline int __down_read_trylock(struct rw_semaphore *sem)
 {
-	rwsem_count_t result, tmp;
+	long result, tmp;
 	asm volatile("# beginning __down_read_trylock\n\t"
 		     "  mov          %0,%1\n\t"
 		     "1:\n\t"
@@ -155,7 +101,7 @@
  */
 static inline void __down_write_nested(struct rw_semaphore *sem, int subclass)
 {
-	rwsem_count_t tmp;
+	long tmp;
 	asm volatile("# beginning down_write\n\t"
 		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* adds 0xffff0001, returns the old value */
@@ -180,9 +126,8 @@
  */
 static inline int __down_write_trylock(struct rw_semaphore *sem)
 {
-	rwsem_count_t ret = cmpxchg(&sem->count,
-				    RWSEM_UNLOCKED_VALUE,
-				    RWSEM_ACTIVE_WRITE_BIAS);
+	long ret = cmpxchg(&sem->count, RWSEM_UNLOCKED_VALUE,
+			   RWSEM_ACTIVE_WRITE_BIAS);
 	if (ret == RWSEM_UNLOCKED_VALUE)
 		return 1;
 	return 0;
@@ -193,7 +138,7 @@
  */
 static inline void __up_read(struct rw_semaphore *sem)
 {
-	rwsem_count_t tmp;
+	long tmp;
 	asm volatile("# beginning __up_read\n\t"
 		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* subtracts 1, returns the old value */
@@ -211,7 +156,7 @@
  */
 static inline void __up_write(struct rw_semaphore *sem)
 {
-	rwsem_count_t tmp;
+	long tmp;
 	asm volatile("# beginning __up_write\n\t"
 		     LOCK_PREFIX "  xadd      %1,(%2)\n\t"
 		     /* subtracts 0xffff0001, returns the old value */
@@ -247,8 +192,7 @@
 /*
  * implement atomic add functionality
  */
-static inline void rwsem_atomic_add(rwsem_count_t delta,
-				    struct rw_semaphore *sem)
+static inline void rwsem_atomic_add(long delta, struct rw_semaphore *sem)
 {
 	asm volatile(LOCK_PREFIX _ASM_ADD "%1,%0"
 		     : "+m" (sem->count)
@@ -258,10 +202,9 @@
 /*
  * implement exchange and add functionality
  */
-static inline rwsem_count_t rwsem_atomic_update(rwsem_count_t delta,
-						struct rw_semaphore *sem)
+static inline long rwsem_atomic_update(long delta, struct rw_semaphore *sem)
 {
-	rwsem_count_t tmp = delta;
+	long tmp = delta;
 
 	asm volatile(LOCK_PREFIX "xadd %0,%1"
 		     : "+r" (tmp), "+m" (sem->count)
@@ -270,10 +213,5 @@
 	return tmp + delta;
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif /* __KERNEL__ */
 #endif /* _ASM_X86_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/segment.h linux-libre-2.6.39-gnu/arch/x86/include/asm/segment.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/segment.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/segment.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,14 +1,16 @@
 #ifndef _ASM_X86_SEGMENT_H
 #define _ASM_X86_SEGMENT_H
 
+#include <linux/const.h>
+
 /* Constructor for a conventional segment GDT (or LDT) entry */
 /* This is a macro so it can be used in initializers */
 #define GDT_ENTRY(flags, base, limit)			\
-	((((base)  & 0xff000000ULL) << (56-24)) |	\
-	 (((flags) & 0x0000f0ffULL) << 40) |		\
-	 (((limit) & 0x000f0000ULL) << (48-16)) |	\
-	 (((base)  & 0x00ffffffULL) << 16) |		\
-	 (((limit) & 0x0000ffffULL)))
+	((((base)  & _AC(0xff000000,ULL)) << (56-24)) |	\
+	 (((flags) & _AC(0x0000f0ff,ULL)) << 40) |	\
+	 (((limit) & _AC(0x000f0000,ULL)) << (48-16)) |	\
+	 (((base)  & _AC(0x00ffffff,ULL)) << 16) |	\
+	 (((limit) & _AC(0x0000ffff,ULL))))
 
 /* Simple and small GDT entries for booting only */
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/smp.h linux-libre-2.6.39-gnu/arch/x86/include/asm/smp.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/smp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/smp.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,12 +17,24 @@
 #endif
 #include <asm/thread_info.h>
 #include <asm/cpumask.h>
+#include <asm/cpufeature.h>
 
 extern int smp_num_siblings;
 extern unsigned int num_processors;
 
+static inline bool cpu_has_ht_siblings(void)
+{
+	bool has_siblings = false;
+#ifdef CONFIG_SMP
+	has_siblings = cpu_has_ht && smp_num_siblings > 1;
+#endif
+	return has_siblings;
+}
+
 DECLARE_PER_CPU(cpumask_var_t, cpu_sibling_map);
 DECLARE_PER_CPU(cpumask_var_t, cpu_core_map);
+/* cpus sharing the last level cache: */
+DECLARE_PER_CPU(cpumask_var_t, cpu_llc_shared_map);
 DECLARE_PER_CPU(u16, cpu_llc_id);
 DECLARE_PER_CPU(int, cpu_number);
 
@@ -36,8 +48,16 @@
 	return per_cpu(cpu_core_map, cpu);
 }
 
+static inline struct cpumask *cpu_llc_shared_mask(int cpu)
+{
+	return per_cpu(cpu_llc_shared_map, cpu);
+}
+
 DECLARE_EARLY_PER_CPU(u16, x86_cpu_to_apicid);
 DECLARE_EARLY_PER_CPU(u16, x86_bios_cpu_apicid);
+#if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_X86_32)
+DECLARE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid);
+#endif
 
 /* Static state in head.S used to set up a CPU */
 extern unsigned long stack_start; /* Initial stack pointer address */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/stacktrace.h linux-libre-2.6.39-gnu/arch/x86/include/asm/stacktrace.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/stacktrace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/stacktrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,7 @@
 };
 
 void dump_trace(struct task_struct *tsk, struct pt_regs *regs,
-		unsigned long *stack,
+		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data);
 
 #ifdef CONFIG_X86_32
@@ -86,11 +86,11 @@
 
 extern void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *stack, char *log_lvl);
+		   unsigned long *stack, unsigned long bp, char *log_lvl);
 
 extern void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, char *log_lvl);
+		   unsigned long *sp, unsigned long bp, char *log_lvl);
 
 extern unsigned int code_bytes;
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/system.h linux-libre-2.6.39-gnu/arch/x86/include/asm/system.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/system.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/system.h	2011-05-19 00:06:34.000000000 -0400
@@ -98,8 +98,6 @@
  */
 #define HAVE_DISABLE_HLT
 #else
-#define __SAVE(reg, offset) "movq %%" #reg ",(14-" #offset ")*8(%%rsp)\n\t"
-#define __RESTORE(reg, offset) "movq (14-" #offset ")*8(%%rsp),%%" #reg "\n\t"
 
 /* frame pointer must be last for get_wchan */
 #define SAVE_CONTEXT    "pushf ; pushq %%rbp ; movq %%rsi,%%rbp\n\t"
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/thread_info.h linux-libre-2.6.39-gnu/arch/x86/include/asm/thread_info.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/thread_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/thread_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -161,8 +161,14 @@
 
 #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR
 
-#define alloc_thread_info(tsk)						\
-	((struct thread_info *)__get_free_pages(THREAD_FLAGS, THREAD_ORDER))
+#define alloc_thread_info_node(tsk, node)				\
+({									\
+	struct page *page = alloc_pages_node(node, THREAD_FLAGS,	\
+					     THREAD_ORDER);		\
+	struct thread_info *ret = page ? page_address(page) : NULL;	\
+									\
+	ret;								\
+})
 
 #ifdef CONFIG_X86_32
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/topology.h linux-libre-2.6.39-gnu/arch/x86/include/asm/topology.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/topology.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/topology.h	2011-05-19 00:06:34.000000000 -0400
@@ -47,21 +47,6 @@
 
 #include <asm/mpspec.h>
 
-#ifdef CONFIG_X86_32
-
-/* Mappings between logical cpu number and node number */
-extern int cpu_to_node_map[];
-
-/* Returns the number of the node containing CPU 'cpu' */
-static inline int __cpu_to_node(int cpu)
-{
-	return cpu_to_node_map[cpu];
-}
-#define early_cpu_to_node __cpu_to_node
-#define cpu_to_node __cpu_to_node
-
-#else /* CONFIG_X86_64 */
-
 /* Mappings between logical cpu number and node number */
 DECLARE_EARLY_PER_CPU(int, x86_cpu_to_node_map);
 
@@ -84,8 +69,6 @@
 
 #endif /* !CONFIG_DEBUG_PER_CPU_MAPS */
 
-#endif /* CONFIG_X86_64 */
-
 /* Mappings between node number and cpus on that node. */
 extern cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 
@@ -155,7 +138,7 @@
 	.balance_interval	= 1,					\
 }
 
-#ifdef CONFIG_X86_64_ACPI_NUMA
+#ifdef CONFIG_X86_64
 extern int __node_distance(int, int);
 #define node_distance(a, b) __node_distance(a, b)
 #endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/trampoline.h linux-libre-2.6.39-gnu/arch/x86/include/asm/trampoline.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/trampoline.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/trampoline.h	2011-05-19 00:06:34.000000000 -0400
@@ -3,25 +3,36 @@
 
 #ifndef __ASSEMBLY__
 
-#ifdef CONFIG_X86_TRAMPOLINE
+#include <linux/types.h>
+#include <asm/io.h>
+
 /*
- * Trampoline 80x86 program as an array.
+ * Trampoline 80x86 program as an array.  These are in the init rodata
+ * segment, but that's okay, because we only care about the relative
+ * addresses of the symbols.
  */
-extern const unsigned char trampoline_data [];
-extern const unsigned char trampoline_end  [];
-extern unsigned char *trampoline_base;
+extern const unsigned char x86_trampoline_start [];
+extern const unsigned char x86_trampoline_end   [];
+extern unsigned char *x86_trampoline_base;
 
 extern unsigned long init_rsp;
 extern unsigned long initial_code;
 extern unsigned long initial_gs;
 
-#define TRAMPOLINE_SIZE roundup(trampoline_end - trampoline_data, PAGE_SIZE)
+extern void __init setup_trampolines(void);
 
-extern unsigned long setup_trampoline(void);
-extern void __init reserve_trampoline_memory(void);
-#else
-static inline void reserve_trampoline_memory(void) {}
-#endif /* CONFIG_X86_TRAMPOLINE */
+extern const unsigned char trampoline_data[];
+extern const unsigned char trampoline_status[];
+
+#define TRAMPOLINE_SYM(x)						\
+	((void *)(x86_trampoline_base +					\
+		  ((const unsigned char *)(x) - x86_trampoline_start)))
+
+/* Address of the SMP trampoline */
+static inline unsigned long trampoline_address(void)
+{
+	return virt_to_phys(TRAMPOLINE_SYM(trampoline_data));
+}
 
 #endif /* __ASSEMBLY__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/tsc.h linux-libre-2.6.39-gnu/arch/x86/include/asm/tsc.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/tsc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/tsc.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 static __always_inline cycles_t vget_cycles(void)
 {
 	/*
-	 * We only do VDSOs on TSC capable CPUs, so this shouldnt
+	 * We only do VDSOs on TSC capable CPUs, so this shouldn't
 	 * access boot_cpu_data (which is not VDSO-safe):
 	 */
 #ifndef CONFIG_X86_TSC
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/types.h linux-libre-2.6.39-gnu/arch/x86/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,22 +1,6 @@
 #ifndef _ASM_X86_TYPES_H
 #define _ASM_X86_TYPES_H
 
-#define dma_addr_t	dma_addr_t
-
 #include <asm-generic/types.h>
 
-#ifdef __KERNEL__
-#ifndef __ASSEMBLY__
-
-typedef u64 dma64_addr_t;
-#if defined(CONFIG_X86_64) || defined(CONFIG_HIGHMEM64G)
-/* DMA addresses come in 32-bit and 64-bit flavours. */
-typedef u64 dma_addr_t;
-#else
-typedef u32 dma_addr_t;
-#endif
-
-#endif /* __ASSEMBLY__ */
-#endif /* __KERNEL__ */
-
 #endif /* _ASM_X86_TYPES_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/unistd_32.h linux-libre-2.6.39-gnu/arch/x86/include/asm/unistd_32.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/unistd_32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/unistd_32.h	2011-05-19 00:06:34.000000000 -0400
@@ -346,10 +346,14 @@
 #define __NR_fanotify_init	338
 #define __NR_fanotify_mark	339
 #define __NR_prlimit64		340
+#define __NR_name_to_handle_at	341
+#define __NR_open_by_handle_at  342
+#define __NR_clock_adjtime	343
+#define __NR_syncfs             344
 
 #ifdef __KERNEL__
 
-#define NR_syscalls 341
+#define NR_syscalls 345
 
 #define __ARCH_WANT_IPC_PARSE_VERSION
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/unistd_64.h linux-libre-2.6.39-gnu/arch/x86/include/asm/unistd_64.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/unistd_64.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/unistd_64.h	2011-05-19 00:06:34.000000000 -0400
@@ -669,6 +669,14 @@
 __SYSCALL(__NR_fanotify_mark, sys_fanotify_mark)
 #define __NR_prlimit64				302
 __SYSCALL(__NR_prlimit64, sys_prlimit64)
+#define __NR_name_to_handle_at			303
+__SYSCALL(__NR_name_to_handle_at, sys_name_to_handle_at)
+#define __NR_open_by_handle_at			304
+__SYSCALL(__NR_open_by_handle_at, sys_open_by_handle_at)
+#define __NR_clock_adjtime			305
+__SYSCALL(__NR_clock_adjtime, sys_clock_adjtime)
+#define __NR_syncfs                             306
+__SYSCALL(__NR_syncfs, sys_syncfs)
 
 #ifndef __NO_STUBS
 #define __ARCH_WANT_OLD_READDIR
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_bau.h linux-libre-2.6.39-gnu/arch/x86/include/asm/uv/uv_bau.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_bau.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/uv/uv_bau.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,6 +94,8 @@
 /* after this # consecutive successes, bump up the throttle if it was lowered */
 #define COMPLETE_THRESHOLD 5
 
+#define UV_LB_SUBNODEID 0x10
+
 /*
  * number of entries in the destination side payload queue
  */
@@ -124,7 +126,7 @@
  * The distribution specification (32 bytes) is interpreted as a 256-bit
  * distribution vector. Adjacent bits correspond to consecutive even numbered
  * nodeIDs. The result of adding the index of a given bit to the 15-bit
- * 'base_dest_nodeid' field of the header corresponds to the
+ * 'base_dest_nasid' field of the header corresponds to the
  * destination nodeID associated with that specified bit.
  */
 struct bau_target_uvhubmask {
@@ -176,7 +178,7 @@
 struct bau_msg_header {
 	unsigned int dest_subnodeid:6;	/* must be 0x10, for the LB */
 	/* bits 5:0 */
-	unsigned int base_dest_nodeid:15; /* nasid of the */
+	unsigned int base_dest_nasid:15; /* nasid of the */
 	/* bits 20:6 */			  /* first bit in uvhub map */
 	unsigned int command:8;	/* message type */
 	/* bits 28:21 */
@@ -378,6 +380,10 @@
 	unsigned long d_rcanceled; /* number of messages canceled by resets */
 };
 
+struct hub_and_pnode {
+	short uvhub;
+	short pnode;
+};
 /*
  * one per-cpu; to locate the software tables
  */
@@ -399,10 +405,12 @@
 	int baudisabled;
 	int set_bau_off;
 	short cpu;
+	short osnode;
 	short uvhub_cpu;
 	short uvhub;
 	short cpus_in_socket;
 	short cpus_in_uvhub;
+	short partition_base_pnode;
 	unsigned short message_number;
 	unsigned short uvhub_quiesce;
 	short socket_acknowledge_count[DEST_Q_SIZE];
@@ -422,15 +430,16 @@
 	int congested_period;
 	cycles_t period_time;
 	long period_requests;
+	struct hub_and_pnode *target_hub_and_pnode;
 };
 
 static inline int bau_uvhub_isset(int uvhub, struct bau_target_uvhubmask *dstp)
 {
 	return constant_test_bit(uvhub, &dstp->bits[0]);
 }
-static inline void bau_uvhub_set(int uvhub, struct bau_target_uvhubmask *dstp)
+static inline void bau_uvhub_set(int pnode, struct bau_target_uvhubmask *dstp)
 {
-	__set_bit(uvhub, &dstp->bits[0]);
+	__set_bit(pnode, &dstp->bits[0]);
 }
 static inline void bau_uvhubs_clear(struct bau_target_uvhubmask *dstp,
 				    int nbits)
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_hub.h linux-libre-2.6.39-gnu/arch/x86/include/asm/uv/uv_hub.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_hub.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/uv/uv_hub.h	2011-05-19 00:06:34.000000000 -0400
@@ -398,6 +398,8 @@
 	unsigned short	nr_online_cpus;
 	unsigned short	pnode;
 	short		memory_nid;
+	spinlock_t	nmi_lock;
+	unsigned long	nmi_count;
 };
 extern struct uv_blade_info *uv_blade_info;
 extern short *uv_node_to_blade;
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_mmrs.h linux-libre-2.6.39-gnu/arch/x86/include/asm/uv/uv_mmrs.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/uv/uv_mmrs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/uv/uv_mmrs.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * SGI UV MMR definitions
  *
- * Copyright (C) 2007-2010 Silicon Graphics, Inc. All rights reserved.
+ * Copyright (C) 2007-2011 Silicon Graphics, Inc. All rights reserved.
  */
 
 #ifndef _ASM_X86_UV_UV_MMRS_H
@@ -1099,5 +1099,19 @@
     } s;
 };
 
+/* ========================================================================= */
+/*                               UVH_SCRATCH5                                */
+/* ========================================================================= */
+#define UVH_SCRATCH5 0x2d0200UL
+#define UVH_SCRATCH5_32 0x00778
+
+#define UVH_SCRATCH5_SCRATCH5_SHFT 0
+#define UVH_SCRATCH5_SCRATCH5_MASK 0xffffffffffffffffUL
+union uvh_scratch5_u {
+    unsigned long	v;
+    struct uvh_scratch5_s {
+	unsigned long	scratch5 : 64;  /* RW, W1CS */
+    } s;
+};
 
 #endif /* __ASM_UV_MMRS_X86_H__ */
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/x86_init.h linux-libre-2.6.39-gnu/arch/x86/include/asm/x86_init.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/x86_init.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/x86_init.h	2011-05-19 00:06:34.000000000 -0400
@@ -68,6 +68,17 @@
 };
 
 /**
+ * struct x86_init_mapping - platform specific initial kernel pagetable setup
+ * @pagetable_reserve:	reserve a range of addresses for kernel pagetable usage
+ *
+ * For more details on the purpose of this hook, look in
+ * init_memory_mapping and the commit that added it.
+ */
+struct x86_init_mapping {
+	void (*pagetable_reserve)(u64 start, u64 end);
+};
+
+/**
  * struct x86_init_paging - platform specific paging functions
  * @pagetable_setup_start:	platform specific pre paging_init() call
  * @pagetable_setup_done:	platform specific post paging_init() call
@@ -83,11 +94,13 @@
  *				boot cpu
  * @tsc_pre_init:		platform function called before TSC init
  * @timer_init:			initialize the platform timer (default PIT/HPET)
+ * @wallclock_init:		init the wallclock device
  */
 struct x86_init_timers {
 	void (*setup_percpu_clockev)(void);
 	void (*tsc_pre_init)(void);
 	void (*timer_init)(void);
+	void (*wallclock_init)(void);
 };
 
 /**
@@ -121,6 +134,7 @@
 	struct x86_init_mpparse		mpparse;
 	struct x86_init_irqs		irqs;
 	struct x86_init_oem		oem;
+	struct x86_init_mapping		mapping;
 	struct x86_init_paging		paging;
 	struct x86_init_timers		timers;
 	struct x86_init_iommu		iommu;
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/hypercall.h linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/hypercall.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/hypercall.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/hypercall.h	2011-05-19 00:06:34.000000000 -0400
@@ -287,7 +287,7 @@
 static inline int
 HYPERVISOR_sched_op(int cmd, void *arg)
 {
-	return _hypercall2(int, sched_op_new, cmd, arg);
+	return _hypercall2(int, sched_op, cmd, arg);
 }
 
 static inline long
@@ -422,10 +422,17 @@
 #endif
 
 static inline int
-HYPERVISOR_suspend(unsigned long srec)
+HYPERVISOR_suspend(unsigned long start_info_mfn)
 {
-	return _hypercall3(int, sched_op, SCHEDOP_shutdown,
-			   SHUTDOWN_suspend, srec);
+	struct sched_shutdown r = { .reason = SHUTDOWN_suspend };
+
+	/*
+	 * For a PV guest the tools require that the start_info mfn be
+	 * present in rdx/edx when the hypercall is made. Per the
+	 * hypercall calling convention this is the third hypercall
+	 * argument, which is start_info_mfn here.
+	 */
+	return _hypercall3(int, sched_op, SCHEDOP_shutdown, &r, start_info_mfn);
 }
 
 static inline int
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/interface.h linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/interface.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/interface.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/interface.h	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
  * The privilege level specifies which modes may enter a trap via a software
  * interrupt. On x86/64, since rings 1 and 2 are unavailable, we allocate
  * privilege levels as follows:
- *  Level == 0: Noone may enter
+ *  Level == 0: No one may enter
  *  Level == 1: Kernel may enter
  *  Level == 2: Kernel may enter
  *  Level == 3: Everyone may enter
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/page.h linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/page.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/page.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/page.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,8 +29,10 @@
 
 /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
 #define INVALID_P2M_ENTRY	(~0UL)
-#define FOREIGN_FRAME_BIT	(1UL<<31)
+#define FOREIGN_FRAME_BIT	(1UL<<(BITS_PER_LONG-1))
+#define IDENTITY_FRAME_BIT	(1UL<<(BITS_PER_LONG-2))
 #define FOREIGN_FRAME(m)	((m) | FOREIGN_FRAME_BIT)
+#define IDENTITY_FRAME(m)	((m) | IDENTITY_FRAME_BIT)
 
 /* Maximum amount of memory we can handle in a domain in pages */
 #define MAX_DOMAIN_PAGES						\
@@ -41,12 +43,18 @@
 
 extern unsigned long get_phys_to_machine(unsigned long pfn);
 extern bool set_phys_to_machine(unsigned long pfn, unsigned long mfn);
+extern bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn);
+extern unsigned long set_phys_range_identity(unsigned long pfn_s,
+					     unsigned long pfn_e);
 
 extern int m2p_add_override(unsigned long mfn, struct page *page);
 extern int m2p_remove_override(struct page *page);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
+#ifdef CONFIG_XEN_DEBUG_FS
+extern int p2m_dump_show(struct seq_file *m, void *v);
+#endif
 static inline unsigned long pfn_to_mfn(unsigned long pfn)
 {
 	unsigned long mfn;
@@ -57,7 +65,7 @@
 	mfn = get_phys_to_machine(pfn);
 
 	if (mfn != INVALID_P2M_ENTRY)
-		mfn &= ~FOREIGN_FRAME_BIT;
+		mfn &= ~(FOREIGN_FRAME_BIT | IDENTITY_FRAME_BIT);
 
 	return mfn;
 }
@@ -73,25 +81,44 @@
 static inline unsigned long mfn_to_pfn(unsigned long mfn)
 {
 	unsigned long pfn;
+	int ret = 0;
 
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return mfn;
 
+	if (unlikely((mfn >> machine_to_phys_order) != 0)) {
+		pfn = ~0;
+		goto try_override;
+	}
 	pfn = 0;
 	/*
 	 * The array access can fail (e.g., device space beyond end of RAM).
 	 * In such cases it doesn't matter what we return (we return garbage),
 	 * but we must handle the fault without crashing!
 	 */
-	__get_user(pfn, &machine_to_phys_mapping[mfn]);
+	ret = __get_user(pfn, &machine_to_phys_mapping[mfn]);
+try_override:
+	/* ret might be < 0 if there are no entries in the m2p for mfn */
+	if (ret < 0)
+		pfn = ~0;
+	else if (get_phys_to_machine(pfn) != mfn)
+		/*
+		 * If this appears to be a foreign mfn (because the pfn
+		 * doesn't map back to the mfn), then check the local override
+		 * table to see if there's a better pfn to use.
+		 *
+		 * m2p_find_override_pfn returns ~0 if it doesn't find anything.
+		 */
+		pfn = m2p_find_override_pfn(mfn, ~0);
 
-	/*
-	 * If this appears to be a foreign mfn (because the pfn
-	 * doesn't map back to the mfn), then check the local override
-	 * table to see if there's a better pfn to use.
+	/* 
+	 * pfn is ~0 if there are no entries in the m2p for mfn or if the
+	 * entry doesn't map back to the mfn and m2p_override doesn't have a
+	 * valid entry for it.
 	 */
-	if (get_phys_to_machine(pfn) != mfn)
-		pfn = m2p_find_override_pfn(mfn, pfn);
+	if (pfn == ~0 &&
+			get_phys_to_machine(mfn) == IDENTITY_FRAME(mfn))
+		pfn = mfn;
 
 	return pfn;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/pci.h linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/pci.h
--- linux-libre-2.6.38-gnu/arch/x86/include/asm/xen/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/include/asm/xen/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,16 +27,16 @@
  * its own functions.
  */
 struct xen_pci_frontend_ops {
-	int (*enable_msi)(struct pci_dev *dev, int **vectors);
+	int (*enable_msi)(struct pci_dev *dev, int vectors[]);
 	void (*disable_msi)(struct pci_dev *dev);
-	int (*enable_msix)(struct pci_dev *dev, int **vectors, int nvec);
+	int (*enable_msix)(struct pci_dev *dev, int vectors[], int nvec);
 	void (*disable_msix)(struct pci_dev *dev);
 };
 
 extern struct xen_pci_frontend_ops *xen_pci_frontend;
 
 static inline int xen_pci_frontend_enable_msi(struct pci_dev *dev,
-					      int **vectors)
+					      int vectors[])
 {
 	if (xen_pci_frontend && xen_pci_frontend->enable_msi)
 		return xen_pci_frontend->enable_msi(dev, vectors);
@@ -48,7 +48,7 @@
 			xen_pci_frontend->disable_msi(dev);
 }
 static inline int xen_pci_frontend_enable_msix(struct pci_dev *dev,
-					       int **vectors, int nvec)
+					       int vectors[], int nvec)
 {
 	if (xen_pci_frontend && xen_pci_frontend->enable_msix)
 		return xen_pci_frontend->enable_msix(dev, vectors, nvec);
diff -druN linux-libre-2.6.38-gnu/arch/x86/Kconfig linux-libre-2.6.39-gnu/arch/x86/Kconfig
--- linux-libre-2.6.38-gnu/arch/x86/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -64,9 +64,14 @@
 	select HAVE_TEXT_POKE_SMP
 	select HAVE_GENERIC_HARDIRQS
 	select HAVE_SPARSE_IRQ
+	select GENERIC_FIND_FIRST_BIT
+	select GENERIC_FIND_NEXT_BIT
 	select GENERIC_IRQ_PROBE
 	select GENERIC_PENDING_IRQ if SMP
+	select GENERIC_IRQ_SHOW
+	select IRQ_FORCED_THREADING
 	select USE_GENERIC_SMP_HELPERS if SMP
+	select ARCH_NO_SYSDEV_OPS
 
 config INSTRUCTION_DECODER
 	def_bool (KPROBES || PERF_EVENTS)
@@ -119,7 +124,7 @@
 	def_bool y
 
 config GENERIC_ISA_DMA
-	def_bool y
+	def_bool ISA_DMA_API
 
 config GENERIC_IOMAP
 	def_bool y
@@ -139,7 +144,7 @@
 	bool
 
 config ARCH_MAY_HAVE_PC_FDC
-	def_bool y
+	def_bool ISA_DMA_API
 
 config RWSEM_GENERIC_SPINLOCK
 	def_bool !X86_XADD
@@ -217,10 +222,6 @@
 	def_bool y
 	depends on SMP
 
-config X86_TRAMPOLINE
-	def_bool y
-	depends on SMP || (64BIT && ACPI_SLEEP)
-
 config X86_32_LAZY_GS
 	def_bool y
 	depends on X86_32 && !CC_STACKPROTECTOR
@@ -382,6 +383,8 @@
 	depends on X86_32
 	depends on X86_EXTENDED_PLATFORM
 	select X86_REBOOTFIXUPS
+	select OF
+	select OF_EARLY_FLATTREE
 	---help---
 	  Select for the Intel CE media processor (CE4100) SOC.
 	  This option compiles in support for the CE4100 SOC for settop
@@ -811,7 +814,7 @@
 
 config X86_IO_APIC
 	def_bool y
-	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_APIC
+	depends on X86_64 || SMP || X86_32_NON_STANDARD || X86_UP_IOAPIC
 
 config X86_VISWS_APIC
 	def_bool y
@@ -1705,7 +1708,7 @@
 	depends on NUMA
 
 config USE_PERCPU_NUMA_NODE_ID
-	def_bool X86_64
+	def_bool y
 	depends on NUMA
 
 menu "Power management and ACPI options"
@@ -2000,9 +2003,13 @@
 
 source "drivers/pci/Kconfig"
 
-# x86_64 have no ISA slots, but do have ISA-style DMA.
+# x86_64 have no ISA slots, but can have ISA-style DMA.
 config ISA_DMA_API
-	def_bool y
+	bool "ISA-style DMA support" if (X86_64 && EXPERT)
+	default y
+	help
+	  Enables ISA-style DMA support for devices requiring such controllers.
+	  If unsure, say Y.
 
 if X86_32
 
@@ -2066,9 +2073,10 @@
 
 config OLPC
 	bool "One Laptop Per Child support"
+	depends on !X86_PAE
 	select GPIOLIB
-	select OLPC_OPENFIRMWARE
-	depends on !X86_64 && !X86_PAE
+	select OF
+	select OF_PROMTREE if PROC_DEVICETREE
 	---help---
 	  Add support for detecting the unique features of the OLPC
 	  XO hardware.
@@ -2079,21 +2087,6 @@
 	---help---
 	  Add support for non-essential features of the OLPC XO-1 laptop.
 
-config OLPC_OPENFIRMWARE
-	bool "Support for OLPC's Open Firmware"
-	depends on !X86_64 && !X86_PAE
-	default n
-	select OF
-	help
-	  This option adds support for the implementation of Open Firmware
-	  that is used on the OLPC XO-1 Children's Machine.
-	  If unsure, say N here.
-
-config OLPC_OPENFIRMWARE_DT
-	bool
-	default y if OLPC_OPENFIRMWARE && PROC_DEVICETREE
-	select OF_PROMTREE
-
 endif # X86_32
 
 config AMD_NB
@@ -2104,6 +2097,16 @@
 
 source "drivers/pci/hotplug/Kconfig"
 
+config RAPIDIO
+	bool "RapidIO support"
+	depends on PCI
+	default n
+	help
+	  If you say Y here, the kernel will include drivers and
+	  infrastructure code to support RapidIO interconnect devices.
+
+source "drivers/rapidio/Kconfig"
+
 endmenu
 
 
@@ -2138,6 +2141,11 @@
 	def_bool y
 	depends on COMPAT && SYSVIPC
 
+config KEYS_COMPAT
+	bool
+	depends on COMPAT && KEYS
+	default y
+
 endmenu
 
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/Kconfig.cpu linux-libre-2.6.39-gnu/arch/x86/Kconfig.cpu
--- linux-libre-2.6.38-gnu/arch/x86/Kconfig.cpu	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/Kconfig.cpu	2011-05-19 00:06:34.000000000 -0400
@@ -294,11 +294,6 @@
 
 endif
 
-config X86_CPU
-	def_bool y
-	select GENERIC_FIND_FIRST_BIT
-	select GENERIC_FIND_NEXT_BIT
-
 #
 # Define implied options from the CPU selection here
 config X86_INTERNODE_CACHE_SHIFT
@@ -331,7 +326,7 @@
 	  Old PentiumPro multiprocessor systems had errata that could cause
 	  memory operations to violate the x86 ordering standard in rare cases.
 	  Enabling this option will attempt to work around some (but not all)
-	  occurances of this problem, at the cost of much heavier spinlock and
+	  occurrences of this problem, at the cost of much heavier spinlock and
 	  memory barrier operations.
 
 	  If unsure, say n here. Even distro kernels should think twice before
@@ -371,7 +366,7 @@
 
 config X86_USE_PPRO_CHECKSUM
 	def_bool y
-	depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM
+	depends on MWINCHIP3D || MWINCHIPC6 || MCYRIXIII || MK7 || MK6 || MPENTIUM4 || MPENTIUMM || MPENTIUMIII || MPENTIUMII || M686 || MK8 || MVIAC3_2 || MVIAC7 || MEFFICEON || MGEODE_LX || MCORE2 || MATOM
 
 config X86_USE_3DNOW
 	def_bool y
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/boot.c linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/boot.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/boot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/boot.c	2011-05-19 00:06:34.000000000 -0400
@@ -595,14 +595,8 @@
 	nid = acpi_get_node(handle);
 	if (nid == -1 || !node_online(nid))
 		return;
-#ifdef CONFIG_X86_64
-	apicid_to_node[physid] = nid;
+	set_apicid_to_node(physid, nid);
 	numa_set_node(cpu, nid);
-#else /* CONFIG_X86_32 */
-	apicid_2_node[physid] = nid;
-	cpu_to_node_map[cpu] = nid;
-#endif
-
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/realmode/wakeup.h linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/realmode/wakeup.h
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/realmode/wakeup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/realmode/wakeup.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,8 @@
 extern struct wakeup_header wakeup_header;
 #endif
 
-#define HEADER_OFFSET 0x3f00
-#define WAKEUP_SIZE   0x4000
+#define WAKEUP_HEADER_OFFSET	8
+#define WAKEUP_HEADER_SIGNATURE 0x51ee1111
+#define WAKEUP_END_SIGNATURE	0x65a22c82
 
 #endif /* ARCH_X86_KERNEL_ACPI_RM_WAKEUP_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/realmode/wakeup.lds.S linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/realmode/wakeup.lds.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/realmode/wakeup.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/realmode/wakeup.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -13,9 +13,19 @@
 SECTIONS
 {
 	. = 0;
+	.jump	: {
+		*(.jump)
+	} = 0x90909090
+
+	. = WAKEUP_HEADER_OFFSET;
+	.header : {
+		*(.header)
+	}
+
+	. = ALIGN(16);
 	.text : {
 		 *(.text*)
-	}
+	} = 0x90909090
 
 	. = ALIGN(16);
 	.rodata : {
@@ -33,11 +43,6 @@
 		 *(.data*)
 	}
 
-	.signature : {
-		end_signature = .;
-		LONG(0x65a22c82)
-	}
-
 	. = ALIGN(16);
 	.bss :	{
 		__bss_start = .;
@@ -45,20 +50,13 @@
 		__bss_end = .;
 	}
 
-	. = HEADER_OFFSET;
-	.header : {
-		*(.header)
+	.signature : {
+		*(.signature)
 	}
 
-	. = ALIGN(16);
 	_end = .;
 
 	/DISCARD/ : {
 		*(.note*)
 	}
-
-	/*
-	 * The ASSERT() sink to . is intentional, for binutils 2.14 compatibility:
-	 */
-	. = ASSERT(_end <= WAKEUP_SIZE, "Wakeup too big!");
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/realmode/wakeup.S linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/realmode/wakeup.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/realmode/wakeup.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/realmode/wakeup.S	2011-05-19 00:06:34.000000000 -0400
@@ -6,11 +6,17 @@
 #include <asm/page_types.h>
 #include <asm/pgtable_types.h>
 #include <asm/processor-flags.h>
+#include "wakeup.h"
 
 	.code16
-	.section ".header", "a"
+	.section ".jump", "ax"
+	.globl	_start
+_start:
+	cli
+	jmp	wakeup_code
 
 /* This should match the structure in wakeup.h */
+		.section ".header", "a"
 		.globl	wakeup_header
 wakeup_header:
 video_mode:	.short	0	/* Video mode number */
@@ -30,14 +36,11 @@
 wakeup_jmp_off:	.word	3f
 wakeup_jmp_seg:	.word	0
 wakeup_gdt:	.quad	0, 0, 0
-signature:	.long	0x51ee1111
+signature:	.long	WAKEUP_HEADER_SIGNATURE
 
 	.text
-	.globl	_start
 	.code16
 wakeup_code:
-_start:
-	cli
 	cld
 
 	/* Apparently some dimwit BIOS programmers don't know how to
@@ -77,12 +80,12 @@
 
 	/* Check header signature... */
 	movl	signature, %eax
-	cmpl	$0x51ee1111, %eax
+	cmpl	$WAKEUP_HEADER_SIGNATURE, %eax
 	jne	bogus_real_magic
 
 	/* Check we really have everything... */
 	movl	end_signature, %eax
-	cmpl	$0x65a22c82, %eax
+	cmpl	$WAKEUP_END_SIGNATURE, %eax
 	jne	bogus_real_magic
 
 	/* Call the C code */
@@ -147,3 +150,7 @@
 wakeup_stack:
 	.space	2048
 wakeup_stack_end:
+
+	.section ".signature","a"
+end_signature:
+	.long	WAKEUP_END_SIGNATURE
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/sleep.c linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/sleep.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/sleep.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/sleep.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,37 +18,28 @@
 #include "realmode/wakeup.h"
 #include "sleep.h"
 
-unsigned long acpi_wakeup_address;
 unsigned long acpi_realmode_flags;
 
-/* address in low memory of the wakeup routine. */
-static unsigned long acpi_realmode;
-
 #if defined(CONFIG_SMP) && defined(CONFIG_64BIT)
 static char temp_stack[4096];
 #endif
 
 /**
- * acpi_save_state_mem - save kernel state
+ * acpi_suspend_lowlevel - save kernel state
  *
  * Create an identity mapped page table and copy the wakeup routine to
  * low memory.
- *
- * Note that this is too late to change acpi_wakeup_address.
  */
-int acpi_save_state_mem(void)
+int acpi_suspend_lowlevel(void)
 {
 	struct wakeup_header *header;
+	/* address in low memory of the wakeup routine. */
+	char *acpi_realmode;
 
-	if (!acpi_realmode) {
-		printk(KERN_ERR "Could not allocate memory during boot, "
-		       "S3 disabled\n");
-		return -ENOMEM;
-	}
-	memcpy((void *)acpi_realmode, &wakeup_code_start, WAKEUP_SIZE);
+	acpi_realmode = TRAMPOLINE_SYM(acpi_wakeup_code);
 
-	header = (struct wakeup_header *)(acpi_realmode + HEADER_OFFSET);
-	if (header->signature != 0x51ee1111) {
+	header = (struct wakeup_header *)(acpi_realmode + WAKEUP_HEADER_OFFSET);
+	if (header->signature != WAKEUP_HEADER_SIGNATURE) {
 		printk(KERN_ERR "wakeup header does not match\n");
 		return -EINVAL;
 	}
@@ -68,9 +59,7 @@
 	/* GDT[0]: GDT self-pointer */
 	header->wakeup_gdt[0] =
 		(u64)(sizeof(header->wakeup_gdt) - 1) +
-		((u64)(acpi_wakeup_address +
-			((char *)&header->wakeup_gdt - (char *)acpi_realmode))
-				<< 16);
+		((u64)__pa(&header->wakeup_gdt) << 16);
 	/* GDT[1]: big real mode-like code segment */
 	header->wakeup_gdt[1] =
 		GDT_ENTRY(0x809b, acpi_wakeup_address, 0xfffff);
@@ -96,7 +85,7 @@
 	header->pmode_cr3 = (u32)__pa(&initial_page_table);
 	saved_magic = 0x12345678;
 #else /* CONFIG_64BIT */
-	header->trampoline_segment = setup_trampoline() >> 4;
+	header->trampoline_segment = trampoline_address() >> 4;
 #ifdef CONFIG_SMP
 	stack_start = (unsigned long)temp_stack + sizeof(temp_stack);
 	early_gdt_descr.address =
@@ -107,56 +96,10 @@
        saved_magic = 0x123456789abcdef0L;
 #endif /* CONFIG_64BIT */
 
+	do_suspend_lowlevel();
 	return 0;
 }
 
-/*
- * acpi_restore_state - undo effects of acpi_save_state_mem
- */
-void acpi_restore_state_mem(void)
-{
-}
-
-
-/**
- * acpi_reserve_wakeup_memory - do _very_ early ACPI initialisation
- *
- * We allocate a page from the first 1MB of memory for the wakeup
- * routine for when we come back from a sleep state. The
- * runtime allocator allows specification of <16MB pages, but not
- * <1MB pages.
- */
-void __init acpi_reserve_wakeup_memory(void)
-{
-	phys_addr_t mem;
-
-	if ((&wakeup_code_end - &wakeup_code_start) > WAKEUP_SIZE) {
-		printk(KERN_ERR
-		       "ACPI: Wakeup code way too big, S3 disabled.\n");
-		return;
-	}
-
-	mem = memblock_find_in_range(0, 1<<20, WAKEUP_SIZE, PAGE_SIZE);
-
-	if (mem == MEMBLOCK_ERROR) {
-		printk(KERN_ERR "ACPI: Cannot allocate lowmem, S3 disabled.\n");
-		return;
-	}
-	acpi_realmode = (unsigned long) phys_to_virt(mem);
-	acpi_wakeup_address = mem;
-	memblock_x86_reserve_range(mem, mem + WAKEUP_SIZE, "ACPI WAKEUP");
-}
-
-int __init acpi_configure_wakeup_memory(void)
-{
-	if (acpi_realmode)
-		set_memory_x(acpi_realmode, WAKEUP_SIZE >> PAGE_SHIFT);
-
-	return 0;
-}
-arch_initcall(acpi_configure_wakeup_memory);
-
-
 static int __init acpi_sleep_setup(char *str)
 {
 	while ((str != NULL) && (*str != '\0')) {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/sleep.h linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/sleep.h
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/sleep.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/sleep.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,13 +4,12 @@
 
 #include <asm/trampoline.h>
 
-extern char wakeup_code_start, wakeup_code_end;
-
 extern unsigned long saved_video_mode;
 extern long saved_magic;
 
 extern int wakeup_pmode_return;
-extern char swsusp_pg_dir[PAGE_SIZE];
 
 extern unsigned long acpi_copy_wakeup_routine(unsigned long);
 extern void wakeup_long64(void);
+
+extern void do_suspend_lowlevel(void);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/wakeup_rm.S linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/wakeup_rm.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/acpi/wakeup_rm.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/acpi/wakeup_rm.S	2011-05-19 00:06:34.000000000 -0400
@@ -2,9 +2,11 @@
  * Wrapper script for the realmode binary as a transport object
  * before copying to low memory.
  */
-	.section ".rodata","a"
-	.globl	wakeup_code_start, wakeup_code_end
-wakeup_code_start:
+#include <asm/page_types.h>
+
+	.section ".x86_trampoline","a"
+	.balign PAGE_SIZE
+	.globl	acpi_wakeup_code
+acpi_wakeup_code:
 	.incbin	"arch/x86/kernel/acpi/realmode/wakeup.bin"
-wakeup_code_end:
-	.size	wakeup_code_start, .-wakeup_code_start
+	.size	acpi_wakeup_code, .-acpi_wakeup_code
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/alternative.c linux-libre-2.6.39-gnu/arch/x86/kernel/alternative.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/alternative.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/alternative.c	2011-05-19 00:06:34.000000000 -0400
@@ -199,7 +199,7 @@
 
 /* Replace instructions with better alternatives for this CPU type.
    This runs before SMP is initialized to avoid SMP problems with
-   self modifying code. This implies that assymetric systems where
+   self modifying code. This implies that asymmetric systems where
    APs have less capabilities than the boot processor are not handled.
    Tough. Make sure you disable such features by hand. */
 
@@ -620,7 +620,12 @@
 		flush_icache_range((unsigned long)p->addr,
 				   (unsigned long)p->addr + p->len);
 	}
-
+	/*
+	 * Intel Archiecture Software Developer's Manual section 7.1.3 specifies
+	 * that a core serializing instruction such as "cpuid" should be
+	 * executed on _each_ core before the new instruction is made visible.
+	 */
+	sync_core();
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/amd_iommu_init.c linux-libre-2.6.39-gnu/arch/x86/kernel/amd_iommu_init.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/amd_iommu_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/amd_iommu_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/acpi.h>
 #include <linux/list.h>
 #include <linux/slab.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/interrupt.h>
 #include <linux/msi.h>
 #include <asm/pci-direct.h>
@@ -1260,7 +1260,7 @@
  * disable suspend until real resume implemented
  */
 
-static int amd_iommu_resume(struct sys_device *dev)
+static void amd_iommu_resume(void)
 {
 	struct amd_iommu *iommu;
 
@@ -1276,11 +1276,9 @@
 	 */
 	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)
+static int amd_iommu_suspend(void)
 {
 	/* disable IOMMUs to go out of the way for BIOS */
 	disable_iommus();
@@ -1288,17 +1286,11 @@
 	return 0;
 }
 
-static struct sysdev_class amd_iommu_sysdev_class = {
-	.name = "amd_iommu",
+static struct syscore_ops amd_iommu_syscore_ops = {
 	.suspend = amd_iommu_suspend,
 	.resume = amd_iommu_resume,
 };
 
-static struct sys_device device_amd_iommu = {
-	.id = 0,
-	.cls = &amd_iommu_sysdev_class,
-};
-
 /*
  * This is the core init function for AMD IOMMU hardware in the system.
  * This function is called from the generic x86 DMA layer initialization
@@ -1415,14 +1407,6 @@
 		goto free;
 	}
 
-	ret = sysdev_class_register(&amd_iommu_sysdev_class);
-	if (ret)
-		goto free;
-
-	ret = sysdev_register(&device_amd_iommu);
-	if (ret)
-		goto free;
-
 	ret = amd_iommu_init_devices();
 	if (ret)
 		goto free;
@@ -1441,6 +1425,8 @@
 
 	amd_iommu_init_notifier();
 
+	register_syscore_ops(&amd_iommu_syscore_ops);
+
 	if (iommu_pass_through)
 		goto out;
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/amd_nb.c linux-libre-2.6.39-gnu/arch/x86/kernel/amd_nb.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/amd_nb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/amd_nb.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,14 +12,19 @@
 
 static u32 *flush_words;
 
-struct pci_device_id amd_nb_misc_ids[] = {
+const struct pci_device_id amd_nb_misc_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
-	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_MISC) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F3) },
 	{}
 };
 EXPORT_SYMBOL(amd_nb_misc_ids);
 
+static struct pci_device_id amd_nb_link_ids[] = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
+	{}
+};
+
 const struct amd_nb_bus_dev_range amd_nb_bus_dev_ranges[] __initconst = {
 	{ 0x00, 0x18, 0x20 },
 	{ 0xff, 0x00, 0x20 },
@@ -31,7 +36,7 @@
 EXPORT_SYMBOL(amd_northbridges);
 
 static struct pci_dev *next_northbridge(struct pci_dev *dev,
-					struct pci_device_id *ids)
+					const struct pci_device_id *ids)
 {
 	do {
 		dev = pci_get_device(PCI_ANY_ID, PCI_ANY_ID, dev);
@@ -43,9 +48,9 @@
 
 int amd_cache_northbridges(void)
 {
-	int i = 0;
+	u16 i = 0;
 	struct amd_northbridge *nb;
-	struct pci_dev *misc;
+	struct pci_dev *misc, *link;
 
 	if (amd_nb_num())
 		return 0;
@@ -64,10 +69,12 @@
 	amd_northbridges.nb = nb;
 	amd_northbridges.num = i;
 
-	misc = NULL;
+	link = misc = NULL;
 	for (i = 0; i != amd_nb_num(); i++) {
 		node_to_amd_nb(i)->misc = misc =
 			next_northbridge(misc, amd_nb_misc_ids);
+		node_to_amd_nb(i)->link = link =
+			next_northbridge(link, amd_nb_link_ids);
         }
 
 	/* some CPU families (e.g. family 0x11) do not support GART */
@@ -85,26 +92,95 @@
 	     boot_cpu_data.x86_mask >= 0x1))
 		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
 
+	if (boot_cpu_data.x86 == 0x15)
+		amd_northbridges.flags |= AMD_NB_L3_INDEX_DISABLE;
+
+	/* L3 cache partitioning is supported on family 0x15 */
+	if (boot_cpu_data.x86 == 0x15)
+		amd_northbridges.flags |= AMD_NB_L3_PARTITIONING;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(amd_cache_northbridges);
 
-/* Ignores subdevice/subvendor but as far as I can figure out
-   they're useless anyways */
-int __init early_is_amd_nb(u32 device)
+/*
+ * Ignores subdevice/subvendor but as far as I can figure out
+ * they're useless anyways
+ */
+bool __init early_is_amd_nb(u32 device)
 {
-	struct pci_device_id *id;
+	const struct pci_device_id *id;
 	u32 vendor = device & 0xffff;
+
 	device >>= 16;
 	for (id = amd_nb_misc_ids; id->vendor; id++)
 		if (vendor == id->vendor && device == id->device)
-			return 1;
+			return true;
+	return false;
+}
+
+int amd_get_subcaches(int cpu)
+{
+	struct pci_dev *link = node_to_amd_nb(amd_get_nb_id(cpu))->link;
+	unsigned int mask;
+	int cuid = 0;
+
+	if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		return 0;
+
+	pci_read_config_dword(link, 0x1d4, &mask);
+
+#ifdef CONFIG_SMP
+	cuid = cpu_data(cpu).compute_unit_id;
+#endif
+	return (mask >> (4 * cuid)) & 0xf;
+}
+
+int amd_set_subcaches(int cpu, int mask)
+{
+	static unsigned int reset, ban;
+	struct amd_northbridge *nb = node_to_amd_nb(amd_get_nb_id(cpu));
+	unsigned int reg;
+	int cuid = 0;
+
+	if (!amd_nb_has_feature(AMD_NB_L3_PARTITIONING) || mask > 0xf)
+		return -EINVAL;
+
+	/* if necessary, collect reset state of L3 partitioning and BAN mode */
+	if (reset == 0) {
+		pci_read_config_dword(nb->link, 0x1d4, &reset);
+		pci_read_config_dword(nb->misc, 0x1b8, &ban);
+		ban &= 0x180000;
+	}
+
+	/* deactivate BAN mode if any subcaches are to be disabled */
+	if (mask != 0xf) {
+		pci_read_config_dword(nb->misc, 0x1b8, &reg);
+		pci_write_config_dword(nb->misc, 0x1b8, reg & ~0x180000);
+	}
+
+#ifdef CONFIG_SMP
+	cuid = cpu_data(cpu).compute_unit_id;
+#endif
+	mask <<= 4 * cuid;
+	mask |= (0xf ^ (1 << cuid)) << 26;
+
+	pci_write_config_dword(nb->link, 0x1d4, mask);
+
+	/* reset BAN mode if L3 partitioning returned to reset state */
+	pci_read_config_dword(nb->link, 0x1d4, &reg);
+	if (reg == reset) {
+		pci_read_config_dword(nb->misc, 0x1b8, &reg);
+		reg &= ~0x180000;
+		pci_write_config_dword(nb->misc, 0x1b8, reg | ban);
+	}
+
 	return 0;
 }
 
-int amd_cache_gart(void)
+static int amd_cache_gart(void)
 {
-       int i;
+	u16 i;
 
        if (!amd_nb_has_feature(AMD_NB_GART))
                return 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apb_timer.c linux-libre-2.6.39-gnu/arch/x86/kernel/apb_timer.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apb_timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apb_timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -316,7 +316,7 @@
 	irq_modify_status(adev->irq, 0, IRQ_MOVE_PCNTXT);
 	irq_set_affinity(adev->irq, cpumask_of(adev->cpu));
 	/* APB timer irqs are set up as mp_irqs, timer is edge type */
-	__set_irq_handler(adev->irq, handle_edge_irq, 0, "edge");
+	__irq_set_handler(adev->irq, handle_edge_irq, 0, "edge");
 
 	if (system_state == SYSTEM_BOOTING) {
 		if (request_irq(adev->irq, apbt_interrupt_handler,
@@ -508,64 +508,12 @@
 	return 0;
 }
 
-/*
- * APB timer clock is not in sync with pclk on Langwell, which translates to
- * unreliable read value caused by sampling error. the error does not add up
- * overtime and only happens when sampling a 0 as a 1 by mistake. so the time
- * would go backwards. the following code is trying to prevent time traveling
- * backwards. little bit paranoid.
- */
 static cycle_t apbt_read_clocksource(struct clocksource *cs)
 {
-	unsigned long t0, t1, t2;
-	static unsigned long last_read;
+	unsigned long current_count;
 
-bad_count:
-	t1 = apbt_readl(phy_cs_timer_id,
-			APBTMR_N_CURRENT_VALUE);
-	t2 = apbt_readl(phy_cs_timer_id,
-			APBTMR_N_CURRENT_VALUE);
-	if (unlikely(t1 < t2)) {
-		pr_debug("APBT: read current count error %lx:%lx:%lx\n",
-			 t1, t2, t2 - t1);
-		goto bad_count;
-	}
-	/*
-	 * check against cached last read, makes sure time does not go back.
-	 * it could be a normal rollover but we will do tripple check anyway
-	 */
-	if (unlikely(t2 > last_read)) {
-		/* check if we have a normal rollover */
-		unsigned long raw_intr_status =
-			apbt_readl_reg(APBTMRS_RAW_INT_STATUS);
-		/*
-		 * cs timer interrupt is masked but raw intr bit is set if
-		 * rollover occurs. then we read EOI reg to clear it.
-		 */
-		if (raw_intr_status & (1 << phy_cs_timer_id)) {
-			apbt_readl(phy_cs_timer_id, APBTMR_N_EOI);
-			goto out;
-		}
-		pr_debug("APB CS going back %lx:%lx:%lx ",
-			 t2, last_read, t2 - last_read);
-bad_count_x3:
-		pr_debug("triple check enforced\n");
-		t0 = apbt_readl(phy_cs_timer_id,
-				APBTMR_N_CURRENT_VALUE);
-		udelay(1);
-		t1 = apbt_readl(phy_cs_timer_id,
-				APBTMR_N_CURRENT_VALUE);
-		udelay(1);
-		t2 = apbt_readl(phy_cs_timer_id,
-				APBTMR_N_CURRENT_VALUE);
-		if ((t2 > t1) || (t1 > t0)) {
-			printk(KERN_ERR "Error: APB CS tripple check failed\n");
-			goto bad_count_x3;
-		}
-	}
-out:
-	last_read = t2;
-	return (cycle_t)~t2;
+	current_count = apbt_readl(phy_cs_timer_id, APBTMR_N_CURRENT_VALUE);
+	return (cycle_t)~current_count;
 }
 
 static int apbt_clocksource_register(void)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/aperture_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/aperture_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/aperture_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/aperture_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
-#include <linux/bootmem.h>
+#include <linux/memblock.h>
 #include <linux/mmzone.h>
 #include <linux/pci_ids.h>
 #include <linux/pci.h>
@@ -57,7 +57,7 @@
 static u32 __init allocate_aperture(void)
 {
 	u32 aper_size;
-	void *p;
+	unsigned long addr;
 
 	/* aper_size should <= 1G */
 	if (fallback_aper_order > 5)
@@ -73,7 +73,7 @@
 	/*
 	 * using 512M as goal, in case kexec will load kernel_big
 	 * that will do the on position decompress, and  could overlap with
-	 * that positon with gart that is used.
+	 * that position with gart that is used.
 	 * sequende:
 	 * kernel_small
 	 * ==> kexec (with kdump trigger path or previous doesn't shutdown gart)
@@ -83,27 +83,26 @@
 	 * so don't use 512M below as gart iommu, leave the space for kernel
 	 * code for safe
 	 */
-	p = __alloc_bootmem_nopanic(aper_size, aper_size, 512ULL<<20);
+	addr = memblock_find_in_range(0, 1ULL<<32, aper_size, 512ULL<<20);
+	if (addr == MEMBLOCK_ERROR || addr + aper_size > 0xffffffff) {
+		printk(KERN_ERR
+			"Cannot allocate aperture memory hole (%lx,%uK)\n",
+				addr, aper_size>>10);
+		return 0;
+	}
+	memblock_x86_reserve_range(addr, addr + aper_size, "aperture64");
 	/*
 	 * Kmemleak should not scan this block as it may not be mapped via the
 	 * kernel direct mapping.
 	 */
-	kmemleak_ignore(p);
-	if (!p || __pa(p)+aper_size > 0xffffffff) {
-		printk(KERN_ERR
-			"Cannot allocate aperture memory hole (%p,%uK)\n",
-				p, aper_size>>10);
-		if (p)
-			free_bootmem(__pa(p), aper_size);
-		return 0;
-	}
+	kmemleak_ignore(phys_to_virt(addr));
 	printk(KERN_INFO "Mapping aperture over %d KB of RAM @ %lx\n",
-			aper_size >> 10, __pa(p));
-	insert_aperture_resource((u32)__pa(p), aper_size);
-	register_nosave_region((u32)__pa(p) >> PAGE_SHIFT,
-				(u32)__pa(p+aper_size) >> PAGE_SHIFT);
+			aper_size >> 10, addr);
+	insert_aperture_resource((u32)addr, aper_size);
+	register_nosave_region(addr >> PAGE_SHIFT,
+			       (addr+aper_size) >> PAGE_SHIFT);
 
-	return (u32)__pa(p);
+	return (u32)addr;
 }
 
 
@@ -500,7 +499,7 @@
 		 * Don't enable translation yet but enable GART IO and CPU
 		 * accesses and set DISTLBWALKPRB since GART table memory is UC.
 		 */
-		u32 ctl = DISTLBWALKPRB | aper_order << 1;
+		u32 ctl = aper_order << 1;
 
 		bus = amd_nb_bus_dev_ranges[i].bus;
 		dev_base = amd_nb_bus_dev_ranges[i].dev_base;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/apic.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/apic.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/apic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/apic.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 #include <linux/ftrace.h>
 #include <linux/ioport.h>
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/delay.h>
 #include <linux/timex.h>
 #include <linux/dmar.h>
@@ -43,6 +43,7 @@
 #include <asm/i8259.h>
 #include <asm/proto.h>
 #include <asm/apic.h>
+#include <asm/io_apic.h>
 #include <asm/desc.h>
 #include <asm/hpet.h>
 #include <asm/idle.h>
@@ -78,12 +79,21 @@
 EXPORT_EARLY_PER_CPU_SYMBOL(x86_bios_cpu_apicid);
 
 #ifdef CONFIG_X86_32
+
+/*
+ * On x86_32, the mapping between cpu and logical apicid may vary
+ * depending on apic in use.  The following early percpu variable is
+ * used for the mapping.  This is where the behaviors of x86_64 and 32
+ * actually diverge.  Let's keep it ugly for now.
+ */
+DEFINE_EARLY_PER_CPU(int, x86_cpu_to_logical_apicid, BAD_APICID);
+
 /*
  * Knob to control our willingness to enable the local APIC.
  *
  * +1=force-enable
  */
-static int force_enable_local_apic;
+static int force_enable_local_apic __initdata;
 /*
  * APIC command line parameters
  */
@@ -153,7 +163,7 @@
 unsigned long mp_lapic_addr;
 int disable_apic;
 /* Disable local APIC timer from the kernel commandline or via dmi quirk */
-static int disable_apic_timer __cpuinitdata;
+static int disable_apic_timer __initdata;
 /* Local APIC timer works in C2 */
 int local_apic_timer_c2_ok;
 EXPORT_SYMBOL_GPL(local_apic_timer_c2_ok);
@@ -177,29 +187,8 @@
 
 static unsigned int calibration_result;
 
-static int lapic_next_event(unsigned long delta,
-			    struct clock_event_device *evt);
-static void lapic_timer_setup(enum clock_event_mode mode,
-			      struct clock_event_device *evt);
-static void lapic_timer_broadcast(const struct cpumask *mask);
 static void apic_pm_activate(void);
 
-/*
- * The local apic timer can be used for any function which is CPU local.
- */
-static struct clock_event_device lapic_clockevent = {
-	.name		= "lapic",
-	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
-			| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
-	.shift		= 32,
-	.set_mode	= lapic_timer_setup,
-	.set_next_event	= lapic_next_event,
-	.broadcast	= lapic_timer_broadcast,
-	.rating		= 100,
-	.irq		= -1,
-};
-static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
-
 static unsigned long apic_phys;
 
 /*
@@ -238,7 +227,7 @@
  * right after this call apic become NOOP driven
  * so apic->write/read doesn't do anything
  */
-void apic_disable(void)
+static void __init apic_disable(void)
 {
 	pr_info("APIC: switched to apic NOOP\n");
 	apic = &apic_noop;
@@ -282,23 +271,6 @@
 	return icr1 | ((u64)icr2 << 32);
 }
 
-/**
- * enable_NMI_through_LVT0 - enable NMI through local vector table 0
- */
-void __cpuinit enable_NMI_through_LVT0(void)
-{
-	unsigned int v;
-
-	/* unmask and set to NMI */
-	v = APIC_DM_NMI;
-
-	/* Level triggered for 82489DX (32bit mode) */
-	if (!lapic_is_integrated())
-		v |= APIC_LVT_LEVEL_TRIGGER;
-
-	apic_write(APIC_LVT0, v);
-}
-
 #ifdef CONFIG_X86_32
 /**
  * get_physical_broadcast - Get number of physical broadcast IDs
@@ -508,6 +480,23 @@
 #endif
 }
 
+
+/*
+ * The local apic timer can be used for any function which is CPU local.
+ */
+static struct clock_event_device lapic_clockevent = {
+	.name		= "lapic",
+	.features	= CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT
+			| CLOCK_EVT_FEAT_C3STOP | CLOCK_EVT_FEAT_DUMMY,
+	.shift		= 32,
+	.set_mode	= lapic_timer_setup,
+	.set_next_event	= lapic_next_event,
+	.broadcast	= lapic_timer_broadcast,
+	.rating		= 100,
+	.irq		= -1,
+};
+static DEFINE_PER_CPU(struct clock_event_device, lapic_events);
+
 /*
  * Setup the local APIC timer for this CPU. Copy the initialized values
  * of the boot CPU and register the clock event in the framework.
@@ -1209,7 +1198,7 @@
 		rdtscll(tsc);
 
 	if (disable_apic) {
-		arch_disable_smp_support();
+		disable_ioapic_support();
 		return;
 	}
 
@@ -1237,6 +1226,19 @@
 	 */
 	apic->init_apic_ldr();
 
+#ifdef CONFIG_X86_32
+	/*
+	 * APIC LDR is initialized.  If logical_apicid mapping was
+	 * initialized during get_smp_config(), make sure it matches the
+	 * actual value.
+	 */
+	i = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+	WARN_ON(i != BAD_APICID && i != logical_smp_processor_id());
+	/* always use the value from LDR */
+	early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+		logical_smp_processor_id();
+#endif
+
 	/*
 	 * Set Task Priority to 'accept all'. We never change this
 	 * later on.
@@ -1448,7 +1450,7 @@
 void __init enable_IR_x2apic(void)
 {
 	unsigned long flags;
-	struct IO_APIC_route_entry **ioapic_entries = NULL;
+	struct IO_APIC_route_entry **ioapic_entries;
 	int ret, x2apic_enabled = 0;
 	int dmar_table_init_ret;
 
@@ -1537,7 +1539,7 @@
 }
 #else
 
-static int apic_verify(void)
+static int __init apic_verify(void)
 {
 	u32 features, h, l;
 
@@ -1562,7 +1564,7 @@
 	return 0;
 }
 
-int apic_force_enable(void)
+int __init apic_force_enable(unsigned long addr)
 {
 	u32 h, l;
 
@@ -1578,7 +1580,7 @@
 	if (!(l & MSR_IA32_APICBASE_ENABLE)) {
 		pr_info("Local APIC disabled by BIOS -- reenabling.\n");
 		l &= ~MSR_IA32_APICBASE_BASE;
-		l |= MSR_IA32_APICBASE_ENABLE | APIC_DEFAULT_PHYS_BASE;
+		l |= MSR_IA32_APICBASE_ENABLE | addr;
 		wrmsr(MSR_IA32_APICBASE, l, h);
 		enabled_via_apicbase = 1;
 	}
@@ -1619,7 +1621,7 @@
 				"you can enable it with \"lapic\"\n");
 			return -1;
 		}
-		if (apic_force_enable())
+		if (apic_force_enable(APIC_DEFAULT_PHYS_BASE))
 			return -1;
 	} else {
 		if (apic_verify())
@@ -1930,17 +1932,6 @@
 {
 	int cpu;
 
-	/*
-	 * Validate version
-	 */
-	if (version == 0x0) {
-		pr_warning("BIOS bug, APIC version is 0 for CPU#%d! "
-			   "fixing up to 0x10. (tell your hw vendor)\n",
-				version);
-		version = 0x10;
-	}
-	apic_version[apicid] = version;
-
 	if (num_processors >= nr_cpu_ids) {
 		int max = nr_cpu_ids;
 		int thiscpu = max + disabled_cpus;
@@ -1954,22 +1945,34 @@
 	}
 
 	num_processors++;
-	cpu = cpumask_next_zero(-1, cpu_present_mask);
-
-	if (version != apic_version[boot_cpu_physical_apicid])
-		WARN_ONCE(1,
-			"ACPI: apic version mismatch, bootcpu: %x cpu %d: %x\n",
-			apic_version[boot_cpu_physical_apicid], cpu, version);
-
-	physid_set(apicid, phys_cpu_present_map);
 	if (apicid == boot_cpu_physical_apicid) {
 		/*
 		 * x86_bios_cpu_apicid is required to have processors listed
 		 * in same order as logical cpu numbers. Hence the first
 		 * entry is BSP, and so on.
+		 * boot_cpu_init() already hold bit 0 in cpu_present_mask
+		 * for BSP.
 		 */
 		cpu = 0;
+	} else
+		cpu = cpumask_next_zero(-1, cpu_present_mask);
+
+	/*
+	 * Validate version
+	 */
+	if (version == 0x0) {
+		pr_warning("BIOS bug: APIC version is 0 for CPU %d/0x%x, fixing up to 0x10\n",
+			   cpu, apicid);
+		version = 0x10;
 	}
+	apic_version[apicid] = version;
+
+	if (version != apic_version[boot_cpu_physical_apicid]) {
+		pr_warning("BIOS bug: APIC version mismatch, boot CPU: %x, CPU %d: version %x\n",
+			apic_version[boot_cpu_physical_apicid], cpu, version);
+	}
+
+	physid_set(apicid, phys_cpu_present_map);
 	if (apicid > max_physical_apicid)
 		max_physical_apicid = apicid;
 
@@ -1977,7 +1980,10 @@
 	early_per_cpu(x86_cpu_to_apicid, cpu) = apicid;
 	early_per_cpu(x86_bios_cpu_apicid, cpu) = apicid;
 #endif
-
+#ifdef CONFIG_X86_32
+	early_per_cpu(x86_cpu_to_logical_apicid, cpu) =
+		apic->x86_32_early_logical_apicid(cpu);
+#endif
 	set_cpu_possible(cpu, true);
 	set_cpu_present(cpu, true);
 }
@@ -1998,10 +2004,14 @@
 }
 
 #ifdef CONFIG_X86_32
-int default_apicid_to_node(int logical_apicid)
+int default_x86_32_numa_cpu_node(int cpu)
 {
-#ifdef CONFIG_SMP
-	return apicid_2_node[hard_smp_processor_id()];
+#ifdef CONFIG_NUMA
+	int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
+
+	if (apicid != BAD_APICID)
+		return __apicid_to_node[apicid];
+	return NUMA_NO_NODE;
 #else
 	return 0;
 #endif
@@ -2036,7 +2046,7 @@
 	unsigned int apic_thmr;
 } apic_pm_state;
 
-static int lapic_suspend(struct sys_device *dev, pm_message_t state)
+static int lapic_suspend(void)
 {
 	unsigned long flags;
 	int maxlvt;
@@ -2074,23 +2084,21 @@
 	return 0;
 }
 
-static int lapic_resume(struct sys_device *dev)
+static void lapic_resume(void)
 {
 	unsigned int l, h;
 	unsigned long flags;
-	int maxlvt;
-	int ret = 0;
+	int maxlvt, ret;
 	struct IO_APIC_route_entry **ioapic_entries = NULL;
 
 	if (!apic_pm_state.active)
-		return 0;
+		return;
 
 	local_irq_save(flags);
 	if (intr_remapping_enabled) {
 		ioapic_entries = alloc_ioapic_entries();
 		if (!ioapic_entries) {
 			WARN(1, "Alloc ioapic_entries in lapic resume failed.");
-			ret = -ENOMEM;
 			goto restore;
 		}
 
@@ -2152,8 +2160,6 @@
 	}
 restore:
 	local_irq_restore(flags);
-
-	return ret;
 }
 
 /*
@@ -2161,17 +2167,11 @@
  * are needed on every CPU up until machine_halt/restart/poweroff.
  */
 
-static struct sysdev_class lapic_sysclass = {
-	.name		= "lapic",
+static struct syscore_ops lapic_syscore_ops = {
 	.resume		= lapic_resume,
 	.suspend	= lapic_suspend,
 };
 
-static struct sys_device device_lapic = {
-	.id	= 0,
-	.cls	= &lapic_sysclass,
-};
-
 static void __cpuinit apic_pm_activate(void)
 {
 	apic_pm_state.active = 1;
@@ -2179,16 +2179,11 @@
 
 static int __init init_lapic_sysfs(void)
 {
-	int error;
-
-	if (!cpu_has_apic)
-		return 0;
 	/* XXX: remove suspend/resume procs if !apic_pm_state.active? */
+	if (cpu_has_apic)
+		register_syscore_ops(&lapic_syscore_ops);
 
-	error = sysdev_class_register(&lapic_sysclass);
-	if (!error)
-		error = sysdev_register(&device_lapic);
-	return error;
+	return 0;
 }
 
 /* local apic needs to resume before other devices access its registers. */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/apic_flat_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/apic_flat_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/apic_flat_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/apic_flat_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,8 +185,6 @@
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
@@ -337,8 +335,6 @@
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/apic_noop.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/apic_noop.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/apic_noop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/apic_noop.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,11 +54,6 @@
 	return 0;
 }
 
-static int noop_cpu_to_logical_apicid(int cpu)
-{
-	return 0;
-}
-
 static int noop_phys_pkg_id(int cpuid_apic, int index_msb)
 {
 	return 0;
@@ -113,12 +108,6 @@
 	cpumask_set_cpu(cpu, retmask);
 }
 
-int noop_apicid_to_node(int logical_apicid)
-{
-	/* we're always on node 0 */
-	return 0;
-}
-
 static u32 noop_apic_read(u32 reg)
 {
 	WARN_ON_ONCE((cpu_has_apic && !disable_apic));
@@ -130,6 +119,14 @@
 	WARN_ON_ONCE(cpu_has_apic && !disable_apic);
 }
 
+#ifdef CONFIG_X86_32
+static int noop_x86_32_numa_cpu_node(int cpu)
+{
+	/* we're always on node 0 */
+	return 0;
+}
+#endif
+
 struct apic apic_noop = {
 	.name				= "noop",
 	.probe				= noop_probe,
@@ -153,9 +150,7 @@
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= noop_apicid_to_node,
 
-	.cpu_to_logical_apicid		= noop_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 
@@ -197,4 +192,9 @@
 	.icr_write			= noop_apic_icr_write,
 	.wait_icr_idle			= noop_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= noop_safe_apic_wait_icr_idle,
+
+#ifdef CONFIG_X86_32
+	.x86_32_early_logical_apicid	= noop_x86_32_early_logical_apicid,
+	.x86_32_numa_cpu_node		= noop_x86_32_numa_cpu_node,
+#endif
 };
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/bigsmp_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/bigsmp_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/bigsmp_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/bigsmp_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,12 @@
 	return 1;
 }
 
+static int bigsmp_early_logical_apicid(int cpu)
+{
+	/* on bigsmp, logical apicid is the same as physical */
+	return early_per_cpu(x86_cpu_to_apicid, cpu);
+}
+
 static inline unsigned long calculate_ldr(int cpu)
 {
 	unsigned long val, id;
@@ -80,11 +86,6 @@
 		nr_ioapics);
 }
 
-static int bigsmp_apicid_to_node(int logical_apicid)
-{
-	return apicid_2_node[hard_smp_processor_id()];
-}
-
 static int bigsmp_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids)
@@ -93,14 +94,6 @@
 	return BAD_APICID;
 }
 
-/* Mapping from cpu number to logical apicid */
-static inline int bigsmp_cpu_to_logical_apicid(int cpu)
-{
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_physical_id(cpu);
-}
-
 static void bigsmp_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
 {
 	/* For clustered we don't have a good way to do this yet - hack */
@@ -115,7 +108,11 @@
 /* As we are using single CPU as destination, pick only one CPU here */
 static unsigned int bigsmp_cpu_mask_to_apicid(const struct cpumask *cpumask)
 {
-	return bigsmp_cpu_to_logical_apicid(cpumask_first(cpumask));
+	int cpu = cpumask_first(cpumask);
+
+	if (cpu < nr_cpu_ids)
+		return cpu_physical_id(cpu);
+	return BAD_APICID;
 }
 
 static unsigned int bigsmp_cpu_mask_to_apicid_and(const struct cpumask *cpumask,
@@ -129,9 +126,9 @@
 	 */
 	for_each_cpu_and(cpu, cpumask, andmask) {
 		if (cpumask_test_cpu(cpu, cpu_online_mask))
-			break;
+			return cpu_physical_id(cpu);
 	}
-	return bigsmp_cpu_to_logical_apicid(cpu);
+	return BAD_APICID;
 }
 
 static int bigsmp_phys_pkg_id(int cpuid_apic, int index_msb)
@@ -219,8 +216,6 @@
 	.ioapic_phys_id_map		= bigsmp_ioapic_phys_id_map,
 	.setup_apic_routing		= bigsmp_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= bigsmp_apicid_to_node,
-	.cpu_to_logical_apicid		= bigsmp_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= bigsmp_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 	.setup_portio_remap		= NULL,
@@ -256,4 +251,7 @@
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= bigsmp_early_logical_apicid,
+	.x86_32_numa_cpu_node		= default_x86_32_numa_cpu_node,
 };
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/es7000_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/es7000_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/es7000_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/es7000_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -460,6 +460,12 @@
 	return physid_isset(bit, phys_cpu_present_map);
 }
 
+static int es7000_early_logical_apicid(int cpu)
+{
+	/* on es7000, logical apicid is the same as physical */
+	return early_per_cpu(x86_bios_cpu_apicid, cpu);
+}
+
 static unsigned long calculate_ldr(int cpu)
 {
 	unsigned long id = per_cpu(x86_bios_cpu_apicid, cpu);
@@ -504,12 +510,11 @@
 		nr_ioapics, cpumask_bits(es7000_target_cpus())[0]);
 }
 
-static int es7000_apicid_to_node(int logical_apicid)
+static int es7000_numa_cpu_node(int cpu)
 {
 	return 0;
 }
 
-
 static int es7000_cpu_present_to_apicid(int mps_cpu)
 {
 	if (!mps_cpu)
@@ -528,18 +533,6 @@
 	++cpu_id;
 }
 
-/* Mapping from cpu number to logical apicid */
-static int es7000_cpu_to_logical_apicid(int cpu)
-{
-#ifdef CONFIG_SMP
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_2_logical_apicid[cpu];
-#else
-	return logical_smp_processor_id();
-#endif
-}
-
 static void es7000_ioapic_phys_id_map(physid_mask_t *phys_map, physid_mask_t *retmap)
 {
 	/* For clustered we don't have a good way to do this yet - hack */
@@ -561,7 +554,7 @@
 	 * The cpus in the mask must all be on the apic cluster.
 	 */
 	for_each_cpu(cpu, cpumask) {
-		int new_apicid = es7000_cpu_to_logical_apicid(cpu);
+		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
 		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
 			WARN(1, "Not a valid mask!");
@@ -578,7 +571,7 @@
 es7000_cpu_mask_to_apicid_and(const struct cpumask *inmask,
 			      const struct cpumask *andmask)
 {
-	int apicid = es7000_cpu_to_logical_apicid(0);
+	int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 	cpumask_var_t cpumask;
 
 	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
@@ -655,8 +648,6 @@
 	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
 	.setup_apic_routing		= es7000_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= es7000_apicid_to_node,
-	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
 	.setup_portio_remap		= NULL,
@@ -695,6 +686,9 @@
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= es7000_early_logical_apicid,
+	.x86_32_numa_cpu_node		= es7000_numa_cpu_node,
 };
 
 struct apic __refdata apic_es7000 = {
@@ -720,8 +714,6 @@
 	.ioapic_phys_id_map		= es7000_ioapic_phys_id_map,
 	.setup_apic_routing		= es7000_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= es7000_apicid_to_node,
-	.cpu_to_logical_apicid		= es7000_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= es7000_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= es7000_apicid_to_cpu_present,
 	.setup_portio_remap		= NULL,
@@ -758,4 +750,7 @@
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= es7000_early_logical_apicid,
+	.x86_32_numa_cpu_node		= es7000_numa_cpu_node,
 };
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/hw_nmi.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/hw_nmi.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/hw_nmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/hw_nmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/kprobes.h>
 #include <linux/nmi.h>
 #include <linux/module.h>
+#include <linux/delay.h>
 
 #ifdef CONFIG_HARDLOCKUP_DETECTOR
 u64 hw_nmi_get_sample_period(void)
@@ -83,7 +84,6 @@
 		arch_spin_lock(&lock);
 		printk(KERN_WARNING "NMI backtrace for cpu %d\n", cpu);
 		show_regs(regs);
-		dump_stack();
 		arch_spin_unlock(&lock);
 		cpumask_clear_cpu(cpu, to_cpumask(backtrace_mask));
 		return NOTIFY_STOP;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/io_apic.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/io_apic.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/io_apic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/io_apic.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 #include <linux/compiler.h>
 #include <linux/acpi.h>
 #include <linux/module.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/msi.h>
 #include <linux/htirq.h>
 #include <linux/freezer.h>
@@ -108,7 +108,10 @@
 
 int skip_ioapic_setup;
 
-void arch_disable_smp_support(void)
+/**
+ * disable_ioapic_support() - disables ioapic support at runtime
+ */
+void disable_ioapic_support(void)
 {
 #ifdef CONFIG_PCI
 	noioapicquirk = 1;
@@ -120,11 +123,14 @@
 static int __init parse_noapic(char *str)
 {
 	/* disable IO-APIC */
-	arch_disable_smp_support();
+	disable_ioapic_support();
 	return 0;
 }
 early_param("noapic", parse_noapic);
 
+static int io_apic_setup_irq_pin(unsigned int irq, int node,
+				 struct io_apic_irq_attr *attr);
+
 /* Will be called in mpparse/acpi/sfi codes for saving IRQ info */
 void mp_save_irq(struct mpc_intsrc *m)
 {
@@ -181,7 +187,7 @@
 	irq_reserve_irqs(0, legacy_pic->nr_legacy_irqs);
 
 	for (i = 0; i < count; i++) {
-		set_irq_chip_data(i, &cfg[i]);
+		irq_set_chip_data(i, &cfg[i]);
 		zalloc_cpumask_var_node(&cfg[i].domain, GFP_KERNEL, node);
 		zalloc_cpumask_var_node(&cfg[i].old_domain, GFP_KERNEL, node);
 		/*
@@ -200,7 +206,7 @@
 #ifdef CONFIG_SPARSE_IRQ
 static struct irq_cfg *irq_cfg(unsigned int irq)
 {
-	return get_irq_chip_data(irq);
+	return irq_get_chip_data(irq);
 }
 
 static struct irq_cfg *alloc_irq_cfg(unsigned int irq, int node)
@@ -226,7 +232,7 @@
 {
 	if (!cfg)
 		return;
-	set_irq_chip_data(at, NULL);
+	irq_set_chip_data(at, NULL);
 	free_cpumask_var(cfg->domain);
 	free_cpumask_var(cfg->old_domain);
 	kfree(cfg);
@@ -256,14 +262,14 @@
 	if (res < 0) {
 		if (res != -EEXIST)
 			return NULL;
-		cfg = get_irq_chip_data(at);
+		cfg = irq_get_chip_data(at);
 		if (cfg)
 			return cfg;
 	}
 
 	cfg = alloc_irq_cfg(at, node);
 	if (cfg)
-		set_irq_chip_data(at, cfg);
+		irq_set_chip_data(at, cfg);
 	else
 		irq_free_desc(at);
 	return cfg;
@@ -818,7 +824,7 @@
 #define default_MCA_trigger(idx)	(1)
 #define default_MCA_polarity(idx)	default_ISA_polarity(idx)
 
-static int MPBIOS_polarity(int idx)
+static int irq_polarity(int idx)
 {
 	int bus = mp_irqs[idx].srcbus;
 	int polarity;
@@ -860,7 +866,7 @@
 	return polarity;
 }
 
-static int MPBIOS_trigger(int idx)
+static int irq_trigger(int idx)
 {
 	int bus = mp_irqs[idx].srcbus;
 	int trigger;
@@ -932,16 +938,6 @@
 	return trigger;
 }
 
-static inline int irq_polarity(int idx)
-{
-	return MPBIOS_polarity(idx);
-}
-
-static inline int irq_trigger(int idx)
-{
-	return MPBIOS_trigger(idx);
-}
-
 static int pin_2_irq(int idx, int apic, int pin)
 {
 	int irq;
@@ -1189,7 +1185,7 @@
 	raw_spin_lock(&vector_lock);
 	/* Mark the inuse vectors */
 	for_each_active_irq(irq) {
-		cfg = get_irq_chip_data(irq);
+		cfg = irq_get_chip_data(irq);
 		if (!cfg)
 			continue;
 		/*
@@ -1220,10 +1216,6 @@
 static struct irq_chip ioapic_chip;
 static struct irq_chip ir_ioapic_chip;
 
-#define IOAPIC_AUTO     -1
-#define IOAPIC_EDGE     0
-#define IOAPIC_LEVEL    1
-
 #ifdef CONFIG_X86_32
 static inline int IO_APIC_irq_trigger(int irq)
 {
@@ -1248,35 +1240,31 @@
 }
 #endif
 
-static void ioapic_register_intr(unsigned int irq, unsigned long trigger)
+static void ioapic_register_intr(unsigned int irq, struct irq_cfg *cfg,
+				 unsigned long trigger)
 {
+	struct irq_chip *chip = &ioapic_chip;
+	irq_flow_handler_t hdl;
+	bool fasteoi;
 
 	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
+	    trigger == IOAPIC_LEVEL) {
 		irq_set_status_flags(irq, IRQ_LEVEL);
-	else
+		fasteoi = true;
+	} else {
 		irq_clear_status_flags(irq, IRQ_LEVEL);
+		fasteoi = false;
+	}
 
-	if (irq_remapped(get_irq_chip_data(irq))) {
+	if (irq_remapped(cfg)) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		if (trigger)
-			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
-						      handle_fasteoi_irq,
-						     "fasteoi");
-		else
-			set_irq_chip_and_handler_name(irq, &ir_ioapic_chip,
-						      handle_edge_irq, "edge");
-		return;
+		chip = &ir_ioapic_chip;
+		fasteoi = trigger != 0;
 	}
 
-	if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
-	    trigger == IOAPIC_LEVEL)
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					      handle_fasteoi_irq,
-					      "fasteoi");
-	else
-		set_irq_chip_and_handler_name(irq, &ioapic_chip,
-					      handle_edge_irq, "edge");
+	hdl = fasteoi ? handle_fasteoi_irq : handle_edge_irq;
+	irq_set_chip_and_handler_name(irq, chip, hdl,
+				      fasteoi ? "fasteoi" : "edge");
 }
 
 static int setup_ioapic_entry(int apic_id, int irq,
@@ -1374,7 +1362,7 @@
 		return;
 	}
 
-	ioapic_register_intr(irq, trigger);
+	ioapic_register_intr(irq, cfg, trigger);
 	if (irq < legacy_pic->nr_legacy_irqs)
 		legacy_pic->mask(irq);
 
@@ -1385,33 +1373,26 @@
 	DECLARE_BITMAP(pin_programmed, MP_MAX_IOAPIC_PIN + 1);
 } mp_ioapic_routing[MAX_IO_APICS];
 
-static void __init setup_IO_APIC_irqs(void)
+static bool __init io_apic_pin_not_connected(int idx, int apic_id, int pin)
 {
-	int apic_id, pin, idx, irq, notcon = 0;
-	int node = cpu_to_node(0);
-	struct irq_cfg *cfg;
+	if (idx != -1)
+		return false;
 
-	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+	apic_printk(APIC_VERBOSE, KERN_DEBUG " apic %d pin %d not connected\n",
+		    mp_ioapics[apic_id].apicid, pin);
+	return true;
+}
+
+static void __init __io_apic_setup_irqs(unsigned int apic_id)
+{
+	int idx, node = cpu_to_node(0);
+	struct io_apic_irq_attr attr;
+	unsigned int pin, irq;
 
-	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
 	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,
-					KERN_DEBUG " %d-%d",
-					mp_ioapics[apic_id].apicid, pin);
-			} else
-				apic_printk(APIC_VERBOSE, " %d-%d",
-					mp_ioapics[apic_id].apicid, pin);
+		if (io_apic_pin_not_connected(idx, apic_id, pin))
 			continue;
-		}
-		if (notcon) {
-			apic_printk(APIC_VERBOSE,
-				" (apicid-pin) not connected\n");
-			notcon = 0;
-		}
 
 		irq = pin_2_irq(idx, apic_id, pin);
 
@@ -1423,25 +1404,24 @@
 		 * installed and if it returns 1:
 		 */
 		if (apic->multi_timer_check &&
-				apic->multi_timer_check(apic_id, irq))
+		    apic->multi_timer_check(apic_id, irq))
 			continue;
 
-		cfg = alloc_irq_and_cfg_at(irq, node);
-		if (!cfg)
-			continue;
+		set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+				     irq_polarity(idx));
 
-		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_ioapic_irq(apic_id, pin, irq, cfg, irq_trigger(idx),
-				  irq_polarity(idx));
+		io_apic_setup_irq_pin(irq, node, &attr);
 	}
+}
 
-	if (notcon)
-		apic_printk(APIC_VERBOSE,
-			" (apicid-pin) not connected\n");
+static void __init setup_IO_APIC_irqs(void)
+{
+	unsigned int apic_id;
+
+	apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
+
+	for (apic_id = 0; apic_id < nr_ioapics; apic_id++)
+		__io_apic_setup_irqs(apic_id);
 }
 
 /*
@@ -1452,7 +1432,7 @@
 void setup_IO_APIC_irq_extra(u32 gsi)
 {
 	int apic_id = 0, pin, idx, irq, node = cpu_to_node(0);
-	struct irq_cfg *cfg;
+	struct io_apic_irq_attr attr;
 
 	/*
 	 * Convert 'gsi' to 'ioapic.pin'.
@@ -1472,21 +1452,10 @@
 	if (apic_id == 0 || irq < NR_IRQS_LEGACY)
 		return;
 
-	cfg = alloc_irq_and_cfg_at(irq, node);
-	if (!cfg)
-		return;
-
-	add_pin_to_irq_node(cfg, node, apic_id, pin);
-
-	if (test_bit(pin, mp_ioapic_routing[apic_id].pin_programmed)) {
-		pr_debug("Pin %d-%d already programmed\n",
-			 mp_ioapics[apic_id].apicid, pin);
-		return;
-	}
-	set_bit(pin, mp_ioapic_routing[apic_id].pin_programmed);
+	set_io_apic_irq_attr(&attr, apic_id, pin, irq_trigger(idx),
+			     irq_polarity(idx));
 
-	setup_ioapic_irq(apic_id, pin, irq, cfg,
-			irq_trigger(idx), irq_polarity(idx));
+	io_apic_setup_irq_pin_once(irq, node, &attr);
 }
 
 /*
@@ -1518,7 +1487,8 @@
 	 * The timer IRQ doesn't have to know that behind the
 	 * scene we may have a 8259A-master in AEOI mode ...
 	 */
-	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
+	irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq,
+				      "edge");
 
 	/*
 	 * Add it to the IO-APIC irq-routing table:
@@ -1625,7 +1595,7 @@
 	for_each_active_irq(irq) {
 		struct irq_pin_list *entry;
 
-		cfg = get_irq_chip_data(irq);
+		cfg = irq_get_chip_data(irq);
 		if (!cfg)
 			continue;
 		entry = cfg->irq_2_pin;
@@ -1916,7 +1886,7 @@
 	 *
 	 * With interrupt-remapping, for now we will use virtual wire A mode,
 	 * as virtual wire B is little complex (need to configure both
-	 * IOAPIC RTE aswell as interrupt-remapping table entry).
+	 * IOAPIC RTE as well as interrupt-remapping table entry).
 	 * As this gets called during crash dump, keep this simple for now.
 	 */
 	if (ioapic_i8259.pin != -1 && !intr_remapping_enabled) {
@@ -2391,7 +2361,7 @@
 
 void irq_force_complete_move(int irq)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 
 	if (!cfg)
 		return;
@@ -2405,7 +2375,7 @@
 static void ack_apic_edge(struct irq_data *data)
 {
 	irq_complete_move(data->chip_data);
-	move_native_irq(data->irq);
+	irq_move_irq(data);
 	ack_APIC_irq();
 }
 
@@ -2462,7 +2432,7 @@
 	irq_complete_move(cfg);
 #ifdef CONFIG_GENERIC_PENDING_IRQ
 	/* If we are moving the irq we need to mask it */
-	if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
+	if (unlikely(irqd_is_setaffinity_pending(data))) {
 		do_unmask_irq = 1;
 		mask_ioapic(cfg);
 	}
@@ -2551,7 +2521,7 @@
 		 * and you can go talk to the chipset vendor about it.
 		 */
 		if (!io_apic_level_ack_pending(cfg))
-			move_masked_irq(irq);
+			irq_move_masked_irq(data);
 		unmask_ioapic(cfg);
 	}
 }
@@ -2614,7 +2584,7 @@
 	 * 0x80, because int 0x80 is hm, kind of importantish. ;)
 	 */
 	for_each_active_irq(irq) {
-		cfg = get_irq_chip_data(irq);
+		cfg = irq_get_chip_data(irq);
 		if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
 			/*
 			 * Hmm.. We don't have an entry for this,
@@ -2625,7 +2595,7 @@
 				legacy_pic->make_irq(irq);
 			else
 				/* Strange. Oh, well.. */
-				set_irq_chip(irq, &no_irq_chip);
+				irq_set_chip(irq, &no_irq_chip);
 		}
 	}
 }
@@ -2665,7 +2635,7 @@
 static void lapic_register_intr(int irq)
 {
 	irq_clear_status_flags(irq, IRQ_LEVEL);
-	set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
+	irq_set_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
 				      "edge");
 }
 
@@ -2749,7 +2719,7 @@
  */
 static inline void __init check_timer(void)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(0);
+	struct irq_cfg *cfg = irq_get_chip_data(0);
 	int node = cpu_to_node(0);
 	int apic1, pin1, apic2, pin2;
 	unsigned long flags;
@@ -2935,7 +2905,7 @@
 }
 
 /*
- *      Called after all the initialization is done. If we didnt find any
+ *      Called after all the initialization is done. If we didn't find any
  *      APIC bugs then we can allow the modify fast path
  */
 
@@ -2948,89 +2918,84 @@
 
 late_initcall(io_apic_bug_finalize);
 
-struct sysfs_ioapic_data {
-	struct sys_device dev;
-	struct IO_APIC_route_entry entry[0];
-};
-static struct sysfs_ioapic_data * mp_ioapic_data[MAX_IO_APICS];
+static struct IO_APIC_route_entry *ioapic_saved_data[MAX_IO_APICS];
 
-static int ioapic_suspend(struct sys_device *dev, pm_message_t state)
+static void suspend_ioapic(int ioapic_id)
 {
-	struct IO_APIC_route_entry *entry;
-	struct sysfs_ioapic_data *data;
+	struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id];
 	int i;
 
-	data = container_of(dev, struct sysfs_ioapic_data, dev);
-	entry = data->entry;
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i ++, entry ++ )
-		*entry = ioapic_read_entry(dev->id, i);
+	if (!saved_data)
+		return;
+
+	for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++)
+		saved_data[i] = ioapic_read_entry(ioapic_id, i);
+}
+
+static int ioapic_suspend(void)
+{
+	int ioapic_id;
+
+	for (ioapic_id = 0; ioapic_id < nr_ioapics; ioapic_id++)
+		suspend_ioapic(ioapic_id);
 
 	return 0;
 }
 
-static int ioapic_resume(struct sys_device *dev)
+static void resume_ioapic(int ioapic_id)
 {
-	struct IO_APIC_route_entry *entry;
-	struct sysfs_ioapic_data *data;
+	struct IO_APIC_route_entry *saved_data = ioapic_saved_data[ioapic_id];
 	unsigned long flags;
 	union IO_APIC_reg_00 reg_00;
 	int i;
 
-	data = container_of(dev, struct sysfs_ioapic_data, dev);
-	entry = data->entry;
+	if (!saved_data)
+		return;
 
 	raw_spin_lock_irqsave(&ioapic_lock, flags);
-	reg_00.raw = io_apic_read(dev->id, 0);
-	if (reg_00.bits.ID != mp_ioapics[dev->id].apicid) {
-		reg_00.bits.ID = mp_ioapics[dev->id].apicid;
-		io_apic_write(dev->id, 0, reg_00.raw);
+	reg_00.raw = io_apic_read(ioapic_id, 0);
+	if (reg_00.bits.ID != mp_ioapics[ioapic_id].apicid) {
+		reg_00.bits.ID = mp_ioapics[ioapic_id].apicid;
+		io_apic_write(ioapic_id, 0, reg_00.raw);
 	}
 	raw_spin_unlock_irqrestore(&ioapic_lock, flags);
-	for (i = 0; i < nr_ioapic_registers[dev->id]; i++)
-		ioapic_write_entry(dev->id, i, entry[i]);
+	for (i = 0; i < nr_ioapic_registers[ioapic_id]; i++)
+		ioapic_write_entry(ioapic_id, i, saved_data[i]);
+}
 
-	return 0;
+static void ioapic_resume(void)
+{
+	int ioapic_id;
+
+	for (ioapic_id = nr_ioapics - 1; ioapic_id >= 0; ioapic_id--)
+		resume_ioapic(ioapic_id);
 }
 
-static struct sysdev_class ioapic_sysdev_class = {
-	.name = "ioapic",
+static struct syscore_ops ioapic_syscore_ops = {
 	.suspend = ioapic_suspend,
 	.resume = ioapic_resume,
 };
 
-static int __init ioapic_init_sysfs(void)
+static int __init ioapic_init_ops(void)
 {
-	struct sys_device * dev;
-	int i, size, error;
+	int i;
 
-	error = sysdev_class_register(&ioapic_sysdev_class);
-	if (error)
-		return error;
+	for (i = 0; i < nr_ioapics; i++) {
+		unsigned int size;
 
-	for (i = 0; i < nr_ioapics; i++ ) {
-		size = sizeof(struct sys_device) + nr_ioapic_registers[i]
+		size = nr_ioapic_registers[i]
 			* sizeof(struct IO_APIC_route_entry);
-		mp_ioapic_data[i] = kzalloc(size, GFP_KERNEL);
-		if (!mp_ioapic_data[i]) {
-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-			continue;
-		}
-		dev = &mp_ioapic_data[i]->dev;
-		dev->id = i;
-		dev->cls = &ioapic_sysdev_class;
-		error = sysdev_register(dev);
-		if (error) {
-			kfree(mp_ioapic_data[i]);
-			mp_ioapic_data[i] = NULL;
-			printk(KERN_ERR "Can't suspend/resume IOAPIC %d\n", i);
-			continue;
-		}
+		ioapic_saved_data[i] = kzalloc(size, GFP_KERNEL);
+		if (!ioapic_saved_data[i])
+			pr_err("IOAPIC %d: suspend/resume impossible!\n", i);
 	}
 
+	register_syscore_ops(&ioapic_syscore_ops);
+
 	return 0;
 }
 
-device_initcall(ioapic_init_sysfs);
+device_initcall(ioapic_init_ops);
 
 /*
  * Dynamic irq allocate and deallocation
@@ -3060,7 +3025,7 @@
 	raw_spin_unlock_irqrestore(&vector_lock, flags);
 
 	if (ret) {
-		set_irq_chip_data(irq, cfg);
+		irq_set_chip_data(irq, cfg);
 		irq_clear_status_flags(irq, IRQ_NOREQUEST);
 	} else {
 		free_irq_at(irq, cfg);
@@ -3085,7 +3050,7 @@
 
 void destroy_irq(unsigned int irq)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 	unsigned long flags;
 
 	irq_set_status_flags(irq, IRQ_NOREQUEST|IRQ_NOPROBE);
@@ -3119,7 +3084,7 @@
 
 	dest = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus());
 
-	if (irq_remapped(get_irq_chip_data(irq))) {
+	if (irq_remapped(cfg)) {
 		struct irte irte;
 		int ir_index;
 		u16 sub_handle;
@@ -3291,6 +3256,7 @@
 
 static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
 {
+	struct irq_chip *chip = &msi_chip;
 	struct msi_msg msg;
 	int ret;
 
@@ -3298,14 +3264,15 @@
 	if (ret < 0)
 		return ret;
 
-	set_irq_msi(irq, msidesc);
+	irq_set_msi_desc(irq, msidesc);
 	write_msi_msg(irq, &msg);
 
-	if (irq_remapped(get_irq_chip_data(irq))) {
+	if (irq_remapped(irq_get_chip_data(irq))) {
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-		set_irq_chip_and_handler_name(irq, &msi_ir_chip, handle_edge_irq, "edge");
-	} else
-		set_irq_chip_and_handler_name(irq, &msi_chip, handle_edge_irq, "edge");
+		chip = &msi_ir_chip;
+	}
+
+	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 
 	dev_printk(KERN_DEBUG, &dev->dev, "irq %d for MSI/MSI-X\n", irq);
 
@@ -3423,8 +3390,8 @@
 	if (ret < 0)
 		return ret;
 	dmar_msi_write(irq, &msg);
-	set_irq_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
-		"edge");
+	irq_set_chip_and_handler_name(irq, &dmar_msi_type, handle_edge_irq,
+				      "edge");
 	return 0;
 }
 #endif
@@ -3482,6 +3449,7 @@
 
 int arch_setup_hpet_msi(unsigned int irq, unsigned int id)
 {
+	struct irq_chip *chip = &hpet_msi_type;
 	struct msi_msg msg;
 	int ret;
 
@@ -3501,15 +3469,12 @@
 	if (ret < 0)
 		return ret;
 
-	hpet_msi_write(get_irq_data(irq), &msg);
+	hpet_msi_write(irq_get_handler_data(irq), &msg);
 	irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
-	if (irq_remapped(get_irq_chip_data(irq)))
-		set_irq_chip_and_handler_name(irq, &ir_hpet_msi_type,
-					      handle_edge_irq, "edge");
-	else
-		set_irq_chip_and_handler_name(irq, &hpet_msi_type,
-					      handle_edge_irq, "edge");
+	if (irq_remapped(irq_get_chip_data(irq)))
+		chip = &ir_hpet_msi_type;
 
+	irq_set_chip_and_handler_name(irq, chip, handle_edge_irq, "edge");
 	return 0;
 }
 #endif
@@ -3596,7 +3561,7 @@
 
 		write_ht_irq_msg(irq, &msg);
 
-		set_irq_chip_and_handler_name(irq, &ht_irq_chip,
+		irq_set_chip_and_handler_name(irq, &ht_irq_chip,
 					      handle_edge_irq, "edge");
 
 		dev_printk(KERN_DEBUG, &dev->dev, "irq %d for HT\n", irq);
@@ -3605,7 +3570,40 @@
 }
 #endif /* CONFIG_HT_IRQ */
 
-int __init io_apic_get_redir_entries (int ioapic)
+static int
+io_apic_setup_irq_pin(unsigned int irq, int node, struct io_apic_irq_attr *attr)
+{
+	struct irq_cfg *cfg = alloc_irq_and_cfg_at(irq, node);
+	int ret;
+
+	if (!cfg)
+		return -EINVAL;
+	ret = __add_pin_to_irq_node(cfg, node, attr->ioapic, attr->ioapic_pin);
+	if (!ret)
+		setup_ioapic_irq(attr->ioapic, attr->ioapic_pin, irq, cfg,
+				 attr->trigger, attr->polarity);
+	return ret;
+}
+
+int io_apic_setup_irq_pin_once(unsigned int irq, int node,
+			       struct io_apic_irq_attr *attr)
+{
+	unsigned int id = attr->ioapic, pin = attr->ioapic_pin;
+	int ret;
+
+	/* Avoid redundant programming */
+	if (test_bit(pin, mp_ioapic_routing[id].pin_programmed)) {
+		pr_debug("Pin %d-%d already programmed\n",
+			 mp_ioapics[id].apicid, pin);
+		return 0;
+	}
+	ret = io_apic_setup_irq_pin(irq, node, attr);
+	if (!ret)
+		set_bit(pin, mp_ioapic_routing[id].pin_programmed);
+	return ret;
+}
+
+static int __init io_apic_get_redir_entries(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3659,96 +3657,24 @@
 }
 #endif
 
-static int __io_apic_set_pci_routing(struct device *dev, int irq,
-				struct io_apic_irq_attr *irq_attr)
+int io_apic_set_pci_routing(struct device *dev, int irq,
+			    struct io_apic_irq_attr *irq_attr)
 {
-	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);
+			    irq_attr->ioapic);
 		return -EINVAL;
 	}
 
-	if (dev)
-		node = dev_to_node(dev);
-	else
-		node = cpu_to_node(0);
-
-	cfg = alloc_irq_and_cfg_at(irq, node);
-	if (!cfg)
-		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 >= legacy_pic->nr_legacy_irqs) {
-		if (__add_pin_to_irq_node(cfg, node, ioapic, pin)) {
-			printk(KERN_INFO "can not add pin %d for irq %d\n",
-				pin, irq);
-			return 0;
-		}
-	}
-
-	setup_ioapic_irq(ioapic, pin, irq, cfg, 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);
-}
-
-u8 __init io_apic_unique_id(u8 id)
-{
-#ifdef CONFIG_X86_32
-	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
-	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
-		return io_apic_get_unique_id(nr_ioapics, id);
-	else
-		return id;
-#else
-	int i;
-	DECLARE_BITMAP(used, 256);
+	node = dev ? dev_to_node(dev) : cpu_to_node(0);
 
-	bitmap_zero(used, 256);
-	for (i = 0; i < nr_ioapics; i++) {
-		struct mpc_ioapic *ia = &mp_ioapics[i];
-		__set_bit(ia->apicid, used);
-	}
-	if (!test_bit(id, used))
-		return id;
-	return find_first_zero_bit(used, 256);
-#endif
+	return io_apic_setup_irq_pin_once(irq, node, irq_attr);
 }
 
 #ifdef CONFIG_X86_32
-int __init io_apic_get_unique_id(int ioapic, int apic_id)
+static int __init io_apic_get_unique_id(int ioapic, int apic_id)
 {
 	union IO_APIC_reg_00 reg_00;
 	static physid_mask_t apic_id_map = PHYSID_MASK_NONE;
@@ -3821,9 +3747,33 @@
 
 	return apic_id;
 }
+
+static u8 __init io_apic_unique_id(u8 id)
+{
+	if ((boot_cpu_data.x86_vendor == X86_VENDOR_INTEL) &&
+	    !APIC_XAPIC(apic_version[boot_cpu_physical_apicid]))
+		return io_apic_get_unique_id(nr_ioapics, id);
+	else
+		return id;
+}
+#else
+static u8 __init io_apic_unique_id(u8 id)
+{
+	int i;
+	DECLARE_BITMAP(used, 256);
+
+	bitmap_zero(used, 256);
+	for (i = 0; i < nr_ioapics; i++) {
+		struct mpc_ioapic *ia = &mp_ioapics[i];
+		__set_bit(ia->apicid, used);
+	}
+	if (!test_bit(id, used))
+		return id;
+	return find_first_zero_bit(used, 256);
+}
 #endif
 
-int __init io_apic_get_version(int ioapic)
+static int __init io_apic_get_version(int ioapic)
 {
 	union IO_APIC_reg_01	reg_01;
 	unsigned long flags;
@@ -3868,8 +3818,8 @@
 void __init setup_ioapic_dest(void)
 {
 	int pin, ioapic, irq, irq_entry;
-	struct irq_desc *desc;
 	const struct cpumask *mask;
+	struct irq_data *idata;
 
 	if (skip_ioapic_setup == 1)
 		return;
@@ -3884,21 +3834,20 @@
 		if ((ioapic > 0) && (irq > 16))
 			continue;
 
-		desc = irq_to_desc(irq);
+		idata = irq_get_irq_data(irq);
 
 		/*
 		 * Honour affinities which have been set in early boot
 		 */
-		if (desc->status &
-		    (IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
-			mask = desc->irq_data.affinity;
+		if (!irqd_can_balance(idata) || irqd_affinity_was_set(idata))
+			mask = idata->affinity;
 		else
 			mask = apic->target_cpus();
 
 		if (intr_remapping_enabled)
-			ir_ioapic_set_affinity(&desc->irq_data, mask, false);
+			ir_ioapic_set_affinity(idata, mask, false);
 		else
-			ioapic_set_affinity(&desc->irq_data, mask, false);
+			ioapic_set_affinity(idata, mask, false);
 	}
 
 }
@@ -4026,10 +3975,10 @@
 	return gsi - mp_gsi_routing[ioapic].gsi_base;
 }
 
-static int bad_ioapic(unsigned long address)
+static __init int bad_ioapic(unsigned long address)
 {
 	if (nr_ioapics >= MAX_IO_APICS) {
-		printk(KERN_WARNING "WARING: Max # of I/O APICs (%d) exceeded "
+		printk(KERN_WARNING "WARNING: Max # of I/O APICs (%d) exceeded "
 		       "(found %d), skipping\n", MAX_IO_APICS, nr_ioapics);
 		return 1;
 	}
@@ -4086,20 +4035,16 @@
 /* Enable IOAPIC early just for system timer */
 void __init pre_init_apic_IRQ0(void)
 {
-	struct irq_cfg *cfg;
+	struct io_apic_irq_attr attr = { 0, 0, 0, 0 };
 
 	printk(KERN_INFO "Early APIC setup for system timer0\n");
 #ifndef CONFIG_SMP
 	physid_set_mask_of_physid(boot_cpu_physical_apicid,
 					 &phys_cpu_present_map);
 #endif
-	/* Make sure the irq descriptor is set up */
-	cfg = alloc_irq_and_cfg_at(0, 0);
-
 	setup_local_APIC();
 
-	add_pin_to_irq_node(cfg, 0, 0, 0);
-	set_irq_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq, "edge");
-
-	setup_ioapic_irq(0, 0, 0, cfg, 0, 0);
+	io_apic_setup_irq_pin(0, 0, &attr);
+	irq_set_chip_and_handler_name(0, &ioapic_chip, handle_edge_irq,
+				      "edge");
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/ipi.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/ipi.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/ipi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/ipi.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,6 +56,8 @@
 	local_irq_restore(flags);
 }
 
+#ifdef CONFIG_X86_32
+
 void default_send_IPI_mask_sequence_logical(const struct cpumask *mask,
 						 int vector)
 {
@@ -71,8 +73,8 @@
 	local_irq_save(flags);
 	for_each_cpu(query_cpu, mask)
 		__default_send_IPI_dest_field(
-			apic->cpu_to_logical_apicid(query_cpu), vector,
-			apic->dest_logical);
+			early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+			vector, apic->dest_logical);
 	local_irq_restore(flags);
 }
 
@@ -90,14 +92,12 @@
 		if (query_cpu == this_cpu)
 			continue;
 		__default_send_IPI_dest_field(
-			apic->cpu_to_logical_apicid(query_cpu), vector,
-			apic->dest_logical);
+			early_per_cpu(x86_cpu_to_logical_apicid, query_cpu),
+			vector, apic->dest_logical);
 		}
 	local_irq_restore(flags);
 }
 
-#ifdef CONFIG_X86_32
-
 /*
  * This is only used on smaller machines.
  */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/numaq_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/numaq_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/numaq_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/numaq_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -373,13 +373,6 @@
 	return physids_promote(0xFUL, retmap);
 }
 
-static inline int numaq_cpu_to_logical_apicid(int cpu)
-{
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_2_logical_apicid[cpu];
-}
-
 /*
  * Supporting over 60 cpus on NUMA-Q requires a locality-dependent
  * cpu to APIC ID relation to properly interact with the intelligent
@@ -398,6 +391,15 @@
 	return logical_apicid >> 4;
 }
 
+static int numaq_numa_cpu_node(int cpu)
+{
+	int logical_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+
+	if (logical_apicid != BAD_APICID)
+		return numaq_apicid_to_node(logical_apicid);
+	return NUMA_NO_NODE;
+}
+
 static void numaq_apicid_to_cpu_present(int logical_apicid, physid_mask_t *retmap)
 {
 	int node = numaq_apicid_to_node(logical_apicid);
@@ -508,8 +510,6 @@
 	.ioapic_phys_id_map		= numaq_ioapic_phys_id_map,
 	.setup_apic_routing		= numaq_setup_apic_routing,
 	.multi_timer_check		= numaq_multi_timer_check,
-	.apicid_to_node			= numaq_apicid_to_node,
-	.cpu_to_logical_apicid		= numaq_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= numaq_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= numaq_apicid_to_cpu_present,
 	.setup_portio_remap		= numaq_setup_portio_remap,
@@ -547,4 +547,7 @@
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= noop_x86_32_early_logical_apicid,
+	.x86_32_numa_cpu_node		= numaq_numa_cpu_node,
 };
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/probe_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/probe_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/probe_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/probe_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -77,6 +77,11 @@
 		apic->setup_apic_routing();
 }
 
+static int default_x86_32_early_logical_apicid(int cpu)
+{
+	return 1 << cpu;
+}
+
 static void setup_apic_flat_routing(void)
 {
 #ifdef CONFIG_X86_IO_APIC
@@ -130,8 +135,6 @@
 	.ioapic_phys_id_map		= default_ioapic_phys_id_map,
 	.setup_apic_routing		= setup_apic_flat_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= default_apicid_to_node,
-	.cpu_to_logical_apicid		= default_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= physid_set_mask_of_physid,
 	.setup_portio_remap		= NULL,
@@ -167,6 +170,9 @@
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= default_x86_32_early_logical_apicid,
+	.x86_32_numa_cpu_node		= default_x86_32_numa_cpu_node,
 };
 
 extern struct apic apic_numaq;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/summit_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/summit_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/summit_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/summit_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -194,11 +194,10 @@
 	return 1;
 }
 
-static void summit_init_apic_ldr(void)
+static int summit_early_logical_apicid(int cpu)
 {
-	unsigned long val, id;
 	int count = 0;
-	u8 my_id = (u8)hard_smp_processor_id();
+	u8 my_id = early_per_cpu(x86_cpu_to_apicid, cpu);
 	u8 my_cluster = APIC_CLUSTER(my_id);
 #ifdef CONFIG_SMP
 	u8 lid;
@@ -206,7 +205,7 @@
 
 	/* Create logical APIC IDs by counting CPUs already in cluster. */
 	for (count = 0, i = nr_cpu_ids; --i >= 0; ) {
-		lid = cpu_2_logical_apicid[i];
+		lid = early_per_cpu(x86_cpu_to_logical_apicid, i);
 		if (lid != BAD_APICID && APIC_CLUSTER(lid) == my_cluster)
 			++count;
 	}
@@ -214,7 +213,15 @@
 	/* We only have a 4 wide bitmap in cluster mode.  If a deranged
 	 * BIOS puts 5 CPUs in one APIC cluster, we're hosed. */
 	BUG_ON(count >= XAPIC_DEST_CPUS_SHIFT);
-	id = my_cluster | (1UL << count);
+	return my_cluster | (1UL << count);
+}
+
+static void summit_init_apic_ldr(void)
+{
+	int cpu = smp_processor_id();
+	unsigned long id = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
+	unsigned long val;
+
 	apic_write(APIC_DFR, SUMMIT_APIC_DFR_VALUE);
 	val = apic_read(APIC_LDR) & ~APIC_LDR_MASK;
 	val |= SET_APIC_LOGICAL_ID(id);
@@ -232,27 +239,6 @@
 						nr_ioapics);
 }
 
-static int summit_apicid_to_node(int logical_apicid)
-{
-#ifdef CONFIG_SMP
-	return apicid_2_node[hard_smp_processor_id()];
-#else
-	return 0;
-#endif
-}
-
-/* Mapping from cpu number to logical apicid */
-static inline int summit_cpu_to_logical_apicid(int cpu)
-{
-#ifdef CONFIG_SMP
-	if (cpu >= nr_cpu_ids)
-		return BAD_APICID;
-	return cpu_2_logical_apicid[cpu];
-#else
-	return logical_smp_processor_id();
-#endif
-}
-
 static int summit_cpu_present_to_apicid(int mps_cpu)
 {
 	if (mps_cpu < nr_cpu_ids)
@@ -286,7 +272,7 @@
 	 * The cpus in the mask must all be on the apic cluster.
 	 */
 	for_each_cpu(cpu, cpumask) {
-		int new_apicid = summit_cpu_to_logical_apicid(cpu);
+		int new_apicid = early_per_cpu(x86_cpu_to_logical_apicid, cpu);
 
 		if (round && APIC_CLUSTER(apicid) != APIC_CLUSTER(new_apicid)) {
 			printk("%s: Not a valid mask!\n", __func__);
@@ -301,7 +287,7 @@
 static unsigned int summit_cpu_mask_to_apicid_and(const struct cpumask *inmask,
 			      const struct cpumask *andmask)
 {
-	int apicid = summit_cpu_to_logical_apicid(0);
+	int apicid = early_per_cpu(x86_cpu_to_logical_apicid, 0);
 	cpumask_var_t cpumask;
 
 	if (!alloc_cpumask_var(&cpumask, GFP_ATOMIC))
@@ -528,8 +514,6 @@
 	.ioapic_phys_id_map		= summit_ioapic_phys_id_map,
 	.setup_apic_routing		= summit_setup_apic_routing,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= summit_apicid_to_node,
-	.cpu_to_logical_apicid		= summit_cpu_to_logical_apicid,
 	.cpu_present_to_apicid		= summit_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= summit_apicid_to_cpu_present,
 	.setup_portio_remap		= NULL,
@@ -565,4 +549,7 @@
 	.icr_write			= native_apic_icr_write,
 	.wait_icr_idle			= native_apic_wait_icr_idle,
 	.safe_wait_icr_idle		= native_safe_apic_wait_icr_idle,
+
+	.x86_32_early_logical_apicid	= summit_early_logical_apicid,
+	.x86_32_numa_cpu_node		= default_x86_32_numa_cpu_node,
 };
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/x2apic_cluster.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/x2apic_cluster.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/x2apic_cluster.c	2011-05-19 00:06:34.000000000 -0400
@@ -206,8 +206,6 @@
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/x2apic_phys.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/x2apic_phys.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/x2apic_phys.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/x2apic_phys.c	2011-05-19 00:06:34.000000000 -0400
@@ -195,8 +195,6 @@
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apic/x2apic_uv_x.c linux-libre-2.6.39-gnu/arch/x86/kernel/apic/x2apic_uv_x.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apic/x2apic_uv_x.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,8 @@
 #include <linux/io.h>
 #include <linux/pci.h>
 #include <linux/kdebug.h>
+#include <linux/delay.h>
+#include <linux/crash_dump.h>
 
 #include <asm/uv/uv_mmrs.h>
 #include <asm/uv/uv_hub.h>
@@ -34,6 +36,14 @@
 #include <asm/ipi.h>
 #include <asm/smp.h>
 #include <asm/x86_init.h>
+#include <asm/emergency-restart.h>
+#include <asm/nmi.h>
+
+/* BMC sets a bit this MMR non-zero before sending an NMI */
+#define UVH_NMI_MMR				UVH_SCRATCH5
+#define UVH_NMI_MMR_CLEAR			(UVH_NMI_MMR + 8)
+#define UV_NMI_PENDING_MASK			(1UL << 63)
+DEFINE_PER_CPU(unsigned long, cpu_last_nmi_count);
 
 DEFINE_PER_CPU(int, x2apic_extra_bits);
 
@@ -338,8 +348,6 @@
 	.ioapic_phys_id_map		= NULL,
 	.setup_apic_routing		= NULL,
 	.multi_timer_check		= NULL,
-	.apicid_to_node			= NULL,
-	.cpu_to_logical_apicid		= NULL,
 	.cpu_present_to_apicid		= default_cpu_present_to_apicid,
 	.apicid_to_cpu_present		= NULL,
 	.setup_portio_remap		= NULL,
@@ -641,18 +649,46 @@
  */
 int uv_handle_nmi(struct notifier_block *self, unsigned long reason, void *data)
 {
+	unsigned long real_uv_nmi;
+	int bid;
+
 	if (reason != DIE_NMIUNKNOWN)
 		return NOTIFY_OK;
 
 	if (in_crash_kexec)
 		/* do nothing if entering the crash kernel */
 		return NOTIFY_OK;
+
 	/*
-	 * Use a lock so only one cpu prints at a time
-	 * to prevent intermixed output.
+	 * Each blade has an MMR that indicates when an NMI has been sent
+	 * to cpus on the blade. If an NMI is detected, atomically
+	 * clear the MMR and update a per-blade NMI count used to
+	 * cause each cpu on the blade to notice a new NMI.
+	 */
+	bid = uv_numa_blade_id();
+	real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
+
+	if (unlikely(real_uv_nmi)) {
+		spin_lock(&uv_blade_info[bid].nmi_lock);
+		real_uv_nmi = (uv_read_local_mmr(UVH_NMI_MMR) & UV_NMI_PENDING_MASK);
+		if (real_uv_nmi) {
+			uv_blade_info[bid].nmi_count++;
+			uv_write_local_mmr(UVH_NMI_MMR_CLEAR, UV_NMI_PENDING_MASK);
+		}
+		spin_unlock(&uv_blade_info[bid].nmi_lock);
+	}
+
+	if (likely(__get_cpu_var(cpu_last_nmi_count) == uv_blade_info[bid].nmi_count))
+		return NOTIFY_DONE;
+
+	__get_cpu_var(cpu_last_nmi_count) = uv_blade_info[bid].nmi_count;
+
+	/*
+	 * Use a lock so only one cpu prints at a time.
+	 * This prevents intermixed output.
 	 */
 	spin_lock(&uv_nmi_lock);
-	pr_info("NMI stack dump cpu %u:\n", smp_processor_id());
+	pr_info("UV NMI stack dump cpu %u:\n", smp_processor_id());
 	dump_stack();
 	spin_unlock(&uv_nmi_lock);
 
@@ -660,7 +696,8 @@
 }
 
 static struct notifier_block uv_dump_stack_nmi_nb = {
-	.notifier_call	= uv_handle_nmi
+	.notifier_call	= uv_handle_nmi,
+	.priority = NMI_LOCAL_LOW_PRIOR - 1,
 };
 
 void uv_register_nmi_notifier(void)
@@ -719,8 +756,9 @@
 	printk(KERN_DEBUG "UV: Found %d blades\n", uv_num_possible_blades());
 
 	bytes = sizeof(struct uv_blade_info) * uv_num_possible_blades();
-	uv_blade_info = kmalloc(bytes, GFP_KERNEL);
+	uv_blade_info = kzalloc(bytes, GFP_KERNEL);
 	BUG_ON(!uv_blade_info);
+
 	for (blade = 0; blade < uv_num_possible_blades(); blade++)
 		uv_blade_info[blade].memory_nid = -1;
 
@@ -746,6 +784,7 @@
 			uv_blade_info[blade].pnode = pnode;
 			uv_blade_info[blade].nr_possible_cpus = 0;
 			uv_blade_info[blade].nr_online_cpus = 0;
+			spin_lock_init(&uv_blade_info[blade].nmi_lock);
 			max_pnode = max(pnode, max_pnode);
 			blade++;
 		}
@@ -812,4 +851,11 @@
 
 	/* register Legacy VGA I/O redirection handler */
 	pci_register_set_vga_state(uv_set_vga_state);
+
+	/*
+	 * For a kdump kernel the reset must be BOOT_ACPI, not BOOT_EFI, as
+	 * EFI is not enabled in the kdump kernel.
+	 */
+	if (is_kdump_kernel())
+		reboot_type = BOOT_ACPI;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/apm_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/apm_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/apm_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/apm_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
  *    1.5: Fix segment register reloading (in case of bad segments saved
  *         across BIOS call).
  *         Stephen Rothwell
- *    1.6: Cope with complier/assembler differences.
+ *    1.6: Cope with compiler/assembler differences.
  *         Only try to turn off the first display device.
  *         Fix OOPS at power off with no APM BIOS by Jan Echternach
  *                   <echter@informatik.uni-rostock.de>
@@ -227,6 +227,8 @@
 #include <linux/suspend.h>
 #include <linux/kthread.h>
 #include <linux/jiffies.h>
+#include <linux/acpi.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
@@ -975,20 +977,10 @@
 
 static void apm_power_off(void)
 {
-	unsigned char po_bios_call[] = {
-		0xb8, 0x00, 0x10,	/* movw  $0x1000,ax  */
-		0x8e, 0xd0,		/* movw  ax,ss       */
-		0xbc, 0x00, 0xf0,	/* movw  $0xf000,sp  */
-		0xb8, 0x07, 0x53,	/* movw  $0x5307,ax  */
-		0xbb, 0x01, 0x00,	/* movw  $0x0001,bx  */
-		0xb9, 0x03, 0x00,	/* movw  $0x0003,cx  */
-		0xcd, 0x15		/* int   $0x15       */
-	};
-
 	/* Some bioses don't like being called from CPU != 0 */
 	if (apm_info.realmode_power_off) {
 		set_cpus_allowed_ptr(current, cpumask_of(0));
-		machine_real_restart(po_bios_call, sizeof(po_bios_call));
+		machine_real_restart(MRR_APM);
 	} else {
 		(void)set_system_power_state(APM_STATE_OFF);
 	}
@@ -1247,6 +1239,7 @@
 
 	local_irq_disable();
 	sysdev_suspend(PMSG_SUSPEND);
+	syscore_suspend();
 
 	local_irq_enable();
 
@@ -1264,6 +1257,7 @@
 		apm_error("suspend", err);
 	err = (err == APM_SUCCESS) ? 0 : -EIO;
 
+	syscore_resume();
 	sysdev_resume();
 	local_irq_enable();
 
@@ -1289,6 +1283,7 @@
 
 	local_irq_disable();
 	sysdev_suspend(PMSG_SUSPEND);
+	syscore_suspend();
 	local_irq_enable();
 
 	err = set_system_power_state(APM_STATE_STANDBY);
@@ -1296,6 +1291,7 @@
 		apm_error("standby", err);
 
 	local_irq_disable();
+	syscore_resume();
 	sysdev_resume();
 	local_irq_enable();
 
@@ -2331,12 +2327,11 @@
 		apm_info.disabled = 1;
 		return -ENODEV;
 	}
-	if (pm_flags & PM_ACPI) {
+	if (!acpi_disabled) {
 		printk(KERN_NOTICE "apm: overridden by ACPI.\n");
 		apm_info.disabled = 1;
 		return -ENODEV;
 	}
-	pm_flags |= PM_APM;
 
 	/*
 	 * Set up the long jump entry point to the APM BIOS, which is called
@@ -2428,7 +2423,6 @@
 		kthread_stop(kapmd_task);
 		kapmd_task = NULL;
 	}
-	pm_flags &= ~PM_APM;
 }
 
 module_init(apm_init);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/asm-offsets_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/asm-offsets_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/asm-offsets_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/asm-offsets_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,26 +1,4 @@
-/*
- * Generate definitions needed by assembly language modules.
- * This code generates raw asm output which is post-processed
- * to extract and format the required data.
- */
-
-#include <linux/crypto.h>
-#include <linux/sched.h>
-#include <linux/signal.h>
-#include <linux/personality.h>
-#include <linux/suspend.h>
-#include <linux/kbuild.h>
 #include <asm/ucontext.h>
-#include <asm/sigframe.h>
-#include <asm/pgtable.h>
-#include <asm/fixmap.h>
-#include <asm/processor.h>
-#include <asm/thread_info.h>
-#include <asm/bootparam.h>
-#include <asm/elf.h>
-#include <asm/suspend.h>
-
-#include <xen/interface/xen.h>
 
 #include <linux/lguest.h>
 #include "../../../drivers/lguest/lg.h"
@@ -51,21 +29,10 @@
 	OFFSET(CPUINFO_x86_vendor_id, cpuinfo_x86, x86_vendor_id);
 	BLANK();
 
-	OFFSET(TI_task, thread_info, task);
-	OFFSET(TI_exec_domain, thread_info, exec_domain);
-	OFFSET(TI_flags, thread_info, flags);
-	OFFSET(TI_status, thread_info, status);
-	OFFSET(TI_preempt_count, thread_info, preempt_count);
-	OFFSET(TI_addr_limit, thread_info, addr_limit);
-	OFFSET(TI_restart_block, thread_info, restart_block);
 	OFFSET(TI_sysenter_return, thread_info, sysenter_return);
 	OFFSET(TI_cpu, thread_info, cpu);
 	BLANK();
 
-	OFFSET(GDS_size, desc_ptr, size);
-	OFFSET(GDS_address, desc_ptr, address);
-	BLANK();
-
 	OFFSET(PT_EBX, pt_regs, bx);
 	OFFSET(PT_ECX, pt_regs, cx);
 	OFFSET(PT_EDX, pt_regs, dx);
@@ -85,42 +52,13 @@
 	OFFSET(PT_OLDSS,  pt_regs, ss);
 	BLANK();
 
-	OFFSET(EXEC_DOMAIN_handler, exec_domain, handler);
 	OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe, uc.uc_mcontext);
 	BLANK();
 
-	OFFSET(pbe_address, pbe, address);
-	OFFSET(pbe_orig_address, pbe, orig_address);
-	OFFSET(pbe_next, pbe, next);
-
 	/* Offset from the sysenter stack to tss.sp0 */
 	DEFINE(TSS_sysenter_sp0, offsetof(struct tss_struct, x86_tss.sp0) -
 		 sizeof(struct tss_struct));
 
-	DEFINE(PAGE_SIZE_asm, PAGE_SIZE);
-	DEFINE(PAGE_SHIFT_asm, PAGE_SHIFT);
-	DEFINE(THREAD_SIZE_asm, THREAD_SIZE);
-
-	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
-
-#ifdef CONFIG_PARAVIRT
-	BLANK();
-	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
-	OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
-	OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
-	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
-	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
-	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
-	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
-	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
-#endif
-
-#ifdef CONFIG_XEN
-	BLANK();
-	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
-	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
-#endif
-
 #if defined(CONFIG_LGUEST) || defined(CONFIG_LGUEST_GUEST) || defined(CONFIG_LGUEST_MODULE)
 	BLANK();
 	OFFSET(LGUEST_DATA_irq_enabled, lguest_data, irq_enabled);
@@ -139,11 +77,4 @@
 	OFFSET(LGUEST_PAGES_regs_errcode, lguest_pages, regs.errcode);
 	OFFSET(LGUEST_PAGES_regs, lguest_pages, regs);
 #endif
-
-	BLANK();
-	OFFSET(BP_scratch, boot_params, scratch);
-	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.38-gnu/arch/x86/kernel/asm-offsets_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/asm-offsets_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/asm-offsets_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/asm-offsets_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,27 +1,4 @@
-/*
- * Generate definitions needed by assembly language modules.
- * This code generates raw asm output which is post-processed to extract
- * and format the required data.
- */
-#define COMPILE_OFFSETS
-
-#include <linux/crypto.h>
-#include <linux/sched.h> 
-#include <linux/stddef.h>
-#include <linux/errno.h> 
-#include <linux/hardirq.h>
-#include <linux/suspend.h>
-#include <linux/kbuild.h>
-#include <asm/processor.h>
-#include <asm/segment.h>
-#include <asm/thread_info.h>
 #include <asm/ia32.h>
-#include <asm/bootparam.h>
-#include <asm/suspend.h>
-
-#include <xen/interface/xen.h>
-
-#include <asm/sigframe.h>
 
 #define __NO_STUBS 1
 #undef __SYSCALL
@@ -33,41 +10,19 @@
 
 int main(void)
 {
-#define ENTRY(entry) DEFINE(tsk_ ## entry, offsetof(struct task_struct, entry))
-	ENTRY(state);
-	ENTRY(flags); 
-	ENTRY(pid);
-	BLANK();
-#undef ENTRY
-#define ENTRY(entry) DEFINE(TI_ ## entry, offsetof(struct thread_info, entry))
-	ENTRY(flags);
-	ENTRY(addr_limit);
-	ENTRY(preempt_count);
-	ENTRY(status);
-#ifdef CONFIG_IA32_EMULATION
-	ENTRY(sysenter_return);
-#endif
-	BLANK();
-#undef ENTRY
 #ifdef CONFIG_PARAVIRT
-	BLANK();
-	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
-	OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
-	OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
-	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
-	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
 	OFFSET(PV_IRQ_adjust_exception_frame, pv_irq_ops, adjust_exception_frame);
-	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
 	OFFSET(PV_CPU_usergs_sysret32, pv_cpu_ops, usergs_sysret32);
 	OFFSET(PV_CPU_usergs_sysret64, pv_cpu_ops, usergs_sysret64);
-	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
 	OFFSET(PV_CPU_swapgs, pv_cpu_ops, swapgs);
-	OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
+	BLANK();
 #endif
 
-
 #ifdef CONFIG_IA32_EMULATION
-#define ENTRY(entry) DEFINE(IA32_SIGCONTEXT_ ## entry, offsetof(struct sigcontext_ia32, entry))
+	OFFSET(TI_sysenter_return, thread_info, sysenter_return);
+	BLANK();
+
+#define ENTRY(entry) OFFSET(IA32_SIGCONTEXT_ ## entry, sigcontext_ia32, entry)
 	ENTRY(ax);
 	ENTRY(bx);
 	ENTRY(cx);
@@ -79,15 +34,12 @@
 	ENTRY(ip);
 	BLANK();
 #undef ENTRY
-	DEFINE(IA32_RT_SIGFRAME_sigcontext,
-	       offsetof (struct rt_sigframe_ia32, uc.uc_mcontext));
+
+	OFFSET(IA32_RT_SIGFRAME_sigcontext, rt_sigframe_ia32, uc.uc_mcontext);
 	BLANK();
 #endif
-	DEFINE(pbe_address, offsetof(struct pbe, address));
-	DEFINE(pbe_orig_address, offsetof(struct pbe, orig_address));
-	DEFINE(pbe_next, offsetof(struct pbe, next));
-	BLANK();
-#define ENTRY(entry) DEFINE(pt_regs_ ## entry, offsetof(struct pt_regs, entry))
+
+#define ENTRY(entry) OFFSET(pt_regs_ ## entry, pt_regs, entry)
 	ENTRY(bx);
 	ENTRY(bx);
 	ENTRY(cx);
@@ -107,7 +59,8 @@
 	ENTRY(flags);
 	BLANK();
 #undef ENTRY
-#define ENTRY(entry) DEFINE(saved_context_ ## entry, offsetof(struct saved_context, entry))
+
+#define ENTRY(entry) OFFSET(saved_context_ ## entry, saved_context, entry)
 	ENTRY(cr0);
 	ENTRY(cr2);
 	ENTRY(cr3);
@@ -115,26 +68,11 @@
 	ENTRY(cr8);
 	BLANK();
 #undef ENTRY
-	DEFINE(TSS_ist, offsetof(struct tss_struct, x86_tss.ist));
-	BLANK();
-	DEFINE(crypto_tfm_ctx_offset, offsetof(struct crypto_tfm, __crt_ctx));
-	BLANK();
-	DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
 
+	OFFSET(TSS_ist, tss_struct, x86_tss.ist);
 	BLANK();
-	OFFSET(BP_scratch, boot_params, scratch);
-	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);
-#ifdef CONFIG_XEN
-	BLANK();
-	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
-	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
-#undef ENTRY
-#endif
+	DEFINE(__NR_syscall_max, sizeof(syscalls) - 1);
+
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/asm-offsets.c linux-libre-2.6.39-gnu/arch/x86/kernel/asm-offsets.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/asm-offsets.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/asm-offsets.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,70 @@
+/*
+ * Generate definitions needed by assembly language modules.
+ * This code generates raw asm output which is post-processed to extract
+ * and format the required data.
+ */
+#define COMPILE_OFFSETS
+
+#include <linux/crypto.h>
+#include <linux/sched.h>
+#include <linux/stddef.h>
+#include <linux/hardirq.h>
+#include <linux/suspend.h>
+#include <linux/kbuild.h>
+#include <asm/processor.h>
+#include <asm/thread_info.h>
+#include <asm/sigframe.h>
+#include <asm/bootparam.h>
+#include <asm/suspend.h>
+
+#ifdef CONFIG_XEN
+#include <xen/interface/xen.h>
+#endif
+
 #ifdef CONFIG_X86_32
 # include "asm-offsets_32.c"
 #else
 # include "asm-offsets_64.c"
 #endif
+
+void common(void) {
+	BLANK();
+	OFFSET(TI_flags, thread_info, flags);
+	OFFSET(TI_status, thread_info, status);
+	OFFSET(TI_addr_limit, thread_info, addr_limit);
+	OFFSET(TI_preempt_count, thread_info, preempt_count);
+
+	BLANK();
+	OFFSET(crypto_tfm_ctx_offset, crypto_tfm, __crt_ctx);
+
+	BLANK();
+	OFFSET(pbe_address, pbe, address);
+	OFFSET(pbe_orig_address, pbe, orig_address);
+	OFFSET(pbe_next, pbe, next);
+
+#ifdef CONFIG_PARAVIRT
+	BLANK();
+	OFFSET(PARAVIRT_enabled, pv_info, paravirt_enabled);
+	OFFSET(PARAVIRT_PATCH_pv_cpu_ops, paravirt_patch_template, pv_cpu_ops);
+	OFFSET(PARAVIRT_PATCH_pv_irq_ops, paravirt_patch_template, pv_irq_ops);
+	OFFSET(PV_IRQ_irq_disable, pv_irq_ops, irq_disable);
+	OFFSET(PV_IRQ_irq_enable, pv_irq_ops, irq_enable);
+	OFFSET(PV_CPU_iret, pv_cpu_ops, iret);
+	OFFSET(PV_CPU_irq_enable_sysexit, pv_cpu_ops, irq_enable_sysexit);
+	OFFSET(PV_CPU_read_cr0, pv_cpu_ops, read_cr0);
+	OFFSET(PV_MMU_read_cr2, pv_mmu_ops, read_cr2);
+#endif
+
+#ifdef CONFIG_XEN
+	BLANK();
+	OFFSET(XEN_vcpu_info_mask, vcpu_info, evtchn_upcall_mask);
+	OFFSET(XEN_vcpu_info_pending, vcpu_info, evtchn_upcall_pending);
+#endif
+
+	BLANK();
+	OFFSET(BP_scratch, boot_params, scratch);
+	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.38-gnu/arch/x86/kernel/cpu/amd.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/amd.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/amd.c	2011-05-19 00:06:34.000000000 -0400
@@ -233,18 +233,22 @@
 }
 #endif
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
+/*
+ * To workaround broken NUMA config.  Read the comment in
+ * srat_detect_node().
+ */
 static int __cpuinit nearby_node(int apicid)
 {
 	int i, node;
 
 	for (i = apicid - 1; i >= 0; i--) {
-		node = apicid_to_node[i];
+		node = __apicid_to_node[i];
 		if (node != NUMA_NO_NODE && node_online(node))
 			return node;
 	}
 	for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
-		node = apicid_to_node[i];
+		node = __apicid_to_node[i];
 		if (node != NUMA_NO_NODE && node_online(node))
 			return node;
 	}
@@ -261,7 +265,7 @@
 #ifdef CONFIG_X86_HT
 static void __cpuinit amd_get_topology(struct cpuinfo_x86 *c)
 {
-	u32 nodes;
+	u32 nodes, cores_per_cu = 1;
 	u8 node_id;
 	int cpu = smp_processor_id();
 
@@ -276,6 +280,7 @@
 		/* get compute unit information */
 		smp_num_siblings = ((ebx >> 8) & 3) + 1;
 		c->compute_unit_id = ebx & 0xff;
+		cores_per_cu += ((ebx >> 8) & 3);
 	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
 		u64 value;
 
@@ -288,15 +293,18 @@
 	/* fixup multi-node processor information */
 	if (nodes > 1) {
 		u32 cores_per_node;
+		u32 cus_per_node;
 
 		set_cpu_cap(c, X86_FEATURE_AMD_DCM);
 		cores_per_node = c->x86_max_cores / nodes;
+		cus_per_node = cores_per_node / cores_per_cu;
 
 		/* store NodeID, use llc_shared_map to store sibling info */
 		per_cpu(cpu_llc_id, cpu) = node_id;
 
-		/* core id to be in range from 0 to (cores_per_node - 1) */
-		c->cpu_core_id = c->cpu_core_id % cores_per_node;
+		/* core id has to be in the [0 .. cores_per_node - 1] range */
+		c->cpu_core_id %= cores_per_node;
+		c->compute_unit_id %= cus_per_node;
 	}
 }
 #endif
@@ -334,31 +342,40 @@
 
 static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 {
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
 	int cpu = smp_processor_id();
 	int node;
 	unsigned apicid = c->apicid;
 
-	node = per_cpu(cpu_llc_id, cpu);
+	node = numa_cpu_node(cpu);
+	if (node == NUMA_NO_NODE)
+		node = per_cpu(cpu_llc_id, cpu);
 
-	if (apicid_to_node[apicid] != NUMA_NO_NODE)
-		node = apicid_to_node[apicid];
 	if (!node_online(node)) {
-		/* Two possibilities here:
-		   - The CPU is missing memory and no node was created.
-		   In that case try picking one from a nearby CPU
-		   - The APIC IDs differ from the HyperTransport node IDs
-		   which the K8 northbridge parsing fills in.
-		   Assume they are all increased by a constant offset,
-		   but in the same order as the HT nodeids.
-		   If that doesn't result in a usable node fall back to the
-		   path for the previous case.  */
-
+		/*
+		 * Two possibilities here:
+		 *
+		 * - The CPU is missing memory and no node was created.  In
+		 *   that case try picking one from a nearby CPU.
+		 *
+		 * - The APIC IDs differ from the HyperTransport node IDs
+		 *   which the K8 northbridge parsing fills in.  Assume
+		 *   they are all increased by a constant offset, but in
+		 *   the same order as the HT nodeids.  If that doesn't
+		 *   result in a usable node fall back to the path for the
+		 *   previous case.
+		 *
+		 * This workaround operates directly on the mapping between
+		 * APIC ID and NUMA node, assuming certain relationship
+		 * between APIC ID, HT node ID and NUMA topology.  As going
+		 * through CPU mapping may alter the outcome, directly
+		 * access __apicid_to_node[].
+		 */
 		int ht_nodeid = c->initial_apicid;
 
 		if (ht_nodeid >= 0 &&
-		    apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
-			node = apicid_to_node[ht_nodeid];
+		    __apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
+			node = __apicid_to_node[ht_nodeid];
 		/* Pick a nearby node */
 		if (!node_online(node))
 			node = nearby_node(apicid);
@@ -594,6 +611,29 @@
 		}
 	}
 #endif
+
+	/* As a rule processors have APIC timer running in deep C states */
+	if (c->x86 > 0xf && !cpu_has_amd_erratum(amd_erratum_400))
+		set_cpu_cap(c, X86_FEATURE_ARAT);
+
+	/*
+	 * Disable GART TLB Walk Errors on Fam10h. We do this here
+	 * because this is always needed when GART is enabled, even in a
+	 * kernel which has no MCE support built in.
+	 */
+	if (c->x86 == 0x10) {
+		/*
+		 * BIOS should disable GartTlbWlk Errors themself. If
+		 * it doesn't do it here as suggested by the BKDG.
+		 *
+		 * Fixes: https://bugzilla.kernel.org/show_bug.cgi?id=33012
+		 */
+		u64 mask;
+
+		rdmsrl(MSR_AMD64_MCx_MASK(4), mask);
+		mask |= (1 << 10);
+		wrmsrl(MSR_AMD64_MCx_MASK(4), mask);
+	}
 }
 
 #ifdef CONFIG_X86_32
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/common.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/common.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -675,7 +675,7 @@
 	const struct cpu_dev *const *cdev;
 	int count = 0;
 
-#ifdef PROCESSOR_SELECT
+#ifdef CONFIG_PROCESSOR_SELECT
 	printk(KERN_INFO "KERNEL supported cpus:\n");
 #endif
 
@@ -687,7 +687,7 @@
 		cpu_devs[count] = cpudev;
 		count++;
 
-#ifdef PROCESSOR_SELECT
+#ifdef CONFIG_PROCESSOR_SELECT
 		{
 			unsigned int j;
 
@@ -869,7 +869,7 @@
 
 	select_idle_routine(c);
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
 	numa_add_cpu(smp_processor_id());
 #endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/longhaul.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/longhaul.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/longhaul.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/longhaul.c	2011-05-19 00:06:34.000000000 -0400
@@ -444,7 +444,7 @@
 		return -EINVAL;
 	}
 	/* Get max multiplier - as we always did.
-	 * Longhaul MSR is usefull only when voltage scaling is enabled.
+	 * Longhaul MSR is useful only when voltage scaling is enabled.
 	 * C3 is booting at max anyway. */
 	maxmult = mult;
 	/* Get min multiplier */
@@ -1011,7 +1011,7 @@
  * trigger frequency transition in some cases. */
 module_param(disable_acpi_c3, int, 0644);
 MODULE_PARM_DESC(disable_acpi_c3, "Don't use ACPI C3 support");
-/* Change CPU voltage with frequency. Very usefull to save
+/* Change CPU voltage with frequency. Very useful to save
  * power, but most VIA C3 processors aren't supporting it. */
 module_param(scale_voltage, int, 0644);
 MODULE_PARM_DESC(scale_voltage, "Scale voltage of processor");
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/pcc-cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -315,8 +315,6 @@
 
 	input.count = 4;
 	input.pointer = in_params;
-	input.count = 4;
-	input.pointer = in_params;
 	in_params[0].type               = ACPI_TYPE_BUFFER;
 	in_params[0].buffer.length      = 16;
 	in_params[0].buffer.pointer     = OSC_UUID;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/powernow-k8.c	2011-05-19 00:06:34.000000000 -0400
@@ -630,8 +630,7 @@
 					data->powernow_table[j].frequency/1000);
 			} else {
 				printk(KERN_INFO PFX
-					"   %d : fid 0x%x (%d MHz), vid 0x%x\n",
-					j,
+					"fid 0x%x (%d MHz), vid 0x%x\n",
 					data->powernow_table[j].index & 0xff,
 					data->powernow_table[j].frequency/1000,
 					data->powernow_table[j].index >> 8);
@@ -1276,7 +1275,7 @@
 
 	if (powernow_k8_cpu_init_acpi(data)) {
 		/*
-		 * Use the PSB BIOS structure. This is only availabe on
+		 * Use the PSB BIOS structure. This is only available on
 		 * an UP version, and is deprecated by AMD.
 		 */
 		if (num_online_cpus() != 1) {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/cpufreq/speedstep-smi.c	2011-05-19 00:06:34.000000000 -0400
@@ -292,7 +292,7 @@
 
 	result = speedstep_smi_ownership();
 	if (result) {
-		dprintk("fails in aquiring ownership of a SMI interface.\n");
+		dprintk("fails in acquiring ownership of a SMI interface.\n");
 		return -EINVAL;
 	}
 
@@ -360,7 +360,7 @@
 	int result = speedstep_smi_ownership();
 
 	if (result)
-		dprintk("fails in re-aquiring ownership of a SMI interface.\n");
+		dprintk("fails in re-acquiring ownership of a SMI interface.\n");
 
 	return result;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/intel.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/intel.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/intel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/intel.c	2011-05-19 00:06:34.000000000 -0400
@@ -276,14 +276,13 @@
 
 static void __cpuinit srat_detect_node(struct cpuinfo_x86 *c)
 {
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_64)
+#ifdef CONFIG_NUMA
 	unsigned node;
 	int cpu = 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. */
-	node = apicid_to_node[apicid];
+	node = numa_cpu_node(cpu);
 	if (node == NUMA_NO_NODE || !node_online(node)) {
 		/* reuse the value from init_cpu_to_node() */
 		node = cpu_to_node(cpu);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/intel_cacheinfo.c	2011-05-19 00:06:34.000000000 -0400
@@ -304,8 +304,9 @@
 
 struct _cache_attr {
 	struct attribute attr;
-	ssize_t (*show)(struct _cpuid4_info *, char *);
-	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count);
+	ssize_t (*show)(struct _cpuid4_info *, char *, unsigned int);
+	ssize_t (*store)(struct _cpuid4_info *, const char *, size_t count,
+			 unsigned int);
 };
 
 #ifdef CONFIG_AMD_NB
@@ -400,7 +401,8 @@
 
 #define SHOW_CACHE_DISABLE(slot)					\
 static ssize_t								\
-show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf)	\
+show_cache_disable_##slot(struct _cpuid4_info *this_leaf, char *buf,	\
+			  unsigned int cpu)				\
 {									\
 	return show_cache_disable(this_leaf, buf, slot);		\
 }
@@ -512,7 +514,8 @@
 #define STORE_CACHE_DISABLE(slot)					\
 static ssize_t								\
 store_cache_disable_##slot(struct _cpuid4_info *this_leaf,		\
-			   const char *buf, size_t count)		\
+			   const char *buf, size_t count,		\
+			   unsigned int cpu)				\
 {									\
 	return store_cache_disable(this_leaf, buf, count, slot);	\
 }
@@ -524,6 +527,39 @@
 static struct _cache_attr cache_disable_1 = __ATTR(cache_disable_1, 0644,
 		show_cache_disable_1, store_cache_disable_1);
 
+static ssize_t
+show_subcaches(struct _cpuid4_info *this_leaf, char *buf, unsigned int cpu)
+{
+	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		return -EINVAL;
+
+	return sprintf(buf, "%x\n", amd_get_subcaches(cpu));
+}
+
+static ssize_t
+store_subcaches(struct _cpuid4_info *this_leaf, const char *buf, size_t count,
+		unsigned int cpu)
+{
+	unsigned long val;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EPERM;
+
+	if (!this_leaf->l3 || !amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		return -EINVAL;
+
+	if (strict_strtoul(buf, 16, &val) < 0)
+		return -EINVAL;
+
+	if (amd_set_subcaches(cpu, val))
+		return -EINVAL;
+
+	return count;
+}
+
+static struct _cache_attr subcaches =
+	__ATTR(subcaches, 0644, show_subcaches, store_subcaches);
+
 #else	/* CONFIG_AMD_NB */
 #define amd_init_l3_cache(x, y)
 #endif /* CONFIG_AMD_NB */
@@ -532,9 +568,9 @@
 __cpuinit cpuid4_cache_lookup_regs(int index,
 				   struct _cpuid4_info_regs *this_leaf)
 {
-	union _cpuid4_leaf_eax 	eax;
-	union _cpuid4_leaf_ebx 	ebx;
-	union _cpuid4_leaf_ecx 	ecx;
+	union _cpuid4_leaf_eax	eax;
+	union _cpuid4_leaf_ebx	ebx;
+	union _cpuid4_leaf_ecx	ecx;
 	unsigned		edx;
 
 	if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD) {
@@ -732,11 +768,11 @@
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 
 	if ((index == 3) && (c->x86_vendor == X86_VENDOR_AMD)) {
-		for_each_cpu(i, c->llc_shared_map) {
+		for_each_cpu(i, cpu_llc_shared_mask(cpu)) {
 			if (!per_cpu(ici_cpuid4_info, i))
 				continue;
 			this_leaf = CPUID4_INFO_IDX(i, index);
-			for_each_cpu(sibling, c->llc_shared_map) {
+			for_each_cpu(sibling, cpu_llc_shared_mask(cpu)) {
 				if (!cpu_online(sibling))
 					continue;
 				set_bit(sibling, this_leaf->shared_cpu_map);
@@ -870,8 +906,8 @@
 #define INDEX_KOBJECT_PTR(x, y)		(&((per_cpu(ici_index_kobject, x))[y]))
 
 #define show_one_plus(file_name, object, val)				\
-static ssize_t show_##file_name						\
-			(struct _cpuid4_info *this_leaf, char *buf)	\
+static ssize_t show_##file_name(struct _cpuid4_info *this_leaf, char *buf, \
+				unsigned int cpu)			\
 {									\
 	return sprintf(buf, "%lu\n", (unsigned long)this_leaf->object + val); \
 }
@@ -882,7 +918,8 @@
 show_one_plus(ways_of_associativity, ebx.split.ways_of_associativity, 1);
 show_one_plus(number_of_sets, ecx.split.number_of_sets, 1);
 
-static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf)
+static ssize_t show_size(struct _cpuid4_info *this_leaf, char *buf,
+			 unsigned int cpu)
 {
 	return sprintf(buf, "%luK\n", this_leaf->size / 1024);
 }
@@ -906,17 +943,20 @@
 	return n;
 }
 
-static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf)
+static inline ssize_t show_shared_cpu_map(struct _cpuid4_info *leaf, char *buf,
+					  unsigned int cpu)
 {
 	return show_shared_cpu_map_func(leaf, 0, buf);
 }
 
-static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf)
+static inline ssize_t show_shared_cpu_list(struct _cpuid4_info *leaf, char *buf,
+					   unsigned int cpu)
 {
 	return show_shared_cpu_map_func(leaf, 1, buf);
 }
 
-static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf)
+static ssize_t show_type(struct _cpuid4_info *this_leaf, char *buf,
+			 unsigned int cpu)
 {
 	switch (this_leaf->eax.split.type) {
 	case CACHE_TYPE_DATA:
@@ -974,6 +1014,9 @@
 	if (amd_nb_has_feature(AMD_NB_L3_INDEX_DISABLE))
 		n += 2;
 
+	if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		n += 1;
+
 	attrs = kzalloc(n * sizeof (struct attribute *), GFP_KERNEL);
 	if (attrs == NULL)
 		return attrs = default_attrs;
@@ -986,6 +1029,9 @@
 		attrs[n++] = &cache_disable_1.attr;
 	}
 
+	if (amd_nb_has_feature(AMD_NB_L3_PARTITIONING))
+		attrs[n++] = &subcaches.attr;
+
 	return attrs;
 }
 #endif
@@ -998,7 +1044,7 @@
 
 	ret = fattr->show ?
 		fattr->show(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
-			buf) :
+			buf, this_leaf->cpu) :
 		0;
 	return ret;
 }
@@ -1012,7 +1058,7 @@
 
 	ret = fattr->store ?
 		fattr->store(CPUID4_INFO_IDX(this_leaf->cpu, this_leaf->index),
-			buf, count) :
+			buf, count, this_leaf->cpu) :
 		0;
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce_amd.c	2011-05-19 00:06:34.000000000 -0400
@@ -509,6 +509,7 @@
 out_free:
 	if (b) {
 		kobject_put(&b->kobj);
+		list_del(&b->miscj);
 		kfree(b);
 	}
 	return err;
@@ -527,15 +528,12 @@
 	int i, err = 0;
 	struct threshold_bank *b = NULL;
 	char name[32];
-#ifdef CONFIG_SMP
-	struct cpuinfo_x86 *c = &cpu_data(cpu);
-#endif
 
 	sprintf(name, "threshold_bank%i", bank);
 
 #ifdef CONFIG_SMP
 	if (cpu_data(cpu).cpu_core_id && shared_bank[bank]) {	/* symlink */
-		i = cpumask_first(c->llc_shared_map);
+		i = cpumask_first(cpu_llc_shared_mask(cpu));
 
 		/* first core not up yet */
 		if (cpu_data(i).cpu_core_id)
@@ -555,7 +553,7 @@
 		if (err)
 			goto out;
 
-		cpumask_copy(b->cpus, c->llc_shared_map);
+		cpumask_copy(b->cpus, cpu_llc_shared_mask(cpu));
 		per_cpu(threshold_banks, cpu)[bank] = b;
 
 		goto out;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce-apei.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,24 +106,34 @@
 ssize_t apei_read_mce(struct mce *m, u64 *record_id)
 {
 	struct cper_mce_record rcd;
-	ssize_t len;
-
-	len = erst_read_next(&rcd.hdr, sizeof(rcd));
-	if (len <= 0)
-		return len;
-	/* Can not skip other records in storage via ERST unless clear them */
-	else if (len != sizeof(rcd) ||
-		 uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE)) {
-		if (printk_ratelimit())
-			pr_warning(
-			"MCE-APEI: Can not skip the unknown record in ERST");
-		return -EIO;
-	}
+	int rc, pos;
 
+	rc = erst_get_record_id_begin(&pos);
+	if (rc)
+		return rc;
+retry:
+	rc = erst_get_record_id_next(&pos, record_id);
+	if (rc)
+		goto out;
+	/* no more record */
+	if (*record_id == APEI_ERST_INVALID_RECORD_ID)
+		goto out;
+	rc = erst_read(*record_id, &rcd.hdr, sizeof(rcd));
+	/* someone else has cleared the record, try next one */
+	if (rc == -ENOENT)
+		goto retry;
+	else if (rc < 0)
+		goto out;
+	/* try to skip other type records in storage */
+	else if (rc != sizeof(rcd) ||
+		 uuid_le_cmp(rcd.hdr.creator_id, CPER_CREATOR_MCE))
+		goto retry;
 	memcpy(m, &rcd.mce, sizeof(*m));
-	*record_id = rcd.hdr.record_id;
+	rc = sizeof(*m);
+out:
+	erst_get_record_id_end();
 
-	return sizeof(*m);
+	return rc;
 }
 
 /* Check whether there is record in ERST */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/percpu.h>
 #include <linux/string.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/delay.h>
 #include <linux/ctype.h>
 #include <linux/sched.h>
@@ -881,7 +882,7 @@
  * 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.
+ * parser). So only support physical addresses up to page granuality for now.
  */
 static int mce_usable_address(struct mce *m)
 {
@@ -1625,7 +1626,7 @@
 static unsigned int mce_poll(struct file *file, poll_table *wait)
 {
 	poll_wait(file, &mce_wait, wait);
-	if (rcu_dereference_check_mce(mcelog.next))
+	if (rcu_access_index(mcelog.next))
 		return POLLIN | POLLRDNORM;
 	if (!mce_apei_read_done && apei_check_mce())
 		return POLLIN | POLLRDNORM;
@@ -1749,14 +1750,14 @@
 	return 0;
 }
 
-static int mce_suspend(struct sys_device *dev, pm_message_t state)
+static int mce_suspend(void)
 {
 	return mce_disable_error_reporting();
 }
 
-static int mce_shutdown(struct sys_device *dev)
+static void mce_shutdown(void)
 {
-	return mce_disable_error_reporting();
+	mce_disable_error_reporting();
 }
 
 /*
@@ -1764,14 +1765,18 @@
  * 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)
+static void mce_resume(void)
 {
 	__mcheck_cpu_init_generic();
 	__mcheck_cpu_init_vendor(__this_cpu_ptr(&cpu_info));
-
-	return 0;
 }
 
+static struct syscore_ops mce_syscore_ops = {
+	.suspend	= mce_suspend,
+	.shutdown	= mce_shutdown,
+	.resume		= mce_resume,
+};
+
 static void mce_cpu_restart(void *data)
 {
 	del_timer_sync(&__get_cpu_var(mce_timer));
@@ -1808,9 +1813,6 @@
 }
 
 static struct sysdev_class mce_sysclass = {
-	.suspend	= mce_suspend,
-	.shutdown	= mce_shutdown,
-	.resume		= mce_resume,
 	.name		= "machinecheck",
 };
 
@@ -2139,6 +2141,7 @@
 			return err;
 	}
 
+	register_syscore_ops(&mce_syscore_ops);
 	register_hotcpu_notifier(&mce_cpu_notifier);
 	misc_register(&mce_log_device);
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/mce-inject.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 {
 	struct mce *i = &per_cpu(injectm, m->extcpu);
 
-	/* Make sure noone reads partially written injectm */
+	/* Make sure no one reads partially written injectm */
 	i->finished = 0;
 	mb();
 	m->finished = 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mcheck/therm_throt.c	2011-05-19 00:06:34.000000000 -0400
@@ -446,18 +446,20 @@
 	 */
 	rdmsr(MSR_IA32_MISC_ENABLE, l, h);
 
+	h = lvtthmr_init;
 	/*
 	 * The initial value of thermal LVT entries on all APs always reads
 	 * 0x10000 because APs are woken up by BSP issuing INIT-SIPI-SIPI
 	 * sequence to them and LVT registers are reset to 0s except for
 	 * the mask bits which are set to 1s when APs receive INIT IPI.
-	 * Always restore the value that BIOS has programmed on AP based on
-	 * BSP's info we saved since BIOS is always setting the same value
-	 * for all threads/cores
+	 * If BIOS takes over the thermal interrupt and sets its interrupt
+	 * delivery mode to SMI (not fixed), it restores the value that the
+	 * BIOS has programmed on AP based on BSP's info we saved since BIOS
+	 * is always setting the same value for all threads/cores.
 	 */
-	apic_write(APIC_LVTTHMR, lvtthmr_init);
+	if ((h & APIC_DM_FIXED_MASK) != APIC_DM_FIXED)
+		apic_write(APIC_LVTTHMR, lvtthmr_init);
 
-	h = lvtthmr_init;
 
 	if ((l & MSR_IA32_MISC_ENABLE_TM1) && (h & APIC_DM_SMI)) {
 		printk(KERN_DEBUG
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mtrr/generic.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mtrr/generic.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mtrr/generic.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * This only handles 32bit MTRR on 32bit hosts. This is strictly wrong
- * because MTRRs can span upto 40 bits (36bits on most modern x86)
+ * because MTRRs can span up to 40 bits (36bits on most modern x86)
  */
 #define DEBUG
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mtrr/main.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mtrr/main.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/mtrr/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/mtrr/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 #include <linux/cpu.h>
 #include <linux/pci.h>
 #include <linux/smp.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/processor.h>
 #include <asm/e820.h>
@@ -292,14 +293,24 @@
 
 	/*
 	 * HACK!
-	 * We use this same function to initialize the mtrrs on boot.
-	 * The state of the boot cpu's mtrrs has been saved, and we want
-	 * to replicate across all the APs.
-	 * If we're doing that @reg is set to something special...
+	 *
+	 * We use this same function to initialize the mtrrs during boot,
+	 * resume, runtime cpu online and on an explicit request to set a
+	 * specific MTRR.
+	 *
+	 * During boot or suspend, the state of the boot cpu's mtrrs has been
+	 * saved, and we want to replicate that across all the cpus that come
+	 * online (either at the end of boot or resume or during a runtime cpu
+	 * online). If we're doing that, @reg is set to something special and on
+	 * this cpu we still do mtrr_if->set_all(). During boot/resume, this
+	 * is unnecessary if at this point we are still on the cpu that started
+	 * the boot/resume sequence. But there is no guarantee that we are still
+	 * on the same cpu. So we do mtrr_if->set_all() on this cpu aswell to be
+	 * sure that we are in sync with everyone else.
 	 */
 	if (reg != ~0U)
 		mtrr_if->set(reg, base, size, type);
-	else if (!mtrr_aps_delayed_init)
+	else
 		mtrr_if->set_all();
 
 	/* Wait for the others */
@@ -630,7 +641,7 @@
 
 static struct mtrr_value mtrr_value[MTRR_MAX_VAR_RANGES];
 
-static int mtrr_save(struct sys_device *sysdev, pm_message_t state)
+static int mtrr_save(void)
 {
 	int i;
 
@@ -642,7 +653,7 @@
 	return 0;
 }
 
-static int mtrr_restore(struct sys_device *sysdev)
+static void mtrr_restore(void)
 {
 	int i;
 
@@ -653,12 +664,11 @@
 				    mtrr_value[i].ltype);
 		}
 	}
-	return 0;
 }
 
 
 
-static struct sysdev_driver mtrr_sysdev_driver = {
+static struct syscore_ops mtrr_syscore_ops = {
 	.suspend	= mtrr_save,
 	.resume		= mtrr_restore,
 };
@@ -839,7 +849,7 @@
 	 * TBD: is there any system with such CPU which supports
 	 * suspend/resume? If no, we should remove the code.
 	 */
-	sysdev_driver_register(&cpu_sysdev_class, &mtrr_sysdev_driver);
+	register_syscore_ops(&mtrr_syscore_ops);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perfctr-watchdog.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,6 +46,8 @@
 	/* returns the bit offset of the performance counter register */
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
+		if (msr >= MSR_F15H_PERF_CTR)
+			return (msr - MSR_F15H_PERF_CTR) >> 1;
 		return msr - MSR_K7_PERFCTR0;
 	case X86_VENDOR_INTEL:
 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
@@ -70,6 +72,8 @@
 	/* returns the bit offset of the event selection register */
 	switch (boot_cpu_data.x86_vendor) {
 	case X86_VENDOR_AMD:
+		if (msr >= MSR_F15H_PERF_CTL)
+			return (msr - MSR_F15H_PERF_CTL) >> 1;
 		return msr - MSR_K7_EVNTSEL0;
 	case X86_VENDOR_INTEL:
 		if (cpu_has(&boot_cpu_data, X86_FEATURE_ARCH_PERFMON))
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_amd.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_amd.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_amd.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
  [ C(L1D) ] = {
 	[ C(OP_READ) ] = {
 		[ C(RESULT_ACCESS) ] = 0x0040, /* Data Cache Accesses        */
-		[ C(RESULT_MISS)   ] = 0x0041, /* Data Cache Misses          */
+		[ C(RESULT_MISS)   ] = 0x0141, /* Data Cache Misses          */
 	},
 	[ C(OP_WRITE) ] = {
 		[ C(RESULT_ACCESS) ] = 0x0142, /* Data Cache Refills :system */
@@ -127,6 +127,11 @@
 /*
  * AMD64 events are detected based on their event codes.
  */
+static inline unsigned int amd_get_event_code(struct hw_perf_event *hwc)
+{
+	return ((hwc->config >> 24) & 0x0f00) | (hwc->config & 0x00ff);
+}
+
 static inline int amd_is_nb_event(struct hw_perf_event *hwc)
 {
 	return (hwc->config & 0xe0) == 0xe0;
@@ -385,13 +390,195 @@
 	.cpu_dead		= amd_pmu_cpu_dead,
 };
 
+/* AMD Family 15h */
+
+#define AMD_EVENT_TYPE_MASK	0x000000F0ULL
+
+#define AMD_EVENT_FP		0x00000000ULL ... 0x00000010ULL
+#define AMD_EVENT_LS		0x00000020ULL ... 0x00000030ULL
+#define AMD_EVENT_DC		0x00000040ULL ... 0x00000050ULL
+#define AMD_EVENT_CU		0x00000060ULL ... 0x00000070ULL
+#define AMD_EVENT_IC_DE		0x00000080ULL ... 0x00000090ULL
+#define AMD_EVENT_EX_LS		0x000000C0ULL
+#define AMD_EVENT_DE		0x000000D0ULL
+#define AMD_EVENT_NB		0x000000E0ULL ... 0x000000F0ULL
+
+/*
+ * AMD family 15h event code/PMC mappings:
+ *
+ * type = event_code & 0x0F0:
+ *
+ * 0x000	FP	PERF_CTL[5:3]
+ * 0x010	FP	PERF_CTL[5:3]
+ * 0x020	LS	PERF_CTL[5:0]
+ * 0x030	LS	PERF_CTL[5:0]
+ * 0x040	DC	PERF_CTL[5:0]
+ * 0x050	DC	PERF_CTL[5:0]
+ * 0x060	CU	PERF_CTL[2:0]
+ * 0x070	CU	PERF_CTL[2:0]
+ * 0x080	IC/DE	PERF_CTL[2:0]
+ * 0x090	IC/DE	PERF_CTL[2:0]
+ * 0x0A0	---
+ * 0x0B0	---
+ * 0x0C0	EX/LS	PERF_CTL[5:0]
+ * 0x0D0	DE	PERF_CTL[2:0]
+ * 0x0E0	NB	NB_PERF_CTL[3:0]
+ * 0x0F0	NB	NB_PERF_CTL[3:0]
+ *
+ * Exceptions:
+ *
+ * 0x000	FP	PERF_CTL[3], PERF_CTL[5:3] (*)
+ * 0x003	FP	PERF_CTL[3]
+ * 0x004	FP	PERF_CTL[3], PERF_CTL[5:3] (*)
+ * 0x00B	FP	PERF_CTL[3]
+ * 0x00D	FP	PERF_CTL[3]
+ * 0x023	DE	PERF_CTL[2:0]
+ * 0x02D	LS	PERF_CTL[3]
+ * 0x02E	LS	PERF_CTL[3,0]
+ * 0x043	CU	PERF_CTL[2:0]
+ * 0x045	CU	PERF_CTL[2:0]
+ * 0x046	CU	PERF_CTL[2:0]
+ * 0x054	CU	PERF_CTL[2:0]
+ * 0x055	CU	PERF_CTL[2:0]
+ * 0x08F	IC	PERF_CTL[0]
+ * 0x187	DE	PERF_CTL[0]
+ * 0x188	DE	PERF_CTL[0]
+ * 0x0DB	EX	PERF_CTL[5:0]
+ * 0x0DC	LS	PERF_CTL[5:0]
+ * 0x0DD	LS	PERF_CTL[5:0]
+ * 0x0DE	LS	PERF_CTL[5:0]
+ * 0x0DF	LS	PERF_CTL[5:0]
+ * 0x1D6	EX	PERF_CTL[5:0]
+ * 0x1D8	EX	PERF_CTL[5:0]
+ *
+ * (*) depending on the umask all FPU counters may be used
+ */
+
+static struct event_constraint amd_f15_PMC0  = EVENT_CONSTRAINT(0, 0x01, 0);
+static struct event_constraint amd_f15_PMC20 = EVENT_CONSTRAINT(0, 0x07, 0);
+static struct event_constraint amd_f15_PMC3  = EVENT_CONSTRAINT(0, 0x08, 0);
+static struct event_constraint amd_f15_PMC30 = EVENT_CONSTRAINT(0, 0x09, 0);
+static struct event_constraint amd_f15_PMC50 = EVENT_CONSTRAINT(0, 0x3F, 0);
+static struct event_constraint amd_f15_PMC53 = EVENT_CONSTRAINT(0, 0x38, 0);
+
+static struct event_constraint *
+amd_get_event_constraints_f15h(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned int event_code = amd_get_event_code(hwc);
+
+	switch (event_code & AMD_EVENT_TYPE_MASK) {
+	case AMD_EVENT_FP:
+		switch (event_code) {
+		case 0x000:
+			if (!(hwc->config & 0x0000F000ULL))
+				break;
+			if (!(hwc->config & 0x00000F00ULL))
+				break;
+			return &amd_f15_PMC3;
+		case 0x004:
+			if (hweight_long(hwc->config & ARCH_PERFMON_EVENTSEL_UMASK) <= 1)
+				break;
+			return &amd_f15_PMC3;
+		case 0x003:
+		case 0x00B:
+		case 0x00D:
+			return &amd_f15_PMC3;
+		}
+		return &amd_f15_PMC53;
+	case AMD_EVENT_LS:
+	case AMD_EVENT_DC:
+	case AMD_EVENT_EX_LS:
+		switch (event_code) {
+		case 0x023:
+		case 0x043:
+		case 0x045:
+		case 0x046:
+		case 0x054:
+		case 0x055:
+			return &amd_f15_PMC20;
+		case 0x02D:
+			return &amd_f15_PMC3;
+		case 0x02E:
+			return &amd_f15_PMC30;
+		default:
+			return &amd_f15_PMC50;
+		}
+	case AMD_EVENT_CU:
+	case AMD_EVENT_IC_DE:
+	case AMD_EVENT_DE:
+		switch (event_code) {
+		case 0x08F:
+		case 0x187:
+		case 0x188:
+			return &amd_f15_PMC0;
+		case 0x0DB ... 0x0DF:
+		case 0x1D6:
+		case 0x1D8:
+			return &amd_f15_PMC50;
+		default:
+			return &amd_f15_PMC20;
+		}
+	case AMD_EVENT_NB:
+		/* not yet implemented */
+		return &emptyconstraint;
+	default:
+		return &emptyconstraint;
+	}
+}
+
+static __initconst const struct x86_pmu amd_pmu_f15h = {
+	.name			= "AMD Family 15h",
+	.handle_irq		= x86_pmu_handle_irq,
+	.disable_all		= x86_pmu_disable_all,
+	.enable_all		= x86_pmu_enable_all,
+	.enable			= x86_pmu_enable_event,
+	.disable		= x86_pmu_disable_event,
+	.hw_config		= amd_pmu_hw_config,
+	.schedule_events	= x86_schedule_events,
+	.eventsel		= MSR_F15H_PERF_CTL,
+	.perfctr		= MSR_F15H_PERF_CTR,
+	.event_map		= amd_pmu_event_map,
+	.max_events		= ARRAY_SIZE(amd_perfmon_event_map),
+	.num_counters		= 6,
+	.cntval_bits		= 48,
+	.cntval_mask		= (1ULL << 48) - 1,
+	.apic			= 1,
+	/* use highest bit to detect overflow */
+	.max_period		= (1ULL << 47) - 1,
+	.get_event_constraints	= amd_get_event_constraints_f15h,
+	/* nortbridge counters not yet implemented: */
+#if 0
+	.put_event_constraints	= amd_put_event_constraints,
+
+	.cpu_prepare		= amd_pmu_cpu_prepare,
+	.cpu_starting		= amd_pmu_cpu_starting,
+	.cpu_dead		= amd_pmu_cpu_dead,
+#endif
+};
+
 static __init int amd_pmu_init(void)
 {
 	/* Performance-monitoring supported from K7 and later: */
 	if (boot_cpu_data.x86 < 6)
 		return -ENODEV;
 
-	x86_pmu = amd_pmu;
+	/*
+	 * If core performance counter extensions exists, it must be
+	 * family 15h, otherwise fail. See x86_pmu_addr_offset().
+	 */
+	switch (boot_cpu_data.x86) {
+	case 0x15:
+		if (!cpu_has_perfctr_core)
+			return -ENODEV;
+		x86_pmu = amd_pmu_f15h;
+		break;
+	default:
+		if (cpu_has_perfctr_core)
+			return -ENODEV;
+		x86_pmu = amd_pmu;
+		break;
+	}
 
 	/* Events are common for all AMDs */
 	memcpy(hw_cache_event_ids, amd_hw_cache_event_ids,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include <asm/stacktrace.h>
 #include <asm/nmi.h>
 #include <asm/compat.h>
+#include <asm/smp.h>
 
 #if 0
 #undef wrmsrl
@@ -93,6 +94,8 @@
 	struct event_constraint event_constraints[X86_PMC_IDX_MAX];
 };
 
+struct intel_percore;
+
 #define MAX_LBR_ENTRIES		16
 
 struct cpu_hw_events {
@@ -128,6 +131,13 @@
 	struct perf_branch_entry	lbr_entries[MAX_LBR_ENTRIES];
 
 	/*
+	 * Intel percore register state.
+	 * Coordinate shared resources between HT threads.
+	 */
+	int				percore_used; /* Used by this CPU? */
+	struct intel_percore		*per_core;
+
+	/*
 	 * AMD specific bits
 	 */
 	struct amd_nb		*amd_nb;
@@ -166,7 +176,7 @@
 /*
  * Constraint on the Event code + UMask
  */
-#define PEBS_EVENT_CONSTRAINT(c, n)	\
+#define INTEL_UEVENT_CONSTRAINT(c, n)	\
 	EVENT_CONSTRAINT(c, n, INTEL_ARCH_EVENT_MASK)
 
 #define EVENT_CONSTRAINT_END		\
@@ -175,6 +185,28 @@
 #define for_each_event_constraint(e, c)	\
 	for ((e) = (c); (e)->weight; (e)++)
 
+/*
+ * Extra registers for specific events.
+ * Some events need large masks and require external MSRs.
+ * Define a mapping to these extra registers.
+ */
+struct extra_reg {
+	unsigned int		event;
+	unsigned int		msr;
+	u64			config_mask;
+	u64			valid_mask;
+};
+
+#define EVENT_EXTRA_REG(e, ms, m, vm) {	\
+	.event = (e),		\
+	.msr = (ms),		\
+	.config_mask = (m),	\
+	.valid_mask = (vm),	\
+	}
+#define INTEL_EVENT_EXTRA_REG(event, msr, vm)	\
+	EVENT_EXTRA_REG(event, msr, ARCH_PERFMON_EVENTSEL_EVENT, vm)
+#define EVENT_EXTRA_END EVENT_EXTRA_REG(0, 0, 0, 0)
+
 union perf_capabilities {
 	struct {
 		u64	lbr_format    : 6;
@@ -219,6 +251,7 @@
 	void		(*put_event_constraints)(struct cpu_hw_events *cpuc,
 						 struct perf_event *event);
 	struct event_constraint *event_constraints;
+	struct event_constraint *percore_constraints;
 	void		(*quirks)(void);
 	int		perfctr_second_write;
 
@@ -247,6 +280,11 @@
 	 */
 	unsigned long	lbr_tos, lbr_from, lbr_to; /* MSR base regs       */
 	int		lbr_nr;			   /* hardware stack size */
+
+	/*
+	 * Extra registers for events
+	 */
+	struct extra_reg *extra_regs;
 };
 
 static struct x86_pmu x86_pmu __read_mostly;
@@ -271,6 +309,10 @@
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
 				[PERF_COUNT_HW_CACHE_RESULT_MAX];
+static u64 __read_mostly hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX];
 
 /*
  * Propagate event elapsed time into the generic event.
@@ -298,7 +340,7 @@
 	 */
 again:
 	prev_raw_count = local64_read(&hwc->prev_count);
-	rdmsrl(hwc->event_base + idx, new_raw_count);
+	rdmsrl(hwc->event_base, new_raw_count);
 
 	if (local64_cmpxchg(&hwc->prev_count, prev_raw_count,
 					new_raw_count) != prev_raw_count)
@@ -321,6 +363,49 @@
 	return new_raw_count;
 }
 
+/* using X86_FEATURE_PERFCTR_CORE to later implement ALTERNATIVE() here */
+static inline int x86_pmu_addr_offset(int index)
+{
+	if (boot_cpu_has(X86_FEATURE_PERFCTR_CORE))
+		return index << 1;
+	return index;
+}
+
+static inline unsigned int x86_pmu_config_addr(int index)
+{
+	return x86_pmu.eventsel + x86_pmu_addr_offset(index);
+}
+
+static inline unsigned int x86_pmu_event_addr(int index)
+{
+	return x86_pmu.perfctr + x86_pmu_addr_offset(index);
+}
+
+/*
+ * Find and validate any extra registers to set up.
+ */
+static int x86_pmu_extra_regs(u64 config, struct perf_event *event)
+{
+	struct extra_reg *er;
+
+	event->hw.extra_reg = 0;
+	event->hw.extra_config = 0;
+
+	if (!x86_pmu.extra_regs)
+		return 0;
+
+	for (er = x86_pmu.extra_regs; er->msr; er++) {
+		if (er->event != (config & er->config_mask))
+			continue;
+		if (event->attr.config1 & ~er->valid_mask)
+			return -EINVAL;
+		event->hw.extra_reg = er->msr;
+		event->hw.extra_config = event->attr.config1;
+		break;
+	}
+	return 0;
+}
+
 static atomic_t active_events;
 static DEFINE_MUTEX(pmc_reserve_mutex);
 
@@ -331,12 +416,12 @@
 	int i;
 
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		if (!reserve_perfctr_nmi(x86_pmu.perfctr + i))
+		if (!reserve_perfctr_nmi(x86_pmu_event_addr(i)))
 			goto perfctr_fail;
 	}
 
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		if (!reserve_evntsel_nmi(x86_pmu.eventsel + i))
+		if (!reserve_evntsel_nmi(x86_pmu_config_addr(i)))
 			goto eventsel_fail;
 	}
 
@@ -344,13 +429,13 @@
 
 eventsel_fail:
 	for (i--; i >= 0; i--)
-		release_evntsel_nmi(x86_pmu.eventsel + i);
+		release_evntsel_nmi(x86_pmu_config_addr(i));
 
 	i = x86_pmu.num_counters;
 
 perfctr_fail:
 	for (i--; i >= 0; i--)
-		release_perfctr_nmi(x86_pmu.perfctr + i);
+		release_perfctr_nmi(x86_pmu_event_addr(i));
 
 	return false;
 }
@@ -360,8 +445,8 @@
 	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);
+		release_perfctr_nmi(x86_pmu_event_addr(i));
+		release_evntsel_nmi(x86_pmu_config_addr(i));
 	}
 }
 
@@ -382,7 +467,7 @@
 	 * complain and bail.
 	 */
 	for (i = 0; i < x86_pmu.num_counters; i++) {
-		reg = x86_pmu.eventsel + i;
+		reg = x86_pmu_config_addr(i);
 		ret = rdmsrl_safe(reg, &val);
 		if (ret)
 			goto msr_fail;
@@ -407,20 +492,25 @@
 	 * that don't trap on the MSR access and always return 0s.
 	 */
 	val = 0xabcdUL;
-	ret = checking_wrmsrl(x86_pmu.perfctr, val);
-	ret |= rdmsrl_safe(x86_pmu.perfctr, &val_new);
+	ret = checking_wrmsrl(x86_pmu_event_addr(0), val);
+	ret |= rdmsrl_safe(x86_pmu_event_addr(0), &val_new);
 	if (ret || val != val_new)
 		goto msr_fail;
 
 	return true;
 
 bios_fail:
-	printk(KERN_CONT "Broken BIOS detected, using software events only.\n");
+	/*
+	 * We still allow the PMU driver to operate:
+	 */
+	printk(KERN_CONT "Broken BIOS detected, complain to your hardware vendor.\n");
 	printk(KERN_ERR FW_BUG "the BIOS has corrupted hw-PMU resources (MSR %x is %Lx)\n", reg, val);
-	return false;
+
+	return true;
 
 msr_fail:
 	printk(KERN_CONT "Broken PMU hardware detected, using software events only.\n");
+
 	return false;
 }
 
@@ -442,8 +532,9 @@
 }
 
 static inline int
-set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event_attr *attr)
+set_ext_hw_attr(struct hw_perf_event *hwc, struct perf_event *event)
 {
+	struct perf_event_attr *attr = &event->attr;
 	unsigned int cache_type, cache_op, cache_result;
 	u64 config, val;
 
@@ -470,8 +561,8 @@
 		return -EINVAL;
 
 	hwc->config |= val;
-
-	return 0;
+	attr->config1 = hw_cache_extra_regs[cache_type][cache_op][cache_result];
+	return x86_pmu_extra_regs(val, event);
 }
 
 static int x86_setup_perfctr(struct perf_event *event)
@@ -495,11 +586,15 @@
 			return -EOPNOTSUPP;
 	}
 
+	/*
+	 * Do not allow config1 (extended registers) to propagate,
+	 * there's no sane user-space generalization yet:
+	 */
 	if (attr->type == PERF_TYPE_RAW)
 		return 0;
 
 	if (attr->type == PERF_TYPE_HW_CACHE)
-		return set_ext_hw_attr(hwc, attr);
+		return set_ext_hw_attr(hwc, event);
 
 	if (attr->config >= x86_pmu.max_events)
 		return -EINVAL;
@@ -518,8 +613,8 @@
 	/*
 	 * Branch tracing:
 	 */
-	if ((attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
-	    (hwc->sample_period == 1)) {
+	if (attr->config == PERF_COUNT_HW_BRANCH_INSTRUCTIONS &&
+	    !attr->freq && hwc->sample_period == 1) {
 		/* BTS is not supported by this architecture. */
 		if (!x86_pmu.bts_active)
 			return -EOPNOTSUPP;
@@ -617,11 +712,11 @@
 
 		if (!test_bit(idx, cpuc->active_mask))
 			continue;
-		rdmsrl(x86_pmu.eventsel + idx, val);
+		rdmsrl(x86_pmu_config_addr(idx), val);
 		if (!(val & ARCH_PERFMON_EVENTSEL_ENABLE))
 			continue;
 		val &= ~ARCH_PERFMON_EVENTSEL_ENABLE;
-		wrmsrl(x86_pmu.eventsel + idx, val);
+		wrmsrl(x86_pmu_config_addr(idx), val);
 	}
 }
 
@@ -642,21 +737,26 @@
 	x86_pmu.disable_all();
 }
 
+static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
+					  u64 enable_mask)
+{
+	if (hwc->extra_reg)
+		wrmsrl(hwc->extra_reg, hwc->extra_config);
+	wrmsrl(hwc->config_base, hwc->config | enable_mask);
+}
+
 static void x86_pmu_enable_all(int added)
 {
 	struct cpu_hw_events *cpuc = &__get_cpu_var(cpu_hw_events);
 	int idx;
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-		struct perf_event *event = cpuc->events[idx];
-		u64 val;
+		struct hw_perf_event *hwc = &cpuc->events[idx]->hw;
 
 		if (!test_bit(idx, cpuc->active_mask))
 			continue;
 
-		val = event->hw.config;
-		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
-		wrmsrl(x86_pmu.eventsel + idx, val);
+		__x86_pmu_enable_event(hwc, ARCH_PERFMON_EVENTSEL_ENABLE);
 	}
 }
 
@@ -821,15 +921,10 @@
 		hwc->event_base	= 0;
 	} else if (hwc->idx >= X86_PMC_IDX_FIXED) {
 		hwc->config_base = MSR_ARCH_PERFMON_FIXED_CTR_CTRL;
-		/*
-		 * We set it so that event_base + idx in wrmsr/rdmsr maps to
-		 * MSR_ARCH_PERFMON_FIXED_CTR0 ... CTR2:
-		 */
-		hwc->event_base =
-			MSR_ARCH_PERFMON_FIXED_CTR0 - X86_PMC_IDX_FIXED;
+		hwc->event_base = MSR_ARCH_PERFMON_FIXED_CTR0 + (hwc->idx - X86_PMC_IDX_FIXED);
 	} else {
-		hwc->config_base = x86_pmu.eventsel;
-		hwc->event_base  = x86_pmu.perfctr;
+		hwc->config_base = x86_pmu_config_addr(hwc->idx);
+		hwc->event_base  = x86_pmu_event_addr(hwc->idx);
 	}
 }
 
@@ -915,17 +1010,11 @@
 	x86_pmu.enable_all(added);
 }
 
-static inline void __x86_pmu_enable_event(struct hw_perf_event *hwc,
-					  u64 enable_mask)
-{
-	wrmsrl(hwc->config_base + hwc->idx, hwc->config | enable_mask);
-}
-
 static inline void x86_pmu_disable_event(struct perf_event *event)
 {
 	struct hw_perf_event *hwc = &event->hw;
 
-	wrmsrl(hwc->config_base + hwc->idx, hwc->config);
+	wrmsrl(hwc->config_base, hwc->config);
 }
 
 static DEFINE_PER_CPU(u64 [X86_PMC_IDX_MAX], pmc_prev_left);
@@ -978,7 +1067,7 @@
 	 */
 	local64_set(&hwc->prev_count, (u64)-left);
 
-	wrmsrl(hwc->event_base + idx, (u64)(-left) & x86_pmu.cntval_mask);
+	wrmsrl(hwc->event_base, (u64)(-left) & x86_pmu.cntval_mask);
 
 	/*
 	 * Due to erratum on certan cpu we need
@@ -986,7 +1075,7 @@
 	 * is updated properly
 	 */
 	if (x86_pmu.perfctr_second_write) {
-		wrmsrl(hwc->event_base + idx,
+		wrmsrl(hwc->event_base,
 			(u64)(-left) & x86_pmu.cntval_mask);
 	}
 
@@ -1029,7 +1118,7 @@
 
 	/*
 	 * If group events scheduling transaction was started,
-	 * skip the schedulability test here, it will be peformed
+	 * skip the schedulability test here, it will be performed
 	 * at commit time (->commit_txn) as a whole
 	 */
 	if (cpuc->group_flag & PERF_EVENT_TXN)
@@ -1113,8 +1202,8 @@
 	pr_info("CPU#%d: active:     %016llx\n", cpu, *(u64 *)cpuc->active_mask);
 
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
-		rdmsrl(x86_pmu.eventsel + idx, pmc_ctrl);
-		rdmsrl(x86_pmu.perfctr  + idx, pmc_count);
+		rdmsrl(x86_pmu_config_addr(idx), pmc_ctrl);
+		rdmsrl(x86_pmu_event_addr(idx), pmc_count);
 
 		prev_left = per_cpu(pmc_prev_left[idx], cpu);
 
@@ -1199,6 +1288,16 @@
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
+	/*
+	 * Some chipsets need to unmask the LVTPC in a particular spot
+	 * inside the nmi handler.  As a result, the unmasking was pushed
+	 * into all the nmi handlers.
+	 *
+	 * This generic handler doesn't seem to have any issues where the
+	 * unmasking occurs so it was left at the top.
+	 */
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+
 	for (idx = 0; idx < x86_pmu.num_counters; idx++) {
 		if (!test_bit(idx, cpuc->active_mask)) {
 			/*
@@ -1285,8 +1384,6 @@
 		return NOTIFY_DONE;
 	}
 
-	apic_write(APIC_LVTPC, APIC_DM_NMI);
-
 	handled = x86_pmu.handle_irq(args->regs);
 	if (!handled)
 		return NOTIFY_DONE;
@@ -1389,7 +1486,7 @@
 	pr_info("no hardware sampling interrupt available.\n");
 }
 
-int __init init_hw_perf_events(void)
+static int __init init_hw_perf_events(void)
 {
 	struct event_constraint *c;
 	int err;
@@ -1608,7 +1705,7 @@
 	return ret;
 }
 
-int x86_pmu_event_init(struct perf_event *event)
+static int x86_pmu_event_init(struct perf_event *event)
 {
 	struct pmu *tmp;
 	int err;
@@ -1710,7 +1807,7 @@
 
 	perf_callchain_store(entry, regs->ip);
 
-	dump_trace(NULL, regs, NULL, &backtrace_ops, entry);
+	dump_trace(NULL, regs, NULL, 0, &backtrace_ops, entry);
 }
 
 #ifdef CONFIG_COMPAT
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_intel.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_intel.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_intel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_intel.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,9 +1,31 @@
 #ifdef CONFIG_CPU_SUP_INTEL
 
+#define MAX_EXTRA_REGS 2
+
+/*
+ * Per register state.
+ */
+struct er_account {
+	int			ref;		/* reference count */
+	unsigned int		extra_reg;	/* extra MSR number */
+	u64			extra_config;	/* extra MSR config */
+};
+
+/*
+ * Per core state
+ * This used to coordinate shared registers for HT threads.
+ */
+struct intel_percore {
+	raw_spinlock_t		lock;		/* protect structure */
+	struct er_account	regs[MAX_EXTRA_REGS];
+	int			refcnt;		/* number of threads */
+	unsigned		core_id;
+};
+
 /*
  * Intel PerfMon, used on Core and later.
  */
-static const u64 intel_perfmon_event_map[] =
+static u64 intel_perfmon_event_map[PERF_COUNT_HW_MAX] __read_mostly =
 {
   [PERF_COUNT_HW_CPU_CYCLES]		= 0x003c,
   [PERF_COUNT_HW_INSTRUCTIONS]		= 0x00c0,
@@ -64,6 +86,18 @@
 	EVENT_CONSTRAINT_END
 };
 
+static struct extra_reg intel_nehalem_extra_regs[] =
+{
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
+	EVENT_EXTRA_END
+};
+
+static struct event_constraint intel_nehalem_percore_constraints[] =
+{
+	INTEL_EVENT_CONSTRAINT(0xb7, 0),
+	EVENT_CONSTRAINT_END
+};
+
 static struct event_constraint intel_westmere_event_constraints[] =
 {
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -76,6 +110,33 @@
 	EVENT_CONSTRAINT_END
 };
 
+static struct event_constraint intel_snb_event_constraints[] =
+{
+	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
+	FIXED_EVENT_CONSTRAINT(0x003c, 1), /* CPU_CLK_UNHALTED.CORE */
+	/* FIXED_EVENT_CONSTRAINT(0x013c, 2), CPU_CLK_UNHALTED.REF */
+	INTEL_EVENT_CONSTRAINT(0x48, 0x4), /* L1D_PEND_MISS.PENDING */
+	INTEL_EVENT_CONSTRAINT(0xb7, 0x1), /* OFF_CORE_RESPONSE_0 */
+	INTEL_EVENT_CONSTRAINT(0xbb, 0x8), /* OFF_CORE_RESPONSE_1 */
+	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PREC_DIST */
+	INTEL_EVENT_CONSTRAINT(0xcd, 0x8), /* MEM_TRANS_RETIRED.LOAD_LATENCY */
+	EVENT_CONSTRAINT_END
+};
+
+static struct extra_reg intel_westmere_extra_regs[] =
+{
+	INTEL_EVENT_EXTRA_REG(0xb7, MSR_OFFCORE_RSP_0, 0xffff),
+	INTEL_EVENT_EXTRA_REG(0xbb, MSR_OFFCORE_RSP_1, 0xffff),
+	EVENT_EXTRA_END
+};
+
+static struct event_constraint intel_westmere_percore_constraints[] =
+{
+	INTEL_EVENT_CONSTRAINT(0xb7, 0),
+	INTEL_EVENT_CONSTRAINT(0xbb, 0),
+	EVENT_CONSTRAINT_END
+};
+
 static struct event_constraint intel_gen_event_constraints[] =
 {
 	FIXED_EVENT_CONSTRAINT(0x00c0, 0), /* INST_RETIRED.ANY */
@@ -89,6 +150,103 @@
 	return intel_perfmon_event_map[hw_event];
 }
 
+static __initconst const u64 snb_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) ] = 0xf1d0, /* MEM_UOP_RETIRED.LOADS        */
+		[ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPLACEMENT              */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0xf2d0, /* MEM_UOP_RETIRED.STORES       */
+		[ C(RESULT_MISS)   ] = 0x0851, /* L1D.ALL_M_REPLACEMENT        */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x024e, /* HW_PRE_REQ.DL1_MISS          */
+	},
+ },
+ [ C(L1I ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0280, /* ICACHE.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) ] = {
+		/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+	[ C(OP_WRITE) ] = {
+		/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+	[ C(OP_PREFETCH) ] = {
+		/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
+	},
+ },
+ [ C(DTLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x81d0, /* MEM_UOP_RETIRED.ALL_LOADS */
+		[ C(RESULT_MISS)   ] = 0x0108, /* DTLB_LOAD_MISSES.CAUSES_A_WALK */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = 0x82d0, /* MEM_UOP_RETIRED.ALL_STORES */
+		[ C(RESULT_MISS)   ] = 0x0149, /* DTLB_STORE_MISSES.MISS_CAUSES_A_WALK */
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = 0x0,
+		[ C(RESULT_MISS)   ] = 0x0,
+	},
+ },
+ [ C(ITLB) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = 0x1085, /* ITLB_MISSES.STLB_HIT         */
+		[ C(RESULT_MISS)   ] = 0x0185, /* ITLB_MISSES.CAUSES_A_WALK    */
+	},
+	[ 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)   ] = 0x00c5, /* BR_MISP_RETIRED.ALL_BRANCHES */
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = -1,
+		[ C(RESULT_MISS)   ] = -1,
+	},
+ },
+};
+
 static __initconst const u64 westmere_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -124,16 +282,26 @@
  },
  [ C(LL  ) ] = {
 	[ C(OP_READ) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS               */
-		[ C(RESULT_MISS)   ] = 0x0224, /* L2_RQSTS.LD_MISS             */
+		/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
+	/*
+	 * Use RFO, not WRITEBACK, because a write miss would typically occur
+	 * on RFO.
+	 */
 	[ C(OP_WRITE) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS                */
-		[ C(RESULT_MISS)   ] = 0x0824, /* L2_RQSTS.RFO_MISS            */
+		/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
 	[ C(OP_PREFETCH) ] = {
-		[ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference                */
-		[ C(RESULT_MISS)   ] = 0x412e, /* LLC Misses                   */
+		/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
  },
  [ C(DTLB) ] = {
@@ -180,6 +348,59 @@
  },
 };
 
+/*
+ * Nehalem/Westmere MSR_OFFCORE_RESPONSE bits;
+ * See IA32 SDM Vol 3B 30.6.1.3
+ */
+
+#define NHM_DMND_DATA_RD	(1 << 0)
+#define NHM_DMND_RFO		(1 << 1)
+#define NHM_DMND_IFETCH		(1 << 2)
+#define NHM_DMND_WB		(1 << 3)
+#define NHM_PF_DATA_RD		(1 << 4)
+#define NHM_PF_DATA_RFO		(1 << 5)
+#define NHM_PF_IFETCH		(1 << 6)
+#define NHM_OFFCORE_OTHER	(1 << 7)
+#define NHM_UNCORE_HIT		(1 << 8)
+#define NHM_OTHER_CORE_HIT_SNP	(1 << 9)
+#define NHM_OTHER_CORE_HITM	(1 << 10)
+        			/* reserved */
+#define NHM_REMOTE_CACHE_FWD	(1 << 12)
+#define NHM_REMOTE_DRAM		(1 << 13)
+#define NHM_LOCAL_DRAM		(1 << 14)
+#define NHM_NON_DRAM		(1 << 15)
+
+#define NHM_ALL_DRAM		(NHM_REMOTE_DRAM|NHM_LOCAL_DRAM)
+
+#define NHM_DMND_READ		(NHM_DMND_DATA_RD)
+#define NHM_DMND_WRITE		(NHM_DMND_RFO|NHM_DMND_WB)
+#define NHM_DMND_PREFETCH	(NHM_PF_DATA_RD|NHM_PF_DATA_RFO)
+
+#define NHM_L3_HIT	(NHM_UNCORE_HIT|NHM_OTHER_CORE_HIT_SNP|NHM_OTHER_CORE_HITM)
+#define NHM_L3_MISS	(NHM_NON_DRAM|NHM_ALL_DRAM|NHM_REMOTE_CACHE_FWD)
+#define NHM_L3_ACCESS	(NHM_L3_HIT|NHM_L3_MISS)
+
+static __initconst const u64 nehalem_hw_cache_extra_regs
+				[PERF_COUNT_HW_CACHE_MAX]
+				[PERF_COUNT_HW_CACHE_OP_MAX]
+				[PERF_COUNT_HW_CACHE_RESULT_MAX] =
+{
+ [ C(LL  ) ] = {
+	[ C(OP_READ) ] = {
+		[ C(RESULT_ACCESS) ] = NHM_DMND_READ|NHM_L3_ACCESS,
+		[ C(RESULT_MISS)   ] = NHM_DMND_READ|NHM_L3_MISS,
+	},
+	[ C(OP_WRITE) ] = {
+		[ C(RESULT_ACCESS) ] = NHM_DMND_WRITE|NHM_L3_ACCESS,
+		[ C(RESULT_MISS)   ] = NHM_DMND_WRITE|NHM_L3_MISS,
+	},
+	[ C(OP_PREFETCH) ] = {
+		[ C(RESULT_ACCESS) ] = NHM_DMND_PREFETCH|NHM_L3_ACCESS,
+		[ C(RESULT_MISS)   ] = NHM_DMND_PREFETCH|NHM_L3_MISS,
+	},
+ }
+};
+
 static __initconst const u64 nehalem_hw_cache_event_ids
 				[PERF_COUNT_HW_CACHE_MAX]
 				[PERF_COUNT_HW_CACHE_OP_MAX]
@@ -187,12 +408,12 @@
 {
  [ C(L1D) ] = {
 	[ C(OP_READ) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0f40, /* L1D_CACHE_LD.MESI            */
-		[ C(RESULT_MISS)   ] = 0x0140, /* L1D_CACHE_LD.I_STATE         */
+		[ C(RESULT_ACCESS) ] = 0x010b, /* MEM_INST_RETIRED.LOADS       */
+		[ C(RESULT_MISS)   ] = 0x0151, /* L1D.REPL                     */
 	},
 	[ C(OP_WRITE) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0f41, /* L1D_CACHE_ST.MESI            */
-		[ C(RESULT_MISS)   ] = 0x0141, /* L1D_CACHE_ST.I_STATE         */
+		[ C(RESULT_ACCESS) ] = 0x020b, /* MEM_INST_RETURED.STORES      */
+		[ C(RESULT_MISS)   ] = 0x0251, /* L1D.M_REPL                   */
 	},
 	[ C(OP_PREFETCH) ] = {
 		[ C(RESULT_ACCESS) ] = 0x014e, /* L1D_PREFETCH.REQUESTS        */
@@ -215,16 +436,26 @@
  },
  [ C(LL  ) ] = {
 	[ C(OP_READ) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0324, /* L2_RQSTS.LOADS               */
-		[ C(RESULT_MISS)   ] = 0x0224, /* L2_RQSTS.LD_MISS             */
+		/* OFFCORE_RESPONSE.ANY_DATA.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_DATA.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
+	/*
+	 * Use RFO, not WRITEBACK, because a write miss would typically occur
+	 * on RFO.
+	 */
 	[ C(OP_WRITE) ] = {
-		[ C(RESULT_ACCESS) ] = 0x0c24, /* L2_RQSTS.RFOS                */
-		[ C(RESULT_MISS)   ] = 0x0824, /* L2_RQSTS.RFO_MISS            */
+		/* OFFCORE_RESPONSE.ANY_RFO.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.ANY_RFO.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
 	[ C(OP_PREFETCH) ] = {
-		[ C(RESULT_ACCESS) ] = 0x4f2e, /* LLC Reference                */
-		[ C(RESULT_MISS)   ] = 0x412e, /* LLC Misses                   */
+		/* OFFCORE_RESPONSE.PREFETCH.LOCAL_CACHE */
+		[ C(RESULT_ACCESS) ] = 0x01b7,
+		/* OFFCORE_RESPONSE.PREFETCH.ANY_LLC_MISS */
+		[ C(RESULT_MISS)   ] = 0x01b7,
 	},
  },
  [ C(DTLB) ] = {
@@ -691,8 +922,8 @@
 	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);
+		checking_wrmsrl(x86_pmu_config_addr(idx), 0ull);
+		checking_wrmsrl(x86_pmu_event_addr(idx),  0ull);
 	}
 	for (idx = 0; idx < x86_pmu.num_counters_fixed; idx++)
 		checking_wrmsrl(MSR_ARCH_PERFMON_FIXED_CTR0 + idx, 0ull);
@@ -719,6 +950,16 @@
 
 	cpuc = &__get_cpu_var(cpu_hw_events);
 
+	/*
+	 * Some chipsets need to unmask the LVTPC in a particular spot
+	 * inside the nmi handler.  As a result, the unmasking was pushed
+	 * into all the nmi handlers.
+	 *
+	 * This handler doesn't seem to have any issues with the unmasking
+	 * so it was left at the top.
+	 */
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
+
 	intel_pmu_disable_all();
 	handled = intel_pmu_drain_bts_buffer();
 	status = intel_pmu_get_status();
@@ -784,6 +1025,9 @@
 	struct hw_perf_event *hwc = &event->hw;
 	unsigned int hw_event, bts_event;
 
+	if (event->attr.freq)
+		return NULL;
+
 	hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
 	bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
@@ -794,6 +1038,67 @@
 }
 
 static struct event_constraint *
+intel_percore_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
+{
+	struct hw_perf_event *hwc = &event->hw;
+	unsigned int e = hwc->config & ARCH_PERFMON_EVENTSEL_EVENT;
+	struct event_constraint *c;
+	struct intel_percore *pc;
+	struct er_account *era;
+	int i;
+	int free_slot;
+	int found;
+
+	if (!x86_pmu.percore_constraints || hwc->extra_alloc)
+		return NULL;
+
+	for (c = x86_pmu.percore_constraints; c->cmask; c++) {
+		if (e != c->code)
+			continue;
+
+		/*
+		 * Allocate resource per core.
+		 */
+		pc = cpuc->per_core;
+		if (!pc)
+			break;
+		c = &emptyconstraint;
+		raw_spin_lock(&pc->lock);
+		free_slot = -1;
+		found = 0;
+		for (i = 0; i < MAX_EXTRA_REGS; i++) {
+			era = &pc->regs[i];
+			if (era->ref > 0 && hwc->extra_reg == era->extra_reg) {
+				/* Allow sharing same config */
+				if (hwc->extra_config == era->extra_config) {
+					era->ref++;
+					cpuc->percore_used = 1;
+					hwc->extra_alloc = 1;
+					c = NULL;
+				}
+				/* else conflict */
+				found = 1;
+				break;
+			} else if (era->ref == 0 && free_slot == -1)
+				free_slot = i;
+		}
+		if (!found && free_slot != -1) {
+			era = &pc->regs[free_slot];
+			era->ref = 1;
+			era->extra_reg = hwc->extra_reg;
+			era->extra_config = hwc->extra_config;
+			cpuc->percore_used = 1;
+			hwc->extra_alloc = 1;
+			c = NULL;
+		}
+		raw_spin_unlock(&pc->lock);
+		return c;
+	}
+
+	return NULL;
+}
+
+static struct event_constraint *
 intel_get_event_constraints(struct cpu_hw_events *cpuc, struct perf_event *event)
 {
 	struct event_constraint *c;
@@ -806,9 +1111,51 @@
 	if (c)
 		return c;
 
+	c = intel_percore_constraints(cpuc, event);
+	if (c)
+		return c;
+
 	return x86_get_event_constraints(cpuc, event);
 }
 
+static void intel_put_event_constraints(struct cpu_hw_events *cpuc,
+					struct perf_event *event)
+{
+	struct extra_reg *er;
+	struct intel_percore *pc;
+	struct er_account *era;
+	struct hw_perf_event *hwc = &event->hw;
+	int i, allref;
+
+	if (!cpuc->percore_used)
+		return;
+
+	for (er = x86_pmu.extra_regs; er->msr; er++) {
+		if (er->event != (hwc->config & er->config_mask))
+			continue;
+
+		pc = cpuc->per_core;
+		raw_spin_lock(&pc->lock);
+		for (i = 0; i < MAX_EXTRA_REGS; i++) {
+			era = &pc->regs[i];
+			if (era->ref > 0 &&
+			    era->extra_config == hwc->extra_config &&
+			    era->extra_reg == er->msr) {
+				era->ref--;
+				hwc->extra_alloc = 0;
+				break;
+			}
+		}
+		allref = 0;
+		for (i = 0; i < MAX_EXTRA_REGS; i++)
+			allref += pc->regs[i].ref;
+		if (allref == 0)
+			cpuc->percore_used = 0;
+		raw_spin_unlock(&pc->lock);
+		break;
+	}
+}
+
 static int intel_pmu_hw_config(struct perf_event *event)
 {
 	int ret = x86_pmu_hw_config(event);
@@ -880,20 +1227,67 @@
 	 */
 	.max_period		= (1ULL << 31) - 1,
 	.get_event_constraints	= intel_get_event_constraints,
+	.put_event_constraints	= intel_put_event_constraints,
 	.event_constraints	= intel_core_event_constraints,
 };
 
+static int intel_pmu_cpu_prepare(int cpu)
+{
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+
+	if (!cpu_has_ht_siblings())
+		return NOTIFY_OK;
+
+	cpuc->per_core = kzalloc_node(sizeof(struct intel_percore),
+				      GFP_KERNEL, cpu_to_node(cpu));
+	if (!cpuc->per_core)
+		return NOTIFY_BAD;
+
+	raw_spin_lock_init(&cpuc->per_core->lock);
+	cpuc->per_core->core_id = -1;
+	return NOTIFY_OK;
+}
+
 static void intel_pmu_cpu_starting(int cpu)
 {
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+	int core_id = topology_core_id(cpu);
+	int i;
+
 	init_debug_store_on_cpu(cpu);
 	/*
 	 * Deal with CPUs that don't clear their LBRs on power-up.
 	 */
 	intel_pmu_lbr_reset();
+
+	if (!cpu_has_ht_siblings())
+		return;
+
+	for_each_cpu(i, topology_thread_cpumask(cpu)) {
+		struct intel_percore *pc = per_cpu(cpu_hw_events, i).per_core;
+
+		if (pc && pc->core_id == core_id) {
+			kfree(cpuc->per_core);
+			cpuc->per_core = pc;
+			break;
+		}
+	}
+
+	cpuc->per_core->core_id = core_id;
+	cpuc->per_core->refcnt++;
 }
 
 static void intel_pmu_cpu_dying(int cpu)
 {
+	struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
+	struct intel_percore *pc = cpuc->per_core;
+
+	if (pc) {
+		if (pc->core_id == -1 || --pc->refcnt == 0)
+			kfree(pc);
+		cpuc->per_core = NULL;
+	}
+
 	fini_debug_store_on_cpu(cpu);
 }
 
@@ -918,7 +1312,9 @@
 	 */
 	.max_period		= (1ULL << 31) - 1,
 	.get_event_constraints	= intel_get_event_constraints,
+	.put_event_constraints	= intel_put_event_constraints,
 
+	.cpu_prepare		= intel_pmu_cpu_prepare,
 	.cpu_starting		= intel_pmu_cpu_starting,
 	.cpu_dying		= intel_pmu_cpu_dying,
 };
@@ -939,7 +1335,7 @@
 	 * AJ106 could possibly be worked around by not allowing LBR
 	 *       usage from PEBS, including the fixup.
 	 * AJ68  could possibly be worked around by always programming
-	 * 	 a pebs_event_reset[0] value and coping with the lost events.
+	 *	 a pebs_event_reset[0] value and coping with the lost events.
 	 *
 	 * But taken together it might just make sense to not enable PEBS on
 	 * these chips.
@@ -1024,6 +1420,7 @@
 		intel_pmu_lbr_init_core();
 
 		x86_pmu.event_constraints = intel_core2_event_constraints;
+		x86_pmu.pebs_constraints = intel_core2_pebs_event_constraints;
 		pr_cont("Core2 events, ");
 		break;
 
@@ -1032,11 +1429,28 @@
 	case 46: /* 45 nm nehalem-ex, "Beckton" */
 		memcpy(hw_cache_event_ids, nehalem_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
+		memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
+		       sizeof(hw_cache_extra_regs));
 
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_nehalem_event_constraints;
+		x86_pmu.pebs_constraints = intel_nehalem_pebs_event_constraints;
+		x86_pmu.percore_constraints = intel_nehalem_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
+		x86_pmu.extra_regs = intel_nehalem_extra_regs;
+
+		if (ebx & 0x40) {
+			/*
+			 * Erratum AAJ80 detected, we work it around by using
+			 * the BR_MISP_EXEC.ANY event. This will over-count
+			 * branch-misses, but it's still much better than the
+			 * architectural event which is often completely bogus:
+			 */
+			intel_perfmon_event_map[PERF_COUNT_HW_BRANCH_MISSES] = 0x7f89;
+
+			pr_cont("erratum AAJ80 worked around, ");
+		}
 		pr_cont("Nehalem events, ");
 		break;
 
@@ -1047,21 +1461,39 @@
 		intel_pmu_lbr_init_atom();
 
 		x86_pmu.event_constraints = intel_gen_event_constraints;
+		x86_pmu.pebs_constraints = intel_atom_pebs_event_constraints;
 		pr_cont("Atom events, ");
 		break;
 
 	case 37: /* 32 nm nehalem, "Clarkdale" */
 	case 44: /* 32 nm nehalem, "Gulftown" */
+	case 47: /* 32 nm Xeon E7 */
 		memcpy(hw_cache_event_ids, westmere_hw_cache_event_ids,
 		       sizeof(hw_cache_event_ids));
+		memcpy(hw_cache_extra_regs, nehalem_hw_cache_extra_regs,
+		       sizeof(hw_cache_extra_regs));
 
 		intel_pmu_lbr_init_nhm();
 
 		x86_pmu.event_constraints = intel_westmere_event_constraints;
+		x86_pmu.percore_constraints = intel_westmere_percore_constraints;
 		x86_pmu.enable_all = intel_pmu_nhm_enable_all;
+		x86_pmu.pebs_constraints = intel_westmere_pebs_event_constraints;
+		x86_pmu.extra_regs = intel_westmere_extra_regs;
 		pr_cont("Westmere events, ");
 		break;
 
+	case 42: /* SandyBridge */
+		memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+		       sizeof(hw_cache_event_ids));
+
+		intel_pmu_lbr_init_nhm();
+
+		x86_pmu.event_constraints = intel_snb_event_constraints;
+		x86_pmu.pebs_constraints = intel_snb_pebs_events;
+		pr_cont("SandyBridge events, ");
+		break;
+
 	default:
 		/*
 		 * default constraints for v2 and up
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_intel_ds.c	2011-05-19 00:06:34.000000000 -0400
@@ -361,30 +361,70 @@
 /*
  * PEBS
  */
+static struct event_constraint intel_core2_pebs_event_constraints[] = {
+	INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+	INTEL_UEVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
+	INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
+	INTEL_UEVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
+	EVENT_CONSTRAINT_END
+};
 
-static struct event_constraint intel_core_pebs_events[] = {
-	PEBS_EVENT_CONSTRAINT(0x00c0, 0x1), /* INSTR_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0xfec1, 0x1), /* X87_OPS_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x00c5, 0x1), /* BR_INST_RETIRED.MISPRED */
-	PEBS_EVENT_CONSTRAINT(0x1fc7, 0x1), /* SIMD_INST_RETURED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x01cb, 0x1), /* MEM_LOAD_RETIRED.L1D_MISS */
-	PEBS_EVENT_CONSTRAINT(0x02cb, 0x1), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x04cb, 0x1), /* MEM_LOAD_RETIRED.L2_MISS */
-	PEBS_EVENT_CONSTRAINT(0x08cb, 0x1), /* MEM_LOAD_RETIRED.L2_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x10cb, 0x1), /* MEM_LOAD_RETIRED.DTLB_MISS */
+static struct event_constraint intel_atom_pebs_event_constraints[] = {
+	INTEL_UEVENT_CONSTRAINT(0x00c0, 0x1), /* INST_RETIRED.ANY */
+	INTEL_UEVENT_CONSTRAINT(0x00c5, 0x1), /* MISPREDICTED_BRANCH_RETIRED */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0x1),    /* MEM_LOAD_RETIRED.* */
 	EVENT_CONSTRAINT_END
 };
 
-static struct event_constraint intel_nehalem_pebs_events[] = {
-	PEBS_EVENT_CONSTRAINT(0x00c0, 0xf), /* INSTR_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0xfec1, 0xf), /* X87_OPS_RETIRED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x00c5, 0xf), /* BR_INST_RETIRED.MISPRED */
-	PEBS_EVENT_CONSTRAINT(0x1fc7, 0xf), /* SIMD_INST_RETURED.ANY */
-	PEBS_EVENT_CONSTRAINT(0x01cb, 0xf), /* MEM_LOAD_RETIRED.L1D_MISS */
-	PEBS_EVENT_CONSTRAINT(0x02cb, 0xf), /* MEM_LOAD_RETIRED.L1D_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x04cb, 0xf), /* MEM_LOAD_RETIRED.L2_MISS */
-	PEBS_EVENT_CONSTRAINT(0x08cb, 0xf), /* MEM_LOAD_RETIRED.L2_LINE_MISS */
-	PEBS_EVENT_CONSTRAINT(0x10cb, 0xf), /* MEM_LOAD_RETIRED.DTLB_MISS */
+static struct event_constraint intel_nehalem_pebs_event_constraints[] = {
+	INTEL_EVENT_CONSTRAINT(0x0b, 0xf),    /* MEM_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+	INTEL_EVENT_CONSTRAINT(0xc0, 0xf),    /* INST_RETIRED.ANY */
+	INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x02c5, 0xf), /* BR_MISP_RETIRED.NEAR_CALL */
+	INTEL_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+	EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_westmere_pebs_event_constraints[] = {
+	INTEL_EVENT_CONSTRAINT(0x0b, 0xf),    /* MEM_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0x0f, 0xf),    /* MEM_UNCORE_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x010c, 0xf), /* MEM_STORE_RETIRED.DTLB_MISS */
+	INTEL_EVENT_CONSTRAINT(0xc0, 0xf),    /* INSTR_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc2, 0xf),    /* UOPS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc7, 0xf),    /* SSEX_UOPS_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x20c8, 0xf), /* ITLB_MISS_RETIRED */
+	INTEL_EVENT_CONSTRAINT(0xcb, 0xf),    /* MEM_LOAD_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xf7, 0xf),    /* FP_ASSIST.* */
+	EVENT_CONSTRAINT_END
+};
+
+static struct event_constraint intel_snb_pebs_events[] = {
+	INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+	INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
+	INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
+	INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xcd, 0x8),    /* MEM_TRANS_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x11d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x12d0, 0xf), /* MEM_UOP_RETIRED.STLB_MISS_STORES */
+	INTEL_UEVENT_CONSTRAINT(0x21d0, 0xf), /* MEM_UOP_RETIRED.LOCK_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x22d0, 0xf), /* MEM_UOP_RETIRED.LOCK_STORES */
+	INTEL_UEVENT_CONSTRAINT(0x41d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x42d0, 0xf), /* MEM_UOP_RETIRED.SPLIT_STORES */
+	INTEL_UEVENT_CONSTRAINT(0x81d0, 0xf), /* MEM_UOP_RETIRED.ANY_LOADS */
+	INTEL_UEVENT_CONSTRAINT(0x82d0, 0xf), /* MEM_UOP_RETIRED.ANY_STORES */
+	INTEL_EVENT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+	INTEL_EVENT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+	INTEL_UEVENT_CONSTRAINT(0x02d4, 0xf), /* MEM_LOAD_UOPS_MISC_RETIRED.LLC_MISS */
 	EVENT_CONSTRAINT_END
 };
 
@@ -695,20 +735,17 @@
 			printk(KERN_CONT "PEBS fmt0%c, ", pebs_type);
 			x86_pmu.pebs_record_size = sizeof(struct pebs_record_core);
 			x86_pmu.drain_pebs = intel_pmu_drain_pebs_core;
-			x86_pmu.pebs_constraints = intel_core_pebs_events;
 			break;
 
 		case 1:
 			printk(KERN_CONT "PEBS fmt1%c, ", pebs_type);
 			x86_pmu.pebs_record_size = sizeof(struct pebs_record_nhm);
 			x86_pmu.drain_pebs = intel_pmu_drain_pebs_nhm;
-			x86_pmu.pebs_constraints = intel_nehalem_pebs_events;
 			break;
 
 		default:
 			printk(KERN_CONT "no PEBS fmt%d%c, ", format, pebs_type);
 			x86_pmu.pebs = 0;
-			break;
 		}
 	}
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_p4.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_p4.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_p4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_p4.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Netburst Perfomance Events (P4, old Xeon)
+ * Netburst Performance Events (P4, old Xeon)
  *
  *  Copyright (C) 2010 Parallels, Inc., Cyrill Gorcunov <gorcunov@openvz.org>
  *  Copyright (C) 2010 Intel Corporation, Lin Ming <ming.m.lin@intel.com>
@@ -679,7 +679,7 @@
 	 */
 
 	/*
-	 * if an event is shared accross the logical threads
+	 * if an event is shared across the logical threads
 	 * the user needs special permissions to be able to use it
 	 */
 	if (p4_ht_active() && p4_event_bind_map[v].shared) {
@@ -764,9 +764,9 @@
 	u64 v;
 
 	/* an official way for overflow indication */
-	rdmsrl(hwc->config_base + hwc->idx, v);
+	rdmsrl(hwc->config_base, v);
 	if (v & P4_CCCR_OVF) {
-		wrmsrl(hwc->config_base + hwc->idx, v & ~P4_CCCR_OVF);
+		wrmsrl(hwc->config_base, v & ~P4_CCCR_OVF);
 		return 1;
 	}
 
@@ -777,6 +777,7 @@
 	 * the counter has reached zero value and continued counting before
 	 * real NMI signal was received:
 	 */
+	rdmsrl(hwc->event_base, v);
 	if (!(v & ARCH_P4_UNFLAGGED_BIT))
 		return 1;
 
@@ -790,13 +791,13 @@
 	 *
 	 * It's still allowed that two threads setup same cache
 	 * events so we can't simply clear metrics until we knew
-	 * noone is depending on us, so we need kind of counter
+	 * no one is depending on us, so we need kind of counter
 	 * for "ReplayEvent" users.
 	 *
 	 * What is more complex -- RAW events, if user (for some
 	 * reason) will pass some cache event metric with improper
 	 * event opcode -- it's fine from hardware point of view
-	 * but completely nonsence from "meaning" of such action.
+	 * but completely nonsense from "meaning" of such action.
 	 *
 	 * So at moment let leave metrics turned on forever -- it's
 	 * ok for now but need to be revisited!
@@ -815,7 +816,7 @@
 	 * state we need to clear P4_CCCR_OVF, otherwise interrupt get
 	 * asserted again and again
 	 */
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx,
+	(void)checking_wrmsrl(hwc->config_base,
 		(u64)(p4_config_unpack_cccr(hwc->config)) &
 			~P4_CCCR_ENABLE & ~P4_CCCR_OVF & ~P4_CCCR_RESERVED);
 }
@@ -885,7 +886,7 @@
 	p4_pmu_enable_pebs(hwc->config);
 
 	(void)checking_wrmsrl(escr_addr, escr_conf);
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx,
+	(void)checking_wrmsrl(hwc->config_base,
 				(cccr & ~P4_CCCR_RESERVED) | P4_CCCR_ENABLE);
 }
 
@@ -946,14 +947,23 @@
 		if (!x86_perf_event_set_period(event))
 			continue;
 		if (perf_event_overflow(event, 1, &data, regs))
-			p4_pmu_disable_event(event);
+			x86_pmu_stop(event, 0);
 	}
 
-	if (handled) {
-		/* p4 quirk: unmask it again */
-		apic_write(APIC_LVTPC, apic_read(APIC_LVTPC) & ~APIC_LVT_MASKED);
+	if (handled)
 		inc_irq_stat(apic_perf_irqs);
-	}
+
+	/*
+	 * When dealing with the unmasking of the LVTPC on P4 perf hw, it has
+	 * been observed that the OVF bit flag has to be cleared first _before_
+	 * the LVTPC can be unmasked.
+	 *
+	 * The reason is the NMI line will continue to be asserted while the OVF
+	 * bit is set.  This causes a second NMI to generate if the LVTPC is
+	 * unmasked before the OVF bit is cleared, leading to unknown NMI
+	 * messages.
+	 */
+	apic_write(APIC_LVTPC, APIC_DM_NMI);
 
 	return handled;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_p6.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_p6.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/perf_event_p6.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/perf_event_p6.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,7 +68,7 @@
 	if (cpuc->enabled)
 		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx, val);
+	(void)checking_wrmsrl(hwc->config_base, val);
 }
 
 static void p6_pmu_enable_event(struct perf_event *event)
@@ -81,7 +81,7 @@
 	if (cpuc->enabled)
 		val |= ARCH_PERFMON_EVENTSEL_ENABLE;
 
-	(void)checking_wrmsrl(hwc->config_base + hwc->idx, val);
+	(void)checking_wrmsrl(hwc->config_base, val);
 }
 
 static __initconst const struct x86_pmu p6_pmu = {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/vmware.c linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/vmware.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/cpu/vmware.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/cpu/vmware.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 }
 
 /*
- * While checking the dmi string infomation, just checking the product
+ * While checking the dmi string information, just checking the product
  * serial key should be enough, as this will always have a VMware
  * specific string when running under VMware hypervisor.
  */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/crash_dump_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/crash_dump_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/crash_dump_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/crash_dump_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,9 +14,6 @@
 
 static void *kdump_buf_page;
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
 static inline bool is_crashed_pfn_valid(unsigned long pfn)
 {
 #ifndef CONFIG_X86_PAE
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/crash_dump_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/crash_dump_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/crash_dump_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/crash_dump_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,9 +10,6 @@
 #include <linux/uaccess.h>
 #include <linux/io.h>
 
-/* Stores the physical address of elf header of crash image. */
-unsigned long long elfcorehdr_addr = ELFCORE_ADDR_MAX;
-
 /**
  * copy_oldmem_page - copy one page from "oldmem"
  * @pfn: page frame number to be copied
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/devicetree.c linux-libre-2.6.39-gnu/arch/x86/kernel/devicetree.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/devicetree.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/devicetree.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,439 @@
+/*
+ * Architecture specific OF callbacks.
+ */
+#include <linux/bootmem.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/list.h>
+#include <linux/of.h>
+#include <linux/of_fdt.h>
+#include <linux/of_address.h>
+#include <linux/of_platform.h>
+#include <linux/of_irq.h>
+#include <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/of_pci.h>
+
+#include <asm/hpet.h>
+#include <asm/irq_controller.h>
+#include <asm/apic.h>
+#include <asm/pci_x86.h>
+
+__initdata u64 initial_dtb;
+char __initdata cmd_line[COMMAND_LINE_SIZE];
+static LIST_HEAD(irq_domains);
+static DEFINE_RAW_SPINLOCK(big_irq_lock);
+
+int __initdata of_ioapic;
+
+#ifdef CONFIG_X86_IO_APIC
+static void add_interrupt_host(struct irq_domain *ih)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&big_irq_lock, flags);
+	list_add(&ih->l, &irq_domains);
+	raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+}
+#endif
+
+static struct irq_domain *get_ih_from_node(struct device_node *controller)
+{
+	struct irq_domain *ih, *found = NULL;
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&big_irq_lock, flags);
+	list_for_each_entry(ih, &irq_domains, l) {
+		if (ih->controller ==  controller) {
+			found = ih;
+			break;
+		}
+	}
+	raw_spin_unlock_irqrestore(&big_irq_lock, flags);
+	return found;
+}
+
+unsigned int irq_create_of_mapping(struct device_node *controller,
+				   const u32 *intspec, unsigned int intsize)
+{
+	struct irq_domain *ih;
+	u32 virq, type;
+	int ret;
+
+	ih = get_ih_from_node(controller);
+	if (!ih)
+		return 0;
+	ret = ih->xlate(ih, intspec, intsize, &virq, &type);
+	if (ret)
+		return 0;
+	if (type == IRQ_TYPE_NONE)
+		return virq;
+	irq_set_irq_type(virq, type);
+	return virq;
+}
+EXPORT_SYMBOL_GPL(irq_create_of_mapping);
+
+unsigned long pci_address_to_pio(phys_addr_t address)
+{
+	/*
+	 * The ioport address can be directly used by inX / outX
+	 */
+	BUG_ON(address >= (1 << 16));
+	return (unsigned long)address;
+}
+EXPORT_SYMBOL_GPL(pci_address_to_pio);
+
+void __init early_init_dt_scan_chosen_arch(unsigned long node)
+{
+	BUG();
+}
+
+void __init early_init_dt_add_memory_arch(u64 base, u64 size)
+{
+	BUG();
+}
+
+void * __init early_init_dt_alloc_memory_arch(u64 size, u64 align)
+{
+	return __alloc_bootmem(size, align, __pa(MAX_DMA_ADDRESS));
+}
+
+void __init add_dtb(u64 data)
+{
+	initial_dtb = data + offsetof(struct setup_data, data);
+}
+
+/*
+ * CE4100 ids. Will be moved to machine_device_initcall() once we have it.
+ */
+static struct of_device_id __initdata ce4100_ids[] = {
+	{ .compatible = "intel,ce4100-cp", },
+	{ .compatible = "isa", },
+	{ .compatible = "pci", },
+	{},
+};
+
+static int __init add_bus_probe(void)
+{
+	if (!of_have_populated_dt())
+		return 0;
+
+	return of_platform_bus_probe(NULL, ce4100_ids, NULL);
+}
+module_init(add_bus_probe);
+
+#ifdef CONFIG_PCI
+static int x86_of_pci_irq_enable(struct pci_dev *dev)
+{
+	struct of_irq oirq;
+	u32 virq;
+	int ret;
+	u8 pin;
+
+	ret = pci_read_config_byte(dev, PCI_INTERRUPT_PIN, &pin);
+	if (ret)
+		return ret;
+	if (!pin)
+		return 0;
+
+	ret = of_irq_map_pci(dev, &oirq);
+	if (ret)
+		return ret;
+
+	virq = irq_create_of_mapping(oirq.controller, oirq.specifier,
+			oirq.size);
+	if (virq == 0)
+		return -EINVAL;
+	dev->irq = virq;
+	return 0;
+}
+
+static void x86_of_pci_irq_disable(struct pci_dev *dev)
+{
+}
+
+void __cpuinit x86_of_pci_init(void)
+{
+	struct device_node *np;
+
+	pcibios_enable_irq = x86_of_pci_irq_enable;
+	pcibios_disable_irq = x86_of_pci_irq_disable;
+
+	for_each_node_by_type(np, "pci") {
+		const void *prop;
+		struct pci_bus *bus;
+		unsigned int bus_min;
+		struct device_node *child;
+
+		prop = of_get_property(np, "bus-range", NULL);
+		if (!prop)
+			continue;
+		bus_min = be32_to_cpup(prop);
+
+		bus = pci_find_bus(0, bus_min);
+		if (!bus) {
+			printk(KERN_ERR "Can't find a node for bus %s.\n",
+					np->full_name);
+			continue;
+		}
+
+		if (bus->self)
+			bus->self->dev.of_node = np;
+		else
+			bus->dev.of_node = np;
+
+		for_each_child_of_node(np, child) {
+			struct pci_dev *dev;
+			u32 devfn;
+
+			prop = of_get_property(child, "reg", NULL);
+			if (!prop)
+				continue;
+
+			devfn = (be32_to_cpup(prop) >> 8) & 0xff;
+			dev = pci_get_slot(bus, devfn);
+			if (!dev)
+				continue;
+			dev->dev.of_node = child;
+			pci_dev_put(dev);
+		}
+	}
+}
+#endif
+
+static void __init dtb_setup_hpet(void)
+{
+#ifdef CONFIG_HPET_TIMER
+	struct device_node *dn;
+	struct resource r;
+	int ret;
+
+	dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-hpet");
+	if (!dn)
+		return;
+	ret = of_address_to_resource(dn, 0, &r);
+	if (ret) {
+		WARN_ON(1);
+		return;
+	}
+	hpet_address = r.start;
+#endif
+}
+
+static void __init dtb_lapic_setup(void)
+{
+#ifdef CONFIG_X86_LOCAL_APIC
+	struct device_node *dn;
+	struct resource r;
+	int ret;
+
+	dn = of_find_compatible_node(NULL, NULL, "intel,ce4100-lapic");
+	if (!dn)
+		return;
+
+	ret = of_address_to_resource(dn, 0, &r);
+	if (WARN_ON(ret))
+		return;
+
+	/* Did the boot loader setup the local APIC ? */
+	if (!cpu_has_apic) {
+		if (apic_force_enable(r.start))
+			return;
+	}
+	smp_found_config = 1;
+	pic_mode = 1;
+	register_lapic_address(r.start);
+	generic_processor_info(boot_cpu_physical_apicid,
+			       GET_APIC_VERSION(apic_read(APIC_LVR)));
+#endif
+}
+
+#ifdef CONFIG_X86_IO_APIC
+static unsigned int ioapic_id;
+
+static void __init dtb_add_ioapic(struct device_node *dn)
+{
+	struct resource r;
+	int ret;
+
+	ret = of_address_to_resource(dn, 0, &r);
+	if (ret) {
+		printk(KERN_ERR "Can't obtain address from node %s.\n",
+				dn->full_name);
+		return;
+	}
+	mp_register_ioapic(++ioapic_id, r.start, gsi_top);
+}
+
+static void __init dtb_ioapic_setup(void)
+{
+	struct device_node *dn;
+
+	for_each_compatible_node(dn, NULL, "intel,ce4100-ioapic")
+		dtb_add_ioapic(dn);
+
+	if (nr_ioapics) {
+		of_ioapic = 1;
+		return;
+	}
+	printk(KERN_ERR "Error: No information about IO-APIC in OF.\n");
+}
+#else
+static void __init dtb_ioapic_setup(void) {}
+#endif
+
+static void __init dtb_apic_setup(void)
+{
+	dtb_lapic_setup();
+	dtb_ioapic_setup();
+}
+
+#ifdef CONFIG_OF_FLATTREE
+static void __init x86_flattree_get_config(void)
+{
+	u32 size, map_len;
+	void *new_dtb;
+
+	if (!initial_dtb)
+		return;
+
+	map_len = max(PAGE_SIZE - (initial_dtb & ~PAGE_MASK),
+			(u64)sizeof(struct boot_param_header));
+
+	initial_boot_params = early_memremap(initial_dtb, map_len);
+	size = be32_to_cpu(initial_boot_params->totalsize);
+	if (map_len < size) {
+		early_iounmap(initial_boot_params, map_len);
+		initial_boot_params = early_memremap(initial_dtb, size);
+		map_len = size;
+	}
+
+	new_dtb = alloc_bootmem(size);
+	memcpy(new_dtb, initial_boot_params, size);
+	early_iounmap(initial_boot_params, map_len);
+
+	initial_boot_params = new_dtb;
+
+	/* root level address cells */
+	of_scan_flat_dt(early_init_dt_scan_root, NULL);
+
+	unflatten_device_tree();
+}
+#else
+static inline void x86_flattree_get_config(void) { }
+#endif
+
+void __init x86_dtb_init(void)
+{
+	x86_flattree_get_config();
+
+	if (!of_have_populated_dt())
+		return;
+
+	dtb_setup_hpet();
+	dtb_apic_setup();
+}
+
+#ifdef CONFIG_X86_IO_APIC
+
+struct of_ioapic_type {
+	u32 out_type;
+	u32 trigger;
+	u32 polarity;
+};
+
+static struct of_ioapic_type of_ioapic_type[] =
+{
+	{
+		.out_type	= IRQ_TYPE_EDGE_RISING,
+		.trigger	= IOAPIC_EDGE,
+		.polarity	= 1,
+	},
+	{
+		.out_type	= IRQ_TYPE_LEVEL_LOW,
+		.trigger	= IOAPIC_LEVEL,
+		.polarity	= 0,
+	},
+	{
+		.out_type	= IRQ_TYPE_LEVEL_HIGH,
+		.trigger	= IOAPIC_LEVEL,
+		.polarity	= 1,
+	},
+	{
+		.out_type	= IRQ_TYPE_EDGE_FALLING,
+		.trigger	= IOAPIC_EDGE,
+		.polarity	= 0,
+	},
+};
+
+static int ioapic_xlate(struct irq_domain *id, const u32 *intspec, u32 intsize,
+			u32 *out_hwirq, u32 *out_type)
+{
+	struct io_apic_irq_attr attr;
+	struct of_ioapic_type *it;
+	u32 line, idx, type;
+
+	if (intsize < 2)
+		return -EINVAL;
+
+	line = *intspec;
+	idx = (u32) id->priv;
+	*out_hwirq = line + mp_gsi_routing[idx].gsi_base;
+
+	intspec++;
+	type = *intspec;
+
+	if (type >= ARRAY_SIZE(of_ioapic_type))
+		return -EINVAL;
+
+	it = of_ioapic_type + type;
+	*out_type = it->out_type;
+
+	set_io_apic_irq_attr(&attr, idx, line, it->trigger, it->polarity);
+
+	return io_apic_setup_irq_pin_once(*out_hwirq, cpu_to_node(0), &attr);
+}
+
+static void __init ioapic_add_ofnode(struct device_node *np)
+{
+	struct resource r;
+	int i, ret;
+
+	ret = of_address_to_resource(np, 0, &r);
+	if (ret) {
+		printk(KERN_ERR "Failed to obtain address for %s\n",
+				np->full_name);
+		return;
+	}
+
+	for (i = 0; i < nr_ioapics; i++) {
+		if (r.start == mp_ioapics[i].apicaddr) {
+			struct irq_domain *id;
+
+			id = kzalloc(sizeof(*id), GFP_KERNEL);
+			BUG_ON(!id);
+			id->controller = np;
+			id->xlate = ioapic_xlate;
+			id->priv = (void *)i;
+			add_interrupt_host(id);
+			return;
+		}
+	}
+	printk(KERN_ERR "IOxAPIC at %s is not registered.\n", np->full_name);
+}
+
+void __init x86_add_irq_domains(void)
+{
+	struct device_node *dp;
+
+	if (!of_have_populated_dt())
+		return;
+
+	for_each_node_with_property(dp, "interrupt-controller") {
+		if (of_device_is_compatible(dp, "intel,ce4100-ioapic"))
+			ioapic_add_ofnode(dp);
+	}
+}
+#else
+void __init x86_add_irq_domains(void) { }
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/dumpstack_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/dumpstack_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/dumpstack_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/dumpstack_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,12 +17,11 @@
 #include <asm/stacktrace.h>
 
 
-void dump_trace(struct task_struct *task,
-		struct pt_regs *regs, unsigned long *stack,
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data)
 {
 	int graph = 0;
-	unsigned long bp;
 
 	if (!task)
 		task = current;
@@ -35,7 +34,9 @@
 			stack = (unsigned long *)task->thread.sp;
 	}
 
-	bp = stack_frame(task, regs);
+	if (!bp)
+		bp = stack_frame(task, regs);
+
 	for (;;) {
 		struct thread_info *context;
 
@@ -55,7 +56,7 @@
 
 void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, char *log_lvl)
+		   unsigned long *sp, unsigned long bp, char *log_lvl)
 {
 	unsigned long *stack;
 	int i;
@@ -77,7 +78,7 @@
 		touch_nmi_watchdog();
 	}
 	printk(KERN_CONT "\n");
-	show_trace_log_lvl(task, regs, sp, log_lvl);
+	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
 
@@ -102,7 +103,7 @@
 		u8 *ip;
 
 		printk(KERN_EMERG "Stack:\n");
-		show_stack_log_lvl(NULL, regs, &regs->sp, KERN_EMERG);
+		show_stack_log_lvl(NULL, regs, &regs->sp, 0, KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/dumpstack_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/dumpstack_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/dumpstack_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/dumpstack_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,8 +139,8 @@
  * severe exception (double fault, nmi, stack fault, debug, mce) hardware stack
  */
 
-void dump_trace(struct task_struct *task,
-		struct pt_regs *regs, unsigned long *stack,
+void dump_trace(struct task_struct *task, struct pt_regs *regs,
+		unsigned long *stack, unsigned long bp,
 		const struct stacktrace_ops *ops, void *data)
 {
 	const unsigned cpu = get_cpu();
@@ -150,7 +150,6 @@
 	struct thread_info *tinfo;
 	int graph = 0;
 	unsigned long dummy;
-	unsigned long bp;
 
 	if (!task)
 		task = current;
@@ -161,7 +160,8 @@
 			stack = (unsigned long *)task->thread.sp;
 	}
 
-	bp = stack_frame(task, regs);
+	if (!bp)
+		bp = stack_frame(task, regs);
 	/*
 	 * Print function call entries in all stacks, starting at the
 	 * current stack address. If the stacks consist of nested
@@ -225,7 +225,7 @@
 
 void
 show_stack_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		   unsigned long *sp, char *log_lvl)
+		   unsigned long *sp, unsigned long bp, char *log_lvl)
 {
 	unsigned long *irq_stack_end;
 	unsigned long *irq_stack;
@@ -269,7 +269,7 @@
 	preempt_enable();
 
 	printk(KERN_CONT "\n");
-	show_trace_log_lvl(task, regs, sp, log_lvl);
+	show_trace_log_lvl(task, regs, sp, bp, log_lvl);
 }
 
 void show_registers(struct pt_regs *regs)
@@ -298,7 +298,7 @@
 
 		printk(KERN_EMERG "Stack:\n");
 		show_stack_log_lvl(NULL, regs, (unsigned long *)sp,
-				   KERN_EMERG);
+				   0, KERN_EMERG);
 
 		printk(KERN_EMERG "Code: ");
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/dumpstack.c linux-libre-2.6.39-gnu/arch/x86/kernel/dumpstack.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/dumpstack.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/dumpstack.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 
 void printk_address(unsigned long address, int reliable)
 {
-	printk(" [<%p>] %s%pS\n", (void *) address,
+	printk(" [<%p>] %s%pB\n", (void *) address,
 			reliable ? "" : "? ", (void *) address);
 }
 
@@ -175,21 +175,21 @@
 
 void
 show_trace_log_lvl(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack, char *log_lvl)
+		unsigned long *stack, unsigned long bp, char *log_lvl)
 {
 	printk("%sCall Trace:\n", log_lvl);
-	dump_trace(task, regs, stack, &print_trace_ops, log_lvl);
+	dump_trace(task, regs, stack, bp, &print_trace_ops, log_lvl);
 }
 
 void show_trace(struct task_struct *task, struct pt_regs *regs,
-		unsigned long *stack)
+		unsigned long *stack, unsigned long bp)
 {
-	show_trace_log_lvl(task, regs, stack, "");
+	show_trace_log_lvl(task, regs, stack, bp, "");
 }
 
 void show_stack(struct task_struct *task, unsigned long *sp)
 {
-	show_stack_log_lvl(task, NULL, sp, "");
+	show_stack_log_lvl(task, NULL, sp, 0, "");
 }
 
 /*
@@ -197,14 +197,16 @@
  */
 void dump_stack(void)
 {
+	unsigned long bp;
 	unsigned long stack;
 
+	bp = stack_frame(current, NULL);
 	printk("Pid: %d, comm: %.20s %s %s %.*s\n",
 		current->pid, current->comm, print_tainted(),
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
-	show_trace(NULL, NULL, &stack);
+	show_trace(NULL, NULL, &stack, bp);
 }
 EXPORT_SYMBOL(dump_stack);
 
@@ -320,41 +322,6 @@
 	oops_end(flags, regs, sig);
 }
 
-void notrace __kprobes
-die_nmi(char *str, struct pt_regs *regs, int do_panic)
-{
-	unsigned long flags;
-
-	if (notify_die(DIE_NMIWATCHDOG, str, regs, 0, 2, SIGINT) == NOTIFY_STOP)
-		return;
-
-	/*
-	 * We are in trouble anyway, lets at least try
-	 * to get a message out.
-	 */
-	flags = oops_begin();
-	printk(KERN_EMERG "%s", str);
-	printk(" on CPU%d, ip %08lx, registers:\n",
-		smp_processor_id(), regs->ip);
-	show_registers(regs);
-	oops_end(flags, regs, 0);
-	if (do_panic || panic_on_oops)
-		panic("Non maskable interrupt");
-	nmi_exit();
-	local_irq_enable();
-	do_exit(SIGBUS);
-}
-
-static int __init oops_setup(char *s)
-{
-	if (!s)
-		return -EINVAL;
-	if (!strcmp(s, "panic"))
-		panic_on_oops = 1;
-	return 0;
-}
-early_param("oops", oops_setup);
-
 static int __init kstack_setup(char *s)
 {
 	if (!s)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/e820.c linux-libre-2.6.39-gnu/arch/x86/kernel/e820.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/e820.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/e820.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/kernel.h>
 #include <linux/types.h>
 #include <linux/init.h>
+#include <linux/crash_dump.h>
 #include <linux/bootmem.h>
 #include <linux/pfn.h>
 #include <linux/suspend.h>
@@ -667,21 +668,15 @@
  * boot_params.e820_map, others are passed via SETUP_E820_EXT node of
  * linked list of struct setup_data, which is parsed here.
  */
-void __init parse_e820_ext(struct setup_data *sdata, unsigned long pa_data)
+void __init parse_e820_ext(struct setup_data *sdata)
 {
-	u32 map_len;
 	int entries;
 	struct e820entry *extmap;
 
 	entries = sdata->len / sizeof(struct e820entry);
-	map_len = sdata->len + sizeof(struct setup_data);
-	if (map_len > PAGE_SIZE)
-		sdata = early_ioremap(pa_data, map_len);
 	extmap = (struct e820entry *)(sdata->data);
 	__append_e820_map(extmap, entries);
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
-	if (map_len > PAGE_SIZE)
-		early_iounmap(sdata, map_len);
 	printk(KERN_INFO "extended physical RAM map:\n");
 	e820_print_map("extended");
 }
@@ -847,15 +842,21 @@
 	if (!p)
 		return -EINVAL;
 
-#ifdef CONFIG_X86_32
 	if (!strcmp(p, "nopentium")) {
+#ifdef CONFIG_X86_32
 		setup_clear_cpu_cap(X86_FEATURE_PSE);
 		return 0;
-	}
+#else
+		printk(KERN_WARNING "mem=nopentium ignored! (only supported on x86_32)\n");
+		return -EINVAL;
 #endif
+	}
 
 	userdef = 1;
 	mem_size = memparse(p, &p);
+	/* don't remove all of memory when handling "mem={invalid}" param */
+	if (mem_size == 0)
+		return -EINVAL;
 	e820_remove_range(mem_size, ULLONG_MAX - mem_size, E820_RAM, 1);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/early-quirks.c linux-libre-2.6.39-gnu/arch/x86/kernel/early-quirks.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/early-quirks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/early-quirks.c	2011-05-19 00:06:34.000000000 -0400
@@ -159,7 +159,12 @@
 	if (rev >= 0x40)
 		acpi_fix_pin2_polarity = 1;
 
-	if (rev > 0x13)
+	/*
+	 * SB600: revisions 0x11, 0x12, 0x13, 0x14, ...
+	 * SB700: revisions 0x39, 0x3a, ...
+	 * SB800: revisions 0x40, 0x41, ...
+	 */
+	if (rev >= 0x39)
 		return;
 
 	if (acpi_use_timer_override)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/entry_32.S linux-libre-2.6.39-gnu/arch/x86/kernel/entry_32.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/entry_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/entry_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -65,6 +65,8 @@
 #define sysexit_audit	syscall_exit_work
 #endif
 
+	.section .entry.text, "ax"
+
 /*
  * We use macros for low-level operations which need to be overridden
  * for paravirtualization.  The following will never clobber any registers:
@@ -395,7 +397,7 @@
 	 * A tiny bit of offset fixup is necessary - 4*4 means the 4 words
 	 * pushed above; +8 corresponds to copy_thread's esp0 setting.
 	 */
-	pushl_cfi ((TI_sysenter_return)-THREAD_SIZE_asm+8+4*4)(%esp)
+	pushl_cfi ((TI_sysenter_return)-THREAD_SIZE+8+4*4)(%esp)
 	CFI_REL_OFFSET eip, 0
 
 	pushl_cfi %eax
@@ -788,7 +790,7 @@
  */
 .section .init.rodata,"a"
 ENTRY(interrupt)
-.text
+.section .entry.text, "ax"
 	.p2align 5
 	.p2align CONFIG_X86_L1_CACHE_SHIFT
 ENTRY(irq_entries_start)
@@ -807,7 +809,7 @@
       .endif
       .previous
 	.long 1b
-      .text
+      .section .entry.text, "ax"
 vector=vector+1
     .endif
   .endr
@@ -1409,11 +1411,10 @@
 #ifdef CONFIG_KVM_GUEST
 ENTRY(async_page_fault)
 	RING0_EC_FRAME
-	pushl $do_async_page_fault
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi $do_async_page_fault
 	jmp error_code
 	CFI_ENDPROC
-END(apf_page_fault)
+END(async_page_fault)
 #endif
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/entry_64.S linux-libre-2.6.39-gnu/arch/x86/kernel/entry_64.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/entry_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/entry_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
  * A note on terminology:
  * - top of stack: Architecture defined interrupt frame from SS to RIP
  * at the top of the kernel process stack.
- * - partial stack frame: partially saved registers upto R11.
+ * - partial stack frame: partially saved registers up to R11.
  * - full stack frame: Like partial stack frame, but all register saved.
  *
  * Some macro usage:
@@ -61,6 +61,8 @@
 #define __AUDIT_ARCH_LE	   0x40000000
 
 	.code64
+	.section .entry.text, "ax"
+
 #ifdef CONFIG_FUNCTION_TRACER
 #ifdef CONFIG_DYNAMIC_FTRACE
 ENTRY(mcount)
@@ -420,7 +422,7 @@
 END(ret_from_fork)
 
 /*
- * System call entry. Upto 6 arguments in registers are supported.
+ * System call entry. Up to 6 arguments in registers are supported.
  *
  * SYSCALL does not save anything on the stack and does not change the
  * stack pointer.
@@ -744,7 +746,7 @@
  */
 	.section .init.rodata,"a"
 ENTRY(interrupt)
-	.text
+	.section .entry.text
 	.p2align 5
 	.p2align CONFIG_X86_L1_CACHE_SHIFT
 ENTRY(irq_entries_start)
@@ -763,7 +765,7 @@
       .endif
       .previous
 	.quad 1b
-      .text
+      .section .entry.text
 vector=vector+1
     .endif
   .endr
@@ -975,9 +977,12 @@
 	x86_platform_ipi smp_x86_platform_ipi
 
 #ifdef CONFIG_SMP
-.irpc idx, "01234567"
+.irp idx,0,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
+.if NUM_INVALIDATE_TLB_VECTORS > \idx
 apicinterrupt (INVALIDATE_TLB_VECTOR_START)+\idx \
 	invalidate_interrupt\idx smp_invalidate_interrupt
+.endif
 .endr
 #endif
 
@@ -1248,7 +1253,7 @@
 	decl PER_CPU_VAR(irq_count)
 	jmp  error_exit
 	CFI_ENDPROC
-END(do_hypervisor_callback)
+END(xen_do_hypervisor_callback)
 
 /*
  * Hypervisor uses this for application faults while it executes.
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/ftrace.c linux-libre-2.6.39-gnu/arch/x86/kernel/ftrace.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/ftrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/ftrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -437,18 +437,19 @@
 		return;
 	}
 
-	if (ftrace_push_return_trace(old, self_addr, &trace.depth,
-		    frame_pointer) == -EBUSY) {
-		*parent = old;
-		return;
-	}
-
 	trace.func = self_addr;
+	trace.depth = current->curr_ret_stack + 1;
 
 	/* Only trace if the calling function expects to */
 	if (!ftrace_graph_entry(&trace)) {
-		current->curr_ret_stack--;
 		*parent = old;
+		return;
+	}
+
+	if (ftrace_push_return_trace(old, self_addr, &trace.depth,
+		    frame_pointer) == -EBUSY) {
+		*parent = old;
+		return;
 	}
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/head32.c linux-libre-2.6.39-gnu/arch/x86/kernel/head32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/head32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/head32.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,15 +34,6 @@
 {
 	memblock_init();
 
-#ifdef CONFIG_X86_TRAMPOLINE
-	/*
-	 * But first pinch a few for the stack/trampoline stuff
-	 * FIXME: Don't need the extra page at 4K, but need to fix
-	 * trampoline before removing it. (see the GDT stuff)
-	 */
-	memblock_x86_reserve_range(PAGE_SIZE, PAGE_SIZE + PAGE_SIZE, "EX TRAMPOLINE");
-#endif
-
 	memblock_x86_reserve_range(__pa_symbol(&_text), __pa_symbol(&__bss_stop), "TEXT DATA BSS");
 
 #ifdef CONFIG_BLK_DEV_INITRD
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/head_32.S linux-libre-2.6.39-gnu/arch/x86/kernel/head_32.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/head_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/head_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
  */
 KERNEL_PAGES = LOWMEM_PAGES
 
-INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE_asm
+INIT_MAP_SIZE = PAGE_TABLE_SIZE(KERNEL_PAGES) * PAGE_SIZE
 RESERVE_BRK(pagetables, INIT_MAP_SIZE)
 
 /*
@@ -137,7 +137,7 @@
 	movsl
 1:
 
-#ifdef CONFIG_OLPC_OPENFIRMWARE
+#ifdef CONFIG_OLPC
 	/* save OFW's pgdir table for later use when calling into OFW */
 	movl %cr3, %eax
 	movl %eax, pa(olpc_ofw_pgd)
@@ -623,7 +623,7 @@
  * BSS section
  */
 __PAGE_ALIGNED_BSS
-	.align PAGE_SIZE_asm
+	.align PAGE_SIZE
 #ifdef CONFIG_X86_PAE
 initial_pg_pmd:
 	.fill 1024*KPMDS,4,0
@@ -644,7 +644,7 @@
 #ifdef CONFIG_X86_PAE
 __PAGE_ALIGNED_DATA
 	/* Page-aligned for the benefit of paravirt? */
-	.align PAGE_SIZE_asm
+	.align PAGE_SIZE
 ENTRY(initial_page_table)
 	.long	pa(initial_pg_pmd+PGD_IDENT_ATTR),0	/* low identity map */
 # if KPMDS == 3
@@ -662,7 +662,7 @@
 # else
 #  error "Kernel PMDs should be 1, 2 or 3"
 # endif
-	.align PAGE_SIZE_asm		/* needs to be page-sized too */
+	.align PAGE_SIZE		/* needs to be page-sized too */
 #endif
 
 .data
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/head64.c linux-libre-2.6.39-gnu/arch/x86/kernel/head64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/head64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/head64.c	2011-05-19 00:06:34.000000000 -0400
@@ -77,9 +77,6 @@
 	/* Make NULL pointers segfault */
 	zap_identity_mappings();
 
-	/* Cleanup the over mapped high alias */
-	cleanup_highmap();
-
 	max_pfn_mapped = KERNEL_IMAGE_SIZE >> PAGE_SHIFT;
 
 	for (i = 0; i < NUM_EXCEPTION_VECTORS; i++) {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/head_64.S linux-libre-2.6.39-gnu/arch/x86/kernel/head_64.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/head_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/head_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -136,10 +136,9 @@
 	/* Fixup phys_base */
 	addq	%rbp, phys_base(%rip)
 
-#ifdef CONFIG_X86_TRAMPOLINE
+	/* Fixup trampoline */
 	addq	%rbp, trampoline_level4_pgt + 0(%rip)
 	addq	%rbp, trampoline_level4_pgt + (511*8)(%rip)
-#endif
 
 	/* Due to ENTRY(), sometimes the empty space gets filled with
 	 * zeros. Better take a jmp than relying on empty space being
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/hpet.c linux-libre-2.6.39-gnu/arch/x86/kernel/hpet.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/hpet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/hpet.c	2011-05-19 00:06:34.000000000 -0400
@@ -503,7 +503,7 @@
 	if (!irq)
 		return -EINVAL;
 
-	set_irq_data(irq, dev);
+	irq_set_handler_data(irq, dev);
 
 	if (hpet_setup_msi_irq(irq))
 		return -EINVAL;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/i387.c linux-libre-2.6.39-gnu/arch/x86/kernel/i387.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/i387.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/i387.c	2011-05-19 00:06:34.000000000 -0400
@@ -145,7 +145,7 @@
  * The _current_ task is using the FPU for the first time
  * so initialize it and set the mxcsr to its default
  * value at reset if we support XMM instructions and then
- * remeber the current task has used the FPU.
+ * remember the current task has used the FPU.
  */
 int init_fpu(struct task_struct *tsk)
 {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/i8237.c linux-libre-2.6.39-gnu/arch/x86/kernel/i8237.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/i8237.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/i8237.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,7 @@
  */
 
 #include <linux/init.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/dma.h>
 
@@ -21,7 +21,7 @@
  * in asm/dma.h.
  */
 
-static int i8237A_resume(struct sys_device *dev)
+static void i8237A_resume(void)
 {
 	unsigned long flags;
 	int i;
@@ -41,31 +41,15 @@
 	enable_dma(4);
 
 	release_dma_lock(flags);
-
-	return 0;
 }
 
-static int i8237A_suspend(struct sys_device *dev, pm_message_t state)
-{
-	return 0;
-}
-
-static struct sysdev_class i8237_sysdev_class = {
-	.name		= "i8237",
-	.suspend	= i8237A_suspend,
+static struct syscore_ops i8237_syscore_ops = {
 	.resume		= i8237A_resume,
 };
 
-static struct sys_device device_i8237A = {
-	.id		= 0,
-	.cls		= &i8237_sysdev_class,
-};
-
-static int __init i8237A_init_sysfs(void)
+static int __init i8237A_init_ops(void)
 {
-	int error = sysdev_class_register(&i8237_sysdev_class);
-	if (!error)
-		error = sysdev_register(&device_i8237A);
-	return error;
+	register_syscore_ops(&i8237_syscore_ops);
+	return 0;
 }
-device_initcall(i8237A_init_sysfs);
+device_initcall(i8237A_init_ops);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/i8259.c linux-libre-2.6.39-gnu/arch/x86/kernel/i8259.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/i8259.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/i8259.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
 #include <linux/random.h>
 #include <linux/init.h>
 #include <linux/kernel_stat.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/bitops.h>
 #include <linux/acpi.h>
 #include <linux/io.h>
@@ -112,7 +112,7 @@
 {
 	disable_irq_nosync(irq);
 	io_apic_irqs &= ~(1<<irq);
-	set_irq_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
+	irq_set_chip_and_handler_name(irq, &i8259A_chip, handle_level_irq,
 				      i8259A_chip.name);
 	enable_irq(irq);
 }
@@ -245,20 +245,19 @@
 	trigger[1] = inb(0x4d1) & 0xDE;
 }
 
-static int i8259A_resume(struct sys_device *dev)
+static void i8259A_resume(void)
 {
 	init_8259A(i8259A_auto_eoi);
 	restore_ELCR(irq_trigger);
-	return 0;
 }
 
-static int i8259A_suspend(struct sys_device *dev, pm_message_t state)
+static int i8259A_suspend(void)
 {
 	save_ELCR(irq_trigger);
 	return 0;
 }
 
-static int i8259A_shutdown(struct sys_device *dev)
+static void i8259A_shutdown(void)
 {
 	/* Put the i8259A into a quiescent state that
 	 * the kernel initialization code can get it
@@ -266,21 +265,14 @@
 	 */
 	outb(0xff, PIC_MASTER_IMR);	/* mask all of 8259A-1 */
 	outb(0xff, PIC_SLAVE_IMR);	/* mask all of 8259A-1 */
-	return 0;
 }
 
-static struct sysdev_class i8259_sysdev_class = {
-	.name = "i8259",
+static struct syscore_ops i8259_syscore_ops = {
 	.suspend = i8259A_suspend,
 	.resume = i8259A_resume,
 	.shutdown = i8259A_shutdown,
 };
 
-static struct sys_device device_i8259A = {
-	.id	= 0,
-	.cls	= &i8259_sysdev_class,
-};
-
 static void mask_8259A(void)
 {
 	unsigned long flags;
@@ -399,17 +391,12 @@
 
 struct legacy_pic *legacy_pic = &default_legacy_pic;
 
-static int __init i8259A_init_sysfs(void)
+static int __init i8259A_init_ops(void)
 {
-	int error;
-
-	if (legacy_pic != &default_legacy_pic)
-		return 0;
+	if (legacy_pic == &default_legacy_pic)
+		register_syscore_ops(&i8259_syscore_ops);
 
-	error = sysdev_class_register(&i8259_sysdev_class);
-	if (!error)
-		error = sysdev_register(&device_i8259A);
-	return error;
+	return 0;
 }
 
-device_initcall(i8259A_init_sysfs);
+device_initcall(i8259A_init_ops);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/ioport.c linux-libre-2.6.39-gnu/arch/x86/kernel/ioport.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/ioport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/ioport.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,22 +14,9 @@
 #include <linux/slab.h>
 #include <linux/thread_info.h>
 #include <linux/syscalls.h>
+#include <linux/bitmap.h>
 #include <asm/syscalls.h>
 
-/* Set EXTENT bits starting at BASE in BITMAP to value TURN_ON. */
-static void set_bitmap(unsigned long *bitmap, unsigned int base,
-		       unsigned int extent, int new_value)
-{
-	unsigned int i;
-
-	for (i = base; i < base + extent; i++) {
-		if (new_value)
-			__set_bit(i, bitmap);
-		else
-			__clear_bit(i, bitmap);
-	}
-}
-
 /*
  * this changes the io permissions bitmap in the current task.
  */
@@ -69,7 +56,10 @@
 	 */
 	tss = &per_cpu(init_tss, get_cpu());
 
-	set_bitmap(t->io_bitmap_ptr, from, num, !turn_on);
+	if (turn_on)
+		bitmap_clear(t->io_bitmap_ptr, from, num);
+	else
+		bitmap_set(t->io_bitmap_ptr, from, num);
 
 	/*
 	 * Search for a (possibly new) maximum. This is simple and stupid,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/irq_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/irq_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/irq_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/irq_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -172,7 +172,7 @@
 
 		call_on_stack(__do_softirq, isp);
 		/*
-		 * Shouldnt happen, we returned above if in_interrupt():
+		 * Shouldn't happen, we returned above if in_interrupt():
 		 */
 		WARN_ON_ONCE(softirq_count());
 	}
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/irq.c linux-libre-2.6.39-gnu/arch/x86/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,7 @@
 #include <linux/seq_file.h>
 #include <linux/smp.h>
 #include <linux/ftrace.h>
+#include <linux/delay.h>
 
 #include <asm/apic.h>
 #include <asm/io_apic.h>
@@ -44,9 +45,9 @@
 
 #define irq_stats(x)		(&per_cpu(irq_stat, x))
 /*
- * /proc/interrupts printing:
+ * /proc/interrupts printing for arch specific interrupts
  */
-static int show_other_interrupts(struct seq_file *p, int prec)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
 	int j;
 
@@ -122,59 +123,6 @@
 	return 0;
 }
 
-int show_interrupts(struct seq_file *p, void *v)
-{
-	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);
-
-	/* print header */
-	if (i == 0) {
-		seq_printf(p, "%*s", prec + 8, "");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%-8d", j);
-		seq_putc(p, '\n');
-	}
-
-	desc = irq_to_desc(i);
-	if (!desc)
-		return 0;
-
-	raw_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, " %8s", desc->irq_data.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');
-out:
-	raw_spin_unlock_irqrestore(&desc->lock, flags);
-	return 0;
-}
-
 /*
  * /proc/stat helpers
  */
@@ -276,15 +224,6 @@
 
 EXPORT_SYMBOL_GPL(vector_used_by_percpu_irq);
 
-#ifdef CONFIG_OF
-unsigned int irq_create_of_mapping(struct device_node *controller,
-		const u32 *intspec, unsigned int intsize)
-{
-	return intspec[0];
-}
-EXPORT_SYMBOL_GPL(irq_create_of_mapping);
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 /* A cpu has been removed from cpu_online_mask.  Reset irq affinities. */
 void fixup_irqs(void)
@@ -293,6 +232,7 @@
 	static int warned;
 	struct irq_desc *desc;
 	struct irq_data *data;
+	struct irq_chip *chip;
 
 	for_each_irq_desc(irq, desc) {
 		int break_affinity = 0;
@@ -307,10 +247,10 @@
 		/* interrupt's are disabled at this point */
 		raw_spin_lock(&desc->lock);
 
-		data = &desc->irq_data;
+		data = irq_desc_get_irq_data(desc);
 		affinity = data->affinity;
 		if (!irq_has_action(irq) ||
-		    cpumask_equal(affinity, cpu_online_mask)) {
+		    cpumask_subset(affinity, cpu_online_mask)) {
 			raw_spin_unlock(&desc->lock);
 			continue;
 		}
@@ -327,16 +267,17 @@
 			affinity = cpu_all_mask;
 		}
 
-		if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_mask)
-			data->chip->irq_mask(data);
+		chip = irq_data_get_irq_chip(data);
+		if (!irqd_can_move_in_process_context(data) && chip->irq_mask)
+			chip->irq_mask(data);
 
-		if (data->chip->irq_set_affinity)
-			data->chip->irq_set_affinity(data, affinity, true);
+		if (chip->irq_set_affinity)
+			chip->irq_set_affinity(data, affinity, true);
 		else if (!(warned++))
 			set_affinity = 0;
 
-		if (!(desc->status & IRQ_MOVE_PCNTXT) && data->chip->irq_unmask)
-			data->chip->irq_unmask(data);
+		if (!irqd_can_move_in_process_context(data) && chip->irq_unmask)
+			chip->irq_unmask(data);
 
 		raw_spin_unlock(&desc->lock);
 
@@ -368,10 +309,11 @@
 			irq = __this_cpu_read(vector_irq[vector]);
 
 			desc = irq_to_desc(irq);
-			data = &desc->irq_data;
+			data = irq_desc_get_irq_data(desc);
+			chip = irq_data_get_irq_chip(data);
 			raw_spin_lock(&desc->lock);
-			if (data->chip->irq_retrigger)
-				data->chip->irq_retrigger(data);
+			if (chip->irq_retrigger)
+				chip->irq_retrigger(data);
 			raw_spin_unlock(&desc->lock);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/irqinit.c linux-libre-2.6.39-gnu/arch/x86/kernel/irqinit.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/irqinit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/irqinit.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <asm/setup.h>
 #include <asm/i8259.h>
 #include <asm/traps.h>
+#include <asm/prom.h>
 
 /*
  * ISA PIC or low IO-APIC triggered (INTA-cycle or APIC) interrupts:
@@ -71,6 +72,7 @@
 static struct irqaction fpu_irq = {
 	.handler = math_error_irq,
 	.name = "fpu",
+	.flags = IRQF_NO_THREAD,
 };
 #endif
 
@@ -80,6 +82,7 @@
 static struct irqaction irq2 = {
 	.handler = no_action,
 	.name = "cascade",
+	.flags = IRQF_NO_THREAD,
 };
 
 DEFINE_PER_CPU(vector_irq_t, vector_irq) = {
@@ -110,7 +113,7 @@
 	legacy_pic->init(0);
 
 	for (i = 0; i < legacy_pic->nr_legacy_irqs; i++)
-		set_irq_chip_and_handler_name(i, chip, handle_level_irq, name);
+		irq_set_chip_and_handler_name(i, chip, handle_level_irq, name);
 }
 
 void __init init_IRQ(void)
@@ -118,6 +121,12 @@
 	int i;
 
 	/*
+	 * We probably need a better place for this, but it works for
+	 * now ...
+	 */
+	x86_add_irq_domains();
+
+	/*
 	 * On cpu 0, Assign IRQ0_VECTOR..IRQ15_VECTOR's to IRQ 0..15.
 	 * If these IRQ's are handled by legacy interrupt-controllers like PIC,
 	 * then this configuration will likely be static after the boot. If
@@ -164,14 +173,77 @@
 	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);
+#define ALLOC_INVTLB_VEC(NR) \
+	alloc_intr_gate(INVALIDATE_TLB_VECTOR_START+NR, \
+		invalidate_interrupt##NR)
+
+	switch (NUM_INVALIDATE_TLB_VECTORS) {
+	default:
+		ALLOC_INVTLB_VEC(31);
+	case 31:
+		ALLOC_INVTLB_VEC(30);
+	case 30:
+		ALLOC_INVTLB_VEC(29);
+	case 29:
+		ALLOC_INVTLB_VEC(28);
+	case 28:
+		ALLOC_INVTLB_VEC(27);
+	case 27:
+		ALLOC_INVTLB_VEC(26);
+	case 26:
+		ALLOC_INVTLB_VEC(25);
+	case 25:
+		ALLOC_INVTLB_VEC(24);
+	case 24:
+		ALLOC_INVTLB_VEC(23);
+	case 23:
+		ALLOC_INVTLB_VEC(22);
+	case 22:
+		ALLOC_INVTLB_VEC(21);
+	case 21:
+		ALLOC_INVTLB_VEC(20);
+	case 20:
+		ALLOC_INVTLB_VEC(19);
+	case 19:
+		ALLOC_INVTLB_VEC(18);
+	case 18:
+		ALLOC_INVTLB_VEC(17);
+	case 17:
+		ALLOC_INVTLB_VEC(16);
+	case 16:
+		ALLOC_INVTLB_VEC(15);
+	case 15:
+		ALLOC_INVTLB_VEC(14);
+	case 14:
+		ALLOC_INVTLB_VEC(13);
+	case 13:
+		ALLOC_INVTLB_VEC(12);
+	case 12:
+		ALLOC_INVTLB_VEC(11);
+	case 11:
+		ALLOC_INVTLB_VEC(10);
+	case 10:
+		ALLOC_INVTLB_VEC(9);
+	case 9:
+		ALLOC_INVTLB_VEC(8);
+	case 8:
+		ALLOC_INVTLB_VEC(7);
+	case 7:
+		ALLOC_INVTLB_VEC(6);
+	case 6:
+		ALLOC_INVTLB_VEC(5);
+	case 5:
+		ALLOC_INVTLB_VEC(4);
+	case 4:
+		ALLOC_INVTLB_VEC(3);
+	case 3:
+		ALLOC_INVTLB_VEC(2);
+	case 2:
+		ALLOC_INVTLB_VEC(1);
+	case 1:
+		ALLOC_INVTLB_VEC(0);
+		break;
+	}
 
 	/* IPI for generic function call */
 	alloc_intr_gate(CALL_FUNCTION_VECTOR, call_function_interrupt);
@@ -243,7 +315,7 @@
 			set_intr_gate(i, interrupt[i-FIRST_EXTERNAL_VECTOR]);
 	}
 
-	if (!acpi_ioapic)
+	if (!acpi_ioapic && !of_ioapic)
 		setup_irq(2, &irq2);
 
 #ifdef CONFIG_X86_32
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/kgdb.c linux-libre-2.6.39-gnu/arch/x86/kernel/kgdb.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/kgdb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/kgdb.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,8 +121,8 @@
 		memcpy(mem, (void *)regs + dbg_reg_def[regno].offset,
 		       dbg_reg_def[regno].size);
 
-	switch (regno) {
 #ifdef CONFIG_X86_32
+	switch (regno) {
 	case GDB_SS:
 		if (!user_mode_vm(regs))
 			*(unsigned long *)mem = __KERNEL_DS;
@@ -135,8 +135,8 @@
 	case GDB_FS:
 		*(unsigned long *)mem = 0xFFFF;
 		break;
-#endif
 	}
+#endif
 	return dbg_reg_def[regno].name;
 }
 
@@ -278,7 +278,7 @@
 		pevent = per_cpu_ptr(breakinfo[breakno].pev, cpu);
 		if (dbg_release_bp_slot(*pevent))
 			/*
-			 * The debugger is responisble for handing the retry on
+			 * The debugger is responsible for handing the retry on
 			 * remove failure.
 			 */
 			return -1;
@@ -533,15 +533,6 @@
 		}
 		return NOTIFY_DONE;
 
-	case DIE_NMIWATCHDOG:
-		if (atomic_read(&kgdb_active) != -1) {
-			/* KGDB CPU roundup: */
-			kgdb_nmicallback(raw_smp_processor_id(), regs);
-			return NOTIFY_STOP;
-		}
-		/* Enter debugger: */
-		break;
-
 	case DIE_DEBUG:
 		if (atomic_read(&kgdb_cpu_doing_single_step) != -1) {
 			if (user_mode(regs))
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/kprobes.c linux-libre-2.6.39-gnu/arch/x86/kernel/kprobes.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/kprobes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/kprobes.c	2011-05-19 00:06:34.000000000 -0400
@@ -1183,12 +1183,13 @@
 					 struct pt_regs *regs)
 {
 	struct kprobe_ctlblk *kcb = get_kprobe_ctlblk();
+	unsigned long flags;
 
 	/* This is possible if op is under delayed unoptimizing */
 	if (kprobe_disabled(&op->kp))
 		return;
 
-	preempt_disable();
+	local_irq_save(flags);
 	if (kprobe_running()) {
 		kprobes_inc_nmissed_count(&op->kp);
 	} else {
@@ -1207,7 +1208,7 @@
 		opt_pre_handler(&op->kp, regs);
 		__this_cpu_write(current_kprobe, NULL);
 	}
-	preempt_enable_no_resched();
+	local_irq_restore(flags);
 }
 
 static int __kprobes copy_optimized_instructions(u8 *dest, u8 *src)
@@ -1276,6 +1277,14 @@
 	if (!kallsyms_lookup_size_offset(paddr, &size, &offset))
 		return 0;
 
+	/*
+	 * Do not optimize in the entry code due to the unstable
+	 * stack handling.
+	 */
+	if ((paddr >= (unsigned long )__entry_text_start) &&
+	    (paddr <  (unsigned long )__entry_text_end))
+		return 0;
+
 	/* Check there is enough space for a relative jump. */
 	if (size - offset < RELATIVEJUMP_SIZE)
 		return 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/kvm.c linux-libre-2.6.39-gnu/arch/x86/kernel/kvm.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/kvm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/kvm.c	2011-05-19 00:06:34.000000000 -0400
@@ -493,7 +493,7 @@
 	native_smp_prepare_boot_cpu();
 }
 
-static void kvm_guest_cpu_online(void *dummy)
+static void __cpuinit kvm_guest_cpu_online(void *dummy)
 {
 	kvm_guest_cpu_init();
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/Makefile linux-libre-2.6.39-gnu/arch/x86/kernel/Makefile
--- linux-libre-2.6.38-gnu/arch/x86/kernel/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -41,13 +41,13 @@
 obj-$(CONFIG_X86_64)	+= sys_x86_64.o x8664_ksyms_64.o
 obj-$(CONFIG_X86_64)	+= syscall_64.o vsyscall_64.o
 obj-y			+= bootflag.o e820.o
-obj-y			+= pci-dma.o quirks.o i8237.o topology.o kdebugfs.o
+obj-y			+= pci-dma.o quirks.o topology.o kdebugfs.o
 obj-y			+= alternative.o i8253.o pci-nommu.o hw_breakpoint.o
 obj-y			+= tsc.o io_delay.o rtc.o
 obj-y			+= pci-iommu_table.o
 obj-y			+= resource.o
 
-obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline.o
+obj-y				+= trampoline.o trampoline_$(BITS).o
 obj-y				+= process.o
 obj-y				+= i387.o xsave.o
 obj-y				+= ptrace.o
@@ -55,10 +55,12 @@
 obj-$(CONFIG_IA32_EMULATION)	+= tls.o
 obj-y				+= step.o
 obj-$(CONFIG_INTEL_TXT)		+= tboot.o
+obj-$(CONFIG_ISA_DMA_API)	+= i8237.o
 obj-$(CONFIG_STACKTRACE)	+= stacktrace.o
 obj-y				+= cpu/
 obj-y				+= acpi/
 obj-y				+= reboot.o
+obj-$(CONFIG_X86_32)		+= reboot_32.o
 obj-$(CONFIG_MCA)		+= mca_32.o
 obj-$(CONFIG_X86_MSR)		+= msr.o
 obj-$(CONFIG_X86_CPUID)		+= cpuid.o
@@ -66,10 +68,9 @@
 apm-y				:= apm_32.o
 obj-$(CONFIG_APM)		+= apm.o
 obj-$(CONFIG_SMP)		+= smp.o
-obj-$(CONFIG_SMP)		+= smpboot.o tsc_sync.o
+obj-$(CONFIG_SMP)		+= smpboot.o
+obj-$(CONFIG_SMP)		+= tsc_sync.o
 obj-$(CONFIG_SMP)		+= setup_percpu.o
-obj-$(CONFIG_X86_64_SMP)	+= tsc_sync.o
-obj-$(CONFIG_X86_TRAMPOLINE)	+= trampoline_$(BITS).o
 obj-$(CONFIG_X86_MPPARSE)	+= mpparse.o
 obj-y				+= apic/
 obj-$(CONFIG_X86_REBOOTFIXUPS)	+= reboot_fixups_32.o
@@ -109,6 +110,7 @@
 obj-$(CONFIG_X86_CHECK_BIOS_CORRUPTION) += check.o
 
 obj-$(CONFIG_SWIOTLB)			+= pci-swiotlb.o
+obj-$(CONFIG_OF)			+= devicetree.o
 
 ###
 # 64 bit specific files
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/mca_32.c linux-libre-2.6.39-gnu/arch/x86/kernel/mca_32.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/mca_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/mca_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -259,7 +259,7 @@
 	/*
 	 * WARNING: Be careful when making changes here. Putting an adapter
 	 * and the motherboard simultaneously into setup mode may result in
-	 * damage to chips (according to The Indispensible PC Hardware Book
+	 * damage to chips (according to The Indispensable PC Hardware Book
 	 * by Hans-Peter Messmer). Also, we disable system interrupts (so
 	 * that we are not disturbed in the middle of this).
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/microcode_amd.c linux-libre-2.6.39-gnu/arch/x86/kernel/microcode_amd.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/microcode_amd.c	2012-03-24 00:59:11.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/microcode_amd.c	2012-03-24 03:25:30.000000000 -0400
@@ -66,7 +66,6 @@
 	unsigned int			mpb[0];
 };
 
-#define UCODE_MAX_SIZE			2048
 #define UCODE_CONTAINER_SECTION_HDR	8
 #define UCODE_CONTAINER_HEADER_SIZE	12
 
@@ -77,20 +76,20 @@
 	struct cpuinfo_x86 *c = &cpu_data(cpu);
 	u32 dummy;
 
-	memset(csig, 0, sizeof(*csig));
 	if (c->x86_vendor != X86_VENDOR_AMD || c->x86 < 0x10) {
-		pr_warning("microcode: CPU%d: AMD CPU family 0x%x not "
-			   "supported\n", cpu, c->x86);
+		pr_warning("CPU%d: family %d not supported\n", cpu, c->x86);
 		return -1;
 	}
+
 	rdmsr(MSR_AMD64_PATCH_LEVEL, csig->rev, dummy);
-	pr_info("CPU%d: patch_level=0x%x\n", cpu, csig->rev);
+	pr_info("CPU%d: patch_level=0x%08x\n", cpu, csig->rev);
+
 	return 0;
 }
 
-static int get_matching_microcode(int cpu, void *mc, int rev)
+static int get_matching_microcode(int cpu, struct microcode_header_amd *mc_hdr,
+				  int rev)
 {
-	struct microcode_header_amd *mc_header = mc;
 	unsigned int current_cpu_id;
 	u16 equiv_cpu_id = 0;
 	unsigned int i = 0;
@@ -109,17 +108,17 @@
 	if (!equiv_cpu_id)
 		return 0;
 
-	if (mc_header->processor_rev_id != equiv_cpu_id)
+	if (mc_hdr->processor_rev_id != equiv_cpu_id)
 		return 0;
 
 	/* ucode might be chipset specific -- currently we don't support this */
-	if (mc_header->nb_dev_id || mc_header->sb_dev_id) {
-		pr_err("CPU%d: loading of chipset specific code not yet supported\n",
+	if (mc_hdr->nb_dev_id || mc_hdr->sb_dev_id) {
+		pr_err("CPU%d: chipset specific code not yet supported\n",
 		       cpu);
 		return 0;
 	}
 
-	if (mc_header->patch_id <= rev)
+	if (mc_hdr->patch_id <= rev)
 		return 0;
 
 	return 1;
@@ -144,71 +143,93 @@
 
 	/* check current patch id and patch's id for match */
 	if (rev != mc_amd->hdr.patch_id) {
-		pr_err("CPU%d: update failed (for patch_level=0x%x)\n",
+		pr_err("CPU%d: update failed for patch_level=0x%08x\n",
 		       cpu, mc_amd->hdr.patch_id);
 		return -1;
 	}
 
-	pr_info("CPU%d: updated (new patch_level=0x%x)\n", cpu, rev);
+	pr_info("CPU%d: new patch_level=0x%08x\n", cpu, rev);
 	uci->cpu_sig.rev = rev;
 
 	return 0;
 }
 
-static void *
-get_next_ucode(const u8 *buf, unsigned int size, unsigned int *mc_size)
+static unsigned int verify_ucode_size(int cpu, const u8 *buf, unsigned int size)
 {
-	unsigned int total_size;
-	u8 section_hdr[UCODE_CONTAINER_SECTION_HDR];
-	void *mc;
+	struct cpuinfo_x86 *c = &cpu_data(cpu);
+	unsigned int max_size, actual_size;
 
-	get_ucode_data(section_hdr, buf, UCODE_CONTAINER_SECTION_HDR);
+#define F1XH_MPB_MAX_SIZE 2048
+#define F14H_MPB_MAX_SIZE 1824
+#define F15H_MPB_MAX_SIZE 4096
 
-	if (section_hdr[0] != UCODE_UCODE_TYPE) {
-		pr_err("error: invalid type field in container file section header\n");
-		return NULL;
+	switch (c->x86) {
+	case 0x14:
+		max_size = F14H_MPB_MAX_SIZE;
+		break;
+	case 0x15:
+		max_size = F15H_MPB_MAX_SIZE;
+		break;
+	default:
+		max_size = F1XH_MPB_MAX_SIZE;
+		break;
 	}
 
-	total_size = (unsigned long) (section_hdr[4] + (section_hdr[5] << 8));
+	actual_size = buf[4] + (buf[5] << 8);
 
-	if (total_size > size || total_size > UCODE_MAX_SIZE) {
-		pr_err("error: size mismatch\n");
-		return NULL;
+	if (actual_size > size || actual_size > max_size) {
+		pr_err("section size mismatch\n");
+		return 0;
 	}
 
-	mc = vzalloc(UCODE_MAX_SIZE);
+	return actual_size;
+}
+
+static struct microcode_header_amd *
+get_next_ucode(int cpu, const u8 *buf, unsigned int size, unsigned int *mc_size)
+{
+	struct microcode_header_amd *mc = NULL;
+	unsigned int actual_size = 0;
+
+	if (buf[0] != UCODE_UCODE_TYPE) {
+		pr_err("invalid type field in container file section header\n");
+		goto out;
+	}
+
+	actual_size = verify_ucode_size(cpu, buf, size);
+	if (!actual_size)
+		goto out;
+
+	mc = vzalloc(actual_size);
 	if (!mc)
-		return NULL;
+		goto out;
 
-	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, total_size);
-	*mc_size = total_size + UCODE_CONTAINER_SECTION_HDR;
+	get_ucode_data(mc, buf + UCODE_CONTAINER_SECTION_HDR, actual_size);
+	*mc_size = actual_size + UCODE_CONTAINER_SECTION_HDR;
 
+out:
 	return mc;
 }
 
 static int install_equiv_cpu_table(const u8 *buf)
 {
-	u8 *container_hdr[UCODE_CONTAINER_HEADER_SIZE];
-	unsigned int *buf_pos = (unsigned int *)container_hdr;
-	unsigned long size;
-
-	get_ucode_data(&container_hdr, buf, UCODE_CONTAINER_HEADER_SIZE);
-
-	size = buf_pos[2];
+	unsigned int *ibuf = (unsigned int *)buf;
+	unsigned int type = ibuf[1];
+	unsigned int size = ibuf[2];
 
-	if (buf_pos[1] != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
-		pr_err("error: invalid type field in container file section header\n");
-		return 0;
+	if (type != UCODE_EQUIV_CPU_TABLE_TYPE || !size) {
+		pr_err("empty section/"
+		       "invalid type field in container file section header\n");
+		return -EINVAL;
 	}
 
 	equiv_cpu_table = vmalloc(size);
 	if (!equiv_cpu_table) {
 		pr_err("failed to allocate equivalent CPU table\n");
-		return 0;
+		return -ENOMEM;
 	}
 
-	buf += UCODE_CONTAINER_HEADER_SIZE;
-	get_ucode_data(equiv_cpu_table, buf, size);
+	get_ucode_data(equiv_cpu_table, buf + UCODE_CONTAINER_HEADER_SIZE, size);
 
 	return size + UCODE_CONTAINER_HEADER_SIZE; /* add header length */
 }
@@ -223,16 +244,16 @@
 generic_load_microcode(int cpu, const u8 *data, size_t size)
 {
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
+	struct microcode_header_amd *mc_hdr = NULL;
+	unsigned int mc_size, leftover;
+	int offset;
 	const u8 *ucode_ptr = data;
 	void *new_mc = NULL;
-	void *mc;
-	int new_rev = uci->cpu_sig.rev;
-	unsigned int leftover;
-	unsigned long offset;
+	unsigned int new_rev = uci->cpu_sig.rev;
 	enum ucode_state state = UCODE_OK;
 
 	offset = install_equiv_cpu_table(ucode_ptr);
-	if (!offset) {
+	if (offset < 0) {
 		pr_err("failed to create equivalent cpu table\n");
 		return UCODE_ERROR;
 	}
@@ -241,64 +262,65 @@
 	leftover = size - offset;
 
 	while (leftover) {
-		unsigned int uninitialized_var(mc_size);
-		struct microcode_header_amd *mc_header;
-
-		mc = get_next_ucode(ucode_ptr, leftover, &mc_size);
-		if (!mc)
+		mc_hdr = get_next_ucode(cpu, ucode_ptr, leftover, &mc_size);
+		if (!mc_hdr)
 			break;
 
-		mc_header = (struct microcode_header_amd *)mc;
-		if (get_matching_microcode(cpu, mc, new_rev)) {
+		if (get_matching_microcode(cpu, mc_hdr, new_rev)) {
 			vfree(new_mc);
-			new_rev = mc_header->patch_id;
-			new_mc  = mc;
+			new_rev = mc_hdr->patch_id;
+			new_mc  = mc_hdr;
 		} else
-			vfree(mc);
+			vfree(mc_hdr);
 
 		ucode_ptr += mc_size;
 		leftover  -= mc_size;
 	}
 
-	if (new_mc) {
-		if (!leftover) {
-			vfree(uci->mc);
-			uci->mc = new_mc;
-			pr_debug("CPU%d found a matching microcode update with version 0x%x (current=0x%x)\n",
-				 cpu, new_rev, uci->cpu_sig.rev);
-		} else {
-			vfree(new_mc);
-			state = UCODE_ERROR;
-		}
-	} else
+	if (!new_mc) {
 		state = UCODE_NFOUND;
+		goto free_table;
+	}
 
+	if (!leftover) {
+		vfree(uci->mc);
+		uci->mc = new_mc;
+		pr_debug("CPU%d update ucode (0x%08x -> 0x%08x)\n",
+			 cpu, uci->cpu_sig.rev, new_rev);
+	} else {
+		vfree(new_mc);
+		state = UCODE_ERROR;
+	}
+
+free_table:
 	free_equiv_cpu_table();
 
 	return state;
 }
 
-static enum ucode_state request_microcode_fw(int cpu, struct device *device)
+static enum ucode_state request_microcode_amd(int cpu, struct device *device)
 {
 	const char *fw_name = "/*(DEBLOBBED)*/";
-	const struct firmware *firmware;
-	enum ucode_state ret;
+	const struct firmware *fw;
+	enum ucode_state ret = UCODE_NFOUND;
 
-	if (reject_firmware(&firmware, fw_name, device)) {
-		printk(KERN_ERR "microcode: failed to load file %s\n", fw_name);
-		return UCODE_NFOUND;
+	if (reject_firmware(&fw, fw_name, device)) {
+		pr_err("failed to load file %s\n", fw_name);
+		goto out;
 	}
 
-	if (*(u32 *)firmware->data != UCODE_MAGIC) {
-		pr_err("invalid UCODE_MAGIC (0x%08x)\n",
-		       *(u32 *)firmware->data);
-		return UCODE_ERROR;
+	ret = UCODE_ERROR;
+	if (*(u32 *)fw->data != UCODE_MAGIC) {
+		pr_err("invalid magic value (0x%08x)\n", *(u32 *)fw->data);
+		goto fw_release;
 	}
 
-	ret = generic_load_microcode(cpu, firmware->data, firmware->size);
+	ret = generic_load_microcode(cpu, fw->data, fw->size);
 
-	release_firmware(firmware);
+fw_release:
+	release_firmware(fw);
 
+out:
 	return ret;
 }
 
@@ -319,7 +341,7 @@
 
 static struct microcode_ops microcode_amd_ops = {
 	.request_microcode_user           = request_microcode_user,
-	.request_microcode_fw             = request_microcode_fw,
+	.request_microcode_fw             = request_microcode_amd,
 	.collect_cpu_info                 = collect_cpu_info_amd,
 	.apply_microcode                  = apply_microcode_amd,
 	.microcode_fini_cpu               = microcode_fini_cpu_amd,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/microcode_core.c linux-libre-2.6.39-gnu/arch/x86/kernel/microcode_core.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/microcode_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/microcode_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,6 +82,7 @@
 #include <linux/cpu.h>
 #include <linux/fs.h>
 #include <linux/mm.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/microcode.h>
 #include <asm/processor.h>
@@ -417,8 +418,10 @@
 	if (err)
 		return err;
 
-	if (microcode_init_cpu(cpu) == UCODE_ERROR)
-		err = -EINVAL;
+	if (microcode_init_cpu(cpu) == UCODE_ERROR) {
+		sysfs_remove_group(&sys_dev->kobj, &mc_attr_group);
+		return -EINVAL;
+	}
 
 	return err;
 }
@@ -436,33 +439,25 @@
 	return 0;
 }
 
-static int mc_sysdev_resume(struct sys_device *dev)
+static struct sysdev_driver mc_sysdev_driver = {
+	.add			= mc_sysdev_add,
+	.remove			= mc_sysdev_remove,
+};
+
+/**
+ * mc_bp_resume - Update boot CPU microcode during resume.
+ */
+static void mc_bp_resume(void)
 {
-	int cpu = dev->id;
+	int cpu = smp_processor_id();
 	struct ucode_cpu_info *uci = ucode_cpu_info + cpu;
 
-	if (!cpu_online(cpu))
-		return 0;
-
-	/*
-	 * 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,
+static struct syscore_ops mc_syscore_ops = {
+	.resume			= mc_bp_resume,
 };
 
 static __cpuinit int
@@ -540,6 +535,7 @@
 	if (error)
 		return error;
 
+	register_syscore_ops(&mc_syscore_ops);
 	register_hotcpu_notifier(&mc_cpu_notifier);
 
 	pr_info("Microcode Update Driver: v" MICROCODE_VERSION
@@ -554,6 +550,7 @@
 	microcode_dev_exit();
 
 	unregister_hotcpu_notifier(&mc_cpu_notifier);
+	unregister_syscore_ops(&mc_syscore_ops);
 
 	get_online_cpus();
 	mutex_lock(&microcode_mutex);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/mpparse.c linux-libre-2.6.39-gnu/arch/x86/kernel/mpparse.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/mpparse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/mpparse.c	2011-05-19 00:06:34.000000000 -0400
@@ -714,10 +714,6 @@
 		*nr_m_spare += 1;
 	}
 }
-#else /* CONFIG_X86_IO_APIC */
-static
-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)
@@ -731,6 +727,10 @@
 
 	return ret;
 }
+#else /* CONFIG_X86_IO_APIC */
+static
+inline void __init check_irq_src(struct mpc_intsrc *m, int *nr_m_spare) {}
+#endif /* CONFIG_X86_IO_APIC */
 
 static int  __init replace_intsrc_all(struct mpc_table *mpc,
 					unsigned long mpc_new_phys,
@@ -883,7 +883,7 @@
 
 	if (!mpc_new_phys) {
 		unsigned char old, new;
-		/* check if we can change the postion */
+		/* check if we can change the position */
 		mpc->checksum = 0;
 		old = mpf_checksum((unsigned char *)mpc, mpc->length);
 		mpc->checksum = 0xff;
@@ -892,7 +892,7 @@
 			printk(KERN_INFO "mpc is readonly, please try alloc_mptable instead\n");
 			return 0;
 		}
-		printk(KERN_INFO "use in-positon replacing\n");
+		printk(KERN_INFO "use in-position replacing\n");
 	} else {
 		mpf->physptr = mpc_new_phys;
 		mpc_new = phys_to_virt(mpc_new_phys);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/pci-calgary_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/pci-calgary_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/pci-calgary_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/pci-calgary_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -1279,7 +1279,7 @@
 
 	if (pci_dev == PCI_DEVICE_ID_IBM_CALIOC2) {
 		/*
-		 * FIXME: properly scan for devices accross the
+		 * FIXME: properly scan for devices across the
 		 * PCI-to-PCI bridge on every CalIOC2 port.
 		 */
 		return 1;
@@ -1295,7 +1295,7 @@
 
 /*
  * calgary_init_bitmap_from_tce_table():
- * Funtion for kdump case. In the second/kdump kernel initialize
+ * Function for kdump case. In the second/kdump kernel initialize
  * the bitmap based on the tce table entries obtained from first kernel
  */
 static void calgary_init_bitmap_from_tce_table(struct iommu_table *tbl)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/pci-gart_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/pci-gart_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/pci-gart_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/pci-gart_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 #include <linux/kdebug.h>
 #include <linux/scatterlist.h>
 #include <linux/iommu-helper.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/io.h>
 #include <linux/gfp.h>
 #include <asm/atomic.h>
@@ -81,6 +81,9 @@
 #define AGPEXTERN
 #endif
 
+/* GART can only remap to physical addresses < 1TB */
+#define GART_MAX_PHYS_ADDR	(1ULL << 40)
+
 /* backdoor interface to AGP driver */
 AGPEXTERN int agp_memory_reserved;
 AGPEXTERN __u32 *agp_gatt_table;
@@ -212,9 +215,13 @@
 				size_t size, int dir, unsigned long align_mask)
 {
 	unsigned long npages = iommu_num_pages(phys_mem, size, PAGE_SIZE);
-	unsigned long iommu_page = alloc_iommu(dev, npages, align_mask);
+	unsigned long iommu_page;
 	int i;
 
+	if (unlikely(phys_mem + size > GART_MAX_PHYS_ADDR))
+		return bad_dma_addr;
+
+	iommu_page = alloc_iommu(dev, npages, align_mask);
 	if (iommu_page == -1) {
 		if (!nonforced_iommu(dev, phys_mem, size))
 			return phys_mem;
@@ -589,7 +596,7 @@
 	aperture_alloc = aper_alloc;
 }
 
-static void gart_fixup_northbridges(struct sys_device *dev)
+static void gart_fixup_northbridges(void)
 {
 	int i;
 
@@ -613,33 +620,20 @@
 	}
 }
 
-static int gart_resume(struct sys_device *dev)
+static void gart_resume(void)
 {
 	pr_info("PCI-DMA: Resuming GART IOMMU\n");
 
-	gart_fixup_northbridges(dev);
+	gart_fixup_northbridges();
 
 	enable_gart_translations();
-
-	return 0;
 }
 
-static int gart_suspend(struct sys_device *dev, pm_message_t state)
-{
-	return 0;
-}
-
-static struct sysdev_class gart_sysdev_class = {
-	.name		= "gart",
-	.suspend	= gart_suspend,
+static struct syscore_ops gart_syscore_ops = {
 	.resume		= gart_resume,
 
 };
 
-static struct sys_device device_gart = {
-	.cls		= &gart_sysdev_class,
-};
-
 /*
  * Private Northbridge GATT initialization in case we cannot use the
  * AGP driver for some reason.
@@ -650,7 +644,7 @@
 	unsigned aper_base, new_aper_base;
 	struct pci_dev *dev;
 	void *gatt;
-	int i, error;
+	int i;
 
 	pr_info("PCI-DMA: Disabling AGP.\n");
 
@@ -685,12 +679,7 @@
 
 	agp_gatt_table = gatt;
 
-	error = sysdev_class_register(&gart_sysdev_class);
-	if (!error)
-		error = sysdev_register(&device_gart);
-	if (error)
-		panic("Could not register gart_sysdev -- "
-		      "would corrupt data on next suspend");
+	register_syscore_ops(&gart_syscore_ops);
 
 	flush_gart();
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/process_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/process_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/process_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/process_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -501,6 +501,10 @@
 	/* Make sure to be in 64bit mode */
 	clear_thread_flag(TIF_IA32);
 
+	/* Ensure the corresponding mm is not marked. */
+	if (current->mm)
+		current->mm->context.ia32_compat = 0;
+
 	/* TBD: overwrites user setup. Should have two bits.
 	   But 64bit processes have always behaved this way,
 	   so it's not too bad. The main problem is just that
@@ -516,6 +520,10 @@
 	set_thread_flag(TIF_IA32);
 	current->personality |= force_personality32;
 
+	/* Mark the associated mm as containing 32-bit tasks. */
+	if (current->mm)
+		current->mm->context.ia32_compat = 1;
+
 	/* Prepare the first "return" to user space */
 	current_thread_info()->status |= TS_COMPAT;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/process.c linux-libre-2.6.39-gnu/arch/x86/kernel/process.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/process.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/process.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,7 +87,7 @@
 void show_regs(struct pt_regs *regs)
 {
 	show_registers(regs);
-	show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs));
+	show_trace(NULL, regs, (unsigned long *)kernel_stack_pointer(regs), 0);
 }
 
 void show_regs_common(void)
@@ -110,12 +110,9 @@
 		init_utsname()->release,
 		(int)strcspn(init_utsname()->version, " "),
 		init_utsname()->version);
-	printk(KERN_CONT " ");
-	printk(KERN_CONT "%s %s", vendor, product);
-	if (board) {
-		printk(KERN_CONT "/");
-		printk(KERN_CONT "%s", board);
-	}
+	printk(KERN_CONT " %s %s", vendor, product);
+	if (board)
+		printk(KERN_CONT "/%s", board);
 	printk(KERN_CONT "\n");
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/ptrace.c linux-libre-2.6.39-gnu/arch/x86/kernel/ptrace.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/ptrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/ptrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -608,6 +608,9 @@
 	unsigned len, type;
 	struct perf_event *bp;
 
+	if (ptrace_get_breakpoints(tsk) < 0)
+		return -ESRCH;
+
 	data &= ~DR_CONTROL_RESERVED;
 	old_dr7 = ptrace_get_dr7(thread->ptrace_bps);
 restore:
@@ -655,6 +658,9 @@
 		}
 		goto restore;
 	}
+
+	ptrace_put_breakpoints(tsk);
+
 	return ((orig_ret < 0) ? orig_ret : rc);
 }
 
@@ -668,10 +674,17 @@
 
 	if (n < HBP_NUM) {
 		struct perf_event *bp;
+
+		if (ptrace_get_breakpoints(tsk) < 0)
+			return -ESRCH;
+
 		bp = thread->ptrace_bps[n];
 		if (!bp)
-			return 0;
-		val = bp->hw.info.address;
+			val = 0;
+		else
+			val = bp->hw.info.address;
+
+		ptrace_put_breakpoints(tsk);
 	} else if (n == 6) {
 		val = thread->debugreg6;
 	 } else if (n == 7) {
@@ -686,6 +699,10 @@
 	struct perf_event *bp;
 	struct thread_struct *t = &tsk->thread;
 	struct perf_event_attr attr;
+	int err = 0;
+
+	if (ptrace_get_breakpoints(tsk) < 0)
+		return -ESRCH;
 
 	if (!t->ptrace_bps[nr]) {
 		ptrace_breakpoint_init(&attr);
@@ -709,24 +726,23 @@
 		 * writing for the user. And anyway this is the previous
 		 * behaviour.
 		 */
-		if (IS_ERR(bp))
-			return PTR_ERR(bp);
+		if (IS_ERR(bp)) {
+			err = PTR_ERR(bp);
+			goto put;
+		}
 
 		t->ptrace_bps[nr] = bp;
 	} else {
-		int err;
-
 		bp = t->ptrace_bps[nr];
 
 		attr = bp->attr;
 		attr.bp_addr = addr;
 		err = modify_user_hw_breakpoint(bp, &attr);
-		if (err)
-			return err;
 	}
 
-
-	return 0;
+put:
+	ptrace_put_breakpoints(tsk);
+	return err;
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/reboot_32.S linux-libre-2.6.39-gnu/arch/x86/kernel/reboot_32.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/reboot_32.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/reboot_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,135 @@
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/segment.h>
+#include <asm/page_types.h>
+
+/*
+ * The following code and data reboots the machine by switching to real
+ * mode and jumping to the BIOS reset entry point, as if the CPU has
+ * really been reset.  The previous version asked the keyboard
+ * controller to pulse the CPU reset line, which is more thorough, but
+ * doesn't work with at least one type of 486 motherboard.  It is easy
+ * to stop this code working; hence the copious comments.
+ *
+ * This code is called with the restart type (0 = BIOS, 1 = APM) in %eax.
+ */
+	.section ".x86_trampoline","a"
+	.balign 16
+	.code32
+ENTRY(machine_real_restart_asm)
+r_base = .
+	/* Get our own relocated address */
+	call	1f
+1:	popl	%ebx
+	subl	$(1b - r_base), %ebx
+
+	/* Compute the equivalent real-mode segment */
+	movl	%ebx, %ecx
+	shrl	$4, %ecx
+	
+	/* Patch post-real-mode segment jump */
+	movw	(dispatch_table - r_base)(%ebx,%eax,2),%ax
+	movw	%ax, (101f - r_base)(%ebx)
+	movw	%cx, (102f - r_base)(%ebx)
+
+	/* Set up the IDT for real mode. */
+	lidtl	(machine_real_restart_idt - r_base)(%ebx)
+
+	/*
+	 * Set up a GDT from which we can load segment descriptors for real
+	 * mode.  The GDT is not used in real mode; it is just needed here to
+	 * prepare the descriptors.
+	 */
+	lgdtl	(machine_real_restart_gdt - r_base)(%ebx)
+
+	/*
+	 * Load the data segment registers with 16-bit compatible values
+	 */
+	movl	$16, %ecx
+	movl	%ecx, %ds
+	movl	%ecx, %es
+	movl	%ecx, %fs
+	movl	%ecx, %gs
+	movl	%ecx, %ss
+	ljmpl	$8, $1f - r_base
+
+/*
+ * This is 16-bit protected mode code to disable paging and the cache,
+ * switch to real mode and jump to the BIOS reset code.
+ *
+ * The instruction that switches to real mode by writing to CR0 must be
+ * followed immediately by a far jump instruction, which set CS to a
+ * valid value for real mode, and flushes the prefetch queue to avoid
+ * running instructions that have already been decoded in protected
+ * mode.
+ *
+ * Clears all the flags except ET, especially PG (paging), PE
+ * (protected-mode enable) and TS (task switch for coprocessor state
+ * save).  Flushes the TLB after paging has been disabled.  Sets CD and
+ * NW, to disable the cache on a 486, and invalidates the cache.  This
+ * is more like the state of a 486 after reset.  I don't know if
+ * something else should be done for other chips.
+ *
+ * More could be done here to set up the registers as if a CPU reset had
+ * occurred; hopefully real BIOSs don't assume much.  This is not the
+ * actual BIOS entry point, anyway (that is at 0xfffffff0).
+ *
+ * Most of this work is probably excessive, but it is what is tested.
+ */
+	.code16
+1:
+	xorl	%ecx, %ecx
+	movl	%cr0, %eax
+	andl	$0x00000011, %eax
+	orl	$0x60000000, %eax
+	movl	%eax, %cr0
+	movl	%ecx, %cr3
+	movl	%cr0, %edx
+	andl	$0x60000000, %edx	/* If no cache bits -> no wbinvd */
+	jz	2f
+	wbinvd
+2:
+	andb	$0x10, %al
+	movl	%eax, %cr0
+	.byte	0xea			/* ljmpw */
+101:	.word	0			/* Offset */
+102:	.word	0			/* Segment */
+
+bios:
+	ljmpw	$0xf000, $0xfff0
+
+apm:
+	movw	$0x1000, %ax
+	movw	%ax, %ss
+	movw	$0xf000, %sp
+	movw	$0x5307, %ax
+	movw	$0x0001, %bx
+	movw	$0x0003, %cx
+	int	$0x15
+
+END(machine_real_restart_asm)
+
+	.balign 16
+	/* These must match <asm/reboot.h */
+dispatch_table:
+	.word	bios - r_base
+	.word	apm - r_base
+END(dispatch_table)
+
+	.balign 16
+machine_real_restart_idt:
+	.word	0xffff		/* Length - real mode default value */
+	.long	0		/* Base - real mode default value */
+END(machine_real_restart_idt)
+
+	.balign 16
+ENTRY(machine_real_restart_gdt)
+	.quad	0		/* Self-pointer, filled in by PM code */
+	.quad	0		/* 16-bit code segment, filled in by PM code */
+	/*
+	 * 16-bit data segment with the selector value 16 = 0x10 and
+	 * base value 0x100; since this is consistent with real mode
+	 * semantics we don't have to reload the segments once CR0.PE = 0.
+	 */
+	.quad	GDT_ENTRY(0x0093, 0x100, 0xffff)
+END(machine_real_restart_gdt)
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/reboot.c linux-libre-2.6.39-gnu/arch/x86/kernel/reboot.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/reboot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/reboot.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
 #include <linux/dmi.h>
 #include <linux/sched.h>
 #include <linux/tboot.h>
+#include <linux/delay.h>
 #include <acpi/reboot.h>
 #include <asm/io.h>
 #include <asm/apic.h>
@@ -303,68 +304,16 @@
 }
 core_initcall(reboot_init);
 
-/* The following code and data reboots the machine by switching to real
-   mode and jumping to the BIOS reset entry point, as if the CPU has
-   really been reset.  The previous version asked the keyboard
-   controller to pulse the CPU reset line, which is more thorough, but
-   doesn't work with at least one type of 486 motherboard.  It is easy
-   to stop this code working; hence the copious comments. */
-static const unsigned long long
-real_mode_gdt_entries [3] =
-{
-	0x0000000000000000ULL,	/* Null descriptor */
-	0x00009b000000ffffULL,	/* 16-bit real-mode 64k code at 0x00000000 */
-	0x000093000100ffffULL	/* 16-bit real-mode 64k data at 0x00000100 */
-};
-
-static const struct desc_ptr
-real_mode_gdt = { sizeof (real_mode_gdt_entries) - 1, (long)real_mode_gdt_entries },
-real_mode_idt = { 0x3ff, 0 };
-
-/* This is 16-bit protected mode code to disable paging and the cache,
-   switch to real mode and jump to the BIOS reset code.
-
-   The instruction that switches to real mode by writing to CR0 must be
-   followed immediately by a far jump instruction, which set CS to a
-   valid value for real mode, and flushes the prefetch queue to avoid
-   running instructions that have already been decoded in protected
-   mode.
-
-   Clears all the flags except ET, especially PG (paging), PE
-   (protected-mode enable) and TS (task switch for coprocessor state
-   save).  Flushes the TLB after paging has been disabled.  Sets CD and
-   NW, to disable the cache on a 486, and invalidates the cache.  This
-   is more like the state of a 486 after reset.  I don't know if
-   something else should be done for other chips.
+extern const unsigned char machine_real_restart_asm[];
+extern const u64 machine_real_restart_gdt[3];
 
-   More could be done here to set up the registers as if a CPU reset had
-   occurred; hopefully real BIOSs don't assume much. */
-static const unsigned char real_mode_switch [] =
-{
-	0x66, 0x0f, 0x20, 0xc0,			/*    movl  %cr0,%eax        */
-	0x66, 0x83, 0xe0, 0x11,			/*    andl  $0x00000011,%eax */
-	0x66, 0x0d, 0x00, 0x00, 0x00, 0x60,	/*    orl   $0x60000000,%eax */
-	0x66, 0x0f, 0x22, 0xc0,			/*    movl  %eax,%cr0        */
-	0x66, 0x0f, 0x22, 0xd8,			/*    movl  %eax,%cr3        */
-	0x66, 0x0f, 0x20, 0xc3,			/*    movl  %cr0,%ebx        */
-	0x66, 0x81, 0xe3, 0x00, 0x00, 0x00, 0x60,	/*    andl  $0x60000000,%ebx */
-	0x74, 0x02,				/*    jz    f                */
-	0x0f, 0x09,				/*    wbinvd                 */
-	0x24, 0x10,				/* f: andb  $0x10,al         */
-	0x66, 0x0f, 0x22, 0xc0			/*    movl  %eax,%cr0        */
-};
-static const unsigned char jump_to_bios [] =
+void machine_real_restart(unsigned int type)
 {
-	0xea, 0x00, 0x00, 0xff, 0xff		/*    ljmp  $0xffff,$0x0000  */
-};
+	void *restart_va;
+	unsigned long restart_pa;
+	void (*restart_lowmem)(unsigned int);
+	u64 *lowmem_gdt;
 
-/*
- * Switch to real mode and then execute the code
- * specified by the code and length parameters.
- * We assume that length will aways be less that 100!
- */
-void machine_real_restart(const unsigned char *code, int length)
-{
 	local_irq_disable();
 
 	/* Write zero to CMOS register number 0x0f, which the BIOS POST
@@ -392,41 +341,23 @@
 	   too. */
 	*((unsigned short *)0x472) = reboot_mode;
 
-	/* For the switch to real mode, copy some code to low memory.  It has
-	   to be in the first 64k because it is running in 16-bit mode, and it
-	   has to have the same physical and virtual address, because it turns
-	   off paging.  Copy it near the end of the first page, out of the way
-	   of BIOS variables. */
-	memcpy((void *)(0x1000 - sizeof(real_mode_switch) - 100),
-		real_mode_switch, sizeof (real_mode_switch));
-	memcpy((void *)(0x1000 - 100), code, length);
-
-	/* Set up the IDT for real mode. */
-	load_idt(&real_mode_idt);
+	/* Patch the GDT in the low memory trampoline */
+	lowmem_gdt = TRAMPOLINE_SYM(machine_real_restart_gdt);
 
-	/* Set up a GDT from which we can load segment descriptors for real
-	   mode.  The GDT is not used in real mode; it is just needed here to
-	   prepare the descriptors. */
-	load_gdt(&real_mode_gdt);
+	restart_va = TRAMPOLINE_SYM(machine_real_restart_asm);
+	restart_pa = virt_to_phys(restart_va);
+	restart_lowmem = (void (*)(unsigned int))restart_pa;
 
-	/* Load the data segment registers, and thus the descriptors ready for
-	   real mode.  The base address of each segment is 0x100, 16 times the
-	   selector value being loaded here.  This is so that the segment
-	   registers don't have to be reloaded after switching to real mode:
-	   the values are consistent for real mode operation already. */
-	__asm__ __volatile__ ("movl $0x0010,%%eax\n"
-				"\tmovl %%eax,%%ds\n"
-				"\tmovl %%eax,%%es\n"
-				"\tmovl %%eax,%%fs\n"
-				"\tmovl %%eax,%%gs\n"
-				"\tmovl %%eax,%%ss" : : : "eax");
+	/* GDT[0]: GDT self-pointer */
+	lowmem_gdt[0] =
+		(u64)(sizeof(machine_real_restart_gdt) - 1) +
+		((u64)virt_to_phys(lowmem_gdt) << 16);
+	/* GDT[1]: 64K real mode code segment */
+	lowmem_gdt[1] =
+		GDT_ENTRY(0x009b, restart_pa, 0xffff);
 
-	/* Jump to the 16-bit code that we copied earlier.  It disables paging
-	   and the cache, switches to real mode, and jumps to the BIOS reset
-	   entry point. */
-	__asm__ __volatile__ ("ljmp $0x0008,%0"
-				:
-				: "i" ((void *)(0x1000 - sizeof (real_mode_switch) - 100)));
+	/* Jump to the identity-mapped low memory code */
+	restart_lowmem(type);
 }
 #ifdef CONFIG_APM_MODULE
 EXPORT_SYMBOL(machine_real_restart);
@@ -581,7 +512,7 @@
 
 #ifdef CONFIG_X86_32
 		case BOOT_BIOS:
-			machine_real_restart(jump_to_bios, sizeof(jump_to_bios));
+			machine_real_restart(MRR_BIOS);
 
 			reboot_type = BOOT_KBD;
 			break;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/rtc.c linux-libre-2.6.39-gnu/arch/x86/kernel/rtc.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/rtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/rtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
 #include <linux/acpi.h>
 #include <linux/bcd.h>
 #include <linux/pnp.h>
+#include <linux/of.h>
 
 #include <asm/vsyscall.h>
 #include <asm/x86_init.h>
@@ -236,6 +237,8 @@
 		}
 	}
 #endif
+	if (of_have_populated_dt())
+		return 0;
 
 	platform_device_register(&rtc_device);
 	dev_info(&rtc_device.dev,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/setup.c linux-libre-2.6.39-gnu/arch/x86/kernel/setup.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -113,6 +113,7 @@
 #endif
 #include <asm/mce.h>
 #include <asm/alternative.h>
+#include <asm/prom.h>
 
 /*
  * end_pfn only includes RAM, while max_pfn_mapped includes all e820 entries.
@@ -297,6 +298,9 @@
 static inline void init_gbpages(void)
 {
 }
+static void __init cleanup_highmap(void)
+{
+}
 #endif
 
 static void __init reserve_brk(void)
@@ -429,16 +433,30 @@
 		return;
 	pa_data = boot_params.hdr.setup_data;
 	while (pa_data) {
-		data = early_memremap(pa_data, PAGE_SIZE);
+		u32 data_len, map_len;
+
+		map_len = max(PAGE_SIZE - (pa_data & ~PAGE_MASK),
+			      (u64)sizeof(struct setup_data));
+		data = early_memremap(pa_data, map_len);
+		data_len = data->len + sizeof(struct setup_data);
+		if (data_len > map_len) {
+			early_iounmap(data, map_len);
+			data = early_memremap(pa_data, data_len);
+			map_len = data_len;
+		}
+
 		switch (data->type) {
 		case SETUP_E820_EXT:
-			parse_e820_ext(data, pa_data);
+			parse_e820_ext(data);
+			break;
+		case SETUP_DTB:
+			add_dtb(pa_data);
 			break;
 		default:
 			break;
 		}
 		pa_data = data->next;
-		early_iounmap(data, PAGE_SIZE);
+		early_iounmap(data, map_len);
 	}
 }
 
@@ -601,28 +619,6 @@
 
 }
 
-/*
- * Note: elfcorehdr_addr is not just limited to vmcore. It is also used by
- * is_kdump_kernel() to determine if we are booting after a panic. Hence
- * ifdef it under CONFIG_CRASH_DUMP and not CONFIG_PROC_VMCORE.
- */
-
-#ifdef CONFIG_CRASH_DUMP
-/* elfcorehdr= specifies the location of elf core header
- * stored by the crashed kernel. This option will be passed
- * by kexec loader to the capture kernel.
- */
-static int __init setup_elfcorehdr(char *arg)
-{
-	char *end;
-	if (!arg)
-		return -EINVAL;
-	elfcorehdr_addr = memparse(arg, &end);
-	return end > arg ? 0 : -EINVAL;
-}
-early_param("elfcorehdr", setup_elfcorehdr);
-#endif
-
 static __init void reserve_ibft_region(void)
 {
 	unsigned long addr, size = 0;
@@ -680,15 +676,6 @@
 
 early_param("reservelow", parse_reservelow);
 
-static u64 __init get_max_mapped(void)
-{
-	u64 end = max_pfn_mapped;
-
-	end <<= PAGE_SHIFT;
-
-	return end;
-}
-
 /*
  * Determine if we were loaded by an EFI loader.  If so, then we have also been
  * passed the efi memmap, systab, etc., so we should use these data structures
@@ -704,8 +691,6 @@
 
 void __init setup_arch(char **cmdline_p)
 {
-	int acpi = 0;
-	int amd = 0;
 	unsigned long flags;
 
 #ifdef CONFIG_X86_32
@@ -922,6 +907,8 @@
 	 */
 	reserve_brk();
 
+	cleanup_highmap();
+
 	memblock.current_limit = get_max_mapped();
 	memblock_x86_fill();
 
@@ -935,15 +922,8 @@
 	printk(KERN_DEBUG "initial memory mapped : 0 - %08lx\n",
 			max_pfn_mapped<<PAGE_SHIFT);
 
-	reserve_trampoline_memory();
+	setup_trampolines();
 
-#ifdef CONFIG_ACPI_SLEEP
-	/*
-	 * Reserve low memory region for sleep support.
-	 * even before init_memory_mapping
-	 */
-	acpi_reserve_wakeup_memory();
-#endif
 	init_gbpages();
 
 	/* max_pfn_mapped is updated here */
@@ -984,19 +964,7 @@
 
 	early_acpi_boot_init();
 
-#ifdef CONFIG_ACPI_NUMA
-	/*
-	 * Parse SRAT to discover nodes.
-	 */
-	acpi = acpi_numa_init();
-#endif
-
-#ifdef CONFIG_AMD_NUMA
-	if (!acpi)
-		amd = !amd_numa_init(0, max_pfn);
-#endif
-
-	initmem_init(0, max_pfn, acpi, amd);
+	initmem_init();
 	memblock_find_dma_reserve();
 	dma32_reserve_bootmem();
 
@@ -1008,6 +976,11 @@
 	paging_init();
 	x86_init.paging.pagetable_setup_done(swapper_pg_dir);
 
+	if (boot_cpu_data.cpuid_level >= 0) {
+		/* A CPU has %cr4 if and only if it has CPUID */
+		mmu_cr4_features = read_cr4();
+	}
+
 #ifdef CONFIG_X86_32
 	/* sync back kernel address range */
 	clone_pgd_range(initial_page_table + KERNEL_PGD_BOUNDARY,
@@ -1029,8 +1002,8 @@
 	 * Read APIC and some other early information from ACPI tables.
 	 */
 	acpi_boot_init();
-
 	sfi_init();
+	x86_dtb_init();
 
 	/*
 	 * get boot-time SMP configuration:
@@ -1040,9 +1013,7 @@
 
 	prefill_possible_map();
 
-#ifdef CONFIG_X86_64
 	init_cpu_to_node();
-#endif
 
 	init_apic_mappings();
 	ioapic_and_gsi_init();
@@ -1066,6 +1037,8 @@
 #endif
 	x86_init.oem.banner();
 
+	x86_init.timers.wallclock_init();
+
 	mcheck_init();
 
 	local_irq_save(flags);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/setup_percpu.c linux-libre-2.6.39-gnu/arch/x86/kernel/setup_percpu.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/setup_percpu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/setup_percpu.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,10 +225,15 @@
 		per_cpu(x86_bios_cpu_apicid, cpu) =
 			early_per_cpu_map(x86_bios_cpu_apicid, cpu);
 #endif
+#ifdef CONFIG_X86_32
+		per_cpu(x86_cpu_to_logical_apicid, cpu) =
+			early_per_cpu_map(x86_cpu_to_logical_apicid, cpu);
+#endif
 #ifdef CONFIG_X86_64
 		per_cpu(irq_stack_ptr, cpu) =
 			per_cpu(irq_stack_union.irq_stack, cpu) +
 			IRQ_STACK_SIZE - 64;
+#endif
 #ifdef CONFIG_NUMA
 		per_cpu(x86_cpu_to_node_map, cpu) =
 			early_per_cpu_map(x86_cpu_to_node_map, cpu);
@@ -242,7 +247,6 @@
 		 */
 		set_cpu_numa_node(cpu, early_cpu_to_node(cpu));
 #endif
-#endif
 		/*
 		 * Up to this point, the boot CPU has been using .init.data
 		 * area.  Reload any changed state for the boot CPU.
@@ -256,7 +260,10 @@
 	early_per_cpu_ptr(x86_cpu_to_apicid) = NULL;
 	early_per_cpu_ptr(x86_bios_cpu_apicid) = NULL;
 #endif
-#if defined(CONFIG_X86_64) && defined(CONFIG_NUMA)
+#ifdef CONFIG_X86_32
+	early_per_cpu_ptr(x86_cpu_to_logical_apicid) = NULL;
+#endif
+#ifdef CONFIG_NUMA
 	early_per_cpu_ptr(x86_cpu_to_node_map) = NULL;
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/smpboot.c linux-libre-2.6.39-gnu/arch/x86/kernel/smpboot.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/smpboot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/smpboot.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,6 +64,7 @@
 #include <asm/mtrr.h>
 #include <asm/mwait.h>
 #include <asm/apic.h>
+#include <asm/io_apic.h>
 #include <asm/setup.h>
 #include <asm/uv/uv.h>
 #include <linux/mc146818rtc.h>
@@ -71,10 +72,6 @@
 #include <asm/smpboot_hooks.h>
 #include <asm/i8259.h>
 
-#ifdef CONFIG_X86_32
-u8 apicid_2_node[MAX_APICID];
-#endif
-
 /* State of each CPU */
 DEFINE_PER_CPU(int, cpu_state) = { 0 };
 
@@ -130,68 +127,14 @@
 DEFINE_PER_CPU(cpumask_var_t, cpu_core_map);
 EXPORT_PER_CPU_SYMBOL(cpu_core_map);
 
+DEFINE_PER_CPU(cpumask_var_t, cpu_llc_shared_map);
+
 /* Per CPU bogomips and other parameters */
 DEFINE_PER_CPU_SHARED_ALIGNED(struct cpuinfo_x86, cpu_info);
 EXPORT_PER_CPU_SYMBOL(cpu_info);
 
 atomic_t init_deasserted;
 
-#if defined(CONFIG_NUMA) && defined(CONFIG_X86_32)
-/* which node each logical CPU is on */
-int cpu_to_node_map[NR_CPUS] __read_mostly = { [0 ... NR_CPUS-1] = 0 };
-EXPORT_SYMBOL(cpu_to_node_map);
-
-/* set up a mapping between cpu and node. */
-static void map_cpu_to_node(int cpu, int node)
-{
-	printk(KERN_INFO "Mapping cpu %d to node %d\n", cpu, node);
-	cpumask_set_cpu(cpu, node_to_cpumask_map[node]);
-	cpu_to_node_map[cpu] = node;
-}
-
-/* undo a mapping between cpu and node. */
-static void unmap_cpu_to_node(int cpu)
-{
-	int node;
-
-	printk(KERN_INFO "Unmapping cpu %d from all nodes\n", cpu);
-	for (node = 0; node < MAX_NUMNODES; node++)
-		cpumask_clear_cpu(cpu, node_to_cpumask_map[node]);
-	cpu_to_node_map[cpu] = 0;
-}
-#else /* !(CONFIG_NUMA && CONFIG_X86_32) */
-#define map_cpu_to_node(cpu, node)	({})
-#define unmap_cpu_to_node(cpu)	({})
-#endif
-
-#ifdef CONFIG_X86_32
-static int boot_cpu_logical_apicid;
-
-u8 cpu_2_logical_apicid[NR_CPUS] __read_mostly =
-					{ [0 ... NR_CPUS-1] = BAD_APICID };
-
-static void map_cpu_to_logical_apicid(void)
-{
-	int cpu = smp_processor_id();
-	int apicid = logical_smp_processor_id();
-	int node = apic->apicid_to_node(apicid);
-
-	if (!node_online(node))
-		node = first_online_node;
-
-	cpu_2_logical_apicid[cpu] = apicid;
-	map_cpu_to_node(cpu, node);
-}
-
-void numa_remove_cpu(int cpu)
-{
-	cpu_2_logical_apicid[cpu] = BAD_APICID;
-	unmap_cpu_to_node(cpu);
-}
-#else
-#define map_cpu_to_logical_apicid()  do {} while (0)
-#endif
-
 /*
  * Report back to the Boot Processor.
  * Running on AP.
@@ -259,7 +202,6 @@
 		apic->smp_callin_clear_local_apic();
 	setup_local_APIC();
 	end_local_APIC_setup();
-	map_cpu_to_logical_apicid();
 
 	/*
 	 * Need to setup vector mappings before we enable interrupts.
@@ -355,23 +297,6 @@
 	cpu_idle();
 }
 
-#ifdef CONFIG_CPUMASK_OFFSTACK
-/* In this case, llc_shared_map is a pointer to a cpumask. */
-static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst,
-				    const struct cpuinfo_x86 *src)
-{
-	struct cpumask *llc = dst->llc_shared_map;
-	*dst = *src;
-	dst->llc_shared_map = llc;
-}
-#else
-static inline void copy_cpuinfo_x86(struct cpuinfo_x86 *dst,
-				    const struct cpuinfo_x86 *src)
-{
-	*dst = *src;
-}
-#endif /* CONFIG_CPUMASK_OFFSTACK */
-
 /*
  * The bootstrap kernel entry code has set these up. Save them for
  * a given CPU
@@ -381,7 +306,7 @@
 {
 	struct cpuinfo_x86 *c = &cpu_data(id);
 
-	copy_cpuinfo_x86(c, &boot_cpu_data);
+	*c = boot_cpu_data;
 	c->cpu_index = id;
 	if (id != 0)
 		identify_secondary_cpu(c);
@@ -389,15 +314,12 @@
 
 static void __cpuinit link_thread_siblings(int cpu1, int cpu2)
 {
-	struct cpuinfo_x86 *c1 = &cpu_data(cpu1);
-	struct cpuinfo_x86 *c2 = &cpu_data(cpu2);
-
 	cpumask_set_cpu(cpu1, cpu_sibling_mask(cpu2));
 	cpumask_set_cpu(cpu2, cpu_sibling_mask(cpu1));
 	cpumask_set_cpu(cpu1, cpu_core_mask(cpu2));
 	cpumask_set_cpu(cpu2, cpu_core_mask(cpu1));
-	cpumask_set_cpu(cpu1, c2->llc_shared_map);
-	cpumask_set_cpu(cpu2, c1->llc_shared_map);
+	cpumask_set_cpu(cpu1, cpu_llc_shared_mask(cpu2));
+	cpumask_set_cpu(cpu2, cpu_llc_shared_mask(cpu1));
 }
 
 
@@ -414,6 +336,7 @@
 
 			if (cpu_has(c, X86_FEATURE_TOPOEXT)) {
 				if (c->phys_proc_id == o->phys_proc_id &&
+				    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i) &&
 				    c->compute_unit_id == o->compute_unit_id)
 					link_thread_siblings(cpu, i);
 			} else if (c->phys_proc_id == o->phys_proc_id &&
@@ -425,7 +348,7 @@
 		cpumask_set_cpu(cpu, cpu_sibling_mask(cpu));
 	}
 
-	cpumask_set_cpu(cpu, c->llc_shared_map);
+	cpumask_set_cpu(cpu, cpu_llc_shared_mask(cpu));
 
 	if (__this_cpu_read(cpu_info.x86_max_cores) == 1) {
 		cpumask_copy(cpu_core_mask(cpu), cpu_sibling_mask(cpu));
@@ -436,8 +359,8 @@
 	for_each_cpu(i, cpu_sibling_setup_mask) {
 		if (per_cpu(cpu_llc_id, cpu) != BAD_APICID &&
 		    per_cpu(cpu_llc_id, cpu) == per_cpu(cpu_llc_id, i)) {
-			cpumask_set_cpu(i, c->llc_shared_map);
-			cpumask_set_cpu(cpu, cpu_data(i).llc_shared_map);
+			cpumask_set_cpu(i, cpu_llc_shared_mask(cpu));
+			cpumask_set_cpu(cpu, cpu_llc_shared_mask(i));
 		}
 		if (c->phys_proc_id == cpu_data(i).phys_proc_id) {
 			cpumask_set_cpu(i, cpu_core_mask(cpu));
@@ -476,7 +399,7 @@
 	    !(cpu_has(c, X86_FEATURE_AMD_DCM)))
 		return cpu_core_mask(cpu);
 	else
-		return c->llc_shared_map;
+		return cpu_llc_shared_mask(cpu);
 }
 
 static void impress_friends(void)
@@ -788,7 +711,7 @@
 	stack_start  = c_idle.idle->thread.sp;
 
 	/* start_ip had better be page-aligned! */
-	start_ip = setup_trampoline();
+	start_ip = trampoline_address();
 
 	/* So we see what's up */
 	announce_cpu(cpu, apicid);
@@ -798,6 +721,8 @@
 	 * the targeted processor.
 	 */
 
+	printk(KERN_DEBUG "smpboot cpu %d: start_ip = %lx\n", cpu, start_ip);
+
 	atomic_set(&init_deasserted, 0);
 
 	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
@@ -851,8 +776,8 @@
 			pr_debug("CPU%d: has booted.\n", cpu);
 		else {
 			boot_error = 1;
-			if (*((volatile unsigned char *)trampoline_base)
-					== 0xA5)
+			if (*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status)
+			    == 0xA5A5A5A5)
 				/* trampoline started but...? */
 				pr_err("CPU%d: Stuck ??\n", cpu);
 			else
@@ -878,7 +803,7 @@
 	}
 
 	/* mark "stuck" area as not stuck */
-	*((volatile unsigned long *)trampoline_base) = 0;
+	*(volatile u32 *)TRAMPOLINE_SYM(trampoline_status) = 0;
 
 	if (get_uv_system_type() != UV_NON_UNIQUE_APIC) {
 		/*
@@ -945,6 +870,14 @@
 	return 0;
 }
 
+/**
+ * arch_disable_smp_support() - disables SMP support for x86 at runtime
+ */
+void arch_disable_smp_support(void)
+{
+	disable_ioapic_support();
+}
+
 /*
  * Fall back to non SMP mode after errors.
  *
@@ -960,7 +893,6 @@
 		physid_set_mask_of_physid(boot_cpu_physical_apicid, &phys_cpu_present_map);
 	else
 		physid_set_mask_of_physid(0, &phys_cpu_present_map);
-	map_cpu_to_logical_apicid();
 	cpumask_set_cpu(0, cpu_sibling_mask(0));
 	cpumask_set_cpu(0, cpu_core_mask(0));
 }
@@ -1045,7 +977,7 @@
 				"(tell your hw vendor)\n");
 		}
 		smpboot_clear_io_apic();
-		arch_disable_smp_support();
+		disable_ioapic_support();
 		return -1;
 	}
 
@@ -1089,21 +1021,19 @@
 
 	preempt_disable();
 	smp_cpu_index_default();
-	memcpy(__this_cpu_ptr(&cpu_info), &boot_cpu_data, sizeof(cpu_info));
-	cpumask_copy(cpu_callin_mask, cpumask_of(0));
-	mb();
+
 	/*
 	 * Setup boot CPU information
 	 */
 	smp_store_cpu_info(0); /* Final full version of the data */
-#ifdef CONFIG_X86_32
-	boot_cpu_logical_apicid = logical_smp_processor_id();
-#endif
+	cpumask_copy(cpu_callin_mask, cpumask_of(0));
+	mb();
+
 	current_thread_info()->cpu = 0;  /* needed? */
 	for_each_possible_cpu(i) {
 		zalloc_cpumask_var(&per_cpu(cpu_sibling_map, i), GFP_KERNEL);
 		zalloc_cpumask_var(&per_cpu(cpu_core_map, i), GFP_KERNEL);
-		zalloc_cpumask_var(&cpu_data(i).llc_shared_map, GFP_KERNEL);
+		zalloc_cpumask_var(&per_cpu(cpu_llc_shared_map, i), GFP_KERNEL);
 	}
 	set_cpu_sibling_map(0);
 
@@ -1139,8 +1069,6 @@
 
 	bsp_end_local_APIC_setup();
 
-	map_cpu_to_logical_apicid();
-
 	if (apic->setup_portio_remap)
 		apic->setup_portio_remap();
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/stacktrace.c linux-libre-2.6.39-gnu/arch/x86/kernel/stacktrace.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/stacktrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/stacktrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
  */
 void save_stack_trace(struct stack_trace *trace)
 {
-	dump_trace(current, NULL, NULL, &save_stack_ops, trace);
+	dump_trace(current, NULL, NULL, 0, &save_stack_ops, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
@@ -81,14 +81,14 @@
 
 void save_stack_trace_regs(struct stack_trace *trace, struct pt_regs *regs)
 {
-	dump_trace(current, regs, NULL, &save_stack_ops, trace);
+	dump_trace(current, regs, NULL, 0, &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, &save_stack_ops_nosched, trace);
+	dump_trace(tsk, NULL, NULL, 0, &save_stack_ops_nosched, trace);
 	if (trace->nr_entries < trace->max_entries)
 		trace->entries[trace->nr_entries++] = ULONG_MAX;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/step.c linux-libre-2.6.39-gnu/arch/x86/kernel/step.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/step.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/step.c	2011-05-19 00:06:34.000000000 -0400
@@ -166,7 +166,7 @@
 	 * Make sure block stepping (BTF) is not enabled unless it should be.
 	 * Note that we don't try to worry about any is_setting_trap_flag()
 	 * instructions after the first when using block stepping.
-	 * So noone should try to use debugger block stepping in a program
+	 * So no one should try to use debugger block stepping in a program
 	 * that uses user-mode single stepping itself.
 	 */
 	if (enable_single_step(child) && block) {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/syscall_table_32.S linux-libre-2.6.39-gnu/arch/x86/kernel/syscall_table_32.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/syscall_table_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/syscall_table_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -340,3 +340,7 @@
 	.long sys_fanotify_init
 	.long sys_fanotify_mark
 	.long sys_prlimit64		/* 340 */
+	.long sys_name_to_handle_at
+	.long sys_open_by_handle_at
+	.long sys_clock_adjtime
+	.long sys_syncfs
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/topology.c linux-libre-2.6.39-gnu/arch/x86/kernel/topology.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/topology.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/topology.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 	/*
 	 * CPU0 cannot be offlined due to several
 	 * restrictions and assumptions in kernel. This basically
-	 * doesnt add a control file, one cannot attempt to offline
+	 * doesn't add a control file, one cannot attempt to offline
 	 * BSP.
 	 *
 	 * Also certain PCI quirks require not to enable hotplug control
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/trampoline_32.S linux-libre-2.6.39-gnu/arch/x86/kernel/trampoline_32.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/trampoline_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/trampoline_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -32,9 +32,11 @@
 #include <asm/segment.h>
 #include <asm/page_types.h>
 
-/* We can free up trampoline after bootup if cpu hotplug is not supported. */
-__CPUINITRODATA
-.code16
+#ifdef CONFIG_SMP
+
+	.section ".x86_trampoline","a"
+	.balign PAGE_SIZE
+	.code16
 
 ENTRY(trampoline_data)
 r_base = .
@@ -44,7 +46,7 @@
 
 	cli			# We should be safe anyway
 
-	movl	$0xA5A5A5A5, trampoline_data - r_base
+	movl	$0xA5A5A5A5, trampoline_status - r_base
 				# write marker for master knows we're running
 
 	/* GDT tables in non default location kernel can be beyond 16MB and
@@ -72,5 +74,10 @@
 	.word	0				# idt limit = 0
 	.long	0				# idt base = 0L
 
+ENTRY(trampoline_status)
+	.long	0
+
 .globl trampoline_end
 trampoline_end:
+
+#endif /* CONFIG_SMP */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/trampoline_64.S linux-libre-2.6.39-gnu/arch/x86/kernel/trampoline_64.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/trampoline_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/trampoline_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -32,13 +32,9 @@
 #include <asm/segment.h>
 #include <asm/processor-flags.h>
 
-#ifdef CONFIG_ACPI_SLEEP
-.section .rodata, "a", @progbits
-#else
-/* We can free up the trampoline after bootup if cpu hotplug is not supported. */
-__CPUINITRODATA
-#endif
-.code16
+	.section ".x86_trampoline","a"
+	.balign PAGE_SIZE
+	.code16
 
 ENTRY(trampoline_data)
 r_base = .
@@ -50,7 +46,7 @@
 	mov	%ax, %ss
 
 
-	movl	$0xA5A5A5A5, trampoline_data - r_base
+	movl	$0xA5A5A5A5, trampoline_status - r_base
 				# write marker for master knows we're running
 
 					# Setup stack
@@ -64,10 +60,13 @@
 	movzx	%ax, %esi		# Find the 32bit trampoline location
 	shll	$4, %esi
 
-					# Fixup the vectors
-	addl	%esi, startup_32_vector - r_base
-	addl	%esi, startup_64_vector - r_base
-	addl	%esi, tgdt + 2 - r_base	# Fixup the gdt pointer
+					# Fixup the absolute vectors
+	leal	(startup_32 - r_base)(%esi), %eax
+	movl	%eax, startup_32_vector - r_base
+	leal	(startup_64 - r_base)(%esi), %eax
+	movl	%eax, startup_64_vector - r_base
+	leal	(tgdt - r_base)(%esi), %eax
+	movl	%eax, (tgdt + 2 - r_base)
 
 	/*
 	 * GDT tables in non default location kernel can be beyond 16MB and
@@ -129,6 +128,7 @@
 	jmp no_longmode
 #include "verify_cpu.S"
 
+	.balign 4
 	# Careful these need to be in the same 64K segment as the above;
 tidt:
 	.word	0			# idt limit = 0
@@ -156,6 +156,10 @@
 	.long	startup_64 - r_base
 	.word	__KERNEL_CS, 0
 
+	.balign 4
+ENTRY(trampoline_status)
+	.long	0
+
 trampoline_stack:
 	.org 0x1000
 trampoline_stack_end:
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/trampoline.c linux-libre-2.6.39-gnu/arch/x86/kernel/trampoline.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/trampoline.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/trampoline.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,39 +2,41 @@
 #include <linux/memblock.h>
 
 #include <asm/trampoline.h>
+#include <asm/cacheflush.h>
 #include <asm/pgtable.h>
 
-#if defined(CONFIG_X86_64) && defined(CONFIG_ACPI_SLEEP)
-#define __trampinit
-#define __trampinitdata
-#else
-#define __trampinit __cpuinit
-#define __trampinitdata __cpuinitdata
-#endif
-
-/* ready for x86_64 and x86 */
-unsigned char *__trampinitdata trampoline_base;
+unsigned char *x86_trampoline_base;
 
-void __init reserve_trampoline_memory(void)
+void __init setup_trampolines(void)
 {
 	phys_addr_t mem;
+	size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
 
 	/* Has to be in very low memory so we can execute real-mode AP code. */
-	mem = memblock_find_in_range(0, 1<<20, TRAMPOLINE_SIZE, PAGE_SIZE);
+	mem = memblock_find_in_range(0, 1<<20, size, PAGE_SIZE);
 	if (mem == MEMBLOCK_ERROR)
 		panic("Cannot allocate trampoline\n");
 
-	trampoline_base = __va(mem);
-	memblock_x86_reserve_range(mem, mem + TRAMPOLINE_SIZE, "TRAMPOLINE");
+	x86_trampoline_base = __va(mem);
+	memblock_x86_reserve_range(mem, mem + size, "TRAMPOLINE");
+
+	printk(KERN_DEBUG "Base memory trampoline at [%p] %llx size %zu\n",
+	       x86_trampoline_base, (unsigned long long)mem, size);
+
+	memcpy(x86_trampoline_base, x86_trampoline_start, size);
 }
 
 /*
- * Currently trivial. Write the real->protected mode
- * bootstrap into the page concerned. The caller
- * has made sure it's suitably aligned.
+ * setup_trampolines() gets called very early, to guarantee the
+ * availability of low memory.  This is before the proper kernel page
+ * tables are set up, so we cannot set page permissions in that
+ * function.  Thus, we use an arch_initcall instead.
  */
-unsigned long __trampinit setup_trampoline(void)
+static int __init configure_trampolines(void)
 {
-	memcpy(trampoline_base, trampoline_data, TRAMPOLINE_SIZE);
-	return virt_to_phys(trampoline_base);
+	size_t size = PAGE_ALIGN(x86_trampoline_end - x86_trampoline_start);
+
+	set_memory_x((unsigned long)x86_trampoline_base, size >> PAGE_SHIFT);
+	return 0;
 }
+arch_initcall(configure_trampolines);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/tsc.c linux-libre-2.6.39-gnu/arch/x86/kernel/tsc.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/tsc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/tsc.c	2011-05-19 00:06:34.000000000 -0400
@@ -427,7 +427,7 @@
 	 * the delta to the previous read. We keep track of the min
 	 * and max values of that delta. The delta is mostly defined
 	 * by the IO time of the PIT access, so we can detect when a
-	 * SMI/SMM disturbance happend between the two reads. If the
+	 * SMI/SMM disturbance happened between the two reads. If the
 	 * maximum time is significantly larger than the minimum time,
 	 * then we discard the result and have another try.
 	 *
@@ -900,7 +900,7 @@
  * timer based, instead of loop based, we don't block the boot
  * process while this longer calibration is done.
  *
- * If there are any calibration anomolies (too many SMIs, etc),
+ * If there are any calibration anomalies (too many SMIs, etc),
  * or the refined calibration is off by 1% of the fast early
  * calibration, we throw out the new calibration and use the
  * early calibration.
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/verify_cpu.S linux-libre-2.6.39-gnu/arch/x86/kernel/verify_cpu.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/verify_cpu.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/verify_cpu.S	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,7 @@
  *	This file is expected to run in 32bit code.  Currently:
  *
  *	arch/x86/boot/compressed/head_64.S: Boot cpu verification
- *	arch/x86/kernel/trampoline_64.S: secondary processor verfication
+ *	arch/x86/kernel/trampoline_64.S: secondary processor verification
  *	arch/x86/kernel/head_32.S: processor startup
  *
  *	verify_cpu, returns the status of longmode and SSE in register %eax.
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/x86/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/x86/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -105,6 +105,7 @@
 		SCHED_TEXT
 		LOCK_TEXT
 		KPROBES_TEXT
+		ENTRY_TEXT
 		IRQENTRY_TEXT
 		*(.fixup)
 		*(.gnu.warning)
@@ -230,7 +231,7 @@
 	 * output PHDR, so the next output section - .init.text - should
 	 * start another segment - init.
 	 */
-	PERCPU_VADDR(0, :percpu)
+	PERCPU_VADDR(INTERNODE_CACHE_BYTES, 0, :percpu)
 #endif
 
 	INIT_TEXT_SECTION(PAGE_SIZE)
@@ -240,6 +241,18 @@
 
 	INIT_DATA_SECTION(16)
 
+	/*
+	 * Code and data for a variety of lowlevel trampolines, to be
+	 * copied into base memory (< 1 MiB) during initialization.
+	 * Since it is copied early, the main copy can be discarded
+	 * afterwards.
+	 */
+	 .x86_trampoline : AT(ADDR(.x86_trampoline) - LOAD_OFFSET) {
+		x86_trampoline_start = .;
+		*(.x86_trampoline)
+		x86_trampoline_end = .;
+	}
+
 	.x86_cpu_dev.init : AT(ADDR(.x86_cpu_dev.init) - LOAD_OFFSET) {
 		__x86_cpu_dev_start = .;
 		*(.x86_cpu_dev.init)
@@ -291,6 +304,7 @@
 		*(.iommu_table)
 		__iommu_table_end = .;
 	}
+
 	. = ALIGN(8);
 	/*
 	 * .exit.text is discard at runtime, not link time, to deal with
@@ -305,7 +319,7 @@
 	}
 
 #if !defined(CONFIG_X86_64) || !defined(CONFIG_SMP)
-	PERCPU(THREAD_SIZE)
+	PERCPU(INTERNODE_CACHE_BYTES, PAGE_SIZE)
 #endif
 
 	. = ALIGN(PAGE_SIZE);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/x8664_ksyms_64.c linux-libre-2.6.39-gnu/arch/x86/kernel/x8664_ksyms_64.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/x8664_ksyms_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/x8664_ksyms_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,6 +52,7 @@
 EXPORT_SYMBOL(memset);
 EXPORT_SYMBOL(memcpy);
 EXPORT_SYMBOL(__memcpy);
+EXPORT_SYMBOL(memmove);
 
 EXPORT_SYMBOL(empty_zero_page);
 #ifndef CONFIG_PARAVIRT
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/x86_init.c linux-libre-2.6.39-gnu/arch/x86/kernel/x86_init.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/x86_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/x86_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,10 @@
 		.banner			= default_banner,
 	},
 
+	.mapping = {
+		.pagetable_reserve		= native_pagetable_reserve,
+	},
+
 	.paging = {
 		.pagetable_setup_start	= native_pagetable_setup_start,
 		.pagetable_setup_done	= native_pagetable_setup_done,
@@ -70,6 +74,7 @@
 		.setup_percpu_clockev	= setup_boot_APIC_clock,
 		.tsc_pre_init		= x86_init_noop,
 		.timer_init		= hpet_time_init,
+		.wallclock_init		= x86_init_noop,
 	},
 
 	.iommu = {
diff -druN linux-libre-2.6.38-gnu/arch/x86/kernel/xsave.c linux-libre-2.6.39-gnu/arch/x86/kernel/xsave.c
--- linux-libre-2.6.38-gnu/arch/x86/kernel/xsave.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kernel/xsave.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 
 	/*
 	 * None of the feature bits are in init state. So nothing else
-	 * to do for us, as the memory layout is upto date.
+	 * to do for us, as the memory layout is up to date.
 	 */
 	if ((xstate_bv & pcntxt_mask) == pcntxt_mask)
 		return;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/emulate.c linux-libre-2.6.39-gnu/arch/x86/kvm/emulate.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/emulate.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/emulate.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,6 +76,7 @@
 #define Group       (1<<14)     /* Bits 3:5 of modrm byte extend opcode */
 #define GroupDual   (1<<15)     /* Alternate decoding of mod == 3 */
 /* Misc flags */
+#define VendorSpecific (1<<22) /* Vendor specific instruction */
 #define NoAccess    (1<<23) /* Don't access memory (lea/invlpg/verr etc) */
 #define Op3264      (1<<24) /* Operand is 64b in long mode, 32b otherwise */
 #define Undefined   (1<<25) /* No Such Instruction */
@@ -877,7 +878,8 @@
 	if (selector & 1 << 2) {
 		struct desc_struct desc;
 		memset (dt, 0, sizeof *dt);
-		if (!ops->get_cached_descriptor(&desc, VCPU_SREG_LDTR, ctxt->vcpu))
+		if (!ops->get_cached_descriptor(&desc, NULL, VCPU_SREG_LDTR,
+						ctxt->vcpu))
 			return;
 
 		dt->size = desc_limit_scaled(&desc); /* what if limit > 65535? */
@@ -929,6 +931,7 @@
 	return ret;
 }
 
+/* Does not support long mode */
 static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt,
 				   struct x86_emulate_ops *ops,
 				   u16 selector, int seg)
@@ -1040,7 +1043,7 @@
 	}
 load:
 	ops->set_segment_selector(selector, seg, ctxt->vcpu);
-	ops->set_cached_descriptor(&seg_desc, seg, ctxt->vcpu);
+	ops->set_cached_descriptor(&seg_desc, 0, seg, ctxt->vcpu);
 	return X86EMUL_CONTINUE;
 exception:
 	emulate_exception(ctxt, err_vec, err_code, true);
@@ -1560,7 +1563,7 @@
 			struct desc_struct *ss)
 {
 	memset(cs, 0, sizeof(struct desc_struct));
-	ops->get_cached_descriptor(cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->get_cached_descriptor(cs, NULL, VCPU_SREG_CS, ctxt->vcpu);
 	memset(ss, 0, sizeof(struct desc_struct));
 
 	cs->l = 0;		/* will be adjusted later */
@@ -1607,9 +1610,9 @@
 		cs.d = 0;
 		cs.l = 1;
 	}
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	c->regs[VCPU_REGS_RCX] = c->eip;
@@ -1679,9 +1682,9 @@
 		cs.l = 1;
 	}
 
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
@@ -1736,9 +1739,9 @@
 	cs_sel |= SELECTOR_RPL_MASK;
 	ss_sel |= SELECTOR_RPL_MASK;
 
-	ops->set_cached_descriptor(&cs, VCPU_SREG_CS, ctxt->vcpu);
+	ops->set_cached_descriptor(&cs, 0, VCPU_SREG_CS, ctxt->vcpu);
 	ops->set_segment_selector(cs_sel, VCPU_SREG_CS, ctxt->vcpu);
-	ops->set_cached_descriptor(&ss, VCPU_SREG_SS, ctxt->vcpu);
+	ops->set_cached_descriptor(&ss, 0, VCPU_SREG_SS, ctxt->vcpu);
 	ops->set_segment_selector(ss_sel, VCPU_SREG_SS, ctxt->vcpu);
 
 	c->eip = c->regs[VCPU_REGS_RDX];
@@ -1764,24 +1767,28 @@
 					    u16 port, u16 len)
 {
 	struct desc_struct tr_seg;
+	u32 base3;
 	int r;
-	u16 io_bitmap_ptr;
-	u8 perm, bit_idx = port & 0x7;
+	u16 io_bitmap_ptr, perm, bit_idx = port & 0x7;
 	unsigned mask = (1 << len) - 1;
+	unsigned long base;
 
-	ops->get_cached_descriptor(&tr_seg, VCPU_SREG_TR, ctxt->vcpu);
+	ops->get_cached_descriptor(&tr_seg, &base3, VCPU_SREG_TR, ctxt->vcpu);
 	if (!tr_seg.p)
 		return false;
 	if (desc_limit_scaled(&tr_seg) < 103)
 		return false;
-	r = ops->read_std(get_desc_base(&tr_seg) + 102, &io_bitmap_ptr, 2,
-			  ctxt->vcpu, NULL);
+	base = get_desc_base(&tr_seg);
+#ifdef CONFIG_X86_64
+	base |= ((u64)base3) << 32;
+#endif
+	r = ops->read_std(base + 102, &io_bitmap_ptr, 2, ctxt->vcpu, NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
 	if (io_bitmap_ptr + port/8 > desc_limit_scaled(&tr_seg))
 		return false;
-	r = ops->read_std(get_desc_base(&tr_seg) + io_bitmap_ptr + port/8,
-			  &perm, 1, ctxt->vcpu, NULL);
+	r = ops->read_std(base + io_bitmap_ptr + port/8, &perm, 2, ctxt->vcpu,
+			  NULL);
 	if (r != X86EMUL_CONTINUE)
 		return false;
 	if ((perm >> bit_idx) & mask)
@@ -2126,7 +2133,7 @@
 	}
 
 	ops->set_cr(0,  ops->get_cr(0, ctxt->vcpu) | X86_CR0_TS, ctxt->vcpu);
-	ops->set_cached_descriptor(&next_tss_desc, VCPU_SREG_TR, ctxt->vcpu);
+	ops->set_cached_descriptor(&next_tss_desc, 0, VCPU_SREG_TR, ctxt->vcpu);
 	ops->set_segment_selector(tss_selector, VCPU_SREG_TR, ctxt->vcpu);
 
 	if (has_error_code) {
@@ -2365,7 +2372,8 @@
 	D(SrcMem16 | ModRM | Mov | Priv),
 	D(SrcMem | ModRM | ByteOp | Priv | NoAccess),
 }, {
-	D(SrcNone | ModRM | Priv), N, N, D(SrcNone | ModRM | Priv),
+	D(SrcNone | ModRM | Priv | VendorSpecific), N,
+	N, D(SrcNone | ModRM | Priv | VendorSpecific),
 	D(SrcNone | ModRM | DstMem | Mov), N,
 	D(SrcMem16 | ModRM | Mov | Priv), N,
 } };
@@ -2489,7 +2497,7 @@
 static struct opcode twobyte_table[256] = {
 	/* 0x00 - 0x0F */
 	N, GD(0, &group7), N, N,
-	N, D(ImplicitOps), D(ImplicitOps | Priv), N,
+	N, D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv), N,
 	D(ImplicitOps | Priv), D(ImplicitOps | Priv), N, N,
 	N, D(ImplicitOps | ModRM), N, N,
 	/* 0x10 - 0x1F */
@@ -2502,7 +2510,8 @@
 	/* 0x30 - 0x3F */
 	D(ImplicitOps | Priv), I(ImplicitOps, em_rdtsc),
 	D(ImplicitOps | Priv), N,
-	D(ImplicitOps), D(ImplicitOps | Priv), N, N,
+	D(ImplicitOps | VendorSpecific), D(ImplicitOps | Priv | VendorSpecific),
+	N, N,
 	N, N, N, N, N, N, N, N,
 	/* 0x40 - 0x4F */
 	X16(D(DstReg | SrcMem | ModRM | Mov)),
@@ -2741,6 +2750,9 @@
 	if (c->d == 0 || (c->d & Undefined))
 		return -1;
 
+	if (!(c->d & VendorSpecific) && ctxt->only_vendor_specific_insn)
+		return -1;
+
 	if (mode == X86EMUL_MODE_PROT64 && (c->d & Stack))
 		c->op_bytes = 8;
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/i8259.c linux-libre-2.6.39-gnu/arch/x86/kvm/i8259.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/i8259.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/i8259.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,9 +62,6 @@
 		}
 
 		if (!found)
-			found = s->kvm->bsp_vcpu;
-
-		if (!found)
 			return;
 
 		kvm_make_request(KVM_REQ_EVENT, found);
@@ -75,7 +72,6 @@
 static void pic_clear_isr(struct kvm_kpic_state *s, int irq)
 {
 	s->isr &= ~(1 << irq);
-	s->isr_ack |= (1 << irq);
 	if (s != &s->pics_state->pics[0])
 		irq += 8;
 	/*
@@ -89,16 +85,6 @@
 	pic_lock(s->pics_state);
 }
 
-void kvm_pic_clear_isr_ack(struct kvm *kvm)
-{
-	struct kvm_pic *s = pic_irqchip(kvm);
-
-	pic_lock(s);
-	s->pics[0].isr_ack = 0xff;
-	s->pics[1].isr_ack = 0xff;
-	pic_unlock(s);
-}
-
 /*
  * set irq level. If an edge is detected, then the IRR is set to 1
  */
@@ -281,7 +267,6 @@
 	s->irr = 0;
 	s->imr = 0;
 	s->isr = 0;
-	s->isr_ack = 0xff;
 	s->priority_add = 0;
 	s->irq_base = 0;
 	s->read_reg_select = 0;
@@ -545,15 +530,11 @@
  */
 static void pic_irq_request(struct kvm *kvm, int level)
 {
-	struct kvm_vcpu *vcpu = kvm->bsp_vcpu;
 	struct kvm_pic *s = pic_irqchip(kvm);
-	int irq = pic_get_irq(&s->pics[0]);
 
-	s->output = level;
-	if (vcpu && level && (s->pics[0].isr_ack & (1 << irq))) {
-		s->pics[0].isr_ack &= ~(1 << irq);
+	if (!s->output)
 		s->wakeup_needed = true;
-	}
+	s->output = level;
 }
 
 static const struct kvm_io_device_ops picdev_ops = {
@@ -575,8 +556,6 @@
 	s->pics[1].elcr_mask = 0xde;
 	s->pics[0].pics_state = s;
 	s->pics[1].pics_state = s;
-	s->pics[0].isr_ack = 0xff;
-	s->pics[1].isr_ack = 0xff;
 
 	/*
 	 * Initialize PIO device
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/lapic.c linux-libre-2.6.39-gnu/arch/x86/kvm/lapic.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/lapic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/lapic.c	2011-05-19 00:06:34.000000000 -0400
@@ -417,10 +417,6 @@
 	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",
-				       vcpu->vcpu_id);
 			vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
 			kvm_make_request(KVM_REQ_EVENT, vcpu);
 			kvm_vcpu_kick(vcpu);
@@ -875,8 +871,8 @@
 
 	hrtimer_cancel(&vcpu->arch.apic->lapic_timer.timer);
 
-	if (vcpu->arch.apic->regs_page)
-		__free_page(vcpu->arch.apic->regs_page);
+	if (vcpu->arch.apic->regs)
+		free_page((unsigned long)vcpu->arch.apic->regs);
 
 	kfree(vcpu->arch.apic);
 }
@@ -1065,13 +1061,12 @@
 
 	vcpu->arch.apic = apic;
 
-	apic->regs_page = alloc_page(GFP_KERNEL|__GFP_ZERO);
-	if (apic->regs_page == NULL) {
+	apic->regs = (void *)get_zeroed_page(GFP_KERNEL);
+	if (!apic->regs) {
 		printk(KERN_ERR "malloc apic regs error for vcpu %x\n",
 		       vcpu->vcpu_id);
 		goto nomem_free_apic;
 	}
-	apic->regs = page_address(apic->regs_page);
 	apic->vcpu = vcpu;
 
 	hrtimer_init(&apic->lapic_timer.timer, CLOCK_MONOTONIC,
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/lapic.h linux-libre-2.6.39-gnu/arch/x86/kvm/lapic.h
--- linux-libre-2.6.38-gnu/arch/x86/kvm/lapic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/lapic.h	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,6 @@
 	u32 divide_count;
 	struct kvm_vcpu *vcpu;
 	bool irr_pending;
-	struct page *regs_page;
 	void *regs;
 	gpa_t vapic_addr;
 	struct page *vapic_page;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/mmu.c linux-libre-2.6.39-gnu/arch/x86/kvm/mmu.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/mmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/mmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,9 +111,6 @@
 #define PT64_LEVEL_SHIFT(level) \
 		(PAGE_SHIFT + (level - 1) * PT64_LEVEL_BITS)
 
-#define PT64_LEVEL_MASK(level) \
-		(((1ULL << PT64_LEVEL_BITS) - 1) << PT64_LEVEL_SHIFT(level))
-
 #define PT64_INDEX(address, level)\
 	(((address) >> PT64_LEVEL_SHIFT(level)) & ((1 << PT64_LEVEL_BITS) - 1))
 
@@ -123,8 +120,6 @@
 #define PT32_LEVEL_SHIFT(level) \
 		(PAGE_SHIFT + (level - 1) * PT32_LEVEL_BITS)
 
-#define PT32_LEVEL_MASK(level) \
-		(((1ULL << PT32_LEVEL_BITS) - 1) << PT32_LEVEL_SHIFT(level))
 #define PT32_LVL_OFFSET_MASK(level) \
 	(PT32_BASE_ADDR_MASK & ((1ULL << (PAGE_SHIFT + (((level) - 1) \
 						* PT32_LEVEL_BITS))) - 1))
@@ -379,15 +374,15 @@
 static int mmu_topup_memory_cache_page(struct kvm_mmu_memory_cache *cache,
 				       int min)
 {
-	struct page *page;
+	void *page;
 
 	if (cache->nobjs >= min)
 		return 0;
 	while (cache->nobjs < ARRAY_SIZE(cache->objects)) {
-		page = alloc_page(GFP_KERNEL);
+		page = (void *)__get_free_page(GFP_KERNEL);
 		if (!page)
 			return -ENOMEM;
-		cache->objects[cache->nobjs++] = page_address(page);
+		cache->objects[cache->nobjs++] = page;
 	}
 	return 0;
 }
@@ -554,13 +549,23 @@
 	return ret;
 }
 
-static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+static struct kvm_memory_slot *
+gfn_to_memslot_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t gfn,
+			    bool no_dirty_log)
 {
 	struct kvm_memory_slot *slot;
-	slot = gfn_to_memslot(vcpu->kvm, large_gfn);
-	if (slot && slot->dirty_bitmap)
-		return true;
-	return false;
+
+	slot = gfn_to_memslot(vcpu->kvm, gfn);
+	if (!slot || slot->flags & KVM_MEMSLOT_INVALID ||
+	      (no_dirty_log && slot->dirty_bitmap))
+		slot = NULL;
+
+	return slot;
+}
+
+static bool mapping_level_dirty_bitmap(struct kvm_vcpu *vcpu, gfn_t large_gfn)
+{
+	return gfn_to_memslot_dirty_bitmap(vcpu, large_gfn, true);
 }
 
 static int mapping_level(struct kvm_vcpu *vcpu, gfn_t large_gfn)
@@ -1032,9 +1037,9 @@
 	ASSERT(is_empty_shadow_page(sp->spt));
 	hlist_del(&sp->hash_link);
 	list_del(&sp->link);
-	__free_page(virt_to_page(sp->spt));
+	free_page((unsigned long)sp->spt);
 	if (!sp->role.direct)
-		__free_page(virt_to_page(sp->gfns));
+		free_page((unsigned long)sp->gfns);
 	kmem_cache_free(mmu_page_header_cache, sp);
 	kvm_mod_used_mmu_pages(kvm, -1);
 }
@@ -1199,6 +1204,13 @@
 {
 }
 
+static void nonpaging_update_pte(struct kvm_vcpu *vcpu,
+				 struct kvm_mmu_page *sp, u64 *spte,
+				 const void *pte, unsigned long mmu_seq)
+{
+	WARN_ON(1);
+}
+
 #define KVM_PAGE_ARRAY_NR 16
 
 struct kvm_mmu_pages {
@@ -2150,26 +2162,13 @@
 {
 }
 
-static struct kvm_memory_slot *
-pte_prefetch_gfn_to_memslot(struct kvm_vcpu *vcpu, gfn_t gfn, bool no_dirty_log)
-{
-	struct kvm_memory_slot *slot;
-
-	slot = gfn_to_memslot(vcpu->kvm, gfn);
-	if (!slot || slot->flags & KVM_MEMSLOT_INVALID ||
-	      (no_dirty_log && slot->dirty_bitmap))
-		slot = NULL;
-
-	return slot;
-}
-
 static pfn_t pte_prefetch_gfn_to_pfn(struct kvm_vcpu *vcpu, gfn_t gfn,
 				     bool no_dirty_log)
 {
 	struct kvm_memory_slot *slot;
 	unsigned long hva;
 
-	slot = pte_prefetch_gfn_to_memslot(vcpu, gfn, no_dirty_log);
+	slot = gfn_to_memslot_dirty_bitmap(vcpu, gfn, no_dirty_log);
 	if (!slot) {
 		get_page(bad_page);
 		return page_to_pfn(bad_page);
@@ -2190,7 +2189,7 @@
 	gfn_t gfn;
 
 	gfn = kvm_mmu_page_get_gfn(sp, start - sp->spt);
-	if (!pte_prefetch_gfn_to_memslot(vcpu, gfn, access & ACC_WRITE_MASK))
+	if (!gfn_to_memslot_dirty_bitmap(vcpu, gfn, access & ACC_WRITE_MASK))
 		return -1;
 
 	ret = gfn_to_page_many_atomic(vcpu->kvm, gfn, pages, end - start);
@@ -2804,6 +2803,7 @@
 	context->prefetch_page = nonpaging_prefetch_page;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
+	context->update_pte = nonpaging_update_pte;
 	context->root_level = 0;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
 	context->root_hpa = INVALID_PAGE;
@@ -2933,6 +2933,7 @@
 	context->prefetch_page = paging64_prefetch_page;
 	context->sync_page = paging64_sync_page;
 	context->invlpg = paging64_invlpg;
+	context->update_pte = paging64_update_pte;
 	context->free = paging_free;
 	context->root_level = level;
 	context->shadow_root_level = level;
@@ -2961,6 +2962,7 @@
 	context->prefetch_page = paging32_prefetch_page;
 	context->sync_page = paging32_sync_page;
 	context->invlpg = paging32_invlpg;
+	context->update_pte = paging32_update_pte;
 	context->root_level = PT32_ROOT_LEVEL;
 	context->shadow_root_level = PT32E_ROOT_LEVEL;
 	context->root_hpa = INVALID_PAGE;
@@ -2985,6 +2987,7 @@
 	context->prefetch_page = nonpaging_prefetch_page;
 	context->sync_page = nonpaging_sync_page;
 	context->invlpg = nonpaging_invlpg;
+	context->update_pte = nonpaging_update_pte;
 	context->shadow_root_level = kvm_x86_ops->get_tdp_level();
 	context->root_hpa = INVALID_PAGE;
 	context->direct_map = true;
@@ -3089,8 +3092,6 @@
 
 static int init_kvm_mmu(struct kvm_vcpu *vcpu)
 {
-	vcpu->arch.update_pte.pfn = bad_pfn;
-
 	if (mmu_is_nested(vcpu))
 		return init_kvm_nested_mmu(vcpu);
 	else if (tdp_enabled)
@@ -3164,7 +3165,7 @@
 static void mmu_pte_write_new_pte(struct kvm_vcpu *vcpu,
 				  struct kvm_mmu_page *sp,
 				  u64 *spte,
-				  const void *new)
+				  const void *new, unsigned long mmu_seq)
 {
 	if (sp->role.level != PT_PAGE_TABLE_LEVEL) {
 		++vcpu->kvm->stat.mmu_pde_zapped;
@@ -3172,10 +3173,7 @@
         }
 
 	++vcpu->kvm->stat.mmu_pte_updated;
-	if (!sp->role.cr4_pae)
-		paging32_update_pte(vcpu, sp, spte, new);
-	else
-		paging64_update_pte(vcpu, sp, spte, new);
+	vcpu->arch.mmu.update_pte(vcpu, sp, spte, new, mmu_seq);
 }
 
 static bool need_remote_flush(u64 old, u64 new)
@@ -3210,28 +3208,6 @@
 	return !!(spte && (*spte & shadow_accessed_mask));
 }
 
-static void mmu_guess_page_from_pte_write(struct kvm_vcpu *vcpu, gpa_t gpa,
-					  u64 gpte)
-{
-	gfn_t gfn;
-	pfn_t pfn;
-
-	if (!is_present_gpte(gpte))
-		return;
-	gfn = (gpte & PT64_BASE_ADDR_MASK) >> PAGE_SHIFT;
-
-	vcpu->arch.update_pte.mmu_seq = vcpu->kvm->mmu_notifier_seq;
-	smp_rmb();
-	pfn = gfn_to_pfn(vcpu->kvm, gfn);
-
-	if (is_error_pfn(pfn)) {
-		kvm_release_pfn_clean(pfn);
-		return;
-	}
-	vcpu->arch.update_pte.gfn = gfn;
-	vcpu->arch.update_pte.pfn = pfn;
-}
-
 static void kvm_mmu_access_page(struct kvm_vcpu *vcpu, gfn_t gfn)
 {
 	u64 *spte = vcpu->arch.last_pte_updated;
@@ -3253,21 +3229,14 @@
 	struct kvm_mmu_page *sp;
 	struct hlist_node *node;
 	LIST_HEAD(invalid_list);
-	u64 entry, gentry;
-	u64 *spte;
-	unsigned offset = offset_in_page(gpa);
-	unsigned pte_size;
-	unsigned page_offset;
-	unsigned misaligned;
-	unsigned quadrant;
-	int level;
-	int flooded = 0;
-	int npte;
-	int r;
-	int invlpg_counter;
+	unsigned long mmu_seq;
+	u64 entry, gentry, *spte;
+	unsigned pte_size, page_offset, misaligned, quadrant, offset;
+	int level, npte, invlpg_counter, r, flooded = 0;
 	bool remote_flush, local_flush, zap_page;
 
 	zap_page = remote_flush = local_flush = false;
+	offset = offset_in_page(gpa);
 
 	pgprintk("%s: gpa %llx bytes %d\n", __func__, gpa, bytes);
 
@@ -3275,9 +3244,8 @@
 
 	/*
 	 * Assume that the pte write on a page table of the same type
-	 * as the current vcpu paging mode.  This is nearly always true
-	 * (might be false while changing modes).  Note it is verified later
-	 * by update_pte().
+	 * as the current vcpu paging mode since we update the sptes only
+	 * when they have the same mode.
 	 */
 	if ((is_pae(vcpu) && bytes == 4) || !new) {
 		/* Handle a 32-bit guest writing two halves of a 64-bit gpte */
@@ -3303,15 +3271,17 @@
 		break;
 	}
 
-	mmu_guess_page_from_pte_write(vcpu, gpa, gentry);
+	mmu_seq = vcpu->kvm->mmu_notifier_seq;
+	smp_rmb();
+
 	spin_lock(&vcpu->kvm->mmu_lock);
 	if (atomic_read(&vcpu->kvm->arch.invlpg_counter) != invlpg_counter)
 		gentry = 0;
-	kvm_mmu_access_page(vcpu, gfn);
 	kvm_mmu_free_some_pages(vcpu);
 	++vcpu->kvm->stat.mmu_pte_write;
 	trace_kvm_mmu_audit(vcpu, AUDIT_PRE_PTE_WRITE);
 	if (guest_initiated) {
+		kvm_mmu_access_page(vcpu, gfn);
 		if (gfn == vcpu->arch.last_pt_write_gfn
 		    && !last_updated_pte_accessed(vcpu)) {
 			++vcpu->arch.last_pt_write_count;
@@ -3375,7 +3345,8 @@
 			if (gentry &&
 			      !((sp->role.word ^ vcpu->arch.mmu.base_role.word)
 			      & mask.word))
-				mmu_pte_write_new_pte(vcpu, sp, spte, &gentry);
+				mmu_pte_write_new_pte(vcpu, sp, spte, &gentry,
+						      mmu_seq);
 			if (!remote_flush && need_remote_flush(entry, *spte))
 				remote_flush = true;
 			++spte;
@@ -3385,10 +3356,6 @@
 	kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
 	trace_kvm_mmu_audit(vcpu, AUDIT_POST_PTE_WRITE);
 	spin_unlock(&vcpu->kvm->mmu_lock);
-	if (!is_error_pfn(vcpu->arch.update_pte.pfn)) {
-		kvm_release_pfn_clean(vcpu->arch.update_pte.pfn);
-		vcpu->arch.update_pte.pfn = bad_pfn;
-	}
 }
 
 int kvm_mmu_unprotect_page_virt(struct kvm_vcpu *vcpu, gva_t gva)
@@ -3538,14 +3505,23 @@
 		if (!test_bit(slot, sp->slot_bitmap))
 			continue;
 
-		if (sp->role.level != PT_PAGE_TABLE_LEVEL)
-			continue;
-
 		pt = sp->spt;
-		for (i = 0; i < PT64_ENT_PER_PAGE; ++i)
+		for (i = 0; i < PT64_ENT_PER_PAGE; ++i) {
+			if (!is_shadow_present_pte(pt[i]) ||
+			      !is_last_spte(pt[i], sp->role.level))
+				continue;
+
+			if (is_large_pte(pt[i])) {
+				drop_spte(kvm, &pt[i],
+					  shadow_trap_nonpresent_pte);
+				--kvm->stat.lpages;
+				continue;
+			}
+
 			/* avoid RMW */
 			if (is_writable_pte(pt[i]))
 				update_spte(&pt[i], pt[i] & ~PT_WRITABLE_MASK);
+		}
 	}
 	kvm_flush_remote_tlbs(kvm);
 }
@@ -3583,7 +3559,7 @@
 	if (nr_to_scan == 0)
 		goto out;
 
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 
 	list_for_each_entry(kvm, &vm_list, vm_list) {
 		int idx, freed_pages;
@@ -3606,7 +3582,7 @@
 	if (kvm_freed)
 		list_move_tail(&kvm_freed->vm_list, &vm_list);
 
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 
 out:
 	return percpu_counter_read_positive(&kvm_total_used_mmu_pages);
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/paging_tmpl.h linux-libre-2.6.39-gnu/arch/x86/kvm/paging_tmpl.h
--- linux-libre-2.6.38-gnu/arch/x86/kvm/paging_tmpl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/paging_tmpl.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,6 @@
 	#define PT_LVL_ADDR_MASK(lvl) PT64_LVL_ADDR_MASK(lvl)
 	#define PT_LVL_OFFSET_MASK(lvl) PT64_LVL_OFFSET_MASK(lvl)
 	#define PT_INDEX(addr, level) PT64_INDEX(addr, level)
-	#define PT_LEVEL_MASK(level) PT64_LEVEL_MASK(level)
 	#define PT_LEVEL_BITS PT64_LEVEL_BITS
 	#ifdef CONFIG_X86_64
 	#define PT_MAX_FULL_LEVELS 4
@@ -48,7 +47,6 @@
 	#define PT_LVL_ADDR_MASK(lvl) PT32_LVL_ADDR_MASK(lvl)
 	#define PT_LVL_OFFSET_MASK(lvl) PT32_LVL_OFFSET_MASK(lvl)
 	#define PT_INDEX(addr, level) PT32_INDEX(addr, level)
-	#define PT_LEVEL_MASK(level) PT32_LEVEL_MASK(level)
 	#define PT_LEVEL_BITS PT32_LEVEL_BITS
 	#define PT_MAX_FULL_LEVELS 2
 	#define CMPXCHG cmpxchg
@@ -327,7 +325,7 @@
 }
 
 static void FNAME(update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
-			      u64 *spte, const void *pte)
+			      u64 *spte, const void *pte, unsigned long mmu_seq)
 {
 	pt_element_t gpte;
 	unsigned pte_access;
@@ -339,16 +337,16 @@
 
 	pgprintk("%s: gpte %llx spte %p\n", __func__, (u64)gpte, spte);
 	pte_access = sp->role.access & FNAME(gpte_access)(vcpu, gpte);
-	if (gpte_to_gfn(gpte) != vcpu->arch.update_pte.gfn)
-		return;
-	pfn = vcpu->arch.update_pte.pfn;
-	if (is_error_pfn(pfn))
+	pfn = gfn_to_pfn_atomic(vcpu->kvm, gpte_to_gfn(gpte));
+	if (is_error_pfn(pfn)) {
+		kvm_release_pfn_clean(pfn);
 		return;
-	if (mmu_notifier_retry(vcpu, vcpu->arch.update_pte.mmu_seq))
+	}
+	if (mmu_notifier_retry(vcpu, mmu_seq))
 		return;
-	kvm_get_pfn(pfn);
+
 	/*
-	 * we call mmu_set_spte() with host_writable = true beacuse that
+	 * we call mmu_set_spte() with host_writable = true because that
 	 * vcpu->arch.update_pte.pfn was fetched from get_user_pages(write = 1).
 	 */
 	mmu_set_spte(vcpu, spte, sp->role.access, pte_access, 0, 0,
@@ -829,7 +827,6 @@
 #undef FNAME
 #undef PT_BASE_ADDR_MASK
 #undef PT_INDEX
-#undef PT_LEVEL_MASK
 #undef PT_LVL_ADDR_MASK
 #undef PT_LVL_OFFSET_MASK
 #undef PT_LEVEL_BITS
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/svm.c linux-libre-2.6.39-gnu/arch/x86/kvm/svm.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/svm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/svm.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,6 +135,8 @@
 
 	u32 *msrpm;
 
+	ulong nmi_iret_rip;
+
 	struct nested_state nested;
 
 	bool nmi_singlestep;
@@ -1153,8 +1155,10 @@
 	wrmsrl(MSR_KERNEL_GS_BASE, current->thread.gs);
 	load_gs_index(svm->host.gs);
 #else
+#ifdef CONFIG_X86_32_LAZY_GS
 	loadsegment(gs, svm->host.gs);
 #endif
+#endif
 	for (i = 0; i < NR_HOST_SAVE_USER_MSRS; i++)
 		wrmsrl(host_save_user_msrs[i], svm->host_user_msrs[i]);
 }
@@ -2653,6 +2657,7 @@
 	++svm->vcpu.stat.nmi_window_exits;
 	clr_intercept(svm, INTERCEPT_IRET);
 	svm->vcpu.arch.hflags |= HF_IRET_MASK;
+	svm->nmi_iret_rip = kvm_rip_read(&svm->vcpu);
 	return 1;
 }
 
@@ -3474,7 +3479,12 @@
 
 	svm->int3_injected = 0;
 
-	if (svm->vcpu.arch.hflags & HF_IRET_MASK) {
+	/*
+	 * If we've made progress since setting HF_IRET_MASK, we've
+	 * executed an IRET and can allow NMI injection.
+	 */
+	if ((svm->vcpu.arch.hflags & HF_IRET_MASK)
+	    && kvm_rip_read(&svm->vcpu) != svm->nmi_iret_rip) {
 		svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
 		kvm_make_request(KVM_REQ_EVENT, &svm->vcpu);
 	}
@@ -3641,19 +3651,30 @@
 	wrmsrl(MSR_GS_BASE, svm->host.gs_base);
 #else
 	loadsegment(fs, svm->host.fs);
+#ifndef CONFIG_X86_32_LAZY_GS
+	loadsegment(gs, svm->host.gs);
+#endif
 #endif
 
 	reload_tss(vcpu);
 
 	local_irq_disable();
 
-	stgi();
-
 	vcpu->arch.cr2 = svm->vmcb->save.cr2;
 	vcpu->arch.regs[VCPU_REGS_RAX] = svm->vmcb->save.rax;
 	vcpu->arch.regs[VCPU_REGS_RSP] = svm->vmcb->save.rsp;
 	vcpu->arch.regs[VCPU_REGS_RIP] = svm->vmcb->save.rip;
 
+	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
+		kvm_before_handle_nmi(&svm->vcpu);
+
+	stgi();
+
+	/* Any pending NMI will happen here */
+
+	if (unlikely(svm->vmcb->control.exit_code == SVM_EXIT_NMI))
+		kvm_after_handle_nmi(&svm->vcpu);
+
 	sync_cr8_to_lapic(vcpu);
 
 	svm->next_rip = 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/timer.c linux-libre-2.6.39-gnu/arch/x86/kvm/timer.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/timer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/timer.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,7 +25,7 @@
 
 	/*
 	 * There is a race window between reading and incrementing, but we do
-	 * not care about potentially loosing timer events in the !reinject
+	 * not care about potentially losing timer events in the !reinject
 	 * case anyway. Note: KVM_REQ_PENDING_TIMER is implicitly checked
 	 * in vcpu_enter_guest.
 	 */
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/trace.h linux-libre-2.6.39-gnu/arch/x86/kvm/trace.h
--- linux-libre-2.6.38-gnu/arch/x86/kvm/trace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/trace.h	2011-05-19 00:06:34.000000000 -0400
@@ -62,21 +62,21 @@
 	TP_ARGS(code, fast, rep_cnt, rep_idx, ingpa, outgpa),
 
 	TP_STRUCT__entry(
-		__field(	__u16, 		code		)
-		__field(	bool,		fast		)
 		__field(	__u16,		rep_cnt		)
 		__field(	__u16,		rep_idx		)
 		__field(	__u64,		ingpa		)
 		__field(	__u64,		outgpa		)
+		__field(	__u16, 		code		)
+		__field(	bool,		fast		)
 	),
 
 	TP_fast_assign(
-		__entry->code		= code;
-		__entry->fast		= fast;
 		__entry->rep_cnt	= rep_cnt;
 		__entry->rep_idx	= rep_idx;
 		__entry->ingpa		= ingpa;
 		__entry->outgpa		= outgpa;
+		__entry->code		= code;
+		__entry->fast		= fast;
 	),
 
 	TP_printk("code 0x%x %s cnt 0x%x idx 0x%x in 0x%llx out 0x%llx",
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/vmx.c linux-libre-2.6.39-gnu/arch/x86/kvm/vmx.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/vmx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/vmx.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,14 +93,14 @@
  * These 2 parameters are used to config the controls for Pause-Loop Exiting:
  * ple_gap:    upper bound on the amount of time between two successive
  *             executions of PAUSE in a loop. Also indicate if ple enabled.
- *             According to test, this time is usually small than 41 cycles.
+ *             According to test, this time is usually smaller than 128 cycles.
  * ple_window: upper bound on the amount of time a guest is allowed to execute
  *             in a PAUSE loop. Tests indicate that most spinlocks are held for
  *             less than 2^12 cycles
  * Time is measured based on a counter that runs at the same rate as the TSC,
  * refer SDM volume 3b section 21.6.13 & 22.1.3.
  */
-#define KVM_VMX_DEFAULT_PLE_GAP    41
+#define KVM_VMX_DEFAULT_PLE_GAP    128
 #define KVM_VMX_DEFAULT_PLE_WINDOW 4096
 static int ple_gap = KVM_VMX_DEFAULT_PLE_GAP;
 module_param(ple_gap, int, S_IRUGO);
@@ -176,11 +176,11 @@
 	return container_of(vcpu, struct vcpu_vmx, vcpu);
 }
 
-static int init_rmode(struct kvm *kvm);
 static u64 construct_eptp(unsigned long root_hpa);
 static void kvm_cpu_vmxon(u64 addr);
 static void kvm_cpu_vmxoff(void);
 static void vmx_set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3);
+static int vmx_set_tss_addr(struct kvm *kvm, unsigned int addr);
 
 static DEFINE_PER_CPU(struct vmcs *, vmxarea);
 static DEFINE_PER_CPU(struct vmcs *, current_vmcs);
@@ -1333,19 +1333,25 @@
 
 	rdmsrl(MSR_IA32_FEATURE_CONTROL, msr);
 	if (msr & FEATURE_CONTROL_LOCKED) {
+		/* launched w/ TXT and VMX disabled */
 		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
 			&& tboot_enabled())
 			return 1;
+		/* launched w/o TXT and VMX only enabled w/ TXT */
 		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+			&& (msr & FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX)
 			&& !tboot_enabled()) {
 			printk(KERN_WARNING "kvm: disable TXT in the BIOS or "
-				" activate TXT before enabling KVM\n");
+				"activate TXT before enabling KVM\n");
 			return 1;
 		}
+		/* launched w/o TXT and VMX disabled */
+		if (!(msr & FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX)
+			&& !tboot_enabled())
+			return 1;
 	}
 
 	return 0;
-	/* locked but not enabled */
 }
 
 static void kvm_cpu_vmxon(u64 addr)
@@ -1683,6 +1689,7 @@
 	vmx->emulation_required = 1;
 	vmx->rmode.vm86_active = 0;
 
+	vmcs_write16(GUEST_TR_SELECTOR, vmx->rmode.tr.selector);
 	vmcs_writel(GUEST_TR_BASE, vmx->rmode.tr.base);
 	vmcs_write32(GUEST_TR_LIMIT, vmx->rmode.tr.limit);
 	vmcs_write32(GUEST_TR_AR_BYTES, vmx->rmode.tr.ar);
@@ -1756,6 +1763,19 @@
 	vmx->emulation_required = 1;
 	vmx->rmode.vm86_active = 1;
 
+	/*
+	 * Very old userspace does not call KVM_SET_TSS_ADDR before entering
+	 * vcpu. Call it here with phys address pointing 16M below 4G.
+	 */
+	if (!vcpu->kvm->arch.tss_addr) {
+		printk_once(KERN_WARNING "kvm: KVM_SET_TSS_ADDR need to be "
+			     "called before entering vcpu\n");
+		srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
+		vmx_set_tss_addr(vcpu->kvm, 0xfeffd000);
+		vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
+	}
+
+	vmx->rmode.tr.selector = vmcs_read16(GUEST_TR_SELECTOR);
 	vmx->rmode.tr.base = vmcs_readl(GUEST_TR_BASE);
 	vmcs_writel(GUEST_TR_BASE, rmode_tss_base(vcpu->kvm));
 
@@ -1794,7 +1814,6 @@
 
 continue_rmode:
 	kvm_mmu_reset_context(vcpu);
-	init_rmode(vcpu->kvm);
 }
 
 static void vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer)
@@ -2030,23 +2049,40 @@
 	vmcs_writel(GUEST_CR4, hw_cr4);
 }
 
-static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
-{
-	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
-
-	return vmcs_readl(sf->base);
-}
-
 static void vmx_get_segment(struct kvm_vcpu *vcpu,
 			    struct kvm_segment *var, int seg)
 {
+	struct vcpu_vmx *vmx = to_vmx(vcpu);
 	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	struct kvm_save_segment *save;
 	u32 ar;
 
+	if (vmx->rmode.vm86_active
+	    && (seg == VCPU_SREG_TR || seg == VCPU_SREG_ES
+		|| seg == VCPU_SREG_DS || seg == VCPU_SREG_FS
+		|| seg == VCPU_SREG_GS)
+	    && !emulate_invalid_guest_state) {
+		switch (seg) {
+		case VCPU_SREG_TR: save = &vmx->rmode.tr; break;
+		case VCPU_SREG_ES: save = &vmx->rmode.es; break;
+		case VCPU_SREG_DS: save = &vmx->rmode.ds; break;
+		case VCPU_SREG_FS: save = &vmx->rmode.fs; break;
+		case VCPU_SREG_GS: save = &vmx->rmode.gs; break;
+		default: BUG();
+		}
+		var->selector = save->selector;
+		var->base = save->base;
+		var->limit = save->limit;
+		ar = save->ar;
+		if (seg == VCPU_SREG_TR
+		    || var->selector == vmcs_read16(sf->selector))
+			goto use_saved_rmode_seg;
+	}
 	var->base = vmcs_readl(sf->base);
 	var->limit = vmcs_read32(sf->limit);
 	var->selector = vmcs_read16(sf->selector);
 	ar = vmcs_read32(sf->ar_bytes);
+use_saved_rmode_seg:
 	if ((ar & AR_UNUSABLE_MASK) && !emulate_invalid_guest_state)
 		ar = 0;
 	var->type = ar & 15;
@@ -2060,6 +2096,18 @@
 	var->unusable = (ar >> 16) & 1;
 }
 
+static u64 vmx_get_segment_base(struct kvm_vcpu *vcpu, int seg)
+{
+	struct kvm_vmx_segment_field *sf = &kvm_vmx_segment_fields[seg];
+	struct kvm_segment s;
+
+	if (to_vmx(vcpu)->rmode.vm86_active) {
+		vmx_get_segment(vcpu, &s, seg);
+		return s.base;
+	}
+	return vmcs_readl(sf->base);
+}
+
 static int vmx_get_cpl(struct kvm_vcpu *vcpu)
 {
 	if (!is_protmode(vcpu))
@@ -2101,6 +2149,7 @@
 	u32 ar;
 
 	if (vmx->rmode.vm86_active && seg == VCPU_SREG_TR) {
+		vmcs_write16(sf->selector, var->selector);
 		vmx->rmode.tr.selector = var->selector;
 		vmx->rmode.tr.base = var->base;
 		vmx->rmode.tr.limit = var->limit;
@@ -2361,11 +2410,12 @@
 
 static int init_rmode_tss(struct kvm *kvm)
 {
-	gfn_t fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
+	gfn_t fn;
 	u16 data = 0;
-	int ret = 0;
-	int r;
+	int r, idx, ret = 0;
 
+	idx = srcu_read_lock(&kvm->srcu);
+	fn = rmode_tss_base(kvm) >> PAGE_SHIFT;
 	r = kvm_clear_guest_page(kvm, fn, 0, PAGE_SIZE);
 	if (r < 0)
 		goto out;
@@ -2389,12 +2439,13 @@
 
 	ret = 1;
 out:
+	srcu_read_unlock(&kvm->srcu, idx);
 	return ret;
 }
 
 static int init_rmode_identity_map(struct kvm *kvm)
 {
-	int i, r, ret;
+	int i, idx, r, ret;
 	pfn_t identity_map_pfn;
 	u32 tmp;
 
@@ -2409,6 +2460,7 @@
 		return 1;
 	ret = 0;
 	identity_map_pfn = kvm->arch.ept_identity_map_addr >> PAGE_SHIFT;
+	idx = srcu_read_lock(&kvm->srcu);
 	r = kvm_clear_guest_page(kvm, identity_map_pfn, 0, PAGE_SIZE);
 	if (r < 0)
 		goto out;
@@ -2424,6 +2476,7 @@
 	kvm->arch.ept_identity_pagetable_done = true;
 	ret = 1;
 out:
+	srcu_read_unlock(&kvm->srcu, idx);
 	return ret;
 }
 
@@ -2699,22 +2752,6 @@
 	return 0;
 }
 
-static int init_rmode(struct kvm *kvm)
-{
-	int idx, ret = 0;
-
-	idx = srcu_read_lock(&kvm->srcu);
-	if (!init_rmode_tss(kvm))
-		goto exit;
-	if (!init_rmode_identity_map(kvm))
-		goto exit;
-
-	ret = 1;
-exit:
-	srcu_read_unlock(&kvm->srcu, idx);
-	return ret;
-}
-
 static int vmx_vcpu_reset(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
@@ -2722,10 +2759,6 @@
 	int ret;
 
 	vcpu->arch.regs_avail = ~((1 << VCPU_REGS_RIP) | (1 << VCPU_REGS_RSP));
-	if (!init_rmode(vmx->vcpu.kvm)) {
-		ret = -ENOMEM;
-		goto out;
-	}
 
 	vmx->rmode.vm86_active = 0;
 
@@ -2805,7 +2838,7 @@
 		vmcs_write64(VIRTUAL_APIC_PAGE_ADDR, 0);
 		if (vm_need_tpr_shadow(vmx->vcpu.kvm))
 			vmcs_write64(VIRTUAL_APIC_PAGE_ADDR,
-				page_to_phys(vmx->vcpu.arch.apic->regs_page));
+				     __pa(vmx->vcpu.arch.apic->regs));
 		vmcs_write32(TPR_THRESHOLD, 0);
 	}
 
@@ -2971,6 +3004,9 @@
 	if (ret)
 		return ret;
 	kvm->arch.tss_addr = addr;
+	if (!init_rmode_tss(kvm))
+		return  -ENOMEM;
+
 	return 0;
 }
 
@@ -3962,7 +3998,7 @@
 #define Q "l"
 #endif
 
-static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+static void __noclone vmx_vcpu_run(struct kvm_vcpu *vcpu)
 {
 	struct vcpu_vmx *vmx = to_vmx(vcpu);
 
@@ -3991,6 +4027,7 @@
 	asm(
 		/* Store host registers */
 		"push %%"R"dx; push %%"R"bp;"
+		"push %%"R"cx \n\t" /* placeholder for guest rcx */
 		"push %%"R"cx \n\t"
 		"cmp %%"R"sp, %c[host_rsp](%0) \n\t"
 		"je 1f \n\t"
@@ -4032,10 +4069,11 @@
 		".Llaunched: " __ex(ASM_VMX_VMRESUME) "\n\t"
 		".Lkvm_vmx_return: "
 		/* Save guest registers, load host registers, keep flags */
-		"xchg %0,     (%%"R"sp) \n\t"
+		"mov %0, %c[wordsize](%%"R"sp) \n\t"
+		"pop %0 \n\t"
 		"mov %%"R"ax, %c[rax](%0) \n\t"
 		"mov %%"R"bx, %c[rbx](%0) \n\t"
-		"push"Q" (%%"R"sp); pop"Q" %c[rcx](%0) \n\t"
+		"pop"Q" %c[rcx](%0) \n\t"
 		"mov %%"R"dx, %c[rdx](%0) \n\t"
 		"mov %%"R"si, %c[rsi](%0) \n\t"
 		"mov %%"R"di, %c[rdi](%0) \n\t"
@@ -4053,7 +4091,7 @@
 		"mov %%cr2, %%"R"ax   \n\t"
 		"mov %%"R"ax, %c[cr2](%0) \n\t"
 
-		"pop  %%"R"bp; pop  %%"R"bp; pop  %%"R"dx \n\t"
+		"pop  %%"R"bp; pop  %%"R"dx \n\t"
 		"setbe %c[fail](%0) \n\t"
 	      : : "c"(vmx), "d"((unsigned long)HOST_RSP),
 		[launched]"i"(offsetof(struct vcpu_vmx, launched)),
@@ -4076,7 +4114,8 @@
 		[r14]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R14])),
 		[r15]"i"(offsetof(struct vcpu_vmx, vcpu.arch.regs[VCPU_REGS_R15])),
 #endif
-		[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2))
+		[cr2]"i"(offsetof(struct vcpu_vmx, vcpu.arch.cr2)),
+		[wordsize]"i"(sizeof(ulong))
 	      : "cc", "memory"
 		, R"ax", R"bx", R"di", R"si"
 #ifdef CONFIG_X86_64
@@ -4183,8 +4222,11 @@
 		if (!kvm->arch.ept_identity_map_addr)
 			kvm->arch.ept_identity_map_addr =
 				VMX_EPT_IDENTITY_PAGETABLE_ADDR;
+		err = -ENOMEM;
 		if (alloc_identity_pagetable(kvm) != 0)
 			goto free_vmcs;
+		if (!init_rmode_identity_map(kvm))
+			goto free_vmcs;
 	}
 
 	return &vmx->vcpu;
diff -druN linux-libre-2.6.38-gnu/arch/x86/kvm/x86.c linux-libre-2.6.39-gnu/arch/x86/kvm/x86.c
--- linux-libre-2.6.38-gnu/arch/x86/kvm/x86.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/kvm/x86.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,9 +81,10 @@
  * - enable LME and LMA per default on 64 bit KVM
  */
 #ifdef CONFIG_X86_64
-static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffafeULL;
+static
+u64 __read_mostly efer_reserved_bits = ~((u64)(EFER_SCE | EFER_LME | EFER_LMA));
 #else
-static u64 __read_mostly efer_reserved_bits = 0xfffffffffffffffeULL;
+static u64 __read_mostly efer_reserved_bits = ~((u64)EFER_SCE);
 #endif
 
 #define VM_STAT(x) offsetof(struct kvm, stat.x), KVM_STAT_VM
@@ -360,8 +361,8 @@
 
 void kvm_inject_nmi(struct kvm_vcpu *vcpu)
 {
+	kvm_make_request(KVM_REQ_NMI, vcpu);
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
-	vcpu->arch.nmi_pending = 1;
 }
 EXPORT_SYMBOL_GPL(kvm_inject_nmi);
 
@@ -525,8 +526,10 @@
 
 	kvm_x86_ops->set_cr0(vcpu, cr0);
 
-	if ((cr0 ^ old_cr0) & X86_CR0_PG)
+	if ((cr0 ^ old_cr0) & X86_CR0_PG) {
 		kvm_clear_async_pf_completion_queue(vcpu);
+		kvm_async_pf_hash_reset(vcpu);
+	}
 
 	if ((cr0 ^ old_cr0) & update_bits)
 		kvm_mmu_reset_context(vcpu);
@@ -1017,7 +1020,7 @@
 	unsigned long flags;
 	s64 sdiff;
 
-	spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
+	raw_spin_lock_irqsave(&kvm->arch.tsc_write_lock, flags);
 	offset = data - native_read_tsc();
 	ns = get_kernel_ns();
 	elapsed = ns - kvm->arch.last_tsc_nsec;
@@ -1028,7 +1031,7 @@
 	/*
 	 * Special case: close write to TSC within 5 seconds of
 	 * another CPU is interpreted as an attempt to synchronize
-	 * The 5 seconds is to accomodate host load / swapping as
+	 * The 5 seconds is to accommodate host load / swapping as
 	 * well as any reset of TSC during the boot process.
 	 *
 	 * In that case, for a reliable TSC, we can match TSC offsets,
@@ -1050,7 +1053,7 @@
 	kvm->arch.last_tsc_write = data;
 	kvm->arch.last_tsc_offset = offset;
 	kvm_x86_ops->write_tsc_offset(vcpu, offset);
-	spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
+	raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags);
 
 	/* Reset of TSC must disable overshoot protection below */
 	vcpu->arch.hv_clock.tsc_timestamp = 0;
@@ -1453,6 +1456,14 @@
 	return 0;
 }
 
+static void kvmclock_reset(struct kvm_vcpu *vcpu)
+{
+	if (vcpu->arch.time_page) {
+		kvm_release_page_dirty(vcpu->arch.time_page);
+		vcpu->arch.time_page = NULL;
+	}
+}
+
 int kvm_set_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 data)
 {
 	switch (msr) {
@@ -1510,10 +1521,7 @@
 		break;
 	case MSR_KVM_SYSTEM_TIME_NEW:
 	case MSR_KVM_SYSTEM_TIME: {
-		if (vcpu->arch.time_page) {
-			kvm_release_page_dirty(vcpu->arch.time_page);
-			vcpu->arch.time_page = NULL;
-		}
+		kvmclock_reset(vcpu);
 
 		vcpu->arch.time = data;
 		kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
@@ -1592,6 +1600,12 @@
 		} else
 			return set_msr_hyperv(vcpu, msr, data);
 		break;
+	case MSR_IA32_BBL_CR_CTL3:
+		/* Drop writes to this legacy MSR -- see rdmsr
+		 * counterpart for further detail.
+		 */
+		pr_unimpl(vcpu, "ignored wrmsr: 0x%x data %llx\n", msr, data);
+		break;
 	default:
 		if (msr && (msr == vcpu->kvm->arch.xen_hvm_config.msr))
 			return xen_hvm_config(vcpu, data);
@@ -1846,6 +1860,19 @@
 		} else
 			return get_msr_hyperv(vcpu, msr, pdata);
 		break;
+	case MSR_IA32_BBL_CR_CTL3:
+		/* This legacy MSR exists but isn't fully documented in current
+		 * silicon.  It is however accessed by winxp in very narrow
+		 * scenarios where it sets bit #19, itself documented as
+		 * a "reserved" bit.  Best effort attempt to source coherent
+		 * read data here should the balance of the register be
+		 * interpreted by the guest:
+		 *
+		 * L2 cache control register 3: 64GB range, 256KB size,
+		 * enabled, latency 0x1, configured
+		 */
+		data = 0xbe702111;
+		break;
 	default:
 		if (!ignore_msrs) {
 			pr_unimpl(vcpu, "unhandled rdmsr: 0x%x\n", msr);
@@ -2100,8 +2127,8 @@
 		if (check_tsc_unstable()) {
 			kvm_x86_ops->adjust_tsc_offset(vcpu, -tsc_delta);
 			vcpu->arch.tsc_catchup = 1;
-			kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 		}
+		kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu);
 		if (vcpu->cpu != cpu)
 			kvm_migrate_timers(vcpu);
 		vcpu->cpu = cpu;
@@ -2368,9 +2395,9 @@
 		int i;
 
 		entry->flags |= KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
-		for (i = 1; *nent < maxnent; ++i) {
-			if (entry[i - 1].eax == 0 && i != 2)
-				break;
+		for (i = 1; *nent < maxnent && i < 64; ++i) {
+			if (entry[i].eax == 0)
+				continue;
 			do_cpuid_1_ent(&entry[i], function, i);
 			entry[i].flags |=
 			       KVM_CPUID_FLAG_SIGNIFCANT_INDEX;
@@ -2575,9 +2602,6 @@
 	if (mce->status & MCI_STATUS_UC) {
 		if ((vcpu->arch.mcg_status & MCG_STATUS_MCIP) ||
 		    !kvm_read_cr4_bits(vcpu, X86_CR4_MCE)) {
-			printk(KERN_DEBUG "kvm: set_mce: "
-			       "injects mce exception while "
-			       "previous one is in progress!\n");
 			kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
 			return 0;
 		}
@@ -2648,8 +2672,6 @@
 	vcpu->arch.interrupt.pending = events->interrupt.injected;
 	vcpu->arch.interrupt.nr = events->interrupt.nr;
 	vcpu->arch.interrupt.soft = events->interrupt.soft;
-	if (vcpu->arch.interrupt.pending && irqchip_in_kernel(vcpu->kvm))
-		kvm_pic_clear_isr_ack(vcpu->kvm);
 	if (events->flags & KVM_VCPUEVENT_VALID_SHADOW)
 		kvm_x86_ops->set_interrupt_shadow(vcpu,
 						  events->interrupt.shadow);
@@ -4140,8 +4162,8 @@
 	return get_segment_base(vcpu, seg);
 }
 
-static bool emulator_get_cached_descriptor(struct desc_struct *desc, int seg,
-					   struct kvm_vcpu *vcpu)
+static bool emulator_get_cached_descriptor(struct desc_struct *desc, u32 *base3,
+					   int seg, struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment var;
 
@@ -4154,6 +4176,10 @@
 		var.limit >>= 12;
 	set_desc_limit(desc, var.limit);
 	set_desc_base(desc, (unsigned long)var.base);
+#ifdef CONFIG_X86_64
+	if (base3)
+		*base3 = var.base >> 32;
+#endif
 	desc->type = var.type;
 	desc->s = var.s;
 	desc->dpl = var.dpl;
@@ -4166,8 +4192,8 @@
 	return true;
 }
 
-static void emulator_set_cached_descriptor(struct desc_struct *desc, int seg,
-					   struct kvm_vcpu *vcpu)
+static void emulator_set_cached_descriptor(struct desc_struct *desc, u32 base3,
+					   int seg, struct kvm_vcpu *vcpu)
 {
 	struct kvm_segment var;
 
@@ -4175,6 +4201,9 @@
 	kvm_get_segment(vcpu, &var, seg);
 
 	var.base = get_desc_base(desc);
+#ifdef CONFIG_X86_64
+	var.base |= ((u64)base3) << 32;
+#endif
 	var.limit = get_desc_limit(desc);
 	if (desc->g)
 		var.limit = (var.limit << 12) | 0xfff;
@@ -4390,41 +4419,16 @@
 		vcpu->arch.emulate_ctxt.have_exception = false;
 		vcpu->arch.emulate_ctxt.perm_ok = false;
 
+		vcpu->arch.emulate_ctxt.only_vendor_specific_insn
+			= emulation_type & EMULTYPE_TRAP_UD;
+
 		r = x86_decode_insn(&vcpu->arch.emulate_ctxt, insn, insn_len);
-		if (r == X86EMUL_PROPAGATE_FAULT)
-			goto done;
 
 		trace_kvm_emulate_insn_start(vcpu);
-
-		/* Only allow emulation of specific instructions on #UD
-		 * (namely VMMCALL, sysenter, sysexit, syscall)*/
-		if (emulation_type & EMULTYPE_TRAP_UD) {
-			if (!c->twobyte)
-				return EMULATE_FAIL;
-			switch (c->b) {
-			case 0x01: /* VMMCALL */
-				if (c->modrm_mod != 3 || c->modrm_rm != 1)
-					return EMULATE_FAIL;
-				break;
-			case 0x34: /* sysenter */
-			case 0x35: /* sysexit */
-				if (c->modrm_mod != 0 || c->modrm_rm != 0)
-					return EMULATE_FAIL;
-				break;
-			case 0x05: /* syscall */
-				if (c->modrm_mod != 0 || c->modrm_rm != 0)
-					return EMULATE_FAIL;
-				break;
-			default:
-				return EMULATE_FAIL;
-			}
-
-			if (!(c->modrm_reg == 0 || c->modrm_reg == 3))
-				return EMULATE_FAIL;
-		}
-
 		++vcpu->stat.insn_emulation;
 		if (r)  {
+			if (emulation_type & EMULTYPE_TRAP_UD)
+				return EMULATE_FAIL;
 			if (reexecute_instruction(vcpu, cr2))
 				return EMULATE_DONE;
 			if (emulation_type & EMULTYPE_SKIP)
@@ -4452,7 +4456,6 @@
 		return handle_emulation_failure(vcpu);
 	}
 
-done:
 	if (vcpu->arch.emulate_ctxt.have_exception) {
 		inject_emulated_exception(vcpu);
 		r = EMULATE_DONE;
@@ -4562,7 +4565,7 @@
 
 	smp_call_function_single(freq->cpu, tsc_khz_changed, freq, 1);
 
-	spin_lock(&kvm_lock);
+	raw_spin_lock(&kvm_lock);
 	list_for_each_entry(kvm, &vm_list, vm_list) {
 		kvm_for_each_vcpu(i, vcpu, kvm) {
 			if (vcpu->cpu != freq->cpu)
@@ -4572,7 +4575,7 @@
 				send_ipi = 1;
 		}
 	}
-	spin_unlock(&kvm_lock);
+	raw_spin_unlock(&kvm_lock);
 
 	if (freq->old < freq->new && send_ipi) {
 		/*
@@ -4955,12 +4958,6 @@
 			best = e;
 			break;
 		}
-		/*
-		 * Both basic or both extended?
-		 */
-		if (((e->function ^ function) & 0x80000000) == 0)
-			if (!best || e->function > best->function)
-				best = e;
 	}
 	return best;
 }
@@ -4980,6 +4977,27 @@
 	return 36;
 }
 
+/*
+ * If no match is found, check whether we exceed the vCPU's limit
+ * and return the content of the highest valid _standard_ leaf instead.
+ * This is to satisfy the CPUID specification.
+ */
+static struct kvm_cpuid_entry2* check_cpuid_limit(struct kvm_vcpu *vcpu,
+                                                  u32 function, u32 index)
+{
+	struct kvm_cpuid_entry2 *maxlevel;
+
+	maxlevel = kvm_find_cpuid_entry(vcpu, function & 0x80000000, 0);
+	if (!maxlevel || maxlevel->eax >= function)
+		return NULL;
+	if (function & 0x80000000) {
+		maxlevel = kvm_find_cpuid_entry(vcpu, 0, 0);
+		if (!maxlevel)
+			return NULL;
+	}
+	return kvm_find_cpuid_entry(vcpu, maxlevel->eax, index);
+}
+
 void kvm_emulate_cpuid(struct kvm_vcpu *vcpu)
 {
 	u32 function, index;
@@ -4992,6 +5010,10 @@
 	kvm_register_write(vcpu, VCPU_REGS_RCX, 0);
 	kvm_register_write(vcpu, VCPU_REGS_RDX, 0);
 	best = kvm_find_cpuid_entry(vcpu, function, index);
+
+	if (!best)
+		best = check_cpuid_limit(vcpu, function, index);
+
 	if (best) {
 		kvm_register_write(vcpu, VCPU_REGS_RAX, best->eax);
 		kvm_register_write(vcpu, VCPU_REGS_RBX, best->ebx);
@@ -5185,6 +5207,8 @@
 			r = 1;
 			goto out;
 		}
+		if (kvm_check_request(KVM_REQ_NMI, vcpu))
+			vcpu->arch.nmi_pending = true;
 	}
 
 	r = kvm_mmu_reload(vcpu);
@@ -5213,14 +5237,18 @@
 		kvm_load_guest_fpu(vcpu);
 	kvm_load_guest_xcr0(vcpu);
 
-	atomic_set(&vcpu->guest_mode, 1);
-	smp_wmb();
+	vcpu->mode = IN_GUEST_MODE;
+
+	/* We should set ->mode before check ->requests,
+	 * see the comment in make_all_cpus_request.
+	 */
+	smp_mb();
 
 	local_irq_disable();
 
-	if (!atomic_read(&vcpu->guest_mode) || vcpu->requests
+	if (vcpu->mode == EXITING_GUEST_MODE || vcpu->requests
 	    || need_resched() || signal_pending(current)) {
-		atomic_set(&vcpu->guest_mode, 0);
+		vcpu->mode = OUTSIDE_GUEST_MODE;
 		smp_wmb();
 		local_irq_enable();
 		preempt_enable();
@@ -5256,7 +5284,7 @@
 
 	kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
 
-	atomic_set(&vcpu->guest_mode, 0);
+	vcpu->mode = OUTSIDE_GUEST_MODE;
 	smp_wmb();
 	local_irq_enable();
 
@@ -5574,7 +5602,7 @@
 				  struct kvm_sregs *sregs)
 {
 	int mmu_reset_needed = 0;
-	int pending_vec, max_bits;
+	int pending_vec, max_bits, idx;
 	struct desc_ptr dt;
 
 	dt.size = sregs->idt.limit;
@@ -5603,10 +5631,13 @@
 	kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
 	if (sregs->cr4 & X86_CR4_OSXSAVE)
 		update_cpuid(vcpu);
+
+	idx = srcu_read_lock(&vcpu->kvm->srcu);
 	if (!is_long_mode(vcpu) && is_pae(vcpu)) {
 		load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
 		mmu_reset_needed = 1;
 	}
+	srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
 	if (mmu_reset_needed)
 		kvm_mmu_reset_context(vcpu);
@@ -5617,8 +5648,6 @@
 	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);
@@ -5814,10 +5843,7 @@
 
 void kvm_arch_vcpu_free(struct kvm_vcpu *vcpu)
 {
-	if (vcpu->arch.time_page) {
-		kvm_release_page_dirty(vcpu->arch.time_page);
-		vcpu->arch.time_page = NULL;
-	}
+	kvmclock_reset(vcpu);
 
 	free_cpumask_var(vcpu->arch.wbinvd_dirty_mask);
 	fx_free(vcpu);
@@ -5878,6 +5904,8 @@
 	kvm_make_request(KVM_REQ_EVENT, vcpu);
 	vcpu->arch.apf.msr_val = 0;
 
+	kvmclock_reset(vcpu);
+
 	kvm_clear_async_pf_completion_queue(vcpu);
 	kvm_async_pf_hash_reset(vcpu);
 	vcpu->arch.apf.halted = false;
@@ -6005,7 +6033,7 @@
 	/* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
 	set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
 
-	spin_lock_init(&kvm->arch.tsc_write_lock);
+	raw_spin_lock_init(&kvm->arch.tsc_write_lock);
 
 	return 0;
 }
@@ -6103,7 +6131,7 @@
 				int user_alloc)
 {
 
-	int npages = mem->memory_size >> PAGE_SHIFT;
+	int nr_mmu_pages = 0, npages = mem->memory_size >> PAGE_SHIFT;
 
 	if (!user_alloc && !old.user_alloc && old.rmap && !npages) {
 		int ret;
@@ -6118,12 +6146,12 @@
 			       "failed to munmap memory\n");
 	}
 
+	if (!kvm->arch.n_requested_mmu_pages)
+		nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
+
 	spin_lock(&kvm->mmu_lock);
-	if (!kvm->arch.n_requested_mmu_pages) {
-		unsigned int nr_mmu_pages = kvm_mmu_calculate_mmu_pages(kvm);
+	if (nr_mmu_pages)
 		kvm_mmu_change_mmu_pages(kvm, nr_mmu_pages);
-	}
-
 	kvm_mmu_slot_remove_write_access(kvm, mem->slot);
 	spin_unlock(&kvm->mmu_lock);
 }
@@ -6157,7 +6185,7 @@
 
 	me = get_cpu();
 	if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu))
-		if (atomic_xchg(&vcpu->guest_mode, 0))
+		if (kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE)
 			smp_send_reschedule(cpu);
 	put_cpu();
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/lguest/boot.c linux-libre-2.6.39-gnu/arch/x86/lguest/boot.c
--- linux-libre-2.6.38-gnu/arch/x86/lguest/boot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lguest/boot.c	2011-05-19 00:06:34.000000000 -0400
@@ -397,7 +397,7 @@
  * instead we just use the real "cpuid" instruction.  Then I pretty much turned
  * off feature bits until the Guest booted.  (Don't say that: you'll damage
  * lguest sales!)  Shut up, inner voice!  (Hey, just pointing out that this is
- * hardly future proof.)  Noone's listening!  They don't like you anyway,
+ * hardly future proof.)  No one's listening!  They don't like you anyway,
  * parenthetic weirdo!
  *
  * Replacing the cpuid so we can turn features off is great for the kernel, but
@@ -847,7 +847,7 @@
 void lguest_setup_irq(unsigned int irq)
 {
 	irq_alloc_desc_at(irq, 0);
-	set_irq_chip_and_handler_name(irq, &lguest_irq_controller,
+	irq_set_chip_and_handler_name(irq, &lguest_irq_controller,
 				      handle_level_irq, "level");
 }
 
@@ -995,7 +995,7 @@
 static void lguest_time_init(void)
 {
 	/* Set up the timer interrupt (0) to go to our simple timer routine */
-	set_irq_handler(0, lguest_time_irq);
+	irq_set_handler(0, lguest_time_irq);
 
 	clocksource_register(&lguest_clock);
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/atomic64_386_32.S linux-libre-2.6.39-gnu/arch/x86/lib/atomic64_386_32.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/atomic64_386_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/atomic64_386_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -15,14 +15,12 @@
 
 /* if you want SMP support, implement these with real spinlocks */
 .macro LOCK reg
-	pushfl
-	CFI_ADJUST_CFA_OFFSET 4
+	pushfl_cfi
 	cli
 .endm
 
 .macro UNLOCK reg
-	popfl
-	CFI_ADJUST_CFA_OFFSET -4
+	popfl_cfi
 .endm
 
 #define BEGIN(op) \
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/atomic64_cx8_32.S linux-libre-2.6.39-gnu/arch/x86/lib/atomic64_cx8_32.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/atomic64_cx8_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/atomic64_cx8_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -14,14 +14,12 @@
 #include <asm/dwarf2.h>
 
 .macro SAVE reg
-	pushl %\reg
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %\reg
 	CFI_REL_OFFSET \reg, 0
 .endm
 
 .macro RESTORE reg
-	popl %\reg
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %\reg
 	CFI_RESTORE \reg
 .endm
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/checksum_32.S linux-libre-2.6.39-gnu/arch/x86/lib/checksum_32.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/checksum_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/checksum_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -50,11 +50,9 @@
 	   */		
 ENTRY(csum_partial)
 	CFI_STARTPROC
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl 20(%esp),%eax	# Function arg: unsigned int sum
 	movl 16(%esp),%ecx	# Function arg: int len
@@ -132,11 +130,9 @@
 	jz 8f
 	roll $8, %eax
 8:
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
 	ret
 	CFI_ENDPROC
@@ -148,11 +144,9 @@
 
 ENTRY(csum_partial)
 	CFI_STARTPROC
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl 20(%esp),%eax	# Function arg: unsigned int sum
 	movl 16(%esp),%ecx	# Function arg: int len
@@ -260,11 +254,9 @@
 	jz 90f
 	roll $8, %eax
 90: 
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
 	ret
 	CFI_ENDPROC
@@ -309,14 +301,11 @@
 	CFI_STARTPROC
 	subl  $4,%esp	
 	CFI_ADJUST_CFA_OFFSET 4
-	pushl %edi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edi
 	CFI_REL_OFFSET edi, 0
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
 	movl ARGBASE+16(%esp),%eax	# sum
 	movl ARGBASE+12(%esp),%ecx	# len
@@ -426,17 +415,13 @@
 
 .previous
 
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
-	popl %edi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edi
 	CFI_RESTORE edi
-	popl %ecx			# equivalent to addl $4,%esp
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx			# equivalent to addl $4,%esp
 	ret	
 	CFI_ENDPROC
 ENDPROC(csum_partial_copy_generic)
@@ -459,14 +444,11 @@
 		
 ENTRY(csum_partial_copy_generic)
 	CFI_STARTPROC
-	pushl %ebx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ebx
 	CFI_REL_OFFSET ebx, 0
-	pushl %edi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edi
 	CFI_REL_OFFSET edi, 0
-	pushl %esi
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %esi
 	CFI_REL_OFFSET esi, 0
 	movl ARGBASE+4(%esp),%esi	#src
 	movl ARGBASE+8(%esp),%edi	#dst	
@@ -527,14 +509,11 @@
 	jmp  7b			
 .previous				
 
-	popl %esi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %esi
 	CFI_RESTORE esi
-	popl %edi
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edi
 	CFI_RESTORE edi
-	popl %ebx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ebx
 	CFI_RESTORE ebx
 	ret
 	CFI_ENDPROC
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/cmpxchg16b_emu.S linux-libre-2.6.39-gnu/arch/x86/lib/cmpxchg16b_emu.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/cmpxchg16b_emu.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/lib/cmpxchg16b_emu.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,65 @@
+/*
+ *	This program is free software; 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/linkage.h>
+#include <asm/alternative-asm.h>
+#include <asm/frame.h>
+#include <asm/dwarf2.h>
+
+#ifdef CONFIG_SMP
+#define SEG_PREFIX %gs:
+#else
+#define SEG_PREFIX
+#endif
+
+.text
+
+/*
+ * Inputs:
+ * %rsi : memory location to compare
+ * %rax : low 64 bits of old value
+ * %rdx : high 64 bits of old value
+ * %rbx : low 64 bits of new value
+ * %rcx : high 64 bits of new value
+ * %al  : Operation successful
+ */
+ENTRY(this_cpu_cmpxchg16b_emu)
+CFI_STARTPROC
+
+#
+# Emulate 'cmpxchg16b %gs:(%rsi)' except we return the result in %al not
+# via the ZF.  Caller will access %al to get result.
+#
+# Note that this is only useful for a cpuops operation.  Meaning that we
+# do *not* have a fully atomic operation but just an operation that is
+# *atomic* on a single cpu (as provided by the this_cpu_xx class of
+# macros).
+#
+this_cpu_cmpxchg16b_emu:
+	pushf
+	cli
+
+	cmpq SEG_PREFIX(%rsi), %rax
+	jne not_same
+	cmpq SEG_PREFIX 8(%rsi), %rdx
+	jne not_same
+
+	movq %rbx, SEG_PREFIX(%rsi)
+	movq %rcx, SEG_PREFIX 8(%rsi)
+
+	popf
+	mov $1, %al
+	ret
+
+ not_same:
+	popf
+	xor %al,%al
+	ret
+
+CFI_ENDPROC
+
+ENDPROC(this_cpu_cmpxchg16b_emu)
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/copy_user_64.S linux-libre-2.6.39-gnu/arch/x86/lib/copy_user_64.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/copy_user_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/copy_user_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -117,7 +117,7 @@
  * rdx count
  *
  * Output:
- * eax uncopied bytes or 0 if successfull.
+ * eax uncopied bytes or 0 if successful.
  */
 ENTRY(copy_user_generic_unrolled)
 	CFI_STARTPROC
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/csum-copy_64.S linux-libre-2.6.39-gnu/arch/x86/lib/csum-copy_64.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/csum-copy_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/csum-copy_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
- * Copyright 2002,2003 Andi Kleen, SuSE Labs.
- *	
+ * Copyright 2002, 2003 Andi Kleen, SuSE Labs.
+ *
  * 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. No warranty for anything given at all.
@@ -11,82 +11,82 @@
 
 /*
  * Checksum copy with exception handling.
- * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the 
+ * On exceptions src_err_ptr or dst_err_ptr is set to -EFAULT and the
  * destination is zeroed.
- * 
+ *
  * Input
  * rdi  source
  * rsi  destination
  * edx  len (32bit)
- * ecx  sum (32bit) 
+ * ecx  sum (32bit)
  * r8   src_err_ptr (int)
  * r9   dst_err_ptr (int)
  *
  * Output
  * eax  64bit sum. undefined in case of exception.
- * 
- * Wrappers need to take care of valid exception sum and zeroing.		 
+ *
+ * Wrappers need to take care of valid exception sum and zeroing.
  * They also should align source or destination to 8 bytes.
  */
 
 	.macro source
 10:
-	.section __ex_table,"a"
+	.section __ex_table, "a"
 	.align 8
-	.quad 10b,.Lbad_source
+	.quad 10b, .Lbad_source
 	.previous
 	.endm
-		
+
 	.macro dest
 20:
-	.section __ex_table,"a"
+	.section __ex_table, "a"
 	.align 8
-	.quad 20b,.Lbad_dest
+	.quad 20b, .Lbad_dest
 	.previous
 	.endm
-			
+
 	.macro ignore L=.Lignore
 30:
-	.section __ex_table,"a"
+	.section __ex_table, "a"
 	.align 8
-	.quad 30b,\L
+	.quad 30b, \L
 	.previous
 	.endm
-	
-				
+
+
 ENTRY(csum_partial_copy_generic)
 	CFI_STARTPROC
-	cmpl	 $3*64,%edx
-	jle	 .Lignore
+	cmpl	$3*64, %edx
+	jle	.Lignore
 
-.Lignore:		
-	subq  $7*8,%rsp
+.Lignore:
+	subq  $7*8, %rsp
 	CFI_ADJUST_CFA_OFFSET 7*8
-	movq  %rbx,2*8(%rsp)
+	movq  %rbx, 2*8(%rsp)
 	CFI_REL_OFFSET rbx, 2*8
-	movq  %r12,3*8(%rsp)
+	movq  %r12, 3*8(%rsp)
 	CFI_REL_OFFSET r12, 3*8
-	movq  %r14,4*8(%rsp)
+	movq  %r14, 4*8(%rsp)
 	CFI_REL_OFFSET r14, 4*8
-	movq  %r13,5*8(%rsp)
+	movq  %r13, 5*8(%rsp)
 	CFI_REL_OFFSET r13, 5*8
-	movq  %rbp,6*8(%rsp)
+	movq  %rbp, 6*8(%rsp)
 	CFI_REL_OFFSET rbp, 6*8
 
-	movq  %r8,(%rsp)
-	movq  %r9,1*8(%rsp)
-	
-	movl  %ecx,%eax
-	movl  %edx,%ecx
+	movq  %r8, (%rsp)
+	movq  %r9, 1*8(%rsp)
 
-	xorl  %r9d,%r9d
-	movq  %rcx,%r12
+	movl  %ecx, %eax
+	movl  %edx, %ecx
 
-	shrq  $6,%r12
-	jz    .Lhandle_tail       /* < 64 */
+	xorl  %r9d, %r9d
+	movq  %rcx, %r12
+
+	shrq  $6, %r12
+	jz	.Lhandle_tail       /* < 64 */
 
 	clc
-	
+
 	/* main loop. clear in 64 byte blocks */
 	/* r9: zero, r8: temp2, rbx: temp1, rax: sum, rcx: saved length */
 	/* r11:	temp3, rdx: temp4, r12 loopcnt */
@@ -94,156 +94,156 @@
 	.p2align 4
 .Lloop:
 	source
-	movq  (%rdi),%rbx
+	movq  (%rdi), %rbx
 	source
-	movq  8(%rdi),%r8
+	movq  8(%rdi), %r8
 	source
-	movq  16(%rdi),%r11
+	movq  16(%rdi), %r11
 	source
-	movq  24(%rdi),%rdx
+	movq  24(%rdi), %rdx
 
 	source
-	movq  32(%rdi),%r10
+	movq  32(%rdi), %r10
 	source
-	movq  40(%rdi),%rbp
+	movq  40(%rdi), %rbp
 	source
-	movq  48(%rdi),%r14
+	movq  48(%rdi), %r14
 	source
-	movq  56(%rdi),%r13
-		
+	movq  56(%rdi), %r13
+
 	ignore 2f
 	prefetcht0 5*64(%rdi)
-2:							
-	adcq  %rbx,%rax
-	adcq  %r8,%rax
-	adcq  %r11,%rax
-	adcq  %rdx,%rax
-	adcq  %r10,%rax
-	adcq  %rbp,%rax
-	adcq  %r14,%rax
-	adcq  %r13,%rax
+2:
+	adcq  %rbx, %rax
+	adcq  %r8, %rax
+	adcq  %r11, %rax
+	adcq  %rdx, %rax
+	adcq  %r10, %rax
+	adcq  %rbp, %rax
+	adcq  %r14, %rax
+	adcq  %r13, %rax
 
 	decl %r12d
-	
+
 	dest
-	movq %rbx,(%rsi)
+	movq %rbx, (%rsi)
 	dest
-	movq %r8,8(%rsi)
+	movq %r8, 8(%rsi)
 	dest
-	movq %r11,16(%rsi)
+	movq %r11, 16(%rsi)
 	dest
-	movq %rdx,24(%rsi)
+	movq %rdx, 24(%rsi)
 
 	dest
-	movq %r10,32(%rsi)
+	movq %r10, 32(%rsi)
 	dest
-	movq %rbp,40(%rsi)
+	movq %rbp, 40(%rsi)
 	dest
-	movq %r14,48(%rsi)
+	movq %r14, 48(%rsi)
 	dest
-	movq %r13,56(%rsi)
-	
+	movq %r13, 56(%rsi)
+
 3:
-	
-	leaq 64(%rdi),%rdi
-	leaq 64(%rsi),%rsi
 
-	jnz   .Lloop
+	leaq 64(%rdi), %rdi
+	leaq 64(%rsi), %rsi
 
-	adcq  %r9,%rax
+	jnz	.Lloop
 
-	/* do last upto 56 bytes */
+	adcq  %r9, %rax
+
+	/* do last up to 56 bytes */
 .Lhandle_tail:
 	/* ecx:	count */
-	movl %ecx,%r10d
-	andl $63,%ecx
-	shrl $3,%ecx
-	jz 	 .Lfold
+	movl %ecx, %r10d
+	andl $63, %ecx
+	shrl $3, %ecx
+	jz	.Lfold
 	clc
 	.p2align 4
-.Lloop_8:	
+.Lloop_8:
 	source
-	movq (%rdi),%rbx
-	adcq %rbx,%rax
+	movq (%rdi), %rbx
+	adcq %rbx, %rax
 	decl %ecx
 	dest
-	movq %rbx,(%rsi)
-	leaq 8(%rsi),%rsi /* preserve carry */
-	leaq 8(%rdi),%rdi
+	movq %rbx, (%rsi)
+	leaq 8(%rsi), %rsi /* preserve carry */
+	leaq 8(%rdi), %rdi
 	jnz	.Lloop_8
-	adcq %r9,%rax	/* add in carry */
+	adcq %r9, %rax	/* add in carry */
 
 .Lfold:
 	/* reduce checksum to 32bits */
-	movl %eax,%ebx
-	shrq $32,%rax
-	addl %ebx,%eax
-	adcl %r9d,%eax
+	movl %eax, %ebx
+	shrq $32, %rax
+	addl %ebx, %eax
+	adcl %r9d, %eax
 
-	/* do last upto 6 bytes */	
+	/* do last up to 6 bytes */
 .Lhandle_7:
-	movl %r10d,%ecx
-	andl $7,%ecx
-	shrl $1,%ecx
+	movl %r10d, %ecx
+	andl $7, %ecx
+	shrl $1, %ecx
 	jz   .Lhandle_1
-	movl $2,%edx
-	xorl %ebx,%ebx
-	clc  
+	movl $2, %edx
+	xorl %ebx, %ebx
+	clc
 	.p2align 4
-.Lloop_1:	
+.Lloop_1:
 	source
-	movw (%rdi),%bx
-	adcl %ebx,%eax
+	movw (%rdi), %bx
+	adcl %ebx, %eax
 	decl %ecx
 	dest
-	movw %bx,(%rsi)
-	leaq 2(%rdi),%rdi
-	leaq 2(%rsi),%rsi
+	movw %bx, (%rsi)
+	leaq 2(%rdi), %rdi
+	leaq 2(%rsi), %rsi
 	jnz .Lloop_1
-	adcl %r9d,%eax	/* add in carry */
-	
+	adcl %r9d, %eax	/* add in carry */
+
 	/* handle last odd byte */
 .Lhandle_1:
-	testl $1,%r10d
+	testl $1, %r10d
 	jz    .Lende
-	xorl  %ebx,%ebx
+	xorl  %ebx, %ebx
 	source
-	movb (%rdi),%bl
+	movb (%rdi), %bl
 	dest
-	movb %bl,(%rsi)
-	addl %ebx,%eax
-	adcl %r9d,%eax		/* carry */
-			
+	movb %bl, (%rsi)
+	addl %ebx, %eax
+	adcl %r9d, %eax		/* carry */
+
 	CFI_REMEMBER_STATE
 .Lende:
-	movq 2*8(%rsp),%rbx
+	movq 2*8(%rsp), %rbx
 	CFI_RESTORE rbx
-	movq 3*8(%rsp),%r12
+	movq 3*8(%rsp), %r12
 	CFI_RESTORE r12
-	movq 4*8(%rsp),%r14
+	movq 4*8(%rsp), %r14
 	CFI_RESTORE r14
-	movq 5*8(%rsp),%r13
+	movq 5*8(%rsp), %r13
 	CFI_RESTORE r13
-	movq 6*8(%rsp),%rbp
+	movq 6*8(%rsp), %rbp
 	CFI_RESTORE rbp
-	addq $7*8,%rsp
+	addq $7*8, %rsp
 	CFI_ADJUST_CFA_OFFSET -7*8
 	ret
 	CFI_RESTORE_STATE
 
 	/* Exception handlers. Very simple, zeroing is done in the wrappers */
 .Lbad_source:
-	movq (%rsp),%rax
-	testq %rax,%rax
+	movq (%rsp), %rax
+	testq %rax, %rax
 	jz   .Lende
-	movl $-EFAULT,(%rax)
+	movl $-EFAULT, (%rax)
 	jmp  .Lende
-	
+
 .Lbad_dest:
-	movq 8(%rsp),%rax
-	testq %rax,%rax
-	jz   .Lende	
-	movl $-EFAULT,(%rax)
+	movq 8(%rsp), %rax
+	testq %rax, %rax
+	jz   .Lende
+	movl $-EFAULT, (%rax)
 	jmp .Lende
 	CFI_ENDPROC
 ENDPROC(csum_partial_copy_generic)
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/csum-partial_64.c linux-libre-2.6.39-gnu/arch/x86/lib/csum-partial_64.c
--- linux-libre-2.6.38-gnu/arch/x86/lib/csum-partial_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/csum-partial_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,7 @@
 				count64--;
 			}
 
-			/* last upto 7 8byte blocks */
+			/* last up to 7 8byte blocks */
 			count %= 8; 
 			while (count) { 
 				asm("addq %1,%0\n\t"
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/Makefile linux-libre-2.6.39-gnu/arch/x86/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/x86/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -42,4 +42,5 @@
         lib-y += memmove_64.o memset_64.o
         lib-y += copy_user_64.o rwlock_64.o copy_user_nocache_64.o
 	lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem_64.o
+	lib-y += cmpxchg16b_emu.o
 endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/memmove_64.c linux-libre-2.6.39-gnu/arch/x86/lib/memmove_64.c
--- linux-libre-2.6.38-gnu/arch/x86/lib/memmove_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/memmove_64.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,192 +0,0 @@
-/* Normally compiler builtins are used, but sometimes the compiler calls out
-   of line code. Based on asm-i386/string.h.
- */
-#define _STRING_C
-#include <linux/string.h>
-#include <linux/module.h>
-
-#undef memmove
-void *memmove(void *dest, const void *src, size_t count)
-{
-	unsigned long d0,d1,d2,d3,d4,d5,d6,d7;
-	char *ret;
-
-	__asm__ __volatile__(
-		/* Handle more 32bytes in loop */
-		"mov %2, %3\n\t"
-		"cmp $0x20, %0\n\t"
-		"jb	1f\n\t"
-
-		/* Decide forward/backward copy mode */
-		"cmp %2, %1\n\t"
-		"jb	2f\n\t"
-
-		/*
-		 * movsq instruction have many startup latency
-		 * so we handle small size by general register.
-		 */
-		"cmp  $680, %0\n\t"
-		"jb 3f\n\t"
-		/*
-		 * movsq instruction is only good for aligned case.
-		 */
-		"cmpb %%dil, %%sil\n\t"
-		"je 4f\n\t"
-		"3:\n\t"
-		"sub $0x20, %0\n\t"
-		/*
-		 * We gobble 32byts forward in each loop.
-		 */
-		"5:\n\t"
-		"sub $0x20, %0\n\t"
-		"movq 0*8(%1), %4\n\t"
-		"movq 1*8(%1), %5\n\t"
-		"movq 2*8(%1), %6\n\t"
-		"movq 3*8(%1), %7\n\t"
-		"leaq 4*8(%1), %1\n\t"
-
-		"movq %4, 0*8(%2)\n\t"
-		"movq %5, 1*8(%2)\n\t"
-		"movq %6, 2*8(%2)\n\t"
-		"movq %7, 3*8(%2)\n\t"
-		"leaq 4*8(%2), %2\n\t"
-		"jae 5b\n\t"
-		"addq $0x20, %0\n\t"
-		"jmp 1f\n\t"
-		/*
-		 * Handle data forward by movsq.
-		 */
-		".p2align 4\n\t"
-		"4:\n\t"
-		"movq %0, %8\n\t"
-		"movq -8(%1, %0), %4\n\t"
-		"lea -8(%2, %0), %5\n\t"
-		"shrq $3, %8\n\t"
-		"rep movsq\n\t"
-		"movq %4, (%5)\n\t"
-		"jmp 13f\n\t"
-		/*
-		 * Handle data backward by movsq.
-		 */
-		".p2align 4\n\t"
-		"7:\n\t"
-		"movq %0, %8\n\t"
-		"movq (%1), %4\n\t"
-		"movq %2, %5\n\t"
-		"leaq -8(%1, %0), %1\n\t"
-		"leaq -8(%2, %0), %2\n\t"
-		"shrq $3, %8\n\t"
-		"std\n\t"
-		"rep movsq\n\t"
-		"cld\n\t"
-		"movq %4, (%5)\n\t"
-		"jmp 13f\n\t"
-
-		/*
-		 * Start to prepare for backward copy.
-		 */
-		".p2align 4\n\t"
-		"2:\n\t"
-		"cmp $680, %0\n\t"
-		"jb 6f \n\t"
-		"cmp %%dil, %%sil\n\t"
-		"je 7b \n\t"
-		"6:\n\t"
-		/*
-		 * Calculate copy position to tail.
-		 */
-		"addq %0, %1\n\t"
-		"addq %0, %2\n\t"
-		"subq $0x20, %0\n\t"
-		/*
-		 * We gobble 32byts backward in each loop.
-		 */
-		"8:\n\t"
-		"subq $0x20, %0\n\t"
-		"movq -1*8(%1), %4\n\t"
-		"movq -2*8(%1), %5\n\t"
-		"movq -3*8(%1), %6\n\t"
-		"movq -4*8(%1), %7\n\t"
-		"leaq -4*8(%1), %1\n\t"
-
-		"movq %4, -1*8(%2)\n\t"
-		"movq %5, -2*8(%2)\n\t"
-		"movq %6, -3*8(%2)\n\t"
-		"movq %7, -4*8(%2)\n\t"
-		"leaq -4*8(%2), %2\n\t"
-		"jae 8b\n\t"
-		/*
-		 * Calculate copy position to head.
-		 */
-		"addq $0x20, %0\n\t"
-		"subq %0, %1\n\t"
-		"subq %0, %2\n\t"
-		"1:\n\t"
-		"cmpq $16, %0\n\t"
-		"jb 9f\n\t"
-		/*
-		 * Move data from 16 bytes to 31 bytes.
-		 */
-		"movq 0*8(%1), %4\n\t"
-		"movq 1*8(%1), %5\n\t"
-		"movq -2*8(%1, %0), %6\n\t"
-		"movq -1*8(%1, %0), %7\n\t"
-		"movq %4, 0*8(%2)\n\t"
-		"movq %5, 1*8(%2)\n\t"
-		"movq %6, -2*8(%2, %0)\n\t"
-		"movq %7, -1*8(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		".p2align 4\n\t"
-		"9:\n\t"
-		"cmpq $8, %0\n\t"
-		"jb 10f\n\t"
-		/*
-		 * Move data from 8 bytes to 15 bytes.
-		 */
-		"movq 0*8(%1), %4\n\t"
-		"movq -1*8(%1, %0), %5\n\t"
-		"movq %4, 0*8(%2)\n\t"
-		"movq %5, -1*8(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		"10:\n\t"
-		"cmpq $4, %0\n\t"
-		"jb 11f\n\t"
-		/*
-		 * Move data from 4 bytes to 7 bytes.
-		 */
-		"movl (%1), %4d\n\t"
-		"movl -4(%1, %0), %5d\n\t"
-		"movl %4d, (%2)\n\t"
-		"movl %5d, -4(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		"11:\n\t"
-		"cmp $2, %0\n\t"
-		"jb 12f\n\t"
-		/*
-		 * Move data from 2 bytes to 3 bytes.
-		 */
-		"movw (%1), %4w\n\t"
-		"movw -2(%1, %0), %5w\n\t"
-		"movw %4w, (%2)\n\t"
-		"movw %5w, -2(%2, %0)\n\t"
-		"jmp 13f\n\t"
-		"12:\n\t"
-		"cmp $1, %0\n\t"
-		"jb 13f\n\t"
-		/*
-		 * Move data for 1 byte.
-		 */
-		"movb (%1), %4b\n\t"
-		"movb %4b, (%2)\n\t"
-		"13:\n\t"
-		: "=&d" (d0), "=&S" (d1), "=&D" (d2), "=&a" (ret) ,
-		  "=r"(d3), "=r"(d4), "=r"(d5), "=r"(d6), "=&c" (d7)
-		:"0" (count),
-		 "1" (src),
-		 "2" (dest)
-		:"memory");
-
-		return ret;
-
-}
-EXPORT_SYMBOL(memmove);
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/memmove_64.S linux-libre-2.6.39-gnu/arch/x86/lib/memmove_64.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/memmove_64.S	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/lib/memmove_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,197 @@
+/*
+ * Normally compiler builtins are used, but sometimes the compiler calls out
+ * of line code. Based on asm-i386/string.h.
+ *
+ * This assembly file is re-written from memmove_64.c file.
+ *	- Copyright 2011 Fenghua Yu <fenghua.yu@intel.com>
+ */
+#define _STRING_C
+#include <linux/linkage.h>
+#include <asm/dwarf2.h>
+
+#undef memmove
+
+/*
+ * Implement memmove(). This can handle overlap between src and dst.
+ *
+ * Input:
+ * rdi: dest
+ * rsi: src
+ * rdx: count
+ *
+ * Output:
+ * rax: dest
+ */
+ENTRY(memmove)
+	CFI_STARTPROC
+	/* Handle more 32bytes in loop */
+	mov %rdi, %rax
+	cmp $0x20, %rdx
+	jb	1f
+
+	/* Decide forward/backward copy mode */
+	cmp %rdi, %rsi
+	jb	2f
+
+	/*
+	 * movsq instruction have many startup latency
+	 * so we handle small size by general register.
+	 */
+	cmp  $680, %rdx
+	jb	3f
+	/*
+	 * movsq instruction is only good for aligned case.
+	 */
+
+	cmpb %dil, %sil
+	je 4f
+3:
+	sub $0x20, %rdx
+	/*
+	 * We gobble 32byts forward in each loop.
+	 */
+5:
+	sub $0x20, %rdx
+	movq 0*8(%rsi), %r11
+	movq 1*8(%rsi), %r10
+	movq 2*8(%rsi), %r9
+	movq 3*8(%rsi), %r8
+	leaq 4*8(%rsi), %rsi
+
+	movq %r11, 0*8(%rdi)
+	movq %r10, 1*8(%rdi)
+	movq %r9, 2*8(%rdi)
+	movq %r8, 3*8(%rdi)
+	leaq 4*8(%rdi), %rdi
+	jae 5b
+	addq $0x20, %rdx
+	jmp 1f
+	/*
+	 * Handle data forward by movsq.
+	 */
+	.p2align 4
+4:
+	movq %rdx, %rcx
+	movq -8(%rsi, %rdx), %r11
+	lea -8(%rdi, %rdx), %r10
+	shrq $3, %rcx
+	rep movsq
+	movq %r11, (%r10)
+	jmp 13f
+	/*
+	 * Handle data backward by movsq.
+	 */
+	.p2align 4
+7:
+	movq %rdx, %rcx
+	movq (%rsi), %r11
+	movq %rdi, %r10
+	leaq -8(%rsi, %rdx), %rsi
+	leaq -8(%rdi, %rdx), %rdi
+	shrq $3, %rcx
+	std
+	rep movsq
+	cld
+	movq %r11, (%r10)
+	jmp 13f
+
+	/*
+	 * Start to prepare for backward copy.
+	 */
+	.p2align 4
+2:
+	cmp $680, %rdx
+	jb 6f
+	cmp %dil, %sil
+	je 7b
+6:
+	/*
+	 * Calculate copy position to tail.
+	 */
+	addq %rdx, %rsi
+	addq %rdx, %rdi
+	subq $0x20, %rdx
+	/*
+	 * We gobble 32byts backward in each loop.
+	 */
+8:
+	subq $0x20, %rdx
+	movq -1*8(%rsi), %r11
+	movq -2*8(%rsi), %r10
+	movq -3*8(%rsi), %r9
+	movq -4*8(%rsi), %r8
+	leaq -4*8(%rsi), %rsi
+
+	movq %r11, -1*8(%rdi)
+	movq %r10, -2*8(%rdi)
+	movq %r9, -3*8(%rdi)
+	movq %r8, -4*8(%rdi)
+	leaq -4*8(%rdi), %rdi
+	jae 8b
+	/*
+	 * Calculate copy position to head.
+	 */
+	addq $0x20, %rdx
+	subq %rdx, %rsi
+	subq %rdx, %rdi
+1:
+	cmpq $16, %rdx
+	jb 9f
+	/*
+	 * Move data from 16 bytes to 31 bytes.
+	 */
+	movq 0*8(%rsi), %r11
+	movq 1*8(%rsi), %r10
+	movq -2*8(%rsi, %rdx), %r9
+	movq -1*8(%rsi, %rdx), %r8
+	movq %r11, 0*8(%rdi)
+	movq %r10, 1*8(%rdi)
+	movq %r9, -2*8(%rdi, %rdx)
+	movq %r8, -1*8(%rdi, %rdx)
+	jmp 13f
+	.p2align 4
+9:
+	cmpq $8, %rdx
+	jb 10f
+	/*
+	 * Move data from 8 bytes to 15 bytes.
+	 */
+	movq 0*8(%rsi), %r11
+	movq -1*8(%rsi, %rdx), %r10
+	movq %r11, 0*8(%rdi)
+	movq %r10, -1*8(%rdi, %rdx)
+	jmp 13f
+10:
+	cmpq $4, %rdx
+	jb 11f
+	/*
+	 * Move data from 4 bytes to 7 bytes.
+	 */
+	movl (%rsi), %r11d
+	movl -4(%rsi, %rdx), %r10d
+	movl %r11d, (%rdi)
+	movl %r10d, -4(%rdi, %rdx)
+	jmp 13f
+11:
+	cmp $2, %rdx
+	jb 12f
+	/*
+	 * Move data from 2 bytes to 3 bytes.
+	 */
+	movw (%rsi), %r11w
+	movw -2(%rsi, %rdx), %r10w
+	movw %r11w, (%rdi)
+	movw %r10w, -2(%rdi, %rdx)
+	jmp 13f
+12:
+	cmp $1, %rdx
+	jb 13f
+	/*
+	 * Move data for 1 byte.
+	 */
+	movb (%rsi), %r11b
+	movb %r11b, (%rdi)
+13:
+	retq
+	CFI_ENDPROC
+ENDPROC(memmove)
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/rwsem_64.S linux-libre-2.6.39-gnu/arch/x86/lib/rwsem_64.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/rwsem_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/rwsem_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -23,43 +23,50 @@
 #include <asm/dwarf2.h>
 
 #define save_common_regs \
-	pushq %rdi; \
-	pushq %rsi; \
-	pushq %rcx; \
-	pushq %r8; \
-	pushq %r9; \
-	pushq %r10; \
-	pushq %r11
+	pushq_cfi %rdi; CFI_REL_OFFSET rdi, 0; \
+	pushq_cfi %rsi; CFI_REL_OFFSET rsi, 0; \
+	pushq_cfi %rcx; CFI_REL_OFFSET rcx, 0; \
+	pushq_cfi %r8;  CFI_REL_OFFSET r8,  0; \
+	pushq_cfi %r9;  CFI_REL_OFFSET r9,  0; \
+	pushq_cfi %r10; CFI_REL_OFFSET r10, 0; \
+	pushq_cfi %r11; CFI_REL_OFFSET r11, 0
 
 #define restore_common_regs \
-	popq %r11; \
-	popq %r10; \
-	popq %r9; \
-	popq %r8; \
-	popq %rcx; \
-	popq %rsi; \
-	popq %rdi
+	popq_cfi %r11; CFI_RESTORE r11; \
+	popq_cfi %r10; CFI_RESTORE r10; \
+	popq_cfi %r9;  CFI_RESTORE r9; \
+	popq_cfi %r8;  CFI_RESTORE r8; \
+	popq_cfi %rcx; CFI_RESTORE rcx; \
+	popq_cfi %rsi; CFI_RESTORE rsi; \
+	popq_cfi %rdi; CFI_RESTORE rdi
 
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
+	CFI_STARTPROC
 	save_common_regs
-	pushq %rdx
+	pushq_cfi %rdx
+	CFI_REL_OFFSET rdx, 0
 	movq %rax,%rdi
 	call rwsem_down_read_failed
-	popq %rdx
+	popq_cfi %rdx
+	CFI_RESTORE rdx
 	restore_common_regs
 	ret
-	ENDPROC(call_rwsem_down_read_failed)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_down_read_failed)
 
 ENTRY(call_rwsem_down_write_failed)
+	CFI_STARTPROC
 	save_common_regs
 	movq %rax,%rdi
 	call rwsem_down_write_failed
 	restore_common_regs
 	ret
-	ENDPROC(call_rwsem_down_write_failed)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_down_write_failed)
 
 ENTRY(call_rwsem_wake)
+	CFI_STARTPROC
 	decl %edx	/* do nothing if still outstanding active readers */
 	jnz 1f
 	save_common_regs
@@ -67,15 +74,20 @@
 	call rwsem_wake
 	restore_common_regs
 1:	ret
-	ENDPROC(call_rwsem_wake)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_wake)
 
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_downgrade_wake)
+	CFI_STARTPROC
 	save_common_regs
-	pushq %rdx
+	pushq_cfi %rdx
+	CFI_REL_OFFSET rdx, 0
 	movq %rax,%rdi
 	call rwsem_downgrade_wake
-	popq %rdx
+	popq_cfi %rdx
+	CFI_RESTORE rdx
 	restore_common_regs
 	ret
-	ENDPROC(call_rwsem_downgrade_wake)
+	CFI_ENDPROC
+ENDPROC(call_rwsem_downgrade_wake)
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/semaphore_32.S linux-libre-2.6.39-gnu/arch/x86/lib/semaphore_32.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/semaphore_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/semaphore_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
  */
 #ifdef CONFIG_SMP
 ENTRY(__write_lock_failed)
-	CFI_STARTPROC simple
+	CFI_STARTPROC
 	FRAME
 2: 	LOCK_PREFIX
 	addl	$ RW_LOCK_BIAS,(%eax)
@@ -74,29 +74,23 @@
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_down_read_failed)
 	CFI_STARTPROC
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edx
 	CFI_REL_OFFSET edx,0
 	call rwsem_down_read_failed
-	pop %edx
-	CFI_ADJUST_CFA_OFFSET -4
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edx
+	popl_cfi %ecx
 	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_down_read_failed)
 
 ENTRY(call_rwsem_down_write_failed)
 	CFI_STARTPROC
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
 	calll rwsem_down_write_failed
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx
 	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_down_write_failed)
@@ -105,12 +99,10 @@
 	CFI_STARTPROC
 	decw %dx    /* do nothing if still outstanding active readers */
 	jnz 1f
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
 	call rwsem_wake
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %ecx
 1:	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_wake)
@@ -118,17 +110,13 @@
 /* Fix up special calling conventions */
 ENTRY(call_rwsem_downgrade_wake)
 	CFI_STARTPROC
-	push %ecx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %ecx
 	CFI_REL_OFFSET ecx,0
-	push %edx
-	CFI_ADJUST_CFA_OFFSET 4
+	pushl_cfi %edx
 	CFI_REL_OFFSET edx,0
 	call rwsem_downgrade_wake
-	pop %edx
-	CFI_ADJUST_CFA_OFFSET -4
-	pop %ecx
-	CFI_ADJUST_CFA_OFFSET -4
+	popl_cfi %edx
+	popl_cfi %ecx
 	ret
 	CFI_ENDPROC
 	ENDPROC(call_rwsem_downgrade_wake)
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/thunk_32.S linux-libre-2.6.39-gnu/arch/x86/lib/thunk_32.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/thunk_32.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/thunk_32.S	2011-05-19 00:06:34.000000000 -0400
@@ -7,24 +7,6 @@
 
 	#include <linux/linkage.h>
 
-#define ARCH_TRACE_IRQS_ON			\
-	pushl %eax;				\
-	pushl %ecx;				\
-	pushl %edx;				\
-	call trace_hardirqs_on;			\
-	popl %edx;				\
-	popl %ecx;				\
-	popl %eax;
-
-#define ARCH_TRACE_IRQS_OFF			\
-	pushl %eax;				\
-	pushl %ecx;				\
-	pushl %edx;				\
-	call trace_hardirqs_off;		\
-	popl %edx;				\
-	popl %ecx;				\
-	popl %eax;
-
 #ifdef CONFIG_TRACE_IRQFLAGS
 	/* put return address in eax (arg1) */
 	.macro thunk_ra name,func
diff -druN linux-libre-2.6.38-gnu/arch/x86/lib/thunk_64.S linux-libre-2.6.39-gnu/arch/x86/lib/thunk_64.S
--- linux-libre-2.6.38-gnu/arch/x86/lib/thunk_64.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/lib/thunk_64.S	2011-05-19 00:06:34.000000000 -0400
@@ -22,26 +22,6 @@
 	CFI_ENDPROC
 	.endm
 
-	/* rdi:	arg1 ... normal C conventions. rax is passed from C. */ 	
-	.macro thunk_retrax name,func
-	.globl \name
-\name:	
-	CFI_STARTPROC
-	SAVE_ARGS
-	call \func
-	jmp  restore_norax
-	CFI_ENDPROC
-	.endm
-	
-
-	.section .sched.text, "ax"
-#ifdef CONFIG_RWSEM_XCHGADD_ALGORITHM
-	thunk rwsem_down_read_failed_thunk,rwsem_down_read_failed
-	thunk rwsem_down_write_failed_thunk,rwsem_down_write_failed
-	thunk rwsem_wake_thunk,rwsem_wake
-	thunk rwsem_downgrade_thunk,rwsem_downgrade_wake
-#endif	
-	
 #ifdef CONFIG_TRACE_IRQFLAGS
 	/* put return address in rdi (arg1) */
 	.macro thunk_ra name,func
@@ -72,10 +52,3 @@
 	RESTORE_ARGS
 	ret	
 	CFI_ENDPROC
-	
-	CFI_STARTPROC
-	SAVE_ARGS
-restore_norax:	
-	RESTORE_ARGS 1
-	ret
-	CFI_ENDPROC
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/amdtopology_64.c linux-libre-2.6.39-gnu/arch/x86/mm/amdtopology_64.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/amdtopology_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/amdtopology_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,9 +26,7 @@
 #include <asm/apic.h>
 #include <asm/amd_nb.h>
 
-static struct bootnode __initdata nodes[8];
 static unsigned char __initdata nodeids[8];
-static nodemask_t __initdata nodes_parsed = NODE_MASK_NONE;
 
 static __init int find_northbridge(void)
 {
@@ -51,7 +49,7 @@
 		return num;
 	}
 
-	return -1;
+	return -ENOENT;
 }
 
 static __init void early_get_boot_cpu_id(void)
@@ -69,17 +67,18 @@
 #endif
 }
 
-int __init amd_numa_init(unsigned long start_pfn, unsigned long end_pfn)
+int __init amd_numa_init(void)
 {
-	unsigned long start = PFN_PHYS(start_pfn);
-	unsigned long end = PFN_PHYS(end_pfn);
+	unsigned long start = PFN_PHYS(0);
+	unsigned long end = PFN_PHYS(max_pfn);
 	unsigned numnodes;
 	unsigned long prevbase;
-	int i, nb, found = 0;
+	int i, j, nb;
 	u32 nodeid, reg;
+	unsigned int bits, cores, apicid_base;
 
 	if (!early_pci_allowed())
-		return -1;
+		return -EINVAL;
 
 	nb = find_northbridge();
 	if (nb < 0)
@@ -90,7 +89,7 @@
 	reg = read_pci_config(0, nb, 0, 0x60);
 	numnodes = ((reg >> 4) & 0xF) + 1;
 	if (numnodes <= 1)
-		return -1;
+		return -ENOENT;
 
 	pr_info("Number of physical nodes %d\n", numnodes);
 
@@ -121,9 +120,9 @@
 		if ((base >> 8) & 3 || (limit >> 8) & 3) {
 			pr_err("Node %d using interleaving mode %lx/%lx\n",
 			       nodeid, (base >> 8) & 3, (limit >> 8) & 3);
-			return -1;
+			return -EINVAL;
 		}
-		if (node_isset(nodeid, nodes_parsed)) {
+		if (node_isset(nodeid, numa_nodes_parsed)) {
 			pr_info("Node %d already present, skipping\n",
 				nodeid);
 			continue;
@@ -160,117 +159,28 @@
 		if (prevbase > base) {
 			pr_err("Node map not sorted %lx,%lx\n",
 			       prevbase, base);
-			return -1;
+			return -EINVAL;
 		}
 
 		pr_info("Node %d MemBase %016lx Limit %016lx\n",
 			nodeid, base, limit);
 
-		found++;
-
-		nodes[nodeid].start = base;
-		nodes[nodeid].end = limit;
-
 		prevbase = base;
-
-		node_set(nodeid, nodes_parsed);
-	}
-
-	if (!found)
-		return -1;
-	return 0;
-}
-
-#ifdef CONFIG_NUMA_EMU
-static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
-	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
-};
-
-void __init amd_get_nodes(struct bootnode *physnodes)
-{
-	int i;
-
-	for_each_node_mask(i, nodes_parsed) {
-		physnodes[i].start = nodes[i].start;
-		physnodes[i].end = nodes[i].end;
+		numa_add_memblk(nodeid, base, limit);
+		node_set(nodeid, numa_nodes_parsed);
 	}
-}
 
-static int __init find_node_by_addr(unsigned long addr)
-{
-	int ret = NUMA_NO_NODE;
-	int i;
-
-	for (i = 0; i < 8; i++)
-		if (addr >= nodes[i].start && addr < nodes[i].end) {
-			ret = i;
-			break;
-		}
-	return ret;
-}
-
-/*
- * For NUMA emulation, fake proximity domain (_PXM) to node id mappings must be
- * setup to represent the physical topology but reflect the emulated
- * environment.  For each emulated node, the real node which it appears on is
- * found and a fake pxm to nid mapping is created which mirrors the actual
- * locality.  node_distance() then represents the correct distances between
- * emulated nodes by using the fake acpi mappings to pxms.
- */
-void __init amd_fake_nodes(const struct bootnode *nodes, int nr_nodes)
-{
-	unsigned int bits;
-	unsigned int cores;
-	unsigned int apicid_base = 0;
-	int i;
+	if (!nodes_weight(numa_nodes_parsed))
+		return -ENOENT;
 
+	/*
+	 * We seem to have valid NUMA configuration.  Map apicids to nodes
+	 * using the coreid bits from early_identify_cpu.
+	 */
 	bits = boot_cpu_data.x86_coreid_bits;
 	cores = 1 << bits;
-	early_get_boot_cpu_id();
-	if (boot_cpu_physical_apicid > 0)
-		apicid_base = boot_cpu_physical_apicid;
-
-	for (i = 0; i < nr_nodes; i++) {
-		int index;
-		int nid;
-		int j;
-
-		nid = find_node_by_addr(nodes[i].start);
-		if (nid == NUMA_NO_NODE)
-			continue;
-
-		index = nodeids[nid] << bits;
-		if (fake_apicid_to_node[index + apicid_base] == NUMA_NO_NODE)
-			for (j = apicid_base; j < cores + apicid_base; j++)
-				fake_apicid_to_node[index + j] = i;
-#ifdef CONFIG_ACPI_NUMA
-		__acpi_map_pxm_to_node(nid, i);
-#endif
-	}
-	memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
-}
-#endif /* CONFIG_NUMA_EMU */
-
-int __init amd_scan_nodes(void)
-{
-	unsigned int bits;
-	unsigned int cores;
-	unsigned int apicid_base;
-	int i;
-
-	BUG_ON(nodes_empty(nodes_parsed));
-	node_possible_map = nodes_parsed;
-	memnode_shift = compute_hash_shift(nodes, 8, NULL);
-	if (memnode_shift < 0) {
-		pr_err("No NUMA node hash function found. Contact maintainer\n");
-		return -1;
-	}
-	pr_info("Using node hash shift of %d\n", memnode_shift);
-
-	/* use the coreid bits from early_identify_cpu */
-	bits = boot_cpu_data.x86_coreid_bits;
-	cores = (1<<bits);
 	apicid_base = 0;
+
 	/* get the APIC ID of the BSP early for systems with apicid lifting */
 	early_get_boot_cpu_id();
 	if (boot_cpu_physical_apicid > 0) {
@@ -278,17 +188,9 @@
 		apicid_base = boot_cpu_physical_apicid;
 	}
 
-	for_each_node_mask(i, node_possible_map) {
-		int j;
-
-		memblock_x86_register_active_regions(i,
-				nodes[i].start >> PAGE_SHIFT,
-				nodes[i].end >> PAGE_SHIFT);
+	for_each_node_mask(i, numa_nodes_parsed)
 		for (j = apicid_base; j < cores + apicid_base; j++)
-			apicid_to_node[(i << bits) + j] = i;
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	}
+			set_apicid_to_node((i << bits) + j, i);
 
-	numa_init_array();
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/hugetlbpage.c linux-libre-2.6.39-gnu/arch/x86/mm/hugetlbpage.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/hugetlbpage.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/hugetlbpage.c	2011-05-19 00:06:34.000000000 -0400
@@ -326,7 +326,7 @@
 	if (mm->free_area_cache < len)
 		goto fail;
 
-	/* either no address requested or cant fit in requested address hole */
+	/* either no address requested or can't fit in requested address hole */
 	addr = (mm->free_area_cache - len) & huge_page_mask(h);
 	do {
 		/*
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/init_32.c linux-libre-2.6.39-gnu/arch/x86/mm/init_32.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/init_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/init_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,10 +62,10 @@
 
 static __init void *alloc_low_page(void)
 {
-	unsigned long pfn = e820_table_end++;
+	unsigned long pfn = pgt_buf_end++;
 	void *adr;
 
-	if (pfn >= e820_table_top)
+	if (pfn >= pgt_buf_top)
 		panic("alloc_low_page: ran out of memory");
 
 	adr = __va(pfn * PAGE_SIZE);
@@ -163,8 +163,8 @@
 	if (pmd_idx_kmap_begin != pmd_idx_kmap_end
 	    && (vaddr >> PMD_SHIFT) >= pmd_idx_kmap_begin
 	    && (vaddr >> PMD_SHIFT) <= pmd_idx_kmap_end
-	    && ((__pa(pte) >> PAGE_SHIFT) < e820_table_start
-		|| (__pa(pte) >> PAGE_SHIFT) >= e820_table_end)) {
+	    && ((__pa(pte) >> PAGE_SHIFT) < pgt_buf_start
+		|| (__pa(pte) >> PAGE_SHIFT) >= pgt_buf_end)) {
 		pte_t *newpte;
 		int i;
 
@@ -644,8 +644,7 @@
 }
 
 #ifndef CONFIG_NEED_MULTIPLE_NODES
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(void)
 {
 #ifdef CONFIG_HIGHMEM
 	highstart_pfn = highend_pfn = max_pfn;
@@ -918,7 +917,7 @@
 {
 	/*
 	 * When this called, init has already been executed and released,
-	 * so everything past _etext sould be NX.
+	 * so everything past _etext should be NX.
 	 */
 	unsigned long start = PFN_ALIGN(_etext);
 	/*
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/init_64.c linux-libre-2.6.39-gnu/arch/x86/mm/init_64.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/init_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/init_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,8 @@
 #include <asm/numa.h>
 #include <asm/cacheflush.h>
 #include <asm/init.h>
+#include <asm/uv/uv.h>
+#include <asm/setup.h>
 
 static int __init parse_direct_gbpages_off(char *arg)
 {
@@ -293,18 +295,18 @@
  * to the compile time generated pmds. This results in invalid pmds up
  * to the point where we hit the physaddr 0 mapping.
  *
- * We limit the mappings to the region from _text to _end.  _end is
- * rounded up to the 2MB boundary. This catches the invalid pmds as
+ * We limit the mappings to the region from _text to _brk_end.  _brk_end
+ * is rounded up to the 2MB boundary. This catches the invalid pmds as
  * well, as they are located before _text:
  */
 void __init cleanup_highmap(void)
 {
 	unsigned long vaddr = __START_KERNEL_map;
-	unsigned long end = roundup((unsigned long)_end, PMD_SIZE) - 1;
+	unsigned long vaddr_end = __START_KERNEL_map + (max_pfn_mapped << PAGE_SHIFT);
+	unsigned long end = roundup((unsigned long)_brk_end, PMD_SIZE) - 1;
 	pmd_t *pmd = level2_kernel_pgt;
-	pmd_t *last_pmd = pmd + PTRS_PER_PMD;
 
-	for (; pmd < last_pmd; pmd++, vaddr += PMD_SIZE) {
+	for (; vaddr + PMD_SIZE - 1 < vaddr_end; pmd++, vaddr += PMD_SIZE) {
 		if (pmd_none(*pmd))
 			continue;
 		if (vaddr < (unsigned long) _text || vaddr > end)
@@ -314,7 +316,7 @@
 
 static __ref void *alloc_low_page(unsigned long *phys)
 {
-	unsigned long pfn = e820_table_end++;
+	unsigned long pfn = pgt_buf_end++;
 	void *adr;
 
 	if (after_bootmem) {
@@ -324,7 +326,7 @@
 		return adr;
 	}
 
-	if (pfn >= e820_table_top)
+	if (pfn >= pgt_buf_top)
 		panic("alloc_low_page: ran out of memory");
 
 	adr = early_memremap(pfn * PAGE_SIZE, PAGE_SIZE);
@@ -333,12 +335,28 @@
 	return adr;
 }
 
+static __ref void *map_low_page(void *virt)
+{
+	void *adr;
+	unsigned long phys, left;
+
+	if (after_bootmem)
+		return virt;
+
+	phys = __pa(virt);
+	left = phys & (PAGE_SIZE - 1);
+	adr = early_memremap(phys & PAGE_MASK, PAGE_SIZE);
+	adr = (void *)(((unsigned long)adr) | left);
+
+	return adr;
+}
+
 static __ref void unmap_low_page(void *adr)
 {
 	if (after_bootmem)
 		return;
 
-	early_iounmap(adr, PAGE_SIZE);
+	early_iounmap((void *)((unsigned long)adr & PAGE_MASK), PAGE_SIZE);
 }
 
 static unsigned long __meminit
@@ -386,15 +404,6 @@
 }
 
 static unsigned long __meminit
-phys_pte_update(pmd_t *pmd, unsigned long address, unsigned long end,
-		pgprot_t prot)
-{
-	pte_t *pte = (pte_t *)pmd_page_vaddr(*pmd);
-
-	return phys_pte_init(pte, address, end, prot);
-}
-
-static unsigned long __meminit
 phys_pmd_init(pmd_t *pmd_page, unsigned long address, unsigned long end,
 	      unsigned long page_size_mask, pgprot_t prot)
 {
@@ -420,8 +429,10 @@
 		if (pmd_val(*pmd)) {
 			if (!pmd_large(*pmd)) {
 				spin_lock(&init_mm.page_table_lock);
-				last_map_addr = phys_pte_update(pmd, address,
+				pte = map_low_page((pte_t *)pmd_page_vaddr(*pmd));
+				last_map_addr = phys_pte_init(pte, address,
 								end, prot);
+				unmap_low_page(pte);
 				spin_unlock(&init_mm.page_table_lock);
 				continue;
 			}
@@ -468,18 +479,6 @@
 }
 
 static unsigned long __meminit
-phys_pmd_update(pud_t *pud, unsigned long address, unsigned long end,
-		unsigned long page_size_mask, pgprot_t prot)
-{
-	pmd_t *pmd = pmd_offset(pud, 0);
-	unsigned long last_map_addr;
-
-	last_map_addr = phys_pmd_init(pmd, address, end, page_size_mask, prot);
-	__flush_tlb_all();
-	return last_map_addr;
-}
-
-static unsigned long __meminit
 phys_pud_init(pud_t *pud_page, unsigned long addr, unsigned long end,
 			 unsigned long page_size_mask)
 {
@@ -504,8 +503,11 @@
 
 		if (pud_val(*pud)) {
 			if (!pud_large(*pud)) {
-				last_map_addr = phys_pmd_update(pud, addr, end,
+				pmd = map_low_page(pmd_offset(pud, 0));
+				last_map_addr = phys_pmd_init(pmd, addr, end,
 							 page_size_mask, prot);
+				unmap_low_page(pmd);
+				__flush_tlb_all();
 				continue;
 			}
 			/*
@@ -553,17 +555,6 @@
 	return last_map_addr;
 }
 
-static unsigned long __meminit
-phys_pud_update(pgd_t *pgd, unsigned long addr, unsigned long end,
-		 unsigned long page_size_mask)
-{
-	pud_t *pud;
-
-	pud = (pud_t *)pgd_page_vaddr(*pgd);
-
-	return phys_pud_init(pud, addr, end, page_size_mask);
-}
-
 unsigned long __meminit
 kernel_physical_mapping_init(unsigned long start,
 			     unsigned long end,
@@ -587,8 +578,10 @@
 			next = end;
 
 		if (pgd_val(*pgd)) {
-			last_map_addr = phys_pud_update(pgd, __pa(start),
+			pud = map_low_page((pud_t *)pgd_page_vaddr(*pgd));
+			last_map_addr = phys_pud_init(pud, __pa(start),
 						 __pa(end), page_size_mask);
+			unmap_low_page(pud);
 			continue;
 		}
 
@@ -612,10 +605,9 @@
 }
 
 #ifndef CONFIG_NUMA
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(void)
 {
-	memblock_x86_register_active_regions(0, start_pfn, end_pfn);
+	memblock_x86_register_active_regions(0, 0, max_pfn);
 }
 #endif
 
@@ -870,18 +862,18 @@
 	.vm_flags	= VM_READ | VM_EXEC
 };
 
-struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 {
 #ifdef CONFIG_IA32_EMULATION
-	if (test_tsk_thread_flag(tsk, TIF_IA32))
+	if (!mm || mm->context.ia32_compat)
 		return NULL;
 #endif
 	return &gate_vma;
 }
 
-int in_gate_area(struct task_struct *task, unsigned long addr)
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
 {
-	struct vm_area_struct *vma = get_gate_vma(task);
+	struct vm_area_struct *vma = get_gate_vma(mm);
 
 	if (!vma)
 		return 0;
@@ -890,11 +882,11 @@
 }
 
 /*
- * Use this when you have no reliable task/vma, typically from interrupt
- * context. It is less reliable than using the task's vma and may give
- * false positives:
+ * Use this when you have no reliable mm, typically from interrupt
+ * context. It is less reliable than using a task's mm and may give
+ * false positives.
  */
-int in_gate_area_no_task(unsigned long addr)
+int in_gate_area_no_mm(unsigned long addr)
 {
 	return (addr >= VSYSCALL_START) && (addr < VSYSCALL_END);
 }
@@ -908,6 +900,19 @@
 	return NULL;
 }
 
+#ifdef CONFIG_X86_UV
+#define MIN_MEMORY_BLOCK_SIZE   (1 << SECTION_SIZE_BITS)
+
+unsigned long memory_block_size_bytes(void)
+{
+	if (is_uv_system()) {
+		printk(KERN_INFO "UV: memory block size 2GB\n");
+		return 2UL * 1024 * 1024 * 1024;
+	}
+	return MIN_MEMORY_BLOCK_SIZE;
+}
+#endif
+
 #ifdef CONFIG_SPARSEMEM_VMEMMAP
 /*
  * Initialise the sparsemem vmemmap using huge-pages at the PMD level.
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/init.c linux-libre-2.6.39-gnu/arch/x86/mm/init.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,9 +18,9 @@
 
 DEFINE_PER_CPU(struct mmu_gather, mmu_gathers);
 
-unsigned long __initdata e820_table_start;
-unsigned long __meminitdata e820_table_end;
-unsigned long __meminitdata e820_table_top;
+unsigned long __initdata pgt_buf_start;
+unsigned long __meminitdata pgt_buf_end;
+unsigned long __meminitdata pgt_buf_top;
 
 int after_bootmem;
 
@@ -33,7 +33,7 @@
 static void __init find_early_table_space(unsigned long end, int use_pse,
 					  int use_gbpages)
 {
-	unsigned long puds, pmds, ptes, tables, start;
+	unsigned long puds, pmds, ptes, tables, start = 0, good_end = end;
 	phys_addr_t base;
 
 	puds = (end + PUD_SIZE - 1) >> PUD_SHIFT;
@@ -65,29 +65,25 @@
 #ifdef CONFIG_X86_32
 	/* for fixmap */
 	tables += roundup(__end_of_fixed_addresses * sizeof(pte_t), PAGE_SIZE);
-#endif
 
-	/*
-	 * RED-PEN putting page tables only on node 0 could
-	 * cause a hotspot and fill up ZONE_DMA. The page tables
-	 * need roughly 0.5KB per GB.
-	 */
-#ifdef CONFIG_X86_32
-	start = 0x7000;
-#else
-	start = 0x8000;
+	good_end = max_pfn_mapped << PAGE_SHIFT;
 #endif
-	base = memblock_find_in_range(start, max_pfn_mapped<<PAGE_SHIFT,
-					tables, PAGE_SIZE);
+
+	base = memblock_find_in_range(start, good_end, tables, PAGE_SIZE);
 	if (base == MEMBLOCK_ERROR)
 		panic("Cannot find space for the kernel page tables");
 
-	e820_table_start = base >> PAGE_SHIFT;
-	e820_table_end = e820_table_start;
-	e820_table_top = e820_table_start + (tables >> PAGE_SHIFT);
+	pgt_buf_start = base >> PAGE_SHIFT;
+	pgt_buf_end = pgt_buf_start;
+	pgt_buf_top = pgt_buf_start + (tables >> PAGE_SHIFT);
 
 	printk(KERN_DEBUG "kernel direct mapping tables up to %lx @ %lx-%lx\n",
-		end, e820_table_start << PAGE_SHIFT, e820_table_top << PAGE_SHIFT);
+		end, pgt_buf_start << PAGE_SHIFT, pgt_buf_top << PAGE_SHIFT);
+}
+
+void __init native_pagetable_reserve(u64 start, u64 end)
+{
+	memblock_x86_reserve_range(start, end, "PGTABLE");
 }
 
 struct map_range {
@@ -279,30 +275,26 @@
 	load_cr3(swapper_pg_dir);
 #endif
 
-#ifdef CONFIG_X86_64
-	if (!after_bootmem && !start) {
-		pud_t *pud;
-		pmd_t *pmd;
-
-		mmu_cr4_features = read_cr4();
-
-		/*
-		 * _brk_end cannot change anymore, but it and _end may be
-		 * located on different 2M pages. cleanup_highmap(), however,
-		 * can only consider _end when it runs, so destroy any
-		 * mappings beyond _brk_end here.
-		 */
-		pud = pud_offset(pgd_offset_k(_brk_end), _brk_end);
-		pmd = pmd_offset(pud, _brk_end - 1);
-		while (++pmd <= pmd_offset(pud, (unsigned long)_end - 1))
-			pmd_clear(pmd);
-	}
-#endif
 	__flush_tlb_all();
 
-	if (!after_bootmem && e820_table_end > e820_table_start)
-		memblock_x86_reserve_range(e820_table_start << PAGE_SHIFT,
-				 e820_table_end << PAGE_SHIFT, "PGTABLE");
+	/*
+	 * Reserve the kernel pagetable pages we used (pgt_buf_start -
+	 * pgt_buf_end) and free the other ones (pgt_buf_end - pgt_buf_top)
+	 * so that they can be reused for other purposes.
+	 *
+	 * On native it just means calling memblock_x86_reserve_range, on Xen it
+	 * also means marking RW the pagetable pages that we allocated before
+	 * but that haven't been used.
+	 *
+	 * In fact on xen we mark RO the whole range pgt_buf_start -
+	 * pgt_buf_top, because we have to make sure that when
+	 * init_memory_mapping reaches the pagetable pages area, it maps
+	 * RO all the pagetable pages, including the ones that are beyond
+	 * pgt_buf_end at that time.
+	 */
+	if (!after_bootmem && pgt_buf_end > pgt_buf_start)
+		x86_init.mapping.pagetable_reserve(PFN_PHYS(pgt_buf_start),
+				PFN_PHYS(pgt_buf_end));
 
 	if (!after_bootmem)
 		early_memtest(start, end);
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/Makefile linux-libre-2.6.39-gnu/arch/x86/mm/Makefile
--- linux-libre-2.6.38-gnu/arch/x86/mm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 obj-$(CONFIG_NUMA)		+= numa.o numa_$(BITS).o
 obj-$(CONFIG_AMD_NUMA)		+= amdtopology_64.o
 obj-$(CONFIG_ACPI_NUMA)		+= srat_$(BITS).o
+obj-$(CONFIG_NUMA_EMU)		+= numa_emulation.o
 
 obj-$(CONFIG_HAVE_MEMBLOCK)		+= memblock.o
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/numa_32.c linux-libre-2.6.39-gnu/arch/x86/mm/numa_32.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/numa_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/numa_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,6 +110,12 @@
 
 static unsigned long kva_start_pfn;
 static unsigned long kva_pages;
+
+int __cpuinit numa_cpu_node(int cpu)
+{
+	return apic->x86_32_numa_cpu_node(cpu);
+}
+
 /*
  * FLAT - support for basic PC memory model with discontig enabled, essentially
  *        a single node with all available processors in it with a flat
@@ -346,8 +352,7 @@
 		(ulong) node_remap_end_vaddr[nid]);
 }
 
-void __init initmem_init(unsigned long start_pfn, unsigned long end_pfn,
-				int acpi, int k8)
+void __init initmem_init(void)
 {
 	int nid;
 	long kva_target_pfn;
@@ -361,6 +366,7 @@
 	 */
 
 	get_memcfg_numa();
+	numa_init_array();
 
 	kva_pages = roundup(calculate_numa_remap_pages(), PTRS_PER_PTE);
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/numa_64.c linux-libre-2.6.39-gnu/arch/x86/mm/numa_64.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/numa_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/numa_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,31 +13,30 @@
 #include <linux/module.h>
 #include <linux/nodemask.h>
 #include <linux/sched.h>
+#include <linux/acpi.h>
 
 #include <asm/e820.h>
 #include <asm/proto.h>
 #include <asm/dma.h>
-#include <asm/numa.h>
 #include <asm/acpi.h>
 #include <asm/amd_nb.h>
 
+#include "numa_internal.h"
+
 struct pglist_data *node_data[MAX_NUMNODES] __read_mostly;
 EXPORT_SYMBOL(node_data);
 
-struct memnode memnode;
+nodemask_t numa_nodes_parsed __initdata;
 
-s16 apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
-	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
-};
+struct memnode memnode;
 
 static unsigned long __initdata nodemap_addr;
 static unsigned long __initdata nodemap_size;
 
-/*
- * Map cpu index to node index
- */
-DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE);
-EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map);
+static struct numa_meminfo numa_meminfo __initdata;
+
+static int numa_distance_cnt;
+static u8 *numa_distance;
 
 /*
  * Given a shift value, try to populate memnodemap[]
@@ -46,16 +45,15 @@
  * 0 if memnodmap[] too small (of shift too small)
  * -1 if node overlap or lost ram (shift too big)
  */
-static int __init populate_memnodemap(const struct bootnode *nodes,
-				      int numnodes, int shift, int *nodeids)
+static int __init populate_memnodemap(const struct numa_meminfo *mi, int shift)
 {
 	unsigned long addr, end;
 	int i, res = -1;
 
 	memset(memnodemap, 0xff, sizeof(s16)*memnodemapsize);
-	for (i = 0; i < numnodes; i++) {
-		addr = nodes[i].start;
-		end = nodes[i].end;
+	for (i = 0; i < mi->nr_blks; i++) {
+		addr = mi->blk[i].start;
+		end = mi->blk[i].end;
 		if (addr >= end)
 			continue;
 		if ((end >> shift) >= memnodemapsize)
@@ -63,12 +61,7 @@
 		do {
 			if (memnodemap[addr >> shift] != NUMA_NO_NODE)
 				return -1;
-
-			if (!nodeids)
-				memnodemap[addr >> shift] = i;
-			else
-				memnodemap[addr >> shift] = nodeids[i];
-
+			memnodemap[addr >> shift] = mi->blk[i].nid;
 			addr += (1UL << shift);
 		} while (addr < end);
 		res = 1;
@@ -86,7 +79,7 @@
 
 	addr = 0x8000;
 	nodemap_size = roundup(sizeof(s16) * memnodemapsize, L1_CACHE_BYTES);
-	nodemap_addr = memblock_find_in_range(addr, max_pfn<<PAGE_SHIFT,
+	nodemap_addr = memblock_find_in_range(addr, get_max_mapped(),
 				      nodemap_size, L1_CACHE_BYTES);
 	if (nodemap_addr == MEMBLOCK_ERROR) {
 		printk(KERN_ERR
@@ -106,16 +99,15 @@
  * The LSB of all start and end addresses in the node map is the value of the
  * maximum possible shift.
  */
-static int __init extract_lsb_from_nodes(const struct bootnode *nodes,
-					 int numnodes)
+static int __init extract_lsb_from_nodes(const struct numa_meminfo *mi)
 {
 	int i, nodes_used = 0;
 	unsigned long start, end;
 	unsigned long bitfield = 0, memtop = 0;
 
-	for (i = 0; i < numnodes; i++) {
-		start = nodes[i].start;
-		end = nodes[i].end;
+	for (i = 0; i < mi->nr_blks; i++) {
+		start = mi->blk[i].start;
+		end = mi->blk[i].end;
 		if (start >= end)
 			continue;
 		bitfield |= start;
@@ -131,18 +123,17 @@
 	return i;
 }
 
-int __init compute_hash_shift(struct bootnode *nodes, int numnodes,
-			      int *nodeids)
+static int __init compute_hash_shift(const struct numa_meminfo *mi)
 {
 	int shift;
 
-	shift = extract_lsb_from_nodes(nodes, numnodes);
+	shift = extract_lsb_from_nodes(mi);
 	if (allocate_cachealigned_memnodemap())
 		return -1;
 	printk(KERN_DEBUG "NUMA: Using %d for the hash shift.\n",
 		shift);
 
-	if (populate_memnodemap(nodes, numnodes, shift, nodeids) != 1) {
+	if (populate_memnodemap(mi, shift) != 1) {
 		printk(KERN_INFO "Your memory is not aligned you need to "
 		       "rebuild your kernel with a bigger NODEMAPSIZE "
 		       "shift=%d\n", shift);
@@ -188,6 +179,63 @@
 	return NULL;
 }
 
+static int __init numa_add_memblk_to(int nid, u64 start, u64 end,
+				     struct numa_meminfo *mi)
+{
+	/* ignore zero length blks */
+	if (start == end)
+		return 0;
+
+	/* whine about and ignore invalid blks */
+	if (start > end || nid < 0 || nid >= MAX_NUMNODES) {
+		pr_warning("NUMA: Warning: invalid memblk node %d (%Lx-%Lx)\n",
+			   nid, start, end);
+		return 0;
+	}
+
+	if (mi->nr_blks >= NR_NODE_MEMBLKS) {
+		pr_err("NUMA: too many memblk ranges\n");
+		return -EINVAL;
+	}
+
+	mi->blk[mi->nr_blks].start = start;
+	mi->blk[mi->nr_blks].end = end;
+	mi->blk[mi->nr_blks].nid = nid;
+	mi->nr_blks++;
+	return 0;
+}
+
+/**
+ * numa_remove_memblk_from - Remove one numa_memblk from a numa_meminfo
+ * @idx: Index of memblk to remove
+ * @mi: numa_meminfo to remove memblk from
+ *
+ * Remove @idx'th numa_memblk from @mi by shifting @mi->blk[] and
+ * decrementing @mi->nr_blks.
+ */
+void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi)
+{
+	mi->nr_blks--;
+	memmove(&mi->blk[idx], &mi->blk[idx + 1],
+		(mi->nr_blks - idx) * sizeof(mi->blk[0]));
+}
+
+/**
+ * numa_add_memblk - Add one numa_memblk to numa_meminfo
+ * @nid: NUMA node ID of the new memblk
+ * @start: Start address of the new memblk
+ * @end: End address of the new memblk
+ *
+ * Add a new memblk to the default numa_meminfo.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
+ */
+int __init numa_add_memblk(int nid, u64 start, u64 end)
+{
+	return numa_add_memblk_to(nid, start, end, &numa_meminfo);
+}
+
 /* Initialize bootmem allocator for a node */
 void __init
 setup_node_bootmem(int nodeid, unsigned long start, unsigned long end)
@@ -234,692 +282,386 @@
 	node_set_online(nodeid);
 }
 
-/*
- * There are unfortunately some poorly designed mainboards around that
- * only connect memory to a single CPU. This breaks the 1:1 cpu->node
- * mapping. To avoid this fill in the mapping for all possible CPUs,
- * as the number of CPUs is not known yet. We round robin the existing
- * nodes.
+/**
+ * numa_cleanup_meminfo - Cleanup a numa_meminfo
+ * @mi: numa_meminfo to clean up
+ *
+ * Sanitize @mi by merging and removing unncessary memblks.  Also check for
+ * conflicts and clear unused memblks.
+ *
+ * RETURNS:
+ * 0 on success, -errno on failure.
  */
-void __init numa_init_array(void)
+int __init numa_cleanup_meminfo(struct numa_meminfo *mi)
 {
-	int rr, i;
-
-	rr = first_node(node_online_map);
-	for (i = 0; i < nr_cpu_ids; i++) {
-		if (early_cpu_to_node(i) != NUMA_NO_NODE)
-			continue;
-		numa_set_node(i, rr);
-		rr = next_node(rr, node_online_map);
-		if (rr == MAX_NUMNODES)
-			rr = first_node(node_online_map);
-	}
-}
-
-#ifdef CONFIG_NUMA_EMU
-/* Numa emulation */
-static struct bootnode nodes[MAX_NUMNODES] __initdata;
-static struct bootnode physnodes[MAX_NUMNODES] __cpuinitdata;
-static char *cmdline __initdata;
+	const u64 low = 0;
+	const u64 high = (u64)max_pfn << PAGE_SHIFT;
+	int i, j, k;
 
-void __init numa_emu_cmdline(char *str)
-{
-	cmdline = str;
-}
+	for (i = 0; i < mi->nr_blks; i++) {
+		struct numa_memblk *bi = &mi->blk[i];
 
-static int __init setup_physnodes(unsigned long start, unsigned long end,
-					int acpi, int amd)
-{
-	int ret = 0;
-	int i;
+		/* make sure all blocks are inside the limits */
+		bi->start = max(bi->start, low);
+		bi->end = min(bi->end, high);
 
-	memset(physnodes, 0, sizeof(physnodes));
-#ifdef CONFIG_ACPI_NUMA
-	if (acpi)
-		acpi_get_nodes(physnodes, start, end);
-#endif
-#ifdef CONFIG_AMD_NUMA
-	if (amd)
-		amd_get_nodes(physnodes);
-#endif
-	/*
-	 * Basic sanity checking on the physical node map: there may be errors
-	 * if the SRAT or AMD code incorrectly reported the topology or the mem=
-	 * kernel parameter is used.
-	 */
-	for (i = 0; i < MAX_NUMNODES; i++) {
-		if (physnodes[i].start == physnodes[i].end)
-			continue;
-		if (physnodes[i].start > end) {
-			physnodes[i].end = physnodes[i].start;
-			continue;
-		}
-		if (physnodes[i].end < start) {
-			physnodes[i].start = physnodes[i].end;
+		/* and there's no empty block */
+		if (bi->start >= bi->end) {
+			numa_remove_memblk_from(i--, mi);
 			continue;
 		}
-		if (physnodes[i].start < start)
-			physnodes[i].start = start;
-		if (physnodes[i].end > end)
-			physnodes[i].end = end;
-		ret++;
-	}
 
-	/*
-	 * If no physical topology was detected, a single node is faked to cover
-	 * the entire address space.
-	 */
-	if (!ret) {
-		physnodes[ret].start = start;
-		physnodes[ret].end = end;
-		ret = 1;
-	}
-	return ret;
-}
-
-static void __init fake_physnodes(int acpi, int amd, int nr_nodes)
-{
-	int i;
-
-	BUG_ON(acpi && amd);
-#ifdef CONFIG_ACPI_NUMA
-	if (acpi)
-		acpi_fake_nodes(nodes, nr_nodes);
-#endif
-#ifdef CONFIG_AMD_NUMA
-	if (amd)
-		amd_fake_nodes(nodes, nr_nodes);
-#endif
-	if (!acpi && !amd)
-		for (i = 0; i < nr_cpu_ids; i++)
-			numa_set_node(i, 0);
-}
-
-/*
- * Setups up nid to range from addr to addr + size.  If the end
- * boundary is greater than max_addr, then max_addr is used instead.
- * The return value is 0 if there is additional memory left for
- * allocation past addr and -1 otherwise.  addr is adjusted to be at
- * the end of the node.
- */
-static int __init setup_node_range(int nid, u64 *addr, u64 size, u64 max_addr)
-{
-	int ret = 0;
-	nodes[nid].start = *addr;
-	*addr += size;
-	if (*addr >= max_addr) {
-		*addr = max_addr;
-		ret = -1;
-	}
-	nodes[nid].end = *addr;
-	node_set(nid, node_possible_map);
-	printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
-	       nodes[nid].start, nodes[nid].end,
-	       (nodes[nid].end - nodes[nid].start) >> 20);
-	return ret;
-}
-
-/*
- * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr
- * to max_addr.  The return value is the number of nodes allocated.
- */
-static int __init split_nodes_interleave(u64 addr, u64 max_addr, int nr_nodes)
-{
-	nodemask_t physnode_mask = NODE_MASK_NONE;
-	u64 size;
-	int big;
-	int ret = 0;
-	int i;
-
-	if (nr_nodes <= 0)
-		return -1;
-	if (nr_nodes > MAX_NUMNODES) {
-		pr_info("numa=fake=%d too large, reducing to %d\n",
-			nr_nodes, MAX_NUMNODES);
-		nr_nodes = MAX_NUMNODES;
-	}
-
-	size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
-	/*
-	 * Calculate the number of big nodes that can be allocated as a result
-	 * of consolidating the remainder.
-	 */
-	big = ((size & ~FAKE_NODE_MIN_HASH_MASK) * nr_nodes) /
-		FAKE_NODE_MIN_SIZE;
-
-	size &= FAKE_NODE_MIN_HASH_MASK;
-	if (!size) {
-		pr_err("Not enough memory for each node.  "
-			"NUMA emulation disabled.\n");
-		return -1;
-	}
-
-	for (i = 0; i < MAX_NUMNODES; i++)
-		if (physnodes[i].start != physnodes[i].end)
-			node_set(i, physnode_mask);
-
-	/*
-	 * Continue to fill physical nodes with fake nodes until there is no
-	 * memory left on any of them.
-	 */
-	while (nodes_weight(physnode_mask)) {
-		for_each_node_mask(i, physnode_mask) {
-			u64 end = physnodes[i].start + size;
-			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
-
-			if (ret < big)
-				end += FAKE_NODE_MIN_SIZE;
+		for (j = i + 1; j < mi->nr_blks; j++) {
+			struct numa_memblk *bj = &mi->blk[j];
+			unsigned long start, end;
 
 			/*
-			 * Continue to add memory to this fake node if its
-			 * non-reserved memory is less than the per-node size.
+			 * See whether there are overlapping blocks.  Whine
+			 * about but allow overlaps of the same nid.  They
+			 * will be merged below.
 			 */
-			while (end - physnodes[i].start -
-				memblock_x86_hole_size(physnodes[i].start, end) < size) {
-				end += FAKE_NODE_MIN_SIZE;
-				if (end > physnodes[i].end) {
-					end = physnodes[i].end;
-					break;
+			if (bi->end > bj->start && bi->start < bj->end) {
+				if (bi->nid != bj->nid) {
+					pr_err("NUMA: node %d (%Lx-%Lx) overlaps with node %d (%Lx-%Lx)\n",
+					       bi->nid, bi->start, bi->end,
+					       bj->nid, bj->start, bj->end);
+					return -EINVAL;
 				}
+				pr_warning("NUMA: Warning: node %d (%Lx-%Lx) overlaps with itself (%Lx-%Lx)\n",
+					   bi->nid, bi->start, bi->end,
+					   bj->start, bj->end);
 			}
 
 			/*
-			 * If there won't be at least FAKE_NODE_MIN_SIZE of
-			 * non-reserved memory in ZONE_DMA32 for the next node,
-			 * this one must extend to the boundary.
-			 */
-			if (end < dma32_end && dma32_end - end -
-			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
-				end = dma32_end;
-
-			/*
-			 * If there won't be enough non-reserved memory for the
-			 * next node, this one must extend to the end of the
-			 * physical node.
-			 */
-			if (physnodes[i].end - end -
-			    memblock_x86_hole_size(end, physnodes[i].end) < size)
-				end = physnodes[i].end;
-
-			/*
-			 * Avoid allocating more nodes than requested, which can
-			 * happen as a result of rounding down each node's size
-			 * to FAKE_NODE_MIN_SIZE.
+			 * Join together blocks on the same node, holes
+			 * between which don't overlap with memory on other
+			 * nodes.
 			 */
-			if (nodes_weight(physnode_mask) + ret >= nr_nodes)
-				end = physnodes[i].end;
+			if (bi->nid != bj->nid)
+				continue;
+			start = max(min(bi->start, bj->start), low);
+			end = min(max(bi->end, bj->end), high);
+			for (k = 0; k < mi->nr_blks; k++) {
+				struct numa_memblk *bk = &mi->blk[k];
 
-			if (setup_node_range(ret++, &physnodes[i].start,
-						end - physnodes[i].start,
-						physnodes[i].end) < 0)
-				node_clear(i, physnode_mask);
+				if (bi->nid == bk->nid)
+					continue;
+				if (start < bk->end && end > bk->start)
+					break;
+			}
+			if (k < mi->nr_blks)
+				continue;
+			printk(KERN_INFO "NUMA: Node %d [%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
+			       bi->nid, bi->start, bi->end, bj->start, bj->end,
+			       start, end);
+			bi->start = start;
+			bi->end = end;
+			numa_remove_memblk_from(j--, mi);
 		}
 	}
-	return ret;
-}
-
-/*
- * Returns the end address of a node so that there is at least `size' amount of
- * non-reserved memory or `max_addr' is reached.
- */
-static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
-{
-	u64 end = start + size;
 
-	while (end - start - memblock_x86_hole_size(start, end) < size) {
-		end += FAKE_NODE_MIN_SIZE;
-		if (end > max_addr) {
-			end = max_addr;
-			break;
-		}
+	for (i = mi->nr_blks; i < ARRAY_SIZE(mi->blk); i++) {
+		mi->blk[i].start = mi->blk[i].end = 0;
+		mi->blk[i].nid = NUMA_NO_NODE;
 	}
-	return end;
+
+	return 0;
 }
 
 /*
- * Sets up fake nodes of `size' interleaved over physical nodes ranging from
- * `addr' to `max_addr'.  The return value is the number of nodes allocated.
+ * Set nodes, which have memory in @mi, in *@nodemask.
  */
-static int __init split_nodes_size_interleave(u64 addr, u64 max_addr, u64 size)
+static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask,
+					      const struct numa_meminfo *mi)
 {
-	nodemask_t physnode_mask = NODE_MASK_NONE;
-	u64 min_size;
-	int ret = 0;
 	int i;
 
-	if (!size)
-		return -1;
-	/*
-	 * The limit on emulated nodes is MAX_NUMNODES, so the size per node is
-	 * increased accordingly if the requested size is too small.  This
-	 * creates a uniform distribution of node sizes across the entire
-	 * machine (but not necessarily over physical nodes).
-	 */
-	min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
-						MAX_NUMNODES;
-	min_size = max(min_size, FAKE_NODE_MIN_SIZE);
-	if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
-		min_size = (min_size + FAKE_NODE_MIN_SIZE) &
-						FAKE_NODE_MIN_HASH_MASK;
-	if (size < min_size) {
-		pr_err("Fake node size %LuMB too small, increasing to %LuMB\n",
-			size >> 20, min_size >> 20);
-		size = min_size;
-	}
-	size &= FAKE_NODE_MIN_HASH_MASK;
-
-	for (i = 0; i < MAX_NUMNODES; i++)
-		if (physnodes[i].start != physnodes[i].end)
-			node_set(i, physnode_mask);
-	/*
-	 * Fill physical nodes with fake nodes of size until there is no memory
-	 * left on any of them.
-	 */
-	while (nodes_weight(physnode_mask)) {
-		for_each_node_mask(i, physnode_mask) {
-			u64 dma32_end = MAX_DMA32_PFN << PAGE_SHIFT;
-			u64 end;
-
-			end = find_end_of_node(physnodes[i].start,
-						physnodes[i].end, size);
-			/*
-			 * If there won't be at least FAKE_NODE_MIN_SIZE of
-			 * non-reserved memory in ZONE_DMA32 for the next node,
-			 * this one must extend to the boundary.
-			 */
-			if (end < dma32_end && dma32_end - end -
-			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
-				end = dma32_end;
+	for (i = 0; i < ARRAY_SIZE(mi->blk); i++)
+		if (mi->blk[i].start != mi->blk[i].end &&
+		    mi->blk[i].nid != NUMA_NO_NODE)
+			node_set(mi->blk[i].nid, *nodemask);
+}
 
-			/*
-			 * If there won't be enough non-reserved memory for the
-			 * next node, this one must extend to the end of the
-			 * physical node.
-			 */
-			if (physnodes[i].end - end -
-			    memblock_x86_hole_size(end, physnodes[i].end) < size)
-				end = physnodes[i].end;
+/**
+ * numa_reset_distance - Reset NUMA distance table
+ *
+ * The current table is freed.  The next numa_set_distance() call will
+ * create a new one.
+ */
+void __init numa_reset_distance(void)
+{
+	size_t size = numa_distance_cnt * numa_distance_cnt * sizeof(numa_distance[0]);
 
-			/*
-			 * Setup the fake node that will be allocated as bootmem
-			 * later.  If setup_node_range() returns non-zero, there
-			 * is no more memory available on this physical node.
-			 */
-			if (setup_node_range(ret++, &physnodes[i].start,
-						end - physnodes[i].start,
-						physnodes[i].end) < 0)
-				node_clear(i, physnode_mask);
-		}
-	}
-	return ret;
+	/* numa_distance could be 1LU marking allocation failure, test cnt */
+	if (numa_distance_cnt)
+		memblock_x86_free_range(__pa(numa_distance),
+					__pa(numa_distance) + size);
+	numa_distance_cnt = 0;
+	numa_distance = NULL;	/* enable table creation */
 }
 
-/*
- * Sets up the system RAM area from start_pfn to last_pfn according to the
- * numa=fake command-line option.
- */
-static int __init numa_emulation(unsigned long start_pfn,
-			unsigned long last_pfn, int acpi, int amd)
+static int __init numa_alloc_distance(void)
 {
-	u64 addr = start_pfn << PAGE_SHIFT;
-	u64 max_addr = last_pfn << PAGE_SHIFT;
-	int num_nodes;
-	int i;
+	nodemask_t nodes_parsed;
+	size_t size;
+	int i, j, cnt = 0;
+	u64 phys;
 
-	/*
-	 * If the numa=fake command-line contains a 'M' or 'G', it represents
-	 * the fixed node size.  Otherwise, if it is just a single number N,
-	 * split the system RAM into N fake nodes.
-	 */
-	if (strchr(cmdline, 'M') || strchr(cmdline, 'G')) {
-		u64 size;
+	/* size the new table and allocate it */
+	nodes_parsed = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&nodes_parsed, &numa_meminfo);
 
-		size = memparse(cmdline, &cmdline);
-		num_nodes = split_nodes_size_interleave(addr, max_addr, size);
-	} else {
-		unsigned long n;
+	for_each_node_mask(i, nodes_parsed)
+		cnt = i;
+	cnt++;
+	size = cnt * cnt * sizeof(numa_distance[0]);
 
-		n = simple_strtoul(cmdline, NULL, 0);
-		num_nodes = split_nodes_interleave(addr, max_addr, n);
+	phys = memblock_find_in_range(0, (u64)max_pfn_mapped << PAGE_SHIFT,
+				      size, PAGE_SIZE);
+	if (phys == MEMBLOCK_ERROR) {
+		pr_warning("NUMA: Warning: can't allocate distance table!\n");
+		/* don't retry until explicitly reset */
+		numa_distance = (void *)1LU;
+		return -ENOMEM;
 	}
+	memblock_x86_reserve_range(phys, phys + size, "NUMA DIST");
 
-	if (num_nodes < 0)
-		return num_nodes;
-	memnode_shift = compute_hash_shift(nodes, num_nodes, NULL);
-	if (memnode_shift < 0) {
-		memnode_shift = 0;
-		printk(KERN_ERR "No NUMA hash function found.  NUMA emulation "
-		       "disabled.\n");
-		return -1;
-	}
+	numa_distance = __va(phys);
+	numa_distance_cnt = cnt;
+
+	/* fill with the default distances */
+	for (i = 0; i < cnt; i++)
+		for (j = 0; j < cnt; j++)
+			numa_distance[i * cnt + j] = i == j ?
+				LOCAL_DISTANCE : REMOTE_DISTANCE;
+	printk(KERN_DEBUG "NUMA: Initialized distance table, cnt=%d\n", cnt);
 
-	/*
-	 * We need to vacate all active ranges that may have been registered for
-	 * the e820 memory map.
-	 */
-	remove_all_active_ranges();
-	for_each_node_mask(i, node_possible_map) {
-		memblock_x86_register_active_regions(i, nodes[i].start >> PAGE_SHIFT,
-						nodes[i].end >> PAGE_SHIFT);
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	}
-	setup_physnodes(addr, max_addr, acpi, amd);
-	fake_physnodes(acpi, amd, num_nodes);
-	numa_init_array();
 	return 0;
 }
-#endif /* CONFIG_NUMA_EMU */
 
-void __init initmem_init(unsigned long start_pfn, unsigned long last_pfn,
-				int acpi, int amd)
+/**
+ * numa_set_distance - Set NUMA distance from one NUMA to another
+ * @from: the 'from' node to set distance
+ * @to: the 'to'  node to set distance
+ * @distance: NUMA distance
+ *
+ * Set the distance from node @from to @to to @distance.  If distance table
+ * doesn't exist, one which is large enough to accommodate all the currently
+ * known nodes will be created.
+ *
+ * If such table cannot be allocated, a warning is printed and further
+ * calls are ignored until the distance table is reset with
+ * numa_reset_distance().
+ *
+ * If @from or @to is higher than the highest known node at the time of
+ * table creation or @distance doesn't make sense, the call is ignored.
+ * This is to allow simplification of specific NUMA config implementations.
+ */
+void __init numa_set_distance(int from, int to, int distance)
 {
-	int i;
-
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-
-#ifdef CONFIG_NUMA_EMU
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
-	if (cmdline && !numa_emulation(start_pfn, last_pfn, acpi, amd))
+	if (!numa_distance && numa_alloc_distance() < 0)
 		return;
-	setup_physnodes(start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT,
-			acpi, amd);
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
 
-#ifdef CONFIG_ACPI_NUMA
-	if (!numa_off && acpi && !acpi_scan_nodes(start_pfn << PAGE_SHIFT,
-						  last_pfn << PAGE_SHIFT))
+	if (from >= numa_distance_cnt || to >= numa_distance_cnt) {
+		printk_once(KERN_DEBUG "NUMA: Debug: distance out of bound, from=%d to=%d distance=%d\n",
+			    from, to, distance);
 		return;
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
+	}
 
-#ifdef CONFIG_AMD_NUMA
-	if (!numa_off && amd && !amd_scan_nodes())
+	if ((u8)distance != distance ||
+	    (from == to && distance != LOCAL_DISTANCE)) {
+		pr_warn_once("NUMA: Warning: invalid distance parameter, from=%d to=%d distance=%d\n",
+			     from, to, distance);
 		return;
-	nodes_clear(node_possible_map);
-	nodes_clear(node_online_map);
-#endif
-	printk(KERN_INFO "%s\n",
-	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
+	}
 
-	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
-	       start_pfn << PAGE_SHIFT,
-	       last_pfn << PAGE_SHIFT);
-	/* setup dummy node covering all memory */
-	memnode_shift = 63;
-	memnodemap = memnode.embedded_map;
-	memnodemap[0] = 0;
-	node_set_online(0);
-	node_set(0, node_possible_map);
-	for (i = 0; i < nr_cpu_ids; i++)
-		numa_set_node(i, 0);
-	memblock_x86_register_active_regions(0, start_pfn, last_pfn);
-	setup_node_bootmem(0, start_pfn << PAGE_SHIFT, last_pfn << PAGE_SHIFT);
+	numa_distance[from * numa_distance_cnt + to] = distance;
 }
 
-unsigned long __init numa_free_all_bootmem(void)
+int __node_distance(int from, int to)
 {
-	unsigned long pages = 0;
-	int i;
-
-	for_each_online_node(i)
-		pages += free_all_bootmem_node(NODE_DATA(i));
-
-	pages += free_all_memory_core_early(MAX_NUMNODES);
-
-	return pages;
+	if (from >= numa_distance_cnt || to >= numa_distance_cnt)
+		return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
+	return numa_distance[from * numa_distance_cnt + to];
 }
+EXPORT_SYMBOL(__node_distance);
 
-#ifdef CONFIG_NUMA
-
-static __init int find_near_online_node(int node)
+/*
+ * Sanity check to catch more bad NUMA configurations (they are amazingly
+ * common).  Make sure the nodes cover all memory.
+ */
+static bool __init numa_meminfo_cover_memory(const struct numa_meminfo *mi)
 {
-	int n, val;
-	int min_val = INT_MAX;
-	int best_node = -1;
-
-	for_each_online_node(n) {
-		val = node_distance(node, n);
+	unsigned long numaram, e820ram;
+	int i;
 
-		if (val < min_val) {
-			min_val = val;
-			best_node = n;
-		}
+	numaram = 0;
+	for (i = 0; i < mi->nr_blks; i++) {
+		unsigned long s = mi->blk[i].start >> PAGE_SHIFT;
+		unsigned long e = mi->blk[i].end >> PAGE_SHIFT;
+		numaram += e - s;
+		numaram -= __absent_pages_in_range(mi->blk[i].nid, s, e);
+		if ((long)numaram < 0)
+			numaram = 0;
 	}
 
-	return best_node;
+	e820ram = max_pfn - (memblock_x86_hole_size(0,
+					max_pfn << PAGE_SHIFT) >> PAGE_SHIFT);
+	/* We seem to lose 3 pages somewhere. Allow 1M of slack. */
+	if ((long)(e820ram - numaram) >= (1 << (20 - PAGE_SHIFT))) {
+		printk(KERN_ERR "NUMA: nodes only cover %luMB of your %luMB e820 RAM. Not used.\n",
+		       (numaram << PAGE_SHIFT) >> 20,
+		       (e820ram << PAGE_SHIFT) >> 20);
+		return false;
+	}
+	return true;
 }
 
-/*
- * Setup early cpu_to_node.
- *
- * Populate cpu_to_node[] only if x86_cpu_to_apicid[],
- * and apicid_to_node[] tables have valid entries for a CPU.
- * This means we skip cpu_to_node[] initialisation for NUMA
- * emulation and faking node case (when running a kernel compiled
- * for NUMA on a non NUMA box), which is OK as cpu_to_node[]
- * is already initialized in a round robin manner at numa_init_array,
- * prior to this call, and this initialization is good enough
- * for the fake NUMA cases.
- *
- * Called before the per_cpu areas are setup.
- */
-void __init init_cpu_to_node(void)
+static int __init numa_register_memblks(struct numa_meminfo *mi)
 {
-	int cpu;
-	u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
-
-	BUG_ON(cpu_to_apicid == NULL);
+	int i, nid;
 
-	for_each_possible_cpu(cpu) {
-		int node;
-		u16 apicid = cpu_to_apicid[cpu];
+	/* Account for nodes with cpus and no memory */
+	node_possible_map = numa_nodes_parsed;
+	numa_nodemask_from_meminfo(&node_possible_map, mi);
+	if (WARN_ON(nodes_empty(node_possible_map)))
+		return -EINVAL;
 
-		if (apicid == BAD_APICID)
-			continue;
-		node = apicid_to_node[apicid];
-		if (node == NUMA_NO_NODE)
-			continue;
-		if (!node_online(node))
-			node = find_near_online_node(node);
-		numa_set_node(cpu, node);
+	memnode_shift = compute_hash_shift(mi);
+	if (memnode_shift < 0) {
+		printk(KERN_ERR "NUMA: No NUMA node hash function found. Contact maintainer\n");
+		return -EINVAL;
 	}
-}
-#endif
 
+	for (i = 0; i < mi->nr_blks; i++)
+		memblock_x86_register_active_regions(mi->blk[i].nid,
+					mi->blk[i].start >> PAGE_SHIFT,
+					mi->blk[i].end >> PAGE_SHIFT);
 
-void __cpuinit numa_set_node(int cpu, int node)
-{
-	int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map);
+	/* for out of order entries */
+	sort_node_map();
+	if (!numa_meminfo_cover_memory(mi))
+		return -EINVAL;
 
-	/* early setting, no percpu area yet */
-	if (cpu_to_node_map) {
-		cpu_to_node_map[cpu] = node;
-		return;
-	}
+	/* Finally register nodes. */
+	for_each_node_mask(nid, node_possible_map) {
+		u64 start = (u64)max_pfn << PAGE_SHIFT;
+		u64 end = 0;
 
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
-	if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
-		printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu);
-		dump_stack();
-		return;
+		for (i = 0; i < mi->nr_blks; i++) {
+			if (nid != mi->blk[i].nid)
+				continue;
+			start = min(mi->blk[i].start, start);
+			end = max(mi->blk[i].end, end);
+		}
+
+		if (start < end)
+			setup_node_bootmem(nid, start, end);
 	}
-#endif
-	per_cpu(x86_cpu_to_node_map, cpu) = node;
 
-	if (node != NUMA_NO_NODE)
-		set_cpu_numa_node(cpu, node);
+	return 0;
 }
 
-void __cpuinit numa_clear_node(int cpu)
+/**
+ * dummy_numma_init - Fallback dummy NUMA init
+ *
+ * Used if there's no underlying NUMA architecture, NUMA initialization
+ * fails, or NUMA is disabled on the command line.
+ *
+ * Must online at least one node and add memory blocks that cover all
+ * allowed memory.  This function must not fail.
+ */
+static int __init dummy_numa_init(void)
 {
-	numa_set_node(cpu, NUMA_NO_NODE);
-}
+	printk(KERN_INFO "%s\n",
+	       numa_off ? "NUMA turned off" : "No NUMA configuration found");
+	printk(KERN_INFO "Faking a node at %016lx-%016lx\n",
+	       0LU, max_pfn << PAGE_SHIFT);
 
-#ifndef CONFIG_DEBUG_PER_CPU_MAPS
+	node_set(0, numa_nodes_parsed);
+	numa_add_memblk(0, 0, (u64)max_pfn << PAGE_SHIFT);
 
-#ifndef CONFIG_NUMA_EMU
-void __cpuinit numa_add_cpu(int cpu)
-{
-	cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
+	return 0;
 }
 
-void __cpuinit numa_remove_cpu(int cpu)
-{
-	cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
-}
-#else
-void __cpuinit numa_add_cpu(int cpu)
+static int __init numa_init(int (*init_func)(void))
 {
-	unsigned long addr;
-	u16 apicid;
-	int physnid;
-	int nid = NUMA_NO_NODE;
+	int i;
+	int ret;
 
-	nid = early_cpu_to_node(cpu);
-	BUG_ON(nid == NUMA_NO_NODE || !node_online(nid));
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		set_apicid_to_node(i, NUMA_NO_NODE);
 
-	/*
-	 * Use the starting address of the emulated node to find which physical
-	 * node it is allocated on.
-	 */
-	addr = node_start_pfn(nid) << PAGE_SHIFT;
-	for (physnid = 0; physnid < MAX_NUMNODES; physnid++)
-		if (addr >= physnodes[physnid].start &&
-		    addr < physnodes[physnid].end)
-			break;
+	nodes_clear(numa_nodes_parsed);
+	nodes_clear(node_possible_map);
+	nodes_clear(node_online_map);
+	memset(&numa_meminfo, 0, sizeof(numa_meminfo));
+	remove_all_active_ranges();
+	numa_reset_distance();
 
-	/*
-	 * Map the cpu to each emulated node that is allocated on the physical
-	 * node of the cpu's apic id.
-	 */
-	for_each_online_node(nid) {
-		addr = node_start_pfn(nid) << PAGE_SHIFT;
-		if (addr >= physnodes[physnid].start &&
-		    addr < physnodes[physnid].end)
-			cpumask_set_cpu(cpu, node_to_cpumask_map[nid]);
-	}
-}
+	ret = init_func();
+	if (ret < 0)
+		return ret;
+	ret = numa_cleanup_meminfo(&numa_meminfo);
+	if (ret < 0)
+		return ret;
 
-void __cpuinit numa_remove_cpu(int cpu)
-{
-	int i;
+	numa_emulation(&numa_meminfo, numa_distance_cnt);
 
-	for_each_online_node(i)
-		cpumask_clear_cpu(cpu, node_to_cpumask_map[i]);
-}
-#endif /* !CONFIG_NUMA_EMU */
+	ret = numa_register_memblks(&numa_meminfo);
+	if (ret < 0)
+		return ret;
 
-#else /* CONFIG_DEBUG_PER_CPU_MAPS */
-static struct cpumask __cpuinit *debug_cpumask_set_cpu(int cpu, int enable)
-{
-	int node = early_cpu_to_node(cpu);
-	struct cpumask *mask;
-	char buf[64];
+	for (i = 0; i < nr_cpu_ids; i++) {
+		int nid = early_cpu_to_node(i);
 
-	mask = node_to_cpumask_map[node];
-	if (!mask) {
-		pr_err("node_to_cpumask_map[%i] NULL\n", node);
-		dump_stack();
-		return NULL;
+		if (nid == NUMA_NO_NODE)
+			continue;
+		if (!node_online(nid))
+			numa_clear_node(i);
 	}
-
-	cpulist_scnprintf(buf, sizeof(buf), mask);
-	printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
-		enable ? "numa_add_cpu" : "numa_remove_cpu",
-		cpu, node, buf);
-	return mask;
+	numa_init_array();
+	return 0;
 }
 
-/*
- * --------- debug versions of the numa functions ---------
- */
-#ifndef CONFIG_NUMA_EMU
-static void __cpuinit numa_set_cpumask(int cpu, int enable)
-{
-	struct cpumask *mask;
-
-	mask = debug_cpumask_set_cpu(cpu, enable);
-	if (!mask)
-		return;
-
-	if (enable)
-		cpumask_set_cpu(cpu, mask);
-	else
-		cpumask_clear_cpu(cpu, mask);
-}
-#else
-static void __cpuinit numa_set_cpumask(int cpu, int enable)
+void __init initmem_init(void)
 {
-	int node = early_cpu_to_node(cpu);
-	struct cpumask *mask;
-	int i;
-
-	for_each_online_node(i) {
-		unsigned long addr;
+	int ret;
 
-		addr = node_start_pfn(i) << PAGE_SHIFT;
-		if (addr < physnodes[node].start ||
-					addr >= physnodes[node].end)
-			continue;
-		mask = debug_cpumask_set_cpu(cpu, enable);
-		if (!mask)
+	if (!numa_off) {
+#ifdef CONFIG_ACPI_NUMA
+		ret = numa_init(x86_acpi_numa_init);
+		if (!ret)
 			return;
-
-		if (enable)
-			cpumask_set_cpu(cpu, mask);
-		else
-			cpumask_clear_cpu(cpu, mask);
+#endif
+#ifdef CONFIG_AMD_NUMA
+		ret = numa_init(amd_numa_init);
+		if (!ret)
+			return;
+#endif
 	}
-}
-#endif /* CONFIG_NUMA_EMU */
 
-void __cpuinit numa_add_cpu(int cpu)
-{
-	numa_set_cpumask(cpu, 1);
+	numa_init(dummy_numa_init);
 }
 
-void __cpuinit numa_remove_cpu(int cpu)
+unsigned long __init numa_free_all_bootmem(void)
 {
-	numa_set_cpumask(cpu, 0);
-}
+	unsigned long pages = 0;
+	int i;
 
-int __cpu_to_node(int cpu)
-{
-	if (early_per_cpu_ptr(x86_cpu_to_node_map)) {
-		printk(KERN_WARNING
-			"cpu_to_node(%d): usage too early!\n", cpu);
-		dump_stack();
-		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
-	}
-	return per_cpu(x86_cpu_to_node_map, cpu);
-}
-EXPORT_SYMBOL(__cpu_to_node);
+	for_each_online_node(i)
+		pages += free_all_bootmem_node(NODE_DATA(i));
 
-/*
- * Same function as cpu_to_node() but used if called before the
- * per_cpu areas are setup.
- */
-int early_cpu_to_node(int cpu)
-{
-	if (early_per_cpu_ptr(x86_cpu_to_node_map))
-		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
+	pages += free_all_memory_core_early(MAX_NUMNODES);
 
-	if (!cpu_possible(cpu)) {
-		printk(KERN_WARNING
-			"early_cpu_to_node(%d): no per_cpu area!\n", cpu);
-		dump_stack();
-		return NUMA_NO_NODE;
-	}
-	return per_cpu(x86_cpu_to_node_map, cpu);
+	return pages;
 }
 
-/*
- * --------- end of debug versions of the numa functions ---------
- */
+int __cpuinit numa_cpu_node(int cpu)
+{
+	int apicid = early_per_cpu(x86_cpu_to_apicid, cpu);
 
-#endif /* CONFIG_DEBUG_PER_CPU_MAPS */
+	if (apicid != BAD_APICID)
+		return __apicid_to_node[apicid];
+	return NUMA_NO_NODE;
+}
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/numa.c linux-libre-2.6.39-gnu/arch/x86/mm/numa.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/numa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/numa.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,12 +26,50 @@
 early_param("numa", numa_setup);
 
 /*
- * Which logical CPUs are on which nodes
+ * apicid, cpu, node mappings
  */
+s16 __apicid_to_node[MAX_LOCAL_APIC] __cpuinitdata = {
+	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
+};
+
 cpumask_var_t node_to_cpumask_map[MAX_NUMNODES];
 EXPORT_SYMBOL(node_to_cpumask_map);
 
 /*
+ * Map cpu index to node index
+ */
+DEFINE_EARLY_PER_CPU(int, x86_cpu_to_node_map, NUMA_NO_NODE);
+EXPORT_EARLY_PER_CPU_SYMBOL(x86_cpu_to_node_map);
+
+void __cpuinit numa_set_node(int cpu, int node)
+{
+	int *cpu_to_node_map = early_per_cpu_ptr(x86_cpu_to_node_map);
+
+	/* early setting, no percpu area yet */
+	if (cpu_to_node_map) {
+		cpu_to_node_map[cpu] = node;
+		return;
+	}
+
+#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+	if (cpu >= nr_cpu_ids || !cpu_possible(cpu)) {
+		printk(KERN_ERR "numa_set_node: invalid cpu# (%d)\n", cpu);
+		dump_stack();
+		return;
+	}
+#endif
+	per_cpu(x86_cpu_to_node_map, cpu) = node;
+
+	if (node != NUMA_NO_NODE)
+		set_cpu_numa_node(cpu, node);
+}
+
+void __cpuinit numa_clear_node(int cpu)
+{
+	numa_set_node(cpu, NUMA_NO_NODE);
+}
+
+/*
  * Allocate node_to_cpumask_map based on number of available nodes
  * Requires node_possible_map to be valid.
  *
@@ -57,7 +95,169 @@
 	pr_debug("Node to cpumask map for %d nodes\n", nr_node_ids);
 }
 
-#ifdef CONFIG_DEBUG_PER_CPU_MAPS
+/*
+ * There are unfortunately some poorly designed mainboards around that
+ * only connect memory to a single CPU. This breaks the 1:1 cpu->node
+ * mapping. To avoid this fill in the mapping for all possible CPUs,
+ * as the number of CPUs is not known yet. We round robin the existing
+ * nodes.
+ */
+void __init numa_init_array(void)
+{
+	int rr, i;
+
+	rr = first_node(node_online_map);
+	for (i = 0; i < nr_cpu_ids; i++) {
+		if (early_cpu_to_node(i) != NUMA_NO_NODE)
+			continue;
+		numa_set_node(i, rr);
+		rr = next_node(rr, node_online_map);
+		if (rr == MAX_NUMNODES)
+			rr = first_node(node_online_map);
+	}
+}
+
+static __init int find_near_online_node(int node)
+{
+	int n, val;
+	int min_val = INT_MAX;
+	int best_node = -1;
+
+	for_each_online_node(n) {
+		val = node_distance(node, n);
+
+		if (val < min_val) {
+			min_val = val;
+			best_node = n;
+		}
+	}
+
+	return best_node;
+}
+
+/*
+ * Setup early cpu_to_node.
+ *
+ * Populate cpu_to_node[] only if x86_cpu_to_apicid[],
+ * and apicid_to_node[] tables have valid entries for a CPU.
+ * This means we skip cpu_to_node[] initialisation for NUMA
+ * emulation and faking node case (when running a kernel compiled
+ * for NUMA on a non NUMA box), which is OK as cpu_to_node[]
+ * is already initialized in a round robin manner at numa_init_array,
+ * prior to this call, and this initialization is good enough
+ * for the fake NUMA cases.
+ *
+ * Called before the per_cpu areas are setup.
+ */
+void __init init_cpu_to_node(void)
+{
+	int cpu;
+	u16 *cpu_to_apicid = early_per_cpu_ptr(x86_cpu_to_apicid);
+
+	BUG_ON(cpu_to_apicid == NULL);
+
+	for_each_possible_cpu(cpu) {
+		int node = numa_cpu_node(cpu);
+
+		if (node == NUMA_NO_NODE)
+			continue;
+		if (!node_online(node))
+			node = find_near_online_node(node);
+		numa_set_node(cpu, node);
+	}
+}
+
+#ifndef CONFIG_DEBUG_PER_CPU_MAPS
+
+# ifndef CONFIG_NUMA_EMU
+void __cpuinit numa_add_cpu(int cpu)
+{
+	cpumask_set_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	cpumask_clear_cpu(cpu, node_to_cpumask_map[early_cpu_to_node(cpu)]);
+}
+# endif	/* !CONFIG_NUMA_EMU */
+
+#else	/* !CONFIG_DEBUG_PER_CPU_MAPS */
+
+int __cpu_to_node(int cpu)
+{
+	if (early_per_cpu_ptr(x86_cpu_to_node_map)) {
+		printk(KERN_WARNING
+			"cpu_to_node(%d): usage too early!\n", cpu);
+		dump_stack();
+		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
+	}
+	return per_cpu(x86_cpu_to_node_map, cpu);
+}
+EXPORT_SYMBOL(__cpu_to_node);
+
+/*
+ * Same function as cpu_to_node() but used if called before the
+ * per_cpu areas are setup.
+ */
+int early_cpu_to_node(int cpu)
+{
+	if (early_per_cpu_ptr(x86_cpu_to_node_map))
+		return early_per_cpu_ptr(x86_cpu_to_node_map)[cpu];
+
+	if (!cpu_possible(cpu)) {
+		printk(KERN_WARNING
+			"early_cpu_to_node(%d): no per_cpu area!\n", cpu);
+		dump_stack();
+		return NUMA_NO_NODE;
+	}
+	return per_cpu(x86_cpu_to_node_map, cpu);
+}
+
+void debug_cpumask_set_cpu(int cpu, int node, bool enable)
+{
+	struct cpumask *mask;
+	char buf[64];
+
+	if (node == NUMA_NO_NODE) {
+		/* early_cpu_to_node() already emits a warning and trace */
+		return;
+	}
+	mask = node_to_cpumask_map[node];
+	if (!mask) {
+		pr_err("node_to_cpumask_map[%i] NULL\n", node);
+		dump_stack();
+		return;
+	}
+
+	if (enable)
+		cpumask_set_cpu(cpu, mask);
+	else
+		cpumask_clear_cpu(cpu, mask);
+
+	cpulist_scnprintf(buf, sizeof(buf), mask);
+	printk(KERN_DEBUG "%s cpu %d node %d: mask now %s\n",
+		enable ? "numa_add_cpu" : "numa_remove_cpu",
+		cpu, node, buf);
+	return;
+}
+
+# ifndef CONFIG_NUMA_EMU
+static void __cpuinit numa_set_cpumask(int cpu, bool enable)
+{
+	debug_cpumask_set_cpu(cpu, early_cpu_to_node(cpu), enable);
+}
+
+void __cpuinit numa_add_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, true);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, false);
+}
+# endif	/* !CONFIG_NUMA_EMU */
+
 /*
  * Returns a pointer to the bitmask of CPUs on Node 'node'.
  */
@@ -80,4 +280,5 @@
 	return node_to_cpumask_map[node];
 }
 EXPORT_SYMBOL(cpumask_of_node);
-#endif
+
+#endif	/* !CONFIG_DEBUG_PER_CPU_MAPS */
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/numa_emulation.c linux-libre-2.6.39-gnu/arch/x86/mm/numa_emulation.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/numa_emulation.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/mm/numa_emulation.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,486 @@
+/*
+ * NUMA emulation
+ */
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/topology.h>
+#include <linux/memblock.h>
+#include <asm/dma.h>
+
+#include "numa_internal.h"
+
+static int emu_nid_to_phys[MAX_NUMNODES] __cpuinitdata;
+static char *emu_cmdline __initdata;
+
+void __init numa_emu_cmdline(char *str)
+{
+	emu_cmdline = str;
+}
+
+static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi)
+{
+	int i;
+
+	for (i = 0; i < mi->nr_blks; i++)
+		if (mi->blk[i].nid == nid)
+			return i;
+	return -ENOENT;
+}
+
+/*
+ * Sets up nid to range from @start to @end.  The return value is -errno if
+ * something went wrong, 0 otherwise.
+ */
+static int __init emu_setup_memblk(struct numa_meminfo *ei,
+				   struct numa_meminfo *pi,
+				   int nid, int phys_blk, u64 size)
+{
+	struct numa_memblk *eb = &ei->blk[ei->nr_blks];
+	struct numa_memblk *pb = &pi->blk[phys_blk];
+
+	if (ei->nr_blks >= NR_NODE_MEMBLKS) {
+		pr_err("NUMA: Too many emulated memblks, failing emulation\n");
+		return -EINVAL;
+	}
+
+	ei->nr_blks++;
+	eb->start = pb->start;
+	eb->end = pb->start + size;
+	eb->nid = nid;
+
+	if (emu_nid_to_phys[nid] == NUMA_NO_NODE)
+		emu_nid_to_phys[nid] = pb->nid;
+
+	pb->start += size;
+	if (pb->start >= pb->end) {
+		WARN_ON_ONCE(pb->start > pb->end);
+		numa_remove_memblk_from(phys_blk, pi);
+	}
+
+	printk(KERN_INFO "Faking node %d at %016Lx-%016Lx (%LuMB)\n", nid,
+	       eb->start, eb->end, (eb->end - eb->start) >> 20);
+	return 0;
+}
+
+/*
+ * Sets up nr_nodes fake nodes interleaved over physical nodes ranging from addr
+ * to max_addr.  The return value is the number of nodes allocated.
+ */
+static int __init split_nodes_interleave(struct numa_meminfo *ei,
+					 struct numa_meminfo *pi,
+					 u64 addr, u64 max_addr, int nr_nodes)
+{
+	nodemask_t physnode_mask = NODE_MASK_NONE;
+	u64 size;
+	int big;
+	int nid = 0;
+	int i, ret;
+
+	if (nr_nodes <= 0)
+		return -1;
+	if (nr_nodes > MAX_NUMNODES) {
+		pr_info("numa=fake=%d too large, reducing to %d\n",
+			nr_nodes, MAX_NUMNODES);
+		nr_nodes = MAX_NUMNODES;
+	}
+
+	size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) / nr_nodes;
+	/*
+	 * Calculate the number of big nodes that can be allocated as a result
+	 * of consolidating the remainder.
+	 */
+	big = ((size & ~FAKE_NODE_MIN_HASH_MASK) * nr_nodes) /
+		FAKE_NODE_MIN_SIZE;
+
+	size &= FAKE_NODE_MIN_HASH_MASK;
+	if (!size) {
+		pr_err("Not enough memory for each node.  "
+			"NUMA emulation disabled.\n");
+		return -1;
+	}
+
+	for (i = 0; i < pi->nr_blks; i++)
+		node_set(pi->blk[i].nid, physnode_mask);
+
+	/*
+	 * Continue to fill physical nodes with fake nodes until there is no
+	 * memory left on any of them.
+	 */
+	while (nodes_weight(physnode_mask)) {
+		for_each_node_mask(i, physnode_mask) {
+			u64 dma32_end = PFN_PHYS(MAX_DMA32_PFN);
+			u64 start, limit, end;
+			int phys_blk;
+
+			phys_blk = emu_find_memblk_by_nid(i, pi);
+			if (phys_blk < 0) {
+				node_clear(i, physnode_mask);
+				continue;
+			}
+			start = pi->blk[phys_blk].start;
+			limit = pi->blk[phys_blk].end;
+			end = start + size;
+
+			if (nid < big)
+				end += FAKE_NODE_MIN_SIZE;
+
+			/*
+			 * Continue to add memory to this fake node if its
+			 * non-reserved memory is less than the per-node size.
+			 */
+			while (end - start -
+			       memblock_x86_hole_size(start, end) < size) {
+				end += FAKE_NODE_MIN_SIZE;
+				if (end > limit) {
+					end = limit;
+					break;
+				}
+			}
+
+			/*
+			 * If there won't be at least FAKE_NODE_MIN_SIZE of
+			 * non-reserved memory in ZONE_DMA32 for the next node,
+			 * this one must extend to the boundary.
+			 */
+			if (end < dma32_end && dma32_end - end -
+			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+				end = dma32_end;
+
+			/*
+			 * If there won't be enough non-reserved memory for the
+			 * next node, this one must extend to the end of the
+			 * physical node.
+			 */
+			if (limit - end -
+			    memblock_x86_hole_size(end, limit) < size)
+				end = limit;
+
+			ret = emu_setup_memblk(ei, pi, nid++ % nr_nodes,
+					       phys_blk,
+					       min(end, limit) - start);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+/*
+ * Returns the end address of a node so that there is at least `size' amount of
+ * non-reserved memory or `max_addr' is reached.
+ */
+static u64 __init find_end_of_node(u64 start, u64 max_addr, u64 size)
+{
+	u64 end = start + size;
+
+	while (end - start - memblock_x86_hole_size(start, end) < size) {
+		end += FAKE_NODE_MIN_SIZE;
+		if (end > max_addr) {
+			end = max_addr;
+			break;
+		}
+	}
+	return end;
+}
+
+/*
+ * Sets up fake nodes of `size' interleaved over physical nodes ranging from
+ * `addr' to `max_addr'.  The return value is the number of nodes allocated.
+ */
+static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
+					      struct numa_meminfo *pi,
+					      u64 addr, u64 max_addr, u64 size)
+{
+	nodemask_t physnode_mask = NODE_MASK_NONE;
+	u64 min_size;
+	int nid = 0;
+	int i, ret;
+
+	if (!size)
+		return -1;
+	/*
+	 * The limit on emulated nodes is MAX_NUMNODES, so the size per node is
+	 * increased accordingly if the requested size is too small.  This
+	 * creates a uniform distribution of node sizes across the entire
+	 * machine (but not necessarily over physical nodes).
+	 */
+	min_size = (max_addr - addr - memblock_x86_hole_size(addr, max_addr)) /
+						MAX_NUMNODES;
+	min_size = max(min_size, FAKE_NODE_MIN_SIZE);
+	if ((min_size & FAKE_NODE_MIN_HASH_MASK) < min_size)
+		min_size = (min_size + FAKE_NODE_MIN_SIZE) &
+						FAKE_NODE_MIN_HASH_MASK;
+	if (size < min_size) {
+		pr_err("Fake node size %LuMB too small, increasing to %LuMB\n",
+			size >> 20, min_size >> 20);
+		size = min_size;
+	}
+	size &= FAKE_NODE_MIN_HASH_MASK;
+
+	for (i = 0; i < pi->nr_blks; i++)
+		node_set(pi->blk[i].nid, physnode_mask);
+
+	/*
+	 * Fill physical nodes with fake nodes of size until there is no memory
+	 * left on any of them.
+	 */
+	while (nodes_weight(physnode_mask)) {
+		for_each_node_mask(i, physnode_mask) {
+			u64 dma32_end = MAX_DMA32_PFN << PAGE_SHIFT;
+			u64 start, limit, end;
+			int phys_blk;
+
+			phys_blk = emu_find_memblk_by_nid(i, pi);
+			if (phys_blk < 0) {
+				node_clear(i, physnode_mask);
+				continue;
+			}
+			start = pi->blk[phys_blk].start;
+			limit = pi->blk[phys_blk].end;
+
+			end = find_end_of_node(start, limit, size);
+			/*
+			 * If there won't be at least FAKE_NODE_MIN_SIZE of
+			 * non-reserved memory in ZONE_DMA32 for the next node,
+			 * this one must extend to the boundary.
+			 */
+			if (end < dma32_end && dma32_end - end -
+			    memblock_x86_hole_size(end, dma32_end) < FAKE_NODE_MIN_SIZE)
+				end = dma32_end;
+
+			/*
+			 * If there won't be enough non-reserved memory for the
+			 * next node, this one must extend to the end of the
+			 * physical node.
+			 */
+			if (limit - end -
+			    memblock_x86_hole_size(end, limit) < size)
+				end = limit;
+
+			ret = emu_setup_memblk(ei, pi, nid++ % MAX_NUMNODES,
+					       phys_blk,
+					       min(end, limit) - start);
+			if (ret < 0)
+				return ret;
+		}
+	}
+	return 0;
+}
+
+/**
+ * numa_emulation - Emulate NUMA nodes
+ * @numa_meminfo: NUMA configuration to massage
+ * @numa_dist_cnt: The size of the physical NUMA distance table
+ *
+ * Emulate NUMA nodes according to the numa=fake kernel parameter.
+ * @numa_meminfo contains the physical memory configuration and is modified
+ * to reflect the emulated configuration on success.  @numa_dist_cnt is
+ * used to determine the size of the physical distance table.
+ *
+ * On success, the following modifications are made.
+ *
+ * - @numa_meminfo is updated to reflect the emulated nodes.
+ *
+ * - __apicid_to_node[] is updated such that APIC IDs are mapped to the
+ *   emulated nodes.
+ *
+ * - NUMA distance table is rebuilt to represent distances between emulated
+ *   nodes.  The distances are determined considering how emulated nodes
+ *   are mapped to physical nodes and match the actual distances.
+ *
+ * - emu_nid_to_phys[] reflects how emulated nodes are mapped to physical
+ *   nodes.  This is used by numa_add_cpu() and numa_remove_cpu().
+ *
+ * If emulation is not enabled or fails, emu_nid_to_phys[] is filled with
+ * identity mapping and no other modification is made.
+ */
+void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
+{
+	static struct numa_meminfo ei __initdata;
+	static struct numa_meminfo pi __initdata;
+	const u64 max_addr = max_pfn << PAGE_SHIFT;
+	u8 *phys_dist = NULL;
+	size_t phys_size = numa_dist_cnt * numa_dist_cnt * sizeof(phys_dist[0]);
+	int max_emu_nid, dfl_phys_nid;
+	int i, j, ret;
+
+	if (!emu_cmdline)
+		goto no_emu;
+
+	memset(&ei, 0, sizeof(ei));
+	pi = *numa_meminfo;
+
+	for (i = 0; i < MAX_NUMNODES; i++)
+		emu_nid_to_phys[i] = NUMA_NO_NODE;
+
+	/*
+	 * If the numa=fake command-line contains a 'M' or 'G', it represents
+	 * the fixed node size.  Otherwise, if it is just a single number N,
+	 * split the system RAM into N fake nodes.
+	 */
+	if (strchr(emu_cmdline, 'M') || strchr(emu_cmdline, 'G')) {
+		u64 size;
+
+		size = memparse(emu_cmdline, &emu_cmdline);
+		ret = split_nodes_size_interleave(&ei, &pi, 0, max_addr, size);
+	} else {
+		unsigned long n;
+
+		n = simple_strtoul(emu_cmdline, NULL, 0);
+		ret = split_nodes_interleave(&ei, &pi, 0, max_addr, n);
+	}
+
+	if (ret < 0)
+		goto no_emu;
+
+	if (numa_cleanup_meminfo(&ei) < 0) {
+		pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
+		goto no_emu;
+	}
+
+	/* copy the physical distance table */
+	if (numa_dist_cnt) {
+		u64 phys;
+
+		phys = memblock_find_in_range(0,
+					      (u64)max_pfn_mapped << PAGE_SHIFT,
+					      phys_size, PAGE_SIZE);
+		if (phys == MEMBLOCK_ERROR) {
+			pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
+			goto no_emu;
+		}
+		memblock_x86_reserve_range(phys, phys + phys_size, "TMP NUMA DIST");
+		phys_dist = __va(phys);
+
+		for (i = 0; i < numa_dist_cnt; i++)
+			for (j = 0; j < numa_dist_cnt; j++)
+				phys_dist[i * numa_dist_cnt + j] =
+					node_distance(i, j);
+	}
+
+	/*
+	 * Determine the max emulated nid and the default phys nid to use
+	 * for unmapped nodes.
+	 */
+	max_emu_nid = 0;
+	dfl_phys_nid = NUMA_NO_NODE;
+	for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++) {
+		if (emu_nid_to_phys[i] != NUMA_NO_NODE) {
+			max_emu_nid = i;
+			if (dfl_phys_nid == NUMA_NO_NODE)
+				dfl_phys_nid = emu_nid_to_phys[i];
+		}
+	}
+	if (dfl_phys_nid == NUMA_NO_NODE) {
+		pr_warning("NUMA: Warning: can't determine default physical node, disabling emulation\n");
+		goto no_emu;
+	}
+
+	/* commit */
+	*numa_meminfo = ei;
+
+	/*
+	 * Transform __apicid_to_node table to use emulated nids by
+	 * reverse-mapping phys_nid.  The maps should always exist but fall
+	 * back to zero just in case.
+	 */
+	for (i = 0; i < ARRAY_SIZE(__apicid_to_node); i++) {
+		if (__apicid_to_node[i] == NUMA_NO_NODE)
+			continue;
+		for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
+			if (__apicid_to_node[i] == emu_nid_to_phys[j])
+				break;
+		__apicid_to_node[i] = j < ARRAY_SIZE(emu_nid_to_phys) ? j : 0;
+	}
+
+	/* make sure all emulated nodes are mapped to a physical node */
+	for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
+		if (emu_nid_to_phys[i] == NUMA_NO_NODE)
+			emu_nid_to_phys[i] = dfl_phys_nid;
+
+	/* transform distance table */
+	numa_reset_distance();
+	for (i = 0; i < max_emu_nid + 1; i++) {
+		for (j = 0; j < max_emu_nid + 1; j++) {
+			int physi = emu_nid_to_phys[i];
+			int physj = emu_nid_to_phys[j];
+			int dist;
+
+			if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
+				dist = physi == physj ?
+					LOCAL_DISTANCE : REMOTE_DISTANCE;
+			else
+				dist = phys_dist[physi * numa_dist_cnt + physj];
+
+			numa_set_distance(i, j, dist);
+		}
+	}
+
+	/* free the copied physical distance table */
+	if (phys_dist)
+		memblock_x86_free_range(__pa(phys_dist), __pa(phys_dist) + phys_size);
+	return;
+
+no_emu:
+	/* No emulation.  Build identity emu_nid_to_phys[] for numa_add_cpu() */
+	for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
+		emu_nid_to_phys[i] = i;
+}
+
+#ifndef CONFIG_DEBUG_PER_CPU_MAPS
+void __cpuinit numa_add_cpu(int cpu)
+{
+	int physnid, nid;
+
+	nid = early_cpu_to_node(cpu);
+	BUG_ON(nid == NUMA_NO_NODE || !node_online(nid));
+
+	physnid = emu_nid_to_phys[nid];
+
+	/*
+	 * Map the cpu to each emulated node that is allocated on the physical
+	 * node of the cpu's apic id.
+	 */
+	for_each_online_node(nid)
+		if (emu_nid_to_phys[nid] == physnid)
+			cpumask_set_cpu(cpu, node_to_cpumask_map[nid]);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	int i;
+
+	for_each_online_node(i)
+		cpumask_clear_cpu(cpu, node_to_cpumask_map[i]);
+}
+#else	/* !CONFIG_DEBUG_PER_CPU_MAPS */
+static void __cpuinit numa_set_cpumask(int cpu, bool enable)
+{
+	int nid, physnid;
+
+	nid = early_cpu_to_node(cpu);
+	if (nid == NUMA_NO_NODE) {
+		/* early_cpu_to_node() already emits a warning and trace */
+		return;
+	}
+
+	physnid = emu_nid_to_phys[nid];
+
+	for_each_online_node(nid) {
+		if (emu_nid_to_phys[nid] != physnid)
+			continue;
+
+		debug_cpumask_set_cpu(cpu, nid, enable);
+	}
+}
+
+void __cpuinit numa_add_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, true);
+}
+
+void __cpuinit numa_remove_cpu(int cpu)
+{
+	numa_set_cpumask(cpu, false);
+}
+#endif	/* !CONFIG_DEBUG_PER_CPU_MAPS */
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/numa_internal.h linux-libre-2.6.39-gnu/arch/x86/mm/numa_internal.h
--- linux-libre-2.6.38-gnu/arch/x86/mm/numa_internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/mm/numa_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+#ifndef __X86_MM_NUMA_INTERNAL_H
+#define __X86_MM_NUMA_INTERNAL_H
+
+#include <linux/types.h>
+#include <asm/numa.h>
+
+struct numa_memblk {
+	u64			start;
+	u64			end;
+	int			nid;
+};
+
+struct numa_meminfo {
+	int			nr_blks;
+	struct numa_memblk	blk[NR_NODE_MEMBLKS];
+};
+
+void __init numa_remove_memblk_from(int idx, struct numa_meminfo *mi);
+int __init numa_cleanup_meminfo(struct numa_meminfo *mi);
+void __init numa_reset_distance(void);
+
+#ifdef CONFIG_NUMA_EMU
+void __init numa_emulation(struct numa_meminfo *numa_meminfo,
+			   int numa_dist_cnt);
+#else
+static inline void numa_emulation(struct numa_meminfo *numa_meminfo,
+				  int numa_dist_cnt)
+{ }
+#endif
+
+#endif	/* __X86_MM_NUMA_INTERNAL_H */
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/pageattr.c linux-libre-2.6.39-gnu/arch/x86/mm/pageattr.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/pageattr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/pageattr.c	2011-05-19 00:06:34.000000000 -0400
@@ -310,7 +310,7 @@
 		 * these shared mappings are made of small page mappings.
 		 * Thus this don't enforce !RW mapping for small page kernel
 		 * text mapping logic will help Linux Xen parvirt guest boot
-		 * aswell.
+		 * as well.
 		 */
 		if (lookup_address(address, &level) && (level != PG_LEVEL_4K))
 			pgprot_val(forbidden) |= _PAGE_RW;
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/pgtable.c linux-libre-2.6.39-gnu/arch/x86/mm/pgtable.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/pgtable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/pgtable.c	2011-05-19 00:06:34.000000000 -0400
@@ -168,8 +168,7 @@
 	 * section 8.1: in PAE mode we explicitly have to flush the
 	 * TLB via cr3 if the top-level pgd is changed...
 	 */
-	if (mm == current->active_mm)
-		write_cr3(read_cr3());
+	flush_tlb_mm(mm);
 }
 #else  /* !CONFIG_X86_PAE */
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/srat_32.c linux-libre-2.6.39-gnu/arch/x86/mm/srat_32.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/srat_32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/srat_32.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 static struct node_memory_chunk_s __initdata node_memory_chunk[MAXCHUNKS];
 
 static int __initdata num_memory_chunks; /* total number of memory chunks */
-static u8 __initdata apicid_to_pxm[MAX_APICID];
+static u8 __initdata apicid_to_pxm[MAX_LOCAL_APIC];
 
 int acpi_numa __initdata;
 
@@ -211,10 +211,12 @@
 {
 	int i, j, nid;
 
-
 	if (srat_disabled())
 		goto out_fail;
 
+	if (acpi_numa_init() < 0)
+		goto out_fail;
+
 	if (num_memory_chunks == 0) {
 		printk(KERN_DEBUG
 			 "could not find any ACPI SRAT memory areas.\n");
@@ -254,8 +256,8 @@
 	printk(KERN_DEBUG "Number of memory chunks in system = %d\n",
 			 num_memory_chunks);
 
-	for (i = 0; i < MAX_APICID; i++)
-		apicid_2_node[i] = pxm_to_node(apicid_to_pxm[i]);
+	for (i = 0; i < MAX_LOCAL_APIC; i++)
+		set_apicid_to_node(i, pxm_to_node(apicid_to_pxm[i]));
 
 	for (j = 0; j < num_memory_chunks; j++){
 		struct node_memory_chunk_s * chunk = &node_memory_chunk[j];
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/srat_64.c linux-libre-2.6.39-gnu/arch/x86/mm/srat_64.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/srat_64.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/srat_64.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,88 +26,34 @@
 
 int acpi_numa __initdata;
 
-static struct acpi_table_slit *acpi_slit;
-
-static nodemask_t nodes_parsed __initdata;
-static nodemask_t cpu_nodes_parsed __initdata;
-static struct bootnode nodes[MAX_NUMNODES] __initdata;
 static struct bootnode nodes_add[MAX_NUMNODES];
 
-static int num_node_memblks __initdata;
-static struct bootnode node_memblk_range[NR_NODE_MEMBLKS] __initdata;
-static int memblk_nodeid[NR_NODE_MEMBLKS] __initdata;
-
 static __init int setup_node(int pxm)
 {
 	return acpi_map_pxm_to_node(pxm);
 }
 
-static __init int conflicting_memblks(unsigned long start, unsigned long end)
-{
-	int i;
-	for (i = 0; i < num_node_memblks; i++) {
-		struct bootnode *nd = &node_memblk_range[i];
-		if (nd->start == nd->end)
-			continue;
-		if (nd->end > start && nd->start < end)
-			return memblk_nodeid[i];
-		if (nd->end == end && nd->start == start)
-			return memblk_nodeid[i];
-	}
-	return -1;
-}
-
-static __init void cutoff_node(int i, unsigned long start, unsigned long end)
-{
-	struct bootnode *nd = &nodes[i];
-
-	if (nd->start < start) {
-		nd->start = start;
-		if (nd->end < nd->start)
-			nd->start = nd->end;
-	}
-	if (nd->end > end) {
-		nd->end = end;
-		if (nd->start > nd->end)
-			nd->start = nd->end;
-	}
-}
-
 static __init void bad_srat(void)
 {
-	int i;
 	printk(KERN_ERR "SRAT: SRAT not used.\n");
 	acpi_numa = -1;
-	for (i = 0; i < MAX_LOCAL_APIC; i++)
-		apicid_to_node[i] = NUMA_NO_NODE;
-	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();
+	memset(nodes_add, 0, sizeof(nodes_add));
 }
 
 static __init inline int srat_disabled(void)
 {
-	return numa_off || acpi_numa < 0;
+	return acpi_numa < 0;
 }
 
 /* Callback for SLIT parsing */
 void __init acpi_numa_slit_init(struct acpi_table_slit *slit)
 {
-	unsigned length;
-	unsigned long phys;
-
-	length = slit->header.length;
-	phys = memblock_find_in_range(0, max_pfn_mapped<<PAGE_SHIFT, length,
-		 PAGE_SIZE);
-
-	if (phys == MEMBLOCK_ERROR)
-		panic(" Can not save slit!\n");
+	int i, j;
 
-	acpi_slit = __va(phys);
-	memcpy(acpi_slit, slit, length);
-	memblock_x86_reserve_range(phys, phys + length, "ACPI SLIT");
+	for (i = 0; i < slit->locality_count; i++)
+		for (j = 0; j < slit->locality_count; j++)
+			numa_set_distance(pxm_to_node(i), pxm_to_node(j),
+				slit->entry[slit->locality_count * i + j]);
 }
 
 /* Callback for Proximity Domain -> x2APIC mapping */
@@ -138,8 +84,8 @@
 		printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u skipped apicid that is too big\n", pxm, apic_id, node);
 		return;
 	}
-	apicid_to_node[apic_id] = node;
-	node_set(node, cpu_nodes_parsed);
+	set_apicid_to_node(apic_id, node);
+	node_set(node, numa_nodes_parsed);
 	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%04x -> Node %u\n",
 	       pxm, apic_id, node);
@@ -178,8 +124,8 @@
 		return;
 	}
 
-	apicid_to_node[apic_id] = node;
-	node_set(node, cpu_nodes_parsed);
+	set_apicid_to_node(apic_id, node);
+	node_set(node, numa_nodes_parsed);
 	acpi_numa = 1;
 	printk(KERN_INFO "SRAT: PXM %u -> APIC 0x%02x -> Node %u\n",
 	       pxm, apic_id, node);
@@ -241,7 +187,7 @@
 	}
 
 	if (changed) {
-		node_set(node, cpu_nodes_parsed);
+		node_set(node, numa_nodes_parsed);
 		printk(KERN_INFO "SRAT: hot plug zone found %Lx - %Lx\n",
 				 nd->start, nd->end);
 	}
@@ -251,10 +197,8 @@
 void __init
 acpi_numa_memory_affinity_init(struct acpi_srat_mem_affinity *ma)
 {
-	struct bootnode *nd, oldnode;
 	unsigned long start, end;
 	int node, pxm;
-	int i;
 
 	if (srat_disabled())
 		return;
@@ -276,300 +220,31 @@
 		bad_srat();
 		return;
 	}
-	i = conflicting_memblks(start, end);
-	if (i == node) {
-		printk(KERN_WARNING
-		"SRAT: Warning: PXM %d (%lx-%lx) overlaps with itself (%Lx-%Lx)\n",
-			pxm, start, end, nodes[i].start, nodes[i].end);
-	} else if (i >= 0) {
-		printk(KERN_ERR
-		       "SRAT: PXM %d (%lx-%lx) overlaps with PXM %d (%Lx-%Lx)\n",
-		       pxm, start, end, node_to_pxm(i),
-			nodes[i].start, nodes[i].end);
+
+	if (numa_add_memblk(node, start, end) < 0) {
 		bad_srat();
 		return;
 	}
-	nd = &nodes[node];
-	oldnode = *nd;
-	if (!node_test_and_set(node, nodes_parsed)) {
-		nd->start = start;
-		nd->end = end;
-	} else {
-		if (start < nd->start)
-			nd->start = start;
-		if (nd->end < end)
-			nd->end = end;
-	}
 
 	printk(KERN_INFO "SRAT: Node %u PXM %u %lx-%lx\n", node, pxm,
 	       start, end);
 
-	if (ma->flags & ACPI_SRAT_MEM_HOT_PLUGGABLE) {
+	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);
-	}
-
-	node_memblk_range[num_node_memblks].start = start;
-	node_memblk_range[num_node_memblks].end = end;
-	memblk_nodeid[num_node_memblks] = node;
-	num_node_memblks++;
-}
-
-/* Sanity check to catch more bad SRATs (they are amazingly common).
-   Make sure the PXMs cover all memory. */
-static int __init nodes_cover_memory(const struct bootnode *nodes)
-{
-	int i;
-	unsigned long pxmram, e820ram;
-
-	pxmram = 0;
-	for_each_node_mask(i, nodes_parsed) {
-		unsigned long s = nodes[i].start >> PAGE_SHIFT;
-		unsigned long e = nodes[i].end >> PAGE_SHIFT;
-		pxmram += e - s;
-		pxmram -= __absent_pages_in_range(i, s, e);
-		if ((long)pxmram < 0)
-			pxmram = 0;
-	}
-
-	e820ram = max_pfn - (memblock_x86_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,
-			(e820ram << PAGE_SHIFT) >> 20);
-		return 0;
-	}
-	return 1;
 }
 
 void __init acpi_numa_arch_fixup(void) {}
 
-#ifdef CONFIG_NUMA_EMU
-void __init acpi_get_nodes(struct bootnode *physnodes, unsigned long start,
-				unsigned long end)
-{
-	int i;
-
-	for_each_node_mask(i, nodes_parsed) {
-		cutoff_node(i, start, end);
-		physnodes[i].start = nodes[i].start;
-		physnodes[i].end = nodes[i].end;
-	}
-}
-#endif /* CONFIG_NUMA_EMU */
-
-/* Use the information discovered above to actually set up the nodes. */
-int __init acpi_scan_nodes(unsigned long start, unsigned long end)
-{
-	int i;
-
-	if (acpi_numa <= 0)
-		return -1;
-
-	/* First clean up the node list */
-	for (i = 0; i < MAX_NUMNODES; i++)
-		cutoff_node(i, start, end);
-
-	/*
-	 * Join together blocks on the same node, holes between
-	 * which don't overlap with memory on other nodes.
-	 */
-	for (i = 0; i < num_node_memblks; ++i) {
-		int j, k;
-
-		for (j = i + 1; j < num_node_memblks; ++j) {
-			unsigned long start, end;
-
-			if (memblk_nodeid[i] != memblk_nodeid[j])
-				continue;
-			start = min(node_memblk_range[i].end,
-			            node_memblk_range[j].end);
-			end = max(node_memblk_range[i].start,
-			          node_memblk_range[j].start);
-			for (k = 0; k < num_node_memblks; ++k) {
-				if (memblk_nodeid[i] == memblk_nodeid[k])
-					continue;
-				if (start < node_memblk_range[k].end &&
-				    end > node_memblk_range[k].start)
-					break;
-			}
-			if (k < num_node_memblks)
-				continue;
-			start = min(node_memblk_range[i].start,
-			            node_memblk_range[j].start);
-			end = max(node_memblk_range[i].end,
-			          node_memblk_range[j].end);
-			printk(KERN_INFO "SRAT: Node %d "
-			       "[%Lx,%Lx) + [%Lx,%Lx) -> [%lx,%lx)\n",
-			       memblk_nodeid[i],
-			       node_memblk_range[i].start,
-			       node_memblk_range[i].end,
-			       node_memblk_range[j].start,
-			       node_memblk_range[j].end,
-			       start, end);
-			node_memblk_range[i].start = start;
-			node_memblk_range[i].end = end;
-			k = --num_node_memblks - j;
-			memmove(memblk_nodeid + j, memblk_nodeid + j+1,
-				k * sizeof(*memblk_nodeid));
-			memmove(node_memblk_range + j, node_memblk_range + j+1,
-				k * sizeof(*node_memblk_range));
-			--j;
-		}
-	}
-
-	memnode_shift = compute_hash_shift(node_memblk_range, num_node_memblks,
-					   memblk_nodeid);
-	if (memnode_shift < 0) {
-		printk(KERN_ERR
-		     "SRAT: No NUMA node hash function found. Contact maintainer\n");
-		bad_srat();
-		return -1;
-	}
-
-	for (i = 0; i < num_node_memblks; i++)
-		memblock_x86_register_active_regions(memblk_nodeid[i],
-				node_memblk_range[i].start >> PAGE_SHIFT,
-				node_memblk_range[i].end >> PAGE_SHIFT);
-
-	/* for out of order entries in SRAT */
-	sort_node_map();
-	if (!nodes_cover_memory(nodes)) {
-		bad_srat();
-		return -1;
-	}
-
-	/* Account for nodes with cpus and no memory */
-	nodes_or(node_possible_map, nodes_parsed, cpu_nodes_parsed);
-
-	/* Finally register nodes */
-	for_each_node_mask(i, node_possible_map)
-		setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-	/* Try again in case setup_node_bootmem missed one due
-	   to missing bootmem */
-	for_each_node_mask(i, node_possible_map)
-		if (!node_online(i))
-			setup_node_bootmem(i, nodes[i].start, nodes[i].end);
-
-	for (i = 0; i < nr_cpu_ids; i++) {
-		int node = early_cpu_to_node(i);
-
-		if (node == NUMA_NO_NODE)
-			continue;
-		if (!node_online(node))
-			numa_clear_node(i);
-	}
-	numa_init_array();
-	return 0;
-}
-
-#ifdef CONFIG_NUMA_EMU
-static int fake_node_to_pxm_map[MAX_NUMNODES] __initdata = {
-	[0 ... MAX_NUMNODES-1] = PXM_INVAL
-};
-static s16 fake_apicid_to_node[MAX_LOCAL_APIC] __initdata = {
-	[0 ... MAX_LOCAL_APIC-1] = NUMA_NO_NODE
-};
-static int __init find_node_by_addr(unsigned long addr)
-{
-	int ret = NUMA_NO_NODE;
-	int i;
-
-	for_each_node_mask(i, nodes_parsed) {
-		/*
-		 * Find the real node that this emulated node appears on.  For
-		 * the sake of simplicity, we only use a real node's starting
-		 * address to determine which emulated node it appears on.
-		 */
-		if (addr >= nodes[i].start && addr < nodes[i].end) {
-			ret = i;
-			break;
-		}
-	}
-	return ret;
-}
-
-/*
- * In NUMA emulation, we need to setup proximity domain (_PXM) to node ID
- * mappings that respect the real ACPI topology but reflect our emulated
- * environment.  For each emulated node, we find which real node it appears on
- * and create PXM to NID mappings for those fake nodes which mirror that
- * locality.  SLIT will now represent the correct distances between emulated
- * nodes as a result of the real topology.
- */
-void __init acpi_fake_nodes(const struct bootnode *fake_nodes, int num_nodes)
-{
-	int i, j;
-
-	for (i = 0; i < num_nodes; i++) {
-		int nid, pxm;
-
-		nid = find_node_by_addr(fake_nodes[i].start);
-		if (nid == NUMA_NO_NODE)
-			continue;
-		pxm = node_to_pxm(nid);
-		if (pxm == PXM_INVAL)
-			continue;
-		fake_node_to_pxm_map[i] = pxm;
-		/*
-		 * For each apicid_to_node mapping that exists for this real
-		 * node, it must now point to the fake node ID.
-		 */
-		for (j = 0; j < MAX_LOCAL_APIC; j++)
-			if (apicid_to_node[j] == nid &&
-			    fake_apicid_to_node[j] == NUMA_NO_NODE)
-				fake_apicid_to_node[j] = i;
-	}
-
-	/*
-	 * If there are apicid-to-node mappings for physical nodes that do not
-	 * have a corresponding emulated node, it should default to a guaranteed
-	 * value.
-	 */
-	for (i = 0; i < MAX_LOCAL_APIC; i++)
-		if (apicid_to_node[i] != NUMA_NO_NODE &&
-		    fake_apicid_to_node[i] == NUMA_NO_NODE)
-			fake_apicid_to_node[i] = 0;
-
-	for (i = 0; i < num_nodes; i++)
-		__acpi_map_pxm_to_node(fake_node_to_pxm_map[i], i);
-	memcpy(apicid_to_node, fake_apicid_to_node, sizeof(apicid_to_node));
-
-	nodes_clear(nodes_parsed);
-	for (i = 0; i < num_nodes; i++)
-		if (fake_nodes[i].start != fake_nodes[i].end)
-			node_set(i, nodes_parsed);
-}
-
-static int null_slit_node_compare(int a, int b)
-{
-	return node_to_pxm(a) == node_to_pxm(b);
-}
-#else
-static int null_slit_node_compare(int a, int b)
-{
-	return a == b;
-}
-#endif /* CONFIG_NUMA_EMU */
-
-int __node_distance(int a, int b)
+int __init x86_acpi_numa_init(void)
 {
-	int index;
+	int ret;
 
-	if (!acpi_slit)
-		return null_slit_node_compare(a, b) ? LOCAL_DISTANCE :
-						      REMOTE_DISTANCE;
-	index = acpi_slit->locality_count * node_to_pxm(a);
-	return acpi_slit->entry[index + node_to_pxm(b)];
+	ret = acpi_numa_init();
+	if (ret < 0)
+		return ret;
+	return srat_disabled() ? -EINVAL : 0;
 }
 
-EXPORT_SYMBOL(__node_distance);
-
 #if defined(CONFIG_MEMORY_HOTPLUG_SPARSE) || defined(CONFIG_ACPI_HOTPLUG_MEMORY)
 int memory_add_physaddr_to_nid(u64 start)
 {
diff -druN linux-libre-2.6.38-gnu/arch/x86/mm/tlb.c linux-libre-2.6.39-gnu/arch/x86/mm/tlb.c
--- linux-libre-2.6.38-gnu/arch/x86/mm/tlb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/mm/tlb.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,12 +179,8 @@
 	sender = this_cpu_read(tlb_vector_offset);
 	f = &flush_state[sender];
 
-	/*
-	 * Could avoid this lock when
-	 * num_online_cpus() <= NUM_INVALIDATE_TLB_VECTORS, but it is
-	 * probably not worth checking this for a cache-hot lock.
-	 */
-	raw_spin_lock(&f->tlbstate_lock);
+	if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS)
+		raw_spin_lock(&f->tlbstate_lock);
 
 	f->flush_mm = mm;
 	f->flush_va = va;
@@ -202,7 +198,8 @@
 
 	f->flush_mm = NULL;
 	f->flush_va = 0;
-	raw_spin_unlock(&f->tlbstate_lock);
+	if (nr_cpu_ids > NUM_INVALIDATE_TLB_VECTORS)
+		raw_spin_unlock(&f->tlbstate_lock);
 }
 
 void native_flush_tlb_others(const struct cpumask *cpumask,
@@ -211,11 +208,10 @@
 	if (is_uv_system()) {
 		unsigned int cpu;
 
-		cpu = get_cpu();
+		cpu = smp_processor_id();
 		cpumask = uv_flush_tlb_others(cpumask, mm, va, cpu);
 		if (cpumask)
 			flush_tlb_others_ipi(cpumask, mm, va);
-		put_cpu();
 		return;
 	}
 	flush_tlb_others_ipi(cpumask, mm, va);
diff -druN linux-libre-2.6.38-gnu/arch/x86/oprofile/backtrace.c linux-libre-2.6.39-gnu/arch/x86/oprofile/backtrace.c
--- linux-libre-2.6.38-gnu/arch/x86/oprofile/backtrace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/oprofile/backtrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -126,7 +126,7 @@
 	if (!user_mode_vm(regs)) {
 		unsigned long stack = kernel_stack_pointer(regs);
 		if (depth)
-			dump_trace(NULL, regs, (unsigned long *)stack,
+			dump_trace(NULL, regs, (unsigned long *)stack, 0,
 				   &backtrace_ops, &depth);
 		return;
 	}
diff -druN linux-libre-2.6.38-gnu/arch/x86/oprofile/nmi_int.c linux-libre-2.6.39-gnu/arch/x86/oprofile/nmi_int.c
--- linux-libre-2.6.38-gnu/arch/x86/oprofile/nmi_int.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/oprofile/nmi_int.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 #include <linux/notifier.h>
 #include <linux/smp.h>
 #include <linux/oprofile.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/slab.h>
 #include <linux/moduleparam.h>
 #include <linux/kdebug.h>
@@ -49,6 +49,10 @@
 	val |= counter_config->user ? ARCH_PERFMON_EVENTSEL_USR : 0;
 	val |= counter_config->kernel ? ARCH_PERFMON_EVENTSEL_OS : 0;
 	val |= (counter_config->unit_mask & 0xFF) << 8;
+	counter_config->extra &= (ARCH_PERFMON_EVENTSEL_INV |
+				  ARCH_PERFMON_EVENTSEL_EDGE |
+				  ARCH_PERFMON_EVENTSEL_CMASK);
+	val |= counter_config->extra;
 	event &= model->event_mask ? model->event_mask : 0xFF;
 	val |= event & 0xFF;
 	val |= (event & 0x0F00) << 24;
@@ -440,6 +444,7 @@
 		oprofilefs_create_ulong(sb, dir, "unit_mask", &counter_config[i].unit_mask);
 		oprofilefs_create_ulong(sb, dir, "kernel", &counter_config[i].kernel);
 		oprofilefs_create_ulong(sb, dir, "user", &counter_config[i].user);
+		oprofilefs_create_ulong(sb, dir, "extra", &counter_config[i].extra);
 	}
 
 	return 0;
@@ -536,7 +541,7 @@
 
 #ifdef CONFIG_PM
 
-static int nmi_suspend(struct sys_device *dev, pm_message_t state)
+static int nmi_suspend(void)
 {
 	/* Only one CPU left, just stop that one */
 	if (nmi_enabled == 1)
@@ -544,49 +549,31 @@
 	return 0;
 }
 
-static int nmi_resume(struct sys_device *dev)
+static void nmi_resume(void)
 {
 	if (nmi_enabled == 1)
 		nmi_cpu_start(NULL);
-	return 0;
 }
 
-static struct sysdev_class oprofile_sysclass = {
-	.name		= "oprofile",
+static struct syscore_ops oprofile_syscore_ops = {
 	.resume		= nmi_resume,
 	.suspend	= nmi_suspend,
 };
 
-static struct sys_device device_oprofile = {
-	.id	= 0,
-	.cls	= &oprofile_sysclass,
-};
-
-static int __init init_sysfs(void)
+static void __init init_suspend_resume(void)
 {
-	int error;
-
-	error = sysdev_class_register(&oprofile_sysclass);
-	if (error)
-		return error;
-
-	error = sysdev_register(&device_oprofile);
-	if (error)
-		sysdev_class_unregister(&oprofile_sysclass);
-
-	return error;
+	register_syscore_ops(&oprofile_syscore_ops);
 }
 
-static void exit_sysfs(void)
+static void exit_suspend_resume(void)
 {
-	sysdev_unregister(&device_oprofile);
-	sysdev_class_unregister(&oprofile_sysclass);
+	unregister_syscore_ops(&oprofile_syscore_ops);
 }
 
 #else
 
-static inline int  init_sysfs(void) { return 0; }
-static inline void exit_sysfs(void) { }
+static inline void init_suspend_resume(void) { }
+static inline void exit_suspend_resume(void) { }
 
 #endif /* CONFIG_PM */
 
@@ -789,9 +776,7 @@
 
 	mux_init(ops);
 
-	ret = init_sysfs();
-	if (ret)
-		return ret;
+	init_suspend_resume();
 
 	printk(KERN_INFO "oprofile: using NMI interrupt.\n");
 	return 0;
@@ -799,5 +784,5 @@
 
 void op_nmi_exit(void)
 {
-	exit_sysfs();
+	exit_suspend_resume();
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/oprofile/op_counter.h linux-libre-2.6.39-gnu/arch/x86/oprofile/op_counter.h
--- linux-libre-2.6.38-gnu/arch/x86/oprofile/op_counter.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/oprofile/op_counter.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 	unsigned long kernel;
 	unsigned long user;
 	unsigned long unit_mask;
+	unsigned long extra;
 };
 
 extern struct op_counter_config counter_config[];
diff -druN linux-libre-2.6.38-gnu/arch/x86/oprofile/op_model_p4.c linux-libre-2.6.39-gnu/arch/x86/oprofile/op_model_p4.c
--- linux-libre-2.6.38-gnu/arch/x86/oprofile/op_model_p4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/oprofile/op_model_p4.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 #endif
 }
 
-static int inline addr_increment(void)
+static inline int addr_increment(void)
 {
 #ifdef CONFIG_SMP
 	return smp_num_siblings == 2 ? 2 : 1;
diff -druN linux-libre-2.6.38-gnu/arch/x86/pci/amd_bus.c linux-libre-2.6.39-gnu/arch/x86/pci/amd_bus.c
--- linux-libre-2.6.38-gnu/arch/x86/pci/amd_bus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/pci/amd_bus.c	2011-05-19 00:06:34.000000000 -0400
@@ -350,7 +350,7 @@
 
 #define ENABLE_CF8_EXT_CFG      (1ULL << 46)
 
-static void enable_pci_io_ecs(void *unused)
+static void __cpuinit enable_pci_io_ecs(void *unused)
 {
 	u64 reg;
 	rdmsrl(MSR_AMD64_NB_CFG, reg);
diff -druN linux-libre-2.6.38-gnu/arch/x86/pci/ce4100.c linux-libre-2.6.39-gnu/arch/x86/pci/ce4100.c
--- linux-libre-2.6.38-gnu/arch/x86/pci/ce4100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/pci/ce4100.c	2011-05-19 00:06:34.000000000 -0400
@@ -255,7 +255,7 @@
 static int ce4100_conf_read(unsigned int seg, unsigned int bus,
 			    unsigned int devfn, int reg, int len, u32 *value)
 {
-	int i, retval = 1;
+	int i;
 
 	if (bus == 1) {
 		for (i = 0; i < ARRAY_SIZE(bus1_fixups); i++) {
diff -druN linux-libre-2.6.38-gnu/arch/x86/pci/i386.c linux-libre-2.6.39-gnu/arch/x86/pci/i386.c
--- linux-libre-2.6.38-gnu/arch/x86/pci/i386.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/pci/i386.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,7 +241,7 @@
 	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
+	 * occurred 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();
@@ -304,7 +304,7 @@
 		/*
 		 * ioremap() and ioremap_nocache() defaults to UC MINUS for now.
 		 * To avoid attribute conflicts, request UC MINUS here
-		 * aswell.
+		 * as well.
 		 */
 		prot |= _PAGE_CACHE_UC_MINUS;
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/pci/irq.c linux-libre-2.6.39-gnu/arch/x86/pci/irq.c
--- linux-libre-2.6.38-gnu/arch/x86/pci/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/pci/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -597,21 +597,18 @@
 		return 1;
 	}
 
-	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN) && 
-		(device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX)) {
+	if ((device >= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MIN && 
+	     device <= PCI_DEVICE_ID_INTEL_5_3400_SERIES_LPC_MAX) 
+	||  (device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN && 
+	     device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)
+	||  (device >= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MIN &&
+	     device <= PCI_DEVICE_ID_INTEL_DH89XXCC_LPC_MAX)) {
 		r->name = "PIIX/ICH";
 		r->get = pirq_piix_get;
 		r->set = pirq_piix_set;
 		return 1;
 	}
 
-	if ((device >= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MIN) && 
-		(device <= PCI_DEVICE_ID_INTEL_COUGARPOINT_LPC_MAX)) {
-		r->name = "PIIX/ICH";
-		r->get = pirq_piix_get;
-		r->set = pirq_piix_set;
-		return 1;
-	}
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/pci/xen.c linux-libre-2.6.39-gnu/arch/x86/pci/xen.c
--- linux-libre-2.6.38-gnu/arch/x86/pci/xen.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/pci/xen.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,8 @@
 #include <asm/xen/pci.h>
 
 #ifdef CONFIG_ACPI
-static int xen_hvm_register_pirq(u32 gsi, int triggering)
+static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
+				 int trigger, int polarity)
 {
 	int rc, irq;
 	struct physdev_map_pirq map_irq;
@@ -41,7 +42,7 @@
 		return -1;
 	}
 
-	if (triggering == ACPI_EDGE_SENSITIVE) {
+	if (trigger == ACPI_EDGE_SENSITIVE) {
 		shareable = 0;
 		name = "ioapic-edge";
 	} else {
@@ -49,18 +50,12 @@
 		name = "ioapic-level";
 	}
 
-	irq = xen_map_pirq_gsi(map_irq.pirq, gsi, shareable, name);
+	irq = xen_bind_pirq_gsi_to_irq(gsi, map_irq.pirq, shareable, name);
 
 	printk(KERN_DEBUG "xen: --> irq=%d, pirq=%d\n", irq, map_irq.pirq);
 
 	return irq;
 }
-
-static int acpi_register_gsi_xen_hvm(struct device *dev, u32 gsi,
-				 int trigger, int polarity)
-{
-	return xen_hvm_register_pirq(gsi, trigger);
-}
 #endif
 
 #if defined(CONFIG_PCI_MSI)
@@ -91,7 +86,7 @@
 
 static int xen_hvm_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-	int irq, pirq, ret = 0;
+	int irq, pirq;
 	struct msi_desc *msidesc;
 	struct msi_msg msg;
 
@@ -99,39 +94,32 @@
 		__read_msi_msg(msidesc, &msg);
 		pirq = MSI_ADDR_EXT_DEST_ID(msg.address_hi) |
 			((msg.address_lo >> MSI_ADDR_DEST_ID_SHIFT) & 0xff);
-		if (xen_irq_from_pirq(pirq) >= 0 && msg.data == XEN_PIRQ_MSI_DATA) {
-			xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
-					"msi-x" : "msi", &irq, &pirq, XEN_ALLOC_IRQ);
-			if (irq < 0)
+		if (msg.data != XEN_PIRQ_MSI_DATA ||
+		    xen_irq_from_pirq(pirq) < 0) {
+			pirq = xen_allocate_pirq_msi(dev, msidesc);
+			if (pirq < 0)
 				goto error;
-			ret = set_irq_msi(irq, msidesc);
-			if (ret < 0)
-				goto error_while;
-			printk(KERN_DEBUG "xen: msi already setup: msi --> irq=%d"
-					" pirq=%d\n", irq, pirq);
-			return 0;
+			xen_msi_compose_msg(dev, pirq, &msg);
+			__write_msi_msg(msidesc, &msg);
+			dev_dbg(&dev->dev, "xen: msi bound to pirq=%d\n", pirq);
+		} else {
+			dev_dbg(&dev->dev,
+				"xen: msi already bound to pirq=%d\n", pirq);
 		}
-		xen_allocate_pirq_msi((type == PCI_CAP_ID_MSIX) ?
-				"msi-x" : "msi", &irq, &pirq, (XEN_ALLOC_IRQ | XEN_ALLOC_PIRQ));
-		if (irq < 0 || pirq < 0)
+		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, pirq, 0,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "msi-x" : "msi");
+		if (irq < 0)
 			goto error;
-		printk(KERN_DEBUG "xen: msi --> irq=%d, pirq=%d\n", irq, pirq);
-		xen_msi_compose_msg(dev, pirq, &msg);
-		ret = set_irq_msi(irq, msidesc);
-		if (ret < 0)
-			goto error_while;
-		write_msi_msg(irq, &msg);
+		dev_dbg(&dev->dev,
+			"xen: msi --> pirq=%d --> irq=%d\n", pirq, irq);
 	}
 	return 0;
 
-error_while:
-	unbind_from_irqhandler(irq, NULL);
 error:
-	if (ret == -ENODEV)
-		dev_err(&dev->dev, "Xen PCI frontend has not registered" \
-				" MSI/MSI-X support!\n");
-
-	return ret;
+	dev_err(&dev->dev,
+		"Xen PCI frontend has not registered MSI/MSI-X support!\n");
+	return -ENODEV;
 }
 
 /*
@@ -150,35 +138,26 @@
 		return -ENOMEM;
 
 	if (type == PCI_CAP_ID_MSIX)
-		ret = xen_pci_frontend_enable_msix(dev, &v, nvec);
+		ret = xen_pci_frontend_enable_msix(dev, v, nvec);
 	else
-		ret = xen_pci_frontend_enable_msi(dev, &v);
+		ret = xen_pci_frontend_enable_msi(dev, v);
 	if (ret)
 		goto error;
 	i = 0;
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = xen_allocate_pirq(v[i], 0, /* not sharable */
-			(type == PCI_CAP_ID_MSIX) ?
-			"pcifront-msi-x" : "pcifront-msi");
-		if (irq < 0) {
-			ret = -1;
+		irq = xen_bind_pirq_msi_to_irq(dev, msidesc, v[i], 0,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "pcifront-msi-x" :
+					       "pcifront-msi");
+		if (irq < 0)
 			goto free;
-		}
-
-		ret = set_irq_msi(irq, msidesc);
-		if (ret)
-			goto error_while;
 		i++;
 	}
 	kfree(v);
 	return 0;
 
-error_while:
-	unbind_from_irqhandler(irq, NULL);
 error:
-	if (ret == -ENODEV)
-		dev_err(&dev->dev, "Xen PCI frontend has not registered" \
-			" MSI/MSI-X support!\n");
+	dev_err(&dev->dev, "Xen PCI frontend has not registered MSI/MSI-X support!\n");
 free:
 	kfree(v);
 	return ret;
@@ -193,6 +172,9 @@
 		xen_pci_frontend_disable_msix(dev);
 	else
 		xen_pci_frontend_disable_msi(dev);
+
+	/* Free the IRQ's and the msidesc using the generic code. */
+	default_teardown_msi_irqs(dev);
 }
 
 static void xen_teardown_msi_irq(unsigned int irq)
@@ -200,47 +182,91 @@
 	xen_destroy_irq(irq);
 }
 
+#ifdef CONFIG_XEN_DOM0
 static int xen_initdom_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
-	int irq, ret;
+	int ret = 0;
 	struct msi_desc *msidesc;
 
 	list_for_each_entry(msidesc, &dev->msi_list, list) {
-		irq = xen_create_msi_irq(dev, msidesc, type);
-		if (irq < 0)
-			return -1;
+		struct physdev_map_pirq map_irq;
 
-		ret = set_irq_msi(irq, msidesc);
-		if (ret)
-			goto error;
-	}
-	return 0;
+		memset(&map_irq, 0, sizeof(map_irq));
+		map_irq.domid = DOMID_SELF;
+		map_irq.type = MAP_PIRQ_TYPE_MSI;
+		map_irq.index = -1;
+		map_irq.pirq = -1;
+		map_irq.bus = dev->bus->number;
+		map_irq.devfn = dev->devfn;
 
-error:
-	xen_destroy_irq(irq);
+		if (type == PCI_CAP_ID_MSIX) {
+			int pos;
+			u32 table_offset, bir;
+
+			pos = pci_find_capability(dev, PCI_CAP_ID_MSIX);
+
+			pci_read_config_dword(dev, pos + PCI_MSIX_TABLE,
+					      &table_offset);
+			bir = (u8)(table_offset & PCI_MSIX_FLAGS_BIRMASK);
+
+			map_irq.table_base = pci_resource_start(dev, bir);
+			map_irq.entry_nr = msidesc->msi_attrib.entry_nr;
+		}
+
+		ret = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
+		if (ret) {
+			dev_warn(&dev->dev, "xen map irq failed %d\n", ret);
+			goto out;
+		}
+
+		ret = xen_bind_pirq_msi_to_irq(dev, msidesc,
+					       map_irq.pirq, map_irq.index,
+					       (type == PCI_CAP_ID_MSIX) ?
+					       "msi-x" : "msi");
+		if (ret < 0)
+			goto out;
+	}
+	ret = 0;
+out:
 	return ret;
 }
 #endif
+#endif
 
 static int xen_pcifront_enable_irq(struct pci_dev *dev)
 {
 	int rc;
 	int share = 1;
+	int pirq;
+	u8 gsi;
 
-	dev_info(&dev->dev, "Xen PCI enabling IRQ: %d\n", dev->irq);
+	rc = pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &gsi);
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI: failed to read interrupt line: %d\n",
+			 rc);
+		return rc;
+	}
 
-	if (dev->irq < 0)
-		return -EINVAL;
+	rc = xen_allocate_pirq_gsi(gsi);
+	if (rc < 0) {
+		dev_warn(&dev->dev, "Xen PCI: failed to allocate a PIRQ for GSI%d: %d\n",
+			 gsi, rc);
+		return rc;
+	}
+	pirq = rc;
 
-	if (dev->irq < NR_IRQS_LEGACY)
+	if (gsi < NR_IRQS_LEGACY)
 		share = 0;
 
-	rc = xen_allocate_pirq(dev->irq, share, "pcifront");
+	rc = xen_bind_pirq_gsi_to_irq(gsi, pirq, share, "pcifront");
 	if (rc < 0) {
-		dev_warn(&dev->dev, "Xen PCI IRQ: %d, failed to register:%d\n",
-			 dev->irq, rc);
+		dev_warn(&dev->dev, "Xen PCI: failed to bind GSI%d (PIRQ%d) to IRQ: %d\n",
+			 gsi, pirq, rc);
 		return rc;
 	}
+
+	dev->irq = rc;
+	dev_info(&dev->dev, "Xen PCI mapped GSI%d to IRQ%d\n", gsi, dev->irq);
 	return 0;
 }
 
@@ -292,7 +318,7 @@
 #ifdef CONFIG_XEN_DOM0
 static int xen_register_pirq(u32 gsi, int triggering)
 {
-	int rc, irq;
+	int rc, pirq, irq = -1;
 	struct physdev_map_pirq map_irq;
 	int shareable = 0;
 	char *name;
@@ -308,17 +334,20 @@
 		name = "ioapic-level";
 	}
 
-	irq = xen_allocate_pirq(gsi, shareable, name);
-
-	printk(KERN_DEBUG "xen: --> irq=%d\n", irq);
+	pirq = xen_allocate_pirq_gsi(gsi);
+	if (pirq < 0)
+		goto out;
 
+	irq = xen_bind_pirq_gsi_to_irq(gsi, pirq, shareable, name);
 	if (irq < 0)
 		goto out;
 
+	printk(KERN_DEBUG "xen: --> pirq=%d -> irq=%d\n", pirq, irq);
+
 	map_irq.domid = DOMID_SELF;
 	map_irq.type = MAP_PIRQ_TYPE_GSI;
 	map_irq.index = gsi;
-	map_irq.pirq = irq;
+	map_irq.pirq = pirq;
 
 	rc = HYPERVISOR_physdev_op(PHYSDEVOP_map_pirq, &map_irq);
 	if (rc) {
@@ -405,13 +434,18 @@
 
 void __init xen_setup_pirqs(void)
 {
-	int irq;
+	int pirq, irq;
 
 	pci_xen_initial_domain();
 
 	if (0 == nr_ioapics) {
-		for (irq = 0; irq < NR_IRQS_LEGACY; irq++)
-			xen_allocate_pirq(irq, 0, "xt-pic");
+		for (irq = 0; irq < NR_IRQS_LEGACY; irq++) {
+			pirq = xen_allocate_pirq_gsi(irq);
+			if (WARN(pirq < 0,
+				 "Could not allocate PIRQ for legacy interrupt\n"))
+				break;
+			irq = xen_bind_pirq_gsi_to_irq(irq, pirq, 0, "xt-pic");
+		}
 		return;
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/ce4100/ce4100.c linux-libre-2.6.39-gnu/arch/x86/platform/ce4100/ce4100.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/ce4100/ce4100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/ce4100/ce4100.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,21 +16,19 @@
 #include <linux/serial_8250.h>
 
 #include <asm/ce4100.h>
+#include <asm/prom.h>
 #include <asm/setup.h>
+#include <asm/i8259.h>
 #include <asm/io.h>
+#include <asm/io_apic.h>
 
 static int ce4100_i8042_detect(void)
 {
 	return 0;
 }
 
-static void __init sdv_find_smp_config(void)
-{
-}
-
 #ifdef CONFIG_SERIAL_8250
 
-
 static unsigned int mem_serial_in(struct uart_port *p, int offset)
 {
 	offset = offset << p->regshift;
@@ -119,6 +117,15 @@
 	sdv_serial_fixup();
 }
 
+#ifdef CONFIG_X86_IO_APIC
+static void __cpuinit sdv_pci_init(void)
+{
+	x86_of_pci_init();
+	/* We can't set this earlier, because we need to calibrate the timer */
+	legacy_pic = &null_legacy_pic;
+}
+#endif
+
 /*
  * CE4100 specific x86_init function overrides and early setup
  * calls.
@@ -129,6 +136,11 @@
 	x86_platform.i8042_detect = ce4100_i8042_detect;
 	x86_init.resources.probe_roms = x86_init_noop;
 	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
-	x86_init.mpparse.find_smp_config = sdv_find_smp_config;
+	x86_init.mpparse.find_smp_config = x86_init_noop;
 	x86_init.pci.init = ce4100_pci_init;
+
+#ifdef CONFIG_X86_IO_APIC
+	x86_init.pci.init_irq = sdv_pci_init;
+	x86_init.mpparse.setup_ioapic_ids = setup_ioapic_ids_from_mpc_nocheck;
+#endif
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/ce4100/falconfalls.dts linux-libre-2.6.39-gnu/arch/x86/platform/ce4100/falconfalls.dts
--- linux-libre-2.6.38-gnu/arch/x86/platform/ce4100/falconfalls.dts	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/arch/x86/platform/ce4100/falconfalls.dts	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,430 @@
+/*
+ * CE4100 on Falcon Falls
+ *
+ * (c) Copyright 2010 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.
+ */
+/dts-v1/;
+/ {
+	model = "intel,falconfalls";
+	compatible = "intel,falconfalls";
+	#address-cells = <1>;
+	#size-cells = <1>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "intel,ce4100";
+			reg = <0>;
+			lapic = <&lapic0>;
+		};
+	};
+
+	soc@0 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "intel,ce4100-cp";
+		ranges;
+
+		ioapic1: interrupt-controller@fec00000 {
+			#interrupt-cells = <2>;
+			compatible = "intel,ce4100-ioapic";
+			interrupt-controller;
+			reg = <0xfec00000 0x1000>;
+		};
+
+		timer@fed00000 {
+			compatible = "intel,ce4100-hpet";
+			reg = <0xfed00000 0x200>;
+		};
+
+		lapic0: interrupt-controller@fee00000 {
+			compatible = "intel,ce4100-lapic";
+			reg = <0xfee00000 0x1000>;
+		};
+
+		pci@3fc {
+			#address-cells = <3>;
+			#size-cells = <2>;
+			compatible = "intel,ce4100-pci", "pci";
+			device_type = "pci";
+			bus-range = <0 0>;
+			ranges = <0x2000000 0 0xbffff000 0xbffff000 0 0x1000
+				  0x2000000 0 0xdffe0000 0xdffe0000 0 0x1000
+				  0x0000000 0 0x0	 0x0	    0 0x100>;
+
+			/* Secondary IO-APIC */
+			ioapic2: interrupt-controller@0,1 {
+				#interrupt-cells = <2>;
+				compatible = "intel,ce4100-ioapic";
+				interrupt-controller;
+				reg = <0x100 0x0 0x0 0x0 0x0>;
+				assigned-addresses = <0x02000000 0x0 0xbffff000 0x0 0x1000>;
+			};
+
+			pci@1,0 {
+				#address-cells = <3>;
+				#size-cells = <2>;
+				compatible = "intel,ce4100-pci", "pci";
+				device_type = "pci";
+				bus-range = <1 1>;
+				reg = <0x0800 0x0 0x0 0x0 0x0>;
+				ranges = <0x2000000 0 0xdffe0000 0x2000000 0 0xdffe0000 0 0x1000>;
+
+				interrupt-parent = <&ioapic2>;
+
+				display@2,0 {
+					compatible = "pci8086,2e5b.2",
+						   "pci8086,2e5b",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x11000 0x0 0x0 0x0 0x0>;
+					interrupts = <0 1>;
+				};
+
+				multimedia@3,0 {
+					compatible = "pci8086,2e5c.2",
+						   "pci8086,2e5c",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x11800 0x0 0x0 0x0 0x0>;
+					interrupts = <2 1>;
+				};
+
+				multimedia@4,0 {
+					compatible = "pci8086,2e5d.2",
+						   "pci8086,2e5d",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12000 0x0 0x0 0x0 0x0>;
+					interrupts = <4 1>;
+				};
+
+				multimedia@4,1 {
+					compatible = "pci8086,2e5e.2",
+						   "pci8086,2e5e",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x12100 0x0 0x0 0x0 0x0>;
+					interrupts = <5 1>;
+				};
+
+				sound@6,0 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13000 0x0 0x0 0x0 0x0>;
+					interrupts = <6 1>;
+				};
+
+				sound@6,1 {
+					compatible = "pci8086,2e5f.2",
+						   "pci8086,2e5f",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13100 0x0 0x0 0x0 0x0>;
+					interrupts = <7 1>;
+				};
+
+				sound@6,2 {
+					compatible = "pci8086,2e60.2",
+						   "pci8086,2e60",
+						   "pciclass040100",
+						   "pciclass0401";
+
+					reg = <0x13200 0x0 0x0 0x0 0x0>;
+					interrupts = <8 1>;
+				};
+
+				display@8,0 {
+					compatible = "pci8086,2e61.2",
+						   "pci8086,2e61",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14000 0x0 0x0 0x0 0x0>;
+					interrupts = <9 1>;
+				};
+
+				display@8,1 {
+					compatible = "pci8086,2e62.2",
+						   "pci8086,2e62",
+						   "pciclass038000",
+						   "pciclass0380";
+
+					reg = <0x14100 0x0 0x0 0x0 0x0>;
+					interrupts = <10 1>;
+				};
+
+				multimedia@8,2 {
+					compatible = "pci8086,2e63.2",
+						   "pci8086,2e63",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x14200 0x0 0x0 0x0 0x0>;
+					interrupts = <11 1>;
+				};
+
+				entertainment-encryption@9,0 {
+					compatible = "pci8086,2e64.2",
+						   "pci8086,2e64",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x14800 0x0 0x0 0x0 0x0>;
+					interrupts = <12 1>;
+				};
+
+				localbus@a,0 {
+					compatible = "pci8086,2e65.2",
+						   "pci8086,2e65",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15000 0x0 0x0 0x0 0x0>;
+				};
+
+				serial@b,0 {
+					compatible = "pci8086,2e66.2",
+						   "pci8086,2e66",
+						   "pciclass070003",
+						   "pciclass0700";
+
+					reg = <0x15800 0x0 0x0 0x0 0x0>;
+					interrupts = <14 1>;
+				};
+
+				gpio@b,1 {
+					compatible = "pci8086,2e67.2",
+						   "pci8086,2e67",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					#gpio-cells = <2>;
+					reg = <0x15900 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+					gpio-controller;
+				};
+
+				i2c-controller@b,2 {
+					#address-cells = <2>;
+					#size-cells = <1>;
+					compatible = "pci8086,2e68.2",
+						   "pci8086,2e68",
+						   "pciclass,ff0000",
+						   "pciclass,ff00";
+
+					reg = <0x15a00 0x0 0x0 0x0 0x0>;
+					interrupts = <16 1>;
+					ranges = <0 0	0x02000000 0 0xdffe0500	0x100
+						  1 0	0x02000000 0 0xdffe0600	0x100
+						  2 0	0x02000000 0 0xdffe0700	0x100>;
+
+					i2c@0 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <0 0 0x100>;
+					};
+
+					i2c@1 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <1 0 0x100>;
+
+						gpio@26 {
+							#gpio-cells = <2>;
+							compatible = "ti,pcf8575";
+							reg = <0x26>;
+							gpio-controller;
+						};
+					};
+
+					i2c@2 {
+						#address-cells = <1>;
+						#size-cells = <0>;
+						compatible = "intel,ce4100-i2c-controller";
+						reg = <2 0 0x100>;
+
+						gpio@26 {
+							#gpio-cells = <2>;
+							compatible = "ti,pcf8575";
+							reg = <0x26>;
+							gpio-controller;
+						};
+					};
+				};
+
+				smard-card@b,3 {
+					compatible = "pci8086,2e69.2",
+						   "pci8086,2e69",
+						   "pciclass070500",
+						   "pciclass0705";
+
+					reg = <0x15b00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+				};
+
+				spi-controller@b,4 {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					compatible =
+						"pci8086,2e6a.2",
+						"pci8086,2e6a",
+						"pciclass,ff0000",
+						"pciclass,ff00";
+
+					reg = <0x15c00 0x0 0x0 0x0 0x0>;
+					interrupts = <15 1>;
+
+					dac@0 {
+						compatible = "ti,pcm1755";
+						reg = <0>;
+						spi-max-frequency = <115200>;
+					};
+
+					dac@1 {
+						compatible = "ti,pcm1609a";
+						reg = <1>;
+						spi-max-frequency = <115200>;
+					};
+
+					eeprom@2 {
+						compatible = "atmel,at93c46";
+						reg = <2>;
+						spi-max-frequency = <115200>;
+					};
+				};
+
+				multimedia@b,7 {
+					compatible = "pci8086,2e6d.2",
+						   "pci8086,2e6d",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x15f00 0x0 0x0 0x0 0x0>;
+				};
+
+				ethernet@c,0 {
+					compatible = "pci8086,2e6e.2",
+						   "pci8086,2e6e",
+						   "pciclass020000",
+						   "pciclass0200";
+
+					reg = <0x16000 0x0 0x0 0x0 0x0>;
+					interrupts = <21 1>;
+				};
+
+				clock@c,1 {
+					compatible = "pci8086,2e6f.2",
+						   "pci8086,2e6f",
+						   "pciclassff0000",
+						   "pciclassff00";
+
+					reg = <0x16100 0x0 0x0 0x0 0x0>;
+					interrupts = <3 1>;
+				};
+
+				usb@d,0 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16800 0x0 0x0 0x0 0x0>;
+					interrupts = <22 1>;
+				};
+
+				usb@d,1 {
+					compatible = "pci8086,2e70.2",
+						   "pci8086,2e70",
+						   "pciclass0c0320",
+						   "pciclass0c03";
+
+					reg = <0x16900 0x0 0x0 0x0 0x0>;
+					interrupts = <22 1>;
+				};
+
+				sata@e,0 {
+					compatible = "pci8086,2e71.0",
+						   "pci8086,2e71",
+						   "pciclass010601",
+						   "pciclass0106";
+
+					reg = <0x17000 0x0 0x0 0x0 0x0>;
+					interrupts = <23 1>;
+				};
+
+				flash@f,0 {
+					compatible = "pci8086,701.1",
+						   "pci8086,701",
+						   "pciclass050100",
+						   "pciclass0501";
+
+					reg = <0x17800 0x0 0x0 0x0 0x0>;
+					interrupts = <13 1>;
+				};
+
+				entertainment-encryption@10,0 {
+					compatible = "pci8086,702.1",
+						   "pci8086,702",
+						   "pciclass101000",
+						   "pciclass1010";
+
+					reg = <0x18000 0x0 0x0 0x0 0x0>;
+				};
+
+				co-processor@11,0 {
+					compatible = "pci8086,703.1",
+						   "pci8086,703",
+						   "pciclass0b4000",
+						   "pciclass0b40";
+
+					reg = <0x18800 0x0 0x0 0x0 0x0>;
+					interrupts = <1 1>;
+				};
+
+				multimedia@12,0 {
+					compatible = "pci8086,704.0",
+						   "pci8086,704",
+						   "pciclass048000",
+						   "pciclass0480";
+
+					reg = <0x19000 0x0 0x0 0x0 0x0>;
+				};
+			};
+
+			isa@1f,0 {
+				#address-cells = <2>;
+				#size-cells = <1>;
+				compatible = "isa";
+				reg = <0xf800 0x0 0x0 0x0 0x0>;
+				ranges = <1 0 0 0 0 0x100>;
+
+				rtc@70 {
+					compatible = "intel,ce4100-rtc", "motorola,mc146818";
+					interrupts = <8 3>;
+					interrupt-parent = <&ioapic1>;
+					ctrl-reg = <2>;
+					freq-reg = <0x26>;
+					reg = <1 0x70 2>;
+				};
+			};
+		};
+	};
+};
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/mrst/mrst.c linux-libre-2.6.39-gnu/arch/x86/platform/mrst/mrst.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/mrst/mrst.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/mrst/mrst.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 #include <asm/apic.h>
 #include <asm/io_apic.h>
 #include <asm/mrst.h>
+#include <asm/mrst-vrtc.h>
 #include <asm/io.h>
 #include <asm/i8259.h>
 #include <asm/intel_scu_ipc.h>
@@ -96,11 +97,11 @@
 			pentry->freq_hz, pentry->irq);
 			if (!pentry->irq)
 				continue;
-			mp_irq.type = MP_IOAPIC;
+			mp_irq.type = MP_INTSRC;
 			mp_irq.irqtype = mp_INT;
 /* triggering mode edge bit 2-3, active high polarity bit 0-1 */
 			mp_irq.irqflag = 5;
-			mp_irq.srcbus = 0;
+			mp_irq.srcbus = MP_BUS_ISA;
 			mp_irq.srcbusirq = pentry->irq;	/* IRQ */
 			mp_irq.dstapic = MP_APIC_ALL;
 			mp_irq.dstirq = pentry->irq;
@@ -167,10 +168,10 @@
 	for (totallen = 0; totallen < sfi_mrtc_num; totallen++, pentry++) {
 		pr_debug("RTC[%d]: paddr = 0x%08x, irq = %d\n",
 			totallen, (u32)pentry->phys_addr, pentry->irq);
-		mp_irq.type = MP_IOAPIC;
+		mp_irq.type = MP_INTSRC;
 		mp_irq.irqtype = mp_INT;
 		mp_irq.irqflag = 0xf;	/* level trigger and active low */
-		mp_irq.srcbus = 0;
+		mp_irq.srcbus = MP_BUS_ISA;
 		mp_irq.srcbusirq = pentry->irq;	/* IRQ */
 		mp_irq.dstapic = MP_APIC_ALL;
 		mp_irq.dstirq = pentry->irq;
@@ -268,6 +269,7 @@
 
 	x86_platform.calibrate_tsc = mrst_calibrate_tsc;
 	x86_platform.i8042_detect = mrst_i8042_detect;
+	x86_init.timers.wallclock_init = mrst_rtc_init;
 	x86_init.pci.init = pci_mrst_init;
 	x86_init.pci.fixup_irqs = x86_init_noop;
 
@@ -280,7 +282,7 @@
 	/* Avoid searching for BIOS MP tables */
 	x86_init.mpparse.find_smp_config = x86_init_noop;
 	x86_init.mpparse.get_smp_config = x86_init_uint_noop;
-
+	set_bit(MP_BUS_ISA, mp_bus_not_pci);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/mrst/vrtc.c linux-libre-2.6.39-gnu/arch/x86/platform/mrst/vrtc.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/mrst/vrtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/mrst/vrtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,22 +100,16 @@
 
 void __init mrst_rtc_init(void)
 {
-	unsigned long rtc_paddr;
-	void __iomem *virt_base;
+	unsigned long vrtc_paddr;
 
 	sfi_table_parse(SFI_SIG_MRTC, NULL, NULL, sfi_parse_mrtc);
-	if (!sfi_mrtc_num)
-		return;
-
-	rtc_paddr = sfi_mrtc_array[0].phys_addr;
-
-	/* vRTC's register address may not be page aligned */
-	set_fixmap_nocache(FIX_LNW_VRTC, rtc_paddr);
 
-	virt_base = (void __iomem *)__fix_to_virt(FIX_LNW_VRTC);
-	virt_base += rtc_paddr & ~PAGE_MASK;
-	vrtc_virt_base = virt_base;
+	vrtc_paddr = sfi_mrtc_array[0].phys_addr;
+	if (!sfi_mrtc_num || !vrtc_paddr)
+		return;
 
+	vrtc_virt_base = (void __iomem *)set_fixmap_offset_nocache(FIX_LNW_VRTC,
+								vrtc_paddr);
 	x86_platform.get_wallclock = vrtc_get_time;
 	x86_platform.set_wallclock = vrtc_set_mmss;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/olpc/Makefile linux-libre-2.6.39-gnu/arch/x86/platform/olpc/Makefile
--- linux-libre-2.6.38-gnu/arch/x86/platform/olpc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/olpc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
 obj-$(CONFIG_OLPC)		+= olpc.o
 obj-$(CONFIG_OLPC_XO1)		+= olpc-xo1.o
-obj-$(CONFIG_OLPC_OPENFIRMWARE)	+= olpc_ofw.o
-obj-$(CONFIG_OLPC_OPENFIRMWARE_DT)	+= olpc_dt.o
+obj-$(CONFIG_OLPC)		+= olpc_ofw.o
+obj-$(CONFIG_OF_PROMTREE)	+= olpc_dt.o
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/olpc/olpc-xo1.c linux-libre-2.6.39-gnu/arch/x86/platform/olpc/olpc-xo1.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/olpc/olpc-xo1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/olpc/olpc-xo1.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/pm.h>
+#include <linux/mfd/core.h>
 
 #include <asm/io.h>
 #include <asm/olpc.h>
@@ -56,25 +57,24 @@
 static int __devinit olpc_xo1_probe(struct platform_device *pdev)
 {
 	struct resource *res;
+	int err;
 
 	/* don't run on non-XOs */
 	if (!machine_is_olpc())
 		return -ENODEV;
 
+	err = mfd_cell_enable(pdev);
+	if (err)
+		return err;
+
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!res) {
 		dev_err(&pdev->dev, "can't fetch device resource info\n");
 		return -EIO;
 	}
-
-	if (!request_region(res->start, resource_size(res), DRV_NAME)) {
-		dev_err(&pdev->dev, "can't request region\n");
-		return -EIO;
-	}
-
 	if (strcmp(pdev->name, "cs5535-pms") == 0)
 		pms_base = res->start;
-	else if (strcmp(pdev->name, "cs5535-acpi") == 0)
+	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
 		acpi_base = res->start;
 
 	/* If we have both addresses, we can override the poweroff hook */
@@ -88,14 +88,11 @@
 
 static int __devexit olpc_xo1_remove(struct platform_device *pdev)
 {
-	struct resource *r;
-
-	r = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(r->start, resource_size(r));
+	mfd_cell_disable(pdev);
 
 	if (strcmp(pdev->name, "cs5535-pms") == 0)
 		pms_base = 0;
-	else if (strcmp(pdev->name, "cs5535-acpi") == 0)
+	else if (strcmp(pdev->name, "olpc-xo1-pm-acpi") == 0)
 		acpi_base = 0;
 
 	pm_power_off = NULL;
@@ -113,7 +110,7 @@
 
 static struct platform_driver cs5535_acpi_drv = {
 	.driver = {
-		.name = "cs5535-acpi",
+		.name = "olpc-xo1-pm-acpi",
 		.owner = THIS_MODULE,
 	},
 	.probe = olpc_xo1_probe,
@@ -143,7 +140,7 @@
 
 MODULE_AUTHOR("Daniel Drake <dsd@laptop.org>");
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:olpc-xo1");
+MODULE_ALIAS("platform:cs5535-pms");
 
 module_init(olpc_xo1_init);
 module_exit(olpc_xo1_exit);
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/uv/tlb_uv.c linux-libre-2.6.39-gnu/arch/x86/platform/uv/tlb_uv.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/uv/tlb_uv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/uv/tlb_uv.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/debugfs.h>
 #include <linux/kernel.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 
 #include <asm/mmu_context.h>
 #include <asm/uv/uv.h>
@@ -698,16 +699,17 @@
 					  struct mm_struct *mm,
 					  unsigned long va, unsigned int cpu)
 {
-	int tcpu;
-	int uvhub;
 	int locals = 0;
 	int remotes = 0;
 	int hubs = 0;
+	int tcpu;
+	int tpnode;
 	struct bau_desc *bau_desc;
 	struct cpumask *flush_mask;
 	struct ptc_stats *stat;
 	struct bau_control *bcp;
 	struct bau_control *tbcp;
+	struct hub_and_pnode *hpp;
 
 	/* kernel was booted 'nobau' */
 	if (nobau)
@@ -749,11 +751,18 @@
 	bau_desc += UV_ITEMS_PER_DESCRIPTOR * bcp->uvhub_cpu;
 	bau_uvhubs_clear(&bau_desc->distribution, UV_DISTRIBUTION_SIZE);
 
-	/* cpu statistics */
 	for_each_cpu(tcpu, flush_mask) {
-		uvhub = uv_cpu_to_blade_id(tcpu);
-		bau_uvhub_set(uvhub, &bau_desc->distribution);
-		if (uvhub == bcp->uvhub)
+		/*
+		 * The distribution vector is a bit map of pnodes, relative
+		 * to the partition base pnode (and the partition base nasid
+		 * in the header).
+		 * Translate cpu to pnode and hub using an array stored
+		 * in local memory.
+		 */
+		hpp = &bcp->socket_master->target_hub_and_pnode[tcpu];
+		tpnode = hpp->pnode - bcp->partition_base_pnode;
+		bau_uvhub_set(tpnode, &bau_desc->distribution);
+		if (hpp->uvhub == bcp->uvhub)
 			locals++;
 		else
 			remotes++;
@@ -854,7 +863,7 @@
  * an interrupt, but causes an error message to be returned to
  * the sender.
  */
-static void uv_enable_timeouts(void)
+static void __init uv_enable_timeouts(void)
 {
 	int uvhub;
 	int nuvhubs;
@@ -1325,10 +1334,10 @@
 }
 
 /*
- * initialize the sending side's sending buffers
+ * Initialize the sending side's sending buffers.
  */
 static void
-uv_activation_descriptor_init(int node, int pnode)
+uv_activation_descriptor_init(int node, int pnode, int base_pnode)
 {
 	int i;
 	int cpu;
@@ -1351,11 +1360,11 @@
 	n = pa >> uv_nshift;
 	m = pa & uv_mmask;
 
+	/* the 14-bit pnode */
 	uv_write_global_mmr64(pnode, UVH_LB_BAU_SB_DESCRIPTOR_BASE,
 			      (n << UV_DESC_BASE_PNODE_SHIFT | m));
-
 	/*
-	 * initializing all 8 (UV_ITEMS_PER_DESCRIPTOR) descriptors for each
+	 * 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 uv hubs.
 	 */
@@ -1364,12 +1373,13 @@
 		memset(bd2, 0, sizeof(struct bau_desc));
 		bd2->header.sw_ack_flag = 1;
 		/*
-		 * base_dest_nodeid is the nasid of the first uvhub
-		 * in the partition. The bit map will indicate uvhub numbers,
-		 * which are 0-N in a partition. Pnodes are unique system-wide.
+		 * The base_dest_nasid set in the message header is the nasid
+		 * of the first uvhub in the partition. The bit map will
+		 * indicate destination pnode numbers relative to that base.
+		 * They may not be consecutive if nasid striding is being used.
 		 */
-		bd2->header.base_dest_nodeid = UV_PNODE_TO_NASID(uv_partition_base_pnode);
-		bd2->header.dest_subnodeid = 0x10; /* the LB */
+		bd2->header.base_dest_nasid = UV_PNODE_TO_NASID(base_pnode);
+		bd2->header.dest_subnodeid = UV_LB_SUBNODEID;
 		bd2->header.command = UV_NET_ENDPOINT_INTD;
 		bd2->header.int_both = 1;
 		/*
@@ -1441,7 +1451,7 @@
 /*
  * Initialization of each UV hub's structures
  */
-static void __init uv_init_uvhub(int uvhub, int vector)
+static void __init uv_init_uvhub(int uvhub, int vector, int base_pnode)
 {
 	int node;
 	int pnode;
@@ -1449,11 +1459,11 @@
 
 	node = uvhub_to_first_node(uvhub);
 	pnode = uv_blade_to_pnode(uvhub);
-	uv_activation_descriptor_init(node, pnode);
+	uv_activation_descriptor_init(node, pnode, base_pnode);
 	uv_payload_queue_init(node, pnode);
 	/*
-	 * the below initialization can't be in firmware because the
-	 * messaging IRQ will be determined by the OS
+	 * The below initialization can't be in firmware because the
+	 * messaging IRQ will be determined by the OS.
 	 */
 	apicid = uvhub_to_first_apicid(uvhub) | uv_apicid_hibits;
 	uv_write_global_mmr64(pnode, UVH_BAU_DATA_CONFIG,
@@ -1490,10 +1500,11 @@
 /*
  * initialize the bau_control structure for each cpu
  */
-static int __init uv_init_per_cpu(int nuvhubs)
+static int __init uv_init_per_cpu(int nuvhubs, int base_part_pnode)
 {
 	int i;
 	int cpu;
+	int tcpu;
 	int pnode;
 	int uvhub;
 	int have_hmaster;
@@ -1527,6 +1538,15 @@
 		bcp = &per_cpu(bau_control, cpu);
 		memset(bcp, 0, sizeof(struct bau_control));
 		pnode = uv_cpu_hub_info(cpu)->pnode;
+		if ((pnode - base_part_pnode) >= UV_DISTRIBUTION_SIZE) {
+			printk(KERN_EMERG
+				"cpu %d pnode %d-%d beyond %d; BAU disabled\n",
+				cpu, pnode, base_part_pnode,
+				UV_DISTRIBUTION_SIZE);
+			return 1;
+		}
+		bcp->osnode = cpu_to_node(cpu);
+		bcp->partition_base_pnode = uv_partition_base_pnode;
 		uvhub = uv_cpu_hub_info(cpu)->numa_blade_id;
 		*(uvhub_mask + (uvhub/8)) |= (1 << (uvhub%8));
 		bdp = &uvhub_descs[uvhub];
@@ -1535,7 +1555,7 @@
 		bdp->pnode = pnode;
 		/* kludge: 'assuming' one node per socket, and assuming that
 		   disabling a socket just leaves a gap in node numbers */
-		socket = (cpu_to_node(cpu) & 1);
+		socket = bcp->osnode & 1;
 		bdp->socket_mask |= (1 << socket);
 		sdp = &bdp->socket[socket];
 		sdp->cpu_number[sdp->num_cpus] = cpu;
@@ -1584,6 +1604,20 @@
 nextsocket:
 			socket++;
 			socket_mask = (socket_mask >> 1);
+			/* each socket gets a local array of pnodes/hubs */
+			bcp = smaster;
+			bcp->target_hub_and_pnode = kmalloc_node(
+				sizeof(struct hub_and_pnode) *
+				num_possible_cpus(), GFP_KERNEL, bcp->osnode);
+			memset(bcp->target_hub_and_pnode, 0,
+				sizeof(struct hub_and_pnode) *
+				num_possible_cpus());
+			for_each_present_cpu(tcpu) {
+				bcp->target_hub_and_pnode[tcpu].pnode =
+					uv_cpu_hub_info(tcpu)->pnode;
+				bcp->target_hub_and_pnode[tcpu].uvhub =
+					uv_cpu_hub_info(tcpu)->numa_blade_id;
+			}
 		}
 	}
 	kfree(uvhub_descs);
@@ -1636,21 +1670,22 @@
 	spin_lock_init(&disable_lock);
 	congested_cycles = microsec_2_cycles(congested_response_us);
 
-	if (uv_init_per_cpu(nuvhubs)) {
-		nobau = 1;
-		return 0;
-	}
-
 	uv_partition_base_pnode = 0x7fffffff;
-	for (uvhub = 0; uvhub < nuvhubs; uvhub++)
+	for (uvhub = 0; uvhub < nuvhubs; uvhub++) {
 		if (uv_blade_nr_possible_cpus(uvhub) &&
 			(uv_blade_to_pnode(uvhub) < uv_partition_base_pnode))
 			uv_partition_base_pnode = uv_blade_to_pnode(uvhub);
+	}
+
+	if (uv_init_per_cpu(nuvhubs, uv_partition_base_pnode)) {
+		nobau = 1;
+		return 0;
+	}
 
 	vector = UV_BAU_MESSAGE;
 	for_each_possible_blade(uvhub)
 		if (uv_blade_nr_possible_cpus(uvhub))
-			uv_init_uvhub(uvhub, vector);
+			uv_init_uvhub(uvhub, vector, uv_partition_base_pnode);
 
 	uv_enable_timeouts();
 	alloc_intr_gate(vector, uv_bau_message_intr1);
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/uv/uv_irq.c linux-libre-2.6.39-gnu/arch/x86/platform/uv/uv_irq.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/uv/uv_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/uv/uv_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -131,7 +131,7 @@
 		       unsigned long mmr_offset, int limit)
 {
 	const struct cpumask *eligible_cpu = cpumask_of(cpu);
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 	unsigned long mmr_value;
 	struct uv_IO_APIC_route_entry *entry;
 	int mmr_pnode, err;
@@ -148,7 +148,7 @@
 	else
 		irq_set_status_flags(irq, IRQ_MOVE_PCNTXT);
 
-	set_irq_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
+	irq_set_chip_and_handler_name(irq, &uv_irq_chip, handle_percpu_irq,
 				      irq_name);
 
 	mmr_value = 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/platform/visws/visws_quirks.c linux-libre-2.6.39-gnu/arch/x86/platform/visws/visws_quirks.c
--- linux-libre-2.6.38-gnu/arch/x86/platform/visws/visws_quirks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/platform/visws/visws_quirks.c	2011-05-19 00:06:34.000000000 -0400
@@ -471,15 +471,7 @@
 {
 	legacy_pic->init(0);
 	enable_cobalt_irq(data);
-}
-
-static void end_piix4_master_irq(struct irq_data *data)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cobalt_lock, flags);
-	enable_cobalt_irq(data);
-	spin_unlock_irqrestore(&cobalt_lock, flags);
+	return 0;
 }
 
 static struct irq_chip piix4_master_irq_type = {
@@ -492,7 +484,7 @@
 
 static struct irq_chip piix4_virtual_irq_type = {
 	.name		= "PIIX4-virtual",
-	.mask		= pii4_mask,
+	.irq_mask	= pii4_mask,
 };
 
 /*
@@ -569,18 +561,20 @@
 static struct irqaction master_action = {
 	.handler =	piix4_master_intr,
 	.name =		"PIIX4-8259",
+	.flags =	IRQF_NO_THREAD,
 };
 
 static struct irqaction cascade_action = {
 	.handler = 	no_action,
 	.name =		"cascade",
+	.flags =	IRQF_NO_THREAD,
 };
 
 static inline void set_piix4_virtual_irq_type(void)
 {
-	piix4_virtual_irq_type.enable =	i8259A_chip.unmask;
-	piix4_virtual_irq_type.disable = i8259A_chip.mask;
-	piix4_virtual_irq_type.unmask =	i8259A_chip.unmask;
+	piix4_virtual_irq_type.irq_enable = i8259A_chip.irq_unmask;
+	piix4_virtual_irq_type.irq_disable = i8259A_chip.irq_mask;
+	piix4_virtual_irq_type.irq_unmask = i8259A_chip.irq_unmask;
 }
 
 static void __init visws_pre_intr_init(void)
@@ -597,7 +591,7 @@
 		else if (i == CO_IRQ_IDE0)
 			chip = &cobalt_irq_type;
 		else if (i == CO_IRQ_IDE1)
-			>chip = &cobalt_irq_type;
+			chip = &cobalt_irq_type;
 		else if (i == CO_IRQ_8259)
 			chip = &piix4_master_irq_type;
 		else if (i < CO_IRQ_APIC0)
@@ -606,7 +600,7 @@
 			chip = &cobalt_irq_type;
 
 		if (chip)
-			set_irq_chip(i, chip);
+			irq_set_chip(i, chip);
 	}
 
 	setup_irq(CO_IRQ_8259, &master_action);
diff -druN linux-libre-2.6.38-gnu/arch/x86/vdso/vdso32-setup.c linux-libre-2.6.39-gnu/arch/x86/vdso/vdso32-setup.c
--- linux-libre-2.6.38-gnu/arch/x86/vdso/vdso32-setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/vdso/vdso32-setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -417,24 +417,25 @@
 	return NULL;
 }
 
-struct vm_area_struct *get_gate_vma(struct task_struct *tsk)
+struct vm_area_struct *get_gate_vma(struct mm_struct *mm)
 {
-	struct mm_struct *mm = tsk->mm;
-
-	/* Check to see if this task was created in compat vdso mode */
+	/*
+	 * Check to see if the corresponding task was created in compat vdso
+	 * mode.
+	 */
 	if (mm && mm->context.vdso == (void *)VDSO_HIGH_BASE)
 		return &gate_vma;
 	return NULL;
 }
 
-int in_gate_area(struct task_struct *task, unsigned long addr)
+int in_gate_area(struct mm_struct *mm, unsigned long addr)
 {
-	const struct vm_area_struct *vma = get_gate_vma(task);
+	const struct vm_area_struct *vma = get_gate_vma(mm);
 
 	return vma && addr >= vma->vm_start && addr < vma->vm_end;
 }
 
-int in_gate_area_no_task(unsigned long addr)
+int in_gate_area_no_mm(unsigned long addr)
 {
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/enlighten.c linux-libre-2.6.39-gnu/arch/x86/xen/enlighten.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/enlighten.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/enlighten.c	2011-05-19 00:06:34.000000000 -0400
@@ -238,6 +238,7 @@
 static __init void xen_init_cpuid_mask(void)
 {
 	unsigned int ax, bx, cx, dx;
+	unsigned int xsave_mask;
 
 	cpuid_leaf1_edx_mask =
 		~((1 << X86_FEATURE_MCE)  |  /* disable MCE */
@@ -249,24 +250,16 @@
 		cpuid_leaf1_edx_mask &=
 			~((1 << X86_FEATURE_APIC) |  /* disable local APIC */
 			  (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 */
-	if (cx & (1 << (X86_FEATURE_XSAVE % 32))) {
-		unsigned long cr4;
-
-		set_in_cr4(X86_CR4_OSXSAVE);
-		
-		cr4 = read_cr4();
-
-		if ((cr4 & X86_CR4_OSXSAVE) == 0)
-			cpuid_leaf1_ecx_mask &= ~(1 << (X86_FEATURE_XSAVE % 32));
+	xsave_mask =
+		(1 << (X86_FEATURE_XSAVE % 32)) |
+		(1 << (X86_FEATURE_OSXSAVE % 32));
 
-		clear_in_cr4(X86_CR4_OSXSAVE);
-	}
+	/* Xen will set CR4.OSXSAVE if supported and not disabled by force */
+	if ((cx & xsave_mask) != xsave_mask)
+		cpuid_leaf1_ecx_mask &= ~xsave_mask; /* disable XSAVE & OSXSAVE */
 }
 
 static void xen_set_debugreg(int reg, unsigned long val)
@@ -1284,15 +1277,14 @@
 
 	xen_setup_features();
 
-	pv_info = xen_info;
-	pv_info.kernel_rpl = 0;
+	pv_info.name = "Xen HVM";
 
 	xen_domain_type = XEN_HVM_DOMAIN;
 
 	return 0;
 }
 
-void xen_hvm_init_shared_info(void)
+void __ref xen_hvm_init_shared_info(void)
 {
 	int cpu;
 	struct xen_add_to_physmap xatp;
@@ -1331,6 +1323,8 @@
 	switch (action) {
 	case CPU_UP_PREPARE:
 		per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
+		if (xen_have_vector_callback)
+			xen_init_lock_cpu(cpu);
 		break;
 	default:
 		break;
@@ -1355,6 +1349,7 @@
 
 	if (xen_feature(XENFEAT_hvm_callback_vector))
 		xen_have_vector_callback = 1;
+	xen_hvm_smp_init();
 	register_cpu_notifier(&xen_hvm_cpu_notifier);
 	xen_unplug_emulated_devices();
 	have_vcpu_info_placement = 0;
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/Kconfig linux-libre-2.6.39-gnu/arch/x86/xen/Kconfig
--- linux-libre-2.6.38-gnu/arch/x86/xen/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,8 @@
 
 config XEN_SAVE_RESTORE
        bool
-       depends on XEN && PM
+       depends on XEN
+       select HIBERNATE_CALLBACKS
        default y
 
 config XEN_DEBUG_FS
@@ -48,3 +49,11 @@
 	help
 	  Enable statistics output and various tuning options in debugfs.
 	  Enabling this option may incur a significant performance overhead.
+
+config XEN_DEBUG
+	bool "Enable Xen debug checks"
+	depends on XEN
+	default n
+	help
+	  Enable various WARN_ON checks in the Xen MMU code.
+	  Enabling this option WILL incur a significant performance overhead.
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/mmu.c linux-libre-2.6.39-gnu/arch/x86/xen/mmu.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/mmu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/mmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,6 +46,7 @@
 #include <linux/module.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
+#include <linux/seq_file.h>
 
 #include <asm/pgtable.h>
 #include <asm/tlbflush.h>
@@ -78,8 +79,7 @@
 
 /*
  * Protects atomic reservation decrease/increase against concurrent increases.
- * Also protects non-atomic updates of current_pages and driver_pages, and
- * balloon lists.
+ * Also protects non-atomic updates of current_pages and balloon lists.
  */
 DEFINE_SPINLOCK(xen_reservation_lock);
 
@@ -416,8 +416,12 @@
 	if (val & _PAGE_PRESENT) {
 		unsigned long pfn = (val & PTE_PFN_MASK) >> PAGE_SHIFT;
 		pteval_t flags = val & PTE_FLAGS_MASK;
-		unsigned long mfn = pfn_to_mfn(pfn);
+		unsigned long mfn;
 
+		if (!xen_feature(XENFEAT_auto_translated_physmap))
+			mfn = get_phys_to_machine(pfn);
+		else
+			mfn = pfn;
 		/*
 		 * If there's no mfn for the pfn, then just create an
 		 * empty non-present pte.  Unfortunately this loses
@@ -427,8 +431,18 @@
 		if (unlikely(mfn == INVALID_P2M_ENTRY)) {
 			mfn = 0;
 			flags = 0;
+		} else {
+			/*
+			 * Paramount to do this test _after_ the
+			 * INVALID_P2M_ENTRY as INVALID_P2M_ENTRY &
+			 * IDENTITY_FRAME_BIT resolves to true.
+			 */
+			mfn &= ~FOREIGN_FRAME_BIT;
+			if (mfn & IDENTITY_FRAME_BIT) {
+				mfn &= ~IDENTITY_FRAME_BIT;
+				flags |= _PAGE_IOMAP;
+			}
 		}
-
 		val = ((pteval_t)mfn << PAGE_SHIFT) | flags;
 	}
 
@@ -532,6 +546,41 @@
 }
 PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte);
 
+#ifdef CONFIG_XEN_DEBUG
+pte_t xen_make_pte_debug(pteval_t pte)
+{
+	phys_addr_t addr = (pte & PTE_PFN_MASK);
+	phys_addr_t other_addr;
+	bool io_page = false;
+	pte_t _pte;
+
+	if (pte & _PAGE_IOMAP)
+		io_page = true;
+
+	_pte = xen_make_pte(pte);
+
+	if (!addr)
+		return _pte;
+
+	if (io_page &&
+	    (xen_initial_domain() || addr >= ISA_END_ADDRESS)) {
+		other_addr = pfn_to_mfn(addr >> PAGE_SHIFT) << PAGE_SHIFT;
+		WARN_ONCE(addr != other_addr,
+			"0x%lx is using VM_IO, but it is 0x%lx!\n",
+			(unsigned long)addr, (unsigned long)other_addr);
+	} else {
+		pteval_t iomap_set = (_pte.pte & PTE_FLAGS_MASK) & _PAGE_IOMAP;
+		other_addr = (_pte.pte & PTE_PFN_MASK);
+		WARN_ONCE((addr == other_addr) && (!io_page) && (!iomap_set),
+			"0x%lx is missing VM_IO (and wasn't fixed)!\n",
+			(unsigned long)addr);
+	}
+
+	return _pte;
+}
+PV_CALLEE_SAVE_REGS_THUNK(xen_make_pte_debug);
+#endif
+
 pgd_t xen_make_pgd(pgdval_t pgd)
 {
 	pgd = pte_pfn_to_mfn(pgd);
@@ -1226,6 +1275,20 @@
 {
 }
 
+static __init void xen_mapping_pagetable_reserve(u64 start, u64 end)
+{
+	/* reserve the range used */
+	native_pagetable_reserve(start, end);
+
+	/* set as RW the rest */
+	printk(KERN_DEBUG "xen: setting RW the range %llx - %llx\n", end,
+			PFN_PHYS(pgt_buf_top));
+	while (end < PFN_PHYS(pgt_buf_top)) {
+		make_lowmem_page_readwrite(__va(end));
+		end += PAGE_SIZE;
+	}
+}
+
 static void xen_post_allocator_init(void);
 
 static __init void xen_pagetable_setup_done(pgd_t *base)
@@ -1424,28 +1487,35 @@
 #endif
 }
 
+#ifdef CONFIG_X86_32
 static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
 {
-	unsigned long pfn = pte_pfn(pte);
-
-#ifdef CONFIG_X86_32
 	/* If there's an existing pte, then don't allow _PAGE_RW to be set */
 	if (pte_val_ma(*ptep) & _PAGE_PRESENT)
 		pte = __pte_ma(((pte_val_ma(*ptep) & _PAGE_RW) | ~_PAGE_RW) &
 			       pte_val_ma(pte));
-#endif
+
+	return pte;
+}
+#else /* CONFIG_X86_64 */
+static __init pte_t mask_rw_pte(pte_t *ptep, pte_t pte)
+{
+	unsigned long pfn = pte_pfn(pte);
 
 	/*
 	 * If the new pfn is within the range of the newly allocated
 	 * kernel pagetable, and it isn't being mapped into an
-	 * early_ioremap fixmap slot, make sure it is RO.
+	 * early_ioremap fixmap slot as a freshly allocated page, make sure
+	 * it is RO.
 	 */
-	if (!is_early_ioremap_ptep(ptep) &&
-	    pfn >= e820_table_start && pfn < e820_table_end)
+	if (((!is_early_ioremap_ptep(ptep) &&
+			pfn >= pgt_buf_start && pfn < pgt_buf_top)) ||
+			(is_early_ioremap_ptep(ptep) && pfn != (pgt_buf_end - 1)))
 		pte = pte_wrprotect(pte);
 
 	return pte;
 }
+#endif /* CONFIG_X86_64 */
 
 /* Init-time set_pte while constructing initial pagetables, which
    doesn't allow RO pagetable pages to be remapped RW */
@@ -1651,9 +1721,6 @@
 		for (pteidx = 0; pteidx < PTRS_PER_PTE; pteidx++, pfn++) {
 			pte_t pte;
 
-			if (pfn > max_pfn_mapped)
-				max_pfn_mapped = pfn;
-
 			if (!pte_none(pte_page[pteidx]))
 				continue;
 
@@ -1695,7 +1762,7 @@
 }
 
 /*
- * Set up the inital kernel pagetable.
+ * Set up the initial kernel pagetable.
  *
  * We can construct this by grafting the Xen provided pagetable into
  * head_64.S's preconstructed pagetables.  We copy the Xen L2's into
@@ -1711,6 +1778,12 @@
 	pud_t *l3;
 	pmd_t *l2;
 
+	/* max_pfn_mapped is the last pfn mapped in the initial memory
+	 * mappings. Considering that on Xen after the kernel mappings we
+	 * have the mappings of some pages that don't exist in pfn space, we
+	 * set max_pfn_mapped to the last real pfn mapped. */
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
+
 	/* Zap identity mapping */
 	init_level4_pgt[0] = __pgd(0);
 
@@ -1815,9 +1888,7 @@
 	initial_kernel_pmd =
 		extend_brk(sizeof(pmd_t) * PTRS_PER_PMD, PAGE_SIZE);
 
-	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->pt_base) +
-				  xen_start_info->nr_pt_frames * PAGE_SIZE +
-				  512*1024);
+	max_pfn_mapped = PFN_DOWN(__pa(xen_start_info->mfn_list));
 
 	kernel_pmd = m2v(pgd[KERNEL_PGD_BOUNDARY].pgd);
 	memcpy(initial_kernel_pmd, kernel_pmd, sizeof(pmd_t) * PTRS_PER_PMD);
@@ -1940,6 +2011,9 @@
 
 static __init void xen_post_allocator_init(void)
 {
+#ifdef CONFIG_XEN_DEBUG
+	pv_mmu_ops.make_pte = PV_CALLEE_SAVE(xen_make_pte_debug);
+#endif
 	pv_mmu_ops.set_pte = xen_set_pte;
 	pv_mmu_ops.set_pmd = xen_set_pmd;
 	pv_mmu_ops.set_pud = xen_set_pud;
@@ -2045,6 +2119,7 @@
 
 void __init xen_init_mmu_ops(void)
 {
+	x86_init.mapping.pagetable_reserve = xen_mapping_pagetable_reserve;
 	x86_init.paging.pagetable_setup_start = xen_pagetable_setup_start;
 	x86_init.paging.pagetable_setup_done = xen_pagetable_setup_done;
 	pv_mmu_ops = xen_mmu_ops;
@@ -2072,7 +2147,7 @@
 			in_frames[i] = virt_to_mfn(vaddr);
 
 		MULTI_update_va_mapping(mcs.mc, vaddr, VOID_PTE, 0);
-		set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);
+		__set_phys_to_machine(virt_to_pfn(vaddr), INVALID_P2M_ENTRY);
 
 		if (out_frames)
 			out_frames[i] = virt_to_pfn(vaddr);
@@ -2351,6 +2426,18 @@
 
 #ifdef CONFIG_XEN_DEBUG_FS
 
+static int p2m_dump_open(struct inode *inode, struct file *filp)
+{
+	return single_open(filp, p2m_dump_show, NULL);
+}
+
+static const struct file_operations p2m_dump_fops = {
+	.open		= p2m_dump_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
 static struct dentry *d_mmu_debug;
 
 static int __init xen_mmu_debugfs(void)
@@ -2406,6 +2493,7 @@
 	debugfs_create_u32("prot_commit_batched", 0444, d_mmu_debug,
 			   &mmu_stats.prot_commit_batched);
 
+	debugfs_create_file("p2m", 0600, d_mmu_debug, NULL, &p2m_dump_fops);
 	return 0;
 }
 fs_initcall(xen_mmu_debugfs);
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/p2m.c linux-libre-2.6.39-gnu/arch/x86/xen/p2m.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/p2m.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/p2m.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,129 @@
  * P2M_PER_PAGE depends on the architecture, as a mfn is always
  * unsigned long (8 bytes on 64-bit, 4 bytes on 32), leading to
  * 512 and 1024 entries respectively. 
+ *
+ * In short, these structures contain the Machine Frame Number (MFN) of the PFN.
+ *
+ * However not all entries are filled with MFNs. Specifically for all other
+ * leaf entries, or for the top  root, or middle one, for which there is a void
+ * entry, we assume it is  "missing". So (for example)
+ *  pfn_to_mfn(0x90909090)=INVALID_P2M_ENTRY.
+ *
+ * We also have the possibility of setting 1-1 mappings on certain regions, so
+ * that:
+ *  pfn_to_mfn(0xc0000)=0xc0000
+ *
+ * The benefit of this is, that we can assume for non-RAM regions (think
+ * PCI BARs, or ACPI spaces), we can create mappings easily b/c we
+ * get the PFN value to match the MFN.
+ *
+ * For this to work efficiently we have one new page p2m_identity and
+ * allocate (via reserved_brk) any other pages we need to cover the sides
+ * (1GB or 4MB boundary violations). All entries in p2m_identity are set to
+ * INVALID_P2M_ENTRY type (Xen toolstack only recognizes that and MFNs,
+ * no other fancy value).
+ *
+ * On lookup we spot that the entry points to p2m_identity and return the
+ * identity value instead of dereferencing and returning INVALID_P2M_ENTRY.
+ * If the entry points to an allocated page, we just proceed as before and
+ * return the PFN.  If the PFN has IDENTITY_FRAME_BIT set we unmask that in
+ * appropriate functions (pfn_to_mfn).
+ *
+ * The reason for having the IDENTITY_FRAME_BIT instead of just returning the
+ * PFN is that we could find ourselves where pfn_to_mfn(pfn)==pfn for a
+ * non-identity pfn. To protect ourselves against we elect to set (and get) the
+ * IDENTITY_FRAME_BIT on all identity mapped PFNs.
+ *
+ * This simplistic diagram is used to explain the more subtle piece of code.
+ * There is also a digram of the P2M at the end that can help.
+ * Imagine your E820 looking as so:
+ *
+ *                    1GB                                           2GB
+ * /-------------------+---------\/----\         /----------\    /---+-----\
+ * | System RAM        | Sys RAM ||ACPI|         | reserved |    | Sys RAM |
+ * \-------------------+---------/\----/         \----------/    \---+-----/
+ *                               ^- 1029MB                       ^- 2001MB
+ *
+ * [1029MB = 263424 (0x40500), 2001MB = 512256 (0x7D100),
+ *  2048MB = 524288 (0x80000)]
+ *
+ * And dom0_mem=max:3GB,1GB is passed in to the guest, meaning memory past 1GB
+ * is actually not present (would have to kick the balloon driver to put it in).
+ *
+ * When we are told to set the PFNs for identity mapping (see patch: "xen/setup:
+ * Set identity mapping for non-RAM E820 and E820 gaps.") we pass in the start
+ * of the PFN and the end PFN (263424 and 512256 respectively). The first step
+ * is to reserve_brk a top leaf page if the p2m[1] is missing. The top leaf page
+ * covers 512^2 of page estate (1GB) and in case the start or end PFN is not
+ * aligned on 512^2*PAGE_SIZE (1GB) we loop on aligned 1GB PFNs from start pfn
+ * to end pfn.  We reserve_brk top leaf pages if they are missing (means they
+ * point to p2m_mid_missing).
+ *
+ * With the E820 example above, 263424 is not 1GB aligned so we allocate a
+ * reserve_brk page which will cover the PFNs estate from 0x40000 to 0x80000.
+ * Each entry in the allocate page is "missing" (points to p2m_missing).
+ *
+ * Next stage is to determine if we need to do a more granular boundary check
+ * on the 4MB (or 2MB depending on architecture) off the start and end pfn's.
+ * We check if the start pfn and end pfn violate that boundary check, and if
+ * so reserve_brk a middle (p2m[x][y]) leaf page. This way we have a much finer
+ * granularity of setting which PFNs are missing and which ones are identity.
+ * In our example 263424 and 512256 both fail the check so we reserve_brk two
+ * pages. Populate them with INVALID_P2M_ENTRY (so they both have "missing"
+ * values) and assign them to p2m[1][2] and p2m[1][488] respectively.
+ *
+ * At this point we would at minimum reserve_brk one page, but could be up to
+ * three. Each call to set_phys_range_identity has at maximum a three page
+ * cost. If we were to query the P2M at this stage, all those entries from
+ * start PFN through end PFN (so 1029MB -> 2001MB) would return
+ * INVALID_P2M_ENTRY ("missing").
+ *
+ * The next step is to walk from the start pfn to the end pfn setting
+ * the IDENTITY_FRAME_BIT on each PFN. This is done in set_phys_range_identity.
+ * If we find that the middle leaf is pointing to p2m_missing we can swap it
+ * over to p2m_identity - this way covering 4MB (or 2MB) PFN space.  At this
+ * point we do not need to worry about boundary aligment (so no need to
+ * reserve_brk a middle page, figure out which PFNs are "missing" and which
+ * ones are identity), as that has been done earlier.  If we find that the
+ * middle leaf is not occupied by p2m_identity or p2m_missing, we dereference
+ * that page (which covers 512 PFNs) and set the appropriate PFN with
+ * IDENTITY_FRAME_BIT. In our example 263424 and 512256 end up there, and we
+ * set from p2m[1][2][256->511] and p2m[1][488][0->256] with
+ * IDENTITY_FRAME_BIT set.
+ *
+ * All other regions that are void (or not filled) either point to p2m_missing
+ * (considered missing) or have the default value of INVALID_P2M_ENTRY (also
+ * considered missing). In our case, p2m[1][2][0->255] and p2m[1][488][257->511]
+ * contain the INVALID_P2M_ENTRY value and are considered "missing."
+ *
+ * This is what the p2m ends up looking (for the E820 above) with this
+ * fabulous drawing:
+ *
+ *    p2m         /--------------\
+ *  /-----\       | &mfn_list[0],|                           /-----------------\
+ *  |  0  |------>| &mfn_list[1],|    /---------------\      | ~0, ~0, ..      |
+ *  |-----|       |  ..., ~0, ~0 |    | ~0, ~0, [x]---+----->| IDENTITY [@256] |
+ *  |  1  |---\   \--------------/    | [p2m_identity]+\     | IDENTITY [@257] |
+ *  |-----|    \                      | [p2m_identity]+\\    | ....            |
+ *  |  2  |--\  \-------------------->|  ...          | \\   \----------------/
+ *  |-----|   \                       \---------------/  \\
+ *  |  3  |\   \                                          \\  p2m_identity
+ *  |-----| \   \-------------------->/---------------\   /-----------------\
+ *  | ..  +->+                        | [p2m_identity]+-->| ~0, ~0, ~0, ... |
+ *  \-----/ /                         | [p2m_identity]+-->| ..., ~0         |
+ *         / /---------------\        | ....          |   \-----------------/
+ *        /  | IDENTITY[@0]  |      /-+-[x], ~0, ~0.. |
+ *       /   | IDENTITY[@256]|<----/  \---------------/
+ *      /    | ~0, ~0, ....  |
+ *     |     \---------------/
+ *     |
+ *     p2m_missing             p2m_missing
+ * /------------------\     /------------\
+ * | [p2m_mid_missing]+---->| ~0, ~0, ~0 |
+ * | [p2m_mid_missing]+---->| ..., ~0    |
+ * \------------------/     \------------/
+ *
+ * where ~0 is INVALID_P2M_ENTRY. IDENTITY is (PFN | IDENTITY_BIT)
  */
 
 #include <linux/init.h>
@@ -30,6 +153,7 @@
 #include <linux/list.h>
 #include <linux/hash.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 
 #include <asm/cache.h>
 #include <asm/setup.h>
@@ -59,9 +183,15 @@
 static RESERVE_BRK_ARRAY(unsigned long, p2m_top_mfn, P2M_TOP_PER_PAGE);
 static RESERVE_BRK_ARRAY(unsigned long *, p2m_top_mfn_p, P2M_TOP_PER_PAGE);
 
+static RESERVE_BRK_ARRAY(unsigned long, p2m_identity, P2M_PER_PAGE);
+
 RESERVE_BRK(p2m_mid, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 RESERVE_BRK(p2m_mid_mfn, PAGE_SIZE * (MAX_DOMAIN_PAGES / (P2M_PER_PAGE * P2M_MID_PER_PAGE)));
 
+/* We might hit two boundary violations at the start and end, at max each
+ * boundary violation will require three middle nodes. */
+RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
+
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
 	BUG_ON(pfn >= MAX_P2M_PFN);
@@ -136,7 +266,7 @@
  * - After resume we're called from within stop_machine, but the mfn
  *   tree should alreay be completely allocated.
  */
-void xen_build_mfn_list_list(void)
+void __ref xen_build_mfn_list_list(void)
 {
 	unsigned long pfn;
 
@@ -221,6 +351,9 @@
 	p2m_top = extend_brk(PAGE_SIZE, PAGE_SIZE);
 	p2m_top_init(p2m_top);
 
+	p2m_identity = extend_brk(PAGE_SIZE, PAGE_SIZE);
+	p2m_init(p2m_identity);
+
 	/*
 	 * The domain builder gives us a pre-constructed p2m array in
 	 * mfn_list for all the pages initially given to us, so we just
@@ -266,6 +399,14 @@
 	mididx = p2m_mid_index(pfn);
 	idx = p2m_index(pfn);
 
+	/*
+	 * The INVALID_P2M_ENTRY is filled in both p2m_*identity
+	 * and in p2m_*missing, so returning the INVALID_P2M_ENTRY
+	 * would be wrong.
+	 */
+	if (p2m_top[topidx][mididx] == p2m_identity)
+		return IDENTITY_FRAME(pfn);
+
 	return p2m_top[topidx][mididx][idx];
 }
 EXPORT_SYMBOL_GPL(get_phys_to_machine);
@@ -335,9 +476,11 @@
 			p2m_top_mfn_p[topidx] = mid_mfn;
 	}
 
-	if (p2m_top[topidx][mididx] == p2m_missing) {
+	if (p2m_top[topidx][mididx] == p2m_identity ||
+	    p2m_top[topidx][mididx] == p2m_missing) {
 		/* p2m leaf page is missing */
 		unsigned long *p2m;
+		unsigned long *p2m_orig = p2m_top[topidx][mididx];
 
 		p2m = alloc_p2m_page();
 		if (!p2m)
@@ -345,7 +488,7 @@
 
 		p2m_init(p2m);
 
-		if (cmpxchg(&mid[mididx], p2m_missing, p2m) != p2m_missing)
+		if (cmpxchg(&mid[mididx], p2m_orig, p2m) != p2m_orig)
 			free_p2m_page(p2m);
 		else
 			mid_mfn[mididx] = virt_to_mfn(p2m);
@@ -354,11 +497,91 @@
 	return true;
 }
 
+static bool __init __early_alloc_p2m(unsigned long pfn)
+{
+	unsigned topidx, mididx, idx;
+
+	topidx = p2m_top_index(pfn);
+	mididx = p2m_mid_index(pfn);
+	idx = p2m_index(pfn);
+
+	/* Pfff.. No boundary cross-over, lets get out. */
+	if (!idx)
+		return false;
+
+	WARN(p2m_top[topidx][mididx] == p2m_identity,
+		"P2M[%d][%d] == IDENTITY, should be MISSING (or alloced)!\n",
+		topidx, mididx);
+
+	/*
+	 * Could be done by xen_build_dynamic_phys_to_machine..
+	 */
+	if (p2m_top[topidx][mididx] != p2m_missing)
+		return false;
+
+	/* Boundary cross-over for the edges: */
+	if (idx) {
+		unsigned long *p2m = extend_brk(PAGE_SIZE, PAGE_SIZE);
+
+		p2m_init(p2m);
+
+		p2m_top[topidx][mididx] = p2m;
+
+	}
+	return idx != 0;
+}
+unsigned long __init set_phys_range_identity(unsigned long pfn_s,
+				      unsigned long pfn_e)
+{
+	unsigned long pfn;
+
+	if (unlikely(pfn_s >= MAX_P2M_PFN || pfn_e >= MAX_P2M_PFN))
+		return 0;
+
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap)))
+		return pfn_e - pfn_s;
+
+	if (pfn_s > pfn_e)
+		return 0;
+
+	for (pfn = (pfn_s & ~(P2M_MID_PER_PAGE * P2M_PER_PAGE - 1));
+		pfn < ALIGN(pfn_e, (P2M_MID_PER_PAGE * P2M_PER_PAGE));
+		pfn += P2M_MID_PER_PAGE * P2M_PER_PAGE)
+	{
+		unsigned topidx = p2m_top_index(pfn);
+		if (p2m_top[topidx] == p2m_mid_missing) {
+			unsigned long **mid = extend_brk(PAGE_SIZE, PAGE_SIZE);
+
+			p2m_mid_init(mid);
+
+			p2m_top[topidx] = mid;
+		}
+	}
+
+	__early_alloc_p2m(pfn_s);
+	__early_alloc_p2m(pfn_e);
+
+	for (pfn = pfn_s; pfn < pfn_e; pfn++)
+		if (!__set_phys_to_machine(pfn, IDENTITY_FRAME(pfn)))
+			break;
+
+	if (!WARN((pfn - pfn_s) != (pfn_e - pfn_s),
+		"Identity mapping failed. We are %ld short of 1-1 mappings!\n",
+		(pfn_e - pfn_s) - (pfn - pfn_s)))
+		printk(KERN_DEBUG "1-1 mapping on %lx->%lx\n", pfn_s, pfn);
+
+	return pfn - pfn_s;
+}
+
 /* Try to install p2m mapping; fail if intermediate bits missing */
 bool __set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
 	unsigned topidx, mididx, idx;
 
+	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
+		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
+		return true;
+	}
 	if (unlikely(pfn >= MAX_P2M_PFN)) {
 		BUG_ON(mfn != INVALID_P2M_ENTRY);
 		return true;
@@ -368,6 +591,21 @@
 	mididx = p2m_mid_index(pfn);
 	idx = p2m_index(pfn);
 
+	/* For sparse holes were the p2m leaf has real PFN along with
+	 * PCI holes, stick in the PFN as the MFN value.
+	 */
+	if (mfn != INVALID_P2M_ENTRY && (mfn & IDENTITY_FRAME_BIT)) {
+		if (p2m_top[topidx][mididx] == p2m_identity)
+			return true;
+
+		/* Swap over from MISSING to IDENTITY if needed. */
+		if (p2m_top[topidx][mididx] == p2m_missing) {
+			WARN_ON(cmpxchg(&p2m_top[topidx][mididx], p2m_missing,
+				p2m_identity) != p2m_missing);
+			return true;
+		}
+	}
+
 	if (p2m_top[topidx][mididx] == p2m_missing)
 		return mfn == INVALID_P2M_ENTRY;
 
@@ -378,11 +616,6 @@
 
 bool set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
-	if (unlikely(xen_feature(XENFEAT_auto_translated_physmap))) {
-		BUG_ON(pfn != mfn && mfn != INVALID_P2M_ENTRY);
-		return true;
-	}
-
 	if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
 		if (!alloc_p2m(pfn))
 			return false;
@@ -421,7 +654,7 @@
 {
 	unsigned long flags;
 	unsigned long pfn;
-	unsigned long address;
+	unsigned long uninitialized_var(address);
 	unsigned level;
 	pte_t *ptep = NULL;
 
@@ -438,7 +671,9 @@
 	page->private = mfn;
 	page->index = pfn_to_mfn(pfn);
 
-	__set_phys_to_machine(pfn, FOREIGN_FRAME(mfn));
+	if (unlikely(!set_phys_to_machine(pfn, FOREIGN_FRAME(mfn))))
+		return -ENOMEM;
+
 	if (!PageHighMem(page))
 		/* Just zap old mapping for now */
 		pte_clear(&init_mm, address, ptep);
@@ -455,7 +690,7 @@
 	unsigned long flags;
 	unsigned long mfn;
 	unsigned long pfn;
-	unsigned long address;
+	unsigned long uninitialized_var(address);
 	unsigned level;
 	pte_t *ptep = NULL;
 
@@ -476,7 +711,7 @@
 	spin_lock_irqsave(&m2p_override_lock, flags);
 	list_del(&page->lru);
 	spin_unlock_irqrestore(&m2p_override_lock, flags);
-	__set_phys_to_machine(pfn, page->index);
+	set_phys_to_machine(pfn, page->index);
 
 	if (!PageHighMem(page))
 		set_pte_at(&init_mm, address, ptep,
@@ -520,3 +755,80 @@
 	return ret;
 }
 EXPORT_SYMBOL_GPL(m2p_find_override_pfn);
+
+#ifdef CONFIG_XEN_DEBUG_FS
+
+int p2m_dump_show(struct seq_file *m, void *v)
+{
+	static const char * const level_name[] = { "top", "middle",
+						"entry", "abnormal" };
+	static const char * const type_name[] = { "identity", "missing",
+						"pfn", "abnormal"};
+#define TYPE_IDENTITY 0
+#define TYPE_MISSING 1
+#define TYPE_PFN 2
+#define TYPE_UNKNOWN 3
+	unsigned long pfn, prev_pfn_type = 0, prev_pfn_level = 0;
+	unsigned int uninitialized_var(prev_level);
+	unsigned int uninitialized_var(prev_type);
+
+	if (!p2m_top)
+		return 0;
+
+	for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn++) {
+		unsigned topidx = p2m_top_index(pfn);
+		unsigned mididx = p2m_mid_index(pfn);
+		unsigned idx = p2m_index(pfn);
+		unsigned lvl, type;
+
+		lvl = 4;
+		type = TYPE_UNKNOWN;
+		if (p2m_top[topidx] == p2m_mid_missing) {
+			lvl = 0; type = TYPE_MISSING;
+		} else if (p2m_top[topidx] == NULL) {
+			lvl = 0; type = TYPE_UNKNOWN;
+		} else if (p2m_top[topidx][mididx] == NULL) {
+			lvl = 1; type = TYPE_UNKNOWN;
+		} else if (p2m_top[topidx][mididx] == p2m_identity) {
+			lvl = 1; type = TYPE_IDENTITY;
+		} else if (p2m_top[topidx][mididx] == p2m_missing) {
+			lvl = 1; type = TYPE_MISSING;
+		} else if (p2m_top[topidx][mididx][idx] == 0) {
+			lvl = 2; type = TYPE_UNKNOWN;
+		} else if (p2m_top[topidx][mididx][idx] == IDENTITY_FRAME(pfn)) {
+			lvl = 2; type = TYPE_IDENTITY;
+		} else if (p2m_top[topidx][mididx][idx] == INVALID_P2M_ENTRY) {
+			lvl = 2; type = TYPE_MISSING;
+		} else if (p2m_top[topidx][mididx][idx] == pfn) {
+			lvl = 2; type = TYPE_PFN;
+		} else if (p2m_top[topidx][mididx][idx] != pfn) {
+			lvl = 2; type = TYPE_PFN;
+		}
+		if (pfn == 0) {
+			prev_level = lvl;
+			prev_type = type;
+		}
+		if (pfn == MAX_DOMAIN_PAGES-1) {
+			lvl = 3;
+			type = TYPE_UNKNOWN;
+		}
+		if (prev_type != type) {
+			seq_printf(m, " [0x%lx->0x%lx] %s\n",
+				prev_pfn_type, pfn, type_name[prev_type]);
+			prev_pfn_type = pfn;
+			prev_type = type;
+		}
+		if (prev_level != lvl) {
+			seq_printf(m, " [0x%lx->0x%lx] level %s\n",
+				prev_pfn_level, pfn, level_name[prev_level]);
+			prev_pfn_level = pfn;
+			prev_level = lvl;
+		}
+	}
+	return 0;
+#undef TYPE_IDENTITY
+#undef TYPE_MISSING
+#undef TYPE_PFN
+#undef TYPE_UNKNOWN
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/setup.c linux-libre-2.6.39-gnu/arch/x86/xen/setup.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/setup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/setup.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,6 +52,8 @@
 
 static __init void xen_add_extra_mem(unsigned long pages)
 {
+	unsigned long pfn;
+
 	u64 size = (u64)pages * PAGE_SIZE;
 	u64 extra_start = xen_extra_mem_start + xen_extra_mem_size;
 
@@ -66,6 +68,9 @@
 	xen_extra_mem_size += size;
 
 	xen_max_p2m_pfn = PFN_DOWN(extra_start + size);
+
+	for (pfn = PFN_DOWN(extra_start); pfn <= xen_max_p2m_pfn; pfn++)
+		__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 }
 
 static unsigned long __init xen_release_chunk(phys_addr_t start_addr,
@@ -104,7 +109,7 @@
 		WARN(ret != 1, "Failed to release memory %lx-%lx err=%d\n",
 		     start, end, ret);
 		if (ret == 1) {
-			set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+			__set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
 			len++;
 		}
 	}
@@ -138,12 +143,55 @@
 	return released;
 }
 
+static unsigned long __init xen_set_identity(const struct e820entry *list,
+					     ssize_t map_size)
+{
+	phys_addr_t last = xen_initial_domain() ? 0 : ISA_END_ADDRESS;
+	phys_addr_t start_pci = last;
+	const struct e820entry *entry;
+	unsigned long identity = 0;
+	int i;
+
+	for (i = 0, entry = list; i < map_size; i++, entry++) {
+		phys_addr_t start = entry->addr;
+		phys_addr_t end = start + entry->size;
+
+		if (start < last)
+			start = last;
+
+		if (end <= start)
+			continue;
+
+		/* Skip over the 1MB region. */
+		if (last > end)
+			continue;
+
+		if (entry->type == E820_RAM) {
+			if (start > start_pci)
+				identity += set_phys_range_identity(
+						PFN_UP(start_pci), PFN_DOWN(start));
+
+			/* Without saving 'last' we would gooble RAM too
+			 * at the end of the loop. */
+			last = end;
+			start_pci = end;
+			continue;
+		}
+		start_pci = min(start, start_pci);
+		last = end;
+	}
+	if (last > start_pci)
+		identity += set_phys_range_identity(
+					PFN_UP(start_pci), PFN_DOWN(last));
+	return identity;
+}
 /**
  * machine_specific_memory_setup - Hook for machine specific memory setup.
  **/
 char * __init xen_memory_setup(void)
 {
 	static struct e820entry map[E820MAX] __initdata;
+	static struct e820entry map_raw[E820MAX] __initdata;
 
 	unsigned long max_pfn = xen_start_info->nr_pages;
 	unsigned long long mem_end;
@@ -151,6 +199,7 @@
 	struct xen_memory_map memmap;
 	unsigned long extra_pages = 0;
 	unsigned long extra_limit;
+	unsigned long identity_pages = 0;
 	int i;
 	int op;
 
@@ -176,8 +225,9 @@
 	}
 	BUG_ON(rc);
 
+	memcpy(map_raw, map, sizeof(map));
 	e820.nr_map = 0;
-	xen_extra_mem_start = mem_end;
+	xen_extra_mem_start = max((1ULL << 32), mem_end);
 	for (i = 0; i < memmap.nr_entries; i++) {
 		unsigned long long end;
 
@@ -194,6 +244,15 @@
 			end -= delta;
 
 			extra_pages += PFN_DOWN(delta);
+			/*
+			 * Set RAM below 4GB that is not for us to be unusable.
+			 * This prevents "System RAM" address space from being
+			 * used as potential resource for I/O address (happens
+			 * when 'allocate_resource' is called).
+			 */
+			if (delta &&
+				(xen_initial_domain() && end < 0x100000000ULL))
+				e820_add_region(end, delta, E820_UNUSABLE);
 		}
 
 		if (map[i].size > 0 && end > xen_extra_mem_start)
@@ -251,6 +310,13 @@
 
 	xen_add_extra_mem(extra_pages);
 
+	/*
+	 * Set P2M for all non-RAM pages and E820 gaps to be identity
+	 * type PFNs. We supply it with the non-sanitized version
+	 * of the E820.
+	 */
+	identity_pages = xen_set_identity(map_raw, memmap.nr_entries);
+	printk(KERN_INFO "Set %ld page(s) to 1-1 mapping.\n", identity_pages);
 	return "Xen";
 }
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/smp.c linux-libre-2.6.39-gnu/arch/x86/xen/smp.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/smp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/smp.c	2011-05-19 00:06:34.000000000 -0400
@@ -509,3 +509,41 @@
 	xen_fill_possible_map();
 	xen_init_spinlocks();
 }
+
+static void __init xen_hvm_smp_prepare_cpus(unsigned int max_cpus)
+{
+	native_smp_prepare_cpus(max_cpus);
+	WARN_ON(xen_smp_intr_init(0));
+
+	if (!xen_have_vector_callback)
+		return;
+	xen_init_lock_cpu(0);
+	xen_init_spinlocks();
+}
+
+static int __cpuinit xen_hvm_cpu_up(unsigned int cpu)
+{
+	int rc;
+	rc = native_cpu_up(cpu);
+	WARN_ON (xen_smp_intr_init(cpu));
+	return rc;
+}
+
+static void xen_hvm_cpu_die(unsigned int cpu)
+{
+	unbind_from_irqhandler(per_cpu(xen_resched_irq, cpu), NULL);
+	unbind_from_irqhandler(per_cpu(xen_callfunc_irq, cpu), NULL);
+	unbind_from_irqhandler(per_cpu(xen_debug_irq, cpu), NULL);
+	unbind_from_irqhandler(per_cpu(xen_callfuncsingle_irq, cpu), NULL);
+	native_cpu_die(cpu);
+}
+
+void __init xen_hvm_smp_init(void)
+{
+	smp_ops.smp_prepare_cpus = xen_hvm_smp_prepare_cpus;
+	smp_ops.smp_send_reschedule = xen_smp_send_reschedule;
+	smp_ops.cpu_up = xen_hvm_cpu_up;
+	smp_ops.cpu_die = xen_hvm_cpu_die;
+	smp_ops.send_call_func_ipi = xen_smp_send_call_function_ipi;
+	smp_ops.send_call_func_single_ipi = xen_smp_send_call_function_single_ipi;
+}
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/suspend.c linux-libre-2.6.39-gnu/arch/x86/xen/suspend.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/suspend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/suspend.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
 #include "xen-ops.h"
 #include "mmu.h"
 
-void xen_pre_suspend(void)
+void xen_arch_pre_suspend(void)
 {
 	xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
 	xen_start_info->console.domU.mfn =
@@ -26,8 +26,9 @@
 		BUG();
 }
 
-void xen_hvm_post_suspend(int suspend_cancelled)
+void xen_arch_hvm_post_suspend(int suspend_cancelled)
 {
+#ifdef CONFIG_XEN_PVHVM
 	int cpu;
 	xen_hvm_init_shared_info();
 	xen_callback_vector();
@@ -37,9 +38,10 @@
 			xen_setup_runstate_info(cpu);
 		}
 	}
+#endif
 }
 
-void xen_post_suspend(int suspend_cancelled)
+void xen_arch_post_suspend(int suspend_cancelled)
 {
 	xen_build_mfn_list_list();
 
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/time.c linux-libre-2.6.39-gnu/arch/x86/xen/time.c
--- linux-libre-2.6.38-gnu/arch/x86/xen/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -397,7 +397,9 @@
 		name = "<timer kasprintf failed>";
 
 	irq = bind_virq_to_irqhandler(VIRQ_TIMER, cpu, xen_timer_interrupt,
-				      IRQF_DISABLED|IRQF_PERCPU|IRQF_NOBALANCING|IRQF_TIMER,
+				      IRQF_DISABLED|IRQF_PERCPU|
+				      IRQF_NOBALANCING|IRQF_TIMER|
+				      IRQF_FORCE_RESUME,
 				      name, NULL);
 
 	evt = &per_cpu(xen_clock_events, cpu);
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/xen-head.S linux-libre-2.6.39-gnu/arch/x86/xen/xen-head.S
--- linux-libre-2.6.38-gnu/arch/x86/xen/xen-head.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/xen-head.S	2011-05-19 00:06:34.000000000 -0400
@@ -28,9 +28,9 @@
 	__FINIT
 
 .pushsection .text
-	.align PAGE_SIZE_asm
+	.align PAGE_SIZE
 ENTRY(hypercall_page)
-	.skip PAGE_SIZE_asm
+	.skip PAGE_SIZE
 .popsection
 
 	ELFNOTE(Xen, XEN_ELFNOTE_GUEST_OS,       .asciz "linux")
diff -druN linux-libre-2.6.38-gnu/arch/x86/xen/xen-ops.h linux-libre-2.6.39-gnu/arch/x86/xen/xen-ops.h
--- linux-libre-2.6.38-gnu/arch/x86/xen/xen-ops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/x86/xen/xen-ops.h	2011-05-19 00:06:34.000000000 -0400
@@ -64,10 +64,12 @@
 
 #ifdef CONFIG_SMP
 void xen_smp_init(void);
+void __init xen_hvm_smp_init(void);
 
 extern cpumask_var_t xen_cpu_initialized_map;
 #else
 static inline void xen_smp_init(void) {}
+static inline void xen_hvm_smp_init(void) {}
 #endif
 
 #ifdef CONFIG_PARAVIRT_SPINLOCKS
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/boot/lib/Makefile linux-libre-2.6.39-gnu/arch/xtensa/boot/lib/Makefile
--- linux-libre-2.6.38-gnu/arch/xtensa/boot/lib/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/boot/lib/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 
 lib-y	+= $(zlib:.c=.o) zmem.o
 
-EXTRA_CFLAGS	+= -Ilib/zlib_inflate
+ccflags-y	:= -Ilib/zlib_inflate
 
 quiet_cmd_copy_zlib = COPY    $@
       cmd_copy_zlib = cat $< > $@
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/boot/Makefile linux-libre-2.6.39-gnu/arch/xtensa/boot/Makefile
--- linux-libre-2.6.38-gnu/arch/xtensa/boot/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/boot/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 
 BIG_ENDIAN	:= $(shell echo -e __XTENSA_EB__ | $(CC) -E - | grep -v "\#")
 
-export EXTRA_CFLAGS
+export ccflags-y
 export BIG_ENDIAN
 
 subdir-y	:= lib
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/configs/s6105_defconfig linux-libre-2.6.39-gnu/arch/xtensa/configs/s6105_defconfig
--- linux-libre-2.6.38-gnu/arch/xtensa/configs/s6105_defconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/configs/s6105_defconfig	2011-05-19 00:06:34.000000000 -0400
@@ -598,7 +598,7 @@
 # CONFIG_CONTEXT_SWITCH_TRACER is not set
 # CONFIG_BOOT_TRACER is not set
 # CONFIG_TRACE_BRANCH_PROFILING is not set
-# CONFIG_DYNAMIC_PRINTK_DEBUG is not set
+# CONFIG_DYNAMIC_DEBUG is not set
 # CONFIG_SAMPLES is not set
 
 #
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/include/asm/bitops.h linux-libre-2.6.39-gnu/arch/xtensa/include/asm/bitops.h
--- linux-libre-2.6.38-gnu/arch/xtensa/include/asm/bitops.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/include/asm/bitops.h	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 
 #include <asm-generic/bitops/fls64.h>
 #include <asm-generic/bitops/find.h>
-#include <asm-generic/bitops/ext2-non-atomic.h>
+#include <asm-generic/bitops/le.h>
 
 #ifdef __XTENSA_EL__
 # define ext2_set_bit_atomic(lock,nr,addr)				\
@@ -125,7 +125,6 @@
 #include <asm-generic/bitops/hweight.h>
 #include <asm-generic/bitops/lock.h>
 #include <asm-generic/bitops/sched.h>
-#include <asm-generic/bitops/minix.h>
 
 #endif	/* __KERNEL__ */
 
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/include/asm/dma.h linux-libre-2.6.39-gnu/arch/xtensa/include/asm/dma.h
--- linux-libre-2.6.38-gnu/arch/xtensa/include/asm/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/include/asm/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
  *	the size of the statically mapped kernel segment
  *	(XCHAL_KSEG_{CACHED,BYPASS}_SIZE), ie. 128 MB.
  *
- * NOTE: When the entire KSEG area is DMA capable, we substract
+ * NOTE: When the entire KSEG area is DMA capable, we subtract
  *	one from the max address so that the virt_to_phys() macro
  *	works correctly on the address (otherwise the address
  *	enters another area, and virt_to_phys() may not return
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/include/asm/ioctls.h linux-libre-2.6.39-gnu/arch/xtensa/include/asm/ioctls.h
--- linux-libre-2.6.38-gnu/arch/xtensa/include/asm/ioctls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/include/asm/ioctls.h	2011-05-19 00:06:34.000000000 -0400
@@ -100,6 +100,7 @@
 #define TIOCSPTLCK	_IOW('T',0x31, int)  /* Lock/unlock Pty */
 #define TIOCGDEV	_IOR('T',0x32, unsigned int) /* Get primary device node of /dev/console */
 #define TIOCSIG		_IOW('T',0x36, int)  /* Generate signal on Pty slave */
+#define TIOCVHANGUP	_IO('T', 0x37)
 
 #define TIOCSERCONFIG	_IO('T', 83)
 #define TIOCSERGWILD	_IOR('T', 84,  int)
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/include/asm/rwsem.h linux-libre-2.6.39-gnu/arch/xtensa/include/asm/rwsem.h
--- linux-libre-2.6.38-gnu/arch/xtensa/include/asm/rwsem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/include/asm/rwsem.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,44 +17,12 @@
 #error "Please don't include <asm/rwsem.h> directly, use <linux/rwsem.h> instead."
 #endif
 
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <asm/atomic.h>
-#include <asm/system.h>
-
-/*
- * the semaphore definition
- */
-struct rw_semaphore {
-	signed long		count;
 #define RWSEM_UNLOCKED_VALUE		0x00000000
 #define RWSEM_ACTIVE_BIAS		0x00000001
 #define RWSEM_ACTIVE_MASK		0x0000ffff
 #define RWSEM_WAITING_BIAS		(-0x00010000)
 #define RWSEM_ACTIVE_READ_BIAS		RWSEM_ACTIVE_BIAS
 #define RWSEM_ACTIVE_WRITE_BIAS		(RWSEM_WAITING_BIAS + RWSEM_ACTIVE_BIAS)
-	spinlock_t		wait_lock;
-	struct list_head	wait_list;
-};
-
-#define __RWSEM_INITIALIZER(name) \
-	{ RWSEM_UNLOCKED_VALUE, SPIN_LOCK_UNLOCKED, \
-	  LIST_HEAD_INIT((name).wait_list) }
-
-#define DECLARE_RWSEM(name)		\
-	struct rw_semaphore name = __RWSEM_INITIALIZER(name)
-
-extern struct rw_semaphore *rwsem_down_read_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_down_write_failed(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_wake(struct rw_semaphore *sem);
-extern struct rw_semaphore *rwsem_downgrade_wake(struct rw_semaphore *sem);
-
-static inline void init_rwsem(struct rw_semaphore *sem)
-{
-	sem->count = RWSEM_UNLOCKED_VALUE;
-	spin_lock_init(&sem->wait_lock);
-	INIT_LIST_HEAD(&sem->wait_list);
-}
 
 /*
  * lock for reading
@@ -160,9 +128,4 @@
 	return atomic_add_return(delta, (atomic_t *)(&sem->count));
 }
 
-static inline int rwsem_is_locked(struct rw_semaphore *sem)
-{
-	return (sem->count != 0);
-}
-
 #endif	/* _XTENSA_RWSEM_H */
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/include/asm/types.h linux-libre-2.6.39-gnu/arch/xtensa/include/asm/types.h
--- linux-libre-2.6.38-gnu/arch/xtensa/include/asm/types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/include/asm/types.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,10 +32,6 @@
 
 #define BITS_PER_LONG 32
 
-/* Dma addresses are 32-bits wide.  */
-
-typedef u32 dma_addr_t;
-
 #endif	/* __KERNEL__ */
 #endif
 
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/Kconfig linux-libre-2.6.39-gnu/arch/xtensa/Kconfig
--- linux-libre-2.6.38-gnu/arch/xtensa/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,8 @@
 config XTENSA
 	def_bool y
 	select HAVE_IDE
+	select HAVE_GENERIC_HARDIRQS
+	select GENERIC_IRQ_SHOW
 	help
 	  Xtensa processors are 32-bit RISC machines designed by Tensilica
 	  primarily for embedded systems.  These processors are both
@@ -21,10 +23,10 @@
 config GENERIC_FIND_NEXT_BIT
 	def_bool y
 
-config GENERIC_HWEIGHT
+config GENERIC_FIND_BIT_LE
 	def_bool y
 
-config GENERIC_HARDIRQS
+config GENERIC_HWEIGHT
 	def_bool y
 
 config GENERIC_GPIO
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/kernel/entry.S linux-libre-2.6.39-gnu/arch/xtensa/kernel/entry.S
--- linux-libre-2.6.38-gnu/arch/xtensa/kernel/entry.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/kernel/entry.S	2011-05-19 00:06:34.000000000 -0400
@@ -1026,7 +1026,7 @@
  * TRY	 adds an entry to the __ex_table fixup table for the immediately
  *	 following instruction.
  *
- * CATCH catches any exception that occurred at one of the preceeding TRY
+ * CATCH catches any exception that occurred at one of the preceding TRY
  *       statements and continues from there
  *
  * Usage TRY	l32i	a0, a1, 0
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/kernel/irq.c linux-libre-2.6.39-gnu/arch/xtensa/kernel/irq.c
--- linux-libre-2.6.38-gnu/arch/xtensa/kernel/irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/kernel/irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,6 @@
 asmlinkage void do_IRQ(int irq, struct pt_regs *regs)
 {
 	struct pt_regs *old_regs = set_irq_regs(regs);
-	struct irq_desc *desc = irq_desc + irq;
 
 	if (irq >= NR_IRQS) {
 		printk(KERN_EMERG "%s: cannot handle IRQ %d\n",
@@ -57,104 +56,63 @@
 			       sp - sizeof(struct thread_info));
 	}
 #endif
-	desc->handle_irq(irq, desc);
+	generic_handle_irq(irq);
 
 	irq_exit();
 	set_irq_regs(old_regs);
 }
 
-/*
- * Generic, controller-independent functions:
- */
-
-int show_interrupts(struct seq_file *p, void *v)
+int arch_show_interrupts(struct seq_file *p, int prec)
 {
-	int i = *(loff_t *) v, j;
-	struct irqaction * action;
-	unsigned long flags;
-
-	if (i == 0) {
-		seq_printf(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
-		seq_putc(p, '\n');
-	}
-
-	if (i < NR_IRQS) {
-		raw_spin_lock_irqsave(&irq_desc[i].lock, flags);
-		action = irq_desc[i].action;
-		if (!action)
-			goto skip;
-		seq_printf(p, "%3d: ",i);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_irqs_cpu(i, j));
-#endif
-		seq_printf(p, " %14s", irq_desc[i].chip->name);
-		seq_printf(p, "  %s", action->name);
-
-		for (action=action->next; action; action = action->next)
-			seq_printf(p, ", %s", action->name);
-
-		seq_putc(p, '\n');
-skip:
-		raw_spin_unlock_irqrestore(&irq_desc[i].lock, flags);
-	} else if (i == NR_IRQS) {
-		seq_printf(p, "NMI: ");
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", nmi_count(j));
-		seq_putc(p, '\n');
-		seq_printf(p, "ERR: %10u\n", atomic_read(&irq_err_count));
-	}
+	seq_printf(p, "%*s: ", prec, "ERR");
+	seq_printf(p, "%10u\n", atomic_read(&irq_err_count));
 	return 0;
 }
 
-static void xtensa_irq_mask(unsigned int irq)
+static void xtensa_irq_mask(struct irq_data *d)
 {
-	cached_irq_mask &= ~(1 << irq);
+	cached_irq_mask &= ~(1 << d->irq);
 	set_sr (cached_irq_mask, INTENABLE);
 }
 
-static void xtensa_irq_unmask(unsigned int irq)
+static void xtensa_irq_unmask(struct irq_data *d)
 {
-	cached_irq_mask |= 1 << irq;
+	cached_irq_mask |= 1 << d->irq;
 	set_sr (cached_irq_mask, INTENABLE);
 }
 
-static void xtensa_irq_enable(unsigned int irq)
+static void xtensa_irq_enable(struct irq_data *d)
 {
-	variant_irq_enable(irq);
-	xtensa_irq_unmask(irq);
+	variant_irq_enable(d->irq);
+	xtensa_irq_unmask(d->irq);
 }
 
-static void xtensa_irq_disable(unsigned int irq)
+static void xtensa_irq_disable(struct irq_data *d)
 {
-	xtensa_irq_mask(irq);
-	variant_irq_disable(irq);
+	xtensa_irq_mask(d->irq);
+	variant_irq_disable(d->irq);
 }
 
-static void xtensa_irq_ack(unsigned int irq)
+static void xtensa_irq_ack(struct irq_data *d)
 {
-	set_sr(1 << irq, INTCLEAR);
+	set_sr(1 << d->irq, INTCLEAR);
 }
 
-static int xtensa_irq_retrigger(unsigned int irq)
+static int xtensa_irq_retrigger(struct irq_data *d)
 {
-	set_sr (1 << irq, INTSET);
+	set_sr (1 << d->irq, INTSET);
 	return 1;
 }
 
 
 static struct irq_chip xtensa_irq_chip = {
 	.name		= "xtensa",
-	.enable		= xtensa_irq_enable,
-	.disable	= xtensa_irq_disable,
-	.mask		= xtensa_irq_mask,
-	.unmask		= xtensa_irq_unmask,
-	.ack		= xtensa_irq_ack,
-	.retrigger	= xtensa_irq_retrigger,
+	.irq_enable	= xtensa_irq_enable,
+	.irq_disable	= xtensa_irq_disable,
+	.irq_mask	= xtensa_irq_mask,
+	.irq_unmask	= xtensa_irq_unmask,
+	.irq_ack	= xtensa_irq_ack,
+	.irq_retrigger	= xtensa_irq_retrigger,
 };
 
 void __init init_IRQ(void)
@@ -165,25 +123,25 @@
 		int mask = 1 << index;
 
 		if (mask & XCHAL_INTTYPE_MASK_SOFTWARE)
-			set_irq_chip_and_handler(index, &xtensa_irq_chip,
+			irq_set_chip_and_handler(index, &xtensa_irq_chip,
 						 handle_simple_irq);
 
 		else if (mask & XCHAL_INTTYPE_MASK_EXTERN_EDGE)
-			set_irq_chip_and_handler(index, &xtensa_irq_chip,
+			irq_set_chip_and_handler(index, &xtensa_irq_chip,
 						 handle_edge_irq);
 
 		else if (mask & XCHAL_INTTYPE_MASK_EXTERN_LEVEL)
-			set_irq_chip_and_handler(index, &xtensa_irq_chip,
+			irq_set_chip_and_handler(index, &xtensa_irq_chip,
 						 handle_level_irq);
 
 		else if (mask & XCHAL_INTTYPE_MASK_TIMER)
-			set_irq_chip_and_handler(index, &xtensa_irq_chip,
+			irq_set_chip_and_handler(index, &xtensa_irq_chip,
 						 handle_edge_irq);
 
 		else	/* XCHAL_INTTYPE_MASK_WRITE_ERROR */
 			/* XCHAL_INTTYPE_MASK_NMI */
 
-			set_irq_chip_and_handler(index, &xtensa_irq_chip,
+			irq_set_chip_and_handler(index, &xtensa_irq_chip,
 						 handle_level_irq);
 	}
 
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/kernel/time.c linux-libre-2.6.39-gnu/arch/xtensa/kernel/time.c
--- linux-libre-2.6.38-gnu/arch/xtensa/kernel/time.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/kernel/time.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,16 +96,12 @@
 		update_process_times(user_mode(get_irq_regs()));
 #endif
 
-		write_seqlock(&xtime_lock);
-
-		do_timer(1); /* Linux handler in kernel/timer.c */
+		xtime_update(1); /* Linux handler in kernel/time/timekeeping */
 
 		/* Note that writing CCOMPARE clears the interrupt. */
 
 		next += CCOUNT_PER_JIFFY;
 		set_linux_timer(next);
-
-		write_sequnlock(&xtime_lock);
 	}
 
 	/* Allow platform to do something useful (Wdog). */
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/kernel/vmlinux.lds.S linux-libre-2.6.39-gnu/arch/xtensa/kernel/vmlinux.lds.S
--- linux-libre-2.6.38-gnu/arch/xtensa/kernel/vmlinux.lds.S	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/kernel/vmlinux.lds.S	2011-05-19 00:06:34.000000000 -0400
@@ -155,7 +155,7 @@
     INIT_RAM_FS
   }
 
-  PERCPU(PAGE_SIZE)
+  PERCPU(XCHAL_ICACHE_LINESIZE, PAGE_SIZE)
 
   /* We need this dummy segment here */
 
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/platforms/s6105/device.c linux-libre-2.6.39-gnu/arch/xtensa/platforms/s6105/device.c
--- linux-libre-2.6.38-gnu/arch/xtensa/platforms/s6105/device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/platforms/s6105/device.c	2011-05-19 00:06:34.000000000 -0400
@@ -120,7 +120,7 @@
 	irq = gpio_to_irq(pin);
 	if (irq < 0)
 		goto free;
-	if (set_irq_type(irq, IRQ_TYPE_LEVEL_LOW) < 0)
+	if (irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW) < 0)
 		goto free;
 	return irq;
 free:
diff -druN linux-libre-2.6.38-gnu/arch/xtensa/variants/s6000/gpio.c linux-libre-2.6.39-gnu/arch/xtensa/variants/s6000/gpio.c
--- linux-libre-2.6.38-gnu/arch/xtensa/variants/s6000/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/arch/xtensa/variants/s6000/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,30 +85,29 @@
 	return gpiochip_add(&gpiochip);
 }
 
-static void ack(unsigned int irq)
+static void ack(struct irq_data *d)
 {
-	writeb(1 << (irq - IRQ_BASE), S6_REG_GPIO + S6_GPIO_IC);
+	writeb(1 << (d->irq - IRQ_BASE), S6_REG_GPIO + S6_GPIO_IC);
 }
 
-static void mask(unsigned int irq)
+static void mask(struct irq_data *d)
 {
 	u8 r = readb(S6_REG_GPIO + S6_GPIO_IE);
-	r &= ~(1 << (irq - IRQ_BASE));
+	r &= ~(1 << (d->irq - IRQ_BASE));
 	writeb(r, S6_REG_GPIO + S6_GPIO_IE);
 }
 
-static void unmask(unsigned int irq)
+static void unmask(struct irq_data *d)
 {
 	u8 m = readb(S6_REG_GPIO + S6_GPIO_IE);
-	m |= 1 << (irq - IRQ_BASE);
+	m |= 1 << (d->irq - IRQ_BASE);
 	writeb(m, S6_REG_GPIO + S6_GPIO_IE);
 }
 
-static int set_type(unsigned int irq, unsigned int type)
+static int set_type(struct irq_data *d, unsigned int type)
 {
-	const u8 m = 1 << (irq - IRQ_BASE);
+	const u8 m = 1 << (d->irq - IRQ_BASE);
 	irq_flow_handler_t handler;
-	struct irq_desc *desc;
 	u8 reg;
 
 	if (type == IRQ_TYPE_PROBE) {
@@ -129,8 +128,7 @@
 		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;
+	__irq_set_handler_locked(irq, handler);
 
 	reg = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_IEV);
 	if (type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_EDGE_RISING))
@@ -150,22 +148,23 @@
 
 static struct irq_chip gpioirqs = {
 	.name = "GPIO",
-	.ack = ack,
-	.mask = mask,
-	.unmask = unmask,
-	.set_type = set_type,
+	.irq_ack = ack,
+	.irq_mask = mask,
+	.irq_unmask = unmask,
+	.irq_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);
+	struct irq_chip *chip = irq_desc_get_chip(desc);
+	u8 *mask = irq_desc_get_handler_data(desc);
 	u8 pending;
 	int cirq;
 
-	desc->chip->mask(irq);
-	desc->chip->ack(irq);
+	chip->irq_mask(&desc->irq_data);
+	chip->irq_ack(&desc->irq_data));
 	pending = readb(S6_REG_GPIO + S6_GPIO_BANK(0) + S6_GPIO_MIS) & *mask;
 	cirq = IRQ_BASE - 1;
 	while (pending) {
@@ -174,7 +173,7 @@
 		pending >>= n;
 		generic_handle_irq(cirq);
 	}
-	desc->chip->unmask(irq);
+	chip->irq_unmask(&desc->irq_data));
 }
 
 extern const signed char *platform_irq_mappings[XTENSA_NR_IRQS];
@@ -219,11 +218,11 @@
 				i = ffs(mask);
 				cirq += i;
 				mask >>= i;
-				set_irq_chip(cirq, &gpioirqs);
-				set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
+				irq_set_chip(cirq, &gpioirqs);
+				irq_set_irq_type(irq, IRQ_TYPE_LEVEL_LOW);
 			} while (mask);
-			set_irq_data(irq, demux_masks + n);
-			set_irq_chained_handler(irq, demux_irqs);
+			irq_set_handler_data(irq, demux_masks + n);
+			irq_set_chained_handler(irq, demux_irqs);
 			if (++n == ARRAY_SIZE(demux_masks))
 				break;
 		}
diff -druN linux-libre-2.6.38-gnu/block/blk-cgroup.c linux-libre-2.6.39-gnu/block/blk-cgroup.c
--- linux-libre-2.6.38-gnu/block/blk-cgroup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-cgroup.c	2011-05-19 00:06:34.000000000 -0400
@@ -114,6 +114,13 @@
 }
 EXPORT_SYMBOL_GPL(cgroup_to_blkio_cgroup);
 
+struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk)
+{
+	return container_of(task_subsys_state(tsk, blkio_subsys_id),
+			    struct blkio_cgroup, css);
+}
+EXPORT_SYMBOL_GPL(task_blkio_cgroup);
+
 static inline void
 blkio_update_group_weight(struct blkio_group *blkg, unsigned int weight)
 {
@@ -371,12 +378,14 @@
 }
 EXPORT_SYMBOL_GPL(blkiocg_update_io_remove_stats);
 
-void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time)
+void blkiocg_update_timeslice_used(struct blkio_group *blkg, unsigned long time,
+				unsigned long unaccounted_time)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&blkg->stats_lock, flags);
 	blkg->stats.time += time;
+	blkg->stats.unaccounted_time += unaccounted_time;
 	spin_unlock_irqrestore(&blkg->stats_lock, flags);
 }
 EXPORT_SYMBOL_GPL(blkiocg_update_timeslice_used);
@@ -604,6 +613,9 @@
 		return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
 					blkg->stats.sectors, cb, dev);
 #ifdef CONFIG_DEBUG_BLK_CGROUP
+	if (type == BLKIO_STAT_UNACCOUNTED_TIME)
+		return blkio_fill_stat(key_str, MAX_KEY_LEN - 1,
+					blkg->stats.unaccounted_time, cb, dev);
 	if (type == BLKIO_STAT_AVG_QUEUE_SIZE) {
 		uint64_t sum = blkg->stats.avg_queue_size_sum;
 		uint64_t samples = blkg->stats.avg_queue_size_samples;
@@ -863,7 +875,7 @@
 }
 
 /*
- * Some rules/values in blkg have changed. Propogate those to respective
+ * Some rules/values in blkg have changed. Propagate those to respective
  * policies.
  */
 static void blkio_update_blkg_policy(struct blkio_cgroup *blkcg,
@@ -898,7 +910,7 @@
 }
 
 /*
- * A policy node rule has been updated. Propogate this update to all the
+ * A policy node rule has been updated. Propagate this update to all the
  * block groups which might be affected by this update.
  */
 static void blkio_update_policy_node_blkg(struct blkio_cgroup *blkcg,
@@ -1125,6 +1137,9 @@
 			return blkio_read_blkg_stats(blkcg, cft, cb,
 						BLKIO_STAT_QUEUED, 1);
 #ifdef CONFIG_DEBUG_BLK_CGROUP
+		case BLKIO_PROP_unaccounted_time:
+			return blkio_read_blkg_stats(blkcg, cft, cb,
+						BLKIO_STAT_UNACCOUNTED_TIME, 0);
 		case BLKIO_PROP_dequeue:
 			return blkio_read_blkg_stats(blkcg, cft, cb,
 						BLKIO_STAT_DEQUEUE, 0);
@@ -1382,6 +1397,12 @@
 				BLKIO_PROP_dequeue),
 		.read_map = blkiocg_file_read_map,
 	},
+	{
+		.name = "unaccounted_time",
+		.private = BLKIOFILE_PRIVATE(BLKIO_POLICY_PROP,
+				BLKIO_PROP_unaccounted_time),
+		.read_map = blkiocg_file_read_map,
+	},
 #endif
 };
 
diff -druN linux-libre-2.6.38-gnu/block/blk-cgroup.h linux-libre-2.6.39-gnu/block/blk-cgroup.h
--- linux-libre-2.6.38-gnu/block/blk-cgroup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-cgroup.h	2011-05-19 00:06:34.000000000 -0400
@@ -49,6 +49,8 @@
 	/* All the single valued stats go below this */
 	BLKIO_STAT_TIME,
 	BLKIO_STAT_SECTORS,
+	/* Time not charged to this cgroup */
+	BLKIO_STAT_UNACCOUNTED_TIME,
 #ifdef CONFIG_DEBUG_BLK_CGROUP
 	BLKIO_STAT_AVG_QUEUE_SIZE,
 	BLKIO_STAT_IDLE_TIME,
@@ -81,6 +83,7 @@
 	BLKIO_PROP_io_serviced,
 	BLKIO_PROP_time,
 	BLKIO_PROP_sectors,
+	BLKIO_PROP_unaccounted_time,
 	BLKIO_PROP_io_service_time,
 	BLKIO_PROP_io_wait_time,
 	BLKIO_PROP_io_merged,
@@ -114,6 +117,8 @@
 	/* total disk time and nr sectors dispatched by this group */
 	uint64_t time;
 	uint64_t sectors;
+	/* Time not charged to this cgroup */
+	uint64_t unaccounted_time;
 	uint64_t stat_arr[BLKIO_STAT_QUEUED + 1][BLKIO_STAT_TOTAL];
 #ifdef CONFIG_DEBUG_BLK_CGROUP
 	/* Sum of number of IOs queued across all samples */
@@ -240,7 +245,7 @@
 
 #endif
 
-#define BLKIO_WEIGHT_MIN	100
+#define BLKIO_WEIGHT_MIN	10
 #define BLKIO_WEIGHT_MAX	1000
 #define BLKIO_WEIGHT_DEFAULT	500
 
@@ -286,6 +291,7 @@
 #if defined(CONFIG_BLK_CGROUP) || defined(CONFIG_BLK_CGROUP_MODULE)
 extern struct blkio_cgroup blkio_root_cgroup;
 extern struct blkio_cgroup *cgroup_to_blkio_cgroup(struct cgroup *cgroup);
+extern struct blkio_cgroup *task_blkio_cgroup(struct task_struct *tsk);
 extern void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
 	struct blkio_group *blkg, void *key, dev_t dev,
 	enum blkio_policy_id plid);
@@ -293,7 +299,8 @@
 extern struct blkio_group *blkiocg_lookup_group(struct blkio_cgroup *blkcg,
 						void *key);
 void blkiocg_update_timeslice_used(struct blkio_group *blkg,
-					unsigned long time);
+					unsigned long time,
+					unsigned long unaccounted_time);
 void blkiocg_update_dispatch_stats(struct blkio_group *blkg, uint64_t bytes,
 						bool direction, bool sync);
 void blkiocg_update_completion_stats(struct blkio_group *blkg,
@@ -308,6 +315,8 @@
 struct cgroup;
 static inline struct blkio_cgroup *
 cgroup_to_blkio_cgroup(struct cgroup *cgroup) { return NULL; }
+static inline struct blkio_cgroup *
+task_blkio_cgroup(struct task_struct *tsk) { return NULL; }
 
 static inline void blkiocg_add_blkio_group(struct blkio_cgroup *blkcg,
 		struct blkio_group *blkg, void *key, dev_t dev,
@@ -319,7 +328,9 @@
 static inline struct blkio_group *
 blkiocg_lookup_group(struct blkio_cgroup *blkcg, void *key) { return NULL; }
 static inline void blkiocg_update_timeslice_used(struct blkio_group *blkg,
-						unsigned long time) {}
+						unsigned long time,
+						unsigned long unaccounted_time)
+{}
 static inline void blkiocg_update_dispatch_stats(struct blkio_group *blkg,
 				uint64_t bytes, bool direction, bool sync) {}
 static inline void blkiocg_update_completion_stats(struct blkio_group *blkg,
diff -druN linux-libre-2.6.38-gnu/block/blk-core.c linux-libre-2.6.39-gnu/block/blk-core.c
--- linux-libre-2.6.38-gnu/block/blk-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/writeback.h>
 #include <linux/task_io_accounting_ops.h>
 #include <linux/fault-inject.h>
+#include <linux/list_sort.h>
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/block.h>
@@ -149,39 +150,29 @@
 static void req_bio_endio(struct request *rq, struct bio *bio,
 			  unsigned int nbytes, int error)
 {
-	struct request_queue *q = rq->q;
-
-	if (&q->flush_rq != rq) {
-		if (error)
-			clear_bit(BIO_UPTODATE, &bio->bi_flags);
-		else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
-			error = -EIO;
+	if (error)
+		clear_bit(BIO_UPTODATE, &bio->bi_flags);
+	else if (!test_bit(BIO_UPTODATE, &bio->bi_flags))
+		error = -EIO;
 
-		if (unlikely(nbytes > bio->bi_size)) {
-			printk(KERN_ERR "%s: want %u bytes done, %u left\n",
-			       __func__, nbytes, bio->bi_size);
-			nbytes = bio->bi_size;
-		}
+	if (unlikely(nbytes > bio->bi_size)) {
+		printk(KERN_ERR "%s: want %u bytes done, %u left\n",
+		       __func__, nbytes, bio->bi_size);
+		nbytes = bio->bi_size;
+	}
 
-		if (unlikely(rq->cmd_flags & REQ_QUIET))
-			set_bit(BIO_QUIET, &bio->bi_flags);
+	if (unlikely(rq->cmd_flags & REQ_QUIET))
+		set_bit(BIO_QUIET, &bio->bi_flags);
 
-		bio->bi_size -= nbytes;
-		bio->bi_sector += (nbytes >> 9);
+	bio->bi_size -= nbytes;
+	bio->bi_sector += (nbytes >> 9);
 
-		if (bio_integrity(bio))
-			bio_integrity_advance(bio, nbytes);
+	if (bio_integrity(bio))
+		bio_integrity_advance(bio, nbytes);
 
-		if (bio->bi_size == 0)
-			bio_endio(bio, error);
-	} else {
-		/*
-		 * Okay, this is the sequenced flush request in
-		 * progress, just record the error;
-		 */
-		if (error && !q->flush_err)
-			q->flush_err = error;
-	}
+	/* don't actually finish bio if it's part of flush sequence */
+	if (bio->bi_size == 0 && !(rq->cmd_flags & REQ_FLUSH_SEQ))
+		bio_endio(bio, error);
 }
 
 void blk_dump_rq_flags(struct request *rq, char *msg)
@@ -207,136 +198,32 @@
 }
 EXPORT_SYMBOL(blk_dump_rq_flags);
 
-/*
- * "plug" the device if there are no outstanding requests: this will
- * force the transfer to start only after we have put all the requests
- * on the list.
- *
- * This is called with interrupts off and no requests on the queue and
- * with the queue lock held.
- */
-void blk_plug_device(struct request_queue *q)
+static void blk_delay_work(struct work_struct *work)
 {
-	WARN_ON(!irqs_disabled());
-
-	/*
-	 * don't plug a stopped queue, it must be paired with blk_start_queue()
-	 * which will restart the queueing
-	 */
-	if (blk_queue_stopped(q))
-		return;
+	struct request_queue *q;
 
-	if (!queue_flag_test_and_set(QUEUE_FLAG_PLUGGED, q)) {
-		mod_timer(&q->unplug_timer, jiffies + q->unplug_delay);
-		trace_block_plug(q);
-	}
+	q = container_of(work, struct request_queue, delay_work.work);
+	spin_lock_irq(q->queue_lock);
+	__blk_run_queue(q);
+	spin_unlock_irq(q->queue_lock);
 }
-EXPORT_SYMBOL(blk_plug_device);
 
 /**
- * blk_plug_device_unlocked - plug a device without queue lock held
- * @q:    The &struct request_queue to plug
+ * blk_delay_queue - restart queueing after defined interval
+ * @q:		The &struct request_queue in question
+ * @msecs:	Delay in msecs
  *
  * Description:
- *   Like @blk_plug_device(), but grabs the queue lock and disables
- *   interrupts.
- **/
-void blk_plug_device_unlocked(struct request_queue *q)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(q->queue_lock, flags);
-	blk_plug_device(q);
-	spin_unlock_irqrestore(q->queue_lock, flags);
-}
-EXPORT_SYMBOL(blk_plug_device_unlocked);
-
-/*
- * remove the queue from the plugged list, if present. called with
- * queue lock held and interrupts disabled.
- */
-int blk_remove_plug(struct request_queue *q)
-{
-	WARN_ON(!irqs_disabled());
-
-	if (!queue_flag_test_and_clear(QUEUE_FLAG_PLUGGED, q))
-		return 0;
-
-	del_timer(&q->unplug_timer);
-	return 1;
-}
-EXPORT_SYMBOL(blk_remove_plug);
-
-/*
- * remove the plug and let it rip..
+ *   Sometimes queueing needs to be postponed for a little while, to allow
+ *   resources to come back. This function will make sure that queueing is
+ *   restarted around the specified time.
  */
-void __generic_unplug_device(struct request_queue *q)
-{
-	if (unlikely(blk_queue_stopped(q)))
-		return;
-	if (!blk_remove_plug(q) && !blk_queue_nonrot(q))
-		return;
-
-	q->request_fn(q);
-}
-
-/**
- * generic_unplug_device - fire a request queue
- * @q:    The &struct request_queue in question
- *
- * Description:
- *   Linux uses plugging to build bigger requests queues before letting
- *   the device have at them. If a queue is plugged, the I/O scheduler
- *   is still adding and merging requests on the queue. Once the queue
- *   gets unplugged, the request_fn defined for the queue is invoked and
- *   transfers started.
- **/
-void generic_unplug_device(struct request_queue *q)
-{
-	if (blk_queue_plugged(q)) {
-		spin_lock_irq(q->queue_lock);
-		__generic_unplug_device(q);
-		spin_unlock_irq(q->queue_lock);
-	}
-}
-EXPORT_SYMBOL(generic_unplug_device);
-
-static void blk_backing_dev_unplug(struct backing_dev_info *bdi,
-				   struct page *page)
-{
-	struct request_queue *q = bdi->unplug_io_data;
-
-	blk_unplug(q);
-}
-
-void blk_unplug_work(struct work_struct *work)
-{
-	struct request_queue *q =
-		container_of(work, struct request_queue, unplug_work);
-
-	trace_block_unplug_io(q);
-	q->unplug_fn(q);
-}
-
-void blk_unplug_timeout(unsigned long data)
-{
-	struct request_queue *q = (struct request_queue *)data;
-
-	trace_block_unplug_timer(q);
-	kblockd_schedule_work(q, &q->unplug_work);
-}
-
-void blk_unplug(struct request_queue *q)
+void blk_delay_queue(struct request_queue *q, unsigned long msecs)
 {
-	/*
-	 * devices don't necessarily have an ->unplug_fn defined
-	 */
-	if (q->unplug_fn) {
-		trace_block_unplug_io(q);
-		q->unplug_fn(q);
-	}
+	queue_delayed_work(kblockd_workqueue, &q->delay_work,
+				msecs_to_jiffies(msecs));
 }
-EXPORT_SYMBOL(blk_unplug);
+EXPORT_SYMBOL(blk_delay_queue);
 
 /**
  * blk_start_queue - restart a previously stopped queue
@@ -352,7 +239,7 @@
 	WARN_ON(!irqs_disabled());
 
 	queue_flag_clear(QUEUE_FLAG_STOPPED, q);
-	__blk_run_queue(q, false);
+	__blk_run_queue(q);
 }
 EXPORT_SYMBOL(blk_start_queue);
 
@@ -372,7 +259,7 @@
  **/
 void blk_stop_queue(struct request_queue *q)
 {
-	blk_remove_plug(q);
+	__cancel_delayed_work(&q->delay_work);
 	queue_flag_set(QUEUE_FLAG_STOPPED, q);
 }
 EXPORT_SYMBOL(blk_stop_queue);
@@ -390,49 +277,51 @@
  *     that its ->make_request_fn will not re-add plugging prior to calling
  *     this function.
  *
+ *     This function does not cancel any asynchronous activity arising
+ *     out of elevator or throttling code. That would require elevaotor_exit()
+ *     and blk_throtl_exit() to be called with queue lock initialized.
+ *
  */
 void blk_sync_queue(struct request_queue *q)
 {
-	del_timer_sync(&q->unplug_timer);
 	del_timer_sync(&q->timeout);
-	cancel_work_sync(&q->unplug_work);
-	throtl_shutdown_timer_wq(q);
+	cancel_delayed_work_sync(&q->delay_work);
 }
 EXPORT_SYMBOL(blk_sync_queue);
 
 /**
  * __blk_run_queue - run a single device queue
  * @q:	The queue to run
- * @force_kblockd: Don't run @q->request_fn directly.  Use kblockd.
  *
  * Description:
  *    See @blk_run_queue. This variant must be called with the queue lock
  *    held and interrupts disabled.
- *
  */
-void __blk_run_queue(struct request_queue *q, bool force_kblockd)
+void __blk_run_queue(struct request_queue *q)
 {
-	blk_remove_plug(q);
-
 	if (unlikely(blk_queue_stopped(q)))
 		return;
 
-	if (elv_queue_empty(q))
-		return;
+	q->request_fn(q);
+}
+EXPORT_SYMBOL(__blk_run_queue);
 
-	/*
-	 * Only recurse once to avoid overrunning the stack, let the unplug
-	 * handling reinvoke the handler shortly if we already got there.
-	 */
-	if (!force_kblockd && !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_run_queue_async - run a single device queue in workqueue context
+ * @q:	The queue to run
+ *
+ * Description:
+ *    Tells kblockd to perform the equivalent of @blk_run_queue on behalf
+ *    of us.
+ */
+void blk_run_queue_async(struct request_queue *q)
+{
+	if (likely(!blk_queue_stopped(q))) {
+		__cancel_delayed_work(&q->delay_work);
+		queue_delayed_work(kblockd_workqueue, &q->delay_work, 0);
 	}
 }
-EXPORT_SYMBOL(__blk_run_queue);
+EXPORT_SYMBOL(blk_run_queue_async);
 
 /**
  * blk_run_queue - run a single device queue
@@ -447,7 +336,7 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	__blk_run_queue(q, false);
+	__blk_run_queue(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_run_queue);
@@ -457,6 +346,11 @@
 	kobject_put(&q->kobj);
 }
 
+/*
+ * Note: If a driver supplied the queue lock, it should not zap that lock
+ * unexpectedly as some queue cleanup components like elevator_exit() and
+ * blk_throtl_exit() need queue lock.
+ */
 void blk_cleanup_queue(struct request_queue *q)
 {
 	/*
@@ -475,6 +369,8 @@
 	if (q->elevator)
 		elevator_exit(q->elevator);
 
+	blk_throtl_exit(q);
+
 	blk_put_queue(q);
 }
 EXPORT_SYMBOL(blk_cleanup_queue);
@@ -517,8 +413,6 @@
 	if (!q)
 		return NULL;
 
-	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;
@@ -538,17 +432,24 @@
 
 	setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
 		    laptop_mode_timer_fn, (unsigned long) q);
-	init_timer(&q->unplug_timer);
 	setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
 	INIT_LIST_HEAD(&q->timeout_list);
-	INIT_LIST_HEAD(&q->pending_flushes);
-	INIT_WORK(&q->unplug_work, blk_unplug_work);
+	INIT_LIST_HEAD(&q->flush_queue[0]);
+	INIT_LIST_HEAD(&q->flush_queue[1]);
+	INIT_LIST_HEAD(&q->flush_data_in_flight);
+	INIT_DELAYED_WORK(&q->delay_work, blk_delay_work);
 
 	kobject_init(&q->kobj, &blk_queue_ktype);
 
 	mutex_init(&q->sysfs_lock);
 	spin_lock_init(&q->__queue_lock);
 
+	/*
+	 * By default initialize queue_lock to internal lock and driver can
+	 * override it later if need be.
+	 */
+	q->queue_lock = &q->__queue_lock;
+
 	return q;
 }
 EXPORT_SYMBOL(blk_alloc_queue_node);
@@ -631,9 +532,11 @@
 	q->request_fn		= rfn;
 	q->prep_rq_fn		= NULL;
 	q->unprep_rq_fn		= NULL;
-	q->unplug_fn		= generic_unplug_device;
 	q->queue_flags		= QUEUE_FLAG_DEFAULT;
-	q->queue_lock		= lock;
+
+	/* Override internal queue lock with supplied lock pointer */
+	if (lock)
+		q->queue_lock		= lock;
 
 	/*
 	 * This also sets hw/phys segments, boundary and size
@@ -666,6 +569,8 @@
 
 static inline void blk_free_request(struct request_queue *q, struct request *rq)
 {
+	BUG_ON(rq->cmd_flags & REQ_ON_PLUG);
+
 	if (rq->cmd_flags & REQ_ELVPRIV)
 		elv_put_request(q, rq);
 	mempool_free(rq, q->rq.rq_pool);
@@ -762,6 +667,25 @@
 }
 
 /*
+ * Determine if elevator data should be initialized when allocating the
+ * request associated with @bio.
+ */
+static bool blk_rq_should_init_elevator(struct bio *bio)
+{
+	if (!bio)
+		return true;
+
+	/*
+	 * Flush requests do not use the elevator so skip initialization.
+	 * This allows a request to share the flush and elevator data.
+	 */
+	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA))
+		return false;
+
+	return true;
+}
+
+/*
  * Get a free request, queue_lock must be held.
  * Returns NULL on failure, with queue_lock held.
  * Returns !NULL on success, with queue_lock *not held*.
@@ -773,7 +697,7 @@
 	struct request_list *rl = &q->rq;
 	struct io_context *ioc = NULL;
 	const bool is_sync = rw_is_sync(rw_flags) != 0;
-	int may_queue, priv;
+	int may_queue, priv = 0;
 
 	may_queue = elv_may_queue(q, rw_flags);
 	if (may_queue == ELV_MQUEUE_NO)
@@ -817,9 +741,11 @@
 	rl->count[is_sync]++;
 	rl->starved[is_sync] = 0;
 
-	priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
-	if (priv)
-		rl->elvpriv++;
+	if (blk_rq_should_init_elevator(bio)) {
+		priv = !test_bit(QUEUE_FLAG_ELVSWITCH, &q->queue_flags);
+		if (priv)
+			rl->elvpriv++;
+	}
 
 	if (blk_queue_io_stat(q))
 		rw_flags |= REQ_IO_STAT;
@@ -866,8 +792,8 @@
 }
 
 /*
- * No available requests for this queue, unplug the device and wait for some
- * requests to become available.
+ * No available requests for this queue, wait for some requests to become
+ * available.
  *
  * Called with q->queue_lock held, and returns with it unlocked.
  */
@@ -888,7 +814,6 @@
 
 		trace_block_sleeprq(q, bio, rw_flags & 1);
 
-		__generic_unplug_device(q);
 		spin_unlock_irq(q->queue_lock);
 		io_schedule();
 
@@ -1010,6 +935,13 @@
 }
 EXPORT_SYMBOL(blk_requeue_request);
 
+static void add_acct_request(struct request_queue *q, struct request *rq,
+			     int where)
+{
+	drive_stat_acct(rq, 1);
+	__elv_add_request(q, rq, where);
+}
+
 /**
  * blk_insert_request - insert a special request into a request queue
  * @q:		request queue where request should be inserted
@@ -1052,9 +984,8 @@
 	if (blk_rq_tagged(rq))
 		blk_queue_end_tag(q, rq);
 
-	drive_stat_acct(rq, 1);
-	__elv_add_request(q, rq, where, 0);
-	__blk_run_queue(q, false);
+	add_acct_request(q, rq, where);
+	__blk_run_queue(q);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(blk_insert_request);
@@ -1174,6 +1105,113 @@
 }
 EXPORT_SYMBOL_GPL(blk_add_request_payload);
 
+static bool bio_attempt_back_merge(struct request_queue *q, struct request *req,
+				   struct bio *bio)
+{
+	const int ff = bio->bi_rw & REQ_FAILFAST_MASK;
+
+	/*
+	 * Debug stuff, kill later
+	 */
+	if (!rq_mergeable(req)) {
+		blk_dump_rq_flags(req, "back");
+		return false;
+	}
+
+	if (!ll_back_merge_fn(q, req, bio))
+		return false;
+
+	trace_block_bio_backmerge(q, bio);
+
+	if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff)
+		blk_rq_set_mixed_merge(req);
+
+	req->biotail->bi_next = bio;
+	req->biotail = bio;
+	req->__data_len += bio->bi_size;
+	req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
+
+	drive_stat_acct(req, 0);
+	return true;
+}
+
+static bool bio_attempt_front_merge(struct request_queue *q,
+				    struct request *req, struct bio *bio)
+{
+	const int ff = bio->bi_rw & REQ_FAILFAST_MASK;
+	sector_t sector;
+
+	/*
+	 * Debug stuff, kill later
+	 */
+	if (!rq_mergeable(req)) {
+		blk_dump_rq_flags(req, "front");
+		return false;
+	}
+
+	if (!ll_front_merge_fn(q, req, bio))
+		return false;
+
+	trace_block_bio_frontmerge(q, bio);
+
+	if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff)
+		blk_rq_set_mixed_merge(req);
+
+	sector = bio->bi_sector;
+
+	bio->bi_next = req->bio;
+	req->bio = bio;
+
+	/*
+	 * may not be valid. if the low level driver said
+	 * it didn't need a bounce buffer then it better
+	 * not touch req->buffer either...
+	 */
+	req->buffer = bio_data(bio);
+	req->__sector = bio->bi_sector;
+	req->__data_len += bio->bi_size;
+	req->ioprio = ioprio_best(req->ioprio, bio_prio(bio));
+
+	drive_stat_acct(req, 0);
+	return true;
+}
+
+/*
+ * Attempts to merge with the plugged list in the current process. Returns
+ * true if merge was successful, otherwise false.
+ */
+static bool attempt_plug_merge(struct task_struct *tsk, struct request_queue *q,
+			       struct bio *bio)
+{
+	struct blk_plug *plug;
+	struct request *rq;
+	bool ret = false;
+
+	plug = tsk->plug;
+	if (!plug)
+		goto out;
+
+	list_for_each_entry_reverse(rq, &plug->list, queuelist) {
+		int el_ret;
+
+		if (rq->q != q)
+			continue;
+
+		el_ret = elv_try_merge(rq, bio);
+		if (el_ret == ELEVATOR_BACK_MERGE) {
+			ret = bio_attempt_back_merge(q, rq, bio);
+			if (ret)
+				break;
+		} else if (el_ret == ELEVATOR_FRONT_MERGE) {
+			ret = bio_attempt_front_merge(q, rq, bio);
+			if (ret)
+				break;
+		}
+	}
+out:
+	return ret;
+}
+
 void init_request_from_bio(struct request *req, struct bio *bio)
 {
 	req->cpu = bio->bi_comp_cpu;
@@ -1189,26 +1227,12 @@
 	blk_rq_bio_prep(req->q, req, bio);
 }
 
-/*
- * Only disabling plugging for non-rotational devices if it does tagging
- * as well, otherwise we do need the proper merging
- */
-static inline bool queue_should_plug(struct request_queue *q)
-{
-	return !(blk_queue_nonrot(q) && blk_queue_tagged(q));
-}
-
 static int __make_request(struct request_queue *q, struct bio *bio)
 {
-	struct request *req;
-	int el_ret;
-	unsigned int bytes = bio->bi_size;
-	const unsigned short prio = bio_prio(bio);
 	const bool sync = !!(bio->bi_rw & REQ_SYNC);
-	const bool unplug = !!(bio->bi_rw & REQ_UNPLUG);
-	const unsigned long ff = bio->bi_rw & REQ_FAILFAST_MASK;
-	int where = ELEVATOR_INSERT_SORT;
-	int rw_flags;
+	struct blk_plug *plug;
+	int el_ret, rw_flags, where = ELEVATOR_INSERT_SORT;
+	struct request *req;
 
 	/*
 	 * low level driver can indicate that it wants pages above a
@@ -1217,78 +1241,36 @@
 	 */
 	blk_queue_bounce(q, &bio);
 
-	spin_lock_irq(q->queue_lock);
-
 	if (bio->bi_rw & (REQ_FLUSH | REQ_FUA)) {
-		where = ELEVATOR_INSERT_FRONT;
+		spin_lock_irq(q->queue_lock);
+		where = ELEVATOR_INSERT_FLUSH;
 		goto get_rq;
 	}
 
-	if (elv_queue_empty(q))
-		goto get_rq;
-
-	el_ret = elv_merge(q, &req, bio);
-	switch (el_ret) {
-	case ELEVATOR_BACK_MERGE:
-		BUG_ON(!rq_mergeable(req));
-
-		if (!ll_back_merge_fn(q, req, bio))
-			break;
-
-		trace_block_bio_backmerge(q, bio);
-
-		if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff)
-			blk_rq_set_mixed_merge(req);
-
-		req->biotail->bi_next = bio;
-		req->biotail = bio;
-		req->__data_len += bytes;
-		req->ioprio = ioprio_best(req->ioprio, prio);
-		if (!blk_rq_cpu_valid(req))
-			req->cpu = bio->bi_comp_cpu;
-		drive_stat_acct(req, 0);
-		elv_bio_merged(q, req, bio);
-		if (!attempt_back_merge(q, req))
-			elv_merged_request(q, req, el_ret);
+	/*
+	 * Check if we can merge with the plugged list before grabbing
+	 * any locks.
+	 */
+	if (attempt_plug_merge(current, q, bio))
 		goto out;
 
-	case ELEVATOR_FRONT_MERGE:
-		BUG_ON(!rq_mergeable(req));
-
-		if (!ll_front_merge_fn(q, req, bio))
-			break;
-
-		trace_block_bio_frontmerge(q, bio);
+	spin_lock_irq(q->queue_lock);
 
-		if ((req->cmd_flags & REQ_FAILFAST_MASK) != ff) {
-			blk_rq_set_mixed_merge(req);
-			req->cmd_flags &= ~REQ_FAILFAST_MASK;
-			req->cmd_flags |= ff;
+	el_ret = elv_merge(q, &req, bio);
+	if (el_ret == ELEVATOR_BACK_MERGE) {
+		BUG_ON(req->cmd_flags & REQ_ON_PLUG);
+		if (bio_attempt_back_merge(q, req, bio)) {
+			if (!attempt_back_merge(q, req))
+				elv_merged_request(q, req, el_ret);
+			goto out_unlock;
+		}
+	} else if (el_ret == ELEVATOR_FRONT_MERGE) {
+		BUG_ON(req->cmd_flags & REQ_ON_PLUG);
+		if (bio_attempt_front_merge(q, req, bio)) {
+			if (!attempt_front_merge(q, req))
+				elv_merged_request(q, req, el_ret);
+			goto out_unlock;
 		}
-
-		bio->bi_next = req->bio;
-		req->bio = bio;
-
-		/*
-		 * may not be valid. if the low level driver said
-		 * it didn't need a bounce buffer then it better
-		 * not touch req->buffer either...
-		 */
-		req->buffer = bio_data(bio);
-		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;
-		drive_stat_acct(req, 0);
-		elv_bio_merged(q, req, bio);
-		if (!attempt_front_merge(q, req))
-			elv_merged_request(q, req, el_ret);
-		goto out;
-
-	/* ELV_NO_MERGE: elevator says don't/can't merge. */
-	default:
-		;
 	}
 
 get_rq:
@@ -1315,20 +1297,43 @@
 	 */
 	init_request_from_bio(req, bio);
 
-	spin_lock_irq(q->queue_lock);
 	if (test_bit(QUEUE_FLAG_SAME_COMP, &q->queue_flags) ||
-	    bio_flagged(bio, BIO_CPU_AFFINE))
-		req->cpu = blk_cpu_to_group(smp_processor_id());
-	if (queue_should_plug(q) && elv_queue_empty(q))
-		blk_plug_device(q);
+	    bio_flagged(bio, BIO_CPU_AFFINE)) {
+		req->cpu = blk_cpu_to_group(get_cpu());
+		put_cpu();
+	}
 
-	/* insert the request into the elevator */
-	drive_stat_acct(req, 1);
-	__elv_add_request(q, req, where, 0);
+	plug = current->plug;
+	if (plug) {
+		/*
+		 * If this is the first request added after a plug, fire
+		 * of a plug trace. If others have been added before, check
+		 * if we have multiple devices in this plug. If so, make a
+		 * note to sort the list before dispatch.
+		 */
+		if (list_empty(&plug->list))
+			trace_block_plug(q);
+		else if (!plug->should_sort) {
+			struct request *__rq;
+
+			__rq = list_entry_rq(plug->list.prev);
+			if (__rq->q != q)
+				plug->should_sort = 1;
+		}
+		/*
+		 * Debug flag, kill later
+		 */
+		req->cmd_flags |= REQ_ON_PLUG;
+		list_add_tail(&req->queuelist, &plug->list);
+		drive_stat_acct(req, 1);
+	} else {
+		spin_lock_irq(q->queue_lock);
+		add_acct_request(q, req, where);
+		__blk_run_queue(q);
+out_unlock:
+		spin_unlock_irq(q->queue_lock);
+	}
 out:
-	if (unplug || !queue_should_plug(q))
-		__generic_unplug_device(q);
-	spin_unlock_irq(q->queue_lock);
 	return 0;
 }
 
@@ -1731,9 +1736,7 @@
 	 */
 	BUG_ON(blk_queued_rq(rq));
 
-	drive_stat_acct(rq, 1);
-	__elv_add_request(q, rq, ELEVATOR_INSERT_BACK, 0);
-
+	add_acct_request(q, rq, ELEVATOR_INSERT_BACK);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
 	return 0;
@@ -1805,7 +1808,7 @@
 	 * normal IO on queueing nor completion.  Accounting the
 	 * containing request is enough.
 	 */
-	if (blk_do_io_stat(req) && req != &req->q->flush_rq) {
+	if (blk_do_io_stat(req) && !(req->cmd_flags & REQ_FLUSH_SEQ)) {
 		unsigned long duration = jiffies - req->start_time;
 		const int rw = rq_data_dir(req);
 		struct hd_struct *part;
@@ -2045,9 +2048,26 @@
 
 	if (error && req->cmd_type == REQ_TYPE_FS &&
 	    !(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)blk_rq_pos(req));
+		char *error_type;
+
+		switch (error) {
+		case -ENOLINK:
+			error_type = "recoverable transport";
+			break;
+		case -EREMOTEIO:
+			error_type = "critical target";
+			break;
+		case -EBADE:
+			error_type = "critical nexus";
+			break;
+		case -EIO:
+		default:
+			error_type = "I/O";
+			break;
+		}
+		printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
+		       error_type, req->rq_disk ? req->rq_disk->disk_name : "?",
+		       (unsigned long long)blk_rq_pos(req));
 	}
 
 	blk_account_io_completion(req, nr_bytes);
@@ -2145,7 +2165,7 @@
 	 * size, something has gone terribly wrong.
 	 */
 	if (blk_rq_bytes(req) < blk_rq_cur_bytes(req)) {
-		printk(KERN_ERR "blk: request botched\n");
+		blk_dump_rq_flags(req, "request botched");
 		req->__data_len = blk_rq_cur_bytes(req);
 	}
 
@@ -2611,6 +2631,166 @@
 }
 EXPORT_SYMBOL(kblockd_schedule_work);
 
+int kblockd_schedule_delayed_work(struct request_queue *q,
+			struct delayed_work *dwork, unsigned long delay)
+{
+	return queue_delayed_work(kblockd_workqueue, dwork, delay);
+}
+EXPORT_SYMBOL(kblockd_schedule_delayed_work);
+
+#define PLUG_MAGIC	0x91827364
+
+void blk_start_plug(struct blk_plug *plug)
+{
+	struct task_struct *tsk = current;
+
+	plug->magic = PLUG_MAGIC;
+	INIT_LIST_HEAD(&plug->list);
+	INIT_LIST_HEAD(&plug->cb_list);
+	plug->should_sort = 0;
+
+	/*
+	 * If this is a nested plug, don't actually assign it. It will be
+	 * flushed on its own.
+	 */
+	if (!tsk->plug) {
+		/*
+		 * Store ordering should not be needed here, since a potential
+		 * preempt will imply a full memory barrier
+		 */
+		tsk->plug = plug;
+	}
+}
+EXPORT_SYMBOL(blk_start_plug);
+
+static int plug_rq_cmp(void *priv, struct list_head *a, struct list_head *b)
+{
+	struct request *rqa = container_of(a, struct request, queuelist);
+	struct request *rqb = container_of(b, struct request, queuelist);
+
+	return !(rqa->q <= rqb->q);
+}
+
+/*
+ * If 'from_schedule' is true, then postpone the dispatch of requests
+ * until a safe kblockd context. We due this to avoid accidental big
+ * additional stack usage in driver dispatch, in places where the originally
+ * plugger did not intend it.
+ */
+static void queue_unplugged(struct request_queue *q, unsigned int depth,
+			    bool from_schedule)
+	__releases(q->queue_lock)
+{
+	trace_block_unplug(q, depth, !from_schedule);
+
+	/*
+	 * If we are punting this to kblockd, then we can safely drop
+	 * the queue_lock before waking kblockd (which needs to take
+	 * this lock).
+	 */
+	if (from_schedule) {
+		spin_unlock(q->queue_lock);
+		blk_run_queue_async(q);
+	} else {
+		__blk_run_queue(q);
+		spin_unlock(q->queue_lock);
+	}
+
+}
+
+static void flush_plug_callbacks(struct blk_plug *plug)
+{
+	LIST_HEAD(callbacks);
+
+	if (list_empty(&plug->cb_list))
+		return;
+
+	list_splice_init(&plug->cb_list, &callbacks);
+
+	while (!list_empty(&callbacks)) {
+		struct blk_plug_cb *cb = list_first_entry(&callbacks,
+							  struct blk_plug_cb,
+							  list);
+		list_del(&cb->list);
+		cb->callback(cb);
+	}
+}
+
+void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
+{
+	struct request_queue *q;
+	unsigned long flags;
+	struct request *rq;
+	LIST_HEAD(list);
+	unsigned int depth;
+
+	BUG_ON(plug->magic != PLUG_MAGIC);
+
+	flush_plug_callbacks(plug);
+	if (list_empty(&plug->list))
+		return;
+
+	list_splice_init(&plug->list, &list);
+
+	if (plug->should_sort) {
+		list_sort(NULL, &list, plug_rq_cmp);
+		plug->should_sort = 0;
+	}
+
+	q = NULL;
+	depth = 0;
+
+	/*
+	 * Save and disable interrupts here, to avoid doing it for every
+	 * queue lock we have to take.
+	 */
+	local_irq_save(flags);
+	while (!list_empty(&list)) {
+		rq = list_entry_rq(list.next);
+		list_del_init(&rq->queuelist);
+		BUG_ON(!(rq->cmd_flags & REQ_ON_PLUG));
+		BUG_ON(!rq->q);
+		if (rq->q != q) {
+			/*
+			 * This drops the queue lock
+			 */
+			if (q)
+				queue_unplugged(q, depth, from_schedule);
+			q = rq->q;
+			depth = 0;
+			spin_lock(q->queue_lock);
+		}
+		rq->cmd_flags &= ~REQ_ON_PLUG;
+
+		/*
+		 * rq is already accounted, so use raw insert
+		 */
+		if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA))
+			__elv_add_request(q, rq, ELEVATOR_INSERT_FLUSH);
+		else
+			__elv_add_request(q, rq, ELEVATOR_INSERT_SORT_MERGE);
+
+		depth++;
+	}
+
+	/*
+	 * This drops the queue lock
+	 */
+	if (q)
+		queue_unplugged(q, depth, from_schedule);
+
+	local_irq_restore(flags);
+}
+
+void blk_finish_plug(struct blk_plug *plug)
+{
+	blk_flush_plug_list(plug, false);
+
+	if (plug == current->plug)
+		current->plug = NULL;
+}
+EXPORT_SYMBOL(blk_finish_plug);
+
 int __init blk_dev_init(void)
 {
 	BUILD_BUG_ON(__REQ_NR_BITS > 8 *
diff -druN linux-libre-2.6.38-gnu/block/blk-exec.c linux-libre-2.6.39-gnu/block/blk-exec.c
--- linux-libre-2.6.38-gnu/block/blk-exec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-exec.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,8 +54,8 @@
 	rq->end_io = done;
 	WARN_ON(irqs_disabled());
 	spin_lock_irq(q->queue_lock);
-	__elv_add_request(q, rq, where, 1);
-	__generic_unplug_device(q);
+	__elv_add_request(q, rq, where);
+	__blk_run_queue(q);
 	/* the queue is stopped so it won't be plugged+unplugged */
 	if (rq->cmd_type == REQ_TYPE_PM_RESUME)
 		q->request_fn(q);
diff -druN linux-libre-2.6.38-gnu/block/blk-flush.c linux-libre-2.6.39-gnu/block/blk-flush.c
--- linux-libre-2.6.38-gnu/block/blk-flush.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-flush.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,69 @@
 /*
  * Functions to sequence FLUSH and FUA writes.
+ *
+ * Copyright (C) 2011		Max Planck Institute for Gravitational Physics
+ * Copyright (C) 2011		Tejun Heo <tj@kernel.org>
+ *
+ * This file is released under the GPLv2.
+ *
+ * REQ_{FLUSH|FUA} requests are decomposed to sequences consisted of three
+ * optional steps - PREFLUSH, DATA and POSTFLUSH - according to the request
+ * properties and hardware capability.
+ *
+ * If a request doesn't have data, only REQ_FLUSH makes sense, which
+ * indicates a simple flush request.  If there is data, REQ_FLUSH indicates
+ * that the device cache should be flushed before the data is executed, and
+ * REQ_FUA means that the data must be on non-volatile media on request
+ * completion.
+ *
+ * If the device doesn't have writeback cache, FLUSH and FUA don't make any
+ * difference.  The requests are either completed immediately if there's no
+ * data or executed as normal requests otherwise.
+ *
+ * If the device has writeback cache and supports FUA, REQ_FLUSH is
+ * translated to PREFLUSH but REQ_FUA is passed down directly with DATA.
+ *
+ * If the device has writeback cache and doesn't support FUA, REQ_FLUSH is
+ * translated to PREFLUSH and REQ_FUA to POSTFLUSH.
+ *
+ * The actual execution of flush is double buffered.  Whenever a request
+ * needs to execute PRE or POSTFLUSH, it queues at
+ * q->flush_queue[q->flush_pending_idx].  Once certain criteria are met, a
+ * flush is issued and the pending_idx is toggled.  When the flush
+ * completes, all the requests which were pending are proceeded to the next
+ * step.  This allows arbitrary merging of different types of FLUSH/FUA
+ * requests.
+ *
+ * Currently, the following conditions are used to determine when to issue
+ * flush.
+ *
+ * C1. At any given time, only one flush shall be in progress.  This makes
+ *     double buffering sufficient.
+ *
+ * C2. Flush is deferred if any request is executing DATA of its sequence.
+ *     This avoids issuing separate POSTFLUSHes for requests which shared
+ *     PREFLUSH.
+ *
+ * C3. The second condition is ignored if there is a request which has
+ *     waited longer than FLUSH_PENDING_TIMEOUT.  This is to avoid
+ *     starvation in the unlikely case where there are continuous stream of
+ *     FUA (without FLUSH) requests.
+ *
+ * For devices which support FUA, it isn't clear whether C2 (and thus C3)
+ * is beneficial.
+ *
+ * Note that a sequenced FLUSH/FUA request with DATA is completed twice.
+ * Once while executing DATA and again after the whole sequence is
+ * complete.  The first completion updates the contained bio but doesn't
+ * finish it so that the bio submitter is notified only after the whole
+ * sequence is complete.  This is implemented by testing REQ_FLUSH_SEQ in
+ * req_bio_endio().
+ *
+ * The above peculiarity requires that each FLUSH/FUA request has only one
+ * bio attached to it, which is guaranteed as they aren't allowed to be
+ * merged in the usual way.
  */
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/bio.h>
@@ -11,58 +74,142 @@
 
 /* FLUSH/FUA sequences */
 enum {
-	QUEUE_FSEQ_STARTED	= (1 << 0), /* flushing in progress */
-	QUEUE_FSEQ_PREFLUSH	= (1 << 1), /* pre-flushing in progress */
-	QUEUE_FSEQ_DATA		= (1 << 2), /* data write in progress */
-	QUEUE_FSEQ_POSTFLUSH	= (1 << 3), /* post-flushing in progress */
-	QUEUE_FSEQ_DONE		= (1 << 4),
+	REQ_FSEQ_PREFLUSH	= (1 << 0), /* pre-flushing in progress */
+	REQ_FSEQ_DATA		= (1 << 1), /* data write in progress */
+	REQ_FSEQ_POSTFLUSH	= (1 << 2), /* post-flushing in progress */
+	REQ_FSEQ_DONE		= (1 << 3),
+
+	REQ_FSEQ_ACTIONS	= REQ_FSEQ_PREFLUSH | REQ_FSEQ_DATA |
+				  REQ_FSEQ_POSTFLUSH,
+
+	/*
+	 * If flush has been pending longer than the following timeout,
+	 * it's issued even if flush_data requests are still in flight.
+	 */
+	FLUSH_PENDING_TIMEOUT	= 5 * HZ,
 };
 
-static struct request *queue_next_fseq(struct request_queue *q);
+static bool blk_kick_flush(struct request_queue *q);
 
-unsigned blk_flush_cur_seq(struct request_queue *q)
+static unsigned int blk_flush_policy(unsigned int fflags, struct request *rq)
 {
-	if (!q->flush_seq)
-		return 0;
-	return 1 << ffz(q->flush_seq);
+	unsigned int policy = 0;
+
+	if (fflags & REQ_FLUSH) {
+		if (rq->cmd_flags & REQ_FLUSH)
+			policy |= REQ_FSEQ_PREFLUSH;
+		if (blk_rq_sectors(rq))
+			policy |= REQ_FSEQ_DATA;
+		if (!(fflags & REQ_FUA) && (rq->cmd_flags & REQ_FUA))
+			policy |= REQ_FSEQ_POSTFLUSH;
+	}
+	return policy;
 }
 
-static struct request *blk_flush_complete_seq(struct request_queue *q,
-					      unsigned seq, int error)
+static unsigned int blk_flush_cur_seq(struct request *rq)
 {
-	struct request *next_rq = NULL;
+	return 1 << ffz(rq->flush.seq);
+}
 
-	if (error && !q->flush_err)
-		q->flush_err = error;
+static void blk_flush_restore_request(struct request *rq)
+{
+	/*
+	 * After flush data completion, @rq->bio is %NULL but we need to
+	 * complete the bio again.  @rq->biotail is guaranteed to equal the
+	 * original @rq->bio.  Restore it.
+	 */
+	rq->bio = rq->biotail;
 
-	BUG_ON(q->flush_seq & seq);
-	q->flush_seq |= seq;
+	/* make @rq a normal request */
+	rq->cmd_flags &= ~REQ_FLUSH_SEQ;
+	rq->end_io = NULL;
+}
 
-	if (blk_flush_cur_seq(q) != QUEUE_FSEQ_DONE) {
-		/* not complete yet, queue the next flush sequence */
-		next_rq = queue_next_fseq(q);
-	} else {
-		/* complete this flush request */
-		__blk_end_request_all(q->orig_flush_rq, q->flush_err);
-		q->orig_flush_rq = NULL;
-		q->flush_seq = 0;
+/**
+ * blk_flush_complete_seq - complete flush sequence
+ * @rq: FLUSH/FUA request being sequenced
+ * @seq: sequences to complete (mask of %REQ_FSEQ_*, can be zero)
+ * @error: whether an error occurred
+ *
+ * @rq just completed @seq part of its flush sequence, record the
+ * completion and trigger the next step.
+ *
+ * CONTEXT:
+ * spin_lock_irq(q->queue_lock)
+ *
+ * RETURNS:
+ * %true if requests were added to the dispatch queue, %false otherwise.
+ */
+static bool blk_flush_complete_seq(struct request *rq, unsigned int seq,
+				   int error)
+{
+	struct request_queue *q = rq->q;
+	struct list_head *pending = &q->flush_queue[q->flush_pending_idx];
+	bool queued = false;
 
-		/* dispatch the next flush if there's one */
-		if (!list_empty(&q->pending_flushes)) {
-			next_rq = list_entry_rq(q->pending_flushes.next);
-			list_move(&next_rq->queuelist, &q->queue_head);
-		}
+	BUG_ON(rq->flush.seq & seq);
+	rq->flush.seq |= seq;
+
+	if (likely(!error))
+		seq = blk_flush_cur_seq(rq);
+	else
+		seq = REQ_FSEQ_DONE;
+
+	switch (seq) {
+	case REQ_FSEQ_PREFLUSH:
+	case REQ_FSEQ_POSTFLUSH:
+		/* queue for flush */
+		if (list_empty(pending))
+			q->flush_pending_since = jiffies;
+		list_move_tail(&rq->flush.list, pending);
+		break;
+
+	case REQ_FSEQ_DATA:
+		list_move_tail(&rq->flush.list, &q->flush_data_in_flight);
+		list_add(&rq->queuelist, &q->queue_head);
+		queued = true;
+		break;
+
+	case REQ_FSEQ_DONE:
+		/*
+		 * @rq was previously adjusted by blk_flush_issue() for
+		 * flush sequencing and may already have gone through the
+		 * flush data request completion path.  Restore @rq for
+		 * normal completion and end it.
+		 */
+		BUG_ON(!list_empty(&rq->queuelist));
+		list_del_init(&rq->flush.list);
+		blk_flush_restore_request(rq);
+		__blk_end_request_all(rq, error);
+		break;
+
+	default:
+		BUG();
 	}
-	return next_rq;
+
+	return blk_kick_flush(q) | queued;
 }
 
-static void blk_flush_complete_seq_end_io(struct request_queue *q,
-					  unsigned seq, int error)
+static void flush_end_io(struct request *flush_rq, int error)
 {
-	bool was_empty = elv_queue_empty(q);
-	struct request *next_rq;
+	struct request_queue *q = flush_rq->q;
+	struct list_head *running = &q->flush_queue[q->flush_running_idx];
+	bool queued = false;
+	struct request *rq, *n;
 
-	next_rq = blk_flush_complete_seq(q, seq, error);
+	BUG_ON(q->flush_pending_idx == q->flush_running_idx);
+
+	/* account completion of the flush request */
+	q->flush_running_idx ^= 1;
+	elv_completed_request(q, flush_rq);
+
+	/* and push the waiting requests to the next stage */
+	list_for_each_entry_safe(rq, n, running, flush.list) {
+		unsigned int seq = blk_flush_cur_seq(rq);
+
+		BUG_ON(seq != REQ_FSEQ_PREFLUSH && seq != REQ_FSEQ_POSTFLUSH);
+		queued |= blk_flush_complete_seq(rq, seq, error);
+	}
 
 	/*
 	 * Moving a request silently to empty queue_head may stall the
@@ -70,127 +217,153 @@
 	 * from request completion path and calling directly into
 	 * request_fn may confuse the driver.  Always use kblockd.
 	 */
-	if (was_empty && next_rq)
-		__blk_run_queue(q, true);
+	if (queued)
+		blk_run_queue_async(q);
 }
 
-static void pre_flush_end_io(struct request *rq, int error)
+/**
+ * blk_kick_flush - consider issuing flush request
+ * @q: request_queue being kicked
+ *
+ * Flush related states of @q have changed, consider issuing flush request.
+ * Please read the comment at the top of this file for more info.
+ *
+ * CONTEXT:
+ * spin_lock_irq(q->queue_lock)
+ *
+ * RETURNS:
+ * %true if flush was issued, %false otherwise.
+ */
+static bool blk_kick_flush(struct request_queue *q)
 {
-	elv_completed_request(rq->q, rq);
-	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_PREFLUSH, error);
+	struct list_head *pending = &q->flush_queue[q->flush_pending_idx];
+	struct request *first_rq =
+		list_first_entry(pending, struct request, flush.list);
+
+	/* C1 described at the top of this file */
+	if (q->flush_pending_idx != q->flush_running_idx || list_empty(pending))
+		return false;
+
+	/* C2 and C3 */
+	if (!list_empty(&q->flush_data_in_flight) &&
+	    time_before(jiffies,
+			q->flush_pending_since + FLUSH_PENDING_TIMEOUT))
+		return false;
+
+	/*
+	 * Issue flush and toggle pending_idx.  This makes pending_idx
+	 * different from running_idx, which means flush is in flight.
+	 */
+	blk_rq_init(q, &q->flush_rq);
+	q->flush_rq.cmd_type = REQ_TYPE_FS;
+	q->flush_rq.cmd_flags = WRITE_FLUSH | REQ_FLUSH_SEQ;
+	q->flush_rq.rq_disk = first_rq->rq_disk;
+	q->flush_rq.end_io = flush_end_io;
+
+	q->flush_pending_idx ^= 1;
+	list_add_tail(&q->flush_rq.queuelist, &q->queue_head);
+	return true;
 }
 
 static void flush_data_end_io(struct request *rq, int error)
 {
-	elv_completed_request(rq->q, rq);
-	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_DATA, error);
-}
+	struct request_queue *q = rq->q;
 
-static void post_flush_end_io(struct request *rq, int error)
-{
-	elv_completed_request(rq->q, rq);
-	blk_flush_complete_seq_end_io(rq->q, QUEUE_FSEQ_POSTFLUSH, error);
+	/*
+	 * After populating an empty queue, kick it to avoid stall.  Read
+	 * the comment in flush_end_io().
+	 */
+	if (blk_flush_complete_seq(rq, REQ_FSEQ_DATA, error))
+		blk_run_queue_async(q);
 }
 
-static void init_flush_request(struct request *rq, struct gendisk *disk)
+/**
+ * blk_insert_flush - insert a new FLUSH/FUA request
+ * @rq: request to insert
+ *
+ * To be called from __elv_add_request() for %ELEVATOR_INSERT_FLUSH insertions.
+ * @rq is being submitted.  Analyze what needs to be done and put it on the
+ * right queue.
+ *
+ * CONTEXT:
+ * spin_lock_irq(q->queue_lock)
+ */
+void blk_insert_flush(struct request *rq)
 {
-	rq->cmd_type = REQ_TYPE_FS;
-	rq->cmd_flags = WRITE_FLUSH;
-	rq->rq_disk = disk;
-}
+	struct request_queue *q = rq->q;
+	unsigned int fflags = q->flush_flags;	/* may change, cache */
+	unsigned int policy = blk_flush_policy(fflags, rq);
 
-static struct request *queue_next_fseq(struct request_queue *q)
-{
-	struct request *orig_rq = q->orig_flush_rq;
-	struct request *rq = &q->flush_rq;
+	BUG_ON(rq->end_io);
+	BUG_ON(!rq->bio || rq->bio != rq->biotail);
 
-	blk_rq_init(q, rq);
+	/*
+	 * @policy now records what operations need to be done.  Adjust
+	 * REQ_FLUSH and FUA for the driver.
+	 */
+	rq->cmd_flags &= ~REQ_FLUSH;
+	if (!(fflags & REQ_FUA))
+		rq->cmd_flags &= ~REQ_FUA;
 
-	switch (blk_flush_cur_seq(q)) {
-	case QUEUE_FSEQ_PREFLUSH:
-		init_flush_request(rq, orig_rq->rq_disk);
-		rq->end_io = pre_flush_end_io;
-		break;
-	case QUEUE_FSEQ_DATA:
-		init_request_from_bio(rq, orig_rq->bio);
-		/*
-		 * orig_rq->rq_disk may be different from
-		 * bio->bi_bdev->bd_disk if orig_rq got here through
-		 * remapping drivers.  Make sure rq->rq_disk points
-		 * to the same one as orig_rq.
-		 */
-		rq->rq_disk = orig_rq->rq_disk;
-		rq->cmd_flags &= ~(REQ_FLUSH | REQ_FUA);
-		rq->cmd_flags |= orig_rq->cmd_flags & (REQ_FLUSH | REQ_FUA);
-		rq->end_io = flush_data_end_io;
-		break;
-	case QUEUE_FSEQ_POSTFLUSH:
-		init_flush_request(rq, orig_rq->rq_disk);
-		rq->end_io = post_flush_end_io;
-		break;
-	default:
-		BUG();
+	/*
+	 * If there's data but flush is not necessary, the request can be
+	 * processed directly without going through flush machinery.  Queue
+	 * for normal execution.
+	 */
+	if ((policy & REQ_FSEQ_DATA) &&
+	    !(policy & (REQ_FSEQ_PREFLUSH | REQ_FSEQ_POSTFLUSH))) {
+		list_add_tail(&rq->queuelist, &q->queue_head);
+		return;
 	}
 
-	elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
-	return rq;
+	/*
+	 * @rq should go through flush machinery.  Mark it part of flush
+	 * sequence and submit for further processing.
+	 */
+	memset(&rq->flush, 0, sizeof(rq->flush));
+	INIT_LIST_HEAD(&rq->flush.list);
+	rq->cmd_flags |= REQ_FLUSH_SEQ;
+	rq->end_io = flush_data_end_io;
+
+	blk_flush_complete_seq(rq, REQ_FSEQ_ACTIONS & ~policy, 0);
 }
 
-struct request *blk_do_flush(struct request_queue *q, struct request *rq)
+/**
+ * blk_abort_flushes - @q is being aborted, abort flush requests
+ * @q: request_queue being aborted
+ *
+ * To be called from elv_abort_queue().  @q is being aborted.  Prepare all
+ * FLUSH/FUA requests for abortion.
+ *
+ * CONTEXT:
+ * spin_lock_irq(q->queue_lock)
+ */
+void blk_abort_flushes(struct request_queue *q)
 {
-	unsigned int fflags = q->flush_flags; /* may change, cache it */
-	bool has_flush = fflags & REQ_FLUSH, has_fua = fflags & REQ_FUA;
-	bool do_preflush = has_flush && (rq->cmd_flags & REQ_FLUSH);
-	bool do_postflush = has_flush && !has_fua && (rq->cmd_flags & REQ_FUA);
-	unsigned skip = 0;
+	struct request *rq, *n;
+	int i;
 
 	/*
-	 * Special case.  If there's data but flush is not necessary,
-	 * the request can be issued directly.
-	 *
-	 * Flush w/o data should be able to be issued directly too but
-	 * currently some drivers assume that rq->bio contains
-	 * non-zero data if it isn't NULL and empty FLUSH requests
-	 * getting here usually have bio's without data.
+	 * Requests in flight for data are already owned by the dispatch
+	 * queue or the device driver.  Just restore for normal completion.
 	 */
-	if (blk_rq_sectors(rq) && !do_preflush && !do_postflush) {
-		rq->cmd_flags &= ~REQ_FLUSH;
-		if (!has_fua)
-			rq->cmd_flags &= ~REQ_FUA;
-		return rq;
+	list_for_each_entry_safe(rq, n, &q->flush_data_in_flight, flush.list) {
+		list_del_init(&rq->flush.list);
+		blk_flush_restore_request(rq);
 	}
 
 	/*
-	 * Sequenced flushes can't be processed in parallel.  If
-	 * another one is already in progress, queue for later
-	 * processing.
+	 * We need to give away requests on flush queues.  Restore for
+	 * normal completion and put them on the dispatch queue.
 	 */
-	if (q->flush_seq) {
-		list_move_tail(&rq->queuelist, &q->pending_flushes);
-		return NULL;
+	for (i = 0; i < ARRAY_SIZE(q->flush_queue); i++) {
+		list_for_each_entry_safe(rq, n, &q->flush_queue[i],
+					 flush.list) {
+			list_del_init(&rq->flush.list);
+			blk_flush_restore_request(rq);
+			list_add_tail(&rq->queuelist, &q->queue_head);
+		}
 	}
-
-	/*
-	 * Start a new flush sequence
-	 */
-	q->flush_err = 0;
-	q->flush_seq |= QUEUE_FSEQ_STARTED;
-
-	/* adjust FLUSH/FUA of the original request and stash it away */
-	rq->cmd_flags &= ~REQ_FLUSH;
-	if (!has_fua)
-		rq->cmd_flags &= ~REQ_FUA;
-	blk_dequeue_request(rq);
-	q->orig_flush_rq = rq;
-
-	/* skip unneded sequences and return the first one */
-	if (!do_preflush)
-		skip |= QUEUE_FSEQ_PREFLUSH;
-	if (!blk_rq_sectors(rq))
-		skip |= QUEUE_FSEQ_DATA;
-	if (!do_postflush)
-		skip |= QUEUE_FSEQ_POSTFLUSH;
-	return blk_flush_complete_seq(q, skip, 0);
 }
 
 static void bio_end_flush(struct bio *bio, int err)
diff -druN linux-libre-2.6.38-gnu/block/blk.h linux-libre-2.6.39-gnu/block/blk.h
--- linux-libre-2.6.38-gnu/block/blk.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk.h	2011-05-19 00:06:34.000000000 -0400
@@ -18,8 +18,6 @@
 void blk_dequeue_request(struct request *rq);
 void __blk_queue_free_tags(struct request_queue *q);
 
-void blk_unplug_work(struct work_struct *work);
-void blk_unplug_timeout(unsigned long data);
 void blk_rq_timed_out_timer(unsigned long data);
 void blk_delete_timer(struct request *);
 void blk_add_timer(struct request *);
@@ -34,7 +32,7 @@
 
 /*
  * EH timer and IO completion will both attempt to 'grab' the request, make
- * sure that only one of them suceeds
+ * sure that only one of them succeeds
  */
 static inline int blk_mark_rq_complete(struct request *rq)
 {
@@ -51,21 +49,17 @@
  */
 #define ELV_ON_HASH(rq)		(!hlist_unhashed(&(rq)->hash))
 
-struct request *blk_do_flush(struct request_queue *q, struct request *rq);
+void blk_insert_flush(struct request *rq);
+void blk_abort_flushes(struct request_queue *q);
 
 static inline struct request *__elv_next_request(struct request_queue *q)
 {
 	struct request *rq;
 
 	while (1) {
-		while (!list_empty(&q->queue_head)) {
+		if (!list_empty(&q->queue_head)) {
 			rq = list_entry_rq(q->queue_head.next);
-			if (!(rq->cmd_flags & (REQ_FLUSH | REQ_FUA)) ||
-			    rq == &q->flush_rq)
-				return rq;
-			rq = blk_do_flush(q, rq);
-			if (rq)
-				return rq;
+			return rq;
 		}
 
 		if (!q->elevator->ops->elevator_dispatch_fn(q, 0))
@@ -109,6 +103,8 @@
 		      struct bio *bio);
 int attempt_back_merge(struct request_queue *q, struct request *rq);
 int attempt_front_merge(struct request_queue *q, struct request *rq);
+int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
+				struct request *next);
 void blk_recalc_rq_segments(struct request *rq);
 void blk_rq_set_mixed_merge(struct request *rq);
 
diff -druN linux-libre-2.6.38-gnu/block/blk-integrity.c linux-libre-2.6.39-gnu/block/blk-integrity.c
--- linux-libre-2.6.38-gnu/block/blk-integrity.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-integrity.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,8 @@
 
 static struct kmem_cache *integrity_cachep;
 
+static const char *bi_unsupported_name = "unsupported";
+
 /**
  * blk_rq_count_integrity_sg - Count number of integrity scatterlist elements
  * @q:		request queue
@@ -358,6 +360,14 @@
 	.release	= blk_integrity_release,
 };
 
+bool blk_integrity_is_initialized(struct gendisk *disk)
+{
+	struct blk_integrity *bi = blk_get_integrity(disk);
+
+	return (bi && bi->name && strcmp(bi->name, bi_unsupported_name) != 0);
+}
+EXPORT_SYMBOL(blk_integrity_is_initialized);
+
 /**
  * blk_integrity_register - Register a gendisk as being integrity-capable
  * @disk:	struct gendisk pointer to make integrity-aware
@@ -407,7 +417,7 @@
 		bi->get_tag_fn = template->get_tag_fn;
 		bi->tag_size = template->tag_size;
 	} else
-		bi->name = "unsupported";
+		bi->name = bi_unsupported_name;
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/block/blk-lib.c linux-libre-2.6.39-gnu/block/blk-lib.c
--- linux-libre-2.6.38-gnu/block/blk-lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,8 +136,6 @@
  *
  * Description:
  *  Generate and issue number of bios with zerofiled pages.
- *  Send barrier at the beginning and at the end if requested. This guarantie
- *  correct request ordering. Empty barrier allow us to avoid post queue flush.
  */
 
 int blkdev_issue_zeroout(struct block_device *bdev, sector_t sector,
diff -druN linux-libre-2.6.38-gnu/block/blk-merge.c linux-libre-2.6.39-gnu/block/blk-merge.c
--- linux-libre-2.6.38-gnu/block/blk-merge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-merge.c	2011-05-19 00:06:34.000000000 -0400
@@ -465,3 +465,9 @@
 
 	return 0;
 }
+
+int blk_attempt_req_merge(struct request_queue *q, struct request *rq,
+			  struct request *next)
+{
+	return attempt_merge(q, rq, next);
+}
diff -druN linux-libre-2.6.38-gnu/block/blk-settings.c linux-libre-2.6.39-gnu/block/blk-settings.c
--- linux-libre-2.6.38-gnu/block/blk-settings.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-settings.c	2011-05-19 00:06:34.000000000 -0400
@@ -164,25 +164,10 @@
 	blk_queue_congestion_threshold(q);
 	q->nr_batching = BLK_BATCH_REQ;
 
-	q->unplug_thresh = 4;		/* hmm */
-	q->unplug_delay = msecs_to_jiffies(3);	/* 3 milliseconds */
-	if (q->unplug_delay == 0)
-		q->unplug_delay = 1;
-
-	q->unplug_timer.function = blk_unplug_timeout;
-	q->unplug_timer.data = (unsigned long)q;
-
 	blk_set_default_limits(&q->limits);
 	blk_queue_max_hw_sectors(q, BLK_SAFE_MAX_SECTORS);
 
 	/*
-	 * 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
 	 */
 	blk_queue_bounce_limit(q, BLK_BOUNCE_HIGH);
diff -druN linux-libre-2.6.38-gnu/block/blk-sysfs.c linux-libre-2.6.39-gnu/block/blk-sysfs.c
--- linux-libre-2.6.38-gnu/block/blk-sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,14 +66,14 @@
 
 	if (rl->count[BLK_RW_SYNC] >= q->nr_requests) {
 		blk_set_queue_full(q, BLK_RW_SYNC);
-	} else if (rl->count[BLK_RW_SYNC]+1 <= q->nr_requests) {
+	} else {
 		blk_clear_queue_full(q, BLK_RW_SYNC);
 		wake_up(&rl->wait[BLK_RW_SYNC]);
 	}
 
 	if (rl->count[BLK_RW_ASYNC] >= q->nr_requests) {
 		blk_set_queue_full(q, BLK_RW_ASYNC);
-	} else if (rl->count[BLK_RW_ASYNC]+1 <= q->nr_requests) {
+	} else {
 		blk_clear_queue_full(q, BLK_RW_ASYNC);
 		wake_up(&rl->wait[BLK_RW_ASYNC]);
 	}
@@ -471,8 +471,6 @@
 
 	blk_sync_queue(q);
 
-	blk_throtl_exit(q);
-
 	if (rl->rq_pool)
 		mempool_destroy(rl->rq_pool);
 
@@ -500,7 +498,6 @@
 {
 	int ret;
 	struct device *dev = disk_to_dev(disk);
-
 	struct request_queue *q = disk->queue;
 
 	if (WARN_ON(!q))
@@ -511,8 +508,10 @@
 		return ret;
 
 	ret = kobject_add(&q->kobj, kobject_get(&dev->kobj), "%s", "queue");
-	if (ret < 0)
+	if (ret < 0) {
+		blk_trace_remove_sysfs(dev);
 		return ret;
+	}
 
 	kobject_uevent(&q->kobj, KOBJ_ADD);
 
@@ -523,7 +522,7 @@
 	if (ret) {
 		kobject_uevent(&q->kobj, KOBJ_REMOVE);
 		kobject_del(&q->kobj);
-		blk_trace_remove_sysfs(disk_to_dev(disk));
+		blk_trace_remove_sysfs(dev);
 		kobject_put(&dev->kobj);
 		return ret;
 	}
diff -druN linux-libre-2.6.38-gnu/block/blk-throttle.c linux-libre-2.6.39-gnu/block/blk-throttle.c
--- linux-libre-2.6.38-gnu/block/blk-throttle.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/blk-throttle.c	2011-05-19 00:06:34.000000000 -0400
@@ -77,7 +77,7 @@
 	unsigned long slice_end[2];
 
 	/* Some throttle limits got updated for the group */
-	bool limits_changed;
+	int limits_changed;
 };
 
 struct throtl_data
@@ -102,7 +102,7 @@
 	/* Work for dispatching throttled bios */
 	struct delayed_work throtl_work;
 
-	atomic_t limits_changed;
+	int limits_changed;
 };
 
 enum tg_state_flags {
@@ -160,9 +160,8 @@
 }
 
 static struct throtl_grp * throtl_find_alloc_tg(struct throtl_data *td,
-			struct cgroup *cgroup)
+			struct blkio_cgroup *blkcg)
 {
-	struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
 	struct throtl_grp *tg = NULL;
 	void *key = td;
 	struct backing_dev_info *bdi = &td->queue->backing_dev_info;
@@ -201,6 +200,7 @@
 	RB_CLEAR_NODE(&tg->rb_node);
 	bio_list_init(&tg->bio_lists[0]);
 	bio_list_init(&tg->bio_lists[1]);
+	td->limits_changed = false;
 
 	/*
 	 * Take the initial reference that will be released on destroy
@@ -228,12 +228,12 @@
 
 static struct throtl_grp * throtl_get_tg(struct throtl_data *td)
 {
-	struct cgroup *cgroup;
 	struct throtl_grp *tg = NULL;
+	struct blkio_cgroup *blkcg;
 
 	rcu_read_lock();
-	cgroup = task_cgroup(current, blkio_subsys_id);
-	tg = throtl_find_alloc_tg(td, cgroup);
+	blkcg = task_blkio_cgroup(current);
+	tg = throtl_find_alloc_tg(td, blkcg);
 	if (!tg)
 		tg = &td->root_tg;
 	rcu_read_unlock();
@@ -737,34 +737,36 @@
 	struct throtl_grp *tg;
 	struct hlist_node *pos, *n;
 
-	if (!atomic_read(&td->limits_changed))
+	if (!td->limits_changed)
 		return;
 
-	throtl_log(td, "limit changed =%d", atomic_read(&td->limits_changed));
+	xchg(&td->limits_changed, false);
 
-	/*
-	 * Make sure updates from throtl_update_blkio_group_read_bps() group
-	 * of functions to tg->limits_changed are visible. We do not
-	 * want update td->limits_changed to be visible but update to
-	 * tg->limits_changed not being visible yet on this cpu. Hence
-	 * the read barrier.
-	 */
-	smp_rmb();
+	throtl_log(td, "limits changed");
 
 	hlist_for_each_entry_safe(tg, pos, n, &td->tg_list, tg_node) {
-		if (throtl_tg_on_rr(tg) && tg->limits_changed) {
-			throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
-				" riops=%u wiops=%u", tg->bps[READ],
-				tg->bps[WRITE], tg->iops[READ],
-				tg->iops[WRITE]);
+		if (!tg->limits_changed)
+			continue;
+
+		if (!xchg(&tg->limits_changed, false))
+			continue;
+
+		throtl_log_tg(td, tg, "limit change rbps=%llu wbps=%llu"
+			" riops=%u wiops=%u", tg->bps[READ], tg->bps[WRITE],
+			tg->iops[READ], tg->iops[WRITE]);
+
+		/*
+		 * Restart the slices for both READ and WRITES. It
+		 * might happen that a group's limit are dropped
+		 * suddenly and we don't want to account recently
+		 * dispatched IO with new low rate
+		 */
+		throtl_start_new_slice(td, tg, 0);
+		throtl_start_new_slice(td, tg, 1);
+
+		if (throtl_tg_on_rr(tg))
 			tg_update_disptime(td, tg);
-			tg->limits_changed = false;
-		}
 	}
-
-	smp_mb__before_atomic_dec();
-	atomic_dec(&td->limits_changed);
-	smp_mb__after_atomic_dec();
 }
 
 /* Dispatch throttled bios. Should be called without queue lock held. */
@@ -774,6 +776,7 @@
 	unsigned int nr_disp = 0;
 	struct bio_list bio_list_on_stack;
 	struct bio *bio;
+	struct blk_plug plug;
 
 	spin_lock_irq(q->queue_lock);
 
@@ -802,9 +805,10 @@
 	 * immediate dispatch
 	 */
 	if (nr_disp) {
+		blk_start_plug(&plug);
 		while((bio = bio_list_pop(&bio_list_on_stack)))
 			generic_make_request(bio);
-		blk_unplug(q);
+		blk_finish_plug(&plug);
 	}
 	return nr_disp;
 }
@@ -825,7 +829,8 @@
 
 	struct delayed_work *dwork = &td->throtl_work;
 
-	if (total_nr_queued(td) > 0) {
+	/* schedule work if limits changed even if no bio is queued */
+	if (total_nr_queued(td) > 0 || td->limits_changed) {
 		/*
 		 * We might have a work scheduled to be executed in future.
 		 * Cancel that and schedule a new one.
@@ -898,10 +903,19 @@
 	spin_unlock_irqrestore(td->queue->queue_lock, flags);
 }
 
+static void throtl_update_blkio_group_common(struct throtl_data *td,
+				struct throtl_grp *tg)
+{
+	xchg(&tg->limits_changed, true);
+	xchg(&td->limits_changed, true);
+	/* Schedule a work now to process the limit change */
+	throtl_schedule_delayed_work(td, 0);
+}
+
 /*
  * For all update functions, key should be a valid pointer because these
  * update functions are called under blkcg_lock, that means, blkg is
- * valid and in turn key is valid. queue exit path can not race becuase
+ * valid and in turn key is valid. queue exit path can not race because
  * of blkcg_lock
  *
  * Can not take queue lock in update functions as queue lock under blkcg_lock
@@ -911,64 +925,43 @@
 				struct blkio_group *blkg, u64 read_bps)
 {
 	struct throtl_data *td = key;
+	struct throtl_grp *tg = tg_of_blkg(blkg);
 
-	tg_of_blkg(blkg)->bps[READ] = read_bps;
-	/* Make sure read_bps is updated before setting limits_changed */
-	smp_wmb();
-	tg_of_blkg(blkg)->limits_changed = true;
-
-	/* Make sure tg->limits_changed is updated before td->limits_changed */
-	smp_mb__before_atomic_inc();
-	atomic_inc(&td->limits_changed);
-	smp_mb__after_atomic_inc();
-
-	/* Schedule a work now to process the limit change */
-	throtl_schedule_delayed_work(td, 0);
+	tg->bps[READ] = read_bps;
+	throtl_update_blkio_group_common(td, tg);
 }
 
 static void throtl_update_blkio_group_write_bps(void *key,
 				struct blkio_group *blkg, u64 write_bps)
 {
 	struct throtl_data *td = key;
+	struct throtl_grp *tg = tg_of_blkg(blkg);
 
-	tg_of_blkg(blkg)->bps[WRITE] = write_bps;
-	smp_wmb();
-	tg_of_blkg(blkg)->limits_changed = true;
-	smp_mb__before_atomic_inc();
-	atomic_inc(&td->limits_changed);
-	smp_mb__after_atomic_inc();
-	throtl_schedule_delayed_work(td, 0);
+	tg->bps[WRITE] = write_bps;
+	throtl_update_blkio_group_common(td, tg);
 }
 
 static void throtl_update_blkio_group_read_iops(void *key,
 			struct blkio_group *blkg, unsigned int read_iops)
 {
 	struct throtl_data *td = key;
+	struct throtl_grp *tg = tg_of_blkg(blkg);
 
-	tg_of_blkg(blkg)->iops[READ] = read_iops;
-	smp_wmb();
-	tg_of_blkg(blkg)->limits_changed = true;
-	smp_mb__before_atomic_inc();
-	atomic_inc(&td->limits_changed);
-	smp_mb__after_atomic_inc();
-	throtl_schedule_delayed_work(td, 0);
+	tg->iops[READ] = read_iops;
+	throtl_update_blkio_group_common(td, tg);
 }
 
 static void throtl_update_blkio_group_write_iops(void *key,
 			struct blkio_group *blkg, unsigned int write_iops)
 {
 	struct throtl_data *td = key;
+	struct throtl_grp *tg = tg_of_blkg(blkg);
 
-	tg_of_blkg(blkg)->iops[WRITE] = write_iops;
-	smp_wmb();
-	tg_of_blkg(blkg)->limits_changed = true;
-	smp_mb__before_atomic_inc();
-	atomic_inc(&td->limits_changed);
-	smp_mb__after_atomic_inc();
-	throtl_schedule_delayed_work(td, 0);
+	tg->iops[WRITE] = write_iops;
+	throtl_update_blkio_group_common(td, tg);
 }
 
-void throtl_shutdown_timer_wq(struct request_queue *q)
+static void throtl_shutdown_wq(struct request_queue *q)
 {
 	struct throtl_data *td = q->td;
 
@@ -1009,20 +1002,28 @@
 		/*
 		 * There is already another bio queued in same dir. No
 		 * need to update dispatch time.
-		 * Still update the disptime if rate limits on this group
-		 * were changed.
 		 */
-		if (!tg->limits_changed)
-			update_disptime = false;
-		else
-			tg->limits_changed = false;
-
+		update_disptime = false;
 		goto queue_bio;
+
 	}
 
 	/* Bio is with-in rate limit of group */
 	if (tg_may_dispatch(td, tg, bio, NULL)) {
 		throtl_charge_bio(tg, bio);
+
+		/*
+		 * We need to trim slice even when bios are not being queued
+		 * otherwise it might happen that a bio is not queued for
+		 * a long time and slice keeps on extending and trim is not
+		 * called for a long time. Now if limits are reduced suddenly
+		 * we take into account all the IO dispatched so far at new
+		 * low rate and * newly queued IO gets a really long dispatch
+		 * time.
+		 *
+		 * So keep on trimming slice even if bio is not queued.
+		 */
+		throtl_trim_slice(td, tg, rw);
 		goto out;
 	}
 
@@ -1058,7 +1059,7 @@
 
 	INIT_HLIST_HEAD(&td->tg_list);
 	td->tg_service_tree = THROTL_RB_ROOT;
-	atomic_set(&td->limits_changed, 0);
+	td->limits_changed = false;
 
 	/* Init root group */
 	tg = &td->root_tg;
@@ -1070,6 +1071,7 @@
 	/* Practically unlimited BW */
 	tg->bps[0] = tg->bps[1] = -1;
 	tg->iops[0] = tg->iops[1] = -1;
+	td->limits_changed = false;
 
 	/*
 	 * Set root group reference to 2. One reference will be dropped when
@@ -1102,7 +1104,7 @@
 
 	BUG_ON(!td);
 
-	throtl_shutdown_timer_wq(q);
+	throtl_shutdown_wq(q);
 
 	spin_lock_irq(q->queue_lock);
 	throtl_release_tgs(td);
@@ -1132,7 +1134,7 @@
 	 * update limits through cgroup and another work got queued, cancel
 	 * it.
 	 */
-	throtl_shutdown_timer_wq(q);
+	throtl_shutdown_wq(q);
 	throtl_td_free(td);
 }
 
diff -druN linux-libre-2.6.38-gnu/block/cfq.h linux-libre-2.6.39-gnu/block/cfq.h
--- linux-libre-2.6.38-gnu/block/cfq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/cfq.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,9 +16,9 @@
 }
 
 static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
-			unsigned long time)
+			unsigned long time, unsigned long unaccounted_time)
 {
-	blkiocg_update_timeslice_used(blkg, time);
+	blkiocg_update_timeslice_used(blkg, time, unaccounted_time);
 }
 
 static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg)
@@ -85,7 +85,7 @@
 			unsigned long dequeue) {}
 
 static inline void cfq_blkiocg_update_timeslice_used(struct blkio_group *blkg,
-			unsigned long time) {}
+			unsigned long time, unsigned long unaccounted_time) {}
 static inline void cfq_blkiocg_set_start_empty_time(struct blkio_group *blkg) {}
 static inline void cfq_blkiocg_update_io_remove_stats(struct blkio_group *blkg,
 				bool direction, bool sync) {}
diff -druN linux-libre-2.6.38-gnu/block/cfq-iosched.c linux-libre-2.6.39-gnu/block/cfq-iosched.c
--- linux-libre-2.6.38-gnu/block/cfq-iosched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/cfq-iosched.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,9 +54,9 @@
 #define CFQQ_SEEKY(cfqq)	(hweight32(cfqq->seek_history) > 32/8)
 
 #define RQ_CIC(rq)		\
-	((struct cfq_io_context *) (rq)->elevator_private)
-#define RQ_CFQQ(rq)		(struct cfq_queue *) ((rq)->elevator_private2)
-#define RQ_CFQG(rq)		(struct cfq_group *) ((rq)->elevator_private3)
+	((struct cfq_io_context *) (rq)->elevator_private[0])
+#define RQ_CFQQ(rq)		(struct cfq_queue *) ((rq)->elevator_private[1])
+#define RQ_CFQG(rq)		(struct cfq_group *) ((rq)->elevator_private[2])
 
 static struct kmem_cache *cfq_pool;
 static struct kmem_cache *cfq_ioc_pool;
@@ -146,7 +146,6 @@
 	struct cfq_rb_root *service_tree;
 	struct cfq_queue *new_cfqq;
 	struct cfq_group *cfqg;
-	struct cfq_group *orig_cfqg;
 	/* Number of sectors dispatched from queue in single dispatch round */
 	unsigned long nr_sectors;
 };
@@ -179,6 +178,8 @@
 	/* group service_tree key */
 	u64 vdisktime;
 	unsigned int weight;
+	unsigned int new_weight;
+	bool needs_update;
 
 	/* number of cfqq currently on this group */
 	int nr_cfqq;
@@ -238,6 +239,7 @@
 	struct rb_root prio_trees[CFQ_PRIO_LISTS];
 
 	unsigned int busy_queues;
+	unsigned int busy_sync_queues;
 
 	int rq_in_driver;
 	int rq_in_flight[2];
@@ -285,7 +287,6 @@
 	unsigned int cfq_slice_idle;
 	unsigned int cfq_group_idle;
 	unsigned int cfq_latency;
-	unsigned int cfq_group_isolation;
 
 	unsigned int cic_index;
 	struct list_head cic_list;
@@ -501,13 +502,6 @@
 	}
 }
 
-static int cfq_queue_empty(struct request_queue *q)
-{
-	struct cfq_data *cfqd = q->elevator->elevator_data;
-
-	return !cfqd->rq_queued;
-}
-
 /*
  * Scale schedule slice based on io priority. Use the sync time slice only
  * if a queue is marked sync and has sync io queued. A sync queue with async
@@ -558,15 +552,13 @@
 
 static void update_min_vdisktime(struct cfq_rb_root *st)
 {
-	u64 vdisktime = st->min_vdisktime;
 	struct cfq_group *cfqg;
 
 	if (st->left) {
 		cfqg = rb_entry_cfqg(st->left);
-		vdisktime = min_vdisktime(vdisktime, cfqg->vdisktime);
+		st->min_vdisktime = max_vdisktime(st->min_vdisktime,
+						  cfqg->vdisktime);
 	}
-
-	st->min_vdisktime = max_vdisktime(st->min_vdisktime, vdisktime);
 }
 
 /*
@@ -863,7 +855,27 @@
 }
 
 static void
-cfq_group_service_tree_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
+cfq_update_group_weight(struct cfq_group *cfqg)
+{
+	BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
+	if (cfqg->needs_update) {
+		cfqg->weight = cfqg->new_weight;
+		cfqg->needs_update = false;
+	}
+}
+
+static void
+cfq_group_service_tree_add(struct cfq_rb_root *st, struct cfq_group *cfqg)
+{
+	BUG_ON(!RB_EMPTY_NODE(&cfqg->rb_node));
+
+	cfq_update_group_weight(cfqg);
+	__cfq_group_service_tree_add(st, cfqg);
+	st->total_weight += cfqg->weight;
+}
+
+static void
+cfq_group_notify_queue_add(struct cfq_data *cfqd, struct cfq_group *cfqg)
 {
 	struct cfq_rb_root *st = &cfqd->grp_service_tree;
 	struct cfq_group *__cfqg;
@@ -876,7 +888,7 @@
 	/*
 	 * Currently put the group at the end. Later implement something
 	 * so that groups get lesser vtime based on their weights, so that
-	 * if group does not loose all if it was not continously backlogged.
+	 * if group does not loose all if it was not continuously backlogged.
 	 */
 	n = rb_last(&st->rb);
 	if (n) {
@@ -884,13 +896,19 @@
 		cfqg->vdisktime = __cfqg->vdisktime + CFQ_IDLE_DELAY;
 	} else
 		cfqg->vdisktime = st->min_vdisktime;
+	cfq_group_service_tree_add(st, cfqg);
+}
 
-	__cfq_group_service_tree_add(st, cfqg);
-	st->total_weight += cfqg->weight;
+static void
+cfq_group_service_tree_del(struct cfq_rb_root *st, struct cfq_group *cfqg)
+{
+	st->total_weight -= cfqg->weight;
+	if (!RB_EMPTY_NODE(&cfqg->rb_node))
+		cfq_rb_erase(&cfqg->rb_node, st);
 }
 
 static void
-cfq_group_service_tree_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
+cfq_group_notify_queue_del(struct cfq_data *cfqd, struct cfq_group *cfqg)
 {
 	struct cfq_rb_root *st = &cfqd->grp_service_tree;
 
@@ -902,14 +920,13 @@
 		return;
 
 	cfq_log_cfqg(cfqd, cfqg, "del_from_rr group");
-	st->total_weight -= cfqg->weight;
-	if (!RB_EMPTY_NODE(&cfqg->rb_node))
-		cfq_rb_erase(&cfqg->rb_node, st);
+	cfq_group_service_tree_del(st, cfqg);
 	cfqg->saved_workload_slice = 0;
 	cfq_blkiocg_update_dequeue_stats(&cfqg->blkg, 1);
 }
 
-static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq)
+static inline unsigned int cfq_cfqq_slice_usage(struct cfq_queue *cfqq,
+						unsigned int *unaccounted_time)
 {
 	unsigned int slice_used;
 
@@ -928,8 +945,13 @@
 					1);
 	} else {
 		slice_used = jiffies - cfqq->slice_start;
-		if (slice_used > cfqq->allocated_slice)
+		if (slice_used > cfqq->allocated_slice) {
+			*unaccounted_time = slice_used - cfqq->allocated_slice;
 			slice_used = cfqq->allocated_slice;
+		}
+		if (time_after(cfqq->slice_start, cfqq->dispatch_start))
+			*unaccounted_time += cfqq->slice_start -
+					cfqq->dispatch_start;
 	}
 
 	return slice_used;
@@ -939,12 +961,12 @@
 				struct cfq_queue *cfqq)
 {
 	struct cfq_rb_root *st = &cfqd->grp_service_tree;
-	unsigned int used_sl, charge;
+	unsigned int used_sl, charge, unaccounted_sl = 0;
 	int nr_sync = cfqg->nr_cfqq - cfqg_busy_async_queues(cfqd, cfqg)
 			- cfqg->service_tree_idle.count;
 
 	BUG_ON(nr_sync < 0);
-	used_sl = charge = cfq_cfqq_slice_usage(cfqq);
+	used_sl = charge = cfq_cfqq_slice_usage(cfqq, &unaccounted_sl);
 
 	if (iops_mode(cfqd))
 		charge = cfqq->slice_dispatch;
@@ -952,9 +974,10 @@
 		charge = cfqq->allocated_slice;
 
 	/* Can't update vdisktime while group is on service tree */
-	cfq_rb_erase(&cfqg->rb_node, st);
+	cfq_group_service_tree_del(st, cfqg);
 	cfqg->vdisktime += cfq_scale_slice(charge, cfqg);
-	__cfq_group_service_tree_add(st, cfqg);
+	/* If a new weight was requested, update now, off tree */
+	cfq_group_service_tree_add(st, cfqg);
 
 	/* This group is being expired. Save the context */
 	if (time_after(cfqd->workload_expires, jiffies)) {
@@ -970,7 +993,8 @@
 	cfq_log_cfqq(cfqq->cfqd, cfqq, "sl_used=%u disp=%u charge=%u iops=%u"
 			" sect=%u", used_sl, cfqq->slice_dispatch, charge,
 			iops_mode(cfqd), cfqq->nr_sectors);
-	cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl);
+	cfq_blkiocg_update_timeslice_used(&cfqg->blkg, used_sl,
+					  unaccounted_sl);
 	cfq_blkiocg_set_start_empty_time(&cfqg->blkg);
 }
 
@@ -985,13 +1009,14 @@
 void cfq_update_blkio_group_weight(void *key, struct blkio_group *blkg,
 					unsigned int weight)
 {
-	cfqg_of_blkg(blkg)->weight = weight;
+	struct cfq_group *cfqg = cfqg_of_blkg(blkg);
+	cfqg->new_weight = weight;
+	cfqg->needs_update = true;
 }
 
-static struct cfq_group *
-cfq_find_alloc_cfqg(struct cfq_data *cfqd, struct cgroup *cgroup, int create)
+static struct cfq_group * cfq_find_alloc_cfqg(struct cfq_data *cfqd,
+		struct blkio_cgroup *blkcg, int create)
 {
-	struct blkio_cgroup *blkcg = cgroup_to_blkio_cgroup(cgroup);
 	struct cfq_group *cfqg = NULL;
 	void *key = cfqd;
 	int i, j;
@@ -1053,12 +1078,12 @@
  */
 static struct cfq_group *cfq_get_cfqg(struct cfq_data *cfqd, int create)
 {
-	struct cgroup *cgroup;
+	struct blkio_cgroup *blkcg;
 	struct cfq_group *cfqg = NULL;
 
 	rcu_read_lock();
-	cgroup = task_cgroup(current, blkio_subsys_id);
-	cfqg = cfq_find_alloc_cfqg(cfqd, cgroup, create);
+	blkcg = task_blkio_cgroup(current);
+	cfqg = cfq_find_alloc_cfqg(cfqd, blkcg, create);
 	if (!cfqg && create)
 		cfqg = &cfqd->root_group;
 	rcu_read_unlock();
@@ -1187,32 +1212,6 @@
 	int new_cfqq = 1;
 	int group_changed = 0;
 
-#ifdef CONFIG_CFQ_GROUP_IOSCHED
-	if (!cfqd->cfq_group_isolation
-	    && cfqq_type(cfqq) == SYNC_NOIDLE_WORKLOAD
-	    && cfqq->cfqg && cfqq->cfqg != &cfqd->root_group) {
-		/* Move this cfq to root group */
-		cfq_log_cfqq(cfqd, cfqq, "moving to root group");
-		if (!RB_EMPTY_NODE(&cfqq->rb_node))
-			cfq_group_service_tree_del(cfqd, cfqq->cfqg);
-		cfqq->orig_cfqg = cfqq->cfqg;
-		cfqq->cfqg = &cfqd->root_group;
-		cfqd->root_group.ref++;
-		group_changed = 1;
-	} else if (!cfqd->cfq_group_isolation
-		   && cfqq_type(cfqq) == SYNC_WORKLOAD && cfqq->orig_cfqg) {
-		/* cfqq is sequential now needs to go to its original group */
-		BUG_ON(cfqq->cfqg != &cfqd->root_group);
-		if (!RB_EMPTY_NODE(&cfqq->rb_node))
-			cfq_group_service_tree_del(cfqd, cfqq->cfqg);
-		cfq_put_cfqg(cfqq->cfqg);
-		cfqq->cfqg = cfqq->orig_cfqg;
-		cfqq->orig_cfqg = NULL;
-		group_changed = 1;
-		cfq_log_cfqq(cfqd, cfqq, "moved to origin group");
-	}
-#endif
-
 	service_tree = service_tree_for(cfqq->cfqg, cfqq_prio(cfqq),
 						cfqq_type(cfqq));
 	if (cfq_class_idle(cfqq)) {
@@ -1284,7 +1283,7 @@
 	service_tree->count++;
 	if ((add_front || !new_cfqq) && !group_changed)
 		return;
-	cfq_group_service_tree_add(cfqd, cfqq->cfqg);
+	cfq_group_notify_queue_add(cfqd, cfqq->cfqg);
 }
 
 static struct cfq_queue *
@@ -1372,6 +1371,8 @@
 	BUG_ON(cfq_cfqq_on_rr(cfqq));
 	cfq_mark_cfqq_on_rr(cfqq);
 	cfqd->busy_queues++;
+	if (cfq_cfqq_sync(cfqq))
+		cfqd->busy_sync_queues++;
 
 	cfq_resort_rr_list(cfqd, cfqq);
 }
@@ -1395,9 +1396,11 @@
 		cfqq->p_root = NULL;
 	}
 
-	cfq_group_service_tree_del(cfqd, cfqq->cfqg);
+	cfq_group_notify_queue_del(cfqd, cfqq->cfqg);
 	BUG_ON(!cfqd->busy_queues);
 	cfqd->busy_queues--;
+	if (cfq_cfqq_sync(cfqq))
+		cfqd->busy_sync_queues--;
 }
 
 /*
@@ -2405,6 +2408,7 @@
 	 * Does this cfqq already have too much IO in flight?
 	 */
 	if (cfqq->dispatched >= max_dispatch) {
+		bool promote_sync = false;
 		/*
 		 * idle queue must always only have a single IO in flight
 		 */
@@ -2412,15 +2416,26 @@
 			return false;
 
 		/*
+		 * If there is only one sync queue
+		 * we can ignore async queue here and give the sync
+		 * queue no dispatch limit. The reason is a sync queue can
+		 * preempt async queue, limiting the sync queue doesn't make
+		 * sense. This is useful for aiostress test.
+		 */
+		if (cfq_cfqq_sync(cfqq) && cfqd->busy_sync_queues == 1)
+			promote_sync = true;
+
+		/*
 		 * We have other queues, don't allow more IO from this one
 		 */
-		if (cfqd->busy_queues > 1 && cfq_slice_used_soon(cfqd, cfqq))
+		if (cfqd->busy_queues > 1 && cfq_slice_used_soon(cfqd, cfqq) &&
+				!promote_sync)
 			return false;
 
 		/*
 		 * Sole queue user, no limit
 		 */
-		if (cfqd->busy_queues == 1)
+		if (cfqd->busy_queues == 1 || promote_sync)
 			max_dispatch = -1;
 		else
 			/*
@@ -2542,7 +2557,7 @@
 static void cfq_put_queue(struct cfq_queue *cfqq)
 {
 	struct cfq_data *cfqd = cfqq->cfqd;
-	struct cfq_group *cfqg, *orig_cfqg;
+	struct cfq_group *cfqg;
 
 	BUG_ON(cfqq->ref <= 0);
 
@@ -2554,7 +2569,6 @@
 	BUG_ON(rb_first(&cfqq->sort_list));
 	BUG_ON(cfqq->allocated[READ] + cfqq->allocated[WRITE]);
 	cfqg = cfqq->cfqg;
-	orig_cfqg = cfqq->orig_cfqg;
 
 	if (unlikely(cfqd->active_queue == cfqq)) {
 		__cfq_slice_expired(cfqd, cfqq, 0);
@@ -2564,33 +2578,23 @@
 	BUG_ON(cfq_cfqq_on_rr(cfqq));
 	kmem_cache_free(cfq_pool, cfqq);
 	cfq_put_cfqg(cfqg);
-	if (orig_cfqg)
-		cfq_put_cfqg(orig_cfqg);
 }
 
 /*
- * Must always be called with the rcu_read_lock() held
+ * Call func for each cic attached to this ioc.
  */
 static void
-__call_for_each_cic(struct io_context *ioc,
-		    void (*func)(struct io_context *, struct cfq_io_context *))
+call_for_each_cic(struct io_context *ioc,
+		  void (*func)(struct io_context *, struct cfq_io_context *))
 {
 	struct cfq_io_context *cic;
 	struct hlist_node *n;
 
+	rcu_read_lock();
+
 	hlist_for_each_entry_rcu(cic, n, &ioc->cic_list, cic_list)
 		func(ioc, cic);
-}
 
-/*
- * Call func for each cic attached to this ioc.
- */
-static void
-call_for_each_cic(struct io_context *ioc,
-		  void (*func)(struct io_context *, struct cfq_io_context *))
-{
-	rcu_read_lock();
-	__call_for_each_cic(ioc, func);
 	rcu_read_unlock();
 }
 
@@ -2651,7 +2655,7 @@
 	 * should be ok to iterate over the known list, we will see all cic's
 	 * since no new ones are added.
 	 */
-	__call_for_each_cic(ioc, cic_free_func);
+	call_for_each_cic(ioc, cic_free_func);
 }
 
 static void cfq_put_cooperator(struct cfq_queue *cfqq)
@@ -3355,7 +3359,7 @@
 			    cfqd->busy_queues > 1) {
 				cfq_del_timer(cfqd, cfqq);
 				cfq_clear_cfqq_wait_request(cfqq);
-				__blk_run_queue(cfqd->queue, false);
+				__blk_run_queue(cfqd->queue);
 			} else {
 				cfq_blkiocg_update_idle_time_stats(
 						&cfqq->cfqg->blkg);
@@ -3370,7 +3374,7 @@
 		 * this new queue is RT and the current one is BE
 		 */
 		cfq_preempt_queue(cfqd, cfqq);
-		__blk_run_queue(cfqd->queue, false);
+		__blk_run_queue(cfqd->queue);
 	}
 }
 
@@ -3613,12 +3617,12 @@
 
 		put_io_context(RQ_CIC(rq)->ioc);
 
-		rq->elevator_private = NULL;
-		rq->elevator_private2 = NULL;
+		rq->elevator_private[0] = NULL;
+		rq->elevator_private[1] = NULL;
 
 		/* Put down rq reference on cfqg */
 		cfq_put_cfqg(RQ_CFQG(rq));
-		rq->elevator_private3 = NULL;
+		rq->elevator_private[2] = NULL;
 
 		cfq_put_queue(cfqq);
 	}
@@ -3705,13 +3709,12 @@
 	}
 
 	cfqq->allocated[rw]++;
-	cfqq->ref++;
-	rq->elevator_private = cic;
-	rq->elevator_private2 = cfqq;
-	rq->elevator_private3 = cfq_ref_get_cfqg(cfqq->cfqg);
 
+	cfqq->ref++;
+	rq->elevator_private[0] = cic;
+	rq->elevator_private[1] = cfqq;
+	rq->elevator_private[2] = cfq_ref_get_cfqg(cfqq->cfqg);
 	spin_unlock_irqrestore(q->queue_lock, flags);
-
 	return 0;
 
 queue_fail:
@@ -3731,7 +3734,7 @@
 	struct request_queue *q = cfqd->queue;
 
 	spin_lock_irq(q->queue_lock);
-	__blk_run_queue(cfqd->queue, false);
+	__blk_run_queue(cfqd->queue);
 	spin_unlock_irq(q->queue_lock);
 }
 
@@ -3953,7 +3956,6 @@
 	cfqd->cfq_slice_idle = cfq_slice_idle;
 	cfqd->cfq_group_idle = cfq_group_idle;
 	cfqd->cfq_latency = 1;
-	cfqd->cfq_group_isolation = 0;
 	cfqd->hw_tag = -1;
 	/*
 	 * we optimistically start assuming sync ops weren't delayed in last
@@ -4029,7 +4031,6 @@
 SHOW_FUNCTION(cfq_slice_async_show, cfqd->cfq_slice[0], 1);
 SHOW_FUNCTION(cfq_slice_async_rq_show, cfqd->cfq_slice_async_rq, 0);
 SHOW_FUNCTION(cfq_low_latency_show, cfqd->cfq_latency, 0);
-SHOW_FUNCTION(cfq_group_isolation_show, cfqd->cfq_group_isolation, 0);
 #undef SHOW_FUNCTION
 
 #define STORE_FUNCTION(__FUNC, __PTR, MIN, MAX, __CONV)			\
@@ -4063,7 +4064,6 @@
 STORE_FUNCTION(cfq_slice_async_rq_store, &cfqd->cfq_slice_async_rq, 1,
 		UINT_MAX, 0);
 STORE_FUNCTION(cfq_low_latency_store, &cfqd->cfq_latency, 0, 1, 0);
-STORE_FUNCTION(cfq_group_isolation_store, &cfqd->cfq_group_isolation, 0, 1, 0);
 #undef STORE_FUNCTION
 
 #define CFQ_ATTR(name) \
@@ -4081,7 +4081,6 @@
 	CFQ_ATTR(slice_idle),
 	CFQ_ATTR(group_idle),
 	CFQ_ATTR(low_latency),
-	CFQ_ATTR(group_isolation),
 	__ATTR_NULL
 };
 
@@ -4096,7 +4095,6 @@
 		.elevator_add_req_fn =		cfq_insert_request,
 		.elevator_activate_req_fn =	cfq_activate_request,
 		.elevator_deactivate_req_fn =	cfq_deactivate_request,
-		.elevator_queue_empty_fn =	cfq_queue_empty,
 		.elevator_completed_req_fn =	cfq_completed_request,
 		.elevator_former_req_fn =	elv_rb_former_request,
 		.elevator_latter_req_fn =	elv_rb_latter_request,
diff -druN linux-libre-2.6.38-gnu/block/deadline-iosched.c linux-libre-2.6.39-gnu/block/deadline-iosched.c
--- linux-libre-2.6.38-gnu/block/deadline-iosched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/deadline-iosched.c	2011-05-19 00:06:34.000000000 -0400
@@ -326,14 +326,6 @@
 	return 1;
 }
 
-static int deadline_queue_empty(struct request_queue *q)
-{
-	struct deadline_data *dd = q->elevator->elevator_data;
-
-	return list_empty(&dd->fifo_list[WRITE])
-		&& list_empty(&dd->fifo_list[READ]);
-}
-
 static void deadline_exit_queue(struct elevator_queue *e)
 {
 	struct deadline_data *dd = e->elevator_data;
@@ -445,7 +437,6 @@
 		.elevator_merge_req_fn =	deadline_merged_requests,
 		.elevator_dispatch_fn =		deadline_dispatch_requests,
 		.elevator_add_req_fn =		deadline_add_request,
-		.elevator_queue_empty_fn =	deadline_queue_empty,
 		.elevator_former_req_fn =	elv_rb_former_request,
 		.elevator_latter_req_fn =	elv_rb_latter_request,
 		.elevator_init_fn =		deadline_init_queue,
diff -druN linux-libre-2.6.38-gnu/block/elevator.c linux-libre-2.6.39-gnu/block/elevator.c
--- linux-libre-2.6.38-gnu/block/elevator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/elevator.c	2011-05-19 00:06:34.000000000 -0400
@@ -113,7 +113,7 @@
 }
 EXPORT_SYMBOL(elv_rq_merge_ok);
 
-static inline int elv_try_merge(struct request *__rq, struct bio *bio)
+int elv_try_merge(struct request *__rq, struct bio *bio)
 {
 	int ret = ELEVATOR_NO_MERGE;
 
@@ -421,6 +421,8 @@
 	struct list_head *entry;
 	int stop_flags;
 
+	BUG_ON(rq->cmd_flags & REQ_ON_PLUG);
+
 	if (q->last_merge == rq)
 		q->last_merge = NULL;
 
@@ -519,6 +521,40 @@
 	return ELEVATOR_NO_MERGE;
 }
 
+/*
+ * Attempt to do an insertion back merge. Only check for the case where
+ * we can append 'rq' to an existing request, so we can throw 'rq' away
+ * afterwards.
+ *
+ * Returns true if we merged, false otherwise
+ */
+static bool elv_attempt_insert_merge(struct request_queue *q,
+				     struct request *rq)
+{
+	struct request *__rq;
+
+	if (blk_queue_nomerges(q))
+		return false;
+
+	/*
+	 * First try one-hit cache.
+	 */
+	if (q->last_merge && blk_attempt_req_merge(q, q->last_merge, rq))
+		return true;
+
+	if (blk_queue_noxmerges(q))
+		return false;
+
+	/*
+	 * See if our hash lookup can find a potential backmerge.
+	 */
+	__rq = elv_rqhash_find(q, blk_rq_pos(rq));
+	if (__rq && blk_attempt_req_merge(q, __rq, rq))
+		return true;
+
+	return false;
+}
+
 void elv_merged_request(struct request_queue *q, struct request *rq, int type)
 {
 	struct elevator_queue *e = q->elevator;
@@ -536,14 +572,18 @@
 			     struct request *next)
 {
 	struct elevator_queue *e = q->elevator;
+	const int next_sorted = next->cmd_flags & REQ_SORTED;
 
-	if (e->ops->elevator_merge_req_fn)
+	if (next_sorted && e->ops->elevator_merge_req_fn)
 		e->ops->elevator_merge_req_fn(q, rq, next);
 
 	elv_rqhash_reposition(q, rq);
-	elv_rqhash_del(q, next);
 
-	q->nr_sorted--;
+	if (next_sorted) {
+		elv_rqhash_del(q, next);
+		q->nr_sorted--;
+	}
+
 	q->last_merge = rq;
 }
 
@@ -570,7 +610,7 @@
 
 	rq->cmd_flags &= ~REQ_STARTED;
 
-	elv_insert(q, rq, ELEVATOR_INSERT_REQUEUE);
+	__elv_add_request(q, rq, ELEVATOR_INSERT_REQUEUE);
 }
 
 void elv_drain_elevator(struct request_queue *q)
@@ -602,7 +642,7 @@
 	 */
 	elv_drain_elevator(q);
 	while (q->rq.elvpriv) {
-		__blk_run_queue(q, false);
+		__blk_run_queue(q);
 		spin_unlock_irq(q->queue_lock);
 		msleep(10);
 		spin_lock_irq(q->queue_lock);
@@ -615,23 +655,28 @@
 	queue_flag_clear(QUEUE_FLAG_ELVSWITCH, q);
 }
 
-void elv_insert(struct request_queue *q, struct request *rq, int where)
+void __elv_add_request(struct request_queue *q, struct request *rq, int where)
 {
-	int unplug_it = 1;
-
 	trace_block_rq_insert(q, rq);
 
 	rq->q = q;
 
+	BUG_ON(rq->cmd_flags & REQ_ON_PLUG);
+
+	if (rq->cmd_flags & REQ_SOFTBARRIER) {
+		/* barriers are scheduling boundary, update end_sector */
+		if (rq->cmd_type == REQ_TYPE_FS ||
+		    (rq->cmd_flags & REQ_DISCARD)) {
+			q->end_sector = rq_end_sector(rq);
+			q->boundary_rq = rq;
+		}
+	} else if (!(rq->cmd_flags & REQ_ELVPRIV) &&
+		    (where == ELEVATOR_INSERT_SORT ||
+		     where == ELEVATOR_INSERT_SORT_MERGE))
+		where = ELEVATOR_INSERT_BACK;
+
 	switch (where) {
 	case ELEVATOR_INSERT_REQUEUE:
-		/*
-		 * Most requeues happen because of a busy condition,
-		 * don't force unplug of the queue for that case.
-		 * Clear unplug_it and fall through.
-		 */
-		unplug_it = 0;
-
 	case ELEVATOR_INSERT_FRONT:
 		rq->cmd_flags |= REQ_SOFTBARRIER;
 		list_add(&rq->queuelist, &q->queue_head);
@@ -651,9 +696,17 @@
 		 *   with anything.  There's no point in delaying queue
 		 *   processing.
 		 */
-		__blk_run_queue(q, false);
+		__blk_run_queue(q);
 		break;
 
+	case ELEVATOR_INSERT_SORT_MERGE:
+		/*
+		 * If we succeed in merging this request with one in the
+		 * queue already, we are done - rq has now been freed,
+		 * so no need to do anything further.
+		 */
+		if (elv_attempt_insert_merge(q, rq))
+			break;
 	case ELEVATOR_INSERT_SORT:
 		BUG_ON(rq->cmd_type != REQ_TYPE_FS &&
 		       !(rq->cmd_flags & REQ_DISCARD));
@@ -673,67 +726,28 @@
 		q->elevator->ops->elevator_add_req_fn(q, rq);
 		break;
 
+	case ELEVATOR_INSERT_FLUSH:
+		rq->cmd_flags |= REQ_SOFTBARRIER;
+		blk_insert_flush(rq);
+		break;
 	default:
 		printk(KERN_ERR "%s: bad insertion point %d\n",
 		       __func__, where);
 		BUG();
 	}
-
-	if (unplug_it && blk_queue_plugged(q)) {
-		int nrq = q->rq.count[BLK_RW_SYNC] + q->rq.count[BLK_RW_ASYNC]
-				- queue_in_flight(q);
-
-		if (nrq >= q->unplug_thresh)
-			__generic_unplug_device(q);
-	}
-}
-
-void __elv_add_request(struct request_queue *q, struct request *rq, int where,
-		       int plug)
-{
-	if (rq->cmd_flags & REQ_SOFTBARRIER) {
-		/* barriers are scheduling boundary, update end_sector */
-		if (rq->cmd_type == REQ_TYPE_FS ||
-		    (rq->cmd_flags & REQ_DISCARD)) {
-			q->end_sector = rq_end_sector(rq);
-			q->boundary_rq = rq;
-		}
-	} else if (!(rq->cmd_flags & REQ_ELVPRIV) &&
-		    where == ELEVATOR_INSERT_SORT)
-		where = ELEVATOR_INSERT_BACK;
-
-	if (plug)
-		blk_plug_device(q);
-
-	elv_insert(q, rq, where);
 }
 EXPORT_SYMBOL(__elv_add_request);
 
-void elv_add_request(struct request_queue *q, struct request *rq, int where,
-		     int plug)
+void elv_add_request(struct request_queue *q, struct request *rq, int where)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(q->queue_lock, flags);
-	__elv_add_request(q, rq, where, plug);
+	__elv_add_request(q, rq, where);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 }
 EXPORT_SYMBOL(elv_add_request);
 
-int elv_queue_empty(struct request_queue *q)
-{
-	struct elevator_queue *e = q->elevator;
-
-	if (!list_empty(&q->queue_head))
-		return 0;
-
-	if (e->ops->elevator_queue_empty_fn)
-		return e->ops->elevator_queue_empty_fn(q);
-
-	return 1;
-}
-EXPORT_SYMBOL(elv_queue_empty);
-
 struct request *elv_latter_request(struct request_queue *q, struct request *rq)
 {
 	struct elevator_queue *e = q->elevator;
@@ -759,7 +773,7 @@
 	if (e->ops->elevator_set_req_fn)
 		return e->ops->elevator_set_req_fn(q, rq, gfp_mask);
 
-	rq->elevator_private = NULL;
+	rq->elevator_private[0] = NULL;
 	return 0;
 }
 
@@ -785,6 +799,8 @@
 {
 	struct request *rq;
 
+	blk_abort_flushes(q);
+
 	while (!list_empty(&q->queue_head)) {
 		rq = list_entry_rq(q->queue_head.next);
 		rq->cmd_flags |= REQ_QUIET;
diff -druN linux-libre-2.6.38-gnu/block/genhd.c linux-libre-2.6.39-gnu/block/genhd.c
--- linux-libre-2.6.38-gnu/block/genhd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/genhd.c	2011-05-19 00:06:34.000000000 -0400
@@ -739,7 +739,7 @@
 
 		/*
 		 * Don't show empty devices or things that have been
-		 * surpressed
+		 * suppressed
 		 */
 		if (get_capacity(disk) == 0 ||
 		    (disk->flags & GENHD_FL_SUPPRESS_PARTITION_INFO))
@@ -1158,14 +1158,14 @@
 			   "%u %lu %lu %llu %u %u %u %u\n",
 			   MAJOR(part_devt(hd)), MINOR(part_devt(hd)),
 			   disk_name(gp, hd->partno, buf),
-			   part_stat_read(hd, ios[0]),
-			   part_stat_read(hd, merges[0]),
-			   (unsigned long long)part_stat_read(hd, sectors[0]),
-			   jiffies_to_msecs(part_stat_read(hd, ticks[0])),
-			   part_stat_read(hd, ios[1]),
-			   part_stat_read(hd, merges[1]),
-			   (unsigned long long)part_stat_read(hd, sectors[1]),
-			   jiffies_to_msecs(part_stat_read(hd, ticks[1])),
+			   part_stat_read(hd, ios[READ]),
+			   part_stat_read(hd, merges[READ]),
+			   (unsigned long long)part_stat_read(hd, sectors[READ]),
+			   jiffies_to_msecs(part_stat_read(hd, ticks[READ])),
+			   part_stat_read(hd, ios[WRITE]),
+			   part_stat_read(hd, merges[WRITE]),
+			   (unsigned long long)part_stat_read(hd, sectors[WRITE]),
+			   jiffies_to_msecs(part_stat_read(hd, ticks[WRITE])),
 			   part_in_flight(hd),
 			   jiffies_to_msecs(part_stat_read(hd, io_ticks)),
 			   jiffies_to_msecs(part_stat_read(hd, time_in_queue))
@@ -1494,7 +1494,7 @@
 void disk_unblock_events(struct gendisk *disk)
 {
 	if (disk->ev)
-		__disk_unblock_events(disk, true);
+		__disk_unblock_events(disk, false);
 }
 
 /**
@@ -1588,9 +1588,13 @@
 
 	spin_unlock_irq(&ev->lock);
 
-	/* tell userland about new events */
+	/*
+	 * Tell userland about new events.  Only the events listed in
+	 * @disk->events are reported.  Unlisted events are processed the
+	 * same internally but never get reported to userland.
+	 */
 	for (i = 0; i < ARRAY_SIZE(disk_uevents); i++)
-		if (events & (1 << i))
+		if (events & disk->events & (1 << i))
 			envp[nr_events++] = disk_uevents[i];
 
 	if (nr_events)
diff -druN linux-libre-2.6.38-gnu/block/noop-iosched.c linux-libre-2.6.39-gnu/block/noop-iosched.c
--- linux-libre-2.6.38-gnu/block/noop-iosched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/block/noop-iosched.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,13 +39,6 @@
 	list_add_tail(&rq->queuelist, &nd->queue);
 }
 
-static int noop_queue_empty(struct request_queue *q)
-{
-	struct noop_data *nd = q->elevator->elevator_data;
-
-	return list_empty(&nd->queue);
-}
-
 static struct request *
 noop_former_request(struct request_queue *q, struct request *rq)
 {
@@ -90,7 +83,6 @@
 		.elevator_merge_req_fn		= noop_merged_requests,
 		.elevator_dispatch_fn		= noop_dispatch,
 		.elevator_add_req_fn		= noop_add_request,
-		.elevator_queue_empty_fn	= noop_queue_empty,
 		.elevator_former_req_fn		= noop_former_request,
 		.elevator_latter_req_fn		= noop_latter_request,
 		.elevator_init_fn		= noop_init_queue,
diff -druN linux-libre-2.6.38-gnu/CREDITS linux-libre-2.6.39-gnu/CREDITS
--- linux-libre-2.6.38-gnu/CREDITS	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/CREDITS	2011-05-19 00:06:34.000000000 -0400
@@ -1677,7 +1677,7 @@
 D: Assorted VIA x86 support.
 D: 2.5 AGPGART overhaul.
 D: CPUFREQ maintenance.
-D: Fedora kernel maintainence.
+D: Fedora kernel maintenance.
 D: Misc/Other.
 S: 314 Littleton Rd, Westford, MA 01886, USA
 
@@ -3211,7 +3211,7 @@
 E: jsimmons@infradead.org
 E: jsimmons@users.sf.net 
 D: Frame buffer device maintainer
-D: input layer developement 
+D: input layer development
 D: tty/console layer
 D: various mipsel devices 
 S: 115 Carmel Avenue 
@@ -3290,7 +3290,7 @@
 N: Manfred Spraul
 E: manfred@colorfullife.com
 W: http://www.colorfullife.com/~manfred
-D: Lots of tiny hacks. Larger improvments to SysV IPC msg,
+D: Lots of tiny hacks. Larger improvements to SysV IPC msg,
 D: slab, pipe, select.
 S: 71701 Schwieberdingen
 S: Germany
diff -druN linux-libre-2.6.38-gnu/crypto/ablkcipher.c linux-libre-2.6.39-gnu/crypto/ablkcipher.c
--- linux-libre-2.6.38-gnu/crypto/ablkcipher.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/ablkcipher.c	2011-05-19 00:06:34.000000000 -0400
@@ -141,8 +141,7 @@
 
 	if (walk->iv != req->info)
 		memcpy(req->info, walk->iv, tfm->crt_ablkcipher.ivsize);
-	if (walk->iv_buffer)
-		kfree(walk->iv_buffer);
+	kfree(walk->iv_buffer);
 
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/crypto/ansi_cprng.c linux-libre-2.6.39-gnu/crypto/ansi_cprng.c
--- linux-libre-2.6.38-gnu/crypto/ansi_cprng.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/ansi_cprng.c	2011-05-19 00:06:34.000000000 -0400
@@ -83,7 +83,7 @@
 }
 /*
  * Returns DEFAULT_BLK_SZ bytes of random data per call
- * returns 0 if generation succeded, <0 if something went wrong
+ * returns 0 if generation succeeded, <0 if something went wrong
  */
 static int _get_more_prng_bytes(struct prng_context *ctx, int cont_test)
 {
diff -druN linux-libre-2.6.38-gnu/crypto/async_tx/async_xor.c linux-libre-2.6.39-gnu/crypto/async_tx/async_xor.c
--- linux-libre-2.6.38-gnu/crypto/async_tx/async_xor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/async_tx/async_xor.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,7 @@
 		if (unlikely(!tx))
 			async_tx_quiesce(&submit->depend_tx);
 
-		/* spin wait for the preceeding transactions to complete */
+		/* spin wait for the preceding transactions to complete */
 		while (unlikely(!tx)) {
 			dma_async_issue_pending(chan);
 			tx = dma->device_prep_dma_xor(chan, dma_dest,
diff -druN linux-libre-2.6.38-gnu/crypto/authencesn.c linux-libre-2.6.39-gnu/crypto/authencesn.c
--- linux-libre-2.6.38-gnu/crypto/authencesn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/crypto/authencesn.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,835 @@
+/*
+ * authencesn.c - AEAD wrapper for IPsec with extended sequence numbers,
+ *                 derived from authenc.c
+ *
+ * Copyright (C) 2010 secunet Security Networks AG
+ * Copyright (C) 2010 Steffen Klassert <steffen.klassert@secunet.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/aead.h>
+#include <crypto/internal/hash.h>
+#include <crypto/internal/skcipher.h>
+#include <crypto/authenc.h>
+#include <crypto/scatterwalk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/rtnetlink.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+
+struct authenc_esn_instance_ctx {
+	struct crypto_ahash_spawn auth;
+	struct crypto_skcipher_spawn enc;
+};
+
+struct crypto_authenc_esn_ctx {
+	unsigned int reqoff;
+	struct crypto_ahash *auth;
+	struct crypto_ablkcipher *enc;
+};
+
+struct authenc_esn_request_ctx {
+	unsigned int cryptlen;
+	unsigned int headlen;
+	unsigned int trailen;
+	struct scatterlist *sg;
+	struct scatterlist hsg[2];
+	struct scatterlist tsg[1];
+	struct scatterlist cipher[2];
+	crypto_completion_t complete;
+	crypto_completion_t update_complete;
+	crypto_completion_t update_complete2;
+	char tail[];
+};
+
+static void authenc_esn_request_complete(struct aead_request *req, int err)
+{
+	if (err != -EINPROGRESS)
+		aead_request_complete(req, err);
+}
+
+static int crypto_authenc_esn_setkey(struct crypto_aead *authenc_esn, const u8 *key,
+				     unsigned int keylen)
+{
+	unsigned int authkeylen;
+	unsigned int enckeylen;
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct crypto_ahash *auth = ctx->auth;
+	struct crypto_ablkcipher *enc = ctx->enc;
+	struct rtattr *rta = (void *)key;
+	struct crypto_authenc_key_param *param;
+	int err = -EINVAL;
+
+	if (!RTA_OK(rta, keylen))
+		goto badkey;
+	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+		goto badkey;
+	if (RTA_PAYLOAD(rta) < sizeof(*param))
+		goto badkey;
+
+	param = RTA_DATA(rta);
+	enckeylen = be32_to_cpu(param->enckeylen);
+
+	key += RTA_ALIGN(rta->rta_len);
+	keylen -= RTA_ALIGN(rta->rta_len);
+
+	if (keylen < enckeylen)
+		goto badkey;
+
+	authkeylen = keylen - enckeylen;
+
+	crypto_ahash_clear_flags(auth, CRYPTO_TFM_REQ_MASK);
+	crypto_ahash_set_flags(auth, crypto_aead_get_flags(authenc_esn) &
+				     CRYPTO_TFM_REQ_MASK);
+	err = crypto_ahash_setkey(auth, key, authkeylen);
+	crypto_aead_set_flags(authenc_esn, crypto_ahash_get_flags(auth) &
+					   CRYPTO_TFM_RES_MASK);
+
+	if (err)
+		goto out;
+
+	crypto_ablkcipher_clear_flags(enc, CRYPTO_TFM_REQ_MASK);
+	crypto_ablkcipher_set_flags(enc, crypto_aead_get_flags(authenc_esn) &
+					 CRYPTO_TFM_REQ_MASK);
+	err = crypto_ablkcipher_setkey(enc, key + authkeylen, enckeylen);
+	crypto_aead_set_flags(authenc_esn, crypto_ablkcipher_get_flags(enc) &
+					   CRYPTO_TFM_RES_MASK);
+
+out:
+	return err;
+
+badkey:
+	crypto_aead_set_flags(authenc_esn, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	goto out;
+}
+
+static void authenc_esn_geniv_ahash_update_done(struct crypto_async_request *areq,
+						int err)
+{
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
+				areq_ctx->cryptlen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->update_complete2, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
+				 areq_ctx->cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+static void authenc_esn_geniv_ahash_update_done2(struct crypto_async_request *areq,
+						 int err)
+{
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
+				 areq_ctx->cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+
+static void authenc_esn_geniv_ahash_done(struct crypto_async_request *areq,
+					 int err)
+{
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+
+	if (err)
+		goto out;
+
+	scatterwalk_map_and_copy(ahreq->result, areq_ctx->sg,
+				 areq_ctx->cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+
+out:
+	aead_request_complete(req, err);
+}
+
+
+static void authenc_esn_verify_ahash_update_done(struct crypto_async_request *areq,
+						 int err)
+{
+	u8 *ihash;
+	unsigned int authsize;
+	struct ablkcipher_request *abreq;
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	unsigned int cryptlen = req->cryptlen;
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->sg, ahreq->result,
+				areq_ctx->cryptlen);
+
+	ahash_request_set_callback(ahreq,
+				   aead_request_flags(req) &
+				   CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->update_complete2, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	cryptlen -= authsize;
+	ihash = ahreq->result + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+
+	err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+	if (err)
+		goto out;
+
+	abreq = aead_request_ctx(req);
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst,
+				     cryptlen, req->iv);
+
+	err = crypto_ablkcipher_decrypt(abreq);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+static void authenc_esn_verify_ahash_update_done2(struct crypto_async_request *areq,
+						  int err)
+{
+	u8 *ihash;
+	unsigned int authsize;
+	struct ablkcipher_request *abreq;
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	unsigned int cryptlen = req->cryptlen;
+
+	if (err)
+		goto out;
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, ahreq->result,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) &
+					  CRYPTO_TFM_REQ_MAY_SLEEP,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		goto out;
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	cryptlen -= authsize;
+	ihash = ahreq->result + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+
+	err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+	if (err)
+		goto out;
+
+	abreq = aead_request_ctx(req);
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst,
+				     cryptlen, req->iv);
+
+	err = crypto_ablkcipher_decrypt(abreq);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+
+static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
+					  int err)
+{
+	u8 *ihash;
+	unsigned int authsize;
+	struct ablkcipher_request *abreq;
+	struct aead_request *req = areq->data;
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	unsigned int cryptlen = req->cryptlen;
+
+	if (err)
+		goto out;
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	cryptlen -= authsize;
+	ihash = ahreq->result + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+
+	err = memcmp(ihash, ahreq->result, authsize) ? -EBADMSG : 0;
+	if (err)
+		goto out;
+
+	abreq = aead_request_ctx(req);
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst,
+				     cryptlen, req->iv);
+
+	err = crypto_ablkcipher_decrypt(abreq);
+
+out:
+	authenc_esn_request_complete(req, err);
+}
+
+static u8 *crypto_authenc_esn_ahash(struct aead_request *req,
+				    unsigned int flags)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct crypto_ahash *auth = ctx->auth;
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct ahash_request *ahreq = (void *)(areq_ctx->tail + ctx->reqoff);
+	u8 *hash = areq_ctx->tail;
+	int err;
+
+	hash = (u8 *)ALIGN((unsigned long)hash + crypto_ahash_alignmask(auth),
+			    crypto_ahash_alignmask(auth) + 1);
+
+	ahash_request_set_tfm(ahreq, auth);
+
+	err = crypto_ahash_init(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	ahash_request_set_crypt(ahreq, areq_ctx->hsg, hash, areq_ctx->headlen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
+				   areq_ctx->update_complete, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	ahash_request_set_crypt(ahreq, areq_ctx->sg, hash, areq_ctx->cryptlen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
+				   areq_ctx->update_complete2, req);
+
+	err = crypto_ahash_update(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	ahash_request_set_crypt(ahreq, areq_ctx->tsg, hash,
+				areq_ctx->trailen);
+	ahash_request_set_callback(ahreq, aead_request_flags(req) & flags,
+				   areq_ctx->complete, req);
+
+	err = crypto_ahash_finup(ahreq);
+	if (err)
+		return ERR_PTR(err);
+
+	return hash;
+}
+
+static int crypto_authenc_esn_genicv(struct aead_request *req, u8 *iv,
+				     unsigned int flags)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct scatterlist *dst = req->dst;
+	struct scatterlist *assoc = req->assoc;
+	struct scatterlist *cipher = areq_ctx->cipher;
+	struct scatterlist *hsg = areq_ctx->hsg;
+	struct scatterlist *tsg = areq_ctx->tsg;
+	struct scatterlist *assoc1;
+	struct scatterlist *assoc2;
+	unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
+	unsigned int cryptlen = req->cryptlen;
+	struct page *dstp;
+	u8 *vdst;
+	u8 *hash;
+
+	dstp = sg_page(dst);
+	vdst = PageHighMem(dstp) ? NULL : page_address(dstp) + dst->offset;
+
+	if (ivsize) {
+		sg_init_table(cipher, 2);
+		sg_set_buf(cipher, iv, ivsize);
+		scatterwalk_crypto_chain(cipher, dst, vdst == iv + ivsize, 2);
+		dst = cipher;
+		cryptlen += ivsize;
+	}
+
+	if (sg_is_last(assoc))
+		return -EINVAL;
+
+	assoc1 = assoc + 1;
+	if (sg_is_last(assoc1))
+		return -EINVAL;
+
+	assoc2 = assoc + 2;
+	if (!sg_is_last(assoc2))
+		return -EINVAL;
+
+	sg_init_table(hsg, 2);
+	sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
+	sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+
+	sg_init_table(tsg, 1);
+	sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+
+	areq_ctx->cryptlen = cryptlen;
+	areq_ctx->headlen = assoc->length + assoc2->length;
+	areq_ctx->trailen = assoc1->length;
+	areq_ctx->sg = dst;
+
+	areq_ctx->complete = authenc_esn_geniv_ahash_done;
+	areq_ctx->update_complete = authenc_esn_geniv_ahash_update_done;
+	areq_ctx->update_complete2 = authenc_esn_geniv_ahash_update_done2;
+
+	hash = crypto_authenc_esn_ahash(req, flags);
+	if (IS_ERR(hash))
+		return PTR_ERR(hash);
+
+	scatterwalk_map_and_copy(hash, dst, cryptlen,
+				 crypto_aead_authsize(authenc_esn), 1);
+	return 0;
+}
+
+
+static void crypto_authenc_esn_encrypt_done(struct crypto_async_request *req,
+					    int err)
+{
+	struct aead_request *areq = req->data;
+
+	if (!err) {
+		struct crypto_aead *authenc_esn = crypto_aead_reqtfm(areq);
+		struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+		struct ablkcipher_request *abreq = aead_request_ctx(areq);
+		u8 *iv = (u8 *)(abreq + 1) +
+			 crypto_ablkcipher_reqsize(ctx->enc);
+
+		err = crypto_authenc_esn_genicv(areq, iv, 0);
+	}
+
+	authenc_esn_request_complete(areq, err);
+}
+
+static int crypto_authenc_esn_encrypt(struct aead_request *req)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct crypto_ablkcipher *enc = ctx->enc;
+	struct scatterlist *dst = req->dst;
+	unsigned int cryptlen = req->cryptlen;
+	struct ablkcipher_request *abreq = (void *)(areq_ctx->tail
+						    + ctx->reqoff);
+	u8 *iv = (u8 *)abreq - crypto_ablkcipher_ivsize(enc);
+	int err;
+
+	ablkcipher_request_set_tfm(abreq, enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					crypto_authenc_esn_encrypt_done, req);
+	ablkcipher_request_set_crypt(abreq, req->src, dst, cryptlen, req->iv);
+
+	memcpy(iv, req->iv, crypto_aead_ivsize(authenc_esn));
+
+	err = crypto_ablkcipher_encrypt(abreq);
+	if (err)
+		return err;
+
+	return crypto_authenc_esn_genicv(req, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+}
+
+static void crypto_authenc_esn_givencrypt_done(struct crypto_async_request *req,
+					       int err)
+{
+	struct aead_request *areq = req->data;
+
+	if (!err) {
+		struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
+
+		err = crypto_authenc_esn_genicv(areq, greq->giv, 0);
+	}
+
+	authenc_esn_request_complete(areq, err);
+}
+
+static int crypto_authenc_esn_givencrypt(struct aead_givcrypt_request *req)
+{
+	struct crypto_aead *authenc_esn = aead_givcrypt_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct aead_request *areq = &req->areq;
+	struct skcipher_givcrypt_request *greq = aead_request_ctx(areq);
+	u8 *iv = req->giv;
+	int err;
+
+	skcipher_givcrypt_set_tfm(greq, ctx->enc);
+	skcipher_givcrypt_set_callback(greq, aead_request_flags(areq),
+				       crypto_authenc_esn_givencrypt_done, areq);
+	skcipher_givcrypt_set_crypt(greq, areq->src, areq->dst, areq->cryptlen,
+				    areq->iv);
+	skcipher_givcrypt_set_giv(greq, iv, req->seq);
+
+	err = crypto_skcipher_givencrypt(greq);
+	if (err)
+		return err;
+
+	return crypto_authenc_esn_genicv(areq, iv, CRYPTO_TFM_REQ_MAY_SLEEP);
+}
+
+static int crypto_authenc_esn_verify(struct aead_request *req)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	u8 *ohash;
+	u8 *ihash;
+	unsigned int authsize;
+
+	areq_ctx->complete = authenc_esn_verify_ahash_done;
+	areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
+
+	ohash = crypto_authenc_esn_ahash(req, CRYPTO_TFM_REQ_MAY_SLEEP);
+	if (IS_ERR(ohash))
+		return PTR_ERR(ohash);
+
+	authsize = crypto_aead_authsize(authenc_esn);
+	ihash = ohash + authsize;
+	scatterwalk_map_and_copy(ihash, areq_ctx->sg, areq_ctx->cryptlen,
+				 authsize, 0);
+	return memcmp(ihash, ohash, authsize) ? -EBADMSG : 0;
+}
+
+static int crypto_authenc_esn_iverify(struct aead_request *req, u8 *iv,
+				      unsigned int cryptlen)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct authenc_esn_request_ctx *areq_ctx = aead_request_ctx(req);
+	struct scatterlist *src = req->src;
+	struct scatterlist *assoc = req->assoc;
+	struct scatterlist *cipher = areq_ctx->cipher;
+	struct scatterlist *hsg = areq_ctx->hsg;
+	struct scatterlist *tsg = areq_ctx->tsg;
+	struct scatterlist *assoc1;
+	struct scatterlist *assoc2;
+	unsigned int ivsize = crypto_aead_ivsize(authenc_esn);
+	struct page *srcp;
+	u8 *vsrc;
+
+	srcp = sg_page(src);
+	vsrc = PageHighMem(srcp) ? NULL : page_address(srcp) + src->offset;
+
+	if (ivsize) {
+		sg_init_table(cipher, 2);
+		sg_set_buf(cipher, iv, ivsize);
+		scatterwalk_crypto_chain(cipher, src, vsrc == iv + ivsize, 2);
+		src = cipher;
+		cryptlen += ivsize;
+	}
+
+	if (sg_is_last(assoc))
+		return -EINVAL;
+
+	assoc1 = assoc + 1;
+	if (sg_is_last(assoc1))
+		return -EINVAL;
+
+	assoc2 = assoc + 2;
+	if (!sg_is_last(assoc2))
+		return -EINVAL;
+
+	sg_init_table(hsg, 2);
+	sg_set_page(hsg, sg_page(assoc), assoc->length, assoc->offset);
+	sg_set_page(hsg + 1, sg_page(assoc2), assoc2->length, assoc2->offset);
+
+	sg_init_table(tsg, 1);
+	sg_set_page(tsg, sg_page(assoc1), assoc1->length, assoc1->offset);
+
+	areq_ctx->cryptlen = cryptlen;
+	areq_ctx->headlen = assoc->length + assoc2->length;
+	areq_ctx->trailen = assoc1->length;
+	areq_ctx->sg = src;
+
+	areq_ctx->complete = authenc_esn_verify_ahash_done;
+	areq_ctx->update_complete = authenc_esn_verify_ahash_update_done;
+	areq_ctx->update_complete2 = authenc_esn_verify_ahash_update_done2;
+
+	return crypto_authenc_esn_verify(req);
+}
+
+static int crypto_authenc_esn_decrypt(struct aead_request *req)
+{
+	struct crypto_aead *authenc_esn = crypto_aead_reqtfm(req);
+	struct crypto_authenc_esn_ctx *ctx = crypto_aead_ctx(authenc_esn);
+	struct ablkcipher_request *abreq = aead_request_ctx(req);
+	unsigned int cryptlen = req->cryptlen;
+	unsigned int authsize = crypto_aead_authsize(authenc_esn);
+	u8 *iv = req->iv;
+	int err;
+
+	if (cryptlen < authsize)
+		return -EINVAL;
+	cryptlen -= authsize;
+
+	err = crypto_authenc_esn_iverify(req, iv, cryptlen);
+	if (err)
+		return err;
+
+	ablkcipher_request_set_tfm(abreq, ctx->enc);
+	ablkcipher_request_set_callback(abreq, aead_request_flags(req),
+					req->base.complete, req->base.data);
+	ablkcipher_request_set_crypt(abreq, req->src, req->dst, cryptlen, iv);
+
+	return crypto_ablkcipher_decrypt(abreq);
+}
+
+static int crypto_authenc_esn_init_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_instance *inst = crypto_tfm_alg_instance(tfm);
+	struct authenc_esn_instance_ctx *ictx = crypto_instance_ctx(inst);
+	struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_ahash *auth;
+	struct crypto_ablkcipher *enc;
+	int err;
+
+	auth = crypto_spawn_ahash(&ictx->auth);
+	if (IS_ERR(auth))
+		return PTR_ERR(auth);
+
+	enc = crypto_spawn_skcipher(&ictx->enc);
+	err = PTR_ERR(enc);
+	if (IS_ERR(enc))
+		goto err_free_ahash;
+
+	ctx->auth = auth;
+	ctx->enc = enc;
+
+	ctx->reqoff = ALIGN(2 * crypto_ahash_digestsize(auth) +
+			    crypto_ahash_alignmask(auth),
+			    crypto_ahash_alignmask(auth) + 1) +
+		      crypto_ablkcipher_ivsize(enc);
+
+	tfm->crt_aead.reqsize = sizeof(struct authenc_esn_request_ctx) +
+				ctx->reqoff +
+				max_t(unsigned int,
+				crypto_ahash_reqsize(auth) +
+				sizeof(struct ahash_request),
+				sizeof(struct skcipher_givcrypt_request) +
+				crypto_ablkcipher_reqsize(enc));
+
+	return 0;
+
+err_free_ahash:
+	crypto_free_ahash(auth);
+	return err;
+}
+
+static void crypto_authenc_esn_exit_tfm(struct crypto_tfm *tfm)
+{
+	struct crypto_authenc_esn_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	crypto_free_ahash(ctx->auth);
+	crypto_free_ablkcipher(ctx->enc);
+}
+
+static struct crypto_instance *crypto_authenc_esn_alloc(struct rtattr **tb)
+{
+	struct crypto_attr_type *algt;
+	struct crypto_instance *inst;
+	struct hash_alg_common *auth;
+	struct crypto_alg *auth_base;
+	struct crypto_alg *enc;
+	struct authenc_esn_instance_ctx *ctx;
+	const char *enc_name;
+	int err;
+
+	algt = crypto_get_attr_type(tb);
+	err = PTR_ERR(algt);
+	if (IS_ERR(algt))
+		return ERR_PTR(err);
+
+	if ((algt->type ^ CRYPTO_ALG_TYPE_AEAD) & algt->mask)
+		return ERR_PTR(-EINVAL);
+
+	auth = ahash_attr_alg(tb[1], CRYPTO_ALG_TYPE_HASH,
+			       CRYPTO_ALG_TYPE_AHASH_MASK);
+	if (IS_ERR(auth))
+		return ERR_CAST(auth);
+
+	auth_base = &auth->base;
+
+	enc_name = crypto_attr_alg_name(tb[2]);
+	err = PTR_ERR(enc_name);
+	if (IS_ERR(enc_name))
+		goto out_put_auth;
+
+	inst = kzalloc(sizeof(*inst) + sizeof(*ctx), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!inst)
+		goto out_put_auth;
+
+	ctx = crypto_instance_ctx(inst);
+
+	err = crypto_init_ahash_spawn(&ctx->auth, auth, inst);
+	if (err)
+		goto err_free_inst;
+
+	crypto_set_skcipher_spawn(&ctx->enc, inst);
+	err = crypto_grab_skcipher(&ctx->enc, enc_name, 0,
+				   crypto_requires_sync(algt->type,
+							algt->mask));
+	if (err)
+		goto err_drop_auth;
+
+	enc = crypto_skcipher_spawn_alg(&ctx->enc);
+
+	err = -ENAMETOOLONG;
+	if (snprintf(inst->alg.cra_name, CRYPTO_MAX_ALG_NAME,
+		     "authencesn(%s,%s)", auth_base->cra_name, enc->cra_name) >=
+	    CRYPTO_MAX_ALG_NAME)
+		goto err_drop_enc;
+
+	if (snprintf(inst->alg.cra_driver_name, CRYPTO_MAX_ALG_NAME,
+		     "authencesn(%s,%s)", auth_base->cra_driver_name,
+		     enc->cra_driver_name) >= CRYPTO_MAX_ALG_NAME)
+		goto err_drop_enc;
+
+	inst->alg.cra_flags = CRYPTO_ALG_TYPE_AEAD;
+	inst->alg.cra_flags |= enc->cra_flags & CRYPTO_ALG_ASYNC;
+	inst->alg.cra_priority = enc->cra_priority *
+				 10 + auth_base->cra_priority;
+	inst->alg.cra_blocksize = enc->cra_blocksize;
+	inst->alg.cra_alignmask = auth_base->cra_alignmask | enc->cra_alignmask;
+	inst->alg.cra_type = &crypto_aead_type;
+
+	inst->alg.cra_aead.ivsize = enc->cra_ablkcipher.ivsize;
+	inst->alg.cra_aead.maxauthsize = auth->digestsize;
+
+	inst->alg.cra_ctxsize = sizeof(struct crypto_authenc_esn_ctx);
+
+	inst->alg.cra_init = crypto_authenc_esn_init_tfm;
+	inst->alg.cra_exit = crypto_authenc_esn_exit_tfm;
+
+	inst->alg.cra_aead.setkey = crypto_authenc_esn_setkey;
+	inst->alg.cra_aead.encrypt = crypto_authenc_esn_encrypt;
+	inst->alg.cra_aead.decrypt = crypto_authenc_esn_decrypt;
+	inst->alg.cra_aead.givencrypt = crypto_authenc_esn_givencrypt;
+
+out:
+	crypto_mod_put(auth_base);
+	return inst;
+
+err_drop_enc:
+	crypto_drop_skcipher(&ctx->enc);
+err_drop_auth:
+	crypto_drop_ahash(&ctx->auth);
+err_free_inst:
+	kfree(inst);
+out_put_auth:
+	inst = ERR_PTR(err);
+	goto out;
+}
+
+static void crypto_authenc_esn_free(struct crypto_instance *inst)
+{
+	struct authenc_esn_instance_ctx *ctx = crypto_instance_ctx(inst);
+
+	crypto_drop_skcipher(&ctx->enc);
+	crypto_drop_ahash(&ctx->auth);
+	kfree(inst);
+}
+
+static struct crypto_template crypto_authenc_esn_tmpl = {
+	.name = "authencesn",
+	.alloc = crypto_authenc_esn_alloc,
+	.free = crypto_authenc_esn_free,
+	.module = THIS_MODULE,
+};
+
+static int __init crypto_authenc_esn_module_init(void)
+{
+	return crypto_register_template(&crypto_authenc_esn_tmpl);
+}
+
+static void __exit crypto_authenc_esn_module_exit(void)
+{
+	crypto_unregister_template(&crypto_authenc_esn_tmpl);
+}
+
+module_init(crypto_authenc_esn_module_init);
+module_exit(crypto_authenc_esn_module_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
+MODULE_DESCRIPTION("AEAD wrapper for IPsec with extended sequence numbers");
diff -druN linux-libre-2.6.38-gnu/crypto/deflate.c linux-libre-2.6.39-gnu/crypto/deflate.c
--- linux-libre-2.6.38-gnu/crypto/deflate.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/deflate.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,8 @@
 	int ret = 0;
 	struct z_stream_s *stream = &ctx->comp_stream;
 
-	stream->workspace = vzalloc(zlib_deflate_workspacesize());
+	stream->workspace = vzalloc(zlib_deflate_workspacesize(
+				-DEFLATE_DEF_WINBITS, DEFLATE_DEF_MEMLEVEL));
 	if (!stream->workspace) {
 		ret = -ENOMEM;
 		goto out;
diff -druN linux-libre-2.6.38-gnu/crypto/gf128mul.c linux-libre-2.6.39-gnu/crypto/gf128mul.c
--- linux-libre-2.6.38-gnu/crypto/gf128mul.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/gf128mul.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,7 +89,7 @@
 }
 
 /*	Given the value i in 0..255 as the byte overflow when a field element
-    in GHASH is multipled by x^8, this function will return the values that
+    in GHASH is multiplied by x^8, this function will return the values that
     are generated in the lo 16-bit word of the field value by applying the
     modular polynomial. The values lo_byte and hi_byte are returned via the
     macro xp_fun(lo_byte, hi_byte) so that the values can be assembled into
diff -druN linux-libre-2.6.38-gnu/crypto/Makefile linux-libre-2.6.39-gnu/crypto/Makefile
--- linux-libre-2.6.38-gnu/crypto/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
 obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o
 obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
 obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
-obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
+obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o authencesn.o
 obj-$(CONFIG_CRYPTO_LZO) += lzo.o
 obj-$(CONFIG_CRYPTO_RNG2) += rng.o
 obj-$(CONFIG_CRYPTO_RNG2) += krng.o
diff -druN linux-libre-2.6.38-gnu/crypto/tcrypt.c linux-libre-2.6.39-gnu/crypto/tcrypt.c
--- linux-libre-2.6.38-gnu/crypto/tcrypt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/tcrypt.c	2011-05-19 00:06:34.000000000 -0400
@@ -146,7 +146,8 @@
 			      unsigned int tcount, u8 *keysize)
 {
 	unsigned int ret, i, j, iv_len;
-	const char *key, iv[128];
+	const char *key;
+	char iv[128];
 	struct crypto_blkcipher *tfm;
 	struct blkcipher_desc desc;
 	const char *e;
diff -druN linux-libre-2.6.38-gnu/crypto/testmgr.c linux-libre-2.6.39-gnu/crypto/testmgr.c
--- linux-libre-2.6.38-gnu/crypto/testmgr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/testmgr.c	2011-05-19 00:06:34.000000000 -0400
@@ -2077,6 +2077,7 @@
 	}, {
 		.alg = "ghash",
 		.test = alg_test_hash,
+		.fips_allowed = 1,
 		.suite = {
 			.hash = {
 				.vecs = ghash_tv_template,
@@ -2453,6 +2454,7 @@
 	}, {
 		.alg = "xts(aes)",
 		.test = alg_test_skcipher,
+		.fips_allowed = 1,
 		.suite = {
 			.cipher = {
 				.enc = {
diff -druN linux-libre-2.6.38-gnu/crypto/testmgr.h linux-libre-2.6.39-gnu/crypto/testmgr.h
--- linux-libre-2.6.38-gnu/crypto/testmgr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/testmgr.h	2011-05-19 00:06:34.000000000 -0400
@@ -451,8 +451,9 @@
 
 /*
  * SHA1 test vectors  from from FIPS PUB 180-1
+ * Long vector from CAVS 5.0
  */
-#define SHA1_TEST_VECTORS	2
+#define SHA1_TEST_VECTORS	3
 
 static struct hash_testvec sha1_tv_template[] = {
 	{
@@ -467,6 +468,33 @@
 			  "\x4a\xa1\xf9\x51\x29\xe5\xe5\x46\x70\xf1",
 		.np	= 2,
 		.tap	= { 28, 28 }
+	}, {
+		.plaintext = "\xec\x29\x56\x12\x44\xed\xe7\x06"
+			     "\xb6\xeb\x30\xa1\xc3\x71\xd7\x44"
+			     "\x50\xa1\x05\xc3\xf9\x73\x5f\x7f"
+			     "\xa9\xfe\x38\xcf\x67\xf3\x04\xa5"
+			     "\x73\x6a\x10\x6e\x92\xe1\x71\x39"
+			     "\xa6\x81\x3b\x1c\x81\xa4\xf3\xd3"
+			     "\xfb\x95\x46\xab\x42\x96\xfa\x9f"
+			     "\x72\x28\x26\xc0\x66\x86\x9e\xda"
+			     "\xcd\x73\xb2\x54\x80\x35\x18\x58"
+			     "\x13\xe2\x26\x34\xa9\xda\x44\x00"
+			     "\x0d\x95\xa2\x81\xff\x9f\x26\x4e"
+			     "\xcc\xe0\xa9\x31\x22\x21\x62\xd0"
+			     "\x21\xcc\xa2\x8d\xb5\xf3\xc2\xaa"
+			     "\x24\x94\x5a\xb1\xe3\x1c\xb4\x13"
+			     "\xae\x29\x81\x0f\xd7\x94\xca\xd5"
+			     "\xdf\xaf\x29\xec\x43\xcb\x38\xd1"
+			     "\x98\xfe\x4a\xe1\xda\x23\x59\x78"
+			     "\x02\x21\x40\x5b\xd6\x71\x2a\x53"
+			     "\x05\xda\x4b\x1b\x73\x7f\xce\x7c"
+			     "\xd2\x1c\x0e\xb7\x72\x8d\x08\x23"
+			     "\x5a\x90\x11",
+		.psize	= 163,
+		.digest	= "\x97\x01\x11\xc4\xe7\x7b\xcc\x88\xcc\x20"
+			  "\x45\x9c\x02\xb6\x9b\x4a\xa8\xf5\x82\x17",
+		.np	= 4,
+		.tap	= { 63, 64, 31, 5 }
 	}
 };
 
diff -druN linux-libre-2.6.38-gnu/crypto/vmac.c linux-libre-2.6.39-gnu/crypto/vmac.c
--- linux-libre-2.6.38-gnu/crypto/vmac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/vmac.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 
 /*
  * For highest performance the L1 NH and L2 polynomial hashes should be
- * carefully implemented to take advantage of one's target architechture.
+ * carefully implemented to take advantage of one's target architecture.
  * Here these two hash functions are defined multiple time; once for
  * 64-bit architectures, once for 32-bit SSE2 architectures, and once
  * for the rest (32-bit) architectures.
diff -druN linux-libre-2.6.38-gnu/crypto/xts.c linux-libre-2.6.39-gnu/crypto/xts.c
--- linux-libre-2.6.38-gnu/crypto/xts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/xts.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 		return -EINVAL;
 	}
 
-	/* we need two cipher instances: one to compute the inital 'tweak'
+	/* we need two cipher instances: one to compute the initial 'tweak'
 	 * by encrypting the IV (usually the 'plain' iv) and the other
 	 * one to encrypt and decrypt the data */
 
diff -druN linux-libre-2.6.38-gnu/crypto/zlib.c linux-libre-2.6.39-gnu/crypto/zlib.c
--- linux-libre-2.6.38-gnu/crypto/zlib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/crypto/zlib.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 	struct zlib_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
 	struct z_stream_s *stream = &ctx->comp_stream;
 	struct nlattr *tb[ZLIB_COMP_MAX + 1];
+	int window_bits, mem_level;
 	size_t workspacesize;
 	int ret;
 
@@ -94,7 +95,14 @@
 
 	zlib_comp_exit(ctx);
 
-	workspacesize = zlib_deflate_workspacesize();
+	window_bits = tb[ZLIB_COMP_WINDOWBITS]
+					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
+					: MAX_WBITS;
+	mem_level = tb[ZLIB_COMP_MEMLEVEL]
+					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
+					: DEF_MEM_LEVEL;
+
+	workspacesize = zlib_deflate_workspacesize(window_bits, mem_level);
 	stream->workspace = vzalloc(workspacesize);
 	if (!stream->workspace)
 		return -ENOMEM;
@@ -106,12 +114,8 @@
 				tb[ZLIB_COMP_METHOD]
 					? nla_get_u32(tb[ZLIB_COMP_METHOD])
 					: Z_DEFLATED,
-				tb[ZLIB_COMP_WINDOWBITS]
-					? nla_get_u32(tb[ZLIB_COMP_WINDOWBITS])
-					: MAX_WBITS,
-				tb[ZLIB_COMP_MEMLEVEL]
-					? nla_get_u32(tb[ZLIB_COMP_MEMLEVEL])
-					: DEF_MEM_LEVEL,
+				window_bits,
+				mem_level,
 				tb[ZLIB_COMP_STRATEGY]
 					? nla_get_u32(tb[ZLIB_COMP_STRATEGY])
 					: Z_DEFAULT_STRATEGY);
diff -druN linux-libre-2.6.38-gnu/Documentation/00-INDEX linux-libre-2.6.39-gnu/Documentation/00-INDEX
--- linux-libre-2.6.38-gnu/Documentation/00-INDEX	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/00-INDEX	2011-05-19 00:06:34.000000000 -0400
@@ -206,8 +206,8 @@
 	- directory with laptop related info and laptop driver documentation.
 ldm.txt
 	- a brief description of LDM (Windows Dynamic Disks).
-leds-class.txt
-	- documents LED handling under Linux.
+leds/
+	- directory with info about LED handling under Linux.
 local_ops.txt
 	- semantics and behavior of local atomic operations.
 lockdep-design.txt
@@ -328,8 +328,6 @@
 	- info on the magic SysRq key.
 telephony/
 	- directory with info on telephony (e.g. voice over IP) support.
-time_interpolators.txt
-	- info on time interpolators.
 uml/
 	- directory with information about User Mode Linux.
 unicode.txt
@@ -346,8 +344,6 @@
 	- directory with info on the Linux vm code.
 volatile-considered-harmful.txt
 	- Why the "volatile" type class should not be used
-voyager.txt
-	- guide to running Linux on the Voyager architecture.
 w1/
 	- directory with documents regarding the 1-wire (w1) subsystem.
 watchdog/
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/stable/sysfs-class-backlight linux-libre-2.6.39-gnu/Documentation/ABI/stable/sysfs-class-backlight
--- linux-libre-2.6.38-gnu/Documentation/ABI/stable/sysfs-class-backlight	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/stable/sysfs-class-backlight	2011-05-19 00:06:34.000000000 -0400
@@ -34,3 +34,23 @@
 Description:
 		Maximum brightness for <backlight>.
 Users:		HAL
+
+What:		/sys/class/backlight/<backlight>/type
+Date:		September 2010
+KernelVersion:	2.6.37
+Contact:	Matthew Garrett <mjg@redhat.com>
+Description:
+		The type of interface controlled by <backlight>.
+		"firmware": The driver uses a standard firmware interface
+		"platform": The driver uses a platform-specific interface
+		"raw": The driver controls hardware registers directly
+
+		In the general case, when multiple backlight
+		interfaces are available for a single device, firmware
+		control should be preferred to platform control should
+		be preferred to raw control. Using a firmware
+		interface reduces the probability of confusion with
+		the hardware and the OS independently updating the
+		backlight state. Platform interfaces are mostly a
+		holdover from pre-standardisation of firmware
+		interfaces.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/stable/sysfs-firmware-efi-vars linux-libre-2.6.39-gnu/Documentation/ABI/stable/sysfs-firmware-efi-vars
--- linux-libre-2.6.38-gnu/Documentation/ABI/stable/sysfs-firmware-efi-vars	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/stable/sysfs-firmware-efi-vars	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,75 @@
+What:		/sys/firmware/efi/vars
+Date:		April 2004
+Contact:	Matt Domsch <Matt_Domsch@dell.com>
+Description:
+		This directory exposes interfaces for interactive with
+		EFI variables.  For more information on EFI variables,
+		see 'Variable Services' in the UEFI specification
+		(section 7.2 in specification version 2.3 Errata D).
+
+		In summary, EFI variables are named, and are classified
+		into separate namespaces through the use of a vendor
+		GUID.  They also have an arbitrary binary value
+		associated with them.
+
+		The efivars module enumerates these variables and
+		creates a separate directory for each one found.  Each
+		directory has a name of the form "<key>-<vendor guid>"
+		and contains the following files:
+
+		attributes:	A read-only text file enumerating the
+				EFI variable flags.  Potential values
+				include:
+
+				EFI_VARIABLE_NON_VOLATILE
+				EFI_VARIABLE_BOOTSERVICE_ACCESS
+				EFI_VARIABLE_RUNTIME_ACCESS
+				EFI_VARIABLE_HARDWARE_ERROR_RECORD
+				EFI_VARIABLE_AUTHENTICATED_WRITE_ACCESS
+
+				See the EFI documentation for an
+				explanation of each of these variables.
+
+		data:		A read-only binary file that can be read
+				to attain the value of the EFI variable
+
+		guid:		The vendor GUID of the variable.  This
+				should always match the GUID in the
+				variable's name.
+
+		raw_var:	A binary file that can be read to obtain
+				a structure that contains everything
+				there is to know about the variable.
+				For structure definition see "struct
+				efi_variable" in the kernel sources.
+
+				This file can also be written to in
+				order to update the value of a variable.
+				For this to work however, all fields of
+				the "struct efi_variable" passed must
+				match byte for byte with the structure
+				read out of the file, save for the value
+				portion.
+
+				**Note** the efi_variable structure
+				read/written with this file contains a
+				'long' type that may change widths
+				depending on your underlying
+				architecture.
+
+		size:		As ASCII representation of the size of
+				the variable's value.
+
+
+		In addition, two other magic binary files are provided
+		in the top-level directory and are used for adding and
+		removing variables:
+
+		new_var:	Takes a "struct efi_variable" and
+				instructs the EFI firmware to create a
+				new variable.
+
+		del_var:	Takes a "struct efi_variable" and
+				instructs the EFI firmware to remove any
+				variable that has a matching vendor GUID
+				and variable key name.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/configfs-spear-pcie-gadget linux-libre-2.6.39-gnu/Documentation/ABI/testing/configfs-spear-pcie-gadget
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/configfs-spear-pcie-gadget	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/configfs-spear-pcie-gadget	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+What:		/config/pcie-gadget
+Date:		Feb 2011
+KernelVersion:	2.6.37
+Contact:	Pratyush Anand <pratyush.anand@st.com>
+Description:
+
+	Interface is used to configure selected dual mode PCIe controller
+	as device and then program its various registers to configure it
+	as a particular device type.
+	This interfaces can be used to show spear's PCIe device capability.
+
+	Nodes are only visible when configfs is mounted. To mount configfs
+	in /config directory use:
+	# mount -t configfs none /config/
+
+	For nth PCIe Device Controller
+	/config/pcie-gadget.n/
+		link ... used to enable ltssm and read its status.
+		int_type ...used to configure and read type of supported
+			interrupt
+		no_of_msi ... used to configure number of MSI vector needed and
+			to read no of MSI granted.
+		inta ... write 1 to assert INTA and 0 to de-assert.
+		send_msi ... write MSI vector to be sent.
+		vendor_id ... used to write and read vendor id (hex)
+		device_id ... used to write and read device id (hex)
+		bar0_size ... used to write and read bar0_size
+		bar0_address ... used to write and read bar0 mapped area in hex.
+		bar0_rw_offset ... used to write and read offset of bar0 where
+			bar0_data will be written or read.
+		bar0_data ... used to write and read data at bar0_rw_offset.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/pstore linux-libre-2.6.39-gnu/Documentation/ABI/testing/pstore
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/pstore	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/pstore	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,41 @@
+Where:		/dev/pstore/...
+Date:		March 2011
+Kernel Version: 2.6.39
+Contact:	tony.luck@intel.com
+Description:	Generic interface to platform dependent persistent storage.
+
+		Platforms that provide a mechanism to preserve some data
+		across system reboots can register with this driver to
+		provide a generic interface to show records captured in
+		the dying moments.  In the case of a panic the last part
+		of the console log is captured, but other interesting
+		data can also be saved.
+
+		# mount -t pstore -o kmsg_bytes=8000 - /dev/pstore
+
+		$ ls -l /dev/pstore
+		total 0
+		-r--r--r-- 1 root root 7896 Nov 30 15:38 dmesg-erst-1
+
+		Different users of this interface will result in different
+		filename prefixes.  Currently two are defined:
+
+		"dmesg"	- saved console log
+		"mce"	- architecture dependent data from fatal h/w error
+
+		Once the information in a file has been read, removing
+		the file will signal to the underlying persistent storage
+		device that it can reclaim the space for later re-use.
+
+		$ rm /dev/pstore/dmesg-erst-1
+
+		The expectation is that all files in /dev/pstore
+		will be saved elsewhere and erased from persistent store
+		soon after boot to free up space ready for the next
+		catastrophe.
+
+		The 'kmsg_bytes' mount option changes the target amount of
+		data saved on each oops/panic. Pstore saves (possibly
+		multiple) files based on the record size of the underlying
+		persistent storage until at least this amount is reached.
+		Default is 10 Kbytes.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-css linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-css
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-css	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-css	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 		linux-s390@vger.kernel.org
 Description:	Contains the PIM/PAM/POM values, as reported by the
 		channel subsystem when last queried by the common I/O
-		layer (this implies that this attribute is not neccessarily
+		layer (this implies that this attribute is not necessarily
 		in sync with the values current in the channel subsystem).
 		Note: This is an I/O-subchannel specific attribute.
 Users:		s390-tools, HAL
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-media linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-media
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-media	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-media	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+What:		/sys/bus/media/devices/.../model
+Date:		January 2011
+Contact:	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+		linux-media@vger.kernel.org
+Description:	Contains the device model name in UTF-8. The device version is
+		is not be appended to the model name.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-pci linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-pci
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-pci	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-pci	2011-05-19 00:06:34.000000000 -0400
@@ -145,9 +145,11 @@
 Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
 Description:
 		Reading this attribute will provide the firmware
-		given name(SMBIOS type 41 string) of the PCI device.
-		The attribute will be created only if the firmware
-		has given a name to the PCI device.
+		given name (SMBIOS type 41 string or ACPI _DSM string) of
+		the PCI device.	The attribute will be created only
+		if the firmware	has given a name to the PCI device.
+		ACPI _DSM string name will be given priority if the
+		system firmware provides SMBIOS type 41 string also.
 Users:
 		Userspace applications interested in knowing the
 		firmware assigned name of the PCI device.
@@ -157,12 +159,27 @@
 Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
 Description:
 		Reading this attribute will provide the firmware
-		given instance(SMBIOS type 41 device type instance)
-		of the PCI device. The attribute will be created
-		only if the firmware has given a device type instance
-		to the PCI device.
+		given instance (SMBIOS type 41 device type instance) of the
+		PCI device. The attribute will be created only if the firmware
+		has given an instance number to the PCI device.
 Users:
 		Userspace applications interested in knowing the
 		firmware assigned device type instance of the PCI
 		device that can help in understanding the firmware
 		intended order of the PCI device.
+
+What:		/sys/bus/pci/devices/.../acpi_index
+Date:		July 2010
+Contact:	Narendra K <narendra_k@dell.com>, linux-bugs@dell.com
+Description:
+		Reading this attribute will provide the firmware
+		given instance (ACPI _DSM instance number) of the PCI device.
+		The attribute will be created only if the firmware has given
+		an instance number to the PCI device. ACPI _DSM instance number
+		will be given priority if the system firmware provides SMBIOS
+		type 41 device type instance also.
+Users:
+		Userspace applications interested in knowing the
+		firmware assigned instance number of the PCI
+		device that can help in understanding the firmware
+		intended order of the PCI device.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-pci-devices-cciss	2011-05-19 00:06:34.000000000 -0400
@@ -59,3 +59,15 @@
 Contact:	iss_storagedev@hp.com
 Description:	Displays the usage count (number of opens) of logical drive Y
 		of controller X.
+
+Where:		/sys/bus/pci/devices/<dev>/ccissX/resettable
+Date:		February 2011
+Kernel Version:	2.6.38
+Contact:	iss_storagedev@hp.com
+Description:	Value of 1 indicates the controller can honor the reset_devices
+		kernel parameter.  Value of 0 indicates reset_devices cannot be
+		honored.  This is to allow, for example, kexec tools to be able
+		to warn the user if they designate an unresettable device as
+		a dump device, as kdump requires resetting the device in order
+		to work reliably.
+
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-rbd linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-rbd
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-bus-rbd	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-bus-rbd	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 What:		/sys/bus/rbd/
 Date:		November 2010
-Contact:	Yehuda Sadeh <yehuda@hq.newdream.net>,
+Contact:	Yehuda Sadeh <yehuda@newdream.net>,
 		Sage Weil <sage@newdream.net>
 Description:
 
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-class-led linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-class-led
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-class-led	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-class-led	2011-05-19 00:06:34.000000000 -0400
@@ -33,5 +33,5 @@
 Description:
 		Invert the LED on/off state. This parameter is specific to
 		gpio and backlight triggers. In case of the backlight trigger,
-		it is usefull when driving a LED which is intended to indicate
+		it is useful when driving a LED which is intended to indicate
 		a device in a standby like state.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-devices-mmc linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-devices-mmc
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-devices-mmc	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-devices-mmc	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,21 @@
+What:		/sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_offset
+Date:		January 2011
+Contact:	Chuanxiao Dong <chuanxiao.dong@intel.com>
+Description:
+		Enhanced area is a new feature defined in eMMC4.4 standard.
+		eMMC4.4 or later card can support such feature. This kind of
+		area can help to improve the card performance. If the feature
+		is enabled, this attribute will indicate the start address of
+		enhanced data area. If not, this attribute will be -EINVAL.
+		Unit Byte. Format decimal.
+
+What:		/sys/devices/.../mmc_host/mmcX/mmcX:XXXX/enhanced_area_size
+Date:		January 2011
+Contact:	Chuanxiao Dong <chuanxiao.dong@intel.com>
+Description:
+		Enhanced area is a new feature defined in eMMC4.4 standard.
+		eMMC4.4 or later card can support such feature. This kind of
+		area can help to improve the card performance. If the feature
+		is enabled, this attribute will indicate the size of enhanced
+		data area. If not, this attribute will be -EINVAL.
+		Unit KByte. Format decimal.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-devices-power linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-devices-power
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-devices-power	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-devices-power	2011-05-19 00:06:34.000000000 -0400
@@ -29,9 +29,8 @@
 		"disabled" to it.
 
 		For the devices that are not capable of generating system wakeup
-		events this file contains "\n".  In that cases the user space
-		cannot modify the contents of this file and the device cannot be
-		enabled to wake up the system.
+		events this file is not present.  In that case the device cannot
+		be enabled to wake up the system from sleep states.
 
 What:		/sys/devices/.../power/control
 Date:		January 2009
@@ -85,7 +84,7 @@
 		The /sys/devices/.../wakeup_count attribute contains the number
 		of signaled wakeup events associated with the device.  This
 		attribute is read-only.  If the device is not enabled to wake up
-		the system from sleep states, this attribute is empty.
+		the system from sleep states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_active_count
 Date:		September 2010
@@ -95,7 +94,7 @@
 		number of times the processing of wakeup events associated with
 		the device was completed (at the kernel level).  This attribute
 		is read-only.  If the device is not enabled to wake up the
-		system from sleep states, this attribute is empty.
+		system from sleep states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_hit_count
 Date:		September 2010
@@ -105,7 +104,8 @@
 		number of times the processing of a wakeup event associated with
 		the device might prevent the system from entering a sleep state.
 		This attribute is read-only.  If the device is not enabled to
-		wake up the system from sleep states, this attribute is empty.
+		wake up the system from sleep states, this attribute is not
+		present.
 
 What:		/sys/devices/.../power/wakeup_active
 Date:		September 2010
@@ -115,7 +115,7 @@
 		or 0, depending on whether or not a wakeup event associated with
 		the device is being processed (1).  This attribute is read-only.
 		If the device is not enabled to wake up the system from sleep
-		states, this attribute is empty.
+		states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_total_time_ms
 Date:		September 2010
@@ -125,7 +125,7 @@
 		the total time of processing wakeup events associated with the
 		device, in milliseconds.  This attribute is read-only.  If the
 		device is not enabled to wake up the system from sleep states,
-		this attribute is empty.
+		this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_max_time_ms
 Date:		September 2010
@@ -135,7 +135,7 @@
 		the maximum time of processing a single wakeup event associated
 		with the device, in milliseconds.  This attribute is read-only.
 		If the device is not enabled to wake up the system from sleep
-		states, this attribute is empty.
+		states, this attribute is not present.
 
 What:		/sys/devices/.../power/wakeup_last_time_ms
 Date:		September 2010
@@ -146,7 +146,7 @@
 		signaling the last wakeup event associated with the device, in
 		milliseconds.  This attribute is read-only.  If the device is
 		not enabled to wake up the system from sleep states, this
-		attribute is empty.
+		attribute is not present.
 
 What:		/sys/devices/.../power/autosuspend_delay_ms
 Date:		September 2010
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+What:		For USB devices	: /sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
+		For BT devices	: /sys/class/bluetooth/hci<addr>/<hid-bus>:<vendor-id>:<product-id>.<num>/report_descriptor
+		Symlink		: /sys/class/hidraw/hidraw<num>/device/report_descriptor
+Date:		Jan 2011
+KernelVersion:	2.0.39
+Contact:	Alan Ott <alan@signal11.us>
+Description:	When read, this file returns the device's raw binary HID
+		report descriptor.
+		This file cannot be written.
+Users:		HIDAPI library (http://www.signal11.us/oss/hidapi)
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-arvo	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,53 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/actual_profile
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-5.
+		When read, this attribute returns the number of the actual
+		profile which is also the profile that's active on device startup.
+		When written this attribute activates the selected profile
+		immediately.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/button
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The keyboard can store short macros with consist of 1 button with
+		several modifier keys internally.
+		When written, this file lets one set the sequence for a specific
+		button for a specific profile. Button and profile numbers are
+		included in written data. The data has to be 24 bytes long.
+		This file is writeonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/info
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns some info about the device like the
+		installed firmware version.
+		The size of the data is 8 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/key_mask
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The keyboard lets the user deactivate 5 certain keys like the
+		windows and application keys, to protect the user from the outcome
+		of accidentally pressing them.
+		The integer value of this attribute has bits 0-4 set depending
+		on the state of the corresponding key.
+		When read, this file returns the current state of the buttons.
+		When written, the given buttons are activated/deactivated
+		immediately.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/arvo/roccatarvo<minor>/mode_key
+Date:		Januar 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The keyboard has a condensed layout without num-lock key.
+		Instead it uses a mode-key which activates a gaming mode where
+		the assignment of the number block changes.
+		The integer value of this attribute ranges from 0 (OFF) to 1 (ON).
+		When read, this file returns the actual state of the key.
+		When written, the key is activated/deactivated immediately.
+Users:		http://roccat.sourceforge.net
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kone	2011-05-19 00:06:34.000000000 -0400
@@ -16,12 +16,14 @@
 		6     3200
 
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/actual_profile
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	When read, this file returns the number of the actual profile.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/firmware_version
 Date:		March 2010
@@ -32,12 +34,13 @@
 		number the decimal point has to be shifted 2 positions to the
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/profile[1-5]
 Date:		March 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
-                press of a button. A profile holds informations like button
+                press of a button. A profile holds information like button
                 mappings, sensitivity, the colors of the 5 leds and light
                 effects.
                 When read, these files return the respective profile. The
@@ -47,6 +50,7 @@
 		The mouse will reject invalid data, whereas the profile number
 		stored in the profile doesn't need to fit the number of the
 		store.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/settings
 Date:		March 2010
@@ -57,6 +61,7 @@
 		When written, this file lets write settings back to the mouse.
 		The data has to be 36 bytes long. The mouse will reject invalid
 		data.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/startup_profile
 Date:		March 2010
@@ -66,6 +71,7 @@
                 that's active when the mouse is powered on.
 		When written, this file sets the number of the startup profile
 		and the mouse activates this profile immediately.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/tcu
 Date:		March 2010
@@ -77,6 +83,7 @@
 		Writing 0 in this file will switch the TCU off.
 		Writing 1 in this file will start the calibration which takes
 		around 6 seconds to complete and activates the TCU.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kone/roccatkone<minor>/weight
 Date:		March 2010
@@ -96,3 +103,4 @@
 		4     20g
 
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-koneplus	2011-05-19 00:06:34.000000000 -0400
@@ -4,6 +4,7 @@
 Description:	When read, this file returns the number of the actual profile in
 		range 0-4.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/firmware_version
 Date:		October 2010
@@ -14,6 +15,7 @@
 		number the decimal point has to be shifted 2 positions to the
 		left. E.g. a returned value of 121 means 1.21
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/macro
 Date:		October 2010
@@ -24,36 +26,39 @@
 		button for a specific profile. Button and profile numbers are
 		included in written data. The data has to be 2082 bytes long.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_buttons
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds informations about button layout.
+		profile_buttons holds information about button layout.
 		When written, this file lets one write the respective profile
 		buttons back to the mouse. The data has to be 77 bytes long.
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_buttons
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds informations about button layout.
+		profile_buttons holds information about button layout.
 		When read, these files return the respective profile buttons.
 		The returned data is 77 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile_settings
 Date:		October 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_settings holds informations like resolution, sensitivity
+		profile_settings holds information like resolution, sensitivity
 		and light effects.
 		When written, this file lets one write the respective profile
 		settings back to the mouse. The data has to be 43 bytes long.
@@ -61,17 +66,19 @@
 		Which profile to write is determined by the profile number
 		contained in the data.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/profile[1-5]_settings
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_settings holds informations like resolution, sensitivity
+		profile_settings holds information like resolution, sensitivity
 		and light effects.
 		When read, these files return the respective profile settings.
 		The returned data is 43 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/sensor
 Date:		October 2010
@@ -80,6 +87,7 @@
 		can be activated/deactivated and the lift-off distance can be
 		set. The data has to be 6 bytes long.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/startup_profile
 Date:		October 2010
@@ -89,6 +97,7 @@
                 that's active when the mouse is powered on.
 		When written, this file sets the number of the startup profile
 		and the mouse activates this profile immediately.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu
 Date:		October 2010
@@ -97,6 +106,7 @@
 		can be initiated/cancelled.
 		The data has to be 3 bytes long.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/koneplus/roccatkoneplus<minor>/tcu_image
 Date:		October 2010
@@ -106,3 +116,4 @@
 		calibration process initiated with tcu.
 		The returned data is 1028 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-kovaplus	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,100 @@
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_cpi
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-4.
+		When read, this attribute returns the number of the active
+		cpi level.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_profile
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 0-4.
+		When read, this attribute returns the number of the active
+		profile.
+		When written, the mouse activates this profile immediately.
+		The profile that's active when powered down is the same that's
+		active when the mouse is powered on.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_x
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-10.
+		When read, this attribute returns the number of the actual
+		sensitivity in x direction.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/actual_sensitivity_y
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The integer value of this attribute ranges from 1-10.
+		When read, this attribute returns the number of the actual
+		sensitivity in y direction.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/firmware_version
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	When read, this file returns the raw integer version number of the
+		firmware reported by the mouse. Using the integer value eases
+		further usage in other programs. To receive the real version
+		number the decimal point has to be shifted 2 positions to the
+		left. E.g. a returned value of 121 means 1.21
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_buttons
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds information about button layout.
+		When written, this file lets one write the respective profile
+		buttons back to the mouse. The data has to be 23 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		This file is writeonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_buttons
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_buttons holds information about button layout.
+		When read, these files return the respective profile buttons.
+		The returned data is 23 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile_settings
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds information like resolution, sensitivity
+		and light effects.
+		When written, this file lets one write the respective profile
+		settings back to the mouse. The data has to be 16 bytes long.
+		The mouse will reject invalid data.
+		Which profile to write is determined by the profile number
+		contained in the data.
+		This file is writeonly.
+Users:		http://roccat.sourceforge.net
+
+What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/kovaplus/roccatkovaplus<minor>/profile[1-5]_settings
+Date:		January 2011
+Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
+Description:	The mouse can store 5 profiles which can be switched by the
+		press of a button. A profile is split in settings and buttons.
+		profile_settings holds information like resolution, sensitivity
+		and light effects.
+		When read, these files return the respective profile settings.
+		The returned data is 16 bytes in size.
+		This file is readonly.
+Users:		http://roccat.sourceforge.net
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-hid-roccat-pyra	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 		4     1600
 
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/actual_profile
 Date:		August 2010
@@ -20,6 +21,7 @@
 Description:	When read, this file returns the number of the actual profile in
 		range 0-4.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/firmware_version
 Date:		August 2010
@@ -30,13 +32,14 @@
 		number the decimal point has to be shifted 2 positions to the
 		left. E.g. a returned value of 138 means 1.38
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_settings
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_settings holds informations like resolution, sensitivity
+		profile_settings holds information like resolution, sensitivity
 		and light effects.
 		When written, this file lets one write the respective profile
 		settings back to the mouse. The data has to be 13 bytes long.
@@ -44,40 +47,44 @@
 		Which profile to write is determined by the profile number
 		contained in the data.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_settings
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_settings holds informations like resolution, sensitivity
+		profile_settings holds information like resolution, sensitivity
 		and light effects.
 		When read, these files return the respective profile settings.
 		The returned data is 13 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile_buttons
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds informations about button layout.
+		profile_buttons holds information about button layout.
 		When written, this file lets one write the respective profile
 		buttons back to the mouse. The data has to be 19 bytes long.
 		The mouse will reject invalid data.
 		Which profile to write is determined by the profile number
 		contained in the data.
 		This file is writeonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/profile[1-5]_buttons
 Date:		August 2010
 Contact:	Stefan Achatz <erazor_de@users.sourceforge.net>
 Description:	The mouse can store 5 profiles which can be switched by the
 		press of a button. A profile is split in settings and buttons.
-		profile_buttons holds informations about button layout.
+		profile_buttons holds information about button layout.
 		When read, these files return the respective profile buttons.
 		The returned data is 19 bytes in size.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/startup_profile
 Date:		August 2010
@@ -86,6 +93,7 @@
                 When read, this attribute returns the number of the profile
                 that's active when the mouse is powered on.
 		This file is readonly.
+Users:		http://roccat.sourceforge.net
 
 What:		/sys/bus/usb/devices/<busnum>-<devnum>:<config num>.<interface num>/<hid-bus>:<vendor-id>:<product-id>.<num>/pyra/roccatpyra<minor>/settings
 Date:		August 2010
@@ -96,3 +104,4 @@
 		When written, this file lets write settings back to the mouse.
 		The data has to be 3 bytes long. The mouse will reject invalid
 		data.
+Users:		http://roccat.sourceforge.net
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-samsung-laptop linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-samsung-laptop
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-driver-samsung-laptop	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-driver-samsung-laptop	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,19 @@
+What:		/sys/devices/platform/samsung/performance_level
+Date:		January 1, 2010
+KernelVersion:	2.6.33
+Contact:	Greg Kroah-Hartman <gregkh@suse.de>
+Description:	Some Samsung laptops have different "performance levels"
+		that are can be modified by a function key, and by this
+		sysfs file.  These values don't always make a whole lot
+		of sense, but some users like to modify them to keep
+		their fans quiet at all costs.  Reading from this file
+		will show the current performance level.  Writing to the
+		file can change this value.
+			Valid options:
+				"silent"
+				"normal"
+				"overclock"
+		Note that not all laptops support all of these options.
+		Specifically, not all support the "overclock" option,
+		and it's still unknown if this value even changes
+		anything, other than making the user feel a bit better.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-firmware-dmi linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-firmware-dmi
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-firmware-dmi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-firmware-dmi	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,110 @@
+What:		/sys/firmware/dmi/
+Date:		February 2011
+Contact:	Mike Waychison <mikew@google.com>
+Description:
+		Many machines' firmware (x86 and ia64) export DMI /
+		SMBIOS tables to the operating system.  Getting at this
+		information is often valuable to userland, especially in
+		cases where there are OEM extensions used.
+
+		The kernel itself does not rely on the majority of the
+		information in these tables being correct.  It equally
+		cannot ensure that the data as exported to userland is
+		without error either.
+
+		DMI is structured as a large table of entries, where
+		each entry has a common header indicating the type and
+		length of the entry, as well as 'handle' that is
+		supposed to be unique amongst all entries.
+
+		Some entries are required by the specification, but many
+		others are optional.  In general though, users should
+		never expect to find a specific entry type on their
+		system unless they know for certain what their firmware
+		is doing.  Machine to machine will vary.
+
+		Multiple entries of the same type are allowed.  In order
+		to handle these duplicate entry types, each entry is
+		assigned by the operating system an 'instance', which is
+		derived from an entry type's ordinal position.  That is
+		to say, if there are 'N' multiple entries with the same type
+		'T' in the DMI tables (adjacent or spread apart, it
+		doesn't matter), they will be represented in sysfs as
+		entries "T-0" through "T-(N-1)":
+
+		Example entry directories:
+
+			/sys/firmware/dmi/entries/17-0
+			/sys/firmware/dmi/entries/17-1
+			/sys/firmware/dmi/entries/17-2
+			/sys/firmware/dmi/entries/17-3
+			...
+
+		Instance numbers are used in lieu of the firmware
+		assigned entry handles as the kernel itself makes no
+		guarantees that handles as exported are unique, and
+		there are likely firmware images that get this wrong in
+		the wild.
+
+		Each DMI entry in sysfs has the common header values
+		exported as attributes:
+
+		handle	: The 16bit 'handle' that is assigned to this
+			  entry by the firmware.  This handle may be
+			  referred to by other entries.
+		length	: The length of the entry, as presented in the
+			  entry itself.  Note that this is _not the
+			  total count of bytes associated with the
+			  entry_.  This value represents the length of
+			  the "formatted" portion of the entry.  This
+			  "formatted" region is sometimes followed by
+			  the "unformatted" region composed of nul
+			  terminated strings, with termination signalled
+			  by a two nul characters in series.
+		raw	: The raw bytes of the entry. This includes the
+			  "formatted" portion of the entry, the
+			  "unformatted" strings portion of the entry,
+			  and the two terminating nul characters.
+		type	: The type of the entry.  This value is the same
+			  as found in the directory name.  It indicates
+			  how the rest of the entry should be
+			  interpreted.
+		instance: The instance ordinal of the entry for the
+			  given type.  This value is the same as found
+			  in the parent directory name.
+		position: The position of the entry within the entirety
+			  of the entirety.
+
+		=== Entry Specialization ===
+
+		Some entry types may have other information available in
+		sysfs.
+
+		--- Type 15 - System Event Log ---
+
+		This entry allows the firmware to export a log of
+		events the system has taken.  This information is
+		typically backed by nvram, but the implementation
+		details are abstracted by this table.  This entries data
+		is exported in the directory:
+
+		/sys/firmware/dmi/entries/15-0/system_event_log
+
+		and has the following attributes (documented in the
+		SMBIOS / DMI specification under "System Event Log (Type 15)":
+
+		area_length
+		header_start_offset
+		data_start_offset
+		access_method
+		status
+		change_token
+		access_method_address
+		header_format
+		per_log_type_descriptor_length
+		type_descriptors_supported_count
+
+		As well, the kernel exports the binary attribute:
+
+		raw_event_log	: The raw binary bits of the event log
+				  as described by the DMI entry.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-fs-ext4 linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-fs-ext4
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-fs-ext4	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-fs-ext4	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
 		 will have its blocks allocated out of its own unique
 		 preallocation pool.
 
-What:		/sys/fs/ext4/<disk>/inode_readahead
+What:		/sys/fs/ext4/<disk>/inode_readahead_blks
 Date:		March 2008
 Contact:	"Theodore Ts'o" <tytso@mit.edu>
 Description:
@@ -85,7 +85,14 @@
 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
+		inode used by the inode allocator in preference to
+		all other allocation heuristics.  This is intended for
 		debugging use only, and should be 0 on production
 		systems.
+
+What:		/sys/fs/ext4/<disk>/max_writeback_mb_bump
+Date:		September 2009
+Contact:	"Theodore Ts'o" <tytso@mit.edu>
+Description:
+		The maximum number of megabytes the writeback code will
+		try to write out before move on to another inode.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-asus-laptop linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-asus-laptop
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-asus-laptop	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-asus-laptop	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 Contact:	"Corentin Chary" <corentincj@iksaif.net>
 Description:
 		Some models like the W1N have a LED display that can be
-		used to display several informations.
+		used to display several items of information.
 		To control the LED display, use the following :
 		    echo 0x0T000DDD > /sys/devices/platform/asus_laptop/
 		where T control the 3 letters display, and DDD the 3 digits display.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-asus-wmi linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-asus-wmi
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-asus-wmi	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-asus-wmi	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+What:		/sys/devices/platform/<platform>/cpufv
+Date:		Oct 2010
+KernelVersion:	2.6.37
+Contact:	"Corentin Chary" <corentincj@iksaif.net>
+Description:
+		Change CPU clock configuration (write-only).
+		There are three available clock configuration:
+		    * 0 -> Super Performance Mode
+		    * 1 -> High Performance Mode
+		    * 2 -> Power Saving Mode
+
+What:		/sys/devices/platform/<platform>/camera
+Date:		Jan 2010
+KernelVersion:	2.6.39
+Contact:	"Corentin Chary" <corentincj@iksaif.net>
+Description:
+		Control the camera. 1 means on, 0 means off.
+
+What:		/sys/devices/platform/<platform>/cardr
+Date:		Jan 2010
+KernelVersion:	2.6.39
+Contact:	"Corentin Chary" <corentincj@iksaif.net>
+Description:
+		Control the card reader. 1 means on, 0 means off.
+
+What:		/sys/devices/platform/<platform>/touchpad
+Date:		Jan 2010
+KernelVersion:	2.6.39
+Contact:	"Corentin Chary" <corentincj@iksaif.net>
+Description:
+		Control the card touchpad. 1 means on, 0 means off.
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-eeepc-wmi linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-eeepc-wmi
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-eeepc-wmi	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-eeepc-wmi	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-What:		/sys/devices/platform/eeepc-wmi/cpufv
-Date:		Oct 2010
-KernelVersion:	2.6.37
-Contact:	"Corentin Chary" <corentincj@iksaif.net>
-Description:
-		Change CPU clock configuration (write-only).
-		There are three available clock configuration:
-		    * 0 -> Super Performance Mode
-		    * 1 -> High Performance Mode
-		    * 2 -> Power Saving Mode
diff -druN linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-kim linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-kim
--- linux-libre-2.6.38-gnu/Documentation/ABI/testing/sysfs-platform-kim	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/ABI/testing/sysfs-platform-kim	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,48 @@
+What:		/sys/devices/platform/kim/dev_name
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		Name of the UART device at which the WL128x chip
+		is connected. example: "/dev/ttyS0".
+		The device name flows down to architecture specific board
+		initialization file from the SFI/ATAGS bootloader
+		firmware. The name exposed is read from the user-space
+		dameon and opens the device when install is requested.
+
+What:		/sys/devices/platform/kim/baud_rate
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		The maximum reliable baud-rate the host can support.
+		Different platforms tend to have different high-speed
+		UART configurations, so the baud-rate needs to be set
+		locally and also sent across to the WL128x via a HCI-VS
+		command. The entry is read and made use by the user-space
+		daemon when the ldisc install is requested.
+
+What:		/sys/devices/platform/kim/flow_cntrl
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		The WL128x makes use of flow control mechanism, and this
+		entry most often should be 1, the host's UART is required
+		to have the capability of flow-control, or else this
+		entry can be made use of for exceptions.
+
+What:		/sys/devices/platform/kim/install
+Date:		January 2010
+KernelVersion:	2.6.38
+Contact:	"Pavan Savoy" <pavan_savoy@ti.com>
+Description:
+		When one of the protocols Bluetooth, FM or GPS wants to make
+		use of the shared UART transport, it registers to the shared
+		transport driver, which will signal the user-space for opening,
+		configuring baud and install line discipline via this sysfs
+		entry. This entry would be polled upon by the user-space
+		daemon managing the UART, and is notified about the change
+		by the sysfs_notify. The value would be '1' when UART needs
+		to be opened/ldisc installed, and would be '0' when UART
+		is no more required and needs to be closed.
diff -druN linux-libre-2.6.38-gnu/Documentation/acpi/apei/output_format.txt linux-libre-2.6.39-gnu/Documentation/acpi/apei/output_format.txt
--- linux-libre-2.6.38-gnu/Documentation/acpi/apei/output_format.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/acpi/apei/output_format.txt	2011-05-19 00:06:34.000000000 -0400
@@ -92,6 +92,11 @@
 class_code: <integer>]
 [serial number: <integer>, <integer>]
 [bridge: secondary_status: <integer>, control: <integer>]
+[aer_status: <integer>, aer_mask: <integer>
+<aer status string>
+[aer_uncor_severity: <integer>]
+aer_layer=<aer layer string>, aer_agent=<aer agent string>
+aer_tlp_header: <integer> <integer> <integer> <integer>]
 
 <pcie port type string>* := PCIe end point | legacy PCI end point | \
 unknown | unknown | root port | upstream switch port | \
@@ -99,6 +104,26 @@
 PCI/PCI-X to PCIe bridge | root complex integrated endpoint device | \
 root complex event collector
 
+if section severity is fatal or recoverable
+<aer status string># :=
+unknown | unknown | unknown | unknown | Data Link Protocol | \
+unknown | unknown | unknown | unknown | unknown | unknown | unknown | \
+Poisoned TLP | Flow Control Protocol | Completion Timeout | \
+Completer Abort | Unexpected Completion | Receiver Overflow | \
+Malformed TLP | ECRC | Unsupported Request
+else
+<aer status string># :=
+Receiver Error | unknown | unknown | unknown | unknown | unknown | \
+Bad TLP | Bad DLLP | RELAY_NUM Rollover | unknown | unknown | unknown | \
+Replay Timer Timeout | Advisory Non-Fatal
+fi
+
+<aer layer string> :=
+Physical Layer | Data Link Layer | Transaction Layer
+
+<aer agent string> :=
+Receiver ID | Requester ID | Completer ID | Transmitter ID
+
 Where, [] designate corresponding content is optional
 
 All <field string> description with * has the following format:
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/IXP4xx linux-libre-2.6.39-gnu/Documentation/arm/IXP4xx
--- linux-libre-2.6.38-gnu/Documentation/arm/IXP4xx	2012-03-24 00:59:19.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/IXP4xx	2012-03-24 03:25:34.000000000 -0400
@@ -43,7 +43,7 @@
 
 /*(DEBLOBBED)*/
 
-DO NOT POST QUESTIONS TO THE LINUX MAILING LISTS REGARDING THE PROPIETARY
+DO NOT POST QUESTIONS TO THE LINUX MAILING LISTS REGARDING THE PROPRIETARY
 SOFTWARE.
 
 There are several websites that provide directions/pointers on using
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Samsung/GPIO.txt linux-libre-2.6.39-gnu/Documentation/arm/Samsung/GPIO.txt
--- linux-libre-2.6.38-gnu/Documentation/arm/Samsung/GPIO.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Samsung/GPIO.txt	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
 ------------
 
 This outlines the Samsung GPIO implementation and the architecture
-specfic calls provided alongisde the drivers/gpio core.
+specific calls provided alongisde the drivers/gpio core.
 
 
 S3C24XX (Legacy)
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Samsung-S3C24XX/Suspend.txt linux-libre-2.6.39-gnu/Documentation/arm/Samsung-S3C24XX/Suspend.txt
--- linux-libre-2.6.38-gnu/Documentation/arm/Samsung-S3C24XX/Suspend.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Samsung-S3C24XX/Suspend.txt	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,7 @@
     Allows the entire memory to be checksummed before and after the
     suspend to see if there has been any corruption of the contents.
 
-    Note, the time to calculate the CRC is dependant on the CPU speed
+    Note, the time to calculate the CRC is dependent on the CPU speed
     and the size of memory. For an 64Mbyte RAM area on an 200MHz
     S3C2410, this can take approximately 4 seconds to complete.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/ADC-LH7-Touchscreen	1969-12-31 19:00:00.000000000 -0500
@@ -1,61 +0,0 @@
-README on the ADC/Touchscreen Controller
-========================================
-
-The LH79524 and LH7A404 include a built-in Analog to Digital
-controller (ADC) that is used to process input from a touchscreen.
-The driver only implements a four-wire touch panel protocol.
-
-The touchscreen driver is maintenance free except for the pen-down or
-touch threshold.  Some resistive displays and board combinations may
-require tuning of this threshold.  The driver exposes some of its
-internal state in the sys filesystem.  If the kernel is configured
-with it, CONFIG_SYSFS, and sysfs is mounted at /sys, there will be a
-directory
-
-  /sys/devices/platform/adc-lh7.0
-
-containing these files.
-
-  -r--r--r--    1 root     root         4096 Jan  1 00:00 samples
-  -rw-r--r--    1 root     root         4096 Jan  1 00:00 threshold
-  -r--r--r--    1 root     root         4096 Jan  1 00:00 threshold_range
-
-The threshold is the current touch threshold.  It defaults to 750 on
-most targets.
-
-  # cat threshold
- 750
-
-The threshold_range contains the range of valid values for the
-threshold.  Values outside of this range will be silently ignored.
-
-  # cat threshold_range
-  0 1023
-
-To change the threshold, write a value to the threshold file.
-
-  # echo 500 > threshold
-  # cat threshold
-  500
-
-The samples file contains the most recently sampled values from the
-ADC.  There are 12.  Below are typical of the last sampled values when
-the pen has been released.  The first two and last two samples are for
-detecting whether or not the pen is down.  The third through sixth are
-X coordinate samples.  The seventh through tenth are Y coordinate
-samples.
-
-  # cat samples
-  1023 1023 0 0 0 0 530 529 530 529 1023 1023
-
-To determine a reasonable threshold, press on the touch panel with an
-appropriate stylus and read the values from samples.
-
-  # cat samples
-  1023 676 92 103 101 102 855 919 922 922 1023 679
-
-The first and eleventh samples are discarded.  Thus, the important
-values are the second and twelfth which are used to determine if the
-pen is down.  When both are below the threshold, the driver registers
-that the pen is down.  When either is above the threshold, it
-registers then pen is up.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/CompactFlash linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/CompactFlash
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/CompactFlash	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/CompactFlash	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-README on the Compact Flash for Card Engines
-============================================
-
-There are three challenges in supporting the CF interface of the Card
-Engines.  First, every IO operation must be followed with IO to
-another memory region.  Second, the slot is wired for one-to-one
-address mapping *and* it is wired for 16 bit access only.  Second, the
-interrupt request line from the CF device isn't wired.
-
-The IOBARRIER issue is covered in README.IOBARRIER.  This isn't an
-onerous problem.  Enough said here.
-
-The addressing issue is solved in the
-arch/arm/mach-lh7a40x/ide-lpd7a40x.c file with some awkward
-work-arounds.  We implement a special SELECT_DRIVE routine that is
-called before the IDE driver performs its own SELECT_DRIVE.  Our code
-recognizes that the SELECT register cannot be modified without also
-writing a command.  It send an IDLE_IMMEDIATE command on selecting a
-drive.  The function also prevents drive select to the slave drive
-since there can be only one.  The awkward part is that the IDE driver,
-even though we have a select procedure, also attempts to change the
-drive by writing directly the SELECT register.  This attempt is
-explicitly blocked by the OUTB function--not pretty, but effective.
-
-The lack of interrupts is a more serious problem.  Even though the CF
-card is fast when compared to a normal IDE device, we don't know that
-the CF is really flash.  A user could use one of the very small hard
-drives being shipped with a CF interface.  The IDE code includes a
-check for interfaces that lack an IRQ.  In these cases, submitting a
-command to the IDE controller is followed by a call to poll for
-completion.  If the device isn't immediately ready, it schedules a
-timer to poll again later.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/IOBarrier linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/IOBarrier
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/IOBarrier	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/IOBarrier	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-README on the IOBARRIER for CardEngine IO
-=========================================
-
-Due to an unfortunate oversight when the Card Engines were designed,
-the signals that control access to some peripherals, most notably the
-SMC91C9111 ethernet controller, are not properly handled.
-
-The symptom is that some back to back IO with the peripheral returns
-unreliable data.  With the SMC chip, you'll see errors about the bank
-register being 'screwed'.
-
-The cause is that the AEN signal to the SMC chip does not transition
-for every memory access.  It is driven through the CPLD from the CS7
-line of the CPU's static memory controller which is optimized to
-eliminate unnecessary transitions.  Yet, the SMC requires a transition
-for every write access.  The Sharp website has more information about
-the effect this power-conserving feature has on peripheral
-interfacing.
-
-The solution is to follow every write access to the SMC chip with an
-access to another memory region that will force the CPU to release the
-chip select line.  It is important to guarantee that this access
-forces the CPU off-chip.  We map a page of SDRAM as if it were an
-uncacheable IO device and read from it after every SMC IO write
-operation.
-
-  SMC IO
-  BARRIER IO
-
-Only this sequence is important.  It does not matter that there is no
-BARRIER IO before the access to the SMC chip because the AEN latch
-only needs occurs after the SMC IO write cycle.  The routines that
-implement this work-around make an additional concession which is to
-disable interrupts during the IO sequence.  Other hardware devices
-(the LogicPD CPLD) have registers in the same physical memory
-region as the SMC chip.  An interrupt might allow an access to one of
-those registers while SMC IO is being performed.
-
-You might be tempted to think that we have to access another device
-attached to the static memory controller, but the empirical evidence
-indicates that this is not so.  Mapping 0x00000000 (flash) and
-0xc0000000 (SDRAM) appear to have the same effect.  Using SDRAM seems
-to be faster.  Choosing to access an undecoded memory region is not
-desirable as there is no way to know how that chip select will be used
-in the future.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/KEV7A400 linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/KEV7A400
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/KEV7A400	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/KEV7A400	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-README on Implementing Linux for Sharp's KEV7a400
-=================================================
-
-This product has been discontinued by Sharp.  For the time being, the
-partially implemented code remains in the kernel.  At some point in
-the future, either the code will be finished or it will be removed
-completely.  This depends primarily on how many of the development
-boards are in the field.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/LCDPanels linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/LCDPanels
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/LCDPanels	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/LCDPanels	1969-12-31 19:00:00.000000000 -0500
@@ -1,59 +0,0 @@
-README on the LCD Panels
-========================
-
-Configuration options for several LCD panels, available from Logic PD,
-are included in the kernel source.  This README will help you
-understand the configuration data and give you some guidance for
-adding support for other panels if you wish.
-
-
-lcd-panels.h
-------------
-
-There is no way, at present, to detect which panel is attached to the
-system at runtime.  Thus the kernel configuration is static.  The file
-arch/arm/mach-ld7a40x/lcd-panels.h (or similar) defines all of the
-panel specific parameters.
-
-It should be possible for this data to be shared among several device
-families.  The current layout may be insufficiently general, but it is
-amenable to improvement.
-
-
-PIXEL_CLOCK
------------
-
-The panel data sheets will give a range of acceptable pixel clocks.
-The fundamental LCDCLK input frequency is divided down by a PCD
-constant in field '.tim2'.  It may happen that it is impossible to set
-the pixel clock within this range.  A clock which is too slow will
-tend to flicker.  For the highest quality image, set the clock as high
-as possible.
-
-
-MARGINS
--------
-
-These values may be difficult to glean from the panel data sheet.  In
-the case of the Sharp panels, the upper margin is explicitly called
-out as a specific number of lines from the top of the frame.  The
-other values may not matter as much as the panels tend to
-automatically center the image.
-
-
-Sync Sense
-----------
-
-The sense of the hsync and vsync pulses may be called out in the data
-sheet.  On one panel, the sense of these pulses determine the height
-of the visible region on the panel.  Most of the Sharp panels use
-negative sense sync pulses set by the TIM2_IHS and TIM2_IVS bits in
-'.tim2'.
-
-
-Pel Layout
-----------
-
-The Sharp color TFT panels are all configured for 16 bit direct color
-modes.  The amba-lcd driver sets the pel mode to 565 for 5 bits of
-each red and blue and 6 bits of green.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/LPD7A400 linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/LPD7A400
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/LPD7A400	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/LPD7A400	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-README on Implementing Linux for the Logic PD LPD7A400-10
-=========================================================
-
-- CPLD memory mapping
-
-  The board designers chose to use high address lines for controlling
-  access to the CPLD registers.  It turns out to be a big waste
-  because we're using an MMU and must map IO space into virtual
-  memory.  The result is that we have to make a mapping for every
-  register.
-
-- Serial Console
-
-  It may be OK not to use the serial console option if the user passes
-  the console device name to the kernel.  This deserves some exploration.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/LPD7A40X linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/LPD7A40X
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/LPD7A40X	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/LPD7A40X	1969-12-31 19:00:00.000000000 -0500
@@ -1,16 +0,0 @@
-README on Implementing Linux for the Logic PD LPD7A40X-10
-=========================================================
-
-- CPLD memory mapping
-
-  The board designers chose to use high address lines for controlling
-  access to the CPLD registers.  It turns out to be a big waste
-  because we're using an MMU and must map IO space into virtual
-  memory.  The result is that we have to make a mapping for every
-  register.
-
-- Serial Console
-
-  It may be OK not to use the serial console option if the user passes
-  the console device name to the kernel.  This deserves some exploration.
-
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/SDRAM linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/SDRAM
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/SDRAM	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/SDRAM	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-README on the SDRAM Controller for the LH7a40X
-==============================================
-
-The standard configuration for the SDRAM controller generates a sparse
-memory array.  The precise layout is determined by the SDRAM chips.  A
-default kernel configuration assembles the discontiguous memory
-regions into separate memory nodes via the NUMA (Non-Uniform Memory
-Architecture) facilities.  In this default configuration, the kernel
-is forgiving about the precise layout.  As long as it is given an
-accurate picture of available memory by the bootloader the kernel will
-execute correctly.
-
-The SDRC supports a mode where some of the chip select lines are
-swapped in order to make SDRAM look like a synchronous ROM.  Setting
-this bit means that the RAM will present as a contiguous array.  Some
-programmers prefer this to the discontiguous layout.  Be aware that
-may be a penalty for this feature where some some configurations of
-memory are significantly reduced; i.e. 64MiB of RAM appears as only 32
-MiB.
-
-There are a couple of configuration options to override the default
-behavior.  When the SROMLL bit is set and memory appears as a
-contiguous array, there is no reason to support NUMA.
-CONFIG_LH7A40X_CONTIGMEM disables NUMA support.  When physical memory
-is discontiguous, the memory tables are organized such that there are
-two banks per nodes with a small gap between them.  This layout wastes
-some kernel memory for page tables representing non-existent memory.
-CONFIG_LH7A40X_ONE_BANK_PER_NODE optimizes the node tables such that
-there are no gaps.  These options control the low level organization
-of the memory management tables in ways that may prevent the kernel
-from booting or may cause the kernel to allocated excessively large
-page tables.  Be warned.  Only change these options if you know what
-you are doing.  The default behavior is a reasonable compromise that
-will suit all users.
-
---
-
-A typical 32MiB system with the default configuration options will
-find physical memory managed as follows.
-
-   node 0: 0xc0000000 4MiB
-           0xc1000000 4MiB
-   node 1: 0xc4000000 4MiB
-           0xc5000000 4MiB
-   node 2: 0xc8000000 4MiB
-           0xc9000000 4MiB
-   node 3: 0xcc000000 4MiB
-           0xcd000000 4MiB
-
-Setting CONFIG_LH7A40X_ONE_BANK_PER_NODE will put each bank into a
-separate node.
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/VectoredInterruptController linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/VectoredInterruptController
--- linux-libre-2.6.38-gnu/Documentation/arm/Sharp-LH/VectoredInterruptController	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/arm/Sharp-LH/VectoredInterruptController	1969-12-31 19:00:00.000000000 -0500
@@ -1,80 +0,0 @@
-README on the Vectored Interrupt Controller of the LH7A404
-==========================================================
-
-The 404 revision of the LH7A40X series comes with two vectored
-interrupts controllers.  While the kernel does use some of the
-features of these devices, it is far from the purpose for which they
-were designed.
-
-When this README was written, the implementation of the VICs was in
-flux.  It is possible that some details, especially with priorities,
-will change.
-
-The VIC support code is inspired by routines written by Sharp.
-
-
-Priority Control
-----------------
-
-The significant reason for using the VIC's vectoring is to control
-interrupt priorities.  There are two tables in
-arch/arm/mach-lh7a40x/irq-lh7a404.c that look something like this.
-
-  static unsigned char irq_pri_vic1[] = { IRQ_GPIO3INTR, };
-  static unsigned char irq_pri_vic2[] = {
-	IRQ_T3UI, IRQ_GPIO7INTR,
-	IRQ_UART1INTR, IRQ_UART2INTR, IRQ_UART3INTR, };
-
-The initialization code reads these tables and inserts a vector
-address and enable for each indicated IRQ.  Vectored interrupts have
-higher priority than non-vectored interrupts.  So, on VIC1,
-IRQ_GPIO3INTR will be served before any other non-FIQ interrupt.  Due
-to the way that the vectoring works, IRQ_T3UI is the next highest
-priority followed by the other vectored interrupts on VIC2.  After
-that, the non-vectored interrupts are scanned in VIC1 then in VIC2.
-
-
-ISR
----
-
-The interrupt service routine macro get_irqnr() in
-arch/arm/kernel/entry-armv.S scans the VICs for the next active
-interrupt.  The vectoring makes this code somewhat larger than it was
-before using vectoring (refer to the LH7A400 implementation).  In the
-case where an interrupt is vectored, the implementation will tend to
-be faster than the non-vectored version.  However, the worst-case path
-is longer.
-
-It is worth noting that at present, there is no need to read
-VIC2_VECTADDR because the register appears to be shared between the
-controllers.  The code is written such that if this changes, it ought
-to still work properly.
-
-
-Vector Addresses
-----------------
-
-The proper use of the vectoring hardware would jump to the ISR
-specified by the vectoring address.  Linux isn't structured to take
-advantage of this feature, though it might be possible to change
-things to support it.
-
-In this implementation, the vectoring address is used to speed the
-search for the active IRQ.  The address is coded such that the lowest
-6 bits store the IRQ number for vectored interrupts.  These numbers
-correspond to the bits in the interrupt status registers.  IRQ zero is
-the lowest interrupt bit in VIC1.  IRQ 32 is the lowest interrupt bit
-in VIC2.  Because zero is a valid IRQ number and because we cannot
-detect whether or not there is a valid vectoring address if that
-address is zero, the eigth bit (0x100) is set for vectored interrupts.
-The address for IRQ 0x18 (VIC2) is 0x118.  Only the ninth bit is set
-for the default handler on VIC1 and only the tenth bit is set for the
-default handler on VIC2.
-
-In other words.
-
-  0x000		- no active interrupt
-  0x1ii		- vectored interrupt 0xii
-  0x2xx		- unvectored interrupt on VIC1 (xx is don't care)
-  0x4xx		- unvectored interrupt on VIC2 (xx is don't care)
-
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/SH-Mobile/Makefile linux-libre-2.6.39-gnu/Documentation/arm/SH-Mobile/Makefile
--- linux-libre-2.6.38-gnu/Documentation/arm/SH-Mobile/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/arm/SH-Mobile/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,8 @@
+BIN := vrl4
+
+.PHONY: all
+all: $(BIN)
+
+.PHONY: clean
+clean:
+	rm -f *.o $(BIN)
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/SH-Mobile/vrl4.c linux-libre-2.6.39-gnu/Documentation/arm/SH-Mobile/vrl4.c
--- linux-libre-2.6.38-gnu/Documentation/arm/SH-Mobile/vrl4.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/arm/SH-Mobile/vrl4.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,169 @@
+/*
+ * vrl4 format generator
+ *
+ * Copyright (C) 2010 Simon Horman
+ *
+ * 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.
+ */
+
+/*
+ * usage: vrl4 < zImage > out
+ *	  dd if=out of=/dev/sdx bs=512 seek=1 # Write the image to sector 1
+ *
+ * Reads a zImage from stdin and writes a vrl4 image to stdout.
+ * In practice this means writing a padded vrl4 header to stdout followed
+ * by the zImage.
+ *
+ * The padding places the zImage at ALIGN bytes into the output.
+ * The vrl4 uses ALIGN + START_BASE as the start_address.
+ * This is where the mask ROM will jump to after verifying the header.
+ *
+ * The header sets copy_size to min(sizeof(zImage), MAX_BOOT_PROG_LEN) + ALIGN.
+ * That is, the mask ROM will load the padded header (ALIGN bytes)
+ * And then MAX_BOOT_PROG_LEN bytes of the image, or the entire image,
+ * whichever is smaller.
+ *
+ * The zImage is not modified in any way.
+ */
+
+#define _BSD_SOURCE
+#include <endian.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <errno.h>
+
+struct hdr {
+	uint32_t magic1;
+	uint32_t reserved1;
+	uint32_t magic2;
+	uint32_t reserved2;
+	uint16_t copy_size;
+	uint16_t boot_options;
+	uint32_t reserved3;
+	uint32_t start_address;
+	uint32_t reserved4;
+	uint32_t reserved5;
+	char     reserved6[308];
+};
+
+#define DECLARE_HDR(h)					\
+	struct hdr (h) = {				\
+		.magic1 =	htole32(0xea000000),	\
+		.reserved1 =	htole32(0x56),		\
+		.magic2 =	htole32(0xe59ff008),	\
+		.reserved3 =	htole16(0x1) }
+
+/* Align to 512 bytes, the MMCIF sector size */
+#define ALIGN_BITS	9
+#define ALIGN		(1 << ALIGN_BITS)
+
+#define START_BASE	0xe55b0000
+
+/*
+ * With an alignment of 512 the header uses the first sector.
+ * There is a 128 sector (64kbyte) limit on the data loaded by the mask ROM.
+ * So there are 127 sectors left for the boot programme. But in practice
+ * Only a small portion of a zImage is needed, 16 sectors should be more
+ * than enough.
+ *
+ * Note that this sets how much of the zImage is copied by the mask ROM.
+ * The entire zImage is present after the header and is loaded
+ * by the code in the boot program (which is the first portion of the zImage).
+ */
+#define	MAX_BOOT_PROG_LEN (16 * 512)
+
+#define ROUND_UP(x)	((x + ALIGN - 1) & ~(ALIGN - 1))
+
+ssize_t do_read(int fd, void *buf, size_t count)
+{
+	size_t offset = 0;
+	ssize_t l;
+
+	while (offset < count) {
+		l = read(fd, buf + offset, count - offset);
+		if (!l)
+			break;
+		if (l < 0) {
+			if (errno == EAGAIN || errno == EWOULDBLOCK)
+				continue;
+			perror("read");
+			return -1;
+		}
+		offset += l;
+	}
+
+	return offset;
+}
+
+ssize_t do_write(int fd, const void *buf, size_t count)
+{
+	size_t offset = 0;
+	ssize_t l;
+
+	while (offset < count) {
+		l = write(fd, buf + offset, count - offset);
+		if (l < 0) {
+			if (errno == EAGAIN || errno == EWOULDBLOCK)
+				continue;
+			perror("write");
+			return -1;
+		}
+		offset += l;
+	}
+
+	return offset;
+}
+
+ssize_t write_zero(int fd, size_t len)
+{
+	size_t i = len;
+
+	while (i--) {
+		const char x = 0;
+		if (do_write(fd, &x, 1) < 0)
+			return -1;
+	}
+
+	return len;
+}
+
+int main(void)
+{
+	DECLARE_HDR(hdr);
+	char boot_program[MAX_BOOT_PROG_LEN];
+	size_t aligned_hdr_len, alligned_prog_len;
+	ssize_t prog_len;
+
+	prog_len = do_read(0, boot_program, sizeof(boot_program));
+	if (prog_len <= 0)
+		return -1;
+
+	aligned_hdr_len = ROUND_UP(sizeof(hdr));
+	hdr.start_address = htole32(START_BASE + aligned_hdr_len);
+	alligned_prog_len = ROUND_UP(prog_len);
+	hdr.copy_size = htole16(aligned_hdr_len + alligned_prog_len);
+
+	if (do_write(1, &hdr, sizeof(hdr)) < 0)
+		return -1;
+	if (write_zero(1, aligned_hdr_len - sizeof(hdr)) < 0)
+		return -1;
+
+	if (do_write(1, boot_program, prog_len) < 0)
+		return 1;
+
+	/* Write out the rest of the kernel */
+	while (1) {
+		prog_len = do_read(0, boot_program, sizeof(boot_program));
+		if (prog_len < 0)
+			return 1;
+		if (prog_len == 0)
+			break;
+		if (do_write(1, boot_program, prog_len) < 0)
+			return 1;
+	}
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt linux-libre-2.6.39-gnu/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt
--- linux-libre-2.6.38-gnu/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/arm/SH-Mobile/zboot-rom-mmcif.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29 @@
+ROM-able zImage boot from MMC
+-----------------------------
+
+An ROM-able zImage compiled with ZBOOT_ROM_MMCIF may be written to MMC and
+SuperH Mobile ARM will to boot directly from the MMCIF hardware block.
+
+This is achieved by the mask ROM loading the first portion of the image into
+MERAM and then jumping to it. This portion contains loader code which
+copies the entire image to SDRAM and jumps to it. From there the zImage
+boot code proceeds as normal, uncompressing the image into its final
+location and then jumping to it.
+
+This code has been tested on an AP4EB board using the developer 1A eMMC
+boot mode which is configured using the following jumper settings.
+The board used for testing required a patched mask ROM in order for
+this mode to function.
+
+   8 7 6 5 4 3 2 1
+   x|x|x|x|x| |x|
+S4 -+-+-+-+-+-+-+-
+    | | | | |x| |x on
+
+The zImage must be written to the MMC card at sector 1 (512 bytes) in
+vrl4 format. A utility vrl4 is supplied to accomplish this.
+
+e.g.
+	vrl4 < zImage | dd of=/dev/sdX bs=512 seek=1
+
+A dual-voltage MMC 4.0 card was used for testing.
diff -druN linux-libre-2.6.38-gnu/Documentation/block/biodoc.txt linux-libre-2.6.39-gnu/Documentation/block/biodoc.txt
--- linux-libre-2.6.38-gnu/Documentation/block/biodoc.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/block/biodoc.txt	2011-05-19 00:06:34.000000000 -0400
@@ -497,7 +497,7 @@
 entries with their corresponding dma address mappings filled in at the
 appropriate time. As an optimization, contiguous physical pages can be
 covered by a single entry where <page> refers to the first page and <len>
-covers the range of pages (upto 16 contiguous pages could be covered this
+covers the range of pages (up to 16 contiguous pages could be covered this
 way). There is a helper routine (blk_rq_map_sg) which drivers can use to build
 the sg list.
 
@@ -565,7 +565,7 @@
 	.
 	int tag;	/* command tag associated with request */
 	void *special;  /* same as before */
-	char *buffer;   /* valid only for low memory buffers upto
+	char *buffer;   /* valid only for low memory buffers up to
 			 current_nr_sectors */
 	.
 	.
@@ -963,11 +963,6 @@
 
 elevator_add_req_fn*		called to add a new request into the scheduler
 
-elevator_queue_empty_fn		returns true if the merge queue is empty.
-				Drivers shouldn't use this, but rather check
-				if elv_next_request is NULL (without losing the
-				request if one exists!)
-
 elevator_former_req_fn
 elevator_latter_req_fn		These return the request before or after the
 				one specified in disk sort order. Used by the
diff -druN linux-libre-2.6.38-gnu/Documentation/cgroups/blkio-controller.txt linux-libre-2.6.39-gnu/Documentation/cgroups/blkio-controller.txt
--- linux-libre-2.6.38-gnu/Documentation/cgroups/blkio-controller.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/cgroups/blkio-controller.txt	2011-05-19 00:06:34.000000000 -0400
@@ -140,7 +140,7 @@
 	- Specifies per cgroup weight. This is default weight of the group
 	  on all the devices until and unless overridden by per device rule.
 	  (See blkio.weight_device).
-	  Currently allowed range of weights is from 100 to 1000.
+	  Currently allowed range of weights is from 10 to 1000.
 
 - blkio.weight_device
 	- One can specify per cgroup per device rules using this interface.
@@ -343,34 +343,6 @@
 
 CFQ sysfs tunable
 =================
-/sys/block/<disk>/queue/iosched/group_isolation
------------------------------------------------
-
-If group_isolation=1, it provides stronger isolation between groups at the
-expense of throughput. By default group_isolation is 0. In general that
-means that if group_isolation=0, expect fairness for sequential workload
-only. Set group_isolation=1 to see fairness for random IO workload also.
-
-Generally CFQ will put random seeky workload in sync-noidle category. CFQ
-will disable idling on these queues and it does a collective idling on group
-of such queues. Generally these are slow moving queues and if there is a
-sync-noidle service tree in each group, that group gets exclusive access to
-disk for certain period. That means it will bring the throughput down if
-group does not have enough IO to drive deeper queue depths and utilize disk
-capacity to the fullest in the slice allocated to it. But the flip side is
-that even a random reader should get better latencies and overall throughput
-if there are lots of sequential readers/sync-idle workload running in the
-system.
-
-If group_isolation=0, then CFQ automatically moves all the random seeky queues
-in the root group. That means there will be no service differentiation for
-that kind of workload. This leads to better throughput as we do collective
-idling on root sync-noidle tree.
-
-By default one should run with group_isolation=0. If that is not sufficient
-and one wants stronger isolation between groups, then set group_isolation=1
-but this will come at cost of reduced throughput.
-
 /sys/block/<disk>/queue/iosched/slice_idle
 ------------------------------------------
 On a faster hardware CFQ can be slow, especially with sequential workload.
diff -druN linux-libre-2.6.38-gnu/Documentation/cgroups/cgroups.txt linux-libre-2.6.39-gnu/Documentation/cgroups/cgroups.txt
--- linux-libre-2.6.38-gnu/Documentation/cgroups/cgroups.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/cgroups/cgroups.txt	2011-05-19 00:06:34.000000000 -0400
@@ -110,22 +110,22 @@
 tasks etc. The resource planning for this server could be along the
 following lines:
 
-       CPU :           Top cpuset
+       CPU :          "Top cpuset"
                        /       \
                CPUSet1         CPUSet2
-                  |              |
-               (Profs)         (Students)
+                  |               |
+               (Professors)    (Students)
 
                In addition (system tasks) are attached to topcpuset (so
                that they can run anywhere) with a limit of 20%
 
-       Memory : Professors (50%), students (30%), system (20%)
+       Memory : Professors (50%), Students (30%), system (20%)
 
-       Disk : Prof (50%), students (30%), system (20%)
+       Disk : Professors (50%), Students (30%), system (20%)
 
        Network : WWW browsing (20%), Network File System (60%), others (20%)
                                / \
-                       Prof (15%) students (5%)
+               Professors (15%)  students (5%)
 
 Browsers like Firefox/Lynx go into the WWW network class, while (k)nfsd go
 into NFS network class.
@@ -349,6 +349,10 @@
 The "xxx" is not interpreted by the cgroup code, but will appear in
 /proc/mounts so may be any useful identifying string that you like.
 
+Note: Some subsystems do not work without some user input first.  For instance,
+if cpusets are enabled the user will have to populate the cpus and mems files
+for each new cgroup created before that group can be used.
+
 To mount a cgroup hierarchy with just the cpuset and memory
 subsystems, type:
 # mount -t cgroup -o cpuset,memory hier1 /dev/cgroup
@@ -426,6 +430,14 @@
 
 # echo 0 > tasks
 
+Note: Since every task is always a member of exactly one cgroup in each
+mounted hierarchy, to remove a task from its current cgroup you must
+move it into a new cgroup (possibly the root cgroup) by writing to the
+new cgroup's tasks file.
+
+Note: If the ns cgroup is active, moving a process to another cgroup can
+fail.
+
 2.3 Mounting hierarchies by name
 --------------------------------
 
diff -druN linux-libre-2.6.38-gnu/Documentation/cgroups/cpusets.txt linux-libre-2.6.39-gnu/Documentation/cgroups/cpusets.txt
--- linux-libre-2.6.38-gnu/Documentation/cgroups/cpusets.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/cgroups/cpusets.txt	2011-05-19 00:06:34.000000000 -0400
@@ -693,7 +693,7 @@
  - via the C library libcgroup.
    (http://sourceforge.net/projects/libcg/)
  - via the python application cset.
-   (http://developer.novell.com/wiki/index.php/Cpuset)
+   (http://code.google.com/p/cpuset/)
 
 The sched_setaffinity calls can also be done at the shell prompt using
 SGI's runon or Robert Love's taskset.  The mbind and set_mempolicy
@@ -725,13 +725,14 @@
 
 In this directory you can find several files:
 # ls
-cpuset.cpu_exclusive       cpuset.memory_spread_slab
-cpuset.cpus                cpuset.mems
-cpuset.mem_exclusive       cpuset.sched_load_balance
-cpuset.mem_hardwall        cpuset.sched_relax_domain_level
-cpuset.memory_migrate      notify_on_release
-cpuset.memory_pressure     tasks
-cpuset.memory_spread_page
+cgroup.clone_children  cpuset.memory_pressure
+cgroup.event_control   cpuset.memory_spread_page
+cgroup.procs           cpuset.memory_spread_slab
+cpuset.cpu_exclusive   cpuset.mems
+cpuset.cpus            cpuset.sched_load_balance
+cpuset.mem_exclusive   cpuset.sched_relax_domain_level
+cpuset.mem_hardwall    notify_on_release
+cpuset.memory_migrate  tasks
 
 Reading them will give you information about the state of this cpuset:
 the CPUs and Memory Nodes it can use, the processes that are using
diff -druN linux-libre-2.6.38-gnu/Documentation/cgroups/memory.txt linux-libre-2.6.39-gnu/Documentation/cgroups/memory.txt
--- linux-libre-2.6.38-gnu/Documentation/cgroups/memory.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/cgroups/memory.txt	2011-05-19 00:06:34.000000000 -0400
@@ -52,8 +52,10 @@
  tasks				 # attach a task(thread) and show list of threads
  cgroup.procs			 # show list of processes
  cgroup.event_control		 # an interface for event_fd()
- memory.usage_in_bytes		 # show current memory(RSS+Cache) usage.
- memory.memsw.usage_in_bytes	 # show current memory+Swap usage
+ memory.usage_in_bytes		 # show current res_counter usage for memory
+				 (See 5.5 for details)
+ memory.memsw.usage_in_bytes	 # show current res_counter usage for memory+Swap
+				 (See 5.5 for details)
  memory.limit_in_bytes		 # set/show limit of memory usage
  memory.memsw.limit_in_bytes	 # set/show limit of memory+Swap usage
  memory.failcnt			 # show the number of memory usage hits limits
@@ -453,6 +455,15 @@
 You can reset failcnt by writing 0 to failcnt file.
 # echo 0 > .../memory.failcnt
 
+5.5 usage_in_bytes
+
+For efficiency, as other kernel components, memory cgroup uses some optimization
+to avoid unnecessary cacheline false sharing. usage_in_bytes is affected by the
+method and doesn't show 'exact' value of memory(and swap) usage, it's an fuzz
+value for efficient access. (Of course, when necessary, it's synchronized.)
+If you want to know more exact memory usage, you should use RSS+CACHE(+SWAP)
+value in memory.stat(see 5.2).
+
 6. Hierarchy support
 
 The memory controller supports a deep hierarchy and hierarchical accounting.
@@ -485,8 +496,9 @@
 
 # echo 0 > memory.use_hierarchy
 
-NOTE1: Enabling/disabling will fail if the cgroup already has other
-       cgroups created below it.
+NOTE1: Enabling/disabling will fail if either the cgroup already has other
+       cgroups created below it, or if the parent cgroup has use_hierarchy
+       enabled.
 
 NOTE2: When panic_on_oom is set to "2", the whole system will panic in
        case of an OOM event in any cgroup.
diff -druN linux-libre-2.6.38-gnu/Documentation/Changes linux-libre-2.6.39-gnu/Documentation/Changes
--- linux-libre-2.6.38-gnu/Documentation/Changes	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/Changes	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 o  module-init-tools      0.9.10                  # depmod -V
 o  e2fsprogs              1.41.4                  # e2fsck -V
 o  jfsutils               1.1.3                   # fsck.jfs -V
-o  reiserfsprogs          3.6.3                   # reiserfsck -V 2>&1|grep reiserfsprogs
+o  reiserfsprogs          3.6.3                   # reiserfsck -V
 o  xfsprogs               2.6.0                   # xfs_db -V
 o  squashfs-tools         4.0                     # mksquashfs -version
 o  btrfs-progs            0.18                    # btrfsck
@@ -46,9 +46,9 @@
 o  nfs-utils              1.0.5                   # showmount --version
 o  procps                 3.2.0                   # ps --version
 o  oprofile               0.9                     # oprofiled --version
-o  udev                   081                     # udevinfo -V
-o  grub                   0.93                    # grub --version
-o  mcelog		  0.6
+o  udev                   081                     # udevd --version
+o  grub                   0.93                    # grub --version || grub-install --version
+o  mcelog                 0.6                     # mcelog --version
 o  iptables               1.4.2                   # iptables -V
 
 
diff -druN linux-libre-2.6.38-gnu/Documentation/CodingStyle linux-libre-2.6.39-gnu/Documentation/CodingStyle
--- linux-libre-2.6.38-gnu/Documentation/CodingStyle	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/CodingStyle	2011-05-19 00:06:34.000000000 -0400
@@ -168,6 +168,13 @@
 if (condition)
 	action();
 
+and
+
+if (condition)
+	do_this();
+else
+	do_that();
+
 This does not apply if one branch of a conditional statement is a single
 statement. Use braces in both branches.
 
@@ -659,7 +666,7 @@
 which you should use to make sure messages are matched to the right device
 and driver, and are tagged with the right level:  dev_err(), dev_warn(),
 dev_info(), and so forth.  For messages that aren't associated with a
-particular device, <linux/kernel.h> defines pr_debug() and pr_info().
+particular device, <linux/printk.h> defines pr_debug() and pr_info().
 
 Coming up with good debugging messages can be quite a challenge; and once
 you have them, they can be a huge help for remote troubleshooting.  Such
@@ -819,6 +826,3 @@
 Kernel CodingStyle, by greg@kroah.com at OLS 2002:
 http://www.kroah.com/linux/talks/ols_2002_kernel_codingstyle_talk/html/
 
---
-Last updated on 2007-July-13.
-
diff -druN linux-libre-2.6.38-gnu/Documentation/cpu-freq/governors.txt linux-libre-2.6.39-gnu/Documentation/cpu-freq/governors.txt
--- linux-libre-2.6.38-gnu/Documentation/cpu-freq/governors.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/cpu-freq/governors.txt	2011-05-19 00:06:34.000000000 -0400
@@ -158,6 +158,17 @@
 takes to complete as you can 'nice' it and prevent it from taking part
 in the deciding process of whether to increase your CPU frequency.
 
+sampling_down_factor: this parameter controls the rate at which the
+kernel makes a decision on when to decrease the frequency while running
+at top speed. When set to 1 (the default) decisions to reevaluate load
+are made at the same interval regardless of current clock speed. But
+when set to greater than 1 (e.g. 100) it acts as a multiplier for the
+scheduling interval for reevaluating load when the CPU is at its top
+speed due to high load. This improves performance by reducing the overhead
+of load evaluation and helping the CPU stay at its top speed when truly
+busy, rather than shifting back and forth in speed. This tunable has no
+effect on behavior at lower speeds/lower CPU loads.
+
 
 2.5 Conservative
 ----------------
diff -druN linux-libre-2.6.38-gnu/Documentation/cpu-hotplug.txt linux-libre-2.6.39-gnu/Documentation/cpu-hotplug.txt
--- linux-libre-2.6.38-gnu/Documentation/cpu-hotplug.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/cpu-hotplug.txt	2011-05-19 00:06:34.000000000 -0400
@@ -196,7 +196,7 @@
 	#To display the current cpu state.
 	#cat /sys/devices/system/cpu/cpuX/online
 
-Q: Why cant i remove CPU0 on some systems?
+Q: Why can't i remove CPU0 on some systems?
 A: Some architectures may have some special dependency on a certain CPU.
 
 For e.g in IA64 platforms we have ability to sent platform interrupts to the
diff -druN linux-libre-2.6.38-gnu/Documentation/dell_rbu.txt linux-libre-2.6.39-gnu/Documentation/dell_rbu.txt
--- linux-libre-2.6.38-gnu/Documentation/dell_rbu.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/dell_rbu.txt	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 file.
 This file is then copied to /sys/class/firmware/dell_rbu/data.
 Once this file gets to the driver, the driver extracts packet_size data from
-the file and spreads it accross the physical memory in contiguous packet_sized
+the file and spreads it across the physical memory in contiguous packet_sized
 space.
 This method makes sure that all the packets get to the driver in a single operation.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/1.Intro linux-libre-2.6.39-gnu/Documentation/development-process/1.Intro
--- linux-libre-2.6.38-gnu/Documentation/development-process/1.Intro	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/1.Intro	2011-05-19 00:06:34.000000000 -0400
@@ -56,13 +56,13 @@
 
 1.2: WHAT THIS DOCUMENT IS ABOUT
 
-The Linux kernel, at over 6 million lines of code and well over 1000 active
-contributors, is one of the largest and most active free software projects
-in existence.  Since its humble beginning in 1991, this kernel has evolved
-into a best-of-breed operating system component which runs on pocket-sized
-digital music players, desktop PCs, the largest supercomputers in
-existence, and all types of systems in between.  It is a robust, efficient,
-and scalable solution for almost any situation.
+The Linux kernel, at over 8 million lines of code and well over 1000
+contributors to each release, is one of the largest and most active free
+software projects in existence.  Since its humble beginning in 1991, this
+kernel has evolved into a best-of-breed operating system component which
+runs on pocket-sized digital music players, desktop PCs, the largest
+supercomputers in existence, and all types of systems in between.  It is a
+robust, efficient, and scalable solution for almost any situation.
 
 With the growth of Linux has come an increase in the number of developers
 (and companies) wishing to participate in its development.  Hardware
@@ -115,7 +115,7 @@
 improved by comments from Johannes Berg, James Berry, Alex Chiang, Roland
 Dreier, Randy Dunlap, Jake Edge, Jiri Kosina, Matt Mackall, Arthur Marsh,
 Amanda McPherson, Andrew Morton, Andrew Price, Tsugikazu Shibata, and
-Jochen VoÃŸ. 
+Jochen VoÃŸ.
 
 This work was supported by the Linux Foundation; thanks especially to
 Amanda McPherson, who saw the value of this effort and made it all happen.
@@ -221,7 +221,7 @@
 - Everything that was said above about code review applies doubly to
   closed-source code.  Since this code is not available at all, it cannot
   have been reviewed by the community and will, beyond doubt, have serious
-  problems. 
+  problems.
 
 Makers of embedded systems, in particular, may be tempted to disregard much
 of what has been said in this section in the belief that they are shipping
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/2.Process linux-libre-2.6.39-gnu/Documentation/development-process/2.Process
--- linux-libre-2.6.38-gnu/Documentation/development-process/2.Process	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/2.Process	2011-05-19 00:06:34.000000000 -0400
@@ -14,16 +14,15 @@
 major kernel release happening every two or three months.  The recent
 release history looks like this:
 
-	2.6.26	July 13, 2008
-	2.6.25	April 16, 2008
-	2.6.24	January 24, 2008
-	2.6.23	October 9, 2007
-	2.6.22	July 8, 2007
-	2.6.21	April 25, 2007
-	2.6.20	February 4, 2007
+	2.6.38	March 14, 2011
+	2.6.37	January 4, 2011
+	2.6.36	October 20, 2010
+	2.6.35	August 1, 2010
+	2.6.34	May 15, 2010
+	2.6.33	February 24, 2010
 
 Every 2.6.x release is a major kernel release with new features, internal
-API changes, and more.  A typical 2.6 release can contain over 10,000
+API changes, and more.  A typical 2.6 release can contain nearly 10,000
 changesets with changes to several hundred thousand lines of code.  2.6 is
 thus the leading edge of Linux kernel development; the kernel uses a
 rolling development model which is continually integrating major changes.
@@ -42,13 +41,13 @@
 and staged ahead of time.  How that process works will be described in
 detail later on).
 
-The merge window lasts for two weeks.  At the end of this time, Linus
-Torvalds will declare that the window is closed and release the first of
-the "rc" kernels.  For the kernel which is destined to be 2.6.26, for
-example, the release which happens at the end of the merge window will be
-called 2.6.26-rc1.  The -rc1 release is the signal that the time to merge
-new features has passed, and that the time to stabilize the next kernel has
-begun.
+The merge window lasts for approximately two weeks.  At the end of this
+time, Linus Torvalds will declare that the window is closed and release the
+first of the "rc" kernels.  For the kernel which is destined to be 2.6.40,
+for example, the release which happens at the end of the merge window will
+be called 2.6.40-rc1.  The -rc1 release is the signal that the time to
+merge new features has passed, and that the time to stabilize the next
+kernel has begun.
 
 Over the next six to ten weeks, only patches which fix problems should be
 submitted to the mainline.  On occasion a more significant change will be
@@ -66,20 +65,19 @@
 considered to be sufficiently stable and the final 2.6.x release is made.
 At that point the whole process starts over again.
 
-As an example, here is how the 2.6.25 development cycle went (all dates in
-2008): 
+As an example, here is how the 2.6.38 development cycle went (all dates in
+2011):
 
-	January 24	2.6.24 stable release
-	February 10	2.6.25-rc1, merge window closes
-	February 15	2.6.25-rc2
-	February 24	2.6.25-rc3
-	March 4	 	2.6.25-rc4
-	March 9		2.6.25-rc5
-	March 16	2.6.25-rc6
-	March 25	2.6.25-rc7
-	April 1		2.6.25-rc8
-	April 11	2.6.25-rc9
-	April 16	2.6.25 stable release
+	January 4	2.6.37 stable release
+	January 18	2.6.38-rc1, merge window closes
+	January 21	2.6.38-rc2
+	February 1	2.6.38-rc3
+	February 7	2.6.38-rc4
+	February 15	2.6.38-rc5
+	February 21	2.6.38-rc6
+	March 1		2.6.38-rc7
+	March 7		2.6.38-rc8
+	March 14	2.6.38 stable release
 
 How do the developers decide when to close the development cycle and create
 the stable release?  The most significant metric used is the list of
@@ -87,7 +85,7 @@
 break systems which worked in the past are considered to be especially
 serious.  For this reason, patches which cause regressions are looked upon
 unfavorably and are quite likely to be reverted during the stabilization
-period. 
+period.
 
 The developers' goal is to fix all known regressions before the stable
 release is made.  In the real world, this kind of perfection is hard to
@@ -99,26 +97,34 @@
 of them are serious.
 
 Once a stable release is made, its ongoing maintenance is passed off to the
-"stable team," currently comprised of Greg Kroah-Hartman and Chris Wright.
-The stable team will release occasional updates to the stable release using
-the 2.6.x.y numbering scheme.  To be considered for an update release, a
-patch must (1) fix a significant bug, and (2) already be merged into the
-mainline for the next development kernel.  Continuing our 2.6.25 example,
-the history (as of this writing) is:
+"stable team," currently consisting of Greg Kroah-Hartman.  The stable team
+will release occasional updates to the stable release using the 2.6.x.y
+numbering scheme.  To be considered for an update release, a patch must (1)
+fix a significant bug, and (2) already be merged into the mainline for the
+next development kernel.  Kernels will typically receive stable updates for
+a little more than one development cycle past their initial release.  So,
+for example, the 2.6.36 kernel's history looked like:
 
-	May 1		2.6.25.1
-	May 6		2.6.25.2 
-	May 9		2.6.25.3 
-	May 15		2.6.25.4
-	June 7		2.6.25.5
-	June 9		2.6.25.6
-	June 16		2.6.25.7
-	June 21		2.6.25.8
-	June 24		2.6.25.9
+	October 10	2.6.36 stable release
+	November 22	2.6.36.1
+	December 9	2.6.36.2
+	January 7	2.6.36.3
+	February 17	2.6.36.4
 
-Stable updates for a given kernel are made for approximately six months;
-after that, the maintenance of stable releases is solely the responsibility
-of the distributors which have shipped that particular kernel.
+2.6.36.4 was the final stable update for the 2.6.36 release.
+
+Some kernels are designated "long term" kernels; they will receive support
+for a longer period.  As of this writing, the current long term kernels
+and their maintainers are:
+
+	2.6.27	Willy Tarreau		(Deep-frozen stable kernel)
+	2.6.32	Greg Kroah-Hartman
+	2.6.35	Andi Kleen		(Embedded flag kernel)
+
+The selection of a kernel for long-term support is purely a matter of a
+maintainer having the need and the time to maintain that release.  There
+are no known plans for long-term support for any specific upcoming
+release.
 
 
 2.2: THE LIFECYCLE OF A PATCH
@@ -130,7 +136,7 @@
 This process can happen quickly for minor fixes, or, in the case of large
 and controversial changes, go on for years.  Much developer frustration
 comes from a lack of understanding of this process or from attempts to
-circumvent it.  
+circumvent it.
 
 In the hopes of reducing that frustration, this document will describe how
 a patch gets into the kernel.  What follows below is an introduction which
@@ -193,8 +199,8 @@
 2.3: HOW PATCHES GET INTO THE KERNEL
 
 There is exactly one person who can merge patches into the mainline kernel
-repository: Linus Torvalds.  But, of the over 12,000 patches which went
-into the 2.6.25 kernel, only 250 (around 2%) were directly chosen by Linus
+repository: Linus Torvalds.  But, of the over 9,500 patches which went
+into the 2.6.38 kernel, only 112 (around 1.3%) were directly chosen by Linus
 himself.  The kernel project has long since grown to a size where no single
 developer could possibly inspect and select every patch unassisted.  The
 way the kernel developers have addressed this growth is through the use of
@@ -229,7 +235,7 @@
 etc.  This chain of repositories can be arbitrarily long, though it rarely
 exceeds two or three links.  Since each maintainer in the chain trusts
 those managing lower-level trees, this process is known as the "chain of
-trust." 
+trust."
 
 Clearly, in a system like this, getting patches into the kernel depends on
 finding the right maintainer.  Sending patches directly to Linus is not
@@ -254,7 +260,7 @@
 collected for testing and review.  The older of these trees, maintained by
 Andrew Morton, is called "-mm" (for memory management, which is how it got
 started).  The -mm tree integrates patches from a long list of subsystem
-trees; it also has some patches aimed at helping with debugging.  
+trees; it also has some patches aimed at helping with debugging.
 
 Beyond that, -mm contains a significant collection of patches which have
 been selected by Andrew directly.  These patches may have been posted on a
@@ -264,8 +270,8 @@
 patch into the mainline, it is likely to end up in -mm.  Miscellaneous
 patches which accumulate in -mm will eventually either be forwarded on to
 an appropriate subsystem tree or be sent directly to Linus.  In a typical
-development cycle, approximately 10% of the patches going into the mainline
-get there via -mm.
+development cycle, approximately 5-10% of the patches going into the
+mainline get there via -mm.
 
 The current -mm patch is available in the "mmotm" (-mm of the moment)
 directory at:
@@ -275,7 +281,7 @@
 Use of the MMOTM tree is likely to be a frustrating experience, though;
 there is a definite chance that it will not even compile.
 
-The other -next tree, started more recently, is linux-next, maintained by
+The primary tree for next-cycle patch merging is linux-next, maintained by
 Stephen Rothwell.  The linux-next tree is, by design, a snapshot of what
 the mainline is expected to look like after the next merge window closes.
 Linux-next trees are announced on the linux-kernel and linux-next mailing
@@ -287,25 +293,14 @@
 
 	http://linux.f-seidel.de/linux-next/pmwiki/
 
-How the linux-next tree will fit into the development process is still
-changing.  As of this writing, the first full development cycle involving
-linux-next (2.6.26) is coming to an end; thus far, it has proved to be a
-valuable resource for finding and fixing integration problems before the
-beginning of the merge window.  See http://lwn.net/Articles/287155/ for
-more information on how linux-next has worked to set up the 2.6.27 merge
-window.
+Linux-next has become an integral part of the kernel development process;
+all patches merged during a given merge window should really have found
+their way into linux-next some time before the merge window opens.
 
-Some developers have begun to suggest that linux-next should be used as the
-target for future development as well.  The linux-next tree does tend to be
-far ahead of the mainline and is more representative of the tree into which
-any new work will be merged.  The downside to this idea is that the
-volatility of linux-next tends to make it a difficult development target.
-See http://lwn.net/Articles/289013/ for more information on this topic, and
-stay tuned; much is still in flux where linux-next is involved.
 
 2.4.1: STAGING TREES
 
-The kernel source tree now contains the drivers/staging/ directory, where
+The kernel source tree contains the drivers/staging/ directory, where
 many sub-directories for drivers or filesystems that are on their way to
 being added to the kernel tree live.  They remain in drivers/staging while
 they still need more work; once complete, they can be moved into the
@@ -313,15 +308,23 @@
 up to Linux kernel coding or quality standards, but people may want to use
 them and track development.
 
-Greg Kroah-Hartman currently (as of 2.6.36) maintains the staging tree.
-Drivers that still need work are sent to him, with each driver having
-its own subdirectory in drivers/staging/.  Along with the driver source
-files, a TODO file should be present in the directory as well.  The TODO
-file lists the pending work that the driver needs for acceptance into
-the kernel proper, as well as a list of people that should be Cc'd for any
-patches to the driver.  Staging drivers that don't currently build should
-have their config entries depend upon CONFIG_BROKEN.  Once they can
-be successfully built without outside patches, CONFIG_BROKEN can be removed.
+Greg Kroah-Hartman currently maintains the staging tree.  Drivers that
+still need work are sent to him, with each driver having its own
+subdirectory in drivers/staging/.  Along with the driver source files, a
+TODO file should be present in the directory as well.  The TODO file lists
+the pending work that the driver needs for acceptance into the kernel
+proper, as well as a list of people that should be Cc'd for any patches to
+the driver.  Current rules require that drivers contributed to staging
+must, at a minimum, compile properly.
+
+Staging can be a relatively easy way to get new drivers into the mainline
+where, with luck, they will come to the attention of other developers and
+improve quickly.  Entry into staging is not the end of the story, though;
+code in staging which is not seeing regular progress will eventually be
+removed.  Distributors also tend to be relatively reluctant to enable
+staging drivers.  So staging is, at best, a stop on the way toward becoming
+a proper mainline driver.
+
 
 2.5: TOOLS
 
@@ -347,11 +350,7 @@
 
 	http://git-scm.com/
 
-That page has pointers to documentation and tutorials.  One should be
-aware, in particular, of the Kernel Hacker's Guide to git, which has
-information specific to kernel development:
-
-	http://linux.yyz.us/git-howto.html
+That page has pointers to documentation and tutorials.
 
 Among the kernel developers who do not use git, the most popular choice is
 almost certainly Mercurial:
@@ -408,7 +407,7 @@
   important to filter on both the topic of interest (though note that
   long-running conversations can drift away from the original subject
   without changing the email subject line) and the people who are
-  participating.  
+  participating.
 
 - Do not feed the trolls.  If somebody is trying to stir up an angry
   response, ignore them.
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/3.Early-stage linux-libre-2.6.39-gnu/Documentation/development-process/3.Early-stage
--- linux-libre-2.6.38-gnu/Documentation/development-process/3.Early-stage	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/3.Early-stage	2011-05-19 00:06:34.000000000 -0400
@@ -110,8 +110,8 @@
 
  - The AppArmor security module made use of internal virtual filesystem
    data structures in ways which were considered to be unsafe and
-   unreliable.  This code has since been significantly reworked, but
-   remains outside of the mainline.
+   unreliable.  This concern (among others) kept AppArmor out of the
+   mainline for years.
 
 In each of these cases, a great deal of pain and extra work could have been
 avoided with some early discussion with the kernel developers.
@@ -138,6 +138,19 @@
 patches.  Those are the people who will be best placed to help with a new
 development project.
 
+The task of finding the right maintainer is sometimes challenging enough
+that the kernel developers have added a script to ease the process:
+
+	.../scripts/get_maintainer.pl
+
+This script will return the current maintainer(s) for a given file or
+directory when given the "-f" option.  If passed a patch on the
+command line, it will list the maintainers who should probably receive
+copies of the patch.  There are a number of options regulating how hard
+get_maintainer.pl will search for maintainers; please be careful about
+using the more aggressive options as you may end up including developers
+who have no real interest in the code you are modifying.
+
 If all else fails, talking to Andrew Morton can be an effective way to
 track down a maintainer for a specific piece of code.
 
@@ -155,11 +168,15 @@
 matter is (1) kernel developers tend to be busy, (2) there is no shortage
 of people with grand plans and little code (or even prospect of code) to
 back them up, and (3) nobody is obligated to review or comment on ideas
-posted by others.  If a request-for-comments posting yields little in the
-way of comments, do not assume that it means there is no interest in the
-project.  Unfortunately, you also cannot assume that there are no problems
-with your idea.  The best thing to do in this situation is to proceed,
-keeping the community informed as you go.
+posted by others.  Beyond that, high-level designs often hide problems
+which are only reviewed when somebody actually tries to implement those
+designs; for that reason, kernel developers would rather see the code.
+
+If a request-for-comments posting yields little in the way of comments, do
+not assume that it means there is no interest in the project.
+Unfortunately, you also cannot assume that there are no problems with your
+idea.  The best thing to do in this situation is to proceed, keeping the
+community informed as you go.
 
 
 3.5: GETTING OFFICIAL BUY-IN
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/4.Coding linux-libre-2.6.39-gnu/Documentation/development-process/4.Coding
--- linux-libre-2.6.38-gnu/Documentation/development-process/4.Coding	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/4.Coding	2011-05-19 00:06:34.000000000 -0400
@@ -131,6 +131,11 @@
 often does not apply to contemporary hardware.  Space *is* time, in that a
 larger program will run slower than one which is more compact.
 
+More recent compilers take an increasingly active role in deciding whether
+a given function should actually be inlined or not.  So the liberal
+placement of "inline" keywords may not just be excessive; it could also be
+irrelevant.
+
 
 * Locking
 
@@ -285,6 +290,13 @@
 distributor does not package it); it can then be run on the code by adding
 "C=1" to your make command.
 
+The "Coccinelle" tool (http://coccinelle.lip6.fr/) is able to find a wide
+variety of potential coding problems; it can also propose fixes for those
+problems.  Quite a few "semantic patches" for the kernel have been packaged
+under the scripts/coccinelle directory; running "make coccicheck" will run
+through those semantic patches and report on any problems found.  See
+Documentation/coccinelle.txt for more information.
+
 Other kinds of portability errors are best found by compiling your code for
 other architectures.  If you do not happen to have an S/390 system or a
 Blackfin development board handy, you can still perform the compilation
@@ -308,7 +320,9 @@
 changelog.  Log entries should describe the problem being solved, the form
 of the solution, the people who worked on the patch, any relevant
 effects on performance, and anything else that might be needed to
-understand the patch.
+understand the patch.  Be sure that the changelog says *why* the patch is
+worth applying; a surprising number of developers fail to provide that
+information.
 
 Any code which adds a new user-space interface - including new sysfs or
 /proc files - should include documentation of that interface which enables
@@ -321,7 +335,7 @@
 appropriate entries to this file.
 
 Any new configuration options must be accompanied by help text which
-clearly explains the options and when the user might want to select them. 
+clearly explains the options and when the user might want to select them.
 
 Internal API information for many subsystems is documented by way of
 specially-formatted comments; these comments can be extracted and formatted
@@ -372,7 +386,8 @@
 lead to literally hundreds or thousands of changes - many of which are
 likely to conflict with work being done by other developers.  Needless to
 say, this can be a large job, so it is best to be sure that the
-justification is solid.
+justification is solid.  Note that the Coccinelle tool can help with
+wide-ranging API changes.
 
 When making an incompatible API change, one should, whenever possible,
 ensure that code which has not been updated is caught by the compiler.
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/5.Posting linux-libre-2.6.39-gnu/Documentation/development-process/5.Posting
--- linux-libre-2.6.38-gnu/Documentation/development-process/5.Posting	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/5.Posting	2011-05-19 00:06:34.000000000 -0400
@@ -60,12 +60,15 @@
 
 Patches must be prepared against a specific version of the kernel.  As a
 general rule, a patch should be based on the current mainline as found in
-Linus's git tree.  It may become necessary to make versions against -mm,
-linux-next, or a subsystem tree, though, to facilitate wider testing and
-review.  Depending on the area of your patch and what is going on
-elsewhere, basing a patch against these other trees can require a
-significant amount of work resolving conflicts and dealing with API
-changes.
+Linus's git tree.  When basing on mainline, start with a well-known release
+point - a stable or -rc release - rather than branching off the mainline at
+an arbitrary spot.
+
+It may become necessary to make versions against -mm, linux-next, or a
+subsystem tree, though, to facilitate wider testing and review.  Depending
+on the area of your patch and what is going on elsewhere, basing a patch
+against these other trees can require a significant amount of work
+resolving conflicts and dealing with API changes.
 
 Only the most simple changes should be formatted as a single patch;
 everything else should be made as a logical series of changes.  Splitting
@@ -100,11 +103,11 @@
    result is a broken kernel, you will make life harder for developers and
    users who are engaging in the noble work of tracking down problems.
 
- - Do not overdo it, though.  One developer recently posted a set of edits
+ - Do not overdo it, though.  One developer once posted a set of edits
    to a single file as 500 separate patches - an act which did not make him
    the most popular person on the kernel mailing list.  A single patch can
    be reasonably large as long as it still contains a single *logical*
-   change. 
+   change.
 
  - It can be tempting to add a whole new infrastructure with a series of
    patches, but to leave that infrastructure unused until the final patch
@@ -162,7 +165,8 @@
 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
+which introduced the bug if possible (and please provide both the commit ID
+and the title when citing commits).  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
@@ -230,7 +234,7 @@
    which have had gratuitous white-space changes or line wrapping performed
    by the mail client will not apply at the other end, and often will not
    be examined in any detail.  If there is any doubt at all, mail the patch
-   to yourself and convince yourself that it shows up intact.  
+   to yourself and convince yourself that it shows up intact.
 
    Documentation/email-clients.txt has some helpful hints on making
    specific mail clients work for sending patches.
@@ -287,7 +291,7 @@
 
 where "nn" is the ordinal number of the patch, "mm" is the total number of
 patches in the series, and "subsys" is the name of the affected subsystem.
-Clearly, nn/mm can be omitted for a single, standalone patch.  
+Clearly, nn/mm can be omitted for a single, standalone patch.
 
 If you have a significant series of patches, it is customary to send an
 introductory description as part zero.  This convention is not universally
@@ -299,5 +303,5 @@
 sent as a reply to the first part so that they all thread together at the
 receiving end.  Tools like git and quilt have commands to mail out a set of
 patches with the proper threading.  If you have a long series, though, and
-are using git, please provide the --no-chain-reply-to option to avoid
+are using git, please stay away from the --chain-reply-to option to avoid
 creating exceptionally deep nesting.
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/6.Followthrough linux-libre-2.6.39-gnu/Documentation/development-process/6.Followthrough
--- linux-libre-2.6.38-gnu/Documentation/development-process/6.Followthrough	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/6.Followthrough	2011-05-19 00:06:34.000000000 -0400
@@ -66,6 +66,11 @@
 that you don't realize that something is fundamentally wrong or, perhaps,
 you're not even solving the right problem.
 
+Andrew Morton has suggested that every review comment which does not result
+in a code change should result in an additional code comment instead; that
+can help future reviewers avoid the questions which came up the first time
+around.
+
 One fatal mistake is to ignore review comments in the hope that they will
 go away.  They will not go away.  If you repost code without having
 responded to the comments you got the time before, you're likely to find
@@ -100,7 +105,7 @@
 subsystem to the next; each maintainer has his or her own way of doing
 things.  In particular, there may be more than one tree - one, perhaps,
 dedicated to patches planned for the next merge window, and another for
-longer-term work.  
+longer-term work.
 
 For patches applying to areas for which there is no obvious subsystem tree
 (memory management patches, for example), the default tree often ends up
@@ -109,11 +114,10 @@
 
 Inclusion into a subsystem tree can bring a higher level of visibility to a
 patch.  Now other developers working with that tree will get the patch by
-default.  Subsystem trees typically feed into -mm and linux-next as well,
-making their contents visible to the development community as a whole.  At
-this point, there's a good chance that you will get more comments from a
-new set of reviewers; these comments need to be answered as in the previous
-round.
+default.  Subsystem trees typically feed linux-next as well, making their
+contents visible to the development community as a whole.  At this point,
+there's a good chance that you will get more comments from a new set of
+reviewers; these comments need to be answered as in the previous round.
 
 What may also happen at this point, depending on the nature of your patch,
 is that conflicts with work being done by others turn up.  In the worst
diff -druN linux-libre-2.6.38-gnu/Documentation/development-process/7.AdvancedTopics linux-libre-2.6.39-gnu/Documentation/development-process/7.AdvancedTopics
--- linux-libre-2.6.38-gnu/Documentation/development-process/7.AdvancedTopics	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/development-process/7.AdvancedTopics	2011-05-19 00:06:34.000000000 -0400
@@ -119,7 +119,7 @@
 	to trust things *without* then having to go and check every
 	individual change by hand.
 
-(http://lwn.net/Articles/224135/).  
+(http://lwn.net/Articles/224135/).
 
 To avoid this kind of situation, ensure that all patches within a given
 branch stick closely to the associated topic; a "driver fixes" branch
@@ -138,7 +138,7 @@
 your tree is, what branch to pull, and what changes will result from the
 pull.  The git request-pull command can be helpful in this regard; it will
 format the request as other developers expect, and will also check to be
-sure that you have remembered to push those changes to the public server. 
+sure that you have remembered to push those changes to the public server.
 
 
 7.2: REVIEWING PATCHES
diff -druN linux-libre-2.6.38-gnu/Documentation/device-mapper/dm-crypt.txt linux-libre-2.6.39-gnu/Documentation/device-mapper/dm-crypt.txt
--- linux-libre-2.6.38-gnu/Documentation/device-mapper/dm-crypt.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/device-mapper/dm-crypt.txt	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
 ===============
 LUKS (Linux Unified Key Setup) is now the preferred way to set up disk
 encryption with dm-crypt using the 'cryptsetup' utility, see
-http://clemens.endorphin.org/cryptography
+http://code.google.com/p/cryptsetup/
 
 [[
 #!/bin/sh
diff -druN linux-libre-2.6.38-gnu/Documentation/device-mapper/dm-flakey.txt linux-libre-2.6.39-gnu/Documentation/device-mapper/dm-flakey.txt
--- linux-libre-2.6.38-gnu/Documentation/device-mapper/dm-flakey.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/device-mapper/dm-flakey.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+dm-flakey
+=========
+
+This target is the same as the linear target except that it returns I/O
+errors periodically.  It's been found useful in simulating failing
+devices for testing purposes.
+
+Starting from the time the table is loaded, the device is available for
+<up interval> seconds, then returns errors for <down interval> seconds,
+and then this cycle repeats.
+
+Parameters: <dev path> <offset> <up interval> <down interval>
+    <dev path>: Full pathname to the underlying block-device, or a
+                "major:minor" device-number.
+    <offset>: Starting sector within the device.
+    <up interval>: Number of seconds device is available.
+    <down interval>: Number of seconds device returns errors.
diff -druN linux-libre-2.6.38-gnu/Documentation/device-mapper/dm-service-time.txt linux-libre-2.6.39-gnu/Documentation/device-mapper/dm-service-time.txt
--- linux-libre-2.6.38-gnu/Documentation/device-mapper/dm-service-time.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/device-mapper/dm-service-time.txt	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
 =========
 
 dm-service-time adds the I/O size to 'in-flight-size' when the I/O is
-dispatched and substracts when completed.
+dispatched and subtracts when completed.
 Basically, dm-service-time selects a path having minimum service time
 which is calculated by:
 
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/00-INDEX linux-libre-2.6.39-gnu/Documentation/devicetree/00-INDEX
--- linux-libre-2.6.38-gnu/Documentation/devicetree/00-INDEX	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/00-INDEX	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+Documentation for device trees, a data structure by which bootloaders pass
+hardware layout to Linux in a device-independent manner, simplifying hardware
+probing.  This subsystem is maintained by Grant Likely
+<grant.likely@secretlab.ca> and has a mailing list at
+https://lists.ozlabs.org/listinfo/devicetree-discuss
+
+00-INDEX
+	- this file
+booting-without-of.txt
+	- Booting Linux without Open Firmware, describes history and format of device trees.
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/fb/sm501fb.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/fb/sm501fb.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/fb/sm501fb.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/fb/sm501fb.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,34 @@
+* SM SM501
+
+The SM SM501 is a LCD controller, with proper hardware, it can also
+drive DVI monitors.
+
+Required properties:
+- compatible : should be "smi,sm501".
+- reg : contain two entries:
+    - First entry: System Configuration register
+    - Second entry: IO space (Display Controller register)
+- interrupts : SMI interrupt to the cpu should be described here.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
+
+Optional properties:
+- mode : select a video mode:
+    <xres>x<yres>[-<bpp>][@<refresh>]
+- edid : verbatim EDID data block describing attached display.
+  Data from the detailed timing descriptor will be used to
+  program the display controller.
+- little-endian: available on big endian systems, to
+  set different foreign endian.
+- big-endian: available on little endian systems, to
+  set different foreign endian.
+
+Example for MPC5200:
+	display@1,0 {
+		compatible = "smi,sm501";
+		reg = <1 0x00000000 0x00800000
+		       1 0x03e00000 0x00200000>;
+		interrupts = <1 1 3>;
+		mode = "640x480-32@60";
+		edid = [edid-data];
+	};
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/hwmon/ads1015.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/hwmon/ads1015.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/hwmon/ads1015.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/hwmon/ads1015.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,73 @@
+ADS1015 (I2C)
+
+This device is a 12-bit A-D converter with 4 inputs.
+
+The inputs can be used single ended or in certain differential combinations.
+
+For configuration all possible combinations are mapped to 8 channels:
+  0: Voltage over AIN0 and AIN1.
+  1: Voltage over AIN0 and AIN3.
+  2: Voltage over AIN1 and AIN3.
+  3: Voltage over AIN2 and AIN3.
+  4: Voltage over AIN0 and GND.
+  5: Voltage over AIN1 and GND.
+  6: Voltage over AIN2 and GND.
+  7: Voltage over AIN3 and GND.
+
+Each channel can be configured individually:
+ - pga is the programmable gain amplifier (values are full scale)
+    0: +/- 6.144 V
+    1: +/- 4.096 V
+    2: +/- 2.048 V (default)
+    3: +/- 1.024 V
+    4: +/- 0.512 V
+    5: +/- 0.256 V
+ - data_rate in samples per second
+    0: 128
+    1: 250
+    2: 490
+    3: 920
+    4: 1600 (default)
+    5: 2400
+    6: 3300
+
+1) The /ads1015 node
+
+  Required properties:
+
+   - compatible : must be "ti,ads1015"
+   - reg : I2C bus address of the device
+   - #address-cells : must be <1>
+   - #size-cells : must be <0>
+
+  The node contains child nodes for each channel that the platform uses.
+
+  Example ADS1015 node:
+
+    ads1015@49 {
+	    compatible = "ti,ads1015";
+	    reg = <0x49>;
+	    #address-cells = <1>;
+	    #size-cells = <0>;
+
+	    [ child node definitions... ]
+    }
+
+2) channel nodes
+
+  Required properties:
+
+   - reg : the channel number
+
+  Optional properties:
+
+   - ti,gain : the programmable gain amplifier setting
+   - ti,datarate : the converter data rate
+
+  Example ADS1015 channel node:
+
+    channel@4 {
+	    reg = <4>;
+	    ti,gain = <3>;
+	    ti,datarate = <5>;
+    };
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/i2c/ce4100-i2c.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,93 @@
+CE4100 I2C
+----------
+
+CE4100 has one PCI device which is described as the I2C-Controller. This
+PCI device has three PCI-bars, each bar contains a complete I2C
+controller. So we have a total of three independent I2C-Controllers
+which share only an interrupt line.
+The driver is probed via the PCI-ID and is gathering the information of
+attached devices from the devices tree.
+Grant Likely recommended to use the ranges property to map the PCI-Bar
+number to its physical address and to use this to find the child nodes
+of the specific I2C controller. This were his exact words:
+
+       Here's where the magic happens.  Each entry in
+       ranges describes how the parent pci address space
+       (middle group of 3) is translated to the local
+       address space (first group of 2) and the size of
+       each range (last cell).  In this particular case,
+       the first cell of the local address is chosen to be
+       1:1 mapped to the BARs, and the second is the
+       offset from be base of the BAR (which would be
+       non-zero if you had 2 or more devices mapped off
+       the same BAR)
+
+       ranges allows the address mapping to be described
+       in a way that the OS can interpret without
+       requiring custom device driver code.
+
+This is an example which is used on FalconFalls:
+------------------------------------------------
+	i2c-controller@b,2 {
+		#address-cells = <2>;
+		#size-cells = <1>;
+		compatible = "pci8086,2e68.2",
+				"pci8086,2e68",
+				"pciclass,ff0000",
+				"pciclass,ff00";
+
+		reg = <0x15a00 0x0 0x0 0x0 0x0>;
+		interrupts = <16 1>;
+
+		/* as described by Grant, the first number in the group of
+		* three is the bar number followed by the 64bit bar address
+		* followed by size of the mapping. The bar address
+		* requires also a valid translation in parents ranges
+		* property.
+		*/
+		ranges = <0 0   0x02000000 0 0xdffe0500 0x100
+			  1 0   0x02000000 0 0xdffe0600 0x100
+			  2 0   0x02000000 0 0xdffe0700 0x100>;
+
+		i2c@0 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+
+			/* The first number in the reg property is the
+			* number of the bar
+			*/
+			reg = <0 0 0x100>;
+
+			/* This I2C controller has no devices */
+		};
+
+		i2c@1 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+			reg = <1 0 0x100>;
+
+			/* This I2C controller has one gpio controller */
+			gpio@26 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8575";
+				reg = <0x26>;
+				gpio-controller;
+			};
+		};
+
+		i2c@2 {
+			#address-cells = <1>;
+			#size-cells = <0>;
+			compatible = "intel,ce4100-i2c-controller";
+			reg = <2 0 0x100>;
+
+			gpio@26 {
+				#gpio-cells = <2>;
+				compatible = "ti,pcf8575";
+				reg = <0x26>;
+				gpio-controller;
+			};
+		};
+	};
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/mmc/mmc-spi-slot.txt	2011-05-19 00:06:34.000000000 -0400
@@ -7,8 +7,13 @@
 - voltage-ranges : two cells are required, first cell specifies minimum
   slot voltage (mV), second cell specifies maximum slot voltage (mV).
   Several ranges could be specified.
-- gpios : (optional) may specify GPIOs in this order: Card-Detect GPIO,
+
+Optional properties:
+- gpios : may specify GPIOs in this order: Card-Detect GPIO,
   Write-Protect GPIO.
+- interrupts : the interrupt of a card detect interrupt.
+- interrupt-parent : the phandle for the interrupt controller that
+  services interrupts for this device.
 
 Example:
 
@@ -20,4 +25,6 @@
 			 &qe_pio_d 15 0>;
 		voltage-ranges = <3300 3300>;
 		spi-max-frequency = <50000000>;
+		interrupts = <42>;
+		interrupt-parent = <&PIC>;
 	};
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/mtd/fsl-upm-nand.txt	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 - gpios : may specify optional GPIOs connected to the Ready-Not-Busy pins
 	(R/B#). For multi-chip devices, "n" GPIO definitions are required
 	according to the number of chips.
-- chip-delay : chip dependent delay for transfering data from array to
+- chip-delay : chip dependent delay for transferring data from array to
 	read registers (tR). Required if property "gpios" is not used
 	(R/B# pins not connected).
 
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/net/can/sja1000.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/net/can/sja1000.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/net/can/sja1000.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/net/can/sja1000.txt	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 
 - nxp,no-comparator-bypass : Allows to disable the CAN input comperator.
 
-For futher information, please have a look to the SJA1000 data sheet.
+For further information, please have a look to the SJA1000 data sheet.
 
 Examples:
 
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/open-pic.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/open-pic.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/open-pic.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/open-pic.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+* Open PIC Binding
+
+This binding specifies what properties must be available in the device tree
+representation of an Open PIC compliant interrupt controller.  This binding is
+based on the binding defined for Open PIC in [1] and is a superset of that
+binding.
+
+Required properties:
+
+  NOTE: Many of these descriptions were paraphrased here from [1] to aid
+        readability.
+
+    - compatible: Specifies the compatibility list for the PIC.  The type
+      shall be <string> and the value shall include "open-pic".
+
+    - reg: Specifies the base physical address(s) and size(s) of this
+      PIC's addressable register space.  The type shall be <prop-encoded-array>.
+
+    - interrupt-controller: The presence of this property identifies the node
+      as an Open PIC.  No property value shall be defined.
+
+    - #interrupt-cells: Specifies the number of cells needed to encode an
+      interrupt source.  The type shall be a <u32> and the value shall be 2.
+
+    - #address-cells: Specifies the number of cells needed to encode an
+      address.  The type shall be <u32> and the value shall be 0.  As such,
+      'interrupt-map' nodes do not have to specify a parent unit address.
+
+Optional properties:
+
+    - pic-no-reset: The presence of this property indicates that the PIC
+      shall not be reset during runtime initialization.  No property value shall
+      be defined.  The presence of this property also mandates that any
+      initialization related to interrupt sources shall be limited to sources
+      explicitly referenced in the device tree.
+
+* Interrupt Specifier Definition
+
+  Interrupt specifiers consists of 2 cells encoded as
+  follows:
+
+    - <1st-cell>: The interrupt-number that identifies the interrupt source.
+
+    - <2nd-cell>: The level-sense information, encoded as follows:
+                    0 = low-to-high edge triggered
+                    1 = active low level-sensitive
+                    2 = active high level-sensitive
+                    3 = high-to-low edge triggered
+
+* Examples
+
+Example 1:
+
+	/*
+	 * An Open PIC interrupt controller
+	 */
+	mpic: pic@40000 {
+		// This is an interrupt controller node.
+		interrupt-controller;
+
+		// No address cells so that 'interrupt-map' nodes which reference
+		// this Open PIC node do not need a parent address specifier.
+		#address-cells = <0>;
+
+		// Two cells to encode interrupt sources.
+		#interrupt-cells = <2>;
+
+		// Offset address of 0x40000 and size of 0x40000.
+		reg = <0x40000 0x40000>;
+
+		// Compatible with Open PIC.
+		compatible = "open-pic";
+
+		// The PIC shall not be reset.
+		pic-no-reset;
+	};
+
+Example 2:
+
+	/*
+	 * An interrupt generating device that is wired to an Open PIC.
+	 */
+	serial0: serial@4500 {
+		// Interrupt source '42' that is active high level-sensitive.
+		// Note that there are only two cells as specified in the interrupt
+		// parent's '#interrupt-cells' property.
+		interrupts = <42 2>;
+
+		// The interrupt controller that this device is wired to.
+		interrupt-parent = <&mpic>;
+	};
+
+* References
+
+[1] Power.org (TM) Standard for Embedded Power Architecture (TM) Platform
+    Requirements (ePAPR), Version 1.0, July 2008.
+    (http://www.power.org/resources/downloads/Power_ePAPR_APPROVED_v1.0.pdf)
+
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/powerpc/fsl/cache_sram.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,20 @@
+* Freescale PQ3 and QorIQ based Cache SRAM
+
+Freescale's mpc85xx and some QorIQ platforms provide an
+option of configuring a part of (or full) cache memory
+as SRAM. This cache SRAM representation in the device
+tree should be done as under:-
+
+Required properties:
+
+- compatible : should be "fsl,p2020-cache-sram"
+- fsl,cache-sram-ctlr-handle : points to the L2 controller
+- reg : offset and length of the cache-sram.
+
+Example:
+
+cache-sram@fff00000 {
+	fsl,cache-sram-ctlr-handle = <&L2>;
+	reg = <0 0xfff00000 0 0x10000>;
+	compatible = "fsl,p2020-cache-sram";
+};
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/powerpc/fsl/mpic.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,42 +1,211 @@
-* OpenPIC and its interrupt numbers on Freescale's e500/e600 cores
+=====================================================================
+Freescale MPIC Interrupt Controller Node
+Copyright (C) 2010,2011 Freescale Semiconductor Inc.
+=====================================================================
 
-The OpenPIC specification does not specify which interrupt source has to
-become which interrupt number. This is up to the software implementation
-of the interrupt controller. The only requirement is that every
-interrupt source has to have an unique interrupt number / vector number.
-To accomplish this the current implementation assigns the number zero to
-the first source, the number one to the second source and so on until
-all interrupt sources have their unique number.
-Usually the assigned vector number equals the interrupt number mentioned
-in the documentation for a given core / CPU. This is however not true
-for the e500 cores (MPC85XX CPUs) where the documentation distinguishes
-between internal and external interrupt sources and starts counting at
-zero for both of them.
+The Freescale MPIC interrupt controller is found on all PowerQUICC
+and QorIQ processors and is compatible with the Open PIC.  The
+notable difference from Open PIC binding is the addition of 2
+additional cells in the interrupt specifier defining interrupt type
+information.
 
-So what to write for external interrupt source X or internal interrupt
-source Y into the device tree? Here is an example:
+PROPERTIES
 
-The memory map for the interrupt controller in the MPC8544[0] shows,
-that the first interrupt source starts at 0x5_0000 (PIC Register Address
-Map-Interrupt Source Configuration Registers). This source becomes the
-number zero therefore:
- External interrupt 0 = interrupt number 0
- External interrupt 1 = interrupt number 1
- External interrupt 2 = interrupt number 2
- ...
-Every interrupt number allocates 0x20 bytes register space. So to get
-its number it is sufficient to shift the lower 16bits to right by five.
-So for the external interrupt 10 we have:
-  0x0140 >> 5 = 10
+  - compatible
+      Usage: required
+      Value type: <string>
+      Definition: Shall include "fsl,mpic".  Freescale MPIC
+          controllers compatible with this binding have Block
+          Revision Registers BRR1 and BRR2 at offset 0x0 and
+          0x10 in the MPIC.
 
-After the external sources, the internal sources follow. The in core I2C
-controller on the MPC8544 for instance has the internal source number
-27. Oo obtain its interrupt number we take the lower 16bits of its memory
-address (0x5_0560) and shift it right:
- 0x0560 >> 5 = 43
+  - reg
+      Usage: required
+      Value type: <prop-encoded-array>
+      Definition: A standard property.  Specifies the physical
+          offset and length of the device's registers within the
+          CCSR address space.
 
-Therefore the I2C device node for the MPC8544 CPU has to have the
-interrupt number 43 specified in the device tree.
+  - interrupt-controller
+      Usage: required
+      Value type: <empty>
+      Definition: Specifies that this node is an interrupt
+          controller
 
-[0] MPC8544E PowerQUICCTM III, Integrated Host Processor Family Reference Manual
-    MPC8544ERM Rev. 1 10/2007
+  - #interrupt-cells
+      Usage: required
+      Value type: <u32>
+      Definition: Shall be 2 or 4.  A value of 2 means that interrupt
+          specifiers do not contain the interrupt-type or type-specific
+          information cells.
+
+  - #address-cells
+      Usage: required
+      Value type: <u32>
+      Definition: Shall be 0.
+
+  - pic-no-reset
+      Usage: optional
+      Value type: <empty>
+      Definition: The presence of this property specifies that the
+          MPIC must not be reset by the client program, and that
+          the boot program has initialized all interrupt source
+          configuration registers to a sane state-- masked or
+          directed at other cores.  This ensures that the client
+          program will not receive interrupts for sources not belonging
+          to the client.  The presence of this property also mandates
+          that any initialization related to interrupt sources shall
+          be limited to sources explicitly referenced in the device tree.
+       
+INTERRUPT SPECIFIER DEFINITION
+
+  Interrupt specifiers consists of 4 cells encoded as
+  follows:
+
+   <1st-cell>   interrupt-number
+
+                Identifies the interrupt source.  The meaning
+                depends on the type of interrupt.
+
+                Note: If the interrupt-type cell is undefined
+                (i.e. #interrupt-cells = 2), this cell
+                should be interpreted the same as for
+                interrupt-type 0-- i.e. an external or
+                normal SoC device interrupt.
+
+   <2nd-cell>   level-sense information, encoded as follows:
+                    0 = low-to-high edge triggered
+                    1 = active low level-sensitive
+                    2 = active high level-sensitive
+                    3 = high-to-low edge triggered
+
+   <3rd-cell>   interrupt-type
+
+                The following types are supported:
+
+                  0 = external or normal SoC device interrupt
+
+                      The interrupt-number cell contains
+                      the SoC device interrupt number.  The
+                      type-specific cell is undefined.  The
+                      interrupt-number is derived from the
+                      MPIC a block of registers referred to as
+                      the "Interrupt Source Configuration Registers".
+                      Each source has 32-bytes of registers
+                      (vector/priority and destination) in this
+                      region.   So interrupt 0 is at offset 0x0,
+                      interrupt 1 is at offset 0x20, and so on.
+
+                  1 = error interrupt
+
+                      The interrupt-number cell contains
+                      the SoC device interrupt number for
+                      the error interrupt.  The type-specific
+                      cell identifies the specific error
+                      interrupt number.
+
+                  2 = MPIC inter-processor interrupt (IPI)
+
+                      The interrupt-number cell identifies
+                      the MPIC IPI number.  The type-specific
+                      cell is undefined.
+
+                  3 = MPIC timer interrupt
+
+                      The interrupt-number cell identifies
+                      the MPIC timer number.  The type-specific
+                      cell is undefined.
+
+   <4th-cell>   type-specific information
+
+                The type-specific cell is encoded as follows:
+
+                 - For interrupt-type 1 (error interrupt),
+                   the type-specific cell contains the
+                   bit number of the error interrupt in the
+                   Error Interrupt Summary Register.
+
+EXAMPLE 1
+	/*
+	 * mpic interrupt controller with 4 cells per specifier
+	 */
+	mpic: pic@40000 {
+		compatible = "fsl,mpic";
+		interrupt-controller;
+		#interrupt-cells = <4>;
+		#address-cells = <0>;
+		reg = <0x40000 0x40000>;
+	};
+
+EXAMPLE 2
+	/*
+	 * The MPC8544 I2C controller node has an internal
+	 * interrupt number of 27.  As per the reference manual
+	 * this corresponds to interrupt source configuration
+	 * registers at 0x5_0560.
+	 *
+	 * The interrupt source configuration registers begin
+	 * at 0x5_0000.
+	 *
+	 * To compute the interrupt specifier interrupt number
+         *
+	 *       0x560 >> 5 = 43
+	 *
+	 * The interrupt source configuration registers begin
+	 * at 0x5_0000, and so the i2c vector/priority registers
+	 * are at 0x5_0560.
+	 */
+	i2c@3000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cell-index = <0>;
+		compatible = "fsl-i2c";
+		reg = <0x3000 0x100>;
+		interrupts = <43 2>;
+		interrupt-parent = <&mpic>;
+		dfsrr;
+	};
+
+
+EXAMPLE 3
+	/*
+	 *  Definition of a node defining the 4
+	 *  MPIC IPI interrupts.  Note the interrupt
+	 *  type of 2.
+	 */
+	ipi@410a0 {
+		compatible = "fsl,mpic-ipi";
+		reg = <0x40040 0x10>;
+		interrupts = <0 0 2 0
+		              1 0 2 0
+		              2 0 2 0
+		              3 0 2 0>;
+	};
+
+EXAMPLE 4
+	/*
+	 *  Definition of a node defining the MPIC
+	 *  global timers.  Note the interrupt
+	 *  type of 3.
+	 */
+	timer0: timer@41100 {
+		compatible = "fsl,mpic-global-timer";
+		reg = <0x41100 0x100>;
+		interrupts = <0 0 3 0
+		              1 0 3 0
+		              2 0 3 0
+		              3 0 3 0>;
+	};
+
+EXAMPLE 5
+	/*
+	 * Definition of an error interrupt (interrupt type 1).
+	 * SoC interrupt number is 16 and the specific error
+         * interrupt bit in the error interrupt summary register
+	 * is 23.
+	 */
+	memory-controller@8000 {
+		compatible = "fsl,p4080-memory-controller";
+		reg = <0x8000 0x1000>;
+		interrupts = <16 2 1 23>;
+	};
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/powerpc/fsl/msi-pic.txt	2011-05-19 00:06:34.000000000 -0400
@@ -5,14 +5,21 @@
   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
   the parent type.
+
 - reg : should contain the address and the length of the shared message
   interrupt register set.
+
 - msi-available-ranges: use <start count> style section to define which
   msi interrupt can be used in the 256 msi interrupts. This property is
   optional, without this, all the 256 MSI interrupts can be used.
+  Each available range must begin and end on a multiple of 32 (i.e.
+  no splitting an individual MSI register or the associated PIC interrupt).
+
 - interrupts : each one of the interrupts here is one entry per 32 MSIs,
   and routed to the host interrupt controller. the interrupts should
-  be set as edge sensitive.
+  be set as edge sensitive.  If msi-available-ranges is present, only
+  the interrupts that correspond to available ranges shall be present.
+
 - interrupt-parent: the phandle for the interrupt controller
   that services interrupts for this device. for 83xx cpu, the interrupts
   are routed to IPIC, and for 85xx/86xx cpu the interrupts are routed
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/rtc/rtc-cmos.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/rtc/rtc-cmos.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/rtc/rtc-cmos.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/rtc/rtc-cmos.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,28 @@
+ Motorola mc146818 compatible RTC
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Required properties:
+  - compatible : "motorola,mc146818"
+  - reg : should contain registers location and length.
+
+Optional properties:
+  - interrupts : should contain interrupt.
+  - interrupt-parent : interrupt source phandle.
+  - ctrl-reg : Contains the initial value of the control register also
+    called "Register B".
+  - freq-reg : Contains the initial value of the frequency register also
+    called "Regsiter A".
+
+"Register A" and "B" are usually initialized by the firmware (BIOS for
+instance). If this is not done, it can be performed by the driver.
+
+ISA Example:
+
+	rtc@70 {
+	         compatible = "motorola,mc146818";
+	         interrupts = <8 3>;
+	         interrupt-parent = <&ioapic1>;
+	         ctrl-reg = <2>;
+	         freq-reg = <0x26>;
+	         reg = <1 0x70 2>;
+	 };
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/serial/altera_jtaguart.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/serial/altera_jtaguart.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/serial/altera_jtaguart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/serial/altera_jtaguart.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,4 @@
+Altera JTAG UART
+
+Required properties:
+- compatible : should be "ALTR,juart-1.0"
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/serial/altera_uart.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/serial/altera_uart.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/serial/altera_uart.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/serial/altera_uart.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,7 @@
+Altera UART
+
+Required properties:
+- compatible : should be "ALTR,uart-1.0"
+
+Optional properties:
+- clock-frequency : frequency of the clock input to the UART
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/serio/altera_ps2.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/serio/altera_ps2.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/serio/altera_ps2.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/serio/altera_ps2.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,4 @@
+Altera UP PS/2 controller
+
+Required properties:
+- compatible : should be "ALTR,ps2-1.0".
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/spi/spi_altera.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/spi/spi_altera.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/spi/spi_altera.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/spi/spi_altera.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,4 @@
+Altera SPI
+
+Required properties:
+- compatible : should be "ALTR,spi-1.0".
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/spi/spi_oc_tiny.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,12 @@
+OpenCores tiny SPI
+
+Required properties:
+- compatible : should be "opencores,tiny-spi-rtlsvn2".
+- gpios : should specify GPIOs used for chipselect.
+Optional properties:
+- clock-frequency : input clock frequency to the core.
+- baud-width: width, in bits, of the programmable divider used to scale
+	the input clock to SCLK.
+
+The clock-frequency and baud-width properties are needed only if the divider
+is programmable. They are not needed if the divider is fixed.
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/x86/ce4100.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/x86/ce4100.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/x86/ce4100.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/x86/ce4100.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+CE4100 Device Tree Bindings
+---------------------------
+
+The CE4100 SoC uses for in core peripherals the following compatible
+format: <vendor>,<chip>-<device>.
+Many of the "generic" devices like HPET or IO APIC have the ce4100
+name in their compatible property because they first appeared in this
+SoC.
+
+The CPU node
+------------
+	cpu@0 {
+		device_type = "cpu";
+		compatible = "intel,ce4100";
+		reg = <0>;
+		lapic = <&lapic0>;
+	};
+
+The reg property describes the CPU number. The lapic property points to
+the local APIC timer.
+
+The SoC node
+------------
+
+This node describes the in-core peripherals. Required property:
+  compatible = "intel,ce4100-cp";
+
+The PCI node
+------------
+This node describes the PCI bus on the SoC. Its property should be
+  compatible = "intel,ce4100-pci", "pci";
+
+If the OS is using the IO-APIC for interrupt routing then the reported
+interrupt numbers for devices is no longer true. In order to obtain the
+correct interrupt number, the child node which represents the device has
+to contain the interrupt property. Besides the interrupt property it has
+to contain at least the reg property containing the PCI bus address and
+compatible property according to "PCI Bus Binding Revision 2.1".
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/x86/interrupt.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/x86/interrupt.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/x86/interrupt.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/x86/interrupt.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+Interrupt chips
+---------------
+
+* Intel I/O Advanced Programmable Interrupt Controller (IO APIC)
+
+  Required properties:
+  --------------------
+     compatible = "intel,ce4100-ioapic";
+     #interrupt-cells = <2>;
+
+  Device's interrupt property:
+
+     interrupts = <P S>;
+
+  The first number (P) represents the interrupt pin which is wired to the
+  IO APIC. The second number (S) represents the sense of interrupt which
+  should be configured and can be one of:
+    0 - Edge Rising
+    1 - Level Low
+    2 - Level High
+    3 - Edge Falling
+
+* Local APIC
+  Required property:
+
+     compatible = "intel,ce4100-lapic";
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/x86/timer.txt linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/x86/timer.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/bindings/x86/timer.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/bindings/x86/timer.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+Timers
+------
+
+* High Precision Event Timer (HPET)
+  Required property:
+     compatible = "intel,ce4100-hpet";
diff -druN linux-libre-2.6.38-gnu/Documentation/devicetree/booting-without-of.txt linux-libre-2.6.39-gnu/Documentation/devicetree/booting-without-of.txt
--- linux-libre-2.6.38-gnu/Documentation/devicetree/booting-without-of.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/devicetree/booting-without-of.txt	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 
   I - Introduction
     1) Entry point for arch/powerpc
+    2) Entry point for arch/x86
 
   II - The DT block format
     1) Header
@@ -137,7 +138,7 @@
 section III, but, for example, the kernel does not require you to
 create a node for every PCI device in the system. It is a requirement
 to have a node for PCI host bridges in order to provide interrupt
-routing informations and memory/IO ranges, among others. It is also
+routing information and memory/IO ranges, among others. It is also
 recommended to define nodes for on chip devices and other buses that
 don't specifically fit in an existing OF specification. This creates a
 great flexibility in the way the kernel can then probe those and match
@@ -225,6 +226,25 @@
   cannot support both configurations with Book E and configurations
   with classic Powerpc architectures.
 
+2) Entry point for arch/x86
+-------------------------------
+
+  There is one single 32bit entry point to the kernel at code32_start,
+  the decompressor (the real mode entry point goes to the same  32bit
+  entry point once it switched into protected mode). That entry point
+  supports one calling convention which is documented in
+  Documentation/x86/boot.txt
+  The physical pointer to the device-tree block (defined in chapter II)
+  is passed via setup_data which requires at least boot protocol 2.09.
+  The type filed is defined as
+
+  #define SETUP_DTB                      2
+
+  This device-tree is used as an extension to the "boot page". As such it
+  does not parse / consider data which is already covered by the boot
+  page. This includes memory size, reserved ranges, command line arguments
+  or initrd address. It simply holds information which can not be retrieved
+  otherwise like interrupt routing or a list of devices behind an I2C bus.
 
 II - The DT block format
 ========================
@@ -365,7 +385,7 @@
      among others, by kexec. If you are on an SMP system, this value
      should match the content of the "reg" property of the CPU node in
      the device-tree corresponding to the CPU calling the kernel entry
-     point (see further chapters for more informations on the required
+     point (see further chapters for more information on the required
      device-tree contents)
 
    - size_dt_strings
@@ -533,7 +553,7 @@
 
 This tree is almost a minimal tree. It pretty much contains the
 minimal set of required nodes and properties to boot a linux kernel;
-that is, some basic model informations at the root, the CPUs, and the
+that is, some basic model information at the root, the CPUs, and the
 physical memory layout.  It also includes misc information passed
 through /chosen, like in this example, the platform type (mandatory)
 and the kernel command line arguments (optional).
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/dvb/dvbproperty.xml linux-libre-2.6.39-gnu/Documentation/DocBook/dvb/dvbproperty.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/dvb/dvbproperty.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/dvb/dvbproperty.xml	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 
 			<para>Central frequency of the channel.</para>
 
-			<para>For ISDB-T the channels are usally transmitted with an offset of 143kHz. E.g. a
+			<para>For ISDB-T the channels are usually transmitted with an offset of 143kHz. E.g. a
 				valid frequncy could be 474143 kHz. The stepping is bound to the bandwidth of
 				the channel which is 6MHz.</para>
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/dvb/frontend.xml linux-libre-2.6.39-gnu/Documentation/DocBook/dvb/frontend.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/dvb/frontend.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/dvb/frontend.xml	2011-05-19 00:06:34.000000000 -0400
@@ -139,7 +139,7 @@
 <section id="frontend_sec_tone">
 <title>SEC continuous tone</title>
 
-<para>The continous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the
+<para>The continuous 22KHz tone is usually used with non-DiSEqC capable LNBs to switch the
 high/low band of a dual-band LNB. When using DiSEqC epuipment this voltage has to
 be switched consistently to the DiSEqC commands as described in the DiSEqC
 spec.</para>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/kernel-locking.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/kernel-locking.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/kernel-locking.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/kernel-locking.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -1763,7 +1763,7 @@
 There is a furthur optimization possible here: remember our original
 cache code, where there were no reference counts and the caller simply
 held the lock whenever using the object?  This is still possible: if
-you hold the lock, noone can delete the object, so you don't need to
+you hold the lock, no one can delete the object, so you don't need to
 get and put the reference count.
 </para>
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/libata.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/libata.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/libata.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/libata.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -1032,7 +1032,7 @@
 	   <listitem>
 	   <para>
 	   This is indicated by ICRC bit in the ERROR register and
-	   means that corruption occurred during data transfer.  Upto
+	   means that corruption occurred during data transfer.  Up to
 	   ATA/ATAPI-7, the standard specifies that this bit is only
 	   applicable to UDMA transfers but ATA/ATAPI-8 draft revision
 	   1f says that the bit may be applicable to multiword DMA and
@@ -1045,10 +1045,10 @@
 	   <term>ABRT error during data transfer or on completion</term>
 	   <listitem>
 	   <para>
-	   Upto ATA/ATAPI-7, the standard specifies that ABRT could be
+	   Up to ATA/ATAPI-7, the standard specifies that ABRT could be
 	   set on ICRC errors and on cases where a device is not able
 	   to complete a command.  Combined with the fact that MWDMA
-	   and PIO transfer errors aren't allowed to use ICRC bit upto
+	   and PIO transfer errors aren't allowed to use ICRC bit up to
 	   ATA/ATAPI-7, it seems to imply that ABRT bit alone could
 	   indicate tranfer errors.
 	   </para>
@@ -1122,7 +1122,7 @@
 	<para>
 	Depending on commands, not all STATUS/ERROR bits are
 	applicable.  These non-applicable bits are marked with
-	&quot;na&quot; in the output descriptions but upto ATA/ATAPI-7
+	&quot;na&quot; in the output descriptions but up to ATA/ATAPI-7
 	no definition of &quot;na&quot; can be found.  However,
 	ATA/ATAPI-8 draft revision 1f describes &quot;N/A&quot; as
 	follows.
@@ -1507,7 +1507,7 @@
 
 	<listitem>
 	<para>
-	CHS set up with INITIALIZE DEVICE PARAMETERS (seldomly used)
+	CHS set up with INITIALIZE DEVICE PARAMETERS (seldom used)
 	</para>
 	</listitem>
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/Makefile linux-libre-2.6.39-gnu/Documentation/DocBook/Makefile
--- linux-libre-2.6.38-gnu/Documentation/DocBook/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,9 @@
 mandocs: $(MAN)
 
 build_images = mkdir -p $(objtree)/Documentation/DocBook/media/ && \
-	       cp $(srctree)/Documentation/DocBook/dvb/*.png $(srctree)/Documentation/DocBook/v4l/*.gif $(objtree)/Documentation/DocBook/media/
+	       cp $(srctree)/Documentation/DocBook/dvb/*.png \
+	          $(srctree)/Documentation/DocBook/v4l/*.gif \
+		  $(objtree)/Documentation/DocBook/media/
 
 xmldoclinks:
 ifneq ($(objtree),$(srctree))
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/media-entities.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/media-entities.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/media-entities.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/media-entities.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,10 @@
 <!ENTITY func-select "<link linkend='func-select'><function>select()</function></link>">
 <!ENTITY func-write "<link linkend='func-write'><function>write()</function></link>">
 
+<!ENTITY media-func-close "<link linkend='media-func-close'><function>close()</function></link>">
+<!ENTITY media-func-ioctl "<link linkend='media-func-ioctl'><function>ioctl()</function></link>">
+<!ENTITY media-func-open "<link linkend='media-func-open'><function>open()</function></link>">
+
 <!-- Ioctls -->
 <!ENTITY VIDIOC-CROPCAP "<link linkend='vidioc-cropcap'><constant>VIDIOC_CROPCAP</constant></link>">
 <!ENTITY VIDIOC-DBG-G-CHIP-IDENT "<link linkend='vidioc-dbg-g-chip-ident'><constant>VIDIOC_DBG_G_CHIP_IDENT</constant></link>">
@@ -82,11 +86,24 @@
 <!ENTITY VIDIOC-S-PRIORITY "<link linkend='vidioc-g-priority'><constant>VIDIOC_S_PRIORITY</constant></link>">
 <!ENTITY VIDIOC-S-STD "<link linkend='vidioc-g-std'><constant>VIDIOC_S_STD</constant></link>">
 <!ENTITY VIDIOC-S-TUNER "<link linkend='vidioc-g-tuner'><constant>VIDIOC_S_TUNER</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-ENUM-FRAME-SIZE "<link linkend='vidioc-subdev-enum-frame-size'><constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-ENUM-MBUS-CODE "<link linkend='vidioc-subdev-enum-mbus-code'><constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-G-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_G_CROP</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-G-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_G_FMT</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-G-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-S-CROP "<link linkend='vidioc-subdev-g-crop'><constant>VIDIOC_SUBDEV_S_CROP</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-S-FMT "<link linkend='vidioc-subdev-g-fmt'><constant>VIDIOC_SUBDEV_S_FMT</constant></link>">
+<!ENTITY VIDIOC-SUBDEV-S-FRAME-INTERVAL "<link linkend='vidioc-subdev-g-frame-interval'><constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></link>">
 <!ENTITY VIDIOC-TRY-ENCODER-CMD "<link linkend='vidioc-encoder-cmd'><constant>VIDIOC_TRY_ENCODER_CMD</constant></link>">
 <!ENTITY VIDIOC-TRY-EXT-CTRLS "<link linkend='vidioc-g-ext-ctrls'><constant>VIDIOC_TRY_EXT_CTRLS</constant></link>">
 <!ENTITY VIDIOC-TRY-FMT "<link linkend='vidioc-g-fmt'><constant>VIDIOC_TRY_FMT</constant></link>">
 <!ENTITY VIDIOC-UNSUBSCRIBE-EVENT "<link linkend='vidioc-subscribe-event'><constant>VIDIOC_UNSUBSCRIBE_EVENT</constant></link>">
 
+<!ENTITY MEDIA-IOC-DEVICE-INFO "<link linkend='media-ioc-device-info'><constant>MEDIA_IOC_DEVICE_INFO</constant></link>">
+<!ENTITY MEDIA-IOC-ENUM-ENTITIES "<link linkend='media-ioc-enum-entities'><constant>MEDIA_IOC_ENUM_ENTITIES</constant></link>">
+<!ENTITY MEDIA-IOC-ENUM-LINKS "<link linkend='media-ioc-enum-links'><constant>MEDIA_IOC_ENUM_LINKS</constant></link>">
+<!ENTITY MEDIA-IOC-SETUP-LINK "<link linkend='media-ioc-setup-link'><constant>MEDIA_IOC_SETUP_LINK</constant></link>">
+
 <!-- Types -->
 <!ENTITY v4l2-std-id "<link linkend='v4l2-std-id'>v4l2_std_id</link>">
 
@@ -98,6 +115,7 @@
 <!ENTITY v4l2-field "enum&nbsp;<link linkend='v4l2-field'>v4l2_field</link>">
 <!ENTITY v4l2-frmivaltypes "enum&nbsp;<link linkend='v4l2-frmivaltypes'>v4l2_frmivaltypes</link>">
 <!ENTITY v4l2-frmsizetypes "enum&nbsp;<link linkend='v4l2-frmsizetypes'>v4l2_frmsizetypes</link>">
+<!ENTITY v4l2-mbus-pixelcode "enum&nbsp;<link linkend='v4l2-mbus-pixelcode'>v4l2_mbus_pixelcode</link>">
 <!ENTITY v4l2-memory "enum&nbsp;<link linkend='v4l2-memory'>v4l2_memory</link>">
 <!ENTITY v4l2-mpeg-audio-ac3-bitrate "enum&nbsp;<link linkend='v4l2-mpeg-audio-ac3-bitrate'>v4l2_mpeg_audio_ac3_bitrate</link>">
 <!ENTITY v4l2-mpeg-audio-crc "enum&nbsp;<link linkend='v4l2-mpeg-audio-crc'>v4l2_mpeg_audio_crc</link>">
@@ -121,6 +139,7 @@
 <!ENTITY v4l2-mpeg-video-encoding "enum&nbsp;<link linkend='v4l2-mpeg-video-encoding'>v4l2_mpeg_video_encoding</link>">
 <!ENTITY v4l2-power-line-frequency "enum&nbsp;<link linkend='v4l2-power-line-frequency'>v4l2_power_line_frequency</link>">
 <!ENTITY v4l2-priority "enum&nbsp;<link linkend='v4l2-priority'>v4l2_priority</link>">
+<!ENTITY v4l2-subdev-format-whence "enum&nbsp;<link linkend='v4l2-subdev-format-whence'>v4l2_subdev_format_whence</link>">
 <!ENTITY v4l2-tuner-type "enum&nbsp;<link linkend='v4l2-tuner-type'>v4l2_tuner_type</link>">
 <!ENTITY v4l2-preemphasis "enum&nbsp;<link linkend='v4l2-preemphasis'>v4l2_preemphasis</link>">
 
@@ -129,6 +148,7 @@
 <!ENTITY v4l2-audioout "struct&nbsp;<link linkend='v4l2-audioout'>v4l2_audioout</link>">
 <!ENTITY v4l2-bt-timings "struct&nbsp;<link linkend='v4l2-bt-timings'>v4l2_bt_timings</link>">
 <!ENTITY v4l2-buffer "struct&nbsp;<link linkend='v4l2-buffer'>v4l2_buffer</link>">
+<!ENTITY v4l2-plane "struct&nbsp;<link linkend='v4l2-plane'>v4l2_plane</link>">
 <!ENTITY v4l2-capability "struct&nbsp;<link linkend='v4l2-capability'>v4l2_capability</link>">
 <!ENTITY v4l2-captureparm "struct&nbsp;<link linkend='v4l2-captureparm'>v4l2_captureparm</link>">
 <!ENTITY v4l2-clip "struct&nbsp;<link linkend='v4l2-clip'>v4l2_clip</link>">
@@ -162,11 +182,14 @@
 <!ENTITY v4l2-hw-freq-seek "struct&nbsp;<link linkend='v4l2-hw-freq-seek'>v4l2_hw_freq_seek</link>">
 <!ENTITY v4l2-input "struct&nbsp;<link linkend='v4l2-input'>v4l2_input</link>">
 <!ENTITY v4l2-jpegcompression "struct&nbsp;<link linkend='v4l2-jpegcompression'>v4l2_jpegcompression</link>">
+<!ENTITY v4l2-mbus-framefmt "struct&nbsp;<link linkend='v4l2-mbus-framefmt'>v4l2_mbus_framefmt</link>">
 <!ENTITY v4l2-modulator "struct&nbsp;<link linkend='v4l2-modulator'>v4l2_modulator</link>">
 <!ENTITY v4l2-mpeg-vbi-fmt-ivtv "struct&nbsp;<link linkend='v4l2-mpeg-vbi-fmt-ivtv'>v4l2_mpeg_vbi_fmt_ivtv</link>">
 <!ENTITY v4l2-output "struct&nbsp;<link linkend='v4l2-output'>v4l2_output</link>">
 <!ENTITY v4l2-outputparm "struct&nbsp;<link linkend='v4l2-outputparm'>v4l2_outputparm</link>">
 <!ENTITY v4l2-pix-format "struct&nbsp;<link linkend='v4l2-pix-format'>v4l2_pix_format</link>">
+<!ENTITY v4l2-pix-format-mplane "struct&nbsp;<link linkend='v4l2-pix-format-mplane'>v4l2_pix_format_mplane</link>">
+<!ENTITY v4l2-plane-pix-format "struct&nbsp;<link linkend='v4l2-plane-pix-format'>v4l2_plane_pix_format</link>">
 <!ENTITY v4l2-queryctrl "struct&nbsp;<link linkend='v4l2-queryctrl'>v4l2_queryctrl</link>">
 <!ENTITY v4l2-querymenu "struct&nbsp;<link linkend='v4l2-querymenu'>v4l2_querymenu</link>">
 <!ENTITY v4l2-rect "struct&nbsp;<link linkend='v4l2-rect'>v4l2_rect</link>">
@@ -174,6 +197,12 @@
 <!ENTITY v4l2-sliced-vbi-cap "struct&nbsp;<link linkend='v4l2-sliced-vbi-cap'>v4l2_sliced_vbi_cap</link>">
 <!ENTITY v4l2-sliced-vbi-data "struct&nbsp;<link linkend='v4l2-sliced-vbi-data'>v4l2_sliced_vbi_data</link>">
 <!ENTITY v4l2-sliced-vbi-format "struct&nbsp;<link linkend='v4l2-sliced-vbi-format'>v4l2_sliced_vbi_format</link>">
+<!ENTITY v4l2-subdev-frame-interval "struct&nbsp;<link linkend='v4l2-subdev-frame-interval'>v4l2_subdev_frame_interval</link>">
+<!ENTITY v4l2-subdev-frame-interval-enum "struct&nbsp;<link linkend='v4l2-subdev-frame-interval-enum'>v4l2_subdev_frame_interval_enum</link>">
+<!ENTITY v4l2-subdev-frame-size-enum "struct&nbsp;<link linkend='v4l2-subdev-frame-size-enum'>v4l2_subdev_frame_size_enum</link>">
+<!ENTITY v4l2-subdev-crop "struct&nbsp;<link linkend='v4l2-subdev-crop'>v4l2_subdev_crop</link>">
+<!ENTITY v4l2-subdev-format "struct&nbsp;<link linkend='v4l2-subdev-format'>v4l2_subdev_format</link>">
+<!ENTITY v4l2-subdev-mbus-code-enum "struct&nbsp;<link linkend='v4l2-subdev-mbus-code-enum'>v4l2_subdev_mbus_code_enum</link>">
 <!ENTITY v4l2-standard "struct&nbsp;<link linkend='v4l2-standard'>v4l2_standard</link>">
 <!ENTITY v4l2-streamparm "struct&nbsp;<link linkend='v4l2-streamparm'>v4l2_streamparm</link>">
 <!ENTITY v4l2-timecode "struct&nbsp;<link linkend='v4l2-timecode'>v4l2_timecode</link>">
@@ -181,6 +210,12 @@
 <!ENTITY v4l2-vbi-format "struct&nbsp;<link linkend='v4l2-vbi-format'>v4l2_vbi_format</link>">
 <!ENTITY v4l2-window "struct&nbsp;<link linkend='v4l2-window'>v4l2_window</link>">
 
+<!ENTITY media-device-info "struct&nbsp;<link linkend='media-device-info'>media_device_info</link>">
+<!ENTITY media-entity-desc "struct&nbsp;<link linkend='media-entity-desc'>media_entity_desc</link>">
+<!ENTITY media-links-enum "struct&nbsp;<link linkend='media-links-enum'>media_links_enum</link>">
+<!ENTITY media-pad-desc "struct&nbsp;<link linkend='media-pad-desc'>media_pad_desc</link>">
+<!ENTITY media-link-desc "struct&nbsp;<link linkend='media-link-desc'>media_link_desc</link>">
+
 <!-- Error Codes -->
 <!ENTITY EACCES "<errorcode>EACCES</errorcode> error code">
 <!ENTITY EAGAIN "<errorcode>EAGAIN</errorcode> error code">
@@ -197,11 +232,13 @@
 <!ENTITY ENXIO "<errorcode>ENXIO</errorcode> error code">
 <!ENTITY EMFILE "<errorcode>EMFILE</errorcode> error code">
 <!ENTITY EPERM "<errorcode>EPERM</errorcode> error code">
+<!ENTITY EPIPE "<errorcode>EPIPE</errorcode> error code">
 <!ENTITY ERANGE "<errorcode>ERANGE</errorcode> error code">
 
 <!-- Subsections -->
 <!ENTITY sub-biblio SYSTEM "v4l/biblio.xml">
 <!ENTITY sub-common SYSTEM "v4l/common.xml">
+<!ENTITY sub-planar-apis SYSTEM "v4l/planar-apis.xml">
 <!ENTITY sub-compat SYSTEM "v4l/compat.xml">
 <!ENTITY sub-controls SYSTEM "v4l/controls.xml">
 <!ENTITY sub-dev-capture SYSTEM "v4l/dev-capture.xml">
@@ -215,6 +252,7 @@
 <!ENTITY sub-dev-raw-vbi SYSTEM "v4l/dev-raw-vbi.xml">
 <!ENTITY sub-dev-rds SYSTEM "v4l/dev-rds.xml">
 <!ENTITY sub-dev-sliced-vbi SYSTEM "v4l/dev-sliced-vbi.xml">
+<!ENTITY sub-dev-subdev SYSTEM "v4l/dev-subdev.xml">
 <!ENTITY sub-dev-teletext SYSTEM "v4l/dev-teletext.xml">
 <!ENTITY sub-driver SYSTEM "v4l/driver.xml">
 <!ENTITY sub-libv4l SYSTEM "v4l/libv4l.xml">
@@ -233,6 +271,8 @@
 <!ENTITY sub-io SYSTEM "v4l/io.xml">
 <!ENTITY sub-grey SYSTEM "v4l/pixfmt-grey.xml">
 <!ENTITY sub-nv12 SYSTEM "v4l/pixfmt-nv12.xml">
+<!ENTITY sub-nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
+<!ENTITY sub-nv12mt SYSTEM "v4l/pixfmt-nv12mt.xml">
 <!ENTITY sub-nv16 SYSTEM "v4l/pixfmt-nv16.xml">
 <!ENTITY sub-packed-rgb SYSTEM "v4l/pixfmt-packed-rgb.xml">
 <!ENTITY sub-packed-yuv SYSTEM "v4l/pixfmt-packed-yuv.xml">
@@ -247,12 +287,14 @@
 <!ENTITY sub-yuv410 SYSTEM "v4l/pixfmt-yuv410.xml">
 <!ENTITY sub-yuv411p SYSTEM "v4l/pixfmt-yuv411p.xml">
 <!ENTITY sub-yuv420 SYSTEM "v4l/pixfmt-yuv420.xml">
+<!ENTITY sub-yuv420m SYSTEM "v4l/pixfmt-yuv420m.xml">
 <!ENTITY sub-yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
 <!ENTITY sub-yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
 <!ENTITY sub-yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
 <!ENTITY sub-srggb10 SYSTEM "v4l/pixfmt-srggb10.xml">
 <!ENTITY sub-srggb8 SYSTEM "v4l/pixfmt-srggb8.xml">
 <!ENTITY sub-y10 SYSTEM "v4l/pixfmt-y10.xml">
+<!ENTITY sub-y12 SYSTEM "v4l/pixfmt-y12.xml">
 <!ENTITY sub-pixfmt SYSTEM "v4l/pixfmt.xml">
 <!ENTITY sub-cropcap SYSTEM "v4l/vidioc-cropcap.xml">
 <!ENTITY sub-dbg-g-register SYSTEM "v4l/vidioc-dbg-g-register.xml">
@@ -298,6 +340,13 @@
 <!ENTITY sub-reqbufs SYSTEM "v4l/vidioc-reqbufs.xml">
 <!ENTITY sub-s-hw-freq-seek SYSTEM "v4l/vidioc-s-hw-freq-seek.xml">
 <!ENTITY sub-streamon SYSTEM "v4l/vidioc-streamon.xml">
+<!ENTITY sub-subdev-enum-frame-interval SYSTEM "v4l/vidioc-subdev-enum-frame-interval.xml">
+<!ENTITY sub-subdev-enum-frame-size SYSTEM "v4l/vidioc-subdev-enum-frame-size.xml">
+<!ENTITY sub-subdev-enum-mbus-code SYSTEM "v4l/vidioc-subdev-enum-mbus-code.xml">
+<!ENTITY sub-subdev-formats SYSTEM "v4l/subdev-formats.xml">
+<!ENTITY sub-subdev-g-crop SYSTEM "v4l/vidioc-subdev-g-crop.xml">
+<!ENTITY sub-subdev-g-fmt SYSTEM "v4l/vidioc-subdev-g-fmt.xml">
+<!ENTITY sub-subdev-g-frame-interval SYSTEM "v4l/vidioc-subdev-g-frame-interval.xml">
 <!ENTITY sub-capture-c SYSTEM "v4l/capture.c.xml">
 <!ENTITY sub-keytable-c SYSTEM "v4l/keytable.c.xml">
 <!ENTITY sub-v4l2grab-c SYSTEM "v4l/v4l2grab.c.xml">
@@ -321,6 +370,15 @@
 <!ENTITY sub-media-entities SYSTEM "media-entities.tmpl">
 <!ENTITY sub-media-indices SYSTEM "media-indices.tmpl">
 
+<!ENTITY sub-media-controller SYSTEM "v4l/media-controller.xml">
+<!ENTITY sub-media-open SYSTEM "v4l/media-func-open.xml">
+<!ENTITY sub-media-close SYSTEM "v4l/media-func-close.xml">
+<!ENTITY sub-media-ioctl SYSTEM "v4l/media-func-ioctl.xml">
+<!ENTITY sub-media-ioc-device-info SYSTEM "v4l/media-ioc-device-info.xml">
+<!ENTITY sub-media-ioc-enum-entities SYSTEM "v4l/media-ioc-enum-entities.xml">
+<!ENTITY sub-media-ioc-enum-links SYSTEM "v4l/media-ioc-enum-links.xml">
+<!ENTITY sub-media-ioc-setup-link SYSTEM "v4l/media-ioc-setup-link.xml">
+
 <!-- Function Reference -->
 <!ENTITY close SYSTEM "v4l/func-close.xml">
 <!ENTITY ioctl SYSTEM "v4l/func-ioctl.xml">
@@ -333,6 +391,7 @@
 <!ENTITY write SYSTEM "v4l/func-write.xml">
 <!ENTITY grey SYSTEM "v4l/pixfmt-grey.xml">
 <!ENTITY nv12 SYSTEM "v4l/pixfmt-nv12.xml">
+<!ENTITY nv12m SYSTEM "v4l/pixfmt-nv12m.xml">
 <!ENTITY nv16 SYSTEM "v4l/pixfmt-nv16.xml">
 <!ENTITY packed-rgb SYSTEM "v4l/pixfmt-packed-rgb.xml">
 <!ENTITY packed-yuv SYSTEM "v4l/pixfmt-packed-yuv.xml">
@@ -347,6 +406,7 @@
 <!ENTITY yuv410 SYSTEM "v4l/pixfmt-yuv410.xml">
 <!ENTITY yuv411p SYSTEM "v4l/pixfmt-yuv411p.xml">
 <!ENTITY yuv420 SYSTEM "v4l/pixfmt-yuv420.xml">
+<!ENTITY yuv420m SYSTEM "v4l/pixfmt-yuv420m.xml">
 <!ENTITY yuv422p SYSTEM "v4l/pixfmt-yuv422p.xml">
 <!ENTITY yuyv SYSTEM "v4l/pixfmt-yuyv.xml">
 <!ENTITY yvyu SYSTEM "v4l/pixfmt-yvyu.xml">
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/media.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/media.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/media.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/media.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -106,6 +106,9 @@
 &sub-remote_controllers;
 </chapter>
 </part>
+<part id="media_common">
+&sub-media-controller;
+</part>
 
 &sub-fdl-appendix;
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/mtdnand.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/mtdnand.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/mtdnand.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/mtdnand.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -485,7 +485,7 @@
 				Reed-Solomon library.
 			</para>
 			<para>
-				The ECC bytes must be placed immidiately after the data
+				The ECC bytes must be placed immediately after the data
 				bytes in order to make the syndrome generator work. This
 				is contrary to the usual layout used by software ECC. The
 				separation of data and out of band area is not longer
@@ -629,7 +629,7 @@
 				holds the bad block table. Store a pointer to the pattern  
 				in the pattern field. Further the length of the pattern has to be 
 				stored in len and the offset in the spare area must be given
-				in the offs member of the nand_bbt_descr stucture. For mirrored
+				in the offs member of the nand_bbt_descr structure. For mirrored
 				bad block tables different patterns are mandatory.</para></listitem>
 				<listitem><para>Table creation</para>
 				<para>Set the option NAND_BBT_CREATE to enable the table creation
@@ -648,7 +648,7 @@
 				<listitem><para>Table version control</para>
 				<para>Set the option NAND_BBT_VERSION to enable the table version control.
 				It's highly recommended to enable this for mirrored tables with write
-				support. It makes sure that the risk of loosing the bad block
+				support. It makes sure that the risk of losing the bad block
 				table information is reduced to the loss of the information about the
 				one worn out block which should be marked bad. The version is stored in
 				4 consecutive bytes in the spare area of the device. The position of
@@ -1060,19 +1060,19 @@
 <row>
 <entry>0x3D</entry>
 <entry>ECC byte 21</entry>
-<entry>Error correction code byte 0 of the eigth 256 Bytes of data
+<entry>Error correction code byte 0 of the eighth 256 Bytes of data
 in this page</entry>
 </row>
 <row>
 <entry>0x3E</entry>
 <entry>ECC byte 22</entry>
-<entry>Error correction code byte 1 of the eigth 256 Bytes of data
+<entry>Error correction code byte 1 of the eighth 256 Bytes of data
 in this page</entry>
 </row>
 <row>
 <entry>0x3F</entry>
 <entry>ECC byte 23</entry>
-<entry>Error correction code byte 2 of the eigth 256 Bytes of data
+<entry>Error correction code byte 2 of the eighth 256 Bytes of data
 in this page</entry>
 </row>
 </tbody></tgroup></informaltable>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/rapidio.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/rapidio.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/rapidio.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/rapidio.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,6 @@
 !Idrivers/rapidio/rio-sysfs.c
      </sect1>
      <sect1 id="PPC32_support"><title>PPC32 support</title>
-!Earch/powerpc/sysdev/fsl_rio.c
 !Iarch/powerpc/sysdev/fsl_rio.c
      </sect1>
   </chapter>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/regulator.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/regulator.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/regulator.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/regulator.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -267,8 +267,8 @@
      <sect1 id="machine-constraint">
        <title>Constraints</title>
        <para>
-	 As well as definining the connections the machine interface
-	 also provides constraints definining the operations that
+	 As well as defining the connections the machine interface
+	 also provides constraints defining the operations that
 	 clients are allowed to perform and the parameters that may be
 	 set.  This is required since generally regulator devices will
 	 offer more flexibility than it is safe to use on a given
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/uio-howto.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/uio-howto.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/uio-howto.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/uio-howto.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -797,7 +797,7 @@
 	perform some initialization. After that, your hardware
 	starts working and will generate an interrupt as soon
 	as it's finished, has some data available, or needs your
-	attention because an error occured.
+	attention because an error occurred.
 	</para>
 	<para>
 	<filename>/dev/uioX</filename> is a read-only file. A
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/usb.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/usb.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/usb.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/usb.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -690,7 +690,7 @@
 		    </para><para>
 		    This request lets kernel drivers talk to user mode code
 		    through filesystem operations even when they don't create
-		    a charactor or block special device.
+		    a character or block special device.
 		    It's also been used to do things like ask devices what
 		    device special file should be used.
 		    Two pre-defined ioctls are used
Binary files linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/bayer.pdf and linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/bayer.pdf differ
Binary files linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/bayer.png and linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/bayer.png differ
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/common.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/common.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/common.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/common.xml	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,7 @@
 
       <para>By convention system administrators create various
 character device special files with these major and minor numbers in
-the <filename>/dev</filename> directory. The names recomended for the
+the <filename>/dev</filename> directory. The names recommended for the
 different V4L2 device types are listed in <xref linkend="devices" />.
 </para>
 
@@ -846,6 +846,8 @@
     </section>
   </section>
 
+  &sub-planar-apis;
+
   <section id="crop">
     <title>Image Cropping, Insertion and Scaling</title>
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/compat.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/compat.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/compat.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/compat.xml	2011-05-19 00:06:34.000000000 -0400
@@ -1711,8 +1711,8 @@
 determine the current audio input, if more than one combines with the
 current video input, did not exist. So
 <constant>VIDIOC_G_AUDIO</constant> was renamed to
-<constant>VIDIOC_G_AUDIO_OLD</constant>, this ioctl will be removed in
-the future. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate
+<constant>VIDIOC_G_AUDIO_OLD</constant>, this ioctl was removed on
+Kernel 2.6.39. The &VIDIOC-ENUMAUDIO; ioctl was added to enumerate
 audio inputs, while &VIDIOC-G-AUDIO; now reports the current audio
 input.</para>
 	  <para>The same changes were made to &VIDIOC-G-AUDOUT; and
@@ -1726,7 +1726,7 @@
 	  <para>The &VIDIOC-OVERLAY; ioctl was incorrectly defined with
 write-read parameter. It was changed to write-only, while the write-read
 version was renamed to <constant>VIDIOC_OVERLAY_OLD</constant>. The old
-ioctl will be removed in the future. Until further the "videodev"
+ioctl was removed on Kernel 2.6.39. Until further the "videodev"
 kernel module will automatically translate to the new version, so drivers
 must be recompiled, but not applications.</para>
 	</listitem>
@@ -1744,7 +1744,7 @@
 defined with write-only parameter, inconsistent with other ioctls
 modifying their argument. They were changed to write-read, while a
 <constant>_OLD</constant> suffix was added to the write-only versions.
-The old ioctls will be removed in the future. Drivers and
+The old ioctls were removed on Kernel 2.6.39. Drivers and
 applications assuming a constant parameter need an update.</para>
 	</listitem>
       </orderedlist>
@@ -1815,8 +1815,8 @@
 	  <para>The &VIDIOC-CROPCAP; ioctl was incorrectly defined
 with read-only parameter. It is now defined as write-read ioctl, while
 the read-only version was renamed to
-<constant>VIDIOC_CROPCAP_OLD</constant>. The old ioctl will be removed
-in the future.</para>
+<constant>VIDIOC_CROPCAP_OLD</constant>. The old ioctl was removed
+on Kernel 2.6.39.</para>
 	</listitem>
       </orderedlist>
     </section>
@@ -2353,6 +2353,20 @@
 	</listitem>
       </orderedlist>
     </section>
+    <section>
+      <title>V4L2 in Linux 2.6.39</title>
+      <orderedlist>
+        <listitem>
+          <para>The old VIDIOC_*_OLD symbols and V4L1 support were removed.</para>
+        </listitem>
+        <listitem>
+          <para>Multi-planar API added. Does not affect the compatibility of
+          current drivers and applications. See
+          <link linkend="planar-apis">multi-planar API</link>
+          for details.</para>
+        </listitem>
+      </orderedlist>
+    </section>
 
     <section id="other">
       <title>Relation of V4L2 to other Linux multimedia APIs</title>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/controls.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/controls.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/controls.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/controls.xml	2011-05-19 00:06:34.000000000 -0400
@@ -1243,7 +1243,7 @@
 	      </row><row><entry spanname="descr">Mutes the audio when
 capturing. This is not done by muting audio hardware, which can still
 produce a slight hiss, but in the encoder itself, guaranteeing a fixed
-and reproducable audio bitstream. 0 = unmuted, 1 = muted.</entry>
+and reproducible audio bitstream. 0 = unmuted, 1 = muted.</entry>
 	      </row>
 	      <row><entry></entry></row>
 	      <row id="v4l2-mpeg-video-encoding">
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/dev-capture.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/dev-capture.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/dev-capture.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/dev-capture.xml	2011-05-19 00:06:34.000000000 -0400
@@ -18,7 +18,8 @@
     <title>Querying Capabilities</title>
 
     <para>Devices supporting the video capture interface set the
-<constant>V4L2_CAP_VIDEO_CAPTURE</constant> flag in the
+<constant>V4L2_CAP_VIDEO_CAPTURE</constant> or
+<constant>V4L2_CAP_VIDEO_CAPTURE_MPLANE</constant> flag in the
 <structfield>capabilities</structfield> field of &v4l2-capability;
 returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions
 they may also support the <link linkend="overlay">video overlay</link>
@@ -64,9 +65,11 @@
 
     <para>To query the current image format applications set the
 <structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> and call the
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant> and call the
 &VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
-the &v4l2-pix-format; <structfield>pix</structfield> member of the
+the &v4l2-pix-format; <structfield>pix</structfield> or the
+&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
 <structfield>fmt</structfield> union.</para>
 
     <para>To request different parameters applications set the
@@ -84,8 +87,8 @@
 without disabling I/O or possibly time consuming hardware
 preparations.</para>
 
-    <para>The contents of &v4l2-pix-format; are discussed in <xref
-linkend="pixfmt" />. See also the specification of the
+    <para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
+are discussed in <xref linkend="pixfmt" />. See also the specification of the
 <constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
 and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
 capture devices must implement both the
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/dev-output.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/dev-output.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/dev-output.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/dev-output.xml	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,8 @@
     <title>Querying Capabilities</title>
 
     <para>Devices supporting the video output interface set the
-<constant>V4L2_CAP_VIDEO_OUTPUT</constant> flag in the
+<constant>V4L2_CAP_VIDEO_OUTPUT</constant> or
+<constant>V4L2_CAP_VIDEO_OUTPUT_MPLANE</constant> flag in the
 <structfield>capabilities</structfield> field of &v4l2-capability;
 returned by the &VIDIOC-QUERYCAP; ioctl. As secondary device functions
 they may also support the <link linkend="raw-vbi">raw VBI
@@ -60,9 +61,11 @@
 
     <para>To query the current image format applications set the
 <structfield>type</structfield> field of a &v4l2-format; to
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and call the
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> or
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and call the
 &VIDIOC-G-FMT; ioctl with a pointer to this structure. Drivers fill
-the &v4l2-pix-format; <structfield>pix</structfield> member of the
+the &v4l2-pix-format; <structfield>pix</structfield> or the
+&v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member of the
 <structfield>fmt</structfield> union.</para>
 
     <para>To request different parameters applications set the
@@ -80,8 +83,8 @@
 without disabling I/O or possibly time consuming hardware
 preparations.</para>
 
-    <para>The contents of &v4l2-pix-format; are discussed in <xref
-linkend="pixfmt" />. See also the specification of the
+    <para>The contents of &v4l2-pix-format; and &v4l2-pix-format-mplane;
+are discussed in <xref linkend="pixfmt" />. See also the specification of the
 <constant>VIDIOC_G_FMT</constant>, <constant>VIDIOC_S_FMT</constant>
 and <constant>VIDIOC_TRY_FMT</constant> ioctls for details. Video
 output devices must implement both the
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/dev-subdev.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/dev-subdev.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/dev-subdev.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/dev-subdev.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,313 @@
+  <title>Sub-device Interface</title>
+
+  <note>
+    <title>Experimental</title>
+    <para>This is an <link linkend="experimental">experimental</link>
+    interface and may change in the future.</para>
+  </note>
+
+  <para>The complex nature of V4L2 devices, where hardware is often made of
+  several integrated circuits that need to interact with each other in a
+  controlled way, leads to complex V4L2 drivers. The drivers usually reflect
+  the hardware model in software, and model the different hardware components
+  as software blocks called sub-devices.</para>
+
+  <para>V4L2 sub-devices are usually kernel-only objects. If the V4L2 driver
+  implements the media device API, they will automatically inherit from media
+  entities. Applications will be able to enumerate the sub-devices and discover
+  the hardware topology using the media entities, pads and links enumeration
+  API.</para>
+
+  <para>In addition to make sub-devices discoverable, drivers can also choose
+  to make them directly configurable by applications. When both the sub-device
+  driver and the V4L2 device driver support this, sub-devices will feature a
+  character device node on which ioctls can be called to
+  <itemizedlist>
+    <listitem><para>query, read and write sub-devices controls</para></listitem>
+    <listitem><para>subscribe and unsubscribe to events and retrieve them</para></listitem>
+    <listitem><para>negotiate image formats on individual pads</para></listitem>
+  </itemizedlist>
+  </para>
+
+  <para>Sub-device character device nodes, conventionally named
+  <filename>/dev/v4l-subdev*</filename>, use major number 81.</para>
+
+  <section>
+    <title>Controls</title>
+    <para>Most V4L2 controls are implemented by sub-device hardware. Drivers
+    usually merge all controls and expose them through video device nodes.
+    Applications can control all sub-devices through a single interface.</para>
+
+    <para>Complex devices sometimes implement the same control in different
+    pieces of hardware. This situation is common in embedded platforms, where
+    both sensors and image processing hardware implement identical functions,
+    such as contrast adjustment, white balance or faulty pixels correction. As
+    the V4L2 controls API doesn't support several identical controls in a single
+    device, all but one of the identical controls are hidden.</para>
+
+    <para>Applications can access those hidden controls through the sub-device
+    node with the V4L2 control API described in <xref linkend="control" />. The
+    ioctls behave identically as when issued on V4L2 device nodes, with the
+    exception that they deal only with controls implemented in the sub-device.
+    </para>
+
+    <para>Depending on the driver, those controls might also be exposed through
+    one (or several) V4L2 device nodes.</para>
+  </section>
+
+  <section>
+    <title>Events</title>
+    <para>V4L2 sub-devices can notify applications of events as described in
+    <xref linkend="event" />. The API behaves identically as when used on V4L2
+    device nodes, with the exception that it only deals with events generated by
+    the sub-device. Depending on the driver, those events might also be reported
+    on one (or several) V4L2 device nodes.</para>
+  </section>
+
+  <section id="pad-level-formats">
+    <title>Pad-level Formats</title>
+
+    <warning><para>Pad-level formats are only applicable to very complex device that
+    need to expose low-level format configuration to user space. Generic V4L2
+    applications do <emphasis>not</emphasis> need to use the API described in
+    this section.</para></warning>
+
+    <note><para>For the purpose of this section, the term
+    <wordasword>format</wordasword> means the combination of media bus data
+    format, frame width and frame height.</para></note>
+
+    <para>Image formats are typically negotiated on video capture and output
+    devices using the <link linkend="crop">cropping and scaling</link> ioctls.
+    The driver is responsible for configuring every block in the video pipeline
+    according to the requested format at the pipeline input and/or
+    output.</para>
+
+    <para>For complex devices, such as often found in embedded systems,
+    identical image sizes at the output of a pipeline can be achieved using
+    different hardware configurations. One such example is shown on
+    <xref linkend="pipeline-scaling" />, where
+    image scaling can be performed on both the video sensor and the host image
+    processing hardware.</para>
+
+    <figure id="pipeline-scaling">
+      <title>Image Format Negotiation on Pipelines</title>
+      <mediaobject>
+	<imageobject>
+	  <imagedata fileref="pipeline.pdf" format="PS" />
+	</imageobject>
+	<imageobject>
+	  <imagedata fileref="pipeline.png" format="PNG" />
+	</imageobject>
+	<textobject>
+	  <phrase>High quality and high speed pipeline configuration</phrase>
+	</textobject>
+      </mediaobject>
+    </figure>
+
+    <para>The sensor scaler is usually of less quality than the host scaler, but
+    scaling on the sensor is required to achieve higher frame rates. Depending
+    on the use case (quality vs. speed), the pipeline must be configured
+    differently. Applications need to configure the formats at every point in
+    the pipeline explicitly.</para>
+
+    <para>Drivers that implement the <link linkend="media-controller-intro">media
+    API</link> can expose pad-level image format configuration to applications.
+    When they do, applications can use the &VIDIOC-SUBDEV-G-FMT; and
+    &VIDIOC-SUBDEV-S-FMT; ioctls. to negotiate formats on a per-pad basis.</para>
+
+    <para>Applications are responsible for configuring coherent parameters on
+    the whole pipeline and making sure that connected pads have compatible
+    formats. The pipeline is checked for formats mismatch at &VIDIOC-STREAMON;
+    time, and an &EPIPE; is then returned if the configuration is
+    invalid.</para>
+
+    <para>Pad-level image format configuration support can be tested by calling
+    the &VIDIOC-SUBDEV-G-FMT; ioctl on pad 0. If the driver returns an &EINVAL;
+    pad-level format configuration is not supported by the sub-device.</para>
+
+    <section>
+      <title>Format Negotiation</title>
+
+      <para>Acceptable formats on pads can (and usually do) depend on a number
+      of external parameters, such as formats on other pads, active links, or
+      even controls. Finding a combination of formats on all pads in a video
+      pipeline, acceptable to both application and driver, can't rely on formats
+      enumeration only. A format negotiation mechanism is required.</para>
+
+      <para>Central to the format negotiation mechanism are the get/set format
+      operations. When called with the <structfield>which</structfield> argument
+      set to <constant>V4L2_SUBDEV_FORMAT_TRY</constant>, the
+      &VIDIOC-SUBDEV-G-FMT; and &VIDIOC-SUBDEV-S-FMT; ioctls operate on a set of
+      formats parameters that are not connected to the hardware configuration.
+      Modifying those 'try' formats leaves the device state untouched (this
+      applies to both the software state stored in the driver and the hardware
+      state stored in the device itself).</para>
+
+      <para>While not kept as part of the device state, try formats are stored
+      in the sub-device file handles. A &VIDIOC-SUBDEV-G-FMT; call will return
+      the last try format set <emphasis>on the same sub-device file
+      handle</emphasis>. Several applications querying the same sub-device at
+      the same time will thus not interact with each other.</para>
+
+      <para>To find out whether a particular format is supported by the device,
+      applications use the &VIDIOC-SUBDEV-S-FMT; ioctl. Drivers verify and, if
+      needed, change the requested <structfield>format</structfield> based on
+      device requirements and return the possibly modified value. Applications
+      can then choose to try a different format or accept the returned value and
+      continue.</para>
+
+      <para>Formats returned by the driver during a negotiation iteration are
+      guaranteed to be supported by the device. In particular, drivers guarantee
+      that a returned format will not be further changed if passed to an
+      &VIDIOC-SUBDEV-S-FMT; call as-is (as long as external parameters, such as
+      formats on other pads or links' configuration are not changed).</para>
+
+      <para>Drivers automatically propagate formats inside sub-devices. When a
+      try or active format is set on a pad, corresponding formats on other pads
+      of the same sub-device can be modified by the driver. Drivers are free to
+      modify formats as required by the device. However, they should comply with
+      the following rules when possible:
+      <itemizedlist>
+        <listitem><para>Formats should be propagated from sink pads to source pads.
+	Modifying a format on a source pad should not modify the format on any
+	sink pad.</para></listitem>
+        <listitem><para>Sub-devices that scale frames using variable scaling factors
+	should reset the scale factors to default values when sink pads formats
+	are modified. If the 1:1 scaling ratio is supported, this means that
+	source pads formats should be reset to the sink pads formats.</para></listitem>
+      </itemizedlist>
+      </para>
+
+      <para>Formats are not propagated across links, as that would involve
+      propagating them from one sub-device file handle to another. Applications
+      must then take care to configure both ends of every link explicitly with
+      compatible formats. Identical formats on the two ends of a link are
+      guaranteed to be compatible. Drivers are free to accept different formats
+      matching device requirements as being compatible.</para>
+
+      <para><xref linkend="sample-pipeline-config" />
+      shows a sample configuration sequence for the pipeline described in
+      <xref linkend="pipeline-scaling" /> (table
+      columns list entity names and pad numbers).</para>
+
+      <table pgwide="0" frame="none" id="sample-pipeline-config">
+	<title>Sample Pipeline Configuration</title>
+	<tgroup cols="3">
+	  <colspec colname="what"/>
+	  <colspec colname="sensor-0" />
+	  <colspec colname="frontend-0" />
+	  <colspec colname="frontend-1" />
+	  <colspec colname="scaler-0" />
+	  <colspec colname="scaler-1" />
+	  <thead>
+	    <row>
+	      <entry></entry>
+	      <entry>Sensor/0</entry>
+	      <entry>Frontend/0</entry>
+	      <entry>Frontend/1</entry>
+	      <entry>Scaler/0</entry>
+	      <entry>Scaler/1</entry>
+	    </row>
+	  </thead>
+	  <tbody valign="top">
+	    <row>
+	      <entry>Initial state</entry>
+	      <entry>2048x1536</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	    </row>
+	    <row>
+	      <entry>Configure frontend input</entry>
+	      <entry>2048x1536</entry>
+	      <entry><emphasis>2048x1536</emphasis></entry>
+	      <entry><emphasis>2046x1534</emphasis></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	    </row>
+	    <row>
+	      <entry>Configure scaler input</entry>
+	      <entry>2048x1536</entry>
+	      <entry>2048x1536</entry>
+	      <entry>2046x1534</entry>
+	      <entry><emphasis>2046x1534</emphasis></entry>
+	      <entry><emphasis>2046x1534</emphasis></entry>
+	    </row>
+	    <row>
+	      <entry>Configure scaler output</entry>
+	      <entry>2048x1536</entry>
+	      <entry>2048x1536</entry>
+	      <entry>2046x1534</entry>
+	      <entry>2046x1534</entry>
+	      <entry><emphasis>1280x960</emphasis></entry>
+	    </row>
+	  </tbody>
+	</tgroup>
+      </table>
+
+      <para>
+      <orderedlist>
+	<listitem><para>Initial state. The sensor output is set to its native 3MP
+	resolution. Resolutions on the host frontend and scaler input and output
+	pads are undefined.</para></listitem>
+	<listitem><para>The application configures the frontend input pad resolution to
+	2048x1536. The driver propagates the format to the frontend output pad.
+	Note that the propagated output format can be different, as in this case,
+	than the input format, as the hardware might need to crop pixels (for
+	instance when converting a Bayer filter pattern to RGB or YUV).</para></listitem>
+	<listitem><para>The application configures the scaler input pad resolution to
+	2046x1534 to match the frontend output resolution. The driver propagates
+	the format to the scaler output pad.</para></listitem>
+	<listitem><para>The application configures the scaler output pad resolution to
+	1280x960.</para></listitem>
+      </orderedlist>
+      </para>
+
+      <para>When satisfied with the try results, applications can set the active
+      formats by setting the <structfield>which</structfield> argument to
+      <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. Active formats are changed
+      exactly as try formats by drivers. To avoid modifying the hardware state
+      during format negotiation, applications should negotiate try formats first
+      and then modify the active settings using the try formats returned during
+      the last negotiation iteration. This guarantees that the active format
+      will be applied as-is by the driver without being modified.
+      </para>
+    </section>
+
+    <section>
+      <title>Cropping and scaling</title>
+
+      <para>Many sub-devices support cropping frames on their input or output
+      pads (or possible even on both). Cropping is used to select the area of
+      interest in an image, typically on a video sensor or video decoder. It can
+      also be used as part of digital zoom implementations to select the area of
+      the image that will be scaled up.</para>
+
+      <para>Crop settings are defined by a crop rectangle and represented in a
+      &v4l2-rect; by the coordinates of the top left corner and the rectangle
+      size. Both the coordinates and sizes are expressed in pixels.</para>
+
+      <para>The crop rectangle is retrieved and set using the
+      &VIDIOC-SUBDEV-G-CROP; and &VIDIOC-SUBDEV-S-CROP; ioctls. Like for pad
+      formats, drivers store try and active crop rectangles. The format
+      negotiation mechanism applies to crop settings as well.</para>
+
+      <para>On input pads, cropping is applied relatively to the current pad
+      format. The pad format represents the image size as received by the
+      sub-device from the previous block in the pipeline, and the crop rectangle
+      represents the sub-image that will be transmitted further inside the
+      sub-device for processing. The crop rectangle be entirely containted
+      inside the input image size.</para>
+
+      <para>Input crop rectangle are reset to their default value when the input
+      image format is modified. Drivers should use the input image size as the
+      crop rectangle default value, but hardware requirements may prevent this.
+      </para>
+
+      <para>Cropping behaviour on output pads is not defined.</para>
+
+    </section>
+  </section>
+
+  &sub-subdev-formats;
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/func-mmap.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/func-mmap.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/func-mmap.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/func-mmap.xml	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,10 @@
 	<listitem>
 	  <para>Length of the memory area to map. This must be the
 same value as returned by the driver in the &v4l2-buffer;
-<structfield>length</structfield> field.</para>
+<structfield>length</structfield> field for the
+single-planar API, and the same value as returned by the driver
+in the &v4l2-plane; <structfield>length</structfield> field for the
+multi-planar API.</para>
 	</listitem>
       </varlistentry>
       <varlistentry>
@@ -106,7 +109,10 @@
 	<listitem>
 	  <para>Offset of the buffer in device memory. This must be the
 same value as returned by the driver in the &v4l2-buffer;
-<structfield>m</structfield> union <structfield>offset</structfield> field.</para>
+<structfield>m</structfield> union <structfield>offset</structfield> field for
+the single-planar API, and the same value as returned by the driver
+in the &v4l2-plane; <structfield>m</structfield> union
+<structfield>mem_offset</structfield> field for the multi-planar API.</para>
 	</listitem>
       </varlistentry>
     </variablelist>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/func-munmap.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/func-munmap.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/func-munmap.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/func-munmap.xml	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,8 @@
 	  <para>Length of the mapped buffer. This must be the same
 value as given to <function>mmap()</function> and returned by the
 driver in the &v4l2-buffer; <structfield>length</structfield>
-field.</para>
+field for the single-planar API and in the &v4l2-plane;
+<structfield>length</structfield> field for the multi-planar API.</para>
 	</listitem>
       </varlistentry>
     </variablelist>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/io.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/io.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/io.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/io.xml	2011-05-19 00:06:34.000000000 -0400
@@ -121,18 +121,22 @@
     <para>Before applications can access the buffers they must map
 them into their address space with the &func-mmap; function. The
 location of the buffers in device memory can be determined with the
-&VIDIOC-QUERYBUF; ioctl. The <structfield>m.offset</structfield> and
-<structfield>length</structfield> returned in a &v4l2-buffer; are
-passed as sixth and second parameter to the
-<function>mmap()</function> function. The offset and length values
-must not be modified. Remember the buffers are allocated in physical
-memory, as opposed to virtual memory which can be swapped out to disk.
-Applications should free the buffers as soon as possible with the
-&func-munmap; function.</para>
+&VIDIOC-QUERYBUF; ioctl. In the single-planar API case, the
+<structfield>m.offset</structfield> and <structfield>length</structfield>
+returned in a &v4l2-buffer; are passed as sixth and second parameter to the
+<function>mmap()</function> function. When using the multi-planar API,
+struct &v4l2-buffer; contains an array of &v4l2-plane; structures, each
+containing its own <structfield>m.offset</structfield> and
+<structfield>length</structfield>. When using the multi-planar API, every
+plane of every buffer has to be mapped separately, so the number of
+calls to &func-mmap; should be equal to number of buffers times number of
+planes in each buffer. The offset and length values must not be modified.
+Remember, the buffers are allocated in physical memory, as opposed to virtual
+memory, which can be swapped out to disk. Applications should free the buffers
+as soon as possible with the &func-munmap; function.</para>
 
     <example>
-      <title>Mapping buffers</title>
-
+      <title>Mapping buffers in the single-planar API</title>
       <programlisting>
 &v4l2-requestbuffers; reqbuf;
 struct {
@@ -141,63 +145,145 @@
 } *buffers;
 unsigned int i;
 
-memset (&amp;reqbuf, 0, sizeof (reqbuf));
+memset(&amp;reqbuf, 0, sizeof(reqbuf));
 reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 reqbuf.memory = V4L2_MEMORY_MMAP;
 reqbuf.count = 20;
 
 if (-1 == ioctl (fd, &VIDIOC-REQBUFS;, &amp;reqbuf)) {
 	if (errno == EINVAL)
-		printf ("Video capturing or mmap-streaming is not supported\n");
+		printf("Video capturing or mmap-streaming is not supported\n");
 	else
-		perror ("VIDIOC_REQBUFS");
+		perror("VIDIOC_REQBUFS");
 
-	exit (EXIT_FAILURE);
+	exit(EXIT_FAILURE);
 }
 
 /* We want at least five buffers. */
 
 if (reqbuf.count &lt; 5) {
 	/* You may need to free the buffers here. */
-	printf ("Not enough buffer memory\n");
-	exit (EXIT_FAILURE);
+	printf("Not enough buffer memory\n");
+	exit(EXIT_FAILURE);
 }
 
-buffers = calloc (reqbuf.count, sizeof (*buffers));
-assert (buffers != NULL);
+buffers = calloc(reqbuf.count, sizeof(*buffers));
+assert(buffers != NULL);
 
 for (i = 0; i &lt; reqbuf.count; i++) {
 	&v4l2-buffer; buffer;
 
-	memset (&amp;buffer, 0, sizeof (buffer));
+	memset(&amp;buffer, 0, sizeof(buffer));
 	buffer.type = reqbuf.type;
 	buffer.memory = V4L2_MEMORY_MMAP;
 	buffer.index = i;
 
 	if (-1 == ioctl (fd, &VIDIOC-QUERYBUF;, &amp;buffer)) {
-		perror ("VIDIOC_QUERYBUF");
-		exit (EXIT_FAILURE);
+		perror("VIDIOC_QUERYBUF");
+		exit(EXIT_FAILURE);
 	}
 
 	buffers[i].length = buffer.length; /* remember for munmap() */
 
-	buffers[i].start = mmap (NULL, buffer.length,
-				 PROT_READ | PROT_WRITE, /* recommended */
-				 MAP_SHARED,             /* recommended */
-				 fd, buffer.m.offset);
+	buffers[i].start = mmap(NULL, buffer.length,
+				PROT_READ | PROT_WRITE, /* recommended */
+				MAP_SHARED,             /* recommended */
+				fd, buffer.m.offset);
 
 	if (MAP_FAILED == buffers[i].start) {
 		/* If you do not exit here you should unmap() and free()
 		   the buffers mapped so far. */
-		perror ("mmap");
-		exit (EXIT_FAILURE);
+		perror("mmap");
+		exit(EXIT_FAILURE);
 	}
 }
 
 /* Cleanup. */
 
 for (i = 0; i &lt; reqbuf.count; i++)
-	munmap (buffers[i].start, buffers[i].length);
+	munmap(buffers[i].start, buffers[i].length);
+      </programlisting>
+    </example>
+
+    <example>
+      <title>Mapping buffers in the multi-planar API</title>
+      <programlisting>
+&v4l2-requestbuffers; reqbuf;
+/* Our current format uses 3 planes per buffer */
+#define FMT_NUM_PLANES = 3;
+
+struct {
+	void *start[FMT_NUM_PLANES];
+	size_t length[FMT_NUM_PLANES];
+} *buffers;
+unsigned int i, j;
+
+memset(&amp;reqbuf, 0, sizeof(reqbuf));
+reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+reqbuf.memory = V4L2_MEMORY_MMAP;
+reqbuf.count = 20;
+
+if (ioctl(fd, &VIDIOC-REQBUFS;, &amp;reqbuf) &lt; 0) {
+	if (errno == EINVAL)
+		printf("Video capturing or mmap-streaming is not supported\n");
+	else
+		perror("VIDIOC_REQBUFS");
+
+	exit(EXIT_FAILURE);
+}
+
+/* We want at least five buffers. */
+
+if (reqbuf.count &lt; 5) {
+	/* You may need to free the buffers here. */
+	printf("Not enough buffer memory\n");
+	exit(EXIT_FAILURE);
+}
+
+buffers = calloc(reqbuf.count, sizeof(*buffers));
+assert(buffers != NULL);
+
+for (i = 0; i &lt; reqbuf.count; i++) {
+	&v4l2-buffer; buffer;
+	&v4l2-plane; planes[FMT_NUM_PLANES];
+
+	memset(&amp;buffer, 0, sizeof(buffer));
+	buffer.type = reqbuf.type;
+	buffer.memory = V4L2_MEMORY_MMAP;
+	buffer.index = i;
+	/* length in struct v4l2_buffer in multi-planar API stores the size
+	 * of planes array. */
+	buffer.length = FMT_NUM_PLANES;
+	buffer.m.planes = planes;
+
+	if (ioctl(fd, &VIDIOC-QUERYBUF;, &amp;buffer) &lt; 0) {
+		perror("VIDIOC_QUERYBUF");
+		exit(EXIT_FAILURE);
+	}
+
+	/* Every plane has to be mapped separately */
+	for (j = 0; j &lt; FMT_NUM_PLANES; j++) {
+		buffers[i].length[j] = buffer.m.planes[j].length; /* remember for munmap() */
+
+		buffers[i].start[j] = mmap(NULL, buffer.m.planes[j].length,
+				 PROT_READ | PROT_WRITE, /* recommended */
+				 MAP_SHARED,             /* recommended */
+				 fd, buffer.m.planes[j].m.offset);
+
+		if (MAP_FAILED == buffers[i].start[j]) {
+			/* If you do not exit here you should unmap() and free()
+			   the buffers and planes mapped so far. */
+			perror("mmap");
+			exit(EXIT_FAILURE);
+		}
+	}
+}
+
+/* Cleanup. */
+
+for (i = 0; i &lt; reqbuf.count; i++)
+	for (j = 0; j &lt; FMT_NUM_PLANES; j++)
+		munmap(buffers[i].start[j], buffers[i].length[j]);
       </programlisting>
     </example>
 
@@ -286,13 +372,13 @@
 determined by calling the &VIDIOC-REQBUFS; ioctl.</para>
 
     <para>This I/O method combines advantages of the read/write and
-memory mapping methods. Buffers are allocated by the application
+memory mapping methods. Buffers (planes) are allocated by the application
 itself, and can reside for example in virtual or shared memory. Only
 pointers to data are exchanged, these pointers and meta-information
-are passed in &v4l2-buffer;. The driver must be switched
-into user pointer I/O mode by calling the &VIDIOC-REQBUFS; with the
-desired buffer type. No buffers are allocated beforehands,
-consequently they are not indexed and cannot be queried like mapped
+are passed in &v4l2-buffer; (or in &v4l2-plane; in the multi-planar API case).
+The driver must be switched into user pointer I/O mode by calling the
+&VIDIOC-REQBUFS; with the desired buffer type. No buffers (planes) are allocated
+beforehand, consequently they are not indexed and cannot be queried like mapped
 buffers with the <constant>VIDIOC_QUERYBUF</constant> ioctl.</para>
 
     <example>
@@ -316,7 +402,7 @@
       </programlisting>
     </example>
 
-    <para>Buffer addresses and sizes are passed on the fly with the
+    <para>Buffer (plane) addresses and sizes are passed on the fly with the
 &VIDIOC-QBUF; ioctl. Although buffers are commonly cycled,
 applications can pass different addresses and sizes at each
 <constant>VIDIOC_QBUF</constant> call. If required by the hardware the
@@ -396,11 +482,18 @@
     <title>Buffers</title>
 
     <para>A buffer contains data exchanged by application and
-driver using one of the Streaming I/O methods. Only pointers to
-buffers are exchanged, the data itself is not copied. These pointers,
-together with meta-information like timestamps or field parity, are
-stored in a struct <structname>v4l2_buffer</structname>, argument to
-the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl.</para>
+driver using one of the Streaming I/O methods. In the multi-planar API, the
+data is held in planes, while the buffer structure acts as a container
+for the planes. Only pointers to buffers (planes) are exchanged, the data
+itself is not copied. These pointers, together with meta-information like
+timestamps or field parity, are stored in a struct
+<structname>v4l2_buffer</structname>, argument to
+the &VIDIOC-QUERYBUF;, &VIDIOC-QBUF; and &VIDIOC-DQBUF; ioctl.
+In the multi-planar API, some plane-specific members of struct
+<structname>v4l2_buffer</structname>, such as pointers and sizes for each
+plane, are stored in struct <structname>v4l2_plane</structname> instead.
+In that case, struct <structname>v4l2_buffer</structname> contains an array of
+plane structures.</para>
 
       <para>Nominally timestamps refer to the first data byte transmitted.
 In practice however the wide range of hardware covered by the V4L2 API
@@ -551,26 +644,40 @@
 	    <entry></entry>
 	    <entry>__u32</entry>
 	    <entry><structfield>offset</structfield></entry>
-	    <entry>When <structfield>memory</structfield> is
-<constant>V4L2_MEMORY_MMAP</constant> this is the offset of the buffer
-from the start of the device memory. The value is returned by the
-driver and apart of serving as parameter to the &func-mmap; function
-not useful for applications. See <xref linkend="mmap" /> for details.</entry>
+	    <entry>For the single-planar API and when
+<structfield>memory</structfield> is <constant>V4L2_MEMORY_MMAP</constant> this
+is the offset of the buffer from the start of the device memory. The value is
+returned by the driver and apart of serving as parameter to the &func-mmap;
+function not useful for applications. See <xref linkend="mmap" /> for details
+	  </entry>
 	  </row>
 	  <row>
 	    <entry></entry>
 	    <entry>unsigned long</entry>
 	    <entry><structfield>userptr</structfield></entry>
-	    <entry>When <structfield>memory</structfield> is
-<constant>V4L2_MEMORY_USERPTR</constant> this is a pointer to the
-buffer (casted to unsigned long type) in virtual memory, set by the
-application. See <xref linkend="userp" /> for details.</entry>
+	    <entry>For the single-planar API and when
+<structfield>memory</structfield> is <constant>V4L2_MEMORY_USERPTR</constant>
+this is a pointer to the buffer (casted to unsigned long type) in virtual
+memory, set by the application. See <xref linkend="userp" /> for details.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>struct v4l2_plane</entry>
+	    <entry><structfield>*planes</structfield></entry>
+	    <entry>When using the multi-planar API, contains a userspace pointer
+	    to an array of &v4l2-plane;. The size of the array should be put
+	    in the <structfield>length</structfield> field of this
+	    <structname>v4l2_buffer</structname> structure.</entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
 	    <entry><structfield>length</structfield></entry>
 	    <entry></entry>
-	    <entry>Size of the buffer (not the payload) in bytes.</entry>
+	    <entry>Size of the buffer (not the payload) in bytes for the
+	    single-planar API. For the multi-planar API should contain the
+	    number of elements in the <structfield>planes</structfield> array.
+	    </entry>
 	  </row>
 	  <row>
 	    <entry>__u32</entry>
@@ -596,6 +703,66 @@
       </tgroup>
     </table>
 
+    <table frame="none" pgwide="1" id="v4l2-plane">
+      <title>struct <structname>v4l2_plane</structname></title>
+      <tgroup cols="4">
+        &cs-ustr;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>bytesused</structfield></entry>
+	    <entry></entry>
+	    <entry>The number of bytes occupied by data in the plane
+	    (its payload).</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>length</structfield></entry>
+	    <entry></entry>
+	    <entry>Size in bytes of the plane (not its payload).</entry>
+	  </row>
+	  <row>
+	    <entry>union</entry>
+	    <entry><structfield>m</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>mem_offset</structfield></entry>
+	    <entry>When the memory type in the containing &v4l2-buffer; is
+	      <constant>V4L2_MEMORY_MMAP</constant>, this is the value that
+	      should be passed to &func-mmap;, similar to the
+	      <structfield>offset</structfield> field in &v4l2-buffer;.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__unsigned long</entry>
+	    <entry><structfield>userptr</structfield></entry>
+	    <entry>When the memory type in the containing &v4l2-buffer; is
+	      <constant>V4L2_MEMORY_USERPTR</constant>, this is a userspace
+	      pointer to the memory allocated for this plane by an application.
+	      </entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>data_offset</structfield></entry>
+	    <entry></entry>
+	    <entry>Offset in bytes to video data in the plane, if applicable.
+	    </entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved[11]</structfield></entry>
+	    <entry></entry>
+	    <entry>Reserved for future use. Should be zeroed by an
+	    application.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
     <table frame="none" pgwide="1" id="v4l2-buf-type">
       <title>enum v4l2_buf_type</title>
       <tgroup cols="3">
@@ -604,13 +771,27 @@
 	  <row>
 	    <entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant></entry>
 	    <entry>1</entry>
-	    <entry>Buffer of a video capture stream, see <xref
+	    <entry>Buffer of a single-planar video capture stream, see <xref
+		linkend="capture" />.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>
+	    </entry>
+	    <entry>9</entry>
+	    <entry>Buffer of a multi-planar video capture stream, see <xref
 		linkend="capture" />.</entry>
 	  </row>
 	  <row>
 	    <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant></entry>
 	    <entry>2</entry>
-	    <entry>Buffer of a video output stream, see <xref
+	    <entry>Buffer of a single-planar video output stream, see <xref
+		linkend="output" />.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>
+	    </entry>
+	    <entry>10</entry>
+	    <entry>Buffer of a multi-planar video output stream, see <xref
 		linkend="output" />.</entry>
 	  </row>
 	  <row>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/libv4l.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/libv4l.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/libv4l.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/libv4l.xml	2011-05-19 00:06:34.000000000 -0400
@@ -140,7 +140,7 @@
 			<para>int v4l2_get_control(int fd, int cid) -
 This function returns a value of 0 - 65535, scaled to from the actual range
 of the given v4l control id. when the cid does not exist, could not be
-accessed for some reason, or some error occured 0 is returned.
+accessed for some reason, or some error occurred 0 is returned.
 </para></listitem>
 </itemizedlist>
 		</section>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/lirc_device_interface.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/lirc_device_interface.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/lirc_device_interface.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/lirc_device_interface.xml	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 <para>The data written to the chardev is a pulse/space sequence of integer
 values. Pulses and spaces are only marked implicitly by their position. The
 data must start and end with a pulse, therefore, the data must always include
-an unevent number of samples. The write function must block until the data has
+an uneven number of samples. The write function must block until the data has
 been transmitted by the hardware.</para>
 </section>
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-controller.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-controller.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-controller.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-controller.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,89 @@
+<partinfo>
+  <authorgroup>
+    <author>
+      <firstname>Laurent</firstname>
+      <surname>Pinchart</surname>
+      <affiliation><address><email>laurent.pinchart@ideasonboard.com</email></address></affiliation>
+      <contrib>Initial version.</contrib>
+    </author>
+  </authorgroup>
+  <copyright>
+    <year>2010</year>
+    <holder>Laurent Pinchart</holder>
+  </copyright>
+
+  <revhistory>
+    <!-- Put document revisions here, newest first. -->
+    <revision>
+      <revnumber>1.0.0</revnumber>
+      <date>2010-11-10</date>
+      <authorinitials>lp</authorinitials>
+      <revremark>Initial revision</revremark>
+    </revision>
+  </revhistory>
+</partinfo>
+
+<title>Media Controller API</title>
+
+<chapter id="media_controller">
+  <title>Media Controller</title>
+
+  <section id="media-controller-intro">
+    <title>Introduction</title>
+    <para>Media devices increasingly handle multiple related functions. Many USB
+    cameras include microphones, video capture hardware can also output video,
+    or SoC camera interfaces also perform memory-to-memory operations similar to
+    video codecs.</para>
+    <para>Independent functions, even when implemented in the same hardware, can
+    be modelled as separate devices. A USB camera with a microphone will be
+    presented to userspace applications as V4L2 and ALSA capture devices. The
+    devices' relationships (when using a webcam, end-users shouldn't have to
+    manually select the associated USB microphone), while not made available
+    directly to applications by the drivers, can usually be retrieved from
+    sysfs.</para>
+    <para>With more and more advanced SoC devices being introduced, the current
+    approach will not scale. Device topologies are getting increasingly complex
+    and can't always be represented by a tree structure. Hardware blocks are
+    shared between different functions, creating dependencies between seemingly
+    unrelated devices.</para>
+    <para>Kernel abstraction APIs such as V4L2 and ALSA provide means for
+    applications to access hardware parameters. As newer hardware expose an
+    increasingly high number of those parameters, drivers need to guess what
+    applications really require based on limited information, thereby
+    implementing policies that belong to userspace.</para>
+    <para>The media controller API aims at solving those problems.</para>
+  </section>
+
+  <section id="media-controller-model">
+    <title>Media device model</title>
+    <para>Discovering a device internal topology, and configuring it at runtime,
+    is one of the goals of the media controller API. To achieve this, hardware
+    devices are modelled as an oriented graph of building blocks called entities
+    connected through pads.</para>
+    <para>An entity is a basic media hardware or software building block. It can
+    correspond to a large variety of logical blocks such as physical hardware
+    devices (CMOS sensor for instance), logical hardware devices (a building
+    block in a System-on-Chip image processing pipeline), DMA channels or
+    physical connectors.</para>
+    <para>A pad is a connection endpoint through which an entity can interact
+    with other entities. Data (not restricted to video) produced by an entity
+    flows from the entity's output to one or more entity inputs. Pads should not
+    be confused with physical pins at chip boundaries.</para>
+    <para>A link is a point-to-point oriented connection between two pads,
+    either on the same entity or on different entities. Data flows from a source
+    pad to a sink pad.</para>
+  </section>
+</chapter>
+
+<appendix id="media-user-func">
+  <title>Function Reference</title>
+  <!-- Keep this alphabetically sorted. -->
+  &sub-media-open;
+  &sub-media-close;
+  &sub-media-ioctl;
+  <!-- All ioctls go here. -->
+  &sub-media-ioc-device-info;
+  &sub-media-ioc-enum-entities;
+  &sub-media-ioc-enum-links;
+  &sub-media-ioc-setup-link;
+</appendix>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-func-close.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-func-close.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-func-close.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-func-close.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,59 @@
+<refentry id="media-func-close">
+  <refmeta>
+    <refentrytitle>media close()</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>media-close</refname>
+    <refpurpose>Close a media device</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;unistd.h&gt;</funcsynopsisinfo>
+      <funcprototype>
+	<funcdef>int <function>close</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>Closes the media device. Resources associated with the file descriptor
+    are freed. The device configuration remain unchanged.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para><function>close</function> returns 0 on success. On error, -1 is
+    returned, and <varname>errno</varname> is set appropriately. Possible error
+    codes are:</para>
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBADF</errorcode></term>
+	<listitem>
+	  <para><parameter>fd</parameter> is not a valid open file descriptor.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-func-ioctl.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-func-ioctl.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-func-ioctl.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-func-ioctl.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,116 @@
+<refentry id="media-func-ioctl">
+  <refmeta>
+    <refentrytitle>media ioctl()</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>media-ioctl</refname>
+    <refpurpose>Control a media device</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;sys/ioctl.h&gt;</funcsynopsisinfo>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>void *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>Media ioctl request code as defined in the media.h header file,
+	  for example MEDIA_IOC_SETUP_LINK.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para>Pointer to a request-specific structure.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+    <para>The <function>ioctl()</function> function manipulates media device
+    parameters. The argument <parameter>fd</parameter> must be an open file
+    descriptor.</para>
+    <para>The ioctl <parameter>request</parameter> code specifies the media
+    function to be called. It has encoded in it whether the argument is an
+    input, output or read/write parameter, and the size of the argument
+    <parameter>argp</parameter> in bytes.</para>
+    <para>Macros and structures definitions specifying media ioctl requests and
+    their parameters are located in the media.h header file. All media ioctl
+    requests, their respective function and parameters are specified in
+    <xref linkend="media-user-func" />.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return Value</title>
+
+    <para><function>ioctl()</function> returns <returnvalue>0</returnvalue> on
+    success. On failure, <returnvalue>-1</returnvalue> is returned, and the
+    <varname>errno</varname> variable is set appropriately. Generic error codes
+    are listed below, and request-specific error codes are listed in the
+    individual requests descriptions.</para>
+    <para>When an ioctl that takes an output or read/write parameter fails,
+    the parameter remains unmodified.</para>
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBADF</errorcode></term>
+	<listitem>
+	  <para><parameter>fd</parameter> is not a valid open file descriptor.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EFAULT</errorcode></term>
+	<listitem>
+	  <para><parameter>argp</parameter> references an inaccessible memory
+	  area.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The <parameter>request</parameter> or the data pointed to by
+	  <parameter>argp</parameter> is not valid. This is a very common error
+	  code, see the individual ioctl requests listed in
+	  <xref linkend="media-user-func" /> for actual causes.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>ENOMEM</errorcode></term>
+	<listitem>
+	  <para>Insufficient kernel memory was available to complete the
+	  request.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>ENOTTY</errorcode></term>
+	<listitem>
+	  <para><parameter>fd</parameter> is  not  associated  with  a character
+	  special device.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-func-open.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-func-open.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-func-open.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-func-open.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,94 @@
+<refentry id="media-func-open">
+  <refmeta>
+    <refentrytitle>media open()</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>media-open</refname>
+    <refpurpose>Open a media device</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcsynopsisinfo>#include &lt;fcntl.h&gt;</funcsynopsisinfo>
+      <funcprototype>
+	<funcdef>int <function>open</function></funcdef>
+	<paramdef>const char *<parameter>device_name</parameter></paramdef>
+	<paramdef>int <parameter>flags</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>device_name</parameter></term>
+	<listitem>
+	  <para>Device to be opened.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>flags</parameter></term>
+	<listitem>
+	  <para>Open flags. Access mode must be either <constant>O_RDONLY</constant>
+	  or <constant>O_RDWR</constant>. Other flags have no effect.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+  <refsect1>
+    <title>Description</title>
+    <para>To open a media device applications call <function>open()</function>
+    with the desired device name. The function has no side effects; the device
+    configuration remain unchanged.</para>
+    <para>When the device is opened in read-only mode, attemps to modify its
+    configuration will result in an error, and <varname>errno</varname> will be
+    set to <errorcode>EBADF</errorcode>.</para>
+  </refsect1>
+  <refsect1>
+    <title>Return Value</title>
+
+    <para><function>open</function> returns the new file descriptor on success.
+    On error, -1 is returned, and <varname>errno</varname> is set appropriately.
+    Possible error codes are:</para>
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EACCES</errorcode></term>
+	<listitem>
+	  <para>The requested access to the file is not allowed.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EMFILE</errorcode></term>
+	<listitem>
+	  <para>The  process  already  has  the  maximum number of files open.
+	  </para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>ENFILE</errorcode></term>
+	<listitem>
+	  <para>The system limit on the total number of open files has been
+	  reached.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>ENOMEM</errorcode></term>
+	<listitem>
+	  <para>Insufficient kernel memory was available.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>ENXIO</errorcode></term>
+	<listitem>
+	  <para>No device corresponding to this device special file exists.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-device-info.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-device-info.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-device-info.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-device-info.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,133 @@
+<refentry id="media-ioc-device-info">
+  <refmeta>
+    <refentrytitle>ioctl MEDIA_IOC_DEVICE_INFO</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>MEDIA_IOC_DEVICE_INFO</refname>
+    <refpurpose>Query device information</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct media_device_info *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>File descriptor returned by
+	  <link linkend='media-func-open'><function>open()</function></link>.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>MEDIA_IOC_DEVICE_INFO</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>All media devices must support the <constant>MEDIA_IOC_DEVICE_INFO</constant>
+    ioctl. To query device information, applications call the ioctl with a
+    pointer to a &media-device-info;. The driver fills the structure and returns
+    the information to the application.
+    The ioctl never fails.</para>
+
+    <table pgwide="1" frame="none" id="media-device-info">
+      <title>struct <structname>media_device_info</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>driver</structfield>[16]</entry>
+	    <entry><para>Name of the driver implementing the media API as a
+	    NUL-terminated ASCII string. The driver version is stored in the
+	    <structfield>driver_version</structfield> field.</para>
+	    <para>Driver specific applications can use this information to
+	    verify the driver identity. It is also useful to work around
+	    known bugs, or to identify drivers in error reports.</para></entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>model</structfield>[32]</entry>
+	    <entry>Device model name as a NUL-terminated UTF-8 string. The
+	    device version is stored in the <structfield>device_version</structfield>
+	    field and is not be appended to the model name.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>serial</structfield>[40]</entry>
+	    <entry>Serial number as a NUL-terminated ASCII string.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>bus_info</structfield>[32]</entry>
+	    <entry>Location of the device in the system as a NUL-terminated
+	    ASCII string. This includes the bus type name (PCI, USB, ...) and a
+	    bus-specific identifier.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>media_version</structfield></entry>
+	    <entry>Media API version, formatted with the
+	    <constant>KERNEL_VERSION()</constant> macro.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>hw_revision</structfield></entry>
+	    <entry>Hardware device revision in a driver-specific format.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>media_version</structfield></entry>
+	    <entry>Media device driver version, formatted with the
+	    <constant>KERNEL_VERSION()</constant> macro. Together with the
+	    <structfield>driver</structfield> field this identifies a particular
+	    driver.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[31]</entry>
+	    <entry>Reserved for future extensions. Drivers and applications must
+	    set this array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+    <para>The <structfield>serial</structfield> and <structfield>bus_info</structfield>
+    fields can be used to distinguish between multiple instances of otherwise
+    identical hardware. The serial number takes precedence when provided and can
+    be assumed to be unique. If the serial number is an empty string, the
+    <structfield>bus_info</structfield> field can be used instead. The
+    <structfield>bus_info</structfield> field is guaranteed to be unique, but
+    can vary across reboots or device unplug/replug.</para>
+  </refsect1>
+
+  <refsect1>
+    <title>Return value</title>
+    <para>This function doesn't return specific error codes.</para>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-enum-entities.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-enum-entities.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-enum-entities.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-enum-entities.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,308 @@
+<refentry id="media-ioc-enum-entities">
+  <refmeta>
+    <refentrytitle>ioctl MEDIA_IOC_ENUM_ENTITIES</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>MEDIA_IOC_ENUM_ENTITIES</refname>
+    <refpurpose>Enumerate entities and their properties</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct media_entity_desc *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>File descriptor returned by
+	  <link linkend='media-func-open'><function>open()</function></link>.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>MEDIA_IOC_ENUM_ENTITIES</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+    <para>To query the attributes of an entity, applications set the id field
+    of a &media-entity-desc; structure and call the MEDIA_IOC_ENUM_ENTITIES
+    ioctl with a pointer to this structure. The driver fills the rest of the
+    structure or returns an &EINVAL; when the id is invalid.</para>
+    <para>Entities can be enumerated by or'ing the id with the
+    <constant>MEDIA_ENT_ID_FLAG_NEXT</constant> flag. The driver will return
+    information about the entity with the smallest id strictly larger than the
+    requested one ('next entity'), or the &EINVAL; if there is none.</para>
+    <para>Entity IDs can be non-contiguous. Applications must
+    <emphasis>not</emphasis> try to enumerate entities by calling
+    MEDIA_IOC_ENUM_ENTITIES with increasing id's until they get an error.</para>
+    <para>Two or more entities that share a common non-zero
+    <structfield>group_id</structfield> value are considered as logically
+    grouped. Groups are used to report
+    <itemizedlist>
+      <listitem><para>ALSA, VBI and video nodes that carry the same media
+      stream</para></listitem>
+      <listitem><para>lens and flash controllers associated with a sensor</para></listitem>
+    </itemizedlist>
+    </para>
+
+    <table pgwide="1" frame="none" id="media-entity-desc">
+      <title>struct <structname>media_entity_desc</structname></title>
+      <tgroup cols="5">
+	<colspec colname="c1" />
+	<colspec colname="c2" />
+	<colspec colname="c3" />
+	<colspec colname="c4" />
+	<colspec colname="c5" />
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>id</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Entity id, set by the application. When the id is or'ed with
+	    <constant>MEDIA_ENT_ID_FLAG_NEXT</constant>, the driver clears the
+	    flag and returns the first entity with a larger id.</entry>
+	  </row>
+	  <row>
+	    <entry>char</entry>
+	    <entry><structfield>name</structfield>[32]</entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Entity name as an UTF-8 NULL-terminated string.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>type</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Entity type, see <xref linkend="media-entity-type" /> for details.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>revision</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Entity revision in a driver/hardware specific format.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Entity flags, see <xref linkend="media-entity-flag" /> for details.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>group_id</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Entity group ID</entry>
+	  </row>
+	  <row>
+	    <entry>__u16</entry>
+	    <entry><structfield>pads</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Number of pads</entry>
+	  </row>
+	  <row>
+	    <entry>__u16</entry>
+	    <entry><structfield>links</structfield></entry>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>Total number of outbound links. Inbound links are not counted
+	    in this field.</entry>
+	  </row>
+	  <row>
+	    <entry>union</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>struct</entry>
+	    <entry><structfield>v4l</structfield></entry>
+	    <entry></entry>
+	    <entry>Valid for V4L sub-devices and nodes only.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>major</structfield></entry>
+	    <entry>V4L device node major number. For V4L sub-devices with no
+	    device node, set by the driver to 0.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>minor</structfield></entry>
+	    <entry>V4L device node minor number. For V4L sub-devices with no
+	    device node, set by the driver to 0.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>struct</entry>
+	    <entry><structfield>fb</structfield></entry>
+	    <entry></entry>
+	    <entry>Valid for frame buffer nodes only.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>major</structfield></entry>
+	    <entry>Frame buffer device node major number.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>minor</structfield></entry>
+	    <entry>Frame buffer device node minor number.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>struct</entry>
+	    <entry><structfield>alsa</structfield></entry>
+	    <entry></entry>
+	    <entry>Valid for ALSA devices only.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>card</structfield></entry>
+	    <entry>ALSA card number</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>device</structfield></entry>
+	    <entry>ALSA device number</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry></entry>
+	    <entry>__u32</entry>
+	    <entry><structfield>subdevice</structfield></entry>
+	    <entry>ALSA sub-device number</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>int</entry>
+	    <entry><structfield>dvb</structfield></entry>
+	    <entry></entry>
+	    <entry>DVB card number</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
+	    <entry>__u8</entry>
+	    <entry><structfield>raw</structfield>[180]</entry>
+	    <entry></entry>
+	    <entry></entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="media-entity-type">
+      <title>Media entity types</title>
+      <tgroup cols="2">
+        <colspec colname="c1"/>
+        <colspec colname="c2"/>
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE</constant></entry>
+	    <entry>Unknown device node</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_V4L</constant></entry>
+	    <entry>V4L video, radio or vbi device node</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_FB</constant></entry>
+	    <entry>Frame buffer device node</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_ALSA</constant></entry>
+	    <entry>ALSA card</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_DEVNODE_DVB</constant></entry>
+	    <entry>DVB card</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV</constant></entry>
+	    <entry>Unknown V4L sub-device</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_SENSOR</constant></entry>
+	    <entry>Video sensor</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_FLASH</constant></entry>
+	    <entry>Flash controller</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_ENT_T_V4L2_SUBDEV_LENS</constant></entry>
+	    <entry>Lens controller</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="media-entity-flag">
+      <title>Media entity flags</title>
+      <tgroup cols="2">
+        <colspec colname="c1"/>
+        <colspec colname="c2"/>
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>MEDIA_ENT_FL_DEFAULT</constant></entry>
+	    <entry>Default entity for its type. Used to discover the default
+	    audio, VBI and video devices, the default camera sensor, ...</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &media-entity-desc; <structfield>id</structfield> references
+	  a non-existing entity.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-enum-links.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-enum-links.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-enum-links.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-enum-links.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,207 @@
+<refentry id="media-ioc-enum-links">
+  <refmeta>
+    <refentrytitle>ioctl MEDIA_IOC_ENUM_LINKS</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>MEDIA_IOC_ENUM_LINKS</refname>
+    <refpurpose>Enumerate all pads and links for a given entity</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct media_links_enum *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>File descriptor returned by
+	  <link linkend='media-func-open'><function>open()</function></link>.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>MEDIA_IOC_ENUM_LINKS</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>To enumerate pads and/or links for a given entity, applications set
+    the entity field of a &media-links-enum; structure and initialize the
+    &media-pad-desc; and &media-link-desc; structure arrays pointed by the
+    <structfield>pads</structfield> and <structfield>links</structfield> fields.
+    They then call the MEDIA_IOC_ENUM_LINKS ioctl with a pointer to this
+    structure.</para>
+    <para>If the <structfield>pads</structfield> field is not NULL, the driver
+    fills the <structfield>pads</structfield> array with information about the
+    entity's pads. The array must have enough room to store all the entity's
+    pads. The number of pads can be retrieved with the &MEDIA-IOC-ENUM-ENTITIES;
+    ioctl.</para>
+    <para>If the <structfield>links</structfield> field is not NULL, the driver
+    fills the <structfield>links</structfield> array with information about the
+    entity's outbound links. The array must have enough room to store all the
+    entity's outbound links. The number of outbound links can be retrieved with
+    the &MEDIA-IOC-ENUM-ENTITIES; ioctl.</para>
+    <para>Only forward links that originate at one of the entity's source pads
+    are returned during the enumeration process.</para>
+
+    <table pgwide="1" frame="none" id="media-links-enum">
+      <title>struct <structname>media_links_enum</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>entity</structfield></entry>
+	    <entry>Entity id, set by the application.</entry>
+	  </row>
+	  <row>
+	    <entry>struct &media-pad-desc;</entry>
+	    <entry>*<structfield>pads</structfield></entry>
+	    <entry>Pointer to a pads array allocated by the application. Ignored
+	    if NULL.</entry>
+	  </row>
+	  <row>
+	    <entry>struct &media-link-desc;</entry>
+	    <entry>*<structfield>links</structfield></entry>
+	    <entry>Pointer to a links array allocated by the application. Ignored
+	    if NULL.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="media-pad-desc">
+      <title>struct <structname>media_pad_desc</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>entity</structfield></entry>
+	    <entry>ID of the entity this pad belongs to.</entry>
+	  </row>
+	  <row>
+	    <entry>__u16</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>0-based pad index.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Pad flags, see <xref linkend="media-pad-flag" /> for more details.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="media-pad-flag">
+      <title>Media pad flags</title>
+      <tgroup cols="2">
+        <colspec colname="c1"/>
+        <colspec colname="c2"/>
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>MEDIA_PAD_FL_SINK</constant></entry>
+	    <entry>Input pad, relative to the entity. Input pads sink data and
+	    are targets of links.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_PAD_FL_SOURCE</constant></entry>
+	    <entry>Output pad, relative to the entity. Output pads source data
+	    and are origins of links.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="media-link-desc">
+      <title>struct <structname>media_links_desc</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>struct &media-pad-desc;</entry>
+	    <entry><structfield>source</structfield></entry>
+	    <entry>Pad at the origin of this link.</entry>
+	  </row>
+	  <row>
+	    <entry>struct &media-pad-desc;</entry>
+	    <entry><structfield>sink</structfield></entry>
+	    <entry>Pad at the target of this link.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>flags</structfield></entry>
+	    <entry>Link flags, see <xref linkend="media-link-flag" /> for more details.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table frame="none" pgwide="1" id="media-link-flag">
+      <title>Media link flags</title>
+      <tgroup cols="2">
+        <colspec colname="c1"/>
+        <colspec colname="c2"/>
+	<tbody valign="top">
+	  <row>
+	    <entry><constant>MEDIA_LNK_FL_ENABLED</constant></entry>
+	    <entry>The link is enabled and can be used to transfer media data.
+	    When two or more links target a sink pad, only one of them can be
+	    enabled at a time.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_LNK_FL_IMMUTABLE</constant></entry>
+	    <entry>The link enabled state can't be modified at runtime. An
+	    immutable link is always enabled.</entry>
+	  </row>
+	  <row>
+	    <entry><constant>MEDIA_LNK_FL_DYNAMIC</constant></entry>
+	    <entry>The link enabled state can be modified during streaming. This
+	    flag is set by drivers and is read-only for applications.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+    <para>One and only one of <constant>MEDIA_PAD_FL_SINK</constant> and
+    <constant>MEDIA_PAD_FL_SOURCE</constant> must be set for every pad.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &media-links-enum; <structfield>id</structfield> references
+	  a non-existing entity.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-setup-link.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-setup-link.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/media-ioc-setup-link.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/media-ioc-setup-link.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,93 @@
+<refentry id="media-ioc-setup-link">
+  <refmeta>
+    <refentrytitle>ioctl MEDIA_IOC_SETUP_LINK</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>MEDIA_IOC_SETUP_LINK</refname>
+    <refpurpose>Modify the properties of a link</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct media_link_desc *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>File descriptor returned by
+	  <link linkend='media-func-open'><function>open()</function></link>.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>MEDIA_IOC_SETUP_LINK</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <para>To change link properties applications fill a &media-link-desc; with
+    link identification information (source and sink pad) and the new requested
+    link flags. They then call the MEDIA_IOC_SETUP_LINK ioctl with a pointer to
+    that structure.</para>
+    <para>The only configurable property is the <constant>ENABLED</constant>
+    link flag to enable/disable a link. Links marked with the
+    <constant>IMMUTABLE</constant> link flag can not be enabled or disabled.
+    </para>
+    <para>Link configuration has no side effect on other links. If an enabled
+    link at the sink pad prevents the link from being enabled, the driver
+    returns with an &EBUSY;.</para>
+    <para>Only links marked with the <constant>DYNAMIC</constant> link flag can
+    be enabled/disabled while streaming media data. Attempting to enable or
+    disable a streaming non-dynamic link will return an &EBUSY;.</para>
+    <para>If the specified link can't be found the driver returns with an
+    &EINVAL;.</para>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The link properties can't be changed because the link is
+	  currently busy. This can be caused, for instance, by an active media
+	  stream (audio or video) on the link. The ioctl shouldn't be retried if
+	  no other action is performed before to fix the problem.</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &media-link-desc; references a non-existing link, or the
+	  link is immutable and an attempt to modify its configuration was made.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
Binary files linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/nv12mt_example.gif and linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/nv12mt_example.gif differ
Binary files linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/nv12mt.gif and linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/nv12mt.gif differ
Binary files linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pipeline.pdf and linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pipeline.pdf differ
Binary files linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pipeline.png and linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pipeline.png differ
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-nv12mt.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-nv12mt.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-nv12mt.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-nv12mt.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,74 @@
+    <refentry>
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_NV12MT ('TM12')</refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname id="V4L2-PIX-FMT-NV12MT"><constant>V4L2_PIX_FMT_NV12MT
+</constant></refname>
+	<refpurpose>Formats with &frac12; horizontal and vertical
+chroma resolution. This format has two planes - one for luminance and one for
+chrominance. Chroma samples are interleaved. The difference to
+<constant>V4L2_PIX_FMT_NV12</constant> is the memory layout. Pixels are
+grouped in macroblocks of 64x32 size. The order of macroblocks in memory is
+also not standard.
+	</refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>This is the two-plane versions of the YUV 4:2:0 format where data
+is grouped into 64x32 macroblocks. The three components are separated into two
+sub-images or planes. The Y plane has one byte per pixel and pixels are grouped
+into 64x32 macroblocks. The CbCr plane has the same width, in bytes, as the Y
+plane (and the image), but is half as tall in pixels. The chroma plane is also
+grouped into 64x32 macroblocks.</para>
+	<para>Width of the buffer has to be aligned to the multiple of 128, and
+height alignment is 32. Every four adjactent buffers - two horizontally and two
+vertically are grouped together and are located in memory in Z or flipped Z
+order. </para>
+	<para>Layout of macroblocks in memory is presented in the following
+figure.</para>
+	<para><figure id="nv12mt">
+	    <title><constant>V4L2_PIX_FMT_NV12MT</constant> macroblock Z shape
+memory layout</title>
+	    <mediaobject>
+	      <imageobject>
+		<imagedata fileref="nv12mt.gif" format="GIF" />
+	      </imageobject>
+	    </mediaobject>
+	</figure>
+	The requirement that width is multiple of 128 is implemented because,
+the Z shape cannot be cut in half horizontally. In case the vertical resolution
+of macroblocks is odd then the last row of macroblocks is arranged in a linear
+order.  </para>
+	<para>In case of chroma the layout is identical. Cb and Cr samples are
+interleaved. Height of the buffer is aligned to 32.
+	</para>
+	<example>
+	  <title>Memory layout of macroblocks in <constant>V4L2_PIX_FMT_NV12
+</constant> format pixel image - extreme case</title>
+	<para>
+	<figure id="nv12mt_ex">
+	    <title>Example <constant>V4L2_PIX_FMT_NV12MT</constant> memory
+layout of macroblocks</title>
+	    <mediaobject>
+	      <imageobject>
+		<imagedata fileref="nv12mt_example.gif" format="GIF" />
+	      </imageobject>
+	    </mediaobject>
+	</figure>
+	Memory layout of macroblocks of <constant>V4L2_PIX_FMT_NV12MT
+</constant> format in most extreme case.
+	</para>
+	</example>
+      </refsect1>
+    </refentry>
+
+  <!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "pixfmt.sgml"
+indent-tabs-mode: nil
+End:
+  -->
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-nv12m.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-nv12m.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-nv12m.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-nv12m.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,154 @@
+    <refentry id="V4L2-PIX-FMT-NV12M">
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_NV12M ('NV12M')</refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname> <constant>V4L2_PIX_FMT_NV12M</constant></refname>
+	<refpurpose>Variation of <constant>V4L2_PIX_FMT_NV12</constant> with planes
+	  non contiguous in memory. </refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>This is a multi-planar, two-plane version of the YUV 4:2:0 format.
+The three components are separated into two sub-images or planes.
+<constant>V4L2_PIX_FMT_NV12M</constant> differs from <constant>V4L2_PIX_FMT_NV12
+</constant> in that the two planes are non-contiguous in memory, i.e. the chroma
+plane do not necessarily immediately follows the luma plane.
+The luminance data occupies the first plane. The Y plane has one byte per pixel.
+In the second plane there is a chrominance data with alternating chroma samples.
+The CbCr plane is the same width, in bytes, as the Y plane (and of the image),
+but is half as tall in pixels. Each CbCr pair belongs to four pixels. For example,
+Cb<subscript>0</subscript>/Cr<subscript>0</subscript> belongs to
+Y'<subscript>00</subscript>, Y'<subscript>01</subscript>,
+Y'<subscript>10</subscript>, Y'<subscript>11</subscript>. </para>
+
+	<para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
+used only in drivers and applications that support the multi-planar API,
+described in <xref linkend="planar-apis"/>. </para>
+
+	<para>If the Y plane has pad bytes after each row, then the
+CbCr plane has as many pad bytes after its rows.</para>
+
+	<example>
+	  <title><constant>V4L2_PIX_FMT_NV12M</constant> 4 &times; 4 pixel image</title>
+
+	  <formalpara>
+	    <title>Byte Order.</title>
+	    <para>Each cell is one byte.
+		<informaltable frame="none">
+		<tgroup cols="5" align="center">
+		  <colspec align="left" colwidth="2*" />
+		  <tbody valign="top">
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;0:</entry>
+		      <entry>Y'<subscript>00</subscript></entry>
+		      <entry>Y'<subscript>01</subscript></entry>
+		      <entry>Y'<subscript>02</subscript></entry>
+		      <entry>Y'<subscript>03</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;4:</entry>
+		      <entry>Y'<subscript>10</subscript></entry>
+		      <entry>Y'<subscript>11</subscript></entry>
+		      <entry>Y'<subscript>12</subscript></entry>
+		      <entry>Y'<subscript>13</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;8:</entry>
+		      <entry>Y'<subscript>20</subscript></entry>
+		      <entry>Y'<subscript>21</subscript></entry>
+		      <entry>Y'<subscript>22</subscript></entry>
+		      <entry>Y'<subscript>23</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;12:</entry>
+		      <entry>Y'<subscript>30</subscript></entry>
+		      <entry>Y'<subscript>31</subscript></entry>
+		      <entry>Y'<subscript>32</subscript></entry>
+		      <entry>Y'<subscript>33</subscript></entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		    </row>
+		    <row>
+		      <entry>start1&nbsp;+&nbsp;0:</entry>
+		      <entry>Cb<subscript>00</subscript></entry>
+		      <entry>Cr<subscript>00</subscript></entry>
+		      <entry>Cb<subscript>01</subscript></entry>
+		      <entry>Cr<subscript>01</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start1&nbsp;+&nbsp;4:</entry>
+		      <entry>Cb<subscript>10</subscript></entry>
+		      <entry>Cr<subscript>10</subscript></entry>
+		      <entry>Cb<subscript>11</subscript></entry>
+		      <entry>Cr<subscript>11</subscript></entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+
+	  <formalpara>
+	    <title>Color Sample Location.</title>
+	    <para>
+		<informaltable frame="none">
+		<tgroup cols="7" align="center">
+		  <tbody valign="top">
+		    <row>
+		      <entry></entry>
+		      <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
+		      <entry>2</entry><entry></entry><entry>3</entry>
+		    </row>
+		    <row>
+		      <entry>0</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>1</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		    </row>
+		    <row>
+		      <entry>2</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>3</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+	</example>
+      </refsect1>
+    </refentry>
+
+  <!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "pixfmt.sgml"
+indent-tabs-mode: nil
+End:
+  -->
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-srggb12.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-srggb12.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-srggb12.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-srggb12.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,90 @@
+    <refentry>
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_SRGGB12 ('RG12'),
+	 V4L2_PIX_FMT_SGRBG12 ('BA12'),
+	 V4L2_PIX_FMT_SGBRG12 ('GB12'),
+	 V4L2_PIX_FMT_SBGGR12 ('BG12'),
+	 </refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname id="V4L2-PIX-FMT-SRGGB12"><constant>V4L2_PIX_FMT_SRGGB12</constant></refname>
+	<refname id="V4L2-PIX-FMT-SGRBG12"><constant>V4L2_PIX_FMT_SGRBG12</constant></refname>
+	<refname id="V4L2-PIX-FMT-SGBRG12"><constant>V4L2_PIX_FMT_SGBRG12</constant></refname>
+	<refname id="V4L2-PIX-FMT-SBGGR12"><constant>V4L2_PIX_FMT_SBGGR12</constant></refname>
+	<refpurpose>12-bit Bayer formats expanded to 16 bits</refpurpose>
+      </refnamediv>
+      <refsect1>
+	<title>Description</title>
+
+	<para>The following four pixel formats are raw sRGB / Bayer formats with
+12 bits per colour. Each colour component is stored in a 16-bit word, with 6
+unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
+and n/2 blue or red samples, with alternating red and blue rows. Bytes are
+stored in memory in little endian order. They are conventionally described
+as GRGR... BGBG..., RGRG... GBGB..., etc. Below is an example of one of these
+formats</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_SBGGR12</constant> 4 &times; 4
+pixel image</title>
+
+      <formalpara>
+	<title>Byte Order.</title>
+	<para>Each cell is one byte, high 6 bits in high bytes are 0.
+	  <informaltable frame="none">
+	    <tgroup cols="5" align="center">
+	      <colspec align="left" colwidth="2*" />
+	      <tbody valign="top">
+		<row>
+		  <entry>start&nbsp;+&nbsp;0:</entry>
+		  <entry>B<subscript>00low</subscript></entry>
+		  <entry>B<subscript>00high</subscript></entry>
+		  <entry>G<subscript>01low</subscript></entry>
+		  <entry>G<subscript>01high</subscript></entry>
+		  <entry>B<subscript>02low</subscript></entry>
+		  <entry>B<subscript>02high</subscript></entry>
+		  <entry>G<subscript>03low</subscript></entry>
+		  <entry>G<subscript>03high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;8:</entry>
+		  <entry>G<subscript>10low</subscript></entry>
+		  <entry>G<subscript>10high</subscript></entry>
+		  <entry>R<subscript>11low</subscript></entry>
+		  <entry>R<subscript>11high</subscript></entry>
+		  <entry>G<subscript>12low</subscript></entry>
+		  <entry>G<subscript>12high</subscript></entry>
+		  <entry>R<subscript>13low</subscript></entry>
+		  <entry>R<subscript>13high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;16:</entry>
+		  <entry>B<subscript>20low</subscript></entry>
+		  <entry>B<subscript>20high</subscript></entry>
+		  <entry>G<subscript>21low</subscript></entry>
+		  <entry>G<subscript>21high</subscript></entry>
+		  <entry>B<subscript>22low</subscript></entry>
+		  <entry>B<subscript>22high</subscript></entry>
+		  <entry>G<subscript>23low</subscript></entry>
+		  <entry>G<subscript>23high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;24:</entry>
+		  <entry>G<subscript>30low</subscript></entry>
+		  <entry>G<subscript>30high</subscript></entry>
+		  <entry>R<subscript>31low</subscript></entry>
+		  <entry>R<subscript>31high</subscript></entry>
+		  <entry>G<subscript>32low</subscript></entry>
+		  <entry>G<subscript>32high</subscript></entry>
+		  <entry>R<subscript>33low</subscript></entry>
+		  <entry>R<subscript>33high</subscript></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt.xml	2011-05-19 00:06:34.000000000 -0400
@@ -2,12 +2,16 @@
 
   <para>The V4L2 API was primarily designed for devices exchanging
 image data with applications. The
-<structname>v4l2_pix_format</structname> structure defines the format
-and layout of an image in memory. Image formats are negotiated with
-the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video
+<structname>v4l2_pix_format</structname> and <structname>v4l2_pix_format_mplane
+</structname> structures define the format and layout of an image in memory.
+The former is used with the single-planar API, while the latter is used with the
+multi-planar version (see <xref linkend="planar-apis"/>). Image formats are
+negotiated with the &VIDIOC-S-FMT; ioctl. (The explanations here focus on video
 capturing and output, for overlay frame buffer formats see also
 &VIDIOC-G-FBUF;.)</para>
 
+<section>
+  <title>Single-planar format structure</title>
   <table pgwide="1" frame="none" id="v4l2-pix-format">
     <title>struct <structname>v4l2_pix_format</structname></title>
     <tgroup cols="3">
@@ -106,6 +110,98 @@
       </tbody>
     </tgroup>
   </table>
+</section>
+
+<section>
+  <title>Multi-planar format structures</title>
+  <para>The <structname>v4l2_plane_pix_format</structname> structures define
+    size and layout for each of the planes in a multi-planar format.
+    The <structname>v4l2_pix_format_mplane</structname> structure contains
+    information common to all planes (such as image width and height) and
+    an array of <structname>v4l2_plane_pix_format</structname> structures,
+    describing all planes of that format.</para>
+  <table pgwide="1" frame="none" id="v4l2-plane-pix-format">
+    <title>struct <structname>vl42_plane_pix_format</structname></title>
+    <tgroup cols="3">
+      &cs-str;
+      <tbody valign="top">
+        <row>
+          <entry>__u32</entry>
+          <entry><structfield>sizeimage</structfield></entry>
+          <entry>Maximum size in bytes required for image data in this plane.
+          </entry>
+        </row>
+        <row>
+          <entry>__u16</entry>
+          <entry><structfield>bytesperline</structfield></entry>
+          <entry>Distance in bytes between the leftmost pixels in two adjacent
+            lines.</entry>
+        </row>
+        <row>
+          <entry>__u16</entry>
+          <entry><structfield>reserved[7]</structfield></entry>
+          <entry>Reserved for future extensions. Should be zeroed by the
+           application.</entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+  <table pgwide="1" frame="none" id="v4l2-pix-format-mplane">
+    <title>struct <structname>v4l2_pix_format_mplane</structname></title>
+    <tgroup cols="3">
+      &cs-str;
+      <tbody valign="top">
+        <row>
+          <entry>__u32</entry>
+          <entry><structfield>width</structfield></entry>
+          <entry>Image width in pixels.</entry>
+        </row>
+        <row>
+          <entry>__u32</entry>
+          <entry><structfield>height</structfield></entry>
+          <entry>Image height in pixels.</entry>
+        </row>
+        <row>
+          <entry>__u32</entry>
+          <entry><structfield>pixelformat</structfield></entry>
+          <entry>The pixel format. Both single- and multi-planar four character
+codes can be used.</entry>
+        </row>
+        <row>
+          <entry>&v4l2-field;</entry>
+          <entry><structfield>field</structfield></entry>
+          <entry>See &v4l2-pix-format;.</entry>
+        </row>
+        <row>
+          <entry>&v4l2-colorspace;</entry>
+          <entry><structfield>colorspace</structfield></entry>
+          <entry>See &v4l2-pix-format;.</entry>
+        </row>
+        <row>
+          <entry>&v4l2-plane-pix-format;</entry>
+          <entry><structfield>plane_fmt[VIDEO_MAX_PLANES]</structfield></entry>
+          <entry>An array of structures describing format of each plane this
+          pixel format consists of. The number of valid entries in this array
+          has to be put in the <structfield>num_planes</structfield>
+          field.</entry>
+        </row>
+        <row>
+          <entry>__u8</entry>
+          <entry><structfield>num_planes</structfield></entry>
+          <entry>Number of planes (i.e. separate memory buffers) for this format
+          and the number of valid entries in the
+          <structfield>plane_fmt</structfield> array.</entry>
+        </row>
+        <row>
+          <entry>__u8</entry>
+          <entry><structfield>reserved[11]</structfield></entry>
+          <entry>Reserved for future extensions. Should be zeroed by the
+           application.</entry>
+        </row>
+      </tbody>
+    </tgroup>
+  </table>
+</section>
 
   <section>
     <title>Standard Image Formats</title>
@@ -142,11 +238,19 @@
 has just as many pad bytes after it as the other rows.</para>
 
     <para>In V4L2 each format has an identifier which looks like
-<constant>PIX_FMT_XXX</constant>, defined in the <filename>videodev2.h</filename>
-header file. These identifiers
-represent <link linkend="v4l2-fourcc">four character codes</link>
+<constant>PIX_FMT_XXX</constant>, defined in the <link
+linkend="videodev">videodev.h</link> header file. These identifiers
+represent <link linkend="v4l2-fourcc">four character (FourCC) codes</link>
 which are also listed below, however they are not the same as those
 used in the Windows world.</para>
+
+    <para>For some formats, data is stored in separate, discontiguous
+memory buffers. Those formats are identified by a separate set of FourCC codes
+and are referred to as "multi-planar formats". For example, a YUV422 frame is
+normally stored in one memory buffer, but it can also be placed in two or three
+separate buffers, with Y component in one buffer and CbCr components in another
+in the 2-planar version or with each component in its own buffer in the
+3-planar case. Those sub-buffers are referred to as "planes".</para>
   </section>
 
   <section id="colorspaces">
@@ -592,6 +696,7 @@
     &sub-packed-yuv;
     &sub-grey;
     &sub-y10;
+    &sub-y12;
     &sub-y16;
     &sub-yuyv;
     &sub-uyvy;
@@ -599,10 +704,13 @@
     &sub-vyuy;
     &sub-y41p;
     &sub-yuv420;
+    &sub-yuv420m;
     &sub-yuv410;
     &sub-yuv422p;
     &sub-yuv411p;
     &sub-nv12;
+    &sub-nv12m;
+    &sub-nv12mt;
     &sub-nv16;
   </section>
 
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-y12.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-y12.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-y12.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-y12.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,79 @@
+<refentry id="V4L2-PIX-FMT-Y12">
+  <refmeta>
+    <refentrytitle>V4L2_PIX_FMT_Y12 ('Y12 ')</refentrytitle>
+    &manvol;
+  </refmeta>
+  <refnamediv>
+    <refname><constant>V4L2_PIX_FMT_Y12</constant></refname>
+    <refpurpose>Grey-scale image</refpurpose>
+  </refnamediv>
+  <refsect1>
+    <title>Description</title>
+
+    <para>This is a grey-scale image with a depth of 12 bits per pixel. Pixels
+are stored in 16-bit words with unused high bits padded with 0. The least
+significant byte is stored at lower memory addresses (little-endian).</para>
+
+    <example>
+      <title><constant>V4L2_PIX_FMT_Y12</constant> 4 &times; 4
+pixel image</title>
+
+      <formalpara>
+	<title>Byte Order.</title>
+	<para>Each cell is one byte.
+	  <informaltable frame="none">
+	    <tgroup cols="9" align="center">
+	      <colspec align="left" colwidth="2*" />
+	      <tbody valign="top">
+		<row>
+		  <entry>start&nbsp;+&nbsp;0:</entry>
+		  <entry>Y'<subscript>00low</subscript></entry>
+		  <entry>Y'<subscript>00high</subscript></entry>
+		  <entry>Y'<subscript>01low</subscript></entry>
+		  <entry>Y'<subscript>01high</subscript></entry>
+		  <entry>Y'<subscript>02low</subscript></entry>
+		  <entry>Y'<subscript>02high</subscript></entry>
+		  <entry>Y'<subscript>03low</subscript></entry>
+		  <entry>Y'<subscript>03high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;8:</entry>
+		  <entry>Y'<subscript>10low</subscript></entry>
+		  <entry>Y'<subscript>10high</subscript></entry>
+		  <entry>Y'<subscript>11low</subscript></entry>
+		  <entry>Y'<subscript>11high</subscript></entry>
+		  <entry>Y'<subscript>12low</subscript></entry>
+		  <entry>Y'<subscript>12high</subscript></entry>
+		  <entry>Y'<subscript>13low</subscript></entry>
+		  <entry>Y'<subscript>13high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;16:</entry>
+		  <entry>Y'<subscript>20low</subscript></entry>
+		  <entry>Y'<subscript>20high</subscript></entry>
+		  <entry>Y'<subscript>21low</subscript></entry>
+		  <entry>Y'<subscript>21high</subscript></entry>
+		  <entry>Y'<subscript>22low</subscript></entry>
+		  <entry>Y'<subscript>22high</subscript></entry>
+		  <entry>Y'<subscript>23low</subscript></entry>
+		  <entry>Y'<subscript>23high</subscript></entry>
+		</row>
+		<row>
+		  <entry>start&nbsp;+&nbsp;24:</entry>
+		  <entry>Y'<subscript>30low</subscript></entry>
+		  <entry>Y'<subscript>30high</subscript></entry>
+		  <entry>Y'<subscript>31low</subscript></entry>
+		  <entry>Y'<subscript>31high</subscript></entry>
+		  <entry>Y'<subscript>32low</subscript></entry>
+		  <entry>Y'<subscript>32high</subscript></entry>
+		  <entry>Y'<subscript>33low</subscript></entry>
+		  <entry>Y'<subscript>33high</subscript></entry>
+		</row>
+	      </tbody>
+	    </tgroup>
+	  </informaltable>
+	</para>
+      </formalpara>
+    </example>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-yuv420m.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-yuv420m.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/pixfmt-yuv420m.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/pixfmt-yuv420m.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,162 @@
+    <refentry id="V4L2-PIX-FMT-YUV420M">
+      <refmeta>
+	<refentrytitle>V4L2_PIX_FMT_YUV420M ('YU12M')</refentrytitle>
+	&manvol;
+      </refmeta>
+      <refnamediv>
+	<refname> <constant>V4L2_PIX_FMT_YUV420M</constant></refname>
+	<refpurpose>Variation of <constant>V4L2_PIX_FMT_YUV420</constant>
+	  with planes non contiguous in memory. </refpurpose>
+      </refnamediv>
+
+      <refsect1>
+	<title>Description</title>
+
+	<para>This is a multi-planar format, as opposed to a packed format.
+The three components are separated into three sub- images or planes.
+
+The Y plane is first. The Y plane has one byte per pixel. The Cb data
+constitutes the second plane which is half the width and half
+the height of the Y plane (and of the image). Each Cb belongs to four
+pixels, a two-by-two square of the image. For example,
+Cb<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
+Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
+Y'<subscript>11</subscript>. The Cr data, just like the Cb plane, is
+in the third plane. </para>
+
+	<para>If the Y plane has pad bytes after each row, then the Cb
+and Cr planes have half as many pad bytes after their rows. In other
+words, two Cx rows (including padding) is exactly as long as one Y row
+(including padding).</para>
+
+	<para><constant>V4L2_PIX_FMT_NV12M</constant> is intended to be
+used only in drivers and applications that support the multi-planar API,
+described in <xref linkend="planar-apis"/>. </para>
+
+	<example>
+	  <title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 &times; 4
+pixel image</title>
+
+	  <formalpara>
+	    <title>Byte Order.</title>
+	    <para>Each cell is one byte.
+		<informaltable frame="none">
+		<tgroup cols="5" align="center">
+		  <colspec align="left" colwidth="2*" />
+		  <tbody valign="top">
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;0:</entry>
+		      <entry>Y'<subscript>00</subscript></entry>
+		      <entry>Y'<subscript>01</subscript></entry>
+		      <entry>Y'<subscript>02</subscript></entry>
+		      <entry>Y'<subscript>03</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;4:</entry>
+		      <entry>Y'<subscript>10</subscript></entry>
+		      <entry>Y'<subscript>11</subscript></entry>
+		      <entry>Y'<subscript>12</subscript></entry>
+		      <entry>Y'<subscript>13</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;8:</entry>
+		      <entry>Y'<subscript>20</subscript></entry>
+		      <entry>Y'<subscript>21</subscript></entry>
+		      <entry>Y'<subscript>22</subscript></entry>
+		      <entry>Y'<subscript>23</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start0&nbsp;+&nbsp;12:</entry>
+		      <entry>Y'<subscript>30</subscript></entry>
+		      <entry>Y'<subscript>31</subscript></entry>
+		      <entry>Y'<subscript>32</subscript></entry>
+		      <entry>Y'<subscript>33</subscript></entry>
+		    </row>
+		    <row><entry></entry></row>
+		    <row>
+		      <entry>start1&nbsp;+&nbsp;0:</entry>
+		      <entry>Cb<subscript>00</subscript></entry>
+		      <entry>Cb<subscript>01</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start1&nbsp;+&nbsp;2:</entry>
+		      <entry>Cb<subscript>10</subscript></entry>
+		      <entry>Cb<subscript>11</subscript></entry>
+		    </row>
+		    <row><entry></entry></row>
+		    <row>
+		      <entry>start2&nbsp;+&nbsp;0:</entry>
+		      <entry>Cr<subscript>00</subscript></entry>
+		      <entry>Cr<subscript>01</subscript></entry>
+		    </row>
+		    <row>
+		      <entry>start2&nbsp;+&nbsp;2:</entry>
+		      <entry>Cr<subscript>10</subscript></entry>
+		      <entry>Cr<subscript>11</subscript></entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+
+	  <formalpara>
+	    <title>Color Sample Location.</title>
+	    <para>
+		<informaltable frame="none">
+		<tgroup cols="7" align="center">
+		  <tbody valign="top">
+		    <row>
+		      <entry></entry>
+		      <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
+		      <entry>2</entry><entry></entry><entry>3</entry>
+		    </row>
+		    <row>
+		      <entry>0</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>1</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		    </row>
+		    <row>
+		      <entry>2</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		    <row>
+		      <entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry><entry></entry>
+		      <entry></entry><entry>C</entry><entry></entry>
+		    </row>
+		    <row>
+		      <entry>3</entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+		      <entry>Y</entry><entry></entry><entry>Y</entry>
+		    </row>
+		  </tbody>
+		</tgroup>
+		</informaltable>
+	      </para>
+	  </formalpara>
+	</example>
+      </refsect1>
+    </refentry>
+
+  <!--
+Local Variables:
+mode: sgml
+sgml-parent-document: "pixfmt.sgml"
+indent-tabs-mode: nil
+End:
+  -->
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/planar-apis.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/planar-apis.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/planar-apis.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/planar-apis.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+<section id="planar-apis">
+  <title>Single- and multi-planar APIs</title>
+
+  <para>Some devices require data for each input or output video frame
+  to be placed in discontiguous memory buffers. In such cases, one
+  video frame has to be addressed using more than one memory address, i.e. one
+  pointer per "plane". A plane is a sub-buffer of the current frame. For
+  examples of such formats see <xref linkend="pixfmt" />.</para>
+
+  <para>Initially, V4L2 API did not support multi-planar buffers and a set of
+  extensions has been introduced to handle them. Those extensions constitute
+  what is being referred to as the "multi-planar API".</para>
+
+  <para>Some of the V4L2 API calls and structures are interpreted differently,
+  depending on whether single- or multi-planar API is being used. An application
+  can choose whether to use one or the other by passing a corresponding buffer
+  type to its ioctl calls. Multi-planar versions of buffer types are suffixed
+  with an `_MPLANE' string. For a list of available multi-planar buffer types
+  see &v4l2-buf-type;.
+  </para>
+
+  <section>
+    <title>Multi-planar formats</title>
+    <para>Multi-planar API introduces new multi-planar formats. Those formats
+    use a separate set of FourCC codes. It is important to distinguish between
+    the multi-planar API and a multi-planar format. Multi-planar API calls can
+    handle all single-planar formats as well (as long as they are passed in
+    multi-planar API structures), while the single-planar API cannot
+    handle multi-planar formats.</para>
+  </section>
+
+  <section>
+    <title>Calls that distinguish between single and multi-planar APIs</title>
+    <variablelist>
+      <varlistentry>
+        <term>&VIDIOC-QUERYCAP;</term>
+        <listitem><para>Two additional multi-planar capabilities are added. They can
+        be set together with non-multi-planar ones for devices that handle
+        both single- and multi-planar formats.</para></listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>&VIDIOC-G-FMT;, &VIDIOC-S-FMT;, &VIDIOC-TRY-FMT;</term>
+        <listitem><para>New structures for describing multi-planar formats are added:
+        &v4l2-pix-format-mplane; and &v4l2-plane-pix-format;. Drivers may
+        define new multi-planar formats, which have distinct FourCC codes from
+        the existing single-planar ones.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>&VIDIOC-QBUF;, &VIDIOC-DQBUF;, &VIDIOC-QUERYBUF;</term>
+        <listitem><para>A new &v4l2-plane; structure for describing planes is added.
+        Arrays of this structure are passed in the new
+        <structfield>m.planes</structfield> field of &v4l2-buffer;.</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term>&VIDIOC-REQBUFS;</term>
+        <listitem><para>Will allocate multi-planar buffers as requested.</para></listitem>
+      </varlistentry>
+    </variablelist>
+  </section>
+</section>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/remote_controllers.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/remote_controllers.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/remote_controllers.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/remote_controllers.xml	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,7 @@
 <row><entry><constant>KEY_LEFT</constant></entry><entry>Left key</entry><entry>LEFT</entry></row>
 <row><entry><constant>KEY_RIGHT</constant></entry><entry>Right key</entry><entry>RIGHT</entry></row>
 
-<row><entry><emphasis role="bold">Miscelaneous keys</emphasis></entry></row>
+<row><entry><emphasis role="bold">Miscellaneous keys</emphasis></entry></row>
 
 <row><entry><constant>KEY_DOT</constant></entry><entry>Return a dot</entry><entry>.</entry></row>
 <row><entry><constant>KEY_FN</constant></entry><entry>Select a function</entry><entry>FUNCTION</entry></row>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/subdev-formats.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/subdev-formats.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/subdev-formats.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/subdev-formats.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2526 @@
+<section id="v4l2-mbus-format">
+  <title>Media Bus Formats</title>
+
+  <table pgwide="1" frame="none" id="v4l2-mbus-framefmt">
+    <title>struct <structname>v4l2_mbus_framefmt</structname></title>
+    <tgroup cols="3">
+      &cs-str;
+      <tbody valign="top">
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>width</structfield></entry>
+	  <entry>Image width, in pixels.</entry>
+	</row>
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>height</structfield></entry>
+	  <entry>Image height, in pixels.</entry>
+	</row>
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>code</structfield></entry>
+	  <entry>Format code, from &v4l2-mbus-pixelcode;.</entry>
+	</row>
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>field</structfield></entry>
+	  <entry>Field order, from &v4l2-field;. See
+	  <xref linkend="field-order" /> for details.</entry>
+	</row>
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>colorspace</structfield></entry>
+	  <entry>Image colorspace, from &v4l2-colorspace;. See
+	  <xref linkend="colorspaces" /> for details.</entry>
+	</row>
+	<row>
+	  <entry>__u32</entry>
+	  <entry><structfield>reserved</structfield>[7]</entry>
+	  <entry>Reserved for future extensions. Applications and drivers must
+	  set the array to zero.</entry>
+	</row>
+      </tbody>
+    </tgroup>
+  </table>
+
+  <section id="v4l2-mbus-pixelcode">
+    <title>Media Bus Pixel Codes</title>
+
+    <para>The media bus pixel codes describe image formats as flowing over
+    physical busses (both between separate physical components and inside SoC
+    devices). This should not be confused with the V4L2 pixel formats that
+    describe, using four character codes, image formats as stored in memory.
+    </para>
+
+    <para>While there is a relationship between image formats on busses and
+    image formats in memory (a raw Bayer image won't be magically converted to
+    JPEG just by storing it to memory), there is no one-to-one correspondance
+    between them.</para>
+
+    <section>
+      <title>Packed RGB Formats</title>
+
+      <para>Those formats transfer pixel data as red, green and blue components.
+      The format code is made of the following information.
+      <itemizedlist>
+	<listitem><para>The red, green and blue components order code, as encoded in a
+	pixel sample. Possible values are RGB and BGR.</para></listitem>
+	<listitem><para>The number of bits per component, for each component. The values
+	can be different for all components. Common values are 555 and 565.</para>
+	</listitem>
+	<listitem><para>The number of bus samples per pixel. Pixels that are wider than
+	the bus width must be transferred in multiple samples. Common values are
+	1 and 2.</para></listitem>
+	<listitem><para>The bus width.</para></listitem>
+	<listitem><para>For formats where the total number of bits per pixel is smaller
+	than the number of bus samples per pixel times the bus width, a padding
+	value stating if the bytes are padded in their most high order bits
+	(PADHI) or low order bits (PADLO).</para></listitem>
+	<listitem><para>For formats where the number of bus samples per pixel is larger
+	than 1, an endianness value stating if the pixel is transferred MSB first
+	(BE) or LSB first (LE).</para></listitem>
+      </itemizedlist>
+      </para>
+
+      <para>For instance, a format where pixels are encoded as 5-bits red, 5-bits
+      green and 5-bit blue values padded on the high bit, transferred as 2 8-bit
+      samples per pixel with the most significant bits (padding, red and half of
+      the green value) transferred first will be named
+      <constant>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</constant>.
+      </para>
+
+      <para>The following tables list existing packet RGB formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-rgb">
+	<title>RGB formats</title>
+	<tgroup cols="11">
+	  <colspec colname="id" align="left" />
+	  <colspec colname="code" align="center"/>
+	  <colspec colname="bit" />
+	  <colspec colnum="4" colname="b07" align="center" />
+	  <colspec colnum="5" colname="b06" align="center" />
+	  <colspec colnum="6" colname="b05" align="center" />
+	  <colspec colnum="7" colname="b04" align="center" />
+	  <colspec colnum="8" colname="b03" align="center" />
+	  <colspec colnum="9" colname="b02" align="center" />
+	  <colspec colnum="10" colname="b01" align="center" />
+	  <colspec colnum="11" colname="b00" align="center" />
+	  <spanspec namest="b07" nameend="b00" spanname="b0" />
+	  <thead>
+	    <row>
+	      <entry>Identifier</entry>
+	      <entry>Code</entry>
+	      <entry></entry>
+	      <entry spanname="b0">Data organization</entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>Bit</entry>
+	      <entry>7</entry>
+	      <entry>6</entry>
+	      <entry>5</entry>
+	      <entry>4</entry>
+	      <entry>3</entry>
+	      <entry>2</entry>
+	      <entry>1</entry>
+	      <entry>0</entry>
+	    </row>
+	  </thead>
+	  <tbody valign="top">
+	    <row id="V4L2-MBUS-FMT-RGB444-2X8-PADHI-BE">
+	      <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_BE</entry>
+	      <entry>0x1001</entry>
+	      <entry></entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-RGB444-2X8-PADHI-LE">
+	      <entry>V4L2_MBUS_FMT_RGB444_2X8_PADHI_LE</entry>
+	      <entry>0x1002</entry>
+	      <entry></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-RGB555-2X8-PADHI-BE">
+	      <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE</entry>
+	      <entry>0x1003</entry>
+	      <entry></entry>
+	      <entry>0</entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-RGB555-2X8-PADHI-LE">
+	      <entry>V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE</entry>
+	      <entry>0x1004</entry>
+	      <entry></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>0</entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-BGR565-2X8-BE">
+	      <entry>V4L2_MBUS_FMT_BGR565_2X8_BE</entry>
+	      <entry>0x1005</entry>
+	      <entry></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-BGR565-2X8-LE">
+	      <entry>V4L2_MBUS_FMT_BGR565_2X8_LE</entry>
+	      <entry>0x1006</entry>
+	      <entry></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-RGB565-2X8-BE">
+	      <entry>V4L2_MBUS_FMT_RGB565_2X8_BE</entry>
+	      <entry>0x1007</entry>
+	      <entry></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-RGB565-2X8-LE">
+	      <entry>V4L2_MBUS_FMT_RGB565_2X8_LE</entry>
+	      <entry>0x1008</entry>
+	      <entry></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	    </row>
+	  </tbody>
+	</tgroup>
+      </table>
+    </section>
+
+    <section>
+      <title>Bayer Formats</title>
+
+      <para>Those formats transfer pixel data as red, green and blue components.
+      The format code is made of the following information.
+      <itemizedlist>
+	<listitem><para>The red, green and blue components order code, as encoded in a
+	pixel sample. The possible values are shown in <xref
+	linkend="bayer-patterns" />.</para></listitem>
+	<listitem><para>The number of bits per pixel component. All components are
+	transferred on the same number of bits. Common values are 8, 10 and 12.</para>
+	</listitem>
+	<listitem><para>If the pixel components are DPCM-compressed, a mention of the
+	DPCM compression and the number of bits per compressed pixel component.</para>
+	</listitem>
+	<listitem><para>The number of bus samples per pixel. Pixels that are wider than
+	the bus width must be transferred in multiple samples. Common values are
+	1 and 2.</para></listitem>
+	<listitem><para>The bus width.</para></listitem>
+	<listitem><para>For formats where the total number of bits per pixel is smaller
+	than the number of bus samples per pixel times the bus width, a padding
+	value stating if the bytes are padded in their most high order bits
+	(PADHI) or low order bits (PADLO).</para></listitem>
+	<listitem><para>For formats where the number of bus samples per pixel is larger
+	than 1, an endianness value stating if the pixel is transferred MSB first
+	(BE) or LSB first (LE).</para></listitem>
+      </itemizedlist>
+      </para>
+
+      <para>For instance, a format with uncompressed 10-bit Bayer components
+      arranged in a red, green, green, blue pattern transferred as 2 8-bit
+      samples per pixel with the least significant bits transferred first will
+      be named <constant>V4L2_MBUS_FMT_SRGGB10_2X8_PADHI_LE</constant>.
+      </para>
+
+      <figure id="bayer-patterns">
+	<title>Bayer Patterns</title>
+	<mediaobject>
+	  <imageobject>
+	    <imagedata fileref="bayer.pdf" format="PS" />
+	  </imageobject>
+	  <imageobject>
+	    <imagedata fileref="bayer.png" format="PNG" />
+	  </imageobject>
+	  <textobject>
+	    <phrase>Bayer filter color patterns</phrase>
+	  </textobject>
+	</mediaobject>
+      </figure>
+
+      <para>The following table lists existing packet Bayer formats. The data
+      organization is given as an example for the first pixel only.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-bayer">
+	<title>Bayer Formats</title>
+	<tgroup cols="15">
+	  <colspec colname="id" align="left" />
+	  <colspec colname="code" align="center"/>
+	  <colspec colname="bit" />
+	  <colspec colnum="4" colname="b11" align="center" />
+	  <colspec colnum="5" colname="b10" align="center" />
+	  <colspec colnum="6" colname="b09" align="center" />
+	  <colspec colnum="7" colname="b08" align="center" />
+	  <colspec colnum="8" colname="b07" align="center" />
+	  <colspec colnum="9" colname="b06" align="center" />
+	  <colspec colnum="10" colname="b05" align="center" />
+	  <colspec colnum="11" colname="b04" align="center" />
+	  <colspec colnum="12" colname="b03" align="center" />
+	  <colspec colnum="13" colname="b02" align="center" />
+	  <colspec colnum="14" colname="b01" align="center" />
+	  <colspec colnum="15" colname="b00" align="center" />
+	  <spanspec namest="b11" nameend="b00" spanname="b0" />
+	  <thead>
+	    <row>
+	      <entry>Identifier</entry>
+	      <entry>Code</entry>
+	      <entry></entry>
+	      <entry spanname="b0">Data organization</entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>Bit</entry>
+	      <entry>11</entry>
+	      <entry>10</entry>
+	      <entry>9</entry>
+	      <entry>8</entry>
+	      <entry>7</entry>
+	      <entry>6</entry>
+	      <entry>5</entry>
+	      <entry>4</entry>
+	      <entry>3</entry>
+	      <entry>2</entry>
+	      <entry>1</entry>
+	      <entry>0</entry>
+	    </row>
+	  </thead>
+	  <tbody valign="top">
+	    <row id="V4L2-MBUS-FMT-SBGGR8-1X8">
+	      <entry>V4L2_MBUS_FMT_SBGGR8_1X8</entry>
+	      <entry>0x3001</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGBRG8-1X8">
+	      <entry>V4L2_MBUS_FMT_SGBRG8_1X8</entry>
+	      <entry>0x3013</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGRBG8-1X8">
+	      <entry>V4L2_MBUS_FMT_SGRBG8_1X8</entry>
+	      <entry>0x3002</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SRGGB8-1X8">
+	      <entry>V4L2_MBUS_FMT_SRGGB8_1X8</entry>
+	      <entry>0x3014</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>r<subscript>7</subscript></entry>
+	      <entry>r<subscript>6</subscript></entry>
+	      <entry>r<subscript>5</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR10-DPCM8-1X8">
+	      <entry>V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8</entry>
+	      <entry>0x300b</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGBRG10-DPCM8-1X8">
+	      <entry>V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8</entry>
+	      <entry>0x300c</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGRBG10-DPCM8-1X8">
+	      <entry>V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8</entry>
+	      <entry>0x3009</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SRGGB10-DPCM8-1X8">
+	      <entry>V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8</entry>
+	      <entry>0x300d</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>r<subscript>7</subscript></entry>
+	      <entry>r<subscript>6</subscript></entry>
+	      <entry>r<subscript>5</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADHI-BE">
+	      <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_BE</entry>
+	      <entry>0x3003</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>b<subscript>9</subscript></entry>
+	      <entry>b<subscript>8</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADHI-LE">
+	      <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADHI_LE</entry>
+	      <entry>0x3004</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>b<subscript>9</subscript></entry>
+	      <entry>b<subscript>8</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADLO-BE">
+	      <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_BE</entry>
+	      <entry>0x3005</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>9</subscript></entry>
+	      <entry>b<subscript>8</subscript></entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR10-2X8-PADLO-LE">
+	      <entry>V4L2_MBUS_FMT_SBGGR10_2X8_PADLO_LE</entry>
+	      <entry>0x3006</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	      <entry>0</entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>9</subscript></entry>
+	      <entry>b<subscript>8</subscript></entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR10-1X10">
+	      <entry>V4L2_MBUS_FMT_SBGGR10_1X10</entry>
+	      <entry>0x3007</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>b<subscript>9</subscript></entry>
+	      <entry>b<subscript>8</subscript></entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGBRG10-1X10">
+	      <entry>V4L2_MBUS_FMT_SGBRG10_1X10</entry>
+	      <entry>0x300e</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>g<subscript>9</subscript></entry>
+	      <entry>g<subscript>8</subscript></entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGRBG10-1X10">
+	      <entry>V4L2_MBUS_FMT_SGRBG10_1X10</entry>
+	      <entry>0x300a</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>g<subscript>9</subscript></entry>
+	      <entry>g<subscript>8</subscript></entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SRGGB10-1X10">
+	      <entry>V4L2_MBUS_FMT_SRGGB10_1X10</entry>
+	      <entry>0x300f</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>r<subscript>9</subscript></entry>
+	      <entry>r<subscript>8</subscript></entry>
+	      <entry>r<subscript>7</subscript></entry>
+	      <entry>r<subscript>6</subscript></entry>
+	      <entry>r<subscript>5</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SBGGR12-1X12">
+	      <entry>V4L2_MBUS_FMT_SBGGR12_1X12</entry>
+	      <entry>0x3008</entry>
+	      <entry></entry>
+	      <entry>b<subscript>11</subscript></entry>
+	      <entry>b<subscript>10</subscript></entry>
+	      <entry>b<subscript>9</subscript></entry>
+	      <entry>b<subscript>8</subscript></entry>
+	      <entry>b<subscript>7</subscript></entry>
+	      <entry>b<subscript>6</subscript></entry>
+	      <entry>b<subscript>5</subscript></entry>
+	      <entry>b<subscript>4</subscript></entry>
+	      <entry>b<subscript>3</subscript></entry>
+	      <entry>b<subscript>2</subscript></entry>
+	      <entry>b<subscript>1</subscript></entry>
+	      <entry>b<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGBRG12-1X12">
+	      <entry>V4L2_MBUS_FMT_SGBRG12_1X12</entry>
+	      <entry>0x3010</entry>
+	      <entry></entry>
+	      <entry>g<subscript>11</subscript></entry>
+	      <entry>g<subscript>10</subscript></entry>
+	      <entry>g<subscript>9</subscript></entry>
+	      <entry>g<subscript>8</subscript></entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SGRBG12-1X12">
+	      <entry>V4L2_MBUS_FMT_SGRBG12_1X12</entry>
+	      <entry>0x3011</entry>
+	      <entry></entry>
+	      <entry>g<subscript>11</subscript></entry>
+	      <entry>g<subscript>10</subscript></entry>
+	      <entry>g<subscript>9</subscript></entry>
+	      <entry>g<subscript>8</subscript></entry>
+	      <entry>g<subscript>7</subscript></entry>
+	      <entry>g<subscript>6</subscript></entry>
+	      <entry>g<subscript>5</subscript></entry>
+	      <entry>g<subscript>4</subscript></entry>
+	      <entry>g<subscript>3</subscript></entry>
+	      <entry>g<subscript>2</subscript></entry>
+	      <entry>g<subscript>1</subscript></entry>
+	      <entry>g<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-SRGGB12-1X12">
+	      <entry>V4L2_MBUS_FMT_SRGGB12_1X12</entry>
+	      <entry>0x3012</entry>
+	      <entry></entry>
+	      <entry>r<subscript>11</subscript></entry>
+	      <entry>r<subscript>10</subscript></entry>
+	      <entry>r<subscript>9</subscript></entry>
+	      <entry>r<subscript>8</subscript></entry>
+	      <entry>r<subscript>7</subscript></entry>
+	      <entry>r<subscript>6</subscript></entry>
+	      <entry>r<subscript>5</subscript></entry>
+	      <entry>r<subscript>4</subscript></entry>
+	      <entry>r<subscript>3</subscript></entry>
+	      <entry>r<subscript>2</subscript></entry>
+	      <entry>r<subscript>1</subscript></entry>
+	      <entry>r<subscript>0</subscript></entry>
+	    </row>
+	  </tbody>
+	</tgroup>
+      </table>
+    </section>
+
+    <section>
+      <title>Packed YUV Formats</title>
+
+      <para>Those data formats transfer pixel data as (possibly downsampled) Y, U
+      and V components. The format code is made of the following information.
+      <itemizedlist>
+	<listitem><para>The Y, U and V components order code, as transferred on the
+	bus. Possible values are YUYV, UYVY, YVYU and VYUY.</para></listitem>
+	<listitem><para>The number of bits per pixel component. All components are
+	transferred on the same number of bits. Common values are 8, 10 and 12.</para>
+	</listitem>
+	<listitem><para>The number of bus samples per pixel. Pixels that are wider than
+	the bus width must be transferred in multiple samples. Common values are
+	1, 1.5 (encoded as 1_5) and 2.</para></listitem>
+	<listitem><para>The bus width. When the bus width is larger than the number of
+	bits per pixel component, several components are packed in a single bus
+	sample. The components are ordered as specified by the order code, with
+	components on the left of the code transferred in the high order bits.
+	Common values are 8 and 16.</para>
+	</listitem>
+      </itemizedlist>
+      </para>
+
+      <para>For instance, a format where pixels are encoded as 8-bit YUV values
+      downsampled to 4:2:2 and transferred as 2 8-bit bus samples per pixel in the
+      U, Y, V, Y order will be named <constant>V4L2_MBUS_FMT_UYVY8_2X8</constant>.
+      </para>
+
+      <para>The following table lisst existing packet YUV formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-yuv8">
+	<title>YUV Formats</title>
+	<tgroup cols="23">
+	  <colspec colname="id" align="left" />
+	  <colspec colname="code" align="center"/>
+	  <colspec colname="bit" />
+	  <colspec colnum="4" colname="b19" align="center" />
+	  <colspec colnum="5" colname="b18" align="center" />
+	  <colspec colnum="6" colname="b17" align="center" />
+	  <colspec colnum="7" colname="b16" align="center" />
+	  <colspec colnum="8" colname="b15" align="center" />
+	  <colspec colnum="9" colname="b14" align="center" />
+	  <colspec colnum="10" colname="b13" align="center" />
+	  <colspec colnum="11" colname="b12" align="center" />
+	  <colspec colnum="12" colname="b11" align="center" />
+	  <colspec colnum="13" colname="b10" align="center" />
+	  <colspec colnum="14" colname="b09" align="center" />
+	  <colspec colnum="15" colname="b08" align="center" />
+	  <colspec colnum="16" colname="b07" align="center" />
+	  <colspec colnum="17" colname="b06" align="center" />
+	  <colspec colnum="18" colname="b05" align="center" />
+	  <colspec colnum="19" colname="b04" align="center" />
+	  <colspec colnum="20" colname="b03" align="center" />
+	  <colspec colnum="21" colname="b02" align="center" />
+	  <colspec colnum="22" colname="b01" align="center" />
+	  <colspec colnum="23" colname="b00" align="center" />
+	  <spanspec namest="b19" nameend="b00" spanname="b0" />
+	  <thead>
+	    <row>
+	      <entry>Identifier</entry>
+	      <entry>Code</entry>
+	      <entry></entry>
+	      <entry spanname="b0">Data organization</entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>Bit</entry>
+	      <entry>19</entry>
+	      <entry>18</entry>
+	      <entry>17</entry>
+	      <entry>16</entry>
+	      <entry>15</entry>
+	      <entry>14</entry>
+	      <entry>13</entry>
+	      <entry>12</entry>
+	      <entry>11</entry>
+	      <entry>10</entry>
+	      <entry>9</entry>
+	      <entry>8</entry>
+	      <entry>7</entry>
+	      <entry>6</entry>
+	      <entry>5</entry>
+	      <entry>4</entry>
+	      <entry>3</entry>
+	      <entry>2</entry>
+	      <entry>1</entry>
+	      <entry>0</entry>
+	    </row>
+	  </thead>
+	  <tbody valign="top">
+	    <row id="V4L2-MBUS-FMT-Y8-1X8">
+	      <entry>V4L2_MBUS_FMT_Y8_1X8</entry>
+	      <entry>0x2001</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY8-1_5X8">
+	      <entry>V4L2_MBUS_FMT_UYVY8_1_5X8</entry>
+	      <entry>0x2002</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY8-1_5X8">
+	      <entry>V4L2_MBUS_FMT_VYUY8_1_5X8</entry>
+	      <entry>0x2003</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV8-1_5X8">
+	      <entry>V4L2_MBUS_FMT_YUYV8_1_5X8</entry>
+	      <entry>0x2004</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU8-1_5X8">
+	      <entry>V4L2_MBUS_FMT_YVYU8_1_5X8</entry>
+	      <entry>0x2005</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY8-2X8">
+	      <entry>V4L2_MBUS_FMT_UYVY8_2X8</entry>
+	      <entry>0x2006</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY8-2X8">
+	      <entry>V4L2_MBUS_FMT_VYUY8_2X8</entry>
+	      <entry>0x2007</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV8-2X8">
+	      <entry>V4L2_MBUS_FMT_YUYV8_2X8</entry>
+	      <entry>0x2008</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU8-2X8">
+	      <entry>V4L2_MBUS_FMT_YVYU8_2X8</entry>
+	      <entry>0x2009</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-Y10-1X10">
+	      <entry>V4L2_MBUS_FMT_Y10_1X10</entry>
+	      <entry>0x200a</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV10-2X10">
+	      <entry>V4L2_MBUS_FMT_YUYV10_2X10</entry>
+	      <entry>0x200b</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU10-2X10">
+	      <entry>V4L2_MBUS_FMT_YVYU10_2X10</entry>
+	      <entry>0x200c</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-Y12-1X12">
+	      <entry>V4L2_MBUS_FMT_Y12_1X12</entry>
+	      <entry>0x2013</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>11</subscript></entry>
+	      <entry>y<subscript>10</subscript></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-UYVY8-1X16">
+	      <entry>V4L2_MBUS_FMT_UYVY8_1X16</entry>
+	      <entry>0x200f</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-VYUY8-1X16">
+	      <entry>V4L2_MBUS_FMT_VYUY8_1X16</entry>
+	      <entry>0x2010</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV8-1X16">
+	      <entry>V4L2_MBUS_FMT_YUYV8_1X16</entry>
+	      <entry>0x2011</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU8-1X16">
+	      <entry>V4L2_MBUS_FMT_YVYU8_1X16</entry>
+	      <entry>0x2012</entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>-</entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YUYV10-1X20">
+	      <entry>V4L2_MBUS_FMT_YUYV10_1X20</entry>
+	      <entry>0x200d</entry>
+	      <entry></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row id="V4L2-MBUS-FMT-YVYU10-1X20">
+	      <entry>V4L2_MBUS_FMT_YVYU10_1X20</entry>
+	      <entry>0x200e</entry>
+	      <entry></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>v<subscript>9</subscript></entry>
+	      <entry>v<subscript>8</subscript></entry>
+	      <entry>v<subscript>7</subscript></entry>
+	      <entry>v<subscript>6</subscript></entry>
+	      <entry>v<subscript>5</subscript></entry>
+	      <entry>v<subscript>4</subscript></entry>
+	      <entry>v<subscript>3</subscript></entry>
+	      <entry>v<subscript>2</subscript></entry>
+	      <entry>v<subscript>1</subscript></entry>
+	      <entry>v<subscript>0</subscript></entry>
+	    </row>
+	    <row>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry></entry>
+	      <entry>y<subscript>9</subscript></entry>
+	      <entry>y<subscript>8</subscript></entry>
+	      <entry>y<subscript>7</subscript></entry>
+	      <entry>y<subscript>6</subscript></entry>
+	      <entry>y<subscript>5</subscript></entry>
+	      <entry>y<subscript>4</subscript></entry>
+	      <entry>y<subscript>3</subscript></entry>
+	      <entry>y<subscript>2</subscript></entry>
+	      <entry>y<subscript>1</subscript></entry>
+	      <entry>y<subscript>0</subscript></entry>
+	      <entry>u<subscript>9</subscript></entry>
+	      <entry>u<subscript>8</subscript></entry>
+	      <entry>u<subscript>7</subscript></entry>
+	      <entry>u<subscript>6</subscript></entry>
+	      <entry>u<subscript>5</subscript></entry>
+	      <entry>u<subscript>4</subscript></entry>
+	      <entry>u<subscript>3</subscript></entry>
+	      <entry>u<subscript>2</subscript></entry>
+	      <entry>u<subscript>1</subscript></entry>
+	      <entry>u<subscript>0</subscript></entry>
+	    </row>
+	  </tbody>
+	</tgroup>
+      </table>
+    </section>
+  </section>
+</section>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/v4l2.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/v4l2.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/v4l2.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/v4l2.xml	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,17 @@
 	  </address>
 	</affiliation>
       </author>
+
+      <author>
+      	<firstname>Pawel</firstname>
+	<surname>Osciak</surname>
+	<contrib>Designed and documented the multi-planar API.</contrib>
+	<affiliation>
+	  <address>
+	    <email>pawel AT osciak.com</email>
+	  </address>
+	</affiliation>
+      </author>
     </authorgroup>
 
     <copyright>
@@ -102,7 +113,8 @@
       <year>2010</year>
       <year>2011</year>
       <holder>Bill Dirks, Michael H. Schimek, Hans Verkuil, Martin
-Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab</holder>
+Rubli, Andy Walls, Muralidharan Karicheri, Mauro Carvalho Chehab,
+	Pawel Osciak</holder>
     </copyright>
     <legalnotice>
     <para>Except when explicitly stated as GPL, programming examples within
@@ -116,6 +128,13 @@
 applications. -->
 
       <revision>
+	<revnumber>2.6.39</revnumber>
+	<date>2011-03-01</date>
+	<authorinitials>mcc, po</authorinitials>
+	<revremark>Removed VIDIOC_*_OLD from videodev2.h header and update it to reflect latest changes. Added the <link linkend="planar-apis">multi-planar API</link>.</revremark>
+      </revision>
+
+      <revision>
 	<revnumber>2.6.37</revnumber>
 	<date>2010-08-06</date>
 	<authorinitials>hv</authorinitials>
@@ -382,7 +401,7 @@
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 2.6.38</subtitle>
+ <subtitle>Revision 2.6.39</subtitle>
 
   <chapter id="common">
     &sub-common;
@@ -411,6 +430,7 @@
     <section id="radio"> &sub-dev-radio; </section>
     <section id="rds"> &sub-dev-rds; </section>
     <section id="event"> &sub-dev-event; </section>
+    <section id="subdev"> &sub-dev-subdev; </section>
   </chapter>
 
   <chapter id="driver">
@@ -478,6 +498,12 @@
     &sub-reqbufs;
     &sub-s-hw-freq-seek;
     &sub-streamon;
+    &sub-subdev-enum-frame-interval;
+    &sub-subdev-enum-frame-size;
+    &sub-subdev-enum-mbus-code;
+    &sub-subdev-g-crop;
+    &sub-subdev-g-fmt;
+    &sub-subdev-g-frame-interval;
     &sub-subscribe-event;
     <!-- End of ioctls. -->
     &sub-mmap;
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/videodev2.h.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/videodev2.h.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/videodev2.h.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/videodev2.h.xml	2011-05-19 00:06:34.000000000 -0400
@@ -71,6 +71,7 @@
  * Moved from videodev.h
  */
 #define VIDEO_MAX_FRAME               32
+#define VIDEO_MAX_PLANES               8
 
 #ifndef __KERNEL__
 
@@ -158,9 +159,23 @@
         /* Experimental */
         V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY = 8,
 #endif
+        V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
+        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
         V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
 
+#define V4L2_TYPE_IS_MULTIPLANAR(type)                  \
+        ((type) == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE   \
+         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+
+#define V4L2_TYPE_IS_OUTPUT(type)                               \
+        ((type) == V4L2_BUF_TYPE_VIDEO_OUTPUT                   \
+         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE         \
+         || (type) == V4L2_BUF_TYPE_VIDEO_OVERLAY               \
+         || (type) == V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY        \
+         || (type) == V4L2_BUF_TYPE_VBI_OUTPUT                  \
+         || (type) == V4L2_BUF_TYPE_SLICED_VBI_OUTPUT)
+
 enum <link linkend="v4l2-tuner-type">v4l2_tuner_type</link> {
         V4L2_TUNER_RADIO             = 1,
         V4L2_TUNER_ANALOG_TV         = 2,
@@ -246,6 +261,11 @@
 #define V4L2_CAP_HW_FREQ_SEEK           0x00000400  /* Can do hardware frequency seek  */
 #define V4L2_CAP_RDS_OUTPUT             0x00000800  /* Is an RDS encoder */
 
+/* Is a video capture device that supports multiplanar formats */
+#define V4L2_CAP_VIDEO_CAPTURE_MPLANE   0x00001000
+/* Is a video output device that supports multiplanar formats */
+#define V4L2_CAP_VIDEO_OUTPUT_MPLANE    0x00002000
+
 #define V4L2_CAP_TUNER                  0x00010000  /* has a tuner */
 #define V4L2_CAP_AUDIO                  0x00020000  /* has audio support */
 #define V4L2_CAP_RADIO                  0x00040000  /* is a radio device */
@@ -320,6 +340,13 @@
 #define <link linkend="V4L2-PIX-FMT-NV16">V4L2_PIX_FMT_NV16</link>    v4l2_fourcc('N', 'V', '1', '6') /* 16  Y/CbCr 4:2:2  */
 #define <link linkend="V4L2-PIX-FMT-NV61">V4L2_PIX_FMT_NV61</link>    v4l2_fourcc('N', 'V', '6', '1') /* 16  Y/CrCb 4:2:2  */
 
+/* two non contiguous planes - one Y, one Cr + Cb interleaved  */
+#define <link linkend="V4L2-PIX-FMT-NV12M">V4L2_PIX_FMT_NV12M</link>   v4l2_fourcc('N', 'M', '1', '2') /* 12  Y/CbCr 4:2:0  */
+#define <link linkend="V4L2-PIX-FMT-NV12MT">V4L2_PIX_FMT_NV12MT</link>  v4l2_fourcc('T', 'M', '1', '2') /* 12  Y/CbCr 4:2:0 64x32 macroblocks */
+
+/* three non contiguous planes - Y, Cb, Cr */
+#define <link linkend="V4L2-PIX-FMT-YUV420M">V4L2_PIX_FMT_YUV420M</link> v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
+
 /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define <link linkend="V4L2-PIX-FMT-SBGGR8">V4L2_PIX_FMT_SBGGR8</link>  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
 #define <link linkend="V4L2-PIX-FMT-SGBRG8">V4L2_PIX_FMT_SGBRG8</link>  v4l2_fourcc('G', 'B', 'R', 'G') /*  8  GBGB.. RGRG.. */
@@ -518,6 +545,62 @@
         __u32                   reserved[2];
 };
 
+/**
+ * struct <link linkend="v4l2-plane">v4l2_plane</link> - plane info for multi-planar buffers
+ * @bytesused:          number of bytes occupied by data in the plane (payload)
+ * @length:             size of this plane (NOT the payload) in bytes
+ * @mem_offset:         when memory in the associated struct <link linkend="v4l2-buffer">v4l2_buffer</link> is
+ *                      V4L2_MEMORY_MMAP, equals the offset from the start of
+ *                      the device memory for this plane (or is a "cookie" that
+ *                      should be passed to mmap() called on the video node)
+ * @userptr:            when memory is V4L2_MEMORY_USERPTR, a userspace pointer
+ *                      pointing to this plane
+ * @data_offset:        offset in the plane to the start of data; usually 0,
+ *                      unless there is a header in front of the data
+ *
+ * Multi-planar buffers consist of one or more planes, e.g. an YCbCr buffer
+ * with two planes can have one plane for Y, and another for interleaved CbCr
+ * components. Each plane can reside in a separate memory buffer, or even in
+ * a completely separate memory node (e.g. in embedded devices).
+ */
+struct <link linkend="v4l2-plane">v4l2_plane</link> {
+        __u32                   bytesused;
+        __u32                   length;
+        union {
+                __u32           mem_offset;
+                unsigned long   userptr;
+        } m;
+        __u32                   data_offset;
+        __u32                   reserved[11];
+};
+
+/**
+ * struct <link linkend="v4l2-buffer">v4l2_buffer</link> - video buffer info
+ * @index:      id number of the buffer
+ * @type:       buffer type (type == *_MPLANE for multiplanar buffers)
+ * @bytesused:  number of bytes occupied by data in the buffer (payload);
+ *              unused (set to 0) for multiplanar buffers
+ * @flags:      buffer informational flags
+ * @field:      field order of the image in the buffer
+ * @timestamp:  frame timestamp
+ * @timecode:   frame timecode
+ * @sequence:   sequence count of this frame
+ * @memory:     the method, in which the actual video data is passed
+ * @offset:     for non-multiplanar buffers with memory == V4L2_MEMORY_MMAP;
+ *              offset from the start of the device memory for this plane,
+ *              (or a "cookie" that should be passed to mmap() as offset)
+ * @userptr:    for non-multiplanar buffers with memory == V4L2_MEMORY_USERPTR;
+ *              a userspace pointer pointing to this buffer
+ * @planes:     for multiplanar buffers; userspace pointer to the array of plane
+ *              info structs for this buffer
+ * @length:     size in bytes of the buffer (NOT its payload) for single-plane
+ *              buffers (when type != *_MPLANE); number of elements in the
+ *              planes array for multi-plane buffers
+ * @input:      input number from which the video data has has been captured
+ *
+ * Contains data exchanged by application and driver using one of the Streaming
+ * I/O methods.
+ */
 struct <link linkend="v4l2-buffer">v4l2_buffer</link> {
         __u32                   index;
         enum <link linkend="v4l2-buf-type">v4l2_buf_type</link>      type;
@@ -533,6 +616,7 @@
         union {
                 __u32           offset;
                 unsigned long   userptr;
+                struct <link linkend="v4l2-plane">v4l2_plane</link> *planes;
         } m;
         __u32                   length;
         __u32                   input;
@@ -1623,12 +1707,56 @@
  *      A G G R E G A T E   S T R U C T U R E S
  */
 
-/*      Stream data format
+/**
+ * struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> - additional, per-plane format definition
+ * @sizeimage:          maximum size in bytes required for data, for which
+ *                      this plane will be used
+ * @bytesperline:       distance in bytes between the leftmost pixels in two
+ *                      adjacent lines
+ */
+struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link> {
+        __u32           sizeimage;
+        __u16           bytesperline;
+        __u16           reserved[7];
+} __attribute__ ((packed));
+
+/**
+ * struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> - multiplanar format definition
+ * @width:              image width in pixels
+ * @height:             image height in pixels
+ * @pixelformat:        little endian four character code (fourcc)
+ * @field:              field order (for interlaced video)
+ * @colorspace:         supplemental to pixelformat
+ * @plane_fmt:          per-plane information
+ * @num_planes:         number of planes for this format
+ */
+struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link> {
+        __u32                           width;
+        __u32                           height;
+        __u32                           pixelformat;
+        enum <link linkend="v4l2-field">v4l2_field</link>                 field;
+        enum <link linkend="v4l2-colorspace">v4l2_colorspace</link>            colorspace;
+
+        struct <link linkend="v4l2-plane-pix-format">v4l2_plane_pix_format</link>    plane_fmt[VIDEO_MAX_PLANES];
+        __u8                            num_planes;
+        __u8                            reserved[11];
+} __attribute__ ((packed));
+
+/**
+ * struct <link linkend="v4l2-format">v4l2_format</link> - stream data format
+ * @type:       type of the data stream
+ * @pix:        definition of an image format
+ * @pix_mp:     definition of a multiplanar image format
+ * @win:        definition of an overlaid image
+ * @vbi:        raw VBI capture or output parameters
+ * @sliced:     sliced VBI capture or output parameters
+ * @raw_data:   placeholder for future extensions and custom formats
  */
 struct <link linkend="v4l2-format">v4l2_format</link> {
         enum <link linkend="v4l2-buf-type">v4l2_buf_type</link> type;
         union {
                 struct <link linkend="v4l2-pix-format">v4l2_pix_format</link>          pix;     /* V4L2_BUF_TYPE_VIDEO_CAPTURE */
+                struct <link linkend="v4l2-pix-format-mplane">v4l2_pix_format_mplane</link>   pix_mp;  /* V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE */
                 struct <link linkend="v4l2-window">v4l2_window</link>              win;     /* V4L2_BUF_TYPE_VIDEO_OVERLAY */
                 struct <link linkend="v4l2-vbi-format">v4l2_vbi_format</link>          vbi;     /* V4L2_BUF_TYPE_VBI_CAPTURE */
                 struct <link linkend="v4l2-sliced-vbi-format">v4l2_sliced_vbi_format</link>   sliced;  /* V4L2_BUF_TYPE_SLICED_VBI_CAPTURE */
@@ -1636,7 +1764,6 @@
         } fmt;
 };
 
-
 /*      Stream type-dependent parameters
  */
 struct <link linkend="v4l2-streamparm">v4l2_streamparm</link> {
@@ -1809,16 +1936,6 @@
 /* Reminder: when adding new ioctls please add support for them to
    drivers/media/video/v4l2-compat-ioctl32.c as well! */
 
-#ifdef __OLD_VIDIOC_
-/* for compatibility, will go away some day */
-#define VIDIOC_OVERLAY_OLD      _IOWR('V', 14, int)
-#define VIDIOC_S_PARM_OLD        _IOW('V', 22, struct <link linkend="v4l2-streamparm">v4l2_streamparm</link>)
-#define VIDIOC_S_CTRL_OLD        _IOW('V', 28, struct <link linkend="v4l2-control">v4l2_control</link>)
-#define VIDIOC_G_AUDIO_OLD      _IOWR('V', 33, struct <link linkend="v4l2-audio">v4l2_audio</link>)
-#define VIDIOC_G_AUDOUT_OLD     _IOWR('V', 49, struct <link linkend="v4l2-audioout">v4l2_audioout</link>)
-#define VIDIOC_CROPCAP_OLD       _IOR('V', 58, struct <link linkend="v4l2-cropcap">v4l2_cropcap</link>)
-#endif
-
 #define BASE_VIDIOC_PRIVATE     192             /* 192-255 are private */
 
 #endif /* __LINUX_VIDEODEV2_H */
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-enum-fmt.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-enum-fmt.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-enum-fmt.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-enum-fmt.xml	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,9 @@
 	    <entry>Type of the data stream, set by the application.
 Only these types are valid here:
 <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>,
 <constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>, and custom (driver
 defined) types with code <constant>V4L2_BUF_TYPE_PRIVATE</constant>
 and higher.</entry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-g-fmt.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-g-fmt.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-g-fmt.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-g-fmt.xml	2011-05-19 00:06:34.000000000 -0400
@@ -60,11 +60,13 @@
 <structfield>type</structfield> field of a struct
 <structname>v4l2_format</structname> to the respective buffer (stream)
 type. For example video capture devices use
-<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>. When the application
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> or
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. When the application
 calls the <constant>VIDIOC_G_FMT</constant> ioctl with a pointer to
 this structure the driver fills the respective member of the
 <structfield>fmt</structfield> union. In case of video capture devices
-that is the &v4l2-pix-format; <structfield>pix</structfield> member.
+that is either the &v4l2-pix-format; <structfield>pix</structfield> or
+the &v4l2-pix-format-mplane; <structfield>pix_mp</structfield> member.
 When the requested buffer type is not supported drivers return an
 &EINVAL;.</para>
 
@@ -134,6 +136,15 @@
 	  </row>
 	  <row>
 	    <entry></entry>
+	    <entry>&v4l2-pix-format-mplane;</entry>
+	    <entry><structfield>pix_mp</structfield></entry>
+	    <entry>Definition of an image format, see <xref
+		linkend="pixfmt" />, used by video capture and output
+devices that support the <link linkend="planar-apis">multi-planar
+version of the API</link>.</entry>
+	  </row>
+	  <row>
+	    <entry></entry>
 	    <entry>&v4l2-window;</entry>
 	    <entry><structfield>win</structfield></entry>
 	    <entry>Definition of an overlaid image, see <xref
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-qbuf.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-qbuf.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-qbuf.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-qbuf.xml	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,8 @@
 contents of the struct <structname>v4l2_buffer</structname> returned
 by a &VIDIOC-QUERYBUF; ioctl will do as well. When the buffer is
 intended for output (<structfield>type</structfield> is
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> or
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>, or
 <constant>V4L2_BUF_TYPE_VBI_OUTPUT</constant>) applications must also
 initialize the <structfield>bytesused</structfield>,
 <structfield>field</structfield> and
@@ -75,7 +76,11 @@
 input, then <structfield>flags</structfield> should be set to
 <constant>V4L2_BUF_FLAG_INPUT</constant> and the field
 <structfield>input</structfield> must be initialized to the desired input.
-The <structfield>reserved</structfield> field must be set to 0.
+The <structfield>reserved</structfield> field must be set to 0. When using
+the <link linkend="planar-apis">multi-planar API</link>, the
+<structfield>m.planes</structfield> field must contain a userspace pointer
+to a filled-in array of &v4l2-plane; and the <structfield>length</structfield>
+field must be set to the number of elements in that array.
 </para>
 
     <para>To enqueue a <link linkend="mmap">memory mapped</link>
@@ -93,10 +98,13 @@
 buffer applications set the <structfield>memory</structfield>
 field to <constant>V4L2_MEMORY_USERPTR</constant>, the
 <structfield>m.userptr</structfield> field to the address of the
-buffer and <structfield>length</structfield> to its size.
-When <constant>VIDIOC_QBUF</constant> is called with a pointer to this
-structure the driver sets the <constant>V4L2_BUF_FLAG_QUEUED</constant>
-flag and clears the <constant>V4L2_BUF_FLAG_MAPPED</constant> and
+buffer and <structfield>length</structfield> to its size. When the multi-planar
+API is used, <structfield>m.userptr</structfield> and
+<structfield>length</structfield> members of the passed array of &v4l2-plane;
+have to be used instead. When <constant>VIDIOC_QBUF</constant> is called with
+a pointer to this structure the driver sets the
+<constant>V4L2_BUF_FLAG_QUEUED</constant> flag and clears the
+<constant>V4L2_BUF_FLAG_MAPPED</constant> and
 <constant>V4L2_BUF_FLAG_DONE</constant> flags in the
 <structfield>flags</structfield> field, or it returns an error code.
 This ioctl locks the memory pages of the buffer in physical memory,
@@ -115,7 +123,9 @@
 <constant>V4L2_BUF_FLAG_ERROR</constant> in the <structfield>flags</structfield>
 field. It indicates a non-critical (recoverable) streaming error. In such case
 the application may continue as normal, but should be aware that data in the
-dequeued buffer might be corrupted.</para>
+dequeued buffer might be corrupted. When using the multi-planar API, the
+planes array does not have to be passed; the <structfield>m.planes</structfield>
+member must be set to NULL in that case.</para>
 
     <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
 buffer is in the outgoing queue. When the
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-querybuf.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-querybuf.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-querybuf.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-querybuf.xml	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,10 @@
 to the number of buffers allocated with &VIDIOC-REQBUFS;
     (&v4l2-requestbuffers; <structfield>count</structfield>) minus one.
 The <structfield>reserved</structfield> field should to set to 0.
+When using the <link linkend="planar-apis">multi-planar API</link>, the
+<structfield>m.planes</structfield> field must contain a userspace pointer to an
+array of &v4l2-plane; and the <structfield>length</structfield> field has
+to be set to the number of elements in that array.
 After calling <constant>VIDIOC_QUERYBUF</constant> with a pointer to
     this structure drivers return an error code or fill the rest of
 the structure.</para>
@@ -70,11 +74,13 @@
 <constant>V4L2_BUF_FLAG_QUEUED</constant> and
 <constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
 <structfield>memory</structfield> field will be set to the current
-I/O method, the <structfield>m.offset</structfield>
+I/O method. For the single-planar API, the <structfield>m.offset</structfield>
 contains the offset of the buffer from the start of the device memory,
-the <structfield>length</structfield> field its size. The driver may
-or may not set the remaining fields and flags, they are meaningless in
-this context.</para>
+the <structfield>length</structfield> field its size. For the multi-planar API,
+fields <structfield>m.mem_offset</structfield> and
+<structfield>length</structfield> in the <structfield>m.planes</structfield>
+array elements will be used instead. The driver may or may not set the remaining
+fields and flags, they are meaningless in this context.</para>
 
     <para>The <structname>v4l2_buffer</structname> structure is
     specified in <xref linkend="buffer" />.</para>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-querycap.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-querycap.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-querycap.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-querycap.xml	2011-05-19 00:06:34.000000000 -0400
@@ -142,16 +142,30 @@
 	  <row>
 	    <entry><constant>V4L2_CAP_VIDEO_CAPTURE</constant></entry>
 	    <entry>0x00000001</entry>
-	    <entry>The device supports the <link
+	    <entry>The device supports the single-planar API through the <link
 linkend="capture">Video Capture</link> interface.</entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_CAP_VIDEO_CAPTURE_MPLANE</constant></entry>
+	    <entry>0x00001000</entry>
+	    <entry>The device supports the
+	    <link linkend="planar-apis">multi-planar API</link> through the
+	    <link linkend="capture">Video Capture</link> interface.</entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_CAP_VIDEO_OUTPUT</constant></entry>
 	    <entry>0x00000002</entry>
-	    <entry>The device supports the <link
+	    <entry>The device supports the single-planar API through the <link
 linkend="output">Video Output</link> interface.</entry>
 	  </row>
 	  <row>
+	    <entry><constant>V4L2_CAP_VIDEO_OUTPUT_MPLANE</constant></entry>
+	    <entry>0x00002000</entry>
+	    <entry>The device supports the
+	    <link linkend="planar-apis">multi-planar API</link> through the
+	    <link linkend="output">Video Output</link> interface.</entry>
+	  </row>
+	  <row>
 	    <entry><constant>V4L2_CAP_VIDEO_OVERLAY</constant></entry>
 	    <entry>0x00000004</entry>
 	    <entry>The device supports the <link
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-streamon.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-streamon.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-streamon.xml	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-streamon.xml	2011-05-19 00:06:34.000000000 -0400
@@ -93,6 +93,15 @@
 been allocated (memory mapping) or enqueued (output) yet.</para>
 	</listitem>
       </varlistentry>
+      <varlistentry>
+	<term><errorcode>EPIPE</errorcode></term>
+	<listitem>
+	  <para>The driver implements <link
+	  linkend="pad-level-formats">pad-level format configuration</link> and
+	  the pipeline configuration is invalid.
+	  </para>
+	</listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-interval.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,152 @@
+<refentry id="vidioc-subdev-enum-frame-interval">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</refname>
+    <refpurpose>Enumerate frame intervals</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_subdev_frame_interval_enum *
+	<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental">experimental</link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>This ioctl lets applications enumerate available frame intervals on a
+    given sub-device pad. Frame intervals only makes sense for sub-devices that
+    can control the frame period on their own. This includes, for instance,
+    image sensors and TV tuners.</para>
+
+    <para>For the common use case of image sensors, the frame intervals
+    available on the sub-device output pad depend on the frame format and size
+    on the same pad. Applications must thus specify the desired format and size
+    when enumerating frame intervals.</para>
+
+    <para>To enumerate frame intervals applications initialize the
+    <structfield>index</structfield>, <structfield>pad</structfield>,
+    <structfield>code</structfield>, <structfield>width</structfield> and
+    <structfield>height</structfield> fields of
+    &v4l2-subdev-frame-interval-enum; and call the
+    <constant>VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL</constant> ioctl with a pointer
+    to this structure. Drivers fill the rest of the structure or return
+    an &EINVAL; if one of the input fields is invalid. All frame intervals are
+    enumerable by beginning at index zero and incrementing by one until
+    <errorcode>EINVAL</errorcode> is returned.</para>
+
+    <para>Available frame intervals may depend on the current 'try' formats
+    at other pads of the sub-device, as well as on the current active links. See
+    &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
+
+    <para>Sub-devices that support the frame interval enumeration ioctl should
+    implemented it on a single pad only. Its behaviour when supported on
+    multiple pads of the same sub-device is not defined.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval-enum">
+      <title>struct <structname>v4l2_subdev_frame_interval_enum</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>Number of the format in the enumeration, set by the
+	    application.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>code</structfield></entry>
+	    <entry>The media bus format code, as defined in
+	    <xref linkend="v4l2-mbus-format" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>width</structfield></entry>
+	    <entry>Frame width, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>height</structfield></entry>
+	    <entry>Frame height, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-fract;</entry>
+	    <entry><structfield>interval</structfield></entry>
+	    <entry>Period, in seconds, between consecutive video frames.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers must
+	    set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-subdev-frame-interval-enum;
+	  <structfield>pad</structfield> references a non-existing pad, one of
+	  the <structfield>code</structfield>, <structfield>width</structfield>
+	  or <structfield>height</structfield> fields are invalid for the given
+	  pad or the <structfield>index</structfield> field is out of bounds.
+	  </para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-frame-size.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,154 @@
+<refentry id="vidioc-subdev-enum-frame-size">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_FRAME_SIZE</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</refname>
+    <refpurpose>Enumerate media bus frame sizes</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_subdev_frame_size_enum *
+	<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental">experimental</link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>This ioctl allows applications to enumerate all frame sizes
+    supported by a sub-device on the given pad for the given media bus format.
+    Supported formats can be retrieved with the &VIDIOC-SUBDEV-ENUM-MBUS-CODE;
+    ioctl.</para>
+
+    <para>To enumerate frame sizes applications initialize the
+    <structfield>pad</structfield>, <structfield>code</structfield> and
+    <structfield>index</structfield> fields of the
+    &v4l2-subdev-mbus-code-enum; and call the
+    <constant>VIDIOC_SUBDEV_ENUM_FRAME_SIZE</constant> ioctl with a pointer to
+    the structure. Drivers fill the minimum and maximum frame sizes or return
+    an &EINVAL; if one of the input parameters is invalid.</para>
+
+    <para>Sub-devices that only support discrete frame sizes (such as most
+    sensors) will return one or more frame sizes with identical minimum and
+    maximum values.</para>
+
+    <para>Not all possible sizes in given [minimum, maximum] ranges need to be
+    supported. For instance, a scaler that uses a fixed-point scaling ratio
+    might not be able to produce every frame size between the minimum and
+    maximum values. Applications must use the &VIDIOC-SUBDEV-S-FMT; ioctl to
+    try the sub-device for an exact supported frame size.</para>
+
+    <para>Available frame sizes may depend on the current 'try' formats at other
+    pads of the sub-device, as well as on the current active links and the
+    current values of V4L2 controls. See &VIDIOC-SUBDEV-G-FMT; for more
+    information about try formats.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-frame-size-enum">
+      <title>struct <structname>v4l2_subdev_frame_size_enum</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>Number of the format in the enumeration, set by the
+	    application.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>code</structfield></entry>
+	    <entry>The media bus format code, as defined in
+	    <xref linkend="v4l2-mbus-format" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>min_width</structfield></entry>
+	    <entry>Minimum frame width, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>max_width</structfield></entry>
+	    <entry>Maximum frame width, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>min_height</structfield></entry>
+	    <entry>Minimum frame height, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>max_height</structfield></entry>
+	    <entry>Maximum frame height, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers must
+	    set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-subdev-frame-size-enum; <structfield>pad</structfield>
+	  references a non-existing pad, the <structfield>code</structfield> is
+	  invalid for the given pad or the <structfield>index</structfield>
+	  field is out of bounds.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-enum-mbus-code.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,119 @@
+<refentry id="vidioc-subdev-enum-mbus-code">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_ENUM_MBUS_CODE</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_ENUM_MBUS_CODE</refname>
+    <refpurpose>Enumerate media bus formats</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_subdev_mbus_code_enum *
+	<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_SUBDEV_ENUM_MBUS_CODE</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental">experimental</link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>To enumerate media bus formats available at a given sub-device pad
+    applications initialize the <structfield>pad</structfield> and
+    <structfield>index</structfield> fields of &v4l2-subdev-mbus-code-enum; and
+    call the <constant>VIDIOC_SUBDEV_ENUM_MBUS_CODE</constant> ioctl with a
+    pointer to this structure. Drivers fill the rest of the structure or return
+    an &EINVAL; if either the <structfield>pad</structfield> or
+    <structfield>index</structfield> are invalid. All media bus formats are
+    enumerable by beginning at index zero and incrementing by one until
+    <errorcode>EINVAL</errorcode> is returned.</para>
+
+    <para>Available media bus formats may depend on the current 'try' formats
+    at other pads of the sub-device, as well as on the current active links. See
+    &VIDIOC-SUBDEV-G-FMT; for more information about the try formats.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-mbus-code-enum">
+      <title>struct <structname>v4l2_subdev_mbus_code_enum</structname></title>
+      <tgroup cols="3">
+	&cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>index</structfield></entry>
+	    <entry>Number of the format in the enumeration, set by the
+	    application.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>code</structfield></entry>
+	    <entry>The media bus format code, as defined in
+	    <xref linkend="v4l2-mbus-format" />.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers must
+	    set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-subdev-mbus-code-enum; <structfield>pad</structfield>
+	  references a non-existing pad, or the <structfield>index</structfield>
+	  field is out of bounds.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-crop.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,155 @@
+<refentry id="vidioc-subdev-g-crop">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_G_CROP</refname>
+    <refname>VIDIOC_SUBDEV_S_CROP</refname>
+    <refpurpose>Get or set the crop rectangle on a subdev pad</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_subdev_crop *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>const struct v4l2_subdev_crop *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_SUBDEV_G_CROP, VIDIOC_SUBDEV_S_CROP</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental">experimental</link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>To retrieve the current crop rectangle applications set the
+    <structfield>pad</structfield> field of a &v4l2-subdev-crop; to the
+    desired pad number as reported by the media API and the
+    <structfield>which</structfield> field to
+    <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. They then call the
+    <constant>VIDIOC_SUBDEV_G_CROP</constant> ioctl with a pointer to this
+    structure. The driver fills the members of the <structfield>rect</structfield>
+    field or returns &EINVAL; if the input arguments are invalid, or if cropping
+    is not supported on the given pad.</para>
+
+    <para>To change the current crop rectangle applications set both the
+    <structfield>pad</structfield> and <structfield>which</structfield> fields
+    and all members of the <structfield>rect</structfield> field. They then call
+    the <constant>VIDIOC_SUBDEV_S_CROP</constant> ioctl with a pointer to this
+    structure. The driver verifies the requested crop rectangle, adjusts it
+    based on the hardware capabilities and configures the device. Upon return
+    the &v4l2-subdev-crop; contains the current format as would be returned
+    by a <constant>VIDIOC_SUBDEV_G_CROP</constant> call.</para>
+
+    <para>Applications can query the device capabilities by setting the
+    <structfield>which</structfield> to
+    <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' crop
+    rectangles are not applied to the device by the driver, but are mangled
+    exactly as active crop rectangles and stored in the sub-device file handle.
+    Two applications querying the same sub-device would thus not interact with
+    each other.</para>
+
+    <para>Drivers must not return an error solely because the requested crop
+    rectangle doesn't match the device capabilities. They must instead modify
+    the rectangle to match what the hardware can provide. The modified format
+    should be as close as possible to the original request.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-crop">
+      <title>struct <structname>v4l2_subdev_crop</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media framework.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>which</structfield></entry>
+	    <entry>Crop rectangle to get or set, from
+	    &v4l2-subdev-format-whence;.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-rect;</entry>
+	    <entry><structfield>rect</structfield></entry>
+	    <entry>Crop rectangle boundaries, in pixels.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers must
+	    set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The crop rectangle can't be changed because the pad is currently
+	  busy. This can be caused, for instance, by an active video stream on
+	  the pad. The ioctl must not be retried without performing another
+	  action to fix the problem first. Only returned by
+	  <constant>VIDIOC_SUBDEV_S_CROP</constant></para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-subdev-crop; <structfield>pad</structfield>
+	  references a non-existing pad, the <structfield>which</structfield>
+	  field references a non-existing format, or cropping is not supported
+	  on the given subdev pad.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-fmt.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,180 @@
+<refentry id="vidioc-subdev-g-fmt">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_G_FMT</refname>
+    <refname>VIDIOC_SUBDEV_S_FMT</refname>
+    <refpurpose>Get or set the data format on a subdev pad</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_subdev_format *<parameter>argp</parameter>
+	</paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_SUBDEV_G_FMT, VIDIOC_SUBDEV_S_FMT</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental">experimental</link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>These ioctls are used to negotiate the frame format at specific
+    subdev pads in the image pipeline.</para>
+
+    <para>To retrieve the current format applications set the
+    <structfield>pad</structfield> field of a &v4l2-subdev-format; to the
+    desired pad number as reported by the media API and the
+    <structfield>which</structfield> field to
+    <constant>V4L2_SUBDEV_FORMAT_ACTIVE</constant>. When they call the
+    <constant>VIDIOC_SUBDEV_G_FMT</constant> ioctl with a pointer to this
+    structure the driver fills the members of the <structfield>format</structfield>
+    field.</para>
+
+    <para>To change the current format applications set both the
+    <structfield>pad</structfield> and <structfield>which</structfield> fields
+    and all members of the <structfield>format</structfield> field. When they
+    call the <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl with a pointer to this
+    structure the driver verifies the requested format, adjusts it based on the
+    hardware capabilities and configures the device. Upon return the
+    &v4l2-subdev-format; contains the current format as would be returned by a
+    <constant>VIDIOC_SUBDEV_G_FMT</constant> call.</para>
+
+    <para>Applications can query the device capabilities by setting the
+    <structfield>which</structfield> to
+    <constant>V4L2_SUBDEV_FORMAT_TRY</constant>. When set, 'try' formats are not
+    applied to the device by the driver, but are changed exactly as active
+    formats and stored in the sub-device file handle. Two applications querying
+    the same sub-device would thus not interact with each other.</para>
+
+    <para>For instance, to try a format at the output pad of a sub-device,
+    applications would first set the try format at the sub-device input with the
+    <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl. They would then either
+    retrieve the default format at the output pad with the
+    <constant>VIDIOC_SUBDEV_G_FMT</constant> ioctl, or set the desired output
+    pad format with the <constant>VIDIOC_SUBDEV_S_FMT</constant> ioctl and check
+    the returned value.</para>
+
+    <para>Try formats do not depend on active formats, but can depend on the
+    current links configuration or sub-device controls value. For instance, a
+    low-pass noise filter might crop pixels at the frame boundaries, modifying
+    its output frame size.</para>
+
+    <para>Drivers must not return an error solely because the requested format
+    doesn't match the device capabilities. They must instead modify the format
+    to match what the hardware can provide. The modified format should be as
+    close as possible to the original request.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-format">
+      <title>struct <structname>v4l2_subdev_format</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>which</structfield></entry>
+	    <entry>Format to modified, from &v4l2-subdev-format-whence;.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-mbus-framefmt;</entry>
+	    <entry><structfield>format</structfield></entry>
+	    <entry>Definition of an image format, see <xref
+	    linkend="v4l2-mbus-framefmt" /> for details.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[8]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers must
+	    set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-format-whence">
+      <title>enum <structname>v4l2_subdev_format_whence</structname></title>
+      <tgroup cols="3">
+        &cs-def;
+	<tbody valign="top">
+	  <row>
+	    <entry>V4L2_SUBDEV_FORMAT_TRY</entry>
+	    <entry>0</entry>
+	    <entry>Try formats, used for querying device capabilities.</entry>
+	  </row>
+	  <row>
+	    <entry>V4L2_SUBDEV_FORMAT_ACTIVE</entry>
+	    <entry>1</entry>
+	    <entry>Active formats, applied to the hardware.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The format can't be changed because the pad is currently busy.
+	  This can be caused, for instance, by an active video stream on the
+	  pad. The ioctl must not be retried without performing another action
+	  to fix the problem first. Only returned by
+	  <constant>VIDIOC_SUBDEV_S_FMT</constant></para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-subdev-format; <structfield>pad</structfield>
+	  references a non-existing pad, or the <structfield>which</structfield>
+	  field references a non-existing format.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml
--- linux-libre-2.6.38-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/v4l/vidioc-subdev-g-frame-interval.xml	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,141 @@
+<refentry id="vidioc-subdev-g-frame-interval">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_G_FRAME_INTERVAL</refname>
+    <refname>VIDIOC_SUBDEV_S_FRAME_INTERVAL</refname>
+    <refpurpose>Get or set the frame interval on a subdev pad</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+	<funcdef>int <function>ioctl</function></funcdef>
+	<paramdef>int <parameter>fd</parameter></paramdef>
+	<paramdef>int <parameter>request</parameter></paramdef>
+	<paramdef>struct v4l2_subdev_frame_interval *<parameter>argp</parameter>
+	</paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+	<term><parameter>fd</parameter></term>
+	<listitem>
+	  <para>&fd;</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>request</parameter></term>
+	<listitem>
+	  <para>VIDIOC_SUBDEV_G_FRAME_INTERVAL, VIDIOC_SUBDEV_S_FRAME_INTERVAL</para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><parameter>argp</parameter></term>
+	<listitem>
+	  <para></para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+
+    <note>
+      <title>Experimental</title>
+      <para>This is an <link linkend="experimental">experimental</link>
+      interface and may change in the future.</para>
+    </note>
+
+    <para>These ioctls are used to get and set the frame interval at specific
+    subdev pads in the image pipeline. The frame interval only makes sense for
+    sub-devices that can control the frame period on their own. This includes,
+    for instance, image sensors and TV tuners. Sub-devices that don't support
+    frame intervals must not implement these ioctls.</para>
+
+    <para>To retrieve the current frame interval applications set the
+    <structfield>pad</structfield> field of a &v4l2-subdev-frame-interval; to
+    the desired pad number as reported by the media controller API. When they
+    call the <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> ioctl with a
+    pointer to this structure the driver fills the members of the
+    <structfield>interval</structfield> field.</para>
+
+    <para>To change the current frame interval applications set both the
+    <structfield>pad</structfield> field and all members of the
+    <structfield>interval</structfield> field. When they call the
+    <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant> ioctl with a pointer to
+    this structure the driver verifies the requested interval, adjusts it based
+    on the hardware capabilities and configures the device. Upon return the
+    &v4l2-subdev-frame-interval; contains the current frame interval as would be
+    returned by a <constant>VIDIOC_SUBDEV_G_FRAME_INTERVAL</constant> call.
+    </para>
+
+    <para>Drivers must not return an error solely because the requested interval
+    doesn't match the device capabilities. They must instead modify the interval
+    to match what the hardware can provide. The modified interval should be as
+    close as possible to the original request.</para>
+
+    <para>Sub-devices that support the frame interval ioctls should implement
+    them on a single pad only. Their behaviour when supported on multiple pads
+    of the same sub-device is not defined.</para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-frame-interval">
+      <title>struct <structname>v4l2_subdev_frame_interval</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+	<tbody valign="top">
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>pad</structfield></entry>
+	    <entry>Pad number as reported by the media controller API.</entry>
+	  </row>
+	  <row>
+	    <entry>&v4l2-fract;</entry>
+	    <entry><structfield>interval</structfield></entry>
+	    <entry>Period, in seconds, between consecutive video frames.</entry>
+	  </row>
+	  <row>
+	    <entry>__u32</entry>
+	    <entry><structfield>reserved</structfield>[9]</entry>
+	    <entry>Reserved for future extensions. Applications and drivers must
+	    set the array to zero.</entry>
+	  </row>
+	</tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+	<term><errorcode>EBUSY</errorcode></term>
+	<listitem>
+	  <para>The frame interval can't be changed because the pad is currently
+	  busy. This can be caused, for instance, by an active video stream on
+	  the pad. The ioctl must not be retried without performing another
+	  action to fix the problem first. Only returned by
+	  <constant>VIDIOC_SUBDEV_S_FRAME_INTERVAL</constant></para>
+	</listitem>
+      </varlistentry>
+      <varlistentry>
+	<term><errorcode>EINVAL</errorcode></term>
+	<listitem>
+	  <para>The &v4l2-subdev-frame-interval; <structfield>pad</structfield>
+	  references a non-existing pad, or the pad doesn't support frame
+	  intervals.</para>
+	</listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
diff -druN linux-libre-2.6.38-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl linux-libre-2.6.39-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl
--- linux-libre-2.6.38-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/DocBook/writing-an-alsa-driver.tmpl	2011-05-19 00:06:34.000000000 -0400
@@ -4784,7 +4784,7 @@
         FM registers can be directly accessed through the direct-FM API,
       defined in <filename>&lt;sound/asound_fm.h&gt;</filename>. In
       ALSA native mode, FM registers are accessed through
-      the Hardware-Dependant Device direct-FM extension API, whereas in
+      the Hardware-Dependent Device direct-FM extension API, whereas in
       OSS compatible mode, FM registers can be accessed with the OSS
       direct-FM compatible API in <filename>/dev/dmfmX</filename> device. 
       </para>
diff -druN linux-libre-2.6.38-gnu/Documentation/dvb/ci.txt linux-libre-2.6.39-gnu/Documentation/dvb/ci.txt
--- linux-libre-2.6.38-gnu/Documentation/dvb/ci.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/dvb/ci.txt	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,7 @@
 
 * CI modules that are supported
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The CI module support is largely dependant upon the firmware on the cards
+The CI module support is largely dependent upon the firmware on the cards
 Some cards do support almost all of the available CI modules. There is
 nothing much that can be done in order to make additional CI modules
 working with these cards.
diff -druN linux-libre-2.6.38-gnu/Documentation/dvb/faq.txt linux-libre-2.6.39-gnu/Documentation/dvb/faq.txt
--- linux-libre-2.6.38-gnu/Documentation/dvb/faq.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/dvb/faq.txt	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 5. The dvb_net device doesn't give me any packets at all
 
 	Run tcpdump on the dvb0_0 interface. This sets the interface
-	into promiscous mode so it accepts any packets from the PID
+	into promiscuous mode so it accepts any packets from the PID
 	you have configured with the dvbnet utility. Check if there
 	are any packets with the IP addr and MAC addr you have
 	configured with ifconfig.
diff -druN linux-libre-2.6.38-gnu/Documentation/dvb/README.dvb-usb linux-libre-2.6.39-gnu/Documentation/dvb/README.dvb-usb
--- linux-libre-2.6.38-gnu/Documentation/dvb/README.dvb-usb	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/dvb/README.dvb-usb	2011-05-19 00:06:34.000000000 -0400
@@ -138,7 +138,7 @@
 in the device).
 
 If you want to enable debug output, you have to load the driver manually and
-from withing the dvb-kernel cvs repository.
+from within the dvb-kernel cvs repository.
 
 first have a look, which debug level are available:
 
diff -druN linux-libre-2.6.38-gnu/Documentation/dvb/udev.txt linux-libre-2.6.39-gnu/Documentation/dvb/udev.txt
--- linux-libre-2.6.38-gnu/Documentation/dvb/udev.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/dvb/udev.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 The DVB subsystem currently registers to the sysfs subsystem using the
 "class_simple" interface.
 
-This means that only the basic informations like module loading parameters
+This means that only the basic information like module loading parameters
 are presented through sysfs. Other things that might be interesting are
 currently *not* available.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/dynamic-debug-howto.txt linux-libre-2.6.39-gnu/Documentation/dynamic-debug-howto.txt
--- linux-libre-2.6.38-gnu/Documentation/dynamic-debug-howto.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/dynamic-debug-howto.txt	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 
 Dynamic debug is designed to allow you to dynamically enable/disable kernel
 code to obtain additional kernel information. Currently, if
-CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_debug() calls can be
+CONFIG_DYNAMIC_DEBUG is set, then all pr_debug()/dev_dbg() calls can be
 dynamically enabled per-callsite.
 
 Dynamic debug has even more useful features:
@@ -26,7 +26,7 @@
 Controlling dynamic debug Behaviour
 ===================================
 
-The behaviour of pr_debug()/dev_debug()s are controlled via writing to a
+The behaviour of pr_debug()/dev_dbg()s are controlled via writing to a
 control file in the 'debugfs' filesystem. Thus, you must first mount the debugfs
 filesystem, in order to make use of this feature. Subsequently, we refer to the
 control file as: <debugfs>/dynamic_debug/control. For example, if you want to
@@ -205,12 +205,20 @@
 
 The flags are:
 
+f
+    Include the function name in the printed message
+l
+    Include line number in the printed message
+m
+    Include module name in the printed message
 p
     Causes a printk() message to be emitted to dmesg
+t
+    Include thread ID in messages not generated from interrupt context
 
-Note the regexp ^[-+=][scp]+$ matches a flags specification.
+Note the regexp ^[-+=][flmpt]+$ matches a flags specification.
 Note also that there is no convenient syntax to remove all
-the flags at once, you need to use "-psc".
+the flags at once, you need to use "-flmpt".
 
 
 Debug messages during boot process
diff -druN linux-libre-2.6.38-gnu/Documentation/edac.txt linux-libre-2.6.39-gnu/Documentation/edac.txt
--- linux-libre-2.6.38-gnu/Documentation/edac.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/edac.txt	2011-05-19 00:06:34.000000000 -0400
@@ -311,7 +311,7 @@
 	'ce_noinfo_count'
 
 	This attribute file displays the number of CEs that
-	have occurred wherewith no informations as to which DIMM slot
+	have occurred wherewith no information as to which DIMM slot
 	is having errors. Memory is handicapped, but operational,
 	yet no information is available to indicate which slot
 	the failing memory is in. This count field should be also
@@ -741,7 +741,7 @@
    As EDAC API maps the minimum unity is csrows, the driver sequencially
    maps channel/dimm into different csrows.
 
-   For example, suposing the following layout:
+   For example, supposing the following layout:
 	Ch0 phy rd0, wr0 (0x063f4031): 2 ranks, UDIMMs
 	  dimm 0 1024 Mb offset: 0, bank: 8, rank: 1, row: 0x4000, col: 0x400
 	  dimm 1 1024 Mb offset: 4, bank: 8, rank: 1, row: 0x4000, col: 0x400
diff -druN linux-libre-2.6.38-gnu/Documentation/eisa.txt linux-libre-2.6.39-gnu/Documentation/eisa.txt
--- linux-libre-2.6.38-gnu/Documentation/eisa.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/eisa.txt	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,7 @@
 
 id_table	: an array of NULL terminated EISA id strings,
 		  followed by an empty string. Each string can
-		  optionally be paired with a driver-dependant value
+		  optionally be paired with a driver-dependent value
 		  (driver_data).
 
 driver		: a generic driver, such as described in
diff -druN linux-libre-2.6.38-gnu/Documentation/fb/sm501.txt linux-libre-2.6.39-gnu/Documentation/fb/sm501.txt
--- linux-libre-2.6.38-gnu/Documentation/fb/sm501.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/fb/sm501.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,10 @@
+Configuration:
+
+You can pass the following kernel command line options to sm501 videoframebuffer:
+
+	sm501fb.bpp=	SM501 Display driver:
+			Specifiy bits-per-pixel if not specified by 'mode'
+
+	sm501fb.mode=	SM501 Display driver:
+			Specify resolution as
+			"<xres>x<yres>[-<bpp>][@<refresh>]"
diff -druN linux-libre-2.6.38-gnu/Documentation/fb/viafb.txt linux-libre-2.6.39-gnu/Documentation/fb/viafb.txt
--- linux-libre-2.6.38-gnu/Documentation/fb/viafb.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/fb/viafb.txt	2011-05-19 00:06:34.000000000 -0400
@@ -204,7 +204,7 @@
 
     supported_output_devices
 
-        This read-only file contains a full ',' seperated list containing all
+        This read-only file contains a full ',' separated list containing all
         output devices that could be available on your platform. It is likely
         that not all of those have a connector on your hardware but it should
         provide a good starting point to figure out which of those names match
@@ -225,7 +225,7 @@
         This can happen for example if only one (the other) iga is used.
         Writing to these files allows adjusting the output devices during
         runtime. One can add new devices, remove existing ones or switch
-        between igas. Essentially you can write a ',' seperated list of device
+        between igas. Essentially you can write a ',' separated list of device
         names (or a single one) in the same format as the output to those
         files. You can add a '+' or '-' as a prefix allowing simple addition
         and removal of devices. So a prefix '+' adds the devices from your list
diff -druN linux-libre-2.6.38-gnu/Documentation/feature-removal-schedule.txt linux-libre-2.6.39-gnu/Documentation/feature-removal-schedule.txt
--- linux-libre-2.6.38-gnu/Documentation/feature-removal-schedule.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/feature-removal-schedule.txt	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,17 @@
 
 ---------------------------
 
+What:	AR9170USB
+When:	2.6.40
+
+Why:	This driver is deprecated and the firmware is no longer
+	maintained. The replacement driver "carl9170" has been
+	around for a while, so the devices are still supported.
+
+Who:	Christian Lamparter <chunkeey@googlemail.com>
+
+---------------------------
+
 What:	IRQF_SAMPLE_RANDOM
 Check:	IRQF_SAMPLE_RANDOM
 When:	July 2009
@@ -97,42 +108,6 @@
 
 ---------------------------
 
-What:	Video4Linux obsolete drivers using V4L1 API
-When:	kernel 2.6.39
-Files:	drivers/staging/se401/* drivers/staging/usbvideo/*
-Check:	drivers/staging/se401/se401.c drivers/staging/usbvideo/usbvideo.c
-Why:	There are some drivers still using V4L1 API, despite all efforts we've done
-	to migrate. Those drivers are for obsolete hardware that the old maintainer
-	didn't care (or not have the hardware anymore), and that no other developer
-	could find any hardware to buy. They probably have no practical usage today,
-	and people with such old hardware could probably keep using an older version
-	of the kernel. Those drivers will be moved to staging on 2.6.38 and, if nobody
-	cares enough to port and test them with V4L2 API, they'll be removed on 2.6.39.
-Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
-
----------------------------
-
-What:	Video4Linux: Remove obsolete ioctl's
-When:	kernel 2.6.39
-Files:	include/media/videodev2.h
-Why:	Some ioctl's were defined wrong on 2.6.2 and 2.6.6, using the wrong
-	type of R/W arguments. They were fixed, but the old ioctl names are
-	still there, maintained to avoid breaking binary compatibility:
-	  #define VIDIOC_OVERLAY_OLD   	_IOWR('V', 14, int)
-	  #define VIDIOC_S_PARM_OLD	_IOW('V', 22, struct v4l2_streamparm)
-	  #define VIDIOC_S_CTRL_OLD	_IOW('V', 28, struct v4l2_control)
-	  #define VIDIOC_G_AUDIO_OLD	_IOWR('V', 33, struct v4l2_audio)
-	  #define VIDIOC_G_AUDOUT_OLD	_IOWR('V', 49, struct v4l2_audioout)
-	  #define VIDIOC_CROPCAP_OLD	_IOR('V', 58, struct v4l2_cropcap)
-	There's no sense on preserving those forever, as it is very doubtful
-	that someone would try to use a such old binary with a modern kernel.
-	Removing them will allow us to remove some magic done at the V4L ioctl
-	handler.
-
-Who:	Mauro Carvalho Chehab <mchehab@infradead.org>
-
----------------------------
-
 What:	sys_sysctl
 When:	September 2010
 Option: CONFIG_SYSCTL_SYSCALL
@@ -259,14 +234,6 @@
 
 ---------------------------
 
-What:	/proc/acpi/button
-When:	August 2007
-Why:	/proc/acpi/button has been replaced by events to the input layer
-	since 2.6.20.
-Who:	Len Brown <len.brown@intel.com>
-
----------------------------
-
 What:	/proc/acpi/event
 When:	February 2008
 Why:	/proc/acpi/event has been replaced by events via the input layer
@@ -420,26 +387,6 @@
 
 ----------------------------
 
-What:	Support for lcd_switch and display_get in asus-laptop driver
-When:	March 2010
-Why:	These two features use non-standard interfaces. There are the
-	only features that really need multiple path to guess what's
-	the right method name on a specific laptop.
-
-	Removing them will allow to remove a lot of code an significantly
-	clean the drivers.
-
-	This will affect the backlight code which won't be able to know
-	if the backlight is on or off. The platform display file will also be
-	write only (like the one in eeepc-laptop).
-
-	This should'nt affect a lot of user because they usually know
-	when their display is on or off.
-
-Who:	Corentin Chary <corentin.chary@gmail.com>
-
-----------------------------
-
 What:	sysfs-class-rfkill state file
 When:	Feb 2014
 Files:	net/rfkill/core.c
@@ -574,16 +521,6 @@
 
 ----------------------------
 
-What:	i2c_adapter.id
-When:	June 2011
-Why:	This field is deprecated. I2C device drivers shouldn't change their
-	behavior based on the underlying I2C adapter. Instead, the I2C
-	adapter driver should instantiate the I2C devices and provide the
-	needed platform-specific information.
-Who:	Jean Delvare <khali@linux-fr.org>
-
-----------------------------
-
 What:	cancel_rearming_delayed_work[queue]()
 When:	2.6.39
 
@@ -604,6 +541,13 @@
 
 ----------------------------
 
+What:	xt_connlimit rev 0
+When:	2012
+Who:	Jan Engelhardt <jengelh@medozas.de>
+Files:	net/netfilter/xt_connlimit.c
+
+----------------------------
+
 What:	noswapaccount kernel command line parameter
 When:	2.6.40
 Why:	The original implementation of memsw feature enabled by
@@ -619,3 +563,20 @@
 Who:	Michal Hocko <mhocko@suse.cz>
 
 ----------------------------
+
+What:	ipt_addrtype match include file
+When:	2012
+Why:	superseded by xt_addrtype
+Who:	Florian Westphal <fw@strlen.de>
+Files:	include/linux/netfilter_ipv4/ipt_addrtype.h
+
+----------------------------
+
+What:	i2c_driver.attach_adapter
+	i2c_driver.detach_adapter
+When:	September 2011
+Why:	These legacy callbacks should no longer be used as i2c-core offers
+	a variety of preferable alternative ways to instantiate I2C devices.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+----------------------------
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/adfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/adfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/adfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/adfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,9 @@
 		will be nnn.  Default 0700.
   othmask=nnn	The permission mask for ADFS 'other' permissions
 		will be nnn.  Default 0077.
+  ftsuffix=n	When ftsuffix=0, no file type suffix will be applied.
+		When ftsuffix=1, a hexadecimal suffix corresponding to
+		the RISC OS file type will be added.  Default 0.
 
 Mapping of ADFS permissions to Linux permissions
 ------------------------------------------------
@@ -55,3 +58,18 @@
 
   You can therefore tailor the permission translation to whatever you
   desire the permissions should be under Linux.
+
+RISC OS file type suffix
+------------------------
+
+  RISC OS file types are stored in bits 19..8 of the file load address.
+
+  To enable non-RISC OS systems to be used to store files without losing
+  file type information, a file naming convention was devised (initially
+  for use with NFS) such that a hexadecimal suffix of the form ,xyz
+  denoted the file type: e.g. BasicFile,ffb is a BASIC (0xffb) file.  This
+  naming convention is now also used by RISC OS emulators such as RPCEmu.
+
+  Mounting an ADFS disc with option ftsuffix=1 will cause appropriate file
+  type suffixes to be appended to file names read from a directory.  If the
+  ftsuffix option is zero or omitted, no file type suffixes will be added.
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/autofs4-mount-control.txt linux-libre-2.6.39-gnu/Documentation/filesystems/autofs4-mount-control.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/autofs4-mount-control.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/autofs4-mount-control.txt	2011-05-19 00:06:34.000000000 -0400
@@ -309,7 +309,7 @@
 AUTOFS_DEV_IOCTL_TIMEOUT_CMD
 ----------------------------
 
-Set the expire timeout for mounts withing an autofs mount point.
+Set the expire timeout for mounts within an autofs mount point.
 
 The call requires an initialized struct autofs_dev_ioctl with the
 ioctlfd field set to the descriptor obtained from the open call.
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/caching/netfs-api.txt linux-libre-2.6.39-gnu/Documentation/filesystems/caching/netfs-api.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/caching/netfs-api.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/caching/netfs-api.txt	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 the tree.  The netfs can even mix indices and data files at the same level, but
 it's not recommended.
 
-Each index entry consists of a key of indeterminate length plus some auxilliary
+Each index entry consists of a key of indeterminate length plus some auxiliary
 data, also of indeterminate length.
 
 There are some limits on indices:
@@ -203,23 +203,23 @@
 
      If the function is absent, a file size of 0 is assumed.
 
- (6) A function to retrieve auxilliary data from the netfs [optional].
+ (6) A function to retrieve auxiliary data from the netfs [optional].
 
      This function will be called with the netfs data that was passed to the
-     cookie acquisition function and the maximum length of auxilliary data that
-     it may provide.  It should write the auxilliary data into the given buffer
+     cookie acquisition function and the maximum length of auxiliary data that
+     it may provide.  It should write the auxiliary data into the given buffer
      and return the quantity it wrote.
 
-     If this function is absent, the auxilliary data length will be set to 0.
+     If this function is absent, the auxiliary data length will be set to 0.
 
-     The length of the auxilliary data buffer may be dependent on the key
+     The length of the auxiliary data buffer may be dependent on the key
      length.  A netfs mustn't rely on being able to provide more than 400 bytes
      for both.
 
- (7) A function to check the auxilliary data [optional].
+ (7) A function to check the auxiliary data [optional].
 
      This function will be called to check that a match found in the cache for
-     this object is valid.  For instance with AFS it could check the auxilliary
+     this object is valid.  For instance with AFS it could check the auxiliary
      data against the data version number returned by the server to determine
      whether the index entry in a cache is still valid.
 
@@ -232,7 +232,7 @@
 	(*) FSCACHE_CHECKAUX_NEEDS_UPDATE	- the entry requires update
 	(*) FSCACHE_CHECKAUX_OBSOLETE		- the entry should be deleted
 
-     This function can also be used to extract data from the auxilliary data in
+     This function can also be used to extract data from the auxiliary data in
      the cache and copy it into the netfs's structures.
 
  (8) A pair of functions to manage contexts for the completion callback
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/configfs/configfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/configfs/configfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/configfs/configfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/configfs/configfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -409,7 +409,7 @@
 rmdir(2).  They also are not considered when rmdir(2) on the parent
 group is checking for children.
 
-[Dependant Subsystems]
+[Dependent Subsystems]
 
 Sometimes other drivers depend on particular configfs items.  For
 example, ocfs2 mounts depend on a heartbeat region item.  If that
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/exofs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/exofs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/exofs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/exofs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -104,7 +104,15 @@
     exofs specific options: Options are separated by commas (,)
 		pid=<integer> - The partition number to mount/create as
                                 container of the filesystem.
-                                This option is mandatory.
+                                This option is mandatory. integer can be
+                                Hex by pre-pending an 0x to the number.
+		osdname=<id>  - Mount by a device's osdname.
+                                osdname is usually a 36 character uuid of the
+                                form "d2683732-c906-4ee1-9dbd-c10c27bb40df".
+                                It is one of the device's uuid specified in the
+                                mkfs.exofs format command.
+                                If this option is specified then the /dev/osdX
+                                above can be empty and is ignored.
                 to=<integer>  - Timeout in ticks for a single command.
                                 default is (60 * HZ) [for debugging only]
 
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/ext4.txt linux-libre-2.6.39-gnu/Documentation/filesystems/ext4.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/ext4.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/ext4.txt	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 * Inode allocation using large virtual block groups via flex_bg
 * delayed allocation
 * large block (up to pagesize) support
-* efficent new ordered mode in JBD2 and ext4(avoid using buffer head to force
+* efficient new ordered mode in JBD2 and ext4(avoid using buffer head to force
   the ordering)
 
 [1] Filesystems with a block size of 1k may see a limit imposed by the
@@ -106,7 +106,7 @@
 2.2 Candidate features for future inclusion
 
 * Online defrag (patches available but not well tested)
-* reduced mke2fs time via lazy itable initialization in conjuction with
+* reduced mke2fs time via lazy itable initialization in conjunction with
   the uninit_bg feature (capability to do this is available in e2fsprogs
   but a kernel thread to do lazy zeroing of unused inode table blocks
   after filesystem is first mounted is required for safety)
@@ -367,12 +367,47 @@
 			minimizes the impact on the systme performance
 			while file system's inode table is being initialized.
 
-discard		Controls whether ext4 should issue discard/TRIM
+discard			Controls whether ext4 should issue discard/TRIM
 nodiscard(*)		commands to the underlying block device when
 			blocks are freed.  This is useful for SSD devices
 			and sparse/thinly-provisioned LUNs, but it is off
 			by default until sufficient testing has been done.
 
+nouid32			Disables 32-bit UIDs and GIDs.  This is for
+			interoperability  with  older kernels which only
+			store and expect 16-bit values.
+
+resize			Allows to resize filesystem to the end of the last
+			existing block group, further resize has to be done
+			with resize2fs either online, or offline. It can be
+			used only with conjunction with remount.
+
+block_validity		This options allows to enables/disables the in-kernel
+noblock_validity	facility for tracking filesystem metadata blocks
+			within internal data structures. This allows multi-
+			block allocator and other routines to quickly locate
+			extents which might overlap with filesystem metadata
+			blocks. This option is intended for debugging
+			purposes and since it negatively affects the
+			performance, it is off by default.
+
+dioread_lock		Controls whether or not ext4 should use the DIO read
+dioread_nolock		locking. If the dioread_nolock option is specified
+			ext4 will allocate uninitialized extent before buffer
+			write and convert the extent to initialized after IO
+			completes. This approach allows ext4 code to avoid
+			using inode mutex, which improves scalability on high
+			speed storages. However this does not work with nobh
+			option and the mount will fail. Nor does it work with
+			data journaling and dioread_nolock option will be
+			ignored with kernel warning. Note that dioread_nolock
+			code path is only used for extent-based files.
+			Because of the restrictions this options comprises
+			it is off by default (e.g. dioread_lock).
+
+i_version		Enable 64-bit inode version support. This option is
+			off by default.
+
 Data Mode
 =========
 There are 3 different data modes:
@@ -400,6 +435,176 @@
 outperforms all others modes.  Currently ext4 does not have delayed
 allocation support if this data journalling mode is selected.
 
+/proc entries
+=============
+
+Information about mounted ext4 file systems can be found in
+/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 below.
+
+Files in /proc/fs/ext4/<devname>
+..............................................................................
+ File            Content
+ mb_groups       details of multiblock allocator buddy cache of free blocks
+..............................................................................
+
+/sys entries
+============
+
+Information about mounted ext4 file systems can be found in
+/sys/fs/ext4.  Each mounted filesystem will have a directory in
+/sys/fs/ext4 based on its device name (i.e., /sys/fs/ext4/hdc or
+/sys/fs/ext4/dm-0).   The files in each per-device directory are shown
+in table below.
+
+Files in /sys/fs/ext4/<devname>
+(see also Documentation/ABI/testing/sysfs-fs-ext4)
+..............................................................................
+ File                         Content
+
+ delayed_allocation_blocks    This file is read-only and shows the number of
+                              blocks that are dirty in the page cache, but
+                              which do not have their location in the
+                              filesystem allocated yet.
+
+ inode_goal                   Tuning parameter which (if non-zero) controls
+                              the goal inode used by the inode allocator in
+                              preference to all other allocation heuristics.
+                              This is intended for debugging use only, and
+                              should be 0 on production systems.
+
+ inode_readahead_blks         Tuning parameter which controls the maximum
+                              number of inode table blocks that ext4's inode
+                              table readahead algorithm will pre-read into
+                              the buffer cache
+
+ lifetime_write_kbytes        This file is read-only and shows the number of
+                              kilobytes of data that have been written to this
+                              filesystem since it was created.
+
+ max_writeback_mb_bump        The maximum number of megabytes the writeback
+                              code will try to write out before move on to
+                              another inode.
+
+ mb_group_prealloc            The multiblock allocator will round up allocation
+                              requests to a multiple of this tuning parameter if
+                              the stripe size is not set in the ext4 superblock
+
+ mb_max_to_scan               The maximum number of extents the multiblock
+                              allocator will search to find the best extent
+
+ mb_min_to_scan               The minimum number of extents the multiblock
+                              allocator will search to find the best extent
+
+ mb_order2_req                Tuning parameter which controls the minimum size
+                              for requests (as a power of 2) where the buddy
+                              cache is used
+
+ mb_stats                     Controls whether the multiblock allocator should
+                              collect statistics, which are shown during the
+                              unmount. 1 means to collect statistics, 0 means
+                              not to collect statistics
+
+ mb_stream_req                Files which have fewer blocks than this tunable
+                              parameter will have their blocks allocated out
+                              of a block group specific preallocation pool, so
+                              that small files are packed closely together.
+                              Each large file will have its blocks allocated
+                              out of its own unique preallocation pool.
+
+ session_write_kbytes         This file is read-only and shows the number of
+                              kilobytes of data that have been written to this
+                              filesystem since it was mounted.
+..............................................................................
+
+Ioctls
+======
+
+There is some Ext4 specific functionality which can be accessed by applications
+through the system call interfaces. The list of all Ext4 specific ioctls are
+shown in the table below.
+
+Table of Ext4 specific ioctls
+..............................................................................
+ Ioctl			      Description
+ EXT4_IOC_GETFLAGS	      Get additional attributes associated with inode.
+			      The ioctl argument is an integer bitfield, with
+			      bit values described in ext4.h. This ioctl is an
+			      alias for FS_IOC_GETFLAGS.
+
+ EXT4_IOC_SETFLAGS	      Set additional attributes associated with inode.
+			      The ioctl argument is an integer bitfield, with
+			      bit values described in ext4.h. This ioctl is an
+			      alias for FS_IOC_SETFLAGS.
+
+ EXT4_IOC_GETVERSION
+ EXT4_IOC_GETVERSION_OLD
+			      Get the inode i_generation number stored for
+			      each inode. The i_generation number is normally
+			      changed only when new inode is created and it is
+			      particularly useful for network filesystems. The
+			      '_OLD' version of this ioctl is an alias for
+			      FS_IOC_GETVERSION.
+
+ EXT4_IOC_SETVERSION
+ EXT4_IOC_SETVERSION_OLD
+			      Set the inode i_generation number stored for
+			      each inode. The '_OLD' version of this ioctl
+			      is an alias for FS_IOC_SETVERSION.
+
+ EXT4_IOC_GROUP_EXTEND	      This ioctl has the same purpose as the resize
+			      mount option. It allows to resize filesystem
+			      to the end of the last existing block group,
+			      further resize has to be done with resize2fs,
+			      either online, or offline. The argument points
+			      to the unsigned logn number representing the
+			      filesystem new block count.
+
+ EXT4_IOC_MOVE_EXT	      Move the block extents from orig_fd (the one
+			      this ioctl is pointing to) to the donor_fd (the
+			      one specified in move_extent structure passed
+			      as an argument to this ioctl). Then, exchange
+			      inode metadata between orig_fd and donor_fd.
+			      This is especially useful for online
+			      defragmentation, because the allocator has the
+			      opportunity to allocate moved blocks better,
+			      ideally into one contiguous extent.
+
+ EXT4_IOC_GROUP_ADD	      Add a new group descriptor to an existing or
+			      new group descriptor block. The new group
+			      descriptor is described by ext4_new_group_input
+			      structure, which is passed as an argument to
+			      this ioctl. This is especially useful in
+			      conjunction with EXT4_IOC_GROUP_EXTEND,
+			      which allows online resize of the filesystem
+			      to the end of the last existing block group.
+			      Those two ioctls combined is used in userspace
+			      online resize tool (e.g. resize2fs).
+
+ EXT4_IOC_MIGRATE	      This ioctl operates on the filesystem itself.
+			      It converts (migrates) ext3 indirect block mapped
+			      inode to ext4 extent mapped inode by walking
+			      through indirect block mapping of the original
+			      inode and converting contiguous block ranges
+			      into ext4 extents of the temporary inode. Then,
+			      inodes are swapped. This ioctl might help, when
+			      migrating from ext3 to ext4 filesystem, however
+			      suggestion is to create fresh ext4 filesystem
+			      and copy data from the backup. Note, that
+			      filesystem has to support extents for this ioctl
+			      to work.
+
+ EXT4_IOC_ALLOC_DA_BLKS	      Force all of the delay allocated blocks to be
+			      allocated to preserve application-expected ext3
+			      behaviour. Note that this will also start
+			      triggering a write of the data blocks, but this
+			      behaviour may change in the future as it is
+			      not necessary and has been done this way only
+			      for sake of simplicity.
+..............................................................................
+
 References
 ==========
 
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/gfs2.txt linux-libre-2.6.39-gnu/Documentation/filesystems/gfs2.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/gfs2.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/gfs2.txt	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 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, the currently
+GFS uses interchangeable inter-node locking mechanisms, the currently
 supported mechanisms are:
 
   lock_nolock -- allows gfs to be used as a local file system
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/gfs2-uevents.txt linux-libre-2.6.39-gnu/Documentation/filesystems/gfs2-uevents.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/gfs2-uevents.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/gfs2-uevents.txt	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 
 The REMOVE uevent is generated at the end of an unsuccessful mount
 or at the end of a umount of the filesystem. All REMOVE uevents will
-have been preceeded by at least an ADD uevent for the same fileystem,
+have been preceded by at least an ADD uevent for the same fileystem,
 and unlike the other uevents is generated automatically by the kernel's
 kobject subsystem.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/Locking linux-libre-2.6.39-gnu/Documentation/filesystems/Locking
--- linux-libre-2.6.38-gnu/Documentation/filesystems/Locking	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/Locking	2011-05-19 00:06:34.000000000 -0400
@@ -128,7 +128,7 @@
 destroy_inode:
 dirty_inode:				(must not sleep)
 write_inode:
-drop_inode:				!!!inode_lock!!!
+drop_inode:				!!!inode->i_lock!!!
 evict_inode:
 put_super:		write
 write_super:		read
@@ -166,13 +166,11 @@
 	void (*kill_sb) (struct super_block *);
 locking rules:
 		may block
-get_sb		yes
 mount		yes
 kill_sb		yes
 
-->get_sb() returns error or 0 with locked superblock attached to the vfsmount
-(exclusive on ->s_umount).
-->mount() returns ERR_PTR or the root dentry.
+->mount() returns ERR_PTR or the root dentry; its superblock should be locked
+on return.
 ->kill_sb() takes a write-locked superblock, does all shutdown work on it,
 unlocks and drops the reference.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/nfs/pnfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/nfs/pnfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/nfs/pnfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/nfs/pnfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -46,3 +46,10 @@
 file driver devices refer to data servers, which are kept in a module
 level cache.  Its reference is held over the lifetime of the deviceid
 pointing to it.
+
+lseg
+----
+lseg maintains an extra reference corresponding to the NFS_LSEG_VALID
+bit which holds it in the pnfs_layout_hdr's list.  When the final lseg
+is removed from the pnfs_layout_hdr's list, the NFS_LAYOUT_DESTROYED
+bit is set, preventing any new lsegs from being added.
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/ntfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/ntfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/ntfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/ntfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -350,7 +350,7 @@
 already in sync which will be the case on a clean shutdown of Windows.  If the
 mirrors are not clean, you can specify the "sync" option instead of "nosync"
 and the Device-Mapper driver will then copy the entirety of the "Source Device"
-to the "Target Device" or if you specified multipled target devices to all of
+to the "Target Device" or if you specified multiple target devices to all of
 them.
 
 Once you have your table, save it in a file somewhere (e.g. /etc/ntfsvolume1),
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/ocfs2.txt linux-libre-2.6.39-gnu/Documentation/filesystems/ocfs2.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/ocfs2.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/ocfs2.txt	2011-05-19 00:06:34.000000000 -0400
@@ -80,7 +80,7 @@
 nouser_xattr		Disables Extended User Attributes.
 acl			Enables POSIX Access Control Lists support.
 noacl		(*)	Disables POSIX Access Control Lists support.
-resv_level=2	(*)	Set how agressive allocation reservations will be.
+resv_level=2	(*)	Set how aggressive allocation reservations will be.
 			Valid values are between 0 (reservations off) to 8
 			(maximum space for reservations).
 dir_resv_level=	(*)	By default, directory reservations will scale with file
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/path-lookup.txt linux-libre-2.6.39-gnu/Documentation/filesystems/path-lookup.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/path-lookup.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/path-lookup.txt	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,7 @@
 A name string specifies a start (root directory, cwd, fd-relative) and a
 sequence of elements (directory entry names), which together refer to a path in
 the namespace. A path is represented as a (dentry, vfsmount) tuple. The name
-elements are sub-strings, seperated by '/'.
+elements are sub-strings, separated by '/'.
 
 Name lookups will want to find a particular path that a name string refers to
 (usually the final element, or parent of final element). This is done by taking
@@ -354,7 +354,7 @@
 
 What this shows is that failed rcu-walk lookups, ie. ones that are restarted
 entirely with ref-walk, are quite rare. Even the "vfstest" case which
-specifically has concurrent renames/mkdir/rmdir/ creat/unlink/etc to excercise
+specifically has concurrent renames/mkdir/rmdir/ creat/unlink/etc to exercise
 such races is not showing a huge amount of restarts.
 
 Dropping from rcu-walk to ref-walk mean that we have encountered a dentry where
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/pohmelfs/network_protocol.txt linux-libre-2.6.39-gnu/Documentation/filesystems/pohmelfs/network_protocol.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/pohmelfs/network_protocol.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/pohmelfs/network_protocol.txt	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
 so one can extend protocol as needed without breaking backward compatibility as long
 as old commands are supported. All string lengths include tail 0 byte.
 
-All commans are transfered over the network in big-endian. CPU endianess is used at the end peers.
+All commands are transferred over the network in big-endian. CPU endianess is used at the end peers.
 
 @cmd - command number, which specifies command to be processed. Following
 	commands are used currently:
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/porting linux-libre-2.6.39-gnu/Documentation/filesystems/porting
--- linux-libre-2.6.38-gnu/Documentation/filesystems/porting	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/porting	2011-05-19 00:06:34.000000000 -0400
@@ -298,11 +298,14 @@
 remaining links or not.  Caller does *not* evict the pagecache or inode-associated
 metadata buffers; getting rid of those is responsibility of method, as it had
 been for ->delete_inode().
-	->drop_inode() returns int now; it's called on final iput() with inode_lock
-held and it returns true if filesystems wants the inode to be dropped.  As before,
-generic_drop_inode() is still the default and it's been updated appropriately.
-generic_delete_inode() is also alive and it consists simply of return 1.  Note that
-all actual eviction work is done by caller after ->drop_inode() returns.
+
+	->drop_inode() returns int now; it's called on final iput() with
+inode->i_lock held and it returns true if filesystems wants the inode to be
+dropped.  As before, generic_drop_inode() is still the default and it's been
+updated appropriately.  generic_delete_inode() is also alive and it consists
+simply of return 1.  Note that all actual eviction work is done by caller after
+->drop_inode() returns.
+
 	clear_inode() is gone; use end_writeback() instead.  As before, it must
 be called exactly once on each call of ->evict_inode() (as it used to be for
 each call of ->delete_inode()).  Unlike before, if you are using inode-associated
@@ -394,3 +397,13 @@
 Currently you can only have FALLOC_FL_PUNCH_HOLE with FALLOC_FL_KEEP_SIZE set,
 so the i_size should not change when hole punching, even when puching the end of
 a file off.
+
+--
+[mandatory]
+
+--
+[mandatory]
+	->get_sb() is gone.  Switch to use of ->mount().  Typically it's just
+a matter of switching from calling get_sb_... to mount_... and changing the
+function type.  If you were doing it manually, just switch from setting ->mnt_root
+to some pointer to returning that pointer.  On errors return ERR_PTR(...).
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/proc.txt linux-libre-2.6.39-gnu/Documentation/filesystems/proc.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/proc.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/proc.txt	2011-05-19 00:06:34.000000000 -0400
@@ -543,7 +543,7 @@
   their statistics are used by kernel developers and interested users to
   determine the occurrence of interrupts of the given type.
 
-The above IRQ vectors are displayed only when relevent.  For example,
+The above IRQ vectors are displayed only when relevant.  For example,
 the threshold vector does not exist on x86_64 platforms.  Others are
 suppressed when the system is a uniprocessor.  As of this writing, only
 i386 and x86_64 platforms support the new IRQ vector displays.
@@ -1202,7 +1202,7 @@
                        W = can do write operations
                        U = can do unblank
   flags                E = it is enabled
-                       C = it is prefered console
+                       C = it is preferred console
                        B = it is primary boot console
                        p = it is used for printk buffer
                        b = it is not a TTY but a Braille device
@@ -1331,7 +1331,7 @@
 Documentation/feature-removal-schedule.txt.
 
 Caveat: when a parent task is selected, the oom killer will sacrifice any first
-generation children with seperate address spaces instead, if possible.  This
+generation children with separate address spaces instead, if possible.  This
 avoids servers and important system daemons from being killed and loses the
 minimal amount of work.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/romfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/romfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/romfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/romfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -17,8 +17,7 @@
 with romfs, it needed 3079 blocks.
 
 To create such a file system, you'll need a user program named
-genromfs.  It is available via anonymous ftp on sunsite.unc.edu and
-its mirrors, in the /pub/Linux/system/recovery/ directory.
+genromfs. It is available on http://romfs.sourceforge.net/
 
 As the name suggests, romfs could be also used (space-efficiently) on
 various read-only media, like (E)EPROM disks if someone will have the
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/squashfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/squashfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/squashfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/squashfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -59,12 +59,15 @@
 3. SQUASHFS FILESYSTEM DESIGN
 -----------------------------
 
-A squashfs filesystem consists of a maximum of eight parts, packed together on a byte
-alignment:
+A squashfs filesystem consists of a maximum of nine parts, packed together on a
+byte alignment:
 
 	 ---------------
 	|  superblock 	|
 	|---------------|
+	|  compression  |
+	|    options    |
+	|---------------|
 	|  datablocks   |
 	|  & fragments  |
 	|---------------|
@@ -91,7 +94,14 @@
 written the completed inode, directory, fragment, export and uid/gid lookup
 tables are written.
 
-3.1 Inodes
+3.1 Compression options
+-----------------------
+
+Compressors can optionally support compression specific options (e.g.
+dictionary size).  If non-default compression options have been used, then
+these are stored here.
+
+3.2 Inodes
 ----------
 
 Metadata (inodes and directories) are compressed in 8Kbyte blocks.  Each
@@ -114,7 +124,7 @@
 regular files and directories, and extended types where extra
 information has to be stored.
 
-3.2 Directories
+3.3 Directories
 ---------------
 
 Like inodes, directories are packed into compressed metadata blocks, stored
@@ -144,7 +154,7 @@
 This scheme has the advantage that it doesn't require extra memory overhead
 and doesn't require much extra storage on disk.
 
-3.3 File data
+3.4 File data
 -------------
 
 Regular files consist of a sequence of contiguous compressed blocks, and/or a
@@ -163,7 +173,7 @@
 The index cache is designed to be memory efficient, and by default uses
 16 KiB.
 
-3.4 Fragment lookup table
+3.5 Fragment lookup table
 -------------------------
 
 Regular files can contain a fragment index which is mapped to a fragment
@@ -173,7 +183,7 @@
 speed of access (and because it is small) is read at mount time and cached
 in memory.
 
-3.5 Uid/gid lookup table
+3.6 Uid/gid lookup table
 ------------------------
 
 For space efficiency regular files store uid and gid indexes, which are
@@ -182,7 +192,7 @@
 locate these.  This second index table for speed of access (and because it
 is small) is read at mount time and cached in memory.
 
-3.6 Export table
+3.7 Export table
 ----------------
 
 To enable Squashfs filesystems to be exportable (via NFS etc.) filesystems
@@ -196,7 +206,7 @@
 used to locate these.  This second index table for speed of access (and because
 it is small) is read at mount time and cached in memory.
 
-3.7 Xattr table
+3.8 Xattr table
 ---------------
 
 The xattr table contains extended attributes for each inode.  The xattrs
@@ -209,7 +219,7 @@
 reference to where the actual value is stored).  This allows large values
 to be stored out of line improving scanning and lookup performance and it
 also allows values to be de-duplicated, the value being stored once, and
-all other occurences holding an out of line reference to that value.
+all other occurrences holding an out of line reference to that value.
 
 The xattr lists are packed into compressed 8K metadata blocks.
 To reduce overhead in inodes, rather than storing the on-disk
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/sysfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/sysfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/sysfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/sysfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -39,10 +39,12 @@
 ancestors of object hierarchies; i.e. the subsystems the objects
 belong to. 
 
-Sysfs internally stores the kobject that owns the directory in the
-->d_fsdata pointer of the directory's dentry. This allows sysfs to do
-reference counting directly on the kobject when the file is opened and
-closed. 
+Sysfs internally stores a pointer to the kobject that implements a
+directory in the sysfs_dirent object associated with the directory. In
+the past this kobject pointer has been used by sysfs to do reference
+counting directly on the kobject whenever the file is opened or closed.
+With the current sysfs implementation the kobject reference count is
+only modified directly by the function sysfs_schedule_callback().
 
 
 Attributes
@@ -60,7 +62,7 @@
 
 Mixing types, expressing multiple lines of data, and doing fancy
 formatting of data is heavily frowned upon. Doing these things may get
-you publically humiliated and your code rewritten without notice. 
+you publicly humiliated and your code rewritten without notice. 
 
 
 An attribute definition is simply:
@@ -208,9 +210,9 @@
   is 4096. 
 
 - show() methods should return the number of bytes printed into the
-  buffer. This is the return value of snprintf().
+  buffer. This is the return value of scnprintf().
 
-- show() should always use snprintf(). 
+- show() should always use scnprintf().
 
 - store() should return the number of bytes used from the buffer. If the
   entire buffer has been used, just return the count argument.
@@ -229,7 +231,7 @@
 static ssize_t show_name(struct device *dev, struct device_attribute *attr,
                          char *buf)
 {
-	return snprintf(buf, PAGE_SIZE, "%s\n", dev->name);
+	return scnprintf(buf, PAGE_SIZE, "%s\n", dev->name);
 }
 
 static ssize_t store_name(struct device *dev, struct device_attribute *attr,
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/ubifs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/ubifs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/ubifs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/ubifs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -82,12 +82,12 @@
 bulk_read		read more in one go to take advantage of flash
 			media that read faster sequentially
 no_bulk_read (*)	do not bulk-read
-no_chk_data_crc		skip checking of CRCs on data nodes in order to
+no_chk_data_crc (*)	skip checking of CRCs on data nodes in order to
 			improve read performance. Use this option only
 			if the flash media is highly reliable. The effect
 			of this option is that corruption of the contents
 			of a file can go unnoticed.
-chk_data_crc (*)	do not skip checking CRCs on data nodes
+chk_data_crc		do not skip checking CRCs on data nodes
 compr=none              override default compressor and set it to "none"
 compr=lzo               override default compressor and set it to "lzo"
 compr=zlib              override default compressor and set it to "zlib"
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/vfs.txt linux-libre-2.6.39-gnu/Documentation/filesystems/vfs.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/vfs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/vfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -95,10 +95,11 @@
    extern int unregister_filesystem(struct file_system_type *);
 
 The passed struct file_system_type describes your filesystem. When a
-request is made to mount a device onto a directory in your filespace,
-the VFS will call the appropriate get_sb() method for the specific
-filesystem. The dentry for the mount point will then be updated to
-point to the root inode for the new filesystem.
+request is made to mount a filesystem onto a directory in your namespace,
+the VFS will call the appropriate mount() method for the specific
+filesystem.  New vfsmount referring to the tree returned by ->mount()
+will be attached to the mountpoint, so that when pathname resolution
+reaches the mountpoint it will jump into the root of that vfsmount.
 
 You can see all filesystems that are registered to the kernel in the
 file /proc/filesystems.
@@ -107,14 +108,14 @@
 struct file_system_type
 -----------------------
 
-This describes the filesystem. As of kernel 2.6.22, the following
+This describes the filesystem. As of kernel 2.6.39, the following
 members are defined:
 
 struct file_system_type {
 	const char *name;
 	int fs_flags;
-        int (*get_sb) (struct file_system_type *, int,
-                       const char *, void *, struct vfsmount *);
+        struct dentry (*mount) (struct file_system_type *, int,
+                       const char *, void *);
         void (*kill_sb) (struct super_block *);
         struct module *owner;
         struct file_system_type * next;
@@ -128,11 +129,11 @@
 
   fs_flags: various flags (i.e. FS_REQUIRES_DEV, FS_NO_DCACHE, etc.)
 
-  get_sb: the method to call when a new instance of this
+  mount: the method to call when a new instance of this
 	filesystem should be mounted
 
   kill_sb: the method to call when an instance of this filesystem
-	should be unmounted
+	should be shut down
 
   owner: for internal VFS use: you should initialize this to THIS_MODULE in
   	most cases.
@@ -141,7 +142,7 @@
 
   s_lock_key, s_umount_key: lockdep-specific
 
-The get_sb() method has the following arguments:
+The mount() method has the following arguments:
 
   struct file_system_type *fs_type: describes the filesystem, partly initialized
   	by the specific filesystem code
@@ -153,32 +154,39 @@
   void *data: arbitrary mount options, usually comes as an ASCII
 	string (see "Mount Options" section)
 
-  struct vfsmount *mnt: a vfs-internal representation of a mount point
+The mount() method must return the root dentry of the tree requested by
+caller.  An active reference to its superblock must be grabbed and the
+superblock must be locked.  On failure it should return ERR_PTR(error).
 
-The get_sb() method must determine if the block device specified
-in the dev_name and fs_type contains a filesystem of the type the method
-supports. If it succeeds in opening the named block device, it initializes a
-struct super_block descriptor for the filesystem contained by the block device.
-On failure it returns an error.
+The arguments match those of mount(2) and their interpretation
+depends on filesystem type.  E.g. for block filesystems, dev_name is
+interpreted as block device name, that device is opened and if it
+contains a suitable filesystem image the method creates and initializes
+struct super_block accordingly, returning its root dentry to caller.
+
+->mount() may choose to return a subtree of existing filesystem - it
+doesn't have to create a new one.  The main result from the caller's
+point of view is a reference to dentry at the root of (sub)tree to
+be attached; creation of new superblock is a common side effect.
 
 The most interesting member of the superblock structure that the
-get_sb() method fills in is the "s_op" field. This is a pointer to
+mount() method fills in is the "s_op" field. This is a pointer to
 a "struct super_operations" which describes the next level of the
 filesystem implementation.
 
-Usually, a filesystem uses one of the generic get_sb() implementations
-and provides a fill_super() method instead. The generic methods are:
+Usually, a filesystem uses one of the generic mount() implementations
+and provides a fill_super() callback instead. The generic variants are:
 
-  get_sb_bdev: mount a filesystem residing on a block device
+  mount_bdev: mount a filesystem residing on a block device
 
-  get_sb_nodev: mount a filesystem that is not backed by a device
+  mount_nodev: mount a filesystem that is not backed by a device
 
-  get_sb_single: mount a filesystem which shares the instance between
+  mount_single: mount a filesystem which shares the instance between
   	all mounts
 
-A fill_super() method implementation has the following arguments:
+A fill_super() callback implementation has the following arguments:
 
-  struct super_block *sb: the superblock structure. The method fill_super()
+  struct super_block *sb: the superblock structure. The callback
   	must initialize this properly.
 
   void *data: arbitrary mount options, usually comes as an ASCII
@@ -246,7 +254,7 @@
 	should be synchronous or not, not all filesystems check this flag.
 
   drop_inode: called when the last access to the inode is dropped,
-	with the inode_lock spinlock held.
+	with the inode->i_lock spinlock held.
 
 	This method should be either NULL (normal UNIX filesystem
 	semantics) or "generic_delete_inode" (for filesystems that do not
@@ -865,7 +873,7 @@
 	void (*d_iput)(struct dentry *, struct inode *);
 	char *(*d_dname)(struct dentry *, char *, int);
 	struct vfsmount *(*d_automount)(struct path *);
-	int (*d_manage)(struct dentry *, bool, bool);
+	int (*d_manage)(struct dentry *, bool);
 };
 
   d_revalidate: called when the VFS needs to revalidate a dentry. This
@@ -961,10 +969,6 @@
 	mounted on it and not to check the automount flag.  Any other error
 	code will abort pathwalk completely.
 
-	If the 'mounting_here' parameter is true, then namespace_sem is being
-	held by the caller and the function should not initiate any mounts or
-	unmounts that it will then wait for.
-
 	If the 'rcu_walk' parameter is true, then the caller is doing a
 	pathwalk in RCU-walk mode.  Sleeping is not permitted in this mode,
 	and the caller can be asked to leave it and call again by returing
diff -druN linux-libre-2.6.38-gnu/Documentation/filesystems/xfs-delayed-logging-design.txt linux-libre-2.6.39-gnu/Documentation/filesystems/xfs-delayed-logging-design.txt
--- linux-libre-2.6.38-gnu/Documentation/filesystems/xfs-delayed-logging-design.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/filesystems/xfs-delayed-logging-design.txt	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,7 @@
 This relogging technique also allows objects to be moved forward in the log so
 that an object being relogged does not prevent the tail of the log from ever
 moving forward.  This can be seen in the table above by the changing
-(increasing) LSN of each subsquent transaction - the LSN is effectively a
+(increasing) LSN of each subsequent transaction - the LSN is effectively a
 direct encoding of the location in the log of the transaction.
 
 This relogging is also used to implement long-running, multiple-commit
@@ -338,7 +338,7 @@
 into the new CIL, then checkpoint transaction commit code cannot use log items
 to store the list of log vectors that need to be written into the transaction.
 Hence log vectors need to be able to be chained together to allow them to be
-detatched from the log items. That is, when the CIL is flushed the memory
+detached from the log items. That is, when the CIL is flushed the memory
 buffer and log vector attached to each log item needs to be attached to the
 checkpoint context so that the log item can be released. In diagrammatic form,
 the CIL would look like this before the flush:
@@ -577,7 +577,7 @@
 pending transactions. Thus the pinning and unpinning of a log item is symmetric
 as there is a 1:1 relationship with transaction commit and log item completion.
 
-For delayed logging, however, we have an assymetric transaction commit to
+For delayed logging, however, we have an asymmetric transaction commit to
 completion relationship. Every time an object is relogged in the CIL it goes
 through the commit process without a corresponding completion being registered.
 That is, we now have a many-to-one relationship between transaction commit and
@@ -780,7 +780,7 @@
 From this, it can be seen that the only life cycle differences between the two
 logging methods are in the middle of the life cycle - they still have the same
 beginning and end and execution constraints. The only differences are in the
-commiting of the log items to the log itself and the completion processing.
+committing of the log items to the log itself and the completion processing.
 Hence delayed logging should not introduce any constraints on log item
 behaviour, allocation or freeing that don't already exist.
 
@@ -791,10 +791,3 @@
 be able to swap methods automatically and transparently depending on load
 characteristics, but this should not be necessary if delayed logging works as
 designed.
-
-Roadmap:
-
-2.6.39 Switch default mount option to use delayed logging
-	=> should be roughly 12 months after initial merge
-	=> enough time to shake out remaining problems before next round of
-	   enterprise distro kernel rebases
diff -druN linux-libre-2.6.38-gnu/Documentation/flexible-arrays.txt linux-libre-2.6.39-gnu/Documentation/flexible-arrays.txt
--- linux-libre-2.6.38-gnu/Documentation/flexible-arrays.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/flexible-arrays.txt	2011-05-19 00:06:34.000000000 -0400
@@ -66,10 +66,10 @@
 entering atomic context, using:
 
     int flex_array_prealloc(struct flex_array *array, unsigned int start,
-			    unsigned int end, gfp_t flags);
+			    unsigned int nr_elements, gfp_t flags);
 
 This function will ensure that memory for the elements indexed in the range
-defined by start and end has been allocated.  Thereafter, a
+defined by start and nr_elements has been allocated.  Thereafter, a
 flex_array_put() call on an element in that range is guaranteed not to
 block.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/abituguru linux-libre-2.6.39-gnu/Documentation/hwmon/abituguru
--- linux-libre-2.6.38-gnu/Documentation/hwmon/abituguru	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/abituguru	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
 
 The first and second revision of the uGuru chip in reality is a Winbond
 W83L950D in disguise (despite Abit claiming it is "a new microprocessor
-designed by the ABIT Engineers"). Unfortunatly this doesn't help since the
+designed by the ABIT Engineers"). Unfortunately this doesn't help since the
 W83L950D is a generic microcontroller with a custom Abit application running
 on it.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/abituguru3 linux-libre-2.6.39-gnu/Documentation/hwmon/abituguru3
--- linux-libre-2.6.38-gnu/Documentation/hwmon/abituguru3	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/abituguru3	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,7 @@
 the Abit uGuru chip, found on recent Abit uGuru featuring motherboards.
 
 The 3rd revision of the uGuru chip in reality is a Winbond W83L951G.
-Unfortunatly this doesn't help since the W83L951G is a generic microcontroller
+Unfortunately this doesn't help since the W83L951G is a generic microcontroller
 with a custom Abit application running on it.
 
 Despite Abit not releasing any information regarding the uGuru revision 3,
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/abituguru-datasheet linux-libre-2.6.39-gnu/Documentation/hwmon/abituguru-datasheet
--- linux-libre-2.6.38-gnu/Documentation/hwmon/abituguru-datasheet	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/abituguru-datasheet	2011-05-19 00:06:34.000000000 -0400
@@ -5,9 +5,9 @@
 datasheet from Abit. The data I have got on uGuru have I assembled through
 my weak knowledge in "backwards engineering".
 And just for the record, you may have noticed uGuru isn't a chip developed by
-Abit, as they claim it to be. It's realy just an microprocessor (uC) created by
+Abit, as they claim it to be. It's really just an microprocessor (uC) created by
 Winbond (W83L950D). And no, reading the manual for this specific uC or
-mailing  Windbond for help won't give any usefull data about uGuru, as it is
+mailing  Windbond for help won't give any useful data about uGuru, as it is
 the program inside the uC that is responding to calls.
 
 Olle Sandberg <ollebull@gmail.com>, 2005-05-25
@@ -41,7 +41,7 @@
 
 After wider testing of the Linux kernel driver some variants of the uGuru have
 turned up which will hold 0x00 instead of 0xAC at the CMD port, thus we also
-have to test CMD for two different values. On these uGuru's DATA will initally
+have to test CMD for two different values. On these uGuru's DATA will initially
 hold 0x09 and will only hold 0x08 after reading CMD first, so CMD must be read
 first!
 
@@ -308,5 +308,5 @@
 resulted in a _permanent_ reprogramming of the voltages, luckily I had the
 sensors part configured so that it would shutdown my system on any out of spec
 voltages which proprably safed my computer (after a reboot I managed to
-immediatly enter the bios and reload the defaults). This probably means that
+immediately enter the bios and reload the defaults). This probably means that
 the read/write cycle for the non sensor part is different from the sensor part.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/adm1021 linux-libre-2.6.39-gnu/Documentation/hwmon/adm1021
--- linux-libre-2.6.38-gnu/Documentation/hwmon/adm1021	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/adm1021	2011-05-19 00:06:34.000000000 -0400
@@ -14,10 +14,6 @@
     Prefix: 'gl523sm'
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
     Datasheet:
-  * Intel Xeon Processor
-    Prefix: - any other - may require 'force_adm1021' parameter
-    Addresses scanned: none
-    Datasheet: Publicly available at Intel website
   * Maxim MAX1617
     Prefix: 'max1617'
     Addresses scanned: I2C 0x18 - 0x1a, 0x29 - 0x2b, 0x4c - 0x4e
@@ -91,21 +87,27 @@
 ADM1021-clones do faster measurements, but there is really no good reason
 for that.
 
-Xeon support
-------------
 
-Some Xeon processors have real max1617, adm1021, or compatible chips
-within them, with two temperature sensors.
+Netburst-based Xeon support
+---------------------------
 
-Other Xeons have chips with only one sensor.
+Some Xeon processors based on the Netburst (early Pentium 4, from 2001 to
+2003) microarchitecture had real MAX1617, ADM1021, or compatible chips
+within them, with two temperature sensors. Other Xeon processors of this
+era (with 400 MHz FSB) had chips with only one temperature sensor.
 
-If you have a Xeon, and the adm1021 module loads, and both temperatures
-appear valid, then things are good.
+If you have such an old Xeon, and you get two valid temperatures when
+loading the adm1021 module, then things are good.
 
-If the adm1021 module doesn't load, you should try this:
-	modprobe adm1021 force_adm1021=BUS,ADDRESS
-	ADDRESS can only be 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e.
+If nothing happens when loading the adm1021 module, and you are certain
+that your specific Xeon processor model includes compatible sensors, you
+will have to explicitly instantiate the sensor chips from user-space. See
+method 4 in Documentation/i2c/instantiating-devices. Possible slave
+addresses are 0x18, 0x1a, 0x29, 0x2b, 0x4c, or 0x4e. It is likely that
+only temp2 will be correct and temp1 will have to be ignored.
 
-If you have dual Xeons you may have appear to have two separate
-adm1021-compatible chips, or two single-temperature sensors, at distinct
-addresses.
+Previous generations of the Xeon processor (based on Pentium II/III)
+didn't have these sensors. Next generations of Xeon processors (533 MHz
+FSB and faster) lost them, until the Core-based generation which
+introduced integrated digital thermal sensors. These are supported by
+the coretemp driver.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/ads1015 linux-libre-2.6.39-gnu/Documentation/hwmon/ads1015
--- linux-libre-2.6.38-gnu/Documentation/hwmon/ads1015	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/ads1015	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,72 @@
+Kernel driver ads1015
+=====================
+
+Supported chips:
+  * Texas Instruments ADS1015
+    Prefix: 'ads1015'
+    Datasheet: Publicly available at the Texas Instruments website :
+               http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+
+Authors:
+        Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+
+Description
+-----------
+
+This driver implements support for the Texas Instruments ADS1015.
+
+This device is a 12-bit A-D converter with 4 inputs.
+
+The inputs can be used single ended or in certain differential combinations.
+
+The inputs can be made available by 8 sysfs input files in0_input - in7_input:
+in0: Voltage over AIN0 and AIN1.
+in1: Voltage over AIN0 and AIN3.
+in2: Voltage over AIN1 and AIN3.
+in3: Voltage over AIN2 and AIN3.
+in4: Voltage over AIN0 and GND.
+in5: Voltage over AIN1 and GND.
+in6: Voltage over AIN2 and GND.
+in7: Voltage over AIN3 and GND.
+
+Which inputs are available can be configured using platform data or devicetree.
+
+By default all inputs are exported.
+
+Platform Data
+-------------
+
+In linux/i2c/ads1015.h platform data is defined, channel_data contains
+configuration data for the used input combinations:
+- pga is the programmable gain amplifier (values are full scale)
+  0: +/- 6.144 V
+  1: +/- 4.096 V
+  2: +/- 2.048 V
+  3: +/- 1.024 V
+  4: +/- 0.512 V
+  5: +/- 0.256 V
+- data_rate in samples per second
+  0: 128
+  1: 250
+  2: 490
+  3: 920
+  4: 1600
+  5: 2400
+  6: 3300
+
+Example:
+struct ads1015_platform_data data = {
+	.channel_data = {
+		[2] = { .enabled = true, .pga = 1, .data_rate = 0 },
+		[4] = { .enabled = true, .pga = 4, .data_rate = 5 },
+	}
+};
+
+In this case only in2_input (FS +/- 4.096 V, 128 SPS) and in4_input
+(FS +/- 0.512 V, 2400 SPS) would be created.
+
+Devicetree
+----------
+
+Configuration is also possible via devicetree:
+Documentation/devicetree/bindings/hwmon/ads1015.txt
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/f71882fg linux-libre-2.6.39-gnu/Documentation/hwmon/f71882fg
--- linux-libre-2.6.38-gnu/Documentation/hwmon/f71882fg	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/f71882fg	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,10 @@
 ======================
 
 Supported chips:
+  * Fintek F71808E
+    Prefix: 'f71808e'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Not public
   * Fintek F71858FG
     Prefix: 'f71858fg'
     Addresses scanned: none, address read from Super I/O config space
@@ -10,6 +14,10 @@
     Prefix: 'f71862fg'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Available from the Fintek website
+  * Fintek F71869F and F71869E
+    Prefix: 'f71869'
+    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
@@ -17,11 +25,30 @@
   * Fintek F71889FG
     Prefix: 'f71889fg'
     Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available from the Fintek website
+  * Fintek F71889ED
+    Prefix: 'f71889ed'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Should become available on the Fintek website soon
+  * Fintek F71889A
+    Prefix: 'f71889a'
+    Addresses scanned: none, address read from Super I/O config space
     Datasheet: Should become available on the Fintek website soon
   * Fintek F8000
     Prefix: 'f8000'
     Addresses scanned: none, address read from Super I/O config space
     Datasheet: Not public
+  * Fintek F81801U
+    Prefix: 'f71889fg'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Not public
+    Note: This is the 64-pin variant of the F71889FG, they have the
+	  same device ID and are fully compatible as far as hardware
+	  monitoring is concerned.
+  * Fintek F81865F
+    Prefix: 'f81865f'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available from the Fintek website
 
 Author: Hans de Goede <hdegoede@redhat.com>
 
@@ -29,9 +56,9 @@
 Description
 -----------
 
-Fintek F718xxFG/F8000 Super I/O chips include complete hardware monitoring
-capabilities. They can monitor up to 9 voltages (3 for the F8000), 4 fans and
-3 temperature sensors.
+Fintek F718xx/F8000 Super I/O chips include complete hardware monitoring
+capabilities. They can monitor up to 9 voltages, 4 fans and 3 temperature
+sensors.
 
 These chips also have fan controlling features, using either DC or PWM, in
 three different modes (one manual, two automatic).
@@ -99,5 +126,5 @@
   The fan speed is regulated to keep the temp the fan is mapped to between
   temp#_auto_point2_temp and temp#_auto_point3_temp.
 
-Both of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
+All of the automatic modes require that pwm1 corresponds to fan1, pwm2 to
 fan2 and pwm3 to fan3.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/hpfall.c linux-libre-2.6.39-gnu/Documentation/hwmon/hpfall.c
--- linux-libre-2.6.38-gnu/Documentation/hwmon/hpfall.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/hpfall.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,146 +0,0 @@
-/* Disk protection for HP machines.
- *
- * Copyright 2008 Eric Piel
- * Copyright 2009 Pavel Machek <pavel@ucw.cz>
- *
- * GPLv2.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <string.h>
-#include <stdint.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sched.h>
-
-char unload_heads_path[64];
-
-int set_unload_heads_path(char *device)
-{
-	char devname[64];
-
-	if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
-		return -EINVAL;
-	strncpy(devname, device + 5, sizeof(devname));
-
-	snprintf(unload_heads_path, sizeof(unload_heads_path),
-				"/sys/block/%s/device/unload_heads", devname);
-	return 0;
-}
-int valid_disk(void)
-{
-	int fd = open(unload_heads_path, O_RDONLY);
-	if (fd < 0) {
-		perror(unload_heads_path);
-		return 0;
-	}
-
-	close(fd);
-	return 1;
-}
-
-void write_int(char *path, int i)
-{
-	char buf[1024];
-	int fd = open(path, O_RDWR);
-	if (fd < 0) {
-		perror("open");
-		exit(1);
-	}
-	sprintf(buf, "%d", i);
-	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
-		perror("write");
-		exit(1);
-	}
-	close(fd);
-}
-
-void set_led(int on)
-{
-	write_int("/sys/class/leds/hp::hddprotect/brightness", on);
-}
-
-void protect(int seconds)
-{
-	write_int(unload_heads_path, seconds*1000);
-}
-
-int on_ac(void)
-{
-//	/sys/class/power_supply/AC0/online
-}
-
-int lid_open(void)
-{
-//	/proc/acpi/button/lid/LID/state
-}
-
-void ignore_me(void)
-{
-	protect(0);
-	set_led(0);
-}
-
-int main(int argc, char **argv)
-{
-	int fd, ret;
-	struct sched_param param;
-
-	if (argc == 1)
-		ret = set_unload_heads_path("/dev/sda");
-	else if (argc == 2)
-		ret = set_unload_heads_path(argv[1]);
-	else
-		ret = -EINVAL;
-
-	if (ret || !valid_disk()) {
-		fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n",
-				argv[0]);
-		exit(1);
-	}
-
-	fd = open("/dev/freefall", O_RDONLY);
-	if (fd < 0) {
-		perror("/dev/freefall");
-		return EXIT_FAILURE;
-	}
-
-	daemon(0, 0);
-	param.sched_priority = sched_get_priority_max(SCHED_FIFO);
-	sched_setscheduler(0, SCHED_FIFO, &param);
-	mlockall(MCL_CURRENT|MCL_FUTURE);
-
-	signal(SIGALRM, ignore_me);
-
-	for (;;) {
-		unsigned char count;
-
-		ret = read(fd, &count, sizeof(count));
-		alarm(0);
-		if ((ret == -1) && (errno == EINTR)) {
-			/* Alarm expired, time to unpark the heads */
-			continue;
-		}
-
-		if (ret != sizeof(count)) {
-			perror("read");
-			break;
-		}
-
-		protect(21);
-		set_led(1);
-		if (1 || on_ac() || lid_open())
-			alarm(2);
-		else
-			alarm(20);
-	}
-
-	close(fd);
-	return EXIT_SUCCESS;
-}
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/lineage-pem linux-libre-2.6.39-gnu/Documentation/hwmon/lineage-pem
--- linux-libre-2.6.38-gnu/Documentation/hwmon/lineage-pem	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/lineage-pem	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,77 @@
+Kernel driver lineage-pem
+=========================
+
+Supported devices:
+  * Lineage Compact Power Line Power Entry Modules
+    Prefix: 'lineage-pem'
+    Addresses scanned: -
+    Documentation:
+        http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports various Lineage Compact Power Line DC/DC and AC/DC
+converters such as CP1800, CP2000AC, CP2000DC, CP2100DC, and others.
+
+Lineage CPL power entry modules are nominally PMBus compliant. However, most
+standard PMBus commands are not supported. Specifically, all hardware monitoring
+and status reporting commands are non-standard. For this reason, a standard
+PMBus driver can not be used.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for Lineage CPL devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for a Lineage PEM at address 0x40
+on I2C bus #1:
+$ modprobe lineage-pem
+$ echo lineage-pem 0x40 > /sys/bus/i2c/devices/i2c-1/new_device
+
+All Lineage CPL power entry modules have a built-in I2C bus master selector
+(PCA9541). To ensure device access, this driver should only be used as client
+driver to the pca9541 I2C master selector driver.
+
+
+Sysfs entries
+-------------
+
+All Lineage CPL devices report output voltage and device temperature as well as
+alarms for output voltage, temperature, input voltage, input current, input power,
+and fan status.
+
+Input voltage, input current, input power, and fan speed measurement is only
+supported on newer devices. The driver detects if those attributes are supported,
+and only creates respective sysfs entries if they are.
+
+in1_input		Output voltage (mV)
+in1_min_alarm		Output undervoltage alarm
+in1_max_alarm		Output overvoltage alarm
+in1_crit		Output voltage critical alarm
+
+in2_input		Input voltage (mV, optional)
+in2_alarm		Input voltage alarm
+
+curr1_input		Input current (mA, optional)
+curr1_alarm		Input overcurrent alarm
+
+power1_input		Input power (uW, optional)
+power1_alarm		Input power alarm
+
+fan1_input		Fan 1 speed (rpm, optional)
+fan2_input		Fan 2 speed (rpm, optional)
+fan3_input		Fan 3 speed (rpm, optional)
+
+temp1_input
+temp1_max
+temp1_crit
+temp1_alarm
+temp1_crit_alarm
+temp1_fault
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/lis3lv02d linux-libre-2.6.39-gnu/Documentation/hwmon/lis3lv02d
--- linux-libre-2.6.38-gnu/Documentation/hwmon/lis3lv02d	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/lis3lv02d	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-Kernel driver lis3lv02d
-=======================
-
-Supported chips:
-
-  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
-  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
-
-Authors:
-        Yan Burman <burman.yan@gmail.com>
-	Eric Piel <eric.piel@tremplin-utc.net>
-
-
-Description
------------
-
-This driver provides support for the accelerometer found in various HP laptops
-sporting the feature officially called "HP Mobile Data Protection System 3D" or
-"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known
-models (full list can be found in drivers/hwmon/hp_accel.c) will have their
-axis automatically oriented on standard way (eg: you can directly play
-neverball). The accelerometer data is readable via
-/sys/devices/platform/lis3lv02d. Reported values are scaled
-to mg values (1/1000th of earth gravity).
-
-Sysfs attributes under /sys/devices/platform/lis3lv02d/:
-position - 3D position that the accelerometer reports. Format: "(x,y,z)"
-rate - read reports the sampling rate of the accelerometer device in HZ.
-	write changes sampling rate of the accelerometer device.
-	Only values which are supported by HW are accepted.
-selftest - performs selftest for the chip as specified by chip manufacturer.
-
-This driver also provides an absolute input class device, allowing
-the laptop to act as a pinball machine-esque joystick. Joystick device can be
-calibrated. Joystick device can be in two different modes.
-By default output values are scaled between -32768 .. 32767. In joystick raw
-mode, joystick and sysfs position entry have the same scale. There can be
-small difference due to input system fuzziness feature.
-Events are also available as input event device.
-
-Selftest is meant only for hardware diagnostic purposes. It is not meant to be
-used during normal operations. Position data is not corrupted during selftest
-but interrupt behaviour is not guaranteed to work reliably. In test mode, the
-sensing element is internally moved little bit. Selftest measures difference
-between normal mode and test mode. Chip specifications tell the acceptance
-limit for each type of the chip. Limits are provided via platform data
-to allow adjustment of the limits without a change to the actual driver.
-Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are
-measured difference between modes. Axes are not remapped in selftest mode.
-Measurement values are provided to help HW diagnostic applications to make
-final decision.
-
-On HP laptops, if the led infrastructure is activated, support for a led
-indicating disk protection will be provided as /sys/class/leds/hp::hddprotect.
-
-Another feature of the driver is misc device called "freefall" that
-acts similar to /dev/rtc and reacts on free-fall interrupts received
-from the device. It supports blocking operations, poll/select and
-fasync operation modes. You must read 1 bytes from the device.  The
-result is number of free-fall interrupts since the last successful
-read (or 255 if number of interrupts would not fit). See the hpfall.c
-file for an example on using the device.
-
-
-Axes orientation
-----------------
-
-For better compatibility between the various laptops. The values reported by
-the accelerometer are converted into a "standard" organisation of the axes
-(aka "can play neverball out of the box"):
- * When the laptop is horizontal the position reported is about 0 for X and Y
-	and a positive value for Z
- * If the left side is elevated, X increases (becomes positive)
- * If the front side (where the touchpad is) is elevated, Y decreases
-	(becomes negative)
- * If the laptop is put upside-down, Z becomes negative
-
-If your laptop model is not recognized (cf "dmesg"), you can send an
-email to the maintainer to add it to the database.  When reporting a new
-laptop, please include the output of "dmidecode" plus the value of
-/sys/devices/platform/lis3lv02d/position in these four cases.
-
-Q&A
----
-
-Q: How do I safely simulate freefall? I have an HP "portable
-workstation" which has about 3.5kg and a plastic case, so letting it
-fall to the ground is out of question...
-
-A: The sensor is pretty sensitive, so your hands can do it. Lift it
-into free space, follow the fall with your hands for like 10
-centimeters. That should be enough to trigger the detection.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/lm75 linux-libre-2.6.39-gnu/Documentation/hwmon/lm75
--- linux-libre-2.6.38-gnu/Documentation/hwmon/lm75	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/lm75	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,11 @@
     Addresses scanned: I2C 0x48 - 0x4f
     Datasheet: Publicly available at the National Semiconductor website
                http://www.national.com/
+  * National Semiconductor LM75A
+    Prefix: 'lm75a'
+    Addresses scanned: I2C 0x48 - 0x4f
+    Datasheet: Publicly available at the National Semiconductor website
+               http://www.national.com/
   * Dallas Semiconductor DS75
     Prefix: 'lm75'
     Addresses scanned: I2C 0x48 - 0x4f
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/lm85 linux-libre-2.6.39-gnu/Documentation/hwmon/lm85
--- linux-libre-2.6.38-gnu/Documentation/hwmon/lm85	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/lm85	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,14 @@
     Prefix: 'emc6d102'
     Addresses scanned: I2C 0x2c, 0x2d, 0x2e
     Datasheet: http://www.smsc.com/main/catalog/emc6d102.html
+  * SMSC EMC6D103
+    Prefix: 'emc6d103'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/catalog/emc6d103.html
+  * SMSC EMC6D103S
+    Prefix: 'emc6d103s'
+    Addresses scanned: I2C 0x2c, 0x2d, 0x2e
+    Datasheet: http://www.smsc.com/main/catalog/emc6d103s.html
 
 Authors:
         Philip Pokorny <ppokorny@penguincomputing.com>,
@@ -122,9 +130,11 @@
 EMC6D101 plus additional voltage monitoring and system control features.
 Unfortunately it is not possible to distinguish between the package
 versions on register level so these additional voltage inputs may read
-zero. The EMC6D102 features addtional ADC bits thus extending precision
+zero. EMC6D102 and EMC6D103 feature additional ADC bits thus extending precision
 of voltage and temperature channels.
 
+SMSC EMC6D103S is similar to EMC6D103, but does not support pwm#_auto_pwm_minctl
+and temp#_auto_temp_off.
 
 Hardware Configurations
 -----------------------
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/lm90 linux-libre-2.6.39-gnu/Documentation/hwmon/lm90
--- linux-libre-2.6.38-gnu/Documentation/hwmon/lm90	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/lm90	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,16 @@
     Addresses scanned: I2C 0x4c and 0x4d
     Datasheet: Publicly available at the ON Semiconductor website
                http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461
+  * Analog Devices ADT7461A
+    Prefix: 'adt7461a'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the ON Semiconductor website
+               http://www.onsemi.com/PowerSolutions/product.do?id=ADT7461A
+  * ON Semiconductor NCT1008
+    Prefix: 'nct1008'
+    Addresses scanned: I2C 0x4c and 0x4d
+    Datasheet: Publicly available at the ON Semiconductor website
+               http://www.onsemi.com/PowerSolutions/product.do?id=NCT1008
   * Maxim MAX6646
     Prefix: 'max6646'
     Addresses scanned: I2C 0x4d
@@ -149,7 +159,7 @@
   * ALERT is triggered by open remote sensor.
   * SMBus PEC support for Write Byte and Receive Byte transactions.
 
-ADT7461:
+ADT7461, ADT7461A, NCT1008:
   * Extended temperature range (breaks compatibility)
   * Lower resolution for remote temperature
 
@@ -195,9 +205,9 @@
 Only the local hysteresis can be set from user-space, and the same delta
 applies to the remote hysteresis.
 
-The lm90 driver will not update its values more frequently than every
-other second; reading them more often will do no harm, but will return
-'old' values.
+The lm90 driver will not update its values more frequently than configured with
+the update_interval attribute; reading them more often will do no harm, but will
+return 'old' values.
 
 SMBus Alert Support
 -------------------
@@ -205,11 +215,12 @@
 This driver has basic support for SMBus alert. When an alert is received,
 the status register is read and the faulty temperature channel is logged.
 
-The Analog Devices chips (ADM1032 and ADT7461) do not implement the SMBus
-alert protocol properly so additional care is needed: the ALERT output is
-disabled when an alert is received, and is re-enabled only when the alarm
-is gone. Otherwise the chip would block alerts from other chips in the bus
-as long as the alarm is active.
+The Analog Devices chips (ADM1032, ADT7461 and ADT7461A) and ON
+Semiconductor chips (NCT1008) do not implement the SMBus alert protocol
+properly so additional care is needed: the ALERT output is disabled when
+an alert is received, and is re-enabled only when the alarm is gone.
+Otherwise the chip would block alerts from other chips in the bus as long
+as the alarm is active.
 
 PEC Support
 -----------
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/ltc4151 linux-libre-2.6.39-gnu/Documentation/hwmon/ltc4151
--- linux-libre-2.6.38-gnu/Documentation/hwmon/ltc4151	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/ltc4151	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+Kernel driver ltc4151
+=====================
+
+Supported chips:
+  * Linear Technology LTC4151
+    Prefix: 'ltc4151'
+    Addresses scanned: -
+    Datasheet:
+        http://www.linear.com/docs/Datasheet/4151fc.pdf
+
+Author: Per Dalen <per.dalen@appeartv.com>
+
+
+Description
+-----------
+
+The LTC4151 is a High Voltage I2C Current and Voltage Monitor.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for LTC4151 devices, since there is no register
+which can be safely used to identify the chip. You will have to instantiate
+the devices explicitly.
+
+Example: the following will load the driver for an LTC4151 at address 0x6f
+on I2C bus #0:
+# modprobe ltc4151
+# echo ltc4151 0x6f > /sys/bus/i2c/devices/i2c-0/new_device
+
+
+Sysfs entries
+-------------
+
+Voltage readings provided by this driver are reported as obtained from the ADIN
+and VIN registers.
+
+Current reading provided by this driver is reported as obtained from the Current
+Sense register. The reported value assumes that a 1 mOhm sense resistor is
+installed.
+
+in1_input		VDIN voltage (mV)
+
+in2_input		ADIN voltage (mV)
+
+curr1_input		SENSE current (mA)
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/max16064 linux-libre-2.6.39-gnu/Documentation/hwmon/max16064
--- linux-libre-2.6.38-gnu/Documentation/hwmon/max16064	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/max16064	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+Kernel driver max16064
+======================
+
+Supported chips:
+  * Maxim MAX16064
+    Prefix: 'max16064'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX16064.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX16064 Quad Power-Supply
+Controller with Active-Voltage Output Control and PMBus Interface.
+
+The driver is a client driver to the core PMBus driver.
+Please see Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in[1-4]_label		"vout[1-4]"
+in[1-4]_input		Measured voltage. From READ_VOUT register.
+in[1-4]_min		Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in[1-4]_max		Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in[1-4]_lcrit		Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in[1-4]_crit		Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in[1-4]_min_alarm	Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in[1-4]_max_alarm	Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in[1-4]_lcrit_alarm	Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in[1-4]_crit_alarm	Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+temp1_input		Measured temperature. From READ_TEMPERATURE_1 register.
+temp1_max		Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit		Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm		Chip temperature high alarm. Set by comparing
+			READ_TEMPERATURE_1 with OT_WARN_LIMIT if TEMP_OT_WARNING
+			status is set.
+temp1_crit_alarm	Chip temperature critical high alarm. Set by comparing
+			READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+			status is set.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/max34440 linux-libre-2.6.39-gnu/Documentation/hwmon/max34440
--- linux-libre-2.6.38-gnu/Documentation/hwmon/max34440	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/max34440	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,79 @@
+Kernel driver max34440
+======================
+
+Supported chips:
+  * Maxim MAX34440
+    Prefixes: 'max34440'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34440.pdf
+  * Maxim MAX34441
+    PMBus 5-Channel Power-Supply Manager and Intelligent Fan Controller
+    Prefixes: 'max34441'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX34441.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX34440 PMBus 6-Channel
+Power-Supply Manager and MAX34441 PMBus 5-Channel Power-Supply Manager
+and Intelligent Fan Controller.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in[1-6]_label		"vout[1-6]".
+in[1-6]_input		Measured voltage. From READ_VOUT register.
+in[1-6]_min		Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in[1-6]_max		Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in[1-6]_lcrit		Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in[1-6]_crit		Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in[1-6]_min_alarm	Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in[1-6]_max_alarm	Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in[1-6]_lcrit_alarm	Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in[1-6]_crit_alarm	Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+curr[1-6]_label		"iout[1-6]".
+curr[1-6]_input		Measured current. From READ_IOUT register.
+curr[1-6]_max		Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr[1-6]_crit		Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr[1-6]_max_alarm	Current high alarm. From IOUT_OC_WARNING status.
+curr[1-6]_crit_alarm	Current critical high alarm. From IOUT_OC_FAULT status.
+
+			in6 and curr6 attributes only exist for MAX34440.
+
+temp[1-8]_input		Measured temperatures. From READ_TEMPERATURE_1 register.
+			temp1 is the chip's internal temperature. temp2..temp5
+			are remote I2C temperature sensors. For MAX34441, temp6
+			is a remote thermal-diode sensor. For MAX34440, temp6..8
+			are remote I2C temperature sensors.
+temp[1-8]_max		Maximum temperature. From OT_WARN_LIMIT register.
+temp[1-8]_crit		Critical high temperature. From OT_FAULT_LIMIT register.
+temp[1-8]_max_alarm	Temperature high alarm.
+temp[1-8]_crit_alarm	Temperature critical high alarm.
+
+			temp7 and temp8 attributes only exist for MAX34440.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/max6639 linux-libre-2.6.39-gnu/Documentation/hwmon/max6639
--- linux-libre-2.6.38-gnu/Documentation/hwmon/max6639	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/max6639	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,49 @@
+Kernel driver max6639
+=====================
+
+Supported chips:
+  * Maxim MAX6639
+    Prefix: 'max6639'
+    Addresses scanned: I2C 0x2c, 0x2e, 0x2f
+    Datasheet: http://pdfserv.maxim-ic.com/en/ds/MAX6639.pdf
+
+Authors:
+    He Changqing <hechangqing@semptian.com>
+    Roland Stigge <stigge@antcom.de>
+
+Description
+-----------
+
+This driver implements support for the Maxim MAX6639. This chip is a 2-channel
+temperature monitor with dual PWM fan speed controller. It can monitor its own
+temperature and one external diode-connected transistor or two external
+diode-connected transistors.
+
+The following device attributes are implemented via sysfs:
+
+Attribute              R/W  Contents
+----------------------------------------------------------------------------
+temp1_input            R    Temperature channel 1 input (0..150 C)
+temp2_input            R    Temperature channel 2 input (0..150 C)
+temp1_fault            R    Temperature channel 1 diode fault
+temp2_fault            R    Temperature channel 2 diode fault
+temp1_max              RW   Set THERM temperature for input 1
+                            (in C, see datasheet)
+temp2_max              RW   Set THERM temperature for input 2
+temp1_crit             RW   Set ALERT temperature for input 1
+temp2_crit             RW   Set ALERT temperature for input 2
+temp1_emergency        RW   Set OT temperature for input 1
+                            (in C, see datasheet)
+temp2_emergency        RW   Set OT temperature for input 2
+pwm1                   RW   Fan 1 target duty cycle (0..255)
+pwm2                   RW   Fan 2 target duty cycle (0..255)
+fan1_input             R    TACH1 fan tachometer input (in RPM)
+fan2_input             R    TACH2 fan tachometer input (in RPM)
+fan1_fault             R    Fan 1 fault
+fan2_fault             R    Fan 2 fault
+temp1_max_alarm        R    Alarm on THERM temperature on channel 1
+temp2_max_alarm        R    Alarm on THERM temperature on channel 2
+temp1_crit_alarm       R    Alarm on ALERT temperature on channel 1
+temp2_crit_alarm       R    Alarm on ALERT temperature on channel 2
+temp1_emergency_alarm  R    Alarm on OT temperature on channel 1
+temp2_emergency_alarm  R    Alarm on OT temperature on channel 2
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/max8688 linux-libre-2.6.39-gnu/Documentation/hwmon/max8688
--- linux-libre-2.6.38-gnu/Documentation/hwmon/max8688	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/max8688	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,69 @@
+Kernel driver max8688
+=====================
+
+Supported chips:
+  * Maxim MAX8688
+    Prefix: 'max8688'
+    Addresses scanned: -
+    Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX8688.pdf
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for Maxim MAX8688 Digital Power-Supply
+Controller/Monitor with PMBus Interface.
+
+The driver is a client driver to the core PMBus driver. Please see
+Documentation/hwmon/pmbus for details on PMBus client drivers.
+
+
+Usage Notes
+-----------
+
+This driver does not auto-detect devices. You will have to instantiate the
+devices explicitly. Please see Documentation/i2c/instantiating-devices for
+details.
+
+
+Platform data support
+---------------------
+
+The driver supports standard PMBus driver platform data.
+
+
+Sysfs entries
+-------------
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+in1_label		"vout1"
+in1_input		Measured voltage. From READ_VOUT register.
+in1_min			Minumum Voltage. From VOUT_UV_WARN_LIMIT register.
+in1_max			Maximum voltage. From VOUT_OV_WARN_LIMIT register.
+in1_lcrit		Critical minumum Voltage. VOUT_UV_FAULT_LIMIT register.
+in1_crit		Critical maximum voltage. From VOUT_OV_FAULT_LIMIT register.
+in1_min_alarm		Voltage low alarm. From VOLTAGE_UV_WARNING status.
+in1_max_alarm		Voltage high alarm. From VOLTAGE_OV_WARNING status.
+in1_lcrit_alarm		Voltage critical low alarm. From VOLTAGE_UV_FAULT status.
+in1_crit_alarm		Voltage critical high alarm. From VOLTAGE_OV_FAULT status.
+
+curr1_label		"iout1"
+curr1_input		Measured current. From READ_IOUT register.
+curr1_max		Maximum current. From IOUT_OC_WARN_LIMIT register.
+curr1_crit		Critical maximum current. From IOUT_OC_FAULT_LIMIT register.
+curr1_max_alarm		Current high alarm. From IOUT_OC_WARN_LIMIT register.
+curr1_crit_alarm	Current critical high alarm. From IOUT_OC_FAULT status.
+
+temp1_input		Measured temperature. From READ_TEMPERATURE_1 register.
+temp1_max		Maximum temperature. From OT_WARN_LIMIT register.
+temp1_crit		Critical high temperature. From OT_FAULT_LIMIT register.
+temp1_max_alarm		Chip temperature high alarm. Set by comparing
+			READ_TEMPERATURE_1 with OT_WARN_LIMIT if TEMP_OT_WARNING
+			status is set.
+temp1_crit_alarm	Chip temperature critical high alarm. Set by comparing
+			READ_TEMPERATURE_1 with OT_FAULT_LIMIT if TEMP_OT_FAULT
+			status is set.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/pmbus linux-libre-2.6.39-gnu/Documentation/hwmon/pmbus
--- linux-libre-2.6.38-gnu/Documentation/hwmon/pmbus	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/pmbus	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,197 @@
+Kernel driver pmbus
+====================
+
+Supported chips:
+  * Ericsson BMR45X series
+    DC/DC Converter
+    Prefixes: 'bmr450', 'bmr451', 'bmr453', 'bmr454'
+    Addresses scanned: -
+    Datasheet:
+ http://archive.ericsson.net/service/internet/picov/get?DocNo=28701-EN/LZT146395
+  * Linear Technology LTC2978
+    Octal PMBus Power Supply Monitor and Controller
+    Prefix: 'ltc2978'
+    Addresses scanned: -
+    Datasheet: http://cds.linear.com/docs/Datasheet/2978fa.pdf
+  * Generic PMBus devices
+    Prefix: 'pmbus'
+    Addresses scanned: -
+    Datasheet: n.a.
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+
+Description
+-----------
+
+This driver supports hardware montoring for various PMBus compliant devices.
+It supports voltage, current, power, and temperature sensors as supported
+by the device.
+
+Each monitored channel has its own high and low limits, plus a critical
+limit.
+
+Fan support will be added in a later version of this driver.
+
+
+Usage Notes
+-----------
+
+This driver does not probe for PMBus devices, since there is no register
+which can be safely used to identify the chip (The MFG_ID register is not
+supported by all chips), and since there is no well defined address range for
+PMBus devices. You will have to instantiate the devices explicitly.
+
+Example: the following will load the driver for an LTC2978 at address 0x60
+on I2C bus #1:
+$ modprobe pmbus
+$ echo ltc2978 0x60 > /sys/bus/i2c/devices/i2c-1/new_device
+
+
+Platform data support
+---------------------
+
+Support for additional PMBus chips can be added by defining chip parameters in
+a new chip specific driver file. For example, (untested) code to add support for
+Emerson DS1200 power modules might look as follows.
+
+static struct pmbus_driver_info ds1200_info = {
+	.pages = 1,
+	/* Note: All other sensors are in linear mode */
+	.direct[PSC_VOLTAGE_OUT] = true,
+	.direct[PSC_TEMPERATURE] = true,
+	.direct[PSC_CURRENT_OUT] = true,
+	.m[PSC_VOLTAGE_IN] = 1,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = 3,
+	.m[PSC_VOLTAGE_OUT] = 1,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = 3,
+	.m[PSC_TEMPERATURE] = 1,
+	.b[PSC_TEMPERATURE] = 0,
+	.R[PSC_TEMPERATURE] = 3,
+	.func[0] = PMBUS_HAVE_VIN | PMBUS_HAVE_IIN | PMBUS_HAVE_STATUS_INPUT
+		   | PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		   | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT
+		   | PMBUS_HAVE_PIN | PMBUS_HAVE_POUT
+		   | PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP
+		   | PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
+};
+
+static int ds1200_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &ds1200_info);
+}
+
+static int ds1200_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id ds1200_id[] = {
+	{"ds1200", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, ds1200_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ds1200_driver = {
+	.driver = {
+		   .name = "ds1200",
+		   },
+	.probe = ds1200_probe,
+	.remove = ds1200_remove,
+	.id_table = ds1200_id,
+};
+
+static int __init ds1200_init(void)
+{
+	return i2c_add_driver(&ds1200_driver);
+}
+
+static void __exit ds1200_exit(void)
+{
+	i2c_del_driver(&ds1200_driver);
+}
+
+
+Sysfs entries
+-------------
+
+When probing the chip, the driver identifies which PMBus registers are
+supported, and determines available sensors from this information.
+Attribute files only exist if respective sensors are suported by the chip.
+Labels are provided to inform the user about the sensor associated with
+a given sysfs entry.
+
+The following attributes are supported. Limits are read-write; all other
+attributes are read-only.
+
+inX_input		Measured voltage. From READ_VIN or READ_VOUT register.
+inX_min			Minimum Voltage.
+			From VIN_UV_WARN_LIMIT or VOUT_UV_WARN_LIMIT register.
+inX_max			Maximum voltage.
+			From VIN_OV_WARN_LIMIT or VOUT_OV_WARN_LIMIT register.
+inX_lcrit		Critical minimum Voltage.
+			From VIN_UV_FAULT_LIMIT or VOUT_UV_FAULT_LIMIT register.
+inX_crit		Critical maximum voltage.
+			From VIN_OV_FAULT_LIMIT or VOUT_OV_FAULT_LIMIT register.
+inX_min_alarm		Voltage low alarm. From VOLTAGE_UV_WARNING status.
+inX_max_alarm		Voltage high alarm. From VOLTAGE_OV_WARNING status.
+inX_lcrit_alarm		Voltage critical low alarm.
+			From VOLTAGE_UV_FAULT status.
+inX_crit_alarm		Voltage critical high alarm.
+			From VOLTAGE_OV_FAULT status.
+inX_label		"vin", "vcap", or "voutY"
+
+currX_input		Measured current. From READ_IIN or READ_IOUT register.
+currX_max		Maximum current.
+			From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT register.
+currX_lcrit		Critical minimum output current.
+			From IOUT_UC_FAULT_LIMIT register.
+currX_crit		Critical maximum current.
+			From IIN_OC_FAULT_LIMIT or IOUT_OC_FAULT_LIMIT register.
+currX_alarm		Current high alarm.
+			From IIN_OC_WARNING or IOUT_OC_WARNING status.
+currX_max_alarm		Current high alarm.
+			From IIN_OC_WARN_LIMIT or IOUT_OC_WARN_LIMIT status.
+currX_lcrit_alarm	Output current critical low alarm.
+			From IOUT_UC_FAULT status.
+currX_crit_alarm	Current critical high alarm.
+			From IIN_OC_FAULT or IOUT_OC_FAULT status.
+currX_label		"iin" or "ioutY"
+
+powerX_input		Measured power. From READ_PIN or READ_POUT register.
+powerX_cap		Output power cap. From POUT_MAX register.
+powerX_max		Power limit. From PIN_OP_WARN_LIMIT or
+			POUT_OP_WARN_LIMIT register.
+powerX_crit		Critical output power limit.
+			From POUT_OP_FAULT_LIMIT register.
+powerX_alarm		Power high alarm.
+			From PIN_OP_WARNING or POUT_OP_WARNING status.
+powerX_crit_alarm	Output power critical high alarm.
+			From POUT_OP_FAULT status.
+powerX_label		"pin" or "poutY"
+
+tempX_input		Measured temperature.
+			From READ_TEMPERATURE_X register.
+tempX_min		Mimimum temperature. From UT_WARN_LIMIT register.
+tempX_max		Maximum temperature. From OT_WARN_LIMIT register.
+tempX_lcrit		Critical low temperature.
+			From UT_FAULT_LIMIT register.
+tempX_crit		Critical high temperature.
+			From OT_FAULT_LIMIT register.
+tempX_min_alarm		Chip temperature low alarm. Set by comparing
+			READ_TEMPERATURE_X with UT_WARN_LIMIT if
+			TEMP_UT_WARNING status is set.
+tempX_max_alarm		Chip temperature high alarm. Set by comparing
+			READ_TEMPERATURE_X with OT_WARN_LIMIT if
+			TEMP_OT_WARNING status is set.
+tempX_lcrit_alarm	Chip temperature critical low alarm. Set by comparing
+			READ_TEMPERATURE_X with UT_FAULT_LIMIT if
+			TEMP_UT_FAULT status is set.
+tempX_crit_alarm	Chip temperature critical high alarm. Set by comparing
+			READ_TEMPERATURE_X with OT_FAULT_LIMIT if
+			TEMP_OT_FAULT status is set.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/sch5627 linux-libre-2.6.39-gnu/Documentation/hwmon/sch5627
--- linux-libre-2.6.38-gnu/Documentation/hwmon/sch5627	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/sch5627	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,22 @@
+Kernel driver sch5627
+=====================
+
+Supported chips:
+  * SMSC SCH5627
+    Prefix: 'sch5627'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Application Note available upon request
+
+Author: Hans de Goede <hdegoede@redhat.com>
+
+
+Description
+-----------
+
+SMSC SCH5627 Super I/O chips include complete hardware monitoring
+capabilities. They can monitor up to 5 voltages, 4 fans and 8 temperatures.
+
+The hardware monitoring part of the SMSC SCH5627 is accessed by talking
+through an embedded microcontroller. An application note describing the
+protocol for communicating with the microcontroller is available upon
+request. Please mail me if you want a copy.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/smm665 linux-libre-2.6.39-gnu/Documentation/hwmon/smm665
--- linux-libre-2.6.38-gnu/Documentation/hwmon/smm665	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/smm665	2011-05-19 00:06:34.000000000 -0400
@@ -150,8 +150,8 @@
 in9_crit_alarm		AIN1 critical alarm
 in10_crit_alarm		AIN2 critical alarm
 
-temp1_input		Chip tempererature
-temp1_min		Mimimum chip tempererature
-temp1_max		Maximum chip tempererature
-temp1_crit		Critical chip tempererature
+temp1_input		Chip temperature
+temp1_min		Mimimum chip temperature
+temp1_max		Maximum chip temperature
+temp1_crit		Critical chip temperature
 temp1_crit_alarm	Temperature critical alarm
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/submitting-patches linux-libre-2.6.39-gnu/Documentation/hwmon/submitting-patches
--- linux-libre-2.6.38-gnu/Documentation/hwmon/submitting-patches	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/submitting-patches	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,109 @@
+	How to Get Your Patch Accepted Into the Hwmon Subsystem
+	-------------------------------------------------------
+
+This text is is a collection of suggestions for people writing patches or
+drivers for the hwmon subsystem. Following these suggestions will greatly
+increase the chances of your change being accepted.
+
+
+1. General
+----------
+
+* It should be unnecessary to mention, but please read and follow
+    Documentation/SubmitChecklist
+    Documentation/SubmittingDrivers
+    Documentation/SubmittingPatches
+    Documentation/CodingStyle
+
+* If your patch generates checkpatch warnings, please refrain from explanations
+  such as "I don't like that coding style". Keep in mind that each unnecessary
+  warning helps hiding a real problem. If you don't like the kernel coding
+  style, don't write kernel drivers.
+
+* Please test your patch thoroughly. We are not your test group.
+  Sometimes a patch can not or not completely be tested because of missing
+  hardware. In such cases, you should test-build the code on at least one
+  architecture. If run-time testing was not achieved, it should be written
+  explicitly below the patch header.
+
+* If your patch (or the driver) is affected by configuration options such as
+  CONFIG_SMP or CONFIG_HOTPLUG, make sure it compiles for all configuration
+  variants.
+
+
+2. Adding functionality to existing drivers
+-------------------------------------------
+
+* Make sure the documentation in Documentation/hwmon/<driver_name> is up to
+  date.
+
+* Make sure the information in Kconfig is up to date.
+
+* If the added functionality requires some cleanup or structural changes, split
+  your patch into a cleanup part and the actual addition. This makes it easier
+  to review your changes, and to bisect any resulting problems.
+
+* Never mix bug fixes, cleanup, and functional enhancements in a single patch.
+
+
+3. New drivers
+--------------
+
+* Running your patch or driver file(s) through checkpatch does not mean its
+  formatting is clean. If unsure about formatting in your new driver, run it
+  through Lindent. Lindent is not perfect, and you may have to do some minor
+  cleanup, but it is a good start.
+
+* Consider adding yourself to MAINTAINERS.
+
+* Document the driver in Documentation/hwmon/<driver_name>.
+
+* Add the driver to Kconfig and Makefile in alphabetical order.
+
+* Make sure that all dependencies are listed in Kconfig. For new drivers, it
+  is most likely prudent to add a dependency on EXPERIMENTAL.
+
+* Avoid forward declarations if you can. Rearrange the code if necessary.
+
+* Avoid calculations in macros and macro-generated functions. While such macros
+  may save a line or so in the source, it obfuscates the code and makes code
+  review more difficult. It may also result in code which is more complicated
+  than necessary. Use inline functions or just regular functions instead.
+
+* If the driver has a detect function, make sure it is silent. Debug messages
+  and messages printed after a successful detection are acceptable, but it
+  must not print messages such as "Chip XXX not found/supported".
+
+  Keep in mind that the detect function will run for all drivers supporting an
+  address if a chip is detected on that address. Unnecessary messages will just
+  pollute the kernel log and not provide any value.
+
+* Provide a detect function if and only if a chip can be detected reliably.
+
+* Avoid writing to chip registers in the detect function. If you have to write,
+  only do it after you have already gathered enough data to be certain that the
+  detection is going to be successful.
+
+  Keep in mind that the chip might not be what your driver believes it is, and
+  writing to it might cause a bad misconfiguration.
+
+* Make sure there are no race conditions in the probe function. Specifically,
+  completely initialize your chip first, then create sysfs entries and register
+  with the hwmon subsystem.
+
+* Do not provide support for deprecated sysfs attributes.
+
+* Do not create non-standard attributes unless really needed. If you have to use
+  non-standard attributes, or you believe you do, discuss it on the mailing list
+  first. Either case, provide a detailed explanation why you need the
+  non-standard attribute(s).
+  Standard attributes are specified in Documentation/hwmon/sysfs-interface.
+
+* When deciding which sysfs attributes to support, look at the chip's
+  capabilities. While we do not expect your driver to support everything the
+  chip may offer, it should at least support all limits and alarms.
+
+* Last but not least, please check if a driver for your chip already exists
+  before starting to write a new driver. Especially for temperature sensors,
+  new chips are often variants of previously released chips. In some cases,
+  a presumably new chip may simply have been relabeled.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/sysfs-interface linux-libre-2.6.39-gnu/Documentation/hwmon/sysfs-interface
--- linux-libre-2.6.38-gnu/Documentation/hwmon/sysfs-interface	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/sysfs-interface	2011-05-19 00:06:34.000000000 -0400
@@ -187,6 +187,17 @@
 		Note that this is actually an internal clock divisor, which
 		affects the measurable speed range, not the read value.
 
+fan[1-*]_pulses	Number of tachometer pulses per fan revolution.
+		Integer value, typically between 1 and 4.
+		RW
+		This value is a characteristic of the fan connected to the
+		device's input, so it has to be set in accordance with the fan
+		model.
+		Should only be created if the chip has a register to configure
+		the number of pulses. In the absence of such a register (and
+		thus attribute) the value assumed by all devices is 2 pulses
+		per fan revolution.
+
 fan[1-*]_target
 		Desired fan speed
 		Unit: revolution/min (RPM)
@@ -568,7 +579,7 @@
 fan[1-*]_fault
 temp[1-*]_fault
 		Input fault condition
-		0: no fault occured
+		0: no fault occurred
 		1: fault condition
 		RO
 
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/twl4030-madc-hwmon linux-libre-2.6.39-gnu/Documentation/hwmon/twl4030-madc-hwmon
--- linux-libre-2.6.38-gnu/Documentation/hwmon/twl4030-madc-hwmon	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/twl4030-madc-hwmon	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,45 @@
+Kernel driver twl4030-madc
+=========================
+
+Supported chips:
+	* Texas Instruments TWL4030
+	Prefix: 'twl4030-madc'
+
+
+Authors:
+	J Keerthy <j-keerthy@ti.com>
+
+Description
+-----------
+
+The Texas Instruments TWL4030 is a Power Management and Audio Circuit. Among
+other things it contains a 10-bit A/D converter MADC. The converter has 16
+channels which can be used in different modes.
+
+
+See this table for the meaning of the different channels
+
+Channel Signal
+------------------------------------------
+0	Battery type(BTYPE)
+1	BCI: Battery temperature (BTEMP)
+2	GP analog input
+3	GP analog input
+4	GP analog input
+5	GP analog input
+6	GP analog input
+7	GP analog input
+8	BCI: VBUS voltage(VBUS)
+9	Backup Battery voltage (VBKP)
+10	BCI: Battery charger current (ICHG)
+11	BCI: Battery charger voltage (VCHG)
+12	BCI: Main battery voltage (VBAT)
+13	Reserved
+14	Reserved
+15	VRUSB Supply/Speaker left/Speaker right polarization level
+
+
+The Sysfs nodes will represent the voltage in the units of mV,
+the temperature channel shows the converted temperature in
+degree celcius. The Battery charging current channel represents
+battery charging current in mA.
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/w83627ehf linux-libre-2.6.39-gnu/Documentation/hwmon/w83627ehf
--- linux-libre-2.6.38-gnu/Documentation/hwmon/w83627ehf	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/w83627ehf	2011-05-19 00:06:34.000000000 -0400
@@ -5,13 +5,11 @@
   * Winbond W83627EHF/EHG (ISA access ONLY)
     Prefix: 'w83627ehf'
     Addresses scanned: ISA address retrieved from Super I/O registers
-    Datasheet:
-        http://www.nuvoton.com.tw/NR/rdonlyres/A6A258F0-F0C9-4F97-81C0-C4D29E7E943E/0/W83627EHF.pdf
+    Datasheet: not available
   * Winbond W83627DHG
     Prefix: 'w83627dhg'
     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
+    Datasheet: not available
   * Winbond W83627DHG-P
     Prefix: 'w83627dhg'
     Addresses scanned: ISA address retrieved from Super I/O registers
@@ -24,6 +22,14 @@
     Prefix: 'w83667hg'
     Addresses scanned: ISA address retrieved from Super I/O registers
     Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6775F/W83667HG-I
+    Prefix: 'nct6775'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
+  * Nuvoton NCT6776F
+    Prefix: 'nct6776'
+    Addresses scanned: ISA address retrieved from Super I/O registers
+    Datasheet: Available from Nuvoton upon request
 
 Authors:
         Jean Delvare <khali@linux-fr.org>
@@ -36,19 +42,28 @@
 -----------
 
 This driver implements support for the Winbond W83627EHF, W83627EHG,
-W83627DHG, W83627DHG-P, W83667HG and W83667HG-B super I/O chips.
-We will refer to them collectively as Winbond chips.
+W83627DHG, W83627DHG-P, W83667HG, W83667HG-B, W83667HG-I (NCT6775F),
+and NCT6776F 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
-VID (6 pins for the 627EHF/EHG, 8 pins for the 627DHG and 667HG), alarms
-with beep warnings (control unimplemented), and some automatic fan
-regulation strategies (plus manual fan control mode).
+The chips implement three temperature sensors (up to four for 667HG-B, and nine
+for NCT6775F and NCT6776F), five fan rotation speed sensors, ten analog voltage
+sensors (only nine for the 627DHG), one VID (6 pins for the 627EHF/EHG, 8 pins
+for the 627DHG and 667HG), alarms with beep warnings (control unimplemented),
+and some automatic fan regulation strategies (plus manual fan control mode).
+
+The temperature sensor sources on W82677HG-B, NCT6775F, and NCT6776F are
+configurable. temp4 and higher attributes are only reported if its temperature
+source differs from the temperature sources of the already reported temperature
+sensors. The configured source for each of the temperature sensors is provided
+in tempX_label.
 
 Temperatures are measured in degrees Celsius and measurement resolution is 1
-degC for temp1 and 0.5 degC for temp2 and temp3. An alarm is triggered when
-the temperature gets higher than high limit; it stays on until the temperature
-falls below the hysteresis value.
+degC for temp1 and and 0.5 degC for temp2 and temp3. For temp4 and higher,
+resolution is 1 degC for W83667HG-B and 0.0 degC for NCT6775F and NCT6776F.
+An alarm is triggered when the temperature gets higher than high limit;
+it stays on until the temperature falls below the hysteresis value.
+Alarms are only supported for temp1, temp2, and temp3.
 
 Fan rotation speeds are reported in RPM (rotations per minute). An alarm is
 triggered if the rotation speed has dropped below a programmable limit. Fan
@@ -80,7 +95,8 @@
 
 name - this is a standard hwmon device entry. For the W83627EHF and W83627EHG,
        it is set to "w83627ehf", for the W83627DHG it is set to "w83627dhg",
-       and for the W83667HG it is set to "w83667hg".
+       for the W83667HG and W83667HG-B it is set to "w83667hg", for NCT6775F it
+       is set to "nct6775", and for NCT6776F it is set to "nct6776".
 
 pwm[1-4] - this file stores PWM duty cycle or DC value (fan speed) in range:
 	   0 (stop) to 255 (full)
@@ -90,6 +106,18 @@
 	* 2 "Thermal Cruise" mode
 	* 3 "Fan Speed Cruise" mode
 	* 4 "Smart Fan III" mode
+	* 5 "Smart Fan IV" mode
+
+	SmartFan III mode is not supported on NCT6776F.
+
+	SmartFan IV mode is configurable only if it was configured at system
+	startup, and is only supported for W83677HG-B, NCT6775F, and NCT6776F.
+	SmartFan IV operational parameters can not be configured at this time,
+	and the various pwm attributes are not used in SmartFan IV mode.
+	The attributes can be written to, which is useful if you plan to
+	configure the system for a different pwm mode. However, the information
+	returned when reading pwm attributes is unrelated to SmartFan IV
+	operation.
 
 pwm[1-4]_mode - controls if output is PWM or DC level
         * 0 DC output (0 - 12v)
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/w83781d linux-libre-2.6.39-gnu/Documentation/hwmon/w83781d
--- linux-libre-2.6.38-gnu/Documentation/hwmon/w83781d	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/w83781d	2011-05-19 00:06:34.000000000 -0400
@@ -403,7 +403,7 @@
 
 0x80 - seems to turn fans off after some time(1-2 minutes)... might be
 some form of auto-fan-control based on temp? hmm (Qfan? this mobo is an
-old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attemp at Qfan
+old ASUS, it isn't marketed as Qfan. Maybe some beta pre-attempt at Qfan
 that was dropped at the BIOS)
 0x81 - off
 0x82 - slightly "on-ner" than off, but my fans do not get to move. I can
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/w83791d linux-libre-2.6.39-gnu/Documentation/hwmon/w83791d
--- linux-libre-2.6.38-gnu/Documentation/hwmon/w83791d	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/w83791d	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 method of a single sysfs beep_mask file to a newer method using multiple
 *_beep files as described in .../Documentation/hwmon/sysfs-interface.
 
-A similar change has occured for the bitmap corresponding to the alarms. The
+A similar change has occurred for the bitmap corresponding to the alarms. The
 original legacy method used a single sysfs alarms file containing a bitmap
 of triggered alarms. The newer method uses multiple sysfs *_alarm files
 (again following the pattern described in sysfs-interface).
diff -druN linux-libre-2.6.38-gnu/Documentation/hwmon/w83795 linux-libre-2.6.39-gnu/Documentation/hwmon/w83795
--- linux-libre-2.6.38-gnu/Documentation/hwmon/w83795	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwmon/w83795	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,127 @@
+Kernel driver w83795
+====================
+
+Supported chips:
+  * Winbond/Nuvoton W83795G
+    Prefix: 'w83795g'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Available for download on nuvoton.com
+  * Winbond/Nuvoton W83795ADG
+    Prefix: 'w83795adg'
+    Addresses scanned: I2C 0x2c - 0x2f
+    Datasheet: Available for download on nuvoton.com
+
+Authors:
+    Wei Song (Nuvoton)
+    Jean Delvare <khali@linux-fr.org>
+
+
+Pin mapping
+-----------
+
+Here is a summary of the pin mapping for the W83795G and W83795ADG.
+This can be useful to convert data provided by board manufacturers
+into working libsensors configuration statements.
+
+    W83795G			|
+  Pin	| Name			| Register	| Sysfs attribute
+------------------------------------------------------------------
+   13	| VSEN1 (VCORE1)	| 10h		| in0
+   14	| VSEN2 (VCORE2)	| 11h		| in1
+   15	| VSEN3 (VCORE3)	| 12h		| in2
+   16	| VSEN4			| 13h		| in3
+   17	| VSEN5			| 14h		| in4
+   18	| VSEN6			| 15h		| in5
+   19	| VSEN7			| 16h		| in6
+   20	| VSEN8			| 17h		| in7
+   21	| VSEN9			| 18h		| in8
+   22	| VSEN10		| 19h		| in9
+   23	| VSEN11		| 1Ah		| in10
+   28	| VTT			| 1Bh		| in11
+   24	| 3VDD			| 1Ch		| in12
+   25	| 3VSB			| 1Dh		| in13
+   26	| VBAT			| 1Eh		| in14
+    3	| VSEN12/TR5		| 1Fh		| in15/temp5
+    4	| VSEN13/TR5		| 20h		| in16/temp6
+  5/  6	| VDSEN14/TR1/TD1	| 21h		| in17/temp1
+  7/  8	| VDSEN15/TR2/TD2	| 22h		| in18/temp2
+  9/ 10	| VDSEN16/TR3/TD3	| 23h		| in19/temp3
+ 11/ 12	| VDSEN17/TR4/TD4	| 24h		| in20/temp4
+   40	| FANIN1		| 2Eh		| fan1
+   42	| FANIN2		| 2Fh		| fan2
+   44	| FANIN3		| 30h		| fan3
+   46	| FANIN4		| 31h		| fan4
+   48	| FANIN5		| 32h		| fan5
+   50	| FANIN6		| 33h		| fan6
+   52	| FANIN7		| 34h		| fan7
+   54	| FANIN8		| 35h		| fan8
+   57	| FANIN9		| 36h		| fan9
+   58	| FANIN10		| 37h		| fan10
+   59	| FANIN11		| 38h		| fan11
+   60	| FANIN12		| 39h		| fan12
+   31	| FANIN13		| 3Ah		| fan13
+   35	| FANIN14		| 3Bh		| fan14
+   41	| FANCTL1		| 10h (bank 2)	| pwm1
+   43	| FANCTL2		| 11h (bank 2)	| pwm2
+   45	| FANCTL3		| 12h (bank 2)	| pwm3
+   47	| FANCTL4		| 13h (bank 2)	| pwm4
+   49	| FANCTL5		| 14h (bank 2)	| pwm5
+   51	| FANCTL6		| 15h (bank 2)	| pwm6
+   53	| FANCTL7		| 16h (bank 2)	| pwm7
+   55	| FANCTL8		| 17h (bank 2)	| pwm8
+ 29/ 30	| PECI/TSI (DTS1)	| 26h		| temp7
+ 29/ 30	| PECI/TSI (DTS2)	| 27h		| temp8
+ 29/ 30	| PECI/TSI (DTS3)	| 28h		| temp9
+ 29/ 30	| PECI/TSI (DTS4)	| 29h		| temp10
+ 29/ 30	| PECI/TSI (DTS5)	| 2Ah		| temp11
+ 29/ 30	| PECI/TSI (DTS6)	| 2Bh		| temp12
+ 29/ 30	| PECI/TSI (DTS7)	| 2Ch		| temp13
+ 29/ 30	| PECI/TSI (DTS8)	| 2Dh		| temp14
+   27	| CASEOPEN#		| 46h		| intrusion0
+
+    W83795ADG			|
+  Pin	| Name			| Register	| Sysfs attribute
+------------------------------------------------------------------
+   10	| VSEN1 (VCORE1)	| 10h		| in0
+   11	| VSEN2 (VCORE2)	| 11h		| in1
+   12	| VSEN3 (VCORE3)	| 12h		| in2
+   13	| VSEN4			| 13h		| in3
+   14	| VSEN5			| 14h		| in4
+   15	| VSEN6			| 15h		| in5
+   16	| VSEN7			| 16h		| in6
+   17	| VSEN8			| 17h		| in7
+   22	| VTT			| 1Bh		| in11
+   18	| 3VDD			| 1Ch		| in12
+   19	| 3VSB			| 1Dh		| in13
+   20	| VBAT			| 1Eh		| in14
+   48	| VSEN12/TR5		| 1Fh		| in15/temp5
+    1	| VSEN13/TR5		| 20h		| in16/temp6
+  2/  3	| VDSEN14/TR1/TD1	| 21h		| in17/temp1
+  4/  5	| VDSEN15/TR2/TD2	| 22h		| in18/temp2
+  6/  7	| VDSEN16/TR3/TD3	| 23h		| in19/temp3
+  8/  9	| VDSEN17/TR4/TD4	| 24h		| in20/temp4
+   32	| FANIN1		| 2Eh		| fan1
+   34	| FANIN2		| 2Fh		| fan2
+   36	| FANIN3		| 30h		| fan3
+   37	| FANIN4		| 31h		| fan4
+   38	| FANIN5		| 32h		| fan5
+   39	| FANIN6		| 33h		| fan6
+   40	| FANIN7		| 34h		| fan7
+   41	| FANIN8		| 35h		| fan8
+   43	| FANIN9		| 36h		| fan9
+   44	| FANIN10		| 37h		| fan10
+   45	| FANIN11		| 38h		| fan11
+   46	| FANIN12		| 39h		| fan12
+   24	| FANIN13		| 3Ah		| fan13
+   28	| FANIN14		| 3Bh		| fan14
+   33	| FANCTL1		| 10h (bank 2)	| pwm1
+   35	| FANCTL2		| 11h (bank 2)	| pwm2
+   23	| PECI (DTS1)		| 26h		| temp7
+   23	| PECI (DTS2)		| 27h		| temp8
+   23	| PECI (DTS3)		| 28h		| temp9
+   23	| PECI (DTS4)		| 29h		| temp10
+   23	| PECI (DTS5)		| 2Ah		| temp11
+   23	| PECI (DTS6)		| 2Bh		| temp12
+   23	| PECI (DTS7)		| 2Ch		| temp13
+   23	| PECI (DTS8)		| 2Dh		| temp14
+   21	| CASEOPEN#		| 46h		| intrusion0
diff -druN linux-libre-2.6.38-gnu/Documentation/hwspinlock.txt linux-libre-2.6.39-gnu/Documentation/hwspinlock.txt
--- linux-libre-2.6.38-gnu/Documentation/hwspinlock.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/hwspinlock.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,293 @@
+Hardware Spinlock Framework
+
+1. Introduction
+
+Hardware spinlock modules provide hardware assistance for synchronization
+and mutual exclusion between heterogeneous processors and those not operating
+under a single, shared operating system.
+
+For example, OMAP4 has dual Cortex-A9, dual Cortex-M3 and a C64x+ DSP,
+each of which is running a different Operating System (the master, A9,
+is usually running Linux and the slave processors, the M3 and the DSP,
+are running some flavor of RTOS).
+
+A generic hwspinlock framework allows platform-independent drivers to use
+the hwspinlock device in order to access data structures that are shared
+between remote processors, that otherwise have no alternative mechanism
+to accomplish synchronization and mutual exclusion operations.
+
+This is necessary, for example, for Inter-processor communications:
+on OMAP4, cpu-intensive multimedia tasks are offloaded by the host to the
+remote M3 and/or C64x+ slave processors (by an IPC subsystem called Syslink).
+
+To achieve fast message-based communications, a minimal kernel support
+is needed to deliver messages arriving from a remote processor to the
+appropriate user process.
+
+This communication is based on simple data structures that is shared between
+the remote processors, and access to it is synchronized using the hwspinlock
+module (remote processor directly places new messages in this shared data
+structure).
+
+A common hwspinlock interface makes it possible to have generic, platform-
+independent, drivers.
+
+2. User API
+
+  struct hwspinlock *hwspin_lock_request(void);
+   - dynamically assign an hwspinlock and return its address, or NULL
+     in case an unused hwspinlock isn't available. Users of this
+     API will usually want to communicate the lock's id to the remote core
+     before it can be used to achieve synchronization.
+     Can be called from an atomic context (this function will not sleep) but
+     not from within interrupt context.
+
+  struct hwspinlock *hwspin_lock_request_specific(unsigned int id);
+   - assign a specific hwspinlock id and return its address, or NULL
+     if that hwspinlock is already in use. Usually board code will
+     be calling this function in order to reserve specific hwspinlock
+     ids for predefined purposes.
+     Can be called from an atomic context (this function will not sleep) but
+     not from within interrupt context.
+
+  int hwspin_lock_free(struct hwspinlock *hwlock);
+   - free a previously-assigned hwspinlock; returns 0 on success, or an
+     appropriate error code on failure (e.g. -EINVAL if the hwspinlock
+     is already free).
+     Can be called from an atomic context (this function will not sleep) but
+     not from within interrupt context.
+
+  int hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int timeout);
+   - lock a previously-assigned hwspinlock with a timeout limit (specified in
+     msecs). If the hwspinlock is already taken, the function will busy loop
+     waiting for it to be released, but give up when the timeout elapses.
+     Upon a successful return from this function, preemption is disabled so
+     the caller must not sleep, and is advised to release the hwspinlock as
+     soon as possible, in order to minimize remote cores polling on the
+     hardware interconnect.
+     Returns 0 when successful and an appropriate error code otherwise (most
+     notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
+     The function will never sleep.
+
+  int hwspin_lock_timeout_irq(struct hwspinlock *hwlock, unsigned int timeout);
+   - lock a previously-assigned hwspinlock with a timeout limit (specified in
+     msecs). If the hwspinlock is already taken, the function will busy loop
+     waiting for it to be released, but give up when the timeout elapses.
+     Upon a successful return from this function, preemption and the local
+     interrupts are disabled, so the caller must not sleep, and is advised to
+     release the hwspinlock as soon as possible.
+     Returns 0 when successful and an appropriate error code otherwise (most
+     notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
+     The function will never sleep.
+
+  int hwspin_lock_timeout_irqsave(struct hwspinlock *hwlock, unsigned int to,
+							unsigned long *flags);
+   - lock a previously-assigned hwspinlock with a timeout limit (specified in
+     msecs). If the hwspinlock is already taken, the function will busy loop
+     waiting for it to be released, but give up when the timeout elapses.
+     Upon a successful return from this function, preemption is disabled,
+     local interrupts are disabled and their previous state is saved at the
+     given flags placeholder. The caller must not sleep, and is advised to
+     release the hwspinlock as soon as possible.
+     Returns 0 when successful and an appropriate error code otherwise (most
+     notably -ETIMEDOUT if the hwspinlock is still busy after timeout msecs).
+     The function will never sleep.
+
+  int hwspin_trylock(struct hwspinlock *hwlock);
+   - attempt to lock a previously-assigned hwspinlock, but immediately fail if
+     it is already taken.
+     Upon a successful return from this function, preemption is disabled so
+     caller must not sleep, and is advised to release the hwspinlock as soon as
+     possible, in order to minimize remote cores polling on the hardware
+     interconnect.
+     Returns 0 on success and an appropriate error code otherwise (most
+     notably -EBUSY if the hwspinlock was already taken).
+     The function will never sleep.
+
+  int hwspin_trylock_irq(struct hwspinlock *hwlock);
+   - attempt to lock a previously-assigned hwspinlock, but immediately fail if
+     it is already taken.
+     Upon a successful return from this function, preemption and the local
+     interrupts are disabled so caller must not sleep, and is advised to
+     release the hwspinlock as soon as possible.
+     Returns 0 on success and an appropriate error code otherwise (most
+     notably -EBUSY if the hwspinlock was already taken).
+     The function will never sleep.
+
+  int hwspin_trylock_irqsave(struct hwspinlock *hwlock, unsigned long *flags);
+   - attempt to lock a previously-assigned hwspinlock, but immediately fail if
+     it is already taken.
+     Upon a successful return from this function, preemption is disabled,
+     the local interrupts are disabled and their previous state is saved
+     at the given flags placeholder. The caller must not sleep, and is advised
+     to release the hwspinlock as soon as possible.
+     Returns 0 on success and an appropriate error code otherwise (most
+     notably -EBUSY if the hwspinlock was already taken).
+     The function will never sleep.
+
+  void hwspin_unlock(struct hwspinlock *hwlock);
+   - unlock a previously-locked hwspinlock. Always succeed, and can be called
+     from any context (the function never sleeps). Note: code should _never_
+     unlock an hwspinlock which is already unlocked (there is no protection
+     against this).
+
+  void hwspin_unlock_irq(struct hwspinlock *hwlock);
+   - unlock a previously-locked hwspinlock and enable local interrupts.
+     The caller should _never_ unlock an hwspinlock which is already unlocked.
+     Doing so is considered a bug (there is no protection against this).
+     Upon a successful return from this function, preemption and local
+     interrupts are enabled. This function will never sleep.
+
+  void
+  hwspin_unlock_irqrestore(struct hwspinlock *hwlock, unsigned long *flags);
+   - unlock a previously-locked hwspinlock.
+     The caller should _never_ unlock an hwspinlock which is already unlocked.
+     Doing so is considered a bug (there is no protection against this).
+     Upon a successful return from this function, preemption is reenabled,
+     and the state of the local interrupts is restored to the state saved at
+     the given flags. This function will never sleep.
+
+  int hwspin_lock_get_id(struct hwspinlock *hwlock);
+   - retrieve id number of a given hwspinlock. This is needed when an
+     hwspinlock is dynamically assigned: before it can be used to achieve
+     mutual exclusion with a remote cpu, the id number should be communicated
+     to the remote task with which we want to synchronize.
+     Returns the hwspinlock id number, or -EINVAL if hwlock is null.
+
+3. Typical usage
+
+#include <linux/hwspinlock.h>
+#include <linux/err.h>
+
+int hwspinlock_example1(void)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	/* dynamically assign a hwspinlock */
+	hwlock = hwspin_lock_request();
+	if (!hwlock)
+		...
+
+	id = hwspin_lock_get_id(hwlock);
+	/* probably need to communicate id to a remote processor now */
+
+	/* take the lock, spin for 1 sec if it's already taken */
+	ret = hwspin_lock_timeout(hwlock, 1000);
+	if (ret)
+		...
+
+	/*
+	 * we took the lock, do our thing now, but do NOT sleep
+	 */
+
+	/* release the lock */
+	hwspin_unlock(hwlock);
+
+	/* free the lock */
+	ret = hwspin_lock_free(hwlock);
+	if (ret)
+		...
+
+	return ret;
+}
+
+int hwspinlock_example2(void)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	/*
+	 * assign a specific hwspinlock id - this should be called early
+	 * by board init code.
+	 */
+	hwlock = hwspin_lock_request_specific(PREDEFINED_LOCK_ID);
+	if (!hwlock)
+		...
+
+	/* try to take it, but don't spin on it */
+	ret = hwspin_trylock(hwlock);
+	if (!ret) {
+		pr_info("lock is already taken\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * we took the lock, do our thing now, but do NOT sleep
+	 */
+
+	/* release the lock */
+	hwspin_unlock(hwlock);
+
+	/* free the lock */
+	ret = hwspin_lock_free(hwlock);
+	if (ret)
+		...
+
+	return ret;
+}
+
+
+4. API for implementors
+
+  int hwspin_lock_register(struct hwspinlock *hwlock);
+   - to be called from the underlying platform-specific implementation, in
+     order to register a new hwspinlock instance. Can be called from an atomic
+     context (this function will not sleep) but not from within interrupt
+     context. Returns 0 on success, or appropriate error code on failure.
+
+  struct hwspinlock *hwspin_lock_unregister(unsigned int id);
+   - to be called from the underlying vendor-specific implementation, in order
+     to unregister an existing (and unused) hwspinlock instance.
+     Can be called from an atomic context (will not sleep) but not from
+     within interrupt context.
+     Returns the address of hwspinlock on success, or NULL on error (e.g.
+     if the hwspinlock is sill in use).
+
+5. struct hwspinlock
+
+This struct represents an hwspinlock instance. It is registered by the
+underlying hwspinlock implementation using the hwspin_lock_register() API.
+
+/**
+ * struct hwspinlock - vendor-specific hwspinlock implementation
+ *
+ * @dev: underlying device, will be used with runtime PM api
+ * @ops: vendor-specific hwspinlock handlers
+ * @id: a global, unique, system-wide, index of the lock.
+ * @lock: initialized and used by hwspinlock core
+ * @owner: underlying implementation module, used to maintain module ref count
+ */
+struct hwspinlock {
+	struct device *dev;
+	const struct hwspinlock_ops *ops;
+	int id;
+	spinlock_t lock;
+	struct module *owner;
+};
+
+The underlying implementation is responsible to assign the dev, ops, id and
+owner members. The lock member, OTOH, is initialized and used by the hwspinlock
+core.
+
+6. Implementation callbacks
+
+There are three possible callbacks defined in 'struct hwspinlock_ops':
+
+struct hwspinlock_ops {
+	int (*trylock)(struct hwspinlock *lock);
+	void (*unlock)(struct hwspinlock *lock);
+	void (*relax)(struct hwspinlock *lock);
+};
+
+The first two callbacks are mandatory:
+
+The ->trylock() callback should make a single attempt to take the lock, and
+return 0 on failure and 1 on success. This callback may _not_ sleep.
+
+The ->unlock() callback releases the lock. It always succeed, and it, too,
+may _not_ sleep.
+
+The ->relax() callback is optional. It is called by hwspinlock core while
+spinning on a lock, and can be used by the underlying implementation to force
+a delay between two successive invocations of ->trylock(). It may _not_ sleep.
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-diolan-u2c linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-diolan-u2c
--- linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-diolan-u2c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-diolan-u2c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,26 @@
+Kernel driver i2c-diolan-u2c
+
+Supported adapters:
+  * Diolan U2C-12 I2C-USB adapter
+    Documentation:
+	http://www.diolan.com/i2c/u2c12.html
+
+Author: Guenter Roeck <guenter.roeck@ericsson.com>
+
+Description
+-----------
+
+This is the driver for the Diolan U2C-12 USB-I2C adapter.
+
+The Diolan U2C-12 I2C-USB Adapter provides a low cost solution to connect
+a computer to I2C slave devices using a USB interface. It also supports
+connectivity to SPI devices.
+
+This driver only supports the I2C interface of U2C-12. The driver does not use
+interrupts.
+
+
+Module parameters
+-----------------
+
+* frequency: I2C bus frequency
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-i801 linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-i801
--- linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-i801	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-i801	2011-05-19 00:06:34.000000000 -0400
@@ -16,8 +16,9 @@
   * Intel EP80579 (Tolapai)
   * Intel 82801JI (ICH10)
   * Intel 5/3400 Series (PCH)
-  * Intel Cougar Point (PCH)
+  * Intel 6 Series (PCH)
   * Intel Patsburg (PCH)
+  * Intel DH89xxCC (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-parport-light linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-parport-light
--- linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-parport-light	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-parport-light	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 
 This driver is a light version of i2c-parport. It doesn't depend        
 on the parport driver, and uses direct I/O access instead. This might be
-prefered on embedded systems where wasting memory for the clean but heavy
+preferred on embedded systems where wasting memory for the clean but heavy
 parport handling is not an option. The drawback is a reduced portability
 and the impossibility to daisy-chain other parallel port devices.                 
   
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-sis96x linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-sis96x
--- linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-sis96x	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-sis96x	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 
 (kernel versions later than 2.4.18 may fill in the "Unknown"s)
 
-If you cant see it please look on quirk_sis_96x_smbus
+If you can't see it please look on quirk_sis_96x_smbus
 (drivers/pci/quirks.c) (also if southbridge detection fails)
 
 I suspect that this driver could be made to work for the following SiS
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-taos-evm linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-taos-evm
--- linux-libre-2.6.38-gnu/Documentation/i2c/busses/i2c-taos-evm	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2c/busses/i2c-taos-evm	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 
 * TAOS TSL2550 EVM
 
-For addtional information on TAOS products, please see
+For additional information on TAOS products, please see
   http://www.taosinc.com/
 
 
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/instantiating-devices linux-libre-2.6.39-gnu/Documentation/i2c/instantiating-devices
--- linux-libre-2.6.38-gnu/Documentation/i2c/instantiating-devices	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2c/instantiating-devices	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,7 @@
 	(...)
 	i2c_adap = i2c_get_adapter(2);
 	memset(&i2c_info, 0, sizeof(struct i2c_board_info));
-	strlcpy(i2c_info.name, "isp1301_pnx", I2C_NAME_SIZE);
+	strlcpy(i2c_info.type, "isp1301_pnx", I2C_NAME_SIZE);
 	isp1301_i2c_client = i2c_new_probed_device(i2c_adap, &i2c_info,
 						   normal_i2c, NULL);
 	i2c_put_adapter(i2c_adap);
diff -druN linux-libre-2.6.38-gnu/Documentation/i2c/upgrading-clients linux-libre-2.6.39-gnu/Documentation/i2c/upgrading-clients
--- linux-libre-2.6.38-gnu/Documentation/i2c/upgrading-clients	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2c/upgrading-clients	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
 	return 0;
 }
 
-static int __devexit example_detach(struct i2c_client *client)
+static int example_detach(struct i2c_client *client)
 {
 	struct example_state *state = i2c_get_clientdata(client);
 
@@ -81,7 +81,7 @@
 		.name		= "example",
 	},
 	.attach_adapter = example_attach_adapter,
-	.detach_client	= __devexit_p(example_detach),
+	.detach_client	= example_detach,
 	.suspend	= example_suspend,
 	.resume		= example_resume,
 };
@@ -93,7 +93,7 @@
 The new style binding model will check against a list of supported
 devices and their associated address supplied by the code registering
 the busses. This means that the driver .attach_adapter and
-.detach_adapter methods can be removed, along with the addr_data,
+.detach_client methods can be removed, along with the addr_data,
 as follows:
 
 - static struct i2c_driver example_driver;
@@ -110,14 +110,14 @@
 
  static struct i2c_driver example_driver = {
 -	.attach_adapter = example_attach_adapter,
--	.detach_client	= __devexit_p(example_detach),
+-	.detach_client	= example_detach,
  }
 
 Add the probe and remove methods to the i2c_driver, as so:
 
  static struct i2c_driver example_driver = {
 +	.probe		= example_probe,
-+	.remove		= __devexit_p(example_remove),
++	.remove		= example_remove,
  }
 
 Change the example_attach method to accept the new parameters
@@ -199,8 +199,8 @@
 can also remove the ret variable as it is not not needed for
 any of the core functions.
 
-- static int __devexit example_detach(struct i2c_client *client)
-+ static int __devexit example_remove(struct i2c_client *client)
+- static int example_detach(struct i2c_client *client)
++ static int example_remove(struct i2c_client *client)
 {
 	struct example_state *state = i2c_get_clientdata(client);
 
@@ -253,7 +253,7 @@
 	return 0;
 }
 
-static int __devexit example_remove(struct i2c_client *client)
+static int example_remove(struct i2c_client *client)
 {
 	struct example_state *state = i2c_get_clientdata(client);
 
@@ -275,7 +275,7 @@
 	},
 	.id_table	= example_idtable,
 	.probe		= example_probe,
-	.remove		= __devexit_p(example_remove),
+	.remove		= example_remove,
 	.suspend	= example_suspend,
 	.resume		= example_resume,
 };
diff -druN linux-libre-2.6.38-gnu/Documentation/i2o/README linux-libre-2.6.39-gnu/Documentation/i2o/README
--- linux-libre-2.6.38-gnu/Documentation/i2o/README	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/i2o/README	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 BoxHill Corporation
 	Loan of initial FibreChannel disk array used for development work.
 
-European Comission
+European Commission
 	Funding the work done by the University of Helsinki
 
 SysKonnect
diff -druN linux-libre-2.6.38-gnu/Documentation/ia64/aliasing-test.c linux-libre-2.6.39-gnu/Documentation/ia64/aliasing-test.c
--- linux-libre-2.6.38-gnu/Documentation/ia64/aliasing-test.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ia64/aliasing-test.c	2011-05-19 00:06:34.000000000 -0400
@@ -177,7 +177,7 @@
 
 			/*
 			 * It's OK if the ROM is unreadable.  Maybe there
-			 * is no ROM, or some other error ocurred.  The
+			 * is no ROM, or some other error occurred.  The
 			 * important thing is that no MCA happened.
 			 */
 			if (rc > 0)
diff -druN linux-libre-2.6.38-gnu/Documentation/input/event-codes.txt linux-libre-2.6.39-gnu/Documentation/input/event-codes.txt
--- linux-libre-2.6.38-gnu/Documentation/input/event-codes.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/input/event-codes.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,262 @@
+The input protocol uses a map of types and codes to express input device values
+to userspace. This document describes the types and codes and how and when they
+may be used.
+
+A single hardware event generates multiple input events. Each input event
+contains the new value of a single data item. A special event type, EV_SYN, is
+used to separate input events into packets of input data changes occurring at
+the same moment in time. In the following, the term "event" refers to a single
+input event encompassing a type, code, and value.
+
+The input protocol is a stateful protocol. Events are emitted only when values
+of event codes have changed. However, the state is maintained within the Linux
+input subsystem; drivers do not need to maintain the state and may attempt to
+emit unchanged values without harm. Userspace may obtain the current state of
+event code values using the EVIOCG* ioctls defined in linux/input.h. The event
+reports supported by a device are also provided by sysfs in
+class/input/event*/device/capabilities/, and the properties of a device are
+provided in class/input/event*/device/properties.
+
+Types:
+==========
+Types are groupings of codes under a logical input construct. Each type has a
+set of applicable codes to be used in generating events. See the Codes section
+for details on valid codes for each type.
+
+* EV_SYN:
+  - Used as markers to separate events. Events may be separated in time or in
+    space, such as with the multitouch protocol.
+
+* EV_KEY:
+  - Used to describe state changes of keyboards, buttons, or other key-like
+    devices.
+
+* EV_REL:
+  - Used to describe relative axis value changes, e.g. moving the mouse 5 units
+    to the left.
+
+* EV_ABS:
+  - Used to describe absolute axis value changes, e.g. describing the
+    coordinates of a touch on a touchscreen.
+
+* EV_MSC:
+  - Used to describe miscellaneous input data that do not fit into other types.
+
+* EV_SW:
+  - Used to describe binary state input switches.
+
+* EV_LED:
+  - Used to turn LEDs on devices on and off.
+
+* EV_SND:
+  - Used to output sound to devices.
+
+* EV_REP:
+  - Used for autorepeating devices.
+
+* EV_FF:
+  - Used to send force feedback commands to an input device.
+
+* EV_PWR:
+  - A special type for power button and switch input.
+
+* EV_FF_STATUS:
+  - Used to receive force feedback device status.
+
+Codes:
+==========
+Codes define the precise type of event.
+
+EV_SYN:
+----------
+EV_SYN event values are undefined. Their usage is defined only by when they are
+sent in the evdev event stream.
+
+* SYN_REPORT:
+  - Used to synchronize and separate events into packets of input data changes
+    occurring at the same moment in time. For example, motion of a mouse may set
+    the REL_X and REL_Y values for one motion, then emit a SYN_REPORT. The next
+    motion will emit more REL_X and REL_Y values and send another SYN_REPORT.
+
+* SYN_CONFIG:
+  - TBD
+
+* SYN_MT_REPORT:
+  - Used to synchronize and separate touch events. See the
+    multi-touch-protocol.txt document for more information.
+
+* SYN_DROPPED:
+  - Used to indicate buffer overrun in the evdev client's event queue.
+    Client should ignore all events up to and including next SYN_REPORT
+    event and query the device (using EVIOCG* ioctls) to obtain its
+    current state.
+
+EV_KEY:
+----------
+EV_KEY events take the form KEY_<name> or BTN_<name>. For example, KEY_A is used
+to represent the 'A' key on a keyboard. When a key is depressed, an event with
+the key's code is emitted with value 1. When the key is released, an event is
+emitted with value 0. Some hardware send events when a key is repeated. These
+events have a value of 2. In general, KEY_<name> is used for keyboard keys, and
+BTN_<name> is used for other types of momentary switch events.
+
+A few EV_KEY codes have special meanings:
+
+* BTN_TOOL_<name>:
+  - These codes are used in conjunction with input trackpads, tablets, and
+    touchscreens. These devices may be used with fingers, pens, or other tools.
+    When an event occurs and a tool is used, the corresponding BTN_TOOL_<name>
+    code should be set to a value of 1. When the tool is no longer interacting
+    with the input device, the BTN_TOOL_<name> code should be reset to 0. All
+    trackpads, tablets, and touchscreens should use at least one BTN_TOOL_<name>
+    code when events are generated.
+
+* BTN_TOUCH:
+    BTN_TOUCH is used for touch contact. While an input tool is determined to be
+    within meaningful physical contact, the value of this property must be set
+    to 1. Meaningful physical contact may mean any contact, or it may mean
+    contact conditioned by an implementation defined property. For example, a
+    touchpad may set the value to 1 only when the touch pressure rises above a
+    certain value. BTN_TOUCH may be combined with BTN_TOOL_<name> codes. For
+    example, a pen tablet may set BTN_TOOL_PEN to 1 and BTN_TOUCH to 0 while the
+    pen is hovering over but not touching the tablet surface.
+
+Note: For appropriate function of the legacy mousedev emulation driver,
+BTN_TOUCH must be the first evdev code emitted in a synchronization frame.
+
+Note: Historically a touch device with BTN_TOOL_FINGER and BTN_TOUCH was
+interpreted as a touchpad by userspace, while a similar device without
+BTN_TOOL_FINGER was interpreted as a touchscreen. For backwards compatibility
+with current userspace it is recommended to follow this distinction. In the
+future, this distinction will be deprecated and the device properties ioctl
+EVIOCGPROP, defined in linux/input.h, will be used to convey the device type.
+
+* BTN_TOOL_FINGER, BTN_TOOL_DOUBLETAP, BTN_TOOL_TRIPLETAP, BTN_TOOL_QUADTAP:
+  - These codes denote one, two, three, and four finger interaction on a
+    trackpad or touchscreen. For example, if the user uses two fingers and moves
+    them on the touchpad in an effort to scroll content on screen,
+    BTN_TOOL_DOUBLETAP should be set to value 1 for the duration of the motion.
+    Note that all BTN_TOOL_<name> codes and the BTN_TOUCH code are orthogonal in
+    purpose. A trackpad event generated by finger touches should generate events
+    for one code from each group. At most only one of these BTN_TOOL_<name>
+    codes should have a value of 1 during any synchronization frame.
+
+Note: Historically some drivers emitted multiple of the finger count codes with
+a value of 1 in the same synchronization frame. This usage is deprecated.
+
+Note: In multitouch drivers, the input_mt_report_finger_count() function should
+be used to emit these codes. Please see multi-touch-protocol.txt for details.
+
+EV_REL:
+----------
+EV_REL events describe relative changes in a property. For example, a mouse may
+move to the left by a certain number of units, but its absolute position in
+space is unknown. If the absolute position is known, EV_ABS codes should be used
+instead of EV_REL codes.
+
+A few EV_REL codes have special meanings:
+
+* REL_WHEEL, REL_HWHEEL:
+  - These codes are used for vertical and horizontal scroll wheels,
+    respectively.
+
+EV_ABS:
+----------
+EV_ABS events describe absolute changes in a property. For example, a touchpad
+may emit coordinates for a touch location.
+
+A few EV_ABS codes have special meanings:
+
+* ABS_DISTANCE:
+  - Used to describe the distance of a tool from an interaction surface. This
+    event should only be emitted while the tool is hovering, meaning in close
+    proximity of the device and while the value of the BTN_TOUCH code is 0. If
+    the input device may be used freely in three dimensions, consider ABS_Z
+    instead.
+
+* ABS_MT_<name>:
+  - Used to describe multitouch input events. Please see
+    multi-touch-protocol.txt for details.
+
+EV_SW:
+----------
+EV_SW events describe stateful binary switches. For example, the SW_LID code is
+used to denote when a laptop lid is closed.
+
+Upon binding to a device or resuming from suspend, a driver must report
+the current switch state. This ensures that the device, kernel, and userspace
+state is in sync.
+
+Upon resume, if the switch state is the same as before suspend, then the input
+subsystem will filter out the duplicate switch state reports. The driver does
+not need to keep the state of the switch at any time.
+
+EV_MSC:
+----------
+EV_MSC events are used for input and output events that do not fall under other
+categories.
+
+EV_LED:
+----------
+EV_LED events are used for input and output to set and query the state of
+various LEDs on devices.
+
+EV_REP:
+----------
+EV_REP events are used for specifying autorepeating events.
+
+EV_SND:
+----------
+EV_SND events are used for sending sound commands to simple sound output
+devices.
+
+EV_FF:
+----------
+EV_FF events are used to initialize a force feedback capable device and to cause
+such device to feedback.
+
+EV_PWR:
+----------
+EV_PWR events are a special type of event used specifically for power
+mangement. Its usage is not well defined. To be addressed later.
+
+Guidelines:
+==========
+The guidelines below ensure proper single-touch and multi-finger functionality.
+For multi-touch functionality, see the multi-touch-protocol.txt document for
+more information.
+
+Mice:
+----------
+REL_{X,Y} must be reported when the mouse moves. BTN_LEFT must be used to report
+the primary button press. BTN_{MIDDLE,RIGHT,4,5,etc.} should be used to report
+further buttons of the device. REL_WHEEL and REL_HWHEEL should be used to report
+scroll wheel events where available.
+
+Touchscreens:
+----------
+ABS_{X,Y} must be reported with the location of the touch. BTN_TOUCH must be
+used to report when a touch is active on the screen.
+BTN_{MOUSE,LEFT,MIDDLE,RIGHT} must not be reported as the result of touch
+contact. BTN_TOOL_<name> events should be reported where possible.
+
+Trackpads:
+----------
+Legacy trackpads that only provide relative position information must report
+events like mice described above.
+
+Trackpads that provide absolute touch position must report ABS_{X,Y} for the
+location of the touch. BTN_TOUCH should be used to report when a touch is active
+on the trackpad. Where multi-finger support is available, BTN_TOOL_<name> should
+be used to report the number of touches active on the trackpad.
+
+Tablets:
+----------
+BTN_TOOL_<name> events must be reported when a stylus or other tool is active on
+the tablet. ABS_{X,Y} must be reported with the location of the tool. BTN_TOUCH
+should be used to report when the tool is in contact with the tablet.
+BTN_{STYLUS,STYLUS2} should be used to report buttons on the tool itself. Any
+button may be used for buttons on the tablet except BTN_{MOUSE,LEFT}.
+BTN_{0,1,2,etc} are good generic codes for unlabeled buttons. Do not use
+meaningful buttons, like BTN_FORWARD, unless the button is labeled for that
+purpose on the device.
diff -druN linux-libre-2.6.38-gnu/Documentation/input/joystick-parport.txt linux-libre-2.6.39-gnu/Documentation/input/joystick-parport.txt
--- linux-libre-2.6.38-gnu/Documentation/input/joystick-parport.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/input/joystick-parport.txt	2011-05-19 00:06:34.000000000 -0400
@@ -272,7 +272,7 @@
 
   Also, the connection is a bit more complex. You'll need a bunch of diodes,
 and one pullup resistor. First, you connect the Directions and the button
-the same as for db9, however with the diodes inbetween.
+the same as for db9, however with the diodes between.
 
 	    Diodes
 (pin 2) -----|<|----> Up
diff -druN linux-libre-2.6.38-gnu/Documentation/input/rotary-encoder.txt linux-libre-2.6.39-gnu/Documentation/input/rotary-encoder.txt
--- linux-libre-2.6.38-gnu/Documentation/input/rotary-encoder.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/input/rotary-encoder.txt	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
 
 d) Falling edge on channel B, channel A in low state
 	Parking position. If the encoder enters this state, a full transition
-	should have happend, unless it flipped back on half the way. The
+	should have happened, unless it flipped back on half the way. The
 	'armed' state tells us about that.
 
 2. Platform requirements
diff -druN linux-libre-2.6.38-gnu/Documentation/input/walkera0701.txt linux-libre-2.6.39-gnu/Documentation/input/walkera0701.txt
--- linux-libre-2.6.38-gnu/Documentation/input/walkera0701.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/input/walkera0701.txt	2011-05-19 00:06:34.000000000 -0400
@@ -77,7 +77,7 @@
 
 24 bin+oct values + 1 bin value = 24*4+1 bits  = 97 bits
 
-(Warning, pulses on ACK ar inverted by transistor, irq is rised up on sync
+(Warning, pulses on ACK are inverted by transistor, irq is raised up on sync
 to bin change or octal value to bin change).
 
 Binary data representations:
diff -druN linux-libre-2.6.38-gnu/Documentation/ioctl/ioctl-number.txt linux-libre-2.6.39-gnu/Documentation/ioctl/ioctl-number.txt
--- linux-libre-2.6.38-gnu/Documentation/ioctl/ioctl-number.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/ioctl/ioctl-number.txt	2011-05-19 00:06:34.000000000 -0400
@@ -133,6 +133,7 @@
 'H'	C0-DF	net/bluetooth/hidp/hidp.h	conflict!
 'H'	C0-DF	net/bluetooth/cmtp/cmtp.h	conflict!
 'H'	C0-DF	net/bluetooth/bnep/bnep.h	conflict!
+'H'	F1	linux/hid-roccat.h	<mailto:erazor_de@users.sourceforge.net>
 'I'	all	linux/isdn.h		conflict!
 'I'	00-0F	drivers/isdn/divert/isdn_divert.h	conflict!
 'I'	40-4F	linux/mISDNif.h		conflict!
@@ -272,6 +273,7 @@
 'z'	40-7F				CAN bus card	conflict!
 					<mailto:oe@port.de>
 'z'	10-4F	drivers/s390/crypto/zcrypt_api.h	conflict!
+'|'	00-7F	linux/media.h
 0x80	00-1F	linux/fb.h
 0x89	00-06	arch/x86/include/asm/sockios.h
 0x89	0B-DF	linux/sockios.h
diff -druN linux-libre-2.6.38-gnu/Documentation/iostats.txt linux-libre-2.6.39-gnu/Documentation/iostats.txt
--- linux-libre-2.6.38-gnu/Documentation/iostats.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/iostats.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,6 @@
 I/O statistics fields
 ---------------
 
-Last modified Sep 30, 2003
-
 Since 2.4.20 (and some versions before, with patches), and 2.5.45,
 more extensive disk statistics have been introduced to help measure disk
 activity. Tools such as sar and iostat typically interpret these and do
@@ -46,11 +44,12 @@
 By contrast, in 2.6 if you look at /sys/block/hda/stat, you'll
 find just the eleven fields, beginning with 446216.  If you look at
 /proc/diskstats, the eleven fields will be preceded by the major and
-minor device numbers, and device name.  Each of these formats provide
+minor device numbers, and device name.  Each of these formats provides
 eleven fields of statistics, each meaning exactly the same things.
 All fields except field 9 are cumulative since boot.  Field 9 should
-go to zero as I/Os complete; all others only increase.  Yes, these are
-32 bit unsigned numbers, and on a very busy or long-lived system they
+go to zero as I/Os complete; all others only increase (unless they
+overflow and wrap).  Yes, these are (32-bit or 64-bit) unsigned long
+(native word size) numbers, and on a very busy or long-lived system they
 may wrap. Applications should be prepared to deal with that; unless
 your observations are measured in large numbers of minutes or hours,
 they should not wrap twice before you notice them.
@@ -96,11 +95,11 @@
 read I/Os issued per partition should equal those made to the disks ...
 but due to the lack of locking it may only be very close.
 
-In 2.6, there are counters for each cpu, which made the lack of locking
-almost a non-issue.  When the statistics are read, the per-cpu counters
-are summed (possibly overflowing the unsigned 32-bit variable they are
+In 2.6, there are counters for each CPU, which make the lack of locking
+almost a non-issue.  When the statistics are read, the per-CPU counters
+are summed (possibly overflowing the unsigned long variable they are
 summed to) and the result given to the user.  There is no convenient
-user interface for accessing the per-cpu counters themselves.
+user interface for accessing the per-CPU counters themselves.
 
 Disks vs Partitions
 -------------------
diff -druN linux-libre-2.6.38-gnu/Documentation/irqflags-tracing.txt linux-libre-2.6.39-gnu/Documentation/irqflags-tracing.txt
--- linux-libre-2.6.38-gnu/Documentation/irqflags-tracing.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/irqflags-tracing.txt	2011-05-19 00:06:34.000000000 -0400
@@ -53,5 +53,5 @@
 turn itself off. I.e. the lock validator will still be reliable. There
 should be no crashes due to irq-tracing bugs. (except if the assembly
 changes break other code by modifying conditions or registers that
-shouldnt be)
+shouldn't be)
 
diff -druN linux-libre-2.6.38-gnu/Documentation/isdn/INTERFACE.CAPI linux-libre-2.6.39-gnu/Documentation/isdn/INTERFACE.CAPI
--- linux-libre-2.6.38-gnu/Documentation/isdn/INTERFACE.CAPI	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/isdn/INTERFACE.CAPI	2011-05-19 00:06:34.000000000 -0400
@@ -240,7 +240,7 @@
 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.
+sure it is big enough to accommodate the resulting CAPI message.
 
 
 5. Lower Layer Interface Functions
diff -druN linux-libre-2.6.38-gnu/Documentation/kbuild/kbuild.txt linux-libre-2.6.39-gnu/Documentation/kbuild/kbuild.txt
--- linux-libre-2.6.38-gnu/Documentation/kbuild/kbuild.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kbuild/kbuild.txt	2011-05-19 00:06:34.000000000 -0400
@@ -26,11 +26,11 @@
 
 AFLAGS_MODULE
 --------------------------------------------------
-Addtional module specific options to use for $(AS).
+Additional module specific options to use for $(AS).
 
 AFLAGS_KERNEL
 --------------------------------------------------
-Addtional options for $(AS) when used for assembler
+Additional options for $(AS) when used for assembler
 code for code that is compiled as built-in.
 
 KCFLAGS
@@ -39,12 +39,12 @@
 
 CFLAGS_KERNEL
 --------------------------------------------------
-Addtional options for $(CC) when used to compile
+Additional options for $(CC) when used to compile
 code that is compiled as built-in.
 
 CFLAGS_MODULE
 --------------------------------------------------
-Addtional module specific options to use for $(CC).
+Additional module specific options to use for $(CC).
 
 LDFLAGS_MODULE
 --------------------------------------------------
@@ -146,7 +146,7 @@
 INSTALL_MOD_STRIP, if defined, will cause modules to be
 stripped after they are installed.  If INSTALL_MOD_STRIP is '1', then
 the default option --strip-debug will be used.  Otherwise,
-INSTALL_MOD_STRIP will used as the options to the strip command.
+INSTALL_MOD_STRIP value will be used as the options to the strip command.
 
 INSTALL_FW_PATH
 --------------------------------------------------
@@ -196,3 +196,8 @@
 To get all available archs you can also specify all. E.g.:
 
     $ make ALLSOURCE_ARCHS=all tags
+
+KBUILD_ENABLE_EXTRA_GCC_CHECKS
+--------------------------------------------------
+If enabled over the make command line with "W=1", it turns on additional
+gcc -W... options for more extensive build-time checking.
diff -druN linux-libre-2.6.38-gnu/Documentation/kbuild/makefiles.txt linux-libre-2.6.39-gnu/Documentation/kbuild/makefiles.txt
--- linux-libre-2.6.38-gnu/Documentation/kbuild/makefiles.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kbuild/makefiles.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1325,7 +1325,8 @@
 	If this variable is specified, will cause modules to be stripped
 	after they are installed.  If INSTALL_MOD_STRIP is '1', then the
 	default option --strip-debug will be used.  Otherwise,
-	INSTALL_MOD_STRIP will used as the option(s) to the strip command.
+	INSTALL_MOD_STRIP value will be used as the option(s) to the strip
+	command.
 
 
 === 9 Makefile language
diff -druN linux-libre-2.6.38-gnu/Documentation/kernel-parameters.txt linux-libre-2.6.39-gnu/Documentation/kernel-parameters.txt
--- linux-libre-2.6.38-gnu/Documentation/kernel-parameters.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kernel-parameters.txt	2011-05-19 00:06:34.000000000 -0400
@@ -626,6 +626,10 @@
 	disable=	[IPV6]
 			See Documentation/networking/ipv6.txt.
 
+	disable_ddw     [PPC/PSERIES]
+			Disable Dynamic DMA Window support. Use this if
+			to workaround buggy firmware.
+
 	disable_ipv6=	[IPV6]
 			See Documentation/networking/ipv6.txt.
 
@@ -695,7 +699,7 @@
 	ekgdboc=	[X86,KGDB] Allow early kernel console debugging
 			ekgdboc=kbd
 
-			This is desgined to be used in conjunction with
+			This is designed to be used in conjunction with
 			the boot argument: earlyprintk=vga
 
 	edd=		[EDD]
@@ -868,6 +872,12 @@
 			       If specified, z/VM IUCV HVC accepts connections
 			       from listed z/VM user IDs only.
 
+	keep_bootcon	[KNL]
+			Do not unregister boot console at start. This is only
+			useful for debugging when something happens in the window
+			between unregistering the boot console and initializing
+			the real console.
+
 	i2c_bus=	[HW] Override the default board specific I2C bus speed
 			     or register an additional I2C bus that is not
 			     registered from board initialization code.
@@ -1580,16 +1590,25 @@
 			of returning the full 64-bit number.
 			The default is to return 64-bit inode numbers.
 
+	nfs.nfs4_disable_idmapping=
+			[NFSv4] When set, this option disables the NFSv4
+			idmapper on the client, but only if the mount
+			is using the 'sec=sys' security flavour. This may
+			make migration from legacy NFSv2/v3 systems easier
+			provided that the server has the appropriate support.
+			The default is to always enable NFSv4 idmapping.
+
 	nmi_debug=	[KNL,AVR32,SH] Specify one or more actions to take
 			when a NMI is triggered.
 			Format: [state][,regs][,debounce][,die]
 
 	nmi_watchdog=	[KNL,BUGS=X86] Debugging features for SMP kernels
-			Format: [panic,][num]
+			Format: [panic,][nopanic,][num]
 			Valid num: 0
 			0 - turn nmi_watchdog off
 			When panic is specified, panic when an NMI watchdog
-			timeout occurs.
+			timeout occurs (or 'nopanic' to override the opposite
+			default).
 			This is useful when you use a panic=... timeout and
 			need the box quickly up again.
 
@@ -1813,10 +1832,17 @@
 				perfmon on Intel CPUs instead of the
 				CPU specific event set.
 
+	oops=panic	Always panic on oopses. Default is to just kill the
+			process, but there is a small probability of
+			deadlocking the machine.
+			This will also cause panics on machine check exceptions.
+			Useful together with panic=30 to trigger a reboot.
+
 	OSS		[HW,OSS]
 			See Documentation/sound/oss/oss-parameters.txt
 
-	panic=		[KNL] Kernel behaviour on panic
+	panic=		[KNL] Kernel behaviour on panic: delay <timeout>
+			seconds before rebooting
 			Format: <timeout>
 
 	parkbd.port=	[HW] Parallel port number the keyboard adapter is
@@ -2319,6 +2345,7 @@
 
 	softlockup_panic=
 			[KNL] Should the soft-lockup detector generate panics.
+			Format: <integer>
 
 	sonypi.*=	[HW] Sony Programmable I/O Control Device driver
 			See Documentation/sonypi.txt
@@ -2444,11 +2471,15 @@
 			<deci-seconds>: poll all this frequency
 			0: no polling (default)
 
+	threadirqs	[KNL]
+			Force threading of all interrupt handlers except those
+			marked explicitely IRQF_NO_THREAD.
+
 	topology=	[S390]
 			Format: {off | on}
 			Specify if the kernel should make use of the cpu
-			topology informations if the hardware supports these.
-			The scheduler will make use of these informations and
+			topology information if the hardware supports this.
+			The scheduler will make use of this information and
 			e.g. base its process migration decisions on it.
 			Default is on.
 
@@ -2501,8 +2532,7 @@
 			reported either.
 
 	unknown_nmi_panic
-			[X86]
-			Set unknown_nmi_panic=1 early on boot.
+			[X86] Cause panic on unknown NMI.
 
 	usbcore.autosuspend=
 			[USB] The autosuspend time delay (in seconds) used
diff -druN linux-libre-2.6.38-gnu/Documentation/keys-request-key.txt linux-libre-2.6.39-gnu/Documentation/keys-request-key.txt
--- linux-libre-2.6.38-gnu/Documentation/keys-request-key.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/keys-request-key.txt	2011-05-19 00:06:34.000000000 -0400
@@ -127,14 +127,15 @@
 of them, and (b) it requires the same UID/GID/Groups all the way through.
 
 
-======================
-NEGATIVE INSTANTIATION
-======================
+====================================
+NEGATIVE INSTANTIATION AND REJECTION
+====================================
 
 Rather than instantiating a key, it is possible for the possessor of an
 authorisation key to negatively instantiate a key that's under construction.
 This is a short duration placeholder that causes any attempt at re-requesting
-the key whilst it exists to fail with error ENOKEY.
+the key whilst it exists to fail with error ENOKEY if negated or the specified
+error if rejected.
 
 This is provided to prevent excessive repeated spawning of /sbin/request-key
 processes for a key that will never be obtainable.
diff -druN linux-libre-2.6.38-gnu/Documentation/keys.txt linux-libre-2.6.39-gnu/Documentation/keys.txt
--- linux-libre-2.6.38-gnu/Documentation/keys.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/keys.txt	2011-05-19 00:06:34.000000000 -0400
@@ -637,6 +637,9 @@
 	long keyctl(KEYCTL_INSTANTIATE, key_serial_t key,
 		    const void *payload, size_t plen,
 		    key_serial_t keyring);
+	long keyctl(KEYCTL_INSTANTIATE_IOV, key_serial_t key,
+		    const struct iovec *payload_iov, unsigned ioc,
+		    key_serial_t keyring);
 
      If the kernel calls back to userspace to complete the instantiation of a
      key, userspace should use this call to supply data for the key before the
@@ -652,11 +655,16 @@
 
      The payload and plen arguments describe the payload data as for add_key().
 
+     The payload_iov and ioc arguments describe the payload data in an iovec
+     array instead of a single buffer.
+
 
  (*) Negatively instantiate a partially constructed key.
 
 	long keyctl(KEYCTL_NEGATE, key_serial_t key,
 		    unsigned timeout, key_serial_t keyring);
+	long keyctl(KEYCTL_REJECT, key_serial_t key,
+		    unsigned timeout, unsigned error, key_serial_t keyring);
 
      If the kernel calls back to userspace to complete the instantiation of a
      key, userspace should use this call mark the key as negative before the
@@ -669,6 +677,10 @@
      that keyring, however all the constraints applying in KEYCTL_LINK apply in
      this case too.
 
+     If the key is rejected, future searches for it will return the specified
+     error code until the rejected key expires.  Negating the key is the same
+     as rejecting the key with ENOKEY as the error code.
+
 
  (*) Set the default request-key destination keyring.
 
@@ -1062,6 +1074,13 @@
      viable.
 
 
+ (*) int (*vet_description)(const char *description);
+
+     This optional method is called to vet a key description.  If the key type
+     doesn't approve of the key description, it may return an error, otherwise
+     it should return 0.
+
+
  (*) int (*instantiate)(struct key *key, const void *data, size_t datalen);
 
      This method is called to attach a payload to a key during construction.
@@ -1231,10 +1250,11 @@
 example, the KDE desktop manager).
 
 The program (or whatever it calls) should finish construction of the key by
-calling KEYCTL_INSTANTIATE, which also permits it to cache the key in one of
-the keyrings (probably the session ring) before returning. Alternatively, the
-key can be marked as negative with KEYCTL_NEGATE; this also permits the key to
-be cached in one of the keyrings.
+calling KEYCTL_INSTANTIATE or KEYCTL_INSTANTIATE_IOV, which also permits it to
+cache the key in one of the keyrings (probably the session ring) before
+returning.  Alternatively, the key can be marked as negative with KEYCTL_NEGATE
+or KEYCTL_REJECT; this also permits the key to be cached in one of the
+keyrings.
 
 If it returns with the key remaining in the unconstructed state, the key will
 be marked as being negative, it will be added to the session keyring, and an
diff -druN linux-libre-2.6.38-gnu/Documentation/kmemleak.txt linux-libre-2.6.39-gnu/Documentation/kmemleak.txt
--- linux-libre-2.6.38-gnu/Documentation/kmemleak.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kmemleak.txt	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 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.
+Kmemleak is supported on x86, arm, powerpc, sparc, sh, microblaze and tile.
 
 Usage
 -----
@@ -178,5 +179,4 @@
 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.
+Page allocations and ioremap are not tracked.
diff -druN linux-libre-2.6.38-gnu/Documentation/kref.txt linux-libre-2.6.39-gnu/Documentation/kref.txt
--- linux-libre-2.6.38-gnu/Documentation/kref.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kref.txt	2011-05-19 00:06:34.000000000 -0400
@@ -156,7 +156,7 @@
 	struct my_data *entry = NULL;
 	mutex_lock(&mutex);
 	if (!list_empty(&q)) {
-		entry = container_of(q.next, struct my_q_entry, link);
+		entry = container_of(q.next, struct my_data, link);
 		kref_get(&entry->refcount);
 	}
 	mutex_unlock(&mutex);
diff -druN linux-libre-2.6.38-gnu/Documentation/kvm/api.txt linux-libre-2.6.39-gnu/Documentation/kvm/api.txt
--- linux-libre-2.6.38-gnu/Documentation/kvm/api.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kvm/api.txt	2011-05-19 00:06:34.000000000 -0400
@@ -166,7 +166,7 @@
 
 This ioctl is obsolete and has been removed.
 
-4.6 KVM_CREATE_VCPU
+4.7 KVM_CREATE_VCPU
 
 Capability: basic
 Architectures: all
@@ -177,7 +177,7 @@
 This API adds a vcpu to a virtual machine.  The vcpu id is a small integer
 in the range [0, max_vcpus).
 
-4.7 KVM_GET_DIRTY_LOG (vm ioctl)
+4.8 KVM_GET_DIRTY_LOG (vm ioctl)
 
 Capability: basic
 Architectures: x86
@@ -200,7 +200,7 @@
 memory slot.  Ensure the entire structure is cleared to avoid padding
 issues.
 
-4.8 KVM_SET_MEMORY_ALIAS
+4.9 KVM_SET_MEMORY_ALIAS
 
 Capability: basic
 Architectures: x86
@@ -210,7 +210,7 @@
 
 This ioctl is obsolete and has been removed.
 
-4.9 KVM_RUN
+4.10 KVM_RUN
 
 Capability: basic
 Architectures: all
@@ -226,7 +226,7 @@
 KVM_GET_VCPU_MMAP_SIZE.  The parameter block is formatted as a 'struct
 kvm_run' (see below).
 
-4.10 KVM_GET_REGS
+4.11 KVM_GET_REGS
 
 Capability: basic
 Architectures: all
@@ -246,7 +246,7 @@
 	__u64 rip, rflags;
 };
 
-4.11 KVM_SET_REGS
+4.12 KVM_SET_REGS
 
 Capability: basic
 Architectures: all
@@ -258,7 +258,7 @@
 
 See KVM_GET_REGS for the data structure.
 
-4.12 KVM_GET_SREGS
+4.13 KVM_GET_SREGS
 
 Capability: basic
 Architectures: x86
@@ -283,7 +283,7 @@
 one bit may be set.  This interrupt has been acknowledged by the APIC
 but not yet injected into the cpu core.
 
-4.13 KVM_SET_SREGS
+4.14 KVM_SET_SREGS
 
 Capability: basic
 Architectures: x86
@@ -294,7 +294,7 @@
 Writes special registers into the vcpu.  See KVM_GET_SREGS for the
 data structures.
 
-4.14 KVM_TRANSLATE
+4.15 KVM_TRANSLATE
 
 Capability: basic
 Architectures: x86
@@ -317,7 +317,7 @@
 	__u8  pad[5];
 };
 
-4.15 KVM_INTERRUPT
+4.16 KVM_INTERRUPT
 
 Capability: basic
 Architectures: x86, ppc
@@ -365,7 +365,7 @@
 Note that any value for 'irq' other than the ones stated above is invalid
 and incurs unexpected behavior.
 
-4.16 KVM_DEBUG_GUEST
+4.17 KVM_DEBUG_GUEST
 
 Capability: basic
 Architectures: none
@@ -375,7 +375,7 @@
 
 Support for this has been removed.  Use KVM_SET_GUEST_DEBUG instead.
 
-4.17 KVM_GET_MSRS
+4.18 KVM_GET_MSRS
 
 Capability: basic
 Architectures: x86
@@ -403,7 +403,7 @@
 size of the entries array) and the 'index' member of each array entry.
 kvm will fill in the 'data' member.
 
-4.18 KVM_SET_MSRS
+4.19 KVM_SET_MSRS
 
 Capability: basic
 Architectures: x86
@@ -418,7 +418,7 @@
 size of the entries array), and the 'index' and 'data' members of each
 array entry.
 
-4.19 KVM_SET_CPUID
+4.20 KVM_SET_CPUID
 
 Capability: basic
 Architectures: x86
@@ -446,7 +446,7 @@
 	struct kvm_cpuid_entry entries[0];
 };
 
-4.20 KVM_SET_SIGNAL_MASK
+4.21 KVM_SET_SIGNAL_MASK
 
 Capability: basic
 Architectures: x86
@@ -468,7 +468,7 @@
 	__u8  sigset[0];
 };
 
-4.21 KVM_GET_FPU
+4.22 KVM_GET_FPU
 
 Capability: basic
 Architectures: x86
@@ -493,7 +493,7 @@
 	__u32 pad2;
 };
 
-4.22 KVM_SET_FPU
+4.23 KVM_SET_FPU
 
 Capability: basic
 Architectures: x86
@@ -518,7 +518,7 @@
 	__u32 pad2;
 };
 
-4.23 KVM_CREATE_IRQCHIP
+4.24 KVM_CREATE_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -531,7 +531,7 @@
 local APIC.  IRQ routing for GSIs 0-15 is set to both PIC and IOAPIC; GSI 16-23
 only go to the IOAPIC.  On ia64, a IOSAPIC is created.
 
-4.24 KVM_IRQ_LINE
+4.25 KVM_IRQ_LINE
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -552,7 +552,7 @@
 	__u32 level;           /* 0 or 1 */
 };
 
-4.25 KVM_GET_IRQCHIP
+4.26 KVM_GET_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -573,7 +573,7 @@
 	} chip;
 };
 
-4.26 KVM_SET_IRQCHIP
+4.27 KVM_SET_IRQCHIP
 
 Capability: KVM_CAP_IRQCHIP
 Architectures: x86, ia64
@@ -594,7 +594,7 @@
 	} chip;
 };
 
-4.27 KVM_XEN_HVM_CONFIG
+4.28 KVM_XEN_HVM_CONFIG
 
 Capability: KVM_CAP_XEN_HVM
 Architectures: x86
@@ -618,7 +618,7 @@
 	__u8 pad2[30];
 };
 
-4.27 KVM_GET_CLOCK
+4.29 KVM_GET_CLOCK
 
 Capability: KVM_CAP_ADJUST_CLOCK
 Architectures: x86
@@ -636,7 +636,7 @@
 	__u32 pad[9];
 };
 
-4.28 KVM_SET_CLOCK
+4.30 KVM_SET_CLOCK
 
 Capability: KVM_CAP_ADJUST_CLOCK
 Architectures: x86
@@ -654,7 +654,7 @@
 	__u32 pad[9];
 };
 
-4.29 KVM_GET_VCPU_EVENTS
+4.31 KVM_GET_VCPU_EVENTS
 
 Capability: KVM_CAP_VCPU_EVENTS
 Extended by: KVM_CAP_INTR_SHADOW
@@ -693,7 +693,7 @@
 KVM_VCPUEVENT_VALID_SHADOW may be set in the flags field to signal that
 interrupt.shadow contains a valid state. Otherwise, this field is undefined.
 
-4.30 KVM_SET_VCPU_EVENTS
+4.32 KVM_SET_VCPU_EVENTS
 
 Capability: KVM_CAP_VCPU_EVENTS
 Extended by: KVM_CAP_INTR_SHADOW
@@ -719,7 +719,7 @@
 the flags field to signal that interrupt.shadow contains a valid state and
 shall be written into the VCPU.
 
-4.32 KVM_GET_DEBUGREGS
+4.33 KVM_GET_DEBUGREGS
 
 Capability: KVM_CAP_DEBUGREGS
 Architectures: x86
@@ -737,7 +737,7 @@
 	__u64 reserved[9];
 };
 
-4.33 KVM_SET_DEBUGREGS
+4.34 KVM_SET_DEBUGREGS
 
 Capability: KVM_CAP_DEBUGREGS
 Architectures: x86
@@ -750,7 +750,7 @@
 See KVM_GET_DEBUGREGS for the data structure. The flags field is unused
 yet and must be cleared on entry.
 
-4.34 KVM_SET_USER_MEMORY_REGION
+4.35 KVM_SET_USER_MEMORY_REGION
 
 Capability: KVM_CAP_USER_MEM
 Architectures: all
@@ -796,7 +796,7 @@
 The KVM_SET_MEMORY_REGION does not allow fine grained control over memory
 allocation and is deprecated.
 
-4.35 KVM_SET_TSS_ADDR
+4.36 KVM_SET_TSS_ADDR
 
 Capability: KVM_CAP_SET_TSS_ADDR
 Architectures: x86
@@ -814,7 +814,7 @@
 because of a quirk in the virtualization implementation (see the internals
 documentation when it pops into existence).
 
-4.36 KVM_ENABLE_CAP
+4.37 KVM_ENABLE_CAP
 
 Capability: KVM_CAP_ENABLE_CAP
 Architectures: ppc
@@ -849,7 +849,7 @@
        __u8  pad[64];
 };
 
-4.37 KVM_GET_MP_STATE
+4.38 KVM_GET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
 Architectures: x86, ia64
@@ -879,7 +879,7 @@
 This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
 irqchip, the multiprocessing state must be maintained by userspace.
 
-4.38 KVM_SET_MP_STATE
+4.39 KVM_SET_MP_STATE
 
 Capability: KVM_CAP_MP_STATE
 Architectures: x86, ia64
@@ -893,7 +893,7 @@
 This ioctl is only useful after KVM_CREATE_IRQCHIP.  Without an in-kernel
 irqchip, the multiprocessing state must be maintained by userspace.
 
-4.39 KVM_SET_IDENTITY_MAP_ADDR
+4.40 KVM_SET_IDENTITY_MAP_ADDR
 
 Capability: KVM_CAP_SET_IDENTITY_MAP_ADDR
 Architectures: x86
@@ -911,7 +911,7 @@
 because of a quirk in the virtualization implementation (see the internals
 documentation when it pops into existence).
 
-4.40 KVM_SET_BOOT_CPU_ID
+4.41 KVM_SET_BOOT_CPU_ID
 
 Capability: KVM_CAP_SET_BOOT_CPU_ID
 Architectures: x86, ia64
@@ -923,7 +923,7 @@
 as the vcpu id in KVM_CREATE_VCPU.  If this ioctl is not called, the default
 is vcpu 0.
 
-4.41 KVM_GET_XSAVE
+4.42 KVM_GET_XSAVE
 
 Capability: KVM_CAP_XSAVE
 Architectures: x86
@@ -937,7 +937,7 @@
 
 This ioctl would copy current vcpu's xsave struct to the userspace.
 
-4.42 KVM_SET_XSAVE
+4.43 KVM_SET_XSAVE
 
 Capability: KVM_CAP_XSAVE
 Architectures: x86
@@ -951,7 +951,7 @@
 
 This ioctl would copy userspace's xsave struct to the kernel.
 
-4.43 KVM_GET_XCRS
+4.44 KVM_GET_XCRS
 
 Capability: KVM_CAP_XCRS
 Architectures: x86
@@ -974,7 +974,7 @@
 
 This ioctl would copy current vcpu's xcrs to the userspace.
 
-4.44 KVM_SET_XCRS
+4.45 KVM_SET_XCRS
 
 Capability: KVM_CAP_XCRS
 Architectures: x86
@@ -997,7 +997,7 @@
 
 This ioctl would set vcpu's xcr to the value userspace specified.
 
-4.45 KVM_GET_SUPPORTED_CPUID
+4.46 KVM_GET_SUPPORTED_CPUID
 
 Capability: KVM_CAP_EXT_CPUID
 Architectures: x86
@@ -1062,7 +1062,7 @@
    eax, ebx, ecx, edx: the values returned by the cpuid instruction for
          this function/index combination
 
-4.46 KVM_PPC_GET_PVINFO
+4.47 KVM_PPC_GET_PVINFO
 
 Capability: KVM_CAP_PPC_GET_PVINFO
 Architectures: ppc
@@ -1085,7 +1085,7 @@
 If any additional field gets added to this structure later on, a bit for that
 additional piece of information will be set in the flags bitmap.
 
-4.47 KVM_ASSIGN_PCI_DEVICE
+4.48 KVM_ASSIGN_PCI_DEVICE
 
 Capability: KVM_CAP_DEVICE_ASSIGNMENT
 Architectures: x86 ia64
@@ -1113,7 +1113,7 @@
 /* Depends on KVM_CAP_IOMMU */
 #define KVM_DEV_ASSIGN_ENABLE_IOMMU	(1 << 0)
 
-4.48 KVM_DEASSIGN_PCI_DEVICE
+4.49 KVM_DEASSIGN_PCI_DEVICE
 
 Capability: KVM_CAP_DEVICE_DEASSIGNMENT
 Architectures: x86 ia64
@@ -1126,7 +1126,7 @@
 See KVM_CAP_DEVICE_ASSIGNMENT for the data structure. Only assigned_dev_id is
 used in kvm_assigned_pci_dev to identify the device.
 
-4.49 KVM_ASSIGN_DEV_IRQ
+4.50 KVM_ASSIGN_DEV_IRQ
 
 Capability: KVM_CAP_ASSIGN_DEV_IRQ
 Architectures: x86 ia64
@@ -1164,7 +1164,7 @@
 It is not valid to specify multiple types per host or guest IRQ. However, the
 IRQ type of host and guest can differ or can even be null.
 
-4.50 KVM_DEASSIGN_DEV_IRQ
+4.51 KVM_DEASSIGN_DEV_IRQ
 
 Capability: KVM_CAP_ASSIGN_DEV_IRQ
 Architectures: x86 ia64
@@ -1178,7 +1178,7 @@
 by assigned_dev_id, flags must correspond to the IRQ type specified on
 KVM_ASSIGN_DEV_IRQ. Partial deassignment of host or guest IRQ is allowed.
 
-4.51 KVM_SET_GSI_ROUTING
+4.52 KVM_SET_GSI_ROUTING
 
 Capability: KVM_CAP_IRQ_ROUTING
 Architectures: x86 ia64
@@ -1226,7 +1226,7 @@
 	__u32 pad;
 };
 
-4.52 KVM_ASSIGN_SET_MSIX_NR
+4.53 KVM_ASSIGN_SET_MSIX_NR
 
 Capability: KVM_CAP_DEVICE_MSIX
 Architectures: x86 ia64
@@ -1245,7 +1245,7 @@
 
 #define KVM_MAX_MSIX_PER_DEV		256
 
-4.53 KVM_ASSIGN_SET_MSIX_ENTRY
+4.54 KVM_ASSIGN_SET_MSIX_ENTRY
 
 Capability: KVM_CAP_DEVICE_MSIX
 Architectures: x86 ia64
diff -druN linux-libre-2.6.38-gnu/Documentation/kvm/locking.txt linux-libre-2.6.39-gnu/Documentation/kvm/locking.txt
--- linux-libre-2.6.38-gnu/Documentation/kvm/locking.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/kvm/locking.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,25 @@
+KVM Lock Overview
+=================
+
+1. Acquisition Orders
+---------------------
+
+(to be written)
+
+2. Reference
+------------
+
+Name:		kvm_lock
+Type:		raw_spinlock
+Arch:		any
+Protects:	- vm_list
+		- hardware virtualization enable/disable
+Comment:	'raw' because hardware enabling/disabling must be atomic /wrt
+		migration.
+
+Name:		kvm_arch::tsc_write_lock
+Type:		raw_spinlock
+Arch:		x86
+Protects:	- kvm_arch::{last_tsc_write,last_tsc_nsec,last_tsc_offset}
+		- tsc offset in vmcb
+Comment:	'raw' because updating the tsc offsets must not be preempted.
diff -druN linux-libre-2.6.38-gnu/Documentation/kvm/mmu.txt linux-libre-2.6.39-gnu/Documentation/kvm/mmu.txt
--- linux-libre-2.6.38-gnu/Documentation/kvm/mmu.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kvm/mmu.txt	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
                and framebuffer-based displays
 - footprint:   keep the amount of pinned kernel memory low (most memory
                should be shrinkable)
-- reliablity:  avoid multipage or GFP_ATOMIC allocations
+- reliability:  avoid multipage or GFP_ATOMIC allocations
 
 Acronyms
 ========
diff -druN linux-libre-2.6.38-gnu/Documentation/kvm/ppc-pv.txt linux-libre-2.6.39-gnu/Documentation/kvm/ppc-pv.txt
--- linux-libre-2.6.38-gnu/Documentation/kvm/ppc-pv.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kvm/ppc-pv.txt	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,7 @@
 ====================
 
 The "ld" and "std" instructions are transormed to "lwz" and "stw" instructions
-respectively on 32 bit systems with an added offset of 4 to accomodate for big
+respectively on 32 bit systems with an added offset of 4 to accommodate for big
 endianness.
 
 The following is a list of mapping the Linux kernel performs when running as
diff -druN linux-libre-2.6.38-gnu/Documentation/kvm/timekeeping.txt linux-libre-2.6.39-gnu/Documentation/kvm/timekeeping.txt
--- linux-libre-2.6.38-gnu/Documentation/kvm/timekeeping.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/kvm/timekeeping.txt	2011-05-19 00:06:34.000000000 -0400
@@ -81,7 +81,7 @@
  when the gate is high (always true for timers 0 and 1).  When the count
  reaches zero, the output goes high.
 
-Mode 1: Triggered One-shot.  The output is intially set high.  When the gate
+Mode 1: Triggered One-shot.  The output is initially set high.  When the gate
  line is set high, a countdown is initiated (which does not stop if the gate is
  lowered), during which the output is set low.  When the count reaches zero,
  the output goes high.
diff -druN linux-libre-2.6.38-gnu/Documentation/laptops/asus-laptop.txt linux-libre-2.6.39-gnu/Documentation/laptops/asus-laptop.txt
--- linux-libre-2.6.38-gnu/Documentation/laptops/asus-laptop.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/laptops/asus-laptop.txt	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
   Hotkeys are also reported as input keys (like keyboards) you can check
   which key are supported using "xev" under X11.
 
-  You can get informations on the version of your DSDT table by reading the
+  You can get information on the version of your DSDT table by reading the
   /sys/devices/platform/asus-laptop/infos entry. If you have a question or a
   bug report to do, please include the output of this entry.
 
@@ -178,7 +178,7 @@
 -----------
 
   Some models like the W1N have a LED display that can be used to display
-  several informations.
+  several items of information.
 
   LED display works for the following models:
     W1000N
diff -druN linux-libre-2.6.38-gnu/Documentation/laptops/hpfall.c linux-libre-2.6.39-gnu/Documentation/laptops/hpfall.c
--- linux-libre-2.6.38-gnu/Documentation/laptops/hpfall.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/laptops/hpfall.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,146 @@
+/* Disk protection for HP machines.
+ *
+ * Copyright 2008 Eric Piel
+ * Copyright 2009 Pavel Machek <pavel@ucw.cz>
+ *
+ * GPLv2.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <stdint.h>
+#include <errno.h>
+#include <signal.h>
+#include <sys/mman.h>
+#include <sched.h>
+
+char unload_heads_path[64];
+
+int set_unload_heads_path(char *device)
+{
+	char devname[64];
+
+	if (strlen(device) <= 5 || strncmp(device, "/dev/", 5) != 0)
+		return -EINVAL;
+	strncpy(devname, device + 5, sizeof(devname));
+
+	snprintf(unload_heads_path, sizeof(unload_heads_path),
+				"/sys/block/%s/device/unload_heads", devname);
+	return 0;
+}
+int valid_disk(void)
+{
+	int fd = open(unload_heads_path, O_RDONLY);
+	if (fd < 0) {
+		perror(unload_heads_path);
+		return 0;
+	}
+
+	close(fd);
+	return 1;
+}
+
+void write_int(char *path, int i)
+{
+	char buf[1024];
+	int fd = open(path, O_RDWR);
+	if (fd < 0) {
+		perror("open");
+		exit(1);
+	}
+	sprintf(buf, "%d", i);
+	if (write(fd, buf, strlen(buf)) != strlen(buf)) {
+		perror("write");
+		exit(1);
+	}
+	close(fd);
+}
+
+void set_led(int on)
+{
+	write_int("/sys/class/leds/hp::hddprotect/brightness", on);
+}
+
+void protect(int seconds)
+{
+	write_int(unload_heads_path, seconds*1000);
+}
+
+int on_ac(void)
+{
+//	/sys/class/power_supply/AC0/online
+}
+
+int lid_open(void)
+{
+//	/proc/acpi/button/lid/LID/state
+}
+
+void ignore_me(void)
+{
+	protect(0);
+	set_led(0);
+}
+
+int main(int argc, char **argv)
+{
+	int fd, ret;
+	struct sched_param param;
+
+	if (argc == 1)
+		ret = set_unload_heads_path("/dev/sda");
+	else if (argc == 2)
+		ret = set_unload_heads_path(argv[1]);
+	else
+		ret = -EINVAL;
+
+	if (ret || !valid_disk()) {
+		fprintf(stderr, "usage: %s <device> (default: /dev/sda)\n",
+				argv[0]);
+		exit(1);
+	}
+
+	fd = open("/dev/freefall", O_RDONLY);
+	if (fd < 0) {
+		perror("/dev/freefall");
+		return EXIT_FAILURE;
+	}
+
+	daemon(0, 0);
+	param.sched_priority = sched_get_priority_max(SCHED_FIFO);
+	sched_setscheduler(0, SCHED_FIFO, &param);
+	mlockall(MCL_CURRENT|MCL_FUTURE);
+
+	signal(SIGALRM, ignore_me);
+
+	for (;;) {
+		unsigned char count;
+
+		ret = read(fd, &count, sizeof(count));
+		alarm(0);
+		if ((ret == -1) && (errno == EINTR)) {
+			/* Alarm expired, time to unpark the heads */
+			continue;
+		}
+
+		if (ret != sizeof(count)) {
+			perror("read");
+			break;
+		}
+
+		protect(21);
+		set_led(1);
+		if (1 || on_ac() || lid_open())
+			alarm(2);
+		else
+			alarm(20);
+	}
+
+	close(fd);
+	return EXIT_SUCCESS;
+}
diff -druN linux-libre-2.6.38-gnu/Documentation/laptops/sony-laptop.txt linux-libre-2.6.39-gnu/Documentation/laptops/sony-laptop.txt
--- linux-libre-2.6.38-gnu/Documentation/laptops/sony-laptop.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/laptops/sony-laptop.txt	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,8 @@
 reported both through the ACPI subsystem as acpi events and through the INPUT
 subsystem. See the logs of acpid or /proc/acpi/event and
 /proc/bus/input/devices to find out what those events are and which input
-devices are created by the driver.
+devices are created by the driver. Additionally, loading the driver with the
+debug option will report all events in the kernel log.
 
 Backlight control:
 ------------------
@@ -64,6 +65,16 @@
 	# echo "1" > /sys/devices/platform/sony-laptop/audiopower
 powers on the sound card.
 
+
+RFkill control:
+---------------
+More recent Vaio models expose a consistent set of ACPI methods to
+control radio frequency emitting devices. If you are a lucky owner of
+such a laptop you will find the necessary rfkill devices under
+/sys/class/rfkill. Check those starting with sony-* in
+	# grep . /sys/class/rfkill/*/{state,name}
+
+
 Development:
 ------------
 
@@ -75,8 +86,21 @@
 REPEAT: DON'T DO THIS IF YOU DON'T LIKE RISKY BUSINESS.
 
 In your kernel logs you will find the list of all ACPI methods
-the SNC device has on your laptop. You can see the GCDP/GCDP methods
-used to pwer on/off the CD drive, but there are others.
+the SNC device has on your laptop.
+
+* For new models you will see a long list of meaningless method names,
+reading the DSDT table source should reveal that:
+(1) the SNC device uses an internal capability lookup table
+(2) SN00 is used to find values in the lookup table
+(3) SN06 and SN07 are used to call into the real methods based on
+    offsets you can obtain iterating the table using SN00
+(4) SN02 used to enable events.
+Some values in the capability lookup table are more or less known, see
+the code for all sony_call_snc_handle calls, others are more obscure.
+
+* For old models you can see the GCDP/GCDP methods used to pwer on/off
+the CD drive, but there are others and they are usually different from
+model to model.
 
 I HAVE NO IDEA WHAT THOSE METHODS DO.
 
@@ -108,9 +132,8 @@
   laptop, including permanent damage.
 
 * The sony-laptop and sonypi drivers do not interact at all. In the
-  future, sonypi could use sony-laptop to do (part of) its business.
+  future, sonypi will be removed and replaced by sony-laptop.
 
 * spicctrl, which is the userspace tool used to communicate with the
-  sonypi driver (through /dev/sonypi) does not try to use the
-  sony-laptop driver. In the future, spicctrl could try sonypi first,
-  and if it isn't present, try sony-laptop instead.
+  sonypi driver (through /dev/sonypi) is deprecated as well since all
+  its features are now available under the sysfs tree via sony-laptop.
diff -druN linux-libre-2.6.38-gnu/Documentation/leds/00-INDEX linux-libre-2.6.39-gnu/Documentation/leds/00-INDEX
--- linux-libre-2.6.38-gnu/Documentation/leds/00-INDEX	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/leds/00-INDEX	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,8 @@
+leds-class.txt
+	- documents LED handling under Linux.
+leds-lp3944.txt
+	- notes on how to use the leds-lp3944 driver.
+leds-lp5521.txt
+	- notes on how to use the leds-lp5521 driver.
+leds-lp5523.txt
+	- notes on how to use the leds-lp5523 driver.
diff -druN linux-libre-2.6.38-gnu/Documentation/leds/leds-class.txt linux-libre-2.6.39-gnu/Documentation/leds/leds-class.txt
--- linux-libre-2.6.38-gnu/Documentation/leds/leds-class.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/leds/leds-class.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,97 @@
+
+LED handling under Linux
+========================
+
+If you're reading this and thinking about keyboard leds, these are
+handled by the input subsystem and the led class is *not* needed.
+
+In its simplest form, the LED class just allows control of LEDs from
+userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the
+LED is defined in max_brightness file. The brightness file will set the brightness
+of the LED (taking a value 0-max_brightness). Most LEDs don't have hardware
+brightness support so will just be turned on for non-zero brightness settings.
+
+The class also introduces the optional concept of an LED trigger. A trigger
+is a kernel based source of led events. Triggers can either be simple or
+complex. A simple trigger isn't configurable and is designed to slot into
+existing subsystems with minimal additional code. Examples are the ide-disk,
+nand-disk and sharpsl-charge triggers. With led triggers disabled, the code
+optimises away.
+
+Complex triggers whilst available to all LEDs have LED specific
+parameters and work on a per LED basis. The timer trigger is an example.
+The timer trigger will periodically change the LED brightness between
+LED_OFF and the current brightness setting. The "on" and "off" time can
+be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
+You can change the brightness value of a LED independently of the timer
+trigger. However, if you set the brightness value to LED_OFF it will
+also disable the timer trigger.
+
+You can change triggers in a similar manner to the way an IO scheduler
+is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
+parameters can appear in /sys/class/leds/<device> once a given trigger is
+selected.
+
+
+Design Philosophy
+=================
+
+The underlying design philosophy is simplicity. LEDs are simple devices
+and the aim is to keep a small amount of code giving as much functionality
+as possible.  Please keep this in mind when suggesting enhancements.
+
+
+LED Device Naming
+=================
+
+Is currently of the form:
+
+"devicename:colour:function"
+
+There have been calls for LED properties such as colour to be exported as
+individual led class attributes. As a solution which doesn't incur as much
+overhead, I suggest these become part of the device name. The naming scheme
+above leaves scope for further attributes should they be needed. If sections
+of the name don't apply, just leave that section blank.
+
+
+Hardware accelerated blink of LEDs
+==================================
+
+Some LEDs can be programmed to blink without any CPU interaction. To
+support this feature, a LED driver can optionally implement the
+blink_set() function (see <linux/leds.h>). To set an LED to blinking,
+however, it is better to use use the API function led_blink_set(),
+as it will check and implement software fallback if necessary.
+
+To turn off blinking again, use the API function led_brightness_set()
+as that will not just set the LED brightness but also stop any software
+timers that may have been required for blinking.
+
+The blink_set() function should choose a user friendly blinking value
+if it is called with *delay_on==0 && *delay_off==0 parameters. In this
+case the driver should give back the chosen value through delay_on and
+delay_off parameters to the leds subsystem.
+
+Setting the brightness to zero with brightness_set() callback function
+should completely turn off the LED and cancel the previously programmed
+hardware blinking function, if any.
+
+
+Known Issues
+============
+
+The LED Trigger core cannot be a module as the simple trigger functions
+would cause nightmare dependency issues. I see this as a minor issue
+compared to the benefits the simple trigger functionality brings. The
+rest of the LED subsystem can be modular.
+
+
+Future Development
+==================
+
+At the moment, a trigger can't be created specifically for a single LED.
+There are a number of cases where a trigger might only be mappable to a
+particular LED (ACPI?). The addition of triggers provided by the LED driver
+should cover this option and be possible to add without breaking the
+current interface.
diff -druN linux-libre-2.6.38-gnu/Documentation/leds/leds-lp3944.txt linux-libre-2.6.39-gnu/Documentation/leds/leds-lp3944.txt
--- linux-libre-2.6.38-gnu/Documentation/leds/leds-lp3944.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/leds/leds-lp3944.txt	2011-05-19 00:06:34.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.38-gnu/Documentation/leds-class.txt linux-libre-2.6.39-gnu/Documentation/leds-class.txt
--- linux-libre-2.6.38-gnu/Documentation/leds-class.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/leds-class.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-
-LED handling under Linux
-========================
-
-If you're reading this and thinking about keyboard leds, these are
-handled by the input subsystem and the led class is *not* needed.
-
-In its simplest form, the LED class just allows control of LEDs from
-userspace. LEDs appear in /sys/class/leds/. The maximum brightness of the
-LED is defined in max_brightness file. The brightness file will set the brightness
-of the LED (taking a value 0-max_brightness). Most LEDs don't have hardware
-brightness support so will just be turned on for non-zero brightness settings.
-
-The class also introduces the optional concept of an LED trigger. A trigger
-is a kernel based source of led events. Triggers can either be simple or
-complex. A simple trigger isn't configurable and is designed to slot into
-existing subsystems with minimal additional code. Examples are the ide-disk,
-nand-disk and sharpsl-charge triggers. With led triggers disabled, the code
-optimises away.
-
-Complex triggers whilst available to all LEDs have LED specific
-parameters and work on a per LED basis. The timer trigger is an example.
-The timer trigger will periodically change the LED brightness between
-LED_OFF and the current brightness setting. The "on" and "off" time can
-be specified via /sys/class/leds/<device>/delay_{on,off} in milliseconds.
-You can change the brightness value of a LED independently of the timer
-trigger. However, if you set the brightness value to LED_OFF it will
-also disable the timer trigger.
-
-You can change triggers in a similar manner to the way an IO scheduler
-is chosen (via /sys/class/leds/<device>/trigger). Trigger specific
-parameters can appear in /sys/class/leds/<device> once a given trigger is
-selected.
-
-
-Design Philosophy
-=================
-
-The underlying design philosophy is simplicity. LEDs are simple devices
-and the aim is to keep a small amount of code giving as much functionality
-as possible.  Please keep this in mind when suggesting enhancements.
-
-
-LED Device Naming
-=================
-
-Is currently of the form:
-
-"devicename:colour:function"
-
-There have been calls for LED properties such as colour to be exported as
-individual led class attributes. As a solution which doesn't incur as much
-overhead, I suggest these become part of the device name. The naming scheme
-above leaves scope for further attributes should they be needed. If sections
-of the name don't apply, just leave that section blank.
-
-
-Hardware accelerated blink of LEDs
-==================================
-
-Some LEDs can be programmed to blink without any CPU interaction. To
-support this feature, a LED driver can optionally implement the
-blink_set() function (see <linux/leds.h>). To set an LED to blinking,
-however, it is better to use use the API function led_blink_set(),
-as it will check and implement software fallback if necessary.
-
-To turn off blinking again, use the API function led_brightness_set()
-as that will not just set the LED brightness but also stop any software
-timers that may have been required for blinking.
-
-The blink_set() function should choose a user friendly blinking value
-if it is called with *delay_on==0 && *delay_off==0 parameters. In this
-case the driver should give back the chosen value through delay_on and
-delay_off parameters to the leds subsystem.
-
-Setting the brightness to zero with brightness_set() callback function
-should completely turn off the LED and cancel the previously programmed
-hardware blinking function, if any.
-
-
-Known Issues
-============
-
-The LED Trigger core cannot be a module as the simple trigger functions
-would cause nightmare dependency issues. I see this as a minor issue
-compared to the benefits the simple trigger functionality brings. The
-rest of the LED subsystem can be modular.
-
-
-Future Development
-==================
-
-At the moment, a trigger can't be created specifically for a single LED.
-There are a number of cases where a trigger might only be mappable to a
-particular LED (ACPI?). The addition of triggers provided by the LED driver
-should cover this option and be possible to add without breaking the
-current interface.
-
diff -druN linux-libre-2.6.38-gnu/Documentation/leds-lp3944.txt linux-libre-2.6.39-gnu/Documentation/leds-lp3944.txt
--- linux-libre-2.6.38-gnu/Documentation/leds-lp3944.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/leds-lp3944.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,50 +0,0 @@
-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.38-gnu/Documentation/md.txt linux-libre-2.6.39-gnu/Documentation/md.txt
--- linux-libre-2.6.38-gnu/Documentation/md.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/md.txt	2011-05-19 00:06:34.000000000 -0400
@@ -552,6 +552,16 @@
      within the array where IO will be blocked.  This is currently
      only supported for raid4/5/6.
 
+   sync_min
+   sync_max
+     The two values, given as numbers of sectors, indicate a range
+     withing the array where 'check'/'repair' will operate. Must be
+     a multiple of chunk_size. When it reaches "sync_max" it will
+     pause, rather than complete.
+     You can use 'select' or 'poll' on "sync_completed" to wait for
+     that number to reach sync_max.  Then you can either increase
+     "sync_max", or can write 'idle' to "sync_action".
+
 
 Each active md device may also have attributes specific to the
 personality module that manages it.
diff -druN linux-libre-2.6.38-gnu/Documentation/media-framework.txt linux-libre-2.6.39-gnu/Documentation/media-framework.txt
--- linux-libre-2.6.38-gnu/Documentation/media-framework.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/media-framework.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,353 @@
+Linux kernel media framework
+============================
+
+This document describes the Linux kernel media framework, its data structures,
+functions and their usage.
+
+
+Introduction
+------------
+
+The media controller API is documented in DocBook format in
+Documentation/DocBook/v4l/media-controller.xml. This document will focus on
+the kernel-side implementation of the media framework.
+
+
+Abstract media device model
+---------------------------
+
+Discovering a device internal topology, and configuring it at runtime, is one
+of the goals of the media framework. To achieve this, hardware devices are
+modeled as an oriented graph of building blocks called entities connected
+through pads.
+
+An entity is a basic media hardware building block. It can correspond to
+a large variety of logical blocks such as physical hardware devices
+(CMOS sensor for instance), logical hardware devices (a building block
+in a System-on-Chip image processing pipeline), DMA channels or physical
+connectors.
+
+A pad is a connection endpoint through which an entity can interact with
+other entities. Data (not restricted to video) produced by an entity
+flows from the entity's output to one or more entity inputs. Pads should
+not be confused with physical pins at chip boundaries.
+
+A link is a point-to-point oriented connection between two pads, either
+on the same entity or on different entities. Data flows from a source
+pad to a sink pad.
+
+
+Media device
+------------
+
+A media device is represented by a struct media_device instance, defined in
+include/media/media-device.h. Allocation of the structure is handled by the
+media device driver, usually by embedding the media_device instance in a
+larger driver-specific structure.
+
+Drivers register media device instances by calling
+
+	media_device_register(struct media_device *mdev);
+
+The caller is responsible for initializing the media_device structure before
+registration. The following fields must be set:
+
+ - dev must point to the parent device (usually a pci_dev, usb_interface or
+   platform_device instance).
+
+ - model must be filled with the device model name as a NUL-terminated UTF-8
+   string. The device/model revision must not be stored in this field.
+
+The following fields are optional:
+
+ - serial is a unique serial number stored as a NUL-terminated ASCII string.
+   The field is big enough to store a GUID in text form. If the hardware
+   doesn't provide a unique serial number this field must be left empty.
+
+ - bus_info represents the location of the device in the system as a
+   NUL-terminated ASCII string. For PCI/PCIe devices bus_info must be set to
+   "PCI:" (or "PCIe:") followed by the value of pci_name(). For USB devices,
+   the usb_make_path() function must be used. This field is used by
+   applications to distinguish between otherwise identical devices that don't
+   provide a serial number.
+
+ - hw_revision is the hardware device revision in a driver-specific format.
+   When possible the revision should be formatted with the KERNEL_VERSION
+   macro.
+
+ - driver_version is formatted with the KERNEL_VERSION macro. The version
+   minor must be incremented when new features are added to the userspace API
+   without breaking binary compatibility. The version major must be
+   incremented when binary compatibility is broken.
+
+Upon successful registration a character device named media[0-9]+ is created.
+The device major and minor numbers are dynamic. The model name is exported as
+a sysfs attribute.
+
+Drivers unregister media device instances by calling
+
+	media_device_unregister(struct media_device *mdev);
+
+Unregistering a media device that hasn't been registered is *NOT* safe.
+
+
+Entities, pads and links
+------------------------
+
+- Entities
+
+Entities are represented by a struct media_entity instance, defined in
+include/media/media-entity.h. The structure is usually embedded into a
+higher-level structure, such as a v4l2_subdev or video_device instance,
+although drivers can allocate entities directly.
+
+Drivers initialize entities by calling
+
+	media_entity_init(struct media_entity *entity, u16 num_pads,
+			  struct media_pad *pads, u16 extra_links);
+
+The media_entity name, type, flags, revision and group_id fields can be
+initialized before or after calling media_entity_init. Entities embedded in
+higher-level standard structures can have some of those fields set by the
+higher-level framework.
+
+As the number of pads is known in advance, the pads array is not allocated
+dynamically but is managed by the entity driver. Most drivers will embed the
+pads array in a driver-specific structure, avoiding dynamic allocation.
+
+Drivers must set the direction of every pad in the pads array before calling
+media_entity_init. The function will initialize the other pads fields.
+
+Unlike the number of pads, the total number of links isn't always known in
+advance by the entity driver. As an initial estimate, media_entity_init
+pre-allocates a number of links equal to the number of pads plus an optional
+number of extra links. The links array will be reallocated if it grows beyond
+the initial estimate.
+
+Drivers register entities with a media device by calling
+
+	media_device_register_entity(struct media_device *mdev,
+				     struct media_entity *entity);
+
+Entities are identified by a unique positive integer ID. Drivers can provide an
+ID by filling the media_entity id field prior to registration, or request the
+media controller framework to assign an ID automatically. Drivers that provide
+IDs manually must ensure that all IDs are unique. IDs are not guaranteed to be
+contiguous even when they are all assigned automatically by the framework.
+
+Drivers unregister entities by calling
+
+	media_device_unregister_entity(struct media_entity *entity);
+
+Unregistering an entity will not change the IDs of the other entities, and the
+ID will never be reused for a newly registered entity.
+
+When a media device is unregistered, all its entities are unregistered
+automatically. No manual entities unregistration is then required.
+
+Drivers free resources associated with an entity by calling
+
+	media_entity_cleanup(struct media_entity *entity);
+
+This function must be called during the cleanup phase after unregistering the
+entity. Note that the media_entity instance itself must be freed explicitly by
+the driver if required.
+
+Entities have flags that describe the entity capabilities and state.
+
+	MEDIA_ENT_FL_DEFAULT indicates the default entity for a given type.
+	This can be used to report the default audio and video devices or the
+	default camera sensor.
+
+Logical entity groups can be defined by setting the group ID of all member
+entities to the same non-zero value. An entity group serves no purpose in the
+kernel, but is reported to userspace during entities enumeration. The group_id
+field belongs to the media device driver and must not by touched by entity
+drivers.
+
+Media device drivers should define groups if several entities are logically
+bound together. Example usages include reporting
+
+	- ALSA, VBI and video nodes that carry the same media stream
+	- lens and flash controllers associated with a sensor
+
+- Pads
+
+Pads are represented by a struct media_pad instance, defined in
+include/media/media-entity.h. Each entity stores its pads in a pads array
+managed by the entity driver. Drivers usually embed the array in a
+driver-specific structure.
+
+Pads are identified by their entity and their 0-based index in the pads array.
+Both information are stored in the media_pad structure, making the media_pad
+pointer the canonical way to store and pass link references.
+
+Pads have flags that describe the pad capabilities and state.
+
+	MEDIA_PAD_FL_SINK indicates that the pad supports sinking data.
+	MEDIA_PAD_FL_SOURCE indicates that the pad supports sourcing data.
+
+One and only one of MEDIA_PAD_FL_SINK and MEDIA_PAD_FL_SOURCE must be set for
+each pad.
+
+- Links
+
+Links are represented by a struct media_link instance, defined in
+include/media/media-entity.h. Each entity stores all links originating at or
+targeting any of its pads in a links array. A given link is thus stored
+twice, once in the source entity and once in the target entity. The array is
+pre-allocated and grows dynamically as needed.
+
+Drivers create links by calling
+
+	media_entity_create_link(struct media_entity *source, u16 source_pad,
+				 struct media_entity *sink,   u16 sink_pad,
+				 u32 flags);
+
+An entry in the link array of each entity is allocated and stores pointers
+to source and sink pads.
+
+Links have flags that describe the link capabilities and state.
+
+	MEDIA_LNK_FL_ENABLED indicates that the link is enabled and can be used
+	to transfer media data. When two or more links target a sink pad, only
+	one of them can be enabled at a time.
+	MEDIA_LNK_FL_IMMUTABLE indicates that the link enabled state can't be
+	modified at runtime. If MEDIA_LNK_FL_IMMUTABLE is set, then
+	MEDIA_LNK_FL_ENABLED must also be set since an immutable link is always
+	enabled.
+
+
+Graph traversal
+---------------
+
+The media framework provides APIs to iterate over entities in a graph.
+
+To iterate over all entities belonging to a media device, drivers can use the
+media_device_for_each_entity macro, defined in include/media/media-device.h.
+
+	struct media_entity *entity;
+
+	media_device_for_each_entity(entity, mdev) {
+		/* entity will point to each entity in turn */
+		...
+	}
+
+Drivers might also need to iterate over all entities in a graph that can be
+reached only through enabled links starting at a given entity. The media
+framework provides a depth-first graph traversal API for that purpose.
+
+Note that graphs with cycles (whether directed or undirected) are *NOT*
+supported by the graph traversal API. To prevent infinite loops, the graph
+traversal code limits the maximum depth to MEDIA_ENTITY_ENUM_MAX_DEPTH,
+currently defined as 16.
+
+Drivers initiate a graph traversal by calling
+
+	media_entity_graph_walk_start(struct media_entity_graph *graph,
+				      struct media_entity *entity);
+
+The graph structure, provided by the caller, is initialized to start graph
+traversal at the given entity.
+
+Drivers can then retrieve the next entity by calling
+
+	media_entity_graph_walk_next(struct media_entity_graph *graph);
+
+When the graph traversal is complete the function will return NULL.
+
+Graph traversal can be interrupted at any moment. No cleanup function call is
+required and the graph structure can be freed normally.
+
+Helper functions can be used to find a link between two given pads, or a pad
+connected to another pad through an enabled link
+
+	media_entity_find_link(struct media_pad *source,
+			       struct media_pad *sink);
+
+	media_entity_remote_source(struct media_pad *pad);
+
+Refer to the kerneldoc documentation for more information.
+
+
+Use count and power handling
+----------------------------
+
+Due to the wide differences between drivers regarding power management needs,
+the media controller does not implement power management. However, the
+media_entity structure includes a use_count field that media drivers can use to
+track the number of users of every entity for power management needs.
+
+The use_count field is owned by media drivers and must not be touched by entity
+drivers. Access to the field must be protected by the media device graph_mutex
+lock.
+
+
+Links setup
+-----------
+
+Link properties can be modified at runtime by calling
+
+	media_entity_setup_link(struct media_link *link, u32 flags);
+
+The flags argument contains the requested new link flags.
+
+The only configurable property is the ENABLED link flag to enable/disable a
+link. Links marked with the IMMUTABLE link flag can not be enabled or disabled.
+
+When a link is enabled or disabled, the media framework calls the
+link_setup operation for the two entities at the source and sink of the link,
+in that order. If the second link_setup call fails, another link_setup call is
+made on the first entity to restore the original link flags.
+
+Media device drivers can be notified of link setup operations by setting the
+media_device::link_notify pointer to a callback function. If provided, the
+notification callback will be called before enabling and after disabling
+links.
+
+Entity drivers must implement the link_setup operation if any of their links
+is non-immutable. The operation must either configure the hardware or store
+the configuration information to be applied later.
+
+Link configuration must not have any side effect on other links. If an enabled
+link at a sink pad prevents another link at the same pad from being disabled,
+the link_setup operation must return -EBUSY and can't implicitly disable the
+first enabled link.
+
+
+Pipelines and media streams
+---------------------------
+
+When starting streaming, drivers must notify all entities in the pipeline to
+prevent link states from being modified during streaming by calling
+
+	media_entity_pipeline_start(struct media_entity *entity,
+				    struct media_pipeline *pipe);
+
+The function will mark all entities connected to the given entity through
+enabled links, either directly or indirectly, as streaming.
+
+The media_pipeline instance pointed to by the pipe argument will be stored in
+every entity in the pipeline. Drivers should embed the media_pipeline structure
+in higher-level pipeline structures and can then access the pipeline through
+the media_entity pipe field.
+
+Calls to media_entity_pipeline_start() can be nested. The pipeline pointer must
+be identical for all nested calls to the function.
+
+When stopping the stream, drivers must notify the entities with
+
+	media_entity_pipeline_stop(struct media_entity *entity);
+
+If multiple calls to media_entity_pipeline_start() have been made the same
+number of media_entity_pipeline_stop() calls are required to stop streaming. The
+media_entity pipe field is reset to NULL on the last nested stop call.
+
+Link configuration will fail with -EBUSY by default if either end of the link is
+a streaming entity. Links that can be modified while streaming must be marked
+with the MEDIA_LNK_FL_DYNAMIC flag.
+
+If other operations need to be disallowed on streaming entities (such as
+changing entities configuration parameters) drivers can explicitly check the
+media_entity stream_count field to find out if an entity is streaming. This
+operation must be done with the media_device graph_mutex held.
diff -druN linux-libre-2.6.38-gnu/Documentation/memory-barriers.txt linux-libre-2.6.39-gnu/Documentation/memory-barriers.txt
--- linux-libre-2.6.38-gnu/Documentation/memory-barriers.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/memory-barriers.txt	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
      - SMP barrier pairing.
      - Examples of memory barrier sequences.
      - Read memory barriers vs load speculation.
+     - Transitivity
 
  (*) Explicit kernel barriers.
 
@@ -959,6 +960,63 @@
 	retrieved                               :       :       +-------+
 
 
+TRANSITIVITY
+------------
+
+Transitivity is a deeply intuitive notion about ordering that is not
+always provided by real computer systems.  The following example
+demonstrates transitivity (also called "cumulativity"):
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<general barrier>	<general barrier>
+				LOAD Y			LOAD X
+
+Suppose that CPU 2's load from X returns 1 and its load from Y returns 0.
+This indicates that CPU 2's load from X in some sense follows CPU 1's
+store to X and that CPU 2's load from Y in some sense preceded CPU 3's
+store to Y.  The question is then "Can CPU 3's load from X return 0?"
+
+Because CPU 2's load from X in some sense came after CPU 1's store, it
+is natural to expect that CPU 3's load from X must therefore return 1.
+This expectation is an example of transitivity: if a load executing on
+CPU A follows a load from the same variable executing on CPU B, then
+CPU A's load must either return the same value that CPU B's load did,
+or must return some later value.
+
+In the Linux kernel, use of general memory barriers guarantees
+transitivity.  Therefore, in the above example, if CPU 2's load from X
+returns 1 and its load from Y returns 0, then CPU 3's load from X must
+also return 1.
+
+However, transitivity is -not- guaranteed for read or write barriers.
+For example, suppose that CPU 2's general barrier in the above example
+is changed to a read barrier as shown below:
+
+	CPU 1			CPU 2			CPU 3
+	=======================	=======================	=======================
+		{ X = 0, Y = 0 }
+	STORE X=1		LOAD X			STORE Y=1
+				<read barrier>		<general barrier>
+				LOAD Y			LOAD X
+
+This substitution destroys transitivity: in this example, it is perfectly
+legal for CPU 2's load from X to return 1, its load from Y to return 0,
+and CPU 3's load from X to return 0.
+
+The key point is that although CPU 2's read barrier orders its pair
+of loads, it does not guarantee to order CPU 1's store.  Therefore, if
+this example runs on a system where CPUs 1 and 2 share a store buffer
+or a level of cache, CPU 2 might have early access to CPU 1's writes.
+General barriers are therefore required to ensure that all CPUs agree
+on the combined order of CPU 1's and CPU 2's accesses.
+
+To reiterate, if your code requires transitivity, use general barriers
+throughout.
+
+
 ========================
 EXPLICIT KERNEL BARRIERS
 ========================
diff -druN linux-libre-2.6.38-gnu/Documentation/memory-hotplug.txt linux-libre-2.6.39-gnu/Documentation/memory-hotplug.txt
--- linux-libre-2.6.38-gnu/Documentation/memory-hotplug.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/memory-hotplug.txt	2011-05-19 00:06:34.000000000 -0400
@@ -126,36 +126,51 @@
 --------------------------------
 4 sysfs files for memory hotplug
 --------------------------------
-All sections have their device information under /sys/devices/system/memory as
+All sections have their device information in sysfs.  Each section is part of
+a memory block under /sys/devices/system/memory as
 
 /sys/devices/system/memory/memoryXXX
-(XXX is section id.)
+(XXX is the section id.)
 
-Now, XXX is defined as start_address_of_section / section_size.
+Now, XXX is defined as (start_address_of_section / section_size) of the first
+section contained in the memory block.  The files 'phys_index' and
+'end_phys_index' under each directory report the beginning and end section id's
+for the memory block covered by the sysfs directory.  It is expected that all
+memory sections in this range are present and no memory holes exist in the
+range. Currently there is no way to determine if there is a memory hole, but
+the existence of one should not affect the hotplug capabilities of the memory
+block.
 
 For example, assume 1GiB section size. A device for a memory starting at
 0x100000000 is /sys/device/system/memory/memory4
 (0x100000000 / 1Gib = 4)
 This device covers address range [0x100000000 ... 0x140000000)
 
-Under each section, you can see 4 files.
+Under each section, you can see 4 or 5 files, the end_phys_index file being
+a recent addition and not present on older kernels.
 
-/sys/devices/system/memory/memoryXXX/phys_index
+/sys/devices/system/memory/memoryXXX/start_phys_index
+/sys/devices/system/memory/memoryXXX/end_phys_index
 /sys/devices/system/memory/memoryXXX/phys_device
 /sys/devices/system/memory/memoryXXX/state
 /sys/devices/system/memory/memoryXXX/removable
 
-'phys_index' : read-only and contains section id, same as XXX.
-'state'      : read-write
-               at read:  contains online/offline state of memory.
-               at write: user can specify "online", "offline" command
-'phys_device': read-only: designed to show the name of physical memory device.
-               This is not well implemented now.
-'removable'  : read-only: contains an integer value indicating
-               whether the memory section is removable or not
-               removable.  A value of 1 indicates that the memory
-               section is removable and a value of 0 indicates that
-               it is not removable.
+'phys_index'      : read-only and contains section id of the first section
+		    in the memory block, same as XXX.
+'end_phys_index'  : read-only and contains section id of the last section
+		    in the memory block.
+'state'           : read-write
+                    at read:  contains online/offline state of memory.
+                    at write: user can specify "online", "offline" command
+                    which will be performed on al sections in the block.
+'phys_device'     : read-only: designed to show the name of physical memory
+                    device.  This is not well implemented now.
+'removable'       : read-only: contains an integer value indicating
+                    whether the memory block is removable or not
+                    removable.  A value of 1 indicates that the memory
+                    block is removable and a value of 0 indicates that
+                    it is not removable. A memory block is removable only if
+                    every section in the block is removable.
 
 NOTE:
   These directories/files appear after physical memory hotplug phase.
diff -druN linux-libre-2.6.38-gnu/Documentation/mips/AU1xxx_IDE.README linux-libre-2.6.39-gnu/Documentation/mips/AU1xxx_IDE.README
--- linux-libre-2.6.38-gnu/Documentation/mips/AU1xxx_IDE.README	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/mips/AU1xxx_IDE.README	2011-05-19 00:06:34.000000000 -0400
@@ -39,13 +39,13 @@
       Interface and Linux Device Driver" Application Note.
 
 
-FILES, CONFIGS AND COMPATABILITY
+FILES, CONFIGS AND COMPATIBILITY
 --------------------------------
 
 Two files are introduced:
 
   a) 'arch/mips/include/asm/mach-au1x00/au1xxx_ide.h'
-     containes : struct _auide_hwif
+     contains : struct _auide_hwif
                  timing parameters for PIO mode 0/1/2/3/4
                  timing parameters for MWDMA 0/1/2
 
diff -druN linux-libre-2.6.38-gnu/Documentation/misc-devices/ics932s401 linux-libre-2.6.39-gnu/Documentation/misc-devices/ics932s401
--- linux-libre-2.6.38-gnu/Documentation/misc-devices/ics932s401	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/misc-devices/ics932s401	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
   * IDT ICS932S401
     Prefix: 'ics932s401'
     Addresses scanned: I2C 0x69
-    Datasheet: Publically available at the IDT website
+    Datasheet: Publicly available at the IDT website
 
 Author: Darrick J. Wong
 
diff -druN linux-libre-2.6.38-gnu/Documentation/misc-devices/lis3lv02d linux-libre-2.6.39-gnu/Documentation/misc-devices/lis3lv02d
--- linux-libre-2.6.38-gnu/Documentation/misc-devices/lis3lv02d	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/misc-devices/lis3lv02d	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,92 @@
+Kernel driver lis3lv02d
+=======================
+
+Supported chips:
+
+  * STMicroelectronics LIS3LV02DL, LIS3LV02DQ (12 bits precision)
+  * STMicroelectronics LIS302DL, LIS3L02DQ, LIS331DL (8 bits)
+
+Authors:
+        Yan Burman <burman.yan@gmail.com>
+	Eric Piel <eric.piel@tremplin-utc.net>
+
+
+Description
+-----------
+
+This driver provides support for the accelerometer found in various HP laptops
+sporting the feature officially called "HP Mobile Data Protection System 3D" or
+"HP 3D DriveGuard". It detects automatically laptops with this sensor. Known
+models (full list can be found in drivers/platform/x86/hp_accel.c) will have
+their axis automatically oriented on standard way (eg: you can directly play
+neverball). The accelerometer data is readable via
+/sys/devices/platform/lis3lv02d. Reported values are scaled
+to mg values (1/1000th of earth gravity).
+
+Sysfs attributes under /sys/devices/platform/lis3lv02d/:
+position - 3D position that the accelerometer reports. Format: "(x,y,z)"
+rate - read reports the sampling rate of the accelerometer device in HZ.
+	write changes sampling rate of the accelerometer device.
+	Only values which are supported by HW are accepted.
+selftest - performs selftest for the chip as specified by chip manufacturer.
+
+This driver also provides an absolute input class device, allowing
+the laptop to act as a pinball machine-esque joystick. Joystick device can be
+calibrated. Joystick device can be in two different modes.
+By default output values are scaled between -32768 .. 32767. In joystick raw
+mode, joystick and sysfs position entry have the same scale. There can be
+small difference due to input system fuzziness feature.
+Events are also available as input event device.
+
+Selftest is meant only for hardware diagnostic purposes. It is not meant to be
+used during normal operations. Position data is not corrupted during selftest
+but interrupt behaviour is not guaranteed to work reliably. In test mode, the
+sensing element is internally moved little bit. Selftest measures difference
+between normal mode and test mode. Chip specifications tell the acceptance
+limit for each type of the chip. Limits are provided via platform data
+to allow adjustment of the limits without a change to the actual driver.
+Seltest returns either "OK x y z" or "FAIL x y z" where x, y and z are
+measured difference between modes. Axes are not remapped in selftest mode.
+Measurement values are provided to help HW diagnostic applications to make
+final decision.
+
+On HP laptops, if the led infrastructure is activated, support for a led
+indicating disk protection will be provided as /sys/class/leds/hp::hddprotect.
+
+Another feature of the driver is misc device called "freefall" that
+acts similar to /dev/rtc and reacts on free-fall interrupts received
+from the device. It supports blocking operations, poll/select and
+fasync operation modes. You must read 1 bytes from the device.  The
+result is number of free-fall interrupts since the last successful
+read (or 255 if number of interrupts would not fit). See the hpfall.c
+file for an example on using the device.
+
+
+Axes orientation
+----------------
+
+For better compatibility between the various laptops. The values reported by
+the accelerometer are converted into a "standard" organisation of the axes
+(aka "can play neverball out of the box"):
+ * When the laptop is horizontal the position reported is about 0 for X and Y
+	and a positive value for Z
+ * If the left side is elevated, X increases (becomes positive)
+ * If the front side (where the touchpad is) is elevated, Y decreases
+	(becomes negative)
+ * If the laptop is put upside-down, Z becomes negative
+
+If your laptop model is not recognized (cf "dmesg"), you can send an
+email to the maintainer to add it to the database.  When reporting a new
+laptop, please include the output of "dmidecode" plus the value of
+/sys/devices/platform/lis3lv02d/position in these four cases.
+
+Q&A
+---
+
+Q: How do I safely simulate freefall? I have an HP "portable
+workstation" which has about 3.5kg and a plastic case, so letting it
+fall to the ground is out of question...
+
+A: The sensor is pretty sensitive, so your hands can do it. Lift it
+into free space, follow the fall with your hands for like 10
+centimeters. That should be enough to trigger the detection.
diff -druN linux-libre-2.6.38-gnu/Documentation/misc-devices/spear-pcie-gadget.txt linux-libre-2.6.39-gnu/Documentation/misc-devices/spear-pcie-gadget.txt
--- linux-libre-2.6.38-gnu/Documentation/misc-devices/spear-pcie-gadget.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/misc-devices/spear-pcie-gadget.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,130 @@
+Spear PCIe Gadget Driver:
+
+Author
+=============
+Pratyush Anand (pratyush.anand@st.com)
+
+Location
+============
+driver/misc/spear13xx_pcie_gadget.c
+
+Supported Chip:
+===================
+SPEAr1300
+SPEAr1310
+
+Menuconfig option:
+==========================
+Device Drivers
+	Misc devices
+		PCIe gadget support for SPEAr13XX platform
+purpose
+===========
+This driver has several nodes which can be read/written by configfs interface.
+Its main purpose is to configure selected dual mode PCIe controller as device
+and then program its various registers to configure it as a particular device
+type. This driver can be used to show spear's PCIe device capability.
+
+Description of different nodes:
+=================================
+
+read behavior of nodes:
+------------------------------
+link 		:gives ltssm status.
+int_type 	:type of supported interrupt
+no_of_msi 	:zero if MSI is not enabled by host. A positive value is the
+		number of MSI vector granted.
+vendor_id	:returns programmed vendor id (hex)
+device_id	:returns programmed device id(hex)
+bar0_size:	:returns size of bar0 in hex.
+bar0_address	:returns address of bar0 mapped area in hex.
+bar0_rw_offset	:returns offset of bar0 for which bar0_data will return value.
+bar0_data	:returns data at bar0_rw_offset.
+
+write behavior of nodes:
+------------------------------
+link 		:write UP to enable ltsmm DOWN to disable
+int_type	:write interrupt type to be configured and (int_type could be
+		INTA, MSI or NO_INT). Select MSI only when you have programmed
+		no_of_msi node.
+no_of_msi	:number of MSI vector needed.
+inta		:write 1 to assert INTA and 0 to de-assert.
+send_msi	:write MSI vector to be sent.
+vendor_id	:write vendor id(hex) to be programmed.
+device_id	:write device id(hex) to be programmed.
+bar0_size	:write size of bar0 in hex. default bar0 size is 1000 (hex)
+		bytes.
+bar0_address	:write	address of bar0 mapped area in hex. (default mapping of
+		bar0 is SYSRAM1(E0800000). Always program bar size before bar
+		address. Kernel might modify bar size and address for alignment, so
+		read back bar size and address after writing to cross check.
+bar0_rw_offset	:write offset of bar0 for which	bar0_data will write value.
+bar0_data	:write data to be written at bar0_rw_offset.
+
+Node programming example
+===========================
+Program all PCIe registers in such a way that when this device is connected
+to the PCIe host, then host sees this device as 1MB RAM.
+#mount -t configfs none /Config
+For nth PCIe Device Controller
+# cd /config/pcie_gadget.n/
+Now you have all the nodes in this directory.
+program vendor id as 0x104a
+# echo 104A >> vendor_id
+
+program device id as 0xCD80
+# echo CD80 >> device_id
+
+program BAR0 size as 1MB
+# echo 100000 >> bar0_size
+
+check for programmed bar0 size
+# cat bar0_size
+
+Program BAR0 Address as DDR (0x2100000). This is the physical address of
+memory, which is to be made visible to PCIe host. Similarly any other peripheral
+can also be made visible to PCIe host. E.g., if you program base address of UART
+as BAR0 address then when this device will be connected to a host, it will be
+visible as UART.
+# echo 2100000 >> bar0_address
+
+program interrupt type : INTA
+# echo INTA >> int_type
+
+go for link up now.
+# echo UP >> link
+
+It will have to be insured that, once link up is done on gadget, then only host
+is initialized and start to search PCIe devices on its port.
+
+/*wait till link is up*/
+# cat link
+wait till it returns UP.
+
+To assert INTA
+# echo 1 >> inta
+
+To de-assert INTA
+# echo 0 >> inta
+
+if MSI is to be used as interrupt, program no of msi vector needed (say4)
+# echo 4 >> no_of_msi
+
+select MSI as interrupt type
+# echo MSI >> int_type
+
+go for link up now
+# echo UP >> link
+
+wait till link is up
+# cat link
+An application can repetitively read this node till link is found UP. It can
+sleep between two read.
+
+wait till msi is enabled
+# cat no_of_msi
+Should return 4 (number of requested MSI vector)
+
+to send msi vector 2
+# echo 2 >> send_msi
+#cd -
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/3c359.txt linux-libre-2.6.39-gnu/Documentation/networking/3c359.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/3c359.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/3c359.txt	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 
 Variable MTU size:
 
-The driver can handle a MTU size upto either 4500 or 18000 depending upon 
+The driver can handle a MTU size up to either 4500 or 18000 depending upon 
 ring speed.  The driver also changes the size of the receive buffers as part
 of the mtu re-sizing, so if you set mtu = 18000, you will need to be able
 to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring 
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/batman-adv.txt linux-libre-2.6.39-gnu/Documentation/networking/batman-adv.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/batman-adv.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/batman-adv.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-[state: 21-11-2010]
+[state: 27-01-2011]
 
 BATMAN-ADV
 ----------
@@ -67,15 +67,16 @@
 folder:
 
 #  ls  /sys/class/net/bat0/mesh/
-#  aggregated_ogms  bonding  fragmentation  orig_interval
-#  vis_mode
+#  aggregated_ogms  gw_bandwidth  hop_penalty
+#  bonding          gw_mode       orig_interval
+#  fragmentation    gw_sel_class  vis_mode
 
 
-There is a special folder for debugging informations:
+There is a special folder for debugging information:
 
 #  ls /sys/kernel/debug/batman_adv/bat0/
-#  originators  socket  transtable_global  transtable_local
-#  vis_data
+#  gateways     socket        transtable_global  vis_data
+#  originators  softif_neigh  transtable_local
 
 
 Some of the files contain all sort of status information  regard-
@@ -230,9 +231,8 @@
 Please send us comments, experiences, questions, anything :)
 
 IRC:            #batman   on   irc.freenode.org
-Mailing-list:   b.a.t.m.a.n@b.a.t.m.a.n@lists.open-mesh.org
-                (optional   subscription   at
-                 https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
+Mailing-list:   b.a.t.m.a.n@open-mesh.org (optional  subscription
+          at https://lists.open-mesh.org/mm/listinfo/b.a.t.m.a.n)
 
 You can also contact the Authors:
 
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/bonding.txt linux-libre-2.6.39-gnu/Documentation/networking/bonding.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/bonding.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/bonding.txt	2011-05-19 00:06:34.000000000 -0400
@@ -368,7 +368,7 @@
 		gratuitous ARP is lost, communication may be
 		disrupted.
 
-		When this policy is used in conjuction with the mii
+		When this policy is used in conjunction with the mii
 		monitor, devices which assert link up prior to being
 		able to actually transmit and receive are particularly
 		susceptible to loss of the gratuitous ARP, and an
@@ -2558,18 +2558,15 @@
 16. Resources and Links
 =======================
 
-The latest version of the bonding driver can be found in the latest
+	The latest version of the bonding driver can be found in the latest
 version of the linux kernel, found on http://kernel.org
 
-The latest version of this document can be found in either the latest
-kernel source (named Documentation/networking/bonding.txt), or on the
-bonding sourceforge site:
-
-http://www.sourceforge.net/projects/bonding
+	The latest version of this document can be found in the latest kernel
+source (named Documentation/networking/bonding.txt).
 
-Discussions regarding the bonding driver take place primarily on the
-bonding-devel mailing list, hosted at sourceforge.net.  If you have
-questions or problems, post them to the list.  The list address is:
+	Discussions regarding the usage of the bonding driver take place on the
+bonding-devel mailing list, hosted at sourceforge.net. If you have questions or
+problems, post them to the list.  The list address is:
 
 bonding-devel@lists.sourceforge.net
 
@@ -2578,6 +2575,17 @@
 
 https://lists.sourceforge.net/lists/listinfo/bonding-devel
 
+	Discussions regarding the developpement of the bonding driver take place
+on the main Linux network mailing list, hosted at vger.kernel.org. The list
+address is:
+
+netdev@vger.kernel.org
+
+	The administrative interface (to subscribe or unsubscribe) can
+be found at:
+
+http://vger.kernel.org/vger-lists.html#netdev
+
 Donald Becker's Ethernet Drivers and diag programs may be found at :
  - http://web.archive.org/web/*/http://www.scyld.com/network/ 
 
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/caif/Linux-CAIF.txt linux-libre-2.6.39-gnu/Documentation/networking/caif/Linux-CAIF.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/caif/Linux-CAIF.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/caif/Linux-CAIF.txt	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,7 @@
       - CFMUX CAIF Mux layer. Handles multiplexing between multiple
 	physical bearers and multiple channels such as VEI, Datagram, etc.
 	The MUX keeps track of the existing CAIF Channels and
-	Physical Instances and selects the apropriate instance based
+	Physical Instances and selects the appropriate instance based
 	on Channel-Id and Physical-ID.
 
       - CFFRML CAIF Framing layer. Handles Framing i.e. Frame length
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/caif/spi_porting.txt linux-libre-2.6.39-gnu/Documentation/networking/caif/spi_porting.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/caif/spi_porting.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/caif/spi_porting.txt	2011-05-19 00:06:34.000000000 -0400
@@ -150,7 +150,7 @@
 void sspi_sig_xfer(bool xfer, struct cfspi_dev *dev)
 {
 	/* If xfer is true then you should assert the SPI_INT to indicate to
-	 * the master that you are ready to recieve the data from the master
+	 * the master that you are ready to receive the data from the master
 	 * SPI. If xfer is false then you should de-assert SPI_INT to indicate
 	 * that the transfer is done.
 	 */
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/can.txt linux-libre-2.6.39-gnu/Documentation/networking/can.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/can.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/can.txt	2011-05-19 00:06:34.000000000 -0400
@@ -240,7 +240,7 @@
   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
+  The format of the CAN error frame is briefly described in the Linux
   header file "include/linux/can/error.h".
 
 4. How to use Socket CAN
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/ieee802154.txt linux-libre-2.6.39-gnu/Documentation/networking/ieee802154.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/ieee802154.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/ieee802154.txt	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
 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
+Currently only IEEE 802.15.4 layer is implemented. We have chosen
 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
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/ip-sysctl.txt linux-libre-2.6.39-gnu/Documentation/networking/ip-sysctl.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/ip-sysctl.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/ip-sysctl.txt	2011-05-19 00:06:34.000000000 -0400
@@ -280,6 +280,17 @@
 	more aggressively. Let me to remind again: each orphan eats
 	up to ~64K of unswappable memory.
 
+tcp_max_ssthresh - INTEGER
+	Limited Slow-Start for TCP with large congestion windows (cwnd) defined in
+	RFC3742. Limited slow-start is a mechanism to limit growth of the cwnd
+	on the region where cwnd is larger than tcp_max_ssthresh. TCP increases cwnd
+	by at most tcp_max_ssthresh segments, and by at least tcp_max_ssthresh/2
+	segments per RTT when the cwnd is above tcp_max_ssthresh.
+	If TCP connection increased cwnd to thousands (or tens of thousands) segments,
+	and thousands of packets were being dropped during slow-start, you can set
+	tcp_max_ssthresh to improve performance for new TCP connection.
+	Default: 0 (off)
+
 tcp_max_syn_backlog - INTEGER
 	Maximal number of remembered connection requests, which are
 	still did not receive an acknowledgment from connecting client.
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/olympic.txt linux-libre-2.6.39-gnu/Documentation/networking/olympic.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/olympic.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/olympic.txt	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
 
 Variable MTU size:
 
-The driver can handle a MTU size upto either 4500 or 18000 depending upon 
+The driver can handle a MTU size up to either 4500 or 18000 depending upon 
 ring speed.  The driver also changes the size of the receive buffers as part
 of the mtu re-sizing, so if you set mtu = 18000, you will need to be able
 to allocate 16 * (sk_buff with 18000 buffer size) call it 18500 bytes per ring 
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/packet_mmap.txt linux-libre-2.6.39-gnu/Documentation/networking/packet_mmap.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/packet_mmap.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/packet_mmap.txt	2011-05-19 00:06:34.000000000 -0400
@@ -223,7 +223,7 @@
 
 A frame can be of any size with the only condition it can fit in a block. A block
 can only hold an integer number of frames, or in other words, a frame cannot 
-be spawned accross two blocks, so there are some details you have to take into 
+be spawned across two blocks, so there are some details you have to take into 
 account when choosing the frame_size. See "Mapping and use of the circular 
 buffer (ring)".
 
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/phonet.txt linux-libre-2.6.39-gnu/Documentation/networking/phonet.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/phonet.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/phonet.txt	2011-05-19 00:06:34.000000000 -0400
@@ -154,9 +154,28 @@
     write(cfd, msg, msglen);
   }
 
-Connections are established between two endpoints by a "third party"
-application. This means that both endpoints are passive; so connect()
-is not possible.
+Connections are traditionally established between two endpoints by a
+"third party" application. This means that both endpoints are passive.
+
+
+As of Linux kernel version 2.6.39, it is also possible to connect
+two endpoints directly, using connect() on the active side. This is
+intended to support the newer Nokia Wireless Modem API, as found in
+e.g. the Nokia Slim Modem in the ST-Ericsson U8500 platform:
+
+  struct sockaddr_spn spn;
+  int fd;
+
+  fd = socket(PF_PHONET, SOCK_SEQPACKET, PN_PROTO_PIPE);
+  memset(&spn, 0, sizeof(spn));
+  spn.spn_family = AF_PHONET;
+  spn.spn_obj = ...;
+  spn.spn_dev = ...;
+  spn.spn_resource = 0xD9;
+  connect(fd, (struct sockaddr *)&spn, sizeof(spn));
+  /* normal I/O here ... */
+  close(fd);
+
 
 WARNING:
 When polling a connected pipe socket for writability, there is an
@@ -181,45 +200,9 @@
     interface index of the network interface created by PNPIPE_ENCAP,
     or zero if encapsulation is off.
 
-
-Phonet Pipe-controller Implementation
--------------------------------------
-
-Phonet Pipe-controller is enabled by selecting the CONFIG_PHONET_PIPECTRLR Kconfig
-option. It is useful when communicating with those Nokia Modems which do not
-implement Pipe controller in them e.g. Nokia Slim Modem used in ST-Ericsson
-U8500 platform.
-
-The implementation is based on the Data Connection Establishment Sequence
-depicted in 'Nokia Wireless Modem API - Wireless_modem_user_guide.pdf'
-document.
-
-It allows a phonet sequenced socket (host-pep) to initiate a Pipe connection
-between itself and a remote pipe-end point (e.g. modem).
-
-The implementation adds socket options at SOL_PNPIPE level:
-
- PNPIPE_PIPE_HANDLE
-	It accepts an integer argument for setting value of pipe handle.
-
-  PNPIPE_ENABLE accepts one integer value (int). If set to zero, the pipe
-    is disabled. If the value is non-zero, the pipe is enabled. If the pipe
-    is not (yet) connected, ENOTCONN is error is returned.
-
-The implementation also adds socket 'connect'. On calling the 'connect', pipe
-will be created between the source socket and the destination, and the pipe
-state will be set to PIPE_DISABLED.
-
-After a pipe has been created and enabled successfully, the Pipe data can be
-exchanged between the host-pep and remote-pep (modem).
-
-User-space would typically follow below sequence with Pipe controller:-
--socket
--bind
--setsockopt for PNPIPE_PIPE_HANDLE
--connect
--setsockopt for PNPIPE_ENCAP_IP
--setsockopt for PNPIPE_ENABLE
+  PNPIPE_HANDLE is a read-only integer value. It contains the underlying
+    identifier ("pipe handle") of the pipe. This is only defined for
+    socket descriptors that are already connected or being connected.
 
 
 Authors
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/README.ipw2200 linux-libre-2.6.39-gnu/Documentation/networking/README.ipw2200
--- linux-libre-2.6.38-gnu/Documentation/networking/README.ipw2200	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/README.ipw2200	2011-05-19 00:06:34.000000000 -0400
@@ -256,7 +256,7 @@
 
 Where $VALUE would be a number in the case of this sysfs entry.  The 
 input to sysfs files does not have to be a number.  For example, the 
-firmware loader used by hotplug utilizes sysfs entries for transfering 
+firmware loader used by hotplug utilizes sysfs entries for transferring 
 the firmware image from user space into the driver.
 
 The Intel(R) PRO/Wireless 2915ABG Driver for Linux exposes sysfs entries 
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/s2io.txt linux-libre-2.6.39-gnu/Documentation/networking/s2io.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/s2io.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/s2io.txt	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
 The corresponding adapter's LED will blink multiple times.
 
 3.	Features supported:
-a. Jumbo frames. Xframe I/II supports MTU upto 9600 bytes,
+a. Jumbo frames. Xframe I/II supports MTU up to 9600 bytes,
 modifiable using ifconfig command.
 
 b. Offloads. Supports checksum offload(TCP/UDP/IP) on transmit
@@ -49,7 +49,7 @@
 IBM xSeries).
 
 d. MSI/MSI-X. Can be enabled on platforms which support this feature
-(IA64, Xeon) resulting in noticeable performance improvement(upto 7%
+(IA64, Xeon) resulting in noticeable performance improvement(up to 7%
 on certain platforms).
 
 e. Statistics. Comprehensive MAC-level and software statistics displayed
diff -druN linux-libre-2.6.38-gnu/Documentation/networking/tc-actions-env-rules.txt linux-libre-2.6.39-gnu/Documentation/networking/tc-actions-env-rules.txt
--- linux-libre-2.6.38-gnu/Documentation/networking/tc-actions-env-rules.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/networking/tc-actions-env-rules.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 
-The "enviromental" rules for authors of any new tc actions are:
+The "environmental" rules for authors of any new tc actions are:
 
 1) If you stealeth or borroweth any packet thou shalt be branching
 from the righteous path and thou shalt cloneth.
@@ -20,7 +20,7 @@
 3) Dropping packets you don't own is a no-no. You simply return
 TC_ACT_SHOT to the caller and they will drop it.
 
-The "enviromental" rules for callers of actions (qdiscs etc) are:
+The "environmental" rules for callers of actions (qdiscs etc) are:
 
 *) Thou art responsible for freeing anything returned as being
 TC_ACT_SHOT/STOLEN/QUEUED. If none of TC_ACT_SHOT/STOLEN/QUEUED is
diff -druN linux-libre-2.6.38-gnu/Documentation/PCI/MSI-HOWTO.txt linux-libre-2.6.39-gnu/Documentation/PCI/MSI-HOWTO.txt
--- linux-libre-2.6.38-gnu/Documentation/PCI/MSI-HOWTO.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/PCI/MSI-HOWTO.txt	2011-05-19 00:06:34.000000000 -0400
@@ -253,8 +253,8 @@
 must be a power of two).  In addition, the MSI interrupt vectors must
 be allocated consecutively, so the system may not be able to allocate
 as many vectors for MSI as it could for MSI-X.  On some platforms, MSI
-interrupts must all be targetted at the same set of CPUs whereas MSI-X
-interrupts can all be targetted at different CPUs.
+interrupts must all be targeted at the same set of CPUs whereas MSI-X
+interrupts can all be targeted at different CPUs.
 
 4.5.2 Spinlocks
 
diff -druN linux-libre-2.6.38-gnu/Documentation/power/devices.txt linux-libre-2.6.39-gnu/Documentation/power/devices.txt
--- linux-libre-2.6.38-gnu/Documentation/power/devices.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/devices.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 Device Power Management
 
-Copyright (c) 2010 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+Copyright (c) 2010-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
 Copyright (c) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 
@@ -159,18 +159,18 @@
 whether or not a wakeup-capable device should issue wakeup events is a policy
 decision, and it is managed by user space through a sysfs attribute: the
 power/wakeup file.  User space can write the strings "enabled" or "disabled" to
-set or clear the should_wakeup flag, respectively.  Reads from the file will
-return the corresponding string if can_wakeup is true, but if can_wakeup is
-false then reads will return an empty string, to indicate that the device
-doesn't support wakeup events.  (But even though the file appears empty, writes
-will still affect the should_wakeup flag.)
+set or clear the "should_wakeup" flag, respectively.  This file is only present
+for wakeup-capable devices (i.e. devices whose "can_wakeup" flags are set)
+and is created (or removed) by device_set_wakeup_capable().  Reads from the
+file will return the corresponding string.
 
 The device_may_wakeup() routine returns true only if both flags are set.
-Drivers should check this routine when putting devices in a low-power state
-during a system sleep transition, to see whether or not to enable the devices'
-wakeup mechanisms.  However for runtime power management, wakeup events should
-be enabled whenever the device and driver both support them, regardless of the
-should_wakeup flag.
+This information is used by subsystems, like the PCI bus type code, to see
+whether or not to enable the devices' wakeup mechanisms.  If device wakeup
+mechanisms are enabled or disabled directly by drivers, they also should use
+device_may_wakeup() to decide what to do during a system sleep transition.
+However for runtime power management, wakeup events should be enabled whenever
+the device and driver both support them, regardless of the should_wakeup flag.
 
 
 /sys/devices/.../power/control files
@@ -249,23 +249,18 @@
 unfrozen.  Furthermore, the *_noirq phases run at a time when IRQ handlers have
 been disabled (except for those marked with the IRQ_WAKEUP flag).
 
-Most phases use bus, type, and class callbacks (that is, methods defined in
-dev->bus->pm, dev->type->pm, and dev->class->pm).  The prepare and complete
-phases are exceptions; they use only bus callbacks.  When multiple callbacks
-are used in a phase, they are invoked in the order: <class, type, bus> during
-power-down transitions and in the opposite order during power-up transitions.
-For example, during the suspend phase the PM core invokes
-
-	dev->class->pm.suspend(dev);
-	dev->type->pm.suspend(dev);
-	dev->bus->pm.suspend(dev);
-
-before moving on to the next device, whereas during the resume phase the core
-invokes
-
-	dev->bus->pm.resume(dev);
-	dev->type->pm.resume(dev);
-	dev->class->pm.resume(dev);
+All phases use bus, type, or class callbacks (that is, methods defined in
+dev->bus->pm, dev->type->pm, or dev->class->pm).  These callbacks are mutually
+exclusive, so if the device type provides a struct dev_pm_ops object pointed to
+by its pm field (i.e. both dev->type and dev->type->pm are defined), the
+callbacks included in that object (i.e. dev->type->pm) will be used.  Otherwise,
+if the class provides a struct dev_pm_ops object pointed to by its pm field
+(i.e. both dev->class and dev->class->pm are defined), the PM core will use the
+callbacks from that object (i.e. dev->class->pm).  Finally, if the pm fields of
+both the device type and class objects are NULL (or those objects do not exist),
+the callbacks provided by the bus (that is, the callbacks from dev->bus->pm)
+will be used (this allows device types to override callbacks provided by bus
+types or classes if necessary).
 
 These callbacks may in turn invoke device- or driver-specific methods stored in
 dev->driver->pm, but they don't have to.
@@ -372,7 +367,7 @@
 suspend methods were called, for example by complete reinitialization.
 This may be the hardest part, and the one most protected by NDA'd documents
 and chip errata.  It's simplest if the hardware state hasn't changed since
-the suspend was carried out, but that can't be guaranteed (in fact, it ususally
+the suspend was carried out, but that can't be guaranteed (in fact, it usually
 is not the case).
 
 Drivers must also be prepared to notice that the device has been removed
@@ -507,6 +502,49 @@
 situation where it actually matters.
 
 
+Device Power Domains
+--------------------
+Sometimes devices share reference clocks or other power resources.  In those
+cases it generally is not possible to put devices into low-power states
+individually.  Instead, a set of devices sharing a power resource can be put
+into a low-power state together at the same time by turning off the shared
+power resource.  Of course, they also need to be put into the full-power state
+together, by turning the shared power resource on.  A set of devices with this
+property is often referred to as a power domain.
+
+Support for power domains is provided through the pwr_domain field of struct
+device.  This field is a pointer to an object of type struct dev_power_domain,
+defined in include/linux/pm.h, providing a set of power management callbacks
+analogous to the subsystem-level and device driver callbacks that are executed
+for the given device during all power transitions, in addition to the respective
+subsystem-level callbacks.  Specifically, the power domain "suspend" callbacks
+(i.e. ->runtime_suspend(), ->suspend(), ->freeze(), ->poweroff(), etc.) are
+executed after the analogous subsystem-level callbacks, while the power domain
+"resume" callbacks (i.e. ->runtime_resume(), ->resume(), ->thaw(), ->restore,
+etc.) are executed before the analogous subsystem-level callbacks.  Error codes
+returned by the "suspend" and "resume" power domain callbacks are ignored.
+
+Power domain ->runtime_idle() callback is executed before the subsystem-level
+->runtime_idle() callback and the result returned by it is not ignored.  Namely,
+if it returns error code, the subsystem-level ->runtime_idle() callback will not
+be called and the helper function rpm_idle() executing it will return error
+code.  This mechanism is intended to help platforms where saving device state
+is a time consuming operation and should only be carried out if all devices
+in the power domain are idle, before turning off the shared power resource(s).
+Namely, the power domain ->runtime_idle() callback may return error code until
+the pm_runtime_idle() helper (or its asychronous version) has been called for
+all devices in the power domain (it is recommended that the returned error code
+be -EBUSY in those cases), preventing the subsystem-level ->runtime_idle()
+callback from being run prematurely.
+
+The support for device power domains is only relevant to platforms needing to
+use the same subsystem-level (e.g. platform bus type) and device driver power
+management callbacks in many different power domain configurations and wanting
+to avoid incorporating the support for power domains into the subsystem-level
+callbacks.  The other platforms need not implement it or take it into account
+in any way.
+
+
 System Devices
 --------------
 System devices (sysdevs) follow a slightly different API, which can be found in
diff -druN linux-libre-2.6.38-gnu/Documentation/power/notifiers.txt linux-libre-2.6.39-gnu/Documentation/power/notifiers.txt
--- linux-libre-2.6.38-gnu/Documentation/power/notifiers.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/notifiers.txt	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 			be frozen immediately.
 
 PM_POST_HIBERNATION	The system memory state has been restored from a
-			hibernation image or an error occured during the
+			hibernation image or an error occurred during the
 			hibernation.  Device drivers' .resume() callbacks have
 			been executed and tasks have been thawed.
 
@@ -38,7 +38,7 @@
 
 PM_SUSPEND_PREPARE	The system is preparing for a suspend.
 
-PM_POST_SUSPEND		The system has just resumed or an error occured during
+PM_POST_SUSPEND		The system has just resumed or an error occurred during
 			the suspend.	Device drivers' .resume() callbacks have
 			been executed and tasks have been thawed.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/power/opp.txt linux-libre-2.6.39-gnu/Documentation/power/opp.txt
--- linux-libre-2.6.38-gnu/Documentation/power/opp.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/opp.txt	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,7 @@
 		if (!IS_ERR(opp))
 			soc_switch_to_freq_voltage(freq);
 		else
-			/* do something when we cant satisfy the req */
+			/* do something when we can't satisfy the req */
 		/* do other stuff */
 	 }
 
diff -druN linux-libre-2.6.38-gnu/Documentation/power/runtime_pm.txt linux-libre-2.6.39-gnu/Documentation/power/runtime_pm.txt
--- linux-libre-2.6.38-gnu/Documentation/power/runtime_pm.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/runtime_pm.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 Run-time Power Management Framework for I/O Devices
 
-(C) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+(C) 2009-2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
 (C) 2010 Alan Stern <stern@rowland.harvard.edu>
 
 1. Introduction
@@ -44,11 +44,12 @@
 };
 
 The ->runtime_suspend(), ->runtime_resume() and ->runtime_idle() callbacks are
-executed by the PM core for either the bus type, or device type (if the bus
-type's callback is not defined), or device class (if the bus type's and device
-type's callbacks are not defined) of given device.  The bus type, device type
-and device class callbacks are referred to as subsystem-level callbacks in what
-follows.
+executed by the PM core for either the device type, or the class (if the device
+type's struct dev_pm_ops object does not exist), or the bus type (if the
+device type's and class' struct dev_pm_ops objects do not exist) of the given
+device (this allows device types to override callbacks provided by bus types or
+classes if necessary).  The bus type, device type and class callbacks are
+referred to as subsystem-level callbacks in what follows.
 
 By default, the callbacks are always invoked in process context with interrupts
 enabled.  However, subsystems can use the pm_runtime_irq_safe() helper function
diff -druN linux-libre-2.6.38-gnu/Documentation/power/states.txt linux-libre-2.6.39-gnu/Documentation/power/states.txt
--- linux-libre-2.6.38-gnu/Documentation/power/states.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/states.txt	2011-05-19 00:06:34.000000000 -0400
@@ -62,12 +62,12 @@
 inconvenience, this method requires minimal work by the kernel, since
 the firmware will also handle restoring memory contents on resume. 
 
-For suspend-to-disk, a mechanism called swsusp called 'swsusp' (Swap
-Suspend) is used to write memory contents to free swap space.
-swsusp has some restrictive requirements, but should work in most
-cases. Some, albeit outdated, documentation can be found in
-Documentation/power/swsusp.txt. Alternatively, userspace can do most
-of the actual suspend to disk work, see userland-swsusp.txt.
+For suspend-to-disk, a mechanism called 'swsusp' (Swap Suspend) is used
+to write memory contents to free swap space. swsusp has some restrictive
+requirements, but should work in most cases. Some, albeit outdated,
+documentation can be found in Documentation/power/swsusp.txt.
+Alternatively, userspace can do most of the actual suspend to disk work,
+see userland-swsusp.txt.
 
 Once memory state is written to disk, the system may either enter a
 low-power state (like ACPI S4), or it may simply power down. Powering
diff -druN linux-libre-2.6.38-gnu/Documentation/power/swsusp.txt linux-libre-2.6.39-gnu/Documentation/power/swsusp.txt
--- linux-libre-2.6.38-gnu/Documentation/power/swsusp.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/swsusp.txt	2011-05-19 00:06:34.000000000 -0400
@@ -192,7 +192,7 @@
 distinctions between SUSPEND and FREEZE.
 
 A: Doing SUSPEND when you are asked to do FREEZE is always correct,
-but it may be unneccessarily slow. If you want your driver to stay simple,
+but it may be unnecessarily slow. If you want your driver to stay simple,
 slowness may not matter to you. It can always be fixed later.
 
 For devices like disk it does matter, you do not want to spindown for
@@ -237,7 +237,7 @@
 
       running system, user asks for suspend-to-disk
 
-      user processes are stopped (in common case there are none, but with resume-from-initrd, noone knows)
+      user processes are stopped (in common case there are none, but with resume-from-initrd, no one knows)
 
       read image from disk
 
diff -druN linux-libre-2.6.38-gnu/Documentation/power/userland-swsusp.txt linux-libre-2.6.39-gnu/Documentation/power/userland-swsusp.txt
--- linux-libre-2.6.38-gnu/Documentation/power/userland-swsusp.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/power/userland-swsusp.txt	2011-05-19 00:06:34.000000000 -0400
@@ -98,7 +98,7 @@
 The device's read() operation can be used to transfer the snapshot image from
 the kernel.  It has the following limitations:
 - you cannot read() more than one virtual memory page at a time
-- read()s accross page boundaries are impossible (ie. if ypu read() 1/2 of
+- read()s across page boundaries are impossible (ie. if ypu read() 1/2 of
 	a page in the previous call, you will only be able to read()
 	_at_ _most_ 1/2 of the page in the next call)
 
@@ -137,7 +137,7 @@
 means, such as checksums, to ensure the integrity of the snapshot image.
 
 The suspending and resuming utilities MUST lock themselves in memory,
-preferrably using mlockall(), before calling SNAPSHOT_FREEZE.
+preferably using mlockall(), before calling SNAPSHOT_FREEZE.
 
 The suspending utility MUST check the value stored by SNAPSHOT_CREATE_IMAGE
 in the memory location pointed to by the last argument of ioctl() and proceed
@@ -147,7 +147,7 @@
 	(a)	The suspending utility MUST NOT close the snapshot device
 		_unless_ the whole suspend procedure is to be cancelled, in
 		which case, if the snapshot image has already been saved, the
-		suspending utility SHOULD destroy it, preferrably by zapping
+		suspending utility SHOULD destroy it, preferably by zapping
 		its header.  If the suspend is not to be cancelled, the
 		system MUST be powered off or rebooted after the snapshot
 		image has been saved.
diff -druN linux-libre-2.6.38-gnu/Documentation/powerpc/00-INDEX linux-libre-2.6.39-gnu/Documentation/powerpc/00-INDEX
--- linux-libre-2.6.38-gnu/Documentation/powerpc/00-INDEX	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/powerpc/00-INDEX	2011-05-19 00:06:34.000000000 -0400
@@ -5,8 +5,6 @@
 
 00-INDEX
 	- this file
-booting-without-of.txt
-	- Booting the Linux/ppc kernel without Open Firmware
 cpu_features.txt
 	- info on how we support a variety of CPUs with minimal compile-time
 	options.
@@ -16,8 +14,6 @@
 	- IBM "Hypervisor Virtual Console Server" Installation Guide
 mpc52xx.txt
 	- Linux 2.6.x on MPC52xx family
-mpc52xx-device-tree-bindings.txt
-	- MPC5200 Device Tree Bindings
 sound.txt
 	- info on sound support under Linux/PPC
 zImage_layout.txt
diff -druN linux-libre-2.6.38-gnu/Documentation/powerpc/hvcs.txt linux-libre-2.6.39-gnu/Documentation/powerpc/hvcs.txt
--- linux-libre-2.6.38-gnu/Documentation/powerpc/hvcs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/powerpc/hvcs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -528,7 +528,7 @@
 order than how they would be exposed on module load.  Rebooting or
 reloading the module after dynamic addition may result in the /dev/hvcs*
 and vty-server coupling changing if a vty-server adapter was added in a
-slot inbetween two other vty-server adapters.  Refer to the section above
+slot between two other vty-server adapters.  Refer to the section above
 on how to determine which vty-server goes with which /dev/hvcs* node.
 Hint; look at the sysfs "index" attribute for the vty-server.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/rapidio/rapidio.txt linux-libre-2.6.39-gnu/Documentation/rapidio/rapidio.txt
--- linux-libre-2.6.38-gnu/Documentation/rapidio/rapidio.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/rapidio/rapidio.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,173 @@
+                          The Linux RapidIO Subsystem
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+The RapidIO standard is a packet-based fabric interconnect standard designed for
+use in embedded systems. Development of the RapidIO standard is directed by the
+RapidIO Trade Association (RTA). The current version of the RapidIO specification
+is publicly available for download from the RTA web-site [1].
+
+This document describes the basics of the Linux RapidIO subsystem and provides
+information on its major components.
+
+1 Overview
+----------
+
+Because the RapidIO subsystem follows the Linux device model it is integrated
+into the kernel similarly to other buses by defining RapidIO-specific device and
+bus types and registering them within the device model.
+
+The Linux RapidIO subsystem is architecture independent and therefore defines
+architecture-specific interfaces that provide support for common RapidIO
+subsystem operations.
+
+2. Core Components
+------------------
+
+A typical RapidIO network is a combination of endpoints and switches.
+Each of these components is represented in the subsystem by an associated data
+structure. The core logical components of the RapidIO subsystem are defined
+in include/linux/rio.h file.
+
+2.1 Master Port
+
+A master port (or mport) is a RapidIO interface controller that is local to the
+processor executing the Linux code. A master port generates and receives RapidIO
+packets (transactions). In the RapidIO subsystem each master port is represented
+by a rio_mport data structure. This structure contains master port specific
+resources such as mailboxes and doorbells. The rio_mport also includes a unique
+host device ID that is valid when a master port is configured as an enumerating
+host.
+
+RapidIO master ports are serviced by subsystem specific mport device drivers
+that provide functionality defined for this subsystem. To provide a hardware
+independent interface for RapidIO subsystem operations, rio_mport structure
+includes rio_ops data structure which contains pointers to hardware specific
+implementations of RapidIO functions.
+
+2.2 Device
+
+A RapidIO device is any endpoint (other than mport) or switch in the network.
+All devices are presented in the RapidIO subsystem by corresponding rio_dev data
+structure. Devices form one global device list and per-network device lists
+(depending on number of available mports and networks).
+
+2.3 Switch
+
+A RapidIO switch is a special class of device that routes packets between its
+ports towards their final destination. The packet destination port within a
+switch is defined by an internal routing table. A switch is presented in the
+RapidIO subsystem by rio_dev data structure expanded by additional rio_switch
+data structure, which contains switch specific information such as copy of the
+routing table and pointers to switch specific functions.
+
+The RapidIO subsystem defines the format and initialization method for subsystem
+specific switch drivers that are designed to provide hardware-specific
+implementation of common switch management routines.
+
+2.4 Network
+
+A RapidIO network is a combination of interconnected endpoint and switch devices.
+Each RapidIO network known to the system is represented by corresponding rio_net
+data structure. This structure includes lists of all devices and local master
+ports that form the same network. It also contains a pointer to the default
+master port that is used to communicate with devices within the network.
+
+3. Subsystem Initialization
+---------------------------
+
+In order to initialize the RapidIO subsystem, a platform must initialize and
+register at least one master port within the RapidIO network. To register mport
+within the subsystem controller driver initialization code calls function
+rio_register_mport() for each available master port. After all active master
+ports are registered with a RapidIO subsystem, the rio_init_mports() routine
+is called to perform enumeration and discovery.
+
+In the current PowerPC-based implementation a subsys_initcall() is specified to
+perform controller initialization and mport registration. At the end it directly
+calls rio_init_mports() to execute RapidIO enumeration and discovery.
+
+4. Enumeration and Discovery
+----------------------------
+
+When rio_init_mports() is called it scans a list of registered master ports and
+calls an enumeration or discovery routine depending on the configured role of a
+master port: host or agent.
+
+Enumeration is performed by a master port if it is configured as a host port by
+assigning a host device ID greater than or equal to zero. A host device ID is
+assigned to a master port through the kernel command line parameter "riohdid=",
+or can be configured in a platform-specific manner. If the host device ID for
+a specific master port is set to -1, the discovery process will be performed
+for it.
+
+The enumeration and discovery routines use RapidIO maintenance transactions
+to access the configuration space of devices.
+
+The enumeration process is implemented according to the enumeration algorithm
+outlined in the RapidIO Interconnect Specification: Annex I [1].
+
+The enumeration process traverses the network using a recursive depth-first
+algorithm. When a new device is found, the enumerator takes ownership of that
+device by writing into the Host Device ID Lock CSR. It does this to ensure that
+the enumerator has exclusive right to enumerate the device. If device ownership
+is successfully acquired, the enumerator allocates a new rio_dev structure and
+initializes it according to device capabilities.
+
+If the device is an endpoint, a unique device ID is assigned to it and its value
+is written into the device's Base Device ID CSR.
+
+If the device is a switch, the enumerator allocates an additional rio_switch
+structure to store switch specific information. Then the switch's vendor ID and
+device ID are queried against a table of known RapidIO switches. Each switch
+table entry contains a pointer to a switch-specific initialization routine that
+initializes pointers to the rest of switch specific operations, and performs
+hardware initialization if necessary. A RapidIO switch does not have a unique
+device ID; it relies on hopcount and routing for device ID of an attached
+endpoint if access to its configuration registers is required. If a switch (or
+chain of switches) does not have any endpoint (except enumerator) attached to
+it, a fake device ID will be assigned to configure a route to that switch.
+In the case of a chain of switches without endpoint, one fake device ID is used
+to configure a route through the entire chain and switches are differentiated by
+their hopcount value.
+
+For both endpoints and switches the enumerator writes a unique component tag
+into device's Component Tag CSR. That unique value is used by the error
+management notification mechanism to identify a device that is reporting an
+error management event.
+
+Enumeration beyond a switch is completed by iterating over each active egress
+port of that switch. For each active link, a route to a default device ID
+(0xFF for 8-bit systems and 0xFFFF for 16-bit systems) is temporarily written
+into the routing table. The algorithm recurs by calling itself with hopcount + 1
+and the default device ID in order to access the device on the active port.
+
+After the host has completed enumeration of the entire network it releases
+devices by clearing device ID locks (calls rio_clear_locks()). For each endpoint
+in the system, it sets the Master Enable bit in the Port General Control CSR
+to indicate that enumeration is completed and agents are allowed to execute
+passive discovery of the network.
+
+The discovery process is performed by agents and is similar to the enumeration
+process that is described above. However, the discovery process is performed
+without changes to the existing routing because agents only gather information
+about RapidIO network structure and are building an internal map of discovered
+devices. This way each Linux-based component of the RapidIO subsystem has
+a complete view of the network. The discovery process can be performed
+simultaneously by several agents. After initializing its RapidIO master port
+each agent waits for enumeration completion by the host for the configured wait
+time period. If this wait time period expires before enumeration is completed,
+an agent skips RapidIO discovery and continues with remaining kernel
+initialization.
+
+5. References
+-------------
+
+[1] RapidIO Trade Association. RapidIO Interconnect Specifications.
+    http://www.rapidio.org.
+[2] Rapidio TA. Technology Comparisons.
+    http://www.rapidio.org/education/technology_comparisons/
+[3] RapidIO support for Linux.
+    http://lwn.net/Articles/139118/
+[4] Matt Porter. RapidIO for Linux. Ottawa Linux Symposium, 2005
+    http://www.kernel.org/doc/ols/2005/ols2005v2-pages-43-56.pdf
diff -druN linux-libre-2.6.38-gnu/Documentation/rapidio/sysfs.txt linux-libre-2.6.39-gnu/Documentation/rapidio/sysfs.txt
--- linux-libre-2.6.38-gnu/Documentation/rapidio/sysfs.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/rapidio/sysfs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,90 @@
+                         RapidIO sysfs Files
+
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+1. Device Subdirectories
+------------------------
+
+For each RapidIO device, the RapidIO subsystem creates files in an individual
+subdirectory with the following name, /sys/bus/rapidio/devices/<device_name>.
+
+The format of device_name is "nn:d:iiii", where:
+
+nn - two-digit hexadecimal ID of RapidIO network where the device resides
+d  - device typr: 'e' - for endpoint or 's' - for switch
+iiii - four-digit device destID for endpoints, or switchID for switches
+
+For example, below is a list of device directories that represents a typical
+RapidIO network with one switch, one host, and two agent endpoints, as it is
+seen by the enumerating host (destID = 1):
+
+/sys/bus/rapidio/devices/00:e:0000
+/sys/bus/rapidio/devices/00:e:0002
+/sys/bus/rapidio/devices/00:s:0001
+
+NOTE: An enumerating or discovering endpoint does not create a sysfs entry for
+itself, this is why an endpoint with destID=1 is not shown in the list.
+
+2. Attributes Common for All Devices
+------------------------------------
+
+Each device subdirectory contains the following informational read-only files:
+
+       did - returns the device identifier
+       vid - returns the device vendor identifier
+device_rev - returns the device revision level
+   asm_did - returns identifier for the assembly containing the device
+   asm_rev - returns revision level of the assembly containing the device
+   asm_vid - returns vendor identifier of the assembly containing the device
+   destid  - returns device destination ID assigned by the enumeration routine
+             (see 4.1 for switch specific details)
+   lprev   - returns name of previous device (switch) on the path to the device
+             that that owns this attribute
+
+In addition to the files listed above, each device has a binary attribute file
+that allows read/write access to the device configuration registers using
+the RapidIO maintenance transactions:
+
+ config - reads from and writes to the device configuration registers.
+
+This attribute is similar in behavior to the "config" attribute of PCI devices
+and provides an access to the RapidIO device registers using standard file read
+and write operations.
+
+3. Endpoint Device Attributes
+-----------------------------
+
+Currently Linux RapidIO subsystem does not create any endpoint specific sysfs
+attributes. It is possible that RapidIO master port drivers and endpoint device
+drivers will add their device-specific sysfs attributes but such attributes are
+outside the scope of this document.
+
+4. Switch Device Attributes
+---------------------------
+
+RapidIO switches have additional attributes in sysfs. RapidIO subsystem supports
+common and device-specific sysfs attributes for switches. Because switches are
+integrated into the RapidIO subsystem, it offers a method to create
+device-specific sysfs attributes by specifying a callback function that may be
+set by the switch initialization routine during enumeration or discovery process.
+
+4.1 Common Switch Attributes
+
+   routes - reports switch routing information in "destID port" format. This
+            attribute reports only valid routing table entries, one line for
+            each entry.
+   destid - device destination ID that defines a route to the switch
+ hopcount - number of hops on the path to the switch
+    lnext - returns names of devices linked to the switch except one of a device
+            linked to the ingress port (reported as "lprev"). This is an array
+            names with number of lines equal to number of ports in switch. If
+            a switch port has no attached device, returns "null" instead of
+            a device name.
+
+4.2 Device-specific Switch Attributes
+
+Device-specific switch attributes are listed for each RapidIO switch driver
+that exports additional attributes.
+
+IDT_GEN2:
+ errlog - reads contents of device error log until it is empty.
diff -druN linux-libre-2.6.38-gnu/Documentation/RCU/whatisRCU.txt linux-libre-2.6.39-gnu/Documentation/RCU/whatisRCU.txt
--- linux-libre-2.6.38-gnu/Documentation/RCU/whatisRCU.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/RCU/whatisRCU.txt	2011-05-19 00:06:34.000000000 -0400
@@ -849,6 +849,37 @@
 See the comment headers in the source code (or the docbook generated
 from them) for more information.
 
+However, given that there are no fewer than four families of RCU APIs
+in the Linux kernel, how do you choose which one to use?  The following
+list can be helpful:
+
+a.	Will readers need to block?  If so, you need SRCU.
+
+b.	What about the -rt patchset?  If readers would need to block
+	in an non-rt kernel, you need SRCU.  If readers would block
+	in a -rt kernel, but not in a non-rt kernel, SRCU is not
+	necessary.
+
+c.	Do you need to treat NMI handlers, hardirq handlers,
+	and code segments with preemption disabled (whether
+	via preempt_disable(), local_irq_save(), local_bh_disable(),
+	or some other mechanism) as if they were explicit RCU readers?
+	If so, you need RCU-sched.
+
+d.	Do you need RCU grace periods to complete even in the face
+	of softirq monopolization of one or more of the CPUs?  For
+	example, is your code subject to network-based denial-of-service
+	attacks?  If so, you need RCU-bh.
+
+e.	Is your workload too update-intensive for normal use of
+	RCU, but inappropriate for other synchronization mechanisms?
+	If so, consider SLAB_DESTROY_BY_RCU.  But please be careful!
+
+f.	Otherwise, use RCU.
+
+Of course, this all assumes that you have determined that RCU is in fact
+the right tool for your job.
+
 
 8.  ANSWERS TO QUICK QUIZZES
 
diff -druN linux-libre-2.6.38-gnu/Documentation/rtc.txt linux-libre-2.6.39-gnu/Documentation/rtc.txt
--- linux-libre-2.6.38-gnu/Documentation/rtc.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/rtc.txt	2011-05-19 00:06:34.000000000 -0400
@@ -178,38 +178,29 @@
 	setting the longer alarm time and enabling its IRQ using a single
 	request (using the same model as EFI firmware).
 
-    *	RTC_UIE_ON, RTC_UIE_OFF ... if the RTC offers IRQs, it probably
-	also offers update IRQs whenever the "seconds" counter changes.
-	If needed, the RTC framework can emulate this mechanism.
+    *	RTC_UIE_ON, RTC_UIE_OFF ... if the RTC offers IRQs, the RTC framework
+	will emulate this mechanism.
 
-    *	RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ ... another
-	feature often accessible with an IRQ line is a periodic IRQ, issued
-	at settable frequencies (usually 2^N Hz).
+    *	RTC_PIE_ON, RTC_PIE_OFF, RTC_IRQP_SET, RTC_IRQP_READ ... these icotls
+	are emulated via a kernel hrtimer.
 
 In many cases, the RTC alarm can be a system wake event, used to force
 Linux out of a low power sleep state (or hibernation) back to a fully
 operational state.  For example, a system could enter a deep power saving
 state until it's time to execute some scheduled tasks.
 
-Note that many of these ioctls need not actually be implemented by your
-driver.  The common rtc-dev interface handles many of these nicely if your
-driver returns ENOIOCTLCMD.  Some common examples:
+Note that many of these ioctls are handled by the common rtc-dev interface.
+Some common examples:
 
     *	RTC_RD_TIME, RTC_SET_TIME: the read_time/set_time functions will be
 	called with appropriate values.
 
-    *	RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: the
-	set_alarm/read_alarm functions will be called.
+    *	RTC_ALM_SET, RTC_ALM_READ, RTC_WKALM_SET, RTC_WKALM_RD: gets or sets
+	the alarm rtc_timer. May call the set_alarm driver function.
 
-    *	RTC_IRQP_SET, RTC_IRQP_READ: the irq_set_freq function will be called
-	to set the frequency while the framework will handle the read for you
-	since the frequency is stored in the irq_freq member of the rtc_device
-	structure.  Your driver needs to initialize the irq_freq member during
-	init.  Make sure you check the requested frequency is in range of your
-	hardware in the irq_set_freq function.  If it isn't, return -EINVAL.  If
-	you cannot actually change the frequency, do not define irq_set_freq.
+    *	RTC_IRQP_SET, RTC_IRQP_READ: These are emulated by the generic code.
 
-    *	RTC_PIE_ON, RTC_PIE_OFF: the irq_set_state function will be called.
+    *	RTC_PIE_ON, RTC_PIE_OFF: These are also emulated by the generic code.
 
 If all else fails, check out the rtc-test.c driver!
 
diff -druN linux-libre-2.6.38-gnu/Documentation/s390/Debugging390.txt linux-libre-2.6.39-gnu/Documentation/s390/Debugging390.txt
--- linux-libre-2.6.38-gnu/Documentation/s390/Debugging390.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/s390/Debugging390.txt	2011-05-19 00:06:34.000000000 -0400
@@ -2273,7 +2273,7 @@
 There is a lot of useful info in here best found by going in & having a look around,
 so I'll take you through some entries I consider important.
 
-All the processes running on the machine have there own entry defined by
+All the processes running on the machine have their own entry defined by
 /proc/<pid>
 So lets have a look at the init process
 cd /proc/1
diff -druN linux-libre-2.6.38-gnu/Documentation/scheduler/sched-design-CFS.txt linux-libre-2.6.39-gnu/Documentation/scheduler/sched-design-CFS.txt
--- linux-libre-2.6.38-gnu/Documentation/scheduler/sched-design-CFS.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scheduler/sched-design-CFS.txt	2011-05-19 00:06:34.000000000 -0400
@@ -164,7 +164,7 @@
    It puts the scheduling entity (task) into the red-black tree and
    increments the nr_running variable.
 
- - dequeue_tree(...)
+ - dequeue_task(...)
 
    When a task is no longer runnable, this function is called to keep the
    corresponding scheduling entity out of the red-black tree.  It decrements
@@ -195,11 +195,6 @@
    This function is mostly called from time tick functions; it might lead to
    process switch.  This drives the running preemption.
 
- - task_new(...)
-
-   The core scheduler gives the scheduling module an opportunity to manage new
-   task startup.  The CFS scheduling module uses it for group scheduling, while
-   the scheduling module for a real-time task does not use it.
 
 
 
diff -druN linux-libre-2.6.38-gnu/Documentation/scheduler/sched-domains.txt linux-libre-2.6.39-gnu/Documentation/scheduler/sched-domains.txt
--- linux-libre-2.6.38-gnu/Documentation/scheduler/sched-domains.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scheduler/sched-domains.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,7 @@
-Each CPU has a "base" scheduling domain (struct sched_domain). These are
-accessed via cpu_sched_domain(i) and this_sched_domain() macros. The domain
+Each CPU has a "base" scheduling domain (struct sched_domain). The domain
 hierarchy is built from these base domains via the ->parent pointer. ->parent
-MUST be NULL terminated, and domain structures should be per-CPU as they
-are locklessly updated.
+MUST be NULL terminated, and domain structures should be per-CPU as they are
+locklessly updated.
 
 Each scheduling domain spans a number of CPUs (stored in the ->span field).
 A domain's span MUST be a superset of it child's span (this restriction could
@@ -26,11 +25,26 @@
 load of each of its member CPUs, and only when the load of a group becomes
 out of balance are tasks moved between groups.
 
-In kernel/sched.c, rebalance_tick is run periodically on each CPU. This
-function takes its CPU's base sched domain and checks to see if has reached
-its rebalance interval. If so, then it will run load_balance on that domain.
-rebalance_tick then checks the parent sched_domain (if it exists), and the
-parent of the parent and so forth.
+In kernel/sched.c, trigger_load_balance() is run periodically on each CPU
+through scheduler_tick(). It raises a softirq after the next regularly scheduled
+rebalancing event for the current runqueue has arrived. The actual load
+balancing workhorse, run_rebalance_domains()->rebalance_domains(), is then run
+in softirq context (SCHED_SOFTIRQ).
+
+The latter function takes two arguments: the current CPU and whether it was idle
+at the time the scheduler_tick() happened and iterates over all sched domains
+our CPU is on, starting from its base domain and going up the ->parent chain.
+While doing that, it checks to see if the current domain has exhausted its
+rebalance interval. If so, it runs load_balance() on that domain. It then checks
+the parent sched_domain (if it exists), and the parent of the parent and so
+forth.
+
+Initially, load_balance() finds the busiest group in the current sched domain.
+If it succeeds, it looks for the busiest runqueue of all the CPUs' runqueues in
+that group. If it manages to find such a runqueue, it locks both our initial
+CPU's runqueue and the newly found busiest one and starts moving tasks from it
+to our runqueue. The exact number of tasks amounts to an imbalance previously
+computed while iterating over this sched domain's groups.
 
 *** Implementing sched domains ***
 The "base" domain will "span" the first level of the hierarchy. In the case
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/aha152x.txt linux-libre-2.6.39-gnu/Documentation/scsi/aha152x.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/aha152x.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/aha152x.txt	2011-05-19 00:06:34.000000000 -0400
@@ -124,7 +124,7 @@
 the right geometry to be able to interpret it.
 
 Moreover there are certain limitations to the C/H/S addressing scheme,
-namely the address space is limited to upto 255 heads, upto 63 sectors
+namely the address space is limited to up to 255 heads, up to 63 sectors
 and a maximum of 1023 cylinders.
 
 The AHA-1522 BIOS calculates the geometry by fixing the number of heads
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/aic79xx.txt linux-libre-2.6.39-gnu/Documentation/scsi/aic79xx.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/aic79xx.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/aic79xx.txt	2011-05-19 00:06:34.000000000 -0400
@@ -267,7 +267,7 @@
               Option: tag_info:{{value[,value...]}[,{value[,value...]}...]}
           Definition: Set the per-target tagged queue depth on a
                       per controller basis.  Both controllers and targets
-                      may be ommitted indicating that they should retain
+                      may be omitted indicating that they should retain
                       the default tag depth.
             Examples: tag_info:{{16,32,32,64,8,8,,32,32,32,32,32,32,32,32,32}
                         On Controller 0
@@ -291,7 +291,7 @@
                       The rd_strm_bitmask is a 16 bit hex value in which
                       each bit represents a target.  Setting the target's
                       bit to '1' enables read streaming for that
-                      target.  Controllers may be ommitted indicating that
+                      target.  Controllers may be omitted indicating that
                       they should retain the default read streaming setting.
              Example: rd_strm:{0x0041}
                         On Controller 0
@@ -313,7 +313,7 @@
    -----------------------------------------------------------------
               Option: dv: {value[,value...]}
           Definition: Set Domain Validation Policy on a per-controller basis.
-                      Controllers may be ommitted indicating that
+                      Controllers may be omitted indicating that
                       they should retain the default read streaming setting.
              Example: dv:{-1,0,,1,1,0}
                         On Controller 0 leave DV at its default setting.
@@ -340,7 +340,7 @@
               Option: precomp: {value[,value...]}
           Definition: Set IO Cell precompensation value on a per-controller
                       basis.
-                      Controllers may be ommitted indicating that
+                      Controllers may be omitted indicating that
                       they should retain the default precompensation setting.
              Example: precomp:{0x1}
                         On Controller 0 set precompensation to 1.
@@ -353,7 +353,7 @@
    -----------------------------------------------------------------
               Option: slewrate: {value[,value...]}
           Definition: Set IO Cell slew rate on a per-controller basis.
-                      Controllers may be ommitted indicating that
+                      Controllers may be omitted indicating that
                       they should retain the default slew rate setting.
              Example: slewrate:{0x1}
                         On Controller 0 set slew rate to 1.
@@ -366,7 +366,7 @@
    -----------------------------------------------------------------
               Option: amplitude: {value[,value...]}
           Definition: Set IO Cell signal amplitude on a per-controller basis.
-                      Controllers may be ommitted indicating that
+                      Controllers may be omitted indicating that
                       they should retain the default read streaming setting.
              Example: amplitude:{0x1}
                         On Controller 0 set amplitude to 1.
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.lpfc linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.lpfc
--- linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.lpfc	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.lpfc	2011-05-19 00:06:34.000000000 -0400
@@ -352,7 +352,7 @@
 	  lpfc_scsiport.c
 	* In remote port changes: no longer nulling target->pnode when
 	  removing from mapped list. Pnode get nulled when the node is
-	  freed (after nodev tmo). This bug was causing i/o recieved in
+	  freed (after nodev tmo). This bug was causing i/o received in
 	  the small window while the device was blocked to be errored w/
 	  did_no_connect. With the fix, it returns host_busy
 	  (per the pre-remote port changes).
@@ -530,7 +530,7 @@
 	  coherent mappings.  Note: There are more consistent mappings
 	  that are using pci_dma_sync calls. Probably these should be
 	  removed as well.
-	* Modified lpfc_free_scsi_buf to accomodate all three scsi_buf
+	* Modified lpfc_free_scsi_buf to accommodate all three scsi_buf
 	  free types to alleviate miscellaneous panics with cable pull
 	  testing.
 	* Set hotplug to default 0 and lpfc_target_remove to not remove
@@ -583,7 +583,7 @@
 	  included more than once.
 	* Replaced "set_current_state(TASK_UNINTERRUPTIBLE);
 	  schedule_timeout(timeout)" with "msleep(timeout)".
-	* Fixnode was loosing starget when rediscovered. We saw messages
+	* Fixnode was losing starget when rediscovered. We saw messages
 	  like: lpfc 0000:04:02.0: 0:0263 Cannot block scsi target as a
 	  result.  Moved starget field into struct lpfc_target which is
 	  referenced from the node.
@@ -604,7 +604,7 @@
 	* Make 3 functions static: lpfc_get_hba_sym_node_name,
 	  lpfc_intr_prep and lpfc_setup_slim_access.  Move lpfc_intr_prep
 	  and lpfc_setup_slim_access so they're defined before being used.
-	* Remove an unecessary list_del() in lpfc_hbadisc.c.
+	* Remove an unnecessary list_del() in lpfc_hbadisc.c.
 	* Set nlp_state before calling lpfc_nlp_list() since this will
 	  potentially call fc_target_unblock which may cause a race in
 	  queuecommand by releasing host_lock.
@@ -753,7 +753,7 @@
 	* Changed version number to 8.0.12
 	* Removed used #defines: DEFAULT_PCI_LATENCY_CLOCKS and
 	  PCI_LATENCY_VALUE from lpfc_hw.h.
-	* Changes to accomodate rnid.
+	* Changes to accommodate rnid.
 	* Fix RSCN handling so RSCN NS queries only effect NPorts found in
 	  RSCN data.
 	* If we rcv a plogi on a NPort queued up for discovery, clear the
@@ -813,7 +813,7 @@
 	  counter instead, brd_no isn't reused anymore.  Also some tiny
 	  whitespace cleanups in surrounding code.
 	* Reorder functions in lpfc_els.c to remove need for prototypes.
-	* Removed unsed prototypes from lpfc_crtn.h -
+	* Removed unused prototypes from lpfc_crtn.h -
 	  lpfc_ip_timeout_handler, lpfc_read_pci and lpfc_revoke.
 	* Removed some unused prototypes from lpfc_crtn.h -
 	  lpfc_scsi_hba_reset, lpfc_scsi_issue_inqsn,
@@ -863,7 +863,7 @@
 	* Minimal support for SCSI flat space addressing/volume set
 	  addressing.  Use 16 bits of LUN address so that flat
 	  addressing/VSA will work.
-	* Changed 2 occurences of if( 1 != f(x)) to if(f(x) != 1)
+	* Changed 2 occurrences of if( 1 != f(x)) to if(f(x) != 1)
 	* Drop include of lpfc_cfgparm.h.
 	* Reduce stack usage of lpfc_fdmi_cmd in lpfc_ct.c.
 	* Add minimum range checking property to /sys write/store
@@ -1449,7 +1449,7 @@
 	* Removed lpfc_els_chk_latt from the lpfc_config_post function.
 	  lpfc_els_chk_latt will enable the link event interrupts when
 	  flogi is pending which causes two discovery state machines
-	  running parallely.
+	  running parallelly.
 	* Add pci_disable_device to unload path.
 	* Move lpfc_sleep_event from lpfc_fcp.c to lpfc_util_ioctl.c
 	* Call dma_map_single() & pci_map_single() directly instead of via
@@ -1590,7 +1590,7 @@
 	  ELX_WRITE_HS ELX_WRITE_HA ELX_WRITE_CA ELX_READ_HC
 	  ELX_READ_HS ELX_READ_HA ELX_READ_CA ELX_READ_MB ELX_RESET
 	  ELX_READ_HBA ELX_INSTANCE ELX_LIP.  Also introduced
-	  attribute "set" to be used in conjuction with the above
+	  attribute "set" to be used in conjunction with the above
 	  attributes.
 	* Removed DLINK, enque and deque declarations now that clock
 	  doesn't use them anymore
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.megaraid linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.megaraid
--- linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.megaraid	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.megaraid	2011-05-19 00:06:34.000000000 -0400
@@ -168,7 +168,7 @@
 
 1.	Sorted out PCI IDs to remove megaraid support overlaps.
 	Based on the patch from Daniel, sorted out PCI IDs along with
-	charactor node name change from 'megadev' to 'megadev_legacy' to avoid
+	character node name change from 'megadev' to 'megadev_legacy' to avoid
 	conflict.
 	---
 	Hopefully we'll be getting the build restriction zapped much sooner, 
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.megaraid_sas linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.megaraid_sas
--- linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.megaraid_sas	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.megaraid_sas	2011-05-19 00:06:34.000000000 -0400
@@ -1,3 +1,26 @@
+Release Date    : Thu. Feb 24, 2011 17:00:00 PST 2010 -
+			(emaild-id:megaraidlinux@lsi.com)
+			Adam Radford
+Current Version : 00.00.05.34-rc1
+Old Version     : 00.00.05.29-rc1
+    1. Fix some failure gotos from megasas_probe_one(), etc.
+    2. Add missing check_and_restore_queue_depth() call in
+       complete_cmd_fusion().
+    3. Enable MSI-X before calling megasas_init_fw().
+    4. Call tasklet_schedule() even if outbound_intr_status == 0 for MFI based
+       boards in MSI-X mode.
+    5. Fix megasas_probe_one() to clear PCI_MSIX_FLAGS_ENABLE in msi control
+       register in kdump kernel.
+    6. Fix megasas_get_cmd() to only print "Command pool empty" if
+       megasas_dbg_lvl is set.
+    7. Fix megasas_build_dcdb_fusion() to not filter by TYPE_DISK.
+    8. Fix megasas_build_dcdb_fusion() to use io_request->LUN[1] field.
+    9. Add MR_EVT_CFG_CLEARED to megasas_aen_polling().
+    10. Fix tasklet_init() in megasas_init_fw() to use instancet->tasklet.
+    11. Fix fault state handling in megasas_transition_to_ready().
+    12. Fix max_sectors setting for IEEE SGL's.
+    13. Fix iMR OCR support to work correctly.
+-------------------------------------------------------------------------------
 Release Date    : Tues.  Dec 14, 2010 17:00:00 PST 2010 -
 			(emaild-id:megaraidlinux@lsi.com)
 			Adam Radford
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.ncr53c8xx linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.ncr53c8xx
--- linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.ncr53c8xx	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.ncr53c8xx	2011-05-19 00:06:34.000000000 -0400
@@ -200,7 +200,7 @@
 	  By default the driver uses both IRQF_SHARED and IRQF_DISABLED.
 	  Option 'ncr53c8xx=irqm:0x20' may be used when an IRQ is shared by 
 	  a 53C8XX adapter and a network board.
-	- Tiny mispelling fixed (ABORT instead of ABRT). Was fortunately 
+	- Tiny misspelling fixed (ABORT instead of ABRT). Was fortunately 
 	  harmless.
 	- Negotiate SYNC data transfers with CCS devices.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.sym53c8xx linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.sym53c8xx
--- linux-libre-2.6.38-gnu/Documentation/scsi/ChangeLog.sym53c8xx	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/ChangeLog.sym53c8xx	2011-05-19 00:06:34.000000000 -0400
@@ -457,7 +457,7 @@
 Sat Dec 19  21:00 1998 Gerard Roudier (groudier@club-internet.fr)
 	* version sym53c8xx-1.0
 	- Define some new IO registers for the 896 (istat1, mbox0, mbox1)
-	- Revamp slighly the Symbios NVRAM lay-out based on the excerpt of 
+	- Revamp slightly the Symbios NVRAM lay-out based on the excerpt of 
 	  the header file I received from Symbios.
 	- Check the PCI bus number for the boot order (Using a fast 
 	  PCI controller behing a PCI-PCI bridge seems sub-optimal).
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/hpsa.txt linux-libre-2.6.39-gnu/Documentation/scsi/hpsa.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/hpsa.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/hpsa.txt	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,12 @@
 nor supported by HP with this driver.  For older Smart Arrays, the cciss
 driver should still be used.
 
+The "hpsa_simple_mode=1" boot parameter may be used to prevent the driver from
+putting the controller into "performant" mode.  The difference is that with simple
+mode, each command completion requires an interrupt, while with "performant mode"
+(the default, and ordinarily better performing) it is possible to have multiple
+command completions indicated by a single interrupt.
+
 HPSA specific entries in /sys
 -----------------------------
 
@@ -39,6 +45,8 @@
 
   /sys/class/scsi_host/host*/rescan
   /sys/class/scsi_host/host*/firmware_revision
+  /sys/class/scsi_host/host*/resettable
+  /sys/class/scsi_host/host*/transport_mode
 
   the host "rescan" attribute is a write only attribute.  Writing to this
   attribute will cause the driver to scan for new, changed, or removed devices
@@ -55,6 +63,21 @@
 	root@host:/sys/class/scsi_host/host4# cat firmware_revision
 	7.14
 
+  The transport_mode indicates whether the controller is in "performant"
+  or "simple" mode.  This is controlled by the "hpsa_simple_mode" module
+  parameter.
+
+  The "resettable" read-only attribute indicates whether a particular
+  controller is able to honor the "reset_devices" kernel parameter.  If the
+  device is resettable, this file will contain a "1", otherwise, a "0".  This
+  parameter is used by kdump, for example, to reset the controller at driver
+  load time to eliminate any outstanding commands on the controller and get the
+  controller into a known state so that the kdump initiated i/o will work right
+  and not be disrupted in any way by stale commands or other stale state
+  remaining on the controller from the previous kernel.  This attribute enables
+  kexec tools to warn the user if they attempt to designate a device which is
+  unable to honor the reset_devices kernel parameter as a dump device.
+
   HPSA specific disk attributes:
   ------------------------------
 
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/ibmmca.txt linux-libre-2.6.39-gnu/Documentation/scsi/ibmmca.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/ibmmca.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/ibmmca.txt	2011-05-19 00:06:34.000000000 -0400
@@ -303,7 +303,7 @@
    (scb) and calls a local function issue_cmd(), which writes a scb 
    command into subsystem I/O ports. Once the scb command is carried out, 
    the interrupt_handler() is invoked. If a device is determined to be 
-   existant and it has not assigned any ldn, it gets one dynamically.
+   existent and it has not assigned any ldn, it gets one dynamically.
    For this, the whole stuff is done in ibmmca_queuecommand().
 
    2.6 Abort & Reset Commands
@@ -741,7 +741,7 @@
       some error appeared, else it is undefined. Now, this is fixed. Before
       any SCB command gets queued, the tsb.dev_status is set to 0, so the 
       cmd->result won't screw up Linux higher level drivers.
-   2) The reset-function has slightly improved. This is still planed for 
+   2) The reset-function has slightly improved. This is still planned for 
       abort. During the abort and the reset function, no interrupts are 
       allowed. This is however quite hard to cope with, so the INT-status
       register is read. When the interrupt gets queued, one can find its
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/scsi-changer.txt linux-libre-2.6.39-gnu/Documentation/scsi/scsi-changer.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/scsi-changer.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/scsi-changer.txt	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,7 @@
 
 If you insmod the driver with "insmod debug=1", it will be verbose and
 prints a lot of stuff to the syslog.  Compiling the kernel with
-CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages alot
+CONFIG_SCSI_CONSTANTS=y improves the quality of the error messages a lot
 because the kernel will translate the error codes into human-readable
 strings then.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/scsi_eh.txt linux-libre-2.6.39-gnu/Documentation/scsi/scsi_eh.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/scsi_eh.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/scsi_eh.txt	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
 	SCSI transports/LLDDs automatically acquire sense data on
 	command failures (autosense).  Autosense is recommended for
 	performance reasons and as sense information could get out of
-	sync inbetween occurrence of CHECK CONDITION and this action.
+	sync between occurrence of CHECK CONDITION and this action.
 
 	Note that if autosense is not supported, scmd->sense_buffer
 	contains invalid sense data when error-completing the scmd
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/scsi_fc_transport.txt linux-libre-2.6.39-gnu/Documentation/scsi/scsi_fc_transport.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/scsi_fc_transport.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/scsi_fc_transport.txt	2011-05-19 00:06:34.000000000 -0400
@@ -291,7 +291,7 @@
 Vport support by LLDD:
 
   The LLDD indicates support for vports by supplying a vport_create()
-  function in the transport template.  The presense of this function will
+  function in the transport template.  The presence of this function will
   cause the creation of the new attributes on the fc_host.  As part of
   the physical port completing its initialization relative to the
   transport, it should set the max_npiv_vports attribute to indicate the
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/scsi_mid_low_api.txt linux-libre-2.6.39-gnu/Documentation/scsi/scsi_mid_low_api.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/scsi_mid_low_api.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/scsi_mid_low_api.txt	2011-05-19 00:06:34.000000000 -0400
@@ -1343,7 +1343,7 @@
                    underruns (overruns should be rare). If possible an LLD
                    should set 'resid' prior to invoking 'done'. The most
                    interesting case is data transfers from a SCSI target
-                   device device (i.e. READs) that underrun. 
+                   device (e.g. READs) that underrun.
     underflow    - LLD should place (DID_ERROR << 16) in 'result' if
                    actual number of bytes transferred is less than this
                    figure. Not many LLDs implement this check and some that
@@ -1351,6 +1351,18 @@
                    report a DID_ERROR. Better for an LLD to implement
                    'resid'.
 
+It is recommended that a LLD set 'resid' on data transfers from a SCSI
+target device (e.g. READs). It is especially important that 'resid' is set
+when such data transfers have sense keys of MEDIUM ERROR and HARDWARE ERROR
+(and possibly RECOVERED ERROR). In these cases if a LLD is in doubt how much
+data has been received then the safest approach is to indicate no bytes have
+been received. For example: to indicate that no valid data has been received
+a LLD might use these helpers:
+    scsi_set_resid(SCpnt, scsi_bufflen(SCpnt));
+where 'SCpnt' is a pointer to a scsi_cmnd object. To indicate only three 512
+bytes blocks has been received 'resid' could be set like this:
+    scsi_set_resid(SCpnt, scsi_bufflen(SCpnt) - (3 * 512));
+
 The scsi_cmnd structure is defined in include/scsi/scsi_cmnd.h
 
 
diff -druN linux-libre-2.6.38-gnu/Documentation/scsi/sym53c8xx_2.txt linux-libre-2.6.39-gnu/Documentation/scsi/sym53c8xx_2.txt
--- linux-libre-2.6.38-gnu/Documentation/scsi/sym53c8xx_2.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/scsi/sym53c8xx_2.txt	2011-05-19 00:06:34.000000000 -0400
@@ -285,7 +285,7 @@
 
 7. Profiling information
 
-This driver does not provide profiling informations as did its predecessors.
+This driver does not provide profiling information as did its predecessors.
 This feature was not this useful and added complexity to the code. 
 As the driver code got more complex, I have decided to remove everything 
 that didn't seem actually useful.
diff -druN linux-libre-2.6.38-gnu/Documentation/SecurityBugs linux-libre-2.6.39-gnu/Documentation/SecurityBugs
--- linux-libre-2.6.38-gnu/Documentation/SecurityBugs	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/SecurityBugs	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,7 @@
 A disclosure date is negotiated by the security team working with the
 bug submitter as well as vendors.  However, the kernel security team
 holds the final say when setting a disclosure date.  The timeframe for
-disclosure is from immediate (esp. if it's already publically known)
+disclosure is from immediate (esp. if it's already publicly known)
 to a few weeks.  As a basic default policy, we expect report date to
 disclosure date to be on the order of 7 days.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/serial/moxa-smartio linux-libre-2.6.39-gnu/Documentation/serial/moxa-smartio
--- linux-libre-2.6.38-gnu/Documentation/serial/moxa-smartio	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/serial/moxa-smartio	2011-05-19 00:06:34.000000000 -0400
@@ -473,7 +473,7 @@
    spd_normal	  Use  38.4kb  when  the application requests 38.4kb.
    spd_cust	  Use  the custom divisor to set the speed when  the
 		  application requests 38.4kb.
-   divisor	  This option set the custom divison.
+   divisor	  This option set the custom division.
    baud_base	  This option set the base baud rate.
 
 -----------------------------------------------------------------------------
diff -druN linux-libre-2.6.38-gnu/Documentation/serial/n_gsm.txt linux-libre-2.6.39-gnu/Documentation/serial/n_gsm.txt
--- linux-libre-2.6.38-gnu/Documentation/serial/n_gsm.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/serial/n_gsm.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,89 @@
+n_gsm.c GSM 0710 tty multiplexor HOWTO
+===================================================
+
+This line discipline implements the GSM 07.10 multiplexing protocol
+detailed in the following 3GPP document :
+http://www.3gpp.org/ftp/Specs/archive/07_series/07.10/0710-720.zip
+
+This document give some hints on how to use this driver with GPRS and 3G
+modems connected to a physical serial port.
+
+How to use it
+-------------
+1- initialize the modem in 0710 mux mode (usually AT+CMUX= command) through
+its serial port. Depending on the modem used, you can pass more or less
+parameters to this command,
+2- switch the serial line to using the n_gsm line discipline by using
+TIOCSETD ioctl,
+3- configure the mux using GSMIOC_GETCONF / GSMIOC_SETCONF ioctl,
+
+Major parts of the initialization program :
+(a good starting point is util-linux-ng/sys-utils/ldattach.c)
+#include <linux/gsmmux.h>
+#define N_GSM0710	21	/* GSM 0710 Mux */
+#define DEFAULT_SPEED	B115200
+#define SERIAL_PORT	/dev/ttyS0
+
+	int ldisc = N_GSM0710;
+	struct gsm_config c;
+	struct termios configuration;
+
+	/* open the serial port connected to the modem */
+	fd = open(SERIAL_PORT, O_RDWR | O_NOCTTY | O_NDELAY);
+
+	/* configure the serial port : speed, flow control ... */
+
+	/* send the AT commands to switch the modem to CMUX mode
+	   and check that it's successful (should return OK) */
+	write(fd, "AT+CMUX=0\r", 10);
+
+	/* experience showed that some modems need some time before
+	   being able to answer to the first MUX packet so a delay
+	   may be needed here in some case */
+	sleep(3);
+
+	/* use n_gsm line discipline */
+	ioctl(fd, TIOCSETD, &ldisc);
+
+	/* get n_gsm configuration */
+	ioctl(fd, GSMIOC_GETCONF, &c);
+	/* we are initiator and need encoding 0 (basic) */
+	c.initiator = 1;
+	c.encapsulation = 0;
+	/* our modem defaults to a maximum size of 127 bytes */
+	c.mru = 127;
+	c.mtu = 127;
+	/* set the new configuration */
+	ioctl(fd, GSMIOC_SETCONF, &c);
+
+	/* and wait for ever to keep the line discipline enabled */
+	daemon(0,0);
+	pause();
+
+4- create the devices corresponding to the "virtual" serial ports (take care,
+each modem has its configuration and some DLC have dedicated functions,
+for example GPS), starting with minor 1 (DLC0 is reserved for the management
+of the mux)
+
+MAJOR=`cat /proc/devices |grep gsmtty | awk '{print $1}`
+for i in `seq 1 4`; do
+	mknod /dev/ttygsm$i c $MAJOR $i
+done
+
+5- use these devices as plain serial ports.
+for example, it's possible :
+- and to use gnokii to send / receive SMS on ttygsm1
+- to use ppp to establish a datalink on ttygsm2
+
+6- first close all virtual ports before closing the physical port.
+
+Additional Documentation
+------------------------
+More practical details on the protocol and how it's supported by industrial
+modems can be found in the following documents :
+http://www.telit.com/module/infopool/download.php?id=616
+http://www.u-blox.com/images/downloads/Product_Docs/LEON-G100-G200-MuxImplementation_ApplicationNote_%28GSM%20G1-CS-10002%29.pdf
+http://www.sierrawireless.com/Support/Downloads/AirPrime/WMP_Series/~/media/Support_Downloads/AirPrime/Application_notes/CMUX_Feature_Application_Note-Rev004.ashx
+http://wm.sim.com/sim/News/photo/2010721161442.pdf
+
+11-03-08 - Eric BÃ©nard - <eric@eukrea.com>
diff -druN linux-libre-2.6.38-gnu/Documentation/sound/alsa/ALSA-Configuration.txt linux-libre-2.6.39-gnu/Documentation/sound/alsa/ALSA-Configuration.txt
--- linux-libre-2.6.38-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2012-03-24 01:23:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sound/alsa/ALSA-Configuration.txt	2012-03-24 03:39:50.000000000 -0400
@@ -322,7 +322,7 @@
     "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
     or the value stored in the card's EEPROM for cards that have an EEPROM and
     their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
-    be choosen freely from the options enumerated above.
+    be chosen freely from the options enumerated above.
 
     If dma2 is specified and different from dma1, the card will operate in
     full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
@@ -356,7 +356,7 @@
     "port" needs to match the BASE ADDRESS jumper on the card (0x220 or 0x240)
     or the value stored in the card's EEPROM for cards that have an EEPROM and
     their "CONFIG MODE" jumper set to "EEPROM SETTING". The other values can
-    be choosen freely from the options enumerated above.
+    be chosen freely from the options enumerated above.
 
     If dma2 is specified and different from dma1, the card will operate in
     full-duplex mode. When dma1=3, only dma2=0 is valid and the only way to
@@ -2220,7 +2220,7 @@
 
 /proc/asound/card#/pcm#[cp]/oss
 -------------------------------
-  String "erase" - erase all additional informations about OSS applications
+  String "erase" - erase all additional information about OSS applications
   String "<app_name> <fragments> <fragment_size> [<options>]"
 
    <app_name> - name of application with (higher priority) or without path
diff -druN linux-libre-2.6.38-gnu/Documentation/sound/alsa/SB-Live-mixer.txt linux-libre-2.6.39-gnu/Documentation/sound/alsa/SB-Live-mixer.txt
--- linux-libre-2.6.38-gnu/Documentation/sound/alsa/SB-Live-mixer.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sound/alsa/SB-Live-mixer.txt	2011-05-19 00:06:34.000000000 -0400
@@ -87,14 +87,14 @@
 The result is forwarded to the ADC capture FIFO (thus to the standard capture
 PCM device).
 
-name='Music Playback Volume',index=0
+name='Synth Playback Volume',index=0
 
 This control is used to attenuate samples for left and right MIDI FX-bus
 accumulators. ALSA uses accumulators 4 and 5 for left and right MIDI samples.
 The result samples are forwarded to the front DAC PCM slots of the AC97 codec.
 
-name='Music Capture Volume',index=0
-name='Music Capture Switch',index=0
+name='Synth Capture Volume',index=0
+name='Synth Capture Switch',index=0
 
 These controls are used to attenuate samples for left and right MIDI FX-bus
 accumulator. ALSA uses accumulators 4 and 5 for left and right PCM.
diff -druN linux-libre-2.6.38-gnu/Documentation/sound/oss/AudioExcelDSP16 linux-libre-2.6.39-gnu/Documentation/sound/oss/AudioExcelDSP16
--- linux-libre-2.6.38-gnu/Documentation/sound/oss/AudioExcelDSP16	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sound/oss/AudioExcelDSP16	2011-05-19 00:06:34.000000000 -0400
@@ -1,10 +1,10 @@
 Driver
 ------
 
-Informations about Audio Excel DSP 16 driver can be found in the source
+Information about Audio Excel DSP 16 driver can be found in the source
 file aedsp16.c
 Please, read the head of the source before using it. It contain useful
-informations.
+information.
 
 Configuration
 -------------
@@ -68,7 +68,7 @@
 This driver supports the SC-6000 and SC-6600 based Gallant's sound card.
 It don't support the Audio Excel DSP 16 III (try the SC-6600 code).
 I'm working on the III version of the card: if someone have useful
-informations about it, please let me know.
+information about it, please let me know.
 For all the non-supported audio cards, you have to boot MS-DOS (or WIN95)
 activating the audio card with the MS-DOS device driver, then you have to
 <ctrl>-<alt>-<del> and boot Linux.
diff -druN linux-libre-2.6.38-gnu/Documentation/sound/oss/README.OSS linux-libre-2.6.39-gnu/Documentation/sound/oss/README.OSS
--- linux-libre-2.6.38-gnu/Documentation/sound/oss/README.OSS	2012-03-24 01:23:48.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sound/oss/README.OSS	2012-03-24 03:39:59.000000000 -0400
@@ -1322,7 +1322,7 @@
 The PCM20 contains a radio tuner, which is also controlled by
 ACI. This radio tuner is supported by the ACI driver together with the
 miropcm20.o module. Also the 7-band equalizer is integrated
-(limited by the OSS-design). Developement has started and maybe
+(limited by the OSS-design). Development has started and maybe
 finished for the RDS decoder on this card, too. You will be able to
 read RadioText, the Programme Service name, Programme TYpe and
 others. Even the v4l radio module benefits from it with a refined
diff -druN linux-libre-2.6.38-gnu/Documentation/sound/oss/README.ymfsb linux-libre-2.6.39-gnu/Documentation/sound/oss/README.ymfsb
--- linux-libre-2.6.38-gnu/Documentation/sound/oss/README.ymfsb	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sound/oss/README.ymfsb	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
 ============
 
   This code references YAMAHA's sample codes and data sheets.
-  I respect and thank for all people they made open the informations
+  I respect and thank for all people they made open the information
   about YMF7xx cards.
 
   And this codes heavily based on Jeff Garzik <jgarzik@pobox.com>'s
diff -druN linux-libre-2.6.38-gnu/Documentation/spi/pxa2xx linux-libre-2.6.39-gnu/Documentation/spi/pxa2xx
--- linux-libre-2.6.38-gnu/Documentation/spi/pxa2xx	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/spi/pxa2xx	2011-05-19 00:06:34.000000000 -0400
@@ -143,7 +143,7 @@
 NOTE: the SPI driver cannot control the chip select if SSPFRM is used, so the
 chipselect is dropped after each spi_transfer.  Most devices need chip select
 asserted around the complete message.  Use SSPFRM as a GPIO (through cs_control)
-to accomodate these chips.
+to accommodate these chips.
 
 
 NSSP SLAVE SAMPLE
diff -druN linux-libre-2.6.38-gnu/Documentation/spi/spi-lm70llp linux-libre-2.6.39-gnu/Documentation/spi/spi-lm70llp
--- linux-libre-2.6.38-gnu/Documentation/spi/spi-lm70llp	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/spi/spi-lm70llp	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
 
 Note that since the LM70 uses a "3-wire" variant of SPI, the SI/SO pin
 is connected to both pin D7 (as Master Out) and Select (as Master In)
-using an arrangment that lets either the parport or the LM70 pull the
+using an arrangement that lets either the parport or the LM70 pull the
 pin low.  This can't be shared with true SPI devices, but other 3-wire
 devices might share the same SI/SO pin.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/spinlocks.txt linux-libre-2.6.39-gnu/Documentation/spinlocks.txt
--- linux-libre-2.6.38-gnu/Documentation/spinlocks.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/spinlocks.txt	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 
 The routines look the same as above:
 
-   rwlock_t xxx_lock = RW_LOCK_UNLOCKED;
+   rwlock_t xxx_lock = __RW_LOCK_UNLOCKED(xxx_lock);
 
 	unsigned long flags;
 
@@ -196,25 +196,3 @@
 
 For static initialization, use DEFINE_SPINLOCK() / DEFINE_RWLOCK() or
 __SPIN_LOCK_UNLOCKED() / __RW_LOCK_UNLOCKED() as appropriate.
-
-SPIN_LOCK_UNLOCKED and RW_LOCK_UNLOCKED are deprecated.  These interfere
-with lockdep state tracking.
-
-Most of the time, you can simply turn:
-	static spinlock_t xxx_lock = SPIN_LOCK_UNLOCKED;
-into:
-	static DEFINE_SPINLOCK(xxx_lock);
-
-Static structure member variables go from:
-
-	struct foo bar {
-		.lock	=	SPIN_LOCK_UNLOCKED;
-	};
-
-to:
-
-	struct foo bar {
-		.lock	=	__SPIN_LOCK_UNLOCKED(bar.lock);
-	};
-
-Declaration of static rw_locks undergo a similar transformation.
diff -druN linux-libre-2.6.38-gnu/Documentation/SubmittingDrivers linux-libre-2.6.39-gnu/Documentation/SubmittingDrivers
--- linux-libre-2.6.38-gnu/Documentation/SubmittingDrivers	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/SubmittingDrivers	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 		complete overview of the power management issues related to
 		drivers see Documentation/power/devices.txt .
 
-Control:	In general if there is active maintainance of a driver by
+Control:	In general if there is active maintenance of a driver by
 		the author then patches will be redirected to them unless
 		they are totally obvious and without need of checking.
 		If you want to be the contact and update point for the
diff -druN linux-libre-2.6.38-gnu/Documentation/SubmittingPatches linux-libre-2.6.39-gnu/Documentation/SubmittingPatches
--- linux-libre-2.6.38-gnu/Documentation/SubmittingPatches	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/SubmittingPatches	2011-05-19 00:06:34.000000000 -0400
@@ -729,7 +729,7 @@
   <http://lkml.org/lkml/2005/4/7/183>
 
 Andi Kleen, "On submitting kernel patches"
-  Some strategies to get difficult or controversal changes in.
+  Some strategies to get difficult or controversial changes in.
   http://halobates.de/on-submitting-patches.pdf
 
 --
diff -druN linux-libre-2.6.38-gnu/Documentation/sysctl/fs.txt linux-libre-2.6.39-gnu/Documentation/sysctl/fs.txt
--- linux-libre-2.6.38-gnu/Documentation/sysctl/fs.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sysctl/fs.txt	2011-05-19 00:06:34.000000000 -0400
@@ -88,20 +88,19 @@
 
 file-max & file-nr:
 
-The kernel allocates file handles dynamically, but as yet it
-doesn't free them again.
-
 The value in file-max denotes the maximum number of file-
 handles that the Linux kernel will allocate. When you get lots
 of error messages about running out of file handles, you might
 want to increase this limit.
 
-Historically, the three values in file-nr denoted the number of
-allocated file handles, the number of allocated but unused file
-handles, and the maximum number of file handles. Linux 2.6 always
-reports 0 as the number of free file handles -- this is not an
-error, it just means that the number of allocated file handles
-exactly matches the number of used file handles.
+Historically,the kernel was able to allocate file handles
+dynamically, but not to free them again. The three values in
+file-nr denote the number of allocated file handles, the number
+of allocated but unused file handles, and the maximum number of
+file handles. Linux 2.6 always reports 0 as the number of free
+file handles -- this is not an error, it just means that the
+number of allocated file handles exactly matches the number of
+used file handles.
 
 Attempts to allocate more file descriptors than file-max are
 reported with printk, look for "VFS: file-max limit <number>
diff -druN linux-libre-2.6.38-gnu/Documentation/sysctl/kernel.txt linux-libre-2.6.39-gnu/Documentation/sysctl/kernel.txt
--- linux-libre-2.6.38-gnu/Documentation/sysctl/kernel.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/sysctl/kernel.txt	2011-05-19 00:06:34.000000000 -0400
@@ -367,7 +367,7 @@
 
 - console_loglevel: messages with a higher priority than
   this will be printed to the console
-- default_message_level: messages without an explicit priority
+- default_message_loglevel: messages without an explicit priority
   will be printed with this priority
 - minimum_console_loglevel: minimum (highest) value to which
   console_loglevel can be set
diff -druN linux-libre-2.6.38-gnu/Documentation/target/tcm_mod_builder.py linux-libre-2.6.39-gnu/Documentation/target/tcm_mod_builder.py
--- linux-libre-2.6.38-gnu/Documentation/target/tcm_mod_builder.py	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/target/tcm_mod_builder.py	2011-05-19 00:06:34.000000000 -0400
@@ -239,8 +239,8 @@
 	buf += "#include <target/target_core_configfs.h>\n"
 	buf += "#include <target/target_core_base.h>\n"
 	buf += "#include <target/configfs_macros.h>\n\n"
-	buf += "#include <" + fabric_mod_name + "_base.h>\n"
-	buf += "#include <" + fabric_mod_name + "_fabric.h>\n\n"
+	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
+	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
 
 	buf += "/* Local pointer to allocated TCM configfs fabric module */\n"
 	buf += "struct target_fabric_configfs *" + fabric_mod_name + "_fabric_configfs;\n\n"
@@ -289,6 +289,7 @@
 	buf += "{\n"
 	buf += "	struct " + fabric_mod_name + "_nacl *nacl = container_of(se_acl,\n"
 	buf += "				struct " + fabric_mod_name + "_nacl, se_node_acl);\n"
+	buf += "	core_tpg_del_initiator_node_acl(se_acl->se_tpg, se_acl, 1);\n"
 	buf += "	kfree(nacl);\n"
 	buf += "}\n\n"
 
@@ -583,9 +584,9 @@
 	buf += "#include <target/target_core_fabric_lib.h>\n"
 	buf += "#include <target/target_core_device.h>\n"
 	buf += "#include <target/target_core_tpg.h>\n"
-	buf += "#include <target/target_core_configfs.h>\n"
-	buf += "#include <" + fabric_mod_name + "_base.h>\n"
-	buf += "#include <" + fabric_mod_name + "_fabric.h>\n\n"
+	buf += "#include <target/target_core_configfs.h>\n\n"
+	buf += "#include \"" + fabric_mod_name + "_base.h\"\n"
+	buf += "#include \"" + fabric_mod_name + "_fabric.h\"\n\n"
 
 	buf += "int " + fabric_mod_name + "_check_true(struct se_portal_group *se_tpg)\n"
 	buf += "{\n"
@@ -973,14 +974,13 @@
 def tcm_mod_build_kbuild(fabric_mod_dir_var, fabric_mod_name):
 
 	buf = ""
-	f = fabric_mod_dir_var + "/Kbuild"
+	f = fabric_mod_dir_var + "/Makefile"
 	print "Writing file: " + f
 
 	p = open(f, 'w')
 	if not p:
 		tcm_mod_err("Unable to open file: " + f)
 
-	buf = "EXTRA_CFLAGS += -I$(srctree)/drivers/target/ -I$(srctree)/include/ -I$(srctree)/drivers/scsi/ -I$(srctree)/include/scsi/ -I$(srctree)/drivers/target/" + fabric_mod_name + "\n\n"
 	buf += fabric_mod_name + "-objs			:= " + fabric_mod_name + "_fabric.o \\\n"
 	buf += "					   " + fabric_mod_name + "_configfs.o\n"
 	buf += "obj-$(CONFIG_" + fabric_mod_name.upper() + ")		+= " + fabric_mod_name + ".o\n"
@@ -1018,7 +1018,7 @@
 
 def tcm_mod_add_kbuild(tcm_dir, fabric_mod_name):
 	buf = "obj-$(CONFIG_" + fabric_mod_name.upper() + ")	+= " + fabric_mod_name.lower() + "/\n"
-	kbuild = tcm_dir + "/drivers/target/Kbuild"
+	kbuild = tcm_dir + "/drivers/target/Makefile"
 
 	f = open(kbuild, 'a')
 	f.write(buf)
@@ -1064,7 +1064,7 @@
 	tcm_mod_build_kbuild(fabric_mod_dir, fabric_mod_name)
 	tcm_mod_build_kconfig(fabric_mod_dir, fabric_mod_name)
 
-	input = raw_input("Would you like to add " + fabric_mod_name + "to drivers/target/Kbuild..? [yes,no]: ")
+	input = raw_input("Would you like to add " + fabric_mod_name + "to drivers/target/Makefile..? [yes,no]: ")
 	if input == "yes" or input == "y":
 		tcm_mod_add_kbuild(tcm_dir, fabric_mod_name)
 
diff -druN linux-libre-2.6.38-gnu/Documentation/telephony/ixj.txt linux-libre-2.6.39-gnu/Documentation/telephony/ixj.txt
--- linux-libre-2.6.38-gnu/Documentation/telephony/ixj.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/telephony/ixj.txt	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
 Specifically, very old Internet PhoneJACK cards have non-standard
 G.723.1 codecs (due to the early nature of the DSPs in those days).
 The auto-conversion code to bring those cards into compliance with
-todays standards is available as a binary only module to those people
+today's standards is available as a binary only module to those people
 needing it.  If you bought your card after 1997 or so, you are OK -
 it's only the very old cards that are affected.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/trace/ftrace-design.txt linux-libre-2.6.39-gnu/Documentation/trace/ftrace-design.txt
--- linux-libre-2.6.38-gnu/Documentation/trace/ftrace-design.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/trace/ftrace-design.txt	2011-05-19 00:06:34.000000000 -0400
@@ -247,6 +247,13 @@
 - Support the TIF_SYSCALL_TRACEPOINT thread flags.
 - Put the trace_sys_enter() and trace_sys_exit() tracepoints calls from ptrace
   in the ptrace syscalls tracing path.
+- If the system call table on this arch is more complicated than a simple array
+  of addresses of the system calls, implement an arch_syscall_addr to return
+  the address of a given system call.
+- If the symbol names of the system calls do not match the function names on
+  this arch, define ARCH_HAS_SYSCALL_MATCH_SYM_NAME in asm/ftrace.h and
+  implement arch_syscall_match_sym_name with the appropriate logic to return
+  true if the function name corresponds with the symbol name.
 - Tag this arch as HAVE_SYSCALL_TRACEPOINTS.
 
 
diff -druN linux-libre-2.6.38-gnu/Documentation/trace/ftrace.txt linux-libre-2.6.39-gnu/Documentation/trace/ftrace.txt
--- linux-libre-2.6.38-gnu/Documentation/trace/ftrace.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/trace/ftrace.txt	2011-05-19 00:06:34.000000000 -0400
@@ -80,11 +80,11 @@
 	tracers listed here can be configured by
 	echoing their name into current_tracer.
 
-  tracing_enabled:
+  tracing_on:
 
-	This sets or displays whether the current_tracer
-	is activated and tracing or not. Echo 0 into this
-	file to disable the tracer or 1 to enable it.
+	This sets or displays whether writing to the trace
+	ring buffer is enabled. Echo 0 into this file to disable
+	the tracer or 1 to enable it.
 
   trace:
 
@@ -202,10 +202,6 @@
 	to draw a graph of function calls similar to C code
 	source.
 
-  "sched_switch"
-
-	Traces the context switches and wakeups between tasks.
-
   "irqsoff"
 
 	Traces the areas that disable interrupts and saves
@@ -273,39 +269,6 @@
 parent function that called this function "path_walk". The
 timestamp is the time at which the function was entered.
 
-The sched_switch tracer also includes tracing of task wakeups
-and context switches.
-
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:R   +  2916:115:S
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:R   +    10:115:S
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:R ==>    10:115:R
-        events/1-10    [01]  1453.070013:     10:115:S ==>  2916:115:R
-     kondemand/1-2916  [01]  1453.070013:   2916:115:S ==>     7:115:R
-     ksoftirqd/1-7     [01]  1453.070013:      7:115:S ==>     0:140:R
-
-Wake ups are represented by a "+" and the context switches are
-shown as "==>".  The format is:
-
- Context switches:
-
-       Previous task              Next Task
-
-  <pid>:<prio>:<state>  ==>  <pid>:<prio>:<state>
-
- Wake ups:
-
-       Current task               Task waking up
-
-  <pid>:<prio>:<state>    +  <pid>:<prio>:<state>
-
-The prio is the internal kernel priority, which is the inverse
-of the priority that is usually displayed by user-space tools.
-Zero represents the highest priority (99). Prio 100 starts the
-"nice" priorities with 100 being equal to nice -20 and 139 being
-nice 19. The prio "140" is reserved for the idle task which is
-the lowest priority thread (pid 0).
-
-
 Latency trace format
 --------------------
 
@@ -491,78 +454,10 @@
                    latencies, as described in "Latency
                    trace format".
 
-sched_switch
-------------
-
-This tracer simply records schedule switches. Here is an example
-of how to use it.
-
- # echo sched_switch > current_tracer
- # echo 1 > tracing_enabled
- # sleep 1
- # echo 0 > tracing_enabled
- # cat trace
-
-# tracer: sched_switch
-#
-#           TASK-PID   CPU#    TIMESTAMP  FUNCTION
-#              | |      |          |         |
-            bash-3997  [01]   240.132281:   3997:120:R   +  4055:120:R
-            bash-3997  [01]   240.132284:   3997:120:R ==>  4055:120:R
-           sleep-4055  [01]   240.132371:   4055:120:S ==>  3997:120:R
-            bash-3997  [01]   240.132454:   3997:120:R   +  4055:120:S
-            bash-3997  [01]   240.132457:   3997:120:R ==>  4055:120:R
-           sleep-4055  [01]   240.132460:   4055:120:D ==>  3997:120:R
-            bash-3997  [01]   240.132463:   3997:120:R   +  4055:120:D
-            bash-3997  [01]   240.132465:   3997:120:R ==>  4055:120:R
-          <idle>-0     [00]   240.132589:      0:140:R   +     4:115:S
-          <idle>-0     [00]   240.132591:      0:140:R ==>     4:115:R
-     ksoftirqd/0-4     [00]   240.132595:      4:115:S ==>     0:140:R
-          <idle>-0     [00]   240.132598:      0:140:R   +     4:115:S
-          <idle>-0     [00]   240.132599:      0:140:R ==>     4:115:R
-     ksoftirqd/0-4     [00]   240.132603:      4:115:S ==>     0:140:R
-           sleep-4055  [01]   240.133058:   4055:120:S ==>  3997:120:R
- [...]
-
-
-As we have discussed previously about this format, the header
-shows the name of the trace and points to the options. The
-"FUNCTION" is a misnomer since here it represents the wake ups
-and context switches.
-
-The sched_switch file only lists the wake ups (represented with
-'+') and context switches ('==>') with the previous task or
-current task first followed by the next task or task waking up.
-The format for both of these is PID:KERNEL-PRIO:TASK-STATE.
-Remember that the KERNEL-PRIO is the inverse of the actual
-priority with zero (0) being the highest priority and the nice
-values starting at 100 (nice -20). Below is a quick chart to map
-the kernel priority to user land priorities.
-
-   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:
-
- R - running : wants to run, may not actually be running
- S - sleep   : process is waiting to be woken up (handles signals)
- D - disk sleep (uninterruptible sleep) : process must be woken up
-					(ignores signals)
- T - stopped : process suspended
- t - traced  : process is being traced (with something like gdb)
- Z - zombie  : process waiting to be cleaned up
- X - unknown
-
+  overwrite - This controls what happens when the trace buffer is
+              full. If "1" (default), the oldest events are
+              discarded and overwritten. If "0", then the newest
+              events are discarded.
 
 ftrace_enabled
 --------------
@@ -607,10 +502,10 @@
  # echo irqsoff > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # ls -ltr
  [...]
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: irqsoff
 #
@@ -715,10 +610,10 @@
  # echo preemptoff > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # ls -ltr
  [...]
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: preemptoff
 #
@@ -863,10 +758,10 @@
  # echo preemptirqsoff > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # ls -ltr
  [...]
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: preemptirqsoff
 #
@@ -1026,9 +921,9 @@
  # echo wakeup > current_tracer
  # echo latency-format > trace_options
  # echo 0 > tracing_max_latency
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # chrt -f 5 sleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: wakeup
 #
@@ -1140,9 +1035,9 @@
 
  # sysctl kernel.ftrace_enabled=1
  # echo function > current_tracer
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # usleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: function
 #
@@ -1180,7 +1075,7 @@
 [...]
 int main(int argc, char *argv[]) {
 	[...]
-	trace_fd = open(tracing_file("tracing_enabled"), O_WRONLY);
+	trace_fd = open(tracing_file("tracing_on"), O_WRONLY);
 	[...]
 	if (condition_hit()) {
 		write(trace_fd, "0", 1);
@@ -1631,9 +1526,9 @@
  # echo sys_nanosleep hrtimer_interrupt \
 		> set_ftrace_filter
  # echo function > current_tracer
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # usleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: ftrace
 #
@@ -1879,9 +1774,9 @@
  # echo function > current_tracer
  # cat trace_pipe > /tmp/trace.out &
 [1] 4153
- # echo 1 > tracing_enabled
+ # echo 1 > tracing_on
  # usleep 1
- # echo 0 > tracing_enabled
+ # echo 0 > tracing_on
  # cat trace
 # tracer: function
 #
diff -druN linux-libre-2.6.38-gnu/Documentation/trace/kprobetrace.txt linux-libre-2.6.39-gnu/Documentation/trace/kprobetrace.txt
--- linux-libre-2.6.38-gnu/Documentation/trace/kprobetrace.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/trace/kprobetrace.txt	2011-05-19 00:06:34.000000000 -0400
@@ -42,11 +42,25 @@
   +|-offs(FETCHARG) : Fetch memory at FETCHARG +|- offs address.(**)
   NAME=FETCHARG : Set NAME as the argument name of FETCHARG.
   FETCHARG:TYPE : Set TYPE as the type of FETCHARG. Currently, basic types
-		  (u8/u16/u32/u64/s8/s16/s32/s64) and string are supported.
+		  (u8/u16/u32/u64/s8/s16/s32/s64), "string" and bitfield
+		  are supported.
 
   (*) only for return probe.
   (**) this is useful for fetching a field of data structures.
 
+Types
+-----
+Several types are supported for fetch-args. Kprobe tracer will access memory
+by given type. Prefix 's' and 'u' means those types are signed and unsigned
+respectively. Traced arguments are shown in decimal (signed) or hex (unsigned).
+String type is a special type, which fetches a "null-terminated" string from
+kernel space. This means it will fail and store NULL if the string container
+has been paged out.
+Bitfield is another special type, which takes 3 parameters, bit-width, bit-
+offset, and container-size (usually 32). The syntax is;
+
+ b<bit-width>@<bit-offset>/<container-size>
+
 
 Per-Probe Event Filtering
 -------------------------
diff -druN linux-libre-2.6.38-gnu/Documentation/trace/ring-buffer-design.txt linux-libre-2.6.39-gnu/Documentation/trace/ring-buffer-design.txt
--- linux-libre-2.6.38-gnu/Documentation/trace/ring-buffer-design.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/trace/ring-buffer-design.txt	2011-05-19 00:06:34.000000000 -0400
@@ -237,7 +237,7 @@
       |written  |
       +---------+
       |written  |
-      +---------+  <--- next positon for write (current commit)
+      +---------+  <--- next position for write (current commit)
       | empty   |
       +---------+
 
diff -druN linux-libre-2.6.38-gnu/Documentation/usb/usbmon.txt linux-libre-2.6.39-gnu/Documentation/usb/usbmon.txt
--- linux-libre-2.6.38-gnu/Documentation/usb/usbmon.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/usb/usbmon.txt	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,10 @@
 usbmon may not correspond to bus transactions precisely. This is the same
 situation as with tcpdump.
 
+Two APIs are currently implemented: "text" and "binary". The binary API
+is available through a character device in /dev namespace and is an ABI.
+The text API is deprecated since 2.6.35, but available for convenience.
+
 * How to use usbmon to collect raw text traces
 
 Unlike the packet socket, usbmon has an interface which provides traces
@@ -162,39 +166,11 @@
   not machine words, but really just a byte stream split into words to make
   it easier to read. Thus, the last word may contain from one to four bytes.
   The length of collected data is limited and can be less than the data length
-  report in Data Length word.
-
-Here is an example of code to read the data stream in a well known programming
-language:
-
-class ParsedLine {
-	int data_len;		/* Available length of data */
-	byte data[];
-
-	void parseData(StringTokenizer st) {
-		int availwords = st.countTokens();
-		data = new byte[availwords * 4];
-		data_len = 0;
-		while (st.hasMoreTokens()) {
-			String data_str = st.nextToken();
-			int len = data_str.length() / 2;
-			int i;
-			int b;	// byte is signed, apparently?! XXX
-			for (i = 0; i < len; i++) {
-				// data[data_len] = Byte.parseByte(
-				//     data_str.substring(i*2, i*2 + 2),
-				//     16);
-				b = Integer.parseInt(
-				     data_str.substring(i*2, i*2 + 2),
-				     16);
-				if (b >= 128)
-					b *= -1;
-				data[data_len] = (byte) b;
-				data_len++;
-			}
-		}
-	}
-}
+  reported in the Data Length word. In the case of an Isochronous input (Zi)
+  completion where the received data is sparse in the buffer, the length of
+  the collected data can be greater than the Data Length value (because Data
+  Length counts only the bytes that were received whereas the Data words
+  contain the entire transfer buffer).
 
 Examples:
 
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/Insmod-options linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/Insmod-options
--- linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/Insmod-options	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/Insmod-options	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 
-Note: "modinfo <module>" prints various informations about a kernel
+Note: "modinfo <module>" prints various information about a kernel
 module, among them a complete and up-to-date list of insmod options.
 This list tends to be outdated because it is updated manually ...
 
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/README linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/README
--- linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/README	2012-03-24 01:04:15.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/README	2012-03-24 03:28:48.000000000 -0400
@@ -66,7 +66,7 @@
 instead of mailing me directly.  The chance that someone with the
 same card listens there is much higher...
 
-For problems with sound:  There are alot of different systems used
+For problems with sound:  There are a lot of different systems used
 for TV sound all over the world.  And there are also different chips
 which decode the audio signal.  Reports about sound problems ("stereo
 does'nt work") are pretty useless unless you include some details
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/README.freeze linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/README.freeze
--- linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/README.freeze	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/README.freeze	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 
 I've seen reports that bttv 0.7.x crashes whereas 0.8.x works rock solid
 for some people.  Thus probably a small buglet left somewhere in bttv
-0.7.x.  I have no idea where exactly, it works stable for me and alot of
+0.7.x.  I have no idea where exactly, it works stable for me and a lot of
 other people.  But in case you have problems with the 0.7.x versions you
 can give 0.8.x a try ...
 
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/Sound-FAQ linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/Sound-FAQ
--- linux-libre-2.6.38-gnu/Documentation/video4linux/bttv/Sound-FAQ	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/bttv/Sound-FAQ	2011-05-19 00:06:34.000000000 -0400
@@ -2,13 +2,13 @@
 bttv and sound mini howto
 =========================
 
-There are alot of different bt848/849/878/879 based boards available.
+There are a lot of different bt848/849/878/879 based boards available.
 Making video work often is not a big deal, because this is handled
 completely by the bt8xx chip, which is common on all boards.  But
 sound is handled in slightly different ways on each board.
 
 To handle the grabber boards correctly, there is a array tvcards[] in
-bttv-cards.c, which holds the informations required for each board.
+bttv-cards.c, which holds the information required for each board.
 Sound will work only, if the correct entry is used (for video it often
 makes no difference).  The bttv driver prints a line to the kernel
 log, telling which card type is used.  Like this one:
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/et61x251.txt linux-libre-2.6.39-gnu/Documentation/video4linux/et61x251.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/et61x251.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/et61x251.txt	2011-05-19 00:06:34.000000000 -0400
@@ -191,10 +191,10 @@
 Description:    Debugging information level, from 0 to 3:
 		0 = none (use carefully)
 		1 = critical errors
-		2 = significant informations
+		2 = significant information
 		3 = more verbose messages
 		Level 3 is useful for testing only, when only one device
-		is used at the same time. It also shows some more informations
+		is used at the same time. It also shows some more information
 		about the hardware being detected. This module parameter can be
 		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/gspca.txt linux-libre-2.6.39-gnu/Documentation/video4linux/gspca.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/gspca.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/gspca.txt	2011-05-19 00:06:34.000000000 -0400
@@ -103,6 +103,7 @@
 spca561		046d:092e	Logitech QC Elch2
 spca561		046d:092f	Logitech QuickCam Express Plus
 sunplus		046d:0960	Logitech ClickSmart 420
+nw80x		046d:d001	Logitech QuickCam Pro (dark focus ring)
 sunplus		0471:0322	Philips DMVC1300K
 zc3xx		0471:0325	Philips SPC 200 NC
 zc3xx		0471:0326	Philips SPC 300 NC
@@ -150,10 +151,12 @@
 sunplus		04fc:5360	Sunplus Generic
 spca500		04fc:7333	PalmPixDC85
 sunplus		04fc:ffff	Pure DigitalDakota
+nw80x		0502:d001	DVC V6
 spca501		0506:00df	3Com HomeConnect Lite
 sunplus		052b:1507	Megapixel 5 Pretec DC-1007
 sunplus		052b:1513	Megapix V4
 sunplus		052b:1803	MegaImage VI
+nw80x		052b:d001	EZCam Pro p35u
 tv8532		0545:808b	Veo Stingray
 tv8532		0545:8333	Veo Stingray
 sunplus		0546:3155	Polaroid PDC3070
@@ -177,6 +180,7 @@
 sunplus		055f:c540	Gsmart D30
 sunplus		055f:c630	Mustek MDC4000
 sunplus		055f:c650	Mustek MDC5500Z
+nw80x		055f:d001	Mustek Wcam 300 mini
 zc3xx		055f:d003	Mustek WCam300A
 zc3xx		055f:d004	Mustek WCam300 AN
 conex		0572:0041	Creative Notebook cx11646
@@ -195,14 +199,20 @@
 gl860		05e3:f191	Genesys Logic PC Camera
 spca561		060b:a001	Maxell Compact Pc PM3
 zc3xx		0698:2003	CTX M730V built in
+nw80x		06a5:0000	Typhoon Webcam 100 USB
+nw80x		06a5:d001	Divio based webcams
+nw80x		06a5:d800	Divio Chicony TwinkleCam, Trust SpaceCam
 spca500		06bd:0404	Agfa CL20
 spca500		06be:0800	Optimedia
+nw80x		06be:d001	EZCam Pro p35u
 sunplus		06d6:0031	Trust 610 LCD PowerC@m Zoom
 spca506		06e1:a190	ADS Instant VCD
+ov534		06f8:3002	Hercules Blog Webcam
 ov534_9		06f8:3003	Hercules Dualpix HD Weblog
 sonixj		06f8:3004	Hercules Classic Silver
 sonixj		06f8:3008	Hercules Deluxe Optical Glass
 pac7302		06f8:3009	Hercules Classic Link
+nw80x		0728:d001	AVerMedia Camguard
 spca508		0733:0110	ViewQuest VQ110
 spca501		0733:0401	Intel Create and Share
 spca501		0733:0402	ViewQuest M318B
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/omap3isp.txt linux-libre-2.6.39-gnu/Documentation/video4linux/omap3isp.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/omap3isp.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/omap3isp.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,278 @@
+OMAP 3 Image Signal Processor (ISP) driver
+
+Copyright (C) 2010 Nokia Corporation
+Copyright (C) 2009 Texas Instruments, Inc.
+
+Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+	  Sakari Ailus <sakari.ailus@iki.fi>
+	  David Cohen <dacohen@gmail.com>
+
+
+Introduction
+============
+
+This file documents the Texas Instruments OMAP 3 Image Signal Processor (ISP)
+driver located under drivers/media/video/omap3isp. The original driver was
+written by Texas Instruments but since that it has been rewritten (twice) at
+Nokia.
+
+The driver has been successfully used on the following versions of OMAP 3:
+
+	3430
+	3530
+	3630
+
+The driver implements V4L2, Media controller and v4l2_subdev interfaces.
+Sensor, lens and flash drivers using the v4l2_subdev interface in the kernel
+are supported.
+
+
+Split to subdevs
+================
+
+The OMAP 3 ISP is split into V4L2 subdevs, each of the blocks inside the ISP
+having one subdev to represent it. Each of the subdevs provide a V4L2 subdev
+interface to userspace.
+
+	OMAP3 ISP CCP2
+	OMAP3 ISP CSI2a
+	OMAP3 ISP CCDC
+	OMAP3 ISP preview
+	OMAP3 ISP resizer
+	OMAP3 ISP AEWB
+	OMAP3 ISP AF
+	OMAP3 ISP histogram
+
+Each possible link in the ISP is modelled by a link in the Media controller
+interface. For an example program see [2].
+
+
+Controlling the OMAP 3 ISP
+==========================
+
+In general, the settings given to the OMAP 3 ISP take effect at the beginning
+of the following frame. This is done when the module becomes idle during the
+vertical blanking period on the sensor. In memory-to-memory operation the pipe
+is run one frame at a time. Applying the settings is done between the frames.
+
+All the blocks in the ISP, excluding the CSI-2 and possibly the CCP2 receiver,
+insist on receiving complete frames. Sensors must thus never send the ISP
+partial frames.
+
+Autoidle does have issues with some ISP blocks on the 3430, at least.
+Autoidle is only enabled on 3630 when the omap3isp module parameter autoidle
+is non-zero.
+
+
+Events
+======
+
+The OMAP 3 ISP driver does support the V4L2 event interface on CCDC and
+statistics (AEWB, AF and histogram) subdevs.
+
+The CCDC subdev produces V4L2_EVENT_OMAP3ISP_HS_VS type event on HS_VS
+interrupt which is used to signal frame start. The event is triggered exactly
+when the reception of the first line of the frame starts in the CCDC module.
+The event can be subscribed on the CCDC subdev.
+
+(When using parallel interface one must pay account to correct configuration
+of the VS signal polarity. This is automatically correct when using the serial
+receivers.)
+
+Each of the statistics subdevs is able to produce events. An event is
+generated whenever a statistics buffer can be dequeued by a user space
+application using the VIDIOC_OMAP3ISP_STAT_REQ IOCTL. The events available
+are:
+
+	V4L2_EVENT_OMAP3ISP_AEWB
+	V4L2_EVENT_OMAP3ISP_AF
+	V4L2_EVENT_OMAP3ISP_HIST
+
+The type of the event data is struct omap3isp_stat_event_status for these
+ioctls. If there is an error calculating the statistics, there will be an
+event as usual, but no related statistics buffer. In this case
+omap3isp_stat_event_status.buf_err is set to non-zero.
+
+
+Private IOCTLs
+==============
+
+The OMAP 3 ISP driver supports standard V4L2 IOCTLs and controls where
+possible and practical. Much of the functions provided by the ISP, however,
+does not fall under the standard IOCTLs --- gamma tables and configuration of
+statistics collection are examples of such.
+
+In general, there is a private ioctl for configuring each of the blocks
+containing hardware-dependent functions.
+
+The following private IOCTLs are supported:
+
+	VIDIOC_OMAP3ISP_CCDC_CFG
+	VIDIOC_OMAP3ISP_PRV_CFG
+	VIDIOC_OMAP3ISP_AEWB_CFG
+	VIDIOC_OMAP3ISP_HIST_CFG
+	VIDIOC_OMAP3ISP_AF_CFG
+	VIDIOC_OMAP3ISP_STAT_REQ
+	VIDIOC_OMAP3ISP_STAT_EN
+
+The parameter structures used by these ioctls are described in
+include/linux/omap3isp.h. The detailed functions of the ISP itself related to
+a given ISP block is described in the Technical Reference Manuals (TRMs) ---
+see the end of the document for those.
+
+While it is possible to use the ISP driver without any use of these private
+IOCTLs it is not possible to obtain optimal image quality this way. The AEWB,
+AF and histogram modules cannot be used without configuring them using the
+appropriate private IOCTLs.
+
+
+CCDC and preview block IOCTLs
+=============================
+
+The VIDIOC_OMAP3ISP_CCDC_CFG and VIDIOC_OMAP3ISP_PRV_CFG IOCTLs are used to
+configure, enable and disable functions in the CCDC and preview blocks,
+respectively. Both IOCTLs control several functions in the blocks they
+control. VIDIOC_OMAP3ISP_CCDC_CFG IOCTL accepts a pointer to struct
+omap3isp_ccdc_update_config as its argument. Similarly VIDIOC_OMAP3ISP_PRV_CFG
+accepts a pointer to struct omap3isp_prev_update_config. The definition of
+both structures is available in [1].
+
+The update field in the structures tells whether to update the configuration
+for the specific function and the flag tells whether to enable or disable the
+function.
+
+The update and flag bit masks accept the following values. Each separate
+functions in the CCDC and preview blocks is associated with a flag (either
+disable or enable; part of the flag field in the structure) and a pointer to
+configuration data for the function.
+
+Valid values for the update and flag fields are listed here for
+VIDIOC_OMAP3ISP_CCDC_CFG. Values may be or'ed to configure more than one
+function in the same IOCTL call.
+
+        OMAP3ISP_CCDC_ALAW
+        OMAP3ISP_CCDC_LPF
+        OMAP3ISP_CCDC_BLCLAMP
+        OMAP3ISP_CCDC_BCOMP
+        OMAP3ISP_CCDC_FPC
+        OMAP3ISP_CCDC_CULL
+        OMAP3ISP_CCDC_CONFIG_LSC
+        OMAP3ISP_CCDC_TBL_LSC
+
+The corresponding values for the VIDIOC_OMAP3ISP_PRV_CFG are here:
+
+        OMAP3ISP_PREV_LUMAENH
+        OMAP3ISP_PREV_INVALAW
+        OMAP3ISP_PREV_HRZ_MED
+        OMAP3ISP_PREV_CFA
+        OMAP3ISP_PREV_CHROMA_SUPP
+        OMAP3ISP_PREV_WB
+        OMAP3ISP_PREV_BLKADJ
+        OMAP3ISP_PREV_RGB2RGB
+        OMAP3ISP_PREV_COLOR_CONV
+        OMAP3ISP_PREV_YC_LIMIT
+        OMAP3ISP_PREV_DEFECT_COR
+        OMAP3ISP_PREV_GAMMABYPASS
+        OMAP3ISP_PREV_DRK_FRM_CAPTURE
+        OMAP3ISP_PREV_DRK_FRM_SUBTRACT
+        OMAP3ISP_PREV_LENS_SHADING
+        OMAP3ISP_PREV_NF
+        OMAP3ISP_PREV_GAMMA
+
+The associated configuration pointer for the function may not be NULL when
+enabling the function. When disabling a function the configuration pointer is
+ignored.
+
+
+Statistic blocks IOCTLs
+=======================
+
+The statistics subdevs do offer more dynamic configuration options than the
+other subdevs. They can be enabled, disable and reconfigured when the pipeline
+is in streaming state.
+
+The statistics blocks always get the input image data from the CCDC (as the
+histogram memory read isn't implemented). The statistics are dequeueable by
+the user from the statistics subdev nodes using private IOCTLs.
+
+The private IOCTLs offered by the AEWB, AF and histogram subdevs are heavily
+reflected by the register level interface offered by the ISP hardware. There
+are aspects that are purely related to the driver implementation and these are
+discussed next.
+
+VIDIOC_OMAP3ISP_STAT_EN
+-----------------------
+
+This private IOCTL enables/disables a statistic module. If this request is
+done before streaming, it will take effect as soon as the pipeline starts to
+stream.  If the pipeline is already streaming, it will take effect as soon as
+the CCDC becomes idle.
+
+VIDIOC_OMAP3ISP_AEWB_CFG, VIDIOC_OMAP3ISP_HIST_CFG and VIDIOC_OMAP3ISP_AF_CFG
+-----------------------------------------------------------------------------
+
+Those IOCTLs are used to configure the modules. They require user applications
+to have an in-depth knowledge of the hardware. Most of the fields explanation
+can be found on OMAP's TRMs. The two following fields common to all the above
+configure private IOCTLs require explanation for better understanding as they
+are not part of the TRM.
+
+omap3isp_[h3a_af/h3a_aewb/hist]_config.buf_size:
+
+The modules handle their buffers internally. The necessary buffer size for the
+module's data output depends on the requested configuration. Although the
+driver supports reconfiguration while streaming, it does not support a
+reconfiguration which requires bigger buffer size than what is already
+internally allocated if the module is enabled. It will return -EBUSY on this
+case. In order to avoid such condition, either disable/reconfigure/enable the
+module or request the necessary buffer size during the first configuration
+while the module is disabled.
+
+The internal buffer size allocation considers the requested configuration's
+minimum buffer size and the value set on buf_size field. If buf_size field is
+out of [minimum, maximum] buffer size range, it's clamped to fit in there.
+The driver then selects the biggest value. The corrected buf_size value is
+written back to user application.
+
+omap3isp_[h3a_af/h3a_aewb/hist]_config.config_counter:
+
+As the configuration doesn't take effect synchronously to the request, the
+driver must provide a way to track this information to provide more accurate
+data. After a configuration is requested, the config_counter returned to user
+space application will be an unique value associated to that request. When
+user application receives an event for buffer availability or when a new
+buffer is requested, this config_counter is used to match a buffer data and a
+configuration.
+
+VIDIOC_OMAP3ISP_STAT_REQ
+------------------------
+
+Send to user space the oldest data available in the internal buffer queue and
+discards such buffer afterwards. The field omap3isp_stat_data.frame_number
+matches with the video buffer's field_count.
+
+
+Technical reference manuals (TRMs) and other documentation
+==========================================================
+
+OMAP 3430 TRM:
+<URL:http://focus.ti.com/pdfs/wtbu/OMAP34xx_ES3.1.x_PUBLIC_TRM_vZM.zip>
+Referenced 2011-03-05.
+
+OMAP 35xx TRM:
+<URL:http://www.ti.com/litv/pdf/spruf98o> Referenced 2011-03-05.
+
+OMAP 3630 TRM:
+<URL:http://focus.ti.com/pdfs/wtbu/OMAP36xx_ES1.x_PUBLIC_TRM_vQ.zip>
+Referenced 2011-03-05.
+
+DM 3730 TRM:
+<URL:http://www.ti.com/litv/pdf/sprugn4h> Referenced 2011-03-06.
+
+
+References
+==========
+
+[1] include/linux/omap3isp.h
+
+[2] http://git.ideasonboard.org/?p=media-ctl.git;a=summary
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/pxa_camera.txt linux-libre-2.6.39-gnu/Documentation/video4linux/pxa_camera.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/pxa_camera.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/pxa_camera.txt	2011-05-19 00:06:34.000000000 -0400
@@ -84,12 +84,12 @@
        transfer is not started. On "End Of Frame" interrupt, the irq handler
        starts the DMA chain.
      - capture of one videobuffer
-       The DMA chain starts transfering data into videobuffer RAM pages.
-       When all pages are transfered, the DMA irq is raised on "ENDINTR" status
+       The DMA chain starts transferring data into videobuffer RAM pages.
+       When all pages are transferred, the DMA irq is raised on "ENDINTR" status
      - finishing one videobuffer
        The DMA irq handler marks the videobuffer as "done", and removes it from
        the active running queue
-       Meanwhile, the next videobuffer (if there is one), is transfered by DMA
+       Meanwhile, the next videobuffer (if there is one), is transferred by DMA
      - finishing the last videobuffer
        On the DMA irq of the last videobuffer, the QCI is stopped.
 
@@ -101,7 +101,7 @@
 
      This structure is pointed by dma->sg_cpu.
      The descriptors are used as follows :
-      - desc-sg[i]: i-th descriptor, transfering the i-th sg
+      - desc-sg[i]: i-th descriptor, transferring the i-th sg
         element to the video buffer scatter gather
       - finisher: has ddadr=DADDR_STOP, dcmd=ENDIRQEN
       - linker: has ddadr= desc-sg[0] of next video buffer, dcmd=0
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/README.ivtv linux-libre-2.6.39-gnu/Documentation/video4linux/README.ivtv
--- linux-libre-2.6.38-gnu/Documentation/video4linux/README.ivtv	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/README.ivtv	2011-05-19 00:06:34.000000000 -0400
@@ -36,8 +36,7 @@
  * Provides comprehensive OSD (On Screen Display: ie. graphics overlaying the
    video signal)
  * Provides a framebuffer (allowing X applications to appear on the video
-   device) (this framebuffer is not yet part of the kernel. In the meantime it
-   is available from www.ivtvdriver.org).
+   device)
  * Supports raw YUV output.
 
 IMPORTANT: In case of problems first read this page:
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/README.pvrusb2 linux-libre-2.6.39-gnu/Documentation/video4linux/README.pvrusb2
--- linux-libre-2.6.38-gnu/Documentation/video4linux/README.pvrusb2	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/README.pvrusb2	2011-05-19 00:06:34.000000000 -0400
@@ -172,7 +172,7 @@
     to provide a streaming API usable by a read() system call style of
     I/O.  Right now this is the only layer on top of pvrusb2-io.[ch],
     however the underlying architecture here was intended to allow for
-    other styles of I/O to be implemented with additonal modules, like
+    other styles of I/O to be implemented with additional modules, like
     mmap()'ed buffers or something even more exotic.
 
   pvrusb2-main.c - This is the top level of the driver.  Module level
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/sh_mobile_ceu_camera.txt linux-libre-2.6.39-gnu/Documentation/video4linux/sh_mobile_ceu_camera.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/sh_mobile_ceu_camera.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/sh_mobile_ceu_camera.txt	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
 -1'-
 
 In the above chart minuses and slashes represent "real" data amounts, points and
-accents represent "useful" data, basically, CEU scaled amd cropped output,
+accents represent "useful" data, basically, CEU scaled and cropped output,
 mapped back onto the client's source plane.
 
 Such a configuration can be produced by user requests:
@@ -65,7 +65,7 @@
 
 1. Calculate current sensor scales:
 
-	scale_s = ((3') - (3)) / ((2') - (2))
+	scale_s = ((2') - (2)) / ((3') - (3))
 
 2. Calculate "effective" input crop (sensor subwindow) - CEU crop scaled back at
 current sensor scales onto input window - this is user S_CROP:
@@ -80,7 +80,7 @@
 4. Calculate sensor output window by applying combined scales to real input
 window:
 
-	width_s_out = ((2') - (2)) / scale_comb
+	width_s_out = ((7') - (7)) = ((2') - (2)) / scale_comb
 
 5. Apply iterative sensor S_FMT for sensor output window.
 
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/sn9c102.txt linux-libre-2.6.39-gnu/Documentation/video4linux/sn9c102.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/sn9c102.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/sn9c102.txt	2011-05-19 00:06:34.000000000 -0400
@@ -214,10 +214,10 @@
 Description:    Debugging information level, from 0 to 3:
 		0 = none (use carefully)
 		1 = critical errors
-		2 = significant informations
+		2 = significant information
 		3 = more verbose messages
 		Level 3 is useful for testing only. It also shows some more
-		informations about the hardware being detected.
+		information about the hardware being detected.
 		This parameter can be changed at runtime thanks to the /sys
 		filesystem interface.
 Default:        2
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/v4l2-framework.txt linux-libre-2.6.39-gnu/Documentation/video4linux/v4l2-framework.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/v4l2-framework.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/v4l2-framework.txt	2011-05-19 00:06:34.000000000 -0400
@@ -71,6 +71,10 @@
 and in the future a v4l2_fh struct will keep track of filehandle instances
 (this is not yet implemented).
 
+The V4L2 framework also optionally integrates with the media framework. If a
+driver sets the struct v4l2_device mdev field, sub-devices and video nodes
+will automatically appear in the media framework as entities.
+
 
 struct v4l2_device
 ------------------
@@ -83,11 +87,20 @@
 
 	v4l2_device_register(struct device *dev, struct v4l2_device *v4l2_dev);
 
-Registration will initialize the v4l2_device struct and link dev->driver_data
-to v4l2_dev. If v4l2_dev->name is empty then it will be set to a value derived
-from dev (driver name followed by the bus_id, to be precise). If you set it
-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.
+Registration will initialize the v4l2_device struct. If the dev->driver_data
+field is NULL, it will be linked to v4l2_dev.
+
+Drivers that want integration with the media device framework need to set
+dev->driver_data manually to point to the driver-specific device structure
+that embed the struct v4l2_device instance. This is achieved by a
+dev_set_drvdata() call before registering the V4L2 device instance. They must
+also set the struct v4l2_device mdev field to point to a properly initialized
+and registered media_device instance.
+
+If v4l2_dev->name is empty then it will be set to a value derived from dev
+(driver name followed by the bus_id, to be precise). If you set it 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,
@@ -108,6 +121,7 @@
 
 	v4l2_device_unregister(struct v4l2_device *v4l2_dev);
 
+If the dev->driver_data field points to v4l2_dev, it will be reset to NULL.
 Unregistering will also automatically unregister all subdevs from the device.
 
 If you have a hotpluggable device (e.g. a USB device), then when a disconnect
@@ -167,6 +181,21 @@
 	state->instance = atomic_inc_return(&drv_instance) - 1;
 }
 
+If you have multiple device nodes then it can be difficult to know when it is
+safe to unregister v4l2_device. For this purpose v4l2_device has refcounting
+support. The refcount is increased whenever video_register_device is called and
+it is decreased whenever that device node is released. When the refcount reaches
+zero, then the v4l2_device release() callback is called. You can do your final
+cleanup there.
+
+If other device nodes (e.g. ALSA) are created, then you can increase and
+decrease the refcount manually as well by calling:
+
+void v4l2_device_get(struct v4l2_device *v4l2_dev);
+
+or:
+
+int v4l2_device_put(struct v4l2_device *v4l2_dev);
 
 struct v4l2_subdev
 ------------------
@@ -254,6 +283,26 @@
 Afterwards you need to initialize subdev->name with a unique name and set the
 module owner. This is done for you if you use the i2c helper functions.
 
+If integration with the media framework is needed, you must initialize the
+media_entity struct embedded in the v4l2_subdev struct (entity field) by
+calling media_entity_init():
+
+	struct media_pad *pads = &my_sd->pads;
+	int err;
+
+	err = media_entity_init(&sd->entity, npads, pads, 0);
+
+The pads array must have been previously initialized. There is no need to
+manually set the struct media_entity type and name fields, but the revision
+field must be initialized if needed.
+
+A reference to the entity will be automatically acquired/released when the
+subdev device node (if any) is opened/closed.
+
+Don't forget to cleanup the media entity before the sub-device is destroyed:
+
+	media_entity_cleanup(&sd->entity);
+
 A device (bridge) driver needs to register the v4l2_subdev with the
 v4l2_device:
 
@@ -263,6 +312,9 @@
 After this function was called successfully the subdev->dev field points to
 the v4l2_device.
 
+If the v4l2_device parent device has a non-NULL mdev field, the sub-device
+entity will be automatically registered with the media device.
+
 You can unregister a sub-device using:
 
 	v4l2_device_unregister_subdev(sd);
@@ -291,7 +343,7 @@
 	err = v4l2_device_call_until_err(v4l2_dev, 0, core, g_chip_ident, &chip);
 
 Any error except -ENOIOCTLCMD will exit the loop with that error. If no
-errors (except -ENOIOCTLCMD) occured, then 0 is returned.
+errors (except -ENOIOCTLCMD) occurred, then 0 is returned.
 
 The second argument to both calls is a group ID. If 0, then all subdevs are
 called. If non-zero, then only those whose group ID match that value will
@@ -319,6 +371,61 @@
 up the device, but once the subdev is registered it is completely transparent.
 
 
+V4L2 sub-device userspace API
+-----------------------------
+
+Beside exposing a kernel API through the v4l2_subdev_ops structure, V4L2
+sub-devices can also be controlled directly by userspace applications.
+
+Device nodes named v4l-subdevX can be created in /dev to access sub-devices
+directly. If a sub-device supports direct userspace configuration it must set
+the V4L2_SUBDEV_FL_HAS_DEVNODE flag before being registered.
+
+After registering sub-devices, the v4l2_device driver can create device nodes
+for all registered sub-devices marked with V4L2_SUBDEV_FL_HAS_DEVNODE by calling
+v4l2_device_register_subdev_nodes(). Those device nodes will be automatically
+removed when sub-devices are unregistered.
+
+The device node handles a subset of the V4L2 API.
+
+VIDIOC_QUERYCTRL
+VIDIOC_QUERYMENU
+VIDIOC_G_CTRL
+VIDIOC_S_CTRL
+VIDIOC_G_EXT_CTRLS
+VIDIOC_S_EXT_CTRLS
+VIDIOC_TRY_EXT_CTRLS
+
+	The controls ioctls are identical to the ones defined in V4L2. They
+	behave identically, with the only exception that they deal only with
+	controls implemented in the sub-device. Depending on the driver, those
+	controls can be also be accessed through one (or several) V4L2 device
+	nodes.
+
+VIDIOC_DQEVENT
+VIDIOC_SUBSCRIBE_EVENT
+VIDIOC_UNSUBSCRIBE_EVENT
+
+	The events ioctls are identical to the ones defined in V4L2. They
+	behave identically, with the only exception that they deal only with
+	events generated by the sub-device. Depending on the driver, those
+	events can also be reported by one (or several) V4L2 device nodes.
+
+	Sub-device drivers that want to use events need to set the
+	V4L2_SUBDEV_USES_EVENTS v4l2_subdev::flags and initialize
+	v4l2_subdev::nevents to events queue depth before registering the
+	sub-device. After registration events can be queued as usual on the
+	v4l2_subdev::devnode device node.
+
+	To properly support events, the poll() file operation is also
+	implemented.
+
+Private ioctls
+
+	All ioctls not in the above list are passed directly to the sub-device
+	driver through the core::ioctl operation.
+
+
 I2C sub-device drivers
 ----------------------
 
@@ -457,6 +564,10 @@
   Otherwise you give it a pointer to a struct mutex_lock and before any
   of the v4l2_file_operations is called this lock will be taken by the
   core and released afterwards.
+- prio: keeps track of the priorities. Used to implement VIDIOC_G/S_PRIORITY.
+  If left to NULL, then it will use the struct v4l2_prio_state in v4l2_device.
+  If you want to have a separate priority state per (group of) device node(s),
+  then you can point it to your own struct v4l2_prio_state.
 - parent: you only set this if v4l2_device was registered with NULL as
   the parent device struct. This only happens in cases where one hardware
   device has multiple PCI devices that all share the same v4l2_device core.
@@ -466,13 +577,34 @@
   (cx8802). Since the v4l2_device cannot be associated with a particular
   PCI device it is setup without a parent device. But when the struct
   video_device is setup you do know which parent PCI device to use.
+- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework
+  handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct
+  v4l2_fh. Eventually this flag will disappear once all drivers use the core
+  priority handling. But for now it has to be set explicitly.
 
-If you use v4l2_ioctl_ops, then you should set either .unlocked_ioctl or
-.ioctl to video_ioctl2 in your v4l2_file_operations struct.
+If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2
+in your v4l2_file_operations struct.
+
+Do not use .ioctl! This is deprecated and will go away in the future.
 
 The v4l2_file_operations struct is a subset of file_operations. The main
 difference is that the inode argument is omitted since it is never used.
 
+If integration with the media framework is needed, you must initialize the
+media_entity struct embedded in the video_device struct (entity field) by
+calling media_entity_init():
+
+	struct media_pad *pad = &my_vdev->pad;
+	int err;
+
+	err = media_entity_init(&vdev->entity, 1, pad, 0);
+
+The pads array must have been previously initialized. There is no need to
+manually set the struct media_entity type and name fields.
+
+A reference to the entity will be automatically acquired/released when the
+video device is opened/closed.
+
 v4l2_file_operations and locking
 --------------------------------
 
@@ -502,6 +634,9 @@
 		return err;
 	}
 
+If the v4l2_device parent device has a non-NULL mdev field, the video device
+entity will be automatically registered with the media device.
+
 Which device is registered depends on the type argument. The following
 types exist:
 
@@ -577,6 +712,13 @@
 When the last user of the video device node exits, then the vdev->release()
 callback is called and you can do the final cleanup there.
 
+Don't forget to cleanup the media entity associated with the video device if
+it has been initialized:
+
+	media_entity_cleanup(&vdev->entity);
+
+This can be done from the release callback.
+
 
 video_device helper functions
 -----------------------------
@@ -636,39 +778,25 @@
 --------------
 
 struct v4l2_fh provides a way to easily keep file handle specific data
-that is used by the V4L2 framework. Using v4l2_fh is optional for
-drivers.
+that is used by the V4L2 framework. New drivers must use struct v4l2_fh
+since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY)
+if the video_device flag V4L2_FL_USE_FH_PRIO is also set.
 
 The users of v4l2_fh (in the V4L2 framework, not the driver) know
 whether a driver uses v4l2_fh as its file->private_data pointer by
-testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags.
-
-Useful functions:
-
-- v4l2_fh_init()
-
-  Initialise the file handle. This *MUST* be performed in the driver's
-  v4l2_file_operations->open() handler.
-
-- v4l2_fh_add()
-
-  Add a v4l2_fh to video_device file handle list. May be called after
-  initialising the file handle.
-
-- v4l2_fh_del()
-
-  Unassociate the file handle from video_device(). The file handle
-  exit function may now be called.
+testing the V4L2_FL_USES_V4L2_FH bit in video_device->flags. This bit is
+set whenever v4l2_fh_init() is called.
 
-- v4l2_fh_exit()
+struct v4l2_fh is allocated as a part of the driver's own file handle
+structure and file->private_data is set to it in the driver's open
+function by the driver.
 
-  Uninitialise the file handle. After uninitialisation the v4l2_fh
-  memory can be freed.
+In many cases the struct v4l2_fh will be embedded in a larger structure.
+In that case you should call v4l2_fh_init+v4l2_fh_add in open() and
+v4l2_fh_del+v4l2_fh_exit in release().
 
-struct v4l2_fh is allocated as a part of the driver's own file handle
-structure and is set to file->private_data in the driver's open
-function by the driver. Drivers can extract their own file handle
-structure by using the container_of macro. Example:
+Drivers can extract their own file handle structure by using the container_of
+macro. Example:
 
 struct my_fh {
 	int blah;
@@ -685,15 +813,21 @@
 
 	...
 
+	my_fh = kzalloc(sizeof(*my_fh), GFP_KERNEL);
+
+	...
+
 	ret = v4l2_fh_init(&my_fh->fh, vfd);
-	if (ret)
+	if (ret) {
+		kfree(my_fh);
 		return ret;
+	}
 
-	v4l2_fh_add(&my_fh->fh);
+	...
 
 	file->private_data = &my_fh->fh;
-
-	...
+	v4l2_fh_add(&my_fh->fh);
+	return 0;
 }
 
 int my_release(struct file *file)
@@ -702,8 +836,65 @@
 	struct my_fh *my_fh = container_of(fh, struct my_fh, fh);
 
 	...
+	v4l2_fh_del(&my_fh->fh);
+	v4l2_fh_exit(&my_fh->fh);
+	kfree(my_fh);
+	return 0;
 }
 
+Below is a short description of the v4l2_fh functions used:
+
+int v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
+
+  Initialise the file handle. This *MUST* be performed in the driver's
+  v4l2_file_operations->open() handler.
+
+void v4l2_fh_add(struct v4l2_fh *fh)
+
+  Add a v4l2_fh to video_device file handle list. Must be called once the
+  file handle is completely initialized.
+
+void v4l2_fh_del(struct v4l2_fh *fh)
+
+  Unassociate the file handle from video_device(). The file handle
+  exit function may now be called.
+
+void v4l2_fh_exit(struct v4l2_fh *fh)
+
+  Uninitialise the file handle. After uninitialisation the v4l2_fh
+  memory can be freed.
+
+
+If struct v4l2_fh is not embedded, then you can use these helper functions:
+
+int v4l2_fh_open(struct file *filp)
+
+  This allocates a struct v4l2_fh, initializes it and adds it to the struct
+  video_device associated with the file struct.
+
+int v4l2_fh_release(struct file *filp)
+
+  This deletes it from the struct video_device associated with the file
+  struct, uninitialised the v4l2_fh and frees it.
+
+These two functions can be plugged into the v4l2_file_operation's open() and
+release() ops.
+
+
+Several drivers need to do something when the first file handle is opened and
+when the last file handle closes. Two helper functions were added to check
+whether the v4l2_fh struct is the only open filehandle of the associated
+device node:
+
+int v4l2_fh_is_singular(struct v4l2_fh *fh)
+
+  Returns 1 if the file handle is the only open file handle, else 0.
+
+int v4l2_fh_is_singular_file(struct file *filp)
+
+  Same, but it calls v4l2_fh_is_singular with filp->private_data.
+
+
 V4L2 events
 -----------
 
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/w9968cf.txt linux-libre-2.6.39-gnu/Documentation/video4linux/w9968cf.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/w9968cf.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/w9968cf.txt	2011-05-19 00:06:34.000000000 -0400
@@ -413,7 +413,7 @@
 Description:    Debugging information level, from 0 to 6:
 		0 = none (use carefully)
 		1 = critical errors
-		2 = significant informations
+		2 = significant information
 		3 = configuration or general messages
 		4 = warnings
 		5 = called functions
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/zc0301.txt linux-libre-2.6.39-gnu/Documentation/video4linux/zc0301.txt
--- linux-libre-2.6.38-gnu/Documentation/video4linux/zc0301.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/zc0301.txt	2011-05-19 00:06:34.000000000 -0400
@@ -181,10 +181,10 @@
 Description:    Debugging information level, from 0 to 3:
 		0 = none (use carefully)
 		1 = critical errors
-		2 = significant informations
+		2 = significant information
 		3 = more verbose messages
 		Level 3 is useful for testing only, when only one device
-		is used at the same time. It also shows some more informations
+		is used at the same time. It also shows some information
 		about the hardware being detected. This module parameter can be
 		changed at runtime thanks to the /sys filesystem interface.
 Default:        2
@@ -261,7 +261,7 @@
 
 11. Credits
 ===========
-- Informations about the chip internals needed to enable the I2C protocol have
+- Information about the chip internals needed to enable the I2C protocol have
   been taken from the documentation of the ZC030x Video4Linux1 driver written
   by Andrew Birkett <andy@nobugs.org>;
 - The initialization values of the ZC0301 controller connected to the PAS202BCB
diff -druN linux-libre-2.6.38-gnu/Documentation/video4linux/Zoran linux-libre-2.6.39-gnu/Documentation/video4linux/Zoran
--- linux-libre-2.6.38-gnu/Documentation/video4linux/Zoran	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/video4linux/Zoran	2011-05-19 00:06:34.000000000 -0400
@@ -130,7 +130,7 @@
 
 Note: No module for the mse3000 is available yet
 Note: No module for the vpx3224 is available yet
-Note: use encoder=X or decoder=X for non-default i2c chips (see i2c-id.h)
+Note: use encoder=X or decoder=X for non-default i2c chips
 
 ===========================
 
diff -druN linux-libre-2.6.38-gnu/Documentation/vm/active_mm.txt linux-libre-2.6.39-gnu/Documentation/vm/active_mm.txt
--- linux-libre-2.6.38-gnu/Documentation/vm/active_mm.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/vm/active_mm.txt	2011-05-19 00:06:34.000000000 -0400
@@ -74,7 +74,7 @@
 and things like that).
 
 Anyway, I put a pre-patch-2.3.13-1 on ftp.kernel.org just a moment ago,
-because it slightly changes the interfaces to accomodate the alpha (who
+because it slightly changes the interfaces to accommodate the alpha (who
 would have thought it, but the alpha actually ends up having one of the
 ugliest context switch codes - unlike the other architectures where the MM
 and register state is separate, the alpha PALcode joins the two, and you
diff -druN linux-libre-2.6.38-gnu/Documentation/vm/hugetlbpage.txt linux-libre-2.6.39-gnu/Documentation/vm/hugetlbpage.txt
--- linux-libre-2.6.38-gnu/Documentation/vm/hugetlbpage.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/vm/hugetlbpage.txt	2011-05-19 00:06:34.000000000 -0400
@@ -72,7 +72,7 @@
 allocating huge pages as memory has not yet become fragmented.
 
 Some platforms support multiple huge page sizes.  To allocate huge pages
-of a specific size, one must preceed the huge pages boot command parameters
+of a specific size, one must precede the huge pages boot command parameters
 with a huge page size selection parameter "hugepagesz=<size>".  <size> must
 be specified in bytes with optional scale suffix [kKmMgG].  The default huge
 page size may be selected with the "default_hugepagesz=<size>" boot parameter.
diff -druN linux-libre-2.6.38-gnu/Documentation/vm/overcommit-accounting linux-libre-2.6.39-gnu/Documentation/vm/overcommit-accounting
--- linux-libre-2.6.38-gnu/Documentation/vm/overcommit-accounting	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/vm/overcommit-accounting	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 		address space are refused. Used for a typical system. It
 		ensures a seriously wild allocation fails while allowing
 		overcommit to reduce swap usage.  root is allowed to 
-		allocate slighly more memory in this mode. This is the 
+		allocate slightly more memory in this mode. This is the 
 		default.
 
 1	-	Always overcommit. Appropriate for some scientific
diff -druN linux-libre-2.6.38-gnu/Documentation/vm/page-types.c linux-libre-2.6.39-gnu/Documentation/vm/page-types.c
--- linux-libre-2.6.38-gnu/Documentation/vm/page-types.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/vm/page-types.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,19 @@
 #include <sys/types.h>
 #include <sys/errno.h>
 #include <sys/fcntl.h>
+#include <sys/mount.h>
+#include <sys/statfs.h>
+#include "../../include/linux/magic.h"
+
+
+#ifndef MAX_PATH
+# define MAX_PATH 256
+#endif
 
+#ifndef STR
+# define _STR(x) #x
+# define STR(x) _STR(x)
+#endif
 
 /*
  * pagemap kernel ABI bits
@@ -152,6 +164,12 @@
 };
 
 
+static const char *debugfs_known_mountpoints[] = {
+	"/sys/kernel/debug",
+	"/debug",
+	0,
+};
+
 /*
  * data structures
  */
@@ -184,7 +202,7 @@
 static int		opt_hwpoison;
 static int		opt_unpoison;
 
-static const char	hwpoison_debug_fs[] = "/debug/hwpoison";
+static char		hwpoison_debug_fs[MAX_PATH+1];
 static int		hwpoison_inject_fd;
 static int		hwpoison_forget_fd;
 
@@ -464,21 +482,100 @@
 	return flags;
 }
 
+/* verify that a mountpoint is actually a debugfs instance */
+static int debugfs_valid_mountpoint(const char *debugfs)
+{
+	struct statfs st_fs;
+
+	if (statfs(debugfs, &st_fs) < 0)
+		return -ENOENT;
+	else if (st_fs.f_type != (long) DEBUGFS_MAGIC)
+		return -ENOENT;
+
+	return 0;
+}
+
+/* find the path to the mounted debugfs */
+static const char *debugfs_find_mountpoint(void)
+{
+	const char **ptr;
+	char type[100];
+	FILE *fp;
+
+	ptr = debugfs_known_mountpoints;
+	while (*ptr) {
+		if (debugfs_valid_mountpoint(*ptr) == 0) {
+			strcpy(hwpoison_debug_fs, *ptr);
+			return hwpoison_debug_fs;
+		}
+		ptr++;
+	}
+
+	/* give up and parse /proc/mounts */
+	fp = fopen("/proc/mounts", "r");
+	if (fp == NULL)
+		perror("Can't open /proc/mounts for read");
+
+	while (fscanf(fp, "%*s %"
+		      STR(MAX_PATH)
+		      "s %99s %*s %*d %*d\n",
+		      hwpoison_debug_fs, type) == 2) {
+		if (strcmp(type, "debugfs") == 0)
+			break;
+	}
+	fclose(fp);
+
+	if (strcmp(type, "debugfs") != 0)
+		return NULL;
+
+	return hwpoison_debug_fs;
+}
+
+/* mount the debugfs somewhere if it's not mounted */
+
+static void debugfs_mount(void)
+{
+	const char **ptr;
+
+	/* see if it's already mounted */
+	if (debugfs_find_mountpoint())
+		return;
+
+	ptr = debugfs_known_mountpoints;
+	while (*ptr) {
+		if (mount(NULL, *ptr, "debugfs", 0, NULL) == 0) {
+			/* save the mountpoint */
+			strcpy(hwpoison_debug_fs, *ptr);
+			break;
+		}
+		ptr++;
+	}
+
+	if (*ptr == NULL) {
+		perror("mount debugfs");
+		exit(EXIT_FAILURE);
+	}
+}
+
 /*
  * page actions
  */
 
 static void prepare_hwpoison_fd(void)
 {
-	char buf[100];
+	char buf[MAX_PATH + 1];
+
+	debugfs_mount();
 
 	if (opt_hwpoison && !hwpoison_inject_fd) {
-		sprintf(buf, "%s/corrupt-pfn", hwpoison_debug_fs);
+		snprintf(buf, MAX_PATH, "%s/hwpoison/corrupt-pfn",
+			hwpoison_debug_fs);
 		hwpoison_inject_fd = checked_open(buf, O_WRONLY);
 	}
 
 	if (opt_unpoison && !hwpoison_forget_fd) {
-		sprintf(buf, "%s/unpoison-pfn", hwpoison_debug_fs);
+		snprintf(buf, MAX_PATH, "%s/hwpoison/unpoison-pfn",
+			hwpoison_debug_fs);
 		hwpoison_forget_fd = checked_open(buf, O_WRONLY);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/Documentation/vm/unevictable-lru.txt linux-libre-2.6.39-gnu/Documentation/vm/unevictable-lru.txt
--- linux-libre-2.6.38-gnu/Documentation/vm/unevictable-lru.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/vm/unevictable-lru.txt	2011-05-19 00:06:34.000000000 -0400
@@ -84,8 +84,7 @@
 
 The PG_unevictable flag is analogous to, and mutually exclusive with, the
 PG_active flag in that it indicates on which LRU list a page resides when
-PG_lru is set.  The unevictable list is compile-time configurable based on the
-UNEVICTABLE_LRU Kconfig option.
+PG_lru is set.
 
 The Unevictable LRU infrastructure maintains unevictable pages on an additional
 LRU list for a few reasons:
diff -druN linux-libre-2.6.38-gnu/Documentation/w1/slaves/w1_ds2423 linux-libre-2.6.39-gnu/Documentation/w1/slaves/w1_ds2423
--- linux-libre-2.6.38-gnu/Documentation/w1/slaves/w1_ds2423	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/w1/slaves/w1_ds2423	2011-05-19 00:06:34.000000000 -0400
@@ -21,8 +21,8 @@
 
 Each lines will contain the values of 42 bytes read from the counter and
 memory page along the crc=YES or NO for indicating whether the read operation
-was successfull and CRC matched.
-If the operation was successfull, there is also in the end of each line
+was successful and CRC matched.
+If the operation was successful, there is also in the end of each line
 a counter value expressed as an integer after c=
 
 Meaning of 42 bytes represented is following:
@@ -34,7 +34,7 @@
  - crc=YES/NO indicating whether read was ok and crc matched
  - c=<int> current counter value
 
-example from the successfull read:
+example from the successful read:
 00 02 00 00 00 00 00 00 00 6d 38 00 ff ff 00 00 fe ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
 00 02 00 00 00 00 00 00 00 e0 1f 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=2
 00 29 c6 5d 18 00 00 00 00 04 37 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff 00 00 ff ff crc=YES c=408798761
diff -druN linux-libre-2.6.38-gnu/Documentation/w1/w1.netlink linux-libre-2.6.39-gnu/Documentation/w1/w1.netlink
--- linux-libre-2.6.38-gnu/Documentation/w1/w1.netlink	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/w1/w1.netlink	2011-05-19 00:06:34.000000000 -0400
@@ -81,7 +81,7 @@
 format:
 
 	cn_msg (CN_W1_IDX.CN_W1_VAL as id, len is equal to sizeof(struct
-	w1_netlink_msg) plus number of masters multipled by 4)
+	w1_netlink_msg) plus number of masters multiplied by 4)
 	w1_netlink_msg (type: W1_LIST_MASTERS, len is equal to
 		number of masters multiplied by 4 (u32 size))
 	id0 ... idN
diff -druN linux-libre-2.6.38-gnu/Documentation/watchdog/hpwdt.txt linux-libre-2.6.39-gnu/Documentation/watchdog/hpwdt.txt
--- linux-libre-2.6.38-gnu/Documentation/watchdog/hpwdt.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/watchdog/hpwdt.txt	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
  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.
+ by the user. Remember that the two modes are not dependent 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
diff -druN linux-libre-2.6.38-gnu/Documentation/workqueue.txt linux-libre-2.6.39-gnu/Documentation/workqueue.txt
--- linux-libre-2.6.38-gnu/Documentation/workqueue.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/workqueue.txt	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 4. Application Programming Interface (API)
 5. Example Execution Scenarios
 6. Guidelines
+7. Debugging
 
 
 1. Introduction
@@ -379,3 +380,42 @@
 * Unless work items are expected to consume a huge amount of CPU
   cycles, using a bound wq is usually beneficial due to the increased
   level of locality in wq operations and work item execution.
+
+
+7. Debugging
+
+Because the work functions are executed by generic worker threads
+there are a few tricks needed to shed some light on misbehaving
+workqueue users.
+
+Worker threads show up in the process list as:
+
+root      5671  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/0:1]
+root      5672  0.0  0.0      0     0 ?        S    12:07   0:00 [kworker/1:2]
+root      5673  0.0  0.0      0     0 ?        S    12:12   0:00 [kworker/0:0]
+root      5674  0.0  0.0      0     0 ?        S    12:13   0:00 [kworker/1:0]
+
+If kworkers are going crazy (using too much cpu), there are two types
+of possible problems:
+
+	1. Something beeing scheduled in rapid succession
+	2. A single work item that consumes lots of cpu cycles
+
+The first one can be tracked using tracing:
+
+	$ echo workqueue:workqueue_queue_work > /sys/kernel/debug/tracing/set_event
+	$ cat /sys/kernel/debug/tracing/trace_pipe > out.txt
+	(wait a few secs)
+	^C
+
+If something is busy looping on work queueing, it would be dominating
+the output and the offender can be determined with the work item
+function.
+
+For the second type of problems it should be possible to just check
+the stack trace of the offending worker thread.
+
+	$ cat /proc/THE_OFFENDING_KWORKER/stack
+
+The work item's function should be trivially visible in the stack
+trace.
diff -druN linux-libre-2.6.38-gnu/Documentation/x86/x86_64/boot-options.txt linux-libre-2.6.39-gnu/Documentation/x86/x86_64/boot-options.txt
--- linux-libre-2.6.38-gnu/Documentation/x86/x86_64/boot-options.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/x86/x86_64/boot-options.txt	2011-05-19 00:06:34.000000000 -0400
@@ -189,13 +189,13 @@
 
 PCI
 
-  pci=off	Don't use PCI
-  pci=conf1	Use conf1 access.
-  pci=conf2	Use conf2 access.
-  pci=rom	Assign ROMs.
-  pci=assign-busses    Assign busses
-  pci=irqmask=MASK	       Set PCI interrupt mask to MASK
-  pci=lastbus=NUMBER	       Scan upto NUMBER busses, no matter what the mptable says.
+  pci=off		Don't use PCI
+  pci=conf1		Use conf1 access.
+  pci=conf2		Use conf2 access.
+  pci=rom		Assign ROMs.
+  pci=assign-busses	Assign busses
+  pci=irqmask=MASK	Set PCI interrupt mask to MASK
+  pci=lastbus=NUMBER	Scan up to NUMBER busses, no matter what the mptable says.
   pci=noacpi		Don't use ACPI to set up PCI interrupt routing.
 
 IOMMU (input/output memory management unit)
@@ -293,11 +293,6 @@
 
 Debugging
 
-  oops=panic	Always panic on oopses. Default is to just kill the process,
-		but there is a small probability of deadlocking the machine.
-		This will also cause panics on machine check exceptions.
-		Useful together with panic=30 to trigger a reboot.
-
   kstack=N	Print N words from the kernel stack in oops dumps.
 
   pagefaulttrace  Dump all page faults. Only useful for extreme debugging
diff -druN linux-libre-2.6.38-gnu/Documentation/zh_CN/magic-number.txt linux-libre-2.6.39-gnu/Documentation/zh_CN/magic-number.txt
--- linux-libre-2.6.38-gnu/Documentation/zh_CN/magic-number.txt	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/zh_CN/magic-number.txt	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,167 @@
+Chinese translated version of Documentation/magic-number.txt
+
+If you have any comment or update to the content, please post to LKML directly.
+However, if you have problem communicating in English you can also ask the
+Chinese maintainer for help.  Contact the Chinese maintainer, if this
+translation is outdated or there is problem with translation.
+
+Chinese maintainer: Jia Wei Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/magic-number.txtçš„ä¸­æ–‡ç¿»è¯‘
+
+å¦‚æžœæƒ³è¯„è®ºæˆ–æ›´æ–°æœ¬æ–‡çš„å†…å®¹ï¼Œè¯·ç›´æŽ¥å�‘ä¿¡åˆ°LKMLã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡äº¤æµ�æœ‰å›°éš¾çš„è¯�ï¼Œä¹Ÿå�¯
+ä»¥å�‘ä¸­æ–‡ç‰ˆç»´æŠ¤è€…æ±‚åŠ©ã€‚å¦‚æžœæœ¬ç¿»è¯‘æ›´æ–°ä¸�å�Šæ—¶æˆ–è€…ç¿»è¯‘å­˜åœ¨é—®é¢˜ï¼Œè¯·è�”ç³»ä¸­æ–‡ç‰ˆç»´æŠ¤è€…ã€‚
+
+ä¸­æ–‡ç‰ˆç»´æŠ¤è€…ï¼š è´¾å¨�å¨� Jia Wei Wei <harryxiyou@gmail.com>
+ä¸­æ–‡ç‰ˆç¿»è¯‘è€…ï¼š è´¾å¨�å¨� Jia Wei Wei <harryxiyou@gmail.com>
+ä¸­æ–‡ç‰ˆæ ¡è¯‘è€…ï¼š è´¾å¨�å¨� Jia Wei Wei <harryxiyou@gmail.com>
+
+ä»¥ä¸‹ä¸ºæ­£æ–‡
+---------------------------------------------------------------------
+è¿™ä¸ªæ–‡ä»¶æ˜¯æœ‰å…³å½“å‰�ä½¿ç”¨çš„é­”æœ¯å€¼æ³¨å†Œè¡¨ã€‚å½“ä½ ç»™ä¸€ä¸ªç»“æž„æ·»åŠ äº†ä¸€ä¸ªé­”æœ¯å€¼ï¼Œä½ ä¹Ÿåº”è¯¥æŠŠè¿™ä¸ªé­”æœ¯å€¼æ·»åŠ åˆ°è¿™ä¸ªæ–‡ä»¶ï¼Œå› ä¸ºæˆ‘ä»¬æœ€å¥½æŠŠç”¨äºŽå�„ç§�ç»“æž„çš„é­”æœ¯å€¼ç»Ÿä¸€èµ·æ�¥ã€‚
+
+ä½¿ç”¨é­”æœ¯å€¼æ�¥ä¿�æŠ¤å†…æ ¸æ•°æ�®ç»“æž„æ˜¯ä¸€ä¸ªé�žå¸¸å¥½çš„ä¸»æ„�ã€‚è¿™å°±å…�è®¸ä½ åœ¨è¿�è¡ŒæœŸæ£€æŸ¥(a)ä¸€ä¸ªç»“æž„æ˜¯å�¦å·²ç»�è¢«æ”»å‡»ï¼Œæˆ–è€…(b)ä½ å·²ç»�ç»™ä¸€ä¸ªä¾‹è¡Œç¨‹åº�é€šè¿‡äº†ä¸€ä¸ªé”™è¯¯çš„ç»“æž„ã€‚å�Žä¸€ç§�æƒ…å†µç‰¹åˆ«åœ°æœ‰ç”¨---ç‰¹åˆ«æ˜¯å½“ä½ é€šè¿‡ä¸€ä¸ªç©ºæŒ‡é’ˆæŒ‡å�‘ç»“æž„ä½“çš„æ—¶å€™ã€‚ttyæº�ç �ï¼Œä¾‹å¦‚ï¼Œç»�å¸¸é€šè¿‡ç‰¹å®šé©±åŠ¨ä½¿ç”¨è¿™ç§�æ–¹æ³•å¹¶ä¸”å��å¤�åœ°æŽ’åˆ—ç‰¹å®šæ–¹é�¢çš„ç»“æž„ã€‚
+
+ä½¿ç”¨é­”æœ¯å€¼çš„æ–¹æ³•æ˜¯åœ¨ç»“æž„çš„å¼€å§‹å¤„å£°æ˜Žçš„ï¼Œå¦‚ä¸‹ï¼š
+
+struct tty_ldisc {
+	int	magic;
+	...
+};
+
+å½“ä½ ä»¥å�Žç»™å†…æ ¸æ·»åŠ å¢žå¼ºåŠŸèƒ½çš„æ—¶å€™ï¼Œè¯·é�µå®ˆè¿™æ�¡è§„åˆ™ï¼�è¿™æ ·å°±ä¼šèŠ‚çœ�æ•°ä¸�æ¸…çš„è°ƒè¯•æ—¶é—´ï¼Œç‰¹åˆ«æ˜¯ä¸€äº›å�¤æ€ªçš„æƒ…å†µï¼Œä¾‹å¦‚ï¼Œæ•°ç»„è¶…å‡ºèŒƒå›´å¹¶ä¸”é‡�æ–°å†™äº†è¶…å‡ºéƒ¨åˆ†ã€‚é�µå®ˆè¿™ä¸ªè§„åˆ™ï¼Œâ€ªè¿™äº›æƒ…å†µå�¯ä»¥è¢«å¿«é€Ÿåœ°ï¼Œå®‰å…¨åœ°é�¿å…�ã€‚
+
+		Theodore Ts'o
+		  31 Mar 94
+
+ç»™å½“å‰�çš„Linux 2.1.55æ·»åŠ é­”æœ¯è¡¨ã€‚
+
+		Michael Chastain
+		<mailto:mec@shout.net>
+		22 Sep 1997
+
+çŽ°åœ¨åº”è¯¥æœ€æ–°çš„Linux 2.1.112.å› ä¸ºåœ¨ç‰¹æ€§å†»ç»“æœŸé—´ï¼Œä¸�èƒ½åœ¨2.2.xå‰�æ”¹å�˜ä»»ä½•ä¸œè¥¿ã€‚è¿™äº›æ�¡ç›®è¢«æ•°åŸŸæ‰€æŽ’åº�ã€‚
+
+		Krzysztof G.Baranowski
+	        <mailto: kgb@knm.org.pl>
+		29 Jul 1998
+
+æ›´æ–°é­”æœ¯è¡¨åˆ°Linux 2.5.45ã€‚åˆšå¥½è¶Šè¿‡ç‰¹æ€§å†»ç»“ï¼Œä½†æ˜¯æœ‰å�¯èƒ½è¿˜ä¼šæœ‰ä¸€äº›æ–°çš„é­”æœ¯å€¼åœ¨2.6.xä¹‹å‰�èž�å…¥åˆ°å†…æ ¸ä¸­ã€‚
+
+		Petr Baudis
+		<pasky@ucw.cz>
+		03 Nov 2002
+
+æ›´æ–°é­”æœ¯è¡¨åˆ°Linux 2.5.74ã€‚
+
+		Fabian Frederick
+                <ffrederick@users.sourceforge.net>
+		09 Jul 2003
+
+é­”æœ¯å��                 åœ°å�€         ç»“æž„               æ‰€åœ¨æ–‡ä»¶
+===========================================================================
+PG_MAGIC              'P'         pg_{read,write}_hdr include/linux/pg.h
+CMAGIC                0x0111      user              include/linux/a.out.h
+MKISS_DRIVER_MAGIC    0x04bf      mkiss_channel     drivers/net/mkiss.h
+RISCOM8_MAGIC         0x0907      riscom_port       drivers/char/riscom8.h
+SPECIALIX_MAGIC       0x0907      specialix_port    drivers/char/specialix_io8.h
+HDLC_MAGIC            0x239e      n_hdlc            drivers/char/n_hdlc.c
+APM_BIOS_MAGIC        0x4101      apm_user          arch/i386/kernel/apm.c
+CYCLADES_MAGIC        0x4359      cyclades_port     include/linux/cyclades.h
+DB_MAGIC              0x4442      fc_info           drivers/net/iph5526_novram.c
+DL_MAGIC              0x444d      fc_info           drivers/net/iph5526_novram.c
+FASYNC_MAGIC          0x4601      fasync_struct     include/linux/fs.h
+FF_MAGIC              0x4646      fc_info           drivers/net/iph5526_novram.c
+ISICOM_MAGIC          0x4d54      isi_port          include/linux/isicom.h
+PTY_MAGIC             0x5001                        drivers/char/pty.c
+PPP_MAGIC             0x5002      ppp               include/linux/if_pppvar.h
+SERIAL_MAGIC          0x5301      async_struct      include/linux/serial.h
+SSTATE_MAGIC          0x5302      serial_state      include/linux/serial.h
+SLIP_MAGIC            0x5302      slip              drivers/net/slip.h
+STRIP_MAGIC           0x5303      strip             drivers/net/strip.c
+X25_ASY_MAGIC         0x5303      x25_asy           drivers/net/x25_asy.h
+SIXPACK_MAGIC         0x5304      sixpack           drivers/net/hamradio/6pack.h
+AX25_MAGIC            0x5316      ax_disp           drivers/net/mkiss.h
+ESP_MAGIC             0x53ee      esp_struct        drivers/char/esp.h
+TTY_MAGIC             0x5401      tty_struct        include/linux/tty.h
+MGSL_MAGIC            0x5401      mgsl_info         drivers/char/synclink.c
+TTY_DRIVER_MAGIC      0x5402      tty_driver        include/linux/tty_driver.h
+MGSLPC_MAGIC          0x5402      mgslpc_info       drivers/char/pcmcia/synclink_cs.c
+TTY_LDISC_MAGIC       0x5403      tty_ldisc         include/linux/tty_ldisc.h
+USB_SERIAL_MAGIC      0x6702      usb_serial        drivers/usb/serial/usb-serial.h
+FULL_DUPLEX_MAGIC     0x6969                        drivers/net/tulip/de2104x.c
+USB_BLUETOOTH_MAGIC   0x6d02      usb_bluetooth     drivers/usb/class/bluetty.c
+RFCOMM_TTY_MAGIC      0x6d02                        net/bluetooth/rfcomm/tty.c
+USB_SERIAL_PORT_MAGIC 0x7301      usb_serial_port   drivers/usb/serial/usb-serial.h
+CG_MAGIC              0x00090255  ufs_cylinder_group include/linux/ufs_fs.h
+A2232_MAGIC           0x000a2232  gs_port           drivers/char/ser_a2232.h
+RPORT_MAGIC           0x00525001  r_port            drivers/char/rocket_int.h
+LSEMAGIC              0x05091998  lse               drivers/fc4/fc.c
+GDTIOCTL_MAGIC        0x06030f07  gdth_iowr_str     drivers/scsi/gdth_ioctl.h
+RIEBL_MAGIC           0x09051990                    drivers/net/atarilance.c
+RIO_MAGIC             0x12345678  gs_port           drivers/char/rio/rio_linux.c
+SX_MAGIC              0x12345678  gs_port           drivers/char/sx.h
+NBD_REQUEST_MAGIC     0x12560953  nbd_request       include/linux/nbd.h
+RED_MAGIC2            0x170fc2a5  (any)             mm/slab.c
+BAYCOM_MAGIC          0x19730510  baycom_state      drivers/net/baycom_epp.c
+ISDN_X25IFACE_MAGIC   0x1e75a2b9  isdn_x25iface_proto_data
+                                                    drivers/isdn/isdn_x25iface.h
+ECP_MAGIC             0x21504345  cdkecpsig         include/linux/cdk.h
+LSOMAGIC              0x27091997  lso               drivers/fc4/fc.c
+LSMAGIC               0x2a3b4d2a  ls                drivers/fc4/fc.c
+WANPIPE_MAGIC         0x414C4453  sdla_{dump,exec}  include/linux/wanpipe.h
+CS_CARD_MAGIC         0x43525553  cs_card           sound/oss/cs46xx.c
+LABELCL_MAGIC         0x4857434c  labelcl_info_s    include/asm/ia64/sn/labelcl.h
+ISDN_ASYNC_MAGIC      0x49344C01  modem_info        include/linux/isdn.h
+CTC_ASYNC_MAGIC       0x49344C01  ctc_tty_info      drivers/s390/net/ctctty.c
+ISDN_NET_MAGIC        0x49344C02  isdn_net_local_s  drivers/isdn/i4l/isdn_net_lib.h
+SAVEKMSG_MAGIC2       0x4B4D5347  savekmsg          arch/*/amiga/config.c
+STLI_BOARDMAGIC       0x4bc6c825  stlibrd           include/linux/istallion.h
+CS_STATE_MAGIC        0x4c4f4749  cs_state          sound/oss/cs46xx.c
+SLAB_C_MAGIC          0x4f17a36d  kmem_cache        mm/slab.c
+COW_MAGIC             0x4f4f4f4d  cow_header_v1     arch/um/drivers/ubd_user.c
+I810_CARD_MAGIC       0x5072696E  i810_card         sound/oss/i810_audio.c
+TRIDENT_CARD_MAGIC    0x5072696E  trident_card      sound/oss/trident.c
+ROUTER_MAGIC          0x524d4157  wan_device        include/linux/wanrouter.h
+SCC_MAGIC             0x52696368  gs_port           drivers/char/scc.h
+SAVEKMSG_MAGIC1       0x53415645  savekmsg          arch/*/amiga/config.c
+GDA_MAGIC             0x58464552  gda               arch/mips/include/asm/sn/gda.h
+RED_MAGIC1            0x5a2cf071  (any)             mm/slab.c
+STL_PORTMAGIC         0x5a7182c9  stlport           include/linux/stallion.h
+EEPROM_MAGIC_VALUE    0x5ab478d2  lanai_dev         drivers/atm/lanai.c
+HDLCDRV_MAGIC         0x5ac6e778  hdlcdrv_state     include/linux/hdlcdrv.h
+EPCA_MAGIC            0x5c6df104  channel           include/linux/epca.h
+PCXX_MAGIC            0x5c6df104  channel           drivers/char/pcxx.h
+KV_MAGIC              0x5f4b565f  kernel_vars_s     arch/mips/include/asm/sn/klkernvars.h
+I810_STATE_MAGIC      0x63657373  i810_state        sound/oss/i810_audio.c
+TRIDENT_STATE_MAGIC   0x63657373  trient_state      sound/oss/trident.c
+M3_CARD_MAGIC         0x646e6f50  m3_card           sound/oss/maestro3.c
+FW_HEADER_MAGIC       0x65726F66  fw_header         drivers/atm/fore200e.h
+SLOT_MAGIC            0x67267321  slot              drivers/hotplug/cpqphp.h
+SLOT_MAGIC            0x67267322  slot              drivers/hotplug/acpiphp.h
+LO_MAGIC              0x68797548  nbd_device        include/linux/nbd.h
+OPROFILE_MAGIC        0x6f70726f  super_block       drivers/oprofile/oprofilefs.h
+M3_STATE_MAGIC        0x734d724d  m3_state          sound/oss/maestro3.c
+STL_PANELMAGIC        0x7ef621a1  stlpanel          include/linux/stallion.h
+VMALLOC_MAGIC         0x87654320  snd_alloc_track   sound/core/memory.c
+KMALLOC_MAGIC         0x87654321  snd_alloc_track   sound/core/memory.c
+PWC_MAGIC             0x89DC10AB  pwc_device        drivers/usb/media/pwc.h
+NBD_REPLY_MAGIC       0x96744668  nbd_reply         include/linux/nbd.h
+STL_BOARDMAGIC        0xa2267f52  stlbrd            include/linux/stallion.h
+ENI155_MAGIC          0xa54b872d  midway_eprom	    drivers/atm/eni.h
+SCI_MAGIC             0xbabeface  gs_port           drivers/char/sh-sci.h
+CODA_MAGIC            0xC0DAC0DA  coda_file_info    include/linux/coda_fs_i.h
+DPMEM_MAGIC           0xc0ffee11  gdt_pci_sram      drivers/scsi/gdth.h
+STLI_PORTMAGIC        0xe671c7a1  stliport          include/linux/istallion.h
+YAM_MAGIC             0xF10A7654  yam_port          drivers/net/hamradio/yam.c
+CCB_MAGIC             0xf2691ad2  ccb               drivers/scsi/ncr53c8xx.c
+QUEUE_MAGIC_FREE      0xf7e1c9a3  queue_entry       drivers/scsi/arm/queue.c
+QUEUE_MAGIC_USED      0xf7e1cc33  queue_entry       drivers/scsi/arm/queue.c
+HTB_CMAGIC            0xFEFAFEF1  htb_class         net/sched/sch_htb.c
+NMI_MAGIC             0x48414d4d455201 nmi_s        arch/mips/include/asm/sn/nmi.h
+
+è¯·æ³¨æ„�ï¼Œåœ¨å£°éŸ³è®°å¿†ç®¡ç�†ä¸­ä»�ç„¶æœ‰æ¯�ä¸€äº›è¢«å®šä¹‰çš„é©±åŠ¨é­”æœ¯å€¼ã€‚æŸ¥çœ‹include/sound/sndmagic.hæ�¥èŽ·å�–ä»–ä»¬å®Œæ•´çš„åˆ—è¡¨ä¿¡æ�¯ã€‚å¾ˆå¤šOSSå£°éŸ³é©±åŠ¨æ‹¥æœ‰è‡ªå·±ä»Žå£°å�¡PCI IDæž„å»ºçš„é­”æœ¯å€¼-ä»–ä»¬ä¹Ÿæ²¡æœ‰è¢«åˆ—åœ¨è¿™é‡Œã€‚
+
+IrDAå­�ç³»ç»Ÿä¹Ÿä½¿ç”¨äº†å¤§é‡�çš„è‡ªå·±çš„é­”æœ¯å€¼ï¼ŒæŸ¥çœ‹include/net/irda/irda.hæ�¥èŽ·å�–ä»–ä»¬å®Œæ•´çš„ä¿¡æ�¯ã€‚
+
+HFSæ˜¯å�¦å¤–ä¸€ä¸ªæ¯”è¾ƒå¤§çš„ä½¿ç”¨é­”æœ¯å€¼çš„æ–‡ä»¶ç³»ç»Ÿ-ä½ å�¯ä»¥åœ¨fs/hfs/hfs.hä¸­æ‰¾åˆ°ä»–ä»¬ã€‚
diff -druN linux-libre-2.6.38-gnu/Documentation/zh_CN/SecurityBugs linux-libre-2.6.39-gnu/Documentation/zh_CN/SecurityBugs
--- linux-libre-2.6.38-gnu/Documentation/zh_CN/SecurityBugs	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/zh_CN/SecurityBugs	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,50 @@
+Chinese translated version of Documentation/SecurityBugs
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/SecurityBugs çš„ä¸­æ–‡ç¿»è¯‘
+
+å¦‚æžœæƒ³è¯„è®ºæˆ–æ›´æ–°æœ¬æ–‡çš„å†…å®¹ï¼Œè¯·ç›´æŽ¥è�”ç³»åŽŸæ–‡æ¡£çš„ç»´æŠ¤è€…ã€‚å¦‚æžœä½ ä½¿ç”¨è‹±æ–‡
+äº¤æµ�æœ‰å›°éš¾çš„è¯�ï¼Œä¹Ÿå�¯ä»¥å�‘ä¸­æ–‡ç‰ˆç»´æŠ¤è€…æ±‚åŠ©ã€‚å¦‚æžœæœ¬ç¿»è¯‘æ›´æ–°ä¸�å�Šæ—¶æˆ–è€…ç¿»
+è¯‘å­˜åœ¨é—®é¢˜ï¼Œè¯·è�”ç³»ä¸­æ–‡ç‰ˆç»´æŠ¤è€…ã€‚
+
+ä¸­æ–‡ç‰ˆç»´æŠ¤è€…ï¼š è´¾å¨�å¨� Harry Wei <harryxiyou@gmail.com>
+ä¸­æ–‡ç‰ˆç¿»è¯‘è€…ï¼š è´¾å¨�å¨� Harry Wei <harryxiyou@gmail.com>
+ä¸­æ–‡ç‰ˆæ ¡è¯‘è€…ï¼š è´¾å¨�å¨� Harry Wei <harryxiyou@gmail.com>
+
+
+ä»¥ä¸‹ä¸ºæ­£æ–‡
+---------------------------------------------------------------------
+Linuxå†…æ ¸å¼€å�‘è€…è®¤ä¸ºå®‰å…¨é�žå¸¸é‡�è¦�ã€‚å› æ­¤ï¼Œæˆ‘ä»¬æƒ³è¦�çŸ¥é�“å½“ä¸€ä¸ªæœ‰å…³äºŽ
+å®‰å…¨çš„æ¼�æ´žè¢«å�‘çŽ°çš„æ—¶å€™ï¼Œå¹¶ä¸”å®ƒå�¯èƒ½ä¼šè¢«å°½å¿«çš„ä¿®å¤�æˆ–è€…å…¬å¼€ã€‚è¯·æŠŠè¿™ä¸ªå®‰å…¨
+æ¼�æ´žæŠ¥å‘Šç»™Linuxå†…æ ¸å®‰å…¨å›¢é˜Ÿã€‚
+
+1) è�”ç³»
+
+linuxå†…æ ¸å®‰å…¨å›¢é˜Ÿå�¯ä»¥é€šè¿‡email<security@kernel.org>æ�¥è�”ç³»ã€‚è¿™æ˜¯
+ä¸€ç»„ç‹¬ç«‹çš„å®‰å…¨å·¥ä½œäººå‘˜ï¼Œå�¯ä»¥å¸®åŠ©æ”¹å–„æ¼�æ´žæŠ¥å‘Šå¹¶ä¸”å…¬å¸ƒå’Œå�–æ¶ˆä¸€ä¸ªä¿®å¤�ã€‚å®‰
+å…¨å›¢é˜Ÿæœ‰å�¯èƒ½ä¼šä»Žéƒ¨åˆ†çš„ç»´æŠ¤è€…é‚£é‡Œå¼•è¿›é¢�å¤–çš„å¸®åŠ©æ�¥äº†è§£å¹¶ä¸”ä¿®å¤�å®‰å…¨æ¼�æ´žã€‚
+å½“é�‡åˆ°ä»»ä½•æ¼�æ´žï¼Œæ‰€èƒ½æ��ä¾›çš„ä¿¡æ�¯è¶Šå¤šå°±è¶Šèƒ½è¯Šæ–­å’Œä¿®å¤�ã€‚å¦‚æžœä½ ä¸�æ¸…æ¥šä»€ä¹ˆ
+æ˜¯æœ‰å¸®åŠ©çš„ä¿¡æ�¯ï¼Œé‚£å°±è¯·é‡�æ¸©ä¸€ä¸‹REPORTING-BUGSæ–‡ä»¶ä¸­çš„æ¦‚è¿°è¿‡ç¨‹ã€‚ä»»
+ä½•æ”»å‡»æ€§çš„ä»£ç �éƒ½æ˜¯é�žå¸¸æœ‰ç”¨çš„ï¼Œæœªç»�æŠ¥å‘Šè€…çš„å�Œæ„�ä¸�ä¼šè¢«å�–æ¶ˆï¼Œé™¤é�žå®ƒå·²ç»�
+è¢«å…¬å¸ƒäºŽä¼—ã€‚
+
+2) å…¬å¼€
+
+Linuxå†…æ ¸å®‰å…¨å›¢é˜Ÿçš„å®—æ—¨å°±æ˜¯å’Œæ¼�æ´žæ��äº¤è€…ä¸€èµ·å¤„ç�†æ¼�æ´žçš„è§£å†³æ–¹æ¡ˆç›´
+åˆ°å…¬å¼€ã€‚æˆ‘ä»¬å–œæ¬¢å°½å¿«åœ°å®Œå…¨å…¬å¼€æ¼�æ´žã€‚å½“ä¸€ä¸ªæ¼�æ´žæˆ–è€…ä¿®å¤�è¿˜æ²¡æœ‰è¢«å®Œå…¨åœ°ç�†
+è§£ï¼Œè§£å†³æ–¹æ¡ˆæ²¡æœ‰é€šè¿‡æµ‹è¯•æˆ–è€…ä¾›åº”å•†å��è°ƒï¼Œå�¯ä»¥å�ˆç�†åœ°å»¶è¿Ÿå…¬å¼€ã€‚ç„¶è€Œï¼Œæˆ‘ä»¬
+æœŸæœ›è¿™äº›å»¶è¿Ÿå°½å�¯èƒ½çš„çŸ­äº›ï¼Œæ˜¯å�¯æ•°çš„å‡ å¤©ï¼Œè€Œä¸�æ˜¯å‡ ä¸ªæ˜ŸæœŸæˆ–è€…å‡ ä¸ªæœˆã€‚å…¬å¼€
+æ—¥æœŸæ˜¯é€šè¿‡å®‰å…¨å›¢é˜Ÿå’Œæ¼�æ´žæ��ä¾›è€…ä»¥å�Šä¾›åº”å•†æ´½è°ˆå�Žçš„ç»“æžœã€‚å…¬å¼€æ—¶é—´è¡¨æ˜¯ä»Žå¾ˆ
+çŸ­ï¼ˆç‰¹æ®Šçš„ï¼Œå®ƒå·²ç»�è¢«å…¬ä¼—æ‰€çŸ¥é�“ï¼‰åˆ°å‡ ä¸ªæ˜ŸæœŸã€‚ä½œä¸ºä¸€ä¸ªåŸºæœ¬çš„é»˜è®¤æ”¿ç­–ï¼Œæˆ‘
+ä»¬æ‰€æœŸæœ›é€šçŸ¥å…¬ä¼—çš„æ—¥æœŸæ˜¯7å¤©çš„å®‰æŽ’ã€‚
+
+3) ä¿�å¯†å��è®®
+
+Linuxå†…æ ¸å®‰å…¨å›¢é˜Ÿä¸�æ˜¯ä¸€ä¸ªæ­£å¼�çš„å›¢ä½“ï¼Œå› æ­¤ä¸�èƒ½åŠ å…¥ä»»ä½•çš„ä¿�å¯†å��è®®ã€‚
diff -druN linux-libre-2.6.38-gnu/Documentation/zh_CN/SubmitChecklist linux-libre-2.6.39-gnu/Documentation/zh_CN/SubmitChecklist
--- linux-libre-2.6.38-gnu/Documentation/zh_CN/SubmitChecklist	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/Documentation/zh_CN/SubmitChecklist	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,109 @@
+Chinese translated version of Documentation/SubmitChecklist
+
+If you have any comment or update to the content, please contact the
+original document maintainer directly.  However, if you have a problem
+communicating in English you can also ask the Chinese maintainer for
+help.  Contact the Chinese maintainer if this translation is outdated
+or if there is a problem with the translation.
+
+Chinese maintainer: Harry Wei <harryxiyou@gmail.com>
+---------------------------------------------------------------------
+Documentation/SubmitChecklist µÄÖÐÎÄ·­Òë
+
+Èç¹ûÏëÆÀÂÛ»ò¸üÐÂ±¾ÎÄµÄÄÚÈÝ£¬ÇëÖ±½ÓÁªÏµÔ­ÎÄµµµÄÎ¬»¤Õß¡£Èç¹ûÄãÊ¹ÓÃÓ¢ÎÄ
+½»Á÷ÓÐÀ§ÄÑµÄ»°£¬Ò²¿ÉÒÔÏòÖÐÎÄ°æÎ¬»¤ÕßÇóÖú¡£Èç¹û±¾·­Òë¸üÐÂ²»¼°Ê±»òÕß·­
+Òë´æÔÚÎÊÌâ£¬ÇëÁªÏµÖÐÎÄ°æÎ¬»¤Õß¡£
+
+ÖÐÎÄ°æÎ¬»¤Õß£º ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
+ÖÐÎÄ°æ·­ÒëÕß£º ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
+ÖÐÎÄ°æÐ£ÒëÕß£º ¼ÖÍþÍþ Harry Wei <harryxiyou@gmail.com>
+
+
+ÒÔÏÂÎªÕýÎÄ
+---------------------------------------------------------------------
+LinuxÄÚºËÌá½»Çåµ¥
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+ÕâÀïÓÐÒ»Ð©ÄÚºË¿ª·¢ÕßÓ¦¸Ã×öµÄ»ù±¾ÊÂÇé£¬Èç¹ûËûÃÇÏë¿´µ½×Ô¼ºµÄÄÚºË²¹¶¡Ìá½»
+±»½ÓÊÜµÄ¸ü¿ì¡£
+
+ÕâÐ©¶¼ÊÇ³¬³öDocumentation/SubmittingPatchesÎÄµµÀïËùÌá¹©µÄÒÔ¼°ÆäËû
+¹ØÓÚÌá½»LinuxÄÚºË²¹¶¡µÄËµÃ÷¡£
+
+1£ºÈç¹ûÄãÊ¹ÓÃÁËÒ»¸ö¹¦ÄÜÄÇÃ´¾Í#include¶¨Òå/ÉùÃ÷ÄÇ¸ö¹¦ÄÜµÄÄÇ¸öÎÄ¼þ¡£
+   ²»ÒªÒÀ¿¿ÆäËû¼ä½ÓÒýÈë¶¨Òå/ÉùÃ÷ÄÇ¸ö¹¦ÄÜµÄÍ·ÎÄ¼þ¡£
+
+2£º¹¹½¨¼ò½àÊÊÓÃ»òÕß¸ü¸ÄCONFIGÑ¡Ïî =y£¬=m£¬»òÕß=n¡£
+   ²»ÒªÓÐ±àÒë¾¯¸æ/´íÎó£¬ ²»ÒªÓÐÁ´½Ó¾¯¸æ/´íÎó¡£
+
+2b£ºÍ¨¹ý allnoconfig, allmodconfig
+
+2c£ºµ±Ê¹ÓÃ 0=builddir ³É¹¦µØ¹¹½¨
+
+3£ºÍ¨¹ýÊ¹ÓÃ±¾µØ½»²æ±àÒë¹¤¾ß»òÕßÆäËûÒ»Ð©¹¹½¨²úËù£¬ÔÚ¶àCPU¿ò¼ÜÉÏ¹¹½¨¡£
+
+4£ºppc64 ÊÇÒ»¸öºÜºÃµÄ¼ì²é½»²æ±àÒëµÄ¿ò¼Ü£¬ÒòÎªËüÍùÍù°Ñ¡®unsigned long¡¯
+   µ±64Î»ÖµÀ´Ê¹ÓÃ¡£
+
+5£º°´ÕÕDocumentation/CodingStyleÎÄ¼þÀïµÄÏêÏ¸ÃèÊö£¬¼ì²éÄã²¹¶¡µÄÕûÌå·ç¸ñ¡£
+   Ê¹ÓÃ²¹¶¡·ç¸ñ¼ì²éËöËéµÄÎ¥¹æ(scripts/checkpatch.pl)£¬ÉóºËÔ±ÓÅÏÈÌá½»¡£
+   ÄãÓ¦¸Ãµ÷ÕûÒÅÁôÔÚÄã²¹¶¡ÖÐµÄËùÓÐÎ¥¹æ¡£
+
+6£ºÈÎºÎ¸üÐÂ»òÕß¸Ä¶¯CONFIGÑ¡Ïî¶¼²»ÄÜ´òÂÒÅäÖÃ²Ëµ¥¡£
+
+7£ºËùÓÐµÄKconfigÑ¡Ïî¸üÐÂ¶¼ÒªÓÐËµÃ÷ÎÄ×Ö¡£
+
+8£ºÒÑ¾­ÈÏÕæµØ×Ü½áÁËÏà¹ØµÄKconfig×éºÏ¡£ÕâÊÇºÜÄÑÍ¨¹ý²âÊÔ×öºÃµÄ--ÄÔÁ¦ÔÚÕâÀïÏÂ½µ¡£
+
+9£º¼ì²é¾ßÓÐ¼ò½àÐÔ¡£
+
+10£ºÊ¹ÓÃ'make checkstack'ºÍ'make namespacecheck'¼ì²é£¬È»ºóÐÞ¸ÄËùÕÒµ½µÄÎÊÌâ¡£
+    ×¢Òâ£º¶ÑÕ»¼ì²é²»»áÃ÷È·µØ³öÏÖÎÊÌâ£¬µ«ÊÇÈÎºÎµÄÒ»¸öº¯ÊýÔÚ¶ÑÕ»ÉÏÊ¹ÓÃ¶àÓÚ512×Ö½Ú
+    ¶¼Òª×¼±¸ÐÞ¸Ä¡£
+
+11£º°üº¬kernel-docµ½È«¾ÖÄÚºËAPIsÎÄ¼þ¡££¨²»ÒªÇó¾²Ì¬µÄº¯Êý£¬µ«ÊÇ°üº¬Ò²ÎÞËùÎ½¡££©
+    Ê¹ÓÃ'make htmldocs'»òÕß'make mandocs'À´¼ì²ékernel-doc£¬È»ºóÐÞ¸ÄÈÎºÎ
+    ·¢ÏÖµÄÎÊÌâ¡£
+
+12£ºÒÑ¾­Í¨¹ýCONFIG_PREEMPT, CONFIG_DEBUG_PREEMPT,
+    CONFIG_DEBUG_SLAB, CONFIG_DEBUG_PAGEALLOC, CONFIG_DEBUG_MUTEXES,
+    CONFIG_DEBUG_SPINLOCK, CONFIG_DEBUG_SPINLOCK_SLEEP²âÊÔ£¬²¢ÇÒÍ¬Ê±¶¼
+    Ê¹ÄÜ¡£
+
+13£ºÒÑ¾­¶¼¹¹½¨²¢ÇÒÊ¹ÓÃ»òÕß²»Ê¹ÓÃ CONFIG_SMP ºÍ CONFIG_PREEMPT²âÊÔÖ´ÐÐÊ±¼ä¡£
+
+14£ºÈç¹û²¹¶¡Ó°ÏìIO/Disk£¬µÈµÈ£ºÒÑ¾­Í¨¹ýÊ¹ÓÃ»òÕß²»Ê¹ÓÃ CONFIG_LBDAF ²âÊÔ¡£
+
+15£ºËùÓÐµÄcodepathsÒÑ¾­ÐÐÊ¹ËùÓÐlockdepÆôÓÃ¹¦ÄÜ¡£
+
+16£ºËùÓÐµÄ/proc¼ÇÂ¼¸üÐÂ¶¼Òª×÷³ÉÎÄ¼þ·ÅÔÚDocumentation/Ä¿Â¼ÏÂ¡£
+
+17£ºËùÓÐµÄÄÚºËÆô¶¯²ÎÊý¸üÐÂ¶¼±»¼ÇÂ¼µ½Documentation/kernel-parameters.txtÎÄ¼þÖÐ¡£
+
+18£ºËùÓÐµÄÄ£¿é²ÎÊý¸üÐÂ¶¼ÓÃMODULE_PARM_DESC()¼ÇÂ¼¡£
+
+19£ºËùÓÐµÄÓÃ»§¿Õ¼ä½Ó¿Ú¸üÐÂ¶¼±»¼ÇÂ¼µ½Documentation/ABI/¡£²é¿´Documentation/ABI/README
+    ¿ÉÒÔ»ñµÃ¸ü¶àµÄÐÅÏ¢¡£¸Ä±äÓÃ»§¿Õ¼ä½Ó¿ÚµÄ²¹¶¡Ó¦¸Ã±»ÓÊ¼þ³­ËÍ¸ølinux-api@vger.kernel.org¡£
+
+20£º¼ì²éËüÊÇ²»ÊÇ¶¼Í¨¹ý`make headers_check'¡£
+
+21£ºÒÑ¾­Í¨¹ýÖÁÉÙÒýÈëslabºÍpage-allocationÊ§°Ü¼ì²é¡£²é¿´Documentation/fault-injection/¡£
+
+22£ºÐÂ¼ÓÈëµÄÔ´ÂëÒÑ¾­Í¨¹ý`gcc -W'£¨Ê¹ÓÃ"make EXTRA_CFLAGS=-W"£©±àÒë¡£ÕâÑù½«²úÉúºÜ¶à·³ÄÕ£¬
+    µ«ÊÇ¶ÔÓÚÑ°ÕÒÂ©¶´ºÜÓÐÒæ´¦£¬ÀýÈç:"warning: comparison between signed and unsigned"¡£
+
+23£ºµ±Ëü±»ºÏ²¢µ½-mm²¹¶¡¼¯ºóÔÙ²âÊÔ£¬ÓÃÀ´È·¶¨ËüÊÇ·ñ»¹ºÍ²¹¶¡¶ÓÁÐÖÐµÄÆäËû²¹¶¡Ò»Æð¹¤×÷ÒÔ¼°ÔÚVM£¬VFS
+    ºÍÆäËû×ÓÏµÍ³ÖÐ¸÷¸ö±ä»¯¡£
+
+24£ºËùÓÐµÄÄÚ´æÆÁÕÏ{e.g., barrier(), rmb(), wmb()}ÐèÒªÔÚÔ´´úÂëÖÐµÄÒ»¸ö×¢ÊÍÀ´½âÊÍËûÃÇ¶¼ÊÇ¸ÉÊ²Ã´µÄ
+    ÒÔ¼°Ô­Òò¡£
+
+25£ºÈç¹ûÓÐÈÎºÎÊäÈëÊä³ö¿ØÖÆµÄ²¹¶¡±»Ìí¼Ó£¬Ò²Òª¸üÐÂDocumentation/ioctl/ioctl-number.txt¡£
+
+26£ºÈç¹ûÄãµÄ¸ü¸Ä´úÂëÒÀ¿¿»òÕßÊ¹ÓÃÈÎºÎµÄÄÚºËAPIs»òÕßÓëÏÂÃæµÄkconfig·ûºÅÓÐ¹ØÏµµÄ¹¦ÄÜ£¬Äã¾ÍÒª
+    Ê¹ÓÃÏà¹ØµÄkconfig·ûºÅ¹Ø±Õ£¬ and/or =m£¨Èç¹ûÑ¡ÏîÌá¹©£©[ÔÚÍ¬Ò»Ê±¼ä²»ÊÇËùÓÃµÄ¶¼ÆôÓÃ£¬½ö½ö¸÷¸ö»òÕß×ÔÓÉ
+    ×éºÏËûÃÇ]£º
+
+    CONFIG_SMP, CONFIG_SYSFS, CONFIG_PROC_FS, CONFIG_INPUT, CONFIG_PCI,
+    CONFIG_BLOCK, CONFIG_PM, CONFIG_HOTPLUG, CONFIG_MAGIC_SYSRQ,
+    CONFIG_NET, CONFIG_INET=n (ºóÒ»¸öÊ¹ÓÃ CONFIG_NET=y)
diff -druN linux-libre-2.6.38-gnu/Documentation/zh_CN/SubmittingPatches linux-libre-2.6.39-gnu/Documentation/zh_CN/SubmittingPatches
--- linux-libre-2.6.38-gnu/Documentation/zh_CN/SubmittingPatches	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/Documentation/zh_CN/SubmittingPatches	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,7 @@
 
 å°†æ”¹åŠ¨æ‹†åˆ†ï¼Œé€»è¾‘ç±»ä¼¼çš„æ”¾åˆ°å�Œä¸€ä¸ªè¡¥ä¸�æ–‡ä»¶é‡Œã€‚
 
-ä¾‹å¦‚ï¼Œå¦‚æžœä½ çš„æ”¹åŠ¨é‡Œå�Œæ—¶æœ‰bugä¿®æ­£å’Œæ€§èƒ½ä¼˜åŒ–ï¼Œé‚£ä¹ˆæŠŠè¿™äº›æ”¹åŠ¨æ‰�åˆ†åˆ°ä¸¤ä¸ªæˆ–
+ä¾‹å¦‚ï¼Œå¦‚æžœä½ çš„æ”¹åŠ¨é‡Œå�Œæ—¶æœ‰bugä¿®æ­£å’Œæ€§èƒ½ä¼˜åŒ–ï¼Œé‚£ä¹ˆæŠŠè¿™äº›æ”¹åŠ¨æ‹†åˆ†åˆ°ä¸¤ä¸ªæˆ–
 è€…æ›´å¤šçš„è¡¥ä¸�æ–‡ä»¶ä¸­ã€‚å¦‚æžœä½ çš„æ”¹åŠ¨åŒ…å�«å¯¹APIçš„ä¿®æ”¹ï¼Œå¹¶ä¸”ä¿®æ”¹äº†é©±åŠ¨ç¨‹åº�æ�¥é€‚
 åº”è¿™äº›æ–°çš„APIï¼Œé‚£ä¹ˆæŠŠè¿™äº›ä¿®æ”¹åˆ†æˆ�ä¸¤ä¸ªè¡¥ä¸�ã€‚
 
@@ -230,7 +230,7 @@
 äº›åŽŸå› ï¼Œä¿®æ­£é”™è¯¯ï¼Œé‡�æ–°æ��äº¤æ›´æ–°å�Žçš„æ”¹åŠ¨ï¼Œæ˜¯ä½ è‡ªå·±çš„å·¥ä½œã€‚
 
 Linusä¸�ç»™å‡ºä»»ä½•è¯„è®ºå°±â€œä¸¢å¼ƒâ€�ä½ çš„è¡¥ä¸�æ˜¯å¸¸è§�çš„äº‹æƒ…ã€‚åœ¨ç³»ç»Ÿä¸­è¿™æ ·çš„äº‹æƒ…å¾ˆ
-å¹³å¸¸ã€‚å¦‚æžœä»–æ²¡æœ‰æŽ¥å�—ä½ çš„è¡¥ä¸�ï¼Œä¹Ÿè®¸æ˜¯ç”±äºŽä»¥ä¸‹åŽŸæœ¬ï¼š
+å¹³å¸¸ã€‚å¦‚æžœä»–æ²¡æœ‰æŽ¥å�—ä½ çš„è¡¥ä¸�ï¼Œä¹Ÿè®¸æ˜¯ç”±äºŽä»¥ä¸‹åŽŸå› ï¼š
 * ä½ çš„è¡¥ä¸�ä¸�èƒ½åœ¨æœ€æ–°ç‰ˆæœ¬çš„å†…æ ¸ä¸Šå¹²å‡€çš„æ‰“ä¸Šã€‚
 * ä½ çš„è¡¥ä¸�åœ¨ linux-kernel é‚®ä»¶åˆ—è¡¨ä¸­æ²¡æœ‰å¾—åˆ°å……åˆ†çš„è®¨è®ºã€‚
 * é£Žæ ¼é—®é¢˜ï¼ˆå�‚ç…§ç¬¬2å°�èŠ‚ï¼‰
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/acdispat.h linux-libre-2.6.39-gnu/drivers/acpi/acpica/acdispat.h
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/acdispat.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/acdispat.h	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
 #define NAMEOF_ARG_NTE      "__A0"
 
 /*
- * dsopcode - support for late evaluation
+ * dsargs - execution of dynamic arguments for static objects
  */
 acpi_status
 acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc);
@@ -62,6 +62,20 @@
 
 acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc);
 
+/*
+ * dscontrol - support for execution control opcodes
+ */
+acpi_status
+acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
+			      union acpi_parse_object *op);
+
+acpi_status
+acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
+			    union acpi_parse_object *op);
+
+/*
+ * dsopcode - support for late operand evaluation
+ */
 acpi_status
 acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,
 				   union acpi_parse_object *op);
@@ -86,17 +100,6 @@
 acpi_status acpi_ds_initialize_region(acpi_handle obj_handle);
 
 /*
- * dsctrl - Parser/Interpreter interface, control stack routines
- */
-acpi_status
-acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
-			      union acpi_parse_object *op);
-
-acpi_status
-acpi_ds_exec_end_control_op(struct acpi_walk_state *walk_state,
-			    union acpi_parse_object *op);
-
-/*
  * dsexec - Parser/Interpreter interface, method execution callbacks
  */
 acpi_status
@@ -136,23 +139,26 @@
 			   struct acpi_walk_state *walk_state);
 
 /*
- * dsload - Parser/Interpreter interface, namespace load callbacks
+ * dsload - Parser/Interpreter interface, pass 1 namespace load callbacks
  */
 acpi_status
+acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
+
+acpi_status
 acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
 		       union acpi_parse_object **out_op);
 
 acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state);
 
+/*
+ * dsload - Parser/Interpreter interface, pass 2 namespace load callbacks
+ */
 acpi_status
 acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
 		       union acpi_parse_object **out_op);
 
 acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state);
 
-acpi_status
-acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number);
-
 /*
  * dsmthdat - method data (locals/args)
  */
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/acglobal.h linux-libre-2.6.39-gnu/drivers/acpi/acpica/acglobal.h
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/acglobal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/acglobal.h	2011-05-19 00:06:34.000000000 -0400
@@ -273,6 +273,10 @@
 ACPI_EXTERN u8 acpi_gbl_last_owner_id_index;
 ACPI_EXTERN u8 acpi_gbl_next_owner_id_offset;
 
+/* Initialization sequencing */
+
+ACPI_EXTERN u8 acpi_gbl_reg_methods_executed;
+
 /* Misc */
 
 ACPI_EXTERN u32 acpi_gbl_original_mode;
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/aclocal.h linux-libre-2.6.39-gnu/drivers/acpi/acpica/aclocal.h
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/aclocal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/aclocal.h	2011-05-19 00:06:34.000000000 -0400
@@ -89,25 +89,6 @@
 #define ACPI_MAX_MUTEX                  7
 #define ACPI_NUM_MUTEX                  ACPI_MAX_MUTEX+1
 
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-#ifdef DEFINE_ACPI_GLOBALS
-
-/* Debug names for the mutexes above */
-
-static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
-	"ACPI_MTX_Interpreter",
-	"ACPI_MTX_Namespace",
-	"ACPI_MTX_Tables",
-	"ACPI_MTX_Events",
-	"ACPI_MTX_Caches",
-	"ACPI_MTX_Memory",
-	"ACPI_MTX_CommandComplete",
-	"ACPI_MTX_CommandReady"
-};
-
-#endif
-#endif
-
 /* Lock structure for reader/writer interfaces */
 
 struct acpi_rw_lock {
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/dsargs.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/dsargs.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/dsargs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/dsargs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,391 @@
+/******************************************************************************
+ *
+ * Module Name: dsargs - Support for execution of dynamic arguments for static
+ *                       objects (regions, fields, buffer fields, etc.)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, Intel Corp.
+ * 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
+ *    substantially 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 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 <acpi/acpi.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+ACPI_MODULE_NAME("dsargs")
+
+/* Local prototypes */
+static acpi_status
+acpi_ds_execute_arguments(struct acpi_namespace_node *node,
+			  struct acpi_namespace_node *scope_node,
+			  u32 aml_length, u8 *aml_start);
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_execute_arguments
+ *
+ * PARAMETERS:  Node                - Object NS node
+ *              scope_node          - Parent NS node
+ *              aml_length          - Length of executable AML
+ *              aml_start           - Pointer to the AML
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Late (deferred) execution of region or field arguments
+ *
+ ******************************************************************************/
+
+static acpi_status
+acpi_ds_execute_arguments(struct acpi_namespace_node *node,
+			  struct acpi_namespace_node *scope_node,
+			  u32 aml_length, u8 *aml_start)
+{
+	acpi_status status;
+	union acpi_parse_object *op;
+	struct acpi_walk_state *walk_state;
+
+	ACPI_FUNCTION_TRACE(ds_execute_arguments);
+
+	/* Allocate a new parser op to be the root of the parsed tree */
+
+	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
+	if (!op) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	/* Save the Node for use in acpi_ps_parse_aml */
+
+	op->common.node = scope_node;
+
+	/* Create and initialize a new parser state */
+
+	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
+	if (!walk_state) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
+
+	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
+				       aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
+	if (ACPI_FAILURE(status)) {
+		acpi_ds_delete_walk_state(walk_state);
+		goto cleanup;
+	}
+
+	/* Mark this parse as a deferred opcode */
+
+	walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
+	walk_state->deferred_node = node;
+
+	/* Pass1: Parse the entire declaration */
+
+	status = acpi_ps_parse_aml(walk_state);
+	if (ACPI_FAILURE(status)) {
+		goto cleanup;
+	}
+
+	/* Get and init the Op created above */
+
+	op->common.node = node;
+	acpi_ps_delete_parse_tree(op);
+
+	/* Evaluate the deferred arguments */
+
+	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
+	if (!op) {
+		return_ACPI_STATUS(AE_NO_MEMORY);
+	}
+
+	op->common.node = scope_node;
+
+	/* Create and initialize a new parser state */
+
+	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
+	if (!walk_state) {
+		status = AE_NO_MEMORY;
+		goto cleanup;
+	}
+
+	/* Execute the opcode and arguments */
+
+	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
+				       aml_length, NULL, ACPI_IMODE_EXECUTE);
+	if (ACPI_FAILURE(status)) {
+		acpi_ds_delete_walk_state(walk_state);
+		goto cleanup;
+	}
+
+	/* Mark this execution as a deferred opcode */
+
+	walk_state->deferred_node = node;
+	status = acpi_ps_parse_aml(walk_state);
+
+      cleanup:
+	acpi_ps_delete_parse_tree(op);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_get_buffer_field_arguments
+ *
+ * PARAMETERS:  obj_desc        - A valid buffer_field object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
+ *              evaluation of these field attributes.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
+{
+	union acpi_operand_object *extra_desc;
+	struct acpi_namespace_node *node;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
+
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/* Get the AML pointer (method object) and buffer_field node */
+
+	extra_desc = acpi_ns_get_secondary_object(obj_desc);
+	node = obj_desc->buffer_field.node;
+
+	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname(ACPI_TYPE_BUFFER_FIELD,
+						      node, NULL));
+
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
+			  acpi_ut_get_node_name(node)));
+
+	/* Execute the AML code for the term_arg arguments */
+
+	status = acpi_ds_execute_arguments(node, node->parent,
+					   extra_desc->extra.aml_length,
+					   extra_desc->extra.aml_start);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_get_bank_field_arguments
+ *
+ * PARAMETERS:  obj_desc        - A valid bank_field object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get bank_field bank_value. This implements the late
+ *              evaluation of these field attributes.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
+{
+	union acpi_operand_object *extra_desc;
+	struct acpi_namespace_node *node;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
+
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/* Get the AML pointer (method object) and bank_field node */
+
+	extra_desc = acpi_ns_get_secondary_object(obj_desc);
+	node = obj_desc->bank_field.node;
+
+	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+			(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
+
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
+			  acpi_ut_get_node_name(node)));
+
+	/* Execute the AML code for the term_arg arguments */
+
+	status = acpi_ds_execute_arguments(node, node->parent,
+					   extra_desc->extra.aml_length,
+					   extra_desc->extra.aml_start);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_get_buffer_arguments
+ *
+ * PARAMETERS:  obj_desc        - A valid Buffer object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get Buffer length and initializer byte list. This implements
+ *              the late evaluation of these attributes.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
+{
+	struct acpi_namespace_node *node;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
+
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/* Get the Buffer node */
+
+	node = obj_desc->buffer.node;
+	if (!node) {
+		ACPI_ERROR((AE_INFO,
+			    "No pointer back to namespace node in buffer object %p",
+			    obj_desc));
+		return_ACPI_STATUS(AE_AML_INTERNAL);
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
+
+	/* Execute the AML code for the term_arg arguments */
+
+	status = acpi_ds_execute_arguments(node, node,
+					   obj_desc->buffer.aml_length,
+					   obj_desc->buffer.aml_start);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_get_package_arguments
+ *
+ * PARAMETERS:  obj_desc        - A valid Package object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get Package length and initializer byte list. This implements
+ *              the late evaluation of these attributes.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
+{
+	struct acpi_namespace_node *node;
+	acpi_status status;
+
+	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
+
+	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	/* Get the Package node */
+
+	node = obj_desc->package.node;
+	if (!node) {
+		ACPI_ERROR((AE_INFO,
+			    "No pointer back to namespace node in package %p",
+			    obj_desc));
+		return_ACPI_STATUS(AE_AML_INTERNAL);
+	}
+
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
+
+	/* Execute the AML code for the term_arg arguments */
+
+	status = acpi_ds_execute_arguments(node, node,
+					   obj_desc->package.aml_length,
+					   obj_desc->package.aml_start);
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_get_region_arguments
+ *
+ * PARAMETERS:  obj_desc        - A valid region object
+ *
+ * RETURN:      Status.
+ *
+ * DESCRIPTION: Get region address and length. This implements the late
+ *              evaluation of these region attributes.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
+{
+	struct acpi_namespace_node *node;
+	acpi_status status;
+	union acpi_operand_object *extra_desc;
+
+	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
+
+	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	extra_desc = acpi_ns_get_secondary_object(obj_desc);
+	if (!extra_desc) {
+		return_ACPI_STATUS(AE_NOT_EXIST);
+	}
+
+	/* Get the Region node */
+
+	node = obj_desc->region.node;
+
+	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
+			(ACPI_TYPE_REGION, node, NULL));
+
+	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
+			  acpi_ut_get_node_name(node),
+			  extra_desc->extra.aml_start));
+
+	/* Execute the argument AML */
+
+	status = acpi_ds_execute_arguments(node, node->parent,
+					   extra_desc->extra.aml_length,
+					   extra_desc->extra.aml_start);
+	return_ACPI_STATUS(status);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/dscontrol.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/dscontrol.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/dscontrol.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/dscontrol.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,410 @@
+/******************************************************************************
+ *
+ * Module Name: dscontrol - Support for execution control opcodes -
+ *                          if/else/while/return
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, Intel Corp.
+ * 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
+ *    substantially 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 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 <acpi/acpi.h>
+#include "accommon.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+ACPI_MODULE_NAME("dscontrol")
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_exec_begin_control_op
+ *
+ * PARAMETERS:  walk_list       - The list that owns the walk stack
+ *              Op              - The control Op
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Handles all control ops encountered during control method
+ *              execution.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
+			      union acpi_parse_object *op)
+{
+	acpi_status status = AE_OK;
+	union acpi_generic_state *control_state;
+
+	ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
+
+	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n",
+			  op, op->common.aml_opcode, walk_state));
+
+	switch (op->common.aml_opcode) {
+	case AML_WHILE_OP:
+
+		/*
+		 * If this is an additional iteration of a while loop, continue.
+		 * There is no need to allocate a new control state.
+		 */
+		if (walk_state->control_state) {
+			if (walk_state->control_state->control.
+			    aml_predicate_start ==
+			    (walk_state->parser_state.aml - 1)) {
+
+				/* Reset the state to start-of-loop */
+
+				walk_state->control_state->common.state =
+				    ACPI_CONTROL_CONDITIONAL_EXECUTING;
+				break;
+			}
+		}
+
+		/*lint -fallthrough */
+
+	case AML_IF_OP:
+
+		/*
+		 * IF/WHILE: Create a new control state to manage these
+		 * constructs. We need to manage these as a stack, in order
+		 * to handle nesting.
+		 */
+		control_state = acpi_ut_create_control_state();
+		if (!control_state) {
+			status = AE_NO_MEMORY;
+			break;
+		}
+		/*
+		 * Save a pointer to the predicate for multiple executions
+		 * of a loop
+		 */
+		control_state->control.aml_predicate_start =
+		    walk_state->parser_state.aml - 1;
+		control_state->control.package_end =
+		    walk_state->parser_state.pkg_end;
+		control_state->control.opcode = op->common.aml_opcode;
+
+		/* Push the control state on this walk's control stack */
+
+		acpi_ut_push_generic_state(&walk_state->control_state,
+					   control_state);
+		break;
+
+	case AML_ELSE_OP:
+
+		/* Predicate is in the state object */
+		/* If predicate is true, the IF was executed, ignore ELSE part */
+
+		if (walk_state->last_predicate) {
+			status = AE_CTRL_TRUE;
+		}
+
+		break;
+
+	case AML_RETURN_OP:
+
+		break;
+
+	default:
+		break;
+	}
+
+	return (status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_exec_end_control_op
+ *
+ * PARAMETERS:  walk_list       - The list that owns the walk stack
+ *              Op              - The control Op
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Handles all control ops encountered during control method
+ *              execution.
+ *
+ ******************************************************************************/
+
+acpi_status
+acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
+			    union acpi_parse_object * op)
+{
+	acpi_status status = AE_OK;
+	union acpi_generic_state *control_state;
+
+	ACPI_FUNCTION_NAME(ds_exec_end_control_op);
+
+	switch (op->common.aml_opcode) {
+	case AML_IF_OP:
+
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
+
+		/*
+		 * Save the result of the predicate in case there is an
+		 * ELSE to come
+		 */
+		walk_state->last_predicate =
+		    (u8)walk_state->control_state->common.value;
+
+		/*
+		 * Pop the control state that was created at the start
+		 * of the IF and free it
+		 */
+		control_state =
+		    acpi_ut_pop_generic_state(&walk_state->control_state);
+		acpi_ut_delete_generic_state(control_state);
+		break;
+
+	case AML_ELSE_OP:
+
+		break;
+
+	case AML_WHILE_OP:
+
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
+
+		control_state = walk_state->control_state;
+		if (control_state->common.value) {
+
+			/* Predicate was true, the body of the loop was just executed */
+
+			/*
+			 * This loop counter mechanism allows the interpreter to escape
+			 * possibly infinite loops. This can occur in poorly written AML
+			 * when the hardware does not respond within a while loop and the
+			 * loop does not implement a timeout.
+			 */
+			control_state->control.loop_count++;
+			if (control_state->control.loop_count >
+			    ACPI_MAX_LOOP_ITERATIONS) {
+				status = AE_AML_INFINITE_LOOP;
+				break;
+			}
+
+			/*
+			 * Go back and evaluate the predicate and maybe execute the loop
+			 * another time
+			 */
+			status = AE_CTRL_PENDING;
+			walk_state->aml_last_while =
+			    control_state->control.aml_predicate_start;
+			break;
+		}
+
+		/* Predicate was false, terminate this while loop */
+
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+				  "[WHILE_OP] termination! Op=%p\n", op));
+
+		/* Pop this control state and free it */
+
+		control_state =
+		    acpi_ut_pop_generic_state(&walk_state->control_state);
+		acpi_ut_delete_generic_state(control_state);
+		break;
+
+	case AML_RETURN_OP:
+
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+				  "[RETURN_OP] Op=%p Arg=%p\n", op,
+				  op->common.value.arg));
+
+		/*
+		 * One optional operand -- the return value
+		 * It can be either an immediate operand or a result that
+		 * has been bubbled up the tree
+		 */
+		if (op->common.value.arg) {
+
+			/* Since we have a real Return(), delete any implicit return */
+
+			acpi_ds_clear_implicit_return(walk_state);
+
+			/* Return statement has an immediate operand */
+
+			status =
+			    acpi_ds_create_operands(walk_state,
+						    op->common.value.arg);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+
+			/*
+			 * If value being returned is a Reference (such as
+			 * an arg or local), resolve it now because it may
+			 * cease to exist at the end of the method.
+			 */
+			status =
+			    acpi_ex_resolve_to_value(&walk_state->operands[0],
+						     walk_state);
+			if (ACPI_FAILURE(status)) {
+				return (status);
+			}
+
+			/*
+			 * Get the return value and save as the last result
+			 * value.  This is the only place where walk_state->return_desc
+			 * is set to anything other than zero!
+			 */
+			walk_state->return_desc = walk_state->operands[0];
+		} else if (walk_state->result_count) {
+
+			/* Since we have a real Return(), delete any implicit return */
+
+			acpi_ds_clear_implicit_return(walk_state);
+
+			/*
+			 * The return value has come from a previous calculation.
+			 *
+			 * If value being returned is a Reference (such as
+			 * an arg or local), resolve it now because it may
+			 * cease to exist at the end of the method.
+			 *
+			 * Allow references created by the Index operator to return
+			 * unchanged.
+			 */
+			if ((ACPI_GET_DESCRIPTOR_TYPE
+			     (walk_state->results->results.obj_desc[0]) ==
+			     ACPI_DESC_TYPE_OPERAND)
+			    && ((walk_state->results->results.obj_desc[0])->
+				common.type == ACPI_TYPE_LOCAL_REFERENCE)
+			    && ((walk_state->results->results.obj_desc[0])->
+				reference.class != ACPI_REFCLASS_INDEX)) {
+				status =
+				    acpi_ex_resolve_to_value(&walk_state->
+							     results->results.
+							     obj_desc[0],
+							     walk_state);
+				if (ACPI_FAILURE(status)) {
+					return (status);
+				}
+			}
+
+			walk_state->return_desc =
+			    walk_state->results->results.obj_desc[0];
+		} else {
+			/* No return operand */
+
+			if (walk_state->num_operands) {
+				acpi_ut_remove_reference(walk_state->
+							 operands[0]);
+			}
+
+			walk_state->operands[0] = NULL;
+			walk_state->num_operands = 0;
+			walk_state->return_desc = NULL;
+		}
+
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+				  "Completed RETURN_OP State=%p, RetVal=%p\n",
+				  walk_state, walk_state->return_desc));
+
+		/* End the control method execution right now */
+
+		status = AE_CTRL_TERMINATE;
+		break;
+
+	case AML_NOOP_OP:
+
+		/* Just do nothing! */
+		break;
+
+	case AML_BREAK_POINT_OP:
+
+		/*
+		 * 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"));
+
+		/* 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:
+	case AML_CONTINUE_OP:	/* ACPI 2.0 */
+
+		/* Pop and delete control states until we find a while */
+
+		while (walk_state->control_state &&
+		       (walk_state->control_state->control.opcode !=
+			AML_WHILE_OP)) {
+			control_state =
+			    acpi_ut_pop_generic_state(&walk_state->
+						      control_state);
+			acpi_ut_delete_generic_state(control_state);
+		}
+
+		/* No while found? */
+
+		if (!walk_state->control_state) {
+			return (AE_AML_NO_WHILE);
+		}
+
+		/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
+
+		walk_state->aml_last_while =
+		    walk_state->control_state->control.package_end;
+
+		/* Return status depending on opcode */
+
+		if (op->common.aml_opcode == AML_BREAK_OP) {
+			status = AE_CTRL_BREAK;
+		} else {
+			status = AE_CTRL_CONTINUE;
+		}
+		break;
+
+	default:
+
+		ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p",
+			    op->common.aml_opcode, op));
+
+		status = AE_AML_BAD_OPCODE;
+		break;
+	}
+
+	return (status);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/dsopcode.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/dsopcode.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/dsopcode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/dsopcode.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,6 @@
 /******************************************************************************
  *
- * Module Name: dsopcode - Dispatcher Op Region support and handling of
- *                         "control" opcodes
+ * Module Name: dsopcode - Dispatcher suport for regions and fields
  *
  *****************************************************************************/
 
@@ -57,11 +56,6 @@
 
 /* Local prototypes */
 static acpi_status
-acpi_ds_execute_arguments(struct acpi_namespace_node *node,
-			  struct acpi_namespace_node *scope_node,
-			  u32 aml_length, u8 * aml_start);
-
-static acpi_status
 acpi_ds_init_buffer_field(u16 aml_opcode,
 			  union acpi_operand_object *obj_desc,
 			  union acpi_operand_object *buffer_desc,
@@ -71,361 +65,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ds_execute_arguments
- *
- * PARAMETERS:  Node                - Object NS node
- *              scope_node          - Parent NS node
- *              aml_length          - Length of executable AML
- *              aml_start           - Pointer to the AML
- *
- * RETURN:      Status.
- *
- * DESCRIPTION: Late (deferred) execution of region or field arguments
- *
- ******************************************************************************/
-
-static acpi_status
-acpi_ds_execute_arguments(struct acpi_namespace_node *node,
-			  struct acpi_namespace_node *scope_node,
-			  u32 aml_length, u8 * aml_start)
-{
-	acpi_status status;
-	union acpi_parse_object *op;
-	struct acpi_walk_state *walk_state;
-
-	ACPI_FUNCTION_TRACE(ds_execute_arguments);
-
-	/*
-	 * Allocate a new parser op to be the root of the parsed tree
-	 */
-	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
-	if (!op) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
-
-	/* Save the Node for use in acpi_ps_parse_aml */
-
-	op->common.node = scope_node;
-
-	/* Create and initialize a new parser state */
-
-	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
-	if (!walk_state) {
-		status = AE_NO_MEMORY;
-		goto cleanup;
-	}
-
-	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
-				       aml_length, NULL, ACPI_IMODE_LOAD_PASS1);
-	if (ACPI_FAILURE(status)) {
-		acpi_ds_delete_walk_state(walk_state);
-		goto cleanup;
-	}
-
-	/* Mark this parse as a deferred opcode */
-
-	walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP;
-	walk_state->deferred_node = node;
-
-	/* Pass1: Parse the entire declaration */
-
-	status = acpi_ps_parse_aml(walk_state);
-	if (ACPI_FAILURE(status)) {
-		goto cleanup;
-	}
-
-	/* Get and init the Op created above */
-
-	op->common.node = node;
-	acpi_ps_delete_parse_tree(op);
-
-	/* Evaluate the deferred arguments */
-
-	op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP);
-	if (!op) {
-		return_ACPI_STATUS(AE_NO_MEMORY);
-	}
-
-	op->common.node = scope_node;
-
-	/* Create and initialize a new parser state */
-
-	walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL);
-	if (!walk_state) {
-		status = AE_NO_MEMORY;
-		goto cleanup;
-	}
-
-	/* Execute the opcode and arguments */
-
-	status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start,
-				       aml_length, NULL, ACPI_IMODE_EXECUTE);
-	if (ACPI_FAILURE(status)) {
-		acpi_ds_delete_walk_state(walk_state);
-		goto cleanup;
-	}
-
-	/* Mark this execution as a deferred opcode */
-
-	walk_state->deferred_node = node;
-	status = acpi_ps_parse_aml(walk_state);
-
-      cleanup:
-	acpi_ps_delete_parse_tree(op);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_get_buffer_field_arguments
- *
- * PARAMETERS:  obj_desc        - A valid buffer_field object
- *
- * RETURN:      Status.
- *
- * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late
- *              evaluation of these field attributes.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc)
-{
-	union acpi_operand_object *extra_desc;
-	struct acpi_namespace_node *node;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc);
-
-	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	/* Get the AML pointer (method object) and buffer_field node */
-
-	extra_desc = acpi_ns_get_secondary_object(obj_desc);
-	node = obj_desc->buffer_field.node;
-
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
-			(ACPI_TYPE_BUFFER_FIELD, node, NULL));
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n",
-			  acpi_ut_get_node_name(node)));
-
-	/* Execute the AML code for the term_arg arguments */
-
-	status = acpi_ds_execute_arguments(node, node->parent,
-					   extra_desc->extra.aml_length,
-					   extra_desc->extra.aml_start);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_get_bank_field_arguments
- *
- * PARAMETERS:  obj_desc        - A valid bank_field object
- *
- * RETURN:      Status.
- *
- * DESCRIPTION: Get bank_field bank_value. This implements the late
- *              evaluation of these field attributes.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc)
-{
-	union acpi_operand_object *extra_desc;
-	struct acpi_namespace_node *node;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc);
-
-	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	/* Get the AML pointer (method object) and bank_field node */
-
-	extra_desc = acpi_ns_get_secondary_object(obj_desc);
-	node = obj_desc->bank_field.node;
-
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
-			(ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL));
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n",
-			  acpi_ut_get_node_name(node)));
-
-	/* Execute the AML code for the term_arg arguments */
-
-	status = acpi_ds_execute_arguments(node, node->parent,
-					   extra_desc->extra.aml_length,
-					   extra_desc->extra.aml_start);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_get_buffer_arguments
- *
- * PARAMETERS:  obj_desc        - A valid Buffer object
- *
- * RETURN:      Status.
- *
- * DESCRIPTION: Get Buffer length and initializer byte list.  This implements
- *              the late evaluation of these attributes.
- *
- ******************************************************************************/
-
-acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc)
-{
-	struct acpi_namespace_node *node;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc);
-
-	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	/* Get the Buffer node */
-
-	node = obj_desc->buffer.node;
-	if (!node) {
-		ACPI_ERROR((AE_INFO,
-			    "No pointer back to namespace node in buffer object %p",
-			    obj_desc));
-		return_ACPI_STATUS(AE_AML_INTERNAL);
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n"));
-
-	/* Execute the AML code for the term_arg arguments */
-
-	status = acpi_ds_execute_arguments(node, node,
-					   obj_desc->buffer.aml_length,
-					   obj_desc->buffer.aml_start);
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_get_package_arguments
- *
- * PARAMETERS:  obj_desc        - A valid Package object
- *
- * RETURN:      Status.
- *
- * DESCRIPTION: Get Package length and initializer byte list.  This implements
- *              the late evaluation of these attributes.
- *
- ******************************************************************************/
-
-acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc)
-{
-	struct acpi_namespace_node *node;
-	acpi_status status;
-
-	ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc);
-
-	if (obj_desc->common.flags & AOPOBJ_DATA_VALID) {
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	/* Get the Package node */
-
-	node = obj_desc->package.node;
-	if (!node) {
-		ACPI_ERROR((AE_INFO,
-			    "No pointer back to namespace node in package %p",
-			    obj_desc));
-		return_ACPI_STATUS(AE_AML_INTERNAL);
-	}
-
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n"));
-
-	/* Execute the AML code for the term_arg arguments */
-
-	status = acpi_ds_execute_arguments(node, node,
-					   obj_desc->package.aml_length,
-					   obj_desc->package.aml_start);
-	return_ACPI_STATUS(status);
-}
-
-/*****************************************************************************
- *
- * FUNCTION:    acpi_ds_get_region_arguments
- *
- * PARAMETERS:  obj_desc        - A valid region object
- *
- * RETURN:      Status.
- *
- * DESCRIPTION: Get region address and length.  This implements the late
- *              evaluation of these region attributes.
- *
- ****************************************************************************/
-
-acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc)
-{
-	struct acpi_namespace_node *node;
-	acpi_status status;
-	union acpi_operand_object *extra_desc;
-
-	ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc);
-
-	if (obj_desc->region.flags & AOPOBJ_DATA_VALID) {
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	extra_desc = acpi_ns_get_secondary_object(obj_desc);
-	if (!extra_desc) {
-		return_ACPI_STATUS(AE_NOT_EXIST);
-	}
-
-	/* Get the Region node */
-
-	node = obj_desc->region.node;
-
-	ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname
-			(ACPI_TYPE_REGION, node, NULL));
-
-	ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n",
-			  acpi_ut_get_node_name(node),
-			  extra_desc->extra.aml_start));
-
-	/* Execute the argument AML */
-
-	status = acpi_ds_execute_arguments(node, node->parent,
-					   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);
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ds_initialize_region
  *
  * PARAMETERS:  obj_handle      - Region namespace node
@@ -826,8 +465,9 @@
  *
  * RETURN:      Status
  *
- * DESCRIPTION: Get region address and length
- *              Called from acpi_ds_exec_end_op during data_table_region parse tree walk
+ * DESCRIPTION: Get region address and length.
+ *              Called from acpi_ds_exec_end_op during data_table_region parse
+ *              tree walk.
  *
  ******************************************************************************/
 
@@ -1114,360 +754,3 @@
 	acpi_ut_remove_reference(operand_desc);
 	return_ACPI_STATUS(status);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_exec_begin_control_op
- *
- * PARAMETERS:  walk_list       - The list that owns the walk stack
- *              Op              - The control Op
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Handles all control ops encountered during control method
- *              execution.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state,
-			      union acpi_parse_object *op)
-{
-	acpi_status status = AE_OK;
-	union acpi_generic_state *control_state;
-
-	ACPI_FUNCTION_NAME(ds_exec_begin_control_op);
-
-	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op,
-			  op->common.aml_opcode, walk_state));
-
-	switch (op->common.aml_opcode) {
-	case AML_WHILE_OP:
-
-		/*
-		 * If this is an additional iteration of a while loop, continue.
-		 * There is no need to allocate a new control state.
-		 */
-		if (walk_state->control_state) {
-			if (walk_state->control_state->control.aml_predicate_start
-				== (walk_state->parser_state.aml - 1)) {
-
-				/* Reset the state to start-of-loop */
-
-				walk_state->control_state->common.state =
-				    ACPI_CONTROL_CONDITIONAL_EXECUTING;
-				break;
-			}
-		}
-
-		/*lint -fallthrough */
-
-	case AML_IF_OP:
-
-		/*
-		 * IF/WHILE: Create a new control state to manage these
-		 * constructs. We need to manage these as a stack, in order
-		 * to handle nesting.
-		 */
-		control_state = acpi_ut_create_control_state();
-		if (!control_state) {
-			status = AE_NO_MEMORY;
-			break;
-		}
-		/*
-		 * Save a pointer to the predicate for multiple executions
-		 * of a loop
-		 */
-		control_state->control.aml_predicate_start =
-		    walk_state->parser_state.aml - 1;
-		control_state->control.package_end =
-		    walk_state->parser_state.pkg_end;
-		control_state->control.opcode = op->common.aml_opcode;
-
-		/* Push the control state on this walk's control stack */
-
-		acpi_ut_push_generic_state(&walk_state->control_state,
-					   control_state);
-		break;
-
-	case AML_ELSE_OP:
-
-		/* Predicate is in the state object */
-		/* If predicate is true, the IF was executed, ignore ELSE part */
-
-		if (walk_state->last_predicate) {
-			status = AE_CTRL_TRUE;
-		}
-
-		break;
-
-	case AML_RETURN_OP:
-
-		break;
-
-	default:
-		break;
-	}
-
-	return (status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_exec_end_control_op
- *
- * PARAMETERS:  walk_list       - The list that owns the walk stack
- *              Op              - The control Op
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Handles all control ops encountered during control method
- *              execution.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
-			    union acpi_parse_object * op)
-{
-	acpi_status status = AE_OK;
-	union acpi_generic_state *control_state;
-
-	ACPI_FUNCTION_NAME(ds_exec_end_control_op);
-
-	switch (op->common.aml_opcode) {
-	case AML_IF_OP:
-
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op));
-
-		/*
-		 * Save the result of the predicate in case there is an
-		 * ELSE to come
-		 */
-		walk_state->last_predicate =
-		    (u8) walk_state->control_state->common.value;
-
-		/*
-		 * Pop the control state that was created at the start
-		 * of the IF and free it
-		 */
-		control_state =
-		    acpi_ut_pop_generic_state(&walk_state->control_state);
-		acpi_ut_delete_generic_state(control_state);
-		break;
-
-	case AML_ELSE_OP:
-
-		break;
-
-	case AML_WHILE_OP:
-
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op));
-
-		control_state = walk_state->control_state;
-		if (control_state->common.value) {
-
-			/* Predicate was true, the body of the loop was just executed */
-
-			/*
-			 * This loop counter mechanism allows the interpreter to escape
-			 * possibly infinite loops. This can occur in poorly written AML
-			 * when the hardware does not respond within a while loop and the
-			 * loop does not implement a timeout.
-			 */
-			control_state->control.loop_count++;
-			if (control_state->control.loop_count >
-				ACPI_MAX_LOOP_ITERATIONS) {
-				status = AE_AML_INFINITE_LOOP;
-				break;
-			}
-
-			/*
-			 * Go back and evaluate the predicate and maybe execute the loop
-			 * another time
-			 */
-			status = AE_CTRL_PENDING;
-			walk_state->aml_last_while =
-			    control_state->control.aml_predicate_start;
-			break;
-		}
-
-		/* Predicate was false, terminate this while loop */
-
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "[WHILE_OP] termination! Op=%p\n", op));
-
-		/* Pop this control state and free it */
-
-		control_state =
-		    acpi_ut_pop_generic_state(&walk_state->control_state);
-		acpi_ut_delete_generic_state(control_state);
-		break;
-
-	case AML_RETURN_OP:
-
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "[RETURN_OP] Op=%p Arg=%p\n", op,
-				  op->common.value.arg));
-
-		/*
-		 * One optional operand -- the return value
-		 * It can be either an immediate operand or a result that
-		 * has been bubbled up the tree
-		 */
-		if (op->common.value.arg) {
-
-			/* Since we have a real Return(), delete any implicit return */
-
-			acpi_ds_clear_implicit_return(walk_state);
-
-			/* Return statement has an immediate operand */
-
-			status =
-			    acpi_ds_create_operands(walk_state,
-						    op->common.value.arg);
-			if (ACPI_FAILURE(status)) {
-				return (status);
-			}
-
-			/*
-			 * If value being returned is a Reference (such as
-			 * an arg or local), resolve it now because it may
-			 * cease to exist at the end of the method.
-			 */
-			status =
-			    acpi_ex_resolve_to_value(&walk_state->operands[0],
-						     walk_state);
-			if (ACPI_FAILURE(status)) {
-				return (status);
-			}
-
-			/*
-			 * Get the return value and save as the last result
-			 * value.  This is the only place where walk_state->return_desc
-			 * is set to anything other than zero!
-			 */
-			walk_state->return_desc = walk_state->operands[0];
-		} else if (walk_state->result_count) {
-
-			/* Since we have a real Return(), delete any implicit return */
-
-			acpi_ds_clear_implicit_return(walk_state);
-
-			/*
-			 * The return value has come from a previous calculation.
-			 *
-			 * If value being returned is a Reference (such as
-			 * an arg or local), resolve it now because it may
-			 * cease to exist at the end of the method.
-			 *
-			 * Allow references created by the Index operator to return unchanged.
-			 */
-			if ((ACPI_GET_DESCRIPTOR_TYPE
-			     (walk_state->results->results.obj_desc[0]) ==
-			     ACPI_DESC_TYPE_OPERAND)
-			    && ((walk_state->results->results.obj_desc[0])->
-				common.type == ACPI_TYPE_LOCAL_REFERENCE)
-			    && ((walk_state->results->results.obj_desc[0])->
-				reference.class != ACPI_REFCLASS_INDEX)) {
-				status =
-				    acpi_ex_resolve_to_value(&walk_state->
-							     results->results.
-							     obj_desc[0],
-							     walk_state);
-				if (ACPI_FAILURE(status)) {
-					return (status);
-				}
-			}
-
-			walk_state->return_desc =
-			    walk_state->results->results.obj_desc[0];
-		} else {
-			/* No return operand */
-
-			if (walk_state->num_operands) {
-				acpi_ut_remove_reference(walk_state->
-							 operands[0]);
-			}
-
-			walk_state->operands[0] = NULL;
-			walk_state->num_operands = 0;
-			walk_state->return_desc = NULL;
-		}
-
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "Completed RETURN_OP State=%p, RetVal=%p\n",
-				  walk_state, walk_state->return_desc));
-
-		/* End the control method execution right now */
-
-		status = AE_CTRL_TERMINATE;
-		break;
-
-	case AML_NOOP_OP:
-
-		/* Just do nothing! */
-		break;
-
-	case AML_BREAK_POINT_OP:
-
-		/*
-		 * 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"));
-
-		/* 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:
-	case AML_CONTINUE_OP:	/* ACPI 2.0 */
-
-		/* Pop and delete control states until we find a while */
-
-		while (walk_state->control_state &&
-		       (walk_state->control_state->control.opcode !=
-			AML_WHILE_OP)) {
-			control_state =
-			    acpi_ut_pop_generic_state(&walk_state->
-						      control_state);
-			acpi_ut_delete_generic_state(control_state);
-		}
-
-		/* No while found? */
-
-		if (!walk_state->control_state) {
-			return (AE_AML_NO_WHILE);
-		}
-
-		/* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */
-
-		walk_state->aml_last_while =
-		    walk_state->control_state->control.package_end;
-
-		/* Return status depending on opcode */
-
-		if (op->common.aml_opcode == AML_BREAK_OP) {
-			status = AE_CTRL_BREAK;
-		} else {
-			status = AE_CTRL_CONTINUE;
-		}
-		break;
-
-	default:
-
-		ACPI_ERROR((AE_INFO, "Unknown control opcode=0x%X Op=%p",
-			    op->common.aml_opcode, op));
-
-		status = AE_AML_BAD_OPCODE;
-		break;
-	}
-
-	return (status);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/dswload2.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/dswload2.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/dswload2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/dswload2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,720 @@
+/******************************************************************************
+ *
+ * Module Name: dswload2 - Dispatcher second pass namespace load callbacks
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, Intel Corp.
+ * 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
+ *    substantially 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 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 <acpi/acpi.h>
+#include "accommon.h"
+#include "acparser.h"
+#include "amlcode.h"
+#include "acdispat.h"
+#include "acinterp.h"
+#include "acnamesp.h"
+#include "acevents.h"
+
+#define _COMPONENT          ACPI_DISPATCHER
+ACPI_MODULE_NAME("dswload2")
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_load2_begin_op
+ *
+ * PARAMETERS:  walk_state      - Current state of the parse tree walk
+ *              out_op          - Wher to return op if a new one is created
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Descending callback used during the loading of ACPI tables.
+ *
+ ******************************************************************************/
+acpi_status
+acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
+		       union acpi_parse_object **out_op)
+{
+	union acpi_parse_object *op;
+	struct acpi_namespace_node *node;
+	acpi_status status;
+	acpi_object_type object_type;
+	char *buffer_ptr;
+	u32 flags;
+
+	ACPI_FUNCTION_TRACE(ds_load2_begin_op);
+
+	op = walk_state->op;
+	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
+			  walk_state));
+
+	if (op) {
+		if ((walk_state->control_state) &&
+		    (walk_state->control_state->common.state ==
+		     ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
+
+			/* We are executing a while loop outside of a method */
+
+			status = acpi_ds_exec_begin_op(walk_state, out_op);
+			return_ACPI_STATUS(status);
+		}
+
+		/* We only care about Namespace opcodes here */
+
+		if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
+		     (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
+		    (!(walk_state->op_info->flags & AML_NAMED))) {
+			return_ACPI_STATUS(AE_OK);
+		}
+
+		/* Get the name we are going to enter or lookup in the namespace */
+
+		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
+
+			/* For Namepath op, get the path string */
+
+			buffer_ptr = op->common.value.string;
+			if (!buffer_ptr) {
+
+				/* No name, just exit */
+
+				return_ACPI_STATUS(AE_OK);
+			}
+		} else {
+			/* Get name from the op */
+
+			buffer_ptr = ACPI_CAST_PTR(char, &op->named.name);
+		}
+	} else {
+		/* Get the namestring from the raw AML */
+
+		buffer_ptr =
+		    acpi_ps_get_next_namestring(&walk_state->parser_state);
+	}
+
+	/* Map the opcode into an internal object type */
+
+	object_type = walk_state->op_info->object_type;
+
+	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+			  "State=%p Op=%p Type=%X\n", walk_state, op,
+			  object_type));
+
+	switch (walk_state->opcode) {
+	case AML_FIELD_OP:
+	case AML_BANK_FIELD_OP:
+	case AML_INDEX_FIELD_OP:
+
+		node = NULL;
+		status = AE_OK;
+		break;
+
+	case AML_INT_NAMEPATH_OP:
+		/*
+		 * The name_path is an object reference to an existing object.
+		 * Don't enter the name into the namespace, but look it up
+		 * for use later.
+		 */
+		status =
+		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+				   object_type, ACPI_IMODE_EXECUTE,
+				   ACPI_NS_SEARCH_PARENT, walk_state, &(node));
+		break;
+
+	case AML_SCOPE_OP:
+
+		/* Special case for Scope(\) -> refers to the Root node */
+
+		if (op && (op->named.node == acpi_gbl_root_node)) {
+			node = op->named.node;
+
+			status =
+			    acpi_ds_scope_stack_push(node, object_type,
+						     walk_state);
+			if (ACPI_FAILURE(status)) {
+				return_ACPI_STATUS(status);
+			}
+		} else {
+			/*
+			 * The Path is an object reference to an existing object.
+			 * Don't enter the name into the namespace, but look it up
+			 * for use later.
+			 */
+			status =
+			    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+					   object_type, ACPI_IMODE_EXECUTE,
+					   ACPI_NS_SEARCH_PARENT, walk_state,
+					   &(node));
+			if (ACPI_FAILURE(status)) {
+#ifdef ACPI_ASL_COMPILER
+				if (status == AE_NOT_FOUND) {
+					status = AE_OK;
+				} else {
+					ACPI_ERROR_NAMESPACE(buffer_ptr,
+							     status);
+				}
+#else
+				ACPI_ERROR_NAMESPACE(buffer_ptr, status);
+#endif
+				return_ACPI_STATUS(status);
+			}
+		}
+
+		/*
+		 * We must check to make sure that the target is
+		 * one of the opcodes that actually opens a scope
+		 */
+		switch (node->type) {
+		case ACPI_TYPE_ANY:
+		case ACPI_TYPE_LOCAL_SCOPE:	/* Scope */
+		case ACPI_TYPE_DEVICE:
+		case ACPI_TYPE_POWER:
+		case ACPI_TYPE_PROCESSOR:
+		case ACPI_TYPE_THERMAL:
+
+			/* These are acceptable types */
+			break;
+
+		case ACPI_TYPE_INTEGER:
+		case ACPI_TYPE_STRING:
+		case ACPI_TYPE_BUFFER:
+
+			/*
+			 * These types we will allow, but we will change the type.
+			 * This enables some existing code of the form:
+			 *
+			 *  Name (DEB, 0)
+			 *  Scope (DEB) { ... }
+			 */
+			ACPI_WARNING((AE_INFO,
+				      "Type override - [%4.4s] had invalid type (%s) "
+				      "for Scope operator, changed to type ANY\n",
+				      acpi_ut_get_node_name(node),
+				      acpi_ut_get_type_name(node->type)));
+
+			node->type = ACPI_TYPE_ANY;
+			walk_state->scope_info->common.value = ACPI_TYPE_ANY;
+			break;
+
+		default:
+
+			/* All other types are an error */
+
+			ACPI_ERROR((AE_INFO,
+				    "Invalid type (%s) for target of "
+				    "Scope operator [%4.4s] (Cannot override)",
+				    acpi_ut_get_type_name(node->type),
+				    acpi_ut_get_node_name(node)));
+
+			return (AE_AML_OPERAND_TYPE);
+		}
+		break;
+
+	default:
+
+		/* All other opcodes */
+
+		if (op && op->common.node) {
+
+			/* This op/node was previously entered into the namespace */
+
+			node = op->common.node;
+
+			if (acpi_ns_opens_scope(object_type)) {
+				status =
+				    acpi_ds_scope_stack_push(node, object_type,
+							     walk_state);
+				if (ACPI_FAILURE(status)) {
+					return_ACPI_STATUS(status);
+				}
+			}
+
+			return_ACPI_STATUS(AE_OK);
+		}
+
+		/*
+		 * Enter the named type into the internal namespace. We enter the name
+		 * as we go downward in the parse tree. Any necessary subobjects that
+		 * involve arguments to the opcode must be created as we go back up the
+		 * parse tree later.
+		 *
+		 * Note: Name may already exist if we are executing a deferred opcode.
+		 */
+		if (walk_state->deferred_node) {
+
+			/* This name is already in the namespace, get the node */
+
+			node = walk_state->deferred_node;
+			status = AE_OK;
+			break;
+		}
+
+		flags = ACPI_NS_NO_UPSEARCH;
+		if (walk_state->pass_number == ACPI_IMODE_EXECUTE) {
+
+			/* Execution mode, node cannot already exist, node is temporary */
+
+			flags |= ACPI_NS_ERROR_IF_FOUND;
+
+			if (!
+			    (walk_state->
+			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
+				flags |= ACPI_NS_TEMPORARY;
+			}
+		}
+
+		/* Add new entry or lookup existing entry */
+
+		status =
+		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
+				   object_type, ACPI_IMODE_LOAD_PASS2, flags,
+				   walk_state, &node);
+
+		if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
+			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+					  "***New Node [%4.4s] %p is temporary\n",
+					  acpi_ut_get_node_name(node), node));
+		}
+		break;
+	}
+
+	if (ACPI_FAILURE(status)) {
+		ACPI_ERROR_NAMESPACE(buffer_ptr, status);
+		return_ACPI_STATUS(status);
+	}
+
+	if (!op) {
+
+		/* Create a new op */
+
+		op = acpi_ps_alloc_op(walk_state->opcode);
+		if (!op) {
+			return_ACPI_STATUS(AE_NO_MEMORY);
+		}
+
+		/* Initialize the new op */
+
+		if (node) {
+			op->named.name = node->name.integer;
+		}
+		*out_op = op;
+	}
+
+	/*
+	 * Put the Node in the "op" object that the parser uses, so we
+	 * can get it again quickly when this scope is closed
+	 */
+	op->common.node = node;
+	return_ACPI_STATUS(status);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ds_load2_end_op
+ *
+ * PARAMETERS:  walk_state      - Current state of the parse tree walk
+ *
+ * RETURN:      Status
+ *
+ * DESCRIPTION: Ascending callback used during the loading of the namespace,
+ *              both control methods and everything else.
+ *
+ ******************************************************************************/
+
+acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
+{
+	union acpi_parse_object *op;
+	acpi_status status = AE_OK;
+	acpi_object_type object_type;
+	struct acpi_namespace_node *node;
+	union acpi_parse_object *arg;
+	struct acpi_namespace_node *new_node;
+#ifndef ACPI_NO_METHOD_EXECUTION
+	u32 i;
+	u8 region_space;
+#endif
+
+	ACPI_FUNCTION_TRACE(ds_load2_end_op);
+
+	op = walk_state->op;
+	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
+			  walk_state->op_info->name, op, walk_state));
+
+	/* Check if opcode had an associated namespace object */
+
+	if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
+		return_ACPI_STATUS(AE_OK);
+	}
+
+	if (op->common.aml_opcode == AML_SCOPE_OP) {
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+				  "Ending scope Op=%p State=%p\n", op,
+				  walk_state));
+	}
+
+	object_type = walk_state->op_info->object_type;
+
+	/*
+	 * Get the Node/name from the earlier lookup
+	 * (It was saved in the *op structure)
+	 */
+	node = op->common.node;
+
+	/*
+	 * Put the Node on the object stack (Contains the ACPI Name of
+	 * this object)
+	 */
+	walk_state->operands[0] = (void *)node;
+	walk_state->num_operands = 1;
+
+	/* Pop the scope stack */
+
+	if (acpi_ns_opens_scope(object_type) &&
+	    (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+				  "(%s) Popping scope for Op %p\n",
+				  acpi_ut_get_type_name(object_type), op));
+
+		status = acpi_ds_scope_stack_pop(walk_state);
+		if (ACPI_FAILURE(status)) {
+			goto cleanup;
+		}
+	}
+
+	/*
+	 * Named operations are as follows:
+	 *
+	 * AML_ALIAS
+	 * AML_BANKFIELD
+	 * AML_CREATEBITFIELD
+	 * AML_CREATEBYTEFIELD
+	 * AML_CREATEDWORDFIELD
+	 * AML_CREATEFIELD
+	 * AML_CREATEQWORDFIELD
+	 * AML_CREATEWORDFIELD
+	 * AML_DATA_REGION
+	 * AML_DEVICE
+	 * AML_EVENT
+	 * AML_FIELD
+	 * AML_INDEXFIELD
+	 * AML_METHOD
+	 * AML_METHODCALL
+	 * AML_MUTEX
+	 * AML_NAME
+	 * AML_NAMEDFIELD
+	 * AML_OPREGION
+	 * AML_POWERRES
+	 * AML_PROCESSOR
+	 * AML_SCOPE
+	 * AML_THERMALZONE
+	 */
+
+	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
+			  acpi_ps_get_opcode_name(op->common.aml_opcode),
+			  walk_state, op, node));
+
+	/* Decode the opcode */
+
+	arg = op->common.value.arg;
+
+	switch (walk_state->op_info->type) {
+#ifndef ACPI_NO_METHOD_EXECUTION
+
+	case AML_TYPE_CREATE_FIELD:
+		/*
+		 * Create the field object, but the field buffer and index must
+		 * be evaluated later during the execution phase
+		 */
+		status = acpi_ds_create_buffer_field(op, walk_state);
+		break;
+
+	case AML_TYPE_NAMED_FIELD:
+		/*
+		 * If we are executing a method, initialize the field
+		 */
+		if (walk_state->method_node) {
+			status = acpi_ds_init_field_objects(op, walk_state);
+		}
+
+		switch (op->common.aml_opcode) {
+		case AML_INDEX_FIELD_OP:
+
+			status =
+			    acpi_ds_create_index_field(op,
+						       (acpi_handle) arg->
+						       common.node, walk_state);
+			break;
+
+		case AML_BANK_FIELD_OP:
+
+			status =
+			    acpi_ds_create_bank_field(op, arg->common.node,
+						      walk_state);
+			break;
+
+		case AML_FIELD_OP:
+
+			status =
+			    acpi_ds_create_field(op, arg->common.node,
+						 walk_state);
+			break;
+
+		default:
+			/* All NAMED_FIELD opcodes must be handled above */
+			break;
+		}
+		break;
+
+	case AML_TYPE_NAMED_SIMPLE:
+
+		status = acpi_ds_create_operands(walk_state, arg);
+		if (ACPI_FAILURE(status)) {
+			goto cleanup;
+		}
+
+		switch (op->common.aml_opcode) {
+		case AML_PROCESSOR_OP:
+
+			status = acpi_ex_create_processor(walk_state);
+			break;
+
+		case AML_POWER_RES_OP:
+
+			status = acpi_ex_create_power_resource(walk_state);
+			break;
+
+		case AML_MUTEX_OP:
+
+			status = acpi_ex_create_mutex(walk_state);
+			break;
+
+		case AML_EVENT_OP:
+
+			status = acpi_ex_create_event(walk_state);
+			break;
+
+		case AML_ALIAS_OP:
+
+			status = acpi_ex_create_alias(walk_state);
+			break;
+
+		default:
+			/* Unknown opcode */
+
+			status = AE_OK;
+			goto cleanup;
+		}
+
+		/* Delete operands */
+
+		for (i = 1; i < walk_state->num_operands; i++) {
+			acpi_ut_remove_reference(walk_state->operands[i]);
+			walk_state->operands[i] = NULL;
+		}
+
+		break;
+#endif				/* ACPI_NO_METHOD_EXECUTION */
+
+	case AML_TYPE_NAMED_COMPLEX:
+
+		switch (op->common.aml_opcode) {
+#ifndef ACPI_NO_METHOD_EXECUTION
+		case AML_REGION_OP:
+		case AML_DATA_REGION_OP:
+
+			if (op->common.aml_opcode == AML_REGION_OP) {
+				region_space = (acpi_adr_space_type)
+				    ((op->common.value.arg)->common.value.
+				     integer);
+			} else {
+				region_space = REGION_DATA_TABLE;
+			}
+
+			/*
+			 * The op_region is not fully parsed at this time. The only valid
+			 * argument is the space_id. (We must save the address of the
+			 * AML of the address and length operands)
+			 *
+			 * If we have a valid region, initialize it. The namespace is
+			 * unlocked at this point.
+			 *
+			 * Need to unlock interpreter if it is locked (if we are running
+			 * a control method), in order to allow _REG methods to be run
+			 * during acpi_ev_initialize_region.
+			 */
+			if (walk_state->method_node) {
+				/*
+				 * Executing a method: initialize the region and unlock
+				 * the interpreter
+				 */
+				status =
+				    acpi_ex_create_region(op->named.data,
+							  op->named.length,
+							  region_space,
+							  walk_state);
+				if (ACPI_FAILURE(status)) {
+					return (status);
+				}
+
+				acpi_ex_exit_interpreter();
+			}
+
+			status =
+			    acpi_ev_initialize_region
+			    (acpi_ns_get_attached_object(node), FALSE);
+			if (walk_state->method_node) {
+				acpi_ex_enter_interpreter();
+			}
+
+			if (ACPI_FAILURE(status)) {
+				/*
+				 *  If AE_NOT_EXIST is returned, it is not fatal
+				 *  because many regions get created before a handler
+				 *  is installed for said region.
+				 */
+				if (AE_NOT_EXIST == status) {
+					status = AE_OK;
+				}
+			}
+			break;
+
+		case AML_NAME_OP:
+
+			status = acpi_ds_create_node(walk_state, node, op);
+			break;
+
+		case AML_METHOD_OP:
+			/*
+			 * method_op pkg_length name_string method_flags term_list
+			 *
+			 * Note: We must create the method node/object pair as soon as we
+			 * see the method declaration. This allows later pass1 parsing
+			 * of invocations of the method (need to know the number of
+			 * arguments.)
+			 */
+			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
+					  walk_state, op, op->named.node));
+
+			if (!acpi_ns_get_attached_object(op->named.node)) {
+				walk_state->operands[0] =
+				    ACPI_CAST_PTR(void, op->named.node);
+				walk_state->num_operands = 1;
+
+				status =
+				    acpi_ds_create_operands(walk_state,
+							    op->common.value.
+							    arg);
+				if (ACPI_SUCCESS(status)) {
+					status =
+					    acpi_ex_create_method(op->named.
+								  data,
+								  op->named.
+								  length,
+								  walk_state);
+				}
+				walk_state->operands[0] = NULL;
+				walk_state->num_operands = 0;
+
+				if (ACPI_FAILURE(status)) {
+					return_ACPI_STATUS(status);
+				}
+			}
+			break;
+
+#endif				/* ACPI_NO_METHOD_EXECUTION */
+
+		default:
+			/* All NAMED_COMPLEX opcodes must be handled above */
+			break;
+		}
+		break;
+
+	case AML_CLASS_INTERNAL:
+
+		/* case AML_INT_NAMEPATH_OP: */
+		break;
+
+	case AML_CLASS_METHOD_CALL:
+
+		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
+				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
+				  walk_state, op, node));
+
+		/*
+		 * Lookup the method name and save the Node
+		 */
+		status =
+		    acpi_ns_lookup(walk_state->scope_info,
+				   arg->common.value.string, ACPI_TYPE_ANY,
+				   ACPI_IMODE_LOAD_PASS2,
+				   ACPI_NS_SEARCH_PARENT |
+				   ACPI_NS_DONT_OPEN_SCOPE, walk_state,
+				   &(new_node));
+		if (ACPI_SUCCESS(status)) {
+			/*
+			 * Make sure that what we found is indeed a method
+			 * We didn't search for a method on purpose, to see if the name
+			 * would resolve
+			 */
+			if (new_node->type != ACPI_TYPE_METHOD) {
+				status = AE_AML_OPERAND_TYPE;
+			}
+
+			/* We could put the returned object (Node) on the object stack for
+			 * later, but for now, we will put it in the "op" object that the
+			 * parser uses, so we can get it again at the end of this scope
+			 */
+			op->common.node = new_node;
+		} else {
+			ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
+		}
+		break;
+
+	default:
+		break;
+	}
+
+      cleanup:
+
+	/* Remove the Node pushed at the very beginning */
+
+	walk_state->operands[0] = NULL;
+	walk_state->num_operands = 0;
+	return_ACPI_STATUS(status);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/dswload.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/dswload.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/dswload.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/dswload.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /******************************************************************************
  *
- * Module Name: dswload - Dispatcher namespace load callbacks
+ * Module Name: dswload - Dispatcher first pass namespace load callbacks
  *
  *****************************************************************************/
 
@@ -48,7 +48,6 @@
 #include "acdispat.h"
 #include "acinterp.h"
 #include "acnamesp.h"
-#include "acevents.h"
 
 #ifdef ACPI_ASL_COMPILER
 #include <acpi/acdisasm.h>
@@ -537,670 +536,3 @@
 
 	return_ACPI_STATUS(status);
 }
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_load2_begin_op
- *
- * PARAMETERS:  walk_state      - Current state of the parse tree walk
- *              out_op          - Wher to return op if a new one is created
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Descending callback used during the loading of ACPI tables.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
-		       union acpi_parse_object **out_op)
-{
-	union acpi_parse_object *op;
-	struct acpi_namespace_node *node;
-	acpi_status status;
-	acpi_object_type object_type;
-	char *buffer_ptr;
-	u32 flags;
-
-	ACPI_FUNCTION_TRACE(ds_load2_begin_op);
-
-	op = walk_state->op;
-	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
-			  walk_state));
-
-	if (op) {
-		if ((walk_state->control_state) &&
-		    (walk_state->control_state->common.state ==
-		     ACPI_CONTROL_CONDITIONAL_EXECUTING)) {
-
-			/* We are executing a while loop outside of a method */
-
-			status = acpi_ds_exec_begin_op(walk_state, out_op);
-			return_ACPI_STATUS(status);
-		}
-
-		/* We only care about Namespace opcodes here */
-
-		if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
-		     (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
-		    (!(walk_state->op_info->flags & AML_NAMED))) {
-			return_ACPI_STATUS(AE_OK);
-		}
-
-		/* Get the name we are going to enter or lookup in the namespace */
-
-		if (walk_state->opcode == AML_INT_NAMEPATH_OP) {
-
-			/* For Namepath op, get the path string */
-
-			buffer_ptr = op->common.value.string;
-			if (!buffer_ptr) {
-
-				/* No name, just exit */
-
-				return_ACPI_STATUS(AE_OK);
-			}
-		} else {
-			/* Get name from the op */
-
-			buffer_ptr = ACPI_CAST_PTR(char, &op->named.name);
-		}
-	} else {
-		/* Get the namestring from the raw AML */
-
-		buffer_ptr =
-		    acpi_ps_get_next_namestring(&walk_state->parser_state);
-	}
-
-	/* Map the opcode into an internal object type */
-
-	object_type = walk_state->op_info->object_type;
-
-	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-			  "State=%p Op=%p Type=%X\n", walk_state, op,
-			  object_type));
-
-	switch (walk_state->opcode) {
-	case AML_FIELD_OP:
-	case AML_BANK_FIELD_OP:
-	case AML_INDEX_FIELD_OP:
-
-		node = NULL;
-		status = AE_OK;
-		break;
-
-	case AML_INT_NAMEPATH_OP:
-		/*
-		 * The name_path is an object reference to an existing object.
-		 * Don't enter the name into the namespace, but look it up
-		 * for use later.
-		 */
-		status =
-		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
-				   object_type, ACPI_IMODE_EXECUTE,
-				   ACPI_NS_SEARCH_PARENT, walk_state, &(node));
-		break;
-
-	case AML_SCOPE_OP:
-
-		/* Special case for Scope(\) -> refers to the Root node */
-
-		if (op && (op->named.node == acpi_gbl_root_node)) {
-			node = op->named.node;
-
-			status =
-			    acpi_ds_scope_stack_push(node, object_type,
-						     walk_state);
-			if (ACPI_FAILURE(status)) {
-				return_ACPI_STATUS(status);
-			}
-		} else {
-			/*
-			 * The Path is an object reference to an existing object.
-			 * Don't enter the name into the namespace, but look it up
-			 * for use later.
-			 */
-			status =
-			    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
-					   object_type, ACPI_IMODE_EXECUTE,
-					   ACPI_NS_SEARCH_PARENT, walk_state,
-					   &(node));
-			if (ACPI_FAILURE(status)) {
-#ifdef ACPI_ASL_COMPILER
-				if (status == AE_NOT_FOUND) {
-					status = AE_OK;
-				} else {
-					ACPI_ERROR_NAMESPACE(buffer_ptr,
-							     status);
-				}
-#else
-				ACPI_ERROR_NAMESPACE(buffer_ptr, status);
-#endif
-				return_ACPI_STATUS(status);
-			}
-		}
-
-		/*
-		 * We must check to make sure that the target is
-		 * one of the opcodes that actually opens a scope
-		 */
-		switch (node->type) {
-		case ACPI_TYPE_ANY:
-		case ACPI_TYPE_LOCAL_SCOPE:	/* Scope */
-		case ACPI_TYPE_DEVICE:
-		case ACPI_TYPE_POWER:
-		case ACPI_TYPE_PROCESSOR:
-		case ACPI_TYPE_THERMAL:
-
-			/* These are acceptable types */
-			break;
-
-		case ACPI_TYPE_INTEGER:
-		case ACPI_TYPE_STRING:
-		case ACPI_TYPE_BUFFER:
-
-			/*
-			 * These types we will allow, but we will change the type.
-			 * This enables some existing code of the form:
-			 *
-			 *  Name (DEB, 0)
-			 *  Scope (DEB) { ... }
-			 */
-			ACPI_WARNING((AE_INFO,
-				      "Type override - [%4.4s] had invalid type (%s) "
-				      "for Scope operator, changed to type ANY\n",
-				      acpi_ut_get_node_name(node),
-				      acpi_ut_get_type_name(node->type)));
-
-			node->type = ACPI_TYPE_ANY;
-			walk_state->scope_info->common.value = ACPI_TYPE_ANY;
-			break;
-
-		default:
-
-			/* All other types are an error */
-
-			ACPI_ERROR((AE_INFO,
-				    "Invalid type (%s) for target of "
-				    "Scope operator [%4.4s] (Cannot override)",
-				    acpi_ut_get_type_name(node->type),
-				    acpi_ut_get_node_name(node)));
-
-			return (AE_AML_OPERAND_TYPE);
-		}
-		break;
-
-	default:
-
-		/* All other opcodes */
-
-		if (op && op->common.node) {
-
-			/* This op/node was previously entered into the namespace */
-
-			node = op->common.node;
-
-			if (acpi_ns_opens_scope(object_type)) {
-				status =
-				    acpi_ds_scope_stack_push(node, object_type,
-							     walk_state);
-				if (ACPI_FAILURE(status)) {
-					return_ACPI_STATUS(status);
-				}
-			}
-
-			return_ACPI_STATUS(AE_OK);
-		}
-
-		/*
-		 * Enter the named type into the internal namespace. We enter the name
-		 * as we go downward in the parse tree. Any necessary subobjects that
-		 * involve arguments to the opcode must be created as we go back up the
-		 * parse tree later.
-		 *
-		 * Note: Name may already exist if we are executing a deferred opcode.
-		 */
-		if (walk_state->deferred_node) {
-
-			/* This name is already in the namespace, get the node */
-
-			node = walk_state->deferred_node;
-			status = AE_OK;
-			break;
-		}
-
-		flags = ACPI_NS_NO_UPSEARCH;
-		if (walk_state->pass_number == ACPI_IMODE_EXECUTE) {
-
-			/* Execution mode, node cannot already exist, node is temporary */
-
-			flags |= ACPI_NS_ERROR_IF_FOUND;
-
-			if (!
-			    (walk_state->
-			     parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
-				flags |= ACPI_NS_TEMPORARY;
-			}
-		}
-
-		/* Add new entry or lookup existing entry */
-
-		status =
-		    acpi_ns_lookup(walk_state->scope_info, buffer_ptr,
-				   object_type, ACPI_IMODE_LOAD_PASS2, flags,
-				   walk_state, &node);
-
-		if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) {
-			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-					  "***New Node [%4.4s] %p is temporary\n",
-					  acpi_ut_get_node_name(node), node));
-		}
-		break;
-	}
-
-	if (ACPI_FAILURE(status)) {
-		ACPI_ERROR_NAMESPACE(buffer_ptr, status);
-		return_ACPI_STATUS(status);
-	}
-
-	if (!op) {
-
-		/* Create a new op */
-
-		op = acpi_ps_alloc_op(walk_state->opcode);
-		if (!op) {
-			return_ACPI_STATUS(AE_NO_MEMORY);
-		}
-
-		/* Initialize the new op */
-
-		if (node) {
-			op->named.name = node->name.integer;
-		}
-		*out_op = op;
-	}
-
-	/*
-	 * Put the Node in the "op" object that the parser uses, so we
-	 * can get it again quickly when this scope is closed
-	 */
-	op->common.node = node;
-	return_ACPI_STATUS(status);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ds_load2_end_op
- *
- * PARAMETERS:  walk_state      - Current state of the parse tree walk
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Ascending callback used during the loading of the namespace,
- *              both control methods and everything else.
- *
- ******************************************************************************/
-
-acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
-{
-	union acpi_parse_object *op;
-	acpi_status status = AE_OK;
-	acpi_object_type object_type;
-	struct acpi_namespace_node *node;
-	union acpi_parse_object *arg;
-	struct acpi_namespace_node *new_node;
-#ifndef ACPI_NO_METHOD_EXECUTION
-	u32 i;
-	u8 region_space;
-#endif
-
-	ACPI_FUNCTION_TRACE(ds_load2_end_op);
-
-	op = walk_state->op;
-	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
-			  walk_state->op_info->name, op, walk_state));
-
-	/* Check if opcode had an associated namespace object */
-
-	if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
-		return_ACPI_STATUS(AE_OK);
-	}
-
-	if (op->common.aml_opcode == AML_SCOPE_OP) {
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "Ending scope Op=%p State=%p\n", op,
-				  walk_state));
-	}
-
-	object_type = walk_state->op_info->object_type;
-
-	/*
-	 * Get the Node/name from the earlier lookup
-	 * (It was saved in the *op structure)
-	 */
-	node = op->common.node;
-
-	/*
-	 * Put the Node on the object stack (Contains the ACPI Name of
-	 * this object)
-	 */
-	walk_state->operands[0] = (void *)node;
-	walk_state->num_operands = 1;
-
-	/* Pop the scope stack */
-
-	if (acpi_ns_opens_scope(object_type) &&
-	    (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "(%s) Popping scope for Op %p\n",
-				  acpi_ut_get_type_name(object_type), op));
-
-		status = acpi_ds_scope_stack_pop(walk_state);
-		if (ACPI_FAILURE(status)) {
-			goto cleanup;
-		}
-	}
-
-	/*
-	 * Named operations are as follows:
-	 *
-	 * AML_ALIAS
-	 * AML_BANKFIELD
-	 * AML_CREATEBITFIELD
-	 * AML_CREATEBYTEFIELD
-	 * AML_CREATEDWORDFIELD
-	 * AML_CREATEFIELD
-	 * AML_CREATEQWORDFIELD
-	 * AML_CREATEWORDFIELD
-	 * AML_DATA_REGION
-	 * AML_DEVICE
-	 * AML_EVENT
-	 * AML_FIELD
-	 * AML_INDEXFIELD
-	 * AML_METHOD
-	 * AML_METHODCALL
-	 * AML_MUTEX
-	 * AML_NAME
-	 * AML_NAMEDFIELD
-	 * AML_OPREGION
-	 * AML_POWERRES
-	 * AML_PROCESSOR
-	 * AML_SCOPE
-	 * AML_THERMALZONE
-	 */
-
-	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
-			  acpi_ps_get_opcode_name(op->common.aml_opcode),
-			  walk_state, op, node));
-
-	/* Decode the opcode */
-
-	arg = op->common.value.arg;
-
-	switch (walk_state->op_info->type) {
-#ifndef ACPI_NO_METHOD_EXECUTION
-
-	case AML_TYPE_CREATE_FIELD:
-		/*
-		 * Create the field object, but the field buffer and index must
-		 * be evaluated later during the execution phase
-		 */
-		status = acpi_ds_create_buffer_field(op, walk_state);
-		break;
-
-	case AML_TYPE_NAMED_FIELD:
-		/*
-		 * If we are executing a method, initialize the field
-		 */
-		if (walk_state->method_node) {
-			status = acpi_ds_init_field_objects(op, walk_state);
-		}
-
-		switch (op->common.aml_opcode) {
-		case AML_INDEX_FIELD_OP:
-
-			status =
-			    acpi_ds_create_index_field(op,
-						       (acpi_handle) arg->
-						       common.node, walk_state);
-			break;
-
-		case AML_BANK_FIELD_OP:
-
-			status =
-			    acpi_ds_create_bank_field(op, arg->common.node,
-						      walk_state);
-			break;
-
-		case AML_FIELD_OP:
-
-			status =
-			    acpi_ds_create_field(op, arg->common.node,
-						 walk_state);
-			break;
-
-		default:
-			/* All NAMED_FIELD opcodes must be handled above */
-			break;
-		}
-		break;
-
-	case AML_TYPE_NAMED_SIMPLE:
-
-		status = acpi_ds_create_operands(walk_state, arg);
-		if (ACPI_FAILURE(status)) {
-			goto cleanup;
-		}
-
-		switch (op->common.aml_opcode) {
-		case AML_PROCESSOR_OP:
-
-			status = acpi_ex_create_processor(walk_state);
-			break;
-
-		case AML_POWER_RES_OP:
-
-			status = acpi_ex_create_power_resource(walk_state);
-			break;
-
-		case AML_MUTEX_OP:
-
-			status = acpi_ex_create_mutex(walk_state);
-			break;
-
-		case AML_EVENT_OP:
-
-			status = acpi_ex_create_event(walk_state);
-			break;
-
-		case AML_ALIAS_OP:
-
-			status = acpi_ex_create_alias(walk_state);
-			break;
-
-		default:
-			/* Unknown opcode */
-
-			status = AE_OK;
-			goto cleanup;
-		}
-
-		/* Delete operands */
-
-		for (i = 1; i < walk_state->num_operands; i++) {
-			acpi_ut_remove_reference(walk_state->operands[i]);
-			walk_state->operands[i] = NULL;
-		}
-
-		break;
-#endif				/* ACPI_NO_METHOD_EXECUTION */
-
-	case AML_TYPE_NAMED_COMPLEX:
-
-		switch (op->common.aml_opcode) {
-#ifndef ACPI_NO_METHOD_EXECUTION
-		case AML_REGION_OP:
-		case AML_DATA_REGION_OP:
-
-			if (op->common.aml_opcode == AML_REGION_OP) {
-				region_space = (acpi_adr_space_type)
-				    ((op->common.value.arg)->common.value.
-				     integer);
-			} else {
-				region_space = REGION_DATA_TABLE;
-			}
-
-			/*
-			 * The op_region is not fully parsed at this time. The only valid
-			 * argument is the space_id. (We must save the address of the
-			 * AML of the address and length operands)
-			 *
-			 * If we have a valid region, initialize it. The namespace is
-			 * unlocked at this point.
-			 *
-			 * Need to unlock interpreter if it is locked (if we are running
-			 * a control method), in order to allow _REG methods to be run
-			 * during acpi_ev_initialize_region.
-			 */
-			if (walk_state->method_node) {
-				/*
-				 * Executing a method: initialize the region and unlock
-				 * the interpreter
-				 */
-				status =
-				    acpi_ex_create_region(op->named.data,
-							  op->named.length,
-							  region_space,
-							  walk_state);
-				if (ACPI_FAILURE(status)) {
-					return (status);
-				}
-
-				acpi_ex_exit_interpreter();
-			}
-
-			status =
-			    acpi_ev_initialize_region
-			    (acpi_ns_get_attached_object(node), FALSE);
-			if (walk_state->method_node) {
-				acpi_ex_enter_interpreter();
-			}
-
-			if (ACPI_FAILURE(status)) {
-				/*
-				 *  If AE_NOT_EXIST is returned, it is not fatal
-				 *  because many regions get created before a handler
-				 *  is installed for said region.
-				 */
-				if (AE_NOT_EXIST == status) {
-					status = AE_OK;
-				}
-			}
-			break;
-
-		case AML_NAME_OP:
-
-			status = acpi_ds_create_node(walk_state, node, op);
-			break;
-
-		case AML_METHOD_OP:
-			/*
-			 * method_op pkg_length name_string method_flags term_list
-			 *
-			 * Note: We must create the method node/object pair as soon as we
-			 * see the method declaration. This allows later pass1 parsing
-			 * of invocations of the method (need to know the number of
-			 * arguments.)
-			 */
-			ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-					  "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
-					  walk_state, op, op->named.node));
-
-			if (!acpi_ns_get_attached_object(op->named.node)) {
-				walk_state->operands[0] =
-				    ACPI_CAST_PTR(void, op->named.node);
-				walk_state->num_operands = 1;
-
-				status =
-				    acpi_ds_create_operands(walk_state,
-							    op->common.value.
-							    arg);
-				if (ACPI_SUCCESS(status)) {
-					status =
-					    acpi_ex_create_method(op->named.
-								  data,
-								  op->named.
-								  length,
-								  walk_state);
-				}
-				walk_state->operands[0] = NULL;
-				walk_state->num_operands = 0;
-
-				if (ACPI_FAILURE(status)) {
-					return_ACPI_STATUS(status);
-				}
-			}
-			break;
-
-#endif				/* ACPI_NO_METHOD_EXECUTION */
-
-		default:
-			/* All NAMED_COMPLEX opcodes must be handled above */
-			break;
-		}
-		break;
-
-	case AML_CLASS_INTERNAL:
-
-		/* case AML_INT_NAMEPATH_OP: */
-		break;
-
-	case AML_CLASS_METHOD_CALL:
-
-		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
-				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
-				  walk_state, op, node));
-
-		/*
-		 * Lookup the method name and save the Node
-		 */
-		status =
-		    acpi_ns_lookup(walk_state->scope_info,
-				   arg->common.value.string, ACPI_TYPE_ANY,
-				   ACPI_IMODE_LOAD_PASS2,
-				   ACPI_NS_SEARCH_PARENT |
-				   ACPI_NS_DONT_OPEN_SCOPE, walk_state,
-				   &(new_node));
-		if (ACPI_SUCCESS(status)) {
-			/*
-			 * Make sure that what we found is indeed a method
-			 * We didn't search for a method on purpose, to see if the name
-			 * would resolve
-			 */
-			if (new_node->type != ACPI_TYPE_METHOD) {
-				status = AE_AML_OPERAND_TYPE;
-			}
-
-			/* We could put the returned object (Node) on the object stack for
-			 * later, but for now, we will put it in the "op" object that the
-			 * parser uses, so we can get it again at the end of this scope
-			 */
-			op->common.node = new_node;
-		} else {
-			ACPI_ERROR_NAMESPACE(arg->common.value.string, status);
-		}
-		break;
-
-	default:
-		break;
-	}
-
-      cleanup:
-
-	/* Remove the Node pushed at the very beginning */
-
-	walk_state->operands[0] = NULL;
-	walk_state->num_operands = 0;
-	return_ACPI_STATUS(status);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/evgpe.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/evgpe.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/evgpe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/evgpe.c	2011-05-19 00:06:34.000000000 -0400
@@ -373,6 +373,15 @@
 
 			gpe_register_info = &gpe_block->register_info[i];
 
+			/*
+			 * Optimization: If there are no GPEs enabled within this
+			 * register, we can safely ignore the entire register.
+			 */
+			if (!(gpe_register_info->enable_for_run |
+			      gpe_register_info->enable_for_wake)) {
+				continue;
+			}
+
 			/* Read the Status Register */
 
 			status =
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/evregion.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/evregion.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/evregion.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/evregion.c	2011-05-19 00:06:34.000000000 -0400
@@ -231,6 +231,8 @@
 		}
 	}
 
+	acpi_gbl_reg_methods_executed = TRUE;
+
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
 	return_ACPI_STATUS(status);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/evxfregn.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/evxfregn.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/evxfregn.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/evxfregn.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,9 +110,39 @@
 		goto unlock_and_exit;
 	}
 
-	/* Run all _REG methods for this address space */
+	/*
+	 * For the default space_iDs, (the IDs for which there are default region handlers
+	 * installed) Only execute the _REG methods if the global initialization _REG
+	 * methods have already been run (via acpi_initialize_objects). In other words,
+	 * we will defer the execution of the _REG methods for these space_iDs until
+	 * execution of acpi_initialize_objects. This is done because we need the handlers
+	 * for the default spaces (mem/io/pci/table) to be installed before we can run
+	 * any control methods (or _REG methods). There is known BIOS code that depends
+	 * on this.
+	 *
+	 * For all other space_iDs, we can safely execute the _REG methods immediately.
+	 * This means that for IDs like embedded_controller, this function should be called
+	 * only after acpi_enable_subsystem has been called.
+	 */
+	switch (space_id) {
+	case ACPI_ADR_SPACE_SYSTEM_MEMORY:
+	case ACPI_ADR_SPACE_SYSTEM_IO:
+	case ACPI_ADR_SPACE_PCI_CONFIG:
+	case ACPI_ADR_SPACE_DATA_TABLE:
 
-	status = acpi_ev_execute_reg_methods(node, space_id);
+		if (acpi_gbl_reg_methods_executed) {
+
+			/* Run all _REG methods for this address space */
+
+			status = acpi_ev_execute_reg_methods(node, space_id);
+		}
+		break;
+
+	default:
+
+		status = acpi_ev_execute_reg_methods(node, space_id);
+		break;
+	}
 
       unlock_and_exit:
 	(void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/exfldio.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/exfldio.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/exfldio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/exfldio.c	2011-05-19 00:06:34.000000000 -0400
@@ -280,13 +280,13 @@
 	if (ACPI_FAILURE(status)) {
 		if (status == AE_NOT_IMPLEMENTED) {
 			ACPI_ERROR((AE_INFO,
-				    "Region %s(0x%X) not implemented",
+				    "Region %s (ID=%u) not implemented",
 				    acpi_ut_get_region_name(rgn_desc->region.
 							    space_id),
 				    rgn_desc->region.space_id));
 		} else if (status == AE_NOT_EXIST) {
 			ACPI_ERROR((AE_INFO,
-				    "Region %s(0x%X) has no handler",
+				    "Region %s (ID=%u) has no handler",
 				    acpi_ut_get_region_name(rgn_desc->region.
 							    space_id),
 				    rgn_desc->region.space_id));
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/hwxface.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/hwxface.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/hwxface.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/hwxface.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,14 +80,14 @@
 
 	if (reset_reg->space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
 		/*
-		 * For I/O space, write directly to the OSL. This bypasses the port
-		 * validation mechanism, which may block a valid write to the reset
-		 * register.
+		 * For I/O space, write directly to the OSL. This
+		 * bypasses the port validation mechanism, which may
+		 * block a valid write to the reset register. Spec
+		 * section 4.7.3.6 requires register width to be 8.
 		 */
 		status =
 		    acpi_os_write_port((acpi_io_address) reset_reg->address,
-				       acpi_gbl_FADT.reset_value,
-				       reset_reg->bit_width);
+				       acpi_gbl_FADT.reset_value, 8);
 	} else {
 		/* Write the reset value to the reset register */
 
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/Makefile linux-libre-2.6.39-gnu/drivers/acpi/acpica/Makefile
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,7 @@
 
 acpi-y := dsfield.o   dsmthdat.o  dsopcode.o  dswexec.o  dswscope.o \
 	 dsmethod.o  dsobject.o  dsutils.o   dswload.o  dswstate.o \
-	 dsinit.o
+	 dsinit.o dsargs.o dscontrol.o dswload2.o
 
 acpi-y += evevent.o  evregion.o  evsci.o    evxfevnt.o \
 	 evmisc.o   evrgnini.o  evxface.o  evxfregn.o \
@@ -45,4 +45,4 @@
 acpi-y += utalloc.o utdebug.o uteval.o utinit.o utmisc.o utxface.o \
 		utcopy.o utdelete.o utglobal.o utmath.o utobject.o \
 		utstate.o utmutex.o utobject.o utresrc.o utlock.o utids.o \
-		utosi.o utxferror.o
+		utosi.o utxferror.o utdecode.o
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/tbfadt.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/tbfadt.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/tbfadt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/tbfadt.c	2011-05-19 00:06:34.000000000 -0400
@@ -384,8 +384,11 @@
 	 *
 	 * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at
 	 * offset 45, 55, 95, and the word located at offset 109, 110.
+	 *
+	 * Note: The FADT revision value is unreliable. Only the length can be
+	 * trusted.
 	 */
-	if (acpi_gbl_FADT.header.revision < FADT2_REVISION_ID) {
+	if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) {
 		acpi_gbl_FADT.preferred_profile = 0;
 		acpi_gbl_FADT.pstate_control = 0;
 		acpi_gbl_FADT.cst_control = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/utdecode.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/utdecode.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/utdecode.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/utdecode.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,548 @@
+/******************************************************************************
+ *
+ * Module Name: utdecode - Utility decoding routines (value-to-string)
+ *
+ *****************************************************************************/
+
+/*
+ * Copyright (C) 2000 - 2011, Intel Corp.
+ * 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
+ *    substantially 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 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 <acpi/acpi.h>
+#include "accommon.h"
+#include "acnamesp.h"
+
+#define _COMPONENT          ACPI_UTILITIES
+ACPI_MODULE_NAME("utdecode")
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_format_exception
+ *
+ * PARAMETERS:  Status       - The acpi_status code to be formatted
+ *
+ * RETURN:      A string containing the exception text. A valid pointer is
+ *              always returned.
+ *
+ * DESCRIPTION: This function translates an ACPI exception into an ASCII string
+ *              It is here instead of utxface.c so it is always present.
+ *
+ ******************************************************************************/
+const char *acpi_format_exception(acpi_status status)
+{
+	const char *exception = NULL;
+
+	ACPI_FUNCTION_ENTRY();
+
+	exception = acpi_ut_validate_exception(status);
+	if (!exception) {
+
+		/* Exception code was not recognized */
+
+		ACPI_ERROR((AE_INFO,
+			    "Unknown exception code: 0x%8.8X", status));
+
+		exception = "UNKNOWN_STATUS_CODE";
+	}
+
+	return (ACPI_CAST_PTR(const char, exception));
+}
+
+ACPI_EXPORT_SYMBOL(acpi_format_exception)
+
+/*
+ * Properties of the ACPI Object Types, both internal and external.
+ * The table is indexed by values of acpi_object_type
+ */
+const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES] = {
+	ACPI_NS_NORMAL,		/* 00 Any              */
+	ACPI_NS_NORMAL,		/* 01 Number           */
+	ACPI_NS_NORMAL,		/* 02 String           */
+	ACPI_NS_NORMAL,		/* 03 Buffer           */
+	ACPI_NS_NORMAL,		/* 04 Package          */
+	ACPI_NS_NORMAL,		/* 05 field_unit       */
+	ACPI_NS_NEWSCOPE,	/* 06 Device           */
+	ACPI_NS_NORMAL,		/* 07 Event            */
+	ACPI_NS_NEWSCOPE,	/* 08 Method           */
+	ACPI_NS_NORMAL,		/* 09 Mutex            */
+	ACPI_NS_NORMAL,		/* 10 Region           */
+	ACPI_NS_NEWSCOPE,	/* 11 Power            */
+	ACPI_NS_NEWSCOPE,	/* 12 Processor        */
+	ACPI_NS_NEWSCOPE,	/* 13 Thermal          */
+	ACPI_NS_NORMAL,		/* 14 buffer_field     */
+	ACPI_NS_NORMAL,		/* 15 ddb_handle       */
+	ACPI_NS_NORMAL,		/* 16 Debug Object     */
+	ACPI_NS_NORMAL,		/* 17 def_field        */
+	ACPI_NS_NORMAL,		/* 18 bank_field       */
+	ACPI_NS_NORMAL,		/* 19 index_field      */
+	ACPI_NS_NORMAL,		/* 20 Reference        */
+	ACPI_NS_NORMAL,		/* 21 Alias            */
+	ACPI_NS_NORMAL,		/* 22 method_alias     */
+	ACPI_NS_NORMAL,		/* 23 Notify           */
+	ACPI_NS_NORMAL,		/* 24 Address Handler  */
+	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 25 Resource Desc    */
+	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 26 Resource Field   */
+	ACPI_NS_NEWSCOPE,	/* 27 Scope            */
+	ACPI_NS_NORMAL,		/* 28 Extra            */
+	ACPI_NS_NORMAL,		/* 29 Data             */
+	ACPI_NS_NORMAL		/* 30 Invalid          */
+};
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_hex_to_ascii_char
+ *
+ * PARAMETERS:  Integer             - Contains the hex digit
+ *              Position            - bit position of the digit within the
+ *                                    integer (multiple of 4)
+ *
+ * RETURN:      The converted Ascii character
+ *
+ * DESCRIPTION: Convert a hex digit to an Ascii character
+ *
+ ******************************************************************************/
+
+/* Hex to ASCII conversion table */
+
+static const char acpi_gbl_hex_to_ascii[] = {
+	'0', '1', '2', '3', '4', '5', '6', '7',
+	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+};
+
+char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
+{
+
+	return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_region_name
+ *
+ * PARAMETERS:  Space ID            - ID for the region
+ *
+ * RETURN:      Decoded region space_id name
+ *
+ * DESCRIPTION: Translate a Space ID into a name string (Debug only)
+ *
+ ******************************************************************************/
+
+/* Region type decoding */
+
+const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
+	"SystemMemory",
+	"SystemIO",
+	"PCI_Config",
+	"EmbeddedControl",
+	"SMBus",
+	"SystemCMOS",
+	"PCIBARTarget",
+	"IPMI",
+	"DataTable"
+};
+
+char *acpi_ut_get_region_name(u8 space_id)
+{
+
+	if (space_id >= ACPI_USER_REGION_BEGIN) {
+		return ("UserDefinedRegion");
+	} else if (space_id == ACPI_ADR_SPACE_FIXED_HARDWARE) {
+		return ("FunctionalFixedHW");
+	} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
+		return ("InvalidSpaceId");
+	}
+
+	return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_event_name
+ *
+ * PARAMETERS:  event_id            - Fixed event ID
+ *
+ * RETURN:      Decoded event ID name
+ *
+ * DESCRIPTION: Translate a Event ID into a name string (Debug only)
+ *
+ ******************************************************************************/
+
+/* Event type decoding */
+
+static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
+	"PM_Timer",
+	"GlobalLock",
+	"PowerButton",
+	"SleepButton",
+	"RealTimeClock",
+};
+
+char *acpi_ut_get_event_name(u32 event_id)
+{
+
+	if (event_id > ACPI_EVENT_MAX) {
+		return ("InvalidEventID");
+	}
+
+	return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_type_name
+ *
+ * PARAMETERS:  Type                - An ACPI object type
+ *
+ * RETURN:      Decoded ACPI object type name
+ *
+ * DESCRIPTION: Translate a Type ID into a name string (Debug only)
+ *
+ ******************************************************************************/
+
+/*
+ * Elements of acpi_gbl_ns_type_names below must match
+ * one-to-one with values of acpi_object_type
+ *
+ * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching;
+ * when stored in a table it really means that we have thus far seen no
+ * evidence to indicate what type is actually going to be stored for this entry.
+ */
+static const char acpi_gbl_bad_type[] = "UNDEFINED";
+
+/* Printable names of the ACPI object types */
+
+static const char *acpi_gbl_ns_type_names[] = {
+	/* 00 */ "Untyped",
+	/* 01 */ "Integer",
+	/* 02 */ "String",
+	/* 03 */ "Buffer",
+	/* 04 */ "Package",
+	/* 05 */ "FieldUnit",
+	/* 06 */ "Device",
+	/* 07 */ "Event",
+	/* 08 */ "Method",
+	/* 09 */ "Mutex",
+	/* 10 */ "Region",
+	/* 11 */ "Power",
+	/* 12 */ "Processor",
+	/* 13 */ "Thermal",
+	/* 14 */ "BufferField",
+	/* 15 */ "DdbHandle",
+	/* 16 */ "DebugObject",
+	/* 17 */ "RegionField",
+	/* 18 */ "BankField",
+	/* 19 */ "IndexField",
+	/* 20 */ "Reference",
+	/* 21 */ "Alias",
+	/* 22 */ "MethodAlias",
+	/* 23 */ "Notify",
+	/* 24 */ "AddrHandler",
+	/* 25 */ "ResourceDesc",
+	/* 26 */ "ResourceFld",
+	/* 27 */ "Scope",
+	/* 28 */ "Extra",
+	/* 29 */ "Data",
+	/* 30 */ "Invalid"
+};
+
+char *acpi_ut_get_type_name(acpi_object_type type)
+{
+
+	if (type > ACPI_TYPE_INVALID) {
+		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
+	}
+
+	return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type]));
+}
+
+char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
+{
+
+	if (!obj_desc) {
+		return ("[NULL Object Descriptor]");
+	}
+
+	return (acpi_ut_get_type_name(obj_desc->common.type));
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_node_name
+ *
+ * PARAMETERS:  Object               - A namespace node
+ *
+ * RETURN:      ASCII name of the node
+ *
+ * DESCRIPTION: Validate the node and return the node's ACPI name.
+ *
+ ******************************************************************************/
+
+char *acpi_ut_get_node_name(void *object)
+{
+	struct acpi_namespace_node *node = (struct acpi_namespace_node *)object;
+
+	/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
+
+	if (!object) {
+		return ("NULL");
+	}
+
+	/* Check for Root node */
+
+	if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) {
+		return ("\"\\\" ");
+	}
+
+	/* Descriptor must be a namespace node */
+
+	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
+		return ("####");
+	}
+
+	/*
+	 * Ensure name is valid. The name was validated/repaired when the node
+	 * was created, but make sure it has not been corrupted.
+	 */
+	acpi_ut_repair_name(node->name.ascii);
+
+	/* Return the name */
+
+	return (node->name.ascii);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_descriptor_name
+ *
+ * PARAMETERS:  Object               - An ACPI object
+ *
+ * RETURN:      Decoded name of the descriptor type
+ *
+ * DESCRIPTION: Validate object and return the descriptor type
+ *
+ ******************************************************************************/
+
+/* Printable names of object descriptor types */
+
+static const char *acpi_gbl_desc_type_names[] = {
+	/* 00 */ "Not a Descriptor",
+	/* 01 */ "Cached",
+	/* 02 */ "State-Generic",
+	/* 03 */ "State-Update",
+	/* 04 */ "State-Package",
+	/* 05 */ "State-Control",
+	/* 06 */ "State-RootParseScope",
+	/* 07 */ "State-ParseScope",
+	/* 08 */ "State-WalkScope",
+	/* 09 */ "State-Result",
+	/* 10 */ "State-Notify",
+	/* 11 */ "State-Thread",
+	/* 12 */ "Walk",
+	/* 13 */ "Parser",
+	/* 14 */ "Operand",
+	/* 15 */ "Node"
+};
+
+char *acpi_ut_get_descriptor_name(void *object)
+{
+
+	if (!object) {
+		return ("NULL OBJECT");
+	}
+
+	if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) {
+		return ("Not a Descriptor");
+	}
+
+	return (ACPI_CAST_PTR(char,
+			      acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE
+						       (object)]));
+
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_reference_name
+ *
+ * PARAMETERS:  Object               - An ACPI reference object
+ *
+ * RETURN:      Decoded name of the type of reference
+ *
+ * DESCRIPTION: Decode a reference object sub-type to a string.
+ *
+ ******************************************************************************/
+
+/* Printable names of reference object sub-types */
+
+static const char *acpi_gbl_ref_class_names[] = {
+	/* 00 */ "Local",
+	/* 01 */ "Argument",
+	/* 02 */ "RefOf",
+	/* 03 */ "Index",
+	/* 04 */ "DdbHandle",
+	/* 05 */ "Named Object",
+	/* 06 */ "Debug"
+};
+
+const char *acpi_ut_get_reference_name(union acpi_operand_object *object)
+{
+
+	if (!object) {
+		return ("NULL Object");
+	}
+
+	if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND) {
+		return ("Not an Operand object");
+	}
+
+	if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE) {
+		return ("Not a Reference object");
+	}
+
+	if (object->reference.class > ACPI_REFCLASS_MAX) {
+		return ("Unknown Reference class");
+	}
+
+	return (acpi_gbl_ref_class_names[object->reference.class]);
+}
+
+#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
+/*
+ * Strings and procedures used for debug only
+ */
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_mutex_name
+ *
+ * PARAMETERS:  mutex_id        - The predefined ID for this mutex.
+ *
+ * RETURN:      Decoded name of the internal mutex
+ *
+ * DESCRIPTION: Translate a mutex ID into a name string (Debug only)
+ *
+ ******************************************************************************/
+
+/* Names for internal mutex objects, used for debug output */
+
+static char *acpi_gbl_mutex_names[ACPI_NUM_MUTEX] = {
+	"ACPI_MTX_Interpreter",
+	"ACPI_MTX_Namespace",
+	"ACPI_MTX_Tables",
+	"ACPI_MTX_Events",
+	"ACPI_MTX_Caches",
+	"ACPI_MTX_Memory",
+	"ACPI_MTX_CommandComplete",
+	"ACPI_MTX_CommandReady"
+};
+
+char *acpi_ut_get_mutex_name(u32 mutex_id)
+{
+
+	if (mutex_id > ACPI_MAX_MUTEX) {
+		return ("Invalid Mutex ID");
+	}
+
+	return (acpi_gbl_mutex_names[mutex_id]);
+}
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_get_notify_name
+ *
+ * PARAMETERS:  notify_value    - Value from the Notify() request
+ *
+ * RETURN:      Decoded name for the notify value
+ *
+ * DESCRIPTION: Translate a Notify Value to a notify namestring.
+ *
+ ******************************************************************************/
+
+/* Names for Notify() values, used for debug output */
+
+static const char *acpi_gbl_notify_value_names[] = {
+	"Bus Check",
+	"Device Check",
+	"Device Wake",
+	"Eject Request",
+	"Device Check Light",
+	"Frequency Mismatch",
+	"Bus Mode Mismatch",
+	"Power Fault",
+	"Capabilities Check",
+	"Device PLD Check",
+	"Reserved",
+	"System Locality Update"
+};
+
+const char *acpi_ut_get_notify_name(u32 notify_value)
+{
+
+	if (notify_value <= ACPI_NOTIFY_MAX) {
+		return (acpi_gbl_notify_value_names[notify_value]);
+	} else if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
+		return ("Reserved");
+	} else {		/* Greater or equal to 0x80 */
+
+		return ("**Device Specific**");
+	}
+}
+#endif
+
+/*******************************************************************************
+ *
+ * FUNCTION:    acpi_ut_valid_object_type
+ *
+ * PARAMETERS:  Type            - Object type to be validated
+ *
+ * RETURN:      TRUE if valid object type, FALSE otherwise
+ *
+ * DESCRIPTION: Validate an object type
+ *
+ ******************************************************************************/
+
+u8 acpi_ut_valid_object_type(acpi_object_type type)
+{
+
+	if (type > ACPI_TYPE_LOCAL_MAX) {
+
+		/* Note: Assumes all TYPEs are contiguous (external/local) */
+
+		return (FALSE);
+	}
+
+	return (TRUE);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpica/utglobal.c linux-libre-2.6.39-gnu/drivers/acpi/acpica/utglobal.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpica/utglobal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpica/utglobal.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,6 @@
 
 #include <acpi/acpi.h>
 #include "accommon.h"
-#include "acnamesp.h"
 
 #define _COMPONENT          ACPI_UTILITIES
 ACPI_MODULE_NAME("utglobal")
@@ -107,43 +106,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_format_exception
- *
- * PARAMETERS:  Status       - The acpi_status code to be formatted
- *
- * RETURN:      A string containing the exception text. A valid pointer is
- *              always returned.
- *
- * DESCRIPTION: This function translates an ACPI exception into an ASCII string
- *              It is here instead of utxface.c so it is always present.
- *
- ******************************************************************************/
-
-const char *acpi_format_exception(acpi_status status)
-{
-	const char *exception = NULL;
-
-	ACPI_FUNCTION_ENTRY();
-
-	exception = acpi_ut_validate_exception(status);
-	if (!exception) {
-
-		/* Exception code was not recognized */
-
-		ACPI_ERROR((AE_INFO,
-			    "Unknown exception code: 0x%8.8X", status));
-
-		exception = "UNKNOWN_STATUS_CODE";
-		dump_stack();
-	}
-
-	return (ACPI_CAST_PTR(const char, exception));
-}
-
-ACPI_EXPORT_SYMBOL(acpi_format_exception)
-
-/*******************************************************************************
- *
  * Namespace globals
  *
  ******************************************************************************/
@@ -177,71 +139,6 @@
 	{NULL, ACPI_TYPE_ANY, NULL}
 };
 
-/*
- * Properties of the ACPI Object Types, both internal and external.
- * The table is indexed by values of acpi_object_type
- */
-const u8 acpi_gbl_ns_properties[] = {
-	ACPI_NS_NORMAL,		/* 00 Any              */
-	ACPI_NS_NORMAL,		/* 01 Number           */
-	ACPI_NS_NORMAL,		/* 02 String           */
-	ACPI_NS_NORMAL,		/* 03 Buffer           */
-	ACPI_NS_NORMAL,		/* 04 Package          */
-	ACPI_NS_NORMAL,		/* 05 field_unit       */
-	ACPI_NS_NEWSCOPE,	/* 06 Device           */
-	ACPI_NS_NORMAL,		/* 07 Event            */
-	ACPI_NS_NEWSCOPE,	/* 08 Method           */
-	ACPI_NS_NORMAL,		/* 09 Mutex            */
-	ACPI_NS_NORMAL,		/* 10 Region           */
-	ACPI_NS_NEWSCOPE,	/* 11 Power            */
-	ACPI_NS_NEWSCOPE,	/* 12 Processor        */
-	ACPI_NS_NEWSCOPE,	/* 13 Thermal          */
-	ACPI_NS_NORMAL,		/* 14 buffer_field     */
-	ACPI_NS_NORMAL,		/* 15 ddb_handle       */
-	ACPI_NS_NORMAL,		/* 16 Debug Object     */
-	ACPI_NS_NORMAL,		/* 17 def_field        */
-	ACPI_NS_NORMAL,		/* 18 bank_field       */
-	ACPI_NS_NORMAL,		/* 19 index_field      */
-	ACPI_NS_NORMAL,		/* 20 Reference        */
-	ACPI_NS_NORMAL,		/* 21 Alias            */
-	ACPI_NS_NORMAL,		/* 22 method_alias     */
-	ACPI_NS_NORMAL,		/* 23 Notify           */
-	ACPI_NS_NORMAL,		/* 24 Address Handler  */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 25 Resource Desc    */
-	ACPI_NS_NEWSCOPE | ACPI_NS_LOCAL,	/* 26 Resource Field   */
-	ACPI_NS_NEWSCOPE,	/* 27 Scope            */
-	ACPI_NS_NORMAL,		/* 28 Extra            */
-	ACPI_NS_NORMAL,		/* 29 Data             */
-	ACPI_NS_NORMAL		/* 30 Invalid          */
-};
-
-/* Hex to ASCII conversion table */
-
-static const char acpi_gbl_hex_to_ascii[] = {
-	'0', '1', '2', '3', '4', '5', '6', '7',
-	'8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
-};
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_hex_to_ascii_char
- *
- * PARAMETERS:  Integer             - Contains the hex digit
- *              Position            - bit position of the digit within the
- *                                    integer (multiple of 4)
- *
- * RETURN:      The converted Ascii character
- *
- * DESCRIPTION: Convert a hex digit to an Ascii character
- *
- ******************************************************************************/
-
-char acpi_ut_hex_to_ascii_char(u64 integer, u32 position)
-{
-
-	return (acpi_gbl_hex_to_ascii[(integer >> position) & 0xF]);
-}
-
 /******************************************************************************
  *
  * Event and Hardware globals
@@ -341,386 +238,6 @@
 
 /*******************************************************************************
  *
- * FUNCTION:    acpi_ut_get_region_name
- *
- * PARAMETERS:  None.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Translate a Space ID into a name string (Debug only)
- *
- ******************************************************************************/
-
-/* Region type decoding */
-
-const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS] = {
-	"SystemMemory",
-	"SystemIO",
-	"PCI_Config",
-	"EmbeddedControl",
-	"SMBus",
-	"SystemCMOS",
-	"PCIBARTarget",
-	"IPMI",
-	"DataTable"
-};
-
-char *acpi_ut_get_region_name(u8 space_id)
-{
-
-	if (space_id >= ACPI_USER_REGION_BEGIN) {
-		return ("UserDefinedRegion");
-	} else if (space_id >= ACPI_NUM_PREDEFINED_REGIONS) {
-		return ("InvalidSpaceId");
-	}
-
-	return (ACPI_CAST_PTR(char, acpi_gbl_region_types[space_id]));
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_event_name
- *
- * PARAMETERS:  None.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Translate a Event ID into a name string (Debug only)
- *
- ******************************************************************************/
-
-/* Event type decoding */
-
-static const char *acpi_gbl_event_types[ACPI_NUM_FIXED_EVENTS] = {
-	"PM_Timer",
-	"GlobalLock",
-	"PowerButton",
-	"SleepButton",
-	"RealTimeClock",
-};
-
-char *acpi_ut_get_event_name(u32 event_id)
-{
-
-	if (event_id > ACPI_EVENT_MAX) {
-		return ("InvalidEventID");
-	}
-
-	return (ACPI_CAST_PTR(char, acpi_gbl_event_types[event_id]));
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_type_name
- *
- * PARAMETERS:  None.
- *
- * RETURN:      Status
- *
- * DESCRIPTION: Translate a Type ID into a name string (Debug only)
- *
- ******************************************************************************/
-
-/*
- * Elements of acpi_gbl_ns_type_names below must match
- * one-to-one with values of acpi_object_type
- *
- * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching;
- * when stored in a table it really means that we have thus far seen no
- * evidence to indicate what type is actually going to be stored for this entry.
- */
-static const char acpi_gbl_bad_type[] = "UNDEFINED";
-
-/* Printable names of the ACPI object types */
-
-static const char *acpi_gbl_ns_type_names[] = {
-	/* 00 */ "Untyped",
-	/* 01 */ "Integer",
-	/* 02 */ "String",
-	/* 03 */ "Buffer",
-	/* 04 */ "Package",
-	/* 05 */ "FieldUnit",
-	/* 06 */ "Device",
-	/* 07 */ "Event",
-	/* 08 */ "Method",
-	/* 09 */ "Mutex",
-	/* 10 */ "Region",
-	/* 11 */ "Power",
-	/* 12 */ "Processor",
-	/* 13 */ "Thermal",
-	/* 14 */ "BufferField",
-	/* 15 */ "DdbHandle",
-	/* 16 */ "DebugObject",
-	/* 17 */ "RegionField",
-	/* 18 */ "BankField",
-	/* 19 */ "IndexField",
-	/* 20 */ "Reference",
-	/* 21 */ "Alias",
-	/* 22 */ "MethodAlias",
-	/* 23 */ "Notify",
-	/* 24 */ "AddrHandler",
-	/* 25 */ "ResourceDesc",
-	/* 26 */ "ResourceFld",
-	/* 27 */ "Scope",
-	/* 28 */ "Extra",
-	/* 29 */ "Data",
-	/* 30 */ "Invalid"
-};
-
-char *acpi_ut_get_type_name(acpi_object_type type)
-{
-
-	if (type > ACPI_TYPE_INVALID) {
-		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
-	}
-
-	return (ACPI_CAST_PTR(char, acpi_gbl_ns_type_names[type]));
-}
-
-char *acpi_ut_get_object_type_name(union acpi_operand_object *obj_desc)
-{
-
-	if (!obj_desc) {
-		return ("[NULL Object Descriptor]");
-	}
-
-	return (acpi_ut_get_type_name(obj_desc->common.type));
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_node_name
- *
- * PARAMETERS:  Object               - A namespace node
- *
- * RETURN:      Pointer to a string
- *
- * DESCRIPTION: Validate the node and return the node's ACPI name.
- *
- ******************************************************************************/
-
-char *acpi_ut_get_node_name(void *object)
-{
-	struct acpi_namespace_node *node = (struct acpi_namespace_node *)object;
-
-	/* Must return a string of exactly 4 characters == ACPI_NAME_SIZE */
-
-	if (!object) {
-		return ("NULL");
-	}
-
-	/* Check for Root node */
-
-	if ((object == ACPI_ROOT_OBJECT) || (object == acpi_gbl_root_node)) {
-		return ("\"\\\" ");
-	}
-
-	/* Descriptor must be a namespace node */
-
-	if (ACPI_GET_DESCRIPTOR_TYPE(node) != ACPI_DESC_TYPE_NAMED) {
-		return ("####");
-	}
-
-	/* Name must be a valid ACPI name */
-
-	if (!acpi_ut_valid_acpi_name(node->name.integer)) {
-		node->name.integer = acpi_ut_repair_name(node->name.ascii);
-	}
-
-	/* Return the name */
-
-	return (node->name.ascii);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_descriptor_name
- *
- * PARAMETERS:  Object               - An ACPI object
- *
- * RETURN:      Pointer to a string
- *
- * DESCRIPTION: Validate object and return the descriptor type
- *
- ******************************************************************************/
-
-/* Printable names of object descriptor types */
-
-static const char *acpi_gbl_desc_type_names[] = {
-	/* 00 */ "Invalid",
-	/* 01 */ "Cached",
-	/* 02 */ "State-Generic",
-	/* 03 */ "State-Update",
-	/* 04 */ "State-Package",
-	/* 05 */ "State-Control",
-	/* 06 */ "State-RootParseScope",
-	/* 07 */ "State-ParseScope",
-	/* 08 */ "State-WalkScope",
-	/* 09 */ "State-Result",
-	/* 10 */ "State-Notify",
-	/* 11 */ "State-Thread",
-	/* 12 */ "Walk",
-	/* 13 */ "Parser",
-	/* 14 */ "Operand",
-	/* 15 */ "Node"
-};
-
-char *acpi_ut_get_descriptor_name(void *object)
-{
-
-	if (!object) {
-		return ("NULL OBJECT");
-	}
-
-	if (ACPI_GET_DESCRIPTOR_TYPE(object) > ACPI_DESC_TYPE_MAX) {
-		return (ACPI_CAST_PTR(char, acpi_gbl_bad_type));
-	}
-
-	return (ACPI_CAST_PTR(char,
-			      acpi_gbl_desc_type_names[ACPI_GET_DESCRIPTOR_TYPE
-						       (object)]));
-
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_reference_name
- *
- * PARAMETERS:  Object               - An ACPI reference object
- *
- * RETURN:      Pointer to a string
- *
- * DESCRIPTION: Decode a reference object sub-type to a string.
- *
- ******************************************************************************/
-
-/* Printable names of reference object sub-types */
-
-static const char *acpi_gbl_ref_class_names[] = {
-	/* 00 */ "Local",
-	/* 01 */ "Argument",
-	/* 02 */ "RefOf",
-	/* 03 */ "Index",
-	/* 04 */ "DdbHandle",
-	/* 05 */ "Named Object",
-	/* 06 */ "Debug"
-};
-
-const char *acpi_ut_get_reference_name(union acpi_operand_object *object)
-{
-	if (!object)
-		return "NULL Object";
-
-	if (ACPI_GET_DESCRIPTOR_TYPE(object) != ACPI_DESC_TYPE_OPERAND)
-		return "Not an Operand object";
-
-	if (object->common.type != ACPI_TYPE_LOCAL_REFERENCE)
-		return "Not a Reference object";
-
-	if (object->reference.class > ACPI_REFCLASS_MAX)
-		return "Unknown Reference class";
-
-	return acpi_gbl_ref_class_names[object->reference.class];
-}
-
-#if defined(ACPI_DEBUG_OUTPUT) || defined(ACPI_DEBUGGER)
-/*
- * Strings and procedures used for debug only
- */
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_mutex_name
- *
- * PARAMETERS:  mutex_id        - The predefined ID for this mutex.
- *
- * RETURN:      String containing the name of the mutex. Always returns a valid
- *              pointer.
- *
- * DESCRIPTION: Translate a mutex ID into a name string (Debug only)
- *
- ******************************************************************************/
-
-char *acpi_ut_get_mutex_name(u32 mutex_id)
-{
-
-	if (mutex_id > ACPI_MAX_MUTEX) {
-		return ("Invalid Mutex ID");
-	}
-
-	return (acpi_gbl_mutex_names[mutex_id]);
-}
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_get_notify_name
- *
- * PARAMETERS:  notify_value    - Value from the Notify() request
- *
- * RETURN:      String corresponding to the Notify Value.
- *
- * DESCRIPTION: Translate a Notify Value to a notify namestring.
- *
- ******************************************************************************/
-
-/* Names for Notify() values, used for debug output */
-
-static const char *acpi_gbl_notify_value_names[] = {
-	"Bus Check",
-	"Device Check",
-	"Device Wake",
-	"Eject Request",
-	"Device Check Light",
-	"Frequency Mismatch",
-	"Bus Mode Mismatch",
-	"Power Fault",
-	"Capabilities Check",
-	"Device PLD Check",
-	"Reserved",
-	"System Locality Update"
-};
-
-const char *acpi_ut_get_notify_name(u32 notify_value)
-{
-
-	if (notify_value <= ACPI_NOTIFY_MAX) {
-		return (acpi_gbl_notify_value_names[notify_value]);
-	} else if (notify_value <= ACPI_MAX_SYS_NOTIFY) {
-		return ("Reserved");
-	} else {		/* Greater or equal to 0x80 */
-
-		return ("**Device Specific**");
-	}
-}
-#endif
-
-/*******************************************************************************
- *
- * FUNCTION:    acpi_ut_valid_object_type
- *
- * PARAMETERS:  Type            - Object type to be validated
- *
- * RETURN:      TRUE if valid object type, FALSE otherwise
- *
- * DESCRIPTION: Validate an object type
- *
- ******************************************************************************/
-
-u8 acpi_ut_valid_object_type(acpi_object_type type)
-{
-
-	if (type > ACPI_TYPE_LOCAL_MAX) {
-
-		/* Note: Assumes all TYPEs are contiguous (external/local) */
-
-		return (FALSE);
-	}
-
-	return (TRUE);
-}
-
-/*******************************************************************************
- *
  * FUNCTION:    acpi_ut_init_globals
  *
  * PARAMETERS:  None
@@ -806,6 +323,7 @@
 	acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT;
 	acpi_gbl_osi_data = 0;
 	acpi_gbl_osi_mutex = NULL;
+	acpi_gbl_reg_methods_executed = FALSE;
 
 	/* Hardware oriented */
 
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/acpi_pad.c linux-libre-2.6.39-gnu/drivers/acpi/acpi_pad.c
--- linux-libre-2.6.38-gnu/drivers/acpi/acpi_pad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/acpi_pad.c	2011-05-19 00:06:34.000000000 -0400
@@ -298,7 +298,7 @@
 static ssize_t acpi_pad_rrtime_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d", round_robin_time);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", round_robin_time);
 }
 static DEVICE_ATTR(rrtime, S_IRUGO|S_IWUSR,
 	acpi_pad_rrtime_show,
@@ -321,7 +321,7 @@
 static ssize_t acpi_pad_idlepct_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return scnprintf(buf, PAGE_SIZE, "%d", idle_pct);
+	return scnprintf(buf, PAGE_SIZE, "%d\n", idle_pct);
 }
 static DEVICE_ATTR(idlepct, S_IRUGO|S_IWUSR,
 	acpi_pad_idlepct_show,
@@ -342,8 +342,11 @@
 static ssize_t acpi_pad_idlecpus_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return cpumask_scnprintf(buf, PAGE_SIZE,
-		to_cpumask(pad_busy_cpus_bits));
+	int n = 0;
+	n = cpumask_scnprintf(buf, PAGE_SIZE-2, to_cpumask(pad_busy_cpus_bits));
+	buf[n++] = '\n';
+	buf[n] = '\0';
+	return n;
 }
 static DEVICE_ATTR(idlecpus, S_IRUGO|S_IWUSR,
 	acpi_pad_idlecpus_show,
@@ -453,7 +456,7 @@
 			dev_name(&device->dev), event, 0);
 		break;
 	default:
-		printk(KERN_WARNING"Unsupported event [0x%x]\n", event);
+		printk(KERN_WARNING "Unsupported event [0x%x]\n", event);
 		break;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/apei/cper.c linux-libre-2.6.39-gnu/drivers/acpi/apei/cper.c
--- linux-libre-2.6.38-gnu/drivers/acpi/apei/cper.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/apei/cper.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/time.h>
 #include <linux/cper.h>
 #include <linux/acpi.h>
+#include <linux/aer.h>
 
 /*
  * CPER record ID need to be unique even after reboot, because record
@@ -70,8 +71,8 @@
  * If the output length is longer than 80, multiple line will be
  * printed, with @pfx is printed at the beginning of each line.
  */
-static void cper_print_bits(const char *pfx, unsigned int bits,
-			    const char *strs[], unsigned int strs_size)
+void cper_print_bits(const char *pfx, unsigned int bits,
+		     const char *strs[], unsigned int strs_size)
 {
 	int i, len = 0;
 	const char *str;
@@ -81,6 +82,8 @@
 		if (!(bits & (1U << i)))
 			continue;
 		str = strs[i];
+		if (!str)
+			continue;
 		if (len && len + strlen(str) + 2 > 80) {
 			printk("%s\n", buf);
 			len = 0;
@@ -243,7 +246,8 @@
 	"root complex event collector",
 };
 
-static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie)
+static void cper_print_pcie(const char *pfx, const struct cper_sec_pcie *pcie,
+			    const struct acpi_hest_generic_data *gdata)
 {
 	if (pcie->validation_bits & CPER_PCIE_VALID_PORT_TYPE)
 		printk("%s""port_type: %d, %s\n", pfx, pcie->port_type,
@@ -276,6 +280,12 @@
 		printk(
 	"%s""bridge: secondary_status: 0x%04x, control: 0x%04x\n",
 	pfx, pcie->bridge.secondary_status, pcie->bridge.control);
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+	if (pcie->validation_bits & CPER_PCIE_VALID_AER_INFO) {
+		struct aer_capability_regs *aer_regs = (void *)pcie->aer_info;
+		cper_print_aer(pfx, gdata->error_severity, aer_regs);
+	}
+#endif
 }
 
 static const char *apei_estatus_section_flag_strs[] = {
@@ -322,7 +332,7 @@
 		struct cper_sec_pcie *pcie = (void *)(gdata + 1);
 		printk("%s""section_type: PCIe error\n", pfx);
 		if (gdata->error_data_length >= sizeof(*pcie))
-			cper_print_pcie(pfx, pcie);
+			cper_print_pcie(pfx, pcie, gdata);
 		else
 			goto err_section_too_small;
 	} else
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/apei/erst.c linux-libre-2.6.39-gnu/drivers/acpi/apei/erst.c
--- linux-libre-2.6.38-gnu/drivers/acpi/apei/erst.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/apei/erst.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/cper.h>
 #include <linux/nmi.h>
 #include <linux/hardirq.h>
+#include <linux/pstore.h>
 #include <acpi/apei.h>
 
 #include "apei-internal.h"
@@ -429,6 +430,22 @@
 }
 EXPORT_SYMBOL_GPL(erst_get_record_count);
 
+#define ERST_RECORD_ID_CACHE_SIZE_MIN	16
+#define ERST_RECORD_ID_CACHE_SIZE_MAX	1024
+
+struct erst_record_id_cache {
+	struct mutex lock;
+	u64 *entries;
+	int len;
+	int size;
+	int refcount;
+};
+
+static struct erst_record_id_cache erst_record_id_cache = {
+	.lock = __MUTEX_INITIALIZER(erst_record_id_cache.lock),
+	.refcount = 0,
+};
+
 static int __erst_get_next_record_id(u64 *record_id)
 {
 	struct apei_exec_context ctx;
@@ -443,26 +460,179 @@
 	return 0;
 }
 
+int erst_get_record_id_begin(int *pos)
+{
+	int rc;
+
+	if (erst_disable)
+		return -ENODEV;
+
+	rc = mutex_lock_interruptible(&erst_record_id_cache.lock);
+	if (rc)
+		return rc;
+	erst_record_id_cache.refcount++;
+	mutex_unlock(&erst_record_id_cache.lock);
+
+	*pos = 0;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(erst_get_record_id_begin);
+
+/* erst_record_id_cache.lock must be held by caller */
+static int __erst_record_id_cache_add_one(void)
+{
+	u64 id, prev_id, first_id;
+	int i, rc;
+	u64 *entries;
+	unsigned long flags;
+
+	id = prev_id = first_id = APEI_ERST_INVALID_RECORD_ID;
+retry:
+	raw_spin_lock_irqsave(&erst_lock, flags);
+	rc = __erst_get_next_record_id(&id);
+	raw_spin_unlock_irqrestore(&erst_lock, flags);
+	if (rc == -ENOENT)
+		return 0;
+	if (rc)
+		return rc;
+	if (id == APEI_ERST_INVALID_RECORD_ID)
+		return 0;
+	/* can not skip current ID, or loop back to first ID */
+	if (id == prev_id || id == first_id)
+		return 0;
+	if (first_id == APEI_ERST_INVALID_RECORD_ID)
+		first_id = id;
+	prev_id = id;
+
+	entries = erst_record_id_cache.entries;
+	for (i = 0; i < erst_record_id_cache.len; i++) {
+		if (entries[i] == id)
+			break;
+	}
+	/* record id already in cache, try next */
+	if (i < erst_record_id_cache.len)
+		goto retry;
+	if (erst_record_id_cache.len >= erst_record_id_cache.size) {
+		int new_size, alloc_size;
+		u64 *new_entries;
+
+		new_size = erst_record_id_cache.size * 2;
+		new_size = clamp_val(new_size, ERST_RECORD_ID_CACHE_SIZE_MIN,
+				     ERST_RECORD_ID_CACHE_SIZE_MAX);
+		if (new_size <= erst_record_id_cache.size) {
+			if (printk_ratelimit())
+				pr_warning(FW_WARN ERST_PFX
+					   "too many record ID!\n");
+			return 0;
+		}
+		alloc_size = new_size * sizeof(entries[0]);
+		if (alloc_size < PAGE_SIZE)
+			new_entries = kmalloc(alloc_size, GFP_KERNEL);
+		else
+			new_entries = vmalloc(alloc_size);
+		if (!new_entries)
+			return -ENOMEM;
+		memcpy(new_entries, entries,
+		       erst_record_id_cache.len * sizeof(entries[0]));
+		if (erst_record_id_cache.size < PAGE_SIZE)
+			kfree(entries);
+		else
+			vfree(entries);
+		erst_record_id_cache.entries = entries = new_entries;
+		erst_record_id_cache.size = new_size;
+	}
+	entries[i] = id;
+	erst_record_id_cache.len++;
+
+	return 1;
+}
+
 /*
  * Get the record ID of an existing error record on the persistent
  * storage. If there is no error record on the persistent storage, the
  * returned record_id is APEI_ERST_INVALID_RECORD_ID.
  */
-int erst_get_next_record_id(u64 *record_id)
+int erst_get_record_id_next(int *pos, u64 *record_id)
 {
-	int rc;
-	unsigned long flags;
+	int rc = 0;
+	u64 *entries;
 
 	if (erst_disable)
 		return -ENODEV;
 
-	raw_spin_lock_irqsave(&erst_lock, flags);
-	rc = __erst_get_next_record_id(record_id);
-	raw_spin_unlock_irqrestore(&erst_lock, flags);
+	/* must be enclosed by erst_get_record_id_begin/end */
+	BUG_ON(!erst_record_id_cache.refcount);
+	BUG_ON(*pos < 0 || *pos > erst_record_id_cache.len);
+
+	mutex_lock(&erst_record_id_cache.lock);
+	entries = erst_record_id_cache.entries;
+	for (; *pos < erst_record_id_cache.len; (*pos)++)
+		if (entries[*pos] != APEI_ERST_INVALID_RECORD_ID)
+			break;
+	/* found next record id in cache */
+	if (*pos < erst_record_id_cache.len) {
+		*record_id = entries[*pos];
+		(*pos)++;
+		goto out_unlock;
+	}
+
+	/* Try to add one more record ID to cache */
+	rc = __erst_record_id_cache_add_one();
+	if (rc < 0)
+		goto out_unlock;
+	/* successfully add one new ID */
+	if (rc == 1) {
+		*record_id = erst_record_id_cache.entries[*pos];
+		(*pos)++;
+		rc = 0;
+	} else {
+		*pos = -1;
+		*record_id = APEI_ERST_INVALID_RECORD_ID;
+	}
+out_unlock:
+	mutex_unlock(&erst_record_id_cache.lock);
 
 	return rc;
 }
-EXPORT_SYMBOL_GPL(erst_get_next_record_id);
+EXPORT_SYMBOL_GPL(erst_get_record_id_next);
+
+/* erst_record_id_cache.lock must be held by caller */
+static void __erst_record_id_cache_compact(void)
+{
+	int i, wpos = 0;
+	u64 *entries;
+
+	if (erst_record_id_cache.refcount)
+		return;
+
+	entries = erst_record_id_cache.entries;
+	for (i = 0; i < erst_record_id_cache.len; i++) {
+		if (entries[i] == APEI_ERST_INVALID_RECORD_ID)
+			continue;
+		if (wpos != i)
+			memcpy(&entries[wpos], &entries[i], sizeof(entries[i]));
+		wpos++;
+	}
+	erst_record_id_cache.len = wpos;
+}
+
+void erst_get_record_id_end(void)
+{
+	/*
+	 * erst_disable != 0 should be detected by invoker via the
+	 * return value of erst_get_record_id_begin/next, so this
+	 * function should not be called for erst_disable != 0.
+	 */
+	BUG_ON(erst_disable);
+
+	mutex_lock(&erst_record_id_cache.lock);
+	erst_record_id_cache.refcount--;
+	BUG_ON(erst_record_id_cache.refcount < 0);
+	__erst_record_id_cache_compact();
+	mutex_unlock(&erst_record_id_cache.lock);
+}
+EXPORT_SYMBOL_GPL(erst_get_record_id_end);
 
 static int __erst_write_to_storage(u64 offset)
 {
@@ -703,56 +873,34 @@
 }
 EXPORT_SYMBOL_GPL(erst_read);
 
-/*
- * If return value > buflen, the buffer size is not big enough,
- * else if return value = 0, there is no more record to read,
- * else if return value < 0, something goes wrong,
- * else everything is OK, and return value is record length
- */
-ssize_t erst_read_next(struct cper_record_header *record, size_t buflen)
-{
-	int rc;
-	ssize_t len;
-	unsigned long flags;
-	u64 record_id;
-
-	if (erst_disable)
-		return -ENODEV;
-
-	raw_spin_lock_irqsave(&erst_lock, flags);
-	rc = __erst_get_next_record_id(&record_id);
-	if (rc) {
-		raw_spin_unlock_irqrestore(&erst_lock, flags);
-		return rc;
-	}
-	/* no more record */
-	if (record_id == APEI_ERST_INVALID_RECORD_ID) {
-		raw_spin_unlock_irqrestore(&erst_lock, flags);
-		return 0;
-	}
-
-	len = __erst_read(record_id, record, buflen);
-	raw_spin_unlock_irqrestore(&erst_lock, flags);
-
-	return len;
-}
-EXPORT_SYMBOL_GPL(erst_read_next);
-
 int erst_clear(u64 record_id)
 {
-	int rc;
+	int rc, i;
 	unsigned long flags;
+	u64 *entries;
 
 	if (erst_disable)
 		return -ENODEV;
 
+	rc = mutex_lock_interruptible(&erst_record_id_cache.lock);
+	if (rc)
+		return rc;
 	raw_spin_lock_irqsave(&erst_lock, flags);
 	if (erst_erange.attr & ERST_RANGE_NVRAM)
 		rc = __erst_clear_from_nvram(record_id);
 	else
 		rc = __erst_clear_from_storage(record_id);
 	raw_spin_unlock_irqrestore(&erst_lock, flags);
-
+	if (rc)
+		goto out;
+	entries = erst_record_id_cache.entries;
+	for (i = 0; i < erst_record_id_cache.len; i++) {
+		if (entries[i] == record_id)
+			entries[i] = APEI_ERST_INVALID_RECORD_ID;
+	}
+	__erst_record_id_cache_compact();
+out:
+	mutex_unlock(&erst_record_id_cache.lock);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(erst_clear);
@@ -781,6 +929,128 @@
 	return 0;
 }
 
+static size_t erst_reader(u64 *id, enum pstore_type_id *type,
+		       struct timespec *time);
+static u64 erst_writer(enum pstore_type_id type, size_t size);
+
+static struct pstore_info erst_info = {
+	.owner		= THIS_MODULE,
+	.name		= "erst",
+	.read		= erst_reader,
+	.write		= erst_writer,
+	.erase		= erst_clear
+};
+
+#define CPER_CREATOR_PSTORE						\
+	UUID_LE(0x75a574e3, 0x5052, 0x4b29, 0x8a, 0x8e, 0xbe, 0x2c,	\
+		0x64, 0x90, 0xb8, 0x9d)
+#define CPER_SECTION_TYPE_DMESG						\
+	UUID_LE(0xc197e04e, 0xd545, 0x4a70, 0x9c, 0x17, 0xa5, 0x54,	\
+		0x94, 0x19, 0xeb, 0x12)
+#define CPER_SECTION_TYPE_MCE						\
+	UUID_LE(0xfe08ffbe, 0x95e4, 0x4be7, 0xbc, 0x73, 0x40, 0x96,	\
+		0x04, 0x4a, 0x38, 0xfc)
+
+struct cper_pstore_record {
+	struct cper_record_header hdr;
+	struct cper_section_descriptor sec_hdr;
+	char data[];
+} __packed;
+
+static size_t erst_reader(u64 *id, enum pstore_type_id *type,
+		       struct timespec *time)
+{
+	int rc;
+	ssize_t len;
+	unsigned long flags;
+	u64 record_id;
+	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
+					(erst_info.buf - sizeof(*rcd));
+
+	if (erst_disable)
+		return -ENODEV;
+
+	raw_spin_lock_irqsave(&erst_lock, flags);
+skip:
+	rc = __erst_get_next_record_id(&record_id);
+	if (rc) {
+		raw_spin_unlock_irqrestore(&erst_lock, flags);
+		return rc;
+	}
+	/* no more record */
+	if (record_id == APEI_ERST_INVALID_RECORD_ID) {
+		raw_spin_unlock_irqrestore(&erst_lock, flags);
+		return 0;
+	}
+
+	len = __erst_read(record_id, &rcd->hdr, sizeof(*rcd) +
+			  erst_erange.size);
+	if (uuid_le_cmp(rcd->hdr.creator_id, CPER_CREATOR_PSTORE) != 0)
+		goto skip;
+	raw_spin_unlock_irqrestore(&erst_lock, flags);
+
+	*id = record_id;
+	if (uuid_le_cmp(rcd->sec_hdr.section_type,
+			CPER_SECTION_TYPE_DMESG) == 0)
+		*type = PSTORE_TYPE_DMESG;
+	else if (uuid_le_cmp(rcd->sec_hdr.section_type,
+			     CPER_SECTION_TYPE_MCE) == 0)
+		*type = PSTORE_TYPE_MCE;
+	else
+		*type = PSTORE_TYPE_UNKNOWN;
+
+	if (rcd->hdr.validation_bits & CPER_VALID_TIMESTAMP)
+		time->tv_sec = rcd->hdr.timestamp;
+	else
+		time->tv_sec = 0;
+	time->tv_nsec = 0;
+
+	return len - sizeof(*rcd);
+}
+
+static u64 erst_writer(enum pstore_type_id type, size_t size)
+{
+	struct cper_pstore_record *rcd = (struct cper_pstore_record *)
+					(erst_info.buf - sizeof(*rcd));
+
+	memset(rcd, 0, sizeof(*rcd));
+	memcpy(rcd->hdr.signature, CPER_SIG_RECORD, CPER_SIG_SIZE);
+	rcd->hdr.revision = CPER_RECORD_REV;
+	rcd->hdr.signature_end = CPER_SIG_END;
+	rcd->hdr.section_count = 1;
+	rcd->hdr.error_severity = CPER_SEV_FATAL;
+	/* timestamp valid. platform_id, partition_id are invalid */
+	rcd->hdr.validation_bits = CPER_VALID_TIMESTAMP;
+	rcd->hdr.timestamp = get_seconds();
+	rcd->hdr.record_length = sizeof(*rcd) + size;
+	rcd->hdr.creator_id = CPER_CREATOR_PSTORE;
+	rcd->hdr.notification_type = CPER_NOTIFY_MCE;
+	rcd->hdr.record_id = cper_next_record_id();
+	rcd->hdr.flags = CPER_HW_ERROR_FLAGS_PREVERR;
+
+	rcd->sec_hdr.section_offset = sizeof(*rcd);
+	rcd->sec_hdr.section_length = size;
+	rcd->sec_hdr.revision = CPER_SEC_REV;
+	/* fru_id and fru_text is invalid */
+	rcd->sec_hdr.validation_bits = 0;
+	rcd->sec_hdr.flags = CPER_SEC_PRIMARY;
+	switch (type) {
+	case PSTORE_TYPE_DMESG:
+		rcd->sec_hdr.section_type = CPER_SECTION_TYPE_DMESG;
+		break;
+	case PSTORE_TYPE_MCE:
+		rcd->sec_hdr.section_type = CPER_SECTION_TYPE_MCE;
+		break;
+	default:
+		return -EINVAL;
+	}
+	rcd->sec_hdr.section_severity = CPER_SEV_FATAL;
+
+	erst_write(&rcd->hdr);
+
+	return rcd->hdr.record_id;
+}
+
 static int __init erst_init(void)
 {
 	int rc = 0;
@@ -788,6 +1058,7 @@
 	struct apei_exec_context ctx;
 	struct apei_resources erst_resources;
 	struct resource *r;
+	char *buf;
 
 	if (acpi_disabled)
 		goto err;
@@ -854,6 +1125,18 @@
 	if (!erst_erange.vaddr)
 		goto err_release_erange;
 
+	buf = kmalloc(erst_erange.size, GFP_KERNEL);
+	mutex_init(&erst_info.buf_mutex);
+	if (buf) {
+		erst_info.buf = buf + sizeof(struct cper_pstore_record);
+		erst_info.bufsize = erst_erange.size -
+				    sizeof(struct cper_pstore_record);
+		if (pstore_register(&erst_info)) {
+			pr_info(ERST_PFX "Could not register with persistent store\n");
+			kfree(buf);
+		}
+	}
+
 	pr_info(ERST_PFX
 	"Error Record Serialization Table (ERST) support is initialized.\n");
 
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/apei/erst-dbg.c linux-libre-2.6.39-gnu/drivers/acpi/apei/erst-dbg.c
--- linux-libre-2.6.38-gnu/drivers/acpi/apei/erst-dbg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/apei/erst-dbg.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,12 +43,27 @@
 
 static int erst_dbg_open(struct inode *inode, struct file *file)
 {
+	int rc, *pos;
+
 	if (erst_disable)
 		return -ENODEV;
 
+	pos = (int *)&file->private_data;
+
+	rc = erst_get_record_id_begin(pos);
+	if (rc)
+		return rc;
+
 	return nonseekable_open(inode, file);
 }
 
+static int erst_dbg_release(struct inode *inode, struct file *file)
+{
+	erst_get_record_id_end();
+
+	return 0;
+}
+
 static long erst_dbg_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
 {
 	int rc;
@@ -79,18 +94,20 @@
 static ssize_t erst_dbg_read(struct file *filp, char __user *ubuf,
 			     size_t usize, loff_t *off)
 {
-	int rc;
+	int rc, *pos;
 	ssize_t len = 0;
 	u64 id;
 
-	if (*off != 0)
+	if (*off)
 		return -EINVAL;
 
 	if (mutex_lock_interruptible(&erst_dbg_mutex) != 0)
 		return -EINTR;
 
+	pos = (int *)&filp->private_data;
+
 retry_next:
-	rc = erst_get_next_record_id(&id);
+	rc = erst_get_record_id_next(pos, &id);
 	if (rc)
 		goto out;
 	/* no more record */
@@ -181,6 +198,7 @@
 static const struct file_operations erst_dbg_ops = {
 	.owner		= THIS_MODULE,
 	.open		= erst_dbg_open,
+	.release	= erst_dbg_release,
 	.read		= erst_dbg_read,
 	.write		= erst_dbg_write,
 	.unlocked_ioctl	= erst_dbg_ioctl,
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/apei/ghes.c linux-libre-2.6.39-gnu/drivers/acpi/apei/ghes.c
--- linux-libre-2.6.38-gnu/drivers/acpi/apei/ghes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/apei/ghes.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,7 +241,7 @@
 	case CPER_SEV_FATAL:
 		return GHES_SEV_PANIC;
 	default:
-		/* Unkown, go panic */
+		/* Unknown, go panic */
 		return GHES_SEV_PANIC;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/apei/Kconfig linux-libre-2.6.39-gnu/drivers/acpi/apei/Kconfig
--- linux-libre-2.6.38-gnu/drivers/acpi/apei/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/apei/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,6 @@
 config ACPI_APEI
 	bool "ACPI Platform Error Interface (APEI)"
+	select PSTORE
 	depends on X86
 	help
 	  APEI allows to report errors (for example from the chipset)
@@ -21,6 +22,13 @@
 	  by firmware to produce more valuable hardware error
 	  information for Linux.
 
+config ACPI_APEI_PCIEAER
+	bool "APEI PCIe AER logging/recovering support"
+	depends on ACPI_APEI && PCIEAER
+	help
+	  PCIe AER errors may be reported via APEI firmware first mode.
+	  Turn on this option to enable the corresponding support.
+
 config ACPI_APEI_EINJ
 	tristate "APEI Error INJection (EINJ)"
 	depends on ACPI_APEI && DEBUG_FS
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/battery.c linux-libre-2.6.39-gnu/drivers/acpi/battery.c
--- linux-libre-2.6.38-gnu/drivers/acpi/battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/battery.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,7 @@
 #include <linux/async.h>
 #include <linux/dmi.h>
 #include <linux/slab.h>
+#include <linux/suspend.h>
 
 #ifdef CONFIG_ACPI_PROCFS_POWER
 #include <linux/proc_fs.h>
@@ -102,6 +103,7 @@
 	struct mutex lock;
 	struct power_supply bat;
 	struct acpi_device *device;
+	struct notifier_block pm_nb;
 	unsigned long update_time;
 	int rate_now;
 	int capacity_now;
@@ -940,6 +942,21 @@
 		power_supply_changed(&battery->bat);
 }
 
+static int battery_notify(struct notifier_block *nb,
+			       unsigned long mode, void *_unused)
+{
+	struct acpi_battery *battery = container_of(nb, struct acpi_battery,
+						    pm_nb);
+	switch (mode) {
+	case PM_POST_SUSPEND:
+		sysfs_remove_battery(battery);
+		sysfs_add_battery(battery);
+		break;
+	}
+
+	return 0;
+}
+
 static int acpi_battery_add(struct acpi_device *device)
 {
 	int result = 0;
@@ -972,6 +989,10 @@
 #endif
 		kfree(battery);
 	}
+
+	battery->pm_nb.notifier_call = battery_notify;
+	register_pm_notifier(&battery->pm_nb);
+
 	return result;
 }
 
@@ -982,6 +1003,7 @@
 	if (!device || !acpi_driver_data(device))
 		return -EINVAL;
 	battery = acpi_driver_data(device);
+	unregister_pm_notifier(&battery->pm_nb);
 #ifdef CONFIG_ACPI_PROCFS_POWER
 	acpi_battery_remove_fs(device);
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/bus.c linux-libre-2.6.39-gnu/drivers/acpi/bus.c
--- linux-libre-2.6.38-gnu/drivers/acpi/bus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/bus.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
 #include <linux/dmi.h>
+#include <linux/suspend.h>
 
 #include "internal.h"
 
@@ -1006,8 +1007,7 @@
 
 static int __init acpi_init(void)
 {
-	int result = 0;
-
+	int result;
 
 	if (acpi_disabled) {
 		printk(KERN_INFO PREFIX "Interpreter disabled.\n");
@@ -1022,29 +1022,18 @@
 
 	init_acpi_device_notify();
 	result = acpi_bus_init();
-
-	if (!result) {
-		pci_mmcfg_late_init();
-		if (!(pm_flags & PM_APM))
-			pm_flags |= PM_ACPI;
-		else {
-			printk(KERN_INFO PREFIX
-			       "APM is already active, exiting\n");
-			disable_acpi();
-			result = -ENODEV;
-		}
-	} else
+	if (result) {
 		disable_acpi();
-
-	if (acpi_disabled)
 		return result;
+	}
 
+	pci_mmcfg_late_init();
 	acpi_scan_init();
 	acpi_ec_init();
 	acpi_debugfs_init();
 	acpi_sleep_proc_init();
 	acpi_wakeup_device_init();
-	return result;
+	return 0;
 }
 
 subsys_initcall(acpi_init);
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/button.c linux-libre-2.6.39-gnu/drivers/acpi/button.c
--- linux-libre-2.6.38-gnu/drivers/acpi/button.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/button.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,8 +78,6 @@
 static int acpi_button_remove(struct acpi_device *device, int type);
 static int acpi_button_resume(struct acpi_device *device);
 static void acpi_button_notify(struct acpi_device *device, u32 event);
-static int acpi_button_info_open_fs(struct inode *inode, struct file *file);
-static int acpi_button_state_open_fs(struct inode *inode, struct file *file);
 
 static struct acpi_driver acpi_button_driver = {
 	.name = "button",
@@ -98,22 +96,7 @@
 	struct input_dev *input;
 	char phys[32];			/* for input device */
 	unsigned long pushed;
-};
-
-static const struct file_operations acpi_button_info_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_button_info_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static const struct file_operations acpi_button_state_fops = {
-	.owner = THIS_MODULE,
-	.open = acpi_button_state_open_fs,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
+	bool wakeup_enabled;
 };
 
 static BLOCKING_NOTIFIER_HEAD(acpi_lid_notifier);
@@ -124,20 +107,7 @@
    -------------------------------------------------------------------------- */
 
 static struct proc_dir_entry *acpi_button_dir;
-
-static int acpi_button_info_seq_show(struct seq_file *seq, void *offset)
-{
-	struct acpi_device *device = seq->private;
-
-	seq_printf(seq, "type:                    %s\n",
-		   acpi_device_name(device));
-	return 0;
-}
-
-static int acpi_button_info_open_fs(struct inode *inode, struct file *file)
-{
-	return single_open(file, acpi_button_info_seq_show, PDE(inode)->data);
-}
+static struct proc_dir_entry *acpi_lid_dir;
 
 static int acpi_button_state_seq_show(struct seq_file *seq, void *offset)
 {
@@ -157,77 +127,85 @@
 	return single_open(file, acpi_button_state_seq_show, PDE(inode)->data);
 }
 
-static struct proc_dir_entry *acpi_power_dir;
-static struct proc_dir_entry *acpi_sleep_dir;
-static struct proc_dir_entry *acpi_lid_dir;
+static const struct file_operations acpi_button_state_fops = {
+	.owner = THIS_MODULE,
+	.open = acpi_button_state_open_fs,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
 
 static int acpi_button_add_fs(struct acpi_device *device)
 {
 	struct acpi_button *button = acpi_driver_data(device);
 	struct proc_dir_entry *entry = NULL;
+	int ret = 0;
 
-	switch (button->type) {
-	case ACPI_BUTTON_TYPE_POWER:
-		if (!acpi_power_dir)
-			acpi_power_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_POWER,
-						    acpi_button_dir);
-		entry = acpi_power_dir;
-		break;
-	case ACPI_BUTTON_TYPE_SLEEP:
-		if (!acpi_sleep_dir)
-			acpi_sleep_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_SLEEP,
-						    acpi_button_dir);
-		entry = acpi_sleep_dir;
-		break;
-	case ACPI_BUTTON_TYPE_LID:
-		if (!acpi_lid_dir)
-			acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID,
-						  acpi_button_dir);
-		entry = acpi_lid_dir;
-		break;
+	/* procfs I/F for ACPI lid device only */
+	if (button->type != ACPI_BUTTON_TYPE_LID)
+		return 0;
+
+	if (acpi_button_dir || acpi_lid_dir) {
+		printk(KERN_ERR PREFIX "More than one Lid device found!\n");
+		return -EEXIST;
 	}
 
-	if (!entry)
+	/* create /proc/acpi/button */
+	acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
+	if (!acpi_button_dir)
 		return -ENODEV;
 
-	acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), entry);
-	if (!acpi_device_dir(device))
-		return -ENODEV;
+	/* create /proc/acpi/button/lid */
+	acpi_lid_dir = proc_mkdir(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+	if (!acpi_lid_dir) {
+		ret = -ENODEV;
+		goto remove_button_dir;
+	}
 
-	/* 'info' [R] */
-	entry = proc_create_data(ACPI_BUTTON_FILE_INFO,
-				 S_IRUGO, acpi_device_dir(device),
-				 &acpi_button_info_fops, device);
-	if (!entry)
-		return -ENODEV;
+	/* create /proc/acpi/button/lid/LID/ */
+	acpi_device_dir(device) = proc_mkdir(acpi_device_bid(device), acpi_lid_dir);
+	if (!acpi_device_dir(device)) {
+		ret = -ENODEV;
+		goto remove_lid_dir;
+	}
 
-	/* show lid state [R] */
-	if (button->type == ACPI_BUTTON_TYPE_LID) {
-		entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
-					 S_IRUGO, acpi_device_dir(device),
-					 &acpi_button_state_fops, device);
-		if (!entry)
-			return -ENODEV;
+	/* create /proc/acpi/button/lid/LID/state */
+	entry = proc_create_data(ACPI_BUTTON_FILE_STATE,
+				 S_IRUGO, acpi_device_dir(device),
+				 &acpi_button_state_fops, device);
+	if (!entry) {
+		ret = -ENODEV;
+		goto remove_dev_dir;
 	}
 
-	return 0;
+done:
+	return ret;
+
+remove_dev_dir:
+	remove_proc_entry(acpi_device_bid(device),
+			  acpi_lid_dir);
+	acpi_device_dir(device) = NULL;
+remove_lid_dir:
+	remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+remove_button_dir:
+	remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
+	goto done;
 }
 
 static int acpi_button_remove_fs(struct acpi_device *device)
 {
 	struct acpi_button *button = acpi_driver_data(device);
 
-	if (acpi_device_dir(device)) {
-		if (button->type == ACPI_BUTTON_TYPE_LID)
-			remove_proc_entry(ACPI_BUTTON_FILE_STATE,
-					  acpi_device_dir(device));
-		remove_proc_entry(ACPI_BUTTON_FILE_INFO,
-				  acpi_device_dir(device));
+	if (button->type != ACPI_BUTTON_TYPE_LID)
+		return 0;
 
-		remove_proc_entry(acpi_device_bid(device),
-				  acpi_device_dir(device)->parent);
-		acpi_device_dir(device) = NULL;
-	}
+	remove_proc_entry(ACPI_BUTTON_FILE_STATE,
+			  acpi_device_dir(device));
+	remove_proc_entry(acpi_device_bid(device),
+			  acpi_lid_dir);
+	acpi_device_dir(device) = NULL;
+	remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
+	remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
 
 	return 0;
 }
@@ -430,8 +408,10 @@
 		/* Button's GPE is run-wake GPE */
 		acpi_enable_gpe(device->wakeup.gpe_device,
 				device->wakeup.gpe_number);
-		device->wakeup.run_wake_count++;
-		device_set_wakeup_enable(&device->dev, true);
+		if (!device_may_wakeup(&device->dev)) {
+			device_set_wakeup_enable(&device->dev, true);
+			button->wakeup_enabled = true;
+		}
 	}
 
 	printk(KERN_INFO PREFIX "%s [%s]\n", name, acpi_device_bid(device));
@@ -453,8 +433,8 @@
 	if (device->wakeup.flags.valid) {
 		acpi_disable_gpe(device->wakeup.gpe_device,
 				device->wakeup.gpe_number);
-		device->wakeup.run_wake_count--;
-		device_set_wakeup_enable(&device->dev, false);
+		if (button->wakeup_enabled)
+			device_set_wakeup_enable(&device->dev, false);
 	}
 
 	acpi_button_remove_fs(device);
@@ -465,32 +445,12 @@
 
 static int __init acpi_button_init(void)
 {
-	int result;
-
-	acpi_button_dir = proc_mkdir(ACPI_BUTTON_CLASS, acpi_root_dir);
-	if (!acpi_button_dir)
-		return -ENODEV;
-
-	result = acpi_bus_register_driver(&acpi_button_driver);
-	if (result < 0) {
-		remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
-		return -ENODEV;
-	}
-
-	return 0;
+	return acpi_bus_register_driver(&acpi_button_driver);
 }
 
 static void __exit acpi_button_exit(void)
 {
 	acpi_bus_unregister_driver(&acpi_button_driver);
-
-	if (acpi_power_dir)
-		remove_proc_entry(ACPI_BUTTON_SUBCLASS_POWER, acpi_button_dir);
-	if (acpi_sleep_dir)
-		remove_proc_entry(ACPI_BUTTON_SUBCLASS_SLEEP, acpi_button_dir);
-	if (acpi_lid_dir)
-		remove_proc_entry(ACPI_BUTTON_SUBCLASS_LID, acpi_button_dir);
-	remove_proc_entry(ACPI_BUTTON_CLASS, acpi_root_dir);
 }
 
 module_init(acpi_button_init);
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/ec_sys.c linux-libre-2.6.39-gnu/drivers/acpi/ec_sys.c
--- linux-libre-2.6.38-gnu/drivers/acpi/ec_sys.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/ec_sys.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,10 +24,6 @@
 
 #define EC_SPACE_SIZE 256
 
-struct sysdev_class acpi_ec_sysdev_class = {
-	.name = "ec",
-};
-
 static struct dentry *acpi_ec_debugfs_dir;
 
 static int acpi_ec_open_io(struct inode *i, struct file *f)
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/internal.h linux-libre-2.6.39-gnu/drivers/acpi/internal.h
--- linux-libre-2.6.38-gnu/drivers/acpi/internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,8 +21,6 @@
 #ifndef _ACPI_INTERNAL_H_
 #define _ACPI_INTERNAL_H_
 
-#include <linux/sysdev.h>
-
 #define PREFIX "ACPI: "
 
 int init_acpi_device_notify(void);
@@ -64,7 +62,6 @@
 	struct list_head list;
 	struct transaction *curr;
 	spinlock_t curr_lock;
-	struct sys_device sysdev;
 };
 
 extern struct acpi_ec *first_ec;
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/Kconfig linux-libre-2.6.39-gnu/drivers/acpi/Kconfig
--- linux-libre-2.6.38-gnu/drivers/acpi/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,6 @@
 	depends on !IA64_HP_SIM
 	depends on IA64 || X86
 	depends on PCI
-	depends on PM
 	select PNP
 	default y
 	help
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/numa.c linux-libre-2.6.39-gnu/drivers/acpi/numa.c
--- linux-libre-2.6.38-gnu/drivers/acpi/numa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/numa.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,7 +274,7 @@
 
 int __init acpi_numa_init(void)
 {
-	int ret = 0;
+	int cnt = 0;
 
 	/*
 	 * Should not limit number with cpu num that is from NR_CPUS or nr_cpus=
@@ -288,7 +288,7 @@
 				     acpi_parse_x2apic_affinity, 0);
 		acpi_table_parse_srat(ACPI_SRAT_TYPE_CPU_AFFINITY,
 				     acpi_parse_processor_affinity, 0);
-		ret = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
+		cnt = acpi_table_parse_srat(ACPI_SRAT_TYPE_MEMORY_AFFINITY,
 					    acpi_parse_memory_affinity,
 					    NR_NODE_MEMBLKS);
 	}
@@ -297,7 +297,10 @@
 	acpi_table_parse(ACPI_SIG_SLIT, acpi_parse_slit);
 
 	acpi_numa_arch_fixup();
-	return ret;
+
+	if (cnt <= 0)
+		return cnt ?: -ENOENT;
+	return 0;
 }
 
 int acpi_get_pxm(acpi_handle h)
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/nvs.c linux-libre-2.6.39-gnu/drivers/acpi/nvs.c
--- linux-libre-2.6.38-gnu/drivers/acpi/nvs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/nvs.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 	unsigned int size;
 	void *kaddr;
 	void *data;
+	bool unmap;
 	struct list_head node;
 };
 
@@ -44,6 +45,9 @@
 {
 	struct nvs_page *entry, *next;
 
+	pr_info("PM: Registering ACPI NVS region at %lx (%ld bytes)\n",
+		start, size);
+
 	while (size > 0) {
 		unsigned int nr_bytes;
 
@@ -81,7 +85,13 @@
 			free_page((unsigned long)entry->data);
 			entry->data = NULL;
 			if (entry->kaddr) {
-				iounmap(entry->kaddr);
+				if (entry->unmap) {
+					iounmap(entry->kaddr);
+					entry->unmap = false;
+				} else {
+					acpi_os_unmap_memory(entry->kaddr,
+							     entry->size);
+				}
 				entry->kaddr = NULL;
 			}
 		}
@@ -115,8 +125,14 @@
 
 	list_for_each_entry(entry, &nvs_list, node)
 		if (entry->data) {
-			entry->kaddr = acpi_os_ioremap(entry->phys_start,
-						    entry->size);
+			unsigned long phys = entry->phys_start;
+			unsigned int size = entry->size;
+
+			entry->kaddr = acpi_os_get_iomem(phys, size);
+			if (!entry->kaddr) {
+				entry->kaddr = acpi_os_ioremap(phys, size);
+				entry->unmap = !!entry->kaddr;
+			}
 			if (!entry->kaddr) {
 				suspend_nvs_free();
 				return -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/osl.c linux-libre-2.6.39-gnu/drivers/acpi/osl.c
--- linux-libre-2.6.38-gnu/drivers/acpi/osl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/osl.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,6 @@
 extern char line_buf[80];
 #endif				/*ENABLE_DEBUGGER */
 
-static unsigned int acpi_irq_irq;
 static acpi_osd_handler acpi_irq_handler;
 static void *acpi_irq_context;
 static struct workqueue_struct *kacpid_wq;
@@ -105,11 +104,11 @@
 	void __iomem *virt;
 	acpi_physical_address phys;
 	acpi_size size;
-	struct kref ref;
+	unsigned long refcount;
 };
 
 static LIST_HEAD(acpi_ioremaps);
-static DEFINE_SPINLOCK(acpi_ioremap_lock);
+static DEFINE_MUTEX(acpi_ioremap_lock);
 
 static void __init acpi_osi_setup_late(void);
 
@@ -285,6 +284,22 @@
 	return NULL;
 }
 
+void __iomem *acpi_os_get_iomem(acpi_physical_address phys, unsigned int size)
+{
+	struct acpi_ioremap *map;
+	void __iomem *virt = NULL;
+
+	mutex_lock(&acpi_ioremap_lock);
+	map = acpi_map_lookup(phys, size);
+	if (map) {
+		virt = map->virt + (phys - map->phys);
+		map->refcount++;
+	}
+	mutex_unlock(&acpi_ioremap_lock);
+	return virt;
+}
+EXPORT_SYMBOL_GPL(acpi_os_get_iomem);
+
 /* Must be called with 'acpi_ioremap_lock' or RCU read lock held. */
 static struct acpi_ioremap *
 acpi_map_lookup_virt(void __iomem *virt, acpi_size size)
@@ -302,8 +317,7 @@
 void __iomem *__init_refok
 acpi_os_map_memory(acpi_physical_address phys, acpi_size size)
 {
-	struct acpi_ioremap *map, *tmp_map;
-	unsigned long flags;
+	struct acpi_ioremap *map;
 	void __iomem *virt;
 	acpi_physical_address pg_off;
 	acpi_size pg_sz;
@@ -316,14 +330,25 @@
 	if (!acpi_gbl_permanent_mmap)
 		return __acpi_map_table((unsigned long)phys, size);
 
+	mutex_lock(&acpi_ioremap_lock);
+	/* Check if there's a suitable mapping already. */
+	map = acpi_map_lookup(phys, size);
+	if (map) {
+		map->refcount++;
+		goto out;
+	}
+
 	map = kzalloc(sizeof(*map), GFP_KERNEL);
-	if (!map)
+	if (!map) {
+		mutex_unlock(&acpi_ioremap_lock);
 		return NULL;
+	}
 
 	pg_off = round_down(phys, PAGE_SIZE);
 	pg_sz = round_up(phys + size, PAGE_SIZE) - pg_off;
 	virt = acpi_os_ioremap(pg_off, pg_sz);
 	if (!virt) {
+		mutex_unlock(&acpi_ioremap_lock);
 		kfree(map);
 		return NULL;
 	}
@@ -332,62 +357,51 @@
 	map->virt = virt;
 	map->phys = pg_off;
 	map->size = pg_sz;
-	kref_init(&map->ref);
+	map->refcount = 1;
 
-	spin_lock_irqsave(&acpi_ioremap_lock, flags);
-	/* Check if page has already been mapped. */
-	tmp_map = acpi_map_lookup(phys, size);
-	if (tmp_map) {
-		kref_get(&tmp_map->ref);
-		spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
-		iounmap(map->virt);
-		kfree(map);
-		return tmp_map->virt + (phys - tmp_map->phys);
-	}
 	list_add_tail_rcu(&map->list, &acpi_ioremaps);
-	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
 
+ out:
+	mutex_unlock(&acpi_ioremap_lock);
 	return map->virt + (phys - map->phys);
 }
 EXPORT_SYMBOL_GPL(acpi_os_map_memory);
 
-static void acpi_kref_del_iomap(struct kref *ref)
+static void acpi_os_drop_map_ref(struct acpi_ioremap *map)
 {
-	struct acpi_ioremap *map;
+	if (!--map->refcount)
+		list_del_rcu(&map->list);
+}
 
-	map = container_of(ref, struct acpi_ioremap, ref);
-	list_del_rcu(&map->list);
+static void acpi_os_map_cleanup(struct acpi_ioremap *map)
+{
+	if (!map->refcount) {
+		synchronize_rcu();
+		iounmap(map->virt);
+		kfree(map);
+	}
 }
 
 void __ref acpi_os_unmap_memory(void __iomem *virt, acpi_size size)
 {
 	struct acpi_ioremap *map;
-	unsigned long flags;
-	int del;
 
 	if (!acpi_gbl_permanent_mmap) {
 		__acpi_unmap_table(virt, size);
 		return;
 	}
 
-	spin_lock_irqsave(&acpi_ioremap_lock, flags);
+	mutex_lock(&acpi_ioremap_lock);
 	map = acpi_map_lookup_virt(virt, size);
 	if (!map) {
-		spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
-		printk(KERN_ERR PREFIX "%s: bad address %p\n", __func__, virt);
-		dump_stack();
+		mutex_unlock(&acpi_ioremap_lock);
+		WARN(true, PREFIX "%s: bad address %p\n", __func__, virt);
 		return;
 	}
+	acpi_os_drop_map_ref(map);
+	mutex_unlock(&acpi_ioremap_lock);
 
-	del = kref_put(&map->ref, acpi_kref_del_iomap);
-	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
-
-	if (!del)
-		return;
-
-	synchronize_rcu();
-	iounmap(map->virt);
-	kfree(map);
+	acpi_os_map_cleanup(map);
 }
 EXPORT_SYMBOL_GPL(acpi_os_unmap_memory);
 
@@ -397,7 +411,7 @@
 		__acpi_unmap_table(virt, size);
 }
 
-int acpi_os_map_generic_address(struct acpi_generic_address *addr)
+static int acpi_os_map_generic_address(struct acpi_generic_address *addr)
 {
 	void __iomem *virt;
 
@@ -413,13 +427,10 @@
 
 	return 0;
 }
-EXPORT_SYMBOL_GPL(acpi_os_map_generic_address);
 
-void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
+static void acpi_os_unmap_generic_address(struct acpi_generic_address *addr)
 {
-	void __iomem *virt;
-	unsigned long flags;
-	acpi_size size = addr->bit_width / 8;
+	struct acpi_ioremap *map;
 
 	if (addr->space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY)
 		return;
@@ -427,13 +438,17 @@
 	if (!addr->address || !addr->bit_width)
 		return;
 
-	spin_lock_irqsave(&acpi_ioremap_lock, flags);
-	virt = acpi_map_vaddr_lookup(addr->address, size);
-	spin_unlock_irqrestore(&acpi_ioremap_lock, flags);
+	mutex_lock(&acpi_ioremap_lock);
+	map = acpi_map_lookup(addr->address, addr->bit_width / 8);
+	if (!map) {
+		mutex_unlock(&acpi_ioremap_lock);
+		return;
+	}
+	acpi_os_drop_map_ref(map);
+	mutex_unlock(&acpi_ioremap_lock);
 
-	acpi_os_unmap_memory(virt, size);
+	acpi_os_map_cleanup(map);
 }
-EXPORT_SYMBOL_GPL(acpi_os_unmap_generic_address);
 
 #ifdef ACPI_FUTURE_USAGE
 acpi_status
@@ -516,11 +531,15 @@
 	acpi_irq_stats_init();
 
 	/*
-	 * Ignore the GSI from the core, and use the value in our copy of the
-	 * FADT. It may not be the same if an interrupt source override exists
-	 * for the SCI.
+	 * ACPI interrupts different from the SCI in our copy of the FADT are
+	 * not supported.
 	 */
-	gsi = acpi_gbl_FADT.sci_interrupt;
+	if (gsi != acpi_gbl_FADT.sci_interrupt)
+		return AE_BAD_PARAMETER;
+
+	if (acpi_irq_handler)
+		return AE_ALREADY_ACQUIRED;
+
 	if (acpi_gsi_to_irq(gsi, &irq) < 0) {
 		printk(KERN_ERR PREFIX "SCI (ACPI GSI %d) not registered\n",
 		       gsi);
@@ -531,20 +550,20 @@
 	acpi_irq_context = context;
 	if (request_irq(irq, acpi_irq, IRQF_SHARED, "acpi", acpi_irq)) {
 		printk(KERN_ERR PREFIX "SCI (IRQ%d) allocation failed\n", irq);
+		acpi_irq_handler = NULL;
 		return AE_NOT_ACQUIRED;
 	}
-	acpi_irq_irq = irq;
 
 	return AE_OK;
 }
 
 acpi_status acpi_os_remove_interrupt_handler(u32 irq, acpi_osd_handler handler)
 {
-	if (irq) {
-		free_irq(irq, acpi_irq);
-		acpi_irq_handler = NULL;
-		acpi_irq_irq = 0;
-	}
+	if (irq != acpi_gbl_FADT.sci_interrupt)
+		return AE_BAD_PARAMETER;
+
+	free_irq(irq, acpi_irq);
+	acpi_irq_handler = NULL;
 
 	return AE_OK;
 }
@@ -1589,9 +1608,9 @@
 
 acpi_status __init acpi_os_initialize1(void)
 {
-	kacpid_wq = create_workqueue("kacpid");
-	kacpi_notify_wq = create_workqueue("kacpi_notify");
-	kacpi_hotplug_wq = create_workqueue("kacpi_hotplug");
+	kacpid_wq = alloc_workqueue("kacpid", 0, 1);
+	kacpi_notify_wq = alloc_workqueue("kacpi_notify", 0, 1);
+	kacpi_hotplug_wq = alloc_workqueue("kacpi_hotplug", 0, 1);
 	BUG_ON(!kacpid_wq);
 	BUG_ON(!kacpi_notify_wq);
 	BUG_ON(!kacpi_hotplug_wq);
@@ -1603,7 +1622,7 @@
 acpi_status acpi_os_terminate(void)
 {
 	if (acpi_irq_handler) {
-		acpi_os_remove_interrupt_handler(acpi_irq_irq,
+		acpi_os_remove_interrupt_handler(acpi_gbl_FADT.sci_interrupt,
 						 acpi_irq_handler);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/pci_link.c linux-libre-2.6.39-gnu/drivers/acpi/pci_link.c
--- linux-libre-2.6.38-gnu/drivers/acpi/pci_link.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/pci_link.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
  *	   for IRQ management (e.g. start()->_SRS).
  */
 
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -757,14 +757,13 @@
 	return 0;
 }
 
-static int irqrouter_resume(struct sys_device *dev)
+static void irqrouter_resume(void)
 {
 	struct acpi_pci_link *link;
 
 	list_for_each_entry(link, &acpi_link_list, list) {
 		acpi_pci_link_resume(link);
 	}
-	return 0;
 }
 
 static int acpi_pci_link_remove(struct acpi_device *device, int type)
@@ -871,32 +870,19 @@
 
 __setup("acpi_irq_balance", acpi_irq_balance_set);
 
-/* FIXME: we will remove this interface after all drivers call pci_disable_device */
-static struct sysdev_class irqrouter_sysdev_class = {
-	.name = "irqrouter",
+static struct syscore_ops irqrouter_syscore_ops = {
 	.resume = irqrouter_resume,
 };
 
-static struct sys_device device_irqrouter = {
-	.id = 0,
-	.cls = &irqrouter_sysdev_class,
-};
-
-static int __init irqrouter_init_sysfs(void)
+static int __init irqrouter_init_ops(void)
 {
-	int error;
-
-	if (acpi_disabled || acpi_noirq)
-		return 0;
-
-	error = sysdev_class_register(&irqrouter_sysdev_class);
-	if (!error)
-		error = sysdev_register(&device_irqrouter);
+	if (!acpi_disabled && !acpi_noirq)
+		register_syscore_ops(&irqrouter_syscore_ops);
 
-	return error;
+	return 0;
 }
 
-device_initcall(irqrouter_init_sysfs);
+device_initcall(irqrouter_init_ops);
 
 static int __init acpi_pci_link_init(void)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/pci_root.c linux-libre-2.6.39-gnu/drivers/acpi/pci_root.c
--- linux-libre-2.6.38-gnu/drivers/acpi/pci_root.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/pci_root.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/pci.h>
 #include <linux/pci-acpi.h>
+#include <linux/pci-aspm.h>
 #include <linux/acpi.h>
 #include <linux/slab.h>
 #include <acpi/acpi_bus.h>
@@ -564,7 +565,7 @@
 	/* Indicate support for various _OSC capabilities. */
 	if (pci_ext_cfg_avail(root->bus->self))
 		flags |= OSC_EXT_PCI_CONFIG_SUPPORT;
-	if (pcie_aspm_enabled())
+	if (pcie_aspm_support_enabled())
 		flags |= OSC_ACTIVE_STATE_PWR_SUPPORT |
 			OSC_CLOCK_PWR_CAPABILITY_SUPPORT;
 	if (pci_msi_enabled())
@@ -591,12 +592,16 @@
 
 		status = acpi_pci_osc_control_set(device->handle, &flags,
 					OSC_PCI_EXPRESS_CAP_STRUCTURE_CONTROL);
-		if (ACPI_SUCCESS(status))
+		if (ACPI_SUCCESS(status)) {
 			dev_info(root->bus->bridge,
 				"ACPI _OSC control (0x%02x) granted\n", flags);
-		else
+		} else {
 			dev_dbg(root->bus->bridge,
 				"ACPI _OSC request failed (code %d)\n", status);
+			printk(KERN_INFO "Unable to assume _OSC PCIe control. "
+				"Disabling ASPM\n");
+			pcie_no_aspm();
+		}
 	}
 
 	pci_acpi_add_bus_pm_notifier(device, root->bus);
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/processor_core.c linux-libre-2.6.39-gnu/drivers/acpi/processor_core.c
--- linux-libre-2.6.38-gnu/drivers/acpi/processor_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/processor_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 #define _COMPONENT		ACPI_PROCESSOR_COMPONENT
 ACPI_MODULE_NAME("processor_core");
 
-static int set_no_mwait(const struct dmi_system_id *id)
+static int __init set_no_mwait(const struct dmi_system_id *id)
 {
 	printk(KERN_NOTICE PREFIX "%s detected - "
 		"disabling mwait for CPU C-states\n", id->ident);
@@ -27,7 +27,7 @@
 	return 0;
 }
 
-static struct dmi_system_id __cpuinitdata processor_idle_dmi_table[] = {
+static struct dmi_system_id __initdata processor_idle_dmi_table[] = {
 	{
 	set_no_mwait, "Extensa 5220", {
 	DMI_MATCH(DMI_BIOS_VENDOR, "Phoenix Technologies LTD"),
@@ -183,7 +183,7 @@
 EXPORT_SYMBOL_GPL(acpi_get_cpuid);
 #endif
 
-static bool processor_physically_present(acpi_handle handle)
+static bool __init processor_physically_present(acpi_handle handle)
 {
 	int cpuid, type;
 	u32 acpi_id;
@@ -223,7 +223,7 @@
 	return true;
 }
 
-static void acpi_set_pdc_bits(u32 *buf)
+static void __cpuinit acpi_set_pdc_bits(u32 *buf)
 {
 	buf[0] = ACPI_PDC_REVISION_ID;
 	buf[1] = 1;
@@ -235,7 +235,7 @@
 	arch_acpi_set_pdc_bits(buf);
 }
 
-static struct acpi_object_list *acpi_processor_alloc_pdc(void)
+static struct acpi_object_list *__cpuinit acpi_processor_alloc_pdc(void)
 {
 	struct acpi_object_list *obj_list;
 	union acpi_object *obj;
@@ -278,7 +278,7 @@
  * _PDC is required for a BIOS-OS handshake for most of the newer
  * ACPI processor features.
  */
-static int
+static int __cpuinit
 acpi_processor_eval_pdc(acpi_handle handle, struct acpi_object_list *pdc_in)
 {
 	acpi_status status = AE_OK;
@@ -306,7 +306,7 @@
 	return status;
 }
 
-void acpi_processor_set_pdc(acpi_handle handle)
+void __cpuinit acpi_processor_set_pdc(acpi_handle handle)
 {
 	struct acpi_object_list *obj_list;
 
@@ -323,9 +323,8 @@
 	kfree(obj_list->pointer);
 	kfree(obj_list);
 }
-EXPORT_SYMBOL_GPL(acpi_processor_set_pdc);
 
-static acpi_status
+static acpi_status __init
 early_init_pdc(acpi_handle handle, u32 lvl, void *context, void **rv)
 {
 	if (processor_physically_present(handle) == false)
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/processor_driver.c linux-libre-2.6.39-gnu/drivers/acpi/processor_driver.c
--- linux-libre-2.6.38-gnu/drivers/acpi/processor_driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/processor_driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -635,8 +635,8 @@
 	return 0;
 }
 
-static void __ref acpi_processor_hotplug_notify(acpi_handle handle,
-						u32 event, void *data)
+static void acpi_processor_hotplug_notify(acpi_handle handle,
+					  u32 event, void *data)
 {
 	struct acpi_processor *pr;
 	struct acpi_device *device = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/processor_throttling.c linux-libre-2.6.39-gnu/drivers/acpi/processor_throttling.c
--- linux-libre-2.6.38-gnu/drivers/acpi/processor_throttling.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/processor_throttling.c	2011-05-19 00:06:34.000000000 -0400
@@ -1164,7 +1164,7 @@
 			 */
 			if (!match_pr->flags.throttling) {
 				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
-					"Throttling Controll is unsupported "
+					"Throttling Control is unsupported "
 					"on CPU %d\n", i));
 				continue;
 			}
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/reboot.c linux-libre-2.6.39-gnu/drivers/acpi/reboot.c
--- linux-libre-2.6.38-gnu/drivers/acpi/reboot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/reboot.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,9 +15,15 @@
 
 	rr = &acpi_gbl_FADT.reset_register;
 
-	/* Is the reset register supported? */
-	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER) ||
-	    rr->bit_width != 8 || rr->bit_offset != 0)
+	/* ACPI reset register was only introduced with v2 of the FADT */
+
+	if (acpi_gbl_FADT.header.revision < 2)
+		return;
+
+	/* Is the reset register supported? The spec says we should be
+	 * checking the bit width and bit offset, but Windows ignores
+	 * these fields */
+	if (!(acpi_gbl_FADT.flags & ACPI_FADT_RESET_REGISTER))
 		return;
 
 	reset_value = acpi_gbl_FADT.reset_value;
@@ -45,6 +51,4 @@
 		acpi_reset();
 		break;
 	}
-	/* Wait ten seconds */
-	acpi_os_stall(10000000);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/scan.c linux-libre-2.6.39-gnu/drivers/acpi/scan.c
--- linux-libre-2.6.38-gnu/drivers/acpi/scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -797,7 +797,6 @@
 	acpi_status status;
 	acpi_event_status event_status;
 
-	device->wakeup.run_wake_count = 0;
 	device->wakeup.flags.notifier_present = 0;
 
 	/* Power button, Lid switch always enable wakeup */
@@ -944,6 +943,10 @@
 	if (ACPI_SUCCESS(status))
 		device->flags.lockable = 1;
 
+	/* Power resources cannot be power manageable. */
+	if (device->device_type == ACPI_BUS_TYPE_POWER)
+		return 0;
+
 	/* Presence of _PS0|_PR0 indicates 'power manageable' */
 	status = acpi_get_handle(device->handle, "_PS0", &temp);
 	if (ACPI_FAILURE(status))
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/sleep.c linux-libre-2.6.39-gnu/drivers/acpi/sleep.c
--- linux-libre-2.6.38-gnu/drivers/acpi/sleep.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/sleep.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,7 @@
 #include <linux/device.h>
 #include <linux/suspend.h>
 #include <linux/reboot.h>
+#include <linux/acpi.h>
 
 #include <asm/io.h>
 
@@ -199,8 +200,6 @@
 #endif /* CONFIG_ACPI_SLEEP */
 
 #ifdef CONFIG_SUSPEND
-extern void do_suspend_lowlevel(void);
-
 static u32 acpi_suspend_states[] = {
 	[PM_SUSPEND_ON] = ACPI_STATE_S0,
 	[PM_SUSPEND_STANDBY] = ACPI_STATE_S1,
@@ -243,20 +242,11 @@
 static int acpi_suspend_enter(suspend_state_t pm_state)
 {
 	acpi_status status = AE_OK;
-	unsigned long flags = 0;
 	u32 acpi_state = acpi_target_sleep_state;
+	int error;
 
 	ACPI_FLUSH_CPU_CACHE();
 
-	/* Do arch specific saving of state. */
-	if (acpi_state == ACPI_STATE_S3) {
-		int error = acpi_save_state_mem();
-
-		if (error)
-			return error;
-	}
-
-	local_irq_save(flags);
 	switch (acpi_state) {
 	case ACPI_STATE_S1:
 		barrier();
@@ -264,7 +254,10 @@
 		break;
 
 	case ACPI_STATE_S3:
-		do_suspend_lowlevel();
+		error = acpi_suspend_lowlevel();
+		if (error)
+			return error;
+		pr_info(PREFIX "Low-level resume complete\n");
 		break;
 	}
 
@@ -290,13 +283,6 @@
 	/* Allow EC transactions to happen. */
 	acpi_ec_unblock_transactions_early();
 
-	local_irq_restore(flags);
-	printk(KERN_DEBUG "Back to C!\n");
-
-	/* restore processor state */
-	if (acpi_state == ACPI_STATE_S3)
-		acpi_restore_state_mem();
-
 	suspend_nvs_restore();
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
@@ -472,16 +458,13 @@
 static int acpi_hibernation_enter(void)
 {
 	acpi_status status = AE_OK;
-	unsigned long flags = 0;
 
 	ACPI_FLUSH_CPU_CACHE();
 
-	local_irq_save(flags);
 	/* This shouldn't return.  If it returns, we have a problem */
 	status = acpi_enter_sleep_state(ACPI_STATE_S4);
 	/* Reprogram control registers and execute _BFS */
 	acpi_leave_sleep_state_prep(ACPI_STATE_S4);
-	local_irq_restore(flags);
 
 	return ACPI_SUCCESS(status) ? 0 : -EFAULT;
 }
@@ -585,7 +568,7 @@
 	return -EINVAL;
 }
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 /**
  *	acpi_pm_device_sleep_state - return preferred power state of ACPI device
  *		in the system sleep state given by %acpi_target_sleep_state
@@ -671,7 +654,7 @@
 		*d_min_p = d_min;
 	return d_max;
 }
-#endif /* CONFIG_PM_OPS */
+#endif /* CONFIG_PM */
 
 #ifdef CONFIG_PM_SLEEP
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/acpi/video.c linux-libre-2.6.39-gnu/drivers/acpi/video.c
--- linux-libre-2.6.38-gnu/drivers/acpi/video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/acpi/video.c	2011-05-19 00:06:34.000000000 -0400
@@ -782,6 +782,9 @@
 
 	if (acpi_video_backlight_support()) {
 		struct backlight_properties props;
+		struct pci_dev *pdev;
+		acpi_handle acpi_parent;
+		struct device *parent = NULL;
 		int result;
 		static int count = 0;
 		char *name;
@@ -794,9 +797,20 @@
 			return;
 		count++;
 
+		acpi_get_parent(device->dev->handle, &acpi_parent);
+
+		pdev = acpi_get_pci_dev(acpi_parent);
+		if (pdev) {
+			parent = &pdev->dev;
+			pci_dev_put(pdev);
+		}
+
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_FIRMWARE;
 		props.max_brightness = device->brightness->count - 3;
-		device->backlight = backlight_device_register(name, NULL, device,
+		device->backlight = backlight_device_register(name,
+							      parent,
+							      device,
 							      &acpi_backlight_ops,
 							      &props);
 		kfree(name);
@@ -810,11 +824,6 @@
 		device->backlight->props.brightness =
 				acpi_video_get_brightness(device->backlight);
 
-		result = sysfs_create_link(&device->backlight->dev.kobj,
-					   &device->dev->dev.kobj, "device");
-		if (result)
-			printk(KERN_ERR PREFIX "Create sysfs link\n");
-
 		device->cooling_dev = thermal_cooling_device_register("LCD",
 					device->dev, &video_cooling_ops);
 		if (IS_ERR(device->cooling_dev)) {
@@ -1345,7 +1354,7 @@
 		status = acpi_video_bus_get_one_device(dev, video);
 		if (ACPI_FAILURE(status)) {
 			printk(KERN_WARNING PREFIX
-					"Cant attach device\n");
+					"Can't attach device\n");
 			continue;
 		}
 	}
@@ -1364,10 +1373,9 @@
 					    acpi_video_device_notify);
 	if (ACPI_FAILURE(status)) {
 		printk(KERN_WARNING PREFIX
-		       "Cant remove video notify handler\n");
+		       "Can't remove video notify handler\n");
 	}
 	if (device->backlight) {
-		sysfs_remove_link(&device->backlight->dev.kobj, "device");
 		backlight_device_unregister(device->backlight);
 		device->backlight = NULL;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/amba/bus.c linux-libre-2.6.39-gnu/drivers/amba/bus.c
--- linux-libre-2.6.38-gnu/drivers/amba/bus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/amba/bus.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,16 +13,17 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/pm.h>
+#include <linux/pm_runtime.h>
 #include <linux/amba/bus.h>
 
 #include <asm/irq.h>
 #include <asm/sizes.h>
 
-#define to_amba_device(d)	container_of(d, struct amba_device, dev)
 #define to_amba_driver(d)	container_of(d, struct amba_driver, drv)
 
-static struct amba_id *
-amba_lookup(struct amba_id *table, struct amba_device *dev)
+static const struct amba_id *
+amba_lookup(const struct amba_id *table, struct amba_device *dev)
 {
 	int ret = 0;
 
@@ -57,26 +58,6 @@
 #define amba_uevent NULL
 #endif
 
-static int amba_suspend(struct device *dev, pm_message_t state)
-{
-	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(to_amba_device(dev), state);
-	return ret;
-}
-
-static int amba_resume(struct device *dev)
-{
-	struct amba_driver *drv = to_amba_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(to_amba_device(dev));
-	return ret;
-}
-
 #define amba_attr_func(name,fmt,arg...)					\
 static ssize_t name##_show(struct device *_dev,				\
 			   struct device_attribute *attr, char *buf)	\
@@ -102,17 +83,330 @@
 	__ATTR_NULL,
 };
 
+#ifdef CONFIG_PM_SLEEP
+
+static int amba_legacy_suspend(struct device *dev, pm_message_t mesg)
+{
+	struct amba_driver *adrv = to_amba_driver(dev->driver);
+	struct amba_device *adev = to_amba_device(dev);
+	int ret = 0;
+
+	if (dev->driver && adrv->suspend)
+		ret = adrv->suspend(adev, mesg);
+
+	return ret;
+}
+
+static int amba_legacy_resume(struct device *dev)
+{
+	struct amba_driver *adrv = to_amba_driver(dev->driver);
+	struct amba_device *adev = to_amba_device(dev);
+	int ret = 0;
+
+	if (dev->driver && adrv->resume)
+		ret = adrv->resume(adev);
+
+	return ret;
+}
+
+static int amba_pm_prepare(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (drv && drv->pm && drv->pm->prepare)
+		ret = drv->pm->prepare(dev);
+
+	return ret;
+}
+
+static void amba_pm_complete(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+
+	if (drv && drv->pm && drv->pm->complete)
+		drv->pm->complete(dev);
+}
+
+#else /* !CONFIG_PM_SLEEP */
+
+#define amba_pm_prepare		NULL
+#define amba_pm_complete		NULL
+
+#endif /* !CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_SUSPEND
+
+static int amba_pm_suspend(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend)
+			ret = drv->pm->suspend(dev);
+	} else {
+		ret = amba_legacy_suspend(dev, PMSG_SUSPEND);
+	}
+
+	return ret;
+}
+
+static int amba_pm_suspend_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->suspend_noirq)
+			ret = drv->pm->suspend_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_resume(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume)
+			ret = drv->pm->resume(dev);
+	} else {
+		ret = amba_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_resume_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->resume_noirq)
+			ret = drv->pm->resume_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_SUSPEND */
+
+#define amba_pm_suspend		NULL
+#define amba_pm_resume		NULL
+#define amba_pm_suspend_noirq	NULL
+#define amba_pm_resume_noirq	NULL
+
+#endif /* !CONFIG_SUSPEND */
+
+#ifdef CONFIG_HIBERNATE_CALLBACKS
+
+static int amba_pm_freeze(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze)
+			ret = drv->pm->freeze(dev);
+	} else {
+		ret = amba_legacy_suspend(dev, PMSG_FREEZE);
+	}
+
+	return ret;
+}
+
+static int amba_pm_freeze_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->freeze_noirq)
+			ret = drv->pm->freeze_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_thaw(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw)
+			ret = drv->pm->thaw(dev);
+	} else {
+		ret = amba_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_thaw_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->thaw_noirq)
+			ret = drv->pm->thaw_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_poweroff(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff)
+			ret = drv->pm->poweroff(dev);
+	} else {
+		ret = amba_legacy_suspend(dev, PMSG_HIBERNATE);
+	}
+
+	return ret;
+}
+
+static int amba_pm_poweroff_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->poweroff_noirq)
+			ret = drv->pm->poweroff_noirq(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_restore(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore)
+			ret = drv->pm->restore(dev);
+	} else {
+		ret = amba_legacy_resume(dev);
+	}
+
+	return ret;
+}
+
+static int amba_pm_restore_noirq(struct device *dev)
+{
+	struct device_driver *drv = dev->driver;
+	int ret = 0;
+
+	if (!drv)
+		return 0;
+
+	if (drv->pm) {
+		if (drv->pm->restore_noirq)
+			ret = drv->pm->restore_noirq(dev);
+	}
+
+	return ret;
+}
+
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
+
+#define amba_pm_freeze		NULL
+#define amba_pm_thaw		NULL
+#define amba_pm_poweroff		NULL
+#define amba_pm_restore		NULL
+#define amba_pm_freeze_noirq	NULL
+#define amba_pm_thaw_noirq		NULL
+#define amba_pm_poweroff_noirq	NULL
+#define amba_pm_restore_noirq	NULL
+
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
+
+#ifdef CONFIG_PM
+
+static const struct dev_pm_ops amba_pm = {
+	.prepare	= amba_pm_prepare,
+	.complete	= amba_pm_complete,
+	.suspend	= amba_pm_suspend,
+	.resume		= amba_pm_resume,
+	.freeze		= amba_pm_freeze,
+	.thaw		= amba_pm_thaw,
+	.poweroff	= amba_pm_poweroff,
+	.restore	= amba_pm_restore,
+	.suspend_noirq	= amba_pm_suspend_noirq,
+	.resume_noirq	= amba_pm_resume_noirq,
+	.freeze_noirq	= amba_pm_freeze_noirq,
+	.thaw_noirq	= amba_pm_thaw_noirq,
+	.poweroff_noirq	= amba_pm_poweroff_noirq,
+	.restore_noirq	= amba_pm_restore_noirq,
+	SET_RUNTIME_PM_OPS(
+		pm_generic_runtime_suspend,
+		pm_generic_runtime_resume,
+		pm_generic_runtime_idle
+	)
+};
+
+#define AMBA_PM (&amba_pm)
+
+#else /* !CONFIG_PM */
+
+#define AMBA_PM	NULL
+
+#endif /* !CONFIG_PM */
+
 /*
  * Primecells are part of the Advanced Microcontroller Bus Architecture,
  * so we call the bus "amba".
  */
-static struct bus_type amba_bustype = {
+struct bus_type amba_bustype = {
 	.name		= "amba",
 	.dev_attrs	= amba_dev_attrs,
 	.match		= amba_match,
 	.uevent		= amba_uevent,
-	.suspend	= amba_suspend,
-	.resume		= amba_resume,
+	.pm		= AMBA_PM,
 };
 
 static int __init amba_init(void)
@@ -188,7 +482,7 @@
 {
 	struct amba_device *pcdev = to_amba_device(dev);
 	struct amba_driver *pcdrv = to_amba_driver(dev->driver);
-	struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
+	const struct amba_id *id = amba_lookup(pcdrv->id_table, pcdev);
 	int ret;
 
 	do {
@@ -466,7 +760,7 @@
 }
 
 /**
- *	amba_release_regions - release mem regions assoicated with device
+ *	amba_release_regions - release mem regions associated with device
  *	@dev: amba_device structure for device
  *
  *	Release regions claimed by a successful call to amba_request_regions.
diff -druN linux-libre-2.6.38-gnu/drivers/ata/ahci.c linux-libre-2.6.39-gnu/drivers/ata/ahci.c
--- linux-libre-2.6.38-gnu/drivers/ata/ahci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/ahci.c	2011-05-19 00:06:34.000000000 -0400
@@ -150,7 +150,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_FPDMA_AA | AHCI_HFLAG_NO_PMP |
 				 AHCI_HFLAG_YES_NCQ),
-		.flags		= AHCI_FLAG_COMMON,
+		.flags		= AHCI_FLAG_COMMON | ATA_FLAG_NO_DIPM,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -175,8 +175,7 @@
 	{
 		AHCI_HFLAGS	(AHCI_HFLAG_NO_NCQ | AHCI_HFLAG_NO_MSI |
 				 AHCI_HFLAG_MV_PATA | AHCI_HFLAG_NO_PMP),
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
 		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &ahci_ops,
@@ -260,7 +259,14 @@
 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1d04), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x1d06), board_ahci }, /* PBG RAID */
+	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
 
 	/* 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,
@@ -383,6 +389,10 @@
 	  .class = PCI_CLASS_STORAGE_SATA_AHCI,
 	  .class_mask = 0xffffff,
 	  .driver_data = board_ahci_yes_fbs },			/* 88se9128 */
+	{ PCI_DEVICE(0x1b4b, 0x9125),
+	  .driver_data = board_ahci_yes_fbs },			/* 88se9125 */
+	{ PCI_DEVICE(0x1b4b, 0x91a3),
+	  .driver_data = board_ahci_yes_fbs },
 
 	/* Promise */
 	{ PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },	/* PDC42819 */
@@ -922,7 +932,7 @@
 		/*
 		 * Acer eMachines G725 has the same problem.  BIOS
 		 * V1.03 is known to be broken.  V3.04 is known to
-		 * work.  Inbetween, there are V1.06, V2.06 and V3.03
+		 * work.  Between, there are V1.06, V2.06 and V3.03
 		 * that we don't have much idea about.  For now,
 		 * blacklist anything older than V3.04.
 		 *
diff -druN linux-libre-2.6.38-gnu/drivers/ata/ahci.h linux-libre-2.6.39-gnu/drivers/ata/ahci.h
--- linux-libre-2.6.38-gnu/drivers/ata/ahci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/ahci.h	2011-05-19 00:06:34.000000000 -0400
@@ -213,10 +213,8 @@
 
 	/* ap->flags bits */
 
-	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-					  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
-					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN |
-					  ATA_FLAG_LPM,
+	AHCI_FLAG_COMMON		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
+					  ATA_FLAG_ACPI_SATA | ATA_FLAG_AN,
 
 	ICH_MAP				= 0x90, /* ICH MAP register */
 
@@ -227,10 +225,14 @@
 	/* em_ctl bits */
 	EM_CTL_RST		= (1 << 9), /* Reset */
 	EM_CTL_TM		= (1 << 8), /* Transmit Message */
-	EM_CTL_MR		= (1 << 0), /* Message Recieved */
+	EM_CTL_MR		= (1 << 0), /* Message Received */
 	EM_CTL_ALHD		= (1 << 26), /* Activity LED */
 	EM_CTL_XMT		= (1 << 25), /* Transmit Only */
 	EM_CTL_SMB		= (1 << 24), /* Single Message Buffer */
+	EM_CTL_SGPIO		= (1 << 19), /* SGPIO messages supported */
+	EM_CTL_SES		= (1 << 18), /* SES-2 messages supported */
+	EM_CTL_SAFTE		= (1 << 17), /* SAF-TE messages supported */
+	EM_CTL_LED		= (1 << 16), /* LED messages supported */
 
 	/* em message type */
 	EM_MSG_TYPE_LED		= (1 << 0), /* LED */
@@ -283,7 +285,7 @@
 };
 
 struct ahci_host_priv {
-	void __iomem *		mmio;		/* bus-independant mem map */
+	void __iomem *		mmio;		/* bus-independent mem map */
 	unsigned int		flags;		/* AHCI_HFLAG_* */
 	u32			cap;		/* cap to use */
 	u32			cap2;		/* cap2 to use */
diff -druN linux-libre-2.6.38-gnu/drivers/ata/ata_generic.c linux-libre-2.6.39-gnu/drivers/ata/ata_generic.c
--- linux-libre-2.6.38-gnu/drivers/ata/ata_generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/ata_generic.c	2011-05-19 00:06:34.000000000 -0400
@@ -237,7 +237,7 @@
 #endif
 	/* Intel, IDE class device */
 	{ PCI_VENDOR_ID_INTEL, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
-	  PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL, 
+	  PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL,
 	  .driver_data = ATA_GEN_INTEL_IDER },
 	/* Must come last. If you add entries adjust this table appropriately */
 	{ PCI_DEVICE_CLASS(PCI_CLASS_STORAGE_IDE << 8, 0xFFFFFF00UL),
diff -druN linux-libre-2.6.38-gnu/drivers/ata/ata_piix.c linux-libre-2.6.39-gnu/drivers/ata/ata_piix.c
--- linux-libre-2.6.38-gnu/drivers/ata/ata_piix.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/ata_piix.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,16 +38,16 @@
  *  Hardware documentation available at http://developer.intel.com/
  *
  * Documentation
- *	Publically available from Intel web site. Errata documentation
- * is also publically available. As an aide to anyone hacking on this
+ *	Publicly available from Intel web site. Errata documentation
+ * is also publicly available. As an aide to anyone hacking on this
  * driver the list of errata that are relevant is below, going back to
  * PIIX4. Older device documentation is now a bit tricky to find.
  *
  * The chipsets all follow very much the same design. The original Triton
- * series chipsets do _not_ support independant device timings, but this
+ * series chipsets do _not_ support independent device timings, but this
  * is fixed in Triton II. With the odd mobile exception the chips then
  * change little except in gaining more modes until SATA arrives. This
- * driver supports only the chips with independant timing (that is those
+ * driver supports only the chips with independent timing (that is those
  * with SITRE and the 0x44 timing register). See pata_oldpiix and pata_mpiix
  * for the early chip drivers.
  *
@@ -122,7 +122,7 @@
 	P2			= 2,  /* port 2 */
 	P3			= 3,  /* port 3 */
 	IDE			= -1, /* IDE */
-	NA			= -2, /* not avaliable */
+	NA			= -2, /* not available */
 	RV			= -3, /* reserved */
 
 	PIIX_AHCI_DEVICE	= 6,
@@ -230,7 +230,7 @@
 	{ 0x8086, 0x2850, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich_pata_100 },
 
 	/* SATA ports */
-	
+
 	/* 82801EB (ICH5) */
 	{ 0x8086, 0x24d1, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich5_sata },
 	/* 82801EB (ICH5) */
@@ -309,6 +309,14 @@
 	{ 0x8086, 0x1d00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
 	/* SATA Controller IDE (PBG) */
 	{ 0x8086, 0x1d08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (Panther Point) */
+	{ 0x8086, 0x1e00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	/* SATA Controller IDE (Panther Point) */
+	{ 0x8086, 0x1e01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata },
+	/* SATA Controller IDE (Panther Point) */
+	{ 0x8086, 0x1e08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+	/* SATA Controller IDE (Panther Point) */
+	{ 0x8086, 0x1e09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
 	{ }	/* terminate list */
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/Kconfig linux-libre-2.6.39-gnu/drivers/ata/Kconfig
--- linux-libre-2.6.38-gnu/drivers/ata/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -202,6 +202,18 @@
 
 	  If unsure, say N.
 
+config SATA_DWC_DEBUG
+	bool "Debugging driver version"
+	depends on SATA_DWC
+	help
+	  This option enables debugging output in the driver.
+
+config SATA_DWC_VDEBUG
+	bool "Verbose debug output"
+	depends on SATA_DWC_DEBUG
+	help
+	  This option enables the taskfile dumping and NCQ debugging.
+
 config SATA_MV
 	tristate "Marvell SATA support"
 	help
@@ -299,6 +311,12 @@
 
 	  If unsure, say N.
 
+config PATA_ARASAN_CF
+	tristate "ARASAN CompactFlash PATA Controller Support"
+	select DMA_ENGINE
+	help
+	  Say Y here to support the ARASAN CompactFlash PATA controller
+
 config PATA_ARTOP
 	tristate "ARTOP 6210/6260 PATA support"
 	depends on PCI
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libahci.c linux-libre-2.6.39-gnu/drivers/ata/libahci.c
--- linux-libre-2.6.38-gnu/drivers/ata/libahci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libahci.c	2011-05-19 00:06:34.000000000 -0400
@@ -109,6 +109,8 @@
 static ssize_t ahci_store_em_buffer(struct device *dev,
 				    struct device_attribute *attr,
 				    const char *buf, size_t size);
+static ssize_t ahci_show_em_supported(struct device *dev,
+				      struct device_attribute *attr, char *buf);
 
 static DEVICE_ATTR(ahci_host_caps, S_IRUGO, ahci_show_host_caps, NULL);
 static DEVICE_ATTR(ahci_host_cap2, S_IRUGO, ahci_show_host_cap2, NULL);
@@ -116,6 +118,7 @@
 static DEVICE_ATTR(ahci_port_cmd, S_IRUGO, ahci_show_port_cmd, NULL);
 static DEVICE_ATTR(em_buffer, S_IWUSR | S_IRUGO,
 		   ahci_read_em_buffer, ahci_store_em_buffer);
+static DEVICE_ATTR(em_message_supported, S_IRUGO, ahci_show_em_supported, NULL);
 
 struct device_attribute *ahci_shost_attrs[] = {
 	&dev_attr_link_power_management_policy,
@@ -126,6 +129,7 @@
 	&dev_attr_ahci_host_version,
 	&dev_attr_ahci_port_cmd,
 	&dev_attr_em_buffer,
+	&dev_attr_em_message_supported,
 	NULL
 };
 EXPORT_SYMBOL_GPL(ahci_shost_attrs);
@@ -343,6 +347,24 @@
 	return size;
 }
 
+static ssize_t ahci_show_em_supported(struct device *dev,
+				      struct device_attribute *attr, char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct ata_port *ap = ata_shost_to_port(shost);
+	struct ahci_host_priv *hpriv = ap->host->private_data;
+	void __iomem *mmio = hpriv->mmio;
+	u32 em_ctl;
+
+	em_ctl = readl(mmio + HOST_EM_CTL);
+
+	return sprintf(buf, "%s%s%s%s\n",
+		       em_ctl & EM_CTL_LED ? "led " : "",
+		       em_ctl & EM_CTL_SAFTE ? "saf-te " : "",
+		       em_ctl & EM_CTL_SES ? "ses-2 " : "",
+		       em_ctl & EM_CTL_SGPIO ? "sgpio " : "");
+}
+
 /**
  *	ahci_save_initial_config - Save and fixup initial config values
  *	@dev: target AHCI device
@@ -1897,7 +1919,17 @@
 	ahci_enable_fbs(ap);
 
 	pp->intr_mask |= PORT_IRQ_BAD_PMP;
-	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+	/*
+	 * We must not change the port interrupt mask register if the
+	 * port is marked frozen, the value in pp->intr_mask will be
+	 * restored later when the port is thawed.
+	 *
+	 * Note that during initialization, the port is marked as
+	 * frozen since the irq handler is not yet registered.
+	 */
+	if (!(ap->pflags & ATA_PFLAG_FROZEN))
+		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 static void ahci_pmp_detach(struct ata_port *ap)
@@ -1913,7 +1945,10 @@
 	writel(cmd, port_mmio + PORT_CMD);
 
 	pp->intr_mask &= ~PORT_IRQ_BAD_PMP;
-	writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
+
+	/* see comment above in ahci_pmp_attach() */
+	if (!(ap->pflags & ATA_PFLAG_FROZEN))
+		writel(pp->intr_mask, port_mmio + PORT_IRQ_MASK);
 }
 
 int ahci_port_resume(struct ata_port *ap)
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-acpi.c linux-libre-2.6.39-gnu/drivers/ata/libata-acpi.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libata-acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -660,8 +660,7 @@
  * @dev: target ATA device
  * @gtf: raw ATA taskfile register set (0x1f1 - 0x1f7)
  *
- * Outputs ATA taskfile to standard ATA host controller using MMIO
- * or PIO as indicated by the ATA_FLAG_MMIO flag.
+ * Outputs ATA taskfile to standard ATA host controller.
  * Writes the control, feature, nsect, lbal, lbam, and lbah registers.
  * Optionally (ATA_TFLAG_LBA48) writes hob_feature, hob_nsect,
  * hob_lbal, hob_lbam, and hob_lbah.
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-core.c linux-libre-2.6.39-gnu/drivers/ata/libata-core.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libata-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -4139,6 +4139,7 @@
 	 */
 	{ "PIONEER DVD-RW  DVRTD08",	"1.00",	ATA_HORKAGE_NOSETXFER },
 	{ "PIONEER DVD-RW  DVR-212D",	"1.28", ATA_HORKAGE_NOSETXFER },
+	{ "PIONEER DVD-RW  DVR-216D",	"1.08", ATA_HORKAGE_NOSETXFER },
 
 	/* End Marker */
 	{ }
@@ -4210,7 +4211,7 @@
 		return 0;  /* End of both strings: match */
 	return 1;  /* No match */
 }
- 
+
 static unsigned long ata_dev_blacklisted(const struct ata_device *dev)
 {
 	unsigned char model_num[ATA_ID_PROD_LEN + 1];
@@ -5340,7 +5341,7 @@
  *
  *	Resume @host.  Actual operation is performed by EH.  This
  *	function requests EH to perform PM operations and returns.
- *	Note that all resume operations are performed parallely.
+ *	Note that all resume operations are performed parallelly.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep).
@@ -5479,8 +5480,8 @@
 	ap = kzalloc(sizeof(*ap), GFP_KERNEL);
 	if (!ap)
 		return NULL;
-	
-	ap->pflags |= ATA_PFLAG_INITIALIZING;
+
+	ap->pflags |= ATA_PFLAG_INITIALIZING | ATA_PFLAG_FROZEN;
 	ap->lock = &host->lock;
 	ap->print_id = -1;
 	ap->host = host;
@@ -5887,21 +5888,9 @@
 	host->ops = ops;
 }
 
-
-static void async_port_probe(void *data, async_cookie_t cookie)
+int ata_port_probe(struct ata_port *ap)
 {
-	int rc;
-	struct ata_port *ap = data;
-
-	/*
-	 * If we're not allowed to scan this host in parallel,
-	 * we need to wait until all previous scans have completed
-	 * before going further.
-	 * Jeff Garzik says this is only within a controller, so we
-	 * don't need to wait for port 0, only for later ports.
-	 */
-	if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
-		async_synchronize_cookie(cookie);
+	int rc = 0;
 
 	/* probe */
 	if (ap->ops->error_handler) {
@@ -5927,23 +5916,33 @@
 		DPRINTK("ata%u: bus probe begin\n", ap->print_id);
 		rc = ata_bus_probe(ap);
 		DPRINTK("ata%u: bus probe end\n", ap->print_id);
-
-		if (rc) {
-			/* FIXME: do something useful here?
-			 * Current libata behavior will
-			 * tear down everything when
-			 * the module is removed
-			 * or the h/w is unplugged.
-			 */
-		}
 	}
+	return rc;
+}
+
+
+static void async_port_probe(void *data, async_cookie_t cookie)
+{
+	struct ata_port *ap = data;
+
+	/*
+	 * If we're not allowed to scan this host in parallel,
+	 * we need to wait until all previous scans have completed
+	 * before going further.
+	 * Jeff Garzik says this is only within a controller, so we
+	 * don't need to wait for port 0, only for later ports.
+	 */
+	if (!(ap->host->flags & ATA_HOST_PARALLEL_SCAN) && ap->port_no != 0)
+		async_synchronize_cookie(cookie);
+
+	(void)ata_port_probe(ap);
 
 	/* in order to keep device order, we need to synchronize at this point */
 	async_synchronize_cookie(cookie);
 
 	ata_scsi_scan_host(ap, 1);
-
 }
+
 /**
  *	ata_host_register - register initialized ATA host
  *	@host: ATA host to register
@@ -5983,7 +5982,7 @@
 	for (i = 0; i < host->n_ports; i++)
 		host->ports[i]->print_id = ata_print_id++;
 
-	
+
 	/* Create associated sysfs transport objects  */
 	for (i = 0; i < host->n_ports; i++) {
 		rc = ata_tport_add(host->dev,host->ports[i]);
@@ -6471,7 +6470,7 @@
 		ata_sff_exit();
 		rc = -ENOMEM;
 		goto err_out;
-	}		
+	}
 
 	printk(KERN_DEBUG "libata version " DRV_VERSION " loaded.\n");
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-eh.c linux-libre-2.6.39-gnu/drivers/ata/libata-eh.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-eh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libata-eh.c	2011-05-19 00:06:34.000000000 -0400
@@ -587,11 +587,43 @@
 void ata_scsi_error(struct Scsi_Host *host)
 {
 	struct ata_port *ap = ata_shost_to_port(host);
-	int i;
 	unsigned long flags;
+	LIST_HEAD(eh_work_q);
 
 	DPRINTK("ENTER\n");
 
+	spin_lock_irqsave(host->host_lock, flags);
+	list_splice_init(&host->eh_cmd_q, &eh_work_q);
+	spin_unlock_irqrestore(host->host_lock, flags);
+
+	ata_scsi_cmd_error_handler(host, ap, &eh_work_q);
+
+	/* If we timed raced normal completion and there is nothing to
+	   recover nr_timedout == 0 why exactly are we doing error recovery ? */
+	ata_scsi_port_error_handler(host, ap);
+
+	/* finish or retry handled scmd's and clean up */
+	WARN_ON(host->host_failed || !list_empty(&eh_work_q));
+
+	DPRINTK("EXIT\n");
+}
+
+/**
+ * ata_scsi_cmd_error_handler - error callback for a list of commands
+ * @host:	scsi host containing the port
+ * @ap:		ATA port within the host
+ * @eh_work_q:	list of commands to process
+ *
+ * process the given list of commands and return those finished to the
+ * ap->eh_done_q.  This function is the first part of the libata error
+ * handler which processes a given list of failed commands.
+ */
+void ata_scsi_cmd_error_handler(struct Scsi_Host *host, struct ata_port *ap,
+				struct list_head *eh_work_q)
+{
+	int i;
+	unsigned long flags;
+
 	/* make sure sff pio task is not running */
 	ata_sff_flush_pio_task(ap);
 
@@ -627,7 +659,7 @@
 		if (ap->ops->lost_interrupt)
 			ap->ops->lost_interrupt(ap);
 
-		list_for_each_entry_safe(scmd, tmp, &host->eh_cmd_q, eh_entry) {
+		list_for_each_entry_safe(scmd, tmp, eh_work_q, eh_entry) {
 			struct ata_queued_cmd *qc;
 
 			for (i = 0; i < ATA_MAX_QUEUE; i++) {
@@ -671,8 +703,20 @@
 	} else
 		spin_unlock_wait(ap->lock);
 
-	/* If we timed raced normal completion and there is nothing to
-	   recover nr_timedout == 0 why exactly are we doing error recovery ? */
+}
+EXPORT_SYMBOL(ata_scsi_cmd_error_handler);
+
+/**
+ * ata_scsi_port_error_handler - recover the port after the commands
+ * @host:	SCSI host containing the port
+ * @ap:		the ATA port
+ *
+ * Handle the recovery of the port @ap after all the commands
+ * have been recovered.
+ */
+void ata_scsi_port_error_handler(struct Scsi_Host *host, struct ata_port *ap)
+{
+	unsigned long flags;
 
 	/* invoke error handler */
 	if (ap->ops->error_handler) {
@@ -727,7 +771,7 @@
 		/* process port suspend request */
 		ata_eh_handle_port_suspend(ap);
 
-		/* Exception might have happend after ->error_handler
+		/* Exception might have happened after ->error_handler
 		 * recovered the port but before this point.  Repeat
 		 * EH in such case.
 		 */
@@ -761,9 +805,6 @@
 		ap->ops->eng_timeout(ap);
 	}
 
-	/* finish or retry handled scmd's and clean up */
-	WARN_ON(host->host_failed || !list_empty(&host->eh_cmd_q));
-
 	scsi_eh_flush_done_q(&ap->eh_done_q);
 
 	/* clean up */
@@ -784,9 +825,8 @@
 	wake_up_all(&ap->eh_wait_q);
 
 	spin_unlock_irqrestore(ap->lock, flags);
-
-	DPRINTK("EXIT\n");
 }
+EXPORT_SYMBOL_GPL(ata_scsi_port_error_handler);
 
 /**
  *	ata_port_wait_eh - Wait for the currently pending EH to complete
@@ -1618,7 +1658,7 @@
 	 * host links.  For disabled PMP links, only N bit is
 	 * considered as X bit is left at 1 for link plugging.
 	 */
-	if (link->lpm_policy != ATA_LPM_MAX_POWER)
+	if (link->lpm_policy > ATA_LPM_MAX_POWER)
 		hotplug_mask = 0;	/* hotplug doesn't work w/ LPM */
 	else if (!(link->flags & ATA_LFLAG_DISABLED) || ata_is_host_link(link))
 		hotplug_mask = SERR_PHYRDY_CHG | SERR_DEV_XCHG;
@@ -1702,7 +1742,7 @@
  *
  *	Analyze taskfile of @qc and further determine cause of
  *	failure.  This function also requests ATAPI sense data if
- *	avaliable.
+ *	available.
  *
  *	LOCKING:
  *	Kernel thread context (may sleep).
@@ -1853,7 +1893,7 @@
  *	   occurred during last 5 mins, NCQ_OFF.
  *
  *	3. If more than 8 ATA_BUS, TOUT_HSM or UNK_DEV errors
- *	   ocurred during last 5 mins, FALLBACK_TO_PIO
+ *	   occurred during last 5 mins, FALLBACK_TO_PIO
  *
  *	4. If more than 3 TOUT_HSM or UNK_DEV errors occurred
  *	   during last 10 mins, NCQ_OFF.
@@ -2537,7 +2577,7 @@
 	if (link->flags & ATA_LFLAG_NO_SRST)
 		softreset = NULL;
 
-	/* make sure each reset attemp is at least COOL_DOWN apart */
+	/* make sure each reset attempt is at least COOL_DOWN apart */
 	if (ehc->i.flags & ATA_EHI_DID_RESET) {
 		now = jiffies;
 		WARN_ON(time_after(ehc->last_reset, now));
@@ -2696,7 +2736,7 @@
 			if (!reset) {
 				ata_link_printk(link, KERN_ERR,
 						"follow-up softreset required "
-						"but no softreset avaliable\n");
+						"but no softreset available\n");
 				failed_link = link;
 				rc = -EINVAL;
 				goto fail;
@@ -3276,6 +3316,7 @@
 	struct ata_eh_context *ehc = &link->eh_context;
 	struct ata_device *dev, *link_dev = NULL, *lpm_dev = NULL;
 	enum ata_lpm_policy old_policy = link->lpm_policy;
+	bool no_dipm = link->ap->flags & ATA_FLAG_NO_DIPM;
 	unsigned int hints = ATA_LPM_EMPTY | ATA_LPM_HIPM;
 	unsigned int err_mask;
 	int rc;
@@ -3292,7 +3333,7 @@
 	 */
 	ata_for_each_dev(dev, link, ENABLED) {
 		bool hipm = ata_id_has_hipm(dev->id);
-		bool dipm = ata_id_has_dipm(dev->id);
+		bool dipm = ata_id_has_dipm(dev->id) && !no_dipm;
 
 		/* find the first enabled and LPM enabled devices */
 		if (!link_dev)
@@ -3349,7 +3390,8 @@
 
 	/* host config updated, enable DIPM if transitioning to MIN_POWER */
 	ata_for_each_dev(dev, link, ENABLED) {
-		if (policy == ATA_LPM_MIN_POWER && ata_id_has_dipm(dev->id)) {
+		if (policy == ATA_LPM_MIN_POWER && !no_dipm &&
+		    ata_id_has_dipm(dev->id)) {
 			err_mask = ata_dev_set_feature(dev,
 					SETFEATURES_SATA_ENABLE, SATA_DIPM);
 			if (err_mask && err_mask != AC_ERR_DEV) {
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata.h linux-libre-2.6.39-gnu/drivers/ata/libata.h
--- linux-libre-2.6.38-gnu/drivers/ata/libata.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libata.h	2011-05-19 00:06:34.000000000 -0400
@@ -103,6 +103,7 @@
 extern int ata_cmd_ioctl(struct scsi_device *scsidev, void __user *arg);
 extern struct ata_port *ata_port_alloc(struct ata_host *host);
 extern const char *sata_spd_string(unsigned int spd);
+extern int ata_port_probe(struct ata_port *ap);
 
 /* libata-acpi.c */
 #ifdef CONFIG_ATA_ACPI
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-scsi.c linux-libre-2.6.39-gnu/drivers/ata/libata-scsi.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-scsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libata-scsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -999,7 +999,7 @@
  *	@qc: Command that we are erroring out
  *
  *	Generate sense block for a failed ATA command @qc.  Descriptor
- *	format is used to accomodate LBA48 block address.
+ *	format is used to accommodate LBA48 block address.
  *
  *	LOCKING:
  *	None.
@@ -2056,6 +2056,17 @@
 		      ATA_ID_SERNO_LEN);
 	num += ATA_ID_SERNO_LEN;
 
+	if (ata_id_has_wwn(args->id)) {
+		/* SAT defined lu world wide name */
+		/* piv=0, assoc=lu, code_set=binary, designator=NAA */
+		rbuf[num + 0] = 1;
+		rbuf[num + 1] = 3;
+		rbuf[num + 3] = ATA_ID_WWN_LEN;
+		num += 4;
+		ata_id_string(args->id, (unsigned char *) rbuf + num,
+			      ATA_ID_WWN, ATA_ID_WWN_LEN);
+		num += ATA_ID_WWN_LEN;
+	}
 	rbuf[3] = num - 4;    /* page len (assume less than 256 bytes) */
 	return 0;
 }
@@ -3759,7 +3770,7 @@
 		return NULL;
 
 	ap->port_no = 0;
-	ap->lock = shost->host_lock;
+	ap->lock = &host->lock;
 	ap->pio_mask = port_info->pio_mask;
 	ap->mwdma_mask = port_info->mwdma_mask;
 	ap->udma_mask = port_info->udma_mask;
@@ -3821,7 +3832,7 @@
 
 	if (!rc) {
 		ap->print_id = ata_print_id++;
-		rc = ata_bus_probe(ap);
+		rc = ata_port_probe(ap);
 	}
 
 	return rc;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/libata-sff.c linux-libre-2.6.39-gnu/drivers/ata/libata-sff.c
--- linux-libre-2.6.38-gnu/drivers/ata/libata-sff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/libata-sff.c	2011-05-19 00:06:34.000000000 -0400
@@ -1302,6 +1302,18 @@
 }
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 
+void ata_sff_queue_work(struct work_struct *work)
+{
+	queue_work(ata_sff_wq, work);
+}
+EXPORT_SYMBOL_GPL(ata_sff_queue_work);
+
+void ata_sff_queue_delayed_work(struct delayed_work *dwork, unsigned long delay)
+{
+	queue_delayed_work(ata_sff_wq, dwork, delay);
+}
+EXPORT_SYMBOL_GPL(ata_sff_queue_delayed_work);
+
 void ata_sff_queue_pio_task(struct ata_link *link, unsigned long delay)
 {
 	struct ata_port *ap = link->ap;
@@ -1311,8 +1323,7 @@
 	ap->sff_pio_task_link = link;
 
 	/* may fail if ata_sff_flush_pio_task() in progress */
-	queue_delayed_work(ata_sff_wq, &ap->sff_pio_task,
-			   msecs_to_jiffies(delay));
+	ata_sff_queue_delayed_work(&ap->sff_pio_task, msecs_to_jiffies(delay));
 }
 EXPORT_SYMBOL_GPL(ata_sff_queue_pio_task);
 
@@ -1336,7 +1347,7 @@
 	u8 status;
 	int poll_next;
 
-	BUG_ON(ap->sff_pio_task_link == NULL); 
+	BUG_ON(ap->sff_pio_task_link == NULL);
 	/* qc can be NULL if timeout occurred */
 	qc = ata_qc_from_tag(ap, link->active_tag);
 	if (!qc) {
@@ -2828,7 +2839,7 @@
 		bmdma_stopped = true;
 
 		if (unlikely(host_stat & ATA_DMA_ERR)) {
-			/* error when transfering data to/from memory */
+			/* error when transferring data to/from memory */
 			qc->err_mask |= AC_ERR_HOST_BUS;
 			ap->hsm_task_state = HSM_ST_ERR;
 		}
@@ -3021,7 +3032,7 @@
 	 * Or maybe I'm just being paranoid.
 	 *
 	 * FIXME: The posting of this write means I/O starts are
-	 * unneccessarily delayed for MMIO
+	 * unnecessarily delayed for MMIO
 	 */
 }
 EXPORT_SYMBOL_GPL(ata_bmdma_start);
diff -druN linux-libre-2.6.38-gnu/drivers/ata/Makefile linux-libre-2.6.39-gnu/drivers/ata/Makefile
--- linux-libre-2.6.38-gnu/drivers/ata/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 
 # SFF w/ custom DMA
 obj-$(CONFIG_PDC_ADMA)		+= pdc_adma.o
+obj-$(CONFIG_PATA_ARASAN_CF)	+= pata_arasan_cf.o
 obj-$(CONFIG_PATA_OCTEON_CF)	+= pata_octeon_cf.o
 obj-$(CONFIG_SATA_QSTOR)	+= sata_qstor.o
 obj-$(CONFIG_SATA_SX4)		+= sata_sx4.o
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_acpi.c linux-libre-2.6.39-gnu/drivers/ata/pata_acpi.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -245,7 +245,7 @@
 static int pacpi_init_one (struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	static const struct ata_port_info info = {
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_amd.c linux-libre-2.6.39-gnu/drivers/ata/pata_amd.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_amd.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
  *	Power management on ports
  *
  *
- *  Documentation publically available.
+ *  Documentation publicly available.
  */
 
 #include <linux/kernel.h>
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_arasan_cf.c linux-libre-2.6.39-gnu/drivers/ata/pata_arasan_cf.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_arasan_cf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_arasan_cf.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,983 @@
+/*
+ * drivers/ata/pata_arasan_cf.c
+ *
+ * Arasan Compact Flash host controller source file
+ *
+ * Copyright (C) 2011 ST Microelectronics
+ * Viresh Kumar <viresh.kumar@st.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.
+ */
+
+/*
+ * The Arasan CompactFlash Device Controller IP core has three basic modes of
+ * operation: PC card ATA using I/O mode, PC card ATA using memory mode, PC card
+ * ATA using true IDE modes. This driver supports only True IDE mode currently.
+ *
+ * Arasan CF Controller shares global irq register with Arasan XD Controller.
+ *
+ * Tested on arch/arm/mach-spear13xx
+ */
+
+#include <linux/ata.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/dmaengine.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/libata.h>
+#include <linux/module.h>
+#include <linux/pata_arasan_cf_data.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/workqueue.h>
+
+#define DRIVER_NAME	"arasan_cf"
+#define TIMEOUT		msecs_to_jiffies(3000)
+
+/* Registers */
+/* CompactFlash Interface Status */
+#define CFI_STS			0x000
+	#define STS_CHG				(1)
+	#define BIN_AUDIO_OUT			(1 << 1)
+	#define CARD_DETECT1			(1 << 2)
+	#define CARD_DETECT2			(1 << 3)
+	#define INP_ACK				(1 << 4)
+	#define CARD_READY			(1 << 5)
+	#define IO_READY			(1 << 6)
+	#define B16_IO_PORT_SEL			(1 << 7)
+/* IRQ */
+#define IRQ_STS			0x004
+/* Interrupt Enable */
+#define IRQ_EN			0x008
+	#define CARD_DETECT_IRQ			(1)
+	#define STATUS_CHNG_IRQ			(1 << 1)
+	#define MEM_MODE_IRQ			(1 << 2)
+	#define IO_MODE_IRQ			(1 << 3)
+	#define TRUE_IDE_MODE_IRQ		(1 << 8)
+	#define PIO_XFER_ERR_IRQ		(1 << 9)
+	#define BUF_AVAIL_IRQ			(1 << 10)
+	#define XFER_DONE_IRQ			(1 << 11)
+	#define IGNORED_IRQS	(STATUS_CHNG_IRQ | MEM_MODE_IRQ | IO_MODE_IRQ |\
+					TRUE_IDE_MODE_IRQ)
+	#define TRUE_IDE_IRQS	(CARD_DETECT_IRQ | PIO_XFER_ERR_IRQ |\
+					BUF_AVAIL_IRQ | XFER_DONE_IRQ)
+/* Operation Mode */
+#define OP_MODE			0x00C
+	#define CARD_MODE_MASK			(0x3)
+	#define MEM_MODE			(0x0)
+	#define IO_MODE				(0x1)
+	#define TRUE_IDE_MODE			(0x2)
+
+	#define CARD_TYPE_MASK			(1 << 2)
+	#define CF_CARD				(0)
+	#define CF_PLUS_CARD			(1 << 2)
+
+	#define CARD_RESET			(1 << 3)
+	#define CFHOST_ENB			(1 << 4)
+	#define OUTPUTS_TRISTATE		(1 << 5)
+	#define ULTRA_DMA_ENB			(1 << 8)
+	#define MULTI_WORD_DMA_ENB		(1 << 9)
+	#define DRQ_BLOCK_SIZE_MASK		(0x3 << 11)
+	#define DRQ_BLOCK_SIZE_512		(0)
+	#define DRQ_BLOCK_SIZE_1024		(1 << 11)
+	#define DRQ_BLOCK_SIZE_2048		(2 << 11)
+	#define DRQ_BLOCK_SIZE_4096		(3 << 11)
+/* CF Interface Clock Configuration */
+#define CLK_CFG			0x010
+	#define CF_IF_CLK_MASK			(0XF)
+/* CF Timing Mode Configuration */
+#define TM_CFG			0x014
+	#define MEM_MODE_TIMING_MASK		(0x3)
+	#define MEM_MODE_TIMING_250NS		(0x0)
+	#define MEM_MODE_TIMING_120NS		(0x1)
+	#define MEM_MODE_TIMING_100NS		(0x2)
+	#define MEM_MODE_TIMING_80NS		(0x3)
+
+	#define IO_MODE_TIMING_MASK		(0x3 << 2)
+	#define IO_MODE_TIMING_250NS		(0x0 << 2)
+	#define IO_MODE_TIMING_120NS		(0x1 << 2)
+	#define IO_MODE_TIMING_100NS		(0x2 << 2)
+	#define IO_MODE_TIMING_80NS		(0x3 << 2)
+
+	#define TRUEIDE_PIO_TIMING_MASK		(0x7 << 4)
+	#define TRUEIDE_PIO_TIMING_SHIFT	4
+
+	#define TRUEIDE_MWORD_DMA_TIMING_MASK	(0x7 << 7)
+	#define TRUEIDE_MWORD_DMA_TIMING_SHIFT	7
+
+	#define ULTRA_DMA_TIMING_MASK		(0x7 << 10)
+	#define ULTRA_DMA_TIMING_SHIFT		10
+/* CF Transfer Address */
+#define XFER_ADDR		0x014
+	#define XFER_ADDR_MASK			(0x7FF)
+	#define MAX_XFER_COUNT			0x20000u
+/* Transfer Control */
+#define XFER_CTR		0x01C
+	#define XFER_COUNT_MASK			(0x3FFFF)
+	#define ADDR_INC_DISABLE		(1 << 24)
+	#define XFER_WIDTH_MASK			(1 << 25)
+	#define XFER_WIDTH_8B			(0)
+	#define XFER_WIDTH_16B			(1 << 25)
+
+	#define MEM_TYPE_MASK			(1 << 26)
+	#define MEM_TYPE_COMMON			(0)
+	#define MEM_TYPE_ATTRIBUTE		(1 << 26)
+
+	#define MEM_IO_XFER_MASK		(1 << 27)
+	#define MEM_XFER			(0)
+	#define IO_XFER				(1 << 27)
+
+	#define DMA_XFER_MODE			(1 << 28)
+
+	#define AHB_BUS_NORMAL_PIO_OPRTN	(~(1 << 29))
+	#define XFER_DIR_MASK			(1 << 30)
+	#define XFER_READ			(0)
+	#define XFER_WRITE			(1 << 30)
+
+	#define XFER_START			(1 << 31)
+/* Write Data Port */
+#define WRITE_PORT		0x024
+/* Read Data Port */
+#define READ_PORT		0x028
+/* ATA Data Port */
+#define ATA_DATA_PORT		0x030
+	#define ATA_DATA_PORT_MASK		(0xFFFF)
+/* ATA Error/Features */
+#define ATA_ERR_FTR		0x034
+/* ATA Sector Count */
+#define ATA_SC			0x038
+/* ATA Sector Number */
+#define ATA_SN			0x03C
+/* ATA Cylinder Low */
+#define ATA_CL			0x040
+/* ATA Cylinder High */
+#define ATA_CH			0x044
+/* ATA Select Card/Head */
+#define ATA_SH			0x048
+/* ATA Status-Command */
+#define ATA_STS_CMD		0x04C
+/* ATA Alternate Status/Device Control */
+#define ATA_ASTS_DCTR		0x050
+/* Extended Write Data Port 0x200-0x3FC */
+#define EXT_WRITE_PORT		0x200
+/* Extended Read Data Port 0x400-0x5FC */
+#define EXT_READ_PORT		0x400
+	#define FIFO_SIZE	0x200u
+/* Global Interrupt Status */
+#define GIRQ_STS		0x800
+/* Global Interrupt Status enable */
+#define GIRQ_STS_EN		0x804
+/* Global Interrupt Signal enable */
+#define GIRQ_SGN_EN		0x808
+	#define GIRQ_CF		(1)
+	#define GIRQ_XD		(1 << 1)
+
+/* Compact Flash Controller Dev Structure */
+struct arasan_cf_dev {
+	/* pointer to ata_host structure */
+	struct ata_host *host;
+	/* clk structure, only if HAVE_CLK is defined */
+#ifdef CONFIG_HAVE_CLK
+	struct clk *clk;
+#endif
+
+	/* physical base address of controller */
+	dma_addr_t pbase;
+	/* virtual base address of controller */
+	void __iomem *vbase;
+	/* irq number*/
+	int irq;
+
+	/* status to be updated to framework regarding DMA transfer */
+	u8 dma_status;
+	/* Card is present or Not */
+	u8 card_present;
+
+	/* dma specific */
+	/* Completion for transfer complete interrupt from controller */
+	struct completion cf_completion;
+	/* Completion for DMA transfer complete. */
+	struct completion dma_completion;
+	/* Dma channel allocated */
+	struct dma_chan *dma_chan;
+	/* Mask for DMA transfers */
+	dma_cap_mask_t mask;
+	/* dma channel private data */
+	void *dma_priv;
+	/* DMA transfer work */
+	struct work_struct work;
+	/* DMA delayed finish work */
+	struct delayed_work dwork;
+	/* qc to be transferred using DMA */
+	struct ata_queued_cmd *qc;
+};
+
+static struct scsi_host_template arasan_cf_sht = {
+	ATA_BASE_SHT(DRIVER_NAME),
+	.sg_tablesize = SG_NONE,
+	.dma_boundary = 0xFFFFFFFFUL,
+};
+
+static void cf_dumpregs(struct arasan_cf_dev *acdev)
+{
+	struct device *dev = acdev->host->dev;
+
+	dev_dbg(dev, ": =========== REGISTER DUMP ===========");
+	dev_dbg(dev, ": CFI_STS: %x", readl(acdev->vbase + CFI_STS));
+	dev_dbg(dev, ": IRQ_STS: %x", readl(acdev->vbase + IRQ_STS));
+	dev_dbg(dev, ": IRQ_EN: %x", readl(acdev->vbase + IRQ_EN));
+	dev_dbg(dev, ": OP_MODE: %x", readl(acdev->vbase + OP_MODE));
+	dev_dbg(dev, ": CLK_CFG: %x", readl(acdev->vbase + CLK_CFG));
+	dev_dbg(dev, ": TM_CFG: %x", readl(acdev->vbase + TM_CFG));
+	dev_dbg(dev, ": XFER_CTR: %x", readl(acdev->vbase + XFER_CTR));
+	dev_dbg(dev, ": GIRQ_STS: %x", readl(acdev->vbase + GIRQ_STS));
+	dev_dbg(dev, ": GIRQ_STS_EN: %x", readl(acdev->vbase + GIRQ_STS_EN));
+	dev_dbg(dev, ": GIRQ_SGN_EN: %x", readl(acdev->vbase + GIRQ_SGN_EN));
+	dev_dbg(dev, ": =====================================");
+}
+
+/* Enable/Disable global interrupts shared between CF and XD ctrlr. */
+static void cf_ginterrupt_enable(struct arasan_cf_dev *acdev, bool enable)
+{
+	/* enable should be 0 or 1 */
+	writel(enable, acdev->vbase + GIRQ_STS_EN);
+	writel(enable, acdev->vbase + GIRQ_SGN_EN);
+}
+
+/* Enable/Disable CF interrupts */
+static inline void
+cf_interrupt_enable(struct arasan_cf_dev *acdev, u32 mask, bool enable)
+{
+	u32 val = readl(acdev->vbase + IRQ_EN);
+	/* clear & enable/disable irqs */
+	if (enable) {
+		writel(mask, acdev->vbase + IRQ_STS);
+		writel(val | mask, acdev->vbase + IRQ_EN);
+	} else
+		writel(val & ~mask, acdev->vbase + IRQ_EN);
+}
+
+static inline void cf_card_reset(struct arasan_cf_dev *acdev)
+{
+	u32 val = readl(acdev->vbase + OP_MODE);
+
+	writel(val | CARD_RESET, acdev->vbase + OP_MODE);
+	udelay(200);
+	writel(val & ~CARD_RESET, acdev->vbase + OP_MODE);
+}
+
+static inline void cf_ctrl_reset(struct arasan_cf_dev *acdev)
+{
+	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB,
+			acdev->vbase + OP_MODE);
+	writel(readl(acdev->vbase + OP_MODE) | CFHOST_ENB,
+			acdev->vbase + OP_MODE);
+}
+
+static void cf_card_detect(struct arasan_cf_dev *acdev, bool hotplugged)
+{
+	struct ata_port *ap = acdev->host->ports[0];
+	struct ata_eh_info *ehi = &ap->link.eh_info;
+	u32 val = readl(acdev->vbase + CFI_STS);
+
+	/* Both CD1 & CD2 should be low if card inserted completely */
+	if (!(val & (CARD_DETECT1 | CARD_DETECT2))) {
+		if (acdev->card_present)
+			return;
+		acdev->card_present = 1;
+		cf_card_reset(acdev);
+	} else {
+		if (!acdev->card_present)
+			return;
+		acdev->card_present = 0;
+	}
+
+	if (hotplugged) {
+		ata_ehi_hotplugged(ehi);
+		ata_port_freeze(ap);
+	}
+}
+
+static int cf_init(struct arasan_cf_dev *acdev)
+{
+	struct arasan_cf_pdata *pdata = dev_get_platdata(acdev->host->dev);
+	unsigned long flags;
+	int ret = 0;
+
+#ifdef CONFIG_HAVE_CLK
+	ret = clk_enable(acdev->clk);
+	if (ret) {
+		dev_dbg(acdev->host->dev, "clock enable failed");
+		return ret;
+	}
+#endif
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	/* configure CF interface clock */
+	writel((pdata->cf_if_clk <= CF_IF_CLK_200M) ? pdata->cf_if_clk :
+			CF_IF_CLK_166M, acdev->vbase + CLK_CFG);
+
+	writel(TRUE_IDE_MODE | CFHOST_ENB, acdev->vbase + OP_MODE);
+	cf_interrupt_enable(acdev, CARD_DETECT_IRQ, 1);
+	cf_ginterrupt_enable(acdev, 1);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	return ret;
+}
+
+static void cf_exit(struct arasan_cf_dev *acdev)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	cf_ginterrupt_enable(acdev, 0);
+	cf_interrupt_enable(acdev, TRUE_IDE_IRQS, 0);
+	cf_card_reset(acdev);
+	writel(readl(acdev->vbase + OP_MODE) & ~CFHOST_ENB,
+			acdev->vbase + OP_MODE);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+#ifdef CONFIG_HAVE_CLK
+	clk_disable(acdev->clk);
+#endif
+}
+
+static void dma_callback(void *dev)
+{
+	struct arasan_cf_dev *acdev = (struct arasan_cf_dev *) dev;
+
+	complete(&acdev->dma_completion);
+}
+
+static bool filter(struct dma_chan *chan, void *slave)
+{
+	chan->private = slave;
+	return true;
+}
+
+static inline void dma_complete(struct arasan_cf_dev *acdev)
+{
+	struct ata_queued_cmd *qc = acdev->qc;
+	unsigned long flags;
+
+	acdev->qc = NULL;
+	ata_sff_interrupt(acdev->irq, acdev->host);
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	if (unlikely(qc->err_mask) && ata_is_dma(qc->tf.protocol))
+		ata_ehi_push_desc(&qc->ap->link.eh_info, "DMA Failed: Timeout");
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+}
+
+static inline int wait4buf(struct arasan_cf_dev *acdev)
+{
+	if (!wait_for_completion_timeout(&acdev->cf_completion, TIMEOUT)) {
+		u32 rw = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+
+		dev_err(acdev->host->dev, "%s TimeOut", rw ? "write" : "read");
+		return -ETIMEDOUT;
+	}
+
+	/* Check if PIO Error interrupt has occurred */
+	if (acdev->dma_status & ATA_DMA_ERR)
+		return -EAGAIN;
+
+	return 0;
+}
+
+static int
+dma_xfer(struct arasan_cf_dev *acdev, dma_addr_t src, dma_addr_t dest, u32 len)
+{
+	struct dma_async_tx_descriptor *tx;
+	struct dma_chan *chan = acdev->dma_chan;
+	dma_cookie_t cookie;
+	unsigned long flags = DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP |
+		DMA_COMPL_SKIP_DEST_UNMAP;
+	int ret = 0;
+
+	tx = chan->device->device_prep_dma_memcpy(chan, dest, src, len, flags);
+	if (!tx) {
+		dev_err(acdev->host->dev, "device_prep_dma_memcpy failed\n");
+		return -EAGAIN;
+	}
+
+	tx->callback = dma_callback;
+	tx->callback_param = acdev;
+	cookie = tx->tx_submit(tx);
+
+	ret = dma_submit_error(cookie);
+	if (ret) {
+		dev_err(acdev->host->dev, "dma_submit_error\n");
+		return ret;
+	}
+
+	chan->device->device_issue_pending(chan);
+
+	/* Wait for DMA to complete */
+	if (!wait_for_completion_timeout(&acdev->dma_completion, TIMEOUT)) {
+		chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		dev_err(acdev->host->dev, "wait_for_completion_timeout\n");
+		return -ETIMEDOUT;
+	}
+
+	return ret;
+}
+
+static int sg_xfer(struct arasan_cf_dev *acdev, struct scatterlist *sg)
+{
+	dma_addr_t dest = 0, src = 0;
+	u32 xfer_cnt, sglen, dma_len, xfer_ctr;
+	u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+	unsigned long flags;
+	int ret = 0;
+
+	sglen = sg_dma_len(sg);
+	if (write) {
+		src = sg_dma_address(sg);
+		dest = acdev->pbase + EXT_WRITE_PORT;
+	} else {
+		dest = sg_dma_address(sg);
+		src = acdev->pbase + EXT_READ_PORT;
+	}
+
+	/*
+	 * For each sg:
+	 * MAX_XFER_COUNT data will be transferred before we get transfer
+	 * complete interrupt. Between after FIFO_SIZE data
+	 * buffer available interrupt will be generated. At this time we will
+	 * fill FIFO again: max FIFO_SIZE data.
+	 */
+	while (sglen) {
+		xfer_cnt = min(sglen, MAX_XFER_COUNT);
+		spin_lock_irqsave(&acdev->host->lock, flags);
+		xfer_ctr = readl(acdev->vbase + XFER_CTR) &
+			~XFER_COUNT_MASK;
+		writel(xfer_ctr | xfer_cnt | XFER_START,
+				acdev->vbase + XFER_CTR);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+		/* continue dma xfers until current sg is completed */
+		while (xfer_cnt) {
+			/* wait for read to complete */
+			if (!write) {
+				ret = wait4buf(acdev);
+				if (ret)
+					goto fail;
+			}
+
+			/* read/write FIFO in chunk of FIFO_SIZE */
+			dma_len = min(xfer_cnt, FIFO_SIZE);
+			ret = dma_xfer(acdev, src, dest, dma_len);
+			if (ret) {
+				dev_err(acdev->host->dev, "dma failed");
+				goto fail;
+			}
+
+			if (write)
+				src += dma_len;
+			else
+				dest += dma_len;
+
+			sglen -= dma_len;
+			xfer_cnt -= dma_len;
+
+			/* wait for write to complete */
+			if (write) {
+				ret = wait4buf(acdev);
+				if (ret)
+					goto fail;
+			}
+		}
+	}
+
+fail:
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START,
+			acdev->vbase + XFER_CTR);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	return ret;
+}
+
+/*
+ * This routine uses External DMA controller to read/write data to FIFO of CF
+ * controller. There are two xfer related interrupt supported by CF controller:
+ * - buf_avail: This interrupt is generated as soon as we have buffer of 512
+ *	bytes available for reading or empty buffer available for writing.
+ * - xfer_done: This interrupt is generated on transfer of "xfer_size" amount of
+ *	data to/from FIFO. xfer_size is programmed in XFER_CTR register.
+ *
+ * Max buffer size = FIFO_SIZE = 512 Bytes.
+ * Max xfer_size = MAX_XFER_COUNT = 256 KB.
+ */
+static void data_xfer(struct work_struct *work)
+{
+	struct arasan_cf_dev *acdev = container_of(work, struct arasan_cf_dev,
+			work);
+	struct ata_queued_cmd *qc = acdev->qc;
+	struct scatterlist *sg;
+	unsigned long flags;
+	u32 temp;
+	int ret = 0;
+
+	/* request dma channels */
+	/* dma_request_channel may sleep, so calling from process context */
+	acdev->dma_chan = dma_request_channel(acdev->mask, filter,
+			acdev->dma_priv);
+	if (!acdev->dma_chan) {
+		dev_err(acdev->host->dev, "Unable to get dma_chan\n");
+		goto chan_request_fail;
+	}
+
+	for_each_sg(qc->sg, sg, qc->n_elem, temp) {
+		ret = sg_xfer(acdev, sg);
+		if (ret)
+			break;
+	}
+
+	dma_release_channel(acdev->dma_chan);
+
+	/* data xferred successfully */
+	if (!ret) {
+		u32 status;
+
+		spin_lock_irqsave(&acdev->host->lock, flags);
+		status = ioread8(qc->ap->ioaddr.altstatus_addr);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		if (status & (ATA_BUSY | ATA_DRQ)) {
+			ata_sff_queue_delayed_work(&acdev->dwork, 1);
+			return;
+		}
+
+		goto sff_intr;
+	}
+
+	cf_dumpregs(acdev);
+
+chan_request_fail:
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	/* error when transferring data to/from memory */
+	qc->err_mask |= AC_ERR_HOST_BUS;
+	qc->ap->hsm_task_state = HSM_ST_ERR;
+
+	cf_ctrl_reset(acdev);
+	spin_unlock_irqrestore(qc->ap->lock, flags);
+sff_intr:
+	dma_complete(acdev);
+}
+
+static void delayed_finish(struct work_struct *work)
+{
+	struct arasan_cf_dev *acdev = container_of(work, struct arasan_cf_dev,
+			dwork.work);
+	struct ata_queued_cmd *qc = acdev->qc;
+	unsigned long flags;
+	u8 status;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	status = ioread8(qc->ap->ioaddr.altstatus_addr);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	if (status & (ATA_BUSY | ATA_DRQ))
+		ata_sff_queue_delayed_work(&acdev->dwork, 1);
+	else
+		dma_complete(acdev);
+}
+
+static irqreturn_t arasan_cf_interrupt(int irq, void *dev)
+{
+	struct arasan_cf_dev *acdev = ((struct ata_host *)dev)->private_data;
+	unsigned long flags;
+	u32 irqsts;
+
+	irqsts = readl(acdev->vbase + GIRQ_STS);
+	if (!(irqsts & GIRQ_CF))
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	irqsts = readl(acdev->vbase + IRQ_STS);
+	writel(irqsts, acdev->vbase + IRQ_STS);		/* clear irqs */
+	writel(GIRQ_CF, acdev->vbase + GIRQ_STS);	/* clear girqs */
+
+	/* handle only relevant interrupts */
+	irqsts &= ~IGNORED_IRQS;
+
+	if (irqsts & CARD_DETECT_IRQ) {
+		cf_card_detect(acdev, 1);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		return IRQ_HANDLED;
+	}
+
+	if (irqsts & PIO_XFER_ERR_IRQ) {
+		acdev->dma_status = ATA_DMA_ERR;
+		writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START,
+				acdev->vbase + XFER_CTR);
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		complete(&acdev->cf_completion);
+		dev_err(acdev->host->dev, "pio xfer err irq\n");
+		return IRQ_HANDLED;
+	}
+
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+
+	if (irqsts & BUF_AVAIL_IRQ) {
+		complete(&acdev->cf_completion);
+		return IRQ_HANDLED;
+	}
+
+	if (irqsts & XFER_DONE_IRQ) {
+		struct ata_queued_cmd *qc = acdev->qc;
+
+		/* Send Complete only for write */
+		if (qc->tf.flags & ATA_TFLAG_WRITE)
+			complete(&acdev->cf_completion);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static void arasan_cf_freeze(struct ata_port *ap)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+
+	/* stop transfer and reset controller */
+	writel(readl(acdev->vbase + XFER_CTR) & ~XFER_START,
+			acdev->vbase + XFER_CTR);
+	cf_ctrl_reset(acdev);
+	acdev->dma_status = ATA_DMA_ERR;
+
+	ata_sff_dma_pause(ap);
+	ata_sff_freeze(ap);
+}
+
+void arasan_cf_error_handler(struct ata_port *ap)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+
+	/*
+	 * DMA transfers using an external DMA controller may be scheduled.
+	 * Abort them before handling error. Refer data_xfer() for further
+	 * details.
+	 */
+	cancel_work_sync(&acdev->work);
+	cancel_delayed_work_sync(&acdev->dwork);
+	return ata_sff_error_handler(ap);
+}
+
+static void arasan_cf_dma_start(struct arasan_cf_dev *acdev)
+{
+	u32 xfer_ctr = readl(acdev->vbase + XFER_CTR) & ~XFER_DIR_MASK;
+	u32 write = acdev->qc->tf.flags & ATA_TFLAG_WRITE;
+
+	xfer_ctr |= write ? XFER_WRITE : XFER_READ;
+	writel(xfer_ctr, acdev->vbase + XFER_CTR);
+
+	acdev->qc->ap->ops->sff_exec_command(acdev->qc->ap, &acdev->qc->tf);
+	ata_sff_queue_work(&acdev->work);
+}
+
+unsigned int arasan_cf_qc_issue(struct ata_queued_cmd *qc)
+{
+	struct ata_port *ap = qc->ap;
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+
+	/* defer PIO handling to sff_qc_issue */
+	if (!ata_is_dma(qc->tf.protocol))
+		return ata_sff_qc_issue(qc);
+
+	/* select the device */
+	ata_wait_idle(ap);
+	ata_sff_dev_select(ap, qc->dev->devno);
+	ata_wait_idle(ap);
+
+	/* start the command */
+	switch (qc->tf.protocol) {
+	case ATA_PROT_DMA:
+		WARN_ON_ONCE(qc->tf.flags & ATA_TFLAG_POLLING);
+
+		ap->ops->sff_tf_load(ap, &qc->tf);
+		acdev->dma_status = 0;
+		acdev->qc = qc;
+		arasan_cf_dma_start(acdev);
+		ap->hsm_task_state = HSM_ST_LAST;
+		break;
+
+	default:
+		WARN_ON(1);
+		return AC_ERR_SYSTEM;
+	}
+
+	return 0;
+}
+
+static void arasan_cf_set_piomode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+	u8 pio = adev->pio_mode - XFER_PIO_0;
+	unsigned long flags;
+	u32 val;
+
+	/* Arasan ctrl supports Mode0 -> Mode6 */
+	if (pio > 6) {
+		dev_err(ap->dev, "Unknown PIO mode\n");
+		return;
+	}
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	val = readl(acdev->vbase + OP_MODE) &
+		~(ULTRA_DMA_ENB | MULTI_WORD_DMA_ENB | DRQ_BLOCK_SIZE_MASK);
+	writel(val, acdev->vbase + OP_MODE);
+	val = readl(acdev->vbase + TM_CFG) & ~TRUEIDE_PIO_TIMING_MASK;
+	val |= pio << TRUEIDE_PIO_TIMING_SHIFT;
+	writel(val, acdev->vbase + TM_CFG);
+
+	cf_interrupt_enable(acdev, BUF_AVAIL_IRQ | XFER_DONE_IRQ, 0);
+	cf_interrupt_enable(acdev, PIO_XFER_ERR_IRQ, 1);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+}
+
+static void arasan_cf_set_dmamode(struct ata_port *ap, struct ata_device *adev)
+{
+	struct arasan_cf_dev *acdev = ap->host->private_data;
+	u32 opmode, tmcfg, dma_mode = adev->dma_mode;
+	unsigned long flags;
+
+	spin_lock_irqsave(&acdev->host->lock, flags);
+	opmode = readl(acdev->vbase + OP_MODE) &
+		~(MULTI_WORD_DMA_ENB | ULTRA_DMA_ENB);
+	tmcfg = readl(acdev->vbase + TM_CFG);
+
+	if ((dma_mode >= XFER_UDMA_0) && (dma_mode <= XFER_UDMA_6)) {
+		opmode |= ULTRA_DMA_ENB;
+		tmcfg &= ~ULTRA_DMA_TIMING_MASK;
+		tmcfg |= (dma_mode - XFER_UDMA_0) << ULTRA_DMA_TIMING_SHIFT;
+	} else if ((dma_mode >= XFER_MW_DMA_0) && (dma_mode <= XFER_MW_DMA_4)) {
+		opmode |= MULTI_WORD_DMA_ENB;
+		tmcfg &= ~TRUEIDE_MWORD_DMA_TIMING_MASK;
+		tmcfg |= (dma_mode - XFER_MW_DMA_0) <<
+			TRUEIDE_MWORD_DMA_TIMING_SHIFT;
+	} else {
+		dev_err(ap->dev, "Unknown DMA mode\n");
+		spin_unlock_irqrestore(&acdev->host->lock, flags);
+		return;
+	}
+
+	writel(opmode, acdev->vbase + OP_MODE);
+	writel(tmcfg, acdev->vbase + TM_CFG);
+	writel(DMA_XFER_MODE, acdev->vbase + XFER_CTR);
+
+	cf_interrupt_enable(acdev, PIO_XFER_ERR_IRQ, 0);
+	cf_interrupt_enable(acdev, BUF_AVAIL_IRQ | XFER_DONE_IRQ, 1);
+	spin_unlock_irqrestore(&acdev->host->lock, flags);
+}
+
+static struct ata_port_operations arasan_cf_ops = {
+	.inherits = &ata_sff_port_ops,
+	.freeze = arasan_cf_freeze,
+	.error_handler = arasan_cf_error_handler,
+	.qc_issue = arasan_cf_qc_issue,
+	.set_piomode = arasan_cf_set_piomode,
+	.set_dmamode = arasan_cf_set_dmamode,
+};
+
+static int __devinit arasan_cf_probe(struct platform_device *pdev)
+{
+	struct arasan_cf_dev *acdev;
+	struct arasan_cf_pdata *pdata = dev_get_platdata(&pdev->dev);
+	struct ata_host *host;
+	struct ata_port *ap;
+	struct resource *res;
+	irq_handler_t irq_handler = NULL;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EINVAL;
+
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				DRIVER_NAME)) {
+		dev_warn(&pdev->dev, "Failed to get memory region resource\n");
+		return -ENOENT;
+	}
+
+	acdev = devm_kzalloc(&pdev->dev, sizeof(*acdev), GFP_KERNEL);
+	if (!acdev) {
+		dev_warn(&pdev->dev, "kzalloc fail\n");
+		return -ENOMEM;
+	}
+
+	/* if irq is 0, support only PIO */
+	acdev->irq = platform_get_irq(pdev, 0);
+	if (acdev->irq)
+		irq_handler = arasan_cf_interrupt;
+	else
+		pdata->quirk |= CF_BROKEN_MWDMA | CF_BROKEN_UDMA;
+
+	acdev->pbase = res->start;
+	acdev->vbase = devm_ioremap_nocache(&pdev->dev, res->start,
+			resource_size(res));
+	if (!acdev->vbase) {
+		dev_warn(&pdev->dev, "ioremap fail\n");
+		return -ENOMEM;
+	}
+
+#ifdef CONFIG_HAVE_CLK
+	acdev->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(acdev->clk)) {
+		dev_warn(&pdev->dev, "Clock not found\n");
+		return PTR_ERR(acdev->clk);
+	}
+#endif
+
+	/* allocate host */
+	host = ata_host_alloc(&pdev->dev, 1);
+	if (!host) {
+		ret = -ENOMEM;
+		dev_warn(&pdev->dev, "alloc host fail\n");
+		goto free_clk;
+	}
+
+	ap = host->ports[0];
+	host->private_data = acdev;
+	acdev->host = host;
+	ap->ops = &arasan_cf_ops;
+	ap->pio_mask = ATA_PIO6;
+	ap->mwdma_mask = ATA_MWDMA4;
+	ap->udma_mask = ATA_UDMA6;
+
+	init_completion(&acdev->cf_completion);
+	init_completion(&acdev->dma_completion);
+	INIT_WORK(&acdev->work, data_xfer);
+	INIT_DELAYED_WORK(&acdev->dwork, delayed_finish);
+	dma_cap_set(DMA_MEMCPY, acdev->mask);
+	acdev->dma_priv = pdata->dma_priv;
+
+	/* Handle platform specific quirks */
+	if (pdata->quirk) {
+		if (pdata->quirk & CF_BROKEN_PIO) {
+			ap->ops->set_piomode = NULL;
+			ap->pio_mask = 0;
+		}
+		if (pdata->quirk & CF_BROKEN_MWDMA)
+			ap->mwdma_mask = 0;
+		if (pdata->quirk & CF_BROKEN_UDMA)
+			ap->udma_mask = 0;
+	}
+	ap->flags |= ATA_FLAG_PIO_POLLING | ATA_FLAG_NO_ATAPI;
+
+	ap->ioaddr.cmd_addr = acdev->vbase + ATA_DATA_PORT;
+	ap->ioaddr.data_addr = acdev->vbase + ATA_DATA_PORT;
+	ap->ioaddr.error_addr = acdev->vbase + ATA_ERR_FTR;
+	ap->ioaddr.feature_addr = acdev->vbase + ATA_ERR_FTR;
+	ap->ioaddr.nsect_addr = acdev->vbase + ATA_SC;
+	ap->ioaddr.lbal_addr = acdev->vbase + ATA_SN;
+	ap->ioaddr.lbam_addr = acdev->vbase + ATA_CL;
+	ap->ioaddr.lbah_addr = acdev->vbase + ATA_CH;
+	ap->ioaddr.device_addr = acdev->vbase + ATA_SH;
+	ap->ioaddr.status_addr = acdev->vbase + ATA_STS_CMD;
+	ap->ioaddr.command_addr = acdev->vbase + ATA_STS_CMD;
+	ap->ioaddr.altstatus_addr = acdev->vbase + ATA_ASTS_DCTR;
+	ap->ioaddr.ctl_addr = acdev->vbase + ATA_ASTS_DCTR;
+
+	ata_port_desc(ap, "phy_addr %llx virt_addr %p",
+		      (unsigned long long) res->start, acdev->vbase);
+
+	ret = cf_init(acdev);
+	if (ret)
+		goto free_clk;
+
+	cf_card_detect(acdev, 0);
+
+	return ata_host_activate(host, acdev->irq, irq_handler, 0,
+			&arasan_cf_sht);
+
+free_clk:
+#ifdef CONFIG_HAVE_CLK
+	clk_put(acdev->clk);
+#endif
+	return ret;
+}
+
+static int __devexit arasan_cf_remove(struct platform_device *pdev)
+{
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
+
+	ata_host_detach(host);
+	cf_exit(acdev);
+#ifdef CONFIG_HAVE_CLK
+	clk_put(acdev->clk);
+#endif
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int arasan_cf_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
+
+	if (acdev->dma_chan) {
+		acdev->dma_chan->device->device_control(acdev->dma_chan,
+				DMA_TERMINATE_ALL, 0);
+		dma_release_channel(acdev->dma_chan);
+	}
+	cf_exit(acdev);
+	return ata_host_suspend(host, PMSG_SUSPEND);
+}
+
+static int arasan_cf_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct ata_host *host = dev_get_drvdata(&pdev->dev);
+	struct arasan_cf_dev *acdev = host->ports[0]->private_data;
+
+	cf_init(acdev);
+	ata_host_resume(host);
+
+	return 0;
+}
+
+static const struct dev_pm_ops arasan_cf_pm_ops = {
+	.suspend	= arasan_cf_suspend,
+	.resume		= arasan_cf_resume,
+};
+#endif
+
+static struct platform_driver arasan_cf_driver = {
+	.probe		= arasan_cf_probe,
+	.remove		= __devexit_p(arasan_cf_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm		= &arasan_cf_pm_ops,
+#endif
+	},
+};
+
+static int __init arasan_cf_init(void)
+{
+	return platform_driver_register(&arasan_cf_driver);
+}
+module_init(arasan_cf_init);
+
+static void __exit arasan_cf_exit(void)
+{
+	platform_driver_unregister(&arasan_cf_driver);
+}
+module_exit(arasan_cf_exit);
+
+MODULE_AUTHOR("Viresh Kumar <viresh.kumar@st.com>");
+MODULE_DESCRIPTION("Arasan ATA Compact Flash driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_at32.c linux-libre-2.6.39-gnu/drivers/ata/pata_at32.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_at32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_at32.c	2011-05-19 00:06:34.000000000 -0400
@@ -194,7 +194,7 @@
 	/* Setup ATA bindings */
 	ap->ops	     = &at32_port_ops;
 	ap->pio_mask = PIO_MASK;
-	ap->flags   |= ATA_FLAG_MMIO | ATA_FLAG_SLAVE_POSS;
+	ap->flags   |= ATA_FLAG_SLAVE_POSS;
 
 	/*
 	 * Since all 8-bit taskfile transfers has to go on the lower
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_at91.c linux-libre-2.6.39-gnu/drivers/ata/pata_at91.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_at91.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_at91.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,11 +33,12 @@
 
 
 #define DRV_NAME "pata_at91"
-#define DRV_VERSION "0.1"
+#define DRV_VERSION "0.2"
 
 #define CF_IDE_OFFSET	    0x00c00000
 #define CF_ALT_IDE_OFFSET   0x00e00000
 #define CF_IDE_RES_SIZE     0x08
+#define NCS_RD_PULSE_LIMIT  0x3f /* maximal value for pulse bitfields */
 
 struct at91_ide_info {
 	unsigned long mode;
@@ -49,8 +50,18 @@
 	void __iomem *alt_addr;
 };
 
-static const struct ata_timing initial_timing =
-	{XFER_PIO_0, 70, 290, 240, 600, 165, 150, 600, 0};
+static const struct ata_timing initial_timing = {
+	.mode		= XFER_PIO_0,
+	.setup		= 70,
+	.act8b		= 290,
+	.rec8b		= 240,
+	.cyc8b		= 600,
+	.active		= 165,
+	.recover	= 150,
+	.dmack_hold	= 0,
+	.cycle		= 600,
+	.udma		= 0
+};
 
 static unsigned long calc_mck_cycles(unsigned long ns, unsigned long mck_hz)
 {
@@ -109,6 +120,11 @@
 	/* (CS0, CS1, DIR, OE) <= (CFCE1, CFCE2, CFRNW, NCSX) timings */
 	ncs_read_setup = 1;
 	ncs_read_pulse = read_cycle - 2;
+	if (ncs_read_pulse > NCS_RD_PULSE_LIMIT) {
+		ncs_read_pulse = NCS_RD_PULSE_LIMIT;
+		dev_warn(dev, "ncs_read_pulse limited to maximal value %lu\n",
+			ncs_read_pulse);
+	}
 
 	/* Write timings same as read timings */
 	write_cycle = read_cycle;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_bf54x.c linux-libre-2.6.39-gnu/drivers/ata/pata_bf54x.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_bf54x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_bf54x.c	2011-05-19 00:06:34.000000000 -0400
@@ -1342,7 +1342,7 @@
 			ap->ops->bmdma_stop(qc);
 
 			if (unlikely(host_stat & ATA_DMA_ERR)) {
-				/* error when transfering data to/from memory */
+				/* error when transferring data to/from memory */
 				qc->err_mask |= AC_ERR_HOST_BUS;
 				ap->hsm_task_state = HSM_ST_ERR;
 			}
@@ -1454,9 +1454,7 @@
 
 static struct ata_port_info bfin_port_info[] = {
 	{
-		.flags		= ATA_FLAG_SLAVE_POSS
-				| ATA_FLAG_MMIO
-				| ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= 0,
 		.udma_mask	= 0,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_cs5520.c linux-libre-2.6.39-gnu/drivers/ata/pata_cs5520.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_cs5520.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_cs5520.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
  * General Public License for more details.
  *
  * Documentation:
- *	Not publically available.
+ *	Not publicly available.
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_hpt366.c linux-libre-2.6.39-gnu/drivers/ata/pata_hpt366.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_hpt366.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_hpt366.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
  *	Look into engine reset on timeout errors. Should not be required.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -25,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt366"
-#define DRV_VERSION	"0.6.10"
+#define DRV_VERSION	"0.6.11"
 
 struct hpt_clock {
 	u8	xfer_mode;
@@ -160,8 +161,8 @@
 
 	while (list[i] != NULL) {
 		if (!strcmp(list[i], model_num)) {
-			pr_warning(DRV_NAME ": %s is not supported for %s.\n",
-				   modestr, list[i]);
+			pr_warn("%s is not supported for %s\n",
+				modestr, list[i]);
 			return 1;
 		}
 		i++;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_hpt37x.c linux-libre-2.6.39-gnu/drivers/ata/pata_hpt37x.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_hpt37x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_hpt37x.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,8 @@
  *	Look into engine reset on timeout errors. Should not be	required.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -24,7 +26,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt37x"
-#define DRV_VERSION	"0.6.22"
+#define DRV_VERSION	"0.6.23"
 
 struct hpt_clock {
 	u8	xfer_speed;
@@ -229,8 +231,8 @@
 
 	while (list[i] != NULL) {
 		if (!strcmp(list[i], model_num)) {
-			pr_warning(DRV_NAME ": %s is not supported for %s.\n",
-				   modestr, list[i]);
+			pr_warn("%s is not supported for %s\n",
+				modestr, list[i]);
 			return 1;
 		}
 		i++;
@@ -863,8 +865,8 @@
 			chip_table = &hpt372;
 			break;
 		default:
-			pr_err(DRV_NAME ": Unknown HPT366 subtype, "
-			       "please report (%d).\n", rev);
+			pr_err("Unknown HPT366 subtype, please report (%d)\n",
+			       rev);
 			return -ENODEV;
 		}
 		break;
@@ -904,8 +906,7 @@
 			*ppi = &info_hpt374_fn1;
 		break;
 	default:
-		pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
-		       dev->device);
+		pr_err("PCI table is bogus, please report (%d)\n", dev->device);
 		return -ENODEV;
 	}
 	/* Ok so this is a chip we support */
@@ -953,7 +954,7 @@
 		u8 sr;
 		u32 total = 0;
 
-		pr_warning(DRV_NAME ": BIOS has not set timing clocks.\n");
+		pr_warn("BIOS has not set timing clocks\n");
 
 		/* This is the process the HPT371 BIOS is reported to use */
 		for (i = 0; i < 128; i++) {
@@ -1009,7 +1010,7 @@
 					       (f_high << 16) | f_low | 0x100);
 		}
 		if (adjust == 8) {
-			pr_err(DRV_NAME ": DPLL did not stabilize!\n");
+			pr_err("DPLL did not stabilize!\n");
 			return -ENODEV;
 		}
 		if (dpll == 3)
@@ -1017,7 +1018,7 @@
 		else
 			private_data = (void *)hpt37x_timings_50;
 
-		pr_info(DRV_NAME ": bus clock %dMHz, using %dMHz DPLL.\n",
+		pr_info("bus clock %dMHz, using %dMHz DPLL\n",
 			MHz[clock_slot], MHz[dpll]);
 	} else {
 		private_data = (void *)chip_table->clocks[clock_slot];
@@ -1032,7 +1033,7 @@
 		if (clock_slot < 2 && ppi[0] == &info_hpt370a)
 			ppi[0] = &info_hpt370a_33;
 
-		pr_info(DRV_NAME ": %s using %dMHz bus clock.\n",
+		pr_info("%s using %dMHz bus clock\n",
 			chip_table->name, MHz[clock_slot]);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_hpt3x2n.c linux-libre-2.6.39-gnu/drivers/ata/pata_hpt3x2n.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_hpt3x2n.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_hpt3x2n.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,8 @@
  *	Work out best PLL policy
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/pci.h>
@@ -25,7 +27,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME	"pata_hpt3x2n"
-#define DRV_VERSION	"0.3.14"
+#define DRV_VERSION	"0.3.15"
 
 enum {
 	HPT_PCI_FAST	=	(1 << 31),
@@ -418,7 +420,7 @@
 		u16 sr;
 		u32 total = 0;
 
-		pr_warning(DRV_NAME ": BIOS clock data not set.\n");
+		pr_warn("BIOS clock data not set\n");
 
 		/* This is the process the HPT371 BIOS is reported to use */
 		for (i = 0; i < 128; i++) {
@@ -528,8 +530,7 @@
 		ppi[0] = &info_hpt372n;
 		break;
 	default:
-		pr_err(DRV_NAME ": PCI table is bogus, please report (%d).\n",
-		       dev->device);
+		pr_err("PCI table is bogus, please report (%d)\n", dev->device);
 		return -ENODEV;
 	}
 
@@ -578,11 +579,11 @@
 		pci_write_config_dword(dev, 0x5C, (f_high << 16) | f_low);
 	}
 	if (adjust == 8) {
-		pr_err(DRV_NAME ": DPLL did not stabilize!\n");
+		pr_err("DPLL did not stabilize!\n");
 		return -ENODEV;
 	}
 
-	pr_info(DRV_NAME ": bus clock %dMHz, using 66MHz DPLL.\n", pci_mhz);
+	pr_info("bus clock %dMHz, using 66MHz DPLL\n", pci_mhz);
 
 	/*
 	 * Set our private data up. We only need a few flags
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_hpt3x3.c linux-libre-2.6.39-gnu/drivers/ata/pata_hpt3x3.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_hpt3x3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_hpt3x3.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,7 +151,7 @@
 	.check_atapi_dma= hpt3x3_atapi_dma,
 	.freeze		= hpt3x3_freeze,
 #endif
-	
+
 };
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_it821x.c linux-libre-2.6.39-gnu/drivers/ata/pata_it821x.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_it821x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_it821x.c	2011-05-19 00:06:34.000000000 -0400
@@ -616,7 +616,7 @@
 	if (buf[52] > 4)	/* No Disk */
 		return;
 
-	ata_id_c_string((u16 *)buf, id, 0, 41); 
+	ata_id_c_string((u16 *)buf, id, 0, 41);
 
 	if (buf[51]) {
 		mode = ffs(buf[51]);
@@ -910,7 +910,7 @@
 	rc = pcim_enable_device(pdev);
 	if (rc)
 		return rc;
-		
+
 	if (pdev->vendor == PCI_VENDOR_ID_RDC) {
 		/* Deal with Vortex86SX */
 		if (pdev->revision == 0x11)
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_ixp4xx_cf.c linux-libre-2.6.39-gnu/drivers/ata/pata_ixp4xx_cf.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_ixp4xx_cf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_ixp4xx_cf.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 
 	irq = platform_get_irq(pdev, 0);
 	if (irq)
-		set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
+		irq_set_irq_type(irq, IRQ_TYPE_EDGE_RISING);
 
 	/* Setup expansion bus chip selects */
 	*data->cs0_cfg = data->cs0_bits;
@@ -177,7 +177,7 @@
 
 	ap->ops	= &ixp4xx_port_ops;
 	ap->pio_mask = ATA_PIO4;
-	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY | ATA_FLAG_NO_ATAPI;
+	ap->flags |= ATA_FLAG_NO_ATAPI;
 
 	ixp4xx_setup_port(ap, data, cs0->start, cs1->start);
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_macio.c linux-libre-2.6.39-gnu/drivers/ata/pata_macio.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_macio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_macio.c	2011-05-19 00:06:34.000000000 -0400
@@ -1053,8 +1053,7 @@
 	/* Allocate libata host for 1 port */
 	memset(&pinfo, 0, sizeof(struct ata_port_info));
 	pmac_macio_calc_timing_masks(priv, &pinfo);
-	pinfo.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO |
-				  ATA_FLAG_NO_LEGACY;
+	pinfo.flags		= ATA_FLAG_SLAVE_POSS;
 	pinfo.port_ops		= &pata_macio_ops;
 	pinfo.private_data	= priv;
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_marvell.c linux-libre-2.6.39-gnu/drivers/ata/pata_marvell.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_marvell.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_marvell.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 
 	/* We don't yet know how to do this for other devices */
 	if (pdev->device != 0x6145)
-		return 1;	
+		return 1;
 
 	barp = pci_iomap(pdev, 5, 0x10);
 	if (barp == NULL)
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_mpc52xx.c linux-libre-2.6.39-gnu/drivers/ata/pata_mpc52xx.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_mpc52xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_mpc52xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -680,7 +680,7 @@
 /* ======================================================================== */
 
 static int __devinit
-mpc52xx_ata_probe(struct platform_device *op, const struct of_device_id *match)
+mpc52xx_ata_probe(struct platform_device *op)
 {
 	unsigned int ipb_freq;
 	struct resource res_mem;
@@ -883,7 +883,7 @@
 };
 
 
-static struct of_platform_driver mpc52xx_ata_of_platform_driver = {
+static struct platform_driver mpc52xx_ata_of_platform_driver = {
 	.probe		= mpc52xx_ata_probe,
 	.remove		= mpc52xx_ata_remove,
 #ifdef CONFIG_PM
@@ -906,13 +906,13 @@
 mpc52xx_ata_init(void)
 {
 	printk(KERN_INFO "ata: MPC52xx IDE/ATA libata driver\n");
-	return of_register_platform_driver(&mpc52xx_ata_of_platform_driver);
+	return platform_driver_register(&mpc52xx_ata_of_platform_driver);
 }
 
 static void __exit
 mpc52xx_ata_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_ata_of_platform_driver);
+	platform_driver_unregister(&mpc52xx_ata_of_platform_driver);
 }
 
 module_init(mpc52xx_ata_init);
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_mpiix.c linux-libre-2.6.39-gnu/drivers/ata/pata_mpiix.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_mpiix.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_mpiix.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
  * with PCI IDE and also that we do not disable the device when our driver is
  * unloaded (as it has many other functions).
  *
- * The driver conciously keeps this logic internally to avoid pushing quirky
+ * The driver consciously keeps this logic internally to avoid pushing quirky
  * PATA history into the clean libata layer.
  *
  * Thinkpad specific note: If you boot an MPIIX using a thinkpad with a PCMCIA
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_ninja32.c linux-libre-2.6.39-gnu/drivers/ata/pata_ninja32.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_ninja32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_ninja32.c	2011-05-19 00:06:34.000000000 -0400
@@ -165,7 +165,7 @@
 		return rc;
 	ninja32_program(host->iomap[0]);
 	ata_host_resume(host);
-	return 0;			
+	return 0;
 }
 #endif
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_octeon_cf.c linux-libre-2.6.39-gnu/drivers/ata/pata_octeon_cf.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_octeon_cf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_octeon_cf.c	2011-05-19 00:06:34.000000000 -0400
@@ -848,8 +848,7 @@
 	cf_port->ap = ap;
 	ap->ops = &octeon_cf_ops;
 	ap->pio_mask = ATA_PIO6;
-	ap->flags |= ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY
-		  | ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
+	ap->flags |= ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING;
 
 	base = cs0 + ocd->base_region_bias;
 	if (!ocd->is16bit) {
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_of_platform.c linux-libre-2.6.39-gnu/drivers/ata/pata_of_platform.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_of_platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_of_platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,8 +14,7 @@
 #include <linux/of_platform.h>
 #include <linux/ata_platform.h>
 
-static int __devinit pata_of_platform_probe(struct platform_device *ofdev,
-					    const struct of_device_id *match)
+static int __devinit pata_of_platform_probe(struct platform_device *ofdev)
 {
 	int ret;
 	struct device_node *dn = ofdev->dev.of_node;
@@ -90,7 +89,7 @@
 };
 MODULE_DEVICE_TABLE(of, pata_of_platform_match);
 
-static struct of_platform_driver pata_of_platform_driver = {
+static struct platform_driver pata_of_platform_driver = {
 	.driver = {
 		.name = "pata_of_platform",
 		.owner = THIS_MODULE,
@@ -102,13 +101,13 @@
 
 static int __init pata_of_platform_init(void)
 {
-	return of_register_platform_driver(&pata_of_platform_driver);
+	return platform_driver_register(&pata_of_platform_driver);
 }
 module_init(pata_of_platform_init);
 
 static void __exit pata_of_platform_exit(void)
 {
-	of_unregister_platform_driver(&pata_of_platform_driver);
+	platform_driver_unregister(&pata_of_platform_driver);
 }
 module_exit(pata_of_platform_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_palmld.c linux-libre-2.6.39-gnu/drivers/ata/pata_palmld.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_palmld.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_palmld.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,11 @@
 
 #define DRV_NAME "pata_palmld"
 
+static struct gpio palmld_hdd_gpios[] = {
+	{ GPIO_NR_PALMLD_IDE_PWEN,	GPIOF_INIT_HIGH,	"HDD Power" },
+	{ GPIO_NR_PALMLD_IDE_RESET,	GPIOF_INIT_LOW,		"HDD Reset" },
+};
+
 static struct scsi_host_template palmld_sht = {
 	ATA_PIO_SHT(DRV_NAME),
 };
@@ -52,28 +57,23 @@
 
 	/* allocate host */
 	host = ata_host_alloc(&pdev->dev, 1);
-	if (!host)
-		return -ENOMEM;
+	if (!host) {
+		ret = -ENOMEM;
+		goto err1;
+	}
 
 	/* remap drive's physical memory address */
 	mem = devm_ioremap(&pdev->dev, PALMLD_IDE_PHYS, 0x1000);
-	if (!mem)
-		return -ENOMEM;
+	if (!mem) {
+		ret = -ENOMEM;
+		goto err1;
+	}
 
 	/* request and activate power GPIO, IRQ GPIO */
-	ret = gpio_request(GPIO_NR_PALMLD_IDE_PWEN, "HDD PWR");
+	ret = gpio_request_array(palmld_hdd_gpios,
+				ARRAY_SIZE(palmld_hdd_gpios));
 	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);
@@ -85,7 +85,7 @@
 	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;
+	ap->flags |= ATA_FLAG_PIO_POLLING;
 
 	/* memory mapping voodoo */
 	ap->ioaddr.cmd_addr = mem + 0x10;
@@ -96,13 +96,15 @@
 	ata_sff_std_ports(&ap->ioaddr);
 
 	/* activate host */
-	return ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,
+	ret = ata_host_activate(host, 0, NULL, IRQF_TRIGGER_RISING,
 					&palmld_sht);
+	if (ret)
+		goto err2;
+
+	return ret;
 
-err3:
-	gpio_free(GPIO_NR_PALMLD_IDE_RESET);
 err2:
-	gpio_free(GPIO_NR_PALMLD_IDE_PWEN);
+	gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios));
 err1:
 	return ret;
 }
@@ -116,8 +118,7 @@
 	/* 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);
+	gpio_free_array(palmld_hdd_gpios, ARRAY_SIZE(palmld_hdd_gpios));
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_pcmcia.c linux-libre-2.6.39-gnu/drivers/ata/pata_pcmcia.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_pcmcia.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_pcmcia.c	2011-05-19 00:06:34.000000000 -0400
@@ -124,7 +124,7 @@
  *	reset will recover the device.
  *
  */
- 
+
 static void pcmcia_8bit_drain_fifo(struct ata_queued_cmd *qc)
 {
 	int count;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_pdc2027x.c linux-libre-2.6.39-gnu/drivers/ata/pata_pdc2027x.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_pdc2027x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_pdc2027x.c	2011-05-19 00:06:34.000000000 -0400
@@ -150,8 +150,7 @@
 static struct ata_port_info pdc2027x_port_info[] = {
 	/* PDC_UDMA_100 */
 	{
-		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
-		                  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA5,
@@ -159,8 +158,7 @@
 	},
 	/* PDC_UDMA_133 */
 	{
-		.flags		= ATA_FLAG_NO_LEGACY | ATA_FLAG_SLAVE_POSS |
-                        	  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_pxa.c linux-libre-2.6.39-gnu/drivers/ata/pata_pxa.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_pxa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_pxa.c	2011-05-19 00:06:34.000000000 -0400
@@ -292,7 +292,6 @@
 	ap->ops		= &pxa_ata_port_ops;
 	ap->pio_mask	= ATA_PIO4;
 	ap->mwdma_mask	= ATA_MWDMA2;
-	ap->flags	= ATA_FLAG_MMIO;
 
 	ap->ioaddr.cmd_addr	= devm_ioremap(&pdev->dev, cmd_res->start,
 						resource_size(cmd_res));
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_rb532_cf.c linux-libre-2.6.39-gnu/drivers/ata/pata_rb532_cf.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_rb532_cf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_rb532_cf.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,10 +60,10 @@
 	struct rb532_cf_info *info = ah->private_data;
 
 	if (gpio_get_value(info->gpio_line)) {
-		set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
+		irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_LOW);
 		ata_sff_interrupt(info->irq, dev_instance);
 	} else {
-		set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
+		irq_set_irq_type(info->irq, IRQ_TYPE_LEVEL_HIGH);
 	}
 
 	return IRQ_HANDLED;
@@ -91,7 +91,6 @@
 
 	ap->ops		= &rb532_pata_port_ops;
 	ap->pio_mask	= ATA_PIO4;
-	ap->flags	= ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO;
 
 	ap->ioaddr.cmd_addr	= info->iobase + RB500_CF_REG_BASE;
 	ap->ioaddr.ctl_addr	= info->iobase + RB500_CF_REG_CTRL;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_rz1000.c linux-libre-2.6.39-gnu/drivers/ata/pata_rz1000.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_rz1000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_rz1000.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,7 +112,7 @@
 	if (rc)
 		return rc;
 
-	/* If this fails on resume (which is a "cant happen" case), we
+	/* If this fails on resume (which is a "can't happen" case), we
 	   must stop as any progress risks data loss */
 	if (rz1000_fifo_disable(pdev))
 		panic("rz1000 fifo");
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_samsung_cf.c linux-libre-2.6.39-gnu/drivers/ata/pata_samsung_cf.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_samsung_cf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_samsung_cf.c	2011-05-19 00:06:34.000000000 -0400
@@ -531,7 +531,6 @@
 	}
 
 	ap = host->ports[0];
-	ap->flags |= ATA_FLAG_MMIO;
 	ap->pio_mask = ATA_PIO4;
 
 	if (cpu_type == TYPE_S3C64XX) {
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_scc.c linux-libre-2.6.39-gnu/drivers/ata/pata_scc.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_scc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_scc.c	2011-05-19 00:06:34.000000000 -0400
@@ -959,7 +959,7 @@
 
 static struct ata_port_info scc_port_info[] = {
 	{
-		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_MMIO | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SLAVE_POSS,
 		.pio_mask	= ATA_PIO4,
 		/* No MWDMA */
 		.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_sil680.c linux-libre-2.6.39-gnu/drivers/ata/pata_sil680.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_sil680.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_sil680.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
  *
  *  May be copied or modified under the terms of the GNU General Public License
  *
- *  Documentation publically available.
+ *  Documentation publicly available.
  *
  *	If you have strange problems with nVidia chipset systems please
  *	see the SI support documentation and update your system BIOS
@@ -43,7 +43,7 @@
  *
  *	Turn a config register offset into the right address in either
  *	PCI space or MMIO space to access the control register in question
- *	Thankfully this is a configuration operation so isnt performance
+ *	Thankfully this is a configuration operation so isn't performance
  *	criticial.
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_sis.c linux-libre-2.6.39-gnu/drivers/ata/pata_sis.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_sis.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_sis.c	2011-05-19 00:06:34.000000000 -0400
@@ -331,7 +331,7 @@
 
 	if (adev->dma_mode < XFER_UDMA_0) {
 		/* bits 3-0 hold recovery timing bits 8-10 active timing and
-		   the higher bits are dependant on the device */
+		   the higher bits are dependent on the device */
 		timing &= ~0x870F;
 		timing |= mwdma_bits[speed];
 	} else {
@@ -371,7 +371,7 @@
 
 	if (adev->dma_mode < XFER_UDMA_0) {
 		/* bits 3-0 hold recovery timing bits 8-10 active timing and
-		   the higher bits are dependant on the device, bit 15 udma */
+		   the higher bits are dependent on the device, bit 15 udma */
 		timing &= ~0x870F;
 		timing |= mwdma_bits[speed];
 	} else {
@@ -593,7 +593,7 @@
 	.port_ops	= &sis_133_ops,
 };
 const struct ata_port_info sis_info133_for_sata = {
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_SRST,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
 	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pata_triflex.c linux-libre-2.6.39-gnu/drivers/ata/pata_triflex.c
--- linux-libre-2.6.38-gnu/drivers/ata/pata_triflex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pata_triflex.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
  * Loosely based on the piix & svwks drivers.
  *
  * Documentation:
- *	Not publically available.
+ *	Not publicly available.
  */
 
 #include <linux/kernel.h>
diff -druN linux-libre-2.6.38-gnu/drivers/ata/pdc_adma.c linux-libre-2.6.39-gnu/drivers/ata/pdc_adma.c
--- linux-libre-2.6.38-gnu/drivers/ata/pdc_adma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/pdc_adma.c	2011-05-19 00:06:34.000000000 -0400
@@ -166,9 +166,7 @@
 static struct ata_port_info adma_port_info[] = {
 	/* board_1841_idx */
 	{
-		.flags		= ATA_FLAG_SLAVE_POSS |
-				  ATA_FLAG_NO_LEGACY | ATA_FLAG_MMIO |
-				  ATA_FLAG_PIO_POLLING,
+		.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= ATA_PIO4_ONLY,
 		.udma_mask	= ATA_UDMA4,
 		.port_ops	= &adma_ata_ops,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_dwc_460ex.c linux-libre-2.6.39-gnu/drivers/ata/sata_dwc_460ex.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_dwc_460ex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_dwc_460ex.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,8 +40,11 @@
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_cmnd.h>
 
+/* These two are defined in "libata.h" */
+#undef	DRV_NAME
+#undef	DRV_VERSION
 #define DRV_NAME        "sata-dwc"
-#define DRV_VERSION     "1.0"
+#define DRV_VERSION     "1.3"
 
 /* SATA DMA driver Globals */
 #define DMA_NUM_CHANS		1
@@ -333,11 +336,47 @@
 			      void __iomem *addr, int dir);
 static void dma_dwc_xfer_start(int dma_ch);
 
+static const char *get_prot_descript(u8 protocol)
+{
+	switch ((enum ata_tf_protocols)protocol) {
+	case ATA_PROT_NODATA:
+		return "ATA no data";
+	case ATA_PROT_PIO:
+		return "ATA PIO";
+	case ATA_PROT_DMA:
+		return "ATA DMA";
+	case ATA_PROT_NCQ:
+		return "ATA NCQ";
+	case ATAPI_PROT_NODATA:
+		return "ATAPI no data";
+	case ATAPI_PROT_PIO:
+		return "ATAPI PIO";
+	case ATAPI_PROT_DMA:
+		return "ATAPI DMA";
+	default:
+		return "unknown";
+	}
+}
+
+static const char *get_dma_dir_descript(int dma_dir)
+{
+	switch ((enum dma_data_direction)dma_dir) {
+	case DMA_BIDIRECTIONAL:
+		return "bidirectional";
+	case DMA_TO_DEVICE:
+		return "to device";
+	case DMA_FROM_DEVICE:
+		return "from device";
+	default:
+		return "none";
+	}
+}
+
 static void sata_dwc_tf_dump(struct ata_taskfile *tf)
 {
 	dev_vdbg(host_pvt.dwc_dev, "taskfile cmd: 0x%02x protocol: %s flags:"
-		"0x%lx device: %x\n", tf->command, ata_get_cmd_descript\
-		(tf->protocol), tf->flags, tf->device);
+		"0x%lx device: %x\n", tf->command,
+		get_prot_descript(tf->protocol), tf->flags, tf->device);
 	dev_vdbg(host_pvt.dwc_dev, "feature: 0x%02x nsect: 0x%x lbal: 0x%x "
 		"lbam: 0x%x lbah: 0x%x\n", tf->feature, tf->nsect, tf->lbal,
 		 tf->lbam, tf->lbah);
@@ -715,7 +754,7 @@
 	/* Program the CTL register with src enable / dst enable */
 	out_le32(&(host_pvt.sata_dma_regs->chan_regs[dma_ch].ctl.low),
 		 DMA_CTL_LLP_SRCEN | DMA_CTL_LLP_DSTEN);
-	return 0;
+	return dma_ch;
 }
 
 /*
@@ -967,7 +1006,7 @@
 		}
 
 		dev_dbg(ap->dev, "%s non-NCQ cmd interrupt, protocol: %s\n",
-			__func__, ata_get_cmd_descript(qc->tf.protocol));
+			__func__, get_prot_descript(qc->tf.protocol));
 DRVSTILLBUSY:
 		if (ata_is_dma(qc->tf.protocol)) {
 			/*
@@ -1057,7 +1096,7 @@
 
 		/* Process completed command */
 		dev_dbg(ap->dev, "%s NCQ command, protocol: %s\n", __func__,
-			ata_get_cmd_descript(qc->tf.protocol));
+			get_prot_descript(qc->tf.protocol));
 		if (ata_is_dma(qc->tf.protocol)) {
 			host_pvt.dma_interrupt_count++;
 			if (hsdevp->dma_pending[tag] == \
@@ -1142,8 +1181,8 @@
 	if (tag > 0) {
 		dev_info(ap->dev, "%s tag=%u cmd=0x%02x dma dir=%s proto=%s "
 			 "dmacr=0x%08x\n", __func__, qc->tag, qc->tf.command,
-			 ata_get_cmd_descript(qc->dma_dir),
-			 ata_get_cmd_descript(qc->tf.protocol),
+			 get_dma_dir_descript(qc->dma_dir),
+			 get_prot_descript(qc->tf.protocol),
 			 in_le32(&(hsdev->sata_dwc_regs->dmacr)));
 	}
 #endif
@@ -1354,7 +1393,7 @@
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
 
 	dev_dbg(ap->dev, "%s cmd(0x%02x): %s tag=%d\n", __func__, tf->command,
-		ata_get_cmd_descript(tf), tag);
+		ata_get_cmd_descript(tf->command), tag);
 
 	spin_lock_irqsave(&ap->host->lock, flags);
 	hsdevp->cmd_issued[tag] = cmd_issued;
@@ -1413,7 +1452,7 @@
 
 	dev_dbg(ap->dev, "%s qc=%p tag: %x cmd: 0x%02x dma_dir: %s "
 		"start_dma? %x\n", __func__, qc, tag, qc->tf.command,
-		ata_get_cmd_descript(qc->dma_dir), start_dma);
+		get_dma_dir_descript(qc->dma_dir), start_dma);
 	sata_dwc_tf_dump(&(qc->tf));
 
 	if (start_dma) {
@@ -1462,10 +1501,9 @@
 	int dma_chan;
 	struct sata_dwc_device *hsdev = HSDEV_FROM_AP(ap);
 	struct sata_dwc_device_port *hsdevp = HSDEVP_FROM_AP(ap);
-	int err;
 
 	dev_dbg(ap->dev, "%s: port=%d dma dir=%s n_elem=%d\n",
-		__func__, ap->port_no, ata_get_cmd_descript(qc->dma_dir),
+		__func__, ap->port_no, get_dma_dir_descript(qc->dma_dir),
 		 qc->n_elem);
 
 	dma_chan = dma_dwc_xfer_setup(sg, qc->n_elem, hsdevp->llit[tag],
@@ -1474,7 +1512,7 @@
 				      dmadr), qc->dma_dir);
 	if (dma_chan < 0) {
 		dev_err(ap->dev, "%s: dma_dwc_xfer_setup returns err %d\n",
-			__func__, err);
+			__func__, dma_chan);
 		return;
 	}
 	hsdevp->dma_chan[tag] = dma_chan;
@@ -1491,8 +1529,8 @@
 		dev_info(ap->dev, "%s ap id=%d cmd(0x%02x)=%s qc tag=%d "
 			 "prot=%s ap active_tag=0x%08x ap sactive=0x%08x\n",
 			 __func__, ap->print_id, qc->tf.command,
-			 ata_get_cmd_descript(&qc->tf),
-			 qc->tag, ata_get_cmd_descript(qc->tf.protocol),
+			 ata_get_cmd_descript(qc->tf.command),
+			 qc->tag, get_prot_descript(qc->tf.protocol),
 			 ap->link.active_tag, ap->link.sactive);
 #endif
 
@@ -1533,7 +1571,7 @@
 #ifdef DEBUG_NCQ
 	if (qc->tag > 0)
 		dev_info(qc->ap->dev, "%s: qc->tag=%d ap->active_tag=0x%08x\n",
-			 __func__, tag, qc->ap->link.active_tag);
+			 __func__, qc->tag, qc->ap->link.active_tag);
 
 	return ;
 #endif
@@ -1580,16 +1618,14 @@
 
 static const struct ata_port_info sata_dwc_port_info[] = {
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
-		.pio_mask	= 0x1f,	/* pio 0-4 */
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NCQ,
+		.pio_mask	= ATA_PIO4,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &sata_dwc_ops,
 	},
 };
 
-static int sata_dwc_probe(struct platform_device *ofdev,
-			const struct of_device_id *match)
+static int sata_dwc_probe(struct platform_device *ofdev)
 {
 	struct sata_dwc_device *hsdev;
 	u32 idr, versionr;
@@ -1727,7 +1763,7 @@
 };
 MODULE_DEVICE_TABLE(of, sata_dwc_match);
 
-static struct of_platform_driver sata_dwc_driver = {
+static struct platform_driver sata_dwc_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -1739,12 +1775,12 @@
 
 static int __init sata_dwc_init(void)
 {
-	return	of_register_platform_driver(&sata_dwc_driver);
+	return platform_driver_register(&sata_dwc_driver);
 }
 
 static void __exit sata_dwc_exit(void)
 {
-	of_unregister_platform_driver(&sata_dwc_driver);
+	platform_driver_unregister(&sata_dwc_driver);
 }
 
 module_init(sata_dwc_init);
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_fsl.c linux-libre-2.6.39-gnu/drivers/ata/sata_fsl.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_fsl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_fsl.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  * Author: Ashish Kalra <ashish.kalra@freescale.com>
  * Li Yang <leoli@freescale.com>
  *
- * Copyright (c) 2006-2007 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006-2007, 2011 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
@@ -33,8 +33,7 @@
 	SATA_FSL_MAX_PRD_USABLE	= SATA_FSL_MAX_PRD - 1,
 	SATA_FSL_MAX_PRD_DIRECT	= 16,	/* Direct PRDT entries */
 
-	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+	SATA_FSL_HOST_FLAGS	= (ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
 				ATA_FLAG_PMP | ATA_FLAG_NCQ | ATA_FLAG_AN),
 
 	SATA_FSL_MAX_CMDS	= SATA_FSL_QUEUE_DEPTH,
@@ -43,7 +42,7 @@
 
 	/*
 	 * SATA-FSL host controller supports a max. of (15+1) direct PRDEs, and
-	 * chained indirect PRDEs upto a max count of 63.
+	 * chained indirect PRDEs up to a max count of 63.
 	 * We are allocating an array of 63 PRDEs contiguously, but PRDE#15 will
 	 * be setup as an indirect descriptor, pointing to it's next
 	 * (contiguous) PRDE. Though chained indirect PRDE arrays are
@@ -158,7 +157,8 @@
 	    IE_ON_SINGL_DEVICE_ERR | IE_ON_CMD_COMPLETE,
 
 	EXT_INDIRECT_SEG_PRD_FLAG = (1 << 31),
-	DATA_SNOOP_ENABLE = (1 << 22),
+	DATA_SNOOP_ENABLE_V1 = (1 << 22),
+	DATA_SNOOP_ENABLE_V2 = (1 << 28),
 };
 
 /*
@@ -186,6 +186,11 @@
 	COMMANDSTAT = 0x20,
 };
 
+/* TRANSCFG (transport-layer) configuration control */
+enum {
+	TRANSCFG_RX_WATER_MARK = (1 << 4),
+};
+
 /* PHY (link-layer) configuration control */
 enum {
 	PHY_BIST_ENABLE = 0x01,
@@ -256,6 +261,7 @@
 	void __iomem *ssr_base;
 	void __iomem *csr_base;
 	int irq;
+	int data_snoop;
 };
 
 static inline unsigned int sata_fsl_tag(unsigned int tag,
@@ -308,7 +314,8 @@
 }
 
 static unsigned int sata_fsl_fill_sg(struct ata_queued_cmd *qc, void *cmd_desc,
-				     u32 *ttl, dma_addr_t cmd_desc_paddr)
+				     u32 *ttl, dma_addr_t cmd_desc_paddr,
+				     int data_snoop)
 {
 	struct scatterlist *sg;
 	unsigned int num_prde = 0;
@@ -358,8 +365,7 @@
 
 		ttl_dwords += sg_len;
 		prd->dba = cpu_to_le32(sg_addr);
-		prd->ddc_and_ext =
-		    cpu_to_le32(DATA_SNOOP_ENABLE | (sg_len & ~0x03));
+		prd->ddc_and_ext = cpu_to_le32(data_snoop | (sg_len & ~0x03));
 
 		VPRINTK("sg_fill, ttl=%d, dba=0x%x, ddc=0x%x\n",
 			ttl_dwords, prd->dba, prd->ddc_and_ext);
@@ -374,7 +380,7 @@
 		/* set indirect extension flag along with indirect ext. size */
 		prd_ptr_to_indirect_ext->ddc_and_ext =
 		    cpu_to_le32((EXT_INDIRECT_SEG_PRD_FLAG |
-				 DATA_SNOOP_ENABLE |
+				 data_snoop |
 				 (indirect_ext_segment_sz & ~0x03)));
 	}
 
@@ -417,7 +423,8 @@
 
 	if (qc->flags & ATA_QCFLAG_DMAMAP)
 		num_prde = sata_fsl_fill_sg(qc, (void *)cd,
-					    &ttl_dwords, cd_paddr);
+					    &ttl_dwords, cd_paddr,
+					    host_priv->data_snoop);
 
 	if (qc->tf.protocol == ATA_PROT_NCQ)
 		desc_info |= FPDMA_QUEUED_CMD;
@@ -900,7 +907,7 @@
 	ata_msleep(ap, 1);
 
 	/*
-	 * SATA device enters reset state after receving a Control register
+	 * SATA device enters reset state after receiving a Control register
 	 * FIS with SRST bit asserted and it awaits another H2D Control reg.
 	 * FIS with SRST bit cleared, then the device does internal diags &
 	 * initialization, followed by indicating it's initialization status
@@ -1040,12 +1047,15 @@
 
 		/* find out the offending link and qc */
 		if (ap->nr_pmp_links) {
+			unsigned int dev_num;
+
 			dereg = ioread32(hcr_base + DE);
 			iowrite32(dereg, hcr_base + DE);
 			iowrite32(cereg, hcr_base + CE);
 
-			if (dereg < ap->nr_pmp_links) {
-				link = &ap->pmp_link[dereg];
+			dev_num = ffs(dereg) - 1;
+			if (dev_num < ap->nr_pmp_links && dereg != 0) {
+				link = &ap->pmp_link[dev_num];
 				ehi = &link->eh_info;
 				qc = ata_qc_from_tag(ap, link->active_tag);
 				/*
@@ -1293,8 +1303,7 @@
 	 },
 };
 
-static int sata_fsl_probe(struct platform_device *ofdev,
-			const struct of_device_id *match)
+static int sata_fsl_probe(struct platform_device *ofdev)
 {
 	int retval = -ENXIO;
 	void __iomem *hcr_base = NULL;
@@ -1303,6 +1312,7 @@
 	struct sata_fsl_host_priv *host_priv = NULL;
 	int irq;
 	struct ata_host *host;
+	u32 temp;
 
 	struct ata_port_info pi = sata_fsl_port_info[0];
 	const struct ata_port_info *ppi[] = { &pi, NULL };
@@ -1317,6 +1327,12 @@
 	ssr_base = hcr_base + 0x100;
 	csr_base = hcr_base + 0x140;
 
+	if (!of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc8315-sata")) {
+		temp = ioread32(csr_base + TRANSCFG);
+		temp = temp & 0xffffffe0;
+		iowrite32(temp | TRANSCFG_RX_WATER_MARK, csr_base + TRANSCFG);
+	}
+
 	DPRINTK("@reset i/o = 0x%x\n", ioread32(csr_base + TRANSCFG));
 	DPRINTK("sizeof(cmd_desc) = %d\n", sizeof(struct command_desc));
 	DPRINTK("sizeof(#define cmd_desc) = %d\n", SATA_FSL_CMD_DESC_SIZE);
@@ -1336,6 +1352,11 @@
 	}
 	host_priv->irq = irq;
 
+	if (of_device_is_compatible(ofdev->dev.of_node, "fsl,pq-sata-v2"))
+		host_priv->data_snoop = DATA_SNOOP_ENABLE_V2;
+	else
+		host_priv->data_snoop = DATA_SNOOP_ENABLE_V1;
+
 	/* allocate host structure */
 	host = ata_host_alloc_pinfo(&ofdev->dev, ppi, SATA_FSL_MAX_PORTS);
 
@@ -1418,12 +1439,15 @@
 	{
 		.compatible = "fsl,pq-sata",
 	},
+	{
+		.compatible = "fsl,pq-sata-v2",
+	},
 	{},
 };
 
 MODULE_DEVICE_TABLE(of, fsl_sata_match);
 
-static struct of_platform_driver fsl_sata_driver = {
+static struct platform_driver fsl_sata_driver = {
 	.driver = {
 		.name = "fsl-sata",
 		.owner = THIS_MODULE,
@@ -1439,13 +1463,13 @@
 
 static int __init sata_fsl_init(void)
 {
-	of_register_platform_driver(&fsl_sata_driver);
+	platform_driver_register(&fsl_sata_driver);
 	return 0;
 }
 
 static void __exit sata_fsl_exit(void)
 {
-	of_unregister_platform_driver(&fsl_sata_driver);
+	platform_driver_unregister(&fsl_sata_driver);
 }
 
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_mv.c linux-libre-2.6.39-gnu/drivers/ata/sata_mv.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_mv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_mv.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,8 +160,7 @@
 	/* Host Flags */
 	MV_FLAG_DUAL_HC		= (1 << 30),  /* two SATA Host Controllers */
 
-	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
+	MV_COMMON_FLAGS		= ATA_FLAG_SATA | ATA_FLAG_PIO_POLLING,
 
 	MV_GEN_I_FLAGS		= MV_COMMON_FLAGS | ATA_FLAG_NO_ATAPI,
 
@@ -1353,7 +1352,7 @@
 			/*
 			 * Workaround for 88SX60x1 FEr SATA#26:
 			 *
-			 * COMRESETs have to take care not to accidently
+			 * COMRESETs have to take care not to accidentally
 			 * put the drive to sleep when writing SCR_CONTROL.
 			 * Setting bits 12..15 prevents this problem.
 			 *
@@ -2045,7 +2044,7 @@
 
 	cw = &pp->crqb[in_index].ata_cmd[0];
 
-	/* Sadly, the CRQB cannot accomodate all registers--there are
+	/* Sadly, the CRQB cannot accommodate all registers--there are
 	 * only 11 bytes...so we must pick and choose required
 	 * registers based on the command.  So, we drop feature and
 	 * hob_feature for [RW] DMA commands, but they are needed for
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_nv.c linux-libre-2.6.39-gnu/drivers/ata/sata_nv.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_nv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_nv.c	2011-05-19 00:06:34.000000000 -0400
@@ -539,7 +539,7 @@
 static const struct ata_port_info nv_port_info[] = {
 	/* generic */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -548,7 +548,7 @@
 	},
 	/* nforce2/3 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -557,7 +557,7 @@
 	},
 	/* ck804 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -566,8 +566,7 @@
 	},
 	/* ADMA */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_NCQ,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NCQ,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -576,7 +575,7 @@
 	},
 	/* MCP5x */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -585,8 +584,7 @@
 	},
 	/* SWNCQ */
 	{
-		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_NCQ,
+		.flags	        = ATA_FLAG_SATA | ATA_FLAG_NCQ,
 		.pio_mask	= NV_PIO_MASK,
 		.mwdma_mask	= NV_MWDMA_MASK,
 		.udma_mask	= NV_UDMA_MASK,
@@ -2123,7 +2121,7 @@
 
 	host_stat = ap->ops->bmdma_status(ap);
 	if (unlikely(host_stat & ATA_DMA_ERR)) {
-		/* error when transfering data to/from memory */
+		/* error when transferring data to/from memory */
 		ata_ehi_clear_desc(ehi);
 		ata_ehi_push_desc(ehi, "BMDMA stat 0x%x", host_stat);
 		ehi->err_mask |= AC_ERR_HOST_BUS;
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_promise.c linux-libre-2.6.39-gnu/drivers/ata/sata_promise.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_promise.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_promise.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,9 +134,7 @@
 	PDC_IRQ_DISABLE		= (1 << 10),
 	PDC_RESET		= (1 << 11), /* HDMA reset */
 
-	PDC_COMMON_FLAGS	= ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO |
-				  ATA_FLAG_PIO_POLLING,
+	PDC_COMMON_FLAGS	= ATA_FLAG_PIO_POLLING,
 
 	/* ap->flags bits */
 	PDC_FLAG_GEN_II		= (1 << 24),
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_qstor.c linux-libre-2.6.39-gnu/drivers/ata/sata_qstor.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_qstor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_qstor.c	2011-05-19 00:06:34.000000000 -0400
@@ -155,8 +155,7 @@
 static const struct ata_port_info qs_port_info[] = {
 	/* board_2068_idx */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_POLLING,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_POLLING,
 		.pio_mask	= ATA_PIO4_ONLY,
 		.udma_mask	= ATA_UDMA6,
 		.port_ops	= &qs_ata_ops,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_sil24.c linux-libre-2.6.39-gnu/drivers/ata/sata_sil24.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_sil24.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_sil24.c	2011-05-19 00:06:34.000000000 -0400
@@ -244,8 +244,7 @@
 	BID_SIL3131		= 2,
 
 	/* host flags */
-	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA |
+	SIL24_COMMON_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA |
 				  ATA_FLAG_NCQ | ATA_FLAG_ACPI_SATA |
 				  ATA_FLAG_AN | ATA_FLAG_PMP,
 	SIL24_FLAG_PCIX_IRQ_WOC	= (1 << 24), /* IRQ loss errata on PCI-X */
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_sil.c linux-libre-2.6.39-gnu/drivers/ata/sata_sil.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_sil.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_sil.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,8 +61,7 @@
 	SIL_FLAG_RERR_ON_DMA_ACT = (1 << 29),
 	SIL_FLAG_MOD15WRITE	= (1 << 30),
 
-	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+	SIL_DFL_PORT_FLAGS	= ATA_FLAG_SATA,
 
 	/*
 	 * Controller IDs
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_sis.c linux-libre-2.6.39-gnu/drivers/ata/sata_sis.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_sis.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_sis.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 };
 
 static const struct ata_port_info sis_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_svw.c linux-libre-2.6.39-gnu/drivers/ata/sata_svw.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_svw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_svw.c	2011-05-19 00:06:34.000000000 -0400
@@ -359,8 +359,7 @@
 static const struct ata_port_info k2_port_info[] = {
 	/* chip_svw4 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA,
+		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
@@ -368,8 +367,7 @@
 	},
 	/* chip_svw8 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | K2_FLAG_NO_ATAPI_DMA |
+		.flags		= ATA_FLAG_SATA | K2_FLAG_NO_ATAPI_DMA |
 				  K2_FLAG_SATA_8_PORTS,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
@@ -378,8 +376,7 @@
 	},
 	/* chip_svw42 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO | K2_FLAG_BAR_POS_3,
+		.flags		= ATA_FLAG_SATA | K2_FLAG_BAR_POS_3,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
@@ -387,8 +384,7 @@
 	},
 	/* chip_svw43 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_sx4.c linux-libre-2.6.39-gnu/drivers/ata/sata_sx4.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_sx4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_sx4.c	2011-05-19 00:06:34.000000000 -0400
@@ -273,9 +273,8 @@
 static const struct ata_port_info pdc_port_info[] = {
 	/* board_20621 */
 	{
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_SRST | ATA_FLAG_MMIO |
-				  ATA_FLAG_NO_ATAPI | ATA_FLAG_PIO_POLLING,
+		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_ATAPI |
+				  ATA_FLAG_PIO_POLLING,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_uli.c linux-libre-2.6.39-gnu/drivers/ata/sata_uli.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_uli.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_uli.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,8 +88,7 @@
 };
 
 static const struct ata_port_info uli_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-			  ATA_FLAG_IGN_SIMPLEX,
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_IGN_SIMPLEX,
 	.pio_mask       = ATA_PIO4,
 	.udma_mask      = ATA_UDMA6,
 	.port_ops       = &uli_ops,
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_via.c linux-libre-2.6.39-gnu/drivers/ata/sata_via.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_via.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_via.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,7 +148,7 @@
 };
 
 static const struct ata_port_info vt6420_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
@@ -156,7 +156,7 @@
 };
 
 static struct ata_port_info vt6421_sport_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
@@ -164,7 +164,7 @@
 };
 
 static struct ata_port_info vt6421_pport_info = {
-	.flags		= ATA_FLAG_SLAVE_POSS | ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
 	/* No MWDMA */
 	.udma_mask	= ATA_UDMA6,
@@ -172,8 +172,7 @@
 };
 
 static struct ata_port_info vt8251_port_info = {
-	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS |
-			  ATA_FLAG_NO_LEGACY,
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_SLAVE_POSS,
 	.pio_mask	= ATA_PIO4,
 	.mwdma_mask	= ATA_MWDMA2,
 	.udma_mask	= ATA_UDMA6,
@@ -583,7 +582,7 @@
 	 * When host issues HOLD, device may send up to 20DW of data
 	 * before acknowledging it with HOLDA and the host should be
 	 * able to buffer them in FIFO.  Unfortunately, some WD drives
-	 * send upto 40DW before acknowledging HOLD and, in the
+	 * send up to 40DW before acknowledging HOLD and, in the
 	 * default configuration, this ends up overflowing vt6421's
 	 * FIFO, making the controller abort the transaction with
 	 * R_ERR.
diff -druN linux-libre-2.6.38-gnu/drivers/ata/sata_vsc.c linux-libre-2.6.39-gnu/drivers/ata/sata_vsc.c
--- linux-libre-2.6.38-gnu/drivers/ata/sata_vsc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ata/sata_vsc.c	2011-05-19 00:06:34.000000000 -0400
@@ -340,8 +340,7 @@
 				       const struct pci_device_id *ent)
 {
 	static const struct ata_port_info pi = {
-		.flags		= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY |
-				  ATA_FLAG_MMIO,
+		.flags		= ATA_FLAG_SATA,
 		.pio_mask	= ATA_PIO4,
 		.mwdma_mask	= ATA_MWDMA2,
 		.udma_mask	= ATA_UDMA6,
diff -druN linux-libre-2.6.38-gnu/drivers/atm/ambassador.c linux-libre-2.6.39-gnu/drivers/atm/ambassador.c
--- linux-libre-2.6.38-gnu/drivers/atm/ambassador.c	2012-03-24 00:59:35.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/ambassador.c	2012-03-24 03:25:44.000000000 -0400
@@ -497,7 +497,7 @@
 	  // VC layer stats
 	  atomic_inc(&atm_vcc->stats->rx);
 	  __net_timestamp(skb);
-	  // end of our responsability
+	  // end of our responsibility
 	  atm_vcc->push (atm_vcc, skb);
 	  return;
 	  
diff -druN linux-libre-2.6.38-gnu/drivers/atm/firestream.c linux-libre-2.6.39-gnu/drivers/atm/firestream.c
--- linux-libre-2.6.38-gnu/drivers/atm/firestream.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/firestream.c	2011-05-19 00:06:34.000000000 -0400
@@ -1031,7 +1031,7 @@
 		/* We now use the "submit_command" function to submit commands to
 		   the firestream. There is a define up near the definition of
 		   that routine that switches this routine between immediate write
-		   to the immediate comamnd registers and queuing the commands in
+		   to the immediate command registers and queuing the commands in
 		   the HPTXQ for execution. This last technique might be more
 		   efficient if we know we're going to submit a whole lot of
 		   commands in one go, but this driver is not setup to be able to
@@ -1782,7 +1782,7 @@
 		write_fs (dev, RAS0, RAS0_DCD_XHLT 
 			  | (((1 << FS155_VPI_BITS) - 1) * RAS0_VPSEL)
 			  | (((1 << FS155_VCI_BITS) - 1) * RAS0_VCSEL));
-		/* We can chose the split arbitarily. We might be able to 
+		/* We can chose the split arbitrarily. We might be able to 
 		   support more. Whatever. This should do for now. */
 		dev->atm_dev->ci_range.vpi_bits = FS155_VPI_BITS;
 		dev->atm_dev->ci_range.vci_bits = FS155_VCI_BITS;
diff -druN linux-libre-2.6.38-gnu/drivers/atm/fore200e.c linux-libre-2.6.39-gnu/drivers/atm/fore200e.c
--- linux-libre-2.6.38-gnu/drivers/atm/fore200e.c	2012-03-24 00:59:43.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/fore200e.c	2012-03-24 03:25:50.000000000 -0400
@@ -2639,14 +2639,20 @@
 }
 
 #ifdef CONFIG_SBUS
-static int __devinit fore200e_sba_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static const struct of_device_id fore200e_sba_match[];
+static int __devinit fore200e_sba_probe(struct platform_device *op)
 {
-	const struct fore200e_bus *bus = match->data;
+	const struct of_device_id *match;
+	const struct fore200e_bus *bus;
 	struct fore200e *fore200e;
 	static int index = 0;
 	int err;
 
+	match = of_match_device(fore200e_sba_match, &op->dev);
+	if (!match)
+		return -EINVAL;
+	bus = match->data;
+
 	fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL);
 	if (!fore200e)
 		return -ENOMEM;
@@ -2690,7 +2696,7 @@
 };
 MODULE_DEVICE_TABLE(of, fore200e_sba_match);
 
-static struct of_platform_driver fore200e_sba_driver = {
+static struct platform_driver fore200e_sba_driver = {
 	.driver = {
 		.name = "fore_200e",
 		.owner = THIS_MODULE,
@@ -2791,7 +2797,7 @@
 	printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n");
 
 #ifdef CONFIG_SBUS
-	err = of_register_platform_driver(&fore200e_sba_driver);
+	err = platform_driver_register(&fore200e_sba_driver);
 	if (err)
 		return err;
 #endif
@@ -2802,7 +2808,7 @@
 
 #ifdef CONFIG_SBUS
 	if (err)
-		of_unregister_platform_driver(&fore200e_sba_driver);
+		platform_driver_unregister(&fore200e_sba_driver);
 #endif
 
 	return err;
@@ -2814,7 +2820,7 @@
 	pci_unregister_driver(&fore200e_pca_driver);
 #endif
 #ifdef CONFIG_SBUS
-	of_unregister_platform_driver(&fore200e_sba_driver);
+	platform_driver_unregister(&fore200e_sba_driver);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/atm/fore200e.h linux-libre-2.6.39-gnu/drivers/atm/fore200e.h
--- linux-libre-2.6.38-gnu/drivers/atm/fore200e.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/fore200e.h	2011-05-19 00:06:34.000000000 -0400
@@ -263,7 +263,7 @@
 } opcode_t;
 
 
-/* virtual path / virtual channel identifers */
+/* virtual path / virtual channel identifiers */
 
 typedef struct vpvc {
     BITFIELD3(
@@ -926,7 +926,7 @@
 
 #define PCA200E_PCI_LATENCY      0x40    /* maximum slave latenty            */
 #define PCA200E_PCI_MASTER_CTRL  0x41    /* master control                   */
-#define PCA200E_PCI_THRESHOLD    0x42    /* burst / continous req threshold  */
+#define PCA200E_PCI_THRESHOLD    0x42    /* burst / continuous req threshold  */
 
 /* PBI master control register */
 
diff -druN linux-libre-2.6.38-gnu/drivers/atm/horizon.c linux-libre-2.6.39-gnu/drivers/atm/horizon.c
--- linux-libre-2.6.38-gnu/drivers/atm/horizon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/horizon.c	2011-05-19 00:06:34.000000000 -0400
@@ -169,13 +169,13 @@
   Real Time (cdv and max CDT given)
   
   CBR(pcr)             pcr bandwidth always available
-  rtVBR(pcr,scr,mbs)   scr bandwidth always available, upto pcr at mbs too
+  rtVBR(pcr,scr,mbs)   scr bandwidth always available, up to pcr at mbs too
   
   Non Real Time
   
-  nrtVBR(pcr,scr,mbs)  scr bandwidth always available, upto pcr at mbs too
+  nrtVBR(pcr,scr,mbs)  scr bandwidth always available, up to pcr at mbs too
   UBR()
-  ABR(mcr,pcr)         mcr bandwidth always available, upto pcr (depending) too
+  ABR(mcr,pcr)         mcr bandwidth always available, up to pcr (depending) too
   
   mbs is max burst size (bucket)
   pcr and scr have associated cdvt values
@@ -944,7 +944,7 @@
 // to be fixed soon, so do not define TAILRECUSRIONWORKS unless you
 // are sure it does as you may otherwise overflow the kernel stack.
 
-// giving this fn a return value would help GCC, alledgedly
+// giving this fn a return value would help GCC, allegedly
 
 static void rx_schedule (hrz_dev * dev, int irq) {
   unsigned int rx_bytes;
@@ -1036,7 +1036,7 @@
 	  // VC layer stats
 	  atomic_inc(&vcc->stats->rx);
 	  __net_timestamp(skb);
-	  // end of our responsability
+	  // end of our responsibility
 	  vcc->push (vcc, skb);
 	}
       }
diff -druN linux-libre-2.6.38-gnu/drivers/atm/idt77252.c linux-libre-2.6.39-gnu/drivers/atm/idt77252.c
--- linux-libre-2.6.38-gnu/drivers/atm/idt77252.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/idt77252.c	2011-05-19 00:06:34.000000000 -0400
@@ -3495,7 +3495,7 @@
 		return -1;
 	}
 	if (dev->phy->ioctl == NULL) {
-		printk("%s: LT had no IOCTL funtion defined.\n", card->name);
+		printk("%s: LT had no IOCTL function defined.\n", card->name);
 		deinit_card(card);
 		return -1;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/atm/idt77252.h linux-libre-2.6.39-gnu/drivers/atm/idt77252.h
--- linux-libre-2.6.38-gnu/drivers/atm/idt77252.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/idt77252.h	2011-05-19 00:06:34.000000000 -0400
@@ -766,7 +766,7 @@
 #define SAR_RCTE_BUFFSTAT_MASK 0x00003000  /* buffer status                  */
 #define SAR_RCTE_EFCI          0x00000800  /* EFCI Congestion flag           */
 #define SAR_RCTE_CLP           0x00000400  /* Cell Loss Priority flag        */
-#define SAR_RCTE_CRC           0x00000200  /* Recieved CRC Error             */
+#define SAR_RCTE_CRC           0x00000200  /* Received CRC Error             */
 #define SAR_RCTE_CELLCNT_MASK  0x000001FF  /* cell Count                     */
 
 #define SAR_RCTE_AAL0          0x00000000  /* AAL types for ALL field        */
diff -druN linux-libre-2.6.38-gnu/drivers/atm/iphase.c linux-libre-2.6.39-gnu/drivers/atm/iphase.c
--- linux-libre-2.6.38-gnu/drivers/atm/iphase.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/iphase.c	2011-05-19 00:06:34.000000000 -0400
@@ -1025,7 +1025,7 @@
 } 
   
   
-/*----------------------------- Recieving side stuff --------------------------*/  
+/*----------------------------- Receiving side stuff --------------------------*/  
  
 static void rx_excp_rcvd(struct atm_dev *dev)  
 {  
@@ -1195,7 +1195,7 @@
   if (status & RX_PKT_RCVD)  
   {  
 	/* do something */  
-	/* Basically recvd an interrupt for receving a packet.  
+	/* Basically recvd an interrupt for receiving a packet.  
 	A descriptor would have been written to the packet complete   
 	queue. Get all the descriptors and set up dma to move the   
 	packets till the packet complete queue is empty..  
@@ -1855,7 +1855,7 @@
                     return -EINVAL; 
                 }
                 if (vcc->qos.txtp.max_pcr > iadev->LineRate) {
-                   IF_CBR(printk("PCR is not availble\n");)
+                   IF_CBR(printk("PCR is not available\n");)
                    return -1;
                 }
                 vc->type = CBR;
diff -druN linux-libre-2.6.38-gnu/drivers/atm/lanai.c linux-libre-2.6.39-gnu/drivers/atm/lanai.c
--- linux-libre-2.6.38-gnu/drivers/atm/lanai.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/lanai.c	2011-05-19 00:06:34.000000000 -0400
@@ -1255,7 +1255,7 @@
 	/*
 	 * Since the "butt register" is a shared resounce on the card we
 	 * serialize all accesses to it through this spinlock.  This is
-	 * mostly just paranoia sicne the register is rarely "busy" anyway
+	 * mostly just paranoia since the register is rarely "busy" anyway
 	 * but is needed for correctness.
 	 */
 	spin_lock(&lanai->endtxlock);
@@ -1990,7 +1990,7 @@
 
 /*
  * We _can_ use VCI==0 for normal traffic, but only for UBR (or we'll
- * get a CBRZERO interrupt), and we can use it only if noone is receiving
+ * get a CBRZERO interrupt), and we can use it only if no one is receiving
  * AAL0 traffic (since they will use the same queue) - according to the
  * docs we shouldn't even use it for AAL0 traffic
  */
diff -druN linux-libre-2.6.38-gnu/drivers/atm/solos-pci.c linux-libre-2.6.39-gnu/drivers/atm/solos-pci.c
--- linux-libre-2.6.38-gnu/drivers/atm/solos-pci.c	2012-03-24 00:59:52.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/atm/solos-pci.c	2012-03-24 03:25:59.000000000 -0400
@@ -163,7 +163,6 @@
 static irqreturn_t solos_irq(int irq, void *dev_id);
 static struct atm_vcc* find_vcc(struct atm_dev *dev, short vpi, int vci);
 static int list_vccs(int vci);
-static void release_vccs(struct atm_dev *dev);
 static int atm_init(struct solos_card *, struct device *);
 static void atm_remove(struct solos_card *);
 static int send_command(struct solos_card *card, int dev, const char *buf, size_t size);
@@ -382,7 +381,6 @@
 	/* Anything but 'Showtime' is down */
 	if (strcmp(state_str, "Showtime")) {
 		atm_dev_signal_change(card->atmdev[port], ATM_PHY_SIG_LOST);
-		release_vccs(card->atmdev[port]);
 		dev_info(&card->dev->dev, "Port %d: %s\n", port, state_str);
 		return 0;
 	}
@@ -695,7 +693,7 @@
 					      size);
 			}
 			if (atmdebug) {
-				dev_info(&card->dev->dev, "Received: device %d\n", port);
+				dev_info(&card->dev->dev, "Received: port %d\n", port);
 				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
 					 size, le16_to_cpu(header->vpi),
 					 le16_to_cpu(header->vci));
@@ -708,8 +706,8 @@
 					       le16_to_cpu(header->vci));
 				if (!vcc) {
 					if (net_ratelimit())
-						dev_warn(&card->dev->dev, "Received packet for unknown VCI.VPI %d.%d on port %d\n",
-							 le16_to_cpu(header->vci), le16_to_cpu(header->vpi),
+						dev_warn(&card->dev->dev, "Received packet for unknown VPI.VCI %d.%d on port %d\n",
+							 le16_to_cpu(header->vpi), le16_to_cpu(header->vci),
 							 port);
 					continue;
 				}
@@ -828,28 +826,6 @@
 	return num_found;
 }
 
-static void release_vccs(struct atm_dev *dev)
-{
-        int i;
-
-        write_lock_irq(&vcc_sklist_lock);
-        for (i = 0; i < VCC_HTABLE_SIZE; i++) {
-                struct hlist_head *head = &vcc_hash[i];
-                struct hlist_node *node, *tmp;
-                struct sock *s;
-                struct atm_vcc *vcc;
-
-                sk_for_each_safe(s, node, tmp, head) {
-                        vcc = atm_sk(s);
-                        if (vcc->dev == dev) {
-                                vcc_release_async(vcc, -EPIPE);
-                                sk_del_node_init(s);
-                        }
-                }
-        }
-        write_unlock_irq(&vcc_sklist_lock);
-}
-
 
 static int popen(struct atm_vcc *vcc)
 {
@@ -1016,8 +992,15 @@
 
 			/* Clean up and free oldskb now it's gone */
 			if (atmdebug) {
+				struct pkt_hdr *header = (void *)oldskb->data;
+				int size = le16_to_cpu(header->size);
+
+				skb_pull(oldskb, sizeof(*header));
 				dev_info(&card->dev->dev, "Transmitted: port %d\n",
 					 port);
+				dev_info(&card->dev->dev, "size: %d VPI: %d VCI: %d\n",
+					 size, le16_to_cpu(header->vpi),
+					 le16_to_cpu(header->vci));
 				print_buffer(oldskb);
 			}
 
@@ -1260,7 +1243,7 @@
 		card->atmdev[i]->ci_range.vci_bits = 16;
 		card->atmdev[i]->dev_data = card;
 		card->atmdev[i]->phy_data = (void *)(unsigned long)i;
-		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_UNKNOWN);
+		atm_dev_signal_change(card->atmdev[i], ATM_PHY_SIG_FOUND);
 
 		skb = alloc_skb(sizeof(*header), GFP_ATOMIC);
 		if (!skb) {
diff -druN linux-libre-2.6.38-gnu/drivers/auxdisplay/cfag12864b.c linux-libre-2.6.39-gnu/drivers/auxdisplay/cfag12864b.c
--- linux-libre-2.6.38-gnu/drivers/auxdisplay/cfag12864b.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/auxdisplay/cfag12864b.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,7 +49,7 @@
 static unsigned int cfag12864b_rate = CONFIG_CFAG12864B_RATE;
 module_param(cfag12864b_rate, uint, S_IRUGO);
 MODULE_PARM_DESC(cfag12864b_rate,
-	"Refresh rate (hertzs)");
+	"Refresh rate (hertz)");
 
 unsigned int cfag12864b_getrate(void)
 {
@@ -60,7 +60,7 @@
  * cfag12864b Commands
  *
  *	E = Enable signal
- *		Everytime E switch from low to high,
+ *		Every time E switch from low to high,
  *		cfag12864b/ks0108 reads the command/data.
  *
  *	CS1 = First ks0108controller.
diff -druN linux-libre-2.6.38-gnu/drivers/base/core.c linux-libre-2.6.39-gnu/drivers/base/core.c
--- linux-libre-2.6.38-gnu/drivers/base/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1320,7 +1320,10 @@
 	struct module *owner;
 };
 
-#define to_root_device(dev) container_of(dev, struct root_device, dev)
+inline struct root_device *to_root_device(struct device *d)
+{
+	return container_of(d, struct root_device, dev);
+}
 
 static void root_device_release(struct device *dev)
 {
@@ -1551,7 +1554,34 @@
  * on the same device to ensure that new_name is valid and
  * won't conflict with other devices.
  *
- * "Never use this function, bad things will happen" - gregkh
+ * Note: Don't call this function.  Currently, the networking layer calls this
+ * function, but that will change.  The following text from Kay Sievers offers
+ * some insight:
+ *
+ * Renaming devices is racy at many levels, symlinks and other stuff are not
+ * replaced atomically, and you get a "move" uevent, but it's not easy to
+ * connect the event to the old and new device. Device nodes are not renamed at
+ * all, there isn't even support for that in the kernel now.
+ *
+ * In the meantime, during renaming, your target name might be taken by another
+ * driver, creating conflicts. Or the old name is taken directly after you
+ * renamed it -- then you get events for the same DEVPATH, before you even see
+ * the "move" event. It's just a mess, and nothing new should ever rely on
+ * kernel device renaming. Besides that, it's not even implemented now for
+ * other things than (driver-core wise very simple) network devices.
+ *
+ * We are currently about to change network renaming in udev to completely
+ * disallow renaming of devices in the same namespace as the kernel uses,
+ * because we can't solve the problems properly, that arise with swapping names
+ * of multiple interfaces without races. Means, renaming of eth[0-9]* will only
+ * be allowed to some other name than eth[0-9]*, for the aforementioned
+ * reasons.
+ *
+ * Make up a "real" name in the driver before you register anything, or add
+ * some other attributes for userspace to find the device, or use udev to add
+ * symlinks -- but never rename kernel devices later, it's a complete mess. We
+ * don't even want to get into that and try to implement the missing pieces in
+ * the core. We really have other pieces to fix in the driver core mess. :)
  */
 int device_rename(struct device *dev, const char *new_name)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/base/firmware_class.c linux-libre-2.6.39-gnu/drivers/base/firmware_class.c
--- linux-libre-2.6.38-gnu/drivers/base/firmware_class.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/firmware_class.c	2011-05-19 00:06:34.000000000 -0400
@@ -593,8 +593,7 @@
 request_firmware(const struct firmware **firmware_p, const char *name,
                  struct device *device)
 {
-        int uevent = 1;
-        return _request_firmware(firmware_p, name, device, uevent, false);
+        return _request_firmware(firmware_p, name, device, true, false);
 }
 
 /**
@@ -618,7 +617,7 @@
 	struct device *device;
 	void *context;
 	void (*cont)(const struct firmware *fw, void *context);
-	int uevent;
+	bool uevent;
 };
 
 static int request_firmware_work_func(void *arg)
@@ -661,7 +660,7 @@
  **/
 int
 request_firmware_nowait(
-	struct module *module, int uevent,
+	struct module *module, bool uevent,
 	const char *name, struct device *device, gfp_t gfp, void *context,
 	void (*cont)(const struct firmware *fw, void *context))
 {
diff -druN linux-libre-2.6.38-gnu/drivers/base/Kconfig linux-libre-2.6.39-gnu/drivers/base/Kconfig
--- linux-libre-2.6.38-gnu/drivers/base/Kconfig	2012-03-24 01:23:48.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/Kconfig	2012-03-24 03:39:59.000000000 -0400
@@ -168,4 +168,11 @@
 	bool
 	default n
 
+config ARCH_NO_SYSDEV_OPS
+	bool
+	---help---
+	  To be selected by architectures that don't use sysdev class or
+	  sysdev driver power management (suspend/resume) and shutdown
+	  operations.
+
 endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/base/Makefile linux-libre-2.6.39-gnu/drivers/base/Makefile
--- linux-libre-2.6.38-gnu/drivers/base/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 # Makefile for the Linux device tree
 
-obj-y			:= core.o sys.o bus.o dd.o \
+obj-y			:= core.o sys.o bus.o dd.o syscore.o \
 			   driver.o class.o platform.o \
 			   cpu.o firmware.o init.o map.o devres.o \
 			   attribute_container.o transport_class.o
diff -druN linux-libre-2.6.38-gnu/drivers/base/memory.c linux-libre-2.6.39-gnu/drivers/base/memory.c
--- linux-libre-2.6.38-gnu/drivers/base/memory.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/memory.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,14 @@
 static DEFINE_MUTEX(mem_sysfs_mutex);
 
 #define MEMORY_CLASS_NAME	"memory"
+#define MIN_MEMORY_BLOCK_SIZE	(1 << SECTION_SIZE_BITS)
+
+static int sections_per_block;
+
+static inline int base_memory_block_id(int section_nr)
+{
+	return section_nr / sections_per_block;
+}
 
 static struct sysdev_class memory_sysdev_class = {
 	.name = MEMORY_CLASS_NAME,
@@ -84,39 +92,72 @@
  * register_memory - Setup a sysfs device for a memory block
  */
 static
-int register_memory(struct memory_block *memory, struct mem_section *section)
+int register_memory(struct memory_block *memory)
 {
 	int error;
 
 	memory->sysdev.cls = &memory_sysdev_class;
-	memory->sysdev.id = __section_nr(section);
+	memory->sysdev.id = memory->start_section_nr / sections_per_block;
 
 	error = sysdev_register(&memory->sysdev);
 	return error;
 }
 
 static void
-unregister_memory(struct memory_block *memory, struct mem_section *section)
+unregister_memory(struct memory_block *memory)
 {
 	BUG_ON(memory->sysdev.cls != &memory_sysdev_class);
-	BUG_ON(memory->sysdev.id != __section_nr(section));
 
 	/* drop the ref. we got in remove_memory_block() */
 	kobject_put(&memory->sysdev.kobj);
 	sysdev_unregister(&memory->sysdev);
 }
 
+unsigned long __weak memory_block_size_bytes(void)
+{
+	return MIN_MEMORY_BLOCK_SIZE;
+}
+
+static unsigned long get_memory_block_size(void)
+{
+	unsigned long block_sz;
+
+	block_sz = memory_block_size_bytes();
+
+	/* Validate blk_sz is a power of 2 and not less than section size */
+	if ((block_sz & (block_sz - 1)) || (block_sz < MIN_MEMORY_BLOCK_SIZE)) {
+		WARN_ON(1);
+		block_sz = MIN_MEMORY_BLOCK_SIZE;
+	}
+
+	return block_sz;
+}
+
 /*
  * use this as the physical section index that this memsection
  * uses.
  */
 
-static ssize_t show_mem_phys_index(struct sys_device *dev,
+static ssize_t show_mem_start_phys_index(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
-	return sprintf(buf, "%08lx\n", mem->phys_index);
+	unsigned long phys_index;
+
+	phys_index = mem->start_section_nr / sections_per_block;
+	return sprintf(buf, "%08lx\n", phys_index);
+}
+
+static ssize_t show_mem_end_phys_index(struct sys_device *dev,
+			struct sysdev_attribute *attr, char *buf)
+{
+	struct memory_block *mem =
+		container_of(dev, struct memory_block, sysdev);
+	unsigned long phys_index;
+
+	phys_index = mem->end_section_nr / sections_per_block;
+	return sprintf(buf, "%08lx\n", phys_index);
 }
 
 /*
@@ -125,13 +166,16 @@
 static ssize_t show_mem_removable(struct sys_device *dev,
 			struct sysdev_attribute *attr, char *buf)
 {
-	unsigned long start_pfn;
-	int ret;
+	unsigned long i, pfn;
+	int ret = 1;
 	struct memory_block *mem =
 		container_of(dev, struct memory_block, sysdev);
 
-	start_pfn = section_nr_to_pfn(mem->phys_index);
-	ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION);
+	for (i = 0; i < sections_per_block; i++) {
+		pfn = section_nr_to_pfn(mem->start_section_nr + i);
+		ret &= is_mem_section_removable(pfn, PAGES_PER_SECTION);
+	}
+
 	return sprintf(buf, "%d\n", ret);
 }
 
@@ -184,17 +228,14 @@
  * OK to have direct references to sparsemem variables in here.
  */
 static int
-memory_block_action(struct memory_block *mem, unsigned long action)
+memory_section_action(unsigned long phys_index, unsigned long action)
 {
 	int i;
-	unsigned long psection;
 	unsigned long start_pfn, start_paddr;
 	struct page *first_page;
 	int ret;
-	int old_state = mem->state;
 
-	psection = mem->phys_index;
-	first_page = pfn_to_page(psection << PFN_SECTION_SHIFT);
+	first_page = pfn_to_page(phys_index << PFN_SECTION_SHIFT);
 
 	/*
 	 * The probe routines leave the pages reserved, just
@@ -207,8 +248,8 @@
 				continue;
 
 			printk(KERN_WARNING "section number %ld page number %d "
-				"not reserved, was it already online? \n",
-				psection, i);
+				"not reserved, was it already online?\n",
+				phys_index, i);
 			return -EBUSY;
 		}
 	}
@@ -219,18 +260,13 @@
 			ret = online_pages(start_pfn, PAGES_PER_SECTION);
 			break;
 		case MEM_OFFLINE:
-			mem->state = MEM_GOING_OFFLINE;
 			start_paddr = page_to_pfn(first_page) << PAGE_SHIFT;
 			ret = remove_memory(start_paddr,
 					    PAGES_PER_SECTION << PAGE_SHIFT);
-			if (ret) {
-				mem->state = old_state;
-				break;
-			}
 			break;
 		default:
-			WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n",
-					__func__, mem, action, action);
+			WARN(1, KERN_WARNING "%s(%ld, %ld) unknown action: "
+			     "%ld\n", __func__, phys_index, action, action);
 			ret = -EINVAL;
 	}
 
@@ -240,7 +276,8 @@
 static int memory_block_change_state(struct memory_block *mem,
 		unsigned long to_state, unsigned long from_state_req)
 {
-	int ret = 0;
+	int i, ret = 0;
+
 	mutex_lock(&mem->state_mutex);
 
 	if (mem->state != from_state_req) {
@@ -248,8 +285,23 @@
 		goto out;
 	}
 
-	ret = memory_block_action(mem, to_state);
-	if (!ret)
+	if (to_state == MEM_OFFLINE)
+		mem->state = MEM_GOING_OFFLINE;
+
+	for (i = 0; i < sections_per_block; i++) {
+		ret = memory_section_action(mem->start_section_nr + i,
+					    to_state);
+		if (ret)
+			break;
+	}
+
+	if (ret) {
+		for (i = 0; i < sections_per_block; i++)
+			memory_section_action(mem->start_section_nr + i,
+					      from_state_req);
+
+		mem->state = from_state_req;
+	} else
 		mem->state = to_state;
 
 out:
@@ -262,20 +314,15 @@
 		struct sysdev_attribute *attr, const char *buf, size_t count)
 {
 	struct memory_block *mem;
-	unsigned int phys_section_nr;
 	int ret = -EINVAL;
 
 	mem = container_of(dev, struct memory_block, sysdev);
-	phys_section_nr = mem->phys_index;
-
-	if (!present_section_nr(phys_section_nr))
-		goto out;
 
 	if (!strncmp(buf, "online", min((int)count, 6)))
 		ret = memory_block_change_state(mem, MEM_ONLINE, MEM_OFFLINE);
 	else if(!strncmp(buf, "offline", min((int)count, 7)))
 		ret = memory_block_change_state(mem, MEM_OFFLINE, MEM_ONLINE);
-out:
+
 	if (ret)
 		return ret;
 	return count;
@@ -298,7 +345,8 @@
 	return sprintf(buf, "%d\n", mem->phys_device);
 }
 
-static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL);
+static SYSDEV_ATTR(phys_index, 0444, show_mem_start_phys_index, NULL);
+static SYSDEV_ATTR(end_phys_index, 0444, show_mem_end_phys_index, NULL);
 static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state);
 static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL);
 static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL);
@@ -315,7 +363,7 @@
 print_block_size(struct sysdev_class *class, struct sysdev_class_attribute *attr,
 		 char *buf)
 {
-	return sprintf(buf, "%lx\n", (unsigned long)PAGES_PER_SECTION * PAGE_SIZE);
+	return sprintf(buf, "%lx\n", get_memory_block_size());
 }
 
 static SYSDEV_CLASS_ATTR(block_size_bytes, 0444, print_block_size, NULL);
@@ -339,12 +387,19 @@
 {
 	u64 phys_addr;
 	int nid;
-	int ret;
+	int i, ret;
 
 	phys_addr = simple_strtoull(buf, NULL, 0);
 
-	nid = memory_add_physaddr_to_nid(phys_addr);
-	ret = add_memory(nid, phys_addr, PAGES_PER_SECTION << PAGE_SHIFT);
+	for (i = 0; i < sections_per_block; i++) {
+		nid = memory_add_physaddr_to_nid(phys_addr);
+		ret = add_memory(nid, phys_addr,
+				 PAGES_PER_SECTION << PAGE_SHIFT);
+		if (ret)
+			break;
+
+		phys_addr += MIN_MEMORY_BLOCK_SIZE;
+	}
 
 	if (ret)
 		count = ret;
@@ -444,6 +499,7 @@
 	struct sys_device *sysdev;
 	struct memory_block *mem;
 	char name[sizeof(MEMORY_CLASS_NAME) + 9 + 1];
+	int block_id = base_memory_block_id(__section_nr(section));
 
 	kobj = hint ? &hint->sysdev.kobj : NULL;
 
@@ -451,7 +507,7 @@
 	 * This only works because we know that section == sysdev->id
 	 * slightly redundant with sysdev_register()
 	 */
-	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, __section_nr(section));
+	sprintf(&name[0], "%s%d", MEMORY_CLASS_NAME, block_id);
 
 	kobj = kset_find_obj_hinted(&memory_sysdev_class.kset, name, kobj);
 	if (!kobj)
@@ -476,36 +532,62 @@
 	return find_memory_block_hinted(section, NULL);
 }
 
-static int add_memory_block(int nid, struct mem_section *section,
-			unsigned long state, enum mem_add_context context)
+static int init_memory_block(struct memory_block **memory,
+			     struct mem_section *section, unsigned long state)
 {
-	struct memory_block *mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	struct memory_block *mem;
 	unsigned long start_pfn;
+	int scn_nr;
 	int ret = 0;
 
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem)
 		return -ENOMEM;
 
-	mutex_lock(&mem_sysfs_mutex);
-
-	mem->phys_index = __section_nr(section);
+	scn_nr = __section_nr(section);
+	mem->start_section_nr =
+			base_memory_block_id(scn_nr) * sections_per_block;
+	mem->end_section_nr = mem->start_section_nr + sections_per_block - 1;
 	mem->state = state;
 	mem->section_count++;
 	mutex_init(&mem->state_mutex);
-	start_pfn = section_nr_to_pfn(mem->phys_index);
+	start_pfn = section_nr_to_pfn(mem->start_section_nr);
 	mem->phys_device = arch_get_memory_phys_device(start_pfn);
 
-	ret = register_memory(mem, section);
+	ret = register_memory(mem);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_index);
 	if (!ret)
+		ret = mem_create_simple_file(mem, end_phys_index);
+	if (!ret)
 		ret = mem_create_simple_file(mem, state);
 	if (!ret)
 		ret = mem_create_simple_file(mem, phys_device);
 	if (!ret)
 		ret = mem_create_simple_file(mem, removable);
+
+	*memory = mem;
+	return ret;
+}
+
+static int add_memory_section(int nid, struct mem_section *section,
+			unsigned long state, enum mem_add_context context)
+{
+	struct memory_block *mem;
+	int ret = 0;
+
+	mutex_lock(&mem_sysfs_mutex);
+
+	mem = find_memory_block(section);
+	if (mem) {
+		mem->section_count++;
+		kobject_put(&mem->sysdev.kobj);
+	} else
+		ret = init_memory_block(&mem, section, state);
+
 	if (!ret) {
-		if (context == HOTPLUG)
+		if (context == HOTPLUG &&
+		    mem->section_count == sections_per_block)
 			ret = register_mem_sect_under_node(mem, nid);
 	}
 
@@ -520,16 +602,19 @@
 
 	mutex_lock(&mem_sysfs_mutex);
 	mem = find_memory_block(section);
+	unregister_mem_sect_under_nodes(mem, __section_nr(section));
 
 	mem->section_count--;
 	if (mem->section_count == 0) {
-		unregister_mem_sect_under_nodes(mem);
 		mem_remove_simple_file(mem, phys_index);
+		mem_remove_simple_file(mem, end_phys_index);
 		mem_remove_simple_file(mem, state);
 		mem_remove_simple_file(mem, phys_device);
 		mem_remove_simple_file(mem, removable);
-		unregister_memory(mem, section);
-	}
+		unregister_memory(mem);
+		kfree(mem);
+	} else
+		kobject_put(&mem->sysdev.kobj);
 
 	mutex_unlock(&mem_sysfs_mutex);
 	return 0;
@@ -541,7 +626,7 @@
  */
 int register_new_memory(int nid, struct mem_section *section)
 {
-	return add_memory_block(nid, section, MEM_OFFLINE, HOTPLUG);
+	return add_memory_section(nid, section, MEM_OFFLINE, HOTPLUG);
 }
 
 int unregister_memory_section(struct mem_section *section)
@@ -560,12 +645,16 @@
 	unsigned int i;
 	int ret;
 	int err;
+	unsigned long block_sz;
 
 	memory_sysdev_class.kset.uevent_ops = &memory_uevent_ops;
 	ret = sysdev_class_register(&memory_sysdev_class);
 	if (ret)
 		goto out;
 
+	block_sz = get_memory_block_size();
+	sections_per_block = block_sz / MIN_MEMORY_BLOCK_SIZE;
+
 	/*
 	 * Create entries for memory sections that were found
 	 * during boot and have been initialized
@@ -573,8 +662,8 @@
 	for (i = 0; i < NR_MEM_SECTIONS; i++) {
 		if (!present_section_nr(i))
 			continue;
-		err = add_memory_block(0, __nr_to_section(i), MEM_ONLINE,
-				       BOOT);
+		err = add_memory_section(0, __nr_to_section(i), MEM_ONLINE,
+					 BOOT);
 		if (!ret)
 			ret = err;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/base/node.c linux-libre-2.6.39-gnu/drivers/base/node.c
--- linux-libre-2.6.38-gnu/drivers/base/node.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/node.c	2011-05-19 00:06:34.000000000 -0400
@@ -375,8 +375,10 @@
 		return -EFAULT;
 	if (!node_online(nid))
 		return 0;
-	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
-	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
+
+	sect_start_pfn = section_nr_to_pfn(mem_blk->start_section_nr);
+	sect_end_pfn = section_nr_to_pfn(mem_blk->end_section_nr);
+	sect_end_pfn += PAGES_PER_SECTION - 1;
 	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
 		int page_nid;
 
@@ -400,7 +402,8 @@
 }
 
 /* unregister memory section under all nodes that it spans */
-int unregister_mem_sect_under_nodes(struct memory_block *mem_blk)
+int unregister_mem_sect_under_nodes(struct memory_block *mem_blk,
+				    unsigned long phys_index)
 {
 	NODEMASK_ALLOC(nodemask_t, unlinked_nodes, GFP_KERNEL);
 	unsigned long pfn, sect_start_pfn, sect_end_pfn;
@@ -412,7 +415,8 @@
 	if (!unlinked_nodes)
 		return -ENOMEM;
 	nodes_clear(*unlinked_nodes);
-	sect_start_pfn = section_nr_to_pfn(mem_blk->phys_index);
+
+	sect_start_pfn = section_nr_to_pfn(phys_index);
 	sect_end_pfn = sect_start_pfn + PAGES_PER_SECTION - 1;
 	for (pfn = sect_start_pfn; pfn <= sect_end_pfn; pfn++) {
 		int nid;
diff -druN linux-libre-2.6.38-gnu/drivers/base/platform.c linux-libre-2.6.39-gnu/drivers/base/platform.c
--- linux-libre-2.6.38-gnu/drivers/base/platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,6 +149,7 @@
 
 	of_device_node_put(&pa->pdev.dev);
 	kfree(pa->pdev.dev.platform_data);
+	kfree(pa->pdev.mfd_cell);
 	kfree(pa->pdev.resource);
 	kfree(pa);
 }
@@ -771,7 +772,7 @@
 
 #endif /* !CONFIG_SUSPEND */
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 
 static int platform_pm_freeze(struct device *dev)
 {
@@ -909,7 +910,7 @@
 	return ret;
 }
 
-#else /* !CONFIG_HIBERNATION */
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #define platform_pm_freeze		NULL
 #define platform_pm_thaw		NULL
@@ -920,7 +921,7 @@
 #define platform_pm_poweroff_noirq	NULL
 #define platform_pm_restore_noirq	NULL
 
-#endif /* !CONFIG_HIBERNATION */
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #ifdef CONFIG_PM_RUNTIME
 
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/main.c linux-libre-2.6.39-gnu/drivers/base/power/main.c
--- linux-libre-2.6.38-gnu/drivers/base/power/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,6 +63,7 @@
 	dev->power.wakeup = NULL;
 	spin_lock_init(&dev->power.lock);
 	pm_runtime_init(dev);
+	INIT_LIST_HEAD(&dev->power.entry);
 }
 
 /**
@@ -233,7 +234,7 @@
 		}
 		break;
 #endif /* CONFIG_SUSPEND */
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 	case PM_EVENT_FREEZE:
 	case PM_EVENT_QUIESCE:
 		if (ops->freeze) {
@@ -260,7 +261,7 @@
 			suspend_report_result(ops->restore, error);
 		}
 		break;
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
 	default:
 		error = -EINVAL;
 	}
@@ -308,7 +309,7 @@
 		}
 		break;
 #endif /* CONFIG_SUSPEND */
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 	case PM_EVENT_FREEZE:
 	case PM_EVENT_QUIESCE:
 		if (ops->freeze_noirq) {
@@ -335,7 +336,7 @@
 			suspend_report_result(ops->restore_noirq, error);
 		}
 		break;
-#endif /* CONFIG_HIBERNATION */
+#endif /* CONFIG_HIBERNATE_CALLBACKS */
 	default:
 		error = -EINVAL;
 	}
@@ -423,26 +424,22 @@
 	TRACE_DEVICE(dev);
 	TRACE_RESUME(0);
 
-	if (dev->bus && dev->bus->pm) {
-		pm_dev_dbg(dev, state, "EARLY ");
-		error = pm_noirq_op(dev, dev->bus->pm, state);
-		if (error)
-			goto End;
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "EARLY power domain ");
+		pm_noirq_op(dev, &dev->pwr_domain->ops, state);
 	}
 
 	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "EARLY type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
-		if (error)
-			goto End;
-	}
-
-	if (dev->class && dev->class->pm) {
+	} else if (dev->class && dev->class->pm) {
 		pm_dev_dbg(dev, state, "EARLY class ");
 		error = pm_noirq_op(dev, dev->class->pm, state);
+	} else if (dev->bus && dev->bus->pm) {
+		pm_dev_dbg(dev, state, "EARLY ");
+		error = pm_noirq_op(dev, dev->bus->pm, state);
 	}
 
-End:
 	TRACE_RESUME(error);
 	return error;
 }
@@ -518,36 +515,39 @@
 
 	dev->power.in_suspend = false;
 
-	if (dev->bus) {
-		if (dev->bus->pm) {
-			pm_dev_dbg(dev, state, "");
-			error = pm_op(dev, dev->bus->pm, state);
-		} else if (dev->bus->resume) {
-			pm_dev_dbg(dev, state, "legacy ");
-			error = legacy_resume(dev, dev->bus->resume);
-		}
-		if (error)
-			goto End;
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "power domain ");
+		pm_op(dev, &dev->pwr_domain->ops, state);
 	}
 
-	if (dev->type) {
-		if (dev->type->pm) {
-			pm_dev_dbg(dev, state, "type ");
-			error = pm_op(dev, dev->type->pm, state);
-		}
-		if (error)
-			goto End;
+	if (dev->type && dev->type->pm) {
+		pm_dev_dbg(dev, state, "type ");
+		error = pm_op(dev, dev->type->pm, state);
+		goto End;
 	}
 
 	if (dev->class) {
 		if (dev->class->pm) {
 			pm_dev_dbg(dev, state, "class ");
 			error = pm_op(dev, dev->class->pm, state);
+			goto End;
 		} else if (dev->class->resume) {
 			pm_dev_dbg(dev, state, "legacy class ");
 			error = legacy_resume(dev, dev->class->resume);
+			goto End;
 		}
 	}
+
+	if (dev->bus) {
+		if (dev->bus->pm) {
+			pm_dev_dbg(dev, state, "");
+			error = pm_op(dev, dev->bus->pm, state);
+		} else if (dev->bus->resume) {
+			pm_dev_dbg(dev, state, "legacy ");
+			error = legacy_resume(dev, dev->bus->resume);
+		}
+	}
+
  End:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -629,19 +629,23 @@
 {
 	device_lock(dev);
 
-	if (dev->class && dev->class->pm && dev->class->pm->complete) {
-		pm_dev_dbg(dev, state, "completing class ");
-		dev->class->pm->complete(dev);
+	if (dev->pwr_domain && dev->pwr_domain->ops.complete) {
+		pm_dev_dbg(dev, state, "completing power domain ");
+		dev->pwr_domain->ops.complete(dev);
 	}
 
-	if (dev->type && dev->type->pm && dev->type->pm->complete) {
+	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "completing type ");
-		dev->type->pm->complete(dev);
-	}
-
-	if (dev->bus && dev->bus->pm && dev->bus->pm->complete) {
+		if (dev->type->pm->complete)
+			dev->type->pm->complete(dev);
+	} else if (dev->class && dev->class->pm) {
+		pm_dev_dbg(dev, state, "completing class ");
+		if (dev->class->pm->complete)
+			dev->class->pm->complete(dev);
+	} else if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "completing ");
-		dev->bus->pm->complete(dev);
+		if (dev->bus->pm->complete)
+			dev->bus->pm->complete(dev);
 	}
 
 	device_unlock(dev);
@@ -669,7 +673,6 @@
 		mutex_unlock(&dpm_list_mtx);
 
 		device_complete(dev, state);
-		pm_runtime_put_sync(dev);
 
 		mutex_lock(&dpm_list_mtx);
 		put_device(dev);
@@ -727,29 +730,31 @@
  */
 static int device_suspend_noirq(struct device *dev, pm_message_t state)
 {
-	int error = 0;
-
-	if (dev->class && dev->class->pm) {
-		pm_dev_dbg(dev, state, "LATE class ");
-		error = pm_noirq_op(dev, dev->class->pm, state);
-		if (error)
-			goto End;
-	}
+	int error;
 
 	if (dev->type && dev->type->pm) {
 		pm_dev_dbg(dev, state, "LATE type ");
 		error = pm_noirq_op(dev, dev->type->pm, state);
 		if (error)
-			goto End;
-	}
-
-	if (dev->bus && dev->bus->pm) {
+			return error;
+	} else if (dev->class && dev->class->pm) {
+		pm_dev_dbg(dev, state, "LATE class ");
+		error = pm_noirq_op(dev, dev->class->pm, state);
+		if (error)
+			return error;
+	} else if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "LATE ");
 		error = pm_noirq_op(dev, dev->bus->pm, state);
+		if (error)
+			return error;
 	}
 
-End:
-	return error;
+	if (dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "LATE power domain ");
+		pm_noirq_op(dev, &dev->pwr_domain->ops, state);
+	}
+
+	return 0;
 }
 
 /**
@@ -836,25 +841,22 @@
 		goto End;
 	}
 
+	if (dev->type && dev->type->pm) {
+		pm_dev_dbg(dev, state, "type ");
+		error = pm_op(dev, dev->type->pm, state);
+		goto Domain;
+	}
+
 	if (dev->class) {
 		if (dev->class->pm) {
 			pm_dev_dbg(dev, state, "class ");
 			error = pm_op(dev, dev->class->pm, state);
+			goto Domain;
 		} else if (dev->class->suspend) {
 			pm_dev_dbg(dev, state, "legacy class ");
 			error = legacy_suspend(dev, state, dev->class->suspend);
+			goto Domain;
 		}
-		if (error)
-			goto End;
-	}
-
-	if (dev->type) {
-		if (dev->type->pm) {
-			pm_dev_dbg(dev, state, "type ");
-			error = pm_op(dev, dev->type->pm, state);
-		}
-		if (error)
-			goto End;
 	}
 
 	if (dev->bus) {
@@ -867,6 +869,12 @@
 		}
 	}
 
+ Domain:
+	if (!error && dev->pwr_domain) {
+		pm_dev_dbg(dev, state, "power domain ");
+		pm_op(dev, &dev->pwr_domain->ops, state);
+	}
+
  End:
 	device_unlock(dev);
 	complete_all(&dev->power.completion);
@@ -957,27 +965,34 @@
 
 	device_lock(dev);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
+	if (dev->type && dev->type->pm) {
+		pm_dev_dbg(dev, state, "preparing type ");
+		if (dev->type->pm->prepare)
+			error = dev->type->pm->prepare(dev);
+		suspend_report_result(dev->type->pm->prepare, error);
+		if (error)
+			goto End;
+	} else if (dev->class && dev->class->pm) {
+		pm_dev_dbg(dev, state, "preparing class ");
+		if (dev->class->pm->prepare)
+			error = dev->class->pm->prepare(dev);
+		suspend_report_result(dev->class->pm->prepare, error);
+		if (error)
+			goto End;
+	} else if (dev->bus && dev->bus->pm) {
 		pm_dev_dbg(dev, state, "preparing ");
-		error = dev->bus->pm->prepare(dev);
+		if (dev->bus->pm->prepare)
+			error = dev->bus->pm->prepare(dev);
 		suspend_report_result(dev->bus->pm->prepare, error);
 		if (error)
 			goto End;
 	}
 
-	if (dev->type && dev->type->pm && dev->type->pm->prepare) {
-		pm_dev_dbg(dev, state, "preparing type ");
-		error = dev->type->pm->prepare(dev);
-		suspend_report_result(dev->type->pm->prepare, error);
-		if (error)
-			goto End;
+	if (dev->pwr_domain && dev->pwr_domain->ops.prepare) {
+		pm_dev_dbg(dev, state, "preparing power domain ");
+		dev->pwr_domain->ops.prepare(dev);
 	}
 
-	if (dev->class && dev->class->pm && dev->class->pm->prepare) {
-		pm_dev_dbg(dev, state, "preparing class ");
-		error = dev->class->pm->prepare(dev);
-		suspend_report_result(dev->class->pm->prepare, error);
-	}
  End:
 	device_unlock(dev);
 
@@ -1005,12 +1020,9 @@
 		if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
 			pm_wakeup_event(dev, 0);
 
-		if (pm_wakeup_pending()) {
-			pm_runtime_put_sync(dev);
-			error = -EBUSY;
-		} else {
-			error = device_prepare(dev, state);
-		}
+		pm_runtime_put_sync(dev);
+		error = pm_wakeup_pending() ?
+				-EBUSY : device_prepare(dev, state);
 
 		mutex_lock(&dpm_list_mtx);
 		if (error) {
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/Makefile linux-libre-2.6.39-gnu/drivers/base/power/Makefile
--- linux-libre-2.6.38-gnu/drivers/base/power/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,6 @@
-obj-$(CONFIG_PM)	+= sysfs.o
+obj-$(CONFIG_PM)	+= sysfs.o generic_ops.o
 obj-$(CONFIG_PM_SLEEP)	+= main.o wakeup.o
 obj-$(CONFIG_PM_RUNTIME)	+= runtime.o
-obj-$(CONFIG_PM_OPS)	+= generic_ops.o
 obj-$(CONFIG_PM_TRACE_RTC)	+= trace.o
 obj-$(CONFIG_PM_OPP)	+= opp.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/opp.c linux-libre-2.6.39-gnu/drivers/base/power/opp.c
--- linux-libre-2.6.38-gnu/drivers/base/power/opp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/opp.c	2011-05-19 00:06:34.000000000 -0400
@@ -222,7 +222,7 @@
  * opp_find_freq_exact() - search for an exact frequency
  * @dev:		device for which we do this operation
  * @freq:		frequency to search for
- * @is_available:	true/false - match for available opp
+ * @available:		true/false - match for available opp
  *
  * Searches for exact match in the opp list and returns pointer to the matching
  * opp if found, else returns ERR_PTR in case of error and should be handled
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/power.h linux-libre-2.6.39-gnu/drivers/base/power/power.h
--- linux-libre-2.6.38-gnu/drivers/base/power/power.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/power.h	2011-05-19 00:06:34.000000000 -0400
@@ -58,19 +58,18 @@
  * sysfs.c
  */
 
-extern int dpm_sysfs_add(struct device *);
-extern void dpm_sysfs_remove(struct device *);
-extern void rpm_sysfs_remove(struct device *);
+extern int dpm_sysfs_add(struct device *dev);
+extern void dpm_sysfs_remove(struct device *dev);
+extern void rpm_sysfs_remove(struct device *dev);
+extern int wakeup_sysfs_add(struct device *dev);
+extern void wakeup_sysfs_remove(struct device *dev);
 
 #else /* CONFIG_PM */
 
-static inline int dpm_sysfs_add(struct device *dev)
-{
-	return 0;
-}
-
-static inline void dpm_sysfs_remove(struct device *dev)
-{
-}
+static inline int dpm_sysfs_add(struct device *dev) { return 0; }
+static inline void dpm_sysfs_remove(struct device *dev) {}
+static inline void rpm_sysfs_remove(struct device *dev) {}
+static inline int wakeup_sysfs_add(struct device *dev) { return 0; }
+static inline void wakeup_sysfs_remove(struct device *dev) {}
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/runtime.c linux-libre-2.6.39-gnu/drivers/base/power/runtime.c
--- linux-libre-2.6.38-gnu/drivers/base/power/runtime.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/runtime.c	2011-05-19 00:06:34.000000000 -0400
@@ -168,6 +168,7 @@
 static int rpm_idle(struct device *dev, int rpmflags)
 {
 	int (*callback)(struct device *);
+	int (*domain_callback)(struct device *);
 	int retval;
 
 	retval = rpm_check_suspend_allowed(dev);
@@ -213,19 +214,28 @@
 
 	dev->power.idle_notification = true;
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_idle)
-		callback = dev->bus->pm->runtime_idle;
-	else if (dev->type && dev->type->pm && dev->type->pm->runtime_idle)
+	if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_idle;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_idle;
+	else if (dev->bus && dev->bus->pm)
+		callback = dev->bus->pm->runtime_idle;
 	else
 		callback = NULL;
 
-	if (callback) {
+	if (dev->pwr_domain)
+		domain_callback = dev->pwr_domain->ops.runtime_idle;
+	else
+		domain_callback = NULL;
+
+	if (callback || domain_callback) {
 		spin_unlock_irq(&dev->power.lock);
 
-		callback(dev);
+		if (domain_callback)
+			retval = domain_callback(dev);
+
+		if (!retval && callback)
+			callback(dev);
 
 		spin_lock_irq(&dev->power.lock);
 	}
@@ -372,12 +382,12 @@
 
 	__update_runtime_status(dev, RPM_SUSPENDING);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend)
-		callback = dev->bus->pm->runtime_suspend;
-	else if (dev->type && dev->type->pm && dev->type->pm->runtime_suspend)
+	if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_suspend;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_suspend;
+	else if (dev->bus && dev->bus->pm)
+		callback = dev->bus->pm->runtime_suspend;
 	else
 		callback = NULL;
 
@@ -390,6 +400,8 @@
 		else
 			pm_runtime_cancel_pending(dev);
 	} else {
+		if (dev->pwr_domain)
+			rpm_callback(dev->pwr_domain->ops.runtime_suspend, dev);
  no_callback:
 		__update_runtime_status(dev, RPM_SUSPENDED);
 		pm_runtime_deactivate_timer(dev);
@@ -431,7 +443,7 @@
  *
  * Check if the device's run-time PM status allows it to be resumed.  Cancel
  * any scheduled or pending requests.  If another resume has been started
- * earlier, either return imediately or wait for it to finish, depending on the
+ * earlier, either return immediately or wait for it to finish, depending on the
  * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
  * parallel with this function, either tell the other process to resume after
  * suspending (deferred_resume) or wait for it to finish.  If the RPM_ASYNC
@@ -569,12 +581,15 @@
 
 	__update_runtime_status(dev, RPM_RESUMING);
 
-	if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume)
-		callback = dev->bus->pm->runtime_resume;
-	else if (dev->type && dev->type->pm && dev->type->pm->runtime_resume)
+	if (dev->pwr_domain)
+		rpm_callback(dev->pwr_domain->ops.runtime_resume, dev);
+
+	if (dev->type && dev->type->pm)
 		callback = dev->type->pm->runtime_resume;
 	else if (dev->class && dev->class->pm)
 		callback = dev->class->pm->runtime_resume;
+	else if (dev->bus && dev->bus->pm)
+		callback = dev->bus->pm->runtime_resume;
 	else
 		callback = NULL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/sysfs.c linux-libre-2.6.39-gnu/drivers/base/power/sysfs.c
--- linux-libre-2.6.38-gnu/drivers/base/power/sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -431,26 +431,18 @@
 static DEVICE_ATTR(async, 0644, async_show, async_store);
 #endif /* CONFIG_PM_ADVANCED_DEBUG */
 
-static struct attribute * power_attrs[] = {
-	&dev_attr_wakeup.attr,
-#ifdef CONFIG_PM_SLEEP
-	&dev_attr_wakeup_count.attr,
-	&dev_attr_wakeup_active_count.attr,
-	&dev_attr_wakeup_hit_count.attr,
-	&dev_attr_wakeup_active.attr,
-	&dev_attr_wakeup_total_time_ms.attr,
-	&dev_attr_wakeup_max_time_ms.attr,
-	&dev_attr_wakeup_last_time_ms.attr,
-#endif
+static struct attribute *power_attrs[] = {
 #ifdef CONFIG_PM_ADVANCED_DEBUG
+#ifdef CONFIG_PM_SLEEP
 	&dev_attr_async.attr,
+#endif
 #ifdef CONFIG_PM_RUNTIME
 	&dev_attr_runtime_status.attr,
 	&dev_attr_runtime_usage.attr,
 	&dev_attr_runtime_active_kids.attr,
 	&dev_attr_runtime_enabled.attr,
 #endif
-#endif
+#endif /* CONFIG_PM_ADVANCED_DEBUG */
 	NULL,
 };
 static struct attribute_group pm_attr_group = {
@@ -458,9 +450,26 @@
 	.attrs	= power_attrs,
 };
 
-#ifdef CONFIG_PM_RUNTIME
+static struct attribute *wakeup_attrs[] = {
+#ifdef CONFIG_PM_SLEEP
+	&dev_attr_wakeup.attr,
+	&dev_attr_wakeup_count.attr,
+	&dev_attr_wakeup_active_count.attr,
+	&dev_attr_wakeup_hit_count.attr,
+	&dev_attr_wakeup_active.attr,
+	&dev_attr_wakeup_total_time_ms.attr,
+	&dev_attr_wakeup_max_time_ms.attr,
+	&dev_attr_wakeup_last_time_ms.attr,
+#endif
+	NULL,
+};
+static struct attribute_group pm_wakeup_attr_group = {
+	.name	= power_group_name,
+	.attrs	= wakeup_attrs,
+};
 
 static struct attribute *runtime_attrs[] = {
+#ifdef CONFIG_PM_RUNTIME
 #ifndef CONFIG_PM_ADVANCED_DEBUG
 	&dev_attr_runtime_status.attr,
 #endif
@@ -468,6 +477,7 @@
 	&dev_attr_runtime_suspended_time.attr,
 	&dev_attr_runtime_active_time.attr,
 	&dev_attr_autosuspend_delay_ms.attr,
+#endif /* CONFIG_PM_RUNTIME */
 	NULL,
 };
 static struct attribute_group pm_runtime_attr_group = {
@@ -480,35 +490,49 @@
 	int rc;
 
 	rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
-	if (rc == 0 && !dev->power.no_callbacks) {
+	if (rc)
+		return rc;
+
+	if (pm_runtime_callbacks_present(dev)) {
 		rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
 		if (rc)
-			sysfs_remove_group(&dev->kobj, &pm_attr_group);
+			goto err_out;
+	}
+
+	if (device_can_wakeup(dev)) {
+		rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
+		if (rc) {
+			if (pm_runtime_callbacks_present(dev))
+				sysfs_unmerge_group(&dev->kobj,
+						    &pm_runtime_attr_group);
+			goto err_out;
+		}
 	}
+	return 0;
+
+ err_out:
+	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 	return rc;
 }
 
-void rpm_sysfs_remove(struct device *dev)
+int wakeup_sysfs_add(struct device *dev)
 {
-	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
+	return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-void dpm_sysfs_remove(struct device *dev)
+void wakeup_sysfs_remove(struct device *dev)
 {
-	rpm_sysfs_remove(dev);
-	sysfs_remove_group(&dev->kobj, &pm_attr_group);
+	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 }
 
-#else /* CONFIG_PM_RUNTIME */
-
-int dpm_sysfs_add(struct device * dev)
+void rpm_sysfs_remove(struct device *dev)
 {
-	return sysfs_create_group(&dev->kobj, &pm_attr_group);
+	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
 }
 
-void dpm_sysfs_remove(struct device * dev)
+void dpm_sysfs_remove(struct device *dev)
 {
+	rpm_sysfs_remove(dev);
+	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
 }
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/trace.c linux-libre-2.6.39-gnu/drivers/base/power/trace.c
--- linux-libre-2.6.38-gnu/drivers/base/power/trace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/trace.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,7 +112,7 @@
 	unsigned int val;
 
 	get_rtc_time(&time);
-	printk("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
+	pr_info("Time: %2d:%02d:%02d  Date: %02d/%02d/%02d\n",
 		time.tm_hour, time.tm_min, time.tm_sec,
 		time.tm_mon + 1, time.tm_mday, time.tm_year % 100);
 	val = time.tm_year;				/* 100 years */
@@ -179,7 +179,7 @@
 		unsigned int hash = hash_string(lineno, file, FILEHASH);
 		if (hash != value)
 			continue;
-		printk("  hash matches %s:%u\n", file, lineno);
+		pr_info("  hash matches %s:%u\n", file, lineno);
 		match++;
 	}
 	return match;
@@ -255,7 +255,7 @@
 	val = val / FILEHASH;
 	dev = val /* % DEVHASH */;
 
-	printk("  Magic number: %d:%d:%d\n", user, file, dev);
+	pr_info("  Magic number: %d:%d:%d\n", user, file, dev);
 	show_file_hash(file);
 	show_dev_hash(dev);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/base/power/wakeup.c linux-libre-2.6.39-gnu/drivers/base/power/wakeup.c
--- linux-libre-2.6.38-gnu/drivers/base/power/wakeup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/power/wakeup.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,12 +24,26 @@
  */
 bool events_check_enabled;
 
-/* The counter of registered wakeup events. */
-static atomic_t event_count = ATOMIC_INIT(0);
-/* A preserved old value of event_count. */
+/*
+ * Combined counters of registered wakeup events and wakeup events in progress.
+ * They need to be modified together atomically, so it's better to use one
+ * atomic variable to hold them both.
+ */
+static atomic_t combined_event_count = ATOMIC_INIT(0);
+
+#define IN_PROGRESS_BITS	(sizeof(int) * 4)
+#define MAX_IN_PROGRESS		((1 << IN_PROGRESS_BITS) - 1)
+
+static void split_counters(unsigned int *cnt, unsigned int *inpr)
+{
+	unsigned int comb = atomic_read(&combined_event_count);
+
+	*cnt = (comb >> IN_PROGRESS_BITS);
+	*inpr = comb & MAX_IN_PROGRESS;
+}
+
+/* A preserved old value of the events counter. */
 static unsigned int saved_count;
-/* The counter of wakeup events being processed. */
-static atomic_t events_in_progress = ATOMIC_INIT(0);
 
 static DEFINE_SPINLOCK(events_lock);
 
@@ -228,6 +242,35 @@
 EXPORT_SYMBOL_GPL(device_wakeup_disable);
 
 /**
+ * device_set_wakeup_capable - Set/reset device wakeup capability flag.
+ * @dev: Device to handle.
+ * @capable: Whether or not @dev is capable of waking up the system from sleep.
+ *
+ * If @capable is set, set the @dev's power.can_wakeup flag and add its
+ * wakeup-related attributes to sysfs.  Otherwise, unset the @dev's
+ * power.can_wakeup flag and remove its wakeup-related attributes from sysfs.
+ *
+ * This function may sleep and it can't be called from any context where
+ * sleeping is not allowed.
+ */
+void device_set_wakeup_capable(struct device *dev, bool capable)
+{
+	if (!!dev->power.can_wakeup == !!capable)
+		return;
+
+	if (device_is_registered(dev) && !list_empty(&dev->power.entry)) {
+		if (capable) {
+			if (wakeup_sysfs_add(dev))
+				return;
+		} else {
+			wakeup_sysfs_remove(dev);
+		}
+	}
+	dev->power.can_wakeup = capable;
+}
+EXPORT_SYMBOL_GPL(device_set_wakeup_capable);
+
+/**
  * device_init_wakeup - Device wakeup initialization.
  * @dev: Device to handle.
  * @enable: Whether or not to enable @dev as a wakeup device.
@@ -307,7 +350,8 @@
 	ws->timer_expires = jiffies;
 	ws->last_time = ktime_get();
 
-	atomic_inc(&events_in_progress);
+	/* Increment the counter of events in progress. */
+	atomic_inc(&combined_event_count);
 }
 
 /**
@@ -394,14 +438,10 @@
 	del_timer(&ws->timer);
 
 	/*
-	 * event_count has to be incremented before events_in_progress is
-	 * modified, so that the callers of pm_check_wakeup_events() and
-	 * pm_save_wakeup_count() don't see the old value of event_count and
-	 * events_in_progress equal to zero at the same time.
+	 * Increment the counter of registered wakeup events and decrement the
+	 * couter of wakeup events in progress simultaneously.
 	 */
-	atomic_inc(&event_count);
-	smp_mb__before_atomic_dec();
-	atomic_dec(&events_in_progress);
+	atomic_add(MAX_IN_PROGRESS, &combined_event_count);
 }
 
 /**
@@ -556,8 +596,10 @@
 
 	spin_lock_irqsave(&events_lock, flags);
 	if (events_check_enabled) {
-		ret = ((unsigned int)atomic_read(&event_count) != saved_count)
-			|| atomic_read(&events_in_progress);
+		unsigned int cnt, inpr;
+
+		split_counters(&cnt, &inpr);
+		ret = (cnt != saved_count || inpr > 0);
 		events_check_enabled = !ret;
 	}
 	spin_unlock_irqrestore(&events_lock, flags);
@@ -573,25 +615,25 @@
  * Store the number of registered wakeup events at the address in @count.  Block
  * if the current number of wakeup events being processed is nonzero.
  *
- * Return false if the wait for the number of wakeup events being processed to
+ * Return 'false' if the wait for the number of wakeup events being processed to
  * drop down to zero has been interrupted by a signal (and the current number
- * of wakeup events being processed is still nonzero).  Otherwise return true.
+ * of wakeup events being processed is still nonzero).  Otherwise return 'true'.
  */
 bool pm_get_wakeup_count(unsigned int *count)
 {
-	bool ret;
-
-	if (capable(CAP_SYS_ADMIN))
-		events_check_enabled = false;
+	unsigned int cnt, inpr;
 
-	while (atomic_read(&events_in_progress) && !signal_pending(current)) {
+	for (;;) {
+		split_counters(&cnt, &inpr);
+		if (inpr == 0 || signal_pending(current))
+			break;
 		pm_wakeup_update_hit_counts();
 		schedule_timeout_interruptible(msecs_to_jiffies(TIMEOUT));
 	}
 
-	ret = !atomic_read(&events_in_progress);
-	*count = atomic_read(&event_count);
-	return ret;
+	split_counters(&cnt, &inpr);
+	*count = cnt;
+	return !inpr;
 }
 
 /**
@@ -600,24 +642,25 @@
  *
  * If @count is equal to the current number of registered wakeup events and the
  * current number of wakeup events being processed is zero, store @count as the
- * old number of registered wakeup events to be used by pm_check_wakeup_events()
- * and return true.  Otherwise return false.
+ * old number of registered wakeup events for pm_check_wakeup_events(), enable
+ * wakeup events detection and return 'true'.  Otherwise disable wakeup events
+ * detection and return 'false'.
  */
 bool pm_save_wakeup_count(unsigned int count)
 {
-	bool ret = false;
+	unsigned int cnt, inpr;
 
+	events_check_enabled = false;
 	spin_lock_irq(&events_lock);
-	if (count == (unsigned int)atomic_read(&event_count)
-	    && !atomic_read(&events_in_progress)) {
+	split_counters(&cnt, &inpr);
+	if (cnt == count && inpr == 0) {
 		saved_count = count;
 		events_check_enabled = true;
-		ret = true;
 	}
 	spin_unlock_irq(&events_lock);
-	if (!ret)
+	if (!events_check_enabled)
 		pm_wakeup_update_hit_counts();
-	return ret;
+	return events_check_enabled;
 }
 
 static struct dentry *wakeup_sources_stats_dentry;
diff -druN linux-libre-2.6.38-gnu/drivers/base/sys.c linux-libre-2.6.39-gnu/drivers/base/sys.c
--- linux-libre-2.6.38-gnu/drivers/base/sys.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/base/sys.c	2011-05-19 00:06:34.000000000 -0400
@@ -166,8 +166,38 @@
 
 static DEFINE_MUTEX(sysdev_drivers_lock);
 
+/*
+ * @dev != NULL means that we're unwinding because some drv->add()
+ * failed for some reason. You need to grab sysdev_drivers_lock before
+ * calling this.
+ */
+static void __sysdev_driver_remove(struct sysdev_class *cls,
+				   struct sysdev_driver *drv,
+				   struct sys_device *from_dev)
+{
+	struct sys_device *dev = from_dev;
+
+	list_del_init(&drv->entry);
+	if (!cls)
+		return;
+
+	if (!drv->remove)
+		goto kset_put;
+
+	if (dev)
+		list_for_each_entry_continue_reverse(dev, &cls->kset.list,
+						     kobj.entry)
+			drv->remove(dev);
+	else
+		list_for_each_entry(dev, &cls->kset.list, kobj.entry)
+			drv->remove(dev);
+
+kset_put:
+	kset_put(&cls->kset);
+}
+
 /**
- *	sysdev_driver_register - Register auxillary driver
+ *	sysdev_driver_register - Register auxiliary driver
  *	@cls:	Device class driver belongs to.
  *	@drv:	Driver.
  *
@@ -175,14 +205,14 @@
  *	called on each operation on devices of that class. The refcount
  *	of @cls is incremented.
  */
-
 int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv)
 {
+	struct sys_device *dev = NULL;
 	int err = 0;
 
 	if (!cls) {
-		WARN(1, KERN_WARNING "sysdev: invalid class passed to "
-			"sysdev_driver_register!\n");
+		WARN(1, KERN_WARNING "sysdev: invalid class passed to %s!\n",
+			__func__);
 		return -EINVAL;
 	}
 
@@ -198,21 +228,29 @@
 
 		/* If devices of this class already exist, tell the driver */
 		if (drv->add) {
-			struct sys_device *dev;
-			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
-				drv->add(dev);
+			list_for_each_entry(dev, &cls->kset.list, kobj.entry) {
+				err = drv->add(dev);
+				if (err)
+					goto unwind;
+			}
 		}
 	} else {
 		err = -EINVAL;
 		WARN(1, KERN_ERR "%s: invalid device class\n", __func__);
 	}
+
+	goto unlock;
+
+unwind:
+	__sysdev_driver_remove(cls, drv, dev);
+
+unlock:
 	mutex_unlock(&sysdev_drivers_lock);
 	return err;
 }
 
-
 /**
- *	sysdev_driver_unregister - Remove an auxillary driver.
+ *	sysdev_driver_unregister - Remove an auxiliary driver.
  *	@cls:	Class driver belongs to.
  *	@drv:	Driver.
  */
@@ -220,23 +258,12 @@
 			      struct sysdev_driver *drv)
 {
 	mutex_lock(&sysdev_drivers_lock);
-	list_del_init(&drv->entry);
-	if (cls) {
-		if (drv->remove) {
-			struct sys_device *dev;
-			list_for_each_entry(dev, &cls->kset.list, kobj.entry)
-				drv->remove(dev);
-		}
-		kset_put(&cls->kset);
-	}
+	__sysdev_driver_remove(cls, drv, NULL);
 	mutex_unlock(&sysdev_drivers_lock);
 }
-
 EXPORT_SYMBOL_GPL(sysdev_driver_register);
 EXPORT_SYMBOL_GPL(sysdev_driver_unregister);
 
-
-
 /**
  *	sysdev_register - add a system device to the tree
  *	@sysdev:	device in question
@@ -275,7 +302,7 @@
 		 * code that should have called us.
 		 */
 
-		/* Notify class auxillary drivers */
+		/* Notify class auxiliary drivers */
 		list_for_each_entry(drv, &cls->drivers, entry) {
 			if (drv->add)
 				drv->add(sysdev);
@@ -302,13 +329,13 @@
 }
 
 
-
+#ifndef CONFIG_ARCH_NO_SYSDEV_OPS
 /**
  *	sysdev_shutdown - Shut down all system devices.
  *
  *	Loop over each class of system devices, and the devices in each
  *	of those classes. For each device, we call the shutdown method for
- *	each driver registered for the device - the auxillaries,
+ *	each driver registered for the device - the auxiliaries,
  *	and the class driver.
  *
  *	Note: The list is iterated in reverse order, so that we shut down
@@ -333,7 +360,7 @@
 			struct sysdev_driver *drv;
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
-			/* Call auxillary drivers first */
+			/* Call auxiliary drivers first */
 			list_for_each_entry(drv, &cls->drivers, entry) {
 				if (drv->shutdown)
 					drv->shutdown(sysdev);
@@ -358,7 +385,7 @@
 	WARN_ONCE(!irqs_disabled(),
 		"Interrupts enabled after %pF\n", cls->resume);
 
-	/* Call auxillary drivers next. */
+	/* Call auxiliary drivers next. */
 	list_for_each_entry(drv, &cls->drivers, entry) {
 		if (drv->resume)
 			drv->resume(dev);
@@ -405,7 +432,7 @@
 		list_for_each_entry(sysdev, &cls->kset.list, kobj.entry) {
 			pr_debug(" %s\n", kobject_name(&sysdev->kobj));
 
-			/* Call auxillary drivers first */
+			/* Call auxiliary drivers first */
 			list_for_each_entry(drv, &cls->drivers, entry) {
 				if (drv->suspend) {
 					ret = drv->suspend(sysdev, state);
@@ -497,6 +524,7 @@
 	return 0;
 }
 EXPORT_SYMBOL_GPL(sysdev_resume);
+#endif /* CONFIG_ARCH_NO_SYSDEV_OPS */
 
 int __init system_bus_init(void)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/base/syscore.c linux-libre-2.6.39-gnu/drivers/base/syscore.c
--- linux-libre-2.6.38-gnu/drivers/base/syscore.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/base/syscore.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ *  syscore.c - Execution of system core operations.
+ *
+ *  Copyright (C) 2011 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
+ *
+ *  This file is released under the GPLv2.
+ */
+
+#include <linux/syscore_ops.h>
+#include <linux/mutex.h>
+#include <linux/module.h>
+
+static LIST_HEAD(syscore_ops_list);
+static DEFINE_MUTEX(syscore_ops_lock);
+
+/**
+ * register_syscore_ops - Register a set of system core operations.
+ * @ops: System core operations to register.
+ */
+void register_syscore_ops(struct syscore_ops *ops)
+{
+	mutex_lock(&syscore_ops_lock);
+	list_add_tail(&ops->node, &syscore_ops_list);
+	mutex_unlock(&syscore_ops_lock);
+}
+EXPORT_SYMBOL_GPL(register_syscore_ops);
+
+/**
+ * unregister_syscore_ops - Unregister a set of system core operations.
+ * @ops: System core operations to unregister.
+ */
+void unregister_syscore_ops(struct syscore_ops *ops)
+{
+	mutex_lock(&syscore_ops_lock);
+	list_del(&ops->node);
+	mutex_unlock(&syscore_ops_lock);
+}
+EXPORT_SYMBOL_GPL(unregister_syscore_ops);
+
+#ifdef CONFIG_PM_SLEEP
+/**
+ * syscore_suspend - Execute all the registered system core suspend callbacks.
+ *
+ * This function is executed with one CPU on-line and disabled interrupts.
+ */
+int syscore_suspend(void)
+{
+	struct syscore_ops *ops;
+	int ret = 0;
+
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled before system core suspend.\n");
+
+	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
+		if (ops->suspend) {
+			if (initcall_debug)
+				pr_info("PM: Calling %pF\n", ops->suspend);
+			ret = ops->suspend();
+			if (ret)
+				goto err_out;
+			WARN_ONCE(!irqs_disabled(),
+				"Interrupts enabled after %pF\n", ops->suspend);
+		}
+
+	return 0;
+
+ err_out:
+	pr_err("PM: System core suspend callback %pF failed.\n", ops->suspend);
+
+	list_for_each_entry_continue(ops, &syscore_ops_list, node)
+		if (ops->resume)
+			ops->resume();
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(syscore_suspend);
+
+/**
+ * syscore_resume - Execute all the registered system core resume callbacks.
+ *
+ * This function is executed with one CPU on-line and disabled interrupts.
+ */
+void syscore_resume(void)
+{
+	struct syscore_ops *ops;
+
+	WARN_ONCE(!irqs_disabled(),
+		"Interrupts enabled before system core resume.\n");
+
+	list_for_each_entry(ops, &syscore_ops_list, node)
+		if (ops->resume) {
+			if (initcall_debug)
+				pr_info("PM: Calling %pF\n", ops->resume);
+			ops->resume();
+			WARN_ONCE(!irqs_disabled(),
+				"Interrupts enabled after %pF\n", ops->resume);
+		}
+}
+EXPORT_SYMBOL_GPL(syscore_resume);
+#endif /* CONFIG_PM_SLEEP */
+
+/**
+ * syscore_shutdown - Execute all the registered system core shutdown callbacks.
+ */
+void syscore_shutdown(void)
+{
+	struct syscore_ops *ops;
+
+	mutex_lock(&syscore_ops_lock);
+
+	list_for_each_entry_reverse(ops, &syscore_ops_list, node)
+		if (ops->shutdown) {
+			if (initcall_debug)
+				pr_info("PM: Calling %pF\n", ops->shutdown);
+			ops->shutdown();
+		}
+
+	mutex_unlock(&syscore_ops_lock);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/block/amiflop.c linux-libre-2.6.39-gnu/drivers/block/amiflop.c
--- linux-libre-2.6.38-gnu/drivers/block/amiflop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/amiflop.c	2011-05-19 00:06:34.000000000 -0400
@@ -1658,12 +1658,12 @@
 }
 
 /*
- * floppy-change is never called from an interrupt, so we can relax a bit
+ * check_events is never called from an interrupt, so we can relax a bit
  * here, sleep etc. Note that floppy-on tries to set current_DOR to point
  * to the desired drive, but it will probably not survive the sleep if
  * several floppies are used at the same time: thus the loop.
  */
-static int amiga_floppy_change(struct gendisk *disk)
+static unsigned amiga_check_events(struct gendisk *disk, unsigned int clearing)
 {
 	struct amiga_floppy_struct *p = disk->private_data;
 	int drive = p - unit;
@@ -1686,7 +1686,7 @@
 		p->dirty = 0;
 		writepending = 0; /* if this was true before, too bad! */
 		writefromint = 0;
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	}
 	return 0;
 }
@@ -1697,7 +1697,7 @@
 	.release	= floppy_release,
 	.ioctl		= fd_ioctl,
 	.getgeo		= fd_getgeo,
-	.media_changed	= amiga_floppy_change,
+	.check_events	= amiga_check_events,
 };
 
 static int __init fd_probe_drives(void)
@@ -1768,8 +1768,8 @@
 		return -EBUSY;
 
 	ret = -ENOMEM;
-	if ((raw_buf = (char *)amiga_chip_alloc (RAW_BUF_SIZE, "Floppy")) ==
-	    NULL) {
+	raw_buf = amiga_chip_alloc(RAW_BUF_SIZE, "Floppy");
+	if (!raw_buf) {
 		printk("fd: cannot get chip mem buffer\n");
 		goto out_blkdev;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/block/ataflop.c linux-libre-2.6.39-gnu/drivers/block/ataflop.c
--- linux-libre-2.6.38-gnu/drivers/block/ataflop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/ataflop.c	2011-05-19 00:06:34.000000000 -0400
@@ -1324,23 +1324,24 @@
  * due to unrecognised disk changes.
  */
 
-static int check_floppy_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	struct atari_floppy_struct *p = disk->private_data;
 	unsigned int drive = p - unit;
 	if (test_bit (drive, &fake_change)) {
 		/* simulated change (e.g. after formatting) */
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	}
 	if (test_bit (drive, &changed_floppies)) {
 		/* surely changed (the WP signal changed at least once) */
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	}
 	if (UD.wpstat) {
 		/* WP is on -> could be changed: to be sure, buffers should be
 		 * invalidated...
 		 */
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	}
 
 	return 0;
@@ -1570,7 +1571,7 @@
 		 * or the next access will revalidate - and clear UDT :-(
 		 */
 
-		if (check_floppy_change(disk))
+		if (floppy_check_events(disk, 0))
 		        floppy_revalidate(disk);
 
 		if (UD.flags & FTD_MSG)
@@ -1904,7 +1905,7 @@
 	.open		= floppy_unlocked_open,
 	.release	= floppy_release,
 	.ioctl		= fd_ioctl,
-	.media_changed	= check_floppy_change,
+	.check_events	= floppy_check_events,
 	.revalidate_disk= floppy_revalidate,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/cciss.c linux-libre-2.6.39-gnu/drivers/block/cciss.c
--- linux-libre-2.6.38-gnu/drivers/block/cciss.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/cciss.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,7 +193,7 @@
 	u64 *cfg_offset);
 static int __devinit cciss_pci_find_memory_BAR(struct pci_dev *pdev,
 	unsigned long *memory_bar);
-
+static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag);
 
 /* performant mode helper functions */
 static void  calc_bucket_map(int *bucket, int num_buckets, int nsgs,
@@ -231,7 +231,7 @@
  */
 static void set_performant_mode(ctlr_info_t *h, CommandList_struct *c)
 {
-	if (likely(h->transMethod == CFGTBL_Trans_Performant))
+	if (likely(h->transMethod & CFGTBL_Trans_Performant))
 		c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
 }
 
@@ -556,6 +556,44 @@
 #define to_hba(n) container_of(n, struct ctlr_info, dev)
 #define to_drv(n) container_of(n, drive_info_struct, dev)
 
+/* List of controllers which cannot be reset on kexec with reset_devices */
+static u32 unresettable_controller[] = {
+	0x324a103C, /* Smart Array P712m */
+	0x324b103C, /* SmartArray P711m */
+	0x3223103C, /* Smart Array P800 */
+	0x3234103C, /* Smart Array P400 */
+	0x3235103C, /* Smart Array P400i */
+	0x3211103C, /* Smart Array E200i */
+	0x3212103C, /* Smart Array E200 */
+	0x3213103C, /* Smart Array E200i */
+	0x3214103C, /* Smart Array E200i */
+	0x3215103C, /* Smart Array E200i */
+	0x3237103C, /* Smart Array E500 */
+	0x323D103C, /* Smart Array P700m */
+	0x409C0E11, /* Smart Array 6400 */
+	0x409D0E11, /* Smart Array 6400 EM */
+};
+
+static int ctlr_is_resettable(struct ctlr_info *h)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++)
+		if (unresettable_controller[i] == h->board_id)
+			return 0;
+	return 1;
+}
+
+static ssize_t host_show_resettable(struct device *dev,
+				    struct device_attribute *attr,
+				    char *buf)
+{
+	struct ctlr_info *h = to_hba(dev);
+
+	return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
+}
+static DEVICE_ATTR(resettable, S_IRUGO, host_show_resettable, NULL);
+
 static ssize_t host_store_rescan(struct device *dev,
 				 struct device_attribute *attr,
 				 const char *buf, size_t count)
@@ -741,6 +779,7 @@
 
 static struct attribute *cciss_host_attrs[] = {
 	&dev_attr_rescan.attr,
+	&dev_attr_resettable.attr,
 	NULL
 };
 
@@ -973,8 +1012,8 @@
 	temp64.val32.upper = c->ErrDesc.Addr.upper;
 	pci_free_consistent(h->pdev, sizeof(ErrorInfo_struct),
 			    c->err_info, (dma_addr_t) temp64.val);
-	pci_free_consistent(h->pdev, sizeof(CommandList_struct),
-			    c, (dma_addr_t) c->busaddr);
+	pci_free_consistent(h->pdev, sizeof(CommandList_struct), c,
+		(dma_addr_t) cciss_tag_discard_error_bits(h, (u32) c->busaddr));
 }
 
 static inline ctlr_info_t *get_host(struct gendisk *disk)
@@ -1490,8 +1529,7 @@
 		return -EINVAL;
 	if (!capable(CAP_SYS_RAWIO))
 		return -EPERM;
-	ioc = (BIG_IOCTL_Command_struct *)
-	    kmalloc(sizeof(*ioc), GFP_KERNEL);
+	ioc = kmalloc(sizeof(*ioc), GFP_KERNEL);
 	if (!ioc) {
 		status = -ENOMEM;
 		goto cleanup1;
@@ -2653,6 +2691,10 @@
 			c->Request.CDB[0]);
 		return_status = IO_NEEDS_RETRY;
 		break;
+	case CMD_UNABORTABLE:
+		dev_warn(&h->pdev->dev, "cmd unabortable\n");
+		return_status = IO_ERROR;
+		break;
 	default:
 		dev_warn(&h->pdev->dev, "cmd 0x%02x returned "
 		       "unknown status %x\n", c->Request.CDB[0],
@@ -3103,6 +3145,13 @@
 			(cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC) ?
 				DID_PASSTHROUGH : DID_ERROR);
 		break;
+	case CMD_UNABORTABLE:
+		dev_warn(&h->pdev->dev, "cmd %p unabortable\n", cmd);
+		rq->errors = make_status_bytes(SAM_STAT_GOOD,
+			cmd->err_info->CommandStatus, DRIVER_OK,
+			cmd->rq->cmd_type == REQ_TYPE_BLOCK_PC ?
+				DID_PASSTHROUGH : DID_ERROR);
+		break;
 	default:
 		dev_warn(&h->pdev->dev, "cmd %p returned "
 		       "unknown status %x\n", cmd,
@@ -3136,10 +3185,13 @@
 	return tag >> DIRECT_LOOKUP_SHIFT;
 }
 
-static inline u32 cciss_tag_discard_error_bits(u32 tag)
+static inline u32 cciss_tag_discard_error_bits(ctlr_info_t *h, u32 tag)
 {
-#define CCISS_ERROR_BITS 0x03
-	return tag & ~CCISS_ERROR_BITS;
+#define CCISS_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1)
+#define CCISS_SIMPLE_ERROR_BITS 0x03
+	if (likely(h->transMethod & CFGTBL_Trans_Performant))
+		return tag & ~CCISS_PERF_ERROR_BITS;
+	return tag & ~CCISS_SIMPLE_ERROR_BITS;
 }
 
 static inline void cciss_mark_tag_indexed(u32 *tag)
@@ -3170,12 +3222,6 @@
 	int sg_index = 0;
 	int chained = 0;
 
-	/* We call start_io here in case there is a command waiting on the
-	 * queue that has not been sent.
-	 */
-	if (blk_queue_plugged(q))
-		goto startio;
-
       queue:
 	creq = blk_peek_request(q);
 	if (!creq)
@@ -3365,7 +3411,7 @@
 {
 	u32 a;
 
-	if (unlikely(h->transMethod != CFGTBL_Trans_Performant))
+	if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
 		return h->access.command_completed(h);
 
 	if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
@@ -3400,14 +3446,12 @@
 /* process completion of a non-indexed command */
 static inline u32 process_nonindexed_cmd(ctlr_info_t *h, u32 raw_tag)
 {
-	u32 tag;
 	CommandList_struct *c = NULL;
 	__u32 busaddr_masked, tag_masked;
 
-	tag = cciss_tag_discard_error_bits(raw_tag);
+	tag_masked = cciss_tag_discard_error_bits(h, raw_tag);
 	list_for_each_entry(c, &h->cmpQ, list) {
-		busaddr_masked = cciss_tag_discard_error_bits(c->busaddr);
-		tag_masked = cciss_tag_discard_error_bits(tag);
+		busaddr_masked = cciss_tag_discard_error_bits(h, c->busaddr);
 		if (busaddr_masked == tag_masked) {
 			finish_cmd(h, c, raw_tag);
 			return next_command(h);
@@ -3759,7 +3803,8 @@
 	}
 }
 
-static __devinit void cciss_enter_performant_mode(ctlr_info_t *h)
+static __devinit void cciss_enter_performant_mode(ctlr_info_t *h,
+	u32 use_short_tags)
 {
 	/* This is a bit complicated.  There are 8 registers on
 	 * the controller which we write to to tell it 8 different
@@ -3814,7 +3859,7 @@
 	writel(0, &h->transtable->RepQCtrAddrHigh32);
 	writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32);
 	writel(0, &h->transtable->RepQAddr0High32);
-	writel(CFGTBL_Trans_Performant,
+	writel(CFGTBL_Trans_Performant | use_short_tags,
 			&(h->cfgtable->HostWrite.TransportRequest));
 
 	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
@@ -3861,7 +3906,8 @@
 	if ((h->reply_pool == NULL) || (h->blockFetchTable == NULL))
 		goto clean_up;
 
-	cciss_enter_performant_mode(h);
+	cciss_enter_performant_mode(h,
+		trans_support & CFGTBL_Trans_use_short_tags);
 
 	/* Change the access methods to the performant access methods */
 	h->access = SA5_performant_access;
diff -druN linux-libre-2.6.38-gnu/drivers/block/cciss_cmd.h linux-libre-2.6.39-gnu/drivers/block/cciss_cmd.h
--- linux-libre-2.6.38-gnu/drivers/block/cciss_cmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/cciss_cmd.h	2011-05-19 00:06:34.000000000 -0400
@@ -56,6 +56,7 @@
 
 #define CFGTBL_Trans_Simple     0x00000002l
 #define CFGTBL_Trans_Performant 0x00000004l
+#define CFGTBL_Trans_use_short_tags 0x20000000l
 
 #define CFGTBL_BusType_Ultra2   0x00000001l
 #define CFGTBL_BusType_Ultra3   0x00000002l
diff -druN linux-libre-2.6.38-gnu/drivers/block/cciss.h linux-libre-2.6.39-gnu/drivers/block/cciss.h
--- linux-libre-2.6.38-gnu/drivers/block/cciss.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/cciss.h	2011-05-19 00:06:34.000000000 -0400
@@ -222,6 +222,7 @@
 			h->ctlr, c->busaddr);
 #endif /* CCISS_DEBUG */
          writel(c->busaddr, h->vaddr + SA5_REQUEST_PORT_OFFSET);
+	readl(h->vaddr + SA5_REQUEST_PORT_OFFSET);
 	 h->commands_outstanding++;
 	 if ( h->commands_outstanding > h->max_outstanding)
 		h->max_outstanding = h->commands_outstanding;
diff -druN linux-libre-2.6.38-gnu/drivers/block/cciss_scsi.c linux-libre-2.6.39-gnu/drivers/block/cciss_scsi.c
--- linux-libre-2.6.38-gnu/drivers/block/cciss_scsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/cciss_scsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -824,13 +824,18 @@
 			break;
 			case CMD_UNSOLICITED_ABORT:
 				cmd->result = DID_ABORT << 16;
-				dev_warn(&h->pdev->dev, "%p aborted do to an "
+				dev_warn(&h->pdev->dev, "%p aborted due to an "
 					"unsolicited abort\n", c);
 			break;
 			case CMD_TIMEOUT:
 				cmd->result = DID_TIME_OUT << 16;
 				dev_warn(&h->pdev->dev, "%p timedout\n", c);
 			break;
+			case CMD_UNABORTABLE:
+				cmd->result = DID_ERROR << 16;
+				dev_warn(&h->pdev->dev, "c %p command "
+					"unabortable\n", c);
+			break;
 			default:
 				cmd->result = DID_ERROR << 16;
 				dev_warn(&h->pdev->dev,
@@ -1007,11 +1012,15 @@
 		break;
 		case CMD_UNSOLICITED_ABORT:
 			dev_warn(&h->pdev->dev,
-				"%p aborted do to an unsolicited abort\n", c);
+				"%p aborted due to an unsolicited abort\n", c);
 		break;
 		case CMD_TIMEOUT:
 			dev_warn(&h->pdev->dev, "%p timedout\n", c);
 		break;
+		case CMD_UNABORTABLE:
+			dev_warn(&h->pdev->dev,
+				"%p unabortable\n", c);
+		break;
 		default:
 			dev_warn(&h->pdev->dev,
 				"%p returned unknown status %x\n",
diff -druN linux-libre-2.6.38-gnu/drivers/block/cpqarray.c linux-libre-2.6.39-gnu/drivers/block/cpqarray.c
--- linux-libre-2.6.38-gnu/drivers/block/cpqarray.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/cpqarray.c	2011-05-19 00:06:34.000000000 -0400
@@ -911,9 +911,6 @@
 	struct scatterlist tmp_sg[SG_MAX];
 	int i, dir, seg;
 
-	if (blk_queue_plugged(q))
-		goto startio;
-
 queue_next:
 	creq = blk_peek_request(q);
 	if (!creq)
diff -druN linux-libre-2.6.38-gnu/drivers/block/DAC960.c linux-libre-2.6.39-gnu/drivers/block/DAC960.c
--- linux-libre-2.6.38-gnu/drivers/block/DAC960.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/DAC960.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,13 +140,14 @@
 	return 0;
 }
 
-static int DAC960_media_changed(struct gendisk *disk)
+static unsigned int DAC960_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	DAC960_Controller_T *p = disk->queue->queuedata;
 	int drive_nr = (long)disk->private_data;
 
 	if (!p->LogicalDriveInitiallyAccessible[drive_nr])
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	return 0;
 }
 
@@ -163,7 +164,7 @@
 	.owner			= THIS_MODULE,
 	.open			= DAC960_open,
 	.getgeo			= DAC960_getgeo,
-	.media_changed		= DAC960_media_changed,
+	.check_events		= DAC960_check_events,
 	.revalidate_disk	= DAC960_revalidate_disk,
 };
 
@@ -1789,7 +1790,7 @@
   unsigned short LogicalDeviceNumber = 0;
   int ModelNameLength;
 
-  /* Get data into dma-able area, then copy into permanant location */
+  /* Get data into dma-able area, then copy into permanent location */
   if (!DAC960_V2_NewControllerInfo(Controller))
     return DAC960_Failure(Controller, "GET CONTROLLER INFO");
   memcpy(ControllerInfo, Controller->V2.NewControllerInformation,
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_actlog.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_actlog.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_actlog.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_actlog.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 
 /* We maintain a trivial check sum in our on disk activity log.
  * With that we can ensure correct operation even when the storage
- * device might do a partial (last) sector write while loosing power.
+ * device might do a partial (last) sector write while losing power.
  */
 struct __packed al_transaction {
 	u32       magic;
@@ -80,7 +80,7 @@
 
 	if ((rw & WRITE) && !test_bit(MD_NO_FUA, &mdev->flags))
 		rw |= REQ_FUA;
-	rw |= REQ_UNPLUG | REQ_SYNC;
+	rw |= REQ_SYNC;
 
 	bio = bio_alloc(GFP_NOIO, 1);
 	bio->bi_bdev = bdev->md_bdev;
@@ -92,7 +92,7 @@
 	bio->bi_end_io = drbd_md_io_complete;
 	bio->bi_rw = rw;
 
-	if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
+	if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD))
 		bio_endio(bio, -EIO);
 	else
 		submit_bio(rw, bio);
@@ -176,13 +176,17 @@
 	struct lc_element *al_ext;
 	struct lc_element *tmp;
 	unsigned long     al_flags = 0;
+	int wake;
 
 	spin_lock_irq(&mdev->al_lock);
 	tmp = lc_find(mdev->resync, enr/AL_EXT_PER_BM_SECT);
 	if (unlikely(tmp != NULL)) {
 		struct bm_extent  *bm_ext = lc_entry(tmp, struct bm_extent, lce);
 		if (test_bit(BME_NO_WRITES, &bm_ext->flags)) {
+			wake = !test_and_set_bit(BME_PRIORITY, &bm_ext->flags);
 			spin_unlock_irq(&mdev->al_lock);
+			if (wake)
+				wake_up(&mdev->al_wait);
 			return NULL;
 		}
 	}
@@ -258,6 +262,33 @@
 	spin_unlock_irqrestore(&mdev->al_lock, flags);
 }
 
+#if (PAGE_SHIFT + 3) < (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT)
+/* Currently BM_BLOCK_SHIFT, BM_EXT_SHIFT and AL_EXTENT_SHIFT
+ * are still coupled, or assume too much about their relation.
+ * Code below will not work if this is violated.
+ * Will be cleaned up with some followup patch.
+ */
+# error FIXME
+#endif
+
+static unsigned int al_extent_to_bm_page(unsigned int al_enr)
+{
+	return al_enr >>
+		/* bit to page */
+		((PAGE_SHIFT + 3) -
+		/* al extent number to bit */
+		 (AL_EXTENT_SHIFT - BM_BLOCK_SHIFT));
+}
+
+static unsigned int rs_extent_to_bm_page(unsigned int rs_enr)
+{
+	return rs_enr >>
+		/* bit to page */
+		((PAGE_SHIFT + 3) -
+		/* al extent number to bit */
+		 (BM_EXT_SHIFT - BM_BLOCK_SHIFT));
+}
+
 int
 w_al_write_transaction(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 {
@@ -285,7 +316,7 @@
 	 * For now, we must not write the transaction,
 	 * if we cannot write out the bitmap of the evicted extent. */
 	if (mdev->state.conn < C_CONNECTED && evicted != LC_FREE)
-		drbd_bm_write_sect(mdev, evicted/AL_EXT_PER_BM_SECT);
+		drbd_bm_write_page(mdev, al_extent_to_bm_page(evicted));
 
 	/* The bitmap write may have failed, causing a state change. */
 	if (mdev->state.disk < D_INCONSISTENT) {
@@ -334,7 +365,7 @@
 		+ mdev->ldev->md.al_offset + mdev->al_tr_pos;
 
 	if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE))
-		drbd_chk_io_error(mdev, 1, TRUE);
+		drbd_chk_io_error(mdev, 1, true);
 
 	if (++mdev->al_tr_pos >
 	    div_ceil(mdev->act_log->nr_elements, AL_EXTENTS_PT))
@@ -511,227 +542,6 @@
 	return 1;
 }
 
-static void atodb_endio(struct bio *bio, int error)
-{
-	struct drbd_atodb_wait *wc = bio->bi_private;
-	struct drbd_conf *mdev = wc->mdev;
-	struct page *page;
-	int uptodate = bio_flagged(bio, BIO_UPTODATE);
-
-	/* strange behavior of some lower level drivers...
-	 * fail the request by clearing the uptodate flag,
-	 * but do not return any error?! */
-	if (!error && !uptodate)
-		error = -EIO;
-
-	drbd_chk_io_error(mdev, error, TRUE);
-	if (error && wc->error == 0)
-		wc->error = error;
-
-	if (atomic_dec_and_test(&wc->count))
-		complete(&wc->io_done);
-
-	page = bio->bi_io_vec[0].bv_page;
-	put_page(page);
-	bio_put(bio);
-	mdev->bm_writ_cnt++;
-	put_ldev(mdev);
-}
-
-/* sector to word */
-#define S2W(s)	((s)<<(BM_EXT_SHIFT-BM_BLOCK_SHIFT-LN2_BPL))
-
-/* activity log to on disk bitmap -- prepare bio unless that sector
- * is already covered by previously prepared bios */
-static int atodb_prepare_unless_covered(struct drbd_conf *mdev,
-					struct bio **bios,
-					unsigned int enr,
-					struct drbd_atodb_wait *wc) __must_hold(local)
-{
-	struct bio *bio;
-	struct page *page;
-	sector_t on_disk_sector;
-	unsigned int page_offset = PAGE_SIZE;
-	int offset;
-	int i = 0;
-	int err = -ENOMEM;
-
-	/* We always write aligned, full 4k blocks,
-	 * so we can ignore the logical_block_size (for now) */
-	enr &= ~7U;
-	on_disk_sector = enr + mdev->ldev->md.md_offset
-			     + mdev->ldev->md.bm_offset;
-
-	D_ASSERT(!(on_disk_sector & 7U));
-
-	/* Check if that enr is already covered by an already created bio.
-	 * Caution, bios[] is not NULL terminated,
-	 * but only initialized to all NULL.
-	 * For completely scattered activity log,
-	 * the last invocation iterates over all bios,
-	 * and finds the last NULL entry.
-	 */
-	while ((bio = bios[i])) {
-		if (bio->bi_sector == on_disk_sector)
-			return 0;
-		i++;
-	}
-	/* bios[i] == NULL, the next not yet used slot */
-
-	/* GFP_KERNEL, we are not in the write-out path */
-	bio = bio_alloc(GFP_KERNEL, 1);
-	if (bio == NULL)
-		return -ENOMEM;
-
-	if (i > 0) {
-		const struct bio_vec *prev_bv = bios[i-1]->bi_io_vec;
-		page_offset = prev_bv->bv_offset + prev_bv->bv_len;
-		page = prev_bv->bv_page;
-	}
-	if (page_offset == PAGE_SIZE) {
-		page = alloc_page(__GFP_HIGHMEM);
-		if (page == NULL)
-			goto out_bio_put;
-		page_offset = 0;
-	} else {
-		get_page(page);
-	}
-
-	offset = S2W(enr);
-	drbd_bm_get_lel(mdev, offset,
-			min_t(size_t, S2W(8), drbd_bm_words(mdev) - offset),
-			kmap(page) + page_offset);
-	kunmap(page);
-
-	bio->bi_private = wc;
-	bio->bi_end_io = atodb_endio;
-	bio->bi_bdev = mdev->ldev->md_bdev;
-	bio->bi_sector = on_disk_sector;
-
-	if (bio_add_page(bio, page, 4096, page_offset) != 4096)
-		goto out_put_page;
-
-	atomic_inc(&wc->count);
-	/* we already know that we may do this...
-	 * get_ldev_if_state(mdev,D_ATTACHING);
-	 * just get the extra reference, so that the local_cnt reflects
-	 * the number of pending IO requests DRBD at its backing device.
-	 */
-	atomic_inc(&mdev->local_cnt);
-
-	bios[i] = bio;
-
-	return 0;
-
-out_put_page:
-	err = -EINVAL;
-	put_page(page);
-out_bio_put:
-	bio_put(bio);
-	return err;
-}
-
-/**
- * drbd_al_to_on_disk_bm() -  * Writes bitmap parts covered by active AL extents
- * @mdev:	DRBD device.
- *
- * Called when we detach (unconfigure) local storage,
- * or when we go from R_PRIMARY to R_SECONDARY role.
- */
-void drbd_al_to_on_disk_bm(struct drbd_conf *mdev)
-{
-	int i, nr_elements;
-	unsigned int enr;
-	struct bio **bios;
-	struct drbd_atodb_wait wc;
-
-	ERR_IF (!get_ldev_if_state(mdev, D_ATTACHING))
-		return; /* sorry, I don't have any act_log etc... */
-
-	wait_event(mdev->al_wait, lc_try_lock(mdev->act_log));
-
-	nr_elements = mdev->act_log->nr_elements;
-
-	/* GFP_KERNEL, we are not in anyone's write-out path */
-	bios = kzalloc(sizeof(struct bio *) * nr_elements, GFP_KERNEL);
-	if (!bios)
-		goto submit_one_by_one;
-
-	atomic_set(&wc.count, 0);
-	init_completion(&wc.io_done);
-	wc.mdev = mdev;
-	wc.error = 0;
-
-	for (i = 0; i < nr_elements; i++) {
-		enr = lc_element_by_index(mdev->act_log, i)->lc_number;
-		if (enr == LC_FREE)
-			continue;
-		/* next statement also does atomic_inc wc.count and local_cnt */
-		if (atodb_prepare_unless_covered(mdev, bios,
-						enr/AL_EXT_PER_BM_SECT,
-						&wc))
-			goto free_bios_submit_one_by_one;
-	}
-
-	/* unnecessary optimization? */
-	lc_unlock(mdev->act_log);
-	wake_up(&mdev->al_wait);
-
-	/* all prepared, submit them */
-	for (i = 0; i < nr_elements; i++) {
-		if (bios[i] == NULL)
-			break;
-		if (FAULT_ACTIVE(mdev, DRBD_FAULT_MD_WR)) {
-			bios[i]->bi_rw = WRITE;
-			bio_endio(bios[i], -EIO);
-		} else {
-			submit_bio(WRITE, bios[i]);
-		}
-	}
-
-	drbd_blk_run_queue(bdev_get_queue(mdev->ldev->md_bdev));
-
-	/* always (try to) flush bitmap to stable storage */
-	drbd_md_flush(mdev);
-
-	/* In case we did not submit a single IO do not wait for
-	 * them to complete. ( Because we would wait forever here. )
-	 *
-	 * In case we had IOs and they are already complete, there
-	 * is not point in waiting anyways.
-	 * Therefore this if () ... */
-	if (atomic_read(&wc.count))
-		wait_for_completion(&wc.io_done);
-
-	put_ldev(mdev);
-
-	kfree(bios);
-	return;
-
- free_bios_submit_one_by_one:
-	/* free everything by calling the endio callback directly. */
-	for (i = 0; i < nr_elements && bios[i]; i++)
-		bio_endio(bios[i], 0);
-
-	kfree(bios);
-
- submit_one_by_one:
-	dev_warn(DEV, "Using the slow drbd_al_to_on_disk_bm()\n");
-
-	for (i = 0; i < mdev->act_log->nr_elements; i++) {
-		enr = lc_element_by_index(mdev->act_log, i)->lc_number;
-		if (enr == LC_FREE)
-			continue;
-		/* Really slow: if we have al-extents 16..19 active,
-		 * sector 4 will be written four times! Synchronous! */
-		drbd_bm_write_sect(mdev, enr/AL_EXT_PER_BM_SECT);
-	}
-
-	lc_unlock(mdev->act_log);
-	wake_up(&mdev->al_wait);
-	put_ldev(mdev);
-}
-
 /**
  * drbd_al_apply_to_bm() - Sets the bitmap to diry(1) where covered ba active AL extents
  * @mdev:	DRBD device.
@@ -811,7 +621,7 @@
 		return 1;
 	}
 
-	drbd_bm_write_sect(mdev, udw->enr);
+	drbd_bm_write_page(mdev, rs_extent_to_bm_page(udw->enr));
 	put_ldev(mdev);
 
 	kfree(udw);
@@ -891,7 +701,6 @@
 				dev_warn(DEV, "Kicking resync_lru element enr=%u "
 				     "out with rs_failed=%d\n",
 				     ext->lce.lc_number, ext->rs_failed);
-				set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags);
 			}
 			ext->rs_left = rs_left;
 			ext->rs_failed = success ? 0 : count;
@@ -910,7 +719,6 @@
 				drbd_queue_work_front(&mdev->data.work, &udw->w);
 			} else {
 				dev_warn(DEV, "Could not kmalloc an udw\n");
-				set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags);
 			}
 		}
 	} else {
@@ -921,6 +729,22 @@
 	}
 }
 
+void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go)
+{
+	unsigned long now = jiffies;
+	unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
+	int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
+	if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
+		if (mdev->rs_mark_left[mdev->rs_last_mark] != still_to_go &&
+		    mdev->state.conn != C_PAUSED_SYNC_T &&
+		    mdev->state.conn != C_PAUSED_SYNC_S) {
+			mdev->rs_mark_time[next] = now;
+			mdev->rs_mark_left[next] = still_to_go;
+			mdev->rs_last_mark = next;
+		}
+	}
+}
+
 /* clear the bit corresponding to the piece of storage in question:
  * size byte of data starting from sector.  Only clear a bits of the affected
  * one ore more _aligned_ BM_BLOCK_SIZE blocks.
@@ -938,7 +762,7 @@
 	int wake_up = 0;
 	unsigned long flags;
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "drbd_set_in_sync: sector=%llus size=%d nonsense!\n",
 				(unsigned long long)sector, size);
 		return;
@@ -971,21 +795,9 @@
 	 */
 	count = drbd_bm_clear_bits(mdev, sbnr, ebnr);
 	if (count && get_ldev(mdev)) {
-		unsigned long now = jiffies;
-		unsigned long last = mdev->rs_mark_time[mdev->rs_last_mark];
-		int next = (mdev->rs_last_mark + 1) % DRBD_SYNC_MARKS;
-		if (time_after_eq(now, last + DRBD_SYNC_MARK_STEP)) {
-			unsigned long tw = drbd_bm_total_weight(mdev);
-			if (mdev->rs_mark_left[mdev->rs_last_mark] != tw &&
-			    mdev->state.conn != C_PAUSED_SYNC_T &&
-			    mdev->state.conn != C_PAUSED_SYNC_S) {
-				mdev->rs_mark_time[next] = now;
-				mdev->rs_mark_left[next] = tw;
-				mdev->rs_last_mark = next;
-			}
-		}
+		drbd_advance_rs_marks(mdev, drbd_bm_total_weight(mdev));
 		spin_lock_irqsave(&mdev->al_lock, flags);
-		drbd_try_clear_on_disk_bm(mdev, sector, count, TRUE);
+		drbd_try_clear_on_disk_bm(mdev, sector, count, true);
 		spin_unlock_irqrestore(&mdev->al_lock, flags);
 
 		/* just wake_up unconditional now, various lc_chaged(),
@@ -1000,27 +812,27 @@
 /*
  * this is intended to set one request worth of data out of sync.
  * affects at least 1 bit,
- * and at most 1+DRBD_MAX_SEGMENT_SIZE/BM_BLOCK_SIZE bits.
+ * and at most 1+DRBD_MAX_BIO_SIZE/BM_BLOCK_SIZE bits.
  *
  * called by tl_clear and drbd_send_dblock (==drbd_make_request).
  * so this can be _any_ process.
  */
-void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
+int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector, int size,
 			    const char *file, const unsigned int line)
 {
 	unsigned long sbnr, ebnr, lbnr, flags;
 	sector_t esector, nr_sectors;
-	unsigned int enr, count;
+	unsigned int enr, count = 0;
 	struct lc_element *e;
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "sector: %llus, size: %d\n",
 			(unsigned long long)sector, size);
-		return;
+		return 0;
 	}
 
 	if (!get_ldev(mdev))
-		return; /* no disk, no metadata, no bitmap to set bits in */
+		return 0; /* no disk, no metadata, no bitmap to set bits in */
 
 	nr_sectors = drbd_get_capacity(mdev->this_bdev);
 	esector = sector + (size >> 9) - 1;
@@ -1050,6 +862,8 @@
 
 out:
 	put_ldev(mdev);
+
+	return count;
 }
 
 static
@@ -1130,7 +944,10 @@
 	unsigned int enr = BM_SECT_TO_EXT(sector);
 	struct bm_extent *bm_ext;
 	int i, sig;
+	int sa = 200; /* Step aside 200 times, then grab the extent and let app-IO wait.
+			 200 times -> 20 seconds. */
 
+retry:
 	sig = wait_event_interruptible(mdev->al_wait,
 			(bm_ext = _bme_get(mdev, enr)));
 	if (sig)
@@ -1141,16 +958,25 @@
 
 	for (i = 0; i < AL_EXT_PER_BM_SECT; i++) {
 		sig = wait_event_interruptible(mdev->al_wait,
-				!_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i));
-		if (sig) {
+					       !_is_in_al(mdev, enr * AL_EXT_PER_BM_SECT + i) ||
+					       test_bit(BME_PRIORITY, &bm_ext->flags));
+
+		if (sig || (test_bit(BME_PRIORITY, &bm_ext->flags) && sa)) {
 			spin_lock_irq(&mdev->al_lock);
 			if (lc_put(mdev->resync, &bm_ext->lce) == 0) {
-				clear_bit(BME_NO_WRITES, &bm_ext->flags);
+				bm_ext->flags = 0; /* clears BME_NO_WRITES and eventually BME_PRIORITY */
 				mdev->resync_locked--;
 				wake_up(&mdev->al_wait);
 			}
 			spin_unlock_irq(&mdev->al_lock);
-			return -EINTR;
+			if (sig)
+				return -EINTR;
+			if (schedule_timeout_interruptible(HZ/10))
+				return -EINTR;
+			if (sa && --sa == 0)
+				dev_warn(DEV,"drbd_rs_begin_io() stepped aside for 20sec."
+					 "Resync stalled?\n");
+			goto retry;
 		}
 	}
 	set_bit(BME_LOCKED, &bm_ext->flags);
@@ -1293,8 +1119,7 @@
 	}
 
 	if (lc_put(mdev->resync, &bm_ext->lce) == 0) {
-		clear_bit(BME_LOCKED, &bm_ext->flags);
-		clear_bit(BME_NO_WRITES, &bm_ext->flags);
+		bm_ext->flags = 0; /* clear BME_LOCKED, BME_NO_WRITES and BME_PRIORITY */
 		mdev->resync_locked--;
 		wake_up(&mdev->al_wait);
 	}
@@ -1385,7 +1210,7 @@
 	sector_t esector, nr_sectors;
 	int wake_up = 0;
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "drbd_rs_failed_io: sector=%llus size=%d nonsense!\n",
 				(unsigned long long)sector, size);
 		return;
@@ -1422,7 +1247,7 @@
 		mdev->rs_failed += count;
 
 		if (get_ldev(mdev)) {
-			drbd_try_clear_on_disk_bm(mdev, sector, count, FALSE);
+			drbd_try_clear_on_disk_bm(mdev, sector, count, false);
 			put_ldev(mdev);
 		}
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_bitmap.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_bitmap.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_bitmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_bitmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,18 +28,56 @@
 #include <linux/drbd.h>
 #include <linux/slab.h>
 #include <asm/kmap_types.h>
+
 #include "drbd_int.h"
 
+
 /* OPAQUE outside this file!
  * interface defined in drbd_int.h
 
  * convention:
  * function name drbd_bm_... => used elsewhere, "public".
  * function name      bm_... => internal to implementation, "private".
+ */
 
- * Note that since find_first_bit returns int, at the current granularity of
- * the bitmap (4KB per byte), this implementation "only" supports up to
- * 1<<(32+12) == 16 TB...
+
+/*
+ * LIMITATIONS:
+ * We want to support >= peta byte of backend storage, while for now still using
+ * a granularity of one bit per 4KiB of storage.
+ * 1 << 50		bytes backend storage (1 PiB)
+ * 1 << (50 - 12)	bits needed
+ *	38 --> we need u64 to index and count bits
+ * 1 << (38 - 3)	bitmap bytes needed
+ *	35 --> we still need u64 to index and count bytes
+ *			(that's 32 GiB of bitmap for 1 PiB storage)
+ * 1 << (35 - 2)	32bit longs needed
+ *	33 --> we'd even need u64 to index and count 32bit long words.
+ * 1 << (35 - 3)	64bit longs needed
+ *	32 --> we could get away with a 32bit unsigned int to index and count
+ *	64bit long words, but I rather stay with unsigned long for now.
+ *	We probably should neither count nor point to bytes or long words
+ *	directly, but either by bitnumber, or by page index and offset.
+ * 1 << (35 - 12)
+ *	22 --> we need that much 4KiB pages of bitmap.
+ *	1 << (22 + 3) --> on a 64bit arch,
+ *	we need 32 MiB to store the array of page pointers.
+ *
+ * Because I'm lazy, and because the resulting patch was too large, too ugly
+ * and still incomplete, on 32bit we still "only" support 16 TiB (minus some),
+ * (1 << 32) bits * 4k storage.
+ *
+
+ * bitmap storage and IO:
+ *	Bitmap is stored little endian on disk, and is kept little endian in
+ *	core memory. Currently we still hold the full bitmap in core as long
+ *	as we are "attached" to a local disk, which at 32 GiB for 1PiB storage
+ *	seems excessive.
+ *
+ *	We plan to reduce the amount of in-core bitmap pages by pageing them in
+ *	and out against their on-disk location as necessary, but need to make
+ *	sure we don't cause too much meta data IO, and must not deadlock in
+ *	tight memory situations. This needs some more work.
  */
 
 /*
@@ -55,13 +93,9 @@
 struct drbd_bitmap {
 	struct page **bm_pages;
 	spinlock_t bm_lock;
-	/* WARNING unsigned long bm_*:
-	 * 32bit number of bit offset is just enough for 512 MB bitmap.
-	 * it will blow up if we make the bitmap bigger...
-	 * not that it makes much sense to have a bitmap that large,
-	 * rather change the granularity to 16k or 64k or something.
-	 * (that implies other problems, however...)
-	 */
+
+	/* see LIMITATIONS: above */
+
 	unsigned long bm_set;       /* nr of set bits; THINK maybe atomic_t? */
 	unsigned long bm_bits;
 	size_t   bm_words;
@@ -69,29 +103,18 @@
 	sector_t bm_dev_capacity;
 	struct mutex bm_change; /* serializes resize operations */
 
-	atomic_t bm_async_io;
-	wait_queue_head_t bm_io_wait;
+	wait_queue_head_t bm_io_wait; /* used to serialize IO of single pages */
 
-	unsigned long  bm_flags;
+	enum bm_flag bm_flags;
 
 	/* debugging aid, in case we are still racy somewhere */
 	char          *bm_why;
 	struct task_struct *bm_task;
 };
 
-/* definition of bits in bm_flags */
-#define BM_LOCKED       0
-#define BM_MD_IO_ERROR  1
-#define BM_P_VMALLOCED  2
-
 static int __bm_change_bits_to(struct drbd_conf *mdev, const unsigned long s,
 			       unsigned long e, int val, const enum km_type km);
 
-static int bm_is_locked(struct drbd_bitmap *b)
-{
-	return test_bit(BM_LOCKED, &b->bm_flags);
-}
-
 #define bm_print_lock_info(m) __bm_print_lock_info(m, __func__)
 static void __bm_print_lock_info(struct drbd_conf *mdev, const char *func)
 {
@@ -108,7 +131,7 @@
 	    b->bm_task == mdev->worker.task   ? "worker"   : "?");
 }
 
-void drbd_bm_lock(struct drbd_conf *mdev, char *why)
+void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	int trylock_failed;
@@ -131,8 +154,9 @@
 		    b->bm_task == mdev->worker.task   ? "worker"   : "?");
 		mutex_lock(&b->bm_change);
 	}
-	if (__test_and_set_bit(BM_LOCKED, &b->bm_flags))
+	if (BM_LOCKED_MASK & b->bm_flags)
 		dev_err(DEV, "FIXME bitmap already locked in bm_lock\n");
+	b->bm_flags |= flags & BM_LOCKED_MASK;
 
 	b->bm_why  = why;
 	b->bm_task = current;
@@ -146,31 +170,137 @@
 		return;
 	}
 
-	if (!__test_and_clear_bit(BM_LOCKED, &mdev->bitmap->bm_flags))
+	if (!(BM_LOCKED_MASK & mdev->bitmap->bm_flags))
 		dev_err(DEV, "FIXME bitmap not locked in bm_unlock\n");
 
+	b->bm_flags &= ~BM_LOCKED_MASK;
 	b->bm_why  = NULL;
 	b->bm_task = NULL;
 	mutex_unlock(&b->bm_change);
 }
 
-/* word offset to long pointer */
-static unsigned long *__bm_map_paddr(struct drbd_bitmap *b, unsigned long offset, const enum km_type km)
+/* we store some "meta" info about our pages in page->private */
+/* at a granularity of 4k storage per bitmap bit:
+ * one peta byte storage: 1<<50 byte, 1<<38 * 4k storage blocks
+ *  1<<38 bits,
+ *  1<<23 4k bitmap pages.
+ * Use 24 bits as page index, covers 2 peta byte storage
+ * at a granularity of 4k per bit.
+ * Used to report the failed page idx on io error from the endio handlers.
+ */
+#define BM_PAGE_IDX_MASK	((1UL<<24)-1)
+/* this page is currently read in, or written back */
+#define BM_PAGE_IO_LOCK		31
+/* if there has been an IO error for this page */
+#define BM_PAGE_IO_ERROR	30
+/* this is to be able to intelligently skip disk IO,
+ * set if bits have been set since last IO. */
+#define BM_PAGE_NEED_WRITEOUT	29
+/* to mark for lazy writeout once syncer cleared all clearable bits,
+ * we if bits have been cleared since last IO. */
+#define BM_PAGE_LAZY_WRITEOUT	28
+
+/* store_page_idx uses non-atomic assingment. It is only used directly after
+ * allocating the page.  All other bm_set_page_* and bm_clear_page_* need to
+ * use atomic bit manipulation, as set_out_of_sync (and therefore bitmap
+ * changes) may happen from various contexts, and wait_on_bit/wake_up_bit
+ * requires it all to be atomic as well. */
+static void bm_store_page_idx(struct page *page, unsigned long idx)
 {
-	struct page *page;
-	unsigned long page_nr;
+	BUG_ON(0 != (idx & ~BM_PAGE_IDX_MASK));
+	page_private(page) |= idx;
+}
+
+static unsigned long bm_page_to_idx(struct page *page)
+{
+	return page_private(page) & BM_PAGE_IDX_MASK;
+}
 
+/* As is very unlikely that the same page is under IO from more than one
+ * context, we can get away with a bit per page and one wait queue per bitmap.
+ */
+static void bm_page_lock_io(struct drbd_conf *mdev, int page_nr)
+{
+	struct drbd_bitmap *b = mdev->bitmap;
+	void *addr = &page_private(b->bm_pages[page_nr]);
+	wait_event(b->bm_io_wait, !test_and_set_bit(BM_PAGE_IO_LOCK, addr));
+}
+
+static void bm_page_unlock_io(struct drbd_conf *mdev, int page_nr)
+{
+	struct drbd_bitmap *b = mdev->bitmap;
+	void *addr = &page_private(b->bm_pages[page_nr]);
+	clear_bit(BM_PAGE_IO_LOCK, addr);
+	smp_mb__after_clear_bit();
+	wake_up(&mdev->bitmap->bm_io_wait);
+}
+
+/* set _before_ submit_io, so it may be reset due to being changed
+ * while this page is in flight... will get submitted later again */
+static void bm_set_page_unchanged(struct page *page)
+{
+	/* use cmpxchg? */
+	clear_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
+	clear_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page));
+}
+
+static void bm_set_page_need_writeout(struct page *page)
+{
+	set_bit(BM_PAGE_NEED_WRITEOUT, &page_private(page));
+}
+
+static int bm_test_page_unchanged(struct page *page)
+{
+	volatile const unsigned long *addr = &page_private(page);
+	return (*addr & ((1UL<<BM_PAGE_NEED_WRITEOUT)|(1UL<<BM_PAGE_LAZY_WRITEOUT))) == 0;
+}
+
+static void bm_set_page_io_err(struct page *page)
+{
+	set_bit(BM_PAGE_IO_ERROR, &page_private(page));
+}
+
+static void bm_clear_page_io_err(struct page *page)
+{
+	clear_bit(BM_PAGE_IO_ERROR, &page_private(page));
+}
+
+static void bm_set_page_lazy_writeout(struct page *page)
+{
+	set_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page));
+}
+
+static int bm_test_page_lazy_writeout(struct page *page)
+{
+	return test_bit(BM_PAGE_LAZY_WRITEOUT, &page_private(page));
+}
+
+/* on a 32bit box, this would allow for exactly (2<<38) bits. */
+static unsigned int bm_word_to_page_idx(struct drbd_bitmap *b, unsigned long long_nr)
+{
 	/* page_nr = (word*sizeof(long)) >> PAGE_SHIFT; */
-	page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3);
+	unsigned int page_nr = long_nr >> (PAGE_SHIFT - LN2_BPL + 3);
 	BUG_ON(page_nr >= b->bm_number_of_pages);
-	page = b->bm_pages[page_nr];
+	return page_nr;
+}
 
+static unsigned int bm_bit_to_page_idx(struct drbd_bitmap *b, u64 bitnr)
+{
+	/* page_nr = (bitnr/8) >> PAGE_SHIFT; */
+	unsigned int page_nr = bitnr >> (PAGE_SHIFT + 3);
+	BUG_ON(page_nr >= b->bm_number_of_pages);
+	return page_nr;
+}
+
+static unsigned long *__bm_map_pidx(struct drbd_bitmap *b, unsigned int idx, const enum km_type km)
+{
+	struct page *page = b->bm_pages[idx];
 	return (unsigned long *) kmap_atomic(page, km);
 }
 
-static unsigned long * bm_map_paddr(struct drbd_bitmap *b, unsigned long offset)
+static unsigned long *bm_map_pidx(struct drbd_bitmap *b, unsigned int idx)
 {
-	return __bm_map_paddr(b, offset, KM_IRQ1);
+	return __bm_map_pidx(b, idx, KM_IRQ1);
 }
 
 static void __bm_unmap(unsigned long *p_addr, const enum km_type km)
@@ -202,6 +332,7 @@
  * to be able to report device specific.
  */
 
+
 static void bm_free_pages(struct page **pages, unsigned long number)
 {
 	unsigned long i;
@@ -269,6 +400,9 @@
 				bm_vk_free(new_pages, vmalloced);
 				return NULL;
 			}
+			/* we want to know which page it is
+			 * from the endio handlers */
+			bm_store_page_idx(page, i);
 			new_pages[i] = page;
 		}
 	} else {
@@ -280,9 +414,9 @@
 	}
 
 	if (vmalloced)
-		set_bit(BM_P_VMALLOCED, &b->bm_flags);
+		b->bm_flags |= BM_P_VMALLOCED;
 	else
-		clear_bit(BM_P_VMALLOCED, &b->bm_flags);
+		b->bm_flags &= ~BM_P_VMALLOCED;
 
 	return new_pages;
 }
@@ -319,7 +453,7 @@
 {
 	ERR_IF (!mdev->bitmap) return;
 	bm_free_pages(mdev->bitmap->bm_pages, mdev->bitmap->bm_number_of_pages);
-	bm_vk_free(mdev->bitmap->bm_pages, test_bit(BM_P_VMALLOCED, &mdev->bitmap->bm_flags));
+	bm_vk_free(mdev->bitmap->bm_pages, (BM_P_VMALLOCED & mdev->bitmap->bm_flags));
 	kfree(mdev->bitmap);
 	mdev->bitmap = NULL;
 }
@@ -329,22 +463,39 @@
  * this masks out the remaining bits.
  * Returns the number of bits cleared.
  */
+#define BITS_PER_PAGE		(1UL << (PAGE_SHIFT + 3))
+#define BITS_PER_PAGE_MASK	(BITS_PER_PAGE - 1)
+#define BITS_PER_LONG_MASK	(BITS_PER_LONG - 1)
 static int bm_clear_surplus(struct drbd_bitmap *b)
 {
-	const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) - 1;
-	size_t w = b->bm_bits >> LN2_BPL;
-	int cleared = 0;
+	unsigned long mask;
 	unsigned long *p_addr, *bm;
+	int tmp;
+	int cleared = 0;
 
-	p_addr = bm_map_paddr(b, w);
-	bm = p_addr + MLPP(w);
-	if (w < b->bm_words) {
+	/* number of bits modulo bits per page */
+	tmp = (b->bm_bits & BITS_PER_PAGE_MASK);
+	/* mask the used bits of the word containing the last bit */
+	mask = (1UL << (tmp & BITS_PER_LONG_MASK)) -1;
+	/* bitmap is always stored little endian,
+	 * on disk and in core memory alike */
+	mask = cpu_to_lel(mask);
+
+	p_addr = bm_map_pidx(b, b->bm_number_of_pages - 1);
+	bm = p_addr + (tmp/BITS_PER_LONG);
+	if (mask) {
+		/* If mask != 0, we are not exactly aligned, so bm now points
+		 * to the long containing the last bit.
+		 * If mask == 0, bm already points to the word immediately
+		 * after the last (long word aligned) bit. */
 		cleared = hweight_long(*bm & ~mask);
 		*bm &= mask;
-		w++; bm++;
+		bm++;
 	}
 
-	if (w < b->bm_words) {
+	if (BITS_PER_LONG == 32 && ((bm - p_addr) & 1) == 1) {
+		/* on a 32bit arch, we may need to zero out
+		 * a padding long to align with a 64bit remote */
 		cleared += hweight_long(*bm);
 		*bm = 0;
 	}
@@ -354,66 +505,75 @@
 
 static void bm_set_surplus(struct drbd_bitmap *b)
 {
-	const unsigned long mask = (1UL << (b->bm_bits & (BITS_PER_LONG-1))) - 1;
-	size_t w = b->bm_bits >> LN2_BPL;
+	unsigned long mask;
 	unsigned long *p_addr, *bm;
+	int tmp;
 
-	p_addr = bm_map_paddr(b, w);
-	bm = p_addr + MLPP(w);
-	if (w < b->bm_words) {
+	/* number of bits modulo bits per page */
+	tmp = (b->bm_bits & BITS_PER_PAGE_MASK);
+	/* mask the used bits of the word containing the last bit */
+	mask = (1UL << (tmp & BITS_PER_LONG_MASK)) -1;
+	/* bitmap is always stored little endian,
+	 * on disk and in core memory alike */
+	mask = cpu_to_lel(mask);
+
+	p_addr = bm_map_pidx(b, b->bm_number_of_pages - 1);
+	bm = p_addr + (tmp/BITS_PER_LONG);
+	if (mask) {
+		/* If mask != 0, we are not exactly aligned, so bm now points
+		 * to the long containing the last bit.
+		 * If mask == 0, bm already points to the word immediately
+		 * after the last (long word aligned) bit. */
 		*bm |= ~mask;
-		bm++; w++;
+		bm++;
 	}
 
-	if (w < b->bm_words) {
-		*bm = ~(0UL);
+	if (BITS_PER_LONG == 32 && ((bm - p_addr) & 1) == 1) {
+		/* on a 32bit arch, we may need to zero out
+		 * a padding long to align with a 64bit remote */
+		*bm = ~0UL;
 	}
 	bm_unmap(p_addr);
 }
 
-static unsigned long __bm_count_bits(struct drbd_bitmap *b, const int swap_endian)
+/* you better not modify the bitmap while this is running,
+ * or its results will be stale */
+static unsigned long bm_count_bits(struct drbd_bitmap *b)
 {
-	unsigned long *p_addr, *bm, offset = 0;
+	unsigned long *p_addr;
 	unsigned long bits = 0;
-	unsigned long i, do_now;
+	unsigned long mask = (1UL << (b->bm_bits & BITS_PER_LONG_MASK)) -1;
+	int idx, i, last_word;
 
-	while (offset < b->bm_words) {
-		i = do_now = min_t(size_t, b->bm_words-offset, LWPP);
-		p_addr = __bm_map_paddr(b, offset, KM_USER0);
-		bm = p_addr + MLPP(offset);
-		while (i--) {
-#ifndef __LITTLE_ENDIAN
-			if (swap_endian)
-				*bm = lel_to_cpu(*bm);
-#endif
-			bits += hweight_long(*bm++);
-		}
+	/* all but last page */
+	for (idx = 0; idx < b->bm_number_of_pages - 1; idx++) {
+		p_addr = __bm_map_pidx(b, idx, KM_USER0);
+		for (i = 0; i < LWPP; i++)
+			bits += hweight_long(p_addr[i]);
 		__bm_unmap(p_addr, KM_USER0);
-		offset += do_now;
 		cond_resched();
 	}
-
+	/* last (or only) page */
+	last_word = ((b->bm_bits - 1) & BITS_PER_PAGE_MASK) >> LN2_BPL;
+	p_addr = __bm_map_pidx(b, idx, KM_USER0);
+	for (i = 0; i < last_word; i++)
+		bits += hweight_long(p_addr[i]);
+	p_addr[last_word] &= cpu_to_lel(mask);
+	bits += hweight_long(p_addr[last_word]);
+	/* 32bit arch, may have an unused padding long */
+	if (BITS_PER_LONG == 32 && (last_word & 1) == 0)
+		p_addr[last_word+1] = 0;
+	__bm_unmap(p_addr, KM_USER0);
 	return bits;
 }
 
-static unsigned long bm_count_bits(struct drbd_bitmap *b)
-{
-	return __bm_count_bits(b, 0);
-}
-
-static unsigned long bm_count_bits_swap_endian(struct drbd_bitmap *b)
-{
-	return __bm_count_bits(b, 1);
-}
-
 /* offset and len in long words.*/
 static void bm_memset(struct drbd_bitmap *b, size_t offset, int c, size_t len)
 {
 	unsigned long *p_addr, *bm;
+	unsigned int idx;
 	size_t do_now, end;
 
-#define BM_SECTORS_PER_BIT (BM_BLOCK_SIZE/512)
-
 	end = offset + len;
 
 	if (end > b->bm_words) {
@@ -423,15 +583,16 @@
 
 	while (offset < end) {
 		do_now = min_t(size_t, ALIGN(offset + 1, LWPP), end) - offset;
-		p_addr = bm_map_paddr(b, offset);
+		idx = bm_word_to_page_idx(b, offset);
+		p_addr = bm_map_pidx(b, idx);
 		bm = p_addr + MLPP(offset);
 		if (bm+do_now > p_addr + LWPP) {
 			printk(KERN_ALERT "drbd: BUG BUG BUG! p_addr:%p bm:%p do_now:%d\n",
 			       p_addr, bm, (int)do_now);
-			break; /* breaks to after catch_oob_access_end() only! */
-		}
-		memset(bm, c, do_now * sizeof(long));
+		} else
+			memset(bm, c, do_now * sizeof(long));
 		bm_unmap(p_addr);
+		bm_set_page_need_writeout(b->bm_pages[idx]);
 		offset += do_now;
 	}
 }
@@ -447,7 +608,7 @@
 int drbd_bm_resize(struct drbd_conf *mdev, sector_t capacity, int set_new_bits)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	unsigned long bits, words, owords, obits, *p_addr, *bm;
+	unsigned long bits, words, owords, obits;
 	unsigned long want, have, onpages; /* number of pages */
 	struct page **npages, **opages = NULL;
 	int err = 0, growing;
@@ -455,7 +616,7 @@
 
 	ERR_IF(!b) return -ENOMEM;
 
-	drbd_bm_lock(mdev, "resize");
+	drbd_bm_lock(mdev, "resize", BM_LOCKED_MASK);
 
 	dev_info(DEV, "drbd_bm_resize called with capacity == %llu\n",
 			(unsigned long long)capacity);
@@ -463,7 +624,7 @@
 	if (capacity == b->bm_dev_capacity)
 		goto out;
 
-	opages_vmalloced = test_bit(BM_P_VMALLOCED, &b->bm_flags);
+	opages_vmalloced = (BM_P_VMALLOCED & b->bm_flags);
 
 	if (capacity == 0) {
 		spin_lock_irq(&b->bm_lock);
@@ -491,18 +652,23 @@
 	words = ALIGN(bits, 64) >> LN2_BPL;
 
 	if (get_ldev(mdev)) {
-		D_ASSERT((u64)bits <= (((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12));
+		u64 bits_on_disk = ((u64)mdev->ldev->md.md_size_sect-MD_BM_OFFSET) << 12;
 		put_ldev(mdev);
+		if (bits > bits_on_disk) {
+			dev_info(DEV, "bits = %lu\n", bits);
+			dev_info(DEV, "bits_on_disk = %llu\n", bits_on_disk);
+			err = -ENOSPC;
+			goto out;
+		}
 	}
 
-	/* one extra long to catch off by one errors */
-	want = ALIGN((words+1)*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT;
+	want = ALIGN(words*sizeof(long), PAGE_SIZE) >> PAGE_SHIFT;
 	have = b->bm_number_of_pages;
 	if (want == have) {
 		D_ASSERT(b->bm_pages != NULL);
 		npages = b->bm_pages;
 	} else {
-		if (FAULT_ACTIVE(mdev, DRBD_FAULT_BM_ALLOC))
+		if (drbd_insert_fault(mdev, DRBD_FAULT_BM_ALLOC))
 			npages = NULL;
 		else
 			npages = bm_realloc_pages(b, want);
@@ -542,11 +708,6 @@
 		bm_free_pages(opages + want, have - want);
 	}
 
-	p_addr = bm_map_paddr(b, words);
-	bm = p_addr + MLPP(words);
-	*bm = DRBD_MAGIC;
-	bm_unmap(p_addr);
-
 	(void)bm_clear_surplus(b);
 
 	spin_unlock_irq(&b->bm_lock);
@@ -554,7 +715,7 @@
 		bm_vk_free(opages, opages_vmalloced);
 	if (!growing)
 		b->bm_set = bm_count_bits(b);
-	dev_info(DEV, "resync bitmap: bits=%lu words=%lu\n", bits, words);
+	dev_info(DEV, "resync bitmap: bits=%lu words=%lu pages=%lu\n", bits, words, want);
 
  out:
 	drbd_bm_unlock(mdev);
@@ -624,6 +785,7 @@
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long *p_addr, *bm;
 	unsigned long word, bits;
+	unsigned int idx;
 	size_t end, do_now;
 
 	end = offset + number;
@@ -638,16 +800,18 @@
 	spin_lock_irq(&b->bm_lock);
 	while (offset < end) {
 		do_now = min_t(size_t, ALIGN(offset+1, LWPP), end) - offset;
-		p_addr = bm_map_paddr(b, offset);
+		idx = bm_word_to_page_idx(b, offset);
+		p_addr = bm_map_pidx(b, idx);
 		bm = p_addr + MLPP(offset);
 		offset += do_now;
 		while (do_now--) {
 			bits = hweight_long(*bm);
-			word = *bm | lel_to_cpu(*buffer++);
+			word = *bm | *buffer++;
 			*bm++ = word;
 			b->bm_set += hweight_long(word) - bits;
 		}
 		bm_unmap(p_addr);
+		bm_set_page_need_writeout(b->bm_pages[idx]);
 	}
 	/* with 32bit <-> 64bit cross-platform connect
 	 * this is only correct for current usage,
@@ -656,7 +820,6 @@
 	 */
 	if (end == b->bm_words)
 		b->bm_set -= bm_clear_surplus(b);
-
 	spin_unlock_irq(&b->bm_lock);
 }
 
@@ -686,11 +849,11 @@
 	else {
 		while (offset < end) {
 			do_now = min_t(size_t, ALIGN(offset+1, LWPP), end) - offset;
-			p_addr = bm_map_paddr(b, offset);
+			p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, offset));
 			bm = p_addr + MLPP(offset);
 			offset += do_now;
 			while (do_now--)
-				*buffer++ = cpu_to_lel(*bm++);
+				*buffer++ = *bm++;
 			bm_unmap(p_addr);
 		}
 	}
@@ -724,9 +887,22 @@
 	spin_unlock_irq(&b->bm_lock);
 }
 
+struct bm_aio_ctx {
+	struct drbd_conf *mdev;
+	atomic_t in_flight;
+	struct completion done;
+	unsigned flags;
+#define BM_AIO_COPY_PAGES	1
+	int error;
+};
+
+/* bv_page may be a copy, or may be the original */
 static void bm_async_io_complete(struct bio *bio, int error)
 {
-	struct drbd_bitmap *b = bio->bi_private;
+	struct bm_aio_ctx *ctx = bio->bi_private;
+	struct drbd_conf *mdev = ctx->mdev;
+	struct drbd_bitmap *b = mdev->bitmap;
+	unsigned int idx = bm_page_to_idx(bio->bi_io_vec[0].bv_page);
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 
 
@@ -737,38 +913,83 @@
 	if (!error && !uptodate)
 		error = -EIO;
 
+	if ((ctx->flags & BM_AIO_COPY_PAGES) == 0 &&
+	    !bm_test_page_unchanged(b->bm_pages[idx]))
+		dev_warn(DEV, "bitmap page idx %u changed during IO!\n", idx);
+
 	if (error) {
-		/* doh. what now?
-		 * for now, set all bits, and flag MD_IO_ERROR */
-		__set_bit(BM_MD_IO_ERROR, &b->bm_flags);
+		/* ctx error will hold the completed-last non-zero error code,
+		 * in case error codes differ. */
+		ctx->error = error;
+		bm_set_page_io_err(b->bm_pages[idx]);
+		/* Not identical to on disk version of it.
+		 * Is BM_PAGE_IO_ERROR enough? */
+		if (__ratelimit(&drbd_ratelimit_state))
+			dev_err(DEV, "IO ERROR %d on bitmap page idx %u\n",
+					error, idx);
+	} else {
+		bm_clear_page_io_err(b->bm_pages[idx]);
+		dynamic_dev_dbg(DEV, "bitmap page idx %u completed\n", idx);
 	}
-	if (atomic_dec_and_test(&b->bm_async_io))
-		wake_up(&b->bm_io_wait);
+
+	bm_page_unlock_io(mdev, idx);
+
+	/* FIXME give back to page pool */
+	if (ctx->flags & BM_AIO_COPY_PAGES)
+		put_page(bio->bi_io_vec[0].bv_page);
 
 	bio_put(bio);
+
+	if (atomic_dec_and_test(&ctx->in_flight))
+		complete(&ctx->done);
 }
 
-static void bm_page_io_async(struct drbd_conf *mdev, struct drbd_bitmap *b, int page_nr, int rw) __must_hold(local)
+static void bm_page_io_async(struct bm_aio_ctx *ctx, int page_nr, int rw) __must_hold(local)
 {
 	/* we are process context. we always get a bio */
 	struct bio *bio = bio_alloc(GFP_KERNEL, 1);
+	struct drbd_conf *mdev = ctx->mdev;
+	struct drbd_bitmap *b = mdev->bitmap;
+	struct page *page;
 	unsigned int len;
+
 	sector_t on_disk_sector =
 		mdev->ldev->md.md_offset + mdev->ldev->md.bm_offset;
 	on_disk_sector += ((sector_t)page_nr) << (PAGE_SHIFT-9);
 
 	/* this might happen with very small
-	 * flexible external meta data device */
+	 * flexible external meta data device,
+	 * or with PAGE_SIZE > 4k */
 	len = min_t(unsigned int, PAGE_SIZE,
 		(drbd_md_last_sector(mdev->ldev) - on_disk_sector + 1)<<9);
 
+	/* serialize IO on this page */
+	bm_page_lock_io(mdev, page_nr);
+	/* before memcpy and submit,
+	 * so it can be redirtied any time */
+	bm_set_page_unchanged(b->bm_pages[page_nr]);
+
+	if (ctx->flags & BM_AIO_COPY_PAGES) {
+		/* FIXME alloc_page is good enough for now, but actually needs
+		 * to use pre-allocated page pool */
+		void *src, *dest;
+		page = alloc_page(__GFP_HIGHMEM|__GFP_WAIT);
+		dest = kmap_atomic(page, KM_USER0);
+		src = kmap_atomic(b->bm_pages[page_nr], KM_USER1);
+		memcpy(dest, src, PAGE_SIZE);
+		kunmap_atomic(src, KM_USER1);
+		kunmap_atomic(dest, KM_USER0);
+		bm_store_page_idx(page, page_nr);
+	} else
+		page = b->bm_pages[page_nr];
+
 	bio->bi_bdev = mdev->ldev->md_bdev;
 	bio->bi_sector = on_disk_sector;
-	bio_add_page(bio, b->bm_pages[page_nr], len, 0);
-	bio->bi_private = b;
+	bio_add_page(bio, page, len, 0);
+	bio->bi_private = ctx;
 	bio->bi_end_io = bm_async_io_complete;
 
-	if (FAULT_ACTIVE(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) {
+	if (drbd_insert_fault(mdev, (rw & WRITE) ? DRBD_FAULT_MD_WR : DRBD_FAULT_MD_RD)) {
 		bio->bi_rw |= rw;
 		bio_endio(bio, -EIO);
 	} else {
@@ -776,88 +997,84 @@
 	}
 }
 
-# if defined(__LITTLE_ENDIAN)
-	/* nothing to do, on disk == in memory */
-# define bm_cpu_to_lel(x) ((void)0)
-# else
-static void bm_cpu_to_lel(struct drbd_bitmap *b)
-{
-	/* need to cpu_to_lel all the pages ...
-	 * this may be optimized by using
-	 * cpu_to_lel(-1) == -1 and cpu_to_lel(0) == 0;
-	 * the following is still not optimal, but better than nothing */
-	unsigned int i;
-	unsigned long *p_addr, *bm;
-	if (b->bm_set == 0) {
-		/* no page at all; avoid swap if all is 0 */
-		i = b->bm_number_of_pages;
-	} else if (b->bm_set == b->bm_bits) {
-		/* only the last page */
-		i = b->bm_number_of_pages - 1;
-	} else {
-		/* all pages */
-		i = 0;
-	}
-	for (; i < b->bm_number_of_pages; i++) {
-		p_addr = kmap_atomic(b->bm_pages[i], KM_USER0);
-		for (bm = p_addr; bm < p_addr + PAGE_SIZE/sizeof(long); bm++)
-			*bm = cpu_to_lel(*bm);
-		kunmap_atomic(p_addr, KM_USER0);
-	}
-}
-# endif
-/* lel_to_cpu == cpu_to_lel */
-# define bm_lel_to_cpu(x) bm_cpu_to_lel(x)
-
 /*
  * bm_rw: read/write the whole bitmap from/to its on disk location.
  */
-static int bm_rw(struct drbd_conf *mdev, int rw) __must_hold(local)
+static int bm_rw(struct drbd_conf *mdev, int rw, unsigned lazy_writeout_upper_idx) __must_hold(local)
 {
+	struct bm_aio_ctx ctx = {
+		.mdev = mdev,
+		.in_flight = ATOMIC_INIT(1),
+		.done = COMPLETION_INITIALIZER_ONSTACK(ctx.done),
+		.flags = lazy_writeout_upper_idx ? BM_AIO_COPY_PAGES : 0,
+	};
 	struct drbd_bitmap *b = mdev->bitmap;
-	/* sector_t sector; */
-	int bm_words, num_pages, i;
+	int num_pages, i, count = 0;
 	unsigned long now;
 	char ppb[10];
 	int err = 0;
 
-	WARN_ON(!bm_is_locked(b));
-
-	/* no spinlock here, the drbd_bm_lock should be enough! */
-
-	bm_words  = drbd_bm_words(mdev);
-	num_pages = (bm_words*sizeof(long) + PAGE_SIZE-1) >> PAGE_SHIFT;
+	/*
+	 * We are protected against bitmap disappearing/resizing by holding an
+	 * ldev reference (caller must have called get_ldev()).
+	 * For read/write, we are protected against changes to the bitmap by
+	 * the bitmap lock (see drbd_bitmap_io).
+	 * For lazy writeout, we don't care for ongoing changes to the bitmap,
+	 * as we submit copies of pages anyways.
+	 */
+	if (!ctx.flags)
+		WARN_ON(!(BM_LOCKED_MASK & b->bm_flags));
 
-	/* on disk bitmap is little endian */
-	if (rw == WRITE)
-		bm_cpu_to_lel(b);
+	num_pages = b->bm_number_of_pages;
 
 	now = jiffies;
-	atomic_set(&b->bm_async_io, num_pages);
-	__clear_bit(BM_MD_IO_ERROR, &b->bm_flags);
 
 	/* let the layers below us try to merge these bios... */
-	for (i = 0; i < num_pages; i++)
-		bm_page_io_async(mdev, b, i, rw);
+	for (i = 0; i < num_pages; i++) {
+		/* ignore completely unchanged pages */
+		if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
+			break;
+		if (rw & WRITE) {
+			if (bm_test_page_unchanged(b->bm_pages[i])) {
+				dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i);
+				continue;
+			}
+			/* during lazy writeout,
+			 * ignore those pages not marked for lazy writeout. */
+			if (lazy_writeout_upper_idx &&
+			    !bm_test_page_lazy_writeout(b->bm_pages[i])) {
+				dynamic_dev_dbg(DEV, "skipped bm lazy write for idx %u\n", i);
+				continue;
+			}
+		}
+		atomic_inc(&ctx.in_flight);
+		bm_page_io_async(&ctx, i, rw);
+		++count;
+		cond_resched();
+	}
 
-	drbd_blk_run_queue(bdev_get_queue(mdev->ldev->md_bdev));
-	wait_event(b->bm_io_wait, atomic_read(&b->bm_async_io) == 0);
+	/*
+	 * We initialize ctx.in_flight to one to make sure bm_async_io_complete
+	 * will not complete() early, and decrement / test it here.  If there
+	 * are still some bios in flight, we need to wait for them here.
+	 */
+	if (!atomic_dec_and_test(&ctx.in_flight))
+		wait_for_completion(&ctx.done);
+	dev_info(DEV, "bitmap %s of %u pages took %lu jiffies\n",
+			rw == WRITE ? "WRITE" : "READ",
+			count, jiffies - now);
 
-	if (test_bit(BM_MD_IO_ERROR, &b->bm_flags)) {
+	if (ctx.error) {
 		dev_alert(DEV, "we had at least one MD IO ERROR during bitmap IO\n");
-		drbd_chk_io_error(mdev, 1, TRUE);
-		err = -EIO;
+		drbd_chk_io_error(mdev, 1, true);
+		err = -EIO; /* ctx.error ? */
 	}
 
 	now = jiffies;
 	if (rw == WRITE) {
-		/* swap back endianness */
-		bm_lel_to_cpu(b);
-		/* flush bitmap to stable storage */
 		drbd_md_flush(mdev);
 	} else /* rw == READ */ {
-		/* just read, if necessary adjust endianness */
-		b->bm_set = bm_count_bits_swap_endian(b);
+		b->bm_set = bm_count_bits(b);
 		dev_info(DEV, "recounting of set bits took additional %lu jiffies\n",
 		     jiffies - now);
 	}
@@ -875,112 +1092,128 @@
  */
 int drbd_bm_read(struct drbd_conf *mdev) __must_hold(local)
 {
-	return bm_rw(mdev, READ);
+	return bm_rw(mdev, READ, 0);
 }
 
 /**
  * drbd_bm_write() - Write the whole bitmap to its on disk location.
  * @mdev:	DRBD device.
+ *
+ * Will only write pages that have changed since last IO.
  */
 int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local)
 {
-	return bm_rw(mdev, WRITE);
+	return bm_rw(mdev, WRITE, 0);
 }
 
 /**
- * drbd_bm_write_sect: Writes a 512 (MD_SECTOR_SIZE) byte piece of the bitmap
+ * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
  * @mdev:	DRBD device.
- * @enr:	Extent number in the resync lru (happens to be sector offset)
+ * @upper_idx:	0: write all changed pages; +ve: page index to stop scanning for changed pages
+ */
+int drbd_bm_write_lazy(struct drbd_conf *mdev, unsigned upper_idx) __must_hold(local)
+{
+	return bm_rw(mdev, WRITE, upper_idx);
+}
+
+
+/**
+ * drbd_bm_write_page: Writes a PAGE_SIZE aligned piece of bitmap
+ * @mdev:	DRBD device.
+ * @idx:	bitmap page index
  *
- * The BM_EXT_SIZE is on purpose exactly the amount of the bitmap covered
- * by a single sector write. Therefore enr == sector offset from the
- * start of the bitmap.
+ * We don't want to special case on logical_block_size of the backend device,
+ * so we submit PAGE_SIZE aligned pieces.
+ * Note that on "most" systems, PAGE_SIZE is 4k.
+ *
+ * In case this becomes an issue on systems with larger PAGE_SIZE,
+ * we may want to change this again to write 4k aligned 4k pieces.
  */
-int drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local)
+int drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local)
 {
-	sector_t on_disk_sector = enr + mdev->ldev->md.md_offset
-				      + mdev->ldev->md.bm_offset;
-	int bm_words, num_words, offset;
-	int err = 0;
+	struct bm_aio_ctx ctx = {
+		.mdev = mdev,
+		.in_flight = ATOMIC_INIT(1),
+		.done = COMPLETION_INITIALIZER_ONSTACK(ctx.done),
+		.flags = BM_AIO_COPY_PAGES,
+	};
 
-	mutex_lock(&mdev->md_io_mutex);
-	bm_words  = drbd_bm_words(mdev);
-	offset    = S2W(enr);	/* word offset into bitmap */
-	num_words = min(S2W(1), bm_words - offset);
-	if (num_words < S2W(1))
-		memset(page_address(mdev->md_io_page), 0, MD_SECTOR_SIZE);
-	drbd_bm_get_lel(mdev, offset, num_words,
-			page_address(mdev->md_io_page));
-	if (!drbd_md_sync_page_io(mdev, mdev->ldev, on_disk_sector, WRITE)) {
-		int i;
-		err = -EIO;
-		dev_err(DEV, "IO ERROR writing bitmap sector %lu "
-		    "(meta-disk sector %llus)\n",
-		    enr, (unsigned long long)on_disk_sector);
-		drbd_chk_io_error(mdev, 1, TRUE);
-		for (i = 0; i < AL_EXT_PER_BM_SECT; i++)
-			drbd_bm_ALe_set_all(mdev, enr*AL_EXT_PER_BM_SECT+i);
+	if (bm_test_page_unchanged(mdev->bitmap->bm_pages[idx])) {
+		dynamic_dev_dbg(DEV, "skipped bm page write for idx %u\n", idx);
+		return 0;
 	}
+
+	bm_page_io_async(&ctx, idx, WRITE_SYNC);
+	wait_for_completion(&ctx.done);
+
+	if (ctx.error)
+		drbd_chk_io_error(mdev, 1, true);
+		/* that should force detach, so the in memory bitmap will be
+		 * gone in a moment as well. */
+
 	mdev->bm_writ_cnt++;
-	mutex_unlock(&mdev->md_io_mutex);
-	return err;
+	return ctx.error;
 }
 
 /* NOTE
  * find_first_bit returns int, we return unsigned long.
- * should not make much difference anyways, but ...
+ * For this to work on 32bit arch with bitnumbers > (1<<32),
+ * we'd need to return u64, and get a whole lot of other places
+ * fixed where we still use unsigned long.
  *
  * this returns a bit number, NOT a sector!
  */
-#define BPP_MASK ((1UL << (PAGE_SHIFT+3)) - 1)
 static unsigned long __bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo,
 	const int find_zero_bit, const enum km_type km)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	unsigned long i = -1UL;
 	unsigned long *p_addr;
-	unsigned long bit_offset; /* bit offset of the mapped page. */
+	unsigned long bit_offset;
+	unsigned i;
+
 
 	if (bm_fo > b->bm_bits) {
 		dev_err(DEV, "bm_fo=%lu bm_bits=%lu\n", bm_fo, b->bm_bits);
+		bm_fo = DRBD_END_OF_BITMAP;
 	} else {
 		while (bm_fo < b->bm_bits) {
-			unsigned long offset;
-			bit_offset = bm_fo & ~BPP_MASK; /* bit offset of the page */
-			offset = bit_offset >> LN2_BPL;    /* word offset of the page */
-			p_addr = __bm_map_paddr(b, offset, km);
+			/* bit offset of the first bit in the page */
+			bit_offset = bm_fo & ~BITS_PER_PAGE_MASK;
+			p_addr = __bm_map_pidx(b, bm_bit_to_page_idx(b, bm_fo), km);
 
 			if (find_zero_bit)
-				i = find_next_zero_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK);
+				i = find_next_zero_bit_le(p_addr,
+						PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK);
 			else
-				i = find_next_bit(p_addr, PAGE_SIZE*8, bm_fo & BPP_MASK);
+				i = find_next_bit_le(p_addr,
+						PAGE_SIZE*8, bm_fo & BITS_PER_PAGE_MASK);
 
 			__bm_unmap(p_addr, km);
 			if (i < PAGE_SIZE*8) {
-				i = bit_offset + i;
-				if (i >= b->bm_bits)
+				bm_fo = bit_offset + i;
+				if (bm_fo >= b->bm_bits)
 					break;
 				goto found;
 			}
 			bm_fo = bit_offset + PAGE_SIZE*8;
 		}
-		i = -1UL;
+		bm_fo = DRBD_END_OF_BITMAP;
 	}
  found:
-	return i;
+	return bm_fo;
 }
 
 static unsigned long bm_find_next(struct drbd_conf *mdev,
 	unsigned long bm_fo, const int find_zero_bit)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
-	unsigned long i = -1UL;
+	unsigned long i = DRBD_END_OF_BITMAP;
 
 	ERR_IF(!b) return i;
 	ERR_IF(!b->bm_pages) return i;
 
 	spin_lock_irq(&b->bm_lock);
-	if (bm_is_locked(b))
+	if (BM_DONT_TEST & b->bm_flags)
 		bm_print_lock_info(mdev);
 
 	i = __bm_find_next(mdev, bm_fo, find_zero_bit, KM_IRQ1);
@@ -1006,13 +1239,13 @@
  * you must take drbd_bm_lock() first */
 unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo)
 {
-	/* WARN_ON(!bm_is_locked(mdev)); */
+	/* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
 	return __bm_find_next(mdev, bm_fo, 0, KM_USER1);
 }
 
 unsigned long _drbd_bm_find_next_zero(struct drbd_conf *mdev, unsigned long bm_fo)
 {
-	/* WARN_ON(!bm_is_locked(mdev)); */
+	/* WARN_ON(!(BM_DONT_SET & mdev->b->bm_flags)); */
 	return __bm_find_next(mdev, bm_fo, 1, KM_USER1);
 }
 
@@ -1028,8 +1261,9 @@
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long *p_addr = NULL;
 	unsigned long bitnr;
-	unsigned long last_page_nr = -1UL;
+	unsigned int last_page_nr = -1U;
 	int c = 0;
+	int changed_total = 0;
 
 	if (e >= b->bm_bits) {
 		dev_err(DEV, "ASSERT FAILED: bit_s=%lu bit_e=%lu bm_bits=%lu\n",
@@ -1037,23 +1271,33 @@
 		e = b->bm_bits ? b->bm_bits -1 : 0;
 	}
 	for (bitnr = s; bitnr <= e; bitnr++) {
-		unsigned long offset = bitnr>>LN2_BPL;
-		unsigned long page_nr = offset >> (PAGE_SHIFT - LN2_BPL + 3);
+		unsigned int page_nr = bm_bit_to_page_idx(b, bitnr);
 		if (page_nr != last_page_nr) {
 			if (p_addr)
 				__bm_unmap(p_addr, km);
-			p_addr = __bm_map_paddr(b, offset, km);
+			if (c < 0)
+				bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]);
+			else if (c > 0)
+				bm_set_page_need_writeout(b->bm_pages[last_page_nr]);
+			changed_total += c;
+			c = 0;
+			p_addr = __bm_map_pidx(b, page_nr, km);
 			last_page_nr = page_nr;
 		}
 		if (val)
-			c += (0 == __test_and_set_bit(bitnr & BPP_MASK, p_addr));
+			c += (0 == __test_and_set_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr));
 		else
-			c -= (0 != __test_and_clear_bit(bitnr & BPP_MASK, p_addr));
+			c -= (0 != __test_and_clear_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr));
 	}
 	if (p_addr)
 		__bm_unmap(p_addr, km);
-	b->bm_set += c;
-	return c;
+	if (c < 0)
+		bm_set_page_lazy_writeout(b->bm_pages[last_page_nr]);
+	else if (c > 0)
+		bm_set_page_need_writeout(b->bm_pages[last_page_nr]);
+	changed_total += c;
+	b->bm_set += changed_total;
+	return changed_total;
 }
 
 /* returns number of bits actually changed.
@@ -1071,7 +1315,7 @@
 	ERR_IF(!b->bm_pages) return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
-	if (bm_is_locked(b))
+	if ((val ? BM_DONT_SET : BM_DONT_CLEAR) & b->bm_flags)
 		bm_print_lock_info(mdev);
 
 	c = __bm_change_bits_to(mdev, s, e, val, KM_IRQ1);
@@ -1188,12 +1432,11 @@
 	ERR_IF(!b->bm_pages) return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
-	if (bm_is_locked(b))
+	if (BM_DONT_TEST & b->bm_flags)
 		bm_print_lock_info(mdev);
 	if (bitnr < b->bm_bits) {
-		unsigned long offset = bitnr>>LN2_BPL;
-		p_addr = bm_map_paddr(b, offset);
-		i = test_bit(bitnr & BPP_MASK, p_addr) ? 1 : 0;
+		p_addr = bm_map_pidx(b, bm_bit_to_page_idx(b, bitnr));
+		i = test_bit_le(bitnr & BITS_PER_PAGE_MASK, p_addr) ? 1 : 0;
 		bm_unmap(p_addr);
 	} else if (bitnr == b->bm_bits) {
 		i = -1;
@@ -1211,10 +1454,10 @@
 {
 	unsigned long flags;
 	struct drbd_bitmap *b = mdev->bitmap;
-	unsigned long *p_addr = NULL, page_nr = -1;
+	unsigned long *p_addr = NULL;
 	unsigned long bitnr;
+	unsigned int page_nr = -1U;
 	int c = 0;
-	size_t w;
 
 	/* If this is called without a bitmap, that is a bug.  But just to be
 	 * robust in case we screwed up elsewhere, in that case pretend there
@@ -1224,20 +1467,20 @@
 	ERR_IF(!b->bm_pages) return 1;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
-	if (bm_is_locked(b))
+	if (BM_DONT_TEST & b->bm_flags)
 		bm_print_lock_info(mdev);
 	for (bitnr = s; bitnr <= e; bitnr++) {
-		w = bitnr >> LN2_BPL;
-		if (page_nr != w >> (PAGE_SHIFT - LN2_BPL + 3)) {
-			page_nr = w >> (PAGE_SHIFT - LN2_BPL + 3);
+		unsigned int idx = bm_bit_to_page_idx(b, bitnr);
+		if (page_nr != idx) {
+			page_nr = idx;
 			if (p_addr)
 				bm_unmap(p_addr);
-			p_addr = bm_map_paddr(b, w);
+			p_addr = bm_map_pidx(b, idx);
 		}
 		ERR_IF (bitnr >= b->bm_bits) {
 			dev_err(DEV, "bitnr=%lu bm_bits=%lu\n", bitnr, b->bm_bits);
 		} else {
-			c += (0 != test_bit(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
+			c += (0 != test_bit_le(bitnr - (page_nr << (PAGE_SHIFT+3)), p_addr));
 		}
 	}
 	if (p_addr)
@@ -1272,7 +1515,7 @@
 	ERR_IF(!b->bm_pages) return 0;
 
 	spin_lock_irqsave(&b->bm_lock, flags);
-	if (bm_is_locked(b))
+	if (BM_DONT_TEST & b->bm_flags)
 		bm_print_lock_info(mdev);
 
 	s = S2W(enr);
@@ -1280,7 +1523,7 @@
 	count = 0;
 	if (s < b->bm_words) {
 		int n = e-s;
-		p_addr = bm_map_paddr(b, s);
+		p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s));
 		bm = p_addr + MLPP(s);
 		while (n--)
 			count += hweight_long(*bm++);
@@ -1292,18 +1535,20 @@
 	return count;
 }
 
-/* set all bits covered by the AL-extent al_enr */
+/* Set all bits covered by the AL-extent al_enr.
+ * Returns number of bits changed. */
 unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev, unsigned long al_enr)
 {
 	struct drbd_bitmap *b = mdev->bitmap;
 	unsigned long *p_addr, *bm;
 	unsigned long weight;
-	int count, s, e, i, do_now;
+	unsigned long s, e;
+	int count, i, do_now;
 	ERR_IF(!b) return 0;
 	ERR_IF(!b->bm_pages) return 0;
 
 	spin_lock_irq(&b->bm_lock);
-	if (bm_is_locked(b))
+	if (BM_DONT_SET & b->bm_flags)
 		bm_print_lock_info(mdev);
 	weight = b->bm_set;
 
@@ -1315,7 +1560,7 @@
 	count = 0;
 	if (s < b->bm_words) {
 		i = do_now = e-s;
-		p_addr = bm_map_paddr(b, s);
+		p_addr = bm_map_pidx(b, bm_word_to_page_idx(b, s));
 		bm = p_addr + MLPP(s);
 		while (i--) {
 			count += hweight_long(*bm);
@@ -1327,7 +1572,7 @@
 		if (e == b->bm_words)
 			b->bm_set -= bm_clear_surplus(b);
 	} else {
-		dev_err(DEV, "start offset (%d) too large in drbd_bm_ALe_set_all\n", s);
+		dev_err(DEV, "start offset (%lu) too large in drbd_bm_ALe_set_all\n", s);
 	}
 	weight = b->bm_set - weight;
 	spin_unlock_irq(&b->bm_lock);
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_int.h linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_int.h
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_int.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_int.h	2011-05-19 00:06:34.000000000 -0400
@@ -72,13 +72,6 @@
 extern char usermode_helper[];
 
 
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-
 /* I don't remember why XCPU ...
  * This is used to wake the asender,
  * and to interrupt sending the sending task
@@ -104,6 +97,7 @@
 #define ID_SYNCER (-1ULL)
 #define ID_VACANT 0
 #define is_syncer_block_id(id) ((id) == ID_SYNCER)
+#define UUID_NEW_BM_OFFSET ((u64)0x0001000000000000ULL)
 
 struct drbd_conf;
 
@@ -137,20 +131,19 @@
 	DRBD_FAULT_MAX,
 };
 
-#ifdef CONFIG_DRBD_FAULT_INJECTION
 extern unsigned int
 _drbd_insert_fault(struct drbd_conf *mdev, unsigned int type);
+
 static inline int
 drbd_insert_fault(struct drbd_conf *mdev, unsigned int type) {
+#ifdef CONFIG_DRBD_FAULT_INJECTION
 	return fault_rate &&
 		(enable_faults & (1<<type)) &&
 		_drbd_insert_fault(mdev, type);
-}
-#define FAULT_ACTIVE(_m, _t) (drbd_insert_fault((_m), (_t)))
-
 #else
-#define FAULT_ACTIVE(_m, _t) (0)
+	return 0;
 #endif
+}
 
 /* integer division, round _UP_ to the next integer */
 #define div_ceil(A, B) ((A)/(B) + ((A)%(B) ? 1 : 0))
@@ -212,8 +205,10 @@
 	/* P_CKPT_FENCE_REQ      = 0x25, * currently reserved for protocol D */
 	/* P_CKPT_DISABLE_REQ    = 0x26, * currently reserved for protocol D */
 	P_DELAY_PROBE         = 0x27, /* is used on BOTH sockets */
+	P_OUT_OF_SYNC         = 0x28, /* Mark as out of sync (Outrunning), data socket */
+	P_RS_CANCEL           = 0x29, /* meta: Used to cancel RS_DATA_REQUEST packet by SyncSource */
 
-	P_MAX_CMD	      = 0x28,
+	P_MAX_CMD	      = 0x2A,
 	P_MAY_IGNORE	      = 0x100, /* Flag to test if (cmd > P_MAY_IGNORE) ... */
 	P_MAX_OPT_CMD	      = 0x101,
 
@@ -269,6 +264,7 @@
 		[P_RS_IS_IN_SYNC]	= "CsumRSIsInSync",
 		[P_COMPRESSED_BITMAP]   = "CBitmap",
 		[P_DELAY_PROBE]         = "DelayProbe",
+		[P_OUT_OF_SYNC]		= "OutOfSync",
 		[P_MAX_CMD]	        = NULL,
 	};
 
@@ -377,7 +373,7 @@
 #define DP_HARDBARRIER	      1 /* depricated */
 #define DP_RW_SYNC	      2 /* equals REQ_SYNC    */
 #define DP_MAY_SET_IN_SYNC    4
-#define DP_UNPLUG             8 /* equals REQ_UNPLUG  */
+#define DP_UNPLUG             8 /* not used anymore   */
 #define DP_FUA               16 /* equals REQ_FUA     */
 #define DP_FLUSH             32 /* equals REQ_FLUSH   */
 #define DP_DISCARD           64 /* equals REQ_DISCARD */
@@ -512,7 +508,7 @@
 	u64	    d_size;  /* size of disk */
 	u64	    u_size;  /* user requested size */
 	u64	    c_size;  /* current exported size */
-	u32	    max_segment_size;  /* Maximal size of a BIO */
+	u32	    max_bio_size;  /* Maximal size of a BIO */
 	u16	    queue_order_type;  /* not yet implemented in DRBD*/
 	u16	    dds_flags; /* use enum dds_flags here. */
 } __packed;
@@ -550,6 +546,13 @@
 	u32	    pad;
 } __packed;
 
+struct p_block_desc {
+	struct p_header80 head;
+	u64 sector;
+	u32 blksize;
+	u32 pad;	/* to multiple of 8 Byte */
+} __packed;
+
 /* Valid values for the encoding field.
  * Bump proto version when changing this. */
 enum drbd_bitmap_code {
@@ -619,7 +622,7 @@
 /* one bitmap packet, including the p_header,
  * should fit within one _architecture independend_ page.
  * so we need to use the fixed size 4KiB page size
- * most architechtures have used for a long time.
+ * most architectures have used for a long time.
  */
 #define BM_PACKET_PAYLOAD_BYTES (4096 - sizeof(struct p_header80))
 #define BM_PACKET_WORDS (BM_PACKET_PAYLOAD_BYTES/sizeof(long))
@@ -647,6 +650,7 @@
         struct p_block_req       block_req;
 	struct p_delay_probe93   delay_probe93;
 	struct p_rs_uuid         rs_uuid;
+	struct p_block_desc      block_desc;
 } __packed;
 
 /**********************************************************************/
@@ -677,13 +681,6 @@
 	return thi->t_state;
 }
 
-
-/*
- * Having this as the first member of a struct provides sort of "inheritance".
- * "derived" structs can be "drbd_queue_work()"ed.
- * The callback should know and cast back to the descendant struct.
- * drbd_request and drbd_epoch_entry are descendants of drbd_work.
- */
 struct drbd_work;
 typedef int (*drbd_work_cb)(struct drbd_conf *, struct drbd_work *, int cancel);
 struct drbd_work {
@@ -712,9 +709,6 @@
 	 * starting a new epoch...
 	 */
 
-	/* up to here, the struct layout is identical to drbd_epoch_entry;
-	 * we might be able to use that to our advantage...  */
-
 	struct list_head tl_requests; /* ring list in the transfer log */
 	struct bio *master_bio;       /* master bio pointer */
 	unsigned long rq_state; /* see comments above _req_mod() */
@@ -816,7 +810,7 @@
 
 /* global flag bits */
 enum {
-	CREATE_BARRIER,		/* next P_DATA is preceeded by a P_BARRIER */
+	CREATE_BARRIER,		/* next P_DATA is preceded by a P_BARRIER */
 	SIGNAL_ASENDER,		/* whether asender wants to be interrupted */
 	SEND_PING,		/* whether asender should send a ping asap */
 
@@ -831,7 +825,7 @@
 	CRASHED_PRIMARY,	/* This node was a crashed primary.
 				 * Gets cleared when the state.conn
 				 * goes into C_CONNECTED state. */
-	WRITE_BM_AFTER_RESYNC,	/* A kmalloc() during resync failed */
+	NO_BARRIER_SUPP,	/* underlying block device doesn't implement barriers */
 	CONSIDER_RESYNC,
 
 	MD_NO_FUA,		/* Users wants us to not use FUA/FLUSH on meta data dev */
@@ -856,10 +850,37 @@
 	GOT_PING_ACK,		/* set when we receive a ping_ack packet, misc wait gets woken */
 	NEW_CUR_UUID,		/* Create new current UUID when thawing IO */
 	AL_SUSPENDED,		/* Activity logging is currently suspended. */
+	AHEAD_TO_SYNC_SOURCE,   /* Ahead -> SyncSource queued */
 };
 
 struct drbd_bitmap; /* opaque for drbd_conf */
 
+/* definition of bits in bm_flags to be used in drbd_bm_lock
+ * and drbd_bitmap_io and friends. */
+enum bm_flag {
+	/* do we need to kfree, or vfree bm_pages? */
+	BM_P_VMALLOCED = 0x10000, /* internal use only, will be masked out */
+
+	/* currently locked for bulk operation */
+	BM_LOCKED_MASK = 0x7,
+
+	/* in detail, that is: */
+	BM_DONT_CLEAR = 0x1,
+	BM_DONT_SET   = 0x2,
+	BM_DONT_TEST  = 0x4,
+
+	/* (test bit, count bit) allowed (common case) */
+	BM_LOCKED_TEST_ALLOWED = 0x3,
+
+	/* testing bits, as well as setting new bits allowed, but clearing bits
+	 * would be unexpected.  Used during bitmap receive.  Setting new bits
+	 * requires sending of "out-of-sync" information, though. */
+	BM_LOCKED_SET_ALLOWED = 0x1,
+
+	/* clear is not expected while bitmap is locked for bulk operation */
+};
+
+
 /* TODO sort members for performance
  * MAYBE group them further */
 
@@ -925,6 +946,7 @@
 struct bm_io_work {
 	struct drbd_work w;
 	char *why;
+	enum bm_flag flags;
 	int (*io_fn)(struct drbd_conf *mdev);
 	void (*done)(struct drbd_conf *mdev, int rv);
 };
@@ -963,9 +985,12 @@
 	struct drbd_work  resync_work,
 			  unplug_work,
 			  go_diskless,
-			  md_sync_work;
+			  md_sync_work,
+			  start_resync_work;
 	struct timer_list resync_timer;
 	struct timer_list md_sync_timer;
+	struct timer_list start_resync_timer;
+	struct timer_list request_timer;
 #ifdef DRBD_DEBUG_MD_SYNC
 	struct {
 		unsigned int line;
@@ -1000,9 +1025,9 @@
 	struct hlist_head *tl_hash;
 	unsigned int tl_hash_s;
 
-	/* blocks to sync in this run [unit BM_BLOCK_SIZE] */
+	/* blocks to resync in this run [unit BM_BLOCK_SIZE] */
 	unsigned long rs_total;
-	/* number of sync IOs that failed in this run */
+	/* number of resync blocks that failed in this run */
 	unsigned long rs_failed;
 	/* Syncer's start time [unit jiffies] */
 	unsigned long rs_start;
@@ -1101,7 +1126,8 @@
 	int c_sync_rate; /* current resync rate after syncer throttle magic */
 	struct fifo_buffer rs_plan_s; /* correction values of resync planer */
 	int rs_in_flight; /* resync sectors in flight (to proxy, in proxy and from proxy) */
-	int rs_planed;    /* resync sectors already planed */
+	int rs_planed;    /* resync sectors already planned */
+	atomic_t ap_in_flight; /* App sectors in flight (waiting for ack) */
 };
 
 static inline struct drbd_conf *minor_to_mdev(unsigned int minor)
@@ -1118,7 +1144,7 @@
 	return mdev->minor;
 }
 
-/* returns 1 if it was successfull,
+/* returns 1 if it was successful,
  * returns 0 if there was no data socket.
  * so wherever you are going to use the data.socket, e.g. do
  * if (!drbd_get_data_sock(mdev))
@@ -1163,14 +1189,19 @@
 };
 
 extern void drbd_init_set_defaults(struct drbd_conf *mdev);
-extern int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
-			union drbd_state mask, union drbd_state val);
+extern enum drbd_state_rv drbd_change_state(struct drbd_conf *mdev,
+					    enum chg_state_flags f,
+					    union drbd_state mask,
+					    union drbd_state val);
 extern void drbd_force_state(struct drbd_conf *, union drbd_state,
 			union drbd_state);
-extern int _drbd_request_state(struct drbd_conf *, union drbd_state,
-			union drbd_state, enum chg_state_flags);
-extern int __drbd_set_state(struct drbd_conf *, union drbd_state,
-			    enum chg_state_flags, struct completion *done);
+extern enum drbd_state_rv _drbd_request_state(struct drbd_conf *,
+					      union drbd_state,
+					      union drbd_state,
+					      enum chg_state_flags);
+extern enum drbd_state_rv __drbd_set_state(struct drbd_conf *, union drbd_state,
+					   enum chg_state_flags,
+					   struct completion *done);
 extern void print_st_err(struct drbd_conf *, union drbd_state,
 			union drbd_state, int);
 extern int  drbd_thread_start(struct drbd_thread *thi);
@@ -1195,7 +1226,7 @@
 extern int drbd_send_protocol(struct drbd_conf *mdev);
 extern int drbd_send_uuids(struct drbd_conf *mdev);
 extern int drbd_send_uuids_skip_initial_sync(struct drbd_conf *mdev);
-extern int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val);
+extern int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev);
 extern int drbd_send_sizes(struct drbd_conf *mdev, int trigger_reply, enum dds_flags flags);
 extern int _drbd_send_state(struct drbd_conf *mdev);
 extern int drbd_send_state(struct drbd_conf *mdev);
@@ -1220,11 +1251,10 @@
 			struct p_data *dp, int data_size);
 extern int drbd_send_ack_ex(struct drbd_conf *mdev, enum drbd_packets cmd,
 			    sector_t sector, int blksize, u64 block_id);
+extern int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_send_block(struct drbd_conf *mdev, enum drbd_packets cmd,
 			   struct drbd_epoch_entry *e);
 extern int drbd_send_dblock(struct drbd_conf *mdev, struct drbd_request *req);
-extern int _drbd_send_barrier(struct drbd_conf *mdev,
-			struct drbd_tl_epoch *barrier);
 extern int drbd_send_drequest(struct drbd_conf *mdev, int cmd,
 			      sector_t sector, int size, u64 block_id);
 extern int drbd_send_drequest_csum(struct drbd_conf *mdev,
@@ -1235,14 +1265,13 @@
 
 extern int drbd_send_bitmap(struct drbd_conf *mdev);
 extern int _drbd_send_bitmap(struct drbd_conf *mdev);
-extern int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode);
+extern int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode);
 extern void drbd_free_bc(struct drbd_backing_dev *ldev);
 extern void drbd_mdev_cleanup(struct drbd_conf *mdev);
+void drbd_print_uuids(struct drbd_conf *mdev, const char *text);
 
-/* drbd_meta-data.c (still in drbd_main.c) */
 extern void drbd_md_sync(struct drbd_conf *mdev);
 extern int  drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev);
-/* maybe define them below as inline? */
 extern void drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local);
 extern void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local);
@@ -1261,10 +1290,12 @@
 extern void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 				 int (*io_fn)(struct drbd_conf *),
 				 void (*done)(struct drbd_conf *, int),
-				 char *why);
+				 char *why, enum bm_flag flags);
+extern int drbd_bitmap_io(struct drbd_conf *mdev,
+		int (*io_fn)(struct drbd_conf *),
+		char *why, enum bm_flag flags);
 extern int drbd_bmio_set_n_write(struct drbd_conf *mdev);
 extern int drbd_bmio_clear_n_write(struct drbd_conf *mdev);
-extern int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why);
 extern void drbd_go_diskless(struct drbd_conf *mdev);
 extern void drbd_ldev_destroy(struct drbd_conf *mdev);
 
@@ -1313,6 +1344,7 @@
 
 #define BME_NO_WRITES  0  /* bm_extent.flags: no more requests on this one! */
 #define BME_LOCKED     1  /* bm_extent.flags: syncer active on this one. */
+#define BME_PRIORITY   2  /* finish resync IO on this extent ASAP! App IO waiting! */
 
 /* drbd_bitmap.c */
 /*
@@ -1390,7 +1422,9 @@
  * you should use 64bit OS for that much storage, anyways. */
 #define DRBD_MAX_SECTORS_FLEX BM_BIT_TO_SECT(0xffff7fff)
 #else
-#define DRBD_MAX_SECTORS_FLEX BM_BIT_TO_SECT(0x1LU << 32)
+/* we allow up to 1 PiB now on 64bit architecture with "flexible" meta data */
+#define DRBD_MAX_SECTORS_FLEX (1UL << 51)
+/* corresponds to (1UL << 38) bits right now. */
 #endif
 #endif
 
@@ -1398,7 +1432,7 @@
  * With a value of 8 all IO in one 128K block make it to the same slot of the
  * hash table. */
 #define HT_SHIFT 8
-#define DRBD_MAX_SEGMENT_SIZE (1U<<(9+HT_SHIFT))
+#define DRBD_MAX_BIO_SIZE (1U<<(9+HT_SHIFT))
 
 #define DRBD_MAX_SIZE_H80_PACKET (1 << 15) /* The old header only allows packets up to 32Kib data */
 
@@ -1410,16 +1444,20 @@
 extern void drbd_bm_cleanup(struct drbd_conf *mdev);
 extern void drbd_bm_set_all(struct drbd_conf *mdev);
 extern void drbd_bm_clear_all(struct drbd_conf *mdev);
+/* set/clear/test only a few bits at a time */
 extern int  drbd_bm_set_bits(
 		struct drbd_conf *mdev, unsigned long s, unsigned long e);
 extern int  drbd_bm_clear_bits(
 		struct drbd_conf *mdev, unsigned long s, unsigned long e);
-/* bm_set_bits variant for use while holding drbd_bm_lock */
+extern int drbd_bm_count_bits(
+	struct drbd_conf *mdev, const unsigned long s, const unsigned long e);
+/* bm_set_bits variant for use while holding drbd_bm_lock,
+ * may process the whole bitmap in one go */
 extern void _drbd_bm_set_bits(struct drbd_conf *mdev,
 		const unsigned long s, const unsigned long e);
 extern int  drbd_bm_test_bit(struct drbd_conf *mdev, unsigned long bitnr);
 extern int  drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr);
-extern int  drbd_bm_write_sect(struct drbd_conf *mdev, unsigned long enr) __must_hold(local);
+extern int  drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
 extern int  drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
 extern int  drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
 extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
@@ -1427,6 +1465,8 @@
 extern size_t	     drbd_bm_words(struct drbd_conf *mdev);
 extern unsigned long drbd_bm_bits(struct drbd_conf *mdev);
 extern sector_t      drbd_bm_capacity(struct drbd_conf *mdev);
+
+#define DRBD_END_OF_BITMAP	(~(unsigned long)0)
 extern unsigned long drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
 /* bm_find_next variants for use while you hold drbd_bm_lock() */
 extern unsigned long _drbd_bm_find_next(struct drbd_conf *mdev, unsigned long bm_fo);
@@ -1437,14 +1477,12 @@
 /* for receive_bitmap */
 extern void drbd_bm_merge_lel(struct drbd_conf *mdev, size_t offset,
 		size_t number, unsigned long *buffer);
-/* for _drbd_send_bitmap and drbd_bm_write_sect */
+/* for _drbd_send_bitmap */
 extern void drbd_bm_get_lel(struct drbd_conf *mdev, size_t offset,
 		size_t number, unsigned long *buffer);
 
-extern void drbd_bm_lock(struct drbd_conf *mdev, char *why);
+extern void drbd_bm_lock(struct drbd_conf *mdev, char *why, enum bm_flag flags);
 extern void drbd_bm_unlock(struct drbd_conf *mdev);
-
-extern int drbd_bm_count_bits(struct drbd_conf *mdev, const unsigned long s, const unsigned long e);
 /* drbd_main.c */
 
 extern struct kmem_cache *drbd_request_cache;
@@ -1467,7 +1505,7 @@
 extern int proc_details;
 
 /* drbd_req */
-extern int drbd_make_request_26(struct request_queue *q, struct bio *bio);
+extern int drbd_make_request(struct request_queue *q, struct bio *bio);
 extern int drbd_read_remote(struct drbd_conf *mdev, struct drbd_request *req);
 extern int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec);
 extern int is_valid_ar_handle(struct drbd_request *, sector_t);
@@ -1482,8 +1520,9 @@
 extern enum determine_dev_size drbd_determin_dev_size(struct drbd_conf *, enum dds_flags) __must_hold(local);
 extern void resync_after_online_grow(struct drbd_conf *);
 extern void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int) __must_hold(local);
-extern int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role,
-		int force);
+extern enum drbd_state_rv drbd_set_role(struct drbd_conf *mdev,
+					enum drbd_role new_role,
+					int force);
 extern enum drbd_disk_state drbd_try_outdate_peer(struct drbd_conf *mdev);
 extern void drbd_try_outdate_peer_async(struct drbd_conf *mdev);
 extern int drbd_khelper(struct drbd_conf *mdev, char *cmd);
@@ -1499,6 +1538,7 @@
 extern int drbd_md_sync_page_io(struct drbd_conf *mdev,
 		struct drbd_backing_dev *bdev, sector_t sector, int rw);
 extern void drbd_ov_oos_found(struct drbd_conf*, sector_t, int);
+extern void drbd_rs_controller_reset(struct drbd_conf *mdev);
 
 static inline void ov_oos_print(struct drbd_conf *mdev)
 {
@@ -1522,21 +1562,23 @@
 extern int w_e_end_ov_reply(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_end_ov_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_ov_finished(struct drbd_conf *, struct drbd_work *, int);
-extern int w_resync_inactive(struct drbd_conf *, struct drbd_work *, int);
+extern int w_resync_timer(struct drbd_conf *, struct drbd_work *, int);
 extern int w_resume_next_sg(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_write_hint(struct drbd_conf *, struct drbd_work *, int);
-extern int w_make_resync_request(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_dblock(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_barrier(struct drbd_conf *, struct drbd_work *, int);
 extern int w_send_read_req(struct drbd_conf *, struct drbd_work *, int);
 extern int w_prev_work_done(struct drbd_conf *, struct drbd_work *, int);
 extern int w_e_reissue(struct drbd_conf *, struct drbd_work *, int);
 extern int w_restart_disk_io(struct drbd_conf *, struct drbd_work *, int);
+extern int w_send_oos(struct drbd_conf *, struct drbd_work *, int);
+extern int w_start_resync(struct drbd_conf *, struct drbd_work *, int);
 
 extern void resync_timer_fn(unsigned long data);
+extern void start_resync_timer_fn(unsigned long data);
 
 /* drbd_receiver.c */
-extern int drbd_rs_should_slow_down(struct drbd_conf *mdev);
+extern int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector);
 extern int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
 		const unsigned rw, const int fault_type);
 extern int drbd_release_ee(struct drbd_conf *mdev, struct list_head *list);
@@ -1619,16 +1661,16 @@
 extern void drbd_rs_failed_io(struct drbd_conf *mdev,
 		sector_t sector, int size);
 extern int drbd_al_read_log(struct drbd_conf *mdev, struct drbd_backing_dev *);
+extern void drbd_advance_rs_marks(struct drbd_conf *mdev, unsigned long still_to_go);
 extern void __drbd_set_in_sync(struct drbd_conf *mdev, sector_t sector,
 		int size, const char *file, const unsigned int line);
 #define drbd_set_in_sync(mdev, sector, size) \
 	__drbd_set_in_sync(mdev, sector, size, __FILE__, __LINE__)
-extern void __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
+extern int __drbd_set_out_of_sync(struct drbd_conf *mdev, sector_t sector,
 		int size, const char *file, const unsigned int line);
 #define drbd_set_out_of_sync(mdev, sector, size) \
 	__drbd_set_out_of_sync(mdev, sector, size, __FILE__, __LINE__)
 extern void drbd_al_apply_to_bm(struct drbd_conf *mdev);
-extern void drbd_al_to_on_disk_bm(struct drbd_conf *mdev);
 extern void drbd_al_shrink(struct drbd_conf *mdev);
 
 
@@ -1747,11 +1789,11 @@
 	wake_up(&mdev->misc_wait);
 }
 
-static inline int _drbd_set_state(struct drbd_conf *mdev,
-				   union drbd_state ns, enum chg_state_flags flags,
-				   struct completion *done)
+static inline enum drbd_state_rv
+_drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+		enum chg_state_flags flags, struct completion *done)
 {
-	int rv;
+	enum drbd_state_rv rv;
 
 	read_lock(&global_state_lock);
 	rv = __drbd_set_state(mdev, ns, flags, done);
@@ -1982,17 +2024,17 @@
 
 static inline void drbd_thread_stop(struct drbd_thread *thi)
 {
-	_drbd_thread_stop(thi, FALSE, TRUE);
+	_drbd_thread_stop(thi, false, true);
 }
 
 static inline void drbd_thread_stop_nowait(struct drbd_thread *thi)
 {
-	_drbd_thread_stop(thi, FALSE, FALSE);
+	_drbd_thread_stop(thi, false, false);
 }
 
 static inline void drbd_thread_restart_nowait(struct drbd_thread *thi)
 {
-	_drbd_thread_stop(thi, TRUE, FALSE);
+	_drbd_thread_stop(thi, true, false);
 }
 
 /* counts how many answer packets packets we expect from our peer,
@@ -2037,7 +2079,7 @@
 /* counts how many resync-related answers we still expect from the peer
  *		     increase			decrease
  * C_SYNC_TARGET sends P_RS_DATA_REQUEST (and expects P_RS_DATA_REPLY)
- * C_SYNC_SOURCE sends P_RS_DATA_REPLY   (and expects P_WRITE_ACK whith ID_SYNCER)
+ * C_SYNC_SOURCE sends P_RS_DATA_REPLY   (and expects P_WRITE_ACK with ID_SYNCER)
  *					   (or P_NEG_ACK with ID_SYNCER)
  */
 static inline void inc_rs_pending(struct drbd_conf *mdev)
@@ -2146,17 +2188,18 @@
 static inline void drbd_get_syncer_progress(struct drbd_conf *mdev,
 		unsigned long *bits_left, unsigned int *per_mil_done)
 {
-	/*
-	 * this is to break it at compile time when we change that
-	 * (we may feel 4TB maximum storage per drbd is not enough)
-	 */
+	/* this is to break it at compile time when we change that, in case we
+	 * want to support more than (1<<32) bits on a 32bit arch. */
 	typecheck(unsigned long, mdev->rs_total);
 
 	/* note: both rs_total and rs_left are in bits, i.e. in
 	 * units of BM_BLOCK_SIZE.
 	 * for the percentage, we don't care. */
 
-	*bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+		*bits_left = mdev->ov_left;
+	else
+		*bits_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
 	/* >> 10 to prevent overflow,
 	 * +1 to prevent division by zero */
 	if (*bits_left > mdev->rs_total) {
@@ -2171,10 +2214,19 @@
 				*bits_left, mdev->rs_total, mdev->rs_failed);
 		*per_mil_done = 0;
 	} else {
-		/* make sure the calculation happens in long context */
-		unsigned long tmp = 1000UL -
-				(*bits_left >> 10)*1000UL
-				/ ((mdev->rs_total >> 10) + 1UL);
+		/* Make sure the division happens in long context.
+		 * We allow up to one petabyte storage right now,
+		 * at a granularity of 4k per bit that is 2**38 bits.
+		 * After shift right and multiplication by 1000,
+		 * this should still fit easily into a 32bit long,
+		 * so we don't need a 64bit division on 32bit arch.
+		 * Note: currently we don't support such large bitmaps on 32bit
+		 * arch anyways, but no harm done to be prepared for it here.
+		 */
+		unsigned int shift = mdev->rs_total >= (1ULL << 32) ? 16 : 10;
+		unsigned long left = *bits_left >> shift;
+		unsigned long total = 1UL + (mdev->rs_total >> shift);
+		unsigned long tmp = 1000UL - left * 1000UL/total;
 		*per_mil_done = tmp;
 	}
 }
@@ -2193,8 +2245,9 @@
 	return mxb;
 }
 
-static inline int drbd_state_is_stable(union drbd_state s)
+static inline int drbd_state_is_stable(struct drbd_conf *mdev)
 {
+	union drbd_state s = mdev->state;
 
 	/* DO NOT add a default clause, we want the compiler to warn us
 	 * for any newly introduced state we may have forgotten to add here */
@@ -2211,11 +2264,9 @@
 	case C_VERIFY_T:
 	case C_PAUSED_SYNC_S:
 	case C_PAUSED_SYNC_T:
-		/* maybe stable, look at the disk state */
-		break;
-
-	/* no new io accepted during tansitional states
-	 * like handshake or teardown */
+	case C_AHEAD:
+	case C_BEHIND:
+		/* transitional states, IO allowed */
 	case C_DISCONNECTING:
 	case C_UNCONNECTED:
 	case C_TIMEOUT:
@@ -2226,7 +2277,15 @@
 	case C_WF_REPORT_PARAMS:
 	case C_STARTING_SYNC_S:
 	case C_STARTING_SYNC_T:
+		break;
+
+		/* Allow IO in BM exchange states with new protocols */
 	case C_WF_BITMAP_S:
+		if (mdev->agreed_pro_version < 96)
+			return 0;
+		break;
+
+		/* no new io accepted in these states */
 	case C_WF_BITMAP_T:
 	case C_WF_SYNC_UUID:
 	case C_MASK:
@@ -2261,41 +2320,47 @@
 	return s.susp || s.susp_nod || s.susp_fen;
 }
 
-static inline int __inc_ap_bio_cond(struct drbd_conf *mdev)
+static inline bool may_inc_ap_bio(struct drbd_conf *mdev)
 {
 	int mxb = drbd_get_max_buffers(mdev);
 
 	if (is_susp(mdev->state))
-		return 0;
+		return false;
 	if (test_bit(SUSPEND_IO, &mdev->flags))
-		return 0;
+		return false;
 
 	/* to avoid potential deadlock or bitmap corruption,
 	 * in various places, we only allow new application io
 	 * to start during "stable" states. */
 
 	/* no new io accepted when attaching or detaching the disk */
-	if (!drbd_state_is_stable(mdev->state))
-		return 0;
+	if (!drbd_state_is_stable(mdev))
+		return false;
 
 	/* since some older kernels don't have atomic_add_unless,
 	 * and we are within the spinlock anyways, we have this workaround.  */
 	if (atomic_read(&mdev->ap_bio_cnt) > mxb)
-		return 0;
+		return false;
 	if (test_bit(BITMAP_IO, &mdev->flags))
-		return 0;
-	return 1;
+		return false;
+	return true;
 }
 
-/* I'd like to use wait_event_lock_irq,
- * but I'm not sure when it got introduced,
- * and not sure when it has 3 or 4 arguments */
-static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+static inline bool inc_ap_bio_cond(struct drbd_conf *mdev, int count)
 {
-	/* compare with after_state_ch,
-	 * os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S */
-	DEFINE_WAIT(wait);
+	bool rv = false;
+
+	spin_lock_irq(&mdev->req_lock);
+	rv = may_inc_ap_bio(mdev);
+	if (rv)
+		atomic_add(count, &mdev->ap_bio_cnt);
+	spin_unlock_irq(&mdev->req_lock);
+
+	return rv;
+}
 
+static inline void inc_ap_bio(struct drbd_conf *mdev, int count)
+{
 	/* we wait here
 	 *    as long as the device is suspended
 	 *    until the bitmap is no longer on the fly during connection
@@ -2304,16 +2369,7 @@
 	 * to avoid races with the reconnect code,
 	 * we need to atomic_inc within the spinlock. */
 
-	spin_lock_irq(&mdev->req_lock);
-	while (!__inc_ap_bio_cond(mdev)) {
-		prepare_to_wait(&mdev->misc_wait, &wait, TASK_UNINTERRUPTIBLE);
-		spin_unlock_irq(&mdev->req_lock);
-		schedule();
-		finish_wait(&mdev->misc_wait, &wait);
-		spin_lock_irq(&mdev->req_lock);
-	}
-	atomic_add(count, &mdev->ap_bio_cnt);
-	spin_unlock_irq(&mdev->req_lock);
+	wait_event(mdev->misc_wait, inc_ap_bio_cond(mdev, count));
 }
 
 static inline void dec_ap_bio(struct drbd_conf *mdev)
@@ -2333,9 +2389,11 @@
 	}
 }
 
-static inline void drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
+static inline int drbd_set_ed_uuid(struct drbd_conf *mdev, u64 val)
 {
+	int changed = mdev->ed_uuid != val;
 	mdev->ed_uuid = val;
+	return changed;
 }
 
 static inline int seq_cmp(u32 a, u32 b)
@@ -2382,20 +2440,6 @@
 	return QUEUE_ORDERED_NONE;
 }
 
-static inline void drbd_blk_run_queue(struct request_queue *q)
-{
-	if (q && q->unplug_fn)
-		q->unplug_fn(q);
-}
-
-static inline void drbd_kick_lo(struct drbd_conf *mdev)
-{
-	if (get_ldev(mdev)) {
-		drbd_blk_run_queue(bdev_get_queue(mdev->ldev->backing_bdev));
-		put_ldev(mdev);
-	}
-}
-
 static inline void drbd_md_flush(struct drbd_conf *mdev)
 {
 	int r;
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_main.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_main.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,7 +85,8 @@
 MODULE_DESCRIPTION("drbd - Distributed Replicated Block Device v" REL_VERSION);
 MODULE_VERSION(REL_VERSION);
 MODULE_LICENSE("GPL");
-MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices (1-255)");
+MODULE_PARM_DESC(minor_count, "Maximum number of drbd devices ("
+		 __stringify(DRBD_MINOR_COUNT_MIN) "-" __stringify(DRBD_MINOR_COUNT_MAX) ")");
 MODULE_ALIAS_BLOCKDEV_MAJOR(DRBD_MAJOR);
 
 #include <linux/moduleparam.h>
@@ -115,7 +116,7 @@
 #endif
 
 /* module parameter, defined */
-unsigned int minor_count = 32;
+unsigned int minor_count = DRBD_MINOR_COUNT_DEF;
 int disable_sendpage;
 int allow_oos;
 unsigned int cn_idx = CN_IDX_DRBD;
@@ -335,6 +336,7 @@
 	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
 }
 
+
 /**
  * _tl_restart() - Walks the transfer log, and applies an action to all requests
  * @mdev:	DRBD device.
@@ -456,7 +458,7 @@
 }
 
 /**
- * cl_wide_st_chg() - TRUE if the state change is a cluster wide one
+ * cl_wide_st_chg() - true if the state change is a cluster wide one
  * @mdev:	DRBD device.
  * @os:		old (current) state.
  * @ns:		new (wanted) state.
@@ -473,12 +475,13 @@
 		(os.conn == C_CONNECTED && ns.conn == C_VERIFY_S);
 }
 
-int drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
-		      union drbd_state mask, union drbd_state val)
+enum drbd_state_rv
+drbd_change_state(struct drbd_conf *mdev, enum chg_state_flags f,
+		  union drbd_state mask, union drbd_state val)
 {
 	unsigned long flags;
 	union drbd_state os, ns;
-	int rv;
+	enum drbd_state_rv rv;
 
 	spin_lock_irqsave(&mdev->req_lock, flags);
 	os = mdev->state;
@@ -502,20 +505,22 @@
 	drbd_change_state(mdev, CS_HARD, mask, val);
 }
 
-static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns);
-static int is_valid_state_transition(struct drbd_conf *,
-				     union drbd_state, union drbd_state);
+static enum drbd_state_rv is_valid_state(struct drbd_conf *, union drbd_state);
+static enum drbd_state_rv is_valid_state_transition(struct drbd_conf *,
+						    union drbd_state,
+						    union drbd_state);
 static union drbd_state sanitize_state(struct drbd_conf *mdev, union drbd_state os,
 				       union drbd_state ns, const char **warn_sync_abort);
 int drbd_send_state_req(struct drbd_conf *,
 			union drbd_state, union drbd_state);
 
-static enum drbd_state_ret_codes _req_st_cond(struct drbd_conf *mdev,
-				    union drbd_state mask, union drbd_state val)
+static enum drbd_state_rv
+_req_st_cond(struct drbd_conf *mdev, union drbd_state mask,
+	     union drbd_state val)
 {
 	union drbd_state os, ns;
 	unsigned long flags;
-	int rv;
+	enum drbd_state_rv rv;
 
 	if (test_and_clear_bit(CL_ST_CHG_SUCCESS, &mdev->flags))
 		return SS_CW_SUCCESS;
@@ -536,7 +541,7 @@
 		if (rv == SS_SUCCESS) {
 			rv = is_valid_state_transition(mdev, ns, os);
 			if (rv == SS_SUCCESS)
-				rv = 0; /* cont waiting, otherwise fail. */
+				rv = SS_UNKNOWN_ERROR; /* cont waiting, otherwise fail. */
 		}
 	}
 	spin_unlock_irqrestore(&mdev->req_lock, flags);
@@ -554,14 +559,14 @@
  * Should not be called directly, use drbd_request_state() or
  * _drbd_request_state().
  */
-static int drbd_req_state(struct drbd_conf *mdev,
-			  union drbd_state mask, union drbd_state val,
-			  enum chg_state_flags f)
+static enum drbd_state_rv
+drbd_req_state(struct drbd_conf *mdev, union drbd_state mask,
+	       union drbd_state val, enum chg_state_flags f)
 {
 	struct completion done;
 	unsigned long flags;
 	union drbd_state os, ns;
-	int rv;
+	enum drbd_state_rv rv;
 
 	init_completion(&done);
 
@@ -636,10 +641,11 @@
  * Cousin of drbd_request_state(), useful with the CS_WAIT_COMPLETE
  * flag, or when logging of failed state change requests is not desired.
  */
-int _drbd_request_state(struct drbd_conf *mdev,	union drbd_state mask,
-			union drbd_state val,	enum chg_state_flags f)
+enum drbd_state_rv
+_drbd_request_state(struct drbd_conf *mdev, union drbd_state mask,
+		    union drbd_state val, enum chg_state_flags f)
 {
-	int rv;
+	enum drbd_state_rv rv;
 
 	wait_event(mdev->state_wait,
 		   (rv = drbd_req_state(mdev, mask, val, f)) != SS_IN_TRANSIENT_STATE);
@@ -663,8 +669,8 @@
 	    );
 }
 
-void print_st_err(struct drbd_conf *mdev,
-	union drbd_state os, union drbd_state ns, int err)
+void print_st_err(struct drbd_conf *mdev, union drbd_state os,
+	          union drbd_state ns, enum drbd_state_rv err)
 {
 	if (err == SS_IN_TRANSIENT_STATE)
 		return;
@@ -674,32 +680,18 @@
 }
 
 
-#define drbd_peer_str drbd_role_str
-#define drbd_pdsk_str drbd_disk_str
-
-#define drbd_susp_str(A)     ((A) ? "1" : "0")
-#define drbd_aftr_isp_str(A) ((A) ? "1" : "0")
-#define drbd_peer_isp_str(A) ((A) ? "1" : "0")
-#define drbd_user_isp_str(A) ((A) ? "1" : "0")
-
-#define PSC(A) \
-	({ if (ns.A != os.A) { \
-		pbp += sprintf(pbp, #A "( %s -> %s ) ", \
-			      drbd_##A##_str(os.A), \
-			      drbd_##A##_str(ns.A)); \
-	} })
-
 /**
  * is_valid_state() - Returns an SS_ error code if ns is not valid
  * @mdev:	DRBD device.
  * @ns:		State to consider.
  */
-static int is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
+static enum drbd_state_rv
+is_valid_state(struct drbd_conf *mdev, union drbd_state ns)
 {
 	/* See drbd_state_sw_errors in drbd_strings.c */
 
 	enum drbd_fencing_p fp;
-	int rv = SS_SUCCESS;
+	enum drbd_state_rv rv = SS_SUCCESS;
 
 	fp = FP_DONT_CARE;
 	if (get_ldev(mdev)) {
@@ -762,10 +754,11 @@
  * @ns:		new state.
  * @os:		old state.
  */
-static int is_valid_state_transition(struct drbd_conf *mdev,
-				     union drbd_state ns, union drbd_state os)
+static enum drbd_state_rv
+is_valid_state_transition(struct drbd_conf *mdev, union drbd_state ns,
+			  union drbd_state os)
 {
-	int rv = SS_SUCCESS;
+	enum drbd_state_rv rv = SS_SUCCESS;
 
 	if ((ns.conn == C_STARTING_SYNC_T || ns.conn == C_STARTING_SYNC_S) &&
 	    os.conn > C_CONNECTED)
@@ -800,6 +793,10 @@
 	    os.conn < C_CONNECTED)
 		rv = SS_NEED_CONNECTION;
 
+	if ((ns.conn == C_SYNC_TARGET || ns.conn == C_SYNC_SOURCE)
+	    && os.conn < C_WF_REPORT_PARAMS)
+		rv = SS_NEED_CONNECTION; /* No NetworkFailure -> SyncTarget etc... */
+
 	return rv;
 }
 
@@ -817,6 +814,7 @@
 				       union drbd_state ns, const char **warn_sync_abort)
 {
 	enum drbd_fencing_p fp;
+	enum drbd_disk_state disk_min, disk_max, pdsk_min, pdsk_max;
 
 	fp = FP_DONT_CARE;
 	if (get_ldev(mdev)) {
@@ -869,56 +867,6 @@
 		ns.conn = C_CONNECTED;
 	}
 
-	if (ns.conn >= C_CONNECTED &&
-	    ((ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED) ||
-	     (ns.disk == D_NEGOTIATING && ns.conn == C_WF_BITMAP_T))) {
-		switch (ns.conn) {
-		case C_WF_BITMAP_T:
-		case C_PAUSED_SYNC_T:
-			ns.disk = D_OUTDATED;
-			break;
-		case C_CONNECTED:
-		case C_WF_BITMAP_S:
-		case C_SYNC_SOURCE:
-		case C_PAUSED_SYNC_S:
-			ns.disk = D_UP_TO_DATE;
-			break;
-		case C_SYNC_TARGET:
-			ns.disk = D_INCONSISTENT;
-			dev_warn(DEV, "Implicitly set disk state Inconsistent!\n");
-			break;
-		}
-		if (os.disk == D_OUTDATED && ns.disk == D_UP_TO_DATE)
-			dev_warn(DEV, "Implicitly set disk from Outdated to UpToDate\n");
-	}
-
-	if (ns.conn >= C_CONNECTED &&
-	    (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)) {
-		switch (ns.conn) {
-		case C_CONNECTED:
-		case C_WF_BITMAP_T:
-		case C_PAUSED_SYNC_T:
-		case C_SYNC_TARGET:
-			ns.pdsk = D_UP_TO_DATE;
-			break;
-		case C_WF_BITMAP_S:
-		case C_PAUSED_SYNC_S:
-			/* remap any consistent state to D_OUTDATED,
-			 * but disallow "upgrade" of not even consistent states.
-			 */
-			ns.pdsk =
-				(D_DISKLESS < os.pdsk && os.pdsk < D_OUTDATED)
-				? os.pdsk : D_OUTDATED;
-			break;
-		case C_SYNC_SOURCE:
-			ns.pdsk = D_INCONSISTENT;
-			dev_warn(DEV, "Implicitly set pdsk Inconsistent!\n");
-			break;
-		}
-		if (os.pdsk == D_OUTDATED && ns.pdsk == D_UP_TO_DATE)
-			dev_warn(DEV, "Implicitly set pdsk from Outdated to UpToDate\n");
-	}
-
 	/* Connection breaks down before we finished "Negotiating" */
 	if (ns.conn < C_CONNECTED && ns.disk == D_NEGOTIATING &&
 	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
@@ -933,6 +881,94 @@
 		put_ldev(mdev);
 	}
 
+	/* D_CONSISTENT and D_OUTDATED vanish when we get connected */
+	if (ns.conn >= C_CONNECTED && ns.conn < C_AHEAD) {
+		if (ns.disk == D_CONSISTENT || ns.disk == D_OUTDATED)
+			ns.disk = D_UP_TO_DATE;
+		if (ns.pdsk == D_CONSISTENT || ns.pdsk == D_OUTDATED)
+			ns.pdsk = D_UP_TO_DATE;
+	}
+
+	/* Implications of the connection stat on the disk states */
+	disk_min = D_DISKLESS;
+	disk_max = D_UP_TO_DATE;
+	pdsk_min = D_INCONSISTENT;
+	pdsk_max = D_UNKNOWN;
+	switch ((enum drbd_conns)ns.conn) {
+	case C_WF_BITMAP_T:
+	case C_PAUSED_SYNC_T:
+	case C_STARTING_SYNC_T:
+	case C_WF_SYNC_UUID:
+	case C_BEHIND:
+		disk_min = D_INCONSISTENT;
+		disk_max = D_OUTDATED;
+		pdsk_min = D_UP_TO_DATE;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_VERIFY_S:
+	case C_VERIFY_T:
+		disk_min = D_UP_TO_DATE;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_UP_TO_DATE;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_CONNECTED:
+		disk_min = D_DISKLESS;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_DISKLESS;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_WF_BITMAP_S:
+	case C_PAUSED_SYNC_S:
+	case C_STARTING_SYNC_S:
+	case C_AHEAD:
+		disk_min = D_UP_TO_DATE;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_INCONSISTENT;
+		pdsk_max = D_CONSISTENT; /* D_OUTDATED would be nice. But explicit outdate necessary*/
+		break;
+	case C_SYNC_TARGET:
+		disk_min = D_INCONSISTENT;
+		disk_max = D_INCONSISTENT;
+		pdsk_min = D_UP_TO_DATE;
+		pdsk_max = D_UP_TO_DATE;
+		break;
+	case C_SYNC_SOURCE:
+		disk_min = D_UP_TO_DATE;
+		disk_max = D_UP_TO_DATE;
+		pdsk_min = D_INCONSISTENT;
+		pdsk_max = D_INCONSISTENT;
+		break;
+	case C_STANDALONE:
+	case C_DISCONNECTING:
+	case C_UNCONNECTED:
+	case C_TIMEOUT:
+	case C_BROKEN_PIPE:
+	case C_NETWORK_FAILURE:
+	case C_PROTOCOL_ERROR:
+	case C_TEAR_DOWN:
+	case C_WF_CONNECTION:
+	case C_WF_REPORT_PARAMS:
+	case C_MASK:
+		break;
+	}
+	if (ns.disk > disk_max)
+		ns.disk = disk_max;
+
+	if (ns.disk < disk_min) {
+		dev_warn(DEV, "Implicitly set disk from %s to %s\n",
+			 drbd_disk_str(ns.disk), drbd_disk_str(disk_min));
+		ns.disk = disk_min;
+	}
+	if (ns.pdsk > pdsk_max)
+		ns.pdsk = pdsk_max;
+
+	if (ns.pdsk < pdsk_min) {
+		dev_warn(DEV, "Implicitly set pdsk from %s to %s\n",
+			 drbd_disk_str(ns.pdsk), drbd_disk_str(pdsk_min));
+		ns.pdsk = pdsk_min;
+	}
+
 	if (fp == FP_STONITH &&
 	    (ns.role == R_PRIMARY && ns.conn < C_CONNECTED && ns.pdsk > D_OUTDATED) &&
 	    !(os.role == R_PRIMARY && os.conn < C_CONNECTED && os.pdsk > D_OUTDATED))
@@ -961,6 +997,10 @@
 /* helper for __drbd_set_state */
 static void set_ov_position(struct drbd_conf *mdev, enum drbd_conns cs)
 {
+	if (mdev->agreed_pro_version < 90)
+		mdev->ov_start_sector = 0;
+	mdev->rs_total = drbd_bm_bits(mdev);
+	mdev->ov_position = 0;
 	if (cs == C_VERIFY_T) {
 		/* starting online verify from an arbitrary position
 		 * does not fit well into the existing protocol.
@@ -970,11 +1010,15 @@
 		mdev->ov_start_sector = ~(sector_t)0;
 	} else {
 		unsigned long bit = BM_SECT_TO_BIT(mdev->ov_start_sector);
-		if (bit >= mdev->rs_total)
+		if (bit >= mdev->rs_total) {
 			mdev->ov_start_sector =
 				BM_BIT_TO_SECT(mdev->rs_total - 1);
+			mdev->rs_total = 1;
+		} else
+			mdev->rs_total -= bit;
 		mdev->ov_position = mdev->ov_start_sector;
 	}
+	mdev->ov_left = mdev->rs_total;
 }
 
 static void drbd_resume_al(struct drbd_conf *mdev)
@@ -992,12 +1036,12 @@
  *
  * Caller needs to hold req_lock, and global_state_lock. Do not call directly.
  */
-int __drbd_set_state(struct drbd_conf *mdev,
-		    union drbd_state ns, enum chg_state_flags flags,
-		    struct completion *done)
+enum drbd_state_rv
+__drbd_set_state(struct drbd_conf *mdev, union drbd_state ns,
+	         enum chg_state_flags flags, struct completion *done)
 {
 	union drbd_state os;
-	int rv = SS_SUCCESS;
+	enum drbd_state_rv rv = SS_SUCCESS;
 	const char *warn_sync_abort = NULL;
 	struct after_state_chg_work *ascw;
 
@@ -1033,22 +1077,46 @@
 		dev_warn(DEV, "%s aborted.\n", warn_sync_abort);
 
 	{
-		char *pbp, pb[300];
-		pbp = pb;
-		*pbp = 0;
-		PSC(role);
-		PSC(peer);
-		PSC(conn);
-		PSC(disk);
-		PSC(pdsk);
-		if (is_susp(ns) != is_susp(os))
-			pbp += sprintf(pbp, "susp( %s -> %s ) ",
-				       drbd_susp_str(is_susp(os)),
-				       drbd_susp_str(is_susp(ns)));
-		PSC(aftr_isp);
-		PSC(peer_isp);
-		PSC(user_isp);
-		dev_info(DEV, "%s\n", pb);
+	char *pbp, pb[300];
+	pbp = pb;
+	*pbp = 0;
+	if (ns.role != os.role)
+		pbp += sprintf(pbp, "role( %s -> %s ) ",
+			       drbd_role_str(os.role),
+			       drbd_role_str(ns.role));
+	if (ns.peer != os.peer)
+		pbp += sprintf(pbp, "peer( %s -> %s ) ",
+			       drbd_role_str(os.peer),
+			       drbd_role_str(ns.peer));
+	if (ns.conn != os.conn)
+		pbp += sprintf(pbp, "conn( %s -> %s ) ",
+			       drbd_conn_str(os.conn),
+			       drbd_conn_str(ns.conn));
+	if (ns.disk != os.disk)
+		pbp += sprintf(pbp, "disk( %s -> %s ) ",
+			       drbd_disk_str(os.disk),
+			       drbd_disk_str(ns.disk));
+	if (ns.pdsk != os.pdsk)
+		pbp += sprintf(pbp, "pdsk( %s -> %s ) ",
+			       drbd_disk_str(os.pdsk),
+			       drbd_disk_str(ns.pdsk));
+	if (is_susp(ns) != is_susp(os))
+		pbp += sprintf(pbp, "susp( %d -> %d ) ",
+			       is_susp(os),
+			       is_susp(ns));
+	if (ns.aftr_isp != os.aftr_isp)
+		pbp += sprintf(pbp, "aftr_isp( %d -> %d ) ",
+			       os.aftr_isp,
+			       ns.aftr_isp);
+	if (ns.peer_isp != os.peer_isp)
+		pbp += sprintf(pbp, "peer_isp( %d -> %d ) ",
+			       os.peer_isp,
+			       ns.peer_isp);
+	if (ns.user_isp != os.user_isp)
+		pbp += sprintf(pbp, "user_isp( %d -> %d ) ",
+			       os.user_isp,
+			       ns.user_isp);
+	dev_info(DEV, "%s\n", pb);
 	}
 
 	/* solve the race between becoming unconfigured,
@@ -1074,6 +1142,10 @@
 		atomic_inc(&mdev->local_cnt);
 
 	mdev->state = ns;
+
+	if (os.disk == D_ATTACHING && ns.disk >= D_NEGOTIATING)
+		drbd_print_uuids(mdev, "attached to UUIDs");
+
 	wake_up(&mdev->misc_wait);
 	wake_up(&mdev->state_wait);
 
@@ -1081,7 +1153,7 @@
 	if ((os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) &&
 	    ns.conn < C_CONNECTED) {
 		mdev->ov_start_sector =
-			BM_BIT_TO_SECT(mdev->rs_total - mdev->ov_left);
+			BM_BIT_TO_SECT(drbd_bm_bits(mdev) - mdev->ov_left);
 		dev_info(DEV, "Online Verify reached sector %llu\n",
 			(unsigned long long)mdev->ov_start_sector);
 	}
@@ -1106,14 +1178,7 @@
 		unsigned long now = jiffies;
 		int i;
 
-		mdev->ov_position = 0;
-		mdev->rs_total = drbd_bm_bits(mdev);
-		if (mdev->agreed_pro_version >= 90)
-			set_ov_position(mdev, ns.conn);
-		else
-			mdev->ov_start_sector = 0;
-		mdev->ov_left = mdev->rs_total
-			      - BM_SECT_TO_BIT(mdev->ov_position);
+		set_ov_position(mdev, ns.conn);
 		mdev->rs_start = now;
 		mdev->rs_last_events = 0;
 		mdev->rs_last_sect_ev = 0;
@@ -1121,10 +1186,12 @@
 		mdev->ov_last_oos_start = 0;
 
 		for (i = 0; i < DRBD_SYNC_MARKS; i++) {
-			mdev->rs_mark_left[i] = mdev->rs_total;
+			mdev->rs_mark_left[i] = mdev->ov_left;
 			mdev->rs_mark_time[i] = now;
 		}
 
+		drbd_rs_controller_reset(mdev);
+
 		if (ns.conn == C_VERIFY_S) {
 			dev_info(DEV, "Starting Online Verify from sector %llu\n",
 					(unsigned long long)mdev->ov_position);
@@ -1228,6 +1295,26 @@
 	}
 }
 
+int drbd_bitmap_io_from_worker(struct drbd_conf *mdev,
+		int (*io_fn)(struct drbd_conf *),
+		char *why, enum bm_flag flags)
+{
+	int rv;
+
+	D_ASSERT(current == mdev->worker.task);
+
+	/* open coded non-blocking drbd_suspend_io(mdev); */
+	set_bit(SUSPEND_IO, &mdev->flags);
+
+	drbd_bm_lock(mdev, why, flags);
+	rv = io_fn(mdev);
+	drbd_bm_unlock(mdev);
+
+	drbd_resume_io(mdev);
+
+	return rv;
+}
+
 /**
  * after_state_ch() - Perform after state change actions that may sleep
  * @mdev:	DRBD device.
@@ -1266,16 +1353,14 @@
 
 	nsm.i = -1;
 	if (ns.susp_nod) {
-		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED) {
-			if (ns.conn == C_CONNECTED)
-				what = resend, nsm.susp_nod = 0;
-			else /* ns.conn > C_CONNECTED */
-				dev_err(DEV, "Unexpected Resynd going on!\n");
-		}
+		if (os.conn < C_CONNECTED && ns.conn >= C_CONNECTED)
+			what = resend;
 
 		if (os.disk == D_ATTACHING && ns.disk > D_ATTACHING)
-			what = restart_frozen_disk_io, nsm.susp_nod = 0;
+			what = restart_frozen_disk_io;
 
+		if (what != nothing)
+			nsm.susp_nod = 0;
 	}
 
 	if (ns.susp_fen) {
@@ -1306,13 +1391,30 @@
 		spin_unlock_irq(&mdev->req_lock);
 	}
 
+	/* Became sync source.  With protocol >= 96, we still need to send out
+	 * the sync uuid now. Need to do that before any drbd_send_state, or
+	 * the other side may go "paused sync" before receiving the sync uuids,
+	 * which is unexpected. */
+	if ((os.conn != C_SYNC_SOURCE && os.conn != C_PAUSED_SYNC_S) &&
+	    (ns.conn == C_SYNC_SOURCE || ns.conn == C_PAUSED_SYNC_S) &&
+	    mdev->agreed_pro_version >= 96 && get_ldev(mdev)) {
+		drbd_gen_and_send_sync_uuid(mdev);
+		put_ldev(mdev);
+	}
+
 	/* Do not change the order of the if above and the two below... */
 	if (os.pdsk == D_DISKLESS && ns.pdsk > D_DISKLESS) {      /* attach on the peer */
 		drbd_send_uuids(mdev);
 		drbd_send_state(mdev);
 	}
-	if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S)
-		drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL, "send_bitmap (WFBitMapS)");
+	/* No point in queuing send_bitmap if we don't have a connection
+	 * anymore, so check also the _current_ state, not only the new state
+	 * at the time this work was queued. */
+	if (os.conn != C_WF_BITMAP_S && ns.conn == C_WF_BITMAP_S &&
+	    mdev->state.conn == C_WF_BITMAP_S)
+		drbd_queue_bitmap_io(mdev, &drbd_send_bitmap, NULL,
+				"send_bitmap (WFBitMapS)",
+				BM_LOCKED_TEST_ALLOWED);
 
 	/* Lost contact to peer's copy of the data */
 	if ((os.pdsk >= D_INCONSISTENT &&
@@ -1343,7 +1445,23 @@
 
 		/* D_DISKLESS Peer becomes secondary */
 		if (os.peer == R_PRIMARY && ns.peer == R_SECONDARY)
-			drbd_al_to_on_disk_bm(mdev);
+			/* We may still be Primary ourselves.
+			 * No harm done if the bitmap still changes,
+			 * redirtied pages will follow later. */
+			drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+				"demote diskless peer", BM_LOCKED_SET_ALLOWED);
+		put_ldev(mdev);
+	}
+
+	/* Write out all changed bits on demote.
+	 * Though, no need to da that just yet
+	 * if there is a resync going on still */
+	if (os.role == R_PRIMARY && ns.role == R_SECONDARY &&
+		mdev->state.conn <= C_CONNECTED && get_ldev(mdev)) {
+		/* No changes to the bitmap expected this time, so assert that,
+		 * even though no harm was done if it did change. */
+		drbd_bitmap_io_from_worker(mdev, &drbd_bm_write,
+				"demote", BM_LOCKED_TEST_ALLOWED);
 		put_ldev(mdev);
 	}
 
@@ -1371,15 +1489,23 @@
 	if (os.conn == C_WF_REPORT_PARAMS && ns.conn >= C_CONNECTED)
 		drbd_send_state(mdev);
 
+	if (os.conn != C_AHEAD && ns.conn == C_AHEAD)
+		drbd_send_state(mdev);
+
 	/* We are in the progress to start a full sync... */
 	if ((os.conn != C_STARTING_SYNC_T && ns.conn == C_STARTING_SYNC_T) ||
 	    (os.conn != C_STARTING_SYNC_S && ns.conn == C_STARTING_SYNC_S))
-		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, &abw_start_sync, "set_n_write from StartingSync");
+		/* no other bitmap changes expected during this phase */
+		drbd_queue_bitmap_io(mdev,
+			&drbd_bmio_set_n_write, &abw_start_sync,
+			"set_n_write from StartingSync", BM_LOCKED_TEST_ALLOWED);
 
 	/* We are invalidating our self... */
 	if (os.conn < C_CONNECTED && ns.conn < C_CONNECTED &&
 	    os.disk > D_INCONSISTENT && ns.disk == D_INCONSISTENT)
-		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL, "set_n_write from invalidate");
+		/* other bitmap operation expected during this phase */
+		drbd_queue_bitmap_io(mdev, &drbd_bmio_set_n_write, NULL,
+			"set_n_write from invalidate", BM_LOCKED_MASK);
 
 	/* first half of local IO error, failure to attach,
 	 * or administrative detach */
@@ -1434,10 +1560,8 @@
 
 		if (drbd_send_state(mdev))
 			dev_warn(DEV, "Notified peer that I'm now diskless.\n");
-		else
-			dev_err(DEV, "Sending state for being diskless failed\n");
 		/* corresponding get_ldev in __drbd_set_state
-		 * this may finaly trigger drbd_ldev_destroy. */
+		 * this may finally trigger drbd_ldev_destroy. */
 		put_ldev(mdev);
 	}
 
@@ -1459,6 +1583,19 @@
 	if (os.disk < D_UP_TO_DATE && os.conn >= C_SYNC_SOURCE && ns.conn == C_CONNECTED)
 		drbd_send_state(mdev);
 
+	/* This triggers bitmap writeout of potentially still unwritten pages
+	 * if the resync finished cleanly, or aborted because of peer disk
+	 * failure, or because of connection loss.
+	 * For resync aborted because of local disk failure, we cannot do
+	 * any bitmap writeout anymore.
+	 * No harm done if some bits change during this phase.
+	 */
+	if (os.conn > C_CONNECTED && ns.conn <= C_CONNECTED && get_ldev(mdev)) {
+		drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL,
+			"write from resync_finished", BM_LOCKED_SET_ALLOWED);
+		put_ldev(mdev);
+	}
+
 	/* free tl_hash if we Got thawed and are C_STANDALONE */
 	if (ns.conn == C_STANDALONE && !is_susp(ns) && mdev->tl_hash)
 		drbd_free_tl_hash(mdev);
@@ -1559,7 +1696,7 @@
 		if (!try_module_get(THIS_MODULE)) {
 			dev_err(DEV, "Failed to get module reference in drbd_thread_start\n");
 			spin_unlock_irqrestore(&thi->t_lock, flags);
-			return FALSE;
+			return false;
 		}
 
 		init_completion(&thi->stop);
@@ -1576,7 +1713,7 @@
 			dev_err(DEV, "Couldn't start thread\n");
 
 			module_put(THIS_MODULE);
-			return FALSE;
+			return false;
 		}
 		spin_lock_irqsave(&thi->t_lock, flags);
 		thi->task = nt;
@@ -1596,7 +1733,7 @@
 		break;
 	}
 
-	return TRUE;
+	return true;
 }
 
 
@@ -1694,8 +1831,8 @@
 {
 	int sent, ok;
 
-	ERR_IF(!h) return FALSE;
-	ERR_IF(!size) return FALSE;
+	ERR_IF(!h) return false;
+	ERR_IF(!size) return false;
 
 	h->magic   = BE_DRBD_MAGIC;
 	h->command = cpu_to_be16(cmd);
@@ -1704,8 +1841,8 @@
 	sent = drbd_send(mdev, sock, h, size, msg_flags);
 
 	ok = (sent == size);
-	if (!ok)
-		dev_err(DEV, "short sent %s size=%d sent=%d\n",
+	if (!ok && !signal_pending(current))
+		dev_warn(DEV, "short sent %s size=%d sent=%d\n",
 		    cmdname(cmd), (int)size, sent);
 	return ok;
 }
@@ -1840,7 +1977,7 @@
 		else {
 			dev_err(DEV, "--dry-run is not supported by peer");
 			kfree(p);
-			return 0;
+			return -1;
 		}
 	}
 	p->conn_flags    = cpu_to_be32(cf);
@@ -1888,12 +2025,36 @@
 	return _drbd_send_uuids(mdev, 8);
 }
 
+void drbd_print_uuids(struct drbd_conf *mdev, const char *text)
+{
+	if (get_ldev_if_state(mdev, D_NEGOTIATING)) {
+		u64 *uuid = mdev->ldev->md.uuid;
+		dev_info(DEV, "%s %016llX:%016llX:%016llX:%016llX\n",
+		     text,
+		     (unsigned long long)uuid[UI_CURRENT],
+		     (unsigned long long)uuid[UI_BITMAP],
+		     (unsigned long long)uuid[UI_HISTORY_START],
+		     (unsigned long long)uuid[UI_HISTORY_END]);
+		put_ldev(mdev);
+	} else {
+		dev_info(DEV, "%s effective data uuid: %016llX\n",
+				text,
+				(unsigned long long)mdev->ed_uuid);
+	}
+}
 
-int drbd_send_sync_uuid(struct drbd_conf *mdev, u64 val)
+int drbd_gen_and_send_sync_uuid(struct drbd_conf *mdev)
 {
 	struct p_rs_uuid p;
+	u64 uuid;
 
-	p.uuid = cpu_to_be64(val);
+	D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
+
+	uuid = mdev->ldev->md.uuid[UI_BITMAP] + UUID_NEW_BM_OFFSET;
+	drbd_uuid_set(mdev, UI_BITMAP, uuid);
+	drbd_print_uuids(mdev, "updated sync UUID");
+	drbd_md_sync(mdev);
+	p.uuid = cpu_to_be64(uuid);
 
 	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_SYNC_UUID,
 			     (struct p_header80 *)&p, sizeof(p));
@@ -1921,7 +2082,7 @@
 	p.d_size = cpu_to_be64(d_size);
 	p.u_size = cpu_to_be64(u_size);
 	p.c_size = cpu_to_be64(trigger_reply ? 0 : drbd_get_capacity(mdev->this_bdev));
-	p.max_segment_size = cpu_to_be32(queue_max_segment_size(mdev->rq_queue));
+	p.max_bio_size = cpu_to_be32(queue_max_hw_sectors(mdev->rq_queue) << 9);
 	p.queue_order_type = cpu_to_be16(q_order_type);
 	p.dds_flags = cpu_to_be16(flags);
 
@@ -1972,7 +2133,7 @@
 			     (struct p_header80 *)&p, sizeof(p));
 }
 
-int drbd_send_sr_reply(struct drbd_conf *mdev, int retcode)
+int drbd_send_sr_reply(struct drbd_conf *mdev, enum drbd_state_rv retcode)
 {
 	struct p_req_state_reply p;
 
@@ -2076,9 +2237,15 @@
 	return len;
 }
 
-enum { OK, FAILED, DONE }
+/**
+ * send_bitmap_rle_or_plain
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 send_bitmap_rle_or_plain(struct drbd_conf *mdev,
-	struct p_header80 *h, struct bm_xfer_ctx *c)
+			 struct p_header80 *h, struct bm_xfer_ctx *c)
 {
 	struct p_compressed_bm *p = (void*)h;
 	unsigned long num_words;
@@ -2088,7 +2255,7 @@
 	len = fill_bitmap_rle_bits(mdev, p, c);
 
 	if (len < 0)
-		return FAILED;
+		return -EIO;
 
 	if (len) {
 		DCBP_set_code(p, RLE_VLI_Bits);
@@ -2118,11 +2285,14 @@
 		if (c->bit_offset > c->bm_bits)
 			c->bit_offset = c->bm_bits;
 	}
-	ok = ok ? ((len == 0) ? DONE : OK) : FAILED;
-
-	if (ok == DONE)
-		INFO_bm_xfer_stats(mdev, "send", c);
-	return ok;
+	if (ok) {
+		if (len == 0) {
+			INFO_bm_xfer_stats(mdev, "send", c);
+			return 0;
+		} else
+			return 1;
+	}
+	return -EIO;
 }
 
 /* See the comment at receive_bitmap() */
@@ -2130,16 +2300,16 @@
 {
 	struct bm_xfer_ctx c;
 	struct p_header80 *p;
-	int ret;
+	int err;
 
-	ERR_IF(!mdev->bitmap) return FALSE;
+	ERR_IF(!mdev->bitmap) return false;
 
 	/* maybe we should use some per thread scratch page,
 	 * and allocate that during initial device creation? */
 	p = (struct p_header80 *) __get_free_page(GFP_NOIO);
 	if (!p) {
 		dev_err(DEV, "failed to allocate one page buffer in %s\n", __func__);
-		return FALSE;
+		return false;
 	}
 
 	if (get_ldev(mdev)) {
@@ -2165,11 +2335,11 @@
 	};
 
 	do {
-		ret = send_bitmap_rle_or_plain(mdev, p, &c);
-	} while (ret == OK);
+		err = send_bitmap_rle_or_plain(mdev, p, &c);
+	} while (err > 0);
 
 	free_page((unsigned long) p);
-	return (ret == DONE);
+	return err == 0;
 }
 
 int drbd_send_bitmap(struct drbd_conf *mdev)
@@ -2192,7 +2362,7 @@
 	p.set_size = cpu_to_be32(set_size);
 
 	if (mdev->state.conn < C_CONNECTED)
-		return FALSE;
+		return false;
 	ok = drbd_send_cmd(mdev, USE_META_SOCKET, P_BARRIER_ACK,
 			(struct p_header80 *)&p, sizeof(p));
 	return ok;
@@ -2220,7 +2390,7 @@
 	p.seq_num  = cpu_to_be32(atomic_add_return(1, &mdev->packet_seq));
 
 	if (!mdev->meta.socket || mdev->state.conn < C_CONNECTED)
-		return FALSE;
+		return false;
 	ok = drbd_send_cmd(mdev, USE_META_SOCKET, cmd,
 				(struct p_header80 *)&p, sizeof(p));
 	return ok;
@@ -2326,8 +2496,8 @@
 }
 
 /* called on sndtimeo
- * returns FALSE if we should retry,
- * TRUE if we think connection is dead
+ * returns false if we should retry,
+ * true if we think connection is dead
  */
 static int we_should_drop_the_connection(struct drbd_conf *mdev, struct socket *sock)
 {
@@ -2340,7 +2510,7 @@
 		|| mdev->state.conn < C_CONNECTED;
 
 	if (drop_it)
-		return TRUE;
+		return true;
 
 	drop_it = !--mdev->ko_count;
 	if (!drop_it) {
@@ -2477,12 +2647,11 @@
 {
 	if (mdev->agreed_pro_version >= 95)
 		return  (bi_rw & REQ_SYNC ? DP_RW_SYNC : 0) |
-			(bi_rw & REQ_UNPLUG ? DP_UNPLUG : 0) |
 			(bi_rw & REQ_FUA ? DP_FUA : 0) |
 			(bi_rw & REQ_FLUSH ? DP_FLUSH : 0) |
 			(bi_rw & REQ_DISCARD ? DP_DISCARD : 0);
 	else
-		return bi_rw & (REQ_SYNC | REQ_UNPLUG) ? DP_RW_SYNC : 0;
+		return bi_rw & REQ_SYNC ? DP_RW_SYNC : 0;
 }
 
 /* Used to send write requests
@@ -2532,13 +2701,39 @@
 	if (ok && dgs) {
 		dgb = mdev->int_dig_out;
 		drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, dgb);
-		ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
+		ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
 	}
 	if (ok) {
-		if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
+		/* For protocol A, we have to memcpy the payload into
+		 * socket buffers, as we may complete right away
+		 * as soon as we handed it over to tcp, at which point the data
+		 * pages may become invalid.
+		 *
+		 * For data-integrity enabled, we copy it as well, so we can be
+		 * sure that even if the bio pages may still be modified, it
+		 * won't change the data on the wire, thus if the digest checks
+		 * out ok after sending on this side, but does not fit on the
+		 * receiving side, we sure have detected corruption elsewhere.
+		 */
+		if (mdev->net_conf->wire_protocol == DRBD_PROT_A || dgs)
 			ok = _drbd_send_bio(mdev, req->master_bio);
 		else
 			ok = _drbd_send_zc_bio(mdev, req->master_bio);
+
+		/* double check digest, sometimes buffers have been modified in flight. */
+		if (dgs > 0 && dgs <= 64) {
+			/* 64 byte, 512 bit, is the larges digest size
+			 * currently supported in kernel crypto. */
+			unsigned char digest[64];
+			drbd_csum_bio(mdev, mdev->integrity_w_tfm, req->master_bio, digest);
+			if (memcmp(mdev->int_dig_out, digest, dgs)) {
+				dev_warn(DEV,
+					"Digest mismatch, buffer modified by upper layers during write: %llus +%u\n",
+					(unsigned long long)req->sector, req->size);
+			}
+		} /* else if (dgs > 64) {
+		     ... Be noisy about digest too large ...
+		} */
 	}
 
 	drbd_put_data_sock(mdev);
@@ -2588,7 +2783,7 @@
 	if (ok && dgs) {
 		dgb = mdev->int_dig_out;
 		drbd_csum_ee(mdev, mdev->integrity_w_tfm, e, dgb);
-		ok = drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
+		ok = dgs == drbd_send(mdev, mdev->data.socket, dgb, dgs, 0);
 	}
 	if (ok)
 		ok = _drbd_send_zc_ee(mdev, e);
@@ -2598,6 +2793,16 @@
 	return ok;
 }
 
+int drbd_send_oos(struct drbd_conf *mdev, struct drbd_request *req)
+{
+	struct p_block_desc p;
+
+	p.sector  = cpu_to_be64(req->sector);
+	p.blksize = cpu_to_be32(req->size);
+
+	return drbd_send_cmd(mdev, USE_DATA_SOCKET, P_OUT_OF_SYNC, &p.head, sizeof(p));
+}
+
 /*
   drbd_send distinguishes two cases:
 
@@ -2719,35 +2924,6 @@
 	return 0;
 }
 
-static void drbd_unplug_fn(struct request_queue *q)
-{
-	struct drbd_conf *mdev = q->queuedata;
-
-	/* unplug FIRST */
-	spin_lock_irq(q->queue_lock);
-	blk_remove_plug(q);
-	spin_unlock_irq(q->queue_lock);
-
-	/* only if connected */
-	spin_lock_irq(&mdev->req_lock);
-	if (mdev->state.pdsk >= D_INCONSISTENT && mdev->state.conn >= C_CONNECTED) {
-		D_ASSERT(mdev->state.role == R_PRIMARY);
-		if (test_and_clear_bit(UNPLUG_REMOTE, &mdev->flags)) {
-			/* add to the data.work queue,
-			 * unless already queued.
-			 * XXX this might be a good addition to drbd_queue_work
-			 * anyways, to detect "double queuing" ... */
-			if (list_empty(&mdev->unplug_work.list))
-				drbd_queue_work(&mdev->data.work,
-						&mdev->unplug_work);
-		}
-	}
-	spin_unlock_irq(&mdev->req_lock);
-
-	if (mdev->state.disk >= D_INCONSISTENT)
-		drbd_kick_lo(mdev);
-}
-
 static void drbd_set_defaults(struct drbd_conf *mdev)
 {
 	/* This way we get a compile error when sync_conf grows,
@@ -2800,6 +2976,7 @@
 	atomic_set(&mdev->pp_in_use_by_net, 0);
 	atomic_set(&mdev->rs_sect_in, 0);
 	atomic_set(&mdev->rs_sect_ev, 0);
+	atomic_set(&mdev->ap_in_flight, 0);
 
 	mutex_init(&mdev->md_io_mutex);
 	mutex_init(&mdev->data.mutex);
@@ -2828,19 +3005,27 @@
 	INIT_LIST_HEAD(&mdev->unplug_work.list);
 	INIT_LIST_HEAD(&mdev->go_diskless.list);
 	INIT_LIST_HEAD(&mdev->md_sync_work.list);
+	INIT_LIST_HEAD(&mdev->start_resync_work.list);
 	INIT_LIST_HEAD(&mdev->bm_io_work.w.list);
 
-	mdev->resync_work.cb  = w_resync_inactive;
+	mdev->resync_work.cb  = w_resync_timer;
 	mdev->unplug_work.cb  = w_send_write_hint;
 	mdev->go_diskless.cb  = w_go_diskless;
 	mdev->md_sync_work.cb = w_md_sync;
 	mdev->bm_io_work.w.cb = w_bitmap_io;
+	mdev->start_resync_work.cb = w_start_resync;
 	init_timer(&mdev->resync_timer);
 	init_timer(&mdev->md_sync_timer);
+	init_timer(&mdev->start_resync_timer);
+	init_timer(&mdev->request_timer);
 	mdev->resync_timer.function = resync_timer_fn;
 	mdev->resync_timer.data = (unsigned long) mdev;
 	mdev->md_sync_timer.function = md_sync_timer_fn;
 	mdev->md_sync_timer.data = (unsigned long) mdev;
+	mdev->start_resync_timer.function = start_resync_timer_fn;
+	mdev->start_resync_timer.data = (unsigned long) mdev;
+	mdev->request_timer.function = request_timer_fn;
+	mdev->request_timer.data = (unsigned long) mdev;
 
 	init_waitqueue_head(&mdev->misc_wait);
 	init_waitqueue_head(&mdev->state_wait);
@@ -2911,6 +3096,8 @@
 	D_ASSERT(list_empty(&mdev->resync_work.list));
 	D_ASSERT(list_empty(&mdev->unplug_work.list));
 	D_ASSERT(list_empty(&mdev->go_diskless.list));
+
+	drbd_set_defaults(mdev);
 }
 
 
@@ -2953,7 +3140,7 @@
 static int drbd_create_mempools(void)
 {
 	struct page *page;
-	const int number = (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE) * minor_count;
+	const int number = (DRBD_MAX_BIO_SIZE/PAGE_SIZE) * minor_count;
 	int i;
 
 	/* prepare our caches and mempools */
@@ -3117,11 +3304,20 @@
 
 	unregister_reboot_notifier(&drbd_notifier);
 
+	/* first remove proc,
+	 * drbdsetup uses it's presence to detect
+	 * whether DRBD is loaded.
+	 * If we would get stuck in proc removal,
+	 * but have netlink already deregistered,
+	 * some drbdsetup commands may wait forever
+	 * for an answer.
+	 */
+	if (drbd_proc)
+		remove_proc_entry("drbd", NULL);
+
 	drbd_nl_cleanup();
 
 	if (minor_table) {
-		if (drbd_proc)
-			remove_proc_entry("drbd", NULL);
 		i = minor_count;
 		while (i--)
 			drbd_delete_device(i);
@@ -3149,7 +3345,7 @@
 	char reason = '-';
 	int r = 0;
 
-	if (!__inc_ap_bio_cond(mdev)) {
+	if (!may_inc_ap_bio(mdev)) {
 		/* DRBD has frozen IO */
 		r = bdi_bits;
 		reason = 'd';
@@ -3202,7 +3398,7 @@
 		goto out_no_disk;
 	mdev->vdisk = disk;
 
-	set_disk_ro(disk, TRUE);
+	set_disk_ro(disk, true);
 
 	disk->queue = q;
 	disk->major = DRBD_MAJOR;
@@ -3218,13 +3414,11 @@
 	q->backing_dev_info.congested_fn = drbd_congested;
 	q->backing_dev_info.congested_data = mdev;
 
-	blk_queue_make_request(q, drbd_make_request_26);
-	blk_queue_max_segment_size(q, DRBD_MAX_SEGMENT_SIZE);
+	blk_queue_make_request(q, drbd_make_request);
+	blk_queue_max_hw_sectors(q, DRBD_MAX_BIO_SIZE >> 9);
 	blk_queue_bounce_limit(q, BLK_BOUNCE_ANY);
 	blk_queue_merge_bvec(q, drbd_merge_bvec);
-	q->queue_lock = &mdev->req_lock; /* needed since we use */
-		/* plugging on a queue, that actually has no requests! */
-	q->unplug_fn = drbd_unplug_fn;
+	q->queue_lock = &mdev->req_lock;
 
 	mdev->md_io_page = alloc_page(GFP_KERNEL);
 	if (!mdev->md_io_page)
@@ -3283,6 +3477,7 @@
 	put_disk(mdev->vdisk);
 	blk_cleanup_queue(mdev->rq_queue);
 	free_cpumask_var(mdev->cpu_mask);
+	drbd_free_tl_hash(mdev);
 	kfree(mdev);
 }
 
@@ -3298,7 +3493,7 @@
 		return -EINVAL;
 	}
 
-	if (1 > minor_count || minor_count > 255) {
+	if (minor_count < DRBD_MINOR_COUNT_MIN || minor_count > DRBD_MINOR_COUNT_MAX) {
 		printk(KERN_ERR
 			"drbd: invalid minor_count (%d)\n", minor_count);
 #ifdef MODULE
@@ -3480,7 +3675,7 @@
 	if (!drbd_md_sync_page_io(mdev, mdev->ldev, sector, WRITE)) {
 		/* this was a try anyways ... */
 		dev_err(DEV, "meta data update failed!\n");
-		drbd_chk_io_error(mdev, 1, TRUE);
+		drbd_chk_io_error(mdev, 1, true);
 	}
 
 	/* Update mdev->ldev->md.la_size_sect,
@@ -3496,7 +3691,7 @@
  * @mdev:	DRBD device.
  * @bdev:	Device from which the meta data should be read in.
  *
- * Return 0 (NO_ERROR) on success, and an enum drbd_ret_codes in case
+ * Return 0 (NO_ERROR) on success, and an enum drbd_ret_code in case
  * something goes wrong.  Currently only: ERR_IO_MD_DISK, ERR_MD_INVALID.
  */
 int drbd_md_read(struct drbd_conf *mdev, struct drbd_backing_dev *bdev)
@@ -3511,7 +3706,7 @@
 	buffer = (struct meta_data_on_disk *)page_address(mdev->md_io_page);
 
 	if (!drbd_md_sync_page_io(mdev, bdev, bdev->md.md_offset, READ)) {
-		/* NOTE: cant do normal error processing here as this is
+		/* NOTE: can't do normal error processing here as this is
 		   called BEFORE disk is attached */
 		dev_err(DEV, "Error while reading metadata.\n");
 		rv = ERR_IO_MD_DISK;
@@ -3566,28 +3761,6 @@
 	return rv;
 }
 
-static void debug_drbd_uuid(struct drbd_conf *mdev, enum drbd_uuid_index index)
-{
-	static char *uuid_str[UI_EXTENDED_SIZE] = {
-		[UI_CURRENT] = "CURRENT",
-		[UI_BITMAP] = "BITMAP",
-		[UI_HISTORY_START] = "HISTORY_START",
-		[UI_HISTORY_END] = "HISTORY_END",
-		[UI_SIZE] = "SIZE",
-		[UI_FLAGS] = "FLAGS",
-	};
-
-	if (index >= UI_EXTENDED_SIZE) {
-		dev_warn(DEV, " uuid_index >= EXTENDED_SIZE\n");
-		return;
-	}
-
-	dynamic_dev_dbg(DEV, " uuid[%s] now %016llX\n",
-		 uuid_str[index],
-		 (unsigned long long)mdev->ldev->md.uuid[index]);
-}
-
-
 /**
  * drbd_md_mark_dirty() - Mark meta data super block as dirty
  * @mdev:	DRBD device.
@@ -3617,10 +3790,8 @@
 {
 	int i;
 
-	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++) {
+	for (i = UI_HISTORY_START; i < UI_HISTORY_END; i++)
 		mdev->ldev->md.uuid[i+1] = mdev->ldev->md.uuid[i];
-		debug_drbd_uuid(mdev, i+1);
-	}
 }
 
 void _drbd_uuid_set(struct drbd_conf *mdev, int idx, u64 val) __must_hold(local)
@@ -3635,7 +3806,6 @@
 	}
 
 	mdev->ldev->md.uuid[idx] = val;
-	debug_drbd_uuid(mdev, idx);
 	drbd_md_mark_dirty(mdev);
 }
 
@@ -3645,7 +3815,6 @@
 	if (mdev->ldev->md.uuid[idx]) {
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[idx];
-		debug_drbd_uuid(mdev, UI_HISTORY_START);
 	}
 	_drbd_uuid_set(mdev, idx, val);
 }
@@ -3660,14 +3829,16 @@
 void drbd_uuid_new_current(struct drbd_conf *mdev) __must_hold(local)
 {
 	u64 val;
+	unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+
+	if (bm_uuid)
+		dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
 
-	dev_info(DEV, "Creating new current UUID\n");
-	D_ASSERT(mdev->ldev->md.uuid[UI_BITMAP] == 0);
 	mdev->ldev->md.uuid[UI_BITMAP] = mdev->ldev->md.uuid[UI_CURRENT];
-	debug_drbd_uuid(mdev, UI_BITMAP);
 
 	get_random_bytes(&val, sizeof(u64));
 	_drbd_uuid_set(mdev, UI_CURRENT, val);
+	drbd_print_uuids(mdev, "new current UUID");
 	/* get it to stable storage _now_ */
 	drbd_md_sync(mdev);
 }
@@ -3681,16 +3852,12 @@
 		drbd_uuid_move_history(mdev);
 		mdev->ldev->md.uuid[UI_HISTORY_START] = mdev->ldev->md.uuid[UI_BITMAP];
 		mdev->ldev->md.uuid[UI_BITMAP] = 0;
-		debug_drbd_uuid(mdev, UI_HISTORY_START);
-		debug_drbd_uuid(mdev, UI_BITMAP);
 	} else {
-		if (mdev->ldev->md.uuid[UI_BITMAP])
-			dev_warn(DEV, "bm UUID already set");
-
-		mdev->ldev->md.uuid[UI_BITMAP] = val;
-		mdev->ldev->md.uuid[UI_BITMAP] &= ~((u64)1);
+		unsigned long long bm_uuid = mdev->ldev->md.uuid[UI_BITMAP];
+		if (bm_uuid)
+			dev_warn(DEV, "bm UUID was already set: %llX\n", bm_uuid);
 
-		debug_drbd_uuid(mdev, UI_BITMAP);
+		mdev->ldev->md.uuid[UI_BITMAP] = val & ~((u64)1);
 	}
 	drbd_md_mark_dirty(mdev);
 }
@@ -3746,15 +3913,19 @@
 static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused)
 {
 	struct bm_io_work *work = container_of(w, struct bm_io_work, w);
-	int rv;
+	int rv = -EIO;
 
 	D_ASSERT(atomic_read(&mdev->ap_bio_cnt) == 0);
 
-	drbd_bm_lock(mdev, work->why);
-	rv = work->io_fn(mdev);
-	drbd_bm_unlock(mdev);
+	if (get_ldev(mdev)) {
+		drbd_bm_lock(mdev, work->why, work->flags);
+		rv = work->io_fn(mdev);
+		drbd_bm_unlock(mdev);
+		put_ldev(mdev);
+	}
 
 	clear_bit(BITMAP_IO, &mdev->flags);
+	smp_mb__after_clear_bit();
 	wake_up(&mdev->misc_wait);
 
 	if (work->done)
@@ -3762,6 +3933,7 @@
 
 	clear_bit(BITMAP_IO_QUEUED, &mdev->flags);
 	work->why = NULL;
+	work->flags = 0;
 
 	return 1;
 }
@@ -3816,7 +3988,7 @@
 void drbd_queue_bitmap_io(struct drbd_conf *mdev,
 			  int (*io_fn)(struct drbd_conf *),
 			  void (*done)(struct drbd_conf *, int),
-			  char *why)
+			  char *why, enum bm_flag flags)
 {
 	D_ASSERT(current == mdev->worker.task);
 
@@ -3830,15 +4002,15 @@
 	mdev->bm_io_work.io_fn = io_fn;
 	mdev->bm_io_work.done = done;
 	mdev->bm_io_work.why = why;
+	mdev->bm_io_work.flags = flags;
 
+	spin_lock_irq(&mdev->req_lock);
 	set_bit(BITMAP_IO, &mdev->flags);
 	if (atomic_read(&mdev->ap_bio_cnt) == 0) {
-		if (list_empty(&mdev->bm_io_work.w.list)) {
-			set_bit(BITMAP_IO_QUEUED, &mdev->flags);
+		if (!test_and_set_bit(BITMAP_IO_QUEUED, &mdev->flags))
 			drbd_queue_work(&mdev->data.work, &mdev->bm_io_work.w);
-		} else
-			dev_err(DEV, "FIXME avoided double queuing bm_io_work\n");
 	}
+	spin_unlock_irq(&mdev->req_lock);
 }
 
 /**
@@ -3850,19 +4022,22 @@
  * freezes application IO while that the actual IO operations runs. This
  * functions MAY NOT be called from worker context.
  */
-int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *), char *why)
+int drbd_bitmap_io(struct drbd_conf *mdev, int (*io_fn)(struct drbd_conf *),
+		char *why, enum bm_flag flags)
 {
 	int rv;
 
 	D_ASSERT(current != mdev->worker.task);
 
-	drbd_suspend_io(mdev);
+	if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
+		drbd_suspend_io(mdev);
 
-	drbd_bm_lock(mdev, why);
+	drbd_bm_lock(mdev, why, flags);
 	rv = io_fn(mdev);
 	drbd_bm_unlock(mdev);
 
-	drbd_resume_io(mdev);
+	if ((flags & BM_LOCKED_SET_ALLOWED) == 0)
+		drbd_resume_io(mdev);
 
 	return rv;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_nl.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_nl.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_nl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_nl.c	2011-05-19 00:06:34.000000000 -0400
@@ -288,10 +288,11 @@
 		dev_err(DEV, "out of mem, failed to invoke fence-peer helper\n");
 }
 
-int drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
+enum drbd_state_rv
+drbd_set_role(struct drbd_conf *mdev, enum drbd_role new_role, int force)
 {
 	const int max_tries = 4;
-	int r = 0;
+	enum drbd_state_rv rv = SS_UNKNOWN_ERROR;
 	int try = 0;
 	int forced = 0;
 	union drbd_state mask, val;
@@ -306,17 +307,17 @@
 	val.i  = 0; val.role  = new_role;
 
 	while (try++ < max_tries) {
-		r = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE);
+		rv = _drbd_request_state(mdev, mask, val, CS_WAIT_COMPLETE);
 
 		/* in case we first succeeded to outdate,
 		 * but now suddenly could establish a connection */
-		if (r == SS_CW_FAILED_BY_PEER && mask.pdsk != 0) {
+		if (rv == SS_CW_FAILED_BY_PEER && mask.pdsk != 0) {
 			val.pdsk = 0;
 			mask.pdsk = 0;
 			continue;
 		}
 
-		if (r == SS_NO_UP_TO_DATE_DISK && force &&
+		if (rv == SS_NO_UP_TO_DATE_DISK && force &&
 		    (mdev->state.disk < D_UP_TO_DATE &&
 		     mdev->state.disk >= D_INCONSISTENT)) {
 			mask.disk = D_MASK;
@@ -325,7 +326,7 @@
 			continue;
 		}
 
-		if (r == SS_NO_UP_TO_DATE_DISK &&
+		if (rv == SS_NO_UP_TO_DATE_DISK &&
 		    mdev->state.disk == D_CONSISTENT && mask.pdsk == 0) {
 			D_ASSERT(mdev->state.pdsk == D_UNKNOWN);
 			nps = drbd_try_outdate_peer(mdev);
@@ -341,9 +342,9 @@
 			continue;
 		}
 
-		if (r == SS_NOTHING_TO_DO)
+		if (rv == SS_NOTHING_TO_DO)
 			goto fail;
-		if (r == SS_PRIMARY_NOP && mask.pdsk == 0) {
+		if (rv == SS_PRIMARY_NOP && mask.pdsk == 0) {
 			nps = drbd_try_outdate_peer(mdev);
 
 			if (force && nps > D_OUTDATED) {
@@ -356,25 +357,24 @@
 
 			continue;
 		}
-		if (r == SS_TWO_PRIMARIES) {
+		if (rv == SS_TWO_PRIMARIES) {
 			/* Maybe the peer is detected as dead very soon...
 			   retry at most once more in this case. */
-			__set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout((mdev->net_conf->ping_timeo+1)*HZ/10);
+			schedule_timeout_interruptible((mdev->net_conf->ping_timeo+1)*HZ/10);
 			if (try < max_tries)
 				try = max_tries - 1;
 			continue;
 		}
-		if (r < SS_SUCCESS) {
-			r = _drbd_request_state(mdev, mask, val,
+		if (rv < SS_SUCCESS) {
+			rv = _drbd_request_state(mdev, mask, val,
 						CS_VERBOSE + CS_WAIT_COMPLETE);
-			if (r < SS_SUCCESS)
+			if (rv < SS_SUCCESS)
 				goto fail;
 		}
 		break;
 	}
 
-	if (r < SS_SUCCESS)
+	if (rv < SS_SUCCESS)
 		goto fail;
 
 	if (forced)
@@ -384,7 +384,7 @@
 	wait_event(mdev->misc_wait, atomic_read(&mdev->ap_pending_cnt) == 0);
 
 	if (new_role == R_SECONDARY) {
-		set_disk_ro(mdev->vdisk, TRUE);
+		set_disk_ro(mdev->vdisk, true);
 		if (get_ldev(mdev)) {
 			mdev->ldev->md.uuid[UI_CURRENT] &= ~(u64)1;
 			put_ldev(mdev);
@@ -394,7 +394,7 @@
 			mdev->net_conf->want_lose = 0;
 			put_net_conf(mdev);
 		}
-		set_disk_ro(mdev->vdisk, FALSE);
+		set_disk_ro(mdev->vdisk, false);
 		if (get_ldev(mdev)) {
 			if (((mdev->state.conn < C_CONNECTED ||
 			       mdev->state.pdsk <= D_FAILED)
@@ -406,10 +406,8 @@
 		}
 	}
 
-	if ((new_role == R_SECONDARY) && get_ldev(mdev)) {
-		drbd_al_to_on_disk_bm(mdev);
-		put_ldev(mdev);
-	}
+	/* writeout of activity log covered areas of the bitmap
+	 * to stable storage done in after state change already */
 
 	if (mdev->state.conn >= C_WF_REPORT_PARAMS) {
 		/* if this was forced, we should consider sync */
@@ -423,7 +421,7 @@
 	kobject_uevent(&disk_to_dev(mdev->vdisk)->kobj, KOBJ_CHANGE);
  fail:
 	mutex_unlock(&mdev->state_mutex);
-	return r;
+	return rv;
 }
 
 static struct drbd_conf *ensure_mdev(int minor, int create)
@@ -528,17 +526,19 @@
 	}
 }
 
+/* input size is expected to be in KB */
 char *ppsize(char *buf, unsigned long long size)
 {
-	/* Needs 9 bytes at max. */
+	/* Needs 9 bytes at max including trailing NUL:
+	 * -1ULL ==> "16384 EB" */
 	static char units[] = { 'K', 'M', 'G', 'T', 'P', 'E' };
 	int base = 0;
-	while (size >= 10000) {
+	while (size >= 10000 && base < sizeof(units)-1) {
 		/* shift + round */
 		size = (size >> 10) + !!(size & (1<<9));
 		base++;
 	}
-	sprintf(buf, "%lu %cB", (long)size, units[base]);
+	sprintf(buf, "%u %cB", (unsigned)size, units[base]);
 
 	return buf;
 }
@@ -642,11 +642,19 @@
 		|| prev_size	   != mdev->ldev->md.md_size_sect;
 
 	if (la_size_changed || md_moved) {
+		int err;
+
 		drbd_al_shrink(mdev); /* All extents inactive. */
 		dev_info(DEV, "Writing the whole bitmap, %s\n",
 			 la_size_changed && md_moved ? "size changed and md moved" :
 			 la_size_changed ? "size changed" : "md moved");
-		rv = drbd_bitmap_io(mdev, &drbd_bm_write, "size changed"); /* does drbd_resume_io() ! */
+		/* next line implicitly does drbd_suspend_io()+drbd_resume_io() */
+		err = drbd_bitmap_io(mdev, &drbd_bm_write,
+				"size changed", BM_LOCKED_MASK);
+		if (err) {
+			rv = dev_size_error;
+			goto out;
+		}
 		drbd_md_mark_dirty(mdev);
 	}
 
@@ -765,22 +773,21 @@
 	return 0;
 }
 
-void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_seg_s) __must_hold(local)
+void drbd_setup_queue_param(struct drbd_conf *mdev, unsigned int max_bio_size) __must_hold(local)
 {
 	struct request_queue * const q = mdev->rq_queue;
 	struct request_queue * const b = mdev->ldev->backing_bdev->bd_disk->queue;
 	int max_segments = mdev->ldev->dc.max_bio_bvecs;
+	int max_hw_sectors = min(queue_max_hw_sectors(b), max_bio_size >> 9);
 
-	max_seg_s = min(queue_max_sectors(b) * queue_logical_block_size(b), max_seg_s);
-
-	blk_queue_max_hw_sectors(q, max_seg_s >> 9);
-	blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
-	blk_queue_max_segment_size(q, max_seg_s);
 	blk_queue_logical_block_size(q, 512);
-	blk_queue_segment_boundary(q, PAGE_SIZE-1);
-	blk_stack_limits(&q->limits, &b->limits, 0);
+	blk_queue_max_hw_sectors(q, max_hw_sectors);
+	/* This is the workaround for "bio would need to, but cannot, be split" */
+	blk_queue_max_segments(q, max_segments ? max_segments : BLK_MAX_SEGMENTS);
+	blk_queue_segment_boundary(q, PAGE_CACHE_SIZE-1);
+	blk_queue_stack_limits(q, b);
 
-	dev_info(DEV, "max_segment_size ( = BIO size ) = %u\n", queue_max_segment_size(q));
+	dev_info(DEV, "max BIO size = %u\n", queue_max_hw_sectors(q) << 9);
 
 	if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
 		dev_info(DEV, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
@@ -850,7 +857,7 @@
 static int drbd_nl_disk_conf(struct drbd_conf *mdev, struct drbd_nl_cfg_req *nlp,
 			     struct drbd_nl_cfg_reply *reply)
 {
-	enum drbd_ret_codes retcode;
+	enum drbd_ret_code retcode;
 	enum determine_dev_size dd;
 	sector_t max_possible_sectors;
 	sector_t min_md_device_sectors;
@@ -858,8 +865,8 @@
 	struct block_device *bdev;
 	struct lru_cache *resync_lru = NULL;
 	union drbd_state ns, os;
-	unsigned int max_seg_s;
-	int rv;
+	unsigned int max_bio_size;
+	enum drbd_state_rv rv;
 	int cp_discovered = 0;
 	int logical_block_size;
 
@@ -1005,9 +1012,10 @@
 	/* and for any other previously queued work */
 	drbd_flush_workqueue(mdev);
 
-	retcode = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
+	rv = _drbd_request_state(mdev, NS(disk, D_ATTACHING), CS_VERBOSE);
+	retcode = rv;  /* FIXME: Type mismatch. */
 	drbd_resume_io(mdev);
-	if (retcode < SS_SUCCESS)
+	if (rv < SS_SUCCESS)
 		goto fail;
 
 	if (!get_ldev_if_state(mdev, D_ATTACHING))
@@ -1109,20 +1117,20 @@
 	mdev->read_cnt = 0;
 	mdev->writ_cnt = 0;
 
-	max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+	max_bio_size = DRBD_MAX_BIO_SIZE;
 	if (mdev->state.conn == C_CONNECTED) {
 		/* We are Primary, Connected, and now attach a new local
 		 * backing store. We must not increase the user visible maximum
 		 * bio size on this device to something the peer may not be
 		 * able to handle. */
 		if (mdev->agreed_pro_version < 94)
-			max_seg_s = queue_max_segment_size(mdev->rq_queue);
+			max_bio_size = queue_max_hw_sectors(mdev->rq_queue) << 9;
 		else if (mdev->agreed_pro_version == 94)
-			max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+			max_bio_size = DRBD_MAX_SIZE_H80_PACKET;
 		/* else: drbd 8.3.9 and later, stay with default */
 	}
 
-	drbd_setup_queue_param(mdev, max_seg_s);
+	drbd_setup_queue_param(mdev, max_bio_size);
 
 	/* If I am currently not R_PRIMARY,
 	 * but meta data primary indicator is set,
@@ -1154,12 +1162,14 @@
 	if (drbd_md_test_flag(mdev->ldev, MDF_FULL_SYNC)) {
 		dev_info(DEV, "Assuming that all blocks are out of sync "
 		     "(aka FullSync)\n");
-		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from attaching")) {
+		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write,
+			"set_n_write from attaching", BM_LOCKED_MASK)) {
 			retcode = ERR_IO_MD_DISK;
 			goto force_diskless_dec;
 		}
 	} else {
-		if (drbd_bitmap_io(mdev, &drbd_bm_read, "read from attaching") < 0) {
+		if (drbd_bitmap_io(mdev, &drbd_bm_read,
+			"read from attaching", BM_LOCKED_MASK) < 0) {
 			retcode = ERR_IO_MD_DISK;
 			goto force_diskless_dec;
 		}
@@ -1167,7 +1177,11 @@
 
 	if (cp_discovered) {
 		drbd_al_apply_to_bm(mdev);
-		drbd_al_to_on_disk_bm(mdev);
+		if (drbd_bitmap_io(mdev, &drbd_bm_write,
+			"crashed primary apply AL", BM_LOCKED_MASK)) {
+			retcode = ERR_IO_MD_DISK;
+			goto force_diskless_dec;
+		}
 	}
 
 	if (_drbd_bm_total_weight(mdev) == drbd_bm_bits(mdev))
@@ -1279,7 +1293,7 @@
 			    struct drbd_nl_cfg_reply *reply)
 {
 	int i, ns;
-	enum drbd_ret_codes retcode;
+	enum drbd_ret_code retcode;
 	struct net_conf *new_conf = NULL;
 	struct crypto_hash *tfm = NULL;
 	struct crypto_hash *integrity_w_tfm = NULL;
@@ -1324,6 +1338,8 @@
 	new_conf->wire_protocol    = DRBD_PROT_C;
 	new_conf->ping_timeo	   = DRBD_PING_TIMEO_DEF;
 	new_conf->rr_conflict	   = DRBD_RR_CONFLICT_DEF;
+	new_conf->on_congestion    = DRBD_ON_CONGESTION_DEF;
+	new_conf->cong_extents     = DRBD_CONG_EXTENTS_DEF;
 
 	if (!net_conf_from_tags(mdev, nlp->tag_list, new_conf)) {
 		retcode = ERR_MANDATORY_TAG;
@@ -1345,6 +1361,11 @@
 		}
 	}
 
+	if (new_conf->on_congestion != OC_BLOCK && new_conf->wire_protocol != DRBD_PROT_A) {
+		retcode = ERR_CONG_NOT_PROTO_A;
+		goto fail;
+	}
+
 	if (mdev->state.role == R_PRIMARY && new_conf->want_lose) {
 		retcode = ERR_DISCARD;
 		goto fail;
@@ -1525,6 +1546,21 @@
 			      struct drbd_nl_cfg_reply *reply)
 {
 	int retcode;
+	struct disconnect dc;
+
+	memset(&dc, 0, sizeof(struct disconnect));
+	if (!disconnect_from_tags(mdev, nlp->tag_list, &dc)) {
+		retcode = ERR_MANDATORY_TAG;
+		goto fail;
+	}
+
+	if (dc.force) {
+		spin_lock_irq(&mdev->req_lock);
+		if (mdev->state.conn >= C_WF_CONNECTION)
+			_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), CS_HARD, NULL);
+		spin_unlock_irq(&mdev->req_lock);
+		goto done;
+	}
 
 	retcode = _drbd_request_state(mdev, NS(conn, C_DISCONNECTING), CS_ORDERED);
 
@@ -1842,6 +1878,10 @@
 {
 	int retcode;
 
+	/* If there is still bitmap IO pending, probably because of a previous
+	 * resync just being finished, wait for it before requesting a new resync. */
+	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
 	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_T), CS_ORDERED);
 
 	if (retcode < SS_SUCCESS && retcode != SS_NEED_CONNECTION)
@@ -1877,6 +1917,10 @@
 {
 	int retcode;
 
+	/* If there is still bitmap IO pending, probably because of a previous
+	 * resync just being finished, wait for it before requesting a new resync. */
+	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
 	retcode = _drbd_request_state(mdev, NS(conn, C_STARTING_SYNC_S), CS_ORDERED);
 
 	if (retcode < SS_SUCCESS) {
@@ -1885,9 +1929,9 @@
 			   into a full resync. */
 			retcode = drbd_request_state(mdev, NS(pdsk, D_INCONSISTENT));
 			if (retcode >= SS_SUCCESS) {
-				/* open coded drbd_bitmap_io() */
 				if (drbd_bitmap_io(mdev, &drbd_bmio_set_susp_al,
-						   "set_n_write from invalidate_peer"))
+					"set_n_write from invalidate_peer",
+					BM_LOCKED_SET_ALLOWED))
 					retcode = ERR_IO_MD_DISK;
 			}
 		} else
@@ -1914,9 +1958,17 @@
 			       struct drbd_nl_cfg_reply *reply)
 {
 	int retcode = NO_ERROR;
+	union drbd_state s;
 
-	if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO)
-		retcode = ERR_PAUSE_IS_CLEAR;
+	if (drbd_request_state(mdev, NS(user_isp, 0)) == SS_NOTHING_TO_DO) {
+		s = mdev->state;
+		if (s.conn == C_PAUSED_SYNC_S || s.conn == C_PAUSED_SYNC_T) {
+			retcode = s.aftr_isp ? ERR_PIC_AFTER_DEP :
+				  s.peer_isp ? ERR_PIC_PEER_DEP : ERR_PAUSE_IS_CLEAR;
+		} else {
+			retcode = ERR_PAUSE_IS_CLEAR;
+		}
+	}
 
 	reply->ret_code = retcode;
 	return 0;
@@ -2054,6 +2106,11 @@
 		reply->ret_code = ERR_MANDATORY_TAG;
 		return 0;
 	}
+
+	/* If there is still bitmap IO pending, e.g. previous resync or verify
+	 * just being finished, wait for it before requesting a new resync. */
+	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
 	/* w_make_ov_request expects position to be aligned */
 	mdev->ov_start_sector = args.start_sector & ~BM_SECT_PER_BIT;
 	reply->ret_code = drbd_request_state(mdev,NS(conn,C_VERIFY_S));
@@ -2097,7 +2154,8 @@
 	drbd_uuid_new_current(mdev); /* New current, previous to UI_BITMAP */
 
 	if (args.clear_bm) {
-		err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write, "clear_n_write from new_c_uuid");
+		err = drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write,
+			"clear_n_write from new_c_uuid", BM_LOCKED_MASK);
 		if (err) {
 			dev_err(DEV, "Writing bitmap failed with %d\n",err);
 			retcode = ERR_IO_MD_DISK;
@@ -2105,6 +2163,7 @@
 		if (skip_initial_sync) {
 			drbd_send_uuids_skip_initial_sync(mdev);
 			_drbd_uuid_set(mdev, UI_BITMAP, 0);
+			drbd_print_uuids(mdev, "cleared bitmap UUID");
 			spin_lock_irq(&mdev->req_lock);
 			_drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
 					CS_VERBOSE, NULL);
@@ -2177,7 +2236,7 @@
 		return;
 	}
 
-	if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN)) {
+	if (!cap_raised(current_cap(), CAP_SYS_ADMIN)) {
 		retcode = ERR_PERM;
 		goto fail;
 	}
@@ -2189,7 +2248,8 @@
 		goto fail;
 	}
 
-	if (nlp->packet_type >= P_nl_after_last_packet) {
+	if (nlp->packet_type >= P_nl_after_last_packet ||
+	    nlp->packet_type == P_return_code_only) {
 		retcode = ERR_PACKET_NR;
 		goto fail;
 	}
@@ -2205,7 +2265,7 @@
 	reply_size += cm->reply_body_size;
 
 	/* allocation not in the IO path, cqueue thread context */
-	cn_reply = kmalloc(reply_size, GFP_KERNEL);
+	cn_reply = kzalloc(reply_size, GFP_KERNEL);
 	if (!cn_reply) {
 		retcode = ERR_NOMEM;
 		goto fail;
@@ -2213,7 +2273,7 @@
 	reply = (struct drbd_nl_cfg_reply *) cn_reply->data;
 
 	reply->packet_type =
-		cm->reply_body_size ? nlp->packet_type : P_nl_after_last_packet;
+		cm->reply_body_size ? nlp->packet_type : P_return_code_only;
 	reply->minor = nlp->drbd_minor;
 	reply->ret_code = NO_ERROR; /* Might by modified by cm->function. */
 	/* reply->tag_list; might be modified by cm->function. */
@@ -2376,7 +2436,7 @@
 	/* receiver thread context, which is not in the writeout path (of this node),
 	 * but may be in the writeout path of the _other_ node.
 	 * GFP_NOIO to avoid potential "distributed deadlock". */
-	cn_reply = kmalloc(
+	cn_reply = kzalloc(
 		sizeof(struct cn_msg)+
 		sizeof(struct drbd_nl_cfg_reply)+
 		sizeof(struct dump_ee_tag_len_struct)+
@@ -2398,10 +2458,11 @@
 	tl = tl_add_int(tl, T_ee_sector, &e->sector);
 	tl = tl_add_int(tl, T_ee_block_id, &e->block_id);
 
+	/* dump the first 32k */
+	len = min_t(unsigned, e->size, 32 << 10);
 	put_unaligned(T_ee_data, tl++);
-	put_unaligned(e->size, tl++);
+	put_unaligned(len, tl++);
 
-	len = e->size;
 	page = e->pages;
 	page_chain_for_each(page) {
 		void *d = kmap_atomic(page, KM_USER0);
@@ -2410,6 +2471,8 @@
 		kunmap_atomic(d, KM_USER0);
 		tl = (unsigned short*)((char*)tl + l);
 		len -= l;
+		if (len == 0)
+			break;
 	}
 	put_unaligned(TT_END, tl++); /* Close the tag list */
 
@@ -2508,6 +2571,7 @@
 		(struct drbd_nl_cfg_reply *)cn_reply->data;
 	int rr;
 
+	memset(buffer, 0, sizeof(buffer));
 	cn_reply->id = req->id;
 
 	cn_reply->seq = req->seq;
@@ -2515,6 +2579,7 @@
 	cn_reply->len = sizeof(struct drbd_nl_cfg_reply);
 	cn_reply->flags = 0;
 
+	reply->packet_type = P_return_code_only;
 	reply->minor = ((struct drbd_nl_cfg_req *)req->data)->drbd_minor;
 	reply->ret_code = ret_code;
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_proc.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_proc.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_proc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_proc.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 #include "drbd_int.h"
 
 static int drbd_proc_open(struct inode *inode, struct file *file);
+static int drbd_proc_release(struct inode *inode, struct file *file);
 
 
 struct proc_dir_entry *drbd_proc;
@@ -42,9 +43,22 @@
 	.open		= drbd_proc_open,
 	.read		= seq_read,
 	.llseek		= seq_lseek,
-	.release	= single_release,
+	.release	= drbd_proc_release,
 };
 
+void seq_printf_with_thousands_grouping(struct seq_file *seq, long v)
+{
+	/* v is in kB/sec. We don't expect TiByte/sec yet. */
+	if (unlikely(v >= 1000000)) {
+		/* cool: > GiByte/s */
+		seq_printf(seq, "%ld,", v / 1000000);
+		v /= 1000000;
+		seq_printf(seq, "%03ld,%03ld", v/1000, v % 1000);
+	} else if (likely(v >= 1000))
+		seq_printf(seq, "%ld,%03ld", v/1000, v % 1000);
+	else
+		seq_printf(seq, "%ld", v);
+}
 
 /*lge
  * progress bars shamelessly adapted from driver/md/md.c
@@ -71,10 +85,15 @@
 		seq_printf(seq, ".");
 	seq_printf(seq, "] ");
 
-	seq_printf(seq, "sync'ed:%3u.%u%% ", res / 10, res % 10);
-	/* if more than 1 GB display in MB */
-	if (mdev->rs_total > 0x100000L)
-		seq_printf(seq, "(%lu/%lu)M\n\t",
+	if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+		seq_printf(seq, "verified:");
+	else
+		seq_printf(seq, "sync'ed:");
+	seq_printf(seq, "%3u.%u%% ", res / 10, res % 10);
+
+	/* if more than a few GB, display in MB */
+	if (mdev->rs_total > (4UL << (30 - BM_BLOCK_SHIFT)))
+		seq_printf(seq, "(%lu/%lu)M",
 			    (unsigned long) Bit2KB(rs_left >> 10),
 			    (unsigned long) Bit2KB(mdev->rs_total >> 10));
 	else
@@ -94,6 +113,7 @@
 	/* Rolling marks. last_mark+1 may just now be modified.  last_mark+2 is
 	 * at least (DRBD_SYNC_MARKS-2)*DRBD_SYNC_MARK_STEP old, and has at
 	 * least DRBD_SYNC_MARK_STEP time before it will be modified. */
+	/* ------------------------ ~18s average ------------------------ */
 	i = (mdev->rs_last_mark + 2) % DRBD_SYNC_MARKS;
 	dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
 	if (dt > (DRBD_SYNC_MARK_STEP * DRBD_SYNC_MARKS))
@@ -107,14 +127,24 @@
 	seq_printf(seq, "finish: %lu:%02lu:%02lu",
 		rt / 3600, (rt % 3600) / 60, rt % 60);
 
-	/* current speed average over (SYNC_MARKS * SYNC_MARK_STEP) jiffies */
 	dbdt = Bit2KB(db/dt);
-	if (dbdt > 1000)
-		seq_printf(seq, " speed: %ld,%03ld",
-			dbdt/1000, dbdt % 1000);
-	else
-		seq_printf(seq, " speed: %ld", dbdt);
+	seq_printf(seq, " speed: ");
+	seq_printf_with_thousands_grouping(seq, dbdt);
+	seq_printf(seq, " (");
+	/* ------------------------- ~3s average ------------------------ */
+	if (proc_details >= 1) {
+		/* this is what drbd_rs_should_slow_down() uses */
+		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+		dt = (jiffies - mdev->rs_mark_time[i]) / HZ;
+		if (!dt)
+			dt++;
+		db = mdev->rs_mark_left[i] - rs_left;
+		dbdt = Bit2KB(db/dt);
+		seq_printf_with_thousands_grouping(seq, dbdt);
+		seq_printf(seq, " -- ");
+	}
 
+	/* --------------------- long term average ---------------------- */
 	/* mean speed since syncer started
 	 * we do account for PausedSync periods */
 	dt = (jiffies - mdev->rs_start - mdev->rs_paused) / HZ;
@@ -122,20 +152,34 @@
 		dt = 1;
 	db = mdev->rs_total - rs_left;
 	dbdt = Bit2KB(db/dt);
-	if (dbdt > 1000)
-		seq_printf(seq, " (%ld,%03ld)",
-			dbdt/1000, dbdt % 1000);
-	else
-		seq_printf(seq, " (%ld)", dbdt);
+	seq_printf_with_thousands_grouping(seq, dbdt);
+	seq_printf(seq, ")");
 
-	if (mdev->state.conn == C_SYNC_TARGET) {
-		if (mdev->c_sync_rate > 1000)
-			seq_printf(seq, " want: %d,%03d",
-				   mdev->c_sync_rate / 1000, mdev->c_sync_rate % 1000);
-		else
-			seq_printf(seq, " want: %d", mdev->c_sync_rate);
+	if (mdev->state.conn == C_SYNC_TARGET ||
+	    mdev->state.conn == C_VERIFY_S) {
+		seq_printf(seq, " want: ");
+		seq_printf_with_thousands_grouping(seq, mdev->c_sync_rate);
 	}
 	seq_printf(seq, " K/sec%s\n", stalled ? " (stalled)" : "");
+
+	if (proc_details >= 1) {
+		/* 64 bit:
+		 * we convert to sectors in the display below. */
+		unsigned long bm_bits = drbd_bm_bits(mdev);
+		unsigned long bit_pos;
+		if (mdev->state.conn == C_VERIFY_S ||
+		    mdev->state.conn == C_VERIFY_T)
+			bit_pos = bm_bits - mdev->ov_left;
+		else
+			bit_pos = mdev->bm_resync_fo;
+		/* Total sectors may be slightly off for oddly
+		 * sized devices. So what. */
+		seq_printf(seq,
+			"\t%3d%% sector pos: %llu/%llu\n",
+			(int)(bit_pos / (bm_bits/100+1)),
+			(unsigned long long)bit_pos * BM_SECT_PER_BIT,
+			(unsigned long long)bm_bits * BM_SECT_PER_BIT);
+	}
 }
 
 static void resync_dump_detail(struct seq_file *seq, struct lc_element *e)
@@ -232,20 +276,16 @@
 			   mdev->epochs,
 			   write_ordering_chars[mdev->write_ordering]
 			);
-			seq_printf(seq, " oos:%lu\n",
-				   Bit2KB(drbd_bm_total_weight(mdev)));
+			seq_printf(seq, " oos:%llu\n",
+				   Bit2KB((unsigned long long)
+					   drbd_bm_total_weight(mdev)));
 		}
 		if (mdev->state.conn == C_SYNC_SOURCE ||
-		    mdev->state.conn == C_SYNC_TARGET)
+		    mdev->state.conn == C_SYNC_TARGET ||
+		    mdev->state.conn == C_VERIFY_S ||
+		    mdev->state.conn == C_VERIFY_T)
 			drbd_syncer_progress(mdev, seq);
 
-		if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
-			seq_printf(seq, "\t%3d%%      %lu/%lu\n",
-				   (int)((mdev->rs_total-mdev->ov_left) /
-					 (mdev->rs_total/100+1)),
-				   mdev->rs_total - mdev->ov_left,
-				   mdev->rs_total);
-
 		if (proc_details >= 1 && get_ldev_if_state(mdev, D_FAILED)) {
 			lc_seq_printf_stats(seq, mdev->resync);
 			lc_seq_printf_stats(seq, mdev->act_log);
@@ -265,7 +305,15 @@
 
 static int drbd_proc_open(struct inode *inode, struct file *file)
 {
-	return single_open(file, drbd_seq_show, PDE(inode)->data);
+	if (try_module_get(THIS_MODULE))
+		return single_open(file, drbd_seq_show, PDE(inode)->data);
+	return -ENODEV;
+}
+
+static int drbd_proc_release(struct inode *inode, struct file *file)
+{
+	module_put(THIS_MODULE);
+	return single_release(inode, file);
 }
 
 /* PROC FS stuff end */
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_receiver.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_receiver.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_receiver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_receiver.c	2011-05-19 00:06:34.000000000 -0400
@@ -187,15 +187,6 @@
 	return NULL;
 }
 
-/* kick lower level device, if we have more than (arbitrary number)
- * reference counts on it, which typically are locally submitted io
- * requests.  don't use unacked_cnt, so we speed up proto A and B, too. */
-static void maybe_kick_lo(struct drbd_conf *mdev)
-{
-	if (atomic_read(&mdev->local_cnt) >= mdev->net_conf->unplug_watermark)
-		drbd_kick_lo(mdev);
-}
-
 static void reclaim_net_ee(struct drbd_conf *mdev, struct list_head *to_be_freed)
 {
 	struct drbd_epoch_entry *e;
@@ -219,7 +210,6 @@
 	LIST_HEAD(reclaimed);
 	struct drbd_epoch_entry *e, *t;
 
-	maybe_kick_lo(mdev);
 	spin_lock_irq(&mdev->req_lock);
 	reclaim_net_ee(mdev, &reclaimed);
 	spin_unlock_irq(&mdev->req_lock);
@@ -287,7 +277,7 @@
 	atomic_t *a = is_net ? &mdev->pp_in_use_by_net : &mdev->pp_in_use;
 	int i;
 
-	if (drbd_pp_vacant > (DRBD_MAX_SEGMENT_SIZE/PAGE_SIZE)*minor_count)
+	if (drbd_pp_vacant > (DRBD_MAX_BIO_SIZE/PAGE_SIZE)*minor_count)
 		i = page_chain_free(page);
 	else {
 		struct page *tmp;
@@ -329,7 +319,7 @@
 	struct page *page;
 	unsigned nr_pages = (data_size + PAGE_SIZE -1) >> PAGE_SHIFT;
 
-	if (FAULT_ACTIVE(mdev, DRBD_FAULT_AL_EE))
+	if (drbd_insert_fault(mdev, DRBD_FAULT_AL_EE))
 		return NULL;
 
 	e = mempool_alloc(drbd_ee_mempool, gfp_mask & ~__GFP_HIGHMEM);
@@ -436,8 +426,7 @@
 	while (!list_empty(head)) {
 		prepare_to_wait(&mdev->ee_wait, &wait, TASK_UNINTERRUPTIBLE);
 		spin_unlock_irq(&mdev->req_lock);
-		drbd_kick_lo(mdev);
-		schedule();
+		io_schedule();
 		finish_wait(&mdev->ee_wait, &wait);
 		spin_lock_irq(&mdev->req_lock);
 	}
@@ -736,16 +725,16 @@
 	char tb[4];
 
 	if (!*sock)
-		return FALSE;
+		return false;
 
 	rr = drbd_recv_short(mdev, *sock, tb, 4, MSG_DONTWAIT | MSG_PEEK);
 
 	if (rr > 0 || rr == -EAGAIN) {
-		return TRUE;
+		return true;
 	} else {
 		sock_release(*sock);
 		*sock = NULL;
-		return FALSE;
+		return false;
 	}
 }
 
@@ -779,8 +768,7 @@
 			if (s || ++try >= 3)
 				break;
 			/* give the other side time to call bind() & listen() */
-			__set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 10);
+			schedule_timeout_interruptible(HZ / 10);
 		}
 
 		if (s) {
@@ -799,8 +787,7 @@
 		}
 
 		if (sock && msock) {
-			__set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ / 10);
+			schedule_timeout_interruptible(HZ / 10);
 			ok = drbd_socket_okay(mdev, &sock);
 			ok = drbd_socket_okay(mdev, &msock) && ok;
 			if (ok)
@@ -875,7 +862,7 @@
 	msock->sk->sk_rcvtimeo = mdev->net_conf->ping_int*HZ;
 
 	/* we don't want delays.
-	 * we use TCP_CORK where apropriate, though */
+	 * we use TCP_CORK where appropriate, though */
 	drbd_tcp_nodelay(sock);
 	drbd_tcp_nodelay(msock);
 
@@ -917,7 +904,7 @@
 		put_ldev(mdev);
 	}
 
-	if (!drbd_send_protocol(mdev))
+	if (drbd_send_protocol(mdev) == -1)
 		return -1;
 	drbd_send_sync_param(mdev, &mdev->sync_conf);
 	drbd_send_sizes(mdev, 0, 0);
@@ -925,6 +912,7 @@
 	drbd_send_state(mdev);
 	clear_bit(USE_DEGR_WFC_T, &mdev->flags);
 	clear_bit(RESIZE_PENDING, &mdev->flags);
+	mod_timer(&mdev->request_timer, jiffies + HZ); /* just start it here. */
 
 	return 1;
 
@@ -943,8 +931,9 @@
 
 	r = drbd_recv(mdev, h, sizeof(*h));
 	if (unlikely(r != sizeof(*h))) {
-		dev_err(DEV, "short read expecting header on sock: r=%d\n", r);
-		return FALSE;
+		if (!signal_pending(current))
+			dev_warn(DEV, "short read expecting header on sock: r=%d\n", r);
+		return false;
 	}
 
 	if (likely(h->h80.magic == BE_DRBD_MAGIC)) {
@@ -958,11 +947,11 @@
 		    be32_to_cpu(h->h80.magic),
 		    be16_to_cpu(h->h80.command),
 		    be16_to_cpu(h->h80.length));
-		return FALSE;
+		return false;
 	}
 	mdev->last_received = jiffies;
 
-	return TRUE;
+	return true;
 }
 
 static void drbd_flush(struct drbd_conf *mdev)
@@ -1085,6 +1074,16 @@
  * @mdev:	DRBD device.
  * @e:		epoch entry
  * @rw:		flag field, see bio->bi_rw
+ *
+ * May spread the pages to multiple bios,
+ * depending on bio_add_page restrictions.
+ *
+ * Returns 0 if all bios have been submitted,
+ * -ENOMEM if we could not allocate enough bios,
+ * -ENOSPC (any better suggestion?) if we have not been able to bio_add_page a
+ *  single page to an empty bio (which should never happen and likely indicates
+ *  that the lower level IO stack is in some way broken). This has been observed
+ *  on certain Xen deployments.
  */
 /* TODO allocate from our own bio_set. */
 int drbd_submit_ee(struct drbd_conf *mdev, struct drbd_epoch_entry *e,
@@ -1097,6 +1096,7 @@
 	unsigned ds = e->size;
 	unsigned n_bios = 0;
 	unsigned nr_pages = (ds + PAGE_SIZE -1) >> PAGE_SHIFT;
+	int err = -ENOMEM;
 
 	/* In most cases, we will only need one bio.  But in case the lower
 	 * level restrictions happen to be different at this offset on this
@@ -1111,8 +1111,6 @@
 	/* > e->sector, unless this is the first bio */
 	bio->bi_sector = sector;
 	bio->bi_bdev = mdev->ldev->backing_bdev;
-	/* we special case some flags in the multi-bio case, see below
-	 * (REQ_UNPLUG) */
 	bio->bi_rw = rw;
 	bio->bi_private = e;
 	bio->bi_end_io = drbd_endio_sec;
@@ -1124,8 +1122,17 @@
 	page_chain_for_each(page) {
 		unsigned len = min_t(unsigned, ds, PAGE_SIZE);
 		if (!bio_add_page(bio, page, len, 0)) {
-			/* a single page must always be possible! */
-			BUG_ON(bio->bi_vcnt == 0);
+			/* A single page must always be possible!
+			 * But in case it fails anyways,
+			 * we deal with it, and complain (below). */
+			if (bio->bi_vcnt == 0) {
+				dev_err(DEV,
+					"bio_add_page failed for len=%u, "
+					"bi_vcnt=0 (bi_sector=%llu)\n",
+					len, (unsigned long long)bio->bi_sector);
+				err = -ENOSPC;
+				goto fail;
+			}
 			goto next_bio;
 		}
 		ds -= len;
@@ -1141,13 +1148,8 @@
 		bios = bios->bi_next;
 		bio->bi_next = NULL;
 
-		/* strip off REQ_UNPLUG unless it is the last bio */
-		if (bios)
-			bio->bi_rw &= ~REQ_UNPLUG;
-
 		drbd_generic_make_request(mdev, fault_type, bio);
 	} while (bios);
-	maybe_kick_lo(mdev);
 	return 0;
 
 fail:
@@ -1156,7 +1158,7 @@
 		bios = bios->bi_next;
 		bio_put(bio);
 	}
-	return -ENOMEM;
+	return err;
 }
 
 static int receive_Barrier(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -1167,9 +1169,6 @@
 
 	inc_unacked(mdev);
 
-	if (mdev->net_conf->wire_protocol != DRBD_PROT_C)
-		drbd_kick_lo(mdev);
-
 	mdev->current_epoch->barrier_nr = p->barrier;
 	rv = drbd_may_finish_epoch(mdev, mdev->current_epoch, EV_GOT_BARRIER_NR);
 
@@ -1181,7 +1180,7 @@
 	switch (mdev->write_ordering) {
 	case WO_none:
 		if (rv == FE_RECYCLED)
-			return TRUE;
+			return true;
 
 		/* receiver context, in the writeout path of the other node.
 		 * avoid potential distributed deadlock */
@@ -1209,10 +1208,10 @@
 		D_ASSERT(atomic_read(&epoch->active) == 0);
 		D_ASSERT(epoch->flags == 0);
 
-		return TRUE;
+		return true;
 	default:
 		dev_err(DEV, "Strangeness in mdev->write_ordering %d\n", mdev->write_ordering);
-		return FALSE;
+		return false;
 	}
 
 	epoch->flags = 0;
@@ -1230,7 +1229,7 @@
 	}
 	spin_unlock(&mdev->epoch_lock);
 
-	return TRUE;
+	return true;
 }
 
 /* used from receive_RSDataReply (recv_resync_read)
@@ -1252,21 +1251,25 @@
 	if (dgs) {
 		rr = drbd_recv(mdev, dig_in, dgs);
 		if (rr != dgs) {
-			dev_warn(DEV, "short read receiving data digest: read %d expected %d\n",
-			     rr, dgs);
+			if (!signal_pending(current))
+				dev_warn(DEV,
+					"short read receiving data digest: read %d expected %d\n",
+					rr, dgs);
 			return NULL;
 		}
 	}
 
 	data_size -= dgs;
 
+	ERR_IF(data_size == 0) return NULL;
 	ERR_IF(data_size &  0x1ff) return NULL;
-	ERR_IF(data_size >  DRBD_MAX_SEGMENT_SIZE) return NULL;
+	ERR_IF(data_size >  DRBD_MAX_BIO_SIZE) return NULL;
 
 	/* even though we trust out peer,
 	 * we sometimes have to double check. */
 	if (sector + (data_size>>9) > capacity) {
-		dev_err(DEV, "capacity: %llus < sector: %llus + size: %u\n",
+		dev_err(DEV, "request from peer beyond end of local disk: "
+			"capacity: %llus < sector: %llus + size: %u\n",
 			(unsigned long long)capacity,
 			(unsigned long long)sector, data_size);
 		return NULL;
@@ -1285,15 +1288,16 @@
 		unsigned len = min_t(int, ds, PAGE_SIZE);
 		data = kmap(page);
 		rr = drbd_recv(mdev, data, len);
-		if (FAULT_ACTIVE(mdev, DRBD_FAULT_RECEIVE)) {
+		if (drbd_insert_fault(mdev, DRBD_FAULT_RECEIVE)) {
 			dev_err(DEV, "Fault injection: Corrupting data on receive\n");
 			data[0] = data[0] ^ (unsigned long)-1;
 		}
 		kunmap(page);
 		if (rr != len) {
 			drbd_free_ee(mdev, e);
-			dev_warn(DEV, "short read receiving data: read %d expected %d\n",
-			     rr, len);
+			if (!signal_pending(current))
+				dev_warn(DEV, "short read receiving data: read %d expected %d\n",
+				rr, len);
 			return NULL;
 		}
 		ds -= rr;
@@ -1302,7 +1306,8 @@
 	if (dgs) {
 		drbd_csum_ee(mdev, mdev->integrity_r_tfm, e, dig_vv);
 		if (memcmp(dig_in, dig_vv, dgs)) {
-			dev_err(DEV, "Digest integrity check FAILED.\n");
+			dev_err(DEV, "Digest integrity check FAILED: %llus +%u\n",
+				(unsigned long long)sector, data_size);
 			drbd_bcast_ee(mdev, "digest failed",
 					dgs, dig_in, dig_vv, e);
 			drbd_free_ee(mdev, e);
@@ -1323,7 +1328,7 @@
 	void *data;
 
 	if (!data_size)
-		return TRUE;
+		return true;
 
 	page = drbd_pp_alloc(mdev, 1, 1);
 
@@ -1332,8 +1337,10 @@
 		rr = drbd_recv(mdev, data, min_t(int, data_size, PAGE_SIZE));
 		if (rr != min_t(int, data_size, PAGE_SIZE)) {
 			rv = 0;
-			dev_warn(DEV, "short read receiving data: read %d expected %d\n",
-			     rr, min_t(int, data_size, PAGE_SIZE));
+			if (!signal_pending(current))
+				dev_warn(DEV,
+					"short read receiving data: read %d expected %d\n",
+					rr, min_t(int, data_size, PAGE_SIZE));
 			break;
 		}
 		data_size -= rr;
@@ -1358,8 +1365,10 @@
 	if (dgs) {
 		rr = drbd_recv(mdev, dig_in, dgs);
 		if (rr != dgs) {
-			dev_warn(DEV, "short read receiving data reply digest: read %d expected %d\n",
-			     rr, dgs);
+			if (!signal_pending(current))
+				dev_warn(DEV,
+					"short read receiving data reply digest: read %d expected %d\n",
+					rr, dgs);
 			return 0;
 		}
 	}
@@ -1380,9 +1389,10 @@
 			     expect);
 		kunmap(bvec->bv_page);
 		if (rr != expect) {
-			dev_warn(DEV, "short read receiving data reply: "
-			     "read %d expected %d\n",
-			     rr, expect);
+			if (!signal_pending(current))
+				dev_warn(DEV, "short read receiving data reply: "
+					"read %d expected %d\n",
+					rr, expect);
 			return 0;
 		}
 		data_size -= rr;
@@ -1446,11 +1456,10 @@
 
 	atomic_add(data_size >> 9, &mdev->rs_sect_ev);
 	if (drbd_submit_ee(mdev, e, WRITE, DRBD_FAULT_RS_WR) == 0)
-		return TRUE;
+		return true;
 
-	/* drbd_submit_ee currently fails for one reason only:
-	 * not being able to allocate enough bios.
-	 * Is dropping the connection going to help? */
+	/* don't care for the reason here */
+	dev_err(DEV, "submit failed, triggering re-connect\n");
 	spin_lock_irq(&mdev->req_lock);
 	list_del(&e->w.list);
 	spin_unlock_irq(&mdev->req_lock);
@@ -1458,7 +1467,7 @@
 	drbd_free_ee(mdev, e);
 fail:
 	put_ldev(mdev);
-	return FALSE;
+	return false;
 }
 
 static int receive_DataReply(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -1475,7 +1484,7 @@
 	spin_unlock_irq(&mdev->req_lock);
 	if (unlikely(!req)) {
 		dev_err(DEV, "Got a corrupt block_id/sector pair(1).\n");
-		return FALSE;
+		return false;
 	}
 
 	/* hlist_del(&req->colision) is done in _req_may_be_done, to avoid
@@ -1632,16 +1641,15 @@
 	return ret;
 }
 
-static unsigned long write_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
+/* see also bio_flags_to_wire()
+ * DRBD_REQ_*, because we need to semantically map the flags to data packet
+ * flags and back. We may replicate to other kernel versions. */
+static unsigned long wire_flags_to_bio(struct drbd_conf *mdev, u32 dpf)
 {
-	if (mdev->agreed_pro_version >= 95)
-		return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
-			(dpf & DP_UNPLUG ? REQ_UNPLUG : 0) |
-			(dpf & DP_FUA ? REQ_FUA : 0) |
-			(dpf & DP_FLUSH ? REQ_FUA : 0) |
-			(dpf & DP_DISCARD ? REQ_DISCARD : 0);
-	else
-		return dpf & DP_RW_SYNC ? (REQ_SYNC | REQ_UNPLUG) : 0;
+	return  (dpf & DP_RW_SYNC ? REQ_SYNC : 0) |
+		(dpf & DP_FUA ? REQ_FUA : 0) |
+		(dpf & DP_FLUSH ? REQ_FLUSH : 0) |
+		(dpf & DP_DISCARD ? REQ_DISCARD : 0);
 }
 
 /* mirrored write */
@@ -1654,9 +1662,6 @@
 	u32 dp_flags;
 
 	if (!get_ldev(mdev)) {
-		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Can not write mirrored data block "
-			    "to local disk.\n");
 		spin_lock(&mdev->peer_seq_lock);
 		if (mdev->peer_seq+1 == be32_to_cpu(p->seq_num))
 			mdev->peer_seq++;
@@ -1676,23 +1681,23 @@
 	e = read_in_block(mdev, p->block_id, sector, data_size);
 	if (!e) {
 		put_ldev(mdev);
-		return FALSE;
+		return false;
 	}
 
 	e->w.cb = e_end_block;
 
+	dp_flags = be32_to_cpu(p->dp_flags);
+	rw |= wire_flags_to_bio(mdev, dp_flags);
+
+	if (dp_flags & DP_MAY_SET_IN_SYNC)
+		e->flags |= EE_MAY_SET_IN_SYNC;
+
 	spin_lock(&mdev->epoch_lock);
 	e->epoch = mdev->current_epoch;
 	atomic_inc(&e->epoch->epoch_size);
 	atomic_inc(&e->epoch->active);
 	spin_unlock(&mdev->epoch_lock);
 
-	dp_flags = be32_to_cpu(p->dp_flags);
-	rw |= write_flags_to_bio(mdev, dp_flags);
-
-	if (dp_flags & DP_MAY_SET_IN_SYNC)
-		e->flags |= EE_MAY_SET_IN_SYNC;
-
 	/* I'm the receiver, I do hold a net_cnt reference. */
 	if (!mdev->net_conf->two_primaries) {
 		spin_lock_irq(&mdev->req_lock);
@@ -1795,7 +1800,7 @@
 				put_ldev(mdev);
 				wake_asender(mdev);
 				finish_wait(&mdev->misc_wait, &wait);
-				return TRUE;
+				return true;
 			}
 
 			if (signal_pending(current)) {
@@ -1851,11 +1856,10 @@
 	}
 
 	if (drbd_submit_ee(mdev, e, rw, DRBD_FAULT_DT_WR) == 0)
-		return TRUE;
+		return true;
 
-	/* drbd_submit_ee currently fails for one reason only:
-	 * not being able to allocate enough bios.
-	 * Is dropping the connection going to help? */
+	/* don't care for the reason here */
+	dev_err(DEV, "submit failed, triggering re-connect\n");
 	spin_lock_irq(&mdev->req_lock);
 	list_del(&e->w.list);
 	hlist_del_init(&e->colision);
@@ -1864,12 +1868,10 @@
 		drbd_al_complete_io(mdev, e->sector);
 
 out_interrupted:
-	/* yes, the epoch_size now is imbalanced.
-	 * but we drop the connection anyways, so we don't have a chance to
-	 * receive a barrier... atomic_inc(&mdev->epoch_size); */
+	drbd_may_finish_epoch(mdev, e->epoch, EV_PUT + EV_CLEANUP);
 	put_ldev(mdev);
 	drbd_free_ee(mdev, e);
-	return FALSE;
+	return false;
 }
 
 /* We may throttle resync, if the lower device seems to be busy,
@@ -1883,10 +1885,11 @@
  * The current sync rate used here uses only the most recent two step marks,
  * to have a short time average so we can react faster.
  */
-int drbd_rs_should_slow_down(struct drbd_conf *mdev)
+int drbd_rs_should_slow_down(struct drbd_conf *mdev, sector_t sector)
 {
 	struct gendisk *disk = mdev->ldev->backing_bdev->bd_contains->bd_disk;
 	unsigned long db, dt, dbdt;
+	struct lc_element *tmp;
 	int curr_events;
 	int throttle = 0;
 
@@ -1894,9 +1897,22 @@
 	if (mdev->sync_conf.c_min_rate == 0)
 		return 0;
 
+	spin_lock_irq(&mdev->al_lock);
+	tmp = lc_find(mdev->resync, BM_SECT_TO_EXT(sector));
+	if (tmp) {
+		struct bm_extent *bm_ext = lc_entry(tmp, struct bm_extent, lce);
+		if (test_bit(BME_PRIORITY, &bm_ext->flags)) {
+			spin_unlock_irq(&mdev->al_lock);
+			return 0;
+		}
+		/* Do not slow down if app IO is already waiting for this extent */
+	}
+	spin_unlock_irq(&mdev->al_lock);
+
 	curr_events = (int)part_stat_read(&disk->part0, sectors[0]) +
 		      (int)part_stat_read(&disk->part0, sectors[1]) -
 			atomic_read(&mdev->rs_sect_ev);
+
 	if (!mdev->rs_last_events || curr_events - mdev->rs_last_events > 64) {
 		unsigned long rs_left;
 		int i;
@@ -1905,8 +1921,12 @@
 
 		/* sync speed average over the last 2*DRBD_SYNC_MARK_STEP,
 		 * approx. */
-		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-2) % DRBD_SYNC_MARKS;
-		rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
+		i = (mdev->rs_last_mark + DRBD_SYNC_MARKS-1) % DRBD_SYNC_MARKS;
+
+		if (mdev->state.conn == C_VERIFY_S || mdev->state.conn == C_VERIFY_T)
+			rs_left = mdev->ov_left;
+		else
+			rs_left = drbd_bm_total_weight(mdev) - mdev->rs_failed;
 
 		dt = ((long)jiffies - (long)mdev->rs_mark_time[i]) / HZ;
 		if (!dt)
@@ -1934,15 +1954,15 @@
 	sector = be64_to_cpu(p->sector);
 	size   = be32_to_cpu(p->blksize);
 
-	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_SEGMENT_SIZE) {
+	if (size <= 0 || (size & 0x1ff) != 0 || size > DRBD_MAX_BIO_SIZE) {
 		dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
 				(unsigned long long)sector, size);
-		return FALSE;
+		return false;
 	}
 	if (sector + (size>>9) > capacity) {
 		dev_err(DEV, "%s:%d: sector: %llus, size: %u\n", __FILE__, __LINE__,
 				(unsigned long long)sector, size);
-		return FALSE;
+		return false;
 	}
 
 	if (!get_ldev_if_state(mdev, D_UP_TO_DATE)) {
@@ -1979,7 +1999,7 @@
 	e = drbd_alloc_ee(mdev, p->block_id, sector, size, GFP_NOIO);
 	if (!e) {
 		put_ldev(mdev);
-		return FALSE;
+		return false;
 	}
 
 	switch (cmd) {
@@ -1992,6 +2012,8 @@
 	case P_RS_DATA_REQUEST:
 		e->w.cb = w_e_end_rsdata_req;
 		fault_type = DRBD_FAULT_RS_RD;
+		/* used in the sector offset progress display */
+		mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
 		break;
 
 	case P_OV_REPLY:
@@ -2013,7 +2035,11 @@
 		if (cmd == P_CSUM_RS_REQUEST) {
 			D_ASSERT(mdev->agreed_pro_version >= 89);
 			e->w.cb = w_e_end_csum_rs_req;
+			/* used in the sector offset progress display */
+			mdev->bm_resync_fo = BM_SECT_TO_BIT(sector);
 		} else if (cmd == P_OV_REPLY) {
+			/* track progress, we may need to throttle */
+			atomic_add(size >> 9, &mdev->rs_sect_in);
 			e->w.cb = w_e_end_ov_reply;
 			dec_rs_pending(mdev);
 			/* drbd_rs_begin_io done when we sent this request,
@@ -2025,9 +2051,16 @@
 	case P_OV_REQUEST:
 		if (mdev->ov_start_sector == ~(sector_t)0 &&
 		    mdev->agreed_pro_version >= 90) {
+			unsigned long now = jiffies;
+			int i;
 			mdev->ov_start_sector = sector;
 			mdev->ov_position = sector;
-			mdev->ov_left = mdev->rs_total - BM_SECT_TO_BIT(sector);
+			mdev->ov_left = drbd_bm_bits(mdev) - BM_SECT_TO_BIT(sector);
+			mdev->rs_total = mdev->ov_left;
+			for (i = 0; i < DRBD_SYNC_MARKS; i++) {
+				mdev->rs_mark_left[i] = mdev->ov_left;
+				mdev->rs_mark_time[i] = now;
+			}
 			dev_info(DEV, "Online Verify start sector: %llu\n",
 					(unsigned long long)sector);
 		}
@@ -2064,9 +2097,9 @@
 	 * we would also throttle its application reads.
 	 * In that case, throttling is done on the SyncTarget only.
 	 */
-	if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev))
-		msleep(100);
-	if (drbd_rs_begin_io(mdev, e->sector))
+	if (mdev->state.peer != R_PRIMARY && drbd_rs_should_slow_down(mdev, sector))
+		schedule_timeout_uninterruptible(HZ/10);
+	if (drbd_rs_begin_io(mdev, sector))
 		goto out_free_e;
 
 submit_for_resync:
@@ -2079,11 +2112,10 @@
 	spin_unlock_irq(&mdev->req_lock);
 
 	if (drbd_submit_ee(mdev, e, READ, fault_type) == 0)
-		return TRUE;
+		return true;
 
-	/* drbd_submit_ee currently fails for one reason only:
-	 * not being able to allocate enough bios.
-	 * Is dropping the connection going to help? */
+	/* don't care for the reason here */
+	dev_err(DEV, "submit failed, triggering re-connect\n");
 	spin_lock_irq(&mdev->req_lock);
 	list_del(&e->w.list);
 	spin_unlock_irq(&mdev->req_lock);
@@ -2092,7 +2124,7 @@
 out_free_e:
 	put_ldev(mdev);
 	drbd_free_ee(mdev, e);
-	return FALSE;
+	return false;
 }
 
 static int drbd_asb_recover_0p(struct drbd_conf *mdev) __must_hold(local)
@@ -2169,10 +2201,7 @@
 
 static int drbd_asb_recover_1p(struct drbd_conf *mdev) __must_hold(local)
 {
-	int self, peer, hg, rv = -100;
-
-	self = mdev->ldev->md.uuid[UI_BITMAP] & 1;
-	peer = mdev->p_uuid[UI_BITMAP] & 1;
+	int hg, rv = -100;
 
 	switch (mdev->net_conf->after_sb_1p) {
 	case ASB_DISCARD_YOUNGER_PRI:
@@ -2199,12 +2228,14 @@
 	case ASB_CALL_HELPER:
 		hg = drbd_asb_recover_0p(mdev);
 		if (hg == -1 && mdev->state.role == R_PRIMARY) {
-			self = drbd_set_role(mdev, R_SECONDARY, 0);
+			enum drbd_state_rv rv2;
+
+			drbd_set_role(mdev, R_SECONDARY, 0);
 			 /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
 			  * we might be here in C_WF_REPORT_PARAMS which is transient.
 			  * we do not need to wait for the after state change work either. */
-			self = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
-			if (self != SS_SUCCESS) {
+			rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
+			if (rv2 != SS_SUCCESS) {
 				drbd_khelper(mdev, "pri-lost-after-sb");
 			} else {
 				dev_warn(DEV, "Successfully gave up primary role.\n");
@@ -2219,10 +2250,7 @@
 
 static int drbd_asb_recover_2p(struct drbd_conf *mdev) __must_hold(local)
 {
-	int self, peer, hg, rv = -100;
-
-	self = mdev->ldev->md.uuid[UI_BITMAP] & 1;
-	peer = mdev->p_uuid[UI_BITMAP] & 1;
+	int hg, rv = -100;
 
 	switch (mdev->net_conf->after_sb_2p) {
 	case ASB_DISCARD_YOUNGER_PRI:
@@ -2242,11 +2270,13 @@
 	case ASB_CALL_HELPER:
 		hg = drbd_asb_recover_0p(mdev);
 		if (hg == -1) {
+			enum drbd_state_rv rv2;
+
 			 /* drbd_change_state() does not sleep while in SS_IN_TRANSIENT_STATE,
 			  * we might be here in C_WF_REPORT_PARAMS which is transient.
 			  * we do not need to wait for the after state change work either. */
-			self = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
-			if (self != SS_SUCCESS) {
+			rv2 = drbd_change_state(mdev, CS_VERBOSE, NS(role, R_SECONDARY));
+			if (rv2 != SS_SUCCESS) {
 				drbd_khelper(mdev, "pri-lost-after-sb");
 			} else {
 				dev_warn(DEV, "Successfully gave up primary role.\n");
@@ -2285,6 +2315,8 @@
    -2	C_SYNC_TARGET set BitMap
  -100	after split brain, disconnect
 -1000	unrelated data
+-1091   requires proto 91
+-1096   requires proto 96
  */
 static int drbd_uuid_compare(struct drbd_conf *mdev, int *rule_nr) __must_hold(local)
 {
@@ -2314,7 +2346,7 @@
 		if (mdev->p_uuid[UI_BITMAP] == (u64)0 && mdev->ldev->md.uuid[UI_BITMAP] != (u64)0) {
 
 			if (mdev->agreed_pro_version < 91)
-				return -1001;
+				return -1091;
 
 			if ((mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) &&
 			    (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1))) {
@@ -2335,7 +2367,7 @@
 		if (mdev->ldev->md.uuid[UI_BITMAP] == (u64)0 && mdev->p_uuid[UI_BITMAP] != (u64)0) {
 
 			if (mdev->agreed_pro_version < 91)
-				return -1001;
+				return -1091;
 
 			if ((mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) == (mdev->p_uuid[UI_BITMAP] & ~((u64)1)) &&
 			    (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) == (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1))) {
@@ -2380,17 +2412,22 @@
 	*rule_nr = 51;
 	peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
-		peer = mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1);
-		if (self == peer) {
+		if (mdev->agreed_pro_version < 96 ?
+		    (mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1)) ==
+		    (mdev->p_uuid[UI_HISTORY_START + 1] & ~((u64)1)) :
+		    peer + UUID_NEW_BM_OFFSET == (mdev->p_uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of the peer's UUIDs. */
 
 			if (mdev->agreed_pro_version < 91)
-				return -1001;
+				return -1091;
 
 			mdev->p_uuid[UI_BITMAP] = mdev->p_uuid[UI_HISTORY_START];
 			mdev->p_uuid[UI_HISTORY_START] = mdev->p_uuid[UI_HISTORY_START + 1];
+
+			dev_info(DEV, "Did not got last syncUUID packet, corrected:\n");
+			drbd_uuid_dump(mdev, "peer", mdev->p_uuid, mdev->p_uuid[UI_SIZE], mdev->p_uuid[UI_FLAGS]);
+
 			return -1;
 		}
 	}
@@ -2412,20 +2449,20 @@
 	*rule_nr = 71;
 	self = mdev->ldev->md.uuid[UI_HISTORY_START] & ~((u64)1);
 	if (self == peer) {
-		self = mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1);
-		peer = mdev->p_uuid[UI_HISTORY_START] & ~((u64)1);
-		if (self == peer) {
+		if (mdev->agreed_pro_version < 96 ?
+		    (mdev->ldev->md.uuid[UI_HISTORY_START + 1] & ~((u64)1)) ==
+		    (mdev->p_uuid[UI_HISTORY_START] & ~((u64)1)) :
+		    self + UUID_NEW_BM_OFFSET == (mdev->ldev->md.uuid[UI_BITMAP] & ~((u64)1))) {
 			/* The last P_SYNC_UUID did not get though. Undo the last start of
 			   resync as sync source modifications of our UUIDs. */
 
 			if (mdev->agreed_pro_version < 91)
-				return -1001;
+				return -1091;
 
 			_drbd_uuid_set(mdev, UI_BITMAP, mdev->ldev->md.uuid[UI_HISTORY_START]);
 			_drbd_uuid_set(mdev, UI_HISTORY_START, mdev->ldev->md.uuid[UI_HISTORY_START + 1]);
 
-			dev_info(DEV, "Undid last start of resync:\n");
-
+			dev_info(DEV, "Last syncUUID did not get through, corrected:\n");
 			drbd_uuid_dump(mdev, "self", mdev->ldev->md.uuid,
 				       mdev->state.disk >= D_NEGOTIATING ? drbd_bm_total_weight(mdev) : 0, 0);
 
@@ -2488,8 +2525,8 @@
 		dev_alert(DEV, "Unrelated data, aborting!\n");
 		return C_MASK;
 	}
-	if (hg == -1001) {
-		dev_alert(DEV, "To resolve this both sides have to support at least protocol\n");
+	if (hg < -1000) {
+		dev_alert(DEV, "To resolve this both sides have to support at least protocol %d\n", -hg - 1000);
 		return C_MASK;
 	}
 
@@ -2588,7 +2625,8 @@
 
 	if (abs(hg) >= 2) {
 		dev_info(DEV, "Writing the whole bitmap, full sync required after drbd_sync_handshake.\n");
-		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake"))
+		if (drbd_bitmap_io(mdev, &drbd_bmio_set_n_write, "set_n_write from sync_handshake",
+					BM_LOCKED_SET_ALLOWED))
 			return C_MASK;
 	}
 
@@ -2682,7 +2720,7 @@
 		unsigned char *my_alg = mdev->net_conf->integrity_alg;
 
 		if (drbd_recv(mdev, p_integrity_alg, data_size) != data_size)
-			return FALSE;
+			return false;
 
 		p_integrity_alg[SHARED_SECRET_MAX-1] = 0;
 		if (strcmp(p_integrity_alg, my_alg)) {
@@ -2693,11 +2731,11 @@
 		     my_alg[0] ? my_alg : (unsigned char *)"<not-used>");
 	}
 
-	return TRUE;
+	return true;
 
 disconnect:
 	drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-	return FALSE;
+	return false;
 }
 
 /* helper function
@@ -2729,7 +2767,7 @@
 
 static int receive_SyncParam(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int packet_size)
 {
-	int ok = TRUE;
+	int ok = true;
 	struct p_rs_param_95 *p = &mdev->data.rbuf.rs_param_95;
 	unsigned int header_size, data_size, exp_max_sz;
 	struct crypto_hash *verify_tfm = NULL;
@@ -2747,7 +2785,7 @@
 	if (packet_size > exp_max_sz) {
 		dev_err(DEV, "SyncParam packet too long: received %u, expected <= %u bytes\n",
 		    packet_size, exp_max_sz);
-		return FALSE;
+		return false;
 	}
 
 	if (apv <= 88) {
@@ -2767,7 +2805,7 @@
 	memset(p->verify_alg, 0, 2 * SHARED_SECRET_MAX);
 
 	if (drbd_recv(mdev, &p->head.payload, header_size) != header_size)
-		return FALSE;
+		return false;
 
 	mdev->sync_conf.rate	  = be32_to_cpu(p->rate);
 
@@ -2777,11 +2815,11 @@
 				dev_err(DEV, "verify-alg too long, "
 				    "peer wants %u, accepting only %u byte\n",
 						data_size, SHARED_SECRET_MAX);
-				return FALSE;
+				return false;
 			}
 
 			if (drbd_recv(mdev, p->verify_alg, data_size) != data_size)
-				return FALSE;
+				return false;
 
 			/* we expect NUL terminated string */
 			/* but just in case someone tries to be evil */
@@ -2875,7 +2913,7 @@
 	/* but free the verify_tfm again, if csums_tfm did not work out */
 	crypto_free_hash(verify_tfm);
 	drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-	return FALSE;
+	return false;
 }
 
 static void drbd_setup_order_type(struct drbd_conf *mdev, int peer)
@@ -2901,7 +2939,7 @@
 {
 	struct p_sizes *p = &mdev->data.rbuf.sizes;
 	enum determine_dev_size dd = unchanged;
-	unsigned int max_seg_s;
+	unsigned int max_bio_size;
 	sector_t p_size, p_usize, my_usize;
 	int ldsc = 0; /* local disk size changed */
 	enum dds_flags ddsf;
@@ -2912,7 +2950,7 @@
 	if (p_size == 0 && mdev->state.disk == D_DISKLESS) {
 		dev_err(DEV, "some backing storage is needed\n");
 		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		return FALSE;
+		return false;
 	}
 
 	/* just store the peer's disk size for now.
@@ -2949,18 +2987,17 @@
 			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
 			mdev->ldev->dc.disk_size = my_usize;
 			put_ldev(mdev);
-			return FALSE;
+			return false;
 		}
 		put_ldev(mdev);
 	}
-#undef min_not_zero
 
 	ddsf = be16_to_cpu(p->dds_flags);
 	if (get_ldev(mdev)) {
 		dd = drbd_determin_dev_size(mdev, ddsf);
 		put_ldev(mdev);
 		if (dd == dev_size_error)
-			return FALSE;
+			return false;
 		drbd_md_sync(mdev);
 	} else {
 		/* I am diskless, need to accept the peer's size. */
@@ -2974,14 +3011,14 @@
 		}
 
 		if (mdev->agreed_pro_version < 94)
-			max_seg_s = be32_to_cpu(p->max_segment_size);
+			max_bio_size = be32_to_cpu(p->max_bio_size);
 		else if (mdev->agreed_pro_version == 94)
-			max_seg_s = DRBD_MAX_SIZE_H80_PACKET;
+			max_bio_size = DRBD_MAX_SIZE_H80_PACKET;
 		else /* drbd 8.3.8 onwards */
-			max_seg_s = DRBD_MAX_SEGMENT_SIZE;
+			max_bio_size = DRBD_MAX_BIO_SIZE;
 
-		if (max_seg_s != queue_max_segment_size(mdev->rq_queue))
-			drbd_setup_queue_param(mdev, max_seg_s);
+		if (max_bio_size != queue_max_hw_sectors(mdev->rq_queue) << 9)
+			drbd_setup_queue_param(mdev, max_bio_size);
 
 		drbd_setup_order_type(mdev, be16_to_cpu(p->queue_order_type));
 		put_ldev(mdev);
@@ -3007,14 +3044,14 @@
 		}
 	}
 
-	return TRUE;
+	return true;
 }
 
 static int receive_uuids(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
 	struct p_uuids *p = &mdev->data.rbuf.uuids;
 	u64 *p_uuid;
-	int i;
+	int i, updated_uuids = 0;
 
 	p_uuid = kmalloc(sizeof(u64)*UI_EXTENDED_SIZE, GFP_NOIO);
 
@@ -3031,7 +3068,7 @@
 		dev_err(DEV, "Can only connect to data with current UUID=%016llX\n",
 		    (unsigned long long)mdev->ed_uuid);
 		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		return FALSE;
+		return false;
 	}
 
 	if (get_ldev(mdev)) {
@@ -3043,19 +3080,21 @@
 		if (skip_initial_sync) {
 			dev_info(DEV, "Accepted new current UUID, preparing to skip initial sync\n");
 			drbd_bitmap_io(mdev, &drbd_bmio_clear_n_write,
-					"clear_n_write from receive_uuids");
+					"clear_n_write from receive_uuids",
+					BM_LOCKED_TEST_ALLOWED);
 			_drbd_uuid_set(mdev, UI_CURRENT, p_uuid[UI_CURRENT]);
 			_drbd_uuid_set(mdev, UI_BITMAP, 0);
 			_drbd_set_state(_NS2(mdev, disk, D_UP_TO_DATE, pdsk, D_UP_TO_DATE),
 					CS_VERBOSE, NULL);
 			drbd_md_sync(mdev);
+			updated_uuids = 1;
 		}
 		put_ldev(mdev);
 	} else if (mdev->state.disk < D_INCONSISTENT &&
 		   mdev->state.role == R_PRIMARY) {
 		/* I am a diskless primary, the peer just created a new current UUID
 		   for me. */
-		drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
+		updated_uuids = drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
 	}
 
 	/* Before we test for the disk state, we should wait until an eventually
@@ -3064,9 +3103,12 @@
 	   new disk state... */
 	wait_event(mdev->misc_wait, !test_bit(CLUSTER_ST_CHANGE, &mdev->flags));
 	if (mdev->state.conn >= C_CONNECTED && mdev->state.disk < D_INCONSISTENT)
-		drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
+		updated_uuids |= drbd_set_ed_uuid(mdev, p_uuid[UI_CURRENT]);
 
-	return TRUE;
+	if (updated_uuids)
+		drbd_print_uuids(mdev, "receiver updated UUIDs to");
+
+	return true;
 }
 
 /**
@@ -3103,7 +3145,7 @@
 {
 	struct p_req_state *p = &mdev->data.rbuf.req_state;
 	union drbd_state mask, val;
-	int rv;
+	enum drbd_state_rv rv;
 
 	mask.i = be32_to_cpu(p->mask);
 	val.i = be32_to_cpu(p->val);
@@ -3111,7 +3153,7 @@
 	if (test_bit(DISCARD_CONCURRENT, &mdev->flags) &&
 	    test_bit(CLUSTER_ST_CHANGE, &mdev->flags)) {
 		drbd_send_sr_reply(mdev, SS_CONCURRENT_ST_CHG);
-		return TRUE;
+		return true;
 	}
 
 	mask = convert_state(mask);
@@ -3122,7 +3164,7 @@
 	drbd_send_sr_reply(mdev, rv);
 	drbd_md_sync(mdev);
 
-	return TRUE;
+	return true;
 }
 
 static int receive_state(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -3167,7 +3209,7 @@
 			 peer_state.conn == C_CONNECTED) {
 			if (drbd_bm_total_weight(mdev) <= mdev->rs_failed)
 				drbd_resync_finished(mdev);
-			return TRUE;
+			return true;
 		}
 	}
 
@@ -3183,6 +3225,9 @@
 	if (ns.conn == C_WF_REPORT_PARAMS)
 		ns.conn = C_CONNECTED;
 
+	if (peer_state.conn == C_AHEAD)
+		ns.conn = C_BEHIND;
+
 	if (mdev->p_uuid && peer_state.disk >= D_NEGOTIATING &&
 	    get_ldev_if_state(mdev, D_NEGOTIATING)) {
 		int cr; /* consider resync */
@@ -3217,10 +3262,10 @@
 				real_peer_disk = D_DISKLESS;
 			} else {
 				if (test_and_clear_bit(CONN_DRY_RUN, &mdev->flags))
-					return FALSE;
+					return false;
 				D_ASSERT(os.conn == C_WF_REPORT_PARAMS);
 				drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-				return FALSE;
+				return false;
 			}
 		}
 	}
@@ -3245,7 +3290,7 @@
 		drbd_uuid_new_current(mdev);
 		clear_bit(NEW_CUR_UUID, &mdev->flags);
 		drbd_force_state(mdev, NS2(conn, C_PROTOCOL_ERROR, susp, 0));
-		return FALSE;
+		return false;
 	}
 	rv = _drbd_set_state(mdev, ns, cs_flags, NULL);
 	ns = mdev->state;
@@ -3253,7 +3298,7 @@
 
 	if (rv < SS_SUCCESS) {
 		drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
-		return FALSE;
+		return false;
 	}
 
 	if (os.conn > C_WF_REPORT_PARAMS) {
@@ -3271,7 +3316,7 @@
 
 	drbd_md_sync(mdev); /* update connected indicator, la_size, ... */
 
-	return TRUE;
+	return true;
 }
 
 static int receive_sync_uuid(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
@@ -3280,6 +3325,7 @@
 
 	wait_event(mdev->misc_wait,
 		   mdev->state.conn == C_WF_SYNC_UUID ||
+		   mdev->state.conn == C_BEHIND ||
 		   mdev->state.conn < C_CONNECTED ||
 		   mdev->state.disk < D_NEGOTIATING);
 
@@ -3291,32 +3337,42 @@
 		_drbd_uuid_set(mdev, UI_CURRENT, be64_to_cpu(p->uuid));
 		_drbd_uuid_set(mdev, UI_BITMAP, 0UL);
 
+		drbd_print_uuids(mdev, "updated sync uuid");
 		drbd_start_resync(mdev, C_SYNC_TARGET);
 
 		put_ldev(mdev);
 	} else
 		dev_err(DEV, "Ignoring SyncUUID packet!\n");
 
-	return TRUE;
+	return true;
 }
 
-enum receive_bitmap_ret { OK, DONE, FAILED };
-
-static enum receive_bitmap_ret
+/**
+ * receive_bitmap_plain
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 receive_bitmap_plain(struct drbd_conf *mdev, unsigned int data_size,
 		     unsigned long *buffer, struct bm_xfer_ctx *c)
 {
 	unsigned num_words = min_t(size_t, BM_PACKET_WORDS, c->bm_words - c->word_offset);
 	unsigned want = num_words * sizeof(long);
+	int err;
 
 	if (want != data_size) {
 		dev_err(DEV, "%s:want (%u) != data_size (%u)\n", __func__, want, data_size);
-		return FAILED;
+		return -EIO;
 	}
 	if (want == 0)
-		return DONE;
-	if (drbd_recv(mdev, buffer, want) != want)
-		return FAILED;
+		return 0;
+	err = drbd_recv(mdev, buffer, want);
+	if (err != want) {
+		if (err >= 0)
+			err = -EIO;
+		return err;
+	}
 
 	drbd_bm_merge_lel(mdev, c->word_offset, num_words, buffer);
 
@@ -3325,10 +3381,16 @@
 	if (c->bit_offset > c->bm_bits)
 		c->bit_offset = c->bm_bits;
 
-	return OK;
+	return 1;
 }
 
-static enum receive_bitmap_ret
+/**
+ * recv_bm_rle_bits
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 recv_bm_rle_bits(struct drbd_conf *mdev,
 		struct p_compressed_bm *p,
 		struct bm_xfer_ctx *c)
@@ -3348,18 +3410,18 @@
 
 	bits = bitstream_get_bits(&bs, &look_ahead, 64);
 	if (bits < 0)
-		return FAILED;
+		return -EIO;
 
 	for (have = bits; have > 0; s += rl, toggle = !toggle) {
 		bits = vli_decode_bits(&rl, look_ahead);
 		if (bits <= 0)
-			return FAILED;
+			return -EIO;
 
 		if (toggle) {
 			e = s + rl -1;
 			if (e >= c->bm_bits) {
 				dev_err(DEV, "bitmap overflow (e:%lu) while decoding bm RLE packet\n", e);
-				return FAILED;
+				return -EIO;
 			}
 			_drbd_bm_set_bits(mdev, s, e);
 		}
@@ -3369,14 +3431,14 @@
 				have, bits, look_ahead,
 				(unsigned int)(bs.cur.b - p->code),
 				(unsigned int)bs.buf_len);
-			return FAILED;
+			return -EIO;
 		}
 		look_ahead >>= bits;
 		have -= bits;
 
 		bits = bitstream_get_bits(&bs, &tmp, 64 - have);
 		if (bits < 0)
-			return FAILED;
+			return -EIO;
 		look_ahead |= tmp << have;
 		have += bits;
 	}
@@ -3384,10 +3446,16 @@
 	c->bit_offset = s;
 	bm_xfer_ctx_bit_to_word_offset(c);
 
-	return (s == c->bm_bits) ? DONE : OK;
+	return (s != c->bm_bits);
 }
 
-static enum receive_bitmap_ret
+/**
+ * decode_bitmap_c
+ *
+ * Return 0 when done, 1 when another iteration is needed, and a negative error
+ * code upon failure.
+ */
+static int
 decode_bitmap_c(struct drbd_conf *mdev,
 		struct p_compressed_bm *p,
 		struct bm_xfer_ctx *c)
@@ -3401,7 +3469,7 @@
 
 	dev_err(DEV, "receive_bitmap_c: unknown encoding %u\n", p->encoding);
 	drbd_force_state(mdev, NS(conn, C_PROTOCOL_ERROR));
-	return FAILED;
+	return -EIO;
 }
 
 void INFO_bm_xfer_stats(struct drbd_conf *mdev,
@@ -3450,13 +3518,13 @@
 {
 	struct bm_xfer_ctx c;
 	void *buffer;
-	enum receive_bitmap_ret ret;
-	int ok = FALSE;
+	int err;
+	int ok = false;
 	struct p_header80 *h = &mdev->data.rbuf.header.h80;
 
-	wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
-
-	drbd_bm_lock(mdev, "receive bitmap");
+	drbd_bm_lock(mdev, "receive bitmap", BM_LOCKED_SET_ALLOWED);
+	/* you are supposed to send additional out-of-sync information
+	 * if you actually set bits during this phase */
 
 	/* maybe we should use some per thread scratch page,
 	 * and allocate that during initial device creation? */
@@ -3471,9 +3539,9 @@
 		.bm_words = drbd_bm_words(mdev),
 	};
 
-	do {
+	for(;;) {
 		if (cmd == P_BITMAP) {
-			ret = receive_bitmap_plain(mdev, data_size, buffer, &c);
+			err = receive_bitmap_plain(mdev, data_size, buffer, &c);
 		} else if (cmd == P_COMPRESSED_BITMAP) {
 			/* MAYBE: sanity check that we speak proto >= 90,
 			 * and the feature is enabled! */
@@ -3490,9 +3558,9 @@
 				goto out;
 			if (data_size <= (sizeof(*p) - sizeof(p->head))) {
 				dev_err(DEV, "ReportCBitmap packet too small (l:%u)\n", data_size);
-				return FAILED;
+				goto out;
 			}
-			ret = decode_bitmap_c(mdev, p, &c);
+			err = decode_bitmap_c(mdev, p, &c);
 		} else {
 			dev_warn(DEV, "receive_bitmap: cmd neither ReportBitMap nor ReportCBitMap (is 0x%x)", cmd);
 			goto out;
@@ -3501,24 +3569,26 @@
 		c.packets[cmd == P_BITMAP]++;
 		c.bytes[cmd == P_BITMAP] += sizeof(struct p_header80) + data_size;
 
-		if (ret != OK)
+		if (err <= 0) {
+			if (err < 0)
+				goto out;
 			break;
-
+		}
 		if (!drbd_recv_header(mdev, &cmd, &data_size))
 			goto out;
-	} while (ret == OK);
-	if (ret == FAILED)
-		goto out;
+	}
 
 	INFO_bm_xfer_stats(mdev, "receive", &c);
 
 	if (mdev->state.conn == C_WF_BITMAP_T) {
+		enum drbd_state_rv rv;
+
 		ok = !drbd_send_bitmap(mdev);
 		if (!ok)
 			goto out;
 		/* Omit CS_ORDERED with this state transition to avoid deadlocks. */
-		ok = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
-		D_ASSERT(ok == SS_SUCCESS);
+		rv = _drbd_request_state(mdev, NS(conn, C_WF_SYNC_UUID), CS_VERBOSE);
+		D_ASSERT(rv == SS_SUCCESS);
 	} else if (mdev->state.conn != C_WF_BITMAP_S) {
 		/* admin may have requested C_DISCONNECTING,
 		 * other threads may have noticed network errors */
@@ -3526,7 +3596,7 @@
 		    drbd_conn_str(mdev->state.conn));
 	}
 
-	ok = TRUE;
+	ok = true;
  out:
 	drbd_bm_unlock(mdev);
 	if (ok && mdev->state.conn == C_WF_BITMAP_S)
@@ -3556,14 +3626,30 @@
 
 static int receive_UnplugRemote(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
 {
-	if (mdev->state.disk >= D_INCONSISTENT)
-		drbd_kick_lo(mdev);
-
 	/* Make sure we've acked all the TCP data associated
 	 * with the data requests being unplugged */
 	drbd_tcp_quickack(mdev->data.socket);
 
-	return TRUE;
+	return true;
+}
+
+static int receive_out_of_sync(struct drbd_conf *mdev, enum drbd_packets cmd, unsigned int data_size)
+{
+	struct p_block_desc *p = &mdev->data.rbuf.block_desc;
+
+	switch (mdev->state.conn) {
+	case C_WF_SYNC_UUID:
+	case C_WF_BITMAP_T:
+	case C_BEHIND:
+			break;
+	default:
+		dev_err(DEV, "ASSERT FAILED cstate = %s, expected: WFSyncUUID|WFBitMapT|Behind\n",
+				drbd_conn_str(mdev->state.conn));
+	}
+
+	drbd_set_out_of_sync(mdev, be64_to_cpu(p->sector), be32_to_cpu(p->blksize));
+
+	return true;
 }
 
 typedef int (*drbd_cmd_handler_f)(struct drbd_conf *, enum drbd_packets cmd, unsigned int to_receive);
@@ -3596,6 +3682,7 @@
 	[P_OV_REPLY]        = { 1, sizeof(struct p_block_req), receive_DataRequest },
 	[P_CSUM_RS_REQUEST] = { 1, sizeof(struct p_block_req), receive_DataRequest },
 	[P_DELAY_PROBE]     = { 0, sizeof(struct p_delay_probe93), receive_skip },
+	[P_OUT_OF_SYNC]     = { 0, sizeof(struct p_block_desc), receive_out_of_sync },
 	/* anything missing from this table is in
 	 * the asender_tbl, see get_asender_cmd */
 	[P_MAX_CMD]	    = { 0, 0, NULL },
@@ -3635,7 +3722,8 @@
 		if (shs) {
 			rv = drbd_recv(mdev, &header->h80.payload, shs);
 			if (unlikely(rv != shs)) {
-				dev_err(DEV, "short read while reading sub header: rv=%d\n", rv);
+				if (!signal_pending(current))
+					dev_warn(DEV, "short read while reading sub header: rv=%d\n", rv);
 				goto err_out;
 			}
 		}
@@ -3707,9 +3795,6 @@
 
 	if (mdev->state.conn == C_STANDALONE)
 		return;
-	if (mdev->state.conn >= C_WF_CONNECTION)
-		dev_err(DEV, "ASSERT FAILED cstate = %s, expected < WFConnection\n",
-				drbd_conn_str(mdev->state.conn));
 
 	/* asender does not clean up anything. it must not interfere, either */
 	drbd_thread_stop(&mdev->asender);
@@ -3738,6 +3823,8 @@
 	atomic_set(&mdev->rs_pending_cnt, 0);
 	wake_up(&mdev->misc_wait);
 
+	del_timer(&mdev->request_timer);
+
 	/* make sure syncer is stopped and w_resume_next_sg queued */
 	del_timer_sync(&mdev->resync_timer);
 	resync_timer_fn((unsigned long)mdev);
@@ -3783,13 +3870,6 @@
 	if (os.conn == C_DISCONNECTING) {
 		wait_event(mdev->net_cnt_wait, atomic_read(&mdev->net_cnt) == 0);
 
-		if (!is_susp(mdev->state)) {
-			/* we must not free the tl_hash
-			 * while application io is still on the fly */
-			wait_event(mdev->misc_wait, !atomic_read(&mdev->ap_bio_cnt));
-			drbd_free_tl_hash(mdev);
-		}
-
 		crypto_free_hash(mdev->cram_hmac_tfm);
 		mdev->cram_hmac_tfm = NULL;
 
@@ -3798,6 +3878,10 @@
 		drbd_request_state(mdev, NS(conn, C_STANDALONE));
 	}
 
+	/* serialize with bitmap writeout triggered by the state change,
+	 * if any. */
+	wait_event(mdev->misc_wait, !test_bit(BITMAP_IO, &mdev->flags));
+
 	/* tcp_close and release of sendpage pages can be deferred.  I don't
 	 * want to use SO_LINGER, because apparently it can be deferred for
 	 * more than 20 seconds (longest time I checked).
@@ -3898,7 +3982,8 @@
 	rv = drbd_recv(mdev, &p->head.payload, expect);
 
 	if (rv != expect) {
-		dev_err(DEV, "short read receiving handshake packet: l=%u\n", rv);
+		if (!signal_pending(current))
+			dev_warn(DEV, "short read receiving handshake packet: l=%u\n", rv);
 		return 0;
 	}
 
@@ -4000,7 +4085,8 @@
 	rv = drbd_recv(mdev, peers_ch, length);
 
 	if (rv != length) {
-		dev_err(DEV, "short read AuthChallenge: l=%u\n", rv);
+		if (!signal_pending(current))
+			dev_warn(DEV, "short read AuthChallenge: l=%u\n", rv);
 		rv = 0;
 		goto fail;
 	}
@@ -4047,7 +4133,8 @@
 	rv = drbd_recv(mdev, response , resp_size);
 
 	if (rv != resp_size) {
-		dev_err(DEV, "short read receiving AuthResponse: l=%u\n", rv);
+		if (!signal_pending(current))
+			dev_warn(DEV, "short read receiving AuthResponse: l=%u\n", rv);
 		rv = 0;
 		goto fail;
 	}
@@ -4099,8 +4186,7 @@
 		h = drbd_connect(mdev);
 		if (h == 0) {
 			drbd_disconnect(mdev);
-			__set_current_state(TASK_INTERRUPTIBLE);
-			schedule_timeout(HZ);
+			schedule_timeout_interruptible(HZ);
 		}
 		if (h == -1) {
 			dev_warn(DEV, "Discarding network configuration.\n");
@@ -4138,7 +4224,7 @@
 	}
 	wake_up(&mdev->state_wait);
 
-	return TRUE;
+	return true;
 }
 
 static int got_Ping(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4154,7 +4240,7 @@
 	if (!test_and_set_bit(GOT_PING_ACK, &mdev->flags))
 		wake_up(&mdev->misc_wait);
 
-	return TRUE;
+	return true;
 }
 
 static int got_IsInSync(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4177,7 +4263,7 @@
 	dec_rs_pending(mdev);
 	atomic_add(blksize >> 9, &mdev->rs_sect_in);
 
-	return TRUE;
+	return true;
 }
 
 /* when we receive the ACK for a write request,
@@ -4201,8 +4287,6 @@
 			return req;
 		}
 	}
-	dev_err(DEV, "_ack_id_to_req: failed to find req %p, sector %llus in list\n",
-		(void *)(unsigned long)id, (unsigned long long)sector);
 	return NULL;
 }
 
@@ -4220,15 +4304,17 @@
 	req = validator(mdev, id, sector);
 	if (unlikely(!req)) {
 		spin_unlock_irq(&mdev->req_lock);
-		dev_err(DEV, "%s: got a corrupt block_id/sector pair\n", func);
-		return FALSE;
+
+		dev_err(DEV, "%s: failed to find req %p, sector %llus\n", func,
+			(void *)(unsigned long)id, (unsigned long long)sector);
+		return false;
 	}
 	__req_mod(req, what, &m);
 	spin_unlock_irq(&mdev->req_lock);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
-	return TRUE;
+	return true;
 }
 
 static int got_BlockAck(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4243,7 +4329,7 @@
 	if (is_syncer_block_id(p->block_id)) {
 		drbd_set_in_sync(mdev, sector, blksize);
 		dec_rs_pending(mdev);
-		return TRUE;
+		return true;
 	}
 	switch (be16_to_cpu(h->command)) {
 	case P_RS_WRITE_ACK:
@@ -4264,7 +4350,7 @@
 		break;
 	default:
 		D_ASSERT(0);
-		return FALSE;
+		return false;
 	}
 
 	return validate_req_change_req_state(mdev, p->block_id, sector,
@@ -4275,20 +4361,44 @@
 {
 	struct p_block_ack *p = (struct p_block_ack *)h;
 	sector_t sector = be64_to_cpu(p->sector);
-
-	if (__ratelimit(&drbd_ratelimit_state))
-		dev_warn(DEV, "Got NegAck packet. Peer is in troubles?\n");
+	int size = be32_to_cpu(p->blksize);
+	struct drbd_request *req;
+	struct bio_and_error m;
 
 	update_peer_seq(mdev, be32_to_cpu(p->seq_num));
 
 	if (is_syncer_block_id(p->block_id)) {
-		int size = be32_to_cpu(p->blksize);
 		dec_rs_pending(mdev);
 		drbd_rs_failed_io(mdev, sector, size);
-		return TRUE;
+		return true;
 	}
-	return validate_req_change_req_state(mdev, p->block_id, sector,
-		_ack_id_to_req, __func__ , neg_acked);
+
+	spin_lock_irq(&mdev->req_lock);
+	req = _ack_id_to_req(mdev, p->block_id, sector);
+	if (!req) {
+		spin_unlock_irq(&mdev->req_lock);
+		if (mdev->net_conf->wire_protocol == DRBD_PROT_A ||
+		    mdev->net_conf->wire_protocol == DRBD_PROT_B) {
+			/* Protocol A has no P_WRITE_ACKs, but has P_NEG_ACKs.
+			   The master bio might already be completed, therefore the
+			   request is no longer in the collision hash.
+			   => Do not try to validate block_id as request. */
+			/* In Protocol B we might already have got a P_RECV_ACK
+			   but then get a P_NEG_ACK after wards. */
+			drbd_set_out_of_sync(mdev, sector, size);
+			return true;
+		} else {
+			dev_err(DEV, "%s: failed to find req %p, sector %llus\n", __func__,
+				(void *)(unsigned long)p->block_id, (unsigned long long)sector);
+			return false;
+		}
+	}
+	__req_mod(req, neg_acked, &m);
+	spin_unlock_irq(&mdev->req_lock);
+
+	if (m.bio)
+		complete_master_bio(mdev, &m);
+	return true;
 }
 
 static int got_NegDReply(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4319,11 +4429,20 @@
 
 	if (get_ldev_if_state(mdev, D_FAILED)) {
 		drbd_rs_complete_io(mdev, sector);
-		drbd_rs_failed_io(mdev, sector, size);
+		switch (be16_to_cpu(h->command)) {
+		case P_NEG_RS_DREPLY:
+			drbd_rs_failed_io(mdev, sector, size);
+		case P_RS_CANCEL:
+			break;
+		default:
+			D_ASSERT(0);
+			put_ldev(mdev);
+			return false;
+		}
 		put_ldev(mdev);
 	}
 
-	return TRUE;
+	return true;
 }
 
 static int got_BarrierAck(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4332,7 +4451,14 @@
 
 	tl_release(mdev, p->barrier, be32_to_cpu(p->set_size));
 
-	return TRUE;
+	if (mdev->state.conn == C_AHEAD &&
+	    atomic_read(&mdev->ap_in_flight) == 0 &&
+	    !test_and_set_bit(AHEAD_TO_SYNC_SOURCE, &mdev->current_epoch->flags)) {
+		mdev->start_resync_timer.expires = jiffies + HZ;
+		add_timer(&mdev->start_resync_timer);
+	}
+
+	return true;
 }
 
 static int got_OVResult(struct drbd_conf *mdev, struct p_header80 *h)
@@ -4353,12 +4479,18 @@
 		ov_oos_print(mdev);
 
 	if (!get_ldev(mdev))
-		return TRUE;
+		return true;
 
 	drbd_rs_complete_io(mdev, sector);
 	dec_rs_pending(mdev);
 
-	if (--mdev->ov_left == 0) {
+	--mdev->ov_left;
+
+	/* let's advance progress step marks only for every other megabyte */
+	if ((mdev->ov_left & 0x200) == 0x200)
+		drbd_advance_rs_marks(mdev, mdev->ov_left);
+
+	if (mdev->ov_left == 0) {
 		w = kmalloc(sizeof(*w), GFP_NOIO);
 		if (w) {
 			w->cb = w_ov_finished;
@@ -4370,12 +4502,12 @@
 		}
 	}
 	put_ldev(mdev);
-	return TRUE;
+	return true;
 }
 
 static int got_skip(struct drbd_conf *mdev, struct p_header80 *h)
 {
-	return TRUE;
+	return true;
 }
 
 struct asender_cmd {
@@ -4403,6 +4535,7 @@
 	[P_STATE_CHG_REPLY] = { sizeof(struct p_req_state_reply), got_RqSReply },
 	[P_RS_IS_IN_SYNC]   = { sizeof(struct p_block_ack), got_IsInSync },
 	[P_DELAY_PROBE]     = { sizeof(struct p_delay_probe93), got_skip },
+	[P_RS_CANCEL]       = { sizeof(struct p_block_ack), got_NegRSDReply},
 	[P_MAX_CMD]	    = { 0, NULL },
 	};
 	if (cmd > P_MAX_CMD || asender_tbl[cmd].process == NULL)
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_req.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_req.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_req.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_req.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,9 +140,14 @@
 	struct hlist_node *n;
 	struct hlist_head *slot;
 
-	/* before we can signal completion to the upper layers,
-	 * we may need to close the current epoch */
+	/* Before we can signal completion to the upper layers,
+	 * we may need to close the current epoch.
+	 * We can skip this, if this request has not even been sent, because we
+	 * did not have a fully established connection yet/anymore, during
+	 * bitmap exchange, or while we are C_AHEAD due to congestion policy.
+	 */
 	if (mdev->state.conn >= C_CONNECTED &&
+	    (s & RQ_NET_SENT) != 0 &&
 	    req->epoch == mdev->newest_tle->br_number)
 		queue_barrier(mdev);
 
@@ -440,7 +445,7 @@
 		req->rq_state |= RQ_LOCAL_COMPLETED;
 		req->rq_state &= ~RQ_LOCAL_PENDING;
 
-		__drbd_chk_io_error(mdev, FALSE);
+		__drbd_chk_io_error(mdev, false);
 		_req_may_be_done_not_susp(req, m);
 		put_ldev(mdev);
 		break;
@@ -461,7 +466,7 @@
 
 		D_ASSERT(!(req->rq_state & RQ_NET_MASK));
 
-		__drbd_chk_io_error(mdev, FALSE);
+		__drbd_chk_io_error(mdev, false);
 		put_ldev(mdev);
 
 		/* no point in retrying if there is no good remote data,
@@ -545,6 +550,14 @@
 
 		break;
 
+	case queue_for_send_oos:
+		req->rq_state |= RQ_NET_QUEUED;
+		req->w.cb =  w_send_oos;
+		drbd_queue_work(&mdev->data.work, &req->w);
+		break;
+
+	case oos_handed_to_network:
+		/* actually the same */
 	case send_canceled:
 		/* treat it the same */
 	case send_failed:
@@ -558,6 +571,9 @@
 
 	case handed_over_to_network:
 		/* assert something? */
+		if (bio_data_dir(req->master_bio) == WRITE)
+			atomic_add(req->size>>9, &mdev->ap_in_flight);
+
 		if (bio_data_dir(req->master_bio) == WRITE &&
 		    mdev->net_conf->wire_protocol == DRBD_PROT_A) {
 			/* this is what is dangerous about protocol A:
@@ -591,6 +607,9 @@
 			dec_ap_pending(mdev);
 		req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
 		req->rq_state |= RQ_NET_DONE;
+		if (req->rq_state & RQ_NET_SENT && req->rq_state & RQ_WRITE)
+			atomic_sub(req->size>>9, &mdev->ap_in_flight);
+
 		/* if it is still queued, we may not complete it here.
 		 * it will be canceled soon. */
 		if (!(req->rq_state & RQ_NET_QUEUED))
@@ -628,14 +647,17 @@
 		req->rq_state |= RQ_NET_OK;
 		D_ASSERT(req->rq_state & RQ_NET_PENDING);
 		dec_ap_pending(mdev);
+		atomic_sub(req->size>>9, &mdev->ap_in_flight);
 		req->rq_state &= ~RQ_NET_PENDING;
 		_req_may_be_done_not_susp(req, m);
 		break;
 
 	case neg_acked:
 		/* assert something? */
-		if (req->rq_state & RQ_NET_PENDING)
+		if (req->rq_state & RQ_NET_PENDING) {
 			dec_ap_pending(mdev);
+			atomic_sub(req->size>>9, &mdev->ap_in_flight);
+		}
 		req->rq_state &= ~(RQ_NET_OK|RQ_NET_PENDING);
 
 		req->rq_state |= RQ_NET_DONE;
@@ -690,8 +712,11 @@
 			dev_err(DEV, "FIXME (barrier_acked but pending)\n");
 			list_move(&req->tl_requests, &mdev->out_of_sequence_requests);
 		}
-		D_ASSERT(req->rq_state & RQ_NET_SENT);
-		req->rq_state |= RQ_NET_DONE;
+		if ((req->rq_state & RQ_NET_MASK) != 0) {
+			req->rq_state |= RQ_NET_DONE;
+			if (mdev->net_conf->wire_protocol == DRBD_PROT_A)
+				atomic_sub(req->size>>9, &mdev->ap_in_flight);
+		}
 		_req_may_be_done(req, m); /* Allowed while state.susp */
 		break;
 
@@ -738,14 +763,14 @@
 	return 0 == drbd_bm_count_bits(mdev, sbnr, ebnr);
 }
 
-static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio)
+static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, unsigned long start_time)
 {
 	const int rw = bio_rw(bio);
 	const int size = bio->bi_size;
 	const sector_t sector = bio->bi_sector;
 	struct drbd_tl_epoch *b = NULL;
 	struct drbd_request *req;
-	int local, remote;
+	int local, remote, send_oos = 0;
 	int err = -EIO;
 	int ret = 0;
 
@@ -759,6 +784,7 @@
 		bio_endio(bio, -ENOMEM);
 		return 0;
 	}
+	req->start_time = start_time;
 
 	local = get_ldev(mdev);
 	if (!local) {
@@ -808,9 +834,9 @@
 		drbd_al_begin_io(mdev, sector);
 	}
 
-	remote = remote && (mdev->state.pdsk == D_UP_TO_DATE ||
-			    (mdev->state.pdsk == D_INCONSISTENT &&
-			     mdev->state.conn >= C_CONNECTED));
+	remote = remote && drbd_should_do_remote(mdev->state);
+	send_oos = rw == WRITE && drbd_should_send_oos(mdev->state);
+	D_ASSERT(!(remote && send_oos));
 
 	if (!(local || remote) && !is_susp(mdev->state)) {
 		if (__ratelimit(&drbd_ratelimit_state))
@@ -824,7 +850,7 @@
 	 * but there is a race between testing the bit and pointer outside the
 	 * spinlock, and grabbing the spinlock.
 	 * if we lost that race, we retry.  */
-	if (rw == WRITE && remote &&
+	if (rw == WRITE && (remote || send_oos) &&
 	    mdev->unused_spare_tle == NULL &&
 	    test_bit(CREATE_BARRIER, &mdev->flags)) {
 allocate_barrier:
@@ -842,18 +868,19 @@
 	if (is_susp(mdev->state)) {
 		/* If we got suspended, use the retry mechanism of
 		   generic_make_request() to restart processing of this
-		   bio. In the next call to drbd_make_request_26
+		   bio. In the next call to drbd_make_request
 		   we sleep in inc_ap_bio() */
 		ret = 1;
 		spin_unlock_irq(&mdev->req_lock);
 		goto fail_free_complete;
 	}
 
-	if (remote) {
-		remote = (mdev->state.pdsk == D_UP_TO_DATE ||
-			    (mdev->state.pdsk == D_INCONSISTENT &&
-			     mdev->state.conn >= C_CONNECTED));
-		if (!remote)
+	if (remote || send_oos) {
+		remote = drbd_should_do_remote(mdev->state);
+		send_oos = rw == WRITE && drbd_should_send_oos(mdev->state);
+		D_ASSERT(!(remote && send_oos));
+
+		if (!(remote || send_oos))
 			dev_warn(DEV, "lost connection while grabbing the req_lock!\n");
 		if (!(local || remote)) {
 			dev_err(DEV, "IO ERROR: neither local nor remote disk\n");
@@ -866,7 +893,7 @@
 		mdev->unused_spare_tle = b;
 		b = NULL;
 	}
-	if (rw == WRITE && remote &&
+	if (rw == WRITE && (remote || send_oos) &&
 	    mdev->unused_spare_tle == NULL &&
 	    test_bit(CREATE_BARRIER, &mdev->flags)) {
 		/* someone closed the current epoch
@@ -889,7 +916,7 @@
 	 * barrier packet.  To get the write ordering right, we only have to
 	 * make sure that, if this is a write request and it triggered a
 	 * barrier packet, this request is queued within the same spinlock. */
-	if (remote && mdev->unused_spare_tle &&
+	if ((remote || send_oos) && mdev->unused_spare_tle &&
 	    test_and_clear_bit(CREATE_BARRIER, &mdev->flags)) {
 		_tl_add_barrier(mdev, mdev->unused_spare_tle);
 		mdev->unused_spare_tle = NULL;
@@ -937,6 +964,34 @@
 				? queue_for_net_write
 				: queue_for_net_read);
 	}
+	if (send_oos && drbd_set_out_of_sync(mdev, sector, size))
+		_req_mod(req, queue_for_send_oos);
+
+	if (remote &&
+	    mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96) {
+		int congested = 0;
+
+		if (mdev->net_conf->cong_fill &&
+		    atomic_read(&mdev->ap_in_flight) >= mdev->net_conf->cong_fill) {
+			dev_info(DEV, "Congestion-fill threshold reached\n");
+			congested = 1;
+		}
+
+		if (mdev->act_log->used >= mdev->net_conf->cong_extents) {
+			dev_info(DEV, "Congestion-extents threshold reached\n");
+			congested = 1;
+		}
+
+		if (congested) {
+			queue_barrier(mdev); /* last barrier, after mirrored writes */
+
+			if (mdev->net_conf->on_congestion == OC_PULL_AHEAD)
+				_drbd_set_state(_NS(mdev, conn, C_AHEAD), 0, NULL);
+			else  /*mdev->net_conf->on_congestion == OC_DISCONNECT */
+				_drbd_set_state(_NS(mdev, conn, C_DISCONNECTING), 0, NULL);
+		}
+	}
+
 	spin_unlock_irq(&mdev->req_lock);
 	kfree(b); /* if someone else has beaten us to it... */
 
@@ -949,9 +1004,9 @@
 		 * stable storage, and this is a WRITE, we may not even submit
 		 * this bio. */
 		if (get_ldev(mdev)) {
-			if (FAULT_ACTIVE(mdev, rw == WRITE ? DRBD_FAULT_DT_WR
-					     : rw == READ  ? DRBD_FAULT_DT_RD
-					     :               DRBD_FAULT_DT_RA))
+			if (drbd_insert_fault(mdev,   rw == WRITE ? DRBD_FAULT_DT_WR
+						    : rw == READ  ? DRBD_FAULT_DT_RD
+						    :               DRBD_FAULT_DT_RA))
 				bio_endio(req->private_bio, -EIO);
 			else
 				generic_make_request(req->private_bio);
@@ -960,10 +1015,6 @@
 			bio_endio(req->private_bio, -EIO);
 	}
 
-	/* we need to plug ALWAYS since we possibly need to kick lo_dev.
-	 * we plug after submit, so we won't miss an unplug event */
-	drbd_plug_device(mdev);
-
 	return 0;
 
 fail_conflicting:
@@ -1022,16 +1073,19 @@
 	return 0;
 }
 
-int drbd_make_request_26(struct request_queue *q, struct bio *bio)
+int drbd_make_request(struct request_queue *q, struct bio *bio)
 {
 	unsigned int s_enr, e_enr;
 	struct drbd_conf *mdev = (struct drbd_conf *) q->queuedata;
+	unsigned long start_time;
 
 	if (drbd_fail_request_early(mdev, bio_data_dir(bio) & WRITE)) {
 		bio_endio(bio, -EPERM);
 		return 0;
 	}
 
+	start_time = jiffies;
+
 	/*
 	 * what we "blindly" assume:
 	 */
@@ -1046,12 +1100,12 @@
 
 	if (likely(s_enr == e_enr)) {
 		inc_ap_bio(mdev, 1);
-		return drbd_make_request_common(mdev, bio);
+		return drbd_make_request_common(mdev, bio, start_time);
 	}
 
 	/* can this bio be split generically?
 	 * Maybe add our own split-arbitrary-bios function. */
-	if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_SEGMENT_SIZE) {
+	if (bio->bi_vcnt != 1 || bio->bi_idx != 0 || bio->bi_size > DRBD_MAX_BIO_SIZE) {
 		/* rather error out here than BUG in bio_split */
 		dev_err(DEV, "bio would need to, but cannot, be split: "
 		    "(vcnt=%u,idx=%u,size=%u,sector=%llu)\n",
@@ -1073,11 +1127,7 @@
 		const int sps = 1 << HT_SHIFT; /* sectors per slot */
 		const int mask = sps - 1;
 		const sector_t first_sectors = sps - (sect & mask);
-		bp = bio_split(bio,
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,28)
-				bio_split_pool,
-#endif
-				first_sectors);
+		bp = bio_split(bio, first_sectors);
 
 		/* we need to get a "reference count" (ap_bio_cnt)
 		 * to avoid races with the disconnect/reconnect/suspend code.
@@ -1088,10 +1138,10 @@
 
 		D_ASSERT(e_enr == s_enr + 1);
 
-		while (drbd_make_request_common(mdev, &bp->bio1))
+		while (drbd_make_request_common(mdev, &bp->bio1, start_time))
 			inc_ap_bio(mdev, 1);
 
-		while (drbd_make_request_common(mdev, &bp->bio2))
+		while (drbd_make_request_common(mdev, &bp->bio2, start_time))
 			inc_ap_bio(mdev, 1);
 
 		dec_ap_bio(mdev);
@@ -1102,7 +1152,7 @@
 }
 
 /* This is called by bio_add_page().  With this function we reduce
- * the number of BIOs that span over multiple DRBD_MAX_SEGMENT_SIZEs
+ * the number of BIOs that span over multiple DRBD_MAX_BIO_SIZEs
  * units (was AL_EXTENTs).
  *
  * we do the calculation within the lower 32bit of the byte offsets,
@@ -1112,7 +1162,7 @@
  * As long as the BIO is empty we have to allow at least one bvec,
  * regardless of size and offset.  so the resulting bio may still
  * cross extent boundaries.  those are dealt with (bio_split) in
- * drbd_make_request_26.
+ * drbd_make_request.
  */
 int drbd_merge_bvec(struct request_queue *q, struct bvec_merge_data *bvm, struct bio_vec *bvec)
 {
@@ -1122,8 +1172,8 @@
 	unsigned int bio_size = bvm->bi_size;
 	int limit, backing_limit;
 
-	limit = DRBD_MAX_SEGMENT_SIZE
-	      - ((bio_offset & (DRBD_MAX_SEGMENT_SIZE-1)) + bio_size);
+	limit = DRBD_MAX_BIO_SIZE
+	      - ((bio_offset & (DRBD_MAX_BIO_SIZE-1)) + bio_size);
 	if (limit < 0)
 		limit = 0;
 	if (bio_size == 0) {
@@ -1140,3 +1190,42 @@
 	}
 	return limit;
 }
+
+void request_timer_fn(unsigned long data)
+{
+	struct drbd_conf *mdev = (struct drbd_conf *) data;
+	struct drbd_request *req; /* oldest request */
+	struct list_head *le;
+	unsigned long et = 0; /* effective timeout = ko_count * timeout */
+
+	if (get_net_conf(mdev)) {
+		et = mdev->net_conf->timeout*HZ/10 * mdev->net_conf->ko_count;
+		put_net_conf(mdev);
+	}
+	if (!et || mdev->state.conn < C_WF_REPORT_PARAMS)
+		return; /* Recurring timer stopped */
+
+	spin_lock_irq(&mdev->req_lock);
+	le = &mdev->oldest_tle->requests;
+	if (list_empty(le)) {
+		spin_unlock_irq(&mdev->req_lock);
+		mod_timer(&mdev->request_timer, jiffies + et);
+		return;
+	}
+
+	le = le->prev;
+	req = list_entry(le, struct drbd_request, tl_requests);
+	if (time_is_before_eq_jiffies(req->start_time + et)) {
+		if (req->rq_state & RQ_NET_PENDING) {
+			dev_warn(DEV, "Remote failed to finish a request within ko-count * timeout\n");
+			_drbd_set_state(_NS(mdev, conn, C_TIMEOUT), CS_VERBOSE, NULL);
+		} else {
+			dev_warn(DEV, "Local backing block device frozen?\n");
+			mod_timer(&mdev->request_timer, jiffies + et);
+		}
+	} else {
+		mod_timer(&mdev->request_timer, req->start_time + et);
+	}
+
+	spin_unlock_irq(&mdev->req_lock);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_req.h linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_req.h
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_req.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_req.h	2011-05-19 00:06:34.000000000 -0400
@@ -82,14 +82,16 @@
 	to_be_submitted,
 
 	/* XXX yes, now I am inconsistent...
-	 * these two are not "events" but "actions"
+	 * these are not "events" but "actions"
 	 * oh, well... */
 	queue_for_net_write,
 	queue_for_net_read,
+	queue_for_send_oos,
 
 	send_canceled,
 	send_failed,
 	handed_over_to_network,
+	oos_handed_to_network,
 	connection_lost_while_pending,
 	read_retry_remote_canceled,
 	recv_acked_by_peer,
@@ -289,7 +291,6 @@
 		req->epoch       = 0;
 		req->sector      = bio_src->bi_sector;
 		req->size        = bio_src->bi_size;
-		req->start_time  = jiffies;
 		INIT_HLIST_NODE(&req->colision);
 		INIT_LIST_HEAD(&req->tl_requests);
 		INIT_LIST_HEAD(&req->w.list);
@@ -321,6 +322,7 @@
 		struct bio_and_error *m);
 extern void complete_master_bio(struct drbd_conf *mdev,
 		struct bio_and_error *m);
+extern void request_timer_fn(unsigned long data);
 
 /* use this if you don't want to deal with calling complete_master_bio()
  * outside the spinlock, e.g. when walking some list on cleanup. */
@@ -338,23 +340,43 @@
 	return rv;
 }
 
-/* completion of master bio is outside of spinlock.
- * If you need it irqsave, do it your self!
- * Which means: don't use from bio endio callback. */
+/* completion of master bio is outside of our spinlock.
+ * We still may or may not be inside some irqs disabled section
+ * of the lower level driver completion callback, so we need to
+ * spin_lock_irqsave here. */
 static inline int req_mod(struct drbd_request *req,
 		enum drbd_req_event what)
 {
+	unsigned long flags;
 	struct drbd_conf *mdev = req->mdev;
 	struct bio_and_error m;
 	int rv;
 
-	spin_lock_irq(&mdev->req_lock);
+	spin_lock_irqsave(&mdev->req_lock, flags);
 	rv = __req_mod(req, what, &m);
-	spin_unlock_irq(&mdev->req_lock);
+	spin_unlock_irqrestore(&mdev->req_lock, flags);
 
 	if (m.bio)
 		complete_master_bio(mdev, &m);
 
 	return rv;
 }
+
+static inline bool drbd_should_do_remote(union drbd_state s)
+{
+	return s.pdsk == D_UP_TO_DATE ||
+		(s.pdsk >= D_INCONSISTENT &&
+		 s.conn >= C_WF_BITMAP_T &&
+		 s.conn < C_AHEAD);
+	/* Before proto 96 that was >= CONNECTED instead of >= C_WF_BITMAP_T.
+	   That is equivalent since before 96 IO was frozen in the C_WF_BITMAP*
+	   states. */
+}
+static inline bool drbd_should_send_oos(union drbd_state s)
+{
+	return s.conn == C_AHEAD || s.conn == C_WF_BITMAP_S;
+	/* pdsk = D_INCONSISTENT as a consequence. Protocol 96 check not necessary
+	   since we enter state C_AHEAD only if proto >= 96 */
+}
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_strings.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_strings.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_strings.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_strings.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,6 +48,8 @@
 	[C_PAUSED_SYNC_T]    = "PausedSyncT",
 	[C_VERIFY_S]         = "VerifyS",
 	[C_VERIFY_T]         = "VerifyT",
+	[C_AHEAD]            = "Ahead",
+	[C_BEHIND]           = "Behind",
 };
 
 static const char *drbd_role_s_names[] = {
@@ -92,7 +94,7 @@
 const char *drbd_conn_str(enum drbd_conns s)
 {
 	/* enums are unsigned... */
-	return s > C_PAUSED_SYNC_T ? "TOO_LARGE" : drbd_conn_s_names[s];
+	return s > C_BEHIND ? "TOO_LARGE" : drbd_conn_s_names[s];
 }
 
 const char *drbd_role_str(enum drbd_role s)
@@ -105,7 +107,7 @@
 	return s > D_UP_TO_DATE    ? "TOO_LARGE" : drbd_disk_s_names[s];
 }
 
-const char *drbd_set_st_err_str(enum drbd_state_ret_codes err)
+const char *drbd_set_st_err_str(enum drbd_state_rv err)
 {
 	return err <= SS_AFTER_LAST_ERROR ? "TOO_SMALL" :
 	       err > SS_TWO_PRIMARIES ? "TOO_LARGE"
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_vli.h linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_vli.h
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_vli.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_vli.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
  * the bitmap transfer time can take much too long,
  * if transmitted in plain text.
  *
- * We try to reduce the transfered bitmap information
+ * We try to reduce the transferred bitmap information
  * by encoding runlengths of bit polarity.
  *
  * We never actually need to encode a "zero" (runlengths are positive).
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_worker.c linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_worker.c
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_worker.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_worker.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,18 +39,17 @@
 #include "drbd_req.h"
 
 static int w_make_ov_request(struct drbd_conf *mdev, struct drbd_work *w, int cancel);
+static int w_make_resync_request(struct drbd_conf *mdev,
+				 struct drbd_work *w, int cancel);
 
 
 
-/* defined here:
-   drbd_md_io_complete
-   drbd_endio_sec
-   drbd_endio_pri
-
- * more endio handlers:
-   atodb_endio in drbd_actlog.c
-   drbd_bm_async_io_complete in drbd_bitmap.c
-
+/* endio handlers:
+ *   drbd_md_io_complete (defined here)
+ *   drbd_endio_pri (defined here)
+ *   drbd_endio_sec (defined here)
+ *   bm_async_io_complete (defined in drbd_bitmap.c)
+ *
  * For all these callbacks, note the following:
  * The callbacks will be called in irq context by the IDE drivers,
  * and in Softirqs/Tasklets/BH context by the SCSI drivers.
@@ -94,7 +93,7 @@
 	if (list_empty(&mdev->read_ee))
 		wake_up(&mdev->ee_wait);
 	if (test_bit(__EE_WAS_ERROR, &e->flags))
-		__drbd_chk_io_error(mdev, FALSE);
+		__drbd_chk_io_error(mdev, false);
 	spin_unlock_irqrestore(&mdev->req_lock, flags);
 
 	drbd_queue_work(&mdev->data.work, &e->w);
@@ -137,7 +136,7 @@
 		: list_empty(&mdev->active_ee);
 
 	if (test_bit(__EE_WAS_ERROR, &e->flags))
-		__drbd_chk_io_error(mdev, FALSE);
+		__drbd_chk_io_error(mdev, false);
 	spin_unlock_irqrestore(&mdev->req_lock, flags);
 
 	if (is_syncer_req)
@@ -163,14 +162,15 @@
 	int uptodate = bio_flagged(bio, BIO_UPTODATE);
 	int is_write = bio_data_dir(bio) == WRITE;
 
-	if (error)
+	if (error && __ratelimit(&drbd_ratelimit_state))
 		dev_warn(DEV, "%s: error=%d s=%llus\n",
 				is_write ? "write" : "read", error,
 				(unsigned long long)e->sector);
 	if (!error && !uptodate) {
-		dev_warn(DEV, "%s: setting error to -EIO s=%llus\n",
-				is_write ? "write" : "read",
-				(unsigned long long)e->sector);
+		if (__ratelimit(&drbd_ratelimit_state))
+			dev_warn(DEV, "%s: setting error to -EIO s=%llus\n",
+					is_write ? "write" : "read",
+					(unsigned long long)e->sector);
 		/* strange behavior of some lower level drivers...
 		 * fail the request by clearing the uptodate flag,
 		 * but do not return any error?! */
@@ -250,13 +250,6 @@
 	return w_send_read_req(mdev, w, 0);
 }
 
-int w_resync_inactive(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
-{
-	ERR_IF(cancel) return 1;
-	dev_err(DEV, "resync inactive, but callback triggered??\n");
-	return 1; /* Simply ignore this! */
-}
-
 void drbd_csum_ee(struct drbd_conf *mdev, struct crypto_hash *tfm, struct drbd_epoch_entry *e, void *digest)
 {
 	struct hash_desc desc;
@@ -355,7 +348,7 @@
 	if (!get_ldev(mdev))
 		return -EIO;
 
-	if (drbd_rs_should_slow_down(mdev))
+	if (drbd_rs_should_slow_down(mdev, sector))
 		goto defer;
 
 	/* GFP_TRY, because if there is no memory available right now, this may
@@ -373,9 +366,10 @@
 	if (drbd_submit_ee(mdev, e, READ, DRBD_FAULT_RS_RD) == 0)
 		return 0;
 
-	/* drbd_submit_ee currently fails for one reason only:
-	 * not being able to allocate enough bios.
-	 * Is dropping the connection going to help? */
+	/* If it failed because of ENOMEM, retry should help.  If it failed
+	 * because bio_add_page failed (probably broken lower level driver),
+	 * retry may or may not help.
+	 * If it does not, you may need to force disconnect. */
 	spin_lock_irq(&mdev->req_lock);
 	list_del(&e->w.list);
 	spin_unlock_irq(&mdev->req_lock);
@@ -386,26 +380,25 @@
 	return -EAGAIN;
 }
 
-void resync_timer_fn(unsigned long data)
+int w_resync_timer(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 {
-	struct drbd_conf *mdev = (struct drbd_conf *) data;
-	int queue;
-
-	queue = 1;
 	switch (mdev->state.conn) {
 	case C_VERIFY_S:
-		mdev->resync_work.cb = w_make_ov_request;
+		w_make_ov_request(mdev, w, cancel);
 		break;
 	case C_SYNC_TARGET:
-		mdev->resync_work.cb = w_make_resync_request;
+		w_make_resync_request(mdev, w, cancel);
 		break;
-	default:
-		queue = 0;
-		mdev->resync_work.cb = w_resync_inactive;
 	}
 
-	/* harmless race: list_empty outside data.work.q_lock */
-	if (list_empty(&mdev->resync_work.list) && queue)
+	return 1;
+}
+
+void resync_timer_fn(unsigned long data)
+{
+	struct drbd_conf *mdev = (struct drbd_conf *) data;
+
+	if (list_empty(&mdev->resync_work.list))
 		drbd_queue_work(&mdev->data.work, &mdev->resync_work);
 }
 
@@ -438,7 +431,7 @@
 		fb->values[i] += value;
 }
 
-int drbd_rs_controller(struct drbd_conf *mdev)
+static int drbd_rs_controller(struct drbd_conf *mdev)
 {
 	unsigned int sect_in;  /* Number of sectors that came in since the last turn */
 	unsigned int want;     /* The number of sectors we want in the proxy */
@@ -492,29 +485,36 @@
 	return req_sect;
 }
 
-int w_make_resync_request(struct drbd_conf *mdev,
-		struct drbd_work *w, int cancel)
+static int drbd_rs_number_requests(struct drbd_conf *mdev)
+{
+	int number;
+	if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
+		number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
+		mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
+	} else {
+		mdev->c_sync_rate = mdev->sync_conf.rate;
+		number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
+	}
+
+	/* ignore the amount of pending requests, the resync controller should
+	 * throttle down to incoming reply rate soon enough anyways. */
+	return number;
+}
+
+static int w_make_resync_request(struct drbd_conf *mdev,
+				 struct drbd_work *w, int cancel)
 {
 	unsigned long bit;
 	sector_t sector;
 	const sector_t capacity = drbd_get_capacity(mdev->this_bdev);
-	int max_segment_size;
-	int number, rollback_i, size, pe, mx;
+	int max_bio_size;
+	int number, rollback_i, size;
 	int align, queued, sndbuf;
 	int i = 0;
 
 	if (unlikely(cancel))
 		return 1;
 
-	if (unlikely(mdev->state.conn < C_CONNECTED)) {
-		dev_err(DEV, "Confused in w_make_resync_request()! cstate < Connected");
-		return 0;
-	}
-
-	if (mdev->state.conn != C_SYNC_TARGET)
-		dev_err(DEV, "%s in w_make_resync_request\n",
-			drbd_conn_str(mdev->state.conn));
-
 	if (mdev->rs_total == 0) {
 		/* empty resync? */
 		drbd_resync_finished(mdev);
@@ -527,49 +527,19 @@
 		   to continue resync with a broken disk makes no sense at
 		   all */
 		dev_err(DEV, "Disk broke down during resync!\n");
-		mdev->resync_work.cb = w_resync_inactive;
 		return 1;
 	}
 
 	/* starting with drbd 8.3.8, we can handle multi-bio EEs,
 	 * if it should be necessary */
-	max_segment_size =
-		mdev->agreed_pro_version < 94 ? queue_max_segment_size(mdev->rq_queue) :
-		mdev->agreed_pro_version < 95 ?	DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_SEGMENT_SIZE;
-
-	if (mdev->rs_plan_s.size) { /* mdev->sync_conf.c_plan_ahead */
-		number = drbd_rs_controller(mdev) >> (BM_BLOCK_SHIFT - 9);
-		mdev->c_sync_rate = number * HZ * (BM_BLOCK_SIZE / 1024) / SLEEP_TIME;
-	} else {
-		mdev->c_sync_rate = mdev->sync_conf.rate;
-		number = SLEEP_TIME * mdev->c_sync_rate  / ((BM_BLOCK_SIZE / 1024) * HZ);
-	}
+	max_bio_size =
+		mdev->agreed_pro_version < 94 ? queue_max_hw_sectors(mdev->rq_queue) << 9 :
+		mdev->agreed_pro_version < 95 ?	DRBD_MAX_SIZE_H80_PACKET : DRBD_MAX_BIO_SIZE;
 
-	/* Throttle resync on lower level disk activity, which may also be
-	 * caused by application IO on Primary/SyncTarget.
-	 * Keep this after the call to drbd_rs_controller, as that assumes
-	 * to be called as precisely as possible every SLEEP_TIME,
-	 * and would be confused otherwise. */
-	if (drbd_rs_should_slow_down(mdev))
+	number = drbd_rs_number_requests(mdev);
+	if (number == 0)
 		goto requeue;
 
-	mutex_lock(&mdev->data.mutex);
-	if (mdev->data.socket)
-		mx = mdev->data.socket->sk->sk_rcvbuf / sizeof(struct p_block_req);
-	else
-		mx = 1;
-	mutex_unlock(&mdev->data.mutex);
-
-	/* For resync rates >160MB/sec, allow more pending RS requests */
-	if (number > mx)
-		mx = number;
-
-	/* Limit the number of pending RS requests to no more than the peer's receive buffer */
-	pe = atomic_read(&mdev->rs_pending_cnt);
-	if ((pe + number) > mx) {
-		number = mx - pe;
-	}
-
 	for (i = 0; i < number; i++) {
 		/* Stop generating RS requests, when half of the send buffer is filled */
 		mutex_lock(&mdev->data.mutex);
@@ -588,16 +558,16 @@
 		size = BM_BLOCK_SIZE;
 		bit  = drbd_bm_find_next(mdev, mdev->bm_resync_fo);
 
-		if (bit == -1UL) {
+		if (bit == DRBD_END_OF_BITMAP) {
 			mdev->bm_resync_fo = drbd_bm_bits(mdev);
-			mdev->resync_work.cb = w_resync_inactive;
 			put_ldev(mdev);
 			return 1;
 		}
 
 		sector = BM_BIT_TO_SECT(bit);
 
-		if (drbd_try_rs_begin_io(mdev, sector)) {
+		if (drbd_rs_should_slow_down(mdev, sector) ||
+		    drbd_try_rs_begin_io(mdev, sector)) {
 			mdev->bm_resync_fo = bit;
 			goto requeue;
 		}
@@ -608,7 +578,7 @@
 			goto next_sector;
 		}
 
-#if DRBD_MAX_SEGMENT_SIZE > BM_BLOCK_SIZE
+#if DRBD_MAX_BIO_SIZE > BM_BLOCK_SIZE
 		/* try to find some adjacent bits.
 		 * we stop if we have already the maximum req size.
 		 *
@@ -618,7 +588,7 @@
 		align = 1;
 		rollback_i = i;
 		for (;;) {
-			if (size + BM_BLOCK_SIZE > max_segment_size)
+			if (size + BM_BLOCK_SIZE > max_bio_size)
 				break;
 
 			/* Be always aligned */
@@ -685,7 +655,6 @@
 		 * resync data block, and the last bit is cleared.
 		 * until then resync "work" is "inactive" ...
 		 */
-		mdev->resync_work.cb = w_resync_inactive;
 		put_ldev(mdev);
 		return 1;
 	}
@@ -706,27 +675,18 @@
 	if (unlikely(cancel))
 		return 1;
 
-	if (unlikely(mdev->state.conn < C_CONNECTED)) {
-		dev_err(DEV, "Confused in w_make_ov_request()! cstate < Connected");
-		return 0;
-	}
-
-	number = SLEEP_TIME*mdev->sync_conf.rate / ((BM_BLOCK_SIZE/1024)*HZ);
-	if (atomic_read(&mdev->rs_pending_cnt) > number)
-		goto requeue;
-
-	number -= atomic_read(&mdev->rs_pending_cnt);
+	number = drbd_rs_number_requests(mdev);
 
 	sector = mdev->ov_position;
 	for (i = 0; i < number; i++) {
 		if (sector >= capacity) {
-			mdev->resync_work.cb = w_resync_inactive;
 			return 1;
 		}
 
 		size = BM_BLOCK_SIZE;
 
-		if (drbd_try_rs_begin_io(mdev, sector)) {
+		if (drbd_rs_should_slow_down(mdev, sector) ||
+		    drbd_try_rs_begin_io(mdev, sector)) {
 			mdev->ov_position = sector;
 			goto requeue;
 		}
@@ -744,11 +704,33 @@
 	mdev->ov_position = sector;
 
  requeue:
+	mdev->rs_in_flight += (i << (BM_BLOCK_SHIFT - 9));
 	mod_timer(&mdev->resync_timer, jiffies + SLEEP_TIME);
 	return 1;
 }
 
 
+void start_resync_timer_fn(unsigned long data)
+{
+	struct drbd_conf *mdev = (struct drbd_conf *) data;
+
+	drbd_queue_work(&mdev->data.work, &mdev->start_resync_work);
+}
+
+int w_start_resync(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+	if (atomic_read(&mdev->unacked_cnt) || atomic_read(&mdev->rs_pending_cnt)) {
+		dev_warn(DEV, "w_start_resync later...\n");
+		mdev->start_resync_timer.expires = jiffies + HZ/10;
+		add_timer(&mdev->start_resync_timer);
+		return 1;
+	}
+
+	drbd_start_resync(mdev, C_SYNC_SOURCE);
+	clear_bit(AHEAD_TO_SYNC_SOURCE, &mdev->current_epoch->flags);
+	return 1;
+}
+
 int w_ov_finished(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
 {
 	kfree(w);
@@ -782,6 +764,7 @@
 	union drbd_state os, ns;
 	struct drbd_work *w;
 	char *khelper_cmd = NULL;
+	int verify_done = 0;
 
 	/* Remove all elements from the resync LRU. Since future actions
 	 * might set bits in the (main) bitmap, then the entries in the
@@ -792,9 +775,7 @@
 		 * queue (or even the read operations for those packets
 		 * is not finished by now).   Retry in 100ms. */
 
-		drbd_kick_lo(mdev);
-		__set_current_state(TASK_INTERRUPTIBLE);
-		schedule_timeout(HZ / 10);
+		schedule_timeout_interruptible(HZ / 10);
 		w = kmalloc(sizeof(struct drbd_work), GFP_ATOMIC);
 		if (w) {
 			w->cb = w_resync_finished;
@@ -819,6 +800,8 @@
 	spin_lock_irq(&mdev->req_lock);
 	os = mdev->state;
 
+	verify_done = (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T);
+
 	/* This protects us against multiple calls (that can happen in the presence
 	   of application IO), and against connectivity loss just before we arrive here. */
 	if (os.conn <= C_CONNECTED)
@@ -828,8 +811,7 @@
 	ns.conn = C_CONNECTED;
 
 	dev_info(DEV, "%s done (total %lu sec; paused %lu sec; %lu K/sec)\n",
-	     (os.conn == C_VERIFY_S || os.conn == C_VERIFY_T) ?
-	     "Online verify " : "Resync",
+	     verify_done ? "Online verify " : "Resync",
 	     dt + mdev->rs_paused, mdev->rs_paused, dbdt);
 
 	n_oos = drbd_bm_total_weight(mdev);
@@ -887,14 +869,18 @@
 			}
 		}
 
-		drbd_uuid_set_bm(mdev, 0UL);
-
-		if (mdev->p_uuid) {
-			/* Now the two UUID sets are equal, update what we
-			 * know of the peer. */
-			int i;
-			for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
-				mdev->p_uuid[i] = mdev->ldev->md.uuid[i];
+		if (!(os.conn == C_VERIFY_S || os.conn == C_VERIFY_T)) {
+			/* for verify runs, we don't update uuids here,
+			 * so there would be nothing to report. */
+			drbd_uuid_set_bm(mdev, 0UL);
+			drbd_print_uuids(mdev, "updated UUIDs");
+			if (mdev->p_uuid) {
+				/* Now the two UUID sets are equal, update what we
+				 * know of the peer. */
+				int i;
+				for (i = UI_CURRENT ; i <= UI_HISTORY_END ; i++)
+					mdev->p_uuid[i] = mdev->ldev->md.uuid[i];
+			}
 		}
 	}
 
@@ -906,15 +892,11 @@
 	mdev->rs_total  = 0;
 	mdev->rs_failed = 0;
 	mdev->rs_paused = 0;
-	mdev->ov_start_sector = 0;
+	if (verify_done)
+		mdev->ov_start_sector = 0;
 
 	drbd_md_sync(mdev);
 
-	if (test_and_clear_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags)) {
-		dev_info(DEV, "Writing the whole bitmap\n");
-		drbd_queue_bitmap_io(mdev, &drbd_bm_write, NULL, "write from resync_finished");
-	}
-
 	if (khelper_cmd)
 		drbd_khelper(mdev, khelper_cmd);
 
@@ -995,7 +977,9 @@
 		put_ldev(mdev);
 	}
 
-	if (likely((e->flags & EE_WAS_ERROR) == 0)) {
+	if (mdev->state.conn == C_AHEAD) {
+		ok = drbd_send_ack(mdev, P_RS_CANCEL, e);
+	} else if (likely((e->flags & EE_WAS_ERROR) == 0)) {
 		if (likely(mdev->state.pdsk >= D_INCONSISTENT)) {
 			inc_rs_pending(mdev);
 			ok = drbd_send_block(mdev, P_RS_DATA_REPLY, e);
@@ -1097,25 +1081,27 @@
 	if (unlikely(cancel))
 		goto out;
 
-	if (unlikely((e->flags & EE_WAS_ERROR) != 0))
-		goto out;
-
 	digest_size = crypto_hash_digestsize(mdev->verify_tfm);
-	/* FIXME if this allocation fails, online verify will not terminate! */
 	digest = kmalloc(digest_size, GFP_NOIO);
-	if (digest) {
-		drbd_csum_ee(mdev, mdev->verify_tfm, e, digest);
-		inc_rs_pending(mdev);
-		ok = drbd_send_drequest_csum(mdev, e->sector, e->size,
-					     digest, digest_size, P_OV_REPLY);
-		if (!ok)
-			dec_rs_pending(mdev);
-		kfree(digest);
+	if (!digest) {
+		ok = 0;	/* terminate the connection in case the allocation failed */
+		goto out;
 	}
 
+	if (likely(!(e->flags & EE_WAS_ERROR)))
+		drbd_csum_ee(mdev, mdev->verify_tfm, e, digest);
+	else
+		memset(digest, 0, digest_size);
+
+	inc_rs_pending(mdev);
+	ok = drbd_send_drequest_csum(mdev, e->sector, e->size,
+				     digest, digest_size, P_OV_REPLY);
+	if (!ok)
+		dec_rs_pending(mdev);
+	kfree(digest);
+
 out:
 	drbd_free_ee(mdev, e);
-
 	dec_unacked(mdev);
 
 	return ok;
@@ -1130,7 +1116,6 @@
 		mdev->ov_last_oos_size = size>>9;
 	}
 	drbd_set_out_of_sync(mdev, sector, size);
-	set_bit(WRITE_BM_AFTER_RESYNC, &mdev->flags);
 }
 
 int w_e_end_ov_reply(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
@@ -1166,10 +1151,6 @@
 			eq = !memcmp(digest, di->digest, digest_size);
 			kfree(digest);
 		}
-	} else {
-		ok = drbd_send_ack(mdev, P_NEG_RS_DREPLY, e);
-		if (__ratelimit(&drbd_ratelimit_state))
-			dev_err(DEV, "Sending NegDReply. I guess it gets messy.\n");
 	}
 
 	dec_unacked(mdev);
@@ -1183,7 +1164,13 @@
 
 	drbd_free_ee(mdev, e);
 
-	if (--mdev->ov_left == 0) {
+	--mdev->ov_left;
+
+	/* let's advance progress step marks only for every other megabyte */
+	if ((mdev->ov_left & 0x200) == 0x200)
+		drbd_advance_rs_marks(mdev, mdev->ov_left);
+
+	if (mdev->ov_left == 0) {
 		ov_oos_print(mdev);
 		drbd_resync_finished(mdev);
 	}
@@ -1236,6 +1223,22 @@
 	return drbd_send_short_cmd(mdev, P_UNPLUG_REMOTE);
 }
 
+int w_send_oos(struct drbd_conf *mdev, struct drbd_work *w, int cancel)
+{
+	struct drbd_request *req = container_of(w, struct drbd_request, w);
+	int ok;
+
+	if (unlikely(cancel)) {
+		req_mod(req, send_canceled);
+		return 1;
+	}
+
+	ok = drbd_send_oos(mdev, req);
+	req_mod(req, oos_handed_to_network);
+
+	return ok;
+}
+
 /**
  * w_send_dblock() - Worker callback to send a P_DATA packet in order to mirror a write request
  * @mdev:	DRBD device.
@@ -1431,6 +1434,17 @@
 	return retcode;
 }
 
+void drbd_rs_controller_reset(struct drbd_conf *mdev)
+{
+	atomic_set(&mdev->rs_sect_in, 0);
+	atomic_set(&mdev->rs_sect_ev, 0);
+	mdev->rs_in_flight = 0;
+	mdev->rs_planed = 0;
+	spin_lock(&mdev->peer_seq_lock);
+	fifo_set(&mdev->rs_plan_s, 0);
+	spin_unlock(&mdev->peer_seq_lock);
+}
+
 /**
  * drbd_start_resync() - Start the resync process
  * @mdev:	DRBD device.
@@ -1444,13 +1458,18 @@
 	union drbd_state ns;
 	int r;
 
-	if (mdev->state.conn >= C_SYNC_SOURCE) {
+	if (mdev->state.conn >= C_SYNC_SOURCE && mdev->state.conn < C_AHEAD) {
 		dev_err(DEV, "Resync already running!\n");
 		return;
 	}
 
-	/* In case a previous resync run was aborted by an IO error/detach on the peer. */
-	drbd_rs_cancel_all(mdev);
+	if (mdev->state.conn < C_AHEAD) {
+		/* In case a previous resync run was aborted by an IO error/detach on the peer. */
+		drbd_rs_cancel_all(mdev);
+		/* This should be done when we abort the resync. We definitely do not
+		   want to have this for connections going back and forth between
+		   Ahead/Behind and SyncSource/SyncTarget */
+	}
 
 	if (side == C_SYNC_TARGET) {
 		/* Since application IO was locked out during C_WF_BITMAP_T and
@@ -1464,6 +1483,20 @@
 			drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
 			return;
 		}
+	} else /* C_SYNC_SOURCE */ {
+		r = drbd_khelper(mdev, "before-resync-source");
+		r = (r >> 8) & 0xff;
+		if (r > 0) {
+			if (r == 3) {
+				dev_info(DEV, "before-resync-source handler returned %d, "
+					 "ignoring. Old userland tools?", r);
+			} else {
+				dev_info(DEV, "before-resync-source handler returned %d, "
+					 "dropping connection.\n", r);
+				drbd_force_state(mdev, NS(conn, C_DISCONNECTING));
+				return;
+			}
+		}
 	}
 
 	drbd_state_lock(mdev);
@@ -1473,18 +1506,6 @@
 		return;
 	}
 
-	if (side == C_SYNC_TARGET) {
-		mdev->bm_resync_fo = 0;
-	} else /* side == C_SYNC_SOURCE */ {
-		u64 uuid;
-
-		get_random_bytes(&uuid, sizeof(u64));
-		drbd_uuid_set(mdev, UI_BITMAP, uuid);
-		drbd_send_sync_uuid(mdev, uuid);
-
-		D_ASSERT(mdev->state.disk == D_UP_TO_DATE);
-	}
-
 	write_lock_irq(&global_state_lock);
 	ns = mdev->state;
 
@@ -1522,13 +1543,24 @@
 		_drbd_pause_after(mdev);
 	}
 	write_unlock_irq(&global_state_lock);
-	put_ldev(mdev);
 
 	if (r == SS_SUCCESS) {
 		dev_info(DEV, "Began resync as %s (will sync %lu KB [%lu bits set]).\n",
 		     drbd_conn_str(ns.conn),
 		     (unsigned long) mdev->rs_total << (BM_BLOCK_SHIFT-10),
 		     (unsigned long) mdev->rs_total);
+		if (side == C_SYNC_TARGET)
+			mdev->bm_resync_fo = 0;
+
+		/* Since protocol 96, we must serialize drbd_gen_and_send_sync_uuid
+		 * with w_send_oos, or the sync target will get confused as to
+		 * how much bits to resync.  We cannot do that always, because for an
+		 * empty resync and protocol < 95, we need to do it here, as we call
+		 * drbd_resync_finished from here in that case.
+		 * We drbd_gen_and_send_sync_uuid here for protocol < 96,
+		 * and from after_state_ch otherwise. */
+		if (side == C_SYNC_SOURCE && mdev->agreed_pro_version < 96)
+			drbd_gen_and_send_sync_uuid(mdev);
 
 		if (mdev->agreed_pro_version < 95 && mdev->rs_total == 0) {
 			/* This still has a race (about when exactly the peers
@@ -1548,13 +1580,7 @@
 			drbd_resync_finished(mdev);
 		}
 
-		atomic_set(&mdev->rs_sect_in, 0);
-		atomic_set(&mdev->rs_sect_ev, 0);
-		mdev->rs_in_flight = 0;
-		mdev->rs_planed = 0;
-		spin_lock(&mdev->peer_seq_lock);
-		fifo_set(&mdev->rs_plan_s, 0);
-		spin_unlock(&mdev->peer_seq_lock);
+		drbd_rs_controller_reset(mdev);
 		/* ns.conn may already be != mdev->state.conn,
 		 * we may have been paused in between, or become paused until
 		 * the timer triggers.
@@ -1564,6 +1590,7 @@
 
 		drbd_md_sync(mdev);
 	}
+	put_ldev(mdev);
 	drbd_state_unlock(mdev);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_wrappers.h linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_wrappers.h
--- linux-libre-2.6.38-gnu/drivers/block/drbd/drbd_wrappers.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/drbd/drbd_wrappers.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,30 +39,12 @@
 		return;
 	}
 
-	if (FAULT_ACTIVE(mdev, fault_type))
+	if (drbd_insert_fault(mdev, fault_type))
 		bio_endio(bio, -EIO);
 	else
 		generic_make_request(bio);
 }
 
-static inline void drbd_plug_device(struct drbd_conf *mdev)
-{
-	struct request_queue *q;
-	q = bdev_get_queue(mdev->this_bdev);
-
-	spin_lock_irq(q->queue_lock);
-
-/* XXX the check on !blk_queue_plugged is redundant,
- * implicitly checked in blk_plug_device */
-
-	if (!blk_queue_plugged(q)) {
-		blk_plug_device(q);
-		del_timer(&q->unplug_timer);
-		/* unplugging should not happen automatically... */
-	}
-	spin_unlock_irq(q->queue_lock);
-}
-
 static inline int drbd_crypto_is_hash(struct crypto_tfm *tfm)
 {
         return (crypto_tfm_alg_type(tfm) & CRYPTO_ALG_TYPE_HASH_MASK)
diff -druN linux-libre-2.6.38-gnu/drivers/block/floppy.c linux-libre-2.6.39-gnu/drivers/block/floppy.c
--- linux-libre-2.6.38-gnu/drivers/block/floppy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/floppy.c	2011-05-19 00:06:34.000000000 -0400
@@ -3770,13 +3770,14 @@
 /*
  * Check if the disk has been changed or if a change has been faked.
  */
-static int check_floppy_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	int drive = (long)disk->private_data;
 
 	if (test_bit(FD_DISK_CHANGED_BIT, &UDRS->flags) ||
 	    test_bit(FD_VERIFY_BIT, &UDRS->flags))
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 
 	if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
 		lock_fdc(drive, false);
@@ -3788,7 +3789,7 @@
 	    test_bit(FD_VERIFY_BIT, &UDRS->flags) ||
 	    test_bit(drive, &fake_change) ||
 	    drive_no_geom(drive))
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	return 0;
 }
 
@@ -3837,7 +3838,6 @@
 	bio.bi_end_io = floppy_rb0_complete;
 
 	submit_bio(READ, &bio);
-	generic_unplug_device(bdev_get_queue(bdev));
 	process_fd_request();
 	wait_for_completion(&complete);
 
@@ -3898,7 +3898,7 @@
 	.release		= floppy_release,
 	.ioctl			= fd_ioctl,
 	.getgeo			= fd_getgeo,
-	.media_changed		= check_floppy_change,
+	.check_events		= floppy_check_events,
 	.revalidate_disk	= floppy_revalidate,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/hd.c linux-libre-2.6.39-gnu/drivers/block/hd.c
--- linux-libre-2.6.38-gnu/drivers/block/hd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/hd.c	2011-05-19 00:06:34.000000000 -0400
@@ -733,7 +733,7 @@
 		 * the BIOS or CMOS.  This doesn't work all that well,
 		 * since this assumes that this is a primary or secondary
 		 * drive, and if we're using this legacy driver, it's
-		 * probably an auxilliary controller added to recover
+		 * probably an auxiliary controller added to recover
 		 * legacy data off an ST-506 drive.  Either way, it's
 		 * definitely safest to have the user explicitly specify
 		 * the information.
diff -druN linux-libre-2.6.38-gnu/drivers/block/loop.c linux-libre-2.6.39-gnu/drivers/block/loop.c
--- linux-libre-2.6.38-gnu/drivers/block/loop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/loop.c	2011-05-19 00:06:34.000000000 -0400
@@ -540,17 +540,6 @@
 	return 0;
 }
 
-/*
- * kick off io on the underlying address space
- */
-static void loop_unplug(struct request_queue *q)
-{
-	struct loop_device *lo = q->queuedata;
-
-	queue_flag_clear_unlocked(QUEUE_FLAG_PLUGGED, q);
-	blk_run_address_space(lo->lo_backing_file->f_mapping);
-}
-
 struct switch_request {
 	struct file *file;
 	struct completion wait;
@@ -917,7 +906,6 @@
 	 */
 	blk_queue_make_request(lo->lo_queue, loop_make_request);
 	lo->lo_queue->queuedata = lo;
-	lo->lo_queue->unplug_fn = loop_unplug;
 
 	if (!(lo_flags & LO_FLAGS_READ_ONLY) && file->f_op->fsync)
 		blk_queue_flush(lo->lo_queue, REQ_FLUSH);
@@ -1019,7 +1007,6 @@
 
 	kthread_stop(lo->lo_thread);
 
-	lo->lo_queue->unplug_fn = NULL;
 	lo->lo_backing_file = NULL;
 
 	loop_release_xfer(lo);
@@ -1636,9 +1623,6 @@
 
 static void loop_free(struct loop_device *lo)
 {
-	if (!lo->lo_queue->queue_lock)
-		lo->lo_queue->queue_lock = &lo->lo_queue->__queue_lock;
-
 	blk_cleanup_queue(lo->lo_queue);
 	put_disk(lo->lo_disk);
 	list_del(&lo->lo_list);
diff -druN linux-libre-2.6.38-gnu/drivers/block/paride/pcd.c linux-libre-2.6.39-gnu/drivers/block/paride/pcd.c
--- linux-libre-2.6.38-gnu/drivers/block/paride/pcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/paride/pcd.c	2011-05-19 00:06:34.000000000 -0400
@@ -172,7 +172,8 @@
 static int pcd_open(struct cdrom_device_info *cdi, int purpose);
 static void pcd_release(struct cdrom_device_info *cdi);
 static int pcd_drive_status(struct cdrom_device_info *cdi, int slot_nr);
-static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr);
+static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
+				     unsigned int clearing, int slot_nr);
 static int pcd_tray_move(struct cdrom_device_info *cdi, int position);
 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock);
 static int pcd_drive_reset(struct cdrom_device_info *cdi);
@@ -257,10 +258,11 @@
 	return ret;
 }
 
-static int pcd_block_media_changed(struct gendisk *disk)
+static unsigned int pcd_block_check_events(struct gendisk *disk,
+					   unsigned int clearing)
 {
 	struct pcd_unit *cd = disk->private_data;
-	return cdrom_media_changed(&cd->info);
+	return cdrom_check_events(&cd->info, clearing);
 }
 
 static const struct block_device_operations pcd_bdops = {
@@ -268,14 +270,14 @@
 	.open		= pcd_block_open,
 	.release	= pcd_block_release,
 	.ioctl		= pcd_block_ioctl,
-	.media_changed	= pcd_block_media_changed,
+	.check_events	= pcd_block_check_events,
 };
 
 static struct cdrom_device_ops pcd_dops = {
 	.open		= pcd_open,
 	.release	= pcd_release,
 	.drive_status	= pcd_drive_status,
-	.media_changed	= pcd_media_changed,
+	.check_events	= pcd_check_events,
 	.tray_move	= pcd_tray_move,
 	.lock_door	= pcd_lock_door,
 	.get_mcn	= pcd_get_mcn,
@@ -502,13 +504,14 @@
 
 #define DBMSG(msg)	((verbose>1)?(msg):NULL)
 
-static int pcd_media_changed(struct cdrom_device_info *cdi, int slot_nr)
+static unsigned int pcd_check_events(struct cdrom_device_info *cdi,
+				     unsigned int clearing, int slot_nr)
 {
 	struct pcd_unit *cd = cdi->handle;
 	int res = cd->changed;
 	if (res)
 		cd->changed = 0;
-	return res;
+	return res ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int pcd_lock_door(struct cdrom_device_info *cdi, int lock)
diff -druN linux-libre-2.6.38-gnu/drivers/block/paride/pd.c linux-libre-2.6.39-gnu/drivers/block/paride/pd.c
--- linux-libre-2.6.38-gnu/drivers/block/paride/pd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/paride/pd.c	2011-05-19 00:06:34.000000000 -0400
@@ -794,7 +794,7 @@
 	return 0;
 }
 
-static int pd_check_media(struct gendisk *p)
+static unsigned int pd_check_events(struct gendisk *p, unsigned int clearing)
 {
 	struct pd_unit *disk = p->private_data;
 	int r;
@@ -803,7 +803,7 @@
 	pd_special_command(disk, pd_media_check);
 	r = disk->changed;
 	disk->changed = 0;
-	return r;
+	return r ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int pd_revalidate(struct gendisk *p)
@@ -822,7 +822,7 @@
 	.release	= pd_release,
 	.ioctl		= pd_ioctl,
 	.getgeo		= pd_getgeo,
-	.media_changed	= pd_check_media,
+	.check_events	= pd_check_events,
 	.revalidate_disk= pd_revalidate
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/paride/pf.c linux-libre-2.6.39-gnu/drivers/block/paride/pf.c
--- linux-libre-2.6.38-gnu/drivers/block/paride/pf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/paride/pf.c	2011-05-19 00:06:34.000000000 -0400
@@ -243,7 +243,8 @@
 static int pf_identify(struct pf_unit *pf);
 static void pf_lock(struct pf_unit *pf, int func);
 static void pf_eject(struct pf_unit *pf);
-static int pf_check_media(struct gendisk *disk);
+static unsigned int pf_check_events(struct gendisk *disk,
+				    unsigned int clearing);
 
 static char pf_scratch[512];	/* scratch block buffer */
 
@@ -270,7 +271,7 @@
 	.release	= pf_release,
 	.ioctl		= pf_ioctl,
 	.getgeo		= pf_getgeo,
-	.media_changed	= pf_check_media,
+	.check_events	= pf_check_events,
 };
 
 static void __init pf_init_units(void)
@@ -377,9 +378,9 @@
 
 }
 
-static int pf_check_media(struct gendisk *disk)
+static unsigned int pf_check_events(struct gendisk *disk, unsigned int clearing)
 {
-	return 1;
+	return DISK_EVENT_MEDIA_CHANGE;
 }
 
 static inline int status_reg(struct pf_unit *pf)
diff -druN linux-libre-2.6.38-gnu/drivers/block/pktcdvd.c linux-libre-2.6.39-gnu/drivers/block/pktcdvd.c
--- linux-libre-2.6.38-gnu/drivers/block/pktcdvd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/pktcdvd.c	2011-05-19 00:06:34.000000000 -0400
@@ -1606,8 +1606,6 @@
 					min_sleep_time = pkt->sleep_time;
 			}
 
-			generic_unplug_device(bdev_get_queue(pd->bdev));
-
 			VPRINTK("kcdrwd: sleeping\n");
 			residue = schedule_timeout(min_sleep_time);
 			VPRINTK("kcdrwd: wake up\n");
@@ -2796,7 +2794,8 @@
 	return ret;
 }
 
-static int pkt_media_changed(struct gendisk *disk)
+static unsigned int pkt_check_events(struct gendisk *disk,
+				     unsigned int clearing)
 {
 	struct pktcdvd_device *pd = disk->private_data;
 	struct gendisk *attached_disk;
@@ -2806,9 +2805,9 @@
 	if (!pd->bdev)
 		return 0;
 	attached_disk = pd->bdev->bd_disk;
-	if (!attached_disk)
+	if (!attached_disk || !attached_disk->fops->check_events)
 		return 0;
-	return attached_disk->fops->media_changed(attached_disk);
+	return attached_disk->fops->check_events(attached_disk, clearing);
 }
 
 static const struct block_device_operations pktcdvd_ops = {
@@ -2816,7 +2815,7 @@
 	.open =			pkt_open,
 	.release =		pkt_close,
 	.ioctl =		pkt_ioctl,
-	.media_changed =	pkt_media_changed,
+	.check_events =		pkt_check_events,
 };
 
 static char *pktcdvd_devnode(struct gendisk *gd, mode_t *mode)
@@ -2889,6 +2888,10 @@
 	if (ret)
 		goto out_new_dev;
 
+	/* inherit events of the host device */
+	disk->events = pd->bdev->bd_disk->events;
+	disk->async_events = pd->bdev->bd_disk->async_events;
+
 	add_disk(disk);
 
 	pkt_sysfs_dev_new(pd);
diff -druN linux-libre-2.6.38-gnu/drivers/block/rbd.c linux-libre-2.6.39-gnu/drivers/block/rbd.c
--- linux-libre-2.6.38-gnu/drivers/block/rbd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/rbd.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/ceph/osd_client.h>
 #include <linux/ceph/mon_client.h>
 #include <linux/ceph/decode.h>
+#include <linux/parser.h>
 
 #include <linux/kernel.h>
 #include <linux/device.h>
@@ -54,6 +55,8 @@
 
 #define DEV_NAME_LEN		32
 
+#define RBD_NOTIFY_TIMEOUT_DEFAULT 10
+
 /*
  * block device image metadata (in-memory version)
  */
@@ -71,6 +74,12 @@
 
 	char *snap_names;
 	u64 *snap_sizes;
+
+	u64 obj_version;
+};
+
+struct rbd_options {
+	int	notify_timeout;
 };
 
 /*
@@ -78,10 +87,13 @@
  */
 struct rbd_client {
 	struct ceph_client	*client;
+	struct rbd_options	*rbd_opts;
 	struct kref		kref;
 	struct list_head	node;
 };
 
+struct rbd_req_coll;
+
 /*
  * a single io request
  */
@@ -90,6 +102,24 @@
 	struct bio		*bio;		/* cloned bio */
 	struct page		**pages;	/* list of used pages */
 	u64			len;
+	int			coll_index;
+	struct rbd_req_coll	*coll;
+};
+
+struct rbd_req_status {
+	int done;
+	int rc;
+	u64 bytes;
+};
+
+/*
+ * a collection of requests
+ */
+struct rbd_req_coll {
+	int			total;
+	int			num_done;
+	struct kref		kref;
+	struct rbd_req_status	status[0];
 };
 
 struct rbd_snap {
@@ -124,6 +154,9 @@
 	char			pool_name[RBD_MAX_POOL_NAME_LEN];
 	int			poolid;
 
+	struct ceph_osd_event   *watch_event;
+	struct ceph_osd_request *watch_request;
+
 	char                    snap_name[RBD_MAX_SNAP_NAME_LEN];
 	u32 cur_snap;	/* index+1 of current snapshot within snap context
 			   0 - for the head */
@@ -177,6 +210,8 @@
 	put_device(&rbd_dev->dev);
 }
 
+static int __rbd_update_snaps(struct rbd_device *rbd_dev);
+
 static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
 	struct gendisk *disk = bdev->bd_disk;
@@ -211,7 +246,8 @@
  * Initialize an rbd client instance.
  * We own *opt.
  */
-static struct rbd_client *rbd_client_create(struct ceph_options *opt)
+static struct rbd_client *rbd_client_create(struct ceph_options *opt,
+					    struct rbd_options *rbd_opts)
 {
 	struct rbd_client *rbdc;
 	int ret = -ENOMEM;
@@ -233,6 +269,8 @@
 	if (ret < 0)
 		goto out_err;
 
+	rbdc->rbd_opts = rbd_opts;
+
 	spin_lock(&node_lock);
 	list_add_tail(&rbdc->node, &rbd_client_list);
 	spin_unlock(&node_lock);
@@ -267,6 +305,59 @@
 }
 
 /*
+ * mount options
+ */
+enum {
+	Opt_notify_timeout,
+	Opt_last_int,
+	/* int args above */
+	Opt_last_string,
+	/* string args above */
+};
+
+static match_table_t rbdopt_tokens = {
+	{Opt_notify_timeout, "notify_timeout=%d"},
+	/* int args above */
+	/* string args above */
+	{-1, NULL}
+};
+
+static int parse_rbd_opts_token(char *c, void *private)
+{
+	struct rbd_options *rbdopt = private;
+	substring_t argstr[MAX_OPT_ARGS];
+	int token, intval, ret;
+
+	token = match_token((char *)c, rbdopt_tokens, argstr);
+	if (token < 0)
+		return -EINVAL;
+
+	if (token < Opt_last_int) {
+		ret = match_int(&argstr[0], &intval);
+		if (ret < 0) {
+			pr_err("bad mount option arg (not int) "
+			       "at '%s'\n", c);
+			return ret;
+		}
+		dout("got int token %d val %d\n", token, intval);
+	} else if (token > Opt_last_int && token < Opt_last_string) {
+		dout("got string token %d val %s\n", token,
+		     argstr[0].from);
+	} else {
+		dout("got token %d\n", token);
+	}
+
+	switch (token) {
+	case Opt_notify_timeout:
+		rbdopt->notify_timeout = intval;
+		break;
+	default:
+		BUG_ON(token);
+	}
+	return 0;
+}
+
+/*
  * Get a ceph client with specific addr and configuration, if one does
  * not exist create it.
  */
@@ -276,11 +367,18 @@
 	struct rbd_client *rbdc;
 	struct ceph_options *opt;
 	int ret;
+	struct rbd_options *rbd_opts;
+
+	rbd_opts = kzalloc(sizeof(*rbd_opts), GFP_KERNEL);
+	if (!rbd_opts)
+		return -ENOMEM;
+
+	rbd_opts->notify_timeout = RBD_NOTIFY_TIMEOUT_DEFAULT;
 
 	ret = ceph_parse_options(&opt, options, mon_addr,
-				 mon_addr + strlen(mon_addr), NULL, NULL);
+				 mon_addr + strlen(mon_addr), parse_rbd_opts_token, rbd_opts);
 	if (ret < 0)
-		return ret;
+		goto done_err;
 
 	spin_lock(&node_lock);
 	rbdc = __rbd_client_find(opt);
@@ -296,13 +394,18 @@
 	}
 	spin_unlock(&node_lock);
 
-	rbdc = rbd_client_create(opt);
-	if (IS_ERR(rbdc))
-		return PTR_ERR(rbdc);
+	rbdc = rbd_client_create(opt, rbd_opts);
+	if (IS_ERR(rbdc)) {
+		ret = PTR_ERR(rbdc);
+		goto done_err;
+	}
 
 	rbd_dev->rbd_client = rbdc;
 	rbd_dev->client = rbdc->client;
 	return 0;
+done_err:
+	kfree(rbd_opts);
+	return ret;
 }
 
 /*
@@ -318,6 +421,7 @@
 	spin_unlock(&node_lock);
 
 	ceph_destroy_client(rbdc->client);
+	kfree(rbdc->rbd_opts);
 	kfree(rbdc);
 }
 
@@ -332,6 +436,17 @@
 	rbd_dev->client = NULL;
 }
 
+/*
+ * Destroy requests collection
+ */
+static void rbd_coll_release(struct kref *kref)
+{
+	struct rbd_req_coll *coll =
+		container_of(kref, struct rbd_req_coll, kref);
+
+	dout("rbd_coll_release %p\n", coll);
+	kfree(coll);
+}
 
 /*
  * Create a new header structure, translate header format from the on-disk
@@ -506,6 +621,14 @@
 	return len;
 }
 
+static int rbd_get_num_segments(struct rbd_image_header *header,
+				u64 ofs, u64 len)
+{
+	u64 start_seg = ofs >> header->obj_order;
+	u64 end_seg = (ofs + len - 1) >> header->obj_order;
+	return end_seg - start_seg + 1;
+}
+
 /*
  * bio helpers
  */
@@ -651,6 +774,50 @@
 	kfree(ops);
 }
 
+static void rbd_coll_end_req_index(struct request *rq,
+				   struct rbd_req_coll *coll,
+				   int index,
+				   int ret, u64 len)
+{
+	struct request_queue *q;
+	int min, max, i;
+
+	dout("rbd_coll_end_req_index %p index %d ret %d len %lld\n",
+	     coll, index, ret, len);
+
+	if (!rq)
+		return;
+
+	if (!coll) {
+		blk_end_request(rq, ret, len);
+		return;
+	}
+
+	q = rq->q;
+
+	spin_lock_irq(q->queue_lock);
+	coll->status[index].done = 1;
+	coll->status[index].rc = ret;
+	coll->status[index].bytes = len;
+	max = min = coll->num_done;
+	while (max < coll->total && coll->status[max].done)
+		max++;
+
+	for (i = min; i<max; i++) {
+		__blk_end_request(rq, coll->status[i].rc,
+				  coll->status[i].bytes);
+		coll->num_done++;
+		kref_put(&coll->kref, rbd_coll_release);
+	}
+	spin_unlock_irq(q->queue_lock);
+}
+
+static void rbd_coll_end_req(struct rbd_request *req,
+			     int ret, u64 len)
+{
+	rbd_coll_end_req_index(req->rq, req->coll, req->coll_index, ret, len);
+}
+
 /*
  * Send ceph osd request
  */
@@ -665,8 +832,12 @@
 			  int flags,
 			  struct ceph_osd_req_op *ops,
 			  int num_reply,
+			  struct rbd_req_coll *coll,
+			  int coll_index,
 			  void (*rbd_cb)(struct ceph_osd_request *req,
-					 struct ceph_msg *msg))
+					 struct ceph_msg *msg),
+			  struct ceph_osd_request **linger_req,
+			  u64 *ver)
 {
 	struct ceph_osd_request *req;
 	struct ceph_file_layout *layout;
@@ -677,12 +848,20 @@
 	struct ceph_osd_request_head *reqhead;
 	struct rbd_image_header *header = &dev->header;
 
-	ret = -ENOMEM;
 	req_data = kzalloc(sizeof(*req_data), GFP_NOIO);
-	if (!req_data)
-		goto done;
+	if (!req_data) {
+		if (coll)
+			rbd_coll_end_req_index(rq, coll, coll_index,
+					       -ENOMEM, len);
+		return -ENOMEM;
+	}
 
-	dout("rbd_do_request len=%lld ofs=%lld\n", len, ofs);
+	if (coll) {
+		req_data->coll = coll;
+		req_data->coll_index = coll_index;
+	}
+
+	dout("rbd_do_request obj=%s ofs=%lld len=%lld\n", obj, len, ofs);
 
 	down_read(&header->snap_rwsem);
 
@@ -691,9 +870,9 @@
 				      ops,
 				      false,
 				      GFP_NOIO, pages, bio);
-	if (IS_ERR(req)) {
+	if (!req) {
 		up_read(&header->snap_rwsem);
-		ret = PTR_ERR(req);
+		ret = -ENOMEM;
 		goto done_pages;
 	}
 
@@ -729,12 +908,21 @@
 				req->r_oid, req->r_oid_len);
 	up_read(&header->snap_rwsem);
 
+	if (linger_req) {
+		ceph_osdc_set_request_linger(&dev->client->osdc, req);
+		*linger_req = req;
+	}
+
 	ret = ceph_osdc_start_request(&dev->client->osdc, req, false);
 	if (ret < 0)
 		goto done_err;
 
 	if (!rbd_cb) {
 		ret = ceph_osdc_wait_request(&dev->client->osdc, req);
+		if (ver)
+			*ver = le64_to_cpu(req->r_reassert_version.version);
+		dout("reassert_ver=%lld\n",
+		     le64_to_cpu(req->r_reassert_version.version));
 		ceph_osdc_put_request(req);
 	}
 	return ret;
@@ -743,10 +931,8 @@
 	bio_chain_put(req_data->bio);
 	ceph_osdc_put_request(req);
 done_pages:
+	rbd_coll_end_req(req_data, ret, len);
 	kfree(req_data);
-done:
-	if (rq)
-		blk_end_request(rq, ret, len);
 	return ret;
 }
 
@@ -780,7 +966,7 @@
 		bytes = req_data->len;
 	}
 
-	blk_end_request(req_data->rq, rc, bytes);
+	rbd_coll_end_req(req_data, rc, bytes);
 
 	if (req_data->bio)
 		bio_chain_put(req_data->bio);
@@ -789,6 +975,11 @@
 	kfree(req_data);
 }
 
+static void rbd_simple_req_cb(struct ceph_osd_request *req, struct ceph_msg *msg)
+{
+	ceph_osdc_put_request(req);
+}
+
 /*
  * Do a synchronous ceph osd operation
  */
@@ -801,7 +992,9 @@
 			   int num_reply,
 			   const char *obj,
 			   u64 ofs, u64 len,
-			   char *buf)
+			   char *buf,
+			   struct ceph_osd_request **linger_req,
+			   u64 *ver)
 {
 	int ret;
 	struct page **pages;
@@ -833,7 +1026,9 @@
 			  flags,
 			  ops,
 			  2,
-			  NULL);
+			  NULL, 0,
+			  NULL,
+			  linger_req, ver);
 	if (ret < 0)
 		goto done_ops;
 
@@ -857,7 +1052,9 @@
 		     u64 snapid,
 		     int opcode, int flags, int num_reply,
 		     u64 ofs, u64 len,
-		     struct bio *bio)
+		     struct bio *bio,
+		     struct rbd_req_coll *coll,
+		     int coll_index)
 {
 	char *seg_name;
 	u64 seg_ofs;
@@ -893,7 +1090,10 @@
 			     flags,
 			     ops,
 			     num_reply,
-			     rbd_req_cb);
+			     coll, coll_index,
+			     rbd_req_cb, 0, NULL);
+
+	rbd_destroy_ops(ops);
 done:
 	kfree(seg_name);
 	return ret;
@@ -906,13 +1106,15 @@
 			 struct rbd_device *rbd_dev,
 			 struct ceph_snap_context *snapc,
 			 u64 ofs, u64 len,
-			 struct bio *bio)
+			 struct bio *bio,
+			 struct rbd_req_coll *coll,
+			 int coll_index)
 {
 	return rbd_do_op(rq, rbd_dev, snapc, CEPH_NOSNAP,
 			 CEPH_OSD_OP_WRITE,
 			 CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
 			 2,
-			 ofs, len, bio);
+			 ofs, len, bio, coll, coll_index);
 }
 
 /*
@@ -922,14 +1124,16 @@
 			 struct rbd_device *rbd_dev,
 			 u64 snapid,
 			 u64 ofs, u64 len,
-			 struct bio *bio)
+			 struct bio *bio,
+			 struct rbd_req_coll *coll,
+			 int coll_index)
 {
 	return rbd_do_op(rq, rbd_dev, NULL,
 			 (snapid ? snapid : CEPH_NOSNAP),
 			 CEPH_OSD_OP_READ,
 			 CEPH_OSD_FLAG_READ,
 			 2,
-			 ofs, len, bio);
+			 ofs, len, bio, coll, coll_index);
 }
 
 /*
@@ -940,18 +1144,177 @@
 			  u64 snapid,
 			  const char *obj,
 			  u64 ofs, u64 len,
-			  char *buf)
+			  char *buf,
+			  u64 *ver)
 {
 	return rbd_req_sync_op(dev, NULL,
 			       (snapid ? snapid : CEPH_NOSNAP),
 			       CEPH_OSD_OP_READ,
 			       CEPH_OSD_FLAG_READ,
 			       NULL,
-			       1, obj, ofs, len, buf);
+			       1, obj, ofs, len, buf, NULL, ver);
 }
 
 /*
- * Request sync osd read
+ * Request sync osd watch
+ */
+static int rbd_req_sync_notify_ack(struct rbd_device *dev,
+				   u64 ver,
+				   u64 notify_id,
+				   const char *obj)
+{
+	struct ceph_osd_req_op *ops;
+	struct page **pages = NULL;
+	int ret;
+
+	ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY_ACK, 0);
+	if (ret < 0)
+		return ret;
+
+	ops[0].watch.ver = cpu_to_le64(dev->header.obj_version);
+	ops[0].watch.cookie = notify_id;
+	ops[0].watch.flag = 0;
+
+	ret = rbd_do_request(NULL, dev, NULL, CEPH_NOSNAP,
+			  obj, 0, 0, NULL,
+			  pages, 0,
+			  CEPH_OSD_FLAG_READ,
+			  ops,
+			  1,
+			  NULL, 0,
+			  rbd_simple_req_cb, 0, NULL);
+
+	rbd_destroy_ops(ops);
+	return ret;
+}
+
+static void rbd_watch_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
+{
+	struct rbd_device *dev = (struct rbd_device *)data;
+	if (!dev)
+		return;
+
+	dout("rbd_watch_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name,
+		notify_id, (int)opcode);
+	mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+	__rbd_update_snaps(dev);
+	mutex_unlock(&ctl_mutex);
+
+	rbd_req_sync_notify_ack(dev, ver, notify_id, dev->obj_md_name);
+}
+
+/*
+ * Request sync osd watch
+ */
+static int rbd_req_sync_watch(struct rbd_device *dev,
+			      const char *obj,
+			      u64 ver)
+{
+	struct ceph_osd_req_op *ops;
+	struct ceph_osd_client *osdc = &dev->client->osdc;
+
+	int ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_WATCH, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = ceph_osdc_create_event(osdc, rbd_watch_cb, 0,
+				     (void *)dev, &dev->watch_event);
+	if (ret < 0)
+		goto fail;
+
+	ops[0].watch.ver = cpu_to_le64(ver);
+	ops[0].watch.cookie = cpu_to_le64(dev->watch_event->cookie);
+	ops[0].watch.flag = 1;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			      CEPH_NOSNAP,
+			      0,
+			      CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			      ops,
+			      1, obj, 0, 0, NULL,
+			      &dev->watch_request, NULL);
+
+	if (ret < 0)
+		goto fail_event;
+
+	rbd_destroy_ops(ops);
+	return 0;
+
+fail_event:
+	ceph_osdc_cancel_event(dev->watch_event);
+	dev->watch_event = NULL;
+fail:
+	rbd_destroy_ops(ops);
+	return ret;
+}
+
+struct rbd_notify_info {
+	struct rbd_device *dev;
+};
+
+static void rbd_notify_cb(u64 ver, u64 notify_id, u8 opcode, void *data)
+{
+	struct rbd_device *dev = (struct rbd_device *)data;
+	if (!dev)
+		return;
+
+	dout("rbd_notify_cb %s notify_id=%lld opcode=%d\n", dev->obj_md_name,
+		notify_id, (int)opcode);
+}
+
+/*
+ * Request sync osd notify
+ */
+static int rbd_req_sync_notify(struct rbd_device *dev,
+		          const char *obj)
+{
+	struct ceph_osd_req_op *ops;
+	struct ceph_osd_client *osdc = &dev->client->osdc;
+	struct ceph_osd_event *event;
+	struct rbd_notify_info info;
+	int payload_len = sizeof(u32) + sizeof(u32);
+	int ret;
+
+	ret = rbd_create_rw_ops(&ops, 1, CEPH_OSD_OP_NOTIFY, payload_len);
+	if (ret < 0)
+		return ret;
+
+	info.dev = dev;
+
+	ret = ceph_osdc_create_event(osdc, rbd_notify_cb, 1,
+				     (void *)&info, &event);
+	if (ret < 0)
+		goto fail;
+
+	ops[0].watch.ver = 1;
+	ops[0].watch.flag = 1;
+	ops[0].watch.cookie = event->cookie;
+	ops[0].watch.prot_ver = RADOS_NOTIFY_VER;
+	ops[0].watch.timeout = 12;
+
+	ret = rbd_req_sync_op(dev, NULL,
+			       CEPH_NOSNAP,
+			       0,
+			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
+			       ops,
+			       1, obj, 0, 0, NULL, NULL, NULL);
+	if (ret < 0)
+		goto fail_event;
+
+	ret = ceph_osdc_wait_event(event, CEPH_OSD_TIMEOUT_DEFAULT);
+	dout("ceph_osdc_wait_event returned %d\n", ret);
+	rbd_destroy_ops(ops);
+	return 0;
+
+fail_event:
+	ceph_osdc_cancel_event(event);
+fail:
+	rbd_destroy_ops(ops);
+	return ret;
+}
+
+/*
+ * Request sync osd rollback
  */
 static int rbd_req_sync_rollback_obj(struct rbd_device *dev,
 				     u64 snapid,
@@ -969,13 +1332,10 @@
 			       0,
 			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
 			       ops,
-			       1, obj, 0, 0, NULL);
+			       1, obj, 0, 0, NULL, NULL, NULL);
 
 	rbd_destroy_ops(ops);
 
-	if (ret < 0)
-		return ret;
-
 	return ret;
 }
 
@@ -987,7 +1347,8 @@
 			     const char *cls,
 			     const char *method,
 			     const char *data,
-			     int len)
+			     int len,
+			     u64 *ver)
 {
 	struct ceph_osd_req_op *ops;
 	int cls_len = strlen(cls);
@@ -1010,7 +1371,7 @@
 			       0,
 			       CEPH_OSD_FLAG_WRITE | CEPH_OSD_FLAG_ONDISK,
 			       ops,
-			       1, obj, 0, 0, NULL);
+			       1, obj, 0, 0, NULL, NULL, ver);
 
 	rbd_destroy_ops(ops);
 
@@ -1018,6 +1379,20 @@
 	return ret;
 }
 
+static struct rbd_req_coll *rbd_alloc_coll(int num_reqs)
+{
+	struct rbd_req_coll *coll =
+			kzalloc(sizeof(struct rbd_req_coll) +
+			        sizeof(struct rbd_req_status) * num_reqs,
+				GFP_ATOMIC);
+
+	if (!coll)
+		return NULL;
+	coll->total = num_reqs;
+	kref_init(&coll->kref);
+	return coll;
+}
+
 /*
  * block device queue callback
  */
@@ -1035,6 +1410,8 @@
 		bool do_write;
 		int size, op_size = 0;
 		u64 ofs;
+		int num_segs, cur_seg = 0;
+		struct rbd_req_coll *coll;
 
 		/* peek at request from block layer */
 		if (!rq)
@@ -1065,6 +1442,14 @@
 		     do_write ? "write" : "read",
 		     size, blk_rq_pos(rq) * 512ULL);
 
+		num_segs = rbd_get_num_segments(&rbd_dev->header, ofs, size);
+		coll = rbd_alloc_coll(num_segs);
+		if (!coll) {
+			spin_lock_irq(q->queue_lock);
+			__blk_end_request_all(rq, -ENOMEM);
+			goto next;
+		}
+
 		do {
 			/* a bio clone to be passed down to OSD req */
 			dout("rq->bio->bi_vcnt=%d\n", rq->bio->bi_vcnt);
@@ -1072,35 +1457,41 @@
 						  rbd_dev->header.block_name,
 						  ofs, size,
 						  NULL, NULL);
+			kref_get(&coll->kref);
 			bio = bio_chain_clone(&rq_bio, &next_bio, &bp,
 					      op_size, GFP_ATOMIC);
 			if (!bio) {
-				spin_lock_irq(q->queue_lock);
-				__blk_end_request_all(rq, -ENOMEM);
-				goto next;
+				rbd_coll_end_req_index(rq, coll, cur_seg,
+						       -ENOMEM, op_size);
+				goto next_seg;
 			}
 
+
 			/* init OSD command: write or read */
 			if (do_write)
 				rbd_req_write(rq, rbd_dev,
 					      rbd_dev->header.snapc,
 					      ofs,
-					      op_size, bio);
+					      op_size, bio,
+					      coll, cur_seg);
 			else
 				rbd_req_read(rq, rbd_dev,
 					     cur_snap_id(rbd_dev),
 					     ofs,
-					     op_size, bio);
+					     op_size, bio,
+					     coll, cur_seg);
 
+next_seg:
 			size -= op_size;
 			ofs += op_size;
 
+			cur_seg++;
 			rq_bio = next_bio;
 		} while (size > 0);
+		kref_put(&coll->kref, rbd_coll_release);
 
 		if (bp)
 			bio_pair_release(bp);
-
 		spin_lock_irq(q->queue_lock);
 next:
 		rq = blk_fetch_request(q);
@@ -1156,6 +1547,7 @@
 	struct rbd_image_header_ondisk *dh;
 	int snap_count = 0;
 	u64 snap_names_len = 0;
+	u64 ver;
 
 	while (1) {
 		int len = sizeof(*dh) +
@@ -1171,7 +1563,7 @@
 				       NULL, CEPH_NOSNAP,
 				       rbd_dev->obj_md_name,
 				       0, len,
-				       (char *)dh);
+				       (char *)dh, &ver);
 		if (rc < 0)
 			goto out_dh;
 
@@ -1188,6 +1580,7 @@
 		}
 		break;
 	}
+	header->obj_version = ver;
 
 out_dh:
 	kfree(dh);
@@ -1205,6 +1598,7 @@
 	u64 new_snapid;
 	int ret;
 	void *data, *data_start, *data_end;
+	u64 ver;
 
 	/* we should create a snapshot only if we're pointing at the head */
 	if (dev->cur_snap)
@@ -1227,7 +1621,7 @@
 	ceph_encode_64_safe(&data, data_end, new_snapid, bad);
 
 	ret = rbd_req_sync_exec(dev, dev->obj_md_name, "rbd", "snap_add",
-				data_start, data - data_start);
+				data_start, data - data_start, &ver);
 
 	kfree(data_start);
 
@@ -1259,6 +1653,7 @@
 	int ret;
 	struct rbd_image_header h;
 	u64 snap_seq;
+	int follow_seq = 0;
 
 	ret = rbd_read_header(rbd_dev, &h);
 	if (ret < 0)
@@ -1267,6 +1662,11 @@
 	down_write(&rbd_dev->header.snap_rwsem);
 
 	snap_seq = rbd_dev->header.snapc->seq;
+	if (rbd_dev->header.total_snaps &&
+	    rbd_dev->header.snapc->snaps[0] == snap_seq)
+		/* pointing at the head, will need to follow that
+		   if head moves */
+		follow_seq = 1;
 
 	kfree(rbd_dev->header.snapc);
 	kfree(rbd_dev->header.snap_names);
@@ -1277,7 +1677,10 @@
 	rbd_dev->header.snap_names = h.snap_names;
 	rbd_dev->header.snap_names_len = h.snap_names_len;
 	rbd_dev->header.snap_sizes = h.snap_sizes;
-	rbd_dev->header.snapc->seq = snap_seq;
+	if (follow_seq)
+		rbd_dev->header.snapc->seq = rbd_dev->header.snapc->snaps[0];
+	else
+		rbd_dev->header.snapc->seq = snap_seq;
 
 	ret = __rbd_init_snaps_header(rbd_dev);
 
@@ -1699,7 +2102,28 @@
 	device_unregister(&rbd_dev->dev);
 }
 
-static ssize_t rbd_add(struct bus_type *bus, const char *buf, size_t count)
+static int rbd_init_watch_dev(struct rbd_device *rbd_dev)
+{
+	int ret, rc;
+
+	do {
+		ret = rbd_req_sync_watch(rbd_dev, rbd_dev->obj_md_name,
+					 rbd_dev->header.obj_version);
+		if (ret == -ERANGE) {
+			mutex_lock_nested(&ctl_mutex, SINGLE_DEPTH_NESTING);
+			rc = __rbd_update_snaps(rbd_dev);
+			mutex_unlock(&ctl_mutex);
+			if (rc < 0)
+				return rc;
+		}
+	} while (ret == -ERANGE);
+
+	return ret;
+}
+
+static ssize_t rbd_add(struct bus_type *bus,
+		       const char *buf,
+		       size_t count)
 {
 	struct ceph_osd_client *osdc;
 	struct rbd_device *rbd_dev;
@@ -1797,6 +2221,10 @@
 	if (rc)
 		goto err_out_bus;
 
+	rc = rbd_init_watch_dev(rbd_dev);
+	if (rc)
+		goto err_out_bus;
+
 	return count;
 
 err_out_bus:
@@ -1849,6 +2277,12 @@
 	struct rbd_device *rbd_dev =
 			container_of(dev, struct rbd_device, dev);
 
+	if (rbd_dev->watch_request)
+		ceph_osdc_unregister_linger_request(&rbd_dev->client->osdc,
+						    rbd_dev->watch_request);
+	if (rbd_dev->watch_event)
+		ceph_osdc_cancel_event(rbd_dev->watch_event);
+
 	rbd_put_client(rbd_dev);
 
 	/* clean up and free blkdev */
@@ -1914,14 +2348,24 @@
 	ret = rbd_header_add_snap(rbd_dev,
 				  name, GFP_KERNEL);
 	if (ret < 0)
-		goto done_unlock;
+		goto err_unlock;
 
 	ret = __rbd_update_snaps(rbd_dev);
 	if (ret < 0)
-		goto done_unlock;
+		goto err_unlock;
+
+	/* shouldn't hold ctl_mutex when notifying.. notify might
+	   trigger a watch callback that would need to get that mutex */
+	mutex_unlock(&ctl_mutex);
+
+	/* make a best effort, don't error if failed */
+	rbd_req_sync_notify(rbd_dev, rbd_dev->obj_md_name);
 
 	ret = count;
-done_unlock:
+	kfree(name);
+	return ret;
+
+err_unlock:
 	mutex_unlock(&ctl_mutex);
 	kfree(name);
 	return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/block/smart1,2.h linux-libre-2.6.39-gnu/drivers/block/smart1,2.h
--- linux-libre-2.6.38-gnu/drivers/block/smart1,2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/smart1,2.h	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
  /*
  *  This hardware returns interrupt pending at a different place and 
  *  it does not tell us if the fifo is empty, we will have check  
- *  that by getting a 0 back from the comamnd_completed call. 
+ *  that by getting a 0 back from the command_completed call. 
  */
 static unsigned long smart4_intr_pending(ctlr_info_t *h)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/block/swim3.c linux-libre-2.6.39-gnu/drivers/block/swim3.c
--- linux-libre-2.6.38-gnu/drivers/block/swim3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/swim3.c	2011-05-19 00:06:34.000000000 -0400
@@ -250,7 +250,8 @@
 			unsigned int cmd, unsigned long param);
 static int floppy_open(struct block_device *bdev, fmode_t mode);
 static int floppy_release(struct gendisk *disk, fmode_t mode);
-static int floppy_check_change(struct gendisk *disk);
+static unsigned int floppy_check_events(struct gendisk *disk,
+					unsigned int clearing);
 static int floppy_revalidate(struct gendisk *disk);
 
 static bool swim3_end_request(int err, unsigned int nr_bytes)
@@ -975,10 +976,11 @@
 	return 0;
 }
 
-static int floppy_check_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	struct floppy_state *fs = disk->private_data;
-	return fs->ejected;
+	return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int floppy_revalidate(struct gendisk *disk)
@@ -1025,7 +1027,7 @@
 	.open		= floppy_unlocked_open,
 	.release	= floppy_release,
 	.ioctl		= floppy_ioctl,
-	.media_changed	= floppy_check_change,
+	.check_events	= floppy_check_events,
 	.revalidate_disk= floppy_revalidate,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/swim.c linux-libre-2.6.39-gnu/drivers/block/swim.c
--- linux-libre-2.6.38-gnu/drivers/block/swim.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/swim.c	2011-05-19 00:06:34.000000000 -0400
@@ -741,11 +741,12 @@
 	return 0;
 }
 
-static int floppy_check_change(struct gendisk *disk)
+static unsigned int floppy_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	struct floppy_state *fs = disk->private_data;
 
-	return fs->ejected;
+	return fs->ejected ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int floppy_revalidate(struct gendisk *disk)
@@ -772,7 +773,7 @@
 	.release	 = floppy_release,
 	.ioctl		 = floppy_ioctl,
 	.getgeo		 = floppy_getgeo,
-	.media_changed	 = floppy_check_change,
+	.check_events	 = floppy_check_events,
 	.revalidate_disk = floppy_revalidate,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/ub.c linux-libre-2.6.39-gnu/drivers/block/ub.c
--- linux-libre-2.6.38-gnu/drivers/block/ub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/ub.c	2011-05-19 00:06:34.000000000 -0400
@@ -1788,7 +1788,8 @@
  *
  * The return code is bool!
  */
-static int ub_bd_media_changed(struct gendisk *disk)
+static unsigned int ub_bd_check_events(struct gendisk *disk,
+				       unsigned int clearing)
 {
 	struct ub_lun *lun = disk->private_data;
 
@@ -1806,10 +1807,10 @@
 	 */
 	if (ub_sync_tur(lun->udev, lun) != 0) {
 		lun->changed = 1;
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	}
 
-	return lun->changed;
+	return lun->changed ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static const struct block_device_operations ub_bd_fops = {
@@ -1817,7 +1818,7 @@
 	.open		= ub_bd_unlocked_open,
 	.release	= ub_bd_release,
 	.ioctl		= ub_bd_ioctl,
-	.media_changed	= ub_bd_media_changed,
+	.check_events	= ub_bd_check_events,
 	.revalidate_disk = ub_bd_revalidate,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/umem.c linux-libre-2.6.39-gnu/drivers/block/umem.c
--- linux-libre-2.6.38-gnu/drivers/block/umem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/umem.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,8 +241,7 @@
  *
  * Whenever IO on the active page completes, the Ready page is activated
  * and the ex-Active page is clean out and made Ready.
- * Otherwise the Ready page is only activated when it becomes full, or
- * when mm_unplug_device is called via the unplug_io_fn.
+ * Otherwise the Ready page is only activated when it becomes full.
  *
  * If a request arrives while both pages a full, it is queued, and b_rdev is
  * overloaded to record whether it was a read or a write.
@@ -333,17 +332,6 @@
 	page->biotail = &page->bio;
 }
 
-static void mm_unplug_device(struct request_queue *q)
-{
-	struct cardinfo *card = q->queuedata;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->lock, flags);
-	if (blk_remove_plug(q))
-		activate(card);
-	spin_unlock_irqrestore(&card->lock, flags);
-}
-
 /*
  * If there is room on Ready page, take
  * one bh off list and add it.
@@ -535,7 +523,6 @@
 	*card->biotail = bio;
 	bio->bi_next = NULL;
 	card->biotail = &bio->bi_next;
-	blk_plug_device(q);
 	spin_unlock_irq(&card->lock);
 
 	return 0;
@@ -779,20 +766,10 @@
 	return 0;
 }
 
-/*
- * Future support for removable devices
- */
-static int mm_check_change(struct gendisk *disk)
-{
-/*  struct cardinfo *dev = disk->private_data; */
-	return 0;
-}
-
 static const struct block_device_operations mm_fops = {
 	.owner		= THIS_MODULE,
 	.getgeo		= mm_getgeo,
 	.revalidate_disk = mm_revalidate,
-	.media_changed	= mm_check_change,
 };
 
 static int __devinit mm_pci_probe(struct pci_dev *dev,
@@ -907,7 +884,6 @@
 	blk_queue_make_request(card->queue, mm_make_request);
 	card->queue->queue_lock = &card->lock;
 	card->queue->queuedata = card;
-	card->queue->unplug_fn = mm_unplug_device;
 
 	tasklet_init(&card->tasklet, process_page, (unsigned long)card);
 
diff -druN linux-libre-2.6.38-gnu/drivers/block/viodasd.c linux-libre-2.6.39-gnu/drivers/block/viodasd.c
--- linux-libre-2.6.38-gnu/drivers/block/viodasd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/viodasd.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,7 @@
 	{ 0x0204, EIO, "Use Error" },
 	{ 0x0205, EIO, "Release Error" },
 	{ 0x0206, EINVAL, "Invalid Disk" },
-	{ 0x0207, EBUSY, "Cant Lock" },
+	{ 0x0207, EBUSY, "Can't Lock" },
 	{ 0x0208, EIO, "Already Locked" },
 	{ 0x0209, EIO, "Already Unlocked" },
 	{ 0x020A, EIO, "Invalid Arg" },
diff -druN linux-libre-2.6.38-gnu/drivers/block/xen-blkfront.c linux-libre-2.6.39-gnu/drivers/block/xen-blkfront.c
--- linux-libre-2.6.38-gnu/drivers/block/xen-blkfront.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/xen-blkfront.c	2011-05-19 00:06:34.000000000 -0400
@@ -120,6 +120,10 @@
 #define EXTENDED (1<<EXT_SHIFT)
 #define VDEV_IS_EXTENDED(dev) ((dev)&(EXTENDED))
 #define BLKIF_MINOR_EXT(dev) ((dev)&(~EXTENDED))
+#define EMULATED_HD_DISK_MINOR_OFFSET (0)
+#define EMULATED_HD_DISK_NAME_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET / 256)
+#define EMULATED_SD_DISK_MINOR_OFFSET (EMULATED_HD_DISK_MINOR_OFFSET + (4 * 16))
+#define EMULATED_SD_DISK_NAME_OFFSET (EMULATED_HD_DISK_NAME_OFFSET + 4)
 
 #define DEV_NAME	"xvd"	/* name in /dev */
 
@@ -281,7 +285,7 @@
 	info->shadow[id].request = req;
 
 	ring_req->id = id;
-	ring_req->sector_number = (blkif_sector_t)blk_rq_pos(req);
+	ring_req->u.rw.sector_number = (blkif_sector_t)blk_rq_pos(req);
 	ring_req->handle = info->handle;
 
 	ring_req->operation = rq_data_dir(req) ?
@@ -317,7 +321,7 @@
 				rq_data_dir(req) );
 
 		info->shadow[id].frame[i] = mfn_to_pfn(buffer_mfn);
-		ring_req->seg[i] =
+		ring_req->u.rw.seg[i] =
 				(struct blkif_request_segment) {
 					.gref       = ref,
 					.first_sect = fsect,
@@ -434,6 +438,65 @@
 	       info->feature_flush ? "enabled" : "disabled");
 }
 
+static int xen_translate_vdev(int vdevice, int *minor, unsigned int *offset)
+{
+	int major;
+	major = BLKIF_MAJOR(vdevice);
+	*minor = BLKIF_MINOR(vdevice);
+	switch (major) {
+		case XEN_IDE0_MAJOR:
+			*offset = (*minor / 64) + EMULATED_HD_DISK_NAME_OFFSET;
+			*minor = ((*minor / 64) * PARTS_PER_DISK) +
+				EMULATED_HD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_IDE1_MAJOR:
+			*offset = (*minor / 64) + 2 + EMULATED_HD_DISK_NAME_OFFSET;
+			*minor = (((*minor / 64) + 2) * PARTS_PER_DISK) +
+				EMULATED_HD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_SCSI_DISK0_MAJOR:
+			*offset = (*minor / PARTS_PER_DISK) + EMULATED_SD_DISK_NAME_OFFSET;
+			*minor = *minor + EMULATED_SD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_SCSI_DISK1_MAJOR:
+		case XEN_SCSI_DISK2_MAJOR:
+		case XEN_SCSI_DISK3_MAJOR:
+		case XEN_SCSI_DISK4_MAJOR:
+		case XEN_SCSI_DISK5_MAJOR:
+		case XEN_SCSI_DISK6_MAJOR:
+		case XEN_SCSI_DISK7_MAJOR:
+			*offset = (*minor / PARTS_PER_DISK) + 
+				((major - XEN_SCSI_DISK1_MAJOR + 1) * 16) +
+				EMULATED_SD_DISK_NAME_OFFSET;
+			*minor = *minor +
+				((major - XEN_SCSI_DISK1_MAJOR + 1) * 16 * PARTS_PER_DISK) +
+				EMULATED_SD_DISK_MINOR_OFFSET;
+			break;
+		case XEN_SCSI_DISK8_MAJOR:
+		case XEN_SCSI_DISK9_MAJOR:
+		case XEN_SCSI_DISK10_MAJOR:
+		case XEN_SCSI_DISK11_MAJOR:
+		case XEN_SCSI_DISK12_MAJOR:
+		case XEN_SCSI_DISK13_MAJOR:
+		case XEN_SCSI_DISK14_MAJOR:
+		case XEN_SCSI_DISK15_MAJOR:
+			*offset = (*minor / PARTS_PER_DISK) + 
+				((major - XEN_SCSI_DISK8_MAJOR + 8) * 16) +
+				EMULATED_SD_DISK_NAME_OFFSET;
+			*minor = *minor +
+				((major - XEN_SCSI_DISK8_MAJOR + 8) * 16 * PARTS_PER_DISK) +
+				EMULATED_SD_DISK_MINOR_OFFSET;
+			break;
+		case XENVBD_MAJOR:
+			*offset = *minor / PARTS_PER_DISK;
+			break;
+		default:
+			printk(KERN_WARNING "blkfront: your disk configuration is "
+					"incorrect, please use an xvd device instead\n");
+			return -ENODEV;
+	}
+	return 0;
+}
 
 static int xlvbd_alloc_gendisk(blkif_sector_t capacity,
 			       struct blkfront_info *info,
@@ -441,7 +504,7 @@
 {
 	struct gendisk *gd;
 	int nr_minors = 1;
-	int err = -ENODEV;
+	int err;
 	unsigned int offset;
 	int minor;
 	int nr_parts;
@@ -456,12 +519,20 @@
 	}
 
 	if (!VDEV_IS_EXTENDED(info->vdevice)) {
-		minor = BLKIF_MINOR(info->vdevice);
-		nr_parts = PARTS_PER_DISK;
+		err = xen_translate_vdev(info->vdevice, &minor, &offset);
+		if (err)
+			return err;		
+ 		nr_parts = PARTS_PER_DISK;
 	} else {
 		minor = BLKIF_MINOR_EXT(info->vdevice);
 		nr_parts = PARTS_PER_EXT_DISK;
+		offset = minor / nr_parts;
+		if (xen_hvm_domain() && offset <= EMULATED_HD_DISK_NAME_OFFSET + 4)
+			printk(KERN_WARNING "blkfront: vdevice 0x%x might conflict with "
+					"emulated IDE disks,\n\t choose an xvd device name"
+					"from xvde on\n", info->vdevice);
 	}
+	err = -ENODEV;
 
 	if ((minor % nr_parts) == 0)
 		nr_minors = nr_parts;
@@ -475,8 +546,6 @@
 	if (gd == NULL)
 		goto release;
 
-	offset = minor / nr_parts;
-
 	if (nr_minors > 1) {
 		if (offset < 26)
 			sprintf(gd->disk_name, "%s%c", DEV_NAME, 'a' + offset);
@@ -615,7 +684,7 @@
 {
 	int i;
 	for (i = 0; i < s->req.nr_segments; i++)
-		gnttab_end_foreign_access(s->req.seg[i].gref, 0, 0UL);
+		gnttab_end_foreign_access(s->req.u.rw.seg[i].gref, 0, 0UL);
 }
 
 static irqreturn_t blkif_interrupt(int irq, void *dev_id)
@@ -932,7 +1001,7 @@
 		/* Rewrite any grant references invalidated by susp/resume. */
 		for (j = 0; j < req->nr_segments; j++)
 			gnttab_grant_foreign_access_ref(
-				req->seg[j].gref,
+				req->u.rw.seg[j].gref,
 				info->xbdev->otherend_id,
 				pfn_to_mfn(info->shadow[req->id].frame[j]),
 				rq_data_dir(info->shadow[req->id].request));
diff -druN linux-libre-2.6.38-gnu/drivers/block/xsysace.c linux-libre-2.6.39-gnu/drivers/block/xsysace.c
--- linux-libre-2.6.38-gnu/drivers/block/xsysace.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/block/xsysace.c	2011-05-19 00:06:34.000000000 -0400
@@ -621,7 +621,7 @@
 		ace_dump_mem(ace->cf_id, 512);	/* Debug: Dump out disk ID */
 
 		if (ace->data_result) {
-			/* Error occured, disable the disk */
+			/* Error occurred, disable the disk */
 			ace->media_change = 1;
 			set_capacity(ace->gd, 0);
 			dev_err(ace->dev, "error fetching CF id (%i)\n",
@@ -801,7 +801,7 @@
 	u32 sreg = ace_in32(ace, ACE_STATUS);
 	u16 creg = ace_in(ace, ACE_CTRL);
 
-	/* Check for error occurance */
+	/* Check for error occurrence */
 	if ((sreg & (ACE_STATUS_CFGERROR | ACE_STATUS_CFCERROR)) &&
 	    (creg & ACE_CTRL_ERRORIRQ)) {
 		dev_err(ace->dev, "transfer failure\n");
@@ -867,12 +867,12 @@
 	}
 }
 
-static int ace_media_changed(struct gendisk *gd)
+static unsigned int ace_check_events(struct gendisk *gd, unsigned int clearing)
 {
 	struct ace_device *ace = gd->private_data;
-	dev_dbg(ace->dev, "ace_media_changed(): %i\n", ace->media_change);
+	dev_dbg(ace->dev, "ace_check_events(): %i\n", ace->media_change);
 
-	return ace->media_change;
+	return ace->media_change ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int ace_revalidate_disk(struct gendisk *gd)
@@ -953,7 +953,7 @@
 	.owner = THIS_MODULE,
 	.open = ace_open,
 	.release = ace_release,
-	.media_changed = ace_media_changed,
+	.check_events = ace_check_events,
 	.revalidate_disk = ace_revalidate_disk,
 	.getgeo = ace_getgeo,
 };
@@ -1168,7 +1168,7 @@
 			irq = dev->resource[i].start;
 	}
 
-	/* Call the bus-independant setup code */
+	/* Call the bus-independent setup code */
 	return ace_alloc(&dev->dev, id, physaddr, irq, bus_width);
 }
 
@@ -1195,16 +1195,13 @@
  */
 
 #if defined(CONFIG_OF)
-static int __devinit
-ace_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ace_of_probe(struct platform_device *op)
 {
 	struct resource res;
 	resource_size_t physaddr;
 	const u32 *id;
 	int irq, bus_width, rc;
 
-	dev_dbg(&op->dev, "ace_of_probe(%p, %p)\n", op, match);
-
 	/* device id */
 	id = of_get_property(op->dev.of_node, "port-number", NULL);
 
@@ -1224,7 +1221,7 @@
 	if (of_find_property(op->dev.of_node, "8-bit", NULL))
 		bus_width = ACE_BUS_WIDTH_8;
 
-	/* Call the bus-independant setup code */
+	/* Call the bus-independent setup code */
 	return ace_alloc(&op->dev, id ? be32_to_cpup(id) : 0,
 						physaddr, irq, bus_width);
 }
@@ -1245,7 +1242,7 @@
 };
 MODULE_DEVICE_TABLE(of, ace_of_match);
 
-static struct of_platform_driver ace_of_driver = {
+static struct platform_driver ace_of_driver = {
 	.probe = ace_of_probe,
 	.remove = __devexit_p(ace_of_remove),
 	.driver = {
@@ -1259,12 +1256,12 @@
 static inline int __init ace_of_register(void)
 {
 	pr_debug("xsysace: registering OF binding\n");
-	return of_register_platform_driver(&ace_of_driver);
+	return platform_driver_register(&ace_of_driver);
 }
 
 static inline void __exit ace_of_unregister(void)
 {
-	of_unregister_platform_driver(&ace_of_driver);
+	platform_driver_unregister(&ace_of_driver);
 }
 #else /* CONFIG_OF */
 /* CONFIG_OF not enabled; do nothing helpers */
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/ath3k.c linux-libre-2.6.39-gnu/drivers/bluetooth/ath3k.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/ath3k.c	2012-03-24 01:15:51.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/ath3k.c	2012-03-24 03:35:09.000000000 -0400
@@ -31,6 +31,30 @@
 
 #define VERSION "1.0"
 
+#define ATH3K_DNLOAD				0x01
+#define ATH3K_GETSTATE				0x05
+#define ATH3K_SET_NORMAL_MODE			0x07
+#define ATH3K_GETVERSION			0x09
+#define USB_REG_SWITCH_VID_PID			0x0a
+
+#define ATH3K_MODE_MASK				0x3F
+#define ATH3K_NORMAL_MODE			0x0E
+
+#define ATH3K_PATCH_UPDATE			0x80
+#define ATH3K_SYSCFG_UPDATE			0x40
+
+#define ATH3K_XTAL_FREQ_26M			0x00
+#define ATH3K_XTAL_FREQ_40M			0x01
+#define ATH3K_XTAL_FREQ_19P2			0x02
+#define ATH3K_NAME_LEN				0xFF
+
+struct ath3k_version {
+	unsigned int	rom_version;
+	unsigned int	build_version;
+	unsigned int	ram_version;
+	unsigned char	ref_clock;
+	unsigned char	reserved[0x07];
+};
 
 static struct usb_device_id ath3k_table[] = {
 	/* Atheros AR3011 */
@@ -42,15 +66,31 @@
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03F0, 0x311D) },
 
+	/* Atheros AR3012 with sflash firmware*/
+	{ USB_DEVICE(0x0CF3, 0x3004) },
+
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
+
 	{ }	/* Terminating entry */
 };
 
 MODULE_DEVICE_TABLE(usb, ath3k_table);
 
+#define BTUSB_ATH3012		0x80
+/* This table is to load patch and sysconfig files
+ * for AR3012 */
+static struct usb_device_id ath3k_blist_tbl[] = {
+
+	/* Atheros AR3012 with sflash firmware*/
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_ATH3012 },
+
+	{ }	/* Terminating entry */
+};
+
 #define USB_REQ_DFU_DNLOAD	1
 #define BULK_SIZE		4096
+#define FW_HDR_SIZE		20
 
 static int ath3k_load_firmware(struct usb_device *udev,
 				const struct firmware *firmware)
@@ -106,28 +146,265 @@
 	return err;
 }
 
+static int ath3k_get_state(struct usb_device *udev, unsigned char *state)
+{
+	int pipe = 0;
+
+	pipe = usb_rcvctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, ATH3K_GETSTATE,
+			USB_TYPE_VENDOR | USB_DIR_IN, 0, 0,
+			state, 0x01, USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_get_version(struct usb_device *udev,
+			struct ath3k_version *version)
+{
+	int pipe = 0;
+
+	pipe = usb_rcvctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, ATH3K_GETVERSION,
+			USB_TYPE_VENDOR | USB_DIR_IN, 0, 0, version,
+			sizeof(struct ath3k_version),
+			USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_load_fwfile(struct usb_device *udev,
+		const struct firmware *firmware)
+{
+	u8 *send_buf;
+	int err, pipe, len, size, count, sent = 0;
+	int ret;
+
+	count = firmware->size;
+
+	send_buf = kmalloc(BULK_SIZE, GFP_ATOMIC);
+	if (!send_buf) {
+		BT_ERR("Can't allocate memory chunk for firmware");
+		return -ENOMEM;
+	}
+
+	size = min_t(uint, count, FW_HDR_SIZE);
+	memcpy(send_buf, firmware->data, size);
+
+	pipe = usb_sndctrlpipe(udev, 0);
+	ret = usb_control_msg(udev, pipe, ATH3K_DNLOAD,
+			USB_TYPE_VENDOR, 0, 0, send_buf,
+			size, USB_CTRL_SET_TIMEOUT);
+	if (ret < 0) {
+		BT_ERR("Can't change to loading configuration err");
+		kfree(send_buf);
+		return ret;
+	}
+
+	sent += size;
+	count -= size;
+
+	while (count) {
+		size = min_t(uint, count, BULK_SIZE);
+		pipe = usb_sndbulkpipe(udev, 0x02);
+
+		memcpy(send_buf, firmware->data + sent, size);
+
+		err = usb_bulk_msg(udev, pipe, send_buf, size,
+					&len, 3000);
+		if (err || (len != size)) {
+			BT_ERR("Error in firmware loading err = %d,"
+				"len = %d, size = %d", err, len, size);
+			kfree(send_buf);
+			return err;
+		}
+		sent  += size;
+		count -= size;
+	}
+
+	kfree(send_buf);
+	return 0;
+}
+
+static int ath3k_switch_pid(struct usb_device *udev)
+{
+	int pipe = 0;
+
+	pipe = usb_sndctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, USB_REG_SWITCH_VID_PID,
+			USB_TYPE_VENDOR, 0, 0,
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_set_normal_mode(struct usb_device *udev)
+{
+	unsigned char fw_state;
+	int pipe = 0, ret;
+
+	ret = ath3k_get_state(udev, &fw_state);
+	if (ret < 0) {
+		BT_ERR("Can't get state to change to normal mode err");
+		return ret;
+	}
+
+	if ((fw_state & ATH3K_MODE_MASK) == ATH3K_NORMAL_MODE) {
+		BT_DBG("firmware was already in normal mode");
+		return 0;
+	}
+
+	pipe = usb_sndctrlpipe(udev, 0);
+	return usb_control_msg(udev, pipe, ATH3K_SET_NORMAL_MODE,
+			USB_TYPE_VENDOR, 0, 0,
+			NULL, 0, USB_CTRL_SET_TIMEOUT);
+}
+
+static int ath3k_load_patch(struct usb_device *udev)
+{
+	unsigned char fw_state;
+	char filename[ATH3K_NAME_LEN] = {0};
+	const struct firmware *firmware;
+	struct ath3k_version fw_version, pt_version;
+	int ret;
+
+	ret = ath3k_get_state(udev, &fw_state);
+	if (ret < 0) {
+		BT_ERR("Can't get state to change to load ram patch err");
+		return ret;
+	}
+
+	if (fw_state & ATH3K_PATCH_UPDATE) {
+		BT_DBG("Patch was already downloaded");
+		return 0;
+	}
+
+	ret = ath3k_get_version(udev, &fw_version);
+	if (ret < 0) {
+		BT_ERR("Can't get version to change to load ram patch err");
+		return ret;
+	}
+
+	snprintf(filename, ATH3K_NAME_LEN, "ar3k/AthrBT_0x%08x.dfu",
+		fw_version.rom_version);
+
+	ret = reject_firmware(&firmware, filename, &udev->dev);
+	if (ret < 0) {
+		BT_ERR("Patch file not found %s", filename);
+		return ret;
+	}
+
+	pt_version.rom_version = *(int *)(firmware->data + firmware->size - 8);
+	pt_version.build_version = *(int *)
+		(firmware->data + firmware->size - 4);
+
+	if ((pt_version.rom_version != fw_version.rom_version) ||
+		(pt_version.build_version <= fw_version.build_version)) {
+		BT_ERR("Patch file version did not match with firmware");
+		release_firmware(firmware);
+		return -EINVAL;
+	}
+
+	ret = ath3k_load_fwfile(udev, firmware);
+	release_firmware(firmware);
+
+	return ret;
+}
+
+static int ath3k_load_syscfg(struct usb_device *udev)
+{
+	unsigned char fw_state;
+	char filename[ATH3K_NAME_LEN] = {0};
+	const struct firmware *firmware;
+	struct ath3k_version fw_version;
+	int clk_value, ret;
+
+	ret = ath3k_get_state(udev, &fw_state);
+	if (ret < 0) {
+		BT_ERR("Can't get state to change to load configration err");
+		return -EBUSY;
+	}
+
+	ret = ath3k_get_version(udev, &fw_version);
+	if (ret < 0) {
+		BT_ERR("Can't get version to change to load ram patch err");
+		return ret;
+	}
+
+	switch (fw_version.ref_clock) {
+
+	case ATH3K_XTAL_FREQ_26M:
+		clk_value = 26;
+		break;
+	case ATH3K_XTAL_FREQ_40M:
+		clk_value = 40;
+		break;
+	case ATH3K_XTAL_FREQ_19P2:
+		clk_value = 19;
+		break;
+	default:
+		clk_value = 0;
+		break;
+	}
+
+	snprintf(filename, ATH3K_NAME_LEN, "ar3k/ramps_0x%08x_%d%s",
+		fw_version.rom_version, clk_value, ".dfu");
+
+	ret = reject_firmware(&firmware, filename, &udev->dev);
+	if (ret < 0) {
+		BT_ERR("Configuration file not found %s", filename);
+		return ret;
+	}
+
+	ret = ath3k_load_fwfile(udev, firmware);
+	release_firmware(firmware);
+
+	return ret;
+}
+
 static int ath3k_probe(struct usb_interface *intf,
 			const struct usb_device_id *id)
 {
 	const struct firmware *firmware;
 	struct usb_device *udev = interface_to_usbdev(intf);
+	int ret;
 
 	BT_DBG("intf %p id %p", intf, id);
 
 	if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
 		return -ENODEV;
 
-	if (reject_firmware(&firmware, "/*(DEBLOBBED)*/", &udev->dev) < 0) {
-		return -EIO;
+	/* match device ID in ath3k blacklist table */
+	if (!id->driver_info) {
+		const struct usb_device_id *match;
+		match = usb_match_id(intf, ath3k_blist_tbl);
+		if (match)
+			id = match;
 	}
 
-	if (ath3k_load_firmware(udev, firmware)) {
-		release_firmware(firmware);
+	/* load patch and sysconfig files for AR3012 */
+	if (id->driver_info & BTUSB_ATH3012) {
+		ret = ath3k_load_patch(udev);
+		if (ret < 0) {
+			BT_ERR("Loading patch file failed");
+			return ret;
+		}
+		ret = ath3k_load_syscfg(udev);
+		if (ret < 0) {
+			BT_ERR("Loading sysconfig file failed");
+			return ret;
+		}
+		ret = ath3k_set_normal_mode(udev);
+		if (ret < 0) {
+			BT_ERR("Set normal mode failed");
+			return ret;
+		}
+		ath3k_switch_pid(udev);
+		return 0;
+	}
+
+	if (reject_firmware(&firmware, "/*(DEBLOBBED)*/", &udev->dev) < 0) {
+		BT_ERR("Error loading firmware");
 		return -EIO;
 	}
+
+	ret = ath3k_load_firmware(udev, firmware);
 	release_firmware(firmware);
 
-	return 0;
+	return ret;
 }
 
 static void ath3k_disconnect(struct usb_interface *intf)
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/btusb.c linux-libre-2.6.39-gnu/drivers/bluetooth/btusb.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/btusb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/btusb.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,6 +71,9 @@
 	/* Apple MacBookAir3,1, MacBookAir3,2 */
 	{ USB_DEVICE(0x05ac, 0x821b) },
 
+	/* Apple MacBookPro8,2 */
+	{ USB_DEVICE(0x05ac, 0x821a) },
+
 	/* AVM BlueFRITZ! USB v2.0 */
 	{ USB_DEVICE(0x057c, 0x3800) },
 
@@ -105,6 +108,9 @@
 	/* Atheros AR9285 Malbec with sflash firmware */
 	{ USB_DEVICE(0x03f0, 0x311d), .driver_info = BTUSB_IGNORE },
 
+	/* Atheros 3012 with sflash firmware */
+	{ USB_DEVICE(0x0cf3, 0x3004), .driver_info = BTUSB_IGNORE },
+
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
 
@@ -430,7 +436,7 @@
 	}
 }
 
-static void inline __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
+static inline void __fill_isoc_descriptor(struct urb *urb, int len, int mtu)
 {
 	int i, offset = 0;
 
@@ -687,7 +693,8 @@
 		break;
 
 	case HCI_ACLDATA_PKT:
-		if (!data->bulk_tx_ep || hdev->conn_hash.acl_num < 1)
+		if (!data->bulk_tx_ep || (hdev->conn_hash.acl_num < 1 &&
+						hdev->conn_hash.le_num < 1))
 			return -ENODEV;
 
 		urb = usb_alloc_urb(0, GFP_ATOMIC);
@@ -714,15 +721,11 @@
 		pipe = usb_sndisocpipe(data->udev,
 					data->isoc_tx_ep->bEndpointAddress);
 
-		urb->dev      = data->udev;
-		urb->pipe     = pipe;
-		urb->context  = skb;
-		urb->complete = btusb_isoc_tx_complete;
-		urb->interval = data->isoc_tx_ep->bInterval;
+		usb_fill_int_urb(urb, data->udev, pipe,
+				skb->data, skb->len, btusb_isoc_tx_complete,
+				skb, data->isoc_tx_ep->bInterval);
 
 		urb->transfer_flags  = URB_ISO_ASAP;
-		urb->transfer_buffer = skb->data;
-		urb->transfer_buffer_length = skb->len;
 
 		__fill_isoc_descriptor(urb, skb->len,
 				le16_to_cpu(data->isoc_tx_ep->wMaxPacketSize));
@@ -781,7 +784,7 @@
 	}
 }
 
-static int inline __set_isoc_interface(struct hci_dev *hdev, int altsetting)
+static inline int __set_isoc_interface(struct hci_dev *hdev, int altsetting)
 {
 	struct btusb_data *data = hdev->driver_data;
 	struct usb_interface *intf = data->isoc;
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/btwilink.c linux-libre-2.6.39-gnu/drivers/bluetooth/btwilink.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/btwilink.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/btwilink.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,395 @@
+/*
+ *  Texas Instrument's Bluetooth Driver For Shared Transport.
+ *
+ *  Bluetooth Driver acts as interface between HCI core and
+ *  TI Shared Transport Layer.
+ *
+ *  Copyright (C) 2009-2010 Texas Instruments
+ *  Author: Raja Mani <raja_mani@ti.com>
+ *	Pavan Savoy <pavan_savoy@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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/platform_device.h>
+#include <net/bluetooth/bluetooth.h>
+#include <net/bluetooth/hci_core.h>
+#include <net/bluetooth/hci.h>
+
+#include <linux/ti_wilink_st.h>
+
+/* Bluetooth Driver Version */
+#define VERSION               "1.0"
+#define MAX_BT_CHNL_IDS		3
+
+/* Number of seconds to wait for registration completion
+ * when ST returns PENDING status.
+ */
+#define BT_REGISTER_TIMEOUT   6000	/* 6 sec */
+
+/**
+ * struct ti_st - driver operation structure
+ * @hdev: hci device pointer which binds to bt driver
+ * @reg_status: ST registration callback status
+ * @st_write: write function provided by the ST driver
+ *	to be used by the driver during send_frame.
+ * @wait_reg_completion - completion sync between ti_st_open
+ *	and st_reg_completion_cb.
+ */
+struct ti_st {
+	struct hci_dev *hdev;
+	char reg_status;
+	long (*st_write) (struct sk_buff *);
+	struct completion wait_reg_completion;
+};
+
+/* Increments HCI counters based on pocket ID (cmd,acl,sco) */
+static inline void ti_st_tx_complete(struct ti_st *hst, int pkt_type)
+{
+	struct hci_dev *hdev = hst->hdev;
+
+	/* Update HCI stat counters */
+	switch (pkt_type) {
+	case HCI_COMMAND_PKT:
+		hdev->stat.cmd_tx++;
+		break;
+
+	case HCI_ACLDATA_PKT:
+		hdev->stat.acl_tx++;
+		break;
+
+	case HCI_SCODATA_PKT:
+		hdev->stat.sco_tx++;
+		break;
+	}
+}
+
+/* ------- Interfaces to Shared Transport ------ */
+
+/* Called by ST layer to indicate protocol registration completion
+ * status.ti_st_open() function will wait for signal from this
+ * API when st_register() function returns ST_PENDING.
+ */
+static void st_reg_completion_cb(void *priv_data, char data)
+{
+	struct ti_st *lhst = priv_data;
+
+	/* Save registration status for use in ti_st_open() */
+	lhst->reg_status = data;
+	/* complete the wait in ti_st_open() */
+	complete(&lhst->wait_reg_completion);
+}
+
+/* Called by Shared Transport layer when receive data is
+ * available */
+static long st_receive(void *priv_data, struct sk_buff *skb)
+{
+	struct ti_st *lhst = priv_data;
+	int err;
+
+	if (!skb)
+		return -EFAULT;
+
+	if (!lhst) {
+		kfree_skb(skb);
+		return -EFAULT;
+	}
+
+	skb->dev = (void *) lhst->hdev;
+
+	/* Forward skb to HCI core layer */
+	err = hci_recv_frame(skb);
+	if (err < 0) {
+		BT_ERR("Unable to push skb to HCI core(%d)", err);
+		return err;
+	}
+
+	lhst->hdev->stat.byte_rx += skb->len;
+
+	return 0;
+}
+
+/* ------- Interfaces to HCI layer ------ */
+/* protocol structure registered with shared transport */
+static struct st_proto_s ti_st_proto[MAX_BT_CHNL_IDS] = {
+	{
+		.chnl_id = HCI_ACLDATA_PKT, /* ACL */
+		.hdr_len = sizeof(struct hci_acl_hdr),
+		.offset_len_in_hdr = offsetof(struct hci_acl_hdr, dlen),
+		.len_size = 2,	/* sizeof(dlen) in struct hci_acl_hdr */
+		.reserve = 8,
+	},
+	{
+		.chnl_id = HCI_SCODATA_PKT, /* SCO */
+		.hdr_len = sizeof(struct hci_sco_hdr),
+		.offset_len_in_hdr = offsetof(struct hci_sco_hdr, dlen),
+		.len_size = 1, /* sizeof(dlen) in struct hci_sco_hdr */
+		.reserve = 8,
+	},
+	{
+		.chnl_id = HCI_EVENT_PKT, /* HCI Events */
+		.hdr_len = sizeof(struct hci_event_hdr),
+		.offset_len_in_hdr = offsetof(struct hci_event_hdr, plen),
+		.len_size = 1, /* sizeof(plen) in struct hci_event_hdr */
+		.reserve = 8,
+	},
+};
+
+/* Called from HCI core to initialize the device */
+static int ti_st_open(struct hci_dev *hdev)
+{
+	unsigned long timeleft;
+	struct ti_st *hst;
+	int err, i;
+
+	BT_DBG("%s %p", hdev->name, hdev);
+
+	if (test_and_set_bit(HCI_RUNNING, &hdev->flags))
+		return -EBUSY;
+
+	/* provide contexts for callbacks from ST */
+	hst = hdev->driver_data;
+
+	for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+		ti_st_proto[i].priv_data = hst;
+		ti_st_proto[i].max_frame_size = HCI_MAX_FRAME_SIZE;
+		ti_st_proto[i].recv = st_receive;
+		ti_st_proto[i].reg_complete_cb = st_reg_completion_cb;
+
+		/* Prepare wait-for-completion handler */
+		init_completion(&hst->wait_reg_completion);
+		/* Reset ST registration callback status flag,
+		 * this value will be updated in
+		 * st_reg_completion_cb()
+		 * function whenever it called from ST driver.
+		 */
+		hst->reg_status = -EINPROGRESS;
+
+		err = st_register(&ti_st_proto[i]);
+		if (!err)
+			goto done;
+
+		if (err != -EINPROGRESS) {
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			BT_ERR("st_register failed %d", err);
+			return err;
+		}
+
+		/* ST is busy with either protocol
+		 * registration or firmware download.
+		 */
+		BT_DBG("waiting for registration "
+				"completion signal from ST");
+		timeleft = wait_for_completion_timeout
+			(&hst->wait_reg_completion,
+			 msecs_to_jiffies(BT_REGISTER_TIMEOUT));
+		if (!timeleft) {
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			BT_ERR("Timeout(%d sec),didn't get reg "
+					"completion signal from ST",
+					BT_REGISTER_TIMEOUT / 1000);
+			return -ETIMEDOUT;
+		}
+
+		/* Is ST registration callback
+		 * called with ERROR status? */
+		if (hst->reg_status != 0) {
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			BT_ERR("ST registration completed with invalid "
+					"status %d", hst->reg_status);
+			return -EAGAIN;
+		}
+
+done:
+		hst->st_write = ti_st_proto[i].write;
+		if (!hst->st_write) {
+			BT_ERR("undefined ST write function");
+			clear_bit(HCI_RUNNING, &hdev->flags);
+			for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+				/* Undo registration with ST */
+				err = st_unregister(&ti_st_proto[i]);
+				if (err)
+					BT_ERR("st_unregister() failed with "
+							"error %d", err);
+				hst->st_write = NULL;
+			}
+			return -EIO;
+		}
+	}
+	return 0;
+}
+
+/* Close device */
+static int ti_st_close(struct hci_dev *hdev)
+{
+	int err, i;
+	struct ti_st *hst = hdev->driver_data;
+
+	if (!test_and_clear_bit(HCI_RUNNING, &hdev->flags))
+		return 0;
+
+	for (i = 0; i < MAX_BT_CHNL_IDS; i++) {
+		err = st_unregister(&ti_st_proto[i]);
+		if (err)
+			BT_ERR("st_unregister(%d) failed with error %d",
+					ti_st_proto[i].chnl_id, err);
+	}
+
+	hst->st_write = NULL;
+
+	return err;
+}
+
+static int ti_st_send_frame(struct sk_buff *skb)
+{
+	struct hci_dev *hdev;
+	struct ti_st *hst;
+	long len;
+
+	hdev = (struct hci_dev *)skb->dev;
+
+	if (!test_bit(HCI_RUNNING, &hdev->flags))
+		return -EBUSY;
+
+	hst = hdev->driver_data;
+
+	/* Prepend skb with frame type */
+	memcpy(skb_push(skb, 1), &bt_cb(skb)->pkt_type, 1);
+
+	BT_DBG("%s: type %d len %d", hdev->name, bt_cb(skb)->pkt_type,
+			skb->len);
+
+	/* Insert skb to shared transport layer's transmit queue.
+	 * Freeing skb memory is taken care in shared transport layer,
+	 * so don't free skb memory here.
+	 */
+	len = hst->st_write(skb);
+	if (len < 0) {
+		kfree_skb(skb);
+		BT_ERR("ST write failed (%ld)", len);
+		/* Try Again, would only fail if UART has gone bad */
+		return -EAGAIN;
+	}
+
+	/* ST accepted our skb. So, Go ahead and do rest */
+	hdev->stat.byte_tx += len;
+	ti_st_tx_complete(hst, bt_cb(skb)->pkt_type);
+
+	return 0;
+}
+
+static void ti_st_destruct(struct hci_dev *hdev)
+{
+	BT_DBG("%s", hdev->name);
+	/* do nothing here, since platform remove
+	 * would free the hdev->driver_data
+	 */
+}
+
+static int bt_ti_probe(struct platform_device *pdev)
+{
+	static struct ti_st *hst;
+	struct hci_dev *hdev;
+	int err;
+
+	hst = kzalloc(sizeof(struct ti_st), GFP_KERNEL);
+	if (!hst)
+		return -ENOMEM;
+
+	/* Expose "hciX" device to user space */
+	hdev = hci_alloc_dev();
+	if (!hdev) {
+		kfree(hst);
+		return -ENOMEM;
+	}
+
+	BT_DBG("hdev %p", hdev);
+
+	hst->hdev = hdev;
+	hdev->bus = HCI_UART;
+	hdev->driver_data = hst;
+	hdev->open = ti_st_open;
+	hdev->close = ti_st_close;
+	hdev->flush = NULL;
+	hdev->send = ti_st_send_frame;
+	hdev->destruct = ti_st_destruct;
+	hdev->owner = THIS_MODULE;
+
+	err = hci_register_dev(hdev);
+	if (err < 0) {
+		BT_ERR("Can't register HCI device error %d", err);
+		kfree(hst);
+		hci_free_dev(hdev);
+		return err;
+	}
+
+	BT_DBG("HCI device registered (hdev %p)", hdev);
+
+	dev_set_drvdata(&pdev->dev, hst);
+	return err;
+}
+
+static int bt_ti_remove(struct platform_device *pdev)
+{
+	struct hci_dev *hdev;
+	struct ti_st *hst = dev_get_drvdata(&pdev->dev);
+
+	if (!hst)
+		return -EFAULT;
+
+	BT_DBG("%s", hst->hdev->name);
+
+	hdev = hst->hdev;
+	ti_st_close(hdev);
+	hci_unregister_dev(hdev);
+
+	hci_free_dev(hdev);
+	kfree(hst);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+	return 0;
+}
+
+static struct platform_driver btwilink_driver = {
+	.probe = bt_ti_probe,
+	.remove = bt_ti_remove,
+	.driver = {
+		.name = "btwilink",
+		.owner = THIS_MODULE,
+	},
+};
+
+/* ------- Module Init/Exit interfaces ------ */
+static int __init btwilink_init(void)
+{
+	BT_INFO("Bluetooth Driver for TI WiLink - Version %s", VERSION);
+
+	return platform_driver_register(&btwilink_driver);
+}
+
+static void __exit btwilink_exit(void)
+{
+	platform_driver_unregister(&btwilink_driver);
+}
+
+module_init(btwilink_init);
+module_exit(btwilink_exit);
+
+/* ------ Module Info ------ */
+
+MODULE_AUTHOR("Raja Mani <raja_mani@ti.com>");
+MODULE_DESCRIPTION("Bluetooth Driver for TI Shared Transport" VERSION);
+MODULE_VERSION(VERSION);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/hci_ath.c linux-libre-2.6.39-gnu/drivers/bluetooth/hci_ath.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/hci_ath.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/hci_ath.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,32 +51,32 @@
 
 static int ath_wakeup_ar3k(struct tty_struct *tty)
 {
-	struct termios settings;
-	int status = tty->driver->ops->tiocmget(tty, NULL);
+	struct ktermios ktermios;
+	int status = tty->driver->ops->tiocmget(tty);
 
 	if (status & TIOCM_CTS)
 		return status;
 
 	/* Disable Automatic RTSCTS */
-	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
-	settings.c_cflag &= ~CRTSCTS;
-	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
+	memcpy(&ktermios, tty->termios, sizeof(ktermios));
+	ktermios.c_cflag &= ~CRTSCTS;
+	tty_set_termios(tty, &ktermios);
 
 	/* Clear RTS first */
-	status = tty->driver->ops->tiocmget(tty, NULL);
-	tty->driver->ops->tiocmset(tty, NULL, 0x00, TIOCM_RTS);
+	status = tty->driver->ops->tiocmget(tty);
+	tty->driver->ops->tiocmset(tty, 0x00, TIOCM_RTS);
 	mdelay(20);
 
 	/* Set RTS, wake up board */
-	status = tty->driver->ops->tiocmget(tty, NULL);
-	tty->driver->ops->tiocmset(tty, NULL, TIOCM_RTS, 0x00);
+	status = tty->driver->ops->tiocmget(tty);
+	tty->driver->ops->tiocmset(tty, TIOCM_RTS, 0x00);
 	mdelay(20);
 
-	status = tty->driver->ops->tiocmget(tty, NULL);
+	status = tty->driver->ops->tiocmget(tty);
 
-	n_tty_ioctl_helper(tty, NULL, TCGETS, (unsigned long)&settings);
-	settings.c_cflag |= CRTSCTS;
-	n_tty_ioctl_helper(tty, NULL, TCSETS, (unsigned long)&settings);
+	/* Disable Automatic RTSCTS */
+	ktermios.c_cflag |= CRTSCTS;
+	status = tty_set_termios(tty, &ktermios);
 
 	return status;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/hci_ldisc.c linux-libre-2.6.39-gnu/drivers/bluetooth/hci_ldisc.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/hci_ldisc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/hci_ldisc.c	2011-05-19 00:06:34.000000000 -0400
@@ -398,6 +398,7 @@
 	hdev->flush = hci_uart_flush;
 	hdev->send  = hci_uart_send_frame;
 	hdev->destruct = hci_uart_destruct;
+	hdev->parent = hu->tty->dev;
 
 	hdev->owner = THIS_MODULE;
 
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/hci_ll.c linux-libre-2.6.39-gnu/drivers/bluetooth/hci_ll.c
--- linux-libre-2.6.38-gnu/drivers/bluetooth/hci_ll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/hci_ll.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,7 +207,7 @@
 		/*
 		 * This state means that both the host and the BRF chip
 		 * have simultaneously sent a wake-up-indication packet.
-		 * Traditionaly, in this case, receiving a wake-up-indication
+		 * Traditionally, in this case, receiving a wake-up-indication
 		 * was enough and an additional wake-up-ack wasn't needed.
 		 * This has changed with the BRF6350, which does require an
 		 * explicit wake-up-ack. Other BRF versions, which do not
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/Kconfig linux-libre-2.6.39-gnu/drivers/bluetooth/Kconfig
--- linux-libre-2.6.38-gnu/drivers/bluetooth/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -219,4 +219,14 @@
 	  Say Y here to compile support for "Atheros firmware download driver"
 	  into the kernel or say M to compile it as module (ath3k).
 
+config BT_WILINK
+	tristate "Texas Instruments WiLink7 driver"
+	depends on TI_ST
+	help
+	  This enables the Bluetooth driver for Texas Instrument's BT/FM/GPS
+	  combo devices. This makes use of shared transport line discipline
+	  core driver to communicate with the BT core of the combo chip.
+
+	  Say Y here to compile support for Texas Instrument's WiLink7 driver
+	  into the kernel or say M to compile it as module.
 endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/bluetooth/Makefile linux-libre-2.6.39-gnu/drivers/bluetooth/Makefile
--- linux-libre-2.6.38-gnu/drivers/bluetooth/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/bluetooth/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 obj-$(CONFIG_BT_ATH3K)		+= ath3k.o
 obj-$(CONFIG_BT_MRVL)		+= btmrvl.o
 obj-$(CONFIG_BT_MRVL_SDIO)	+= btmrvl_sdio.o
+obj-$(CONFIG_BT_WILINK)		+= btwilink.o
 
 btmrvl-y			:= btmrvl_main.o
 btmrvl-$(CONFIG_DEBUG_FS)	+= btmrvl_debugfs.o
diff -druN linux-libre-2.6.38-gnu/drivers/cdrom/cdrom.c linux-libre-2.6.39-gnu/drivers/cdrom/cdrom.c
--- linux-libre-2.6.38-gnu/drivers/cdrom/cdrom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cdrom/cdrom.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
   changelog for the 1.x series, David?
 
 2.00  Dec  2, 1997 -- Erik Andersen <andersee@debian.org>
-  -- New maintainer! As David A. van Leeuwen has been too busy to activly
+  -- New maintainer! As David A. van Leeuwen has been too busy to actively
   maintain and improve this driver, I am now carrying on the torch. If
   you have a problem with this driver, please feel free to contact me.
 
@@ -986,6 +986,9 @@
 
 	cdinfo(CD_OPEN, "entering cdrom_open\n"); 
 
+	/* open is event synchronization point, check events first */
+	check_disk_change(bdev);
+
 	/* if this was a O_NONBLOCK open and we should honor the flags,
 	 * do a quick open without drive/disc integrity checks. */
 	cdi->use_count++;
@@ -1012,9 +1015,6 @@
 
 	cdinfo(CD_OPEN, "Use count for \"/dev/%s\" now %d\n",
 			cdi->name, cdi->use_count);
-	/* Do this on open.  Don't wait for mount, because they might
-	    not be mounting, but opening with O_NONBLOCK */
-	check_disk_change(bdev);
 	return 0;
 err_release:
 	if (CDROM_CAN(CDC_LOCK) && cdi->options & CDO_LOCK) {
@@ -2520,7 +2520,7 @@
 /*
  * Ok, this is where problems start.  The current interface for the
  * CDROM_DISC_STATUS ioctl is flawed.  It makes the false assumption that
- * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc.  Unfortunatly, while this
+ * CDs are all CDS_DATA_1 or all CDS_AUDIO, etc.  Unfortunately, while this
  * is often the case, it is also very common for CDs to have some tracks
  * with data, and some tracks with audio.  Just because I feel like it,
  * I declare the following to be the best way to cope.  If the CD has ANY
diff -druN linux-libre-2.6.38-gnu/drivers/cdrom/gdrom.c linux-libre-2.6.39-gnu/drivers/cdrom/gdrom.c
--- linux-libre-2.6.38-gnu/drivers/cdrom/gdrom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cdrom/gdrom.c	2011-05-19 00:06:34.000000000 -0400
@@ -395,10 +395,12 @@
 	return CDS_NO_INFO;
 }
 
-static int gdrom_mediachanged(struct cdrom_device_info *cd_info, int ignore)
+static unsigned int gdrom_check_events(struct cdrom_device_info *cd_info,
+				       unsigned int clearing, int ignore)
 {
 	/* check the sense key */
-	return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60;
+	return (__raw_readb(GDROM_ERROR_REG) & 0xF0) == 0x60 ?
+		DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 /* reset the G1 bus */
@@ -483,7 +485,7 @@
 	.open			= gdrom_open,
 	.release		= gdrom_release,
 	.drive_status		= gdrom_drivestatus,
-	.media_changed		= gdrom_mediachanged,
+	.check_events		= gdrom_check_events,
 	.get_last_session	= gdrom_get_last_session,
 	.reset			= gdrom_hardreset,
 	.audio_ioctl		= gdrom_audio_ioctl,
@@ -509,9 +511,10 @@
 	return 0;
 }
 
-static int gdrom_bdops_mediachanged(struct gendisk *disk)
+static unsigned int gdrom_bdops_check_events(struct gendisk *disk,
+					     unsigned int clearing)
 {
-	return cdrom_media_changed(gd.cd_info);
+	return cdrom_check_events(gd.cd_info, clearing);
 }
 
 static int gdrom_bdops_ioctl(struct block_device *bdev, fmode_t mode,
@@ -530,7 +533,7 @@
 	.owner			= THIS_MODULE,
 	.open			= gdrom_bdops_open,
 	.release		= gdrom_bdops_release,
-	.media_changed		= gdrom_bdops_mediachanged,
+	.check_events		= gdrom_bdops_check_events,
 	.ioctl			= gdrom_bdops_ioctl,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/cdrom/viocd.c linux-libre-2.6.39-gnu/drivers/cdrom/viocd.c
--- linux-libre-2.6.38-gnu/drivers/cdrom/viocd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cdrom/viocd.c	2011-05-19 00:06:34.000000000 -0400
@@ -186,10 +186,11 @@
 	return ret;
 }
 
-static int viocd_blk_media_changed(struct gendisk *disk)
+static unsigned int viocd_blk_check_events(struct gendisk *disk,
+					   unsigned int clearing)
 {
 	struct disk_info *di = disk->private_data;
-	return cdrom_media_changed(&di->viocd_info);
+	return cdrom_check_events(&di->viocd_info, clearing);
 }
 
 static const struct block_device_operations viocd_fops = {
@@ -197,7 +198,7 @@
 	.open =			viocd_blk_open,
 	.release =		viocd_blk_release,
 	.ioctl =		viocd_blk_ioctl,
-	.media_changed =	viocd_blk_media_changed,
+	.check_events =		viocd_blk_check_events,
 };
 
 static int viocd_open(struct cdrom_device_info *cdi, int purpose)
@@ -320,7 +321,8 @@
 	}
 }
 
-static int viocd_media_changed(struct cdrom_device_info *cdi, int disc_nr)
+static unsigned int viocd_check_events(struct cdrom_device_info *cdi,
+				       unsigned int clearing, int disc_nr)
 {
 	struct viocd_waitevent we;
 	HvLpEvent_Rc hvrc;
@@ -340,7 +342,7 @@
 	if (hvrc != 0) {
 		pr_warning("bad rc on HvCallEvent_signalLpEventFast %d\n",
 			   (int)hvrc);
-		return -EIO;
+		return 0;
 	}
 
 	wait_for_completion(&we.com);
@@ -354,7 +356,7 @@
 		return 0;
 	}
 
-	return we.changed;
+	return we.changed ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static int viocd_lock_door(struct cdrom_device_info *cdi, int locking)
@@ -550,7 +552,7 @@
 static struct cdrom_device_ops viocd_dops = {
 	.open = viocd_open,
 	.release = viocd_release,
-	.media_changed = viocd_media_changed,
+	.check_events = viocd_check_events,
 	.lock_door = viocd_lock_door,
 	.generic_packet = viocd_packet,
 	.audio_ioctl = viocd_audio_ioctl,
diff -druN linux-libre-2.6.38-gnu/drivers/char/agp/agp.h linux-libre-2.6.39-gnu/drivers/char/agp/agp.h
--- linux-libre-2.6.38-gnu/drivers/char/agp/agp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/agp/agp.h	2011-05-19 00:06:34.000000000 -0400
@@ -237,7 +237,7 @@
 
 long compat_agp_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
 
-/* Chipset independant registers (from AGP Spec) */
+/* Chipset independent registers (from AGP Spec) */
 #define AGP_APBASE	0x10
 
 #define AGPSTAT		0x4
diff -druN linux-libre-2.6.38-gnu/drivers/char/agp/amd-k7-agp.c linux-libre-2.6.39-gnu/drivers/char/agp/amd-k7-agp.c
--- linux-libre-2.6.38-gnu/drivers/char/agp/amd-k7-agp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/agp/amd-k7-agp.c	2011-05-19 00:06:34.000000000 -0400
@@ -272,7 +272,7 @@
  * This routine could be implemented by taking the addresses
  * written to the GATT, and flushing them individually.  However
  * currently it just flushes the whole table.  Which is probably
- * more efficent, since agp_memory blocks can be a large number of
+ * more efficient, since agp_memory blocks can be a large number of
  * entries.
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/char/agp/generic.c linux-libre-2.6.39-gnu/drivers/char/agp/generic.c
--- linux-libre-2.6.38-gnu/drivers/char/agp/generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/agp/generic.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,6 +115,9 @@
 	struct agp_memory *new;
 	unsigned long alloc_size = num_agp_pages*sizeof(struct page *);
 
+	if (INT_MAX/sizeof(struct page *) < num_agp_pages)
+		return NULL;
+
 	new = kzalloc(sizeof(struct agp_memory), GFP_KERNEL);
 	if (new == NULL)
 		return NULL;
@@ -234,11 +237,14 @@
 	int scratch_pages;
 	struct agp_memory *new;
 	size_t i;
+	int cur_memory;
 
 	if (!bridge)
 		return NULL;
 
-	if ((atomic_read(&bridge->current_memory_agp) + page_count) > bridge->max_memory_agp)
+	cur_memory = atomic_read(&bridge->current_memory_agp);
+	if ((cur_memory + page_count > bridge->max_memory_agp) ||
+	    (cur_memory + page_count < page_count))
 		return NULL;
 
 	if (type >= AGP_USER_TYPES) {
@@ -1089,8 +1095,8 @@
 		return -EINVAL;
 	}
 
-	/* AK: could wrap */
-	if ((pg_start + mem->page_count) > num_entries)
+	if (((pg_start + mem->page_count) > num_entries) ||
+	    ((pg_start + mem->page_count) < pg_start))
 		return -EINVAL;
 
 	j = pg_start;
@@ -1124,7 +1130,7 @@
 {
 	size_t i;
 	struct agp_bridge_data *bridge;
-	int mask_type;
+	int mask_type, num_entries;
 
 	bridge = mem->bridge;
 	if (!bridge)
@@ -1136,6 +1142,11 @@
 	if (type != mem->type)
 		return -EINVAL;
 
+	num_entries = agp_num_entries();
+	if (((pg_start + mem->page_count) > num_entries) ||
+	    ((pg_start + mem->page_count) < pg_start))
+		return -EINVAL;
+
 	mask_type = bridge->driver->agp_type_to_mask_type(bridge, type);
 	if (mask_type != 0) {
 		/* The generic routines know nothing of memory types */
diff -druN linux-libre-2.6.38-gnu/drivers/char/agp/sworks-agp.c linux-libre-2.6.39-gnu/drivers/char/agp/sworks-agp.c
--- linux-libre-2.6.38-gnu/drivers/char/agp/sworks-agp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/agp/sworks-agp.c	2011-05-19 00:06:34.000000000 -0400
@@ -229,7 +229,7 @@
  * This routine could be implemented by taking the addresses
  * written to the GATT, and flushing them individually.  However
  * currently it just flushes the whole table.  Which is probably
- * more efficent, since agp_memory blocks can be a large number of
+ * more efficient, since agp_memory blocks can be a large number of
  * entries.
  */
 static void serverworks_tlbflush(struct agp_memory *temp)
diff -druN linux-libre-2.6.38-gnu/drivers/char/agp/via-agp.c linux-libre-2.6.39-gnu/drivers/char/agp/via-agp.c
--- linux-libre-2.6.38-gnu/drivers/char/agp/via-agp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/agp/via-agp.c	2011-05-19 00:06:34.000000000 -0400
@@ -400,7 +400,7 @@
 	 * the traditional AGP which resides only in chipset. AGP is used
 	 * by 3D driver which wasn't available for the VT3336 and VT3364
 	 * generation until now.  Unfortunately, by testing, VT3364 works
-	 * but VT3336 doesn't. - explaination from via, just leave this as
+	 * but VT3336 doesn't. - explanation from via, just leave this as
 	 * as a placeholder to avoid future patches adding it back in.
 	 */
 #if 0
diff -druN linux-libre-2.6.38-gnu/drivers/char/amiserial.c linux-libre-2.6.39-gnu/drivers/char/amiserial.c
--- linux-libre-2.6.38-gnu/drivers/char/amiserial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/amiserial.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2178 +0,0 @@
-/*
- *  linux/drivers/char/amiserial.c
- *
- * Serial driver for the amiga builtin port.
- *
- * This code was created by taking serial.c version 4.30 from kernel
- * release 2.3.22, replacing all hardware related stuff with the
- * corresponding amiga hardware actions, and removing all irrelevant
- * code. As a consequence, it uses many of the constants and names
- * associated with the registers and bits of 16550 compatible UARTS -
- * but only to keep track of status, etc in the state variables. It
- * was done this was to make it easier to keep the code in line with
- * (non hardware specific) changes to serial.c.
- *
- * The port is registered with the tty driver as minor device 64, and
- * therefore other ports should should only use 65 upwards.
- *
- * Richard Lucock 28/12/99
- *
- *  Copyright (C) 1991, 1992  Linus Torvalds
- *  Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 
- * 		1998, 1999  Theodore Ts'o
- *
- */
-
-/*
- * Serial driver configuration section.  Here are the various options:
- *
- * SERIAL_PARANOIA_CHECK
- * 		Check the magic number for the async_structure where
- * 		ever possible.
- */
-
-#include <linux/delay.h>
-
-#undef SERIAL_PARANOIA_CHECK
-#define SERIAL_DO_RESTART
-
-/* Set of debugging defines */
-
-#undef SERIAL_DEBUG_INTR
-#undef SERIAL_DEBUG_OPEN
-#undef SERIAL_DEBUG_FLOW
-#undef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-
-/* Sanity checks */
-
-#if defined(MODULE) && defined(SERIAL_DEBUG_MCOUNT)
-#define DBG_CNT(s) printk("(%s): [%x] refc=%d, serc=%d, ttyc=%d -> %s\n", \
- tty->name, (info->flags), serial_driver->refcount,info->count,tty->count,s)
-#else
-#define DBG_CNT(s)
-#endif
-
-/*
- * End of serial driver configuration section.
- */
-
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/serial_reg.h>
-static char *serial_version = "4.30";
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/kernel.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/console.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/platform_device.h>
-
-#include <asm/setup.h>
-
-#include <asm/system.h>
-
-#include <asm/irq.h>
-
-#include <asm/amigahw.h>
-#include <asm/amigaints.h>
-
-#define custom amiga_custom
-static char *serial_name = "Amiga-builtin serial driver";
-
-static struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-static struct async_struct *IRQ_ports;
-
-static unsigned char current_ctl_bits;
-
-static void change_speed(struct async_struct *info, struct ktermios *old);
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout);
-
-
-static struct serial_state rs_table[1];
-
-#define NR_PORTS ARRAY_SIZE(rs_table)
-
-#include <asm/uaccess.h>
-
-#define serial_isroot()	(capable(CAP_SYS_ADMIN))
-
-
-static inline int serial_paranoia_check(struct async_struct *info,
-					char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for serial struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null async_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != SERIAL_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/* some serial hardware definitions */
-#define SDR_OVRUN   (1<<15)
-#define SDR_RBF     (1<<14)
-#define SDR_TBE     (1<<13)
-#define SDR_TSRE    (1<<12)
-
-#define SERPER_PARENB    (1<<15)
-
-#define AC_SETCLR   (1<<15)
-#define AC_UARTBRK  (1<<11)
-
-#define SER_DTR     (1<<7)
-#define SER_RTS     (1<<6)
-#define SER_DCD     (1<<5)
-#define SER_CTS     (1<<4)
-#define SER_DSR     (1<<3)
-
-static __inline__ void rtsdtr_ctrl(int bits)
-{
-    ciab.pra = ((bits & (SER_RTS | SER_DTR)) ^ (SER_RTS | SER_DTR)) | (ciab.pra & ~(SER_RTS | SER_DTR));
-}
-
-/*
- * ------------------------------------------------------------
- * rs_stop() and rs_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rs_stop(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_stop"))
-		return;
-
-	local_irq_save(flags);
-	if (info->IER & UART_IER_THRI) {
-		info->IER &= ~UART_IER_THRI;
-		/* disable Tx interrupt and remove any pending interrupts */
-		custom.intena = IF_TBE;
-		mb();
-		custom.intreq = IF_TBE;
-		mb();
-	}
-	local_irq_restore(flags);
-}
-
-static void rs_start(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_start"))
-		return;
-
-	local_irq_save(flags);
-	if (info->xmit.head != info->xmit.tail
-	    && info->xmit.buf
-	    && !(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		custom.intena = IF_SETCLR | IF_TBE;
-		mb();
-		/* set a pending Tx Interrupt, transmitter should restart now */
-		custom.intreq = IF_SETCLR | IF_TBE;
-		mb();
-	}
-	local_irq_restore(flags);
-}
-
-/*
- * ----------------------------------------------------------------------
- *
- * Here starts the interrupt handling routines.  All of the following
- * subroutines are declared as inline and are folded into
- * rs_interrupt().  They were separated out for readability's sake.
- *
- * Note: rs_interrupt() is a "fast" interrupt, which means that it
- * runs with interrupts turned off.  People who may want to modify
- * rs_interrupt() should try to keep the interrupt handler as fast as
- * possible.  After you are done making modifications, it is not a bad
- * idea to do:
- * 
- * gcc -S -DKERNEL -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer serial.c
- *
- * and look at the resulting assemble code in serial.s.
- *
- * 				- Ted Ts'o (tytso@mit.edu), 7-Mar-93
- * -----------------------------------------------------------------------
- */
-
-/*
- * This routine is used by the interrupt handler to schedule
- * processing in the software interrupt portion of the driver.
- */
-static void rs_sched_event(struct async_struct *info,
-			   int event)
-{
-	info->event |= 1 << event;
-	tasklet_schedule(&info->tlet);
-}
-
-static void receive_chars(struct async_struct *info)
-{
-        int status;
-	int serdatr;
-	struct tty_struct *tty = info->tty;
-	unsigned char ch, flag;
-	struct	async_icount *icount;
-	int oe = 0;
-
-	icount = &info->state->icount;
-
-	status = UART_LSR_DR; /* We obviously have a character! */
-	serdatr = custom.serdatr;
-	mb();
-	custom.intreq = IF_RBF;
-	mb();
-
-	if((serdatr & 0x1ff) == 0)
-	    status |= UART_LSR_BI;
-	if(serdatr & SDR_OVRUN)
-	    status |= UART_LSR_OE;
-
-	ch = serdatr & 0xff;
-	icount->rx++;
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("DR%02x:%02x...", ch, status);
-#endif
-	flag = TTY_NORMAL;
-
-	/*
-	 * We don't handle parity or frame errors - but I have left
-	 * the code in, since I'm not sure that the errors can't be
-	 * detected.
-	 */
-
-	if (status & (UART_LSR_BI | UART_LSR_PE |
-		      UART_LSR_FE | UART_LSR_OE)) {
-	  /*
-	   * For statistics only
-	   */
-	  if (status & UART_LSR_BI) {
-	    status &= ~(UART_LSR_FE | UART_LSR_PE);
-	    icount->brk++;
-	  } else if (status & UART_LSR_PE)
-	    icount->parity++;
-	  else if (status & UART_LSR_FE)
-	    icount->frame++;
-	  if (status & UART_LSR_OE)
-	    icount->overrun++;
-
-	  /*
-	   * Now check to see if character should be
-	   * ignored, and mask off conditions which
-	   * should be ignored.
-	   */
-	  if (status & info->ignore_status_mask)
-	    goto out;
-
-	  status &= info->read_status_mask;
-
-	  if (status & (UART_LSR_BI)) {
-#ifdef SERIAL_DEBUG_INTR
-	    printk("handling break....");
-#endif
-	    flag = TTY_BREAK;
-	    if (info->flags & ASYNC_SAK)
-	      do_SAK(tty);
-	  } else if (status & UART_LSR_PE)
-	    flag = TTY_PARITY;
-	  else if (status & UART_LSR_FE)
-	    flag = TTY_FRAME;
-	  if (status & UART_LSR_OE) {
-	    /*
-	     * Overrun is special, since it's
-	     * reported immediately, and doesn't
-	     * affect the current character
-	     */
-	     oe = 1;
-	  }
-	}
-	tty_insert_flip_char(tty, ch, flag);
-	if (oe == 1)
-		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-	tty_flip_buffer_push(tty);
-out:
-	return;
-}
-
-static void transmit_chars(struct async_struct *info)
-{
-	custom.intreq = IF_TBE;
-	mb();
-	if (info->x_char) {
-	        custom.serdat = info->x_char | 0x100;
-		mb();
-		info->state->icount.tx++;
-		info->x_char = 0;
-		return;
-	}
-	if (info->xmit.head == info->xmit.tail
-	    || info->tty->stopped
-	    || info->tty->hw_stopped) {
-		info->IER &= ~UART_IER_THRI;
-	        custom.intena = IF_TBE;
-		mb();
-		return;
-	}
-
-	custom.serdat = info->xmit.buf[info->xmit.tail++] | 0x100;
-	mb();
-	info->xmit.tail = info->xmit.tail & (SERIAL_XMIT_SIZE-1);
-	info->state->icount.tx++;
-
-	if (CIRC_CNT(info->xmit.head,
-		     info->xmit.tail,
-		     SERIAL_XMIT_SIZE) < WAKEUP_CHARS)
-		rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("THRE...");
-#endif
-	if (info->xmit.head == info->xmit.tail) {
-	        custom.intena = IF_TBE;
-		mb();
-		info->IER &= ~UART_IER_THRI;
-	}
-}
-
-static void check_modem_status(struct async_struct *info)
-{
-	unsigned char status = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
-	unsigned char dstatus;
-	struct	async_icount *icount;
-
-	/* Determine bits that have changed */
-	dstatus = status ^ current_ctl_bits;
-	current_ctl_bits = status;
-
-	if (dstatus) {
-		icount = &info->state->icount;
-		/* update input line counters */
-		if (dstatus & SER_DSR)
-			icount->dsr++;
-		if (dstatus & SER_DCD) {
-			icount->dcd++;
-#ifdef CONFIG_HARD_PPS
-			if ((info->flags & ASYNC_HARDPPS_CD) &&
-			    !(status & SER_DCD))
-				hardpps();
-#endif
-		}
-		if (dstatus & SER_CTS)
-			icount->cts++;
-		wake_up_interruptible(&info->delta_msr_wait);
-	}
-
-	if ((info->flags & ASYNC_CHECK_CD) && (dstatus & SER_DCD)) {
-#if (defined(SERIAL_DEBUG_OPEN) || defined(SERIAL_DEBUG_INTR))
-		printk("ttyS%d CD now %s...", info->line,
-		       (!(status & SER_DCD)) ? "on" : "off");
-#endif
-		if (!(status & SER_DCD))
-			wake_up_interruptible(&info->open_wait);
-		else {
-#ifdef SERIAL_DEBUG_OPEN
-			printk("doing serial hangup...");
-#endif
-			if (info->tty)
-				tty_hangup(info->tty);
-		}
-	}
-	if (info->flags & ASYNC_CTS_FLOW) {
-		if (info->tty->hw_stopped) {
-			if (!(status & SER_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx start...");
-#endif
-				info->tty->hw_stopped = 0;
-				info->IER |= UART_IER_THRI;
-				custom.intena = IF_SETCLR | IF_TBE;
-				mb();
-				/* set a pending Tx Interrupt, transmitter should restart now */
-				custom.intreq = IF_SETCLR | IF_TBE;
-				mb();
-				rs_sched_event(info, RS_EVENT_WRITE_WAKEUP);
-				return;
-			}
-		} else {
-			if ((status & SER_CTS)) {
-#if (defined(SERIAL_DEBUG_INTR) || defined(SERIAL_DEBUG_FLOW))
-				printk("CTS tx stop...");
-#endif
-				info->tty->hw_stopped = 1;
-				info->IER &= ~UART_IER_THRI;
-				/* disable Tx interrupt and remove any pending interrupts */
-				custom.intena = IF_TBE;
-				mb();
-				custom.intreq = IF_TBE;
-				mb();
-			}
-		}
-	}
-}
-
-static irqreturn_t ser_vbl_int( int irq, void *data)
-{
-        /* vbl is just a periodic interrupt we tie into to update modem status */
-	struct async_struct * info = IRQ_ports;
-	/*
-	 * TBD - is it better to unregister from this interrupt or to
-	 * ignore it if MSI is clear ?
-	 */
-	if(info->IER & UART_IER_MSI)
-	  check_modem_status(info);
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ser_rx_int(int irq, void *dev_id)
-{
-	struct async_struct * info;
-
-#ifdef SERIAL_DEBUG_INTR
-	printk("ser_rx_int...");
-#endif
-
-	info = IRQ_ports;
-	if (!info || !info->tty)
-		return IRQ_NONE;
-
-	receive_chars(info);
-	info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
-	printk("end.\n");
-#endif
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t ser_tx_int(int irq, void *dev_id)
-{
-	struct async_struct * info;
-
-	if (custom.serdatr & SDR_TBE) {
-#ifdef SERIAL_DEBUG_INTR
-	  printk("ser_tx_int...");
-#endif
-
-	  info = IRQ_ports;
-	  if (!info || !info->tty)
-		return IRQ_NONE;
-
-	  transmit_chars(info);
-	  info->last_active = jiffies;
-#ifdef SERIAL_DEBUG_INTR
-	  printk("end.\n");
-#endif
-	}
-	return IRQ_HANDLED;
-}
-
-/*
- * -------------------------------------------------------------------
- * Here ends the serial interrupt routines.
- * -------------------------------------------------------------------
- */
-
-/*
- * This routine is used to handle the "bottom half" processing for the
- * serial driver, known also the "software interrupt" processing.
- * This processing is done at the kernel interrupt level, after the
- * rs_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON.  This
- * is where time-consuming activities which can not be done in the
- * interrupt driver proper are done; the interrupt driver schedules
- * them using rs_sched_event(), and they get done here.
- */
-
-static void do_softint(unsigned long private_)
-{
-	struct async_struct	*info = (struct async_struct *) private_;
-	struct tty_struct	*tty;
-
-	tty = info->tty;
-	if (!tty)
-		return;
-
-	if (test_and_clear_bit(RS_EVENT_WRITE_WAKEUP, &info->event))
-		tty_wakeup(tty);
-}
-
-/*
- * ---------------------------------------------------------------
- * Low level utility subroutines for the serial driver:  routines to
- * figure out the appropriate timeout for an interrupt chain, routines
- * to initialize and startup a serial port, and routines to shutdown a
- * serial port.  Useful stuff like that.
- * ---------------------------------------------------------------
- */
-
-static int startup(struct async_struct * info)
-{
-	unsigned long flags;
-	int	retval=0;
-	unsigned long page;
-
-	page = get_zeroed_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	local_irq_save(flags);
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		free_page(page);
-		goto errout;
-	}
-
-	if (info->xmit.buf)
-		free_page(page);
-	else
-		info->xmit.buf = (unsigned char *) page;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("starting up ttys%d ...", info->line);
-#endif
-
-	/* Clear anything in the input buffer */
-
-	custom.intreq = IF_RBF;
-	mb();
-
-	retval = request_irq(IRQ_AMIGA_VERTB, ser_vbl_int, 0, "serial status", info);
-	if (retval) {
-	  if (serial_isroot()) {
-	    if (info->tty)
-	      set_bit(TTY_IO_ERROR,
-		      &info->tty->flags);
-	    retval = 0;
-	  }
-	  goto errout;
-	}
-
-	/* enable both Rx and Tx interrupts */
-	custom.intena = IF_SETCLR | IF_RBF | IF_TBE;
-	mb();
-	info->IER = UART_IER_MSI;
-
-	/* remember current state of the DCD and CTS bits */
-	current_ctl_bits = ciab.pra & (SER_DCD | SER_CTS | SER_DSR);
-
-	IRQ_ports = info;
-
-	info->MCR = 0;
-	if (info->tty->termios->c_cflag & CBAUD)
-	  info->MCR = SER_DTR | SER_RTS;
-	rtsdtr_ctrl(info->MCR);
-
-	if (info->tty)
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	info->xmit.head = info->xmit.tail = 0;
-
-	/*
-	 * Set up the tty->alt_speed kludge
-	 */
-	if (info->tty) {
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			info->tty->alt_speed = 57600;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			info->tty->alt_speed = 115200;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			info->tty->alt_speed = 230400;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			info->tty->alt_speed = 460800;
-	}
-
-	/*
-	 * and set the speed of the serial port
-	 */
-	change_speed(info, NULL);
-
-	info->flags |= ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-	return 0;
-
-errout:
-	local_irq_restore(flags);
-	return retval;
-}
-
-/*
- * This routine will shutdown a serial port; interrupts are disabled, and
- * DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct async_struct * info)
-{
-	unsigned long	flags;
-	struct serial_state *state;
-
-	if (!(info->flags & ASYNC_INITIALIZED))
-		return;
-
-	state = info->state;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("Shutting down serial port %d ....\n", info->line);
-#endif
-
-	local_irq_save(flags); /* Disable interrupts */
-
-	/*
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
-	wake_up_interruptible(&info->delta_msr_wait);
-
-	IRQ_ports = NULL;
-
-	/*
-	 * Free the IRQ, if necessary
-	 */
-	free_irq(IRQ_AMIGA_VERTB, info);
-
-	if (info->xmit.buf) {
-		free_page((unsigned long) info->xmit.buf);
-		info->xmit.buf = NULL;
-	}
-
-	info->IER = 0;
-	custom.intena = IF_RBF | IF_TBE;
-	mb();
-
-	/* disable break condition */
-	custom.adkcon = AC_UARTBRK;
-	mb();
-
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL))
-		info->MCR &= ~(SER_DTR|SER_RTS);
-	rtsdtr_ctrl(info->MCR);
-
-	if (info->tty)
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-
-	info->flags &= ~ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-}
-
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static void change_speed(struct async_struct *info,
-			 struct ktermios *old_termios)
-{
-	int	quot = 0, baud_base, baud;
-	unsigned cflag, cval = 0;
-	int	bits;
-	unsigned long	flags;
-
-	if (!info->tty || !info->tty->termios)
-		return;
-	cflag = info->tty->termios->c_cflag;
-
-	/* Byte size is always 8 bits plus parity bit if requested */
-
-	cval = 3; bits = 10;
-	if (cflag & CSTOPB) {
-		cval |= 0x04;
-		bits++;
-	}
-	if (cflag & PARENB) {
-		cval |= UART_LCR_PARITY;
-		bits++;
-	}
-	if (!(cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-#ifdef CMSPAR
-	if (cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-#endif
-
-	/* Determine divisor based on baud rate */
-	baud = tty_get_baud_rate(info->tty);
-	if (!baud)
-		baud = 9600;	/* B0 transition handled in rs_set_termios */
-	baud_base = info->state->baud_base;
-	if (baud == 38400 &&
-	    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-		quot = info->state->custom_divisor;
-	else {
-		if (baud == 134)
-			/* Special case since 134 is really 134.5 */
-			quot = (2*baud_base / 269);
-		else if (baud)
-			quot = baud_base / baud;
-	}
-	/* If the quotient is zero refuse the change */
-	if (!quot && old_termios) {
-		/* FIXME: Will need updating for new tty in the end */
-		info->tty->termios->c_cflag &= ~CBAUD;
-		info->tty->termios->c_cflag |= (old_termios->c_cflag & CBAUD);
-		baud = tty_get_baud_rate(info->tty);
-		if (!baud)
-			baud = 9600;
-		if (baud == 38400 &&
-		    ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST))
-			quot = info->state->custom_divisor;
-		else {
-			if (baud == 134)
-				/* Special case since 134 is really 134.5 */
-				quot = (2*baud_base / 269);
-			else if (baud)
-				quot = baud_base / baud;
-		}
-	}
-	/* As a last resort, if the quotient is zero, default to 9600 bps */
-	if (!quot)
-		quot = baud_base / 9600;
-	info->quot = quot;
-	info->timeout = ((info->xmit_fifo_size*HZ*bits*quot) / baud_base);
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	/* CTS flow control flag and modem status interrupts */
-	info->IER &= ~UART_IER_MSI;
-	if (info->flags & ASYNC_HARDPPS_CD)
-		info->IER |= UART_IER_MSI;
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->IER |= UART_IER_MSI;
-	} else
-		info->flags &= ~ASYNC_CTS_FLOW;
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else {
-		info->flags |= ASYNC_CHECK_CD;
-		info->IER |= UART_IER_MSI;
-	}
-	/* TBD:
-	 * Does clearing IER_MSI imply that we should disable the VBL interrupt ?
-	 */
-
-	/*
-	 * Set up parity check flag
-	 */
-
-	info->read_status_mask = UART_LSR_OE | UART_LSR_DR;
-	if (I_INPCK(info->tty))
-		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (I_BRKINT(info->tty) || I_PARMRK(info->tty))
-		info->read_status_mask |= UART_LSR_BI;
-
-	/*
-	 * Characters to ignore
-	 */
-	info->ignore_status_mask = 0;
-	if (I_IGNPAR(info->tty))
-		info->ignore_status_mask |= UART_LSR_PE | UART_LSR_FE;
-	if (I_IGNBRK(info->tty)) {
-		info->ignore_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore 
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->tty))
-			info->ignore_status_mask |= UART_LSR_OE;
-	}
-	/*
-	 * !!! ignore all characters if CREAD is not set
-	 */
-	if ((cflag & CREAD) == 0)
-		info->ignore_status_mask |= UART_LSR_DR;
-	local_irq_save(flags);
-
-	{
-	  short serper;
-
-	/* Set up the baud rate */
-	  serper = quot - 1;
-
-	/* Enable or disable parity bit */
-
-	if(cval & UART_LCR_PARITY)
-	  serper |= (SERPER_PARENB);
-
-	custom.serper = serper;
-	mb();
-	}
-
-	info->LCR = cval;				/* Save LCR */
-	local_irq_restore(flags);
-}
-
-static int rs_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct async_struct *info;
-	unsigned long flags;
-
-	info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_put_char"))
-		return 0;
-
-	if (!info->xmit.buf)
-		return 0;
-
-	local_irq_save(flags);
-	if (CIRC_SPACE(info->xmit.head,
-		       info->xmit.tail,
-		       SERIAL_XMIT_SIZE) == 0) {
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	info->xmit.buf[info->xmit.head++] = ch;
-	info->xmit.head &= SERIAL_XMIT_SIZE-1;
-	local_irq_restore(flags);
-	return 1;
-}
-
-static void rs_flush_chars(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_flush_chars"))
-		return;
-
-	if (info->xmit.head == info->xmit.tail
-	    || tty->stopped
-	    || tty->hw_stopped
-	    || !info->xmit.buf)
-		return;
-
-	local_irq_save(flags);
-	info->IER |= UART_IER_THRI;
-	custom.intena = IF_SETCLR | IF_TBE;
-	mb();
-	/* set a pending Tx Interrupt, transmitter should restart now */
-	custom.intreq = IF_SETCLR | IF_TBE;
-	mb();
-	local_irq_restore(flags);
-}
-
-static int rs_write(struct tty_struct * tty, const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	struct async_struct *info;
-	unsigned long flags;
-
-	info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_write"))
-		return 0;
-
-	if (!info->xmit.buf)
-		return 0;
-
-	local_irq_save(flags);
-	while (1) {
-		c = CIRC_SPACE_TO_END(info->xmit.head,
-				      info->xmit.tail,
-				      SERIAL_XMIT_SIZE);
-		if (count < c)
-			c = count;
-		if (c <= 0) {
-			break;
-		}
-		memcpy(info->xmit.buf + info->xmit.head, buf, c);
-		info->xmit.head = ((info->xmit.head + c) &
-				   (SERIAL_XMIT_SIZE-1));
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	local_irq_restore(flags);
-
-	if (info->xmit.head != info->xmit.tail
-	    && !tty->stopped
-	    && !tty->hw_stopped
-	    && !(info->IER & UART_IER_THRI)) {
-		info->IER |= UART_IER_THRI;
-		local_irq_disable();
-		custom.intena = IF_SETCLR | IF_TBE;
-		mb();
-		/* set a pending Tx Interrupt, transmitter should restart now */
-		custom.intreq = IF_SETCLR | IF_TBE;
-		mb();
-		local_irq_restore(flags);
-	}
-	return ret;
-}
-
-static int rs_write_room(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_write_room"))
-		return 0;
-	return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static int rs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "rs_chars_in_buffer"))
-		return 0;
-	return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
-}
-
-static void rs_flush_buffer(struct tty_struct *tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_flush_buffer"))
-		return;
-	local_irq_save(flags);
-	info->xmit.head = info->xmit.tail = 0;
-	local_irq_restore(flags);
-	tty_wakeup(tty);
-}
-
-/*
- * This function is used to send a high-priority XON/XOFF character to
- * the device
- */
-static void rs_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct async_struct *info = tty->driver_data;
-        unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_send_char"))
-		return;
-
-	info->x_char = ch;
-	if (ch) {
-		/* Make sure transmit interrupts are on */
-
-	        /* Check this ! */
-	        local_irq_save(flags);
-		if(!(custom.intenar & IF_TBE)) {
-		    custom.intena = IF_SETCLR | IF_TBE;
-		    mb();
-		    /* set a pending Tx Interrupt, transmitter should restart now */
-		    custom.intreq = IF_SETCLR | IF_TBE;
-		    mb();
-		}
-		local_irq_restore(flags);
-
-		info->IER |= UART_IER_THRI;
-	}
-}
-
-/*
- * ------------------------------------------------------------
- * rs_throttle()
- * 
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- * ------------------------------------------------------------
- */
-static void rs_throttle(struct tty_struct * tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "rs_throttle"))
-		return;
-
-	if (I_IXOFF(tty))
-		rs_send_xchar(tty, STOP_CHAR(tty));
-
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR &= ~SER_RTS;
-
-	local_irq_save(flags);
-	rtsdtr_ctrl(info->MCR);
-	local_irq_restore(flags);
-}
-
-static void rs_unthrottle(struct tty_struct * tty)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-#ifdef SERIAL_DEBUG_THROTTLE
-	char	buf[64];
-
-	printk("unthrottle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "rs_unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			rs_send_xchar(tty, START_CHAR(tty));
-	}
-	if (tty->termios->c_cflag & CRTSCTS)
-		info->MCR |= SER_RTS;
-	local_irq_save(flags);
-	rtsdtr_ctrl(info->MCR);
-	local_irq_restore(flags);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static int get_serial_info(struct async_struct * info,
-			   struct serial_struct __user * retinfo)
-{
-	struct serial_struct tmp;
-	struct serial_state *state = info->state;
-   
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tty_lock();
-	tmp.type = state->type;
-	tmp.line = state->line;
-	tmp.port = state->port;
-	tmp.irq = state->irq;
-	tmp.flags = state->flags;
-	tmp.xmit_fifo_size = state->xmit_fifo_size;
-	tmp.baud_base = state->baud_base;
-	tmp.close_delay = state->close_delay;
-	tmp.closing_wait = state->closing_wait;
-	tmp.custom_divisor = state->custom_divisor;
-	tty_unlock();
-	if (copy_to_user(retinfo,&tmp,sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_serial_info(struct async_struct * info,
-			   struct serial_struct __user * new_info)
-{
-	struct serial_struct new_serial;
- 	struct serial_state old_state, *state;
-	unsigned int		change_irq,change_port;
-	int 			retval = 0;
-
-	if (copy_from_user(&new_serial,new_info,sizeof(new_serial)))
-		return -EFAULT;
-
-	tty_lock();
-	state = info->state;
-	old_state = *state;
-  
-	change_irq = new_serial.irq != state->irq;
-	change_port = (new_serial.port != state->port);
-	if(change_irq || change_port || (new_serial.xmit_fifo_size != state->xmit_fifo_size)) {
-	  tty_unlock();
-	  return -EINVAL;
-	}
-  
-	if (!serial_isroot()) {
-		if ((new_serial.baud_base != state->baud_base) ||
-		    (new_serial.close_delay != state->close_delay) ||
-		    (new_serial.xmit_fifo_size != state->xmit_fifo_size) ||
-		    ((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (state->flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		state->flags = ((state->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		state->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	if (new_serial.baud_base < 9600) {
-		tty_unlock();
-		return -EINVAL;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	state->baud_base = new_serial.baud_base;
-	state->flags = ((state->flags & ~ASYNC_FLAGS) |
-			(new_serial.flags & ASYNC_FLAGS));
-	info->flags = ((state->flags & ~ASYNC_INTERNAL_FLAGS) |
-		       (info->flags & ASYNC_INTERNAL_FLAGS));
-	state->custom_divisor = new_serial.custom_divisor;
-	state->close_delay = new_serial.close_delay * HZ/100;
-	state->closing_wait = new_serial.closing_wait * HZ/100;
-	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-check_and_exit:
-	if (info->flags & ASYNC_INITIALIZED) {
-		if (((old_state.flags & ASYNC_SPD_MASK) !=
-		     (state->flags & ASYNC_SPD_MASK)) ||
-		    (old_state.custom_divisor != state->custom_divisor)) {
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-				info->tty->alt_speed = 57600;
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-				info->tty->alt_speed = 115200;
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-				info->tty->alt_speed = 230400;
-			if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-				info->tty->alt_speed = 460800;
-			change_speed(info, NULL);
-		}
-	} else
-		retval = startup(info);
-	tty_unlock();
-	return retval;
-}
-
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- * 	    is emptied.  On bus types like RS485, the transmitter must
- * 	    release the bus after transmitting. This must be done when
- * 	    the transmit shift register is empty, not be done when the
- * 	    transmit holding register is empty.  This functionality
- * 	    allows an RS485 driver to be written in user space. 
- */
-static int get_lsr_info(struct async_struct * info, unsigned int __user *value)
-{
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	status = custom.serdatr;
-	mb();
-	local_irq_restore(flags);
-	result = ((status & SDR_TSRE) ? TIOCSER_TEMT : 0);
-	if (copy_to_user(value, &result, sizeof(int)))
-		return -EFAULT;
-	return 0;
-}
-
-
-static int rs_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned char control, status;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	control = info->MCR;
-	local_irq_save(flags);
-	status = ciab.pra;
-	local_irq_restore(flags);
-	return    ((control & SER_RTS) ? TIOCM_RTS : 0)
-		| ((control & SER_DTR) ? TIOCM_DTR : 0)
-		| (!(status  & SER_DCD) ? TIOCM_CAR : 0)
-		| (!(status  & SER_DSR) ? TIOCM_DSR : 0)
-		| (!(status  & SER_CTS) ? TIOCM_CTS : 0);
-}
-
-static int rs_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	local_irq_save(flags);
-	if (set & TIOCM_RTS)
-		info->MCR |= SER_RTS;
-	if (set & TIOCM_DTR)
-		info->MCR |= SER_DTR;
-	if (clear & TIOCM_RTS)
-		info->MCR &= ~SER_RTS;
-	if (clear & TIOCM_DTR)
-		info->MCR &= ~SER_DTR;
-	rtsdtr_ctrl(info->MCR);
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*
- * rs_break() --- routine which turns the break handling on or off
- */
-static int rs_break(struct tty_struct *tty, int break_state)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_break"))
-		return -EINVAL;
-
-	local_irq_save(flags);
-	if (break_state == -1)
-	  custom.adkcon = AC_SETCLR | AC_UARTBRK;
-	else
-	  custom.adkcon = AC_UARTBRK;
-	mb();
-	local_irq_restore(flags);
-	return 0;
-}
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- *     RI where only 0->1 is counted.
- */
-static int rs_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct async_struct *info = tty->driver_data;
-	struct async_icount cnow;
-	unsigned long flags;
-
-	local_irq_save(flags);
-	cnow = info->state->icount;
-	local_irq_restore(flags);
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-static int rs_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct async_struct * info = tty->driver_data;
-	struct async_icount cprev, cnow;	/* kernel counter temps */
-	void __user *argp = (void __user *)arg;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, "rs_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCSERCONFIG) && (cmd != TIOCSERGSTRUCT) &&
-	    (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-		case TIOCGSERIAL:
-			return get_serial_info(info, argp);
-		case TIOCSSERIAL:
-			return set_serial_info(info, argp);
-		case TIOCSERCONFIG:
-			return 0;
-
-		case TIOCSERGETLSR: /* Get line status register */
-			return get_lsr_info(info, argp);
-
-		case TIOCSERGSTRUCT:
-			if (copy_to_user(argp,
-					 info, sizeof(struct async_struct)))
-				return -EFAULT;
-			return 0;
-
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
- 		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-		case TIOCMIWAIT:
-			local_irq_save(flags);
-			/* note the counters on entry */
-			cprev = info->state->icount;
-			local_irq_restore(flags);
-			while (1) {
-				interruptible_sleep_on(&info->delta_msr_wait);
-				/* see if a signal did it */
-				if (signal_pending(current))
-					return -ERESTARTSYS;
-				local_irq_save(flags);
-				cnow = info->state->icount; /* atomic copy */
-				local_irq_restore(flags);
-				if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr && 
-				    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts)
-					return -EIO; /* no change => error */
-				if ( ((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-				     ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-				     ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-				     ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-					return 0;
-				}
-				cprev = cnow;
-			}
-			/* NOTREACHED */
-
-		case TIOCSERGWILD:
-		case TIOCSERSWILD:
-			/* "setserial -W" is called in Debian boot */
-			printk ("TIOCSER?WILD ioctl obsolete, ignored.\n");
-			return 0;
-
-		default:
-			return -ENOIOCTLCMD;
-		}
-	return 0;
-}
-
-static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct async_struct *info = tty->driver_data;
-	unsigned long flags;
-	unsigned int cflag = tty->termios->c_cflag;
-
-	change_speed(info, old_termios);
-
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) &&
-	    !(cflag & CBAUD)) {
-		info->MCR &= ~(SER_DTR|SER_RTS);
-		local_irq_save(flags);
-		rtsdtr_ctrl(info->MCR);
-		local_irq_restore(flags);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    (cflag & CBAUD)) {
-		info->MCR |= SER_DTR;
-		if (!(tty->termios->c_cflag & CRTSCTS) || 
-		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->MCR |= SER_RTS;
-		}
-		local_irq_save(flags);
-		rtsdtr_ctrl(info->MCR);
-		local_irq_restore(flags);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rs_start(tty);
-	}
-
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}
-
-/*
- * ------------------------------------------------------------
- * rs_close()
- * 
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- * ------------------------------------------------------------
- */
-static void rs_close(struct tty_struct *tty, struct file * filp)
-{
-	struct async_struct * info = tty->driver_data;
-	struct serial_state *state;
-	unsigned long flags;
-
-	if (!info || serial_paranoia_check(info, tty->name, "rs_close"))
-		return;
-
-	state = info->state;
-
-	local_irq_save(flags);
-
-	if (tty_hung_up_p(filp)) {
-		DBG_CNT("before DEC-hung");
-		local_irq_restore(flags);
-		return;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_close ttys%d, count = %d\n", info->line, state->count);
-#endif
-	if ((tty->count == 1) && (state->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  state->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("rs_close: bad serial port count; tty->count is 1, "
-		       "state->count is %d\n", state->count);
-		state->count = 1;
-	}
-	if (--state->count < 0) {
-		printk("rs_close: bad serial port count for ttys%d: %d\n",
-		       info->line, state->count);
-		state->count = 0;
-	}
-	if (state->count) {
-		DBG_CNT("before DEC-2");
-		local_irq_restore(flags);
-		return;
-	}
-	info->flags |= ASYNC_CLOSING;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	if (info->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, info->closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	info->read_status_mask &= ~UART_LSR_DR;
-	if (info->flags & ASYNC_INITIALIZED) {
-	        /* disable receive interrupts */
-	        custom.intena = IF_RBF;
-		mb();
-		/* clear any pending receive interrupt */
-		custom.intreq = IF_RBF;
-		mb();
-
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		rs_wait_until_sent(tty, info->timeout);
-	}
-	shutdown(info);
-	rs_flush_buffer(tty);
-		
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-	info->event = 0;
-	info->tty = NULL;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			msleep_interruptible(jiffies_to_msecs(info->close_delay));
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-	local_irq_restore(flags);
-}
-
-/*
- * rs_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct async_struct * info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	int tty_was_locked = tty_locked();
-	int lsr;
-
-	if (serial_paranoia_check(info, tty->name, "rs_wait_until_sent"))
-		return;
-
-	if (info->xmit_fifo_size == 0)
-		return; /* Just in case.... */
-
-	orig_jiffies = jiffies;
-
-	/*
-	 * tty_wait_until_sent is called from lots of places,
-	 * with or without the BTM.
-	 */
-	if (!tty_was_locked)
-		tty_lock();
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 * 
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = (info->timeout - HZ/50) / info->xmit_fifo_size;
-	char_time = char_time / 5;
-	if (char_time == 0)
-		char_time = 1;
-	if (timeout)
-	  char_time = min_t(unsigned long, char_time, timeout);
-	/*
-	 * If the transmitter hasn't cleared in twice the approximate
-	 * amount of time to send the entire FIFO, it probably won't
-	 * ever clear.  This assumes the UART isn't doing flow
-	 * control, which is currently the case.  Hence, if it ever
-	 * takes longer than info->timeout, this is probably due to a
-	 * UART bug of some kind.  So, we clamp the timeout parameter at
-	 * 2*info->timeout.
-	 */
-	if (!timeout || timeout > 2*info->timeout)
-		timeout = 2*info->timeout;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("In rs_wait_until_sent(%d) check=%lu...", timeout, char_time);
-	printk("jiff=%lu...", jiffies);
-#endif
-	while(!((lsr = custom.serdatr) & SDR_TSRE)) {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-		printk("serdatr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-		msleep_interruptible(jiffies_to_msecs(char_time));
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-	__set_current_state(TASK_RUNNING);
-	if (!tty_was_locked)
-		tty_unlock();
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * rs_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rs_hangup(struct tty_struct *tty)
-{
-	struct async_struct * info = tty->driver_data;
-	struct serial_state *state = info->state;
-
-	if (serial_paranoia_check(info, tty->name, "rs_hangup"))
-		return;
-
-	state = info->state;
-
-	rs_flush_buffer(tty);
-	shutdown(info);
-	info->event = 0;
-	state->count = 0;
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->tty = NULL;
-	wake_up_interruptible(&info->open_wait);
-}
-
-/*
- * ------------------------------------------------------------
- * rs_open() and friends
- * ------------------------------------------------------------
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-			   struct async_struct *info)
-{
-#ifdef DECLARE_WAITQUEUE
-	DECLARE_WAITQUEUE(wait, current);
-#else
-	struct wait_queue wait = { current, NULL };
-#endif
-	struct serial_state *state = info->state;
-	int		retval;
-	int		do_clocal = 0, extra_count = 0;
-	unsigned long	flags;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		if (info->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		return ((info->flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, state->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: ttys%d, count = %d\n",
-	       state->line, state->count);
-#endif
-	local_irq_save(flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = 1;
-		state->count--;
-	}
-	local_irq_restore(flags);
-	info->blocked_open++;
-	while (1) {
-		local_irq_save(flags);
-		if (tty->termios->c_cflag & CBAUD)
-		        rtsdtr_ctrl(SER_DTR|SER_RTS);
-		local_irq_restore(flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(info->flags & ASYNC_INITIALIZED)) {
-#ifdef SERIAL_DO_RESTART
-			if (info->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-#else
-			retval = -EAGAIN;
-#endif
-			break;
-		}
-		if (!(info->flags & ASYNC_CLOSING) &&
-		    (do_clocal || (!(ciab.pra & SER_DCD)) ))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: ttys%d, count = %d\n",
-		       info->line, state->count);
-#endif
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-	if (extra_count)
-		state->count++;
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: ttys%d, count = %d\n",
-	       info->line, state->count);
-#endif
-	if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}
-
-static int get_async_struct(int line, struct async_struct **ret_info)
-{
-	struct async_struct *info;
-	struct serial_state *sstate;
-
-	sstate = rs_table + line;
-	sstate->count++;
-	if (sstate->info) {
-		*ret_info = sstate->info;
-		return 0;
-	}
-	info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
-	if (!info) {
-		sstate->count--;
-		return -ENOMEM;
-	}
-#ifdef DECLARE_WAITQUEUE
-	init_waitqueue_head(&info->open_wait);
-	init_waitqueue_head(&info->close_wait);
-	init_waitqueue_head(&info->delta_msr_wait);
-#endif
-	info->magic = SERIAL_MAGIC;
-	info->port = sstate->port;
-	info->flags = sstate->flags;
-	info->xmit_fifo_size = sstate->xmit_fifo_size;
-	info->line = line;
-	tasklet_init(&info->tlet, do_softint, (unsigned long)info);
-	info->state = sstate;
-	if (sstate->info) {
-		kfree(info);
-		*ret_info = sstate->info;
-		return 0;
-	}
-	*ret_info = sstate->info = info;
-	return 0;
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int rs_open(struct tty_struct *tty, struct file * filp)
-{
-	struct async_struct	*info;
-	int 			retval, line;
-
-	line = tty->index;
-	if ((line < 0) || (line >= NR_PORTS)) {
-		return -ENODEV;
-	}
-	retval = get_async_struct(line, &info);
-	if (retval) {
-		return retval;
-	}
-	tty->driver_data = info;
-	info->tty = tty;
-	if (serial_paranoia_check(info, tty->name, "rs_open"))
-		return -ENODEV;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s, count = %d\n", tty->name, info->state->count);
-#endif
-	info->tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	/*
-	 * If the port is the middle of closing, bail out now
-	 */
-	if (tty_hung_up_p(filp) ||
-	    (info->flags & ASYNC_CLOSING)) {
-		if (info->flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->close_wait);
-#ifdef SERIAL_DO_RESTART
-		return ((info->flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-#else
-		return -EAGAIN;
-#endif
-	}
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval) {
-		return retval;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("rs_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("rs_open %s successful...", tty->name);
-#endif
-	return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline void line_info(struct seq_file *m, struct serial_state *state)
-{
-	struct async_struct *info = state->info, scr_info;
-	char	stat_buf[30], control, status;
-	unsigned long flags;
-
-	seq_printf(m, "%d: uart:amiga_builtin",state->line);
-
-	/*
-	 * Figure out the current RS-232 lines
-	 */
-	if (!info) {
-		info = &scr_info;	/* This is just for serial_{in,out} */
-
-		info->magic = SERIAL_MAGIC;
-		info->flags = state->flags;
-		info->quot = 0;
-		info->tty = NULL;
-	}
-	local_irq_save(flags);
-	status = ciab.pra;
-	control = info ? info->MCR : status;
-	local_irq_restore(flags);
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if(!(control & SER_RTS))
-		strcat(stat_buf, "|RTS");
-	if(!(status & SER_CTS))
-		strcat(stat_buf, "|CTS");
-	if(!(control & SER_DTR))
-		strcat(stat_buf, "|DTR");
-	if(!(status & SER_DSR))
-		strcat(stat_buf, "|DSR");
-	if(!(status & SER_DCD))
-		strcat(stat_buf, "|CD");
-
-	if (info->quot) {
-		seq_printf(m, " baud:%d", state->baud_base / info->quot);
-	}
-
-	seq_printf(m, " tx:%d rx:%d", state->icount.tx, state->icount.rx);
-
-	if (state->icount.frame)
-		seq_printf(m, " fe:%d", state->icount.frame);
-
-	if (state->icount.parity)
-		seq_printf(m, " pe:%d", state->icount.parity);
-
-	if (state->icount.brk)
-		seq_printf(m, " brk:%d", state->icount.brk);
-
-	if (state->icount.overrun)
-		seq_printf(m, " oe:%d", state->icount.overrun);
-
-	/*
-	 * Last thing is the RS-232 status lines
-	 */
-	seq_printf(m, " %s\n", stat_buf+1);
-}
-
-static int rs_proc_show(struct seq_file *m, void *v)
-{
-	seq_printf(m, "serinfo:1.0 driver:%s\n", serial_version);
-	line_info(m, &rs_table[0]);
-	return 0;
-}
-
-static int rs_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, rs_proc_show, NULL);
-}
-
-static const struct file_operations rs_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= rs_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * ---------------------------------------------------------------------
- * rs_init() and friends
- *
- * rs_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static void show_serial_version(void)
-{
- 	printk(KERN_INFO "%s version %s\n", serial_name, serial_version);
-}
-
-
-static const struct tty_operations serial_ops = {
-	.open = rs_open,
-	.close = rs_close,
-	.write = rs_write,
-	.put_char = rs_put_char,
-	.flush_chars = rs_flush_chars,
-	.write_room = rs_write_room,
-	.chars_in_buffer = rs_chars_in_buffer,
-	.flush_buffer = rs_flush_buffer,
-	.ioctl = rs_ioctl,
-	.throttle = rs_throttle,
-	.unthrottle = rs_unthrottle,
-	.set_termios = rs_set_termios,
-	.stop = rs_stop,
-	.start = rs_start,
-	.hangup = rs_hangup,
-	.break_ctl = rs_break,
-	.send_xchar = rs_send_xchar,
-	.wait_until_sent = rs_wait_until_sent,
-	.tiocmget = rs_tiocmget,
-	.tiocmset = rs_tiocmset,
-	.get_icount = rs_get_icount,
-	.proc_fops = &rs_proc_fops,
-};
-
-/*
- * The serial driver boot-time initialization code!
- */
-static int __init amiga_serial_probe(struct platform_device *pdev)
-{
-	unsigned long flags;
-	struct serial_state * state;
-	int error;
-
-	serial_driver = alloc_tty_driver(1);
-	if (!serial_driver)
-		return -ENOMEM;
-
-	IRQ_ports = NULL;
-
-	show_serial_version();
-
-	/* Initialize the tty_driver structure */
-
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = "amiserial";
-	serial_driver->name = "ttyS";
-	serial_driver->major = TTY_MAJOR;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(serial_driver, &serial_ops);
-
-	error = tty_register_driver(serial_driver);
-	if (error)
-		goto fail_put_tty_driver;
-
-	state = rs_table;
-	state->magic = SSTATE_MAGIC;
-	state->port = (int)&custom.serdatr; /* Just to give it a value */
-	state->line = 0;
-	state->custom_divisor = 0;
-	state->close_delay = 5*HZ/10;
-	state->closing_wait = 30*HZ;
-	state->icount.cts = state->icount.dsr = 
-	  state->icount.rng = state->icount.dcd = 0;
-	state->icount.rx = state->icount.tx = 0;
-	state->icount.frame = state->icount.parity = 0;
-	state->icount.overrun = state->icount.brk = 0;
-
-	printk(KERN_INFO "ttyS%d is the amiga builtin serial port\n",
-		       state->line);
-
-	/* Hardware set up */
-
-	state->baud_base = amiga_colorclock;
-	state->xmit_fifo_size = 1;
-
-	/* set ISRs, and then disable the rx interrupts */
-	error = request_irq(IRQ_AMIGA_TBE, ser_tx_int, 0, "serial TX", state);
-	if (error)
-		goto fail_unregister;
-
-	error = request_irq(IRQ_AMIGA_RBF, ser_rx_int, IRQF_DISABLED,
-			    "serial RX", state);
-	if (error)
-		goto fail_free_irq;
-
-	local_irq_save(flags);
-
-	/* turn off Rx and Tx interrupts */
-	custom.intena = IF_RBF | IF_TBE;
-	mb();
-
-	/* clear any pending interrupt */
-	custom.intreq = IF_RBF | IF_TBE;
-	mb();
-
-	local_irq_restore(flags);
-
-	/*
-	 * set the appropriate directions for the modem control flags,
-	 * and clear RTS and DTR
-	 */
-	ciab.ddra |= (SER_DTR | SER_RTS);   /* outputs */
-	ciab.ddra &= ~(SER_DCD | SER_CTS | SER_DSR);  /* inputs */
-
-	platform_set_drvdata(pdev, state);
-
-	return 0;
-
-fail_free_irq:
-	free_irq(IRQ_AMIGA_TBE, state);
-fail_unregister:
-	tty_unregister_driver(serial_driver);
-fail_put_tty_driver:
-	put_tty_driver(serial_driver);
-	return error;
-}
-
-static int __exit amiga_serial_remove(struct platform_device *pdev)
-{
-	int error;
-	struct serial_state *state = platform_get_drvdata(pdev);
-	struct async_struct *info = state->info;
-
-	/* printk("Unloading %s: version %s\n", serial_name, serial_version); */
-	tasklet_kill(&info->tlet);
-	if ((error = tty_unregister_driver(serial_driver)))
-		printk("SERIAL: failed to unregister serial driver (%d)\n",
-		       error);
-	put_tty_driver(serial_driver);
-
-	rs_table[0].info = NULL;
-	kfree(info);
-
-	free_irq(IRQ_AMIGA_TBE, rs_table);
-	free_irq(IRQ_AMIGA_RBF, rs_table);
-
-	platform_set_drvdata(pdev, NULL);
-
-	return error;
-}
-
-static struct platform_driver amiga_serial_driver = {
-	.remove = __exit_p(amiga_serial_remove),
-	.driver   = {
-		.name	= "amiga-serial",
-		.owner	= THIS_MODULE,
-	},
-};
-
-static int __init amiga_serial_init(void)
-{
-	return platform_driver_probe(&amiga_serial_driver, amiga_serial_probe);
-}
-
-module_init(amiga_serial_init);
-
-static void __exit amiga_serial_exit(void)
-{
-	platform_driver_unregister(&amiga_serial_driver);
-}
-
-module_exit(amiga_serial_exit);
-
-
-#if defined(CONFIG_SERIAL_CONSOLE) && !defined(MODULE)
-
-/*
- * ------------------------------------------------------------
- * Serial console driver
- * ------------------------------------------------------------
- */
-
-static void amiga_serial_putc(char c)
-{
-	custom.serdat = (unsigned char)c | 0x100;
-	while (!(custom.serdatr & 0x2000))
-		barrier();
-}
-
-/*
- *	Print a string to the serial port trying not to disturb
- *	any possible real use of the port...
- *
- *	The console must be locked when we get here.
- */
-static void serial_console_write(struct console *co, const char *s,
-				unsigned count)
-{
-	unsigned short intena = custom.intenar;
-
-	custom.intena = IF_TBE;
-
-	while (count--) {
-		if (*s == '\n')
-			amiga_serial_putc('\r');
-		amiga_serial_putc(*s++);
-	}
-
-	custom.intena = IF_SETCLR | (intena & IF_TBE);
-}
-
-static struct tty_driver *serial_console_device(struct console *c, int *index)
-{
-	*index = 0;
-	return serial_driver;
-}
-
-static struct console sercons = {
-	.name =		"ttyS",
-	.write =	serial_console_write,
-	.device =	serial_console_device,
-	.flags =	CON_PRINTBUFFER,
-	.index =	-1,
-};
-
-/*
- *	Register console.
- */
-static int __init amiserial_console_init(void)
-{
-	register_console(&sercons);
-	return 0;
-}
-console_initcall(amiserial_console_init);
-
-#endif /* CONFIG_SERIAL_CONSOLE && !MODULE */
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("platform:amiga-serial");
diff -druN linux-libre-2.6.38-gnu/drivers/char/bfin_jtag_comm.c linux-libre-2.6.39-gnu/drivers/char/bfin_jtag_comm.c
--- linux-libre-2.6.38-gnu/drivers/char/bfin_jtag_comm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/bfin_jtag_comm.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,366 +0,0 @@
-/*
- * 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/slab.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 console_lock()
-# define console_unlock()
-#endif
-static int
-bfin_jc_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	int i;
-	console_lock();
-	i = bfin_jc_circ_write(buf, count);
-	console_unlock();
-	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 const 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.38-gnu/drivers/char/cd1865.h linux-libre-2.6.39-gnu/drivers/char/cd1865.h
--- linux-libre-2.6.38-gnu/drivers/char/cd1865.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/cd1865.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,263 +0,0 @@
-/*
- *      linux/drivers/char/cd1865.h -- Definitions relating to the CD1865
- *                          for the Specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support.
- *
- *      This driver was developped in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- */
-
-/*
- * Definitions for Driving CD180/CD1864/CD1865 based eightport serial cards.
- */
-
-
-/* Values of choice for Interrupt ACKs */
-/* These values are "obligatory" if you use the register based
- * interrupt acknowledgements. See page 99-101 of V2.0 of the CD1865
- * databook */
-#define SX_ACK_MINT     0x75    /* goes to PILR1                           */
-#define SX_ACK_TINT     0x76    /* goes to PILR2                           */
-#define SX_ACK_RINT     0x77    /* goes to PILR3                           */
-
-/* Chip ID (is used when chips ar daisy chained.) */
-#define SX_ID           0x10
-
-/* Definitions for Cirrus Logic CL-CD186x 8-port async mux chip */
- 
-#define CD186x_NCH       8       /* Total number of channels                */
-#define CD186x_TPC       16      /* Ticks per character                     */
-#define CD186x_NFIFO	 8	 /* TX FIFO size                            */
-
-
-/* Global registers */
-
-#define CD186x_GIVR      0x40    /* Global Interrupt Vector Register        */
-#define CD186x_GICR      0x41    /* Global Interrupting Channel Register    */
-#define CD186x_PILR1     0x61    /* Priority Interrupt Level Register 1     */
-#define CD186x_PILR2     0x62    /* Priority Interrupt Level Register 2     */
-#define CD186x_PILR3     0x63    /* Priority Interrupt Level Register 3     */
-#define CD186x_CAR       0x64    /* Channel Access Register                 */
-#define CD186x_SRSR      0x65    /* Channel Access Register                 */
-#define CD186x_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
-#define CD186x_PPRH      0x70    /* Prescaler Period Register High          */
-#define CD186x_PPRL      0x71    /* Prescaler Period Register Low           */
-#define CD186x_RDR       0x78    /* Receiver Data Register                  */
-#define CD186x_RCSR      0x7a    /* Receiver Character Status Register      */
-#define CD186x_TDR       0x7b    /* Transmit Data Register                  */
-#define CD186x_EOIR      0x7f    /* End of Interrupt Register               */
-#define CD186x_MRAR      0x75    /* Modem Request Acknowledge register       */
-#define CD186x_TRAR      0x76    /* Transmit Request Acknowledge register    */
-#define CD186x_RRAR      0x77    /* Receive Request Acknowledge register     */
-#define CD186x_SRCR      0x66    /* Service Request Configuration register  */
-
-/* Channel Registers */
-
-#define CD186x_CCR       0x01    /* Channel Command Register                */
-#define CD186x_IER       0x02    /* Interrupt Enable Register               */
-#define CD186x_COR1      0x03    /* Channel Option Register 1               */
-#define CD186x_COR2      0x04    /* Channel Option Register 2               */
-#define CD186x_COR3      0x05    /* Channel Option Register 3               */
-#define CD186x_CCSR      0x06    /* Channel Control Status Register         */
-#define CD186x_RDCR      0x07    /* Receive Data Count Register             */
-#define CD186x_SCHR1     0x09    /* Special Character Register 1            */
-#define CD186x_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD186x_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD186x_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD186x_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD186x_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD186x_MCR       0x12    /* Modem Change Register                   */
-#define CD186x_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD186x_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD186x_MSVRTS    0x29    /* Modem Signal Value Register             */
-#define CD186x_MSVDTR    0x2a    /* Modem Signal Value Register             */
-#define CD186x_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
-#define CD186x_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
-#define CD186x_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
-#define CD186x_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
-
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
-#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
-#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
- 
-#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GICR_CHAN_OFF   2       /* Channel Number shift                    */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Interrupt Enable Register (R/W) */
-
-#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define IER_CD          0x40    /* Enable interrupt on CD change           */
-#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Escape characters */
-
-#define CD186x_C_ESC     0x00    /* Escape character                        */
-#define CD186x_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD186x_C_DELAY   0x82    /* Delay output                            */
-#define CD186x_C_EBRK    0x83    /* Stop sending BREAK                      */
-
-#define SRSR_RREQint     0x10    /* This chip wants "rec" serviced          */
-#define SRSR_TREQint     0x04    /* This chip wants "transmit" serviced     */
-#define SRSR_MREQint     0x01    /* This chip wants "mdm change" serviced   */
-
-
-
-#define SRCR_PKGTYPE    0x80
-#define SRCR_REGACKEN   0x40
-#define SRCR_DAISYEN    0x20
-#define SRCR_GLOBPRI    0x10
-#define SRCR_UNFAIR     0x08
-#define SRCR_AUTOPRI    0x02
-#define SRCR_PRISEL     0x01
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/cyclades.c linux-libre-2.6.39-gnu/drivers/char/cyclades.c
--- linux-libre-2.6.38-gnu/drivers/char/cyclades.c	2012-03-24 00:59:59.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/cyclades.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4200 +0,0 @@
-#undef	BLOCKMOVE
-#define	Z_WAKE
-#undef	Z_EXT_CHARS_IN_BUFFER
-
-/*
- *  linux/drivers/char/cyclades.c
- *
- * This file contains the driver for the Cyclades async multiport
- * serial boards.
- *
- * Initially written by Randolph Bentson <bentson@grieg.seaslug.org>.
- * Modified and maintained by Marcio Saito <marcio@cyclades.com>.
- *
- * Copyright (C) 2007-2009 Jiri Slaby <jirislaby@gmail.com>
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- * Converted to pci probing and cleaned up by Jiri Slaby.
- *
- */
-
-#define CY_VERSION	"2.6"
-
-/* If you need to install more boards than NR_CARDS, change the constant
-   in the definition below. No other change is necessary to support up to
-   eight boards. Beyond that you'll have to extend cy_isa_addresses. */
-
-#define NR_CARDS	4
-
-/*
-   If the total number of ports is larger than NR_PORTS, change this
-   constant in the definition below. No other change is necessary to
-   support more boards/ports. */
-
-#define NR_PORTS	256
-
-#define ZO_V1	0
-#define ZO_V2	1
-#define ZE_V1	2
-
-#define	SERIAL_PARANOIA_CHECK
-#undef	CY_DEBUG_OPEN
-#undef	CY_DEBUG_THROTTLE
-#undef	CY_DEBUG_OTHER
-#undef	CY_DEBUG_IO
-#undef	CY_DEBUG_COUNT
-#undef	CY_DEBUG_DTR
-#undef	CY_DEBUG_WAIT_UNTIL_SENT
-#undef	CY_DEBUG_INTERRUPTS
-#undef	CY_16Y_HACK
-#undef	CY_ENABLE_MONITORING
-#undef	CY_PCI_DEBUG
-
-/*
- * Include section
- */
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/cyclades.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/spinlock.h>
-#include <linux/bitops.h>
-#include <linux/firmware.h>
-#include <linux/device.h>
-#include <linux/slab.h>
-
-#include <linux/io.h>
-#include <linux/uaccess.h>
-
-#include <linux/kernel.h>
-#include <linux/pci.h>
-
-#include <linux/stat.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static void cy_send_xchar(struct tty_struct *tty, char ch);
-
-#ifndef SERIAL_XMIT_SIZE
-#define	SERIAL_XMIT_SIZE	(min(PAGE_SIZE, 4096))
-#endif
-
-#define STD_COM_FLAGS (0)
-
-/* firmware stuff */
-#define ZL_MAX_BLOCKS	16
-#define DRIVER_VERSION	0x02010203
-#define RAM_SIZE 0x80000
-
-enum zblock_type {
-	ZBLOCK_PRG = 0,
-	ZBLOCK_FPGA = 1
-};
-
-struct zfile_header {
-	char name[64];
-	char date[32];
-	char aux[32];
-	u32 n_config;
-	u32 config_offset;
-	u32 n_blocks;
-	u32 block_offset;
-	u32 reserved[9];
-} __attribute__ ((packed));
-
-struct zfile_config {
-	char name[64];
-	u32 mailbox;
-	u32 function;
-	u32 n_blocks;
-	u32 block_list[ZL_MAX_BLOCKS];
-} __attribute__ ((packed));
-
-struct zfile_block {
-	u32 type;
-	u32 file_offset;
-	u32 ram_offset;
-	u32 size;
-} __attribute__ ((packed));
-
-static struct tty_driver *cy_serial_driver;
-
-#ifdef CONFIG_ISA
-/* This is the address lookup table. The driver will probe for
-   Cyclom-Y/ISA boards at all addresses in here. If you want the
-   driver to probe addresses at a different address, add it to
-   this table.  If the driver is probing some other board and
-   causing problems, remove the offending address from this table.
-*/
-
-static unsigned int cy_isa_addresses[] = {
-	0xD0000,
-	0xD2000,
-	0xD4000,
-	0xD6000,
-	0xD8000,
-	0xDA000,
-	0xDC000,
-	0xDE000,
-	0, 0, 0, 0, 0, 0, 0, 0
-};
-
-#define NR_ISA_ADDRS ARRAY_SIZE(cy_isa_addresses)
-
-static long maddr[NR_CARDS];
-static int irq[NR_CARDS];
-
-module_param_array(maddr, long, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-
-#endif				/* CONFIG_ISA */
-
-/* This is the per-card data structure containing address, irq, number of
-   channels, etc. This driver supports a maximum of NR_CARDS cards.
-*/
-static struct cyclades_card cy_card[NR_CARDS];
-
-static int cy_next_channel;	/* next minor available */
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates.  The extra
- * are accessed via settings in info->port.flags.
- *      0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
- *     10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
- *                                               HI            VHI
- *     20
- */
-static const int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
-	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
-	230400, 0
-};
-
-static const char baud_co_25[] = {	/* 25 MHz clock option table */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
-	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static const char baud_bpr_25[] = {	/* 25 MHz baud rate period table */
-	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
-	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-
-static const char baud_co_60[] = {	/* 60 MHz clock option table (CD1400 J) */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x00, 0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03,
-	0x03, 0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00
-};
-
-static const char baud_bpr_60[] = {	/* 60 MHz baud rate period table (CD1400 J) */
-	0x00, 0x82, 0x21, 0xff, 0xdb, 0xc3, 0x92, 0x62, 0xc3, 0x62,
-	0x41, 0xc3, 0x62, 0xc3, 0x62, 0xc3, 0x82, 0x62, 0x41, 0x32,
-	0x21
-};
-
-static const char baud_cor3[] = {	/* receive threshold */
-	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07,
-	0x07
-};
-
-/*
- * The Cyclades driver implements HW flow control as any serial driver.
- * The cyclades_port structure member rflow and the vector rflow_thr
- * allows us to take advantage of a special feature in the CD1400 to avoid
- * data loss even when the system interrupt latency is too high. These flags
- * are to be used only with very special applications. Setting these flags
- * requires the use of a special cable (DTR and RTS reversed). In the new
- * CD1400-based boards (rev. 6.00 or later), there is no need for special
- * cables.
- */
-
-static const char rflow_thr[] = {	/* rflow threshold */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a
-};
-
-/*  The Cyclom-Ye has placed the sequential chips in non-sequential
- *  address order.  This look-up table overcomes that problem.
- */
-static const unsigned int cy_chip_offset[] = { 0x0000,
-	0x0400,
-	0x0800,
-	0x0C00,
-	0x0200,
-	0x0600,
-	0x0A00,
-	0x0E00
-};
-
-/* PCI related definitions */
-
-#ifdef CONFIG_PCI
-static const struct pci_device_id cy_pci_dev_id[] = {
-	/* PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Lo) },
-	/* PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Y_Hi) },
-	/* 4Y PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Lo) },
-	/* 4Y PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_4Y_Hi) },
-	/* 8Y PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Lo) },
-	/* 8Y PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_8Y_Hi) },
-	/* Z PCI < 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Lo) },
-	/* Z PCI > 1Mb */
-	{ PCI_DEVICE(PCI_VENDOR_ID_CYCLADES, PCI_DEVICE_ID_CYCLOM_Z_Hi) },
-	{ }			/* end of table */
-};
-MODULE_DEVICE_TABLE(pci, cy_pci_dev_id);
-#endif
-
-static void cy_start(struct tty_struct *);
-static void cy_set_line_char(struct cyclades_port *, struct tty_struct *);
-static int cyz_issue_cmd(struct cyclades_card *, __u32, __u8, __u32);
-#ifdef CONFIG_ISA
-static unsigned detect_isa_irq(void __iomem *);
-#endif				/* CONFIG_ISA */
-
-#ifndef CONFIG_CYZ_INTR
-static void cyz_poll(unsigned long);
-
-/* The Cyclades-Z polling cycle is defined by this variable */
-static long cyz_polling_cycle = CZ_DEF_POLL;
-
-static DEFINE_TIMER(cyz_timerlist, cyz_poll, 0, 0);
-
-#else				/* CONFIG_CYZ_INTR */
-static void cyz_rx_restart(unsigned long);
-static struct timer_list cyz_rx_full_timer[NR_PORTS];
-#endif				/* CONFIG_CYZ_INTR */
-
-static inline void cyy_writeb(struct cyclades_port *port, u32 reg, u8 val)
-{
-	struct cyclades_card *card = port->card;
-
-	cy_writeb(port->u.cyy.base_addr + (reg << card->bus_index), val);
-}
-
-static inline u8 cyy_readb(struct cyclades_port *port, u32 reg)
-{
-	struct cyclades_card *card = port->card;
-
-	return readb(port->u.cyy.base_addr + (reg << card->bus_index));
-}
-
-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,
-		const char *name, const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	if (!info) {
-		printk(KERN_WARNING "cyc Warning: null cyclades_port for (%s) "
-				"in %s\n", name, routine);
-		return 1;
-	}
-
-	if (info->magic != CYCLADES_MAGIC) {
-		printk(KERN_WARNING "cyc Warning: bad magic number for serial "
-				"struct (%s) in %s\n", name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/***********************************************************/
-/********* Start of block of Cyclom-Y specific code ********/
-
-/* This routine waits up to 1000 micro-seconds for the previous
-   command to the Cirrus chip to complete and then issues the
-   new command.  An error is returned if the previous command
-   didn't finish within the time limit.
-
-   This function is only called from inside spinlock-protected code.
- */
-static int __cyy_issue_cmd(void __iomem *base_addr, u8 cmd, int index)
-{
-	void __iomem *ccr = base_addr + (CyCCR << index);
-	unsigned int i;
-
-	/* Check to see that the previous command has completed */
-	for (i = 0; i < 100; i++) {
-		if (readb(ccr) == 0)
-			break;
-		udelay(10L);
-	}
-	/* if the CCR never cleared, the previous command
-	   didn't finish within the "reasonable time" */
-	if (i == 100)
-		return -1;
-
-	/* Issue the new command */
-	cy_writeb(ccr, cmd);
-
-	return 0;
-}
-
-static inline int cyy_issue_cmd(struct cyclades_port *port, u8 cmd)
-{
-	return __cyy_issue_cmd(port->u.cyy.base_addr, cmd,
-			port->card->bus_index);
-}
-
-#ifdef CONFIG_ISA
-/* ISA interrupt detection code */
-static unsigned detect_isa_irq(void __iomem *address)
-{
-	int irq;
-	unsigned long irqs, flags;
-	int save_xir, save_car;
-	int index = 0;		/* IRQ probing is only for ISA */
-
-	/* forget possible initially masked and pending IRQ */
-	irq = probe_irq_off(probe_irq_on());
-
-	/* Clear interrupts on the board first */
-	cy_writeb(address + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-
-	irqs = probe_irq_on();
-	/* Wait ... */
-	msleep(5);
-
-	/* Enable the Tx interrupts on the CD1400 */
-	local_irq_save(flags);
-	cy_writeb(address + (CyCAR << index), 0);
-	__cyy_issue_cmd(address, CyCHAN_CTL | CyENB_XMTR, index);
-
-	cy_writeb(address + (CyCAR << index), 0);
-	cy_writeb(address + (CySRER << index),
-		  readb(address + (CySRER << index)) | CyTxRdy);
-	local_irq_restore(flags);
-
-	/* Wait ... */
-	msleep(5);
-
-	/* Check which interrupt is in use */
-	irq = probe_irq_off(irqs);
-
-	/* Clean up */
-	save_xir = (u_char) readb(address + (CyTIR << index));
-	save_car = readb(address + (CyCAR << index));
-	cy_writeb(address + (CyCAR << index), (save_xir & 0x3));
-	cy_writeb(address + (CySRER << index),
-		  readb(address + (CySRER << index)) & ~CyTxRdy);
-	cy_writeb(address + (CyTIR << index), (save_xir & 0x3f));
-	cy_writeb(address + (CyCAR << index), (save_car));
-	cy_writeb(address + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-
-	return (irq > 0) ? irq : 0;
-}
-#endif				/* CONFIG_ISA */
-
-static void cyy_chip_rx(struct cyclades_card *cinfo, int chip,
-		void __iomem *base_addr)
-{
-	struct cyclades_port *info;
-	struct tty_struct *tty;
-	int len, index = cinfo->bus_index;
-	u8 ivr, save_xir, channel, save_car, data, char_count;
-
-#ifdef CY_DEBUG_INTERRUPTS
-	printk(KERN_DEBUG "cyy_interrupt: rcvd intr, chip %d\n", chip);
-#endif
-	/* determine the channel & change to that context */
-	save_xir = readb(base_addr + (CyRIR << index));
-	channel = save_xir & CyIRChannel;
-	info = &cinfo->ports[channel + chip * 4];
-	save_car = cyy_readb(info, CyCAR);
-	cyy_writeb(info, CyCAR, save_xir);
-	ivr = cyy_readb(info, CyRIVR) & CyIVRMask;
-
-	tty = tty_port_tty_get(&info->port);
-	/* if there is nowhere to put the data, discard it */
-	if (tty == NULL) {
-		if (ivr == CyIVRRxEx) {	/* exception */
-			data = cyy_readb(info, CyRDSR);
-		} else {	/* normal character reception */
-			char_count = cyy_readb(info, CyRDCR);
-			while (char_count--)
-				data = cyy_readb(info, CyRDSR);
-		}
-		goto end;
-	}
-	/* there is an open port for this data */
-	if (ivr == CyIVRRxEx) {	/* exception */
-		data = cyy_readb(info, CyRDSR);
-
-		/* For statistics only */
-		if (data & CyBREAK)
-			info->icount.brk++;
-		else if (data & CyFRAME)
-			info->icount.frame++;
-		else if (data & CyPARITY)
-			info->icount.parity++;
-		else if (data & CyOVERRUN)
-			info->icount.overrun++;
-
-		if (data & info->ignore_status_mask) {
-			info->icount.rx++;
-			tty_kref_put(tty);
-			return;
-		}
-		if (tty_buffer_request_room(tty, 1)) {
-			if (data & info->read_status_mask) {
-				if (data & CyBREAK) {
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_BREAK);
-					info->icount.rx++;
-					if (info->port.flags & ASYNC_SAK)
-						do_SAK(tty);
-				} else if (data & CyFRAME) {
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_FRAME);
-					info->icount.rx++;
-					info->idle_stats.frame_errs++;
-				} else if (data & CyPARITY) {
-					/* Pieces of seven... */
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_PARITY);
-					info->icount.rx++;
-					info->idle_stats.parity_errs++;
-				} else if (data & CyOVERRUN) {
-					tty_insert_flip_char(tty, 0,
-							TTY_OVERRUN);
-					info->icount.rx++;
-					/* If the flip buffer itself is
-					   overflowing, we still lose
-					   the next incoming character.
-					 */
-					tty_insert_flip_char(tty,
-						cyy_readb(info, CyRDSR),
-						TTY_FRAME);
-					info->icount.rx++;
-					info->idle_stats.overruns++;
-				/* These two conditions may imply */
-				/* a normal read should be done. */
-				/* } else if(data & CyTIMEOUT) { */
-				/* } else if(data & CySPECHAR) { */
-				} else {
-					tty_insert_flip_char(tty, 0,
-							TTY_NORMAL);
-					info->icount.rx++;
-				}
-			} else {
-				tty_insert_flip_char(tty, 0, TTY_NORMAL);
-				info->icount.rx++;
-			}
-		} else {
-			/* there was a software buffer overrun and nothing
-			 * could be done about it!!! */
-			info->icount.buf_overrun++;
-			info->idle_stats.overruns++;
-		}
-	} else {	/* normal character reception */
-		/* load # chars available from the chip */
-		char_count = cyy_readb(info, CyRDCR);
-
-#ifdef CY_ENABLE_MONITORING
-		++info->mon.int_count;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		len = tty_buffer_request_room(tty, char_count);
-		while (len--) {
-			data = cyy_readb(info, CyRDSR);
-			tty_insert_flip_char(tty, data, TTY_NORMAL);
-			info->idle_stats.recv_bytes++;
-			info->icount.rx++;
-#ifdef CY_16Y_HACK
-			udelay(10L);
-#endif
-		}
-		info->idle_stats.recv_idle = jiffies;
-	}
-	tty_schedule_flip(tty);
-	tty_kref_put(tty);
-end:
-	/* end of service */
-	cyy_writeb(info, CyRIR, save_xir & 0x3f);
-	cyy_writeb(info, CyCAR, save_car);
-}
-
-static void cyy_chip_tx(struct cyclades_card *cinfo, unsigned int chip,
-		void __iomem *base_addr)
-{
-	struct cyclades_port *info;
-	struct tty_struct *tty;
-	int char_count, index = cinfo->bus_index;
-	u8 save_xir, channel, save_car, outch;
-
-	/* Since we only get here when the transmit buffer
-	   is empty, we know we can always stuff a dozen
-	   characters. */
-#ifdef CY_DEBUG_INTERRUPTS
-	printk(KERN_DEBUG "cyy_interrupt: xmit intr, chip %d\n", chip);
-#endif
-
-	/* determine the channel & change to that context */
-	save_xir = readb(base_addr + (CyTIR << index));
-	channel = save_xir & CyIRChannel;
-	save_car = readb(base_addr + (CyCAR << index));
-	cy_writeb(base_addr + (CyCAR << index), save_xir);
-
-	info = &cinfo->ports[channel + chip * 4];
-	tty = tty_port_tty_get(&info->port);
-	if (tty == NULL) {
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
-		goto end;
-	}
-
-	/* load the on-chip space for outbound data */
-	char_count = info->xmit_fifo_size;
-
-	if (info->x_char) {	/* send special char */
-		outch = info->x_char;
-		cyy_writeb(info, CyTDR, outch);
-		char_count--;
-		info->icount.tx++;
-		info->x_char = 0;
-	}
-
-	if (info->breakon || info->breakoff) {
-		if (info->breakon) {
-			cyy_writeb(info, CyTDR, 0);
-			cyy_writeb(info, CyTDR, 0x81);
-			info->breakon = 0;
-			char_count -= 2;
-		}
-		if (info->breakoff) {
-			cyy_writeb(info, CyTDR, 0);
-			cyy_writeb(info, CyTDR, 0x83);
-			info->breakoff = 0;
-			char_count -= 2;
-		}
-	}
-
-	while (char_count-- > 0) {
-		if (!info->xmit_cnt) {
-			if (cyy_readb(info, CySRER) & CyTxMpty) {
-				cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) & ~CyTxMpty);
-			} else {
-				cyy_writeb(info, CySRER, CyTxMpty |
-					(cyy_readb(info, CySRER) & ~CyTxRdy));
-			}
-			goto done;
-		}
-		if (info->port.xmit_buf == NULL) {
-			cyy_writeb(info, CySRER,
-				cyy_readb(info, CySRER) & ~CyTxRdy);
-			goto done;
-		}
-		if (tty->stopped || tty->hw_stopped) {
-			cyy_writeb(info, CySRER,
-				cyy_readb(info, CySRER) & ~CyTxRdy);
-			goto done;
-		}
-		/* Because the Embedded Transmit Commands have been enabled,
-		 * we must check to see if the escape character, NULL, is being
-		 * sent. If it is, we must ensure that there is room for it to
-		 * be doubled in the output stream.  Therefore we no longer
-		 * advance the pointer when the character is fetched, but
-		 * rather wait until after the check for a NULL output
-		 * character. This is necessary because there may not be room
-		 * for the two chars needed to send a NULL.)
-		 */
-		outch = info->port.xmit_buf[info->xmit_tail];
-		if (outch) {
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1) &
-					(SERIAL_XMIT_SIZE - 1);
-			cyy_writeb(info, CyTDR, outch);
-			info->icount.tx++;
-		} else {
-			if (char_count > 1) {
-				info->xmit_cnt--;
-				info->xmit_tail = (info->xmit_tail + 1) &
-					(SERIAL_XMIT_SIZE - 1);
-				cyy_writeb(info, CyTDR, outch);
-				cyy_writeb(info, CyTDR, 0);
-				info->icount.tx++;
-				char_count--;
-			}
-		}
-	}
-
-done:
-	tty_wakeup(tty);
-	tty_kref_put(tty);
-end:
-	/* end of service */
-	cyy_writeb(info, CyTIR, save_xir & 0x3f);
-	cyy_writeb(info, CyCAR, save_car);
-}
-
-static void cyy_chip_modem(struct cyclades_card *cinfo, int chip,
-		void __iomem *base_addr)
-{
-	struct cyclades_port *info;
-	struct tty_struct *tty;
-	int index = cinfo->bus_index;
-	u8 save_xir, channel, save_car, mdm_change, mdm_status;
-
-	/* determine the channel & change to that context */
-	save_xir = readb(base_addr + (CyMIR << index));
-	channel = save_xir & CyIRChannel;
-	info = &cinfo->ports[channel + chip * 4];
-	save_car = cyy_readb(info, CyCAR);
-	cyy_writeb(info, CyCAR, save_xir);
-
-	mdm_change = cyy_readb(info, CyMISR);
-	mdm_status = cyy_readb(info, CyMSVR1);
-
-	tty = tty_port_tty_get(&info->port);
-	if (!tty)
-		goto end;
-
-	if (mdm_change & CyANY_DELTA) {
-		/* For statistics only */
-		if (mdm_change & CyDCD)
-			info->icount.dcd++;
-		if (mdm_change & CyCTS)
-			info->icount.cts++;
-		if (mdm_change & CyDSR)
-			info->icount.dsr++;
-		if (mdm_change & CyRI)
-			info->icount.rng++;
-
-		wake_up_interruptible(&info->port.delta_msr_wait);
-	}
-
-	if ((mdm_change & CyDCD) && (info->port.flags & ASYNC_CHECK_CD)) {
-		if (mdm_status & CyDCD)
-			wake_up_interruptible(&info->port.open_wait);
-		else
-			tty_hangup(tty);
-	}
-	if ((mdm_change & CyCTS) && (info->port.flags & ASYNC_CTS_FLOW)) {
-		if (tty->hw_stopped) {
-			if (mdm_status & CyCTS) {
-				/* cy_start isn't used
-				   because... !!! */
-				tty->hw_stopped = 0;
-				cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) | CyTxRdy);
-				tty_wakeup(tty);
-			}
-		} else {
-			if (!(mdm_status & CyCTS)) {
-				/* cy_stop isn't used
-				   because ... !!! */
-				tty->hw_stopped = 1;
-				cyy_writeb(info, CySRER,
-					cyy_readb(info, CySRER) & ~CyTxRdy);
-			}
-		}
-	}
-/*	if (mdm_change & CyDSR) {
-	}
-	if (mdm_change & CyRI) {
-	}*/
-	tty_kref_put(tty);
-end:
-	/* end of service */
-	cyy_writeb(info, CyMIR, save_xir & 0x3f);
-	cyy_writeb(info, CyCAR, save_car);
-}
-
-/* The real interrupt service routine is called
-   whenever the card wants its hand held--chars
-   received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cyy_interrupt(int irq, void *dev_id)
-{
-	int status;
-	struct cyclades_card *cinfo = dev_id;
-	void __iomem *base_addr, *card_base_addr;
-	unsigned int chip, too_many, had_work;
-	int index;
-
-	if (unlikely(cinfo == NULL)) {
-#ifdef CY_DEBUG_INTERRUPTS
-		printk(KERN_DEBUG "cyy_interrupt: spurious interrupt %d\n",
-				irq);
-#endif
-		return IRQ_NONE;	/* spurious interrupt */
-	}
-
-	card_base_addr = cinfo->base_addr;
-	index = cinfo->bus_index;
-
-	/* card was not initialized yet (e.g. DEBUG_SHIRQ) */
-	if (unlikely(card_base_addr == NULL))
-		return IRQ_HANDLED;
-
-	/* This loop checks all chips in the card.  Make a note whenever
-	   _any_ chip had some work to do, as this is considered an
-	   indication that there will be more to do.  Only when no chip
-	   has any work does this outermost loop exit.
-	 */
-	do {
-		had_work = 0;
-		for (chip = 0; chip < cinfo->num_chips; chip++) {
-			base_addr = cinfo->base_addr +
-					(cy_chip_offset[chip] << index);
-			too_many = 0;
-			while ((status = readb(base_addr +
-						(CySVRR << index))) != 0x00) {
-				had_work++;
-			/* The purpose of the following test is to ensure that
-			   no chip can monopolize the driver.  This forces the
-			   chips to be checked in a round-robin fashion (after
-			   draining each of a bunch (1000) of characters).
-			 */
-				if (1000 < too_many++)
-					break;
-				spin_lock(&cinfo->card_lock);
-				if (status & CySRReceive) /* rx intr */
-					cyy_chip_rx(cinfo, chip, base_addr);
-				if (status & CySRTransmit) /* tx intr */
-					cyy_chip_tx(cinfo, chip, base_addr);
-				if (status & CySRModem) /* modem intr */
-					cyy_chip_modem(cinfo, chip, base_addr);
-				spin_unlock(&cinfo->card_lock);
-			}
-		}
-	} while (had_work);
-
-	/* clear interrupts */
-	spin_lock(&cinfo->card_lock);
-	cy_writeb(card_base_addr + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-	spin_unlock(&cinfo->card_lock);
-	return IRQ_HANDLED;
-}				/* cyy_interrupt */
-
-static void cyy_change_rts_dtr(struct cyclades_port *info, unsigned int set,
-		unsigned int clear)
-{
-	struct cyclades_card *card = info->card;
-	int channel = info->line - card->first_line;
-	u32 rts, dtr, msvrr, msvrd;
-
-	channel &= 0x03;
-
-	if (info->rtsdtr_inv) {
-		msvrr = CyMSVR2;
-		msvrd = CyMSVR1;
-		rts = CyDTR;
-		dtr = CyRTS;
-	} else {
-		msvrr = CyMSVR1;
-		msvrd = CyMSVR2;
-		rts = CyRTS;
-		dtr = CyDTR;
-	}
-	if (set & TIOCM_RTS) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrr, rts);
-	}
-	if (clear & TIOCM_RTS) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrr, ~rts);
-	}
-	if (set & TIOCM_DTR) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrd, dtr);
-#ifdef CY_DEBUG_DTR
-		printk(KERN_DEBUG "cyc:set_modem_info raising DTR\n");
-		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			cyy_readb(info, CyMSVR1),
-			cyy_readb(info, CyMSVR2));
-#endif
-	}
-	if (clear & TIOCM_DTR) {
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, msvrd, ~dtr);
-#ifdef CY_DEBUG_DTR
-		printk(KERN_DEBUG "cyc:set_modem_info dropping DTR\n");
-		printk(KERN_DEBUG "     status: 0x%x, 0x%x\n",
-			cyy_readb(info, CyMSVR1),
-			cyy_readb(info, CyMSVR2));
-#endif
-	}
-}
-
-/***********************************************************/
-/********* End of block of Cyclom-Y specific code **********/
-/******** Start of block of Cyclades-Z specific code *******/
-/***********************************************************/
-
-static int
-cyz_fetch_msg(struct cyclades_card *cinfo,
-		__u32 *channel, __u8 *cmd, __u32 *param)
-{
-	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
-	unsigned long 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(&cinfo->ctl_addr.p9060->loc_doorbell, 0xffffffff);
-		return 1;
-	}
-	return 0;
-}				/* cyz_fetch_msg */
-
-static int
-cyz_issue_cmd(struct cyclades_card *cinfo,
-		__u32 channel, __u8 cmd, __u32 param)
-{
-	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
-	__u32 __iomem *pci_doorbell;
-	unsigned int index;
-
-	if (!cyz_is_loaded(cinfo))
-		return -1;
-
-	index = 0;
-	pci_doorbell = &cinfo->ctl_addr.p9060->pci_doorbell;
-	while ((readl(pci_doorbell) & 0xff) != 0) {
-		if (index++ == 1000)
-			return (int)(readl(pci_doorbell) & 0xff);
-		udelay(50L);
-	}
-	cy_writel(&board_ctrl->hcmd_channel, channel);
-	cy_writel(&board_ctrl->hcmd_param, param);
-	cy_writel(pci_doorbell, (long)cmd);
-
-	return 0;
-}				/* cyz_issue_cmd */
-
-static void cyz_handle_rx(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
-	struct cyclades_card *cinfo = info->card;
-	unsigned int char_count;
-	int len;
-#ifdef BLOCKMOVE
-	unsigned char *buf;
-#else
-	char data;
-#endif
-	__u32 rx_put, rx_get, new_rx_get, rx_bufsize, rx_bufaddr;
-
-	rx_get = new_rx_get = readl(&buf_ctrl->rx_get);
-	rx_put = readl(&buf_ctrl->rx_put);
-	rx_bufsize = readl(&buf_ctrl->rx_bufsize);
-	rx_bufaddr = readl(&buf_ctrl->rx_bufaddr);
-	if (rx_put >= rx_get)
-		char_count = rx_put - rx_get;
-	else
-		char_count = rx_put - rx_get + rx_bufsize;
-
-	if (char_count) {
-#ifdef CY_ENABLE_MONITORING
-		info->mon.int_count++;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		if (tty == NULL) {
-			/* flush received characters */
-			new_rx_get = (new_rx_get + char_count) &
-					(rx_bufsize - 1);
-			info->rflush_count++;
-		} else {
-#ifdef BLOCKMOVE
-		/* we'd like to use memcpy(t, f, n) and memset(s, c, count)
-		   for performance, but because of buffer boundaries, there
-		   may be several steps to the operation */
-			while (1) {
-				len = tty_prepare_flip_string(tty, &buf,
-						char_count);
-				if (!len)
-					break;
-
-				len = min_t(unsigned int, min(len, char_count),
-						rx_bufsize - new_rx_get);
-
-				memcpy_fromio(buf, cinfo->base_addr +
-						rx_bufaddr + new_rx_get, len);
-
-				new_rx_get = (new_rx_get + len) &
-						(rx_bufsize - 1);
-				char_count -= len;
-				info->icount.rx += len;
-				info->idle_stats.recv_bytes += len;
-			}
-#else
-			len = tty_buffer_request_room(tty, char_count);
-			while (len--) {
-				data = readb(cinfo->base_addr + rx_bufaddr +
-						new_rx_get);
-				new_rx_get = (new_rx_get + 1) &
-							(rx_bufsize - 1);
-				tty_insert_flip_char(tty, data, TTY_NORMAL);
-				info->idle_stats.recv_bytes++;
-				info->icount.rx++;
-			}
-#endif
-#ifdef CONFIG_CYZ_INTR
-		/* Recalculate the number of chars in the RX buffer and issue
-		   a cmd in case it's higher than the RX high water mark */
-			rx_put = readl(&buf_ctrl->rx_put);
-			if (rx_put >= rx_get)
-				char_count = rx_put - rx_get;
-			else
-				char_count = rx_put - rx_get + rx_bufsize;
-			if (char_count >= readl(&buf_ctrl->rx_threshold) &&
-					!timer_pending(&cyz_rx_full_timer[
-							info->line]))
-				mod_timer(&cyz_rx_full_timer[info->line],
-						jiffies + 1);
-#endif
-			info->idle_stats.recv_idle = jiffies;
-			tty_schedule_flip(tty);
-		}
-		/* Update rx_get */
-		cy_writel(&buf_ctrl->rx_get, new_rx_get);
-	}
-}
-
-static void cyz_handle_tx(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
-	struct cyclades_card *cinfo = info->card;
-	u8 data;
-	unsigned int char_count;
-#ifdef BLOCKMOVE
-	int small_count;
-#endif
-	__u32 tx_put, tx_get, tx_bufsize, tx_bufaddr;
-
-	if (info->xmit_cnt <= 0)	/* Nothing to transmit */
-		return;
-
-	tx_get = readl(&buf_ctrl->tx_get);
-	tx_put = readl(&buf_ctrl->tx_put);
-	tx_bufsize = readl(&buf_ctrl->tx_bufsize);
-	tx_bufaddr = readl(&buf_ctrl->tx_bufaddr);
-	if (tx_put >= tx_get)
-		char_count = tx_get - tx_put - 1 + tx_bufsize;
-	else
-		char_count = tx_get - tx_put - 1;
-
-	if (char_count) {
-
-		if (tty == NULL)
-			goto ztxdone;
-
-		if (info->x_char) {	/* send special char */
-			data = info->x_char;
-
-			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
-			tx_put = (tx_put + 1) & (tx_bufsize - 1);
-			info->x_char = 0;
-			char_count--;
-			info->icount.tx++;
-		}
-#ifdef BLOCKMOVE
-		while (0 < (small_count = min_t(unsigned int,
-				tx_bufsize - tx_put, min_t(unsigned int,
-					(SERIAL_XMIT_SIZE - info->xmit_tail),
-					min_t(unsigned int, info->xmit_cnt,
-						char_count))))) {
-
-			memcpy_toio((char *)(cinfo->base_addr + tx_bufaddr +
-					tx_put),
-					&info->port.xmit_buf[info->xmit_tail],
-					small_count);
-
-			tx_put = (tx_put + small_count) & (tx_bufsize - 1);
-			char_count -= small_count;
-			info->icount.tx += small_count;
-			info->xmit_cnt -= small_count;
-			info->xmit_tail = (info->xmit_tail + small_count) &
-					(SERIAL_XMIT_SIZE - 1);
-		}
-#else
-		while (info->xmit_cnt && char_count) {
-			data = info->port.xmit_buf[info->xmit_tail];
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1) &
-					(SERIAL_XMIT_SIZE - 1);
-
-			cy_writeb(cinfo->base_addr + tx_bufaddr + tx_put, data);
-			tx_put = (tx_put + 1) & (tx_bufsize - 1);
-			char_count--;
-			info->icount.tx++;
-		}
-#endif
-		tty_wakeup(tty);
-ztxdone:
-		/* Update tx_put */
-		cy_writel(&buf_ctrl->tx_put, tx_put);
-	}
-}
-
-static void cyz_handle_cmd(struct cyclades_card *cinfo)
-{
-	struct BOARD_CTRL __iomem *board_ctrl = cinfo->board_ctrl;
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	__u32 channel, param, fw_ver;
-	__u8 cmd;
-	int special_count;
-	int delta_count;
-
-	fw_ver = readl(&board_ctrl->fw_version);
-
-	while (cyz_fetch_msg(cinfo, &channel, &cmd, &param) == 1) {
-		special_count = 0;
-		delta_count = 0;
-		info = &cinfo->ports[channel];
-		tty = tty_port_tty_get(&info->port);
-		if (tty == NULL)
-			continue;
-
-		switch (cmd) {
-		case C_CM_PR_ERROR:
-			tty_insert_flip_char(tty, 0, TTY_PARITY);
-			info->icount.rx++;
-			special_count++;
-			break;
-		case C_CM_FR_ERROR:
-			tty_insert_flip_char(tty, 0, TTY_FRAME);
-			info->icount.rx++;
-			special_count++;
-			break;
-		case C_CM_RXBRK:
-			tty_insert_flip_char(tty, 0, TTY_BREAK);
-			info->icount.rx++;
-			special_count++;
-			break;
-		case C_CM_MDCD:
-			info->icount.dcd++;
-			delta_count++;
-			if (info->port.flags & ASYNC_CHECK_CD) {
-				u32 dcd = fw_ver > 241 ? param :
-					readl(&info->u.cyz.ch_ctrl->rs_status);
-				if (dcd & C_RS_DCD)
-					wake_up_interruptible(&info->port.open_wait);
-				else
-					tty_hangup(tty);
-			}
-			break;
-		case C_CM_MCTS:
-			info->icount.cts++;
-			delta_count++;
-			break;
-		case C_CM_MRI:
-			info->icount.rng++;
-			delta_count++;
-			break;
-		case C_CM_MDSR:
-			info->icount.dsr++;
-			delta_count++;
-			break;
-#ifdef Z_WAKE
-		case C_CM_IOCTLW:
-			complete(&info->shutdown_wait);
-			break;
-#endif
-#ifdef CONFIG_CYZ_INTR
-		case C_CM_RXHIWM:
-		case C_CM_RXNNDT:
-		case C_CM_INTBACK2:
-			/* Reception Interrupt */
-#ifdef CY_DEBUG_INTERRUPTS
-			printk(KERN_DEBUG "cyz_interrupt: rcvd intr, card %d, "
-					"port %ld\n", info->card, channel);
-#endif
-			cyz_handle_rx(info, tty);
-			break;
-		case C_CM_TXBEMPTY:
-		case C_CM_TXLOWWM:
-		case C_CM_INTBACK:
-			/* Transmission Interrupt */
-#ifdef CY_DEBUG_INTERRUPTS
-			printk(KERN_DEBUG "cyz_interrupt: xmit intr, card %d, "
-					"port %ld\n", info->card, channel);
-#endif
-			cyz_handle_tx(info, tty);
-			break;
-#endif				/* CONFIG_CYZ_INTR */
-		case C_CM_FATAL:
-			/* should do something with this !!! */
-			break;
-		default:
-			break;
-		}
-		if (delta_count)
-			wake_up_interruptible(&info->port.delta_msr_wait);
-		if (special_count)
-			tty_schedule_flip(tty);
-		tty_kref_put(tty);
-	}
-}
-
-#ifdef CONFIG_CYZ_INTR
-static irqreturn_t cyz_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_card *cinfo = dev_id;
-
-	if (unlikely(!cyz_is_loaded(cinfo))) {
-#ifdef CY_DEBUG_INTERRUPTS
-		printk(KERN_DEBUG "cyz_interrupt: board not yet loaded "
-				"(IRQ%d).\n", irq);
-#endif
-		return IRQ_NONE;
-	}
-
-	/* Handle the interrupts */
-	cyz_handle_cmd(cinfo);
-
-	return IRQ_HANDLED;
-}				/* cyz_interrupt */
-
-static void cyz_rx_restart(unsigned long arg)
-{
-	struct cyclades_port *info = (struct cyclades_port *)arg;
-	struct cyclades_card *card = info->card;
-	int retval;
-	__u32 channel = info->line - card->first_line;
-	unsigned long flags;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	retval = cyz_issue_cmd(card, channel, C_CM_INTBACK2, 0L);
-	if (retval != 0) {
-		printk(KERN_ERR "cyc:cyz_rx_restart retval on ttyC%d was %x\n",
-			info->line, retval);
-	}
-	spin_unlock_irqrestore(&card->card_lock, flags);
-}
-
-#else				/* CONFIG_CYZ_INTR */
-
-static void cyz_poll(unsigned long arg)
-{
-	struct cyclades_card *cinfo;
-	struct cyclades_port *info;
-	unsigned long expires = jiffies + HZ;
-	unsigned int port, card;
-
-	for (card = 0; card < NR_CARDS; card++) {
-		cinfo = &cy_card[card];
-
-		if (!cy_is_Z(cinfo))
-			continue;
-		if (!cyz_is_loaded(cinfo))
-			continue;
-
-	/* Skip first polling cycle to avoid racing conditions with the FW */
-		if (!cinfo->intr_enabled) {
-			cinfo->intr_enabled = 1;
-			continue;
-		}
-
-		cyz_handle_cmd(cinfo);
-
-		for (port = 0; port < cinfo->nports; port++) {
-			struct tty_struct *tty;
-
-			info = &cinfo->ports[port];
-			tty = tty_port_tty_get(&info->port);
-			/* OK to pass NULL to the handle functions below.
-			   They need to drop the data in that case. */
-
-			if (!info->throttle)
-				cyz_handle_rx(info, tty);
-			cyz_handle_tx(info, tty);
-			tty_kref_put(tty);
-		}
-		/* poll every 'cyz_polling_cycle' period */
-		expires = jiffies + cyz_polling_cycle;
-	}
-	mod_timer(&cyz_timerlist, expires);
-}				/* cyz_poll */
-
-#endif				/* CONFIG_CYZ_INTR */
-
-/********** End of block of Cyclades-Z specific code *********/
-/***********************************************************/
-
-/* This is called whenever a port becomes active;
-   interrupts are enabled and DTR & RTS are turned on.
- */
-static int cy_startup(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct cyclades_card *card;
-	unsigned long flags;
-	int retval = 0;
-	int channel;
-	unsigned long page;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	page = get_zeroed_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		goto errout;
-
-	if (!info->type) {
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		goto errout;
-	}
-
-	if (info->port.xmit_buf)
-		free_page(page);
-	else
-		info->port.xmit_buf = (unsigned char *)page;
-
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	cy_set_line_char(info, tty);
-
-	if (!cy_is_Z(card)) {
-		channel &= 0x03;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		cyy_writeb(info, CyCAR, channel);
-
-		cyy_writeb(info, CyRTPR,
-			(info->default_timeout ? info->default_timeout : 0x02));
-		/* 10ms rx timeout */
-
-		cyy_issue_cmd(info, CyCHAN_CTL | CyENB_RCVR | CyENB_XMTR);
-
-		cyy_change_rts_dtr(info, TIOCM_RTS | TIOCM_DTR, 0);
-
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyRxData);
-	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-
-		if (!cyz_is_loaded(card))
-			return -ENODEV;
-
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc startup Z card %d, channel %d, "
-			"base_addr %p\n", card, channel, card->base_addr);
-#endif
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		cy_writel(&ch_ctrl->op_mode, C_CH_ENABLE);
-#ifdef Z_WAKE
-#ifdef CONFIG_CYZ_INTR
-		cy_writel(&ch_ctrl->intr_enable,
-			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
-			  C_IN_RXNNDT | C_IN_IOCTLW | C_IN_MDCD);
-#else
-		cy_writel(&ch_ctrl->intr_enable,
-			  C_IN_IOCTLW | C_IN_MDCD);
-#endif				/* CONFIG_CYZ_INTR */
-#else
-#ifdef CONFIG_CYZ_INTR
-		cy_writel(&ch_ctrl->intr_enable,
-			  C_IN_TXBEMPTY | C_IN_TXLOWWM | C_IN_RXHIWM |
-			  C_IN_RXNNDT | C_IN_MDCD);
-#else
-		cy_writel(&ch_ctrl->intr_enable, C_IN_MDCD);
-#endif				/* CONFIG_CYZ_INTR */
-#endif				/* Z_WAKE */
-
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:startup(1) retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-
-		/* Flush RX buffers before raising DTR and RTS */
-		retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_RX, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:startup(2) retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-
-		/* set timeout !!! */
-		/* set RTS and DTR !!! */
-		tty_port_raise_dtr_rts(&info->port);
-
-		/* enable send, recv, modem !!! */
-	}
-
-	info->port.flags |= ASYNC_INITIALIZED;
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	info->breakon = info->breakoff = 0;
-	memset((char *)&info->idle_stats, 0, sizeof(info->idle_stats));
-	info->idle_stats.in_use =
-	info->idle_stats.recv_idle =
-	info->idle_stats.xmit_idle = jiffies;
-
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc startup done\n");
-#endif
-	return 0;
-
-errout:
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	free_page(page);
-	return retval;
-}				/* startup */
-
-static void start_xmit(struct cyclades_port *info)
-{
-	struct cyclades_card *card = info->card;
-	unsigned long flags;
-	int channel = info->line - card->first_line;
-
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	} else {
-#ifdef CONFIG_CYZ_INTR
-		int retval;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		retval = cyz_issue_cmd(card, channel, C_CM_INTBACK, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:start_xmit retval on ttyC%d was "
-				"%x\n", info->line, retval);
-		}
-		spin_unlock_irqrestore(&card->card_lock, flags);
-#else				/* CONFIG_CYZ_INTR */
-		/* Don't have to do anything at this time */
-#endif				/* CONFIG_CYZ_INTR */
-	}
-}				/* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void cy_shutdown(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct cyclades_card *card;
-	unsigned long flags;
-	int channel;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		/* Clear delta_msr_wait queue to avoid mem leaks. */
-		wake_up_interruptible(&info->port.delta_msr_wait);
-
-		if (info->port.xmit_buf) {
-			unsigned char *temp;
-			temp = info->port.xmit_buf;
-			info->port.xmit_buf = NULL;
-			free_page((unsigned long)temp);
-		}
-		if (tty->termios->c_cflag & HUPCL)
-			cyy_change_rts_dtr(info, 0, TIOCM_RTS | TIOCM_DTR);
-
-		cyy_issue_cmd(info, CyCHAN_CTL | CyDIS_RCVR);
-		/* it may be appropriate to clear _XMIT at
-		   some later date (after testing)!!! */
-
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		info->port.flags &= ~ASYNC_INITIALIZED;
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	} else {
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc shutdown Z card %d, channel %d, "
-			"base_addr %p\n", card, channel, card->base_addr);
-#endif
-
-		if (!cyz_is_loaded(card))
-			return;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-
-		if (info->port.xmit_buf) {
-			unsigned char *temp;
-			temp = info->port.xmit_buf;
-			info->port.xmit_buf = NULL;
-			free_page((unsigned long)temp);
-		}
-
-		if (tty->termios->c_cflag & HUPCL)
-			tty_port_lower_dtr_rts(&info->port);
-
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		info->port.flags &= ~ASYNC_INITIALIZED;
-
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc shutdown done\n");
-#endif
-}				/* shutdown */
-
-/*
- * ------------------------------------------------------------
- * cy_open() and friends
- * ------------------------------------------------------------
- */
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * performs the serial-specific initialization for the tty structure.
- */
-static int cy_open(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info;
-	unsigned int i, line;
-	int retval;
-
-	line = tty->index;
-	if (tty->index < 0 || NR_PORTS <= line)
-		return -ENODEV;
-
-	for (i = 0; i < NR_CARDS; i++)
-		if (line < cy_card[i].first_line + cy_card[i].nports &&
-				line >= cy_card[i].first_line)
-			break;
-	if (i >= NR_CARDS)
-		return -ENODEV;
-	info = &cy_card[i].ports[line - cy_card[i].first_line];
-	if (info->line < 0)
-		return -ENODEV;
-
-	/* If the card's firmware hasn't been loaded,
-	   treat it as absent from the system.  This
-	   will make the user pay attention.
-	 */
-	if (cy_is_Z(info->card)) {
-		struct cyclades_card *cinfo = info->card;
-		struct FIRM_ID __iomem *firm_id = cinfo->base_addr + ID_ADDRESS;
-
-		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 "
-					"halted.\n");
-			} else {
-				printk(KERN_ERR "cyc:Cyclades-Z firmware not "
-					"yet loaded\n");
-			}
-			return -ENODEV;
-		}
-#ifdef CONFIG_CYZ_INTR
-		else {
-		/* In case this Z board is operating in interrupt mode, its
-		   interrupts should be enabled as soon as the first open
-		   happens to one of its ports. */
-			if (!cinfo->intr_enabled) {
-				u16 intr;
-
-				/* Enable interrupts on the PLX chip */
-				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);
-				if (retval != 0) {
-					printk(KERN_ERR "cyc:IRQ enable retval "
-						"was %x\n", retval);
-				}
-				cinfo->intr_enabled = 1;
-			}
-		}
-#endif				/* CONFIG_CYZ_INTR */
-		/* Make sure this Z port really exists in hardware */
-		if (info->line > (cinfo->first_line + cinfo->nports - 1))
-			return -ENODEV;
-	}
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_open ttyC%d\n", info->line);
-#endif
-	tty->driver_data = info;
-	if (serial_paranoia_check(info, tty->name, "cy_open"))
-		return -ENODEV;
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc:cy_open ttyC%d, count = %d\n", info->line,
-			info->port.count);
-#endif
-	info->port.count++;
-#ifdef CY_DEBUG_COUNT
-	printk(KERN_DEBUG "cyc:cy_open (%d): incrementing count to %d\n",
-		current->pid, info->port.count);
-#endif
-
-	/*
-	 * If the port is the middle of closing, bail out now
-	 */
-	if (tty_hung_up_p(filp) || (info->port.flags & ASYNC_CLOSING)) {
-		wait_event_interruptible_tty(info->port.close_wait,
-				!(info->port.flags & ASYNC_CLOSING));
-		return (info->port.flags & ASYNC_HUP_NOTIFY) ? -EAGAIN: -ERESTARTSYS;
-	}
-
-	/*
-	 * Start up serial port
-	 */
-	retval = cy_startup(info, tty);
-	if (retval)
-		return retval;
-
-	retval = tty_port_block_til_ready(&info->port, tty, filp);
-	if (retval) {
-#ifdef CY_DEBUG_OPEN
-		printk(KERN_DEBUG "cyc:cy_open returning after block_til_ready "
-			"with %d\n", retval);
-#endif
-		return retval;
-	}
-
-	info->throttle = 0;
-	tty_port_tty_set(&info->port, tty);
-
-#ifdef CY_DEBUG_OPEN
-	printk(KERN_DEBUG "cyc:cy_open done\n");
-#endif
-	return 0;
-}				/* cy_open */
-
-/*
- * cy_wait_until_sent() --- wait until the transmitter is empty
- */
-static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct cyclades_card *card;
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long orig_jiffies;
-	int char_time;
-
-	if (serial_paranoia_check(info, tty->name, "cy_wait_until_sent"))
-		return;
-
-	if (info->xmit_fifo_size == 0)
-		return;		/* Just in case.... */
-
-	orig_jiffies = jiffies;
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 *
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
-	char_time = char_time / 5;
-	if (char_time <= 0)
-		char_time = 1;
-	if (timeout < 0)
-		timeout = 0;
-	if (timeout)
-		char_time = min(char_time, timeout);
-	/*
-	 * If the transmitter hasn't cleared in twice the approximate
-	 * amount of time to send the entire FIFO, it probably won't
-	 * ever clear.  This assumes the UART isn't doing flow
-	 * control, which is currently the case.  Hence, if it ever
-	 * takes longer than info->timeout, this is probably due to a
-	 * UART bug of some kind.  So, we clamp the timeout parameter at
-	 * 2*info->timeout.
-	 */
-	if (!timeout || timeout > 2 * info->timeout)
-		timeout = 2 * info->timeout;
-#ifdef CY_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "In cy_wait_until_sent(%d) check=%d, jiff=%lu...",
-		timeout, char_time, jiffies);
-#endif
-	card = info->card;
-	if (!cy_is_Z(card)) {
-		while (cyy_readb(info, CySRER) & CyTxRdy) {
-#ifdef CY_DEBUG_WAIT_UNTIL_SENT
-			printk(KERN_DEBUG "Not clean (jiff=%lu)...", jiffies);
-#endif
-			if (msleep_interruptible(jiffies_to_msecs(char_time)))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies +
-					timeout))
-				break;
-		}
-	}
-	/* Run one more char cycle */
-	msleep_interruptible(jiffies_to_msecs(char_time * 5));
-#ifdef CY_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
-#endif
-}
-
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	int channel, retval;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-		return;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	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);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-	tty_wakeup(tty);
-}				/* cy_flush_buffer */
-
-
-static void cy_do_close(struct tty_port *port)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-								port);
-	struct cyclades_card *card;
-	unsigned long flags;
-	int channel;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-	spin_lock_irqsave(&card->card_lock, flags);
-
-	if (!cy_is_Z(card)) {
-		/* Stop accepting input */
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyRxData);
-		if (info->port.flags & ASYNC_INITIALIZED) {
-			/* Waiting for on-board buffers to be empty before
-			   closing the port */
-			spin_unlock_irqrestore(&card->card_lock, flags);
-			cy_wait_until_sent(port->tty, info->timeout);
-			spin_lock_irqsave(&card->card_lock, flags);
-		}
-	} else {
-#ifdef Z_WAKE
-		/* Waiting for on-board buffers to be empty before closing
-		   the port */
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		int retval;
-
-		if (readl(&ch_ctrl->flow_status) != C_FS_TXIDLE) {
-			retval = cyz_issue_cmd(card, channel, C_CM_IOCTLW, 0L);
-			if (retval != 0) {
-				printk(KERN_DEBUG "cyc:cy_close retval on "
-					"ttyC%d was %x\n", info->line, retval);
-			}
-			spin_unlock_irqrestore(&card->card_lock, flags);
-			wait_for_completion_interruptible(&info->shutdown_wait);
-			spin_lock_irqsave(&card->card_lock, flags);
-		}
-#endif
-	}
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	cy_shutdown(info, port->tty);
-}
-
-/*
- * This routine is called when a particular tty device is closed.
- */
-static void cy_close(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info = tty->driver_data;
-	if (!info || serial_paranoia_check(info, tty->name, "cy_close"))
-		return;
-	tty_port_close(&info->port, tty, filp);
-}				/* cy_close */
-
-/* This routine gets called when tty_write has put something into
- * the write_queue.  The characters may come from user space or
- * kernel space.
- *
- * This routine will return the number of characters actually
- * accepted for writing.
- *
- * If the port is not already transmitting stuff, start it off by
- * enabling interrupts.  The interrupt service routine will then
- * ensure that the characters are sent.
- * If the port is already active, there is no need to kick it.
- *
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	int c, ret = 0;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_write ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write"))
-		return 0;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	while (1) {
-		c = min(count, (int)(SERIAL_XMIT_SIZE - info->xmit_cnt - 1));
-		c = min(c, (int)(SERIAL_XMIT_SIZE - info->xmit_head));
-
-		if (c <= 0)
-			break;
-
-		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head = (info->xmit_head + c) &
-			(SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-	info->idle_stats.xmit_bytes += ret;
-	info->idle_stats.xmit_idle = jiffies;
-
-	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped)
-		start_xmit(info);
-
-	return ret;
-}				/* cy_write */
-
-/*
- * This routine is called by the kernel to write a single
- * character to the tty device.  If the kernel uses this routine,
- * it must call the flush_chars() routine (if defined) when it is
- * done stuffing characters into the driver.  If there is no room
- * in the queue, the character is ignored.
- */
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_put_char ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-		return 0;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	if (info->xmit_cnt >= (int)(SERIAL_XMIT_SIZE - 1)) {
-		spin_unlock_irqrestore(&info->card->card_lock, flags);
-		return 0;
-	}
-
-	info->port.xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	info->xmit_cnt++;
-	info->idle_stats.xmit_bytes++;
-	info->idle_stats.xmit_idle = jiffies;
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-	return 1;
-}				/* cy_put_char */
-
-/*
- * This routine is called by the kernel after it has written a
- * series of characters to the tty device using put_char().
- */
-static void cy_flush_chars(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_flush_chars ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-			!info->port.xmit_buf)
-		return;
-
-	start_xmit(info);
-}				/* cy_flush_chars */
-
-/*
- * This routine returns the numbers of characters the tty driver
- * will accept for queuing to be written.  This number is subject
- * to change as output buffers get emptied, or if the output flow
- * control is activated.
- */
-static int cy_write_room(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret;
-
-#ifdef CY_DEBUG_IO
-	printk(KERN_DEBUG "cyc:cy_write_room ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-		return 0;
-	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}				/* cy_write_room */
-
-static int cy_chars_in_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-		return 0;
-
-#ifdef Z_EXT_CHARS_IN_BUFFER
-	if (!cy_is_Z(info->card)) {
-#endif				/* Z_EXT_CHARS_IN_BUFFER */
-#ifdef CY_DEBUG_IO
-		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
-			info->line, info->xmit_cnt);
-#endif
-		return info->xmit_cnt;
-#ifdef Z_EXT_CHARS_IN_BUFFER
-	} else {
-		struct BUF_CTRL __iomem *buf_ctrl = info->u.cyz.buf_ctrl;
-		int char_count;
-		__u32 tx_put, tx_get, tx_bufsize;
-
-		tx_get = readl(&buf_ctrl->tx_get);
-		tx_put = readl(&buf_ctrl->tx_put);
-		tx_bufsize = readl(&buf_ctrl->tx_bufsize);
-		if (tx_put >= tx_get)
-			char_count = tx_put - tx_get;
-		else
-			char_count = tx_put - tx_get + tx_bufsize;
-#ifdef CY_DEBUG_IO
-		printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
-			info->line, info->xmit_cnt + char_count);
-#endif
-		return info->xmit_cnt + char_count;
-	}
-#endif				/* Z_EXT_CHARS_IN_BUFFER */
-}				/* cy_chars_in_buffer */
-
-/*
- * ------------------------------------------------------------
- * cy_ioctl() and friends
- * ------------------------------------------------------------
- */
-
-static void cyy_baud_calc(struct cyclades_port *info, __u32 baud)
-{
-	int co, co_val, bpr;
-	__u32 cy_clock = ((info->chip_rev >= CD1400_REV_J) ? 60000000 :
-			25000000);
-
-	if (baud == 0) {
-		info->tbpr = info->tco = info->rbpr = info->rco = 0;
-		return;
-	}
-
-	/* determine which prescaler to use */
-	for (co = 4, co_val = 2048; co; co--, co_val >>= 2) {
-		if (cy_clock / co_val / baud > 63)
-			break;
-	}
-
-	bpr = (cy_clock / co_val * 2 / baud + 1) / 2;
-	if (bpr > 255)
-		bpr = 255;
-
-	info->tbpr = info->rbpr = bpr;
-	info->tco = info->rco = co;
-}
-
-/*
- * This routine finds or computes the various line characteristics.
- * It used to be called config_setup
- */
-static void cy_set_line_char(struct cyclades_port *info, struct tty_struct *tty)
-{
-	struct cyclades_card *card;
-	unsigned long flags;
-	int channel;
-	unsigned cflag, iflag;
-	int baud, baud_rate = 0;
-	int i;
-
-	if (!tty->termios) /* XXX can this happen at all? */
-		return;
-
-	if (info->line == -1)
-		return;
-
-	cflag = tty->termios->c_cflag;
-	iflag = tty->termios->c_iflag;
-
-	/*
-	 * Set up the tty->alt_speed kludge
-	 */
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-		tty->alt_speed = 57600;
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-		tty->alt_speed = 115200;
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-		tty->alt_speed = 230400;
-	if ((info->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-		tty->alt_speed = 460800;
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	if (!cy_is_Z(card)) {
-		u32 cflags;
-
-		/* baud rate */
-		baud = tty_get_baud_rate(tty);
-		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			if (info->custom_divisor)
-				baud_rate = info->baud / info->custom_divisor;
-			else
-				baud_rate = info->baud;
-		} else if (baud > CD1400_MAX_SPEED) {
-			baud = CD1400_MAX_SPEED;
-		}
-		/* find the baud index */
-		for (i = 0; i < 20; i++) {
-			if (baud == baud_table[i])
-				break;
-		}
-		if (i == 20)
-			i = 19;	/* CD1400_MAX_SPEED */
-
-		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			cyy_baud_calc(info, baud_rate);
-		} else {
-			if (info->chip_rev >= CD1400_REV_J) {
-				/* It is a CD1400 rev. J or later */
-				info->tbpr = baud_bpr_60[i];	/* Tx BPR */
-				info->tco = baud_co_60[i];	/* Tx CO */
-				info->rbpr = baud_bpr_60[i];	/* Rx BPR */
-				info->rco = baud_co_60[i];	/* Rx CO */
-			} else {
-				info->tbpr = baud_bpr_25[i];	/* Tx BPR */
-				info->tco = baud_co_25[i];	/* Tx CO */
-				info->rbpr = baud_bpr_25[i];	/* Rx BPR */
-				info->rco = baud_co_25[i];	/* Rx CO */
-			}
-		}
-		if (baud_table[i] == 134) {
-			/* get it right for 134.5 baud */
-			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
-					2;
-		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud_rate) + 2;
-		} else if (baud_table[i]) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud_table[i]) + 2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-		/* By tradition (is it a standard?) a baud rate of zero
-		   implies the line should be/has been closed.  A bit
-		   later in this routine such a test is performed. */
-
-		/* byte size and parity */
-		info->cor5 = 0;
-		info->cor4 = 0;
-		/* receive threshold */
-		info->cor3 = (info->default_threshold ?
-				info->default_threshold : baud_cor3[i]);
-		info->cor2 = CyETC;
-		switch (cflag & CSIZE) {
-		case CS5:
-			info->cor1 = Cy_5_BITS;
-			break;
-		case CS6:
-			info->cor1 = Cy_6_BITS;
-			break;
-		case CS7:
-			info->cor1 = Cy_7_BITS;
-			break;
-		case CS8:
-			info->cor1 = Cy_8_BITS;
-			break;
-		}
-		if (cflag & CSTOPB)
-			info->cor1 |= Cy_2_STOP;
-
-		if (cflag & PARENB) {
-			if (cflag & PARODD)
-				info->cor1 |= CyPARITY_O;
-			else
-				info->cor1 |= CyPARITY_E;
-		} else
-			info->cor1 |= CyPARITY_NONE;
-
-		/* CTS flow control flag */
-		if (cflag & CRTSCTS) {
-			info->port.flags |= ASYNC_CTS_FLOW;
-			info->cor2 |= CyCtsAE;
-		} else {
-			info->port.flags &= ~ASYNC_CTS_FLOW;
-			info->cor2 &= ~CyCtsAE;
-		}
-		if (cflag & CLOCAL)
-			info->port.flags &= ~ASYNC_CHECK_CD;
-		else
-			info->port.flags |= ASYNC_CHECK_CD;
-
-	 /***********************************************
-	    The hardware option, CyRtsAO, presents RTS when
-	    the chip has characters to send.  Since most modems
-	    use RTS as reverse (inbound) flow control, this
-	    option is not used.  If inbound flow control is
-	    necessary, DTR can be programmed to provide the
-	    appropriate signals for use with a non-standard
-	    cable.  Contact Marcio Saito for details.
-	 ***********************************************/
-
-		channel &= 0x03;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel);
-
-		/* tx and rx baud rate */
-
-		cyy_writeb(info, CyTCOR, info->tco);
-		cyy_writeb(info, CyTBPR, info->tbpr);
-		cyy_writeb(info, CyRCOR, info->rco);
-		cyy_writeb(info, CyRBPR, info->rbpr);
-
-		/* set line characteristics  according configuration */
-
-		cyy_writeb(info, CySCHR1, START_CHAR(tty));
-		cyy_writeb(info, CySCHR2, STOP_CHAR(tty));
-		cyy_writeb(info, CyCOR1, info->cor1);
-		cyy_writeb(info, CyCOR2, info->cor2);
-		cyy_writeb(info, CyCOR3, info->cor3);
-		cyy_writeb(info, CyCOR4, info->cor4);
-		cyy_writeb(info, CyCOR5, info->cor5);
-
-		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR1ch | CyCOR2ch |
-				CyCOR3ch);
-
-		/* !!! Is this needed? */
-		cyy_writeb(info, CyCAR, channel);
-		cyy_writeb(info, CyRTPR,
-			(info->default_timeout ? info->default_timeout : 0x02));
-		/* 10ms rx timeout */
-
-		cflags = CyCTS;
-		if (!C_CLOCAL(tty))
-			cflags |= CyDSR | CyRI | CyDCD;
-		/* without modem intr */
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyMdmCh);
-		/* act on 1->0 modem transitions */
-		if ((cflag & CRTSCTS) && info->rflow)
-			cyy_writeb(info, CyMCOR1, cflags | rflow_thr[i]);
-		else
-			cyy_writeb(info, CyMCOR1, cflags);
-		/* act on 0->1 modem transitions */
-		cyy_writeb(info, CyMCOR2, cflags);
-
-		if (i == 0)	/* baud rate is zero, turn off line */
-			cyy_change_rts_dtr(info, 0, TIOCM_DTR);
-		else
-			cyy_change_rts_dtr(info, TIOCM_DTR, 0);
-
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-
-	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		__u32 sw_flow;
-		int retval;
-
-		if (!cyz_is_loaded(card))
-			return;
-
-		/* baud rate */
-		baud = tty_get_baud_rate(tty);
-		if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			if (info->custom_divisor)
-				baud_rate = info->baud / info->custom_divisor;
-			else
-				baud_rate = info->baud;
-		} else if (baud > CYZ_MAX_SPEED) {
-			baud = CYZ_MAX_SPEED;
-		}
-		cy_writel(&ch_ctrl->comm_baud, baud);
-
-		if (baud == 134) {
-			/* get it right for 134.5 baud */
-			info->timeout = (info->xmit_fifo_size * HZ * 30 / 269) +
-					2;
-		} else if (baud == 38400 && (info->port.flags & ASYNC_SPD_MASK) ==
-				ASYNC_SPD_CUST) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud_rate) + 2;
-		} else if (baud) {
-			info->timeout = (info->xmit_fifo_size * HZ * 15 /
-					baud) + 2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-
-		/* byte size and parity */
-		switch (cflag & CSIZE) {
-		case CS5:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS5);
-			break;
-		case CS6:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS6);
-			break;
-		case CS7:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS7);
-			break;
-		case CS8:
-			cy_writel(&ch_ctrl->comm_data_l, C_DL_CS8);
-			break;
-		}
-		if (cflag & CSTOPB) {
-			cy_writel(&ch_ctrl->comm_data_l,
-				  readl(&ch_ctrl->comm_data_l) | C_DL_2STOP);
-		} else {
-			cy_writel(&ch_ctrl->comm_data_l,
-				  readl(&ch_ctrl->comm_data_l) | C_DL_1STOP);
-		}
-		if (cflag & PARENB) {
-			if (cflag & PARODD)
-				cy_writel(&ch_ctrl->comm_parity, C_PR_ODD);
-			else
-				cy_writel(&ch_ctrl->comm_parity, C_PR_EVEN);
-		} else
-			cy_writel(&ch_ctrl->comm_parity, C_PR_NONE);
-
-		/* CTS flow control flag */
-		if (cflag & CRTSCTS) {
-			cy_writel(&ch_ctrl->hw_flow,
-				readl(&ch_ctrl->hw_flow) | C_RS_CTS | C_RS_RTS);
-		} else {
-			cy_writel(&ch_ctrl->hw_flow, readl(&ch_ctrl->hw_flow) &
-					~(C_RS_CTS | C_RS_RTS));
-		}
-		/* As the HW flow control is done in firmware, the driver
-		   doesn't need to care about it */
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-		/* XON/XOFF/XANY flow control flags */
-		sw_flow = 0;
-		if (iflag & IXON) {
-			sw_flow |= C_FL_OXX;
-			if (iflag & IXANY)
-				sw_flow |= C_FL_OIXANY;
-		}
-		cy_writel(&ch_ctrl->sw_flow, sw_flow);
-
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTL, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:set_line_char retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-
-		/* CD sensitivity */
-		if (cflag & CLOCAL)
-			info->port.flags &= ~ASYNC_CHECK_CD;
-		else
-			info->port.flags |= ASYNC_CHECK_CD;
-
-		if (baud == 0) {	/* baud rate is zero, turn off line */
-			cy_writel(&ch_ctrl->rs_control,
-				  readl(&ch_ctrl->rs_control) & ~C_RS_DTR);
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_line_char dropping Z DTR\n");
-#endif
-		} else {
-			cy_writel(&ch_ctrl->rs_control,
-				  readl(&ch_ctrl->rs_control) | C_RS_DTR);
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_line_char raising Z DTR\n");
-#endif
-		}
-
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:set_line_char(2) retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-	}
-}				/* set_line_char */
-
-static int cy_get_serial_info(struct cyclades_port *info,
-		struct serial_struct __user *retinfo)
-{
-	struct cyclades_card *cinfo = info->card;
-	struct serial_struct tmp = {
-		.type = info->type,
-		.line = info->line,
-		.port = (info->card - cy_card) * 0x100 + info->line -
-			cinfo->first_line,
-		.irq = cinfo->irq,
-		.flags = info->port.flags,
-		.close_delay = info->port.close_delay,
-		.closing_wait = info->port.closing_wait,
-		.baud_base = info->baud,
-		.custom_divisor = info->custom_divisor,
-		.hub6 = 0,		/*!!! */
-	};
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-static int
-cy_set_serial_info(struct cyclades_port *info, struct tty_struct *tty,
-		struct serial_struct __user *new_info)
-{
-	struct serial_struct new_serial;
-	int ret;
-
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-
-	mutex_lock(&info->port.mutex);
-	if (!capable(CAP_SYS_ADMIN)) {
-		if (new_serial.close_delay != info->port.close_delay ||
-				new_serial.baud_base != info->baud ||
-				(new_serial.flags & ASYNC_FLAGS &
-					~ASYNC_USR_MASK) !=
-				(info->port.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK))
-		{
-			mutex_unlock(&info->port.mutex);
-			return -EPERM;
-		}
-		info->port.flags = (info->port.flags & ~ASYNC_USR_MASK) |
-				(new_serial.flags & ASYNC_USR_MASK);
-		info->baud = new_serial.baud_base;
-		info->custom_divisor = new_serial.custom_divisor;
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	info->baud = new_serial.baud_base;
-	info->custom_divisor = new_serial.custom_divisor;
-	info->port.flags = (info->port.flags & ~ASYNC_FLAGS) |
-			(new_serial.flags & ASYNC_FLAGS);
-	info->port.close_delay = new_serial.close_delay * HZ / 100;
-	info->port.closing_wait = new_serial.closing_wait * HZ / 100;
-
-check_and_exit:
-	if (info->port.flags & ASYNC_INITIALIZED) {
-		cy_set_line_char(info, tty);
-		ret = 0;
-	} else {
-		ret = cy_startup(info, tty);
-	}
-	mutex_unlock(&info->port.mutex);
-	return ret;
-}				/* set_serial_info */
-
-/*
- * get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *	    is emptied.  On bus types like RS485, the transmitter must
- *	    release the bus after transmitting. This must be done when
- *	    the transmit shift register is empty, not be done when the
- *	    transmit holding register is empty.  This functionality
- *	    allows an RS485 driver to be written in user space.
- */
-static int get_lsr_info(struct cyclades_port *info, unsigned int __user *value)
-{
-	struct cyclades_card *card = info->card;
-	unsigned int result;
-	unsigned long flags;
-	u8 status;
-
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		status = cyy_readb(info, CySRER) & (CyTxRdy | CyTxMpty);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		result = (status ? 0 : TIOCSER_TEMT);
-	} else {
-		/* Not supported yet */
-		return -EINVAL;
-	}
-	return put_user(result, (unsigned long __user *)value);
-}
-
-static int cy_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	int result;
-
-	if (serial_paranoia_check(info, tty->name, __func__))
-		return -ENODEV;
-
-	card = info->card;
-
-	if (!cy_is_Z(card)) {
-		unsigned long flags;
-		int channel = info->line - card->first_line;
-		u8 status;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		status = cyy_readb(info, CyMSVR1);
-		status |= cyy_readb(info, CyMSVR2);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-
-		if (info->rtsdtr_inv) {
-			result = ((status & CyRTS) ? TIOCM_DTR : 0) |
-				((status & CyDTR) ? TIOCM_RTS : 0);
-		} else {
-			result = ((status & CyRTS) ? TIOCM_RTS : 0) |
-				((status & CyDTR) ? TIOCM_DTR : 0);
-		}
-		result |= ((status & CyDCD) ? TIOCM_CAR : 0) |
-			((status & CyRI) ? TIOCM_RNG : 0) |
-			((status & CyDSR) ? TIOCM_DSR : 0) |
-			((status & CyCTS) ? TIOCM_CTS : 0);
-	} else {
-		u32 lstatus;
-
-		if (!cyz_is_loaded(card)) {
-			result = -ENODEV;
-			goto end;
-		}
-
-		lstatus = readl(&info->u.cyz.ch_ctrl->rs_status);
-		result = ((lstatus & C_RS_RTS) ? TIOCM_RTS : 0) |
-			((lstatus & C_RS_DTR) ? TIOCM_DTR : 0) |
-			((lstatus & C_RS_DCD) ? TIOCM_CAR : 0) |
-			((lstatus & C_RS_RI) ? TIOCM_RNG : 0) |
-			((lstatus & C_RS_DSR) ? TIOCM_DSR : 0) |
-			((lstatus & C_RS_CTS) ? TIOCM_CTS : 0);
-	}
-end:
-	return result;
-}				/* cy_tiomget */
-
-static int
-cy_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-
-	if (serial_paranoia_check(info, tty->name, __func__))
-		return -ENODEV;
-
-	card = info->card;
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_change_rts_dtr(info, set, clear);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	} else {
-		struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-		int retval, channel = info->line - card->first_line;
-		u32 rs;
-
-		if (!cyz_is_loaded(card))
-			return -ENODEV;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		rs = readl(&ch_ctrl->rs_control);
-		if (set & TIOCM_RTS)
-			rs |= C_RS_RTS;
-		if (clear & TIOCM_RTS)
-			rs &= ~C_RS_RTS;
-		if (set & TIOCM_DTR) {
-			rs |= C_RS_DTR;
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_modem_info raising Z DTR\n");
-#endif
-		}
-		if (clear & TIOCM_DTR) {
-			rs &= ~C_RS_DTR;
-#ifdef CY_DEBUG_DTR
-			printk(KERN_DEBUG "cyc:set_modem_info clearing "
-				"Z DTR\n");
-#endif
-		}
-		cy_writel(&ch_ctrl->rs_control, rs);
-		retval = cyz_issue_cmd(card, channel, C_CM_IOCTLM, 0L);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		if (retval != 0) {
-			printk(KERN_ERR "cyc:set_modem_info retval on ttyC%d "
-				"was %x\n", info->line, retval);
-		}
-	}
-	return 0;
-}
-
-/*
- * cy_break() --- routine which turns the break handling on or off
- */
-static int cy_break(struct tty_struct *tty, int break_state)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-	int retval = 0;
-
-	if (serial_paranoia_check(info, tty->name, "cy_break"))
-		return -EINVAL;
-
-	card = info->card;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	if (!cy_is_Z(card)) {
-		/* Let the transmit ISR take care of this (since it
-		   requires stuffing characters into the output stream).
-		 */
-		if (break_state == -1) {
-			if (!info->breakon) {
-				info->breakon = 1;
-				if (!info->xmit_cnt) {
-					spin_unlock_irqrestore(&card->card_lock, flags);
-					start_xmit(info);
-					spin_lock_irqsave(&card->card_lock, flags);
-				}
-			}
-		} else {
-			if (!info->breakoff) {
-				info->breakoff = 1;
-				if (!info->xmit_cnt) {
-					spin_unlock_irqrestore(&card->card_lock, flags);
-					start_xmit(info);
-					spin_lock_irqsave(&card->card_lock, flags);
-				}
-			}
-		}
-	} else {
-		if (break_state == -1) {
-			retval = cyz_issue_cmd(card,
-				info->line - card->first_line,
-				C_CM_SET_BREAK, 0L);
-			if (retval != 0) {
-				printk(KERN_ERR "cyc:cy_break (set) retval on "
-					"ttyC%d was %x\n", info->line, retval);
-			}
-		} else {
-			retval = cyz_issue_cmd(card,
-				info->line - card->first_line,
-				C_CM_CLR_BREAK, 0L);
-			if (retval != 0) {
-				printk(KERN_DEBUG "cyc:cy_break (clr) retval "
-					"on ttyC%d was %x\n", info->line,
-					retval);
-			}
-		}
-	}
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	return retval;
-}				/* cy_break */
-
-static int set_threshold(struct cyclades_port *info, unsigned long value)
-{
-	struct cyclades_card *card = info->card;
-	unsigned long flags;
-
-	if (!cy_is_Z(card)) {
-		info->cor3 &= ~CyREC_FIFO;
-		info->cor3 |= value & CyREC_FIFO;
-
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyCOR3, info->cor3);
-		cyy_issue_cmd(info, CyCOR_CHANGE | CyCOR3ch);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-	return 0;
-}				/* set_threshold */
-
-static int get_threshold(struct cyclades_port *info,
-						unsigned long __user *value)
-{
-	struct cyclades_card *card = info->card;
-
-	if (!cy_is_Z(card)) {
-		u8 tmp = cyy_readb(info, CyCOR3) & CyREC_FIFO;
-		return put_user(tmp, value);
-	}
-	return 0;
-}				/* get_threshold */
-
-static int set_timeout(struct cyclades_port *info, unsigned long value)
-{
-	struct cyclades_card *card = info->card;
-	unsigned long flags;
-
-	if (!cy_is_Z(card)) {
-		spin_lock_irqsave(&card->card_lock, flags);
-		cyy_writeb(info, CyRTPR, value & 0xff);
-		spin_unlock_irqrestore(&card->card_lock, flags);
-	}
-	return 0;
-}				/* set_timeout */
-
-static int get_timeout(struct cyclades_port *info,
-						unsigned long __user *value)
-{
-	struct cyclades_card *card = info->card;
-
-	if (!cy_is_Z(card)) {
-		u8 tmp = cyy_readb(info, CyRTPR);
-		return put_user(tmp, value);
-	}
-	return 0;
-}				/* get_timeout */
-
-static int cy_cflags_changed(struct cyclades_port *info, unsigned long arg,
-		struct cyclades_icount *cprev)
-{
-	struct cyclades_icount cnow;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	cnow = info->icount;	/* atomic copy */
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-	ret =	((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
-		((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
-		((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
-		((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
-
-	*cprev = cnow;
-
-	return ret;
-}
-
-/*
- * This routine allows the tty driver to implement device-
- * specific ioctl's.  If the ioctl number passed in cmd is
- * not recognized by the driver, it should return ENOIOCTLCMD.
- */
-static int
-cy_ioctl(struct tty_struct *tty, struct file *file,
-	 unsigned int cmd, unsigned long arg)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_icount cnow;	/* kernel counter temps */
-	int ret_val = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	if (serial_paranoia_check(info, tty->name, "cy_ioctl"))
-		return -ENODEV;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_ioctl ttyC%d, cmd = %x arg = %lx\n",
-		info->line, cmd, arg);
-#endif
-
-	switch (cmd) {
-	case CYGETMON:
-		if (copy_to_user(argp, &info->mon, sizeof(info->mon))) {
-			ret_val = -EFAULT;
-			break;
-		}
-		memset(&info->mon, 0, sizeof(info->mon));
-		break;
-	case CYGETTHRESH:
-		ret_val = get_threshold(info, argp);
-		break;
-	case CYSETTHRESH:
-		ret_val = set_threshold(info, arg);
-		break;
-	case CYGETDEFTHRESH:
-		ret_val = put_user(info->default_threshold,
-				(unsigned long __user *)argp);
-		break;
-	case CYSETDEFTHRESH:
-		info->default_threshold = arg & 0x0f;
-		break;
-	case CYGETTIMEOUT:
-		ret_val = get_timeout(info, argp);
-		break;
-	case CYSETTIMEOUT:
-		ret_val = set_timeout(info, arg);
-		break;
-	case CYGETDEFTIMEOUT:
-		ret_val = put_user(info->default_timeout,
-				(unsigned long __user *)argp);
-		break;
-	case CYSETDEFTIMEOUT:
-		info->default_timeout = arg & 0xff;
-		break;
-	case CYSETRFLOW:
-		info->rflow = (int)arg;
-		break;
-	case CYGETRFLOW:
-		ret_val = info->rflow;
-		break;
-	case CYSETRTSDTR_INV:
-		info->rtsdtr_inv = (int)arg;
-		break;
-	case CYGETRTSDTR_INV:
-		ret_val = info->rtsdtr_inv;
-		break;
-	case CYGETCD1400VER:
-		ret_val = info->chip_rev;
-		break;
-#ifndef CONFIG_CYZ_INTR
-	case CYZSETPOLLCYCLE:
-		cyz_polling_cycle = (arg * HZ) / 1000;
-		break;
-	case CYZGETPOLLCYCLE:
-		ret_val = (cyz_polling_cycle * 1000) / HZ;
-		break;
-#endif				/* CONFIG_CYZ_INTR */
-	case CYSETWAIT:
-		info->port.closing_wait = (unsigned short)arg * HZ / 100;
-		break;
-	case CYGETWAIT:
-		ret_val = info->port.closing_wait / (HZ / 100);
-		break;
-	case TIOCGSERIAL:
-		ret_val = cy_get_serial_info(info, argp);
-		break;
-	case TIOCSSERIAL:
-		ret_val = cy_set_serial_info(info, tty, argp);
-		break;
-	case TIOCSERGETLSR:	/* Get line status register */
-		ret_val = get_lsr_info(info, argp);
-		break;
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
-		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-	case TIOCMIWAIT:
-		spin_lock_irqsave(&info->card->card_lock, flags);
-		/* note the counters on entry */
-		cnow = info->icount;
-		spin_unlock_irqrestore(&info->card->card_lock, flags);
-		ret_val = wait_event_interruptible(info->port.delta_msr_wait,
-				cy_cflags_changed(info, arg, &cnow));
-		break;
-
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-	default:
-		ret_val = -ENOIOCTLCMD;
-	}
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_ioctl done\n");
-#endif
-	return ret_val;
-}				/* cy_ioctl */
-
-static int cy_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *sic)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_icount cnow;	/* Used to snapshot */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->card->card_lock, flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->card->card_lock, flags);
-
-	sic->cts = cnow.cts;
-	sic->dsr = cnow.dsr;
-	sic->rng = cnow.rng;
-	sic->dcd = cnow.dcd;
-	sic->rx = cnow.rx;
-	sic->tx = cnow.tx;
-	sic->frame = cnow.frame;
-	sic->overrun = cnow.overrun;
-	sic->parity = cnow.parity;
-	sic->brk = cnow.brk;
-	sic->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-/*
- * This routine allows the tty driver to be notified when
- * device's termios settings have changed.  Note that a
- * well-designed tty driver should be prepared to accept the case
- * where old == NULL, and try to do something rational.
- */
-static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_set_termios ttyC%d\n", info->line);
-#endif
-
-	cy_set_line_char(info, tty);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		cy_start(tty);
-	}
-#if 0
-	/*
-	 * No need to wake up processes in open wait, since they
-	 * sample the CLOCAL flag once, and don't recheck it.
-	 * XXX  It's not clear whether the current behavior is correct
-	 * or not.  Hence, this may change.....
-	 */
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->port.open_wait);
-#endif
-}				/* cy_set_termios */
-
-/* This function is used to send a high-priority XON/XOFF character to
-   the device.
-*/
-static void cy_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	int channel;
-
-	if (serial_paranoia_check(info, tty->name, "cy_send_xchar"))
-		return;
-
-	info->x_char = ch;
-
-	if (ch)
-		cy_start(tty);
-
-	card = info->card;
-	channel = info->line - card->first_line;
-
-	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))
-			cyz_issue_cmd(card, channel, C_CM_SENDXON, 0L);
-	}
-}
-
-/* This routine is called by the upper-layer tty layer to signal
-   that incoming characters should be throttled because the input
-   buffers are close to full.
- */
-static void cy_throttle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_THROTTLE
-	char buf[64];
-
-	printk(KERN_DEBUG "cyc:throttle %s: %ld...ttyC%d\n", tty_name(tty, buf),
-			tty->ldisc.chars_in_buffer(tty), info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_throttle"))
-		return;
-
-	card = info->card;
-
-	if (I_IXOFF(tty)) {
-		if (!cy_is_Z(card))
-			cy_send_xchar(tty, STOP_CHAR(tty));
-		else
-			info->throttle = 1;
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		if (!cy_is_Z(card)) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cyy_change_rts_dtr(info, 0, TIOCM_RTS);
-			spin_unlock_irqrestore(&card->card_lock, flags);
-		} else {
-			info->throttle = 1;
-		}
-	}
-}				/* cy_throttle */
-
-/*
- * This routine notifies the tty driver that it should signal
- * that characters can now be sent to the tty without fear of
- * overrunning the input buffers of the line disciplines.
- */
-static void cy_unthrottle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	struct cyclades_card *card;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_THROTTLE
-	char buf[64];
-
-	printk(KERN_DEBUG "cyc:unthrottle %s: %ld...ttyC%d\n",
-		tty_name(tty, buf), tty_chars_in_buffer(tty), info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			cy_send_xchar(tty, START_CHAR(tty));
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		card = info->card;
-		if (!cy_is_Z(card)) {
-			spin_lock_irqsave(&card->card_lock, flags);
-			cyy_change_rts_dtr(info, TIOCM_RTS, 0);
-			spin_unlock_irqrestore(&card->card_lock, flags);
-		} else {
-			info->throttle = 0;
-		}
-	}
-}				/* cy_unthrottle */
-
-/* cy_start and cy_stop provide software output flow control as a
-   function of XON/XOFF, software CTS, and other such stuff.
-*/
-static void cy_stop(struct tty_struct *tty)
-{
-	struct cyclades_card *cinfo;
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_stop ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_stop"))
-		return;
-
-	cinfo = info->card;
-	channel = info->line - cinfo->first_line;
-	if (!cy_is_Z(cinfo)) {
-		spin_lock_irqsave(&cinfo->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) & ~CyTxRdy);
-		spin_unlock_irqrestore(&cinfo->card_lock, flags);
-	}
-}				/* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
-	struct cyclades_card *cinfo;
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	unsigned long flags;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_start ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_start"))
-		return;
-
-	cinfo = info->card;
-	channel = info->line - cinfo->first_line;
-	if (!cy_is_Z(cinfo)) {
-		spin_lock_irqsave(&cinfo->card_lock, flags);
-		cyy_writeb(info, CyCAR, channel & 0x03);
-		cyy_writeb(info, CySRER, cyy_readb(info, CySRER) | CyTxRdy);
-		spin_unlock_irqrestore(&cinfo->card_lock, flags);
-	}
-}				/* cy_start */
-
-/*
- * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void cy_hangup(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef CY_DEBUG_OTHER
-	printk(KERN_DEBUG "cyc:cy_hangup ttyC%d\n", info->line);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-		return;
-
-	cy_flush_buffer(tty);
-	cy_shutdown(info, tty);
-	tty_port_hangup(&info->port);
-}				/* cy_hangup */
-
-static int cyy_carrier_raised(struct tty_port *port)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-	struct cyclades_card *cinfo = info->card;
-	unsigned long flags;
-	int channel = info->line - cinfo->first_line;
-	u32 cd;
-
-	spin_lock_irqsave(&cinfo->card_lock, flags);
-	cyy_writeb(info, CyCAR, channel & 0x03);
-	cd = cyy_readb(info, CyMSVR1) & CyDCD;
-	spin_unlock_irqrestore(&cinfo->card_lock, flags);
-
-	return cd;
-}
-
-static void cyy_dtr_rts(struct tty_port *port, int raise)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-	struct cyclades_card *cinfo = info->card;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cinfo->card_lock, flags);
-	cyy_change_rts_dtr(info, raise ? TIOCM_RTS | TIOCM_DTR : 0,
-			raise ? 0 : TIOCM_RTS | TIOCM_DTR);
-	spin_unlock_irqrestore(&cinfo->card_lock, flags);
-}
-
-static int cyz_carrier_raised(struct tty_port *port)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-
-	return readl(&info->u.cyz.ch_ctrl->rs_status) & C_RS_DCD;
-}
-
-static void cyz_dtr_rts(struct tty_port *port, int raise)
-{
-	struct cyclades_port *info = container_of(port, struct cyclades_port,
-			port);
-	struct cyclades_card *cinfo = info->card;
-	struct CH_CTRL __iomem *ch_ctrl = info->u.cyz.ch_ctrl;
-	int ret, channel = info->line - cinfo->first_line;
-	u32 rs;
-
-	rs = readl(&ch_ctrl->rs_control);
-	if (raise)
-		rs |= C_RS_RTS | C_RS_DTR;
-	else
-		rs &= ~(C_RS_RTS | C_RS_DTR);
-	cy_writel(&ch_ctrl->rs_control, rs);
-	ret = cyz_issue_cmd(cinfo, channel, C_CM_IOCTLM, 0L);
-	if (ret != 0)
-		printk(KERN_ERR "%s: retval on ttyC%d was %x\n",
-				__func__, info->line, ret);
-#ifdef CY_DEBUG_DTR
-	printk(KERN_DEBUG "%s: raising Z DTR\n", __func__);
-#endif
-}
-
-static const struct tty_port_operations cyy_port_ops = {
-	.carrier_raised = cyy_carrier_raised,
-	.dtr_rts = cyy_dtr_rts,
-	.shutdown = cy_do_close,
-};
-
-static const struct tty_port_operations cyz_port_ops = {
-	.carrier_raised = cyz_carrier_raised,
-	.dtr_rts = cyz_dtr_rts,
-	.shutdown = cy_do_close,
-};
-
-/*
- * ---------------------------------------------------------------------
- * cy_init() and friends
- *
- * cy_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-static int __devinit cy_init_card(struct cyclades_card *cinfo)
-{
-	struct cyclades_port *info;
-	unsigned int channel, port;
-
-	spin_lock_init(&cinfo->card_lock);
-	cinfo->intr_enabled = 0;
-
-	cinfo->ports = kcalloc(cinfo->nports, sizeof(*cinfo->ports),
-			GFP_KERNEL);
-	if (cinfo->ports == NULL) {
-		printk(KERN_ERR "Cyclades: cannot allocate ports\n");
-		return -ENOMEM;
-	}
-
-	for (channel = 0, port = cinfo->first_line; channel < cinfo->nports;
-			channel++, port++) {
-		info = &cinfo->ports[channel];
-		tty_port_init(&info->port);
-		info->magic = CYCLADES_MAGIC;
-		info->card = cinfo;
-		info->line = port;
-
-		info->port.closing_wait = CLOSING_WAIT_DELAY;
-		info->port.close_delay = 5 * HZ / 10;
-		info->port.flags = STD_COM_FLAGS;
-		init_completion(&info->shutdown_wait);
-
-		if (cy_is_Z(cinfo)) {
-			struct FIRM_ID *firm_id = cinfo->base_addr + ID_ADDRESS;
-			struct ZFW_CTRL *zfw_ctrl;
-
-			info->port.ops = &cyz_port_ops;
-			info->type = PORT_STARTECH;
-
-			zfw_ctrl = cinfo->base_addr +
-				(readl(&firm_id->zfwctrl_addr) & 0xfffff);
-			info->u.cyz.ch_ctrl = &zfw_ctrl->ch_ctrl[channel];
-			info->u.cyz.buf_ctrl = &zfw_ctrl->buf_ctrl[channel];
-
-			if (cinfo->hw_ver == ZO_V1)
-				info->xmit_fifo_size = CYZ_FIFO_SIZE;
-			else
-				info->xmit_fifo_size = 4 * CYZ_FIFO_SIZE;
-#ifdef CONFIG_CYZ_INTR
-			setup_timer(&cyz_rx_full_timer[port],
-				cyz_rx_restart, (unsigned long)info);
-#endif
-		} else {
-			unsigned short chip_number;
-			int index = cinfo->bus_index;
-
-			info->port.ops = &cyy_port_ops;
-			info->type = PORT_CIRRUS;
-			info->xmit_fifo_size = CyMAX_CHAR_FIFO;
-			info->cor1 = CyPARITY_NONE | Cy_1_STOP | Cy_8_BITS;
-			info->cor2 = CyETC;
-			info->cor3 = 0x08;	/* _very_ small rcv threshold */
-
-			chip_number = channel / CyPORTS_PER_CHIP;
-			info->u.cyy.base_addr = cinfo->base_addr +
-				(cy_chip_offset[chip_number] << index);
-			info->chip_rev = cyy_readb(info, CyGFRCR);
-
-			if (info->chip_rev >= CD1400_REV_J) {
-				/* It is a CD1400 rev. J or later */
-				info->tbpr = baud_bpr_60[13];	/* Tx BPR */
-				info->tco = baud_co_60[13];	/* Tx CO */
-				info->rbpr = baud_bpr_60[13];	/* Rx BPR */
-				info->rco = baud_co_60[13];	/* Rx CO */
-				info->rtsdtr_inv = 1;
-			} else {
-				info->tbpr = baud_bpr_25[13];	/* Tx BPR */
-				info->tco = baud_co_25[13];	/* Tx CO */
-				info->rbpr = baud_bpr_25[13];	/* Rx BPR */
-				info->rco = baud_co_25[13];	/* Rx CO */
-				info->rtsdtr_inv = 0;
-			}
-			info->read_status_mask = CyTIMEOUT | CySPECHAR |
-				CyBREAK | CyPARITY | CyFRAME | CyOVERRUN;
-		}
-
-	}
-
-#ifndef CONFIG_CYZ_INTR
-	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");
-#endif
-	}
-#endif
-	return 0;
-}
-
-/* initialize chips on Cyclom-Y card -- return number of valid
-   chips (which is number of ports/4) */
-static unsigned short __devinit cyy_init_card(void __iomem *true_base_addr,
-		int index)
-{
-	unsigned int chip_number;
-	void __iomem *base_addr;
-
-	cy_writeb(true_base_addr + (Cy_HwReset << index), 0);
-	/* Cy_HwReset is 0x1400 */
-	cy_writeb(true_base_addr + (Cy_ClrIntr << index), 0);
-	/* Cy_ClrIntr is 0x1800 */
-	udelay(500L);
-
-	for (chip_number = 0; chip_number < CyMAX_CHIPS_PER_CARD;
-							chip_number++) {
-		base_addr =
-		    true_base_addr + (cy_chip_offset[chip_number] << index);
-		mdelay(1);
-		if (readb(base_addr + (CyCCR << index)) != 0x00) {
-			/*************
-			printk(" chip #%d at %#6lx is never idle (CCR != 0)\n",
-			chip_number, (unsigned long)base_addr);
-			*************/
-			return chip_number;
-		}
-
-		cy_writeb(base_addr + (CyGFRCR << index), 0);
-		udelay(10L);
-
-		/* The Cyclom-16Y does not decode address bit 9 and therefore
-		   cannot distinguish between references to chip 0 and a non-
-		   existent chip 4.  If the preceding clearing of the supposed
-		   chip 4 GFRCR register appears at chip 0, there is no chip 4
-		   and this must be a Cyclom-16Y, not a Cyclom-32Ye.
-		 */
-		if (chip_number == 4 && readb(true_base_addr +
-				(cy_chip_offset[0] << index) +
-				(CyGFRCR << index)) == 0) {
-			return chip_number;
-		}
-
-		cy_writeb(base_addr + (CyCCR << index), CyCHIP_RESET);
-		mdelay(1);
-
-		if (readb(base_addr + (CyGFRCR << index)) == 0x00) {
-			/*
-			   printk(" chip #%d at %#6lx is not responding ",
-			   chip_number, (unsigned long)base_addr);
-			   printk("(GFRCR stayed 0)\n",
-			 */
-			return chip_number;
-		}
-		if ((0xf0 & (readb(base_addr + (CyGFRCR << index)))) !=
-				0x40) {
-			/*
-			printk(" chip #%d at %#6lx is not valid (GFRCR == "
-					"%#2x)\n",
-					chip_number, (unsigned long)base_addr,
-					base_addr[CyGFRCR<<index]);
-			 */
-			return chip_number;
-		}
-		cy_writeb(base_addr + (CyGCR << index), CyCH0_SERIAL);
-		if (readb(base_addr + (CyGFRCR << index)) >= CD1400_REV_J) {
-			/* It is a CD1400 rev. J or later */
-			/* Impossible to reach 5ms with this chip.
-			   Changed to 2ms instead (f = 500 Hz). */
-			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_60_2MS);
-		} else {
-			/* f = 200 Hz */
-			cy_writeb(base_addr + (CyPPR << index), CyCLOCK_25_5MS);
-		}
-
-		/*
-		   printk(" chip #%d at %#6lx is rev 0x%2x\n",
-		   chip_number, (unsigned long)base_addr,
-		   readb(base_addr+(CyGFRCR<<index)));
-		 */
-	}
-	return chip_number;
-}				/* cyy_init_card */
-
-/*
- * ---------------------------------------------------------------------
- * cy_detect_isa() - Probe for Cyclom-Y/ISA boards.
- * sets global variables and return the number of ISA boards found.
- * ---------------------------------------------------------------------
- */
-static int __init cy_detect_isa(void)
-{
-#ifdef CONFIG_ISA
-	unsigned short cy_isa_irq, nboard;
-	void __iomem *cy_isa_address;
-	unsigned short i, j, cy_isa_nchan;
-	int isparam = 0;
-
-	nboard = 0;
-
-	/* Check for module parameters */
-	for (i = 0; i < NR_CARDS; i++) {
-		if (maddr[i] || i) {
-			isparam = 1;
-			cy_isa_addresses[i] = maddr[i];
-		}
-		if (!maddr[i])
-			break;
-	}
-
-	/* scan the address table probing for Cyclom-Y/ISA boards */
-	for (i = 0; i < NR_ISA_ADDRS; i++) {
-		unsigned int isa_address = cy_isa_addresses[i];
-		if (isa_address == 0x0000)
-			return nboard;
-
-		/* probe for CD1400... */
-		cy_isa_address = ioremap_nocache(isa_address, CyISA_Ywin);
-		if (cy_isa_address == NULL) {
-			printk(KERN_ERR "Cyclom-Y/ISA: can't remap base "
-					"address\n");
-			continue;
-		}
-		cy_isa_nchan = CyPORTS_PER_CHIP *
-			cyy_init_card(cy_isa_address, 0);
-		if (cy_isa_nchan == 0) {
-			iounmap(cy_isa_address);
-			continue;
-		}
-
-		if (isparam && i < NR_CARDS && irq[i])
-			cy_isa_irq = irq[i];
-		else
-			/* find out the board's irq by probing */
-			cy_isa_irq = detect_isa_irq(cy_isa_address);
-		if (cy_isa_irq == 0) {
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but the "
-				"IRQ could not be detected.\n",
-				(unsigned long)cy_isa_address);
-			iounmap(cy_isa_address);
-			continue;
-		}
-
-		if ((cy_next_channel + cy_isa_nchan) > NR_PORTS) {
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
-				"more channels are available. Change NR_PORTS "
-				"in cyclades.c and recompile kernel.\n",
-				(unsigned long)cy_isa_address);
-			iounmap(cy_isa_address);
-			return nboard;
-		}
-		/* fill the next cy_card structure available */
-		for (j = 0; j < NR_CARDS; j++) {
-			if (cy_card[j].base_addr == NULL)
-				break;
-		}
-		if (j == NR_CARDS) {	/* no more cy_cards available */
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but no "
-				"more cards can be used. Change NR_CARDS in "
-				"cyclades.c and recompile kernel.\n",
-				(unsigned long)cy_isa_address);
-			iounmap(cy_isa_address);
-			return nboard;
-		}
-
-		/* allocate IRQ */
-		if (request_irq(cy_isa_irq, cyy_interrupt,
-				IRQF_DISABLED, "Cyclom-Y", &cy_card[j])) {
-			printk(KERN_ERR "Cyclom-Y/ISA found at 0x%lx, but "
-				"could not allocate IRQ#%d.\n",
-				(unsigned long)cy_isa_address, cy_isa_irq);
-			iounmap(cy_isa_address);
-			return nboard;
-		}
-
-		/* set cy_card */
-		cy_card[j].base_addr = cy_isa_address;
-		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 / 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]);
-			iounmap(cy_isa_address);
-			continue;
-		}
-		nboard++;
-
-		printk(KERN_INFO "Cyclom-Y/ISA #%d: 0x%lx-0x%lx, IRQ%d found: "
-			"%d channels starting from port %d\n",
-			j + 1, (unsigned long)cy_isa_address,
-			(unsigned long)(cy_isa_address + (CyISA_Ywin - 1)),
-			cy_isa_irq, cy_isa_nchan, cy_next_channel);
-
-		for (j = cy_next_channel;
-				j < cy_next_channel + cy_isa_nchan; j++)
-			tty_register_device(cy_serial_driver, j, NULL);
-		cy_next_channel += cy_isa_nchan;
-	}
-	return nboard;
-#else
-	return 0;
-#endif				/* CONFIG_ISA */
-}				/* cy_detect_isa */
-
-#ifdef CONFIG_PCI
-static inline int __devinit cyc_isfwstr(const char *str, unsigned int size)
-{
-	unsigned int a;
-
-	for (a = 0; a < size && *str; a++, str++)
-		if (*str & 0x80)
-			return -EINVAL;
-
-	for (; a < size; a++, str++)
-		if (*str)
-			return -EINVAL;
-
-	return 0;
-}
-
-static inline void __devinit cyz_fpga_copy(void __iomem *fpga, const u8 *data,
-		unsigned int size)
-{
-	for (; size > 0; size--) {
-		cy_writel(fpga, *data++);
-		udelay(10);
-	}
-}
-
-static void __devinit plx_init(struct pci_dev *pdev, int irq,
-		struct RUNTIME_9060 __iomem *addr)
-{
-	/* Reset PLX */
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x40000000);
-	udelay(100L);
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x40000000);
-
-	/* Reload Config. Registers from EEPROM */
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) | 0x20000000);
-	udelay(100L);
-	cy_writel(&addr->init_ctrl, readl(&addr->init_ctrl) & ~0x20000000);
-
-	/* For some yet unknown reason, once the PLX9060 reloads the EEPROM,
-	 * the IRQ is lost and, thus, we have to re-write it to the PCI config.
-	 * registers. This will remain here until we find a permanent fix.
-	 */
-	pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, irq);
-}
-
-static int __devinit __cyz_load_fw(const struct firmware *fw,
-		const char *name, const u32 mailbox, void __iomem *base,
-		void __iomem *fpga)
-{
-	const void *ptr = fw->data;
-	const struct zfile_header *h = ptr;
-	const struct zfile_config *c, *cs;
-	const struct zfile_block *b, *bs;
-	unsigned int a, tmp, len = fw->size;
-#define BAD_FW KERN_ERR "Bad firmware: "
-	if (len < sizeof(*h)) {
-		printk(BAD_FW "too short: %u<%zu\n", len, sizeof(*h));
-		return -EINVAL;
-	}
-
-	cs = ptr + h->config_offset;
-	bs = ptr + h->block_offset;
-
-	if ((void *)(cs + h->n_config) > ptr + len ||
-			(void *)(bs + h->n_blocks) > ptr + len) {
-		printk(BAD_FW "too short");
-		return  -EINVAL;
-	}
-
-	if (cyc_isfwstr(h->name, sizeof(h->name)) ||
-			cyc_isfwstr(h->date, sizeof(h->date))) {
-		printk(BAD_FW "bad formatted header string\n");
-		return -EINVAL;
-	}
-
-	if (strncmp(name, h->name, sizeof(h->name))) {
-		printk(BAD_FW "bad name '%s' (expected '%s')\n", h->name, name);
-		return -EINVAL;
-	}
-
-	tmp = 0;
-	for (c = cs; c < cs + h->n_config; c++) {
-		for (a = 0; a < c->n_blocks; a++)
-			if (c->block_list[a] > h->n_blocks) {
-				printk(BAD_FW "bad block ref number in cfgs\n");
-				return -EINVAL;
-			}
-		if (c->mailbox == mailbox && c->function == 0) /* 0 is normal */
-			tmp++;
-	}
-	if (!tmp) {
-		printk(BAD_FW "nothing appropriate\n");
-		return -EINVAL;
-	}
-
-	for (b = bs; b < bs + h->n_blocks; b++)
-		if (b->file_offset + b->size > len) {
-			printk(BAD_FW "bad block data offset\n");
-			return -EINVAL;
-		}
-
-	/* everything is OK, let's seek'n'load it */
-	for (c = cs; c < cs + h->n_config; c++)
-		if (c->mailbox == mailbox && c->function == 0)
-			break;
-
-	for (a = 0; a < c->n_blocks; a++) {
-		b = &bs[c->block_list[a]];
-		if (b->type == ZBLOCK_FPGA) {
-			if (fpga != NULL)
-				cyz_fpga_copy(fpga, ptr + b->file_offset,
-						b->size);
-		} else {
-			if (base != NULL)
-				memcpy_toio(base + b->ram_offset,
-					       ptr + b->file_offset, b->size);
-		}
-	}
-#undef BAD_FW
-	return 0;
-}
-
-static int __devinit cyz_load_fw(struct pci_dev *pdev, void __iomem *base_addr,
-		struct RUNTIME_9060 __iomem *ctl_addr, int irq)
-{
-	const struct firmware *fw;
-	struct FIRM_ID __iomem *fid = base_addr + ID_ADDRESS;
-	struct CUSTOM_REG __iomem *cust = base_addr;
-	struct ZFW_CTRL __iomem *pt_zfwctrl;
-	void __iomem *tmp;
-	u32 mailbox, status, nchan;
-	unsigned int i;
-	int retval;
-
-	retval = reject_firmware(&fw, "/*(DEBLOBBED)*/", &pdev->dev);
-	if (retval) {
-		dev_err(&pdev->dev, "can't get firmware\n");
-		goto err;
-	}
-
-	/* Check whether the firmware is already loaded and running. If
-	   positive, skip this board */
-	if (__cyz_fpga_loaded(ctl_addr) && readl(&fid->signature) == ZFIRM_ID) {
-		u32 cntval = readl(base_addr + 0x190);
-
-		udelay(100);
-		if (cntval != readl(base_addr + 0x190)) {
-			/* FW counter is working, FW is running */
-			dev_dbg(&pdev->dev, "Cyclades-Z FW already loaded. "
-					"Skipping board.\n");
-			retval = 0;
-			goto err_rel;
-		}
-	}
-
-	/* start boot */
-	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) &
-			~0x00030800UL);
-
-	mailbox = readl(&ctl_addr->mail_box_0);
-
-	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);
-		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-		udelay(100);
-	}
-
-	plx_init(pdev, irq, ctl_addr);
-
-	if (mailbox != 0) {
-		/* load FPGA */
-		retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, NULL,
-				base_addr);
-		if (retval)
-			goto err_rel;
-		if (!__cyz_fpga_loaded(ctl_addr)) {
-			dev_err(&pdev->dev, "fw upload successful, but fw is "
-					"not loaded\n");
-			goto err_rel;
-		}
-	}
-
-	/* stops CPU and set window to beginning of RAM */
-	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-	cy_writel(&cust->cpu_stop, 0);
-	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-	udelay(100);
-
-	/* clear memory */
-	for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
-		cy_writeb(tmp, 255);
-	if (mailbox != 0) {
-		/* set window to last 512K of RAM */
-		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM + RAM_SIZE);
-		for (tmp = base_addr; tmp < base_addr + RAM_SIZE; tmp++)
-			cy_writeb(tmp, 255);
-		/* set window to beginning of RAM */
-		cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-	}
-
-	retval = __cyz_load_fw(fw, "Cyclom-Z", mailbox, base_addr, NULL);
-	release_firmware(fw);
-	if (retval)
-		goto err;
-
-	/* finish boot and start boards */
-	cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-	cy_writel(&cust->cpu_start, 0);
-	cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-	i = 0;
-	while ((status = readl(&fid->signature)) != ZFIRM_ID && i++ < 40)
-		msleep(100);
-	if (status != ZFIRM_ID) {
-		if (status == ZFIRM_HLT) {
-			dev_err(&pdev->dev, "you need an external power supply "
-				"for this number of ports. Firmware halted and "
-				"board reset.\n");
-			retval = -EIO;
-			goto err;
-		}
-		dev_warn(&pdev->dev, "fid->signature = 0x%x... Waiting "
-				"some more time\n", status);
-		while ((status = readl(&fid->signature)) != ZFIRM_ID &&
-				i++ < 200)
-			msleep(100);
-		if (status != ZFIRM_ID) {
-			dev_err(&pdev->dev, "Board not started in 20 seconds! "
-					"Giving up. (fid->signature = 0x%x)\n",
-					status);
-			dev_info(&pdev->dev, "*** Warning ***: if you are "
-				"upgrading the FW, please power cycle the "
-				"system before loading the new FW to the "
-				"Cyclades-Z.\n");
-
-			if (__cyz_fpga_loaded(ctl_addr))
-				plx_init(pdev, irq, ctl_addr);
-
-			retval = -EIO;
-			goto err;
-		}
-		dev_dbg(&pdev->dev, "Firmware started after %d seconds.\n",
-				i / 10);
-	}
-	pt_zfwctrl = base_addr + readl(&fid->zfwctrl_addr);
-
-	dev_dbg(&pdev->dev, "fid=> %p, zfwctrl_addr=> %x, npt_zfwctrl=> %p\n",
-			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), nchan);
-
-	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 (__cyz_fpga_loaded(ctl_addr))
-			plx_init(pdev, irq, ctl_addr);
-
-		dev_info(&pdev->dev, "Null number of ports detected. Board "
-				"reset.\n");
-		retval = 0;
-		goto err;
-	}
-
-	cy_writel(&pt_zfwctrl->board_ctrl.op_system, C_OS_LINUX);
-	cy_writel(&pt_zfwctrl->board_ctrl.dr_version, DRIVER_VERSION);
-
-	/*
-	   Early firmware failed to start looking for commands.
-	   This enables firmware interrupts for those commands.
-	 */
-	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
-			(1 << 17));
-	cy_writel(&ctl_addr->intr_ctrl_stat, readl(&ctl_addr->intr_ctrl_stat) |
-			0x00030800UL);
-
-	return nchan;
-err_rel:
-	release_firmware(fw);
-err:
-	return retval;
-}
-
-static int __devinit cy_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	void __iomem *addr0 = NULL, *addr2 = NULL;
-	char *card_name = NULL;
-	u32 uninitialized_var(mailbox);
-	unsigned int device_id, nchan = 0, card_no, i;
-	unsigned char plx_ver;
-	int retval, irq;
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "cannot enable device\n");
-		goto err;
-	}
-
-	/* read PCI configuration area */
-	irq = pdev->irq;
-	device_id = pdev->device & ~PCI_DEVICE_ID_MASK;
-
-#if defined(__alpha__)
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo) {	/* below 1M? */
-		dev_err(&pdev->dev, "Cyclom-Y/PCI not supported for low "
-			"addresses on Alpha systems.\n");
-		retval = -EIO;
-		goto err_dis;
-	}
-#endif
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Lo) {
-		dev_err(&pdev->dev, "Cyclades-Z/PCI not supported for low "
-			"addresses\n");
-		retval = -EIO;
-		goto err_dis;
-	}
-
-	if (pci_resource_flags(pdev, 2) & IORESOURCE_IO) {
-		dev_warn(&pdev->dev, "PCI I/O bit incorrectly set. Ignoring "
-				"it...\n");
-		pdev->resource[2].flags &= ~IORESOURCE_IO;
-	}
-
-	retval = pci_request_regions(pdev, "cyclades");
-	if (retval) {
-		dev_err(&pdev->dev, "failed to reserve resources\n");
-		goto err_dis;
-	}
-
-	retval = -EIO;
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-		card_name = "Cyclom-Y";
-
-		addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
-				CyPCI_Yctl);
-		if (addr0 == NULL) {
-			dev_err(&pdev->dev, "can't remap ctl region\n");
-			goto err_reg;
-		}
-		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
-				CyPCI_Ywin);
-		if (addr2 == NULL) {
-			dev_err(&pdev->dev, "can't remap base region\n");
-			goto err_unmap;
-		}
-
-		nchan = CyPORTS_PER_CHIP * cyy_init_card(addr2, 1);
-		if (nchan == 0) {
-			dev_err(&pdev->dev, "Cyclom-Y PCI host card with no "
-					"Serial-Modules\n");
-			goto err_unmap;
-		}
-	} else if (device_id == PCI_DEVICE_ID_CYCLOM_Z_Hi) {
-		struct RUNTIME_9060 __iomem *ctl_addr;
-
-		ctl_addr = addr0 = ioremap_nocache(pci_resource_start(pdev, 0),
-				CyPCI_Zctl);
-		if (addr0 == NULL) {
-			dev_err(&pdev->dev, "can't remap ctl region\n");
-			goto err_reg;
-		}
-
-		/* Disable interrupts on the PLX before resetting it */
-		cy_writew(&ctl_addr->intr_ctrl_stat,
-				readw(&ctl_addr->intr_ctrl_stat) & ~0x0900);
-
-		plx_init(pdev, irq, addr0);
-
-		mailbox = readl(&ctl_addr->mail_box_0);
-
-		addr2 = ioremap_nocache(pci_resource_start(pdev, 2),
-				mailbox == ZE_V1 ? CyPCI_Ze_win : CyPCI_Zwin);
-		if (addr2 == NULL) {
-			dev_err(&pdev->dev, "can't remap base region\n");
-			goto err_unmap;
-		}
-
-		if (mailbox == ZE_V1) {
-			card_name = "Cyclades-Ze";
-		} else {
-			card_name = "Cyclades-8Zo";
-#ifdef CY_PCI_DEBUG
-			if (mailbox == ZO_V1) {
-				cy_writel(&ctl_addr->loc_addr_base, WIN_CREG);
-				dev_info(&pdev->dev, "Cyclades-8Zo/PCI: FPGA "
-					"id %lx, ver %lx\n", (ulong)(0xff &
-					readl(&((struct CUSTOM_REG *)addr2)->
-						fpga_id)), (ulong)(0xff &
-					readl(&((struct CUSTOM_REG *)addr2)->
-						fpga_version)));
-				cy_writel(&ctl_addr->loc_addr_base, WIN_RAM);
-			} else {
-				dev_info(&pdev->dev, "Cyclades-Z/PCI: New "
-					"Cyclades-Z board.  FPGA not loaded\n");
-			}
-#endif
-			/* The following clears the firmware id word.  This
-			   ensures that the driver will not attempt to talk to
-			   the board until it has been properly initialized.
-			 */
-			if ((mailbox == ZO_V1) || (mailbox == ZO_V2))
-				cy_writel(addr2 + ID_ADDRESS, 0L);
-		}
-
-		retval = cyz_load_fw(pdev, addr2, addr0, irq);
-		if (retval <= 0)
-			goto err_unmap;
-		nchan = retval;
-	}
-
-	if ((cy_next_channel + nchan) > NR_PORTS) {
-		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
-			"channels are available. Change NR_PORTS in "
-			"cyclades.c and recompile kernel.\n");
-		goto err_unmap;
-	}
-	/* fill the next cy_card structure available */
-	for (card_no = 0; card_no < NR_CARDS; card_no++) {
-		if (cy_card[card_no].base_addr == NULL)
-			break;
-	}
-	if (card_no == NR_CARDS) {	/* no more cy_cards available */
-		dev_err(&pdev->dev, "Cyclades-8Zo/PCI found, but no "
-			"more cards can be used. Change NR_CARDS in "
-			"cyclades.c and recompile kernel.\n");
-		goto err_unmap;
-	}
-
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-		/* allocate IRQ */
-		retval = request_irq(irq, cyy_interrupt,
-				IRQF_SHARED, "Cyclom-Y", &cy_card[card_no]);
-		if (retval) {
-			dev_err(&pdev->dev, "could not allocate IRQ\n");
-			goto err_unmap;
-		}
-		cy_card[card_no].num_chips = nchan / CyPORTS_PER_CHIP;
-	} else {
-		struct FIRM_ID __iomem *firm_id = addr2 + ID_ADDRESS;
-		struct ZFW_CTRL __iomem *zfw_ctrl;
-
-		zfw_ctrl = addr2 + (readl(&firm_id->zfwctrl_addr) & 0xfffff);
-
-		cy_card[card_no].hw_ver = mailbox;
-		cy_card[card_no].num_chips = (unsigned int)-1;
-		cy_card[card_no].board_ctrl = &zfw_ctrl->board_ctrl;
-#ifdef CONFIG_CYZ_INTR
-		/* allocate IRQ only if board has an IRQ */
-		if (irq != 0 && irq != 255) {
-			retval = request_irq(irq, cyz_interrupt,
-					IRQF_SHARED, "Cyclades-Z",
-					&cy_card[card_no]);
-			if (retval) {
-				dev_err(&pdev->dev, "could not allocate IRQ\n");
-				goto err_unmap;
-			}
-		}
-#endif				/* CONFIG_CYZ_INTR */
-	}
-
-	/* set cy_card */
-	cy_card[card_no].base_addr = addr2;
-	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;
-
-	pci_set_drvdata(pdev, &cy_card[card_no]);
-
-	if (device_id == PCI_DEVICE_ID_CYCLOM_Y_Lo ||
-			device_id == PCI_DEVICE_ID_CYCLOM_Y_Hi) {
-		/* enable interrupts in the PCI interface */
-		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 */
-		{
-			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 "
-		"port %d.\n", card_name, card_no + 1, nchan, cy_next_channel);
-	for (i = cy_next_channel; i < cy_next_channel + nchan; i++)
-		tty_register_device(cy_serial_driver, i, &pdev->dev);
-	cy_next_channel += nchan;
-
-	return 0;
-err_null:
-	cy_card[card_no].base_addr = NULL;
-	free_irq(irq, &cy_card[card_no]);
-err_unmap:
-	iounmap(addr0);
-	if (addr2)
-		iounmap(addr2);
-err_reg:
-	pci_release_regions(pdev);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return retval;
-}
-
-static void __devexit cy_pci_remove(struct pci_dev *pdev)
-{
-	struct cyclades_card *cinfo = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	/* non-Z with old PLX */
-	if (!cy_is_Z(cinfo) && (readb(cinfo->base_addr + CyPLX_VER) & 0x0f) ==
-			PLX_9050)
-		cy_writeb(cinfo->ctl_addr.p9050 + 0x4c, 0);
-	else
-#ifndef CONFIG_CYZ_INTR
-		if (!cy_is_Z(cinfo))
-#endif
-		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.p9050)
-		iounmap(cinfo->ctl_addr.p9050);
-	if (cinfo->irq
-#ifndef CONFIG_CYZ_INTR
-		&& !cy_is_Z(cinfo)
-#endif /* CONFIG_CYZ_INTR */
-		)
-		free_irq(cinfo->irq, cinfo);
-	pci_release_regions(pdev);
-
-	cinfo->base_addr = NULL;
-	for (i = cinfo->first_line; i < cinfo->first_line +
-			cinfo->nports; i++)
-		tty_unregister_device(cy_serial_driver, i);
-	cinfo->nports = 0;
-	kfree(cinfo->ports);
-}
-
-static struct pci_driver cy_pci_driver = {
-	.name = "cyclades",
-	.id_table = cy_pci_dev_id,
-	.probe = cy_pci_probe,
-	.remove = __devexit_p(cy_pci_remove)
-};
-#endif
-
-static int cyclades_proc_show(struct seq_file *m, void *v)
-{
-	struct cyclades_port *info;
-	unsigned int i, j;
-	__u32 cur_jifs = jiffies;
-
-	seq_puts(m, "Dev TimeOpen   BytesOut  IdleOut    BytesIn   "
-			"IdleIn  Overruns  Ldisc\n");
-
-	/* Output one line for each known port */
-	for (i = 0; i < NR_CARDS; i++)
-		for (j = 0; j < cy_card[i].nports; j++) {
-			info = &cy_card[i].ports[j];
-
-			if (info->port.count) {
-				/* XXX is the ldisc num worth this? */
-				struct tty_struct *tty;
-				struct tty_ldisc *ld;
-				int num = 0;
-				tty = tty_port_tty_get(&info->port);
-				if (tty) {
-					ld = tty_ldisc_ref(tty);
-					if (ld) {
-						num = ld->ops->num;
-						tty_ldisc_deref(ld);
-					}
-					tty_kref_put(tty);
-				}
-				seq_printf(m, "%3d %8lu %10lu %8lu "
-					"%10lu %8lu %9lu %6d\n", info->line,
-					(cur_jifs - info->idle_stats.in_use) /
-					HZ, info->idle_stats.xmit_bytes,
-					(cur_jifs - info->idle_stats.xmit_idle)/
-					HZ, info->idle_stats.recv_bytes,
-					(cur_jifs - info->idle_stats.recv_idle)/
-					HZ, info->idle_stats.overruns,
-					num);
-			} else
-				seq_printf(m, "%3d %8lu %10lu %8lu "
-					"%10lu %8lu %9lu %6ld\n",
-					info->line, 0L, 0L, 0L, 0L, 0L, 0L, 0L);
-		}
-	return 0;
-}
-
-static int cyclades_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, cyclades_proc_show, NULL);
-}
-
-static const struct file_operations cyclades_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= cyclades_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/* The serial driver boot-time initialization code!
-    Hardware I/O ports are mapped to character special devices on a
-    first found, first allocated manner.  That is, this code searches
-    for Cyclom cards in the system.  As each is found, it is probed
-    to discover how many chips (and thus how many ports) are present.
-    These ports are mapped to the tty ports 32 and upward in monotonic
-    fashion.  If an 8-port card is replaced with a 16-port card, the
-    port mapping on a following card will shift.
-
-    This approach is different from what is used in the other serial
-    device driver because the Cyclom is more properly a multiplexer,
-    not just an aggregation of serial ports on one card.
-
-    If there are more cards with more ports than have been
-    statically allocated above, a warning is printed and the
-    extra ports are ignored.
- */
-
-static const struct tty_operations cy_ops = {
-	.open = cy_open,
-	.close = cy_close,
-	.write = cy_write,
-	.put_char = cy_put_char,
-	.flush_chars = cy_flush_chars,
-	.write_room = cy_write_room,
-	.chars_in_buffer = cy_chars_in_buffer,
-	.flush_buffer = cy_flush_buffer,
-	.ioctl = cy_ioctl,
-	.throttle = cy_throttle,
-	.unthrottle = cy_unthrottle,
-	.set_termios = cy_set_termios,
-	.stop = cy_stop,
-	.start = cy_start,
-	.hangup = cy_hangup,
-	.break_ctl = cy_break,
-	.wait_until_sent = cy_wait_until_sent,
-	.tiocmget = cy_tiocmget,
-	.tiocmset = cy_tiocmset,
-	.get_icount = cy_get_icount,
-	.proc_fops = &cyclades_proc_fops,
-};
-
-static int __init cy_init(void)
-{
-	unsigned int nboards;
-	int retval = -ENOMEM;
-
-	cy_serial_driver = alloc_tty_driver(NR_PORTS);
-	if (!cy_serial_driver)
-		goto err;
-
-	printk(KERN_INFO "Cyclades driver " CY_VERSION " (built %s %s)\n",
-			__DATE__, __TIME__);
-
-	/* Initialize the tty_driver structure */
-
-	cy_serial_driver->owner = THIS_MODULE;
-	cy_serial_driver->driver_name = "cyclades";
-	cy_serial_driver->name = "ttyC";
-	cy_serial_driver->major = CYCLADES_MAJOR;
-	cy_serial_driver->minor_start = 0;
-	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	cy_serial_driver->init_termios = tty_std_termios;
-	cy_serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(cy_serial_driver, &cy_ops);
-
-	retval = tty_register_driver(cy_serial_driver);
-	if (retval) {
-		printk(KERN_ERR "Couldn't register Cyclades serial driver\n");
-		goto err_frtty;
-	}
-
-	/* the code below is responsible to find the boards. Each different
-	   type of board has its own detection routine. If a board is found,
-	   the next cy_card structure available is set by the detection
-	   routine. These functions are responsible for checking the
-	   availability of cy_card and cy_port data structures and updating
-	   the cy_next_channel. */
-
-	/* look for isa boards */
-	nboards = cy_detect_isa();
-
-#ifdef CONFIG_PCI
-	/* look for pci boards */
-	retval = pci_register_driver(&cy_pci_driver);
-	if (retval && !nboards) {
-		tty_unregister_driver(cy_serial_driver);
-		goto err_frtty;
-	}
-#endif
-
-	return 0;
-err_frtty:
-	put_tty_driver(cy_serial_driver);
-err:
-	return retval;
-}				/* cy_init */
-
-static void __exit cy_cleanup_module(void)
-{
-	struct cyclades_card *card;
-	unsigned int i, e1;
-
-#ifndef CONFIG_CYZ_INTR
-	del_timer_sync(&cyz_timerlist);
-#endif /* CONFIG_CYZ_INTR */
-
-	e1 = tty_unregister_driver(cy_serial_driver);
-	if (e1)
-		printk(KERN_ERR "failed to unregister Cyclades serial "
-				"driver(%d)\n", e1);
-
-#ifdef CONFIG_PCI
-	pci_unregister_driver(&cy_pci_driver);
-#endif
-
-	for (i = 0; i < NR_CARDS; i++) {
-		card = &cy_card[i];
-		if (card->base_addr) {
-			/* clear interrupt */
-			cy_writeb(card->base_addr + Cy_ClrIntr, 0);
-			iounmap(card->base_addr);
-			if (card->ctl_addr.p9050)
-				iounmap(card->ctl_addr.p9050);
-			if (card->irq
-#ifndef CONFIG_CYZ_INTR
-				&& !cy_is_Z(card)
-#endif /* CONFIG_CYZ_INTR */
-				)
-				free_irq(card->irq, card);
-			for (e1 = card->first_line; e1 < card->first_line +
-					card->nports; e1++)
-				tty_unregister_device(cy_serial_driver, e1);
-			kfree(card->ports);
-		}
-	}
-
-	put_tty_driver(cy_serial_driver);
-} /* cy_cleanup_module */
-
-module_init(cy_init);
-module_exit(cy_cleanup_module);
-
-MODULE_LICENSE("GPL");
-MODULE_VERSION(CY_VERSION);
-MODULE_ALIAS_CHARDEV_MAJOR(CYCLADES_MAJOR);
-/*(DEBLOBBED)*/
diff -druN linux-libre-2.6.38-gnu/drivers/char/digi1.h linux-libre-2.6.39-gnu/drivers/char/digi1.h
--- linux-libre-2.6.38-gnu/drivers/char/digi1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/digi1.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/*          Definitions for DigiBoard ditty(1) command.                 */
-
-#if !defined(TIOCMODG)
-#define	TIOCMODG	(('d'<<8) | 250)	/* get modem ctrl state	*/
-#define	TIOCMODS	(('d'<<8) | 251)	/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMSET)
-#define	TIOCMSET	(('d'<<8) | 252)	/* set modem ctrl state	*/
-#define	TIOCMGET	(('d'<<8) | 253)	/* set modem ctrl state	*/
-#endif
-
-#if !defined(TIOCMBIC)
-#define	TIOCMBIC	(('d'<<8) | 254)	/* set modem ctrl state */
-#define	TIOCMBIS	(('d'<<8) | 255)	/* set modem ctrl state */
-#endif
-
-#if !defined(TIOCSDTR)
-#define	TIOCSDTR	(('e'<<8) | 0)		/* set DTR		*/
-#define	TIOCCDTR	(('e'<<8) | 1)		/* clear DTR		*/
-#endif
-
-/************************************************************************
- * Ioctl command arguments for DIGI parameters.
- ************************************************************************/
-#define DIGI_GETA	(('e'<<8) | 94)		/* Read params		*/
-
-#define DIGI_SETA	(('e'<<8) | 95)		/* Set params		*/
-#define DIGI_SETAW	(('e'<<8) | 96)		/* Drain & set params	*/
-#define DIGI_SETAF	(('e'<<8) | 97)		/* Drain, flush & set params */
-
-#define	DIGI_GETFLOW	(('e'<<8) | 99)		/* Get startc/stopc flow */
-						/* control characters 	 */
-#define	DIGI_SETFLOW	(('e'<<8) | 100)	/* Set startc/stopc flow */
-						/* control characters	 */
-#define	DIGI_GETAFLOW	(('e'<<8) | 101)	/* Get Aux. startc/stopc */
-						/* flow control chars 	 */
-#define	DIGI_SETAFLOW	(('e'<<8) | 102)	/* Set Aux. startc/stopc */
-						/* flow control chars	 */
-
-#define	DIGI_GETINFO	(('e'<<8) | 103)	/* Fill in digi_info */
-#define	DIGI_POLLER	(('e'<<8) | 104)	/* Turn on/off poller */
-#define	DIGI_INIT	(('e'<<8) | 105)	/* Allow things to run. */
-
-struct	digiflow_struct 
-{
-	unsigned char	startc;				/* flow cntl start char	*/
-	unsigned char	stopc;				/* flow cntl stop char	*/
-};
-
-typedef struct digiflow_struct digiflow_t;
-
-
-/************************************************************************
- * Values for digi_flags 
- ************************************************************************/
-#define DIGI_IXON	0x0001		/* Handle IXON in the FEP	*/
-#define DIGI_FAST	0x0002		/* Fast baud rates		*/
-#define RTSPACE		0x0004		/* RTS input flow control	*/
-#define CTSPACE		0x0008		/* CTS output flow control	*/
-#define DSRPACE		0x0010		/* DSR output flow control	*/
-#define DCDPACE		0x0020		/* DCD output flow control	*/
-#define DTRPACE		0x0040		/* DTR input flow control	*/
-#define DIGI_FORCEDCD	0x0100		/* Force carrier		*/
-#define	DIGI_ALTPIN	0x0200		/* Alternate RJ-45 pin config	*/
-#define	DIGI_AIXON	0x0400		/* Aux flow control in fep	*/
-
-
-/************************************************************************
- * Values for digiDload
- ************************************************************************/
-#define NORMAL  0
-#define PCI_CTL 1
-
-#define SIZE8  0
-#define SIZE16 1
-#define SIZE32 2
-
-/************************************************************************
- * Structure used with ioctl commands for DIGI parameters.
- ************************************************************************/
-struct digi_struct 
-{
-	unsigned short	digi_flags;		/* Flags (see above)	*/
-};
-
-typedef struct digi_struct digi_t;
-
-struct digi_info 
-{
-	unsigned long board;        /* Which board is this ? */
-	unsigned char status;       /* Alive or dead */
-	unsigned char type;         /* see epca.h */
-	unsigned char subtype;      /* For future XEM, XR, etc ... */
-	unsigned short numports;    /* Number of ports configured */
-	unsigned char *port;        /* I/O Address */
-	unsigned char *membase;     /* DPR Address */
-	unsigned char *version;     /* For future ... */
-	unsigned short windowData;  /* For future ... */
-} ;
diff -druN linux-libre-2.6.38-gnu/drivers/char/digiFep1.h linux-libre-2.6.39-gnu/drivers/char/digiFep1.h
--- linux-libre-2.6.38-gnu/drivers/char/digiFep1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/digiFep1.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,136 +0,0 @@
-
-#define CSTART       0x400L
-#define CMAX         0x800L
-#define ISTART       0x800L
-#define IMAX         0xC00L
-#define CIN          0xD10L
-#define GLOBAL       0xD10L
-#define EIN          0xD18L
-#define FEPSTAT      0xD20L
-#define CHANSTRUCT   0x1000L
-#define RXTXBUF      0x4000L
-
-
-struct global_data 
-{
-	u16 cin;
-	u16 cout;
-	u16 cstart;
-	u16 cmax;
-	u16 ein;
-	u16 eout;
-	u16 istart;
-	u16 imax;
-};
-
-
-struct board_chan 
-{
-	u32 filler1;
-	u32 filler2;
-	u16 tseg;
-	u16 tin;
-	u16 tout;
-	u16 tmax;
-
-	u16 rseg;
-	u16 rin;
-	u16 rout;
-	u16 rmax;
-
-	u16 tlow;
-	u16 rlow;
-	u16 rhigh;
-	u16 incr;
-
-	u16 etime;
-	u16 edelay;
-	unchar *dev;
-
-	u16 iflag;
-	u16 oflag;
-	u16 cflag;
-	u16 gmask;
-
-	u16 col;
-	u16 delay;
-	u16 imask;
-	u16 tflush;
-
-	u32 filler3;
-	u32 filler4;
-	u32 filler5;
-	u32 filler6;
-
-	u8 num;
-	u8 ract;
-	u8 bstat;
-	u8 tbusy;
-	u8 iempty;
-	u8 ilow;
-	u8 idata;
-	u8 eflag;
-
-	u8 tflag;
-	u8 rflag;
-	u8 xmask;
-	u8 xval;
-	u8 mstat;
-	u8 mchange;
-	u8 mint;
-	u8 lstat;
-
-	u8 mtran;
-	u8 orun;
-	u8 startca;
-	u8 stopca;
-	u8 startc;
-	u8 stopc;
-	u8 vnext;
-	u8 hflow;
-
-	u8 fillc;
-	u8 ochar;
-	u8 omask;
-
-	u8 filler7;
-	u8 filler8[28];
-}; 
-
-
-#define SRXLWATER      0xE0
-#define SRXHWATER      0xE1
-#define STOUT          0xE2
-#define PAUSETX        0xE3
-#define RESUMETX       0xE4
-#define SAUXONOFFC     0xE6
-#define SENDBREAK      0xE8
-#define SETMODEM       0xE9
-#define SETIFLAGS      0xEA
-#define SONOFFC        0xEB
-#define STXLWATER      0xEC
-#define PAUSERX        0xEE
-#define RESUMERX       0xEF
-#define SETBUFFER      0xF2
-#define SETCOOKED      0xF3
-#define SETHFLOW       0xF4
-#define SETCTRLFLAGS   0xF5
-#define SETVNEXT       0xF6
-
-
-
-#define BREAK_IND        0x01
-#define LOWTX_IND        0x02
-#define EMPTYTX_IND      0x04
-#define DATA_IND         0x08
-#define MODEMCHG_IND     0x20
-
-#define FEP_HUPCL  0002000
-#if 0
-#define RTS   0x02
-#define CD    0x08
-#define DSR   0x10
-#define CTS   0x20
-#define RI    0x40
-#define DTR   0x80
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/digiPCI.h linux-libre-2.6.39-gnu/drivers/char/digiPCI.h
--- linux-libre-2.6.38-gnu/drivers/char/digiPCI.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/digiPCI.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-/*************************************************************************
- * Defines and structure definitions for PCI BIOS Interface 
- *************************************************************************/
-#define	PCIMAX  32		/* maximum number of PCI boards */
-
-
-#define	PCI_VENDOR_DIGI		0x114F
-#define	PCI_DEVICE_EPC		0x0002
-#define	PCI_DEVICE_RIGHTSWITCH 0x0003  /* For testing */
-#define	PCI_DEVICE_XEM		0x0004
-#define	PCI_DEVICE_XR		0x0005
-#define	PCI_DEVICE_CX		0x0006
-#define	PCI_DEVICE_XRJ		0x0009   /* Jupiter boards with */
-#define	PCI_DEVICE_EPCJ		0x000a   /* PLX 9060 chip for PCI  */
-
-
-/*
- * On the PCI boards, there is no IO space allocated 
- * The I/O registers will be in the first 3 bytes of the   
- * upper 2MB of the 4MB memory space.  The board memory 
- * will be mapped into the low 2MB of the 4MB memory space 
- */
-
-/* Potential location of PCI Bios from E0000 to FFFFF*/
-#define PCI_BIOS_SIZE		0x00020000	
-
-/* Size of Memory and I/O for PCI (4MB) */
-#define PCI_RAM_SIZE		0x00400000	
-
-/* Size of Memory (2MB) */
-#define PCI_MEM_SIZE		0x00200000	
-
-/* Offset of I/0 in Memory (2MB) */
-#define PCI_IO_OFFSET 		0x00200000	
-
-#define MEMOUTB(basemem, pnum, setmemval)  *(caddr_t)((basemem) + ( PCI_IO_OFFSET | pnum << 4 | pnum )) = (setmemval)
-#define MEMINB(basemem, pnum)  *(caddr_t)((basemem) + (PCI_IO_OFFSET | pnum << 4 | pnum ))   /* for PCI I/O */
-
-
-
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/epca.c linux-libre-2.6.39-gnu/drivers/char/epca.c
--- linux-libre-2.6.38-gnu/drivers/char/epca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/epca.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2784 +0,0 @@
-/*
-	Copyright (C) 1996  Digi International.
-
-	For technical support please email digiLinux@dgii.com or
-	call Digi tech support at (612) 912-3456
-
-	** This driver is no longer supported by Digi **
-
-	Much of this design and code came from epca.c which was
-	copyright (C) 1994, 1995 Troy De Jongh, and subsquently
-	modified by David Nugent, Christoph Lameter, Mike McLagan.
-
-	This program is free software; you can redistribute it and/or modify
-	it under the terms of the 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.
-*/
-/* See README.epca for change history --DAT*/
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/types.h>
-#include <linux/init.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/slab.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <linux/pci.h>
-#include "digiPCI.h"
-
-
-#include "digi1.h"
-#include "digiFep1.h"
-#include "epca.h"
-#include "epcaconfig.h"
-
-#define VERSION            "1.3.0.1-LK2.6"
-
-/* This major needs to be submitted to Linux to join the majors list */
-#define DIGIINFOMAJOR       35  /* For Digi specific ioctl */
-
-
-#define MAXCARDS 7
-#define epcaassert(x, msg)  if (!(x)) epca_error(__LINE__, msg)
-
-#define PFX "epca: "
-
-static int nbdevs, num_cards, liloconfig;
-static int digi_poller_inhibited = 1 ;
-
-static int setup_error_code;
-static int invalid_lilo_config;
-
-/*
- * The ISA boards do window flipping into the same spaces so its only sane with
- * a single lock. It's still pretty efficient. This lock guards the hardware
- * and the tty_port lock guards the kernel side stuff like use counts. Take
- * this lock inside the port lock if you must take both.
- */
-static DEFINE_SPINLOCK(epca_lock);
-
-/* MAXBOARDS is typically 12, but ISA and EISA cards are restricted
-   to 7 below. */
-static struct board_info boards[MAXBOARDS];
-
-static struct tty_driver *pc_driver;
-static struct tty_driver *pc_info;
-
-/* ------------------ Begin Digi specific structures -------------------- */
-
-/*
- * digi_channels represents an array of structures that keep track of each
- * channel of the Digi product. Information such as transmit and receive
- * pointers, termio data, and signal definitions (DTR, CTS, etc ...) are stored
- * here. This structure is NOT used to overlay the cards physical channel
- * structure.
- */
-static struct channel digi_channels[MAX_ALLOC];
-
-/*
- * card_ptr is an array used to hold the address of the first channel structure
- * of each card. This array will hold the addresses of various channels located
- * in digi_channels.
- */
-static struct channel *card_ptr[MAXCARDS];
-
-static struct timer_list epca_timer;
-
-/*
- * Begin generic memory functions. These functions will be alias (point at)
- * more specific functions dependent on the board being configured.
- */
-static void memwinon(struct board_info *b, unsigned int win);
-static void memwinoff(struct board_info *b, unsigned int win);
-static void globalwinon(struct channel *ch);
-static void rxwinon(struct channel *ch);
-static void txwinon(struct channel *ch);
-static void memoff(struct channel *ch);
-static void assertgwinon(struct channel *ch);
-static void assertmemoff(struct channel *ch);
-
-/* ---- Begin more 'specific' memory functions for cx_like products --- */
-
-static void pcxem_memwinon(struct board_info *b, unsigned int win);
-static void pcxem_memwinoff(struct board_info *b, unsigned int win);
-static void pcxem_globalwinon(struct channel *ch);
-static void pcxem_rxwinon(struct channel *ch);
-static void pcxem_txwinon(struct channel *ch);
-static void pcxem_memoff(struct channel *ch);
-
-/* ------ Begin more 'specific' memory functions for the pcxe ------- */
-
-static void pcxe_memwinon(struct board_info *b, unsigned int win);
-static void pcxe_memwinoff(struct board_info *b, unsigned int win);
-static void pcxe_globalwinon(struct channel *ch);
-static void pcxe_rxwinon(struct channel *ch);
-static void pcxe_txwinon(struct channel *ch);
-static void pcxe_memoff(struct channel *ch);
-
-/* ---- Begin more 'specific' memory functions for the pc64xe and pcxi ---- */
-/* Note : pc64xe and pcxi share the same windowing routines */
-
-static void pcxi_memwinon(struct board_info *b, unsigned int win);
-static void pcxi_memwinoff(struct board_info *b, unsigned int win);
-static void pcxi_globalwinon(struct channel *ch);
-static void pcxi_rxwinon(struct channel *ch);
-static void pcxi_txwinon(struct channel *ch);
-static void pcxi_memoff(struct channel *ch);
-
-/* - Begin 'specific' do nothing memory functions needed for some cards - */
-
-static void dummy_memwinon(struct board_info *b, unsigned int win);
-static void dummy_memwinoff(struct board_info *b, unsigned int win);
-static void dummy_globalwinon(struct channel *ch);
-static void dummy_rxwinon(struct channel *ch);
-static void dummy_txwinon(struct channel *ch);
-static void dummy_memoff(struct channel *ch);
-static void dummy_assertgwinon(struct channel *ch);
-static void dummy_assertmemoff(struct channel *ch);
-
-static struct channel *verifyChannel(struct tty_struct *);
-static void pc_sched_event(struct channel *, int);
-static void epca_error(int, char *);
-static void pc_close(struct tty_struct *, struct file *);
-static void shutdown(struct channel *, struct tty_struct *tty);
-static void pc_hangup(struct tty_struct *);
-static int pc_write_room(struct tty_struct *);
-static int pc_chars_in_buffer(struct tty_struct *);
-static void pc_flush_buffer(struct tty_struct *);
-static void pc_flush_chars(struct tty_struct *);
-static int pc_open(struct tty_struct *, struct file *);
-static void post_fep_init(unsigned int crd);
-static void epcapoll(unsigned long);
-static void doevent(int);
-static void fepcmd(struct channel *, int, int, int, int, int);
-static unsigned termios2digi_h(struct channel *ch, unsigned);
-static unsigned termios2digi_i(struct channel *ch, unsigned);
-static unsigned termios2digi_c(struct channel *ch, unsigned);
-static void epcaparam(struct tty_struct *, struct channel *);
-static void receive_data(struct channel *, struct tty_struct *tty);
-static int pc_ioctl(struct tty_struct *, struct file *,
-			unsigned int, unsigned long);
-static int info_ioctl(struct tty_struct *, struct file *,
-			unsigned int, unsigned long);
-static void pc_set_termios(struct tty_struct *, struct ktermios *);
-static void do_softint(struct work_struct *work);
-static void pc_stop(struct tty_struct *);
-static void pc_start(struct tty_struct *);
-static void pc_throttle(struct tty_struct *tty);
-static void pc_unthrottle(struct tty_struct *tty);
-static int pc_send_break(struct tty_struct *tty, int msec);
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch);
-
-static int pc_write(struct tty_struct *, const unsigned char *, int);
-static int pc_init(void);
-static int init_PCI(void);
-
-/*
- * Table of functions for each board to handle memory. Mantaining parallelism
- * is a *very* good idea here. The idea is for the runtime code to blindly call
- * these functions, not knowing/caring about the underlying hardware. This
- * stuff should contain no conditionals; if more functionality is needed a
- * different entry should be established. These calls are the interface calls
- * and are the only functions that should be accessed. Anyone caught making
- * direct calls deserves what they get.
- */
-static void memwinon(struct board_info *b, unsigned int win)
-{
-	b->memwinon(b, win);
-}
-
-static void memwinoff(struct board_info *b, unsigned int win)
-{
-	b->memwinoff(b, win);
-}
-
-static void globalwinon(struct channel *ch)
-{
-	ch->board->globalwinon(ch);
-}
-
-static void rxwinon(struct channel *ch)
-{
-	ch->board->rxwinon(ch);
-}
-
-static void txwinon(struct channel *ch)
-{
-	ch->board->txwinon(ch);
-}
-
-static void memoff(struct channel *ch)
-{
-	ch->board->memoff(ch);
-}
-static void assertgwinon(struct channel *ch)
-{
-	ch->board->assertgwinon(ch);
-}
-
-static void assertmemoff(struct channel *ch)
-{
-	ch->board->assertmemoff(ch);
-}
-
-/* PCXEM windowing is the same as that used in the PCXR and CX series cards. */
-static void pcxem_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(FEPWIN | win, b->port + 1);
-}
-
-static void pcxem_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(0, b->port + 1);
-}
-
-static void pcxem_globalwinon(struct channel *ch)
-{
-	outb_p(FEPWIN, (int)ch->board->port + 1);
-}
-
-static void pcxem_rxwinon(struct channel *ch)
-{
-	outb_p(ch->rxwin, (int)ch->board->port + 1);
-}
-
-static void pcxem_txwinon(struct channel *ch)
-{
-	outb_p(ch->txwin, (int)ch->board->port + 1);
-}
-
-static void pcxem_memoff(struct channel *ch)
-{
-	outb_p(0, (int)ch->board->port + 1);
-}
-
-/* ----------------- Begin pcxe memory window stuff ------------------ */
-static void pcxe_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(FEPWIN | win, b->port + 1);
-}
-
-static void pcxe_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) & ~FEPMEM, b->port + 1);
-	outb_p(0, b->port + 1);
-}
-
-static void pcxe_globalwinon(struct channel *ch)
-{
-	outb_p(FEPWIN, (int)ch->board->port + 1);
-}
-
-static void pcxe_rxwinon(struct channel *ch)
-{
-	outb_p(ch->rxwin, (int)ch->board->port + 1);
-}
-
-static void pcxe_txwinon(struct channel *ch)
-{
-	outb_p(ch->txwin, (int)ch->board->port + 1);
-}
-
-static void pcxe_memoff(struct channel *ch)
-{
-	outb_p(0, (int)ch->board->port);
-	outb_p(0, (int)ch->board->port + 1);
-}
-
-/* ------------- Begin pc64xe and pcxi memory window stuff -------------- */
-static void pcxi_memwinon(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) | FEPMEM, b->port);
-}
-
-static void pcxi_memwinoff(struct board_info *b, unsigned int win)
-{
-	outb_p(inb(b->port) & ~FEPMEM, b->port);
-}
-
-static void pcxi_globalwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_rxwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_txwinon(struct channel *ch)
-{
-	outb_p(FEPMEM, ch->board->port);
-}
-
-static void pcxi_memoff(struct channel *ch)
-{
-	outb_p(0, ch->board->port);
-}
-
-static void pcxi_assertgwinon(struct channel *ch)
-{
-	epcaassert(inb(ch->board->port) & FEPMEM, "Global memory off");
-}
-
-static void pcxi_assertmemoff(struct channel *ch)
-{
-	epcaassert(!(inb(ch->board->port) & FEPMEM), "Memory on");
-}
-
-/*
- * Not all of the cards need specific memory windowing routines. Some cards
- * (Such as PCI) needs no windowing routines at all. We provide these do
- * nothing routines so that the same code base can be used. The driver will
- * ALWAYS call a windowing routine if it thinks it needs to; regardless of the
- * card. However, dependent on the card the routine may or may not do anything.
- */
-static void dummy_memwinon(struct board_info *b, unsigned int win)
-{
-}
-
-static void dummy_memwinoff(struct board_info *b, unsigned int win)
-{
-}
-
-static void dummy_globalwinon(struct channel *ch)
-{
-}
-
-static void dummy_rxwinon(struct channel *ch)
-{
-}
-
-static void dummy_txwinon(struct channel *ch)
-{
-}
-
-static void dummy_memoff(struct channel *ch)
-{
-}
-
-static void dummy_assertgwinon(struct channel *ch)
-{
-}
-
-static void dummy_assertmemoff(struct channel *ch)
-{
-}
-
-static struct channel *verifyChannel(struct tty_struct *tty)
-{
-	/*
-	 * This routine basically provides a sanity check. It insures that the
-	 * channel returned is within the proper range of addresses as well as
-	 * properly initialized. If some bogus info gets passed in
-	 * through tty->driver_data this should catch it.
-	 */
-	if (tty) {
-		struct channel *ch = tty->driver_data;
-		if (ch >= &digi_channels[0] && ch < &digi_channels[nbdevs]) {
-			if (ch->magic == EPCA_MAGIC)
-				return ch;
-		}
-	}
-	return NULL;
-}
-
-static void pc_sched_event(struct channel *ch, int event)
-{
-	/*
-	 * We call this to schedule interrupt processing on some event. The
-	 * kernel sees our request and calls the related routine in OUR driver.
-	 */
-	ch->event |= 1 << event;
-	schedule_work(&ch->tqueue);
-}
-
-static void epca_error(int line, char *msg)
-{
-	printk(KERN_ERR "epca_error (Digi): line = %d %s\n", line, msg);
-}
-
-static void pc_close(struct tty_struct *tty, struct file *filp)
-{
-	struct channel *ch;
-	struct tty_port *port;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return;
-	port = &ch->port;
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-
-	pc_flush_buffer(tty);
-	shutdown(ch, tty);
-
-	tty_port_close_end(port, tty);
-	ch->event = 0;	/* FIXME: review ch->event locking */
-	tty_port_tty_set(port, NULL);
-}
-
-static void shutdown(struct channel *ch, struct tty_struct *tty)
-{
-	unsigned long flags;
-	struct board_chan __iomem *bc;
-	struct tty_port *port = &ch->port;
-
-	if (!(port->flags & ASYNC_INITIALIZED))
-		return;
-
-	spin_lock_irqsave(&epca_lock, flags);
-
-	globalwinon(ch);
-	bc = ch->brdchan;
-
-	/*
-	 * In order for an event to be generated on the receipt of data the
-	 * idata flag must be set. Since we are shutting down, this is not
-	 * necessary clear this flag.
-	 */
-	if (bc)
-		writeb(0, &bc->idata);
-
-	/* If we're a modem control device and HUPCL is on, drop RTS & DTR. */
-	if (tty->termios->c_cflag & HUPCL)  {
-		ch->omodem &= ~(ch->m_rts | ch->m_dtr);
-		fepcmd(ch, SETMODEM, 0, ch->m_dtr | ch->m_rts, 10, 1);
-	}
-	memoff(ch);
-
-	/*
-	 * The channel has officialy been closed. The next time it is opened it
-	 * will have to reinitialized. Set a flag to indicate this.
-	 */
-	/* Prevent future Digi programmed interrupts from coming active */
-	port->flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&epca_lock, flags);
-}
-
-static void pc_hangup(struct tty_struct *tty)
-{
-	struct channel *ch;
-
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		pc_flush_buffer(tty);
-		tty_ldisc_flush(tty);
-		shutdown(ch, tty);
-
-		ch->event = 0;	/* FIXME: review locking of ch->event */
-		tty_port_hangup(&ch->port);
-	}
-}
-
-static int pc_write(struct tty_struct *tty,
-			const unsigned char *buf, int bytesAvailable)
-{
-	unsigned int head, tail;
-	int dataLen;
-	int size;
-	int amountCopied;
-	struct channel *ch;
-	unsigned long flags;
-	int remain;
-	struct board_chan __iomem *bc;
-
-	/*
-	 * pc_write is primarily called directly by the kernel routine
-	 * tty_write (Though it can also be called by put_char) found in
-	 * tty_io.c. pc_write is passed a line discipline buffer where the data
-	 * to be written out is stored. The line discipline implementation
-	 * itself is done at the kernel level and is not brought into the
-	 * driver.
-	 */
-
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return 0;
-
-	/* Make a pointer to the channel data structure found on the board. */
-	bc   = ch->brdchan;
-	size = ch->txbufsize;
-	amountCopied = 0;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-
-	head = readw(&bc->tin) & (size - 1);
-	tail = readw(&bc->tout);
-
-	if (tail != readw(&bc->tout))
-		tail = readw(&bc->tout);
-	tail &= (size - 1);
-
-	if (head >= tail) {
-		/* head has not wrapped */
-		/*
-		 * remain (much like dataLen above) represents the total amount
-		 * of space available on the card for data. Here dataLen
-		 * represents the space existing between the head pointer and
-		 * the end of buffer. This is important because a memcpy cannot
-		 * be told to automatically wrap around when it hits the buffer
-		 * end.
-		 */
-		dataLen = size - head;
-		remain = size - (head - tail) - 1;
-	} else {
-		/* head has wrapped around */
-		remain = tail - head - 1;
-		dataLen = remain;
-	}
-	/*
-	 * Check the space on the card. If we have more data than space; reduce
-	 * the amount of data to fit the space.
-	 */
-	bytesAvailable = min(remain, bytesAvailable);
-	txwinon(ch);
-	while (bytesAvailable > 0) {
-		/* there is data to copy onto card */
-
-		/*
-		 * If head is not wrapped, the below will make sure the first
-		 * data copy fills to the end of card buffer.
-		 */
-		dataLen = min(bytesAvailable, dataLen);
-		memcpy_toio(ch->txptr + head, buf, dataLen);
-		buf += dataLen;
-		head += dataLen;
-		amountCopied += dataLen;
-		bytesAvailable -= dataLen;
-
-		if (head >= size) {
-			head = 0;
-			dataLen = tail;
-		}
-	}
-	ch->statusflags |= TXBUSY;
-	globalwinon(ch);
-	writew(head, &bc->tin);
-
-	if ((ch->statusflags & LOWWAIT) == 0)  {
-		ch->statusflags |= LOWWAIT;
-		writeb(1, &bc->ilow);
-	}
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return amountCopied;
-}
-
-static int pc_write_room(struct tty_struct *tty)
-{
-	int remain = 0;
-	struct channel *ch;
-	unsigned long flags;
-	unsigned int head, tail;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-
-		bc   = ch->brdchan;
-		head = readw(&bc->tin) & (ch->txbufsize - 1);
-		tail = readw(&bc->tout);
-
-		if (tail != readw(&bc->tout))
-			tail = readw(&bc->tout);
-		/* Wrap tail if necessary */
-		tail &= (ch->txbufsize - 1);
-		remain = tail - head - 1;
-		if (remain < 0)
-			remain += ch->txbufsize;
-
-		if (remain && (ch->statusflags & LOWWAIT) == 0) {
-			ch->statusflags |= LOWWAIT;
-			writeb(1, &bc->ilow);
-		}
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-	/* Return how much room is left on card */
-	return remain;
-}
-
-static int pc_chars_in_buffer(struct tty_struct *tty)
-{
-	int chars;
-	unsigned int ctail, head, tail;
-	int remain;
-	unsigned long flags;
-	struct channel *ch;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return 0;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-
-	bc = ch->brdchan;
-	tail = readw(&bc->tout);
-	head = readw(&bc->tin);
-	ctail = readw(&ch->mailbox->cout);
-
-	if (tail == head && readw(&ch->mailbox->cin) == ctail &&
-						readb(&bc->tbusy) == 0)
-		chars = 0;
-	else  { /* Begin if some space on the card has been used */
-		head = readw(&bc->tin) & (ch->txbufsize - 1);
-		tail &= (ch->txbufsize - 1);
-		/*
-		 * The logic here is basically opposite of the above
-		 * pc_write_room here we are finding the amount of bytes in the
-		 * buffer filled. Not the amount of bytes empty.
-		 */
-		remain = tail - head - 1;
-		if (remain < 0)
-			remain += ch->txbufsize;
-		chars = (int)(ch->txbufsize - remain);
-		/*
-		 * Make it possible to wakeup anything waiting for output in
-		 * tty_ioctl.c, etc.
-		 *
-		 * If not already set. Setup an event to indicate when the
-		 * transmit buffer empties.
-		 */
-		if (!(ch->statusflags & EMPTYWAIT))
-			setup_empty_event(tty, ch);
-	} /* End if some space on the card has been used */
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	/* Return number of characters residing on card. */
-	return chars;
-}
-
-static void pc_flush_buffer(struct tty_struct *tty)
-{
-	unsigned int tail;
-	unsigned long flags;
-	struct channel *ch;
-	struct board_chan __iomem *bc;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch == NULL)
-		return;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	bc   = ch->brdchan;
-	tail = readw(&bc->tout);
-	/* Have FEP move tout pointer; effectively flushing transmit buffer */
-	fepcmd(ch, STOUT, (unsigned) tail, 0, 0, 0);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	tty_wakeup(tty);
-}
-
-static void pc_flush_chars(struct tty_struct *tty)
-{
-	struct channel *ch;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&epca_lock, flags);
-		/*
-		 * If not already set and the transmitter is busy setup an
-		 * event to indicate when the transmit empties.
-		 */
-		if ((ch->statusflags & TXBUSY) &&
-				!(ch->statusflags & EMPTYWAIT))
-			setup_empty_event(tty, ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static int epca_carrier_raised(struct tty_port *port)
-{
-	struct channel *ch = container_of(port, struct channel, port);
-	if (ch->imodem & ch->dcd)
-		return 1;
-	return 0;
-}
-
-static void epca_dtr_rts(struct tty_port *port, int onoff)
-{
-}
-
-static int pc_open(struct tty_struct *tty, struct file *filp)
-{
-	struct channel *ch;
-	struct tty_port *port;
-	unsigned long flags;
-	int line, retval, boardnum;
-	struct board_chan __iomem *bc;
-	unsigned int head;
-
-	line = tty->index;
-	if (line < 0 || line >= nbdevs)
-		return -ENODEV;
-
-	ch = &digi_channels[line];
-	port = &ch->port;
-	boardnum = ch->boardnum;
-
-	/* Check status of board configured in system.  */
-
-	/*
-	 * I check to see if the epca_setup routine detected a user error. It
-	 * might be better to put this in pc_init, but for the moment it goes
-	 * here.
-	 */
-	if (invalid_lilo_config) {
-		if (setup_error_code & INVALID_BOARD_TYPE)
-			printk(KERN_ERR "epca: pc_open: Invalid board type specified in kernel options.\n");
-		if (setup_error_code & INVALID_NUM_PORTS)
-			printk(KERN_ERR "epca: pc_open: Invalid number of ports specified in kernel options.\n");
-		if (setup_error_code & INVALID_MEM_BASE)
-			printk(KERN_ERR "epca: pc_open: Invalid board memory address specified in kernel options.\n");
-		if (setup_error_code & INVALID_PORT_BASE)
-			printk(KERN_ERR "epca; pc_open: Invalid board port address specified in kernel options.\n");
-		if (setup_error_code & INVALID_BOARD_STATUS)
-			printk(KERN_ERR "epca: pc_open: Invalid board status specified in kernel options.\n");
-		if (setup_error_code & INVALID_ALTPIN)
-			printk(KERN_ERR "epca: pc_open: Invalid board altpin specified in kernel options;\n");
-		tty->driver_data = NULL;   /* Mark this device as 'down' */
-		return -ENODEV;
-	}
-	if (boardnum >= num_cards || boards[boardnum].status == DISABLED)  {
-		tty->driver_data = NULL;   /* Mark this device as 'down' */
-		return(-ENODEV);
-	}
-
-	bc = ch->brdchan;
-	if (bc == NULL) {
-		tty->driver_data = NULL;
-		return -ENODEV;
-	}
-
-	spin_lock_irqsave(&port->lock, flags);
-	/*
-	 * Every time a channel is opened, increment a counter. This is
-	 * necessary because we do not wish to flush and shutdown the channel
-	 * until the last app holding the channel open, closes it.
-	 */
-	port->count++;
-	/*
-	 * Set a kernel structures pointer to our local channel structure. This
-	 * way we can get to it when passed only a tty struct.
-	 */
-	tty->driver_data = ch;
-	port->tty = tty;
-	/*
-	 * If this is the first time the channel has been opened, initialize
-	 * the tty->termios struct otherwise let pc_close handle it.
-	 */
-	spin_lock(&epca_lock);
-	globalwinon(ch);
-	ch->statusflags = 0;
-
-	/* Save boards current modem status */
-	ch->imodem = readb(&bc->mstat);
-
-	/*
-	 * Set receive head and tail ptrs to each other. This indicates no data
-	 * available to read.
-	 */
-	head = readw(&bc->rin);
-	writew(head, &bc->rout);
-
-	/* Set the channels associated tty structure */
-
-	/*
-	 * The below routine generally sets up parity, baud, flow control
-	 * issues, etc.... It effect both control flags and input flags.
-	 */
-	epcaparam(tty, ch);
-	memoff(ch);
-	spin_unlock(&epca_lock);
-	port->flags |= ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	retval = tty_port_block_til_ready(port, tty, filp);
-	if (retval)
-		return retval;
-	/*
-	 * Set this again in case a hangup set it to zero while this open() was
-	 * waiting for the line...
-	 */
-	spin_lock_irqsave(&port->lock, flags);
-	port->tty = tty;
-	spin_lock(&epca_lock);
-	globalwinon(ch);
-	/* Enable Digi Data events */
-	writeb(1, &bc->idata);
-	memoff(ch);
-	spin_unlock(&epca_lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	return 0;
-}
-
-static int __init epca_module_init(void)
-{
-	return pc_init();
-}
-module_init(epca_module_init);
-
-static struct pci_driver epca_driver;
-
-static void __exit epca_module_exit(void)
-{
-	int               count, crd;
-	struct board_info *bd;
-	struct channel    *ch;
-
-	del_timer_sync(&epca_timer);
-
-	if (tty_unregister_driver(pc_driver) ||
-				tty_unregister_driver(pc_info)) {
-		printk(KERN_WARNING "epca: cleanup_module failed to un-register tty driver\n");
-		return;
-	}
-	put_tty_driver(pc_driver);
-	put_tty_driver(pc_info);
-
-	for (crd = 0; crd < num_cards; crd++) {
-		bd = &boards[crd];
-		if (!bd) { /* sanity check */
-			printk(KERN_ERR "<Error> - Digi : cleanup_module failed\n");
-			return;
-		}
-		ch = card_ptr[crd];
-		for (count = 0; count < bd->numports; count++, ch++) {
-			struct tty_struct *tty = tty_port_tty_get(&ch->port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-		}
-	}
-	pci_unregister_driver(&epca_driver);
-}
-module_exit(epca_module_exit);
-
-static const struct tty_operations pc_ops = {
-	.open = pc_open,
-	.close = pc_close,
-	.write = pc_write,
-	.write_room = pc_write_room,
-	.flush_buffer = pc_flush_buffer,
-	.chars_in_buffer = pc_chars_in_buffer,
-	.flush_chars = pc_flush_chars,
-	.ioctl = pc_ioctl,
-	.set_termios = pc_set_termios,
-	.stop = pc_stop,
-	.start = pc_start,
-	.throttle = pc_throttle,
-	.unthrottle = pc_unthrottle,
-	.hangup = pc_hangup,
-	.break_ctl = pc_send_break
-};
-
-static const struct tty_port_operations epca_port_ops = {
-	.carrier_raised = epca_carrier_raised,
-	.dtr_rts = epca_dtr_rts,
-};
-
-static int info_open(struct tty_struct *tty, struct file *filp)
-{
-	return 0;
-}
-
-static const struct tty_operations info_ops = {
-	.open = info_open,
-	.ioctl = info_ioctl,
-};
-
-static int __init pc_init(void)
-{
-	int crd;
-	struct board_info *bd;
-	unsigned char board_id = 0;
-	int err = -ENOMEM;
-
-	int pci_boards_found, pci_count;
-
-	pci_count = 0;
-
-	pc_driver = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_driver)
-		goto out1;
-
-	pc_info = alloc_tty_driver(MAX_ALLOC);
-	if (!pc_info)
-		goto out2;
-
-	/*
-	 * If epca_setup has not been ran by LILO set num_cards to defaults;
-	 * copy board structure defined by digiConfig into drivers board
-	 * structure. Note : If LILO has ran epca_setup then epca_setup will
-	 * handle defining num_cards as well as copying the data into the board
-	 * structure.
-	 */
-	if (!liloconfig) {
-		/* driver has been configured via. epcaconfig */
-		nbdevs = NBDEVS;
-		num_cards = NUMCARDS;
-		memcpy(&boards, &static_boards,
-		       sizeof(struct board_info) * NUMCARDS);
-	}
-
-	/*
-	 * Note : If lilo was used to configure the driver and the ignore
-	 * epcaconfig option was choosen (digiepca=2) then nbdevs and num_cards
-	 * will equal 0 at this point. This is okay; PCI cards will still be
-	 * picked up if detected.
-	 */
-
-	/*
-	 * Set up interrupt, we will worry about memory allocation in
-	 * post_fep_init.
-	 */
-	printk(KERN_INFO "DIGI epca driver version %s loaded.\n", VERSION);
-
-	/*
-	 * NOTE : This code assumes that the number of ports found in the
-	 * boards array is correct. This could be wrong if the card in question
-	 * is PCI (And therefore has no ports entry in the boards structure.)
-	 * The rest of the information will be valid for PCI because the
-	 * beginning of pc_init scans for PCI and determines i/o and base
-	 * memory addresses. I am not sure if it is possible to read the number
-	 * of ports supported by the card prior to it being booted (Since that
-	 * is the state it is in when pc_init is run). Because it is not
-	 * possible to query the number of supported ports until after the card
-	 * has booted; we are required to calculate the card_ptrs as the card
-	 * is initialized (Inside post_fep_init). The negative thing about this
-	 * approach is that digiDload's call to GET_INFO will have a bad port
-	 * value. (Since this is called prior to post_fep_init.)
-	 */
-	pci_boards_found = 0;
-	if (num_cards < MAXBOARDS)
-		pci_boards_found += init_PCI();
-	num_cards += pci_boards_found;
-
-	pc_driver->owner = THIS_MODULE;
-	pc_driver->name = "ttyD";
-	pc_driver->major = DIGI_MAJOR;
-	pc_driver->minor_start = 0;
-	pc_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	pc_driver->subtype = SERIAL_TYPE_NORMAL;
-	pc_driver->init_termios = tty_std_termios;
-	pc_driver->init_termios.c_iflag = 0;
-	pc_driver->init_termios.c_oflag = 0;
-	pc_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	pc_driver->init_termios.c_lflag = 0;
-	pc_driver->init_termios.c_ispeed = 9600;
-	pc_driver->init_termios.c_ospeed = 9600;
-	pc_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(pc_driver, &pc_ops);
-
-	pc_info->owner = THIS_MODULE;
-	pc_info->name = "digi_ctl";
-	pc_info->major = DIGIINFOMAJOR;
-	pc_info->minor_start = 0;
-	pc_info->type = TTY_DRIVER_TYPE_SERIAL;
-	pc_info->subtype = SERIAL_TYPE_INFO;
-	pc_info->init_termios = tty_std_termios;
-	pc_info->init_termios.c_iflag = 0;
-	pc_info->init_termios.c_oflag = 0;
-	pc_info->init_termios.c_lflag = 0;
-	pc_info->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL;
-	pc_info->init_termios.c_ispeed = 9600;
-	pc_info->init_termios.c_ospeed = 9600;
-	pc_info->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(pc_info, &info_ops);
-
-
-	for (crd = 0; crd < num_cards; crd++) {
-		/*
-		 * This is where the appropriate memory handlers for the
-		 * hardware is set. Everything at runtime blindly jumps through
-		 * these vectors.
-		 */
-
-		/* defined in epcaconfig.h */
-		bd = &boards[crd];
-
-		switch (bd->type) {
-		case PCXEM:
-		case EISAXEM:
-			bd->memwinon     = pcxem_memwinon;
-			bd->memwinoff    = pcxem_memwinoff;
-			bd->globalwinon  = pcxem_globalwinon;
-			bd->txwinon      = pcxem_txwinon;
-			bd->rxwinon      = pcxem_rxwinon;
-			bd->memoff       = pcxem_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			bd->memwinon     = dummy_memwinon;
-			bd->memwinoff    = dummy_memwinoff;
-			bd->globalwinon  = dummy_globalwinon;
-			bd->txwinon      = dummy_txwinon;
-			bd->rxwinon      = dummy_rxwinon;
-			bd->memoff       = dummy_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCXE:
-		case PCXEVE:
-			bd->memwinon     = pcxe_memwinon;
-			bd->memwinoff    = pcxe_memwinoff;
-			bd->globalwinon  = pcxe_globalwinon;
-			bd->txwinon      = pcxe_txwinon;
-			bd->rxwinon      = pcxe_rxwinon;
-			bd->memoff       = pcxe_memoff;
-			bd->assertgwinon = dummy_assertgwinon;
-			bd->assertmemoff = dummy_assertmemoff;
-			break;
-
-		case PCXI:
-		case PC64XE:
-			bd->memwinon     = pcxi_memwinon;
-			bd->memwinoff    = pcxi_memwinoff;
-			bd->globalwinon  = pcxi_globalwinon;
-			bd->txwinon      = pcxi_txwinon;
-			bd->rxwinon      = pcxi_rxwinon;
-			bd->memoff       = pcxi_memoff;
-			bd->assertgwinon = pcxi_assertgwinon;
-			bd->assertmemoff = pcxi_assertmemoff;
-			break;
-
-		default:
-			break;
-		}
-
-		/*
-		 * Some cards need a memory segment to be defined for use in
-		 * transmit and receive windowing operations. These boards are
-		 * listed in the below switch. In the case of the XI the amount
-		 * of memory on the board is variable so the memory_seg is also
-		 * variable. This code determines what they segment should be.
-		 */
-		switch (bd->type) {
-		case PCXE:
-		case PCXEVE:
-		case PC64XE:
-			bd->memory_seg = 0xf000;
-			break;
-
-		case PCXI:
-			board_id = inb((int)bd->port);
-			if ((board_id & 0x1) == 0x1) {
-				/* it's an XI card */
-				/* Is it a 64K board */
-				if ((board_id & 0x30) == 0)
-					bd->memory_seg = 0xf000;
-
-				/* Is it a 128K board */
-				if ((board_id & 0x30) == 0x10)
-					bd->memory_seg = 0xe000;
-
-				/* Is is a 256K board */
-				if ((board_id & 0x30) == 0x20)
-					bd->memory_seg = 0xc000;
-
-				/* Is it a 512K board */
-				if ((board_id & 0x30) == 0x30)
-					bd->memory_seg = 0x8000;
-			} else
-				printk(KERN_ERR "epca: Board at 0x%x doesn't appear to be an XI\n", (int)bd->port);
-			break;
-		}
-	}
-
-	err = tty_register_driver(pc_driver);
-	if (err) {
-		printk(KERN_ERR "Couldn't register Digi PC/ driver");
-		goto out3;
-	}
-
-	err = tty_register_driver(pc_info);
-	if (err) {
-		printk(KERN_ERR "Couldn't register Digi PC/ info ");
-		goto out4;
-	}
-
-	/* Start up the poller to check for events on all enabled boards */
-	init_timer(&epca_timer);
-	epca_timer.function = epcapoll;
-	mod_timer(&epca_timer, jiffies + HZ/25);
-	return 0;
-
-out4:
-	tty_unregister_driver(pc_driver);
-out3:
-	put_tty_driver(pc_info);
-out2:
-	put_tty_driver(pc_driver);
-out1:
-	return err;
-}
-
-static void post_fep_init(unsigned int crd)
-{
-	int i;
-	void __iomem *memaddr;
-	struct global_data __iomem *gd;
-	struct board_info *bd;
-	struct board_chan __iomem *bc;
-	struct channel *ch;
-	int shrinkmem = 0, lowwater;
-
-	/*
-	 * This call is made by the user via. the ioctl call DIGI_INIT. It is
-	 * responsible for setting up all the card specific stuff.
-	 */
-	bd = &boards[crd];
-
-	/*
-	 * If this is a PCI board, get the port info. Remember PCI cards do not
-	 * have entries into the epcaconfig.h file, so we can't get the number
-	 * of ports from it. Unfortunetly, this means that anyone doing a
-	 * DIGI_GETINFO before the board has booted will get an invalid number
-	 * of ports returned (It should return 0). Calls to DIGI_GETINFO after
-	 * DIGI_INIT has been called will return the proper values.
-	 */
-	if (bd->type >= PCIXEM) { /* Begin get PCI number of ports */
-		/*
-		 * Below we use XEMPORTS as a memory offset regardless of which
-		 * PCI card it is. This is because all of the supported PCI
-		 * cards have the same memory offset for the channel data. This
-		 * will have to be changed if we ever develop a PCI/XE card.
-		 * NOTE : The FEP manual states that the port offset is 0xC22
-		 * as opposed to 0xC02. This is only true for PC/XE, and PC/XI
-		 * cards; not for the XEM, or CX series. On the PCI cards the
-		 * number of ports is determined by reading a ID PROM located
-		 * in the box attached to the card. The card can then determine
-		 * the index the id to determine the number of ports available.
-		 * (FYI - The id should be located at 0x1ac (And may use up to
-		 * 4 bytes if the box in question is a XEM or CX)).
-		 */
-		/* PCI cards are already remapped at this point ISA are not */
-		bd->numports = readw(bd->re_map_membase + XEMPORTS);
-		epcaassert(bd->numports <= 64, "PCI returned a invalid number of ports");
-		nbdevs += (bd->numports);
-	} else {
-		/* Fix up the mappings for ISA/EISA etc */
-		/* FIXME: 64K - can we be smarter ? */
-		bd->re_map_membase = ioremap_nocache(bd->membase, 0x10000);
-	}
-
-	if (crd != 0)
-		card_ptr[crd] = card_ptr[crd-1] + boards[crd-1].numports;
-	else
-		card_ptr[crd] = &digi_channels[crd]; /* <- For card 0 only */
-
-	ch = card_ptr[crd];
-	epcaassert(ch <= &digi_channels[nbdevs - 1], "ch out of range");
-
-	memaddr = bd->re_map_membase;
-
-	/*
-	 * The below assignment will set bc to point at the BEGINING of the
-	 * cards channel structures. For 1 card there will be between 8 and 64
-	 * of these structures.
-	 */
-	bc = memaddr + CHANSTRUCT;
-
-	/*
-	 * The below assignment will set gd to point at the BEGINING of global
-	 * memory address 0xc00. The first data in that global memory actually
-	 * starts at address 0xc1a. The command in pointer begins at 0xd10.
-	 */
-	gd = memaddr + GLOBAL;
-
-	/*
-	 * XEPORTS (address 0xc22) points at the number of channels the card
-	 * supports. (For 64XE, XI, XEM, and XR use 0xc02)
-	 */
-	if ((bd->type == PCXEVE || bd->type == PCXE) &&
-					(readw(memaddr + XEPORTS) < 3))
-		shrinkmem = 1;
-	if (bd->type < PCIXEM)
-		if (!request_region((int)bd->port, 4, board_desc[bd->type]))
-			return;
-	memwinon(bd, 0);
-
-	/*
-	 * Remember ch is the main drivers channels structure, while bc is the
-	 * cards channel structure.
-	 */
-	for (i = 0; i < bd->numports; i++, ch++, bc++) {
-		unsigned long flags;
-		u16 tseg, rseg;
-
-		tty_port_init(&ch->port);
-		ch->port.ops = &epca_port_ops;
-		ch->brdchan = bc;
-		ch->mailbox = gd;
-		INIT_WORK(&ch->tqueue, do_softint);
-		ch->board = &boards[crd];
-
-		spin_lock_irqsave(&epca_lock, flags);
-		switch (bd->type) {
-		/*
-		 * Since some of the boards use different bitmaps for
-		 * their control signals we cannot hard code these
-		 * values and retain portability. We virtualize this
-		 * data here.
-		 */
-		case EISAXEM:
-		case PCXEM:
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			ch->m_rts = 0x02;
-			ch->m_dcd = 0x80;
-			ch->m_dsr = 0x20;
-			ch->m_cts = 0x10;
-			ch->m_ri  = 0x40;
-			ch->m_dtr = 0x01;
-			break;
-
-		case PCXE:
-		case PCXEVE:
-		case PCXI:
-		case PC64XE:
-			ch->m_rts = 0x02;
-			ch->m_dcd = 0x08;
-			ch->m_dsr = 0x10;
-			ch->m_cts = 0x20;
-			ch->m_ri  = 0x40;
-			ch->m_dtr = 0x80;
-			break;
-		}
-
-		if (boards[crd].altpin) {
-			ch->dsr = ch->m_dcd;
-			ch->dcd = ch->m_dsr;
-			ch->digiext.digi_flags |= DIGI_ALTPIN;
-		} else {
-			ch->dcd = ch->m_dcd;
-			ch->dsr = ch->m_dsr;
-		}
-
-		ch->boardnum   = crd;
-		ch->channelnum = i;
-		ch->magic      = EPCA_MAGIC;
-		tty_port_tty_set(&ch->port, NULL);
-
-		if (shrinkmem) {
-			fepcmd(ch, SETBUFFER, 32, 0, 0, 0);
-			shrinkmem = 0;
-		}
-
-		tseg = readw(&bc->tseg);
-		rseg = readw(&bc->rseg);
-
-		switch (bd->type) {
-		case PCIXEM:
-		case PCIXRJ:
-		case PCIXR:
-			/* Cover all the 2MEG cards */
-			ch->txptr = memaddr + ((tseg << 4) & 0x1fffff);
-			ch->rxptr = memaddr + ((rseg << 4) & 0x1fffff);
-			ch->txwin = FEPWIN | (tseg >> 11);
-			ch->rxwin = FEPWIN | (rseg >> 11);
-			break;
-
-		case PCXEM:
-		case EISAXEM:
-			/* Cover all the 32K windowed cards */
-			/* Mask equal to window size - 1 */
-			ch->txptr = memaddr + ((tseg << 4) & 0x7fff);
-			ch->rxptr = memaddr + ((rseg << 4) & 0x7fff);
-			ch->txwin = FEPWIN | (tseg >> 11);
-			ch->rxwin = FEPWIN | (rseg >> 11);
-			break;
-
-		case PCXEVE:
-		case PCXE:
-			ch->txptr = memaddr + (((tseg - bd->memory_seg) << 4)
-								& 0x1fff);
-			ch->txwin = FEPWIN | ((tseg - bd->memory_seg) >> 9);
-			ch->rxptr = memaddr + (((rseg - bd->memory_seg) << 4)
-								& 0x1fff);
-			ch->rxwin = FEPWIN | ((rseg - bd->memory_seg) >> 9);
-			break;
-
-		case PCXI:
-		case PC64XE:
-			ch->txptr = memaddr + ((tseg - bd->memory_seg) << 4);
-			ch->rxptr = memaddr + ((rseg - bd->memory_seg) << 4);
-			ch->txwin = ch->rxwin = 0;
-			break;
-		}
-
-		ch->txbufhead = 0;
-		ch->txbufsize = readw(&bc->tmax) + 1;
-
-		ch->rxbufhead = 0;
-		ch->rxbufsize = readw(&bc->rmax) + 1;
-
-		lowwater = ch->txbufsize >= 2000 ? 1024 : (ch->txbufsize / 2);
-
-		/* Set transmitter low water mark */
-		fepcmd(ch, STXLWATER, lowwater, 0, 10, 0);
-
-		/* Set receiver low water mark */
-		fepcmd(ch, SRXLWATER, (ch->rxbufsize / 4), 0, 10, 0);
-
-		/* Set receiver high water mark */
-		fepcmd(ch, SRXHWATER, (3 * ch->rxbufsize / 4), 0, 10, 0);
-
-		writew(100, &bc->edelay);
-		writeb(1, &bc->idata);
-
-		ch->startc  = readb(&bc->startc);
-		ch->stopc   = readb(&bc->stopc);
-		ch->startca = readb(&bc->startca);
-		ch->stopca  = readb(&bc->stopca);
-
-		ch->fepcflag = 0;
-		ch->fepiflag = 0;
-		ch->fepoflag = 0;
-		ch->fepstartc = 0;
-		ch->fepstopc = 0;
-		ch->fepstartca = 0;
-		ch->fepstopca = 0;
-
-		ch->port.close_delay = 50;
-
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-
-	printk(KERN_INFO
-	"Digi PC/Xx Driver V%s:  %s I/O = 0x%lx Mem = 0x%lx Ports = %d\n",
-				VERSION, board_desc[bd->type], (long)bd->port,
-					(long)bd->membase, bd->numports);
-	memwinoff(bd, 0);
-}
-
-static void epcapoll(unsigned long ignored)
-{
-	unsigned long flags;
-	int crd;
-	unsigned int head, tail;
-	struct channel *ch;
-	struct board_info *bd;
-
-	/*
-	 * This routine is called upon every timer interrupt. Even though the
-	 * Digi series cards are capable of generating interrupts this method
-	 * of non-looping polling is more efficient. This routine checks for
-	 * card generated events (Such as receive data, are transmit buffer
-	 * empty) and acts on those events.
-	 */
-	for (crd = 0; crd < num_cards; crd++) {
-		bd = &boards[crd];
-		ch = card_ptr[crd];
-
-		if ((bd->status == DISABLED) || digi_poller_inhibited)
-			continue;
-
-		/*
-		 * assertmemoff is not needed here; indeed it is an empty
-		 * subroutine. It is being kept because future boards may need
-		 * this as well as some legacy boards.
-		 */
-		spin_lock_irqsave(&epca_lock, flags);
-
-		assertmemoff(ch);
-
-		globalwinon(ch);
-
-		/*
-		 * In this case head and tail actually refer to the event queue
-		 * not the transmit or receive queue.
-		 */
-		head = readw(&ch->mailbox->ein);
-		tail = readw(&ch->mailbox->eout);
-
-		/* If head isn't equal to tail we have an event */
-		if (head != tail)
-			doevent(crd);
-		memoff(ch);
-
-		spin_unlock_irqrestore(&epca_lock, flags);
-	} /* End for each card */
-	mod_timer(&epca_timer, jiffies + (HZ / 25));
-}
-
-static void doevent(int crd)
-{
-	void __iomem *eventbuf;
-	struct channel *ch, *chan0;
-	static struct tty_struct *tty;
-	struct board_info *bd;
-	struct board_chan __iomem *bc;
-	unsigned int tail, head;
-	int event, channel;
-	int mstat, lstat;
-
-	/*
-	 * This subroutine is called by epcapoll when an event is detected
-	 * in the event queue. This routine responds to those events.
-	 */
-	bd = &boards[crd];
-
-	chan0 = card_ptr[crd];
-	epcaassert(chan0 <= &digi_channels[nbdevs - 1], "ch out of range");
-	assertgwinon(chan0);
-	while ((tail = readw(&chan0->mailbox->eout)) !=
-			(head = readw(&chan0->mailbox->ein))) {
-		/* Begin while something in event queue */
-		assertgwinon(chan0);
-		eventbuf = bd->re_map_membase + tail + ISTART;
-		/* Get the channel the event occurred on */
-		channel = readb(eventbuf);
-		/* Get the actual event code that occurred */
-		event = readb(eventbuf + 1);
-		/*
-		 * The two assignments below get the current modem status
-		 * (mstat) and the previous modem status (lstat). These are
-		 * useful becuase an event could signal a change in modem
-		 * signals itself.
-		 */
-		mstat = readb(eventbuf + 2);
-		lstat = readb(eventbuf + 3);
-
-		ch = chan0 + channel;
-		if ((unsigned)channel >= bd->numports || !ch)  {
-			if (channel >= bd->numports)
-				ch = chan0;
-			bc = ch->brdchan;
-			goto next;
-		}
-
-		bc = ch->brdchan;
-		if (bc == NULL)
-			goto next;
-
-		tty = tty_port_tty_get(&ch->port);
-		if (event & DATA_IND)  { /* Begin DATA_IND */
-			receive_data(ch, tty);
-			assertgwinon(ch);
-		} /* End DATA_IND */
-		/* else *//* Fix for DCD transition missed bug */
-		if (event & MODEMCHG_IND) {
-			/* A modem signal change has been indicated */
-			ch->imodem = mstat;
-			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);
-				else	/* No dcd; hangup */
-					pc_sched_event(ch, EPCA_EVENT_HANGUP);
-			}
-		}
-		if (tty) {
-			if (event & BREAK_IND) {
-				/* A break has been indicated */
-				tty_insert_flip_char(tty, 0, TTY_BREAK);
-				tty_schedule_flip(tty);
-			} else if (event & LOWTX_IND)  {
-				if (ch->statusflags & LOWWAIT) {
-					ch->statusflags &= ~LOWWAIT;
-					tty_wakeup(tty);
-				}
-			} else if (event & EMPTYTX_IND) {
-				/* This event is generated by
-				   setup_empty_event */
-				ch->statusflags &= ~TXBUSY;
-				if (ch->statusflags & EMPTYWAIT) {
-					ch->statusflags &= ~EMPTYWAIT;
-					tty_wakeup(tty);
-				}
-			}
-			tty_kref_put(tty);
-		}
-next:
-		globalwinon(ch);
-		BUG_ON(!bc);
-		writew(1, &bc->idata);
-		writew((tail + 4) & (IMAX - ISTART - 4), &chan0->mailbox->eout);
-		globalwinon(chan0);
-	} /* End while something in event queue */
-}
-
-static void fepcmd(struct channel *ch, int cmd, int word_or_byte,
-					int byte2, int ncmds, int bytecmd)
-{
-	unchar __iomem *memaddr;
-	unsigned int head, cmdTail, cmdStart, cmdMax;
-	long count;
-	int n;
-
-	/* This is the routine in which commands may be passed to the card. */
-
-	if (ch->board->status == DISABLED)
-		return;
-	assertgwinon(ch);
-	/* Remember head (As well as max) is just an offset not a base addr */
-	head = readw(&ch->mailbox->cin);
-	/* cmdStart is a base address */
-	cmdStart = readw(&ch->mailbox->cstart);
-	/*
-	 * We do the addition below because we do not want a max pointer
-	 * relative to cmdStart. We want a max pointer that points at the
-	 * physical end of the command queue.
-	 */
-	cmdMax = (cmdStart + 4 + readw(&ch->mailbox->cmax));
-	memaddr = ch->board->re_map_membase;
-
-	if (head >= (cmdMax - cmdStart) || (head & 03))  {
-		printk(KERN_ERR "line %d: Out of range, cmd = %x, head = %x\n",
-						__LINE__,  cmd, head);
-		printk(KERN_ERR "line %d: Out of range, cmdMax = %x, cmdStart = %x\n",
-						__LINE__,  cmdMax, cmdStart);
-		return;
-	}
-	if (bytecmd)  {
-		writeb(cmd, memaddr + head + cmdStart + 0);
-		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
-		/* Below word_or_byte is bits to set */
-		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
-		/* Below byte2 is bits to reset */
-		writeb(byte2, memaddr + head + cmdStart + 3);
-	}  else {
-		writeb(cmd, memaddr + head + cmdStart + 0);
-		writeb(ch->channelnum,  memaddr + head + cmdStart + 1);
-		writeb(word_or_byte,  memaddr + head + cmdStart + 2);
-	}
-	head = (head + 4) & (cmdMax - cmdStart - 4);
-	writew(head, &ch->mailbox->cin);
-	count = FEPTIMEOUT;
-
-	for (;;) {
-		count--;
-		if (count == 0)  {
-			printk(KERN_ERR "<Error> - Fep not responding in fepcmd()\n");
-			return;
-		}
-		head = readw(&ch->mailbox->cin);
-		cmdTail = readw(&ch->mailbox->cout);
-		n = (head - cmdTail) & (cmdMax - cmdStart - 4);
-		/*
-		 * Basically this will break when the FEP acknowledges the
-		 * command by incrementing cmdTail (Making it equal to head).
-		 */
-		if (n <= ncmds * (sizeof(short) * 4))
-			break;
-	}
-}
-
-/*
- * Digi products use fields in their channels structures that are very similar
- * to the c_cflag and c_iflag fields typically found in UNIX termios
- * structures. The below three routines allow mappings between these hardware
- * "flags" and their respective Linux flags.
- */
-static unsigned termios2digi_h(struct channel *ch, unsigned cflag)
-{
-	unsigned res = 0;
-
-	if (cflag & CRTSCTS) {
-		ch->digiext.digi_flags |= (RTSPACE | CTSPACE);
-		res |= ((ch->m_cts) | (ch->m_rts));
-	}
-
-	if (ch->digiext.digi_flags & RTSPACE)
-		res |= ch->m_rts;
-
-	if (ch->digiext.digi_flags & DTRPACE)
-		res |= ch->m_dtr;
-
-	if (ch->digiext.digi_flags & CTSPACE)
-		res |= ch->m_cts;
-
-	if (ch->digiext.digi_flags & DSRPACE)
-		res |= ch->dsr;
-
-	if (ch->digiext.digi_flags & DCDPACE)
-		res |= ch->dcd;
-
-	if (res & (ch->m_rts))
-		ch->digiext.digi_flags |= RTSPACE;
-
-	if (res & (ch->m_cts))
-		ch->digiext.digi_flags |= CTSPACE;
-
-	return res;
-}
-
-static unsigned termios2digi_i(struct channel *ch, unsigned iflag)
-{
-	unsigned res = iflag & (IGNBRK | BRKINT | IGNPAR | PARMRK |
-					INPCK | ISTRIP | IXON | IXANY | IXOFF);
-	if (ch->digiext.digi_flags & DIGI_AIXON)
-		res |= IAIXON;
-	return res;
-}
-
-static unsigned termios2digi_c(struct channel *ch, unsigned cflag)
-{
-	unsigned res = 0;
-	if (cflag & CBAUDEX) {
-		ch->digiext.digi_flags |= DIGI_FAST;
-		/*
-		 * HUPCL bit is used by FEP to indicate fast baud table is to
-		 * be used.
-		 */
-		res |= FEP_HUPCL;
-	} else
-		ch->digiext.digi_flags &= ~DIGI_FAST;
-	/*
-	 * CBAUD has bit position 0x1000 set these days to indicate Linux
-	 * baud rate remap. Digi hardware can't handle the bit assignment.
-	 * (We use a different bit assignment for high speed.). Clear this
-	 * bit out.
-	 */
-	res |= cflag & ((CBAUD ^ CBAUDEX) | PARODD | PARENB | CSTOPB | CSIZE);
-	/*
-	 * This gets a little confusing. The Digi cards have their own
-	 * representation of c_cflags controlling baud rate. For the most part
-	 * this is identical to the Linux implementation. However; Digi
-	 * supports one rate (76800) that Linux doesn't. This means that the
-	 * c_cflag entry that would normally mean 76800 for Digi actually means
-	 * 115200 under Linux. Without the below mapping, a stty 115200 would
-	 * only drive the board at 76800. Since the rate 230400 is also found
-	 * after 76800, the same problem afflicts us when we choose a rate of
-	 * 230400. Without the below modificiation stty 230400 would actually
-	 * give us 115200.
-	 *
-	 * There are two additional differences. The Linux value for CLOCAL
-	 * (0x800; 0004000) has no meaning to the Digi hardware. Also in later
-	 * releases of Linux; the CBAUD define has CBAUDEX (0x1000; 0010000)
-	 * ored into it (CBAUD = 0x100f as opposed to 0xf). CBAUDEX should be
-	 * checked for a screened out prior to termios2digi_c returning. Since
-	 * CLOCAL isn't used by the board this can be ignored as long as the
-	 * returned value is used only by Digi hardware.
-	 */
-	if (cflag & CBAUDEX) {
-		/*
-		 * The below code is trying to guarantee that only baud rates
-		 * 115200 and 230400 are remapped. We use exclusive or because
-		 * the various baud rates share common bit positions and
-		 * therefore can't be tested for easily.
-		 */
-		if ((!((cflag & 0x7) ^ (B115200 & ~CBAUDEX))) ||
-		    (!((cflag & 0x7) ^ (B230400 & ~CBAUDEX))))
-			res += 1;
-	}
-	return res;
-}
-
-/* Caller must hold the locks */
-static void epcaparam(struct tty_struct *tty, struct channel *ch)
-{
-	unsigned int cmdHead;
-	struct ktermios *ts;
-	struct board_chan __iomem *bc;
-	unsigned mval, hflow, cflag, iflag;
-
-	bc = ch->brdchan;
-	epcaassert(bc != NULL, "bc out of range");
-
-	assertgwinon(ch);
-	ts = tty->termios;
-	if ((ts->c_cflag & CBAUD) == 0)  { /* Begin CBAUD detected */
-		cmdHead = readw(&bc->rin);
-		writew(cmdHead, &bc->rout);
-		cmdHead = readw(&bc->tin);
-		/* Changing baud in mid-stream transmission can be wonderful */
-		/*
-		 * Flush current transmit buffer by setting cmdTail pointer
-		 * (tout) to cmdHead pointer (tin). Hopefully the transmit
-		 * buffer is empty.
-		 */
-		fepcmd(ch, STOUT, (unsigned) cmdHead, 0, 0, 0);
-		mval = 0;
-	} else { /* Begin CBAUD not detected */
-		/*
-		 * c_cflags have changed but that change had nothing to do with
-		 * BAUD. Propagate the change to the card.
-		 */
-		cflag = termios2digi_c(ch, ts->c_cflag);
-		if (cflag != ch->fepcflag)  {
-			ch->fepcflag = cflag;
-			/* Set baud rate, char size, stop bits, parity */
-			fepcmd(ch, SETCTRLFLAGS, (unsigned) cflag, 0, 0, 0);
-		}
-		/*
-		 * If the user has not forced CLOCAL and if the device is not a
-		 * CALLOUT device (Which is always CLOCAL) we set flags such
-		 * that the driver will wait on carrier detect.
-		 */
-		if (ts->c_cflag & CLOCAL)
-			clear_bit(ASYNCB_CHECK_CD, &ch->port.flags);
-		else
-			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);
-	/* Check input mode flags */
-	if (iflag != ch->fepiflag)  {
-		ch->fepiflag = iflag;
-		/*
-		 * Command sets channels iflag structure on the board. Such
-		 * things as input soft flow control, handling of parity
-		 * errors, and break handling are all set here.
-		 *
-		 * break handling, parity handling, input stripping,
-		 * flow control chars
-		 */
-		fepcmd(ch, SETIFLAGS, (unsigned int) ch->fepiflag, 0, 0, 0);
-	}
-	/*
-	 * Set the board mint value for this channel. This will cause hardware
-	 * events to be generated each time the DCD signal (Described in mint)
-	 * changes.
-	 */
-	writeb(ch->dcd, &bc->mint);
-	if ((ts->c_cflag & CLOCAL) || (ch->digiext.digi_flags & DIGI_FORCEDCD))
-		if (ch->digiext.digi_flags & DIGI_FORCEDCD)
-			writeb(0, &bc->mint);
-	ch->imodem = readb(&bc->mstat);
-	hflow = termios2digi_h(ch, ts->c_cflag);
-	if (hflow != ch->hflow)  {
-		ch->hflow = hflow;
-		/*
-		 * Hard flow control has been selected but the board is not
-		 * using it. Activate hard flow control now.
-		 */
-		fepcmd(ch, SETHFLOW, hflow, 0xff, 0, 1);
-	}
-	mval ^= ch->modemfake & (mval ^ ch->modem);
-
-	if (ch->omodem ^ mval)  {
-		ch->omodem = mval;
-		/*
-		 * The below command sets the DTR and RTS mstat structure. If
-		 * hard flow control is NOT active these changes will drive the
-		 * output of the actual DTR and RTS lines. If hard flow control
-		 * is active, the changes will be saved in the mstat structure
-		 * and only asserted when hard flow control is turned off.
-		 */
-
-		/* First reset DTR & RTS; then set them */
-		fepcmd(ch, SETMODEM, 0, ((ch->m_dtr)|(ch->m_rts)), 0, 1);
-		fepcmd(ch, SETMODEM, mval, 0, 0, 1);
-	}
-	if (ch->startc != ch->fepstartc || ch->stopc != ch->fepstopc)  {
-		ch->fepstartc = ch->startc;
-		ch->fepstopc = ch->stopc;
-		/*
-		 * The XON / XOFF characters have changed; propagate these
-		 * changes to the card.
-		 */
-		fepcmd(ch, SONOFFC, ch->fepstartc, ch->fepstopc, 0, 1);
-	}
-	if (ch->startca != ch->fepstartca || ch->stopca != ch->fepstopca)  {
-		ch->fepstartca = ch->startca;
-		ch->fepstopca = ch->stopca;
-		/*
-		 * Similar to the above, this time the auxilarly XON / XOFF
-		 * characters have changed; propagate these changes to the card.
-		 */
-		fepcmd(ch, SAUXONOFFC, ch->fepstartca, ch->fepstopca, 0, 1);
-	}
-}
-
-/* Caller holds lock */
-static void receive_data(struct channel *ch, struct tty_struct *tty)
-{
-	unchar *rptr;
-	struct ktermios *ts = NULL;
-	struct board_chan __iomem *bc;
-	int dataToRead, wrapgap, bytesAvailable;
-	unsigned int tail, head;
-	unsigned int wrapmask;
-
-	/*
-	 * This routine is called by doint when a receive data event has taken
-	 * place.
-	 */
-	globalwinon(ch);
-	if (ch->statusflags & RXSTOPPED)
-		return;
-	if (tty)
-		ts = tty->termios;
-	bc = ch->brdchan;
-	BUG_ON(!bc);
-	wrapmask = ch->rxbufsize - 1;
-
-	/*
-	 * Get the head and tail pointers to the receiver queue. Wrap the head
-	 * pointer if it has reached the end of the buffer.
-	 */
-	head = readw(&bc->rin);
-	head &= wrapmask;
-	tail = readw(&bc->rout) & wrapmask;
-
-	bytesAvailable = (head - tail) & wrapmask;
-	if (bytesAvailable == 0)
-		return;
-
-	/* If CREAD bit is off or device not open, set TX tail to head */
-	if (!tty || !ts || !(ts->c_cflag & CREAD)) {
-		writew(head, &bc->rout);
-		return;
-	}
-
-	if (tty_buffer_request_room(tty, bytesAvailable + 1) == 0)
-		return;
-
-	if (readb(&bc->orun)) {
-		writeb(0, &bc->orun);
-		printk(KERN_WARNING "epca; overrun! DigiBoard device %s\n",
-								tty->name);
-		tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-	}
-	rxwinon(ch);
-	while (bytesAvailable > 0) {
-		/* Begin while there is data on the card */
-		wrapgap = (head >= tail) ? head - tail : ch->rxbufsize - tail;
-		/*
-		 * Even if head has wrapped around only report the amount of
-		 * data to be equal to the size - tail. Remember memcpy can't
-		 * automaticly wrap around the receive buffer.
-		 */
-		dataToRead = (wrapgap < bytesAvailable) ? wrapgap
-							: bytesAvailable;
-		/* Make sure we don't overflow the buffer */
-		dataToRead = tty_prepare_flip_string(tty, &rptr, dataToRead);
-		if (dataToRead == 0)
-			break;
-		/*
-		 * Move data read from our card into the line disciplines
-		 * buffer for translation if necessary.
-		 */
-		memcpy_fromio(rptr, ch->rxptr + tail, dataToRead);
-		tail = (tail + dataToRead) & wrapmask;
-		bytesAvailable -= dataToRead;
-	} /* End while there is data on the card */
-	globalwinon(ch);
-	writew(tail, &bc->rout);
-	/* Must be called with global data */
-	tty_schedule_flip(tty);
-}
-
-static int info_ioctl(struct tty_struct *tty, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	switch (cmd) {
-	case DIGI_GETINFO:
-		{
-			struct digi_info di;
-			int brd;
-
-			if (get_user(brd, (unsigned int __user *)arg))
-				return -EFAULT;
-			if (brd < 0 || brd >= num_cards || num_cards == 0)
-				return -ENODEV;
-
-			memset(&di, 0, sizeof(di));
-
-			di.board = brd;
-			di.status = boards[brd].status;
-			di.type = boards[brd].type ;
-			di.numports = boards[brd].numports ;
-			/* Legacy fixups - just move along nothing to see */
-			di.port = (unsigned char *)boards[brd].port ;
-			di.membase = (unsigned char *)boards[brd].membase ;
-
-			if (copy_to_user((void __user *)arg, &di, sizeof(di)))
-				return -EFAULT;
-			break;
-
-		}
-
-	case DIGI_POLLER:
-		{
-			int brd = arg & 0xff000000 >> 16;
-			unsigned char state = arg & 0xff;
-
-			if (brd < 0 || brd >= num_cards) {
-				printk(KERN_ERR "epca: DIGI POLLER : brd not valid!\n");
-				return -ENODEV;
-			}
-			digi_poller_inhibited = state;
-			break;
-		}
-
-	case DIGI_INIT:
-		{
-			/*
-			 * This call is made by the apps to complete the
-			 * initialization of the board(s). This routine is
-			 * responsible for setting the card to its initial
-			 * state and setting the drivers control fields to the
-			 * sutianle settings for the card in question.
-			 */
-			int crd;
-			for (crd = 0; crd < num_cards; crd++)
-				post_fep_init(crd);
-			break;
-		}
-	default:
-		return -ENOTTY;
-	}
-	return 0;
-}
-
-static int pc_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct channel *ch = tty->driver_data;
-	struct board_chan __iomem *bc;
-	unsigned int mstat, mflag = 0;
-	unsigned long flags;
-
-	if (ch)
-		bc = ch->brdchan;
-	else
-		return -EINVAL;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	mstat = readb(&bc->mstat);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-
-	if (mstat & ch->m_dtr)
-		mflag |= TIOCM_DTR;
-	if (mstat & ch->m_rts)
-		mflag |= TIOCM_RTS;
-	if (mstat & ch->m_cts)
-		mflag |= TIOCM_CTS;
-	if (mstat & ch->dsr)
-		mflag |= TIOCM_DSR;
-	if (mstat & ch->m_ri)
-		mflag |= TIOCM_RI;
-	if (mstat & ch->dcd)
-		mflag |= TIOCM_CD;
-	return mflag;
-}
-
-static int pc_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct channel *ch = tty->driver_data;
-	unsigned long flags;
-
-	if (!ch)
-		return -EINVAL;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	/*
-	 * I think this modemfake stuff is broken. It doesn't correctly reflect
-	 * the behaviour desired by the TIOCM* ioctls. Therefore this is
-	 * probably broken.
-	 */
-	if (set & TIOCM_RTS) {
-		ch->modemfake |= ch->m_rts;
-		ch->modem |= ch->m_rts;
-	}
-	if (set & TIOCM_DTR) {
-		ch->modemfake |= ch->m_dtr;
-		ch->modem |= ch->m_dtr;
-	}
-	if (clear & TIOCM_RTS) {
-		ch->modemfake |= ch->m_rts;
-		ch->modem &= ~ch->m_rts;
-	}
-	if (clear & TIOCM_DTR) {
-		ch->modemfake |= ch->m_dtr;
-		ch->modem &= ~ch->m_dtr;
-	}
-	globalwinon(ch);
-	/*
-	 * The below routine generally sets up parity, baud, flow control
-	 * issues, etc.... It effect both control flags and input flags.
-	 */
-	epcaparam(tty, ch);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return 0;
-}
-
-static int pc_ioctl(struct tty_struct *tty, struct file *file,
-					unsigned int cmd, unsigned long arg)
-{
-	digiflow_t dflow;
-	unsigned long flags;
-	unsigned int mflag, mstat;
-	unsigned char startc, stopc;
-	struct board_chan __iomem *bc;
-	struct channel *ch = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (ch)
-		bc = ch->brdchan;
-	else
-		return -EINVAL;
-	switch (cmd) {
-	case TIOCMODG:
-		mflag = pc_tiocmget(tty, file);
-		if (put_user(mflag, (unsigned long __user *)argp))
-			return -EFAULT;
-		break;
-	case TIOCMODS:
-		if (get_user(mstat, (unsigned __user *)argp))
-			return -EFAULT;
-		return pc_tiocmset(tty, file, mstat, ~mstat);
-	case TIOCSDTR:
-		spin_lock_irqsave(&epca_lock, flags);
-		ch->omodem |= ch->m_dtr;
-		globalwinon(ch);
-		fepcmd(ch, SETMODEM, ch->m_dtr, 0, 10, 1);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-
-	case TIOCCDTR:
-		spin_lock_irqsave(&epca_lock, flags);
-		ch->omodem &= ~ch->m_dtr;
-		globalwinon(ch);
-		fepcmd(ch, SETMODEM, 0, ch->m_dtr, 10, 1);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-	case DIGI_GETA:
-		if (copy_to_user(argp, &ch->digiext, sizeof(digi_t)))
-			return -EFAULT;
-		break;
-	case DIGI_SETAW:
-	case DIGI_SETAF:
-		if (cmd == DIGI_SETAW) {
-			/* Setup an event to indicate when the transmit
-			   buffer empties */
-			spin_lock_irqsave(&epca_lock, flags);
-			setup_empty_event(tty, ch);
-			spin_unlock_irqrestore(&epca_lock, flags);
-			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);
-		}
-		/* Fall Thru */
-	case DIGI_SETA:
-		if (copy_from_user(&ch->digiext, argp, sizeof(digi_t)))
-			return -EFAULT;
-
-		if (ch->digiext.digi_flags & DIGI_ALTPIN)  {
-			ch->dcd = ch->m_dsr;
-			ch->dsr = ch->m_dcd;
-		} else {
-			ch->dcd = ch->m_dcd;
-			ch->dsr = ch->m_dsr;
-			}
-
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-
-		/*
-		 * The below routine generally sets up parity, baud, flow
-		 * control issues, etc.... It effect both control flags and
-		 * input flags.
-		 */
-		epcaparam(tty, ch);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-		break;
-
-	case DIGI_GETFLOW:
-	case DIGI_GETAFLOW:
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-		if (cmd == DIGI_GETFLOW) {
-			dflow.startc = readb(&bc->startc);
-			dflow.stopc = readb(&bc->stopc);
-		} else {
-			dflow.startc = readb(&bc->startca);
-			dflow.stopc = readb(&bc->stopca);
-		}
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-
-		if (copy_to_user(argp, &dflow, sizeof(dflow)))
-			return -EFAULT;
-		break;
-
-	case DIGI_SETAFLOW:
-	case DIGI_SETFLOW:
-		if (cmd == DIGI_SETFLOW) {
-			startc = ch->startc;
-			stopc = ch->stopc;
-		} else {
-			startc = ch->startca;
-			stopc = ch->stopca;
-		}
-
-		if (copy_from_user(&dflow, argp, sizeof(dflow)))
-			return -EFAULT;
-
-		if (dflow.startc != startc || dflow.stopc != stopc) {
-			/* Begin  if setflow toggled */
-			spin_lock_irqsave(&epca_lock, flags);
-			globalwinon(ch);
-
-			if (cmd == DIGI_SETFLOW) {
-				ch->fepstartc = ch->startc = dflow.startc;
-				ch->fepstopc = ch->stopc = dflow.stopc;
-				fepcmd(ch, SONOFFC, ch->fepstartc,
-						ch->fepstopc, 0, 1);
-			} else {
-				ch->fepstartca = ch->startca = dflow.startc;
-				ch->fepstopca  = ch->stopca = dflow.stopc;
-				fepcmd(ch, SAUXONOFFC, ch->fepstartca,
-						ch->fepstopca, 0, 1);
-			}
-
-			if (ch->statusflags & TXSTOPPED)
-				pc_start(tty);
-
-			memoff(ch);
-			spin_unlock_irqrestore(&epca_lock, flags);
-		} /* End if setflow toggled */
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static void pc_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-
-	if (ch != NULL)  { /* Begin if channel valid */
-		spin_lock_irqsave(&epca_lock, flags);
-		globalwinon(ch);
-		epcaparam(tty, ch);
-		memoff(ch);
-		spin_unlock_irqrestore(&epca_lock, flags);
-
-		if ((old_termios->c_cflag & CRTSCTS) &&
-			 ((tty->termios->c_cflag & CRTSCTS) == 0))
-			tty->hw_stopped = 0;
-
-		if (!(old_termios->c_cflag & CLOCAL) &&
-			 (tty->termios->c_cflag & CLOCAL))
-			wake_up_interruptible(&ch->port.open_wait);
-
-	} /* End if channel valid */
-}
-
-static void do_softint(struct work_struct *work)
-{
-	struct channel *ch = container_of(work, struct channel, tqueue);
-	/* Called in response to a modem change event */
-	if (ch && ch->magic == EPCA_MAGIC) {
-		struct tty_struct *tty = tty_port_tty_get(&ch->port);
-
-		if (tty && tty->driver_data) {
-			if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) {
-				tty_hangup(tty);
-				wake_up_interruptible(&ch->port.open_wait);
-				clear_bit(ASYNCB_NORMAL_ACTIVE,
-						&ch->port.flags);
-			}
-		}
-		tty_kref_put(tty);
-	}
-}
-
-/*
- * pc_stop and pc_start provide software flow control to the routine and the
- * pc_ioctl routine.
- */
-static void pc_stop(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		if ((ch->statusflags & TXSTOPPED) == 0) {
-			/* Begin if transmit stop requested */
-			globalwinon(ch);
-			/* STOP transmitting now !! */
-			fepcmd(ch, PAUSETX, 0, 0, 0, 0);
-			ch->statusflags |= TXSTOPPED;
-			memoff(ch);
-		} /* End if transmit stop requested */
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static void pc_start(struct tty_struct *tty)
-{
-	struct channel *ch;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		unsigned long flags;
-		spin_lock_irqsave(&epca_lock, flags);
-		/* Just in case output was resumed because of a change
-		   in Digi-flow */
-		if (ch->statusflags & TXSTOPPED)  {
-			/* Begin transmit resume requested */
-			struct board_chan __iomem *bc;
-			globalwinon(ch);
-			bc = ch->brdchan;
-			if (ch->statusflags & LOWWAIT)
-				writeb(1, &bc->ilow);
-			/* Okay, you can start transmitting again... */
-			fepcmd(ch, RESUMETX, 0, 0, 0, 0);
-			ch->statusflags &= ~TXSTOPPED;
-			memoff(ch);
-		} /* End transmit resume requested */
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-/*
- * The below routines pc_throttle and pc_unthrottle are used to slow (And
- * resume) the receipt of data into the kernels receive buffers. The exact
- * occurrence of this depends on the size of the kernels receive buffer and
- * what the 'watermarks' are set to for that buffer. See the n_ttys.c file for
- * more details.
- */
-static void pc_throttle(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		spin_lock_irqsave(&epca_lock, flags);
-		if ((ch->statusflags & RXSTOPPED) == 0) {
-			globalwinon(ch);
-			fepcmd(ch, PAUSERX, 0, 0, 0, 0);
-			ch->statusflags |= RXSTOPPED;
-			memoff(ch);
-		}
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static void pc_unthrottle(struct tty_struct *tty)
-{
-	struct channel *ch;
-	unsigned long flags;
-	/*
-	 * verifyChannel returns the channel from the tty struct if it is
-	 * valid. This serves as a sanity check.
-	 */
-	ch = verifyChannel(tty);
-	if (ch != NULL) {
-		/* Just in case output was resumed because of a change
-		   in Digi-flow */
-		spin_lock_irqsave(&epca_lock, flags);
-		if (ch->statusflags & RXSTOPPED) {
-			globalwinon(ch);
-			fepcmd(ch, RESUMERX, 0, 0, 0, 0);
-			ch->statusflags &= ~RXSTOPPED;
-			memoff(ch);
-		}
-		spin_unlock_irqrestore(&epca_lock, flags);
-	}
-}
-
-static int pc_send_break(struct tty_struct *tty, int msec)
-{
-	struct channel *ch = tty->driver_data;
-	unsigned long flags;
-
-	if (msec == -1)
-		msec = 0xFFFF;
-	else if (msec > 0xFFFE)
-		msec = 0xFFFE;
-	else if (msec < 1)
-		msec = 1;
-
-	spin_lock_irqsave(&epca_lock, flags);
-	globalwinon(ch);
-	/*
-	 * Maybe I should send an infinite break here, schedule() for msec
-	 * amount of time, and then stop the break. This way, the user can't
-	 * screw up the FEP by causing digi_send_break() to be called (i.e. via
-	 * an ioctl()) more than once in msec amount of time.
-	 * Try this for now...
-	 */
-	fepcmd(ch, SENDBREAK, msec, 0, 10, 0);
-	memoff(ch);
-	spin_unlock_irqrestore(&epca_lock, flags);
-	return 0;
-}
-
-/* Caller MUST hold the lock */
-static void setup_empty_event(struct tty_struct *tty, struct channel *ch)
-{
-	struct board_chan __iomem *bc = ch->brdchan;
-
-	globalwinon(ch);
-	ch->statusflags |= EMPTYWAIT;
-	/*
-	 * When set the iempty flag request a event to be generated when the
-	 * transmit buffer is empty (If there is no BREAK in progress).
-	 */
-	writeb(1, &bc->iempty);
-	memoff(ch);
-}
-
-#ifndef MODULE
-static void __init epca_setup(char *str, int *ints)
-{
-	struct board_info board;
-	int               index, loop, last;
-	char              *temp, *t2;
-	unsigned          len;
-
-	/*
-	 * If this routine looks a little strange it is because it is only
-	 * called if a LILO append command is given to boot the kernel with
-	 * parameters. In this way, we can provide the user a method of
-	 * changing his board configuration without rebuilding the kernel.
-	 */
-	if (!liloconfig)
-		liloconfig = 1;
-
-	memset(&board, 0, sizeof(board));
-
-	/* Assume the data is int first, later we can change it */
-	/* I think that array position 0 of ints holds the number of args */
-	for (last = 0, index = 1; index <= ints[0]; index++)
-		switch (index) { /* Begin parse switch */
-		case 1:
-			board.status = ints[index];
-			/*
-			 * We check for 2 (As opposed to 1; because 2 is a flag
-			 * instructing the driver to ignore epcaconfig.) For
-			 * this reason we check for 2.
-			 */
-			if (board.status == 2) {
-			/* Begin ignore epcaconfig as well as lilo cmd line */
-				nbdevs = 0;
-				num_cards = 0;
-				return;
-			} /* End ignore epcaconfig as well as lilo cmd line */
-
-			if (board.status > 2) {
-				printk(KERN_ERR "epca_setup: Invalid board status 0x%x\n",
-						board.status);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_STATUS;
-				return;
-			}
-			last = index;
-			break;
-		case 2:
-			board.type = ints[index];
-			if (board.type >= PCIXEM)  {
-				printk(KERN_ERR "epca_setup: Invalid board type 0x%x\n", board.type);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_TYPE;
-				return;
-			}
-			last = index;
-			break;
-		case 3:
-			board.altpin = ints[index];
-			if (board.altpin > 1) {
-				printk(KERN_ERR "epca_setup: Invalid board altpin 0x%x\n", board.altpin);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_ALTPIN;
-				return;
-			}
-			last = index;
-			break;
-
-		case 4:
-			board.numports = ints[index];
-			if (board.numports < 2 || board.numports > 256) {
-				printk(KERN_ERR "epca_setup: Invalid board numports 0x%x\n", board.numports);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_NUM_PORTS;
-				return;
-			}
-			nbdevs += board.numports;
-			last = index;
-			break;
-
-		case 5:
-			board.port = ints[index];
-			if (ints[index] <= 0) {
-				printk(KERN_ERR "epca_setup: Invalid io port 0x%x\n", (unsigned int)board.port);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_PORT_BASE;
-				return;
-			}
-			last = index;
-			break;
-
-		case 6:
-			board.membase = ints[index];
-			if (ints[index] <= 0) {
-				printk(KERN_ERR "epca_setup: Invalid memory base 0x%x\n",
-					(unsigned int)board.membase);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_MEM_BASE;
-				return;
-			}
-			last = index;
-			break;
-
-		default:
-			printk(KERN_ERR "<Error> - epca_setup: Too many integer parms\n");
-			return;
-
-		} /* End parse switch */
-
-	while (str && *str)  { /* Begin while there is a string arg */
-		/* find the next comma or terminator */
-		temp = str;
-		/* While string is not null, and a comma hasn't been found */
-		while (*temp && (*temp != ','))
-			temp++;
-		if (!*temp)
-			temp = NULL;
-		else
-			*temp++ = 0;
-		/* Set index to the number of args + 1 */
-		index = last + 1;
-
-		switch (index) {
-		case 1:
-			len = strlen(str);
-			if (strncmp("Disable", str, len) == 0)
-				board.status = 0;
-			else if (strncmp("Enable", str, len) == 0)
-				board.status = 1;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid status %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_STATUS;
-				return;
-			}
-			last = index;
-			break;
-
-		case 2:
-			for (loop = 0; loop < EPCA_NUM_TYPES; loop++)
-				if (strcmp(board_desc[loop], str) == 0)
-					break;
-			/*
-			 * If the index incremented above refers to a
-			 * legitamate board type set it here.
-			 */
-			if (index < EPCA_NUM_TYPES)
-				board.type = loop;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid board type: %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_BOARD_TYPE;
-				return;
-			}
-			last = index;
-			break;
-
-		case 3:
-			len = strlen(str);
-			if (strncmp("Disable", str, len) == 0)
-				board.altpin = 0;
-			else if (strncmp("Enable", str, len) == 0)
-				board.altpin = 1;
-			else {
-				printk(KERN_ERR "epca_setup: Invalid altpin %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_ALTPIN;
-				return;
-			}
-			last = index;
-			break;
-
-		case 4:
-			t2 = str;
-			while (isdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid port count %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_NUM_PORTS;
-				return;
-			}
-
-			/*
-			 * There is not a man page for simple_strtoul but the
-			 * code can be found in vsprintf.c. The first argument
-			 * is the string to translate (To an unsigned long
-			 * obviously), the second argument can be the address
-			 * of any character variable or a NULL. If a variable
-			 * is given, the end pointer of the string will be
-			 * stored in that variable; if a NULL is given the end
-			 * pointer will not be returned. The last argument is
-			 * the base to use. If a 0 is indicated, the routine
-			 * will attempt to determine the proper base by looking
-			 * at the values prefix (A '0' for octal, a 'x' for
-			 * hex, etc ... If a value is given it will use that
-			 * value as the base.
-			 */
-			board.numports = simple_strtoul(str, NULL, 0);
-			nbdevs += board.numports;
-			last = index;
-			break;
-
-		case 5:
-			t2 = str;
-			while (isxdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid i/o address %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_PORT_BASE;
-				return;
-			}
-
-			board.port = simple_strtoul(str, NULL, 16);
-			last = index;
-			break;
-
-		case 6:
-			t2 = str;
-			while (isxdigit(*t2))
-				t2++;
-
-			if (*t2) {
-				printk(KERN_ERR "epca_setup: Invalid memory base %s\n", str);
-				invalid_lilo_config = 1;
-				setup_error_code |= INVALID_MEM_BASE;
-				return;
-			}
-			board.membase = simple_strtoul(str, NULL, 16);
-			last = index;
-			break;
-		default:
-			printk(KERN_ERR "epca: Too many string parms\n");
-			return;
-		}
-		str = temp;
-	} /* End while there is a string arg */
-
-	if (last < 6) {
-		printk(KERN_ERR "epca: Insufficient parms specified\n");
-		return;
-	}
-
-	/* I should REALLY validate the stuff here */
-	/* Copies our local copy of board into boards */
-	memcpy((void *)&boards[num_cards], (void *)&board, sizeof(board));
-	/* Does this get called once per lilo arg are what ? */
-	printk(KERN_INFO "PC/Xx: Added board %i, %s %i ports at 0x%4.4X base 0x%6.6X\n",
-		num_cards, board_desc[board.type],
-		board.numports, (int)board.port, (unsigned int) board.membase);
-	num_cards++;
-}
-
-static int __init epca_real_setup(char *str)
-{
-	int ints[11];
-
-	epca_setup(get_options(str, 11, ints), ints);
-	return 1;
-}
-
-__setup("digiepca", epca_real_setup);
-#endif
-
-enum epic_board_types {
-	brd_xr = 0,
-	brd_xem,
-	brd_cx,
-	brd_xrj,
-};
-
-/* indexed directly by epic_board_types enum */
-static struct {
-	unsigned char board_type;
-	unsigned bar_idx;		/* PCI base address region */
-} epca_info_tbl[] = {
-	{ PCIXR, 0, },
-	{ PCIXEM, 0, },
-	{ PCICX, 0, },
-	{ PCIXRJ, 2, },
-};
-
-static int __devinit epca_init_one(struct pci_dev *pdev,
-				 const struct pci_device_id *ent)
-{
-	static int board_num = -1;
-	int board_idx, info_idx = ent->driver_data;
-	unsigned long addr;
-
-	if (pci_enable_device(pdev))
-		return -EIO;
-
-	board_num++;
-	board_idx = board_num + num_cards;
-	if (board_idx >= MAXBOARDS)
-		goto err_out;
-
-	addr = pci_resource_start(pdev, epca_info_tbl[info_idx].bar_idx);
-	if (!addr) {
-		printk(KERN_ERR PFX "PCI region #%d not available (size 0)\n",
-			epca_info_tbl[info_idx].bar_idx);
-		goto err_out;
-	}
-
-	boards[board_idx].status = ENABLED;
-	boards[board_idx].type = epca_info_tbl[info_idx].board_type;
-	boards[board_idx].numports = 0x0;
-	boards[board_idx].port = addr + PCI_IO_OFFSET;
-	boards[board_idx].membase = addr;
-
-	if (!request_mem_region(addr + PCI_IO_OFFSET, 0x200000, "epca")) {
-		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out;
-	}
-
-	boards[board_idx].re_map_port = ioremap_nocache(addr + PCI_IO_OFFSET,
-								0x200000);
-	if (!boards[board_idx].re_map_port) {
-		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out_free_pciio;
-	}
-
-	if (!request_mem_region(addr, 0x200000, "epca")) {
-		printk(KERN_ERR PFX "resource 0x%x @ 0x%lx unavailable\n",
-			0x200000, addr);
-		goto err_out_free_iounmap;
-	}
-
-	boards[board_idx].re_map_membase = ioremap_nocache(addr, 0x200000);
-	if (!boards[board_idx].re_map_membase) {
-		printk(KERN_ERR PFX "cannot map 0x%x @ 0x%lx\n",
-			0x200000, addr + PCI_IO_OFFSET);
-		goto err_out_free_memregion;
-	}
-
-	/*
-	 * I don't know what the below does, but the hardware guys say its
-	 * required on everything except PLX (In this case XRJ).
-	 */
-	if (info_idx != brd_xrj) {
-		pci_write_config_byte(pdev, 0x40, 0);
-		pci_write_config_byte(pdev, 0x46, 0);
-	}
-
-	return 0;
-
-err_out_free_memregion:
-	release_mem_region(addr, 0x200000);
-err_out_free_iounmap:
-	iounmap(boards[board_idx].re_map_port);
-err_out_free_pciio:
-	release_mem_region(addr + PCI_IO_OFFSET, 0x200000);
-err_out:
-	return -ENODEV;
-}
-
-
-static struct pci_device_id epca_pci_tbl[] = {
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XR, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xr },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XEM, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xem },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_CX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_cx },
-	{ PCI_VENDOR_DIGI, PCI_DEVICE_XRJ, PCI_ANY_ID, PCI_ANY_ID, 0, 0, brd_xrj },
-	{ 0, }
-};
-
-MODULE_DEVICE_TABLE(pci, epca_pci_tbl);
-
-static int __init init_PCI(void)
-{
-	memset(&epca_driver, 0, sizeof(epca_driver));
-	epca_driver.name = "epca";
-	epca_driver.id_table = epca_pci_tbl;
-	epca_driver.probe = epca_init_one;
-
-	return pci_register_driver(&epca_driver);
-}
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/char/epcaconfig.h linux-libre-2.6.39-gnu/drivers/char/epcaconfig.h
--- linux-libre-2.6.38-gnu/drivers/char/epcaconfig.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/epcaconfig.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#define NUMCARDS 0
-#define NBDEVS 0
-
-struct board_info static_boards[NUMCARDS]={
-};
-
-/* DO NOT HAND EDIT THIS FILE! */
diff -druN linux-libre-2.6.38-gnu/drivers/char/epca.h linux-libre-2.6.39-gnu/drivers/char/epca.h
--- linux-libre-2.6.38-gnu/drivers/char/epca.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/epca.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,158 +0,0 @@
-#define XEMPORTS    0xC02
-#define XEPORTS     0xC22
-
-#define MAX_ALLOC   0x100
-
-#define MAXBOARDS   12
-#define FEPCODESEG  0x0200L
-#define FEPCODE     0x2000L
-#define BIOSCODE    0xf800L
-
-#define MISCGLOBAL  0x0C00L
-#define NPORT       0x0C22L
-#define MBOX        0x0C40L
-#define PORTBASE    0x0C90L
-
-/* Begin code defines used for epca_setup */
-
-#define INVALID_BOARD_TYPE   0x1
-#define INVALID_NUM_PORTS    0x2
-#define INVALID_MEM_BASE     0x4
-#define INVALID_PORT_BASE    0x8
-#define INVALID_BOARD_STATUS 0x10
-#define INVALID_ALTPIN       0x20
-
-/* End code defines used for epca_setup */
-
-
-#define FEPCLR      0x00
-#define FEPMEM      0x02
-#define FEPRST      0x04
-#define FEPINT      0x08
-#define	FEPMASK     0x0e
-#define	FEPWIN      0x80
-
-#define PCXE    0
-#define PCXEVE  1
-#define PCXEM   2   
-#define EISAXEM 3
-#define PC64XE  4
-#define PCXI    5
-#define PCIXEM  7
-#define PCICX   8
-#define PCIXR   9
-#define PCIXRJ  10
-#define EPCA_NUM_TYPES 6
-
-
-static char *board_desc[] = 
-{
-	"PC/Xe",
-	"PC/Xeve",
-	"PC/Xem",
-	"EISA/Xem",
-	"PC/64Xe",
-	"PC/Xi",
-	"unknown",
-	"PCI/Xem",
-	"PCI/CX",
-	"PCI/Xr",
-	"PCI/Xrj",
-};
-
-#define STARTC      021
-#define STOPC       023
-#define IAIXON      0x2000
-
-
-#define TXSTOPPED  0x1
-#define LOWWAIT    0x2
-#define EMPTYWAIT  0x4
-#define RXSTOPPED  0x8
-#define TXBUSY     0x10
-
-#define DISABLED   0
-#define ENABLED    1
-#define OFF        0
-#define ON         1
-
-#define FEPTIMEOUT 200000  
-#define SERIAL_TYPE_INFO    3
-#define EPCA_EVENT_HANGUP   1
-#define EPCA_MAGIC          0x5c6df104L
-
-struct channel 
-{
-	long   magic;
-	struct tty_port port;
-	unsigned char boardnum;
-	unsigned char channelnum;
-	unsigned char omodem;         /* FEP output modem status     */
-	unsigned char imodem;         /* FEP input modem status      */
-	unsigned char modemfake;      /* Modem values to be forced   */
-	unsigned char modem;          /* Force values                */
-	unsigned char hflow;
-	unsigned char dsr;
-	unsigned char dcd;
-	unsigned char m_rts ; 		/* The bits used in whatever FEP */
-	unsigned char m_dcd ;		/* is indiginous to this board to */
-	unsigned char m_dsr ;		/* represent each of the physical */
-	unsigned char m_cts ;		/* handshake lines */
-	unsigned char m_ri ;
-	unsigned char m_dtr ;
-	unsigned char stopc;
-	unsigned char startc;
-	unsigned char stopca;
-	unsigned char startca;
-	unsigned char fepstopc;
-	unsigned char fepstartc;
-	unsigned char fepstopca;
-	unsigned char fepstartca;
-	unsigned char txwin;
-	unsigned char rxwin;
-	unsigned short fepiflag;
-	unsigned short fepcflag;
-	unsigned short fepoflag;
-	unsigned short txbufhead;
-	unsigned short txbufsize;
-	unsigned short rxbufhead;
-	unsigned short rxbufsize;
-	int    close_delay;
-	unsigned long  event;
-	uint   dev;
-	unsigned long  statusflags;
-	unsigned long  c_iflag;
-	unsigned long  c_cflag;
-	unsigned long  c_lflag;
-	unsigned long  c_oflag;
-	unsigned char __iomem *txptr;
-	unsigned char __iomem *rxptr;
-	struct board_info           *board;
-	struct board_chan	    __iomem *brdchan;
-	struct digi_struct          digiext;
-	struct work_struct          tqueue;
-	struct global_data 	    __iomem *mailbox;
-};
-
-struct board_info	
-{
-	unsigned char status;
-	unsigned char type;
-	unsigned char altpin;
-	unsigned short numports;
-	unsigned long port;
-	unsigned long membase;
-	void __iomem *re_map_port;
-	void __iomem *re_map_membase;
-	unsigned long  memory_seg;
-	void ( * memwinon )	(struct board_info *, unsigned int) ;
-	void ( * memwinoff ) 	(struct board_info *, unsigned int) ;
-	void ( * globalwinon )	(struct channel *) ;
-	void ( * txwinon ) 	(struct channel *) ;
-	void ( * rxwinon )	(struct channel *) ;
-	void ( * memoff )	(struct channel *) ;
-	void ( * assertgwinon )	(struct channel *) ;
-	void ( * assertmemoff )	(struct channel *) ;
-	unsigned char poller_inhibited ;
-};
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/generic_serial.c linux-libre-2.6.39-gnu/drivers/char/generic_serial.c
--- linux-libre-2.6.38-gnu/drivers/char/generic_serial.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/generic_serial.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,844 +0,0 @@
-/*
- *  generic_serial.c
- *
- *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
- *
- *  written for the SX serial driver.
- *     Contains the code that should be shared over all the serial drivers.
- *
- *  Credit for the idea to do it this way might go to Alan Cox. 
- *
- *
- *  Version 0.1 -- December, 1998. Initial version.
- *  Version 0.2 -- March, 1999.    Some more routines. Bugfixes. Etc.
- *  Version 0.5 -- August, 1999.   Some more fixes. Reformat for Linus.
- *
- *  BitWizard is actively maintaining this file. We sometimes find
- *  that someone submitted changes to this file. We really appreciate
- *  your help, but please submit changes through us. We're doing our
- *  best to be responsive.  -- REW
- * */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/mm.h>
-#include <linux/generic_serial.h>
-#include <linux/interrupt.h>
-#include <linux/tty_flip.h>
-#include <linux/delay.h>
-#include <linux/gfp.h>
-#include <asm/uaccess.h>
-
-#define DEBUG 
-
-static int gs_debug;
-
-#ifdef DEBUG
-#define gs_dprintk(f, str...) if (gs_debug & f) printk (str)
-#else
-#define gs_dprintk(f, str...) /* nothing */
-#endif
-
-#define func_enter() gs_dprintk (GS_DEBUG_FLOW, "gs: enter %s\n", __func__)
-#define func_exit()  gs_dprintk (GS_DEBUG_FLOW, "gs: exit  %s\n", __func__)
-
-#define RS_EVENT_WRITE_WAKEUP	1
-
-module_param(gs_debug, int, 0644);
-
-
-int gs_put_char(struct tty_struct * tty, unsigned char ch)
-{
-	struct gs_port *port;
-
-	func_enter (); 
-
-	port = tty->driver_data;
-
-	if (!port) return 0;
-
-	if (! (port->port.flags & ASYNC_INITIALIZED)) return 0;
-
-	/* Take a lock on the serial tranmit buffer! */
-	mutex_lock(& port->port_write_mutex);
-
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-		/* Sorry, buffer is full, drop character. Update statistics???? -- REW */
-		mutex_unlock(&port->port_write_mutex);
-		return 0;
-	}
-
-	port->xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;  /* Characters in buffer */
-
-	mutex_unlock(&port->port_write_mutex);
-	func_exit ();
-	return 1;
-}
-
-
-/*
-> Problems to take into account are:
->       -1- Interrupts that empty part of the buffer.
->       -2- page faults on the access to userspace. 
->       -3- Other processes that are also trying to do a "write". 
-*/
-
-int gs_write(struct tty_struct * tty, 
-                    const unsigned char *buf, int count)
-{
-	struct gs_port *port;
-	int c, total = 0;
-	int t;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return 0;
-
-	if (! (port->port.flags & ASYNC_INITIALIZED))
-		return 0;
-
-	/* get exclusive "write" access to this port (problem 3) */
-	/* This is not a spinlock because we can have a disk access (page 
-		 fault) in copy_from_user */
-	mutex_lock(& port->port_write_mutex);
-
-	while (1) {
-
-		c = count;
- 
-		/* This is safe because we "OWN" the "head". Noone else can 
-		   change the "head": we own the port_write_mutex. */
-		/* Don't overrun the end of the buffer */
-		t = SERIAL_XMIT_SIZE - port->xmit_head;
-		if (t < c) c = t;
- 
-		/* This is safe because the xmit_cnt can only decrease. This 
-		   would increase "t", so we might copy too little chars. */
-		/* Don't copy past the "head" of the buffer */
-		t = SERIAL_XMIT_SIZE - 1 - port->xmit_cnt;
-		if (t < c) c = t;
- 
-		/* Can't copy more? break out! */
-		if (c <= 0) break;
-
-		memcpy (port->xmit_buf + port->xmit_head, buf, c);
-
-		port -> xmit_cnt += c;
-		port -> xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE -1);
-		buf += c;
-		count -= c;
-		total += c;
-	}
-	mutex_unlock(& port->port_write_mutex);
-
-	gs_dprintk (GS_DEBUG_WRITE, "write: interrupts are %s\n", 
-	            (port->port.flags & GS_TX_INTEN)?"enabled": "disabled");
-
-	if (port->xmit_cnt && 
-	    !tty->stopped && 
-	    !tty->hw_stopped &&
-	    !(port->port.flags & GS_TX_INTEN)) {
-		port->port.flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-	return total;
-}
-
-
-
-int gs_write_room(struct tty_struct * tty)
-{
-	struct gs_port *port = tty->driver_data;
-	int ret;
-
-	func_enter ();
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	func_exit ();
-	return ret;
-}
-
-
-int gs_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port = tty->driver_data;
-	func_enter ();
-
-	func_exit ();
-	return port->xmit_cnt;
-}
-
-
-static int gs_real_chars_in_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port->rd) return 0;
-	if (!port->rd->chars_in_buffer) return 0;
-
-	func_exit ();
-	return port->xmit_cnt + port->rd->chars_in_buffer (port);
-}
-
-
-static int gs_wait_tx_flushed (void * ptr, unsigned long timeout) 
-{
-	struct gs_port *port = ptr;
-	unsigned long end_jiffies;
-	int jiffies_to_transmit, charsleft = 0, rv = 0;
-	int rcib;
-
-	func_enter();
-
-	gs_dprintk (GS_DEBUG_FLUSH, "port=%p.\n", port);
-	if (port) {
-		gs_dprintk (GS_DEBUG_FLUSH, "xmit_cnt=%x, xmit_buf=%p, tty=%p.\n", 
-		port->xmit_cnt, port->xmit_buf, port->port.tty);
-	}
-
-	if (!port || port->xmit_cnt < 0 || !port->xmit_buf) {
-		gs_dprintk (GS_DEBUG_FLUSH, "ERROR: !port, !port->xmit_buf or prot->xmit_cnt < 0.\n");
-		func_exit();
-		return -EINVAL;  /* This is an error which we don't know how to handle. */
-	}
-
-	rcib = gs_real_chars_in_buffer(port->port.tty);
-
-	if(rcib <= 0) {
-		gs_dprintk (GS_DEBUG_FLUSH, "nothing to wait for.\n");
-		func_exit();
-		return rv;
-	}
-	/* stop trying: now + twice the time it would normally take +  seconds */
-	if (timeout == 0) timeout = MAX_SCHEDULE_TIMEOUT;
-	end_jiffies  = jiffies; 
-	if (timeout !=  MAX_SCHEDULE_TIMEOUT)
-		end_jiffies += port->baud?(2 * rcib * 10 * HZ / port->baud):0;
-	end_jiffies += timeout;
-
-	gs_dprintk (GS_DEBUG_FLUSH, "now=%lx, end=%lx (%ld).\n", 
-		    jiffies, end_jiffies, end_jiffies-jiffies); 
-
-	/* the expression is actually jiffies < end_jiffies, but that won't
-	   work around the wraparound. Tricky eh? */
-	while ((charsleft = gs_real_chars_in_buffer (port->port.tty)) &&
-	        time_after (end_jiffies, jiffies)) {
-		/* Units check: 
-		   chars * (bits/char) * (jiffies /sec) / (bits/sec) = jiffies!
-		   check! */
-
-		charsleft += 16; /* Allow 16 chars more to be transmitted ... */
-		jiffies_to_transmit = port->baud?(1 + charsleft * 10 * HZ / port->baud):0;
-		/*                                ^^^ Round up.... */
-		if (jiffies_to_transmit <= 0) jiffies_to_transmit = 1;
-
-		gs_dprintk (GS_DEBUG_FLUSH, "Expect to finish in %d jiffies "
-			    "(%d chars).\n", jiffies_to_transmit, charsleft); 
-
-		msleep_interruptible(jiffies_to_msecs(jiffies_to_transmit));
-		if (signal_pending (current)) {
-			gs_dprintk (GS_DEBUG_FLUSH, "Signal pending. Bombing out: "); 
-			rv = -EINTR;
-			break;
-		}
-	}
-
-	gs_dprintk (GS_DEBUG_FLUSH, "charsleft = %d.\n", charsleft); 
-	set_current_state (TASK_RUNNING);
-
-	func_exit();
-	return rv;
-}
-
-
-
-void gs_flush_buffer(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	unsigned long flags;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	/* XXX Would the write semaphore do? */
-	spin_lock_irqsave (&port->driver_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore (&port->driver_lock, flags);
-
-	tty_wakeup(tty);
-	func_exit ();
-}
-
-
-void gs_flush_chars(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !port->xmit_buf) {
-		func_exit ();
-		return;
-	}
-
-	/* Beats me -- REW */
-	port->port.flags |= GS_TX_INTEN;
-	port->rd->enable_tx_interrupts (port);
-	func_exit ();
-}
-
-
-void gs_stop(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt && 
-	    port->xmit_buf && 
-	    (port->port.flags & GS_TX_INTEN) ) {
-		port->port.flags &= ~GS_TX_INTEN;
-		port->rd->disable_tx_interrupts (port);
-	}
-	func_exit ();
-}
-
-
-void gs_start(struct tty_struct * tty)
-{
-	struct gs_port *port;
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (port->xmit_cnt && 
-	    port->xmit_buf && 
-	    !(port->port.flags & GS_TX_INTEN) ) {
-		port->port.flags |= GS_TX_INTEN;
-		port->rd->enable_tx_interrupts (port);
-	}
-	func_exit ();
-}
-
-
-static void gs_shutdown_port (struct gs_port *port)
-{
-	unsigned long flags;
-
-	func_enter();
-	
-	if (!port) return;
-	
-	if (!(port->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}
-
-	if (port->port.tty)
-		set_bit(TTY_IO_ERROR, &port->port.tty->flags);
-
-	port->rd->shutdown_port (port);
-
-	port->port.flags &= ~ASYNC_INITIALIZED;
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-
-	func_exit();
-}
-
-
-void gs_hangup(struct tty_struct *tty)
-{
-	struct gs_port *port;
-	unsigned long flags;
-
-	func_enter ();
-
-	port = tty->driver_data;
-	tty = port->port.tty;
-	if (!tty) 
-		return;
-
-	gs_shutdown_port (port);
-	spin_lock_irqsave(&port->port.lock, flags);
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|GS_ACTIVE);
-	port->port.tty = NULL;
-	port->port.count = 0;
-	spin_unlock_irqrestore(&port->port.lock, flags);
-
-	wake_up_interruptible(&port->port.open_wait);
-	func_exit ();
-}
-
-
-int gs_block_til_ready(void *port_, struct file * filp)
-{
-	struct gs_port *gp = port_;
-	struct tty_port *port = &gp->port;
-	DECLARE_WAITQUEUE(wait, current);
-	int    retval;
-	int    do_clocal = 0;
-	int    CD;
-	struct tty_struct *tty;
-	unsigned long flags;
-
-	func_enter ();
-
-	if (!port) return 0;
-
-	tty = port->tty;
-
-	gs_dprintk (GS_DEBUG_BTR, "Entering gs_block_till_ready.\n"); 
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) || port->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->close_wait);
-		if (port->flags & ASYNC_HUP_NOTIFY)
-			return -EAGAIN;
-		else
-			return -ERESTARTSYS;
-	}
-
-	gs_dprintk (GS_DEBUG_BTR, "after hung up\n"); 
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	gs_dprintk (GS_DEBUG_BTR, "after nonblock\n"); 
- 
-	if (C_CLOCAL(tty))
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-
-	add_wait_queue(&port->open_wait, &wait);
-
-	gs_dprintk (GS_DEBUG_BTR, "after add waitq.\n"); 
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		port->count--;
-	}
-	port->blocked_open++;
-	spin_unlock_irqrestore(&port->lock, flags);
-	while (1) {
-		CD = tty_port_carrier_raised(port);
-		gs_dprintk (GS_DEBUG_BTR, "CD is now %d.\n", CD);
-		set_current_state (TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->flags & ASYNC_INITIALIZED)) {
-			if (port->flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-			break;
-		}
-		if (!(port->flags & ASYNC_CLOSING) &&
-		    (do_clocal || CD))
-			break;
-		gs_dprintk (GS_DEBUG_BTR, "signal_pending is now: %d (%lx)\n", 
-		(int)signal_pending (current), *(long*)(&current->blocked)); 
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		schedule();
-	}
-	gs_dprintk (GS_DEBUG_BTR, "Got out of the loop. (%d)\n",
-		    port->blocked_open);
-	set_current_state (TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-	
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		port->count++;
-	}
-	port->blocked_open--;
-	if (retval == 0)
-        	port->flags |= ASYNC_NORMAL_ACTIVE;
-	spin_unlock_irqrestore(&port->lock, flags);
-	func_exit ();
-	return retval;
-}			 
-
-
-void gs_close(struct tty_struct * tty, struct file * filp)
-{
-	unsigned long flags;
-	struct gs_port *port;
-	
-	func_enter ();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-
-	if (!port->port.tty) {
-		/* This seems to happen when this is called from vhangup. */
-		gs_dprintk (GS_DEBUG_CLOSE, "gs: Odd: port->port.tty is NULL\n");
-		port->port.tty = tty;
-	}
-
-	spin_lock_irqsave(&port->port.lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&port->port.lock, flags);
-		if (port->rd->hungup)
-			port->rd->hungup (port);
-		func_exit ();
-		return;
-	}
-
-	if ((tty->count == 1) && (port->port.count != 1)) {
-		printk(KERN_ERR "gs: gs_close port %p: bad port count;"
-		       " tty->count is 1, port count is %d\n", port, port->port.count);
-		port->port.count = 1;
-	}
-	if (--port->port.count < 0) {
-		printk(KERN_ERR "gs: gs_close port %p: bad port count: %d\n", port, port->port.count);
-		port->port.count = 0;
-	}
-
-	if (port->port.count) {
-		gs_dprintk(GS_DEBUG_CLOSE, "gs_close port %p: count: %d\n", port, port->port.count);
-		spin_unlock_irqrestore(&port->port.lock, flags);
-		func_exit ();
-		return;
-	}
-	port->port.flags |= ASYNC_CLOSING;
-
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify 
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	/* if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-	   tty_wait_until_sent(tty, port->closing_wait); */
-
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-	port->rd->disable_rx_interrupts (port);
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	spin_unlock_irqrestore(&port->port.lock, flags);
-
-	/* close has no way of returning "EINTR", so discard return value */
-	if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		gs_wait_tx_flushed (port, port->closing_wait);
-
-	port->port.flags &= ~GS_ACTIVE;
-
-	gs_flush_buffer(tty);
-
-	tty_ldisc_flush(tty);
-	tty->closing = 0;
-
-	spin_lock_irqsave(&port->driver_lock, flags);
-	port->event = 0;
-	port->rd->close (port);
-	port->rd->shutdown_port (port);
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-
-	spin_lock_irqsave(&port->port.lock, flags);
-	port->port.tty = NULL;
-
-	if (port->port.blocked_open) {
-		if (port->close_delay) {
-			spin_unlock_irqrestore(&port->port.lock, flags);
-			msleep_interruptible(jiffies_to_msecs(port->close_delay));
-			spin_lock_irqsave(&port->port.lock, flags);
-		}
-		wake_up_interruptible(&port->port.open_wait);
-	}
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING | ASYNC_INITIALIZED);
-	spin_unlock_irqrestore(&port->port.lock, flags);
-	wake_up_interruptible(&port->port.close_wait);
-
-	func_exit ();
-}
-
-
-void gs_set_termios (struct tty_struct * tty, 
-                     struct ktermios * old_termios)
-{
-	struct gs_port *port;
-	int baudrate, tmp, rv;
-	struct ktermios *tiosp;
-
-	func_enter();
-
-	port = tty->driver_data;
-
-	if (!port) return;
-	if (!port->port.tty) {
-		/* This seems to happen when this is called after gs_close. */
-		gs_dprintk (GS_DEBUG_TERMIOS, "gs: Odd: port->port.tty is NULL\n");
-		port->port.tty = tty;
-	}
-
-
-	tiosp = tty->termios;
-
-	if (gs_debug & GS_DEBUG_TERMIOS) {
-		gs_dprintk (GS_DEBUG_TERMIOS, "termios structure (%p):\n", tiosp);
-	}
-
-	if(old_termios && (gs_debug & GS_DEBUG_TERMIOS)) {
-		if(tiosp->c_iflag != old_termios->c_iflag)  printk("c_iflag changed\n");
-		if(tiosp->c_oflag != old_termios->c_oflag)  printk("c_oflag changed\n");
-		if(tiosp->c_cflag != old_termios->c_cflag)  printk("c_cflag changed\n");
-		if(tiosp->c_lflag != old_termios->c_lflag)  printk("c_lflag changed\n");
-		if(tiosp->c_line  != old_termios->c_line)   printk("c_line changed\n");
-		if(!memcmp(tiosp->c_cc, old_termios->c_cc, NCC)) printk("c_cc changed\n");
-	}
-
-	baudrate = tty_get_baud_rate(tty);
-
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if (     (port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (port->baud_base / port->custom_divisor);
-	}
-
-	/* I recommend using THIS instead of the mess in termios (and
-	   duplicating the above code). Next we should create a clean
-	   interface towards this variable. If your card supports arbitrary
-	   baud rates, (e.g. CD1400 or 16550 based cards) then everything
-	   will be very easy..... */
-	port->baud = baudrate;
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	/* Baudrate/10 is cps. Divide by HZ to get chars per tick. */
-	tmp = (baudrate / 10 / HZ) * 2;			 
-
-	if (tmp <                 0) tmp = 0;
-	if (tmp >= SERIAL_XMIT_SIZE) tmp = SERIAL_XMIT_SIZE-1;
-
-	port->wakeup_chars = tmp;
-
-	/* We should really wait for the characters to be all sent before
-	   changing the settings. -- CAL */
-	rv = gs_wait_tx_flushed (port, MAX_SCHEDULE_TIMEOUT);
-	if (rv < 0) return /* rv */;
-
-	rv = port->rd->set_real_termios(port);
-	if (rv < 0) return /* rv */;
-
-	if ((!old_termios || 
-	     (old_termios->c_cflag & CRTSCTS)) &&
-	    !(      tiosp->c_cflag & CRTSCTS)) {
-		tty->stopped = 0;
-		gs_start(tty);
-	}
-
-#ifdef tytso_patch_94Nov25_1726
-	/* This "makes sense", Why is it commented out? */
-
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&port->gs.open_wait);
-#endif
-
-	func_exit();
-	return /* 0 */;
-}
-
-
-
-/* Must be called with interrupts enabled */
-int gs_init_port(struct gs_port *port)
-{
-	unsigned long flags;
-
-	func_enter ();
-
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		func_exit ();
-		return 0;
-	}
-	if (!port->xmit_buf) {
-		/* We may sleep in get_zeroed_page() */
-		unsigned long tmp;
-
-		tmp = get_zeroed_page(GFP_KERNEL);
-		spin_lock_irqsave (&port->driver_lock, flags);
-		if (port->xmit_buf) 
-			free_page (tmp);
-		else
-			port->xmit_buf = (unsigned char *) tmp;
-		spin_unlock_irqrestore(&port->driver_lock, flags);
-		if (!port->xmit_buf) {
-			func_exit ();
-			return -ENOMEM;
-		}
-	}
-
-	spin_lock_irqsave (&port->driver_lock, flags);
-	if (port->port.tty)
-		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
-	mutex_init(&port->port_write_mutex);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	gs_set_termios(port->port.tty, NULL);
-	spin_lock_irqsave (&port->driver_lock, flags);
-	port->port.flags |= ASYNC_INITIALIZED;
-	port->port.flags &= ~GS_TX_INTEN;
-
-	spin_unlock_irqrestore(&port->driver_lock, flags);
-	func_exit ();
-	return 0;
-}
-
-
-int gs_setserial(struct gs_port *port, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return(-EFAULT);
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != port->baud_base) ||
-		    (sio.close_delay != port->close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK)))
-			return(-EPERM);
-	} 
-
-	port->port.flags = (port->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-  
-	port->baud_base = sio.baud_base;
-	port->close_delay = sio.close_delay;
-	port->closing_wait = sio.closing_wait;
-	port->custom_divisor = sio.custom_divisor;
-
-	gs_set_termios (port->port.tty, NULL);
-
-	return 0;
-}
-
-
-/*****************************************************************************/
-
-/*
- *      Generate the serial struct info.
- */
-
-int gs_getserial(struct gs_port *port, struct serial_struct __user *sp)
-{
-	struct serial_struct    sio;
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-	sio.flags = port->port.flags;
-	sio.baud_base = port->baud_base;
-	sio.close_delay = port->close_delay;
-	sio.closing_wait = port->closing_wait;
-	sio.custom_divisor = port->custom_divisor;
-	sio.hub6 = 0;
-
-	/* If you want you can override these. */
-	sio.type = PORT_UNKNOWN;
-	sio.xmit_fifo_size = -1;
-	sio.line = -1;
-	sio.port = -1;
-	sio.irq = -1;
-
-	if (port->rd->getserial)
-		port->rd->getserial (port, &sio);
-
-	if (copy_to_user(sp, &sio, sizeof(struct serial_struct)))
-		return -EFAULT;
-	return 0;
-
-}
-
-
-void gs_got_break(struct gs_port *port)
-{
-	func_enter ();
-
-	tty_insert_flip_char(port->port.tty, 0, TTY_BREAK);
-	tty_schedule_flip(port->port.tty);
-	if (port->port.flags & ASYNC_SAK) {
-		do_SAK (port->port.tty);
-	}
-
-	func_exit ();
-}
-
-
-EXPORT_SYMBOL(gs_put_char);
-EXPORT_SYMBOL(gs_write);
-EXPORT_SYMBOL(gs_write_room);
-EXPORT_SYMBOL(gs_chars_in_buffer);
-EXPORT_SYMBOL(gs_flush_buffer);
-EXPORT_SYMBOL(gs_flush_chars);
-EXPORT_SYMBOL(gs_stop);
-EXPORT_SYMBOL(gs_start);
-EXPORT_SYMBOL(gs_hangup);
-EXPORT_SYMBOL(gs_block_til_ready);
-EXPORT_SYMBOL(gs_close);
-EXPORT_SYMBOL(gs_set_termios);
-EXPORT_SYMBOL(gs_init_port);
-EXPORT_SYMBOL(gs_setserial);
-EXPORT_SYMBOL(gs_getserial);
-EXPORT_SYMBOL(gs_got_break);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/Kconfig linux-libre-2.6.39-gnu/drivers/char/hw_random/Kconfig
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -198,3 +198,15 @@
 	  module will be called nomadik-rng.
 
 	  If unsure, say Y.
+
+config HW_RANDOM_PICOXCELL
+	tristate "Picochip picoXcell true random number generator support"
+	depends on HW_RANDOM && ARCH_PICOXCELL && PICOXCELL_PC3X3
+	---help---
+	  This driver provides kernel-side support for the Random Number
+	  Generator hardware found on Picochip PC3x3 and later devices.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called picoxcell-rng.
+
+	  If unsure, say Y.
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/Makefile linux-libre-2.6.39-gnu/drivers/char/hw_random/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -19,3 +19,4 @@
 obj-$(CONFIG_HW_RANDOM_MXC_RNGA) += mxc-rnga.o
 obj-$(CONFIG_HW_RANDOM_OCTEON) += octeon-rng.o
 obj-$(CONFIG_HW_RANDOM_NOMADIK) += nomadik-rng.o
+obj-$(CONFIG_HW_RANDOM_PICOXCELL) += picoxcell-rng.o
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/n2-drv.c linux-libre-2.6.39-gnu/drivers/char/hw_random/n2-drv.c
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/n2-drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/n2-drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -619,15 +619,20 @@
 		pr_info("%s", version);
 }
 
-static int __devinit n2rng_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static const struct of_device_id n2rng_match[];
+static int __devinit n2rng_probe(struct platform_device *op)
 {
-	int victoria_falls = (match->data != NULL);
+	const struct of_device_id *match;
+	int victoria_falls;
 	int err = -ENOMEM;
 	struct n2rng *np;
 
-	n2rng_driver_version();
+	match = of_match_device(n2rng_match, &op->dev);
+	if (!match)
+		return -EINVAL;
+	victoria_falls = (match->data != NULL);
 
+	n2rng_driver_version();
 	np = kzalloc(sizeof(*np), GFP_KERNEL);
 	if (!np)
 		goto out;
@@ -750,7 +755,7 @@
 };
 MODULE_DEVICE_TABLE(of, n2rng_match);
 
-static struct of_platform_driver n2rng_driver = {
+static struct platform_driver n2rng_driver = {
 	.driver = {
 		.name = "n2rng",
 		.owner = THIS_MODULE,
@@ -762,12 +767,12 @@
 
 static int __init n2rng_init(void)
 {
-	return of_register_platform_driver(&n2rng_driver);
+	return platform_driver_register(&n2rng_driver);
 }
 
 static void __exit n2rng_exit(void)
 {
-	of_unregister_platform_driver(&n2rng_driver);
+	platform_driver_unregister(&n2rng_driver);
 }
 
 module_init(n2rng_init);
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/nomadik-rng.c linux-libre-2.6.39-gnu/drivers/char/hw_random/nomadik-rng.c
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/nomadik-rng.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/nomadik-rng.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 	.read		= nmk_rng_read,
 };
 
-static int nmk_rng_probe(struct amba_device *dev, struct amba_id *id)
+static int nmk_rng_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	void __iomem *base;
 	int ret;
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/omap-rng.c linux-libre-2.6.39-gnu/drivers/char/hw_random/omap-rng.c
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/omap-rng.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/omap-rng.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
 
 static int __devinit omap_rng_probe(struct platform_device *pdev)
 {
-	struct resource *res, *mem;
+	struct resource *res;
 	int ret;
 
 	/*
@@ -116,14 +116,12 @@
 	if (!res)
 		return -ENOENT;
 
-	mem = request_mem_region(res->start, resource_size(res),
-				 pdev->name);
-	if (mem == NULL) {
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
 		ret = -EBUSY;
 		goto err_region;
 	}
 
-	dev_set_drvdata(&pdev->dev, mem);
+	dev_set_drvdata(&pdev->dev, res);
 	rng_base = ioremap(res->start, resource_size(res));
 	if (!rng_base) {
 		ret = -ENOMEM;
@@ -146,7 +144,7 @@
 	iounmap(rng_base);
 	rng_base = NULL;
 err_ioremap:
-	release_resource(mem);
+	release_mem_region(res->start, resource_size(res));
 err_region:
 	if (cpu_is_omap24xx()) {
 		clk_disable(rng_ick);
@@ -157,7 +155,7 @@
 
 static int __exit omap_rng_remove(struct platform_device *pdev)
 {
-	struct resource *mem = dev_get_drvdata(&pdev->dev);
+	struct resource *res = dev_get_drvdata(&pdev->dev);
 
 	hwrng_unregister(&omap_rng_ops);
 
@@ -170,7 +168,7 @@
 		clk_put(rng_ick);
 	}
 
-	release_resource(mem);
+	release_mem_region(res->start, resource_size(res));
 	rng_base = NULL;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/pasemi-rng.c linux-libre-2.6.39-gnu/drivers/char/hw_random/pasemi-rng.c
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/pasemi-rng.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/pasemi-rng.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,8 +94,7 @@
 	.data_read	= pasemi_rng_data_read,
 };
 
-static int __devinit rng_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit rng_probe(struct platform_device *ofdev)
 {
 	void __iomem *rng_regs;
 	struct device_node *rng_np = ofdev->dev.of_node;
@@ -139,7 +138,7 @@
 	{ },
 };
 
-static struct of_platform_driver rng_driver = {
+static struct platform_driver rng_driver = {
 	.driver = {
 		.name = "pasemi-rng",
 		.owner = THIS_MODULE,
@@ -151,13 +150,13 @@
 
 static int __init rng_init(void)
 {
-	return of_register_platform_driver(&rng_driver);
+	return platform_driver_register(&rng_driver);
 }
 module_init(rng_init);
 
 static void __exit rng_exit(void)
 {
-	of_unregister_platform_driver(&rng_driver);
+	platform_driver_unregister(&rng_driver);
 }
 module_exit(rng_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/char/hw_random/picoxcell-rng.c linux-libre-2.6.39-gnu/drivers/char/hw_random/picoxcell-rng.c
--- linux-libre-2.6.38-gnu/drivers/char/hw_random/picoxcell-rng.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/char/hw_random/picoxcell-rng.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,208 @@
+/*
+ * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
+ *
+ * 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.
+ *
+ * All enquiries to support@picochip.com
+ */
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/hw_random.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+#define DATA_REG_OFFSET		0x0200
+#define CSR_REG_OFFSET		0x0278
+#define CSR_OUT_EMPTY_MASK	(1 << 24)
+#define CSR_FAULT_MASK		(1 << 1)
+#define TRNG_BLOCK_RESET_MASK	(1 << 0)
+#define TAI_REG_OFFSET		0x0380
+
+/*
+ * The maximum amount of time in microseconds to spend waiting for data if the
+ * core wants us to wait.  The TRNG should generate 32 bits every 320ns so a
+ * timeout of 20us seems reasonable.  The TRNG does builtin tests of the data
+ * for randomness so we can't always assume there is data present.
+ */
+#define PICO_TRNG_TIMEOUT		20
+
+static void __iomem *rng_base;
+static struct clk *rng_clk;
+struct device *rng_dev;
+
+static inline u32 picoxcell_trng_read_csr(void)
+{
+	return __raw_readl(rng_base + CSR_REG_OFFSET);
+}
+
+static inline bool picoxcell_trng_is_empty(void)
+{
+	return picoxcell_trng_read_csr() & CSR_OUT_EMPTY_MASK;
+}
+
+/*
+ * Take the random number generator out of reset and make sure the interrupts
+ * are masked. We shouldn't need to get large amounts of random bytes so just
+ * poll the status register. The hardware generates 32 bits every 320ns so we
+ * shouldn't have to wait long enough to warrant waiting for an IRQ.
+ */
+static void picoxcell_trng_start(void)
+{
+	__raw_writel(0, rng_base + TAI_REG_OFFSET);
+	__raw_writel(0, rng_base + CSR_REG_OFFSET);
+}
+
+static void picoxcell_trng_reset(void)
+{
+	__raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + CSR_REG_OFFSET);
+	__raw_writel(TRNG_BLOCK_RESET_MASK, rng_base + TAI_REG_OFFSET);
+	picoxcell_trng_start();
+}
+
+/*
+ * Get some random data from the random number generator. The hw_random core
+ * layer provides us with locking.
+ */
+static int picoxcell_trng_read(struct hwrng *rng, void *buf, size_t max,
+			       bool wait)
+{
+	int i;
+
+	/* Wait for some data to become available. */
+	for (i = 0; i < PICO_TRNG_TIMEOUT && picoxcell_trng_is_empty(); ++i) {
+		if (!wait)
+			return 0;
+
+		udelay(1);
+	}
+
+	if (picoxcell_trng_read_csr() & CSR_FAULT_MASK) {
+		dev_err(rng_dev, "fault detected, resetting TRNG\n");
+		picoxcell_trng_reset();
+		return -EIO;
+	}
+
+	if (i == PICO_TRNG_TIMEOUT)
+		return 0;
+
+	*(u32 *)buf = __raw_readl(rng_base + DATA_REG_OFFSET);
+	return sizeof(u32);
+}
+
+static struct hwrng picoxcell_trng = {
+	.name		= "picoxcell",
+	.read		= picoxcell_trng_read,
+};
+
+static int picoxcell_trng_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!mem) {
+		dev_warn(&pdev->dev, "no memory resource\n");
+		return -ENOMEM;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+				     "picoxcell_trng")) {
+		dev_warn(&pdev->dev, "unable to request io mem\n");
+		return -EBUSY;
+	}
+
+	rng_base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!rng_base) {
+		dev_warn(&pdev->dev, "unable to remap io mem\n");
+		return -ENOMEM;
+	}
+
+	rng_clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(rng_clk)) {
+		dev_warn(&pdev->dev, "no clk\n");
+		return PTR_ERR(rng_clk);
+	}
+
+	ret = clk_enable(rng_clk);
+	if (ret) {
+		dev_warn(&pdev->dev, "unable to enable clk\n");
+		goto err_enable;
+	}
+
+	picoxcell_trng_start();
+	ret = hwrng_register(&picoxcell_trng);
+	if (ret)
+		goto err_register;
+
+	rng_dev = &pdev->dev;
+	dev_info(&pdev->dev, "pixoxcell random number generator active\n");
+
+	return 0;
+
+err_register:
+	clk_disable(rng_clk);
+err_enable:
+	clk_put(rng_clk);
+
+	return ret;
+}
+
+static int __devexit picoxcell_trng_remove(struct platform_device *pdev)
+{
+	hwrng_unregister(&picoxcell_trng);
+	clk_disable(rng_clk);
+	clk_put(rng_clk);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int picoxcell_trng_suspend(struct device *dev)
+{
+	clk_disable(rng_clk);
+
+	return 0;
+}
+
+static int picoxcell_trng_resume(struct device *dev)
+{
+	return clk_enable(rng_clk);
+}
+
+static const struct dev_pm_ops picoxcell_trng_pm_ops = {
+	.suspend	= picoxcell_trng_suspend,
+	.resume		= picoxcell_trng_resume,
+};
+#endif /* CONFIG_PM */
+
+static struct platform_driver picoxcell_trng_driver = {
+	.probe		= picoxcell_trng_probe,
+	.remove		= __devexit_p(picoxcell_trng_remove),
+	.driver		= {
+		.name	= "picoxcell-trng",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &picoxcell_trng_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init picoxcell_trng_init(void)
+{
+	return platform_driver_register(&picoxcell_trng_driver);
+}
+module_init(picoxcell_trng_init);
+
+static void __exit picoxcell_trng_exit(void)
+{
+	platform_driver_unregister(&picoxcell_trng_driver);
+}
+module_exit(picoxcell_trng_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
+MODULE_DESCRIPTION("Picochip picoXcell TRNG driver");
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2cmd.c linux-libre-2.6.39-gnu/drivers/char/ip2/i2cmd.c
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2cmd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,210 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definition table for In-line and Bypass commands. Applicable
-*                only when the standard loadware is active. (This is included
-*                source code, not a separate compilation module.)
-*
-*******************************************************************************/
-
-//------------------------------------------------------------------------------
-//
-// Revision History:
-//
-// 10 October 1991   MAG First Draft
-//  7 November 1991  MAG Reflects additional commands.
-// 24 February 1992  MAG Additional commands for 1.4.x loadware
-// 11 March 1992     MAG Additional commands
-// 30 March 1992     MAG Additional command: CMD_DSS_NOW
-// 18 May 1992       MAG Discovered commands 39 & 40 must be at the end of a
-//                       packet: affects implementation.
-//------------------------------------------------------------------------------
-
-//************
-//* Includes *
-//************
-
-#include "i2cmd.h"   /* To get some bit-defines */
-
-//------------------------------------------------------------------------------
-// Here is the table of global arrays which represent each type of command
-// supported in the IntelliPort standard loadware. See also i2cmd.h
-// for a more complete explanation of what is going on.
-//------------------------------------------------------------------------------
-
-// Here are the various globals: note that the names are not used except through
-// the macros defined in i2cmd.h. Also note that although they are character
-// arrays here (for extendability) they are cast to structure pointers in the
-// i2cmd.h macros. See i2cmd.h for flags definitions.
-
-//                     Length Flags Command
-static UCHAR ct02[] = { 1, BTH,     0x02                     }; // DTR UP
-static UCHAR ct03[] = { 1, BTH,     0x03                     }; // DTR DN
-static UCHAR ct04[] = { 1, BTH,     0x04                     }; // RTS UP
-static UCHAR ct05[] = { 1, BTH,     0x05                     }; // RTS DN
-static UCHAR ct06[] = { 1, BYP,     0x06                     }; // START FL
-static UCHAR ct07[] = { 2, BTH,     0x07,0                   }; // BAUD
-static UCHAR ct08[] = { 2, BTH,     0x08,0                   }; // BITS
-static UCHAR ct09[] = { 2, BTH,     0x09,0                   }; // STOP
-static UCHAR ct10[] = { 2, BTH,     0x0A,0                   }; // PARITY
-static UCHAR ct11[] = { 2, BTH,     0x0B,0                   }; // XON
-static UCHAR ct12[] = { 2, BTH,     0x0C,0                   }; // XOFF
-static UCHAR ct13[] = { 1, BTH,     0x0D                     }; // STOP FL
-static UCHAR ct14[] = { 1, BYP|VIP, 0x0E                     }; // ACK HOTK
-//static UCHAR ct15[]={ 2, BTH|VIP, 0x0F,0                   }; // IRQ SET
-static UCHAR ct16[] = { 2, INL,     0x10,0                   }; // IXONOPTS
-static UCHAR ct17[] = { 2, INL,     0x11,0                   }; // OXONOPTS
-static UCHAR ct18[] = { 1, INL,     0x12                     }; // CTSENAB
-static UCHAR ct19[] = { 1, BTH,     0x13                     }; // CTSDSAB
-static UCHAR ct20[] = { 1, INL,     0x14                     }; // DCDENAB
-static UCHAR ct21[] = { 1, BTH,     0x15                     }; // DCDDSAB
-static UCHAR ct22[] = { 1, BTH,     0x16                     }; // DSRENAB
-static UCHAR ct23[] = { 1, BTH,     0x17                     }; // DSRDSAB
-static UCHAR ct24[] = { 1, BTH,     0x18                     }; // RIENAB
-static UCHAR ct25[] = { 1, BTH,     0x19                     }; // RIDSAB
-static UCHAR ct26[] = { 2, BTH,     0x1A,0                   }; // BRKENAB
-static UCHAR ct27[] = { 1, BTH,     0x1B                     }; // BRKDSAB
-//static UCHAR ct28[]={ 2, BTH,     0x1C,0                   }; // MAXBLOKSIZE
-//static UCHAR ct29[]={ 2, 0,       0x1D,0                   }; // reserved
-static UCHAR ct30[] = { 1, INL,     0x1E                     }; // CTSFLOWENAB
-static UCHAR ct31[] = { 1, INL,     0x1F                     }; // CTSFLOWDSAB
-static UCHAR ct32[] = { 1, INL,     0x20                     }; // RTSFLOWENAB
-static UCHAR ct33[] = { 1, INL,     0x21                     }; // RTSFLOWDSAB
-static UCHAR ct34[] = { 2, BTH,     0x22,0                   }; // ISTRIPMODE
-static UCHAR ct35[] = { 2, BTH|END, 0x23,0                   }; // SENDBREAK
-static UCHAR ct36[] = { 2, BTH,     0x24,0                   }; // SETERRMODE
-//static UCHAR ct36a[]={ 3, INL,    0x24,0,0                 }; // SET_REPLACE
-
-// The following is listed for completeness, but should never be sent directly
-// by user-level code. It is sent only by library routines in response to data
-// movement.
-//static UCHAR ct37[]={ 5, BYP|VIP, 0x25,0,0,0,0             }; // FLOW PACKET
-
-// Back to normal
-//static UCHAR ct38[] = {11, BTH|VAR, 0x26,0,0,0,0,0,0,0,0,0,0 }; // DEF KEY SEQ
-//static UCHAR ct39[]={ 3, BTH|END, 0x27,0,0                 }; // OPOSTON
-//static UCHAR ct40[]={ 1, BTH|END, 0x28                     }; // OPOSTOFF
-static UCHAR ct41[] = { 1, BYP,     0x29                     }; // RESUME
-//static UCHAR ct42[]={ 2, BTH,     0x2A,0                   }; // TXBAUD
-//static UCHAR ct43[]={ 2, BTH,     0x2B,0                   }; // RXBAUD
-//static UCHAR ct44[]={ 2, BTH,     0x2C,0                   }; // MS PING
-//static UCHAR ct45[]={ 1, BTH,     0x2D                     }; // HOTENAB
-//static UCHAR ct46[]={ 1, BTH,     0x2E                     }; // HOTDSAB
-//static UCHAR ct47[]={ 7, BTH,     0x2F,0,0,0,0,0,0         }; // UNIX FLAGS
-//static UCHAR ct48[]={ 1, BTH,     0x30                     }; // DSRFLOWENAB
-//static UCHAR ct49[]={ 1, BTH,     0x31                     }; // DSRFLOWDSAB
-//static UCHAR ct50[]={ 1, BTH,     0x32                     }; // DTRFLOWENAB
-//static UCHAR ct51[]={ 1, BTH,     0x33                     }; // DTRFLOWDSAB
-//static UCHAR ct52[]={ 1, BTH,     0x34                     }; // BAUDTABRESET
-//static UCHAR ct53[] = { 3, BTH,     0x35,0,0                 }; // BAUDREMAP
-static UCHAR ct54[] = { 3, BTH,     0x36,0,0                 }; // CUSTOMBAUD1
-static UCHAR ct55[] = { 3, BTH,     0x37,0,0                 }; // CUSTOMBAUD2
-static UCHAR ct56[] = { 2, BTH|END, 0x38,0                   }; // PAUSE
-static UCHAR ct57[] = { 1, BYP,     0x39                     }; // SUSPEND
-static UCHAR ct58[] = { 1, BYP,     0x3A                     }; // UNSUSPEND
-static UCHAR ct59[] = { 2, BTH,     0x3B,0                   }; // PARITYCHK
-static UCHAR ct60[] = { 1, INL|VIP, 0x3C                     }; // BOOKMARKREQ
-//static UCHAR ct61[]={ 2, BTH,     0x3D,0                   }; // INTERNALLOOP
-//static UCHAR ct62[]={ 2, BTH,     0x3E,0                   }; // HOTKTIMEOUT
-static UCHAR ct63[] = { 2, INL,     0x3F,0                   }; // SETTXON
-static UCHAR ct64[] = { 2, INL,     0x40,0                   }; // SETTXOFF
-//static UCHAR ct65[]={ 2, BTH,     0x41,0                   }; // SETAUTORTS
-//static UCHAR ct66[]={ 2, BTH,     0x42,0                   }; // SETHIGHWAT
-//static UCHAR ct67[]={ 2, BYP,     0x43,0                   }; // STARTSELFL
-//static UCHAR ct68[]={ 2, INL,     0x44,0                   }; // ENDSELFL
-//static UCHAR ct69[]={ 1, BYP,     0x45                     }; // HWFLOW_OFF
-//static UCHAR ct70[]={ 1, BTH,     0x46                     }; // ODSRFL_ENAB
-//static UCHAR ct71[]={ 1, BTH,     0x47                     }; // ODSRFL_DSAB
-//static UCHAR ct72[]={ 1, BTH,     0x48                     }; // ODCDFL_ENAB
-//static UCHAR ct73[]={ 1, BTH,     0x49                     }; // ODCDFL_DSAB
-//static UCHAR ct74[]={ 2, BTH,     0x4A,0                   }; // LOADLEVEL
-//static UCHAR ct75[]={ 2, BTH,     0x4B,0                   }; // STATDATA
-//static UCHAR ct76[]={ 1, BYP,     0x4C                     }; // BREAK_ON
-//static UCHAR ct77[]={ 1, BYP,     0x4D                     }; // BREAK_OFF
-//static UCHAR ct78[]={ 1, BYP,     0x4E                     }; // GETFC
-static UCHAR ct79[] = { 2, BYP,     0x4F,0                   }; // XMIT_NOW
-//static UCHAR ct80[]={ 4, BTH,     0x50,0,0,0               }; // DIVISOR_LATCH
-//static UCHAR ct81[]={ 1, BYP,     0x51                     }; // GET_STATUS
-//static UCHAR ct82[]={ 1, BYP,     0x52                     }; // GET_TXCNT
-//static UCHAR ct83[]={ 1, BYP,     0x53                     }; // GET_RXCNT
-//static UCHAR ct84[]={ 1, BYP,     0x54                     }; // GET_BOXIDS
-//static UCHAR ct85[]={10, BYP,     0x55,0,0,0,0,0,0,0,0,0   }; // ENAB_MULT
-//static UCHAR ct86[]={ 2, BTH,     0x56,0                   }; // RCV_ENABLE
-static UCHAR ct87[] = { 1, BYP,     0x57                     }; // HW_TEST
-//static UCHAR ct88[]={ 3, BTH,     0x58,0,0                 }; // RCV_THRESHOLD
-//static UCHAR ct90[]={ 3, BYP,     0x5A,0,0                 }; // Set SILO
-//static UCHAR ct91[]={ 2, BYP,     0x5B,0                   }; // timed break
-
-// Some composite commands as well
-//static UCHAR cc01[]={ 2, BTH,     0x02,0x04                }; // DTR & RTS UP
-//static UCHAR cc02[]={ 2, BTH,     0x03,0x05                }; // DTR & RTS DN
-
-//********
-//* Code *
-//********
-
-//******************************************************************************
-// Function:   i2cmdUnixFlags(iflag, cflag, lflag)
-// Parameters: Unix tty flags
-//
-// Returns:    Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of command 47 and returns a pointer to the
-// appropriate structure.
-//******************************************************************************
-#if 0
-cmdSyntaxPtr
-i2cmdUnixFlags(unsigned short iflag,unsigned short cflag,unsigned short lflag)
-{
-	cmdSyntaxPtr pCM = (cmdSyntaxPtr) ct47;
-
-	pCM->cmd[1] = (unsigned char)  iflag;
-	pCM->cmd[2] = (unsigned char) (iflag >> 8);
-	pCM->cmd[3] = (unsigned char)  cflag;
-	pCM->cmd[4] = (unsigned char) (cflag >> 8);
-	pCM->cmd[5] = (unsigned char)  lflag;
-	pCM->cmd[6] = (unsigned char) (lflag >> 8);
-	return pCM;
-}
-#endif  /*  0  */
-
-//******************************************************************************
-// Function:   i2cmdBaudDef(which, rate)
-// Parameters: ?
-//
-// Returns:    Pointer to command structure
-//
-// Description:
-//
-// This routine sets the parameters of commands 54 or 55 (according to the
-// argument which), and returns a pointer to the appropriate structure.
-//******************************************************************************
-static cmdSyntaxPtr
-i2cmdBaudDef(int which, unsigned short rate)
-{
-	cmdSyntaxPtr pCM;
-
-	switch(which)
-	{
-	case 1:
-		pCM = (cmdSyntaxPtr) ct54;
-		break;
-	default:
-	case 2:
-		pCM = (cmdSyntaxPtr) ct55;
-		break;
-	}
-	pCM->cmd[1] = (unsigned char) rate;
-	pCM->cmd[2] = (unsigned char) (rate >> 8);
-	return pCM;
-}
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2cmd.h linux-libre-2.6.39-gnu/drivers/char/ip2/i2cmd.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2cmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2cmd.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,630 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions and support for In-line and Bypass commands.
-*                Applicable only when the standard loadware is active.
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 10 October 1991   MAG First Draft
-//  7 November 1991  MAG Reflects some new commands
-// 20 February 1992  MAG CMD_HOTACK corrected: no argument.
-// 24 February 1992  MAG Support added for new commands for 1.4.x loadware.
-// 11 March 1992     MAG Additional commands.
-// 16 March 1992     MAG Additional commands.
-// 30 March 1992     MAG Additional command: CMD_DSS_NOW
-// 18 May   1992     MAG Changed CMD_OPOST
-//
-//------------------------------------------------------------------------------
-#ifndef I2CMD_H      // To prevent multiple includes
-#define I2CMD_H   1
-
-#include "ip2types.h"
-
-// This module is designed to provide a uniform method of sending commands to
-// the board through command packets. The difficulty is, some commands take
-// parameters, others do not. Furthermore, it is often useful to send several
-// commands to the same channel as part of the same packet. (See also i2pack.h.)
-//
-// This module is designed so that the caller should not be responsible for
-// remembering the exact syntax of each command, or at least so that the
-// compiler could check things somewhat. I'll explain as we go...
-//
-// First, a structure which can embody the syntax of each type of command.
-//
-typedef struct _cmdSyntax
-{
-	UCHAR length;   // Number of bytes in the command
-	UCHAR flags;    // Information about the command (see below)
-
-	// The command and its parameters, which may be of arbitrary length. Don't
-	// worry yet how the parameters will be initialized; macros later take care
-	// of it. Also, don't worry about the arbitrary length issue; this structure
-	// is never used to allocate space (see i2cmd.c).
-	UCHAR cmd[2];
-} cmdSyntax, *cmdSyntaxPtr;
-
-// Bit assignments for flags
-
-#define INL 1           // Set if suitable for inline commands
-#define BYP 2           // Set if suitable for bypass commands
-#define BTH (INL|BYP)   // suitable for either!
-#define END 4           // Set if this must be the last command in a block
-#define VIP 8           // Set if this command is special in some way and really
-						// should only be sent from the library-level and not
-						// directly from user-level
-#define VAR 0x10        // This command is of variable length!
-
-// Declarations for the global arrays used to bear the commands and their
-// arguments.
-//
-// Note: Since these are globals and the arguments might change, it is important
-// that the library routine COPY these into buffers from whence they would be
-// sent, rather than merely storing the pointers. In multi-threaded
-// environments, important that the copy should obtain before any context switch
-// is allowed. Also, for parameterized commands, DO NOT ISSUE THE SAME COMMAND
-// MORE THAN ONCE WITH THE SAME PARAMETERS in the same call.
-//
-static UCHAR ct02[];
-static UCHAR ct03[];
-static UCHAR ct04[];
-static UCHAR ct05[];
-static UCHAR ct06[];
-static UCHAR ct07[];
-static UCHAR ct08[];
-static UCHAR ct09[];
-static UCHAR ct10[];
-static UCHAR ct11[];
-static UCHAR ct12[];
-static UCHAR ct13[];
-static UCHAR ct14[];
-static UCHAR ct15[];
-static UCHAR ct16[];
-static UCHAR ct17[];
-static UCHAR ct18[];
-static UCHAR ct19[];
-static UCHAR ct20[];
-static UCHAR ct21[];
-static UCHAR ct22[];
-static UCHAR ct23[];
-static UCHAR ct24[];
-static UCHAR ct25[];
-static UCHAR ct26[];
-static UCHAR ct27[];
-static UCHAR ct28[];
-static UCHAR ct29[];
-static UCHAR ct30[];
-static UCHAR ct31[];
-static UCHAR ct32[];
-static UCHAR ct33[];
-static UCHAR ct34[];
-static UCHAR ct35[];
-static UCHAR ct36[];
-static UCHAR ct36a[];
-static UCHAR ct41[];
-static UCHAR ct42[];
-static UCHAR ct43[];
-static UCHAR ct44[];
-static UCHAR ct45[];
-static UCHAR ct46[];
-static UCHAR ct48[];
-static UCHAR ct49[];
-static UCHAR ct50[];
-static UCHAR ct51[];
-static UCHAR ct52[];
-static UCHAR ct56[];
-static UCHAR ct57[];
-static UCHAR ct58[];
-static UCHAR ct59[];
-static UCHAR ct60[];
-static UCHAR ct61[];
-static UCHAR ct62[];
-static UCHAR ct63[];
-static UCHAR ct64[];
-static UCHAR ct65[];
-static UCHAR ct66[];
-static UCHAR ct67[];
-static UCHAR ct68[];
-static UCHAR ct69[];
-static UCHAR ct70[];
-static UCHAR ct71[];
-static UCHAR ct72[];
-static UCHAR ct73[];
-static UCHAR ct74[];
-static UCHAR ct75[];
-static UCHAR ct76[];
-static UCHAR ct77[];
-static UCHAR ct78[];
-static UCHAR ct79[];
-static UCHAR ct80[];
-static UCHAR ct81[];
-static UCHAR ct82[];
-static UCHAR ct83[];
-static UCHAR ct84[];
-static UCHAR ct85[];
-static UCHAR ct86[];
-static UCHAR ct87[];
-static UCHAR ct88[];
-static UCHAR ct89[];
-static UCHAR ct90[];
-static UCHAR ct91[];
-static UCHAR cc01[];
-static UCHAR cc02[];
-
-// Now, refer to i2cmd.c, and see the character arrays defined there. They are
-// cast here to cmdSyntaxPtr.
-//
-// There are library functions for issuing bypass or inline commands. These
-// functions take one or more arguments of the type cmdSyntaxPtr. The routine
-// then can figure out how long each command is supposed to be and easily add it
-// to the list.
-//
-// For ease of use, we define manifests which return pointers to appropriate
-// cmdSyntaxPtr things. But some commands also take arguments. If a single
-// argument is used, we define a macro which performs the single assignment and
-// (through the expedient of a comma expression) references the appropriate
-// pointer. For commands requiring several arguments, we actually define a
-// function to perform the assignments.
-
-#define CMD_DTRUP	(cmdSyntaxPtr)(ct02)	// Raise DTR
-#define CMD_DTRDN	(cmdSyntaxPtr)(ct03)	// Lower DTR
-#define CMD_RTSUP	(cmdSyntaxPtr)(ct04)	// Raise RTS
-#define CMD_RTSDN	(cmdSyntaxPtr)(ct05)	// Lower RTS
-#define CMD_STARTFL	(cmdSyntaxPtr)(ct06)	// Start Flushing Data
-
-#define CMD_DTRRTS_UP (cmdSyntaxPtr)(cc01)	// Raise DTR and RTS
-#define CMD_DTRRTS_DN (cmdSyntaxPtr)(cc02)	// Lower DTR and RTS
-
-// Set Baud Rate for transmit and receive
-#define CMD_SETBAUD(arg) \
-	(((cmdSyntaxPtr)(ct07))->cmd[1] = (arg),(cmdSyntaxPtr)(ct07))
-
-#define CBR_50       1
-#define CBR_75       2
-#define CBR_110      3
-#define CBR_134      4
-#define CBR_150      5
-#define CBR_200      6
-#define CBR_300      7
-#define CBR_600      8
-#define CBR_1200     9
-#define CBR_1800     10
-#define CBR_2400     11
-#define CBR_4800     12
-#define CBR_9600     13
-#define CBR_19200    14
-#define CBR_38400    15
-#define CBR_2000     16
-#define CBR_3600     17
-#define CBR_7200     18
-#define CBR_56000    19
-#define CBR_57600    20
-#define CBR_64000    21
-#define CBR_76800    22
-#define CBR_115200   23
-#define CBR_C1       24    // Custom baud rate 1
-#define CBR_C2       25    // Custom baud rate 2
-#define CBR_153600   26
-#define CBR_230400   27
-#define CBR_307200   28
-#define CBR_460800   29
-#define CBR_921600   30
-
-// Set Character size
-//
-#define CMD_SETBITS(arg) \
-	(((cmdSyntaxPtr)(ct08))->cmd[1] = (arg),(cmdSyntaxPtr)(ct08))
-
-#define CSZ_5  0
-#define CSZ_6  1
-#define CSZ_7  2
-#define CSZ_8  3
-
-// Set number of stop bits
-//
-#define CMD_SETSTOP(arg) \
-	(((cmdSyntaxPtr)(ct09))->cmd[1] = (arg),(cmdSyntaxPtr)(ct09))
-
-#define CST_1  0
-#define CST_15 1  // 1.5 stop bits
-#define CST_2  2
-
-// Set parity option
-//
-#define CMD_SETPAR(arg) \
-	(((cmdSyntaxPtr)(ct10))->cmd[1] = (arg),(cmdSyntaxPtr)(ct10))
-
-#define CSP_NP 0  // no parity
-#define CSP_OD 1  // odd parity
-#define CSP_EV 2  // Even parity
-#define CSP_SP 3  // Space parity
-#define CSP_MK 4  // Mark parity
-
-// Define xon char for transmitter flow control
-//
-#define CMD_DEF_IXON(arg) \
-	(((cmdSyntaxPtr)(ct11))->cmd[1] = (arg),(cmdSyntaxPtr)(ct11))
-
-// Define xoff char for transmitter flow control
-//
-#define CMD_DEF_IXOFF(arg) \
-	(((cmdSyntaxPtr)(ct12))->cmd[1] = (arg),(cmdSyntaxPtr)(ct12))
-
-#define CMD_STOPFL   (cmdSyntaxPtr)(ct13) // Stop Flushing data
-
-// Acknowledge receipt of hotkey signal
-//
-#define CMD_HOTACK   (cmdSyntaxPtr)(ct14)
-
-// Define irq level to use. Should actually be sent by library-level code, not
-// directly from user...
-//
-#define CMDVALUE_IRQ 15 // For library use at initialization. Until this command
-						// is sent, board processing doesn't really start.
-#define CMD_SET_IRQ(arg) \
-	(((cmdSyntaxPtr)(ct15))->cmd[1] = (arg),(cmdSyntaxPtr)(ct15))
-
-#define CIR_POLL  0  // No IRQ - Poll
-#define CIR_3     3  // IRQ 3
-#define CIR_4     4  // IRQ 4
-#define CIR_5     5  // IRQ 5
-#define CIR_7     7  // IRQ 7
-#define CIR_10    10 // IRQ 10
-#define CIR_11    11 // IRQ 11
-#define CIR_12    12 // IRQ 12
-#define CIR_15    15 // IRQ 15
-
-// Select transmit flow xon/xoff options
-//
-#define CMD_IXON_OPT(arg) \
-	(((cmdSyntaxPtr)(ct16))->cmd[1] = (arg),(cmdSyntaxPtr)(ct16))
-
-#define CIX_NONE  0  // Incoming Xon/Xoff characters not special
-#define CIX_XON   1  // Xoff disable, Xon enable
-#define CIX_XANY  2  // Xoff disable, any key enable
-
-// Select receive flow xon/xoff options
-//
-#define CMD_OXON_OPT(arg) \
-	(((cmdSyntaxPtr)(ct17))->cmd[1] = (arg),(cmdSyntaxPtr)(ct17))
-
-#define COX_NONE  0  // Don't send Xon/Xoff
-#define COX_XON   1  // Send xon/xoff to start/stop incoming data
-
-
-#define CMD_CTS_REP  (cmdSyntaxPtr)(ct18) // Enable  CTS reporting
-#define CMD_CTS_NREP (cmdSyntaxPtr)(ct19) // Disable CTS reporting
-
-#define CMD_DCD_REP  (cmdSyntaxPtr)(ct20) // Enable  DCD reporting
-#define CMD_DCD_NREP (cmdSyntaxPtr)(ct21) // Disable DCD reporting
-
-#define CMD_DSR_REP  (cmdSyntaxPtr)(ct22) // Enable  DSR reporting
-#define CMD_DSR_NREP (cmdSyntaxPtr)(ct23) // Disable DSR reporting
-
-#define CMD_RI_REP   (cmdSyntaxPtr)(ct24) // Enable  RI  reporting
-#define CMD_RI_NREP  (cmdSyntaxPtr)(ct25) // Disable RI  reporting
-
-// Enable break reporting and select style
-//
-#define CMD_BRK_REP(arg) \
-	(((cmdSyntaxPtr)(ct26))->cmd[1] = (arg),(cmdSyntaxPtr)(ct26))
-
-#define CBK_STAT     0x00  // Report breaks as a status (exception,irq)
-#define CBK_NULL     0x01  // Report breaks as a good null
-#define CBK_STAT_SEQ 0x02  // Report breaks as a status AND as in-band character
-                           //  sequence FFh, 01h, 10h
-#define CBK_SEQ      0x03  // Report breaks as the in-band 
-						   //sequence FFh, 01h, 10h ONLY.
-#define CBK_FLSH     0x04  // if this bit set also flush input data
-#define CBK_POSIX    0x08  // if this bit set report as FF,0,0 sequence
-#define CBK_SINGLE   0x10  // if this bit set with CBK_SEQ or CBK_STAT_SEQ
-						   //then reports single null instead of triple
-
-#define CMD_BRK_NREP (cmdSyntaxPtr)(ct27) // Disable break reporting
-
-// Specify maximum block size for received data
-//
-#define CMD_MAX_BLOCK(arg) \
-	(((cmdSyntaxPtr)(ct28))->cmd[1] = (arg),(cmdSyntaxPtr)(ct28))
-
-// -- COMMAND 29 is reserved --
-
-#define CMD_CTSFL_ENAB  (cmdSyntaxPtr)(ct30) // Enable  CTS flow control
-#define CMD_CTSFL_DSAB  (cmdSyntaxPtr)(ct31) // Disable CTS flow control
-#define CMD_RTSFL_ENAB  (cmdSyntaxPtr)(ct32) // Enable  RTS flow control
-#define CMD_RTSFL_DSAB  (cmdSyntaxPtr)(ct33) // Disable RTS flow control
-
-// Specify istrip option
-//
-#define CMD_ISTRIP_OPT(arg) \
-	(((cmdSyntaxPtr)(ct34))->cmd[1] = (arg),(cmdSyntaxPtr)(ct34))
-
-#define CIS_NOSTRIP  0  // Strip characters to character size
-#define CIS_STRIP    1  // Strip any 8-bit characters to 7 bits
-
-// Send a break of arg milliseconds
-//
-#define CMD_SEND_BRK(arg) \
-	(((cmdSyntaxPtr)(ct35))->cmd[1] = (arg),(cmdSyntaxPtr)(ct35))
-
-// Set error reporting mode
-//
-#define CMD_SET_ERROR(arg) \
-	(((cmdSyntaxPtr)(ct36))->cmd[1] = (arg),(cmdSyntaxPtr)(ct36))
-
-#define CSE_ESTAT 0  // Report error in a status packet
-#define CSE_NOREP 1  // Treat character as though it were good
-#define CSE_DROP  2  // Discard the character
-#define CSE_NULL  3  // Replace with a null
-#define CSE_MARK  4  // Replace with a 3-character sequence (as Unix)
-
-#define CSE_REPLACE  0x8	// Replace the errored character with the
-							// replacement character defined here
-
-#define CSE_STAT_REPLACE   0x18	// Replace the errored character with the
-								// replacement character defined here AND
-								// report the error as a status packet (as in
-								// CSE_ESTAT).
-
-
-// COMMAND 37, to send flow control packets, is handled only by low-level
-// library code in response to data movement and shouldn't ever be sent by the
-// user code. See i2pack.h and the body of i2lib.c for details.
-
-// Enable on-board post-processing, using options given in oflag argument.
-// Formerly, this command was automatically preceded by a CMD_OPOST_OFF command
-// because the loadware does not permit sending back-to-back CMD_OPOST_ON
-// commands without an intervening CMD_OPOST_OFF. BUT, WE LEARN 18 MAY 92, that
-// CMD_OPOST_ON and CMD_OPOST_OFF must each be at the end of a packet (or in a
-// solo packet). This means the caller must specify separately CMD_OPOST_OFF,
-// CMD_OPOST_ON(parm) when he calls i2QueueCommands(). That function will ensure
-// each gets a separate packet. Extra CMD_OPOST_OFF's are always ok.
-//
-#define CMD_OPOST_ON(oflag)   \
-	(*(USHORT *)(((cmdSyntaxPtr)(ct39))->cmd[1]) = (oflag), \
-		(cmdSyntaxPtr)(ct39))
-
-#define CMD_OPOST_OFF   (cmdSyntaxPtr)(ct40) // Disable on-board post-proc
-
-#define CMD_RESUME   (cmdSyntaxPtr)(ct41)	// Resume: behave as though an XON
-											// were received;
-
-// Set Transmit baud rate (see command 7 for arguments)
-//
-#define CMD_SETBAUD_TX(arg) \
-	(((cmdSyntaxPtr)(ct42))->cmd[1] = (arg),(cmdSyntaxPtr)(ct42))
-
-// Set Receive baud rate (see command 7 for arguments)
-//
-#define CMD_SETBAUD_RX(arg) \
-	(((cmdSyntaxPtr)(ct43))->cmd[1] = (arg),(cmdSyntaxPtr)(ct43))
-
-// Request interrupt from board each arg milliseconds. Interrupt will specify
-// "received data", even though there may be no data present. If arg == 0,
-// disables any such interrupts.
-//
-#define CMD_PING_REQ(arg) \
-	(((cmdSyntaxPtr)(ct44))->cmd[1] = (arg),(cmdSyntaxPtr)(ct44))
-
-#define CMD_HOT_ENAB (cmdSyntaxPtr)(ct45) // Enable Hot-key checking
-#define CMD_HOT_DSAB (cmdSyntaxPtr)(ct46) // Disable Hot-key checking
-
-#if 0
-// COMMAND 47: Send Protocol info via Unix flags:
-// iflag = Unix tty t_iflag
-// cflag = Unix tty t_cflag
-// lflag = Unix tty t_lflag
-// See System V Unix/Xenix documentation for the meanings of the bit fields
-// within these flags
-//
-#define CMD_UNIX_FLAGS(iflag,cflag,lflag) i2cmdUnixFlags(iflag,cflag,lflag)
-#endif  /*  0  */
-
-#define CMD_DSRFL_ENAB  (cmdSyntaxPtr)(ct48) // Enable  DSR receiver ctrl
-#define CMD_DSRFL_DSAB  (cmdSyntaxPtr)(ct49) // Disable DSR receiver ctrl
-#define CMD_DTRFL_ENAB  (cmdSyntaxPtr)(ct50) // Enable  DTR flow control
-#define CMD_DTRFL_DSAB  (cmdSyntaxPtr)(ct51) // Disable DTR flow control
-#define CMD_BAUD_RESET  (cmdSyntaxPtr)(ct52) // Reset baudrate table
-
-// COMMAND 54: Define custom rate #1
-// rate = (short) 1/10 of the desired baud rate
-//
-#define CMD_BAUD_DEF1(rate) i2cmdBaudDef(1,rate)
-
-// COMMAND 55: Define custom rate #2
-// rate = (short) 1/10 of the desired baud rate
-//
-#define CMD_BAUD_DEF2(rate) i2cmdBaudDef(2,rate)
-
-// Pause arg hundredths of seconds. (Note, this is NOT milliseconds.)
-//
-#define CMD_PAUSE(arg) \
-	(((cmdSyntaxPtr)(ct56))->cmd[1] = (arg),(cmdSyntaxPtr)(ct56))
-
-#define CMD_SUSPEND     (cmdSyntaxPtr)(ct57) // Suspend output
-#define CMD_UNSUSPEND   (cmdSyntaxPtr)(ct58) // Un-Suspend output
-
-// Set parity-checking options
-//
-#define CMD_PARCHK(arg) \
-	(((cmdSyntaxPtr)(ct59))->cmd[1] = (arg),(cmdSyntaxPtr)(ct59))
-
-#define CPK_ENAB  0     // Enable parity checking on input
-#define CPK_DSAB  1     // Disable parity checking on input
-
-#define CMD_BMARK_REQ   (cmdSyntaxPtr)(ct60) // Bookmark request
-
-
-// Enable/Disable internal loopback mode
-//
-#define CMD_INLOOP(arg) \
-	(((cmdSyntaxPtr)(ct61))->cmd[1] = (arg),(cmdSyntaxPtr)(ct61))
-
-#define CIN_DISABLE  0  // Normal operation (default)
-#define CIN_ENABLE   1  // Internal (local) loopback
-#define CIN_REMOTE   2  // Remote loopback
-
-// Specify timeout for hotkeys: Delay will be (arg x 10) milliseconds, arg == 0
-// --> no timeout: wait forever.
-//
-#define CMD_HOT_TIME(arg) \
-	(((cmdSyntaxPtr)(ct62))->cmd[1] = (arg),(cmdSyntaxPtr)(ct62))
-
-
-// Define (outgoing) xon for receive flow control
-//
-#define CMD_DEF_OXON(arg) \
-	(((cmdSyntaxPtr)(ct63))->cmd[1] = (arg),(cmdSyntaxPtr)(ct63))
-
-// Define (outgoing) xoff for receiver flow control
-//
-#define CMD_DEF_OXOFF(arg) \
-	(((cmdSyntaxPtr)(ct64))->cmd[1] = (arg),(cmdSyntaxPtr)(ct64))
-
-// Enable/Disable RTS on transmit (1/2 duplex-style)
-//
-#define CMD_RTS_XMIT(arg) \
-	(((cmdSyntaxPtr)(ct65))->cmd[1] = (arg),(cmdSyntaxPtr)(ct65))
-
-#define CHD_DISABLE  0
-#define CHD_ENABLE   1
-
-// Set high-water-mark level (debugging use only)
-//
-#define CMD_SETHIGHWAT(arg) \
-	(((cmdSyntaxPtr)(ct66))->cmd[1] = (arg),(cmdSyntaxPtr)(ct66))
-
-// Start flushing tagged data (tag = 0-14)
-//
-#define CMD_START_SELFL(tag) \
-	(((cmdSyntaxPtr)(ct67))->cmd[1] = (tag),(cmdSyntaxPtr)(ct67))
-
-// End flushing tagged data (tag = 0-14)
-//
-#define CMD_END_SELFL(tag) \
-	(((cmdSyntaxPtr)(ct68))->cmd[1] = (tag),(cmdSyntaxPtr)(ct68))
-
-#define CMD_HWFLOW_OFF  (cmdSyntaxPtr)(ct69) // Disable HW TX flow control
-#define CMD_ODSRFL_ENAB (cmdSyntaxPtr)(ct70) // Enable DSR output f/c
-#define CMD_ODSRFL_DSAB (cmdSyntaxPtr)(ct71) // Disable DSR output f/c
-#define CMD_ODCDFL_ENAB (cmdSyntaxPtr)(ct72) // Enable DCD output f/c
-#define CMD_ODCDFL_DSAB (cmdSyntaxPtr)(ct73) // Disable DCD output f/c
-
-// Set transmit interrupt load level. Count should be an even value 2-12
-//
-#define CMD_LOADLEVEL(count) \
-	(((cmdSyntaxPtr)(ct74))->cmd[1] = (count),(cmdSyntaxPtr)(ct74))
-
-// If reporting DSS changes, map to character sequence FFh, 2, MSR
-//
-#define CMD_STATDATA(arg) \
-	(((cmdSyntaxPtr)(ct75))->cmd[1] = (arg),(cmdSyntaxPtr)(ct75))
-
-#define CSTD_DISABLE// Report DSS changes as status packets only (default)
-#define CSTD_ENABLE	// Report DSS changes as in-band data sequence as well as
-					// by status packet.
-
-#define CMD_BREAK_ON    (cmdSyntaxPtr)(ct76)// Set break and stop xmit
-#define CMD_BREAK_OFF   (cmdSyntaxPtr)(ct77)// End break and restart xmit
-#define CMD_GETFC       (cmdSyntaxPtr)(ct78)// Request for flow control packet
-											// from board.
-
-// Transmit this character immediately
-//
-#define CMD_XMIT_NOW(ch) \
-	(((cmdSyntaxPtr)(ct79))->cmd[1] = (ch),(cmdSyntaxPtr)(ct79))
-
-// Set baud rate via "divisor latch"
-//
-#define CMD_DIVISOR_LATCH(which,value) \
-			(((cmdSyntaxPtr)(ct80))->cmd[1] = (which), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct80))->cmd[2]) = (value), \
-			(cmdSyntaxPtr)(ct80))
-
-#define CDL_RX 1	// Set receiver rate
-#define CDL_TX 2	// Set transmit rate
-					// (CDL_TX | CDL_RX) Set both rates
-
-// Request for special diagnostic status pkt from the board.
-//
-#define CMD_GET_STATUS (cmdSyntaxPtr)(ct81)
-
-// Request time-stamped transmit character count packet.
-//
-#define CMD_GET_TXCNT  (cmdSyntaxPtr)(ct82)
-
-// Request time-stamped receive character count packet.
-//
-#define CMD_GET_RXCNT  (cmdSyntaxPtr)(ct83)
-
-// Request for box/board I.D. packet.
-#define CMD_GET_BOXIDS (cmdSyntaxPtr)(ct84)
-
-// Enable or disable multiple channels according to bit-mapped ushorts box 1-4
-//
-#define CMD_ENAB_MULT(enable, box1, box2, box3, box4)    \
-			(((cmdSytaxPtr)(ct85))->cmd[1] = (enable),            \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[2]) = (box1), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[4]) = (box2), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[6]) = (box3), \
-			*(USHORT *)(((cmdSyntaxPtr)(ct85))->cmd[8]) = (box4), \
-			(cmdSyntaxPtr)(ct85))
-
-#define CEM_DISABLE  0
-#define CEM_ENABLE   1
-
-// Enable or disable receiver or receiver interrupts (default both enabled)
-//
-#define CMD_RCV_ENABLE(ch) \
-	(((cmdSyntaxPtr)(ct86))->cmd[1] = (ch),(cmdSyntaxPtr)(ct86))
-
-#define CRE_OFF      0  // Disable the receiver
-#define CRE_ON       1  // Enable the receiver
-#define CRE_INTOFF   2  // Disable receiver interrupts (to loadware)
-#define CRE_INTON    3  // Enable receiver interrupts (to loadware)
-
-// Starts up a hardware test process, which runs transparently, and sends a
-// STAT_HWFAIL packet in case a hardware failure is detected.
-//
-#define CMD_HW_TEST  (cmdSyntaxPtr)(ct87)
-
-// Change receiver threshold and timeout value:
-// Defaults: timeout = 20mS
-// threshold count = 8 when DTRflow not in use,
-// threshold count = 5 when DTRflow in use.
-//
-#define CMD_RCV_THRESHOLD(count,ms) \
-			(((cmdSyntaxPtr)(ct88))->cmd[1] = (count), \
-			((cmdSyntaxPtr)(ct88))->cmd[2] = (ms), \
-			(cmdSyntaxPtr)(ct88))
-
-// Makes the loadware report DSS signals for this channel immediately.
-//
-#define CMD_DSS_NOW (cmdSyntaxPtr)(ct89)
-	
-// Set the receive silo parameters 
-// 	timeout is ms idle wait until delivery       (~VTIME)
-// 	threshold is max characters cause interrupt  (~VMIN)
-//
-#define CMD_SET_SILO(timeout,threshold) \
-			(((cmdSyntaxPtr)(ct90))->cmd[1] = (timeout), \
-			((cmdSyntaxPtr)(ct90))->cmd[2]  = (threshold), \
-			(cmdSyntaxPtr)(ct90))
-
-// Set timed break in decisecond (1/10s)
-//
-#define CMD_LBREAK(ds) \
-	(((cmdSyntaxPtr)(ct91))->cmd[1] = (ds),(cmdSyntaxPtr)(ct66))
-
-
-
-#endif // I2CMD_H
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2ellis.c linux-libre-2.6.39-gnu/drivers/char/ip2/i2ellis.c
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2ellis.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2ellis.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1403 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Low-level interface code for the device driver
-*                (This is included source code, not a separate compilation
-*                module.)
-*
-*******************************************************************************/
-//---------------------------------------------
-// Function declarations private to this module
-//---------------------------------------------
-// Functions called only indirectly through i2eBordStr entries.
-
-static int iiWriteBuf16(i2eBordStrPtr, unsigned char *, int);
-static int iiWriteBuf8(i2eBordStrPtr, unsigned char *, int);
-static int iiReadBuf16(i2eBordStrPtr, unsigned char *, int);
-static int iiReadBuf8(i2eBordStrPtr, unsigned char *, int);
-
-static unsigned short iiReadWord16(i2eBordStrPtr);
-static unsigned short iiReadWord8(i2eBordStrPtr);
-static void iiWriteWord16(i2eBordStrPtr, unsigned short);
-static void iiWriteWord8(i2eBordStrPtr, unsigned short);
-
-static int iiWaitForTxEmptyII(i2eBordStrPtr, int);
-static int iiWaitForTxEmptyIIEX(i2eBordStrPtr, int);
-static int iiTxMailEmptyII(i2eBordStrPtr);
-static int iiTxMailEmptyIIEX(i2eBordStrPtr);
-static int iiTrySendMailII(i2eBordStrPtr, unsigned char);
-static int iiTrySendMailIIEX(i2eBordStrPtr, unsigned char);
-
-static unsigned short iiGetMailII(i2eBordStrPtr);
-static unsigned short iiGetMailIIEX(i2eBordStrPtr);
-
-static void iiEnableMailIrqII(i2eBordStrPtr);
-static void iiEnableMailIrqIIEX(i2eBordStrPtr);
-static void iiWriteMaskII(i2eBordStrPtr, unsigned char);
-static void iiWriteMaskIIEX(i2eBordStrPtr, unsigned char);
-
-static void ii2Nop(void);
-
-//***************
-//* Static Data *
-//***************
-
-static int ii2Safe;         // Safe I/O address for delay routine
-
-static int iiDelayed;	// Set when the iiResetDelay function is
-							// called. Cleared when ANY board is reset.
-static DEFINE_RWLOCK(Dl_spinlock);
-
-//********
-//* Code *
-//********
-
-//=======================================================
-// Initialization Routines
-//
-// iiSetAddress
-// iiReset
-// iiResetDelay
-// iiInitialize
-//=======================================================
-
-//******************************************************************************
-// Function:   iiSetAddress(pB, address, delay)
-// Parameters: pB      - pointer to the board structure
-//             address - the purported I/O address of the board
-//             delay   - pointer to the 1-ms delay function to use
-//                       in this and any future operations to this board
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// This routine (roughly) checks for address validity, sets the i2eValid OK and
-// sets the state to II_STATE_COLD which means that we haven't even sent a reset
-// yet.
-//
-//******************************************************************************
-static int
-iiSetAddress( i2eBordStrPtr pB, int address, delayFunc_t delay )
-{
-	// Should any failure occur before init is finished...
-	pB->i2eValid = I2E_INCOMPLETE;
-
-	// Cannot check upper limit except extremely: Might be microchannel
-	// Address must be on an 8-byte boundary
-
-	if ((unsigned int)address <= 0x100
-		|| (unsigned int)address >= 0xfff8
-		|| (address & 0x7)
-		)
-	{
-		I2_COMPLETE(pB, I2EE_BADADDR);
-	}
-
-	// Initialize accelerators
-	pB->i2eBase    = address;
-	pB->i2eData    = address + FIFO_DATA;
-	pB->i2eStatus  = address + FIFO_STATUS;
-	pB->i2ePointer = address + FIFO_PTR;
-	pB->i2eXMail   = address + FIFO_MAIL;
-	pB->i2eXMask   = address + FIFO_MASK;
-
-	// Initialize i/o address for ii2DelayIO
-	ii2Safe = address + FIFO_NOP;
-
-	// Initialize the delay routine
-	pB->i2eDelay = ((delay != (delayFunc_t)NULL) ? delay : (delayFunc_t)ii2Nop);
-
-	pB->i2eValid = I2E_MAGIC;
-	pB->i2eState = II_STATE_COLD;
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReset(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Attempts to reset the board (see also i2hw.h). Normally, we would use this to
-// reset a board immediately after iiSetAddress(), but it is valid to reset a
-// board from any state, say, in order to change or re-load loadware. (Under
-// such circumstances, no reason to re-run iiSetAddress(), which is why it is a
-// separate routine and not included in this routine.
-//
-//******************************************************************************
-static int
-iiReset(i2eBordStrPtr pB)
-{
-	// Magic number should be set, else even the address is suspect
-	if (pB->i2eValid != I2E_MAGIC)
-	{
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-
-	outb(0, pB->i2eBase + FIFO_RESET);  /* Any data will do */
-	iiDelay(pB, 50);                    // Pause between resets
-	outb(0, pB->i2eBase + FIFO_RESET);  /* Second reset */
-
-	// We must wait before even attempting to read anything from the FIFO: the
-	// board's P.O.S.T may actually attempt to read and write its end of the
-	// FIFO in order to check flags, loop back (where supported), etc. On
-	// completion of this testing it would reset the FIFO, and on completion
-	// of all // P.O.S.T., write the message. We must not mistake data which
-	// might have been sent for testing as part of the reset message. To
-	// better utilize time, say, when resetting several boards, we allow the
-	// delay to be performed externally; in this way the caller can reset 
-	// several boards, delay a single time, then call the initialization
-	// routine for all.
-
-	pB->i2eState = II_STATE_RESET;
-
-	iiDelayed = 0;	// i.e., the delay routine hasn't been called since the most
-					// recent reset.
-
-	// Ensure anything which would have been of use to standard loadware is
-	// blanked out, since board has now forgotten everything!.
-
-	pB->i2eUsingIrq = I2_IRQ_UNDEFINED; /* to not use an interrupt so far */
-	pB->i2eWaitingForEmptyFifo = 0;
-	pB->i2eOutMailWaiting = 0;
-	pB->i2eChannelPtr = NULL;
-	pB->i2eChannelCnt = 0;
-
-	pB->i2eLeadoffWord[0] = 0;
-	pB->i2eFifoInInts = 0;
-	pB->i2eFifoOutInts = 0;
-	pB->i2eFatalTrap = NULL;
-	pB->i2eFatal = 0;
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiResetDelay(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Using the delay defined in board structure, waits two seconds (for board to
-// reset).
-//
-//******************************************************************************
-static int
-iiResetDelay(i2eBordStrPtr pB)
-{
-	if (pB->i2eValid != I2E_MAGIC) {
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-	if (pB->i2eState != II_STATE_RESET) {
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-	iiDelay(pB,2000);       /* Now we wait for two seconds. */
-	iiDelayed = 1;          /* Delay has been called: ok to initialize */
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiInitialize(pB)
-// Parameters: pB - pointer to the board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Attempts to read the Power-on reset message. Initializes any remaining fields
-// in the pB structure.
-//
-// This should be called as the third step of a process beginning with
-// iiReset(), then iiResetDelay(). This routine checks to see that the structure
-// is "valid" and in the reset state, also confirms that the delay routine has
-// been called since the latest reset (to any board! overly strong!).
-//
-//******************************************************************************
-static int
-iiInitialize(i2eBordStrPtr pB)
-{
-	int itemp;
-	unsigned char c;
-	unsigned short utemp;
-	unsigned int ilimit;
-
-	if (pB->i2eValid != I2E_MAGIC)
-	{
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-
-	if (pB->i2eState != II_STATE_RESET || !iiDelayed)
-	{
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-
-	// In case there is a failure short of our completely reading the power-up
-	// message.
-	pB->i2eValid = I2E_INCOMPLETE;
-
-
-	// Now attempt to read the message.
-
-	for (itemp = 0; itemp < sizeof(porStr); itemp++)
-	{
-		// We expect the entire message is ready.
-		if (!I2_HAS_INPUT(pB)) {
-			pB->i2ePomSize = itemp;
-			I2_COMPLETE(pB, I2EE_PORM_SHORT);
-		}
-
-		pB->i2ePom.c[itemp] = c = inb(pB->i2eData);
-
-		// We check the magic numbers as soon as they are supposed to be read
-		// (rather than after) to minimize effect of reading something we
-		// already suspect can't be "us".
-		if (  (itemp == POR_1_INDEX && c != POR_MAGIC_1) ||
-				(itemp == POR_2_INDEX && c != POR_MAGIC_2))
-		{
-			pB->i2ePomSize = itemp+1;
-			I2_COMPLETE(pB, I2EE_BADMAGIC);
-		}
-	}
-
-	pB->i2ePomSize = itemp;
-
-	// Ensure that this was all the data...
-	if (I2_HAS_INPUT(pB))
-		I2_COMPLETE(pB, I2EE_PORM_LONG);
-
-	// For now, we'll fail to initialize if P.O.S.T reports bad chip mapper:
-	// Implying we will not be able to download any code either:  That's ok: the
-	// condition is pretty explicit.
-	if (pB->i2ePom.e.porDiag1 & POR_BAD_MAPPER)
-	{
-		I2_COMPLETE(pB, I2EE_POSTERR);
-	}
-
-	// Determine anything which must be done differently depending on the family
-	// of boards!
-	switch (pB->i2ePom.e.porID & POR_ID_FAMILY)
-	{
-	case POR_ID_FII:  // IntelliPort-II
-
-		pB->i2eFifoStyle   = FIFO_II;
-		pB->i2eFifoSize    = 512;     // 512 bytes, always
-		pB->i2eDataWidth16 = false;
-
-		pB->i2eMaxIrq = 15;	// Because board cannot tell us it is in an 8-bit
-							// slot, we do allow it to be done (documentation!)
-
-		pB->i2eGoodMap[1] =
-		pB->i2eGoodMap[2] =
-		pB->i2eGoodMap[3] =
-		pB->i2eChannelMap[1] =
-		pB->i2eChannelMap[2] =
-		pB->i2eChannelMap[3] = 0;
-
-		switch (pB->i2ePom.e.porID & POR_ID_SIZE)
-		{
-		case POR_ID_II_4:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0x0f;  // four-port
-
-			// Since porPorts1 is based on the Hardware ID register, the numbers
-			// should always be consistent for IntelliPort-II.  Ditto below...
-			if (pB->i2ePom.e.porPorts1 != 4)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-
-		case POR_ID_II_8:
-		case POR_ID_II_8R:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0xff;  // Eight port
-			if (pB->i2ePom.e.porPorts1 != 8)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-
-		case POR_ID_II_6:
-			pB->i2eGoodMap[0] =
-			pB->i2eChannelMap[0] = 0x3f;  // Six Port
-			if (pB->i2ePom.e.porPorts1 != 6)
-			{
-				I2_COMPLETE(pB, I2EE_INCONSIST);
-			}
-			break;
-		}
-
-		// Fix up the "good channel list based on any errors reported.
-		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART1)
-		{
-			pB->i2eGoodMap[0] &= ~0x0f;
-		}
-
-		if (pB->i2ePom.e.porDiag1 & POR_BAD_UART2)
-		{
-			pB->i2eGoodMap[0] &= ~0xf0;
-		}
-
-		break;   // POR_ID_FII case
-
-	case POR_ID_FIIEX:   // IntelliPort-IIEX
-
-		pB->i2eFifoStyle = FIFO_IIEX;
-
-		itemp = pB->i2ePom.e.porFifoSize;
-
-		// Implicit assumption that fifo would not grow beyond 32k, 
-		// nor would ever be less than 256.
-
-		if (itemp < 8 || itemp > 15)
-		{
-			I2_COMPLETE(pB, I2EE_INCONSIST);
-		}
-		pB->i2eFifoSize = (1 << itemp);
-
-		// These are based on what P.O.S.T thinks should be there, based on
-		// box ID registers
-		ilimit = pB->i2ePom.e.porNumBoxes;
-		if (ilimit > ABS_MAX_BOXES)
-		{
-			ilimit = ABS_MAX_BOXES;
-		}
-
-		// For as many boxes as EXIST, gives the type of box.
-		// Added 8/6/93: check for the ISA-4 (asic) which looks like an
-		// expandable but for whom "8 or 16?" is not the right question.
-
-		utemp = pB->i2ePom.e.porFlags;
-		if (utemp & POR_CEX4)
-		{
-			pB->i2eChannelMap[0] = 0x000f;
-		} else {
-			utemp &= POR_BOXES;
-			for (itemp = 0; itemp < ilimit; itemp++)
-			{
-				pB->i2eChannelMap[itemp] = 
-					((utemp & POR_BOX_16) ? 0xffff : 0x00ff);
-				utemp >>= 1;
-			}
-		}
-
-		// These are based on what P.O.S.T actually found.
-
-		utemp = (pB->i2ePom.e.porPorts2 << 8) + pB->i2ePom.e.porPorts1;
-
-		for (itemp = 0; itemp < ilimit; itemp++)
-		{
-			pB->i2eGoodMap[itemp] = 0;
-			if (utemp & 1) pB->i2eGoodMap[itemp] |= 0x000f;
-			if (utemp & 2) pB->i2eGoodMap[itemp] |= 0x00f0;
-			if (utemp & 4) pB->i2eGoodMap[itemp] |= 0x0f00;
-			if (utemp & 8) pB->i2eGoodMap[itemp] |= 0xf000;
-			utemp >>= 4;
-		}
-
-		// Now determine whether we should transfer in 8 or 16-bit mode.
-		switch (pB->i2ePom.e.porBus & (POR_BUS_SLOT16 | POR_BUS_DIP16) )
-		{
-		case POR_BUS_SLOT16 | POR_BUS_DIP16:
-			pB->i2eDataWidth16 = true;
-			pB->i2eMaxIrq = 15;
-			break;
-
-		case POR_BUS_SLOT16:
-			pB->i2eDataWidth16 = false;
-			pB->i2eMaxIrq = 15;
-			break;
-
-		case 0:
-		case POR_BUS_DIP16:     // In an 8-bit slot, DIP switch don't care.
-		default:
-			pB->i2eDataWidth16 = false;
-			pB->i2eMaxIrq = 7;
-			break;
-		}
-		break;   // POR_ID_FIIEX case
-
-	default:    // Unknown type of board
-		I2_COMPLETE(pB, I2EE_BAD_FAMILY);
-		break;
-	}  // End the switch based on family
-
-	// Temporarily, claim there is no room in the outbound fifo. 
-	// We will maintain this whenever we check for an empty outbound FIFO.
-	pB->i2eFifoRemains = 0;
-
-	// Now, based on the bus type, should we expect to be able to re-configure
-	// interrupts (say, for testing purposes).
-	switch (pB->i2ePom.e.porBus & POR_BUS_TYPE)
-	{
-	case POR_BUS_T_ISA:
-	case POR_BUS_T_UNK:  // If the type of bus is undeclared, assume ok.
-	case POR_BUS_T_MCA:
-	case POR_BUS_T_EISA:
-		break;
-	default:
-		I2_COMPLETE(pB, I2EE_BADBUS);
-	}
-
-	if (pB->i2eDataWidth16)
-	{
-		pB->i2eWriteBuf  = iiWriteBuf16;
-		pB->i2eReadBuf   = iiReadBuf16;
-		pB->i2eWriteWord = iiWriteWord16;
-		pB->i2eReadWord  = iiReadWord16;
-	} else {
-		pB->i2eWriteBuf  = iiWriteBuf8;
-		pB->i2eReadBuf   = iiReadBuf8;
-		pB->i2eWriteWord = iiWriteWord8;
-		pB->i2eReadWord  = iiReadWord8;
-	}
-
-	switch(pB->i2eFifoStyle)
-	{
-	case FIFO_II:
-		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyII;
-		pB->i2eTxMailEmpty    = iiTxMailEmptyII;
-		pB->i2eTrySendMail    = iiTrySendMailII;
-		pB->i2eGetMail        = iiGetMailII;
-		pB->i2eEnableMailIrq  = iiEnableMailIrqII;
-		pB->i2eWriteMask      = iiWriteMaskII;
-
-		break;
-
-	case FIFO_IIEX:
-		pB->i2eWaitForTxEmpty = iiWaitForTxEmptyIIEX;
-		pB->i2eTxMailEmpty    = iiTxMailEmptyIIEX;
-		pB->i2eTrySendMail    = iiTrySendMailIIEX;
-		pB->i2eGetMail        = iiGetMailIIEX;
-		pB->i2eEnableMailIrq  = iiEnableMailIrqIIEX;
-		pB->i2eWriteMask      = iiWriteMaskIIEX;
-
-		break;
-
-	default:
-		I2_COMPLETE(pB, I2EE_INCONSIST);
-	}
-
-	// Initialize state information.
-	pB->i2eState = II_STATE_READY;   // Ready to load loadware.
-
-	// Some Final cleanup:
-	// For some boards, the bootstrap firmware may perform some sort of test
-	// resulting in a stray character pending in the incoming mailbox. If one is
-	// there, it should be read and discarded, especially since for the standard
-	// firmware, it's the mailbox that interrupts the host.
-
-	pB->i2eStartMail = iiGetMail(pB);
-
-	// Throw it away and clear the mailbox structure element
-	pB->i2eStartMail = NO_MAIL_HERE;
-
-	// Everything is ok now, return with good status/
-
-	pB->i2eValid = I2E_MAGIC;
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   ii2DelayTimer(mseconds)
-// Parameters: mseconds - number of milliseconds to delay
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine delays for approximately mseconds milliseconds and is intended
-// to be called indirectly through i2Delay field in i2eBordStr. It uses the
-// Linux timer_list mechanism.
-//
-// The Linux timers use a unit called "jiffies" which are 10mS in the Intel
-// architecture. This function rounds the delay period up to the next "jiffy".
-// In the Alpha architecture the "jiffy" is 1mS, but this driver is not intended
-// for Alpha platforms at this time.
-//
-//******************************************************************************
-static void
-ii2DelayTimer(unsigned int mseconds)
-{
-	msleep_interruptible(mseconds);
-}
-
-#if 0
-//static void ii2DelayIO(unsigned int);
-//******************************************************************************
-// !!! Not Used, this is DOS crap, some of you young folks may be interested in
-//     in how things were done in the stone age of caculating machines       !!!
-// Function:   ii2DelayIO(mseconds)
-// Parameters: mseconds - number of milliseconds to delay
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// This routine delays for approximately mseconds milliseconds and is intended
-// to be called indirectly through i2Delay field in i2eBordStr. It is intended
-// for use where a clock-based function is impossible: for example, DOS drivers.
-//
-// This function uses the IN instruction to place bounds on the timing and
-// assumes that ii2Safe has been set. This is because I/O instructions are not
-// subject to caching and will therefore take a certain minimum time. To ensure
-// the delay is at least long enough on fast machines, it is based on some
-// fastest-case calculations.  On slower machines this may cause VERY long
-// delays. (3 x fastest case). In the fastest case, everything is cached except
-// the I/O instruction itself.
-//
-// Timing calculations:
-// The fastest bus speed for I/O operations is likely to be 10 MHz. The I/O
-// operation in question is a byte operation to an odd address. For 8-bit
-// operations, the architecture generally enforces two wait states. At 10 MHz, a
-// single cycle time is 100nS. A read operation at two wait states takes 6
-// cycles for a total time of 600nS. Therefore approximately 1666 iterations
-// would be required to generate a single millisecond delay. The worst
-// (reasonable) case would be an 8MHz system with no cacheing. In this case, the
-// I/O instruction would take 125nS x 6 cyles = 750 nS. More importantly, code
-// fetch of other instructions in the loop would take time (zero wait states,
-// however) and would be hard to estimate. This is minimized by using in-line
-// assembler for the in inner loop of IN instructions. This consists of just a
-// few bytes. So we'll guess about four code fetches per loop. Each code fetch
-// should take four cycles, so we have 125nS * 8 = 1000nS. Worst case then is
-// that what should have taken 1 mS takes instead 1666 * (1750) = 2.9 mS.
-//
-// So much for theoretical timings: results using 1666 value on some actual
-// machines:
-// IBM      286      6MHz     3.15 mS
-// Zenith   386      33MHz    2.45 mS
-// (brandX) 386      33MHz    1.90 mS  (has cache)
-// (brandY) 486      33MHz    2.35 mS
-// NCR      486      ??       1.65 mS (microchannel)
-//
-// For most machines, it is probably safe to scale this number back (remember,
-// for robust operation use an actual timed delay if possible), so we are using
-// a value of 1190. This yields 1.17 mS for the fastest machine in our sample,
-// 1.75 mS for typical 386 machines, and 2.25 mS the absolute slowest machine.
-//
-// 1/29/93:
-// The above timings are too slow. Actual cycle times might be faster. ISA cycle
-// times could approach 500 nS, and ...
-// The IBM model 77 being microchannel has no wait states for 8-bit reads and
-// seems to be accessing the I/O at 440 nS per access (from start of one to
-// start of next). This would imply we need 1000/.440 = 2272 iterations to
-// guarantee we are fast enough. In actual testing, we see that 2 * 1190 are in
-// fact enough. For diagnostics, we keep the level at 1190, but developers note
-// this needs tuning.
-//
-// Safe assumption:  2270 i/o reads = 1 millisecond
-//
-//******************************************************************************
-
-
-static int ii2DelValue = 1190;  // See timing calculations below
-						// 1666 for fastest theoretical machine
-						// 1190 safe for most fast 386 machines
-						// 1000 for fastest machine tested here
-						//  540 (sic) for AT286/6Mhz
-static void
-ii2DelayIO(unsigned int mseconds)
-{
-	if (!ii2Safe) 
-		return;   /* Do nothing if this variable uninitialized */
-
-	while(mseconds--) {
-		int i = ii2DelValue;
-		while ( i-- ) {
-			inb(ii2Safe);
-		}
-	}
-}
-#endif 
-
-//******************************************************************************
-// Function:   ii2Nop()
-// Parameters: None
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// iiInitialize will set i2eDelay to this if the delay parameter is NULL. This
-// saves checking for a NULL pointer at every call.
-//******************************************************************************
-static void
-ii2Nop(void)
-{
-	return;	// no mystery here
-}
-
-//=======================================================
-// Routines which are available in 8/16-bit versions, or
-// in different fifo styles. These are ALL called
-// indirectly through the board structure.
-//=======================================================
-
-//******************************************************************************
-// Function:   iiWriteBuf16(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address of data to write
-//             count   - number of data bytes to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes 'count' bytes from 'address' to the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// sent (identity unknown...). Uses 16-bit (word) operations. Is called
-// indirectly through pB->i2eWriteBuf.
-//
-//******************************************************************************
-static int
-iiWriteBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_OUTSW(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiWriteBuf8(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address of data to write
-//             count   - number of data bytes to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes 'count' bytes from 'address' to the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// sent (identity unknown...). This is to be consistent with the 16-bit version.
-// Uses 8-bit (byte) operations. Is called indirectly through pB->i2eWriteBuf.
-//
-//******************************************************************************
-static int
-iiWriteBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	/* Rudimentary sanity checking here */
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_OUTSB(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadBuf16(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address to put data read
-//             count   - number of data bytes to read
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Reads 'count' bytes into 'address' from the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// received (identity unknown...). Uses 16-bit (word) operations. Is called
-// indirectly through pB->i2eReadBuf.
-//
-//******************************************************************************
-static int
-iiReadBuf16(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_INSW(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadBuf8(pB, address, count)
-// Parameters: pB      - pointer to board structure
-//             address - address to put data read
-//             count   - number of data bytes to read
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Reads 'count' bytes into 'address' from the data fifo specified by the board
-// structure pointer pB. Should count happen to be odd, an extra pad byte is
-// received (identity unknown...). This to match the 16-bit behaviour. Uses
-// 8-bit (byte) operations. Is called indirectly through pB->i2eReadBuf.
-//
-//******************************************************************************
-static int
-iiReadBuf8(i2eBordStrPtr pB, unsigned char *address, int count)
-{
-	// Rudimentary sanity checking here.
-	if (pB->i2eValid != I2E_MAGIC)
-		I2_COMPLETE(pB, I2EE_INVALID);
-
-	I2_INSB(pB->i2eData, address, count);
-
-	I2_COMPLETE(pB, I2EE_GOOD);
-}
-
-//******************************************************************************
-// Function:   iiReadWord16(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Returns the word read from the data fifo specified by the board-structure
-// pointer pB. Uses a 16-bit operation. Is called indirectly through
-// pB->i2eReadWord.
-//
-//******************************************************************************
-static unsigned short
-iiReadWord16(i2eBordStrPtr pB)
-{
-	return inw(pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiReadWord8(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Returns the word read from the data fifo specified by the board-structure
-// pointer pB. Uses two 8-bit operations. Bytes are assumed to be LSB first. Is
-// called indirectly through pB->i2eReadWord.
-//
-//******************************************************************************
-static unsigned short
-iiReadWord8(i2eBordStrPtr pB)
-{
-	unsigned short urs;
-
-	urs = inb(pB->i2eData);
-
-	return (inb(pB->i2eData) << 8) | urs;
-}
-
-//******************************************************************************
-// Function:   iiWriteWord16(pB, value)
-// Parameters: pB    - pointer to board structure
-//             value - data to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes the word 'value' to the data fifo specified by the board-structure
-// pointer pB. Uses 16-bit operation. Is called indirectly through
-// pB->i2eWriteWord.
-//
-//******************************************************************************
-static void
-iiWriteWord16(i2eBordStrPtr pB, unsigned short value)
-{
-	outw((int)value, pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiWriteWord8(pB, value)
-// Parameters: pB    - pointer to board structure
-//             value - data to write
-//
-// Returns:    True if everything appears copacetic.
-//             False if there is any error: the pB->i2eError field has the error
-//
-// Description:
-//
-// Writes the word 'value' to the data fifo specified by the board-structure
-// pointer pB. Uses two 8-bit operations (writes LSB first). Is called
-// indirectly through pB->i2eWriteWord.
-//
-//******************************************************************************
-static void
-iiWriteWord8(i2eBordStrPtr pB, unsigned short value)
-{
-	outb((char)value, pB->i2eData);
-	outb((char)(value >> 8), pB->i2eData);
-}
-
-//******************************************************************************
-// Function:   iiWaitForTxEmptyII(pB, mSdelay)
-// Parameters: pB      - pointer to board structure
-//             mSdelay - period to wait before returning
-//
-// Returns:    True if the FIFO is empty.
-//             False if it not empty in the required time: the pB->i2eError
-//             field has the error.
-//
-// Description:
-//
-// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
-// not empty by the required time, returns false and error in pB->i2eError,
-// otherwise returns true.
-//
-// mSdelay == 0 is taken to mean must be empty on the first test.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-// Note this routine is organized so that if status is ok there is no delay at
-// all called either before or after the test.  Is called indirectly through
-// pB->i2eWaitForTxEmpty.
-//
-//******************************************************************************
-static int
-iiWaitForTxEmptyII(i2eBordStrPtr pB, int mSdelay)
-{
-	unsigned long	flags;
-	int itemp;
-
-	for (;;)
-	{
-		// This routine hinges on being able to see the "other" status register
-		// (as seen by the local processor).  His incoming fifo is our outgoing
-		// FIFO.
-		//
-		// By the nature of this routine, you would be using this as part of a
-		// larger atomic context: i.e., you would use this routine to ensure the
-		// fifo empty, then act on this information. Between these two halves, 
-		// you will generally not want to service interrupts or in any way 
-		// disrupt the assumptions implicit in the larger context.
-		//
-		// Even worse, however, this routine "shifts" the status register to 
-		// point to the local status register which is not the usual situation.
-		// Therefore for extra safety, we force the critical section to be
-		// completely atomic, and pick up after ourselves before allowing any
-		// interrupts of any kind.
-
-
-		write_lock_irqsave(&Dl_spinlock, flags);
-		outb(SEL_COMMAND, pB->i2ePointer);
-		outb(SEL_CMD_SH, pB->i2ePointer);
-
-		itemp = inb(pB->i2eStatus);
-
-		outb(SEL_COMMAND, pB->i2ePointer);
-		outb(SEL_CMD_UNSH, pB->i2ePointer);
-
-		if (itemp & ST_IN_EMPTY)
-		{
-			I2_UPDATE_FIFO_ROOM(pB);
-			write_unlock_irqrestore(&Dl_spinlock, flags);
-			I2_COMPLETE(pB, I2EE_GOOD);
-		}
-
-		write_unlock_irqrestore(&Dl_spinlock, flags);
-
-		if (mSdelay-- == 0)
-			break;
-
-		iiDelay(pB, 1);      /* 1 mS granularity on checking condition */
-	}
-	I2_COMPLETE(pB, I2EE_TXE_TIME);
-}
-
-//******************************************************************************
-// Function:   iiWaitForTxEmptyIIEX(pB, mSdelay)
-// Parameters: pB      - pointer to board structure
-//             mSdelay - period to wait before returning
-//
-// Returns:    True if the FIFO is empty.
-//             False if it not empty in the required time: the pB->i2eError
-//             field has the error.
-//
-// Description:
-//
-// Waits up to "mSdelay" milliseconds for the outgoing FIFO to become empty; if
-// not empty by the required time, returns false and error in pB->i2eError,
-// otherwise returns true.
-//
-// mSdelay == 0 is taken to mean must be empty on the first test.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-// Note this routine is organized so that if status is ok there is no delay at
-// all called either before or after the test.  Is called indirectly through
-// pB->i2eWaitForTxEmpty.
-//
-//******************************************************************************
-static int
-iiWaitForTxEmptyIIEX(i2eBordStrPtr pB, int mSdelay)
-{
-	unsigned long	flags;
-
-	for (;;)
-	{
-		// By the nature of this routine, you would be using this as part of a
-		// larger atomic context: i.e., you would use this routine to ensure the
-		// fifo empty, then act on this information. Between these two halves,
-		// you will generally not want to service interrupts or in any way
-		// disrupt the assumptions implicit in the larger context.
-
-		write_lock_irqsave(&Dl_spinlock, flags);
-
-		if (inb(pB->i2eStatus) & STE_OUT_MT) {
-			I2_UPDATE_FIFO_ROOM(pB);
-			write_unlock_irqrestore(&Dl_spinlock, flags);
-			I2_COMPLETE(pB, I2EE_GOOD);
-		}
-		write_unlock_irqrestore(&Dl_spinlock, flags);
-
-		if (mSdelay-- == 0)
-			break;
-
-		iiDelay(pB, 1);      // 1 mS granularity on checking condition
-	}
-	I2_COMPLETE(pB, I2EE_TXE_TIME);
-}
-
-//******************************************************************************
-// Function:   iiTxMailEmptyII(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if the transmit mailbox is empty.
-//             False if it not empty.
-//
-// Description:
-//
-// Returns true or false according to whether the transmit mailbox is empty (and
-// therefore able to accept more mail)
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static int
-iiTxMailEmptyII(i2eBordStrPtr pB)
-{
-	int port = pB->i2ePointer;
-	outb(SEL_OUTMAIL, port);
-	return inb(port) == 0;
-}
-
-//******************************************************************************
-// Function:   iiTxMailEmptyIIEX(pB)
-// Parameters: pB      - pointer to board structure
-//
-// Returns:    True if the transmit mailbox is empty.
-//             False if it not empty.
-//
-// Description:
-//
-// Returns true or false according to whether the transmit mailbox is empty (and
-// therefore able to accept more mail)
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static int
-iiTxMailEmptyIIEX(i2eBordStrPtr pB)
-{
-	return !(inb(pB->i2eStatus) & STE_OUT_MAIL);
-}
-
-//******************************************************************************
-// Function:   iiTrySendMailII(pB,mail)
-// Parameters: pB   - pointer to board structure
-//             mail - value to write to mailbox
-//
-// Returns:    True if the transmit mailbox is empty, and mail is sent.
-//             False if it not empty.
-//
-// Description:
-//
-// If outgoing mailbox is empty, sends mail and returns true. If outgoing
-// mailbox is not empty, returns false.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static int
-iiTrySendMailII(i2eBordStrPtr pB, unsigned char mail)
-{
-	int port = pB->i2ePointer;
-
-	outb(SEL_OUTMAIL, port);
-	if (inb(port) == 0) {
-		outb(SEL_OUTMAIL, port);
-		outb(mail, port);
-		return 1;
-	}
-	return 0;
-}
-
-//******************************************************************************
-// Function:   iiTrySendMailIIEX(pB,mail)
-// Parameters: pB   - pointer to board structure
-//             mail - value to write to mailbox
-//
-// Returns:    True if the transmit mailbox is empty, and mail is sent.
-//             False if it not empty.
-//
-// Description:
-//
-// If outgoing mailbox is empty, sends mail and returns true. If outgoing
-// mailbox is not empty, returns false.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static int
-iiTrySendMailIIEX(i2eBordStrPtr pB, unsigned char mail)
-{
-	if (inb(pB->i2eStatus) & STE_OUT_MAIL)
-		return 0;
-	outb(mail, pB->i2eXMail);
-	return 1;
-}
-
-//******************************************************************************
-// Function:   iiGetMailII(pB,mail)
-// Parameters: pB   - pointer to board structure
-//
-// Returns:    Mailbox data or NO_MAIL_HERE.
-//
-// Description:
-//
-// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
-// the mailbox, which is guaranteed != NO_MAIL_HERE.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static unsigned short
-iiGetMailII(i2eBordStrPtr pB)
-{
-	if (I2_HAS_MAIL(pB)) {
-		outb(SEL_INMAIL, pB->i2ePointer);
-		return inb(pB->i2ePointer);
-	} else {
-		return NO_MAIL_HERE;
-	}
-}
-
-//******************************************************************************
-// Function:   iiGetMailIIEX(pB,mail)
-// Parameters: pB   - pointer to board structure
-//
-// Returns:    Mailbox data or NO_MAIL_HERE.
-//
-// Description:
-//
-// If no mail available, returns NO_MAIL_HERE otherwise returns the data from
-// the mailbox, which is guaranteed != NO_MAIL_HERE.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static unsigned short
-iiGetMailIIEX(i2eBordStrPtr pB)
-{
-	if (I2_HAS_MAIL(pB))
-		return inb(pB->i2eXMail);
-	else
-		return NO_MAIL_HERE;
-}
-
-//******************************************************************************
-// Function:   iiEnableMailIrqII(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static void
-iiEnableMailIrqII(i2eBordStrPtr pB)
-{
-	outb(SEL_MASK, pB->i2ePointer);
-	outb(ST_IN_MAIL, pB->i2ePointer);
-}
-
-//******************************************************************************
-// Function:   iiEnableMailIrqIIEX(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Enables board to interrupt host (only) by writing to host's in-bound mailbox.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static void
-iiEnableMailIrqIIEX(i2eBordStrPtr pB)
-{
-	outb(MX_IN_MAIL, pB->i2eXMask);
-}
-
-//******************************************************************************
-// Function:   iiWriteMaskII(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Writes arbitrary value to the mask register.
-//
-// This version operates on IntelliPort-II - style FIFO's
-//
-//******************************************************************************
-static void
-iiWriteMaskII(i2eBordStrPtr pB, unsigned char value)
-{
-	outb(SEL_MASK, pB->i2ePointer);
-	outb(value, pB->i2ePointer);
-}
-
-//******************************************************************************
-// Function:   iiWriteMaskIIEX(pB)
-// Parameters: pB - pointer to board structure
-//
-// Returns:    Nothing
-//
-// Description:
-//
-// Writes arbitrary value to the mask register.
-//
-// This version operates on IntelliPort-IIEX - style FIFO's
-//
-//******************************************************************************
-static void
-iiWriteMaskIIEX(i2eBordStrPtr pB, unsigned char value)
-{
-	outb(value, pB->i2eXMask);
-}
-
-//******************************************************************************
-// Function:   iiDownloadBlock(pB, pSource, isStandard)
-// Parameters: pB         - pointer to board structure
-//             pSource    - loadware block to download
-//             isStandard - True if "standard" loadware, else false.
-//
-// Returns:    Success or Failure
-//
-// Description:
-//
-// Downloads a single block (at pSource)to the board referenced by pB. Caller
-// sets isStandard to true/false according to whether the "standard" loadware is
-// what's being loaded. The normal process, then, is to perform an iiInitialize
-// to the board, then perform some number of iiDownloadBlocks using the returned
-// state to determine when download is complete.
-//
-// Possible return values: (see I2ELLIS.H)
-// II_DOWN_BADVALID
-// II_DOWN_BADFILE
-// II_DOWN_CONTINUING
-// II_DOWN_GOOD
-// II_DOWN_BAD
-// II_DOWN_BADSTATE
-// II_DOWN_TIMEOUT
-//
-// Uses the i2eState and i2eToLoad fields (initialized at iiInitialize) to
-// determine whether this is the first block, whether to check for magic
-// numbers, how many blocks there are to go...
-//
-//******************************************************************************
-static int
-iiDownloadBlock ( i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard)
-{
-	int itemp;
-	int loadedFirst;
-
-	if (pB->i2eValid != I2E_MAGIC) return II_DOWN_BADVALID;
-
-	switch(pB->i2eState)
-	{
-	case II_STATE_READY:
-
-		// Loading the first block after reset. Must check the magic number of the
-		// loadfile, store the number of blocks we expect to load.
-		if (pSource->e.loadMagic != MAGIC_LOADFILE)
-		{
-			return II_DOWN_BADFILE;
-		}
-
-		// Next we store the total number of blocks to load, including this one.
-		pB->i2eToLoad = 1 + pSource->e.loadBlocksMore;
-
-		// Set the state, store the version numbers. ('Cause this may have come
-		// from a file - we might want to report these versions and revisions in
-		// case of an error!
-		pB->i2eState = II_STATE_LOADING;
-		pB->i2eLVersion = pSource->e.loadVersion;
-		pB->i2eLRevision = pSource->e.loadRevision;
-		pB->i2eLSub = pSource->e.loadSubRevision;
-
-		// The time and date of compilation is also available but don't bother
-		// storing it for normal purposes.
-		loadedFirst = 1;
-		break;
-
-	case II_STATE_LOADING:
-		loadedFirst = 0;
-		break;
-
-	default:
-		return II_DOWN_BADSTATE;
-	}
-
-	// Now we must be in the II_STATE_LOADING state, and we assume i2eToLoad
-	// must be positive still, because otherwise we would have cleaned up last
-	// time and set the state to II_STATE_LOADED.
-	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
-		return II_DOWN_TIMEOUT;
-	}
-
-	if (!iiWriteBuf(pB, pSource->c, LOADWARE_BLOCK_SIZE)) {
-		return II_DOWN_BADVALID;
-	}
-
-	// If we just loaded the first block, wait for the fifo to empty an extra
-	// long time to allow for any special startup code in the firmware, like
-	// sending status messages to the LCD's.
-
-	if (loadedFirst) {
-		if (!iiWaitForTxEmpty(pB, MAX_DLOAD_START_TIME)) {
-			return II_DOWN_TIMEOUT;
-		}
-	}
-
-	// Determine whether this was our last block!
-	if (--(pB->i2eToLoad)) {
-		return II_DOWN_CONTINUING;    // more to come...
-	}
-
-	// It WAS our last block: Clean up operations...
-	// ...Wait for last buffer to drain from the board...
-	if (!iiWaitForTxEmpty(pB, MAX_DLOAD_READ_TIME)) {
-		return II_DOWN_TIMEOUT;
-	}
-	// If there were only a single block written, this would come back
-	// immediately and be harmless, though not strictly necessary.
-	itemp = MAX_DLOAD_ACK_TIME/10;
-	while (--itemp) {
-		if (I2_HAS_INPUT(pB)) {
-			switch (inb(pB->i2eData)) {
-			case LOADWARE_OK:
-				pB->i2eState =
-					isStandard ? II_STATE_STDLOADED :II_STATE_LOADED;
-
-				// Some revisions of the bootstrap firmware (e.g. ISA-8 1.0.2)
-				// will, // if there is a debug port attached, require some
-				// time to send information to the debug port now. It will do
-				// this before // executing any of the code we just downloaded.
-				// It may take up to 700 milliseconds.
-				if (pB->i2ePom.e.porDiag2 & POR_DEBUG_PORT) {
-					iiDelay(pB, 700);
-				}
-
-				return II_DOWN_GOOD;
-
-			case LOADWARE_BAD:
-			default:
-				return II_DOWN_BAD;
-			}
-		}
-
-		iiDelay(pB, 10);      // 10 mS granularity on checking condition
-	}
-
-	// Drop-through --> timed out waiting for firmware confirmation
-
-	pB->i2eState = II_STATE_BADLOAD;
-	return II_DOWN_TIMEOUT;
-}
-
-//******************************************************************************
-// Function:   iiDownloadAll(pB, pSource, isStandard, size)
-// Parameters: pB         - pointer to board structure
-//             pSource    - loadware block to download
-//             isStandard - True if "standard" loadware, else false.
-//             size       - size of data to download (in bytes)
-//
-// Returns:    Success or Failure
-//
-// Description:
-//
-// Given a pointer to a board structure, a pointer to the beginning of some
-// loadware, whether it is considered the "standard loadware", and the size of
-// the array in bytes loads the entire array to the board as loadware.
-//
-// Assumes the board has been freshly reset and the power-up reset message read.
-// (i.e., in II_STATE_READY). Complains if state is bad, or if there seems to be
-// too much or too little data to load, or if iiDownloadBlock complains.
-//******************************************************************************
-static int
-iiDownloadAll(i2eBordStrPtr pB, loadHdrStrPtr pSource, int isStandard, int size)
-{
-	int status;
-
-	// We know (from context) board should be ready for the first block of
-	// download.  Complain if not.
-	if (pB->i2eState != II_STATE_READY) return II_DOWN_BADSTATE;
-
-	while (size > 0) {
-		size -= LOADWARE_BLOCK_SIZE;	// How much data should there be left to
-										// load after the following operation ?
-
-		// Note we just bump pSource by "one", because its size is actually that
-		// of an entire block, same as LOADWARE_BLOCK_SIZE.
-		status = iiDownloadBlock(pB, pSource++, isStandard);
-
-		switch(status)
-		{
-		case II_DOWN_GOOD:
-			return ( (size > 0) ? II_DOWN_OVER : II_DOWN_GOOD);
-
-		case II_DOWN_CONTINUING:
-			break;
-
-		default:
-			return status;
-		}
-	}
-
-	// We shouldn't drop out: it means "while" caught us with nothing left to
-	// download, yet the previous DownloadBlock did not return complete. Ergo,
-	// not enough data to match the size byte in the header.
-	return II_DOWN_UNDER;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2ellis.h linux-libre-2.6.39-gnu/drivers/char/ip2/i2ellis.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2ellis.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2ellis.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,566 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Mainline code for the device driver
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// i2ellis.h
-//
-// IntelliPort-II and IntelliPort-IIEX
-//
-// Extremely
-// Low
-// Level
-// Interface
-// Services
-//
-// Structure Definitions and declarations for "ELLIS" service routines found in
-// i2ellis.c
-//
-// These routines are based on properties of the IntelliPort-II and -IIEX
-// hardware and bootstrap firmware, and are not sensitive to particular
-// conventions of any particular loadware.
-//
-// Unlike i2hw.h, which provides IRONCLAD hardware definitions, the material
-// here and in i2ellis.c is intended to provice a useful, but not required,
-// layer of insulation from the hardware specifics.
-//------------------------------------------------------------------------------
-#ifndef  I2ELLIS_H   /* To prevent multiple includes */
-#define  I2ELLIS_H   1
-//------------------------------------------------
-// Revision History:
-//
-// 30 September 1991 MAG First Draft Started
-// 12 October   1991 ...continued...
-//
-// 20 December  1996 AKM Linux version
-//-------------------------------------------------
-
-//----------------------
-// Mandatory Includes:
-//----------------------
-#include "ip2types.h"
-#include "i2hw.h"       // The hardware definitions
-
-//------------------------------------------
-// STAT_BOXIDS packets
-//------------------------------------------
-#define MAX_BOX		4
-
-typedef struct _bidStat
-{
-	unsigned char bid_value[MAX_BOX];
-} bidStat, *bidStatPtr;
-
-// This packet is sent in response to a CMD_GET_BOXIDS bypass command. For -IIEX
-// boards, reports the hardware-specific "asynchronous resource register" on
-// each expansion box. Boxes not present report 0xff. For -II boards, the first
-// element contains 0x80 for 8-port, 0x40 for 4-port boards.
-
-// Box IDs aka ARR or Async Resource Register (more than you want to know)
-//   7   6   5   4   3   2   1   0
-//   F   F   N   N   L   S   S   S
-//   =============================
-//   F   F   -  Product Family Designator
-//   =====+++++++++++++++++++++++++++++++
-//   0   0   -  Intelliport II EX / ISA-8
-//   1   0   -  IntelliServer
-//   0   1   -  SAC - Port Device (Intelliport III ??? )
-//           =====+++++++++++++++++++++++++++++++++++++++
-//           N   N   -  Number of Ports
-//           0   0   -  8  (eight)
-//           0   1   -  4  (four)
-//           1   0   -  12 (twelve)
-//           1   1   -  16 (sixteen)
-//                   =++++++++++++++++++++++++++++++++++
-//                   L  -   LCD Display Module Present
-//                   0  -   No
-//                   1  -   LCD module present
-//                   =========+++++++++++++++++++++++++++++++++++++
-//                      S   S   S - Async Signals Supported Designator
-//                      0   0   0 - 8dss, Mod DCE DB25 Female
-//                      0   0   1 - 6dss, RJ-45
-//                      0   1   0 - RS-232/422 dss, DB25 Female
-//                      0   1   1 - RS-232/422 dss, separate 232/422 DB25 Female
-//                      1   0   0 - 6dss, 921.6 I/F with ST654's
-//                      1   0   1 - RS-423/232 8dss, RJ-45 10Pin
-//                      1   1   0 - 6dss, Mod DCE DB25 Female
-//                      1   1   1 - NO BOX PRESENT
-
-#define FF(c)	((c & 0xC0) >> 6)
-#define NN(c)	((c & 0x30) >> 4)
-#define L(c)	((c & 0x08) >> 3)
-#define SSS(c)	 (c & 0x07)
-
-#define BID_HAS_654(x)	(SSS(x) == 0x04)
-#define BID_NO_BOX	0xff /* no box */
-#define BID_8PORT  	0x80 /* IP2-8 port */
-#define BID_4PORT   	0x81 /* IP2-4 port */
-#define BID_EXP_MASK   	0x30 /* IP2-EX  */
-#define BID_EXP_8PORT	0x00 /*     8, */
-#define BID_EXP_4PORT	0x10 /*     4, */
-#define BID_EXP_UNDEF	0x20 /*     UNDEF, */
-#define BID_EXP_16PORT	0x30 /*    16, */
-#define BID_LCD_CTRL   	0x08 /* LCD Controller */
-#define BID_LCD_NONE	0x00 /* - no controller present */
-#define BID_LCD_PRES   	0x08 /* - controller present */
-#define BID_CON_MASK	0x07 /* - connector pinouts */
-#define BID_CON_DB25	0x00 /* - DB-25 F */
-#define BID_CON_RJ45	0x01 /* - rj45 */
-
-//------------------------------------------------------------------------------
-// i2eBordStr
-//
-// This structure contains all the information the ELLIS routines require in
-// dealing with a particular board.
-//------------------------------------------------------------------------------
-// There are some queues here which are guaranteed to never contain the entry
-// for a single channel twice. So they must be slightly larger to allow
-// unambiguous full/empty management
-//
-#define CH_QUEUE_SIZE ABS_MOST_PORTS+2
-
-typedef struct _i2eBordStr
-{
-	porStr         i2ePom;	// Structure containing the power-on message.
-
-	unsigned short i2ePomSize;
-						// The number of bytes actually read if
-						// different from sizeof i2ePom, indicates
-						// there is an error!
-
-	unsigned short i2eStartMail;
-						// Contains whatever inbound mailbox data
-						// present at startup. NO_MAIL_HERE indicates
-						// nothing was present. No special
-						// significance as of this writing, but may be
-						// useful for diagnostic reasons.
-
-	unsigned short i2eValid;
-						// Indicates validity of the structure; if
-						// i2eValid == I2E_MAGIC, then we can trust
-						// the other fields. Some (especially
-						// initialization) functions are good about
-						// checking for validity.  Many functions do
-						// not, it being assumed that the larger
-						// context assures we are using a valid
-						// i2eBordStrPtr.
-
-	unsigned short i2eError;
-						// Used for returning an error condition from
-						// several functions which use i2eBordStrPtr
-						// as an argument.
-
-	// Accelerators to characterize separate features of a board, derived from a
-	// number of sources.
-
-	unsigned short i2eFifoSize;
-						// Always, the size of the FIFO. For
-						// IntelliPort-II, always the same, for -IIEX
-						// taken from the Power-On reset message.
-
-	volatile 
-	unsigned short i2eFifoRemains;
-						// Used during normal operation to indicate a
-						// lower bound on the amount of data which
-						// might be in the outbound fifo.
-
-	unsigned char  i2eFifoStyle;
-						// Accelerator which tells which style (-II or
-						// -IIEX) FIFO we are using.
-
-	unsigned char  i2eDataWidth16;
-						// Accelerator which tells whether we should
-						// do 8 or 16-bit data transfers.
-
-	unsigned char  i2eMaxIrq;
-						// The highest allowable IRQ, based on the
-						// slot size.
-
-	// Accelerators for various addresses on the board
-	int            i2eBase;        // I/O Address of the Board
-	int            i2eData;        // From here data transfers happen
-	int            i2eStatus;      // From here status reads happen
-	int            i2ePointer;     // (IntelliPort-II: pointer/commands)
-	int            i2eXMail;       // (IntelliPOrt-IIEX: mailboxes
-	int            i2eXMask;       // (IntelliPort-IIEX: mask write
-
-	//-------------------------------------------------------
-	// Information presented in a common format across boards
-	// For each box, bit map of the channels present.  Box closest to 
-	// the host is box 0. LSB is channel 0. IntelliPort-II (non-expandable)
-	// is taken to be box 0. These are derived from product i.d. registers.
-
-	unsigned short i2eChannelMap[ABS_MAX_BOXES];
-
-	// Same as above, except each is derived from firmware attempting to detect
-	// the uart presence (by reading a valid GFRCR register). If bits are set in
-	// i2eChannelMap and not in i2eGoodMap, there is a potential problem.
-
-	unsigned short i2eGoodMap[ABS_MAX_BOXES];
-
-	// ---------------------------
-	// For indirect function calls
-
-	// Routine to cause an N-millisecond delay: Patched by the ii2Initialize
-	// function.
-
-	void  (*i2eDelay)(unsigned int);
-
-	// Routine to write N bytes to the board through the FIFO. Returns true if
-	// all copacetic, otherwise returns false and error is in i2eError field.
-	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
-
-	int   (*i2eWriteBuf)(struct _i2eBordStr *, unsigned char *, int);
-
-	// Routine to read N bytes from the board through the FIFO. Returns true if
-	// copacetic, otherwise returns false and error in i2eError.
-	// IF COUNT IS ODD, ROUNDS UP TO THE NEXT EVEN NUMBER.
-
-	int   (*i2eReadBuf)(struct _i2eBordStr *, unsigned char *, int);
-
-	// Returns a word from FIFO. Will use 2 byte operations if needed.
-
-	unsigned short (*i2eReadWord)(struct _i2eBordStr *);
-
-	// Writes a word to FIFO. Will use 2 byte operations if needed.
-
-	void  (*i2eWriteWord)(struct _i2eBordStr *, unsigned short);
-
-	// Waits specified time for the Transmit FIFO to go empty. Returns true if
-	//  ok, otherwise returns false and error in i2eError.
-
-	int   (*i2eWaitForTxEmpty)(struct _i2eBordStr *, int);
-
-	// Returns true or false according to whether the outgoing mailbox is empty.
-
-	int   (*i2eTxMailEmpty)(struct _i2eBordStr *);
-
-	// Checks whether outgoing mailbox is empty.  If so, sends mail and returns
-	// true.  Otherwise returns false.
-
-	int   (*i2eTrySendMail)(struct _i2eBordStr *, unsigned char);
-
-	// If no mail available, returns NO_MAIL_HERE, else returns the value in the
-	// mailbox (guaranteed can't be NO_MAIL_HERE).
-
-	unsigned short (*i2eGetMail)(struct _i2eBordStr *);
-
-	// Enables the board to interrupt the host when it writes to the mailbox.
-	// Irqs will not occur, however, until the loadware separately enables
-	// interrupt generation to the host.  The standard loadware does this in
-	// response to a command packet sent by the host. (Also, disables
-	// any other potential interrupt sources from the board -- other than the
-	// inbound mailbox).
-
-	void  (*i2eEnableMailIrq)(struct _i2eBordStr *);
-
-	// Writes an arbitrary value to the mask register.
-
-	void  (*i2eWriteMask)(struct _i2eBordStr *, unsigned char);
-
-
-	// State information
-
-	// During downloading, indicates the number of blocks remaining to download
-	// to the board.
-
-	short i2eToLoad;
-
-	// State of board (see manifests below) (e.g., whether in reset condition,
-	// whether standard loadware is installed, etc.
-
-	unsigned char  i2eState;
-
-	// These three fields are only valid when there is loadware running on the
-	// board. (i2eState == II_STATE_LOADED or i2eState == II_STATE_STDLOADED )
-
-	unsigned char  i2eLVersion;  // Loadware version
-	unsigned char  i2eLRevision; // Loadware revision
-	unsigned char  i2eLSub;      // Loadware subrevision
-
-	// Flags which only have meaning in the context of the standard loadware.
-	// Somewhat violates the layering concept, but there is so little additional
-	// needed at the board level (while much additional at the channel level),
-	// that this beats maintaining two different per-board structures.
-
-	// Indicates which IRQ the board has been initialized (from software) to use
-	// For MicroChannel boards, any value different from IRQ_UNDEFINED means
-	// that the software command has been sent to enable interrupts (or specify
-	// they are disabled). Special value: IRQ_UNDEFINED indicates that the
-	// software command to select the interrupt has not yet been sent, therefore
-	// (since the standard loadware insists that it be sent before any other
-	// packets are sent) no other packets should be sent yet.
-
-	unsigned short i2eUsingIrq;
-
-	// This is set when we hit the MB_OUT_STUFFED mailbox, which prevents us
-	// putting more in the mailbox until an appropriate mailbox message is
-	// received.
-
-	unsigned char  i2eWaitingForEmptyFifo;
-
-	// Any mailbox bits waiting to be sent to the board are OR'ed in here.
-
-	unsigned char  i2eOutMailWaiting;
-
-	// The head of any incoming packet is read into here, is then examined and 
-	// we dispatch accordingly.
-
-	unsigned short i2eLeadoffWord[1];
-
-	// Running counter of interrupts where the mailbox indicated incoming data.
-
-	unsigned short i2eFifoInInts;
-
-	// Running counter of interrupts where the mailbox indicated outgoing data
-	// had been stripped.
-
-	unsigned short i2eFifoOutInts;
-
-	// If not void, gives the address of a routine to call if fatal board error
-	// is found (only applies to standard l/w).
-
-	void  (*i2eFatalTrap)(struct _i2eBordStr *);
-
-	// Will point to an array of some sort of channel structures (whose format
-	// is unknown at this level, being a function of what loadware is
-	// installed and the code configuration (max sizes of buffers, etc.)).
-
-	void  *i2eChannelPtr;
-
-	// Set indicates that the board has gone fatal.
-
-	unsigned short i2eFatal;
-
-	// The number of elements pointed to by i2eChannelPtr.
-
-	unsigned short i2eChannelCnt;
-
-	// Ring-buffers of channel structures whose channels have particular needs.
-
-	rwlock_t	Fbuf_spinlock;
-	volatile
-	unsigned short i2Fbuf_strip;	// Strip index
-	volatile 
-	unsigned short i2Fbuf_stuff;	// Stuff index
-	void  *i2Fbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// flow control packets.
-	rwlock_t	Dbuf_spinlock;
-	volatile
-	unsigned short i2Dbuf_strip;	// Strip index
-	volatile
-	unsigned short i2Dbuf_stuff;	// Stuff index
-	void  *i2Dbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// data or in-line command packets.
-	rwlock_t	Bbuf_spinlock;
-	volatile
-	unsigned short i2Bbuf_strip;	// Strip index
-	volatile
-	unsigned short i2Bbuf_stuff;	// Stuff index
-	void  *i2Bbuf[CH_QUEUE_SIZE];	// An array of channel pointers
-									// of channels who need to send
-									// bypass command packets.
-
-	/*
-	 * A set of flags to indicate that certain events have occurred on at least
-	 * one of the ports on this board. We use this to decide whether to spin
-	 * through the channels looking for breaks, etc.
-	 */
-	int		got_input;
-	int		status_change;
-	bidStat	channelBtypes;
-
-	/*
-	 * Debugging counters, etc.
-	 */
-	unsigned long debugFlowQueued;
-	unsigned long debugInlineQueued;
-	unsigned long debugDataQueued;
-	unsigned long debugBypassQueued;
-	unsigned long debugFlowCount;
-	unsigned long debugInlineCount;
-	unsigned long debugBypassCount;
-	
-	rwlock_t	read_fifo_spinlock;
-	rwlock_t	write_fifo_spinlock;
-
-//	For queuing interrupt bottom half handlers.	/\/\|=mhw=|\/\/
-	struct work_struct	tqueue_interrupt;
-
-	struct timer_list  SendPendingTimer;   // Used by iiSendPending
-	unsigned int	SendPendingRetry;
-} i2eBordStr, *i2eBordStrPtr;
-
-//-------------------------------------------------------------------
-// Macro Definitions for the indirect calls defined in the i2eBordStr
-//-------------------------------------------------------------------
-//
-#define iiDelay(a,b)          (*(a)->i2eDelay)(b)
-#define iiWriteBuf(a,b,c)     (*(a)->i2eWriteBuf)(a,b,c)
-#define iiReadBuf(a,b,c)      (*(a)->i2eReadBuf)(a,b,c)
-
-#define iiWriteWord(a,b)      (*(a)->i2eWriteWord)(a,b)
-#define iiReadWord(a)         (*(a)->i2eReadWord)(a)
-
-#define iiWaitForTxEmpty(a,b) (*(a)->i2eWaitForTxEmpty)(a,b)
-
-#define iiTxMailEmpty(a)      (*(a)->i2eTxMailEmpty)(a)
-#define iiTrySendMail(a,b)    (*(a)->i2eTrySendMail)(a,b)
-
-#define iiGetMail(a)          (*(a)->i2eGetMail)(a)
-#define iiEnableMailIrq(a)    (*(a)->i2eEnableMailIrq)(a)
-#define iiDisableMailIrq(a)   (*(a)->i2eWriteMask)(a,0)
-#define iiWriteMask(a,b)      (*(a)->i2eWriteMask)(a,b)
-
-//-------------------------------------------
-// Manifests for i2eBordStr:
-//-------------------------------------------
-
-typedef void (*delayFunc_t)(unsigned int);
-
-// i2eValid
-//
-#define I2E_MAGIC       0x4251   // Structure is valid.
-#define I2E_INCOMPLETE  0x1122   // Structure failed during init.
-
-
-// i2eError
-//
-#define I2EE_GOOD       0	// Operation successful
-#define I2EE_BADADDR    1	// Address out of range
-#define I2EE_BADSTATE   2	// Attempt to perform a function when the board
-							// structure was in the incorrect state
-#define I2EE_BADMAGIC   3	// Bad magic number from Power On test (i2ePomSize
-							// reflects what was read
-#define I2EE_PORM_SHORT 4	// Power On message too short
-#define I2EE_PORM_LONG  5	// Power On message too long
-#define I2EE_BAD_FAMILY 6	// Un-supported board family type
-#define I2EE_INCONSIST  7	// Firmware reports something impossible,
-							// e.g. unexpected number of ports... Almost no
-							// excuse other than bad FIFO...
-#define I2EE_POSTERR    8	// Power-On self test reported a bad error
-#define I2EE_BADBUS     9	// Unknown Bus type declared in message
-#define I2EE_TXE_TIME   10	// Timed out waiting for TX Fifo to empty
-#define I2EE_INVALID    11	// i2eValid field does not indicate a valid and
-							// complete board structure (for functions which
-							// require this be so.)
-#define I2EE_BAD_PORT   12	// Discrepancy between channels actually found and
-							// what the product is supposed to have. Check
-							// i2eGoodMap vs i2eChannelMap for details.
-#define I2EE_BAD_IRQ    13	// Someone specified an unsupported IRQ
-#define I2EE_NOCHANNELS 14	// No channel structures have been defined (for
-							// functions requiring this).
-
-// i2eFifoStyle
-//
-#define FIFO_II   0  /* IntelliPort-II style: see also i2hw.h */
-#define FIFO_IIEX 1  /* IntelliPort-IIEX style */
-
-// i2eGetMail
-//
-#define NO_MAIL_HERE    0x1111	// Since mail is unsigned char, cannot possibly
-								// promote to 0x1111.
-// i2eState
-//
-#define II_STATE_COLD      0  // Addresses have been defined, but board not even
-							  // reset yet.
-#define II_STATE_RESET     1  // Board,if it exists, has just been reset
-#define II_STATE_READY     2  // Board ready for its first block
-#define II_STATE_LOADING   3  // Board continuing load
-#define II_STATE_LOADED    4  // Board has finished load: status ok
-#define II_STATE_BADLOAD   5  // Board has finished load: failed!
-#define II_STATE_STDLOADED 6  // Board has finished load: standard firmware
-
-// i2eUsingIrq
-//
-#define I2_IRQ_UNDEFINED	0x1352  /* No valid irq (or polling = 0) can
-					 * ever promote to this! */
-//------------------------------------------
-// Handy Macros for i2ellis.c and others
-// Note these are common to -II and -IIEX
-//------------------------------------------
-
-// Given a pointer to the board structure, does the input FIFO have any data or
-// not?
-//
-#define I2_HAS_INPUT(pB)	!(inb(pB->i2eStatus) & ST_IN_EMPTY)
-
-// Given a pointer to the board structure, is there anything in the incoming
-// mailbox?
-//
-#define I2_HAS_MAIL(pB)		(inb(pB->i2eStatus) & ST_IN_MAIL)
-
-#define I2_UPDATE_FIFO_ROOM(pB)	((pB)->i2eFifoRemains = (pB)->i2eFifoSize)
-
-//------------------------------------------
-// Function Declarations for i2ellis.c
-//------------------------------------------
-//
-// Functions called directly
-//
-// Initialization of a board & structure is in four (five!) parts:
-//
-// 1) iiSetAddress() - Define the board address & delay function for a board.
-// 2) iiReset()      - Reset the board   (provided it exists)
-//       -- Note you may do this to several boards --
-// 3) iiResetDelay() - Delay for 2 seconds (once for all boards)
-// 4) iiInitialize() - Attempt to read Power-up message; further initialize
-//                     accelerators
-//
-// Then you may use iiDownloadAll() or iiDownloadFile() (in i2file.c) to write
-// loadware.  To change loadware, you must begin again with step 2, resetting
-// the board again (step 1 not needed).
-
-static int iiSetAddress(i2eBordStrPtr, int, delayFunc_t );
-static int iiReset(i2eBordStrPtr);
-static int iiResetDelay(i2eBordStrPtr);
-static int iiInitialize(i2eBordStrPtr);
-
-// Routine to validate that all channels expected are there.
-//
-extern int iiValidateChannels(i2eBordStrPtr);
-
-// Routine used to download a block of loadware.
-//
-static int iiDownloadBlock(i2eBordStrPtr, loadHdrStrPtr, int);
-
-// Return values given by iiDownloadBlock, iiDownloadAll, iiDownloadFile:
-//
-#define II_DOWN_BADVALID   0	// board structure is invalid
-#define II_DOWN_CONTINUING 1	// So far, so good, firmware expects more
-#define II_DOWN_GOOD       2	// Download complete, CRC good
-#define II_DOWN_BAD        3	// Download complete, but CRC bad
-#define II_DOWN_BADFILE    4	// Bad magic number in loadware file
-#define II_DOWN_BADSTATE   5	// Board is in an inappropriate state for
-								// downloading loadware. (see i2eState)
-#define II_DOWN_TIMEOUT    6	// Timeout waiting for firmware
-#define II_DOWN_OVER       7	// Too much data
-#define II_DOWN_UNDER      8	// Not enough data
-#define II_DOWN_NOFILE     9	// Loadware file not found
-
-// Routine to download an entire loadware module: Return values are a subset of
-// iiDownloadBlock's, excluding, of course, II_DOWN_CONTINUING
-//
-static int iiDownloadAll(i2eBordStrPtr, loadHdrStrPtr, int, int);
-
-// Many functions defined here return True if good, False otherwise, with an
-// error code in i2eError field. Here is a handy macro for setting the error
-// code and returning.
-//
-#define I2_COMPLETE(pB,code) do { \
-		 pB->i2eError = code; \
-		 return (code == I2EE_GOOD);\
-	} while (0)
-
-#endif   // I2ELLIS_H
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2hw.h linux-libre-2.6.39-gnu/drivers/char/ip2/i2hw.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,652 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions limited to properties of the hardware or the
-*                bootstrap firmware. As such, they are applicable regardless of
-*                operating system or loadware (standard or diagnostic).
-*
-*******************************************************************************/
-#ifndef I2HW_H
-#define I2HW_H 1
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 23 September 1991 MAG   First Draft Started...through...
-// 11 October 1991   ...   Continuing development...
-//  6 August 1993          Added support for ISA-4 (asic) which is architected
-//                         as an ISA-CEX with a single 4-port box.
-//
-// 20 December 1996  AKM   Version for Linux
-//
-//------------------------------------------------------------------------------
-/*------------------------------------------------------------------------------
-
-HARDWARE DESCRIPTION:
-
-Introduction:
-
-The IntelliPort-II and IntelliPort-IIEX products occupy a block of eight (8)
-addresses in the host's I/O space.
-
-Some addresses are used to transfer data to/from the board, some to transfer
-so-called "mailbox" messages, and some to read bit-mapped status information.
-While all the products in the line are functionally similar, some use a 16-bit
-data path to transfer data while others use an 8-bit path. Also, the use of
-command /status/mailbox registers differs slightly between the II and IIEX
-branches of the family.
-
-The host determines what type of board it is dealing with by reading a string of
-sixteen characters from the board. These characters are always placed in the
-fifo by the board's local processor whenever the board is reset (either from
-power-on or under software control) and are known as the "Power-on Reset
-Message." In order that this message can be read from either type of board, the
-hardware registers used in reading this message are the same. Once this message
-has been read by the host, then it has the information required to operate.
-
-General Differences between boards:
-
-The greatest structural difference is between the -II and -IIEX families of
-product. The -II boards use the Am4701 dual 512x8 bidirectional fifo to support
-the data path, mailbox registers, and status registers. This chip contains some
-features which are not used in the IntelliPort-II products; a description of
-these is omitted here. Because of these many features, it contains many
-registers, too many to access directly within a small address space. They are
-accessed by first writing a value to a "pointer" register. This value selects
-the register to be accessed.  The next read or write to that address accesses
-the selected register rather than the pointer register.
-
-The -IIEX boards use a proprietary design similar to the Am4701 in function. But
-because of a simpler, more streamlined design it doesn't require so many
-registers. This means they can be accessed directly in single operations rather
-than through a pointer register.
-
-Besides these differences, there are differences in whether 8-bit or 16-bit
-transfers are used to move data to the board.
-
-The -II boards are capable only of 8-bit data transfers, while the -IIEX boards
-may be configured for either 8-bit or 16-bit data transfers. If the on-board DIP
-switch #8 is ON, and the card has been installed in a 16-bit slot, 16-bit
-transfers are supported (and will be expected by the standard loadware). The
-on-board firmware can determine the position of the switch, and whether the
-board is installed in a 16-bit slot; it supplies this information to the host as
-part of the power-up reset message.
-
-The configuration switch (#8) and slot selection do not directly configure the
-hardware. It is up to the on-board loadware and host-based drivers to act
-according to the selected options. That is, loadware and drivers could be
-written to perform 8-bit transfers regardless of the state of the DIP switch or
-slot (and in a diagnostic environment might well do so). Likewise, 16-bit
-transfers could be performed as long as the card is in a 16-bit slot.
-
-Note the slot selection and DIP switch selection are provided separately: a
-board running in 8-bit mode in a 16-bit slot has a greater range of possible
-interrupts to choose from; information of potential use to the host.
-
-All 8-bit data transfers are done in the same way, regardless of whether on a
--II board or a -IIEX board.
-
-The host must consider two things then: 1) whether a -II or -IIEX product is
-being used, and 2) whether an 8-bit or 16-bit data path is used.
-
-A further difference is that -II boards always have a 512-byte fifo operating in
-each direction. -IIEX boards may use fifos of varying size; this size is
-reported as part of the power-up message.
-
-I/O Map Of IntelliPort-II and IntelliPort-IIEX boards:
-(Relative to the chosen base address)
-
-Addr  R/W      IntelliPort-II    IntelliPort-IIEX
-----  ---      --------------    ----------------
-0     R/W      Data Port (byte)  Data Port (byte or word)
-1     R/W      (Not used)        (MSB of word-wide data written to Data Port)
-2     R        Status Register   Status Register
-2     W        Pointer Register  Interrupt Mask Register
-3     R/W      (Not used)        Mailbox Registers (6 bits: 11111100)
-4,5   --       Reserved for future products
-6     --       Reserved for future products
-7     R        Guaranteed to have no effect
-7     W        Hardware reset of board.
-
-
-Rules:
-All data transfers are performed using the even i/o address. If byte-wide data
-transfers are being used, do INB/OUTB operations on the data port. If word-wide
-transfers are used, do INW/OUTW operations. In some circumstances (such as
-reading the power-up message) you will do INB from the data port, but in this
-case the MSB of each word read is lost. When accessing all other unreserved
-registers, use byte operations only.
-------------------------------------------------------------------------------*/
-
-//------------------------------------------------
-// Mandatory Includes:
-//------------------------------------------------
-//
-#include "ip2types.h"
-
-//-------------------------------------------------------------------------
-// Manifests for the I/O map:
-//-------------------------------------------------------------------------
-// R/W: Data port (byte) for IntelliPort-II,
-// R/W: Data port (byte or word) for IntelliPort-IIEX
-// Incoming or outgoing data passes through a FIFO, the status of which is
-// available in some of the bits in FIFO_STATUS. This (bidirectional) FIFO is
-// the primary means of transferring data, commands, flow-control, and status
-// information between the host and board.
-//
-#define FIFO_DATA 0
-
-// Another way of passing information between the board and the host is
-// through "mailboxes". Unlike a FIFO, a mailbox holds only a single byte of
-// data.  Writing data to the mailbox causes a status bit to be set, and
-// potentially interrupting the intended receiver. The sender has some way to
-// determine whether the data has been read yet; as soon as it has, it may send
-// more. The mailboxes are handled differently on -II and -IIEX products, as
-// suggested below.
-//------------------------------------------------------------------------------
-// Read: Status Register for IntelliPort-II or -IIEX
-// The presence of any bit set here will cause an interrupt to the host,
-// provided the corresponding bit has been unmasked in the interrupt mask
-// register. Furthermore, interrupts to the host are disabled globally until the
-// loadware selects the irq line to use. With the exception of STN_MR, the bits
-// remain set so long as the associated condition is true.
-//
-#define FIFO_STATUS 2
-
-// Bit map of status bits which are identical for -II and -IIEX
-//
-#define ST_OUT_FULL  0x40  // Outbound FIFO full
-#define ST_IN_EMPTY  0x20  // Inbound FIFO empty
-#define ST_IN_MAIL   0x04  // Inbound Mailbox full
-
-// The following exists only on the Intelliport-IIEX, and indicates that the
-// board has not read the last outgoing mailbox data yet. In the IntelliPort-II,
-// the outgoing mailbox may be read back: a zero indicates the board has read
-// the data.
-//
-#define STE_OUT_MAIL 0x80  // Outbound mailbox full (!)
-
-// The following bits are defined differently for -II and -IIEX boards. Code
-// which relies on these bits will need to be functionally different for the two
-// types of boards and should be generally avoided because of the additional
-// complexity this creates:
-
-// Bit map of status bits only on -II
-
-// Fifo has been RESET (cleared when the status register is read). Note that
-// this condition cannot be masked and would always interrupt the host, except
-// that the hardware reset also disables interrupts globally from the board
-// until re-enabled by loadware. This could also arise from the
-// Am4701-supported command to reset the chip, but this command is generally not
-// used here.
-//
-#define STN_MR       0x80
-
-// See the AMD Am4701 data sheet for details on the following four bits. They
-// are not presently used by Computone drivers.
-//
-#define STN_OUT_AF  0x10  // Outbound FIFO almost full (programmable)
-#define STN_IN_AE   0x08  // Inbound FIFO almost empty (programmable)
-#define STN_BD      0x02  // Inbound byte detected
-#define STN_PE      0x01  // Parity/Framing condition detected
-
-// Bit-map of status bits only on -IIEX
-//
-#define STE_OUT_HF  0x10  // Outbound FIFO half full
-#define STE_IN_HF   0x08  // Inbound FIFO half full
-#define STE_IN_FULL 0x02  // Inbound FIFO full
-#define STE_OUT_MT  0x01  // Outbound FIFO empty
-
-//------------------------------------------------------------------------------
-
-// Intelliport-II -- Write Only: the pointer register.
-// Values are written to this register to select the Am4701 internal register to
-// be accessed on the next operation.
-//
-#define FIFO_PTR    0x02
-
-// Values for the pointer register
-//
-#define SEL_COMMAND 0x1    // Selects the Am4701 command register
-
-// Some possible commands:
-//
-#define SEL_CMD_MR  0x80	// Am4701 command to reset the chip
-#define SEL_CMD_SH  0x40	// Am4701 command to map the "other" port into the
-							// status register.
-#define SEL_CMD_UNSH   0	// Am4701 command to "unshift": port maps into its
-							// own status register.
-#define SEL_MASK     0x2	// Selects the Am4701 interrupt mask register. The
-							// interrupt mask register is bit-mapped to match 
-							// the status register (FIFO_STATUS) except for
-							// STN_MR. (See above.)
-#define SEL_BYTE_DET 0x3	// Selects the Am4701 byte-detect register. (Not
-							// normally used except in diagnostics.)
-#define SEL_OUTMAIL  0x4	// Selects the outbound mailbox (R/W). Reading back
-							// a value of zero indicates that the mailbox has
-							// been read by the board and is available for more
-							// data./ Writing to the mailbox optionally
-							// interrupts the board, depending on the loadware's
-							// setting of its interrupt mask register.
-#define SEL_AEAF     0x5	// Selects AE/AF threshold register.
-#define SEL_INMAIL   0x6	// Selects the inbound mailbox (Read)
-
-//------------------------------------------------------------------------------
-// IntelliPort-IIEX --  Write Only: interrupt mask (and misc flags) register:
-// Unlike IntelliPort-II, bit assignments do NOT match those of the status
-// register.
-//
-#define FIFO_MASK    0x2
-
-// Mailbox readback select:
-// If set, reads to FIFO_MAIL will read the OUTBOUND mailbox (host to board). If
-// clear (default on reset) reads to FIFO_MAIL will read the INBOUND mailbox.
-// This is the normal situation. The clearing of a mailbox is determined on
-// -IIEX boards by waiting for the STE_OUT_MAIL bit to clear. Readback
-// capability is provided for diagnostic purposes only.
-//
-#define  MX_OUTMAIL_RSEL   0x80
-
-#define  MX_IN_MAIL  0x40	// Enables interrupts when incoming mailbox goes
-							// full (ST_IN_MAIL set).
-#define  MX_IN_FULL  0x20	// Enables interrupts when incoming FIFO goes full
-							// (STE_IN_FULL).
-#define  MX_IN_MT    0x08	// Enables interrupts when incoming FIFO goes empty
-							// (ST_IN_MT).
-#define  MX_OUT_FULL 0x04	// Enables interrupts when outgoing FIFO goes full
-							// (ST_OUT_FULL).
-#define  MX_OUT_MT   0x01	// Enables interrupts when outgoing FIFO goes empty
-							// (STE_OUT_MT).
-
-// Any remaining bits are reserved, and should be written to ZERO for
-// compatibility with future Computone products.
-
-//------------------------------------------------------------------------------
-// IntelliPort-IIEX: -- These are only 6-bit mailboxes !!! -- 11111100 (low two
-// bits always read back 0).
-// Read:  One of the mailboxes, usually Inbound.
-//        Inbound Mailbox (MX_OUTMAIL_RSEL = 0)
-//        Outbound Mailbox (MX_OUTMAIL_RSEL = 1)
-// Write: Outbound Mailbox
-// For the IntelliPort-II boards, the outbound mailbox is read back to determine
-// whether the board has read the data (0 --> data has been read). For the
-// IntelliPort-IIEX, this is done by reading a status register. To determine
-// whether mailbox is available for more outbound data, use the STE_OUT_MAIL bit
-// in FIFO_STATUS. Moreover, although the Outbound Mailbox can be read back by
-// setting MX_OUTMAIL_RSEL, it is NOT cleared when the board reads it, as is the
-// case with the -II boards. For this reason, FIFO_MAIL is normally used to read
-// the inbound FIFO, and MX_OUTMAIL_RSEL kept clear. (See above for
-// MX_OUTMAIL_RSEL description.)
-//
-#define  FIFO_MAIL   0x3
-
-//------------------------------------------------------------------------------
-// WRITE ONLY:  Resets the board. (Data doesn't matter).
-//
-#define  FIFO_RESET  0x7
-
-//------------------------------------------------------------------------------
-// READ ONLY:  Will have no effect. (Data is undefined.)
-// Actually, there will be an effect, in that the operation is sure to generate
-// a bus cycle: viz., an I/O byte Read. This fact can be used to enforce short
-// delays when no comparable time constant is available.
-//
-#define  FIFO_NOP    0x7
-
-//------------------------------------------------------------------------------
-// RESET & POWER-ON RESET MESSAGE
-/*------------------------------------------------------------------------------
-RESET:
-
-The IntelliPort-II and -IIEX boards are reset in three ways: Power-up, channel
-reset, and via a write to the reset register described above. For products using
-the ISA bus, these three sources of reset are equvalent. For MCA and EISA buses,
-the Power-up and channel reset sources cause additional hardware initialization
-which should only occur at system startup time.
-
-The third type of reset, called a "command reset", is done by writing any data
-to the FIFO_RESET address described above. This resets the on-board processor,
-FIFO, UARTS, and associated hardware.
-
-This passes control of the board to the bootstrap firmware, which performs a
-Power-On Self Test and which detects its current configuration. For example,
--IIEX products determine the size of FIFO which has been installed, and the
-number and type of expansion boxes attached.
-
-This and other information is then written to the FIFO in a 16-byte data block
-to be read by the host. This block is guaranteed to be present within two (2)
-seconds of having received the command reset. The firmware is now ready to
-receive loadware from the host.
-
-It is good practice to perform a command reset to the board explicitly as part
-of your software initialization.  This allows your code to properly restart from
-a soft boot. (Many systems do not issue channel reset on soft boot).
-
-Because of a hardware reset problem on some of the Cirrus Logic 1400's which are
-used on the product, it is recommended that you reset the board twice, separated
-by an approximately 50 milliseconds delay. (VERY approximately: probably ok to
-be off by a factor of five. The important point is that the first command reset
-in fact generates a reset pulse on the board. This pulse is guaranteed to last
-less than 10 milliseconds. The additional delay ensures the 1400 has had the
-chance to respond sufficiently to the first reset. Why not a longer delay? Much
-more than 50 milliseconds gets to be noticable, but the board would still work.
-
-Once all 16 bytes of the Power-on Reset Message have been read, the bootstrap
-firmware is ready to receive loadware.
-
-Note on Power-on Reset Message format:
-The various fields have been designed with future expansion in view.
-Combinations of bitfields and values have been defined which define products
-which may not currently exist. This has been done to allow drivers to anticipate
-the possible introduction of products in a systematic fashion. This is not
-intended to suggest that each potential product is actually under consideration.
-------------------------------------------------------------------------------*/
-
-//----------------------------------------
-// Format of Power-on Reset Message
-//----------------------------------------
-
-typedef union _porStr		// "por" stands for Power On Reset
-{
-	unsigned char  c[16];	// array used when considering the message as a
-							// string of undifferentiated characters
-
-	struct					// Elements used when considering values
-	{
-		// The first two bytes out of the FIFO are two magic numbers. These are
-		// intended to establish that there is indeed a member of the
-		// IntelliPort-II(EX) family present. The remaining bytes may be 
-		// expected // to be valid. When reading the Power-on Reset message, 
-		// if the magic numbers do not match it is probably best to stop
-		// reading immediately. You are certainly not reading our board (unless
-		// hardware is faulty), and may in fact be reading some other piece of
-		// hardware.
-
-		unsigned char porMagic1;   // magic number: first byte == POR_MAGIC_1 
-		unsigned char porMagic2;   // magic number: second byte == POR_MAGIC_2 
-
-		// The Version, Revision, and Subrevision are stored as absolute numbers
-		// and would normally be displayed in the format V.R.S (e.g. 1.0.2)
-
-		unsigned char porVersion;  // Bootstrap firmware version number
-		unsigned char porRevision; // Bootstrap firmware revision number
-		unsigned char porSubRev;   // Bootstrap firmware sub-revision number
-
-		unsigned char porID;	// Product ID:  Bit-mapped according to
-								// conventions described below. Among other
-								// things, this allows us to distinguish
-								// IntelliPort-II boards from IntelliPort-IIEX
-								// boards.
-
-		unsigned char porBus;	// IntelliPort-II: Unused
-								// IntelliPort-IIEX: Bus Information:
-								// Bit-mapped below
-
-		unsigned char porMemory;	// On-board DRAM size: in 32k blocks
-
-		// porPorts1 (and porPorts2) are used to determine the ports which are
-		// available to the board. For non-expandable product, a single number 
-		// is sufficient. For expandable product, the board may be connected
-		// to as many as four boxes. Each box may be (so far) either a 16-port
-		// or an 8-port size. Whenever an 8-port box is used, the remaining 8
-		// ports leave gaps between existing channels. For that reason,
-		// expandable products must report a MAP of available channels. Since 
-		// each UART supports four ports, we represent each UART found by a
-		// single bit. Using two bytes to supply the mapping information we
-		// report the presense or absense of up to 16 UARTS, or 64 ports in
-		// steps of 4 ports. For -IIEX products, the ports are numbered
-		// starting at the box closest to the controller in the "chain".
-
-		// Interpreted Differently for IntelliPort-II and -IIEX.
-		// -II:   Number of ports (Derived actually from product ID). See
-		// Diag1&2 to indicate if uart was actually detected.
-		// -IIEX: Bit-map of UARTS found, LSB (see below for MSB of this). This
-		//        bitmap is based on detecting the uarts themselves; 
-		//        see porFlags for information from the box i.d's.
-		unsigned char  porPorts1;
-
-		unsigned char  porDiag1;	// Results of on-board P.O.S.T, 1st byte
-		unsigned char  porDiag2;	// Results of on-board P.O.S.T, 2nd byte
-		unsigned char  porSpeed;	// Speed of local CPU: given as MHz x10
-									// e.g., 16.0 MHz CPU is reported as 160
-		unsigned char  porFlags;	// Misc information (see manifests below)
-									// Bit-mapped: CPU type, UART's present
-
-		unsigned char  porPorts2;	// -II:  Undefined
-									// -IIEX: Bit-map of UARTS found, MSB (see
-									//        above for LSB)
-
-		// IntelliPort-II: undefined
-		// IntelliPort-IIEX: 1 << porFifoSize gives the size, in bytes, of the
-		// host interface FIFO, in each direction. When running the -IIEX in
-		// 8-bit mode, fifo capacity is halved. The bootstrap firmware will
-		// have already accounted for this fact in generating this number.
-		unsigned char  porFifoSize;
-
-		// IntelliPort-II: undefined
-		// IntelliPort-IIEX: The number of boxes connected. (Presently 1-4)
-		unsigned char  porNumBoxes;
-	} e;
-} porStr, *porStrPtr;
-
-//--------------------------
-// Values for porStr fields
-//--------------------------
-
-//---------------------
-// porMagic1, porMagic2
-//----------------------
-//
-#define  POR_MAGIC_1    0x96  // The only valid value for porMagic1
-#define  POR_MAGIC_2    0x35  // The only valid value for porMagic2
-#define  POR_1_INDEX    0     // Byte position of POR_MAGIC_1
-#define  POR_2_INDEX    1     // Ditto for POR_MAGIC_2
-
-//----------------------
-// porID
-//----------------------
-//
-#define  POR_ID_FAMILY  0xc0	// These bits indicate the general family of
-								// product.
-#define  POR_ID_FII     0x00	// Family is "IntelliPort-II"
-#define  POR_ID_FIIEX   0x40	// Family is "IntelliPort-IIEX"
-
-// These bits are reserved, presently zero. May be used at a later date to
-// convey other product information.
-//
-#define POR_ID_RESERVED 0x3c
-
-#define POR_ID_SIZE     0x03	// Remaining bits indicate number of ports &
-								// Connector information.
-#define POR_ID_II_8     0x00	// For IntelliPort-II, indicates 8-port using
-								// standard brick.
-#define POR_ID_II_8R    0x01	// For IntelliPort-II, indicates 8-port using
-								// RJ11's (no CTS)
-#define POR_ID_II_6     0x02	// For IntelliPort-II, indicates 6-port using
-								// RJ45's
-#define POR_ID_II_4     0x03	// For IntelliPort-II, indicates 4-port using
-								// 4xRJ45 connectors
-#define POR_ID_EX       0x00	// For IntelliPort-IIEX, indicates standard
-								// expandable controller (other values reserved)
-
-//----------------------
-// porBus
-//----------------------
-
-// IntelliPort-IIEX only: Board is installed in a 16-bit slot
-//
-#define POR_BUS_SLOT16  0x20
-
-// IntelliPort-IIEX only: DIP switch #8 is on, selecting 16-bit host interface
-// operation.
-// 
-#define POR_BUS_DIP16   0x10
-
-// Bits 0-2 indicate type of bus: This information is stored in the bootstrap
-// loadware, different loadware being used on different products for different
-// buses. For most situations, the drivers do not need this information; but it
-// is handy in a diagnostic environment. For example, on microchannel boards,
-// you would not want to try to test several interrupts, only the one for which
-// you were configured.
-//
-#define  POR_BUS_TYPE   0x07
-
-// Unknown:  this product doesn't know what bus it is running in. (e.g. if same
-// bootstrap firmware were wanted for two different buses.)
-//
-#define  POR_BUS_T_UNK  0
-
-// Note: existing firmware for ISA-8 and MC-8 currently report the POR_BUS_T_UNK
-// state, since the same bootstrap firmware is used for each.
-
-#define  POR_BUS_T_MCA  1  // MCA BUS */
-#define  POR_BUS_T_EISA 2  // EISA BUS */
-#define  POR_BUS_T_ISA  3  // ISA BUS */
-
-// Values 4-7 Reserved
-
-// Remaining bits are reserved
-
-//----------------------
-// porDiag1
-//----------------------
-
-#define  POR_BAD_MAPPER 0x80	// HW failure on P.O.S.T: Chip mapper failed
-
-// These two bits valid only for the IntelliPort-II
-//
-#define  POR_BAD_UART1  0x01	// First  1400 bad
-#define  POR_BAD_UART2  0x02	// Second 1400 bad
-
-//----------------------
-// porDiag2
-//----------------------
-
-#define  POR_DEBUG_PORT 0x80	// debug port was detected by the P.O.S.T
-#define  POR_DIAG_OK    0x00	// Indicates passage: Failure codes not yet
-								// available.
-								// Other bits undefined.
-//----------------------
-// porFlags
-//----------------------
-
-#define  POR_CPU     0x03	// These bits indicate supposed CPU type
-#define  POR_CPU_8   0x01	// Board uses an 80188 (no such thing yet)
-#define  POR_CPU_6   0x02	// Board uses an 80186 (all existing products)
-#define  POR_CEX4    0x04	// If set, this is an ISA-CEX/4: An ISA-4 (asic)
-							// which is architected like an ISA-CEX connected
-							// to a (hitherto impossible) 4-port box.
-#define POR_BOXES    0xf0	// Valid for IntelliPort-IIEX only: Map of Box
-							// sizes based on box I.D.
-#define POR_BOX_16   0x10	// Set indicates 16-port, clear 8-port
-
-//-------------------------------------
-// LOADWARE and DOWNLOADING CODE
-//-------------------------------------
-
-/*
-Loadware may be sent to the board in two ways:
-1) It may be read from a (binary image) data file block by block as each block
-	is sent to the board. This is only possible when the initialization is
-	performed by code which can access your file system. This is most suitable
-	for diagnostics and appications which use the interface library directly.
-
-2) It may be hard-coded into your source by including a .h file (typically
-	supplied by Computone), which declares a data array and initializes every
-	element. This achieves the same result as if an entire loadware file had 
-	been read into the array.
-
-	This requires more data space in your program, but access to the file system
-	is not required. This method is more suited to driver code, which typically
-	is running at a level too low to access the file system directly.
-
-At present, loadware can only be generated at Computone.
-
-All Loadware begins with a header area which has a particular format. This
-includes a magic number which identifies the file as being (purportedly)
-loadware, CRC (for the loader), and version information.
-*/
-
-
-//-----------------------------------------------------------------------------
-// Format of loadware block
-//
-// This is defined as a union so we can pass a pointer to one of these items
-// and (if it is the first block) pick out the version information, etc.
-//
-// Otherwise, to deal with this as a simple character array
-//------------------------------------------------------------------------------
-
-#define LOADWARE_BLOCK_SIZE   512   // Number of bytes in each block of loadware
-
-typedef union _loadHdrStr
-{
-	unsigned char c[LOADWARE_BLOCK_SIZE];  // Valid for every block
-
-	struct	// These fields are valid for only the first block of loadware.
-	{
-		unsigned char loadMagic;		// Magic number: see below
-		unsigned char loadBlocksMore;	// How many more blocks?
-		unsigned char loadCRC[2];		// Two CRC bytes: used by loader
-		unsigned char loadVersion;		// Version number
-		unsigned char loadRevision;		// Revision number
-		unsigned char loadSubRevision;	// Sub-revision number
-		unsigned char loadSpares[9];	// Presently unused
-		unsigned char loadDates[32];	// Null-terminated string which can give
-										// date and time of compilation
-	} e;
-} loadHdrStr, *loadHdrStrPtr;
-
-//------------------------------------
-// Defines for downloading code:
-//------------------------------------
-
-// The loadMagic field in the first block of the loadfile must be this, else the
-// file is not valid.
-//
-#define  MAGIC_LOADFILE 0x3c
-
-// How do we know the load was successful? On completion of the load, the
-// bootstrap firmware returns a code to indicate whether it thought the download
-// was valid and intends to execute it. These are the only possible valid codes:
-//
-#define  LOADWARE_OK    0xc3        // Download was ok
-#define  LOADWARE_BAD   0x5a        // Download was bad (CRC error)
-
-// Constants applicable to writing blocks of loadware:
-// The first block of loadware might take 600 mS to load, in extreme cases.
-// (Expandable board: worst case for sending startup messages to the LCD's).
-// The 600mS figure is not really a calculation, but a conservative
-// guess/guarantee. Usually this will be within 100 mS, like subsequent blocks.
-//
-#define  MAX_DLOAD_START_TIME 1000  // 1000 mS
-#define  MAX_DLOAD_READ_TIME  100   // 100 mS
-
-// Firmware should respond with status (see above) within this long of host
-// having sent the final block.
-//
-#define  MAX_DLOAD_ACK_TIME   100   // 100 mS, again!
-
-//------------------------------------------------------
-// MAXIMUM NUMBER OF PORTS PER BOARD:
-// This is fixed for now (with the expandable), but may
-// be expanding according to even newer products.
-//------------------------------------------------------
-//
-#define ABS_MAX_BOXES   4     // Absolute most boxes per board
-#define ABS_BIGGEST_BOX 16    // Absolute the most ports per box
-#define ABS_MOST_PORTS  (ABS_MAX_BOXES * ABS_BIGGEST_BOX)
-
-#define I2_OUTSW(port, addr, count)	outsw((port), (addr), (((count)+1)/2))
-#define I2_OUTSB(port, addr, count)	outsb((port), (addr), (((count)+1))&-2)
-#define I2_INSW(port, addr, count)	insw((port), (addr), (((count)+1)/2))
-#define I2_INSB(port, addr, count)	insb((port), (addr), (((count)+1))&-2)
-
-#endif   // I2HW_H
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2lib.c linux-libre-2.6.39-gnu/drivers/char/ip2/i2lib.c
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2lib.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2214 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: High-level interface code for the device driver. Uses the
-*                Extremely Low Level Interface Support (i2ellis.c). Provides an
-*                interface to the standard loadware, to support drivers or
-*                application code. (This is included source code, not a separate
-*                compilation module.)
-*
-*******************************************************************************/
-//------------------------------------------------------------------------------
-// Note on Strategy:
-// Once the board has been initialized, it will interrupt us when:
-// 1) It has something in the fifo for us to read (incoming data, flow control
-// packets, or whatever).
-// 2) It has stripped whatever we have sent last time in the FIFO (and
-// consequently is ready for more).
-//
-// Note also that the buffer sizes declared in i2lib.h are VERY SMALL. This
-// worsens performance considerably, but is done so that a great many channels
-// might use only a little memory.
-//------------------------------------------------------------------------------
-
-//------------------------------------------------------------------------------
-// Revision History:
-//
-// 0.00 -  4/16/91 --- First Draft
-// 0.01 -  4/29/91 --- 1st beta release
-// 0.02 -  6/14/91 --- Changes to allow small model compilation
-// 0.03 -  6/17/91 MAG Break reporting protected from interrupts routines with
-//                     in-line asm added for moving data to/from ring buffers,
-//                     replacing a variety of methods used previously.
-// 0.04 -  6/21/91 MAG Initial flow-control packets not queued until
-//                     i2_enable_interrupts time. Former versions would enqueue
-//                     them at i2_init_channel time, before we knew how many
-//                     channels were supposed to exist!
-// 0.05 - 10/12/91 MAG Major changes: works through the ellis.c routines now;
-//                     supports new 16-bit protocol and expandable boards.
-//      - 10/24/91 MAG Most changes in place and stable.
-// 0.06 -  2/20/92 MAG Format of CMD_HOTACK corrected: the command takes no
-//                     argument.
-// 0.07 -- 3/11/92 MAG Support added to store special packet types at interrupt
-//                     level (mostly responses to specific commands.)
-// 0.08 -- 3/30/92 MAG Support added for STAT_MODEM packet
-// 0.09 -- 6/24/93 MAG i2Link... needed to update number of boards BEFORE
-//                     turning on the interrupt.
-// 0.10 -- 6/25/93 MAG To avoid gruesome death from a bad board, we sanity check
-//                     some incoming.
-//
-// 1.1  - 12/25/96 AKM Linux version.
-//      - 10/09/98 DMC Revised Linux version.
-//------------------------------------------------------------------------------
-
-//************
-//* Includes *
-//************
-
-#include <linux/sched.h>
-#include "i2lib.h"
-
-
-//***********************
-//* Function Prototypes *
-//***********************
-static void i2QueueNeeds(i2eBordStrPtr, i2ChanStrPtr, int);
-static i2ChanStrPtr i2DeQueueNeeds(i2eBordStrPtr, int );
-static void i2StripFifo(i2eBordStrPtr);
-static void i2StuffFifoBypass(i2eBordStrPtr);
-static void i2StuffFifoFlow(i2eBordStrPtr);
-static void i2StuffFifoInline(i2eBordStrPtr);
-static int i2RetryFlushOutput(i2ChanStrPtr);
-
-// Not a documented part of the library routines (careful...) but the Diagnostic
-// i2diag.c finds them useful to help the throughput in certain limited
-// single-threaded operations.
-static void iiSendPendingMail(i2eBordStrPtr);
-static void serviceOutgoingFifo(i2eBordStrPtr);
-
-// Functions defined in ip2.c as part of interrupt handling
-static void do_input(struct work_struct *);
-static void do_status(struct work_struct *);
-
-//***************
-//* Debug  Data *
-//***************
-#ifdef DEBUG_FIFO
-
-unsigned char DBGBuf[0x4000];
-unsigned short I = 0;
-
-static void
-WriteDBGBuf(char *s, unsigned char *src, unsigned short n ) 
-{
-	char *p = src;
-
-	// XXX: We need a spin lock here if we ever use this again
-
-	while (*s) {	// copy label
-		DBGBuf[I] = *s++;
-		I = I++ & 0x3fff;
-	}
-	while (n--) {	// copy data
-		DBGBuf[I] = *p++;
-		I = I++ & 0x3fff;
-	}
-}
-
-static void
-fatality(i2eBordStrPtr pB )
-{
-	int i;
-
-	for (i=0;i<sizeof(DBGBuf);i++) {
-		if ((i%16) == 0)
-			printk("\n%4x:",i);
-		printk("%02x ",DBGBuf[i]);
-	}
-	printk("\n");
-	for (i=0;i<sizeof(DBGBuf);i++) {
-		if ((i%16) == 0)
-			printk("\n%4x:",i);
-		if (DBGBuf[i] >= ' ' && DBGBuf[i] <= '~') {
-			printk(" %c ",DBGBuf[i]);
-		} else {
-			printk(" . ");
-		}
-	}
-	printk("\n");
-	printk("Last index %x\n",I);
-}
-#endif /* DEBUG_FIFO */
-
-//********
-//* Code *
-//********
-
-static inline int
-i2Validate ( i2ChanStrPtr pCh )
-{
-	//ip2trace(pCh->port_index, ITRC_VERIFY,ITRC_ENTER,2,pCh->validity,
-	//	(CHANNEL_MAGIC | CHANNEL_SUPPORT));
-	return ((pCh->validity & (CHANNEL_MAGIC_BITS | CHANNEL_SUPPORT)) 
-			  == (CHANNEL_MAGIC | CHANNEL_SUPPORT));
-}
-
-static void iiSendPendingMail_t(unsigned long data)
-{
-	i2eBordStrPtr pB = (i2eBordStrPtr)data;
-
-	iiSendPendingMail(pB);
-}
-
-//******************************************************************************
-// Function:   iiSendPendingMail(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// If any outgoing mail bits are set and there is outgoing mailbox is empty,
-// send the mail and clear the bits.
-//******************************************************************************
-static void
-iiSendPendingMail(i2eBordStrPtr pB)
-{
-	if (pB->i2eOutMailWaiting && (!pB->i2eWaitingForEmptyFifo) )
-	{
-		if (iiTrySendMail(pB, pB->i2eOutMailWaiting))
-		{
-			/* If we were already waiting for fifo to empty,
-			 * or just sent MB_OUT_STUFFED, then we are
-			 * still waiting for it to empty, until we should
-			 * receive an MB_IN_STRIPPED from the board.
-			 */
-			pB->i2eWaitingForEmptyFifo |=
-				(pB->i2eOutMailWaiting & MB_OUT_STUFFED);
-			pB->i2eOutMailWaiting = 0;
-			pB->SendPendingRetry = 0;
-		} else {
-/*		The only time we hit this area is when "iiTrySendMail" has
-		failed.  That only occurs when the outbound mailbox is
-		still busy with the last message.  We take a short breather
-		to let the board catch up with itself and then try again.
-		16 Retries is the limit - then we got a borked board.
-			/\/\|=mhw=|\/\/				*/
-
-			if( ++pB->SendPendingRetry < 16 ) {
-				setup_timer(&pB->SendPendingTimer,
-					iiSendPendingMail_t, (unsigned long)pB);
-				mod_timer(&pB->SendPendingTimer, jiffies + 1);
-			} else {
-				printk( KERN_ERR "IP2: iiSendPendingMail unable to queue outbound mail\n" );
-			}
-		}
-	}
-}
-
-//******************************************************************************
-// Function:   i2InitChannels(pB, nChannels, pCh)
-// Parameters: Pointer to Ellis Board structure
-//             Number of channels to initialize
-//             Pointer to first element in an array of channel structures
-// Returns:    Success or failure
-//
-// Description:
-//
-// This function patches pointers, back-pointers, and initializes all the
-// elements in the channel structure array.
-//
-// This should be run after the board structure is initialized, through having
-// loaded the standard loadware (otherwise it complains).
-//
-// In any case, it must be done before any serious work begins initializing the
-// irq's or sending commands...
-//
-//******************************************************************************
-static int
-i2InitChannels ( i2eBordStrPtr pB, int nChannels, i2ChanStrPtr pCh)
-{
-	int index, stuffIndex;
-	i2ChanStrPtr *ppCh;
-	
-	if (pB->i2eValid != I2E_MAGIC) {
-		I2_COMPLETE(pB, I2EE_BADMAGIC);
-	}
-	if (pB->i2eState != II_STATE_STDLOADED) {
-		I2_COMPLETE(pB, I2EE_BADSTATE);
-	}
-
-	rwlock_init(&pB->read_fifo_spinlock);
-	rwlock_init(&pB->write_fifo_spinlock);
-	rwlock_init(&pB->Dbuf_spinlock);
-	rwlock_init(&pB->Bbuf_spinlock);
-	rwlock_init(&pB->Fbuf_spinlock);
-	
-	// NO LOCK needed yet - this is init
-
-	pB->i2eChannelPtr = pCh;
-	pB->i2eChannelCnt = nChannels;
-
-	pB->i2Fbuf_strip = pB->i2Fbuf_stuff = 0;
-	pB->i2Dbuf_strip = pB->i2Dbuf_stuff = 0;
-	pB->i2Bbuf_strip = pB->i2Bbuf_stuff = 0;
-
-	pB->SendPendingRetry = 0;
-
-	memset ( pCh, 0, sizeof (i2ChanStr) * nChannels );
-
-	for (index = stuffIndex = 0, ppCh = (i2ChanStrPtr *)(pB->i2Fbuf);
-		  nChannels && index < ABS_MOST_PORTS;
-		  index++)
-	{
-		if ( !(pB->i2eChannelMap[index >> 4] & (1 << (index & 0xf)) ) ) {
-			continue;
-		}
-		rwlock_init(&pCh->Ibuf_spinlock);
-		rwlock_init(&pCh->Obuf_spinlock);
-		rwlock_init(&pCh->Cbuf_spinlock);
-		rwlock_init(&pCh->Pbuf_spinlock);
-		// NO LOCK needed yet - this is init
-		// Set up validity flag according to support level
-		if (pB->i2eGoodMap[index >> 4] & (1 << (index & 0xf)) ) {
-			pCh->validity = CHANNEL_MAGIC | CHANNEL_SUPPORT;
-		} else {
-			pCh->validity = CHANNEL_MAGIC;
-		}
-		pCh->pMyBord = pB;      /* Back-pointer */
-
-		// Prepare an outgoing flow-control packet to send as soon as the chance
-		// occurs.
-		if ( pCh->validity & CHANNEL_SUPPORT ) {
-			pCh->infl.hd.i2sChannel = index;
-			pCh->infl.hd.i2sCount = 5;
-			pCh->infl.hd.i2sType = PTYPE_BYPASS;
-			pCh->infl.fcmd = 37;
-			pCh->infl.asof = 0;
-			pCh->infl.room = IBUF_SIZE - 1;
-
-			pCh->whenSendFlow = (IBUF_SIZE/5)*4; // when 80% full
-
-		// The following is similar to calling i2QueueNeeds, except that this
-		// is done in longhand, since we are setting up initial conditions on
-		// many channels at once.
-			pCh->channelNeeds = NEED_FLOW;  // Since starting from scratch
-			pCh->sinceLastFlow = 0;         // No bytes received since last flow
-											// control packet was queued
-			stuffIndex++;
-			*ppCh++ = pCh;      // List this channel as needing
-								// initial flow control packet sent
-		}
-
-		// Don't allow anything to be sent until the status packets come in from
-		// the board.
-
-		pCh->outfl.asof = 0;
-		pCh->outfl.room = 0;
-
-		// Initialize all the ring buffers
-
-		pCh->Ibuf_stuff = pCh->Ibuf_strip = 0;
-		pCh->Obuf_stuff = pCh->Obuf_strip = 0;
-		pCh->Cbuf_stuff = pCh->Cbuf_strip = 0;
-
-		memset( &pCh->icount, 0, sizeof (struct async_icount) );
-		pCh->hotKeyIn       = HOT_CLEAR;
-		pCh->channelOptions = 0;
-		pCh->bookMarks      = 0;
-		init_waitqueue_head(&pCh->pBookmarkWait);
-
-		init_waitqueue_head(&pCh->open_wait);
-		init_waitqueue_head(&pCh->close_wait);
-		init_waitqueue_head(&pCh->delta_msr_wait);
-
-		// Set base and divisor so default custom rate is 9600
-		pCh->BaudBase    = 921600;	// MAX for ST654, changed after we get
-		pCh->BaudDivisor = 96;		// the boxids (UART types) later
-
-		pCh->dataSetIn   = 0;
-		pCh->dataSetOut  = 0;
-
-		pCh->wopen       = 0;
-		pCh->throttled   = 0;
-
-		pCh->speed       = CBR_9600;
-
-		pCh->flags    = 0;
-
-		pCh->ClosingDelay     = 5*HZ/10;
-		pCh->ClosingWaitTime  = 30*HZ;
-
-		// Initialize task queue objects
-		INIT_WORK(&pCh->tqueue_input, do_input);
-		INIT_WORK(&pCh->tqueue_status, do_status);
-
-#ifdef IP2DEBUG_TRACE
-		pCh->trace = ip2trace;
-#endif
-
-		++pCh;
-     	--nChannels;
-	}
-	// No need to check for wrap here; this is initialization.
-	pB->i2Fbuf_stuff = stuffIndex;
-	I2_COMPLETE(pB, I2EE_GOOD);
-
-}
-
-//******************************************************************************
-// Function:   i2DeQueueNeeds(pB, type)
-// Parameters: Pointer to a board structure
-//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
-// Returns:   
-//             Pointer to a channel structure
-//
-// Description: Returns pointer struct of next channel that needs service of
-//  the type specified. Otherwise returns a NULL reference.
-//
-//******************************************************************************
-static i2ChanStrPtr 
-i2DeQueueNeeds(i2eBordStrPtr pB, int type)
-{
-	unsigned short queueIndex;
-	unsigned long flags;
-
-	i2ChanStrPtr pCh = NULL;
-
-	switch(type) {
-
-	case  NEED_INLINE:
-
-		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
-		if ( pB->i2Dbuf_stuff != pB->i2Dbuf_strip)
-		{
-			queueIndex = pB->i2Dbuf_strip;
-			pCh = pB->i2Dbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Dbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_INLINE;
-		}
-		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
-		break;
-
-	case NEED_BYPASS:
-
-		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
-		if (pB->i2Bbuf_stuff != pB->i2Bbuf_strip)
-		{
-			queueIndex = pB->i2Bbuf_strip;
-			pCh = pB->i2Bbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Bbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_BYPASS;
-		}
-		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
-		break;
-	
-	case NEED_FLOW:
-
-		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
-		if (pB->i2Fbuf_stuff != pB->i2Fbuf_strip)
-		{
-			queueIndex = pB->i2Fbuf_strip;
-			pCh = pB->i2Fbuf[queueIndex];
-			queueIndex++;
-			if (queueIndex >= CH_QUEUE_SIZE) {
-				queueIndex = 0;
-			}
-			pB->i2Fbuf_strip = queueIndex;
-			pCh->channelNeeds &= ~NEED_FLOW;
-		}
-		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
-		break;
-	default:
-		printk(KERN_ERR "i2DeQueueNeeds called with bad type:%x\n",type);
-		break;
-	}
-	return pCh;
-}
-
-//******************************************************************************
-// Function:   i2QueueNeeds(pB, pCh, type)
-// Parameters: Pointer to a board structure
-//             Pointer to a channel structure
-//             type bit map: may include NEED_INLINE, NEED_BYPASS, or NEED_FLOW
-// Returns:    Nothing
-//
-// Description:
-// For each type of need selected, if the given channel is not already in the
-// queue, adds it, and sets the flag indicating it is in the queue.
-//******************************************************************************
-static void
-i2QueueNeeds(i2eBordStrPtr pB, i2ChanStrPtr pCh, int type)
-{
-	unsigned short queueIndex;
-	unsigned long flags;
-
-	// We turn off all the interrupts during this brief process, since the
-	// interrupt-level code might want to put things on the queue as well.
-
-	switch (type) {
-
-	case NEED_INLINE:
-
-		write_lock_irqsave(&pB->Dbuf_spinlock, flags);
-		if ( !(pCh->channelNeeds & NEED_INLINE) )
-		{
-			pCh->channelNeeds |= NEED_INLINE;
-			queueIndex = pB->i2Dbuf_stuff;
-			pB->i2Dbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Dbuf_stuff = queueIndex;
-		}
-		write_unlock_irqrestore(&pB->Dbuf_spinlock, flags);
-		break;
-
-	case NEED_BYPASS:
-
-		write_lock_irqsave(&pB->Bbuf_spinlock, flags);
-		if ((type & NEED_BYPASS) && !(pCh->channelNeeds & NEED_BYPASS))
-		{
-			pCh->channelNeeds |= NEED_BYPASS;
-			queueIndex = pB->i2Bbuf_stuff;
-			pB->i2Bbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Bbuf_stuff = queueIndex;
-		} 
-		write_unlock_irqrestore(&pB->Bbuf_spinlock, flags);
-		break;
-
-	case NEED_FLOW:
-
-		write_lock_irqsave(&pB->Fbuf_spinlock, flags);
-		if ((type & NEED_FLOW) && !(pCh->channelNeeds & NEED_FLOW))
-		{
-			pCh->channelNeeds |= NEED_FLOW;
-			queueIndex = pB->i2Fbuf_stuff;
-			pB->i2Fbuf[queueIndex++] = pCh;
-			if (queueIndex >= CH_QUEUE_SIZE)
-				queueIndex = 0;
-			pB->i2Fbuf_stuff = queueIndex;
-		}
-		write_unlock_irqrestore(&pB->Fbuf_spinlock, flags);
-		break;
-
-	case NEED_CREDIT:
-		pCh->channelNeeds |= NEED_CREDIT;
-		break;
-	default:
-		printk(KERN_ERR "i2QueueNeeds called with bad type:%x\n",type);
-		break;
-	}
-	return;
-}
-
-//******************************************************************************
-// Function:   i2QueueCommands(type, pCh, timeout, nCommands, pCs,...)
-// Parameters: type - PTYPE_BYPASS or PTYPE_INLINE
-//             pointer to the channel structure
-//             maximum period to wait
-//             number of commands (n)
-//             n commands
-// Returns:    Number of commands sent, or -1 for error
-//
-// get board lock before calling
-//
-// Description:
-// Queues up some commands to be sent to a channel. To send possibly several
-// bypass or inline commands to the given channel. The timeout parameter
-// indicates how many HUNDREDTHS OF SECONDS to wait until there is room:
-// 0 = return immediately if no room, -ive  = wait forever, +ive = number of
-// 1/100 seconds to wait. Return values:
-// -1 Some kind of nasty error: bad channel structure or invalid arguments.
-//  0 No room to send all the commands
-// (+)   Number of commands sent
-//******************************************************************************
-static int
-i2QueueCommands(int type, i2ChanStrPtr pCh, int timeout, int nCommands,
-					 cmdSyntaxPtr pCs0,...)
-{
-	int totalsize = 0;
-	int blocksize;
-	int lastended;
-	cmdSyntaxPtr *ppCs;
-	cmdSyntaxPtr pCs;
-	int count;
-	int flag;
-	i2eBordStrPtr pB;
-
-	unsigned short maxBlock;
-	unsigned short maxBuff;
-	short bufroom;
-	unsigned short stuffIndex;
-	unsigned char *pBuf;
-	unsigned char *pInsert;
-	unsigned char *pDest, *pSource;
-	unsigned short channel;
-	int cnt;
-	unsigned long flags = 0;
-	rwlock_t *lock_var_p = NULL;
-
-	// Make sure the channel exists, otherwise do nothing
-	if ( !i2Validate ( pCh ) ) {
-		return -1;
-	}
-
-	ip2trace (CHANN, ITRC_QUEUE, ITRC_ENTER, 0 );
-
-	pB = pCh->pMyBord;
-
-	// Board must also exist, and THE INTERRUPT COMMAND ALREADY SENT
-	if (pB->i2eValid != I2E_MAGIC || pB->i2eUsingIrq == I2_IRQ_UNDEFINED)
-		return -2;
-	// If the board has gone fatal, return bad, and also hit the trap routine if
-	// it exists.
-	if (pB->i2eFatal) {
-		if ( pB->i2eFatalTrap ) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return -3;
-	}
-	// Set up some variables, Which buffers are we using?  How big are they?
-	switch(type)
-	{
-	case PTYPE_INLINE:
-		flag = INL;
-		maxBlock = MAX_OBUF_BLOCK;
-		maxBuff = OBUF_SIZE;
-		pBuf = pCh->Obuf;
-		break;
-	case PTYPE_BYPASS:
-		flag = BYP;
-		maxBlock = MAX_CBUF_BLOCK;
-		maxBuff = CBUF_SIZE;
-		pBuf = pCh->Cbuf;
-		break;
-	default:
-		return -4;
-	}
-	// Determine the total size required for all the commands
-	totalsize = blocksize = sizeof(i2CmdHeader);
-	lastended = 0;
-	ppCs = &pCs0;
-	for ( count = nCommands; count; count--, ppCs++)
-	{
-		pCs = *ppCs;
-		cnt = pCs->length;
-		// Will a new block be needed for this one? 
-		// Two possible reasons: too
-		// big or previous command has to be at the end of a packet.
-		if ((blocksize + cnt > maxBlock) || lastended) {
-			blocksize = sizeof(i2CmdHeader);
-			totalsize += sizeof(i2CmdHeader);
-		}
-		totalsize += cnt;
-		blocksize += cnt;
-
-		// If this command had to end a block, then we will make sure to
-		// account for it should there be any more blocks.
-		lastended = pCs->flags & END;
-	}
-	for (;;) {
-		// Make sure any pending flush commands go out before we add more data.
-		if ( !( pCh->flush_flags && i2RetryFlushOutput( pCh ) ) ) {
-			// How much room (this time through) ?
-			switch(type) {
-			case PTYPE_INLINE:
-				lock_var_p = &pCh->Obuf_spinlock;
-				write_lock_irqsave(lock_var_p, flags);
-				stuffIndex = pCh->Obuf_stuff;
-				bufroom = pCh->Obuf_strip - stuffIndex;
-				break;
-			case PTYPE_BYPASS:
-				lock_var_p = &pCh->Cbuf_spinlock;
-				write_lock_irqsave(lock_var_p, flags);
-				stuffIndex = pCh->Cbuf_stuff;
-				bufroom = pCh->Cbuf_strip - stuffIndex;
-				break;
-			default:
-				return -5;
-			}
-			if (--bufroom < 0) {
-				bufroom += maxBuff;
-			}
-
-			ip2trace (CHANN, ITRC_QUEUE, 2, 1, bufroom );
-
-			// Check for overflow
-			if (totalsize <= bufroom) {
-				// Normal Expected path - We still hold LOCK
-				break; /* from for()- Enough room: goto proceed */
-			}
-			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-			write_unlock_irqrestore(lock_var_p, flags);
-		} else
-			ip2trace(CHANN, ITRC_QUEUE, 3, 1, totalsize);
-
-		/* Prepare to wait for buffers to empty */
-		serviceOutgoingFifo(pB);	// Dump what we got
-
-		if (timeout == 0) {
-			return 0;   // Tired of waiting
-		}
-		if (timeout > 0)
-			timeout--;   // So negative values == forever
-		
-		if (!in_interrupt()) {
-			schedule_timeout_interruptible(1);	// short nap
-		} else {
-			// we cannot sched/sleep in interrupt silly
-			return 0;   
-		}
-		if (signal_pending(current)) {
-			return 0;   // Wake up! Time to die!!!
-		}
-
-		ip2trace (CHANN, ITRC_QUEUE, 4, 0 );
-
-	}	// end of for(;;)
-
-	// At this point we have room and the lock - stick them in.
-	channel = pCh->infl.hd.i2sChannel;
-	pInsert = &pBuf[stuffIndex];     // Pointer to start of packet
-	pDest = CMD_OF(pInsert);         // Pointer to start of command
-
-	// When we start counting, the block is the size of the header
-	for (blocksize = sizeof(i2CmdHeader), count = nCommands,
-			lastended = 0, ppCs = &pCs0;
-		count;
-		count--, ppCs++)
-	{
-		pCs = *ppCs;         // Points to command protocol structure
-
-		// If this is a bookmark request command, post the fact that a bookmark
-		// request is pending. NOTE THIS TRICK ONLY WORKS BECAUSE CMD_BMARK_REQ
-		// has no parameters!  The more general solution would be to reference
-		// pCs->cmd[0].
-		if (pCs == CMD_BMARK_REQ) {
-			pCh->bookMarks++;
-
-			ip2trace (CHANN, ITRC_DRAIN, 30, 1, pCh->bookMarks );
-
-		}
-		cnt = pCs->length;
-
-		// If this command would put us over the maximum block size or 
-		// if the last command had to be at the end of a block, we end
-		// the existing block here and start a new one.
-		if ((blocksize + cnt > maxBlock) || lastended) {
-
-			ip2trace (CHANN, ITRC_QUEUE, 5, 0 );
-
-			PTYPE_OF(pInsert) = type;
-			CHANNEL_OF(pInsert) = channel;
-			// count here does not include the header
-			CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
-			stuffIndex += blocksize;
-			if(stuffIndex >= maxBuff) {
-				stuffIndex = 0;
-				pInsert = pBuf;
-			}
-			pInsert = &pBuf[stuffIndex];  // Pointer to start of next pkt
-			pDest = CMD_OF(pInsert);
-			blocksize = sizeof(i2CmdHeader);
-		}
-		// Now we know there is room for this one in the current block
-
-		blocksize += cnt;       // Total bytes in this command
-		pSource = pCs->cmd;     // Copy the command into the buffer
-		while (cnt--) {
-			*pDest++ = *pSource++;
-		}
-		// If this command had to end a block, then we will make sure to account
-		// for it should there be any more blocks.
-		lastended = pCs->flags & END;
-	}	// end for
-	// Clean up the final block by writing header, etc
-
-	PTYPE_OF(pInsert) = type;
-	CHANNEL_OF(pInsert) = channel;
-	// count here does not include the header
-	CMD_COUNT_OF(pInsert) = blocksize - sizeof(i2CmdHeader);
-	stuffIndex += blocksize;
-	if(stuffIndex >= maxBuff) {
-		stuffIndex = 0;
-		pInsert = pBuf;
-	}
-	// Updates the index, and post the need for service. When adding these to
-	// the queue of channels, we turn off the interrupt while doing so,
-	// because at interrupt level we might want to push a channel back to the
-	// end of the queue.
-	switch(type)
-	{
-	case PTYPE_INLINE:
-		pCh->Obuf_stuff = stuffIndex;  // Store buffer pointer
-		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-		pB->debugInlineQueued++;
-		// Add the channel pointer to list of channels needing service (first
-		// come...), if it's not already there.
-		i2QueueNeeds(pB, pCh, NEED_INLINE);
-		break;
-
-	case PTYPE_BYPASS:
-		pCh->Cbuf_stuff = stuffIndex;  // Store buffer pointer
-		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
-
-		pB->debugBypassQueued++;
-		// Add the channel pointer to list of channels needing service (first
-		// come...), if it's not already there.
-		i2QueueNeeds(pB, pCh, NEED_BYPASS);
-		break;
-	}
-
-	ip2trace (CHANN, ITRC_QUEUE, ITRC_RETURN, 1, nCommands );
-
-	return nCommands; // Good status: number of commands sent
-}
-
-//******************************************************************************
-// Function:   i2GetStatus(pCh,resetBits)
-// Parameters: Pointer to a channel structure
-//             Bit map of status bits to clear
-// Returns:    Bit map of current status bits
-//
-// Description:
-// Returns the state of data set signals, and whether a break has been received,
-// (see i2lib.h for bit-mapped result). resetBits is a bit-map of any status
-// bits to be cleared: I2_BRK, I2_PAR, I2_FRA, I2_OVR,... These are cleared
-// AFTER the condition is passed. If pCh does not point to a valid channel,
-// returns -1 (which would be impossible otherwise.
-//******************************************************************************
-static int
-i2GetStatus(i2ChanStrPtr pCh, int resetBits)
-{
-	unsigned short status;
-	i2eBordStrPtr pB;
-
-	ip2trace (CHANN, ITRC_STATUS, ITRC_ENTER, 2, pCh->dataSetIn, resetBits );
-
-	// Make sure the channel exists, otherwise do nothing */
-	if ( !i2Validate ( pCh ) )
-		return -1;
-
-	pB = pCh->pMyBord;
-
-	status = pCh->dataSetIn;
-
-	// Clear any specified error bits: but note that only actual error bits can
-	// be cleared, regardless of the value passed.
-	if (resetBits)
-	{
-		pCh->dataSetIn &= ~(resetBits & (I2_BRK | I2_PAR | I2_FRA | I2_OVR));
-		pCh->dataSetIn &= ~(I2_DDCD | I2_DCTS | I2_DDSR | I2_DRI);
-	}
-
-	ip2trace (CHANN, ITRC_STATUS, ITRC_RETURN, 1, pCh->dataSetIn );
-
-	return status;
-}
-
-//******************************************************************************
-// Function:   i2Input(pChpDest,count)
-// Parameters: Pointer to a channel structure
-//             Pointer to data buffer
-//             Number of bytes to read
-// Returns:    Number of bytes read, or -1 for error
-//
-// Description:
-// Strips data from the input buffer and writes it to pDest. If there is a
-// collosal blunder, (invalid structure pointers or the like), returns -1.
-// Otherwise, returns the number of bytes read.
-//******************************************************************************
-static int
-i2Input(i2ChanStrPtr pCh)
-{
-	int amountToMove;
-	unsigned short stripIndex;
-	int count;
-	unsigned long flags = 0;
-
-	ip2trace (CHANN, ITRC_INPUT, ITRC_ENTER, 0);
-
-	// Ensure channel structure seems real
-	if ( !i2Validate( pCh ) ) {
-		count = -1;
-		goto i2Input_exit;
-	}
-	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-
-	// initialize some accelerators and private copies
-	stripIndex = pCh->Ibuf_strip;
-
-	count = pCh->Ibuf_stuff - stripIndex;
-
-	// If buffer is empty or requested data count was 0, (trivial case) return
-	// without any further thought.
-	if ( count == 0 ) {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		goto i2Input_exit;
-	}
-	// Adjust for buffer wrap
-	if ( count < 0 ) {
-		count += IBUF_SIZE;
-	}
-	// Don't give more than can be taken by the line discipline
-	amountToMove = pCh->pTTY->receive_room;
-	if (count > amountToMove) {
-		count = amountToMove;
-	}
-	// How much could we copy without a wrap?
-	amountToMove = IBUF_SIZE - stripIndex;
-
-	if (amountToMove > count) {
-		amountToMove = count;
-	}
-	// Move the first block
-	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->Ibuf, NULL, count - amountToMove );
-	}
-	// Bump and wrap the stripIndex all at once by the amount of data read. This
-	// method is good regardless of whether the data was in one or two pieces.
-	stripIndex += count;
-	if (stripIndex >= IBUF_SIZE) {
-		stripIndex -= IBUF_SIZE;
-	}
-	pCh->Ibuf_strip = stripIndex;
-
-	// Update our flow control information and possibly queue ourselves to send
-	// it, depending on how much data has been stripped since the last time a
-	// packet was sent.
-	pCh->infl.asof += count;
-
-	if ((pCh->sinceLastFlow += count) >= pCh->whenSendFlow) {
-		pCh->sinceLastFlow -= pCh->whenSendFlow;
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
-	} else {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	}
-
-i2Input_exit:
-
-	ip2trace (CHANN, ITRC_INPUT, ITRC_RETURN, 1, count);
-
-	return count;
-}
-
-//******************************************************************************
-// Function:   i2InputFlush(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Number of bytes stripped, or -1 for error
-//
-// Description:
-// Strips any data from the input buffer. If there is a collosal blunder,
-// (invalid structure pointers or the like), returns -1. Otherwise, returns the
-// number of bytes stripped.
-//******************************************************************************
-static int
-i2InputFlush(i2ChanStrPtr pCh)
-{
-	int count;
-	unsigned long flags;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) )
-		return -1;
-
-	ip2trace (CHANN, ITRC_INPUT, 10, 0);
-
-	write_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-
-	// Adjust for buffer wrap
-	if (count < 0) {
-		count += IBUF_SIZE;
-	}
-
-	// Expedient way to zero out the buffer
-	pCh->Ibuf_strip = pCh->Ibuf_stuff;
-
-
-	// Update our flow control information and possibly queue ourselves to send
-	// it, depending on how much data has been stripped since the last time a
-	// packet was sent.
-
-	pCh->infl.asof += count;
-
-	if ( (pCh->sinceLastFlow += count) >= pCh->whenSendFlow )
-	{
-		pCh->sinceLastFlow -= pCh->whenSendFlow;
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-		i2QueueNeeds(pCh->pMyBord, pCh, NEED_FLOW);
-	} else {
-		write_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	}
-
-	ip2trace (CHANN, ITRC_INPUT, 19, 1, count);
-
-	return count;
-}
-
-//******************************************************************************
-// Function:   i2InputAvailable(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Number of bytes available, or -1 for error
-//
-// Description:
-// If there is a collosal blunder, (invalid structure pointers or the like),
-// returns -1. Otherwise, returns the number of bytes stripped. Otherwise,
-// returns the number of bytes available in the buffer.
-//******************************************************************************
-#if 0
-static int
-i2InputAvailable(i2ChanStrPtr pCh)
-{
-	int count;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) return -1;
-
-
-	// initialize some accelerators and private copies
-	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	count = pCh->Ibuf_stuff - pCh->Ibuf_strip;
-	read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-
-	// Adjust for buffer wrap
-	if (count < 0)
-	{
-		count += IBUF_SIZE;
-	}
-
-	return count;
-}
-#endif 
-
-//******************************************************************************
-// Function:   i2Output(pCh, pSource, count)
-// Parameters: Pointer to channel structure
-//             Pointer to source data
-//             Number of bytes to send
-// Returns:    Number of bytes sent, or -1 for error
-//
-// Description:
-// Queues the data at pSource to be sent as data packets to the board. If there
-// is a collosal blunder, (invalid structure pointers or the like), returns -1.
-// Otherwise, returns the number of bytes written. What if there is not enough
-// room for all the data? If pCh->channelOptions & CO_NBLOCK_WRITE is set, then
-// we transfer as many characters as we can now, then return. If this bit is
-// clear (default), routine will spin along until all the data is buffered.
-// Should this occur, the 1-ms delay routine is called while waiting to avoid
-// applications that one cannot break out of.
-//******************************************************************************
-static int
-i2Output(i2ChanStrPtr pCh, const char *pSource, int count)
-{
-	i2eBordStrPtr pB;
-	unsigned char *pInsert;
-	int amountToMove;
-	int countOriginal = count;
-	unsigned short channel;
-	unsigned short stuffIndex;
-	unsigned long flags;
-
-	int bailout = 10;
-
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_ENTER, 2, count, 0 );
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) 
-		return -1;
-
-	// initialize some accelerators and private copies
-	pB = pCh->pMyBord;
-	channel = pCh->infl.hd.i2sChannel;
-
-	// If the board has gone fatal, return bad, and also hit the trap routine if
-	// it exists.
-	if (pB->i2eFatal) {
-		if (pB->i2eFatalTrap) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return -1;
-	}
-	// Proceed as though we would do everything
-	while ( count > 0 ) {
-
-		// How much room in output buffer is there?
-		read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-		amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-		read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-		if (amountToMove < 0) {
-			amountToMove += OBUF_SIZE;
-		}
-		// Subtract off the headers size and see how much room there is for real
-		// data. If this is negative, we will discover later.
-		amountToMove -= sizeof (i2DataHeader);
-
-		// Don't move more (now) than can go in a single packet
-		if ( amountToMove > (int)(MAX_OBUF_BLOCK - sizeof(i2DataHeader)) ) {
-			amountToMove = MAX_OBUF_BLOCK - sizeof(i2DataHeader);
-		}
-		// Don't move more than the count we were given
-		if (amountToMove > count) {
-			amountToMove = count;
-		}
-		// Now we know how much we must move: NB because the ring buffers have
-		// an overflow area at the end, we needn't worry about wrapping in the
-		// middle of a packet.
-
-// Small WINDOW here with no LOCK but I can't call Flush with LOCK
-// We would be flushing (or ending flush) anyway
-
-		ip2trace (CHANN, ITRC_OUTPUT, 10, 1, amountToMove );
-
-		if ( !(pCh->flush_flags && i2RetryFlushOutput(pCh) ) 
-				&& amountToMove > 0 )
-		{
-			write_lock_irqsave(&pCh->Obuf_spinlock, flags);
-			stuffIndex = pCh->Obuf_stuff;
-      
-			// Had room to move some data: don't know whether the block size,
-			// buffer space, or what was the limiting factor...
-			pInsert = &(pCh->Obuf[stuffIndex]);
-
-			// Set up the header
-			CHANNEL_OF(pInsert)     = channel;
-			PTYPE_OF(pInsert)       = PTYPE_DATA;
-			TAG_OF(pInsert)         = 0;
-			ID_OF(pInsert)          = ID_ORDINARY_DATA;
-			DATA_COUNT_OF(pInsert)  = amountToMove;
-
-			// Move the data
-			memcpy( (char*)(DATA_OF(pInsert)), pSource, amountToMove );
-			// Adjust pointers and indices
-			pSource					+= amountToMove;
-			pCh->Obuf_char_count	+= amountToMove;
-			stuffIndex 				+= amountToMove + sizeof(i2DataHeader);
-			count 					-= amountToMove;
-
-			if (stuffIndex >= OBUF_SIZE) {
-				stuffIndex = 0;
-			}
-			pCh->Obuf_stuff = stuffIndex;
-
-			write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-			ip2trace (CHANN, ITRC_OUTPUT, 13, 1, stuffIndex );
-
-		} else {
-
-			// Cannot move data
-			// becuz we need to stuff a flush 
-			// or amount to move is <= 0
-
-			ip2trace(CHANN, ITRC_OUTPUT, 14, 3,
-				amountToMove,  pB->i2eFifoRemains,
-				pB->i2eWaitingForEmptyFifo );
-
-			// Put this channel back on queue
-			// this ultimatly gets more data or wakes write output
-			i2QueueNeeds(pB, pCh, NEED_INLINE);
-
-			if ( pB->i2eWaitingForEmptyFifo ) {
-
-				ip2trace (CHANN, ITRC_OUTPUT, 16, 0 );
-
-				// or schedule
-				if (!in_interrupt()) {
-
-					ip2trace (CHANN, ITRC_OUTPUT, 61, 0 );
-
-					schedule_timeout_interruptible(2);
-					if (signal_pending(current)) {
-						break;
-					}
-					continue;
-				} else {
-
-					ip2trace (CHANN, ITRC_OUTPUT, 62, 0 );
-
-					// let interrupt in = WAS restore_flags()
-					// We hold no lock nor is irq off anymore???
-					
-					break;
-				}
-				break;   // from while(count)
-			}
-			else if ( pB->i2eFifoRemains < 32 && !pB->i2eTxMailEmpty ( pB ) )
-			{
-				ip2trace (CHANN, ITRC_OUTPUT, 19, 2,
-					pB->i2eFifoRemains,
-					pB->i2eTxMailEmpty );
-
-				break;   // from while(count)
-			} else if ( pCh->channelNeeds & NEED_CREDIT ) {
-
-				ip2trace (CHANN, ITRC_OUTPUT, 22, 0 );
-
-				break;   // from while(count)
-			} else if ( --bailout) {
-
-				// Try to throw more things (maybe not us) in the fifo if we're
-				// not already waiting for it.
-	
-				ip2trace (CHANN, ITRC_OUTPUT, 20, 0 );
-
-				serviceOutgoingFifo(pB);
-				//break;  CONTINUE;
-			} else {
-				ip2trace (CHANN, ITRC_OUTPUT, 21, 3,
-					pB->i2eFifoRemains,
-					pB->i2eOutMailWaiting,
-					pB->i2eWaitingForEmptyFifo );
-
-				break;   // from while(count)
-			}
-		}
-	} // End of while(count)
-
-	i2QueueNeeds(pB, pCh, NEED_INLINE);
-
-	// We drop through either when the count expires, or when there is some
-	// count left, but there was a non-blocking write.
-	if (countOriginal > count) {
-
-		ip2trace (CHANN, ITRC_OUTPUT, 17, 2, countOriginal, count );
-
-		serviceOutgoingFifo( pB );
-	}
-
-	ip2trace (CHANN, ITRC_OUTPUT, ITRC_RETURN, 2, countOriginal, count );
-
-	return countOriginal - count;
-}
-
-//******************************************************************************
-// Function:   i2FlushOutput(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Nothing
-//
-// Description:
-// Sends bypass command to start flushing (waiting possibly forever until there
-// is room), then sends inline command to stop flushing output, (again waiting
-// possibly forever).
-//******************************************************************************
-static inline void
-i2FlushOutput(i2ChanStrPtr pCh)
-{
-
-	ip2trace (CHANN, ITRC_FLUSH, 1, 1, pCh->flush_flags );
-
-	if (pCh->flush_flags)
-		return;
-
-	if ( 1 != i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
-		pCh->flush_flags = STARTFL_FLAG;		// Failed - flag for later
-
-		ip2trace (CHANN, ITRC_FLUSH, 2, 0 );
-
-	} else if ( 1 != i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL) ) {
-		pCh->flush_flags = STOPFL_FLAG;		// Failed - flag for later
-
-		ip2trace (CHANN, ITRC_FLUSH, 3, 0 );
-	}
-}
-
-static int 
-i2RetryFlushOutput(i2ChanStrPtr pCh)
-{
-	int old_flags = pCh->flush_flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, 14, 1, old_flags );
-
-	pCh->flush_flags = 0;	// Clear flag so we can avoid recursion
-									// and queue the commands
-
-	if ( old_flags & STARTFL_FLAG ) {
-		if ( 1 == i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_STARTFL) ) {
-			old_flags = STOPFL_FLAG;	//Success - send stop flush
-		} else {
-			old_flags = STARTFL_FLAG;	//Failure - Flag for retry later
-		}
-
-		ip2trace (CHANN, ITRC_FLUSH, 15, 1, old_flags );
-
-	}
-	if ( old_flags & STOPFL_FLAG ) {
-		if (1 == i2QueueCommands(PTYPE_INLINE, pCh, 0, 1, CMD_STOPFL)) {
-			old_flags = 0;	// Success - clear flags
-		}
-
-		ip2trace (CHANN, ITRC_FLUSH, 16, 1, old_flags );
-	}
-	pCh->flush_flags = old_flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, 17, 1, old_flags );
-
-	return old_flags;
-}
-
-//******************************************************************************
-// Function:   i2DrainOutput(pCh,timeout)
-// Parameters: Pointer to a channel structure
-//             Maximum period to wait
-// Returns:    ?
-//
-// Description:
-// Uses the bookmark request command to ask the board to send a bookmark back as
-// soon as all the data is completely sent.
-//******************************************************************************
-static void
-i2DrainWakeup(unsigned long d)
-{
-	i2ChanStrPtr pCh = (i2ChanStrPtr)d;
-
-	ip2trace (CHANN, ITRC_DRAIN, 10, 1, pCh->BookmarkTimer.expires );
-
-	pCh->BookmarkTimer.expires = 0;
-	wake_up_interruptible( &pCh->pBookmarkWait );
-}
-
-static void
-i2DrainOutput(i2ChanStrPtr pCh, int timeout)
-{
-	wait_queue_t wait;
-	i2eBordStrPtr pB;
-
-	ip2trace (CHANN, ITRC_DRAIN, ITRC_ENTER, 1, pCh->BookmarkTimer.expires);
-
-	pB = pCh->pMyBord;
-	// If the board has gone fatal, return bad, 
-	// and also hit the trap routine if it exists.
-	if (pB->i2eFatal) {
-		if (pB->i2eFatalTrap) {
-			(*(pB)->i2eFatalTrap)(pB);
-		}
-		return;
-	}
-	if ((timeout > 0) && (pCh->BookmarkTimer.expires == 0 )) {
-		// One per customer (channel)
-		setup_timer(&pCh->BookmarkTimer, i2DrainWakeup,
-				(unsigned long)pCh);
-
-		ip2trace (CHANN, ITRC_DRAIN, 1, 1, pCh->BookmarkTimer.expires );
-
-		mod_timer(&pCh->BookmarkTimer, jiffies + timeout);
-	}
-	
-	i2QueueCommands( PTYPE_INLINE, pCh, -1, 1, CMD_BMARK_REQ );
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&(pCh->pBookmarkWait), &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	serviceOutgoingFifo( pB );
-	
-	schedule();	// Now we take our interruptible sleep on
-
-	// Clean up the queue
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&(pCh->pBookmarkWait), &wait);
-
-	// if expires == 0 then timer poped, then do not need to del_timer
-	if ((timeout > 0) && pCh->BookmarkTimer.expires && 
-	                     time_before(jiffies, pCh->BookmarkTimer.expires)) {
-		del_timer( &(pCh->BookmarkTimer) );
-		pCh->BookmarkTimer.expires = 0;
-
-		ip2trace (CHANN, ITRC_DRAIN, 3, 1, pCh->BookmarkTimer.expires );
-
-	}
-	ip2trace (CHANN, ITRC_DRAIN, ITRC_RETURN, 1, pCh->BookmarkTimer.expires );
-	return;
-}
-
-//******************************************************************************
-// Function:   i2OutputFree(pCh)
-// Parameters: Pointer to a channel structure
-// Returns:    Space in output buffer
-//
-// Description:
-// Returns -1 if very gross error. Otherwise returns the amount of bytes still
-// free in the output buffer.
-//******************************************************************************
-static int
-i2OutputFree(i2ChanStrPtr pCh)
-{
-	int amountToMove;
-	unsigned long flags;
-
-	// Ensure channel structure seems real
-	if ( !i2Validate ( pCh ) ) {
-		return -1;
-	}
-	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-	amountToMove = pCh->Obuf_strip - pCh->Obuf_stuff - 1;
-	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-
-	if (amountToMove < 0) {
-		amountToMove += OBUF_SIZE;
-	}
-	// If this is negative, we will discover later
-	amountToMove -= sizeof(i2DataHeader);
-
-	return (amountToMove < 0) ? 0 : amountToMove;
-}
-static void
-
-ip2_owake( PTTY tp)
-{
-	i2ChanStrPtr  pCh;
-
-	if (tp == NULL) return;
-
-	pCh = tp->driver_data;
-
-	ip2trace (CHANN, ITRC_SICMD, 10, 2, tp->flags,
-			(1 << TTY_DO_WRITE_WAKEUP) );
-
-	tty_wakeup(tp);
-}
-
-static inline void
-set_baud_params(i2eBordStrPtr pB) 
-{
-	int i,j;
-	i2ChanStrPtr  *pCh;
-
-	pCh = (i2ChanStrPtr *) pB->i2eChannelPtr;
-
-	for (i = 0; i < ABS_MAX_BOXES; i++) {
-		if (pB->channelBtypes.bid_value[i]) {
-			if (BID_HAS_654(pB->channelBtypes.bid_value[i])) {
-				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
-					if (pCh[i*16+j] == NULL)
-						break;
-					(pCh[i*16+j])->BaudBase    = 921600;	// MAX for ST654
-					(pCh[i*16+j])->BaudDivisor = 96;
-				}
-			} else {	// has cirrus cd1400
-				for (j = 0; j < ABS_BIGGEST_BOX; j++) {
-					if (pCh[i*16+j] == NULL)
-						break;
-					(pCh[i*16+j])->BaudBase    = 115200;	// MAX for CD1400
-					(pCh[i*16+j])->BaudDivisor = 12;
-				}
-			}
-		}
-	}
-}
-
-//******************************************************************************
-// Function:   i2StripFifo(pB)
-// Parameters: Pointer to a board structure
-// Returns:    ?
-//
-// Description:
-// Strips all the available data from the incoming FIFO, identifies the type of
-// packet, and either buffers the data or does what needs to be done.
-//
-// Note there is no overflow checking here: if the board sends more data than it
-// ought to, we will not detect it here, but blindly overflow...
-//******************************************************************************
-
-// A buffer for reading in blocks for unknown channels
-static unsigned char junkBuffer[IBUF_SIZE];
-
-// A buffer to read in a status packet. Because of the size of the count field
-// for these things, the maximum packet size must be less than MAX_CMD_PACK_SIZE
-static unsigned char cmdBuffer[MAX_CMD_PACK_SIZE + 4];
-
-// This table changes the bit order from MSR order given by STAT_MODEM packet to
-// status bits used in our library.
-static char xlatDss[16] = {
-0      | 0     | 0      | 0      ,
-0      | 0     | 0      | I2_CTS ,
-0      | 0     | I2_DSR | 0      ,
-0      | 0     | I2_DSR | I2_CTS ,
-0      | I2_RI | 0      | 0      ,
-0      | I2_RI | 0      | I2_CTS ,
-0      | I2_RI | I2_DSR | 0      ,
-0      | I2_RI | I2_DSR | I2_CTS ,
-I2_DCD | 0     | 0      | 0      ,
-I2_DCD | 0     | 0      | I2_CTS ,
-I2_DCD | 0     | I2_DSR | 0      ,
-I2_DCD | 0     | I2_DSR | I2_CTS ,
-I2_DCD | I2_RI | 0      | 0      ,
-I2_DCD | I2_RI | 0      | I2_CTS ,
-I2_DCD | I2_RI | I2_DSR | 0      ,
-I2_DCD | I2_RI | I2_DSR | I2_CTS };
-
-static inline void
-i2StripFifo(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	int channel;
-	int count;
-	unsigned short stuffIndex;
-	int amountToRead;
-	unsigned char *pc, *pcLimit;
-	unsigned char uc;
-	unsigned char dss_change;
-	unsigned long bflags,cflags;
-
-//	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_ENTER, 0 );
-
-	while (I2_HAS_INPUT(pB)) {
-//		ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 2, 0 );
-
-		// Process packet from fifo a one atomic unit
-		write_lock_irqsave(&pB->read_fifo_spinlock, bflags);
-   
-		// The first word (or two bytes) will have channel number and type of
-		// packet, possibly other information
-		pB->i2eLeadoffWord[0] = iiReadWord(pB);
-
-		switch(PTYPE_OF(pB->i2eLeadoffWord))
-		{
-		case PTYPE_DATA:
-			pB->got_input = 1;
-
-//			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 3, 0 );
-
-			channel = CHANNEL_OF(pB->i2eLeadoffWord); /* Store channel */
-			count = iiReadWord(pB);          /* Count is in the next word */
-
-// NEW: Check the count for sanity! Should the hardware fail, our death
-// is more pleasant. While an oversize channel is acceptable (just more
-// than the driver supports), an over-length count clearly means we are
-// sick!
-			if ( ((unsigned int)count) > IBUF_SIZE ) {
-				pB->i2eFatal = 2;
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				return;     /* Bail out ASAP */
-			}
-			// Channel is illegally big ?
-			if ((channel >= pB->i2eChannelCnt) ||
-				(NULL==(pCh = ((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])))
-			{
-				iiReadBuf(pB, junkBuffer, count);
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				break;         /* From switch: ready for next packet */
-			}
-
-			// Channel should be valid, then
-
-			// If this is a hot-key, merely post its receipt for now. These are
-			// always supposed to be 1-byte packets, so we won't even check the
-			// count. Also we will post an acknowledgement to the board so that
-			// more data can be forthcoming. Note that we are not trying to use
-			// these sequences in this driver, merely to robustly ignore them.
-			if(ID_OF(pB->i2eLeadoffWord) == ID_HOT_KEY)
-			{
-				pCh->hotKeyIn = iiReadWord(pB) & 0xff;
-				write_unlock_irqrestore(&pB->read_fifo_spinlock,
-						bflags);
-				i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_HOTACK);
-				break;   /* From the switch: ready for next packet */
-			}
-
-			// Normal data! We crudely assume there is room for the data in our
-			// buffer because the board wouldn't have exceeded his credit limit.
-			write_lock_irqsave(&pCh->Ibuf_spinlock, cflags);
-													// We have 2 locks now
-			stuffIndex = pCh->Ibuf_stuff;
-			amountToRead = IBUF_SIZE - stuffIndex;
-			if (amountToRead > count)
-				amountToRead = count;
-
-			// stuffIndex would have been already adjusted so there would 
-			// always be room for at least one, and count is always at least
-			// one.
-
-			iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
-			pCh->icount.rx += amountToRead;
-
-			// Update the stuffIndex by the amount of data moved. Note we could
-			// never ask for more data than would just fit. However, we might
-			// have read in one more byte than we wanted because the read
-			// rounds up to even bytes. If this byte is on the end of the
-			// packet, and is padding, we ignore it. If the byte is part of
-			// the actual data, we need to move it.
-
-			stuffIndex += amountToRead;
-
-			if (stuffIndex >= IBUF_SIZE) {
-				if ((amountToRead & 1) && (count > amountToRead)) {
-					pCh->Ibuf[0] = pCh->Ibuf[IBUF_SIZE];
-					amountToRead++;
-					stuffIndex = 1;
-				} else {
-					stuffIndex = 0;
-				}
-			}
-
-			// If there is anything left over, read it as well
-			if (count > amountToRead) {
-				amountToRead = count - amountToRead;
-				iiReadBuf(pB, &(pCh->Ibuf[stuffIndex]), amountToRead);
-				pCh->icount.rx += amountToRead;
-				stuffIndex += amountToRead;
-			}
-
-			// Update stuff index
-			pCh->Ibuf_stuff = stuffIndex;
-			write_unlock_irqrestore(&pCh->Ibuf_spinlock, cflags);
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-#ifdef USE_IQ
-			schedule_work(&pCh->tqueue_input);
-#else
-			do_input(&pCh->tqueue_input);
-#endif
-
-			// Note we do not need to maintain any flow-control credits at this
-			// time:  if we were to increment .asof and decrement .room, there
-			// would be no net effect. Instead, when we strip data, we will
-			// increment .asof and leave .room unchanged.
-
-			break;   // From switch: ready for next packet
-
-		case PTYPE_STATUS:
-			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 4, 0 );
-      
-			count = CMD_COUNT_OF(pB->i2eLeadoffWord);
-
-			iiReadBuf(pB, cmdBuffer, count);
-			// We can release early with buffer grab
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-			pc = cmdBuffer;
-			pcLimit = &(cmdBuffer[count]);
-
-			while (pc < pcLimit) {
-				channel = *pc++;
-
-				ip2trace (channel, ITRC_SFIFO, 7, 2, channel, *pc );
-
-				/* check for valid channel */
-				if (channel < pB->i2eChannelCnt
-					 && 
-					 (pCh = (((i2ChanStrPtr*)pB->i2eChannelPtr)[channel])) != NULL
-					)
-				{
-					dss_change = 0;
-
-					switch (uc = *pc++)
-					{
-					/* Breaks and modem signals are easy: just update status */
-					case STAT_CTS_UP:
-						if ( !(pCh->dataSetIn & I2_CTS) )
-						{
-							pCh->dataSetIn |= I2_DCTS;
-							pCh->icount.cts++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_CTS;
-						break;
-
-					case STAT_CTS_DN:
-						if ( pCh->dataSetIn & I2_CTS )
-						{
-							pCh->dataSetIn |= I2_DCTS;
-							pCh->icount.cts++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_CTS;
-						break;
-
-					case STAT_DCD_UP:
-						ip2trace (channel, ITRC_MODEM, 1, 1, pCh->dataSetIn );
-
-						if ( !(pCh->dataSetIn & I2_DCD) )
-						{
-							ip2trace (CHANN, ITRC_MODEM, 2, 0 );
-							pCh->dataSetIn |= I2_DDCD;
-							pCh->icount.dcd++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_DCD;
-
-						ip2trace (channel, ITRC_MODEM, 3, 1, pCh->dataSetIn );
-						break;
-
-					case STAT_DCD_DN:
-						ip2trace (channel, ITRC_MODEM, 4, 1, pCh->dataSetIn );
-						if ( pCh->dataSetIn & I2_DCD )
-						{
-							ip2trace (channel, ITRC_MODEM, 5, 0 );
-							pCh->dataSetIn |= I2_DDCD;
-							pCh->icount.dcd++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_DCD;
-
-						ip2trace (channel, ITRC_MODEM, 6, 1, pCh->dataSetIn );
-						break;
-
-					case STAT_DSR_UP:
-						if ( !(pCh->dataSetIn & I2_DSR) )
-						{
-							pCh->dataSetIn |= I2_DDSR;
-							pCh->icount.dsr++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_DSR;
-						break;
-
-					case STAT_DSR_DN:
-						if ( pCh->dataSetIn & I2_DSR )
-						{
-							pCh->dataSetIn |= I2_DDSR;
-							pCh->icount.dsr++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn &= ~I2_DSR;
-						break;
-
-					case STAT_RI_UP:
-						if ( !(pCh->dataSetIn & I2_RI) )
-						{
-							pCh->dataSetIn |= I2_DRI;
-							pCh->icount.rng++;
-							dss_change = 1;
-						}
-						pCh->dataSetIn |= I2_RI ;
-						break;
-
-					case STAT_RI_DN:
-						// to be compat with serial.c
-						//if ( pCh->dataSetIn & I2_RI )
-						//{
-						//	pCh->dataSetIn |= I2_DRI;
-						//	pCh->icount.rng++; 
-						//	dss_change = 1;
-						//}
-						pCh->dataSetIn &= ~I2_RI ;
-						break;
-
-					case STAT_BRK_DET:
-						pCh->dataSetIn |= I2_BRK;
-						pCh->icount.brk++;
-						dss_change = 1;
-						break;
-
-					// Bookmarks? one less request we're waiting for
-					case STAT_BMARK:
-						pCh->bookMarks--;
-						if (pCh->bookMarks <= 0 ) {
-							pCh->bookMarks = 0;
-							wake_up_interruptible( &pCh->pBookmarkWait );
-
-						ip2trace (channel, ITRC_DRAIN, 20, 1, pCh->BookmarkTimer.expires );
-						}
-						break;
-
-					// Flow control packets? Update the new credits, and if
-					// someone was waiting for output, queue him up again.
-					case STAT_FLOW:
-						pCh->outfl.room =
-							((flowStatPtr)pc)->room -
-							(pCh->outfl.asof - ((flowStatPtr)pc)->asof);
-
-						ip2trace (channel, ITRC_STFLW, 1, 1, pCh->outfl.room );
-
-						if (pCh->channelNeeds & NEED_CREDIT)
-						{
-							ip2trace (channel, ITRC_STFLW, 2, 1, pCh->channelNeeds);
-
-							pCh->channelNeeds &= ~NEED_CREDIT;
-							i2QueueNeeds(pB, pCh, NEED_INLINE);
-							if ( pCh->pTTY )
-								ip2_owake(pCh->pTTY);
-						}
-
-						ip2trace (channel, ITRC_STFLW, 3, 1, pCh->channelNeeds);
-
-						pc += sizeof(flowStat);
-						break;
-
-					/* Special packets: */
-					/* Just copy the information into the channel structure */
-
-					case STAT_STATUS:
-
-						pCh->channelStatus = *((debugStatPtr)pc);
-						pc += sizeof(debugStat);
-						break;
-
-					case STAT_TXCNT:
-
-						pCh->channelTcount = *((cntStatPtr)pc);
-						pc += sizeof(cntStat);
-						break;
-
-					case STAT_RXCNT:
-
-						pCh->channelRcount = *((cntStatPtr)pc);
-						pc += sizeof(cntStat);
-						break;
-
-					case STAT_BOXIDS:
-						pB->channelBtypes = *((bidStatPtr)pc);
-						pc += sizeof(bidStat);
-						set_baud_params(pB);
-						break;
-
-					case STAT_HWFAIL:
-						i2QueueCommands (PTYPE_INLINE, pCh, 0, 1, CMD_HW_TEST);
-						pCh->channelFail = *((failStatPtr)pc);
-						pc += sizeof(failStat);
-						break;
-
-					/* No explicit match? then
-					 * Might be an error packet...
-					 */
-					default:
-						switch (uc & STAT_MOD_ERROR)
-						{
-						case STAT_ERROR:
-							if (uc & STAT_E_PARITY) {
-								pCh->dataSetIn |= I2_PAR;
-								pCh->icount.parity++;
-							}
-							if (uc & STAT_E_FRAMING){
-								pCh->dataSetIn |= I2_FRA;
-								pCh->icount.frame++;
-							}
-							if (uc & STAT_E_OVERRUN){
-								pCh->dataSetIn |= I2_OVR;
-								pCh->icount.overrun++;
-							}
-							break;
-
-						case STAT_MODEM:
-							// the answer to DSS_NOW request (not change)
-							pCh->dataSetIn = (pCh->dataSetIn
-								& ~(I2_RI | I2_CTS | I2_DCD | I2_DSR) )
-								| xlatDss[uc & 0xf];
-							wake_up_interruptible ( &pCh->dss_now_wait );
-						default:
-							break;
-						}
-					}  /* End of switch on status type */
-					if (dss_change) {
-#ifdef USE_IQ
-						schedule_work(&pCh->tqueue_status);
-#else
-						do_status(&pCh->tqueue_status);
-#endif
-					}
-				}
-				else  /* Or else, channel is invalid */
-				{
-					// Even though the channel is invalid, we must test the
-					// status to see how much additional data it has (to be
-					// skipped)
-					switch (*pc++)
-					{
-					case STAT_FLOW:
-						pc += 4;    /* Skip the data */
-						break;
-
-					default:
-						break;
-					}
-				}
-			}  // End of while (there is still some status packet left)
-			break;
-
-		default: // Neither packet? should be impossible
-			ip2trace (ITRC_NO_PORT, ITRC_SFIFO, 5, 1,
-				PTYPE_OF(pB->i2eLeadoffWord) );
-			write_unlock_irqrestore(&pB->read_fifo_spinlock,
-					bflags);
-
-			break;
-		}  // End of switch on type of packets
-	}	/*while(board I2_HAS_INPUT)*/
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFIFO, ITRC_RETURN, 0 );
-
-	// Send acknowledgement to the board even if there was no data!
-	pB->i2eOutMailWaiting |= MB_IN_STRIPPED;
-	return;
-}
-
-//******************************************************************************
-// Function:   i2Write2Fifo(pB,address,count)
-// Parameters: Pointer to a board structure, source address, byte count
-// Returns:    bytes written
-//
-// Description:
-//  Writes count bytes to board io address(implied) from source
-//  Adjusts count, leaves reserve for next time around bypass cmds
-//******************************************************************************
-static int
-i2Write2Fifo(i2eBordStrPtr pB, unsigned char *source, int count,int reserve)
-{
-	int rc = 0;
-	unsigned long flags;
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	if (!pB->i2eWaitingForEmptyFifo) {
-		if (pB->i2eFifoRemains > (count+reserve)) {
-			pB->i2eFifoRemains -= count;
-			iiWriteBuf(pB, source, count);
-			pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
-			rc =  count;
-		}
-	}
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-	return rc;
-}
-//******************************************************************************
-// Function:   i2StuffFifoBypass(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as many bypass commands into the fifo as possible. This is simpler
-// than stuffing data or inline commands to fifo, since we do not have
-// flow-control to deal with.
-//******************************************************************************
-static inline void
-i2StuffFifoBypass(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned char *pRemove;
-	unsigned short stripIndex;
-	unsigned short packetSize;
-	unsigned short paddedSize;
-	unsigned short notClogged = 1;
-	unsigned long flags;
-
-	int bailout = 1000;
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( --bailout && notClogged && 
-			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_BYPASS))))
-	{
-		write_lock_irqsave(&pCh->Cbuf_spinlock, flags);
-		stripIndex = pCh->Cbuf_strip;
-
-		// as long as there are packets for this channel...
-
-		while (stripIndex != pCh->Cbuf_stuff) {
-			pRemove = &(pCh->Cbuf[stripIndex]);
-			packetSize = CMD_COUNT_OF(pRemove) + sizeof(i2CmdHeader);
-			paddedSize = roundup(packetSize, 2);
-
-			if (paddedSize > 0) {
-				if ( 0 == i2Write2Fifo(pB, pRemove, paddedSize,0)) {
-					notClogged = 0;	/* fifo full */
-					i2QueueNeeds(pB, pCh, NEED_BYPASS);	// Put back on queue
-					break;   // Break from the channel
-				} 
-			}
-#ifdef DEBUG_FIFO
-WriteDBGBuf("BYPS", pRemove, paddedSize);
-#endif	/* DEBUG_FIFO */
-			pB->debugBypassCount++;
-
-			pRemove += packetSize;
-			stripIndex += packetSize;
-			if (stripIndex >= CBUF_SIZE) {
-				stripIndex = 0;
-				pRemove = pCh->Cbuf;
-			}
-		}
-		// Done with this channel. Move to next, removing this one from 
-		// the queue of channels if we cleaned it out (i.e., didn't get clogged.
-		pCh->Cbuf_strip = stripIndex;
-		write_unlock_irqrestore(&pCh->Cbuf_spinlock, flags);
-	}  // Either clogged or finished all the work
-
-#ifdef IP2DEBUG_TRACE
-	if ( !bailout ) {
-		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 1, 0 );
-	}
-#endif
-}
-
-//******************************************************************************
-// Function:   i2StuffFifoFlow(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as many flow control packets into the fifo as possible. This is easier
-// even than doing normal bypass commands, because there is always at most one
-// packet, already assembled, for each channel.
-//******************************************************************************
-static inline void
-i2StuffFifoFlow(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned short paddedSize = roundup(sizeof(flowIn), 2);
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_ENTER, 2,
-		pB->i2eFifoRemains, paddedSize );
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( (NULL != (pCh = i2DeQueueNeeds(pB,NEED_FLOW)))) {
-		pB->debugFlowCount++;
-
-		// NO Chan LOCK needed ???
-		if ( 0 == i2Write2Fifo(pB,(unsigned char *)&(pCh->infl),paddedSize,0)) {
-			break;
-		}
-#ifdef DEBUG_FIFO
-		WriteDBGBuf("FLOW",(unsigned char *) &(pCh->infl), paddedSize);
-#endif /* DEBUG_FIFO */
-
-	}  // Either clogged or finished all the work
-
-	ip2trace (ITRC_NO_PORT, ITRC_SFLOW, ITRC_RETURN, 0 );
-}
-
-//******************************************************************************
-// Function:   i2StuffFifoInline(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Stuffs as much data and inline commands into the fifo as possible. This is
-// the most complex fifo-stuffing operation, since there if now the channel
-// flow-control issue to deal with.
-//******************************************************************************
-static inline void
-i2StuffFifoInline(i2eBordStrPtr pB)
-{
-	i2ChanStrPtr pCh;
-	unsigned char *pRemove;
-	unsigned short stripIndex;
-	unsigned short packetSize;
-	unsigned short paddedSize;
-	unsigned short notClogged = 1;
-	unsigned short flowsize;
-	unsigned long flags;
-
-	int bailout  = 1000;
-	int bailout2;
-
-	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_ENTER, 3, pB->i2eFifoRemains, 
-			pB->i2Dbuf_strip, pB->i2Dbuf_stuff );
-
-	// Continue processing so long as there are entries, or there is room in the
-	// fifo. Each entry represents a channel with something to do.
-	while ( --bailout && notClogged && 
-			(NULL != (pCh = i2DeQueueNeeds(pB,NEED_INLINE))) )
-	{
-		write_lock_irqsave(&pCh->Obuf_spinlock, flags);
-		stripIndex = pCh->Obuf_strip;
-
-		ip2trace (CHANN, ITRC_SICMD, 3, 2, stripIndex, pCh->Obuf_stuff );
-
-		// as long as there are packets for this channel...
-		bailout2 = 1000;
-		while ( --bailout2 && stripIndex != pCh->Obuf_stuff) {
-			pRemove = &(pCh->Obuf[stripIndex]);
-
-			// Must determine whether this be a data or command packet to
-			// calculate correctly the header size and the amount of
-			// flow-control credit this type of packet will use.
-			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
-				flowsize = DATA_COUNT_OF(pRemove);
-				packetSize = flowsize + sizeof(i2DataHeader);
-			} else {
-				flowsize = CMD_COUNT_OF(pRemove);
-				packetSize = flowsize + sizeof(i2CmdHeader);
-			}
-			flowsize = CREDIT_USAGE(flowsize);
-			paddedSize = roundup(packetSize, 2);
-
-			ip2trace (CHANN, ITRC_SICMD, 4, 2, pB->i2eFifoRemains, paddedSize );
-
-			// If we don't have enough credits from the board to send the data,
-			// flag the channel that we are waiting for flow control credit, and
-			// break out. This will clean up this channel and remove us from the
-			// queue of hot things to do.
-
-				ip2trace (CHANN, ITRC_SICMD, 5, 2, pCh->outfl.room, flowsize );
-
-			if (pCh->outfl.room <= flowsize)	{
-				// Do Not have the credits to send this packet.
-				i2QueueNeeds(pB, pCh, NEED_CREDIT);
-				notClogged = 0;
-				break;   // So to do next channel
-			}
-			if ( (paddedSize > 0) 
-				&& ( 0 == i2Write2Fifo(pB, pRemove, paddedSize, 128))) {
-				// Do Not have room in fifo to send this packet.
-				notClogged = 0;
-				i2QueueNeeds(pB, pCh, NEED_INLINE);	
-				break;   // Break from the channel
-			}
-#ifdef DEBUG_FIFO
-WriteDBGBuf("DATA", pRemove, paddedSize);
-#endif /* DEBUG_FIFO */
-			pB->debugInlineCount++;
-
-			pCh->icount.tx += flowsize;
-			// Update current credits
-			pCh->outfl.room -= flowsize;
-			pCh->outfl.asof += flowsize;
-			if (PTYPE_OF(pRemove) == PTYPE_DATA) {
-				pCh->Obuf_char_count -= DATA_COUNT_OF(pRemove);
-			}
-			pRemove += packetSize;
-			stripIndex += packetSize;
-
-			ip2trace (CHANN, ITRC_SICMD, 6, 2, stripIndex, pCh->Obuf_strip);
-
-			if (stripIndex >= OBUF_SIZE) {
-				stripIndex = 0;
-				pRemove = pCh->Obuf;
-
-				ip2trace (CHANN, ITRC_SICMD, 7, 1, stripIndex );
-
-			}
-		}	/* while */
-		if ( !bailout2 ) {
-			ip2trace (CHANN, ITRC_ERROR, 3, 0 );
-		}
-		// Done with this channel. Move to next, removing this one from the
-		// queue of channels if we cleaned it out (i.e., didn't get clogged.
-		pCh->Obuf_strip = stripIndex;
-		write_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-		if ( notClogged )
-		{
-
-			ip2trace (CHANN, ITRC_SICMD, 8, 0 );
-
-			if ( pCh->pTTY ) {
-				ip2_owake(pCh->pTTY);
-			}
-		}
-	}  // Either clogged or finished all the work
-
-	if ( !bailout ) {
-		ip2trace (ITRC_NO_PORT, ITRC_ERROR, 4, 0 );
-	}
-
-	ip2trace (ITRC_NO_PORT, ITRC_SICMD, ITRC_RETURN, 1,pB->i2Dbuf_strip);
-}
-
-//******************************************************************************
-// Function:   serviceOutgoingFifo(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Helper routine to put data in the outgoing fifo, if we aren't already waiting
-// for something to be there. If the fifo has only room for a very little data,
-// go head and hit the board with a mailbox hit immediately. Otherwise, it will
-// have to happen later in the interrupt processing. Since this routine may be
-// called both at interrupt and foreground time, we must turn off interrupts
-// during the entire process.
-//******************************************************************************
-static void
-serviceOutgoingFifo(i2eBordStrPtr pB)
-{
-	// If we aren't currently waiting for the board to empty our fifo, service
-	// everything that is pending, in priority order (especially, Bypass before
-	// Inline).
-	if ( ! pB->i2eWaitingForEmptyFifo )
-	{
-		i2StuffFifoFlow(pB);
-		i2StuffFifoBypass(pB);
-		i2StuffFifoInline(pB);
-
-		iiSendPendingMail(pB);
-	} 
-}
-
-//******************************************************************************
-// Function:   i2ServiceBoard(pB)
-// Parameters: Pointer to a board structure
-// Returns:    Nothing
-//
-// Description:
-// Normally this is called from interrupt level, but there is deliberately
-// nothing in here specific to being called from interrupt level. All the
-// hardware-specific, interrupt-specific things happen at the outer levels.
-//
-// For example, a timer interrupt could drive this routine for some sort of
-// polled operation. The only requirement is that the programmer deal with any
-// atomiticity/concurrency issues that result.
-//
-// This routine responds to the board's having sent mailbox information to the
-// host (which would normally cause an interrupt). This routine reads the
-// incoming mailbox. If there is no data in it, this board did not create the
-// interrupt and/or has nothing to be done to it. (Except, if we have been
-// waiting to write mailbox data to it, we may do so.
-//
-// Based on the value in the mailbox, we may take various actions.
-//
-// No checking here of pB validity: after all, it shouldn't have been called by
-// the handler unless pB were on the list.
-//******************************************************************************
-static inline int
-i2ServiceBoard ( i2eBordStrPtr pB )
-{
-	unsigned inmail;
-	unsigned long flags;
-
-
-	/* This should be atomic because of the way we are called... */
-	if (NO_MAIL_HERE == ( inmail = pB->i2eStartMail ) ) {
-		inmail = iiGetMail(pB);
-	}
-	pB->i2eStartMail = NO_MAIL_HERE;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 2, 1, inmail );
-
-	if (inmail != NO_MAIL_HERE) {
-		// If the board has gone fatal, nothing to do but hit a bit that will
-		// alert foreground tasks to protest!
-		if ( inmail & MB_FATAL_ERROR ) {
-			pB->i2eFatal = 1;
-			goto exit_i2ServiceBoard;
-		}
-
-		/* Assuming no fatal condition, we proceed to do work */
-		if ( inmail & MB_IN_STUFFED ) {
-			pB->i2eFifoInInts++;
-			i2StripFifo(pB);     /* There might be incoming packets */
-		}
-
-		if (inmail & MB_OUT_STRIPPED) {
-			pB->i2eFifoOutInts++;
-			write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-			pB->i2eFifoRemains = pB->i2eFifoSize;
-			pB->i2eWaitingForEmptyFifo = 0;
-			write_unlock_irqrestore(&pB->write_fifo_spinlock,
-					flags);
-
-			ip2trace (ITRC_NO_PORT, ITRC_INTR, 30, 1, pB->i2eFifoRemains );
-
-		}
-		serviceOutgoingFifo(pB);
-	}
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 8, 0 );
-
-exit_i2ServiceBoard:
-
-	return 0;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2lib.h linux-libre-2.6.39-gnu/drivers/char/ip2/i2lib.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2lib.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2lib.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,351 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Header file for high level library functions
-*
-*******************************************************************************/
-#ifndef I2LIB_H
-#define I2LIB_H   1
-//------------------------------------------------------------------------------
-// I2LIB.H
-//
-// IntelliPort-II and IntelliPort-IIEX
-//
-// Defines, structure definitions, and external declarations for i2lib.c
-//------------------------------------------------------------------------------
-//--------------------------------------
-// Mandatory Includes:
-//--------------------------------------
-#include "ip2types.h"
-#include "i2ellis.h"
-#include "i2pack.h"
-#include "i2cmd.h"
-#include <linux/workqueue.h>
-
-//------------------------------------------------------------------------------
-// i2ChanStr -- Channel Structure:
-// Used to track per-channel information for the library routines using standard
-// loadware. Note also, a pointer to an array of these structures is patched
-// into the i2eBordStr (see i2ellis.h)
-//------------------------------------------------------------------------------
-//
-// If we make some limits on the maximum block sizes, we can avoid dealing with
-// buffer wrap. The wrapping of the buffer is based on where the start of the
-// packet is. Then there is always room for the packet contiguously.
-//
-// Maximum total length of an outgoing data or in-line command block. The limit
-// of 36 on data is quite arbitrary and based more on DOS memory limitations
-// than the board interface. However, for commands, the maximum packet length is
-// MAX_CMD_PACK_SIZE, because the field size for the count is only a few bits
-// (see I2PACK.H) in such packets. For data packets, the count field size is not
-// the limiting factor. As of this writing, MAX_OBUF_BLOCK < MAX_CMD_PACK_SIZE,
-// but be careful if wanting to modify either.
-//
-#define MAX_OBUF_BLOCK  36
-
-// Another note on maximum block sizes: we are buffering packets here. Data is
-// put into the buffer (if there is room) regardless of the credits from the
-// board. The board sends new credits whenever it has removed from his buffers a
-// number of characters equal to 80% of total buffer size. (Of course, the total
-// buffer size is what is reported when the very first set of flow control
-// status packets are received from the board. Therefore, to be robust, you must
-// always fill the board to at least 80% of the current credit limit, else you
-// might not give it enough to trigger a new report. These conditions are
-// obtained here so long as the maximum output block size is less than 20% the
-// size of the board's output buffers. This is true at present by "coincidence"
-// or "infernal knowledge": the board's output buffers are at least 700 bytes
-// long (20% = 140 bytes, at least). The 80% figure is "official", so the safest
-// strategy might be to trap the first flow control report and guarantee that
-// the effective maxObufBlock is the minimum of MAX_OBUF_BLOCK and 20% of first
-// reported buffer credit.
-//
-#define MAX_CBUF_BLOCK  6	// Maximum total length of a bypass command block
-
-#define IBUF_SIZE       512	// character capacity of input buffer per channel
-#define OBUF_SIZE       1024// character capacity of output buffer per channel
-#define CBUF_SIZE       10	// character capacity of output bypass buffer
-
-typedef struct _i2ChanStr
-{
-	// First, back-pointers so that given a pointer to this structure, you can
-	// determine the correct board and channel number to reference, (say, when
-	// issuing commands, etc. (Note, channel number is in infl.hd.i2sChannel.)
-
-	int      port_index;    // Index of port in channel structure array attached
-							// to board structure.
-	PTTY     pTTY;          // Pointer to tty structure for port (OS specific)
-	USHORT   validity;      // Indicates whether the given channel has been
-							// initialized, really exists (or is a missing
-							// channel, e.g. channel 9 on an 8-port box.)
-
-	i2eBordStrPtr  pMyBord; // Back-pointer to this channel's board structure 
-
-	int      wopen;			// waiting fer carrier
-
-	int      throttled;		// Set if upper layer can take no data
-
-	int      flags;         // Defined in tty.h
-
-	PWAITQ   open_wait;     // Pointer for OS sleep function.
-	PWAITQ   close_wait;    // Pointer for OS sleep function.
-	PWAITQ   delta_msr_wait;// Pointer for OS sleep function.
-	PWAITQ   dss_now_wait;	// Pointer for OS sleep function.
-
-	struct timer_list  BookmarkTimer;   // Used by i2DrainOutput
-	wait_queue_head_t pBookmarkWait;   // Used by i2DrainOutput
-
-	int      BaudBase;
-	int      BaudDivisor;
-
-	USHORT   ClosingDelay;
-	USHORT   ClosingWaitTime;
-
-	volatile
-	flowIn   infl;	// This structure is initialized as a completely
-					// formed flow-control command packet, and as such
-					// has the channel number, also the capacity and
-					// "as-of" data needed continuously.
-
-	USHORT   sinceLastFlow; // Counts the number of characters read from input
-							// buffers, since the last time flow control info
-							// was sent.
-
-	USHORT   whenSendFlow;  // Determines when new flow control is to be sent to
-							// the board. Note unlike earlier manifestations of
-							// the driver, these packets can be sent from
-							// in-place.
-
-	USHORT   channelNeeds;  // Bit map of important things which must be done
-							// for this channel. (See bits below )
-
-	volatile
-	flowStat outfl;         // Same type of structure is used to hold current
-							// flow control information used to control our
-							// output. "asof" is kept updated as data is sent,
-							// and "room" never goes to zero.
-
-	// The incoming ring buffer
-	// Unlike the outgoing buffers, this holds raw data, not packets. The two
-	// extra bytes are used to hold the byte-padding when there is room for an
-	// odd number of bytes before we must wrap.
-	//
-	UCHAR    Ibuf[IBUF_SIZE + 2];
-	volatile
-	USHORT   Ibuf_stuff;     // Stuffing index
-	volatile
-	USHORT   Ibuf_strip;     // Stripping index
-
-	// The outgoing ring-buffer: Holds Data and command packets. N.B., even
-	// though these are in the channel structure, the channel is also written
-	// here, the easier to send it to the fifo when ready. HOWEVER, individual
-	// packets here are NOT padded to even length: the routines for writing
-	// blocks to the fifo will pad to even byte counts.
-	//
-	UCHAR	Obuf[OBUF_SIZE+MAX_OBUF_BLOCK+4];
-	volatile
-	USHORT	Obuf_stuff;     // Stuffing index
-	volatile
-	USHORT	Obuf_strip;     // Stripping index
-	int	Obuf_char_count;
-
-	// The outgoing bypass-command buffer. Unlike earlier manifestations, the
-	// flow control packets are sent directly from the structures. As above, the
-	// channel number is included in the packet, but they are NOT padded to even
-	// size.
-	//
-	UCHAR    Cbuf[CBUF_SIZE+MAX_CBUF_BLOCK+2];
-	volatile
-	USHORT   Cbuf_stuff;     // Stuffing index
-	volatile
-	USHORT   Cbuf_strip;     // Stripping index
-
-	// The temporary buffer for the Linux tty driver PutChar entry.
-	//
-	UCHAR    Pbuf[MAX_OBUF_BLOCK - sizeof (i2DataHeader)];
-	volatile
-	USHORT   Pbuf_stuff;     // Stuffing index
-
-	// The state of incoming data-set signals
-	//
-	USHORT   dataSetIn;     // Bit-mapped according to below. Also indicates
-							// whether a break has been detected since last
-							// inquiry.
-
-	// The state of outcoming data-set signals (as far as we can tell!)
-	//
-	USHORT   dataSetOut;     // Bit-mapped according to below. 
-
-	// Most recent hot-key identifier detected
-	//
-	USHORT   hotKeyIn;      // Hot key as sent by the board, HOT_CLEAR indicates
-				// no hot key detected since last examined.
-
-	// Counter of outstanding requests for bookmarks
-	//
-	short   bookMarks;	// Number of outstanding bookmark requests, (+ive
-						// whenever a bookmark request if queued up, -ive
-						// whenever a bookmark is received).
-
-	// Misc options
-	//
-	USHORT   channelOptions;   // See below
-
-	// To store various incoming special packets
-	//
-	debugStat   channelStatus;
-	cntStat     channelRcount;
-	cntStat     channelTcount;
-	failStat    channelFail;
-
-	// To store the last values for line characteristics we sent to the board.
-	//
-	int	speed;
-
-	int flush_flags;
-
-	void (*trace)(unsigned short,unsigned char,unsigned char,unsigned long,...);
-
-	/*
-	 * Kernel counters for the 4 input interrupts 
-	 */
-	struct async_icount icount;
-
-	/*
-	 *	Task queues for processing input packets from the board.
-	 */
-	struct work_struct	tqueue_input;
-	struct work_struct	tqueue_status;
-	struct work_struct	tqueue_hangup;
-
-	rwlock_t Ibuf_spinlock;
-	rwlock_t Obuf_spinlock;
-	rwlock_t Cbuf_spinlock;
-	rwlock_t Pbuf_spinlock;
-
-} i2ChanStr, *i2ChanStrPtr;
-
-//---------------------------------------------------
-// Manifests and bit-maps for elements in i2ChanStr
-//---------------------------------------------------
-//
-// flush flags
-//
-#define STARTFL_FLAG 1
-#define STOPFL_FLAG  2
-
-// validity
-//
-#define CHANNEL_MAGIC_BITS 0xff00
-#define CHANNEL_MAGIC      0x5300   // (validity & CHANNEL_MAGIC_BITS) ==
-									// CHANNEL_MAGIC --> structure good
-
-#define CHANNEL_SUPPORT    0x0001   // Indicates channel is supported, exists,
-									// and passed P.O.S.T.
-
-// channelNeeds
-//
-#define NEED_FLOW    1  // Indicates flow control has been queued
-#define NEED_INLINE  2  // Indicates inline commands or data queued
-#define NEED_BYPASS  4  // Indicates bypass commands queued
-#define NEED_CREDIT  8  // Indicates would be sending except has not sufficient
-						// credit. The data is still in the channel structure,
-						// but the channel is not enqueued in the board
-						// structure again until there is a credit received from
-						// the board.
-
-// dataSetIn (Also the bits for i2GetStatus return value)
-//
-#define I2_DCD 1
-#define I2_CTS 2
-#define I2_DSR 4
-#define I2_RI  8
-
-// dataSetOut (Also the bits for i2GetStatus return value)
-//
-#define I2_DTR 1
-#define I2_RTS 2
-
-// i2GetStatus() can optionally clear these bits
-//
-#define I2_BRK    0x10  // A break was detected
-#define I2_PAR    0x20  // A parity error was received 
-#define I2_FRA    0x40  // A framing error was received
-#define I2_OVR    0x80  // An overrun error was received 
-
-// i2GetStatus() automatically clears these bits */
-//
-#define I2_DDCD   0x100 // DCD changed from its  former value
-#define I2_DCTS   0x200 // CTS changed from its former value 
-#define I2_DDSR   0x400 // DSR changed from its former value 
-#define I2_DRI    0x800 // RI changed from its former value 
-
-// hotKeyIn
-//
-#define HOT_CLEAR 0x1322   // Indicates that no hot-key has been detected
-
-// channelOptions
-//
-#define CO_NBLOCK_WRITE 1  	// Writes don't block waiting for buffer. (Default
-							// is, they do wait.)
-
-// fcmodes
-//
-#define I2_OUTFLOW_CTS  0x0001
-#define I2_INFLOW_RTS   0x0002
-#define I2_INFLOW_DSR   0x0004
-#define I2_INFLOW_DTR   0x0008
-#define I2_OUTFLOW_DSR  0x0010
-#define I2_OUTFLOW_DTR  0x0020
-#define I2_OUTFLOW_XON  0x0040
-#define I2_OUTFLOW_XANY 0x0080
-#define I2_INFLOW_XON   0x0100
-
-#define I2_CRTSCTS      (I2_OUTFLOW_CTS|I2_INFLOW_RTS)
-#define I2_IXANY_MODE   (I2_OUTFLOW_XON|I2_OUTFLOW_XANY)
-
-//-------------------------------------------
-// Macros used from user level like functions
-//-------------------------------------------
-
-// Macros to set and clear channel options
-//
-#define i2SetOption(pCh, option) pCh->channelOptions |= option
-#define i2ClrOption(pCh, option) pCh->channelOptions &= ~option
-
-// Macro to set fatal-error trap
-//
-#define i2SetFatalTrap(pB, routine) pB->i2eFatalTrap = routine
-
-//--------------------------------------------
-// Declarations and prototypes for i2lib.c
-//--------------------------------------------
-//
-static int  i2InitChannels(i2eBordStrPtr, int, i2ChanStrPtr);
-static int  i2QueueCommands(int, i2ChanStrPtr, int, int, cmdSyntaxPtr,...);
-static int  i2GetStatus(i2ChanStrPtr, int);
-static int  i2Input(i2ChanStrPtr);
-static int  i2InputFlush(i2ChanStrPtr);
-static int  i2Output(i2ChanStrPtr, const char *, int);
-static int  i2OutputFree(i2ChanStrPtr);
-static int  i2ServiceBoard(i2eBordStrPtr);
-static void i2DrainOutput(i2ChanStrPtr, int);
-
-#ifdef IP2DEBUG_TRACE
-void ip2trace(unsigned short,unsigned char,unsigned char,unsigned long,...);
-#else
-#define ip2trace(a,b,c,d...) do {} while (0)
-#endif
-
-// Argument to i2QueueCommands
-//
-#define C_IN_LINE 1
-#define C_BYPASS  0
-
-#endif   // I2LIB_H
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/i2pack.h linux-libre-2.6.39-gnu/drivers/char/ip2/i2pack.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/i2pack.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/i2pack.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,364 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Definitions of the packets used to transfer data and commands
-*                Host <--> Board. Information provided here is only applicable
-*                when the standard loadware is active.
-*
-*******************************************************************************/
-#ifndef I2PACK_H
-#define I2PACK_H  1
-
-//-----------------------------------------------
-// Revision History:
-//
-// 10 October 1991   MAG First draft
-// 24 February 1992  MAG Additions for 1.4.x loadware
-// 11 March 1992     MAG New status packets
-//
-//-----------------------------------------------
-
-//------------------------------------------------------------------------------
-// Packet Formats:
-//
-// Information passes between the host and board through the FIFO in packets.
-// These have headers which indicate the type of packet. Because the fifo data
-// path may be 16-bits wide, the protocol is constrained such that each packet
-// is always padded to an even byte count. (The lower-level interface routines
-// -- i2ellis.c -- are designed to do this).
-//
-// The sender (be it host or board) must place some number of complete packets
-// in the fifo, then place a message in the mailbox that packets are available.
-// Placing such a message interrupts the "receiver" (be it board or host), who
-// reads the mailbox message and determines that there are incoming packets
-// ready. Since there are no partial packets, and the length of a packet is
-// given in the header, the remainder of the packet can be read without checking
-// for FIFO empty condition. The process is repeated, packet by packet, until
-// the incoming FIFO is empty. Then the receiver uses the outbound mailbox to
-// signal the board that it has read the data. Only then can the sender place
-// additional data in the fifo.
-//------------------------------------------------------------------------------
-//
-//------------------------------------------------
-// Definition of Packet Header Area
-//------------------------------------------------
-//
-// Caution: these only define header areas. In actual use the data runs off
-// beyond the end of these structures.
-//
-// Since these structures are based on sequences of bytes which go to the board,
-// there cannot be ANY padding between the elements.
-#pragma pack(1)
-
-//----------------------------
-// DATA PACKETS
-//----------------------------
-
-typedef struct _i2DataHeader
-{
-	unsigned char i2sChannel;  /* The channel number: 0-255 */
-
-	// -- Bitfields are allocated LSB first --
-
-	// For incoming data, indicates whether this is an ordinary packet or a
-	// special one (e.g., hot key hit).
-	unsigned i2sId : 2 __attribute__ ((__packed__));
-
-	// For tagging data packets. There are flush commands which flush only data
-	// packets bearing a particular tag. (used in implementing IntelliView and
-	// IntelliPrint). THE TAG VALUE 0xf is RESERVED and must not be used (it has
-	// meaning internally to the loadware).
-	unsigned i2sTag : 4;
-
-	// These two bits determine the type of packet sent/received.
-	unsigned i2sType : 2;
-
-	// The count of data to follow: does not include the possible additional
-	// padding byte. MAXIMUM COUNT: 4094. The top four bits must be 0.
-	unsigned short i2sCount;
-
-} i2DataHeader, *i2DataHeaderPtr;
-
-// Structure is immediately followed by the data, proper.
-
-//----------------------------
-// NON-DATA PACKETS
-//----------------------------
-
-typedef struct _i2CmdHeader
-{
-	unsigned char i2sChannel;	// The channel number: 0-255 (Except where noted
-								// - see below
-
-	// Number of bytes of commands, status or whatever to follow
-	unsigned i2sCount : 6;
-
-	// These two bits determine the type of packet sent/received.
-	unsigned i2sType : 2;
-
-} i2CmdHeader, *i2CmdHeaderPtr;
-
-// Structure is immediately followed by the applicable data.
-
-//---------------------------------------
-// Flow Control Packets (Outbound)
-//---------------------------------------
-
-// One type of outbound command packet is so important that the entire structure
-// is explicitly defined here. That is the flow-control packet. This is never
-// sent by user-level code (as would be the commands to raise/lower DTR, for
-// example). These are only sent by the library routines in response to reading
-// incoming data into the buffers.
-//
-// The parameters inside the command block are maintained in place, then the
-// block is sent at the appropriate time.
-
-typedef struct _flowIn
-{
-	i2CmdHeader    hd;      // Channel #, count, type (see above)
-	unsigned char  fcmd;    // The flow control command (37)
-	unsigned short asof;    // As of byte number "asof" (LSB first!) I have room
-							// for "room" bytes
-	unsigned short room;
-} flowIn, *flowInPtr;
-
-//----------------------------------------
-// (Incoming) Status Packets
-//----------------------------------------
-
-// Incoming packets which are non-data packets are status packets. In this case,
-// the channel number in the header is unimportant. What follows are one or more
-// sub-packets, the first word of which consists of the channel (first or low
-// byte) and the status indicator (second or high byte), followed by possibly
-// more data.
-
-#define STAT_CTS_UP     0  /* CTS raised  (no other bytes) */
-#define STAT_CTS_DN     1  /* CTS dropped (no other bytes) */
-#define STAT_DCD_UP     2  /* DCD raised  (no other bytes) */
-#define STAT_DCD_DN     3  /* DCD dropped (no other bytes) */
-#define STAT_DSR_UP     4  /* DSR raised  (no other bytes) */
-#define STAT_DSR_DN     5  /* DSR dropped (no other bytes) */
-#define STAT_RI_UP      6  /* RI  raised  (no other bytes) */
-#define STAT_RI_DN      7  /* RI  dropped (no other bytes) */
-#define STAT_BRK_DET    8  /* BRK detect  (no other bytes) */
-#define STAT_FLOW       9  /* Flow control(-- more: see below */
-#define STAT_BMARK      10 /* Bookmark    (no other bytes)
-							* Bookmark is sent as a response to
-							* a command 60: request for bookmark
-							*/
-#define STAT_STATUS     11 /* Special packet: see below */
-#define STAT_TXCNT      12 /* Special packet: see below */
-#define STAT_RXCNT      13 /* Special packet: see below */
-#define STAT_BOXIDS     14 /* Special packet: see below */
-#define STAT_HWFAIL     15 /* Special packet: see below */
-
-#define STAT_MOD_ERROR  0xc0
-#define STAT_MODEM      0xc0/* If status & STAT_MOD_ERROR:
-							 * == STAT_MODEM, then this is a modem
-							 * status packet, given in response to a
-							 * CMD_DSS_NOW command.
-							 * The low nibble has each data signal:
-							 */
-#define STAT_MOD_DCD    0x8
-#define STAT_MOD_RI     0x4
-#define STAT_MOD_DSR    0x2
-#define STAT_MOD_CTS    0x1
-
-#define STAT_ERROR      0x80/* If status & STAT_MOD_ERROR
-							 * == STAT_ERROR, then
-							 * sort of error on the channel.
-							 * The remaining seven bits indicate
-							 * what sort of error it is.
-							 */
-/* The low three bits indicate parity, framing, or overrun errors */
-
-#define STAT_E_PARITY   4     /* Parity error */
-#define STAT_E_FRAMING  2     /* Framing error */
-#define STAT_E_OVERRUN  1     /* (uxart) overrun error */
-
-//---------------------------------------
-// STAT_FLOW packets
-//---------------------------------------
-
-typedef struct _flowStat
-{
-	unsigned short asof;
-	unsigned short room;
-}flowStat, *flowStatPtr;
-
-// flowStat packets are received from the board to regulate the flow of outgoing
-// data. A local copy of this structure is also kept to track the amount of
-// credits used and credits remaining. "room" is the amount of space in the
-// board's buffers, "as of" having received a certain byte number. When sending
-// data to the fifo, you must calculate how much buffer space your packet will
-// use.  Add this to the current "asof" and subtract it from the current "room".
-//
-// The calculation for the board's buffer is given by CREDIT_USAGE, where size
-// is the un-rounded count of either data characters or command characters.
-// (Which is to say, the count rounded up, plus two).
-
-#define CREDIT_USAGE(size) (((size) + 3) & ~1)
-
-//---------------------------------------
-// STAT_STATUS packets
-//---------------------------------------
-
-typedef  struct   _debugStat
-{
-	unsigned char d_ccsr;
-	unsigned char d_txinh;
-	unsigned char d_stat1;
-	unsigned char d_stat2;
-} debugStat, *debugStatPtr;
-
-// debugStat packets are sent to the host in response to a CMD_GET_STATUS
-// command.  Each byte is bit-mapped as described below:
-
-#define D_CCSR_XON      2     /* Has received XON, ready to transmit */
-#define D_CCSR_XOFF     4     /* Has received XOFF, not transmitting */
-#define D_CCSR_TXENAB   8     /* Transmitter is enabled */
-#define D_CCSR_RXENAB   0x80  /* Receiver is enabled */
-
-#define D_TXINH_BREAK   1     /* We are sending a break */
-#define D_TXINH_EMPTY   2     /* No data to send */
-#define D_TXINH_SUSP    4     /* Output suspended via command 57 */
-#define D_TXINH_CMD     8     /* We are processing an in-line command */
-#define D_TXINH_LCD     0x10  /* LCD diagnostics are running */
-#define D_TXINH_PAUSE   0x20  /* We are processing a PAUSE command */
-#define D_TXINH_DCD     0x40  /* DCD is low, preventing transmission */
-#define D_TXINH_DSR     0x80  /* DSR is low, preventing transmission */
-
-#define D_STAT1_TXEN    1     /* Transmit INTERRUPTS enabled */
-#define D_STAT1_RXEN    2     /* Receiver INTERRUPTS enabled */
-#define D_STAT1_MDEN    4     /* Modem (data set sigs) interrupts enabled */
-#define D_STAT1_RLM     8     /* Remote loopback mode selected */
-#define D_STAT1_LLM     0x10  /* Local internal loopback mode selected */
-#define D_STAT1_CTS     0x20  /* CTS is low, preventing transmission */
-#define D_STAT1_DTR     0x40  /* DTR is low, to stop remote transmission */
-#define D_STAT1_RTS     0x80  /* RTS is low, to stop remote transmission */
-
-#define D_STAT2_TXMT    1     /* Transmit buffers are all empty */
-#define D_STAT2_RXMT    2     /* Receive buffers are all empty */
-#define D_STAT2_RXINH   4     /* Loadware has tried to inhibit remote
-							   * transmission:  dropped DTR, sent XOFF,
-							   * whatever...
-							   */
-#define D_STAT2_RXFLO   8     /* Loadware can send no more data to host
-							   * until it receives a flow-control packet
-							   */
-//-----------------------------------------
-// STAT_TXCNT and STAT_RXCNT packets
-//----------------------------------------
-
-typedef  struct   _cntStat
-{
-	unsigned short cs_time;    // (Assumes host is little-endian!)
-	unsigned short cs_count;
-} cntStat, *cntStatPtr;
-
-// These packets are sent in response to a CMD_GET_RXCNT or a CMD_GET_TXCNT
-// bypass command. cs_time is a running 1 Millisecond counter which acts as a
-// time stamp. cs_count is a running counter of data sent or received from the
-// uxarts. (Not including data added by the chip itself, as with CRLF
-// processing).
-//------------------------------------------
-// STAT_HWFAIL packets
-//------------------------------------------
-
-typedef struct _failStat
-{
-	unsigned char fs_written;
-	unsigned char fs_read;
-	unsigned short fs_address;
-} failStat, *failStatPtr;
-
-// This packet is sent whenever the on-board diagnostic process detects an
-// error. At startup, this process is dormant. The host can wake it up by
-// issuing the bypass command CMD_HW_TEST. The process runs at low priority and
-// performs continuous hardware verification; writing data to certain on-board
-// registers, reading it back, and comparing. If it detects an error, this
-// packet is sent to the host, and the process goes dormant again until the host
-// sends another CMD_HW_TEST. It then continues with the next register to be
-// tested.
-
-//------------------------------------------------------------------------------
-// Macros to deal with the headers more easily! Note that these are defined so
-// they may be used as "left" as well as "right" expressions.
-//------------------------------------------------------------------------------
-
-// Given a pointer to the packet, reference the channel number
-//
-#define CHANNEL_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sChannel
-
-// Given a pointer to the packet, reference the Packet type
-//
-#define PTYPE_OF(pP) ((i2DataHeaderPtr)(pP))->i2sType
-
-// The possible types of packets
-//
-#define PTYPE_DATA   0  /* Host <--> Board */
-#define PTYPE_BYPASS 1  /* Host ---> Board */
-#define PTYPE_INLINE 2  /* Host ---> Board */
-#define PTYPE_STATUS 2  /* Host <--- Board */
-
-// Given a pointer to a Data packet, reference the Tag
-//
-#define TAG_OF(pP) ((i2DataHeaderPtr)(pP))->i2sTag
-
-// Given a pointer to a Data packet, reference the data i.d.
-//
-#define ID_OF(pP)  ((i2DataHeaderPtr)(pP))->i2sId
-
-// The possible types of ID's
-//
-#define ID_ORDINARY_DATA   0
-#define ID_HOT_KEY         1
-
-// Given a pointer to a Data packet, reference the count
-//
-#define DATA_COUNT_OF(pP) ((i2DataHeaderPtr)(pP))->i2sCount
-
-// Given a pointer to a Data packet, reference the beginning of data
-//
-#define DATA_OF(pP) &((unsigned char *)(pP))[4] // 4 = size of header
-
-// Given a pointer to a Non-Data packet, reference the count
-//
-#define CMD_COUNT_OF(pP) ((i2CmdHeaderPtr)(pP))->i2sCount
-
-#define MAX_CMD_PACK_SIZE  62 // Maximum size of such a count
-
-// Given a pointer to a Non-Data packet, reference the beginning of data
-//
-#define CMD_OF(pP) &((unsigned char *)(pP))[2]  // 2 = size of header
-
-//--------------------------------
-// MailBox Bits:
-//--------------------------------
-
-//--------------------------
-// Outgoing (host to board)
-//--------------------------
-//
-#define MB_OUT_STUFFED     0x80  // Host has placed output in fifo 
-#define MB_IN_STRIPPED     0x40  // Host has read in all input from fifo 
-
-//--------------------------
-// Incoming (board to host)
-//--------------------------
-//
-#define MB_IN_STUFFED      0x80  // Board has placed input in fifo 
-#define MB_OUT_STRIPPED    0x40  // Board has read all output from fifo 
-#define MB_FATAL_ERROR     0x20  // Board has encountered a fatal error
-
-#pragma pack()                  // Reset padding to command-line default
-
-#endif      // I2PACK_H
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/ip2.h linux-libre-2.6.39-gnu/drivers/char/ip2/ip2.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/ip2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/ip2.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants for configuration and tuning
-*
-*   NOTES:
-*
-*******************************************************************************/
-#ifndef IP2_H
-#define IP2_H
-
-#include "ip2types.h"
-#include "i2cmd.h"
-
-/*************/
-/* Constants */
-/*************/
-
-/* Device major numbers - since version 2.0.26. */
-#define IP2_TTY_MAJOR      71
-#define IP2_CALLOUT_MAJOR  72
-#define IP2_IPL_MAJOR      73
-
-/* Board configuration array.
- * This array defines the hardware irq and address for up to IP2_MAX_BOARDS
- * (4 supported per ip2_types.h) ISA board addresses and irqs MUST be specified,
- * PCI and EISA boards are probed for and automagicly configed
- * iff the addresses are set to 1 and 2 respectivily.
- *    0x0100 - 0x03f0 == ISA
- *	         1        == PCI
- *	         2        == EISA
- *	         0        == (skip this board)
- * This array defines the hardware addresses for them. Special 
- * addresses are EISA and PCI which go sniffing for boards. 
-
- * In a multiboard system the position in the array determines which port
- * devices are assigned to each board: 
- *		board 0 is assigned ttyF0.. to ttyF63, 
- *		board 1 is assigned ttyF64  to ttyF127,
- *		board 2 is assigned ttyF128 to ttyF191,
- *		board 3 is assigned ttyF192 to ttyF255. 
- *
- * In PCI and EISA bus systems each range is mapped to card in 
- * monotonically increasing slot number order, ISA position is as specified
- * here.
-
- * If the irqs are ALL set to 0,0,0,0 all boards operate in 
- * polled mode. For interrupt operation ISA boards require that the IRQ be 
- * specified, while PCI and EISA boards any nonzero entry 
- * will enable interrupts using the BIOS configured irq for the board. 
- * An invalid irq entry will default to polled mode for that card and print
- * console warning.
- 
- * When the driver is loaded as a module these setting can be overridden on the 
- * modprobe command line or on an option line in /etc/modprobe.conf.
- * If the driver is built-in the configuration must be 
- * set here for ISA cards and address set to 1 and 2 for PCI and EISA.
- *
- * Here is an example that shows most if not all possibe combinations:
-
- *static ip2config_t ip2config =
- *{
- *	{11,1,0,0},		// irqs
- *	{				// Addresses
- *		0x0308,		// Board 0, ttyF0   - ttyF63// ISA card at io=0x308, irq=11
- *		0x0001,		// Board 1, ttyF64  - ttyF127//PCI card configured by BIOS
- *		0x0000,		// Board 2, ttyF128 - ttyF191// Slot skipped
- *		0x0002		// Board 3, ttyF192 - ttyF255//EISA card configured by BIOS
- *												 // but polled not irq driven
- *	}
- *};
- */
-
- /* this structure is zeroed out because the suggested method is to configure
-  * the driver as a module, set up the parameters with an options line in
-  * /etc/modprobe.conf and load with modprobe or kmod, the kernel
-  * module loader
-  */
-
- /* This structure is NOW always initialized when the driver is initialized.
-  * Compiled in defaults MUST be added to the io and irq arrays in
-  * ip2.c.  Those values are configurable from insmod parameters in the
-  * case of modules or from command line parameters (ip2=io,irq) when
-  * compiled in.
-  */
-
-static ip2config_t ip2config =
-{
-	{0,0,0,0},		// irqs
-	{				// Addresses
-	/* Do NOT set compile time defaults HERE!  Use the arrays in
-		ip2.c!  These WILL be overwritten!  =mhw= */
-		0x0000,		// Board 0, ttyF0   - ttyF63
-		0x0000,		// Board 1, ttyF64  - ttyF127
-		0x0000,		// Board 2, ttyF128 - ttyF191
-		0x0000		// Board 3, ttyF192 - ttyF255
-	}
-};
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/ip2ioctl.h linux-libre-2.6.39-gnu/drivers/char/ip2/ip2ioctl.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/ip2ioctl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/ip2ioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,35 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants for configuration and tuning
-*
-*   NOTES:
-*
-*******************************************************************************/
-
-#ifndef IP2IOCTL_H
-#define IP2IOCTL_H
-
-//*************
-//* Constants *
-//*************
-
-// High baud rates (if not defined elsewhere.
-#ifndef B153600   
-#	define B153600   0010005
-#endif
-#ifndef B307200   
-#	define B307200   0010006
-#endif
-#ifndef B921600   
-#	define B921600   0010007
-#endif
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/ip2main.c linux-libre-2.6.39-gnu/drivers/char/ip2/ip2main.c
--- linux-libre-2.6.38-gnu/drivers/char/ip2/ip2main.c	2012-03-24 00:59:55.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/ip2main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3234 +0,0 @@
-/*
-*
-*   (c) 1999 by Computone Corporation
-*
-********************************************************************************
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Mainline code for the device driver
-*
-*******************************************************************************/
-// ToDo:
-//
-// Fix the immediate DSS_NOW problem.
-// Work over the channel stats return logic in ip2_ipl_ioctl so they
-//	make sense for all 256 possible channels and so the user space
-//	utilities will compile and work properly.
-//
-// Done:
-//
-// 1.2.14	/\/\|=mhw=|\/\/
-// Added bounds checking to ip2_ipl_ioctl to avoid potential terroristic acts.
-// Changed the definition of ip2trace to be more consistent with kernel style
-//	Thanks to Andreas Dilger <adilger@turbolabs.com> for these updates
-//
-// 1.2.13	/\/\|=mhw=|\/\/
-// DEVFS: Renamed ttf/{n} to tts/F{n} and cuf/{n} to cua/F{n} to conform
-//	to agreed devfs serial device naming convention.
-//
-// 1.2.12	/\/\|=mhw=|\/\/
-// Cleaned up some remove queue cut and paste errors
-//
-// 1.2.11	/\/\|=mhw=|\/\/
-// Clean up potential NULL pointer dereferences
-// Clean up devfs registration
-// Add kernel command line parsing for io and irq
-//	Compile defaults for io and irq are now set in ip2.c not ip2.h!
-// Reworked poll_only hack for explicit parameter setting
-//	You must now EXPLICITLY set poll_only = 1 or set all irqs to 0
-// Merged ip2_loadmain and old_ip2_init
-// Converted all instances of interruptible_sleep_on into queue calls
-//	Most of these had no race conditions but better to clean up now
-//
-// 1.2.10	/\/\|=mhw=|\/\/
-// Fixed the bottom half interrupt handler and enabled USE_IQI
-//	to split the interrupt handler into a formal top-half / bottom-half
-// Fixed timing window on high speed processors that queued messages to
-// 	the outbound mail fifo faster than the board could handle.
-//
-// 1.2.9
-// Four box EX was barfing on >128k kmalloc, made structure smaller by
-// reducing output buffer size
-//
-// 1.2.8
-// Device file system support (MHW)
-//
-// 1.2.7 
-// Fixed
-// Reload of ip2 without unloading ip2main hangs system on cat of /proc/modules
-//
-// 1.2.6
-//Fixes DCD problems
-//	DCD was not reported when CLOCAL was set on call to TIOCMGET
-//
-//Enhancements:
-//	TIOCMGET requests and waits for status return
-//	No DSS interrupts enabled except for DCD when needed
-//
-// For internal use only
-//
-//#define IP2DEBUG_INIT
-//#define IP2DEBUG_OPEN
-//#define IP2DEBUG_WRITE
-//#define IP2DEBUG_READ
-//#define IP2DEBUG_IOCTL
-//#define IP2DEBUG_IPL
-
-//#define IP2DEBUG_TRACE
-//#define DEBUG_FIFO
-
-/************/
-/* Includes */
-/************/
-
-#include <linux/ctype.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/major.h>
-#include <linux/wait.h>
-#include <linux/device.h>
-#include <linux/mutex.h>
-#include <linux/firmware.h>
-#include <linux/platform_device.h>
-
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/termios.h>
-#include <linux/tty_driver.h>
-#include <linux/serial.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-
-#include <linux/cdk.h>
-#include <linux/comstats.h>
-#include <linux/delay.h>
-#include <linux/bitops.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-
-#include <asm/uaccess.h>
-
-#include "ip2types.h"
-#include "ip2trace.h"
-#include "ip2ioctl.h"
-#include "ip2.h"
-#include "i2ellis.h"
-#include "i2lib.h"
-
-/*****************
- * /proc/ip2mem  *
- *****************/
-
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
-
-static DEFINE_MUTEX(ip2_mutex);
-static const struct file_operations ip2mem_proc_fops;
-static const struct file_operations ip2_proc_fops;
-
-/********************/
-/* Type Definitions */
-/********************/
-
-/*************/
-/* Constants */
-/*************/
-
-/* String constants to identify ourselves */
-static const char pcName[] = "Computone IntelliPort Plus multiport driver";
-static const char pcVersion[] = "1.2.14";
-
-/* String constants for port names */
-static const char pcDriver_name[] = "ip2";
-static const char pcIpl[] = "ip2ipl";
-
-/***********************/
-/* Function Prototypes */
-/***********************/
-
-/* Global module entry functions */
-
-/* Private (static) functions */
-static int  ip2_open(PTTY, struct file *);
-static void ip2_close(PTTY, struct file *);
-static int  ip2_write(PTTY, const unsigned char *, int);
-static int  ip2_putchar(PTTY, unsigned char);
-static void ip2_flush_chars(PTTY);
-static int  ip2_write_room(PTTY);
-static int  ip2_chars_in_buf(PTTY);
-static void ip2_flush_buffer(PTTY);
-static int  ip2_ioctl(PTTY, struct file *, UINT, ULONG);
-static void ip2_set_termios(PTTY, struct ktermios *);
-static void ip2_set_line_discipline(PTTY);
-static void ip2_throttle(PTTY);
-static void ip2_unthrottle(PTTY);
-static void ip2_stop(PTTY);
-static void ip2_start(PTTY);
-static void ip2_hangup(PTTY);
-static int  ip2_tiocmget(struct tty_struct *tty, struct file *file);
-static int  ip2_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear);
-static int ip2_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount);
-
-static void set_irq(int, int);
-static void ip2_interrupt_bh(struct work_struct *work);
-static irqreturn_t ip2_interrupt(int irq, void *dev_id);
-static void ip2_poll(unsigned long arg);
-static inline void service_all_boards(void);
-static void do_input(struct work_struct *);
-static void do_status(struct work_struct *);
-
-static void ip2_wait_until_sent(PTTY,int);
-
-static void set_params (i2ChanStrPtr, struct ktermios *);
-static int get_serial_info(i2ChanStrPtr, struct serial_struct __user *);
-static int set_serial_info(i2ChanStrPtr, struct serial_struct __user *);
-
-static ssize_t ip2_ipl_read(struct file *, char __user *, size_t, loff_t *);
-static ssize_t ip2_ipl_write(struct file *, const char __user *, size_t, loff_t *);
-static long ip2_ipl_ioctl(struct file *, UINT, ULONG);
-static int ip2_ipl_open(struct inode *, struct file *);
-
-static int DumpTraceBuffer(char __user *, int);
-static int DumpFifoBuffer( char __user *, int);
-
-static void ip2_init_board(int, const struct firmware *);
-static unsigned short find_eisa_board(int);
-static int ip2_setup(char *str);
-
-/***************/
-/* Static Data */
-/***************/
-
-static struct tty_driver *ip2_tty_driver;
-
-/* Here, then is a table of board pointers which the interrupt routine should
- * scan through to determine who it must service.
- */
-static unsigned short i2nBoards; // Number of boards here
-
-static i2eBordStrPtr i2BoardPtrTable[IP2_MAX_BOARDS];
-
-static i2ChanStrPtr  DevTable[IP2_MAX_PORTS];
-//DevTableMem just used to save addresses for kfree
-static void  *DevTableMem[IP2_MAX_BOARDS];
-
-/* This is the driver descriptor for the ip2ipl device, which is used to
- * download the loadware to the boards.
- */
-static const struct file_operations ip2_ipl = {
-	.owner		= THIS_MODULE,
-	.read		= ip2_ipl_read,
-	.write		= ip2_ipl_write,
-	.unlocked_ioctl	= ip2_ipl_ioctl,
-	.open		= ip2_ipl_open,
-	.llseek		= noop_llseek,
-}; 
-
-static unsigned long irq_counter;
-static unsigned long bh_counter;
-
-// Use immediate queue to service interrupts
-#define USE_IQI
-//#define USE_IQ	// PCI&2.2 needs work
-
-/* The timer_list entry for our poll routine. If interrupt operation is not
- * selected, the board is serviced periodically to see if anything needs doing.
- */
-#define  POLL_TIMEOUT   (jiffies + 1)
-static DEFINE_TIMER(PollTimer, ip2_poll, 0, 0);
-
-#ifdef IP2DEBUG_TRACE
-/* Trace (debug) buffer data */
-#define TRACEMAX  1000
-static unsigned long tracebuf[TRACEMAX];
-static int tracestuff;
-static int tracestrip;
-static int tracewrap;
-#endif
-
-/**********/
-/* Macros */
-/**********/
-
-#ifdef IP2DEBUG_OPEN
-#define DBG_CNT(s) printk(KERN_DEBUG "(%s): [%x] ttyc=%d, modc=%x -> %s\n", \
-		    tty->name,(pCh->flags), \
-		    tty->count,/*GET_USE_COUNT(module)*/0,s)
-#else
-#define DBG_CNT(s)
-#endif
-
-/********/
-/* Code */
-/********/
-
-#include "i2ellis.c"    /* Extremely low-level interface services */
-#include "i2cmd.c"      /* Standard loadware command definitions */
-#include "i2lib.c"      /* High level interface services */
-
-/* Configuration area for modprobe */
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-MODULE_LICENSE("GPL");
-
-#define	MAX_CMD_STR	50
-
-static int poll_only;
-static char cmd[MAX_CMD_STR];
-
-static int Eisa_irq;
-static int Eisa_slot;
-
-static int iindx;
-static char rirqs[IP2_MAX_BOARDS];
-static int Valid_Irqs[] = { 3, 4, 5, 7, 10, 11, 12, 15, 0};
-
-/* Note: Add compiled in defaults to these arrays, not to the structure
-	in ip2.h any longer.  That structure WILL get overridden
-	by these values, or command line values, or insmod values!!!  =mhw=
-*/
-static int io[IP2_MAX_BOARDS];
-static int irq[IP2_MAX_BOARDS] = { -1, -1, -1, -1 };
-
-MODULE_AUTHOR("Doug McNash");
-MODULE_DESCRIPTION("Computone IntelliPort Plus Driver");
-module_param_array(irq, int, NULL, 0);
-MODULE_PARM_DESC(irq, "Interrupts for IntelliPort Cards");
-module_param_array(io, int, NULL, 0);
-MODULE_PARM_DESC(io, "I/O ports for IntelliPort Cards");
-module_param(poll_only, bool, 0);
-MODULE_PARM_DESC(poll_only, "Do not use card interrupts");
-module_param_string(ip2, cmd, MAX_CMD_STR, 0);
-MODULE_PARM_DESC(ip2, "Contains module parameter passed with 'ip2='");
-
-/* for sysfs class support */
-static struct class *ip2_class;
-
-/* Some functions to keep track of what irqs we have */
-
-static int __init is_valid_irq(int irq)
-{
-	int *i = Valid_Irqs;
-	
-	while (*i != 0 && *i != irq)
-		i++;
-
-	return *i;
-}
-
-static void __init mark_requested_irq(char irq)
-{
-	rirqs[iindx++] = irq;
-}
-
-static int __exit clear_requested_irq(char irq)
-{
-	int i;
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (rirqs[i] == irq) {
-			rirqs[i] = 0;
-			return 1;
-		}
-	}
-	return 0;
-}
-
-static int have_requested_irq(char irq)
-{
-	/* array init to zeros so 0 irq will not be requested as a side
-	 * effect */
-	int i;
-	for (i = 0; i < IP2_MAX_BOARDS; ++i)
-		if (rirqs[i] == irq)
-			return 1;
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   cleanup_module()                                               */
-/* Parameters: None                                                           */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This is a required entry point for an installable module. It has to return */
-/* the device and the driver to a passive state. It should not be necessary   */
-/* to reset the board fully, especially as the loadware is downloaded         */
-/* externally rather than in the driver. We just want to disable the board    */
-/* and clear the loadware to a reset state. To allow this there has to be a   */
-/* way to detect whether the board has the loadware running at init time to   */
-/* handle subsequent installations of the driver. All memory allocated by the */
-/* driver should be returned since it may be unloaded from memory.            */
-/******************************************************************************/
-static void __exit ip2_cleanup_module(void)
-{
-	int err;
-	int i;
-
-	del_timer_sync(&PollTimer);
-
-	/* Reset the boards we have. */
-	for (i = 0; i < IP2_MAX_BOARDS; i++)
-		if (i2BoardPtrTable[i])
-			iiReset(i2BoardPtrTable[i]);
-
-	/* The following is done at most once, if any boards were installed. */
-	for (i = 0; i < IP2_MAX_BOARDS; i++) {
-		if (i2BoardPtrTable[i]) {
-			iiResetDelay(i2BoardPtrTable[i]);
-			/* free io addresses and Tibet */
-			release_region(ip2config.addr[i], 8);
-			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR, 4 * i));
-			device_destroy(ip2_class, MKDEV(IP2_IPL_MAJOR,
-						4 * i + 1));
-		}
-		/* Disable and remove interrupt handler. */
-		if (ip2config.irq[i] > 0 &&
-				have_requested_irq(ip2config.irq[i])) {
-			free_irq(ip2config.irq[i], (void *)&pcName);
-			clear_requested_irq(ip2config.irq[i]);
-		}
-	}
-	class_destroy(ip2_class);
-	err = tty_unregister_driver(ip2_tty_driver);
-	if (err)
-		printk(KERN_ERR "IP2: failed to unregister tty driver (%d)\n",
-				err);
-	put_tty_driver(ip2_tty_driver);
-	unregister_chrdev(IP2_IPL_MAJOR, pcIpl);
-	remove_proc_entry("ip2mem", NULL);
-
-	/* free memory */
-	for (i = 0; i < IP2_MAX_BOARDS; i++) {
-		void *pB;
-#ifdef CONFIG_PCI
-		if (ip2config.type[i] == PCI && ip2config.pci_dev[i]) {
-			pci_disable_device(ip2config.pci_dev[i]);
-			pci_dev_put(ip2config.pci_dev[i]);
-			ip2config.pci_dev[i] = NULL;
-		}
-#endif
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			kfree(pB);
-			i2BoardPtrTable[i] = NULL;
-		}
-		if (DevTableMem[i] != NULL) {
-			kfree(DevTableMem[i]);
-			DevTableMem[i] = NULL;
-		}
-	}
-}
-module_exit(ip2_cleanup_module);
-
-static const struct tty_operations ip2_ops = {
-	.open            = ip2_open,
-	.close           = ip2_close,
-	.write           = ip2_write,
-	.put_char        = ip2_putchar,
-	.flush_chars     = ip2_flush_chars,
-	.write_room      = ip2_write_room,
-	.chars_in_buffer = ip2_chars_in_buf,
-	.flush_buffer    = ip2_flush_buffer,
-	.ioctl           = ip2_ioctl,
-	.throttle        = ip2_throttle,
-	.unthrottle      = ip2_unthrottle,
-	.set_termios     = ip2_set_termios,
-	.set_ldisc       = ip2_set_line_discipline,
-	.stop            = ip2_stop,
-	.start           = ip2_start,
-	.hangup          = ip2_hangup,
-	.tiocmget	 = ip2_tiocmget,
-	.tiocmset	 = ip2_tiocmset,
-	.get_icount	 = ip2_get_icount,
-	.proc_fops	 = &ip2_proc_fops,
-};
-
-/******************************************************************************/
-/* Function:   ip2_loadmain()                                                 */
-/* Parameters: irq, io from command line of insmod et. al.                    */
-/*		pointer to fip firmware and firmware size for boards	      */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/* This was the required entry point for all drivers (now in ip2.c)           */
-/* It performs all                                                            */
-/* initialisation of the devices and driver structures, and registers itself  */
-/* with the relevant kernel modules.                                          */
-/******************************************************************************/
-/* IRQF_DISABLED - if set blocks all interrupts else only this line */
-/* IRQF_SHARED    - for shared irq PCI or maybe EISA only */
-/* SA_RANDOM   - can be source for cert. random number generators */
-#define IP2_SA_FLAGS	0
-
-
-static const struct firmware *ip2_reject_firmware(void)
-{
-	struct platform_device *pdev;
-	const struct firmware *fw;
-
-	pdev = platform_device_register_simple("ip2", 0, NULL, 0);
-	if (IS_ERR(pdev)) {
-		printk(KERN_ERR "Failed to register platform device for ip2\n");
-		return NULL;
-	}
-	if (reject_firmware(&fw, "/*(DEBLOBBED)*/", &pdev->dev)) {
-		printk(KERN_ERR "Failed to load firmware '/*(DEBLOBBED)*/'\n");
-		fw = NULL;
-	}
-	platform_device_unregister(pdev);
-	return fw;
-}
-
-/******************************************************************************
- *	ip2_setup:
- *		str: kernel command line string
- *
- *	Can't autoprobe the boards so user must specify configuration on
- *	kernel command line.  Sane people build it modular but the others
- *	come here.
- *
- *	Alternating pairs of io,irq for up to 4 boards.
- *		ip2=io0,irq0,io1,irq1,io2,irq2,io3,irq3
- *
- *		io=0 => No board
- *		io=1 => PCI
- *		io=2 => EISA
- *		else => ISA I/O address
- *
- *		irq=0 or invalid for ISA will revert to polling mode
- *
- *		Any value = -1, do not overwrite compiled in value.
- *
- ******************************************************************************/
-static int __init ip2_setup(char *str)
-{
-	int j, ints[10];	/* 4 boards, 2 parameters + 2 */
-	unsigned int i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0, j = 1; i < 4; i++) {
-		if (j > ints[0])
-			break;
-		if (ints[j] >= 0)
-			io[i] = ints[j];
-		j++;
-		if (j > ints[0])
-			break;
-		if (ints[j] >= 0)
-			irq[i] = ints[j];
-		j++;
-	}
-	return 1;
-}
-__setup("ip2=", ip2_setup);
-
-static int __init ip2_loadmain(void)
-{
-	int i, j, box;
-	int err = 0;
-	i2eBordStrPtr pB = NULL;
-	int rc = -1;
-	const struct firmware *fw = NULL;
-	char *str;
-
-	str = cmd;
-
-	if (poll_only) {
-		/* Hard lock the interrupts to zero */
-		irq[0] = irq[1] = irq[2] = irq[3] = poll_only = 0;
-	}
-
-	/* Check module parameter with 'ip2=' has been passed or not */
-	if (!poll_only && (!strncmp(str, "ip2=", 4)))
-		ip2_setup(str);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_ENTER, 0);
-
-	/* process command line arguments to modprobe or
-		insmod i.e. iop & irqp */
-	/* irqp and iop should ALWAYS be specified now...  But we check
-		them individually just to be sure, anyways... */
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		ip2config.addr[i] = io[i];
-		if (irq[i] >= 0)
-			ip2config.irq[i] = irq[i];
-		else
-			ip2config.irq[i] = 0;
-	/* This is a little bit of a hack.  If poll_only=1 on command
-	   line back in ip2.c OR all IRQs on all specified boards are
-	   explicitly set to 0, then drop to poll only mode and override
-	   PCI or EISA interrupts.  This superceeds the old hack of
-	   triggering if all interrupts were zero (like da default).
-	   Still a hack but less prone to random acts of terrorism.
-
-	   What we really should do, now that the IRQ default is set
-	   to -1, is to use 0 as a hard coded, do not probe.
-
-		/\/\|=mhw=|\/\/
-	*/
-		poll_only |= irq[i];
-	}
-	poll_only = !poll_only;
-
-	/* Announce our presence */
-	printk(KERN_INFO "%s version %s\n", pcName, pcVersion);
-
-	ip2_tty_driver = alloc_tty_driver(IP2_MAX_PORTS);
-	if (!ip2_tty_driver)
-		return -ENOMEM;
-
-	/* Initialise all the boards we can find (up to the maximum). */
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		switch (ip2config.addr[i]) {
-		case 0:	/* skip this slot even if card is present */
-			break;
-		default: /* ISA */
-		   /* ISA address must be specified */
-			if (ip2config.addr[i] < 0x100 ||
-					ip2config.addr[i] > 0x3f8) {
-				printk(KERN_ERR "IP2: Bad ISA board %d "
-						"address %x\n", i,
-						ip2config.addr[i]);
-				ip2config.addr[i] = 0;
-				break;
-			}
-			ip2config.type[i] = ISA;
-
-			/* Check for valid irq argument, set for polling if
-			 * invalid */
-			if (ip2config.irq[i] &&
-					!is_valid_irq(ip2config.irq[i])) {
-				printk(KERN_ERR "IP2: Bad IRQ(%d) specified\n",
-						ip2config.irq[i]);
-				/* 0 is polling and is valid in that sense */
-				ip2config.irq[i] = 0;
-			}
-			break;
-		case PCI:
-#ifdef CONFIG_PCI
-		{
-			struct pci_dev *pdev = NULL;
-			u32 addr;
-			int status;
-
-			pdev = pci_get_device(PCI_VENDOR_ID_COMPUTONE,
-					PCI_DEVICE_ID_COMPUTONE_IP2EX, pdev);
-			if (pdev == NULL) {
-				ip2config.addr[i] = 0;
-				printk(KERN_ERR "IP2: PCI board %d not "
-						"found\n", i);
-				break;
-			}
-
-			if (pci_enable_device(pdev)) {
-				dev_err(&pdev->dev, "can't enable device\n");
-				goto out;
-			}
-			ip2config.type[i] = PCI;
-			ip2config.pci_dev[i] = pci_dev_get(pdev);
-			status = pci_read_config_dword(pdev, PCI_BASE_ADDRESS_1,
-					&addr);
-			if (addr & 1)
-				ip2config.addr[i] = (USHORT)(addr & 0xfffe);
-			else
-				dev_err(&pdev->dev, "I/O address error\n");
-
-			ip2config.irq[i] = pdev->irq;
-out:
-			pci_dev_put(pdev);
-		}
-#else
-			printk(KERN_ERR "IP2: PCI card specified but PCI "
-					"support not enabled.\n");
-			printk(KERN_ERR "IP2: Recompile kernel with CONFIG_PCI "
-					"defined!\n");
-#endif /* CONFIG_PCI */
-			break;
-		case EISA:
-			ip2config.addr[i] = find_eisa_board(Eisa_slot + 1);
-			if (ip2config.addr[i] != 0) {
-				/* Eisa_irq set as side effect, boo */
-				ip2config.type[i] = EISA;
-			} 
-			ip2config.irq[i] = Eisa_irq;
-			break;
-		}	/* switch */
-	}	/* for */
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (ip2config.addr[i]) {
-			pB = kzalloc(sizeof(i2eBordStr), GFP_KERNEL);
-			if (pB) {
-				i2BoardPtrTable[i] = pB;
-				iiSetAddress(pB, ip2config.addr[i],
-						ii2DelayTimer);
-				iiReset(pB);
-			} else
-				printk(KERN_ERR "IP2: board memory allocation "
-						"error\n");
-		}
-	}
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			iiResetDelay(pB);
-			break;
-		}
-	}
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		/* We don't want to request the firmware unless we have at
-		   least one board */
-		if (i2BoardPtrTable[i] != NULL) {
-			if (!fw)
-				fw = ip2_reject_firmware();
-			if (!fw)
-				break;
-			ip2_init_board(i, fw);
-		}
-	}
-	if (fw)
-		release_firmware(fw);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 2, 0);
-
-	ip2_tty_driver->owner		    = THIS_MODULE;
-	ip2_tty_driver->name                 = "ttyF";
-	ip2_tty_driver->driver_name          = pcDriver_name;
-	ip2_tty_driver->major                = IP2_TTY_MAJOR;
-	ip2_tty_driver->minor_start          = 0;
-	ip2_tty_driver->type                 = TTY_DRIVER_TYPE_SERIAL;
-	ip2_tty_driver->subtype              = SERIAL_TYPE_NORMAL;
-	ip2_tty_driver->init_termios         = tty_std_termios;
-	ip2_tty_driver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-	ip2_tty_driver->flags                = TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(ip2_tty_driver, &ip2_ops);
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 3, 0);
-
-	err = tty_register_driver(ip2_tty_driver);
-	if (err) {
-		printk(KERN_ERR "IP2: failed to register tty driver\n");
-		put_tty_driver(ip2_tty_driver);
-		return err; /* leaking resources */
-	}
-
-	err = register_chrdev(IP2_IPL_MAJOR, pcIpl, &ip2_ipl);
-	if (err) {
-		printk(KERN_ERR "IP2: failed to register IPL device (%d)\n",
-				err);
-	} else {
-		/* create the sysfs class */
-		ip2_class = class_create(THIS_MODULE, "ip2");
-		if (IS_ERR(ip2_class)) {
-			err = PTR_ERR(ip2_class);
-			goto out_chrdev;	
-		}
-	}
-	/* Register the read_procmem thing */
-	if (!proc_create("ip2mem",0,NULL,&ip2mem_proc_fops)) {
-		printk(KERN_ERR "IP2: failed to register read_procmem\n");
-		return -EIO; /* leaking resources */
-	}
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, 4, 0);
-	/* Register the interrupt handler or poll handler, depending upon the
-	 * specified interrupt.
-	 */
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (ip2config.addr[i] == 0)
-			continue;
-
-		pB = i2BoardPtrTable[i];
-		if (pB != NULL) {
-			device_create(ip2_class, NULL,
-				      MKDEV(IP2_IPL_MAJOR, 4 * i),
-				      NULL, "ipl%d", i);
-			device_create(ip2_class, NULL,
-				      MKDEV(IP2_IPL_MAJOR, 4 * i + 1),
-				      NULL, "stat%d", i);
-
-			for (box = 0; box < ABS_MAX_BOXES; box++)
-				for (j = 0; j < ABS_BIGGEST_BOX; j++)
-					if (pB->i2eChannelMap[box] & (1 << j))
-						tty_register_device(
-							ip2_tty_driver,
-							j + ABS_BIGGEST_BOX *
-							(box+i*ABS_MAX_BOXES),
-							NULL);
-		}
-
-		if (poll_only) {
-			/* Poll only forces driver to only use polling and
-			   to ignore the probed PCI or EISA interrupts. */
-			ip2config.irq[i] = CIR_POLL;
-		}
-		if (ip2config.irq[i] == CIR_POLL) {
-retry:
-			if (!timer_pending(&PollTimer)) {
-				mod_timer(&PollTimer, POLL_TIMEOUT);
-				printk(KERN_INFO "IP2: polling\n");
-			}
-		} else {
-			if (have_requested_irq(ip2config.irq[i]))
-				continue;
-			rc = request_irq(ip2config.irq[i], ip2_interrupt,
-				IP2_SA_FLAGS |
-				(ip2config.type[i] == PCI ? IRQF_SHARED : 0),
-				pcName, i2BoardPtrTable[i]);
-			if (rc) {
-				printk(KERN_ERR "IP2: request_irq failed: "
-						"error %d\n", rc);
-				ip2config.irq[i] = CIR_POLL;
-				printk(KERN_INFO "IP2: Polling %ld/sec.\n",
-						(POLL_TIMEOUT - jiffies));
-				goto retry;
-			}
-			mark_requested_irq(ip2config.irq[i]);
-			/* Initialise the interrupt handler bottom half
-			 * (aka slih). */
-		}
-	}
-
-	for (i = 0; i < IP2_MAX_BOARDS; ++i) {
-		if (i2BoardPtrTable[i]) {
-			/* set and enable board interrupt */
-			set_irq(i, ip2config.irq[i]);
-		}
-	}
-
-	ip2trace(ITRC_NO_PORT, ITRC_INIT, ITRC_RETURN, 0);
-
-	return 0;
-
-out_chrdev:
-	unregister_chrdev(IP2_IPL_MAJOR, "ip2");
-	/* unregister and put tty here */
-	return err;
-}
-module_init(ip2_loadmain);
-
-/******************************************************************************/
-/* Function:   ip2_init_board()                                               */
-/* Parameters: Index of board in configuration structure                      */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/* This function initializes the specified board. The loadware is copied to   */
-/* the board, the channel structures are initialized, and the board details   */
-/* are reported on the console.                                               */
-/******************************************************************************/
-static void
-ip2_init_board(int boardnum, const struct firmware *fw)
-{
-	int i;
-	int nports = 0, nboxes = 0;
-	i2ChanStrPtr pCh;
-	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
-
-	if ( !iiInitialize ( pB ) ) {
-		printk ( KERN_ERR "IP2: Failed to initialize board at 0x%x, error %d\n",
-			 pB->i2eBase, pB->i2eError );
-		goto err_initialize;
-	}
-	printk(KERN_INFO "IP2: Board %d: addr=0x%x irq=%d\n", boardnum + 1,
-	       ip2config.addr[boardnum], ip2config.irq[boardnum] );
-
-	if (!request_region( ip2config.addr[boardnum], 8, pcName )) {
-		printk(KERN_ERR "IP2: bad addr=0x%x\n", ip2config.addr[boardnum]);
-		goto err_initialize;
-	}
-
-	if ( iiDownloadAll ( pB, (loadHdrStrPtr)fw->data, 1, fw->size )
-	    != II_DOWN_GOOD ) {
-		printk ( KERN_ERR "IP2: failed to download loadware\n" );
-		goto err_release_region;
-	} else {
-		printk ( KERN_INFO "IP2: fv=%d.%d.%d lv=%d.%d.%d\n",
-			 pB->i2ePom.e.porVersion,
-			 pB->i2ePom.e.porRevision,
-			 pB->i2ePom.e.porSubRev, pB->i2eLVersion,
-			 pB->i2eLRevision, pB->i2eLSub );
-	}
-
-	switch ( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) {
-
-	default:
-		printk( KERN_ERR "IP2: Unknown board type, ID = %x\n",
-				pB->i2ePom.e.porID );
-		nports = 0;
-		goto err_release_region;
-		break;
-
-	case POR_ID_II_4: /* IntelliPort-II, ISA-4 (4xRJ45) */
-		printk ( KERN_INFO "IP2: ISA-4\n" );
-		nports = 4;
-		break;
-
-	case POR_ID_II_8: /* IntelliPort-II, 8-port using standard brick. */
-		printk ( KERN_INFO "IP2: ISA-8 std\n" );
-		nports = 8;
-		break;
-
-	case POR_ID_II_8R: /* IntelliPort-II, 8-port using RJ11's (no CTS) */
-		printk ( KERN_INFO "IP2: ISA-8 RJ11\n" );
-		nports = 8;
-		break;
-
-	case POR_ID_FIIEX: /* IntelliPort IIEX */
-	{
-		int portnum = IP2_PORTS_PER_BOARD * boardnum;
-		int            box;
-
-		for( box = 0; box < ABS_MAX_BOXES; ++box ) {
-			if ( pB->i2eChannelMap[box] != 0 ) {
-				++nboxes;
-			}
-			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
-				if ( pB->i2eChannelMap[box] & 1<< i ) {
-					++nports;
-				}
-			}
-		}
-		DevTableMem[boardnum] = pCh =
-			kmalloc( sizeof(i2ChanStr) * nports, GFP_KERNEL );
-		if ( !pCh ) {
-			printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
-			goto err_release_region;
-		}
-		if ( !i2InitChannels( pB, nports, pCh ) ) {
-			printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
-			kfree ( pCh );
-			goto err_release_region;
-		}
-		pB->i2eChannelPtr = &DevTable[portnum];
-		pB->i2eChannelCnt = ABS_MOST_PORTS;
-
-		for( box = 0; box < ABS_MAX_BOXES; ++box, portnum += ABS_BIGGEST_BOX ) {
-			for( i = 0; i < ABS_BIGGEST_BOX; ++i ) {
-				if ( pB->i2eChannelMap[box] & (1 << i) ) {
-					DevTable[portnum + i] = pCh;
-					pCh->port_index = portnum + i;
-					pCh++;
-				}
-			}
-		}
-		printk(KERN_INFO "IP2: EX box=%d ports=%d %d bit\n",
-			nboxes, nports, pB->i2eDataWidth16 ? 16 : 8 );
-		}
-		goto ex_exit;
-	}
-	DevTableMem[boardnum] = pCh =
-		kmalloc ( sizeof (i2ChanStr) * nports, GFP_KERNEL );
-	if ( !pCh ) {
-		printk ( KERN_ERR "IP2: (i2_init_channel:) Out of memory.\n");
-		goto err_release_region;
-	}
-	pB->i2eChannelPtr = pCh;
-	pB->i2eChannelCnt = nports;
-	if ( !i2InitChannels( pB, nports, pCh ) ) {
-		printk(KERN_ERR "IP2: i2InitChannels failed: %d\n",pB->i2eError);
-		kfree ( pCh );
-		goto err_release_region;
-	}
-	pB->i2eChannelPtr = &DevTable[IP2_PORTS_PER_BOARD * boardnum];
-
-	for( i = 0; i < pB->i2eChannelCnt; ++i ) {
-		DevTable[IP2_PORTS_PER_BOARD * boardnum + i] = pCh;
-		pCh->port_index = (IP2_PORTS_PER_BOARD * boardnum) + i;
-		pCh++;
-	}
-ex_exit:
-	INIT_WORK(&pB->tqueue_interrupt, ip2_interrupt_bh);
-	return;
-
-err_release_region:
-	release_region(ip2config.addr[boardnum], 8);
-err_initialize:
-	kfree ( pB );
-	i2BoardPtrTable[boardnum] = NULL;
-	return;
-}
-
-/******************************************************************************/
-/* Function:   find_eisa_board ( int start_slot )                             */
-/* Parameters: First slot to check                                            */
-/* Returns:    Address of EISA IntelliPort II controller                      */
-/*                                                                            */
-/* Description:                                                               */
-/* This function searches for an EISA IntelliPort controller, starting        */
-/* from the specified slot number. If the motherboard is not identified as an */
-/* EISA motherboard, or no valid board ID is selected it returns 0. Otherwise */
-/* it returns the base address of the controller.                             */
-/******************************************************************************/
-static unsigned short
-find_eisa_board( int start_slot )
-{
-	int i, j;
-	unsigned int idm = 0;
-	unsigned int idp = 0;
-	unsigned int base = 0;
-	unsigned int value;
-	int setup_address;
-	int setup_irq;
-	int ismine = 0;
-
-	/*
-	 * First a check for an EISA motherboard, which we do by comparing the
-	 * EISA ID registers for the system board and the first couple of slots.
-	 * No slot ID should match the system board ID, but on an ISA or PCI
-	 * machine the odds are that an empty bus will return similar values for
-	 * each slot.
-	 */
-	i = 0x0c80;
-	value = (inb(i) << 24) + (inb(i+1) << 16) + (inb(i+2) << 8) + inb(i+3);
-	for( i = 0x1c80; i <= 0x4c80; i += 0x1000 ) {
-		j = (inb(i)<<24)+(inb(i+1)<<16)+(inb(i+2)<<8)+inb(i+3);
-		if ( value == j )
-			return 0;
-	}
-
-	/*
-	 * OK, so we are inclined to believe that this is an EISA machine. Find
-	 * an IntelliPort controller.
-	 */
-	for( i = start_slot; i < 16; i++ ) {
-		base = i << 12;
-		idm = (inb(base + 0xc80) << 8) | (inb(base + 0xc81) & 0xff);
-		idp = (inb(base + 0xc82) << 8) | (inb(base + 0xc83) & 0xff);
-		ismine = 0;
-		if ( idm == 0x0e8e ) {
-			if ( idp == 0x0281 || idp == 0x0218 ) {
-				ismine = 1;
-			} else if ( idp == 0x0282 || idp == 0x0283 ) {
-				ismine = 3;	/* Can do edge-trigger */
-			}
-			if ( ismine ) {
-				Eisa_slot = i;
-				break;
-			}
-		}
-	}
-	if ( !ismine )
-		return 0;
-
-	/* It's some sort of EISA card, but at what address is it configured? */
-
-	setup_address = base + 0xc88;
-	value = inb(base + 0xc86);
-	setup_irq = (value & 8) ? Valid_Irqs[value & 7] : 0;
-
-	if ( (ismine & 2) && !(value & 0x10) ) {
-		ismine = 1;	/* Could be edging, but not */
-	}
-
-	if ( Eisa_irq == 0 ) {
-		Eisa_irq = setup_irq;
-	} else if ( Eisa_irq != setup_irq ) {
-		printk ( KERN_ERR "IP2: EISA irq mismatch between EISA controllers\n" );
-	}
-
-#ifdef IP2DEBUG_INIT
-printk(KERN_DEBUG "Computone EISA board in slot %d, I.D. 0x%x%x, Address 0x%x",
-	       base >> 12, idm, idp, setup_address);
-	if ( Eisa_irq ) {
-		printk(KERN_DEBUG ", Interrupt %d %s\n",
-		       setup_irq, (ismine & 2) ? "(edge)" : "(level)");
-	} else {
-		printk(KERN_DEBUG ", (polled)\n");
-	}
-#endif
-	return setup_address;
-}
-
-/******************************************************************************/
-/* Function:   set_irq()                                                      */
-/* Parameters: index to board in board table                                  */
-/*             IRQ to use                                                     */
-/* Returns:    Success (0)                                                    */
-/*                                                                            */
-/* Description:                                                               */
-/******************************************************************************/
-static void
-set_irq( int boardnum, int boardIrq )
-{
-	unsigned char tempCommand[16];
-	i2eBordStrPtr pB = i2BoardPtrTable[boardnum];
-	unsigned long flags;
-
-	/*
-	 * Notify the boards they may generate interrupts. This is done by
-	 * sending an in-line command to channel 0 on each board. This is why
-	 * the channels have to be defined already. For each board, if the
-	 * interrupt has never been defined, we must do so NOW, directly, since
-	 * board will not send flow control or even give an interrupt until this
-	 * is done.  If polling we must send 0 as the interrupt parameter.
-	 */
-
-	// We will get an interrupt here at the end of this function
-
-	iiDisableMailIrq(pB);
-
-	/* We build up the entire packet header. */
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_INLINE;
-	CMD_COUNT_OF(tempCommand) = 2;
-	(CMD_OF(tempCommand))[0] = CMDVALUE_IRQ;
-	(CMD_OF(tempCommand))[1] = boardIrq;
-	/*
-	 * Write to FIFO; don't bother to adjust fifo capacity for this, since
-	 * board will respond almost immediately after SendMail hit.
-	 */
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 4);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-	pB->i2eUsingIrq = boardIrq;
-	pB->i2eOutMailWaiting |= MB_OUT_STUFFED;
-
-	/* Need to update number of boards before you enable mailbox int */
-	++i2nBoards;
-
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 6;
-	(CMD_OF(tempCommand))[0] = 88;	// SILO
-	(CMD_OF(tempCommand))[1] = 64;	// chars
-	(CMD_OF(tempCommand))[2] = 32;	// ms
-
-	(CMD_OF(tempCommand))[3] = 28;	// MAX_BLOCK
-	(CMD_OF(tempCommand))[4] = 64;	// chars
-
-	(CMD_OF(tempCommand))[5] = 87;	// HW_TEST
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 8);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 1;
-	(CMD_OF(tempCommand))[0] = 84;	/* get BOX_IDS */
-	iiWriteBuf(pB, tempCommand, 3);
-
-#ifdef XXX
-	// enable heartbeat for test porpoises
-	CHANNEL_OF(tempCommand) = 0;
-	PTYPE_OF(tempCommand) = PTYPE_BYPASS;
-	CMD_COUNT_OF(tempCommand) = 2;
-	(CMD_OF(tempCommand))[0] = 44;	/* get ping */
-	(CMD_OF(tempCommand))[1] = 200;	/* 200 ms */
-	write_lock_irqsave(&pB->write_fifo_spinlock, flags);
-	iiWriteBuf(pB, tempCommand, 4);
-	write_unlock_irqrestore(&pB->write_fifo_spinlock, flags);
-#endif
-
-	iiEnableMailIrq(pB);
-	iiSendPendingMail(pB);
-}
-
-/******************************************************************************/
-/* Interrupt Handler Section                                                  */
-/******************************************************************************/
-
-static inline void
-service_all_boards(void)
-{
-	int i;
-	i2eBordStrPtr  pB;
-
-	/* Service every board on the list */
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		pB = i2BoardPtrTable[i];
-		if ( pB ) {
-			i2ServiceBoard( pB );
-		}
-	}
-}
-
-
-/******************************************************************************/
-/* Function:   ip2_interrupt_bh(work)                                         */
-/* Parameters: work - pointer to the board structure                          */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*	Service the board in a bottom half interrupt handler and then         */
-/*	reenable the board's interrupts if it has an IRQ number               */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_interrupt_bh(struct work_struct *work)
-{
-	i2eBordStrPtr pB = container_of(work, i2eBordStr, tqueue_interrupt);
-//	pB better well be set or we have a problem!  We can only get
-//	here from the IMMEDIATE queue.  Here, we process the boards.
-//	Checking pB doesn't cost much and it saves us from the sanity checkers.
-
-	bh_counter++; 
-
-	if ( pB ) {
-		i2ServiceBoard( pB );
-		if( pB->i2eUsingIrq ) {
-//			Re-enable his interrupts
-			iiEnableMailIrq(pB);
-		}
-	}
-}
-
-
-/******************************************************************************/
-/* Function:   ip2_interrupt(int irq, void *dev_id)    */
-/* Parameters: irq - interrupt number                                         */
-/*             pointer to optional device ID structure                        */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*	Our task here is simply to identify each board which needs servicing. */
-/*	If we are queuing then, queue it to be serviced, and disable its irq  */
-/*	mask otherwise process the board directly.                            */
-/*                                                                            */
-/*	We could queue by IRQ but that just complicates things on both ends   */
-/*	with very little gain in performance (how many instructions does      */
-/*	it take to iterate on the immediate queue).                           */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_irq_work(i2eBordStrPtr pB)
-{
-#ifdef USE_IQI
-	if (NO_MAIL_HERE != ( pB->i2eStartMail = iiGetMail(pB))) {
-//		Disable his interrupt (will be enabled when serviced)
-//		This is mostly to protect from reentrancy.
-		iiDisableMailIrq(pB);
-
-//		Park the board on the immediate queue for processing.
-		schedule_work(&pB->tqueue_interrupt);
-
-//		Make sure the immediate queue is flagged to fire.
-	}
-#else
-
-//	We are using immediate servicing here.  This sucks and can
-//	cause all sorts of havoc with ppp and others.  The failsafe
-//	check on iiSendPendingMail could also throw a hairball.
-
-	i2ServiceBoard( pB );
-
-#endif /* USE_IQI */
-}
-
-static void
-ip2_polled_interrupt(void)
-{
-	int i;
-	i2eBordStrPtr  pB;
-
-	ip2trace(ITRC_NO_PORT, ITRC_INTR, 99, 1, 0);
-
-	/* Service just the boards on the list using this irq */
-	for( i = 0; i < i2nBoards; ++i ) {
-		pB = i2BoardPtrTable[i];
-
-//		Only process those boards which match our IRQ.
-//			IRQ = 0 for polled boards, we won't poll "IRQ" boards
-
-		if (pB && pB->i2eUsingIrq == 0)
-			ip2_irq_work(pB);
-	}
-
-	++irq_counter;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-}
-
-static irqreturn_t
-ip2_interrupt(int irq, void *dev_id)
-{
-	i2eBordStrPtr pB = dev_id;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 99, 1, pB->i2eUsingIrq );
-
-	ip2_irq_work(pB);
-
-	++irq_counter;
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-	return IRQ_HANDLED;
-}
-
-/******************************************************************************/
-/* Function:   ip2_poll(unsigned long arg)                                    */
-/* Parameters: ?                                                              */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function calls the library routine i2ServiceBoard for each board in   */
-/* the board table. This is used instead of the interrupt routine when polled */
-/* mode is specified.                                                         */
-/******************************************************************************/
-static void
-ip2_poll(unsigned long arg)
-{
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, 100, 0 );
-
-	// Just polled boards, IRQ = 0 will hit all non-interrupt boards.
-	// It will NOT poll boards handled by hard interrupts.
-	// The issue of queued BH interrupts is handled in ip2_interrupt().
-	ip2_polled_interrupt();
-
-	mod_timer(&PollTimer, POLL_TIMEOUT);
-
-	ip2trace (ITRC_NO_PORT, ITRC_INTR, ITRC_RETURN, 0 );
-}
-
-static void do_input(struct work_struct *work)
-{
-	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_input);
-	unsigned long flags;
-
-	ip2trace(CHANN, ITRC_INPUT, 21, 0 );
-
-	// Data input
-	if ( pCh->pTTY != NULL ) {
-		read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-		if (!pCh->throttled && (pCh->Ibuf_stuff != pCh->Ibuf_strip)) {
-			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-			i2Input( pCh );
-		} else
-			read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-	} else {
-		ip2trace(CHANN, ITRC_INPUT, 22, 0 );
-
-		i2InputFlush( pCh );
-	}
-}
-
-// code duplicated from n_tty (ldisc)
-static inline void  isig(int sig, struct tty_struct *tty, int flush)
-{
-	/* FIXME: This is completely bogus */
-	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);
-		i2InputFlush( tty->driver_data );
-	}
-}
-
-static void do_status(struct work_struct *work)
-{
-	i2ChanStrPtr pCh = container_of(work, i2ChanStr, tqueue_status);
-	int status;
-
-	status =  i2GetStatus( pCh, (I2_BRK|I2_PAR|I2_FRA|I2_OVR) );
-
-	ip2trace (CHANN, ITRC_STATUS, 21, 1, status );
-
-	if (pCh->pTTY && (status & (I2_BRK|I2_PAR|I2_FRA|I2_OVR)) ) {
-		if ( (status & I2_BRK) ) {
-			// code duplicated from n_tty (ldisc)
-			if (I_IGNBRK(pCh->pTTY))
-				goto skip_this;
-			if (I_BRKINT(pCh->pTTY)) {
-				isig(SIGINT, pCh->pTTY, 1);
-				goto skip_this;
-			}
-			wake_up_interruptible(&pCh->pTTY->read_wait);
-		}
-#ifdef NEVER_HAPPENS_AS_SETUP_XXX
-	// and can't work because we don't know the_char
-	// as the_char is reported on a separate path
-	// The intelligent board does this stuff as setup
-	{
-	char brkf = TTY_NORMAL;
-	unsigned char brkc = '\0';
-	unsigned char tmp;
-		if ( (status & I2_BRK) ) {
-			brkf = TTY_BREAK;
-			brkc = '\0';
-		} 
-		else if (status & I2_PAR) {
-			brkf = TTY_PARITY;
-			brkc = the_char;
-		} else if (status & I2_FRA) {
-			brkf = TTY_FRAME;
-			brkc = the_char;
-		} else if (status & I2_OVR) {
-			brkf = TTY_OVERRUN;
-			brkc = the_char;
-		}
-		tmp = pCh->pTTY->real_raw;
-		pCh->pTTY->real_raw = 0;
-		pCh->pTTY->ldisc->ops.receive_buf( pCh->pTTY, &brkc, &brkf, 1 );
-		pCh->pTTY->real_raw = tmp;
-	}
-#endif /* NEVER_HAPPENS_AS_SETUP_XXX */
-	}
-skip_this:
-
-	if ( status & (I2_DDCD | I2_DDSR | I2_DCTS | I2_DRI) ) {
-		wake_up_interruptible(&pCh->delta_msr_wait);
-
-		if ( (pCh->flags & ASYNC_CHECK_CD) && (status & I2_DDCD) ) {
-			if ( status & I2_DCD ) {
-				if ( pCh->wopen ) {
-					wake_up_interruptible ( &pCh->open_wait );
-				}
-			} else {
-				if (pCh->pTTY &&  (!(pCh->pTTY->termios->c_cflag & CLOCAL)) ) {
-					tty_hangup( pCh->pTTY );
-				}
-			}
-		}
-	}
-
-	ip2trace (CHANN, ITRC_STATUS, 26, 0 );
-}
-
-/******************************************************************************/
-/* Device Open/Close/Ioctl Entry Point Section                                */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   open_sanity_check()                                            */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/* Verifies the structure magic numbers and cross links.                      */
-/******************************************************************************/
-#ifdef IP2DEBUG_OPEN
-static void 
-open_sanity_check( i2ChanStrPtr pCh, i2eBordStrPtr pBrd )
-{
-	if ( pBrd->i2eValid != I2E_MAGIC ) {
-		printk(KERN_ERR "IP2: invalid board structure\n" );
-	} else if ( pBrd != pCh->pMyBord ) {
-		printk(KERN_ERR "IP2: board structure pointer mismatch (%p)\n",
-			 pCh->pMyBord );
-	} else if ( pBrd->i2eChannelCnt < pCh->port_index ) {
-		printk(KERN_ERR "IP2: bad device index (%d)\n", pCh->port_index );
-	} else if (&((i2ChanStrPtr)pBrd->i2eChannelPtr)[pCh->port_index] != pCh) {
-	} else {
-		printk(KERN_INFO "IP2: all pointers check out!\n" );
-	}
-}
-#endif
-
-
-/******************************************************************************/
-/* Function:   ip2_open()                                                     */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description: (MANDATORY)                                                   */
-/* A successful device open has to run a gauntlet of checks before it         */
-/* completes. After some sanity checking and pointer setup, the function      */
-/* blocks until all conditions are satisfied. It then initialises the port to */
-/* the default characteristics and returns.                                   */
-/******************************************************************************/
-static int
-ip2_open( PTTY tty, struct file *pFile )
-{
-	wait_queue_t wait;
-	int rc = 0;
-	int do_clocal = 0;
-	i2ChanStrPtr  pCh = DevTable[tty->index];
-
-	ip2trace (tty->index, ITRC_OPEN, ITRC_ENTER, 0 );
-
-	if ( pCh == NULL ) {
-		return -ENODEV;
-	}
-	/* Setup pointer links in device and tty structures */
-	pCh->pTTY = tty;
-	tty->driver_data = pCh;
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG \
-			"IP2:open(tty=%p,pFile=%p):dev=%s,ch=%d,idx=%d\n",
-	       tty, pFile, tty->name, pCh->infl.hd.i2sChannel, pCh->port_index);
-	open_sanity_check ( pCh, pCh->pMyBord );
-#endif
-
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 3, CMD_DTRUP,CMD_RTSUP,CMD_DCD_REP);
-	pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	/* Block here until the port is ready (per serial and istallion) */
-	/*
-	 * 1. If the port is in the middle of closing wait for the completion
-	 *    and then return the appropriate error.
-	 */
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->close_wait, &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	if ( tty_hung_up_p(pFile) || ( pCh->flags & ASYNC_CLOSING )) {
-		if ( pCh->flags & ASYNC_CLOSING ) {
-			tty_unlock();
-			schedule();
-			tty_lock();
-		}
-		if ( tty_hung_up_p(pFile) ) {
-			set_current_state( TASK_RUNNING );
-			remove_wait_queue(&pCh->close_wait, &wait);
-			return( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS;
-		}
-	}
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->close_wait, &wait);
-
-	/*
-	 * 3. Handle a non-blocking open of a normal port.
-	 */
-	if ( (pFile->f_flags & O_NONBLOCK) || (tty->flags & (1<<TTY_IO_ERROR) )) {
-		pCh->flags |= ASYNC_NORMAL_ACTIVE;
-		goto noblock;
-	}
-	/*
-	 * 4. Now loop waiting for the port to be free and carrier present
-	 *    (if required).
-	 */
-	if ( tty->termios->c_cflag & CLOCAL )
-		do_clocal = 1;
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG "OpenBlock: do_clocal = %d\n", do_clocal);
-#endif
-
-	++pCh->wopen;
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->open_wait, &wait);
-
-	for(;;) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
-		pCh->dataSetOut |= (I2_DTR | I2_RTS);
-		set_current_state( TASK_INTERRUPTIBLE );
-		serviceOutgoingFifo( pCh->pMyBord );
-		if ( tty_hung_up_p(pFile) ) {
-			set_current_state( TASK_RUNNING );
-			remove_wait_queue(&pCh->open_wait, &wait);
-			return ( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EBUSY : -ERESTARTSYS;
-		}
-		if (!(pCh->flags & ASYNC_CLOSING) && 
-				(do_clocal || (pCh->dataSetIn & I2_DCD) )) {
-			rc = 0;
-			break;
-		}
-
-#ifdef IP2DEBUG_OPEN
-		printk(KERN_DEBUG "ASYNC_CLOSING = %s\n",
-			(pCh->flags & ASYNC_CLOSING)?"True":"False");
-		printk(KERN_DEBUG "OpenBlock: waiting for CD or signal\n");
-#endif
-		ip2trace (CHANN, ITRC_OPEN, 3, 2, 0,
-				(pCh->flags & ASYNC_CLOSING) );
-		/* check for signal */
-		if (signal_pending(current)) {
-			rc = (( pCh->flags & ASYNC_HUP_NOTIFY ) ? -EAGAIN : -ERESTARTSYS);
-			break;
-		}
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->open_wait, &wait);
-
-	--pCh->wopen; //why count?
-
-	ip2trace (CHANN, ITRC_OPEN, 4, 0 );
-
-	if (rc != 0 ) {
-		return rc;
-	}
-	pCh->flags |= ASYNC_NORMAL_ACTIVE;
-
-noblock:
-
-	/* first open - Assign termios structure to port */
-	if ( tty->count == 1 ) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-		/* Now we must send the termios settings to the loadware */
-		set_params( pCh, NULL );
-	}
-
-	/*
-	 * Now set any i2lib options. These may go away if the i2lib code ends
-	 * up rolled into the mainline.
-	 */
-	pCh->channelOptions |= CO_NBLOCK_WRITE;
-
-#ifdef IP2DEBUG_OPEN
-	printk (KERN_DEBUG "IP2: open completed\n" );
-#endif
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	ip2trace (CHANN, ITRC_OPEN, ITRC_RETURN, 0 );
-
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_close()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_close( PTTY tty, struct file *pFile )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	if ( !pCh ) {
-		return;
-	}
-
-	ip2trace (CHANN, ITRC_CLOSE, ITRC_ENTER, 0 );
-
-#ifdef IP2DEBUG_OPEN
-	printk(KERN_DEBUG "IP2:close %s:\n",tty->name);
-#endif
-
-	if ( tty_hung_up_p ( pFile ) ) {
-
-		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 2 );
-
-		return;
-	}
-	if ( tty->count > 1 ) { /* not the last close */
-
-		ip2trace (CHANN, ITRC_CLOSE, 2, 1, 3 );
-
-		return;
-	}
-	pCh->flags |= ASYNC_CLOSING;	// last close actually
-
-	tty->closing = 1;
-
-	if (pCh->ClosingWaitTime != ASYNC_CLOSING_WAIT_NONE) {
-		/*
-		 * Before we drop DTR, make sure the transmitter has completely drained.
-		 * This uses an timeout, after which the close
-		 * completes.
-		 */
-		ip2_wait_until_sent(tty, pCh->ClosingWaitTime );
-	}
-	/*
-	 * At this point we stop accepting input. Here we flush the channel
-	 * input buffer which will allow the board to send up more data. Any
-	 * additional input is tossed at interrupt/poll time.
-	 */
-	i2InputFlush( pCh );
-
-	/* disable DSS reporting */
-	i2QueueCommands(PTYPE_INLINE, pCh, 100, 4,
-				CMD_DCD_NREP, CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-	if (tty->termios->c_cflag & HUPCL) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
-		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-	}
-
-	serviceOutgoingFifo ( pCh->pMyBord );
-
-	tty_ldisc_flush(tty);
-	tty_driver_flush_buffer(tty);
-	tty->closing = 0;
-	
-	pCh->pTTY = NULL;
-
-	if (pCh->wopen) {
-		if (pCh->ClosingDelay) {
-			msleep_interruptible(jiffies_to_msecs(pCh->ClosingDelay));
-		}
-		wake_up_interruptible(&pCh->open_wait);
-	}
-
-	pCh->flags &=~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&pCh->close_wait);
-
-#ifdef IP2DEBUG_OPEN
-	DBG_CNT("ip2_close: after wakeups--");
-#endif
-
-
-	ip2trace (CHANN, ITRC_CLOSE, ITRC_RETURN, 1, 1 );
-
-	return;
-}
-
-/******************************************************************************/
-/* Function:   ip2_hangup()                                                   */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_hangup ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	if( !pCh ) {
-		return;
-	}
-
-	ip2trace (CHANN, ITRC_HANGUP, ITRC_ENTER, 0 );
-
-	ip2_flush_buffer(tty);
-
-	/* disable DSS reporting */
-
-	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_DCD_NREP);
-	i2QueueCommands(PTYPE_INLINE, pCh, 0, 2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-	if ( (tty->termios->c_cflag & HUPCL) ) {
-		i2QueueCommands(PTYPE_BYPASS, pCh, 0, 2, CMD_RTSDN, CMD_DTRDN);
-		pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-	}
-	i2QueueCommands(PTYPE_INLINE, pCh, 1, 3, 
-				CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-	serviceOutgoingFifo ( pCh->pMyBord );
-
-	wake_up_interruptible ( &pCh->delta_msr_wait );
-
-	pCh->flags &= ~ASYNC_NORMAL_ACTIVE;
-	pCh->pTTY = NULL;
-	wake_up_interruptible ( &pCh->open_wait );
-
-	ip2trace (CHANN, ITRC_HANGUP, ITRC_RETURN, 0 );
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/* Device Output Section                                                      */
-/******************************************************************************/
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_write()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Flag denoting data is in user (1) or kernel (0) space          */
-/*             Pointer to data                                                */
-/*             Number of bytes to write                                       */
-/* Returns:    Number of bytes actually written                               */
-/*                                                                            */
-/* Description: (MANDATORY)                                                   */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_write( PTTY tty, const unsigned char *pData, int count)
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	int bytesSent = 0;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_WRITE, ITRC_ENTER, 2, count, -1 );
-
-	/* Flush out any buffered data left over from ip2_putchar() calls. */
-	ip2_flush_chars( tty );
-
-	/* This is the actual move bit. Make sure it does what we need!!!!! */
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	bytesSent = i2Output( pCh, pData, count);
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-
-	ip2trace (CHANN, ITRC_WRITE, ITRC_RETURN, 1, bytesSent );
-
-	return bytesSent > 0 ? bytesSent : 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_putchar()                                                  */
-/* Parameters: Pointer to tty structure                                       */
-/*             Character to write                                             */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_putchar( PTTY tty, unsigned char ch )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-//	ip2trace (CHANN, ITRC_PUTC, ITRC_ENTER, 1, ch );
-
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	pCh->Pbuf[pCh->Pbuf_stuff++] = ch;
-	if ( pCh->Pbuf_stuff == sizeof pCh->Pbuf ) {
-		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-		ip2_flush_chars( tty );
-	} else
-		write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	return 1;
-
-//	ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
-}
-
-/******************************************************************************/
-/* Function:   ip2_flush_chars()                                              */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_flush_chars( PTTY tty )
-{
-	int   strip;
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	if ( pCh->Pbuf_stuff ) {
-
-//		ip2trace (CHANN, ITRC_PUTC, 10, 1, strip );
-
-		//
-		// We may need to restart i2Output if it does not fullfill this request
-		//
-		strip = i2Output( pCh, pCh->Pbuf, pCh->Pbuf_stuff);
-		if ( strip != pCh->Pbuf_stuff ) {
-			memmove( pCh->Pbuf, &pCh->Pbuf[strip], pCh->Pbuf_stuff - strip );
-		}
-		pCh->Pbuf_stuff -= strip;
-	}
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-}
-
-/******************************************************************************/
-/* Function:   ip2_write_room()                                               */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Number of bytes that the driver can accept                     */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_write_room ( PTTY tty )
-{
-	int bytesFree;
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	bytesFree = i2OutputFree( pCh ) - pCh->Pbuf_stuff;
-	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-
-	ip2trace (CHANN, ITRC_WRITE, 11, 1, bytesFree );
-
-	return ((bytesFree > 0) ? bytesFree : 0);
-}
-
-/******************************************************************************/
-/* Function:   ip2_chars_in_buf()                                             */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Number of bytes queued for transmission                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_chars_in_buf ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	int rc;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_WRITE, 12, 1, pCh->Obuf_char_count + pCh->Pbuf_stuff );
-
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: chars in buffer = %d (%d,%d)\n",
-				 pCh->Obuf_char_count + pCh->Pbuf_stuff,
-				 pCh->Obuf_char_count, pCh->Pbuf_stuff );
-#endif
-	read_lock_irqsave(&pCh->Obuf_spinlock, flags);
-	rc =  pCh->Obuf_char_count;
-	read_unlock_irqrestore(&pCh->Obuf_spinlock, flags);
-	read_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	rc +=  pCh->Pbuf_stuff;
-	read_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	return rc;
-}
-
-/******************************************************************************/
-/* Function:   ip2_flush_buffer()                                             */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_flush_buffer( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-	ip2trace (CHANN, ITRC_FLUSH, ITRC_ENTER, 0 );
-
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: flush buffer\n" );
-#endif
-	write_lock_irqsave(&pCh->Pbuf_spinlock, flags);
-	pCh->Pbuf_stuff = 0;
-	write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
-	i2FlushOutput( pCh );
-	ip2_owake(tty);
-
-	ip2trace (CHANN, ITRC_FLUSH, ITRC_RETURN, 0 );
-
-}
-
-/******************************************************************************/
-/* Function:   ip2_wait_until_sent()                                          */
-/* Parameters: Pointer to tty structure                                       */
-/*             Timeout for wait.                                              */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function is used in place of the normal tty_wait_until_sent, which    */
-/* only waits for the driver buffers to be empty (or rather, those buffers    */
-/* reported by chars_in_buffer) which doesn't work for IP2 due to the         */
-/* indeterminate number of bytes buffered on the board.                       */
-/******************************************************************************/
-static void
-ip2_wait_until_sent ( PTTY tty, int timeout )
-{
-	int i = jiffies;
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-	tty_wait_until_sent(tty, timeout );
-	if ( (i = timeout - (jiffies -i)) > 0)
-		i2DrainOutput( pCh, i );
-}
-
-/******************************************************************************/
-/******************************************************************************/
-/* Device Input Section                                                       */
-/******************************************************************************/
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_throttle()                                                 */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_throttle ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-
-#ifdef IP2DEBUG_READ
-	printk (KERN_DEBUG "IP2: throttle\n" );
-#endif
-	/*
-	 * Signal the poll/interrupt handlers not to forward incoming data to
-	 * the line discipline. This will cause the buffers to fill up in the
-	 * library and thus cause the library routines to send the flow control
-	 * stuff.
-	 */
-	pCh->throttled = 1;
-}
-
-/******************************************************************************/
-/* Function:   ip2_unthrottle()                                               */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_unthrottle ( PTTY tty )
-{
-	i2ChanStrPtr  pCh = tty->driver_data;
-	unsigned long flags;
-
-#ifdef IP2DEBUG_READ
-	printk (KERN_DEBUG "IP2: unthrottle\n" );
-#endif
-
-	/* Pass incoming data up to the line discipline again. */
-	pCh->throttled = 0;
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
-	serviceOutgoingFifo( pCh->pMyBord );
-	read_lock_irqsave(&pCh->Ibuf_spinlock, flags);
-	if ( pCh->Ibuf_stuff != pCh->Ibuf_strip ) {
-		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-#ifdef IP2DEBUG_READ
-		printk (KERN_DEBUG "i2Input called from unthrottle\n" );
-#endif
-		i2Input( pCh );
-	} else
-		read_unlock_irqrestore(&pCh->Ibuf_spinlock, flags);
-}
-
-static void
-ip2_start ( PTTY tty )
-{
- 	i2ChanStrPtr  pCh = DevTable[tty->index];
-
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 0, 1, CMD_RESUME);
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_UNSUSPEND);
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_RESUME);
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: start tx\n" );
-#endif
-}
-
-static void
-ip2_stop ( PTTY tty )
-{
- 	i2ChanStrPtr  pCh = DevTable[tty->index];
-
- 	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_SUSPEND);
-#ifdef IP2DEBUG_WRITE
-	printk (KERN_DEBUG "IP2: stop tx\n" );
-#endif
-}
-
-/******************************************************************************/
-/* Device Ioctl Section                                                       */
-/******************************************************************************/
-
-static int ip2_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-#ifdef	ENABLE_DSSNOW
-	wait_queue_t wait;
-#endif
-
-	if (pCh == NULL)
-		return -ENODEV;
-
-/*
-	FIXME - the following code is causing a NULL pointer dereference in
-	2.3.51 in an interrupt handler.  It's suppose to prompt the board
-	to return the DSS signal status immediately.  Why doesn't it do
-	the same thing in 2.2.14?
-*/
-
-/*	This thing is still busted in the 1.2.12 driver on 2.4.x
-	and even hoses the serial console so the oops can be trapped.
-		/\/\|=mhw=|\/\/			*/
-
-#ifdef	ENABLE_DSSNOW
-	i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DSS_NOW);
-
-	init_waitqueue_entry(&wait, current);
-	add_wait_queue(&pCh->dss_now_wait, &wait);
-	set_current_state( TASK_INTERRUPTIBLE );
-
-	serviceOutgoingFifo( pCh->pMyBord );
-
-	schedule();
-
-	set_current_state( TASK_RUNNING );
-	remove_wait_queue(&pCh->dss_now_wait, &wait);
-
-	if (signal_pending(current)) {
-		return -EINTR;
-	}
-#endif
-	return  ((pCh->dataSetOut & I2_RTS) ? TIOCM_RTS : 0)
-	      | ((pCh->dataSetOut & I2_DTR) ? TIOCM_DTR : 0)
-	      | ((pCh->dataSetIn  & I2_DCD) ? TIOCM_CAR : 0)
-	      | ((pCh->dataSetIn  & I2_RI)  ? TIOCM_RNG : 0)
-	      | ((pCh->dataSetIn  & I2_DSR) ? TIOCM_DSR : 0)
-	      | ((pCh->dataSetIn  & I2_CTS) ? TIOCM_CTS : 0);
-}
-
-static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
-			unsigned int set, unsigned int clear)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-
-	if (pCh == NULL)
-		return -ENODEV;
-
-	if (set & TIOCM_RTS) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSUP);
-		pCh->dataSetOut |= I2_RTS;
-	}
-	if (set & TIOCM_DTR) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRUP);
-		pCh->dataSetOut |= I2_DTR;
-	}
-
-	if (clear & TIOCM_RTS) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_RTSDN);
-		pCh->dataSetOut &= ~I2_RTS;
-	}
-	if (clear & TIOCM_DTR) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DTRDN);
-		pCh->dataSetOut &= ~I2_DTR;
-	}
-	serviceOutgoingFifo( pCh->pMyBord );
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ioctl()                                                    */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to file structure                                      */
-/*             Command                                                        */
-/*             Argument                                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
-{
-	wait_queue_t wait;
-	i2ChanStrPtr pCh = DevTable[tty->index];
-	i2eBordStrPtr pB;
-	struct async_icount cprev, cnow;	/* kernel counter temps */
-	int rc = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	if ( pCh == NULL )
-		return -ENODEV;
-
-	pB = pCh->pMyBord;
-
-	ip2trace (CHANN, ITRC_IOCTL, ITRC_ENTER, 2, cmd, arg );
-
-#ifdef IP2DEBUG_IOCTL
-	printk(KERN_DEBUG "IP2: ioctl cmd (%x), arg (%lx)\n", cmd, arg );
-#endif
-
-	switch(cmd) {
-	case TIOCGSERIAL:
-
-		ip2trace (CHANN, ITRC_IOCTL, 2, 1, rc );
-
-		rc = get_serial_info(pCh, argp);
-		if (rc)
-			return rc;
-		break;
-
-	case TIOCSSERIAL:
-
-		ip2trace (CHANN, ITRC_IOCTL, 3, 1, rc );
-
-		rc = set_serial_info(pCh, argp);
-		if (rc)
-			return rc;
-		break;
-
-	case TCXONC:
-		rc = tty_check_change(tty);
-		if (rc)
-			return rc;
-		switch (arg) {
-		case TCOOFF:
-			//return  -ENOIOCTLCMD;
-			break;
-		case TCOON:
-			//return  -ENOIOCTLCMD;
-			break;
-		case TCIOFF:
-			if (STOP_CHAR(tty) != __DISABLED_CHAR) {
-				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
-						CMD_XMIT_NOW(STOP_CHAR(tty)));
-			}
-			break;
-		case TCION:
-			if (START_CHAR(tty) != __DISABLED_CHAR) {
-				i2QueueCommands( PTYPE_BYPASS, pCh, 100, 1,
-						CMD_XMIT_NOW(START_CHAR(tty)));
-			}
-			break;
-		default:
-			return -EINVAL;
-		}
-		return 0;
-
-	case TCSBRK:   /* SVID version: non-zero arg --> no break */
-		rc = tty_check_change(tty);
-
-		ip2trace (CHANN, ITRC_IOCTL, 4, 1, rc );
-
-		if (!rc) {
-			ip2_wait_until_sent(tty,0);
-			if (!arg) {
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SEND_BRK(250));
-				serviceOutgoingFifo( pCh->pMyBord );
-			}
-		}
-		break;
-
-	case TCSBRKP:  /* support for POSIX tcsendbreak() */
-		rc = tty_check_change(tty);
-
-		ip2trace (CHANN, ITRC_IOCTL, 5, 1, rc );
-
-		if (!rc) {
-			ip2_wait_until_sent(tty,0);
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1,
-				CMD_SEND_BRK(arg ? arg*100 : 250));
-			serviceOutgoingFifo ( pCh->pMyBord );	
-		}
-		break;
-
-	case TIOCGSOFTCAR:
-
-		ip2trace (CHANN, ITRC_IOCTL, 6, 1, rc );
-
-			rc = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *)argp);
-		if (rc)	
-			return rc;
-	break;
-
-	case TIOCSSOFTCAR:
-
-		ip2trace (CHANN, ITRC_IOCTL, 7, 1, rc );
-
-		rc = get_user(arg,(unsigned long __user *) argp);
-		if (rc) 
-			return rc;
-		tty->termios->c_cflag = ((tty->termios->c_cflag & ~CLOCAL)
-					 | (arg ? CLOCAL : 0));
-		
-		break;
-
-	/*
-	 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change - mask
-	 * passed in arg for lines of interest (use |'ed TIOCM_RNG/DSR/CD/CTS
-	 * for masking). Caller should use TIOCGICOUNT to see which one it was
-	 */
-	case TIOCMIWAIT:
-		write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-		cprev = pCh->icount;	 /* note the counters on entry */
-		write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 4, 
-						CMD_DCD_REP, CMD_CTS_REP, CMD_DSR_REP, CMD_RI_REP);
-		init_waitqueue_entry(&wait, current);
-		add_wait_queue(&pCh->delta_msr_wait, &wait);
-		set_current_state( TASK_INTERRUPTIBLE );
-
-		serviceOutgoingFifo( pCh->pMyBord );
-		for(;;) {
-			ip2trace (CHANN, ITRC_IOCTL, 10, 0 );
-
-			schedule();
-
-			ip2trace (CHANN, ITRC_IOCTL, 11, 0 );
-
-			/* see if a signal did it */
-			if (signal_pending(current)) {
-				rc = -ERESTARTSYS;
-				break;
-			}
-			write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-			cnow = pCh->icount; /* atomic copy */
-			write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-			if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-				cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-				rc =  -EIO; /* no change => rc */
-				break;
-			}
-			if (((arg & TIOCM_RNG) && (cnow.rng != cprev.rng)) ||
-			    ((arg & TIOCM_DSR) && (cnow.dsr != cprev.dsr)) ||
-			    ((arg & TIOCM_CD)  && (cnow.dcd != cprev.dcd)) ||
-			    ((arg & TIOCM_CTS) && (cnow.cts != cprev.cts)) ) {
-				rc =  0;
-				break;
-			}
-			cprev = cnow;
-		}
-		set_current_state( TASK_RUNNING );
-		remove_wait_queue(&pCh->delta_msr_wait, &wait);
-
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 3, 
-						 CMD_CTS_NREP, CMD_DSR_NREP, CMD_RI_NREP);
-		if ( ! (pCh->flags	& ASYNC_CHECK_CD)) {
-			i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DCD_NREP);
-		}
-		serviceOutgoingFifo( pCh->pMyBord );
-		return rc;
-		break;
-
-	/*
-	 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
-	 * will be passed to the line discipline for it to handle.
-	 */
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERSWILD:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-
-	default:
-		ip2trace (CHANN, ITRC_IOCTL, 12, 0 );
-
-		rc =  -ENOIOCTLCMD;
-		break;
-	}
-
-	ip2trace (CHANN, ITRC_IOCTL, ITRC_RETURN, 0 );
-
-	return rc;
-}
-
-static int ip2_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount)
-{
-	i2ChanStrPtr pCh = DevTable[tty->index];
-	i2eBordStrPtr pB;
-	struct async_icount cnow;	/* kernel counter temp */
-	unsigned long flags;
-
-	if ( pCh == NULL )
-		return -ENODEV;
-
-	pB = pCh->pMyBord;
-
-	/*
-	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-	 * Return: write counters to the user passed counter struct
-	 * NB: both 1->0 and 0->1 transitions are counted except for RI where
-	 * only 0->1 is counted. The controller is quite capable of counting
-	 * both, but this done to preserve compatibility with the standard
-	 * serial driver.
-	 */
-
-	write_lock_irqsave(&pB->read_fifo_spinlock, flags);
-	cnow = pCh->icount;
-	write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   GetSerialInfo()                                                */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This is to support the setserial command, and requires processing of the   */
-/* standard Linux serial structure.                                           */
-/******************************************************************************/
-static int
-get_serial_info ( i2ChanStrPtr pCh, struct serial_struct __user *retinfo )
-{
-	struct serial_struct tmp;
-
-	memset ( &tmp, 0, sizeof(tmp) );
-	tmp.type = pCh->pMyBord->channelBtypes.bid_value[(pCh->port_index & (IP2_PORTS_PER_BOARD-1))/16];
-	if (BID_HAS_654(tmp.type)) {
-		tmp.type = PORT_16650;
-	} else {
-		tmp.type = PORT_CIRRUS;
-	}
-	tmp.line = pCh->port_index;
-	tmp.port = pCh->pMyBord->i2eBase;
-	tmp.irq  = ip2config.irq[pCh->port_index/64];
-	tmp.flags = pCh->flags;
-	tmp.baud_base = pCh->BaudBase;
-	tmp.close_delay = pCh->ClosingDelay;
-	tmp.closing_wait = pCh->ClosingWaitTime;
-	tmp.custom_divisor = pCh->BaudDivisor;
-   	return copy_to_user(retinfo,&tmp,sizeof(*retinfo));
-}
-
-/******************************************************************************/
-/* Function:   SetSerialInfo()                                                */
-/* Parameters: Pointer to channel structure                                   */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This function provides support for setserial, which uses the TIOCSSERIAL   */
-/* ioctl. Not all setserial parameters are relevant. If the user attempts to  */
-/* change the IRQ, address or type of the port the ioctl fails.               */
-/******************************************************************************/
-static int
-set_serial_info( i2ChanStrPtr pCh, struct serial_struct __user *new_info )
-{
-	struct serial_struct ns;
-	int   old_flags, old_baud_divisor;
-
-	if (copy_from_user(&ns, new_info, sizeof (ns)))
-		return -EFAULT;
-
-	/*
-	 * We don't allow setserial to change IRQ, board address, type or baud
-	 * base. Also line nunber as such is meaningless but we use it for our
-	 * array index so it is fixed also.
-	 */
-	if ( (ns.irq  	    != ip2config.irq[pCh->port_index])
-	    || ((int) ns.port      != ((int) (pCh->pMyBord->i2eBase)))
-	    || (ns.baud_base != pCh->BaudBase)
-	    || (ns.line      != pCh->port_index) ) {
-		return -EINVAL;
-	}
-
-	old_flags = pCh->flags;
-	old_baud_divisor = pCh->BaudDivisor;
-
-	if ( !capable(CAP_SYS_ADMIN) ) {
-		if ( ( ns.close_delay != pCh->ClosingDelay ) ||
-		    ( (ns.flags & ~ASYNC_USR_MASK) !=
-		      (pCh->flags & ~ASYNC_USR_MASK) ) ) {
-			return -EPERM;
-		}
-
-		pCh->flags = (pCh->flags & ~ASYNC_USR_MASK) |
-			       (ns.flags & ASYNC_USR_MASK);
-		pCh->BaudDivisor = ns.custom_divisor;
-	} else {
-		pCh->flags = (pCh->flags & ~ASYNC_FLAGS) |
-			       (ns.flags & ASYNC_FLAGS);
-		pCh->BaudDivisor = ns.custom_divisor;
-		pCh->ClosingDelay = ns.close_delay * HZ/100;
-		pCh->ClosingWaitTime = ns.closing_wait * HZ/100;
-	}
-
-	if ( ( (old_flags & ASYNC_SPD_MASK) != (pCh->flags & ASYNC_SPD_MASK) )
-	    || (old_baud_divisor != pCh->BaudDivisor) ) {
-		// Invalidate speed and reset parameters
-		set_params( pCh, NULL );
-	}
-
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_set_termios()                                              */
-/* Parameters: Pointer to tty structure                                       */
-/*             Pointer to old termios structure                               */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_set_termios( PTTY tty, struct ktermios *old_termios )
-{
-	i2ChanStrPtr pCh = (i2ChanStrPtr)tty->driver_data;
-
-#ifdef IP2DEBUG_IOCTL
-	printk (KERN_DEBUG "IP2: set termios %p\n", old_termios );
-#endif
-
-	set_params( pCh, old_termios );
-}
-
-/******************************************************************************/
-/* Function:   ip2_set_line_discipline()                                      */
-/* Parameters: Pointer to tty structure                                       */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:  Does nothing                                                 */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static void
-ip2_set_line_discipline ( PTTY tty )
-{
-#ifdef IP2DEBUG_IOCTL
-	printk (KERN_DEBUG "IP2: set line discipline\n" );
-#endif
-
-	ip2trace (((i2ChanStrPtr)tty->driver_data)->port_index, ITRC_IOCTL, 16, 0 );
-
-}
-
-/******************************************************************************/
-/* Function:   SetLine Characteristics()                                      */
-/* Parameters: Pointer to channel structure                                   */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/* This routine is called to update the channel structure with the new line   */
-/* characteristics, and send the appropriate commands to the board when they  */
-/* change.                                                                    */
-/******************************************************************************/
-static void
-set_params( i2ChanStrPtr pCh, struct ktermios *o_tios )
-{
-	tcflag_t cflag, iflag, lflag;
-	char stop_char, start_char;
-	struct ktermios dummy;
-
-	lflag = pCh->pTTY->termios->c_lflag;
-	cflag = pCh->pTTY->termios->c_cflag;
-	iflag = pCh->pTTY->termios->c_iflag;
-
-	if (o_tios == NULL) {
-		dummy.c_lflag = ~lflag;
-		dummy.c_cflag = ~cflag;
-		dummy.c_iflag = ~iflag;
-		o_tios = &dummy;
-	}
-
-	{
-		switch ( cflag & CBAUD ) {
-		case B0:
-			i2QueueCommands( PTYPE_BYPASS, pCh, 100, 2, CMD_RTSDN, CMD_DTRDN);
-			pCh->dataSetOut &= ~(I2_DTR | I2_RTS);
-			i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_PAUSE(25));
-			pCh->pTTY->termios->c_cflag |= (CBAUD & o_tios->c_cflag);
-			goto service_it;
-			break;
-		case B38400:
-			/*
-			 * This is the speed that is overloaded with all the other high
-			 * speeds, depending upon the flag settings.
-			 */
-			if ( ( pCh->flags & ASYNC_SPD_MASK ) == ASYNC_SPD_HI ) {
-				pCh->speed = CBR_57600;
-			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI ) {
-				pCh->speed = CBR_115200;
-			} else if ( (pCh->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST ) {
-				pCh->speed = CBR_C1;
-			} else {
-				pCh->speed = CBR_38400;
-			}
-			break;
-		case B50:      pCh->speed = CBR_50;      break;
-		case B75:      pCh->speed = CBR_75;      break;
-		case B110:     pCh->speed = CBR_110;     break;
-		case B134:     pCh->speed = CBR_134;     break;
-		case B150:     pCh->speed = CBR_150;     break;
-		case B200:     pCh->speed = CBR_200;     break;
-		case B300:     pCh->speed = CBR_300;     break;
-		case B600:     pCh->speed = CBR_600;     break;
-		case B1200:    pCh->speed = CBR_1200;    break;
-		case B1800:    pCh->speed = CBR_1800;    break;
-		case B2400:    pCh->speed = CBR_2400;    break;
-		case B4800:    pCh->speed = CBR_4800;    break;
-		case B9600:    pCh->speed = CBR_9600;    break;
-		case B19200:   pCh->speed = CBR_19200;   break;
-		case B57600:   pCh->speed = CBR_57600;   break;
-		case B115200:  pCh->speed = CBR_115200;  break;
-		case B153600:  pCh->speed = CBR_153600;  break;
-		case B230400:  pCh->speed = CBR_230400;  break;
-		case B307200:  pCh->speed = CBR_307200;  break;
-		case B460800:  pCh->speed = CBR_460800;  break;
-		case B921600:  pCh->speed = CBR_921600;  break;
-		default:       pCh->speed = CBR_9600;    break;
-		}
-		if ( pCh->speed == CBR_C1 ) {
-			// Process the custom speed parameters.
-			int bps = pCh->BaudBase / pCh->BaudDivisor;
-			if ( bps == 921600 ) {
-				pCh->speed = CBR_921600;
-			} else {
-				bps = bps/10;
-				i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_BAUD_DEF1(bps) );
-			}
-		}
-		i2QueueCommands( PTYPE_INLINE, pCh, 100, 1, CMD_SETBAUD(pCh->speed));
-		
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 2, CMD_DTRUP, CMD_RTSUP);
-		pCh->dataSetOut |= (I2_DTR | I2_RTS);
-	}
-	if ( (CSTOPB & cflag) ^ (CSTOPB & o_tios->c_cflag)) 
-	{
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, 
-			CMD_SETSTOP( ( cflag & CSTOPB ) ? CST_2 : CST_1));
-	}
-	if (((PARENB|PARODD) & cflag) ^ ((PARENB|PARODD) & o_tios->c_cflag)) 
-	{
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1,
-			CMD_SETPAR( 
-				(cflag & PARENB ?  (cflag & PARODD ? CSP_OD : CSP_EV) : CSP_NP)
-			)
-		);
-	}
-	/* byte size and parity */
-	if ( (CSIZE & cflag)^(CSIZE & o_tios->c_cflag)) 
-	{
-		int datasize;
-		switch ( cflag & CSIZE ) {
-		case CS5: datasize = CSZ_5; break;
-		case CS6: datasize = CSZ_6; break;
-		case CS7: datasize = CSZ_7; break;
-		case CS8: datasize = CSZ_8; break;
-		default:  datasize = CSZ_5; break;	/* as per serial.c */
-		}
-		i2QueueCommands ( PTYPE_INLINE, pCh, 100, 1, CMD_SETBITS(datasize) );
-	}
-	/* Process CTS flow control flag setting */
-	if ( (cflag & CRTSCTS) ) {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100,
-						2, CMD_CTSFL_ENAB, CMD_RTSFL_ENAB);
-	} else {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100,
-						2, CMD_CTSFL_DSAB, CMD_RTSFL_DSAB);
-	}
-	//
-	// Process XON/XOFF flow control flags settings
-	//
-	stop_char = STOP_CHAR(pCh->pTTY);
-	start_char = START_CHAR(pCh->pTTY);
-
-	//////////// can't be \000
-	if (stop_char == __DISABLED_CHAR ) 
-	{
-		stop_char = ~__DISABLED_CHAR; 
-	}
-	if (start_char == __DISABLED_CHAR ) 
-	{
-		start_char = ~__DISABLED_CHAR;
-	}
-	/////////////////////////////////
-
-	if ( o_tios->c_cc[VSTART] != start_char ) 
-	{
-		i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXON(start_char));
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXON(start_char));
-	}
-	if ( o_tios->c_cc[VSTOP] != stop_char ) 
-	{
-		 i2QueueCommands(PTYPE_BYPASS, pCh, 100, 1, CMD_DEF_IXOFF(stop_char));
-		 i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DEF_OXOFF(stop_char));
-	}
-	if (stop_char == __DISABLED_CHAR ) 
-	{
-		stop_char = ~__DISABLED_CHAR;  //TEST123
-		goto no_xoff;
-	}
-	if ((iflag & (IXOFF))^(o_tios->c_iflag & (IXOFF))) 
-	{
-		if ( iflag & IXOFF ) {	// Enable XOFF output flow control
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_XON));
-		} else {	// Disable XOFF output flow control
-no_xoff:
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_OXON_OPT(COX_NONE));
-		}
-	}
-	if (start_char == __DISABLED_CHAR ) 
-	{
-		goto no_xon;
-	}
-	if ((iflag & (IXON|IXANY)) ^ (o_tios->c_iflag & (IXON|IXANY))) 
-	{
-		if ( iflag & IXON ) {
-			if ( iflag & IXANY ) { // Enable XON/XANY output flow control
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XANY));
-			} else { // Enable XON output flow control
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_XON));
-			}
-		} else { // Disable XON output flow control
-no_xon:
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_IXON_OPT(CIX_NONE));
-		}
-	}
-	if ( (iflag & ISTRIP) ^ ( o_tios->c_iflag & (ISTRIP)) ) 
-	{
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
-				CMD_ISTRIP_OPT((iflag & ISTRIP ? 1 : 0)));
-	}
-	if ( (iflag & INPCK) ^ ( o_tios->c_iflag & (INPCK)) ) 
-	{
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, 
-				CMD_PARCHK((iflag & INPCK) ? CPK_ENAB : CPK_DSAB));
-	}
-
-	if ( (iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) 
-			^	( o_tios->c_iflag & (IGNBRK|PARMRK|BRKINT|IGNPAR)) ) 
-	{
-		char brkrpt = 0;
-		char parrpt = 0;
-
-		if ( iflag & IGNBRK ) { /* Ignore breaks altogether */
-			/* Ignore breaks altogether */
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_NREP);
-		} else {
-			if ( iflag & BRKINT ) {
-				if ( iflag & PARMRK ) {
-					brkrpt = 0x0a;	// exception an inline triple
-				} else {
-					brkrpt = 0x1a;	// exception and NULL
-				}
-				brkrpt |= 0x04;	// flush input
-			} else {
-				if ( iflag & PARMRK ) {
-					brkrpt = 0x0b;	//POSIX triple \0377 \0 \0
-				} else {
-					brkrpt = 0x01;	// Null only
-				}
-			}
-			i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_BRK_REP(brkrpt));
-		} 
-
-		if (iflag & IGNPAR) {
-			parrpt = 0x20;
-													/* would be 2 for not cirrus bug */
-													/* would be 0x20 cept for cirrus bug */
-		} else {
-			if ( iflag & PARMRK ) {
-				/*
-				 * Replace error characters with 3-byte sequence (\0377,\0,char)
-				 */
-				parrpt = 0x04 ;
-				i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_ISTRIP_OPT((char)0));
-			} else {
-				parrpt = 0x03;
-			} 
-		}
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_SET_ERROR(parrpt));
-	}
-	if (cflag & CLOCAL) {
-		// Status reporting fails for DCD if this is off
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_NREP);
-		pCh->flags &= ~ASYNC_CHECK_CD;
-	} else {
-		i2QueueCommands(PTYPE_INLINE, pCh, 100, 1, CMD_DCD_REP);
-		pCh->flags	|= ASYNC_CHECK_CD;
-	}
-
-service_it:
-	i2DrainOutput( pCh, 100 );		
-}
-
-/******************************************************************************/
-/* IPL Device Section                                                         */
-/******************************************************************************/
-
-/******************************************************************************/
-/* Function:   ip2_ipl_read()                                                  */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/*             Pointer to data                                                */
-/*             Number of bytes to read                                        */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:   Ugly                                                        */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-
-static 
-ssize_t
-ip2_ipl_read(struct file *pFile, char __user *pData, size_t count, loff_t *off )
-{
-	unsigned int minor = iminor(pFile->f_path.dentry->d_inode);
-	int rc = 0;
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: read %p, %d bytes\n", pData, count );
-#endif
-
-	switch( minor ) {
-	case 0:	    // IPL device
-		rc = -EINVAL;
-		break;
-	case 1:	    // Status dump
-		rc = -EINVAL;
-		break;
-	case 2:	    // Ping device
-		rc = -EINVAL;
-		break;
-	case 3:	    // Trace device
-		rc = DumpTraceBuffer ( pData, count );
-		break;
-	case 4:	    // Trace device
-		rc = DumpFifoBuffer ( pData, count );
-		break;
-	default:
-		rc = -ENODEV;
-		break;
-	}
-	return rc;
-}
-
-static int
-DumpFifoBuffer ( char __user *pData, int count )
-{
-#ifdef DEBUG_FIFO
-	int rc;
-	rc = copy_to_user(pData, DBGBuf, count);
-
-	printk(KERN_DEBUG "Last index %d\n", I );
-
-	return count;
-#endif	/* DEBUG_FIFO */
-	return 0;
-}
-
-static int
-DumpTraceBuffer ( char __user *pData, int count )
-{
-#ifdef IP2DEBUG_TRACE
-	int rc;
-	int dumpcount;
-	int chunk;
-	int *pIndex = (int __user *)pData;
-
-	if ( count < (sizeof(int) * 6) ) {
-		return -EIO;
-	}
-	rc = put_user(tracewrap, pIndex );
-	rc = put_user(TRACEMAX, ++pIndex );
-	rc = put_user(tracestrip, ++pIndex );
-	rc = put_user(tracestuff, ++pIndex );
-	pData += sizeof(int) * 6;
-	count -= sizeof(int) * 6;
-
-	dumpcount = tracestuff - tracestrip;
-	if ( dumpcount < 0 ) {
-		dumpcount += TRACEMAX;
-	}
-	if ( dumpcount > count ) {
-		dumpcount = count;
-	}
-	chunk = TRACEMAX - tracestrip;
-	if ( dumpcount > chunk ) {
-		rc = copy_to_user(pData, &tracebuf[tracestrip],
-			      chunk * sizeof(tracebuf[0]) );
-		pData += chunk * sizeof(tracebuf[0]);
-		tracestrip = 0;
-		chunk = dumpcount - chunk;
-	} else {
-		chunk = dumpcount;
-	}
-	rc = copy_to_user(pData, &tracebuf[tracestrip],
-		      chunk * sizeof(tracebuf[0]) );
-	tracestrip += chunk;
-	tracewrap = 0;
-
-	rc = put_user(tracestrip, ++pIndex );
-	rc = put_user(tracestuff, ++pIndex );
-
-	return dumpcount;
-#else
-	return 0;
-#endif
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_write()                                                 */
-/* Parameters:                                                                */
-/*             Pointer to file structure                                      */
-/*             Pointer to data                                                */
-/*             Number of bytes to write                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static ssize_t
-ip2_ipl_write(struct file *pFile, const char __user *pData, size_t count, loff_t *off)
-{
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: write %p, %d bytes\n", pData, count );
-#endif
-	return 0;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_ioctl()                                                */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/*             Command                                                        */
-/*             Argument                                                       */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static long
-ip2_ipl_ioctl (struct file *pFile, UINT cmd, ULONG arg )
-{
-	unsigned int iplminor = iminor(pFile->f_path.dentry->d_inode);
-	int rc = 0;
-	void __user *argp = (void __user *)arg;
-	ULONG __user *pIndex = argp;
-	i2eBordStrPtr pB = i2BoardPtrTable[iplminor / 4];
-	i2ChanStrPtr pCh;
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: ioctl cmd %d, arg %ld\n", cmd, arg );
-#endif
-
-	mutex_lock(&ip2_mutex);
-
-	switch ( iplminor ) {
-	case 0:	    // IPL device
-		rc = -EINVAL;
-		break;
-	case 1:	    // Status dump
-	case 5:
-	case 9:
-	case 13:
-		switch ( cmd ) {
-		case 64:	/* Driver - ip2stat */
-			rc = put_user(-1, pIndex++ );
-			rc = put_user(irq_counter, pIndex++  );
-			rc = put_user(bh_counter, pIndex++  );
-			break;
-
-		case 65:	/* Board  - ip2stat */
-			if ( pB ) {
-				rc = copy_to_user(argp, pB, sizeof(i2eBordStr));
-				rc = put_user(inb(pB->i2eStatus),
-					(ULONG __user *)(arg + (ULONG)(&pB->i2eStatus) - (ULONG)pB ) );
-			} else {
-				rc = -ENODEV;
-			}
-			break;
-
-		default:
-			if (cmd < IP2_MAX_PORTS) {
-				pCh = DevTable[cmd];
-				if ( pCh )
-				{
-					rc = copy_to_user(argp, pCh, sizeof(i2ChanStr));
-					if (rc)
-						rc = -EFAULT;
-				} else {
-					rc = -ENODEV;
-				}
-			} else {
-				rc = -EINVAL;
-			}
-		}
-		break;
-
-	case 2:	    // Ping device
-		rc = -EINVAL;
-		break;
-	case 3:	    // Trace device
-		/*
-		 * akpm: This used to write a whole bunch of function addresses
-		 * to userspace, which generated lots of put_user() warnings.
-		 * I killed it all.  Just return "success" and don't do
-		 * anything.
-		 */
-		if (cmd == 1)
-			rc = 0;
-		else
-			rc = -EINVAL;
-		break;
-
-	default:
-		rc = -ENODEV;
-		break;
-	}
-	mutex_unlock(&ip2_mutex);
-	return rc;
-}
-
-/******************************************************************************/
-/* Function:   ip2_ipl_open()                                                 */
-/* Parameters: Pointer to device inode                                        */
-/*             Pointer to file structure                                      */
-/* Returns:    Success or failure                                             */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-static int
-ip2_ipl_open( struct inode *pInode, struct file *pFile )
-{
-
-#ifdef IP2DEBUG_IPL
-	printk (KERN_DEBUG "IP2IPL: open\n" );
-#endif
-	return 0;
-}
-
-static int
-proc_ip2mem_show(struct seq_file *m, void *v)
-{
-	i2eBordStrPtr  pB;
-	i2ChanStrPtr  pCh;
-	PTTY tty;
-	int i;
-
-#define FMTLINE	"%3d: 0x%08x 0x%08x 0%011o 0%011o\n"
-#define FMTLIN2	"     0x%04x 0x%04x tx flow 0x%x\n"
-#define FMTLIN3	"     0x%04x 0x%04x rc flow\n"
-
-	seq_printf(m,"\n");
-
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		pB = i2BoardPtrTable[i];
-		if ( pB ) {
-			seq_printf(m,"board %d:\n",i);
-			seq_printf(m,"\tFifo rem: %d mty: %x outM %x\n",
-				pB->i2eFifoRemains,pB->i2eWaitingForEmptyFifo,pB->i2eOutMailWaiting);
-		}
-	}
-
-	seq_printf(m,"#: tty flags, port flags,     cflags,     iflags\n");
-	for (i=0; i < IP2_MAX_PORTS; i++) {
-		pCh = DevTable[i];
-		if (pCh) {
-			tty = pCh->pTTY;
-			if (tty && tty->count) {
-				seq_printf(m,FMTLINE,i,(int)tty->flags,pCh->flags,
-									tty->termios->c_cflag,tty->termios->c_iflag);
-
-				seq_printf(m,FMTLIN2,
-						pCh->outfl.asof,pCh->outfl.room,pCh->channelNeeds);
-				seq_printf(m,FMTLIN3,pCh->infl.asof,pCh->infl.room);
-			}
-		}
-	}
-	return 0;
-}
-
-static int proc_ip2mem_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, proc_ip2mem_show, NULL);
-}
-
-static const struct file_operations ip2mem_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= proc_ip2mem_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * This is the handler for /proc/tty/driver/ip2
- *
- * This stretch of code has been largely plagerized from at least three
- * different sources including ip2mkdev.c and a couple of other drivers.
- * The bugs are all mine.  :-)	=mhw=
- */
-static int ip2_proc_show(struct seq_file *m, void *v)
-{
-	int	i, j, box;
-	int	boxes = 0;
-	int	ports = 0;
-	int	tports = 0;
-	i2eBordStrPtr  pB;
-	char *sep;
-
-	seq_printf(m, "ip2info: 1.0 driver: %s\n", pcVersion);
-	seq_printf(m, "Driver: SMajor=%d CMajor=%d IMajor=%d MaxBoards=%d MaxBoxes=%d MaxPorts=%d\n",
-			IP2_TTY_MAJOR, IP2_CALLOUT_MAJOR, IP2_IPL_MAJOR,
-			IP2_MAX_BOARDS, ABS_MAX_BOXES, ABS_BIGGEST_BOX);
-
-	for( i = 0; i < IP2_MAX_BOARDS; ++i ) {
-		/* This need to be reset for a board by board count... */
-		boxes = 0;
-		pB = i2BoardPtrTable[i];
-		if( pB ) {
-			switch( pB->i2ePom.e.porID & ~POR_ID_RESERVED ) 
-			{
-			case POR_ID_FIIEX:
-				seq_printf(m, "Board %d: EX ports=", i);
-				sep = "";
-				for( box = 0; box < ABS_MAX_BOXES; ++box )
-				{
-					ports = 0;
-
-					if( pB->i2eChannelMap[box] != 0 ) ++boxes;
-					for( j = 0; j < ABS_BIGGEST_BOX; ++j ) 
-					{
-						if( pB->i2eChannelMap[box] & 1<< j ) {
-							++ports;
-						}
-					}
-					seq_printf(m, "%s%d", sep, ports);
-					sep = ",";
-					tports += ports;
-				}
-				seq_printf(m, " boxes=%d width=%d", boxes, pB->i2eDataWidth16 ? 16 : 8);
-				break;
-
-			case POR_ID_II_4:
-				seq_printf(m, "Board %d: ISA-4 ports=4 boxes=1", i);
-				tports = ports = 4;
-				break;
-
-			case POR_ID_II_8:
-				seq_printf(m, "Board %d: ISA-8-std ports=8 boxes=1", i);
-				tports = ports = 8;
-				break;
-
-			case POR_ID_II_8R:
-				seq_printf(m, "Board %d: ISA-8-RJ11 ports=8 boxes=1", i);
-				tports = ports = 8;
-				break;
-
-			default:
-				seq_printf(m, "Board %d: unknown", i);
-				/* Don't try and probe for minor numbers */
-				tports = ports = 0;
-			}
-
-		} else {
-			/* Don't try and probe for minor numbers */
-			seq_printf(m, "Board %d: vacant", i);
-			tports = ports = 0;
-		}
-
-		if( tports ) {
-			seq_puts(m, " minors=");
-			sep = "";
-			for ( box = 0; box < ABS_MAX_BOXES; ++box )
-			{
-				for ( j = 0; j < ABS_BIGGEST_BOX; ++j )
-				{
-					if ( pB->i2eChannelMap[box] & (1 << j) )
-					{
-						seq_printf(m, "%s%d", sep,
-							j + ABS_BIGGEST_BOX *
-							(box+i*ABS_MAX_BOXES));
-						sep = ",";
-					}
-				}
-			}
-		}
-		seq_putc(m, '\n');
-	}
-	return 0;
- }
-
-static int ip2_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, ip2_proc_show, NULL);
-}
-
-static const struct file_operations ip2_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= ip2_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
- 
-/******************************************************************************/
-/* Function:   ip2trace()                                                     */
-/* Parameters: Value to add to trace buffer                                   */
-/* Returns:    Nothing                                                        */
-/*                                                                            */
-/* Description:                                                               */
-/*                                                                            */
-/*                                                                            */
-/******************************************************************************/
-#ifdef IP2DEBUG_TRACE
-void
-ip2trace (unsigned short pn, unsigned char cat, unsigned char label, unsigned long codes, ...)
-{
-	long flags;
-	unsigned long *pCode = &codes;
-	union ip2breadcrumb bc;
-	i2ChanStrPtr  pCh;
-
-
-	tracebuf[tracestuff++] = jiffies;
-	if ( tracestuff == TRACEMAX ) {
-		tracestuff = 0;
-	}
-	if ( tracestuff == tracestrip ) {
-		if ( ++tracestrip == TRACEMAX ) {
-			tracestrip = 0;
-		}
-		++tracewrap;
-	}
-
-	bc.hdr.port  = 0xff & pn;
-	bc.hdr.cat   = cat;
-	bc.hdr.codes = (unsigned char)( codes & 0xff );
-	bc.hdr.label = label;
-	tracebuf[tracestuff++] = bc.value;
-
-	for (;;) {
-		if ( tracestuff == TRACEMAX ) {
-			tracestuff = 0;
-		}
-		if ( tracestuff == tracestrip ) {
-			if ( ++tracestrip == TRACEMAX ) {
-				tracestrip = 0;
-			}
-			++tracewrap;
-		}
-
-		if ( !codes-- )
-			break;
-
-		tracebuf[tracestuff++] = *++pCode;
-	}
-}
-#endif
-
-
-MODULE_LICENSE("GPL");
-
-static struct pci_device_id ip2main_pci_tbl[] __devinitdata __used = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_COMPUTONE, PCI_DEVICE_ID_COMPUTONE_IP2EX) },
-	{ }
-};
-
-MODULE_DEVICE_TABLE(pci, ip2main_pci_tbl);
-
-/*(DEBLOBBED)*/
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/ip2trace.h linux-libre-2.6.39-gnu/drivers/char/ip2/ip2trace.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/ip2trace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/ip2trace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,42 +0,0 @@
-
-//
-union ip2breadcrumb 
-{
-	struct { 
-		unsigned char port, cat, codes, label;
-	} __attribute__ ((packed)) hdr;
-	unsigned long value;
-};
-
-#define ITRC_NO_PORT 	0xFF
-#define CHANN	(pCh->port_index)
-
-#define	ITRC_ERROR	'!'
-#define	ITRC_INIT 	'A'
-#define	ITRC_OPEN	'B'
-#define	ITRC_CLOSE	'C'
-#define	ITRC_DRAIN	'D'
-#define	ITRC_IOCTL	'E'
-#define	ITRC_FLUSH	'F'
-#define	ITRC_STATUS	'G'
-#define	ITRC_HANGUP	'H'
-#define	ITRC_INTR 	'I'
-#define	ITRC_SFLOW	'J'
-#define	ITRC_SBCMD	'K'
-#define	ITRC_SICMD	'L'
-#define	ITRC_MODEM	'M'
-#define	ITRC_INPUT	'N'
-#define	ITRC_OUTPUT	'O'
-#define	ITRC_PUTC	'P'
-#define	ITRC_QUEUE	'Q'
-#define	ITRC_STFLW	'R'
-#define	ITRC_SFIFO	'S'
-#define	ITRC_VERIFY	'V'
-#define	ITRC_WRITE	'W'
-
-#define	ITRC_ENTER	0x00
-#define	ITRC_RETURN	0xFF
-
-#define	ITRC_QUEUE_ROOM	2
-#define	ITRC_QUEUE_CMD	6
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/ip2types.h linux-libre-2.6.39-gnu/drivers/char/ip2/ip2types.h
--- linux-libre-2.6.38-gnu/drivers/char/ip2/ip2types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/ip2types.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*******************************************************************************
-*
-*   (c) 1998 by Computone Corporation
-*
-********************************************************************************
-*
-*
-*   PACKAGE:     Linux tty Device Driver for IntelliPort II family of multiport
-*                serial I/O controllers.
-*
-*   DESCRIPTION: Driver constants and type definitions.
-*
-*   NOTES:
-*
-*******************************************************************************/
-#ifndef IP2TYPES_H
-#define IP2TYPES_H
-
-//*************
-//* Constants *
-//*************
-
-// Define some limits for this driver. Ports per board is a hardware limitation
-// that will not change. Current hardware limits this to 64 ports per board.
-// Boards per driver is a self-imposed limit.
-//
-#define IP2_MAX_BOARDS        4
-#define IP2_PORTS_PER_BOARD   ABS_MOST_PORTS
-#define IP2_MAX_PORTS         (IP2_MAX_BOARDS*IP2_PORTS_PER_BOARD)
-
-#define ISA    0
-#define PCI    1
-#define EISA   2
-
-//********************
-//* Type Definitions *
-//********************
-
-typedef struct tty_struct *   PTTY;
-typedef wait_queue_head_t   PWAITQ;
-
-typedef unsigned char         UCHAR;
-typedef unsigned int          UINT;
-typedef unsigned short        USHORT;
-typedef unsigned long         ULONG;
-
-typedef struct 
-{
-	short irq[IP2_MAX_BOARDS]; 
-	unsigned short addr[IP2_MAX_BOARDS];
-	int type[IP2_MAX_BOARDS];
-#ifdef CONFIG_PCI
-	struct pci_dev *pci_dev[IP2_MAX_BOARDS];
-#endif
-} ip2config_t;
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/ip2/Makefile linux-libre-2.6.39-gnu/drivers/char/ip2/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/ip2/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ip2/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#
-# Makefile for the Computone IntelliPort Plus Driver
-#
-
-obj-$(CONFIG_COMPUTONE)         += ip2.o
-
-ip2-y			:= ip2main.o
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ipmi/ipmi_poweroff.c linux-libre-2.6.39-gnu/drivers/char/ipmi/ipmi_poweroff.c
--- linux-libre-2.6.38-gnu/drivers/char/ipmi/ipmi_poweroff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ipmi/ipmi_poweroff.c	2011-05-19 00:06:34.000000000 -0400
@@ -122,7 +122,7 @@
 
 
 /*
- * Code to send a message and wait for the reponse.
+ * Code to send a message and wait for the response.
  */
 
 static void receive_handler(struct ipmi_recv_msg *recv_msg, void *handler_data)
diff -druN linux-libre-2.6.38-gnu/drivers/char/ipmi/ipmi_si_intf.c linux-libre-2.6.39-gnu/drivers/char/ipmi/ipmi_si_intf.c
--- linux-libre-2.6.38-gnu/drivers/char/ipmi/ipmi_si_intf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ipmi/ipmi_si_intf.c	2011-05-19 00:06:34.000000000 -0400
@@ -66,13 +66,10 @@
 #include <linux/string.h>
 #include <linux/ctype.h>
 #include <linux/pnp.h>
-
-#ifdef CONFIG_PPC_OF
 #include <linux/of_device.h>
 #include <linux/of_platform.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#endif
 
 #define PFX "ipmi_si: "
 
@@ -116,13 +113,7 @@
 
 #define DEVICE_NAME "ipmi_si"
 
-static struct platform_driver ipmi_driver = {
-	.driver = {
-		.name = DEVICE_NAME,
-		.bus = &platform_bus_type
-	}
-};
-
+static struct platform_driver ipmi_driver;
 
 /*
  * Indexes into stats[] in smi_info below.
@@ -308,9 +299,6 @@
 #ifdef CONFIG_ACPI
 static int pnp_registered;
 #endif
-#ifdef CONFIG_PPC_OF
-static int of_registered;
-#endif
 
 static unsigned int kipmid_max_busy_us[SI_MAX_PARMS];
 static int num_max_busy_us;
@@ -351,7 +339,7 @@
 		cCode = IPMI_ERR_UNSPECIFIED;
 	/* else use it as is */
 
-	/* Make it a reponse */
+	/* Make it a response */
 	msg->rsp[0] = msg->data[0] | 4;
 	msg->rsp[1] = msg->data[1];
 	msg->rsp[2] = cCode;
@@ -1868,8 +1856,9 @@
 	return rv;
 }
 
-static void __devinit hardcode_find_bmc(void)
+static int __devinit hardcode_find_bmc(void)
 {
+	int ret = -ENODEV;
 	int             i;
 	struct smi_info *info;
 
@@ -1879,7 +1868,7 @@
 
 		info = smi_info_alloc();
 		if (!info)
-			return;
+			return -ENOMEM;
 
 		info->addr_source = SI_HARDCODED;
 		printk(KERN_INFO PFX "probing via hardcoded address\n");
@@ -1932,10 +1921,12 @@
 		if (!add_smi(info)) {
 			if (try_smi_init(info))
 				cleanup_one_si(info);
+			ret = 0;
 		} else {
 			kfree(info);
 		}
 	}
+	return ret;
 }
 
 #ifdef CONFIG_ACPI
@@ -2563,11 +2554,11 @@
 };
 #endif /* CONFIG_PCI */
 
-
-#ifdef CONFIG_PPC_OF
-static int __devinit ipmi_of_probe(struct platform_device *dev,
-			 const struct of_device_id *match)
+static struct of_device_id ipmi_match[];
+static int __devinit ipmi_probe(struct platform_device *dev)
 {
+#ifdef CONFIG_OF
+	const struct of_device_id *match;
 	struct smi_info *info;
 	struct resource resource;
 	const __be32 *regsize, *regspacing, *regshift;
@@ -2577,6 +2568,10 @@
 
 	dev_info(&dev->dev, "probing via device tree\n");
 
+	match = of_match_device(ipmi_match, &dev->dev);
+	if (!match)
+		return -EINVAL;
+
 	ret = of_address_to_resource(np, 0, &resource);
 	if (ret) {
 		dev_warn(&dev->dev, PFX "invalid address from OF\n");
@@ -2640,13 +2635,15 @@
 		kfree(info);
 		return -EBUSY;
 	}
-
+#endif
 	return 0;
 }
 
-static int __devexit ipmi_of_remove(struct platform_device *dev)
+static int __devexit ipmi_remove(struct platform_device *dev)
 {
+#ifdef CONFIG_OF
 	cleanup_one_si(dev_get_drvdata(&dev->dev));
+#endif
 	return 0;
 }
 
@@ -2661,16 +2658,15 @@
 	{},
 };
 
-static struct of_platform_driver ipmi_of_platform_driver = {
+static struct platform_driver ipmi_driver = {
 	.driver = {
-		.name = "ipmi",
+		.name = DEVICE_NAME,
 		.owner = THIS_MODULE,
 		.of_match_table = ipmi_match,
 	},
-	.probe		= ipmi_of_probe,
-	.remove		= __devexit_p(ipmi_of_remove),
+	.probe		= ipmi_probe,
+	.remove		= __devexit_p(ipmi_remove),
 };
-#endif /* CONFIG_PPC_OF */
 
 static int wait_for_msg_done(struct smi_info *smi_info)
 {
@@ -2934,7 +2930,7 @@
 {
 	struct ipmi_smi_msg *msg = smi_info->curr_msg;
 
-	/* Make it a reponse */
+	/* Make it a response */
 	msg->rsp[0] = msg->data[0] | 4;
 	msg->rsp[1] = msg->data[1];
 	msg->rsp[2] = CANNOT_RETURN_REQUESTED_LENGTH;
@@ -3348,8 +3344,7 @@
 		return 0;
 	initialized = 1;
 
-	/* Register the device drivers. */
-	rv = driver_register(&ipmi_driver.driver);
+	rv = platform_driver_register(&ipmi_driver);
 	if (rv) {
 		printk(KERN_ERR PFX "Unable to register driver: %d\n", rv);
 		return rv;
@@ -3373,15 +3368,9 @@
 
 	printk(KERN_INFO "IPMI System Interface driver.\n");
 
-	hardcode_find_bmc();
-
 	/* If the user gave us a device, they presumably want us to use it */
-	mutex_lock(&smi_infos_lock);
-	if (!list_empty(&smi_infos)) {
-		mutex_unlock(&smi_infos_lock);
+	if (!hardcode_find_bmc())
 		return 0;
-	}
-	mutex_unlock(&smi_infos_lock);
 
 #ifdef CONFIG_PCI
 	rv = pci_register_driver(&ipmi_pci_driver);
@@ -3404,11 +3393,6 @@
 	spmi_find_bmc();
 #endif
 
-#ifdef CONFIG_PPC_OF
-	of_register_platform_driver(&ipmi_of_platform_driver);
-	of_registered = 1;
-#endif
-
 	/* We prefer devices with interrupts, but in the case of a machine
 	   with multiple BMCs we assume that there will be several instances
 	   of a given type so if we succeed in registering a type then also
@@ -3540,7 +3524,7 @@
 	kfree(to_clean);
 }
 
-static void __exit cleanup_ipmi_si(void)
+static void cleanup_ipmi_si(void)
 {
 	struct smi_info *e, *tmp_e;
 
@@ -3556,17 +3540,12 @@
 		pnp_unregister_driver(&ipmi_pnp_driver);
 #endif
 
-#ifdef CONFIG_PPC_OF
-	if (of_registered)
-		of_unregister_platform_driver(&ipmi_of_platform_driver);
-#endif
+	platform_driver_unregister(&ipmi_driver);
 
 	mutex_lock(&smi_infos_lock);
 	list_for_each_entry_safe(e, tmp_e, &smi_infos, link)
 		cleanup_one_si(e);
 	mutex_unlock(&smi_infos_lock);
-
-	driver_unregister(&ipmi_driver.driver);
 }
 module_exit(cleanup_ipmi_si);
 
diff -druN linux-libre-2.6.38-gnu/drivers/char/isicom.c linux-libre-2.6.39-gnu/drivers/char/isicom.c
--- linux-libre-2.6.38-gnu/drivers/char/isicom.c	2012-03-24 01:00:04.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/isicom.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1732 +0,0 @@
-/*
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the GNU General Public License
- *	as published by the Free Software Foundation; either version
- *	2 of the License, or (at your option) any later version.
- *
- *	Original driver code supplied by Multi-Tech
- *
- *	Changes
- *	1/9/98	alan@lxorguk.ukuu.org.uk
- *					Merge to 2.0.x kernel tree
- *					Obtain and use official major/minors
- *					Loader switched to a misc device
- *					(fixed range check bug as a side effect)
- *					Printk clean up
- *	9/12/98	alan@lxorguk.ukuu.org.uk
- *					Rough port to 2.1.x
- *
- *	10/6/99 sameer			Merged the ISA and PCI drivers to
- *					a new unified driver.
- *
- *	3/9/99	sameer			Added support for ISI4616 cards.
- *
- *	16/9/99	sameer			We do not force RTS low anymore.
- *					This is to prevent the firmware
- *					from getting confused.
- *
- *	26/10/99 sameer			Cosmetic changes:The driver now
- *					dumps the Port Count information
- *					along with I/O address and IRQ.
- *
- *	13/12/99 sameer			Fixed the problem with IRQ sharing.
- *
- *	10/5/00  sameer			Fixed isicom_shutdown_board()
- *					to not lower DTR on all the ports
- *					when the last port on the card is
- *					closed.
- *
- *	10/5/00  sameer			Signal mask setup command added
- *					to  isicom_setup_port and
- *					isicom_shutdown_port.
- *
- *	24/5/00  sameer			The driver is now SMP aware.
- *
- *
- *	27/11/00 Vinayak P Risbud	Fixed the Driver Crash Problem
- *
- *
- *	03/01/01  anil .s		Added support for resetting the
- *					internal modems on ISI cards.
- *
- *	08/02/01  anil .s		Upgraded the driver for kernel
- *					2.4.x
- *
- *	11/04/01  Kevin			Fixed firmware load problem with
- *					ISIHP-4X card
- *
- *	30/04/01  anil .s		Fixed the remote login through
- *					ISI port problem. Now the link
- *					does not go down before password
- *					prompt.
- *
- *	03/05/01  anil .s		Fixed the problem with IRQ sharing
- *					among ISI-PCI cards.
- *
- *	03/05/01  anil .s		Added support to display the version
- *					info during insmod as well as module
- *					listing by lsmod.
- *
- *	10/05/01  anil .s		Done the modifications to the source
- *					file and Install script so that the
- *					same installation can be used for
- *					2.2.x and 2.4.x kernel.
- *
- *	06/06/01  anil .s		Now we drop both dtr and rts during
- *					shutdown_port as well as raise them
- *					during isicom_config_port.
- *
- *	09/06/01 acme@conectiva.com.br	use capable, not suser, do
- *					restore_flags on failure in
- *					isicom_send_break, verify put_user
- *					result
- *
- *	11/02/03  ranjeeth		Added support for 230 Kbps and 460 Kbps
- *					Baud index extended to 21
- *
- *	20/03/03  ranjeeth		Made to work for Linux Advanced server.
- *					Taken care of license warning.
- *
- *	10/12/03  Ravindra		Made to work for Fedora Core 1 of
- *					Red Hat Distribution
- *
- *	06/01/05  Alan Cox 		Merged the ISI and base kernel strands
- *					into a single 2.6 driver
- *
- *	***********************************************************
- *
- *	To use this driver you also need the support package. You
- *	can find this in RPM format on
- *		ftp://ftp.linux.org.uk/pub/linux/alan
- *
- *	You can find the original tools for this direct from Multitech
- *		ftp://ftp.multitech.com/ISI-Cards/
- *
- *	Having installed the cards the module options (/etc/modprobe.conf)
- *
- *	options isicom   io=card1,card2,card3,card4 irq=card1,card2,card3,card4
- *
- *	Omit those entries for boards you don't have installed.
- *
- *	TODO
- *		Merge testing
- *		64-bit verification
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/module.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/termios.h>
-#include <linux/fs.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/timer.h>
-#include <linux/delay.h>
-#include <linux/ioport.h>
-#include <linux/slab.h>
-
-#include <linux/uaccess.h>
-#include <linux/io.h>
-#include <asm/system.h>
-
-#include <linux/pci.h>
-
-#include <linux/isicom.h>
-
-#define InterruptTheCard(base) outw(0, (base) + 0xc)
-#define ClearInterrupt(base) inw((base) + 0x0a)
-
-#ifdef DEBUG
-#define isicom_paranoia_check(a, b, c) __isicom_paranoia_check((a), (b), (c))
-#else
-#define isicom_paranoia_check(a, b, c) 0
-#endif
-
-static int isicom_probe(struct pci_dev *, const struct pci_device_id *);
-static void __devexit isicom_remove(struct pci_dev *);
-
-static struct pci_device_id isicom_pci_tbl[] = {
-	{ PCI_DEVICE(VENDOR_ID, 0x2028) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2051) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2052) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2053) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2054) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2055) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2056) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2057) },
-	{ PCI_DEVICE(VENDOR_ID, 0x2058) },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, isicom_pci_tbl);
-
-static struct pci_driver isicom_driver = {
-	.name		= "isicom",
-	.id_table	= isicom_pci_tbl,
-	.probe		= isicom_probe,
-	.remove		= __devexit_p(isicom_remove)
-};
-
-static int prev_card = 3;	/*	start servicing isi_card[0]	*/
-static struct tty_driver *isicom_normal;
-
-static void isicom_tx(unsigned long _data);
-static void isicom_start(struct tty_struct *tty);
-
-static DEFINE_TIMER(tx, isicom_tx, 0, 0);
-
-/*   baud index mappings from linux defns to isi */
-
-static signed char linuxb_to_isib[] = {
-	-1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 11, 13, 15, 16, 17, 18, 19, 20, 21
-};
-
-struct	isi_board {
-	unsigned long		base;
-	int			irq;
-	unsigned char		port_count;
-	unsigned short		status;
-	unsigned short		port_status; /* each bit for each port */
-	unsigned short		shift_count;
-	struct isi_port		*ports;
-	signed char		count;
-	spinlock_t		card_lock; /* Card wide lock 11/5/00 -sameer */
-	unsigned long		flags;
-	unsigned int		index;
-};
-
-struct	isi_port {
-	unsigned short		magic;
-	struct tty_port		port;
-	u16			channel;
-	u16			status;
-	struct isi_board	*card;
-	unsigned char		*xmit_buf;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-};
-
-static struct isi_board isi_card[BOARD_COUNT];
-static struct isi_port  isi_ports[PORT_COUNT];
-
-/*
- *	Locking functions for card level locking. We need to own both
- *	the kernel lock for the card and have the card in a position that
- *	it wants to talk.
- */
-
-static inline int WaitTillCardIsFree(unsigned long base)
-{
-	unsigned int count = 0;
-	unsigned int a = in_atomic(); /* do we run under spinlock? */
-
-	while (!(inw(base + 0xe) & 0x1) && count++ < 100)
-		if (a)
-			mdelay(1);
-		else
-			msleep(1);
-
-	return !(inw(base + 0xe) & 0x1);
-}
-
-static int lock_card(struct isi_board *card)
-{
-	unsigned long base = card->base;
-	unsigned int retries, a;
-
-	for (retries = 0; retries < 10; retries++) {
-		spin_lock_irqsave(&card->card_lock, card->flags);
-		for (a = 0; a < 10; a++) {
-			if (inw(base + 0xe) & 0x1)
-				return 1;
-			udelay(10);
-		}
-		spin_unlock_irqrestore(&card->card_lock, card->flags);
-		msleep(10);
-	}
-	pr_warning("Failed to lock Card (0x%lx)\n", card->base);
-
-	return 0;	/* Failed to acquire the card! */
-}
-
-static void unlock_card(struct isi_board *card)
-{
-	spin_unlock_irqrestore(&card->card_lock, card->flags);
-}
-
-/*
- *  ISI Card specific ops ...
- */
-
-/* card->lock HAS to be held */
-static void raise_dtr(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0504, base);
-	InterruptTheCard(base);
-	port->status |= ISI_DTR;
-}
-
-/* card->lock HAS to be held */
-static inline void drop_dtr(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0404, base);
-	InterruptTheCard(base);
-	port->status &= ~ISI_DTR;
-}
-
-/* card->lock HAS to be held */
-static inline void raise_rts(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0a04, base);
-	InterruptTheCard(base);
-	port->status |= ISI_RTS;
-}
-
-/* card->lock HAS to be held */
-static inline void drop_rts(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0804, base);
-	InterruptTheCard(base);
-	port->status &= ~ISI_RTS;
-}
-
-/* card->lock MUST NOT be held */
-
-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;
-	unsigned long base = card->base;
-	u16 channel = ip->channel;
-
-	if (!lock_card(card))
-		return;
-
-	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);
-}
-
-/* card->lock HAS to be held */
-static void drop_dtr_rts(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-	u16 channel = port->channel;
-
-	if (WaitTillCardIsFree(base))
-		return;
-
-	outw(0x8000 | (channel << card->shift_count) | 0x02, base);
-	outw(0x0c04, base);
-	InterruptTheCard(base);
-	port->status &= ~(ISI_RTS | ISI_DTR);
-}
-
-/*
- *	ISICOM Driver specific routines ...
- *
- */
-
-static inline int __isicom_paranoia_check(struct isi_port const *port,
-	char *name, const char *routine)
-{
-	if (!port) {
-		pr_warning("Warning: bad isicom magic for dev %s in %s.\n",
-			   name, routine);
-		return 1;
-	}
-	if (port->magic != ISICOM_MAGIC) {
-		pr_warning("Warning: NULL isicom port for dev %s in %s.\n",
-			   name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-
-/*
- *	Transmitter.
- *
- *	We shovel data into the card buffers on a regular basis. The card
- *	will do the rest of the work for us.
- */
-
-static void isicom_tx(unsigned long _data)
-{
-	unsigned long flags, base;
-	unsigned int retries;
-	short count = (BOARD_COUNT-1), card;
-	short txcount, wrd, residue, word_count, cnt;
-	struct isi_port *port;
-	struct tty_struct *tty;
-
-	/*	find next active board	*/
-	card = (prev_card + 1) & 0x0003;
-	while (count-- > 0) {
-		if (isi_card[card].status & BOARD_ACTIVE)
-			break;
-		card = (card + 1) & 0x0003;
-	}
-	if (!(isi_card[card].status & BOARD_ACTIVE))
-		goto sched_again;
-
-	prev_card = card;
-
-	count = isi_card[card].port_count;
-	port = isi_card[card].ports;
-	base = isi_card[card].base;
-
-	spin_lock_irqsave(&isi_card[card].card_lock, flags);
-	for (retries = 0; retries < 100; retries++) {
-		if (inw(base + 0xe) & 0x1)
-			break;
-		udelay(2);
-	}
-	if (retries >= 100)
-		goto unlock;
-
-	tty = tty_port_tty_get(&port->port);
-	if (tty == NULL)
-		goto put_unlock;
-
-	for (; count > 0; count--, port++) {
-		/* port not active or tx disabled to force flow control */
-		if (!(port->port.flags & ASYNC_INITIALIZED) ||
-				!(port->status & ISI_TXOK))
-			continue;
-
-		txcount = min_t(short, TX_SIZE, port->xmit_cnt);
-		if (txcount <= 0 || tty->stopped || tty->hw_stopped)
-			continue;
-
-		if (!(inw(base + 0x02) & (1 << port->channel)))
-			continue;
-
-		pr_debug("txing %d bytes, port%d.\n",
-			 txcount, port->channel + 1);
-		outw((port->channel << isi_card[card].shift_count) | txcount,
-			base);
-		residue = NO;
-		wrd = 0;
-		while (1) {
-			cnt = min_t(int, txcount, (SERIAL_XMIT_SIZE
-					- port->xmit_tail));
-			if (residue == YES) {
-				residue = NO;
-				if (cnt > 0) {
-					wrd |= (port->port.xmit_buf[port->xmit_tail]
-									<< 8);
-					port->xmit_tail = (port->xmit_tail + 1)
-						& (SERIAL_XMIT_SIZE - 1);
-					port->xmit_cnt--;
-					txcount--;
-					cnt--;
-					outw(wrd, base);
-				} else {
-					outw(wrd, base);
-					break;
-				}
-			}
-			if (cnt <= 0)
-				break;
-			word_count = cnt >> 1;
-			outsw(base, port->port.xmit_buf+port->xmit_tail, word_count);
-			port->xmit_tail = (port->xmit_tail
-				+ (word_count << 1)) & (SERIAL_XMIT_SIZE - 1);
-			txcount -= (word_count << 1);
-			port->xmit_cnt -= (word_count << 1);
-			if (cnt & 0x0001) {
-				residue = YES;
-				wrd = port->port.xmit_buf[port->xmit_tail];
-				port->xmit_tail = (port->xmit_tail + 1)
-					& (SERIAL_XMIT_SIZE - 1);
-				port->xmit_cnt--;
-				txcount--;
-			}
-		}
-
-		InterruptTheCard(base);
-		if (port->xmit_cnt <= 0)
-			port->status &= ~ISI_TXOK;
-		if (port->xmit_cnt <= WAKEUP_CHARS)
-			tty_wakeup(tty);
-	}
-
-put_unlock:
-	tty_kref_put(tty);
-unlock:
-	spin_unlock_irqrestore(&isi_card[card].card_lock, flags);
-	/*	schedule another tx for hopefully in about 10ms	*/
-sched_again:
-	mod_timer(&tx, jiffies + msecs_to_jiffies(10));
-}
-
-/*
- *	Main interrupt handler routine
- */
-
-static irqreturn_t isicom_interrupt(int irq, void *dev_id)
-{
-	struct isi_board *card = dev_id;
-	struct isi_port *port;
-	struct tty_struct *tty;
-	unsigned long base;
-	u16 header, word_count, count, channel;
-	short byte_count;
-	unsigned char *rp;
-
-	if (!card || !(card->status & FIRMWARE_LOADED))
-		return IRQ_NONE;
-
-	base = card->base;
-
-	/* did the card interrupt us? */
-	if (!(inw(base + 0x0e) & 0x02))
-		return IRQ_NONE;
-
-	spin_lock(&card->card_lock);
-
-	/*
-	 * disable any interrupts from the PCI card and lower the
-	 * interrupt line
-	 */
-	outw(0x8000, base+0x04);
-	ClearInterrupt(base);
-
-	inw(base);		/* get the dummy word out */
-	header = inw(base);
-	channel = (header & 0x7800) >> card->shift_count;
-	byte_count = header & 0xff;
-
-	if (channel + 1 > card->port_count) {
-		pr_warning("%s(0x%lx): %d(channel) > port_count.\n",
-			   __func__, base, channel+1);
-		outw(0x0000, base+0x04); /* enable interrupts */
-		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;
-	}
-	port = card->ports + channel;
-	if (!(port->port.flags & ASYNC_INITIALIZED)) {
-		outw(0x0000, base+0x04); /* enable interrupts */
-		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;
-	}
-
-	tty = tty_port_tty_get(&port->port);
-	if (tty == NULL) {
-		word_count = byte_count >> 1;
-		while (byte_count > 1) {
-			inw(base);
-			byte_count -= 2;
-		}
-		if (byte_count & 0x01)
-			inw(base);
-		outw(0x0000, base+0x04); /* enable interrupts */
-		spin_unlock(&card->card_lock);
-		return IRQ_HANDLED;
-	}
-
-	if (header & 0x8000) {		/* Status Packet */
-		header = inw(base);
-		switch (header & 0xff) {
-		case 0:	/* Change in EIA signals */
-			if (port->port.flags & ASYNC_CHECK_CD) {
-				if (port->status & ISI_DCD) {
-					if (!(header & ISI_DCD)) {
-					/* Carrier has been lost  */
-						pr_debug("%s: DCD->low.\n",
-							 __func__);
-						port->status &= ~ISI_DCD;
-						tty_hangup(tty);
-					}
-				} else if (header & ISI_DCD) {
-				/* Carrier has been detected */
-					pr_debug("%s: DCD->high.\n",
-						__func__);
-					port->status |= ISI_DCD;
-					wake_up_interruptible(&port->port.open_wait);
-				}
-			} else {
-				if (header & ISI_DCD)
-					port->status |= ISI_DCD;
-				else
-					port->status &= ~ISI_DCD;
-			}
-
-			if (port->port.flags & ASYNC_CTS_FLOW) {
-				if (tty->hw_stopped) {
-					if (header & ISI_CTS) {
-						port->port.tty->hw_stopped = 0;
-						/* start tx ing */
-						port->status |= (ISI_TXOK
-							| ISI_CTS);
-						tty_wakeup(tty);
-					}
-				} else if (!(header & ISI_CTS)) {
-					tty->hw_stopped = 1;
-					/* stop tx ing */
-					port->status &= ~(ISI_TXOK | ISI_CTS);
-				}
-			} else {
-				if (header & ISI_CTS)
-					port->status |= ISI_CTS;
-				else
-					port->status &= ~ISI_CTS;
-			}
-
-			if (header & ISI_DSR)
-				port->status |= ISI_DSR;
-			else
-				port->status &= ~ISI_DSR;
-
-			if (header & ISI_RI)
-				port->status |= ISI_RI;
-			else
-				port->status &= ~ISI_RI;
-
-			break;
-
-		case 1:	/* Received Break !!! */
-			tty_insert_flip_char(tty, 0, TTY_BREAK);
-			if (port->port.flags & ASYNC_SAK)
-				do_SAK(tty);
-			tty_flip_buffer_push(tty);
-			break;
-
-		case 2:	/* Statistics		 */
-			pr_debug("%s: stats!!!\n", __func__);
-			break;
-
-		default:
-			pr_debug("%s: Unknown code in status packet.\n",
-				 __func__);
-			break;
-		}
-	} else {				/* Data   Packet */
-
-		count = tty_prepare_flip_string(tty, &rp, byte_count & ~1);
-		pr_debug("%s: Can rx %d of %d bytes.\n",
-			 __func__, count, byte_count);
-		word_count = count >> 1;
-		insw(base, rp, word_count);
-		byte_count -= (word_count << 1);
-		if (count & 0x0001) {
-			tty_insert_flip_char(tty,  inw(base) & 0xff,
-				TTY_NORMAL);
-			byte_count -= 2;
-		}
-		if (byte_count > 0) {
-			pr_debug("%s(0x%lx:%d): Flip buffer overflow! dropping bytes...\n",
-				 __func__, base, channel + 1);
-		/* drain out unread xtra data */
-		while (byte_count > 0) {
-				inw(base);
-				byte_count -= 2;
-			}
-		}
-		tty_flip_buffer_push(tty);
-	}
-	outw(0x0000, base+0x04); /* enable interrupts */
-	spin_unlock(&card->card_lock);
-	tty_kref_put(tty);
-
-	return IRQ_HANDLED;
-}
-
-static void isicom_config_port(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long baud;
-	unsigned long base = card->base;
-	u16 channel_setup, channel = port->channel,
-		shift_count = card->shift_count;
-	unsigned char flow_ctrl;
-
-	/* FIXME: Switch to new tty baud API */
-	baud = C_BAUD(tty);
-	if (baud & CBAUDEX) {
-		baud &= ~CBAUDEX;
-
-		/*  if CBAUDEX bit is on and the baud is set to either 50 or 75
-		 *  then the card is programmed for 57.6Kbps or 115Kbps
-		 *  respectively.
-		 */
-
-		/* 1,2,3,4 => 57.6, 115.2, 230, 460 kbps resp. */
-		if (baud < 1 || baud > 4)
-			tty->termios->c_cflag &= ~CBAUDEX;
-		else
-			baud += 15;
-	}
-	if (baud == 15) {
-
-		/*  the ASYNC_SPD_HI and ASYNC_SPD_VHI options are set
-		 *  by the set_serial_info ioctl ... this is done by
-		 *  the 'setserial' utility.
-		 */
-
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud++; /*  57.6 Kbps */
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud += 2; /*  115  Kbps */
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baud += 3; /* 230 kbps*/
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baud += 4; /* 460 kbps*/
-	}
-	if (linuxb_to_isib[baud] == -1) {
-		/* hang up */
-		drop_dtr(port);
-		return;
-	} else
-		raise_dtr(port);
-
-	if (WaitTillCardIsFree(base) == 0) {
-		outw(0x8000 | (channel << shift_count) | 0x03, base);
-		outw(linuxb_to_isib[baud] << 8 | 0x03, base);
-		channel_setup = 0;
-		switch (C_CSIZE(tty)) {
-		case CS5:
-			channel_setup |= ISICOM_CS5;
-			break;
-		case CS6:
-			channel_setup |= ISICOM_CS6;
-			break;
-		case CS7:
-			channel_setup |= ISICOM_CS7;
-			break;
-		case CS8:
-			channel_setup |= ISICOM_CS8;
-			break;
-		}
-
-		if (C_CSTOPB(tty))
-			channel_setup |= ISICOM_2SB;
-		if (C_PARENB(tty)) {
-			channel_setup |= ISICOM_EVPAR;
-			if (C_PARODD(tty))
-				channel_setup |= ISICOM_ODPAR;
-		}
-		outw(channel_setup, base);
-		InterruptTheCard(base);
-	}
-	if (C_CLOCAL(tty))
-		port->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->port.flags |= ASYNC_CHECK_CD;
-
-	/* flow control settings ...*/
-	flow_ctrl = 0;
-	port->port.flags &= ~ASYNC_CTS_FLOW;
-	if (C_CRTSCTS(tty)) {
-		port->port.flags |= ASYNC_CTS_FLOW;
-		flow_ctrl |= ISICOM_CTSRTS;
-	}
-	if (I_IXON(tty))
-		flow_ctrl |= ISICOM_RESPOND_XONXOFF;
-	if (I_IXOFF(tty))
-		flow_ctrl |= ISICOM_INITIATE_XONXOFF;
-
-	if (WaitTillCardIsFree(base) == 0) {
-		outw(0x8000 | (channel << shift_count) | 0x04, base);
-		outw(flow_ctrl << 8 | 0x05, base);
-		outw((STOP_CHAR(tty)) << 8 | (START_CHAR(tty)), base);
-		InterruptTheCard(base);
-	}
-
-	/*	rx enabled -> enable port for rx on the card	*/
-	if (C_CREAD(tty)) {
-		card->port_status |= (1 << channel);
-		outw(card->port_status, base + 0x02);
-	}
-}
-
-/* open et all */
-
-static inline void isicom_setup_board(struct isi_board *bp)
-{
-	int channel;
-	struct isi_port *port;
-
-	bp->count++;
-	if (!(bp->status & BOARD_INIT)) {
-		port = bp->ports;
-		for (channel = 0; channel < bp->port_count; channel++, port++)
-			drop_dtr_rts(port);
-	}
-	bp->status |= BOARD_ACTIVE | BOARD_INIT;
-}
-
-/* Activate and thus setup board are protected from races against shutdown
-   by the tty_port mutex */
-
-static int isicom_activate(struct tty_port *tport, struct tty_struct *tty)
-{
-	struct isi_port *port = container_of(tport, struct isi_port, port);
-	struct isi_board *card = port->card;
-	unsigned long flags;
-
-	if (tty_port_alloc_xmit_buf(tport) < 0)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	isicom_setup_board(card);
-
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
-	/*	discard any residual data	*/
-	if (WaitTillCardIsFree(card->base) == 0) {
-		outw(0x8000 | (port->channel << card->shift_count) | 0x02,
-				card->base);
-		outw(((ISICOM_KILLTX | ISICOM_KILLRX) << 8) | 0x06, card->base);
-		InterruptTheCard(card->base);
-	}
-	isicom_config_port(tty);
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	return 0;
-}
-
-static int isicom_carrier_raised(struct tty_port *port)
-{
-	struct isi_port *ip = container_of(port, struct isi_port, port);
-	return (ip->status & ISI_DCD)?1 : 0;
-}
-
-static struct tty_port *isicom_find_port(struct tty_struct *tty)
-{
-	struct isi_port *port;
-	struct isi_board *card;
-	unsigned int board;
-	int line = tty->index;
-
-	if (line < 0 || line > PORT_COUNT-1)
-		return NULL;
-	board = BOARD(line);
-	card = &isi_card[board];
-
-	if (!(card->status & FIRMWARE_LOADED))
-		return NULL;
-
-	/*  open on a port greater than the port count for the card !!! */
-	if (line > ((board * 16) + card->port_count - 1))
-		return NULL;
-
-	port = &isi_ports[line];
-	if (isicom_paranoia_check(port, tty->name, "isicom_open"))
-		return NULL;
-
-	return &port->port;
-}
-
-static int isicom_open(struct tty_struct *tty, struct file *filp)
-{
-	struct isi_port *port;
-	struct tty_port *tport;
-
-	tport = isicom_find_port(tty);
-	if (tport == NULL)
-		return -ENODEV;
-	port = container_of(tport, struct isi_port, port);
-
-	tty->driver_data = port;
-	return tty_port_open(tport, tty, filp);
-}
-
-/* close et all */
-
-/* card->lock HAS to be held */
-static void isicom_shutdown_port(struct isi_port *port)
-{
-	struct isi_board *card = port->card;
-
-	if (--card->count < 0) {
-		pr_debug("%s: bad board(0x%lx) count %d.\n",
-			 __func__, card->base, card->count);
-		card->count = 0;
-	}
-	/* last port was closed, shutdown that board too */
-	if (!card->count)
-		card->status &= BOARD_ACTIVE;
-}
-
-static void isicom_flush_buffer(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-
-	tty_wakeup(tty);
-}
-
-static void isicom_shutdown(struct tty_port *port)
-{
-	struct isi_port *ip = container_of(port, struct isi_port, port);
-	struct isi_board *card = ip->card;
-	unsigned long flags;
-
-	/* indicate to the card that no more data can be received
-	   on this port */
-	spin_lock_irqsave(&card->card_lock, flags);
-	card->port_status &= ~(1 << ip->channel);
-	outw(card->port_status, card->base + 0x02);
-	isicom_shutdown_port(ip);
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	tty_port_free_xmit_buf(port);
-}
-
-static void isicom_close(struct tty_struct *tty, struct file *filp)
-{
-	struct isi_port *ip = tty->driver_data;
-	struct tty_port *port;
-
-	if (ip == NULL)
-		return;
-
-	port = &ip->port;
-	if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
-		return;
-	tty_port_close(port, tty, filp);
-}
-
-/* write et all */
-static int isicom_write(struct tty_struct *tty,	const unsigned char *buf,
-	int count)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long flags;
-	int cnt, total = 0;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_write"))
-		return 0;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-
-	while (1) {
-		cnt = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt
-				- 1, SERIAL_XMIT_SIZE - port->xmit_head));
-		if (cnt <= 0)
-			break;
-
-		memcpy(port->port.xmit_buf + port->xmit_head, buf, cnt);
-		port->xmit_head = (port->xmit_head + cnt) & (SERIAL_XMIT_SIZE
-			- 1);
-		port->xmit_cnt += cnt;
-		buf += cnt;
-		count -= cnt;
-		total += cnt;
-	}
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped)
-		port->status |= ISI_TXOK;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	return total;
-}
-
-/* put_char et all */
-static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
-		return 0;
-
-	spin_lock_irqsave(&card->card_lock, flags);
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
-		spin_unlock_irqrestore(&card->card_lock, flags);
-		return 0;
-	}
-
-	port->port.xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
-	port->xmit_cnt++;
-	spin_unlock_irqrestore(&card->card_lock, flags);
-	return 1;
-}
-
-/* flush_chars et all */
-static void isicom_flush_chars(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_flush_chars"))
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-			!port->port.xmit_buf)
-		return;
-
-	/* this tells the transmitter to consider this port for
-	   data output to the card ... that's the best we can do. */
-	port->status |= ISI_TXOK;
-}
-
-/* write_room et all */
-static int isicom_write_room(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	int free;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_write_room"))
-		return 0;
-
-	free = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (free < 0)
-		free = 0;
-	return free;
-}
-
-/* chars_in_buffer et all */
-static int isicom_chars_in_buffer(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	if (isicom_paranoia_check(port, tty->name, "isicom_chars_in_buffer"))
-		return 0;
-	return port->xmit_cnt;
-}
-
-/* ioctl et all */
-static int isicom_send_break(struct tty_struct *tty, int length)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-	unsigned long base = card->base;
-
-	if (length == -1)
-		return -EOPNOTSUPP;
-
-	if (!lock_card(card))
-		return -EINVAL;
-
-	outw(0x8000 | ((port->channel) << (card->shift_count)) | 0x3, base);
-	outw((length & 0xff) << 8 | 0x00, base);
-	outw((length & 0xff00), base);
-	InterruptTheCard(base);
-
-	unlock_card(card);
-	return 0;
-}
-
-static int isicom_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct isi_port *port = tty->driver_data;
-	/* just send the port status */
-	u16 status = port->status;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
-		return -ENODEV;
-
-	return  ((status & ISI_RTS) ? TIOCM_RTS : 0) |
-		((status & ISI_DTR) ? TIOCM_DTR : 0) |
-		((status & ISI_DCD) ? TIOCM_CAR : 0) |
-		((status & ISI_DSR) ? TIOCM_DSR : 0) |
-		((status & ISI_CTS) ? TIOCM_CTS : 0) |
-		((status & ISI_RI ) ? TIOCM_RI  : 0);
-}
-
-static int isicom_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear)
-{
-	struct isi_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
-		return -ENODEV;
-
-	spin_lock_irqsave(&port->card->card_lock, flags);
-	if (set & TIOCM_RTS)
-		raise_rts(port);
-	if (set & TIOCM_DTR)
-		raise_dtr(port);
-
-	if (clear & TIOCM_RTS)
-		drop_rts(port);
-	if (clear & TIOCM_DTR)
-		drop_dtr(port);
-	spin_unlock_irqrestore(&port->card->card_lock, flags);
-
-	return 0;
-}
-
-static int isicom_set_serial_info(struct tty_struct *tty,
-					struct serial_struct __user *info)
-{
-	struct isi_port *port = tty->driver_data;
-	struct serial_struct newinfo;
-	int reconfig_port;
-
-	if (copy_from_user(&newinfo, info, sizeof(newinfo)))
-		return -EFAULT;
-
-	mutex_lock(&port->port.mutex);
-	reconfig_port = ((port->port.flags & ASYNC_SPD_MASK) !=
-		(newinfo.flags & ASYNC_SPD_MASK));
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((newinfo.close_delay != port->port.close_delay) ||
-				(newinfo.closing_wait != port->port.closing_wait) ||
-				((newinfo.flags & ~ASYNC_USR_MASK) !=
-				(port->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-				(newinfo.flags & ASYNC_USR_MASK));
-	} else {
-		port->port.close_delay = newinfo.close_delay;
-		port->port.closing_wait = newinfo.closing_wait;
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-				(newinfo.flags & ASYNC_FLAGS));
-	}
-	if (reconfig_port) {
-		unsigned long flags;
-		spin_lock_irqsave(&port->card->card_lock, flags);
-		isicom_config_port(tty);
-		spin_unlock_irqrestore(&port->card->card_lock, flags);
-	}
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-static int isicom_get_serial_info(struct isi_port *port,
-	struct serial_struct __user *info)
-{
-	struct serial_struct out_info;
-
-	mutex_lock(&port->port.mutex);
-	memset(&out_info, 0, sizeof(out_info));
-/*	out_info.type = ? */
-	out_info.line = port - isi_ports;
-	out_info.port = port->card->base;
-	out_info.irq = port->card->irq;
-	out_info.flags = port->port.flags;
-/*	out_info.baud_base = ? */
-	out_info.close_delay = port->port.close_delay;
-	out_info.closing_wait = port->port.closing_wait;
-	mutex_unlock(&port->port.mutex);
-	if (copy_to_user(info, &out_info, sizeof(out_info)))
-		return -EFAULT;
-	return 0;
-}
-
-static int isicom_ioctl(struct tty_struct *tty, struct file *filp,
-	unsigned int cmd, unsigned long arg)
-{
-	struct isi_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_ioctl"))
-		return -ENODEV;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		return isicom_get_serial_info(port, argp);
-
-	case TIOCSSERIAL:
-		return isicom_set_serial_info(tty, argp);
-
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-/* set_termios et all */
-static void isicom_set_termios(struct tty_struct *tty,
-	struct ktermios *old_termios)
-{
-	struct isi_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_set_termios"))
-		return;
-
-	if (tty->termios->c_cflag == old_termios->c_cflag &&
-			tty->termios->c_iflag == old_termios->c_iflag)
-		return;
-
-	spin_lock_irqsave(&port->card->card_lock, flags);
-	isicom_config_port(tty);
-	spin_unlock_irqrestore(&port->card->card_lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		isicom_start(tty);
-	}
-}
-
-/* throttle et all */
-static void isicom_throttle(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_throttle"))
-		return;
-
-	/* tell the card that this port cannot handle any more data for now */
-	card->port_status &= ~(1 << port->channel);
-	outw(card->port_status, card->base + 0x02);
-}
-
-/* unthrottle et all */
-static void isicom_unthrottle(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-	struct isi_board *card = port->card;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_unthrottle"))
-		return;
-
-	/* tell the card that this port is ready to accept more data */
-	card->port_status |= (1 << port->channel);
-	outw(card->port_status, card->base + 0x02);
-}
-
-/* stop et all */
-static void isicom_stop(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_stop"))
-		return;
-
-	/* this tells the transmitter not to consider this port for
-	   data output to the card. */
-	port->status &= ~ISI_TXOK;
-}
-
-/* start et all */
-static void isicom_start(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_start"))
-		return;
-
-	/* this tells the transmitter to consider this port for
-	   data output to the card. */
-	port->status |= ISI_TXOK;
-}
-
-static void isicom_hangup(struct tty_struct *tty)
-{
-	struct isi_port *port = tty->driver_data;
-
-	if (isicom_paranoia_check(port, tty->name, "isicom_hangup"))
-		return;
-	tty_port_hangup(&port->port);
-}
-
-
-/*
- * Driver init and deinit functions
- */
-
-static const struct tty_operations isicom_ops = {
-	.open			= isicom_open,
-	.close			= isicom_close,
-	.write			= isicom_write,
-	.put_char		= isicom_put_char,
-	.flush_chars		= isicom_flush_chars,
-	.write_room		= isicom_write_room,
-	.chars_in_buffer	= isicom_chars_in_buffer,
-	.ioctl			= isicom_ioctl,
-	.set_termios		= isicom_set_termios,
-	.throttle		= isicom_throttle,
-	.unthrottle		= isicom_unthrottle,
-	.stop			= isicom_stop,
-	.start			= isicom_start,
-	.hangup			= isicom_hangup,
-	.flush_buffer		= isicom_flush_buffer,
-	.tiocmget		= isicom_tiocmget,
-	.tiocmset		= isicom_tiocmset,
-	.break_ctl		= isicom_send_break,
-};
-
-static const struct tty_port_operations isicom_port_ops = {
-	.carrier_raised		= isicom_carrier_raised,
-	.dtr_rts		= isicom_dtr_rts,
-	.activate		= isicom_activate,
-	.shutdown		= isicom_shutdown,
-};
-
-static int __devinit reset_card(struct pci_dev *pdev,
-	const unsigned int card, unsigned int *signature)
-{
-	struct isi_board *board = pci_get_drvdata(pdev);
-	unsigned long base = board->base;
-	unsigned int sig, portcount = 0;
-	int retval = 0;
-
-	dev_dbg(&pdev->dev, "ISILoad:Resetting Card%d at 0x%lx\n", card + 1,
-		base);
-
-	inw(base + 0x8);
-
-	msleep(10);
-
-	outw(0, base + 0x8); /* Reset */
-
-	msleep(1000);
-
-	sig = inw(base + 0x4) & 0xff;
-
-	if (sig != 0xa5 && sig != 0xbb && sig != 0xcc && sig != 0xdd &&
-			sig != 0xee) {
-		dev_warn(&pdev->dev, "ISILoad:Card%u reset failure (Possible "
-			"bad I/O Port Address 0x%lx).\n", card + 1, base);
-		dev_dbg(&pdev->dev, "Sig=0x%x\n", sig);
-		retval = -EIO;
-		goto end;
-	}
-
-	msleep(10);
-
-	portcount = inw(base + 0x2);
-	if (!(inw(base + 0xe) & 0x1) || (portcount != 0 && portcount != 4 &&
-				portcount != 8 && portcount != 16)) {
-		dev_err(&pdev->dev, "ISILoad:PCI Card%d reset failure.\n",
-			card + 1);
-		retval = -EIO;
-		goto end;
-	}
-
-	switch (sig) {
-	case 0xa5:
-	case 0xbb:
-	case 0xdd:
-		board->port_count = (portcount == 4) ? 4 : 8;
-		board->shift_count = 12;
-		break;
-	case 0xcc:
-	case 0xee:
-		board->port_count = 16;
-		board->shift_count = 11;
-		break;
-	}
-	dev_info(&pdev->dev, "-Done\n");
-	*signature = sig;
-
-end:
-	return retval;
-}
-
-static int __devinit load_firmware(struct pci_dev *pdev,
-	const unsigned int index, const unsigned int signature)
-{
-	struct isi_board *board = pci_get_drvdata(pdev);
-	const struct firmware *fw;
-	unsigned long base = board->base;
-	unsigned int a;
-	u16 word_count, status;
-	int retval = -EIO;
-	char *name;
-	u8 *data;
-
-	struct stframe {
-		u16	addr;
-		u16	count;
-		u8	data[0];
-	} *frame;
-
-	switch (signature) {
-	case 0xa5:
-		name = "/*(DEBLOBBED)*/";
-		break;
-	case 0xbb:
-		name = "/*(DEBLOBBED)*/";
-		break;
-	case 0xcc:
-		name = "/*(DEBLOBBED)*/";
-		break;
-	case 0xdd:
-		name = "/*(DEBLOBBED)*/";
-		break;
-	case 0xee:
-		name = "/*(DEBLOBBED)*/";
-		break;
-	default:
-		dev_err(&pdev->dev, "Unknown signature.\n");
-		goto end;
-	}
-
-	retval = reject_firmware(&fw, name, &pdev->dev);
-	if (retval)
-		goto end;
-
-	retval = -EIO;
-
-	for (frame = (struct stframe *)fw->data;
-			frame < (struct stframe *)(fw->data + fw->size);
-			frame = (struct stframe *)((u8 *)(frame + 1) +
-				frame->count)) {
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		outw(0xf0, base);	/* start upload sequence */
-		outw(0x00, base);
-		outw(frame->addr, base); /* lsb of address */
-
-		word_count = frame->count / 2 + frame->count % 2;
-		outw(word_count, base);
-		InterruptTheCard(base);
-
-		udelay(100); /* 0x2f */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_warn(&pdev->dev, "Card%d rejected load header:\n"
-				 "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);
-
-		InterruptTheCard(base);
-
-		udelay(50); /* 0x0f */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_err(&pdev->dev, "Card%d got out of sync.Card "
-				"Status:0x%x\n", index + 1, status);
-			goto errrelfw;
-		}
-	}
-
-/* XXX: should we test it by reading it back and comparing with original like
- * in load firmware package? */
-	for (frame = (struct stframe *)fw->data;
-			frame < (struct stframe *)(fw->data + fw->size);
-			frame = (struct stframe *)((u8 *)(frame + 1) +
-				frame->count)) {
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		outw(0xf1, base); /* start download sequence */
-		outw(0x00, base);
-		outw(frame->addr, base); /* lsb of address */
-
-		word_count = (frame->count >> 1) + frame->count % 2;
-		outw(word_count + 1, base);
-		InterruptTheCard(base);
-
-		udelay(50); /* 0xf */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_warn(&pdev->dev, "Card%d rejected verify header:\n"
-				 "Address:0x%x\n"
-				 "Count:0x%x\n"
-				 "Status: 0x%x\n",
-				 index + 1, frame->addr, frame->count, status);
-			goto errrelfw;
-		}
-
-		data = kmalloc(word_count * 2, GFP_KERNEL);
-		if (data == NULL) {
-			dev_err(&pdev->dev, "Card%d, firmware upload "
-				"failed, not enough memory\n", index + 1);
-			goto errrelfw;
-		}
-		inw(base);
-		insw(base, data, word_count);
-		InterruptTheCard(base);
-
-		for (a = 0; a < frame->count; a++)
-			if (data[a] != frame->data[a]) {
-				kfree(data);
-				dev_err(&pdev->dev, "Card%d, firmware upload "
-					"failed\n", index + 1);
-				goto errrelfw;
-			}
-		kfree(data);
-
-		udelay(50); /* 0xf */
-
-		if (WaitTillCardIsFree(base))
-			goto errrelfw;
-
-		status = inw(base + 0x4);
-		if (status != 0) {
-			dev_err(&pdev->dev, "Card%d verify got out of sync. "
-				"Card Status:0x%x\n", index + 1, status);
-			goto errrelfw;
-		}
-	}
-
-	/* xfer ctrl */
-	if (WaitTillCardIsFree(base))
-		goto errrelfw;
-
-	outw(0xf2, base);
-	outw(0x800, base);
-	outw(0x0, base);
-	outw(0x0, base);
-	InterruptTheCard(base);
-	outw(0x0, base + 0x4); /* for ISI4608 cards */
-
-	board->status |= FIRMWARE_LOADED;
-	retval = 0;
-
-errrelfw:
-	release_firmware(fw);
-end:
-	return retval;
-}
-
-/*
- *	Insmod can set static symbols so keep these static
- */
-static unsigned int card_count;
-
-static int __devinit isicom_probe(struct pci_dev *pdev,
-	const struct pci_device_id *ent)
-{
-	unsigned int uninitialized_var(signature), index;
-	int retval = -EPERM;
-	struct isi_board *board = NULL;
-
-	if (card_count >= BOARD_COUNT)
-		goto err;
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "failed to enable\n");
-		goto err;
-	}
-
-	dev_info(&pdev->dev, "ISI PCI Card(Device ID 0x%x)\n", ent->device);
-
-	/* allot the first empty slot in the array */
-	for (index = 0; index < BOARD_COUNT; index++) {
-		if (isi_card[index].base == 0) {
-			board = &isi_card[index];
-			break;
-		}
-	}
-	if (index == BOARD_COUNT) {
-		retval = -ENODEV;
-		goto err_disable;
-	}
-
-	board->index = index;
-	board->base = pci_resource_start(pdev, 3);
-	board->irq = pdev->irq;
-	card_count++;
-
-	pci_set_drvdata(pdev, board);
-
-	retval = pci_request_region(pdev, 3, ISICOM_NAME);
-	if (retval) {
-		dev_err(&pdev->dev, "I/O Region 0x%lx-0x%lx is busy. Card%d "
-			"will be disabled.\n", board->base, board->base + 15,
-			index + 1);
-		retval = -EBUSY;
-		goto errdec;
-	}
-
-	retval = request_irq(board->irq, isicom_interrupt,
-			IRQF_SHARED | IRQF_DISABLED, ISICOM_NAME, board);
-	if (retval < 0) {
-		dev_err(&pdev->dev, "Could not install handler at Irq %d. "
-			"Card%d will be disabled.\n", board->irq, index + 1);
-		goto errunrr;
-	}
-
-	retval = reset_card(pdev, index, &signature);
-	if (retval < 0)
-		goto errunri;
-
-	retval = load_firmware(pdev, index, signature);
-	if (retval < 0)
-		goto errunri;
-
-	for (index = 0; index < board->port_count; index++)
-		tty_register_device(isicom_normal, board->index * 16 + index,
-				&pdev->dev);
-
-	return 0;
-
-errunri:
-	free_irq(board->irq, board);
-errunrr:
-	pci_release_region(pdev, 3);
-errdec:
-	board->base = 0;
-	card_count--;
-err_disable:
-	pci_disable_device(pdev);
-err:
-	return retval;
-}
-
-static void __devexit isicom_remove(struct pci_dev *pdev)
-{
-	struct isi_board *board = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	for (i = 0; i < board->port_count; i++)
-		tty_unregister_device(isicom_normal, board->index * 16 + i);
-
-	free_irq(board->irq, board);
-	pci_release_region(pdev, 3);
-	board->base = 0;
-	card_count--;
-	pci_disable_device(pdev);
-}
-
-static int __init isicom_init(void)
-{
-	int retval, idx, channel;
-	struct isi_port *port;
-
-	for (idx = 0; idx < BOARD_COUNT; idx++) {
-		port = &isi_ports[idx * 16];
-		isi_card[idx].ports = port;
-		spin_lock_init(&isi_card[idx].card_lock);
-		for (channel = 0; channel < 16; channel++, port++) {
-			tty_port_init(&port->port);
-			port->port.ops = &isicom_port_ops;
-			port->magic = ISICOM_MAGIC;
-			port->card = &isi_card[idx];
-			port->channel = channel;
-			port->port.close_delay = 50 * HZ/100;
-			port->port.closing_wait = 3000 * HZ/100;
-			port->status = 0;
-			/*  . . .  */
-		}
-		isi_card[idx].base = 0;
-		isi_card[idx].irq = 0;
-	}
-
-	/* tty driver structure initialization */
-	isicom_normal = alloc_tty_driver(PORT_COUNT);
-	if (!isicom_normal) {
-		retval = -ENOMEM;
-		goto error;
-	}
-
-	isicom_normal->owner			= THIS_MODULE;
-	isicom_normal->name 			= "ttyM";
-	isicom_normal->major			= ISICOM_NMAJOR;
-	isicom_normal->minor_start		= 0;
-	isicom_normal->type			= TTY_DRIVER_TYPE_SERIAL;
-	isicom_normal->subtype			= SERIAL_TYPE_NORMAL;
-	isicom_normal->init_termios		= tty_std_termios;
-	isicom_normal->init_termios.c_cflag	= B9600 | CS8 | CREAD | HUPCL |
-		CLOCAL;
-	isicom_normal->flags			= TTY_DRIVER_REAL_RAW |
-		TTY_DRIVER_DYNAMIC_DEV | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(isicom_normal, &isicom_ops);
-
-	retval = tty_register_driver(isicom_normal);
-	if (retval) {
-		pr_debug("Couldn't register the dialin driver\n");
-		goto err_puttty;
-	}
-
-	retval = pci_register_driver(&isicom_driver);
-	if (retval < 0) {
-		pr_err("Unable to register pci driver.\n");
-		goto err_unrtty;
-	}
-
-	mod_timer(&tx, jiffies + 1);
-
-	return 0;
-err_unrtty:
-	tty_unregister_driver(isicom_normal);
-err_puttty:
-	put_tty_driver(isicom_normal);
-error:
-	return retval;
-}
-
-static void __exit isicom_exit(void)
-{
-	del_timer_sync(&tx);
-
-	pci_unregister_driver(&isicom_driver);
-	tty_unregister_driver(isicom_normal);
-	put_tty_driver(isicom_normal);
-}
-
-module_init(isicom_init);
-module_exit(isicom_exit);
-
-MODULE_AUTHOR("MultiTech");
-MODULE_DESCRIPTION("Driver for the ISI series of cards by MultiTech");
-MODULE_LICENSE("GPL");
-/*(DEBLOBBED)*/
diff -druN linux-libre-2.6.38-gnu/drivers/char/istallion.c linux-libre-2.6.39-gnu/drivers/char/istallion.c
--- linux-libre-2.6.38-gnu/drivers/char/istallion.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/istallion.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4507 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	istallion.c  -- stallion intelligent multiport serial driver.
- *
- *	Copyright (C) 1996-1999  Stallion Technologies
- *	Copyright (C) 1994-1996  Greg Ungerer.
- *
- *	This code is loosely based on the Linux serial driver, written by
- *	Linus Torvalds, Theodore T'so and others.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the 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/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/seq_file.h>
-#include <linux/cdk.h>
-#include <linux/comstats.h>
-#include <linux/istallion.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/wait.h>
-#include <linux/eisa.h>
-#include <linux/ctype.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/pci.h>
-
-/*****************************************************************************/
-
-/*
- *	Define different board types. Not all of the following board types
- *	are supported by this driver. But I will use the standard "assigned"
- *	board numbers. Currently supported boards are abbreviated as:
- *	ECP = EasyConnection 8/64, ONB = ONboard, BBY = Brumby and
- *	STAL = Stallion.
- */
-#define	BRD_UNKNOWN	0
-#define	BRD_STALLION	1
-#define	BRD_BRUMBY4	2
-#define	BRD_ONBOARD2	3
-#define	BRD_ONBOARD	4
-#define	BRD_ONBOARDE	7
-#define	BRD_ECP		23
-#define BRD_ECPE	24
-#define	BRD_ECPMC	25
-#define	BRD_ECPPCI	29
-
-#define	BRD_BRUMBY	BRD_BRUMBY4
-
-/*
- *	Define a configuration structure to hold the board configuration.
- *	Need to set this up in the code (for now) with the boards that are
- *	to be configured into the system. This is what needs to be modified
- *	when adding/removing/modifying boards. Each line entry in the
- *	stli_brdconf[] array is a board. Each line contains io/irq/memory
- *	ranges for that board (as well as what type of board it is).
- *	Some examples:
- *		{ BRD_ECP, 0x2a0, 0, 0xcc000, 0, 0 },
- *	This line will configure an EasyConnection 8/64 at io address 2a0,
- *	and shared memory address of cc000. Multiple EasyConnection 8/64
- *	boards can share the same shared memory address space. No interrupt
- *	is required for this board type.
- *	Another example:
- *		{ BRD_ECPE, 0x5000, 0, 0x80000000, 0, 0 },
- *	This line will configure an EasyConnection 8/64 EISA in slot 5 and
- *	shared memory address of 0x80000000 (2 GByte). Multiple
- *	EasyConnection 8/64 EISA boards can share the same shared memory
- *	address space. No interrupt is required for this board type.
- *	Another example:
- *		{ BRD_ONBOARD, 0x240, 0, 0xd0000, 0, 0 },
- *	This line will configure an ONboard (ISA type) at io address 240,
- *	and shared memory address of d0000. Multiple ONboards can share
- *	the same shared memory address space. No interrupt required.
- *	Another example:
- *		{ BRD_BRUMBY4, 0x360, 0, 0xc8000, 0, 0 },
- *	This line will configure a Brumby board (any number of ports!) at
- *	io address 360 and shared memory address of c8000. All Brumby boards
- *	configured into a system must have their own separate io and memory
- *	addresses. No interrupt is required.
- *	Another example:
- *		{ BRD_STALLION, 0x330, 0, 0xd0000, 0, 0 },
- *	This line will configure an original Stallion board at io address 330
- *	and shared memory address d0000 (this would only be valid for a "V4.0"
- *	or Rev.O Stallion board). All Stallion boards configured into the
- *	system must have their own separate io and memory addresses. No
- *	interrupt is required.
- */
-
-struct stlconf {
-	int		brdtype;
-	int		ioaddr1;
-	int		ioaddr2;
-	unsigned long	memaddr;
-	int		irq;
-	int		irqtype;
-};
-
-static unsigned int stli_nrbrds;
-
-/* stli_lock must NOT be taken holding brd_lock */
-static spinlock_t stli_lock;	/* TTY logic lock */
-static spinlock_t brd_lock;	/* Board logic lock */
-
-/*
- *	There is some experimental EISA board detection code in this driver.
- *	By default it is disabled, but for those that want to try it out,
- *	then set the define below to be 1.
- */
-#define	STLI_EISAPROBE	0
-
-/*****************************************************************************/
-
-/*
- *	Define some important driver characteristics. Device major numbers
- *	allocated as per Linux Device Registry.
- */
-#ifndef	STL_SIOMEMMAJOR
-#define	STL_SIOMEMMAJOR		28
-#endif
-#ifndef	STL_SERIALMAJOR
-#define	STL_SERIALMAJOR		24
-#endif
-#ifndef	STL_CALLOUTMAJOR
-#define	STL_CALLOUTMAJOR	25
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Define our local driver identity first. Set up stuff to deal with
- *	all the local structures required by a serial tty driver.
- */
-static char	*stli_drvtitle = "Stallion Intelligent Multiport Serial Driver";
-static char	*stli_drvname = "istallion";
-static char	*stli_drvversion = "5.6.0";
-static char	*stli_serialname = "ttyE";
-
-static struct tty_driver	*stli_serial;
-static const struct tty_port_operations stli_port_ops;
-
-#define	STLI_TXBUFSIZE		4096
-
-/*
- *	Use a fast local buffer for cooked characters. Typically a whole
- *	bunch of cooked characters come in for a port, 1 at a time. So we
- *	save those up into a local buffer, then write out the whole lot
- *	with a large memcpy. Just use 1 buffer for all ports, since its
- *	use it is only need for short periods of time by each port.
- */
-static char			*stli_txcookbuf;
-static int			stli_txcooksize;
-static int			stli_txcookrealsize;
-static struct tty_struct	*stli_txcooktty;
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially. Basically all it defines is a raw port
- *	at 9600 baud, 8 data bits, no parity, 1 stop bit.
- */
-static struct ktermios		stli_deftermios = {
-	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_cc		= INIT_C_CC,
-	.c_ispeed	= 9600,
-	.c_ospeed	= 9600,
-};
-
-/*
- *	Define global stats structures. Not used often, and can be
- *	re-used for each stats call.
- */
-static comstats_t	stli_comstats;
-static combrd_t		stli_brdstats;
-static struct asystats	stli_cdkstats;
-
-/*****************************************************************************/
-
-static DEFINE_MUTEX(stli_brdslock);
-static struct stlibrd	*stli_brds[STL_MAXBRDS];
-
-static int		stli_shared;
-
-/*
- *	Per board state flags. Used with the state field of the board struct.
- *	Not really much here... All we need to do is keep track of whether
- *	the board has been detected, and whether it is actually running a slave
- *	or not.
- */
-#define	BST_FOUND	0
-#define	BST_STARTED	1
-#define	BST_PROBED	2
-
-/*
- *	Define the set of port state flags. These are marked for internal
- *	state purposes only, usually to do with the state of communications
- *	with the slave. Most of them need to be updated atomically, so always
- *	use the bit setting operations (unless protected by cli/sti).
- */
-#define	ST_OPENING	2
-#define	ST_CLOSING	3
-#define	ST_CMDING	4
-#define	ST_TXBUSY	5
-#define	ST_RXING	6
-#define	ST_DOFLUSHRX	7
-#define	ST_DOFLUSHTX	8
-#define	ST_DOSIGS	9
-#define	ST_RXSTOP	10
-#define	ST_GETSIGS	11
-
-/*
- *	Define an array of board names as printable strings. Handy for
- *	referencing boards when printing trace and stuff.
- */
-static char	*stli_brdnames[] = {
-	"Unknown",
-	"Stallion",
-	"Brumby",
-	"ONboard-MC",
-	"ONboard",
-	"Brumby",
-	"Brumby",
-	"ONboard-EI",
-	NULL,
-	"ONboard",
-	"ONboard-MC",
-	"ONboard-MC",
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"EasyIO",
-	"EC8/32-AT",
-	"EC8/32-MC",
-	"EC8/64-AT",
-	"EC8/64-EI",
-	"EC8/64-MC",
-	"EC8/32-PCI",
-	"EC8/64-PCI",
-	"EasyIO-PCI",
-	"EC/RA-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *	Define some string labels for arguments passed from the module
- *	load line. These allow for easy board definitions, and easy
- *	modification of the io, memory and irq resoucres.
- */
-
-static char	*board0[8];
-static char	*board1[8];
-static char	*board2[8];
-static char	*board3[8];
-
-static char	**stli_brdsp[] = {
-	(char **) &board0,
-	(char **) &board1,
-	(char **) &board2,
-	(char **) &board3
-};
-
-/*
- *	Define a set of common board names, and types. This is used to
- *	parse any module arguments.
- */
-
-static struct stlibrdtype {
-	char	*name;
-	int	type;
-} stli_brdstr[] = {
-	{ "stallion", BRD_STALLION },
-	{ "1", BRD_STALLION },
-	{ "brumby", BRD_BRUMBY },
-	{ "brumby4", BRD_BRUMBY },
-	{ "brumby/4", BRD_BRUMBY },
-	{ "brumby-4", BRD_BRUMBY },
-	{ "brumby8", BRD_BRUMBY },
-	{ "brumby/8", BRD_BRUMBY },
-	{ "brumby-8", BRD_BRUMBY },
-	{ "brumby16", BRD_BRUMBY },
-	{ "brumby/16", BRD_BRUMBY },
-	{ "brumby-16", BRD_BRUMBY },
-	{ "2", BRD_BRUMBY },
-	{ "onboard2", BRD_ONBOARD2 },
-	{ "onboard-2", BRD_ONBOARD2 },
-	{ "onboard/2", BRD_ONBOARD2 },
-	{ "onboard-mc", BRD_ONBOARD2 },
-	{ "onboard/mc", BRD_ONBOARD2 },
-	{ "onboard-mca", BRD_ONBOARD2 },
-	{ "onboard/mca", BRD_ONBOARD2 },
-	{ "3", BRD_ONBOARD2 },
-	{ "onboard", BRD_ONBOARD },
-	{ "onboardat", BRD_ONBOARD },
-	{ "4", BRD_ONBOARD },
-	{ "onboarde", BRD_ONBOARDE },
-	{ "onboard-e", BRD_ONBOARDE },
-	{ "onboard/e", BRD_ONBOARDE },
-	{ "onboard-ei", BRD_ONBOARDE },
-	{ "onboard/ei", BRD_ONBOARDE },
-	{ "7", BRD_ONBOARDE },
-	{ "ecp", BRD_ECP },
-	{ "ecpat", BRD_ECP },
-	{ "ec8/64", BRD_ECP },
-	{ "ec8/64-at", BRD_ECP },
-	{ "ec8/64-isa", BRD_ECP },
-	{ "23", BRD_ECP },
-	{ "ecpe", BRD_ECPE },
-	{ "ecpei", BRD_ECPE },
-	{ "ec8/64-e", BRD_ECPE },
-	{ "ec8/64-ei", BRD_ECPE },
-	{ "24", BRD_ECPE },
-	{ "ecpmc", BRD_ECPMC },
-	{ "ec8/64-mc", BRD_ECPMC },
-	{ "ec8/64-mca", BRD_ECPMC },
-	{ "25", BRD_ECPMC },
-	{ "ecppci", BRD_ECPPCI },
-	{ "ec/ra", BRD_ECPPCI },
-	{ "ec/ra-pc", BRD_ECPPCI },
-	{ "ec/ra-pci", BRD_ECPPCI },
-	{ "29", BRD_ECPPCI },
-};
-
-/*
- *	Define the module agruments.
- */
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Intelligent Multiport Serial Driver");
-MODULE_LICENSE("GPL");
-
-
-module_param_array(board0, charp, NULL, 0);
-MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,memaddr]");
-module_param_array(board1, charp, NULL, 0);
-MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,memaddr]");
-module_param_array(board2, charp, NULL, 0);
-MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,memaddr]");
-module_param_array(board3, charp, NULL, 0);
-MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,memaddr]");
-
-#if STLI_EISAPROBE != 0
-/*
- *	Set up a default memory address table for EISA board probing.
- *	The default addresses are all bellow 1Mbyte, which has to be the
- *	case anyway. They should be safe, since we only read values from
- *	them, and interrupts are disabled while we do it. If the higher
- *	memory support is compiled in then we also try probing around
- *	the 1Gb, 2Gb and 3Gb areas as well...
- */
-static unsigned long	stli_eisamemprobeaddrs[] = {
-	0xc0000,    0xd0000,    0xe0000,    0xf0000,
-	0x80000000, 0x80010000, 0x80020000, 0x80030000,
-	0x40000000, 0x40010000, 0x40020000, 0x40030000,
-	0xc0000000, 0xc0010000, 0xc0020000, 0xc0030000,
-	0xff000000, 0xff010000, 0xff020000, 0xff030000,
-};
-
-static int	stli_eisamempsize = ARRAY_SIZE(stli_eisamemprobeaddrs);
-#endif
-
-/*
- *	Define the Stallion PCI vendor and device IDs.
- */
-#ifndef PCI_DEVICE_ID_ECRA
-#define	PCI_DEVICE_ID_ECRA		0x0004
-#endif
-
-static struct pci_device_id istallion_pci_tbl[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECRA), },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, istallion_pci_tbl);
-
-static struct pci_driver stli_pcidriver;
-
-/*****************************************************************************/
-
-/*
- *	Hardware configuration info for ECP boards. These defines apply
- *	to the directly accessible io ports of the ECP. There is a set of
- *	defines for each ECP board type, ISA, EISA, MCA and PCI.
- */
-#define	ECP_IOSIZE	4
-
-#define	ECP_MEMSIZE	(128 * 1024)
-#define	ECP_PCIMEMSIZE	(256 * 1024)
-
-#define	ECP_ATPAGESIZE	(4 * 1024)
-#define	ECP_MCPAGESIZE	(4 * 1024)
-#define	ECP_EIPAGESIZE	(64 * 1024)
-#define	ECP_PCIPAGESIZE	(64 * 1024)
-
-#define	STL_EISAID	0x8c4e
-
-/*
- *	Important defines for the ISA class of ECP board.
- */
-#define	ECP_ATIREG	0
-#define	ECP_ATCONFR	1
-#define	ECP_ATMEMAR	2
-#define	ECP_ATMEMPR	3
-#define	ECP_ATSTOP	0x1
-#define	ECP_ATINTENAB	0x10
-#define	ECP_ATENABLE	0x20
-#define	ECP_ATDISABLE	0x00
-#define	ECP_ATADDRMASK	0x3f000
-#define	ECP_ATADDRSHFT	12
-
-/*
- *	Important defines for the EISA class of ECP board.
- */
-#define	ECP_EIIREG	0
-#define	ECP_EIMEMARL	1
-#define	ECP_EICONFR	2
-#define	ECP_EIMEMARH	3
-#define	ECP_EIENABLE	0x1
-#define	ECP_EIDISABLE	0x0
-#define	ECP_EISTOP	0x4
-#define	ECP_EIEDGE	0x00
-#define	ECP_EILEVEL	0x80
-#define	ECP_EIADDRMASKL	0x00ff0000
-#define	ECP_EIADDRSHFTL	16
-#define	ECP_EIADDRMASKH	0xff000000
-#define	ECP_EIADDRSHFTH	24
-#define	ECP_EIBRDENAB	0xc84
-
-#define	ECP_EISAID	0x4
-
-/*
- *	Important defines for the Micro-channel class of ECP board.
- *	(It has a lot in common with the ISA boards.)
- */
-#define	ECP_MCIREG	0
-#define	ECP_MCCONFR	1
-#define	ECP_MCSTOP	0x20
-#define	ECP_MCENABLE	0x80
-#define	ECP_MCDISABLE	0x00
-
-/*
- *	Important defines for the PCI class of ECP board.
- *	(It has a lot in common with the other ECP boards.)
- */
-#define	ECP_PCIIREG	0
-#define	ECP_PCICONFR	1
-#define	ECP_PCISTOP	0x01
-
-/*
- *	Hardware configuration info for ONboard and Brumby boards. These
- *	defines apply to the directly accessible io ports of these boards.
- */
-#define	ONB_IOSIZE	16
-#define	ONB_MEMSIZE	(64 * 1024)
-#define	ONB_ATPAGESIZE	(64 * 1024)
-#define	ONB_MCPAGESIZE	(64 * 1024)
-#define	ONB_EIMEMSIZE	(128 * 1024)
-#define	ONB_EIPAGESIZE	(64 * 1024)
-
-/*
- *	Important defines for the ISA class of ONboard board.
- */
-#define	ONB_ATIREG	0
-#define	ONB_ATMEMAR	1
-#define	ONB_ATCONFR	2
-#define	ONB_ATSTOP	0x4
-#define	ONB_ATENABLE	0x01
-#define	ONB_ATDISABLE	0x00
-#define	ONB_ATADDRMASK	0xff0000
-#define	ONB_ATADDRSHFT	16
-
-#define	ONB_MEMENABLO	0
-#define	ONB_MEMENABHI	0x02
-
-/*
- *	Important defines for the EISA class of ONboard board.
- */
-#define	ONB_EIIREG	0
-#define	ONB_EIMEMARL	1
-#define	ONB_EICONFR	2
-#define	ONB_EIMEMARH	3
-#define	ONB_EIENABLE	0x1
-#define	ONB_EIDISABLE	0x0
-#define	ONB_EISTOP	0x4
-#define	ONB_EIEDGE	0x00
-#define	ONB_EILEVEL	0x80
-#define	ONB_EIADDRMASKL	0x00ff0000
-#define	ONB_EIADDRSHFTL	16
-#define	ONB_EIADDRMASKH	0xff000000
-#define	ONB_EIADDRSHFTH	24
-#define	ONB_EIBRDENAB	0xc84
-
-#define	ONB_EISAID	0x1
-
-/*
- *	Important defines for the Brumby boards. They are pretty simple,
- *	there is not much that is programmably configurable.
- */
-#define	BBY_IOSIZE	16
-#define	BBY_MEMSIZE	(64 * 1024)
-#define	BBY_PAGESIZE	(16 * 1024)
-
-#define	BBY_ATIREG	0
-#define	BBY_ATCONFR	1
-#define	BBY_ATSTOP	0x4
-
-/*
- *	Important defines for the Stallion boards. They are pretty simple,
- *	there is not much that is programmably configurable.
- */
-#define	STAL_IOSIZE	16
-#define	STAL_MEMSIZE	(64 * 1024)
-#define	STAL_PAGESIZE	(64 * 1024)
-
-/*
- *	Define the set of status register values for EasyConnection panels.
- *	The signature will return with the status value for each panel. From
- *	this we can determine what is attached to the board - before we have
- *	actually down loaded any code to it.
- */
-#define	ECH_PNLSTATUS	2
-#define	ECH_PNL16PORT	0x20
-#define	ECH_PNLIDMASK	0x07
-#define	ECH_PNLXPID	0x40
-#define	ECH_PNLINTRPEND	0x80
-
-/*
- *	Define some macros to do things to the board. Even those these boards
- *	are somewhat related there is often significantly different ways of
- *	doing some operation on it (like enable, paging, reset, etc). So each
- *	board class has a set of functions which do the commonly required
- *	operations. The macros below basically just call these functions,
- *	generally checking for a NULL function - which means that the board
- *	needs nothing done to it to achieve this operation!
- */
-#define	EBRDINIT(brdp)						\
-	if (brdp->init != NULL)					\
-		(* brdp->init)(brdp)
-
-#define	EBRDENABLE(brdp)					\
-	if (brdp->enable != NULL)				\
-		(* brdp->enable)(brdp);
-
-#define	EBRDDISABLE(brdp)					\
-	if (brdp->disable != NULL)				\
-		(* brdp->disable)(brdp);
-
-#define	EBRDINTR(brdp)						\
-	if (brdp->intr != NULL)					\
-		(* brdp->intr)(brdp);
-
-#define	EBRDRESET(brdp)						\
-	if (brdp->reset != NULL)				\
-		(* brdp->reset)(brdp);
-
-#define	EBRDGETMEMPTR(brdp,offset)				\
-	(* brdp->getmemptr)(brdp, offset, __LINE__)
-
-/*
- *	Define the maximal baud rate, and the default baud base for ports.
- */
-#define	STL_MAXBAUD	460800
-#define	STL_BAUDBASE	115200
-#define	STL_CLOSEDELAY	(5 * HZ / 10)
-
-/*****************************************************************************/
-
-/*
- *	Define macros to extract a brd or port number from a minor number.
- */
-#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
-#define	MINOR2PORT(min)		((min) & 0x3f)
-
-/*****************************************************************************/
-
-/*
- *	Prototype all functions in this driver!
- */
-
-static int	stli_parsebrd(struct stlconf *confp, char **argp);
-static int	stli_open(struct tty_struct *tty, struct file *filp);
-static void	stli_close(struct tty_struct *tty, struct file *filp);
-static int	stli_write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int	stli_putchar(struct tty_struct *tty, unsigned char ch);
-static void	stli_flushchars(struct tty_struct *tty);
-static int	stli_writeroom(struct tty_struct *tty);
-static int	stli_charsinbuffer(struct tty_struct *tty);
-static int	stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static void	stli_settermios(struct tty_struct *tty, struct ktermios *old);
-static void	stli_throttle(struct tty_struct *tty);
-static void	stli_unthrottle(struct tty_struct *tty);
-static void	stli_stop(struct tty_struct *tty);
-static void	stli_start(struct tty_struct *tty);
-static void	stli_flushbuffer(struct tty_struct *tty);
-static int	stli_breakctl(struct tty_struct *tty, int state);
-static void	stli_waituntilsent(struct tty_struct *tty, int timeout);
-static void	stli_sendxchar(struct tty_struct *tty, char ch);
-static void	stli_hangup(struct tty_struct *tty);
-
-static int	stli_brdinit(struct stlibrd *brdp);
-static int	stli_startbrd(struct stlibrd *brdp);
-static ssize_t	stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
-static ssize_t	stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
-static long	stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-static void	stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
-static void	stli_poll(unsigned long arg);
-static int	stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
-static int	stli_initopen(struct tty_struct *tty, struct stlibrd *brdp, struct stliport *portp);
-static int	stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int	stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait);
-static int	stli_setport(struct tty_struct *tty);
-static int	stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	__stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback);
-static void	stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp);
-static void	stli_mkasyport(struct tty_struct *tty, struct stliport *portp, asyport_t *pp, struct ktermios *tiosp);
-static void	stli_mkasysigs(asysigs_t *sp, int dtr, int rts);
-static long	stli_mktiocm(unsigned long sigvalue);
-static void	stli_read(struct stlibrd *brdp, struct stliport *portp);
-static int	stli_getserial(struct stliport *portp, struct serial_struct __user *sp);
-static int	stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp);
-static int	stli_getbrdstats(combrd_t __user *bp);
-static int	stli_getportstats(struct tty_struct *tty, struct stliport *portp, comstats_t __user *cp);
-static int	stli_portcmdstats(struct tty_struct *tty, struct stliport *portp);
-static int	stli_clrportstats(struct stliport *portp, comstats_t __user *cp);
-static int	stli_getportstruct(struct stliport __user *arg);
-static int	stli_getbrdstruct(struct stlibrd __user *arg);
-static struct stlibrd *stli_allocbrd(void);
-
-static void	stli_ecpinit(struct stlibrd *brdp);
-static void	stli_ecpenable(struct stlibrd *brdp);
-static void	stli_ecpdisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpreset(struct stlibrd *brdp);
-static void	stli_ecpintr(struct stlibrd *brdp);
-static void	stli_ecpeiinit(struct stlibrd *brdp);
-static void	stli_ecpeienable(struct stlibrd *brdp);
-static void	stli_ecpeidisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpeireset(struct stlibrd *brdp);
-static void	stli_ecpmcenable(struct stlibrd *brdp);
-static void	stli_ecpmcdisable(struct stlibrd *brdp);
-static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecpmcreset(struct stlibrd *brdp);
-static void	stli_ecppciinit(struct stlibrd *brdp);
-static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_ecppcireset(struct stlibrd *brdp);
-
-static void	stli_onbinit(struct stlibrd *brdp);
-static void	stli_onbenable(struct stlibrd *brdp);
-static void	stli_onbdisable(struct stlibrd *brdp);
-static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_onbreset(struct stlibrd *brdp);
-static void	stli_onbeinit(struct stlibrd *brdp);
-static void	stli_onbeenable(struct stlibrd *brdp);
-static void	stli_onbedisable(struct stlibrd *brdp);
-static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_onbereset(struct stlibrd *brdp);
-static void	stli_bbyinit(struct stlibrd *brdp);
-static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_bbyreset(struct stlibrd *brdp);
-static void	stli_stalinit(struct stlibrd *brdp);
-static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line);
-static void	stli_stalreset(struct stlibrd *brdp);
-
-static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr, unsigned int portnr);
-
-static int	stli_initecp(struct stlibrd *brdp);
-static int	stli_initonb(struct stlibrd *brdp);
-#if STLI_EISAPROBE != 0
-static int	stli_eisamemprobe(struct stlibrd *brdp);
-#endif
-static int	stli_initports(struct stlibrd *brdp);
-
-/*****************************************************************************/
-
-/*
- *	Define the driver info for a user level shared memory device. This
- *	device will work sort of like the /dev/kmem device - except that it
- *	will give access to the shared memory on the Stallion intelligent
- *	board. This is also a very useful debugging tool.
- */
-static const struct file_operations	stli_fsiomem = {
-	.owner		= THIS_MODULE,
-	.read		= stli_memread,
-	.write		= stli_memwrite,
-	.unlocked_ioctl	= stli_memioctl,
-	.llseek		= default_llseek,
-};
-
-/*****************************************************************************/
-
-/*
- *	Define a timer_list entry for our poll routine. The slave board
- *	is polled every so often to see if anything needs doing. This is
- *	much cheaper on host cpu than using interrupts. It turns out to
- *	not increase character latency by much either...
- */
-static DEFINE_TIMER(stli_timerlist, stli_poll, 0, 0);
-
-static int	stli_timeron;
-
-/*
- *	Define the calculation for the timeout routine.
- */
-#define	STLI_TIMEOUT	(jiffies + 1)
-
-/*****************************************************************************/
-
-static struct class *istallion_class;
-
-static void stli_cleanup_ports(struct stlibrd *brdp)
-{
-	struct stliport *portp;
-	unsigned int j;
-	struct tty_struct *tty;
-
-	for (j = 0; j < STL_MAXPORTS; j++) {
-		portp = brdp->ports[j];
-		if (portp != NULL) {
-			tty = tty_port_tty_get(&portp->port);
-			if (tty != NULL) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-			kfree(portp);
-		}
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Parse the supplied argument string, into the board conf struct.
- */
-
-static int stli_parsebrd(struct stlconf *confp, char **argp)
-{
-	unsigned int i;
-	char *sp;
-
-	if (argp[0] == NULL || *argp[0] == 0)
-		return 0;
-
-	for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
-		*sp = tolower(*sp);
-
-	for (i = 0; i < ARRAY_SIZE(stli_brdstr); i++) {
-		if (strcmp(stli_brdstr[i].name, argp[0]) == 0)
-			break;
-	}
-	if (i == ARRAY_SIZE(stli_brdstr)) {
-		printk(KERN_WARNING "istallion: unknown board name, %s?\n", argp[0]);
-		return 0;
-	}
-
-	confp->brdtype = stli_brdstr[i].type;
-	if (argp[1] != NULL && *argp[1] != 0)
-		confp->ioaddr1 = simple_strtoul(argp[1], NULL, 0);
-	if (argp[2] !=  NULL && *argp[2] != 0)
-		confp->memaddr = simple_strtoul(argp[2], NULL, 0);
-	return(1);
-}
-
-/*****************************************************************************/
-
-/*
- *	On the first open of the device setup the port hardware, and
- *	initialize the per port data structure. Since initializing the port
- *	requires several commands to the board we will need to wait for any
- *	other open that is already initializing the port.
- *
- *	Locking: protected by the port mutex.
- */
-
-static int stli_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	struct stlibrd *brdp = stli_brds[portp->brdnr];
-	int rc;
-
-	if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
-		clear_bit(TTY_IO_ERROR, &tty->flags);
-	wake_up_interruptible(&portp->raw_wait);
-	return rc;
-}
-
-static int stli_open(struct tty_struct *tty, struct file *filp)
-{
-	struct stlibrd *brdp;
-	struct stliport *portp;
-	unsigned int minordev, brdnr, portnr;
-
-	minordev = tty->index;
-	brdnr = MINOR2BRD(minordev);
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (!test_bit(BST_STARTED, &brdp->state))
-		return -ENODEV;
-	portnr = MINOR2PORT(minordev);
-	if (portnr > brdp->nrports)
-		return -ENODEV;
-
-	portp = brdp->ports[portnr];
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->devnr < 1)
-		return -ENODEV;
-
-	tty->driver_data = portp;
-	return tty_port_open(&portp->port, tty, filp);
-}
-
-
-/*****************************************************************************/
-
-static void stli_shutdown(struct tty_port *port)
-{
-	struct stlibrd *brdp;
-	unsigned long ftype;
-	unsigned long flags;
-	struct stliport *portp = container_of(port, struct stliport, port);
-
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	/*
-	 *	May want to wait for data to drain before closing. The BUSY
-	 *	flag keeps track of whether we are still transmitting or not.
-	 *	It is updated by messages from the slave - indicating when all
-	 *	chars really have drained.
-	 */
-
-	if (!test_bit(ST_CLOSING, &portp->state))
-		stli_rawclose(brdp, portp, 0, 0);
-
- 	spin_lock_irqsave(&stli_lock, flags);
-	clear_bit(ST_TXBUSY, &portp->state);
-	clear_bit(ST_RXSTOP, &portp->state);
-	spin_unlock_irqrestore(&stli_lock, flags);
-
-	ftype = FLUSHTX | FLUSHRX;
-	stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
-}
-
-static void stli_close(struct tty_struct *tty, struct file *filp)
-{
-	struct stliport *portp = tty->driver_data;
-	unsigned long flags;
-	if (portp == NULL)
-		return;
- 	spin_lock_irqsave(&stli_lock, flags);
-	/*	Flush any internal buffering out first */
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	spin_unlock_irqrestore(&stli_lock, flags);
-	tty_port_close(&portp->port, tty, filp);
-}
-
-/*****************************************************************************/
-
-/*
- *	Carry out first open operations on a port. This involves a number of
- *	commands to be sent to the slave. We need to open the port, set the
- *	notification events, set the initial port settings, get and set the
- *	initial signal values. We sleep and wait in between each one. But
- *	this still all happens pretty quickly.
- */
-
-static int stli_initopen(struct tty_struct *tty,
-				struct stlibrd *brdp, struct stliport *portp)
-{
-	asynotify_t nt;
-	asyport_t aport;
-	int rc;
-
-	if ((rc = stli_rawopen(brdp, portp, 0, 1)) < 0)
-		return rc;
-
-	memset(&nt, 0, sizeof(asynotify_t));
-	nt.data = (DT_TXLOW | DT_TXEMPTY | DT_RXBUSY | DT_RXBREAK);
-	nt.signal = SG_DCD;
-	if ((rc = stli_cmdwait(brdp, portp, A_SETNOTIFY, &nt,
-	    sizeof(asynotify_t), 0)) < 0)
-		return rc;
-
-	stli_mkasyport(tty, portp, &aport, tty->termios);
-	if ((rc = stli_cmdwait(brdp, portp, A_SETPORT, &aport,
-	    sizeof(asyport_t), 0)) < 0)
-		return rc;
-
-	set_bit(ST_GETSIGS, &portp->state);
-	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS, &portp->asig,
-	    sizeof(asysigs_t), 1)) < 0)
-		return rc;
-	if (test_and_clear_bit(ST_GETSIGS, &portp->state))
-		portp->sigs = stli_mktiocm(portp->asig.sigvalue);
-	stli_mkasysigs(&portp->asig, 1, 1);
-	if ((rc = stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-	    sizeof(asysigs_t), 0)) < 0)
-		return rc;
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send an open message to the slave. This will sleep waiting for the
- *	acknowledgement, so must have user context. We need to co-ordinate
- *	with close events here, since we don't want open and close events
- *	to overlap.
- */
-
-static int stli_rawopen(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-	unsigned long flags;
-	int rc;
-
-/*
- *	Send a message to the slave to open this port.
- */
-
-/*
- *	Slave is already closing this port. This can happen if a hangup
- *	occurs on this port. So we must wait until it is complete. The
- *	order of opens and closes may not be preserved across shared
- *	memory, so we must wait until it is complete.
- */
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_CLOSING, &portp->state));
-	if (signal_pending(current)) {
-		return -ERESTARTSYS;
-	}
-
-/*
- *	Everything is ready now, so write the open message into shared
- *	memory. Once the message is in set the service bits to say that
- *	this port wants service.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	writel(arg, &cp->openarg);
-	writeb(1, &cp->open);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	EBRDDISABLE(brdp);
-
-	if (wait == 0) {
-		spin_unlock_irqrestore(&brd_lock, flags);
-		return 0;
-	}
-
-/*
- *	Slave is in action, so now we must wait for the open acknowledgment
- *	to come back.
- */
-	rc = 0;
-	set_bit(ST_OPENING, &portp->state);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_OPENING, &portp->state));
-	if (signal_pending(current))
-		rc = -ERESTARTSYS;
-
-	if ((rc == 0) && (portp->rc != 0))
-		rc = -EIO;
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a close message to the slave. Normally this will sleep waiting
- *	for the acknowledgement, but if wait parameter is 0 it will not. If
- *	wait is true then must have user context (to sleep).
- */
-
-static int stli_rawclose(struct stlibrd *brdp, struct stliport *portp, unsigned long arg, int wait)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-	unsigned long flags;
-	int rc;
-
-/*
- *	Slave is already closing this port. This can happen if a hangup
- *	occurs on this port.
- */
-	if (wait) {
-		wait_event_interruptible_tty(portp->raw_wait,
-				!test_bit(ST_CLOSING, &portp->state));
-		if (signal_pending(current)) {
-			return -ERESTARTSYS;
-		}
-	}
-
-/*
- *	Write the close command into shared memory.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	writel(arg, &cp->closearg);
-	writeb(1, &cp->close);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) |portp->portbit, bits);
-	EBRDDISABLE(brdp);
-
-	set_bit(ST_CLOSING, &portp->state);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (wait == 0)
-		return 0;
-
-/*
- *	Slave is in action, so now we must wait for the open acknowledgment
- *	to come back.
- */
-	rc = 0;
-	wait_event_interruptible_tty(portp->raw_wait,
-			!test_bit(ST_CLOSING, &portp->state));
-	if (signal_pending(current))
-		rc = -ERESTARTSYS;
-
-	if ((rc == 0) && (portp->rc != 0))
-		rc = -EIO;
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a command to the slave and wait for the response. This must
- *	have user context (it sleeps). This routine is generic in that it
- *	can send any type of command. Its purpose is to wait for that command
- *	to complete (as opposed to initiating the command then returning).
- */
-
-static int stli_cmdwait(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	/*
-	 * no need for wait_event_tty because clearing ST_CMDING cannot block
-	 * on BTM
-	 */
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-
-	wait_event_interruptible(portp->raw_wait,
-			!test_bit(ST_CMDING, &portp->state));
-	if (signal_pending(current))
-		return -ERESTARTSYS;
-
-	if (portp->rc != 0)
-		return -EIO;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Send the termios settings for this port to the slave. This sleeps
- *	waiting for the command to complete - so must have user context.
- */
-
-static int stli_setport(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	asyport_t aport;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	stli_mkasyport(tty, portp, &aport, tty->termios);
-	return(stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0));
-}
-
-/*****************************************************************************/
-
-static int stli_carrier_raised(struct tty_port *port)
-{
-	struct stliport *portp = container_of(port, struct stliport, port);
-	return (portp->sigs & TIOCM_CD) ? 1 : 0;
-}
-
-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, on, on);
-	if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-		sizeof(asysigs_t), 0) < 0)
-			printk(KERN_WARNING "istallion: dtr set failed.\n");
-}
-
-
-/*****************************************************************************/
-
-/*
- *	Write routine. Take the data and put it in the shared memory ring
- *	queue. If port is not already sending chars then need to mark the
- *	service bits for this port.
- */
-
-static int stli_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	cdkasy_t __iomem *ap;
-	cdkhdr_t __iomem *hdrp;
-	unsigned char __iomem *bits;
-	unsigned char __iomem *shbuf;
-	unsigned char *chbuf;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int len, stlen, head, tail, size;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	chbuf = (unsigned char *) buf;
-
-/*
- *	All data is now local, shove as much as possible into shared memory.
- */
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) readw(&ap->txq.head);
-	tail = (unsigned int) readw(&ap->txq.tail);
-	if (tail != ((unsigned int) readw(&ap->txq.tail)))
-		tail = (unsigned int) readw(&ap->txq.tail);
-	size = portp->txsize;
-	if (head >= tail) {
-		len = size - (head - tail) - 1;
-		stlen = size - head;
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, (unsigned int)count);
-	count = 0;
-	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->txoffset);
-
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy_toio(shbuf + head, chbuf, stlen);
-		chbuf += stlen;
-		len -= stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= size) {
-			head = 0;
-			stlen = tail;
-		}
-	}
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	writew(head, &ap->txq.head);
-	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (readl(&ap->changed.data) & DT_TXEMPTY)
-			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
-	}
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_TXBUSY, &portp->state);
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return(count);
-}
-
-/*****************************************************************************/
-
-/*
- *	Output a single character. We put it into a temporary local buffer
- *	(for speed) then write out that buffer when the flushchars routine
- *	is called. There is a safety catch here so that if some other port
- *	writes chars before the current buffer has been, then we write them
- *	first them do the new ports.
- */
-
-static int stli_putchar(struct tty_struct *tty, unsigned char ch)
-{
-	if (tty != stli_txcooktty) {
-		if (stli_txcooktty != NULL)
-			stli_flushchars(stli_txcooktty);
-		stli_txcooktty = tty;
-	}
-
-	stli_txcookbuf[stli_txcooksize++] = ch;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Transfer characters from the local TX cooking buffer to the board.
- *	We sort of ignore the tty that gets passed in here. We rely on the
- *	info stored with the TX cook buffer to tell us which port to flush
- *	the data on. In any case we clean out the TX cook buffer, for re-use
- *	by someone else.
- */
-
-static void stli_flushchars(struct tty_struct *tty)
-{
-	cdkhdr_t __iomem *hdrp;
-	unsigned char __iomem *bits;
-	cdkasy_t __iomem *ap;
-	struct tty_struct *cooktty;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int len, stlen, head, tail, size, count, cooksize;
-	unsigned char *buf;
-	unsigned char __iomem *shbuf;
-	unsigned long flags;
-
-	cooksize = stli_txcooksize;
-	cooktty = stli_txcooktty;
-	stli_txcooksize = 0;
-	stli_txcookrealsize = 0;
-	stli_txcooktty = NULL;
-
-	if (cooktty == NULL)
-		return;
-	if (tty != cooktty)
-		tty = cooktty;
-	if (cooksize == 0)
-		return;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	head = (unsigned int) readw(&ap->txq.head);
-	tail = (unsigned int) readw(&ap->txq.tail);
-	if (tail != ((unsigned int) readw(&ap->txq.tail)))
-		tail = (unsigned int) readw(&ap->txq.tail);
-	size = portp->txsize;
-	if (head >= tail) {
-		len = size - (head - tail) - 1;
-		stlen = size - head;
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, cooksize);
-	count = 0;
-	shbuf = EBRDGETMEMPTR(brdp, portp->txoffset);
-	buf = stli_txcookbuf;
-
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy_toio(shbuf + head, buf, stlen);
-		buf += stlen;
-		len -= stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= size) {
-			head = 0;
-			stlen = tail;
-		}
-	}
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	writew(head, &ap->txq.head);
-
-	if (test_bit(ST_TXBUSY, &portp->state)) {
-		if (readl(&ap->changed.data) & DT_TXEMPTY)
-			writel(readl(&ap->changed.data) & ~DT_TXEMPTY, &ap->changed.data);
-	}
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_TXBUSY, &portp->state);
-
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static int stli_writeroom(struct tty_struct *tty)
-{
-	cdkasyrq_t __iomem *rp;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int head, tail, len;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty) {
-		if (stli_txcookrealsize != 0) {
-			len = stli_txcookrealsize - stli_txcooksize;
-			return len;
-		}
-	}
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	if (tail != ((unsigned int) readw(&rp->tail)))
-		tail = (unsigned int) readw(&rp->tail);
-	len = (head >= tail) ? (portp->txsize - (head - tail)) : (tail - head);
-	len--;
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (tty == stli_txcooktty) {
-		stli_txcookrealsize = len;
-		len -= stli_txcooksize;
-	}
-	return len;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the number of characters in the transmit buffer. Normally we
- *	will return the number of chars in the shared memory ring queue.
- *	We need to kludge around the case where the shared memory buffer is
- *	empty but not all characters have drained yet, for this case just
- *	return that there is 1 character in the buffer!
- */
-
-static int stli_charsinbuffer(struct tty_struct *tty)
-{
-	cdkasyrq_t __iomem *rp;
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned int head, tail, len;
-	unsigned long flags;
-
-	if (tty == stli_txcooktty)
-		stli_flushchars(tty);
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->txq;
-	head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	if (tail != ((unsigned int) readw(&rp->tail)))
-		tail = (unsigned int) readw(&rp->tail);
-	len = (head >= tail) ? (head - tail) : (portp->txsize - (tail - head));
-	if ((len == 0) && test_bit(ST_TXBUSY, &portp->state))
-		len = 1;
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return len;
-}
-
-/*****************************************************************************/
-
-/*
- *	Generate the serial struct info.
- */
-
-static int stli_getserial(struct stliport *portp, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-	struct stlibrd *brdp;
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-	sio.type = PORT_UNKNOWN;
-	sio.line = portp->portnr;
-	sio.irq = 0;
-	sio.flags = portp->port.flags;
-	sio.baud_base = portp->baud_base;
-	sio.close_delay = portp->port.close_delay;
-	sio.closing_wait = portp->closing_wait;
-	sio.custom_divisor = portp->custom_divisor;
-	sio.xmit_fifo_size = 0;
-	sio.hub6 = 0;
-
-	brdp = stli_brds[portp->brdnr];
-	if (brdp != NULL)
-		sio.port = brdp->iobase;
-		
-	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ?
-			-EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Set port according to the serial struct info.
- *	At this point we do not do any auto-configure stuff, so we will
- *	just quietly ignore any requests to change irq, etc.
- */
-
-static int stli_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
-{
-	struct serial_struct sio;
-	int rc;
-	struct stliport *portp = tty->driver_data;
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return -EFAULT;
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != portp->baud_base) ||
-		    (sio.close_delay != portp->port.close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		    (portp->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-	} 
-
-	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-	portp->baud_base = sio.baud_base;
-	portp->port.close_delay = sio.close_delay;
-	portp->closing_wait = sio.closing_wait;
-	portp->custom_divisor = sio.custom_divisor;
-
-	if ((rc = stli_setport(tty)) < 0)
-		return rc;
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int stli_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	int rc;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if ((rc = stli_cmdwait(brdp, portp, A_GETSIGNALS,
-			       &portp->asig, sizeof(asysigs_t), 1)) < 0)
-		return rc;
-
-	return stli_mktiocm(portp->asig.sigvalue);
-}
-
-static int stli_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear)
-{
-	struct stliport *portp = tty->driver_data;
-	struct stlibrd *brdp;
-	int rts = -1, dtr = -1;
-
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	stli_mkasysigs(&portp->asig, dtr, rts);
-
-	return stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-			    sizeof(asysigs_t), 0);
-}
-
-static int stli_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	int rc;
-	void __user *argp = (void __user *)arg;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (portp->brdnr >= stli_nrbrds)
-		return 0;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return 0;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
-	}
-
-	rc = 0;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = stli_getserial(portp, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = stli_setserial(tty, argp);
-		break;
-	case STL_GETPFLAG:
-		rc = put_user(portp->pflag, (unsigned __user *)argp);
-		break;
-	case STL_SETPFLAG:
-		if ((rc = get_user(portp->pflag, (unsigned __user *)argp)) == 0)
-			stli_setport(tty);
-		break;
-	case COM_GETPORTSTATS:
-		rc = stli_getportstats(tty, portp, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stli_clrportstats(portp, argp);
-		break;
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERSWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	This routine assumes that we have user context and can sleep.
- *	Looks like it is true for the current ttys implementation..!!
- */
-
-static void stli_settermios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	struct ktermios *tiosp;
-	asyport_t aport;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	tiosp = tty->termios;
-
-	stli_mkasyport(tty, portp, &aport, tiosp);
-	stli_cmdwait(brdp, portp, A_SETPORT, &aport, sizeof(asyport_t), 0);
-	stli_mkasysigs(&portp->asig, ((tiosp->c_cflag & CBAUD) ? 1 : 0), -1);
-	stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
-		sizeof(asysigs_t), 0);
-	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0))
-		tty->hw_stopped = 0;
-	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
-		wake_up_interruptible(&portp->port.open_wait);
-}
-
-/*****************************************************************************/
-
-/*
- *	Attempt to flow control who ever is sending us data. We won't really
- *	do any flow control action here. We can't directly, and even if we
- *	wanted to we would have to send a command to the slave. The slave
- *	knows how to flow control, and will do so when its buffers reach its
- *	internal high water marks. So what we will do is set a local state
- *	bit that will stop us sending any RX data up from the poll routine
- *	(which is the place where RX data from the slave is handled).
- */
-
-static void stli_throttle(struct tty_struct *tty)
-{
-	struct stliport	*portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	set_bit(ST_RXSTOP, &portp->state);
-}
-
-/*****************************************************************************/
-
-/*
- *	Unflow control the device sending us data... That means that all
- *	we have to do is clear the RXSTOP state bit. The next poll call
- *	will then be able to pass the RX data back up.
- */
-
-static void stli_unthrottle(struct tty_struct *tty)
-{
-	struct stliport	*portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	clear_bit(ST_RXSTOP, &portp->state);
-}
-
-/*****************************************************************************/
-
-/*
- *	Stop the transmitter.
- */
-
-static void stli_stop(struct tty_struct *tty)
-{
-}
-
-/*****************************************************************************/
-
-/*
- *	Start the transmitter again.
- */
-
-static void stli_start(struct tty_struct *tty)
-{
-}
-
-/*****************************************************************************/
-
-
-/*
- *	Hangup this port. This is pretty much like closing the port, only
- *	a little more brutal. No waiting for data to drain. Shutdown the
- *	port and maybe drop signals. This is rather tricky really. We want
- *	to close the port as well.
- */
-
-static void stli_hangup(struct tty_struct *tty)
-{
-	struct stliport *portp = tty->driver_data;
-	tty_port_hangup(&portp->port);
-}
-
-/*****************************************************************************/
-
-/*
- *	Flush characters from the lower buffer. We may not have user context
- *	so we cannot sleep waiting for it to complete. Also we need to check
- *	if there is chars for this port in the TX cook buffer, and flush them
- *	as well.
- */
-
-static void stli_flushbuffer(struct tty_struct *tty)
-{
-	struct stliport *portp;
-	struct stlibrd *brdp;
-	unsigned long ftype, flags;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	if (tty == stli_txcooktty) {
-		stli_txcooktty = NULL;
-		stli_txcooksize = 0;
-		stli_txcookrealsize = 0;
-	}
-	if (test_bit(ST_CMDING, &portp->state)) {
-		set_bit(ST_DOFLUSHTX, &portp->state);
-	} else {
-		ftype = FLUSHTX;
-		if (test_bit(ST_DOFLUSHRX, &portp->state)) {
-			ftype |= FLUSHRX;
-			clear_bit(ST_DOFLUSHRX, &portp->state);
-		}
-		__stli_sendcmd(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
-	}
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
-static int stli_breakctl(struct tty_struct *tty, int state)
-{
-	struct stlibrd	*brdp;
-	struct stliport	*portp;
-	long		arg;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-	if (portp->brdnr >= stli_nrbrds)
-		return -EINVAL;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -EINVAL;
-
-	arg = (state == -1) ? BREAKON : BREAKOFF;
-	stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void stli_waituntilsent(struct tty_struct *tty, int timeout)
-{
-	struct stliport *portp;
-	unsigned long tend;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (timeout == 0)
-		timeout = HZ;
-	tend = jiffies + timeout;
-
-	while (test_bit(ST_TXBUSY, &portp->state)) {
-		if (signal_pending(current))
-			break;
-		msleep_interruptible(20);
-		if (time_after_eq(jiffies, tend))
-			break;
-	}
-}
-
-/*****************************************************************************/
-
-static void stli_sendxchar(struct tty_struct *tty, char ch)
-{
-	struct stlibrd	*brdp;
-	struct stliport	*portp;
-	asyctrl_t	actrl;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->brdnr >= stli_nrbrds)
-		return;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-	memset(&actrl, 0, sizeof(asyctrl_t));
-	if (ch == STOP_CHAR(tty)) {
-		actrl.rxctrl = CT_STOPFLOW;
-	} else if (ch == START_CHAR(tty)) {
-		actrl.rxctrl = CT_STARTFLOW;
-	} else {
-		actrl.txctrl = CT_SENDCHR;
-		actrl.tximdch = ch;
-	}
-	stli_cmdwait(brdp, portp, A_PORTCTRL, &actrl, sizeof(asyctrl_t), 0);
-}
-
-static void stli_portinfo(struct seq_file *m, struct stlibrd *brdp, struct stliport *portp, int portnr)
-{
-	char *uart;
-	int rc;
-
-	rc = stli_portcmdstats(NULL, portp);
-
-	uart = "UNKNOWN";
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		switch (stli_comstats.hwid) {
-		case 0:	uart = "2681"; break;
-		case 1:	uart = "SC26198"; break;
-		default:uart = "CD1400"; break;
-		}
-	}
-	seq_printf(m, "%d: uart:%s ", portnr, uart);
-
-	if (test_bit(BST_STARTED, &brdp->state) && rc >= 0) {
-		char sep;
-
-		seq_printf(m, "tx:%d rx:%d", (int) stli_comstats.txtotal,
-			(int) stli_comstats.rxtotal);
-
-		if (stli_comstats.rxframing)
-			seq_printf(m, " fe:%d",
-				(int) stli_comstats.rxframing);
-		if (stli_comstats.rxparity)
-			seq_printf(m, " pe:%d",
-				(int) stli_comstats.rxparity);
-		if (stli_comstats.rxbreaks)
-			seq_printf(m, " brk:%d",
-				(int) stli_comstats.rxbreaks);
-		if (stli_comstats.rxoverrun)
-			seq_printf(m, " oe:%d",
-				(int) stli_comstats.rxoverrun);
-
-		sep = ' ';
-		if (stli_comstats.signals & TIOCM_RTS) {
-			seq_printf(m, "%c%s", sep, "RTS");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_CTS) {
-			seq_printf(m, "%c%s", sep, "CTS");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_DTR) {
-			seq_printf(m, "%c%s", sep, "DTR");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_CD) {
-			seq_printf(m, "%c%s", sep, "DCD");
-			sep = '|';
-		}
-		if (stli_comstats.signals & TIOCM_DSR) {
-			seq_printf(m, "%c%s", sep, "DSR");
-			sep = '|';
-		}
-	}
-	seq_putc(m, '\n');
-}
-
-/*****************************************************************************/
-
-/*
- *	Port info, read from the /proc file system.
- */
-
-static int stli_proc_show(struct seq_file *m, void *v)
-{
-	struct stlibrd *brdp;
-	struct stliport *portp;
-	unsigned int brdnr, portnr, totalport;
-
-	totalport = 0;
-
-	seq_printf(m, "%s: version %s\n", stli_drvtitle, stli_drvversion);
-
-/*
- *	We scan through for each board, panel and port. The offset is
- *	calculated on the fly, and irrelevant ports are skipped.
- */
-	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
-		brdp = stli_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-
-		totalport = brdnr * STL_MAXPORTS;
-		for (portnr = 0; (portnr < brdp->nrports); portnr++,
-		    totalport++) {
-			portp = brdp->ports[portnr];
-			if (portp == NULL)
-				continue;
-			stli_portinfo(m, brdp, portp, totalport);
-		}
-	}
-	return 0;
-}
-
-static int stli_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, stli_proc_show, NULL);
-}
-
-static const struct file_operations stli_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= stli_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*****************************************************************************/
-
-/*
- *	Generic send command routine. This will send a message to the slave,
- *	of the specified type with the specified argument. Must be very
- *	careful of data that will be copied out from shared memory -
- *	containing command results. The command completion is all done from
- *	a poll routine that does not have user context. Therefore you cannot
- *	copy back directly into user space, or to the kernel stack of a
- *	process. This routine does not sleep, so can be called from anywhere.
- *
- *	The caller must hold the brd_lock (see also stli_sendcmd the usual
- *	entry point)
- */
-
-static void __stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkctrl_t __iomem *cp;
-	unsigned char __iomem *bits;
-
-	if (test_bit(ST_CMDING, &portp->state)) {
-		printk(KERN_ERR "istallion: command already busy, cmd=%x!\n",
-				(int) cmd);
-		return;
-	}
-
-	EBRDENABLE(brdp);
-	cp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->ctrl;
-	if (size > 0) {
-		memcpy_toio((void __iomem *) &(cp->args[0]), arg, size);
-		if (copyback) {
-			portp->argp = arg;
-			portp->argsize = size;
-		}
-	}
-	writel(0, &cp->status);
-	writel(cmd, &cp->cmd);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	bits = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset +
-		portp->portidx;
-	writeb(readb(bits) | portp->portbit, bits);
-	set_bit(ST_CMDING, &portp->state);
-	EBRDDISABLE(brdp);
-}
-
-static void stli_sendcmd(struct stlibrd *brdp, struct stliport *portp, unsigned long cmd, void *arg, int size, int copyback)
-{
-	unsigned long		flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	__stli_sendcmd(brdp, portp, cmd, arg, size, copyback);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Read data from shared memory. This assumes that the shared memory
- *	is enabled and that interrupts are off. Basically we just empty out
- *	the shared memory buffer into the tty buffer. Must be careful to
- *	handle the case where we fill up the tty buffer, but still have
- *	more chars to unload.
- */
-
-static void stli_read(struct stlibrd *brdp, struct stliport *portp)
-{
-	cdkasyrq_t __iomem *rp;
-	char __iomem *shbuf;
-	struct tty_struct	*tty;
-	unsigned int head, tail, size;
-	unsigned int len, stlen;
-
-	if (test_bit(ST_RXSTOP, &portp->state))
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	head = (unsigned int) readw(&rp->head);
-	if (head != ((unsigned int) readw(&rp->head)))
-		head = (unsigned int) readw(&rp->head);
-	tail = (unsigned int) readw(&rp->tail);
-	size = portp->rxsize;
-	if (head >= tail) {
-		len = head - tail;
-		stlen = len;
-	} else {
-		len = size - (tail - head);
-		stlen = size - tail;
-	}
-
-	len = tty_buffer_request_room(tty, len);
-
-	shbuf = (char __iomem *) EBRDGETMEMPTR(brdp, portp->rxoffset);
-
-	while (len > 0) {
-		unsigned char *cptr;
-
-		stlen = min(len, stlen);
-		tty_prepare_flip_string(tty, &cptr, stlen);
-		memcpy_fromio(cptr, shbuf + tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= size) {
-			tail = 0;
-			stlen = head;
-		}
-	}
-	rp = &((cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr))->rxq;
-	writew(tail, &rp->tail);
-
-	if (head != tail)
-		set_bit(ST_RXING, &portp->state);
-
-	tty_schedule_flip(tty);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up and carry out any delayed commands. There is only a small set
- *	of slave commands that can be done "off-level". So it is not too
- *	difficult to deal with them here.
- */
-
-static void stli_dodelaycmd(struct stliport *portp, cdkctrl_t __iomem *cp)
-{
-	int cmd;
-
-	if (test_bit(ST_DOSIGS, &portp->state)) {
-		if (test_bit(ST_DOFLUSHTX, &portp->state) &&
-		    test_bit(ST_DOFLUSHRX, &portp->state))
-			cmd = A_SETSIGNALSF;
-		else if (test_bit(ST_DOFLUSHTX, &portp->state))
-			cmd = A_SETSIGNALSFTX;
-		else if (test_bit(ST_DOFLUSHRX, &portp->state))
-			cmd = A_SETSIGNALSFRX;
-		else
-			cmd = A_SETSIGNALS;
-		clear_bit(ST_DOFLUSHTX, &portp->state);
-		clear_bit(ST_DOFLUSHRX, &portp->state);
-		clear_bit(ST_DOSIGS, &portp->state);
-		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &portp->asig,
-			sizeof(asysigs_t));
-		writel(0, &cp->status);
-		writel(cmd, &cp->cmd);
-		set_bit(ST_CMDING, &portp->state);
-	} else if (test_bit(ST_DOFLUSHTX, &portp->state) ||
-	    test_bit(ST_DOFLUSHRX, &portp->state)) {
-		cmd = ((test_bit(ST_DOFLUSHTX, &portp->state)) ? FLUSHTX : 0);
-		cmd |= ((test_bit(ST_DOFLUSHRX, &portp->state)) ? FLUSHRX : 0);
-		clear_bit(ST_DOFLUSHTX, &portp->state);
-		clear_bit(ST_DOFLUSHRX, &portp->state);
-		memcpy_toio((void __iomem *) &(cp->args[0]), (void *) &cmd, sizeof(int));
-		writel(0, &cp->status);
-		writel(A_FLUSH, &cp->cmd);
-		set_bit(ST_CMDING, &portp->state);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Host command service checking. This handles commands or messages
- *	coming from the slave to the host. Must have board shared memory
- *	enabled and interrupts off when called. Notice that by servicing the
- *	read data last we don't need to change the shared memory pointer
- *	during processing (which is a slow IO operation).
- *	Return value indicates if this port is still awaiting actions from
- *	the slave (like open, command, or even TX data being sent). If 0
- *	then port is still busy, otherwise no longer busy.
- */
-
-static int stli_hostcmd(struct stlibrd *brdp, struct stliport *portp)
-{
-	cdkasy_t __iomem *ap;
-	cdkctrl_t __iomem *cp;
-	struct tty_struct *tty;
-	asynotify_t nt;
-	unsigned long oldsigs;
-	int rc, donerx;
-
-	ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-	cp = &ap->ctrl;
-
-/*
- *	Check if we are waiting for an open completion message.
- */
-	if (test_bit(ST_OPENING, &portp->state)) {
-		rc = readl(&cp->openarg);
-		if (readb(&cp->open) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			writel(0, &cp->openarg);
-			portp->rc = rc;
-			clear_bit(ST_OPENING, &portp->state);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check if we are waiting for a close completion message.
- */
-	if (test_bit(ST_CLOSING, &portp->state)) {
-		rc = (int) readl(&cp->closearg);
-		if (readb(&cp->close) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			writel(0, &cp->closearg);
-			portp->rc = rc;
-			clear_bit(ST_CLOSING, &portp->state);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check if we are waiting for a command completion message. We may
- *	need to copy out the command results associated with this command.
- */
-	if (test_bit(ST_CMDING, &portp->state)) {
-		rc = readl(&cp->status);
-		if (readl(&cp->cmd) == 0 && rc != 0) {
-			if (rc > 0)
-				rc--;
-			if (portp->argp != NULL) {
-				memcpy_fromio(portp->argp, (void __iomem *) &(cp->args[0]),
-					portp->argsize);
-				portp->argp = NULL;
-			}
-			writel(0, &cp->status);
-			portp->rc = rc;
-			clear_bit(ST_CMDING, &portp->state);
-			stli_dodelaycmd(portp, cp);
-			wake_up_interruptible(&portp->raw_wait);
-		}
-	}
-
-/*
- *	Check for any notification messages ready. This includes lots of
- *	different types of events - RX chars ready, RX break received,
- *	TX data low or empty in the slave, modem signals changed state.
- */
-	donerx = 0;
-
-	if (ap->notify) {
-		nt = ap->changed;
-		ap->notify = 0;
-		tty = tty_port_tty_get(&portp->port);
-
-		if (nt.signal & SG_DCD) {
-			oldsigs = portp->sigs;
-			portp->sigs = stli_mktiocm(nt.sigvalue);
-			clear_bit(ST_GETSIGS, &portp->state);
-			if ((portp->sigs & TIOCM_CD) &&
-			    ((oldsigs & TIOCM_CD) == 0))
-				wake_up_interruptible(&portp->port.open_wait);
-			if ((oldsigs & TIOCM_CD) &&
-			    ((portp->sigs & TIOCM_CD) == 0)) {
-				if (portp->port.flags & ASYNC_CHECK_CD) {
-					if (tty)
-						tty_hangup(tty);
-				}
-			}
-		}
-
-		if (nt.data & DT_TXEMPTY)
-			clear_bit(ST_TXBUSY, &portp->state);
-		if (nt.data & (DT_TXEMPTY | DT_TXLOW)) {
-			if (tty != NULL) {
-				tty_wakeup(tty);
-				EBRDENABLE(brdp);
-			}
-		}
-
-		if ((nt.data & DT_RXBREAK) && (portp->rxmarkmsk & BRKINT)) {
-			if (tty != NULL) {
-				tty_insert_flip_char(tty, 0, TTY_BREAK);
-				if (portp->port.flags & ASYNC_SAK) {
-					do_SAK(tty);
-					EBRDENABLE(brdp);
-				}
-				tty_schedule_flip(tty);
-			}
-		}
-		tty_kref_put(tty);
-
-		if (nt.data & DT_RXBUSY) {
-			donerx++;
-			stli_read(brdp, portp);
-		}
-	}
-
-/*
- *	It might seem odd that we are checking for more RX chars here.
- *	But, we need to handle the case where the tty buffer was previously
- *	filled, but we had more characters to pass up. The slave will not
- *	send any more RX notify messages until the RX buffer has been emptied.
- *	But it will leave the service bits on (since the buffer is not empty).
- *	So from here we can try to process more RX chars.
- */
-	if ((!donerx) && test_bit(ST_RXING, &portp->state)) {
-		clear_bit(ST_RXING, &portp->state);
-		stli_read(brdp, portp);
-	}
-
-	return((test_bit(ST_OPENING, &portp->state) ||
-		test_bit(ST_CLOSING, &portp->state) ||
-		test_bit(ST_CMDING, &portp->state) ||
-		test_bit(ST_TXBUSY, &portp->state) ||
-		test_bit(ST_RXING, &portp->state)) ? 0 : 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Service all ports on a particular board. Assumes that the boards
- *	shared memory is enabled, and that the page pointer is pointed
- *	at the cdk header structure.
- */
-
-static void stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp)
-{
-	struct stliport *portp;
-	unsigned char hostbits[(STL_MAXCHANS / 8) + 1];
-	unsigned char slavebits[(STL_MAXCHANS / 8) + 1];
-	unsigned char __iomem *slavep;
-	int bitpos, bitat, bitsize;
-	int channr, nrdevs, slavebitchange;
-
-	bitsize = brdp->bitsize;
-	nrdevs = brdp->nrdevs;
-
-/*
- *	Check if slave wants any service. Basically we try to do as
- *	little work as possible here. There are 2 levels of service
- *	bits. So if there is nothing to do we bail early. We check
- *	8 service bits at a time in the inner loop, so we can bypass
- *	the lot if none of them want service.
- */
-	memcpy_fromio(&hostbits[0], (((unsigned char __iomem *) hdrp) + brdp->hostoffset),
-		bitsize);
-
-	memset(&slavebits[0], 0, bitsize);
-	slavebitchange = 0;
-
-	for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-		if (hostbits[bitpos] == 0)
-			continue;
-		channr = bitpos * 8;
-		for (bitat = 0x1; (channr < nrdevs); channr++, bitat <<= 1) {
-			if (hostbits[bitpos] & bitat) {
-				portp = brdp->ports[(channr - 1)];
-				if (stli_hostcmd(brdp, portp)) {
-					slavebitchange++;
-					slavebits[bitpos] |= bitat;
-				}
-			}
-		}
-	}
-
-/*
- *	If any of the ports are no longer busy then update them in the
- *	slave request bits. We need to do this after, since a host port
- *	service may initiate more slave requests.
- */
-	if (slavebitchange) {
-		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		slavep = ((unsigned char __iomem *) hdrp) + brdp->slaveoffset;
-		for (bitpos = 0; (bitpos < bitsize); bitpos++) {
-			if (readb(slavebits + bitpos))
-				writeb(readb(slavep + bitpos) & ~slavebits[bitpos], slavebits + bitpos);
-		}
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Driver poll routine. This routine polls the boards in use and passes
- *	messages back up to host when necessary. This is actually very
- *	CPU efficient, since we will always have the kernel poll clock, it
- *	adds only a few cycles when idle (since board service can be
- *	determined very easily), but when loaded generates no interrupts
- *	(with their expensive associated context change).
- */
-
-static void stli_poll(unsigned long arg)
-{
-	cdkhdr_t __iomem *hdrp;
-	struct stlibrd *brdp;
-	unsigned int brdnr;
-
-	mod_timer(&stli_timerlist, STLI_TIMEOUT);
-
-/*
- *	Check each board and do any servicing required.
- */
-	for (brdnr = 0; (brdnr < stli_nrbrds); brdnr++) {
-		brdp = stli_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (!test_bit(BST_STARTED, &brdp->state))
-			continue;
-
-		spin_lock(&brd_lock);
-		EBRDENABLE(brdp);
-		hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-		if (readb(&hdrp->hostreq))
-			stli_brdpoll(brdp, hdrp);
-		EBRDDISABLE(brdp);
-		spin_unlock(&brd_lock);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Translate the termios settings into the port setting structure of
- *	the slave.
- */
-
-static void stli_mkasyport(struct tty_struct *tty, struct stliport *portp,
-				asyport_t *pp, struct ktermios *tiosp)
-{
-	memset(pp, 0, sizeof(asyport_t));
-
-/*
- *	Start of by setting the baud, char size, parity and stop bit info.
- */
-	pp->baudout = tty_get_baud_rate(tty);
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			pp->baudout = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			pp->baudout = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			pp->baudout = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			pp->baudout = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			pp->baudout = (portp->baud_base / portp->custom_divisor);
-	}
-	if (pp->baudout > STL_MAXBAUD)
-		pp->baudout = STL_MAXBAUD;
-	pp->baudin = pp->baudout;
-
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		pp->csize = 5;
-		break;
-	case CS6:
-		pp->csize = 6;
-		break;
-	case CS7:
-		pp->csize = 7;
-		break;
-	default:
-		pp->csize = 8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		pp->stopbs = PT_STOP2;
-	else
-		pp->stopbs = PT_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			pp->parity = PT_ODDPARITY;
-		else
-			pp->parity = PT_EVENPARITY;
-	} else {
-		pp->parity = PT_NOPARITY;
-	}
-
-/*
- *	Set up any flow control options enabled.
- */
-	if (tiosp->c_iflag & IXON) {
-		pp->flow |= F_IXON;
-		if (tiosp->c_iflag & IXANY)
-			pp->flow |= F_IXANY;
-	}
-	if (tiosp->c_cflag & CRTSCTS)
-		pp->flow |= (F_RTSFLOW | F_CTSFLOW);
-
-	pp->startin = tiosp->c_cc[VSTART];
-	pp->stopin = tiosp->c_cc[VSTOP];
-	pp->startout = tiosp->c_cc[VSTART];
-	pp->stopout = tiosp->c_cc[VSTOP];
-
-/*
- *	Set up the RX char marking mask with those RX error types we must
- *	catch. We can get the slave to help us out a little here, it will
- *	ignore parity errors and breaks for us, and mark parity errors in
- *	the data stream.
- */
-	if (tiosp->c_iflag & IGNPAR)
-		pp->iflag |= FI_IGNRXERRS;
-	if (tiosp->c_iflag & IGNBRK)
-		pp->iflag |= FI_IGNBREAK;
-
-	portp->rxmarkmsk = 0;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		pp->iflag |= FI_1MARKRXERRS;
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= BRKINT;
-
-/*
- *	Set up clocal processing as required.
- */
-	if (tiosp->c_cflag & CLOCAL)
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		portp->port.flags |= ASYNC_CHECK_CD;
-
-/*
- *	Transfer any persistent flags into the asyport structure.
- */
-	pp->pflag = (portp->pflag & 0xffff);
-	pp->vmin = (portp->pflag & P_RXIMIN) ? 1 : 0;
-	pp->vtime = (portp->pflag & P_RXITIME) ? 1 : 0;
-	pp->cc[1] = (portp->pflag & P_RXTHOLD) ? 1 : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Construct a slave signals structure for setting the DTR and RTS
- *	signals as specified.
- */
-
-static void stli_mkasysigs(asysigs_t *sp, int dtr, int rts)
-{
-	memset(sp, 0, sizeof(asysigs_t));
-	if (dtr >= 0) {
-		sp->signal |= SG_DTR;
-		sp->sigvalue |= ((dtr > 0) ? SG_DTR : 0);
-	}
-	if (rts >= 0) {
-		sp->signal |= SG_RTS;
-		sp->sigvalue |= ((rts > 0) ? SG_RTS : 0);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Convert the signals returned from the slave into a local TIOCM type
- *	signals value. We keep them locally in TIOCM format.
- */
-
-static long stli_mktiocm(unsigned long sigvalue)
-{
-	long	tiocm = 0;
-	tiocm |= ((sigvalue & SG_DCD) ? TIOCM_CD : 0);
-	tiocm |= ((sigvalue & SG_CTS) ? TIOCM_CTS : 0);
-	tiocm |= ((sigvalue & SG_RI) ? TIOCM_RI : 0);
-	tiocm |= ((sigvalue & SG_DSR) ? TIOCM_DSR : 0);
-	tiocm |= ((sigvalue & SG_DTR) ? TIOCM_DTR : 0);
-	tiocm |= ((sigvalue & SG_RTS) ? TIOCM_RTS : 0);
-	return(tiocm);
-}
-
-/*****************************************************************************/
-
-/*
- *	All panels and ports actually attached have been worked out. All
- *	we need to do here is set up the appropriate per port data structures.
- */
-
-static int stli_initports(struct stlibrd *brdp)
-{
-	struct stliport	*portp;
-	unsigned int i, panelnr, panelport;
-
-	for (i = 0, panelnr = 0, panelport = 0; (i < brdp->nrports); i++) {
-		portp = kzalloc(sizeof(struct stliport), GFP_KERNEL);
-		if (!portp) {
-			printk(KERN_WARNING "istallion: failed to allocate port structure\n");
-			continue;
-		}
-		tty_port_init(&portp->port);
-		portp->port.ops = &stli_port_ops;
-		portp->magic = STLI_PORTMAGIC;
-		portp->portnr = i;
-		portp->brdnr = brdp->brdnr;
-		portp->panelnr = panelnr;
-		portp->baud_base = STL_BAUDBASE;
-		portp->port.close_delay = STL_CLOSEDELAY;
-		portp->closing_wait = 30 * HZ;
-		init_waitqueue_head(&portp->port.open_wait);
-		init_waitqueue_head(&portp->port.close_wait);
-		init_waitqueue_head(&portp->raw_wait);
-		panelport++;
-		if (panelport >= brdp->panels[panelnr]) {
-			panelport = 0;
-			panelnr++;
-		}
-		brdp->ports[i] = portp;
-	}
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	All the following routines are board specific hardware operations.
- */
-
-static void stli_ecpinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
-	udelay(10);
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-	udelay(100);
-
-	memconf = (brdp->memaddr & ECP_ATADDRMASK) >> ECP_ATADDRSHFT;
-	outb(memconf, (brdp->iobase + ECP_ATMEMAR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpenable(struct stlibrd *brdp)
-{	
-	outb(ECP_ATENABLE, (brdp->iobase + ECP_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpdisable(struct stlibrd *brdp)
-{	
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_ATPAGESIZE);
-		val = (unsigned char) (offset / ECP_ATPAGESIZE);
-	}
-	outb(val, (brdp->iobase + ECP_ATMEMPR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpreset(struct stlibrd *brdp)
-{	
-	outb(ECP_ATSTOP, (brdp->iobase + ECP_ATCONFR));
-	udelay(10);
-	outb(ECP_ATDISABLE, (brdp->iobase + ECP_ATCONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpintr(struct stlibrd *brdp)
-{	
-	outb(0x1, brdp->iobase);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP EISA boards.
- */
-
-static void stli_ecpeiinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
-	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-	udelay(10);
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-	udelay(500);
-
-	memconf = (brdp->memaddr & ECP_EIADDRMASKL) >> ECP_EIADDRSHFTL;
-	outb(memconf, (brdp->iobase + ECP_EIMEMARL));
-	memconf = (brdp->memaddr & ECP_EIADDRMASKH) >> ECP_EIADDRSHFTH;
-	outb(memconf, (brdp->iobase + ECP_EIMEMARH));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeienable(struct stlibrd *brdp)
-{	
-	outb(ECP_EIENABLE, (brdp->iobase + ECP_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeidisable(struct stlibrd *brdp)
-{	
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpeigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char	val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_EIPAGESIZE);
-		if (offset < ECP_EIPAGESIZE)
-			val = ECP_EIENABLE;
-		else
-			val = ECP_EIENABLE | 0x40;
-	}
-	outb(val, (brdp->iobase + ECP_EICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpeireset(struct stlibrd *brdp)
-{	
-	outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-	udelay(10);
-	outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP MCA boards.
- */
-
-static void stli_ecpmcenable(struct stlibrd *brdp)
-{	
-	outb(ECP_MCENABLE, (brdp->iobase + ECP_MCCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcdisable(struct stlibrd *brdp)
-{	
-	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecpmcgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_MCPAGESIZE);
-		val = ((unsigned char) (offset / ECP_MCPAGESIZE)) | ECP_MCENABLE;
-	}
-	outb(val, (brdp->iobase + ECP_MCCONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecpmcreset(struct stlibrd *brdp)
-{	
-	outb(ECP_MCSTOP, (brdp->iobase + ECP_MCCONFR));
-	udelay(10);
-	outb(ECP_MCDISABLE, (brdp->iobase + ECP_MCCONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following set of functions act on ECP PCI boards.
- */
-
-static void stli_ecppciinit(struct stlibrd *brdp)
-{
-	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + ECP_PCICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_ecppcigetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char	val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), board=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ECP_PCIPAGESIZE);
-		val = (offset / ECP_PCIPAGESIZE) << 1;
-	}
-	outb(val, (brdp->iobase + ECP_PCICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_ecppcireset(struct stlibrd *brdp)
-{	
-	outb(ECP_PCISTOP, (brdp->iobase + ECP_PCICONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + ECP_PCICONFR));
-	udelay(500);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on ONboards.
- */
-
-static void stli_onbinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
-	udelay(10);
-	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
-	mdelay(1000);
-
-	memconf = (brdp->memaddr & ONB_ATADDRMASK) >> ONB_ATADDRSHFT;
-	outb(memconf, (brdp->iobase + ONB_ATMEMAR));
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void stli_onbenable(struct stlibrd *brdp)
-{	
-	outb((brdp->enabval | ONB_ATENABLE), (brdp->iobase + ONB_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_onbdisable(struct stlibrd *brdp)
-{	
-	outb((brdp->enabval | ONB_ATDISABLE), (brdp->iobase + ONB_ATCONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_onbgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-				(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-	} else {
-		ptr = brdp->membase + (offset % ONB_ATPAGESIZE);
-	}
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbreset(struct stlibrd *brdp)
-{	
-	outb(ONB_ATSTOP, (brdp->iobase + ONB_ATCONFR));
-	udelay(10);
-	outb(ONB_ATDISABLE, (brdp->iobase + ONB_ATCONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on ONboard EISA.
- */
-
-static void stli_onbeinit(struct stlibrd *brdp)
-{
-	unsigned long	memconf;
-
-	outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
-	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-	udelay(10);
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-	mdelay(1000);
-
-	memconf = (brdp->memaddr & ONB_EIADDRMASKL) >> ONB_EIADDRSHFTL;
-	outb(memconf, (brdp->iobase + ONB_EIMEMARL));
-	memconf = (brdp->memaddr & ONB_EIADDRMASKH) >> ONB_EIADDRSHFTH;
-	outb(memconf, (brdp->iobase + ONB_EIMEMARH));
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void stli_onbeenable(struct stlibrd *brdp)
-{	
-	outb(ONB_EIENABLE, (brdp->iobase + ONB_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void stli_onbedisable(struct stlibrd *brdp)
-{	
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_onbegetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	if (offset > brdp->memsize) {
-		printk(KERN_ERR "istallion: shared memory pointer=%x out of "
-				"range at line=%d(%d), brd=%d\n",
-			(int) offset, line, __LINE__, brdp->brdnr);
-		ptr = NULL;
-		val = 0;
-	} else {
-		ptr = brdp->membase + (offset % ONB_EIPAGESIZE);
-		if (offset < ONB_EIPAGESIZE)
-			val = ONB_EIENABLE;
-		else
-			val = ONB_EIENABLE | 0x40;
-	}
-	outb(val, (brdp->iobase + ONB_EICONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_onbereset(struct stlibrd *brdp)
-{	
-	outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-	udelay(10);
-	outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on Brumby boards.
- */
-
-static void stli_bbyinit(struct stlibrd *brdp)
-{
-	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + BBY_ATCONFR));
-	mdelay(1000);
-	outb(0x1, brdp->iobase);
-	mdelay(1);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_bbygetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	void __iomem *ptr;
-	unsigned char val;
-
-	BUG_ON(offset > brdp->memsize);
-
-	ptr = brdp->membase + (offset % BBY_PAGESIZE);
-	val = (unsigned char) (offset / BBY_PAGESIZE);
-	outb(val, (brdp->iobase + BBY_ATCONFR));
-	return(ptr);
-}
-
-/*****************************************************************************/
-
-static void stli_bbyreset(struct stlibrd *brdp)
-{	
-	outb(BBY_ATSTOP, (brdp->iobase + BBY_ATCONFR));
-	udelay(10);
-	outb(0, (brdp->iobase + BBY_ATCONFR));
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	The following routines act on original old Stallion boards.
- */
-
-static void stli_stalinit(struct stlibrd *brdp)
-{
-	outb(0x1, brdp->iobase);
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-static void __iomem *stli_stalgetmemptr(struct stlibrd *brdp, unsigned long offset, int line)
-{	
-	BUG_ON(offset > brdp->memsize);
-	return brdp->membase + (offset % STAL_PAGESIZE);
-}
-
-/*****************************************************************************/
-
-static void stli_stalreset(struct stlibrd *brdp)
-{	
-	u32 __iomem *vecp;
-
-	vecp = (u32 __iomem *) (brdp->membase + 0x30);
-	writel(0xffff0000, vecp);
-	outb(0, brdp->iobase);
-	mdelay(1000);
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ECP board and initialize it. This handles only ECP
- *	board types.
- */
-
-static int stli_initecp(struct stlibrd *brdp)
-{
-	cdkecpsig_t sig;
-	cdkecpsig_t __iomem *sigsp;
-	unsigned int status, nxtid;
-	char *name;
-	int retval, panelnr, nrports;
-
-	if ((brdp->iobase == 0) || (brdp->memaddr == 0)) {
-		retval = -ENODEV;
-		goto err;
-	}
-
-	brdp->iosize = ECP_IOSIZE;
-
-	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
-		retval = -EIO;
-		goto err;
-	}
-
-/*
- *	Based on the specific board type setup the common vars to access
- *	and enable shared memory. Set all board specific information now
- *	as well.
- */
-	switch (brdp->brdtype) {
-	case BRD_ECP:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_ATPAGESIZE;
-		brdp->init = stli_ecpinit;
-		brdp->enable = stli_ecpenable;
-		brdp->reenable = stli_ecpenable;
-		brdp->disable = stli_ecpdisable;
-		brdp->getmemptr = stli_ecpgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpreset;
-		name = "serial(EC8/64)";
-		break;
-
-	case BRD_ECPE:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_EIPAGESIZE;
-		brdp->init = stli_ecpeiinit;
-		brdp->enable = stli_ecpeienable;
-		brdp->reenable = stli_ecpeienable;
-		brdp->disable = stli_ecpeidisable;
-		brdp->getmemptr = stli_ecpeigetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpeireset;
-		name = "serial(EC8/64-EI)";
-		break;
-
-	case BRD_ECPMC:
-		brdp->memsize = ECP_MEMSIZE;
-		brdp->pagesize = ECP_MCPAGESIZE;
-		brdp->init = NULL;
-		brdp->enable = stli_ecpmcenable;
-		brdp->reenable = stli_ecpmcenable;
-		brdp->disable = stli_ecpmcdisable;
-		brdp->getmemptr = stli_ecpmcgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecpmcreset;
-		name = "serial(EC8/64-MCA)";
-		break;
-
-	case BRD_ECPPCI:
-		brdp->memsize = ECP_PCIMEMSIZE;
-		brdp->pagesize = ECP_PCIPAGESIZE;
-		brdp->init = stli_ecppciinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_ecppcigetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_ecppcireset;
-		name = "serial(EC/RA-PCI)";
-		break;
-
-	default:
-		retval = -EINVAL;
-		goto err_reg;
-	}
-
-/*
- *	The per-board operations structure is all set up, so now let's go
- *	and get the board operational. Firstly initialize board configuration
- *	registers. Set the memory mapping info so we can get at the boards
- *	shared memory.
- */
-	EBRDINIT(brdp);
-
-	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == NULL) {
-		retval = -ENOMEM;
-		goto err_reg;
-	}
-
-/*
- *	Now that all specific code is set up, enable the shared memory and
- *	look for the a signature area that will tell us exactly what board
- *	this is, and what it is connected to it.
- */
-	EBRDENABLE(brdp);
-	sigsp = (cdkecpsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy_fromio(&sig, sigsp, sizeof(cdkecpsig_t));
-	EBRDDISABLE(brdp);
-
-	if (sig.magic != cpu_to_le32(ECP_MAGIC)) {
-		retval = -ENODEV;
-		goto err_unmap;
-	}
-
-/*
- *	Scan through the signature looking at the panels connected to the
- *	board. Calculate the total number of ports as we go.
- */
-	for (panelnr = 0, nxtid = 0; (panelnr < STL_MAXPANELS); panelnr++) {
-		status = sig.panelid[nxtid];
-		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
-
-		brdp->panelids[panelnr] = status;
-		nrports = (status & ECH_PNL16PORT) ? 16 : 8;
-		if ((nrports == 16) && ((status & ECH_PNLXPID) == 0))
-			nxtid++;
-		brdp->panels[panelnr] = nrports;
-		brdp->nrports += nrports;
-		nxtid++;
-		brdp->nrpanels++;
-	}
-
-
-	set_bit(BST_FOUND, &brdp->state);
-	return 0;
-err_unmap:
-	iounmap(brdp->membase);
-	brdp->membase = NULL;
-err_reg:
-	release_region(brdp->iobase, brdp->iosize);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ONboard, Brumby or Stallion board and initialize it.
- *	This handles only these board types.
- */
-
-static int stli_initonb(struct stlibrd *brdp)
-{
-	cdkonbsig_t sig;
-	cdkonbsig_t __iomem *sigsp;
-	char *name;
-	int i, retval;
-
-/*
- *	Do a basic sanity check on the IO and memory addresses.
- */
-	if (brdp->iobase == 0 || brdp->memaddr == 0) {
-		retval = -ENODEV;
-		goto err;
-	}
-
-	brdp->iosize = ONB_IOSIZE;
-	
-	if (!request_region(brdp->iobase, brdp->iosize, "istallion")) {
-		retval = -EIO;
-		goto err;
-	}
-
-/*
- *	Based on the specific board type setup the common vars to access
- *	and enable shared memory. Set all board specific information now
- *	as well.
- */
-	switch (brdp->brdtype) {
-	case BRD_ONBOARD:
-	case BRD_ONBOARD2:
-		brdp->memsize = ONB_MEMSIZE;
-		brdp->pagesize = ONB_ATPAGESIZE;
-		brdp->init = stli_onbinit;
-		brdp->enable = stli_onbenable;
-		brdp->reenable = stli_onbenable;
-		brdp->disable = stli_onbdisable;
-		brdp->getmemptr = stli_onbgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_onbreset;
-		if (brdp->memaddr > 0x100000)
-			brdp->enabval = ONB_MEMENABHI;
-		else
-			brdp->enabval = ONB_MEMENABLO;
-		name = "serial(ONBoard)";
-		break;
-
-	case BRD_ONBOARDE:
-		brdp->memsize = ONB_EIMEMSIZE;
-		brdp->pagesize = ONB_EIPAGESIZE;
-		brdp->init = stli_onbeinit;
-		brdp->enable = stli_onbeenable;
-		brdp->reenable = stli_onbeenable;
-		brdp->disable = stli_onbedisable;
-		brdp->getmemptr = stli_onbegetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_onbereset;
-		name = "serial(ONBoard/E)";
-		break;
-
-	case BRD_BRUMBY4:
-		brdp->memsize = BBY_MEMSIZE;
-		brdp->pagesize = BBY_PAGESIZE;
-		brdp->init = stli_bbyinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_bbygetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_bbyreset;
-		name = "serial(Brumby)";
-		break;
-
-	case BRD_STALLION:
-		brdp->memsize = STAL_MEMSIZE;
-		brdp->pagesize = STAL_PAGESIZE;
-		brdp->init = stli_stalinit;
-		brdp->enable = NULL;
-		brdp->reenable = NULL;
-		brdp->disable = NULL;
-		brdp->getmemptr = stli_stalgetmemptr;
-		brdp->intr = stli_ecpintr;
-		brdp->reset = stli_stalreset;
-		name = "serial(Stallion)";
-		break;
-
-	default:
-		retval = -EINVAL;
-		goto err_reg;
-	}
-
-/*
- *	The per-board operations structure is all set up, so now let's go
- *	and get the board operational. Firstly initialize board configuration
- *	registers. Set the memory mapping info so we can get at the boards
- *	shared memory.
- */
-	EBRDINIT(brdp);
-
-	brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-	if (brdp->membase == NULL) {
-		retval = -ENOMEM;
-		goto err_reg;
-	}
-
-/*
- *	Now that all specific code is set up, enable the shared memory and
- *	look for the a signature area that will tell us exactly what board
- *	this is, and how many ports.
- */
-	EBRDENABLE(brdp);
-	sigsp = (cdkonbsig_t __iomem *) EBRDGETMEMPTR(brdp, CDK_SIGADDR);
-	memcpy_fromio(&sig, sigsp, sizeof(cdkonbsig_t));
-	EBRDDISABLE(brdp);
-
-	if (sig.magic0 != cpu_to_le16(ONB_MAGIC0) ||
-	    sig.magic1 != cpu_to_le16(ONB_MAGIC1) ||
-	    sig.magic2 != cpu_to_le16(ONB_MAGIC2) ||
-	    sig.magic3 != cpu_to_le16(ONB_MAGIC3)) {
-		retval = -ENODEV;
-		goto err_unmap;
-	}
-
-/*
- *	Scan through the signature alive mask and calculate how many ports
- *	there are on this board.
- */
-	brdp->nrpanels = 1;
-	if (sig.amask1) {
-		brdp->nrports = 32;
-	} else {
-		for (i = 0; (i < 16); i++) {
-			if (((sig.amask0 << i) & 0x8000) == 0)
-				break;
-		}
-		brdp->nrports = i;
-	}
-	brdp->panels[0] = brdp->nrports;
-
-
-	set_bit(BST_FOUND, &brdp->state);
-	return 0;
-err_unmap:
-	iounmap(brdp->membase);
-	brdp->membase = NULL;
-err_reg:
-	release_region(brdp->iobase, brdp->iosize);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Start up a running board. This routine is only called after the
- *	code has been down loaded to the board and is operational. It will
- *	read in the memory map, and get the show on the road...
- */
-
-static int stli_startbrd(struct stlibrd *brdp)
-{
-	cdkhdr_t __iomem *hdrp;
-	cdkmem_t __iomem *memp;
-	cdkasy_t __iomem *ap;
-	unsigned long flags;
-	unsigned int portnr, nrdevs, i;
-	struct stliport *portp;
-	int rc = 0;
-	u32 memoff;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	EBRDENABLE(brdp);
-	hdrp = (cdkhdr_t __iomem *) EBRDGETMEMPTR(brdp, CDK_CDKADDR);
-	nrdevs = hdrp->nrdevs;
-
-#if 0
-	printk("%s(%d): CDK version %d.%d.%d --> "
-		"nrdevs=%d memp=%x hostp=%x slavep=%x\n",
-		 __FILE__, __LINE__, readb(&hdrp->ver_release), readb(&hdrp->ver_modification),
-		 readb(&hdrp->ver_fix), nrdevs, (int) readl(&hdrp->memp), readl(&hdrp->hostp),
-		 readl(&hdrp->slavep));
-#endif
-
-	if (nrdevs < (brdp->nrports + 1)) {
-		printk(KERN_ERR "istallion: slave failed to allocate memory for "
-				"all devices, devices=%d\n", nrdevs);
-		brdp->nrports = nrdevs - 1;
-	}
-	brdp->nrdevs = nrdevs;
-	brdp->hostoffset = hdrp->hostp - CDK_CDKADDR;
-	brdp->slaveoffset = hdrp->slavep - CDK_CDKADDR;
-	brdp->bitsize = (nrdevs + 7) / 8;
-	memoff = readl(&hdrp->memp);
-	if (memoff > brdp->memsize) {
-		printk(KERN_ERR "istallion: corrupted shared memory region?\n");
-		rc = -EIO;
-		goto stli_donestartup;
-	}
-	memp = (cdkmem_t __iomem *) EBRDGETMEMPTR(brdp, memoff);
-	if (readw(&memp->dtype) != TYP_ASYNCTRL) {
-		printk(KERN_ERR "istallion: no slave control device found\n");
-		goto stli_donestartup;
-	}
-	memp++;
-
-/*
- *	Cycle through memory allocation of each port. We are guaranteed to
- *	have all ports inside the first page of slave window, so no need to
- *	change pages while reading memory map.
- */
-	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++, memp++) {
-		if (readw(&memp->dtype) != TYP_ASYNC)
-			break;
-		portp = brdp->ports[portnr];
-		if (portp == NULL)
-			break;
-		portp->devnr = i;
-		portp->addr = readl(&memp->offset);
-		portp->reqbit = (unsigned char) (0x1 << (i * 8 / nrdevs));
-		portp->portidx = (unsigned char) (i / 8);
-		portp->portbit = (unsigned char) (0x1 << (i % 8));
-	}
-
-	writeb(0xff, &hdrp->slavereq);
-
-/*
- *	For each port setup a local copy of the RX and TX buffer offsets
- *	and sizes. We do this separate from the above, because we need to
- *	move the shared memory page...
- */
-	for (i = 1, portnr = 0; (i < nrdevs); i++, portnr++) {
-		portp = brdp->ports[portnr];
-		if (portp == NULL)
-			break;
-		if (portp->addr == 0)
-			break;
-		ap = (cdkasy_t __iomem *) EBRDGETMEMPTR(brdp, portp->addr);
-		if (ap != NULL) {
-			portp->rxsize = readw(&ap->rxq.size);
-			portp->txsize = readw(&ap->txq.size);
-			portp->rxoffset = readl(&ap->rxq.offset);
-			portp->txoffset = readl(&ap->txq.offset);
-		}
-	}
-
-stli_donestartup:
-	EBRDDISABLE(brdp);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	if (rc == 0)
-		set_bit(BST_STARTED, &brdp->state);
-
-	if (! stli_timeron) {
-		stli_timeron++;
-		mod_timer(&stli_timerlist, STLI_TIMEOUT);
-	}
-
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Probe and initialize the specified board.
- */
-
-static int __devinit stli_brdinit(struct stlibrd *brdp)
-{
-	int retval;
-
-	switch (brdp->brdtype) {
-	case BRD_ECP:
-	case BRD_ECPE:
-	case BRD_ECPMC:
-	case BRD_ECPPCI:
-		retval = stli_initecp(brdp);
-		break;
-	case BRD_ONBOARD:
-	case BRD_ONBOARDE:
-	case BRD_ONBOARD2:
-	case BRD_BRUMBY4:
-	case BRD_STALLION:
-		retval = stli_initonb(brdp);
-		break;
-	default:
-		printk(KERN_ERR "istallion: board=%d is unknown board "
-				"type=%d\n", brdp->brdnr, brdp->brdtype);
-		retval = -ENODEV;
-	}
-
-	if (retval)
-		return retval;
-
-	stli_initports(brdp);
-	printk(KERN_INFO "istallion: %s found, board=%d io=%x mem=%x "
-		"nrpanels=%d nrports=%d\n", stli_brdnames[brdp->brdtype],
-		brdp->brdnr, brdp->iobase, (int) brdp->memaddr,
-		brdp->nrpanels, brdp->nrports);
-	return 0;
-}
-
-#if STLI_EISAPROBE != 0
-/*****************************************************************************/
-
-/*
- *	Probe around trying to find where the EISA boards shared memory
- *	might be. This is a bit if hack, but it is the best we can do.
- */
-
-static int stli_eisamemprobe(struct stlibrd *brdp)
-{
-	cdkecpsig_t	ecpsig, __iomem *ecpsigp;
-	cdkonbsig_t	onbsig, __iomem *onbsigp;
-	int		i, foundit;
-
-/*
- *	First up we reset the board, to get it into a known state. There
- *	is only 2 board types here we need to worry about. Don;t use the
- *	standard board init routine here, it programs up the shared
- *	memory address, and we don't know it yet...
- */
-	if (brdp->brdtype == BRD_ECPE) {
-		outb(0x1, (brdp->iobase + ECP_EIBRDENAB));
-		outb(ECP_EISTOP, (brdp->iobase + ECP_EICONFR));
-		udelay(10);
-		outb(ECP_EIDISABLE, (brdp->iobase + ECP_EICONFR));
-		udelay(500);
-		stli_ecpeienable(brdp);
-	} else if (brdp->brdtype == BRD_ONBOARDE) {
-		outb(0x1, (brdp->iobase + ONB_EIBRDENAB));
-		outb(ONB_EISTOP, (brdp->iobase + ONB_EICONFR));
-		udelay(10);
-		outb(ONB_EIDISABLE, (brdp->iobase + ONB_EICONFR));
-		mdelay(100);
-		outb(0x1, brdp->iobase);
-		mdelay(1);
-		stli_onbeenable(brdp);
-	} else {
-		return -ENODEV;
-	}
-
-	foundit = 0;
-	brdp->memsize = ECP_MEMSIZE;
-
-/*
- *	Board shared memory is enabled, so now we have a poke around and
- *	see if we can find it.
- */
-	for (i = 0; (i < stli_eisamempsize); i++) {
-		brdp->memaddr = stli_eisamemprobeaddrs[i];
-		brdp->membase = ioremap_nocache(brdp->memaddr, brdp->memsize);
-		if (brdp->membase == NULL)
-			continue;
-
-		if (brdp->brdtype == BRD_ECPE) {
-			ecpsigp = stli_ecpeigetmemptr(brdp,
-				CDK_SIGADDR, __LINE__);
-			memcpy_fromio(&ecpsig, ecpsigp, sizeof(cdkecpsig_t));
-			if (ecpsig.magic == cpu_to_le32(ECP_MAGIC))
-				foundit = 1;
-		} else {
-			onbsigp = (cdkonbsig_t __iomem *) stli_onbegetmemptr(brdp,
-				CDK_SIGADDR, __LINE__);
-			memcpy_fromio(&onbsig, onbsigp, sizeof(cdkonbsig_t));
-			if ((onbsig.magic0 == cpu_to_le16(ONB_MAGIC0)) &&
-			    (onbsig.magic1 == cpu_to_le16(ONB_MAGIC1)) &&
-			    (onbsig.magic2 == cpu_to_le16(ONB_MAGIC2)) &&
-			    (onbsig.magic3 == cpu_to_le16(ONB_MAGIC3)))
-				foundit = 1;
-		}
-
-		iounmap(brdp->membase);
-		if (foundit)
-			break;
-	}
-
-/*
- *	Regardless of whether we found the shared memory or not we must
- *	disable the region. After that return success or failure.
- */
-	if (brdp->brdtype == BRD_ECPE)
-		stli_ecpeidisable(brdp);
-	else
-		stli_onbedisable(brdp);
-
-	if (! foundit) {
-		brdp->memaddr = 0;
-		brdp->membase = NULL;
-		printk(KERN_ERR "istallion: failed to probe shared memory "
-				"region for %s in EISA slot=%d\n",
-			stli_brdnames[brdp->brdtype], (brdp->iobase >> 12));
-		return -ENODEV;
-	}
-	return 0;
-}
-#endif
-
-static int stli_getbrdnr(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < STL_MAXBRDS; i++) {
-		if (!stli_brds[i]) {
-			if (i >= stli_nrbrds)
-				stli_nrbrds = i + 1;
-			return i;
-		}
-	}
-	return -1;
-}
-
-#if STLI_EISAPROBE != 0
-/*****************************************************************************/
-
-/*
- *	Probe around and try to find any EISA boards in system. The biggest
- *	problem here is finding out what memory address is associated with
- *	an EISA board after it is found. The registers of the ECPE and
- *	ONboardE are not readable - so we can't read them from there. We
- *	don't have access to the EISA CMOS (or EISA BIOS) so we don't
- *	actually have any way to find out the real value. The best we can
- *	do is go probing around in the usual places hoping we can find it.
- */
-
-static int __init stli_findeisabrds(void)
-{
-	struct stlibrd *brdp;
-	unsigned int iobase, eid, i;
-	int brdnr, found = 0;
-
-/*
- *	Firstly check if this is an EISA system.  If this is not an EISA system then
- *	don't bother going any further!
- */
-	if (EISA_bus)
-		return 0;
-
-/*
- *	Looks like an EISA system, so go searching for EISA boards.
- */
-	for (iobase = 0x1000; (iobase <= 0xc000); iobase += 0x1000) {
-		outb(0xff, (iobase + 0xc80));
-		eid = inb(iobase + 0xc80);
-		eid |= inb(iobase + 0xc81) << 8;
-		if (eid != STL_EISAID)
-			continue;
-
-/*
- *		We have found a board. Need to check if this board was
- *		statically configured already (just in case!).
- */
-		for (i = 0; (i < STL_MAXBRDS); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			if (brdp->iobase == iobase)
-				break;
-		}
-		if (i < STL_MAXBRDS)
-			continue;
-
-/*
- *		We have found a Stallion board and it is not configured already.
- *		Allocate a board structure and initialize it.
- */
-		if ((brdp = stli_allocbrd()) == NULL)
-			return found ? : -ENOMEM;
-		brdnr = stli_getbrdnr();
-		if (brdnr < 0)
-			return found ? : -ENOMEM;
-		brdp->brdnr = (unsigned int)brdnr;
-		eid = inb(iobase + 0xc82);
-		if (eid == ECP_EISAID)
-			brdp->brdtype = BRD_ECPE;
-		else if (eid == ONB_EISAID)
-			brdp->brdtype = BRD_ONBOARDE;
-		else
-			brdp->brdtype = BRD_UNKNOWN;
-		brdp->iobase = iobase;
-		outb(0x1, (iobase + 0xc84));
-		if (stli_eisamemprobe(brdp))
-			outb(0, (iobase + 0xc84));
-		if (stli_brdinit(brdp) < 0) {
-			kfree(brdp);
-			continue;
-		}
-
-		stli_brds[brdp->brdnr] = brdp;
-		found++;
-
-		for (i = 0; i < brdp->nrports; i++)
-			tty_register_device(stli_serial,
-					brdp->brdnr * STL_MAXPORTS + i, NULL);
-	}
-
-	return found;
-}
-#else
-static inline int stli_findeisabrds(void) { return 0; }
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Find the next available board number that is free.
- */
-
-/*****************************************************************************/
-
-/*
- *	We have a Stallion board. Allocate a board structure and
- *	initialize it. Read its IO and MEMORY resources from PCI
- *	configuration space.
- */
-
-static int __devinit stli_pciprobe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-	int brdnr, retval = -EIO;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err;
-	brdp = stli_allocbrd();
-	if (brdp == NULL) {
-		retval = -ENOMEM;
-		goto err;
-	}
-	mutex_lock(&stli_brdslock);
-	brdnr = stli_getbrdnr();
-	if (brdnr < 0) {
-		printk(KERN_INFO "istallion: too many boards found, "
-			"maximum supported %d\n", STL_MAXBRDS);
-		mutex_unlock(&stli_brdslock);
-		retval = -EIO;
-		goto err_fr;
-	}
-	brdp->brdnr = (unsigned int)brdnr;
-	stli_brds[brdp->brdnr] = brdp;
-	mutex_unlock(&stli_brdslock);
-	brdp->brdtype = BRD_ECPPCI;
-/*
- *	We have all resources from the board, so lets setup the actual
- *	board structure now.
- */
-	brdp->iobase = pci_resource_start(pdev, 3);
-	brdp->memaddr = pci_resource_start(pdev, 2);
-	retval = stli_brdinit(brdp);
-	if (retval)
-		goto err_null;
-
-	set_bit(BST_PROBED, &brdp->state);
-	pci_set_drvdata(pdev, brdp);
-
-	EBRDENABLE(brdp);
-	brdp->enable = NULL;
-	brdp->disable = NULL;
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_register_device(stli_serial, brdp->brdnr * STL_MAXPORTS + i,
-				&pdev->dev);
-
-	return 0;
-err_null:
-	stli_brds[brdp->brdnr] = NULL;
-err_fr:
-	kfree(brdp);
-err:
-	return retval;
-}
-
-static void __devexit stli_pciremove(struct pci_dev *pdev)
-{
-	struct stlibrd *brdp = pci_get_drvdata(pdev);
-
-	stli_cleanup_ports(brdp);
-
-	iounmap(brdp->membase);
-	if (brdp->iosize > 0)
-		release_region(brdp->iobase, brdp->iosize);
-
-	stli_brds[brdp->brdnr] = NULL;
-	kfree(brdp);
-}
-
-static struct pci_driver stli_pcidriver = {
-	.name = "istallion",
-	.id_table = istallion_pci_tbl,
-	.probe = stli_pciprobe,
-	.remove = __devexit_p(stli_pciremove)
-};
-/*****************************************************************************/
-
-/*
- *	Allocate a new board structure. Fill out the basic info in it.
- */
-
-static struct stlibrd *stli_allocbrd(void)
-{
-	struct stlibrd *brdp;
-
-	brdp = kzalloc(sizeof(struct stlibrd), GFP_KERNEL);
-	if (!brdp) {
-		printk(KERN_ERR "istallion: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlibrd));
-		return NULL;
-	}
-	brdp->magic = STLI_BOARDMAGIC;
-	return brdp;
-}
-
-/*****************************************************************************/
-
-/*
- *	Scan through all the boards in the configuration and see what we
- *	can find.
- */
-
-static int __init stli_initbrds(void)
-{
-	struct stlibrd *brdp, *nxtbrdp;
-	struct stlconf conf;
-	unsigned int i, j, found = 0;
-	int retval;
-
-	for (stli_nrbrds = 0; stli_nrbrds < ARRAY_SIZE(stli_brdsp);
-			stli_nrbrds++) {
-		memset(&conf, 0, sizeof(conf));
-		if (stli_parsebrd(&conf, stli_brdsp[stli_nrbrds]) == 0)
-			continue;
-		if ((brdp = stli_allocbrd()) == NULL)
-			continue;
-		brdp->brdnr = stli_nrbrds;
-		brdp->brdtype = conf.brdtype;
-		brdp->iobase = conf.ioaddr1;
-		brdp->memaddr = conf.memaddr;
-		if (stli_brdinit(brdp) < 0) {
-			kfree(brdp);
-			continue;
-		}
-		stli_brds[brdp->brdnr] = brdp;
-		found++;
-
-		for (i = 0; i < brdp->nrports; i++)
-			tty_register_device(stli_serial,
-					brdp->brdnr * STL_MAXPORTS + i, NULL);
-	}
-
-	retval = stli_findeisabrds();
-	if (retval > 0)
-		found += retval;
-
-/*
- *	All found boards are initialized. Now for a little optimization, if
- *	no boards are sharing the "shared memory" regions then we can just
- *	leave them all enabled. This is in fact the usual case.
- */
-	stli_shared = 0;
-	if (stli_nrbrds > 1) {
-		for (i = 0; (i < stli_nrbrds); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			for (j = i + 1; (j < stli_nrbrds); j++) {
-				nxtbrdp = stli_brds[j];
-				if (nxtbrdp == NULL)
-					continue;
-				if ((brdp->membase >= nxtbrdp->membase) &&
-				    (brdp->membase <= (nxtbrdp->membase +
-				    nxtbrdp->memsize - 1))) {
-					stli_shared++;
-					break;
-				}
-			}
-		}
-	}
-
-	if (stli_shared == 0) {
-		for (i = 0; (i < stli_nrbrds); i++) {
-			brdp = stli_brds[i];
-			if (brdp == NULL)
-				continue;
-			if (test_bit(BST_FOUND, &brdp->state)) {
-				EBRDENABLE(brdp);
-				brdp->enable = NULL;
-				brdp->disable = NULL;
-			}
-		}
-	}
-
-	retval = pci_register_driver(&stli_pcidriver);
-	if (retval && found == 0) {
-		printk(KERN_ERR "Neither isa nor eisa cards found nor pci "
-				"driver can be registered!\n");
-		goto err;
-	}
-
-	return 0;
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Code to handle an "staliomem" read operation. This device is the 
- *	contents of the board shared memory. It is used for down loading
- *	the slave image (and debugging :-)
- */
-
-static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp)
-{
-	unsigned long flags;
-	void __iomem *memptr;
-	struct stlibrd *brdp;
-	unsigned int brdnr;
-	int size, n;
-	void *p;
-	loff_t off = *offp;
-
-	brdnr = iminor(fp->f_path.dentry->d_inode);
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-	if (off >= brdp->memsize || off + count < off)
-		return 0;
-
-	size = min(count, (size_t)(brdp->memsize - off));
-
-	/*
-	 *	Copy the data a page at a time
-	 */
-
-	p = (void *)__get_free_page(GFP_KERNEL);
-	if(p == NULL)
-		return -ENOMEM;
-
-	while (size > 0) {
-		spin_lock_irqsave(&brd_lock, flags);
-		EBRDENABLE(brdp);
-		memptr = EBRDGETMEMPTR(brdp, off);
-		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-		n = min(n, (int)PAGE_SIZE);
-		memcpy_fromio(p, memptr, n);
-		EBRDDISABLE(brdp);
-		spin_unlock_irqrestore(&brd_lock, flags);
-		if (copy_to_user(buf, p, n)) {
-			count = -EFAULT;
-			goto out;
-		}
-		off += n;
-		buf += n;
-		size -= n;
-	}
-out:
-	*offp = off;
-	free_page((unsigned long)p);
-	return count;
-}
-
-/*****************************************************************************/
-
-/*
- *	Code to handle an "staliomem" write operation. This device is the 
- *	contents of the board shared memory. It is used for down loading
- *	the slave image (and debugging :-)
- *
- *	FIXME: copy under lock
- */
-
-static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp)
-{
-	unsigned long flags;
-	void __iomem *memptr;
-	struct stlibrd *brdp;
-	char __user *chbuf;
-	unsigned int brdnr;
-	int size, n;
-	void *p;
-	loff_t off = *offp;
-
-	brdnr = iminor(fp->f_path.dentry->d_inode);
-
-	if (brdnr >= stli_nrbrds)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-	if (off >= brdp->memsize || off + count < off)
-		return 0;
-
-	chbuf = (char __user *) buf;
-	size = min(count, (size_t)(brdp->memsize - off));
-
-	/*
-	 *	Copy the data a page at a time
-	 */
-
-	p = (void *)__get_free_page(GFP_KERNEL);
-	if(p == NULL)
-		return -ENOMEM;
-
-	while (size > 0) {
-		n = min(size, (int)(brdp->pagesize - (((unsigned long) off) % brdp->pagesize)));
-		n = min(n, (int)PAGE_SIZE);
-		if (copy_from_user(p, chbuf, n)) {
-			if (count == 0)
-				count = -EFAULT;
-			goto out;
-		}
-		spin_lock_irqsave(&brd_lock, flags);
-		EBRDENABLE(brdp);
-		memptr = EBRDGETMEMPTR(brdp, off);
-		memcpy_toio(memptr, p, n);
-		EBRDDISABLE(brdp);
-		spin_unlock_irqrestore(&brd_lock, flags);
-		off += n;
-		chbuf += n;
-		size -= n;
-	}
-out:
-	free_page((unsigned long) p);
-	*offp = off;
-	return count;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the board stats structure to user app.
- */
-
-static int stli_getbrdstats(combrd_t __user *bp)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-
-	if (copy_from_user(&stli_brdstats, bp, sizeof(combrd_t)))
-		return -EFAULT;
-	if (stli_brdstats.brd >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[stli_brdstats.brd];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	memset(&stli_brdstats, 0, sizeof(combrd_t));
-
-	stli_brdstats.brd = brdp->brdnr;
-	stli_brdstats.type = brdp->brdtype;
-	stli_brdstats.hwid = 0;
-	stli_brdstats.state = brdp->state;
-	stli_brdstats.ioaddr = brdp->iobase;
-	stli_brdstats.memaddr = brdp->memaddr;
-	stli_brdstats.nrpanels = brdp->nrpanels;
-	stli_brdstats.nrports = brdp->nrports;
-	for (i = 0; (i < brdp->nrpanels); i++) {
-		stli_brdstats.panels[i].panel = i;
-		stli_brdstats.panels[i].hwid = brdp->panelids[i];
-		stli_brdstats.panels[i].nrports = brdp->panels[i];
-	}
-
-	if (copy_to_user(bp, &stli_brdstats, sizeof(combrd_t)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Resolve the referenced port number into a port struct pointer.
- */
-
-static struct stliport *stli_getport(unsigned int brdnr, unsigned int panelnr,
-		unsigned int portnr)
-{
-	struct stlibrd *brdp;
-	unsigned int i;
-
-	if (brdnr >= STL_MAXBRDS)
-		return NULL;
-	brdp = stli_brds[brdnr];
-	if (brdp == NULL)
-		return NULL;
-	for (i = 0; (i < panelnr); i++)
-		portnr += brdp->panels[i];
-	if (portnr >= brdp->nrports)
-		return NULL;
-	return brdp->ports[portnr];
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stli_portcmdstats(struct tty_struct *tty, struct stliport *portp)
-{
-	unsigned long	flags;
-	struct stlibrd	*brdp;
-	int		rc;
-
-	memset(&stli_comstats, 0, sizeof(comstats_t));
-
-	if (portp == NULL)
-		return -ENODEV;
-	brdp = stli_brds[portp->brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	mutex_lock(&portp->port.mutex);
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		if ((rc = stli_cmdwait(brdp, portp, A_GETSTATS,
-		    &stli_cdkstats, sizeof(asystats_t), 1)) < 0) {
-			mutex_unlock(&portp->port.mutex);
-			return rc;
-		}
-	} else {
-		memset(&stli_cdkstats, 0, sizeof(asystats_t));
-	}
-
-	stli_comstats.brd = portp->brdnr;
-	stli_comstats.panel = portp->panelnr;
-	stli_comstats.port = portp->portnr;
-	stli_comstats.state = portp->state;
-	stli_comstats.flags = portp->port.flags;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	if (tty != NULL) {
-		if (portp->port.tty == tty) {
-			stli_comstats.ttystate = tty->flags;
-			stli_comstats.rxbuffered = -1;
-			if (tty->termios != NULL) {
-				stli_comstats.cflags = tty->termios->c_cflag;
-				stli_comstats.iflags = tty->termios->c_iflag;
-				stli_comstats.oflags = tty->termios->c_oflag;
-				stli_comstats.lflags = tty->termios->c_lflag;
-			}
-		}
-	}
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	stli_comstats.txtotal = stli_cdkstats.txchars;
-	stli_comstats.rxtotal = stli_cdkstats.rxchars + stli_cdkstats.ringover;
-	stli_comstats.txbuffered = stli_cdkstats.txringq;
-	stli_comstats.rxbuffered += stli_cdkstats.rxringq;
-	stli_comstats.rxoverrun = stli_cdkstats.overruns;
-	stli_comstats.rxparity = stli_cdkstats.parity;
-	stli_comstats.rxframing = stli_cdkstats.framing;
-	stli_comstats.rxlost = stli_cdkstats.ringover;
-	stli_comstats.rxbreaks = stli_cdkstats.rxbreaks;
-	stli_comstats.txbreaks = stli_cdkstats.txbreaks;
-	stli_comstats.txxon = stli_cdkstats.txstart;
-	stli_comstats.txxoff = stli_cdkstats.txstop;
-	stli_comstats.rxxon = stli_cdkstats.rxstart;
-	stli_comstats.rxxoff = stli_cdkstats.rxstop;
-	stli_comstats.rxrtsoff = stli_cdkstats.rtscnt / 2;
-	stli_comstats.rxrtson = stli_cdkstats.rtscnt - stli_comstats.rxrtsoff;
-	stli_comstats.modem = stli_cdkstats.dcdcnt;
-	stli_comstats.hwid = stli_cdkstats.hwid;
-	stli_comstats.signals = stli_mktiocm(stli_cdkstats.signals);
-	mutex_unlock(&portp->port.mutex);
-
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stli_getportstats(struct tty_struct *tty, struct stliport *portp,
-							comstats_t __user *cp)
-{
-	struct stlibrd *brdp;
-	int rc;
-
-	if (!portp) {
-		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
-			stli_comstats.port);
-		if (!portp)
-			return -ENODEV;
-	}
-
-	brdp = stli_brds[portp->brdnr];
-	if (!brdp)
-		return -ENODEV;
-
-	if ((rc = stli_portcmdstats(tty, portp)) < 0)
-		return rc;
-
-	return copy_to_user(cp, &stli_comstats, sizeof(comstats_t)) ?
-			-EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stli_clrportstats(struct stliport *portp, comstats_t __user *cp)
-{
-	struct stlibrd *brdp;
-	int rc;
-
-	if (!portp) {
-		if (copy_from_user(&stli_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stli_getport(stli_comstats.brd, stli_comstats.panel,
-			stli_comstats.port);
-		if (!portp)
-			return -ENODEV;
-	}
-
-	brdp = stli_brds[portp->brdnr];
-	if (!brdp)
-		return -ENODEV;
-
-	mutex_lock(&portp->port.mutex);
-
-	if (test_bit(BST_STARTED, &brdp->state)) {
-		if ((rc = stli_cmdwait(brdp, portp, A_CLEARSTATS, NULL, 0, 0)) < 0) {
-			mutex_unlock(&portp->port.mutex);
-			return rc;
-		}
-	}
-
-	memset(&stli_comstats, 0, sizeof(comstats_t));
-	stli_comstats.brd = portp->brdnr;
-	stli_comstats.panel = portp->panelnr;
-	stli_comstats.port = portp->portnr;
-	mutex_unlock(&portp->port.mutex);
-
-	if (copy_to_user(cp, &stli_comstats, sizeof(comstats_t)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver ports structure to a user app.
- */
-
-static int stli_getportstruct(struct stliport __user *arg)
-{
-	struct stliport stli_dummyport;
-	struct stliport *portp;
-
-	if (copy_from_user(&stli_dummyport, arg, sizeof(struct stliport)))
-		return -EFAULT;
-	portp = stli_getport(stli_dummyport.brdnr, stli_dummyport.panelnr,
-		 stli_dummyport.portnr);
-	if (!portp)
-		return -ENODEV;
-	if (copy_to_user(arg, portp, sizeof(struct stliport)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver board structure to a user app.
- */
-
-static int stli_getbrdstruct(struct stlibrd __user *arg)
-{
-	struct stlibrd stli_dummybrd;
-	struct stlibrd *brdp;
-
-	if (copy_from_user(&stli_dummybrd, arg, sizeof(struct stlibrd)))
-		return -EFAULT;
-	if (stli_dummybrd.brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[stli_dummybrd.brdnr];
-	if (!brdp)
-		return -ENODEV;
-	if (copy_to_user(arg, brdp, sizeof(struct stlibrd)))
-		return -EFAULT;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	The "staliomem" device is also required to do some special operations on
- *	the board. We need to be able to send an interrupt to the board,
- *	reset it, and start/stop it.
- */
-
-static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
-	struct stlibrd *brdp;
-	int brdnr, rc, done;
-	void __user *argp = (void __user *)arg;
-
-/*
- *	First up handle the board independent ioctls.
- */
-	done = 0;
-	rc = 0;
-
-	switch (cmd) {
-	case COM_GETPORTSTATS:
-		rc = stli_getportstats(NULL, NULL, argp);
-		done++;
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stli_clrportstats(NULL, argp);
-		done++;
-		break;
-	case COM_GETBRDSTATS:
-		rc = stli_getbrdstats(argp);
-		done++;
-		break;
-	case COM_READPORT:
-		rc = stli_getportstruct(argp);
-		done++;
-		break;
-	case COM_READBOARD:
-		rc = stli_getbrdstruct(argp);
-		done++;
-		break;
-	}
-	if (done)
-		return rc;
-
-/*
- *	Now handle the board specific ioctls. These all depend on the
- *	minor number of the device they were called from.
- */
-	brdnr = iminor(fp->f_dentry->d_inode);
-	if (brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stli_brds[brdnr];
-	if (!brdp)
-		return -ENODEV;
-	if (brdp->state == 0)
-		return -ENODEV;
-
-	switch (cmd) {
-	case STL_BINTR:
-		EBRDINTR(brdp);
-		break;
-	case STL_BSTART:
-		rc = stli_startbrd(brdp);
-		break;
-	case STL_BSTOP:
-		clear_bit(BST_STARTED, &brdp->state);
-		break;
-	case STL_BRESET:
-		clear_bit(BST_STARTED, &brdp->state);
-		EBRDRESET(brdp);
-		if (stli_shared == 0) {
-			if (brdp->reenable != NULL)
-				(* brdp->reenable)(brdp);
-		}
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-static const struct tty_operations stli_ops = {
-	.open = stli_open,
-	.close = stli_close,
-	.write = stli_write,
-	.put_char = stli_putchar,
-	.flush_chars = stli_flushchars,
-	.write_room = stli_writeroom,
-	.chars_in_buffer = stli_charsinbuffer,
-	.ioctl = stli_ioctl,
-	.set_termios = stli_settermios,
-	.throttle = stli_throttle,
-	.unthrottle = stli_unthrottle,
-	.stop = stli_stop,
-	.start = stli_start,
-	.hangup = stli_hangup,
-	.flush_buffer = stli_flushbuffer,
-	.break_ctl = stli_breakctl,
-	.wait_until_sent = stli_waituntilsent,
-	.send_xchar = stli_sendxchar,
-	.tiocmget = stli_tiocmget,
-	.tiocmset = stli_tiocmset,
-	.proc_fops = &stli_proc_fops,
-};
-
-static const struct tty_port_operations stli_port_ops = {
-	.carrier_raised = stli_carrier_raised,
-	.dtr_rts = stli_dtr_rts,
-	.activate = stli_activate,
-	.shutdown = stli_shutdown,
-};
-
-/*****************************************************************************/
-/*
- *	Loadable module initialization stuff.
- */
-
-static void istallion_cleanup_isa(void)
-{
-	struct stlibrd	*brdp;
-	unsigned int j;
-
-	for (j = 0; (j < stli_nrbrds); j++) {
-		if ((brdp = stli_brds[j]) == NULL ||
-				test_bit(BST_PROBED, &brdp->state))
-			continue;
-
-		stli_cleanup_ports(brdp);
-
-		iounmap(brdp->membase);
-		if (brdp->iosize > 0)
-			release_region(brdp->iobase, brdp->iosize);
-		kfree(brdp);
-		stli_brds[j] = NULL;
-	}
-}
-
-static int __init istallion_module_init(void)
-{
-	unsigned int i;
-	int retval;
-
-	printk(KERN_INFO "%s: version %s\n", stli_drvtitle, stli_drvversion);
-
-	spin_lock_init(&stli_lock);
-	spin_lock_init(&brd_lock);
-
-	stli_txcookbuf = kmalloc(STLI_TXBUFSIZE, GFP_KERNEL);
-	if (!stli_txcookbuf) {
-		printk(KERN_ERR "istallion: failed to allocate memory "
-				"(size=%d)\n", STLI_TXBUFSIZE);
-		retval = -ENOMEM;
-		goto err;
-	}
-
-	stli_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stli_serial) {
-		retval = -ENOMEM;
-		goto err_free;
-	}
-
-	stli_serial->owner = THIS_MODULE;
-	stli_serial->driver_name = stli_drvname;
-	stli_serial->name = stli_serialname;
-	stli_serial->major = STL_SERIALMAJOR;
-	stli_serial->minor_start = 0;
-	stli_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stli_serial->subtype = SERIAL_TYPE_NORMAL;
-	stli_serial->init_termios = stli_deftermios;
-	stli_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stli_serial, &stli_ops);
-
-	retval = tty_register_driver(stli_serial);
-	if (retval) {
-		printk(KERN_ERR "istallion: failed to register serial driver\n");
-		goto err_ttyput;
-	}
-
-	retval = stli_initbrds();
-	if (retval)
-		goto err_ttyunr;
-
-/*
- *	Set up a character driver for the shared memory region. We need this
- *	to down load the slave code image. Also it is a useful debugging tool.
- */
-	retval = register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stli_fsiomem);
-	if (retval) {
-		printk(KERN_ERR "istallion: failed to register serial memory "
-				"device\n");
-		goto err_deinit;
-	}
-
-	istallion_class = class_create(THIS_MODULE, "staliomem");
-	for (i = 0; i < 4; i++)
-		device_create(istallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      NULL, "staliomem%d", i);
-
-	return 0;
-err_deinit:
-	pci_unregister_driver(&stli_pcidriver);
-	istallion_cleanup_isa();
-err_ttyunr:
-	tty_unregister_driver(stli_serial);
-err_ttyput:
-	put_tty_driver(stli_serial);
-err_free:
-	kfree(stli_txcookbuf);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-static void __exit istallion_module_exit(void)
-{
-	unsigned int j;
-
-	printk(KERN_INFO "Unloading %s: version %s\n", stli_drvtitle,
-		stli_drvversion);
-
-	if (stli_timeron) {
-		stli_timeron = 0;
-		del_timer_sync(&stli_timerlist);
-	}
-
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
-
-	for (j = 0; j < 4; j++)
-		device_destroy(istallion_class, MKDEV(STL_SIOMEMMAJOR, j));
-	class_destroy(istallion_class);
-
-	pci_unregister_driver(&stli_pcidriver);
-	istallion_cleanup_isa();
-
-	tty_unregister_driver(stli_serial);
-	put_tty_driver(stli_serial);
-
-	kfree(stli_txcookbuf);
-}
-
-module_init(istallion_module_init);
-module_exit(istallion_module_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/char/Kconfig linux-libre-2.6.39-gnu/drivers/char/Kconfig
--- linux-libre-2.6.38-gnu/drivers/char/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -4,89 +4,7 @@
 
 menu "Character devices"
 
-config VT
-	bool "Virtual terminal" if EXPERT
-	depends on !S390
-	select INPUT
-	default y
-	---help---
-	  If you say Y here, you will get support for terminal devices with
-	  display and keyboard devices. These are called "virtual" because you
-	  can run several virtual terminals (also called virtual consoles) on
-	  one physical terminal. This is rather useful, for example one
-	  virtual terminal can collect system messages and warnings, another
-	  one can be used for a text-mode user session, and a third could run
-	  an X session, all in parallel. Switching between virtual terminals
-	  is done with certain key combinations, usually Alt-<function key>.
-
-	  The setterm command ("man setterm") can be used to change the
-	  properties (such as colors or beeping) of a virtual terminal. The
-	  man page console_codes(4) ("man console_codes") contains the special
-	  character sequences that can be used to change those properties
-	  directly. The fonts used on virtual terminals can be changed with
-	  the setfont ("man setfont") command and the key bindings are defined
-	  with the loadkeys ("man loadkeys") command.
-
-	  You need at least one virtual terminal device in order to make use
-	  of your keyboard and monitor. Therefore, only people configuring an
-	  embedded system would want to say N here in order to save some
-	  memory; the only way to log into such a system is then via a serial
-	  or network connection.
-
-	  If unsure, say Y, or else you won't be able to do much with your new
-	  shiny Linux system :-)
-
-config CONSOLE_TRANSLATIONS
-	depends on VT
-	default y
-	bool "Enable character translations in console" if EXPERT
-	---help---
-	  This enables support for font mapping and Unicode translation
-	  on virtual consoles.
-
-config VT_CONSOLE
-	bool "Support for console on virtual terminal" if EXPERT
-	depends on VT
-	default y
-	---help---
-	  The system console is the device which receives all kernel messages
-	  and warnings and which allows logins in single user mode. If you
-	  answer Y here, a virtual terminal (the device used to interact with
-	  a physical terminal) can be used as system console. This is the most
-	  common mode of operations, so you should say Y here unless you want
-	  the kernel messages be output only to a serial port (in which case
-	  you should say Y to "Console on serial port", below).
-
-	  If you do say Y here, by default the currently visible virtual
-	  terminal (/dev/tty0) will be used as system console. You can change
-	  that with a kernel command line option such as "console=tty3" which
-	  would use the third virtual terminal as system console. (Try "man
-	  bootparam" or see the documentation of your boot loader (lilo or
-	  loadlin) about how to pass options to the kernel at boot time.)
-
-	  If unsure, say Y.
-
-config HW_CONSOLE
-	bool
-	depends on VT && !S390 && !UML
-	default y
-
-config VT_HW_CONSOLE_BINDING
-       bool "Support for binding and unbinding console drivers"
-       depends on HW_CONSOLE
-       default n
-       ---help---
-         The virtual terminal is the device that interacts with the physical
-         terminal through console drivers. On these systems, at least one
-         console driver is loaded. In other configurations, additional console
-         drivers may be enabled, such as the framebuffer console. If more than
-         1 console driver is enabled, setting this to 'y' will allow you to
-         select the console driver that will serve as the backend for the
-         virtual terminals.
-
-	 See <file:Documentation/console/console.txt> for more
-	 information. For framebuffer console users, please refer to
-	 <file:Documentation/fb/fbcon.txt>.
+source "drivers/tty/Kconfig"
 
 config DEVKMEM
 	bool "/dev/kmem virtual device support"
@@ -97,253 +15,6 @@
 	  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
-	---help---
-	  Say Y here if you have any non-standard serial boards -- boards
-	  which aren't supported using the standard "dumb" serial driver.
-	  This includes intelligent serial boards such as Cyclades,
-	  Digiboards, etc. These are usually used for systems that need many
-	  serial ports because they serve many terminals or dial-in
-	  connections.
-
-	  Note that the answer to this question won't directly affect the
-	  kernel: saying N will just cause the configurator to skip all
-	  the questions about non-standard serial boards.
-
-	  Most people can say N here.
-
-config COMPUTONE
-	tristate "Computone IntelliPort Plus serial support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	---help---
-	  This driver supports the entire family of Intelliport II/Plus
-	  controllers with the exception of the MicroChannel controllers and
-	  products previous to the Intelliport II. These are multiport cards,
-	  which give you many serial ports. You would need something like this
-	  to connect more than two modems to your Linux box, for instance in
-	  order to become a dial-in server. If you have a card like that, say
-	  Y here and read <file:Documentation/serial/computone.txt>.
-
-	  To compile this driver as module, choose M here: the
-	  module will be called ip2.
-
-config ROCKETPORT
-	tristate "Comtrol RocketPort support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	help
-	  This driver supports Comtrol RocketPort and RocketModem PCI boards.   
-          These boards provide 2, 4, 8, 16, or 32 high-speed serial ports or
-          modems.  For information about the RocketPort/RocketModem  boards
-          and this driver read <file:Documentation/serial/rocket.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called rocket.
-
-	  If you want to compile this driver into the kernel, say Y here.  If
-          you don't have a Comtrol RocketPort/RocketModem card installed, say N.
-
-config CYCLADES
-	tristate "Cyclades async mux support"
-	depends on SERIAL_NONSTANDARD && (PCI || ISA)
-	select FW_LOADER
-	---help---
-	  This driver supports Cyclades Z and Y multiserial boards.
-	  You would need something like this to connect more than two modems to
-	  your Linux box, for instance in order to become a dial-in server.
-
-	  For information about the Cyclades-Z card, read
-	  <file:Documentation/serial/README.cycladesZ>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called cyclades.
-
-	  If you haven't heard about it, it's safe to say N.
-
-config CYZ_INTR
-	bool "Cyclades-Z interrupt mode operation (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && CYCLADES
-	help
-	  The Cyclades-Z family of multiport cards allows 2 (two) driver op
-	  modes: polling and interrupt. In polling mode, the driver will check
-	  the status of the Cyclades-Z ports every certain amount of time
-	  (which is called polling cycle and is configurable). In interrupt
-	  mode, it will use an interrupt line (IRQ) in order to check the
-	  status of the Cyclades-Z ports. The default op mode is polling. If
-	  unsure, say N.
-
-config DIGIEPCA
-	tristate "Digiboard Intelligent Async Support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	---help---
-	  This is a driver for Digi International's Xx, Xeve, and Xem series
-	  of cards which provide multiple serial ports. You would need
-	  something like this to connect more than two modems to your Linux
-	  box, for instance in order to become a dial-in server. This driver
-	  supports the original PC (ISA) boards as well as PCI, and EISA. If
-	  you have a card like this, say Y here and read the file
-	  <file:Documentation/serial/digiepca.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called epca.
-
-config MOXA_INTELLIO
-	tristate "Moxa Intellio support"
-	depends on SERIAL_NONSTANDARD && (ISA || EISA || PCI)
-	select FW_LOADER
-	help
-	  Say Y here if you have a Moxa Intellio multiport serial card.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called moxa.
-
-config MOXA_SMARTIO
-	tristate "Moxa SmartIO support v. 2.0"
-	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA)
-	help
-	  Say Y here if you have a Moxa SmartIO multiport serial card and/or
-	  want to help develop a new version of this driver.
-
-	  This is upgraded (1.9.1) driver from original Moxa drivers with
-	  changes finally resulting in PCI probing.
-
-	  This driver can also be built as a module. The module will be called
-	  mxser. If you want to do that, say M here.
-
-config ISI
-	tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
-	depends on SERIAL_NONSTANDARD && PCI
-	select FW_LOADER
-	help
-	  This is a driver for the Multi-Tech cards which provide several
-	  serial ports.  The driver is experimental and can currently only be
-	  built as a module. The module will be called isicom.
-	  If you want to do that, choose M here.
-
-config SYNCLINK
-	tristate "Microgate SyncLink card support"
-	depends on SERIAL_NONSTANDARD && PCI && ISA_DMA_API
-	help
-	  Provides support for the SyncLink ISA and PCI multiprotocol serial
-	  adapters. These adapters support asynchronous and HDLC bit
-	  synchronous communication up to 10Mbps (PCI adapter).
-
-	  This driver can only be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called synclink.  If you want to do that, say M
-	  here.
-
-config SYNCLINKMP
-	tristate "SyncLink Multiport support"
-	depends on SERIAL_NONSTANDARD && PCI
-	help
-	  Enable support for the SyncLink Multiport (2 or 4 ports)
-	  serial adapter, running asynchronous and HDLC communications up
-	  to 2.048Mbps. Each ports is independently selectable for
-	  RS-232, V.35, RS-449, RS-530, and X.21
-
-	  This driver may be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called synclinkmp.  If you want to do that, say M
-	  here.
-
-config SYNCLINK_GT
-	tristate "SyncLink GT/AC support"
-	depends on SERIAL_NONSTANDARD && PCI
-	help
-	  Support for SyncLink GT and SyncLink AC families of
-	  synchronous and asynchronous serial adapters
-	  manufactured by Microgate Systems, Ltd. (www.microgate.com)
-
-config N_HDLC
-	tristate "HDLC line discipline support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  Allows synchronous HDLC communications with tty device drivers that
-	  support synchronous HDLC such as the Microgate SyncLink adapter.
-
-	  This driver can be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called n_hdlc. If you want to do that, say M
-	  here.
-
-config N_GSM
-	tristate "GSM MUX line discipline support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL
-	depends on NET
-	help
-	  This line discipline provides support for the GSM MUX protocol and
-	  presents the mux as a set of 61 individual tty devices.
-
-config RISCOM8
-	tristate "SDL RISCom/8 card support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  This is a driver for the SDL Communications RISCom/8 multiport card,
-	  which gives you many serial ports. You would need something like
-	  this to connect more than two modems to your Linux box, for instance
-	  in order to become a dial-in server. If you have a card like that,
-	  say Y here and read the file <file:Documentation/serial/riscom8.txt>.
-
-	  Also it's possible to say M here and compile this driver as kernel
-	  loadable module; the module will be called riscom8.
-
-config SPECIALIX
-	tristate "Specialix IO8+ card support"
-	depends on SERIAL_NONSTANDARD
-	help
-	  This is a driver for the Specialix IO8+ multiport card (both the
-	  ISA and the PCI version) which gives you many serial ports. You
-	  would need something like this to connect more than two modems to
-	  your Linux box, for instance in order to become a dial-in server.
-
-	  If you have a card like that, say Y here and read the file
-	  <file:Documentation/serial/specialix.txt>. Also it's possible to say
-	  M here and compile this driver as kernel loadable module which will be
-	  called specialix.
-
-config SX
-	tristate "Specialix SX (and SI) card support"
-	depends on SERIAL_NONSTANDARD && (PCI || EISA || ISA) && BROKEN
-	help
-	  This is a driver for the SX and SI multiport serial cards.
-	  Please read the file <file:Documentation/serial/sx.txt> for details.
-
-	  This driver can only be built as a module ( = code which can be
-	  inserted in and removed from the running kernel whenever you want).
-	  The module will be called sx. If you want to do that, say M here.
-
-config RIO
-	tristate "Specialix RIO system support"
-	depends on SERIAL_NONSTANDARD && BROKEN
-	help
-	  This is a driver for the Specialix RIO, a smart serial card which
-	  drives an outboard box that can support up to 128 ports.  Product
-	  information is at <http://www.perle.com/support/documentation.html#multiport>.
-	  There are both ISA and PCI versions.
-
-config RIO_OLDPCI
-	bool "Support really old RIO/PCI cards"
-	depends on RIO
-	help
-	  Older RIO PCI cards need some initialization-time configuration to
-	  determine the IRQ and some control addresses.  If you have a RIO and
-	  this doesn't seem to work, try setting this to Y.
-
 config STALDRV
 	bool "Stallion multiport serial support"
 	depends on SERIAL_NONSTANDARD
@@ -356,54 +27,6 @@
 	  in this case.  If you have never heard about all this, it's safe to
 	  say N.
 
-config STALLION
-	tristate "Stallion EasyIO or EC8/32 support"
-	depends on STALDRV && (ISA || EISA || PCI)
-	help
-	  If you have an EasyIO or EasyConnection 8/32 multiport Stallion
-	  card, then this is for you; say Y.  Make sure to read
-	  <file:Documentation/serial/stallion.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called stallion.
-
-config ISTALLION
-	tristate "Stallion EC8/64, ONboard, Brumby support"
-	depends on STALDRV && (ISA || EISA || PCI)
-	help
-	  If you have an EasyConnection 8/64, ONboard, Brumby or Stallion
-	  serial multiport card, say Y here. Make sure to read
-	  <file:Documentation/serial/stallion.txt>.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called istallion.
-
-config NOZOMI
-	tristate "HSDPA Broadband Wireless Data Card - Globe Trotter"
-	depends on PCI && EXPERIMENTAL
-	help
-	  If you have a HSDPA driver Broadband Wireless Data Card -
-	  Globe Trotter PCMCIA card, say Y here.
-
-	  To compile this driver as a module, choose M here, the module
-	  will be called nozomi.
-
-config A2232
-	tristate "Commodore A2232 serial support (EXPERIMENTAL)"
-	depends on EXPERIMENTAL && ZORRO && BROKEN
-	---help---
-	  This option supports the 2232 7-port serial card shipped with the
-	  Amiga 2000 and other Zorro-bus machines, dating from 1989.  At
-	  a max of 19,200 bps, the ports are served by a 6551 ACIA UART chip
-	  each, plus a 8520 CIA, and a master 6502 CPU and buffer as well. The
-	  ports were connected with 8 pin DIN connectors on the card bracket,
-	  for which 8 pin to DB25 adapters were supplied. The card also had
-	  jumpers internally to toggle various pinning configurations.
-
-	  This driver can be built as a module; but then "generic_serial"
-	  will also be built as a module. This has to be loaded before
-	  "ser_a2232". If you want to do this, answer M here.
-
 config SGI_SNSC
 	bool "SGI Altix system controller communication support"
 	depends on (IA64_SGI_SN2 || IA64_GENERIC)
@@ -428,71 +51,6 @@
 
 source "drivers/tty/serial/Kconfig"
 
-config UNIX98_PTYS
-	bool "Unix98 PTY support" if EXPERT
-	default y
-	---help---
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx for
-	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
-	  has a number of problems. The GNU C library glibc 2.1 and later,
-	  however, supports the Unix98 naming standard: in order to acquire a
-	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
-	  terminal is then made available to the process and the pseudo
-	  terminal slave can be accessed as /dev/pts/<number>. What was
-	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
-
-	  All modern Linux systems use the Unix98 ptys.  Say Y unless
-	  you're on an embedded system and want to conserve memory.
-
-config DEVPTS_MULTIPLE_INSTANCES
-	bool "Support multiple instances of devpts"
-	depends on UNIX98_PTYS
-	default n
-	---help---
-	  Enable support for multiple instances of devpts filesystem.
-	  If you want to have isolated PTY namespaces (eg: in containers),
-	  say Y here.  Otherwise, say N. If enabled, each mount of devpts
-	  filesystem with the '-o newinstance' option will create an
-	  independent PTY namespace.
-
-config LEGACY_PTYS
-	bool "Legacy (BSD) PTY support"
-	default y
-	---help---
-	  A pseudo terminal (PTY) is a software device consisting of two
-	  halves: a master and a slave. The slave device behaves identical to
-	  a physical terminal; the master device is used by a process to
-	  read data from and write data to the slave, thereby emulating a
-	  terminal. Typical programs for the master side are telnet servers
-	  and xterms.
-
-	  Linux has traditionally used the BSD-like names /dev/ptyxx
-	  for masters and /dev/ttyxx for slaves of pseudo
-	  terminals. This scheme has a number of problems, including
-	  security.  This option enables these legacy devices; on most
-	  systems, it is safe to say N.
-
-
-config LEGACY_PTY_COUNT
-	int "Maximum number of legacy PTY in use"
-	depends on LEGACY_PTYS
-	range 0 256
-	default "256"
-	---help---
-	  The maximum number of legacy PTYs that can be used at any one time.
-	  The default is 256, and should be more than enough.  Embedded
-	  systems may want to reduce this to save memory.
-
-	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
-	  architectures and 24 bytes on 64-bit architectures.
-
 config TTY_PRINTK
 	bool "TTY driver to output user messages via printk"
 	depends on EXPERT
@@ -612,84 +170,7 @@
 
 	  If unsure, say N.
 
-config HVC_DRIVER
-	bool
-	help
-	  Generic "hypervisor virtual console" infrastructure for various
-	  hypervisors (pSeries, iSeries, Xen, lguest).
-	  It will automatically be selected if one of the back-end console drivers
-	  is selected.
-
-config HVC_IRQ
-	bool
-
-config HVC_CONSOLE
-	bool "pSeries Hypervisor Virtual Console support"
-	depends on PPC_PSERIES
-	select HVC_DRIVER
-	select HVC_IRQ
-	help
-	  pSeries machines when partitioned support a hypervisor virtual
-	  console. This driver allows each pSeries partition to have a console
-	  which is accessed via the HMC.
-
-config HVC_ISERIES
-	bool "iSeries Hypervisor Virtual Console support"
-	depends on PPC_ISERIES
-	default y
-	select HVC_DRIVER
-	select HVC_IRQ
-	select VIOPATH
-	help
-	  iSeries machines support a hypervisor virtual console.
-
-config HVC_RTAS
-	bool "IBM RTAS Console support"
-	depends on PPC_RTAS
-	select HVC_DRIVER
-	help
-	  IBM Console device driver which makes use of RTAS
-
-config HVC_BEAT
-	bool "Toshiba's Beat Hypervisor Console support"
-	depends on PPC_CELLEB
-	select HVC_DRIVER
-	help
-	  Toshiba's Cell Reference Set Beat Console device driver
-
-config HVC_IUCV
-	bool "z/VM IUCV Hypervisor console support (VM only)"
-	depends on S390
-	select HVC_DRIVER
-	select IUCV
-	default y
-	help
-	  This driver provides a Hypervisor console (HVC) back-end to access
-	  a Linux (console) terminal via a z/VM IUCV communication path.
-
-config HVC_XEN
-	bool "Xen Hypervisor Console support"
-	depends on XEN
-	select HVC_DRIVER
-	select HVC_IRQ
-	default y
-	help
-	  Xen virtual console device driver
-
-config HVC_UDBG
-       bool "udbg based fake hypervisor console"
-       depends on PPC && EXPERIMENTAL
-       select HVC_DRIVER
-       default n
-
-config HVC_DCC
-       bool "ARM JTAG DCC console"
-       depends on ARM
-       select HVC_DRIVER
-       help
-         This console uses the JTAG DCC on ARM to create a console under the HVC
-	 driver. This console is used through a JTAG only on ARM. If you don't have
-	 a JTAG then you probably don't want this option.
+source "drivers/tty/hvc/Kconfig"
 
 config VIRTIO_CONSOLE
 	tristate "Virtio console"
@@ -707,23 +188,6 @@
 	  the port which can be used by udev scripts to create a
 	  symlink to the device.
 
-config HVCS
-	tristate "IBM Hypervisor Virtual Console Server support"
-	depends on PPC_PSERIES && HVC_CONSOLE
-	help
-	  Partitionable IBM Power5 ppc64 machines allow hosting of
-	  firmware virtual consoles from one Linux partition by
-	  another Linux partition.  This driver allows console data
-	  from Linux partitions to be accessed through TTY device
-	  interfaces in the device tree of a Linux partition running
-	  this driver.
-
-	  To compile this driver as a module, choose M here: the
-	  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.
-
 config IBM_BSR
 	tristate "IBM POWER Barrier Synchronization Register support"
 	depends on PPC_PSERIES
@@ -1144,5 +608,13 @@
 	  This enables panic and oops messages to be logged to a circular
 	  buffer in RAM where it can be read back at some later point.
 
+config MSM_SMD_PKT
+	bool "Enable device interface for some SMD packet ports"
+	default n
+	depends on MSM_SMD
+	help
+	  Enables userspace clients to read and write to some packet SMD
+	  ports via device interface for MSM chipset.
+
 endmenu
 
diff -druN linux-libre-2.6.38-gnu/drivers/char/Makefile linux-libre-2.6.39-gnu/drivers/char/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,34 +5,11 @@
 obj-y				+= mem.o random.o
 obj-$(CONFIG_TTY_PRINTK)	+= ttyprintk.o
 obj-y				+= misc.o
-obj-$(CONFIG_BFIN_JTAG_COMM)	+= bfin_jtag_comm.o
-obj-$(CONFIG_MVME147_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_MVME162_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_BVME6000_SCC)	+= generic_serial.o vme_scc.o
-obj-$(CONFIG_ROCKETPORT)	+= rocket.o
-obj-$(CONFIG_SERIAL167)		+= serial167.o
-obj-$(CONFIG_CYCLADES)		+= cyclades.o
-obj-$(CONFIG_STALLION)		+= stallion.o
-obj-$(CONFIG_ISTALLION)		+= istallion.o
-obj-$(CONFIG_NOZOMI)		+= nozomi.o
-obj-$(CONFIG_DIGIEPCA)		+= epca.o
-obj-$(CONFIG_SPECIALIX)		+= specialix.o
-obj-$(CONFIG_MOXA_INTELLIO)	+= moxa.o
-obj-$(CONFIG_A2232)		+= ser_a2232.o generic_serial.o
 obj-$(CONFIG_ATARI_DSP56K)	+= dsp56k.o
-obj-$(CONFIG_MOXA_SMARTIO)	+= mxser.o
-obj-$(CONFIG_COMPUTONE)		+= ip2/
-obj-$(CONFIG_RISCOM8)		+= riscom8.o
-obj-$(CONFIG_ISI)		+= isicom.o
-obj-$(CONFIG_SYNCLINK)		+= synclink.o
-obj-$(CONFIG_SYNCLINKMP)	+= synclinkmp.o
-obj-$(CONFIG_SYNCLINK_GT)	+= synclink_gt.o
-obj-$(CONFIG_AMIGA_BUILTIN_SERIAL) += amiserial.o
-obj-$(CONFIG_SX)		+= sx.o generic_serial.o
-obj-$(CONFIG_RIO)		+= rio/ generic_serial.o
 obj-$(CONFIG_VIRTIO_CONSOLE)	+= virtio_console.o
 obj-$(CONFIG_RAW_DRIVER)	+= raw.o
 obj-$(CONFIG_SGI_SNSC)		+= snsc.o snsc_event.o
+obj-$(CONFIG_MSM_SMD_PKT)	+= msm_smd_pkt.o
 obj-$(CONFIG_MSPEC)		+= mspec.o
 obj-$(CONFIG_MMTIMER)		+= mmtimer.o
 obj-$(CONFIG_UV_MMTIMER)	+= uv_mmtimer.o
diff -druN linux-libre-2.6.38-gnu/drivers/char/mbcs.h linux-libre-2.6.39-gnu/drivers/char/mbcs.h
--- linux-libre-2.6.38-gnu/drivers/char/mbcs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mbcs.h	2011-05-19 00:06:34.000000000 -0400
@@ -36,13 +36,13 @@
 #define MBCS_RD_DMA_CTRL	0x0110	/* Read DMA Control */
 #define MBCS_RD_DMA_AMO_DEST	0x0118	/* Read DMA AMO Destination */
 #define MBCS_RD_DMA_INT_DEST	0x0120	/* Read DMA Interrupt Destination */
-#define MBCS_RD_DMA_AUX_STAT	0x0130	/* Read DMA Auxillary Status */
+#define MBCS_RD_DMA_AUX_STAT	0x0130	/* Read DMA Auxiliary Status */
 #define MBCS_WR_DMA_SYS_ADDR	0x0200	/* Write DMA System Address */
 #define MBCS_WR_DMA_LOC_ADDR	0x0208	/* Write DMA Local Address */
 #define MBCS_WR_DMA_CTRL	0x0210	/* Write DMA Control */
 #define MBCS_WR_DMA_AMO_DEST	0x0218	/* Write DMA AMO Destination */
 #define MBCS_WR_DMA_INT_DEST	0x0220	/* Write DMA Interrupt Destination */
-#define MBCS_WR_DMA_AUX_STAT	0x0230	/* Write DMA Auxillary Status */
+#define MBCS_WR_DMA_AUX_STAT	0x0230	/* Write DMA Auxiliary Status */
 #define MBCS_ALG_AMO_DEST	0x0300	/* Algorithm AMO Destination */
 #define MBCS_ALG_INT_DEST	0x0308	/* Algorithm Interrupt Destination */
 #define MBCS_ALG_OFFSETS	0x0310
diff -druN linux-libre-2.6.38-gnu/drivers/char/mem.c linux-libre-2.6.39-gnu/drivers/char/mem.c
--- linux-libre-2.6.38-gnu/drivers/char/mem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mem.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,10 +47,7 @@
 #ifndef ARCH_HAS_VALID_PHYS_ADDR_RANGE
 static inline int valid_phys_addr_range(unsigned long addr, size_t count)
 {
-	if (addr + count > __pa(high_memory))
-		return 0;
-
-	return 1;
+	return addr + count <= __pa(high_memory);
 }
 
 static inline int valid_mmap_phys_addr_range(unsigned long pfn, size_t size)
diff -druN linux-libre-2.6.38-gnu/drivers/char/mmtimer.c linux-libre-2.6.39-gnu/drivers/char/mmtimer.c
--- linux-libre-2.6.38-gnu/drivers/char/mmtimer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mmtimer.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,6 +53,8 @@
 
 #define RTC_BITS 55 /* 55 bits for this implementation */
 
+static struct k_clock sgi_clock;
+
 extern unsigned long sn_rtc_cycles_per_second;
 
 #define RTC_COUNTER_ADDR        ((long *)LOCAL_MMR_ADDR(SH_RTC))
@@ -487,7 +489,7 @@
 	return 0;
 };
 
-static int sgi_clock_set(clockid_t clockid, struct timespec *tp)
+static int sgi_clock_set(const clockid_t clockid, const struct timespec *tp)
 {
 
 	u64 nsec;
@@ -763,15 +765,21 @@
 	return err;
 }
 
+static int sgi_clock_getres(const clockid_t which_clock, struct timespec *tp)
+{
+	tp->tv_sec = 0;
+	tp->tv_nsec = sgi_clock_period;
+	return 0;
+}
+
 static struct k_clock sgi_clock = {
-	.res = 0,
-	.clock_set = sgi_clock_set,
-	.clock_get = sgi_clock_get,
-	.timer_create = sgi_timer_create,
-	.nsleep = do_posix_clock_nonanosleep,
-	.timer_set = sgi_timer_set,
-	.timer_del = sgi_timer_del,
-	.timer_get = sgi_timer_get
+	.clock_set	= sgi_clock_set,
+	.clock_get	= sgi_clock_get,
+	.clock_getres	= sgi_clock_getres,
+	.timer_create	= sgi_timer_create,
+	.timer_set	= sgi_timer_set,
+	.timer_del	= sgi_timer_del,
+	.timer_get	= sgi_timer_get
 };
 
 /**
@@ -831,8 +839,8 @@
 			(unsigned long) node);
 	}
 
-	sgi_clock_period = sgi_clock.res = NSEC_PER_SEC / sn_rtc_cycles_per_second;
-	register_posix_clock(CLOCK_SGI_CYCLE, &sgi_clock);
+	sgi_clock_period = NSEC_PER_SEC / sn_rtc_cycles_per_second;
+	posix_timers_register_clock(CLOCK_SGI_CYCLE, &sgi_clock);
 
 	printk(KERN_INFO "%s: v%s, %ld MHz\n", MMTIMER_DESC, MMTIMER_VERSION,
 	       sn_rtc_cycles_per_second/(unsigned long)1E6);
diff -druN linux-libre-2.6.38-gnu/drivers/char/moxa.c linux-libre-2.6.39-gnu/drivers/char/moxa.c
--- linux-libre-2.6.38-gnu/drivers/char/moxa.c	2012-03-24 01:00:13.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/moxa.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2090 +0,0 @@
-/*****************************************************************************/
-/*
- *           moxa.c  -- MOXA Intellio family multiport serial driver.
- *
- *      Copyright (C) 1999-2000  Moxa Technologies (support@moxa.com).
- *      Copyright (c) 2007 Jiri Slaby <jirislaby@gmail.com>
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- */
-
-/*
- *    MOXA Intellio Series Driver
- *      for             : LINUX
- *      date            : 1999/1/7
- *      version         : 5.1
- */
-
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/mm.h>
-#include <linux/ioport.h>
-#include <linux/errno.h>
-#include <linux/firmware.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/serial.h>
-#include <linux/tty_driver.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include "moxa.h"
-
-#define MOXA_VERSION		"6.0k"
-
-#define MOXA_FW_HDRLEN		32
-
-#define MOXAMAJOR		172
-
-#define MAX_BOARDS		4	/* Don't change this value */
-#define MAX_PORTS_PER_BOARD	32	/* Don't change this value */
-#define MAX_PORTS		(MAX_BOARDS * MAX_PORTS_PER_BOARD)
-
-#define MOXA_IS_320(brd) ((brd)->boardType == MOXA_BOARD_C320_ISA || \
-		(brd)->boardType == MOXA_BOARD_C320_PCI)
-
-/*
- *    Define the Moxa PCI vendor and device IDs.
- */
-#define MOXA_BUS_TYPE_ISA	0
-#define MOXA_BUS_TYPE_PCI	1
-
-enum {
-	MOXA_BOARD_C218_PCI = 1,
-	MOXA_BOARD_C218_ISA,
-	MOXA_BOARD_C320_PCI,
-	MOXA_BOARD_C320_ISA,
-	MOXA_BOARD_CP204J,
-};
-
-static char *moxa_brdname[] =
-{
-	"C218 Turbo PCI series",
-	"C218 Turbo ISA series",
-	"C320 Turbo PCI series",
-	"C320 Turbo ISA series",
-	"CP-204J series",
-};
-
-#ifdef CONFIG_PCI
-static struct pci_device_id moxa_pcibrds[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C218),
-		.driver_data = MOXA_BOARD_C218_PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_C320),
-		.driver_data = MOXA_BOARD_C320_PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_MOXA, PCI_DEVICE_ID_MOXA_CP204J),
-		.driver_data = MOXA_BOARD_CP204J },
-	{ 0 }
-};
-MODULE_DEVICE_TABLE(pci, moxa_pcibrds);
-#endif /* CONFIG_PCI */
-
-struct moxa_port;
-
-static struct moxa_board_conf {
-	int boardType;
-	int numPorts;
-	int busType;
-
-	unsigned int ready;
-
-	struct moxa_port *ports;
-
-	void __iomem *basemem;
-	void __iomem *intNdx;
-	void __iomem *intPend;
-	void __iomem *intTable;
-} moxa_boards[MAX_BOARDS];
-
-struct mxser_mstatus {
-	tcflag_t cflag;
-	int cts;
-	int dsr;
-	int ri;
-	int dcd;
-};
-
-struct moxaq_str {
-	int inq;
-	int outq;
-};
-
-struct moxa_port {
-	struct tty_port port;
-	struct moxa_board_conf *board;
-	void __iomem *tableAddr;
-
-	int type;
-	int cflag;
-	unsigned long statusflags;
-
-	u8 DCDState;		/* Protected by the port lock */
-	u8 lineCtrl;
-	u8 lowChkFlag;
-};
-
-struct mon_str {
-	int tick;
-	int rxcnt[MAX_PORTS];
-	int txcnt[MAX_PORTS];
-};
-
-/* statusflags */
-#define TXSTOPPED	1
-#define LOWWAIT 	2
-#define EMPTYWAIT	3
-
-#define SERIAL_DO_RESTART
-
-#define WAKEUP_CHARS		256
-
-static int ttymajor = MOXAMAJOR;
-static struct mon_str moxaLog;
-static unsigned int moxaFuncTout = HZ / 2;
-static unsigned int moxaLowWaterChk;
-static DEFINE_MUTEX(moxa_openlock);
-static DEFINE_SPINLOCK(moxa_lock);
-
-static unsigned long baseaddr[MAX_BOARDS];
-static unsigned int type[MAX_BOARDS];
-static unsigned int numports[MAX_BOARDS];
-
-MODULE_AUTHOR("William Chen");
-MODULE_DESCRIPTION("MOXA Intellio Family Multiport Board Device Driver");
-MODULE_LICENSE("GPL");
-/*(DEBLOBBED)*/
-
-module_param_array(type, uint, NULL, 0);
-MODULE_PARM_DESC(type, "card type: C218=2, C320=4");
-module_param_array(baseaddr, ulong, NULL, 0);
-MODULE_PARM_DESC(baseaddr, "base address");
-module_param_array(numports, uint, NULL, 0);
-MODULE_PARM_DESC(numports, "numports (ignored for C218)");
-
-module_param(ttymajor, int, 0);
-
-/*
- * static functions:
- */
-static int moxa_open(struct tty_struct *, struct file *);
-static void moxa_close(struct tty_struct *, struct file *);
-static int moxa_write(struct tty_struct *, const unsigned char *, int);
-static int moxa_write_room(struct tty_struct *);
-static void moxa_flush_buffer(struct tty_struct *);
-static int moxa_chars_in_buffer(struct tty_struct *);
-static void moxa_set_termios(struct tty_struct *, struct ktermios *);
-static void moxa_stop(struct tty_struct *);
-static void moxa_start(struct tty_struct *);
-static void moxa_hangup(struct tty_struct *);
-static int moxa_tiocmget(struct tty_struct *tty, struct file *file);
-static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear);
-static void moxa_poll(unsigned long);
-static void moxa_set_tty_param(struct tty_struct *, struct ktermios *);
-static void moxa_shutdown(struct tty_port *);
-static int moxa_carrier_raised(struct tty_port *);
-static void moxa_dtr_rts(struct tty_port *, int);
-/*
- * moxa board interface functions:
- */
-static void MoxaPortEnable(struct moxa_port *);
-static void MoxaPortDisable(struct moxa_port *);
-static int MoxaPortSetTermio(struct moxa_port *, struct ktermios *, speed_t);
-static int MoxaPortGetLineOut(struct moxa_port *, int *, int *);
-static void MoxaPortLineCtrl(struct moxa_port *, int, int);
-static void MoxaPortFlowCtrl(struct moxa_port *, int, int, int, int, int);
-static int MoxaPortLineStatus(struct moxa_port *);
-static void MoxaPortFlushData(struct moxa_port *, int);
-static int MoxaPortWriteData(struct tty_struct *, const unsigned char *, int);
-static int MoxaPortReadData(struct moxa_port *);
-static int MoxaPortTxQueue(struct moxa_port *);
-static int MoxaPortRxQueue(struct moxa_port *);
-static int MoxaPortTxFree(struct moxa_port *);
-static void MoxaPortTxDisable(struct moxa_port *);
-static void MoxaPortTxEnable(struct moxa_port *);
-static int moxa_get_serial_info(struct moxa_port *, struct serial_struct __user *);
-static int moxa_set_serial_info(struct moxa_port *, struct serial_struct __user *);
-static void MoxaSetFifo(struct moxa_port *port, int enable);
-
-/*
- * I/O functions
- */
-
-static DEFINE_SPINLOCK(moxafunc_lock);
-
-static void moxa_wait_finish(void __iomem *ofsAddr)
-{
-	unsigned long end = jiffies + moxaFuncTout;
-
-	while (readw(ofsAddr + FuncCode) != 0)
-		if (time_after(jiffies, end))
-			return;
-	if (readw(ofsAddr + FuncCode) != 0 && printk_ratelimit())
-		printk(KERN_WARNING "moxa function expired\n");
-}
-
-static void moxafunc(void __iomem *ofsAddr, u16 cmd, u16 arg)
-{
-        unsigned long flags;
-        spin_lock_irqsave(&moxafunc_lock, flags);
-	writew(arg, ofsAddr + FuncArg);
-	writew(cmd, ofsAddr + FuncCode);
-	moxa_wait_finish(ofsAddr);
-	spin_unlock_irqrestore(&moxafunc_lock, flags);
-}
-
-static int moxafuncret(void __iomem *ofsAddr, u16 cmd, u16 arg)
-{
-        unsigned long flags;
-        u16 ret;
-        spin_lock_irqsave(&moxafunc_lock, flags);
-	writew(arg, ofsAddr + FuncArg);
-	writew(cmd, ofsAddr + FuncCode);
-	moxa_wait_finish(ofsAddr);
-	ret = readw(ofsAddr + FuncArg);
-	spin_unlock_irqrestore(&moxafunc_lock, flags);
-	return ret;
-}
-
-static void moxa_low_water_check(void __iomem *ofsAddr)
-{
-	u16 rptr, wptr, mask, len;
-
-	if (readb(ofsAddr + FlagStat) & Xoff_state) {
-		rptr = readw(ofsAddr + RXrptr);
-		wptr = readw(ofsAddr + RXwptr);
-		mask = readw(ofsAddr + RX_mask);
-		len = (wptr - rptr) & mask;
-		if (len <= Low_water)
-			moxafunc(ofsAddr, FC_SendXon, 0);
-	}
-}
-
-/*
- * TTY operations
- */
-
-static int moxa_ioctl(struct tty_struct *tty, struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	struct moxa_port *ch = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int status, ret = 0;
-
-	if (tty->index == MAX_PORTS) {
-		if (cmd != MOXA_GETDATACOUNT && cmd != MOXA_GET_IOQUEUE &&
-				cmd != MOXA_GETMSTATUS)
-			return -EINVAL;
-	} else if (!ch)
-		return -ENODEV;
-
-	switch (cmd) {
-	case MOXA_GETDATACOUNT:
-		moxaLog.tick = jiffies;
-		if (copy_to_user(argp, &moxaLog, sizeof(moxaLog)))
-			ret = -EFAULT;
-		break;
-	case MOXA_FLUSH_QUEUE:
-		MoxaPortFlushData(ch, arg);
-		break;
-	case MOXA_GET_IOQUEUE: {
-		struct moxaq_str __user *argm = argp;
-		struct moxaq_str tmp;
-		struct moxa_port *p;
-		unsigned int i, j;
-
-		for (i = 0; i < MAX_BOARDS; i++) {
-			p = moxa_boards[i].ports;
-			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
-				memset(&tmp, 0, sizeof(tmp));
-				spin_lock_bh(&moxa_lock);
-				if (moxa_boards[i].ready) {
-					tmp.inq = MoxaPortRxQueue(p);
-					tmp.outq = MoxaPortTxQueue(p);
-				}
-				spin_unlock_bh(&moxa_lock);
-				if (copy_to_user(argm, &tmp, sizeof(tmp)))
-					return -EFAULT;
-			}
-		}
-		break;
-	} case MOXA_GET_OQUEUE:
-		status = MoxaPortTxQueue(ch);
-		ret = put_user(status, (unsigned long __user *)argp);
-		break;
-	case MOXA_GET_IQUEUE:
-		status = MoxaPortRxQueue(ch);
-		ret = put_user(status, (unsigned long __user *)argp);
-		break;
-	case MOXA_GETMSTATUS: {
-		struct mxser_mstatus __user *argm = argp;
-		struct mxser_mstatus tmp;
-		struct moxa_port *p;
-		unsigned int i, j;
-
-		for (i = 0; i < MAX_BOARDS; i++) {
-			p = moxa_boards[i].ports;
-			for (j = 0; j < MAX_PORTS_PER_BOARD; j++, p++, argm++) {
-				struct tty_struct *ttyp;
-				memset(&tmp, 0, sizeof(tmp));
-				spin_lock_bh(&moxa_lock);
-				if (!moxa_boards[i].ready) {
-				        spin_unlock_bh(&moxa_lock);
-					goto copy;
-                                }
-
-				status = MoxaPortLineStatus(p);
-				spin_unlock_bh(&moxa_lock);
-
-				if (status & 1)
-					tmp.cts = 1;
-				if (status & 2)
-					tmp.dsr = 1;
-				if (status & 4)
-					tmp.dcd = 1;
-
-				ttyp = tty_port_tty_get(&p->port);
-				if (!ttyp || !ttyp->termios)
-					tmp.cflag = p->cflag;
-				else
-					tmp.cflag = ttyp->termios->c_cflag;
-				tty_kref_put(tty);
-copy:
-				if (copy_to_user(argm, &tmp, sizeof(tmp)))
-					return -EFAULT;
-			}
-		}
-		break;
-	}
-	case TIOCGSERIAL:
-	        mutex_lock(&ch->port.mutex);
-		ret = moxa_get_serial_info(ch, argp);
-		mutex_unlock(&ch->port.mutex);
-		break;
-	case TIOCSSERIAL:
-	        mutex_lock(&ch->port.mutex);
-		ret = moxa_set_serial_info(ch, argp);
-		mutex_unlock(&ch->port.mutex);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-	return ret;
-}
-
-static int moxa_break_ctl(struct tty_struct *tty, int state)
-{
-	struct moxa_port *port = tty->driver_data;
-
-	moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
-			Magic_code);
-	return 0;
-}
-
-static const struct tty_operations moxa_ops = {
-	.open = moxa_open,
-	.close = moxa_close,
-	.write = moxa_write,
-	.write_room = moxa_write_room,
-	.flush_buffer = moxa_flush_buffer,
-	.chars_in_buffer = moxa_chars_in_buffer,
-	.ioctl = moxa_ioctl,
-	.set_termios = moxa_set_termios,
-	.stop = moxa_stop,
-	.start = moxa_start,
-	.hangup = moxa_hangup,
-	.break_ctl = moxa_break_ctl,
-	.tiocmget = moxa_tiocmget,
-	.tiocmset = moxa_tiocmset,
-};
-
-static const struct tty_port_operations moxa_port_ops = {
-	.carrier_raised = moxa_carrier_raised,
-	.dtr_rts = moxa_dtr_rts,
-	.shutdown = moxa_shutdown,
-};
-
-static struct tty_driver *moxaDriver;
-static DEFINE_TIMER(moxaTimer, moxa_poll, 0, 0);
-
-/*
- * HW init
- */
-
-static int moxa_check_fw_model(struct moxa_board_conf *brd, u8 model)
-{
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		if (model != 1)
-			goto err;
-		break;
-	case MOXA_BOARD_CP204J:
-		if (model != 3)
-			goto err;
-		break;
-	default:
-		if (model != 2)
-			goto err;
-		break;
-	}
-	return 0;
-err:
-	return -EINVAL;
-}
-
-static int moxa_check_fw(const void *ptr)
-{
-	const __le16 *lptr = ptr;
-
-	if (*lptr != cpu_to_le16(0x7980))
-		return -EINVAL;
-
-	return 0;
-}
-
-static int moxa_load_bios(struct moxa_board_conf *brd, const u8 *buf,
-		size_t len)
-{
-	void __iomem *baseAddr = brd->basemem;
-	u16 tmp;
-
-	writeb(HW_reset, baseAddr + Control_reg);	/* reset */
-	msleep(10);
-	memset_io(baseAddr, 0, 4096);
-	memcpy_toio(baseAddr, buf, len);	/* download BIOS */
-	writeb(0, baseAddr + Control_reg);	/* restart */
-
-	msleep(2000);
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		tmp = readw(baseAddr + C218_key);
-		if (tmp != C218_KeyCode)
-			goto err;
-		break;
-	case MOXA_BOARD_CP204J:
-		tmp = readw(baseAddr + C218_key);
-		if (tmp != CP204J_KeyCode)
-			goto err;
-		break;
-	default:
-		tmp = readw(baseAddr + C320_key);
-		if (tmp != C320_KeyCode)
-			goto err;
-		tmp = readw(baseAddr + C320_status);
-		if (tmp != STS_init) {
-			printk(KERN_ERR "MOXA: bios upload failed -- CPU/Basic "
-					"module not found\n");
-			return -EIO;
-		}
-		break;
-	}
-
-	return 0;
-err:
-	printk(KERN_ERR "MOXA: bios upload failed -- board not found\n");
-	return -EIO;
-}
-
-static int moxa_load_320b(struct moxa_board_conf *brd, const u8 *ptr,
-		size_t len)
-{
-	void __iomem *baseAddr = brd->basemem;
-
-	if (len < 7168) {
-		printk(KERN_ERR "MOXA: invalid 320 bios -- too short\n");
-		return -EINVAL;
-	}
-
-	writew(len - 7168 - 2, baseAddr + C320bapi_len);
-	writeb(1, baseAddr + Control_reg);	/* Select Page 1 */
-	memcpy_toio(baseAddr + DynPage_addr, ptr, 7168);
-	writeb(2, baseAddr + Control_reg);	/* Select Page 2 */
-	memcpy_toio(baseAddr + DynPage_addr, ptr + 7168, len - 7168);
-
-	return 0;
-}
-
-static int moxa_real_load_code(struct moxa_board_conf *brd, const void *ptr,
-		size_t len)
-{
-	void __iomem *baseAddr = brd->basemem;
-	const __le16 *uptr = ptr;
-	size_t wlen, len2, j;
-	unsigned long key, loadbuf, loadlen, checksum, checksum_ok;
-	unsigned int i, retry;
-	u16 usum, keycode;
-
-	keycode = (brd->boardType == MOXA_BOARD_CP204J) ? CP204J_KeyCode :
-				C218_KeyCode;
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_CP204J:
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		key = C218_key;
-		loadbuf = C218_LoadBuf;
-		loadlen = C218DLoad_len;
-		checksum = C218check_sum;
-		checksum_ok = C218chksum_ok;
-		break;
-	default:
-		key = C320_key;
-		keycode = C320_KeyCode;
-		loadbuf = C320_LoadBuf;
-		loadlen = C320DLoad_len;
-		checksum = C320check_sum;
-		checksum_ok = C320chksum_ok;
-		break;
-	}
-
-	usum = 0;
-	wlen = len >> 1;
-	for (i = 0; i < wlen; i++)
-		usum += le16_to_cpu(uptr[i]);
-	retry = 0;
-	do {
-		wlen = len >> 1;
-		j = 0;
-		while (wlen) {
-			len2 = (wlen > 2048) ? 2048 : wlen;
-			wlen -= len2;
-			memcpy_toio(baseAddr + loadbuf, ptr + j, len2 << 1);
-			j += len2 << 1;
-
-			writew(len2, baseAddr + loadlen);
-			writew(0, baseAddr + key);
-			for (i = 0; i < 100; i++) {
-				if (readw(baseAddr + key) == keycode)
-					break;
-				msleep(10);
-			}
-			if (readw(baseAddr + key) != keycode)
-				return -EIO;
-		}
-		writew(0, baseAddr + loadlen);
-		writew(usum, baseAddr + checksum);
-		writew(0, baseAddr + key);
-		for (i = 0; i < 100; i++) {
-			if (readw(baseAddr + key) == keycode)
-				break;
-			msleep(10);
-		}
-		retry++;
-	} while ((readb(baseAddr + checksum_ok) != 1) && (retry < 3));
-	if (readb(baseAddr + checksum_ok) != 1)
-		return -EIO;
-
-	writew(0, baseAddr + key);
-	for (i = 0; i < 600; i++) {
-		if (readw(baseAddr + Magic_no) == Magic_code)
-			break;
-		msleep(10);
-	}
-	if (readw(baseAddr + Magic_no) != Magic_code)
-		return -EIO;
-
-	if (MOXA_IS_320(brd)) {
-		if (brd->busType == MOXA_BUS_TYPE_PCI) {	/* ASIC board */
-			writew(0x3800, baseAddr + TMS320_PORT1);
-			writew(0x3900, baseAddr + TMS320_PORT2);
-			writew(28499, baseAddr + TMS320_CLOCK);
-		} else {
-			writew(0x3200, baseAddr + TMS320_PORT1);
-			writew(0x3400, baseAddr + TMS320_PORT2);
-			writew(19999, baseAddr + TMS320_CLOCK);
-		}
-	}
-	writew(1, baseAddr + Disable_IRQ);
-	writew(0, baseAddr + Magic_no);
-	for (i = 0; i < 500; i++) {
-		if (readw(baseAddr + Magic_no) == Magic_code)
-			break;
-		msleep(10);
-	}
-	if (readw(baseAddr + Magic_no) != Magic_code)
-		return -EIO;
-
-	if (MOXA_IS_320(brd)) {
-		j = readw(baseAddr + Module_cnt);
-		if (j <= 0)
-			return -EIO;
-		brd->numPorts = j * 8;
-		writew(j, baseAddr + Module_no);
-		writew(0, baseAddr + Magic_no);
-		for (i = 0; i < 600; i++) {
-			if (readw(baseAddr + Magic_no) == Magic_code)
-				break;
-			msleep(10);
-		}
-		if (readw(baseAddr + Magic_no) != Magic_code)
-			return -EIO;
-	}
-	brd->intNdx = baseAddr + IRQindex;
-	brd->intPend = baseAddr + IRQpending;
-	brd->intTable = baseAddr + IRQtable;
-
-	return 0;
-}
-
-static int moxa_load_code(struct moxa_board_conf *brd, const void *ptr,
-		size_t len)
-{
-	void __iomem *ofsAddr, *baseAddr = brd->basemem;
-	struct moxa_port *port;
-	int retval, i;
-
-	if (len % 2) {
-		printk(KERN_ERR "MOXA: bios length is not even\n");
-		return -EINVAL;
-	}
-
-	retval = moxa_real_load_code(brd, ptr, len); /* may change numPorts */
-	if (retval)
-		return retval;
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-	case MOXA_BOARD_CP204J:
-		port = brd->ports;
-		for (i = 0; i < brd->numPorts; i++, port++) {
-			port->board = brd;
-			port->DCDState = 0;
-			port->tableAddr = baseAddr + Extern_table +
-					Extern_size * i;
-			ofsAddr = port->tableAddr;
-			writew(C218rx_mask, ofsAddr + RX_mask);
-			writew(C218tx_mask, ofsAddr + TX_mask);
-			writew(C218rx_spage + i * C218buf_pageno, ofsAddr + Page_rxb);
-			writew(readw(ofsAddr + Page_rxb) + C218rx_pageno, ofsAddr + EndPage_rxb);
-
-			writew(C218tx_spage + i * C218buf_pageno, ofsAddr + Page_txb);
-			writew(readw(ofsAddr + Page_txb) + C218tx_pageno, ofsAddr + EndPage_txb);
-
-		}
-		break;
-	default:
-		port = brd->ports;
-		for (i = 0; i < brd->numPorts; i++, port++) {
-			port->board = brd;
-			port->DCDState = 0;
-			port->tableAddr = baseAddr + Extern_table +
-					Extern_size * i;
-			ofsAddr = port->tableAddr;
-			switch (brd->numPorts) {
-			case 8:
-				writew(C320p8rx_mask, ofsAddr + RX_mask);
-				writew(C320p8tx_mask, ofsAddr + TX_mask);
-				writew(C320p8rx_spage + i * C320p8buf_pgno, ofsAddr + Page_rxb);
-				writew(readw(ofsAddr + Page_rxb) + C320p8rx_pgno, ofsAddr + EndPage_rxb);
-				writew(C320p8tx_spage + i * C320p8buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb) + C320p8tx_pgno, ofsAddr + EndPage_txb);
-
-				break;
-			case 16:
-				writew(C320p16rx_mask, ofsAddr + RX_mask);
-				writew(C320p16tx_mask, ofsAddr + TX_mask);
-				writew(C320p16rx_spage + i * C320p16buf_pgno, ofsAddr + Page_rxb);
-				writew(readw(ofsAddr + Page_rxb) + C320p16rx_pgno, ofsAddr + EndPage_rxb);
-				writew(C320p16tx_spage + i * C320p16buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb) + C320p16tx_pgno, ofsAddr + EndPage_txb);
-				break;
-
-			case 24:
-				writew(C320p24rx_mask, ofsAddr + RX_mask);
-				writew(C320p24tx_mask, ofsAddr + TX_mask);
-				writew(C320p24rx_spage + i * C320p24buf_pgno, ofsAddr + Page_rxb);
-				writew(readw(ofsAddr + Page_rxb) + C320p24rx_pgno, ofsAddr + EndPage_rxb);
-				writew(C320p24tx_spage + i * C320p24buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
-				break;
-			case 32:
-				writew(C320p32rx_mask, ofsAddr + RX_mask);
-				writew(C320p32tx_mask, ofsAddr + TX_mask);
-				writew(C320p32tx_ofs, ofsAddr + Ofs_txb);
-				writew(C320p32rx_spage + i * C320p32buf_pgno, ofsAddr + Page_rxb);
-				writew(readb(ofsAddr + Page_rxb), ofsAddr + EndPage_rxb);
-				writew(C320p32tx_spage + i * C320p32buf_pgno, ofsAddr + Page_txb);
-				writew(readw(ofsAddr + Page_txb), ofsAddr + EndPage_txb);
-				break;
-			}
-		}
-		break;
-	}
-	return 0;
-}
-
-static int moxa_load_fw(struct moxa_board_conf *brd, const struct firmware *fw)
-{
-	const void *ptr = fw->data;
-	char rsn[64];
-	u16 lens[5];
-	size_t len;
-	unsigned int a, lenp, lencnt;
-	int ret = -EINVAL;
-	struct {
-		__le32 magic;	/* 0x34303430 */
-		u8 reserved1[2];
-		u8 type;	/* UNIX = 3 */
-		u8 model;	/* C218T=1, C320T=2, CP204=3 */
-		u8 reserved2[8];
-		__le16 len[5];
-	} const *hdr = ptr;
-
-	BUILD_BUG_ON(ARRAY_SIZE(hdr->len) != ARRAY_SIZE(lens));
-
-	if (fw->size < MOXA_FW_HDRLEN) {
-		strcpy(rsn, "too short (even header won't fit)");
-		goto err;
-	}
-	if (hdr->magic != cpu_to_le32(0x30343034)) {
-		sprintf(rsn, "bad magic: %.8x", le32_to_cpu(hdr->magic));
-		goto err;
-	}
-	if (hdr->type != 3) {
-		sprintf(rsn, "not for linux, type is %u", hdr->type);
-		goto err;
-	}
-	if (moxa_check_fw_model(brd, hdr->model)) {
-		sprintf(rsn, "not for this card, model is %u", hdr->model);
-		goto err;
-	}
-
-	len = MOXA_FW_HDRLEN;
-	lencnt = hdr->model == 2 ? 5 : 3;
-	for (a = 0; a < ARRAY_SIZE(lens); a++) {
-		lens[a] = le16_to_cpu(hdr->len[a]);
-		if (lens[a] && len + lens[a] <= fw->size &&
-				moxa_check_fw(&fw->data[len]))
-			printk(KERN_WARNING "MOXA firmware: unexpected input "
-				"at offset %u, but going on\n", (u32)len);
-		if (!lens[a] && a < lencnt) {
-			sprintf(rsn, "too few entries in fw file");
-			goto err;
-		}
-		len += lens[a];
-	}
-
-	if (len != fw->size) {
-		sprintf(rsn, "bad length: %u (should be %u)", (u32)fw->size,
-				(u32)len);
-		goto err;
-	}
-
-	ptr += MOXA_FW_HDRLEN;
-	lenp = 0; /* bios */
-
-	strcpy(rsn, "read above");
-
-	ret = moxa_load_bios(brd, ptr, lens[lenp]);
-	if (ret)
-		goto err;
-
-	/* we skip the tty section (lens[1]), since we don't need it */
-	ptr += lens[lenp] + lens[lenp + 1];
-	lenp += 2; /* comm */
-
-	if (hdr->model == 2) {
-		ret = moxa_load_320b(brd, ptr, lens[lenp]);
-		if (ret)
-			goto err;
-		/* skip another tty */
-		ptr += lens[lenp] + lens[lenp + 1];
-		lenp += 2;
-	}
-
-	ret = moxa_load_code(brd, ptr, lens[lenp]);
-	if (ret)
-		goto err;
-
-	return 0;
-err:
-	printk(KERN_ERR "firmware failed to load, reason: %s\n", rsn);
-	return ret;
-}
-
-static int moxa_init_board(struct moxa_board_conf *brd, struct device *dev)
-{
-	const struct firmware *fw;
-	const char *file;
-	struct moxa_port *p;
-	unsigned int i;
-	int ret;
-
-	brd->ports = kcalloc(MAX_PORTS_PER_BOARD, sizeof(*brd->ports),
-			GFP_KERNEL);
-	if (brd->ports == NULL) {
-		printk(KERN_ERR "cannot allocate memory for ports\n");
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	for (i = 0, p = brd->ports; i < MAX_PORTS_PER_BOARD; i++, p++) {
-		tty_port_init(&p->port);
-		p->port.ops = &moxa_port_ops;
-		p->type = PORT_16550A;
-		p->cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	}
-
-	switch (brd->boardType) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		file = "/*(DEBLOBBED)*/";
-		break;
-	case MOXA_BOARD_CP204J:
-		file = "/*(DEBLOBBED)*/";
-		break;
-	default:
-		file = "/*(DEBLOBBED)*/";
-		break;
-	}
-
-	ret = reject_firmware(&fw, file, dev);
-	if (ret) {
-		printk(KERN_ERR "MOXA: reject_firmware failed. Make sure "
-				"you've placed '%s' file into your firmware "
-				"loader directory (e.g. /lib/firmware)\n",
-				file);
-		goto err_free;
-	}
-
-	ret = moxa_load_fw(brd, fw);
-
-	release_firmware(fw);
-
-	if (ret)
-		goto err_free;
-
-	spin_lock_bh(&moxa_lock);
-	brd->ready = 1;
-	if (!timer_pending(&moxaTimer))
-		mod_timer(&moxaTimer, jiffies + HZ / 50);
-	spin_unlock_bh(&moxa_lock);
-
-	return 0;
-err_free:
-	kfree(brd->ports);
-err:
-	return ret;
-}
-
-static void moxa_board_deinit(struct moxa_board_conf *brd)
-{
-	unsigned int a, opened;
-
-	mutex_lock(&moxa_openlock);
-	spin_lock_bh(&moxa_lock);
-	brd->ready = 0;
-	spin_unlock_bh(&moxa_lock);
-
-	/* pci hot-un-plug support */
-	for (a = 0; a < brd->numPorts; a++)
-		if (brd->ports[a].port.flags & ASYNC_INITIALIZED) {
-			struct tty_struct *tty = tty_port_tty_get(
-						&brd->ports[a].port);
-			if (tty) {
-				tty_hangup(tty);
-				tty_kref_put(tty);
-			}
-		}
-	while (1) {
-		opened = 0;
-		for (a = 0; a < brd->numPorts; a++)
-			if (brd->ports[a].port.flags & ASYNC_INITIALIZED)
-				opened++;
-		mutex_unlock(&moxa_openlock);
-		if (!opened)
-			break;
-		msleep(50);
-		mutex_lock(&moxa_openlock);
-	}
-
-	iounmap(brd->basemem);
-	brd->basemem = NULL;
-	kfree(brd->ports);
-}
-
-#ifdef CONFIG_PCI
-static int __devinit moxa_pci_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct moxa_board_conf *board;
-	unsigned int i;
-	int board_type = ent->driver_data;
-	int retval;
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "can't enable pci device\n");
-		goto err;
-	}
-
-	for (i = 0; i < MAX_BOARDS; i++)
-		if (moxa_boards[i].basemem == NULL)
-			break;
-
-	retval = -ENODEV;
-	if (i >= MAX_BOARDS) {
-		dev_warn(&pdev->dev, "more than %u MOXA Intellio family boards "
-				"found. Board is ignored.\n", MAX_BOARDS);
-		goto err;
-	}
-
-	board = &moxa_boards[i];
-
-	retval = pci_request_region(pdev, 2, "moxa-base");
-	if (retval) {
-		dev_err(&pdev->dev, "can't request pci region 2\n");
-		goto err;
-	}
-
-	board->basemem = ioremap_nocache(pci_resource_start(pdev, 2), 0x4000);
-	if (board->basemem == NULL) {
-		dev_err(&pdev->dev, "can't remap io space 2\n");
-		goto err_reg;
-	}
-
-	board->boardType = board_type;
-	switch (board_type) {
-	case MOXA_BOARD_C218_ISA:
-	case MOXA_BOARD_C218_PCI:
-		board->numPorts = 8;
-		break;
-
-	case MOXA_BOARD_CP204J:
-		board->numPorts = 4;
-		break;
-	default:
-		board->numPorts = 0;
-		break;
-	}
-	board->busType = MOXA_BUS_TYPE_PCI;
-
-	retval = moxa_init_board(board, &pdev->dev);
-	if (retval)
-		goto err_base;
-
-	pci_set_drvdata(pdev, board);
-
-	dev_info(&pdev->dev, "board '%s' ready (%u ports, firmware loaded)\n",
-			moxa_brdname[board_type - 1], board->numPorts);
-
-	return 0;
-err_base:
-	iounmap(board->basemem);
-	board->basemem = NULL;
-err_reg:
-	pci_release_region(pdev, 2);
-err:
-	return retval;
-}
-
-static void __devexit moxa_pci_remove(struct pci_dev *pdev)
-{
-	struct moxa_board_conf *brd = pci_get_drvdata(pdev);
-
-	moxa_board_deinit(brd);
-
-	pci_release_region(pdev, 2);
-}
-
-static struct pci_driver moxa_pci_driver = {
-	.name = "moxa",
-	.id_table = moxa_pcibrds,
-	.probe = moxa_pci_probe,
-	.remove = __devexit_p(moxa_pci_remove)
-};
-#endif /* CONFIG_PCI */
-
-static int __init moxa_init(void)
-{
-	unsigned int isabrds = 0;
-	int retval = 0;
-	struct moxa_board_conf *brd = moxa_boards;
-	unsigned int i;
-
-	printk(KERN_INFO "MOXA Intellio family driver version %s\n",
-			MOXA_VERSION);
-	moxaDriver = alloc_tty_driver(MAX_PORTS + 1);
-	if (!moxaDriver)
-		return -ENOMEM;
-
-	moxaDriver->owner = THIS_MODULE;
-	moxaDriver->name = "ttyMX";
-	moxaDriver->major = ttymajor;
-	moxaDriver->minor_start = 0;
-	moxaDriver->type = TTY_DRIVER_TYPE_SERIAL;
-	moxaDriver->subtype = SERIAL_TYPE_NORMAL;
-	moxaDriver->init_termios = tty_std_termios;
-	moxaDriver->init_termios.c_cflag = B9600 | CS8 | CREAD | CLOCAL | HUPCL;
-	moxaDriver->init_termios.c_ispeed = 9600;
-	moxaDriver->init_termios.c_ospeed = 9600;
-	moxaDriver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(moxaDriver, &moxa_ops);
-
-	if (tty_register_driver(moxaDriver)) {
-		printk(KERN_ERR "can't register MOXA Smartio tty driver!\n");
-		put_tty_driver(moxaDriver);
-		return -1;
-	}
-
-	/* Find the boards defined from module args. */
-
-	for (i = 0; i < MAX_BOARDS; i++) {
-		if (!baseaddr[i])
-			break;
-		if (type[i] == MOXA_BOARD_C218_ISA ||
-				type[i] == MOXA_BOARD_C320_ISA) {
-			pr_debug("Moxa board %2d: %s board(baseAddr=%lx)\n",
-					isabrds + 1, moxa_brdname[type[i] - 1],
-					baseaddr[i]);
-			brd->boardType = type[i];
-			brd->numPorts = type[i] == MOXA_BOARD_C218_ISA ? 8 :
-					numports[i];
-			brd->busType = MOXA_BUS_TYPE_ISA;
-			brd->basemem = ioremap_nocache(baseaddr[i], 0x4000);
-			if (!brd->basemem) {
-				printk(KERN_ERR "MOXA: can't remap %lx\n",
-						baseaddr[i]);
-				continue;
-			}
-			if (moxa_init_board(brd, NULL)) {
-				iounmap(brd->basemem);
-				brd->basemem = NULL;
-				continue;
-			}
-
-			printk(KERN_INFO "MOXA isa board found at 0x%.8lu and "
-					"ready (%u ports, firmware loaded)\n",
-					baseaddr[i], brd->numPorts);
-
-			brd++;
-			isabrds++;
-		}
-	}
-
-#ifdef CONFIG_PCI
-	retval = pci_register_driver(&moxa_pci_driver);
-	if (retval) {
-		printk(KERN_ERR "Can't register MOXA pci driver!\n");
-		if (isabrds)
-			retval = 0;
-	}
-#endif
-
-	return retval;
-}
-
-static void __exit moxa_exit(void)
-{
-	unsigned int i;
-
-#ifdef CONFIG_PCI
-	pci_unregister_driver(&moxa_pci_driver);
-#endif
-
-	for (i = 0; i < MAX_BOARDS; i++) /* ISA boards */
-		if (moxa_boards[i].ready)
-			moxa_board_deinit(&moxa_boards[i]);
-
-	del_timer_sync(&moxaTimer);
-
-	if (tty_unregister_driver(moxaDriver))
-		printk(KERN_ERR "Couldn't unregister MOXA Intellio family "
-				"serial driver\n");
-	put_tty_driver(moxaDriver);
-}
-
-module_init(moxa_init);
-module_exit(moxa_exit);
-
-static void moxa_shutdown(struct tty_port *port)
-{
-	struct moxa_port *ch = container_of(port, struct moxa_port, port);
-        MoxaPortDisable(ch);
-	MoxaPortFlushData(ch, 2);
-	clear_bit(ASYNCB_NORMAL_ACTIVE, &port->flags);
-}
-
-static int moxa_carrier_raised(struct tty_port *port)
-{
-	struct moxa_port *ch = container_of(port, struct moxa_port, port);
-	int dcd;
-
-	spin_lock_irq(&port->lock);
-	dcd = ch->DCDState;
-	spin_unlock_irq(&port->lock);
-	return dcd;
-}
-
-static void moxa_dtr_rts(struct tty_port *port, int onoff)
-{
-	struct moxa_port *ch = container_of(port, struct moxa_port, port);
-	MoxaPortLineCtrl(ch, onoff, onoff);
-}
-
-
-static int moxa_open(struct tty_struct *tty, struct file *filp)
-{
-	struct moxa_board_conf *brd;
-	struct moxa_port *ch;
-	int port;
-	int retval;
-
-	port = tty->index;
-	if (port == MAX_PORTS) {
-		return capable(CAP_SYS_ADMIN) ? 0 : -EPERM;
-	}
-	if (mutex_lock_interruptible(&moxa_openlock))
-		return -ERESTARTSYS;
-	brd = &moxa_boards[port / MAX_PORTS_PER_BOARD];
-	if (!brd->ready) {
-		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++;
-	tty->driver_data = ch;
-	tty_port_tty_set(&ch->port, tty);
-	mutex_lock(&ch->port.mutex);
-	if (!(ch->port.flags & ASYNC_INITIALIZED)) {
-		ch->statusflags = 0;
-		moxa_set_tty_param(tty, tty->termios);
-		MoxaPortLineCtrl(ch, 1, 1);
-		MoxaPortEnable(ch);
-		MoxaSetFifo(ch, ch->type == PORT_16550A);
-		ch->port.flags |= ASYNC_INITIALIZED;
-	}
-	mutex_unlock(&ch->port.mutex);
-	mutex_unlock(&moxa_openlock);
-
-	retval = tty_port_block_til_ready(&ch->port, tty, filp);
-	if (retval == 0)
-	        set_bit(ASYNCB_NORMAL_ACTIVE, &ch->port.flags);
-	return retval;
-}
-
-static void moxa_close(struct tty_struct *tty, struct file *filp)
-{
-	struct moxa_port *ch = tty->driver_data;
-	ch->cflag = tty->termios->c_cflag;
-	tty_port_close(&ch->port, tty, filp);
-}
-
-static int moxa_write(struct tty_struct *tty,
-		      const unsigned char *buf, int count)
-{
-	struct moxa_port *ch = tty->driver_data;
-	int len;
-
-	if (ch == NULL)
-		return 0;
-
-	spin_lock_bh(&moxa_lock);
-	len = MoxaPortWriteData(tty, buf, count);
-	spin_unlock_bh(&moxa_lock);
-
-	set_bit(LOWWAIT, &ch->statusflags);
-	return len;
-}
-
-static int moxa_write_room(struct tty_struct *tty)
-{
-	struct moxa_port *ch;
-
-	if (tty->stopped)
-		return 0;
-	ch = tty->driver_data;
-	if (ch == NULL)
-		return 0;
-	return MoxaPortTxFree(ch);
-}
-
-static void moxa_flush_buffer(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-	MoxaPortFlushData(ch, 1);
-	tty_wakeup(tty);
-}
-
-static int moxa_chars_in_buffer(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-	int chars;
-
-	chars = MoxaPortTxQueue(ch);
-	if (chars)
-		/*
-		 * Make it possible to wakeup anything waiting for output
-		 * in tty_ioctl.c, etc.
-		 */
-        	set_bit(EMPTYWAIT, &ch->statusflags);
-	return chars;
-}
-
-static int moxa_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct moxa_port *ch = tty->driver_data;
-	int flag = 0, dtr, rts;
-
-	MoxaPortGetLineOut(ch, &dtr, &rts);
-	if (dtr)
-		flag |= TIOCM_DTR;
-	if (rts)
-		flag |= TIOCM_RTS;
-	dtr = MoxaPortLineStatus(ch);
-	if (dtr & 1)
-		flag |= TIOCM_CTS;
-	if (dtr & 2)
-		flag |= TIOCM_DSR;
-	if (dtr & 4)
-		flag |= TIOCM_CD;
-	return flag;
-}
-
-static int moxa_tiocmset(struct tty_struct *tty, struct file *file,
-			 unsigned int set, unsigned int clear)
-{
-	struct moxa_port *ch;
-	int port;
-	int dtr, rts;
-
-	port = tty->index;
-	mutex_lock(&moxa_openlock);
-	ch = tty->driver_data;
-	if (!ch) {
-		mutex_unlock(&moxa_openlock);
-		return -EINVAL;
-	}
-
-	MoxaPortGetLineOut(ch, &dtr, &rts);
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-	MoxaPortLineCtrl(ch, dtr, rts);
-	mutex_unlock(&moxa_openlock);
-	return 0;
-}
-
-static void moxa_set_termios(struct tty_struct *tty,
-		struct ktermios *old_termios)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-	moxa_set_tty_param(tty, old_termios);
-	if (!(old_termios->c_cflag & CLOCAL) && C_CLOCAL(tty))
-		wake_up_interruptible(&ch->port.open_wait);
-}
-
-static void moxa_stop(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-	MoxaPortTxDisable(ch);
-	set_bit(TXSTOPPED, &ch->statusflags);
-}
-
-
-static void moxa_start(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-
-	if (ch == NULL)
-		return;
-
-	if (!(ch->statusflags & TXSTOPPED))
-		return;
-
-	MoxaPortTxEnable(ch);
-	clear_bit(TXSTOPPED, &ch->statusflags);
-}
-
-static void moxa_hangup(struct tty_struct *tty)
-{
-	struct moxa_port *ch = tty->driver_data;
-	tty_port_hangup(&ch->port);
-}
-
-static void moxa_new_dcdstate(struct moxa_port *p, u8 dcd)
-{
-	struct tty_struct *tty;
-	unsigned long flags;
-	dcd = !!dcd;
-
-	spin_lock_irqsave(&p->port.lock, flags);
-	if (dcd != p->DCDState) {
-        	p->DCDState = dcd;
-        	spin_unlock_irqrestore(&p->port.lock, flags);
-		tty = tty_port_tty_get(&p->port);
-		if (tty && C_CLOCAL(tty) && !dcd)
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
-	else
-		spin_unlock_irqrestore(&p->port.lock, flags);
-}
-
-static int moxa_poll_port(struct moxa_port *p, unsigned int handle,
-		u16 __iomem *ip)
-{
-	struct tty_struct *tty = tty_port_tty_get(&p->port);
-	void __iomem *ofsAddr;
-	unsigned int inited = p->port.flags & ASYNC_INITIALIZED;
-	u16 intr;
-
-	if (tty) {
-		if (test_bit(EMPTYWAIT, &p->statusflags) &&
-				MoxaPortTxQueue(p) == 0) {
-			clear_bit(EMPTYWAIT, &p->statusflags);
-			tty_wakeup(tty);
-		}
-		if (test_bit(LOWWAIT, &p->statusflags) && !tty->stopped &&
-				MoxaPortTxQueue(p) <= WAKEUP_CHARS) {
-			clear_bit(LOWWAIT, &p->statusflags);
-			tty_wakeup(tty);
-		}
-
-		if (inited && !test_bit(TTY_THROTTLED, &tty->flags) &&
-				MoxaPortRxQueue(p) > 0) { /* RX */
-			MoxaPortReadData(p);
-			tty_schedule_flip(tty);
-		}
-	} else {
-		clear_bit(EMPTYWAIT, &p->statusflags);
-		MoxaPortFlushData(p, 0); /* flush RX */
-	}
-
-	if (!handle) /* nothing else to do */
-		goto put;
-
-	intr = readw(ip); /* port irq status */
-	if (intr == 0)
-		goto put;
-
-	writew(0, ip); /* ACK port */
-	ofsAddr = p->tableAddr;
-	if (intr & IntrTx) /* disable tx intr */
-		writew(readw(ofsAddr + HostStat) & ~WakeupTx,
-				ofsAddr + HostStat);
-
-	if (!inited)
-		goto put;
-
-	if (tty && (intr & IntrBreak) && !I_IGNBRK(tty)) { /* BREAK */
-		tty_insert_flip_char(tty, 0, TTY_BREAK);
-		tty_schedule_flip(tty);
-	}
-
-	if (intr & IntrLine)
-		moxa_new_dcdstate(p, readb(ofsAddr + FlagStat) & DCD_state);
-put:
-	tty_kref_put(tty);
-
-	return 0;
-}
-
-static void moxa_poll(unsigned long ignored)
-{
-	struct moxa_board_conf *brd;
-	u16 __iomem *ip;
-	unsigned int card, port, served = 0;
-
-	spin_lock(&moxa_lock);
-	for (card = 0; card < MAX_BOARDS; card++) {
-		brd = &moxa_boards[card];
-		if (!brd->ready)
-			continue;
-
-		served++;
-
-		ip = NULL;
-		if (readb(brd->intPend) == 0xff)
-			ip = brd->intTable + readb(brd->intNdx);
-
-		for (port = 0; port < brd->numPorts; port++)
-			moxa_poll_port(&brd->ports[port], !!ip, ip + port);
-
-		if (ip)
-			writeb(0, brd->intPend); /* ACK */
-
-		if (moxaLowWaterChk) {
-			struct moxa_port *p = brd->ports;
-			for (port = 0; port < brd->numPorts; port++, p++)
-				if (p->lowChkFlag) {
-					p->lowChkFlag = 0;
-					moxa_low_water_check(p->tableAddr);
-				}
-		}
-	}
-	moxaLowWaterChk = 0;
-
-	if (served)
-		mod_timer(&moxaTimer, jiffies + HZ / 50);
-	spin_unlock(&moxa_lock);
-}
-
-/******************************************************************************/
-
-static void moxa_set_tty_param(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	register struct ktermios *ts = tty->termios;
-	struct moxa_port *ch = tty->driver_data;
-	int rts, cts, txflow, rxflow, xany, baud;
-
-	rts = cts = txflow = rxflow = xany = 0;
-	if (ts->c_cflag & CRTSCTS)
-		rts = cts = 1;
-	if (ts->c_iflag & IXON)
-		txflow = 1;
-	if (ts->c_iflag & IXOFF)
-		rxflow = 1;
-	if (ts->c_iflag & IXANY)
-		xany = 1;
-
-	/* Clear the features we don't support */
-	ts->c_cflag &= ~CMSPAR;
-	MoxaPortFlowCtrl(ch, rts, cts, txflow, rxflow, xany);
-	baud = MoxaPortSetTermio(ch, ts, tty_get_baud_rate(tty));
-	if (baud == -1)
-		baud = tty_termios_baud_rate(old_termios);
-	/* Not put the baud rate into the termios data */
-	tty_encode_baud_rate(tty, baud, baud);
-}
-
-/*****************************************************************************
- *	Driver level functions: 					     *
- *****************************************************************************/
-
-static void MoxaPortFlushData(struct moxa_port *port, int mode)
-{
-	void __iomem *ofsAddr;
-	if (mode < 0 || mode > 2)
-		return;
-	ofsAddr = port->tableAddr;
-	moxafunc(ofsAddr, FC_FlushQueue, mode);
-	if (mode != 1) {
-		port->lowChkFlag = 0;
-		moxa_low_water_check(ofsAddr);
-	}
-}
-
-/*
- *    Moxa Port Number Description:
- *
- *      MOXA serial driver supports up to 4 MOXA-C218/C320 boards. And,
- *      the port number using in MOXA driver functions will be 0 to 31 for
- *      first MOXA board, 32 to 63 for second, 64 to 95 for third and 96
- *      to 127 for fourth. For example, if you setup three MOXA boards,
- *      first board is C218, second board is C320-16 and third board is
- *      C320-32. The port number of first board (C218 - 8 ports) is from
- *      0 to 7. The port number of second board (C320 - 16 ports) is form
- *      32 to 47. The port number of third board (C320 - 32 ports) is from
- *      64 to 95. And those port numbers form 8 to 31, 48 to 63 and 96 to
- *      127 will be invalid.
- *
- *
- *      Moxa Functions Description:
- *
- *      Function 1:     Driver initialization routine, this routine must be
- *                      called when initialized driver.
- *      Syntax:
- *      void MoxaDriverInit();
- *
- *
- *      Function 2:     Moxa driver private IOCTL command processing.
- *      Syntax:
- *      int  MoxaDriverIoctl(unsigned int cmd, unsigned long arg, int port);
- *
- *           unsigned int cmd   : IOCTL command
- *           unsigned long arg  : IOCTL argument
- *           int port           : port number (0 - 127)
- *
- *           return:    0  (OK)
- *                      -EINVAL
- *                      -ENOIOCTLCMD
- *
- *
- *      Function 6:     Enable this port to start Tx/Rx data.
- *      Syntax:
- *      void MoxaPortEnable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 7:     Disable this port
- *      Syntax:
- *      void MoxaPortDisable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 10:    Setting baud rate of this port.
- *      Syntax:
- *      speed_t MoxaPortSetBaud(int port, speed_t baud);
- *           int port           : port number (0 - 127)
- *           long baud          : baud rate (50 - 115200)
- *
- *           return:    0       : this port is invalid or baud < 50
- *                      50 - 115200 : the real baud rate set to the port, if
- *                                    the argument baud is large than maximun
- *                                    available baud rate, the real setting
- *                                    baud rate will be the maximun baud rate.
- *
- *
- *      Function 12:    Configure the port.
- *      Syntax:
- *      int  MoxaPortSetTermio(int port, struct ktermios *termio, speed_t baud);
- *           int port           : port number (0 - 127)
- *           struct ktermios * termio : termio structure pointer
- *	     speed_t baud	: baud rate
- *
- *           return:    -1      : this port is invalid or termio == NULL
- *                      0       : setting O.K.
- *
- *
- *      Function 13:    Get the DTR/RTS state of this port.
- *      Syntax:
- *      int  MoxaPortGetLineOut(int port, int *dtrState, int *rtsState);
- *           int port           : port number (0 - 127)
- *           int * dtrState     : pointer to INT to receive the current DTR
- *                                state. (if NULL, this function will not
- *                                write to this address)
- *           int * rtsState     : pointer to INT to receive the current RTS
- *                                state. (if NULL, this function will not
- *                                write to this address)
- *
- *           return:    -1      : this port is invalid
- *                      0       : O.K.
- *
- *
- *      Function 14:    Setting the DTR/RTS output state of this port.
- *      Syntax:
- *      void MoxaPortLineCtrl(int port, int dtrState, int rtsState);
- *           int port           : port number (0 - 127)
- *           int dtrState       : DTR output state (0: off, 1: on)
- *           int rtsState       : RTS output state (0: off, 1: on)
- *
- *
- *      Function 15:    Setting the flow control of this port.
- *      Syntax:
- *      void MoxaPortFlowCtrl(int port, int rtsFlow, int ctsFlow, int rxFlow,
- *                            int txFlow,int xany);
- *           int port           : port number (0 - 127)
- *           int rtsFlow        : H/W RTS flow control (0: no, 1: yes)
- *           int ctsFlow        : H/W CTS flow control (0: no, 1: yes)
- *           int rxFlow         : S/W Rx XON/XOFF flow control (0: no, 1: yes)
- *           int txFlow         : S/W Tx XON/XOFF flow control (0: no, 1: yes)
- *           int xany           : S/W XANY flow control (0: no, 1: yes)
- *
- *
- *      Function 16:    Get ths line status of this port
- *      Syntax:
- *      int  MoxaPortLineStatus(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    Bit 0 - CTS state (0: off, 1: on)
- *                      Bit 1 - DSR state (0: off, 1: on)
- *                      Bit 2 - DCD state (0: off, 1: on)
- *
- *
- *      Function 19:    Flush the Rx/Tx buffer data of this port.
- *      Syntax:
- *      void MoxaPortFlushData(int port, int mode);
- *           int port           : port number (0 - 127)
- *           int mode    
- *                      0       : flush the Rx buffer 
- *                      1       : flush the Tx buffer 
- *                      2       : flush the Rx and Tx buffer 
- *
- *
- *      Function 20:    Write data.
- *      Syntax:
- *      int  MoxaPortWriteData(int port, unsigned char * buffer, int length);
- *           int port           : port number (0 - 127)
- *           unsigned char * buffer     : pointer to write data buffer.
- *           int length         : write data length
- *
- *           return:    0 - length      : real write data length
- *
- *
- *      Function 21:    Read data.
- *      Syntax:
- *      int  MoxaPortReadData(int port, struct tty_struct *tty);
- *           int port           : port number (0 - 127)
- *	     struct tty_struct *tty : tty for data
- *
- *           return:    0 - length      : real read data length
- *
- *
- *      Function 24:    Get the Tx buffer current queued data bytes
- *      Syntax:
- *      int  MoxaPortTxQueue(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Tx buffer current queued data bytes
- *
- *
- *      Function 25:    Get the Tx buffer current free space
- *      Syntax:
- *      int  MoxaPortTxFree(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Tx buffer current free space
- *
- *
- *      Function 26:    Get the Rx buffer current queued data bytes
- *      Syntax:
- *      int  MoxaPortRxQueue(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    ..      : Rx buffer current queued data bytes
- *
- *
- *      Function 28:    Disable port data transmission.
- *      Syntax:
- *      void MoxaPortTxDisable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 29:    Enable port data transmission.
- *      Syntax:
- *      void MoxaPortTxEnable(int port);
- *           int port           : port number (0 - 127)
- *
- *
- *      Function 31:    Get the received BREAK signal count and reset it.
- *      Syntax:
- *      int  MoxaPortResetBrkCnt(int port);
- *           int port           : port number (0 - 127)
- *
- *           return:    0 - ..  : BREAK signal count
- *
- *
- */
-
-static void MoxaPortEnable(struct moxa_port *port)
-{
-	void __iomem *ofsAddr;
-	u16 lowwater = 512;
-
-	ofsAddr = port->tableAddr;
-	writew(lowwater, ofsAddr + Low_water);
-	if (MOXA_IS_320(port->board))
-		moxafunc(ofsAddr, FC_SetBreakIrq, 0);
-	else
-		writew(readw(ofsAddr + HostStat) | WakeupBreak,
-				ofsAddr + HostStat);
-
-	moxafunc(ofsAddr, FC_SetLineIrq, Magic_code);
-	moxafunc(ofsAddr, FC_FlushQueue, 2);
-
-	moxafunc(ofsAddr, FC_EnableCH, Magic_code);
-	MoxaPortLineStatus(port);
-}
-
-static void MoxaPortDisable(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-
-	moxafunc(ofsAddr, FC_SetFlowCtl, 0);	/* disable flow control */
-	moxafunc(ofsAddr, FC_ClrLineIrq, Magic_code);
-	writew(0, ofsAddr + HostStat);
-	moxafunc(ofsAddr, FC_DisableCH, Magic_code);
-}
-
-static speed_t MoxaPortSetBaud(struct moxa_port *port, speed_t baud)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	unsigned int clock, val;
-	speed_t max;
-
-	max = MOXA_IS_320(port->board) ? 460800 : 921600;
-	if (baud < 50)
-		return 0;
-	if (baud > max)
-		baud = max;
-	clock = 921600;
-	val = clock / baud;
-	moxafunc(ofsAddr, FC_SetBaud, val);
-	baud = clock / val;
-	return baud;
-}
-
-static int MoxaPortSetTermio(struct moxa_port *port, struct ktermios *termio,
-		speed_t baud)
-{
-	void __iomem *ofsAddr;
-	tcflag_t cflag;
-	tcflag_t mode = 0;
-
-	ofsAddr = port->tableAddr;
-	cflag = termio->c_cflag;	/* termio->c_cflag */
-
-	mode = termio->c_cflag & CSIZE;
-	if (mode == CS5)
-		mode = MX_CS5;
-	else if (mode == CS6)
-		mode = MX_CS6;
-	else if (mode == CS7)
-		mode = MX_CS7;
-	else if (mode == CS8)
-		mode = MX_CS8;
-
-	if (termio->c_cflag & CSTOPB) {
-		if (mode == MX_CS5)
-			mode |= MX_STOP15;
-		else
-			mode |= MX_STOP2;
-	} else
-		mode |= MX_STOP1;
-
-	if (termio->c_cflag & PARENB) {
-		if (termio->c_cflag & PARODD)
-			mode |= MX_PARODD;
-		else
-			mode |= MX_PAREVEN;
-	} else
-		mode |= MX_PARNONE;
-
-	moxafunc(ofsAddr, FC_SetDataMode, (u16)mode);
-
-	if (MOXA_IS_320(port->board) && baud >= 921600)
-		return -1;
-
-	baud = MoxaPortSetBaud(port, baud);
-
-	if (termio->c_iflag & (IXON | IXOFF | IXANY)) {
-	        spin_lock_irq(&moxafunc_lock);
-		writeb(termio->c_cc[VSTART], ofsAddr + FuncArg);
-		writeb(termio->c_cc[VSTOP], ofsAddr + FuncArg1);
-		writeb(FC_SetXonXoff, ofsAddr + FuncCode);
-		moxa_wait_finish(ofsAddr);
-		spin_unlock_irq(&moxafunc_lock);
-
-	}
-	return baud;
-}
-
-static int MoxaPortGetLineOut(struct moxa_port *port, int *dtrState,
-		int *rtsState)
-{
-	if (dtrState)
-		*dtrState = !!(port->lineCtrl & DTR_ON);
-	if (rtsState)
-		*rtsState = !!(port->lineCtrl & RTS_ON);
-
-	return 0;
-}
-
-static void MoxaPortLineCtrl(struct moxa_port *port, int dtr, int rts)
-{
-	u8 mode = 0;
-
-	if (dtr)
-		mode |= DTR_ON;
-	if (rts)
-		mode |= RTS_ON;
-	port->lineCtrl = mode;
-	moxafunc(port->tableAddr, FC_LineControl, mode);
-}
-
-static void MoxaPortFlowCtrl(struct moxa_port *port, int rts, int cts,
-		int txflow, int rxflow, int txany)
-{
-	int mode = 0;
-
-	if (rts)
-		mode |= RTS_FlowCtl;
-	if (cts)
-		mode |= CTS_FlowCtl;
-	if (txflow)
-		mode |= Tx_FlowCtl;
-	if (rxflow)
-		mode |= Rx_FlowCtl;
-	if (txany)
-		mode |= IXM_IXANY;
-	moxafunc(port->tableAddr, FC_SetFlowCtl, mode);
-}
-
-static int MoxaPortLineStatus(struct moxa_port *port)
-{
-	void __iomem *ofsAddr;
-	int val;
-
-	ofsAddr = port->tableAddr;
-	if (MOXA_IS_320(port->board))
-		val = moxafuncret(ofsAddr, FC_LineStatus, 0);
-	else
-		val = readw(ofsAddr + FlagStat) >> 4;
-	val &= 0x0B;
-	if (val & 8)
-		val |= 4;
-	moxa_new_dcdstate(port, val & 8);
-	val &= 7;
-	return val;
-}
-
-static int MoxaPortWriteData(struct tty_struct *tty,
-		const unsigned char *buffer, int len)
-{
-	struct moxa_port *port = tty->driver_data;
-	void __iomem *baseAddr, *ofsAddr, *ofs;
-	unsigned int c, total;
-	u16 head, tail, tx_mask, spage, epage;
-	u16 pageno, pageofs, bufhead;
-
-	ofsAddr = port->tableAddr;
-	baseAddr = port->board->basemem;
-	tx_mask = readw(ofsAddr + TX_mask);
-	spage = readw(ofsAddr + Page_txb);
-	epage = readw(ofsAddr + EndPage_txb);
-	tail = readw(ofsAddr + TXwptr);
-	head = readw(ofsAddr + TXrptr);
-	c = (head > tail) ? (head - tail - 1) : (head - tail + tx_mask);
-	if (c > len)
-		c = len;
-	moxaLog.txcnt[port->port.tty->index] += c;
-	total = c;
-	if (spage == epage) {
-		bufhead = readw(ofsAddr + Ofs_txb);
-		writew(spage, baseAddr + Control_reg);
-		while (c > 0) {
-			if (head > tail)
-				len = head - tail - 1;
-			else
-				len = tx_mask + 1 - tail;
-			len = (c > len) ? len : c;
-			ofs = baseAddr + DynPage_addr + bufhead + tail;
-			memcpy_toio(ofs, buffer, len);
-			buffer += len;
-			tail = (tail + len) & tx_mask;
-			c -= len;
-		}
-	} else {
-		pageno = spage + (tail >> 13);
-		pageofs = tail & Page_mask;
-		while (c > 0) {
-			len = Page_size - pageofs;
-			if (len > c)
-				len = c;
-			writeb(pageno, baseAddr + Control_reg);
-			ofs = baseAddr + DynPage_addr + pageofs;
-			memcpy_toio(ofs, buffer, len);
-			buffer += len;
-			if (++pageno == epage)
-				pageno = spage;
-			pageofs = 0;
-			c -= len;
-		}
-		tail = (tail + total) & tx_mask;
-	}
-	writew(tail, ofsAddr + TXwptr);
-	writeb(1, ofsAddr + CD180TXirq);	/* start to send */
-	return total;
-}
-
-static int MoxaPortReadData(struct moxa_port *port)
-{
-	struct tty_struct *tty = port->port.tty;
-	unsigned char *dst;
-	void __iomem *baseAddr, *ofsAddr, *ofs;
-	unsigned int count, len, total;
-	u16 tail, rx_mask, spage, epage;
-	u16 pageno, pageofs, bufhead, head;
-
-	ofsAddr = port->tableAddr;
-	baseAddr = port->board->basemem;
-	head = readw(ofsAddr + RXrptr);
-	tail = readw(ofsAddr + RXwptr);
-	rx_mask = readw(ofsAddr + RX_mask);
-	spage = readw(ofsAddr + Page_rxb);
-	epage = readw(ofsAddr + EndPage_rxb);
-	count = (tail >= head) ? (tail - head) : (tail - head + rx_mask + 1);
-	if (count == 0)
-		return 0;
-
-	total = count;
-	moxaLog.rxcnt[tty->index] += total;
-	if (spage == epage) {
-		bufhead = readw(ofsAddr + Ofs_rxb);
-		writew(spage, baseAddr + Control_reg);
-		while (count > 0) {
-			ofs = baseAddr + DynPage_addr + bufhead + head;
-			len = (tail >= head) ? (tail - head) :
-					(rx_mask + 1 - head);
-			len = tty_prepare_flip_string(tty, &dst,
-					min(len, count));
-			memcpy_fromio(dst, ofs, len);
-			head = (head + len) & rx_mask;
-			count -= len;
-		}
-	} else {
-		pageno = spage + (head >> 13);
-		pageofs = head & Page_mask;
-		while (count > 0) {
-			writew(pageno, baseAddr + Control_reg);
-			ofs = baseAddr + DynPage_addr + pageofs;
-			len = tty_prepare_flip_string(tty, &dst,
-					min(Page_size - pageofs, count));
-			memcpy_fromio(dst, ofs, len);
-
-			count -= len;
-			pageofs = (pageofs + len) & Page_mask;
-			if (pageofs == 0 && ++pageno == epage)
-				pageno = spage;
-		}
-		head = (head + total) & rx_mask;
-	}
-	writew(head, ofsAddr + RXrptr);
-	if (readb(ofsAddr + FlagStat) & Xoff_state) {
-		moxaLowWaterChk = 1;
-		port->lowChkFlag = 1;
-	}
-	return total;
-}
-
-
-static int MoxaPortTxQueue(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	u16 rptr, wptr, mask;
-
-	rptr = readw(ofsAddr + TXrptr);
-	wptr = readw(ofsAddr + TXwptr);
-	mask = readw(ofsAddr + TX_mask);
-	return (wptr - rptr) & mask;
-}
-
-static int MoxaPortTxFree(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	u16 rptr, wptr, mask;
-
-	rptr = readw(ofsAddr + TXrptr);
-	wptr = readw(ofsAddr + TXwptr);
-	mask = readw(ofsAddr + TX_mask);
-	return mask - ((wptr - rptr) & mask);
-}
-
-static int MoxaPortRxQueue(struct moxa_port *port)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-	u16 rptr, wptr, mask;
-
-	rptr = readw(ofsAddr + RXrptr);
-	wptr = readw(ofsAddr + RXwptr);
-	mask = readw(ofsAddr + RX_mask);
-	return (wptr - rptr) & mask;
-}
-
-static void MoxaPortTxDisable(struct moxa_port *port)
-{
-	moxafunc(port->tableAddr, FC_SetXoffState, Magic_code);
-}
-
-static void MoxaPortTxEnable(struct moxa_port *port)
-{
-	moxafunc(port->tableAddr, FC_SetXonState, Magic_code);
-}
-
-static int moxa_get_serial_info(struct moxa_port *info,
-		struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp = {
-		.type = info->type,
-		.line = info->port.tty->index,
-		.flags = info->port.flags,
-		.baud_base = 921600,
-		.close_delay = info->port.close_delay
-	};
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}
-
-
-static int moxa_set_serial_info(struct moxa_port *info,
-		struct serial_struct __user *new_info)
-{
-	struct serial_struct new_serial;
-
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-
-	if (new_serial.irq != 0 || new_serial.port != 0 ||
-			new_serial.custom_divisor != 0 ||
-			new_serial.baud_base != 921600)
-		return -EPERM;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if (((new_serial.flags & ~ASYNC_USR_MASK) !=
-		     (info->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-	} else
-		info->port.close_delay = new_serial.close_delay * HZ / 100;
-
-	new_serial.flags = (new_serial.flags & ~ASYNC_FLAGS);
-	new_serial.flags |= (info->port.flags & ASYNC_FLAGS);
-
-	MoxaSetFifo(info, new_serial.type == PORT_16550A);
-
-	info->type = new_serial.type;
-	return 0;
-}
-
-
-
-/*****************************************************************************
- *	Static local functions: 					     *
- *****************************************************************************/
-
-static void MoxaSetFifo(struct moxa_port *port, int enable)
-{
-	void __iomem *ofsAddr = port->tableAddr;
-
-	if (!enable) {
-		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 0);
-		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 1);
-	} else {
-		moxafunc(ofsAddr, FC_SetRxFIFOTrig, 3);
-		moxafunc(ofsAddr, FC_SetTxFIFOCnt, 16);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/moxa.h linux-libre-2.6.39-gnu/drivers/char/moxa.h
--- linux-libre-2.6.38-gnu/drivers/char/moxa.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/moxa.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,304 +0,0 @@
-#ifndef MOXA_H_FILE
-#define MOXA_H_FILE
-
-#define	MOXA		0x400
-#define MOXA_GET_IQUEUE 	(MOXA + 1)	/* get input buffered count */
-#define MOXA_GET_OQUEUE 	(MOXA + 2)	/* get output buffered count */
-#define MOXA_GETDATACOUNT       (MOXA + 23)
-#define MOXA_GET_IOQUEUE	(MOXA + 27)
-#define MOXA_FLUSH_QUEUE	(MOXA + 28)
-#define MOXA_GETMSTATUS         (MOXA + 65)
-
-/*
- *    System Configuration
- */
-
-#define Magic_code	0x404
-
-/*
- *    for C218 BIOS initialization
- */
-#define C218_ConfBase	0x800
-#define C218_status	(C218_ConfBase + 0)	/* BIOS running status    */
-#define C218_diag	(C218_ConfBase + 2)	/* diagnostic status      */
-#define C218_key	(C218_ConfBase + 4)	/* WORD (0x218 for C218) */
-#define C218DLoad_len	(C218_ConfBase + 6)	/* WORD           */
-#define C218check_sum	(C218_ConfBase + 8)	/* BYTE           */
-#define C218chksum_ok	(C218_ConfBase + 0x0a)	/* BYTE (1:ok)            */
-#define C218_TestRx	(C218_ConfBase + 0x10)	/* 8 bytes for 8 ports    */
-#define C218_TestTx	(C218_ConfBase + 0x18)	/* 8 bytes for 8 ports    */
-#define C218_RXerr	(C218_ConfBase + 0x20)	/* 8 bytes for 8 ports    */
-#define C218_ErrFlag	(C218_ConfBase + 0x28)	/* 8 bytes for 8 ports    */
-
-#define C218_LoadBuf	0x0F00
-#define C218_KeyCode	0x218
-#define CP204J_KeyCode	0x204
-
-/*
- *    for C320 BIOS initialization
- */
-#define C320_ConfBase	0x800
-#define C320_LoadBuf	0x0f00
-#define STS_init	0x05	/* for C320_status        */
-
-#define C320_status	C320_ConfBase + 0	/* BIOS running status    */
-#define C320_diag	C320_ConfBase + 2	/* diagnostic status      */
-#define C320_key	C320_ConfBase + 4	/* WORD (0320H for C320) */
-#define C320DLoad_len	C320_ConfBase + 6	/* WORD           */
-#define C320check_sum	C320_ConfBase + 8	/* WORD           */
-#define C320chksum_ok	C320_ConfBase + 0x0a	/* WORD (1:ok)            */
-#define C320bapi_len	C320_ConfBase + 0x0c	/* WORD           */
-#define C320UART_no	C320_ConfBase + 0x0e	/* WORD           */
-
-#define C320_KeyCode	0x320
-
-#define FixPage_addr	0x0000	/* starting addr of static page  */
-#define DynPage_addr	0x2000	/* starting addr of dynamic page */
-#define C218_start	0x3000	/* starting addr of C218 BIOS prg */
-#define Control_reg	0x1ff0	/* select page and reset control */
-#define HW_reset	0x80
-
-/*
- *    Function Codes
- */
-#define FC_CardReset	0x80
-#define FC_ChannelReset 1	/* C320 firmware not supported */
-#define FC_EnableCH	2
-#define FC_DisableCH	3
-#define FC_SetParam	4
-#define FC_SetMode	5
-#define FC_SetRate	6
-#define FC_LineControl	7
-#define FC_LineStatus	8
-#define FC_XmitControl	9
-#define FC_FlushQueue	10
-#define FC_SendBreak	11
-#define FC_StopBreak	12
-#define FC_LoopbackON	13
-#define FC_LoopbackOFF	14
-#define FC_ClrIrqTable	15
-#define FC_SendXon	16
-#define FC_SetTermIrq	17	/* C320 firmware not supported */
-#define FC_SetCntIrq	18	/* C320 firmware not supported */
-#define FC_SetBreakIrq	19
-#define FC_SetLineIrq	20
-#define FC_SetFlowCtl	21
-#define FC_GenIrq	22
-#define FC_InCD180	23
-#define FC_OutCD180	24
-#define FC_InUARTreg	23
-#define FC_OutUARTreg	24
-#define FC_SetXonXoff	25
-#define FC_OutCD180CCR	26
-#define FC_ExtIQueue	27
-#define FC_ExtOQueue	28
-#define FC_ClrLineIrq	29
-#define FC_HWFlowCtl	30
-#define FC_GetClockRate 35
-#define FC_SetBaud	36
-#define FC_SetDataMode  41
-#define FC_GetCCSR      43
-#define FC_GetDataError 45
-#define FC_RxControl	50
-#define FC_ImmSend	51
-#define FC_SetXonState	52
-#define FC_SetXoffState	53
-#define FC_SetRxFIFOTrig 54
-#define FC_SetTxFIFOCnt 55
-#define FC_UnixRate	56
-#define FC_UnixResetTimer 57
-
-#define	RxFIFOTrig1	0
-#define	RxFIFOTrig4	1
-#define	RxFIFOTrig8	2
-#define	RxFIFOTrig14	3
-
-/*
- *    Dual-Ported RAM
- */
-#define DRAM_global	0
-#define INT_data	(DRAM_global + 0)
-#define Config_base	(DRAM_global + 0x108)
-
-#define IRQindex	(INT_data + 0)
-#define IRQpending	(INT_data + 4)
-#define IRQtable	(INT_data + 8)
-
-/*
- *    Interrupt Status
- */
-#define IntrRx		0x01	/* receiver data O.K.             */
-#define IntrTx		0x02	/* transmit buffer empty  */
-#define IntrFunc	0x04	/* function complete              */
-#define IntrBreak	0x08	/* received break         */
-#define IntrLine	0x10	/* line status change
-				   for transmitter                */
-#define IntrIntr	0x20	/* received INTR code             */
-#define IntrQuit	0x40	/* received QUIT code             */
-#define IntrEOF 	0x80	/* received EOF code              */
-
-#define IntrRxTrigger 	0x100	/* rx data count reach tigger value */
-#define IntrTxTrigger 	0x200	/* tx data count below trigger value */
-
-#define Magic_no	(Config_base + 0)
-#define Card_model_no	(Config_base + 2)
-#define Total_ports	(Config_base + 4)
-#define Module_cnt	(Config_base + 8)
-#define Module_no	(Config_base + 10)
-#define Timer_10ms	(Config_base + 14)
-#define Disable_IRQ	(Config_base + 20)
-#define TMS320_PORT1	(Config_base + 22)
-#define TMS320_PORT2	(Config_base + 24)
-#define TMS320_CLOCK	(Config_base + 26)
-
-/*
- *    DATA BUFFER in DRAM
- */
-#define Extern_table	0x400	/* Base address of the external table
-				   (24 words *    64) total 3K bytes
-				   (24 words * 128) total 6K bytes */
-#define Extern_size	0x60	/* 96 bytes                       */
-#define RXrptr		0x00	/* read pointer for RX buffer     */
-#define RXwptr		0x02	/* write pointer for RX buffer    */
-#define TXrptr		0x04	/* read pointer for TX buffer     */
-#define TXwptr		0x06	/* write pointer for TX buffer    */
-#define HostStat	0x08	/* IRQ flag and general flag      */
-#define FlagStat	0x0A
-#define FlowControl	0x0C	/* B7 B6 B5 B4 B3 B2 B1 B0              */
-				/*  x  x  x  x  |  |  |  |            */
-				/*              |  |  |  + CTS flow   */
-				/*              |  |  +--- RTS flow   */
-				/*              |  +------ TX Xon/Xoff */
-				/*              +--------- RX Xon/Xoff */
-#define Break_cnt	0x0E	/* received break count   */
-#define CD180TXirq	0x10	/* if non-0: enable TX irq        */
-#define RX_mask 	0x12
-#define TX_mask 	0x14
-#define Ofs_rxb 	0x16
-#define Ofs_txb 	0x18
-#define Page_rxb	0x1A
-#define Page_txb	0x1C
-#define EndPage_rxb	0x1E
-#define EndPage_txb	0x20
-#define Data_error	0x22
-#define RxTrigger	0x28
-#define TxTrigger	0x2a
-
-#define rRXwptr 	0x34
-#define Low_water	0x36
-
-#define FuncCode	0x40
-#define FuncArg 	0x42
-#define FuncArg1	0x44
-
-#define C218rx_size	0x2000	/* 8K bytes */
-#define C218tx_size	0x8000	/* 32K bytes */
-
-#define C218rx_mask	(C218rx_size - 1)
-#define C218tx_mask	(C218tx_size - 1)
-
-#define C320p8rx_size	0x2000
-#define C320p8tx_size	0x8000
-#define C320p8rx_mask	(C320p8rx_size - 1)
-#define C320p8tx_mask	(C320p8tx_size - 1)
-
-#define C320p16rx_size	0x2000
-#define C320p16tx_size	0x4000
-#define C320p16rx_mask	(C320p16rx_size - 1)
-#define C320p16tx_mask	(C320p16tx_size - 1)
-
-#define C320p24rx_size	0x2000
-#define C320p24tx_size	0x2000
-#define C320p24rx_mask	(C320p24rx_size - 1)
-#define C320p24tx_mask	(C320p24tx_size - 1)
-
-#define C320p32rx_size	0x1000
-#define C320p32tx_size	0x1000
-#define C320p32rx_mask	(C320p32rx_size - 1)
-#define C320p32tx_mask	(C320p32tx_size - 1)
-
-#define Page_size	0x2000U
-#define Page_mask	(Page_size - 1)
-#define C218rx_spage	3
-#define C218tx_spage	4
-#define C218rx_pageno	1
-#define C218tx_pageno	4
-#define C218buf_pageno	5
-
-#define C320p8rx_spage	3
-#define C320p8tx_spage	4
-#define C320p8rx_pgno	1
-#define C320p8tx_pgno	4
-#define C320p8buf_pgno	5
-
-#define C320p16rx_spage 3
-#define C320p16tx_spage 4
-#define C320p16rx_pgno	1
-#define C320p16tx_pgno	2
-#define C320p16buf_pgno 3
-
-#define C320p24rx_spage 3
-#define C320p24tx_spage 4
-#define C320p24rx_pgno	1
-#define C320p24tx_pgno	1
-#define C320p24buf_pgno 2
-
-#define C320p32rx_spage 3
-#define C320p32tx_ofs	C320p32rx_size
-#define C320p32tx_spage 3
-#define C320p32buf_pgno 1
-
-/*
- *    Host Status
- */
-#define WakeupRx	0x01
-#define WakeupTx	0x02
-#define WakeupBreak	0x08
-#define WakeupLine	0x10
-#define WakeupIntr	0x20
-#define WakeupQuit	0x40
-#define WakeupEOF	0x80	/* used in VTIME control */
-#define WakeupRxTrigger	0x100
-#define WakeupTxTrigger	0x200
-/*
- *    Flag status
- */
-#define Rx_over		0x01
-#define Xoff_state	0x02
-#define Tx_flowOff	0x04
-#define Tx_enable	0x08
-#define CTS_state	0x10
-#define DSR_state	0x20
-#define DCD_state	0x80
-/*
- *    FlowControl
- */
-#define CTS_FlowCtl	1
-#define RTS_FlowCtl	2
-#define Tx_FlowCtl	4
-#define Rx_FlowCtl	8
-#define IXM_IXANY	0x10
-
-#define LowWater	128
-
-#define DTR_ON		1
-#define RTS_ON		2
-#define CTS_ON		1
-#define DSR_ON		2
-#define DCD_ON		8
-
-/* mode definition */
-#define	MX_CS8		0x03
-#define	MX_CS7		0x02
-#define	MX_CS6		0x01
-#define	MX_CS5		0x00
-
-#define	MX_STOP1	0x00
-#define	MX_STOP15	0x04
-#define	MX_STOP2	0x08
-
-#define	MX_PARNONE	0x00
-#define	MX_PAREVEN	0x40
-#define	MX_PARODD	0xC0
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/msm_smd_pkt.c linux-libre-2.6.39-gnu/drivers/char/msm_smd_pkt.c
--- linux-libre-2.6.38-gnu/drivers/char/msm_smd_pkt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/char/msm_smd_pkt.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,466 @@
+/* Copyright (c) 2008-2010, Code Aurora Forum. 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 and
+ * only 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.
+ *
+ */
+/*
+ * SMD Packet Driver -- Provides userspace interface to SMD packet ports.
+ */
+
+#include <linux/slab.h>
+#include <linux/cdev.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/device.h>
+#include <linux/sched.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/uaccess.h>
+#include <linux/workqueue.h>
+#include <linux/poll.h>
+
+#include <mach/msm_smd.h>
+
+#define NUM_SMD_PKT_PORTS 9
+#define DEVICE_NAME "smdpkt"
+#define MAX_BUF_SIZE 2048
+
+struct smd_pkt_dev {
+	struct cdev cdev;
+	struct device *devicep;
+
+	struct smd_channel *ch;
+	int open_count;
+	struct mutex ch_lock;
+	struct mutex rx_lock;
+	struct mutex tx_lock;
+	wait_queue_head_t ch_read_wait_queue;
+	wait_queue_head_t ch_opened_wait_queue;
+
+	int i;
+
+	unsigned char tx_buf[MAX_BUF_SIZE];
+	unsigned char rx_buf[MAX_BUF_SIZE];
+	int remote_open;
+
+} *smd_pkt_devp[NUM_SMD_PKT_PORTS];
+
+struct class *smd_pkt_classp;
+static dev_t smd_pkt_number;
+
+static int msm_smd_pkt_debug_enable;
+module_param_named(debug_enable, msm_smd_pkt_debug_enable,
+		   int, S_IRUGO | S_IWUSR | S_IWGRP);
+
+#ifdef DEBUG
+#define D_DUMP_BUFFER(prestr, cnt, buf) do {			\
+		int i;						\
+		if (msm_smd_pkt_debug_enable) {			\
+			pr_debug("%s", prestr);			\
+			for (i = 0; i < cnt; i++)		\
+				pr_debug("%.2x", buf[i]);	\
+			pr_debug("\n");				\
+		}						\
+	} while (0)
+#else
+#define D_DUMP_BUFFER(prestr, cnt, buf) do {} while (0)
+#endif
+
+#ifdef DEBUG
+#define DBG(x...) do {			\
+	if (msm_smd_pkt_debug_enable)	\
+		pr_debug(x);		\
+	} while (0)
+#else
+#define DBG(x...) do {} while (0)
+#endif
+
+static void check_and_wakeup_reader(struct smd_pkt_dev *smd_pkt_devp)
+{
+	int sz;
+
+	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+		return;
+
+	sz = smd_cur_packet_size(smd_pkt_devp->ch);
+	if (sz == 0) {
+		DBG("no packet\n");
+		return;
+	}
+	if (sz > smd_read_avail(smd_pkt_devp->ch)) {
+		DBG("incomplete packet\n");
+		return;
+	}
+
+	DBG("waking up reader\n");
+	wake_up_interruptible(&smd_pkt_devp->ch_read_wait_queue);
+}
+
+static int smd_pkt_read(struct file *file, char __user *buf,
+			size_t count, loff_t *ppos)
+{
+	int r, bytes_read;
+	struct smd_pkt_dev *smd_pkt_devp;
+	struct smd_channel *chl;
+
+	DBG("read %d bytes\n", count);
+	if (count > MAX_BUF_SIZE)
+		return -EINVAL;
+
+	smd_pkt_devp = file->private_data;
+	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+		return -EINVAL;
+
+	chl = smd_pkt_devp->ch;
+wait_for_packet:
+	r = wait_event_interruptible(smd_pkt_devp->ch_read_wait_queue,
+				     (smd_cur_packet_size(chl) > 0 &&
+				      smd_read_avail(chl) >=
+				      smd_cur_packet_size(chl)));
+
+	if (r < 0) {
+		if (r != -ERESTARTSYS)
+			pr_err("wait returned %d\n", r);
+		return r;
+	}
+
+	mutex_lock(&smd_pkt_devp->rx_lock);
+
+	bytes_read = smd_cur_packet_size(smd_pkt_devp->ch);
+	if (bytes_read == 0 ||
+	    bytes_read < smd_read_avail(smd_pkt_devp->ch)) {
+		mutex_unlock(&smd_pkt_devp->rx_lock);
+		DBG("Nothing to read\n");
+		goto wait_for_packet;
+	}
+
+	if (bytes_read > count) {
+		mutex_unlock(&smd_pkt_devp->rx_lock);
+		pr_info("packet size %d > buffer size %d", bytes_read, count);
+		return -EINVAL;
+	}
+
+	r = smd_read(smd_pkt_devp->ch, smd_pkt_devp->rx_buf, bytes_read);
+	if (r != bytes_read) {
+		mutex_unlock(&smd_pkt_devp->rx_lock);
+		pr_err("smd_read failed to read %d bytes: %d\n", bytes_read, r);
+		return -EIO;
+	}
+
+	D_DUMP_BUFFER("read: ", bytes_read, smd_pkt_devp->rx_buf);
+	r = copy_to_user(buf, smd_pkt_devp->rx_buf, bytes_read);
+	mutex_unlock(&smd_pkt_devp->rx_lock);
+	if (r) {
+		pr_err("copy_to_user failed %d\n", r);
+		return -EFAULT;
+	}
+
+	DBG("read complete %d bytes\n", bytes_read);
+	check_and_wakeup_reader(smd_pkt_devp);
+
+	return bytes_read;
+}
+
+static int smd_pkt_write(struct file *file, const char __user *buf,
+			 size_t count, loff_t *ppos)
+{
+	int r;
+	struct smd_pkt_dev *smd_pkt_devp;
+
+	if (count > MAX_BUF_SIZE)
+		return -EINVAL;
+
+	DBG("writting %d bytes\n", count);
+
+	smd_pkt_devp = file->private_data;
+	if (!smd_pkt_devp || !smd_pkt_devp->ch)
+		return -EINVAL;
+
+	mutex_lock(&smd_pkt_devp->tx_lock);
+	if (smd_write_avail(smd_pkt_devp->ch) < count) {
+		mutex_unlock(&smd_pkt_devp->tx_lock);
+		DBG("Not enough space to write\n");
+		return -ENOMEM;
+	}
+
+	D_DUMP_BUFFER("write: ", count, buf);
+	r = copy_from_user(smd_pkt_devp->tx_buf, buf, count);
+	if (r) {
+		mutex_unlock(&smd_pkt_devp->tx_lock);
+		pr_err("copy_from_user failed %d\n", r);
+		return -EFAULT;
+	}
+
+	r = smd_write(smd_pkt_devp->ch, smd_pkt_devp->tx_buf, count);
+	if (r != count) {
+		mutex_unlock(&smd_pkt_devp->tx_lock);
+		pr_err("smd_write failed to write %d bytes: %d.\n", count, r);
+		return -EIO;
+	}
+	mutex_unlock(&smd_pkt_devp->tx_lock);
+
+	DBG("wrote %d bytes\n", count);
+	return count;
+}
+
+static unsigned int smd_pkt_poll(struct file *file, poll_table *wait)
+{
+	struct smd_pkt_dev *smd_pkt_devp;
+	unsigned int mask = 0;
+
+	smd_pkt_devp = file->private_data;
+	if (!smd_pkt_devp)
+		return POLLERR;
+
+	DBG("poll waiting\n");
+	poll_wait(file, &smd_pkt_devp->ch_read_wait_queue, wait);
+	if (smd_read_avail(smd_pkt_devp->ch))
+		mask |= POLLIN | POLLRDNORM;
+
+	DBG("poll return\n");
+	return mask;
+}
+
+static void smd_pkt_ch_notify(void *priv, unsigned event)
+{
+	struct smd_pkt_dev *smd_pkt_devp = priv;
+
+	if (smd_pkt_devp->ch == 0)
+		return;
+
+	switch (event) {
+	case SMD_EVENT_DATA:
+		DBG("data\n");
+		check_and_wakeup_reader(smd_pkt_devp);
+		break;
+
+	case SMD_EVENT_OPEN:
+		DBG("remote open\n");
+		smd_pkt_devp->remote_open = 1;
+		wake_up_interruptible(&smd_pkt_devp->ch_opened_wait_queue);
+		break;
+
+	case SMD_EVENT_CLOSE:
+		smd_pkt_devp->remote_open = 0;
+		pr_info("remote closed\n");
+		break;
+
+	default:
+		pr_err("unknown event %d\n", event);
+		break;
+	}
+}
+
+static char *smd_pkt_dev_name[] = {
+	"smdcntl0",
+	"smdcntl1",
+	"smdcntl2",
+	"smdcntl3",
+	"smdcntl4",
+	"smdcntl5",
+	"smdcntl6",
+	"smdcntl7",
+	"smd22",
+};
+
+static char *smd_ch_name[] = {
+	"DATA5_CNTL",
+	"DATA6_CNTL",
+	"DATA7_CNTL",
+	"DATA8_CNTL",
+	"DATA9_CNTL",
+	"DATA12_CNTL",
+	"DATA13_CNTL",
+	"DATA14_CNTL",
+	"DATA22",
+};
+
+static int smd_pkt_open(struct inode *inode, struct file *file)
+{
+	int r = 0;
+	struct smd_pkt_dev *smd_pkt_devp;
+
+	smd_pkt_devp = container_of(inode->i_cdev, struct smd_pkt_dev, cdev);
+	if (!smd_pkt_devp)
+		return -EINVAL;
+
+	file->private_data = smd_pkt_devp;
+
+	mutex_lock(&smd_pkt_devp->ch_lock);
+	if (smd_pkt_devp->open_count == 0) {
+		r = smd_open(smd_ch_name[smd_pkt_devp->i],
+			     &smd_pkt_devp->ch, smd_pkt_devp,
+			     smd_pkt_ch_notify);
+		if (r < 0) {
+			pr_err("smd_open failed for %s, %d\n",
+			       smd_ch_name[smd_pkt_devp->i], r);
+			goto out;
+		}
+
+		r = wait_event_interruptible_timeout(
+				smd_pkt_devp->ch_opened_wait_queue,
+				smd_pkt_devp->remote_open,
+				msecs_to_jiffies(2 * HZ));
+		if (r == 0)
+			r = -ETIMEDOUT;
+
+		if (r < 0) {
+			pr_err("wait returned %d\n", r);
+			smd_close(smd_pkt_devp->ch);
+			smd_pkt_devp->ch = 0;
+		} else {
+			smd_pkt_devp->open_count++;
+			r = 0;
+		}
+	}
+out:
+	mutex_unlock(&smd_pkt_devp->ch_lock);
+	return r;
+}
+
+static int smd_pkt_release(struct inode *inode, struct file *file)
+{
+	int r = 0;
+	struct smd_pkt_dev *smd_pkt_devp = file->private_data;
+
+	if (!smd_pkt_devp)
+		return -EINVAL;
+
+	mutex_lock(&smd_pkt_devp->ch_lock);
+	if (--smd_pkt_devp->open_count == 0) {
+		r = smd_close(smd_pkt_devp->ch);
+		smd_pkt_devp->ch = 0;
+	}
+	mutex_unlock(&smd_pkt_devp->ch_lock);
+
+	return r;
+}
+
+static const struct file_operations smd_pkt_fops = {
+	.owner = THIS_MODULE,
+	.open = smd_pkt_open,
+	.release = smd_pkt_release,
+	.read = smd_pkt_read,
+	.write = smd_pkt_write,
+	.poll = smd_pkt_poll,
+};
+
+static int __init smd_pkt_init(void)
+{
+	int i;
+	int r;
+
+	r = alloc_chrdev_region(&smd_pkt_number, 0,
+				NUM_SMD_PKT_PORTS, DEVICE_NAME);
+	if (r) {
+		pr_err("alloc_chrdev_region() failed %d\n", r);
+		return r;
+	}
+
+	smd_pkt_classp = class_create(THIS_MODULE, DEVICE_NAME);
+	if (IS_ERR(smd_pkt_classp)) {
+		r = PTR_ERR(smd_pkt_classp);
+		pr_err("class_create() failed %d\n", r);
+		goto unreg_chardev;
+	}
+
+	for (i = 0; i < NUM_SMD_PKT_PORTS; ++i) {
+		smd_pkt_devp[i] = kzalloc(sizeof(struct smd_pkt_dev),
+					  GFP_KERNEL);
+		if (IS_ERR(smd_pkt_devp[i])) {
+			r = PTR_ERR(smd_pkt_devp[i]);
+			pr_err("kmalloc() failed %d\n", r);
+			goto clean_cdevs;
+		}
+
+		smd_pkt_devp[i]->i = i;
+
+		init_waitqueue_head(&smd_pkt_devp[i]->ch_read_wait_queue);
+		smd_pkt_devp[i]->remote_open = 0;
+		init_waitqueue_head(&smd_pkt_devp[i]->ch_opened_wait_queue);
+
+		mutex_init(&smd_pkt_devp[i]->ch_lock);
+		mutex_init(&smd_pkt_devp[i]->rx_lock);
+		mutex_init(&smd_pkt_devp[i]->tx_lock);
+
+		cdev_init(&smd_pkt_devp[i]->cdev, &smd_pkt_fops);
+		smd_pkt_devp[i]->cdev.owner = THIS_MODULE;
+
+		r = cdev_add(&smd_pkt_devp[i]->cdev,
+			     (smd_pkt_number + i), 1);
+		if (r) {
+			pr_err("cdev_add() failed %d\n", r);
+			kfree(smd_pkt_devp[i]);
+			goto clean_cdevs;
+		}
+
+		smd_pkt_devp[i]->devicep =
+			device_create(smd_pkt_classp, NULL,
+				      (smd_pkt_number + i), NULL,
+				      smd_pkt_dev_name[i]);
+		if (IS_ERR(smd_pkt_devp[i]->devicep)) {
+			r = PTR_ERR(smd_pkt_devp[i]->devicep);
+			pr_err("device_create() failed %d\n", r);
+			cdev_del(&smd_pkt_devp[i]->cdev);
+			kfree(smd_pkt_devp[i]);
+			goto clean_cdevs;
+		}
+
+	}
+
+	pr_info("SMD Packet Port Driver Initialized.\n");
+	return 0;
+
+clean_cdevs:
+	if (i > 0) {
+		while (--i >= 0) {
+			mutex_destroy(&smd_pkt_devp[i]->ch_lock);
+			mutex_destroy(&smd_pkt_devp[i]->rx_lock);
+			mutex_destroy(&smd_pkt_devp[i]->tx_lock);
+			cdev_del(&smd_pkt_devp[i]->cdev);
+			kfree(smd_pkt_devp[i]);
+			device_destroy(smd_pkt_classp,
+				       MKDEV(MAJOR(smd_pkt_number), i));
+		}
+	}
+
+	class_destroy(smd_pkt_classp);
+unreg_chardev:
+	unregister_chrdev_region(MAJOR(smd_pkt_number), NUM_SMD_PKT_PORTS);
+	return r;
+}
+module_init(smd_pkt_init);
+
+static void __exit smd_pkt_cleanup(void)
+{
+	int i;
+
+	for (i = 0; i < NUM_SMD_PKT_PORTS; ++i) {
+		mutex_destroy(&smd_pkt_devp[i]->ch_lock);
+		mutex_destroy(&smd_pkt_devp[i]->rx_lock);
+		mutex_destroy(&smd_pkt_devp[i]->tx_lock);
+		cdev_del(&smd_pkt_devp[i]->cdev);
+		kfree(smd_pkt_devp[i]);
+		device_destroy(smd_pkt_classp,
+			       MKDEV(MAJOR(smd_pkt_number), i));
+	}
+
+	class_destroy(smd_pkt_classp);
+	unregister_chrdev_region(MAJOR(smd_pkt_number), NUM_SMD_PKT_PORTS);
+}
+module_exit(smd_pkt_cleanup);
+
+MODULE_DESCRIPTION("MSM Shared Memory Packet Port");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/char/mwave/3780i.h linux-libre-2.6.39-gnu/drivers/char/mwave/3780i.h
--- linux-libre-2.6.38-gnu/drivers/char/mwave/3780i.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mwave/3780i.h	2011-05-19 00:06:34.000000000 -0400
@@ -122,7 +122,7 @@
 typedef struct {
 	unsigned char Dma:3;	/* RW: DMA channel selection */
 	unsigned char NumTransfers:2;	/* RW: Maximum # of transfers once being granted the ISA bus */
-	unsigned char ReRequest:2;	/* RW: Minumum delay between releasing the ISA bus and requesting it again */
+	unsigned char ReRequest:2;	/* RW: Minimum delay between releasing the ISA bus and requesting it again */
 	unsigned char MEMCS16:1;	/* RW: ISA signal MEMCS16: 0=disabled, 1=enabled */
 } DSP_BUSMASTER_CFG_1;
 
diff -druN linux-libre-2.6.38-gnu/drivers/char/mwave/Makefile linux-libre-2.6.39-gnu/drivers/char/mwave/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/mwave/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mwave/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
 mwave-y := mwavedd.o smapi.o tp3780i.o 3780i.o
 
 # To have the mwave driver disable other uarts if necessary
-# EXTRA_CFLAGS += -DMWAVE_FUTZ_WITH_OTHER_DEVICES
+# ccflags-y := -DMWAVE_FUTZ_WITH_OTHER_DEVICES
 
 # To compile in lots (~20 KiB) of run-time enablable printk()s for debugging:
-ccflags-y := -DMW_TRACE
+ccflags-y += -DMW_TRACE
diff -druN linux-libre-2.6.38-gnu/drivers/char/mwave/README linux-libre-2.6.39-gnu/drivers/char/mwave/README
--- linux-libre-2.6.38-gnu/drivers/char/mwave/README	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mwave/README	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 	0x0008 tp3780i tracing
 
         Tracing only occurs if the driver has been compiled with the
-        MW_TRACE macro #defined  (i.e. let EXTRA_CFLAGS += -DMW_TRACE
+        MW_TRACE macro #defined  (i.e. let ccflags-y := -DMW_TRACE
         in the Makefile).
 
   mwave_3780i_irq=5/7/10/11/15
diff -druN linux-libre-2.6.38-gnu/drivers/char/mxser.c linux-libre-2.6.39-gnu/drivers/char/mxser.c
--- linux-libre-2.6.38-gnu/drivers/char/mxser.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mxser.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2757 +0,0 @@
-/*
- *          mxser.c  -- MOXA Smartio/Industio family multiport serial driver.
- *
- *      Copyright (C) 1999-2006  Moxa Technologies (support@moxa.com).
- *	Copyright (C) 2006-2008  Jiri Slaby <jirislaby@gmail.com>
- *
- *      This code is loosely based on the 1.8 moxa driver which is based on
- *	Linux serial driver, written by Linus Torvalds, Theodore T'so and
- *	others.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the GNU General Public License as published by
- *      the Free Software Foundation; either version 2 of the License, or
- *      (at your option) any later version.
- *
- *	Fed through a cleanup, indent and remove of non 2.6 code by Alan Cox
- *	<alan@lxorguk.ukuu.org.uk>. The original 1.8 code is available on
- *	www.moxa.com.
- *	- Fixed x86_64 cleanness
- */
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/serial_reg.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/uaccess.h>
-
-#include "mxser.h"
-
-#define	MXSER_VERSION	"2.0.5"		/* 1.14 */
-#define	MXSERMAJOR	 174
-
-#define MXSER_BOARDS		4	/* Max. boards */
-#define MXSER_PORTS_PER_BOARD	8	/* Max. ports per board */
-#define MXSER_PORTS		(MXSER_BOARDS * MXSER_PORTS_PER_BOARD)
-#define MXSER_ISR_PASS_LIMIT	100
-
-/*CheckIsMoxaMust return value*/
-#define MOXA_OTHER_UART		0x00
-#define MOXA_MUST_MU150_HWID	0x01
-#define MOXA_MUST_MU860_HWID	0x02
-
-#define WAKEUP_CHARS		256
-
-#define UART_MCR_AFE		0x20
-#define UART_LSR_SPECIAL	0x1E
-
-#define PCI_DEVICE_ID_POS104UL	0x1044
-#define PCI_DEVICE_ID_CB108	0x1080
-#define PCI_DEVICE_ID_CP102UF	0x1023
-#define PCI_DEVICE_ID_CP112UL	0x1120
-#define PCI_DEVICE_ID_CB114	0x1142
-#define PCI_DEVICE_ID_CP114UL	0x1143
-#define PCI_DEVICE_ID_CB134I	0x1341
-#define PCI_DEVICE_ID_CP138U	0x1380
-
-
-#define C168_ASIC_ID    1
-#define C104_ASIC_ID    2
-#define C102_ASIC_ID	0xB
-#define CI132_ASIC_ID	4
-#define CI134_ASIC_ID	3
-#define CI104J_ASIC_ID  5
-
-#define MXSER_HIGHBAUD	1
-#define MXSER_HAS2	2
-
-/* This is only for PCI */
-static const struct {
-	int type;
-	int tx_fifo;
-	int rx_fifo;
-	int xmit_fifo_size;
-	int rx_high_water;
-	int rx_trigger;
-	int rx_low_water;
-	long max_baud;
-} Gpci_uart_info[] = {
-	{MOXA_OTHER_UART, 16, 16, 16, 14, 14, 1, 921600L},
-	{MOXA_MUST_MU150_HWID, 64, 64, 64, 48, 48, 16, 230400L},
-	{MOXA_MUST_MU860_HWID, 128, 128, 128, 96, 96, 32, 921600L}
-};
-#define UART_INFO_NUM	ARRAY_SIZE(Gpci_uart_info)
-
-struct mxser_cardinfo {
-	char *name;
-	unsigned int nports;
-	unsigned int flags;
-};
-
-static const struct mxser_cardinfo mxser_cards[] = {
-/* 0*/	{ "C168 series",	8, },
-	{ "C104 series",	4, },
-	{ "CI-104J series",	4, },
-	{ "C168H/PCI series",	8, },
-	{ "C104H/PCI series",	4, },
-/* 5*/	{ "C102 series",	4, MXSER_HAS2 },	/* C102-ISA */
-	{ "CI-132 series",	4, MXSER_HAS2 },
-	{ "CI-134 series",	4, },
-	{ "CP-132 series",	2, },
-	{ "CP-114 series",	4, },
-/*10*/	{ "CT-114 series",	4, },
-	{ "CP-102 series",	2, MXSER_HIGHBAUD },
-	{ "CP-104U series",	4, },
-	{ "CP-168U series",	8, },
-	{ "CP-132U series",	2, },
-/*15*/	{ "CP-134U series",	4, },
-	{ "CP-104JU series",	4, },
-	{ "Moxa UC7000 Serial",	8, },		/* RC7000 */
-	{ "CP-118U series",	8, },
-	{ "CP-102UL series",	2, },
-/*20*/	{ "CP-102U series",	2, },
-	{ "CP-118EL series",	8, },
-	{ "CP-168EL series",	8, },
-	{ "CP-104EL series",	4, },
-	{ "CB-108 series",	8, },
-/*25*/	{ "CB-114 series",	4, },
-	{ "CB-134I series",	4, },
-	{ "CP-138U series",	8, },
-	{ "POS-104UL series",	4, },
-	{ "CP-114UL series",	4, },
-/*30*/	{ "CP-102UF series",	2, },
-	{ "CP-112UL series",	2, },
-};
-
-/* driver_data correspond to the lines in the structure above
-   see also ISA probe function before you change something */
-static struct pci_device_id mxser_pcibrds[] = {
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C168),	.driver_data = 3 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_C104),	.driver_data = 4 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132),	.driver_data = 8 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP114),	.driver_data = 9 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CT114),	.driver_data = 10 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102),	.driver_data = 11 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104U),	.driver_data = 12 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168U),	.driver_data = 13 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP132U),	.driver_data = 14 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP134U),	.driver_data = 15 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104JU),.driver_data = 16 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_RC7000),	.driver_data = 17 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118U),	.driver_data = 18 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102UL),.driver_data = 19 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP102U),	.driver_data = 20 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP118EL),.driver_data = 21 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP168EL),.driver_data = 22 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_MOXA_CP104EL),.driver_data = 23 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB108),	.driver_data = 24 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB114),	.driver_data = 25 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CB134I),	.driver_data = 26 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP138U),	.driver_data = 27 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL),	.driver_data = 28 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL),	.driver_data = 29 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF),	.driver_data = 30 },
-	{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL),	.driver_data = 31 },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
-
-static unsigned long ioaddr[MXSER_BOARDS];
-static int ttymajor = MXSERMAJOR;
-
-/* Variables for insmod */
-
-MODULE_AUTHOR("Casper Yang");
-MODULE_DESCRIPTION("MOXA Smartio/Industio Family Multiport Board Device Driver");
-module_param_array(ioaddr, ulong, NULL, 0);
-MODULE_PARM_DESC(ioaddr, "ISA io addresses to look for a moxa board");
-module_param(ttymajor, int, 0);
-MODULE_LICENSE("GPL");
-
-struct mxser_log {
-	int tick;
-	unsigned long rxcnt[MXSER_PORTS];
-	unsigned long txcnt[MXSER_PORTS];
-};
-
-struct mxser_mon {
-	unsigned long rxcnt;
-	unsigned long txcnt;
-	unsigned long up_rxcnt;
-	unsigned long up_txcnt;
-	int modem_status;
-	unsigned char hold_reason;
-};
-
-struct mxser_mon_ext {
-	unsigned long rx_cnt[32];
-	unsigned long tx_cnt[32];
-	unsigned long up_rxcnt[32];
-	unsigned long up_txcnt[32];
-	int modem_status[32];
-
-	long baudrate[32];
-	int databits[32];
-	int stopbits[32];
-	int parity[32];
-	int flowctrl[32];
-	int fifo[32];
-	int iftype[32];
-};
-
-struct mxser_board;
-
-struct mxser_port {
-	struct tty_port port;
-	struct mxser_board *board;
-
-	unsigned long ioaddr;
-	unsigned long opmode_ioaddr;
-	int max_baud;
-
-	int rx_high_water;
-	int rx_trigger;		/* Rx fifo trigger level */
-	int rx_low_water;
-	int baud_base;		/* max. speed */
-	int type;		/* UART type */
-
-	int x_char;		/* xon/xoff character */
-	int IER;		/* Interrupt Enable Register */
-	int MCR;		/* Modem control register */
-
-	unsigned char stop_rx;
-	unsigned char ldisc_stop_rx;
-
-	int custom_divisor;
-	unsigned char err_shadow;
-
-	struct async_icount icount; /* kernel counters for 4 input interrupts */
-	int timeout;
-
-	int read_status_mask;
-	int ignore_status_mask;
-	int xmit_fifo_size;
-	int xmit_head;
-	int xmit_tail;
-	int xmit_cnt;
-
-	struct ktermios normal_termios;
-
-	struct mxser_mon mon_data;
-
-	spinlock_t slock;
-};
-
-struct mxser_board {
-	unsigned int idx;
-	int irq;
-	const struct mxser_cardinfo *info;
-	unsigned long vector;
-	unsigned long vector_mask;
-
-	int chip_flag;
-	int uart_type;
-
-	struct mxser_port ports[MXSER_PORTS_PER_BOARD];
-};
-
-struct mxser_mstatus {
-	tcflag_t cflag;
-	int cts;
-	int dsr;
-	int ri;
-	int dcd;
-};
-
-static struct mxser_board mxser_boards[MXSER_BOARDS];
-static struct tty_driver *mxvar_sdriver;
-static struct mxser_log mxvar_log;
-static int mxser_set_baud_method[MXSER_PORTS + 1];
-
-static void mxser_enable_must_enchance_mode(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr |= MOXA_MUST_EFR_EFRB_ENABLE;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-#ifdef	CONFIG_PCI
-static void mxser_disable_must_enchance_mode(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_EFRB_ENABLE;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-#endif
-
-static void mxser_set_must_xon1_value(unsigned long baseio, u8 value)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK0;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(value, baseio + MOXA_MUST_XON1_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_set_must_xoff1_value(unsigned long baseio, u8 value)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK0;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(value, baseio + MOXA_MUST_XOFF1_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_set_must_fifo_value(struct mxser_port *info)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(info->ioaddr + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, info->ioaddr + UART_LCR);
-
-	efr = inb(info->ioaddr + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK1;
-
-	outb(efr, info->ioaddr + MOXA_MUST_EFR_REGISTER);
-	outb((u8)info->rx_high_water, info->ioaddr + MOXA_MUST_RBRTH_REGISTER);
-	outb((u8)info->rx_trigger, info->ioaddr + MOXA_MUST_RBRTI_REGISTER);
-	outb((u8)info->rx_low_water, info->ioaddr + MOXA_MUST_RBRTL_REGISTER);
-	outb(oldlcr, info->ioaddr + UART_LCR);
-}
-
-static void mxser_set_must_enum_value(unsigned long baseio, u8 value)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK2;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(value, baseio + MOXA_MUST_ENUM_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-#ifdef CONFIG_PCI
-static void mxser_get_must_hardware_id(unsigned long baseio, u8 *pId)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_BANK_MASK;
-	efr |= MOXA_MUST_EFR_BANK2;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	*pId = inb(baseio + MOXA_MUST_HWID_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-#endif
-
-static void SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_MASK;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_enable_must_tx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
-	efr |= MOXA_MUST_EFR_SF_TX1;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_disable_must_tx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_TX_MASK;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_enable_must_rx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
-	efr |= MOXA_MUST_EFR_SF_RX1;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-static void mxser_disable_must_rx_software_flow_control(unsigned long baseio)
-{
-	u8 oldlcr;
-	u8 efr;
-
-	oldlcr = inb(baseio + UART_LCR);
-	outb(MOXA_MUST_ENTER_ENCHANCE, baseio + UART_LCR);
-
-	efr = inb(baseio + MOXA_MUST_EFR_REGISTER);
-	efr &= ~MOXA_MUST_EFR_SF_RX_MASK;
-
-	outb(efr, baseio + MOXA_MUST_EFR_REGISTER);
-	outb(oldlcr, baseio + UART_LCR);
-}
-
-#ifdef CONFIG_PCI
-static int __devinit CheckIsMoxaMust(unsigned long io)
-{
-	u8 oldmcr, hwid;
-	int i;
-
-	outb(0, io + UART_LCR);
-	mxser_disable_must_enchance_mode(io);
-	oldmcr = inb(io + UART_MCR);
-	outb(0, io + UART_MCR);
-	mxser_set_must_xon1_value(io, 0x11);
-	if ((hwid = inb(io + UART_MCR)) != 0) {
-		outb(oldmcr, io + UART_MCR);
-		return MOXA_OTHER_UART;
-	}
-
-	mxser_get_must_hardware_id(io, &hwid);
-	for (i = 1; i < UART_INFO_NUM; i++) { /* 0 = OTHER_UART */
-		if (hwid == Gpci_uart_info[i].type)
-			return (int)hwid;
-	}
-	return MOXA_OTHER_UART;
-}
-#endif
-
-static void process_txrx_fifo(struct mxser_port *info)
-{
-	int i;
-
-	if ((info->type == PORT_16450) || (info->type == PORT_8250)) {
-		info->rx_trigger = 1;
-		info->rx_high_water = 1;
-		info->rx_low_water = 1;
-		info->xmit_fifo_size = 1;
-	} else
-		for (i = 0; i < UART_INFO_NUM; i++)
-			if (info->board->chip_flag == Gpci_uart_info[i].type) {
-				info->rx_trigger = Gpci_uart_info[i].rx_trigger;
-				info->rx_low_water = Gpci_uart_info[i].rx_low_water;
-				info->rx_high_water = Gpci_uart_info[i].rx_high_water;
-				info->xmit_fifo_size = Gpci_uart_info[i].xmit_fifo_size;
-				break;
-			}
-}
-
-static unsigned char mxser_get_msr(int baseaddr, int mode, int port)
-{
-	static unsigned char mxser_msr[MXSER_PORTS + 1];
-	unsigned char status = 0;
-
-	status = inb(baseaddr + UART_MSR);
-
-	mxser_msr[port] &= 0x0F;
-	mxser_msr[port] |= status;
-	status = mxser_msr[port];
-	if (mode)
-		mxser_msr[port] = 0;
-
-	return status;
-}
-
-static int mxser_carrier_raised(struct tty_port *port)
-{
-	struct mxser_port *mp = container_of(port, struct mxser_port, port);
-	return (inb(mp->ioaddr + UART_MSR) & UART_MSR_DCD)?1:0;
-}
-
-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);
-	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);
-}
-
-static int mxser_set_baud(struct tty_struct *tty, long newspd)
-{
-	struct mxser_port *info = tty->driver_data;
-	int quot = 0, baud;
-	unsigned char cval;
-
-	if (!info->ioaddr)
-		return -1;
-
-	if (newspd > info->max_baud)
-		return -1;
-
-	if (newspd == 134) {
-		quot = 2 * info->baud_base / 269;
-		tty_encode_baud_rate(tty, 134, 134);
-	} else if (newspd) {
-		quot = info->baud_base / newspd;
-		if (quot == 0)
-			quot = 1;
-		baud = info->baud_base/quot;
-		tty_encode_baud_rate(tty, baud, baud);
-	} else {
-		quot = 0;
-	}
-
-	info->timeout = ((info->xmit_fifo_size * HZ * 10 * quot) / info->baud_base);
-	info->timeout += HZ / 50;	/* Add .02 seconds of slop */
-
-	if (quot) {
-		info->MCR |= UART_MCR_DTR;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-	} else {
-		info->MCR &= ~UART_MCR_DTR;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-		return 0;
-	}
-
-	cval = inb(info->ioaddr + UART_LCR);
-
-	outb(cval | UART_LCR_DLAB, info->ioaddr + UART_LCR);	/* set DLAB */
-
-	outb(quot & 0xff, info->ioaddr + UART_DLL);	/* LS of divisor */
-	outb(quot >> 8, info->ioaddr + UART_DLM);	/* MS of divisor */
-	outb(cval, info->ioaddr + UART_LCR);	/* reset DLAB */
-
-#ifdef BOTHER
-	if (C_BAUD(tty) == BOTHER) {
-		quot = info->baud_base % newspd;
-		quot *= 8;
-		if (quot % newspd > newspd / 2) {
-			quot /= newspd;
-			quot++;
-		} else
-			quot /= newspd;
-
-		mxser_set_must_enum_value(info->ioaddr, quot);
-	} else
-#endif
-		mxser_set_must_enum_value(info->ioaddr, 0);
-
-	return 0;
-}
-
-/*
- * This routine is called to set the UART divisor registers to match
- * the specified baud rate for a serial port.
- */
-static int mxser_change_speed(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned cflag, cval, fcr;
-	int ret = 0;
-	unsigned char status;
-
-	cflag = tty->termios->c_cflag;
-	if (!info->ioaddr)
-		return ret;
-
-	if (mxser_set_baud_method[tty->index] == 0)
-		mxser_set_baud(tty, tty_get_baud_rate(tty));
-
-	/* byte size and parity */
-	switch (cflag & CSIZE) {
-	case CS5:
-		cval = 0x00;
-		break;
-	case CS6:
-		cval = 0x01;
-		break;
-	case CS7:
-		cval = 0x02;
-		break;
-	case CS8:
-		cval = 0x03;
-		break;
-	default:
-		cval = 0x00;
-		break;		/* too keep GCC shut... */
-	}
-	if (cflag & CSTOPB)
-		cval |= 0x04;
-	if (cflag & PARENB)
-		cval |= UART_LCR_PARITY;
-	if (!(cflag & PARODD))
-		cval |= UART_LCR_EPAR;
-	if (cflag & CMSPAR)
-		cval |= UART_LCR_SPAR;
-
-	if ((info->type == PORT_8250) || (info->type == PORT_16450)) {
-		if (info->board->chip_flag) {
-			fcr = UART_FCR_ENABLE_FIFO;
-			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
-			mxser_set_must_fifo_value(info);
-		} else
-			fcr = 0;
-	} else {
-		fcr = UART_FCR_ENABLE_FIFO;
-		if (info->board->chip_flag) {
-			fcr |= MOXA_MUST_FCR_GDA_MODE_ENABLE;
-			mxser_set_must_fifo_value(info);
-		} else {
-			switch (info->rx_trigger) {
-			case 1:
-				fcr |= UART_FCR_TRIGGER_1;
-				break;
-			case 4:
-				fcr |= UART_FCR_TRIGGER_4;
-				break;
-			case 8:
-				fcr |= UART_FCR_TRIGGER_8;
-				break;
-			default:
-				fcr |= UART_FCR_TRIGGER_14;
-				break;
-			}
-		}
-	}
-
-	/* CTS flow control flag and modem status interrupts */
-	info->IER &= ~UART_IER_MSI;
-	info->MCR &= ~UART_MCR_AFE;
-	if (cflag & CRTSCTS) {
-		info->port.flags |= ASYNC_CTS_FLOW;
-		info->IER |= UART_IER_MSI;
-		if ((info->type == PORT_16550A) || (info->board->chip_flag)) {
-			info->MCR |= UART_MCR_AFE;
-		} else {
-			status = inb(info->ioaddr + UART_MSR);
-			if (tty->hw_stopped) {
-				if (status & UART_MSR_CTS) {
-					tty->hw_stopped = 0;
-					if (info->type != PORT_16550A &&
-							!info->board->chip_flag) {
-						outb(info->IER & ~UART_IER_THRI,
-							info->ioaddr +
-							UART_IER);
-						info->IER |= UART_IER_THRI;
-						outb(info->IER, info->ioaddr +
-								UART_IER);
-					}
-					tty_wakeup(tty);
-				}
-			} else {
-				if (!(status & UART_MSR_CTS)) {
-					tty->hw_stopped = 1;
-					if ((info->type != PORT_16550A) &&
-							(!info->board->chip_flag)) {
-						info->IER &= ~UART_IER_THRI;
-						outb(info->IER, info->ioaddr +
-								UART_IER);
-					}
-				}
-			}
-		}
-	} else {
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-	}
-	outb(info->MCR, info->ioaddr + UART_MCR);
-	if (cflag & CLOCAL) {
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	} else {
-		info->port.flags |= ASYNC_CHECK_CD;
-		info->IER |= UART_IER_MSI;
-	}
-	outb(info->IER, info->ioaddr + UART_IER);
-
-	/*
-	 * Set up parity check flag
-	 */
-	info->read_status_mask = UART_LSR_OE | UART_LSR_THRE | UART_LSR_DR;
-	if (I_INPCK(tty))
-		info->read_status_mask |= UART_LSR_FE | UART_LSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		info->read_status_mask |= UART_LSR_BI;
-
-	info->ignore_status_mask = 0;
-
-	if (I_IGNBRK(tty)) {
-		info->ignore_status_mask |= UART_LSR_BI;
-		info->read_status_mask |= UART_LSR_BI;
-		/*
-		 * If we're ignore parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(tty)) {
-			info->ignore_status_mask |=
-						UART_LSR_OE |
-						UART_LSR_PE |
-						UART_LSR_FE;
-			info->read_status_mask |=
-						UART_LSR_OE |
-						UART_LSR_PE |
-						UART_LSR_FE;
-		}
-	}
-	if (info->board->chip_flag) {
-		mxser_set_must_xon1_value(info->ioaddr, START_CHAR(tty));
-		mxser_set_must_xoff1_value(info->ioaddr, STOP_CHAR(tty));
-		if (I_IXON(tty)) {
-			mxser_enable_must_rx_software_flow_control(
-					info->ioaddr);
-		} else {
-			mxser_disable_must_rx_software_flow_control(
-					info->ioaddr);
-		}
-		if (I_IXOFF(tty)) {
-			mxser_enable_must_tx_software_flow_control(
-					info->ioaddr);
-		} else {
-			mxser_disable_must_tx_software_flow_control(
-					info->ioaddr);
-		}
-	}
-
-
-	outb(fcr, info->ioaddr + UART_FCR);	/* set fcr */
-	outb(cval, info->ioaddr + UART_LCR);
-
-	return ret;
-}
-
-static void mxser_check_modem_status(struct tty_struct *tty,
-				struct mxser_port *port, int status)
-{
-	/* update input line counters */
-	if (status & UART_MSR_TERI)
-		port->icount.rng++;
-	if (status & UART_MSR_DDSR)
-		port->icount.dsr++;
-	if (status & UART_MSR_DDCD)
-		port->icount.dcd++;
-	if (status & UART_MSR_DCTS)
-		port->icount.cts++;
-	port->mon_data.modem_status = status;
-	wake_up_interruptible(&port->port.delta_msr_wait);
-
-	if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
-		if (status & UART_MSR_DCD)
-			wake_up_interruptible(&port->port.open_wait);
-	}
-
-	if (port->port.flags & ASYNC_CTS_FLOW) {
-		if (tty->hw_stopped) {
-			if (status & UART_MSR_CTS) {
-				tty->hw_stopped = 0;
-
-				if ((port->type != PORT_16550A) &&
-						(!port->board->chip_flag)) {
-					outb(port->IER & ~UART_IER_THRI,
-						port->ioaddr + UART_IER);
-					port->IER |= UART_IER_THRI;
-					outb(port->IER, port->ioaddr +
-							UART_IER);
-				}
-				tty_wakeup(tty);
-			}
-		} else {
-			if (!(status & UART_MSR_CTS)) {
-				tty->hw_stopped = 1;
-				if (port->type != PORT_16550A &&
-						!port->board->chip_flag) {
-					port->IER &= ~UART_IER_THRI;
-					outb(port->IER, port->ioaddr +
-							UART_IER);
-				}
-			}
-		}
-	}
-}
-
-static int mxser_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct mxser_port *info = container_of(port, struct mxser_port, port);
-	unsigned long page;
-	unsigned long flags;
-
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	if (!info->ioaddr || !info->type) {
-		set_bit(TTY_IO_ERROR, &tty->flags);
-		free_page(page);
-		spin_unlock_irqrestore(&info->slock, flags);
-		return 0;
-	}
-	info->port.xmit_buf = (unsigned char *) page;
-
-	/*
-	 * Clear the FIFO buffers and disable them
-	 * (they will be reenabled in mxser_change_speed())
-	 */
-	if (info->board->chip_flag)
-		outb((UART_FCR_CLEAR_RCVR |
-			UART_FCR_CLEAR_XMIT |
-			MOXA_MUST_FCR_GDA_MODE_ENABLE), info->ioaddr + UART_FCR);
-	else
-		outb((UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
-			info->ioaddr + UART_FCR);
-
-	/*
-	 * At this point there's no way the LSR could still be 0xFF;
-	 * if it is, then bail out, because there's likely no UART
-	 * here.
-	 */
-	if (inb(info->ioaddr + UART_LSR) == 0xff) {
-		spin_unlock_irqrestore(&info->slock, flags);
-		if (capable(CAP_SYS_ADMIN)) {
-			set_bit(TTY_IO_ERROR, &tty->flags);
-			return 0;
-		} else
-			return -ENODEV;
-	}
-
-	/*
-	 * Clear the interrupt registers.
-	 */
-	(void) inb(info->ioaddr + UART_LSR);
-	(void) inb(info->ioaddr + UART_RX);
-	(void) inb(info->ioaddr + UART_IIR);
-	(void) inb(info->ioaddr + UART_MSR);
-
-	/*
-	 * Now, initialize the UART
-	 */
-	outb(UART_LCR_WLEN8, info->ioaddr + UART_LCR);	/* reset DLAB */
-	info->MCR = UART_MCR_DTR | UART_MCR_RTS;
-	outb(info->MCR, info->ioaddr + UART_MCR);
-
-	/*
-	 * Finally, enable interrupts
-	 */
-	info->IER = UART_IER_MSI | UART_IER_RLSI | UART_IER_RDI;
-
-	if (info->board->chip_flag)
-		info->IER |= MOXA_MUST_IER_EGDAI;
-	outb(info->IER, info->ioaddr + UART_IER);	/* enable interrupts */
-
-	/*
-	 * And clear the interrupt registers again for luck.
-	 */
-	(void) inb(info->ioaddr + UART_LSR);
-	(void) inb(info->ioaddr + UART_RX);
-	(void) inb(info->ioaddr + UART_IIR);
-	(void) inb(info->ioaddr + UART_MSR);
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	/*
-	 * and set the speed of the serial port
-	 */
-	mxser_change_speed(tty, NULL);
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	return 0;
-}
-
-/*
- * This routine will shutdown a serial port
- */
-static void mxser_shutdown_port(struct tty_port *port)
-{
-	struct mxser_port *info = container_of(port, struct mxser_port, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	/*
-	 * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
-	 * here so the queue might never be waken up
-	 */
-	wake_up_interruptible(&info->port.delta_msr_wait);
-
-	/*
-	 * Free the xmit buffer, if necessary
-	 */
-	if (info->port.xmit_buf) {
-		free_page((unsigned long) info->port.xmit_buf);
-		info->port.xmit_buf = NULL;
-	}
-
-	info->IER = 0;
-	outb(0x00, info->ioaddr + UART_IER);
-
-	/* clear Rx/Tx FIFO's */
-	if (info->board->chip_flag)
-		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT |
-				MOXA_MUST_FCR_GDA_MODE_ENABLE,
-				info->ioaddr + UART_FCR);
-	else
-		outb(UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT,
-			info->ioaddr + UART_FCR);
-
-	/* read data port to reset things */
-	(void) inb(info->ioaddr + UART_RX);
-
-
-	if (info->board->chip_flag)
-		SET_MOXA_MUST_NO_SOFTWARE_FLOW_CONTROL(info->ioaddr);
-
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * enables interrupts for a serial port, linking in its async structure into
- * the IRQ chain.   It also performs the serial-specific
- * initialization for the tty structure.
- */
-static int mxser_open(struct tty_struct *tty, struct file *filp)
-{
-	struct mxser_port *info;
-	int line;
-
-	line = tty->index;
-	if (line == MXSER_PORTS)
-		return 0;
-	if (line < 0 || line > MXSER_PORTS)
-		return -ENODEV;
-	info = &mxser_boards[line / MXSER_PORTS_PER_BOARD].ports[line % MXSER_PORTS_PER_BOARD];
-	if (!info->ioaddr)
-		return -ENODEV;
-
-	tty->driver_data = info;
-	return tty_port_open(&info->port, tty, filp);
-}
-
-static void mxser_flush_buffer(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	char fcr;
-	unsigned long flags;
-
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	fcr = inb(info->ioaddr + UART_FCR);
-	outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
-		info->ioaddr + UART_FCR);
-	outb(fcr, info->ioaddr + UART_FCR);
-
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	tty_wakeup(tty);
-}
-
-
-static void mxser_close_port(struct tty_port *port)
-{
-	struct mxser_port *info = container_of(port, struct mxser_port, port);
-	unsigned long timeout;
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	info->IER &= ~UART_IER_RLSI;
-	if (info->board->chip_flag)
-		info->IER &= ~MOXA_MUST_RECV_ISR;
-
-	outb(info->IER, info->ioaddr + UART_IER);
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = jiffies + HZ;
-	while (!(inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT)) {
-		schedule_timeout_interruptible(5);
-		if (time_after(jiffies, timeout))
-			break;
-	}
-}
-
-/*
- * This routine is called when the serial port gets closed.  First, we
- * wait for the last remaining data to be sent.  Then, we unlink its
- * async structure from the interrupt chain if necessary, and we free
- * that IRQ if nothing is left in the chain.
- */
-static void mxser_close(struct tty_struct *tty, struct file *filp)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-
-	if (tty->index == MXSER_PORTS || info == NULL)
-		return;
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-	mutex_lock(&port->mutex);
-	mxser_close_port(port);
-	mxser_flush_buffer(tty);
-	mxser_shutdown_port(port);
-	clear_bit(ASYNCB_INITIALIZED, &port->flags);
-	mutex_unlock(&port->mutex);
-	/* Right now the tty_port set is done outside of the close_end helper
-	   as we don't yet have everyone using refcounts */	
-	tty_port_close_end(port, tty);
-	tty_port_tty_set(port, NULL);
-}
-
-static int mxser_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	int c, total = 0;
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	while (1) {
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0)
-			break;
-
-		memcpy(info->port.xmit_buf + info->xmit_head, buf, c);
-		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_head = (info->xmit_head + c) &
-				  (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (info->xmit_cnt && !tty->stopped) {
-		if (!tty->hw_stopped ||
-				(info->type == PORT_16550A) ||
-				(info->board->chip_flag)) {
-			spin_lock_irqsave(&info->slock, flags);
-			outb(info->IER & ~UART_IER_THRI, info->ioaddr +
-					UART_IER);
-			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->ioaddr + UART_IER);
-			spin_unlock_irqrestore(&info->slock, flags);
-		}
-	}
-	return total;
-}
-
-static int mxser_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (!info->port.xmit_buf)
-		return 0;
-
-	if (info->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
-		return 0;
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->port.xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	info->xmit_cnt++;
-	spin_unlock_irqrestore(&info->slock, flags);
-	if (!tty->stopped) {
-		if (!tty->hw_stopped ||
-				(info->type == PORT_16550A) ||
-				info->board->chip_flag) {
-			spin_lock_irqsave(&info->slock, flags);
-			outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
-			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->ioaddr + UART_IER);
-			spin_unlock_irqrestore(&info->slock, flags);
-		}
-	}
-	return 1;
-}
-
-
-static void mxser_flush_chars(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || !info->port.xmit_buf ||
-			(tty->hw_stopped && info->type != PORT_16550A &&
-			 !info->board->chip_flag))
-		return;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
-	info->IER |= UART_IER_THRI;
-	outb(info->IER, info->ioaddr + UART_IER);
-
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static int mxser_write_room(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	int ret;
-
-	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-	return ret < 0 ? 0 : ret;
-}
-
-static int mxser_chars_in_buffer(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	return info->xmit_cnt;
-}
-
-/*
- * ------------------------------------------------------------
- * friends of mxser_ioctl()
- * ------------------------------------------------------------
- */
-static int mxser_get_serial_info(struct tty_struct *tty,
-		struct serial_struct __user *retinfo)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct serial_struct tmp = {
-		.type = info->type,
-		.line = tty->index,
-		.port = info->ioaddr,
-		.irq = info->board->irq,
-		.flags = info->port.flags,
-		.baud_base = info->baud_base,
-		.close_delay = info->port.close_delay,
-		.closing_wait = info->port.closing_wait,
-		.custom_divisor = info->custom_divisor,
-		.hub6 = 0
-	};
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int mxser_set_serial_info(struct tty_struct *tty,
-		struct serial_struct __user *new_info)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-	struct serial_struct new_serial;
-	speed_t baud;
-	unsigned long sl_flags;
-	unsigned int flags;
-	int retval = 0;
-
-	if (!new_info || !info->ioaddr)
-		return -ENODEV;
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-
-	if (new_serial.irq != info->board->irq ||
-			new_serial.port != info->ioaddr)
-		return -EINVAL;
-
-	flags = port->flags & ASYNC_SPD_MASK;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.baud_base != info->baud_base) ||
-				(new_serial.close_delay != info->port.close_delay) ||
-				((new_serial.flags & ~ASYNC_USR_MASK) != (info->port.flags & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		info->port.flags = ((info->port.flags & ~ASYNC_USR_MASK) |
-				(new_serial.flags & ASYNC_USR_MASK));
-	} else {
-		/*
-		 * OK, past this point, all the error checking has been done.
-		 * At this point, we start making changes.....
-		 */
-		port->flags = ((port->flags & ~ASYNC_FLAGS) |
-				(new_serial.flags & ASYNC_FLAGS));
-		port->close_delay = new_serial.close_delay * HZ / 100;
-		port->closing_wait = new_serial.closing_wait * HZ / 100;
-		tty->low_latency = (port->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-		if ((port->flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST &&
-				(new_serial.baud_base != info->baud_base ||
-				new_serial.custom_divisor !=
-				info->custom_divisor)) {
-			if (new_serial.custom_divisor == 0)
-				return -EINVAL;
-			baud = new_serial.baud_base / new_serial.custom_divisor;
-			tty_encode_baud_rate(tty, baud, baud);
-		}
-	}
-
-	info->type = new_serial.type;
-
-	process_txrx_fifo(info);
-
-	if (test_bit(ASYNCB_INITIALIZED, &port->flags)) {
-		if (flags != (port->flags & ASYNC_SPD_MASK)) {
-			spin_lock_irqsave(&info->slock, sl_flags);
-			mxser_change_speed(tty, NULL);
-			spin_unlock_irqrestore(&info->slock, sl_flags);
-		}
-	} else {
-		retval = mxser_activate(port, tty);
-		if (retval == 0)
-			set_bit(ASYNCB_INITIALIZED, &port->flags);
-	}
-	return retval;
-}
-
-/*
- * mxser_get_lsr_info - get line status register info
- *
- * Purpose: Let user call ioctl() to get info when the UART physically
- *	    is emptied.  On bus types like RS485, the transmitter must
- *	    release the bus after transmitting. This must be done when
- *	    the transmit shift register is empty, not be done when the
- *	    transmit holding register is empty.  This functionality
- *	    allows an RS485 driver to be written in user space.
- */
-static int mxser_get_lsr_info(struct mxser_port *info,
-		unsigned int __user *value)
-{
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	status = inb(info->ioaddr + UART_LSR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	result = ((status & UART_LSR_TEMT) ? TIOCSER_TEMT : 0);
-	return put_user(result, value);
-}
-
-static int mxser_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned char control, status;
-	unsigned long flags;
-
-
-	if (tty->index == MXSER_PORTS)
-		return -ENOIOCTLCMD;
-	if (test_bit(TTY_IO_ERROR, &tty->flags))
-		return -EIO;
-
-	control = info->MCR;
-
-	spin_lock_irqsave(&info->slock, flags);
-	status = inb(info->ioaddr + UART_MSR);
-	if (status & UART_MSR_ANY_DELTA)
-		mxser_check_modem_status(tty, info, status);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return ((control & UART_MCR_RTS) ? TIOCM_RTS : 0) |
-		    ((control & UART_MCR_DTR) ? TIOCM_DTR : 0) |
-		    ((status & UART_MSR_DCD) ? TIOCM_CAR : 0) |
-		    ((status & UART_MSR_RI) ? TIOCM_RNG : 0) |
-		    ((status & UART_MSR_DSR) ? TIOCM_DSR : 0) |
-		    ((status & UART_MSR_CTS) ? TIOCM_CTS : 0);
-}
-
-static int mxser_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-
-	if (tty->index == MXSER_PORTS)
-		return -ENOIOCTLCMD;
-	if (test_bit(TTY_IO_ERROR, &tty->flags))
-		return -EIO;
-
-	spin_lock_irqsave(&info->slock, flags);
-
-	if (set & TIOCM_RTS)
-		info->MCR |= UART_MCR_RTS;
-	if (set & TIOCM_DTR)
-		info->MCR |= UART_MCR_DTR;
-
-	if (clear & TIOCM_RTS)
-		info->MCR &= ~UART_MCR_RTS;
-	if (clear & TIOCM_DTR)
-		info->MCR &= ~UART_MCR_DTR;
-
-	outb(info->MCR, info->ioaddr + UART_MCR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return 0;
-}
-
-static int __init mxser_program_mode(int port)
-{
-	int id, i, j, n;
-
-	outb(0, port);
-	outb(0, port);
-	outb(0, port);
-	(void)inb(port);
-	(void)inb(port);
-	outb(0, port);
-	(void)inb(port);
-
-	id = inb(port + 1) & 0x1F;
-	if ((id != C168_ASIC_ID) &&
-			(id != C104_ASIC_ID) &&
-			(id != C102_ASIC_ID) &&
-			(id != CI132_ASIC_ID) &&
-			(id != CI134_ASIC_ID) &&
-			(id != CI104J_ASIC_ID))
-		return -1;
-	for (i = 0, j = 0; i < 4; i++) {
-		n = inb(port + 2);
-		if (n == 'M') {
-			j = 1;
-		} else if ((j == 1) && (n == 1)) {
-			j = 2;
-			break;
-		} else
-			j = 0;
-	}
-	if (j != 2)
-		id = -2;
-	return id;
-}
-
-static void __init mxser_normal_mode(int port)
-{
-	int i, n;
-
-	outb(0xA5, port + 1);
-	outb(0x80, port + 3);
-	outb(12, port + 0);	/* 9600 bps */
-	outb(0, port + 1);
-	outb(0x03, port + 3);	/* 8 data bits */
-	outb(0x13, port + 4);	/* loop back mode */
-	for (i = 0; i < 16; i++) {
-		n = inb(port + 5);
-		if ((n & 0x61) == 0x60)
-			break;
-		if ((n & 1) == 1)
-			(void)inb(port);
-	}
-	outb(0x00, port + 4);
-}
-
-#define CHIP_SK 	0x01	/* Serial Data Clock  in Eprom */
-#define CHIP_DO 	0x02	/* Serial Data Output in Eprom */
-#define CHIP_CS 	0x04	/* Serial Chip Select in Eprom */
-#define CHIP_DI 	0x08	/* Serial Data Input  in Eprom */
-#define EN_CCMD 	0x000	/* Chip's command register     */
-#define EN0_RSARLO	0x008	/* Remote start address reg 0  */
-#define EN0_RSARHI	0x009	/* Remote start address reg 1  */
-#define EN0_RCNTLO	0x00A	/* Remote byte count reg WR    */
-#define EN0_RCNTHI	0x00B	/* Remote byte count reg WR    */
-#define EN0_DCFG	0x00E	/* Data configuration reg WR   */
-#define EN0_PORT	0x010	/* Rcv missed frame error counter RD */
-#define ENC_PAGE0	0x000	/* Select page 0 of chip registers   */
-#define ENC_PAGE3	0x0C0	/* Select page 3 of chip registers   */
-static int __init mxser_read_register(int port, unsigned short *regs)
-{
-	int i, k, value, id;
-	unsigned int j;
-
-	id = mxser_program_mode(port);
-	if (id < 0)
-		return id;
-	for (i = 0; i < 14; i++) {
-		k = (i & 0x3F) | 0x180;
-		for (j = 0x100; j > 0; j >>= 1) {
-			outb(CHIP_CS, port);
-			if (k & j) {
-				outb(CHIP_CS | CHIP_DO, port);
-				outb(CHIP_CS | CHIP_DO | CHIP_SK, port);	/* A? bit of read */
-			} else {
-				outb(CHIP_CS, port);
-				outb(CHIP_CS | CHIP_SK, port);	/* A? bit of read */
-			}
-		}
-		(void)inb(port);
-		value = 0;
-		for (k = 0, j = 0x8000; k < 16; k++, j >>= 1) {
-			outb(CHIP_CS, port);
-			outb(CHIP_CS | CHIP_SK, port);
-			if (inb(port) & CHIP_DI)
-				value |= j;
-		}
-		regs[i] = value;
-		outb(0, port);
-	}
-	mxser_normal_mode(port);
-	return id;
-}
-
-static int mxser_ioctl_special(unsigned int cmd, void __user *argp)
-{
-	struct mxser_port *ip;
-	struct tty_port *port;
-	struct tty_struct *tty;
-	int result, status;
-	unsigned int i, j;
-	int ret = 0;
-
-	switch (cmd) {
-	case MOXA_GET_MAJOR:
-		if (printk_ratelimit())
-			printk(KERN_WARNING "mxser: '%s' uses deprecated ioctl "
-					"%x (GET_MAJOR), fix your userspace\n",
-					current->comm, cmd);
-		return put_user(ttymajor, (int __user *)argp);
-
-	case MOXA_CHKPORTENABLE:
-		result = 0;
-		for (i = 0; i < MXSER_BOARDS; i++)
-			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++)
-				if (mxser_boards[i].ports[j].ioaddr)
-					result |= (1 << i);
-		return put_user(result, (unsigned long __user *)argp);
-	case MOXA_GETDATACOUNT:
-		/* The receive side is locked by port->slock but it isn't
-		   clear that an exact snapshot is worth copying here */
-		if (copy_to_user(argp, &mxvar_log, sizeof(mxvar_log)))
-			ret = -EFAULT;
-		return ret;
-	case MOXA_GETMSTATUS: {
-		struct mxser_mstatus ms, __user *msu = argp;
-		for (i = 0; i < MXSER_BOARDS; i++)
-			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++) {
-				ip = &mxser_boards[i].ports[j];
-				port = &ip->port;
-				memset(&ms, 0, sizeof(ms));
-
-				mutex_lock(&port->mutex);
-				if (!ip->ioaddr)
-					goto copy;
-				
-				tty = tty_port_tty_get(port);
-
-				if (!tty || !tty->termios)
-					ms.cflag = ip->normal_termios.c_cflag;
-				else
-					ms.cflag = tty->termios->c_cflag;
-				tty_kref_put(tty);
-				spin_lock_irq(&ip->slock);
-				status = inb(ip->ioaddr + UART_MSR);
-				spin_unlock_irq(&ip->slock);
-				if (status & UART_MSR_DCD)
-					ms.dcd = 1;
-				if (status & UART_MSR_DSR)
-					ms.dsr = 1;
-				if (status & UART_MSR_CTS)
-					ms.cts = 1;
-			copy:
-				mutex_unlock(&port->mutex);
-				if (copy_to_user(msu, &ms, sizeof(ms)))
-					return -EFAULT;
-				msu++;
-			}
-		return 0;
-	}
-	case MOXA_ASPP_MON_EXT: {
-		struct mxser_mon_ext *me; /* it's 2k, stack unfriendly */
-		unsigned int cflag, iflag, p;
-		u8 opmode;
-
-		me = kzalloc(sizeof(*me), GFP_KERNEL);
-		if (!me)
-			return -ENOMEM;
-
-		for (i = 0, p = 0; i < MXSER_BOARDS; i++) {
-			for (j = 0; j < MXSER_PORTS_PER_BOARD; j++, p++) {
-				if (p >= ARRAY_SIZE(me->rx_cnt)) {
-					i = MXSER_BOARDS;
-					break;
-				}
-				ip = &mxser_boards[i].ports[j];
-				port = &ip->port;
-
-				mutex_lock(&port->mutex);
-				if (!ip->ioaddr) {
-					mutex_unlock(&port->mutex);
-					continue;
-				}
-
-				spin_lock_irq(&ip->slock);
-				status = mxser_get_msr(ip->ioaddr, 0, p);
-
-				if (status & UART_MSR_TERI)
-					ip->icount.rng++;
-				if (status & UART_MSR_DDSR)
-					ip->icount.dsr++;
-				if (status & UART_MSR_DDCD)
-					ip->icount.dcd++;
-				if (status & UART_MSR_DCTS)
-					ip->icount.cts++;
-
-				ip->mon_data.modem_status = status;
-				me->rx_cnt[p] = ip->mon_data.rxcnt;
-				me->tx_cnt[p] = ip->mon_data.txcnt;
-				me->up_rxcnt[p] = ip->mon_data.up_rxcnt;
-				me->up_txcnt[p] = ip->mon_data.up_txcnt;
-				me->modem_status[p] =
-					ip->mon_data.modem_status;
-				spin_unlock_irq(&ip->slock);
-
-				tty = tty_port_tty_get(&ip->port);
-
-				if (!tty || !tty->termios) {
-					cflag = ip->normal_termios.c_cflag;
-					iflag = ip->normal_termios.c_iflag;
-					me->baudrate[p] = tty_termios_baud_rate(&ip->normal_termios);
-				} else {
-					cflag = tty->termios->c_cflag;
-					iflag = tty->termios->c_iflag;
-					me->baudrate[p] = tty_get_baud_rate(tty);
-				}
-				tty_kref_put(tty);
-
-				me->databits[p] = cflag & CSIZE;
-				me->stopbits[p] = cflag & CSTOPB;
-				me->parity[p] = cflag & (PARENB | PARODD |
-						CMSPAR);
-
-				if (cflag & CRTSCTS)
-					me->flowctrl[p] |= 0x03;
-
-				if (iflag & (IXON | IXOFF))
-					me->flowctrl[p] |= 0x0C;
-
-				if (ip->type == PORT_16550A)
-					me->fifo[p] = 1;
-
-				opmode = inb(ip->opmode_ioaddr)>>((p % 4) * 2);
-				opmode &= OP_MODE_MASK;
-				me->iftype[p] = opmode;
-				mutex_unlock(&port->mutex);
-			}
-		}
-		if (copy_to_user(argp, me, sizeof(*me)))
-			ret = -EFAULT;
-		kfree(me);
-		return ret;
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static int mxser_cflags_changed(struct mxser_port *info, unsigned long arg,
-		struct async_icount *cprev)
-{
-	struct async_icount cnow;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&info->slock, flags);
-	cnow = info->icount;	/* atomic copy */
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	ret =	((arg & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
-		((arg & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
-		((arg & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
-		((arg & TIOCM_CTS) && (cnow.cts != cprev->cts));
-
-	*cprev = cnow;
-
-	return ret;
-}
-
-static int mxser_ioctl(struct tty_struct *tty, struct file *file,
-		unsigned int cmd, unsigned long arg)
-{
-	struct mxser_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-	struct async_icount cnow;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (tty->index == MXSER_PORTS)
-		return mxser_ioctl_special(cmd, argp);
-
-	if (cmd == MOXA_SET_OP_MODE || cmd == MOXA_GET_OP_MODE) {
-		int p;
-		unsigned long opmode;
-		static unsigned char ModeMask[] = { 0xfc, 0xf3, 0xcf, 0x3f };
-		int shiftbit;
-		unsigned char val, mask;
-
-		p = tty->index % 4;
-		if (cmd == MOXA_SET_OP_MODE) {
-			if (get_user(opmode, (int __user *) argp))
-				return -EFAULT;
-			if (opmode != RS232_MODE &&
-					opmode != RS485_2WIRE_MODE &&
-					opmode != RS422_MODE &&
-					opmode != RS485_4WIRE_MODE)
-				return -EFAULT;
-			mask = ModeMask[p];
-			shiftbit = p * 2;
-			spin_lock_irq(&info->slock);
-			val = inb(info->opmode_ioaddr);
-			val &= mask;
-			val |= (opmode << shiftbit);
-			outb(val, info->opmode_ioaddr);
-			spin_unlock_irq(&info->slock);
-		} else {
-			shiftbit = p * 2;
-			spin_lock_irq(&info->slock);
-			opmode = inb(info->opmode_ioaddr) >> shiftbit;
-			spin_unlock_irq(&info->slock);
-			opmode &= OP_MODE_MASK;
-			if (put_user(opmode, (int __user *)argp))
-				return -EFAULT;
-		}
-		return 0;
-	}
-
-	if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
-			test_bit(TTY_IO_ERROR, &tty->flags))
-		return -EIO;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		mutex_lock(&port->mutex);
-		retval = mxser_get_serial_info(tty, argp);
-		mutex_unlock(&port->mutex);
-		return retval;
-	case TIOCSSERIAL:
-		mutex_lock(&port->mutex);
-		retval = mxser_set_serial_info(tty, argp);
-		mutex_unlock(&port->mutex);
-		return retval;
-	case TIOCSERGETLSR:	/* Get line status register */
-		return  mxser_get_lsr_info(info, argp);
-		/*
-		 * Wait for any of the 4 modem inputs (DCD,RI,DSR,CTS) to change
-		 * - mask passed in arg for lines of interest
-		 *   (use |'ed TIOCM_RNG/DSR/CD/CTS for masking)
-		 * Caller should use TIOCGICOUNT to see which one it was
-		 */
-	case TIOCMIWAIT:
-		spin_lock_irqsave(&info->slock, flags);
-		cnow = info->icount;	/* note the counters on entry */
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		return wait_event_interruptible(info->port.delta_msr_wait,
-				mxser_cflags_changed(info, arg, &cnow));
-	case MOXA_HighSpeedOn:
-		return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
-	case MOXA_SDS_RSTICOUNTER:
-		spin_lock_irq(&info->slock);
-		info->mon_data.rxcnt = 0;
-		info->mon_data.txcnt = 0;
-		spin_unlock_irq(&info->slock);
-		return 0;
-
-	case MOXA_ASPP_OQUEUE:{
-		int len, lsr;
-
-		len = mxser_chars_in_buffer(tty);
-		spin_lock_irq(&info->slock);
-		lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE;
-		spin_unlock_irq(&info->slock);
-		len += (lsr ? 0 : 1);
-
-		return put_user(len, (int __user *)argp);
-	}
-	case MOXA_ASPP_MON: {
-		int mcr, status;
-
-		spin_lock_irq(&info->slock);
-		status = mxser_get_msr(info->ioaddr, 1, tty->index);
-		mxser_check_modem_status(tty, info, status);
-
-		mcr = inb(info->ioaddr + UART_MCR);
-		spin_unlock_irq(&info->slock);
-
-		if (mcr & MOXA_MUST_MCR_XON_FLAG)
-			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFHOLD;
-		else
-			info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFHOLD;
-
-		if (mcr & MOXA_MUST_MCR_TX_XON)
-			info->mon_data.hold_reason &= ~NPPI_NOTIFY_XOFFXENT;
-		else
-			info->mon_data.hold_reason |= NPPI_NOTIFY_XOFFXENT;
-
-		if (tty->hw_stopped)
-			info->mon_data.hold_reason |= NPPI_NOTIFY_CTSHOLD;
-		else
-			info->mon_data.hold_reason &= ~NPPI_NOTIFY_CTSHOLD;
-
-		if (copy_to_user(argp, &info->mon_data,
-				sizeof(struct mxser_mon)))
-			return -EFAULT;
-
-		return 0;
-	}
-	case MOXA_ASPP_LSTATUS: {
-		if (put_user(info->err_shadow, (unsigned char __user *)argp))
-			return -EFAULT;
-
-		info->err_shadow = 0;
-		return 0;
-	}
-	case MOXA_SET_BAUD_METHOD: {
-		int method;
-
-		if (get_user(method, (int __user *)argp))
-			return -EFAULT;
-		mxser_set_baud_method[tty->index] = method;
-		return put_user(method, (int __user *)argp);
-	}
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-	/*
-	 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-	 * Return: write counters to the user passed counter struct
-	 * NB: both 1->0 and 0->1 transitions are counted except for
-	 *     RI where only 0->1 is counted.
-	 */
-
-static int mxser_get_icount(struct tty_struct *tty,
-		struct serial_icounter_struct *icount)
-
-{
-	struct mxser_port *info = tty->driver_data;
-	struct async_icount cnow;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	icount->frame = cnow.frame;
-	icount->brk = cnow.brk;
-	icount->overrun = cnow.overrun;
-	icount->buf_overrun = cnow.buf_overrun;
-	icount->parity = cnow.parity;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	return 0;
-}
-
-static void mxser_stoprx(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-
-	info->ldisc_stop_rx = 1;
-	if (I_IXOFF(tty)) {
-		if (info->board->chip_flag) {
-			info->IER &= ~MOXA_MUST_RECV_ISR;
-			outb(info->IER, info->ioaddr + UART_IER);
-		} else {
-			info->x_char = STOP_CHAR(tty);
-			outb(0, info->ioaddr + UART_IER);
-			info->IER |= UART_IER_THRI;
-			outb(info->IER, info->ioaddr + UART_IER);
-		}
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		info->MCR &= ~UART_MCR_RTS;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-	}
-}
-
-/*
- * This routine is called by the upper-layer tty layer to signal that
- * incoming characters should be throttled.
- */
-static void mxser_throttle(struct tty_struct *tty)
-{
-	mxser_stoprx(tty);
-}
-
-static void mxser_unthrottle(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-
-	/* startrx */
-	info->ldisc_stop_rx = 0;
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else {
-			if (info->board->chip_flag) {
-				info->IER |= MOXA_MUST_RECV_ISR;
-				outb(info->IER, info->ioaddr + UART_IER);
-			} else {
-				info->x_char = START_CHAR(tty);
-				outb(0, info->ioaddr + UART_IER);
-				info->IER |= UART_IER_THRI;
-				outb(info->IER, info->ioaddr + UART_IER);
-			}
-		}
-	}
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		info->MCR |= UART_MCR_RTS;
-		outb(info->MCR, info->ioaddr + UART_MCR);
-	}
-}
-
-/*
- * mxser_stop() and mxser_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- */
-static void mxser_stop(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (info->IER & UART_IER_THRI) {
-		info->IER &= ~UART_IER_THRI;
-		outb(info->IER, info->ioaddr + UART_IER);
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static void mxser_start(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (info->xmit_cnt && info->port.xmit_buf) {
-		outb(info->IER & ~UART_IER_THRI, info->ioaddr + UART_IER);
-		info->IER |= UART_IER_THRI;
-		outb(info->IER, info->ioaddr + UART_IER);
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-}
-
-static void mxser_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	mxser_change_speed(tty, old_termios);
-	spin_unlock_irqrestore(&info->slock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-			!(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		mxser_start(tty);
-	}
-
-	/* Handle sw stopped */
-	if ((old_termios->c_iflag & IXON) &&
-			!(tty->termios->c_iflag & IXON)) {
-		tty->stopped = 0;
-
-		if (info->board->chip_flag) {
-			spin_lock_irqsave(&info->slock, flags);
-			mxser_disable_must_rx_software_flow_control(
-					info->ioaddr);
-			spin_unlock_irqrestore(&info->slock, flags);
-		}
-
-		mxser_start(tty);
-	}
-}
-
-/*
- * mxser_wait_until_sent() --- wait until the transmitter is empty
- */
-static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-	unsigned long flags;
-	int lsr;
-
-	if (info->type == PORT_UNKNOWN)
-		return;
-
-	if (info->xmit_fifo_size == 0)
-		return;		/* Just in case.... */
-
-	orig_jiffies = jiffies;
-	/*
-	 * Set the check interval to be 1/5 of the estimated time to
-	 * send a single character, and make it at least 1.  The check
-	 * interval should also be less than the timeout.
-	 *
-	 * Note: we have to use pretty tight timings here to satisfy
-	 * the NIST-PCTS.
-	 */
-	char_time = (info->timeout - HZ / 50) / info->xmit_fifo_size;
-	char_time = char_time / 5;
-	if (char_time == 0)
-		char_time = 1;
-	if (timeout && timeout < char_time)
-		char_time = timeout;
-	/*
-	 * If the transmitter hasn't cleared in twice the approximate
-	 * amount of time to send the entire FIFO, it probably won't
-	 * ever clear.  This assumes the UART isn't doing flow
-	 * control, which is currently the case.  Hence, if it ever
-	 * takes longer than info->timeout, this is probably due to a
-	 * UART bug of some kind.  So, we clamp the timeout parameter at
-	 * 2*info->timeout.
-	 */
-	if (!timeout || timeout > 2 * info->timeout)
-		timeout = 2 * info->timeout;
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk(KERN_DEBUG "In rs_wait_until_sent(%d) check=%lu...",
-		timeout, char_time);
-	printk("jiff=%lu...", jiffies);
-#endif
-	spin_lock_irqsave(&info->slock, flags);
-	while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-		printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
-#endif
-		spin_unlock_irqrestore(&info->slock, flags);
-		schedule_timeout_interruptible(char_time);
-		spin_lock_irqsave(&info->slock, flags);
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-	set_current_state(TASK_RUNNING);
-
-#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
-	printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
-#endif
-}
-
-/*
- * This routine is called by tty_hangup() when a hangup is signaled.
- */
-static void mxser_hangup(struct tty_struct *tty)
-{
-	struct mxser_port *info = tty->driver_data;
-
-	mxser_flush_buffer(tty);
-	tty_port_hangup(&info->port);
-}
-
-/*
- * mxser_rs_break() --- routine which turns the break handling on or off
- */
-static int mxser_rs_break(struct tty_struct *tty, int break_state)
-{
-	struct mxser_port *info = tty->driver_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (break_state == -1)
-		outb(inb(info->ioaddr + UART_LCR) | UART_LCR_SBC,
-			info->ioaddr + UART_LCR);
-	else
-		outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
-			info->ioaddr + UART_LCR);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return 0;
-}
-
-static void mxser_receive_chars(struct tty_struct *tty,
-				struct mxser_port *port, int *status)
-{
-	unsigned char ch, gdl;
-	int ignored = 0;
-	int cnt = 0;
-	int recv_room;
-	int max = 256;
-
-	recv_room = tty->receive_room;
-	if (recv_room == 0 && !port->ldisc_stop_rx)
-		mxser_stoprx(tty);
-	if (port->board->chip_flag != MOXA_OTHER_UART) {
-
-		if (*status & UART_LSR_SPECIAL)
-			goto intr_old;
-		if (port->board->chip_flag == MOXA_MUST_MU860_HWID &&
-				(*status & MOXA_MUST_LSR_RERR))
-			goto intr_old;
-		if (*status & MOXA_MUST_LSR_RERR)
-			goto intr_old;
-
-		gdl = inb(port->ioaddr + MOXA_MUST_GDL_REGISTER);
-
-		if (port->board->chip_flag == MOXA_MUST_MU150_HWID)
-			gdl &= MOXA_MUST_GDL_MASK;
-		if (gdl >= recv_room) {
-			if (!port->ldisc_stop_rx)
-				mxser_stoprx(tty);
-		}
-		while (gdl--) {
-			ch = inb(port->ioaddr + UART_RX);
-			tty_insert_flip_char(tty, ch, 0);
-			cnt++;
-		}
-		goto end_intr;
-	}
-intr_old:
-
-	do {
-		if (max-- < 0)
-			break;
-
-		ch = inb(port->ioaddr + UART_RX);
-		if (port->board->chip_flag && (*status & UART_LSR_OE))
-			outb(0x23, port->ioaddr + UART_FCR);
-		*status &= port->read_status_mask;
-		if (*status & port->ignore_status_mask) {
-			if (++ignored > 100)
-				break;
-		} else {
-			char flag = 0;
-			if (*status & UART_LSR_SPECIAL) {
-				if (*status & UART_LSR_BI) {
-					flag = TTY_BREAK;
-					port->icount.brk++;
-
-					if (port->port.flags & ASYNC_SAK)
-						do_SAK(tty);
-				} else if (*status & UART_LSR_PE) {
-					flag = TTY_PARITY;
-					port->icount.parity++;
-				} else if (*status & UART_LSR_FE) {
-					flag = TTY_FRAME;
-					port->icount.frame++;
-				} else if (*status & UART_LSR_OE) {
-					flag = TTY_OVERRUN;
-					port->icount.overrun++;
-				} else
-					flag = TTY_BREAK;
-			}
-			tty_insert_flip_char(tty, ch, flag);
-			cnt++;
-			if (cnt >= recv_room) {
-				if (!port->ldisc_stop_rx)
-					mxser_stoprx(tty);
-				break;
-			}
-
-		}
-
-		if (port->board->chip_flag)
-			break;
-
-		*status = inb(port->ioaddr + UART_LSR);
-	} while (*status & UART_LSR_DR);
-
-end_intr:
-	mxvar_log.rxcnt[tty->index] += cnt;
-	port->mon_data.rxcnt += cnt;
-	port->mon_data.up_rxcnt += cnt;
-
-	/*
-	 * We are called from an interrupt context with &port->slock
-	 * being held. Drop it temporarily in order to prevent
-	 * recursive locking.
-	 */
-	spin_unlock(&port->slock);
-	tty_flip_buffer_push(tty);
-	spin_lock(&port->slock);
-}
-
-static void mxser_transmit_chars(struct tty_struct *tty, struct mxser_port *port)
-{
-	int count, cnt;
-
-	if (port->x_char) {
-		outb(port->x_char, port->ioaddr + UART_TX);
-		port->x_char = 0;
-		mxvar_log.txcnt[tty->index]++;
-		port->mon_data.txcnt++;
-		port->mon_data.up_txcnt++;
-		port->icount.tx++;
-		return;
-	}
-
-	if (port->port.xmit_buf == NULL)
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped ||
-			(tty->hw_stopped &&
-			(port->type != PORT_16550A) &&
-			(!port->board->chip_flag))) {
-		port->IER &= ~UART_IER_THRI;
-		outb(port->IER, port->ioaddr + UART_IER);
-		return;
-	}
-
-	cnt = port->xmit_cnt;
-	count = port->xmit_fifo_size;
-	do {
-		outb(port->port.xmit_buf[port->xmit_tail++],
-			port->ioaddr + UART_TX);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE - 1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-	mxvar_log.txcnt[tty->index] += (cnt - port->xmit_cnt);
-
-	port->mon_data.txcnt += (cnt - port->xmit_cnt);
-	port->mon_data.up_txcnt += (cnt - port->xmit_cnt);
-	port->icount.tx += (cnt - port->xmit_cnt);
-
-	if (port->xmit_cnt < WAKEUP_CHARS)
-		tty_wakeup(tty);
-
-	if (port->xmit_cnt <= 0) {
-		port->IER &= ~UART_IER_THRI;
-		outb(port->IER, port->ioaddr + UART_IER);
-	}
-}
-
-/*
- * This is the serial driver's generic interrupt routine
- */
-static irqreturn_t mxser_interrupt(int irq, void *dev_id)
-{
-	int status, iir, i;
-	struct mxser_board *brd = NULL;
-	struct mxser_port *port;
-	int max, irqbits, bits, msr;
-	unsigned int int_cnt, pass_counter = 0;
-	int handled = IRQ_NONE;
-	struct tty_struct *tty;
-
-	for (i = 0; i < MXSER_BOARDS; i++)
-		if (dev_id == &mxser_boards[i]) {
-			brd = dev_id;
-			break;
-		}
-
-	if (i == MXSER_BOARDS)
-		goto irq_stop;
-	if (brd == NULL)
-		goto irq_stop;
-	max = brd->info->nports;
-	while (pass_counter++ < MXSER_ISR_PASS_LIMIT) {
-		irqbits = inb(brd->vector) & brd->vector_mask;
-		if (irqbits == brd->vector_mask)
-			break;
-
-		handled = IRQ_HANDLED;
-		for (i = 0, bits = 1; i < max; i++, irqbits |= bits, bits <<= 1) {
-			if (irqbits == brd->vector_mask)
-				break;
-			if (bits & irqbits)
-				continue;
-			port = &brd->ports[i];
-
-			int_cnt = 0;
-			spin_lock(&port->slock);
-			do {
-				iir = inb(port->ioaddr + UART_IIR);
-				if (iir & UART_IIR_NO_INT)
-					break;
-				iir &= MOXA_MUST_IIR_MASK;
-				tty = tty_port_tty_get(&port->port);
-				if (!tty ||
-						(port->port.flags & ASYNC_CLOSING) ||
-						!(port->port.flags &
-							ASYNC_INITIALIZED)) {
-					status = inb(port->ioaddr + UART_LSR);
-					outb(0x27, port->ioaddr + UART_FCR);
-					inb(port->ioaddr + UART_MSR);
-					tty_kref_put(tty);
-					break;
-				}
-
-				status = inb(port->ioaddr + UART_LSR);
-
-				if (status & UART_LSR_PE)
-					port->err_shadow |= NPPI_NOTIFY_PARITY;
-				if (status & UART_LSR_FE)
-					port->err_shadow |= NPPI_NOTIFY_FRAMING;
-				if (status & UART_LSR_OE)
-					port->err_shadow |=
-						NPPI_NOTIFY_HW_OVERRUN;
-				if (status & UART_LSR_BI)
-					port->err_shadow |= NPPI_NOTIFY_BREAK;
-
-				if (port->board->chip_flag) {
-					if (iir == MOXA_MUST_IIR_GDA ||
-					    iir == MOXA_MUST_IIR_RDA ||
-					    iir == MOXA_MUST_IIR_RTO ||
-					    iir == MOXA_MUST_IIR_LSR)
-						mxser_receive_chars(tty, port,
-								&status);
-
-				} else {
-					status &= port->read_status_mask;
-					if (status & UART_LSR_DR)
-						mxser_receive_chars(tty, port,
-								&status);
-				}
-				msr = inb(port->ioaddr + UART_MSR);
-				if (msr & UART_MSR_ANY_DELTA)
-					mxser_check_modem_status(tty, port, msr);
-
-				if (port->board->chip_flag) {
-					if (iir == 0x02 && (status &
-								UART_LSR_THRE))
-						mxser_transmit_chars(tty, port);
-				} else {
-					if (status & UART_LSR_THRE)
-						mxser_transmit_chars(tty, port);
-				}
-				tty_kref_put(tty);
-			} while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
-			spin_unlock(&port->slock);
-		}
-	}
-
-irq_stop:
-	return handled;
-}
-
-static const struct tty_operations mxser_ops = {
-	.open = mxser_open,
-	.close = mxser_close,
-	.write = mxser_write,
-	.put_char = mxser_put_char,
-	.flush_chars = mxser_flush_chars,
-	.write_room = mxser_write_room,
-	.chars_in_buffer = mxser_chars_in_buffer,
-	.flush_buffer = mxser_flush_buffer,
-	.ioctl = mxser_ioctl,
-	.throttle = mxser_throttle,
-	.unthrottle = mxser_unthrottle,
-	.set_termios = mxser_set_termios,
-	.stop = mxser_stop,
-	.start = mxser_start,
-	.hangup = mxser_hangup,
-	.break_ctl = mxser_rs_break,
-	.wait_until_sent = mxser_wait_until_sent,
-	.tiocmget = mxser_tiocmget,
-	.tiocmset = mxser_tiocmset,
-	.get_icount = mxser_get_icount,
-};
-
-struct tty_port_operations mxser_port_ops = {
-	.carrier_raised = mxser_carrier_raised,
-	.dtr_rts = mxser_dtr_rts,
-	.activate = mxser_activate,
-	.shutdown = mxser_shutdown_port,
-};
-
-/*
- * The MOXA Smartio/Industio serial driver boot-time initialization code!
- */
-
-static void mxser_release_ISA_res(struct mxser_board *brd)
-{
-	free_irq(brd->irq, brd);
-	release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-	release_region(brd->vector, 1);
-}
-
-static int __devinit mxser_initbrd(struct mxser_board *brd,
-		struct pci_dev *pdev)
-{
-	struct mxser_port *info;
-	unsigned int i;
-	int retval;
-
-	printk(KERN_INFO "mxser: max. baud rate = %d bps\n",
-			brd->ports[0].max_baud);
-
-	for (i = 0; i < brd->info->nports; i++) {
-		info = &brd->ports[i];
-		tty_port_init(&info->port);
-		info->port.ops = &mxser_port_ops;
-		info->board = brd;
-		info->stop_rx = 0;
-		info->ldisc_stop_rx = 0;
-
-		/* Enhance mode enabled here */
-		if (brd->chip_flag != MOXA_OTHER_UART)
-			mxser_enable_must_enchance_mode(info->ioaddr);
-
-		info->port.flags = ASYNC_SHARE_IRQ;
-		info->type = brd->uart_type;
-
-		process_txrx_fifo(info);
-
-		info->custom_divisor = info->baud_base * 16;
-		info->port.close_delay = 5 * HZ / 10;
-		info->port.closing_wait = 30 * HZ;
-		info->normal_termios = mxvar_sdriver->init_termios;
-		memset(&info->mon_data, 0, sizeof(struct mxser_mon));
-		info->err_shadow = 0;
-		spin_lock_init(&info->slock);
-
-		/* before set INT ISR, disable all int */
-		outb(inb(info->ioaddr + UART_IER) & 0xf0,
-			info->ioaddr + UART_IER);
-	}
-
-	retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
-			brd);
-	if (retval)
-		printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
-			"conflict with another device.\n",
-			brd->info->name, brd->irq);
-
-	return retval;
-}
-
-static int __init mxser_get_ISA_conf(int cap, struct mxser_board *brd)
-{
-	int id, i, bits;
-	unsigned short regs[16], irq;
-	unsigned char scratch, scratch2;
-
-	brd->chip_flag = MOXA_OTHER_UART;
-
-	id = mxser_read_register(cap, regs);
-	switch (id) {
-	case C168_ASIC_ID:
-		brd->info = &mxser_cards[0];
-		break;
-	case C104_ASIC_ID:
-		brd->info = &mxser_cards[1];
-		break;
-	case CI104J_ASIC_ID:
-		brd->info = &mxser_cards[2];
-		break;
-	case C102_ASIC_ID:
-		brd->info = &mxser_cards[5];
-		break;
-	case CI132_ASIC_ID:
-		brd->info = &mxser_cards[6];
-		break;
-	case CI134_ASIC_ID:
-		brd->info = &mxser_cards[7];
-		break;
-	default:
-		return 0;
-	}
-
-	irq = 0;
-	/* some ISA cards have 2 ports, but we want to see them as 4-port (why?)
-	   Flag-hack checks if configuration should be read as 2-port here. */
-	if (brd->info->nports == 2 || (brd->info->flags & MXSER_HAS2)) {
-		irq = regs[9] & 0xF000;
-		irq = irq | (irq >> 4);
-		if (irq != (regs[9] & 0xFF00))
-			goto err_irqconflict;
-	} else if (brd->info->nports == 4) {
-		irq = regs[9] & 0xF000;
-		irq = irq | (irq >> 4);
-		irq = irq | (irq >> 8);
-		if (irq != regs[9])
-			goto err_irqconflict;
-	} else if (brd->info->nports == 8) {
-		irq = regs[9] & 0xF000;
-		irq = irq | (irq >> 4);
-		irq = irq | (irq >> 8);
-		if ((irq != regs[9]) || (irq != regs[10]))
-			goto err_irqconflict;
-	}
-
-	if (!irq) {
-		printk(KERN_ERR "mxser: interrupt number unset\n");
-		return -EIO;
-	}
-	brd->irq = ((int)(irq & 0xF000) >> 12);
-	for (i = 0; i < 8; i++)
-		brd->ports[i].ioaddr = (int) regs[i + 1] & 0xFFF8;
-	if ((regs[12] & 0x80) == 0) {
-		printk(KERN_ERR "mxser: invalid interrupt vector\n");
-		return -EIO;
-	}
-	brd->vector = (int)regs[11];	/* interrupt vector */
-	if (id == 1)
-		brd->vector_mask = 0x00FF;
-	else
-		brd->vector_mask = 0x000F;
-	for (i = 7, bits = 0x0100; i >= 0; i--, bits <<= 1) {
-		if (regs[12] & bits) {
-			brd->ports[i].baud_base = 921600;
-			brd->ports[i].max_baud = 921600;
-		} else {
-			brd->ports[i].baud_base = 115200;
-			brd->ports[i].max_baud = 115200;
-		}
-	}
-	scratch2 = inb(cap + UART_LCR) & (~UART_LCR_DLAB);
-	outb(scratch2 | UART_LCR_DLAB, cap + UART_LCR);
-	outb(0, cap + UART_EFR);	/* EFR is the same as FCR */
-	outb(scratch2, cap + UART_LCR);
-	outb(UART_FCR_ENABLE_FIFO, cap + UART_FCR);
-	scratch = inb(cap + UART_IIR);
-
-	if (scratch & 0xC0)
-		brd->uart_type = PORT_16550A;
-	else
-		brd->uart_type = PORT_16450;
-	if (!request_region(brd->ports[0].ioaddr, 8 * brd->info->nports,
-			"mxser(IO)")) {
-		printk(KERN_ERR "mxser: can't request ports I/O region: "
-				"0x%.8lx-0x%.8lx\n",
-				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
-				8 * brd->info->nports - 1);
-		return -EIO;
-	}
-	if (!request_region(brd->vector, 1, "mxser(vector)")) {
-		release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
-		printk(KERN_ERR "mxser: can't request interrupt vector region: "
-				"0x%.8lx-0x%.8lx\n",
-				brd->ports[0].ioaddr, brd->ports[0].ioaddr +
-				8 * brd->info->nports - 1);
-		return -EIO;
-	}
-	return brd->info->nports;
-
-err_irqconflict:
-	printk(KERN_ERR "mxser: invalid interrupt number\n");
-	return -EIO;
-}
-
-static int __devinit mxser_probe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-#ifdef CONFIG_PCI
-	struct mxser_board *brd;
-	unsigned int i, j;
-	unsigned long ioaddress;
-	int retval = -EINVAL;
-
-	for (i = 0; i < MXSER_BOARDS; i++)
-		if (mxser_boards[i].info == NULL)
-			break;
-
-	if (i >= MXSER_BOARDS) {
-		dev_err(&pdev->dev, "too many boards found (maximum %d), board "
-				"not configured\n", MXSER_BOARDS);
-		goto err;
-	}
-
-	brd = &mxser_boards[i];
-	brd->idx = i * MXSER_PORTS_PER_BOARD;
-	dev_info(&pdev->dev, "found MOXA %s board (BusNo=%d, DevNo=%d)\n",
-		mxser_cards[ent->driver_data].name,
-		pdev->bus->number, PCI_SLOT(pdev->devfn));
-
-	retval = pci_enable_device(pdev);
-	if (retval) {
-		dev_err(&pdev->dev, "PCI enable failed\n");
-		goto err;
-	}
-
-	/* io address */
-	ioaddress = pci_resource_start(pdev, 2);
-	retval = pci_request_region(pdev, 2, "mxser(IO)");
-	if (retval)
-		goto err_dis;
-
-	brd->info = &mxser_cards[ent->driver_data];
-	for (i = 0; i < brd->info->nports; i++)
-		brd->ports[i].ioaddr = ioaddress + 8 * i;
-
-	/* vector */
-	ioaddress = pci_resource_start(pdev, 3);
-	retval = pci_request_region(pdev, 3, "mxser(vector)");
-	if (retval)
-		goto err_zero;
-	brd->vector = ioaddress;
-
-	/* irq */
-	brd->irq = pdev->irq;
-
-	brd->chip_flag = CheckIsMoxaMust(brd->ports[0].ioaddr);
-	brd->uart_type = PORT_16550A;
-	brd->vector_mask = 0;
-
-	for (i = 0; i < brd->info->nports; i++) {
-		for (j = 0; j < UART_INFO_NUM; j++) {
-			if (Gpci_uart_info[j].type == brd->chip_flag) {
-				brd->ports[i].max_baud =
-					Gpci_uart_info[j].max_baud;
-
-				/* exception....CP-102 */
-				if (brd->info->flags & MXSER_HIGHBAUD)
-					brd->ports[i].max_baud = 921600;
-				break;
-			}
-		}
-	}
-
-	if (brd->chip_flag == MOXA_MUST_MU860_HWID) {
-		for (i = 0; i < brd->info->nports; i++) {
-			if (i < 4)
-				brd->ports[i].opmode_ioaddr = ioaddress + 4;
-			else
-				brd->ports[i].opmode_ioaddr = ioaddress + 0x0c;
-		}
-		outb(0, ioaddress + 4);	/* default set to RS232 mode */
-		outb(0, ioaddress + 0x0c);	/* default set to RS232 mode */
-	}
-
-	for (i = 0; i < brd->info->nports; i++) {
-		brd->vector_mask |= (1 << i);
-		brd->ports[i].baud_base = 921600;
-	}
-
-	/* mxser_initbrd will hook ISR. */
-	retval = mxser_initbrd(brd, pdev);
-	if (retval)
-		goto err_rel3;
-
-	for (i = 0; i < brd->info->nports; i++)
-		tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
-
-	pci_set_drvdata(pdev, brd);
-
-	return 0;
-err_rel3:
-	pci_release_region(pdev, 3);
-err_zero:
-	brd->info = NULL;
-	pci_release_region(pdev, 2);
-err_dis:
-	pci_disable_device(pdev);
-err:
-	return retval;
-#else
-	return -ENODEV;
-#endif
-}
-
-static void __devexit mxser_remove(struct pci_dev *pdev)
-{
-#ifdef CONFIG_PCI
-	struct mxser_board *brd = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	for (i = 0; i < brd->info->nports; i++)
-		tty_unregister_device(mxvar_sdriver, brd->idx + i);
-
-	free_irq(pdev->irq, brd);
-	pci_release_region(pdev, 2);
-	pci_release_region(pdev, 3);
-	pci_disable_device(pdev);
-	brd->info = NULL;
-#endif
-}
-
-static struct pci_driver mxser_driver = {
-	.name = "mxser",
-	.id_table = mxser_pcibrds,
-	.probe = mxser_probe,
-	.remove = __devexit_p(mxser_remove)
-};
-
-static int __init mxser_module_init(void)
-{
-	struct mxser_board *brd;
-	unsigned int b, i, m;
-	int retval;
-
-	mxvar_sdriver = alloc_tty_driver(MXSER_PORTS + 1);
-	if (!mxvar_sdriver)
-		return -ENOMEM;
-
-	printk(KERN_INFO "MOXA Smartio/Industio family driver version %s\n",
-		MXSER_VERSION);
-
-	/* Initialize the tty_driver structure */
-	mxvar_sdriver->owner = THIS_MODULE;
-	mxvar_sdriver->magic = TTY_DRIVER_MAGIC;
-	mxvar_sdriver->name = "ttyMI";
-	mxvar_sdriver->major = ttymajor;
-	mxvar_sdriver->minor_start = 0;
-	mxvar_sdriver->num = MXSER_PORTS + 1;
-	mxvar_sdriver->type = TTY_DRIVER_TYPE_SERIAL;
-	mxvar_sdriver->subtype = SERIAL_TYPE_NORMAL;
-	mxvar_sdriver->init_termios = tty_std_termios;
-	mxvar_sdriver->init_termios.c_cflag = B9600|CS8|CREAD|HUPCL|CLOCAL;
-	mxvar_sdriver->flags = TTY_DRIVER_REAL_RAW|TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(mxvar_sdriver, &mxser_ops);
-
-	retval = tty_register_driver(mxvar_sdriver);
-	if (retval) {
-		printk(KERN_ERR "Couldn't install MOXA Smartio/Industio family "
-				"tty driver !\n");
-		goto err_put;
-	}
-
-	/* Start finding ISA boards here */
-	for (m = 0, b = 0; b < MXSER_BOARDS; b++) {
-		if (!ioaddr[b])
-			continue;
-
-		brd = &mxser_boards[m];
-		retval = mxser_get_ISA_conf(ioaddr[b], brd);
-		if (retval <= 0) {
-			brd->info = NULL;
-			continue;
-		}
-
-		printk(KERN_INFO "mxser: found MOXA %s board (CAP=0x%lx)\n",
-				brd->info->name, ioaddr[b]);
-
-		/* mxser_initbrd will hook ISR. */
-		if (mxser_initbrd(brd, NULL) < 0) {
-			brd->info = NULL;
-			continue;
-		}
-
-		brd->idx = m * MXSER_PORTS_PER_BOARD;
-		for (i = 0; i < brd->info->nports; i++)
-			tty_register_device(mxvar_sdriver, brd->idx + i, NULL);
-
-		m++;
-	}
-
-	retval = pci_register_driver(&mxser_driver);
-	if (retval) {
-		printk(KERN_ERR "mxser: can't register pci driver\n");
-		if (!m) {
-			retval = -ENODEV;
-			goto err_unr;
-		} /* else: we have some ISA cards under control */
-	}
-
-	return 0;
-err_unr:
-	tty_unregister_driver(mxvar_sdriver);
-err_put:
-	put_tty_driver(mxvar_sdriver);
-	return retval;
-}
-
-static void __exit mxser_module_exit(void)
-{
-	unsigned int i, j;
-
-	pci_unregister_driver(&mxser_driver);
-
-	for (i = 0; i < MXSER_BOARDS; i++) /* ISA remains */
-		if (mxser_boards[i].info != NULL)
-			for (j = 0; j < mxser_boards[i].info->nports; j++)
-				tty_unregister_device(mxvar_sdriver,
-						mxser_boards[i].idx + j);
-	tty_unregister_driver(mxvar_sdriver);
-	put_tty_driver(mxvar_sdriver);
-
-	for (i = 0; i < MXSER_BOARDS; i++)
-		if (mxser_boards[i].info != NULL)
-			mxser_release_ISA_res(&mxser_boards[i]);
-}
-
-module_init(mxser_module_init);
-module_exit(mxser_module_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/char/mxser.h linux-libre-2.6.39-gnu/drivers/char/mxser.h
--- linux-libre-2.6.38-gnu/drivers/char/mxser.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/mxser.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,150 +0,0 @@
-#ifndef _MXSER_H
-#define _MXSER_H
-
-/*
- *	Semi-public control interfaces
- */
-
-/*
- *	MOXA ioctls
- */
-
-#define MOXA			0x400
-#define MOXA_GETDATACOUNT	(MOXA + 23)
-#define MOXA_DIAGNOSE		(MOXA + 50)
-#define MOXA_CHKPORTENABLE	(MOXA + 60)
-#define MOXA_HighSpeedOn	(MOXA + 61)
-#define MOXA_GET_MAJOR		(MOXA + 63)
-#define MOXA_GETMSTATUS		(MOXA + 65)
-#define MOXA_SET_OP_MODE	(MOXA + 66)
-#define MOXA_GET_OP_MODE	(MOXA + 67)
-
-#define RS232_MODE		0
-#define RS485_2WIRE_MODE	1
-#define RS422_MODE		2
-#define RS485_4WIRE_MODE	3
-#define OP_MODE_MASK		3
-
-#define MOXA_SDS_RSTICOUNTER	(MOXA + 69)
-#define MOXA_ASPP_OQUEUE  	(MOXA + 70)
-#define MOXA_ASPP_MON     	(MOXA + 73)
-#define MOXA_ASPP_LSTATUS 	(MOXA + 74)
-#define MOXA_ASPP_MON_EXT 	(MOXA + 75)
-#define MOXA_SET_BAUD_METHOD	(MOXA + 76)
-
-/* --------------------------------------------------- */
-
-#define NPPI_NOTIFY_PARITY	0x01
-#define NPPI_NOTIFY_FRAMING	0x02
-#define NPPI_NOTIFY_HW_OVERRUN	0x04
-#define NPPI_NOTIFY_SW_OVERRUN	0x08
-#define NPPI_NOTIFY_BREAK	0x10
-
-#define NPPI_NOTIFY_CTSHOLD         0x01	/* Tx hold by CTS low */
-#define NPPI_NOTIFY_DSRHOLD         0x02	/* Tx hold by DSR low */
-#define NPPI_NOTIFY_XOFFHOLD        0x08	/* Tx hold by Xoff received */
-#define NPPI_NOTIFY_XOFFXENT        0x10	/* Xoff Sent */
-
-/* follow just for Moxa Must chip define. */
-/* */
-/* when LCR register (offset 0x03) write following value, */
-/* the Must chip will enter enchance mode. And write value */
-/* on EFR (offset 0x02) bit 6,7 to change bank. */
-#define MOXA_MUST_ENTER_ENCHANCE	0xBF
-
-/* when enhance mode enable, access on general bank register */
-#define MOXA_MUST_GDL_REGISTER		0x07
-#define MOXA_MUST_GDL_MASK		0x7F
-#define MOXA_MUST_GDL_HAS_BAD_DATA	0x80
-
-#define MOXA_MUST_LSR_RERR		0x80	/* error in receive FIFO */
-/* enchance register bank select and enchance mode setting register */
-/* when LCR register equal to 0xBF */
-#define MOXA_MUST_EFR_REGISTER		0x02
-/* enchance mode enable */
-#define MOXA_MUST_EFR_EFRB_ENABLE	0x10
-/* enchance reister bank set 0, 1, 2 */
-#define MOXA_MUST_EFR_BANK0		0x00
-#define MOXA_MUST_EFR_BANK1		0x40
-#define MOXA_MUST_EFR_BANK2		0x80
-#define MOXA_MUST_EFR_BANK3		0xC0
-#define MOXA_MUST_EFR_BANK_MASK		0xC0
-
-/* set XON1 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XON1_REGISTER		0x04
-
-/* set XON2 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XON2_REGISTER		0x05
-
-/* set XOFF1 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XOFF1_REGISTER	0x06
-
-/* set XOFF2 value register, when LCR=0xBF and change to bank0 */
-#define MOXA_MUST_XOFF2_REGISTER	0x07
-
-#define MOXA_MUST_RBRTL_REGISTER	0x04
-#define MOXA_MUST_RBRTH_REGISTER	0x05
-#define MOXA_MUST_RBRTI_REGISTER	0x06
-#define MOXA_MUST_THRTL_REGISTER	0x07
-#define MOXA_MUST_ENUM_REGISTER		0x04
-#define MOXA_MUST_HWID_REGISTER		0x05
-#define MOXA_MUST_ECR_REGISTER		0x06
-#define MOXA_MUST_CSR_REGISTER		0x07
-
-/* good data mode enable */
-#define MOXA_MUST_FCR_GDA_MODE_ENABLE	0x20
-/* only good data put into RxFIFO */
-#define MOXA_MUST_FCR_GDA_ONLY_ENABLE	0x10
-
-/* enable CTS interrupt */
-#define MOXA_MUST_IER_ECTSI		0x80
-/* enable RTS interrupt */
-#define MOXA_MUST_IER_ERTSI		0x40
-/* enable Xon/Xoff interrupt */
-#define MOXA_MUST_IER_XINT		0x20
-/* enable GDA interrupt */
-#define MOXA_MUST_IER_EGDAI		0x10
-
-#define MOXA_MUST_RECV_ISR		(UART_IER_RDI | MOXA_MUST_IER_EGDAI)
-
-/* GDA interrupt pending */
-#define MOXA_MUST_IIR_GDA		0x1C
-#define MOXA_MUST_IIR_RDA		0x04
-#define MOXA_MUST_IIR_RTO		0x0C
-#define MOXA_MUST_IIR_LSR		0x06
-
-/* recieved Xon/Xoff or specical interrupt pending */
-#define MOXA_MUST_IIR_XSC		0x10
-
-/* RTS/CTS change state interrupt pending */
-#define MOXA_MUST_IIR_RTSCTS		0x20
-#define MOXA_MUST_IIR_MASK		0x3E
-
-#define MOXA_MUST_MCR_XON_FLAG		0x40
-#define MOXA_MUST_MCR_XON_ANY		0x80
-#define MOXA_MUST_MCR_TX_XON		0x08
-
-/* software flow control on chip mask value */
-#define MOXA_MUST_EFR_SF_MASK		0x0F
-/* send Xon1/Xoff1 */
-#define MOXA_MUST_EFR_SF_TX1		0x08
-/* send Xon2/Xoff2 */
-#define MOXA_MUST_EFR_SF_TX2		0x04
-/* send Xon1,Xon2/Xoff1,Xoff2 */
-#define MOXA_MUST_EFR_SF_TX12		0x0C
-/* don't send Xon/Xoff */
-#define MOXA_MUST_EFR_SF_TX_NO		0x00
-/* Tx software flow control mask */
-#define MOXA_MUST_EFR_SF_TX_MASK	0x0C
-/* don't receive Xon/Xoff */
-#define MOXA_MUST_EFR_SF_RX_NO		0x00
-/* receive Xon1/Xoff1 */
-#define MOXA_MUST_EFR_SF_RX1		0x02
-/* receive Xon2/Xoff2 */
-#define MOXA_MUST_EFR_SF_RX2		0x01
-/* receive Xon1,Xon2/Xoff1,Xoff2 */
-#define MOXA_MUST_EFR_SF_RX12		0x03
-/* Rx software flow control mask */
-#define MOXA_MUST_EFR_SF_RX_MASK	0x03
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/nozomi.c linux-libre-2.6.39-gnu/drivers/char/nozomi.c
--- linux-libre-2.6.38-gnu/drivers/char/nozomi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/nozomi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1993 +0,0 @@
-/*
- * nozomi.c  -- HSDPA driver Broadband Wireless Data Card - Globe Trotter
- *
- * Written by: Ulf Jakobsson,
- *             Jan Ã…kerfeldt,
- *             Stefan Thomasson,
- *
- * Maintained by: Paul Hardwick (p.hardwick@option.com)
- *
- * Patches:
- *          Locking code changes for Vodafone by Sphere Systems Ltd,
- *                              Andrew Bird (ajb@spheresystems.co.uk )
- *                              & Phil Sanderson
- *
- * Source has been ported from an implementation made by Filip Aben @ Option
- *
- * --------------------------------------------------------------------------
- *
- * Copyright (c) 2005,2006 Option Wireless Sweden AB
- * Copyright (c) 2006 Sphere Systems Ltd
- * Copyright (c) 2006 Option Wireless n/v
- * 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
- *
- * --------------------------------------------------------------------------
- */
-
-/* Enable this to have a lot of debug printouts */
-#define DEBUG
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/pci.h>
-#include <linux/ioport.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/interrupt.h>
-#include <linux/kmod.h>
-#include <linux/init.h>
-#include <linux/kfifo.h>
-#include <linux/uaccess.h>
-#include <linux/slab.h>
-#include <asm/byteorder.h>
-
-#include <linux/delay.h>
-
-
-#define VERSION_STRING DRIVER_DESC " 2.1d (build date: " \
-					__DATE__ " " __TIME__ ")"
-
-/*    Macros definitions */
-
-/* Default debug printout level */
-#define NOZOMI_DEBUG_LEVEL 0x00
-
-#define P_BUF_SIZE 128
-#define NFO(_err_flag_, args...)				\
-do {								\
-	char tmp[P_BUF_SIZE];					\
-	snprintf(tmp, sizeof(tmp), ##args);			\
-	printk(_err_flag_ "[%d] %s(): %s\n", __LINE__,		\
-		__func__, tmp);				\
-} while (0)
-
-#define DBG1(args...) D_(0x01, ##args)
-#define DBG2(args...) D_(0x02, ##args)
-#define DBG3(args...) D_(0x04, ##args)
-#define DBG4(args...) D_(0x08, ##args)
-#define DBG5(args...) D_(0x10, ##args)
-#define DBG6(args...) D_(0x20, ##args)
-#define DBG7(args...) D_(0x40, ##args)
-#define DBG8(args...) D_(0x80, ##args)
-
-#ifdef DEBUG
-/* Do we need this settable at runtime? */
-static int debug = NOZOMI_DEBUG_LEVEL;
-
-#define D(lvl, args...)  do \
-			{if (lvl & debug) NFO(KERN_DEBUG, ##args); } \
-			while (0)
-#define D_(lvl, args...) D(lvl, ##args)
-
-/* These printouts are always printed */
-
-#else
-static int debug;
-#define D_(lvl, args...)
-#endif
-
-/* TODO: rewrite to optimize macros... */
-
-#define TMP_BUF_MAX 256
-
-#define DUMP(buf__,len__) \
-  do {  \
-    char tbuf[TMP_BUF_MAX] = {0};\
-    if (len__ > 1) {\
-	snprintf(tbuf, len__ > TMP_BUF_MAX ? TMP_BUF_MAX : len__, "%s", buf__);\
-	if (tbuf[len__-2] == '\r') {\
-		tbuf[len__-2] = 'r';\
-	} \
-	DBG1("SENDING: '%s' (%d+n)", tbuf, len__);\
-    } else {\
-	DBG1("SENDING: '%s' (%d)", tbuf, len__);\
-    } \
-} while (0)
-
-/*    Defines */
-#define NOZOMI_NAME		"nozomi"
-#define NOZOMI_NAME_TTY		"nozomi_tty"
-#define DRIVER_DESC		"Nozomi driver"
-
-#define NTTY_TTY_MAXMINORS	256
-#define NTTY_FIFO_BUFFER_SIZE	8192
-
-/* Must be power of 2 */
-#define FIFO_BUFFER_SIZE_UL	8192
-
-/* Size of tmp send buffer to card */
-#define SEND_BUF_MAX		1024
-#define RECEIVE_BUF_MAX		4
-
-
-#define R_IIR		0x0000	/* Interrupt Identity Register */
-#define R_FCR		0x0000	/* Flow Control Register */
-#define R_IER		0x0004	/* Interrupt Enable Register */
-
-#define CONFIG_MAGIC	0xEFEFFEFE
-#define TOGGLE_VALID	0x0000
-
-/* Definition of interrupt tokens */
-#define MDM_DL1		0x0001
-#define MDM_UL1		0x0002
-#define MDM_DL2		0x0004
-#define MDM_UL2		0x0008
-#define DIAG_DL1	0x0010
-#define DIAG_DL2	0x0020
-#define DIAG_UL		0x0040
-#define APP1_DL		0x0080
-#define APP1_UL		0x0100
-#define APP2_DL		0x0200
-#define APP2_UL		0x0400
-#define CTRL_DL		0x0800
-#define CTRL_UL		0x1000
-#define RESET		0x8000
-
-#define MDM_DL		(MDM_DL1  | MDM_DL2)
-#define MDM_UL		(MDM_UL1  | MDM_UL2)
-#define DIAG_DL		(DIAG_DL1 | DIAG_DL2)
-
-/* modem signal definition */
-#define CTRL_DSR	0x0001
-#define CTRL_DCD	0x0002
-#define CTRL_RI		0x0004
-#define CTRL_CTS	0x0008
-
-#define CTRL_DTR	0x0001
-#define CTRL_RTS	0x0002
-
-#define MAX_PORT		4
-#define NOZOMI_MAX_PORTS	5
-#define NOZOMI_MAX_CARDS	(NTTY_TTY_MAXMINORS / MAX_PORT)
-
-/*    Type definitions */
-
-/*
- * There are two types of nozomi cards,
- * one with 2048 memory and with 8192 memory
- */
-enum card_type {
-	F32_2 = 2048,	/* 512 bytes downlink + uplink * 2 -> 2048 */
-	F32_8 = 8192,	/* 3072 bytes downl. + 1024 bytes uplink * 2 -> 8192 */
-};
-
-/* Initialization states a card can be in */
-enum card_state {
-	NOZOMI_STATE_UKNOWN	= 0,
-	NOZOMI_STATE_ENABLED	= 1,	/* pci device enabled */
-	NOZOMI_STATE_ALLOCATED	= 2,	/* config setup done */
-	NOZOMI_STATE_READY	= 3,	/* flowcontrols received */
-};
-
-/* Two different toggle channels exist */
-enum channel_type {
-	CH_A = 0,
-	CH_B = 1,
-};
-
-/* Port definition for the card regarding flow control */
-enum ctrl_port_type {
-	CTRL_CMD	= 0,
-	CTRL_MDM	= 1,
-	CTRL_DIAG	= 2,
-	CTRL_APP1	= 3,
-	CTRL_APP2	= 4,
-	CTRL_ERROR	= -1,
-};
-
-/* Ports that the nozomi has */
-enum port_type {
-	PORT_MDM	= 0,
-	PORT_DIAG	= 1,
-	PORT_APP1	= 2,
-	PORT_APP2	= 3,
-	PORT_CTRL	= 4,
-	PORT_ERROR	= -1,
-};
-
-#ifdef __BIG_ENDIAN
-/* Big endian */
-
-struct toggles {
-	unsigned int enabled:5;	/*
-				 * Toggle fields are valid if enabled is 0,
-				 * else A-channels must always be used.
-				 */
-	unsigned int diag_dl:1;
-	unsigned int mdm_dl:1;
-	unsigned int mdm_ul:1;
-} __attribute__ ((packed));
-
-/* Configuration table to read at startup of card */
-/* Is for now only needed during initialization phase */
-struct config_table {
-	u32 signature;
-	u16 product_information;
-	u16 version;
-	u8 pad3[3];
-	struct toggles toggle;
-	u8 pad1[4];
-	u16 dl_mdm_len1;	/*
-				 * If this is 64, it can hold
-				 * 60 bytes + 4 that is length field
-				 */
-	u16 dl_start;
-
-	u16 dl_diag_len1;
-	u16 dl_mdm_len2;	/*
-				 * If this is 64, it can hold
-				 * 60 bytes + 4 that is length field
-				 */
-	u16 dl_app1_len;
-
-	u16 dl_diag_len2;
-	u16 dl_ctrl_len;
-	u16 dl_app2_len;
-	u8 pad2[16];
-	u16 ul_mdm_len1;
-	u16 ul_start;
-	u16 ul_diag_len;
-	u16 ul_mdm_len2;
-	u16 ul_app1_len;
-	u16 ul_app2_len;
-	u16 ul_ctrl_len;
-} __attribute__ ((packed));
-
-/* This stores all control downlink flags */
-struct ctrl_dl {
-	u8 port;
-	unsigned int reserved:4;
-	unsigned int CTS:1;
-	unsigned int RI:1;
-	unsigned int DCD:1;
-	unsigned int DSR:1;
-} __attribute__ ((packed));
-
-/* This stores all control uplink flags */
-struct ctrl_ul {
-	u8 port;
-	unsigned int reserved:6;
-	unsigned int RTS:1;
-	unsigned int DTR:1;
-} __attribute__ ((packed));
-
-#else
-/* Little endian */
-
-/* This represents the toggle information */
-struct toggles {
-	unsigned int mdm_ul:1;
-	unsigned int mdm_dl:1;
-	unsigned int diag_dl:1;
-	unsigned int enabled:5;	/*
-				 * Toggle fields are valid if enabled is 0,
-				 * else A-channels must always be used.
-				 */
-} __attribute__ ((packed));
-
-/* Configuration table to read at startup of card */
-struct config_table {
-	u32 signature;
-	u16 version;
-	u16 product_information;
-	struct toggles toggle;
-	u8 pad1[7];
-	u16 dl_start;
-	u16 dl_mdm_len1;	/*
-				 * If this is 64, it can hold
-				 * 60 bytes + 4 that is length field
-				 */
-	u16 dl_mdm_len2;
-	u16 dl_diag_len1;
-	u16 dl_diag_len2;
-	u16 dl_app1_len;
-	u16 dl_app2_len;
-	u16 dl_ctrl_len;
-	u8 pad2[16];
-	u16 ul_start;
-	u16 ul_mdm_len2;
-	u16 ul_mdm_len1;
-	u16 ul_diag_len;
-	u16 ul_app1_len;
-	u16 ul_app2_len;
-	u16 ul_ctrl_len;
-} __attribute__ ((packed));
-
-/* This stores all control downlink flags */
-struct ctrl_dl {
-	unsigned int DSR:1;
-	unsigned int DCD:1;
-	unsigned int RI:1;
-	unsigned int CTS:1;
-	unsigned int reserverd:4;
-	u8 port;
-} __attribute__ ((packed));
-
-/* This stores all control uplink flags */
-struct ctrl_ul {
-	unsigned int DTR:1;
-	unsigned int RTS:1;
-	unsigned int reserved:6;
-	u8 port;
-} __attribute__ ((packed));
-#endif
-
-/* This holds all information that is needed regarding a port */
-struct port {
-	struct tty_port port;
-	u8 update_flow_control;
-	struct ctrl_ul ctrl_ul;
-	struct ctrl_dl ctrl_dl;
-	struct kfifo fifo_ul;
-	void __iomem *dl_addr[2];
-	u32 dl_size[2];
-	u8 toggle_dl;
-	void __iomem *ul_addr[2];
-	u32 ul_size[2];
-	u8 toggle_ul;
-	u16 token_dl;
-
-	/* mutex to ensure one access patch to this port */
-	struct mutex tty_sem;
-	wait_queue_head_t tty_wait;
-	struct async_icount tty_icount;
-
-	struct nozomi *dc;
-};
-
-/* Private data one for each card in the system */
-struct nozomi {
-	void __iomem *base_addr;
-	unsigned long flip;
-
-	/* Pointers to registers */
-	void __iomem *reg_iir;
-	void __iomem *reg_fcr;
-	void __iomem *reg_ier;
-
-	u16 last_ier;
-	enum card_type card_type;
-	struct config_table config_table;	/* Configuration table */
-	struct pci_dev *pdev;
-	struct port port[NOZOMI_MAX_PORTS];
-	u8 *send_buf;
-
-	spinlock_t spin_mutex;	/* secures access to registers and tty */
-
-	unsigned int index_start;
-	enum card_state state;
-	u32 open_ttys;
-};
-
-/* This is a data packet that is read or written to/from card */
-struct buffer {
-	u32 size;		/* size is the length of the data buffer */
-	u8 *data;
-} __attribute__ ((packed));
-
-/*    Global variables */
-static const struct pci_device_id nozomi_pci_tbl[] __devinitconst = {
-	{PCI_DEVICE(0x1931, 0x000c)},	/* Nozomi HSDPA */
-	{},
-};
-
-MODULE_DEVICE_TABLE(pci, nozomi_pci_tbl);
-
-static struct nozomi *ndevs[NOZOMI_MAX_CARDS];
-static struct tty_driver *ntty_driver;
-
-static const struct tty_port_operations noz_tty_port_ops;
-
-/*
- * find card by tty_index
- */
-static inline struct nozomi *get_dc_by_tty(const struct tty_struct *tty)
-{
-	return tty ? ndevs[tty->index / MAX_PORT] : NULL;
-}
-
-static inline struct port *get_port_by_tty(const struct tty_struct *tty)
-{
-	struct nozomi *ndev = get_dc_by_tty(tty);
-	return ndev ? &ndev->port[tty->index % MAX_PORT] : NULL;
-}
-
-/*
- * TODO:
- * -Optimize
- * -Rewrite cleaner
- */
-
-static void read_mem32(u32 *buf, const void __iomem *mem_addr_start,
-			u32 size_bytes)
-{
-	u32 i = 0;
-	const u32 __iomem *ptr = mem_addr_start;
-	u16 *buf16;
-
-	if (unlikely(!ptr || !buf))
-		goto out;
-
-	/* shortcut for extremely often used cases */
-	switch (size_bytes) {
-	case 2:	/* 2 bytes */
-		buf16 = (u16 *) buf;
-		*buf16 = __le16_to_cpu(readw(ptr));
-		goto out;
-		break;
-	case 4:	/* 4 bytes */
-		*(buf) = __le32_to_cpu(readl(ptr));
-		goto out;
-		break;
-	}
-
-	while (i < size_bytes) {
-		if (size_bytes - i == 2) {
-			/* Handle 2 bytes in the end */
-			buf16 = (u16 *) buf;
-			*(buf16) = __le16_to_cpu(readw(ptr));
-			i += 2;
-		} else {
-			/* Read 4 bytes */
-			*(buf) = __le32_to_cpu(readl(ptr));
-			i += 4;
-		}
-		buf++;
-		ptr++;
-	}
-out:
-	return;
-}
-
-/*
- * TODO:
- * -Optimize
- * -Rewrite cleaner
- */
-static u32 write_mem32(void __iomem *mem_addr_start, const u32 *buf,
-			u32 size_bytes)
-{
-	u32 i = 0;
-	u32 __iomem *ptr = mem_addr_start;
-	const u16 *buf16;
-
-	if (unlikely(!ptr || !buf))
-		return 0;
-
-	/* shortcut for extremely often used cases */
-	switch (size_bytes) {
-	case 2:	/* 2 bytes */
-		buf16 = (const u16 *)buf;
-		writew(__cpu_to_le16(*buf16), ptr);
-		return 2;
-		break;
-	case 1: /*
-		 * also needs to write 4 bytes in this case
-		 * so falling through..
-		 */
-	case 4: /* 4 bytes */
-		writel(__cpu_to_le32(*buf), ptr);
-		return 4;
-		break;
-	}
-
-	while (i < size_bytes) {
-		if (size_bytes - i == 2) {
-			/* 2 bytes */
-			buf16 = (const u16 *)buf;
-			writew(__cpu_to_le16(*buf16), ptr);
-			i += 2;
-		} else {
-			/* 4 bytes */
-			writel(__cpu_to_le32(*buf), ptr);
-			i += 4;
-		}
-		buf++;
-		ptr++;
-	}
-	return i;
-}
-
-/* Setup pointers to different channels and also setup buffer sizes. */
-static void setup_memory(struct nozomi *dc)
-{
-	void __iomem *offset = dc->base_addr + dc->config_table.dl_start;
-	/* The length reported is including the length field of 4 bytes,
-	 * hence subtract with 4.
-	 */
-	const u16 buff_offset = 4;
-
-	/* Modem port dl configuration */
-	dc->port[PORT_MDM].dl_addr[CH_A] = offset;
-	dc->port[PORT_MDM].dl_addr[CH_B] =
-				(offset += dc->config_table.dl_mdm_len1);
-	dc->port[PORT_MDM].dl_size[CH_A] =
-				dc->config_table.dl_mdm_len1 - buff_offset;
-	dc->port[PORT_MDM].dl_size[CH_B] =
-				dc->config_table.dl_mdm_len2 - buff_offset;
-
-	/* Diag port dl configuration */
-	dc->port[PORT_DIAG].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_mdm_len2);
-	dc->port[PORT_DIAG].dl_size[CH_A] =
-				dc->config_table.dl_diag_len1 - buff_offset;
-	dc->port[PORT_DIAG].dl_addr[CH_B] =
-				(offset += dc->config_table.dl_diag_len1);
-	dc->port[PORT_DIAG].dl_size[CH_B] =
-				dc->config_table.dl_diag_len2 - buff_offset;
-
-	/* App1 port dl configuration */
-	dc->port[PORT_APP1].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_diag_len2);
-	dc->port[PORT_APP1].dl_size[CH_A] =
-				dc->config_table.dl_app1_len - buff_offset;
-
-	/* App2 port dl configuration */
-	dc->port[PORT_APP2].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_app1_len);
-	dc->port[PORT_APP2].dl_size[CH_A] =
-				dc->config_table.dl_app2_len - buff_offset;
-
-	/* Ctrl dl configuration */
-	dc->port[PORT_CTRL].dl_addr[CH_A] =
-				(offset += dc->config_table.dl_app2_len);
-	dc->port[PORT_CTRL].dl_size[CH_A] =
-				dc->config_table.dl_ctrl_len - buff_offset;
-
-	offset = dc->base_addr + dc->config_table.ul_start;
-
-	/* Modem Port ul configuration */
-	dc->port[PORT_MDM].ul_addr[CH_A] = offset;
-	dc->port[PORT_MDM].ul_size[CH_A] =
-				dc->config_table.ul_mdm_len1 - buff_offset;
-	dc->port[PORT_MDM].ul_addr[CH_B] =
-				(offset += dc->config_table.ul_mdm_len1);
-	dc->port[PORT_MDM].ul_size[CH_B] =
-				dc->config_table.ul_mdm_len2 - buff_offset;
-
-	/* Diag port ul configuration */
-	dc->port[PORT_DIAG].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_mdm_len2);
-	dc->port[PORT_DIAG].ul_size[CH_A] =
-				dc->config_table.ul_diag_len - buff_offset;
-
-	/* App1 port ul configuration */
-	dc->port[PORT_APP1].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_diag_len);
-	dc->port[PORT_APP1].ul_size[CH_A] =
-				dc->config_table.ul_app1_len - buff_offset;
-
-	/* App2 port ul configuration */
-	dc->port[PORT_APP2].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_app1_len);
-	dc->port[PORT_APP2].ul_size[CH_A] =
-				dc->config_table.ul_app2_len - buff_offset;
-
-	/* Ctrl ul configuration */
-	dc->port[PORT_CTRL].ul_addr[CH_A] =
-				(offset += dc->config_table.ul_app2_len);
-	dc->port[PORT_CTRL].ul_size[CH_A] =
-				dc->config_table.ul_ctrl_len - buff_offset;
-}
-
-/* Dump config table under initalization phase */
-#ifdef DEBUG
-static void dump_table(const struct nozomi *dc)
-{
-	DBG3("signature: 0x%08X", dc->config_table.signature);
-	DBG3("version: 0x%04X", dc->config_table.version);
-	DBG3("product_information: 0x%04X", \
-				dc->config_table.product_information);
-	DBG3("toggle enabled: %d", dc->config_table.toggle.enabled);
-	DBG3("toggle up_mdm: %d", dc->config_table.toggle.mdm_ul);
-	DBG3("toggle dl_mdm: %d", dc->config_table.toggle.mdm_dl);
-	DBG3("toggle dl_dbg: %d", dc->config_table.toggle.diag_dl);
-
-	DBG3("dl_start: 0x%04X", dc->config_table.dl_start);
-	DBG3("dl_mdm_len0: 0x%04X, %d", dc->config_table.dl_mdm_len1,
-	   dc->config_table.dl_mdm_len1);
-	DBG3("dl_mdm_len1: 0x%04X, %d", dc->config_table.dl_mdm_len2,
-	   dc->config_table.dl_mdm_len2);
-	DBG3("dl_diag_len0: 0x%04X, %d", dc->config_table.dl_diag_len1,
-	   dc->config_table.dl_diag_len1);
-	DBG3("dl_diag_len1: 0x%04X, %d", dc->config_table.dl_diag_len2,
-	   dc->config_table.dl_diag_len2);
-	DBG3("dl_app1_len: 0x%04X, %d", dc->config_table.dl_app1_len,
-	   dc->config_table.dl_app1_len);
-	DBG3("dl_app2_len: 0x%04X, %d", dc->config_table.dl_app2_len,
-	   dc->config_table.dl_app2_len);
-	DBG3("dl_ctrl_len: 0x%04X, %d", dc->config_table.dl_ctrl_len,
-	   dc->config_table.dl_ctrl_len);
-	DBG3("ul_start: 0x%04X, %d", dc->config_table.ul_start,
-	   dc->config_table.ul_start);
-	DBG3("ul_mdm_len[0]: 0x%04X, %d", dc->config_table.ul_mdm_len1,
-	   dc->config_table.ul_mdm_len1);
-	DBG3("ul_mdm_len[1]: 0x%04X, %d", dc->config_table.ul_mdm_len2,
-	   dc->config_table.ul_mdm_len2);
-	DBG3("ul_diag_len: 0x%04X, %d", dc->config_table.ul_diag_len,
-	   dc->config_table.ul_diag_len);
-	DBG3("ul_app1_len: 0x%04X, %d", dc->config_table.ul_app1_len,
-	   dc->config_table.ul_app1_len);
-	DBG3("ul_app2_len: 0x%04X, %d", dc->config_table.ul_app2_len,
-	   dc->config_table.ul_app2_len);
-	DBG3("ul_ctrl_len: 0x%04X, %d", dc->config_table.ul_ctrl_len,
-	   dc->config_table.ul_ctrl_len);
-}
-#else
-static inline void dump_table(const struct nozomi *dc) { }
-#endif
-
-/*
- * Read configuration table from card under intalization phase
- * Returns 1 if ok, else 0
- */
-static int nozomi_read_config_table(struct nozomi *dc)
-{
-	read_mem32((u32 *) &dc->config_table, dc->base_addr + 0,
-						sizeof(struct config_table));
-
-	if (dc->config_table.signature != CONFIG_MAGIC) {
-		dev_err(&dc->pdev->dev, "ConfigTable Bad! 0x%08X != 0x%08X\n",
-			dc->config_table.signature, CONFIG_MAGIC);
-		return 0;
-	}
-
-	if ((dc->config_table.version == 0)
-	    || (dc->config_table.toggle.enabled == TOGGLE_VALID)) {
-		int i;
-		DBG1("Second phase, configuring card");
-
-		setup_memory(dc);
-
-		dc->port[PORT_MDM].toggle_ul = dc->config_table.toggle.mdm_ul;
-		dc->port[PORT_MDM].toggle_dl = dc->config_table.toggle.mdm_dl;
-		dc->port[PORT_DIAG].toggle_dl = dc->config_table.toggle.diag_dl;
-		DBG1("toggle ports: MDM UL:%d MDM DL:%d, DIAG DL:%d",
-		   dc->port[PORT_MDM].toggle_ul,
-		   dc->port[PORT_MDM].toggle_dl, dc->port[PORT_DIAG].toggle_dl);
-
-		dump_table(dc);
-
-		for (i = PORT_MDM; i < MAX_PORT; i++) {
-			memset(&dc->port[i].ctrl_dl, 0, sizeof(struct ctrl_dl));
-			memset(&dc->port[i].ctrl_ul, 0, sizeof(struct ctrl_ul));
-		}
-
-		/* Enable control channel */
-		dc->last_ier = dc->last_ier | CTRL_DL;
-		writew(dc->last_ier, dc->reg_ier);
-
-		dc->state = NOZOMI_STATE_ALLOCATED;
-		dev_info(&dc->pdev->dev, "Initialization OK!\n");
-		return 1;
-	}
-
-	if ((dc->config_table.version > 0)
-	    && (dc->config_table.toggle.enabled != TOGGLE_VALID)) {
-		u32 offset = 0;
-		DBG1("First phase: pushing upload buffers, clearing download");
-
-		dev_info(&dc->pdev->dev, "Version of card: %d\n",
-			 dc->config_table.version);
-
-		/* Here we should disable all I/O over F32. */
-		setup_memory(dc);
-
-		/*
-		 * We should send ALL channel pair tokens back along
-		 * with reset token
-		 */
-
-		/* push upload modem buffers */
-		write_mem32(dc->port[PORT_MDM].ul_addr[CH_A],
-			(u32 *) &offset, 4);
-		write_mem32(dc->port[PORT_MDM].ul_addr[CH_B],
-			(u32 *) &offset, 4);
-
-		writew(MDM_UL | DIAG_DL | MDM_DL, dc->reg_fcr);
-
-		DBG1("First phase done");
-	}
-
-	return 1;
-}
-
-/* Enable uplink interrupts  */
-static void enable_transmit_ul(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] = {MDM_UL, DIAG_UL, APP1_UL, APP2_UL, CTRL_UL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier |= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/* Disable uplink interrupts  */
-static void disable_transmit_ul(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] =
-		{~MDM_UL, ~DIAG_UL, ~APP1_UL, ~APP2_UL, ~CTRL_UL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier &= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/* Enable downlink interrupts */
-static void enable_transmit_dl(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] = {MDM_DL, DIAG_DL, APP1_DL, APP2_DL, CTRL_DL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier |= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/* Disable downlink interrupts */
-static void disable_transmit_dl(enum port_type port, struct nozomi *dc)
-{
-	static const u16 mask[] =
-		{~MDM_DL, ~DIAG_DL, ~APP1_DL, ~APP2_DL, ~CTRL_DL};
-
-	if (port < NOZOMI_MAX_PORTS) {
-		dc->last_ier &= mask[port];
-		writew(dc->last_ier, dc->reg_ier);
-	} else {
-		dev_err(&dc->pdev->dev, "Called with wrong port?\n");
-	}
-}
-
-/*
- * Return 1 - send buffer to card and ack.
- * Return 0 - don't ack, don't send buffer to card.
- */
-static int send_data(enum port_type index, struct nozomi *dc)
-{
-	u32 size = 0;
-	struct port *port = &dc->port[index];
-	const u8 toggle = port->toggle_ul;
-	void __iomem *addr = port->ul_addr[toggle];
-	const u32 ul_size = port->ul_size[toggle];
-	struct tty_struct *tty = tty_port_tty_get(&port->port);
-
-	/* Get data from tty and place in buf for now */
-	size = kfifo_out(&port->fifo_ul, dc->send_buf,
-			   ul_size < SEND_BUF_MAX ? ul_size : SEND_BUF_MAX);
-
-	if (size == 0) {
-		DBG4("No more data to send, disable link:");
-		tty_kref_put(tty);
-		return 0;
-	}
-
-	/* DUMP(buf, size); */
-
-	/* Write length + data */
-	write_mem32(addr, (u32 *) &size, 4);
-	write_mem32(addr + 4, (u32 *) dc->send_buf, size);
-
-	if (tty)
-		tty_wakeup(tty);
-
-	tty_kref_put(tty);
-	return 1;
-}
-
-/* If all data has been read, return 1, else 0 */
-static int receive_data(enum port_type index, struct nozomi *dc)
-{
-	u8 buf[RECEIVE_BUF_MAX] = { 0 };
-	int size;
-	u32 offset = 4;
-	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, ret;
-
-	if (unlikely(!tty)) {
-		DBG1("tty not open for port: %d?", index);
-		return 1;
-	}
-
-	read_mem32((u32 *) &size, addr, 4);
-	/*  DBG1( "%d bytes port: %d", size, index); */
-
-	if (test_bit(TTY_THROTTLED, &tty->flags)) {
-		DBG1("No room in tty, don't read data, don't ack interrupt, "
-			"disable interrupt");
-
-		/* disable interrupt in downlink... */
-		disable_transmit_dl(index, dc);
-		ret = 0;
-		goto put;
-	}
-
-	if (unlikely(size == 0)) {
-		dev_err(&dc->pdev->dev, "size == 0?\n");
-		ret = 1;
-		goto put;
-	}
-
-	while (size > 0) {
-		read_mem32((u32 *) buf, addr + offset, RECEIVE_BUF_MAX);
-
-		if (size == 1) {
-			tty_insert_flip_char(tty, buf[0], TTY_NORMAL);
-			size = 0;
-		} else if (size < RECEIVE_BUF_MAX) {
-			size -= tty_insert_flip_string(tty, (char *) buf, size);
-		} else {
-			i = tty_insert_flip_string(tty, \
-						(char *) buf, RECEIVE_BUF_MAX);
-			size -= i;
-			offset += i;
-		}
-	}
-
-	set_bit(index, &dc->flip);
-	ret = 1;
-put:
-	tty_kref_put(tty);
-	return ret;
-}
-
-/* Debug for interrupts */
-#ifdef DEBUG
-static char *interrupt2str(u16 interrupt)
-{
-	static char buf[TMP_BUF_MAX];
-	char *p = buf;
-
-	interrupt & MDM_DL1 ? p += snprintf(p, TMP_BUF_MAX, "MDM_DL1 ") : NULL;
-	interrupt & MDM_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"MDM_DL2 ") : NULL;
-
-	interrupt & MDM_UL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"MDM_UL1 ") : NULL;
-	interrupt & MDM_UL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"MDM_UL2 ") : NULL;
-
-	interrupt & DIAG_DL1 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"DIAG_DL1 ") : NULL;
-	interrupt & DIAG_DL2 ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"DIAG_DL2 ") : NULL;
-
-	interrupt & DIAG_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"DIAG_UL ") : NULL;
-
-	interrupt & APP1_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP1_DL ") : NULL;
-	interrupt & APP2_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP2_DL ") : NULL;
-
-	interrupt & APP1_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP1_UL ") : NULL;
-	interrupt & APP2_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"APP2_UL ") : NULL;
-
-	interrupt & CTRL_DL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"CTRL_DL ") : NULL;
-	interrupt & CTRL_UL ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"CTRL_UL ") : NULL;
-
-	interrupt & RESET ? p += snprintf(p, TMP_BUF_MAX - (p - buf),
-					"RESET ") : NULL;
-
-	return buf;
-}
-#endif
-
-/*
- * Receive flow control
- * Return 1 - If ok, else 0
- */
-static int receive_flow_control(struct nozomi *dc)
-{
-	enum port_type port = PORT_MDM;
-	struct ctrl_dl ctrl_dl;
-	struct ctrl_dl old_ctrl;
-	u16 enable_ier = 0;
-
-	read_mem32((u32 *) &ctrl_dl, dc->port[PORT_CTRL].dl_addr[CH_A], 2);
-
-	switch (ctrl_dl.port) {
-	case CTRL_CMD:
-		DBG1("The Base Band sends this value as a response to a "
-			"request for IMSI detach sent over the control "
-			"channel uplink (see section 7.6.1).");
-		break;
-	case CTRL_MDM:
-		port = PORT_MDM;
-		enable_ier = MDM_DL;
-		break;
-	case CTRL_DIAG:
-		port = PORT_DIAG;
-		enable_ier = DIAG_DL;
-		break;
-	case CTRL_APP1:
-		port = PORT_APP1;
-		enable_ier = APP1_DL;
-		break;
-	case CTRL_APP2:
-		port = PORT_APP2;
-		enable_ier = APP2_DL;
-		if (dc->state == NOZOMI_STATE_ALLOCATED) {
-			/*
-			 * After card initialization the flow control
-			 * received for APP2 is always the last
-			 */
-			dc->state = NOZOMI_STATE_READY;
-			dev_info(&dc->pdev->dev, "Device READY!\n");
-		}
-		break;
-	default:
-		dev_err(&dc->pdev->dev,
-			"ERROR: flow control received for non-existing port\n");
-		return 0;
-	};
-
-	DBG1("0x%04X->0x%04X", *((u16 *)&dc->port[port].ctrl_dl),
-	   *((u16 *)&ctrl_dl));
-
-	old_ctrl = dc->port[port].ctrl_dl;
-	dc->port[port].ctrl_dl = ctrl_dl;
-
-	if (old_ctrl.CTS == 1 && ctrl_dl.CTS == 0) {
-		DBG1("Disable interrupt (0x%04X) on port: %d",
-			enable_ier, port);
-		disable_transmit_ul(port, dc);
-
-	} else if (old_ctrl.CTS == 0 && ctrl_dl.CTS == 1) {
-
-		if (kfifo_len(&dc->port[port].fifo_ul)) {
-			DBG1("Enable interrupt (0x%04X) on port: %d",
-				enable_ier, port);
-			DBG1("Data in buffer [%d], enable transmit! ",
-				kfifo_len(&dc->port[port].fifo_ul));
-			enable_transmit_ul(port, dc);
-		} else {
-			DBG1("No data in buffer...");
-		}
-	}
-
-	if (*(u16 *)&old_ctrl == *(u16 *)&ctrl_dl) {
-		DBG1(" No change in mctrl");
-		return 1;
-	}
-	/* Update statistics */
-	if (old_ctrl.CTS != ctrl_dl.CTS)
-		dc->port[port].tty_icount.cts++;
-	if (old_ctrl.DSR != ctrl_dl.DSR)
-		dc->port[port].tty_icount.dsr++;
-	if (old_ctrl.RI != ctrl_dl.RI)
-		dc->port[port].tty_icount.rng++;
-	if (old_ctrl.DCD != ctrl_dl.DCD)
-		dc->port[port].tty_icount.dcd++;
-
-	wake_up_interruptible(&dc->port[port].tty_wait);
-
-	DBG1("port: %d DCD(%d), CTS(%d), RI(%d), DSR(%d)",
-	   port,
-	   dc->port[port].tty_icount.dcd, dc->port[port].tty_icount.cts,
-	   dc->port[port].tty_icount.rng, dc->port[port].tty_icount.dsr);
-
-	return 1;
-}
-
-static enum ctrl_port_type port2ctrl(enum port_type port,
-					const struct nozomi *dc)
-{
-	switch (port) {
-	case PORT_MDM:
-		return CTRL_MDM;
-	case PORT_DIAG:
-		return CTRL_DIAG;
-	case PORT_APP1:
-		return CTRL_APP1;
-	case PORT_APP2:
-		return CTRL_APP2;
-	default:
-		dev_err(&dc->pdev->dev,
-			"ERROR: send flow control " \
-			"received for non-existing port\n");
-	};
-	return CTRL_ERROR;
-}
-
-/*
- * Send flow control, can only update one channel at a time
- * Return 0 - If we have updated all flow control
- * Return 1 - If we need to update more flow control, ack current enable more
- */
-static int send_flow_control(struct nozomi *dc)
-{
-	u32 i, more_flow_control_to_be_updated = 0;
-	u16 *ctrl;
-
-	for (i = PORT_MDM; i < MAX_PORT; i++) {
-		if (dc->port[i].update_flow_control) {
-			if (more_flow_control_to_be_updated) {
-				/* We have more flow control to be updated */
-				return 1;
-			}
-			dc->port[i].ctrl_ul.port = port2ctrl(i, dc);
-			ctrl = (u16 *)&dc->port[i].ctrl_ul;
-			write_mem32(dc->port[PORT_CTRL].ul_addr[0], \
-				(u32 *) ctrl, 2);
-			dc->port[i].update_flow_control = 0;
-			more_flow_control_to_be_updated = 1;
-		}
-	}
-	return 0;
-}
-
-/*
- * Handle downlink data, ports that are handled are modem and diagnostics
- * Return 1 - ok
- * Return 0 - toggle fields are out of sync
- */
-static int handle_data_dl(struct nozomi *dc, enum port_type port, u8 *toggle,
-			u16 read_iir, u16 mask1, u16 mask2)
-{
-	if (*toggle == 0 && read_iir & mask1) {
-		if (receive_data(port, dc)) {
-			writew(mask1, dc->reg_fcr);
-			*toggle = !(*toggle);
-		}
-
-		if (read_iir & mask2) {
-			if (receive_data(port, dc)) {
-				writew(mask2, dc->reg_fcr);
-				*toggle = !(*toggle);
-			}
-		}
-	} else if (*toggle == 1 && read_iir & mask2) {
-		if (receive_data(port, dc)) {
-			writew(mask2, dc->reg_fcr);
-			*toggle = !(*toggle);
-		}
-
-		if (read_iir & mask1) {
-			if (receive_data(port, dc)) {
-				writew(mask1, dc->reg_fcr);
-				*toggle = !(*toggle);
-			}
-		}
-	} else {
-		dev_err(&dc->pdev->dev, "port out of sync!, toggle:%d\n",
-			*toggle);
-		return 0;
-	}
-	return 1;
-}
-
-/*
- * Handle uplink data, this is currently for the modem port
- * Return 1 - ok
- * Return 0 - toggle field are out of sync
- */
-static int handle_data_ul(struct nozomi *dc, enum port_type port, u16 read_iir)
-{
-	u8 *toggle = &(dc->port[port].toggle_ul);
-
-	if (*toggle == 0 && read_iir & MDM_UL1) {
-		dc->last_ier &= ~MDM_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(port, dc)) {
-			writew(MDM_UL1, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			*toggle = !*toggle;
-		}
-
-		if (read_iir & MDM_UL2) {
-			dc->last_ier &= ~MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			if (send_data(port, dc)) {
-				writew(MDM_UL2, dc->reg_fcr);
-				dc->last_ier = dc->last_ier | MDM_UL;
-				writew(dc->last_ier, dc->reg_ier);
-				*toggle = !*toggle;
-			}
-		}
-
-	} else if (*toggle == 1 && read_iir & MDM_UL2) {
-		dc->last_ier &= ~MDM_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(port, dc)) {
-			writew(MDM_UL2, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			*toggle = !*toggle;
-		}
-
-		if (read_iir & MDM_UL1) {
-			dc->last_ier &= ~MDM_UL;
-			writew(dc->last_ier, dc->reg_ier);
-			if (send_data(port, dc)) {
-				writew(MDM_UL1, dc->reg_fcr);
-				dc->last_ier = dc->last_ier | MDM_UL;
-				writew(dc->last_ier, dc->reg_ier);
-				*toggle = !*toggle;
-			}
-		}
-	} else {
-		writew(read_iir & MDM_UL, dc->reg_fcr);
-		dev_err(&dc->pdev->dev, "port out of sync!\n");
-		return 0;
-	}
-	return 1;
-}
-
-static irqreturn_t interrupt_handler(int irq, void *dev_id)
-{
-	struct nozomi *dc = dev_id;
-	unsigned int a;
-	u16 read_iir;
-
-	if (!dc)
-		return IRQ_NONE;
-
-	spin_lock(&dc->spin_mutex);
-	read_iir = readw(dc->reg_iir);
-
-	/* Card removed */
-	if (read_iir == (u16)-1)
-		goto none;
-	/*
-	 * Just handle interrupt enabled in IER
-	 * (by masking with dc->last_ier)
-	 */
-	read_iir &= dc->last_ier;
-
-	if (read_iir == 0)
-		goto none;
-
-
-	DBG4("%s irq:0x%04X, prev:0x%04X", interrupt2str(read_iir), read_iir,
-		dc->last_ier);
-
-	if (read_iir & RESET) {
-		if (unlikely(!nozomi_read_config_table(dc))) {
-			dc->last_ier = 0x0;
-			writew(dc->last_ier, dc->reg_ier);
-			dev_err(&dc->pdev->dev, "Could not read status from "
-				"card, we should disable interface\n");
-		} else {
-			writew(RESET, dc->reg_fcr);
-		}
-		/* No more useful info if this was the reset interrupt. */
-		goto exit_handler;
-	}
-	if (read_iir & CTRL_UL) {
-		DBG1("CTRL_UL");
-		dc->last_ier &= ~CTRL_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_flow_control(dc)) {
-			writew(CTRL_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | CTRL_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-	if (read_iir & CTRL_DL) {
-		receive_flow_control(dc);
-		writew(CTRL_DL, dc->reg_fcr);
-	}
-	if (read_iir & MDM_DL) {
-		if (!handle_data_dl(dc, PORT_MDM,
-				&(dc->port[PORT_MDM].toggle_dl), read_iir,
-				MDM_DL1, MDM_DL2)) {
-			dev_err(&dc->pdev->dev, "MDM_DL out of sync!\n");
-			goto exit_handler;
-		}
-	}
-	if (read_iir & MDM_UL) {
-		if (!handle_data_ul(dc, PORT_MDM, read_iir)) {
-			dev_err(&dc->pdev->dev, "MDM_UL out of sync!\n");
-			goto exit_handler;
-		}
-	}
-	if (read_iir & DIAG_DL) {
-		if (!handle_data_dl(dc, PORT_DIAG,
-				&(dc->port[PORT_DIAG].toggle_dl), read_iir,
-				DIAG_DL1, DIAG_DL2)) {
-			dev_err(&dc->pdev->dev, "DIAG_DL out of sync!\n");
-			goto exit_handler;
-		}
-	}
-	if (read_iir & DIAG_UL) {
-		dc->last_ier &= ~DIAG_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(PORT_DIAG, dc)) {
-			writew(DIAG_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | DIAG_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-	if (read_iir & APP1_DL) {
-		if (receive_data(PORT_APP1, dc))
-			writew(APP1_DL, dc->reg_fcr);
-	}
-	if (read_iir & APP1_UL) {
-		dc->last_ier &= ~APP1_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(PORT_APP1, dc)) {
-			writew(APP1_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | APP1_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-	if (read_iir & APP2_DL) {
-		if (receive_data(PORT_APP2, dc))
-			writew(APP2_DL, dc->reg_fcr);
-	}
-	if (read_iir & APP2_UL) {
-		dc->last_ier &= ~APP2_UL;
-		writew(dc->last_ier, dc->reg_ier);
-		if (send_data(PORT_APP2, dc)) {
-			writew(APP2_UL, dc->reg_fcr);
-			dc->last_ier = dc->last_ier | APP2_UL;
-			writew(dc->last_ier, dc->reg_ier);
-		}
-	}
-
-exit_handler:
-	spin_unlock(&dc->spin_mutex);
-	for (a = 0; a < NOZOMI_MAX_PORTS; a++) {
-		struct tty_struct *tty;
-		if (test_and_clear_bit(a, &dc->flip)) {
-			tty = tty_port_tty_get(&dc->port[a].port);
-			if (tty)
-				tty_flip_buffer_push(tty);
-			tty_kref_put(tty);
-		}
-	}
-	return IRQ_HANDLED;
-none:
-	spin_unlock(&dc->spin_mutex);
-	return IRQ_NONE;
-}
-
-static void nozomi_get_card_type(struct nozomi *dc)
-{
-	int i;
-	u32 size = 0;
-
-	for (i = 0; i < 6; i++)
-		size += pci_resource_len(dc->pdev, i);
-
-	/* Assume card type F32_8 if no match */
-	dc->card_type = size == 2048 ? F32_2 : F32_8;
-
-	dev_info(&dc->pdev->dev, "Card type is: %d\n", dc->card_type);
-}
-
-static void nozomi_setup_private_data(struct nozomi *dc)
-{
-	void __iomem *offset = dc->base_addr + dc->card_type / 2;
-	unsigned int i;
-
-	dc->reg_fcr = (void __iomem *)(offset + R_FCR);
-	dc->reg_iir = (void __iomem *)(offset + R_IIR);
-	dc->reg_ier = (void __iomem *)(offset + R_IER);
-	dc->last_ier = 0;
-	dc->flip = 0;
-
-	dc->port[PORT_MDM].token_dl = MDM_DL;
-	dc->port[PORT_DIAG].token_dl = DIAG_DL;
-	dc->port[PORT_APP1].token_dl = APP1_DL;
-	dc->port[PORT_APP2].token_dl = APP2_DL;
-
-	for (i = 0; i < MAX_PORT; i++)
-		init_waitqueue_head(&dc->port[i].tty_wait);
-}
-
-static ssize_t card_type_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
-
-	return sprintf(buf, "%d\n", dc->card_type);
-}
-static DEVICE_ATTR(card_type, S_IRUGO, card_type_show, NULL);
-
-static ssize_t open_ttys_show(struct device *dev, struct device_attribute *attr,
-			  char *buf)
-{
-	const struct nozomi *dc = pci_get_drvdata(to_pci_dev(dev));
-
-	return sprintf(buf, "%u\n", dc->open_ttys);
-}
-static DEVICE_ATTR(open_ttys, S_IRUGO, open_ttys_show, NULL);
-
-static void make_sysfs_files(struct nozomi *dc)
-{
-	if (device_create_file(&dc->pdev->dev, &dev_attr_card_type))
-		dev_err(&dc->pdev->dev,
-			"Could not create sysfs file for card_type\n");
-	if (device_create_file(&dc->pdev->dev, &dev_attr_open_ttys))
-		dev_err(&dc->pdev->dev,
-			"Could not create sysfs file for open_ttys\n");
-}
-
-static void remove_sysfs_files(struct nozomi *dc)
-{
-	device_remove_file(&dc->pdev->dev, &dev_attr_card_type);
-	device_remove_file(&dc->pdev->dev, &dev_attr_open_ttys);
-}
-
-/* Allocate memory for one device */
-static int __devinit nozomi_card_init(struct pci_dev *pdev,
-				      const struct pci_device_id *ent)
-{
-	resource_size_t start;
-	int ret;
-	struct nozomi *dc = NULL;
-	int ndev_idx;
-	int i;
-
-	dev_dbg(&pdev->dev, "Init, new card found\n");
-
-	for (ndev_idx = 0; ndev_idx < ARRAY_SIZE(ndevs); ndev_idx++)
-		if (!ndevs[ndev_idx])
-			break;
-
-	if (ndev_idx >= ARRAY_SIZE(ndevs)) {
-		dev_err(&pdev->dev, "no free tty range for this card left\n");
-		ret = -EIO;
-		goto err;
-	}
-
-	dc = kzalloc(sizeof(struct nozomi), GFP_KERNEL);
-	if (unlikely(!dc)) {
-		dev_err(&pdev->dev, "Could not allocate memory\n");
-		ret = -ENOMEM;
-		goto err_free;
-	}
-
-	dc->pdev = pdev;
-
-	ret = pci_enable_device(dc->pdev);
-	if (ret) {
-		dev_err(&pdev->dev, "Failed to enable PCI Device\n");
-		goto err_free;
-	}
-
-	ret = pci_request_regions(dc->pdev, NOZOMI_NAME);
-	if (ret) {
-		dev_err(&pdev->dev, "I/O address 0x%04x already in use\n",
-			(int) /* nozomi_private.io_addr */ 0);
-		goto err_disable_device;
-	}
-
-	start = pci_resource_start(dc->pdev, 0);
-	if (start == 0) {
-		dev_err(&pdev->dev, "No I/O address for card detected\n");
-		ret = -ENODEV;
-		goto err_rel_regs;
-	}
-
-	/* Find out what card type it is */
-	nozomi_get_card_type(dc);
-
-	dc->base_addr = ioremap_nocache(start, dc->card_type);
-	if (!dc->base_addr) {
-		dev_err(&pdev->dev, "Unable to map card MMIO\n");
-		ret = -ENODEV;
-		goto err_rel_regs;
-	}
-
-	dc->send_buf = kmalloc(SEND_BUF_MAX, GFP_KERNEL);
-	if (!dc->send_buf) {
-		dev_err(&pdev->dev, "Could not allocate send buffer?\n");
-		ret = -ENOMEM;
-		goto err_free_sbuf;
-	}
-
-	for (i = PORT_MDM; i < MAX_PORT; i++) {
-		if (kfifo_alloc(&dc->port[i].fifo_ul,
-		      FIFO_BUFFER_SIZE_UL, GFP_ATOMIC)) {
-			dev_err(&pdev->dev,
-					"Could not allocate kfifo buffer\n");
-			ret = -ENOMEM;
-			goto err_free_kfifo;
-		}
-	}
-
-	spin_lock_init(&dc->spin_mutex);
-
-	nozomi_setup_private_data(dc);
-
-	/* Disable all interrupts */
-	dc->last_ier = 0;
-	writew(dc->last_ier, dc->reg_ier);
-
-	ret = request_irq(pdev->irq, &interrupt_handler, IRQF_SHARED,
-			NOZOMI_NAME, dc);
-	if (unlikely(ret)) {
-		dev_err(&pdev->dev, "can't request irq %d\n", pdev->irq);
-		goto err_free_kfifo;
-	}
-
-	DBG1("base_addr: %p", dc->base_addr);
-
-	make_sysfs_files(dc);
-
-	dc->index_start = ndev_idx * MAX_PORT;
-	ndevs[ndev_idx] = dc;
-
-	pci_set_drvdata(pdev, dc);
-
-	/* Enable RESET interrupt */
-	dc->last_ier = RESET;
-	iowrite16(dc->last_ier, dc->reg_ier);
-
-	dc->state = NOZOMI_STATE_ENABLED;
-
-	for (i = 0; i < MAX_PORT; i++) {
-		struct device *tty_dev;
-		struct port *port = &dc->port[i];
-		port->dc = dc;
-		mutex_init(&port->tty_sem);
-		tty_port_init(&port->port);
-		port->port.ops = &noz_tty_port_ops;
-		tty_dev = tty_register_device(ntty_driver, dc->index_start + i,
-							&pdev->dev);
-
-		if (IS_ERR(tty_dev)) {
-			ret = PTR_ERR(tty_dev);
-			dev_err(&pdev->dev, "Could not allocate tty?\n");
-			goto err_free_tty;
-		}
-	}
-
-	return 0;
-
-err_free_tty:
-	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-		tty_unregister_device(ntty_driver, i);
-err_free_kfifo:
-	for (i = 0; i < MAX_PORT; i++)
-		kfifo_free(&dc->port[i].fifo_ul);
-err_free_sbuf:
-	kfree(dc->send_buf);
-	iounmap(dc->base_addr);
-err_rel_regs:
-	pci_release_regions(pdev);
-err_disable_device:
-	pci_disable_device(pdev);
-err_free:
-	kfree(dc);
-err:
-	return ret;
-}
-
-static void __devexit tty_exit(struct nozomi *dc)
-{
-	unsigned int i;
-
-	DBG1(" ");
-
-	flush_scheduled_work();
-
-	for (i = 0; i < MAX_PORT; ++i) {
-		struct tty_struct *tty = tty_port_tty_get(&dc->port[i].port);
-		if (tty && list_empty(&tty->hangup_work.entry))
-			tty_hangup(tty);
-		tty_kref_put(tty);
-	}
-	/* Racy below - surely should wait for scheduled work to be done or
-	   complete off a hangup method ? */
-	while (dc->open_ttys)
-		msleep(1);
-	for (i = dc->index_start; i < dc->index_start + MAX_PORT; ++i)
-		tty_unregister_device(ntty_driver, i);
-}
-
-/* Deallocate memory for one device */
-static void __devexit nozomi_card_exit(struct pci_dev *pdev)
-{
-	int i;
-	struct ctrl_ul ctrl;
-	struct nozomi *dc = pci_get_drvdata(pdev);
-
-	/* Disable all interrupts */
-	dc->last_ier = 0;
-	writew(dc->last_ier, dc->reg_ier);
-
-	tty_exit(dc);
-
-	/* Send 0x0001, command card to resend the reset token.  */
-	/* This is to get the reset when the module is reloaded. */
-	ctrl.port = 0x00;
-	ctrl.reserved = 0;
-	ctrl.RTS = 0;
-	ctrl.DTR = 1;
-	DBG1("sending flow control 0x%04X", *((u16 *)&ctrl));
-
-	/* Setup dc->reg addresses to we can use defines here */
-	write_mem32(dc->port[PORT_CTRL].ul_addr[0], (u32 *)&ctrl, 2);
-	writew(CTRL_UL, dc->reg_fcr);	/* push the token to the card. */
-
-	remove_sysfs_files(dc);
-
-	free_irq(pdev->irq, dc);
-
-	for (i = 0; i < MAX_PORT; i++)
-		kfifo_free(&dc->port[i].fifo_ul);
-
-	kfree(dc->send_buf);
-
-	iounmap(dc->base_addr);
-
-	pci_release_regions(pdev);
-
-	pci_disable_device(pdev);
-
-	ndevs[dc->index_start / MAX_PORT] = NULL;
-
-	kfree(dc);
-}
-
-static void set_rts(const struct tty_struct *tty, int rts)
-{
-	struct port *port = get_port_by_tty(tty);
-
-	port->ctrl_ul.RTS = rts;
-	port->update_flow_control = 1;
-	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
-}
-
-static void set_dtr(const struct tty_struct *tty, int dtr)
-{
-	struct port *port = get_port_by_tty(tty);
-
-	DBG1("SETTING DTR index: %d, dtr: %d", tty->index, dtr);
-
-	port->ctrl_ul.DTR = dtr;
-	port->update_flow_control = 1;
-	enable_transmit_ul(PORT_CTRL, get_dc_by_tty(tty));
-}
-
-/*
- * ----------------------------------------------------------------------------
- * TTY code
- * ----------------------------------------------------------------------------
- */
-
-static int ntty_install(struct tty_driver *driver, struct tty_struct *tty)
-{
-	struct port *port = get_port_by_tty(tty);
-	struct nozomi *dc = get_dc_by_tty(tty);
-	int ret;
-	if (!port || !dc || dc->state != NOZOMI_STATE_READY)
-		return -ENODEV;
-	ret = tty_init_termios(tty);
-	if (ret == 0) {
-		tty_driver_kref_get(driver);
-		tty->count++;
-		tty->driver_data = port;
-		driver->ttys[tty->index] = tty;
-	}
-	return ret;
-}
-
-static void ntty_cleanup(struct tty_struct *tty)
-{
-	tty->driver_data = NULL;
-}
-
-static int ntty_activate(struct tty_port *tport, struct tty_struct *tty)
-{
-	struct port *port = container_of(tport, struct port, port);
-	struct nozomi *dc = port->dc;
-	unsigned long flags;
-
-	DBG1("open: %d", port->token_dl);
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	dc->last_ier = dc->last_ier | port->token_dl;
-	writew(dc->last_ier, dc->reg_ier);
-	dc->open_ttys++;
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-	printk("noz: activated %d: %p\n", tty->index, tport);
-	return 0;
-}
-
-static int ntty_open(struct tty_struct *tty, struct file *filp)
-{
-	struct port *port = tty->driver_data;
-	return tty_port_open(&port->port, tty, filp);
-}
-
-static void ntty_shutdown(struct tty_port *tport)
-{
-	struct port *port = container_of(tport, struct port, port);
-	struct nozomi *dc = port->dc;
-	unsigned long flags;
-
-	DBG1("close: %d", port->token_dl);
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	dc->last_ier &= ~(port->token_dl);
-	writew(dc->last_ier, dc->reg_ier);
-	dc->open_ttys--;
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-	printk("noz: shutdown %p\n", tport);
-}
-
-static void ntty_close(struct tty_struct *tty, struct file *filp)
-{
-	struct port *port = tty->driver_data;
-	if (port)
-		tty_port_close(&port->port, tty, filp);
-}
-
-static void ntty_hangup(struct tty_struct *tty)
-{
-	struct port *port = tty->driver_data;
-	tty_port_hangup(&port->port);
-}
-
-/*
- * called when the userspace process writes to the tty (/dev/noz*).
- * Data is inserted into a fifo, which is then read and transfered to the modem.
- */
-static int ntty_write(struct tty_struct *tty, const unsigned char *buffer,
-		      int count)
-{
-	int rval = -EINVAL;
-	struct nozomi *dc = get_dc_by_tty(tty);
-	struct port *port = tty->driver_data;
-	unsigned long flags;
-
-	/* DBG1( "WRITEx: %d, index = %d", count, index); */
-
-	if (!dc || !port)
-		return -ENODEV;
-
-	mutex_lock(&port->tty_sem);
-
-	if (unlikely(!port->port.count)) {
-		DBG1(" ");
-		goto exit;
-	}
-
-	rval = kfifo_in(&port->fifo_ul, (unsigned char *)buffer, count);
-
-	/* notify card */
-	if (unlikely(dc == NULL)) {
-		DBG1("No device context?");
-		goto exit;
-	}
-
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	/* CTS is only valid on the modem channel */
-	if (port == &(dc->port[PORT_MDM])) {
-		if (port->ctrl_dl.CTS) {
-			DBG4("Enable interrupt");
-			enable_transmit_ul(tty->index % MAX_PORT, dc);
-		} else {
-			dev_err(&dc->pdev->dev,
-				"CTS not active on modem port?\n");
-		}
-	} else {
-		enable_transmit_ul(tty->index % MAX_PORT, dc);
-	}
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-
-exit:
-	mutex_unlock(&port->tty_sem);
-	return rval;
-}
-
-/*
- * Calculate how much is left in device
- * This method is called by the upper tty layer.
- *   #according to sources N_TTY.c it expects a value >= 0 and
- *    does not check for negative values.
- *
- * If the port is unplugged report lots of room and let the bits
- * dribble away so we don't block anything.
- */
-static int ntty_write_room(struct tty_struct *tty)
-{
-	struct port *port = tty->driver_data;
-	int room = 4096;
-	const struct nozomi *dc = get_dc_by_tty(tty);
-
-	if (dc) {
-		mutex_lock(&port->tty_sem);
-		if (port->port.count)
-			room = kfifo_avail(&port->fifo_ul);
-		mutex_unlock(&port->tty_sem);
-	}
-	return room;
-}
-
-/* Gets io control parameters */
-static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	const struct port *port = tty->driver_data;
-	const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
-	const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
-
-	/* Note: these could change under us but it is not clear this
-	   matters if so */
-	return	(ctrl_ul->RTS ? TIOCM_RTS : 0) |
-		(ctrl_ul->DTR ? TIOCM_DTR : 0) |
-		(ctrl_dl->DCD ? TIOCM_CAR : 0) |
-		(ctrl_dl->RI  ? TIOCM_RNG : 0) |
-		(ctrl_dl->DSR ? TIOCM_DSR : 0) |
-		(ctrl_dl->CTS ? TIOCM_CTS : 0);
-}
-
-/* Sets io controls parameters */
-static int ntty_tiocmset(struct tty_struct *tty, struct file *file,
-	unsigned int set, unsigned int clear)
-{
-	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	if (set & TIOCM_RTS)
-		set_rts(tty, 1);
-	else if (clear & TIOCM_RTS)
-		set_rts(tty, 0);
-
-	if (set & TIOCM_DTR)
-		set_dtr(tty, 1);
-	else if (clear & TIOCM_DTR)
-		set_dtr(tty, 0);
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-
-	return 0;
-}
-
-static int ntty_cflags_changed(struct port *port, unsigned long flags,
-		struct async_icount *cprev)
-{
-	const struct async_icount cnow = port->tty_icount;
-	int ret;
-
-	ret =	((flags & TIOCM_RNG) && (cnow.rng != cprev->rng)) ||
-		((flags & TIOCM_DSR) && (cnow.dsr != cprev->dsr)) ||
-		((flags & TIOCM_CD)  && (cnow.dcd != cprev->dcd)) ||
-		((flags & TIOCM_CTS) && (cnow.cts != cprev->cts));
-
-	*cprev = cnow;
-
-	return ret;
-}
-
-static int ntty_tiocgicount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	struct port *port = tty->driver_data;
-	const struct async_icount cnow = port->tty_icount;
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-static int ntty_ioctl(struct tty_struct *tty, struct file *file,
-		      unsigned int cmd, unsigned long arg)
-{
-	struct port *port = tty->driver_data;
-	int rval = -ENOIOCTLCMD;
-
-	DBG1("******** IOCTL, cmd: %d", cmd);
-
-	switch (cmd) {
-	case TIOCMIWAIT: {
-		struct async_icount cprev = port->tty_icount;
-
-		rval = wait_event_interruptible(port->tty_wait,
-				ntty_cflags_changed(port, arg, &cprev));
-		break;
-	}
-	default:
-		DBG1("ERR: 0x%08X, %d", cmd, cmd);
-		break;
-	};
-
-	return rval;
-}
-
-/*
- * Called by the upper tty layer when tty buffers are ready
- * to receive data again after a call to throttle.
- */
-static void ntty_unthrottle(struct tty_struct *tty)
-{
-	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
-	DBG1("UNTHROTTLE");
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	enable_transmit_dl(tty->index % MAX_PORT, dc);
-	set_rts(tty, 1);
-
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-}
-
-/*
- * Called by the upper tty layer when the tty buffers are almost full.
- * The driver should stop send more data.
- */
-static void ntty_throttle(struct tty_struct *tty)
-{
-	struct nozomi *dc = get_dc_by_tty(tty);
-	unsigned long flags;
-
-	DBG1("THROTTLE");
-	spin_lock_irqsave(&dc->spin_mutex, flags);
-	set_rts(tty, 0);
-	spin_unlock_irqrestore(&dc->spin_mutex, flags);
-}
-
-/* Returns number of chars in buffer, called by tty layer */
-static s32 ntty_chars_in_buffer(struct tty_struct *tty)
-{
-	struct port *port = tty->driver_data;
-	struct nozomi *dc = get_dc_by_tty(tty);
-	s32 rval = 0;
-
-	if (unlikely(!dc || !port)) {
-		goto exit_in_buffer;
-	}
-
-	if (unlikely(!port->port.count)) {
-		dev_err(&dc->pdev->dev, "No tty open?\n");
-		goto exit_in_buffer;
-	}
-
-	rval = kfifo_len(&port->fifo_ul);
-
-exit_in_buffer:
-	return rval;
-}
-
-static const struct tty_port_operations noz_tty_port_ops = {
-	.activate = ntty_activate,
-	.shutdown = ntty_shutdown,
-};
-
-static const struct tty_operations tty_ops = {
-	.ioctl = ntty_ioctl,
-	.open = ntty_open,
-	.close = ntty_close,
-	.hangup = ntty_hangup,
-	.write = ntty_write,
-	.write_room = ntty_write_room,
-	.unthrottle = ntty_unthrottle,
-	.throttle = ntty_throttle,
-	.chars_in_buffer = ntty_chars_in_buffer,
-	.tiocmget = ntty_tiocmget,
-	.tiocmset = ntty_tiocmset,
-	.get_icount = ntty_tiocgicount,
-	.install = ntty_install,
-	.cleanup = ntty_cleanup,
-};
-
-/* Module initialization */
-static struct pci_driver nozomi_driver = {
-	.name = NOZOMI_NAME,
-	.id_table = nozomi_pci_tbl,
-	.probe = nozomi_card_init,
-	.remove = __devexit_p(nozomi_card_exit),
-};
-
-static __init int nozomi_init(void)
-{
-	int ret;
-
-	printk(KERN_INFO "Initializing %s\n", VERSION_STRING);
-
-	ntty_driver = alloc_tty_driver(NTTY_TTY_MAXMINORS);
-	if (!ntty_driver)
-		return -ENOMEM;
-
-	ntty_driver->owner = THIS_MODULE;
-	ntty_driver->driver_name = NOZOMI_NAME_TTY;
-	ntty_driver->name = "noz";
-	ntty_driver->major = 0;
-	ntty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	ntty_driver->subtype = SERIAL_TYPE_NORMAL;
-	ntty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	ntty_driver->init_termios = tty_std_termios;
-	ntty_driver->init_termios.c_cflag = B115200 | CS8 | CREAD | \
-						HUPCL | CLOCAL;
-	ntty_driver->init_termios.c_ispeed = 115200;
-	ntty_driver->init_termios.c_ospeed = 115200;
-	tty_set_operations(ntty_driver, &tty_ops);
-
-	ret = tty_register_driver(ntty_driver);
-	if (ret) {
-		printk(KERN_ERR "Nozomi: failed to register ntty driver\n");
-		goto free_tty;
-	}
-
-	ret = pci_register_driver(&nozomi_driver);
-	if (ret) {
-		printk(KERN_ERR "Nozomi: can't register pci driver\n");
-		goto unr_tty;
-	}
-
-	return 0;
-unr_tty:
-	tty_unregister_driver(ntty_driver);
-free_tty:
-	put_tty_driver(ntty_driver);
-	return ret;
-}
-
-static __exit void nozomi_exit(void)
-{
-	printk(KERN_INFO "Unloading %s\n", DRIVER_DESC);
-	pci_unregister_driver(&nozomi_driver);
-	tty_unregister_driver(ntty_driver);
-	put_tty_driver(ntty_driver);
-}
-
-module_init(nozomi_init);
-module_exit(nozomi_exit);
-
-module_param(debug, int, S_IRUGO | S_IWUSR);
-
-MODULE_LICENSE("Dual BSD/GPL");
-MODULE_DESCRIPTION(DRIVER_DESC);
diff -druN linux-libre-2.6.38-gnu/drivers/char/nwbutton.c linux-libre-2.6.39-gnu/drivers/char/nwbutton.c
--- linux-libre-2.6.38-gnu/drivers/char/nwbutton.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/nwbutton.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
  * with -EINVAL. If there is more than one entry with the same address,
  * because it searches the list from end to beginning, it will unregister the
  * last one to be registered first (FILO- First In Last Out).
- * Note that this is not neccessarily true if the entries are not submitted
+ * Note that this is not necessarily true if the entries are not submitted
  * at the same time, because another driver could have unregistered a callback
  * between the submissions creating a gap earlier in the list, which would
  * be filled first at submission time.
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/cm4000_cs.c linux-libre-2.6.39-gnu/drivers/char/pcmcia/cm4000_cs.c
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/cm4000_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/cm4000_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -806,7 +806,7 @@
 		dev->flags1 = 0x01;
 		xoutb(dev->flags1, REG_FLAGS1(iobase));
 
-		/* atr is present (which doesnt mean it's valid) */
+		/* atr is present (which doesn't mean it's valid) */
 		set_bit(IS_ATR_PRESENT, &dev->flags);
 		if (dev->atr[0] == 0x03)
 			str_invert_revert(dev->atr, dev->atr_len);
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/hardware.c linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/hardware.c
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/hardware.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/hardware.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1764 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-
-#include "hardware.h"
-#include "setup_protocol.h"
-#include "network.h"
-#include "main.h"
-
-static void ipw_send_setup_packet(struct ipw_hardware *hw);
-static void handle_received_SETUP_packet(struct ipw_hardware *ipw,
-					 unsigned int address,
-					 const unsigned char *data, int len,
-					 int is_last);
-static void ipwireless_setup_timer(unsigned long data);
-static void handle_received_CTRL_packet(struct ipw_hardware *hw,
-		unsigned int channel_idx, const unsigned char *data, int len);
-
-/*#define TIMING_DIAGNOSTICS*/
-
-#ifdef TIMING_DIAGNOSTICS
-
-static struct timing_stats {
-	unsigned long last_report_time;
-	unsigned long read_time;
-	unsigned long write_time;
-	unsigned long read_bytes;
-	unsigned long write_bytes;
-	unsigned long start_time;
-};
-
-static void start_timing(void)
-{
-	timing_stats.start_time = jiffies;
-}
-
-static void end_read_timing(unsigned length)
-{
-	timing_stats.read_time += (jiffies - start_time);
-	timing_stats.read_bytes += length + 2;
-	report_timing();
-}
-
-static void end_write_timing(unsigned length)
-{
-	timing_stats.write_time += (jiffies - start_time);
-	timing_stats.write_bytes += length + 2;
-	report_timing();
-}
-
-static void report_timing(void)
-{
-	unsigned long since = jiffies - timing_stats.last_report_time;
-
-	/* If it's been more than one second... */
-	if (since >= HZ) {
-		int first = (timing_stats.last_report_time == 0);
-
-		timing_stats.last_report_time = jiffies;
-		if (!first)
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": %u us elapsed - read %lu bytes in %u us, wrote %lu bytes in %u us\n",
-			       jiffies_to_usecs(since),
-			       timing_stats.read_bytes,
-			       jiffies_to_usecs(timing_stats.read_time),
-			       timing_stats.write_bytes,
-			       jiffies_to_usecs(timing_stats.write_time));
-
-		timing_stats.read_time = 0;
-		timing_stats.write_time = 0;
-		timing_stats.read_bytes = 0;
-		timing_stats.write_bytes = 0;
-	}
-}
-#else
-static void start_timing(void) { }
-static void end_read_timing(unsigned length) { }
-static void end_write_timing(unsigned length) { }
-#endif
-
-/* Imported IPW definitions */
-
-#define LL_MTU_V1 318
-#define LL_MTU_V2 250
-#define LL_MTU_MAX (LL_MTU_V1 > LL_MTU_V2 ? LL_MTU_V1 : LL_MTU_V2)
-
-#define PRIO_DATA  2
-#define PRIO_CTRL  1
-#define PRIO_SETUP 0
-
-/* Addresses */
-#define ADDR_SETUP_PROT 0
-
-/* Protocol ids */
-enum {
-	/* Identifier for the Com Data protocol */
-	TL_PROTOCOLID_COM_DATA = 0,
-
-	/* Identifier for the Com Control protocol */
-	TL_PROTOCOLID_COM_CTRL = 1,
-
-	/* Identifier for the Setup protocol */
-	TL_PROTOCOLID_SETUP = 2
-};
-
-/* Number of bytes in NL packet header (cannot do
- * sizeof(nl_packet_header) since it's a bitfield) */
-#define NL_FIRST_PACKET_HEADER_SIZE        3
-
-/* Number of bytes in NL packet header (cannot do
- * sizeof(nl_packet_header) since it's a bitfield) */
-#define NL_FOLLOWING_PACKET_HEADER_SIZE    1
-
-struct nl_first_packet_header {
-	unsigned char protocol:3;
-	unsigned char address:3;
-	unsigned char packet_rank:2;
-	unsigned char length_lsb;
-	unsigned char length_msb;
-};
-
-struct nl_packet_header {
-	unsigned char protocol:3;
-	unsigned char address:3;
-	unsigned char packet_rank:2;
-};
-
-/* Value of 'packet_rank' above */
-#define NL_INTERMEDIATE_PACKET    0x0
-#define NL_LAST_PACKET            0x1
-#define NL_FIRST_PACKET           0x2
-
-union nl_packet {
-	/* Network packet header of the first packet (a special case) */
-	struct nl_first_packet_header hdr_first;
-	/* Network packet header of the following packets (if any) */
-	struct nl_packet_header hdr;
-	/* Complete network packet (header + data) */
-	unsigned char rawpkt[LL_MTU_MAX];
-} __attribute__ ((__packed__));
-
-#define HW_VERSION_UNKNOWN -1
-#define HW_VERSION_1 1
-#define HW_VERSION_2 2
-
-/* IPW I/O ports */
-#define IOIER 0x00		/* Interrupt Enable Register */
-#define IOIR  0x02		/* Interrupt Source/ACK register */
-#define IODCR 0x04		/* Data Control Register */
-#define IODRR 0x06		/* Data Read Register */
-#define IODWR 0x08		/* Data Write Register */
-#define IOESR 0x0A		/* Embedded Driver Status Register */
-#define IORXR 0x0C		/* Rx Fifo Register (Host to Embedded) */
-#define IOTXR 0x0E		/* Tx Fifo Register (Embedded to Host) */
-
-/* I/O ports and bit definitions for version 1 of the hardware */
-
-/* IER bits*/
-#define IER_RXENABLED   0x1
-#define IER_TXENABLED   0x2
-
-/* ISR bits */
-#define IR_RXINTR       0x1
-#define IR_TXINTR       0x2
-
-/* DCR bits */
-#define DCR_RXDONE      0x1
-#define DCR_TXDONE      0x2
-#define DCR_RXRESET     0x4
-#define DCR_TXRESET     0x8
-
-/* I/O ports and bit definitions for version 2 of the hardware */
-
-struct MEMCCR {
-	unsigned short reg_config_option;	/* PCCOR: Configuration Option Register */
-	unsigned short reg_config_and_status;	/* PCCSR: Configuration and Status Register */
-	unsigned short reg_pin_replacement;	/* PCPRR: Pin Replacemant Register */
-	unsigned short reg_socket_and_copy;	/* PCSCR: Socket and Copy Register */
-	unsigned short reg_ext_status;		/* PCESR: Extendend Status Register */
-	unsigned short reg_io_base;		/* PCIOB: I/O Base Register */
-};
-
-struct MEMINFREG {
-	unsigned short memreg_tx_old;	/* TX Register (R/W) */
-	unsigned short pad1;
-	unsigned short memreg_rx_done;	/* RXDone Register (R/W) */
-	unsigned short pad2;
-	unsigned short memreg_rx;	/* RX Register (R/W) */
-	unsigned short pad3;
-	unsigned short memreg_pc_interrupt_ack;	/* PC intr Ack Register (W) */
-	unsigned short pad4;
-	unsigned long memreg_card_present;/* Mask for Host to check (R) for
-					   * CARD_PRESENT_VALUE */
-	unsigned short memreg_tx_new;	/* TX2 (new) Register (R/W) */
-};
-
-#define CARD_PRESENT_VALUE (0xBEEFCAFEUL)
-
-#define MEMTX_TX                       0x0001
-#define MEMRX_RX                       0x0001
-#define MEMRX_RX_DONE                  0x0001
-#define MEMRX_PCINTACKK                0x0001
-
-#define NL_NUM_OF_PRIORITIES       3
-#define NL_NUM_OF_PROTOCOLS        3
-#define NL_NUM_OF_ADDRESSES        NO_OF_IPW_CHANNELS
-
-struct ipw_hardware {
-	unsigned int base_port;
-	short hw_version;
-	unsigned short ll_mtu;
-	spinlock_t lock;
-
-	int initializing;
-	int init_loops;
-	struct timer_list setup_timer;
-
-	/* Flag if hw is ready to send next packet */
-	int tx_ready;
-	/* Count of pending packets to be sent */
-	int tx_queued;
-	struct list_head tx_queue[NL_NUM_OF_PRIORITIES];
-
-	int rx_bytes_queued;
-	struct list_head rx_queue;
-	/* Pool of rx_packet structures that are not currently used. */
-	struct list_head rx_pool;
-	int rx_pool_size;
-	/* True if reception of data is blocked while userspace processes it. */
-	int blocking_rx;
-	/* True if there is RX data ready on the hardware. */
-	int rx_ready;
-	unsigned short last_memtx_serial;
-	/*
-	 * Newer versions of the V2 card firmware send serial numbers in the
-	 * MemTX register. 'serial_number_detected' is set true when we detect
-	 * a non-zero serial number (indicating the new firmware).  Thereafter,
-	 * the driver can safely ignore the Timer Recovery re-sends to avoid
-	 * out-of-sync problems.
-	 */
-	int serial_number_detected;
-	struct work_struct work_rx;
-
-	/* True if we are to send the set-up data to the hardware. */
-	int to_setup;
-
-	/* Card has been removed */
-	int removed;
-	/* Saved irq value when we disable the interrupt. */
-	int irq;
-	/* True if this driver is shutting down. */
-	int shutting_down;
-	/* Modem control lines */
-	unsigned int control_lines[NL_NUM_OF_ADDRESSES];
-	struct ipw_rx_packet *packet_assembler[NL_NUM_OF_ADDRESSES];
-
-	struct tasklet_struct tasklet;
-
-	/* The handle for the network layer, for the sending of events to it. */
-	struct ipw_network *network;
-	struct MEMINFREG __iomem *memory_info_regs;
-	struct MEMCCR __iomem *memregs_CCR;
-	void (*reboot_callback) (void *data);
-	void *reboot_callback_data;
-
-	unsigned short __iomem *memreg_tx;
-};
-
-/*
- * Packet info structure for tx packets.
- * Note: not all the fields defined here are required for all protocols
- */
-struct ipw_tx_packet {
-	struct list_head queue;
-	/* channel idx + 1 */
-	unsigned char dest_addr;
-	/* SETUP, CTRL or DATA */
-	unsigned char protocol;
-	/* Length of data block, which starts at the end of this structure */
-	unsigned short length;
-	/* Sending state */
-	/* Offset of where we've sent up to so far */
-	unsigned long offset;
-	/* Count of packet fragments, starting at 0 */
-	int fragment_count;
-
-	/* Called after packet is sent and before is freed */
-	void (*packet_callback) (void *cb_data, unsigned int packet_length);
-	void *callback_data;
-};
-
-/* Signals from DTE */
-#define COMCTRL_RTS	0
-#define COMCTRL_DTR	1
-
-/* Signals from DCE */
-#define COMCTRL_CTS	2
-#define COMCTRL_DCD	3
-#define COMCTRL_DSR	4
-#define COMCTRL_RI	5
-
-struct ipw_control_packet_body {
-	/* DTE signal or DCE signal */
-	unsigned char sig_no;
-	/* 0: set signal, 1: clear signal */
-	unsigned char value;
-} __attribute__ ((__packed__));
-
-struct ipw_control_packet {
-	struct ipw_tx_packet header;
-	struct ipw_control_packet_body body;
-};
-
-struct ipw_rx_packet {
-	struct list_head queue;
-	unsigned int capacity;
-	unsigned int length;
-	unsigned int protocol;
-	unsigned int channel_idx;
-};
-
-static char *data_type(const unsigned char *buf, unsigned length)
-{
-	struct nl_packet_header *hdr = (struct nl_packet_header *) buf;
-
-	if (length == 0)
-		return "     ";
-
-	if (hdr->packet_rank & NL_FIRST_PACKET) {
-		switch (hdr->protocol) {
-		case TL_PROTOCOLID_COM_DATA:	return "DATA ";
-		case TL_PROTOCOLID_COM_CTRL:	return "CTRL ";
-		case TL_PROTOCOLID_SETUP:	return "SETUP";
-		default: return "???? ";
-		}
-	} else
-		return "     ";
-}
-
-#define DUMP_MAX_BYTES 64
-
-static void dump_data_bytes(const char *type, const unsigned char *data,
-			    unsigned length)
-{
-	char prefix[56];
-
-	sprintf(prefix, IPWIRELESS_PCCARD_NAME ": %s %s ",
-			type, data_type(data, length));
-	print_hex_dump_bytes(prefix, 0, (void *)data,
-			length < DUMP_MAX_BYTES ? length : DUMP_MAX_BYTES);
-}
-
-static void swap_packet_bitfield_to_le(unsigned char *data)
-{
-#ifdef __BIG_ENDIAN_BITFIELD
-	unsigned char tmp = *data, ret = 0;
-
-	/*
-	 * transform bits from aa.bbb.ccc to ccc.bbb.aa
-	 */
-	ret |= tmp & 0xc0 >> 6;
-	ret |= tmp & 0x38 >> 1;
-	ret |= tmp & 0x07 << 5;
-	*data = ret & 0xff;
-#endif
-}
-
-static void swap_packet_bitfield_from_le(unsigned char *data)
-{
-#ifdef __BIG_ENDIAN_BITFIELD
-	unsigned char tmp = *data, ret = 0;
-
-	/*
-	 * transform bits from ccc.bbb.aa to aa.bbb.ccc
-	 */
-	ret |= tmp & 0xe0 >> 5;
-	ret |= tmp & 0x1c << 1;
-	ret |= tmp & 0x03 << 6;
-	*data = ret & 0xff;
-#endif
-}
-
-static void do_send_fragment(struct ipw_hardware *hw, unsigned char *data,
-			    unsigned length)
-{
-	unsigned i;
-	unsigned long flags;
-
-	start_timing();
-	BUG_ON(length > hw->ll_mtu);
-
-	if (ipwireless_debug)
-		dump_data_bytes("send", data, length);
-
-	spin_lock_irqsave(&hw->lock, flags);
-
-	hw->tx_ready = 0;
-	swap_packet_bitfield_to_le(data);
-
-	if (hw->hw_version == HW_VERSION_1) {
-		outw((unsigned short) length, hw->base_port + IODWR);
-
-		for (i = 0; i < length; i += 2) {
-			unsigned short d = data[i];
-			__le16 raw_data;
-
-			if (i + 1 < length)
-				d |= data[i + 1] << 8;
-			raw_data = cpu_to_le16(d);
-			outw(raw_data, hw->base_port + IODWR);
-		}
-
-		outw(DCR_TXDONE, hw->base_port + IODCR);
-	} else if (hw->hw_version == HW_VERSION_2) {
-		outw((unsigned short) length, hw->base_port);
-
-		for (i = 0; i < length; i += 2) {
-			unsigned short d = data[i];
-			__le16 raw_data;
-
-			if (i + 1 < length)
-				d |= data[i + 1] << 8;
-			raw_data = cpu_to_le16(d);
-			outw(raw_data, hw->base_port);
-		}
-		while ((i & 3) != 2) {
-			outw((unsigned short) 0xDEAD, hw->base_port);
-			i += 2;
-		}
-		writew(MEMRX_RX, &hw->memory_info_regs->memreg_rx);
-	}
-
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	end_write_timing(length);
-}
-
-static void do_send_packet(struct ipw_hardware *hw, struct ipw_tx_packet *packet)
-{
-	unsigned short fragment_data_len;
-	unsigned short data_left = packet->length - packet->offset;
-	unsigned short header_size;
-	union nl_packet pkt;
-
-	header_size =
-	    (packet->fragment_count == 0)
-	    ? NL_FIRST_PACKET_HEADER_SIZE
-	    : NL_FOLLOWING_PACKET_HEADER_SIZE;
-	fragment_data_len = hw->ll_mtu - header_size;
-	if (data_left < fragment_data_len)
-		fragment_data_len = data_left;
-
-	/*
-	 * hdr_first is now in machine bitfield order, which will be swapped
-	 * to le just before it goes to hw
-	 */
-	pkt.hdr_first.protocol = packet->protocol;
-	pkt.hdr_first.address = packet->dest_addr;
-	pkt.hdr_first.packet_rank = 0;
-
-	/* First packet? */
-	if (packet->fragment_count == 0) {
-		pkt.hdr_first.packet_rank |= NL_FIRST_PACKET;
-		pkt.hdr_first.length_lsb = (unsigned char) packet->length;
-		pkt.hdr_first.length_msb =
-			(unsigned char) (packet->length >> 8);
-	}
-
-	memcpy(pkt.rawpkt + header_size,
-	       ((unsigned char *) packet) + sizeof(struct ipw_tx_packet) +
-	       packet->offset, fragment_data_len);
-	packet->offset += fragment_data_len;
-	packet->fragment_count++;
-
-	/* Last packet? (May also be first packet.) */
-	if (packet->offset == packet->length)
-		pkt.hdr_first.packet_rank |= NL_LAST_PACKET;
-	do_send_fragment(hw, pkt.rawpkt, header_size + fragment_data_len);
-
-	/* If this packet has unsent data, then re-queue it. */
-	if (packet->offset < packet->length) {
-		/*
-		 * Re-queue it at the head of the highest priority queue so
-		 * it goes before all other packets
-		 */
-		unsigned long flags;
-
-		spin_lock_irqsave(&hw->lock, flags);
-		list_add(&packet->queue, &hw->tx_queue[0]);
-		hw->tx_queued++;
-		spin_unlock_irqrestore(&hw->lock, flags);
-	} else {
-		if (packet->packet_callback)
-			packet->packet_callback(packet->callback_data,
-					packet->length);
-		kfree(packet);
-	}
-}
-
-static void ipw_setup_hardware(struct ipw_hardware *hw)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	if (hw->hw_version == HW_VERSION_1) {
-		/* Reset RX FIFO */
-		outw(DCR_RXRESET, hw->base_port + IODCR);
-		/* SB: Reset TX FIFO */
-		outw(DCR_TXRESET, hw->base_port + IODCR);
-
-		/* Enable TX and RX interrupts. */
-		outw(IER_TXENABLED | IER_RXENABLED, hw->base_port + IOIER);
-	} else {
-		/*
-		 * Set INTRACK bit (bit 0), which means we must explicitly
-		 * acknowledge interrupts by clearing bit 2 of reg_config_and_status.
-		 */
-		unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
-
-		csr |= 1;
-		writew(csr, &hw->memregs_CCR->reg_config_and_status);
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-/*
- * If 'packet' is NULL, then this function allocates a new packet, setting its
- * length to 0 and ensuring it has the specified minimum amount of free space.
- *
- * If 'packet' is not NULL, then this function enlarges it if it doesn't
- * have the specified minimum amount of free space.
- *
- */
-static struct ipw_rx_packet *pool_allocate(struct ipw_hardware *hw,
-					   struct ipw_rx_packet *packet,
-					   int minimum_free_space)
-{
-
-	if (!packet) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&hw->lock, flags);
-		if (!list_empty(&hw->rx_pool)) {
-			packet = list_first_entry(&hw->rx_pool,
-					struct ipw_rx_packet, queue);
-			hw->rx_pool_size--;
-			spin_unlock_irqrestore(&hw->lock, flags);
-			list_del(&packet->queue);
-		} else {
-			const int min_capacity =
-				ipwireless_ppp_mru(hw->network) + 2;
-			int new_capacity;
-
-			spin_unlock_irqrestore(&hw->lock, flags);
-			new_capacity =
-				(minimum_free_space > min_capacity
-				 ? minimum_free_space
-				 : min_capacity);
-			packet = kmalloc(sizeof(struct ipw_rx_packet)
-					+ new_capacity, GFP_ATOMIC);
-			if (!packet)
-				return NULL;
-			packet->capacity = new_capacity;
-		}
-		packet->length = 0;
-	}
-
-	if (packet->length + minimum_free_space > packet->capacity) {
-		struct ipw_rx_packet *old_packet = packet;
-
-		packet = kmalloc(sizeof(struct ipw_rx_packet) +
-				old_packet->length + minimum_free_space,
-				GFP_ATOMIC);
-		if (!packet) {
-			kfree(old_packet);
-			return NULL;
-		}
-		memcpy(packet, old_packet,
-				sizeof(struct ipw_rx_packet)
-					+ old_packet->length);
-		packet->capacity = old_packet->length + minimum_free_space;
-		kfree(old_packet);
-	}
-
-	return packet;
-}
-
-static void pool_free(struct ipw_hardware *hw, struct ipw_rx_packet *packet)
-{
-	if (hw->rx_pool_size > 6)
-		kfree(packet);
-	else {
-		hw->rx_pool_size++;
-		list_add(&packet->queue, &hw->rx_pool);
-	}
-}
-
-static void queue_received_packet(struct ipw_hardware *hw,
-				  unsigned int protocol,
-				  unsigned int address,
-				  const unsigned char *data, int length,
-				  int is_last)
-{
-	unsigned int channel_idx = address - 1;
-	struct ipw_rx_packet *packet = NULL;
-	unsigned long flags;
-
-	/* Discard packet if channel index is out of range. */
-	if (channel_idx >= NL_NUM_OF_ADDRESSES) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": data packet has bad address %u\n", address);
-		return;
-	}
-
-	/*
-	 * ->packet_assembler is safe to touch unlocked, this is the only place
-	 */
-	if (protocol == TL_PROTOCOLID_COM_DATA) {
-		struct ipw_rx_packet **assem =
-			&hw->packet_assembler[channel_idx];
-
-		/*
-		 * Create a new packet, or assembler already contains one
-		 * enlarge it by 'length' bytes.
-		 */
-		(*assem) = pool_allocate(hw, *assem, length);
-		if (!(*assem)) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-				": no memory for incomming data packet, dropped!\n");
-			return;
-		}
-		(*assem)->protocol = protocol;
-		(*assem)->channel_idx = channel_idx;
-
-		/* Append this packet data onto existing data. */
-		memcpy((unsigned char *)(*assem) +
-			       sizeof(struct ipw_rx_packet)
-				+ (*assem)->length, data, length);
-		(*assem)->length += length;
-		if (is_last) {
-			packet = *assem;
-			*assem = NULL;
-			/* Count queued DATA bytes only */
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->rx_bytes_queued += packet->length;
-			spin_unlock_irqrestore(&hw->lock, flags);
-		}
-	} else {
-		/* If it's a CTRL packet, don't assemble, just queue it. */
-		packet = pool_allocate(hw, NULL, length);
-		if (!packet) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-				": no memory for incomming ctrl packet, dropped!\n");
-			return;
-		}
-		packet->protocol = protocol;
-		packet->channel_idx = channel_idx;
-		memcpy((unsigned char *)packet + sizeof(struct ipw_rx_packet),
-				data, length);
-		packet->length = length;
-	}
-
-	/*
-	 * If this is the last packet, then send the assembled packet on to the
-	 * network layer.
-	 */
-	if (packet) {
-		spin_lock_irqsave(&hw->lock, flags);
-		list_add_tail(&packet->queue, &hw->rx_queue);
-		/* Block reception of incoming packets if queue is full. */
-		hw->blocking_rx =
-			(hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE);
-
-		spin_unlock_irqrestore(&hw->lock, flags);
-		schedule_work(&hw->work_rx);
-	}
-}
-
-/*
- * Workqueue callback
- */
-static void ipw_receive_data_work(struct work_struct *work_rx)
-{
-	struct ipw_hardware *hw =
-	    container_of(work_rx, struct ipw_hardware, work_rx);
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	while (!list_empty(&hw->rx_queue)) {
-		struct ipw_rx_packet *packet =
-			list_first_entry(&hw->rx_queue,
-					struct ipw_rx_packet, queue);
-
-		if (hw->shutting_down)
-			break;
-		list_del(&packet->queue);
-
-		/*
-		 * Note: ipwireless_network_packet_received must be called in a
-		 * process context (i.e. via schedule_work) because the tty
-		 * output code can sleep in the tty_flip_buffer_push call.
-		 */
-		if (packet->protocol == TL_PROTOCOLID_COM_DATA) {
-			if (hw->network != NULL) {
-				/* If the network hasn't been disconnected. */
-				spin_unlock_irqrestore(&hw->lock, flags);
-				/*
-				 * This must run unlocked due to tty processing
-				 * and mutex locking
-				 */
-				ipwireless_network_packet_received(
-						hw->network,
-						packet->channel_idx,
-						(unsigned char *)packet
-						+ sizeof(struct ipw_rx_packet),
-						packet->length);
-				spin_lock_irqsave(&hw->lock, flags);
-			}
-			/* Count queued DATA bytes only */
-			hw->rx_bytes_queued -= packet->length;
-		} else {
-			/*
-			 * This is safe to be called locked, callchain does
-			 * not block
-			 */
-			handle_received_CTRL_packet(hw, packet->channel_idx,
-					(unsigned char *)packet
-					+ sizeof(struct ipw_rx_packet),
-					packet->length);
-		}
-		pool_free(hw, packet);
-		/*
-		 * Unblock reception of incoming packets if queue is no longer
-		 * full.
-		 */
-		hw->blocking_rx =
-			hw->rx_bytes_queued >= IPWIRELESS_RX_QUEUE_SIZE;
-		if (hw->shutting_down)
-			break;
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-}
-
-static void handle_received_CTRL_packet(struct ipw_hardware *hw,
-					unsigned int channel_idx,
-					const unsigned char *data, int len)
-{
-	const struct ipw_control_packet_body *body =
-		(const struct ipw_control_packet_body *) data;
-	unsigned int changed_mask;
-
-	if (len != sizeof(struct ipw_control_packet_body)) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": control packet was %d bytes - wrong size!\n",
-		       len);
-		return;
-	}
-
-	switch (body->sig_no) {
-	case COMCTRL_CTS:
-		changed_mask = IPW_CONTROL_LINE_CTS;
-		break;
-	case COMCTRL_DCD:
-		changed_mask = IPW_CONTROL_LINE_DCD;
-		break;
-	case COMCTRL_DSR:
-		changed_mask = IPW_CONTROL_LINE_DSR;
-		break;
-	case COMCTRL_RI:
-		changed_mask = IPW_CONTROL_LINE_RI;
-		break;
-	default:
-		changed_mask = 0;
-	}
-
-	if (changed_mask != 0) {
-		if (body->value)
-			hw->control_lines[channel_idx] |= changed_mask;
-		else
-			hw->control_lines[channel_idx] &= ~changed_mask;
-		if (hw->network)
-			ipwireless_network_notify_control_line_change(
-					hw->network,
-					channel_idx,
-					hw->control_lines[channel_idx],
-					changed_mask);
-	}
-}
-
-static void handle_received_packet(struct ipw_hardware *hw,
-				   const union nl_packet *packet,
-				   unsigned short len)
-{
-	unsigned int protocol = packet->hdr.protocol;
-	unsigned int address = packet->hdr.address;
-	unsigned int header_length;
-	const unsigned char *data;
-	unsigned int data_len;
-	int is_last = packet->hdr.packet_rank & NL_LAST_PACKET;
-
-	if (packet->hdr.packet_rank & NL_FIRST_PACKET)
-		header_length = NL_FIRST_PACKET_HEADER_SIZE;
-	else
-		header_length = NL_FOLLOWING_PACKET_HEADER_SIZE;
-
-	data = packet->rawpkt + header_length;
-	data_len = len - header_length;
-	switch (protocol) {
-	case TL_PROTOCOLID_COM_DATA:
-	case TL_PROTOCOLID_COM_CTRL:
-		queue_received_packet(hw, protocol, address, data, data_len,
-				is_last);
-		break;
-	case TL_PROTOCOLID_SETUP:
-		handle_received_SETUP_packet(hw, address, data, data_len,
-				is_last);
-		break;
-	}
-}
-
-static void acknowledge_data_read(struct ipw_hardware *hw)
-{
-	if (hw->hw_version == HW_VERSION_1)
-		outw(DCR_RXDONE, hw->base_port + IODCR);
-	else
-		writew(MEMRX_PCINTACKK,
-				&hw->memory_info_regs->memreg_pc_interrupt_ack);
-}
-
-/*
- * Retrieve a packet from the IPW hardware.
- */
-static void do_receive_packet(struct ipw_hardware *hw)
-{
-	unsigned len;
-	unsigned i;
-	unsigned char pkt[LL_MTU_MAX];
-
-	start_timing();
-
-	if (hw->hw_version == HW_VERSION_1) {
-		len = inw(hw->base_port + IODRR);
-		if (len > hw->ll_mtu) {
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": received a packet of %u bytes - longer than the MTU!\n", len);
-			outw(DCR_RXDONE | DCR_RXRESET, hw->base_port + IODCR);
-			return;
-		}
-
-		for (i = 0; i < len; i += 2) {
-			__le16 raw_data = inw(hw->base_port + IODRR);
-			unsigned short data = le16_to_cpu(raw_data);
-
-			pkt[i] = (unsigned char) data;
-			pkt[i + 1] = (unsigned char) (data >> 8);
-		}
-	} else {
-		len = inw(hw->base_port);
-		if (len > hw->ll_mtu) {
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": received a packet of %u bytes - longer than the MTU!\n", len);
-			writew(MEMRX_PCINTACKK,
-				&hw->memory_info_regs->memreg_pc_interrupt_ack);
-			return;
-		}
-
-		for (i = 0; i < len; i += 2) {
-			__le16 raw_data = inw(hw->base_port);
-			unsigned short data = le16_to_cpu(raw_data);
-
-			pkt[i] = (unsigned char) data;
-			pkt[i + 1] = (unsigned char) (data >> 8);
-		}
-
-		while ((i & 3) != 2) {
-			inw(hw->base_port);
-			i += 2;
-		}
-	}
-
-	acknowledge_data_read(hw);
-
-	swap_packet_bitfield_from_le(pkt);
-
-	if (ipwireless_debug)
-		dump_data_bytes("recv", pkt, len);
-
-	handle_received_packet(hw, (union nl_packet *) pkt, len);
-
-	end_read_timing(len);
-}
-
-static int get_current_packet_priority(struct ipw_hardware *hw)
-{
-	/*
-	 * If we're initializing, don't send anything of higher priority than
-	 * PRIO_SETUP.  The network layer therefore need not care about
-	 * hardware initialization - any of its stuff will simply be queued
-	 * until setup is complete.
-	 */
-	return (hw->to_setup || hw->initializing
-			? PRIO_SETUP + 1 : NL_NUM_OF_PRIORITIES);
-}
-
-/*
- * return 1 if something has been received from hw
- */
-static int get_packets_from_hw(struct ipw_hardware *hw)
-{
-	int received = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	while (hw->rx_ready && !hw->blocking_rx) {
-		received = 1;
-		hw->rx_ready--;
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		do_receive_packet(hw);
-
-		spin_lock_irqsave(&hw->lock, flags);
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	return received;
-}
-
-/*
- * Send pending packet up to given priority, prioritize SETUP data until
- * hardware is fully setup.
- *
- * return 1 if more packets can be sent
- */
-static int send_pending_packet(struct ipw_hardware *hw, int priority_limit)
-{
-	int more_to_send = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	if (hw->tx_queued && hw->tx_ready) {
-		int priority;
-		struct ipw_tx_packet *packet = NULL;
-
-		/* Pick a packet */
-		for (priority = 0; priority < priority_limit; priority++) {
-			if (!list_empty(&hw->tx_queue[priority])) {
-				packet = list_first_entry(
-						&hw->tx_queue[priority],
-						struct ipw_tx_packet,
-						queue);
-
-				hw->tx_queued--;
-				list_del(&packet->queue);
-
-				break;
-			}
-		}
-		if (!packet) {
-			hw->tx_queued = 0;
-			spin_unlock_irqrestore(&hw->lock, flags);
-			return 0;
-		}
-
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		/* Send */
-		do_send_packet(hw, packet);
-
-		/* Check if more to send */
-		spin_lock_irqsave(&hw->lock, flags);
-		for (priority = 0; priority < priority_limit; priority++)
-			if (!list_empty(&hw->tx_queue[priority])) {
-				more_to_send = 1;
-				break;
-			}
-
-		if (!more_to_send)
-			hw->tx_queued = 0;
-	}
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	return more_to_send;
-}
-
-/*
- * Send and receive all queued packets.
- */
-static void ipwireless_do_tasklet(unsigned long hw_)
-{
-	struct ipw_hardware *hw = (struct ipw_hardware *) hw_;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	if (hw->shutting_down) {
-		spin_unlock_irqrestore(&hw->lock, flags);
-		return;
-	}
-
-	if (hw->to_setup == 1) {
-		/*
-		 * Initial setup data sent to hardware
-		 */
-		hw->to_setup = 2;
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		ipw_setup_hardware(hw);
-		ipw_send_setup_packet(hw);
-
-		send_pending_packet(hw, PRIO_SETUP + 1);
-		get_packets_from_hw(hw);
-	} else {
-		int priority_limit = get_current_packet_priority(hw);
-		int again;
-
-		spin_unlock_irqrestore(&hw->lock, flags);
-
-		do {
-			again = send_pending_packet(hw, priority_limit);
-			again |= get_packets_from_hw(hw);
-		} while (again);
-	}
-}
-
-/*
- * return true if the card is physically present.
- */
-static int is_card_present(struct ipw_hardware *hw)
-{
-	if (hw->hw_version == HW_VERSION_1)
-		return inw(hw->base_port + IOIR) != 0xFFFF;
-	else
-		return readl(&hw->memory_info_regs->memreg_card_present) ==
-		    CARD_PRESENT_VALUE;
-}
-
-static irqreturn_t ipwireless_handle_v1_interrupt(int irq,
-						  struct ipw_hardware *hw)
-{
-	unsigned short irqn;
-
-	irqn = inw(hw->base_port + IOIR);
-
-	/* Check if card is present */
-	if (irqn == 0xFFFF)
-		return IRQ_NONE;
-	else if (irqn != 0) {
-		unsigned short ack = 0;
-		unsigned long flags;
-
-		/* Transmit complete. */
-		if (irqn & IR_TXINTR) {
-			ack |= IR_TXINTR;
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->tx_ready = 1;
-			spin_unlock_irqrestore(&hw->lock, flags);
-		}
-		/* Received data */
-		if (irqn & IR_RXINTR) {
-			ack |= IR_RXINTR;
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->rx_ready++;
-			spin_unlock_irqrestore(&hw->lock, flags);
-		}
-		if (ack != 0) {
-			outw(ack, hw->base_port + IOIR);
-			tasklet_schedule(&hw->tasklet);
-		}
-		return IRQ_HANDLED;
-	}
-	return IRQ_NONE;
-}
-
-static void acknowledge_pcmcia_interrupt(struct ipw_hardware *hw)
-{
-	unsigned short csr = readw(&hw->memregs_CCR->reg_config_and_status);
-
-	csr &= 0xfffd;
-	writew(csr, &hw->memregs_CCR->reg_config_and_status);
-}
-
-static irqreturn_t ipwireless_handle_v2_v3_interrupt(int irq,
-						     struct ipw_hardware *hw)
-{
-	int tx = 0;
-	int rx = 0;
-	int rx_repeat = 0;
-	int try_mem_tx_old;
-	unsigned long flags;
-
-	do {
-
-	unsigned short memtx = readw(hw->memreg_tx);
-	unsigned short memtx_serial;
-	unsigned short memrxdone =
-		readw(&hw->memory_info_regs->memreg_rx_done);
-
-	try_mem_tx_old = 0;
-
-	/* check whether the interrupt was generated by ipwireless card */
-	if (!(memtx & MEMTX_TX) && !(memrxdone & MEMRX_RX_DONE)) {
-
-		/* check if the card uses memreg_tx_old register */
-		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
-			memtx = readw(&hw->memory_info_regs->memreg_tx_old);
-			if (memtx & MEMTX_TX) {
-				printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-					": Using memreg_tx_old\n");
-				hw->memreg_tx =
-					&hw->memory_info_regs->memreg_tx_old;
-			} else {
-				return IRQ_NONE;
-			}
-		} else
-			return IRQ_NONE;
-	}
-
-	/*
-	 * See if the card is physically present. Note that while it is
-	 * powering up, it appears not to be present.
-	 */
-	if (!is_card_present(hw)) {
-		acknowledge_pcmcia_interrupt(hw);
-		return IRQ_HANDLED;
-	}
-
-	memtx_serial = memtx & (unsigned short) 0xff00;
-	if (memtx & MEMTX_TX) {
-		writew(memtx_serial, hw->memreg_tx);
-
-		if (hw->serial_number_detected) {
-			if (memtx_serial != hw->last_memtx_serial) {
-				hw->last_memtx_serial = memtx_serial;
-				spin_lock_irqsave(&hw->lock, flags);
-				hw->rx_ready++;
-				spin_unlock_irqrestore(&hw->lock, flags);
-				rx = 1;
-			} else
-				/* Ignore 'Timer Recovery' duplicates. */
-				rx_repeat = 1;
-		} else {
-			/*
-			 * If a non-zero serial number is seen, then enable
-			 * serial number checking.
-			 */
-			if (memtx_serial != 0) {
-				hw->serial_number_detected = 1;
-				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-					": memreg_tx serial num detected\n");
-
-				spin_lock_irqsave(&hw->lock, flags);
-				hw->rx_ready++;
-				spin_unlock_irqrestore(&hw->lock, flags);
-			}
-			rx = 1;
-		}
-	}
-	if (memrxdone & MEMRX_RX_DONE) {
-		writew(0, &hw->memory_info_regs->memreg_rx_done);
-		spin_lock_irqsave(&hw->lock, flags);
-		hw->tx_ready = 1;
-		spin_unlock_irqrestore(&hw->lock, flags);
-		tx = 1;
-	}
-	if (tx)
-		writew(MEMRX_PCINTACKK,
-				&hw->memory_info_regs->memreg_pc_interrupt_ack);
-
-	acknowledge_pcmcia_interrupt(hw);
-
-	if (tx || rx)
-		tasklet_schedule(&hw->tasklet);
-	else if (!rx_repeat) {
-		if (hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
-			if (hw->serial_number_detected)
-				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": spurious interrupt - new_tx mode\n");
-			else {
-				printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": no valid memreg_tx value - switching to the old memreg_tx\n");
-				hw->memreg_tx =
-					&hw->memory_info_regs->memreg_tx_old;
-				try_mem_tx_old = 1;
-			}
-		} else
-			printk(KERN_WARNING IPWIRELESS_PCCARD_NAME
-					": spurious interrupt - old_tx mode\n");
-	}
-
-	} while (try_mem_tx_old == 1);
-
-	return IRQ_HANDLED;
-}
-
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id)
-{
-	struct ipw_dev *ipw = dev_id;
-
-	if (ipw->hardware->hw_version == HW_VERSION_1)
-		return ipwireless_handle_v1_interrupt(irq, ipw->hardware);
-	else
-		return ipwireless_handle_v2_v3_interrupt(irq, ipw->hardware);
-}
-
-static void flush_packets_to_hw(struct ipw_hardware *hw)
-{
-	int priority_limit;
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	priority_limit = get_current_packet_priority(hw);
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	while (send_pending_packet(hw, priority_limit));
-}
-
-static void send_packet(struct ipw_hardware *hw, int priority,
-			struct ipw_tx_packet *packet)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&hw->lock, flags);
-	list_add_tail(&packet->queue, &hw->tx_queue[priority]);
-	hw->tx_queued++;
-	spin_unlock_irqrestore(&hw->lock, flags);
-
-	flush_packets_to_hw(hw);
-}
-
-/* Create data packet, non-atomic allocation */
-static void *alloc_data_packet(int data_size,
-				unsigned char dest_addr,
-				unsigned char protocol)
-{
-	struct ipw_tx_packet *packet = kzalloc(
-			sizeof(struct ipw_tx_packet) + data_size,
-			GFP_ATOMIC);
-
-	if (!packet)
-		return NULL;
-
-	INIT_LIST_HEAD(&packet->queue);
-	packet->dest_addr = dest_addr;
-	packet->protocol = protocol;
-	packet->length = data_size;
-
-	return packet;
-}
-
-static void *alloc_ctrl_packet(int header_size,
-			       unsigned char dest_addr,
-			       unsigned char protocol,
-			       unsigned char sig_no)
-{
-	/*
-	 * sig_no is located right after ipw_tx_packet struct in every
-	 * CTRL or SETUP packets, we can use ipw_control_packet as a
-	 * common struct
-	 */
-	struct ipw_control_packet *packet = kzalloc(header_size, GFP_ATOMIC);
-
-	if (!packet)
-		return NULL;
-
-	INIT_LIST_HEAD(&packet->header.queue);
-	packet->header.dest_addr = dest_addr;
-	packet->header.protocol = protocol;
-	packet->header.length = header_size - sizeof(struct ipw_tx_packet);
-	packet->body.sig_no = sig_no;
-
-	return packet;
-}
-
-int ipwireless_send_packet(struct ipw_hardware *hw, unsigned int channel_idx,
-			    const unsigned char *data, unsigned int length,
-			    void (*callback) (void *cb, unsigned int length),
-			    void *callback_data)
-{
-	struct ipw_tx_packet *packet;
-
-	packet = alloc_data_packet(length, (channel_idx + 1),
-			TL_PROTOCOLID_COM_DATA);
-	if (!packet)
-		return -ENOMEM;
-	packet->packet_callback = callback;
-	packet->callback_data = callback_data;
-	memcpy((unsigned char *) packet + sizeof(struct ipw_tx_packet), data,
-			length);
-
-	send_packet(hw, PRIO_DATA, packet);
-	return 0;
-}
-
-static int set_control_line(struct ipw_hardware *hw, int prio,
-			   unsigned int channel_idx, int line, int state)
-{
-	struct ipw_control_packet *packet;
-	int protocolid = TL_PROTOCOLID_COM_CTRL;
-
-	if (prio == PRIO_SETUP)
-		protocolid = TL_PROTOCOLID_SETUP;
-
-	packet = alloc_ctrl_packet(sizeof(struct ipw_control_packet),
-			(channel_idx + 1), protocolid, line);
-	if (!packet)
-		return -ENOMEM;
-	packet->header.length = sizeof(struct ipw_control_packet_body);
-	packet->body.value = (state == 0 ? 0 : 1);
-	send_packet(hw, prio, &packet->header);
-	return 0;
-}
-
-
-static int set_DTR(struct ipw_hardware *hw, int priority,
-		   unsigned int channel_idx, int state)
-{
-	if (state != 0)
-		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_DTR;
-	else
-		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_DTR;
-
-	return set_control_line(hw, priority, channel_idx, COMCTRL_DTR, state);
-}
-
-static int set_RTS(struct ipw_hardware *hw, int priority,
-		   unsigned int channel_idx, int state)
-{
-	if (state != 0)
-		hw->control_lines[channel_idx] |= IPW_CONTROL_LINE_RTS;
-	else
-		hw->control_lines[channel_idx] &= ~IPW_CONTROL_LINE_RTS;
-
-	return set_control_line(hw, priority, channel_idx, COMCTRL_RTS, state);
-}
-
-int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
-		       int state)
-{
-	return set_DTR(hw, PRIO_CTRL, channel_idx, state);
-}
-
-int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
-		       int state)
-{
-	return set_RTS(hw, PRIO_CTRL, channel_idx, state);
-}
-
-struct ipw_setup_get_version_query_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_get_version_qry body;
-};
-
-struct ipw_setup_config_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_config_msg body;
-};
-
-struct ipw_setup_config_done_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_config_done_msg body;
-};
-
-struct ipw_setup_open_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_open_msg body;
-};
-
-struct ipw_setup_info_packet {
-	struct ipw_tx_packet header;
-	struct tl_setup_info_msg body;
-};
-
-struct ipw_setup_reboot_msg_ack {
-	struct ipw_tx_packet header;
-	struct TlSetupRebootMsgAck body;
-};
-
-/* This handles the actual initialization of the card */
-static void __handle_setup_get_version_rsp(struct ipw_hardware *hw)
-{
-	struct ipw_setup_config_packet *config_packet;
-	struct ipw_setup_config_done_packet *config_done_packet;
-	struct ipw_setup_open_packet *open_packet;
-	struct ipw_setup_info_packet *info_packet;
-	int port;
-	unsigned int channel_idx;
-
-	/* generate config packet */
-	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
-		config_packet = alloc_ctrl_packet(
-				sizeof(struct ipw_setup_config_packet),
-				ADDR_SETUP_PROT,
-				TL_PROTOCOLID_SETUP,
-				TL_SETUP_SIGNO_CONFIG_MSG);
-		if (!config_packet)
-			goto exit_nomem;
-		config_packet->header.length = sizeof(struct tl_setup_config_msg);
-		config_packet->body.port_no = port;
-		config_packet->body.prio_data = PRIO_DATA;
-		config_packet->body.prio_ctrl = PRIO_CTRL;
-		send_packet(hw, PRIO_SETUP, &config_packet->header);
-	}
-	config_done_packet = alloc_ctrl_packet(
-			sizeof(struct ipw_setup_config_done_packet),
-			ADDR_SETUP_PROT,
-			TL_PROTOCOLID_SETUP,
-			TL_SETUP_SIGNO_CONFIG_DONE_MSG);
-	if (!config_done_packet)
-		goto exit_nomem;
-	config_done_packet->header.length = sizeof(struct tl_setup_config_done_msg);
-	send_packet(hw, PRIO_SETUP, &config_done_packet->header);
-
-	/* generate open packet */
-	for (port = 1; port <= NL_NUM_OF_ADDRESSES; port++) {
-		open_packet = alloc_ctrl_packet(
-				sizeof(struct ipw_setup_open_packet),
-				ADDR_SETUP_PROT,
-				TL_PROTOCOLID_SETUP,
-				TL_SETUP_SIGNO_OPEN_MSG);
-		if (!open_packet)
-			goto exit_nomem;
-		open_packet->header.length = sizeof(struct tl_setup_open_msg);
-		open_packet->body.port_no = port;
-		send_packet(hw, PRIO_SETUP, &open_packet->header);
-	}
-	for (channel_idx = 0;
-			channel_idx < NL_NUM_OF_ADDRESSES; channel_idx++) {
-		int ret;
-
-		ret = set_DTR(hw, PRIO_SETUP, channel_idx,
-			(hw->control_lines[channel_idx] &
-			 IPW_CONTROL_LINE_DTR) != 0);
-		if (ret) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-					": error setting DTR (%d)\n", ret);
-			return;
-		}
-
-		set_RTS(hw, PRIO_SETUP, channel_idx,
-			(hw->control_lines [channel_idx] &
-			 IPW_CONTROL_LINE_RTS) != 0);
-		if (ret) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-					": error setting RTS (%d)\n", ret);
-			return;
-		}
-	}
-	/*
-	 * For NDIS we assume that we are using sync PPP frames, for COM async.
-	 * This driver uses NDIS mode too. We don't bother with translation
-	 * from async -> sync PPP.
-	 */
-	info_packet = alloc_ctrl_packet(sizeof(struct ipw_setup_info_packet),
-			ADDR_SETUP_PROT,
-			TL_PROTOCOLID_SETUP,
-			TL_SETUP_SIGNO_INFO_MSG);
-	if (!info_packet)
-		goto exit_nomem;
-	info_packet->header.length = sizeof(struct tl_setup_info_msg);
-	info_packet->body.driver_type = NDISWAN_DRIVER;
-	info_packet->body.major_version = NDISWAN_DRIVER_MAJOR_VERSION;
-	info_packet->body.minor_version = NDISWAN_DRIVER_MINOR_VERSION;
-	send_packet(hw, PRIO_SETUP, &info_packet->header);
-
-	/* Initialization is now complete, so we clear the 'to_setup' flag */
-	hw->to_setup = 0;
-
-	return;
-
-exit_nomem:
-	printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-			": not enough memory to alloc control packet\n");
-	hw->to_setup = -1;
-}
-
-static void handle_setup_get_version_rsp(struct ipw_hardware *hw,
-		unsigned char vers_no)
-{
-	del_timer(&hw->setup_timer);
-	hw->initializing = 0;
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": card is ready.\n");
-
-	if (vers_no == TL_SETUP_VERSION)
-		__handle_setup_get_version_rsp(hw);
-	else
-		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-				": invalid hardware version no %u\n",
-				(unsigned int) vers_no);
-}
-
-static void ipw_send_setup_packet(struct ipw_hardware *hw)
-{
-	struct ipw_setup_get_version_query_packet *ver_packet;
-
-	ver_packet = alloc_ctrl_packet(
-			sizeof(struct ipw_setup_get_version_query_packet),
-			ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
-			TL_SETUP_SIGNO_GET_VERSION_QRY);
-	ver_packet->header.length = sizeof(struct tl_setup_get_version_qry);
-
-	/*
-	 * Response is handled in handle_received_SETUP_packet
-	 */
-	send_packet(hw, PRIO_SETUP, &ver_packet->header);
-}
-
-static void handle_received_SETUP_packet(struct ipw_hardware *hw,
-					 unsigned int address,
-					 const unsigned char *data, int len,
-					 int is_last)
-{
-	const union ipw_setup_rx_msg *rx_msg = (const union ipw_setup_rx_msg *) data;
-
-	if (address != ADDR_SETUP_PROT) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": setup packet has bad address %d\n", address);
-		return;
-	}
-
-	switch (rx_msg->sig_no) {
-	case TL_SETUP_SIGNO_GET_VERSION_RSP:
-		if (hw->to_setup)
-			handle_setup_get_version_rsp(hw,
-					rx_msg->version_rsp_msg.version);
-		break;
-
-	case TL_SETUP_SIGNO_OPEN_MSG:
-		if (ipwireless_debug) {
-			unsigned int channel_idx = rx_msg->open_msg.port_no - 1;
-
-			printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			       ": OPEN_MSG [channel %u] reply received\n",
-			       channel_idx);
-		}
-		break;
-
-	case TL_SETUP_SIGNO_INFO_MSG_ACK:
-		if (ipwireless_debug)
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-			       ": card successfully configured as NDISWAN\n");
-		break;
-
-	case TL_SETUP_SIGNO_REBOOT_MSG:
-		if (hw->to_setup)
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-			       ": Setup not completed - ignoring reboot msg\n");
-		else {
-			struct ipw_setup_reboot_msg_ack *packet;
-
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-			       ": Acknowledging REBOOT message\n");
-			packet = alloc_ctrl_packet(
-					sizeof(struct ipw_setup_reboot_msg_ack),
-					ADDR_SETUP_PROT, TL_PROTOCOLID_SETUP,
-					TL_SETUP_SIGNO_REBOOT_MSG_ACK);
-			packet->header.length =
-				sizeof(struct TlSetupRebootMsgAck);
-			send_packet(hw, PRIO_SETUP, &packet->header);
-			if (hw->reboot_callback)
-				hw->reboot_callback(hw->reboot_callback_data);
-		}
-		break;
-
-	default:
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": unknown setup message %u received\n",
-		       (unsigned int) rx_msg->sig_no);
-	}
-}
-
-static void do_close_hardware(struct ipw_hardware *hw)
-{
-	unsigned int irqn;
-
-	if (hw->hw_version == HW_VERSION_1) {
-		/* Disable TX and RX interrupts. */
-		outw(0, hw->base_port + IOIER);
-
-		/* Acknowledge any outstanding interrupt requests */
-		irqn = inw(hw->base_port + IOIR);
-		if (irqn & IR_TXINTR)
-			outw(IR_TXINTR, hw->base_port + IOIR);
-		if (irqn & IR_RXINTR)
-			outw(IR_RXINTR, hw->base_port + IOIR);
-
-		synchronize_irq(hw->irq);
-	}
-}
-
-struct ipw_hardware *ipwireless_hardware_create(void)
-{
-	int i;
-	struct ipw_hardware *hw =
-		kzalloc(sizeof(struct ipw_hardware), GFP_KERNEL);
-
-	if (!hw)
-		return NULL;
-
-	hw->irq = -1;
-	hw->initializing = 1;
-	hw->tx_ready = 1;
-	hw->rx_bytes_queued = 0;
-	hw->rx_pool_size = 0;
-	hw->last_memtx_serial = (unsigned short) 0xffff;
-	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
-		INIT_LIST_HEAD(&hw->tx_queue[i]);
-
-	INIT_LIST_HEAD(&hw->rx_queue);
-	INIT_LIST_HEAD(&hw->rx_pool);
-	spin_lock_init(&hw->lock);
-	tasklet_init(&hw->tasklet, ipwireless_do_tasklet, (unsigned long) hw);
-	INIT_WORK(&hw->work_rx, ipw_receive_data_work);
-	setup_timer(&hw->setup_timer, ipwireless_setup_timer,
-			(unsigned long) hw);
-
-	return hw;
-}
-
-void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
-		unsigned int base_port,
-		void __iomem *attr_memory,
-		void __iomem *common_memory,
-		int is_v2_card,
-		void (*reboot_callback) (void *data),
-		void *reboot_callback_data)
-{
-	if (hw->removed) {
-		hw->removed = 0;
-		enable_irq(hw->irq);
-	}
-	hw->base_port = base_port;
-	hw->hw_version = (is_v2_card ? HW_VERSION_2 : HW_VERSION_1);
-	hw->ll_mtu = (hw->hw_version == HW_VERSION_1 ? LL_MTU_V1 : LL_MTU_V2);
-	hw->memregs_CCR = (struct MEMCCR __iomem *)
-			((unsigned short __iomem *) attr_memory + 0x200);
-	hw->memory_info_regs = (struct MEMINFREG __iomem *) common_memory;
-	hw->memreg_tx = &hw->memory_info_regs->memreg_tx_new;
-	hw->reboot_callback = reboot_callback;
-	hw->reboot_callback_data = reboot_callback_data;
-}
-
-void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw)
-{
-	hw->initializing = 1;
-	hw->init_loops = 0;
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-	       ": waiting for card to start up...\n");
-	ipwireless_setup_timer((unsigned long) hw);
-}
-
-static void ipwireless_setup_timer(unsigned long data)
-{
-	struct ipw_hardware *hw = (struct ipw_hardware *) data;
-
-	hw->init_loops++;
-
-	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY &&
-			hw->hw_version == HW_VERSION_2 &&
-			hw->memreg_tx == &hw->memory_info_regs->memreg_tx_new) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-				": failed to startup using TX2, trying TX\n");
-
-		hw->memreg_tx = &hw->memory_info_regs->memreg_tx_old;
-		hw->init_loops = 0;
-	}
-	/* Give up after a certain number of retries */
-	if (hw->init_loops == TL_SETUP_MAX_VERSION_QRY) {
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		       ": card failed to start up!\n");
-		hw->initializing = 0;
-	} else {
-		/* Do not attempt to write to the board if it is not present. */
-		if (is_card_present(hw)) {
-			unsigned long flags;
-
-			spin_lock_irqsave(&hw->lock, flags);
-			hw->to_setup = 1;
-			hw->tx_ready = 1;
-			spin_unlock_irqrestore(&hw->lock, flags);
-			tasklet_schedule(&hw->tasklet);
-		}
-
-		mod_timer(&hw->setup_timer,
-			jiffies + msecs_to_jiffies(TL_SETUP_VERSION_QRY_TMO));
-	}
-}
-
-/*
- * Stop any interrupts from executing so that, once this function returns,
- * other layers of the driver can be sure they won't get any more callbacks.
- * Thus must be called on a proper process context.
- */
-void ipwireless_stop_interrupts(struct ipw_hardware *hw)
-{
-	if (!hw->shutting_down) {
-		/* Tell everyone we are going down. */
-		hw->shutting_down = 1;
-		del_timer(&hw->setup_timer);
-
-		/* Prevent the hardware from sending any more interrupts */
-		do_close_hardware(hw);
-	}
-}
-
-void ipwireless_hardware_free(struct ipw_hardware *hw)
-{
-	int i;
-	struct ipw_rx_packet *rp, *rq;
-	struct ipw_tx_packet *tp, *tq;
-
-	ipwireless_stop_interrupts(hw);
-
-	flush_work_sync(&hw->work_rx);
-
-	for (i = 0; i < NL_NUM_OF_ADDRESSES; i++)
-		if (hw->packet_assembler[i] != NULL)
-			kfree(hw->packet_assembler[i]);
-
-	for (i = 0; i < NL_NUM_OF_PRIORITIES; i++)
-		list_for_each_entry_safe(tp, tq, &hw->tx_queue[i], queue) {
-			list_del(&tp->queue);
-			kfree(tp);
-		}
-
-	list_for_each_entry_safe(rp, rq, &hw->rx_queue, queue) {
-		list_del(&rp->queue);
-		kfree(rp);
-	}
-
-	list_for_each_entry_safe(rp, rq, &hw->rx_pool, queue) {
-		list_del(&rp->queue);
-		kfree(rp);
-	}
-	kfree(hw);
-}
-
-/*
- * Associate the specified network with this hardware, so it will receive events
- * from it.
- */
-void ipwireless_associate_network(struct ipw_hardware *hw,
-				  struct ipw_network *network)
-{
-	hw->network = network;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/hardware.h linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/hardware.h
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/hardware.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/hardware.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,62 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_HARDWARE_H_
-#define _IPWIRELESS_CS_HARDWARE_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-#include <linux/interrupt.h>
-
-#define IPW_CONTROL_LINE_CTS 0x0001
-#define IPW_CONTROL_LINE_DCD 0x0002
-#define IPW_CONTROL_LINE_DSR 0x0004
-#define IPW_CONTROL_LINE_RI  0x0008
-#define IPW_CONTROL_LINE_DTR 0x0010
-#define IPW_CONTROL_LINE_RTS 0x0020
-
-struct ipw_hardware;
-struct ipw_network;
-
-struct ipw_hardware *ipwireless_hardware_create(void);
-void ipwireless_hardware_free(struct ipw_hardware *hw);
-irqreturn_t ipwireless_interrupt(int irq, void *dev_id);
-int ipwireless_set_DTR(struct ipw_hardware *hw, unsigned int channel_idx,
-		int state);
-int ipwireless_set_RTS(struct ipw_hardware *hw, unsigned int channel_idx,
-		int state);
-int ipwireless_send_packet(struct ipw_hardware *hw,
-			    unsigned int channel_idx,
-			    const unsigned char *data,
-			    unsigned int length,
-			    void (*packet_sent_callback) (void *cb,
-							  unsigned int length),
-			    void *sent_cb_data);
-void ipwireless_associate_network(struct ipw_hardware *hw,
-		struct ipw_network *net);
-void ipwireless_stop_interrupts(struct ipw_hardware *hw);
-void ipwireless_init_hardware_v1(struct ipw_hardware *hw,
-				 unsigned int base_port,
-				 void __iomem *attr_memory,
-				 void __iomem *common_memory,
-				 int is_v2_card,
-				 void (*reboot_cb) (void *data),
-				 void *reboot_cb_data);
-void ipwireless_init_hardware_v2_v3(struct ipw_hardware *hw);
-void ipwireless_sleep(unsigned int tenths);
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/main.c linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/main.c
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/main.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,347 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include "hardware.h"
-#include "network.h"
-#include "main.h"
-#include "tty.h"
-
-#include <linux/delay.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include <pcmcia/cisreg.h>
-#include <pcmcia/device_id.h>
-#include <pcmcia/ss.h>
-#include <pcmcia/ds.h>
-
-static struct pcmcia_device_id ipw_ids[] = {
-	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0100),
-	PCMCIA_DEVICE_MANF_CARD(0x02f2, 0x0200),
-	PCMCIA_DEVICE_NULL
-};
-MODULE_DEVICE_TABLE(pcmcia, ipw_ids);
-
-static void ipwireless_detach(struct pcmcia_device *link);
-
-/*
- * Module params
- */
-/* Debug mode: more verbose, print sent/recv bytes */
-int ipwireless_debug;
-int ipwireless_loopback;
-int ipwireless_out_queue = 10;
-
-module_param_named(debug, ipwireless_debug, int, 0);
-module_param_named(loopback, ipwireless_loopback, int, 0);
-module_param_named(out_queue, ipwireless_out_queue, int, 0);
-MODULE_PARM_DESC(debug, "switch on debug messages [0]");
-MODULE_PARM_DESC(loopback,
-		"debug: enable ras_raw channel [0]");
-MODULE_PARM_DESC(out_queue, "debug: set size of outgoing PPP queue [10]");
-
-/* Executes in process context. */
-static void signalled_reboot_work(struct work_struct *work_reboot)
-{
-	struct ipw_dev *ipw = container_of(work_reboot, struct ipw_dev,
-			work_reboot);
-	struct pcmcia_device *link = ipw->link;
-	pcmcia_reset_card(link->socket);
-}
-
-static void signalled_reboot_callback(void *callback_data)
-{
-	struct ipw_dev *ipw = (struct ipw_dev *) callback_data;
-
-	/* Delegate to process context. */
-	schedule_work(&ipw->work_reboot);
-}
-
-static int ipwireless_probe(struct pcmcia_device *p_dev, void *priv_data)
-{
-	struct ipw_dev *ipw = priv_data;
-	int ret;
-
-	p_dev->resource[0]->flags &= ~IO_DATA_PATH_WIDTH;
-	p_dev->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
-
-	/* 0x40 causes it to generate level mode interrupts. */
-	/* 0x04 enables IREQ pin. */
-	p_dev->config_index |= 0x44;
-	p_dev->io_lines = 16;
-	ret = pcmcia_request_io(p_dev);
-	if (ret)
-		return ret;
-
-	if (!request_region(p_dev->resource[0]->start,
-			    resource_size(p_dev->resource[0]),
-			    IPWIRELESS_PCCARD_NAME)) {
-		ret = -EBUSY;
-		goto exit;
-	}
-
-	p_dev->resource[2]->flags |=
-		WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_CM | WIN_ENABLE;
-
-	ret = pcmcia_request_window(p_dev, p_dev->resource[2], 0);
-	if (ret != 0)
-		goto exit1;
-
-	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[2], p_dev->card_addr);
-	if (ret != 0)
-		goto exit1;
-
-	ipw->is_v2_card = resource_size(p_dev->resource[2]) == 0x100;
-
-	ipw->common_memory = ioremap(p_dev->resource[2]->start,
-				resource_size(p_dev->resource[2]));
-	if (!request_mem_region(p_dev->resource[2]->start,
-				resource_size(p_dev->resource[2]),
-				IPWIRELESS_PCCARD_NAME)) {
-		ret = -EBUSY;
-		goto exit2;
-	}
-
-	p_dev->resource[3]->flags |= WIN_DATA_WIDTH_16 | WIN_MEMORY_TYPE_AM |
-					WIN_ENABLE;
-	p_dev->resource[3]->end = 0; /* this used to be 0x1000 */
-	ret = pcmcia_request_window(p_dev, p_dev->resource[3], 0);
-	if (ret != 0)
-		goto exit3;
-
-	ret = pcmcia_map_mem_page(p_dev, p_dev->resource[3], 0);
-	if (ret != 0)
-		goto exit3;
-
-	ipw->attr_memory = ioremap(p_dev->resource[3]->start,
-				resource_size(p_dev->resource[3]));
-	if (!request_mem_region(p_dev->resource[3]->start,
-				resource_size(p_dev->resource[3]),
-				IPWIRELESS_PCCARD_NAME)) {
-		ret = -EBUSY;
-		goto exit4;
-	}
-
-	return 0;
-
-exit4:
-	iounmap(ipw->attr_memory);
-exit3:
-	release_mem_region(p_dev->resource[2]->start,
-			resource_size(p_dev->resource[2]));
-exit2:
-	iounmap(ipw->common_memory);
-exit1:
-	release_region(p_dev->resource[0]->start,
-		       resource_size(p_dev->resource[0]));
-exit:
-	pcmcia_disable_device(p_dev);
-	return ret;
-}
-
-static int config_ipwireless(struct ipw_dev *ipw)
-{
-	struct pcmcia_device *link = ipw->link;
-	int ret = 0;
-
-	ipw->is_v2_card = 0;
-	link->config_flags |= CONF_AUTO_SET_IO | CONF_AUTO_SET_IOMEM |
-		CONF_ENABLE_IRQ;
-
-	ret = pcmcia_loop_config(link, ipwireless_probe, ipw);
-	if (ret != 0)
-		return ret;
-
-	INIT_WORK(&ipw->work_reboot, signalled_reboot_work);
-
-	ipwireless_init_hardware_v1(ipw->hardware, link->resource[0]->start,
-				    ipw->attr_memory, ipw->common_memory,
-				    ipw->is_v2_card, signalled_reboot_callback,
-				    ipw);
-
-	ret = pcmcia_request_irq(link, ipwireless_interrupt);
-	if (ret != 0)
-		goto exit;
-
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME ": Card type %s\n",
-			ipw->is_v2_card ? "V2/V3" : "V1");
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-		": I/O ports %pR, irq %d\n", link->resource[0],
-			(unsigned int) link->irq);
-	if (ipw->attr_memory && ipw->common_memory)
-		printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-			": attr memory %pR, common memory %pR\n",
-			link->resource[3],
-			link->resource[2]);
-
-	ipw->network = ipwireless_network_create(ipw->hardware);
-	if (!ipw->network)
-		goto exit;
-
-	ipw->tty = ipwireless_tty_create(ipw->hardware, ipw->network);
-	if (!ipw->tty)
-		goto exit;
-
-	ipwireless_init_hardware_v2_v3(ipw->hardware);
-
-	/*
-	 * Do the RequestConfiguration last, because it enables interrupts.
-	 * Then we don't get any interrupts before we're ready for them.
-	 */
-	ret = pcmcia_enable_device(link);
-	if (ret != 0)
-		goto exit;
-
-	return 0;
-
-exit:
-	if (ipw->common_memory) {
-		release_mem_region(link->resource[2]->start,
-				resource_size(link->resource[2]));
-		iounmap(ipw->common_memory);
-	}
-	if (ipw->attr_memory) {
-		release_mem_region(link->resource[3]->start,
-				resource_size(link->resource[3]));
-		iounmap(ipw->attr_memory);
-	}
-	pcmcia_disable_device(link);
-	return -1;
-}
-
-static void release_ipwireless(struct ipw_dev *ipw)
-{
-	release_region(ipw->link->resource[0]->start,
-		       resource_size(ipw->link->resource[0]));
-	if (ipw->common_memory) {
-		release_mem_region(ipw->link->resource[2]->start,
-				resource_size(ipw->link->resource[2]));
-		iounmap(ipw->common_memory);
-	}
-	if (ipw->attr_memory) {
-		release_mem_region(ipw->link->resource[3]->start,
-				resource_size(ipw->link->resource[3]));
-		iounmap(ipw->attr_memory);
-	}
-	pcmcia_disable_device(ipw->link);
-}
-
-/*
- * ipwireless_attach() creates an "instance" of the driver, allocating
- * local data structures for one device (one interface).  The device
- * is registered with Card Services.
- *
- * The pcmcia_device structure is initialized, but we don't actually
- * configure the card at this point -- we wait until we receive a
- * card insertion event.
- */
-static int ipwireless_attach(struct pcmcia_device *link)
-{
-	struct ipw_dev *ipw;
-	int ret;
-
-	ipw = kzalloc(sizeof(struct ipw_dev), GFP_KERNEL);
-	if (!ipw)
-		return -ENOMEM;
-
-	ipw->link = link;
-	link->priv = ipw;
-
-	ipw->hardware = ipwireless_hardware_create();
-	if (!ipw->hardware) {
-		kfree(ipw);
-		return -ENOMEM;
-	}
-	/* RegisterClient will call config_ipwireless */
-
-	ret = config_ipwireless(ipw);
-
-	if (ret != 0) {
-		ipwireless_detach(link);
-		return ret;
-	}
-
-	return 0;
-}
-
-/*
- * This deletes a driver "instance".  The device is de-registered with
- * Card Services.  If it has been released, all local data structures
- * are freed.  Otherwise, the structures will be freed when the device
- * is released.
- */
-static void ipwireless_detach(struct pcmcia_device *link)
-{
-	struct ipw_dev *ipw = link->priv;
-
-	release_ipwireless(ipw);
-
-	if (ipw->tty != NULL)
-		ipwireless_tty_free(ipw->tty);
-	if (ipw->network != NULL)
-		ipwireless_network_free(ipw->network);
-	if (ipw->hardware != NULL)
-		ipwireless_hardware_free(ipw->hardware);
-	kfree(ipw);
-}
-
-static struct pcmcia_driver me = {
-	.owner		= THIS_MODULE,
-	.probe          = ipwireless_attach,
-	.remove         = ipwireless_detach,
-	.name		= IPWIRELESS_PCCARD_NAME,
-	.id_table       = ipw_ids
-};
-
-/*
- * Module insertion : initialisation of the module.
- * Register the card with cardmgr...
- */
-static int __init init_ipwireless(void)
-{
-	int ret;
-
-	ret = ipwireless_tty_init();
-	if (ret != 0)
-		return ret;
-
-	ret = pcmcia_register_driver(&me);
-	if (ret != 0)
-		ipwireless_tty_release();
-
-	return ret;
-}
-
-/*
- * Module removal
- */
-static void __exit exit_ipwireless(void)
-{
-	pcmcia_unregister_driver(&me);
-	ipwireless_tty_release();
-}
-
-module_init(init_ipwireless);
-module_exit(exit_ipwireless);
-
-MODULE_AUTHOR(IPWIRELESS_PCMCIA_AUTHOR);
-MODULE_DESCRIPTION(IPWIRELESS_PCCARD_NAME " " IPWIRELESS_PCMCIA_VERSION);
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/main.h linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/main.h
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/main.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/main.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,68 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_H_
-#define _IPWIRELESS_CS_H_
-
-#include <linux/sched.h>
-#include <linux/types.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-#include "hardware.h"
-
-#define IPWIRELESS_PCCARD_NAME		"ipwireless"
-#define IPWIRELESS_PCMCIA_VERSION	"1.1"
-#define IPWIRELESS_PCMCIA_AUTHOR        \
-	"Stephen Blackheath, Ben Martel, Jiri Kosina and David Sterba"
-
-#define IPWIRELESS_TX_QUEUE_SIZE  262144
-#define IPWIRELESS_RX_QUEUE_SIZE  262144
-
-#define IPWIRELESS_STATE_DEBUG
-
-struct ipw_hardware;
-struct ipw_network;
-struct ipw_tty;
-
-struct ipw_dev {
-	struct pcmcia_device *link;
-	int is_v2_card;
-
-	void __iomem *attr_memory;
-
-	void __iomem *common_memory;
-
-	/* Reference to attribute memory, containing CIS data */
-	void *attribute_memory;
-
-	/* Hardware context */
-	struct ipw_hardware *hardware;
-	/* Network layer context */
-	struct ipw_network *network;
-	/* TTY device context */
-	struct ipw_tty *tty;
-	struct work_struct work_reboot;
-};
-
-/* Module parametres */
-extern int ipwireless_debug;
-extern int ipwireless_loopback;
-extern int ipwireless_out_queue;
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/Makefile linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,10 +0,0 @@
-#
-# drivers/char/pcmcia/ipwireless/Makefile
-#
-# Makefile for the IPWireless driver
-#
-
-obj-$(CONFIG_IPWIRELESS) += ipwireless.o
-
-ipwireless-y := hardware.o main.o network.o tty.o
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/network.c linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/network.c
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/network.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/network.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,508 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/netdevice.h>
-#include <linux/ppp_channel.h>
-#include <linux/ppp_defs.h>
-#include <linux/slab.h>
-#include <linux/if_ppp.h>
-#include <linux/skbuff.h>
-
-#include "network.h"
-#include "hardware.h"
-#include "main.h"
-#include "tty.h"
-
-#define MAX_ASSOCIATED_TTYS 2
-
-#define SC_RCV_BITS     (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
-
-struct ipw_network {
-	/* Hardware context, used for calls to hardware layer. */
-	struct ipw_hardware *hardware;
-	/* Context for kernel 'generic_ppp' functionality */
-	struct ppp_channel *ppp_channel;
-	/* tty context connected with IPW console */
-	struct ipw_tty *associated_ttys[NO_OF_IPW_CHANNELS][MAX_ASSOCIATED_TTYS];
-	/* True if ppp needs waking up once we're ready to xmit */
-	int ppp_blocked;
-	/* Number of packets queued up in hardware module. */
-	int outgoing_packets_queued;
-	/* Spinlock to avoid interrupts during shutdown */
-	spinlock_t lock;
-	struct mutex close_lock;
-
-	/* PPP ioctl data, not actually used anywere */
-	unsigned int flags;
-	unsigned int rbits;
-	u32 xaccm[8];
-	u32 raccm;
-	int mru;
-
-	int shutting_down;
-	unsigned int ras_control_lines;
-
-	struct work_struct work_go_online;
-	struct work_struct work_go_offline;
-};
-
-static void notify_packet_sent(void *callback_data, unsigned int packet_length)
-{
-	struct ipw_network *network = callback_data;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	network->outgoing_packets_queued--;
-	if (network->ppp_channel != NULL) {
-		if (network->ppp_blocked) {
-			network->ppp_blocked = 0;
-			spin_unlock_irqrestore(&network->lock, flags);
-			ppp_output_wakeup(network->ppp_channel);
-			if (ipwireless_debug)
-				printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-				       ": ppp unblocked\n");
-		} else
-			spin_unlock_irqrestore(&network->lock, flags);
-	} else
-		spin_unlock_irqrestore(&network->lock, flags);
-}
-
-/*
- * Called by the ppp system when it has a packet to send to the hardware.
- */
-static int ipwireless_ppp_start_xmit(struct ppp_channel *ppp_channel,
-				     struct sk_buff *skb)
-{
-	struct ipw_network *network = ppp_channel->private;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->outgoing_packets_queued < ipwireless_out_queue) {
-		unsigned char *buf;
-		static unsigned char header[] = {
-			PPP_ALLSTATIONS, /* 0xff */
-			PPP_UI,		 /* 0x03 */
-		};
-		int ret;
-
-		network->outgoing_packets_queued++;
-		spin_unlock_irqrestore(&network->lock, flags);
-
-		/*
-		 * If we have the requested amount of headroom in the skb we
-		 * were handed, then we can add the header efficiently.
-		 */
-		if (skb_headroom(skb) >= 2) {
-			memcpy(skb_push(skb, 2), header, 2);
-			ret = ipwireless_send_packet(network->hardware,
-					       IPW_CHANNEL_RAS, skb->data,
-					       skb->len,
-					       notify_packet_sent,
-					       network);
-			if (ret == -1) {
-				skb_pull(skb, 2);
-				return 0;
-			}
-		} else {
-			/* Otherwise (rarely) we do it inefficiently. */
-			buf = kmalloc(skb->len + 2, GFP_ATOMIC);
-			if (!buf)
-				return 0;
-			memcpy(buf + 2, skb->data, skb->len);
-			memcpy(buf, header, 2);
-			ret = ipwireless_send_packet(network->hardware,
-					       IPW_CHANNEL_RAS, buf,
-					       skb->len + 2,
-					       notify_packet_sent,
-					       network);
-			kfree(buf);
-			if (ret == -1)
-				return 0;
-		}
-		kfree_skb(skb);
-		return 1;
-	} else {
-		/*
-		 * Otherwise reject the packet, and flag that the ppp system
-		 * needs to be unblocked once we are ready to send.
-		 */
-		network->ppp_blocked = 1;
-		spin_unlock_irqrestore(&network->lock, flags);
-		if (ipwireless_debug)
-			printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": ppp blocked\n");
-		return 0;
-	}
-}
-
-/* Handle an ioctl call that has come in via ppp. (copy of ppp_async_ioctl() */
-static int ipwireless_ppp_ioctl(struct ppp_channel *ppp_channel,
-				unsigned int cmd, unsigned long arg)
-{
-	struct ipw_network *network = ppp_channel->private;
-	int err, val;
-	u32 accm[8];
-	int __user *user_arg = (int __user *) arg;
-
-	err = -EFAULT;
-	switch (cmd) {
-	case PPPIOCGFLAGS:
-		val = network->flags | network->rbits;
-		if (put_user(val, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSFLAGS:
-		if (get_user(val, user_arg))
-			break;
-		network->flags = val & ~SC_RCV_BITS;
-		network->rbits = val & SC_RCV_BITS;
-		err = 0;
-		break;
-
-	case PPPIOCGASYNCMAP:
-		if (put_user(network->xaccm[0], user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSASYNCMAP:
-		if (get_user(network->xaccm[0], user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCGRASYNCMAP:
-		if (put_user(network->raccm, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSRASYNCMAP:
-		if (get_user(network->raccm, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCGXASYNCMAP:
-		if (copy_to_user((void __user *) arg, network->xaccm,
-					sizeof(network->xaccm)))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSXASYNCMAP:
-		if (copy_from_user(accm, (void __user *) arg, sizeof(accm)))
-			break;
-		accm[2] &= ~0x40000000U;	/* can't escape 0x5e */
-		accm[3] |= 0x60000000U;	/* must escape 0x7d, 0x7e */
-		memcpy(network->xaccm, accm, sizeof(network->xaccm));
-		err = 0;
-		break;
-
-	case PPPIOCGMRU:
-		if (put_user(network->mru, user_arg))
-			break;
-		err = 0;
-		break;
-
-	case PPPIOCSMRU:
-		if (get_user(val, user_arg))
-			break;
-		if (val < PPP_MRU)
-			val = PPP_MRU;
-		network->mru = val;
-		err = 0;
-		break;
-
-	default:
-		err = -ENOTTY;
-	}
-
-	return err;
-}
-
-static const struct ppp_channel_ops ipwireless_ppp_channel_ops = {
-	.start_xmit = ipwireless_ppp_start_xmit,
-	.ioctl      = ipwireless_ppp_ioctl
-};
-
-static void do_go_online(struct work_struct *work_go_online)
-{
-	struct ipw_network *network =
-		container_of(work_go_online, struct ipw_network,
-				work_go_online);
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (!network->ppp_channel) {
-		struct ppp_channel *channel;
-
-		spin_unlock_irqrestore(&network->lock, flags);
-		channel = kzalloc(sizeof(struct ppp_channel), GFP_KERNEL);
-		if (!channel) {
-			printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-					": unable to allocate PPP channel\n");
-			return;
-		}
-		channel->private = network;
-		channel->mtu = 16384;	/* Wild guess */
-		channel->hdrlen = 2;
-		channel->ops = &ipwireless_ppp_channel_ops;
-
-		network->flags = 0;
-		network->rbits = 0;
-		network->mru = PPP_MRU;
-		memset(network->xaccm, 0, sizeof(network->xaccm));
-		network->xaccm[0] = ~0U;
-		network->xaccm[3] = 0x60000000U;
-		network->raccm = ~0U;
-		ppp_register_channel(channel);
-		spin_lock_irqsave(&network->lock, flags);
-		network->ppp_channel = channel;
-	}
-	spin_unlock_irqrestore(&network->lock, flags);
-}
-
-static void do_go_offline(struct work_struct *work_go_offline)
-{
-	struct ipw_network *network =
-		container_of(work_go_offline, struct ipw_network,
-				work_go_offline);
-	unsigned long flags;
-
-	mutex_lock(&network->close_lock);
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->ppp_channel != NULL) {
-		struct ppp_channel *channel = network->ppp_channel;
-
-		network->ppp_channel = NULL;
-		spin_unlock_irqrestore(&network->lock, flags);
-		mutex_unlock(&network->close_lock);
-		ppp_unregister_channel(channel);
-	} else {
-		spin_unlock_irqrestore(&network->lock, flags);
-		mutex_unlock(&network->close_lock);
-	}
-}
-
-void ipwireless_network_notify_control_line_change(struct ipw_network *network,
-						   unsigned int channel_idx,
-						   unsigned int control_lines,
-						   unsigned int changed_mask)
-{
-	int i;
-
-	if (channel_idx == IPW_CHANNEL_RAS)
-		network->ras_control_lines = control_lines;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
-		struct ipw_tty *tty =
-			network->associated_ttys[channel_idx][i];
-
-		/*
-		 * If it's associated with a tty (other than the RAS channel
-		 * when we're online), then send the data to that tty.  The RAS
-		 * channel's data is handled above - it always goes through
-		 * ppp_generic.
-		 */
-		if (tty)
-			ipwireless_tty_notify_control_line_change(tty,
-								  channel_idx,
-								  control_lines,
-								  changed_mask);
-	}
-}
-
-/*
- * Some versions of firmware stuff packets with 0xff 0x03 (PPP: ALLSTATIONS, UI)
- * bytes, which are required on sent packet, but not always present on received
- * packets
- */
-static struct sk_buff *ipw_packet_received_skb(unsigned char *data,
-					       unsigned int length)
-{
-	struct sk_buff *skb;
-
-	if (length > 2 && data[0] == PPP_ALLSTATIONS && data[1] == PPP_UI) {
-		length -= 2;
-		data += 2;
-	}
-
-	skb = dev_alloc_skb(length + 4);
-	skb_reserve(skb, 2);
-	memcpy(skb_put(skb, length), data, length);
-
-	return skb;
-}
-
-void ipwireless_network_packet_received(struct ipw_network *network,
-					unsigned int channel_idx,
-					unsigned char *data,
-					unsigned int length)
-{
-	int i;
-	unsigned long flags;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++) {
-		struct ipw_tty *tty = network->associated_ttys[channel_idx][i];
-
-		if (!tty)
-			continue;
-
-		/*
-		 * If it's associated with a tty (other than the RAS channel
-		 * when we're online), then send the data to that tty.  The RAS
-		 * channel's data is handled above - it always goes through
-		 * ppp_generic.
-		 */
-		if (channel_idx == IPW_CHANNEL_RAS
-				&& (network->ras_control_lines &
-					IPW_CONTROL_LINE_DCD) != 0
-				&& ipwireless_tty_is_modem(tty)) {
-			/*
-			 * If data came in on the RAS channel and this tty is
-			 * the modem tty, and we are online, then we send it to
-			 * the PPP layer.
-			 */
-			mutex_lock(&network->close_lock);
-			spin_lock_irqsave(&network->lock, flags);
-			if (network->ppp_channel != NULL) {
-				struct sk_buff *skb;
-
-				spin_unlock_irqrestore(&network->lock,
-						flags);
-
-				/* Send the data to the ppp_generic module. */
-				skb = ipw_packet_received_skb(data, length);
-				ppp_input(network->ppp_channel, skb);
-			} else
-				spin_unlock_irqrestore(&network->lock,
-						flags);
-			mutex_unlock(&network->close_lock);
-		}
-		/* Otherwise we send it out the tty. */
-		else
-			ipwireless_tty_received(tty, data, length);
-	}
-}
-
-struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw)
-{
-	struct ipw_network *network =
-		kzalloc(sizeof(struct ipw_network), GFP_ATOMIC);
-
-	if (!network)
-		return NULL;
-
-	spin_lock_init(&network->lock);
-	mutex_init(&network->close_lock);
-
-	network->hardware = hw;
-
-	INIT_WORK(&network->work_go_online, do_go_online);
-	INIT_WORK(&network->work_go_offline, do_go_offline);
-
-	ipwireless_associate_network(hw, network);
-
-	return network;
-}
-
-void ipwireless_network_free(struct ipw_network *network)
-{
-	network->shutting_down = 1;
-
-	ipwireless_ppp_close(network);
-	flush_work_sync(&network->work_go_online);
-	flush_work_sync(&network->work_go_offline);
-
-	ipwireless_stop_interrupts(network->hardware);
-	ipwireless_associate_network(network->hardware, NULL);
-
-	kfree(network);
-}
-
-void ipwireless_associate_network_tty(struct ipw_network *network,
-				      unsigned int channel_idx,
-				      struct ipw_tty *tty)
-{
-	int i;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
-		if (network->associated_ttys[channel_idx][i] == NULL) {
-			network->associated_ttys[channel_idx][i] = tty;
-			break;
-		}
-}
-
-void ipwireless_disassociate_network_ttys(struct ipw_network *network,
-					  unsigned int channel_idx)
-{
-	int i;
-
-	for (i = 0; i < MAX_ASSOCIATED_TTYS; i++)
-		network->associated_ttys[channel_idx][i] = NULL;
-}
-
-void ipwireless_ppp_open(struct ipw_network *network)
-{
-	if (ipwireless_debug)
-		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": online\n");
-	schedule_work(&network->work_go_online);
-}
-
-void ipwireless_ppp_close(struct ipw_network *network)
-{
-	/* Disconnect from the wireless network. */
-	if (ipwireless_debug)
-		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME ": offline\n");
-	schedule_work(&network->work_go_offline);
-}
-
-int ipwireless_ppp_channel_index(struct ipw_network *network)
-{
-	int ret = -1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->ppp_channel != NULL)
-		ret = ppp_channel_index(network->ppp_channel);
-	spin_unlock_irqrestore(&network->lock, flags);
-
-	return ret;
-}
-
-int ipwireless_ppp_unit_number(struct ipw_network *network)
-{
-	int ret = -1;
-	unsigned long flags;
-
-	spin_lock_irqsave(&network->lock, flags);
-	if (network->ppp_channel != NULL)
-		ret = ppp_unit_number(network->ppp_channel);
-	spin_unlock_irqrestore(&network->lock, flags);
-
-	return ret;
-}
-
-int ipwireless_ppp_mru(const struct ipw_network *network)
-{
-	return network->mru;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/network.h linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/network.h
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/network.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/network.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_NETWORK_H_
-#define _IPWIRELESS_CS_NETWORK_H_
-
-#include <linux/types.h>
-
-struct ipw_network;
-struct ipw_tty;
-struct ipw_hardware;
-
-/* Definitions of the different channels on the PCMCIA UE */
-#define IPW_CHANNEL_RAS      0
-#define IPW_CHANNEL_DIALLER  1
-#define IPW_CHANNEL_CONSOLE  2
-#define NO_OF_IPW_CHANNELS   5
-
-void ipwireless_network_notify_control_line_change(struct ipw_network *net,
-		unsigned int channel_idx, unsigned int control_lines,
-		unsigned int control_mask);
-void ipwireless_network_packet_received(struct ipw_network *net,
-		unsigned int channel_idx, unsigned char *data,
-		unsigned int length);
-struct ipw_network *ipwireless_network_create(struct ipw_hardware *hw);
-void ipwireless_network_free(struct ipw_network *net);
-void ipwireless_associate_network_tty(struct ipw_network *net,
-		unsigned int channel_idx, struct ipw_tty *tty);
-void ipwireless_disassociate_network_ttys(struct ipw_network *net,
-		unsigned int channel_idx);
-
-void ipwireless_ppp_open(struct ipw_network *net);
-
-void ipwireless_ppp_close(struct ipw_network *net);
-int ipwireless_ppp_channel_index(struct ipw_network *net);
-int ipwireless_ppp_unit_number(struct ipw_network *net);
-int ipwireless_ppp_mru(const struct ipw_network *net);
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/setup_protocol.h linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/setup_protocol.h
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/setup_protocol.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/setup_protocol.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,108 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_SETUP_PROTOCOL_H_
-#define _IPWIRELESS_CS_SETUP_PROTOCOL_H_
-
-/* Version of the setup protocol and transport protocols */
-#define TL_SETUP_VERSION		1
-
-#define TL_SETUP_VERSION_QRY_TMO	1000
-#define TL_SETUP_MAX_VERSION_QRY	30
-
-/* Message numbers 0-9 are obsoleted and must not be reused! */
-#define TL_SETUP_SIGNO_GET_VERSION_QRY	10
-#define TL_SETUP_SIGNO_GET_VERSION_RSP	11
-#define TL_SETUP_SIGNO_CONFIG_MSG	12
-#define TL_SETUP_SIGNO_CONFIG_DONE_MSG	13
-#define TL_SETUP_SIGNO_OPEN_MSG		14
-#define TL_SETUP_SIGNO_CLOSE_MSG	15
-
-#define TL_SETUP_SIGNO_INFO_MSG     20
-#define TL_SETUP_SIGNO_INFO_MSG_ACK 21
-
-#define TL_SETUP_SIGNO_REBOOT_MSG      22
-#define TL_SETUP_SIGNO_REBOOT_MSG_ACK  23
-
-/* Synchronous start-messages */
-struct tl_setup_get_version_qry {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_QRY */
-} __attribute__ ((__packed__));
-
-struct tl_setup_get_version_rsp {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_GET_VERSION_RSP */
-	unsigned char version;		/* TL_SETUP_VERSION */
-} __attribute__ ((__packed__));
-
-struct tl_setup_config_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_MSG */
-	unsigned char port_no;
-	unsigned char prio_data;
-	unsigned char prio_ctrl;
-} __attribute__ ((__packed__));
-
-struct tl_setup_config_done_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_CONFIG_DONE_MSG */
-} __attribute__ ((__packed__));
-
-/* Asyncronous messages */
-struct tl_setup_open_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_OPEN_MSG */
-	unsigned char port_no;
-} __attribute__ ((__packed__));
-
-struct tl_setup_close_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_CLOSE_MSG */
-	unsigned char port_no;
-} __attribute__ ((__packed__));
-
-/* Driver type  - for use in tl_setup_info_msg.driver_type */
-#define COMM_DRIVER     0
-#define NDISWAN_DRIVER  1
-#define NDISWAN_DRIVER_MAJOR_VERSION  2
-#define NDISWAN_DRIVER_MINOR_VERSION  0
-
-/*
- * It should not matter when this message comes over as we just store the
- * results and send the ACK.
- */
-struct tl_setup_info_msg {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG */
-	unsigned char driver_type;
-	unsigned char major_version;
-	unsigned char minor_version;
-} __attribute__ ((__packed__));
-
-struct tl_setup_info_msgAck {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_INFO_MSG_ACK */
-} __attribute__ ((__packed__));
-
-struct TlSetupRebootMsgAck {
-	unsigned char sig_no;		/* TL_SETUP_SIGNO_REBOOT_MSG_ACK */
-} __attribute__ ((__packed__));
-
-/* Define a union of all the msgs that the driver can receive from the card.*/
-union ipw_setup_rx_msg {
-	unsigned char sig_no;
-	struct tl_setup_get_version_rsp version_rsp_msg;
-	struct tl_setup_open_msg open_msg;
-	struct tl_setup_close_msg close_msg;
-	struct tl_setup_info_msg InfoMsg;
-	struct tl_setup_info_msgAck info_msg_ack;
-} __attribute__ ((__packed__));
-
-#endif				/* _IPWIRELESS_CS_SETUP_PROTOCOL_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/tty.c linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/tty.c
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/tty.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/tty.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,679 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/ppp_defs.h>
-#include <linux/if.h>
-#include <linux/if_ppp.h>
-#include <linux/sched.h>
-#include <linux/serial.h>
-#include <linux/slab.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/uaccess.h>
-
-#include "tty.h"
-#include "network.h"
-#include "hardware.h"
-#include "main.h"
-
-#define IPWIRELESS_PCMCIA_START 	(0)
-#define IPWIRELESS_PCMCIA_MINORS	(24)
-#define IPWIRELESS_PCMCIA_MINOR_RANGE	(8)
-
-#define TTYTYPE_MODEM    (0)
-#define TTYTYPE_MONITOR  (1)
-#define TTYTYPE_RAS_RAW  (2)
-
-struct ipw_tty {
-	int index;
-	struct ipw_hardware *hardware;
-	unsigned int channel_idx;
-	unsigned int secondary_channel_idx;
-	int tty_type;
-	struct ipw_network *network;
-	struct tty_struct *linux_tty;
-	int open_count;
-	unsigned int control_lines;
-	struct mutex ipw_tty_mutex;
-	int tx_bytes_queued;
-	int closing;
-};
-
-static struct ipw_tty *ttys[IPWIRELESS_PCMCIA_MINORS];
-
-static struct tty_driver *ipw_tty_driver;
-
-static char *tty_type_name(int tty_type)
-{
-	static char *channel_names[] = {
-		"modem",
-		"monitor",
-		"RAS-raw"
-	};
-
-	return channel_names[tty_type];
-}
-
-static void report_registering(struct ipw_tty *tty)
-{
-	char *iftype = tty_type_name(tty->tty_type);
-
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-	       ": registering %s device ttyIPWp%d\n", iftype, tty->index);
-}
-
-static void report_deregistering(struct ipw_tty *tty)
-{
-	char *iftype = tty_type_name(tty->tty_type);
-
-	printk(KERN_INFO IPWIRELESS_PCCARD_NAME
-	       ": deregistering %s device ttyIPWp%d\n", iftype,
-	       tty->index);
-}
-
-static struct ipw_tty *get_tty(int minor)
-{
-	if (minor < ipw_tty_driver->minor_start
-			|| minor >= ipw_tty_driver->minor_start +
-			IPWIRELESS_PCMCIA_MINORS)
-		return NULL;
-	else {
-		int minor_offset = minor - ipw_tty_driver->minor_start;
-
-		/*
-		 * The 'ras_raw' channel is only available when 'loopback' mode
-		 * is enabled.
-		 * Number of minor starts with 16 (_RANGE * _RAS_RAW).
-		 */
-		if (!ipwireless_loopback &&
-				minor_offset >=
-				 IPWIRELESS_PCMCIA_MINOR_RANGE * TTYTYPE_RAS_RAW)
-			return NULL;
-
-		return ttys[minor_offset];
-	}
-}
-
-static int ipw_open(struct tty_struct *linux_tty, struct file *filp)
-{
-	int minor = linux_tty->index;
-	struct ipw_tty *tty = get_tty(minor);
-
-	if (!tty)
-		return -ENODEV;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-
-	if (tty->closing) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return -ENODEV;
-	}
-	if (tty->open_count == 0)
-		tty->tx_bytes_queued = 0;
-
-	tty->open_count++;
-
-	tty->linux_tty = linux_tty;
-	linux_tty->driver_data = tty;
-	linux_tty->low_latency = 1;
-
-	if (tty->tty_type == TTYTYPE_MODEM)
-		ipwireless_ppp_open(tty->network);
-
-	mutex_unlock(&tty->ipw_tty_mutex);
-
-	return 0;
-}
-
-static void do_ipw_close(struct ipw_tty *tty)
-{
-	tty->open_count--;
-
-	if (tty->open_count == 0) {
-		struct tty_struct *linux_tty = tty->linux_tty;
-
-		if (linux_tty != NULL) {
-			tty->linux_tty = NULL;
-			linux_tty->driver_data = NULL;
-
-			if (tty->tty_type == TTYTYPE_MODEM)
-				ipwireless_ppp_close(tty->network);
-		}
-	}
-}
-
-static void ipw_hangup(struct tty_struct *linux_tty)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-
-	if (!tty)
-		return;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-	if (tty->open_count == 0) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return;
-	}
-
-	do_ipw_close(tty);
-
-	mutex_unlock(&tty->ipw_tty_mutex);
-}
-
-static void ipw_close(struct tty_struct *linux_tty, struct file *filp)
-{
-	ipw_hangup(linux_tty);
-}
-
-/* Take data received from hardware, and send it out the tty */
-void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
-			unsigned int length)
-{
-	struct tty_struct *linux_tty;
-	int work = 0;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-	linux_tty = tty->linux_tty;
-	if (linux_tty == NULL) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return;
-	}
-
-	if (!tty->open_count) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return;
-	}
-	mutex_unlock(&tty->ipw_tty_mutex);
-
-	work = tty_insert_flip_string(linux_tty, data, length);
-
-	if (work != length)
-		printk(KERN_DEBUG IPWIRELESS_PCCARD_NAME
-				": %d chars not inserted to flip buffer!\n",
-				length - work);
-
-	/*
-	 * This may sleep if ->low_latency is set
-	 */
-	if (work)
-		tty_flip_buffer_push(linux_tty);
-}
-
-static void ipw_write_packet_sent_callback(void *callback_data,
-					   unsigned int packet_length)
-{
-	struct ipw_tty *tty = callback_data;
-
-	/*
-	 * Packet has been sent, so we subtract the number of bytes from our
-	 * tally of outstanding TX bytes.
-	 */
-	tty->tx_bytes_queued -= packet_length;
-}
-
-static int ipw_write(struct tty_struct *linux_tty,
-		     const unsigned char *buf, int count)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	int room, ret;
-
-	if (!tty)
-		return -ENODEV;
-
-	mutex_lock(&tty->ipw_tty_mutex);
-	if (!tty->open_count) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return -EINVAL;
-	}
-
-	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
-	if (room < 0)
-		room = 0;
-	/* Don't allow caller to write any more than we have room for */
-	if (count > room)
-		count = room;
-
-	if (count == 0) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return 0;
-	}
-
-	ret = ipwireless_send_packet(tty->hardware, IPW_CHANNEL_RAS,
-			       buf, count,
-			       ipw_write_packet_sent_callback, tty);
-	if (ret == -1) {
-		mutex_unlock(&tty->ipw_tty_mutex);
-		return 0;
-	}
-
-	tty->tx_bytes_queued += count;
-	mutex_unlock(&tty->ipw_tty_mutex);
-
-	return count;
-}
-
-static int ipw_write_room(struct tty_struct *linux_tty)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	int room;
-
-	/* FIXME: Exactly how is the tty object locked here .. */
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	room = IPWIRELESS_TX_QUEUE_SIZE - tty->tx_bytes_queued;
-	if (room < 0)
-		room = 0;
-
-	return room;
-}
-
-static int ipwireless_get_serial_info(struct ipw_tty *tty,
-				      struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-
-	if (!retinfo)
-		return (-EFAULT);
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = PORT_UNKNOWN;
-	tmp.line = tty->index;
-	tmp.port = 0;
-	tmp.irq = 0;
-	tmp.flags = 0;
-	tmp.baud_base = 115200;
-	tmp.close_delay = 0;
-	tmp.closing_wait = 0;
-	tmp.custom_divisor = 0;
-	tmp.hub6 = 0;
-	if (copy_to_user(retinfo, &tmp, sizeof(*retinfo)))
-		return -EFAULT;
-
-	return 0;
-}
-
-static int ipw_chars_in_buffer(struct tty_struct *linux_tty)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-
-	if (!tty)
-		return 0;
-
-	if (!tty->open_count)
-		return 0;
-
-	return tty->tx_bytes_queued;
-}
-
-static int get_control_lines(struct ipw_tty *tty)
-{
-	unsigned int my = tty->control_lines;
-	unsigned int out = 0;
-
-	if (my & IPW_CONTROL_LINE_RTS)
-		out |= TIOCM_RTS;
-	if (my & IPW_CONTROL_LINE_DTR)
-		out |= TIOCM_DTR;
-	if (my & IPW_CONTROL_LINE_CTS)
-		out |= TIOCM_CTS;
-	if (my & IPW_CONTROL_LINE_DSR)
-		out |= TIOCM_DSR;
-	if (my & IPW_CONTROL_LINE_DCD)
-		out |= TIOCM_CD;
-
-	return out;
-}
-
-static int set_control_lines(struct ipw_tty *tty, unsigned int set,
-			     unsigned int clear)
-{
-	int ret;
-
-	if (set & TIOCM_RTS) {
-		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 1);
-		if (ret)
-			return ret;
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_RTS(tty->hardware,
-					  tty->secondary_channel_idx, 1);
-			if (ret)
-				return ret;
-		}
-	}
-	if (set & TIOCM_DTR) {
-		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 1);
-		if (ret)
-			return ret;
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_DTR(tty->hardware,
-					  tty->secondary_channel_idx, 1);
-			if (ret)
-				return ret;
-		}
-	}
-	if (clear & TIOCM_RTS) {
-		ret = ipwireless_set_RTS(tty->hardware, tty->channel_idx, 0);
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_RTS(tty->hardware,
-					  tty->secondary_channel_idx, 0);
-			if (ret)
-				return ret;
-		}
-	}
-	if (clear & TIOCM_DTR) {
-		ret = ipwireless_set_DTR(tty->hardware, tty->channel_idx, 0);
-		if (tty->secondary_channel_idx != -1) {
-			ret = ipwireless_set_DTR(tty->hardware,
-					  tty->secondary_channel_idx, 0);
-			if (ret)
-				return ret;
-		}
-	}
-	return 0;
-}
-
-static int ipw_tiocmget(struct tty_struct *linux_tty, struct file *file)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	/* FIXME: Exactly how is the tty object locked here .. */
-
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	return get_control_lines(tty);
-}
-
-static int
-ipw_tiocmset(struct tty_struct *linux_tty, struct file *file,
-	     unsigned int set, unsigned int clear)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-	/* FIXME: Exactly how is the tty object locked here .. */
-
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	return set_control_lines(tty, set, clear);
-}
-
-static int ipw_ioctl(struct tty_struct *linux_tty, struct file *file,
-		     unsigned int cmd, unsigned long arg)
-{
-	struct ipw_tty *tty = linux_tty->driver_data;
-
-	if (!tty)
-		return -ENODEV;
-
-	if (!tty->open_count)
-		return -EINVAL;
-
-	/* FIXME: Exactly how is the tty object locked here .. */
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		return ipwireless_get_serial_info(tty, (void __user *) arg);
-
-	case TIOCSSERIAL:
-		return 0;	/* Keeps the PCMCIA scripts happy. */
-	}
-
-	if (tty->tty_type == TTYTYPE_MODEM) {
-		switch (cmd) {
-		case PPPIOCGCHAN:
-			{
-				int chan = ipwireless_ppp_channel_index(
-							tty->network);
-
-				if (chan < 0)
-					return -ENODEV;
-				if (put_user(chan, (int __user *) arg))
-					return -EFAULT;
-			}
-			return 0;
-
-		case PPPIOCGUNIT:
-			{
-				int unit = ipwireless_ppp_unit_number(
-						tty->network);
-
-				if (unit < 0)
-					return -ENODEV;
-				if (put_user(unit, (int __user *) arg))
-					return -EFAULT;
-			}
-			return 0;
-
-		case FIONREAD:
-			{
-				int val = 0;
-
-				if (put_user(val, (int __user *) arg))
-					return -EFAULT;
-			}
-			return 0;
-		case TCFLSH:
-			return tty_perform_flush(linux_tty, arg);
-		}
-	}
-	return tty_mode_ioctl(linux_tty, file, cmd , arg);
-}
-
-static int add_tty(int j,
-		    struct ipw_hardware *hardware,
-		    struct ipw_network *network, int channel_idx,
-		    int secondary_channel_idx, int tty_type)
-{
-	ttys[j] = kzalloc(sizeof(struct ipw_tty), GFP_KERNEL);
-	if (!ttys[j])
-		return -ENOMEM;
-	ttys[j]->index = j;
-	ttys[j]->hardware = hardware;
-	ttys[j]->channel_idx = channel_idx;
-	ttys[j]->secondary_channel_idx = secondary_channel_idx;
-	ttys[j]->network = network;
-	ttys[j]->tty_type = tty_type;
-	mutex_init(&ttys[j]->ipw_tty_mutex);
-
-	tty_register_device(ipw_tty_driver, j, NULL);
-	ipwireless_associate_network_tty(network, channel_idx, ttys[j]);
-
-	if (secondary_channel_idx != -1)
-		ipwireless_associate_network_tty(network,
-						 secondary_channel_idx,
-						 ttys[j]);
-	if (get_tty(j + ipw_tty_driver->minor_start) == ttys[j])
-		report_registering(ttys[j]);
-	return 0;
-}
-
-struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hardware,
-				      struct ipw_network *network)
-{
-	int i, j;
-
-	for (i = 0; i < IPWIRELESS_PCMCIA_MINOR_RANGE; i++) {
-		int allfree = 1;
-
-		for (j = i; j < IPWIRELESS_PCMCIA_MINORS;
-				j += IPWIRELESS_PCMCIA_MINOR_RANGE)
-			if (ttys[j] != NULL) {
-				allfree = 0;
-				break;
-			}
-
-		if (allfree) {
-			j = i;
-
-			if (add_tty(j, hardware, network,
-					IPW_CHANNEL_DIALLER, IPW_CHANNEL_RAS,
-					TTYTYPE_MODEM))
-				return NULL;
-
-			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
-			if (add_tty(j, hardware, network,
-					IPW_CHANNEL_DIALLER, -1,
-					TTYTYPE_MONITOR))
-				return NULL;
-
-			j += IPWIRELESS_PCMCIA_MINOR_RANGE;
-			if (add_tty(j, hardware, network,
-					IPW_CHANNEL_RAS, -1,
-					TTYTYPE_RAS_RAW))
-				return NULL;
-
-			return ttys[i];
-		}
-	}
-	return NULL;
-}
-
-/*
- * Must be called before ipwireless_network_free().
- */
-void ipwireless_tty_free(struct ipw_tty *tty)
-{
-	int j;
-	struct ipw_network *network = ttys[tty->index]->network;
-
-	for (j = tty->index; j < IPWIRELESS_PCMCIA_MINORS;
-			j += IPWIRELESS_PCMCIA_MINOR_RANGE) {
-		struct ipw_tty *ttyj = ttys[j];
-
-		if (ttyj) {
-			mutex_lock(&ttyj->ipw_tty_mutex);
-			if (get_tty(j + ipw_tty_driver->minor_start) == ttyj)
-				report_deregistering(ttyj);
-			ttyj->closing = 1;
-			if (ttyj->linux_tty != NULL) {
-				mutex_unlock(&ttyj->ipw_tty_mutex);
-				tty_hangup(ttyj->linux_tty);
-				/* Wait till the tty_hangup has completed */
-				flush_work_sync(&ttyj->linux_tty->hangup_work);
-				/* FIXME: Exactly how is the tty object locked here
-				   against a parallel ioctl etc */
-				mutex_lock(&ttyj->ipw_tty_mutex);
-			}
-			while (ttyj->open_count)
-				do_ipw_close(ttyj);
-			ipwireless_disassociate_network_ttys(network,
-							     ttyj->channel_idx);
-			tty_unregister_device(ipw_tty_driver, j);
-			ttys[j] = NULL;
-			mutex_unlock(&ttyj->ipw_tty_mutex);
-			kfree(ttyj);
-		}
-	}
-}
-
-static const struct tty_operations tty_ops = {
-	.open = ipw_open,
-	.close = ipw_close,
-	.hangup = ipw_hangup,
-	.write = ipw_write,
-	.write_room = ipw_write_room,
-	.ioctl = ipw_ioctl,
-	.chars_in_buffer = ipw_chars_in_buffer,
-	.tiocmget = ipw_tiocmget,
-	.tiocmset = ipw_tiocmset,
-};
-
-int ipwireless_tty_init(void)
-{
-	int result;
-
-	ipw_tty_driver = alloc_tty_driver(IPWIRELESS_PCMCIA_MINORS);
-	if (!ipw_tty_driver)
-		return -ENOMEM;
-
-	ipw_tty_driver->owner = THIS_MODULE;
-	ipw_tty_driver->driver_name = IPWIRELESS_PCCARD_NAME;
-	ipw_tty_driver->name = "ttyIPWp";
-	ipw_tty_driver->major = 0;
-	ipw_tty_driver->minor_start = IPWIRELESS_PCMCIA_START;
-	ipw_tty_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	ipw_tty_driver->subtype = SERIAL_TYPE_NORMAL;
-	ipw_tty_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	ipw_tty_driver->init_termios = tty_std_termios;
-	ipw_tty_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	ipw_tty_driver->init_termios.c_ispeed = 9600;
-	ipw_tty_driver->init_termios.c_ospeed = 9600;
-	tty_set_operations(ipw_tty_driver, &tty_ops);
-	result = tty_register_driver(ipw_tty_driver);
-	if (result) {
-		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-		       ": failed to register tty driver\n");
-		put_tty_driver(ipw_tty_driver);
-		return result;
-	}
-
-	return 0;
-}
-
-void ipwireless_tty_release(void)
-{
-	int ret;
-
-	ret = tty_unregister_driver(ipw_tty_driver);
-	put_tty_driver(ipw_tty_driver);
-	if (ret != 0)
-		printk(KERN_ERR IPWIRELESS_PCCARD_NAME
-			": tty_unregister_driver failed with code %d\n", ret);
-}
-
-int ipwireless_tty_is_modem(struct ipw_tty *tty)
-{
-	return tty->tty_type == TTYTYPE_MODEM;
-}
-
-void
-ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
-					  unsigned int channel_idx,
-					  unsigned int control_lines,
-					  unsigned int changed_mask)
-{
-	unsigned int old_control_lines = tty->control_lines;
-
-	tty->control_lines = (tty->control_lines & ~changed_mask)
-		| (control_lines & changed_mask);
-
-	/*
-	 * If DCD is de-asserted, we close the tty so pppd can tell that we
-	 * have gone offline.
-	 */
-	if ((old_control_lines & IPW_CONTROL_LINE_DCD)
-			&& !(tty->control_lines & IPW_CONTROL_LINE_DCD)
-			&& tty->linux_tty) {
-		tty_hangup(tty->linux_tty);
-	}
-}
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/tty.h linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/tty.h
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/ipwireless/tty.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/ipwireless/tty.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,45 +0,0 @@
-/*
- * IPWireless 3G PCMCIA Network Driver
- *
- * Original code
- *   by Stephen Blackheath <stephen@blacksapphire.com>,
- *      Ben Martel <benm@symmetric.co.nz>
- *
- * Copyrighted as follows:
- *   Copyright (C) 2004 by Symmetric Systems Ltd (NZ)
- *
- * Various driver changes and rewrites, port to new kernels
- *   Copyright (C) 2006-2007 Jiri Kosina
- *
- * Misc code cleanups and updates
- *   Copyright (C) 2007 David Sterba
- */
-
-#ifndef _IPWIRELESS_CS_TTY_H_
-#define _IPWIRELESS_CS_TTY_H_
-
-#include <linux/types.h>
-#include <linux/sched.h>
-
-#include <pcmcia/cistpl.h>
-#include <pcmcia/ds.h>
-
-struct ipw_tty;
-struct ipw_network;
-struct ipw_hardware;
-
-int ipwireless_tty_init(void);
-void ipwireless_tty_release(void);
-
-struct ipw_tty *ipwireless_tty_create(struct ipw_hardware *hw,
-				      struct ipw_network *net);
-void ipwireless_tty_free(struct ipw_tty *tty);
-void ipwireless_tty_received(struct ipw_tty *tty, unsigned char *data,
-			     unsigned int length);
-int ipwireless_tty_is_modem(struct ipw_tty *tty);
-void ipwireless_tty_notify_control_line_change(struct ipw_tty *tty,
-					       unsigned int channel_idx,
-					       unsigned int control_lines,
-					       unsigned int changed_mask);
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/Makefile linux-libre-2.6.39-gnu/drivers/char/pcmcia/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,8 +4,6 @@
 # Makefile for the Linux PCMCIA char device drivers.
 #
 
-obj-y += ipwireless/
-
 obj-$(CONFIG_SYNCLINK_CS) += synclink_cs.o
 obj-$(CONFIG_CARDMAN_4000) += cm4000_cs.o
 obj-$(CONFIG_CARDMAN_4040) += cm4040_cs.o
diff -druN linux-libre-2.6.38-gnu/drivers/char/pcmcia/synclink_cs.c linux-libre-2.6.39-gnu/drivers/char/pcmcia/synclink_cs.c
--- linux-libre-2.6.38-gnu/drivers/char/pcmcia/synclink_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/pcmcia/synclink_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -418,9 +418,9 @@
 /*
  * ioctl handlers
  */
-static int tiocmget(struct tty_struct *tty, struct file *file);
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear);
+static int tiocmget(struct tty_struct *tty);
+static int tiocmset(struct tty_struct *tty,
+					unsigned int set, unsigned int clear);
 static int get_stats(MGSLPC_INFO *info, struct mgsl_icount __user *user_icount);
 static int get_params(MGSLPC_INFO *info, MGSL_PARAMS __user *user_params);
 static int set_params(MGSLPC_INFO *info, MGSL_PARAMS __user *new_params, struct tty_struct *tty);
@@ -1290,7 +1290,7 @@
 	/* Allocate and claim adapter resources */
 	retval = claim_resources(info);
 
-	/* perform existance check and diagnostics */
+	/* perform existence check and diagnostics */
 	if ( !retval )
 		retval = adapter_test(info);
 
@@ -2114,7 +2114,7 @@
 
 /* return the state of the serial control and status signals
  */
-static int tiocmget(struct tty_struct *tty, struct file *file)
+static int tiocmget(struct tty_struct *tty)
 {
 	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
 	unsigned int result;
@@ -2139,7 +2139,7 @@
 
 /* set modem control signals (DTR/RTS)
  */
-static int tiocmset(struct tty_struct *tty, struct file *file,
+static int tiocmset(struct tty_struct *tty,
 		    unsigned int set, unsigned int clear)
 {
 	MGSLPC_INFO *info = (MGSLPC_INFO *)tty->driver_data;
@@ -2222,13 +2222,12 @@
  * Arguments:
  *
  * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
  * 	cmd	IOCTL command code
  * 	arg	command argument/context
  *
  * Return Value:	0 if success, otherwise error code
  */
-static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
+static int mgslpc_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
@@ -2681,7 +2680,7 @@
 static int claim_resources(MGSLPC_INFO *info)
 {
 	if (rx_alloc_buffers(info) < 0 ) {
-		printk( "Cant allocate rx buffer %s\n", info->device_name);
+		printk( "Can't allocate rx buffer %s\n", info->device_name);
 		release_resources(info);
 		return -ENODEV;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/char/random.c linux-libre-2.6.39-gnu/drivers/char/random.c
--- linux-libre-2.6.38-gnu/drivers/char/random.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/random.c	2011-05-19 00:06:34.000000000 -0400
@@ -128,6 +128,7 @@
  * 	void add_input_randomness(unsigned int type, unsigned int code,
  *                                unsigned int value);
  * 	void add_interrupt_randomness(int irq);
+ * 	void add_disk_randomness(struct gendisk *disk);
  *
  * add_input_randomness() uses the input layer interrupt timing, as well as
  * the event type information from the hardware.
@@ -136,9 +137,15 @@
  * inputs to the entropy pool.  Note that not all interrupts are good
  * sources of randomness!  For example, the timer interrupts is not a
  * good choice, because the periodicity of the interrupts is too
- * regular, and hence predictable to an attacker.  Disk interrupts are
- * a better measure, since the timing of the disk interrupts are more
- * unpredictable.
+ * regular, and hence predictable to an attacker.  Network Interface
+ * Controller interrupts are a better measure, since the timing of the
+ * NIC interrupts are more unpredictable.
+ *
+ * add_disk_randomness() uses what amounts to the seek time of block
+ * layer request events, on a per-disk_devt basis, as input to the
+ * entropy pool. Note that high-speed solid state drives with very low
+ * seek times do not make for good sources of entropy, as their seek
+ * times are usually fairly consistent.
  *
  * All of these routines try to estimate how many bits of randomness a
  * particular randomness source.  They do this by keeping track of the
@@ -725,7 +732,7 @@
 			       size_t nbytes, int min, int rsvd);
 
 /*
- * This utility inline function is responsible for transfering entropy
+ * This utility inline function is responsible for transferring entropy
  * from the primary pool to the secondary extraction pool. We make
  * sure we pull enough for a 'catastrophic reseed'.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/board.h linux-libre-2.6.39-gnu/drivers/char/rio/board.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/board.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/board.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,132 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources. 
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: board.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:07
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)board.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_board_h__
-#define	__rio_board_h__
-
-/*
-** board.h contains the definitions for the *hardware* of the host cards.
-** It describes the memory overlay for the dual port RAM area.
-*/
-
-#define	DP_SRAM1_SIZE	0x7C00
-#define	DP_SRAM2_SIZE	0x0200
-#define	DP_SRAM3_SIZE	0x7000
-#define	DP_SCRATCH_SIZE	0x1000
-#define	DP_PARMMAP_ADDR	0x01FE	/* offset into SRAM2 */
-#define	DP_STARTUP_ADDR	0x01F8	/* offset into SRAM2 */
-
-/*
-**	The shape of the Host Control area, at offset 0x7C00, Write Only
-*/
-struct s_Ctrl {
-	u8 DpCtl;		/* 7C00 */
-	u8 Dp_Unused2_[127];
-	u8 DpIntSet;		/* 7C80 */
-	u8 Dp_Unused3_[127];
-	u8 DpTpuReset;	/* 7D00 */
-	u8 Dp_Unused4_[127];
-	u8 DpIntReset;	/* 7D80 */
-	u8 Dp_Unused5_[127];
-};
-
-/*
-** The PROM data area on the host (0x7C00), Read Only
-*/
-struct s_Prom {
-	u16 DpSlxCode[2];
-	u16 DpRev;
-	u16 Dp_Unused6_;
-	u16 DpUniq[4];
-	u16 DpJahre;
-	u16 DpWoche;
-	u16 DpHwFeature[5];
-	u16 DpOemId;
-	u16 DpSiggy[16];
-};
-
-/*
-** Union of the Ctrl and Prom areas
-*/
-union u_CtrlProm {		/* This is the control/PROM area (0x7C00) */
-	struct s_Ctrl DpCtrl;
-	struct s_Prom DpProm;
-};
-
-/*
-** The top end of memory!
-*/
-struct s_ParmMapS {		/* Area containing Parm Map Pointer */
-	u8 Dp_Unused8_[DP_PARMMAP_ADDR];
-	u16 DpParmMapAd;
-};
-
-struct s_StartUpS {
-	u8 Dp_Unused9_[DP_STARTUP_ADDR];
-	u8 Dp_LongJump[0x4];
-	u8 Dp_Unused10_[2];
-	u8 Dp_ShortJump[0x2];
-};
-
-union u_Sram2ParmMap {		/* This is the top of memory (0x7E00-0x7FFF) */
-	u8 DpSramMem[DP_SRAM2_SIZE];
-	struct s_ParmMapS DpParmMapS;
-	struct s_StartUpS DpStartUpS;
-};
-
-/*
-**	This is the DP RAM overlay.
-*/
-struct DpRam {
-	u8 DpSram1[DP_SRAM1_SIZE];	/* 0000 - 7BFF */
-	union u_CtrlProm DpCtrlProm;	/* 7C00 - 7DFF */
-	union u_Sram2ParmMap DpSram2ParmMap;	/* 7E00 - 7FFF */
-	u8 DpScratch[DP_SCRATCH_SIZE];	/* 8000 - 8FFF */
-	u8 DpSram3[DP_SRAM3_SIZE];	/* 9000 - FFFF */
-};
-
-#define	DpControl	DpCtrlProm.DpCtrl.DpCtl
-#define	DpSetInt	DpCtrlProm.DpCtrl.DpIntSet
-#define	DpResetTpu	DpCtrlProm.DpCtrl.DpTpuReset
-#define	DpResetInt	DpCtrlProm.DpCtrl.DpIntReset
-
-#define	DpSlx		DpCtrlProm.DpProm.DpSlxCode
-#define	DpRevision	DpCtrlProm.DpProm.DpRev
-#define	DpUnique	DpCtrlProm.DpProm.DpUniq
-#define	DpYear		DpCtrlProm.DpProm.DpJahre
-#define	DpWeek		DpCtrlProm.DpProm.DpWoche
-#define	DpSignature	DpCtrlProm.DpProm.DpSiggy
-
-#define	DpParmMapR	DpSram2ParmMap.DpParmMapS.DpParmMapAd
-#define	DpSram2		DpSram2ParmMap.DpSramMem
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/cirrus.h linux-libre-2.6.39-gnu/drivers/char/rio/cirrus.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/cirrus.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/cirrus.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,210 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******		CIRRUS.H				      *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Jeremy Rolls
- Date    : 3 Aug 1990
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _cirrus_h
-#define _cirrus_h 1
-
-/* Bit fields for particular registers shared with driver */
-
-/* COR1 - driver and RTA */
-#define RIOC_COR1_ODD		0x80	/* Odd parity */
-#define RIOC_COR1_EVEN		0x00	/* Even parity */
-#define RIOC_COR1_NOP		0x00	/* No parity */
-#define RIOC_COR1_FORCE		0x20	/* Force parity */
-#define RIOC_COR1_NORMAL	0x40	/* With parity */
-#define RIOC_COR1_1STOP		0x00	/* 1 stop bit */
-#define RIOC_COR1_15STOP	0x04	/* 1.5 stop bits */
-#define RIOC_COR1_2STOP		0x08	/* 2 stop bits */
-#define RIOC_COR1_5BITS		0x00	/* 5 data bits */
-#define RIOC_COR1_6BITS		0x01	/* 6 data bits */
-#define RIOC_COR1_7BITS		0x02	/* 7 data bits */
-#define RIOC_COR1_8BITS		0x03	/* 8 data bits */
-
-#define RIOC_COR1_HOST		0xef	/* Safe host bits */
-
-/* RTA only */
-#define RIOC_COR1_CINPCK	0x00	/* Check parity of received characters */
-#define RIOC_COR1_CNINPCK	0x10	/* Don't check parity */
-
-/* COR2 bits for both RTA and driver use */
-#define RIOC_COR2_IXANY		0x80	/* IXANY - any character is XON */
-#define RIOC_COR2_IXON		0x40	/* IXON - enable tx soft flowcontrol */
-#define RIOC_COR2_RTSFLOW	0x02	/* Enable tx hardware flow control */
-
-/* Additional driver bits */
-#define RIOC_COR2_HUPCL		0x20	/* Hang up on close */
-#define RIOC_COR2_CTSFLOW	0x04	/* Enable rx hardware flow control */
-#define RIOC_COR2_IXOFF		0x01	/* Enable rx software flow control */
-#define RIOC_COR2_DTRFLOW	0x08	/* Enable tx hardware flow control */
-
-/* RTA use only */
-#define RIOC_COR2_ETC		0x20	/* Embedded transmit options */
-#define RIOC_COR2_LOCAL		0x10	/* Local loopback mode */
-#define RIOC_COR2_REMOTE	0x08	/* Remote loopback mode */
-#define RIOC_COR2_HOST		0xc2	/* Safe host bits */
-
-/* COR3 - RTA use only */
-#define RIOC_COR3_SCDRNG	0x80	/* Enable special char detect for range */
-#define RIOC_COR3_SCD34		0x40	/* Special character detect for SCHR's 3 + 4 */
-#define RIOC_COR3_FCT		0x20	/* Flow control transparency */
-#define RIOC_COR3_SCD12		0x10	/* Special character detect for SCHR's 1 + 2 */
-#define RIOC_COR3_FIFO12	0x0c	/* 12 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO10	0x0a	/* 10 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO8		0x08	/* 8 chars for receive FIFO threshold */
-#define RIOC_COR3_FIFO6		0x06	/* 6 chars for receive FIFO threshold */
-
-#define RIOC_COR3_THRESHOLD	RIOC_COR3_FIFO8	/* MUST BE LESS THAN MCOR_THRESHOLD */
-
-#define RIOC_COR3_DEFAULT	(RIOC_COR3_FCT | RIOC_COR3_THRESHOLD)
-				/* Default bits for COR3 */
-
-/* COR4 driver and RTA use */
-#define RIOC_COR4_IGNCR		0x80	/* Throw away CR's on input */
-#define RIOC_COR4_ICRNL		0x40	/* Map CR -> NL on input */
-#define RIOC_COR4_INLCR		0x20	/* Map NL -> CR on input */
-#define RIOC_COR4_IGNBRK	0x10	/* Ignore Break */
-#define RIOC_COR4_NBRKINT	0x08	/* No interrupt on break (-BRKINT) */
-#define RIOC_COR4_RAISEMOD	0x01	/* Raise modem output lines on non-zero baud */
-
-
-/* COR4 driver only */
-#define RIOC_COR4_IGNPAR	0x04	/* IGNPAR (ignore characters with errors) */
-#define RIOC_COR4_PARMRK	0x02	/* PARMRK */
-
-#define RIOC_COR4_HOST		0xf8	/* Safe host bits */
-
-/* COR4 RTA only */
-#define RIOC_COR4_CIGNPAR	0x02	/* Thrown away bad characters */
-#define RIOC_COR4_CPARMRK	0x04	/* PARMRK characters */
-#define RIOC_COR4_CNPARMRK	0x03	/* Don't PARMRK */
-
-/* COR5 driver and RTA use */
-#define RIOC_COR5_ISTRIP	0x80	/* Strip input chars to 7 bits */
-#define RIOC_COR5_LNE		0x40	/* Enable LNEXT processing */
-#define RIOC_COR5_CMOE		0x20	/* Match good and errored characters */
-#define RIOC_COR5_ONLCR		0x02	/* NL -> CR NL on output */
-#define RIOC_COR5_OCRNL		0x01	/* CR -> NL on output */
-
-/*
-** Spare bits - these are not used in the CIRRUS registers, so we use
-** them to set various other features.
-*/
-/*
-** tstop and tbusy indication
-*/
-#define RIOC_COR5_TSTATE_ON	0x08	/* Turn on monitoring of tbusy and tstop */
-#define RIOC_COR5_TSTATE_OFF	0x04	/* Turn off monitoring of tbusy and tstop */
-/*
-** TAB3
-*/
-#define RIOC_COR5_TAB3		0x10	/* TAB3 mode */
-
-#define RIOC_COR5_HOST		0xc3	/* Safe host bits */
-
-/* CCSR */
-#define RIOC_CCSR_TXFLOFF	0x04	/* Tx is xoffed */
-
-/* MSVR1 */
-/* NB. DTR / CD swapped from Cirrus spec as the pins are also reversed on the
-   RTA. This is because otherwise DCD would get lost on the 1 parallel / 3
-   serial option.
-*/
-#define RIOC_MSVR1_CD		0x80	/* CD (DSR on Cirrus) */
-#define RIOC_MSVR1_RTS		0x40	/* RTS (CTS on Cirrus) */
-#define RIOC_MSVR1_RI		0x20	/* RI */
-#define RIOC_MSVR1_DTR		0x10	/* DTR (CD on Cirrus) */
-#define RIOC_MSVR1_CTS		0x01	/* CTS output pin (RTS on Cirrus) */
-/* Next two used to indicate state of tbusy and tstop to driver */
-#define RIOC_MSVR1_TSTOP	0x08	/* Set if port flow controlled */
-#define RIOC_MSVR1_TEMPTY	0x04	/* Set if port tx buffer empty */
-
-#define RIOC_MSVR1_HOST		0xf3	/* The bits the host wants */
-
-/* Defines for the subscripts of a CONFIG packet */
-#define RIOC_CONFIG_COR1	1	/* Option register 1 */
-#define RIOC_CONFIG_COR2	2	/* Option register 2 */
-#define RIOC_CONFIG_COR4	3	/* Option register 4 */
-#define RIOC_CONFIG_COR5	4	/* Option register 5 */
-#define RIOC_CONFIG_TXXON	5	/* Tx XON character */
-#define RIOC_CONFIG_TXXOFF	6	/* Tx XOFF character */
-#define RIOC_CONFIG_RXXON	7	/* Rx XON character */
-#define RIOC_CONFIG_RXXOFF	8	/* Rx XOFF character */
-#define RIOC_CONFIG_LNEXT	9	/* LNEXT character */
-#define RIOC_CONFIG_TXBAUD	10	/* Tx baud rate */
-#define RIOC_CONFIG_RXBAUD	11	/* Rx baud rate */
-
-#define RIOC_PRE_EMPTIVE	0x80	/* Pre-emptive bit in command field */
-
-/* Packet types going from Host to remote - with the exception of OPEN, MOPEN,
-   CONFIG, SBREAK and MEMDUMP the remaining bytes of the data array will not
-   be used 
-*/
-#define RIOC_OPEN		0x00	/* Open a port */
-#define RIOC_CONFIG		0x01	/* Configure a port */
-#define RIOC_MOPEN		0x02	/* Modem open (block for DCD) */
-#define RIOC_CLOSE		0x03	/* Close a port */
-#define RIOC_WFLUSH		(0x04 | RIOC_PRE_EMPTIVE)	/* Write flush */
-#define RIOC_RFLUSH		(0x05 | RIOC_PRE_EMPTIVE)	/* Read flush */
-#define RIOC_RESUME		(0x06 | RIOC_PRE_EMPTIVE)	/* Resume if xoffed */
-#define RIOC_SBREAK		0x07	/* Start break */
-#define RIOC_EBREAK		0x08	/* End break */
-#define RIOC_SUSPEND		(0x09 | RIOC_PRE_EMPTIVE)	/* Susp op (behave as tho xoffed) */
-#define RIOC_FCLOSE		(0x0a | RIOC_PRE_EMPTIVE)	/* Force close */
-#define RIOC_XPRINT		0x0b	/* Xprint packet */
-#define RIOC_MBIS		(0x0c | RIOC_PRE_EMPTIVE)	/* Set modem lines */
-#define RIOC_MBIC		(0x0d | RIOC_PRE_EMPTIVE)	/* Clear modem lines */
-#define RIOC_MSET		(0x0e | RIOC_PRE_EMPTIVE)	/* Set modem lines */
-#define RIOC_PCLOSE		0x0f	/* Pseudo close - Leaves rx/tx enabled */
-#define RIOC_MGET		(0x10 | RIOC_PRE_EMPTIVE)	/* Force update of modem status */
-#define RIOC_MEMDUMP		(0x11 | RIOC_PRE_EMPTIVE)	/* Send back mem from addr supplied */
-#define RIOC_READ_REGISTER	(0x12 | RIOC_PRE_EMPTIVE)	/* Read CD1400 register (debug) */
-
-/* "Command" packets going from remote to host COMPLETE and MODEM_STATUS
-   use data[4] / data[3] to indicate current state and modem status respectively
-*/
-
-#define RIOC_COMPLETE		(0x20 | RIOC_PRE_EMPTIVE)
-				/* Command complete */
-#define RIOC_BREAK_RECEIVED	(0x21 | RIOC_PRE_EMPTIVE)
-				/* Break received */
-#define RIOC_MODEM_STATUS	(0x22 | RIOC_PRE_EMPTIVE)
-				/* Change in modem status */
-
-/* "Command" packet that could go either way - handshake wake-up */
-#define RIOC_HANDSHAKE		(0x23 | RIOC_PRE_EMPTIVE)
-				/* Wake-up to HOST / RTA */
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/cmdblk.h linux-libre-2.6.39-gnu/drivers/char/rio/cmdblk.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/cmdblk.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/cmdblk.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,53 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: cmdblk.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)cmdblk.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_cmdblk_h__
-#define __rio_cmdblk_h__
-
-/*
-** the structure of a command block, used to queue commands destined for
-** a rup.
-*/
-
-struct CmdBlk {
-	struct CmdBlk *NextP;	/* Pointer to next command block */
-	struct PKT Packet;	/* A packet, to copy to the rup */
-	/* The func to call to check if OK */
-	int (*PreFuncP) (unsigned long, struct CmdBlk *);
-	int PreArg;		/* The arg for the func */
-	/* The func to call when completed */
-	int (*PostFuncP) (unsigned long, struct CmdBlk *);
-	int PostArg;		/* The arg for the func */
-};
-
-#define NUM_RIO_CMD_BLKS (3 * (MAX_RUP * 4 + LINKS_PER_UNIT * 4))
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/cmdpkt.h linux-libre-2.6.39-gnu/drivers/char/rio/cmdpkt.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/cmdpkt.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/cmdpkt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,177 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: cmdpkt.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:20
-**
-**  ident @(#)cmdpkt.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-#ifndef __rio_cmdpkt_h__
-#define __rio_cmdpkt_h__
-
-/*
-** overlays for the data area of a packet. Used in both directions
-** (to build a packet to send, and to interpret a packet that arrives)
-** and is very inconvenient for MIPS, so they appear as two separate
-** structures - those used for modifying/reading packets on the card
-** and those for modifying/reading packets in real memory, which have an _M
-** suffix.
-*/
-
-#define	RTA_BOOT_DATA_SIZE (PKT_MAX_DATA_LEN-2)
-
-/*
-** The boot information packet looks like this:
-** This structure overlays a PktCmd->CmdData structure, and so starts
-** at Data[2] in the actual pkt!
-*/
-struct BootSequence {
-	u16 NumPackets;
-	u16 LoadBase;
-	u16 CodeSize;
-};
-
-#define	BOOT_SEQUENCE_LEN	8
-
-struct SamTop {
-	u8 Unit;
-	u8 Link;
-};
-
-struct CmdHdr {
-	u8 PcCommand;
-	union {
-		u8 PcPhbNum;
-		u8 PcLinkNum;
-		u8 PcIDNum;
-	} U0;
-};
-
-
-struct PktCmd {
-	union {
-		struct {
-			struct CmdHdr CmdHdr;
-			struct BootSequence PcBootSequence;
-		} S1;
-		struct {
-			u16 PcSequence;
-			u8 PcBootData[RTA_BOOT_DATA_SIZE];
-		} S2;
-		struct {
-			u16 __crud__;
-			u8 PcUniqNum[4];	/* this is really a uint. */
-			u8 PcModuleTypes;	/* what modules are fitted */
-		} S3;
-		struct {
-			struct CmdHdr CmdHdr;
-			u8 __undefined__;
-			u8 PcModemStatus;
-			u8 PcPortStatus;
-			u8 PcSubCommand;	/* commands like mem or register dump */
-			u16 PcSubAddr;	/* Address for command */
-			u8 PcSubData[64];	/* Date area for command */
-		} S4;
-		struct {
-			struct CmdHdr CmdHdr;
-			u8 PcCommandText[1];
-			u8 __crud__[20];
-			u8 PcIDNum2;	/* It had to go somewhere! */
-		} S5;
-		struct {
-			struct CmdHdr CmdHdr;
-			struct SamTop Topology[LINKS_PER_UNIT];
-		} S6;
-	} U1;
-};
-
-struct PktCmd_M {
-	union {
-		struct {
-			struct {
-				u8 PcCommand;
-				union {
-					u8 PcPhbNum;
-					u8 PcLinkNum;
-					u8 PcIDNum;
-				} U0;
-			} CmdHdr;
-			struct {
-				u16 NumPackets;
-				u16 LoadBase;
-				u16 CodeSize;
-			} PcBootSequence;
-		} S1;
-		struct {
-			u16 PcSequence;
-			u8 PcBootData[RTA_BOOT_DATA_SIZE];
-		} S2;
-		struct {
-			u16 __crud__;
-			u8 PcUniqNum[4];	/* this is really a uint. */
-			u8 PcModuleTypes;	/* what modules are fitted */
-		} S3;
-		struct {
-			u16 __cmd_hdr__;
-			u8 __undefined__;
-			u8 PcModemStatus;
-			u8 PcPortStatus;
-			u8 PcSubCommand;
-			u16 PcSubAddr;
-			u8 PcSubData[64];
-		} S4;
-		struct {
-			u16 __cmd_hdr__;
-			u8 PcCommandText[1];
-			u8 __crud__[20];
-			u8 PcIDNum2;	/* Tacked on end */
-		} S5;
-		struct {
-			u16 __cmd_hdr__;
-			struct Top Topology[LINKS_PER_UNIT];
-		} S6;
-	} U1;
-};
-
-#define Command		U1.S1.CmdHdr.PcCommand
-#define PhbNum		U1.S1.CmdHdr.U0.PcPhbNum
-#define IDNum		U1.S1.CmdHdr.U0.PcIDNum
-#define IDNum2		U1.S5.PcIDNum2
-#define LinkNum		U1.S1.CmdHdr.U0.PcLinkNum
-#define Sequence	U1.S2.PcSequence
-#define BootData	U1.S2.PcBootData
-#define BootSequence	U1.S1.PcBootSequence
-#define UniqNum		U1.S3.PcUniqNum
-#define ModemStatus	U1.S4.PcModemStatus
-#define PortStatus	U1.S4.PcPortStatus
-#define SubCommand	U1.S4.PcSubCommand
-#define SubAddr		U1.S4.PcSubAddr
-#define SubData		U1.S4.PcSubData
-#define CommandText	U1.S5.PcCommandText
-#define RouteTopology	U1.S6.Topology
-#define ModuleTypes	U1.S3.PcModuleTypes
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/daemon.h linux-libre-2.6.39-gnu/drivers/char/rio/daemon.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/daemon.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/daemon.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,307 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: daemon.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:09
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)daemon.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_daemon_h__
-#define	__rio_daemon_h__
-
-
-/*
-** structures used on /dev/rio
-*/
-
-struct Error {
-	unsigned int Error;
-	unsigned int Entry;
-	unsigned int Other;
-};
-
-struct DownLoad {
-	char __user *DataP;
-	unsigned int Count;
-	unsigned int ProductCode;
-};
-
-/*
-** A few constants....
-*/
-#ifndef MAX_VERSION_LEN
-#define	MAX_VERSION_LEN	256
-#endif
-
-#ifndef MAX_XP_CTRL_LEN
-#define	MAX_XP_CTRL_LEN 16	/* ALSO IN PORT.H */
-#endif
-
-struct PortSetup {
-	unsigned int From;		/* Set/Clear XP & IXANY Control from this port.... */
-	unsigned int To;		/* .... to this port */
-	unsigned int XpCps;		/* at this speed */
-	char XpOn[MAX_XP_CTRL_LEN];	/* this is the start string */
-	char XpOff[MAX_XP_CTRL_LEN];	/* this is the stop string */
-	u8 IxAny;			/* enable/disable IXANY */
-	u8 IxOn;			/* enable/disable IXON */
-	u8 Lock;			/* lock port params */
-	u8 Store;			/* store params across closes */
-	u8 Drain;			/* close only when drained */
-};
-
-struct LpbReq {
-	unsigned int Host;
-	unsigned int Link;
-	struct LPB __user *LpbP;
-};
-
-struct RupReq {
-	unsigned int HostNum;
-	unsigned int RupNum;
-	struct RUP __user *RupP;
-};
-
-struct PortReq {
-	unsigned int SysPort;
-	struct Port __user *PortP;
-};
-
-struct StreamInfo {
-	unsigned int SysPort;
-	int RQueue;
-	int WQueue;
-};
-
-struct HostReq {
-	unsigned int HostNum;
-	struct Host __user *HostP;
-};
-
-struct HostDpRam {
-	unsigned int HostNum;
-	struct DpRam __user *DpRamP;
-};
-
-struct DebugCtrl {
-	unsigned int SysPort;
-	unsigned int Debug;
-	unsigned int Wait;
-};
-
-struct MapInfo {
-	unsigned int FirstPort;		/* 8 ports, starting from this (tty) number */
-	unsigned int RtaUnique;		/* reside on this RTA (unique number) */
-};
-
-struct MapIn {
-	unsigned int NumEntries;	/* How many port sets are we mapping? */
-	struct MapInfo *MapInfoP;	/* Pointer to (user space) info */
-};
-
-struct SendPack {
-	unsigned int PortNum;
-	unsigned char Len;
-	unsigned char Data[PKT_MAX_DATA_LEN];
-};
-
-struct SpecialRupCmd {
-	struct PKT Packet;
-	unsigned short Host;
-	unsigned short RupNum;
-};
-
-struct IdentifyRta {
-	unsigned long RtaUnique;
-	u8 ID;
-};
-
-struct KillNeighbour {
-	unsigned long UniqueNum;
-	u8 Link;
-};
-
-struct rioVersion {
-	char version[MAX_VERSION_LEN];
-	char relid[MAX_VERSION_LEN];
-	int buildLevel;
-	char buildDate[MAX_VERSION_LEN];
-};
-
-
-/*
-**	RIOC commands are for the daemon type operations
-**
-** 09.12.1998 ARG - ESIL 0776 part fix
-** Definition for 'RIOC' also appears in rioioctl.h, so we'd better do a
-** #ifndef here first.
-** rioioctl.h also now has #define 'RIO_QUICK_CHECK' as this ioctl is now
-** allowed to be used by customers.
-*/
-#ifndef RIOC
-#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
-#endif
-
-/*
-** Boot stuff
-*/
-#define	RIO_GET_TABLE     (RIOC | 100)
-#define RIO_PUT_TABLE     (RIOC | 101)
-#define RIO_ASSIGN_RTA    (RIOC | 102)
-#define RIO_DELETE_RTA    (RIOC | 103)
-#define	RIO_HOST_FOAD	  (RIOC | 104)
-#define	RIO_QUICK_CHECK	  (RIOC | 105)
-#define RIO_SIGNALS_ON    (RIOC | 106)
-#define RIO_SIGNALS_OFF   (RIOC | 107)
-#define	RIO_CHANGE_NAME   (RIOC | 108)
-#define RIO_DOWNLOAD      (RIOC | 109)
-#define	RIO_GET_LOG	  (RIOC | 110)
-#define	RIO_SETUP_PORTS   (RIOC | 111)
-#define RIO_ALL_MODEM     (RIOC | 112)
-
-/*
-** card state, debug stuff
-*/
-#define	RIO_NUM_HOSTS	  (RIOC | 120)
-#define	RIO_HOST_LPB	  (RIOC | 121)
-#define	RIO_HOST_RUP	  (RIOC | 122)
-#define	RIO_HOST_PORT	  (RIOC | 123)
-#define	RIO_PARMS 	  (RIOC | 124)
-#define RIO_HOST_REQ	  (RIOC | 125)
-#define	RIO_READ_CONFIG	  (RIOC | 126)
-#define	RIO_SET_CONFIG	  (RIOC | 127)
-#define	RIO_VERSID	  (RIOC | 128)
-#define	RIO_FLAGS	  (RIOC | 129)
-#define	RIO_SETDEBUG	  (RIOC | 130)
-#define	RIO_GETDEBUG	  (RIOC | 131)
-#define	RIO_READ_LEVELS   (RIOC | 132)
-#define	RIO_SET_FAST_BUS  (RIOC | 133)
-#define	RIO_SET_SLOW_BUS  (RIOC | 134)
-#define	RIO_SET_BYTE_MODE (RIOC | 135)
-#define	RIO_SET_WORD_MODE (RIOC | 136)
-#define RIO_STREAM_INFO   (RIOC | 137)
-#define	RIO_START_POLLER  (RIOC | 138)
-#define	RIO_STOP_POLLER   (RIOC | 139)
-#define	RIO_LAST_ERROR    (RIOC | 140)
-#define	RIO_TICK	  (RIOC | 141)
-#define	RIO_TOCK	  (RIOC | 241)	/* I did this on purpose, you know. */
-#define	RIO_SEND_PACKET   (RIOC | 142)
-#define	RIO_SET_BUSY	  (RIOC | 143)
-#define	SPECIAL_RUP_CMD   (RIOC | 144)
-#define	RIO_FOAD_RTA      (RIOC | 145)
-#define	RIO_ZOMBIE_RTA    (RIOC | 146)
-#define RIO_IDENTIFY_RTA  (RIOC | 147)
-#define RIO_KILL_NEIGHBOUR (RIOC | 148)
-#define RIO_DEBUG_MEM     (RIOC | 149)
-/*
-** 150 - 167 used.....   See below
-*/
-#define RIO_GET_PORT_SETUP (RIOC | 168)
-#define RIO_RESUME        (RIOC | 169)
-#define	RIO_MESG	(RIOC | 170)
-#define	RIO_NO_MESG	(RIOC | 171)
-#define	RIO_WHAT_MESG	(RIOC | 172)
-#define RIO_HOST_DPRAM	(RIOC | 173)
-#define RIO_MAP_B50_TO_50	(RIOC | 174)
-#define RIO_MAP_B50_TO_57600	(RIOC | 175)
-#define RIO_MAP_B110_TO_110	(RIOC | 176)
-#define RIO_MAP_B110_TO_115200	(RIOC | 177)
-#define RIO_GET_PORT_PARAMS	(RIOC | 178)
-#define RIO_SET_PORT_PARAMS	(RIOC | 179)
-#define RIO_GET_PORT_TTY	(RIOC | 180)
-#define RIO_SET_PORT_TTY	(RIOC | 181)
-#define RIO_SYSLOG_ONLY	(RIOC | 182)
-#define RIO_SYSLOG_CONS	(RIOC | 183)
-#define RIO_CONS_ONLY	(RIOC | 184)
-#define RIO_BLOCK_OPENS	(RIOC | 185)
-
-/*
-** 02.03.1999 ARG - ESIL 0820 fix :
-** RIOBootMode is no longer use by the driver, so these ioctls
-** are now obsolete :
-**
-#define RIO_GET_BOOT_MODE	(RIOC | 186)
-#define RIO_SET_BOOT_MODE	(RIOC | 187)
-**
-*/
-
-#define RIO_MEM_DUMP	(RIOC | 189)
-#define RIO_READ_REGISTER	(RIOC | 190)
-#define RIO_GET_MODTYPE	(RIOC | 191)
-#define RIO_SET_TIMER	(RIOC | 192)
-#define RIO_READ_CHECK	(RIOC | 196)
-#define RIO_WAITING_FOR_RESTART	(RIOC | 197)
-#define RIO_BIND_RTA	(RIOC | 198)
-#define RIO_GET_BINDINGS	(RIOC | 199)
-#define RIO_PUT_BINDINGS	(RIOC | 200)
-
-#define	RIO_MAKE_DEV		(RIOC | 201)
-#define	RIO_MINOR		(RIOC | 202)
-
-#define	RIO_IDENTIFY_DRIVER	(RIOC | 203)
-#define	RIO_DISPLAY_HOST_CFG	(RIOC | 204)
-
-
-/*
-** MAKE_DEV / MINOR stuff
-*/
-#define	RIO_DEV_DIRECT		0x0000
-#define	RIO_DEV_MODEM		0x0200
-#define	RIO_DEV_XPRINT		0x0400
-#define	RIO_DEV_MASK		0x0600
-
-/*
-** port management, xprint stuff
-*/
-#define	rIOCN(N)	(RIOC|(N))
-#define	rIOCR(N,T)	(RIOC|(N))
-#define	rIOCW(N,T)	(RIOC|(N))
-
-#define	RIO_GET_XP_ON     rIOCR(150,char[16])	/* start xprint string */
-#define	RIO_SET_XP_ON     rIOCW(151,char[16])
-#define	RIO_GET_XP_OFF    rIOCR(152,char[16])	/* finish xprint string */
-#define	RIO_SET_XP_OFF    rIOCW(153,char[16])
-#define	RIO_GET_XP_CPS    rIOCR(154,int)	/* xprint CPS */
-#define	RIO_SET_XP_CPS    rIOCW(155,int)
-#define RIO_GET_IXANY     rIOCR(156,int)	/* ixany allowed? */
-#define RIO_SET_IXANY     rIOCW(157,int)
-#define RIO_SET_IXANY_ON  rIOCN(158)	/* allow ixany */
-#define RIO_SET_IXANY_OFF rIOCN(159)	/* disallow ixany */
-#define RIO_GET_MODEM     rIOCR(160,int)	/* port is modem/direct line? */
-#define RIO_SET_MODEM     rIOCW(161,int)
-#define RIO_SET_MODEM_ON  rIOCN(162)	/* port is a modem */
-#define RIO_SET_MODEM_OFF rIOCN(163)	/* port is direct */
-#define RIO_GET_IXON      rIOCR(164,int)	/* ixon allowed? */
-#define RIO_SET_IXON      rIOCW(165,int)
-#define RIO_SET_IXON_ON   rIOCN(166)	/* allow ixon */
-#define RIO_SET_IXON_OFF  rIOCN(167)	/* disallow ixon */
-
-#define RIO_GET_SIVIEW	  ((('s')<<8) | 106)	/* backwards compatible with SI */
-
-#define	RIO_IOCTL_UNKNOWN	-2
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/errors.h linux-libre-2.6.39-gnu/drivers/char/rio/errors.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/errors.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/errors.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: errors.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)errors.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_errors_h__
-#define	__rio_errors_h__
-
-/*
-** error codes
-*/
-
-#define	NOTHING_WRONG_AT_ALL		0
-#define	BAD_CHARACTER_IN_NAME		1
-#define	TABLE_ENTRY_ISNT_PROPERLY_NULL	2
-#define	UNKNOWN_HOST_NUMBER		3
-#define	ZERO_RTA_ID			4
-#define	BAD_RTA_ID			5
-#define	DUPLICATED_RTA_ID		6
-#define	DUPLICATE_UNIQUE_NUMBER		7
-#define	BAD_TTY_NUMBER			8
-#define	TTY_NUMBER_IN_USE		9
-#define	NAME_USED_TWICE			10
-#define	HOST_ID_NOT_ZERO		11
-#define	BOOT_IN_PROGRESS		12
-#define	COPYIN_FAILED			13
-#define	HOST_FILE_TOO_LARGE		14
-#define	COPYOUT_FAILED			15
-#define	NOT_SUPER_USER			16
-#define	RIO_ALREADY_POLLING		17
-
-#define	ID_NUMBER_OUT_OF_RANGE		18
-#define PORT_NUMBER_OUT_OF_RANGE	19
-#define	HOST_NUMBER_OUT_OF_RANGE	20
-#define	RUP_NUMBER_OUT_OF_RANGE		21
-#define	TTY_NUMBER_OUT_OF_RANGE		22
-#define	LINK_NUMBER_OUT_OF_RANGE	23
-
-#define	HOST_NOT_RUNNING		24
-#define	IOCTL_COMMAND_UNKNOWN		25
-#define	RIO_SYSTEM_HALTED		26
-#define	WAIT_FOR_DRAIN_BROKEN		27
-#define	PORT_NOT_MAPPED_INTO_SYSTEM	28
-#define	EXCLUSIVE_USE_SET		29
-#define	WAIT_FOR_NOT_CLOSING_BROKEN	30
-#define	WAIT_FOR_PORT_TO_OPEN_BROKEN	31
-#define	WAIT_FOR_CARRIER_BROKEN		32
-#define	WAIT_FOR_NOT_IN_USE_BROKEN	33
-#define	WAIT_FOR_CAN_ADD_COMMAND_BROKEN	34
-#define	WAIT_FOR_ADD_COMMAND_BROKEN	35
-#define	WAIT_FOR_NOT_PARAM_BROKEN	36
-#define	WAIT_FOR_RETRY_BROKEN		37
-#define	HOST_HAS_ALREADY_BEEN_BOOTED	38
-#define	UNIT_IS_IN_USE			39
-#define	COULDNT_FIND_ENTRY		40
-#define	RTA_UNIQUE_NUMBER_ZERO		41
-#define	CLOSE_COMMAND_FAILED		42
-#define	WAIT_FOR_CLOSE_BROKEN		43
-#define	CPS_VALUE_OUT_OF_RANGE		44
-#define	ID_ALREADY_IN_USE		45
-#define	SIGNALS_ALREADY_SET		46
-#define	NOT_RECEIVING_PROCESS		47
-#define	RTA_NUMBER_WRONG		48
-#define NO_SUCH_PRODUCT			49
-#define	HOST_SYSPORT_BAD		50
-#define	ID_NOT_TENTATIVE		51
-#define XPRINT_CPS_OUT_OF_RANGE		52
-#define	NOT_ENOUGH_CORE_FOR_PCI_COPY	53
-
-
-#endif				/* __rio_errors_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/func.h linux-libre-2.6.39-gnu/drivers/char/rio/func.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/func.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/func.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,143 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: func.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)func.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __func_h_def
-#define __func_h_def
-
-#include <linux/kdev_t.h>
-
-/* rioboot.c */
-int RIOBootCodeRTA(struct rio_info *, struct DownLoad *);
-int RIOBootCodeHOST(struct rio_info *, struct DownLoad *);
-int RIOBootCodeUNKNOWN(struct rio_info *, struct DownLoad *);
-void msec_timeout(struct Host *);
-int RIOBootRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
-int RIOBootOk(struct rio_info *, struct Host *, unsigned long);
-int RIORtaBound(struct rio_info *, unsigned int);
-void rio_fill_host_slot(int, int, unsigned int, struct Host *);
-
-/* riocmd.c */
-int RIOFoadRta(struct Host *, struct Map *);
-int RIOZombieRta(struct Host *, struct Map *);
-int RIOCommandRta(struct rio_info *, unsigned long, int (*func) (struct Host *, struct Map *));
-int RIOIdentifyRta(struct rio_info *, void __user *);
-int RIOKillNeighbour(struct rio_info *, void __user *);
-int RIOSuspendBootRta(struct Host *, int, int);
-int RIOFoadWakeup(struct rio_info *);
-struct CmdBlk *RIOGetCmdBlk(void);
-void RIOFreeCmdBlk(struct CmdBlk *);
-int RIOQueueCmdBlk(struct Host *, unsigned int, struct CmdBlk *);
-void RIOPollHostCommands(struct rio_info *, struct Host *);
-int RIOWFlushMark(unsigned long, struct CmdBlk *);
-int RIORFlushEnable(unsigned long, struct CmdBlk *);
-int RIOUnUse(unsigned long, struct CmdBlk *);
-
-/* rioctrl.c */
-int riocontrol(struct rio_info *, dev_t, int, unsigned long, int);
-
-int RIOPreemptiveCmd(struct rio_info *, struct Port *, unsigned char);
-
-/* rioinit.c */
-void rioinit(struct rio_info *, struct RioHostInfo *);
-void RIOInitHosts(struct rio_info *, struct RioHostInfo *);
-void RIOISAinit(struct rio_info *, int);
-int RIODoAT(struct rio_info *, int, int);
-caddr_t RIOCheckForATCard(int);
-int RIOAssignAT(struct rio_info *, int, void __iomem *, int);
-int RIOBoardTest(unsigned long, void __iomem *, unsigned char, int);
-void RIOAllocDataStructs(struct rio_info *);
-void RIOSetupDataStructs(struct rio_info *);
-int RIODefaultName(struct rio_info *, struct Host *, unsigned int);
-struct rioVersion *RIOVersid(void);
-void RIOHostReset(unsigned int, struct DpRam __iomem *, unsigned int);
-
-/* riointr.c */
-void RIOTxEnable(char *);
-void RIOServiceHost(struct rio_info *, struct Host *);
-int riotproc(struct rio_info *, struct ttystatics *, int, int);
-
-/* rioparam.c */
-int RIOParam(struct Port *, int, int, int);
-int RIODelay(struct Port *PortP, int);
-int RIODelay_ni(struct Port *PortP, int);
-void ms_timeout(struct Port *);
-int can_add_transmit(struct PKT __iomem **, struct Port *);
-void add_transmit(struct Port *);
-void put_free_end(struct Host *, struct PKT __iomem *);
-int can_remove_receive(struct PKT __iomem **, struct Port *);
-void remove_receive(struct Port *);
-
-/* rioroute.c */
-int RIORouteRup(struct rio_info *, unsigned int, struct Host *, struct PKT __iomem *);
-void RIOFixPhbs(struct rio_info *, struct Host *, unsigned int);
-unsigned int GetUnitType(unsigned int);
-int RIOSetChange(struct rio_info *);
-int RIOFindFreeID(struct rio_info *, struct Host *, unsigned int *, unsigned int *);
-
-
-/* riotty.c */
-
-int riotopen(struct tty_struct *tty, struct file *filp);
-int riotclose(void *ptr);
-int riotioctl(struct rio_info *, struct tty_struct *, int, caddr_t);
-void ttyseth(struct Port *, struct ttystatics *, struct old_sgttyb *sg);
-
-/* riotable.c */
-int RIONewTable(struct rio_info *);
-int RIOApel(struct rio_info *);
-int RIODeleteRta(struct rio_info *, struct Map *);
-int RIOAssignRta(struct rio_info *, struct Map *);
-int RIOReMapPorts(struct rio_info *, struct Host *, struct Map *);
-int RIOChangeName(struct rio_info *, struct Map *);
-
-#if 0
-/* riodrvr.c */
-struct rio_info *rio_install(struct RioHostInfo *);
-int rio_uninstall(struct rio_info *);
-int rio_open(struct rio_info *, int, struct file *);
-int rio_close(struct rio_info *, struct file *);
-int rio_read(struct rio_info *, struct file *, char *, int);
-int rio_write(struct rio_info *, struct file *f, char *, int);
-int rio_ioctl(struct rio_info *, struct file *, int, char *);
-int rio_select(struct rio_info *, struct file *f, int, struct sel *);
-int rio_intr(char *);
-int rio_isr_thread(char *);
-struct rio_info *rio_info_store(int cmd, struct rio_info *p);
-#endif
-
-extern void rio_copy_to_card(void *from, void __iomem *to, int len);
-extern int rio_minor(struct tty_struct *tty);
-extern int rio_ismodem(struct tty_struct *tty);
-
-extern void rio_start_card_running(struct Host *HostP);
-
-#endif				/* __func_h_def */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/host.h linux-libre-2.6.39-gnu/drivers/char/rio/host.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/host.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/host.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,123 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: host.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:10
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)host.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_host_h__
-#define __rio_host_h__
-
-/*
-** the host structure - one per host card in the system.
-*/
-
-#define	MAX_EXTRA_UNITS	64
-
-/*
-**    Host data structure. This is used for the software equiv. of
-**    the host.
-*/
-struct Host {
-	struct pci_dev *pdev;
-	unsigned char Type;		/* RIO_EISA, RIO_MCA, ... */
-	unsigned char Ivec;		/* POLLED or ivec number */
-	unsigned char Mode;		/* Control stuff */
-	unsigned char Slot;		/* Slot */
-	void  __iomem *Caddr;		/* KV address of DPRAM */
-	struct DpRam __iomem *CardP;	/* KV address of DPRAM, with overlay */
-	unsigned long PaddrP;		/* Phys. address of DPRAM */
-	char Name[MAX_NAME_LEN];	/* The name of the host */
-	unsigned int UniqueNum;		/* host unique number */
-	spinlock_t HostLock;	/* Lock structure for MPX */
-	unsigned int WorkToBeDone;	/* set to true each interrupt */
-	unsigned int InIntr;		/* Being serviced? */
-	unsigned int IntSrvDone;	/* host's interrupt has been serviced */
-	void (*Copy) (void *, void __iomem *, int);	/* copy func */
-	struct timer_list timer;
-	/*
-	 **               I M P O R T A N T !
-	 **
-	 ** The rest of this data structure is cleared to zero after
-	 ** a RIO_HOST_FOAD command.
-	 */
-
-	unsigned long Flags;			/* Whats going down */
-#define RC_WAITING            0
-#define RC_STARTUP            1
-#define RC_RUNNING            2
-#define RC_STUFFED            3
-#define RC_READY              7
-#define RUN_STATE             7
-/*
-** Boot mode applies to the way in which hosts in this system will
-** boot RTAs
-*/
-#define RC_BOOT_ALL           0x8		/* Boot all RTAs attached */
-#define RC_BOOT_OWN           0x10		/* Only boot RTAs bound to this system */
-#define RC_BOOT_NONE          0x20		/* Don't boot any RTAs (slave mode) */
-
-	struct Top Topology[LINKS_PER_UNIT];	/* one per link */
-	struct Map Mapping[MAX_RUP];		/* Mappings for host */
-	struct PHB __iomem *PhbP;		/* Pointer to the PHB array */
-	unsigned short __iomem *PhbNumP;	/* Ptr to Number of PHB's */
-	struct LPB __iomem *LinkStrP;		/* Link Structure Array */
-	struct RUP __iomem *RupP;		/* Sixteen real rups here */
-	struct PARM_MAP __iomem *ParmMapP;	/* points to the parmmap */
-	unsigned int ExtraUnits[MAX_EXTRA_UNITS];	/* unknown things */
-	unsigned int NumExtraBooted;		/* how many of the above */
-	/*
-	 ** Twenty logical rups.
-	 ** The first sixteen are the real Rup entries (above), the last four
-	 ** are the link RUPs.
-	 */
-	struct UnixRup UnixRups[MAX_RUP + LINKS_PER_UNIT];
-	int timeout_id;				/* For calling 100 ms delays */
-	int timeout_sem;			/* For calling 100 ms delays */
-	unsigned long locks;			/* long req'd for set_bit --RR */
-	char ____end_marker____;
-};
-#define Control      CardP->DpControl
-#define SetInt       CardP->DpSetInt
-#define ResetTpu     CardP->DpResetTpu
-#define ResetInt     CardP->DpResetInt
-#define Signature    CardP->DpSignature
-#define Sram1        CardP->DpSram1
-#define Sram2        CardP->DpSram2
-#define Sram3        CardP->DpSram3
-#define Scratch      CardP->DpScratch
-#define __ParmMapR   CardP->DpParmMapR
-#define SLX          CardP->DpSlx
-#define Revision     CardP->DpRevision
-#define Unique       CardP->DpUnique
-#define Year         CardP->DpYear
-#define Week         CardP->DpWeek
-
-#define RIO_DUMBPARM 0x0860	/* what not to expect */
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/link.h linux-libre-2.6.39-gnu/drivers/char/rio/link.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/link.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/link.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,96 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                      L I N K
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _link_h
-#define _link_h 1
-
-/*************************************************
- * Define the Link Status stuff
- ************************************************/
-/* Boot request stuff */
-#define BOOT_REQUEST       ((ushort) 0)	/* Request for a boot */
-#define BOOT_ABORT         ((ushort) 1)	/* Abort a boot */
-#define BOOT_SEQUENCE      ((ushort) 2)	/* Packet with the number of packets
-					   and load address */
-#define BOOT_COMPLETED     ((ushort) 3)	/* Boot completed */
-
-
-struct LPB {
-	u16 link_number;	/* Link Number */
-	u16 in_ch;	/* Link In Channel */
-	u16 out_ch;	/* Link Out Channel */
-	u8 attached_serial[4];  /* Attached serial number */
-	u8 attached_host_serial[4];
-	/* Serial number of Host who
-	   booted the other end */
-	u16 descheduled;	/* Currently Descheduled */
-	u16 state;		/* Current state */
-	u16 send_poll;		/* Send a Poll Packet */
-	u16 ltt_p;	/* Process Descriptor */
-	u16 lrt_p;	/* Process Descriptor */
-	u16 lrt_status;		/* Current lrt status */
-	u16 ltt_status;		/* Current ltt status */
-	u16 timeout;		/* Timeout value */
-	u16 topology;		/* Topology bits */
-	u16 mon_ltt;
-	u16 mon_lrt;
-	u16 WaitNoBoot;	/* Secs to hold off booting */
-	u16 add_packet_list;	/* Add packets to here */
-	u16 remove_packet_list;	/* Send packets from here */
-
-	u16 lrt_fail_chan;	/* Lrt's failure channel */
-	u16 ltt_fail_chan;	/* Ltt's failure channel */
-
-	/* RUP structure for HOST to driver communications */
-	struct RUP rup;
-	struct RUP link_rup;	/* RUP for the link (POLL,
-				   topology etc.) */
-	u16 attached_link;	/* Number of attached link */
-	u16 csum_errors;	/* csum errors */
-	u16 num_disconnects;	/* number of disconnects */
-	u16 num_sync_rcvd;	/* # sync's received */
-	u16 num_sync_rqst;	/* # sync requests */
-	u16 num_tx;		/* Num pkts sent */
-	u16 num_rx;		/* Num pkts received */
-	u16 module_attached;	/* Module tpyes of attached */
-	u16 led_timeout;	/* LED timeout */
-	u16 first_port;		/* First port to service */
-	u16 last_port;		/* Last port to service */
-};
-
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/linux_compat.h linux-libre-2.6.39-gnu/drivers/char/rio/linux_compat.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/linux_compat.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/linux_compat.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/*
- * (C) 2000 R.E.Wolff@BitWizard.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
-
-#include <linux/interrupt.h>
-
-
-#define DEBUG_ALL
-
-struct ttystatics {
-	struct termios tm;
-};
-
-extern int rio_debug;
-
-#define RIO_DEBUG_INIT         0x000001
-#define RIO_DEBUG_BOOT         0x000002
-#define RIO_DEBUG_CMD          0x000004
-#define RIO_DEBUG_CTRL         0x000008
-#define RIO_DEBUG_INTR         0x000010
-#define RIO_DEBUG_PARAM        0x000020
-#define RIO_DEBUG_ROUTE        0x000040
-#define RIO_DEBUG_TABLE        0x000080
-#define RIO_DEBUG_TTY          0x000100
-#define RIO_DEBUG_FLOW         0x000200
-#define RIO_DEBUG_MODEMSIGNALS 0x000400
-#define RIO_DEBUG_PROBE        0x000800
-#define RIO_DEBUG_CLEANUP      0x001000
-#define RIO_DEBUG_IFLOW        0x002000
-#define RIO_DEBUG_PFE          0x004000
-#define RIO_DEBUG_REC          0x008000
-#define RIO_DEBUG_SPINLOCK     0x010000
-#define RIO_DEBUG_DELAY        0x020000
-#define RIO_DEBUG_MOD_COUNT    0x040000
-
-
-/* Copied over from riowinif.h . This is ugly. The winif file declares
-also much other stuff which is incompatible with the headers from
-the older driver. The older driver includes "brates.h" which shadows
-the definitions from Linux, and is incompatible... */
-
-/* RxBaud and TxBaud definitions... */
-#define	RIO_B0			0x00	/* RTS / DTR signals dropped */
-#define	RIO_B50			0x01	/* 50 baud */
-#define	RIO_B75			0x02	/* 75 baud */
-#define	RIO_B110		0x03	/* 110 baud */
-#define	RIO_B134		0x04	/* 134.5 baud */
-#define	RIO_B150		0x05	/* 150 baud */
-#define	RIO_B200		0x06	/* 200 baud */
-#define	RIO_B300		0x07	/* 300 baud */
-#define	RIO_B600		0x08	/* 600 baud */
-#define	RIO_B1200		0x09	/* 1200 baud */
-#define	RIO_B1800		0x0A	/* 1800 baud */
-#define	RIO_B2400		0x0B	/* 2400 baud */
-#define	RIO_B4800		0x0C	/* 4800 baud */
-#define	RIO_B9600		0x0D	/* 9600 baud */
-#define	RIO_B19200		0x0E	/* 19200 baud */
-#define	RIO_B38400		0x0F	/* 38400 baud */
-#define	RIO_B56000		0x10	/* 56000 baud */
-#define	RIO_B57600		0x11	/* 57600 baud */
-#define	RIO_B64000		0x12	/* 64000 baud */
-#define	RIO_B115200		0x13	/* 115200 baud */
-#define	RIO_B2000		0x14	/* 2000 baud */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/Makefile linux-libre-2.6.39-gnu/drivers/char/rio/Makefile
--- linux-libre-2.6.38-gnu/drivers/char/rio/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,12 +0,0 @@
-#
-# Makefile for the linux rio-subsystem.
-#
-# (C) R.E.Wolff@BitWizard.nl 
-# 
-# This file is GPL. See other files for the full Blurb. I'm lazy today. 
-#
-
-obj-$(CONFIG_RIO) += rio.o
-
-rio-y := rio_linux.o rioinit.o rioboot.o riocmd.o rioctrl.o riointr.o \
-            rioparam.o rioroute.o riotable.o riotty.o
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/map.h linux-libre-2.6.39-gnu/drivers/char/rio/map.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/map.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/map.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: map.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:11
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)map.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_map_h__
-#define __rio_map_h__
-
-/*
-** mapping structure passed to and from the config.rio program to
-** determine the current topology of the world
-*/
-
-#define MAX_MAP_ENTRY 17
-#define	TOTAL_MAP_ENTRIES (MAX_MAP_ENTRY*RIO_SLOTS)
-#define	MAX_NAME_LEN 32
-
-struct Map {
-	unsigned int HostUniqueNum;	/* Supporting hosts unique number */
-	unsigned int RtaUniqueNum;	/* Unique number */
-	/*
-	 ** The next two IDs must be swapped on big-endian architectures
-	 ** when using a v2.04 /etc/rio/config with a v3.00 driver (when
-	 ** upgrading for example).
-	 */
-	unsigned short ID;		/* ID used in the subnet */
-	unsigned short ID2;		/* ID of 2nd block of 8 for 16 port */
-	unsigned long Flags;		/* Booted, ID Given, Disconnected */
-	unsigned long SysPort;		/* First tty mapped to this port */
-	struct Top Topology[LINKS_PER_UNIT];	/* ID connected to each link */
-	char Name[MAX_NAME_LEN];	/* Cute name by which RTA is known */
-};
-
-/*
-** Flag values:
-*/
-#define	RTA_BOOTED		0x00000001
-#define RTA_NEWBOOT		0x00000010
-#define	MSG_DONE		0x00000020
-#define	RTA_INTERCONNECT	0x00000040
-#define	RTA16_SECOND_SLOT	0x00000080
-#define	BEEN_HERE		0x00000100
-#define SLOT_TENTATIVE		0x40000000
-#define SLOT_IN_USE		0x80000000
-
-/*
-** HostUniqueNum is the unique number from the host card that this RTA
-** is to be connected to.
-** RtaUniqueNum is the unique number of the RTA concerned. It will be ZERO
-** if the slot in the table is unused. If it is the same as the HostUniqueNum
-** then this slot represents a host card.
-** Flags contains current boot/route state info
-** SysPort is a value in the range 0-504, being the number of the first tty
-** on this RTA. Each RTA supports 8 ports. The SysPort value must be modulo 8.
-** SysPort 0-127 correspond to /dev/ttyr001 to /dev/ttyr128, with minor
-** numbers 0-127. SysPort 128-255 correspond to /dev/ttyr129 to /dev/ttyr256,
-** again with minor numbers 0-127, and so on for SysPorts 256-383 and 384-511
-** ID will be in the range 0-16 for a `known' RTA. ID will be 0xFFFF for an
-** unused slot/unknown ID etc.
-** The Topology array contains the ID of the unit connected to each of the
-** four links on this unit. The entry will be 0xFFFF if NOTHING is connected
-** to the link, or will be 0xFF00 if an UNKNOWN unit is connected to the link.
-** The Name field is a null-terminated string, upto 31 characters, containing
-** the 'cute' name that the sysadmin/users know the RTA by. It is permissible
-** for this string to contain any character in the range \040 to \176 inclusive.
-** In particular, ctrl sequences and DEL (0x7F, \177) are not allowed. The
-** special character '%' IS allowable, and needs no special action.
-**
-*/
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/param.h linux-libre-2.6.39-gnu/drivers/char/rio/param.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/param.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/param.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,55 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: param.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)param.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_param_h__
-#define __rio_param_h__
-
-/*
-** the param command block, as used in OPEN and PARAM calls.
-*/
-
-struct phb_param {
-	u8 Cmd;			/* It is very important that these line up */
-	u8 Cor1;		/* with what is expected at the other end. */
-	u8 Cor2;		/* to confirm that you've got it right,    */
-	u8 Cor4;		/* check with cirrus/cirrus.h              */
-	u8 Cor5;
-	u8 TxXon;		/* Transmit X-On character */
-	u8 TxXoff;		/* Transmit X-Off character */
-	u8 RxXon;		/* Receive X-On character */
-	u8 RxXoff;		/* Receive X-Off character */
-	u8 LNext;		/* Literal-next character */
-	u8 TxBaud;		/* Transmit baudrate */
-	u8 RxBaud;		/* Receive baudrate */
-};
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/parmmap.h linux-libre-2.6.39-gnu/drivers/char/rio/parmmap.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/parmmap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/parmmap.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******               H O S T   M E M O R Y  M A P
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-6/4/1991   jonb		     Made changes to accommodate Mips R3230 bus
- ***************************************************************************/
-
-#ifndef _parmap_h
-#define _parmap_h
-
-typedef struct PARM_MAP PARM_MAP;
-
-struct PARM_MAP {
-	u16 phb_ptr;	/* Pointer to the PHB array */
-	u16 phb_num_ptr;	/* Ptr to Number of PHB's */
-	u16 free_list;	/* Free List pointer */
-	u16 free_list_end;	/* Free List End pointer */
-	u16 q_free_list_ptr;	/* Ptr to Q_BUF variable */
-	u16 unit_id_ptr;	/* Unit Id */
-	u16 link_str_ptr;	/* Link Structure Array */
-	u16 bootloader_1;	/* 1st Stage Boot Loader */
-	u16 bootloader_2;	/* 2nd Stage Boot Loader */
-	u16 port_route_map_ptr;	/* Port Route Map */
-	u16 route_ptr;		/* Unit Route Map */
-	u16 map_present;	/* Route Map present */
-	s16 pkt_num;		/* Total number of packets */
-	s16 q_num;		/* Total number of Q packets */
-	u16 buffers_per_port;	/* Number of buffers per port */
-	u16 heap_size;		/* Initial size of heap */
-	u16 heap_left;		/* Current Heap left */
-	u16 error;		/* Error code */
-	u16 tx_max;		/* Max number of tx pkts per phb */
-	u16 rx_max;		/* Max number of rx pkts per phb */
-	u16 rx_limit;		/* For high / low watermarks */
-	s16 links;		/* Links to use */
-	s16 timer;		/* Interrupts per second */
-	u16 rups;		/* Pointer to the RUPs */
-	u16 max_phb;		/* Mostly for debugging */
-	u16 living;		/* Just increments!! */
-	u16 init_done;		/* Initialisation over */
-	u16 booting_link;
-	u16 idle_count;		/* Idle time counter */
-	u16 busy_count;		/* Busy counter */
-	u16 idle_control;	/* Control Idle Process */
-	u16 tx_intr;		/* TX interrupt pending */
-	u16 rx_intr;		/* RX interrupt pending */
-	u16 rup_intr;		/* RUP interrupt pending */
-};
-
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/pci.h linux-libre-2.6.39-gnu/drivers/char/rio/pci.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/pci.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,72 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: pci.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)pci.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_pci_h__
-#define	__rio_pci_h__
-
-/*
-** PCI stuff
-*/
-
-#define	PCITpFastClock		0x80
-#define	PCITpSlowClock		0x00
-#define	PCITpFastLinks	        0x40
-#define	PCITpSlowLinks	        0x00
-#define	PCITpIntEnable		0x04
-#define	PCITpIntDisable		0x00
-#define	PCITpBusEnable		0x02
-#define	PCITpBusDisable		0x00
-#define	PCITpBootFromRam	0x01
-#define	PCITpBootFromLink	0x00
-
-#define	RIO_PCI_VENDOR		0x11CB
-#define	RIO_PCI_DEVICE		0x8000
-#define	RIO_PCI_BASE_CLASS	0x02
-#define	RIO_PCI_SUB_CLASS	0x80
-#define	RIO_PCI_PROG_IFACE	0x00
-
-#define RIO_PCI_RID		0x0008
-#define RIO_PCI_BADR0		0x0010
-#define RIO_PCI_INTLN		0x003C
-#define RIO_PCI_INTPIN		0x003D
-
-#define	RIO_PCI_MEM_SIZE	65536
-
-#define	RIO_PCI_TURBO_TP	0x80
-#define	RIO_PCI_FAST_LINKS	0x40
-#define	RIO_PCI_INT_ENABLE	0x04
-#define	RIO_PCI_TP_BUS_ENABLE	0x02
-#define	RIO_PCI_BOOT_FROM_RAM	0x01
-
-#define	RIO_PCI_DEFAULT_MODE	0x05
-
-#endif				/* __rio_pci_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/phb.h linux-libre-2.6.39-gnu/drivers/char/rio/phb.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/phb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/phb.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,142 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                 P H B     H E A D E R                        *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra, Jeremy Rolls
- Date    : 
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _phb_h
-#define _phb_h 1
-
-/*************************************************
- * Handshake asserted. Deasserted by the LTT(s)
- ************************************************/
-#define PHB_HANDSHAKE_SET      ((ushort) 0x001)	/* Set by LRT */
-
-#define PHB_HANDSHAKE_RESET     ((ushort) 0x002)	/* Set by ISR / driver */
-
-#define PHB_HANDSHAKE_FLAGS     (PHB_HANDSHAKE_RESET | PHB_HANDSHAKE_SET)
-						/* Reset by ltt */
-
-
-/*************************************************
- * Maximum number of PHB's
- ************************************************/
-#define MAX_PHB               ((ushort) 128)	/* range 0-127 */
-
-/*************************************************
- * Defines for the mode fields
- ************************************************/
-#define TXPKT_INCOMPLETE        0x0001	/* Previous tx packet not completed */
-#define TXINTR_ENABLED          0x0002	/* Tx interrupt is enabled */
-#define TX_TAB3                 0x0004	/* TAB3 mode */
-#define TX_OCRNL                0x0008	/* OCRNL mode */
-#define TX_ONLCR                0x0010	/* ONLCR mode */
-#define TX_SENDSPACES           0x0020	/* Send n spaces command needs
-					   completing */
-#define TX_SENDNULL             0x0040	/* Escaping NULL needs completing */
-#define TX_SENDLF               0x0080	/* LF -> CR LF needs completing */
-#define TX_PARALLELBUG          0x0100	/* CD1400 LF -> CR LF bug on parallel
-					   port */
-#define TX_HANGOVER             (TX_SENDSPACES | TX_SENDLF | TX_SENDNULL)
-#define TX_DTRFLOW		0x0200	/* DTR tx flow control */
-#define	TX_DTRFLOWED		0x0400	/* DTR is low - don't allow more data
-					   into the FIFO */
-#define	TX_DATAINFIFO		0x0800	/* There is data in the FIFO */
-#define	TX_BUSY			0x1000	/* Data in FIFO, shift or holding regs */
-
-#define RX_SPARE	        0x0001	/* SPARE */
-#define RXINTR_ENABLED          0x0002	/* Rx interrupt enabled */
-#define RX_ICRNL                0x0008	/* ICRNL mode */
-#define RX_INLCR                0x0010	/* INLCR mode */
-#define RX_IGNCR                0x0020	/* IGNCR mode */
-#define RX_CTSFLOW              0x0040	/* CTSFLOW enabled */
-#define RX_IXOFF                0x0080	/* IXOFF enabled */
-#define RX_CTSFLOWED            0x0100	/* CTSFLOW and CTS dropped */
-#define RX_IXOFFED              0x0200	/* IXOFF and xoff sent */
-#define RX_BUFFERED		0x0400	/* Try and pass on complete packets */
-
-#define PORT_ISOPEN             0x0001	/* Port open? */
-#define PORT_HUPCL              0x0002	/* Hangup on close? */
-#define PORT_MOPENPEND          0x0004	/* Modem open pending */
-#define PORT_ISPARALLEL         0x0008	/* Parallel port */
-#define PORT_BREAK              0x0010	/* Port on break */
-#define PORT_STATUSPEND		0x0020	/* Status packet pending */
-#define PORT_BREAKPEND          0x0040	/* Break packet pending */
-#define PORT_MODEMPEND          0x0080	/* Modem status packet pending */
-#define PORT_PARALLELBUG        0x0100	/* CD1400 LF -> CR LF bug on parallel
-					   port */
-#define PORT_FULLMODEM          0x0200	/* Full modem signals */
-#define PORT_RJ45               0x0400	/* RJ45 connector - no RI signal */
-#define PORT_RESTRICTED         0x0600	/* Restricted connector - no RI / DTR */
-
-#define PORT_MODEMBITS          0x0600	/* Mask for modem fields */
-
-#define PORT_WCLOSE             0x0800	/* Waiting for close */
-#define	PORT_HANDSHAKEFIX	0x1000	/* Port has H/W flow control fix */
-#define	PORT_WASPCLOSED		0x2000	/* Port closed with PCLOSE */
-#define	DUMPMODE		0x4000	/* Dump RTA mem */
-#define	READ_REG		0x8000	/* Read CD1400 register */
-
-
-
-/**************************************************************************
- * PHB Structure
- * A  few words.
- *
- * Normally Packets are added to the end of the list and removed from
- * the start. The pointer tx_add points to a SPACE to put a Packet.
- * The pointer tx_remove points to the next Packet to remove
- *************************************************************************/
-
-struct PHB {
-	u8 source;
-	u8 handshake;
-	u8 status;
-	u16 timeout;		/* Maximum of 1.9 seconds */
-	u8 link;		/* Send down this link */
-	u8 destination;
-	u16 tx_start;
-	u16 tx_end;
-	u16 tx_add;
-	u16 tx_remove;
-
-	u16 rx_start;
-	u16 rx_end;
-	u16 rx_add;
-	u16 rx_remove;
-
-};
-
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/pkt.h linux-libre-2.6.39-gnu/drivers/char/rio/pkt.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/pkt.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/pkt.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,77 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******            P A C K E T   H E A D E R   F I L E
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _pkt_h
-#define _pkt_h 1
-
-#define PKT_CMD_BIT     ((ushort) 0x080)
-#define PKT_CMD_DATA    ((ushort) 0x080)
-
-#define PKT_ACK         ((ushort) 0x040)
-
-#define PKT_TGL         ((ushort) 0x020)
-
-#define PKT_LEN_MASK    ((ushort) 0x07f)
-
-#define DATA_WNDW       ((ushort) 0x10)
-#define PKT_TTL_MASK    ((ushort) 0x0f)
-
-#define PKT_MAX_DATA_LEN   72
-
-#define PKT_LENGTH         sizeof(struct PKT)
-#define SYNC_PKT_LENGTH    (PKT_LENGTH + 4)
-
-#define CONTROL_PKT_LEN_MASK PKT_LEN_MASK
-#define CONTROL_PKT_CMD_BIT  PKT_CMD_BIT
-#define CONTROL_PKT_ACK (PKT_ACK << 8)
-#define CONTROL_PKT_TGL (PKT_TGL << 8)
-#define CONTROL_PKT_TTL_MASK (PKT_TTL_MASK << 8)
-#define CONTROL_DATA_WNDW  (DATA_WNDW << 8)
-
-struct PKT {
-	u8 dest_unit;		/* Destination Unit Id */
-	u8 dest_port;		/* Destination POrt */
-	u8 src_unit;		/* Source Unit Id */
-	u8 src_port;		/* Source POrt */
-	u8 len;
-	u8 control;
-	u8 data[PKT_MAX_DATA_LEN];
-	/* Actual data :-) */
-	u16 csum;		/* C-SUM */
-};
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/port.h linux-libre-2.6.39-gnu/drivers/char/rio/port.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/port.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/port.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,179 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: port.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:12
-**	Retrieved	: 11/6/98 11:34:21
-**
-**  ident @(#)port.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_port_h__
-#define	__rio_port_h__
-
-/*
-**	Port data structure
-*/
-struct Port {
-	struct gs_port gs;
-	int PortNum;			/* RIO port no., 0-511 */
-	struct Host *HostP;
-	void __iomem *Caddr;
-	unsigned short HostPort;	/* Port number on host card */
-	unsigned char RupNum;		/* Number of RUP for port */
-	unsigned char ID2;		/* Second ID of RTA for port */
-	unsigned long State;		/* FLAGS for open & xopen */
-#define	RIO_LOPEN	0x00001		/* Local open */
-#define	RIO_MOPEN	0x00002		/* Modem open */
-#define	RIO_WOPEN	0x00004		/* Waiting for open */
-#define	RIO_CLOSING	0x00008		/* The port is being close */
-#define	RIO_XPBUSY	0x00010		/* Transparent printer busy */
-#define	RIO_BREAKING	0x00020		/* Break in progress */
-#define	RIO_DIRECT	0x00040		/* Doing Direct output */
-#define	RIO_EXCLUSIVE	0x00080		/* Stream open for exclusive use */
-#define	RIO_NDELAY	0x00100		/* Stream is open FNDELAY */
-#define	RIO_CARR_ON	0x00200		/* Stream has carrier present */
-#define	RIO_XPWANTR	0x00400		/* Stream wanted by Xprint */
-#define	RIO_RBLK	0x00800		/* Stream is read-blocked */
-#define	RIO_BUSY	0x01000		/* Stream is BUSY for write */
-#define	RIO_TIMEOUT	0x02000		/* Stream timeout in progress */
-#define	RIO_TXSTOP	0x04000		/* Stream output is stopped */
-#define	RIO_WAITFLUSH	0x08000		/* Stream waiting for flush */
-#define	RIO_DYNOROD	0x10000		/* Drain failed */
-#define	RIO_DELETED	0x20000		/* RTA has been deleted */
-#define RIO_ISSCANCODE	0x40000		/* This line is in scancode mode */
-#define	RIO_USING_EUC	0x100000	/* Using extended Unix chars */
-#define	RIO_CAN_COOK	0x200000	/* This line can do cooking */
-#define RIO_TRIAD_MODE  0x400000	/* Enable TRIAD special ops. */
-#define RIO_TRIAD_BLOCK 0x800000	/* Next read will block */
-#define RIO_TRIAD_FUNC  0x1000000	/* Seen a function key coming in */
-#define RIO_THROTTLE_RX 0x2000000	/* RX needs to be throttled. */
-
-	unsigned long Config;		/* FLAGS for NOREAD.... */
-#define	RIO_NOREAD	0x0001		/* Are not allowed to read port */
-#define	RIO_NOWRITE	0x0002		/* Are not allowed to write port */
-#define	RIO_NOXPRINT	0x0004		/* Are not allowed to xprint port */
-#define	RIO_NOMASK	0x0007		/* All not allowed things */
-#define RIO_IXANY	0x0008		/* Port is allowed ixany */
-#define	RIO_MODEM	0x0010		/* Stream is a modem device */
-#define	RIO_IXON	0x0020		/* Port is allowed ixon */
-#define RIO_WAITDRAIN	0x0040		/* Wait for port to completely drain */
-#define RIO_MAP_50_TO_50	0x0080	/* Map 50 baud to 50 baud */
-#define RIO_MAP_110_TO_110	0x0100	/* Map 110 baud to 110 baud */
-
-/*
-** 15.10.1998 ARG - ESIL 0761 prt fix
-** As LynxOS does not appear to support Hardware Flow Control .....
-** Define our own flow control flags in 'Config'.
-*/
-#define RIO_CTSFLOW	0x0200		/* RIO's own CTSFLOW flag */
-#define RIO_RTSFLOW	0x0400		/* RIO's own RTSFLOW flag */
-
-
-	struct PHB __iomem *PhbP;	/* pointer to PHB for port */
-	u16 __iomem *TxAdd;		/* Add packets here */
-	u16 __iomem *TxStart;		/* Start of add array */
-	u16 __iomem *TxEnd;		/* End of add array */
-	u16 __iomem *RxRemove;		/* Remove packets here */
-	u16 __iomem *RxStart;		/* Start of remove array */
-	u16 __iomem *RxEnd;		/* End of remove array */
-	unsigned int RtaUniqueNum;	/* Unique number of RTA */
-	unsigned short PortState;	/* status of port */
-	unsigned short ModemState;	/* status of modem lines */
-	unsigned long ModemLines;	/* Modem bits sent to RTA */
-	unsigned char CookMode;		/* who expands CR/LF? */
-	unsigned char ParamSem;		/* Prevent write during param */
-	unsigned char Mapped;		/* if port mapped onto host */
-	unsigned char SecondBlock;	/* if port belongs to 2nd block
-				   		of 16 port RTA */
-	unsigned char InUse;		/* how many pre-emptive cmds */
-	unsigned char Lock;		/* if params locked */
-	unsigned char Store;		/* if params stored across closes */
-	unsigned char FirstOpen;	/* TRUE if first time port opened */
-	unsigned char FlushCmdBodge;	/* if doing a (non)flush */
-	unsigned char MagicFlags;	/* require intr processing */
-#define	MAGIC_FLUSH	0x01		/* mirror of WflushFlag */
-#define	MAGIC_REBOOT	0x02		/* RTA re-booted, re-open ports */
-#define	MORE_OUTPUT_EYGOR 0x04		/* riotproc failed to empty clists */
-	unsigned char WflushFlag;	/* 1 How many WFLUSHs active */
-/*
-** Transparent print stuff
-*/
-	struct Xprint {
-#ifndef MAX_XP_CTRL_LEN
-#define MAX_XP_CTRL_LEN		16	/* ALSO IN DAEMON.H */
-#endif
-		unsigned int XpCps;
-		char XpOn[MAX_XP_CTRL_LEN];
-		char XpOff[MAX_XP_CTRL_LEN];
-		unsigned short XpLen;	/* strlen(XpOn)+strlen(XpOff) */
-		unsigned char XpActive;
-		unsigned char XpLastTickOk;	/* TRUE if we can process */
-#define	XP_OPEN		00001
-#define	XP_RUNABLE	00002
-		struct ttystatics *XttyP;
-	} Xprint;
-	unsigned char RxDataStart;
-	unsigned char Cor2Copy;		/* copy of COR2 */
-	char *Name;			/* points to the Rta's name */
-	char *TxRingBuffer;
-	unsigned short TxBufferIn;	/* New data arrives here */
-	unsigned short TxBufferOut;	/* Intr removes data here */
-	unsigned short OldTxBufferOut;	/* Indicates if draining */
-	int TimeoutId;			/* Timeout ID */
-	unsigned int Debug;
-	unsigned char WaitUntilBooted;	/* True if open should block */
-	unsigned int statsGather;	/* True if gathering stats */
-	unsigned long txchars;		/* Chars transmitted */
-	unsigned long rxchars;		/* Chars received */
-	unsigned long opens;		/* port open count */
-	unsigned long closes;		/* port close count */
-	unsigned long ioctls;		/* ioctl count */
-	unsigned char LastRxTgl;	/* Last state of rx toggle bit */
-	spinlock_t portSem;		/* Lock using this sem */
-	int MonitorTstate;		/* Monitoring ? */
-	int timeout_id;			/* For calling 100 ms delays */
-	int timeout_sem;		/* For calling 100 ms delays */
-	int firstOpen;			/* First time open ? */
-	char *p;			/* save the global struc here .. */
-};
-
-struct ModuleInfo {
-	char *Name;
-	unsigned int Flags[4];		/* one per port on a module */
-};
-
-/*
-** This struct is required because trying to grab an entire Port structure
-** runs into problems with differing struct sizes between driver and config.
-*/
-struct PortParams {
-	unsigned int Port;
-	unsigned long Config;
-	unsigned long State;
-	struct ttystatics *TtyP;
-};
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/protsts.h linux-libre-2.6.39-gnu/drivers/char/rio/protsts.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/protsts.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/protsts.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,110 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******      P R O T O C O L    S T A T U S   S T R U C T U R E      *******
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _protsts_h
-#define _protsts_h 1
-
-/*************************************************
- * ACK bit. Last Packet received OK. Set by
- * rxpkt to indicate that the Packet has been
- * received OK and that the LTT must set the ACK
- * bit in the next outward bound Packet
- * and re-set by LTT's after xmit.
- *
- * Gets shoved into rx_status
- ************************************************/
-#define PHB_RX_LAST_PKT_ACKED    ((ushort) 0x080)
-
-/*******************************************************
- * The Rx TOGGLE bit.
- * Stuffed into rx_status by RXPKT
- ******************************************************/
-#define PHB_RX_DATA_WNDW         ((ushort) 0x040)
-
-/*******************************************************
- * The Rx TOGGLE bit. Matches the setting in PKT.H
- * Stuffed into rx_status
- ******************************************************/
-#define PHB_RX_TGL               ((ushort) 0x2000)
-
-
-/*************************************************
- * This bit is set by the LRT to indicate that
- * an ACK (packet) must be returned.
- *
- * Gets shoved into tx_status
- ************************************************/
-#define PHB_TX_SEND_PKT_ACK      ((ushort) 0x08)
-
-/*************************************************
- * Set by LTT to indicate that an ACK is required
- *************************************************/
-#define PHB_TX_ACK_RQRD         ((ushort) 0x01)
-
-
-/*******************************************************
- * The Tx TOGGLE bit.
- * Stuffed into tx_status by RXPKT from the PKT WndW
- * field. Looked by the LTT when the NEXT Packet
- * is going to be sent.
- ******************************************************/
-#define PHB_TX_DATA_WNDW         ((ushort) 0x04)
-
-
-/*******************************************************
- * The Tx TOGGLE bit. Matches the setting in PKT.H
- * Stuffed into tx_status
- ******************************************************/
-#define PHB_TX_TGL               ((ushort) 0x02)
-
-/*******************************************************
- * Request intr bit. Set when the queue has gone quiet
- * and the PHB has requested an interrupt.
- ******************************************************/
-#define PHB_TX_INTR             ((ushort) 0x100)
-
-/*******************************************************
- * SET if the PHB cannot send any more data down the
- * Link
- ******************************************************/
-#define PHB_TX_HANDSHAKE         ((ushort) 0x010)
-
-
-#define RUP_SEND_WNDW		 ((ushort) 0x08) ;
-
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioboard.h linux-libre-2.6.39-gnu/drivers/char/rio/rioboard.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioboard.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioboard.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,275 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	RIO Host Card Hardware Definitions	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	26th April 1999				*/
-/*									*/
-/*	Version		:	1.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1999	*
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
- *									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the RIO board hardware	*/
-/*									*/
-/************************************************************************/
-
-#ifndef	_rioboard_h		/* If RIOBOARD.H not already defined */
-#define	_rioboard_h    1
-
-/*****************************************************************************
-***********************                                ***********************
-***********************   Hardware Control Registers   ***********************
-***********************                                ***********************
-*****************************************************************************/
-
-/* Hardware Registers... */
-
-#define	RIO_REG_BASE	0x7C00	/* Base of control registers */
-
-#define	RIO_CONFIG	RIO_REG_BASE + 0x0000	/* WRITE: Configuration Register */
-#define	RIO_INTSET	RIO_REG_BASE + 0x0080	/* WRITE: Interrupt Set */
-#define	RIO_RESET	RIO_REG_BASE + 0x0100	/* WRITE: Host Reset */
-#define	RIO_INTRESET	RIO_REG_BASE + 0x0180	/* WRITE: Interrupt Reset */
-
-#define	RIO_VPD_ROM	RIO_REG_BASE + 0x0000	/* READ: Vital Product Data ROM */
-#define	RIO_INTSTAT	RIO_REG_BASE + 0x0080	/* READ: Interrupt Status (Jet boards only) */
-#define	RIO_RESETSTAT	RIO_REG_BASE + 0x0100	/* READ: Reset Status (Jet boards only) */
-
-/* RIO_VPD_ROM definitions... */
-#define	VPD_SLX_ID1	0x00	/* READ: Specialix Identifier #1 */
-#define	VPD_SLX_ID2	0x01	/* READ: Specialix Identifier #2 */
-#define	VPD_HW_REV	0x02	/* READ: Hardware Revision */
-#define	VPD_HW_ASSEM	0x03	/* READ: Hardware Assembly Level */
-#define	VPD_UNIQUEID4	0x04	/* READ: Unique Identifier #4 */
-#define	VPD_UNIQUEID3	0x05	/* READ: Unique Identifier #3 */
-#define	VPD_UNIQUEID2	0x06	/* READ: Unique Identifier #2 */
-#define	VPD_UNIQUEID1	0x07	/* READ: Unique Identifier #1 */
-#define	VPD_MANU_YEAR	0x08	/* READ: Year Of Manufacture (0 = 1970) */
-#define	VPD_MANU_WEEK	0x09	/* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define	VPD_HWFEATURE1	0x0A	/* READ: Hardware Feature Byte 1 */
-#define	VPD_HWFEATURE2	0x0B	/* READ: Hardware Feature Byte 2 */
-#define	VPD_HWFEATURE3	0x0C	/* READ: Hardware Feature Byte 3 */
-#define	VPD_HWFEATURE4	0x0D	/* READ: Hardware Feature Byte 4 */
-#define	VPD_HWFEATURE5	0x0E	/* READ: Hardware Feature Byte 5 */
-#define	VPD_OEMID	0x0F	/* READ: OEM Identifier */
-#define	VPD_IDENT	0x10	/* READ: Identifier string (16 bytes) */
-#define	VPD_IDENT_LEN	0x10
-
-/* VPD ROM Definitions... */
-#define	SLX_ID1		0x4D
-#define	SLX_ID2		0x98
-
-#define	PRODUCT_ID(a)	((a>>4)&0xF)	/* Use to obtain Product ID from VPD_UNIQUEID1 */
-
-#define	ID_SX_ISA	0x2
-#define	ID_RIO_EISA	0x3
-#define	ID_SX_PCI	0x5
-#define	ID_SX_EISA	0x7
-#define	ID_RIO_RTA16	0x9
-#define	ID_RIO_ISA	0xA
-#define	ID_RIO_MCA	0xB
-#define	ID_RIO_SBUS	0xC
-#define	ID_RIO_PCI	0xD
-#define	ID_RIO_RTA8	0xE
-
-/* Transputer bootstrap definitions... */
-
-#define	BOOTLOADADDR		(0x8000 - 6)
-#define	BOOTINDICATE		(0x8000 - 2)
-
-/* Firmware load position... */
-
-#define	FIRMWARELOADADDR	0x7C00	/* Firmware is loaded _before_ this address */
-
-/*****************************************************************************
-*****************************                    *****************************
-*****************************   RIO (Rev1) ISA   *****************************
-*****************************                    *****************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_ISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_ISA_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA_CFG_IRQMASK	0x30	/* Interrupt mask */
-#define	  RIO_ISA_CFG_IRQ12	0x10	/* Interrupt Level 12 */
-#define	  RIO_ISA_CFG_IRQ11	0x20	/* Interrupt Level 11 */
-#define	  RIO_ISA_CFG_IRQ9	0x30	/* Interrupt Level 9 */
-#define	RIO_ISA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_ISA_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
-
-/*****************************************************************************
-*****************************                    *****************************
-*****************************   RIO (Rev2) ISA   *****************************
-*****************************                    *****************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA2_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_ISA2_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_ISA2_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_ISA2_CFG_16BIT	0x08	/* 16bit mode, else 8bit */
-#define	RIO_ISA2_CFG_IRQMASK	0x30	/* Interrupt mask */
-#define	  RIO_ISA2_CFG_IRQ15	0x00	/* Interrupt Level 15 */
-#define	  RIO_ISA2_CFG_IRQ12	0x10	/* Interrupt Level 12 */
-#define	  RIO_ISA2_CFG_IRQ11	0x20	/* Interrupt Level 11 */
-#define	  RIO_ISA2_CFG_IRQ9	0x30	/* Interrupt Level 9 */
-#define	RIO_ISA2_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_ISA2_CFG_WAITSTATE0	0x80	/* 0 waitstates, else 1 */
-
-/*****************************************************************************
-*****************************                   ******************************
-*****************************   RIO (Jet) ISA   ******************************
-*****************************                   ******************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_ISA3_IDENT	"JET HOST BY KEV#"
-
-#define	RIO_ISA3_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_ISA3_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_ISA32_CFG_IRQMASK	0xF30	/* Interrupt mask */
-#define	  RIO_ISA3_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
-#define	  RIO_ISA3_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
-#define	  RIO_ISA3_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
-#define	  RIO_ISA3_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
-#define	  RIO_ISA3_CFG_IRQ9	0x90	/* Interrupt Level 9 */
-
-/*****************************************************************************
-*********************************             ********************************
-*********************************   RIO MCA   ********************************
-*********************************             ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_MCA_IDENT	"JBJGPGGHINSMJPJR"
-
-#define	RIO_MCA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_MCA_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_MCA_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   RIO EISA   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-/* EISA Configuration Space Definitions... */
-#define	EISA_PRODUCT_ID1	0xC80
-#define	EISA_PRODUCT_ID2	0xC81
-#define	EISA_PRODUCT_NUMBER	0xC82
-#define	EISA_REVISION_NUMBER	0xC83
-#define	EISA_CARD_ENABLE	0xC84
-#define	EISA_VPD_UNIQUEID4	0xC88	/* READ: Unique Identifier #4 */
-#define	EISA_VPD_UNIQUEID3	0xC8A	/* READ: Unique Identifier #3 */
-#define	EISA_VPD_UNIQUEID2	0xC90	/* READ: Unique Identifier #2 */
-#define	EISA_VPD_UNIQUEID1	0xC92	/* READ: Unique Identifier #1 */
-#define	EISA_VPD_MANU_YEAR	0xC98	/* READ: Year Of Manufacture (0 = 1970) */
-#define	EISA_VPD_MANU_WEEK	0xC9A	/* READ: Week Of Manufacture (0 = week 1 Jan) */
-#define	EISA_MEM_ADDR_23_16	0xC00
-#define	EISA_MEM_ADDR_31_24	0xC01
-#define	EISA_RIO_CONFIG		0xC02	/* WRITE: Configuration Register */
-#define	EISA_RIO_INTSET		0xC03	/* WRITE: Interrupt Set */
-#define	EISA_RIO_INTRESET	0xC03	/* READ:  Interrupt Reset */
-
-/* Control Register Definitions... */
-#define	RIO_EISA_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_EISA_CFG_LINK20	0x02	/* 20Mbps link, else 10Mbps */
-#define	RIO_EISA_CFG_BUSENABLE	0x04	/* Enable processor bus */
-#define	RIO_EISA_CFG_PROCRUN	0x08	/* Processor running, else reset */
-#define	RIO_EISA_CFG_IRQMASK	0xF0	/* Interrupt mask */
-#define	  RIO_EISA_CFG_IRQ15	0xF0	/* Interrupt Level 15 */
-#define	  RIO_EISA_CFG_IRQ14	0xE0	/* Interrupt Level 14 */
-#define	  RIO_EISA_CFG_IRQ12	0xC0	/* Interrupt Level 12 */
-#define	  RIO_EISA_CFG_IRQ11	0xB0	/* Interrupt Level 11 */
-#define	  RIO_EISA_CFG_IRQ10	0xA0	/* Interrupt Level 10 */
-#define	  RIO_EISA_CFG_IRQ9	0x90	/* Interrupt Level 9 */
-#define	  RIO_EISA_CFG_IRQ7	0x70	/* Interrupt Level 7 */
-#define	  RIO_EISA_CFG_IRQ6	0x60	/* Interrupt Level 6 */
-#define	  RIO_EISA_CFG_IRQ5	0x50	/* Interrupt Level 5 */
-#define	  RIO_EISA_CFG_IRQ4	0x40	/* Interrupt Level 4 */
-#define	  RIO_EISA_CFG_IRQ3	0x30	/* Interrupt Level 3 */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   RIO SBus   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_SBUS_IDENT	"JBPGK#\0\0\0\0\0\0\0\0\0\0"
-
-#define	RIO_SBUS_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_SBUS_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_SBUS_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_SBUS_CFG_IRQMASK	0x38	/* Interrupt mask */
-#define	  RIO_SBUS_CFG_IRQNONE	0x00	/* No Interrupt */
-#define	  RIO_SBUS_CFG_IRQ7	0x38	/* Interrupt Level 7 */
-#define	  RIO_SBUS_CFG_IRQ6	0x30	/* Interrupt Level 6 */
-#define	  RIO_SBUS_CFG_IRQ5	0x28	/* Interrupt Level 5 */
-#define	  RIO_SBUS_CFG_IRQ4	0x20	/* Interrupt Level 4 */
-#define	  RIO_SBUS_CFG_IRQ3	0x18	/* Interrupt Level 3 */
-#define	  RIO_SBUS_CFG_IRQ2	0x10	/* Interrupt Level 2 */
-#define	  RIO_SBUS_CFG_IRQ1	0x08	/* Interrupt Level 1 */
-#define	RIO_SBUS_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_SBUS_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
-
-/*****************************************************************************
-*********************************             ********************************
-*********************************   RIO PCI   ********************************
-*********************************             ********************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_PCI_IDENT	"ECDDPGJGJHJRGSK#"
-
-#define	RIO_PCI_CFG_BOOTRAM	0x01	/* Boot from RAM, else Link */
-#define	RIO_PCI_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_PCI_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-#define	RIO_PCI_CFG_LINK20	0x40	/* 20Mbps link, else 10Mbps */
-#define	RIO_PCI_CFG_PROC25	0x80	/* 25Mhz processor clock, else 20Mhz */
-
-/* PCI Definitions... */
-#define	SPX_VENDOR_ID		0x11CB	/* Assigned by the PCI SIG */
-#define	SPX_DEVICE_ID		0x8000	/* RIO bridge boards */
-#define	SPX_PLXDEVICE_ID	0x2000	/* PLX bridge boards */
-#define	SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
-#define	RIO_SUB_SYS_ID		0x0800	/* RIO PCI board */
-
-/*****************************************************************************
-*****************************                   ******************************
-*****************************   RIO (Jet) PCI   ******************************
-*****************************                   ******************************
-*****************************************************************************/
-
-/* Control Register Definitions... */
-#define	RIO_PCI2_IDENT	"JET HOST BY KEV#"
-
-#define	RIO_PCI2_CFG_BUSENABLE	0x02	/* Enable processor bus */
-#define	RIO_PCI2_CFG_INTENABLE	0x04	/* Interrupt enable, else disable */
-
-/* PCI Definitions... */
-#define	RIO2_SUB_SYS_ID		0x0100	/* RIO (Jet) PCI board */
-
-#endif						/*_rioboard_h */
-
-/* End of RIOBOARD.H */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioboot.c linux-libre-2.6.39-gnu/drivers/char/rio/rioboot.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioboot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioboot.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1113 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioboot.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:36
-**	Retrieved	: 11/6/98 10:33:48
-**
-**  ident @(#)rioboot.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/termios.h>
-#include <linux/serial.h>
-#include <linux/vmalloc.h>
-#include <linux/generic_serial.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP);
-
-static const unsigned char RIOAtVec2Ctrl[] = {
-	/* 0 */ INTERRUPT_DISABLE,
-	/* 1 */ INTERRUPT_DISABLE,
-	/* 2 */ INTERRUPT_DISABLE,
-	/* 3 */ INTERRUPT_DISABLE,
-	/* 4 */ INTERRUPT_DISABLE,
-	/* 5 */ INTERRUPT_DISABLE,
-	/* 6 */ INTERRUPT_DISABLE,
-	/* 7 */ INTERRUPT_DISABLE,
-	/* 8 */ INTERRUPT_DISABLE,
-	/* 9 */ IRQ_9 | INTERRUPT_ENABLE,
-	/* 10 */ INTERRUPT_DISABLE,
-	/* 11 */ IRQ_11 | INTERRUPT_ENABLE,
-	/* 12 */ IRQ_12 | INTERRUPT_ENABLE,
-	/* 13 */ INTERRUPT_DISABLE,
-	/* 14 */ INTERRUPT_DISABLE,
-	/* 15 */ IRQ_15 | INTERRUPT_ENABLE
-};
-
-/**
- *	RIOBootCodeRTA		-	Load RTA boot code
- *	@p: RIO to load
- *	@rbp: Download descriptor
- *
- *	Called when the user process initiates booting of the card firmware.
- *	Lads the firmware
- */
-
-int RIOBootCodeRTA(struct rio_info *p, struct DownLoad * rbp)
-{
-	int offset;
-
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Data at user address %p\n", rbp->DataP);
-
-	/*
-	 ** Check that we have set asside enough memory for this
-	 */
-	if (rbp->Count > SIXTY_FOUR_K) {
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code Too Large!\n");
-		p->RIOError.Error = HOST_FILE_TOO_LARGE;
-		func_exit();
-		return -ENOMEM;
-	}
-
-	if (p->RIOBooting) {
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot Code : BUSY BUSY BUSY!\n");
-		p->RIOError.Error = BOOT_IN_PROGRESS;
-		func_exit();
-		return -EBUSY;
-	}
-
-	/*
-	 ** The data we load in must end on a (RTA_BOOT_DATA_SIZE) byte boundary,
-	 ** so calculate how far we have to move the data up the buffer
-	 ** to achieve this.
-	 */
-	offset = (RTA_BOOT_DATA_SIZE - (rbp->Count % RTA_BOOT_DATA_SIZE)) % RTA_BOOT_DATA_SIZE;
-
-	/*
-	 ** Be clean, and clear the 'unused' portion of the boot buffer,
-	 ** because it will (eventually) be part of the Rta run time environment
-	 ** and so should be zeroed.
-	 */
-	memset(p->RIOBootPackets, 0, offset);
-
-	/*
-	 ** Copy the data from user space into the array
-	 */
-
-	if (copy_from_user(((u8 *)p->RIOBootPackets) + offset, rbp->DataP, rbp->Count)) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Bad data copy from user space\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		func_exit();
-		return -EFAULT;
-	}
-
-	/*
-	 ** Make sure that our copy of the size includes that offset we discussed
-	 ** earlier.
-	 */
-	p->RIONumBootPkts = (rbp->Count + offset) / RTA_BOOT_DATA_SIZE;
-	p->RIOBootCount = rbp->Count;
-
-	func_exit();
-	return 0;
-}
-
-/**
- *	rio_start_card_running		-	host card start
- *	@HostP: The RIO to kick off
- *
- *	Start a RIO processor unit running. Encapsulates the knowledge
- *	of the card type.
- */
-
-void rio_start_card_running(struct Host *HostP)
-{
-	switch (HostP->Type) {
-	case RIO_AT:
-		rio_dprintk(RIO_DEBUG_BOOT, "Start ISA card running\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_ON | HostP->Mode | RIOAtVec2Ctrl[HostP->Ivec & 0xF], &HostP->Control);
-		break;
-	case RIO_PCI:
-		/*
-		 ** PCI is much the same as MCA. Everything is once again memory
-		 ** mapped, so we are writing to memory registers instead of io
-		 ** ports.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Start PCI card running\n");
-		writeb(PCITpBootFromRam | PCITpBusEnable | HostP->Mode, &HostP->Control);
-		break;
-	default:
-		rio_dprintk(RIO_DEBUG_BOOT, "Unknown host type %d\n", HostP->Type);
-		break;
-	}
-	return;
-}
-
-/*
-** Load in the host boot code - load it directly onto all halted hosts
-** of the correct type.
-**
-** Put your rubber pants on before messing with this code - even the magic
-** numbers have trouble understanding what they are doing here.
-*/
-
-int RIOBootCodeHOST(struct rio_info *p, struct DownLoad *rbp)
-{
-	struct Host *HostP;
-	u8 __iomem *Cad;
-	PARM_MAP __iomem *ParmMapP;
-	int RupN;
-	int PortN;
-	unsigned int host;
-	u8 __iomem *StartP;
-	u8 __iomem *DestP;
-	int wait_count;
-	u16 OldParmMap;
-	u16 offset;		/* It is very important that this is a u16 */
-	u8 *DownCode = NULL;
-	unsigned long flags;
-
-	HostP = NULL;		/* Assure the compiler we've initialized it */
-
-
-	/* Walk the hosts */
-	for (host = 0; host < p->RIONumHosts; host++) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Attempt to boot host %d\n", host);
-		HostP = &p->RIOHosts[host];
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
-
-		/* Don't boot hosts already running */
-		if ((HostP->Flags & RUN_STATE) != RC_WAITING) {
-			rio_dprintk(RIO_DEBUG_BOOT, "%s %d already running\n", "Host", host);
-			continue;
-		}
-
-		/*
-		 ** Grab a pointer to the card (ioremapped)
-		 */
-		Cad = HostP->Caddr;
-
-		/*
-		 ** We are going to (try) and load in rbp->Count bytes.
-		 ** The last byte will reside at p->RIOConf.HostLoadBase-1;
-		 ** Therefore, we need to start copying at address
-		 ** (caddr+p->RIOConf.HostLoadBase-rbp->Count)
-		 */
-		StartP = &Cad[p->RIOConf.HostLoadBase - rbp->Count];
-
-		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for host is %p\n", Cad);
-		rio_dprintk(RIO_DEBUG_BOOT, "kernel virtual address for download is %p\n", StartP);
-		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
-		rio_dprintk(RIO_DEBUG_BOOT, "size of download is 0x%x\n", rbp->Count);
-
-		/* Make sure it fits */
-		if (p->RIOConf.HostLoadBase < rbp->Count) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Bin too large\n");
-			p->RIOError.Error = HOST_FILE_TOO_LARGE;
-			func_exit();
-			return -EFBIG;
-		}
-		/*
-		 ** Ensure that the host really is stopped.
-		 ** Disable it's external bus & twang its reset line.
-		 */
-		RIOHostReset(HostP->Type, HostP->CardP, HostP->Slot);
-
-		/*
-		 ** Copy the data directly from user space to the SRAM.
-		 ** This ain't going to be none too clever if the download
-		 ** code is bigger than this segment.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Copy in code\n");
-
-		/* Buffer to local memory as we want to use I/O space and
-		   some cards only do 8 or 16 bit I/O */
-
-		DownCode = vmalloc(rbp->Count);
-		if (!DownCode) {
-			p->RIOError.Error = NOT_ENOUGH_CORE_FOR_PCI_COPY;
-			func_exit();
-			return -ENOMEM;
-		}
-		if (copy_from_user(DownCode, rbp->DataP, rbp->Count)) {
-			kfree(DownCode);
-			p->RIOError.Error = COPYIN_FAILED;
-			func_exit();
-			return -EFAULT;
-		}
-		HostP->Copy(DownCode, StartP, rbp->Count);
-		vfree(DownCode);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Copy completed\n");
-
-		/*
-		 **                     S T O P !
-		 **
-		 ** Upto this point the code has been fairly rational, and possibly
-		 ** even straight forward. What follows is a pile of crud that will
-		 ** magically turn into six bytes of transputer assembler. Normally
-		 ** you would expect an array or something, but, being me, I have
-		 ** chosen [been told] to use a technique whereby the startup code
-		 ** will be correct if we change the loadbase for the code. Which
-		 ** brings us onto another issue - the loadbase is the *end* of the
-		 ** code, not the start.
-		 **
-		 ** If I were you I wouldn't start from here.
-		 */
-
-		/*
-		 ** We now need to insert a short boot section into
-		 ** the memory at the end of Sram2. This is normally (de)composed
-		 ** of the last eight bytes of the download code. The
-		 ** download has been assembled/compiled to expect to be
-		 ** loaded from 0x7FFF downwards. We have loaded it
-		 ** at some other address. The startup code goes into the small
-		 ** ram window at Sram2, in the last 8 bytes, which are really
-		 ** at addresses 0x7FF8-0x7FFF.
-		 **
-		 ** If the loadbase is, say, 0x7C00, then we need to branch to
-		 ** address 0x7BFE to run the host.bin startup code. We assemble
-		 ** this jump manually.
-		 **
-		 ** The two byte sequence 60 08 is loaded into memory at address
-		 ** 0x7FFE,F. This is a local branch to location 0x7FF8 (60 is nfix 0,
-		 ** which adds '0' to the .O register, complements .O, and then shifts
-		 ** it left by 4 bit positions, 08 is a jump .O+8 instruction. This will
-		 ** add 8 to .O (which was 0xFFF0), and will branch RELATIVE to the new
-		 ** location. Now, the branch starts from the value of .PC (or .IP or
-		 ** whatever the bloody register is called on this chip), and the .PC
-		 ** will be pointing to the location AFTER the branch, in this case
-		 ** .PC == 0x8000, so the branch will be to 0x8000+0xFFF8 = 0x7FF8.
-		 **
-		 ** A long branch is coded at 0x7FF8. This consists of loading a four
-		 ** byte offset into .O using nfix (as above) and pfix operators. The
-		 ** pfix operates in exactly the same way as the nfix operator, but
-		 ** without the complement operation. The offset, of course, must be
-		 ** relative to the address of the byte AFTER the branch instruction,
-		 ** which will be (urm) 0x7FFC, so, our final destination of the branch
-		 ** (loadbase-2), has to be reached from here. Imagine that the loadbase
-		 ** is 0x7C00 (which it is), then we will need to branch to 0x7BFE (which
-		 ** is the first byte of the initial two byte short local branch of the
-		 ** download code).
-		 **
-		 ** To code a jump from 0x7FFC (which is where the branch will start
-		 ** from) to 0x7BFE, we will need to branch 0xFC02 bytes (0x7FFC+0xFC02)=
-		 ** 0x7BFE.
-		 ** This will be coded as four bytes:
-		 ** 60 2C 20 02
-		 ** being nfix .O+0
-		 **        pfix .O+C
-		 **        pfix .O+0
-		 **        jump .O+2
-		 **
-		 ** The nfix operator is used, so that the startup code will be
-		 ** compatible with the whole Tp family. (lies, damn lies, it'll never
-		 ** work in a month of Sundays).
-		 **
-		 ** The nfix nyble is the 1s complement of the nyble value you
-		 ** want to load - in this case we wanted 'F' so we nfix loaded '0'.
-		 */
-
-
-		/*
-		 ** Dest points to the top 8 bytes of Sram2. The Tp jumps
-		 ** to 0x7FFE at reset time, and starts executing. This is
-		 ** a short branch to 0x7FF8, where a long branch is coded.
-		 */
-
-		DestP = &Cad[0x7FF8];	/* <<<---- READ THE ABOVE COMMENTS */
-
-#define	NFIX(N)	(0x60 | (N))	/* .O  = (~(.O + N))<<4 */
-#define	PFIX(N)	(0x20 | (N))	/* .O  =   (.O + N)<<4  */
-#define	JUMP(N)	(0x00 | (N))	/* .PC =   .PC + .O      */
-
-		/*
-		 ** 0x7FFC is the address of the location following the last byte of
-		 ** the four byte jump instruction.
-		 ** READ THE ABOVE COMMENTS
-		 **
-		 ** offset is (TO-FROM) % MEMSIZE, but with compound buggering about.
-		 ** Memsize is 64K for this range of Tp, so offset is a short (unsigned,
-		 ** cos I don't understand 2's complement).
-		 */
-		offset = (p->RIOConf.HostLoadBase - 2) - 0x7FFC;
-
-		writeb(NFIX(((unsigned short) (~offset) >> (unsigned short) 12) & 0xF), DestP);
-		writeb(PFIX((offset >> 8) & 0xF), DestP + 1);
-		writeb(PFIX((offset >> 4) & 0xF), DestP + 2);
-		writeb(JUMP(offset & 0xF), DestP + 3);
-
-		writeb(NFIX(0), DestP + 6);
-		writeb(JUMP(8), DestP + 7);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "host loadbase is 0x%x\n", p->RIOConf.HostLoadBase);
-		rio_dprintk(RIO_DEBUG_BOOT, "startup offset is 0x%x\n", offset);
-
-		/*
-		 ** Flag what is going on
-		 */
-		HostP->Flags &= ~RUN_STATE;
-		HostP->Flags |= RC_STARTUP;
-
-		/*
-		 ** Grab a copy of the current ParmMap pointer, so we
-		 ** can tell when it has changed.
-		 */
-		OldParmMap = readw(&HostP->__ParmMapR);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Original parmmap is 0x%x\n", OldParmMap);
-
-		/*
-		 ** And start it running (I hope).
-		 ** As there is nothing dodgy or obscure about the
-		 ** above code, this is guaranteed to work every time.
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Host Type = 0x%x, Mode = 0x%x, IVec = 0x%x\n", HostP->Type, HostP->Mode, HostP->Ivec);
-
-		rio_start_card_running(HostP);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Set control port\n");
-
-		/*
-		 ** Now, wait for upto five seconds for the Tp to setup the parmmap
-		 ** pointer:
-		 */
-		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && (readw(&HostP->__ParmMapR) == OldParmMap); wait_count++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Checkout %d, 0x%x\n", wait_count, readw(&HostP->__ParmMapR));
-			mdelay(100);
-
-		}
-
-		/*
-		 ** If the parmmap pointer is unchanged, then the host code
-		 ** has crashed & burned in a really spectacular way
-		 */
-		if (readw(&HostP->__ParmMapR) == OldParmMap) {
-			rio_dprintk(RIO_DEBUG_BOOT, "parmmap 0x%x\n", readw(&HostP->__ParmMapR));
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail\n");
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Running 0x%x\n", readw(&HostP->__ParmMapR));
-
-		/*
-		 ** Well, the board thought it was OK, and setup its parmmap
-		 ** pointer. For the time being, we will pretend that this
-		 ** board is running, and check out what the error flag says.
-		 */
-
-		/*
-		 ** Grab a 32 bit pointer to the parmmap structure
-		 */
-		ParmMapP = (PARM_MAP __iomem *) RIO_PTR(Cad, readw(&HostP->__ParmMapR));
-		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-		ParmMapP = (PARM_MAP __iomem *)(Cad + readw(&HostP->__ParmMapR));
-		rio_dprintk(RIO_DEBUG_BOOT, "ParmMapP : %p\n", ParmMapP);
-
-		/*
-		 ** The links entry should be 0xFFFF; we set it up
-		 ** with a mask to say how many PHBs to use, and
-		 ** which links to use.
-		 */
-		if (readw(&ParmMapP->links) != 0xFFFF) {
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
-			rio_dprintk(RIO_DEBUG_BOOT, "Links = 0x%x\n", readw(&ParmMapP->links));
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		writew(RIO_LINK_ENABLE, &ParmMapP->links);
-
-		/*
-		 ** now wait for the card to set all the parmmap->XXX stuff
-		 ** this is a wait of upto two seconds....
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Looking for init_done - %d ticks\n", p->RIOConf.StartupTime);
-		HostP->timeout_id = 0;
-		for (wait_count = 0; (wait_count < p->RIOConf.StartupTime) && !readw(&ParmMapP->init_done); wait_count++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Waiting for init_done\n");
-			mdelay(100);
-		}
-		rio_dprintk(RIO_DEBUG_BOOT, "OK! init_done!\n");
-
-		if (readw(&ParmMapP->error) != E_NO_ERROR || !readw(&ParmMapP->init_done)) {
-			rio_dprintk(RIO_DEBUG_BOOT, "RIO Mesg Run Fail %s\n", HostP->Name);
-			rio_dprintk(RIO_DEBUG_BOOT, "Timedout waiting for init_done\n");
-			HostP->Flags &= ~RUN_STATE;
-			HostP->Flags |= RC_STUFFED;
-			RIOHostReset( HostP->Type, HostP->CardP, HostP->Slot );
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Got init_done\n");
-
-		/*
-		 ** It runs! It runs!
-		 */
-		rio_dprintk(RIO_DEBUG_BOOT, "Host ID %x Running\n", HostP->UniqueNum);
-
-		/*
-		 ** set the time period between interrupts.
-		 */
-		writew(p->RIOConf.Timer, &ParmMapP->timer);
-
-		/*
-		 ** Translate all the 16 bit pointers in the __ParmMapR into
-		 ** 32 bit pointers for the driver in ioremap space.
-		 */
-		HostP->ParmMapP = ParmMapP;
-		HostP->PhbP = (struct PHB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_ptr));
-		HostP->RupP = (struct RUP __iomem *) RIO_PTR(Cad, readw(&ParmMapP->rups));
-		HostP->PhbNumP = (unsigned short __iomem *) RIO_PTR(Cad, readw(&ParmMapP->phb_num_ptr));
-		HostP->LinkStrP = (struct LPB __iomem *) RIO_PTR(Cad, readw(&ParmMapP->link_str_ptr));
-
-		/*
-		 ** point the UnixRups at the real Rups
-		 */
-		for (RupN = 0; RupN < MAX_RUP; RupN++) {
-			HostP->UnixRups[RupN].RupP = &HostP->RupP[RupN];
-			HostP->UnixRups[RupN].Id = RupN + 1;
-			HostP->UnixRups[RupN].BaseSysPort = NO_PORT;
-			spin_lock_init(&HostP->UnixRups[RupN].RupLock);
-		}
-
-		for (RupN = 0; RupN < LINKS_PER_UNIT; RupN++) {
-			HostP->UnixRups[RupN + MAX_RUP].RupP = &HostP->LinkStrP[RupN].rup;
-			HostP->UnixRups[RupN + MAX_RUP].Id = 0;
-			HostP->UnixRups[RupN + MAX_RUP].BaseSysPort = NO_PORT;
-			spin_lock_init(&HostP->UnixRups[RupN + MAX_RUP].RupLock);
-		}
-
-		/*
-		 ** point the PortP->Phbs at the real Phbs
-		 */
-		for (PortN = p->RIOFirstPortsMapped; PortN < p->RIOLastPortsMapped + PORTS_PER_RTA; PortN++) {
-			if (p->RIOPortp[PortN]->HostP == HostP) {
-				struct Port *PortP = p->RIOPortp[PortN];
-				struct PHB __iomem *PhbP;
-				/* int oldspl; */
-
-				if (!PortP->Mapped)
-					continue;
-
-				PhbP = &HostP->PhbP[PortP->HostPort];
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-				PortP->PhbP = PhbP;
-
-				PortP->TxAdd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_add));
-				PortP->TxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_start));
-				PortP->TxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->tx_end));
-				PortP->RxRemove = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_remove));
-				PortP->RxStart = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_start));
-				PortP->RxEnd = (u16 __iomem *) RIO_PTR(Cad, readw(&PhbP->rx_end));
-
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				/*
-				 ** point the UnixRup at the base SysPort
-				 */
-				if (!(PortN % PORTS_PER_RTA))
-					HostP->UnixRups[PortP->RupNum].BaseSysPort = PortN;
-			}
-		}
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Set the card running... \n");
-		/*
-		 ** last thing - show the world that everything is in place
-		 */
-		HostP->Flags &= ~RUN_STATE;
-		HostP->Flags |= RC_RUNNING;
-	}
-	/*
-	 ** MPX always uses a poller. This is actually patched into the system
-	 ** configuration and called directly from each clock tick.
-	 **
-	 */
-	p->RIOPolling = 1;
-
-	p->RIOSystemUp++;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Done everything %x\n", HostP->Ivec);
-	func_exit();
-	return 0;
-}
-
-
-
-/**
- *	RIOBootRup		-	Boot an RTA
- *	@p: rio we are working with
- *	@Rup: Rup number
- *	@HostP: host object
- *	@PacketP: packet to use
- *
- *	If we have successfully processed this boot, then
- *	return 1. If we havent, then return 0.
- */
-
-int RIOBootRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem *PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
-	struct PktCmd_M *PktReplyP;
-	struct CmdBlk *CmdBlkP;
-	unsigned int sequence;
-
-	/*
-	 ** If we haven't been told what to boot, we can't boot it.
-	 */
-	if (p->RIONumBootPkts == 0) {
-		rio_dprintk(RIO_DEBUG_BOOT, "No RTA code to download yet\n");
-		return 0;
-	}
-
-	/*
-	 ** Special case of boot completed - if we get one of these then we
-	 ** don't need a command block. For all other cases we do, so handle
-	 ** this first and then get a command block, then handle every other
-	 ** case, relinquishing the command block if disaster strikes!
-	 */
-	if ((readb(&PacketP->len) & PKT_CMD_BIT) && (readb(&PktCmdP->Command) == BOOT_COMPLETED))
-		return RIOBootComplete(p, HostP, Rup, PktCmdP);
-
-	/*
-	 ** Try to allocate a command block. This is in kernel space
-	 */
-	if (!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_BOOT, "No command blocks to boot RTA! come back later.\n");
-		return 0;
-	}
-
-	/*
-	 ** Fill in the default info on the command block
-	 */
-	CmdBlkP->Packet.dest_unit = Rup < (unsigned short) MAX_RUP ? Rup : 0;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-
-	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
-	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
-
-	/*
-	 ** process COMMANDS on the boot rup!
-	 */
-	if (readb(&PacketP->len) & PKT_CMD_BIT) {
-		/*
-		 ** We only expect one type of command - a BOOT_REQUEST!
-		 */
-		if (readb(&PktCmdP->Command) != BOOT_REQUEST) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Unexpected command %d on BOOT RUP %d of host %Zd\n", readb(&PktCmdP->Command), Rup, HostP - p->RIOHosts);
-			RIOFreeCmdBlk(CmdBlkP);
-			return 1;
-		}
-
-		/*
-		 ** Build a Boot Sequence command block
-		 **
-		 ** We no longer need to use "Boot Mode", we'll always allow
-		 ** boot requests - the boot will not complete if the device
-		 ** appears in the bindings table.
-		 **
-		 ** We'll just (always) set the command field in packet reply
-		 ** to allow an attempted boot sequence :
-		 */
-		PktReplyP->Command = BOOT_SEQUENCE;
-
-		PktReplyP->BootSequence.NumPackets = p->RIONumBootPkts;
-		PktReplyP->BootSequence.LoadBase = p->RIOConf.RtaLoadBase;
-		PktReplyP->BootSequence.CodeSize = p->RIOBootCount;
-
-		CmdBlkP->Packet.len = BOOT_SEQUENCE_LEN | PKT_CMD_BIT;
-
-		memcpy((void *) &CmdBlkP->Packet.data[BOOT_SEQUENCE_LEN], "BOOT", 4);
-
-		rio_dprintk(RIO_DEBUG_BOOT, "Boot RTA on Host %Zd Rup %d - %d (0x%x) packets to 0x%x\n", HostP - p->RIOHosts, Rup, p->RIONumBootPkts, p->RIONumBootPkts, p->RIOConf.RtaLoadBase);
-
-		/*
-		 ** If this host is in slave mode, send the RTA an invalid boot
-		 ** sequence command block to force it to kill the boot. We wait
-		 ** for half a second before sending this packet to prevent the RTA
-		 ** attempting to boot too often. The master host should then grab
-		 ** the RTA and make it its own.
-		 */
-		p->RIOBooting++;
-		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-		return 1;
-	}
-
-	/*
-	 ** It is a request for boot data.
-	 */
-	sequence = readw(&PktCmdP->Sequence);
-
-	rio_dprintk(RIO_DEBUG_BOOT, "Boot block %d on Host %Zd Rup%d\n", sequence, HostP - p->RIOHosts, Rup);
-
-	if (sequence >= p->RIONumBootPkts) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Got a request for packet %d, max is %d\n", sequence, p->RIONumBootPkts);
-	}
-
-	PktReplyP->Sequence = sequence;
-	memcpy(PktReplyP->BootData, p->RIOBootPackets[p->RIONumBootPkts - sequence - 1], RTA_BOOT_DATA_SIZE);
-	CmdBlkP->Packet.len = PKT_MAX_DATA_LEN;
-	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-	return 1;
-}
-
-/**
- *	RIOBootComplete		-	RTA boot is done
- *	@p: RIO we are working with
- *	@HostP: Host structure
- *	@Rup: RUP being used
- *	@PktCmdP: Packet command that was used
- *
- *	This function is called when an RTA been booted.
- *	If booted by a host, HostP->HostUniqueNum is the booting host.
- *	If booted by an RTA, HostP->Mapping[Rup].RtaUniqueNum is the booting RTA.
- *	RtaUniq is the booted RTA.
- */
-
-static int RIOBootComplete(struct rio_info *p, struct Host *HostP, unsigned int Rup, struct PktCmd __iomem *PktCmdP)
-{
-	struct Map *MapP = NULL;
-	struct Map *MapP2 = NULL;
-	int Flag;
-	int found;
-	int host, rta;
-	int EmptySlot = -1;
-	int entry, entry2;
-	char *MyType, *MyName;
-	unsigned int MyLink;
-	unsigned short RtaType;
-	u32 RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
-
-	p->RIOBooting = 0;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "RTA Boot completed - BootInProgress now %d\n", p->RIOBooting);
-
-	/*
-	 ** Determine type of unit (16/8 port RTA).
-	 */
-
-	RtaType = GetUnitType(RtaUniq);
-	if (Rup >= (unsigned short) MAX_RUP)
-		rio_dprintk(RIO_DEBUG_BOOT, "RIO: Host %s has booted an RTA(%d) on link %c\n", HostP->Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
-	else
-		rio_dprintk(RIO_DEBUG_BOOT, "RIO: RTA %s has booted an RTA(%d) on link %c\n", HostP->Mapping[Rup].Name, 8 * RtaType, readb(&PktCmdP->LinkNum) + 'A');
-
-	rio_dprintk(RIO_DEBUG_BOOT, "UniqNum is 0x%x\n", RtaUniq);
-
-	if (RtaUniq == 0x00000000 || RtaUniq == 0xffffffff) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Illegal RTA Uniq Number\n");
-		return 1;
-	}
-
-	/*
-	 ** If this RTA has just booted an RTA which doesn't belong to this
-	 ** system, or the system is in slave mode, do not attempt to create
-	 ** a new table entry for it.
-	 */
-
-	if (!RIOBootOk(p, HostP, RtaUniq)) {
-		MyLink = readb(&PktCmdP->LinkNum);
-		if (Rup < (unsigned short) MAX_RUP) {
-			/*
-			 ** RtaUniq was clone booted (by this RTA). Instruct this RTA
-			 ** to hold off further attempts to boot on this link for 30
-			 ** seconds.
-			 */
-			if (RIOSuspendBootRta(HostP, HostP->Mapping[Rup].ID, MyLink)) {
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA failed to suspend booting on link %c\n", 'A' + MyLink);
-			}
-		} else
-			/*
-			 ** RtaUniq was booted by this host. Set the booting link
-			 ** to hold off for 30 seconds to give another unit a
-			 ** chance to boot it.
-			 */
-			writew(30, &HostP->LinkStrP[MyLink].WaitNoBoot);
-		rio_dprintk(RIO_DEBUG_BOOT, "RTA %x not owned - suspend booting down link %c on unit %x\n", RtaUniq, 'A' + MyLink, HostP->Mapping[Rup].RtaUniqueNum);
-		return 1;
-	}
-
-	/*
-	 ** Check for a SLOT_IN_USE entry for this RTA attached to the
-	 ** current host card in the driver table.
-	 **
-	 ** If it exists, make a note that we have booted it. Other parts of
-	 ** the driver are interested in this information at a later date,
-	 ** in particular when the booting RTA asks for an ID for this unit,
-	 ** we must have set the BOOTED flag, and the NEWBOOT flag is used
-	 ** to force an open on any ports that where previously open on this
-	 ** unit.
-	 */
-	for (entry = 0; entry < MAX_RUP; entry++) {
-		unsigned int sysport;
-
-		if ((HostP->Mapping[entry].Flags & SLOT_IN_USE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
-			HostP->Mapping[entry].Flags |= RTA_BOOTED | RTA_NEWBOOT;
-			if ((sysport = HostP->Mapping[entry].SysPort) != NO_PORT) {
-				if (sysport < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = sysport;
-				if (sysport > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = sysport;
-				/*
-				 ** For a 16 port RTA, check the second bank of 8 ports
-				 */
-				if (RtaType == TYPE_RTA16) {
-					entry2 = HostP->Mapping[entry].ID2 - 1;
-					HostP->Mapping[entry2].Flags |= RTA_BOOTED | RTA_NEWBOOT;
-					sysport = HostP->Mapping[entry2].SysPort;
-					if (sysport < p->RIOFirstPortsBooted)
-						p->RIOFirstPortsBooted = sysport;
-					if (sysport > p->RIOLastPortsBooted)
-						p->RIOLastPortsBooted = sysport;
-				}
-			}
-			if (RtaType == TYPE_RTA16)
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given IDs %d+%d\n", entry + 1, entry2 + 1);
-			else
-				rio_dprintk(RIO_DEBUG_BOOT, "RTA will be given ID %d\n", entry + 1);
-			return 1;
-		}
-	}
-
-	rio_dprintk(RIO_DEBUG_BOOT, "RTA not configured for this host\n");
-
-	if (Rup >= (unsigned short) MAX_RUP) {
-		/*
-		 ** It was a host that did the booting
-		 */
-		MyType = "Host";
-		MyName = HostP->Name;
-	} else {
-		/*
-		 ** It was an RTA that did the booting
-		 */
-		MyType = "RTA";
-		MyName = HostP->Mapping[Rup].Name;
-	}
-	MyLink = readb(&PktCmdP->LinkNum);
-
-	/*
-	 ** There is no SLOT_IN_USE entry for this RTA attached to the current
-	 ** host card in the driver table.
-	 **
-	 ** Check for a SLOT_TENTATIVE entry for this RTA attached to the
-	 ** current host card in the driver table.
-	 **
-	 ** If we find one, then we re-use that slot.
-	 */
-	for (entry = 0; entry < MAX_RUP; entry++) {
-		if ((HostP->Mapping[entry].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry].RtaUniqueNum == RtaUniq)) {
-			if (RtaType == TYPE_RTA16) {
-				entry2 = HostP->Mapping[entry].ID2 - 1;
-				if ((HostP->Mapping[entry2].Flags & SLOT_TENTATIVE) && (HostP->Mapping[entry2].RtaUniqueNum == RtaUniq))
-					rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slots (%d+%d)\n", entry, entry2);
-				else
-					continue;
-			} else
-				rio_dprintk(RIO_DEBUG_BOOT, "Found previous tentative slot (%d)\n", entry);
-			if (!p->RIONoMessage)
-				printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
-			return 1;
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** Check if there is a SLOT_IN_USE or SLOT_TENTATIVE entry on another
-	 ** host for this RTA in the driver table.
-	 **
-	 ** For a SLOT_IN_USE entry on another host, we need to delete the RTA
-	 ** entry from the other host and add it to this host (using some of
-	 ** the functions from table.c which do this).
-	 ** For a SLOT_TENTATIVE entry on another host, we must cope with the
-	 ** following scenario:
-	 **
-	 ** + Plug 8 port RTA into host A. (This creates SLOT_TENTATIVE entry
-	 **   in table)
-	 ** + Unplug RTA and plug into host B. (We now have 2 SLOT_TENTATIVE
-	 **   entries)
-	 ** + Configure RTA on host B. (This slot now becomes SLOT_IN_USE)
-	 ** + Unplug RTA and plug back into host A.
-	 ** + Configure RTA on host A. We now have the same RTA configured
-	 **   with different ports on two different hosts.
-	 */
-	rio_dprintk(RIO_DEBUG_BOOT, "Have we seen RTA %x before?\n", RtaUniq);
-	found = 0;
-	Flag = 0;		/* Convince the compiler this variable is initialized */
-	for (host = 0; !found && (host < p->RIONumHosts); host++) {
-		for (rta = 0; rta < MAX_RUP; rta++) {
-			if ((p->RIOHosts[host].Mapping[rta].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (p->RIOHosts[host].Mapping[rta].RtaUniqueNum == RtaUniq)) {
-				Flag = p->RIOHosts[host].Mapping[rta].Flags;
-				MapP = &p->RIOHosts[host].Mapping[rta];
-				if (RtaType == TYPE_RTA16) {
-					MapP2 = &p->RIOHosts[host].Mapping[MapP->ID2 - 1];
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is units %d+%d from host %s\n", rta + 1, MapP->ID2, p->RIOHosts[host].Name);
-				} else
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is unit %d from host %s\n", rta + 1, p->RIOHosts[host].Name);
-				found = 1;
-				break;
-			}
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** If we have not found a SLOT_IN_USE or SLOT_TENTATIVE entry on
-	 ** another host for this RTA in the driver table...
-	 **
-	 ** Check for a SLOT_IN_USE entry for this RTA in the config table.
-	 */
-	if (!MapP) {
-		rio_dprintk(RIO_DEBUG_BOOT, "Look for RTA %x in RIOSavedTable\n", RtaUniq);
-		for (rta = 0; rta < TOTAL_MAP_ENTRIES; rta++) {
-			rio_dprintk(RIO_DEBUG_BOOT, "Check table entry %d (%x)", rta, p->RIOSavedTable[rta].RtaUniqueNum);
-
-			if ((p->RIOSavedTable[rta].Flags & SLOT_IN_USE) && (p->RIOSavedTable[rta].RtaUniqueNum == RtaUniq)) {
-				MapP = &p->RIOSavedTable[rta];
-				Flag = p->RIOSavedTable[rta].Flags;
-				if (RtaType == TYPE_RTA16) {
-					for (entry2 = rta + 1; entry2 < TOTAL_MAP_ENTRIES; entry2++) {
-						if (p->RIOSavedTable[entry2].RtaUniqueNum == RtaUniq)
-							break;
-					}
-					MapP2 = &p->RIOSavedTable[entry2];
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entries %d+%d\n", rta, entry2);
-				} else
-					rio_dprintk(RIO_DEBUG_BOOT, "This RTA is from table entry %d\n", rta);
-				break;
-			}
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** We may have found a SLOT_IN_USE entry on another host for this
-	 ** RTA in the config table, or a SLOT_IN_USE or SLOT_TENTATIVE entry
-	 ** on another host for this RTA in the driver table.
-	 **
-	 ** Check the driver table for room to fit this newly discovered RTA.
-	 ** RIOFindFreeID() first looks for free slots and if it does not
-	 ** find any free slots it will then attempt to oust any
-	 ** tentative entry in the table.
-	 */
-	EmptySlot = 1;
-	if (RtaType == TYPE_RTA16) {
-		if (RIOFindFreeID(p, HostP, &entry, &entry2) == 0) {
-			RIODefaultName(p, HostP, entry);
-			rio_fill_host_slot(entry, entry2, RtaUniq, HostP);
-			EmptySlot = 0;
-		}
-	} else {
-		if (RIOFindFreeID(p, HostP, &entry, NULL) == 0) {
-			RIODefaultName(p, HostP, entry);
-			rio_fill_host_slot(entry, 0, RtaUniq, HostP);
-			EmptySlot = 0;
-		}
-	}
-
-	/*
-	 ** There is no SLOT_IN_USE or SLOT_TENTATIVE entry for this RTA
-	 ** attached to the current host card in the driver table.
-	 **
-	 ** If we found a SLOT_IN_USE entry on another host for this
-	 ** RTA in the config or driver table, and there are enough free
-	 ** slots in the driver table, then we need to move it over and
-	 ** delete it from the other host.
-	 ** If we found a SLOT_TENTATIVE entry on another host for this
-	 ** RTA in the driver table, just delete the other host entry.
-	 */
-	if (EmptySlot == 0) {
-		if (MapP) {
-			if (Flag & SLOT_IN_USE) {
-				rio_dprintk(RIO_DEBUG_BOOT, "This RTA configured on another host - move entry to current host (1)\n");
-				HostP->Mapping[entry].SysPort = MapP->SysPort;
-				memcpy(HostP->Mapping[entry].Name, MapP->Name, MAX_NAME_LEN);
-				HostP->Mapping[entry].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT;
-				RIOReMapPorts(p, HostP, &HostP->Mapping[entry]);
-				if (HostP->Mapping[entry].SysPort < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = HostP->Mapping[entry].SysPort;
-				if (HostP->Mapping[entry].SysPort > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = HostP->Mapping[entry].SysPort;
-				rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) MapP->SysPort, MapP->Name);
-			} else {
-				rio_dprintk(RIO_DEBUG_BOOT, "This RTA has a tentative entry on another host - delete that entry (1)\n");
-				HostP->Mapping[entry].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT;
-			}
-			if (RtaType == TYPE_RTA16) {
-				if (Flag & SLOT_IN_USE) {
-					HostP->Mapping[entry2].Flags = SLOT_IN_USE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-					HostP->Mapping[entry2].SysPort = MapP2->SysPort;
-					/*
-					 ** Map second block of ttys for 16 port RTA
-					 */
-					RIOReMapPorts(p, HostP, &HostP->Mapping[entry2]);
-					if (HostP->Mapping[entry2].SysPort < p->RIOFirstPortsBooted)
-						p->RIOFirstPortsBooted = HostP->Mapping[entry2].SysPort;
-					if (HostP->Mapping[entry2].SysPort > p->RIOLastPortsBooted)
-						p->RIOLastPortsBooted = HostP->Mapping[entry2].SysPort;
-					rio_dprintk(RIO_DEBUG_BOOT, "SysPort %d, Name %s\n", (int) HostP->Mapping[entry2].SysPort, HostP->Mapping[entry].Name);
-				} else
-					HostP->Mapping[entry2].Flags = SLOT_TENTATIVE | RTA_BOOTED | RTA_NEWBOOT | RTA16_SECOND_SLOT;
-				memset(MapP2, 0, sizeof(struct Map));
-			}
-			memset(MapP, 0, sizeof(struct Map));
-			if (!p->RIONoMessage)
-				printk("An orphaned RTA has been adopted by %s '%s' (%c).\n", MyType, MyName, MyLink + 'A');
-		} else if (!p->RIONoMessage)
-			printk("RTA connected to %s '%s' (%c) not configured.\n", MyType, MyName, MyLink + 'A');
-		RIOSetChange(p);
-		return 1;
-	}
-
-	/*
-	 ** There is no room in the driver table to make an entry for the
-	 ** booted RTA. Keep a note of its Uniq Num in the overflow table,
-	 ** so we can ignore it's ID requests.
-	 */
-	if (!p->RIONoMessage)
-		printk("The RTA connected to %s '%s' (%c) cannot be configured.  You cannot configure more than 128 ports to one host card.\n", MyType, MyName, MyLink + 'A');
-	for (entry = 0; entry < HostP->NumExtraBooted; entry++) {
-		if (HostP->ExtraUnits[entry] == RtaUniq) {
-			/*
-			 ** already got it!
-			 */
-			return 1;
-		}
-	}
-	/*
-	 ** If there is room, add the unit to the list of extras
-	 */
-	if (HostP->NumExtraBooted < MAX_EXTRA_UNITS)
-		HostP->ExtraUnits[HostP->NumExtraBooted++] = RtaUniq;
-	return 1;
-}
-
-
-/*
-** If the RTA or its host appears in the RIOBindTab[] structure then
-** we mustn't boot the RTA and should return 0.
-** This operation is slightly different from the other drivers for RIO
-** in that this is designed to work with the new utilities
-** not config.rio and is FAR SIMPLER.
-** We no longer support the RIOBootMode variable. It is all done from the
-** "boot/noboot" field in the rio.cf file.
-*/
-int RIOBootOk(struct rio_info *p, struct Host *HostP, unsigned long RtaUniq)
-{
-	int Entry;
-	unsigned int HostUniq = HostP->UniqueNum;
-
-	/*
-	 ** Search bindings table for RTA or its parent.
-	 ** If it exists, return 0, else 1.
-	 */
-	for (Entry = 0; (Entry < MAX_RTA_BINDINGS) && (p->RIOBindTab[Entry] != 0); Entry++) {
-		if ((p->RIOBindTab[Entry] == HostUniq) || (p->RIOBindTab[Entry] == RtaUniq))
-			return 0;
-	}
-	return 1;
-}
-
-/*
-** Make an empty slot tentative. If this is a 16 port RTA, make both
-** slots tentative, and the second one RTA_SECOND_SLOT as well.
-*/
-
-void rio_fill_host_slot(int entry, int entry2, unsigned int rta_uniq, struct Host *host)
-{
-	int link;
-
-	rio_dprintk(RIO_DEBUG_BOOT, "rio_fill_host_slot(%d, %d, 0x%x...)\n", entry, entry2, rta_uniq);
-
-	host->Mapping[entry].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE);
-	host->Mapping[entry].SysPort = NO_PORT;
-	host->Mapping[entry].RtaUniqueNum = rta_uniq;
-	host->Mapping[entry].HostUniqueNum = host->UniqueNum;
-	host->Mapping[entry].ID = entry + 1;
-	host->Mapping[entry].ID2 = 0;
-	if (entry2) {
-		host->Mapping[entry2].Flags = (RTA_BOOTED | RTA_NEWBOOT | SLOT_TENTATIVE | RTA16_SECOND_SLOT);
-		host->Mapping[entry2].SysPort = NO_PORT;
-		host->Mapping[entry2].RtaUniqueNum = rta_uniq;
-		host->Mapping[entry2].HostUniqueNum = host->UniqueNum;
-		host->Mapping[entry2].Name[0] = '\0';
-		host->Mapping[entry2].ID = entry2 + 1;
-		host->Mapping[entry2].ID2 = entry + 1;
-		host->Mapping[entry].ID2 = entry2 + 1;
-	}
-	/*
-	 ** Must set these up, so that utilities show
-	 ** topology of 16 port RTAs correctly
-	 */
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		host->Mapping[entry].Topology[link].Unit = ROUTE_DISCONNECT;
-		host->Mapping[entry].Topology[link].Link = NO_LINK;
-		if (entry2) {
-			host->Mapping[entry2].Topology[link].Unit = ROUTE_DISCONNECT;
-			host->Mapping[entry2].Topology[link].Link = NO_LINK;
-		}
-	}
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/riocmd.c linux-libre-2.6.39-gnu/drivers/char/rio/riocmd.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/riocmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/riocmd.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,939 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  ported from the existing SCO driver source
-**
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: riocmd.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:41
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)riocmd.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-
-
-static struct IdentifyRta IdRta;
-static struct KillNeighbour KillUnit;
-
-int RIOFoadRta(struct Host *HostP, struct Map *MapP)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA\n");
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = MapP->ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = IFOAD;
-	CmdBlkP->Packet.data[1] = 0;
-	CmdBlkP->Packet.data[2] = IFOAD_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (IFOAD_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "FOAD RTA: Failed to queue foad command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOZombieRta(struct Host *HostP, struct Map *MapP)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA\n");
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = MapP->ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = ZOMBIE;
-	CmdBlkP->Packet.data[1] = 0;
-	CmdBlkP->Packet.data[2] = ZOMBIE_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (ZOMBIE_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "ZOMBIE RTA: Failed to queue zombie command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOCommandRta(struct rio_info *p, unsigned long RtaUnique, int (*func) (struct Host * HostP, struct Map * MapP))
-{
-	unsigned int Host;
-
-	rio_dprintk(RIO_DEBUG_CMD, "Command RTA 0x%lx func %p\n", RtaUnique, func);
-
-	if (!RtaUnique)
-		return (0);
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		unsigned int Rta;
-		struct Host *HostP = &p->RIOHosts[Host];
-
-		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
-			struct Map *MapP = &HostP->Mapping[Rta];
-
-			if (MapP->RtaUniqueNum == RtaUnique) {
-				uint Link;
-
-				/*
-				 ** now, lets just check we have a route to it...
-				 ** IF the routing stuff is working, then one of the
-				 ** topology entries for this unit will have a legit
-				 ** route *somewhere*. We care not where - if its got
-				 ** any connections, we can get to it.
-				 */
-				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
-					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
-						/*
-						 ** Its worth trying the operation...
-						 */
-						return (*func) (HostP, MapP);
-					}
-				}
-			}
-		}
-	}
-	return -ENXIO;
-}
-
-
-int RIOIdentifyRta(struct rio_info *p, void __user * arg)
-{
-	unsigned int Host;
-
-	if (copy_from_user(&IdRta, arg, sizeof(IdRta))) {
-		rio_dprintk(RIO_DEBUG_CMD, "RIO_IDENTIFY_RTA copy failed\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		return -EFAULT;
-	}
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		unsigned int Rta;
-		struct Host *HostP = &p->RIOHosts[Host];
-
-		for (Rta = 0; Rta < RTAS_PER_HOST; Rta++) {
-			struct Map *MapP = &HostP->Mapping[Rta];
-
-			if (MapP->RtaUniqueNum == IdRta.RtaUnique) {
-				uint Link;
-				/*
-				 ** now, lets just check we have a route to it...
-				 ** IF the routing stuff is working, then one of the
-				 ** topology entries for this unit will have a legit
-				 ** route *somewhere*. We care not where - if its got
-				 ** any connections, we can get to it.
-				 */
-				for (Link = 0; Link < LINKS_PER_UNIT; Link++) {
-					if (MapP->Topology[Link].Unit <= (u8) MAX_RUP) {
-						/*
-						 ** Its worth trying the operation...
-						 */
-						struct CmdBlk *CmdBlkP;
-
-						rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA\n");
-
-						CmdBlkP = RIOGetCmdBlk();
-
-						if (!CmdBlkP) {
-							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: GetCmdBlk failed\n");
-							return -ENXIO;
-						}
-
-						CmdBlkP->Packet.dest_unit = MapP->ID;
-						CmdBlkP->Packet.dest_port = BOOT_RUP;
-						CmdBlkP->Packet.src_unit = 0;
-						CmdBlkP->Packet.src_port = BOOT_RUP;
-						CmdBlkP->Packet.len = 0x84;
-						CmdBlkP->Packet.data[0] = IDENTIFY;
-						CmdBlkP->Packet.data[1] = 0;
-						CmdBlkP->Packet.data[2] = IdRta.ID;
-
-						if (RIOQueueCmdBlk(HostP, MapP->ID - 1, CmdBlkP) == RIO_FAIL) {
-							rio_dprintk(RIO_DEBUG_CMD, "IDENTIFY RTA: Failed to queue command\n");
-							return -EIO;
-						}
-						return 0;
-					}
-				}
-			}
-		}
-	}
-	return -ENOENT;
-}
-
-
-int RIOKillNeighbour(struct rio_info *p, void __user * arg)
-{
-	uint Host;
-	uint ID;
-	struct Host *HostP;
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "KILL HOST NEIGHBOUR\n");
-
-	if (copy_from_user(&KillUnit, arg, sizeof(KillUnit))) {
-		rio_dprintk(RIO_DEBUG_CMD, "RIO_KILL_NEIGHBOUR copy failed\n");
-		p->RIOError.Error = COPYIN_FAILED;
-		return -EFAULT;
-	}
-
-	if (KillUnit.Link > 3)
-		return -ENXIO;
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "UFOAD: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = 0;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = UFOAD;
-	CmdBlkP->Packet.data[1] = KillUnit.Link;
-	CmdBlkP->Packet.data[2] = UFOAD_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (UFOAD_MAGIC >> 8) & 0xFF;
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		ID = 0;
-		HostP = &p->RIOHosts[Host];
-
-		if (HostP->UniqueNum == KillUnit.UniqueNum) {
-			if (RIOQueueCmdBlk(HostP, RTAS_PER_HOST + KillUnit.Link, CmdBlkP) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
-				return -EIO;
-			}
-			return 0;
-		}
-
-		for (ID = 0; ID < RTAS_PER_HOST; ID++) {
-			if (HostP->Mapping[ID].RtaUniqueNum == KillUnit.UniqueNum) {
-				CmdBlkP->Packet.dest_unit = ID + 1;
-				if (RIOQueueCmdBlk(HostP, ID, CmdBlkP) == RIO_FAIL) {
-					rio_dprintk(RIO_DEBUG_CMD, "UFOAD: Failed queue command\n");
-					return -EIO;
-				}
-				return 0;
-			}
-		}
-	}
-	RIOFreeCmdBlk(CmdBlkP);
-	return -ENXIO;
-}
-
-int RIOSuspendBootRta(struct Host *HostP, int ID, int Link)
-{
-	struct CmdBlk *CmdBlkP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA ID %d, link %c\n", ID, 'A' + Link);
-
-	CmdBlkP = RIOGetCmdBlk();
-
-	if (!CmdBlkP) {
-		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: GetCmdBlk failed\n");
-		return -ENXIO;
-	}
-
-	CmdBlkP->Packet.dest_unit = ID;
-	CmdBlkP->Packet.dest_port = BOOT_RUP;
-	CmdBlkP->Packet.src_unit = 0;
-	CmdBlkP->Packet.src_port = BOOT_RUP;
-	CmdBlkP->Packet.len = 0x84;
-	CmdBlkP->Packet.data[0] = IWAIT;
-	CmdBlkP->Packet.data[1] = Link;
-	CmdBlkP->Packet.data[2] = IWAIT_MAGIC & 0xFF;
-	CmdBlkP->Packet.data[3] = (IWAIT_MAGIC >> 8) & 0xFF;
-
-	if (RIOQueueCmdBlk(HostP, ID - 1, CmdBlkP) == RIO_FAIL) {
-		rio_dprintk(RIO_DEBUG_CMD, "SUSPEND BOOT ON RTA: Failed to queue iwait command\n");
-		return -EIO;
-	}
-	return 0;
-}
-
-int RIOFoadWakeup(struct rio_info *p)
-{
-	int port;
-	struct Port *PortP;
-	unsigned long flags;
-
-	for (port = 0; port < RIO_PORTS; port++) {
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->Config = 0;
-		PortP->State = 0;
-		PortP->InUse = NOT_INUSE;
-		PortP->PortState = 0;
-		PortP->FlushCmdBodge = 0;
-		PortP->ModemLines = 0;
-		PortP->ModemState = 0;
-		PortP->CookMode = 0;
-		PortP->ParamSem = 0;
-		PortP->Mapped = 0;
-		PortP->WflushFlag = 0;
-		PortP->MagicFlags = 0;
-		PortP->RxDataStart = 0;
-		PortP->TxBufferIn = 0;
-		PortP->TxBufferOut = 0;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	}
-	return (0);
-}
-
-/*
-** Incoming command on the COMMAND_RUP to be processed.
-*/
-static int RIOCommandRup(struct rio_info *p, uint Rup, struct Host *HostP, struct PKT __iomem *PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *)PacketP->data;
-	struct Port *PortP;
-	struct UnixRup *UnixRupP;
-	unsigned short SysPort;
-	unsigned short ReportedModemStatus;
-	unsigned short rup;
-	unsigned short subCommand;
-	unsigned long flags;
-
-	func_enter();
-
-	/*
-	 ** 16 port RTA note:
-	 ** Command rup packets coming from the RTA will have pkt->data[1] (which
-	 ** translates to PktCmdP->PhbNum) set to the host port number for the
-	 ** particular unit. To access the correct BaseSysPort for a 16 port RTA,
-	 ** we can use PhbNum to get the rup number for the appropriate 8 port
-	 ** block (for the first block, this should be equal to 'Rup').
-	 */
-	rup = readb(&PktCmdP->PhbNum) / (unsigned short) PORTS_PER_RTA;
-	UnixRupP = &HostP->UnixRups[rup];
-	SysPort = UnixRupP->BaseSysPort + (readb(&PktCmdP->PhbNum) % (unsigned short) PORTS_PER_RTA);
-	rio_dprintk(RIO_DEBUG_CMD, "Command on rup %d, port %d\n", rup, SysPort);
-
-	if (UnixRupP->BaseSysPort == NO_PORT) {
-		rio_dprintk(RIO_DEBUG_CMD, "OBSCURE ERROR!\n");
-		rio_dprintk(RIO_DEBUG_CMD, "Diagnostics follow. Please WRITE THESE DOWN and report them to Specialix Technical Support\n");
-		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Host number %Zd, name ``%s''\n", HostP - p->RIOHosts, HostP->Name);
-		rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: Rup number  0x%x\n", rup);
-
-		if (Rup < (unsigned short) MAX_RUP) {
-			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for RTA ``%s''\n", HostP->Mapping[Rup].Name);
-		} else
-			rio_dprintk(RIO_DEBUG_CMD, "CONTROL information: This is the RUP for link ``%c'' of host ``%s''\n", ('A' + Rup - MAX_RUP), HostP->Name);
-
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Destination 0x%x:0x%x\n", readb(&PacketP->dest_unit), readb(&PacketP->dest_port));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Source	  0x%x:0x%x\n", readb(&PacketP->src_unit), readb(&PacketP->src_port));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Length	  0x%x (%d)\n", readb(&PacketP->len), readb(&PacketP->len));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Control	 0x%x (%d)\n", readb(&PacketP->control), readb(&PacketP->control));
-		rio_dprintk(RIO_DEBUG_CMD, "PACKET information: Check	   0x%x (%d)\n", readw(&PacketP->csum), readw(&PacketP->csum));
-		rio_dprintk(RIO_DEBUG_CMD, "COMMAND information: Host Port Number 0x%x, " "Command Code 0x%x\n", readb(&PktCmdP->PhbNum), readb(&PktCmdP->Command));
-		return 1;
-	}
-	PortP = p->RIOPortp[SysPort];
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	switch (readb(&PktCmdP->Command)) {
-	case RIOC_BREAK_RECEIVED:
-		rio_dprintk(RIO_DEBUG_CMD, "Received a break!\n");
-		/* If the current line disc. is not multi-threading and
-		   the current processor is not the default, reset rup_intr
-		   and return 0 to ensure that the command packet is
-		   not freed. */
-		/* Call tmgr HANGUP HERE */
-		/* Fix this later when every thing works !!!! RAMRAJ */
-		gs_got_break(&PortP->gs);
-		break;
-
-	case RIOC_COMPLETE:
-		rio_dprintk(RIO_DEBUG_CMD, "Command complete on phb %d host %Zd\n", readb(&PktCmdP->PhbNum), HostP - p->RIOHosts);
-		subCommand = 1;
-		switch (readb(&PktCmdP->SubCommand)) {
-		case RIOC_MEMDUMP:
-			rio_dprintk(RIO_DEBUG_CMD, "Memory dump cmd (0x%x) from addr 0x%x\n", readb(&PktCmdP->SubCommand), readw(&PktCmdP->SubAddr));
-			break;
-		case RIOC_READ_REGISTER:
-			rio_dprintk(RIO_DEBUG_CMD, "Read register (0x%x)\n", readw(&PktCmdP->SubAddr));
-			p->CdRegister = (readb(&PktCmdP->ModemStatus) & RIOC_MSVR1_HOST);
-			break;
-		default:
-			subCommand = 0;
-			break;
-		}
-		if (subCommand)
-			break;
-		rio_dprintk(RIO_DEBUG_CMD, "New status is 0x%x was 0x%x\n", readb(&PktCmdP->PortStatus), PortP->PortState);
-		if (PortP->PortState != readb(&PktCmdP->PortStatus)) {
-			rio_dprintk(RIO_DEBUG_CMD, "Mark status & wakeup\n");
-			PortP->PortState = readb(&PktCmdP->PortStatus);
-			/* What should we do here ...
-			   wakeup( &PortP->PortState );
-			 */
-		} else
-			rio_dprintk(RIO_DEBUG_CMD, "No change\n");
-
-		/* FALLTHROUGH */
-	case RIOC_MODEM_STATUS:
-		/*
-		 ** Knock out the tbusy and tstop bits, as these are not relevant
-		 ** to the check for modem status change (they're just there because
-		 ** it's a convenient place to put them!).
-		 */
-		ReportedModemStatus = readb(&PktCmdP->ModemStatus);
-		if ((PortP->ModemState & RIOC_MSVR1_HOST) ==
-				(ReportedModemStatus & RIOC_MSVR1_HOST)) {
-			rio_dprintk(RIO_DEBUG_CMD, "Modem status unchanged 0x%x\n", PortP->ModemState);
-			/*
-			 ** Update ModemState just in case tbusy or tstop states have
-			 ** changed.
-			 */
-			PortP->ModemState = ReportedModemStatus;
-		} else {
-			rio_dprintk(RIO_DEBUG_CMD, "Modem status change from 0x%x to 0x%x\n", PortP->ModemState, ReportedModemStatus);
-			PortP->ModemState = ReportedModemStatus;
-#ifdef MODEM_SUPPORT
-			if (PortP->Mapped) {
-				/***********************************************************\
-				*************************************************************
-				***													   ***
-				***		  M O D E M   S T A T E   C H A N G E		  ***
-				***													   ***
-				*************************************************************
-				\***********************************************************/
-				/*
-				 ** If the device is a modem, then check the modem
-				 ** carrier.
-				 */
-				if (PortP->gs.port.tty == NULL)
-					break;
-				if (PortP->gs.port.tty->termios == NULL)
-					break;
-
-				if (!(PortP->gs.port.tty->termios->c_cflag & CLOCAL) && ((PortP->State & (RIO_MOPEN | RIO_WOPEN)))) {
-
-					rio_dprintk(RIO_DEBUG_CMD, "Is there a Carrier?\n");
-					/*
-					 ** Is there a carrier?
-					 */
-					if (PortP->ModemState & RIOC_MSVR1_CD) {
-						/*
-						 ** Has carrier just appeared?
-						 */
-						if (!(PortP->State & RIO_CARR_ON)) {
-							rio_dprintk(RIO_DEBUG_CMD, "Carrier just came up.\n");
-							PortP->State |= RIO_CARR_ON;
-							/*
-							 ** wakeup anyone in WOPEN
-							 */
-							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN))
-								wake_up_interruptible(&PortP->gs.port.open_wait);
-						}
-					} else {
-						/*
-						 ** Has carrier just dropped?
-						 */
-						if (PortP->State & RIO_CARR_ON) {
-							if (PortP->State & (PORT_ISOPEN | RIO_WOPEN | RIO_MOPEN))
-								tty_hangup(PortP->gs.port.tty);
-							PortP->State &= ~RIO_CARR_ON;
-							rio_dprintk(RIO_DEBUG_CMD, "Carrirer just went down\n");
-						}
-					}
-				}
-			}
-#endif
-		}
-		break;
-
-	default:
-		rio_dprintk(RIO_DEBUG_CMD, "Unknown command %d on CMD_RUP of host %Zd\n", readb(&PktCmdP->Command), HostP - p->RIOHosts);
-		break;
-	}
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	func_exit();
-
-	return 1;
-}
-
-/*
-** The command mechanism:
-**	Each rup has a chain of commands associated with it.
-**	This chain is maintained by routines in this file.
-**	Periodically we are called and we run a quick check of all the
-**	active chains to determine if there is a command to be executed,
-**	and if the rup is ready to accept it.
-**
-*/
-
-/*
-** Allocate an empty command block.
-*/
-struct CmdBlk *RIOGetCmdBlk(void)
-{
-	struct CmdBlk *CmdBlkP;
-
-	CmdBlkP = kzalloc(sizeof(struct CmdBlk), GFP_ATOMIC);
-	return CmdBlkP;
-}
-
-/*
-** Return a block to the head of the free list.
-*/
-void RIOFreeCmdBlk(struct CmdBlk *CmdBlkP)
-{
-	kfree(CmdBlkP);
-}
-
-/*
-** attach a command block to the list of commands to be performed for
-** a given rup.
-*/
-int RIOQueueCmdBlk(struct Host *HostP, uint Rup, struct CmdBlk *CmdBlkP)
-{
-	struct CmdBlk **Base;
-	struct UnixRup *UnixRupP;
-	unsigned long flags;
-
-	if (Rup >= (unsigned short) (MAX_RUP + LINKS_PER_UNIT)) {
-		rio_dprintk(RIO_DEBUG_CMD, "Illegal rup number %d in RIOQueueCmdBlk\n", Rup);
-		RIOFreeCmdBlk(CmdBlkP);
-		return RIO_FAIL;
-	}
-
-	UnixRupP = &HostP->UnixRups[Rup];
-
-	rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-
-	/*
-	 ** If the RUP is currently inactive, then put the request
-	 ** straight on the RUP....
-	 */
-	if ((UnixRupP->CmdsWaitingP == NULL) && (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE) && (CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP)
-																	     : 1)) {
-		rio_dprintk(RIO_DEBUG_CMD, "RUP inactive-placing command straight on. Cmd byte is 0x%x\n", CmdBlkP->Packet.data[0]);
-
-		/*
-		 ** Whammy! blat that pack!
-		 */
-		HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
-
-		/*
-		 ** place command packet on the pending position.
-		 */
-		UnixRupP->CmdPendingP = CmdBlkP;
-
-		/*
-		 ** set the command register
-		 */
-		writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
-
-		rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-
-		return 0;
-	}
-	rio_dprintk(RIO_DEBUG_CMD, "RUP active - en-queing\n");
-
-	if (UnixRupP->CmdsWaitingP != NULL)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command waiting\n");
-	if (UnixRupP->CmdPendingP != NULL)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command pending\n");
-	if (readw(&UnixRupP->RupP->txcontrol) != TX_RUP_INACTIVE)
-		rio_dprintk(RIO_DEBUG_CMD, "Rup active - command rup not ready\n");
-
-	Base = &UnixRupP->CmdsWaitingP;
-
-	rio_dprintk(RIO_DEBUG_CMD, "First try to queue cmdblk %p at %p\n", CmdBlkP, Base);
-
-	while (*Base) {
-		rio_dprintk(RIO_DEBUG_CMD, "Command cmdblk %p here\n", *Base);
-		Base = &((*Base)->NextP);
-		rio_dprintk(RIO_DEBUG_CMD, "Now try to queue cmd cmdblk %p at %p\n", CmdBlkP, Base);
-	}
-
-	rio_dprintk(RIO_DEBUG_CMD, "Will queue cmdblk %p at %p\n", CmdBlkP, Base);
-
-	*Base = CmdBlkP;
-
-	CmdBlkP->NextP = NULL;
-
-	rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-
-	return 0;
-}
-
-/*
-** Here we go - if there is an empty rup, fill it!
-** must be called at splrio() or higher.
-*/
-void RIOPollHostCommands(struct rio_info *p, struct Host *HostP)
-{
-	struct CmdBlk *CmdBlkP;
-	struct UnixRup *UnixRupP;
-	struct PKT __iomem *PacketP;
-	unsigned short Rup;
-	unsigned long flags;
-
-
-	Rup = MAX_RUP + LINKS_PER_UNIT;
-
-	do {			/* do this loop for each RUP */
-		/*
-		 ** locate the rup we are processing & lock it
-		 */
-		UnixRupP = &HostP->UnixRups[--Rup];
-
-		spin_lock_irqsave(&UnixRupP->RupLock, flags);
-
-		/*
-		 ** First check for incoming commands:
-		 */
-		if (readw(&UnixRupP->RupP->rxcontrol) != RX_RUP_INACTIVE) {
-			int FreeMe;
-
-			PacketP = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->rxpkt));
-
-			switch (readb(&PacketP->dest_port)) {
-			case BOOT_RUP:
-				rio_dprintk(RIO_DEBUG_CMD, "Incoming Boot %s packet '%x'\n", readb(&PacketP->len) & 0x80 ? "Command" : "Data", readb(&PacketP->data[0]));
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIOBootRup(p, Rup, HostP, PacketP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			case COMMAND_RUP:
-				/*
-				 ** Free the RUP lock as loss of carrier causes a
-				 ** ttyflush which will (eventually) call another
-				 ** routine that uses the RUP lock.
-				 */
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIOCommandRup(p, Rup, HostP, PacketP);
-				if (readb(&PacketP->data[5]) == RIOC_MEMDUMP) {
-					rio_dprintk(RIO_DEBUG_CMD, "Memdump from 0x%x complete\n", readw(&(PacketP->data[6])));
-					rio_memcpy_fromio(p->RIOMemDump, &(PacketP->data[8]), 32);
-				}
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			case ROUTE_RUP:
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				FreeMe = RIORouteRup(p, Rup, HostP, PacketP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-				break;
-
-			default:
-				rio_dprintk(RIO_DEBUG_CMD, "Unknown RUP %d\n", readb(&PacketP->dest_port));
-				FreeMe = 1;
-				break;
-			}
-
-			if (FreeMe) {
-				rio_dprintk(RIO_DEBUG_CMD, "Free processed incoming command packet\n");
-				put_free_end(HostP, PacketP);
-
-				writew(RX_RUP_INACTIVE, &UnixRupP->RupP->rxcontrol);
-
-				if (readw(&UnixRupP->RupP->handshake) == PHB_HANDSHAKE_SET) {
-					rio_dprintk(RIO_DEBUG_CMD, "Handshake rup %d\n", Rup);
-					writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &UnixRupP->RupP->handshake);
-				}
-			}
-		}
-
-		/*
-		 ** IF a command was running on the port,
-		 ** and it has completed, then tidy it up.
-		 */
-		if ((CmdBlkP = UnixRupP->CmdPendingP) &&	/* ASSIGN! */
-		    (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
-			/*
-			 ** we are idle.
-			 ** there is a command in pending.
-			 ** Therefore, this command has finished.
-			 ** So, wakeup whoever is waiting for it (and tell them
-			 ** what happened).
-			 */
-			if (CmdBlkP->Packet.dest_port == BOOT_RUP)
-				rio_dprintk(RIO_DEBUG_CMD, "Free Boot %s Command Block '%x'\n", CmdBlkP->Packet.len & 0x80 ? "Command" : "Data", CmdBlkP->Packet.data[0]);
-
-			rio_dprintk(RIO_DEBUG_CMD, "Command %p completed\n", CmdBlkP);
-
-			/*
-			 ** Clear the Rup lock to prevent mutual exclusion.
-			 */
-			if (CmdBlkP->PostFuncP) {
-				rio_spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-				(*CmdBlkP->PostFuncP) (CmdBlkP->PostArg, CmdBlkP);
-				rio_spin_lock_irqsave(&UnixRupP->RupLock, flags);
-			}
-
-			/*
-			 ** ....clear the pending flag....
-			 */
-			UnixRupP->CmdPendingP = NULL;
-
-			/*
-			 ** ....and return the command block to the freelist.
-			 */
-			RIOFreeCmdBlk(CmdBlkP);
-		}
-
-		/*
-		 ** If there is a command for this rup, and the rup
-		 ** is idle, then process the command
-		 */
-		if ((CmdBlkP = UnixRupP->CmdsWaitingP) &&	/* ASSIGN! */
-		    (UnixRupP->CmdPendingP == NULL) && (readw(&UnixRupP->RupP->txcontrol) == TX_RUP_INACTIVE)) {
-			/*
-			 ** if the pre-function is non-zero, call it.
-			 ** If it returns RIO_FAIL then don't
-			 ** send this command yet!
-			 */
-			if (!(CmdBlkP->PreFuncP ? (*CmdBlkP->PreFuncP) (CmdBlkP->PreArg, CmdBlkP) : 1)) {
-				rio_dprintk(RIO_DEBUG_CMD, "Not ready to start command %p\n", CmdBlkP);
-			} else {
-				rio_dprintk(RIO_DEBUG_CMD, "Start new command %p Cmd byte is 0x%x\n", CmdBlkP, CmdBlkP->Packet.data[0]);
-				/*
-				 ** Whammy! blat that pack!
-				 */
-				HostP->Copy(&CmdBlkP->Packet, RIO_PTR(HostP->Caddr, readw(&UnixRupP->RupP->txpkt)), sizeof(struct PKT));
-
-				/*
-				 ** remove the command from the rup command queue...
-				 */
-				UnixRupP->CmdsWaitingP = CmdBlkP->NextP;
-
-				/*
-				 ** ...and place it on the pending position.
-				 */
-				UnixRupP->CmdPendingP = CmdBlkP;
-
-				/*
-				 ** set the command register
-				 */
-				writew(TX_PACKET_READY, &UnixRupP->RupP->txcontrol);
-
-				/*
-				 ** the command block will be freed
-				 ** when the command has been processed.
-				 */
-			}
-		}
-		spin_unlock_irqrestore(&UnixRupP->RupLock, flags);
-	} while (Rup);
-}
-
-int RIOWFlushMark(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	PortP->WflushFlag++;
-	PortP->MagicFlags |= MAGIC_FLUSH;
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return RIOUnUse(iPortP, CmdBlkP);
-}
-
-int RIORFlushEnable(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	struct PKT __iomem *PacketP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	while (can_remove_receive(&PacketP, PortP)) {
-		remove_receive(PortP);
-		put_free_end(PortP->HostP, PacketP);
-	}
-
-	if (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET) {
-		/*
-		 ** MAGIC! (Basically, handshake the RX buffer, so that
-		 ** the RTAs upstream can be re-enabled.)
-		 */
-		rio_dprintk(RIO_DEBUG_CMD, "Util: Set RX handshake bit\n");
-		writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
-	}
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return RIOUnUse(iPortP, CmdBlkP);
-}
-
-int RIOUnUse(unsigned long iPortP, struct CmdBlk *CmdBlkP)
-{
-	struct Port *PortP = (struct Port *) iPortP;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	rio_dprintk(RIO_DEBUG_CMD, "Decrement in use count for port\n");
-
-	if (PortP->InUse) {
-		if (--PortP->InUse != NOT_INUSE) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return 0;
-		}
-	}
-	/*
-	 ** While PortP->InUse is set (i.e. a preemptive command has been sent to
-	 ** the RTA and is awaiting completion), any transmit data is prevented from
-	 ** being transferred from the write queue into the transmit packets
-	 ** (add_transmit) and no furthur transmit interrupt will be sent for that
-	 ** data. The next interrupt will occur up to 500ms later (RIOIntr is called
-	 ** twice a second as a saftey measure). This was the case when kermit was
-	 ** used to send data into a RIO port. After each packet was sent, TCFLSH
-	 ** was called to flush the read queue preemptively. PortP->InUse was
-	 ** incremented, thereby blocking the 6 byte acknowledgement packet
-	 ** transmitted back. This acknowledgment hung around for 500ms before
-	 ** being sent, thus reducing input performance substantially!.
-	 ** When PortP->InUse becomes NOT_INUSE, we must ensure that any data
-	 ** hanging around in the transmit buffer is sent immediately.
-	 */
-	writew(1, &PortP->HostP->ParmMapP->tx_intr);
-	/* What to do here ..
-	   wakeup( (caddr_t)&(PortP->InUse) );
-	 */
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return 0;
-}
-
-/*
-** 
-** How to use this file:
-** 
-** To send a command down a rup, you need to allocate a command block, fill
-** in the packet information, fill in the command number, fill in the pre-
-** and post- functions and arguments, and then add the command block to the
-** queue of command blocks for the port in question. When the port is idle,
-** then the pre-function will be called. If this returns RIO_FAIL then the
-** command will be re-queued and tried again at a later date (probably in one
-** clock tick). If the pre-function returns NOT RIO_FAIL, then the command
-** packet will be queued on the RUP, and the txcontrol field set to the
-** command number. When the txcontrol field has changed from being the
-** command number, then the post-function will be called, with the argument
-** specified earlier, a pointer to the command block, and the value of
-** txcontrol.
-** 
-** To allocate a command block, call RIOGetCmdBlk(). This returns a pointer
-** to the command block structure allocated, or NULL if there aren't any.
-** The block will have been zeroed for you.
-** 
-** The structure has the following fields:
-** 
-** struct CmdBlk
-** {
-**	 struct CmdBlk *NextP;		  ** Pointer to next command block   **
-**	 struct PKT	 Packet;		** A packet, to copy to the rup	**
-**			int	 (*PreFuncP)();  ** The func to call to check if OK **
-**			int	 PreArg;		** The arg for the func			**
-**			int	 (*PostFuncP)(); ** The func to call when completed **
-**			int	 PostArg;	   ** The arg for the func			**
-** };
-** 
-** You need to fill in ALL fields EXCEPT NextP, which is used to link the
-** blocks together either on the free list or on the Rup list.
-** 
-** Packet is an actual packet structure to be filled in with the packet
-** information associated with the command. You need to fill in everything,
-** as the command processor doesn't process the command packet in any way.
-** 
-** The PreFuncP is called before the packet is enqueued on the host rup.
-** PreFuncP is called as (*PreFuncP)(PreArg, CmdBlkP);. PreFuncP must
-** return !RIO_FAIL to have the packet queued on the rup, and RIO_FAIL
-** if the packet is NOT to be queued.
-** 
-** The PostFuncP is called when the command has completed. It is called
-** as (*PostFuncP)(PostArg, CmdBlkP, txcontrol);. PostFuncP is not expected
-** to return a value. PostFuncP does NOT need to free the command block,
-** as this happens automatically after PostFuncP returns.
-** 
-** Once the command block has been filled in, it is attached to the correct
-** queue by calling RIOQueueCmdBlk( HostP, Rup, CmdBlkP ) where HostP is
-** a pointer to the struct Host, Rup is the NUMBER of the rup (NOT a pointer
-** to it!), and CmdBlkP is the pointer to the command block allocated using
-** RIOGetCmdBlk().
-** 
-*/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioctrl.c linux-libre-2.6.39-gnu/drivers/char/rio/rioctrl.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioctrl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioctrl.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1504 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioctrl.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:42
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)rioctrl.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-
-
-static struct LpbReq LpbReq;
-static struct RupReq RupReq;
-static struct PortReq PortReq;
-static struct HostReq HostReq;	/* oh really?  global?  and no locking? */
-static struct HostDpRam HostDpRam;
-static struct DebugCtrl DebugCtrl;
-static struct Map MapEnt;
-static struct PortSetup PortSetup;
-static struct DownLoad DownLoad;
-static struct SendPack SendPack;
-/* static struct StreamInfo	StreamInfo; */
-/* static char modemtable[RIO_PORTS]; */
-static struct SpecialRupCmd SpecialRupCmd;
-static struct PortParams PortParams;
-static struct portStats portStats;
-
-static struct SubCmdStruct {
-	ushort Host;
-	ushort Rup;
-	ushort Port;
-	ushort Addr;
-} SubCmd;
-
-struct PortTty {
-	uint port;
-	struct ttystatics Tty;
-};
-
-static struct PortTty PortTty;
-typedef struct ttystatics TERMIO;
-
-/*
-** This table is used when the config.rio downloads bin code to the
-** driver. We index the table using the product code, 0-F, and call
-** the function pointed to by the entry, passing the information
-** about the boot.
-** The RIOBootCodeUNKNOWN entry is there to politely tell the calling
-** process to bog off.
-*/
-static int
- (*RIOBootTable[MAX_PRODUCT]) (struct rio_info *, struct DownLoad *) = {
-					/* 0 */ RIOBootCodeHOST,
-					/* Host Card */
-					/* 1 */ RIOBootCodeRTA,
-					/* RTA */
-};
-
-#define drv_makedev(maj, min) ((((uint) maj & 0xff) << 8) | ((uint) min & 0xff))
-
-static int copy_from_io(void __user *to, void __iomem *from, size_t size)
-{
-	void *buf = kmalloc(size, GFP_KERNEL);
-	int res = -ENOMEM;
-	if (buf) {
-		rio_memcpy_fromio(buf, from, size);
-		res = copy_to_user(to, buf, size);
-		kfree(buf);
-	}
-	return res;
-}
-
-int riocontrol(struct rio_info *p, dev_t dev, int cmd, unsigned long arg, int su)
-{
-	uint Host;		/* leave me unsigned! */
-	uint port;		/* and me! */
-	struct Host *HostP;
-	ushort loop;
-	int Entry;
-	struct Port *PortP;
-	struct PKT __iomem *PacketP;
-	int retval = 0;
-	unsigned long flags;
-	void __user *argp = (void __user *)arg;
-
-	func_enter();
-
-	/* Confuse the compiler to think that we've initialized these */
-	Host = 0;
-	PortP = NULL;
-
-	rio_dprintk(RIO_DEBUG_CTRL, "control ioctl cmd: 0x%x arg: %p\n", cmd, argp);
-
-	switch (cmd) {
-		/*
-		 ** RIO_SET_TIMER
-		 **
-		 ** Change the value of the host card interrupt timer.
-		 ** If the host card number is -1 then all host cards are changed
-		 ** otherwise just the specified host card will be changed.
-		 */
-	case RIO_SET_TIMER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_TIMER to %ldms\n", arg);
-		{
-			int host, value;
-			host = (arg >> 16) & 0x0000FFFF;
-			value = arg & 0x0000ffff;
-			if (host == -1) {
-				for (host = 0; host < p->RIONumHosts; host++) {
-					if (p->RIOHosts[host].Flags == RC_RUNNING) {
-						writew(value, &p->RIOHosts[host].ParmMapP->timer);
-					}
-				}
-			} else if (host >= p->RIONumHosts) {
-				return -EINVAL;
-			} else {
-				if (p->RIOHosts[host].Flags == RC_RUNNING) {
-					writew(value, &p->RIOHosts[host].ParmMapP->timer);
-				}
-			}
-		}
-		return 0;
-
-	case RIO_FOAD_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_FOAD_RTA\n");
-		return RIOCommandRta(p, arg, RIOFoadRta);
-
-	case RIO_ZOMBIE_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ZOMBIE_RTA\n");
-		return RIOCommandRta(p, arg, RIOZombieRta);
-
-	case RIO_IDENTIFY_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_IDENTIFY_RTA\n");
-		return RIOIdentifyRta(p, argp);
-
-	case RIO_KILL_NEIGHBOUR:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_KILL_NEIGHBOUR\n");
-		return RIOKillNeighbour(p, argp);
-
-	case SPECIAL_RUP_CMD:
-		{
-			struct CmdBlk *CmdBlkP;
-
-			rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD\n");
-			if (copy_from_user(&SpecialRupCmd, argp, sizeof(SpecialRupCmd))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD copy failed\n");
-				p->RIOError.Error = COPYIN_FAILED;
-				return -EFAULT;
-			}
-			CmdBlkP = RIOGetCmdBlk();
-			if (!CmdBlkP) {
-				rio_dprintk(RIO_DEBUG_CTRL, "SPECIAL_RUP_CMD GetCmdBlk failed\n");
-				return -ENXIO;
-			}
-			CmdBlkP->Packet = SpecialRupCmd.Packet;
-			if (SpecialRupCmd.Host >= p->RIONumHosts)
-				SpecialRupCmd.Host = 0;
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue special rup command for host %d rup %d\n", SpecialRupCmd.Host, SpecialRupCmd.RupNum);
-			if (RIOQueueCmdBlk(&p->RIOHosts[SpecialRupCmd.Host], SpecialRupCmd.RupNum, CmdBlkP) == RIO_FAIL) {
-				printk(KERN_WARNING "rio: FAILED TO QUEUE SPECIAL RUP COMMAND\n");
-			}
-			return 0;
-		}
-
-	case RIO_DEBUG_MEM:
-		return -EPERM;
-
-	case RIO_ALL_MODEM:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ALL_MODEM\n");
-		p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
-		return -EINVAL;
-
-	case RIO_GET_TABLE:
-		/*
-		 ** Read the routing table from the device driver to user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE\n");
-
-		if ((retval = RIOApel(p)) != 0)
-			return retval;
-
-		if (copy_to_user(argp, p->RIOConnectTable, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_TABLE copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-
-		{
-			int entry;
-			rio_dprintk(RIO_DEBUG_CTRL, "*****\nMAP ENTRIES\n");
-			for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-				if ((p->RIOConnectTable[entry].ID == 0) && (p->RIOConnectTable[entry].HostUniqueNum == 0) && (p->RIOConnectTable[entry].RtaUniqueNum == 0))
-					continue;
-
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Flags = 0x%x\n", entry, (int) p->RIOConnectTable[entry].Flags);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.SysPort = 0x%x\n", entry, (int) p->RIOConnectTable[entry].SysPort);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[0].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[0].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[1].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[1].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[2].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[2].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[3].Unit = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Unit);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Top[4].Link = %x\n", entry, p->RIOConnectTable[entry].Topology[3].Link);
-				rio_dprintk(RIO_DEBUG_CTRL, "Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name);
-			}
-			rio_dprintk(RIO_DEBUG_CTRL, "*****\nEND MAP ENTRIES\n");
-		}
-		p->RIOQuickCheck = NOT_CHANGED;	/* a table has been gotten */
-		return 0;
-
-	case RIO_PUT_TABLE:
-		/*
-		 ** Write the routing table to the device driver from user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOConnectTable[0], argp, TOTAL_MAP_ENTRIES * sizeof(struct Map))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_TABLE copy failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-/*
-***********************************
-				{
-					int entry;
-					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nMAP ENTRIES\n") );
-					for ( entry=0; entry<TOTAL_MAP_ENTRIES; entry++ )
-					{
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.HostUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].HostUniqueNum ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.RtaUniqueNum = 0x%x\n", entry, p->RIOConnectTable[entry].RtaUniqueNum ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID = 0x%x\n", entry, p->RIOConnectTable[entry].ID ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.ID2 = 0x%x\n", entry, p->RIOConnectTable[entry].ID2 ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Flags = 0x%x\n", entry, p->RIOConnectTable[entry].Flags ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.SysPort = 0x%x\n", entry, p->RIOConnectTable[entry].SysPort ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[0].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[0].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[1].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[1].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[2].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[2].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[3].Unit = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Unit ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Top[4].Link = %b\n", entry, p->RIOConnectTable[entry].Topology[3].Link ) );
-						rio_dprint(RIO_DEBUG_CTRL,  ("Map entry %d.Name = %s\n", entry, p->RIOConnectTable[entry].Name ) );
-					}
-					rio_dprint(RIO_DEBUG_CTRL,  ("*****\nEND MAP ENTRIES\n") );
-				}
-***********************************
-*/
-		return RIONewTable(p);
-
-	case RIO_GET_BINDINGS:
-		/*
-		 ** Send bindings table, containing unique numbers of RTAs owned
-		 ** by this system to user space
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_to_user(argp, p->RIOBindTab, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_BINDINGS copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_PUT_BINDINGS:
-		/*
-		 ** Receive a bindings table, containing unique numbers of RTAs owned
-		 ** by this system
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS\n");
-
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOBindTab[0], argp, (sizeof(ulong) * MAX_RTA_BINDINGS))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PUT_BINDINGS copy failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_BIND_RTA:
-		{
-			int EmptySlot = -1;
-			/*
-			 ** Bind this RTA to host, so that it will be booted by
-			 ** host in 'boot owned RTAs' mode.
-			 */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA\n");
-
-			if (!su) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_BIND_RTA !Root\n");
-				p->RIOError.Error = NOT_SUPER_USER;
-				return -EPERM;
-			}
-			for (Entry = 0; Entry < MAX_RTA_BINDINGS; Entry++) {
-				if ((EmptySlot == -1) && (p->RIOBindTab[Entry] == 0L))
-					EmptySlot = Entry;
-				else if (p->RIOBindTab[Entry] == arg) {
-					/*
-					 ** Already exists - delete
-					 */
-					p->RIOBindTab[Entry] = 0L;
-					rio_dprintk(RIO_DEBUG_CTRL, "Removing Rta %ld from p->RIOBindTab\n", arg);
-					return 0;
-				}
-			}
-			/*
-			 ** Dosen't exist - add
-			 */
-			if (EmptySlot != -1) {
-				p->RIOBindTab[EmptySlot] = arg;
-				rio_dprintk(RIO_DEBUG_CTRL, "Adding Rta %lx to p->RIOBindTab\n", arg);
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "p->RIOBindTab full! - Rta %lx not added\n", arg);
-				return -ENOMEM;
-			}
-			return 0;
-		}
-
-	case RIO_RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME\n");
-		port = arg;
-		if ((port < 0) || (port > 511)) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		PortP = p->RIOPortp[port];
-		if (!PortP->Mapped) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not mapped\n", port);
-			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
-			return -EINVAL;
-		}
-		if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d not open\n", port);
-			return -EINVAL;
-		}
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		if (RIOPreemptiveCmd(p, (p->RIOPortp[port]), RIOC_RESUME) ==
-				RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESUME: Port %d resumed\n", port);
-			PortP->State |= RIO_BUSY;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_ASSIGN_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_ASSIGN_RTA !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIOAssignRta(p, &MapEnt);
-
-	case RIO_CHANGE_NAME:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_CHANGE_NAME !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIOChangeName(p, &MapEnt);
-
-	case RIO_DELETE_RTA:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DELETE_RTA !Root\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&MapEnt, argp, sizeof(MapEnt))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Copy from data space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		return RIODeleteRta(p, &MapEnt);
-
-	case RIO_QUICK_CHECK:
-		if (copy_to_user(argp, &p->RIORtaDisCons, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_LAST_ERROR:
-		if (copy_to_user(argp, &p->RIOError, sizeof(struct Error)))
-			return -EFAULT;
-		return 0;
-
-	case RIO_GET_LOG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_LOG\n");
-		return -EINVAL;
-
-	case RIO_GET_MODTYPE:
-		if (copy_from_user(&port, argp, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Get module type for port %d\n", port);
-		if (port < 0 || port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		PortP = (p->RIOPortp[port]);
-		if (!PortP->Mapped) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_MODTYPE: Port %d not mapped\n", port);
-			p->RIOError.Error = PORT_NOT_MAPPED_INTO_SYSTEM;
-			return -EINVAL;
-		}
-		/*
-		 ** Return module type of port
-		 */
-		port = PortP->HostP->UnixRups[PortP->RupNum].ModTypes;
-		if (copy_to_user(argp, &port, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return (0);
-	case RIO_BLOCK_OPENS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Opens block until booted\n");
-		for (Entry = 0; Entry < RIO_PORTS; Entry++) {
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			p->RIOPortp[Entry]->WaitUntilBooted = 1;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		}
-		return 0;
-
-	case RIO_SETUP_PORTS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Setup ports\n");
-		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "EFAULT");
-			return -EFAULT;
-		}
-		if (PortSetup.From > PortSetup.To || PortSetup.To >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "ENXIO");
-			return -ENXIO;
-		}
-		if (PortSetup.XpCps > p->RIOConf.MaxXpCps || PortSetup.XpCps < p->RIOConf.MinXpCps) {
-			p->RIOError.Error = XPRINT_CPS_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "EINVAL");
-			return -EINVAL;
-		}
-		if (!p->RIOPortp) {
-			printk(KERN_ERR "rio: No p->RIOPortp array!\n");
-			rio_dprintk(RIO_DEBUG_CTRL, "No p->RIOPortp array!\n");
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "entering loop (%d %d)!\n", PortSetup.From, PortSetup.To);
-		for (loop = PortSetup.From; loop <= PortSetup.To; loop++) {
-			rio_dprintk(RIO_DEBUG_CTRL, "in loop (%d)!\n", loop);
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "after loop (%d)!\n", loop);
-		rio_dprintk(RIO_DEBUG_CTRL, "Retval:%x\n", retval);
-		return retval;
-
-	case RIO_GET_PORT_SETUP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port setup\n");
-		if (copy_from_user(&PortSetup, argp, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortSetup.From >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		port = PortSetup.To = PortSetup.From;
-		PortSetup.IxAny = (p->RIOPortp[port]->Config & RIO_IXANY) ? 1 : 0;
-		PortSetup.IxOn = (p->RIOPortp[port]->Config & RIO_IXON) ? 1 : 0;
-		PortSetup.Drain = (p->RIOPortp[port]->Config & RIO_WAITDRAIN) ? 1 : 0;
-		PortSetup.Store = p->RIOPortp[port]->Store;
-		PortSetup.Lock = p->RIOPortp[port]->Lock;
-		PortSetup.XpCps = p->RIOPortp[port]->Xprint.XpCps;
-		memcpy(PortSetup.XpOn, p->RIOPortp[port]->Xprint.XpOn, MAX_XP_CTRL_LEN);
-		memcpy(PortSetup.XpOff, p->RIOPortp[port]->Xprint.XpOff, MAX_XP_CTRL_LEN);
-		PortSetup.XpOn[MAX_XP_CTRL_LEN - 1] = '\0';
-		PortSetup.XpOff[MAX_XP_CTRL_LEN - 1] = '\0';
-
-		if (copy_to_user(argp, &PortSetup, sizeof(PortSetup))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_GET_PORT_PARAMS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port params\n");
-		if (copy_from_user(&PortParams, argp, sizeof(struct PortParams))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortParams.Port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortParams.Port]);
-		PortParams.Config = PortP->Config;
-		PortParams.State = PortP->State;
-		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortParams.Port);
-
-		if (copy_to_user(argp, &PortParams, sizeof(struct PortParams))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_GET_PORT_TTY:
-		rio_dprintk(RIO_DEBUG_CTRL, "Get port tty\n");
-		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortTty.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		rio_dprintk(RIO_DEBUG_CTRL, "Port %d\n", PortTty.port);
-		PortP = (p->RIOPortp[PortTty.port]);
-		if (copy_to_user(argp, &PortTty, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_PORT_TTY:
-		if (copy_from_user(&PortTty, argp, sizeof(struct PortTty))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Set port %d tty\n", PortTty.port);
-		if (PortTty.port >= (ushort) RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortTty.port]);
-		RIOParam(PortP, RIOC_CONFIG, PortP->State & RIO_MODEM,
-				OK_TO_SLEEP);
-		return retval;
-
-	case RIO_SET_PORT_PARAMS:
-		rio_dprintk(RIO_DEBUG_CTRL, "Set port params\n");
-		if (copy_from_user(&PortParams, argp, sizeof(PortParams))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (PortParams.Port >= (ushort) RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[PortParams.Port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->Config = PortParams.Config;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_GET_PORT_STATS:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GET_PORT_STATS\n");
-		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[portStats.port]);
-		portStats.gather = PortP->statsGather;
-		portStats.txchars = PortP->txchars;
-		portStats.rxchars = PortP->rxchars;
-		portStats.opens = PortP->opens;
-		portStats.closes = PortP->closes;
-		portStats.ioctls = PortP->ioctls;
-		if (copy_to_user(argp, &portStats, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_RESET_PORT_STATS:
-		port = arg;
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_RESET_PORT_STATS\n");
-		if (port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->txchars = 0;
-		PortP->rxchars = 0;
-		PortP->opens = 0;
-		PortP->closes = 0;
-		PortP->ioctls = 0;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_GATHER_PORT_STATS:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_GATHER_PORT_STATS\n");
-		if (copy_from_user(&portStats, argp, sizeof(struct portStats))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (portStats.port < 0 || portStats.port >= RIO_PORTS) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		PortP = (p->RIOPortp[portStats.port]);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->statsGather = portStats.gather;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_READ_CONFIG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_CONFIG\n");
-		if (copy_to_user(argp, &p->RIOConf, sizeof(struct Conf))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_CONFIG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_CONFIG\n");
-		if (!su) {
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&p->RIOConf, argp, sizeof(struct Conf))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		/*
-		 ** move a few value around
-		 */
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if ((p->RIOHosts[Host].Flags & RUN_STATE) == RC_RUNNING)
-				writew(p->RIOConf.Timer, &p->RIOHosts[Host].ParmMapP->timer);
-		return retval;
-
-	case RIO_START_POLLER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_START_POLLER\n");
-		return -EINVAL;
-
-	case RIO_STOP_POLLER:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STOP_POLLER\n");
-		if (!su) {
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		p->RIOPolling = NOT_POLLING;
-		return retval;
-
-	case RIO_SETDEBUG:
-	case RIO_GETDEBUG:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG/RIO_GETDEBUG\n");
-		if (copy_from_user(&DebugCtrl, argp, sizeof(DebugCtrl))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (DebugCtrl.SysPort == NO_PORT) {
-			if (cmd == RIO_SETDEBUG) {
-				if (!su) {
-					p->RIOError.Error = NOT_SUPER_USER;
-					return -EPERM;
-				}
-				p->rio_debug = DebugCtrl.Debug;
-				p->RIODebugWait = DebugCtrl.Wait;
-				rio_dprintk(RIO_DEBUG_CTRL, "Set global debug to 0x%x set wait to 0x%x\n", p->rio_debug, p->RIODebugWait);
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "Get global debug 0x%x wait 0x%x\n", p->rio_debug, p->RIODebugWait);
-				DebugCtrl.Debug = p->rio_debug;
-				DebugCtrl.Wait = p->RIODebugWait;
-				if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
-					rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
-					p->RIOError.Error = COPYOUT_FAILED;
-					return -EFAULT;
-				}
-			}
-		} else if (DebugCtrl.SysPort >= RIO_PORTS && DebugCtrl.SysPort != NO_PORT) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET/GET DEBUG: bad port number %d\n", DebugCtrl.SysPort);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		} else if (cmd == RIO_SETDEBUG) {
-			if (!su) {
-				p->RIOError.Error = NOT_SUPER_USER;
-				return -EPERM;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			p->RIOPortp[DebugCtrl.SysPort]->Debug = DebugCtrl.Debug;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG 0x%x\n", p->RIOPortp[DebugCtrl.SysPort]->Debug);
-			DebugCtrl.Debug = p->RIOPortp[DebugCtrl.SysPort]->Debug;
-			if (copy_to_user(argp, &DebugCtrl, sizeof(DebugCtrl))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_GETDEBUG: Bad copy to user space\n");
-				p->RIOError.Error = COPYOUT_FAILED;
-				return -EFAULT;
-			}
-		}
-		return retval;
-
-	case RIO_VERSID:
-		/*
-		 ** Enquire about the release and version.
-		 ** We return MAX_VERSION_LEN bytes, being a
-		 ** textual null terminated string.
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID\n");
-		if (copy_to_user(argp, RIOVersid(), sizeof(struct rioVersion))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_VERSID: Bad copy to user space (host=%d)\n", Host);
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_NUM_HOSTS:
-		/*
-		 ** Enquire as to the number of hosts located
-		 ** at init time.
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS\n");
-		if (copy_to_user(argp, &p->RIONumHosts, sizeof(p->RIONumHosts))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_NUM_HOSTS: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_FOAD:
-		/*
-		 ** Kill host. This may not be in the final version...
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD %ld\n", arg);
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_FOAD: Not super user\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		p->RIOHalted = 1;
-		p->RIOSystemUp = 0;
-
-		for (Host = 0; Host < p->RIONumHosts; Host++) {
-			(void) RIOBoardTest(p->RIOHosts[Host].PaddrP, p->RIOHosts[Host].Caddr, p->RIOHosts[Host].Type, p->RIOHosts[Host].Slot);
-			memset(&p->RIOHosts[Host].Flags, 0, ((char *) &p->RIOHosts[Host].____end_marker____) - ((char *) &p->RIOHosts[Host].Flags));
-			p->RIOHosts[Host].Flags = RC_WAITING;
-		}
-		RIOFoadWakeup(p);
-		p->RIONumBootPkts = 0;
-		p->RIOBooting = 0;
-		printk("HEEEEELP!\n");
-
-		for (loop = 0; loop < RIO_PORTS; loop++) {
-			spin_lock_init(&p->RIOPortp[loop]->portSem);
-			p->RIOPortp[loop]->InUse = NOT_INUSE;
-		}
-
-		p->RIOSystemUp = 0;
-		return retval;
-
-	case RIO_DOWNLOAD:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD\n");
-		if (!su) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Not super user\n");
-			p->RIOError.Error = NOT_SUPER_USER;
-			return -EPERM;
-		}
-		if (copy_from_user(&DownLoad, argp, sizeof(DownLoad))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Copied in download code for product code 0x%x\n", DownLoad.ProductCode);
-
-		/*
-		 ** It is important that the product code is an unsigned object!
-		 */
-		if (DownLoad.ProductCode >= MAX_PRODUCT) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_DOWNLOAD: Bad product code %d passed\n", DownLoad.ProductCode);
-			p->RIOError.Error = NO_SUCH_PRODUCT;
-			return -ENXIO;
-		}
-		/*
-		 ** do something!
-		 */
-		retval = (*(RIOBootTable[DownLoad.ProductCode])) (p, &DownLoad);
-		/* <-- Panic */
-		p->RIOHalted = 0;
-		/*
-		 ** and go back, content with a job well completed.
-		 */
-		return retval;
-
-	case RIO_PARMS:
-		{
-			unsigned int host;
-
-			if (copy_from_user(&host, argp, sizeof(host))) {
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
-				p->RIOError.Error = COPYIN_FAILED;
-				return -EFAULT;
-			}
-			/*
-			 ** Fetch the parmmap
-			 */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS\n");
-			if (copy_from_io(argp, p->RIOHosts[host].ParmMapP, sizeof(PARM_MAP))) {
-				p->RIOError.Error = COPYOUT_FAILED;
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_PARMS: Copy out to user space failed\n");
-				return -EFAULT;
-			}
-		}
-		return retval;
-
-	case RIO_HOST_REQ:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ\n");
-		if (copy_from_user(&HostReq, argp, sizeof(HostReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (HostReq.HostNum >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Illegal host number %d\n", HostReq.HostNum);
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostReq.HostNum);
-
-		if (copy_to_user(HostReq.HostP, &p->RIOHosts[HostReq.HostNum], sizeof(struct Host))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_REQ: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_DPRAM:
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for DPRAM\n");
-		if (copy_from_user(&HostDpRam, argp, sizeof(HostDpRam))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (HostDpRam.HostNum >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Illegal host number %d\n", HostDpRam.HostNum);
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for host %d\n", HostDpRam.HostNum);
-
-		if (p->RIOHosts[HostDpRam.HostNum].Type == RIO_PCI) {
-			int off;
-			/* It's hardware like this that really gets on my tits. */
-			static unsigned char copy[sizeof(struct DpRam)];
-			for (off = 0; off < sizeof(struct DpRam); off++)
-				copy[off] = readb(p->RIOHosts[HostDpRam.HostNum].Caddr + off);
-			if (copy_to_user(HostDpRam.DpRamP, copy, sizeof(struct DpRam))) {
-				p->RIOError.Error = COPYOUT_FAILED;
-				rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
-				return -EFAULT;
-			}
-		} else if (copy_from_io(HostDpRam.DpRamP, p->RIOHosts[HostDpRam.HostNum].Caddr, sizeof(struct DpRam))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_DPRAM: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_SET_BUSY:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY\n");
-		if (arg > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SET_BUSY: Bad port number %ld\n", arg);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		p->RIOPortp[arg]->State |= RIO_BUSY;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_HOST_PORT:
-		/*
-		 ** The daemon want port information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT\n");
-		if (copy_from_user(&PortReq, argp, sizeof(PortReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-
-		if (PortReq.SysPort >= RIO_PORTS) {	/* SysPort is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Illegal port number %d\n", PortReq.SysPort);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for port %d\n", PortReq.SysPort);
-		if (copy_to_user(PortReq.PortP, p->RIOPortp[PortReq.SysPort], sizeof(struct Port))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_PORT: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_RUP:
-		/*
-		 ** The daemon want rup information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP\n");
-		if (copy_from_user(&RupReq, argp, sizeof(RupReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Copy in from user space failed\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (RupReq.HostNum >= p->RIONumHosts) {	/* host is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal host number %d\n", RupReq.HostNum);
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		if (RupReq.RupNum >= MAX_RUP + LINKS_PER_UNIT) {	/* eek! */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Illegal rup number %d\n", RupReq.RupNum);
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		HostP = &p->RIOHosts[RupReq.HostNum];
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Host %d not running\n", RupReq.HostNum);
-			p->RIOError.Error = HOST_NOT_RUNNING;
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for rup %d from host %d\n", RupReq.RupNum, RupReq.HostNum);
-
-		if (copy_from_io(RupReq.RupP, HostP->UnixRups[RupReq.RupNum].RupP, sizeof(struct RUP))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_RUP: Bad copy to user space\n");
-			return -EFAULT;
-		}
-		return retval;
-
-	case RIO_HOST_LPB:
-		/*
-		 ** The daemon want lpb information
-		 ** (probably for debug reasons)
-		 */
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB\n");
-		if (copy_from_user(&LpbReq, argp, sizeof(LpbReq))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy from user space\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (LpbReq.Host >= p->RIONumHosts) {	/* host is unsigned */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal host number %d\n", LpbReq.Host);
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-		if (LpbReq.Link >= LINKS_PER_UNIT) {	/* eek! */
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Illegal link number %d\n", LpbReq.Link);
-			p->RIOError.Error = LINK_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		HostP = &p->RIOHosts[LpbReq.Host];
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Host %d not running\n", LpbReq.Host);
-			p->RIOError.Error = HOST_NOT_RUNNING;
-			return -EIO;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Request for lpb %d from host %d\n", LpbReq.Link, LpbReq.Host);
-
-		if (copy_from_io(LpbReq.LpbP, &HostP->LinkStrP[LpbReq.Link], sizeof(struct LPB))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_HOST_LPB: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return retval;
-
-		/*
-		 ** Here 3 IOCTL's that allow us to change the way in which
-		 ** rio logs errors. send them just to syslog or send them
-		 ** to both syslog and console or send them to just the console.
-		 **
-		 ** See RioStrBuf() in util.c for the other half.
-		 */
-	case RIO_SYSLOG_ONLY:
-		p->RIOPrintLogState = PRINT_TO_LOG;	/* Just syslog */
-		return 0;
-
-	case RIO_SYSLOG_CONS:
-		p->RIOPrintLogState = PRINT_TO_LOG_CONS;	/* syslog and console */
-		return 0;
-
-	case RIO_CONS_ONLY:
-		p->RIOPrintLogState = PRINT_TO_CONS;	/* Just console */
-		return 0;
-
-	case RIO_SIGNALS_ON:
-		if (p->RIOSignalProcess) {
-			p->RIOError.Error = SIGNALS_ALREADY_SET;
-			return -EBUSY;
-		}
-		/* FIXME: PID tracking */
-		p->RIOSignalProcess = current->pid;
-		p->RIOPrintDisabled = DONT_PRINT;
-		return retval;
-
-	case RIO_SIGNALS_OFF:
-		if (p->RIOSignalProcess != current->pid) {
-			p->RIOError.Error = NOT_RECEIVING_PROCESS;
-			return -EPERM;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear signal process to zero\n");
-		p->RIOSignalProcess = 0;
-		return retval;
-
-	case RIO_SET_BYTE_MODE:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode &= ~WORD_OPERATION;
-		return retval;
-
-	case RIO_SET_WORD_MODE:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode |= WORD_OPERATION;
-		return retval;
-
-	case RIO_SET_FAST_BUS:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode |= FAST_AT_BUS;
-		return retval;
-
-	case RIO_SET_SLOW_BUS:
-		for (Host = 0; Host < p->RIONumHosts; Host++)
-			if (p->RIOHosts[Host].Type == RIO_AT)
-				p->RIOHosts[Host].Mode &= ~FAST_AT_BUS;
-		return retval;
-
-	case RIO_MAP_B50_TO_50:
-	case RIO_MAP_B50_TO_57600:
-	case RIO_MAP_B110_TO_110:
-	case RIO_MAP_B110_TO_115200:
-		rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping\n");
-		port = arg;
-		if (port < 0 || port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		switch (cmd) {
-		case RIO_MAP_B50_TO_50:
-			p->RIOPortp[port]->Config |= RIO_MAP_50_TO_50;
-			break;
-		case RIO_MAP_B50_TO_57600:
-			p->RIOPortp[port]->Config &= ~RIO_MAP_50_TO_50;
-			break;
-		case RIO_MAP_B110_TO_110:
-			p->RIOPortp[port]->Config |= RIO_MAP_110_TO_110;
-			break;
-		case RIO_MAP_B110_TO_115200:
-			p->RIOPortp[port]->Config &= ~RIO_MAP_110_TO_110;
-			break;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_STREAM_INFO:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_STREAM_INFO\n");
-		return -EINVAL;
-
-	case RIO_SEND_PACKET:
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET\n");
-		if (copy_from_user(&SendPack, argp, sizeof(SendPack))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_SEND_PACKET: Bad copy from user space\n");
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		if (SendPack.PortNum >= 128) {
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -ENXIO;
-		}
-
-		PortP = p->RIOPortp[SendPack.PortNum];
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (!can_add_transmit(&PacketP, PortP)) {
-			p->RIOError.Error = UNIT_IS_IN_USE;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -ENOSPC;
-		}
-
-		for (loop = 0; loop < (ushort) (SendPack.Len & 127); loop++)
-			writeb(SendPack.Data[loop], &PacketP->data[loop]);
-
-		writeb(SendPack.Len, &PacketP->len);
-
-		add_transmit(PortP);
-		/*
-		 ** Count characters transmitted for port statistics reporting
-		 */
-		if (PortP->statsGather)
-			PortP->txchars += (SendPack.Len & 127);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return retval;
-
-	case RIO_NO_MESG:
-		if (su)
-			p->RIONoMessage = 1;
-		return su ? 0 : -EPERM;
-
-	case RIO_MESG:
-		if (su)
-			p->RIONoMessage = 0;
-		return su ? 0 : -EPERM;
-
-	case RIO_WHAT_MESG:
-		if (copy_to_user(argp, &p->RIONoMessage, sizeof(p->RIONoMessage))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_WHAT_MESG: Bad copy to user space\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_MEM_DUMP:
-		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP host %d rup %d addr %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Addr);
-
-		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Host >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort;
-
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (RIOPreemptiveCmd(p, PortP, RIOC_MEMDUMP) == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else
-			PortP->State |= RIO_BUSY;
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(argp, p->RIOMemDump, MEMDUMP_SIZE)) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_MEM_DUMP copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_TICK:
-		if (arg >= p->RIONumHosts)
-			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Set interrupt for host %ld\n", arg);
-		writeb(0xFF, &p->RIOHosts[arg].SetInt);
-		return 0;
-
-	case RIO_TOCK:
-		if (arg >= p->RIONumHosts)
-			return -EINVAL;
-		rio_dprintk(RIO_DEBUG_CTRL, "Clear interrupt for host %ld\n", arg);
-		writeb(0xFF, &p->RIOHosts[arg].ResetInt);
-		return 0;
-
-	case RIO_READ_CHECK:
-		/* Check reads for pkts with data[0] the same */
-		p->RIOReadCheck = !p->RIOReadCheck;
-		if (copy_to_user(argp, &p->RIOReadCheck, sizeof(unsigned int))) {
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-
-	case RIO_READ_REGISTER:
-		if (copy_from_user(&SubCmd, argp, sizeof(struct SubCmdStruct))) {
-			p->RIOError.Error = COPYIN_FAILED;
-			return -EFAULT;
-		}
-		rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER host %d rup %d port %d reg %x\n", SubCmd.Host, SubCmd.Rup, SubCmd.Port, SubCmd.Addr);
-
-		if (SubCmd.Port > 511) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Baud rate mapping: Bad port number %d\n", SubCmd.Port);
-			p->RIOError.Error = PORT_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Rup >= MAX_RUP + LINKS_PER_UNIT) {
-			p->RIOError.Error = RUP_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		if (SubCmd.Host >= p->RIONumHosts) {
-			p->RIOError.Error = HOST_NUMBER_OUT_OF_RANGE;
-			return -EINVAL;
-		}
-
-		port = p->RIOHosts[SubCmd.Host].UnixRups[SubCmd.Rup].BaseSysPort + SubCmd.Port;
-		PortP = p->RIOPortp[port];
-
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		if (RIOPreemptiveCmd(p, PortP, RIOC_READ_REGISTER) ==
-				RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER failed\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return -EBUSY;
-		} else
-			PortP->State |= RIO_BUSY;
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (copy_to_user(argp, &p->CdRegister, sizeof(unsigned int))) {
-			rio_dprintk(RIO_DEBUG_CTRL, "RIO_READ_REGISTER copy failed\n");
-			p->RIOError.Error = COPYOUT_FAILED;
-			return -EFAULT;
-		}
-		return 0;
-		/*
-		 ** rio_make_dev: given port number (0-511) ORed with port type
-		 ** (RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT) return dev_t
-		 ** value to pass to mknod to create the correct device node.
-		 */
-	case RIO_MAKE_DEV:
-		{
-			unsigned int port = arg & RIO_MODEM_MASK;
-			unsigned int ret;
-
-			switch (arg & RIO_DEV_MASK) {
-			case RIO_DEV_DIRECT:
-				ret = drv_makedev(MAJOR(dev), port);
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev direct 0x%x is 0x%x\n", port, ret);
-				return ret;
-			case RIO_DEV_MODEM:
-				ret = drv_makedev(MAJOR(dev), (port | RIO_MODEM_BIT));
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev modem 0x%x is 0x%x\n", port, ret);
-				return ret;
-			case RIO_DEV_XPRINT:
-				ret = drv_makedev(MAJOR(dev), port);
-				rio_dprintk(RIO_DEBUG_CTRL, "Makedev printer 0x%x is 0x%x\n", port, ret);
-				return ret;
-			}
-			rio_dprintk(RIO_DEBUG_CTRL, "MAKE Device is called\n");
-			return -EINVAL;
-		}
-		/*
-		 ** rio_minor: given a dev_t from a stat() call, return
-		 ** the port number (0-511) ORed with the port type
-		 ** ( RIO_DEV_DIRECT, RIO_DEV_MODEM, RIO_DEV_XPRINT )
-		 */
-	case RIO_MINOR:
-		{
-			dev_t dv;
-			int mino;
-			unsigned long ret;
-
-			dv = (dev_t) (arg);
-			mino = RIO_UNMODEM(dv);
-
-			if (RIO_ISMODEM(dv)) {
-				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: modem %d\n", dv, mino);
-				ret = mino | RIO_DEV_MODEM;
-			} else {
-				rio_dprintk(RIO_DEBUG_CTRL, "Minor for device 0x%x: direct %d\n", dv, mino);
-				ret = mino | RIO_DEV_DIRECT;
-			}
-			return ret;
-		}
-	}
-	rio_dprintk(RIO_DEBUG_CTRL, "INVALID DAEMON IOCTL 0x%x\n", cmd);
-	p->RIOError.Error = IOCTL_COMMAND_UNKNOWN;
-
-	func_exit();
-	return -EINVAL;
-}
-
-/*
-** Pre-emptive commands go on RUPs and are only one byte long.
-*/
-int RIOPreemptiveCmd(struct rio_info *p, struct Port *PortP, u8 Cmd)
-{
-	struct CmdBlk *CmdBlkP;
-	struct PktCmd_M *PktCmdP;
-	int Ret;
-	ushort rup;
-	int port;
-
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Preemptive command to deleted RTA ignored\n");
-		return RIO_FAIL;
-	}
-
-	if ((PortP->InUse == (typeof(PortP->InUse))-1) ||
-			!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_CTRL, "Cannot allocate command block "
-			"for command %d on port %d\n", Cmd, PortP->PortNum);
-		return RIO_FAIL;
-	}
-
-	rio_dprintk(RIO_DEBUG_CTRL, "Command blk %p - InUse now %d\n",
-			CmdBlkP, PortP->InUse);
-
-	PktCmdP = (struct PktCmd_M *)&CmdBlkP->Packet.data[0];
-
-	CmdBlkP->Packet.src_unit = 0;
-	if (PortP->SecondBlock)
-		rup = PortP->ID2;
-	else
-		rup = PortP->RupNum;
-	CmdBlkP->Packet.dest_unit = rup;
-	CmdBlkP->Packet.src_port = COMMAND_RUP;
-	CmdBlkP->Packet.dest_port = COMMAND_RUP;
-	CmdBlkP->Packet.len = PKT_CMD_BIT | 2;
-	CmdBlkP->PostFuncP = RIOUnUse;
-	CmdBlkP->PostArg = (unsigned long) PortP;
-	PktCmdP->Command = Cmd;
-	port = PortP->HostPort % (ushort) PORTS_PER_RTA;
-	/*
-	 ** Index ports 8-15 for 2nd block of 16 port RTA.
-	 */
-	if (PortP->SecondBlock)
-		port += (ushort) PORTS_PER_RTA;
-	PktCmdP->PhbNum = port;
-
-	switch (Cmd) {
-	case RIOC_MEMDUMP:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MEMDUMP command blk %p "
-				"(addr 0x%x)\n", CmdBlkP, (int) SubCmd.Addr);
-		PktCmdP->SubCommand = RIOC_MEMDUMP;
-		PktCmdP->SubAddr = SubCmd.Addr;
-		break;
-	case RIOC_FCLOSE:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue FCLOSE command blk %p\n",
-				CmdBlkP);
-		break;
-	case RIOC_READ_REGISTER:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue READ_REGISTER (0x%x) "
-				"command blk %p\n", (int) SubCmd.Addr, CmdBlkP);
-		PktCmdP->SubCommand = RIOC_READ_REGISTER;
-		PktCmdP->SubAddr = SubCmd.Addr;
-		break;
-	case RIOC_RESUME:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RESUME command blk %p\n",
-				CmdBlkP);
-		break;
-	case RIOC_RFLUSH:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue RFLUSH command blk %p\n",
-				CmdBlkP);
-		CmdBlkP->PostFuncP = RIORFlushEnable;
-		break;
-	case RIOC_SUSPEND:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue SUSPEND command blk %p\n",
-				CmdBlkP);
-		break;
-
-	case RIOC_MGET:
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MGET command blk %p\n",
-				CmdBlkP);
-		break;
-
-	case RIOC_MSET:
-	case RIOC_MBIC:
-	case RIOC_MBIS:
-		CmdBlkP->Packet.data[4] = (char) PortP->ModemLines;
-		rio_dprintk(RIO_DEBUG_CTRL, "Queue MSET/MBIC/MBIS command "
-				"blk %p\n", CmdBlkP);
-		break;
-
-	case RIOC_WFLUSH:
-		/*
-		 ** If we have queued up the maximum number of Write flushes
-		 ** allowed then we should not bother sending any more to the
-		 ** RTA.
-		 */
-		if (PortP->WflushFlag == (typeof(PortP->WflushFlag))-1) {
-			rio_dprintk(RIO_DEBUG_CTRL, "Trashed WFLUSH, "
-					"WflushFlag about to wrap!");
-			RIOFreeCmdBlk(CmdBlkP);
-			return (RIO_FAIL);
-		} else {
-			rio_dprintk(RIO_DEBUG_CTRL, "Queue WFLUSH command "
-					"blk %p\n", CmdBlkP);
-			CmdBlkP->PostFuncP = RIOWFlushMark;
-		}
-		break;
-	}
-
-	PortP->InUse++;
-
-	Ret = RIOQueueCmdBlk(PortP->HostP, rup, CmdBlkP);
-
-	return Ret;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/riodrvr.h linux-libre-2.6.39-gnu/drivers/char/rio/riodrvr.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/riodrvr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/riodrvr.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,138 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: riodrvr.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 09:22:46
-**	Retrieved	: 11/6/98 09:22:46
-**
-**  ident @(#)riodrvr.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __riodrvr_h
-#define __riodrvr_h
-
-#include <asm/param.h>		/* for HZ */
-
-#define MEMDUMP_SIZE	32
-#define	MOD_DISABLE	(RIO_NOREAD|RIO_NOWRITE|RIO_NOXPRINT)
-
-
-struct rio_info {
-	int mode;		/* Intr or polled, word/byte */
-	spinlock_t RIOIntrSem;	/* Interrupt thread sem */
-	int current_chan;	/* current channel */
-	int RIOFailed;		/* Not initialised ? */
-	int RIOInstallAttempts;	/* no. of rio-install() calls */
-	int RIOLastPCISearch;	/* status of last search */
-	int RIONumHosts;	/* Number of RIO Hosts */
-	struct Host *RIOHosts;	/* RIO Host values */
-	struct Port **RIOPortp;	/* RIO port values */
-/*
-** 02.03.1999 ARG - ESIL 0820 fix
-** We no longer use RIOBootMode
-**
-	int			RIOBootMode;		* RIO boot mode *
-**
-*/
-	int RIOPrintDisabled;	/* RIO printing disabled ? */
-	int RIOPrintLogState;	/* RIO printing state ? */
-	int RIOPolling;		/* Polling ? */
-/*
-** 09.12.1998 ARG - ESIL 0776 part fix
-** The 'RIO_QUICK_CHECK' ioctl was using RIOHalted.
-** The fix for this ESIL introduces another member (RIORtaDisCons) here to be
-** updated in RIOConCon() - to keep track of RTA connections/disconnections.
-** 'RIO_QUICK_CHECK' now returns the value of RIORtaDisCons.
-*/
-	int RIOHalted;		/* halted ? */
-	int RIORtaDisCons;	/* RTA connections/disconnections */
-	unsigned int RIOReadCheck;	/* Rio read check */
-	unsigned int RIONoMessage;	/* To display message or not */
-	unsigned int RIONumBootPkts;	/* how many packets for an RTA */
-	unsigned int RIOBootCount;	/* size of RTA code */
-	unsigned int RIOBooting;	/* count of outstanding boots */
-	unsigned int RIOSystemUp;	/* Booted ?? */
-	unsigned int RIOCounting;	/* for counting interrupts */
-	unsigned int RIOIntCount;	/* # of intr since last check */
-	unsigned int RIOTxCount;	/* number of xmit intrs  */
-	unsigned int RIORxCount;	/* number of rx intrs */
-	unsigned int RIORupCount;	/* number of rup intrs */
-	int RIXTimer;
-	int RIOBufferSize;	/* Buffersize */
-	int RIOBufferMask;	/* Buffersize */
-
-	int RIOFirstMajor;	/* First host card's major no */
-
-	unsigned int RIOLastPortsMapped;	/* highest port number known */
-	unsigned int RIOFirstPortsMapped;	/* lowest port number known */
-
-	unsigned int RIOLastPortsBooted;	/* highest port number running */
-	unsigned int RIOFirstPortsBooted;	/* lowest port number running */
-
-	unsigned int RIOLastPortsOpened;	/* highest port number running */
-	unsigned int RIOFirstPortsOpened;	/* lowest port number running */
-
-	/* Flag to say that the topology information has been changed. */
-	unsigned int RIOQuickCheck;
-	unsigned int CdRegister;	/* ??? */
-	int RIOSignalProcess;	/* Signalling process */
-	int rio_debug;		/* To debug ... */
-	int RIODebugWait;	/* For what ??? */
-	int tpri;		/* Thread prio */
-	int tid;		/* Thread id */
-	unsigned int _RIO_Polled;	/* Counter for polling */
-	unsigned int _RIO_Interrupted;	/* Counter for interrupt */
-	int intr_tid;		/* iointset return value */
-	int TxEnSem;		/* TxEnable Semaphore */
-
-
-	struct Error RIOError;	/* to Identify what went wrong */
-	struct Conf RIOConf;	/* Configuration ??? */
-	struct ttystatics channel[RIO_PORTS];	/* channel information */
-	char RIOBootPackets[1 + (SIXTY_FOUR_K / RTA_BOOT_DATA_SIZE)]
-	    [RTA_BOOT_DATA_SIZE];
-	struct Map RIOConnectTable[TOTAL_MAP_ENTRIES];
-	struct Map RIOSavedTable[TOTAL_MAP_ENTRIES];
-
-	/* RTA to host binding table for master/slave operation */
-	unsigned long RIOBindTab[MAX_RTA_BINDINGS];
-	/* RTA memory dump variable */
-	unsigned char RIOMemDump[MEMDUMP_SIZE];
-	struct ModuleInfo RIOModuleTypes[MAX_MODULE_TYPES];
-
-};
-
-
-#ifdef linux
-#define debug(x)        printk x
-#else
-#define debug(x)	kkprintf x
-#endif
-
-
-
-#define RIO_RESET_INT	0x7d80
-
-#endif				/* __riodrvr.h */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rio.h linux-libre-2.6.39-gnu/drivers/char/rio/rio.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/rio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rio.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,208 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 1998 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rio.h
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)rio.h	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rio_rio_h__
-#define	__rio_rio_h__
-
-/*
-**	Maximum numbers of things
-*/
-#define	RIO_SLOTS	4	/* number of configuration slots */
-#define	RIO_HOSTS	4	/* number of hosts that can be found */
-#define	PORTS_PER_HOST	128	/* number of ports per host */
-#define	LINKS_PER_UNIT	4	/* number of links from a host */
-#define	RIO_PORTS	(PORTS_PER_HOST * RIO_HOSTS)	/* max. no. of ports */
-#define	RTAS_PER_HOST	(MAX_RUP)	/* number of RTAs per host */
-#define	PORTS_PER_RTA	(PORTS_PER_HOST/RTAS_PER_HOST)	/* ports on a rta */
-#define	PORTS_PER_MODULE 4	/* number of ports on a plug-in module */
-				/* number of modules on an RTA */
-#define	MODULES_PER_RTA	 (PORTS_PER_RTA/PORTS_PER_MODULE)
-#define MAX_PRODUCT	16	/* numbr of different product codes */
-#define MAX_MODULE_TYPES 16	/* number of different types of module */
-
-#define RIO_CONTROL_DEV	128	/* minor number of host/control device */
-#define RIO_INVALID_MAJOR 0	/* test first host card's major no for validity */
-
-/*
-** number of RTAs that can be bound to a master
-*/
-#define MAX_RTA_BINDINGS (MAX_RUP * RIO_HOSTS)
-
-/*
-**	Unit types
-*/
-#define PC_RTA16	0x90000000
-#define PC_RTA8		0xe0000000
-#define TYPE_HOST	0
-#define TYPE_RTA8	1
-#define TYPE_RTA16	2
-
-/*
-**	Flag values returned by functions
-*/
-
-#define	RIO_FAIL	-1
-
-/*
-** SysPort value for something that hasn't any ports
-*/
-#define	NO_PORT	0xFFFFFFFF
-
-/*
-** Unit ID Of all hosts
-*/
-#define	HOST_ID	0
-
-/*
-** Break bytes into nybles
-*/
-#define	LONYBLE(X)	((X) & 0xF)
-#define	HINYBLE(X)	(((X)>>4) & 0xF)
-
-/*
-** Flag values passed into some functions
-*/
-#define	DONT_SLEEP	0
-#define	OK_TO_SLEEP	1
-
-#define	DONT_PRINT	1
-#define	DO_PRINT	0
-
-#define PRINT_TO_LOG_CONS	0
-#define PRINT_TO_CONS	1
-#define PRINT_TO_LOG	2
-
-/*
-** Timeout has trouble with times of less than 3 ticks...
-*/
-#define	MIN_TIMEOUT	3
-
-/*
-**	Generally useful constants
-*/
-
-#define	HUNDRED_MS		((HZ/10)?(HZ/10):1)
-#define	ONE_MEG			0x100000
-#define	SIXTY_FOUR_K		0x10000
-
-#define	RIO_AT_MEM_SIZE		SIXTY_FOUR_K
-#define	RIO_EISA_MEM_SIZE	SIXTY_FOUR_K
-#define	RIO_MCA_MEM_SIZE	SIXTY_FOUR_K
-
-#define	COOK_WELL		0
-#define	COOK_MEDIUM		1
-#define	COOK_RAW		2
-
-/*
-**	Pointer manipulation stuff
-**	RIO_PTR takes hostp->Caddr and the offset into the DP RAM area
-**	and produces a UNIX caddr_t (pointer) to the object
-**	RIO_OBJ takes hostp->Caddr and a UNIX pointer to an object and
-**	returns the offset into the DP RAM area.
-*/
-#define	RIO_PTR(C,O) (((unsigned char __iomem *)(C))+(0xFFFF&(O)))
-#define	RIO_OFF(C,O) ((unsigned char __iomem *)(O)-(unsigned char __iomem *)(C))
-
-/*
-**	How to convert from various different device number formats:
-**	DEV is a dev number, as passed to open, close etc - NOT a minor
-**	number!
-**/
-
-#define	RIO_MODEM_MASK		0x1FF
-#define	RIO_MODEM_BIT		0x200
-#define	RIO_UNMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_MASK)
-#define	RIO_ISMODEM(DEV)	(MINOR(DEV) & RIO_MODEM_BIT)
-#define RIO_PORT(DEV,FIRST_MAJ)	( (MAJOR(DEV) - FIRST_MAJ) * PORTS_PER_HOST) \
-					+ MINOR(DEV)
-#define CSUM(pkt_ptr)  (((u16 *)(pkt_ptr))[0] + ((u16 *)(pkt_ptr))[1] + \
-			((u16 *)(pkt_ptr))[2] + ((u16 *)(pkt_ptr))[3] + \
-			((u16 *)(pkt_ptr))[4] + ((u16 *)(pkt_ptr))[5] + \
-			((u16 *)(pkt_ptr))[6] + ((u16 *)(pkt_ptr))[7] + \
-			((u16 *)(pkt_ptr))[8] + ((u16 *)(pkt_ptr))[9] )
-
-#define	RIO_LINK_ENABLE	0x80FF	/* FF is a hack, mainly for Mips, to        */
-			       /* prevent a really stupid race condition.  */
-
-#define	NOT_INITIALISED	0
-#define	INITIALISED	1
-
-#define	NOT_POLLING	0
-#define	POLLING		1
-
-#define	NOT_CHANGED	0
-#define	CHANGED		1
-
-#define	NOT_INUSE	0
-
-#define	DISCONNECT	0
-#define	CONNECT		1
-
-/* ------ Control Codes ------ */
-
-#define	CONTROL		'^'
-#define IFOAD		( CONTROL + 1 )
-#define	IDENTIFY	( CONTROL + 2 )
-#define	ZOMBIE		( CONTROL + 3 )
-#define	UFOAD		( CONTROL + 4 )
-#define IWAIT		( CONTROL + 5 )
-
-#define	IFOAD_MAGIC	0xF0AD	/* of course */
-#define	ZOMBIE_MAGIC	(~0xDEAD)	/* not dead -> zombie */
-#define	UFOAD_MAGIC	0xD1E	/* kill-your-neighbour */
-#define	IWAIT_MAGIC	0xB1DE	/* Bide your time */
-
-/* ------ Error Codes ------ */
-
-#define E_NO_ERROR                       ((ushort) 0)
-
-/* ------ Free Lists ------ */
-
-struct rio_free_list {
-	u16 next;
-	u16 prev;
-};
-
-/* NULL for card side linked lists */
-#define	TPNULL	((ushort)(0x8000))
-/* We can add another packet to a transmit queue if the packet pointer pointed
- * to by the TxAdd pointer has PKT_IN_USE clear in its address. */
-#define PKT_IN_USE    0x1
-
-/* ------ Topology ------ */
-
-struct Top {
-	u8 Unit;
-	u8 Link;
-};
-
-#endif				/* __rio_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioinfo.h linux-libre-2.6.39-gnu/drivers/char/rio/rioinfo.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioinfo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioinfo.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,92 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioinfo.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 14:07:49
-**	Retrieved	: 11/6/98 14:07:50
-**
-**  ident @(#)rioinfo.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rioinfo_h
-#define __rioinfo_h
-
-/*
-** Host card data structure
-*/
-struct RioHostInfo {
-	long location;		/* RIO Card Base I/O address */
-	long vector;		/* RIO Card IRQ vector */
-	int bus;		/* ISA/EISA/MCA/PCI */
-	int mode;		/* pointer to host mode - INTERRUPT / POLLED */
-	struct old_sgttyb
-	*Sg;			/* pointer to default term characteristics */
-};
-
-
-/* Mode in rio device info */
-#define INTERRUPTED_MODE	0x01	/* Interrupt is generated */
-#define POLLED_MODE		0x02	/* No interrupt */
-#define AUTO_MODE		0x03	/* Auto mode */
-
-#define WORD_ACCESS_MODE	0x10	/* Word Access Mode */
-#define BYTE_ACCESS_MODE	0x20	/* Byte Access Mode */
-
-
-/* Bus type that RIO supports */
-#define ISA_BUS			0x01	/* The card is ISA */
-#define EISA_BUS		0x02	/* The card is EISA */
-#define MCA_BUS			0x04	/* The card is MCA */
-#define PCI_BUS			0x08	/* The card is PCI */
-
-/*
-** 11.11.1998 ARG - ESIL ???? part fix
-** Moved definition for 'CHAN' here from rioinfo.c (it is now
-** called 'DEF_TERM_CHARACTERISTICS').
-*/
-
-#define DEF_TERM_CHARACTERISTICS \
-{ \
-	B19200, B19200,				/* input and output speed */ \
-	'H' - '@',				/* erase char */ \
-	-1,					/* 2nd erase char */ \
-	'U' - '@',				/* kill char */ \
-	ECHO | CRMOD,				/* mode */ \
-	'C' - '@',				/* interrupt character */ \
-	'\\' - '@',				/* quit char */ \
-	'Q' - '@',				/* start char */ \
-	'S' - '@',				/* stop char */ \
-	'D' - '@',				/* EOF */ \
-	-1,					/* brk */ \
-	(LCRTBS | LCRTERA | LCRTKIL | LCTLECH),	/* local mode word */ \
-	'Z' - '@',				/* process stop */ \
-	'Y' - '@',				/* delayed stop */ \
-	'R' - '@',				/* reprint line */ \
-	'O' - '@',				/* flush output */ \
-	'W' - '@',				/* word erase */ \
-	'V' - '@'				/* literal next char */ \
-}
-
-#endif				/* __rioinfo_h */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioinit.c linux-libre-2.6.39-gnu/drivers/char/rio/rioinit.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioinit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioinit.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,421 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioinit.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:43
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)rioinit.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/delay.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "rio_linux.h"
-
-int RIOPCIinit(struct rio_info *p, int Mode);
-
-static int RIOScrub(int, u8 __iomem *, int);
-
-
-/**
-** RIOAssignAT :
-**
-** Fill out the fields in the p->RIOHosts structure now we know we know
-** we have a board present.
-**
-** bits < 0 indicates 8 bit operation requested,
-** bits > 0 indicates 16 bit operation.
-*/
-
-int RIOAssignAT(struct rio_info *p, int	Base, void __iomem *virtAddr, int mode)
-{
-	int		bits;
-	struct DpRam __iomem *cardp = (struct DpRam __iomem *)virtAddr;
-
-	if ((Base < ONE_MEG) || (mode & BYTE_ACCESS_MODE))
-		bits = BYTE_OPERATION;
-	else
-		bits = WORD_OPERATION;
-
-	/*
-	** Board has passed its scrub test. Fill in all the
-	** transient stuff.
-	*/
-	p->RIOHosts[p->RIONumHosts].Caddr	= virtAddr;
-	p->RIOHosts[p->RIONumHosts].CardP	= virtAddr;
-
-	/*
-	** Revision 01 AT host cards don't support WORD operations,
-	*/
-	if (readb(&cardp->DpRevision) == 01)
-		bits = BYTE_OPERATION;
-
-	p->RIOHosts[p->RIONumHosts].Type = RIO_AT;
-	p->RIOHosts[p->RIONumHosts].Copy = rio_copy_to_card;
-											/* set this later */
-	p->RIOHosts[p->RIONumHosts].Slot = -1;
-	p->RIOHosts[p->RIONumHosts].Mode = SLOW_LINKS | SLOW_AT_BUS | bits;
-	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE ,
-		&p->RIOHosts[p->RIONumHosts].Control);
-	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-	writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | p->RIOHosts[p->RIONumHosts].Mode | INTERRUPT_DISABLE,
-		&p->RIOHosts[p->RIONumHosts].Control);
-	writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-	p->RIOHosts[p->RIONumHosts].UniqueNum =
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[0])&0xFF)<<0)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[1])&0xFF)<<8)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[2])&0xFF)<<16)|
-		((readb(&p->RIOHosts[p->RIONumHosts].Unique[3])&0xFF)<<24);
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Uniquenum 0x%x\n",p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-	p->RIONumHosts++;
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Tests Passed at 0x%x\n", Base);
-	return(1);
-}
-
-static	u8	val[] = {
-#ifdef VERY_LONG_TEST
-	  0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80,
-	  0xa5, 0xff, 0x5a, 0x00, 0xff, 0xc9, 0x36, 
-#endif
-	  0xff, 0x00, 0x00 };
-
-#define	TEST_END sizeof(val)
-
-/*
-** RAM test a board. 
-** Nothing too complicated, just enough to check it out.
-*/
-int RIOBoardTest(unsigned long paddr, void __iomem *caddr, unsigned char type, int slot)
-{
-	struct DpRam __iomem *DpRam = caddr;
-	void __iomem *ram[4];
-	int  size[4];
-	int  op, bank;
-	int  nbanks;
-
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Reset host type=%d, DpRam=%p, slot=%d\n",
-			type, DpRam, slot);
-
-	RIOHostReset(type, DpRam, slot);
-
-	/*
-	** Scrub the memory. This comes in several banks:
-	** DPsram1	- 7000h bytes
-	** DPsram2	- 200h  bytes
-	** DPsram3	- 7000h bytes
-	** scratch	- 1000h bytes
-	*/
-
-	rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Setup ram/size arrays\n");
-
-	size[0] = DP_SRAM1_SIZE;
-	size[1] = DP_SRAM2_SIZE;
-	size[2] = DP_SRAM3_SIZE;
-	size[3] = DP_SCRATCH_SIZE;
-
-	ram[0] = DpRam->DpSram1;
-	ram[1] = DpRam->DpSram2;
-	ram[2] = DpRam->DpSram3;
-	nbanks = (type == RIO_PCI) ? 3 : 4;
-	if (nbanks == 4)
-		ram[3] = DpRam->DpScratch;
-
-
-	if (nbanks == 3) {
-		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Memory: %p(0x%x), %p(0x%x), %p(0x%x)\n",
-				ram[0], size[0], ram[1], size[1], ram[2], size[2]);
-	} else {
-		rio_dprintk (RIO_DEBUG_INIT, "RIO-init: %p(0x%x), %p(0x%x), %p(0x%x), %p(0x%x)\n",
-				ram[0], size[0], ram[1], size[1], ram[2], size[2], ram[3], size[3]);
-	}
-
-	/*
-	** This scrub operation will test for crosstalk between
-	** banks. TEST_END is a magic number, and relates to the offset
-	** within the 'val' array used by Scrub.
-	*/
-	for (op=0; op<TEST_END; op++) {
-		for (bank=0; bank<nbanks; bank++) {
-			if (RIOScrub(op, ram[bank], size[bank]) == RIO_FAIL) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: RIOScrub band %d, op %d failed\n", 
-							bank, op);
-				return RIO_FAIL;
-			}
-		}
-	}
-
-	rio_dprintk (RIO_DEBUG_INIT, "Test completed\n");
-	return 0;
-}
-
-
-/*
-** Scrub an area of RAM.
-** Define PRETEST and POSTTEST for a more thorough checking of the
-** state of the memory.
-** Call with op set to an index into the above 'val' array to determine
-** which value will be written into memory.
-** Call with op set to zero means that the RAM will not be read and checked
-** before it is written.
-** Call with op not zero and the RAM will be read and compared with val[op-1]
-** to check that the data from the previous phase was retained.
-*/
-
-static int RIOScrub(int op, u8 __iomem *ram, int size)
-{
-	int off;
-	unsigned char	oldbyte;
-	unsigned char	newbyte;
-	unsigned char	invbyte;
-	unsigned short	oldword;
-	unsigned short	newword;
-	unsigned short	invword;
-	unsigned short	swapword;
-
-	if (op) {
-		oldbyte = val[op-1];
-		oldword = oldbyte | (oldbyte<<8);
-	} else
-	  oldbyte = oldword = 0; /* Tell the compiler we've initilalized them. */
-	newbyte = val[op];
-	newword = newbyte | (newbyte<<8);
-	invbyte = ~newbyte;
-	invword = invbyte | (invbyte<<8);
-
-	/*
-	** Check that the RAM contains the value that should have been left there
-	** by the previous test (not applicable for pass zero)
-	*/
-	if (op) {
-		for (off=0; off<size; off++) {
-			if (readb(ram + off) != oldbyte) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 1: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
-				return RIO_FAIL;
-			}
-		}
-		for (off=0; off<size; off+=2) {
-			if (readw(ram + off) != oldword) {
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: WORD at offset 0x%x should have been=%x, was=%x\n",off,oldword, readw(ram + off));
-				rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Pre Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
-				return RIO_FAIL;
-			}
-		}
-	}
-
-	/*
-	** Now write the INVERSE of the test data into every location, using
-	** BYTE write operations, first checking before each byte is written
-	** that the location contains the old value still, and checking after
-	** the write that the location contains the data specified - this is
-	** the BYTE read/write test.
-	*/
-	for (off=0; off<size; off++) {
-		if (op && (readb(ram + off) != oldbyte)) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Pre Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, oldbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-		writeb(invbyte, ram + off);
-		if (readb(ram + off) != invbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Byte Inv Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, invbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** now, use WORD operations to write the test value into every location,
-	** check as before that the location contains the previous test value
-	** before overwriting, and that it contains the data value written
-	** afterwards.
-	** This is the WORD operation test.
-	*/
-	for (off=0; off<size; off+=2) {
-		if (readw(ram + off) != invword) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: WORD at offset 0x%x should have been=%x, was=%x\n", off, invword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Word Inv Check: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram+off+1));
-			return RIO_FAIL;
-		}
-
-		writew(newword, ram + off);
-		if ( readw(ram + off) != newword ) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** now run through the block of memory again, first in byte mode
-	** then in word mode, and check that all the locations contain the
-	** required test data.
-	*/
-	for (off=0; off<size; off++) {
-		if (readb(ram + off) != newbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Byte Check: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-	}
-
-	for (off=0; off<size; off+=2) {
-		if (readw(ram + off) != newword ) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: WORD at offset 0x%x should have been=%x, was=%x\n", off, newword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: Post Word Check 2: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-	}
-
-	/*
-	** time to check out byte swapping errors
-	*/
-	swapword = invbyte | (newbyte << 8);
-
-	for (off=0; off<size; off+=2) {
-		writeb(invbyte, &ram[off]);
-		writeb(newbyte, &ram[off+1]);
-	}
-
-	for ( off=0; off<size; off+=2 ) {
-		if (readw(ram + off) != swapword) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: WORD at offset 0x%x should have been=%x, was=%x\n", off, swapword, readw(ram + off));
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 1: BYTE at offset 0x%x is %x BYTE at offset 0x%x is %x\n", off, readb(ram + off), off+1, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-		writew(~swapword, ram + off);
-	}
-
-	for (off=0; off<size; off+=2) {
-		if (readb(ram + off) != newbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off, newbyte, readb(ram + off));
-			return RIO_FAIL;
-		}
-		if (readb(ram + off + 1) != invbyte) {
-			rio_dprintk (RIO_DEBUG_INIT, "RIO-init: SwapWord Check 2: BYTE at offset 0x%x should have been=%x, was=%x\n", off+1, invbyte, readb(ram + off + 1));
-			return RIO_FAIL;
-		}
-		writew(newword, ram + off);
-	}
-	return 0;
-}
-
-
-int RIODefaultName(struct rio_info *p, struct Host *HostP, unsigned int	UnitId)
-{
-	memcpy(HostP->Mapping[UnitId].Name, "UNKNOWN RTA X-XX", 17);
-	HostP->Mapping[UnitId].Name[12]='1'+(HostP-p->RIOHosts);
-	if ((UnitId+1) > 9) {
-		HostP->Mapping[UnitId].Name[14]='0'+((UnitId+1)/10);
-		HostP->Mapping[UnitId].Name[15]='0'+((UnitId+1)%10);
-	}
-	else {
-		HostP->Mapping[UnitId].Name[14]='1'+UnitId;
-		HostP->Mapping[UnitId].Name[15]=0;
-	}
-	return 0;
-}
-
-#define RIO_RELEASE	"Linux"
-#define RELEASE_ID	"1.0"
-
-static struct rioVersion	stVersion;
-
-struct rioVersion *RIOVersid(void)
-{
-    strlcpy(stVersion.version, "RIO driver for linux V1.0",
-	    sizeof(stVersion.version));
-    strlcpy(stVersion.buildDate, __DATE__,
-	    sizeof(stVersion.buildDate));
-
-    return &stVersion;
-}
-
-void RIOHostReset(unsigned int Type, struct DpRam __iomem *DpRamP, unsigned int Slot)
-{
-	/*
-	** Reset the Tpu
-	*/
-	rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: type 0x%x", Type);
-	switch ( Type ) {
-	case RIO_AT:
-		rio_dprintk (RIO_DEBUG_INIT, " (RIO_AT)\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE | BYTE_OPERATION |
-			SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(3);
-			rio_dprintk (RIO_DEBUG_INIT,  "RIOHostReset: Don't know if it worked. Try reset again\n");
-		writeb(BOOT_FROM_RAM | EXTERNAL_BUS_OFF | INTERRUPT_DISABLE |
-			BYTE_OPERATION | SLOW_LINKS | SLOW_AT_BUS, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(3);
-		break;
-	case RIO_PCI:
-		rio_dprintk (RIO_DEBUG_INIT, " (RIO_PCI)\n");
-		writeb(RIO_PCI_BOOT_FROM_RAM, &DpRamP->DpControl);
-		writeb(0xFF, &DpRamP->DpResetInt);
-		writeb(0xFF, &DpRamP->DpResetTpu);
-		udelay(100);
-		break;
-	default:
-		rio_dprintk (RIO_DEBUG_INIT, " (UNKNOWN)\n");
-		break;
-	}
-	return;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/riointr.c linux-libre-2.6.39-gnu/drivers/char/rio/riointr.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/riointr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/riointr.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,645 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: riointr.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:44
-**	Retrieved	: 11/6/98 10:33:49
-**
-**  ident @(#)riointr.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-#include <linux/delay.h>
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-
-
-static void RIOReceive(struct rio_info *, struct Port *);
-
-
-static char *firstchars(char *p, int nch)
-{
-	static char buf[2][128];
-	static int t = 0;
-	t = !t;
-	memcpy(buf[t], p, nch);
-	buf[t][nch] = 0;
-	return buf[t];
-}
-
-
-#define	INCR( P, I )	((P) = (((P)+(I)) & p->RIOBufferMask))
-/* Enable and start the transmission of packets */
-void RIOTxEnable(char *en)
-{
-	struct Port *PortP;
-	struct rio_info *p;
-	struct tty_struct *tty;
-	int c;
-	struct PKT __iomem *PacketP;
-	unsigned long flags;
-
-	PortP = (struct Port *) en;
-	p = (struct rio_info *) PortP->p;
-	tty = PortP->gs.port.tty;
-
-
-	rio_dprintk(RIO_DEBUG_INTR, "tx port %d: %d chars queued.\n", PortP->PortNum, PortP->gs.xmit_cnt);
-
-	if (!PortP->gs.xmit_cnt)
-		return;
-
-
-	/* This routine is an order of magnitude simpler than the specialix
-	   version. One of the disadvantages is that this version will send
-	   an incomplete packet (usually 64 bytes instead of 72) once for
-	   every 4k worth of data. Let's just say that this won't influence
-	   performance significantly..... */
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	while (can_add_transmit(&PacketP, PortP)) {
-		c = PortP->gs.xmit_cnt;
-		if (c > PKT_MAX_DATA_LEN)
-			c = PKT_MAX_DATA_LEN;
-
-		/* Don't copy past the end of the source buffer */
-		if (c > SERIAL_XMIT_SIZE - PortP->gs.xmit_tail)
-			c = SERIAL_XMIT_SIZE - PortP->gs.xmit_tail;
-
-		{
-			int t;
-			t = (c > 10) ? 10 : c;
-
-			rio_dprintk(RIO_DEBUG_INTR, "rio: tx port %d: copying %d chars: %s - %s\n", PortP->PortNum, c, firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail, t), firstchars(PortP->gs.xmit_buf + PortP->gs.xmit_tail + c - t, t));
-		}
-		/* If for one reason or another, we can't copy more data,
-		   we're done! */
-		if (c == 0)
-			break;
-
-		rio_memcpy_toio(PortP->HostP->Caddr, PacketP->data, PortP->gs.xmit_buf + PortP->gs.xmit_tail, c);
-		/*    udelay (1); */
-
-		writeb(c, &(PacketP->len));
-		if (!(PortP->State & RIO_DELETED)) {
-			add_transmit(PortP);
-			/*
-			 ** Count chars tx'd for port statistics reporting
-			 */
-			if (PortP->statsGather)
-				PortP->txchars += c;
-		}
-		PortP->gs.xmit_tail = (PortP->gs.xmit_tail + c) & (SERIAL_XMIT_SIZE - 1);
-		PortP->gs.xmit_cnt -= c;
-	}
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	if (PortP->gs.xmit_cnt <= (PortP->gs.wakeup_chars + 2 * PKT_MAX_DATA_LEN))
-		tty_wakeup(PortP->gs.port.tty);
-
-}
-
-
-/*
-** RIO Host Service routine. Does all the work traditionally associated with an
-** interrupt.
-*/
-static int RupIntr;
-static int RxIntr;
-static int TxIntr;
-
-void RIOServiceHost(struct rio_info *p, struct Host *HostP)
-{
-	rio_spin_lock(&HostP->HostLock);
-	if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-		static int t = 0;
-		rio_spin_unlock(&HostP->HostLock);
-		if ((t++ % 200) == 0)
-			rio_dprintk(RIO_DEBUG_INTR, "Interrupt but host not running. flags=%x.\n", (int) HostP->Flags);
-		return;
-	}
-	rio_spin_unlock(&HostP->HostLock);
-
-	if (readw(&HostP->ParmMapP->rup_intr)) {
-		writew(0, &HostP->ParmMapP->rup_intr);
-		p->RIORupCount++;
-		RupIntr++;
-		rio_dprintk(RIO_DEBUG_INTR, "rio: RUP interrupt on host %Zd\n", HostP - p->RIOHosts);
-		RIOPollHostCommands(p, HostP);
-	}
-
-	if (readw(&HostP->ParmMapP->rx_intr)) {
-		int port;
-
-		writew(0, &HostP->ParmMapP->rx_intr);
-		p->RIORxCount++;
-		RxIntr++;
-
-		rio_dprintk(RIO_DEBUG_INTR, "rio: RX interrupt on host %Zd\n", HostP - p->RIOHosts);
-		/*
-		 ** Loop through every port. If the port is mapped into
-		 ** the system ( i.e. has /dev/ttyXXXX associated ) then it is
-		 ** worth checking. If the port isn't open, grab any packets
-		 ** hanging on its receive queue and stuff them on the free
-		 ** list; check for commands on the way.
-		 */
-		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
-			struct Port *PortP = p->RIOPortp[port];
-			struct tty_struct *ttyP;
-			struct PKT __iomem *PacketP;
-
-			/*
-			 ** not mapped in - most of the RIOPortp[] information
-			 ** has not been set up!
-			 ** Optimise: ports come in bundles of eight.
-			 */
-			if (!PortP->Mapped) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** If the host board isn't THIS host board, check the next one.
-			 ** optimise: ports come in bundles of eight.
-			 */
-			if (PortP->HostP != HostP) {
-				port += 7;
-				continue;
-			}
-
-			/*
-			 ** Let us see - is the port open? If not, then don't service it.
-			 */
-			if (!(PortP->PortState & PORT_ISOPEN)) {
-				continue;
-			}
-
-			/*
-			 ** find corresponding tty structure. The process of mapping
-			 ** the ports puts these here.
-			 */
-			ttyP = PortP->gs.port.tty;
-
-			/*
-			 ** Lock the port before we begin working on it.
-			 */
-			rio_spin_lock(&PortP->portSem);
-
-			/*
-			 ** Process received data if there is any.
-			 */
-			if (can_remove_receive(&PacketP, PortP))
-				RIOReceive(p, PortP);
-
-			/*
-			 ** If there is no data left to be read from the port, and
-			 ** it's handshake bit is set, then we must clear the handshake,
-			 ** so that that downstream RTA is re-enabled.
-			 */
-			if (!can_remove_receive(&PacketP, PortP) && (readw(&PortP->PhbP->handshake) == PHB_HANDSHAKE_SET)) {
-				/*
-				 ** MAGIC! ( Basically, handshake the RX buffer, so that
-				 ** the RTAs upstream can be re-enabled. )
-				 */
-				rio_dprintk(RIO_DEBUG_INTR, "Set RX handshake bit\n");
-				writew(PHB_HANDSHAKE_SET | PHB_HANDSHAKE_RESET, &PortP->PhbP->handshake);
-			}
-			rio_spin_unlock(&PortP->portSem);
-		}
-	}
-
-	if (readw(&HostP->ParmMapP->tx_intr)) {
-		int port;
-
-		writew(0, &HostP->ParmMapP->tx_intr);
-
-		p->RIOTxCount++;
-		TxIntr++;
-		rio_dprintk(RIO_DEBUG_INTR, "rio: TX interrupt on host %Zd\n", HostP - p->RIOHosts);
-
-		/*
-		 ** Loop through every port.
-		 ** If the port is mapped into the system ( i.e. has /dev/ttyXXXX
-		 ** associated ) then it is worth checking.
-		 */
-		for (port = p->RIOFirstPortsBooted; port < p->RIOLastPortsBooted + PORTS_PER_RTA; port++) {
-			struct Port *PortP = p->RIOPortp[port];
-			struct tty_struct *ttyP;
-			struct PKT __iomem *PacketP;
-
-			/*
-			 ** not mapped in - most of the RIOPortp[] information
-			 ** has not been set up!
-			 */
-			if (!PortP->Mapped) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** If the host board isn't running, then its data structures
-			 ** are no use to us - continue quietly.
-			 */
-			if (PortP->HostP != HostP) {
-				port += 7;
-				continue;	/* with the next port */
-			}
-
-			/*
-			 ** Let us see - is the port open? If not, then don't service it.
-			 */
-			if (!(PortP->PortState & PORT_ISOPEN)) {
-				continue;
-			}
-
-			rio_dprintk(RIO_DEBUG_INTR, "rio: Looking into port %d.\n", port);
-			/*
-			 ** Lock the port before we begin working on it.
-			 */
-			rio_spin_lock(&PortP->portSem);
-
-			/*
-			 ** If we can't add anything to the transmit queue, then
-			 ** we need do none of this processing.
-			 */
-			if (!can_add_transmit(&PacketP, PortP)) {
-				rio_dprintk(RIO_DEBUG_INTR, "Can't add to port, so skipping.\n");
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-
-			/*
-			 ** find corresponding tty structure. The process of mapping
-			 ** the ports puts these here.
-			 */
-			ttyP = PortP->gs.port.tty;
-			/* If ttyP is NULL, the port is getting closed. Forget about it. */
-			if (!ttyP) {
-				rio_dprintk(RIO_DEBUG_INTR, "no tty, so skipping.\n");
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-			/*
-			 ** If there is more room available we start up the transmit
-			 ** data process again. This can be direct I/O, if the cookmode
-			 ** is set to COOK_RAW or COOK_MEDIUM, or will be a call to the
-			 ** riotproc( T_OUTPUT ) if we are in COOK_WELL mode, to fetch
-			 ** characters via the line discipline. We must always call
-			 ** the line discipline,
-			 ** so that user input characters can be echoed correctly.
-			 **
-			 ** ++++ Update +++++
-			 ** With the advent of double buffering, we now see if
-			 ** TxBufferOut-In is non-zero. If so, then we copy a packet
-			 ** to the output place, and set it going. If this empties
-			 ** the buffer, then we must issue a wakeup( ) on OUT.
-			 ** If it frees space in the buffer then we must issue
-			 ** a wakeup( ) on IN.
-			 **
-			 ** ++++ Extra! Extra! If PortP->WflushFlag is set, then we
-			 ** have to send a WFLUSH command down the PHB, to mark the
-			 ** end point of a WFLUSH. We also need to clear out any
-			 ** data from the double buffer! ( note that WflushFlag is a
-			 ** *count* of the number of WFLUSH commands outstanding! )
-			 **
-			 ** ++++ And there's more!
-			 ** If an RTA is powered off, then on again, and rebooted,
-			 ** whilst it has ports open, then we need to re-open the ports.
-			 ** ( reasonable enough ). We can't do this when we spot the
-			 ** re-boot, in interrupt time, because the queue is probably
-			 ** full. So, when we come in here, we need to test if any
-			 ** ports are in this condition, and re-open the port before
-			 ** we try to send any more data to it. Now, the re-booted
-			 ** RTA will be discarding packets from the PHB until it
-			 ** receives this open packet, but don't worry tooo much
-			 ** about that. The one thing that is interesting is the
-			 ** combination of this effect and the WFLUSH effect!
-			 */
-			/* For now don't handle RTA reboots. -- REW.
-			   Reenabled. Otherwise RTA reboots didn't work. Duh. -- REW */
-			if (PortP->MagicFlags) {
-				if (PortP->MagicFlags & MAGIC_REBOOT) {
-					/*
-					 ** well, the RTA has been rebooted, and there is room
-					 ** on its queue to add the open packet that is required.
-					 **
-					 ** The messy part of this line is trying to decide if
-					 ** we need to call the Param function as a tty or as
-					 ** a modem.
-					 ** DONT USE CLOCAL AS A TEST FOR THIS!
-					 **
-					 ** If we can't param the port, then move on to the
-					 ** next port.
-					 */
-					PortP->InUse = NOT_INUSE;
-
-					rio_spin_unlock(&PortP->portSem);
-					if (RIOParam(PortP, RIOC_OPEN, ((PortP->Cor2Copy & (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) == (RIOC_COR2_RTSFLOW | RIOC_COR2_CTSFLOW)) ? 1 : 0, DONT_SLEEP) == RIO_FAIL)
-						continue;	/* with next port */
-					rio_spin_lock(&PortP->portSem);
-					PortP->MagicFlags &= ~MAGIC_REBOOT;
-				}
-
-				/*
-				 ** As mentioned above, this is a tacky hack to cope
-				 ** with WFLUSH
-				 */
-				if (PortP->WflushFlag) {
-					rio_dprintk(RIO_DEBUG_INTR, "Want to WFLUSH mark this port\n");
-
-					if (PortP->InUse)
-						rio_dprintk(RIO_DEBUG_INTR, "FAILS - PORT IS IN USE\n");
-				}
-
-				while (PortP->WflushFlag && can_add_transmit(&PacketP, PortP) && (PortP->InUse == NOT_INUSE)) {
-					int p;
-					struct PktCmd __iomem *PktCmdP;
-
-					rio_dprintk(RIO_DEBUG_INTR, "Add WFLUSH marker to data queue\n");
-					/*
-					 ** make it look just like a WFLUSH command
-					 */
-					PktCmdP = (struct PktCmd __iomem *) &PacketP->data[0];
-
-					writeb(RIOC_WFLUSH, &PktCmdP->Command);
-
-					p = PortP->HostPort % (u16) PORTS_PER_RTA;
-
-					/*
-					 ** If second block of ports for 16 port RTA, add 8
-					 ** to index 8-15.
-					 */
-					if (PortP->SecondBlock)
-						p += PORTS_PER_RTA;
-
-					writeb(p, &PktCmdP->PhbNum);
-
-					/*
-					 ** to make debuggery easier
-					 */
-					writeb('W', &PacketP->data[2]);
-					writeb('F', &PacketP->data[3]);
-					writeb('L', &PacketP->data[4]);
-					writeb('U', &PacketP->data[5]);
-					writeb('S', &PacketP->data[6]);
-					writeb('H', &PacketP->data[7]);
-					writeb(' ', &PacketP->data[8]);
-					writeb('0' + PortP->WflushFlag, &PacketP->data[9]);
-					writeb(' ', &PacketP->data[10]);
-					writeb(' ', &PacketP->data[11]);
-					writeb('\0', &PacketP->data[12]);
-
-					/*
-					 ** its two bytes long!
-					 */
-					writeb(PKT_CMD_BIT | 2, &PacketP->len);
-
-					/*
-					 ** queue it!
-					 */
-					if (!(PortP->State & RIO_DELETED)) {
-						add_transmit(PortP);
-						/*
-						 ** Count chars tx'd for port statistics reporting
-						 */
-						if (PortP->statsGather)
-							PortP->txchars += 2;
-					}
-
-					if (--(PortP->WflushFlag) == 0) {
-						PortP->MagicFlags &= ~MAGIC_FLUSH;
-					}
-
-					rio_dprintk(RIO_DEBUG_INTR, "Wflush count now stands at %d\n", PortP->WflushFlag);
-				}
-				if (PortP->MagicFlags & MORE_OUTPUT_EYGOR) {
-					if (PortP->MagicFlags & MAGIC_FLUSH) {
-						PortP->MagicFlags |= MORE_OUTPUT_EYGOR;
-					} else {
-						if (!can_add_transmit(&PacketP, PortP)) {
-							rio_spin_unlock(&PortP->portSem);
-							continue;
-						}
-						rio_spin_unlock(&PortP->portSem);
-						RIOTxEnable((char *) PortP);
-						rio_spin_lock(&PortP->portSem);
-						PortP->MagicFlags &= ~MORE_OUTPUT_EYGOR;
-					}
-				}
-			}
-
-
-			/*
-			 ** If we can't add anything to the transmit queue, then
-			 ** we need do none of the remaining processing.
-			 */
-			if (!can_add_transmit(&PacketP, PortP)) {
-				rio_spin_unlock(&PortP->portSem);
-				continue;
-			}
-
-			rio_spin_unlock(&PortP->portSem);
-			RIOTxEnable((char *) PortP);
-		}
-	}
-}
-
-/*
-** Routine for handling received data for tty drivers
-*/
-static void RIOReceive(struct rio_info *p, struct Port *PortP)
-{
-	struct tty_struct *TtyP;
-	unsigned short transCount;
-	struct PKT __iomem *PacketP;
-	register unsigned int DataCnt;
-	unsigned char __iomem *ptr;
-	unsigned char *buf;
-	int copied = 0;
-
-	static int intCount, RxIntCnt;
-
-	/*
-	 ** The receive data process is to remove packets from the
-	 ** PHB until there aren't any more or the current cblock
-	 ** is full. When this occurs, there will be some left over
-	 ** data in the packet, that we must do something with.
-	 ** As we haven't unhooked the packet from the read list
-	 ** yet, we can just leave the packet there, having first
-	 ** made a note of how far we got. This means that we need
-	 ** a pointer per port saying where we start taking the
-	 ** data from - this will normally be zero, but when we
-	 ** run out of space it will be set to the offset of the
-	 ** next byte to copy from the packet data area. The packet
-	 ** length field is decremented by the number of bytes that
-	 ** we successfully removed from the packet. When this reaches
-	 ** zero, we reset the offset pointer to be zero, and free
-	 ** the packet from the front of the queue.
-	 */
-
-	intCount++;
-
-	TtyP = PortP->gs.port.tty;
-	if (!TtyP) {
-		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: tty is null. \n");
-		return;
-	}
-
-	if (PortP->State & RIO_THROTTLE_RX) {
-		rio_dprintk(RIO_DEBUG_INTR, "RIOReceive: Throttled. Can't handle more input.\n");
-		return;
-	}
-
-	if (PortP->State & RIO_DELETED) {
-		while (can_remove_receive(&PacketP, PortP)) {
-			remove_receive(PortP);
-			put_free_end(PortP->HostP, PacketP);
-		}
-	} else {
-		/*
-		 ** loop, just so long as:
-		 **   i ) there's some data ( i.e. can_remove_receive )
-		 **  ii ) we haven't been blocked
-		 ** iii ) there's somewhere to put the data
-		 **  iv ) we haven't outstayed our welcome
-		 */
-		transCount = 1;
-		while (can_remove_receive(&PacketP, PortP)
-		       && transCount) {
-			RxIntCnt++;
-
-			/*
-			 ** check that it is not a command!
-			 */
-			if (readb(&PacketP->len) & PKT_CMD_BIT) {
-				rio_dprintk(RIO_DEBUG_INTR, "RIO: unexpected command packet received on PHB\n");
-				/*      rio_dprint(RIO_DEBUG_INTR, (" sysport   = %d\n", p->RIOPortp->PortNum)); */
-				rio_dprintk(RIO_DEBUG_INTR, " dest_unit = %d\n", readb(&PacketP->dest_unit));
-				rio_dprintk(RIO_DEBUG_INTR, " dest_port = %d\n", readb(&PacketP->dest_port));
-				rio_dprintk(RIO_DEBUG_INTR, " src_unit  = %d\n", readb(&PacketP->src_unit));
-				rio_dprintk(RIO_DEBUG_INTR, " src_port  = %d\n", readb(&PacketP->src_port));
-				rio_dprintk(RIO_DEBUG_INTR, " len	   = %d\n", readb(&PacketP->len));
-				rio_dprintk(RIO_DEBUG_INTR, " control   = %d\n", readb(&PacketP->control));
-				rio_dprintk(RIO_DEBUG_INTR, " csum	   = %d\n", readw(&PacketP->csum));
-				rio_dprintk(RIO_DEBUG_INTR, "	 data bytes: ");
-				for (DataCnt = 0; DataCnt < PKT_MAX_DATA_LEN; DataCnt++)
-					rio_dprintk(RIO_DEBUG_INTR, "%d\n", readb(&PacketP->data[DataCnt]));
-				remove_receive(PortP);
-				put_free_end(PortP->HostP, PacketP);
-				continue;	/* with next packet */
-			}
-
-			/*
-			 ** How many characters can we move 'upstream' ?
-			 **
-			 ** Determine the minimum of the amount of data
-			 ** available and the amount of space in which to
-			 ** put it.
-			 **
-			 ** 1.        Get the packet length by masking 'len'
-			 **   for only the length bits.
-			 ** 2.        Available space is [buffer size] - [space used]
-			 **
-			 ** Transfer count is the minimum of packet length
-			 ** and available space.
-			 */
-
-			transCount = tty_buffer_request_room(TtyP, readb(&PacketP->len) & PKT_LEN_MASK);
-			rio_dprintk(RIO_DEBUG_REC, "port %d: Copy %d bytes\n", PortP->PortNum, transCount);
-			/*
-			 ** To use the following 'kkprintfs' for debugging - change the '#undef'
-			 ** to '#define', (this is the only place ___DEBUG_IT___ occurs in the
-			 ** driver).
-			 */
-			ptr = (unsigned char __iomem *) PacketP->data + PortP->RxDataStart;
-
-			tty_prepare_flip_string(TtyP, &buf, transCount);
-			rio_memcpy_fromio(buf, ptr, transCount);
-			PortP->RxDataStart += transCount;
-			writeb(readb(&PacketP->len)-transCount, &PacketP->len);
-			copied += transCount;
-
-
-
-			if (readb(&PacketP->len) == 0) {
-				/*
-				 ** If we have emptied the packet, then we can
-				 ** free it, and reset the start pointer for
-				 ** the next packet.
-				 */
-				remove_receive(PortP);
-				put_free_end(PortP->HostP, PacketP);
-				PortP->RxDataStart = 0;
-			}
-		}
-	}
-	if (copied) {
-		rio_dprintk(RIO_DEBUG_REC, "port %d: pushing tty flip buffer: %d total bytes copied.\n", PortP->PortNum, copied);
-		tty_flip_buffer_push(TtyP);
-	}
-
-	return;
-}
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioioctl.h linux-libre-2.6.39-gnu/drivers/char/rio/rioioctl.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioioctl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioioctl.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,57 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioioctl.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)rioioctl.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef	__rioioctl_h__
-#define	__rioioctl_h__
-
-/*
-** RIO device driver - user ioctls and associated structures.
-*/
-
-struct portStats {
-	int port;
-	int gather;
-	unsigned long txchars;
-	unsigned long rxchars;
-	unsigned long opens;
-	unsigned long closes;
-	unsigned long ioctls;
-};
-
-#define	RIOC	('R'<<8)|('i'<<16)|('o'<<24)
-
-#define	RIO_QUICK_CHECK	  	(RIOC | 105)
-#define RIO_GATHER_PORT_STATS	(RIOC | 193)
-#define RIO_RESET_PORT_STATS	(RIOC | 194)
-#define RIO_GET_PORT_STATS	(RIOC | 195)
-
-#endif				/* __rioioctl_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rio_linux.c linux-libre-2.6.39-gnu/drivers/char/rio/rio_linux.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/rio_linux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rio_linux.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1204 +0,0 @@
-
-/* rio_linux.c -- Linux driver for the Specialix RIO series cards. 
- *
- *
- *   (C) 1999 R.E.Wolff@BitWizard.nl
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (rio.txt) first.
- *
- *
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the 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/module.h>
-#include <linux/kdev_t.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/mutex.h>
-#include <linux/miscdevice.h>
-#include <linux/init.h>
-
-#include <linux/generic_serial.h>
-#include <asm/uaccess.h>
-
-#include "linux_compat.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-#include "protsts.h"
-#include "rioboard.h"
-
-
-#include "rio_linux.h"
-
-/* I don't think that this driver can handle more than 512 ports on
-one machine.  Specialix specifies max 4 boards in one machine. I don't
-know why. If you want to try anyway you'll have to increase the number
-of boards in rio.h.  You'll have to allocate more majors if you need
-more than 512 ports.... */
-
-#ifndef RIO_NORMAL_MAJOR0
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define RIO_NORMAL_MAJOR0  154
-#define RIO_NORMAL_MAJOR1  156
-#endif
-
-#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
-#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
-#endif
-
-#ifndef RIO_WINDOW_LEN
-#define RIO_WINDOW_LEN 0x10000
-#endif
-
-
-/* Configurable options: 
-   (Don't be too sure that it'll work if you toggle them) */
-
-/* Am I paranoid or not ? ;-) */
-#undef RIO_PARANOIA_CHECK
-
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 1000
-   Hz, but it is user configurable. I don't recommend going above 1000
-   Hz. The interrupt ratelimit might trigger if the interrupt is
-   shared with a very active other device. 
-   undef this if you want to disable the check....
-*/
-#define IRQ_RATE_LIMIT 200
-
-
-/* These constants are derived from SCO Source */
-static DEFINE_MUTEX(rio_fw_mutex);
-static struct Conf
- RIOConf = {
-	/* locator */ "RIO Config here",
-					/* startuptime */ HZ * 2,
-					/* how long to wait for card to run */
-				/* slowcook */ 0,
-				/* TRUE -> always use line disc. */
-				/* intrpolltime */ 1,
-				/* The frequency of OUR polls */
-				/* breakinterval */ 25,
-				/* x10 mS XXX: units seem to be 1ms not 10! -- REW */
-				/* timer */ 10,
-				/* mS */
-	/* RtaLoadBase */ 0x7000,
-	/* HostLoadBase */ 0x7C00,
-				/* XpHz */ 5,
-				/* number of Xprint hits per second */
-				/* XpCps */ 120,
-				/* Xprint characters per second */
-				/* XpOn */ "\033d#",
-				/* start Xprint for a wyse 60 */
-				/* XpOff */ "\024",
-				/* end Xprint for a wyse 60 */
-				/* MaxXpCps */ 2000,
-				/* highest Xprint speed */
-				/* MinXpCps */ 10,
-				/* slowest Xprint speed */
-				/* SpinCmds */ 1,
-				/* non-zero for mega fast boots */
-					/* First Addr */ 0x0A0000,
-					/* First address to look at */
-					/* Last Addr */ 0xFF0000,
-					/* Last address looked at */
-				/* BufferSize */ 1024,
-				/* Bytes per port of buffering */
-				/* LowWater */ 256,
-				/* how much data left before wakeup */
-				/* LineLength */ 80,
-				/* how wide is the console? */
-				/* CmdTimeout */ HZ,
-				/* how long a close command may take */
-};
-
-
-
-
-/* Function prototypes */
-
-static void rio_disable_tx_interrupts(void *ptr);
-static void rio_enable_tx_interrupts(void *ptr);
-static void rio_disable_rx_interrupts(void *ptr);
-static void rio_enable_rx_interrupts(void *ptr);
-static int rio_carrier_raised(struct tty_port *port);
-static void rio_shutdown_port(void *ptr);
-static int rio_set_real_termios(void *ptr);
-static void rio_hungup(void *ptr);
-static void rio_close(void *ptr);
-static int rio_chars_in_buffer(void *ptr);
-static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-static int rio_init_drivers(void);
-
-static void my_hd(void *addr, int len);
-
-static struct tty_driver *rio_driver, *rio_driver2;
-
-/* The name "p" is a bit non-descript. But that's what the rio-lynxos
-sources use all over the place. */
-struct rio_info *p;
-
-int rio_debug;
-
-
-/* You can have the driver poll your card. 
-    - Set rio_poll to 1 to poll every timer tick (10ms on Intel). 
-      This is used when the card cannot use an interrupt for some reason.
-*/
-static int rio_poll = 1;
-
-
-/* These are the only open spaces in my computer. Yours may have more
-   or less.... */
-static int rio_probe_addrs[] = { 0xc0000, 0xd0000, 0xe0000 };
-
-#define NR_RIO_ADDRS ARRAY_SIZE(rio_probe_addrs)
-
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
-   Some architectures may need more. -- Changed to LONG to
-   support up to 64 bits on 64bit architectures. -- REW 20/06/99 */
-static long rio_irqmask = -1;
-
-MODULE_AUTHOR("Rogier Wolff <R.E.Wolff@bitwizard.nl>, Patrick van de Lageweg <patrick@bitwizard.nl>");
-MODULE_DESCRIPTION("RIO driver");
-MODULE_LICENSE("GPL");
-module_param(rio_poll, int, 0);
-module_param(rio_debug, int, 0644);
-module_param(rio_irqmask, long, 0);
-
-static struct real_driver rio_real_driver = {
-	rio_disable_tx_interrupts,
-	rio_enable_tx_interrupts,
-	rio_disable_rx_interrupts,
-	rio_enable_rx_interrupts,
-	rio_shutdown_port,
-	rio_set_real_termios,
-	rio_chars_in_buffer,
-	rio_close,
-	rio_hungup,
-	NULL
-};
-
-/* 
- *  Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations rio_fw_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = rio_fw_ioctl,
-	.llseek = noop_llseek,
-};
-
-static struct miscdevice rio_fw_device = {
-	RIOCTL_MISC_MINOR, "rioctl", &rio_fw_fops
-};
-
-
-
-
-
-#ifdef RIO_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int rio_paranoia_check(struct rio_port const *port, char *name, const char *routine)
-{
-
-	static const char *badmagic = KERN_ERR "rio: Warning: bad rio port magic number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR "rio: Warning: null rio port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != RIO_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-#else
-#define rio_paranoia_check(a,b,c) 0
-#endif
-
-
-#ifdef DEBUG
-static void my_hd(void *ad, int len)
-{
-	int i, j, ch;
-	unsigned char *addr = ad;
-
-	for (i = 0; i < len; i += 16) {
-		rio_dprintk(RIO_DEBUG_PARAM, "%08lx ", (unsigned long) addr + i);
-		for (j = 0; j < 16; j++) {
-			rio_dprintk(RIO_DEBUG_PARAM, "%02x %s", addr[j + i], (j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = addr[j + i];
-			rio_dprintk(RIO_DEBUG_PARAM, "%c", (ch < 0x20) ? '.' : ((ch > 0x7f) ? '.' : ch));
-		}
-		rio_dprintk(RIO_DEBUG_PARAM, "\n");
-	}
-}
-#else
-#define my_hd(ad,len) do{/* nothing*/ } while (0)
-#endif
-
-
-/* Delay a number of jiffies, allowing a signal to interrupt */
-int RIODelay(struct Port *PortP, int njiffies)
-{
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies\n", njiffies);
-	msleep_interruptible(jiffies_to_msecs(njiffies));
-	func_exit();
-
-	if (signal_pending(current))
-		return RIO_FAIL;
-	else
-		return !RIO_FAIL;
-}
-
-
-/* Delay a number of jiffies, disallowing a signal to interrupt */
-int RIODelay_ni(struct Port *PortP, int njiffies)
-{
-	func_enter();
-
-	rio_dprintk(RIO_DEBUG_DELAY, "delaying %d jiffies (ni)\n", njiffies);
-	msleep(jiffies_to_msecs(njiffies));
-	func_exit();
-	return !RIO_FAIL;
-}
-
-void rio_copy_to_card(void *from, void __iomem *to, int len)
-{
-	rio_copy_toio(to, from, len);
-}
-
-int rio_minor(struct tty_struct *tty)
-{
-	return tty->index + ((tty->driver == rio_driver) ? 0 : 256);
-}
-
-static int rio_set_real_termios(void *ptr)
-{
-	return RIOParam((struct Port *) ptr, RIOC_CONFIG, 1, 1);
-}
-
-
-static void rio_reset_interrupt(struct Host *HostP)
-{
-	func_enter();
-
-	switch (HostP->Type) {
-	case RIO_AT:
-	case RIO_MCA:
-	case RIO_PCI:
-		writeb(0xFF, &HostP->ResetInt);
-	}
-
-	func_exit();
-}
-
-
-static irqreturn_t rio_interrupt(int irq, void *ptr)
-{
-	struct Host *HostP;
-	func_enter();
-
-	HostP = ptr;			/* &p->RIOHosts[(long)ptr]; */
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: enter rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
-
-	/* AAargh! The order in which to do these things is essential and
-	   not trivial.
-
-	   - hardware twiddling goes before "recursive". Otherwise when we
-	   poll the card, and a recursive interrupt happens, we won't
-	   ack the card, so it might keep on interrupting us. (especially
-	   level sensitive interrupt systems like PCI).
-
-	   - Rate limit goes before hardware twiddling. Otherwise we won't
-	   catch a card that has gone bonkers.
-
-	   - The "initialized" test goes after the hardware twiddling. Otherwise
-	   the card will stick us in the interrupt routine again.
-
-	   - The initialized test goes before recursive.
-	 */
-
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: We've have noticed the interrupt\n");
-	if (HostP->Ivec == irq) {
-		/* Tell the card we've noticed the interrupt. */
-		rio_reset_interrupt(HostP);
-	}
-
-	if ((HostP->Flags & RUN_STATE) != RC_RUNNING)
-		return IRQ_HANDLED;
-
-	if (test_and_set_bit(RIO_BOARD_INTR_LOCK, &HostP->locks)) {
-		printk(KERN_ERR "Recursive interrupt! (host %p/irq%d)\n", ptr, HostP->Ivec);
-		return IRQ_HANDLED;
-	}
-
-	RIOServiceHost(p, HostP);
-
-	rio_dprintk(RIO_DEBUG_IFLOW, "riointr() doing host %p type %d\n", ptr, HostP->Type);
-
-	clear_bit(RIO_BOARD_INTR_LOCK, &HostP->locks);
-	rio_dprintk(RIO_DEBUG_IFLOW, "rio: exit rio_interrupt (%d/%d)\n", irq, HostP->Ivec);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-
-static void rio_pollfunc(unsigned long data)
-{
-	func_enter();
-
-	rio_interrupt(0, &p->RIOHosts[data]);
-	mod_timer(&p->RIOHosts[data].timer, jiffies + rio_poll);
-
-	func_exit();
-}
-
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *              interface with the generic_serial driver                  *
- * ********************************************************************** */
-
-/* Ehhm. I don't know how to fiddle with interrupts on the Specialix 
-   cards. ....   Hmm. Ok I figured it out. You don't.  -- REW */
-
-static void rio_disable_tx_interrupts(void *ptr)
-{
-	func_enter();
-
-	/*  port->gs.port.flags &= ~GS_TX_INTEN; */
-
-	func_exit();
-}
-
-
-static void rio_enable_tx_interrupts(void *ptr)
-{
-	struct Port *PortP = ptr;
-	/* int hn; */
-
-	func_enter();
-
-	/* hn = PortP->HostP - p->RIOHosts;
-
-	   rio_dprintk (RIO_DEBUG_TTY, "Pushing host %d\n", hn);
-	   rio_interrupt (-1,(void *) hn, NULL); */
-
-	RIOTxEnable((char *) PortP);
-
-	/*
-	 * In general we cannot count on "tx empty" interrupts, although
-	 * the interrupt routine seems to be able to tell the difference.
-	 */
-	PortP->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-
-static void rio_disable_rx_interrupts(void *ptr)
-{
-	func_enter();
-	func_exit();
-}
-
-static void rio_enable_rx_interrupts(void *ptr)
-{
-	/*  struct rio_port *port = ptr; */
-	func_enter();
-	func_exit();
-}
-
-
-/* Jeez. Isn't this simple?  */
-static int rio_carrier_raised(struct tty_port *port)
-{
-	struct Port *PortP = container_of(port, struct Port, gs.port);
-	int rv;
-
-	func_enter();
-	rv = (PortP->ModemState & RIOC_MSVR1_CD) != 0;
-
-	rio_dprintk(RIO_DEBUG_INIT, "Getting CD status: %d\n", rv);
-
-	func_exit();
-	return rv;
-}
-
-
-/* Jeez. Isn't this simple? Actually, we can sync with the actual port
-   by just pushing stuff into the queue going to the port... */
-static int rio_chars_in_buffer(void *ptr)
-{
-	func_enter();
-
-	func_exit();
-	return 0;
-}
-
-
-/* Nothing special here... */
-static void rio_shutdown_port(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-	PortP->gs.port.tty = NULL;
-	func_exit();
-}
-
-
-/* I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-static void rio_hungup(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-	PortP->gs.port.tty = NULL;
-
-	func_exit();
-}
-
-
-/* The standard serial_close would become shorter if you'd wrap it like
-   this. 
-   rs_close (...){save_flags;cli;real_close();dec_use_count;restore_flags;}
- */
-static void rio_close(void *ptr)
-{
-	struct Port *PortP;
-
-	func_enter();
-
-	PortP = (struct Port *) ptr;
-
-	riotclose(ptr);
-
-	if (PortP->gs.port.count) {
-		printk(KERN_ERR "WARNING port count:%d\n", PortP->gs.port.count);
-		PortP->gs.port.count = 0;
-	}
-
-	PortP->gs.port.tty = NULL;
-	func_exit();
-}
-
-
-
-static long rio_fw_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	int rc = 0;
-	func_enter();
-
-	/* The "dev" argument isn't used. */
-	mutex_lock(&rio_fw_mutex);
-	rc = riocontrol(p, 0, cmd, arg, capable(CAP_SYS_ADMIN));
-	mutex_unlock(&rio_fw_mutex);
-
-	func_exit();
-	return rc;
-}
-
-extern int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-
-static int rio_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	int rc;
-	struct Port *PortP;
-	int ival;
-
-	func_enter();
-
-	PortP = (struct Port *) tty->driver_data;
-
-	rc = 0;
-	switch (cmd) {
-	case TIOCSSOFTCAR:
-		if ((rc = get_user(ival, (unsigned __user *) argp)) == 0) {
-			tty->termios->c_cflag = (tty->termios->c_cflag & ~CLOCAL) | (ival ? CLOCAL : 0);
-		}
-		break;
-	case TIOCGSERIAL:
-		rc = -EFAULT;
-		if (access_ok(VERIFY_WRITE, argp, sizeof(struct serial_struct)))
-			rc = gs_getserial(&PortP->gs, argp);
-		break;
-	case TCSBRK:
-		if (PortP->State & RIO_DELETED) {
-			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
-			rc = -EIO;
-		} else {
-			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2, 250) ==
-					RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
-				rc = -EIO;
-			}
-		}
-		break;
-	case TCSBRKP:
-		if (PortP->State & RIO_DELETED) {
-			rio_dprintk(RIO_DEBUG_TTY, "BREAK on deleted RTA\n");
-			rc = -EIO;
-		} else {
-			int l;
-			l = arg ? arg * 100 : 250;
-			if (l > 255)
-				l = 255;
-			if (RIOShortCommand(p, PortP, RIOC_SBREAK, 2,
-					arg ? arg * 100 : 250) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_INTR, "SBREAK RIOShortCommand failed\n");
-				rc = -EIO;
-			}
-		}
-		break;
-	case TIOCSSERIAL:
-		rc = -EFAULT;
-		if (access_ok(VERIFY_READ, argp, sizeof(struct serial_struct)))
-			rc = gs_setserial(&PortP->gs, argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	func_exit();
-	return rc;
-}
-
-
-/* The throttle/unthrottle scheme for the Specialix card is different
- * from other drivers and deserves some explanation. 
- * The Specialix hardware takes care of XON/XOFF
- * and CTS/RTS flow control itself.  This means that all we have to
- * do when signalled by the upper tty layer to throttle/unthrottle is
- * to make a note of it here.  When we come to read characters from the
- * rx buffers on the card (rio_receive_chars()) we look to see if the
- * upper layer can accept more (as noted here in rio_rx_throt[]). 
- * If it can't we simply don't remove chars from the cards buffer. 
- * When the tty layer can accept chars, we again note that here and when
- * rio_receive_chars() is called it will remove them from the cards buffer.
- * The card will notice that a ports buffer has drained below some low
- * water mark and will unflow control the line itself, using whatever
- * flow control scheme is in use for that port. -- Simon Allen
- */
-
-static void rio_throttle(struct tty_struct *tty)
-{
-	struct Port *port = (struct Port *) tty->driver_data;
-
-	func_enter();
-	/* If the port is using any type of input flow
-	 * control then throttle the port.
-	 */
-
-	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-		port->State |= RIO_THROTTLE_RX;
-	}
-
-	func_exit();
-}
-
-
-static void rio_unthrottle(struct tty_struct *tty)
-{
-	struct Port *port = (struct Port *) tty->driver_data;
-
-	func_enter();
-	/* Always unthrottle even if flow control is not enabled on
-	 * this port in case we disabled flow control while the port
-	 * was throttled
-	 */
-
-	port->State &= ~RIO_THROTTLE_RX;
-
-	func_exit();
-	return;
-}
-
-
-
-
-
-/* ********************************************************************** *
- *                    Here are the initialization routines.               *
- * ********************************************************************** */
-
-
-static struct vpd_prom *get_VPD_PROM(struct Host *hp)
-{
-	static struct vpd_prom vpdp;
-	char *p;
-	int i;
-
-	func_enter();
-	rio_dprintk(RIO_DEBUG_PROBE, "Going to verify vpd prom at %p.\n", hp->Caddr + RIO_VPD_ROM);
-
-	p = (char *) &vpdp;
-	for (i = 0; i < sizeof(struct vpd_prom); i++)
-		*p++ = readb(hp->Caddr + RIO_VPD_ROM + i * 2);
-	/* read_rio_byte (hp, RIO_VPD_ROM + i*2); */
-
-	/* Terminate the identifier string.
-	 *** requires one extra byte in struct vpd_prom *** */
-	*p++ = 0;
-
-	if (rio_debug & RIO_DEBUG_PROBE)
-		my_hd((char *) &vpdp, 0x20);
-
-	func_exit();
-
-	return &vpdp;
-}
-
-static const struct tty_operations rio_ops = {
-	.open = riotopen,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = rio_ioctl,
-	.throttle = rio_throttle,
-	.unthrottle = rio_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-};
-
-static int rio_init_drivers(void)
-{
-	int error = -ENOMEM;
-
-	rio_driver = alloc_tty_driver(256);
-	if (!rio_driver)
-		goto out;
-	rio_driver2 = alloc_tty_driver(256);
-	if (!rio_driver2)
-		goto out1;
-
-	func_enter();
-
-	rio_driver->owner = THIS_MODULE;
-	rio_driver->driver_name = "specialix_rio";
-	rio_driver->name = "ttySR";
-	rio_driver->major = RIO_NORMAL_MAJOR0;
-	rio_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	rio_driver->subtype = SERIAL_TYPE_NORMAL;
-	rio_driver->init_termios = tty_std_termios;
-	rio_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rio_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(rio_driver, &rio_ops);
-
-	rio_driver2->owner = THIS_MODULE;
-	rio_driver2->driver_name = "specialix_rio";
-	rio_driver2->name = "ttySR";
-	rio_driver2->major = RIO_NORMAL_MAJOR1;
-	rio_driver2->type = TTY_DRIVER_TYPE_SERIAL;
-	rio_driver2->subtype = SERIAL_TYPE_NORMAL;
-	rio_driver2->init_termios = tty_std_termios;
-	rio_driver2->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rio_driver2->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(rio_driver2, &rio_ops);
-
-	rio_dprintk(RIO_DEBUG_INIT, "set_termios = %p\n", gs_set_termios);
-
-	if ((error = tty_register_driver(rio_driver)))
-		goto out2;
-	if ((error = tty_register_driver(rio_driver2)))
-		goto out3;
-	func_exit();
-	return 0;
-      out3:
-	tty_unregister_driver(rio_driver);
-      out2:
-	put_tty_driver(rio_driver2);
-      out1:
-	put_tty_driver(rio_driver);
-      out:
-	printk(KERN_ERR "rio: Couldn't register a rio driver, error = %d\n", error);
-	return 1;
-}
-
-static const struct tty_port_operations rio_port_ops = {
-	.carrier_raised = rio_carrier_raised,
-};
-
-static int rio_init_datastructures(void)
-{
-	int i;
-	struct Port *port;
-	func_enter();
-
-	/* Many drivers statically allocate the maximum number of ports
-	   There is no reason not to allocate them dynamically. Is there? -- REW */
-	/* However, the RIO driver allows users to configure their first
-	   RTA as the ports numbered 504-511. We therefore need to allocate
-	   the whole range. :-(   -- REW */
-
-#define RI_SZ   sizeof(struct rio_info)
-#define HOST_SZ sizeof(struct Host)
-#define PORT_SZ sizeof(struct Port *)
-#define TMIO_SZ sizeof(struct termios *)
-	rio_dprintk(RIO_DEBUG_INIT, "getting : %Zd %Zd %Zd %Zd %Zd bytes\n", RI_SZ, RIO_HOSTS * HOST_SZ, RIO_PORTS * PORT_SZ, RIO_PORTS * TMIO_SZ, RIO_PORTS * TMIO_SZ);
-
-	if (!(p = kzalloc(RI_SZ, GFP_KERNEL)))
-		goto free0;
-	if (!(p->RIOHosts = kzalloc(RIO_HOSTS * HOST_SZ, GFP_KERNEL)))
-		goto free1;
-	if (!(p->RIOPortp = kzalloc(RIO_PORTS * PORT_SZ, GFP_KERNEL)))
-		goto free2;
-	p->RIOConf = RIOConf;
-	rio_dprintk(RIO_DEBUG_INIT, "Got : %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
-
-#if 1
-	for (i = 0; i < RIO_PORTS; i++) {
-		port = p->RIOPortp[i] = kzalloc(sizeof(struct Port), GFP_KERNEL);
-		if (!port) {
-			goto free6;
-		}
-		rio_dprintk(RIO_DEBUG_INIT, "initing port %d (%d)\n", i, port->Mapped);
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &rio_port_ops;
-		port->PortNum = i;
-		port->gs.magic = RIO_MAGIC;
-		port->gs.close_delay = HZ / 2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &rio_real_driver;
-		spin_lock_init(&port->portSem);
-	}
-#else
-	/* We could postpone initializing them to when they are configured. */
-#endif
-
-
-
-	if (rio_debug & RIO_DEBUG_INIT) {
-		my_hd(&rio_real_driver, sizeof(rio_real_driver));
-	}
-
-
-	func_exit();
-	return 0;
-
-      free6:for (i--; i >= 0; i--)
-		kfree(p->RIOPortp[i]);
-/*free5:
- free4:
- free3:*/ kfree(p->RIOPortp);
-      free2:kfree(p->RIOHosts);
-      free1:
-	rio_dprintk(RIO_DEBUG_INIT, "Not enough memory! %p %p %p\n", p, p->RIOHosts, p->RIOPortp);
-	kfree(p);
-      free0:
-	return -ENOMEM;
-}
-
-static void __exit rio_release_drivers(void)
-{
-	func_enter();
-	tty_unregister_driver(rio_driver2);
-	tty_unregister_driver(rio_driver);
-	put_tty_driver(rio_driver2);
-	put_tty_driver(rio_driver);
-	func_exit();
-}
-
-
-#ifdef CONFIG_PCI
- /* This was written for SX, but applies to RIO too...
-    (including bugs....)
-
-    There is another bit besides Bit 17. Turning that bit off
-    (on boards shipped with the fix in the eeprom) results in a 
-    hang on the next access to the card. 
-  */
-
- /******************************************************** 
- * Setting bit 17 in the CNTRL register of the PLX 9050  * 
- * chip forces a retry on writes while a read is pending.*
- * This is to prevent the card locking up on Intel Xeon  *
- * multiprocessor systems with the NX chipset.    -- NV  *
- ********************************************************/
-
-/* Newer cards are produced with this bit set from the configuration
-   EEprom.  As the bit is read/write for the CPU, we can fix it here,
-   if we detect that it isn't set correctly. -- REW */
-
-static void fix_rio_pci(struct pci_dev *pdev)
-{
-	unsigned long hwbase;
-	unsigned char __iomem *rebase;
-	unsigned int t;
-
-#define CNTRL_REG_OFFSET        0x50
-#define CNTRL_REG_GOODVALUE     0x18260000
-
-	hwbase = pci_resource_start(pdev, 0);
-	rebase = ioremap(hwbase, 0x80);
-	t = readl(rebase + CNTRL_REG_OFFSET);
-	if (t != CNTRL_REG_GOODVALUE) {
-		printk(KERN_DEBUG "rio: performing cntrl reg fix: %08x -> %08x\n", t, CNTRL_REG_GOODVALUE);
-		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
-	}
-	iounmap(rebase);
-}
-#endif
-
-
-static int __init rio_init(void)
-{
-	int found = 0;
-	int i;
-	struct Host *hp;
-	int retval;
-	struct vpd_prom *vpdp;
-	int okboard;
-
-#ifdef CONFIG_PCI
-	struct pci_dev *pdev = NULL;
-	unsigned short tshort;
-#endif
-
-	func_enter();
-	rio_dprintk(RIO_DEBUG_INIT, "Initing rio module... (rio_debug=%d)\n", rio_debug);
-
-	if (abs((long) (&rio_debug) - rio_debug) < 0x10000) {
-		printk(KERN_WARNING "rio: rio_debug is an address, instead of a value. " "Assuming -1. Was %x/%p.\n", rio_debug, &rio_debug);
-		rio_debug = -1;
-	}
-
-	if (misc_register(&rio_fw_device) < 0) {
-		printk(KERN_ERR "RIO: Unable to register firmware loader driver.\n");
-		return -EIO;
-	}
-
-	retval = rio_init_datastructures();
-	if (retval < 0) {
-		misc_deregister(&rio_fw_device);
-		return retval;
-	}
-#ifdef CONFIG_PCI
-	/* First look for the JET devices: */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8, pdev))) {
-		u32 tint;
-
-		if (pci_enable_device(pdev))
-			continue;
-
-		/* Specialix has a whole bunch of cards with
-		   0x2000 as the device ID. They say its because
-		   the standard requires it. Stupid standard. */
-		/* It seems that reading a word doesn't work reliably on 2.0.
-		   Also, reading a non-aligned dword doesn't work. So we read the
-		   whole dword at 0x2c and extract the word at 0x2e (SUBSYSTEM_ID)
-		   ourselves */
-		pci_read_config_dword(pdev, 0x2c, &tint);
-		tshort = (tint >> 16) & 0xffff;
-		rio_dprintk(RIO_DEBUG_PROBE, "Got a specialix card: %x.\n", tint);
-		if (tshort != 0x0100) {
-			rio_dprintk(RIO_DEBUG_PROBE, "But it's not a RIO card (%d)...\n", tshort);
-			continue;
-		}
-		rio_dprintk(RIO_DEBUG_PROBE, "cp1\n");
-
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = pci_resource_start(pdev, 2);
-		hp->Ivec = pdev->irq;
-		if (((1 << hp->Ivec) & rio_irqmask) == 0)
-			hp->Ivec = 0;
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_PCI;
-		hp->Copy = rio_copy_to_card;
-		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
-		spin_lock_init(&hp->HostLock);
-		rio_reset_interrupt(hp);
-		rio_start_card_running(hp);
-
-		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
-		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
-			rio_dprintk(RIO_DEBUG_INIT, "Done RIOBoardTest\n");
-			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-			p->RIOHosts[p->RIONumHosts].UniqueNum =
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
-			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-			fix_rio_pci(pdev);
-
-			p->RIOHosts[p->RIONumHosts].pdev = pdev;
-			pci_dev_get(pdev);
-
-			p->RIOLastPCISearch = 0;
-			p->RIONumHosts++;
-			found++;
-		} else {
-			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
-			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
-		}
-	}
-
-	/* Then look for the older PCI card.... : */
-
-	/* These older PCI cards have problems (only byte-mode access is
-	   supported), which makes them a bit awkward to support.
-	   They also have problems sharing interrupts. Be careful.
-	   (The driver now refuses to share interrupts for these
-	   cards. This should be sufficient).
-	 */
-
-	/* Then look for the older RIO/PCI devices: */
-	while ((pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_RIO, pdev))) {
-		if (pci_enable_device(pdev))
-			continue;
-
-#ifdef CONFIG_RIO_OLDPCI
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = pci_resource_start(pdev, 0);
-		hp->Ivec = pdev->irq;
-		if (((1 << hp->Ivec) & rio_irqmask) == 0)
-			hp->Ivec = 0;
-		hp->Ivec |= 0x8000;	/* Mark as non-sharable */
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_PCI;
-		hp->Copy = rio_copy_to_card;
-		hp->Mode = RIO_PCI_BOOT_FROM_RAM;
-		spin_lock_init(&hp->HostLock);
-
-		rio_dprintk(RIO_DEBUG_PROBE, "Ivec: %x\n", hp->Ivec);
-		rio_dprintk(RIO_DEBUG_PROBE, "Mode: %x\n", hp->Mode);
-
-		rio_reset_interrupt(hp);
-		rio_start_card_running(hp);
-		rio_dprintk(RIO_DEBUG_PROBE, "Going to test it (%p/%p).\n", (void *) p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr);
-		if (RIOBoardTest(p->RIOHosts[p->RIONumHosts].PaddrP, p->RIOHosts[p->RIONumHosts].Caddr, RIO_PCI, 0) == 0) {
-			writeb(0xFF, &p->RIOHosts[p->RIONumHosts].ResetInt);
-			p->RIOHosts[p->RIONumHosts].UniqueNum =
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[0]) & 0xFF) << 0) |
-			    ((readb(&p->RIOHosts[p->RIONumHosts].Unique[1]) & 0xFF) << 8) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[2]) & 0xFF) << 16) | ((readb(&p->RIOHosts[p->RIONumHosts].Unique[3]) & 0xFF) << 24);
-			rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-
-			p->RIOHosts[p->RIONumHosts].pdev = pdev;
-			pci_dev_get(pdev);
-
-			p->RIOLastPCISearch = 0;
-			p->RIONumHosts++;
-			found++;
-		} else {
-			iounmap(p->RIOHosts[p->RIONumHosts].Caddr);
-			p->RIOHosts[p->RIONumHosts].Caddr = NULL;
-		}
-#else
-		printk(KERN_ERR "Found an older RIO PCI card, but the driver is not " "compiled to support it.\n");
-#endif
-	}
-#endif				/* PCI */
-
-	/* Now probe for ISA cards... */
-	for (i = 0; i < NR_RIO_ADDRS; i++) {
-		hp = &p->RIOHosts[p->RIONumHosts];
-		hp->PaddrP = rio_probe_addrs[i];
-		/* There was something about the IRQs of these cards. 'Forget what.--REW */
-		hp->Ivec = 0;
-		hp->Caddr = ioremap(p->RIOHosts[p->RIONumHosts].PaddrP, RIO_WINDOW_LEN);
-		hp->CardP = (struct DpRam __iomem *) hp->Caddr;
-		hp->Type = RIO_AT;
-		hp->Copy = rio_copy_to_card;	/* AT card PCI???? - PVDL
-                                         * -- YES! this is now a normal copy. Only the
-					 * old PCI card uses the special PCI copy.
-					 * Moreover, the ISA card will work with the
-					 * special PCI copy anyway. -- REW */
-		hp->Mode = 0;
-		spin_lock_init(&hp->HostLock);
-
-		vpdp = get_VPD_PROM(hp);
-		rio_dprintk(RIO_DEBUG_PROBE, "Got VPD ROM\n");
-		okboard = 0;
-		if ((strncmp(vpdp->identifier, RIO_ISA_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA2_IDENT, 16) == 0) || (strncmp(vpdp->identifier, RIO_ISA3_IDENT, 16) == 0)) {
-			/* Board is present... */
-			if (RIOBoardTest(hp->PaddrP, hp->Caddr, RIO_AT, 0) == 0) {
-				/* ... and feeling fine!!!! */
-				rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, uniqid = %x.\n", p->RIOHosts[p->RIONumHosts].UniqueNum);
-				if (RIOAssignAT(p, hp->PaddrP, hp->Caddr, 0)) {
-					rio_dprintk(RIO_DEBUG_PROBE, "Hmm Tested ok, host%d uniqid = %x.\n", p->RIONumHosts, p->RIOHosts[p->RIONumHosts - 1].UniqueNum);
-					okboard++;
-					found++;
-				}
-			}
-
-			if (!okboard) {
-				iounmap(hp->Caddr);
-				hp->Caddr = NULL;
-			}
-		}
-	}
-
-
-	for (i = 0; i < p->RIONumHosts; i++) {
-		hp = &p->RIOHosts[i];
-		if (hp->Ivec) {
-			int mode = IRQF_SHARED;
-			if (hp->Ivec & 0x8000) {
-				mode = 0;
-				hp->Ivec &= 0x7fff;
-			}
-			rio_dprintk(RIO_DEBUG_INIT, "Requesting interrupt hp: %p rio_interrupt: %d Mode: %x\n", hp, hp->Ivec, hp->Mode);
-			retval = request_irq(hp->Ivec, rio_interrupt, mode, "rio", hp);
-			rio_dprintk(RIO_DEBUG_INIT, "Return value from request_irq: %d\n", retval);
-			if (retval) {
-				printk(KERN_ERR "rio: Cannot allocate irq %d.\n", hp->Ivec);
-				hp->Ivec = 0;
-			}
-			rio_dprintk(RIO_DEBUG_INIT, "Got irq %d.\n", hp->Ivec);
-			if (hp->Ivec != 0) {
-				rio_dprintk(RIO_DEBUG_INIT, "Enabling interrupts on rio card.\n");
-				hp->Mode |= RIO_PCI_INT_ENABLE;
-			} else
-				hp->Mode &= ~RIO_PCI_INT_ENABLE;
-			rio_dprintk(RIO_DEBUG_INIT, "New Mode: %x\n", hp->Mode);
-			rio_start_card_running(hp);
-		}
-		/* Init the timer "always" to make sure that it can safely be
-		   deleted when we unload... */
-
-		setup_timer(&hp->timer, rio_pollfunc, i);
-		if (!hp->Ivec) {
-			rio_dprintk(RIO_DEBUG_INIT, "Starting polling at %dj intervals.\n", rio_poll);
-			mod_timer(&hp->timer, jiffies + rio_poll);
-		}
-	}
-
-	if (found) {
-		rio_dprintk(RIO_DEBUG_INIT, "rio: total of %d boards detected.\n", found);
-		rio_init_drivers();
-	} else {
-		/* deregister the misc device we created earlier */
-		misc_deregister(&rio_fw_device);
-	}
-
-	func_exit();
-	return found ? 0 : -EIO;
-}
-
-
-static void __exit rio_exit(void)
-{
-	int i;
-	struct Host *hp;
-
-	func_enter();
-
-	for (i = 0, hp = p->RIOHosts; i < p->RIONumHosts; i++, hp++) {
-		RIOHostReset(hp->Type, hp->CardP, hp->Slot);
-		if (hp->Ivec) {
-			free_irq(hp->Ivec, hp);
-			rio_dprintk(RIO_DEBUG_INIT, "freed irq %d.\n", hp->Ivec);
-		}
-		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer_sync(&hp->timer);
-		if (hp->Caddr)
-			iounmap(hp->Caddr);
-		if (hp->Type == RIO_PCI)
-			pci_dev_put(hp->pdev);
-	}
-
-	if (misc_deregister(&rio_fw_device) < 0) {
-		printk(KERN_INFO "rio: couldn't deregister control-device\n");
-	}
-
-
-	rio_dprintk(RIO_DEBUG_CLEANUP, "Cleaning up drivers\n");
-
-	rio_release_drivers();
-
-	/* Release dynamically allocated memory */
-	kfree(p->RIOPortp);
-	kfree(p->RIOHosts);
-	kfree(p);
-
-	func_exit();
-}
-
-module_init(rio_init);
-module_exit(rio_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rio_linux.h linux-libre-2.6.39-gnu/drivers/char/rio/rio_linux.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/rio_linux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rio_linux.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,197 +0,0 @@
-
-/*
- *  rio_linux.h
- *
- *  Copyright (C) 1998,1999,2000 R.E.Wolff@BitWizard.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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  RIO serial driver.
- *
- *  Version 1.0 -- July, 1999. 
- * 
- */
-
-#define RIO_NBOARDS        4
-#define RIO_PORTSPERBOARD 128
-#define RIO_NPORTS        (RIO_NBOARDS * RIO_PORTSPERBOARD)
-
-#define MODEM_SUPPORT
-
-#ifdef __KERNEL__
-
-#define RIO_MAGIC 0x12345678
-
-
-struct vpd_prom {
-	unsigned short id;
-	char hwrev;
-	char hwass;
-	int uniqid;
-	char myear;
-	char mweek;
-	char hw_feature[5];
-	char oem_id;
-	char identifier[16];
-};
-
-
-#define RIO_DEBUG_ALL           0xffffffff
-
-#define O_OTHER(tty)    \
-      ((O_OLCUC(tty))  ||\
-      (O_ONLCR(tty))   ||\
-      (O_OCRNL(tty))   ||\
-      (O_ONOCR(tty))   ||\
-      (O_ONLRET(tty))  ||\
-      (O_OFILL(tty))   ||\
-      (O_OFDEL(tty))   ||\
-      (O_NLDLY(tty))   ||\
-      (O_CRDLY(tty))   ||\
-      (O_TABDLY(tty))  ||\
-      (O_BSDLY(tty))   ||\
-      (O_VTDLY(tty))   ||\
-      (O_FFDLY(tty)))
-
-/* Same for input. */
-#define I_OTHER(tty)    \
-      ((I_INLCR(tty))  ||\
-      (I_IGNCR(tty))   ||\
-      (I_ICRNL(tty))   ||\
-      (I_IUCLC(tty))   ||\
-      (L_ISIG(tty)))
-
-
-#endif				/* __KERNEL__ */
-
-
-#define RIO_BOARD_INTR_LOCK  1
-
-
-#ifndef RIOCTL_MISC_MINOR
-/* Allow others to gather this into "major.h" or something like that */
-#define RIOCTL_MISC_MINOR    169
-#endif
-
-
-/* Allow us to debug "in the field" without requiring clients to
-   recompile.... */
-#if 1
-#define rio_spin_lock_irqsave(sem, flags) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlockirqsave: %p %s:%d\n", \
-	                                sem, __FILE__, __LINE__);\
-	spin_lock_irqsave(sem, flags);\
-	} while (0)
-
-#define rio_spin_unlock_irqrestore(sem, flags) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlockirqrestore: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_unlock_irqrestore(sem, flags);\
-	} while (0)
-
-#define rio_spin_lock(sem) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinlock: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_lock(sem);\
-	} while (0)
-
-#define rio_spin_unlock(sem) do { \
-	rio_dprintk (RIO_DEBUG_SPINLOCK, "spinunlock: %p %s:%d\n",\
-	                                sem, __FILE__, __LINE__);\
-	spin_unlock(sem);\
-	} while (0)
-#else
-#define rio_spin_lock_irqsave(sem, flags) \
-            spin_lock_irqsave(sem, flags)
-
-#define rio_spin_unlock_irqrestore(sem, flags) \
-            spin_unlock_irqrestore(sem, flags)
-
-#define rio_spin_lock(sem) \
-            spin_lock(sem)
-
-#define rio_spin_unlock(sem) \
-            spin_unlock(sem)
-
-#endif
-
-
-
-#ifdef CONFIG_RIO_OLDPCI
-static inline void __iomem *rio_memcpy_toio(void __iomem *dummy, void __iomem *dest, void *source, int n)
-{
-	char __iomem *dst = dest;
-	char *src = source;
-
-	while (n--) {
-		writeb(*src++, dst++);
-		(void) readb(dummy);
-	}
-
-	return dest;
-}
-
-static inline void __iomem *rio_copy_toio(void __iomem *dest, void *source, int n)
-{
-	char __iomem *dst = dest;
-	char *src = source;
-
-	while (n--)
-		writeb(*src++, dst++);
-
-	return dest;
-}
-
-
-static inline void *rio_memcpy_fromio(void *dest, void __iomem *source, int n)
-{
-	char *dst = dest;
-	char __iomem *src = source;
-
-	while (n--)
-		*dst++ = readb(src++);
-
-	return dest;
-}
-
-#else
-#define rio_memcpy_toio(dummy,dest,source,n)   memcpy_toio(dest, source, n)
-#define rio_copy_toio   		       memcpy_toio
-#define rio_memcpy_fromio                      memcpy_fromio
-#endif
-
-#define DEBUG 1
-
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-
-#ifdef DEBUG
-#define rio_dprintk(f, str...) do { if (rio_debug & f) printk (str);} while (0)
-#define func_enter() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s\n", __func__)
-#define func_exit()  rio_dprintk (RIO_DEBUG_FLOW, "rio: exit  %s\n", __func__)
-#define func_enter2() rio_dprintk (RIO_DEBUG_FLOW, "rio: enter %s (port %d)\n",__func__, port->line)
-#else
-#define rio_dprintk(f, str...)	/* nothing */
-#define func_enter()
-#define func_exit()
-#define func_enter2()
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioparam.c linux-libre-2.6.39-gnu/drivers/char/rio/rioparam.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioparam.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioparam.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,663 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioparam.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:45
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)rioparam.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-
-
-/*
-** The Scam, based on email from jeremyr@bugs.specialix.co.uk....
-**
-** To send a command on a particular port, you put a packet with the
-** command bit set onto the port. The command bit is in the len field,
-** and gets ORed in with the actual byte count.
-**
-** When you send a packet with the command bit set the first
-** data byte (data[0]) is interpreted as the command to execute.
-** It also governs what data structure overlay should accompany the packet.
-** Commands are defined in cirrus/cirrus.h
-**
-** If you want the command to pre-emt data already on the queue for the
-** port, set the pre-emptive bit in conjunction with the command bit.
-** It is not defined what will happen if you set the preemptive bit
-** on a packet that is NOT a command.
-**
-** Pre-emptive commands should be queued at the head of the queue using
-** add_start(), whereas normal commands and data are enqueued using
-** add_end().
-**
-** Most commands do not use the remaining bytes in the data array. The
-** exceptions are OPEN MOPEN and CONFIG. (NB. As with the SI CONFIG and
-** OPEN are currently analogous). With these three commands the following
-** 11 data bytes are all used to pass config information such as baud rate etc.
-** The fields are also defined in cirrus.h. Some contain straightforward
-** information such as the transmit XON character. Two contain the transmit and
-** receive baud rates respectively. For most baud rates there is a direct
-** mapping between the rates defined in <sys/termio.h> and the byte in the
-** packet. There are additional (non UNIX-standard) rates defined in
-** /u/dos/rio/cirrus/h/brates.h.
-**
-** The rest of the data fields contain approximations to the Cirrus registers
-** that are used to program number of bits etc. Each registers bit fields is
-** defined in cirrus.h.
-** 
-** NB. Only use those bits that are defined as being driver specific
-** or common to the RTA and the driver.
-** 
-** All commands going from RTA->Host will be dealt with by the Host code - you
-** will never see them. As with the SI there will be three fields to look out
-** for in each phb (not yet defined - needs defining a.s.a.p).
-** 
-** modem_status	- current state of handshake pins.
-**
-** port_status	 - current port status - equivalent to hi_stat for SI, indicates
-** if port is IDLE_OPEN, IDLE_CLOSED etc.
-**
-** break_status	- bit X set if break has been received.
-** 
-** Happy hacking.
-** 
-*/
-
-/* 
-** RIOParam is used to open or configure a port. You pass it a PortP,
-** which will have a tty struct attached to it. You also pass a command,
-** either OPEN or CONFIG. The port's setup is taken from the t_ fields
-** of the tty struct inside the PortP, and the port is either opened
-** or re-configured. You must also tell RIOParam if the device is a modem
-** device or not (i.e. top bit of minor number set or clear - take special
-** care when deciding on this!).
-** RIOParam neither flushes nor waits for drain, and is NOT preemptive.
-**
-** RIOParam assumes it will be called at splrio(), and also assumes
-** that CookMode is set correctly in the port structure.
-**
-** NB. for MPX
-**	tty lock must NOT have been previously acquired.
-*/
-int RIOParam(struct Port *PortP, int cmd, int Modem, int SleepFlag)
-{
-	struct tty_struct *TtyP;
-	int retval;
-	struct phb_param __iomem *phb_param_ptr;
-	struct PKT __iomem *PacketP;
-	int res;
-	u8 Cor1 = 0, Cor2 = 0, Cor4 = 0, Cor5 = 0;
-	u8 TxXon = 0, TxXoff = 0, RxXon = 0, RxXoff = 0;
-	u8 LNext = 0, TxBaud = 0, RxBaud = 0;
-	int retries = 0xff;
-	unsigned long flags;
-
-	func_enter();
-
-	TtyP = PortP->gs.port.tty;
-
-	rio_dprintk(RIO_DEBUG_PARAM, "RIOParam: Port:%d cmd:%d Modem:%d SleepFlag:%d Mapped: %d, tty=%p\n", PortP->PortNum, cmd, Modem, SleepFlag, PortP->Mapped, TtyP);
-
-	if (!TtyP) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Can't call rioparam with null tty.\n");
-
-		func_exit();
-
-		return RIO_FAIL;
-	}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	if (cmd == RIOC_OPEN) {
-		/*
-		 ** If the port is set to store or lock the parameters, and it is
-		 ** paramed with OPEN, we want to restore the saved port termio, but
-		 ** only if StoredTermio has been saved, i.e. NOT 1st open after reboot.
-		 */
-	}
-
-	/*
-	 ** wait for space
-	 */
-	while (!(res = can_add_transmit(&PacketP, PortP)) || (PortP->InUse != NOT_INUSE)) {
-		if (retries-- <= 0) {
-			break;
-		}
-		if (PortP->InUse != NOT_INUSE) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Port IN_USE for pre-emptive command\n");
-		}
-
-		if (!res) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Port has no space on transmit queue\n");
-		}
-
-		if (SleepFlag != OK_TO_SLEEP) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-
-			return RIO_FAIL;
-		}
-
-		rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		retval = RIODelay(PortP, HUNDRED_MS);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		if (retval == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_PARAM, "wait for can_add_transmit broken by signal\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-			return -EINTR;
-		}
-		if (PortP->State & RIO_DELETED) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			func_exit();
-			return 0;
-		}
-	}
-
-	if (!res) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		func_exit();
-
-		return RIO_FAIL;
-	}
-
-	rio_dprintk(RIO_DEBUG_PARAM, "can_add_transmit() returns %x\n", res);
-	rio_dprintk(RIO_DEBUG_PARAM, "Packet is %p\n", PacketP);
-
-	phb_param_ptr = (struct phb_param __iomem *) PacketP->data;
-
-
-	switch (TtyP->termios->c_cflag & CSIZE) {
-	case CS5:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "5 bit data\n");
-			Cor1 |= RIOC_COR1_5BITS;
-			break;
-		}
-	case CS6:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "6 bit data\n");
-			Cor1 |= RIOC_COR1_6BITS;
-			break;
-		}
-	case CS7:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "7 bit data\n");
-			Cor1 |= RIOC_COR1_7BITS;
-			break;
-		}
-	case CS8:
-		{
-			rio_dprintk(RIO_DEBUG_PARAM, "8 bit data\n");
-			Cor1 |= RIOC_COR1_8BITS;
-			break;
-		}
-	}
-
-	if (TtyP->termios->c_cflag & CSTOPB) {
-		rio_dprintk(RIO_DEBUG_PARAM, "2 stop bits\n");
-		Cor1 |= RIOC_COR1_2STOP;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "1 stop bit\n");
-		Cor1 |= RIOC_COR1_1STOP;
-	}
-
-	if (TtyP->termios->c_cflag & PARENB) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable parity\n");
-		Cor1 |= RIOC_COR1_NORMAL;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Disable parity\n");
-		Cor1 |= RIOC_COR1_NOP;
-	}
-	if (TtyP->termios->c_cflag & PARODD) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Odd parity\n");
-		Cor1 |= RIOC_COR1_ODD;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Even parity\n");
-		Cor1 |= RIOC_COR1_EVEN;
-	}
-
-	/*
-	 ** COR 2
-	 */
-	if (TtyP->termios->c_iflag & IXON) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop output control\n");
-		Cor2 |= RIOC_COR2_IXON;
-	} else {
-		if (PortP->Config & RIO_IXON) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Force enable start/stop output control\n");
-			Cor2 |= RIOC_COR2_IXON;
-		} else
-			rio_dprintk(RIO_DEBUG_PARAM, "IXON has been disabled.\n");
-	}
-
-	if (TtyP->termios->c_iflag & IXANY) {
-		if (PortP->Config & RIO_IXANY) {
-			rio_dprintk(RIO_DEBUG_PARAM, "Enable any key to restart output\n");
-			Cor2 |= RIOC_COR2_IXANY;
-		} else
-			rio_dprintk(RIO_DEBUG_PARAM, "IXANY has been disabled due to sanity reasons.\n");
-	}
-
-	if (TtyP->termios->c_iflag & IXOFF) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable start/stop input control 2\n");
-		Cor2 |= RIOC_COR2_IXOFF;
-	}
-
-	if (TtyP->termios->c_cflag & HUPCL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Hangup on last close\n");
-		Cor2 |= RIOC_COR2_HUPCL;
-	}
-
-	if (C_CRTSCTS(TtyP)) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control enabled\n");
-		Cor2 |= RIOC_COR2_CTSFLOW;
-		Cor2 |= RIOC_COR2_RTSFLOW;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Rx hardware flow control disabled\n");
-		Cor2 &= ~RIOC_COR2_CTSFLOW;
-		Cor2 &= ~RIOC_COR2_RTSFLOW;
-	}
-
-
-	if (TtyP->termios->c_cflag & CLOCAL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Local line\n");
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Possible Modem line\n");
-	}
-
-	/*
-	 ** COR 4 (there is no COR 3)
-	 */
-	if (TtyP->termios->c_iflag & IGNBRK) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore break condition\n");
-		Cor4 |= RIOC_COR4_IGNBRK;
-	}
-	if (!(TtyP->termios->c_iflag & BRKINT)) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Break generates NULL condition\n");
-		Cor4 |= RIOC_COR4_NBRKINT;
-	} else {
-		rio_dprintk(RIO_DEBUG_PARAM, "Interrupt on	break condition\n");
-	}
-
-	if (TtyP->termios->c_iflag & INLCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage return on input\n");
-		Cor4 |= RIOC_COR4_INLCR;
-	}
-
-	if (TtyP->termios->c_iflag & IGNCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore carriage return on input\n");
-		Cor4 |= RIOC_COR4_IGNCR;
-	}
-
-	if (TtyP->termios->c_iflag & ICRNL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on input\n");
-		Cor4 |= RIOC_COR4_ICRNL;
-	}
-	if (TtyP->termios->c_iflag & IGNPAR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Ignore characters with parity errors\n");
-		Cor4 |= RIOC_COR4_IGNPAR;
-	}
-	if (TtyP->termios->c_iflag & PARMRK) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Mark parity errors\n");
-		Cor4 |= RIOC_COR4_PARMRK;
-	}
-
-	/*
-	 ** Set the RAISEMOD flag to ensure that the modem lines are raised
-	 ** on reception of a config packet.
-	 ** The download code handles the zero baud condition.
-	 */
-	Cor4 |= RIOC_COR4_RAISEMOD;
-
-	/*
-	 ** COR 5
-	 */
-
-	Cor5 = RIOC_COR5_CMOE;
-
-	/*
-	 ** Set to monitor tbusy/tstop (or not).
-	 */
-
-	if (PortP->MonitorTstate)
-		Cor5 |= RIOC_COR5_TSTATE_ON;
-	else
-		Cor5 |= RIOC_COR5_TSTATE_OFF;
-
-	/*
-	 ** Could set LNE here if you wanted LNext processing. SVR4 will use it.
-	 */
-	if (TtyP->termios->c_iflag & ISTRIP) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Strip input characters\n");
-		if (!(PortP->State & RIO_TRIAD_MODE)) {
-			Cor5 |= RIOC_COR5_ISTRIP;
-		}
-	}
-
-	if (TtyP->termios->c_oflag & ONLCR) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map newline to carriage-return, newline on output\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_ONLCR;
-	}
-	if (TtyP->termios->c_oflag & OCRNL) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Map carriage return to newline on output\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_OCRNL;
-	}
-	if ((TtyP->termios->c_oflag & TABDLY) == TAB3) {
-		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay 3 set\n");
-		if (PortP->CookMode == COOK_MEDIUM)
-			Cor5 |= RIOC_COR5_TAB3;
-	}
-
-	/*
-	 ** Flow control bytes.
-	 */
-	TxXon = TtyP->termios->c_cc[VSTART];
-	TxXoff = TtyP->termios->c_cc[VSTOP];
-	RxXon = TtyP->termios->c_cc[VSTART];
-	RxXoff = TtyP->termios->c_cc[VSTOP];
-	/*
-	 ** LNEXT byte
-	 */
-	LNext = 0;
-
-	/*
-	 ** Baud rate bytes
-	 */
-	rio_dprintk(RIO_DEBUG_PARAM, "Mapping of rx/tx baud %x (%x)\n", TtyP->termios->c_cflag, CBAUD);
-
-	switch (TtyP->termios->c_cflag & CBAUD) {
-#define e(b) case B ## b : RxBaud = TxBaud = RIO_B ## b ;break
-		e(50);
-		e(75);
-		e(110);
-		e(134);
-		e(150);
-		e(200);
-		e(300);
-		e(600);
-		e(1200);
-		e(1800);
-		e(2400);
-		e(4800);
-		e(9600);
-		e(19200);
-		e(38400);
-		e(57600);
-		e(115200);	/* e(230400);e(460800); e(921600);  */
-	}
-
-	rio_dprintk(RIO_DEBUG_PARAM, "tx baud 0x%x, rx baud 0x%x\n", TxBaud, RxBaud);
-
-
-	/*
-	 ** Leftovers
-	 */
-	if (TtyP->termios->c_cflag & CREAD)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable receiver\n");
-#ifdef RCV1EN
-	if (TtyP->termios->c_cflag & RCV1EN)
-		rio_dprintk(RIO_DEBUG_PARAM, "RCV1EN (?)\n");
-#endif
-#ifdef XMT1EN
-	if (TtyP->termios->c_cflag & XMT1EN)
-		rio_dprintk(RIO_DEBUG_PARAM, "XMT1EN (?)\n");
-#endif
-	if (TtyP->termios->c_lflag & ISIG)
-		rio_dprintk(RIO_DEBUG_PARAM, "Input character signal generating enabled\n");
-	if (TtyP->termios->c_lflag & ICANON)
-		rio_dprintk(RIO_DEBUG_PARAM, "Canonical input: erase and kill enabled\n");
-	if (TtyP->termios->c_lflag & XCASE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Canonical upper/lower presentation\n");
-	if (TtyP->termios->c_lflag & ECHO)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable input echo\n");
-	if (TtyP->termios->c_lflag & ECHOE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo erase\n");
-	if (TtyP->termios->c_lflag & ECHOK)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo kill\n");
-	if (TtyP->termios->c_lflag & ECHONL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable echo newline\n");
-	if (TtyP->termios->c_lflag & NOFLSH)
-		rio_dprintk(RIO_DEBUG_PARAM, "Disable flush after interrupt or quit\n");
-#ifdef TOSTOP
-	if (TtyP->termios->c_lflag & TOSTOP)
-		rio_dprintk(RIO_DEBUG_PARAM, "Send SIGTTOU for background output\n");
-#endif
-#ifdef XCLUDE
-	if (TtyP->termios->c_lflag & XCLUDE)
-		rio_dprintk(RIO_DEBUG_PARAM, "Exclusive use of this line\n");
-#endif
-	if (TtyP->termios->c_iflag & IUCLC)
-		rio_dprintk(RIO_DEBUG_PARAM, "Map uppercase to lowercase on input\n");
-	if (TtyP->termios->c_oflag & OPOST)
-		rio_dprintk(RIO_DEBUG_PARAM, "Enable output post-processing\n");
-	if (TtyP->termios->c_oflag & OLCUC)
-		rio_dprintk(RIO_DEBUG_PARAM, "Map lowercase to uppercase on output\n");
-	if (TtyP->termios->c_oflag & ONOCR)
-		rio_dprintk(RIO_DEBUG_PARAM, "No carriage return output at column 0\n");
-	if (TtyP->termios->c_oflag & ONLRET)
-		rio_dprintk(RIO_DEBUG_PARAM, "Newline performs carriage return function\n");
-	if (TtyP->termios->c_oflag & OFILL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Use fill characters for delay\n");
-	if (TtyP->termios->c_oflag & OFDEL)
-		rio_dprintk(RIO_DEBUG_PARAM, "Fill character is DEL\n");
-	if (TtyP->termios->c_oflag & NLDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Newline delay set\n");
-	if (TtyP->termios->c_oflag & CRDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Carriage return delay set\n");
-	if (TtyP->termios->c_oflag & TABDLY)
-		rio_dprintk(RIO_DEBUG_PARAM, "Tab delay set\n");
-	/*
-	 ** These things are kind of useful in a later life!
-	 */
-	PortP->Cor2Copy = Cor2;
-
-	if (PortP->State & RIO_DELETED) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		func_exit();
-
-		return RIO_FAIL;
-	}
-
-	/*
-	 ** Actually write the info into the packet to be sent
-	 */
-	writeb(cmd, &phb_param_ptr->Cmd);
-	writeb(Cor1, &phb_param_ptr->Cor1);
-	writeb(Cor2, &phb_param_ptr->Cor2);
-	writeb(Cor4, &phb_param_ptr->Cor4);
-	writeb(Cor5, &phb_param_ptr->Cor5);
-	writeb(TxXon, &phb_param_ptr->TxXon);
-	writeb(RxXon, &phb_param_ptr->RxXon);
-	writeb(TxXoff, &phb_param_ptr->TxXoff);
-	writeb(RxXoff, &phb_param_ptr->RxXoff);
-	writeb(LNext, &phb_param_ptr->LNext);
-	writeb(TxBaud, &phb_param_ptr->TxBaud);
-	writeb(RxBaud, &phb_param_ptr->RxBaud);
-
-	/*
-	 ** Set the length/command field
-	 */
-	writeb(12 | PKT_CMD_BIT, &PacketP->len);
-
-	/*
-	 ** The packet is formed - now, whack it off
-	 ** to its final destination:
-	 */
-	add_transmit(PortP);
-	/*
-	 ** Count characters transmitted for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->txchars += 12;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	rio_dprintk(RIO_DEBUG_PARAM, "add_transmit returned.\n");
-	/*
-	 ** job done.
-	 */
-	func_exit();
-
-	return 0;
-}
-
-
-/*
-** We can add another packet to a transmit queue if the packet pointer pointed
-** to by the TxAdd pointer has PKT_IN_USE clear in its address.
-*/
-int can_add_transmit(struct PKT __iomem **PktP, struct Port *PortP)
-{
-	struct PKT __iomem *tp;
-
-	*PktP = tp = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->TxAdd));
-
-	return !((unsigned long) tp & PKT_IN_USE);
-}
-
-/*
-** To add a packet to the queue, you set the PKT_IN_USE bit in the address,
-** and then move the TxAdd pointer along one position to point to the next
-** packet pointer. You must wrap the pointer from the end back to the start.
-*/
-void add_transmit(struct Port *PortP)
-{
-	if (readw(PortP->TxAdd) & PKT_IN_USE) {
-		rio_dprintk(RIO_DEBUG_PARAM, "add_transmit: Packet has been stolen!");
-	}
-	writew(readw(PortP->TxAdd) | PKT_IN_USE, PortP->TxAdd);
-	PortP->TxAdd = (PortP->TxAdd == PortP->TxEnd) ? PortP->TxStart : PortP->TxAdd + 1;
-	writew(RIO_OFF(PortP->Caddr, PortP->TxAdd), &PortP->PhbP->tx_add);
-}
-
-/****************************************
- * Put a packet onto the end of the
- * free list
- ****************************************/
-void put_free_end(struct Host *HostP, struct PKT __iomem *PktP)
-{
-	struct rio_free_list __iomem *tmp_pointer;
-	unsigned short old_end, new_end;
-	unsigned long flags;
-
-	rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-	 /*************************************************
-	* Put a packet back onto the back of the free list
-	*
-	************************************************/
-
-	rio_dprintk(RIO_DEBUG_PFE, "put_free_end(PktP=%p)\n", PktP);
-
-	if ((old_end = readw(&HostP->ParmMapP->free_list_end)) != TPNULL) {
-		new_end = RIO_OFF(HostP->Caddr, PktP);
-		tmp_pointer = (struct rio_free_list __iomem *) RIO_PTR(HostP->Caddr, old_end);
-		writew(new_end, &tmp_pointer->next);
-		writew(old_end, &((struct rio_free_list __iomem *) PktP)->prev);
-		writew(TPNULL, &((struct rio_free_list __iomem *) PktP)->next);
-		writew(new_end, &HostP->ParmMapP->free_list_end);
-	} else {		/* First packet on the free list this should never happen! */
-		rio_dprintk(RIO_DEBUG_PFE, "put_free_end(): This should never happen\n");
-		writew(RIO_OFF(HostP->Caddr, PktP), &HostP->ParmMapP->free_list_end);
-		tmp_pointer = (struct rio_free_list __iomem *) PktP;
-		writew(TPNULL, &tmp_pointer->prev);
-		writew(TPNULL, &tmp_pointer->next);
-	}
-	rio_dprintk(RIO_DEBUG_CMD, "Before unlock: %p\n", &HostP->HostLock);
-	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-}
-
-/*
-** can_remove_receive(PktP,P) returns non-zero if PKT_IN_USE is set
-** for the next packet on the queue. It will also set PktP to point to the
-** relevant packet, [having cleared the PKT_IN_USE bit]. If PKT_IN_USE is clear,
-** then can_remove_receive() returns 0.
-*/
-int can_remove_receive(struct PKT __iomem **PktP, struct Port *PortP)
-{
-	if (readw(PortP->RxRemove) & PKT_IN_USE) {
-		*PktP = (struct PKT __iomem *) RIO_PTR(PortP->Caddr, readw(PortP->RxRemove) & ~PKT_IN_USE);
-		return 1;
-	}
-	return 0;
-}
-
-/*
-** To remove a packet from the receive queue you clear its PKT_IN_USE bit,
-** and then bump the pointers. Once the pointers get to the end, they must
-** be wrapped back to the start.
-*/
-void remove_receive(struct Port *PortP)
-{
-	writew(readw(PortP->RxRemove) & ~PKT_IN_USE, PortP->RxRemove);
-	PortP->RxRemove = (PortP->RxRemove == PortP->RxEnd) ? PortP->RxStart : PortP->RxRemove + 1;
-	writew(RIO_OFF(PortP->Caddr, PortP->RxRemove), &PortP->PhbP->rx_remove);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rioroute.c linux-libre-2.6.39-gnu/drivers/char/rio/rioroute.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/rioroute.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rioroute.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1039 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: rioroute.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:46
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)rioroute.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-static int RIOCheckIsolated(struct rio_info *, struct Host *, unsigned int);
-static int RIOIsolate(struct rio_info *, struct Host *, unsigned int);
-static int RIOCheck(struct Host *, unsigned int);
-static void RIOConCon(struct rio_info *, struct Host *, unsigned int, unsigned int, unsigned int, unsigned int, int);
-
-
-/*
-** Incoming on the ROUTE_RUP
-** I wrote this while I was tired. Forgive me.
-*/
-int RIORouteRup(struct rio_info *p, unsigned int Rup, struct Host *HostP, struct PKT __iomem * PacketP)
-{
-	struct PktCmd __iomem *PktCmdP = (struct PktCmd __iomem *) PacketP->data;
-	struct PktCmd_M *PktReplyP;
-	struct CmdBlk *CmdBlkP;
-	struct Port *PortP;
-	struct Map *MapP;
-	struct Top *TopP;
-	int ThisLink, ThisLinkMin, ThisLinkMax;
-	int port;
-	int Mod, Mod1, Mod2;
-	unsigned short RtaType;
-	unsigned int RtaUniq;
-	unsigned int ThisUnit, ThisUnit2;	/* 2 ids to accommodate 16 port RTA */
-	unsigned int OldUnit, NewUnit, OldLink, NewLink;
-	char *MyType, *MyName;
-	int Lies;
-	unsigned long flags;
-
-	/*
-	 ** Is this unit telling us it's current link topology?
-	 */
-	if (readb(&PktCmdP->Command) == ROUTE_TOPOLOGY) {
-		MapP = HostP->Mapping;
-
-		/*
-		 ** The packet can be sent either by the host or by an RTA.
-		 ** If it comes from the host, then we need to fill in the
-		 ** Topology array in the host structure. If it came in
-		 ** from an RTA then we need to fill in the Mapping structure's
-		 ** Topology array for the unit.
-		 */
-		if (Rup >= (unsigned short) MAX_RUP) {
-			ThisUnit = HOST_ID;
-			TopP = HostP->Topology;
-			MyType = "Host";
-			MyName = HostP->Name;
-			ThisLinkMin = ThisLinkMax = Rup - MAX_RUP;
-		} else {
-			ThisUnit = Rup + 1;
-			TopP = HostP->Mapping[Rup].Topology;
-			MyType = "RTA";
-			MyName = HostP->Mapping[Rup].Name;
-			ThisLinkMin = 0;
-			ThisLinkMax = LINKS_PER_UNIT - 1;
-		}
-
-		/*
-		 ** Lies will not be tolerated.
-		 ** If any pair of links claim to be connected to the same
-		 ** place, then ignore this packet completely.
-		 */
-		Lies = 0;
-		for (ThisLink = ThisLinkMin + 1; ThisLink <= ThisLinkMax; ThisLink++) {
-			/*
-			 ** it won't lie about network interconnect, total disconnects
-			 ** and no-IDs. (or at least, it doesn't *matter* if it does)
-			 */
-			if (readb(&PktCmdP->RouteTopology[ThisLink].Unit) > (unsigned short) MAX_RUP)
-				continue;
-
-			for (NewLink = ThisLinkMin; NewLink < ThisLink; NewLink++) {
-				if ((readb(&PktCmdP->RouteTopology[ThisLink].Unit) == readb(&PktCmdP->RouteTopology[NewLink].Unit)) && (readb(&PktCmdP->RouteTopology[ThisLink].Link) == readb(&PktCmdP->RouteTopology[NewLink].Link))) {
-					Lies++;
-				}
-			}
-		}
-
-		if (Lies) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "LIES! DAMN LIES! %d LIES!\n", Lies);
-			rio_dprintk(RIO_DEBUG_ROUTE, "%d:%c %d:%c %d:%c %d:%c\n",
-				    readb(&PktCmdP->RouteTopology[0].Unit),
-				    'A' + readb(&PktCmdP->RouteTopology[0].Link),
-				    readb(&PktCmdP->RouteTopology[1].Unit),
-				    'A' + readb(&PktCmdP->RouteTopology[1].Link), readb(&PktCmdP->RouteTopology[2].Unit), 'A' + readb(&PktCmdP->RouteTopology[2].Link), readb(&PktCmdP->RouteTopology[3].Unit), 'A' + readb(&PktCmdP->RouteTopology[3].Link));
-			return 1;
-		}
-
-		/*
-		 ** now, process each link.
-		 */
-		for (ThisLink = ThisLinkMin; ThisLink <= ThisLinkMax; ThisLink++) {
-			/*
-			 ** this is what it was connected to
-			 */
-			OldUnit = TopP[ThisLink].Unit;
-			OldLink = TopP[ThisLink].Link;
-
-			/*
-			 ** this is what it is now connected to
-			 */
-			NewUnit = readb(&PktCmdP->RouteTopology[ThisLink].Unit);
-			NewLink = readb(&PktCmdP->RouteTopology[ThisLink].Link);
-
-			if (OldUnit != NewUnit || OldLink != NewLink) {
-				/*
-				 ** something has changed!
-				 */
-
-				if (NewUnit > MAX_RUP && NewUnit != ROUTE_DISCONNECT && NewUnit != ROUTE_NO_ID && NewUnit != ROUTE_INTERCONNECT) {
-					rio_dprintk(RIO_DEBUG_ROUTE, "I have a link from %s %s to unit %d:%d - I don't like it.\n", MyType, MyName, NewUnit, NewLink);
-				} else {
-					/*
-					 ** put the new values in
-					 */
-					TopP[ThisLink].Unit = NewUnit;
-					TopP[ThisLink].Link = NewLink;
-
-					RIOSetChange(p);
-
-					if (OldUnit <= MAX_RUP) {
-						/*
-						 ** If something has become bust, then re-enable them messages
-						 */
-						if (!p->RIONoMessage)
-							RIOConCon(p, HostP, ThisUnit, ThisLink, OldUnit, OldLink, DISCONNECT);
-					}
-
-					if ((NewUnit <= MAX_RUP) && !p->RIONoMessage)
-						RIOConCon(p, HostP, ThisUnit, ThisLink, NewUnit, NewLink, CONNECT);
-
-					if (NewUnit == ROUTE_NO_ID)
-						rio_dprintk(RIO_DEBUG_ROUTE, "%s %s (%c) is connected to an unconfigured unit.\n", MyType, MyName, 'A' + ThisLink);
-
-					if (NewUnit == ROUTE_INTERCONNECT) {
-						if (!p->RIONoMessage)
-							printk(KERN_DEBUG "rio: %s '%s' (%c) is connected to another network.\n", MyType, MyName, 'A' + ThisLink);
-					}
-
-					/*
-					 ** perform an update for 'the other end', so that these messages
-					 ** only appears once. Only disconnect the other end if it is pointing
-					 ** at us!
-					 */
-					if (OldUnit == HOST_ID) {
-						if (HostP->Topology[OldLink].Unit == ThisUnit && HostP->Topology[OldLink].Link == ThisLink) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING HOST (%c) TO DISCONNECTED!\n", OldLink + 'A');
-							HostP->Topology[OldLink].Unit = ROUTE_DISCONNECT;
-							HostP->Topology[OldLink].Link = NO_LINK;
-						} else {
-							rio_dprintk(RIO_DEBUG_ROUTE, "HOST(%c) WAS NOT CONNECTED TO %s (%c)!\n", OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
-						}
-					} else if (OldUnit <= MAX_RUP) {
-						if (HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit == ThisUnit && HostP->Mapping[OldUnit - 1].Topology[OldLink].Link == ThisLink) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "SETTING RTA %s (%c) TO DISCONNECTED!\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A');
-							HostP->Mapping[OldUnit - 1].Topology[OldLink].Unit = ROUTE_DISCONNECT;
-							HostP->Mapping[OldUnit - 1].Topology[OldLink].Link = NO_LINK;
-						} else {
-							rio_dprintk(RIO_DEBUG_ROUTE, "RTA %s (%c) WAS NOT CONNECTED TO %s (%c)\n", HostP->Mapping[OldUnit - 1].Name, OldLink + 'A', HostP->Mapping[ThisUnit - 1].Name, ThisLink + 'A');
-						}
-					}
-					if (NewUnit == HOST_ID) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING HOST (%c) CONNECTED TO %s (%c)\n", NewLink + 'A', MyName, ThisLink + 'A');
-						HostP->Topology[NewLink].Unit = ThisUnit;
-						HostP->Topology[NewLink].Link = ThisLink;
-					} else if (NewUnit <= MAX_RUP) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "MARKING RTA %s (%c) CONNECTED TO %s (%c)\n", HostP->Mapping[NewUnit - 1].Name, NewLink + 'A', MyName, ThisLink + 'A');
-						HostP->Mapping[NewUnit - 1].Topology[NewLink].Unit = ThisUnit;
-						HostP->Mapping[NewUnit - 1].Topology[NewLink].Link = ThisLink;
-					}
-				}
-				RIOSetChange(p);
-				RIOCheckIsolated(p, HostP, OldUnit);
-			}
-		}
-		return 1;
-	}
-
-	/*
-	 ** The only other command we recognise is a route_request command
-	 */
-	if (readb(&PktCmdP->Command) != ROUTE_REQUEST) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unknown command %d received on rup %d host %p ROUTE_RUP\n", readb(&PktCmdP->Command), Rup, HostP);
-		return 1;
-	}
-
-	RtaUniq = (readb(&PktCmdP->UniqNum[0])) + (readb(&PktCmdP->UniqNum[1]) << 8) + (readb(&PktCmdP->UniqNum[2]) << 16) + (readb(&PktCmdP->UniqNum[3]) << 24);
-
-	/*
-	 ** Determine if 8 or 16 port RTA
-	 */
-	RtaType = GetUnitType(RtaUniq);
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "Received a request for an ID for serial number %x\n", RtaUniq);
-
-	Mod = readb(&PktCmdP->ModuleTypes);
-	Mod1 = LONYBLE(Mod);
-	if (RtaType == TYPE_RTA16) {
-		/*
-		 ** Only one ident is set for a 16 port RTA. To make compatible
-		 ** with 8 port, set 2nd ident in Mod2 to the same as Mod1.
-		 */
-		Mod2 = Mod1;
-		rio_dprintk(RIO_DEBUG_ROUTE, "Backplane type is %s (all ports)\n", p->RIOModuleTypes[Mod1].Name);
-	} else {
-		Mod2 = HINYBLE(Mod);
-		rio_dprintk(RIO_DEBUG_ROUTE, "Module types are %s (ports 0-3) and %s (ports 4-7)\n", p->RIOModuleTypes[Mod1].Name, p->RIOModuleTypes[Mod2].Name);
-	}
-
-	/*
-	 ** try to unhook a command block from the command free list.
-	 */
-	if (!(CmdBlkP = RIOGetCmdBlk())) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "No command blocks to route RTA! come back later.\n");
-		return 0;
-	}
-
-	/*
-	 ** Fill in the default info on the command block
-	 */
-	CmdBlkP->Packet.dest_unit = Rup;
-	CmdBlkP->Packet.dest_port = ROUTE_RUP;
-	CmdBlkP->Packet.src_unit = HOST_ID;
-	CmdBlkP->Packet.src_port = ROUTE_RUP;
-	CmdBlkP->Packet.len = PKT_CMD_BIT | 1;
-	CmdBlkP->PreFuncP = CmdBlkP->PostFuncP = NULL;
-	PktReplyP = (struct PktCmd_M *) CmdBlkP->Packet.data;
-
-	if (!RIOBootOk(p, HostP, RtaUniq)) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "RTA %x tried to get an ID, but does not belong - FOAD it!\n", RtaUniq);
-		PktReplyP->Command = ROUTE_FOAD;
-		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-		RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-		return 1;
-	}
-
-	/*
-	 ** Check to see if the RTA is configured for this host
-	 */
-	for (ThisUnit = 0; ThisUnit < MAX_RUP; ThisUnit++) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Entry %d Flags=%s %s UniqueNum=0x%x\n",
-			    ThisUnit, HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE ? "Slot-In-Use" : "Not In Use", HostP->Mapping[ThisUnit].Flags & SLOT_TENTATIVE ? "Slot-Tentative" : "Not Tentative", HostP->Mapping[ThisUnit].RtaUniqueNum);
-
-		/*
-		 ** We have an entry for it.
-		 */
-		if ((HostP->Mapping[ThisUnit].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) && (HostP->Mapping[ThisUnit].RtaUniqueNum == RtaUniq)) {
-			if (RtaType == TYPE_RTA16) {
-				ThisUnit2 = HostP->Mapping[ThisUnit].ID2 - 1;
-				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slots %d+%d\n", RtaUniq, ThisUnit, ThisUnit2);
-			} else
-				rio_dprintk(RIO_DEBUG_ROUTE, "Found unit 0x%x at slot %d\n", RtaUniq, ThisUnit);
-			/*
-			 ** If we have no knowledge of booting it, then the host has
-			 ** been re-booted, and so we must kill the RTA, so that it
-			 ** will be booted again (potentially with new bins)
-			 ** and it will then re-ask for an ID, which we will service.
-			 */
-			if ((HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE) && !(HostP->Mapping[ThisUnit].Flags & RTA_BOOTED)) {
-				if (!(HostP->Mapping[ThisUnit].Flags & MSG_DONE)) {
-					if (!p->RIONoMessage)
-						printk(KERN_DEBUG "rio: RTA '%s' is being updated.\n", HostP->Mapping[ThisUnit].Name);
-					HostP->Mapping[ThisUnit].Flags |= MSG_DONE;
-				}
-				PktReplyP->Command = ROUTE_FOAD;
-				memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-				RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-				return 1;
-			}
-
-			/*
-			 ** Send the ID (entry) to this RTA. The ID number is implicit as
-			 ** the offset into the table. It is worth noting at this stage
-			 ** that offset zero in the table contains the entries for the
-			 ** RTA with ID 1!!!!
-			 */
-			PktReplyP->Command = ROUTE_ALLOCATE;
-			PktReplyP->IDNum = ThisUnit + 1;
-			if (RtaType == TYPE_RTA16) {
-				if (HostP->Mapping[ThisUnit].Flags & SLOT_IN_USE)
-					/*
-					 ** Adjust the phb and tx pkt dest_units for 2nd block of 8
-					 ** only if the RTA has ports associated (SLOT_IN_USE)
-					 */
-					RIOFixPhbs(p, HostP, ThisUnit2);
-				PktReplyP->IDNum2 = ThisUnit2 + 1;
-				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated IDs %d+%d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum, PktReplyP->IDNum2);
-			} else {
-				PktReplyP->IDNum2 = ROUTE_NO_ID;
-				rio_dprintk(RIO_DEBUG_ROUTE, "RTA '%s' has been allocated ID %d\n", HostP->Mapping[ThisUnit].Name, PktReplyP->IDNum);
-			}
-			memcpy(PktReplyP->CommandText, "RT_ALLOCAT", 10);
-
-			RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-
-			/*
-			 ** If this is a freshly booted RTA, then we need to re-open
-			 ** the ports, if any where open, so that data may once more
-			 ** flow around the system!
-			 */
-			if ((HostP->Mapping[ThisUnit].Flags & RTA_NEWBOOT) && (HostP->Mapping[ThisUnit].SysPort != NO_PORT)) {
-				/*
-				 ** look at the ports associated with this beast and
-				 ** see if any where open. If they was, then re-open
-				 ** them, using the info from the tty flags.
-				 */
-				for (port = 0; port < PORTS_PER_RTA; port++) {
-					PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort];
-					if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-						rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
-						rio_spin_lock_irqsave(&PortP->portSem, flags);
-						PortP->MagicFlags |= MAGIC_REBOOT;
-						rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-					}
-				}
-				if (RtaType == TYPE_RTA16) {
-					for (port = 0; port < PORTS_PER_RTA; port++) {
-						PortP = p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort];
-						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-							rio_dprintk(RIO_DEBUG_ROUTE, "Re-opened this port\n");
-							rio_spin_lock_irqsave(&PortP->portSem, flags);
-							PortP->MagicFlags |= MAGIC_REBOOT;
-							rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-						}
-					}
-				}
-			}
-
-			/*
-			 ** keep a copy of the module types!
-			 */
-			HostP->UnixRups[ThisUnit].ModTypes = Mod;
-			if (RtaType == TYPE_RTA16)
-				HostP->UnixRups[ThisUnit2].ModTypes = Mod;
-
-			/*
-			 ** If either of the modules on this unit is read-only or write-only
-			 ** or none-xprint, then we need to transfer that info over to the
-			 ** relevant ports.
-			 */
-			if (HostP->Mapping[ThisUnit].SysPort != NO_PORT) {
-				for (port = 0; port < PORTS_PER_MODULE; port++) {
-					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
-					p->RIOPortp[port + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
-					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config &= ~RIO_NOMASK;
-					p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
-				}
-				if (RtaType == TYPE_RTA16) {
-					for (port = 0; port < PORTS_PER_MODULE; port++) {
-						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
-						p->RIOPortp[port + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod1].Flags[port];
-						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config &= ~RIO_NOMASK;
-						p->RIOPortp[port + PORTS_PER_MODULE + HostP->Mapping[ThisUnit2].SysPort]->Config |= p->RIOModuleTypes[Mod2].Flags[port];
-					}
-				}
-			}
-
-			/*
-			 ** Job done, get on with the interrupts!
-			 */
-			return 1;
-		}
-	}
-	/*
-	 ** There is no table entry for this RTA at all.
-	 **
-	 ** Lets check to see if we actually booted this unit - if not,
-	 ** then we reset it and it will go round the loop of being booted
-	 ** we can then worry about trying to fit it into the table.
-	 */
-	for (ThisUnit = 0; ThisUnit < HostP->NumExtraBooted; ThisUnit++)
-		if (HostP->ExtraUnits[ThisUnit] == RtaUniq)
-			break;
-	if (ThisUnit == HostP->NumExtraBooted && ThisUnit != MAX_EXTRA_UNITS) {
-		/*
-		 ** if the unit wasn't in the table, and the table wasn't full, then
-		 ** we reset the unit, because we didn't boot it.
-		 ** However, if the table is full, it could be that we did boot
-		 ** this unit, and so we won't reboot it, because it isn't really
-		 ** all that disasterous to keep the old bins in most cases. This
-		 ** is a rather tacky feature, but we are on the edge of reallity
-		 ** here, because the implication is that someone has connected
-		 ** 16+MAX_EXTRA_UNITS onto one host.
-		 */
-		static int UnknownMesgDone = 0;
-
-		if (!UnknownMesgDone) {
-			if (!p->RIONoMessage)
-				printk(KERN_DEBUG "rio: One or more unknown RTAs are being updated.\n");
-			UnknownMesgDone = 1;
-		}
-
-		PktReplyP->Command = ROUTE_FOAD;
-		memcpy(PktReplyP->CommandText, "RT_FOAD", 7);
-	} else {
-		/*
-		 ** we did boot it (as an extra), and there may now be a table
-		 ** slot free (because of a delete), so we will try to make
-		 ** a tentative entry for it, so that the configurator can see it
-		 ** and fill in the details for us.
-		 */
-		if (RtaType == TYPE_RTA16) {
-			if (RIOFindFreeID(p, HostP, &ThisUnit, &ThisUnit2) == 0) {
-				RIODefaultName(p, HostP, ThisUnit);
-				rio_fill_host_slot(ThisUnit, ThisUnit2, RtaUniq, HostP);
-			}
-		} else {
-			if (RIOFindFreeID(p, HostP, &ThisUnit, NULL) == 0) {
-				RIODefaultName(p, HostP, ThisUnit);
-				rio_fill_host_slot(ThisUnit, 0, RtaUniq, HostP);
-			}
-		}
-		PktReplyP->Command = ROUTE_USED;
-		memcpy(PktReplyP->CommandText, "RT_USED", 7);
-	}
-	RIOQueueCmdBlk(HostP, Rup, CmdBlkP);
-	return 1;
-}
-
-
-void RIOFixPhbs(struct rio_info *p, struct Host *HostP, unsigned int unit)
-{
-	unsigned short link, port;
-	struct Port *PortP;
-	unsigned long flags;
-	int PortN = HostP->Mapping[unit].SysPort;
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFixPhbs unit %d sysport %d\n", unit, PortN);
-
-	if (PortN != -1) {
-		unsigned short dest_unit = HostP->Mapping[unit].ID2;
-
-		/*
-		 ** Get the link number used for the 1st 8 phbs on this unit.
-		 */
-		PortP = p->RIOPortp[HostP->Mapping[dest_unit - 1].SysPort];
-
-		link = readw(&PortP->PhbP->link);
-
-		for (port = 0; port < PORTS_PER_RTA; port++, PortN++) {
-			unsigned short dest_port = port + 8;
-			u16 __iomem *TxPktP;
-			struct PKT __iomem *Pkt;
-
-			PortP = p->RIOPortp[PortN];
-
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			/*
-			 ** If RTA is not powered on, the tx packets will be
-			 ** unset, so go no further.
-			 */
-			if (!PortP->TxStart) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Tx pkts not set up yet\n");
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				break;
-			}
-
-			/*
-			 ** For the second slot of a 16 port RTA, the driver needs to
-			 ** sort out the phb to port mappings. The dest_unit for this
-			 ** group of 8 phbs is set to the dest_unit of the accompanying
-			 ** 8 port block. The dest_port of the second unit is set to
-			 ** be in the range 8-15 (i.e. 8 is added). Thus, for a 16 port
-			 ** RTA with IDs 5 and 6, traffic bound for port 6 of unit 6
-			 ** (being the second map ID) will be sent to dest_unit 5, port
-			 ** 14. When this RTA is deleted, dest_unit for ID 6 will be
-			 ** restored, and the dest_port will be reduced by 8.
-			 ** Transmit packets also have a destination field which needs
-			 ** adjusting in the same manner.
-			 ** Note that the unit/port bytes in 'dest' are swapped.
-			 ** We also need to adjust the phb and rup link numbers for the
-			 ** second block of 8 ttys.
-			 */
-			for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
-				/*
-				 ** *TxPktP is the pointer to the transmit packet on the host
-				 ** card. This needs to be translated into a 32 bit pointer
-				 ** so it can be accessed from the driver.
-				 */
-				Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(TxPktP));
-
-				/*
-				 ** If the packet is used, reset it.
-				 */
-				Pkt = (struct PKT __iomem *) ((unsigned long) Pkt & ~PKT_IN_USE);
-				writeb(dest_unit, &Pkt->dest_unit);
-				writeb(dest_port, &Pkt->dest_port);
-			}
-			rio_dprintk(RIO_DEBUG_ROUTE, "phb dest: Old %x:%x New %x:%x\n", readw(&PortP->PhbP->destination) & 0xff, (readw(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
-			writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
-			writew(link, &PortP->PhbP->link);
-
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		}
-		/*
-		 ** Now make sure the range of ports to be serviced includes
-		 ** the 2nd 8 on this 16 port RTA.
-		 */
-		if (link > 3)
-			return;
-		if (((unit * 8) + 7) > readw(&HostP->LinkStrP[link].last_port)) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "last port on host link %d: %d\n", link, (unit * 8) + 7);
-			writew((unit * 8) + 7, &HostP->LinkStrP[link].last_port);
-		}
-	}
-}
-
-/*
-** Check to see if the new disconnection has isolated this unit.
-** If it has, then invalidate all its link information, and tell
-** the world about it. This is done to ensure that the configurator
-** only gets up-to-date information about what is going on.
-*/
-static int RIOCheckIsolated(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
-{
-	unsigned long flags;
-	rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-	if (RIOCheck(HostP, UnitId)) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit %d is NOT isolated\n", UnitId);
-		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-		return (0);
-	}
-
-	RIOIsolate(p, HostP, UnitId);
-	RIOSetChange(p);
-	rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-	return 1;
-}
-
-/*
-** Invalidate all the link interconnectivity of this unit, and of
-** all the units attached to it. This will mean that the entire
-** subnet will re-introduce itself.
-*/
-static int RIOIsolate(struct rio_info *p, struct Host *HostP, unsigned int UnitId)
-{
-	unsigned int link, unit;
-
-	UnitId--;		/* this trick relies on the Unit Id being UNSIGNED! */
-
-	if (UnitId >= MAX_RUP)	/* dontcha just lurv unsigned maths! */
-		return (0);
-
-	if (HostP->Mapping[UnitId].Flags & BEEN_HERE)
-		return (0);
-
-	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
-
-	if (p->RIOPrintDisabled == DO_PRINT)
-		rio_dprintk(RIO_DEBUG_ROUTE, "RIOMesgIsolated %s", HostP->Mapping[UnitId].Name);
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		unit = HostP->Mapping[UnitId].Topology[link].Unit;
-		HostP->Mapping[UnitId].Topology[link].Unit = ROUTE_DISCONNECT;
-		HostP->Mapping[UnitId].Topology[link].Link = NO_LINK;
-		RIOIsolate(p, HostP, unit);
-	}
-	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-	return 1;
-}
-
-static int RIOCheck(struct Host *HostP, unsigned int UnitId)
-{
-	unsigned char link;
-
-/* 	rio_dprint(RIO_DEBUG_ROUTE, ("Check to see if unit %d has a route to the host\n",UnitId)); */
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOCheck : UnitID = %d\n", UnitId);
-
-	if (UnitId == HOST_ID) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is NOT isolated - it IS the host!\n", UnitId)); */
-		return 1;
-	}
-
-	UnitId--;
-
-	if (UnitId >= MAX_RUP) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d - ignored.\n", UnitId)); */
-		return 0;
-	}
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		if (HostP->Mapping[UnitId].Topology[link].Unit == HOST_ID) {
-			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected directly to host via link (%c).\n", 
-			   UnitId, 'A'+link)); */
-			return 1;
-		}
-	}
-
-	if (HostP->Mapping[UnitId].Flags & BEEN_HERE) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Been to Unit %d before - ignoring\n", UnitId)); */
-		return 0;
-	}
-
-	HostP->Mapping[UnitId].Flags |= BEEN_HERE;
-
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d check link (%c)\n", UnitId,'A'+link)); */
-		if (RIOCheck(HostP, HostP->Mapping[UnitId].Topology[link].Unit)) {
-			/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d is connected to something that knows the host via link (%c)\n", UnitId,link+'A')); */
-			HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-			return 1;
-		}
-	}
-
-	HostP->Mapping[UnitId].Flags &= ~BEEN_HERE;
-
-	/* rio_dprint(RIO_DEBUG_ROUTE, ("Unit %d DOESNT KNOW THE HOST!\n", UnitId)); */
-
-	return 0;
-}
-
-/*
-** Returns the type of unit (host, 16/8 port RTA)
-*/
-
-unsigned int GetUnitType(unsigned int Uniq)
-{
-	switch ((Uniq >> 28) & 0xf) {
-	case RIO_AT:
-	case RIO_MCA:
-	case RIO_EISA:
-	case RIO_PCI:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Host\n");
-		return (TYPE_HOST);
-	case RIO_RTA_16:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 16 port RTA\n");
-		return (TYPE_RTA16);
-	case RIO_RTA:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: 8 port RTA\n");
-		return (TYPE_RTA8);
-	default:
-		rio_dprintk(RIO_DEBUG_ROUTE, "Unit type: Unrecognised\n");
-		return (99);
-	}
-}
-
-int RIOSetChange(struct rio_info *p)
-{
-	if (p->RIOQuickCheck != NOT_CHANGED)
-		return (0);
-	p->RIOQuickCheck = CHANGED;
-	if (p->RIOSignalProcess) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Send SIG-HUP");
-		/*
-		   psignal( RIOSignalProcess, SIGHUP );
-		 */
-	}
-	return (0);
-}
-
-static void RIOConCon(struct rio_info *p,
-		      struct Host *HostP,
-		      unsigned int FromId,
-		      unsigned int FromLink,
-		      unsigned int ToId,
-		      unsigned int ToLink,
-		      int Change)
-{
-	char *FromName;
-	char *FromType;
-	char *ToName;
-	char *ToType;
-	unsigned int tp;
-
-/*
-** 15.10.1998 ARG - ESIL 0759
-** (Part) fix for port being trashed when opened whilst RTA "disconnected"
-**
-** What's this doing in here anyway ?
-** It was causing the port to be 'unmapped' if opened whilst RTA "disconnected"
-**
-** 09.12.1998 ARG - ESIL 0776 - part fix
-** Okay, We've found out what this was all about now !
-** Someone had botched this to use RIOHalted to indicated the number of RTAs
-** 'disconnected'. The value in RIOHalted was then being used in the
-** 'RIO_QUICK_CHECK' ioctl. A none zero value indicating that a least one RTA
-** is 'disconnected'. The change was put in to satisfy a customer's needs.
-** Having taken this bit of code out 'RIO_QUICK_CHECK' now no longer works for
-** the customer.
-**
-    if (Change == CONNECT) {
-		if (p->RIOHalted) p->RIOHalted --;
-	 }
-	 else {
-		p->RIOHalted ++;
-	 }
-**
-** So - we need to implement it slightly differently - a new member of the
-** rio_info struct - RIORtaDisCons (RIO RTA connections) keeps track of RTA
-** connections and disconnections. 
-*/
-	if (Change == CONNECT) {
-		if (p->RIORtaDisCons)
-			p->RIORtaDisCons--;
-	} else {
-		p->RIORtaDisCons++;
-	}
-
-	if (p->RIOPrintDisabled == DONT_PRINT)
-		return;
-
-	if (FromId > ToId) {
-		tp = FromId;
-		FromId = ToId;
-		ToId = tp;
-		tp = FromLink;
-		FromLink = ToLink;
-		ToLink = tp;
-	}
-
-	FromName = FromId ? HostP->Mapping[FromId - 1].Name : HostP->Name;
-	FromType = FromId ? "RTA" : "HOST";
-	ToName = ToId ? HostP->Mapping[ToId - 1].Name : HostP->Name;
-	ToType = ToId ? "RTA" : "HOST";
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
-	printk(KERN_DEBUG "rio: Link between %s '%s' (%c) and %s '%s' (%c) %s.\n", FromType, FromName, 'A' + FromLink, ToType, ToName, 'A' + ToLink, (Change == CONNECT) ? "established" : "disconnected");
-}
-
-/*
-** RIORemoveFromSavedTable :
-**
-** Delete and RTA entry from the saved table given to us
-** by the configuration program.
-*/
-static int RIORemoveFromSavedTable(struct rio_info *p, struct Map *pMap)
-{
-	int entry;
-
-	/*
-	 ** We loop for all entries even after finding an entry and
-	 ** zeroing it because we may have two entries to delete if
-	 ** it's a 16 port RTA.
-	 */
-	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-		if (p->RIOSavedTable[entry].RtaUniqueNum == pMap->RtaUniqueNum) {
-			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
-		}
-	}
-	return 0;
-}
-
-
-/*
-** RIOCheckDisconnected :
-**
-** Scan the unit links to and return zero if the unit is completely
-** disconnected.
-*/
-static int RIOFreeDisconnected(struct rio_info *p, struct Host *HostP, int unit)
-{
-	int link;
-
-
-	rio_dprintk(RIO_DEBUG_ROUTE, "RIOFreeDisconnect unit %d\n", unit);
-	/*
-	 ** If the slot is tentative and does not belong to the
-	 ** second half of a 16 port RTA then scan to see if
-	 ** is disconnected.
-	 */
-	for (link = 0; link < LINKS_PER_UNIT; link++) {
-		if (HostP->Mapping[unit].Topology[link].Unit != ROUTE_DISCONNECT)
-			break;
-	}
-
-	/*
-	 ** If not all links are disconnected then we can forget about it.
-	 */
-	if (link < LINKS_PER_UNIT)
-		return 1;
-
-#ifdef NEED_TO_FIX_THIS
-	/* Ok so all the links are disconnected. But we may have only just
-	 ** made this slot tentative and not yet received a topology update.
-	 ** Lets check how long ago we made it tentative.
-	 */
-	rio_dprintk(RIO_DEBUG_ROUTE, "Just about to check LBOLT on entry %d\n", unit);
-	if (drv_getparm(LBOLT, (ulong_t *) & current_time))
-		rio_dprintk(RIO_DEBUG_ROUTE, "drv_getparm(LBOLT,....) Failed.\n");
-
-	elapse_time = current_time - TentTime[unit];
-	rio_dprintk(RIO_DEBUG_ROUTE, "elapse %d = current %d - tent %d (%d usec)\n", elapse_time, current_time, TentTime[unit], drv_hztousec(elapse_time));
-	if (drv_hztousec(elapse_time) < WAIT_TO_FINISH) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Skipping slot %d, not timed out yet %d\n", unit, drv_hztousec(elapse_time));
-		return 1;
-	}
-#endif
-
-	/*
-	 ** We have found an usable slot.
-	 ** If it is half of a 16 port RTA then delete the other half.
-	 */
-	if (HostP->Mapping[unit].ID2 != 0) {
-		int nOther = (HostP->Mapping[unit].ID2) - 1;
-
-		rio_dprintk(RIO_DEBUG_ROUTE, "RioFreedis second slot %d.\n", nOther);
-		memset(&HostP->Mapping[nOther], 0, sizeof(struct Map));
-	}
-	RIORemoveFromSavedTable(p, &HostP->Mapping[unit]);
-
-	return 0;
-}
-
-
-/*
-** RIOFindFreeID :
-**
-** This function scans the given host table for either one
-** or two free unit ID's.
-*/
-
-int RIOFindFreeID(struct rio_info *p, struct Host *HostP, unsigned int * pID1, unsigned int * pID2)
-{
-	int unit, tempID;
-
-	/*
-	 ** Initialise the ID's to MAX_RUP.
-	 ** We do this to make the loop for setting the ID's as simple as
-	 ** possible.
-	 */
-	*pID1 = MAX_RUP;
-	if (pID2 != NULL)
-		*pID2 = MAX_RUP;
-
-	/*
-	 ** Scan all entries of the host mapping table for free slots.
-	 ** We scan for free slots first and then if that is not successful
-	 ** we start all over again looking for tentative slots we can re-use.
-	 */
-	for (unit = 0; unit < MAX_RUP; unit++) {
-		rio_dprintk(RIO_DEBUG_ROUTE, "Scanning unit %d\n", unit);
-		/*
-		 ** If the flags are zero then the slot is empty.
-		 */
-		if (HostP->Mapping[unit].Flags == 0) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "      This slot is empty.\n");
-			/*
-			 ** If we haven't allocated the first ID then do it now.
-			 */
-			if (*pID1 == MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for first unit %d\n", unit);
-				*pID1 = unit;
-
-				/*
-				 ** If the second ID is not needed then we can return
-				 ** now.
-				 */
-				if (pID2 == NULL)
-					return 0;
-			} else {
-				/*
-				 ** Allocate the second slot and return.
-				 */
-				rio_dprintk(RIO_DEBUG_ROUTE, "Make tentative entry for second unit %d\n", unit);
-				*pID2 = unit;
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 ** If we manage to come out of the free slot loop then we
-	 ** need to start all over again looking for tentative slots
-	 ** that we can re-use.
-	 */
-	rio_dprintk(RIO_DEBUG_ROUTE, "Starting to scan for tentative slots\n");
-	for (unit = 0; unit < MAX_RUP; unit++) {
-		if (((HostP->Mapping[unit].Flags & SLOT_TENTATIVE) || (HostP->Mapping[unit].Flags == 0)) && !(HostP->Mapping[unit].Flags & RTA16_SECOND_SLOT)) {
-			rio_dprintk(RIO_DEBUG_ROUTE, "    Slot %d looks promising.\n", unit);
-
-			if (unit == *pID1) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "    No it isn't, its the 1st half\n");
-				continue;
-			}
-
-			/*
-			 ** Slot is Tentative or Empty, but not a tentative second
-			 ** slot of a 16 porter.
-			 ** Attempt to free up this slot (and its parnter if
-			 ** it is a 16 port slot. The second slot will become
-			 ** empty after a call to RIOFreeDisconnected so thats why
-			 ** we look for empty slots above  as well).
-			 */
-			if (HostP->Mapping[unit].Flags != 0)
-				if (RIOFreeDisconnected(p, HostP, unit) != 0)
-					continue;
-			/*
-			 ** If we haven't allocated the first ID then do it now.
-			 */
-			if (*pID1 == MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative entry for first unit %d\n", unit);
-				*pID1 = unit;
-
-				/*
-				 ** Clear out this slot now that we intend to use it.
-				 */
-				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
-
-				/*
-				 ** If the second ID is not needed then we can return
-				 ** now.
-				 */
-				if (pID2 == NULL)
-					return 0;
-			} else {
-				/*
-				 ** Allocate the second slot and return.
-				 */
-				rio_dprintk(RIO_DEBUG_ROUTE, "Grab tentative/empty  entry for second unit %d\n", unit);
-				*pID2 = unit;
-
-				/*
-				 ** Clear out this slot now that we intend to use it.
-				 */
-				memset(&HostP->Mapping[unit], 0, sizeof(struct Map));
-
-				/* At this point under the right(wrong?) conditions
-				 ** we may have a first unit ID being higher than the
-				 ** second unit ID. This is a bad idea if we are about
-				 ** to fill the slots with a 16 port RTA.
-				 ** Better check and swap them over.
-				 */
-
-				if (*pID1 > *pID2) {
-					rio_dprintk(RIO_DEBUG_ROUTE, "Swapping IDS %d %d\n", *pID1, *pID2);
-					tempID = *pID1;
-					*pID1 = *pID2;
-					*pID2 = tempID;
-				}
-				return 0;
-			}
-		}
-	}
-
-	/*
-	 ** If we manage to get to the end of the second loop then we
-	 ** can give up and return a failure.
-	 */
-	return 1;
-}
-
-
-/*
-** The link switch scenario.
-**
-** Rta Wun (A) is connected to Tuw (A).
-** The tables are all up to date, and the system is OK.
-**
-** If Wun (A) is now moved to Wun (B) before Wun (A) can
-** become disconnected, then the follow happens:
-**
-** Tuw (A) spots the change of unit:link at the other end
-** of its link and Tuw sends a topology packet reflecting
-** the change: Tuw (A) now disconnected from Wun (A), and
-** this is closely followed by a packet indicating that 
-** Tuw (A) is now connected to Wun (B).
-**
-** Wun (B) will spot that it has now become connected, and
-** Wun will send a topology packet, which indicates that
-** both Wun (A) and Wun (B) is connected to Tuw (A).
-**
-** Eventually Wun (A) realises that it is now disconnected
-** and Wun will send out a topology packet indicating that
-** Wun (A) is now disconnected.
-*/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/riospace.h linux-libre-2.6.39-gnu/drivers/char/rio/riospace.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/riospace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/riospace.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,154 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: riospace.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:13
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)riospace.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_riospace_h__
-#define __rio_riospace_h__
-
-#define	RIO_LOCATOR_LEN	16
-#define	MAX_RIO_BOARDS	4
-
-/*
-** DONT change this file. At all. Unless you can rebuild the entire
-** device driver, which you probably can't, then the rest of the
-** driver won't see any changes you make here. So don't make any.
-** In particular, it won't be able to see changes to RIO_SLOTS
-*/
-
-struct Conf {
-	char Locator[24];
-	unsigned int StartupTime;
-	unsigned int SlowCook;
-	unsigned int IntrPollTime;
-	unsigned int BreakInterval;
-	unsigned int Timer;
-	unsigned int RtaLoadBase;
-	unsigned int HostLoadBase;
-	unsigned int XpHz;
-	unsigned int XpCps;
-	char *XpOn;
-	char *XpOff;
-	unsigned int MaxXpCps;
-	unsigned int MinXpCps;
-	unsigned int SpinCmds;
-	unsigned int FirstAddr;
-	unsigned int LastAddr;
-	unsigned int BufferSize;
-	unsigned int LowWater;
-	unsigned int LineLength;
-	unsigned int CmdTime;
-};
-
-/*
-**	Board types - these MUST correspond to product codes!
-*/
-#define	RIO_EMPTY	0x0
-#define	RIO_EISA	0x3
-#define	RIO_RTA_16	0x9
-#define	RIO_AT		0xA
-#define	RIO_MCA		0xB
-#define	RIO_PCI		0xD
-#define	RIO_RTA		0xE
-
-/*
-**	Board data structure. This is used for configuration info
-*/
-struct Brd {
-	unsigned char Type;	/* RIO_EISA, RIO_MCA, RIO_AT, RIO_EMPTY... */
-	unsigned char Ivec;	/* POLLED or ivec number */
-	unsigned char Mode;	/* Control stuff, see below */
-};
-
-struct Board {
-	char Locator[RIO_LOCATOR_LEN];
-	int NumSlots;
-	struct Brd Boards[MAX_RIO_BOARDS];
-};
-
-#define	BOOT_FROM_LINK		0x00
-#define	BOOT_FROM_RAM		0x01
-#define	EXTERNAL_BUS_OFF	0x00
-#define	EXTERNAL_BUS_ON		0x02
-#define	INTERRUPT_DISABLE	0x00
-#define	INTERRUPT_ENABLE	0x04
-#define	BYTE_OPERATION		0x00
-#define	WORD_OPERATION		0x08
-#define	POLLED			INTERRUPT_DISABLE
-#define	IRQ_15			(0x00 | INTERRUPT_ENABLE)
-#define	IRQ_12			(0x10 | INTERRUPT_ENABLE)
-#define	IRQ_11			(0x20 | INTERRUPT_ENABLE)
-#define	IRQ_9			(0x30 | INTERRUPT_ENABLE)
-#define	SLOW_LINKS		0x00
-#define	FAST_LINKS		0x40
-#define	SLOW_AT_BUS		0x00
-#define	FAST_AT_BUS		0x80
-#define	SLOW_PCI_TP		0x00
-#define	FAST_PCI_TP		0x80
-/*
-**	Debug levels
-*/
-#define	DBG_NONE	0x00000000
-
-#define	DBG_INIT	0x00000001
-#define	DBG_OPEN	0x00000002
-#define	DBG_CLOSE	0x00000004
-#define	DBG_IOCTL	0x00000008
-
-#define	DBG_READ	0x00000010
-#define	DBG_WRITE	0x00000020
-#define	DBG_INTR	0x00000040
-#define	DBG_PROC	0x00000080
-
-#define	DBG_PARAM	0x00000100
-#define	DBG_CMD		0x00000200
-#define	DBG_XPRINT	0x00000400
-#define	DBG_POLL	0x00000800
-
-#define	DBG_DAEMON	0x00001000
-#define	DBG_FAIL	0x00002000
-#define DBG_MODEM	0x00004000
-#define	DBG_LIST	0x00008000
-
-#define	DBG_ROUTE	0x00010000
-#define DBG_UTIL        0x00020000
-#define DBG_BOOT	0x00040000
-#define DBG_BUFFER	0x00080000
-
-#define	DBG_MON		0x00100000
-#define DBG_SPECIAL     0x00200000
-#define	DBG_VPIX	0x00400000
-#define	DBG_FLUSH	0x00800000
-
-#define	DBG_QENABLE	0x01000000
-
-#define	DBG_ALWAYS	0x80000000
-
-#endif				/* __rio_riospace_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/riotable.c linux-libre-2.6.39-gnu/drivers/char/rio/riotable.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/riotable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/riotable.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,941 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: riotable.c
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 10:33:47
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)riotable.c	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/errno.h>
-#include <linux/interrupt.h>
-#include <linux/string.h>
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-#include "protsts.h"
-
-/*
-** A configuration table has been loaded. It is now up to us
-** to sort it out and use the information contained therein.
-*/
-int RIONewTable(struct rio_info *p)
-{
-	int Host, Host1, Host2, NameIsUnique, Entry, SubEnt;
-	struct Map *MapP;
-	struct Map *HostMapP;
-	struct Host *HostP;
-
-	char *cptr;
-
-	/*
-	 ** We have been sent a new table to install. We need to break
-	 ** it down into little bits and spread it around a bit to see
-	 ** what we have got.
-	 */
-	/*
-	 ** Things to check:
-	 ** (things marked 'xx' aren't checked any more!)
-	 ** (1) That there are no booted Hosts/RTAs out there.
-	 ** (2) That the names are properly formed
-	 ** (3) That blank entries really are.
-	 ** xx (4)      That hosts mentioned in the table actually exist. xx
-	 ** (5) That the IDs are unique (per host).
-	 ** (6) That host IDs are zero
-	 ** (7) That port numbers are valid
-	 ** (8) That port numbers aren't duplicated
-	 ** (9) That names aren't duplicated
-	 ** xx (10) That hosts that actually exist are mentioned in the table. xx
-	 */
-	rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(1)\n");
-	if (p->RIOSystemUp) {	/* (1) */
-		p->RIOError.Error = HOST_HAS_ALREADY_BEEN_BOOTED;
-		return -EBUSY;
-	}
-
-	p->RIOError.Error = NOTHING_WRONG_AT_ALL;
-	p->RIOError.Entry = -1;
-	p->RIOError.Other = -1;
-
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		MapP = &p->RIOConnectTable[Entry];
-		if ((MapP->Flags & RTA16_SECOND_SLOT) == 0) {
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(2)\n");
-			cptr = MapP->Name;	/* (2) */
-			cptr[MAX_NAME_LEN - 1] = '\0';
-			if (cptr[0] == '\0') {
-				memcpy(MapP->Name, MapP->RtaUniqueNum ? "RTA	NN" : "HOST NN", 8);
-				MapP->Name[5] = '0' + Entry / 10;
-				MapP->Name[6] = '0' + Entry % 10;
-			}
-			while (*cptr) {
-				if (*cptr < ' ' || *cptr > '~') {
-					p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-					p->RIOError.Entry = Entry;
-					return -ENXIO;
-				}
-				cptr++;
-			}
-		}
-
-		/*
-		 ** If the entry saved was a tentative entry then just forget
-		 ** about it.
-		 */
-		if (MapP->Flags & SLOT_TENTATIVE) {
-			MapP->HostUniqueNum = 0;
-			MapP->RtaUniqueNum = 0;
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(3)\n");
-		if (!MapP->RtaUniqueNum && !MapP->HostUniqueNum) {	/* (3) */
-			if (MapP->ID || MapP->SysPort || MapP->Flags) {
-				rio_dprintk(RIO_DEBUG_TABLE, "%s pretending to be empty but isn't\n", MapP->Name);
-				p->RIOError.Error = TABLE_ENTRY_ISNT_PROPERLY_NULL;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "!RIO: Daemon: test (3) passes\n");
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(4)\n");
-		for (Host = 0; Host < p->RIONumHosts; Host++) {	/* (4) */
-			if (p->RIOHosts[Host].UniqueNum == MapP->HostUniqueNum) {
-				HostP = &p->RIOHosts[Host];
-				/*
-				 ** having done the lookup, we don't really want to do
-				 ** it again, so hang the host number in a safe place
-				 */
-				MapP->Topology[0].Unit = Host;
-				break;
-			}
-		}
-
-		if (Host >= p->RIONumHosts) {
-			rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has unknown host unique number 0x%x\n", MapP->Name, MapP->HostUniqueNum);
-			MapP->HostUniqueNum = 0;
-			/* MapP->RtaUniqueNum   = 0; */
-			/* MapP->ID                     = 0; */
-			/* MapP->Flags           = 0; */
-			/* MapP->SysPort                 = 0; */
-			/* MapP->Name[0]                 = 0; */
-			continue;
-		}
-
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(5)\n");
-		if (MapP->RtaUniqueNum) {	/* (5) */
-			if (!MapP->ID) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an ID of zero!\n", MapP->Name);
-				p->RIOError.Error = ZERO_RTA_ID;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			if (MapP->ID > MAX_RUP) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: RTA %s has been allocated an invalid ID %d\n", MapP->Name, MapP->ID);
-				p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
-				if (MapP->HostUniqueNum == p->RIOConnectTable[SubEnt].HostUniqueNum && MapP->ID == p->RIOConnectTable[SubEnt].ID) {
-					rio_dprintk(RIO_DEBUG_TABLE, "Dupl. ID number allocated to RTA %s and RTA %s\n", MapP->Name, p->RIOConnectTable[SubEnt].Name);
-					p->RIOError.Error = DUPLICATED_RTA_ID;
-					p->RIOError.Entry = Entry;
-					p->RIOError.Other = SubEnt;
-					return -ENXIO;
-				}
-				/*
-				 ** If the RtaUniqueNum is the same, it may be looking at both
-				 ** entries for a 16 port RTA, so check the ids
-				 */
-				if ((MapP->RtaUniqueNum == p->RIOConnectTable[SubEnt].RtaUniqueNum)
-				    && (MapP->ID2 != p->RIOConnectTable[SubEnt].ID)) {
-					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", MapP->Name);
-					rio_dprintk(RIO_DEBUG_TABLE, "RTA %s has duplicate unique number\n", p->RIOConnectTable[SubEnt].Name);
-					p->RIOError.Error = DUPLICATE_UNIQUE_NUMBER;
-					p->RIOError.Entry = Entry;
-					p->RIOError.Other = SubEnt;
-					return -ENXIO;
-				}
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7a)\n");
-			/* (7a) */
-			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
-				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d-RTA %s is not a multiple of %d!\n", (int) MapP->SysPort, MapP->Name, PORTS_PER_RTA);
-				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(7b)\n");
-			/* (7b) */
-			if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
-				rio_dprintk(RIO_DEBUG_TABLE, "TTY Port number %d for RTA %s is too big\n", (int) MapP->SysPort, MapP->Name);
-				p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			for (SubEnt = 0; SubEnt < Entry; SubEnt++) {
-				if (p->RIOConnectTable[SubEnt].Flags & RTA16_SECOND_SLOT)
-					continue;
-				if (p->RIOConnectTable[SubEnt].RtaUniqueNum) {
-					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(8)\n");
-					/* (8) */
-					if ((MapP->SysPort != NO_PORT) && (MapP->SysPort == p->RIOConnectTable[SubEnt].SysPort)) {
-						rio_dprintk(RIO_DEBUG_TABLE, "RTA %s:same TTY port # as RTA %s (%d)\n", MapP->Name, p->RIOConnectTable[SubEnt].Name, (int) MapP->SysPort);
-						p->RIOError.Error = TTY_NUMBER_IN_USE;
-						p->RIOError.Entry = Entry;
-						p->RIOError.Other = SubEnt;
-						return -ENXIO;
-					}
-					rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(9)\n");
-					if (strcmp(MapP->Name, p->RIOConnectTable[SubEnt].Name) == 0 && !(MapP->Flags & RTA16_SECOND_SLOT)) {	/* (9) */
-						rio_dprintk(RIO_DEBUG_TABLE, "RTA name %s used twice\n", MapP->Name);
-						p->RIOError.Error = NAME_USED_TWICE;
-						p->RIOError.Entry = Entry;
-						p->RIOError.Other = SubEnt;
-						return -ENXIO;
-					}
-				}
-			}
-		} else {	/* (6) */
-			rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: entering(6)\n");
-			if (MapP->ID) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO:HOST %s has been allocated ID that isn't zero!\n", MapP->Name);
-				p->RIOError.Error = HOST_ID_NOT_ZERO;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-			if (MapP->SysPort != NO_PORT) {
-				rio_dprintk(RIO_DEBUG_TABLE, "RIO: HOST %s has been allocated port numbers!\n", MapP->Name);
-				p->RIOError.Error = HOST_SYSPORT_BAD;
-				p->RIOError.Entry = Entry;
-				return -ENXIO;
-			}
-		}
-	}
-
-	/*
-	 ** wow! if we get here then it's a goody!
-	 */
-
-	/*
-	 ** Zero the (old) entries for each host...
-	 */
-	for (Host = 0; Host < RIO_HOSTS; Host++) {
-		for (Entry = 0; Entry < MAX_RUP; Entry++) {
-			memset(&p->RIOHosts[Host].Mapping[Entry], 0, sizeof(struct Map));
-		}
-		memset(&p->RIOHosts[Host].Name[0], 0, sizeof(p->RIOHosts[Host].Name));
-	}
-
-	/*
-	 ** Copy in the new table entries
-	 */
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "RIONewTable: Copy table for Host entry %d\n", Entry);
-		MapP = &p->RIOConnectTable[Entry];
-
-		/*
-		 ** Now, if it is an empty slot ignore it!
-		 */
-		if (MapP->HostUniqueNum == 0)
-			continue;
-
-		/*
-		 ** we saved the host number earlier, so grab it back
-		 */
-		HostP = &p->RIOHosts[MapP->Topology[0].Unit];
-
-		/*
-		 ** If it is a host, then we only need to fill in the name field.
-		 */
-		if (MapP->ID == 0) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Host entry found. Name %s\n", MapP->Name);
-			memcpy(HostP->Name, MapP->Name, MAX_NAME_LEN);
-			continue;
-		}
-
-		/*
-		 ** Its an RTA entry, so fill in the host mapping entries for it
-		 ** and the port mapping entries. Notice that entry zero is for
-		 ** ID one.
-		 */
-		HostMapP = &HostP->Mapping[MapP->ID - 1];
-
-		if (MapP->Flags & SLOT_IN_USE) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Rta entry found. Name %s\n", MapP->Name);
-			/*
-			 ** structure assign, then sort out the bits we shouldn't have done
-			 */
-			*HostMapP = *MapP;
-
-			HostMapP->Flags = SLOT_IN_USE;
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				HostMapP->Flags |= RTA16_SECOND_SLOT;
-
-			RIOReMapPorts(p, HostP, HostMapP);
-		} else {
-			rio_dprintk(RIO_DEBUG_TABLE, "TENTATIVE Rta entry found. Name %s\n", MapP->Name);
-		}
-	}
-
-	for (Entry = 0; Entry < TOTAL_MAP_ENTRIES; Entry++) {
-		p->RIOSavedTable[Entry] = p->RIOConnectTable[Entry];
-	}
-
-	for (Host = 0; Host < p->RIONumHosts; Host++) {
-		for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
-			p->RIOHosts[Host].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
-			p->RIOHosts[Host].Topology[SubEnt].Link = NO_LINK;
-		}
-		for (Entry = 0; Entry < MAX_RUP; Entry++) {
-			for (SubEnt = 0; SubEnt < LINKS_PER_UNIT; SubEnt++) {
-				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Unit = ROUTE_DISCONNECT;
-				p->RIOHosts[Host].Mapping[Entry].Topology[SubEnt].Link = NO_LINK;
-			}
-		}
-		if (!p->RIOHosts[Host].Name[0]) {
-			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
-			p->RIOHosts[Host].Name[5] += Host;
-		}
-		/*
-		 ** Check that default name assigned is unique.
-		 */
-		Host1 = Host;
-		NameIsUnique = 0;
-		while (!NameIsUnique) {
-			NameIsUnique = 1;
-			for (Host2 = 0; Host2 < p->RIONumHosts; Host2++) {
-				if (Host2 == Host)
-					continue;
-				if (strcmp(p->RIOHosts[Host].Name, p->RIOHosts[Host2].Name)
-				    == 0) {
-					NameIsUnique = 0;
-					Host1++;
-					if (Host1 >= p->RIONumHosts)
-						Host1 = 0;
-					p->RIOHosts[Host].Name[5] = '1' + Host1;
-				}
-			}
-		}
-		/*
-		 ** Rename host if name already used.
-		 */
-		if (Host1 != Host) {
-			rio_dprintk(RIO_DEBUG_TABLE, "Default name %s already used\n", p->RIOHosts[Host].Name);
-			memcpy(p->RIOHosts[Host].Name, "HOST 1", 7);
-			p->RIOHosts[Host].Name[5] += Host1;
-		}
-		rio_dprintk(RIO_DEBUG_TABLE, "Assigning default name %s\n", p->RIOHosts[Host].Name);
-	}
-	return 0;
-}
-
-/*
-** User process needs the config table - build it from first
-** principles.
-**
-*	FIXME: SMP locking
-*/
-int RIOApel(struct rio_info *p)
-{
-	int Host;
-	int link;
-	int Rup;
-	int Next = 0;
-	struct Map *MapP;
-	struct Host *HostP;
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Generating a table to return to config.rio\n");
-
-	memset(&p->RIOConnectTable[0], 0, sizeof(struct Map) * TOTAL_MAP_ENTRIES);
-
-	for (Host = 0; Host < RIO_HOSTS; Host++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Processing host %d\n", Host);
-		HostP = &p->RIOHosts[Host];
-		rio_spin_lock_irqsave(&HostP->HostLock, flags);
-
-		MapP = &p->RIOConnectTable[Next++];
-		MapP->HostUniqueNum = HostP->UniqueNum;
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-			continue;
-		}
-		MapP->RtaUniqueNum = 0;
-		MapP->ID = 0;
-		MapP->Flags = SLOT_IN_USE;
-		MapP->SysPort = NO_PORT;
-		for (link = 0; link < LINKS_PER_UNIT; link++)
-			MapP->Topology[link] = HostP->Topology[link];
-		memcpy(MapP->Name, HostP->Name, MAX_NAME_LEN);
-		for (Rup = 0; Rup < MAX_RUP; Rup++) {
-			if (HostP->Mapping[Rup].Flags & (SLOT_IN_USE | SLOT_TENTATIVE)) {
-				p->RIOConnectTable[Next] = HostP->Mapping[Rup];
-				if (HostP->Mapping[Rup].Flags & SLOT_IN_USE)
-					p->RIOConnectTable[Next].Flags |= SLOT_IN_USE;
-				if (HostP->Mapping[Rup].Flags & SLOT_TENTATIVE)
-					p->RIOConnectTable[Next].Flags |= SLOT_TENTATIVE;
-				if (HostP->Mapping[Rup].Flags & RTA16_SECOND_SLOT)
-					p->RIOConnectTable[Next].Flags |= RTA16_SECOND_SLOT;
-				Next++;
-			}
-		}
-		rio_spin_unlock_irqrestore(&HostP->HostLock, flags);
-	}
-	return 0;
-}
-
-/*
-** config.rio has taken a dislike to one of the gross maps entries.
-** if the entry is suitably inactive, then we can gob on it and remove
-** it from the table.
-*/
-int RIODeleteRta(struct rio_info *p, struct Map *MapP)
-{
-	int host, entry, port, link;
-	int SysPort;
-	struct Host *HostP;
-	struct Map *HostMapP;
-	struct Port *PortP;
-	int work_done = 0;
-	unsigned long lock_flags, sem_flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Delete entry on host %x, rta %x\n", MapP->HostUniqueNum, MapP->RtaUniqueNum);
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		HostP = &p->RIOHosts[host];
-
-		rio_spin_lock_irqsave(&HostP->HostLock, lock_flags);
-
-		if ((HostP->Flags & RUN_STATE) != RC_RUNNING) {
-			rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-			continue;
-		}
-
-		for (entry = 0; entry < MAX_RUP; entry++) {
-			if (MapP->RtaUniqueNum == HostP->Mapping[entry].RtaUniqueNum) {
-				HostMapP = &HostP->Mapping[entry];
-				rio_dprintk(RIO_DEBUG_TABLE, "Found entry offset %d on host %s\n", entry, HostP->Name);
-
-				/*
-				 ** Check all four links of the unit are disconnected
-				 */
-				for (link = 0; link < LINKS_PER_UNIT; link++) {
-					if (HostMapP->Topology[link].Unit != ROUTE_DISCONNECT) {
-						rio_dprintk(RIO_DEBUG_TABLE, "Entry is in use and cannot be deleted!\n");
-						p->RIOError.Error = UNIT_IS_IN_USE;
-						rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-						return -EBUSY;
-					}
-				}
-				/*
-				 ** Slot has been allocated, BUT not booted/routed/
-				 ** connected/selected or anything else-ed
-				 */
-				SysPort = HostMapP->SysPort;
-
-				if (SysPort != NO_PORT) {
-					for (port = SysPort; port < SysPort + PORTS_PER_RTA; port++) {
-						PortP = p->RIOPortp[port];
-						rio_dprintk(RIO_DEBUG_TABLE, "Unmap port\n");
-
-						rio_spin_lock_irqsave(&PortP->portSem, sem_flags);
-
-						PortP->Mapped = 0;
-
-						if (PortP->State & (RIO_MOPEN | RIO_LOPEN)) {
-
-							rio_dprintk(RIO_DEBUG_TABLE, "Gob on port\n");
-							PortP->TxBufferIn = PortP->TxBufferOut = 0;
-							/* What should I do 
-							   wakeup( &PortP->TxBufferIn );
-							   wakeup( &PortP->TxBufferOut);
-							 */
-							PortP->InUse = NOT_INUSE;
-							/* What should I do 
-							   wakeup( &PortP->InUse );
-							   signal(PortP->TtyP->t_pgrp,SIGKILL);
-							   ttyflush(PortP->TtyP,(FREAD|FWRITE));
-							 */
-							PortP->State |= RIO_CLOSING | RIO_DELETED;
-						}
-
-						/*
-						 ** For the second slot of a 16 port RTA, the
-						 ** driver needs to reset the changes made to
-						 ** the phb to port mappings in RIORouteRup.
-						 */
-						if (PortP->SecondBlock) {
-							u16 dest_unit = HostMapP->ID;
-							u16 dest_port = port - SysPort;
-							u16 __iomem *TxPktP;
-							struct PKT __iomem *Pkt;
-
-							for (TxPktP = PortP->TxStart; TxPktP <= PortP->TxEnd; TxPktP++) {
-								/*
-								 ** *TxPktP is the pointer to the
-								 ** transmit packet on the host card.
-								 ** This needs to be translated into
-								 ** a 32 bit pointer so it can be
-								 ** accessed from the driver.
-								 */
-								Pkt = (struct PKT __iomem *) RIO_PTR(HostP->Caddr, readw(&*TxPktP));
-								rio_dprintk(RIO_DEBUG_TABLE, "Tx packet (%x) destination: Old %x:%x New %x:%x\n", readw(TxPktP), readb(&Pkt->dest_unit), readb(&Pkt->dest_port), dest_unit, dest_port);
-								writew(dest_unit, &Pkt->dest_unit);
-								writew(dest_port, &Pkt->dest_port);
-							}
-							rio_dprintk(RIO_DEBUG_TABLE, "Port %d phb destination: Old %x:%x New %x:%x\n", port, readb(&PortP->PhbP->destination) & 0xff, (readb(&PortP->PhbP->destination) >> 8) & 0xff, dest_unit, dest_port);
-							writew(dest_unit + (dest_port << 8), &PortP->PhbP->destination);
-						}
-						rio_spin_unlock_irqrestore(&PortP->portSem, sem_flags);
-					}
-				}
-				rio_dprintk(RIO_DEBUG_TABLE, "Entry nulled.\n");
-				memset(HostMapP, 0, sizeof(struct Map));
-				work_done++;
-			}
-		}
-		rio_spin_unlock_irqrestore(&HostP->HostLock, lock_flags);
-	}
-
-	/* XXXXX lock me up */
-	for (entry = 0; entry < TOTAL_MAP_ENTRIES; entry++) {
-		if (p->RIOSavedTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
-			memset(&p->RIOSavedTable[entry], 0, sizeof(struct Map));
-			work_done++;
-		}
-		if (p->RIOConnectTable[entry].RtaUniqueNum == MapP->RtaUniqueNum) {
-			memset(&p->RIOConnectTable[entry], 0, sizeof(struct Map));
-			work_done++;
-		}
-	}
-	if (work_done)
-		return 0;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Couldn't find entry to be deleted\n");
-	p->RIOError.Error = COULDNT_FIND_ENTRY;
-	return -ENXIO;
-}
-
-int RIOAssignRta(struct rio_info *p, struct Map *MapP)
-{
-	int host;
-	struct Map *HostMapP;
-	char *sptr;
-	int link;
-
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Assign entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
-
-	if ((MapP->ID != (u16) - 1) && ((int) MapP->ID < (int) 1 || (int) MapP->ID > MAX_RUP)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
-		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	if (MapP->RtaUniqueNum == 0) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Rta Unique number zero!\n");
-		p->RIOError.Error = RTA_UNIQUE_NUMBER_ZERO;
-		return -EINVAL;
-	}
-	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort % PORTS_PER_RTA)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not multiple of %d!\n", (int) MapP->SysPort, PORTS_PER_RTA);
-		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-	if ((MapP->SysPort != NO_PORT) && (MapP->SysPort >= RIO_PORTS)) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Port %d not valid!\n", (int) MapP->SysPort);
-		p->RIOError.Error = TTY_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	/*
-	 ** Copy the name across to the map entry.
-	 */
-	MapP->Name[MAX_NAME_LEN - 1] = '\0';
-	sptr = MapP->Name;
-	while (*sptr) {
-		if (*sptr < ' ' || *sptr > '~') {
-			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
-			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-			return -EINVAL;
-		}
-		sptr++;
-	}
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
-			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
-				p->RIOError.Error = HOST_NOT_RUNNING;
-				return -ENXIO;
-			}
-
-			/*
-			 ** Now we have a host we need to allocate an ID
-			 ** if the entry does not already have one.
-			 */
-			if (MapP->ID == (u16) - 1) {
-				int nNewID;
-
-				rio_dprintk(RIO_DEBUG_TABLE, "Attempting to get a new ID for rta \"%s\"\n", MapP->Name);
-				/*
-				 ** The idea here is to allow RTA's to be assigned
-				 ** before they actually appear on the network.
-				 ** This allows the addition of RTA's without having
-				 ** to plug them in.
-				 ** What we do is:
-				 **  - Find a free ID and allocate it to the RTA.
-				 **  - If this map entry is the second half of a
-				 **    16 port entry then find the other half and
-				 **    make sure the 2 cross reference each other.
-				 */
-				if (RIOFindFreeID(p, &p->RIOHosts[host], &nNewID, NULL) != 0) {
-					p->RIOError.Error = COULDNT_FIND_ENTRY;
-					return -EBUSY;
-				}
-				MapP->ID = (u16) nNewID + 1;
-				rio_dprintk(RIO_DEBUG_TABLE, "Allocated ID %d for this new RTA.\n", MapP->ID);
-				HostMapP = &p->RIOHosts[host].Mapping[nNewID];
-				HostMapP->RtaUniqueNum = MapP->RtaUniqueNum;
-				HostMapP->HostUniqueNum = MapP->HostUniqueNum;
-				HostMapP->ID = MapP->ID;
-				for (link = 0; link < LINKS_PER_UNIT; link++) {
-					HostMapP->Topology[link].Unit = ROUTE_DISCONNECT;
-					HostMapP->Topology[link].Link = NO_LINK;
-				}
-				if (MapP->Flags & RTA16_SECOND_SLOT) {
-					int unit;
-
-					for (unit = 0; unit < MAX_RUP; unit++)
-						if (p->RIOHosts[host].Mapping[unit].RtaUniqueNum == MapP->RtaUniqueNum)
-							break;
-					if (unit == MAX_RUP) {
-						p->RIOError.Error = COULDNT_FIND_ENTRY;
-						return -EBUSY;
-					}
-					HostMapP->Flags |= RTA16_SECOND_SLOT;
-					HostMapP->ID2 = MapP->ID2 = p->RIOHosts[host].Mapping[unit].ID;
-					p->RIOHosts[host].Mapping[unit].ID2 = MapP->ID;
-					rio_dprintk(RIO_DEBUG_TABLE, "Cross referenced id %d to ID %d.\n", MapP->ID, p->RIOHosts[host].Mapping[unit].ID);
-				}
-			}
-
-			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
-
-			if (HostMapP->Flags & SLOT_IN_USE) {
-				rio_dprintk(RIO_DEBUG_TABLE, "Map table slot for ID %d is already in use.\n", MapP->ID);
-				p->RIOError.Error = ID_ALREADY_IN_USE;
-				return -EBUSY;
-			}
-
-			/*
-			 ** Assign the sys ports and the name, and mark the slot as
-			 ** being in use.
-			 */
-			HostMapP->SysPort = MapP->SysPort;
-			if ((MapP->Flags & RTA16_SECOND_SLOT) == 0)
-				memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
-			HostMapP->Flags = SLOT_IN_USE | RTA_BOOTED;
-#ifdef NEED_TO_FIX
-			RIO_SV_BROADCAST(p->RIOHosts[host].svFlags[MapP->ID - 1]);
-#endif
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				HostMapP->Flags |= RTA16_SECOND_SLOT;
-
-			RIOReMapPorts(p, &p->RIOHosts[host], HostMapP);
-			/*
-			 ** Adjust 2nd block of 8 phbs
-			 */
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				RIOFixPhbs(p, &p->RIOHosts[host], HostMapP->ID - 1);
-
-			if (HostMapP->SysPort != NO_PORT) {
-				if (HostMapP->SysPort < p->RIOFirstPortsBooted)
-					p->RIOFirstPortsBooted = HostMapP->SysPort;
-				if (HostMapP->SysPort > p->RIOLastPortsBooted)
-					p->RIOLastPortsBooted = HostMapP->SysPort;
-			}
-			if (MapP->Flags & RTA16_SECOND_SLOT)
-				rio_dprintk(RIO_DEBUG_TABLE, "Second map of RTA %s added to configuration\n", p->RIOHosts[host].Mapping[MapP->ID2 - 1].Name);
-			else
-				rio_dprintk(RIO_DEBUG_TABLE, "RTA %s added to configuration\n", MapP->Name);
-			return 0;
-		}
-	}
-	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
-	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
-	return -ENXIO;
-}
-
-
-int RIOReMapPorts(struct rio_info *p, struct Host *HostP, struct Map *HostMapP)
-{
-	struct Port *PortP;
-	unsigned int SubEnt;
-	unsigned int HostPort;
-	unsigned int SysPort;
-	u16 RtaType;
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d to id %d\n", (int) HostMapP->SysPort, HostMapP->ID);
-
-	/*
-	 ** We need to tell the UnixRups which sysport the rup corresponds to
-	 */
-	HostP->UnixRups[HostMapP->ID - 1].BaseSysPort = HostMapP->SysPort;
-
-	if (HostMapP->SysPort == NO_PORT)
-		return (0);
-
-	RtaType = GetUnitType(HostMapP->RtaUniqueNum);
-	rio_dprintk(RIO_DEBUG_TABLE, "Mapping sysport %d-%d\n", (int) HostMapP->SysPort, (int) HostMapP->SysPort + PORTS_PER_RTA - 1);
-
-	/*
-	 ** now map each of its eight ports
-	 */
-	for (SubEnt = 0; SubEnt < PORTS_PER_RTA; SubEnt++) {
-		rio_dprintk(RIO_DEBUG_TABLE, "subent = %d, HostMapP->SysPort = %d\n", SubEnt, (int) HostMapP->SysPort);
-		SysPort = HostMapP->SysPort + SubEnt;	/* portnumber within system */
-		/* portnumber on host */
-
-		HostPort = (HostMapP->ID - 1) * PORTS_PER_RTA + SubEnt;
-
-		rio_dprintk(RIO_DEBUG_TABLE, "c1 p = %p, p->rioPortp = %p\n", p, p->RIOPortp);
-		PortP = p->RIOPortp[SysPort];
-		rio_dprintk(RIO_DEBUG_TABLE, "Map port\n");
-
-		/*
-		 ** Point at all the real neat data structures
-		 */
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		PortP->HostP = HostP;
-		PortP->Caddr = HostP->Caddr;
-
-		/*
-		 ** The PhbP cannot be filled in yet
-		 ** unless the host has been booted
-		 */
-		if ((HostP->Flags & RUN_STATE) == RC_RUNNING) {
-			struct PHB __iomem *PhbP = PortP->PhbP = &HostP->PhbP[HostPort];
-			PortP->TxAdd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_add));
-			PortP->TxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_start));
-			PortP->TxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->tx_end));
-			PortP->RxRemove = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_remove));
-			PortP->RxStart = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_start));
-			PortP->RxEnd = (u16 __iomem *) RIO_PTR(HostP->Caddr, readw(&PhbP->rx_end));
-		} else
-			PortP->PhbP = NULL;
-
-		/*
-		 ** port related flags
-		 */
-		PortP->HostPort = HostPort;
-		/*
-		 ** For each part of a 16 port RTA, RupNum is ID - 1.
-		 */
-		PortP->RupNum = HostMapP->ID - 1;
-		if (HostMapP->Flags & RTA16_SECOND_SLOT) {
-			PortP->ID2 = HostMapP->ID2 - 1;
-			PortP->SecondBlock = 1;
-		} else {
-			PortP->ID2 = 0;
-			PortP->SecondBlock = 0;
-		}
-		PortP->RtaUniqueNum = HostMapP->RtaUniqueNum;
-
-		/*
-		 ** If the port was already mapped then thats all we need to do.
-		 */
-		if (PortP->Mapped) {
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			continue;
-		} else
-			HostMapP->Flags &= ~RTA_NEWBOOT;
-
-		PortP->State = 0;
-		PortP->Config = 0;
-		/*
-		 ** Check out the module type - if it is special (read only etc.)
-		 ** then we need to set flags in the PortP->Config.
-		 ** Note: For 16 port RTA, all ports are of the same type.
-		 */
-		if (RtaType == TYPE_RTA16) {
-			PortP->Config |= p->RIOModuleTypes[HostP->UnixRups[HostMapP->ID - 1].ModTypes].Flags[SubEnt % PORTS_PER_MODULE];
-		} else {
-			if (SubEnt < PORTS_PER_MODULE)
-				PortP->Config |= p->RIOModuleTypes[LONYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
-			else
-				PortP->Config |= p->RIOModuleTypes[HINYBLE(HostP->UnixRups[HostMapP->ID - 1].ModTypes)].Flags[SubEnt % PORTS_PER_MODULE];
-		}
-
-		/*
-		 ** more port related flags
-		 */
-		PortP->PortState = 0;
-		PortP->ModemLines = 0;
-		PortP->ModemState = 0;
-		PortP->CookMode = COOK_WELL;
-		PortP->ParamSem = 0;
-		PortP->FlushCmdBodge = 0;
-		PortP->WflushFlag = 0;
-		PortP->MagicFlags = 0;
-		PortP->Lock = 0;
-		PortP->Store = 0;
-		PortP->FirstOpen = 1;
-
-		/*
-		 ** Buffers 'n things
-		 */
-		PortP->RxDataStart = 0;
-		PortP->Cor2Copy = 0;
-		PortP->Name = &HostMapP->Name[0];
-		PortP->statsGather = 0;
-		PortP->txchars = 0;
-		PortP->rxchars = 0;
-		PortP->opens = 0;
-		PortP->closes = 0;
-		PortP->ioctls = 0;
-		if (PortP->TxRingBuffer)
-			memset(PortP->TxRingBuffer, 0, p->RIOBufferSize);
-		else if (p->RIOBufferSize) {
-			PortP->TxRingBuffer = kzalloc(p->RIOBufferSize, GFP_KERNEL);
-		}
-		PortP->TxBufferOut = 0;
-		PortP->TxBufferIn = 0;
-		PortP->Debug = 0;
-		/*
-		 ** LastRxTgl stores the state of the rx toggle bit for this
-		 ** port, to be compared with the state of the next pkt received.
-		 ** If the same, we have received the same rx pkt from the RTA
-		 ** twice. Initialise to a value not equal to PHB_RX_TGL or 0.
-		 */
-		PortP->LastRxTgl = ~(u8) PHB_RX_TGL;
-
-		/*
-		 ** and mark the port as usable
-		 */
-		PortP->Mapped = 1;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	}
-	if (HostMapP->SysPort < p->RIOFirstPortsMapped)
-		p->RIOFirstPortsMapped = HostMapP->SysPort;
-	if (HostMapP->SysPort > p->RIOLastPortsMapped)
-		p->RIOLastPortsMapped = HostMapP->SysPort;
-
-	return 0;
-}
-
-int RIOChangeName(struct rio_info *p, struct Map *MapP)
-{
-	int host;
-	struct Map *HostMapP;
-	char *sptr;
-
-	rio_dprintk(RIO_DEBUG_TABLE, "Change name entry on host %x, rta %x, ID %d, Sysport %d\n", MapP->HostUniqueNum, MapP->RtaUniqueNum, MapP->ID, (int) MapP->SysPort);
-
-	if (MapP->ID > MAX_RUP) {
-		rio_dprintk(RIO_DEBUG_TABLE, "Bad ID in map entry!\n");
-		p->RIOError.Error = ID_NUMBER_OUT_OF_RANGE;
-		return -EINVAL;
-	}
-
-	MapP->Name[MAX_NAME_LEN - 1] = '\0';
-	sptr = MapP->Name;
-
-	while (*sptr) {
-		if (*sptr < ' ' || *sptr > '~') {
-			rio_dprintk(RIO_DEBUG_TABLE, "Name entry contains non-printing characters!\n");
-			p->RIOError.Error = BAD_CHARACTER_IN_NAME;
-			return -EINVAL;
-		}
-		sptr++;
-	}
-
-	for (host = 0; host < p->RIONumHosts; host++) {
-		if (MapP->HostUniqueNum == p->RIOHosts[host].UniqueNum) {
-			if ((p->RIOHosts[host].Flags & RUN_STATE) != RC_RUNNING) {
-				p->RIOError.Error = HOST_NOT_RUNNING;
-				return -ENXIO;
-			}
-			if (MapP->ID == 0) {
-				memcpy(p->RIOHosts[host].Name, MapP->Name, MAX_NAME_LEN);
-				return 0;
-			}
-
-			HostMapP = &p->RIOHosts[host].Mapping[MapP->ID - 1];
-
-			if (HostMapP->RtaUniqueNum != MapP->RtaUniqueNum) {
-				p->RIOError.Error = RTA_NUMBER_WRONG;
-				return -ENXIO;
-			}
-			memcpy(HostMapP->Name, MapP->Name, MAX_NAME_LEN);
-			return 0;
-		}
-	}
-	p->RIOError.Error = UNKNOWN_HOST_NUMBER;
-	rio_dprintk(RIO_DEBUG_TABLE, "Unknown host %x\n", MapP->HostUniqueNum);
-	return -ENXIO;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/riotty.c linux-libre-2.6.39-gnu/drivers/char/rio/riotty.c
--- linux-libre-2.6.38-gnu/drivers/char/rio/riotty.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/riotty.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,654 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: riotty.c
-**	SID		: 1.3
-**	Last Modified	: 11/6/98 10:33:47
-**	Retrieved	: 11/6/98 10:33:50
-**
-**  ident @(#)riotty.c	1.3
-**
-** -----------------------------------------------------------------------------
-*/
-
-#define __EXPLICIT_DEF_H__
-
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/string.h>
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/string.h>
-#include <asm/uaccess.h>
-
-#include <linux/termios.h>
-
-#include <linux/serial.h>
-
-#include <linux/generic_serial.h>
-
-
-#include "linux_compat.h"
-#include "rio_linux.h"
-#include "pkt.h"
-#include "daemon.h"
-#include "rio.h"
-#include "riospace.h"
-#include "cmdpkt.h"
-#include "map.h"
-#include "rup.h"
-#include "port.h"
-#include "riodrvr.h"
-#include "rioinfo.h"
-#include "func.h"
-#include "errors.h"
-#include "pci.h"
-
-#include "parmmap.h"
-#include "unixrup.h"
-#include "board.h"
-#include "host.h"
-#include "phb.h"
-#include "link.h"
-#include "cmdblk.h"
-#include "route.h"
-#include "cirrus.h"
-#include "rioioctl.h"
-#include "param.h"
-
-static void RIOClearUp(struct Port *PortP);
-
-/* Below belongs in func.h */
-int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg);
-
-
-extern struct rio_info *p;
-
-
-int riotopen(struct tty_struct *tty, struct file *filp)
-{
-	unsigned int SysPort;
-	int repeat_this = 250;
-	struct Port *PortP;	/* pointer to the port structure */
-	unsigned long flags;
-	int retval = 0;
-
-	func_enter();
-
-	/* Make sure driver_data is NULL in case the rio isn't booted jet. Else gs_close
-	   is going to oops.
-	 */
-	tty->driver_data = NULL;
-
-	SysPort = rio_minor(tty);
-
-	if (p->RIOFailed) {
-		rio_dprintk(RIO_DEBUG_TTY, "System initialisation failed\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "port open SysPort %d (mapped:%d)\n", SysPort, p->RIOPortp[SysPort]->Mapped);
-
-	/*
-	 ** Validate that we have received a legitimate request.
-	 ** Currently, just check that we are opening a port on
-	 ** a host card that actually exists, and that the port
-	 ** has been mapped onto a host.
-	 */
-	if (SysPort >= RIO_PORTS) {	/* out of range ? */
-		rio_dprintk(RIO_DEBUG_TTY, "Illegal port number %d\n", SysPort);
-		func_exit();
-		return -ENXIO;
-	}
-
-	/*
-	 ** Grab pointer to the port stucture
-	 */
-	PortP = p->RIOPortp[SysPort];	/* Get control struc */
-	rio_dprintk(RIO_DEBUG_TTY, "PortP: %p\n", PortP);
-	if (!PortP->Mapped) {	/* we aren't mapped yet! */
-		/*
-		 ** The system doesn't know which RTA this port
-		 ** corresponds to.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "port not mapped into system\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	tty->driver_data = PortP;
-
-	PortP->gs.port.tty = tty;
-	PortP->gs.port.count++;
-
-	rio_dprintk(RIO_DEBUG_TTY, "%d bytes in tx buffer\n", PortP->gs.xmit_cnt);
-
-	retval = gs_init_port(&PortP->gs);
-	if (retval) {
-		PortP->gs.port.count--;
-		return -ENXIO;
-	}
-	/*
-	 ** If the host hasn't been booted yet, then
-	 ** fail
-	 */
-	if ((PortP->HostP->Flags & RUN_STATE) != RC_RUNNING) {
-		rio_dprintk(RIO_DEBUG_TTY, "Host not running\n");
-		func_exit();
-		return -ENXIO;
-	}
-
-	/*
-	 ** If the RTA has not booted yet and the user has choosen to block
-	 ** until the RTA is present then we must spin here waiting for
-	 ** the RTA to boot.
-	 */
-	/* I find the above code a bit hairy. I find the below code
-	   easier to read and shorter. Now, if it works too that would
-	   be great... -- REW 
-	 */
-	rio_dprintk(RIO_DEBUG_TTY, "Checking if RTA has booted... \n");
-	while (!(PortP->HostP->Mapping[PortP->RupNum].Flags & RTA_BOOTED)) {
-		if (!PortP->WaitUntilBooted) {
-			rio_dprintk(RIO_DEBUG_TTY, "RTA never booted\n");
-			func_exit();
-			return -ENXIO;
-		}
-
-		/* Under Linux you'd normally use a wait instead of this
-		   busy-waiting. I'll stick with the old implementation for
-		   now. --REW
-		 */
-		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-			rio_dprintk(RIO_DEBUG_TTY, "RTA_wait_for_boot: EINTR in delay \n");
-			func_exit();
-			return -EINTR;
-		}
-		if (repeat_this-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for RTA to boot timeout\n");
-			func_exit();
-			return -EIO;
-		}
-	}
-	rio_dprintk(RIO_DEBUG_TTY, "RTA has been booted\n");
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	if (p->RIOHalted) {
-		goto bombout;
-	}
-
-	/*
-	 ** If the port is in the final throws of being closed,
-	 ** we should wait here (politely), waiting
-	 ** for it to finish, so that it doesn't close us!
-	 */
-	while ((PortP->State & RIO_CLOSING) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting for RIO_CLOSING to go away\n");
-		if (repeat_this-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-			RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-			retval = -EINTR;
-			goto bombout;
-		}
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-			retval = -EINTR;
-			goto bombout;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-
-	if (!PortP->Mapped) {
-		rio_dprintk(RIO_DEBUG_TTY, "Port unmapped while closing!\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		retval = -ENXIO;
-		func_exit();
-		return retval;
-	}
-
-	if (p->RIOHalted) {
-		goto bombout;
-	}
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,
-** we need to make sure that the flags are clear when the port is opened.
-*/
-	/* Uh? Suppose I turn these on and then another process opens
-	   the port again? The flags get cleared! Not good. -- REW */
-	if (!(PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
-	}
-
-	if (!(PortP->firstOpen)) {	/* First time ? */
-		rio_dprintk(RIO_DEBUG_TTY, "First open for this port\n");
-
-
-		PortP->firstOpen++;
-		PortP->CookMode = 0;	/* XXX RIOCookMode(tp); */
-		PortP->InUse = NOT_INUSE;
-
-		/* Tentative fix for bug PR27. Didn't work. */
-		/* PortP->gs.xmit_cnt = 0; */
-
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-		/* Someone explain to me why this delay/config is
-		   here. If I read the docs correctly the "open"
-		   command piggybacks the parameters immediately.
-		   -- REW */
-		RIOParam(PortP, RIOC_OPEN, 1, OK_TO_SLEEP); /* Open the port */
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-		/*
-		 ** wait for the port to be not closed.
-		 */
-		while (!(PortP->PortState & PORT_ISOPEN) && !p->RIOHalted) {
-			rio_dprintk(RIO_DEBUG_TTY, "Waiting for PORT_ISOPEN-currently %x\n", PortP->PortState);
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "Waiting for open to finish broken by signal\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				func_exit();
-				return -EINTR;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-
-		if (p->RIOHalted) {
-			retval = -EIO;
-		      bombout:
-			/*                    RIOClearUp( PortP ); */
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			return retval;
-		}
-		rio_dprintk(RIO_DEBUG_TTY, "PORT_ISOPEN found\n");
-	}
-	rio_dprintk(RIO_DEBUG_TTY, "Modem - test for carrier\n");
-	/*
-	 ** ACTION
-	 ** insert test for carrier here. -- ???
-	 ** I already see that test here. What's the deal? -- REW
-	 */
-	if ((PortP->gs.port.tty->termios->c_cflag & CLOCAL) ||
-			(PortP->ModemState & RIOC_MSVR1_CD)) {
-		rio_dprintk(RIO_DEBUG_TTY, "open(%d) Modem carr on\n", SysPort);
-		/*
-		   tp->tm.c_state |= CARR_ON;
-		   wakeup((caddr_t) &tp->tm.c_canq);
-		 */
-		PortP->State |= RIO_CARR_ON;
-		wake_up_interruptible(&PortP->gs.port.open_wait);
-	} else {	/* no carrier - wait for DCD */
-			/*
-		   while (!(PortP->gs.port.tty->termios->c_state & CARR_ON) &&
-		   !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted )
-		 */
-		while (!(PortP->State & RIO_CARR_ON) && !(filp->f_flags & O_NONBLOCK) && !p->RIOHalted) {
-				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr on\n", SysPort);
-			/*
-			   PortP->gs.port.tty->termios->c_state |= WOPEN;
-			 */
-			PortP->State |= RIO_WOPEN;
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				/*
-				 ** ACTION: verify that this is a good thing
-				 ** to do here. -- ???
-				 ** I think it's OK. -- REW
-				 */
-				rio_dprintk(RIO_DEBUG_TTY, "open(%d) sleeping for carr broken by signal\n", SysPort);
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				/*
-				   tp->tm.c_state &= ~WOPEN;
-				 */
-				PortP->State &= ~RIO_WOPEN;
-				rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-				func_exit();
-				return -EINTR;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-		PortP->State &= ~RIO_WOPEN;
-	}
-	if (p->RIOHalted)
-		goto bombout;
-	rio_dprintk(RIO_DEBUG_TTY, "Setting RIO_MOPEN\n");
-	PortP->State |= RIO_MOPEN;
-
-	if (p->RIOHalted)
-		goto bombout;
-
-	rio_dprintk(RIO_DEBUG_TTY, "high level open done\n");
-
-	/*
-	 ** Count opens for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->opens++;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Returning from open\n");
-	func_exit();
-	return 0;
-}
-
-/*
-** RIOClose the port.
-** The operating system thinks that this is last close for the device.
-** As there are two interfaces to the port (Modem and tty), we need to
-** check that both are closed before we close the device.
-*/
-int riotclose(void *ptr)
-{
-	struct Port *PortP = ptr;	/* pointer to the port structure */
-	int deleted = 0;
-	int try = -1;		/* Disable the timeouts by setting them to -1 */
-	int repeat_this = -1;	/* Congrats to those having 15 years of
-				   uptime! (You get to break the driver.) */
-	unsigned long end_time;
-	struct tty_struct *tty;
-	unsigned long flags;
-	int rv = 0;
-
-	rio_dprintk(RIO_DEBUG_TTY, "port close SysPort %d\n", PortP->PortNum);
-
-	/* PortP = p->RIOPortp[SysPort]; */
-	rio_dprintk(RIO_DEBUG_TTY, "Port is at address %p\n", PortP);
-	/* tp = PortP->TtyP; *//* Get tty */
-	tty = PortP->gs.port.tty;
-	rio_dprintk(RIO_DEBUG_TTY, "TTY is at address %p\n", tty);
-
-	if (PortP->gs.closing_wait)
-		end_time = jiffies + PortP->gs.closing_wait;
-	else
-		end_time = jiffies + MAX_SCHEDULE_TIMEOUT;
-
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	/*
-	 ** Setting this flag will make any process trying to open
-	 ** this port block until we are complete closing it.
-	 */
-	PortP->State |= RIO_CLOSING;
-
-	if ((PortP->State & RIO_DELETED)) {
-		rio_dprintk(RIO_DEBUG_TTY, "Close on deleted RTA\n");
-		deleted = 1;
-	}
-
-	if (p->RIOHalted) {
-		RIOClearUp(PortP);
-		rv = -EIO;
-		goto close_end;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "Clear bits\n");
-	/*
-	 ** clear the open bits for this device
-	 */
-	PortP->State &= ~RIO_MOPEN;
-	PortP->State &= ~RIO_CARR_ON;
-	PortP->ModemState &= ~RIOC_MSVR1_CD;
-	/*
-	 ** If the device was open as both a Modem and a tty line
-	 ** then we need to wimp out here, as the port has not really
-	 ** been finally closed (gee, whizz!) The test here uses the
-	 ** bit for the OTHER mode of operation, to see if THAT is
-	 ** still active!
-	 */
-	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		/*
-		 ** The port is still open for the other task -
-		 ** return, pretending that we are still active.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "Channel %d still open !\n", PortP->PortNum);
-		PortP->State &= ~RIO_CLOSING;
-		if (PortP->firstOpen)
-			PortP->firstOpen--;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return -EIO;
-	}
-
-	rio_dprintk(RIO_DEBUG_TTY, "Closing down - everything must go!\n");
-
-	PortP->State &= ~RIO_DYNOROD;
-
-	/*
-	 ** This is where we wait for the port
-	 ** to drain down before closing. Bye-bye....
-	 ** (We never meant to do this)
-	 */
-	rio_dprintk(RIO_DEBUG_TTY, "Timeout 1 starts\n");
-
-	if (!deleted)
-		while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted && (PortP->TxBufferIn != PortP->TxBufferOut)) {
-			if (repeat_this-- <= 0) {
-				rv = -EINTR;
-				rio_dprintk(RIO_DEBUG_TTY, "Waiting for not idle closed broken by signal\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				goto close_end;
-			}
-			rio_dprintk(RIO_DEBUG_TTY, "Calling timeout to flush in closing\n");
-			rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-			if (RIODelay_ni(PortP, HUNDRED_MS * 10) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-				rv = -EINTR;
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				goto close_end;
-			}
-			rio_spin_lock_irqsave(&PortP->portSem, flags);
-		}
-
-	PortP->TxBufferIn = PortP->TxBufferOut = 0;
-	repeat_this = 0xff;
-
-	PortP->InUse = 0;
-	if ((PortP->State & (RIO_LOPEN | RIO_MOPEN))) {
-		/*
-		 ** The port has been re-opened for the other task -
-		 ** return, pretending that we are still active.
-		 */
-		rio_dprintk(RIO_DEBUG_TTY, "Channel %d re-open!\n", PortP->PortNum);
-		PortP->State &= ~RIO_CLOSING;
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (PortP->firstOpen)
-			PortP->firstOpen--;
-		return -EIO;
-	}
-
-	if (p->RIOHalted) {
-		RIOClearUp(PortP);
-		goto close_end;
-	}
-
-	/* Can't call RIOShortCommand with the port locked. */
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-
-	if (RIOShortCommand(p, PortP, RIOC_CLOSE, 1, 0) == RIO_FAIL) {
-		RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-		goto close_end;
-	}
-
-	if (!deleted)
-		while (try && (PortP->PortState & PORT_ISOPEN)) {
-			try--;
-			if (time_after(jiffies, end_time)) {
-				rio_dprintk(RIO_DEBUG_TTY, "Run out of tries - force the bugger shut!\n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				break;
-			}
-			rio_dprintk(RIO_DEBUG_TTY, "Close: PortState:ISOPEN is %d\n", PortP->PortState & PORT_ISOPEN);
-
-			if (p->RIOHalted) {
-				RIOClearUp(PortP);
-				rio_spin_lock_irqsave(&PortP->portSem, flags);
-				goto close_end;
-			}
-			if (RIODelay(PortP, HUNDRED_MS) == RIO_FAIL) {
-				rio_dprintk(RIO_DEBUG_TTY, "RTA EINTR in delay \n");
-				RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE);
-				break;
-			}
-		}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Close: try was %d on completion\n", try);
-
-	/* RIOPreemptiveCmd(p, PortP, RIOC_FCLOSE); */
-
-/*
-** 15.10.1998 ARG - ESIL 0761 part fix
-** RIO has it's own CTSFLOW and RTSFLOW flags in 'Config' in the port structure,** we need to make sure that the flags are clear when the port is opened.
-*/
-	PortP->Config &= ~(RIO_CTSFLOW | RIO_RTSFLOW);
-
-	/*
-	 ** Count opens for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->closes++;
-
-close_end:
-	/* XXX: Why would a "DELETED" flag be reset here? I'd have
-	   thought that a "deleted" flag means that the port was
-	   permanently gone, but here we can make it reappear by it
-	   being in close during the "deletion".
-	 */
-	PortP->State &= ~(RIO_CLOSING | RIO_DELETED);
-	if (PortP->firstOpen)
-		PortP->firstOpen--;
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	rio_dprintk(RIO_DEBUG_TTY, "Return from close\n");
-	return rv;
-}
-
-
-
-static void RIOClearUp(struct Port *PortP)
-{
-	rio_dprintk(RIO_DEBUG_TTY, "RIOHalted set\n");
-	PortP->Config = 0;	/* Direct semaphore */
-	PortP->PortState = 0;
-	PortP->firstOpen = 0;
-	PortP->FlushCmdBodge = 0;
-	PortP->ModemState = PortP->CookMode = 0;
-	PortP->Mapped = 0;
-	PortP->WflushFlag = 0;
-	PortP->MagicFlags = 0;
-	PortP->RxDataStart = 0;
-	PortP->TxBufferIn = 0;
-	PortP->TxBufferOut = 0;
-}
-
-/*
-** Put a command onto a port.
-** The PortPointer, command, length and arg are passed.
-** The len is the length *inclusive* of the command byte,
-** and so for a command that takes no data, len==1.
-** The arg is a single byte, and is only used if len==2.
-** Other values of len aren't allowed, and will cause
-** a panic.
-*/
-int RIOShortCommand(struct rio_info *p, struct Port *PortP, int command, int len, int arg)
-{
-	struct PKT __iomem *PacketP;
-	int retries = 20;	/* at 10 per second -> 2 seconds */
-	unsigned long flags;
-
-	rio_dprintk(RIO_DEBUG_TTY, "entering shortcommand.\n");
-
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
-		return RIO_FAIL;
-	}
-	rio_spin_lock_irqsave(&PortP->portSem, flags);
-
-	/*
-	 ** If the port is in use for pre-emptive command, then wait for it to
-	 ** be free again.
-	 */
-	while ((PortP->InUse != NOT_INUSE) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting for not in use (%d)\n", retries);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (retries-- <= 0) {
-			return RIO_FAIL;
-		}
-		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
-			return RIO_FAIL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-	if (PortP->State & RIO_DELETED) {
-		rio_dprintk(RIO_DEBUG_TTY, "Short command to deleted RTA ignored\n");
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return RIO_FAIL;
-	}
-
-	while (!can_add_transmit(&PacketP, PortP) && !p->RIOHalted) {
-		rio_dprintk(RIO_DEBUG_TTY, "Waiting to add short command to queue (%d)\n", retries);
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		if (retries-- <= 0) {
-			rio_dprintk(RIO_DEBUG_TTY, "out of tries. Failing\n");
-			return RIO_FAIL;
-		}
-		if (RIODelay_ni(PortP, HUNDRED_MS) == RIO_FAIL) {
-			return RIO_FAIL;
-		}
-		rio_spin_lock_irqsave(&PortP->portSem, flags);
-	}
-
-	if (p->RIOHalted) {
-		rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-		return RIO_FAIL;
-	}
-
-	/*
-	 ** set the command byte and the argument byte
-	 */
-	writeb(command, &PacketP->data[0]);
-
-	if (len == 2)
-		writeb(arg, &PacketP->data[1]);
-
-	/*
-	 ** set the length of the packet and set the command bit.
-	 */
-	writeb(PKT_CMD_BIT | len, &PacketP->len);
-
-	add_transmit(PortP);
-	/*
-	 ** Count characters transmitted for port statistics reporting
-	 */
-	if (PortP->statsGather)
-		PortP->txchars += len;
-
-	rio_spin_unlock_irqrestore(&PortP->portSem, flags);
-	return p->RIOHalted ? RIO_FAIL : ~RIO_FAIL;
-}
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/route.h linux-libre-2.6.39-gnu/drivers/char/rio/route.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/route.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/route.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,101 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******                 R O U T E     H E A D E R
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra / Jeremy Rolls
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _route_h
-#define _route_h
-
-#define MAX_LINKS 4
-#define MAX_NODES 17		/* Maximum nodes in a subnet */
-#define NODE_BYTES ((MAX_NODES / 8) + 1)	/* Number of bytes needed for
-						   1 bit per node */
-#define ROUTE_DATA_SIZE  (NODE_BYTES + 2)	/* Number of bytes for complete
-						   info about cost etc. */
-#define ROUTES_PER_PACKET ((PKT_MAX_DATA_LEN -2)/ ROUTE_DATA_SIZE)
-					      /* Number of nodes we can squeeze
-					         into one packet */
-#define MAX_TOPOLOGY_PACKETS (MAX_NODES / ROUTES_PER_PACKET + 1)
-/************************************************
- * Define the types of command for the ROUTE RUP.
- ************************************************/
-#define ROUTE_REQUEST    0	/* Request an ID */
-#define ROUTE_FOAD       1	/* Kill the RTA */
-#define ROUTE_ALREADY    2	/* ID given already */
-#define ROUTE_USED       3	/* All ID's used */
-#define ROUTE_ALLOCATE   4	/* Here it is */
-#define ROUTE_REQ_TOP    5	/* I bet you didn't expect....
-				   the Topological Inquisition */
-#define ROUTE_TOPOLOGY   6	/* Topology request answered FD */
-/*******************************************************************
- * Define the Route Map Structure
- *
- * The route map gives a pointer to a Link Structure to use.
- * This allows Disconnected Links to be checked quickly
- ******************************************************************/
-typedef struct COST_ROUTE COST_ROUTE;
-struct COST_ROUTE {
-	unsigned char cost;	/* Cost down this link */
-	unsigned char route[NODE_BYTES];	/* Nodes through this route */
-};
-
-typedef struct ROUTE_STR ROUTE_STR;
-struct ROUTE_STR {
-	COST_ROUTE cost_route[MAX_LINKS];
-	/* cost / route for this link */
-	ushort favoured;	/* favoured link */
-};
-
-
-#define NO_LINK            (short) 5	/* Link unattached */
-#define ROUTE_NO_ID        (short) 100	/* No Id */
-#define ROUTE_DISCONNECT   (ushort) 0xff	/* Not connected */
-#define ROUTE_INTERCONNECT (ushort) 0x40	/* Sub-net interconnect */
-
-
-#define SYNC_RUP         (ushort) 255
-#define COMMAND_RUP      (ushort) 254
-#define ERROR_RUP        (ushort) 253
-#define POLL_RUP         (ushort) 252
-#define BOOT_RUP         (ushort) 251
-#define ROUTE_RUP        (ushort) 250
-#define STATUS_RUP       (ushort) 249
-#define POWER_RUP        (ushort) 248
-
-#define HIGHEST_RUP      (ushort) 255	/* Set to Top one */
-#define LOWEST_RUP       (ushort) 248	/* Set to bottom one */
-
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/rup.h linux-libre-2.6.39-gnu/drivers/char/rio/rup.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/rup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/rup.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,69 +0,0 @@
-/****************************************************************************
- *******                                                              *******
- *******               R U P   S T R U C T U R E
- *******                                                              *******
- ****************************************************************************
-
- Author  : Ian Nandhra
- Date    :
-
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-
- Version : 0.01
-
-
-                            Mods
- ----------------------------------------------------------------------------
-  Date     By                Description
- ----------------------------------------------------------------------------
-
- ***************************************************************************/
-
-#ifndef _rup_h
-#define _rup_h 1
-
-#define MAX_RUP          ((short) 16)
-#define PKTS_PER_RUP     ((short) 2)	/* They are always used in pairs */
-
-/*************************************************
- * Define all the  packet request stuff
- ************************************************/
-#define TX_RUP_INACTIVE          0	/* Nothing to transmit */
-#define TX_PACKET_READY          1	/* Transmit packet ready */
-#define TX_LOCK_RUP              2	/* Transmit side locked */
-
-#define RX_RUP_INACTIVE          0	/* Nothing received */
-#define RX_PACKET_READY          1	/* Packet received */
-
-#define RUP_NO_OWNER             0xff	/* RUP not owned by any process */
-
-struct RUP {
-	u16 txpkt;		/* Outgoing packet */
-	u16 rxpkt;		/* Incoming packet */
-	u16 link;		/* Which link to send down? */
-	u8 rup_dest_unit[2];	/* Destination unit */
-	u16 handshake;		/* For handshaking */
-	u16 timeout;		/* Timeout */
-	u16 status;		/* Status */
-	u16 txcontrol;		/* Transmit control */
-	u16 rxcontrol;		/* Receive control */
-};
-
-#endif
-
-/*********** end of file ***********/
diff -druN linux-libre-2.6.38-gnu/drivers/char/rio/unixrup.h linux-libre-2.6.39-gnu/drivers/char/rio/unixrup.h
--- linux-libre-2.6.38-gnu/drivers/char/rio/unixrup.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rio/unixrup.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,51 +0,0 @@
-/*
-** -----------------------------------------------------------------------------
-**
-**  Perle Specialix driver for Linux
-**  Ported from existing RIO Driver for SCO sources.
- *
- *  (C) 1990 - 2000 Specialix International Ltd., Byfleet, Surrey, UK.
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
-**
-**	Module		: unixrup.h
-**	SID		: 1.2
-**	Last Modified	: 11/6/98 11:34:20
-**	Retrieved	: 11/6/98 11:34:22
-**
-**  ident @(#)unixrup.h	1.2
-**
-** -----------------------------------------------------------------------------
-*/
-
-#ifndef __rio_unixrup_h__
-#define __rio_unixrup_h__
-
-/*
-**    UnixRup data structure. This contains pointers to actual RUPs on the
-**    host card, and all the command/boot control stuff.
-*/
-struct UnixRup {
-	struct CmdBlk *CmdsWaitingP;	/* Commands waiting to be done */
-	struct CmdBlk *CmdPendingP;	/* The command currently being sent */
-	struct RUP __iomem *RupP;	/* the Rup to send it to */
-	unsigned int Id;		/* Id number */
-	unsigned int BaseSysPort;	/* SysPort of first tty on this RTA */
-	unsigned int ModTypes;		/* Modules on this RTA */
-	spinlock_t RupLock;	/* Lock structure for MPX */
-	/*    struct lockb     RupLock;	*//* Lock structure for MPX */
-};
-
-#endif				/* __rio_unixrup_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/char/riscom8.c linux-libre-2.6.39-gnu/drivers/char/riscom8.c
--- linux-libre-2.6.38-gnu/drivers/char/riscom8.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/riscom8.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1560 +0,0 @@
-/*
- *      linux/drivers/char/riscom.c  -- RISCom/8 multiport serial driver.
- *
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card
- *      programming info was obtained from various drivers for other OSes
- *	(FreeBSD, ISC, etc), but no source code from those drivers were
- *	directly included in this driver.
- *
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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.
- *
- *	Revision 1.1
- *
- *	ChangeLog:
- *	Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 27-Jun-2001
- *	- get rid of check_region and several cleanups
- */
-
-#include <linux/module.h>
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/tty_flip.h>
-#include <linux/spinlock.h>
-#include <linux/device.h>
-
-#include <linux/uaccess.h>
-
-#include "riscom8.h"
-#include "riscom8_reg.h"
-
-/* Am I paranoid or not ? ;-) */
-#define RISCOM_PARANOIA_CHECK
-
-/*
- * Crazy InteliCom/8 boards sometimes have swapped CTS & DSR signals.
- * You can slightly speed up things by #undefing the following option,
- * if you are REALLY sure that your board is correct one.
- */
-
-#define RISCOM_BRAIN_DAMAGED_CTS
-
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#undef RC_REPORT_FIFO
-#undef RC_REPORT_OVERRUN
-
-
-#define RISCOM_LEGAL_FLAGS \
-	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
-	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
-	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
-
-static struct tty_driver *riscom_driver;
-
-static DEFINE_SPINLOCK(riscom_lock);
-
-static struct riscom_board rc_board[RC_NBOARD] =  {
-	{
-		.base	= RC_IOBASE1,
-	},
-	{
-		.base	= RC_IOBASE2,
-	},
-	{
-		.base	= RC_IOBASE3,
-	},
-	{
-		.base	= RC_IOBASE4,
-	},
-};
-
-static struct riscom_port rc_port[RC_NBOARD * RC_NPORT];
-
-/* RISCom/8 I/O ports addresses (without address translation) */
-static unsigned short rc_ioport[] =  {
-#if 1
-	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c,
-#else
-	0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x09, 0x0a, 0x0b, 0x0c, 0x10,
-	0x11, 0x12, 0x18, 0x28, 0x31, 0x32, 0x39, 0x3a, 0x40, 0x41, 0x61, 0x62,
-	0x63, 0x64, 0x6b, 0x70, 0x71, 0x78, 0x7a, 0x7b, 0x7f, 0x100, 0x101
-#endif
-};
-#define RC_NIOPORT	ARRAY_SIZE(rc_ioport)
-
-
-static int rc_paranoia_check(struct riscom_port const *port,
-				    char *name, const char *routine)
-{
-#ifdef RISCOM_PARANOIA_CHECK
-	static const char badmagic[] = KERN_INFO
-		"rc: Warning: bad riscom port magic number for device %s in %s\n";
-	static const char badinfo[] = KERN_INFO
-		"rc: Warning: null riscom port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != RISCOM8_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-/*
- *
- *  Service functions for RISCom/8 driver.
- *
- */
-
-/* Get board number from pointer */
-static inline int board_No(struct riscom_board const *bp)
-{
-	return bp - rc_board;
-}
-
-/* Get port number from pointer */
-static inline int port_No(struct riscom_port const *port)
-{
-	return RC_PORT(port - rc_port);
-}
-
-/* Get pointer to board from pointer to port */
-static inline struct riscom_board *port_Board(struct riscom_port const *port)
-{
-	return &rc_board[RC_BOARD(port - rc_port)];
-}
-
-/* Input Byte from CL CD180 register */
-static inline unsigned char rc_in(struct riscom_board const *bp,
-							unsigned short reg)
-{
-	return inb(bp->base + RC_TO_ISA(reg));
-}
-
-/* Output Byte to CL CD180 register */
-static inline void rc_out(struct riscom_board const *bp, unsigned short reg,
-			  unsigned char val)
-{
-	outb(val, bp->base + RC_TO_ISA(reg));
-}
-
-/* Wait for Channel Command Register ready */
-static void rc_wait_CCR(struct riscom_board const *bp)
-{
-	unsigned long delay;
-
-	/* FIXME: need something more descriptive then 100000 :) */
-	for (delay = 100000; delay; delay--)
-		if (!rc_in(bp, CD180_CCR))
-			return;
-
-	printk(KERN_INFO "rc%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-/*
- *  RISCom/8 probe functions.
- */
-
-static int rc_request_io_range(struct riscom_board * const bp)
-{
-	int i;
-
-	for (i = 0; i < RC_NIOPORT; i++)
-		if (!request_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1,
-				   "RISCom/8"))  {
-			goto out_release;
-		}
-	return 0;
-out_release:
-	printk(KERN_INFO "rc%d: Skipping probe at 0x%03x. IO address in use.\n",
-			 board_No(bp), bp->base);
-	while (--i >= 0)
-		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
-	return 1;
-}
-
-static void rc_release_io_range(struct riscom_board * const bp)
-{
-	int i;
-
-	for (i = 0; i < RC_NIOPORT; i++)
-		release_region(RC_TO_ISA(rc_ioport[i]) + bp->base, 1);
-}
-
-/* Reset and setup CD180 chip */
-static void __init rc_init_CD180(struct riscom_board const *bp)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	rc_out(bp, RC_CTOUT, 0);     	           /* Clear timeout        */
-	rc_wait_CCR(bp);			   /* Wait for CCR ready   */
-	rc_out(bp, CD180_CCR, CCR_HARDRESET);      /* Reset CD180 chip     */
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	msleep(50);				   /* Delay 0.05 sec       */
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_out(bp, CD180_GIVR, RC_ID);             /* Set ID for this chip */
-	rc_out(bp, CD180_GICR, 0);                 /* Clear all bits       */
-	rc_out(bp, CD180_PILR1, RC_ACK_MINT);      /* Prio for modem intr  */
-	rc_out(bp, CD180_PILR2, RC_ACK_TINT);      /* Prio for tx intr     */
-	rc_out(bp, CD180_PILR3, RC_ACK_RINT);      /* Prio for rx intr	   */
-
-	/* Setting up prescaler. We need 4 ticks per 1 ms */
-	rc_out(bp, CD180_PPRH, (RC_OSCFREQ/(1000000/RISCOM_TPS)) >> 8);
-	rc_out(bp, CD180_PPRL, (RC_OSCFREQ/(1000000/RISCOM_TPS)) & 0xff);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-/* Main probing routine, also sets irq. */
-static int __init rc_probe(struct riscom_board *bp)
-{
-	unsigned char val1, val2;
-	int irqs = 0;
-	int retries;
-
-	bp->irq = 0;
-
-	if (rc_request_io_range(bp))
-		return 1;
-
-	/* Are the I/O ports here ? */
-	rc_out(bp, CD180_PPRL, 0x5a);
-	outb(0xff, 0x80);
-	val1 = rc_in(bp, CD180_PPRL);
-	rc_out(bp, CD180_PPRL, 0xa5);
-	outb(0x00, 0x80);
-	val2 = rc_in(bp, CD180_PPRL);
-
-	if ((val1 != 0x5a) || (val2 != 0xa5))  {
-		printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not found.\n",
-		       board_No(bp), bp->base);
-		goto out_release;
-	}
-
-	/* It's time to find IRQ for this board */
-	for (retries = 0; retries < 5 && irqs <= 0; retries++) {
-		irqs = probe_irq_on();
-		rc_init_CD180(bp);		 /* Reset CD180 chip	     */
-		rc_out(bp, CD180_CAR, 2);	 /* Select port 2	     */
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_TXEN); /* Enable transmitter	     */
-		rc_out(bp, CD180_IER, IER_TXRDY);/* Enable tx empty intr     */
-		msleep(50);
-		irqs = probe_irq_off(irqs);
-		val1 = rc_in(bp, RC_BSR);	/* Get Board Status reg	     */
-		val2 = rc_in(bp, RC_ACK_TINT);  /* ACK interrupt	     */
-		rc_init_CD180(bp);	       	/* Reset CD180 again	     */
-
-		if ((val1 & RC_BSR_TINT) || (val2 != (RC_ID | GIVR_IT_TX)))  {
-			printk(KERN_ERR "rc%d: RISCom/8 Board at 0x%03x not "
-					"found.\n", board_No(bp), bp->base);
-			goto out_release;
-		}
-	}
-
-	if (irqs <= 0)  {
-		printk(KERN_ERR "rc%d: Can't find IRQ for RISCom/8 board "
-				"at 0x%03x.\n", board_No(bp), bp->base);
-		goto out_release;
-	}
-	bp->irq = irqs;
-	bp->flags |= RC_BOARD_PRESENT;
-
-	printk(KERN_INFO "rc%d: RISCom/8 Rev. %c board detected at "
-			 "0x%03x, IRQ %d.\n",
-	       board_No(bp),
-	       (rc_in(bp, CD180_GFRCR) & 0x0f) + 'A',   /* Board revision */
-	       bp->base, bp->irq);
-
-	return 0;
-out_release:
-	rc_release_io_range(bp);
-	return 1;
-}
-
-/*
- *
- *  Interrupt processing routines.
- *
- */
-
-static struct riscom_port *rc_get_port(struct riscom_board const *bp,
-					       unsigned char const *what)
-{
-	unsigned char channel;
-	struct riscom_port *port;
-
-	channel = rc_in(bp, CD180_GICR) >> GICR_CHAN_OFF;
-	if (channel < CD180_NCH)  {
-		port = &rc_port[board_No(bp) * RC_NPORT + channel];
-		if (port->port.flags & ASYNC_INITIALIZED)
-			return port;
-	}
-	printk(KERN_ERR "rc%d: %s interrupt from invalid port %d\n",
-	       board_No(bp), what, channel);
-	return NULL;
-}
-
-static void rc_receive_exc(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char status;
-	unsigned char ch, flag;
-
-	port = rc_get_port(bp, "Receive");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-#ifdef RC_REPORT_OVERRUN
-	status = rc_in(bp, CD180_RCSR);
-	if (status & RCSR_OE)
-		port->overrun++;
-	status &= port->mark_mask;
-#else
-	status = rc_in(bp, CD180_RCSR) & port->mark_mask;
-#endif
-	ch = rc_in(bp, CD180_RDR);
-	if (!status)
-		goto out;
-	if (status & RCSR_TOUT)  {
-		printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
-				    "Hardware problems ?\n",
-		       board_No(bp), port_No(port));
-		goto out;
-
-	} else if (status & RCSR_BREAK)  {
-		printk(KERN_INFO "rc%d: port %d: Handling break...\n",
-		       board_No(bp), port_No(port));
-		flag = TTY_BREAK;
-		if (tty && (port->port.flags & ASYNC_SAK))
-			do_SAK(tty);
-
-	} else if (status & RCSR_PE)
-		flag = TTY_PARITY;
-
-	else if (status & RCSR_FE)
-		flag = TTY_FRAME;
-
-	else if (status & RCSR_OE)
-		flag = TTY_OVERRUN;
-	else
-		flag = TTY_NORMAL;
-
-	if (tty) {
-		tty_insert_flip_char(tty, ch, flag);
-		tty_flip_buffer_push(tty);
-	}
-out:
-	tty_kref_put(tty);
-}
-
-static void rc_receive(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	port = rc_get_port(bp, "Receive");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	count = rc_in(bp, CD180_RDCR);
-
-#ifdef RC_REPORT_FIFO
-	port->hits[count > 8 ? 9 : count]++;
-#endif
-
-	while (count--)  {
-		u8 ch = rc_in(bp, CD180_RDR);
-		if (tty)
-			tty_insert_flip_char(tty, ch, TTY_NORMAL);
-	}
-	if (tty) {
-		tty_flip_buffer_push(tty);
-		tty_kref_put(tty);
-	}
-}
-
-static void rc_transmit(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	port = rc_get_port(bp, "Transmit");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	if (port->IER & IER_TXEMPTY) {
-		/* FIFO drained */
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXEMPTY;
-		rc_out(bp, CD180_IER, port->IER);
-		goto out;
-	}
-
-	if ((port->xmit_cnt <= 0 && !port->break_length)
-	    || (tty && (tty->stopped || tty->hw_stopped)))  {
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		rc_out(bp, CD180_IER, port->IER);
-		goto out;
-	}
-
-	if (port->break_length)  {
-		if (port->break_length > 0)  {
-			if (port->COR2 & COR2_ETC)  {
-				rc_out(bp, CD180_TDR, CD180_C_ESC);
-				rc_out(bp, CD180_TDR, CD180_C_SBRK);
-				port->COR2 &= ~COR2_ETC;
-			}
-			count = min_t(int, port->break_length, 0xff);
-			rc_out(bp, CD180_TDR, CD180_C_ESC);
-			rc_out(bp, CD180_TDR, CD180_C_DELAY);
-			rc_out(bp, CD180_TDR, count);
-			port->break_length -= count;
-			if (port->break_length == 0)
-				port->break_length--;
-		} else  {
-			rc_out(bp, CD180_TDR, CD180_C_ESC);
-			rc_out(bp, CD180_TDR, CD180_C_EBRK);
-			rc_out(bp, CD180_COR2, port->COR2);
-			rc_wait_CCR(bp);
-			rc_out(bp, CD180_CCR, CCR_CORCHG2);
-			port->break_length = 0;
-		}
-		goto out;
-	}
-
-	count = CD180_NFIFO;
-	do {
-		rc_out(bp, CD180_TDR, port->port.xmit_buf[port->xmit_tail++]);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-
-	if (port->xmit_cnt <= 0)  {
-		rc_out(bp, CD180_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	if (tty && port->xmit_cnt <= port->wakeup_chars)
-		tty_wakeup(tty);
-out:
-	tty_kref_put(tty);
-}
-
-static void rc_check_modem(struct riscom_board const *bp)
-{
-	struct riscom_port *port;
-	struct tty_struct *tty;
-	unsigned char mcr;
-
-	port = rc_get_port(bp, "Modem");
-	if (port == NULL)
-		return;
-
-	tty = tty_port_tty_get(&port->port);
-
-	mcr = rc_in(bp, CD180_MCR);
-	if (mcr & MCR_CDCHG) {
-		if (rc_in(bp, CD180_MSVR) & MSVR_CD)
-			wake_up_interruptible(&port->port.open_wait);
-		else if (tty)
-			tty_hangup(tty);
-	}
-
-#ifdef RISCOM_BRAIN_DAMAGED_CTS
-	if (mcr & MCR_CTSCHG)  {
-		if (rc_in(bp, CD180_MSVR) & MSVR_CTS)  {
-			port->IER |= IER_TXRDY;
-			if (tty) {
-				tty->hw_stopped = 0;
-				if (port->xmit_cnt <= port->wakeup_chars)
-					tty_wakeup(tty);
-			}
-		} else  {
-			if (tty)
-				tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	if (mcr & MCR_DSRCHG)  {
-		if (rc_in(bp, CD180_MSVR) & MSVR_DSR)  {
-			port->IER |= IER_TXRDY;
-			if (tty) {
-				tty->hw_stopped = 0;
-				if (port->xmit_cnt <= port->wakeup_chars)
-					tty_wakeup(tty);
-			}
-		} else  {
-			if (tty)
-				tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		rc_out(bp, CD180_IER, port->IER);
-	}
-#endif /* RISCOM_BRAIN_DAMAGED_CTS */
-
-	/* Clear change bits */
-	rc_out(bp, CD180_MCR, 0);
-	tty_kref_put(tty);
-}
-
-/* The main interrupt processing routine */
-static irqreturn_t rc_interrupt(int dummy, void *dev_id)
-{
-	unsigned char status;
-	unsigned char ack;
-	struct riscom_board *bp = dev_id;
-	unsigned long loop = 0;
-	int handled = 0;
-
-	if (!(bp->flags & RC_BOARD_ACTIVE))
-		return IRQ_NONE;
-
-	while ((++loop < 16) && ((status = ~(rc_in(bp, RC_BSR))) &
-				 (RC_BSR_TOUT | RC_BSR_TINT |
-				  RC_BSR_MINT | RC_BSR_RINT))) {
-		handled = 1;
-		if (status & RC_BSR_TOUT)
-			printk(KERN_WARNING "rc%d: Got timeout. Hardware "
-					    "error?\n", board_No(bp));
-		else if (status & RC_BSR_RINT) {
-			ack = rc_in(bp, RC_ACK_RINT);
-			if (ack == (RC_ID | GIVR_IT_RCV))
-				rc_receive(bp);
-			else if (ack == (RC_ID | GIVR_IT_REXC))
-				rc_receive_exc(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad receive ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		} else if (status & RC_BSR_TINT) {
-			ack = rc_in(bp, RC_ACK_TINT);
-			if (ack == (RC_ID | GIVR_IT_TX))
-				rc_transmit(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad transmit ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		} else /* if (status & RC_BSR_MINT) */ {
-			ack = rc_in(bp, RC_ACK_MINT);
-			if (ack == (RC_ID | GIVR_IT_MODEM))
-				rc_check_modem(bp);
-			else
-				printk(KERN_WARNING "rc%d: Bad modem ack "
-						    "0x%02x.\n",
-				       board_No(bp), ack);
-		}
-		rc_out(bp, CD180_EOIR, 0);   /* Mark end of interrupt */
-		rc_out(bp, RC_CTOUT, 0);     /* Clear timeout flag    */
-	}
-	return IRQ_RETVAL(handled);
-}
-
-/*
- *  Routines for open & close processing.
- */
-
-/* Called with disabled interrupts */
-static int rc_setup_board(struct riscom_board *bp)
-{
-	int error;
-
-	if (bp->flags & RC_BOARD_ACTIVE)
-		return 0;
-
-	error = request_irq(bp->irq, rc_interrupt, IRQF_DISABLED,
-			    "RISCom/8", bp);
-	if (error)
-		return error;
-
-	rc_out(bp, RC_CTOUT, 0);       		/* Just in case         */
-	bp->DTR = ~0;
-	rc_out(bp, RC_DTR, bp->DTR);	        /* Drop DTR on all ports */
-
-	bp->flags |= RC_BOARD_ACTIVE;
-
-	return 0;
-}
-
-/* Called with disabled interrupts */
-static void rc_shutdown_board(struct riscom_board *bp)
-{
-	if (!(bp->flags & RC_BOARD_ACTIVE))
-		return;
-
-	bp->flags &= ~RC_BOARD_ACTIVE;
-
-	free_irq(bp->irq, NULL);
-
-	bp->DTR = ~0;
-	rc_out(bp, RC_DTR, bp->DTR);	       /* Drop DTR on all ports */
-
-}
-
-/*
- * Setting up port characteristics.
- * Must be called with disabled interrupts
- */
-static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp,
-						struct riscom_port *port)
-{
-	unsigned long baud;
-	long tmp;
-	unsigned char cor1 = 0, cor3 = 0;
-	unsigned char mcor1 = 0, mcor2 = 0;
-
-	port->IER  = 0;
-	port->COR2 = 0;
-	port->MSVR = MSVR_RTS;
-
-	baud = tty_get_baud_rate(tty);
-
-	/* Select port on the board */
-	rc_out(bp, CD180_CAR, port_No(port));
-
-	if (!baud)  {
-		/* Drop DTR & exit */
-		bp->DTR |= (1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-		return;
-	} else  {
-		/* Set DTR on */
-		bp->DTR &= ~(1u << port_No(port));
-		rc_out(bp, RC_DTR, bp->DTR);
-	}
-
-	/*
-	 * Now we must calculate some speed depended things
-	 */
-
-	/* Set baud rate for port */
-	tmp = (((RC_OSCFREQ + baud/2) / baud +
-		CD180_TPC/2) / CD180_TPC);
-
-	rc_out(bp, CD180_RBPRH, (tmp >> 8) & 0xff);
-	rc_out(bp, CD180_TBPRH, (tmp >> 8) & 0xff);
-	rc_out(bp, CD180_RBPRL, tmp & 0xff);
-	rc_out(bp, CD180_TBPRL, tmp & 0xff);
-
-	baud = (baud + 5) / 10;   /* Estimated CPS */
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD180_NFIFO;
-	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-					      SERIAL_XMIT_SIZE - 1 : tmp);
-
-	/* Receiver timeout will be transmission time for 1.5 chars */
-	tmp = (RISCOM_TPS + RISCOM_TPS/2 + baud/2) / baud;
-	tmp = (tmp > 0xff) ? 0xff : tmp;
-	rc_out(bp, CD180_RTPR, tmp);
-
-	switch (C_CSIZE(tty)) {
-	case CS5:
-		cor1 |= COR1_5BITS;
-		break;
-	case CS6:
-		cor1 |= COR1_6BITS;
-		break;
-	case CS7:
-		cor1 |= COR1_7BITS;
-		break;
-	case CS8:
-		cor1 |= COR1_8BITS;
-		break;
-	}
-	if (C_CSTOPB(tty))
-		cor1 |= COR1_2SB;
-
-	cor1 |= COR1_IGNORE;
-	if (C_PARENB(tty)) {
-		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty))
-			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty))
-			cor1 &= ~COR1_IGNORE;
-	}
-	/* Set marking of some errors */
-	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty))
-		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty))
-		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-	if (I_IGNBRK(tty)) {
-		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty))
-			/* Real raw mode. Ignore all */
-			port->mark_mask &= ~RCSR_OE;
-	}
-	/* Enable Hardware Flow Control */
-	if (C_CRTSCTS(tty))  {
-#ifdef RISCOM_BRAIN_DAMAGED_CTS
-		port->IER |= IER_DSR | IER_CTS;
-		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
-		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-		tty->hw_stopped = !(rc_in(bp, CD180_MSVR) &
-						(MSVR_CTS|MSVR_DSR));
-#else
-		port->COR2 |= COR2_CTSAE;
-#endif
-	}
-	/* Enable Software Flow Control. FIXME: I'm not sure about this */
-	/* Some people reported that it works, but I still doubt */
-	if (I_IXON(tty))  {
-		port->COR2 |= COR2_TXIBE;
-		cor3 |= (COR3_FCT | COR3_SCDE);
-		if (I_IXANY(tty))
-			port->COR2 |= COR2_IXM;
-		rc_out(bp, CD180_SCHR1, START_CHAR(tty));
-		rc_out(bp, CD180_SCHR2, STOP_CHAR(tty));
-		rc_out(bp, CD180_SCHR3, START_CHAR(tty));
-		rc_out(bp, CD180_SCHR4, STOP_CHAR(tty));
-	}
-	if (!C_CLOCAL(tty))  {
-		/* Enable CD check */
-		port->IER |= IER_CD;
-		mcor1 |= MCOR1_CDZD;
-		mcor2 |= MCOR2_CDOD;
-	}
-
-	if (C_CREAD(tty))
-		/* Enable receiver */
-		port->IER |= IER_RXD;
-
-	/* Set input FIFO size (1-8 bytes) */
-	cor3 |= RISCOM_RXFIFO;
-	/* Setting up CD180 channel registers */
-	rc_out(bp, CD180_COR1, cor1);
-	rc_out(bp, CD180_COR2, port->COR2);
-	rc_out(bp, CD180_COR3, cor3);
-	/* Make CD180 know about registers change */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
-	/* Setting up modem option registers */
-	rc_out(bp, CD180_MCOR1, mcor1);
-	rc_out(bp, CD180_MCOR2, mcor2);
-	/* Enable CD180 transmitter & receiver */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_TXEN | CCR_RXEN);
-	/* Enable interrupts */
-	rc_out(bp, CD180_IER, port->IER);
-	/* And finally set RTS on */
-	rc_out(bp, CD180_MSVR, port->MSVR);
-}
-
-/* Must be called with interrupts enabled */
-static int rc_activate_port(struct tty_port *port, struct tty_struct *tty)
-{
-	struct riscom_port *rp = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(rp);
-	unsigned long flags;
-
-	if (tty_port_alloc_xmit_buf(port) < 0)
-		return -ENOMEM;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	clear_bit(TTY_IO_ERROR, &tty->flags);
-	bp->count++;
-	rp->xmit_cnt = rp->xmit_head = rp->xmit_tail = 0;
-	rc_change_speed(tty, bp, rp);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return 0;
-}
-
-/* Must be called with interrupts disabled */
-static void rc_shutdown_port(struct tty_struct *tty,
-			struct riscom_board *bp, struct riscom_port *port)
-{
-#ifdef RC_REPORT_OVERRUN
-	printk(KERN_INFO "rc%d: port %d: Total %ld overruns were detected.\n",
-	       board_No(bp), port_No(port), port->overrun);
-#endif
-#ifdef RC_REPORT_FIFO
-	{
-		int i;
-
-		printk(KERN_INFO "rc%d: port %d: FIFO hits [ ",
-		       board_No(bp), port_No(port));
-		for (i = 0; i < 10; i++)
-			printk("%ld ", port->hits[i]);
-		printk("].\n");
-	}
-#endif
-	tty_port_free_xmit_buf(&port->port);
-
-	/* Select port */
-	rc_out(bp, CD180_CAR, port_No(port));
-	/* Reset port */
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_SOFTRESET);
-	/* Disable all interrupts from this port */
-	port->IER = 0;
-	rc_out(bp, CD180_IER, port->IER);
-
-	set_bit(TTY_IO_ERROR, &tty->flags);
-
-	if (--bp->count < 0)  {
-		printk(KERN_INFO "rc%d: rc_shutdown_port: "
-				 "bad board count: %d\n",
-		       board_No(bp), bp->count);
-		bp->count = 0;
-	}
-	/*
-	 * If this is the last opened port on the board
-	 * shutdown whole board
-	 */
-	if (!bp->count)
-		rc_shutdown_board(bp);
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	struct riscom_port *p = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(p);
-	unsigned long flags;
-	int CD;
-	
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_out(bp, CD180_CAR, port_No(p));
-	CD = rc_in(bp, CD180_MSVR) & MSVR_CD;
-	rc_out(bp, CD180_MSVR, MSVR_RTS);
-	bp->DTR &= ~(1u << port_No(p));
-	rc_out(bp, RC_DTR, bp->DTR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return CD;
-}
-
-static void dtr_rts(struct tty_port *port, int onoff)
-{
-	struct riscom_port *p = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(p);
-	unsigned long flags;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	bp->DTR &= ~(1u << port_No(p));
-	if (onoff == 0)
-		bp->DTR |= (1u << port_No(p));
-	rc_out(bp, RC_DTR, bp->DTR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static int rc_open(struct tty_struct *tty, struct file *filp)
-{
-	int board;
-	int error;
-	struct riscom_port *port;
-	struct riscom_board *bp;
-
-	board = RC_BOARD(tty->index);
-	if (board >= RC_NBOARD || !(rc_board[board].flags & RC_BOARD_PRESENT))
-		return -ENODEV;
-
-	bp = &rc_board[board];
-	port = rc_port + board * RC_NPORT + RC_PORT(tty->index);
-	if (rc_paranoia_check(port, tty->name, "rc_open"))
-		return -ENODEV;
-
-	error = rc_setup_board(bp);
-	if (error)
-		return error;
-
-	tty->driver_data = port;
-	return tty_port_open(&port->port, tty, filp);
-}
-
-static void rc_flush_buffer(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	tty_wakeup(tty);
-}
-
-static void rc_close_port(struct tty_port *port)
-{
-	unsigned long flags;
-	struct riscom_port *rp = container_of(port, struct riscom_port, port);
-	struct riscom_board *bp = port_Board(rp);
-	unsigned long timeout;
-	
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	rp->IER &= ~IER_RXD;
-
-	rp->IER &= ~IER_TXRDY;
-	rp->IER |= IER_TXEMPTY;
-	rc_out(bp, CD180_CAR, port_No(rp));
-	rc_out(bp, CD180_IER, rp->IER);
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = jiffies + HZ;
-	while (rp->IER & IER_TXEMPTY) {
-		spin_unlock_irqrestore(&riscom_lock, flags);
-		msleep_interruptible(jiffies_to_msecs(rp->timeout));
-		spin_lock_irqsave(&riscom_lock, flags);
-		if (time_after(jiffies, timeout))
-			break;
-	}
-	rc_shutdown_port(port->tty, bp, rp);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_close(struct tty_struct *tty, struct file *filp)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (!port || rc_paranoia_check(port, tty->name, "close"))
-		return;
-	tty_port_close(&port->port, tty, filp);
-}
-
-static int rc_write(struct tty_struct *tty,
-		    const unsigned char *buf, int count)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	int c, total = 0;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_write"))
-		return 0;
-
-	bp = port_Board(port);
-
-	while (1) {
-		spin_lock_irqsave(&riscom_lock, flags);
-
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0)
-			break;	/* lock continues to be held */
-
-		memcpy(port->port.xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-
-		spin_unlock_irqrestore(&riscom_lock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-	    !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		rc_out(bp, CD180_CAR, port_No(port));
-		rc_out(bp, CD180_IER, port->IER);
-	}
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	return total;
-}
-
-static int rc_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (rc_paranoia_check(port, tty->name, "rc_put_char"))
-		return 0;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
-		goto out;
-
-	port->port.xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;
-	ret = 1;
-
-out:
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return ret;
-}
-
-static void rc_flush_chars(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_flush_chars"))
-		return;
-
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped)
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	port->IER |= IER_TXRDY;
-	rc_out(port_Board(port), CD180_CAR, port_No(port));
-	rc_out(port_Board(port), CD180_IER, port->IER);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static int rc_write_room(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	int	ret;
-
-	if (rc_paranoia_check(port, tty->name, "rc_write_room"))
-		return 0;
-
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}
-
-static int rc_chars_in_buffer(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (rc_paranoia_check(port, tty->name, "rc_chars_in_buffer"))
-		return 0;
-
-	return port->xmit_cnt;
-}
-
-static int rc_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, __func__))
-		return -ENODEV;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	rc_out(bp, CD180_CAR, port_No(port));
-	status = rc_in(bp, CD180_MSVR);
-	result = rc_in(bp, RC_RI) & (1u << port_No(port)) ? 0 : TIOCM_RNG;
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	result |= ((status & MSVR_RTS) ? TIOCM_RTS : 0)
-		| ((status & MSVR_DTR) ? TIOCM_DTR : 0)
-		| ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-		| ((status & MSVR_DSR) ? TIOCM_DSR : 0)
-		| ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	return result;
-}
-
-static int rc_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-	struct riscom_board *bp;
-
-	if (rc_paranoia_check(port, tty->name, __func__))
-		return -ENODEV;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (set & TIOCM_RTS)
-		port->MSVR |= MSVR_RTS;
-	if (set & TIOCM_DTR)
-		bp->DTR &= ~(1u << port_No(port));
-
-	if (clear & TIOCM_RTS)
-		port->MSVR &= ~MSVR_RTS;
-	if (clear & TIOCM_DTR)
-		bp->DTR |= (1u << port_No(port));
-
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	rc_out(bp, RC_DTR, bp->DTR);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	return 0;
-}
-
-static int rc_send_break(struct tty_struct *tty, int length)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp = port_Board(port);
-	unsigned long flags;
-
-	if (length == 0 || length == -1)
-		return -EOPNOTSUPP;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	port->break_length = RISCOM_TPS / HZ * length;
-	port->COR2 |= COR2_ETC;
-	port->IER  |= IER_TXRDY;
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_COR2, port->COR2);
-	rc_out(bp, CD180_IER, port->IER);
-	rc_wait_CCR(bp);
-	rc_out(bp, CD180_CCR, CCR_CORCHG2);
-	rc_wait_CCR(bp);
-
-	spin_unlock_irqrestore(&riscom_lock, flags);
-	return 0;
-}
-
-static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
-				     struct serial_struct __user *newinfo)
-{
-	struct serial_struct tmp;
-	struct riscom_board *bp = port_Board(port);
-	int change_speed;
-
-	if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
-		return -EFAULT;
-
-	mutex_lock(&port->port.mutex);
-	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
-			(tmp.flags & ASYNC_SPD_MASK));
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((tmp.close_delay != port->port.close_delay) ||
-		    (tmp.closing_wait != port->port.closing_wait) ||
-		    ((tmp.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-			       (tmp.flags & ASYNC_USR_MASK));
-	} else  {
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-			       (tmp.flags & ASYNC_FLAGS));
-		port->port.close_delay = tmp.close_delay;
-		port->port.closing_wait = tmp.closing_wait;
-	}
-	if (change_speed)  {
-		unsigned long flags;
-
-		spin_lock_irqsave(&riscom_lock, flags);
-		rc_change_speed(tty, bp, port);
-		spin_unlock_irqrestore(&riscom_lock, flags);
-	}
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-static int rc_get_serial_info(struct riscom_port *port,
-				     struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-	struct riscom_board *bp = port_Board(port);
-
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = PORT_CIRRUS;
-	tmp.line = port - rc_port;
-
-	mutex_lock(&port->port.mutex);
-	tmp.port = bp->base;
-	tmp.irq  = bp->irq;
-	tmp.flags = port->port.flags;
-	tmp.baud_base = (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC;
-	tmp.close_delay = port->port.close_delay * HZ/100;
-	tmp.closing_wait = port->port.closing_wait * HZ/100;
-	mutex_unlock(&port->port.mutex);
-	tmp.xmit_fifo_size = CD180_NFIFO;
-	return copy_to_user(retinfo, &tmp, sizeof(tmp)) ? -EFAULT : 0;
-}
-
-static int rc_ioctl(struct tty_struct *tty, struct file *filp,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct riscom_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int retval;
-
-	if (rc_paranoia_check(port, tty->name, "rc_ioctl"))
-		return -ENODEV;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		retval = rc_get_serial_info(port, argp);
-		break;
-	case TIOCSSERIAL:
-		retval = rc_set_serial_info(tty, port, argp);
-		break;
-	default:
-		retval = -ENOIOCTLCMD;
-	}
-	return retval;
-}
-
-static void rc_throttle(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_throttle"))
-		return;
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->MSVR &= ~MSVR_RTS;
-	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty)) {
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_SSCH2);
-		rc_wait_CCR(bp);
-	}
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_unthrottle(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_unthrottle"))
-		return;
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->MSVR |= MSVR_RTS;
-	rc_out(bp, CD180_CAR, port_No(port));
-	if (I_IXOFF(tty))  {
-		rc_wait_CCR(bp);
-		rc_out(bp, CD180_CCR, CCR_SSCH1);
-		rc_wait_CCR(bp);
-	}
-	rc_out(bp, CD180_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_stop(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_stop"))
-		return;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	port->IER &= ~IER_TXRDY;
-	rc_out(bp, CD180_CAR, port_No(port));
-	rc_out(bp, CD180_IER, port->IER);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_start(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-	struct riscom_board *bp;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_start"))
-		return;
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&riscom_lock, flags);
-
-	if (port->xmit_cnt && port->port.xmit_buf && !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		rc_out(bp, CD180_CAR, port_No(port));
-		rc_out(bp, CD180_IER, port->IER);
-	}
-	spin_unlock_irqrestore(&riscom_lock, flags);
-}
-
-static void rc_hangup(struct tty_struct *tty)
-{
-	struct riscom_port *port = tty->driver_data;
-
-	if (rc_paranoia_check(port, tty->name, "rc_hangup"))
-		return;
-
-	tty_port_hangup(&port->port);
-}
-
-static void rc_set_termios(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct riscom_port *port = tty->driver_data;
-	unsigned long flags;
-
-	if (rc_paranoia_check(port, tty->name, "rc_set_termios"))
-		return;
-
-	spin_lock_irqsave(&riscom_lock, flags);
-	rc_change_speed(tty, port_Board(port), port);
-	spin_unlock_irqrestore(&riscom_lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rc_start(tty);
-	}
-}
-
-static const struct tty_operations riscom_ops = {
-	.open  = rc_open,
-	.close = rc_close,
-	.write = rc_write,
-	.put_char = rc_put_char,
-	.flush_chars = rc_flush_chars,
-	.write_room = rc_write_room,
-	.chars_in_buffer = rc_chars_in_buffer,
-	.flush_buffer = rc_flush_buffer,
-	.ioctl = rc_ioctl,
-	.throttle = rc_throttle,
-	.unthrottle = rc_unthrottle,
-	.set_termios = rc_set_termios,
-	.stop = rc_stop,
-	.start = rc_start,
-	.hangup = rc_hangup,
-	.tiocmget = rc_tiocmget,
-	.tiocmset = rc_tiocmset,
-	.break_ctl = rc_send_break,
-};
-
-static const struct tty_port_operations riscom_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-	.shutdown = rc_close_port,
-	.activate = rc_activate_port,
-};
-
-
-static int __init rc_init_drivers(void)
-{
-	int error;
-	int i;
-
-	riscom_driver = alloc_tty_driver(RC_NBOARD * RC_NPORT);
-	if (!riscom_driver)
-		return -ENOMEM;
-
-	riscom_driver->owner = THIS_MODULE;
-	riscom_driver->name = "ttyL";
-	riscom_driver->major = RISCOM8_NORMAL_MAJOR;
-	riscom_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	riscom_driver->subtype = SERIAL_TYPE_NORMAL;
-	riscom_driver->init_termios = tty_std_termios;
-	riscom_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	riscom_driver->init_termios.c_ispeed = 9600;
-	riscom_driver->init_termios.c_ospeed = 9600;
-	riscom_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(riscom_driver, &riscom_ops);
-	error = tty_register_driver(riscom_driver);
-	if (error != 0) {
-		put_tty_driver(riscom_driver);
-		printk(KERN_ERR "rc: Couldn't register RISCom/8 driver, "
-				"error = %d\n", error);
-		return 1;
-	}
-	memset(rc_port, 0, sizeof(rc_port));
-	for (i = 0; i < RC_NPORT * RC_NBOARD; i++)  {
-		tty_port_init(&rc_port[i].port);
-		rc_port[i].port.ops = &riscom_port_ops;
-		rc_port[i].magic = RISCOM8_MAGIC;
-	}
-	return 0;
-}
-
-static void rc_release_drivers(void)
-{
-	tty_unregister_driver(riscom_driver);
-	put_tty_driver(riscom_driver);
-}
-
-#ifndef MODULE
-/*
- * Called at boot time.
- *
- * You can specify IO base for up to RC_NBOARD cards,
- * using line "riscom8=0xiobase1,0xiobase2,.." at LILO prompt.
- * Note that there will be no probing at default
- * addresses in this case.
- *
- */
-static int __init riscom8_setup(char *str)
-{
-	int ints[RC_NBOARD];
-	int i;
-
-	str = get_options(str, ARRAY_SIZE(ints), ints);
-
-	for (i = 0; i < RC_NBOARD; i++) {
-		if (i < ints[0])
-			rc_board[i].base = ints[i+1];
-		else
-			rc_board[i].base = 0;
-	}
-	return 1;
-}
-
-__setup("riscom8=", riscom8_setup);
-#endif
-
-static char banner[] __initdata =
-	KERN_INFO "rc: SDL RISCom/8 card driver v1.1, (c) D.Gorodchanin "
-		  "1994-1996.\n";
-static char no_boards_msg[] __initdata =
-	KERN_INFO "rc: No RISCom/8 boards detected.\n";
-
-/*
- * This routine must be called by kernel at boot time
- */
-static int __init riscom8_init(void)
-{
-	int i;
-	int found = 0;
-
-	printk(banner);
-
-	if (rc_init_drivers())
-		return -EIO;
-
-	for (i = 0; i < RC_NBOARD; i++)
-		if (rc_board[i].base && !rc_probe(&rc_board[i]))
-			found++;
-	if (!found)  {
-		rc_release_drivers();
-		printk(no_boards_msg);
-		return -EIO;
-	}
-	return 0;
-}
-
-#ifdef MODULE
-static int iobase;
-static int iobase1;
-static int iobase2;
-static int iobase3;
-module_param(iobase, int, 0);
-module_param(iobase1, int, 0);
-module_param(iobase2, int, 0);
-module_param(iobase3, int, 0);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(RISCOM8_NORMAL_MAJOR);
-#endif /* MODULE */
-
-/*
- * You can setup up to 4 boards (current value of RC_NBOARD)
- * by specifying "iobase=0xXXX iobase1=0xXXX ..." as insmod parameter.
- *
- */
-static int __init riscom8_init_module(void)
-{
-#ifdef MODULE
-	int i;
-
-	if (iobase || iobase1 || iobase2 || iobase3) {
-		for (i = 0; i < RC_NBOARD; i++)
-			rc_board[i].base = 0;
-	}
-
-	if (iobase)
-		rc_board[0].base = iobase;
-	if (iobase1)
-		rc_board[1].base = iobase1;
-	if (iobase2)
-		rc_board[2].base = iobase2;
-	if (iobase3)
-		rc_board[3].base = iobase3;
-#endif /* MODULE */
-
-	return riscom8_init();
-}
-
-static void __exit riscom8_exit_module(void)
-{
-	int i;
-
-	rc_release_drivers();
-	for (i = 0; i < RC_NBOARD; i++)
-		if (rc_board[i].flags & RC_BOARD_PRESENT)
-			rc_release_io_range(&rc_board[i]);
-
-}
-
-module_init(riscom8_init_module);
-module_exit(riscom8_exit_module);
diff -druN linux-libre-2.6.38-gnu/drivers/char/riscom8.h linux-libre-2.6.39-gnu/drivers/char/riscom8.h
--- linux-libre-2.6.38-gnu/drivers/char/riscom8.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/riscom8.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/*
- *      linux/drivers/char/riscom8.h  -- RISCom/8 multiport serial driver.
- *
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      This code is loosely based on the Linux serial driver, written by
- *      Linus Torvalds, Theodore T'so and others. The RISCom/8 card 
- *      programming info was obtained from various drivers for other OSes 
- *	(FreeBSD, ISC, etc), but no source code from those drivers were 
- *	directly included in this driver.
- *
- *
- *      This program is free software; you can redistribute it and/or modify
- *      it under the terms of the 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 __LINUX_RISCOM8_H
-#define __LINUX_RISCOM8_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-#define RC_NBOARD		4
-/* NOTE: RISCom decoder recognizes 16 addresses... */
-#define RC_NPORT        	8  
-#define RC_BOARD(line)		(((line) >> 3) & 0x07)
-#define RC_PORT(line)		((line) & (RC_NPORT - 1))
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define RISCOM_TPS		4000
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define RISCOM_RXFIFO		6	/* Max. receiver FIFO size (1-8) */
-
-#define RISCOM8_MAGIC		0x0907
-
-#define RC_IOBASE1	0x220
-#define RC_IOBASE2	0x240
-#define RC_IOBASE3	0x250
-#define RC_IOBASE4	0x260
-
-struct riscom_board {
-	unsigned long   flags;
-	unsigned short	base;
-	unsigned char 	irq;
-	signed   char	count;
-	unsigned char	DTR;
-};
-
-#define RC_BOARD_PRESENT	0x00000001
-#define RC_BOARD_ACTIVE		0x00000002
-	
-struct riscom_port {
-	int			magic;
-	struct			tty_port port;
-	int			baud_base;
-	int			timeout;
-	int			custom_divisor;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	short			wakeup_chars;
-	short			break_length;
-	unsigned char		mark_mask;
-	unsigned char		IER;
-	unsigned char		MSVR;
-	unsigned char		COR2;
-#ifdef RC_REPORT_OVERRUN
-	unsigned long		overrun;
-#endif	
-#ifdef RC_REPORT_FIFO
-	unsigned long		hits[10];
-#endif
-};
-
-#endif /* __KERNEL__ */
-#endif /* __LINUX_RISCOM8_H */
diff -druN linux-libre-2.6.38-gnu/drivers/char/riscom8_reg.h linux-libre-2.6.39-gnu/drivers/char/riscom8_reg.h
--- linux-libre-2.6.38-gnu/drivers/char/riscom8_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/riscom8_reg.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,254 +0,0 @@
-/*
- *      linux/drivers/char/riscom8_reg.h  -- RISCom/8 multiport serial driver.
- */
-
-/*
- * Definitions for RISCom/8 Async Mux card by SDL Communications, Inc.
- */
-
-/*
- * Address mapping between Cirrus Logic CD180 chip internal registers
- * and ISA port addresses:
- *
- *      CL-CD180                A6  A5   A4  A3                      A2 A1 A0
- *      ISA             A15 A14 A13 A12  A11 A10 A9 A8  A7 A6 A5 A4  A3 A2 A1 A0
- */
-#define RC_TO_ISA(r)    ((((r)&0x07)<<1) | (((r)&~0x07)<<7))
-
-
-/* RISCom/8 On-Board Registers (assuming address translation) */
-
-#define RC_RI           0x100   /* Ring Indicator Register (R/O)           */
-#define RC_DTR          0x100   /* DTR Register (W/O)                      */
-#define RC_BSR          0x101   /* Board Status Register (R/O)             */
-#define RC_CTOUT        0x101   /* Clear Timeout (W/O)                     */
-
-
-/* Board Status Register */
-
-#define RC_BSR_TOUT     0x08     /* Hardware Timeout                       */
-#define RC_BSR_RINT     0x04     /* Receiver Interrupt                     */
-#define RC_BSR_TINT     0x02     /* Transmitter Interrupt                  */
-#define RC_BSR_MINT     0x01     /* Modem Ctl Interrupt                    */
-
-
-/* On-board oscillator frequency (in Hz) */
-#define RC_OSCFREQ      9830400
-
-/* Values of choice for Interrupt ACKs */
-#define RC_ACK_MINT     0x81    /* goes to PILR1                           */
-#define RC_ACK_RINT     0x82    /* goes to PILR3                           */
-#define RC_ACK_TINT     0x84    /* goes to PILR2                           */
-
-/* Chip ID (sorry, only one chip now) */
-#define RC_ID           0x10
-
-/* Definitions for Cirrus Logic CL-CD180 8-port async mux chip */
- 
-#define CD180_NCH       8       /* Total number of channels                */
-#define CD180_TPC       16      /* Ticks per character                     */
-#define CD180_NFIFO	8	/* TX FIFO size                            */
-
-
-/* Global registers */
-
-#define CD180_GIVR      0x40    /* Global Interrupt Vector Register        */
-#define CD180_GICR      0x41    /* Global Interrupting Channel Register    */
-#define CD180_PILR1     0x61    /* Priority Interrupt Level Register 1     */
-#define CD180_PILR2     0x62    /* Priority Interrupt Level Register 2     */
-#define CD180_PILR3     0x63    /* Priority Interrupt Level Register 3     */
-#define CD180_CAR       0x64    /* Channel Access Register                 */
-#define CD180_GFRCR     0x6b    /* Global Firmware Revision Code Register  */
-#define CD180_PPRH      0x70    /* Prescaler Period Register High          */
-#define CD180_PPRL      0x71    /* Prescaler Period Register Low           */
-#define CD180_RDR       0x78    /* Receiver Data Register                  */
-#define CD180_RCSR      0x7a    /* Receiver Character Status Register      */
-#define CD180_TDR       0x7b    /* Transmit Data Register                  */
-#define CD180_EOIR      0x7f    /* End of Interrupt Register               */
-
-
-/* Channel Registers */
-
-#define CD180_CCR       0x01    /* Channel Command Register                */
-#define CD180_IER       0x02    /* Interrupt Enable Register               */
-#define CD180_COR1      0x03    /* Channel Option Register 1               */
-#define CD180_COR2      0x04    /* Channel Option Register 2               */
-#define CD180_COR3      0x05    /* Channel Option Register 3               */
-#define CD180_CCSR      0x06    /* Channel Control Status Register         */
-#define CD180_RDCR      0x07    /* Receive Data Count Register             */
-#define CD180_SCHR1     0x09    /* Special Character Register 1            */
-#define CD180_SCHR2     0x0a    /* Special Character Register 2            */
-#define CD180_SCHR3     0x0b    /* Special Character Register 3            */
-#define CD180_SCHR4     0x0c    /* Special Character Register 4            */
-#define CD180_MCOR1     0x10    /* Modem Change Option 1 Register          */
-#define CD180_MCOR2     0x11    /* Modem Change Option 2 Register          */
-#define CD180_MCR       0x12    /* Modem Change Register                   */
-#define CD180_RTPR      0x18    /* Receive Timeout Period Register         */
-#define CD180_MSVR      0x28    /* Modem Signal Value Register             */
-#define CD180_RBPRH     0x31    /* Receive Baud Rate Period Register High  */
-#define CD180_RBPRL     0x32    /* Receive Baud Rate Period Register Low   */
-#define CD180_TBPRH     0x39    /* Transmit Baud Rate Period Register High */
-#define CD180_TBPRL     0x3a    /* Transmit Baud Rate Period Register Low  */
-
-
-/* Global Interrupt Vector Register (R/W) */
-
-#define GIVR_ITMASK     0x07     /* Interrupt type mask                     */
-#define  GIVR_IT_MODEM   0x01    /* Modem Signal Change Interrupt           */
-#define  GIVR_IT_TX      0x02    /* Transmit Data Interrupt                 */
-#define  GIVR_IT_RCV     0x03    /* Receive Good Data Interrupt             */
-#define  GIVR_IT_REXC    0x07    /* Receive Exception Interrupt             */
-
-
-/* Global Interrupt Channel Register (R/W) */
- 
-#define GICR_CHAN       0x1c    /* Channel Number Mask                     */
-#define GICR_CHAN_OFF   2       /* Channel Number Offset                   */
-
-
-/* Channel Address Register (R/W) */
-
-#define CAR_CHAN        0x07    /* Channel Number Mask                     */
-#define CAR_A7          0x08    /* A7 Address Extension (unused)           */
-
-
-/* Receive Character Status Register (R/O) */
-
-#define RCSR_TOUT       0x80    /* Rx Timeout                              */
-#define RCSR_SCDET      0x70    /* Special Character Detected Mask         */
-#define  RCSR_NO_SC      0x00   /* No Special Characters Detected          */
-#define  RCSR_SC_1       0x10   /* Special Char 1 (or 1 & 3) Detected      */
-#define  RCSR_SC_2       0x20   /* Special Char 2 (or 2 & 4) Detected      */
-#define  RCSR_SC_3       0x30   /* Special Char 3 Detected                 */
-#define  RCSR_SC_4       0x40   /* Special Char 4 Detected                 */
-#define RCSR_BREAK      0x08    /* Break has been detected                 */
-#define RCSR_PE         0x04    /* Parity Error                            */
-#define RCSR_FE         0x02    /* Frame Error                             */
-#define RCSR_OE         0x01    /* Overrun Error                           */
-
-
-/* Channel Command Register (R/W) (commands in groups can be OR-ed) */
-
-#define CCR_HARDRESET   0x81    /* Reset the chip                          */
-
-#define CCR_SOFTRESET   0x80    /* Soft Channel Reset                      */
-
-#define CCR_CORCHG1     0x42    /* Channel Option Register 1 Changed       */
-#define CCR_CORCHG2     0x44    /* Channel Option Register 2 Changed       */
-#define CCR_CORCHG3     0x48    /* Channel Option Register 3 Changed       */
-
-#define CCR_SSCH1       0x21    /* Send Special Character 1                */
-
-#define CCR_SSCH2       0x22    /* Send Special Character 2                */
-
-#define CCR_SSCH3       0x23    /* Send Special Character 3                */
-
-#define CCR_SSCH4       0x24    /* Send Special Character 4                */
-
-#define CCR_TXEN        0x18    /* Enable Transmitter                      */
-#define CCR_RXEN        0x12    /* Enable Receiver                         */
-
-#define CCR_TXDIS       0x14    /* Disable Transmitter                     */
-#define CCR_RXDIS       0x11    /* Disable Receiver                        */
-
-
-/* Interrupt Enable Register (R/W) */
-
-#define IER_DSR         0x80    /* Enable interrupt on DSR change          */
-#define IER_CD          0x40    /* Enable interrupt on CD change           */
-#define IER_CTS         0x20    /* Enable interrupt on CTS change          */
-#define IER_RXD         0x10    /* Enable interrupt on Receive Data        */
-#define IER_RXSC        0x08    /* Enable interrupt on Receive Spec. Char  */
-#define IER_TXRDY       0x04    /* Enable interrupt on TX FIFO empty       */
-#define IER_TXEMPTY     0x02    /* Enable interrupt on TX completely empty */
-#define IER_RET         0x01    /* Enable interrupt on RX Exc. Timeout     */
-
-
-/* Channel Option Register 1 (R/W) */
-
-#define COR1_ODDP       0x80    /* Odd Parity                              */
-#define COR1_PARMODE    0x60    /* Parity Mode mask                        */
-#define  COR1_NOPAR      0x00   /* No Parity                               */
-#define  COR1_FORCEPAR   0x20   /* Force Parity                            */
-#define  COR1_NORMPAR    0x40   /* Normal Parity                           */
-#define COR1_IGNORE     0x10    /* Ignore Parity on RX                     */
-#define COR1_STOPBITS   0x0c    /* Number of Stop Bits                     */
-#define  COR1_1SB        0x00   /* 1 Stop Bit                              */
-#define  COR1_15SB       0x04   /* 1.5 Stop Bits                           */
-#define  COR1_2SB        0x08   /* 2 Stop Bits                             */
-#define COR1_CHARLEN    0x03    /* Character Length                        */
-#define  COR1_5BITS      0x00   /* 5 bits                                  */
-#define  COR1_6BITS      0x01   /* 6 bits                                  */
-#define  COR1_7BITS      0x02   /* 7 bits                                  */
-#define  COR1_8BITS      0x03   /* 8 bits                                  */
-
-
-/* Channel Option Register 2 (R/W) */
-
-#define COR2_IXM        0x80    /* Implied XON mode                        */
-#define COR2_TXIBE      0x40    /* Enable In-Band (XON/XOFF) Flow Control  */
-#define COR2_ETC        0x20    /* Embedded Tx Commands Enable             */
-#define COR2_LLM        0x10    /* Local Loopback Mode                     */
-#define COR2_RLM        0x08    /* Remote Loopback Mode                    */
-#define COR2_RTSAO      0x04    /* RTS Automatic Output Enable             */
-#define COR2_CTSAE      0x02    /* CTS Automatic Enable                    */
-#define COR2_DSRAE      0x01    /* DSR Automatic Enable                    */
-
-
-/* Channel Option Register 3 (R/W) */
-
-#define COR3_XONCH      0x80    /* XON is a pair of characters (1 & 3)     */
-#define COR3_XOFFCH     0x40    /* XOFF is a pair of characters (2 & 4)    */
-#define COR3_FCT        0x20    /* Flow-Control Transparency Mode          */
-#define COR3_SCDE       0x10    /* Special Character Detection Enable      */
-#define COR3_RXTH       0x0f    /* RX FIFO Threshold value (1-8)           */
-
-
-/* Channel Control Status Register (R/O) */
-
-#define CCSR_RXEN       0x80    /* Receiver Enabled                        */
-#define CCSR_RXFLOFF    0x40    /* Receive Flow Off (XOFF was sent)        */
-#define CCSR_RXFLON     0x20    /* Receive Flow On (XON was sent)          */
-#define CCSR_TXEN       0x08    /* Transmitter Enabled                     */
-#define CCSR_TXFLOFF    0x04    /* Transmit Flow Off (got XOFF)            */
-#define CCSR_TXFLON     0x02    /* Transmit Flow On (got XON)              */
-
-
-/* Modem Change Option Register 1 (R/W) */
-
-#define MCOR1_DSRZD     0x80    /* Detect 0->1 transition of DSR           */
-#define MCOR1_CDZD      0x40    /* Detect 0->1 transition of CD            */
-#define MCOR1_CTSZD     0x20    /* Detect 0->1 transition of CTS           */
-#define MCOR1_DTRTH     0x0f    /* Auto DTR flow control Threshold (1-8)   */
-#define  MCOR1_NODTRFC   0x0     /* Automatic DTR flow control disabled     */
-
-
-/* Modem Change Option Register 2 (R/W) */
-
-#define MCOR2_DSROD     0x80    /* Detect 1->0 transition of DSR           */
-#define MCOR2_CDOD      0x40    /* Detect 1->0 transition of CD            */
-#define MCOR2_CTSOD     0x20    /* Detect 1->0 transition of CTS           */
-
-
-/* Modem Change Register (R/W) */
-
-#define MCR_DSRCHG      0x80    /* DSR Changed                             */
-#define MCR_CDCHG       0x40    /* CD Changed                              */
-#define MCR_CTSCHG      0x20    /* CTS Changed                             */
-
-
-/* Modem Signal Value Register (R/W) */
-
-#define MSVR_DSR        0x80    /* Current state of DSR input              */
-#define MSVR_CD         0x40    /* Current state of CD input               */
-#define MSVR_CTS        0x20    /* Current state of CTS input              */
-#define MSVR_DTR        0x02    /* Current state of DTR output             */
-#define MSVR_RTS        0x01    /* Current state of RTS output             */
-
-
-/* Escape characters */
-
-#define CD180_C_ESC     0x00    /* Escape character                        */
-#define CD180_C_SBRK    0x81    /* Start sending BREAK                     */
-#define CD180_C_DELAY   0x82    /* Delay output                            */
-#define CD180_C_EBRK    0x83    /* Stop sending BREAK                      */
diff -druN linux-libre-2.6.38-gnu/drivers/char/rocket.c linux-libre-2.6.39-gnu/drivers/char/rocket.c
--- linux-libre-2.6.38-gnu/drivers/char/rocket.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rocket.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,3199 +0,0 @@
-/*
- * RocketPort device driver for Linux
- *
- * Written by Theodore Ts'o, 1995, 1996, 1997, 1998, 1999, 2000.
- * 
- * Copyright (C) 1995, 1996, 1997, 1998, 1999, 2000, 2003 by Comtrol, 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.
- */
-
-/*
- * Kernel Synchronization:
- *
- * This driver has 2 kernel control paths - exception handlers (calls into the driver
- * from user mode) and the timer bottom half (tasklet).  This is a polled driver, interrupts
- * are not used.
- *
- * Critical data: 
- * -  rp_table[], accessed through passed "info" pointers, is a global (static) array of 
- *    serial port state information and the xmit_buf circular buffer.  Protected by 
- *    a per port spinlock.
- * -  xmit_flags[], an array of ints indexed by line (port) number, indicating that there
- *    is data to be transmitted.  Protected by atomic bit operations.
- * -  rp_num_ports, int indicating number of open ports, protected by atomic operations.
- * 
- * rp_write() and rp_write_char() functions use a per port semaphore to protect against
- * simultaneous access to the same port by more than one process.
- */
-
-/****** Defines ******/
-#define ROCKET_PARANOIA_CHECK
-#define ROCKET_DISABLE_SIMUSAGE
-
-#undef ROCKET_SOFT_FLOW
-#undef ROCKET_DEBUG_OPEN
-#undef ROCKET_DEBUG_INTR
-#undef ROCKET_DEBUG_WRITE
-#undef ROCKET_DEBUG_FLOW
-#undef ROCKET_DEBUG_THROTTLE
-#undef ROCKET_DEBUG_WAIT_UNTIL_SENT
-#undef ROCKET_DEBUG_RECEIVE
-#undef ROCKET_DEBUG_HANGUP
-#undef REV_PCI_ORDER
-#undef ROCKET_DEBUG_IO
-
-#define POLL_PERIOD HZ/100	/*  Polling period .01 seconds (10ms) */
-
-/****** Kernel includes ******/
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/major.h>
-#include <linux/kernel.h>
-#include <linux/signal.h>
-#include <linux/slab.h>
-#include <linux/mm.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_driver.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/mutex.h>
-#include <linux/ioport.h>
-#include <linux/delay.h>
-#include <linux/completion.h>
-#include <linux/wait.h>
-#include <linux/pci.h>
-#include <linux/uaccess.h>
-#include <asm/atomic.h>
-#include <asm/unaligned.h>
-#include <linux/bitops.h>
-#include <linux/spinlock.h>
-#include <linux/init.h>
-
-/****** RocketPort includes ******/
-
-#include "rocket_int.h"
-#include "rocket.h"
-
-#define ROCKET_VERSION "2.09"
-#define ROCKET_DATE "12-June-2003"
-
-/****** RocketPort Local Variables ******/
-
-static void rp_do_poll(unsigned long dummy);
-
-static struct tty_driver *rocket_driver;
-
-static struct rocket_version driver_version = {	
-	ROCKET_VERSION, ROCKET_DATE
-};
-
-static struct r_port *rp_table[MAX_RP_PORTS];	       /*  The main repository of serial port state information. */
-static unsigned int xmit_flags[NUM_BOARDS];	       /*  Bit significant, indicates port had data to transmit. */
-						       /*  eg.  Bit 0 indicates port 0 has xmit data, ...        */
-static atomic_t rp_num_ports_open;	               /*  Number of serial ports open                           */
-static DEFINE_TIMER(rocket_timer, rp_do_poll, 0, 0);
-
-static unsigned long board1;	                       /* ISA addresses, retrieved from rocketport.conf          */
-static unsigned long board2;
-static unsigned long board3;
-static unsigned long board4;
-static unsigned long controller;
-static int support_low_speed;
-static unsigned long modem1;
-static unsigned long modem2;
-static unsigned long modem3;
-static unsigned long modem4;
-static unsigned long pc104_1[8];
-static unsigned long pc104_2[8];
-static unsigned long pc104_3[8];
-static unsigned long pc104_4[8];
-static unsigned long *pc104[4] = { pc104_1, pc104_2, pc104_3, pc104_4 };
-
-static int rp_baud_base[NUM_BOARDS];	               /*  Board config info (Someday make a per-board structure)  */
-static unsigned long rcktpt_io_addr[NUM_BOARDS];
-static int rcktpt_type[NUM_BOARDS];
-static int is_PCI[NUM_BOARDS];
-static rocketModel_t rocketModel[NUM_BOARDS];
-static int max_board;
-static const struct tty_port_operations rocket_port_ops;
-
-/*
- * The following arrays define the interrupt bits corresponding to each AIOP.
- * These bits are different between the ISA and regular PCI boards and the
- * Universal PCI boards.
- */
-
-static Word_t aiop_intr_bits[AIOP_CTL_SIZE] = {
-	AIOP_INTR_BIT_0,
-	AIOP_INTR_BIT_1,
-	AIOP_INTR_BIT_2,
-	AIOP_INTR_BIT_3
-};
-
-static Word_t upci_aiop_intr_bits[AIOP_CTL_SIZE] = {
-	UPCI_AIOP_INTR_BIT_0,
-	UPCI_AIOP_INTR_BIT_1,
-	UPCI_AIOP_INTR_BIT_2,
-	UPCI_AIOP_INTR_BIT_3
-};
-
-static Byte_t RData[RDATASIZE] = {
-	0x00, 0x09, 0xf6, 0x82,
-	0x02, 0x09, 0x86, 0xfb,
-	0x04, 0x09, 0x00, 0x0a,
-	0x06, 0x09, 0x01, 0x0a,
-	0x08, 0x09, 0x8a, 0x13,
-	0x0a, 0x09, 0xc5, 0x11,
-	0x0c, 0x09, 0x86, 0x85,
-	0x0e, 0x09, 0x20, 0x0a,
-	0x10, 0x09, 0x21, 0x0a,
-	0x12, 0x09, 0x41, 0xff,
-	0x14, 0x09, 0x82, 0x00,
-	0x16, 0x09, 0x82, 0x7b,
-	0x18, 0x09, 0x8a, 0x7d,
-	0x1a, 0x09, 0x88, 0x81,
-	0x1c, 0x09, 0x86, 0x7a,
-	0x1e, 0x09, 0x84, 0x81,
-	0x20, 0x09, 0x82, 0x7c,
-	0x22, 0x09, 0x0a, 0x0a
-};
-
-static Byte_t RRegData[RREGDATASIZE] = {
-	0x00, 0x09, 0xf6, 0x82,	/* 00: Stop Rx processor */
-	0x08, 0x09, 0x8a, 0x13,	/* 04: Tx software flow control */
-	0x0a, 0x09, 0xc5, 0x11,	/* 08: XON char */
-	0x0c, 0x09, 0x86, 0x85,	/* 0c: XANY */
-	0x12, 0x09, 0x41, 0xff,	/* 10: Rx mask char */
-	0x14, 0x09, 0x82, 0x00,	/* 14: Compare/Ignore #0 */
-	0x16, 0x09, 0x82, 0x7b,	/* 18: Compare #1 */
-	0x18, 0x09, 0x8a, 0x7d,	/* 1c: Compare #2 */
-	0x1a, 0x09, 0x88, 0x81,	/* 20: Interrupt #1 */
-	0x1c, 0x09, 0x86, 0x7a,	/* 24: Ignore/Replace #1 */
-	0x1e, 0x09, 0x84, 0x81,	/* 28: Interrupt #2 */
-	0x20, 0x09, 0x82, 0x7c,	/* 2c: Ignore/Replace #2 */
-	0x22, 0x09, 0x0a, 0x0a	/* 30: Rx FIFO Enable */
-};
-
-static CONTROLLER_T sController[CTL_SIZE] = {
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}},
-	{-1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, {0, 0, 0, 0},
-	 {0, 0, 0, 0}, {-1, -1, -1, -1}, {0, 0, 0, 0}}
-};
-
-static Byte_t sBitMapClrTbl[8] = {
-	0xfe, 0xfd, 0xfb, 0xf7, 0xef, 0xdf, 0xbf, 0x7f
-};
-
-static Byte_t sBitMapSetTbl[8] = {
-	0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80
-};
-
-static int sClockPrescale = 0x14;
-
-/*
- *  Line number is the ttySIx number (x), the Minor number.  We 
- *  assign them sequentially, starting at zero.  The following 
- *  array keeps track of the line number assigned to a given board/aiop/channel.
- */
-static unsigned char lineNumbers[MAX_RP_PORTS];
-static unsigned long nextLineNumber;
-
-/*****  RocketPort Static Prototypes   *********/
-static int __init init_ISA(int i);
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout);
-static void rp_flush_buffer(struct tty_struct *tty);
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model);
-static unsigned char GetLineNumber(int ctrl, int aiop, int ch);
-static unsigned char SetLineNumber(int ctrl, int aiop, int ch);
-static void rp_start(struct tty_struct *tty);
-static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
-		     int ChanNum);
-static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode);
-static void sFlushRxFIFO(CHANNEL_T * ChP);
-static void sFlushTxFIFO(CHANNEL_T * ChP);
-static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags);
-static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags);
-static void sModemReset(CONTROLLER_T * CtlP, int chan, int on);
-static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on);
-static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data);
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-			      ByteIO_t * AiopIOList, int AiopIOListSize,
-			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-			      int PeriodicOnly, int altChanRingIndicator,
-			      int UPCIRingInd);
-static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
-			   ByteIO_t * AiopIOList, int AiopIOListSize,
-			   int IRQNum, Byte_t Frequency, int PeriodicOnly);
-static int sReadAiopID(ByteIO_t io);
-static int sReadAiopNumChan(WordIO_t io);
-
-MODULE_AUTHOR("Theodore Ts'o");
-MODULE_DESCRIPTION("Comtrol RocketPort driver");
-module_param(board1, ulong, 0);
-MODULE_PARM_DESC(board1, "I/O port for (ISA) board #1");
-module_param(board2, ulong, 0);
-MODULE_PARM_DESC(board2, "I/O port for (ISA) board #2");
-module_param(board3, ulong, 0);
-MODULE_PARM_DESC(board3, "I/O port for (ISA) board #3");
-module_param(board4, ulong, 0);
-MODULE_PARM_DESC(board4, "I/O port for (ISA) board #4");
-module_param(controller, ulong, 0);
-MODULE_PARM_DESC(controller, "I/O port for (ISA) rocketport controller");
-module_param(support_low_speed, bool, 0);
-MODULE_PARM_DESC(support_low_speed, "1 means support 50 baud, 0 means support 460400 baud");
-module_param(modem1, ulong, 0);
-MODULE_PARM_DESC(modem1, "1 means (ISA) board #1 is a RocketModem");
-module_param(modem2, ulong, 0);
-MODULE_PARM_DESC(modem2, "1 means (ISA) board #2 is a RocketModem");
-module_param(modem3, ulong, 0);
-MODULE_PARM_DESC(modem3, "1 means (ISA) board #3 is a RocketModem");
-module_param(modem4, ulong, 0);
-MODULE_PARM_DESC(modem4, "1 means (ISA) board #4 is a RocketModem");
-module_param_array(pc104_1, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_1, "set interface types for ISA(PC104) board #1 (e.g. pc104_1=232,232,485,485,...");
-module_param_array(pc104_2, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_2, "set interface types for ISA(PC104) board #2 (e.g. pc104_2=232,232,485,485,...");
-module_param_array(pc104_3, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_3, "set interface types for ISA(PC104) board #3 (e.g. pc104_3=232,232,485,485,...");
-module_param_array(pc104_4, ulong, NULL, 0);
-MODULE_PARM_DESC(pc104_4, "set interface types for ISA(PC104) board #4 (e.g. pc104_4=232,232,485,485,...");
-
-static int rp_init(void);
-static void rp_cleanup_module(void);
-
-module_init(rp_init);
-module_exit(rp_cleanup_module);
-
-
-MODULE_LICENSE("Dual BSD/GPL");
-
-/*************************************************************************/
-/*                     Module code starts here                           */
-
-static inline int rocket_paranoia_check(struct r_port *info,
-					const char *routine)
-{
-#ifdef ROCKET_PARANOIA_CHECK
-	if (!info)
-		return 1;
-	if (info->magic != RPORT_MAGIC) {
-		printk(KERN_WARNING "Warning: bad magic number for rocketport "
-				"struct in %s\n", routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-
-/*  Serial port receive data function.  Called (from timer poll) when an AIOPIC signals 
- *  that receive data is present on a serial port.  Pulls data from FIFO, moves it into the 
- *  tty layer.  
- */
-static void rp_do_receive(struct r_port *info,
-			  struct tty_struct *tty,
-			  CHANNEL_t * cp, unsigned int ChanStatus)
-{
-	unsigned int CharNStat;
-	int ToRecv, wRecv, space;
-	unsigned char *cbuf;
-
-	ToRecv = sGetRxCnt(cp);
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_INFO "rp_do_receive(%d)...\n", ToRecv);
-#endif
-	if (ToRecv == 0)
-		return;
-
-	/*
-	 * if status indicates there are errored characters in the
-	 * FIFO, then enter status mode (a word in FIFO holds
-	 * character and status).
-	 */
-	if (ChanStatus & (RXFOVERFL | RXBREAK | RXFRAME | RXPARITY)) {
-		if (!(ChanStatus & STATMODE)) {
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "Entering STATMODE...\n");
-#endif
-			ChanStatus |= STATMODE;
-			sEnRxStatusMode(cp);
-		}
-	}
-
-	/* 
-	 * if we previously entered status mode, then read down the
-	 * FIFO one word at a time, pulling apart the character and
-	 * the status.  Update error counters depending on status
-	 */
-	if (ChanStatus & STATMODE) {
-#ifdef ROCKET_DEBUG_RECEIVE
-		printk(KERN_INFO "Ignore %x, read %x...\n",
-			info->ignore_status_mask, info->read_status_mask);
-#endif
-		while (ToRecv) {
-			char flag;
-
-			CharNStat = sInW(sGetTxRxDataIO(cp));
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "%x...\n", CharNStat);
-#endif
-			if (CharNStat & STMBREAKH)
-				CharNStat &= ~(STMFRAMEH | STMPARITYH);
-			if (CharNStat & info->ignore_status_mask) {
-				ToRecv--;
-				continue;
-			}
-			CharNStat &= info->read_status_mask;
-			if (CharNStat & STMBREAKH)
-				flag = TTY_BREAK;
-			else if (CharNStat & STMPARITYH)
-				flag = TTY_PARITY;
-			else if (CharNStat & STMFRAMEH)
-				flag = TTY_FRAME;
-			else if (CharNStat & STMRCVROVRH)
-				flag = TTY_OVERRUN;
-			else
-				flag = TTY_NORMAL;
-			tty_insert_flip_char(tty, CharNStat & 0xff, flag);
-			ToRecv--;
-		}
-
-		/*
-		 * after we've emptied the FIFO in status mode, turn
-		 * status mode back off
-		 */
-		if (sGetRxCnt(cp) == 0) {
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "Status mode off.\n");
-#endif
-			sDisRxStatusMode(cp);
-		}
-	} else {
-		/*
-		 * we aren't in status mode, so read down the FIFO two
-		 * characters at time by doing repeated word IO
-		 * transfer.
-		 */
-		space = tty_prepare_flip_string(tty, &cbuf, ToRecv);
-		if (space < ToRecv) {
-#ifdef ROCKET_DEBUG_RECEIVE
-			printk(KERN_INFO "rp_do_receive:insufficient space ToRecv=%d space=%d\n", ToRecv, space);
-#endif
-			if (space <= 0)
-				return;
-			ToRecv = space;
-		}
-		wRecv = ToRecv >> 1;
-		if (wRecv)
-			sInStrW(sGetTxRxDataIO(cp), (unsigned short *) cbuf, wRecv);
-		if (ToRecv & 1)
-			cbuf[ToRecv - 1] = sInB(sGetTxRxDataIO(cp));
-	}
-	/*  Push the data up to the tty layer */
-	tty_flip_buffer_push(tty);
-}
-
-/*
- *  Serial port transmit data function.  Called from the timer polling loop as a 
- *  result of a bit set in xmit_flags[], indicating data (from the tty layer) is ready
- *  to be sent out the serial port.  Data is buffered in rp_table[line].xmit_buf, it is 
- *  moved to the port's xmit FIFO.  *info is critical data, protected by spinlocks.
- */
-static void rp_do_transmit(struct r_port *info)
-{
-	int c;
-	CHANNEL_t *cp = &info->channel;
-	struct tty_struct *tty;
-	unsigned long flags;
-
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_DEBUG "%s\n", __func__);
-#endif
-	if (!info)
-		return;
-	tty = tty_port_tty_get(&info->port);
-
-	if (tty == NULL) {
-		printk(KERN_WARNING "rp: WARNING %s called with tty==NULL\n", __func__);
-		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-		return;
-	}
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
-	/*  Loop sending data to FIFO until done or FIFO full */
-	while (1) {
-		if (tty->stopped || tty->hw_stopped)
-			break;
-		c = min(info->xmit_fifo_room, info->xmit_cnt);
-		c = min(c, XMIT_BUF_SIZE - info->xmit_tail);
-		if (c <= 0 || info->xmit_fifo_room <= 0)
-			break;
-		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) (info->xmit_buf + info->xmit_tail), c / 2);
-		if (c & 1)
-			sOutB(sGetTxRxDataIO(cp), info->xmit_buf[info->xmit_tail + c - 1]);
-		info->xmit_tail += c;
-		info->xmit_tail &= XMIT_BUF_SIZE - 1;
-		info->xmit_cnt -= c;
-		info->xmit_fifo_room -= c;
-#ifdef ROCKET_DEBUG_INTR
-		printk(KERN_INFO "tx %d chars...\n", c);
-#endif
-	}
-
-	if (info->xmit_cnt == 0)
-		clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-	if (info->xmit_cnt < WAKEUP_CHARS) {
-		tty_wakeup(tty);
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
-		wake_up_interruptible(&tty->poll_wait);
-#endif
-	}
-
-	spin_unlock_irqrestore(&info->slock, flags);
-	tty_kref_put(tty);
-
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_DEBUG "(%d,%d,%d,%d)...\n", info->xmit_cnt, info->xmit_head,
-	       info->xmit_tail, info->xmit_fifo_room);
-#endif
-}
-
-/*
- *  Called when a serial port signals it has read data in it's RX FIFO.
- *  It checks what interrupts are pending and services them, including
- *  receiving serial data.  
- */
-static void rp_handle_port(struct r_port *info)
-{
-	CHANNEL_t *cp;
-	struct tty_struct *tty;
-	unsigned int IntMask, ChanStatus;
-
-	if (!info)
-		return;
-
-	if ((info->port.flags & ASYNC_INITIALIZED) == 0) {
-		printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
-				"info->flags & NOT_INIT\n");
-		return;
-	}
-	tty = tty_port_tty_get(&info->port);
-	if (!tty) {
-		printk(KERN_WARNING "rp: WARNING: rp_handle_port called with "
-				"tty==NULL\n");
-		return;
-	}
-	cp = &info->channel;
-
-	IntMask = sGetChanIntID(cp) & info->intmask;
-#ifdef ROCKET_DEBUG_INTR
-	printk(KERN_INFO "rp_interrupt %02x...\n", IntMask);
-#endif
-	ChanStatus = sGetChanStatus(cp);
-	if (IntMask & RXF_TRIG) {	/* Rx FIFO trigger level */
-		rp_do_receive(info, tty, cp, ChanStatus);
-	}
-	if (IntMask & DELTA_CD) {	/* CD change  */
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_INTR) || defined(ROCKET_DEBUG_HANGUP))
-		printk(KERN_INFO "ttyR%d CD now %s...\n", info->line,
-		       (ChanStatus & CD_ACT) ? "on" : "off");
-#endif
-		if (!(ChanStatus & CD_ACT) && info->cd_status) {
-#ifdef ROCKET_DEBUG_HANGUP
-			printk(KERN_INFO "CD drop, calling hangup.\n");
-#endif
-			tty_hangup(tty);
-		}
-		info->cd_status = (ChanStatus & CD_ACT) ? 1 : 0;
-		wake_up_interruptible(&info->port.open_wait);
-	}
-#ifdef ROCKET_DEBUG_INTR
-	if (IntMask & DELTA_CTS) {	/* CTS change */
-		printk(KERN_INFO "CTS change...\n");
-	}
-	if (IntMask & DELTA_DSR) {	/* DSR change */
-		printk(KERN_INFO "DSR change...\n");
-	}
-#endif
-	tty_kref_put(tty);
-}
-
-/*
- *  The top level polling routine.  Repeats every 1/100 HZ (10ms).
- */
-static void rp_do_poll(unsigned long dummy)
-{
-	CONTROLLER_t *ctlp;
-	int ctrl, aiop, ch, line;
-	unsigned int xmitmask, i;
-	unsigned int CtlMask;
-	unsigned char AiopMask;
-	Word_t bit;
-
-	/*  Walk through all the boards (ctrl's) */
-	for (ctrl = 0; ctrl < max_board; ctrl++) {
-		if (rcktpt_io_addr[ctrl] <= 0)
-			continue;
-
-		/*  Get a ptr to the board's control struct */
-		ctlp = sCtlNumToCtlPtr(ctrl);
-
-		/*  Get the interrupt status from the board */
-#ifdef CONFIG_PCI
-		if (ctlp->BusType == isPCI)
-			CtlMask = sPCIGetControllerIntStatus(ctlp);
-		else
-#endif
-			CtlMask = sGetControllerIntStatus(ctlp);
-
-		/*  Check if any AIOP read bits are set */
-		for (aiop = 0; CtlMask; aiop++) {
-			bit = ctlp->AiopIntrBits[aiop];
-			if (CtlMask & bit) {
-				CtlMask &= ~bit;
-				AiopMask = sGetAiopIntStatus(ctlp, aiop);
-
-				/*  Check if any port read bits are set */
-				for (ch = 0; AiopMask;  AiopMask >>= 1, ch++) {
-					if (AiopMask & 1) {
-
-						/*  Get the line number (/dev/ttyRx number). */
-						/*  Read the data from the port. */
-						line = GetLineNumber(ctrl, aiop, ch);
-						rp_handle_port(rp_table[line]);
-					}
-				}
-			}
-		}
-
-		xmitmask = xmit_flags[ctrl];
-
-		/*
-		 *  xmit_flags contains bit-significant flags, indicating there is data
-		 *  to xmit on the port. Bit 0 is port 0 on this board, bit 1 is port 
-		 *  1, ... (32 total possible).  The variable i has the aiop and ch 
-		 *  numbers encoded in it (port 0-7 are aiop0, 8-15 are aiop1, etc).
-		 */
-		if (xmitmask) {
-			for (i = 0; i < rocketModel[ctrl].numPorts; i++) {
-				if (xmitmask & (1 << i)) {
-					aiop = (i & 0x18) >> 3;
-					ch = i & 0x07;
-					line = GetLineNumber(ctrl, aiop, ch);
-					rp_do_transmit(rp_table[line]);
-				}
-			}
-		}
-	}
-
-	/*
-	 * Reset the timer so we get called at the next clock tick (10ms).
-	 */
-	if (atomic_read(&rp_num_ports_open))
-		mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-}
-
-/*
- *  Initializes the r_port structure for a port, as well as enabling the port on 
- *  the board.  
- *  Inputs:  board, aiop, chan numbers
- */
-static void init_r_port(int board, int aiop, int chan, struct pci_dev *pci_dev)
-{
-	unsigned rocketMode;
-	struct r_port *info;
-	int line;
-	CONTROLLER_T *ctlp;
-
-	/*  Get the next available line number */
-	line = SetLineNumber(board, aiop, chan);
-
-	ctlp = sCtlNumToCtlPtr(board);
-
-	/*  Get a r_port struct for the port, fill it in and save it globally, indexed by line number */
-	info = kzalloc(sizeof (struct r_port), GFP_KERNEL);
-	if (!info) {
-		printk(KERN_ERR "Couldn't allocate info struct for line #%d\n",
-				line);
-		return;
-	}
-
-	info->magic = RPORT_MAGIC;
-	info->line = line;
-	info->ctlp = ctlp;
-	info->board = board;
-	info->aiop = aiop;
-	info->chan = chan;
-	tty_port_init(&info->port);
-	info->port.ops = &rocket_port_ops;
-	init_completion(&info->close_wait);
-	info->flags &= ~ROCKET_MODE_MASK;
-	switch (pc104[board][line]) {
-	case 422:
-		info->flags |= ROCKET_MODE_RS422;
-		break;
-	case 485:
-		info->flags |= ROCKET_MODE_RS485;
-		break;
-	case 232:
-	default:
-		info->flags |= ROCKET_MODE_RS232;
-		break;
-	}
-
-	info->intmask = RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR;
-	if (sInitChan(ctlp, &info->channel, aiop, chan) == 0) {
-		printk(KERN_ERR "RocketPort sInitChan(%d, %d, %d) failed!\n",
-				board, aiop, chan);
-		kfree(info);
-		return;
-	}
-
-	rocketMode = info->flags & ROCKET_MODE_MASK;
-
-	if ((info->flags & ROCKET_RTS_TOGGLE) || (rocketMode == ROCKET_MODE_RS485))
-		sEnRTSToggle(&info->channel);
-	else
-		sDisRTSToggle(&info->channel);
-
-	if (ctlp->boardType == ROCKET_TYPE_PC104) {
-		switch (rocketMode) {
-		case ROCKET_MODE_RS485:
-			sSetInterfaceMode(&info->channel, InterfaceModeRS485);
-			break;
-		case ROCKET_MODE_RS422:
-			sSetInterfaceMode(&info->channel, InterfaceModeRS422);
-			break;
-		case ROCKET_MODE_RS232:
-		default:
-			if (info->flags & ROCKET_RTS_TOGGLE)
-				sSetInterfaceMode(&info->channel, InterfaceModeRS232T);
-			else
-				sSetInterfaceMode(&info->channel, InterfaceModeRS232);
-			break;
-		}
-	}
-	spin_lock_init(&info->slock);
-	mutex_init(&info->write_mtx);
-	rp_table[line] = info;
-	tty_register_device(rocket_driver, line, pci_dev ? &pci_dev->dev :
-			NULL);
-}
-
-/*
- *  Configures a rocketport port according to its termio settings.  Called from 
- *  user mode into the driver (exception handler).  *info CD manipulation is spinlock protected.
- */
-static void configure_r_port(struct tty_struct *tty, struct r_port *info,
-			     struct ktermios *old_termios)
-{
-	unsigned cflag;
-	unsigned long flags;
-	unsigned rocketMode;
-	int bits, baud, divisor;
-	CHANNEL_t *cp;
-	struct ktermios *t = tty->termios;
-
-	cp = &info->channel;
-	cflag = t->c_cflag;
-
-	/* Byte size and parity */
-	if ((cflag & CSIZE) == CS8) {
-		sSetData8(cp);
-		bits = 10;
-	} else {
-		sSetData7(cp);
-		bits = 9;
-	}
-	if (cflag & CSTOPB) {
-		sSetStop2(cp);
-		bits++;
-	} else {
-		sSetStop1(cp);
-	}
-
-	if (cflag & PARENB) {
-		sEnParity(cp);
-		bits++;
-		if (cflag & PARODD) {
-			sSetOddParity(cp);
-		} else {
-			sSetEvenParity(cp);
-		}
-	} else {
-		sDisParity(cp);
-	}
-
-	/* baud rate */
-	baud = tty_get_baud_rate(tty);
-	if (!baud)
-		baud = 9600;
-	divisor = ((rp_baud_base[info->board] + (baud >> 1)) / baud) - 1;
-	if ((divisor >= 8192 || divisor < 0) && old_termios) {
-		baud = tty_termios_baud_rate(old_termios);
-		if (!baud)
-			baud = 9600;
-		divisor = (rp_baud_base[info->board] / baud) - 1;
-	}
-	if (divisor >= 8192 || divisor < 0) {
-		baud = 9600;
-		divisor = (rp_baud_base[info->board] / baud) - 1;
-	}
-	info->cps = baud / bits;
-	sSetBaud(cp, divisor);
-
-	/* FIXME: Should really back compute a baud rate from the divisor */
-	tty_encode_baud_rate(tty, baud, baud);
-
-	if (cflag & CRTSCTS) {
-		info->intmask |= DELTA_CTS;
-		sEnCTSFlowCtl(cp);
-	} else {
-		info->intmask &= ~DELTA_CTS;
-		sDisCTSFlowCtl(cp);
-	}
-	if (cflag & CLOCAL) {
-		info->intmask &= ~DELTA_CD;
-	} else {
-		spin_lock_irqsave(&info->slock, flags);
-		if (sGetChanStatus(cp) & CD_ACT)
-			info->cd_status = 1;
-		else
-			info->cd_status = 0;
-		info->intmask |= DELTA_CD;
-		spin_unlock_irqrestore(&info->slock, flags);
-	}
-
-	/*
-	 * Handle software flow control in the board
-	 */
-#ifdef ROCKET_SOFT_FLOW
-	if (I_IXON(tty)) {
-		sEnTxSoftFlowCtl(cp);
-		if (I_IXANY(tty)) {
-			sEnIXANY(cp);
-		} else {
-			sDisIXANY(cp);
-		}
-		sSetTxXONChar(cp, START_CHAR(tty));
-		sSetTxXOFFChar(cp, STOP_CHAR(tty));
-	} else {
-		sDisTxSoftFlowCtl(cp);
-		sDisIXANY(cp);
-		sClrTxXOFF(cp);
-	}
-#endif
-
-	/*
-	 * Set up ignore/read mask words
-	 */
-	info->read_status_mask = STMRCVROVRH | 0xFF;
-	if (I_INPCK(tty))
-		info->read_status_mask |= STMFRAMEH | STMPARITYH;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		info->read_status_mask |= STMBREAKH;
-
-	/*
-	 * Characters to ignore
-	 */
-	info->ignore_status_mask = 0;
-	if (I_IGNPAR(tty))
-		info->ignore_status_mask |= STMFRAMEH | STMPARITYH;
-	if (I_IGNBRK(tty)) {
-		info->ignore_status_mask |= STMBREAKH;
-		/*
-		 * If we're ignoring parity and break indicators,
-		 * ignore overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(tty))
-			info->ignore_status_mask |= STMRCVROVRH;
-	}
-
-	rocketMode = info->flags & ROCKET_MODE_MASK;
-
-	if ((info->flags & ROCKET_RTS_TOGGLE)
-	    || (rocketMode == ROCKET_MODE_RS485))
-		sEnRTSToggle(cp);
-	else
-		sDisRTSToggle(cp);
-
-	sSetRTS(&info->channel);
-
-	if (cp->CtlP->boardType == ROCKET_TYPE_PC104) {
-		switch (rocketMode) {
-		case ROCKET_MODE_RS485:
-			sSetInterfaceMode(cp, InterfaceModeRS485);
-			break;
-		case ROCKET_MODE_RS422:
-			sSetInterfaceMode(cp, InterfaceModeRS422);
-			break;
-		case ROCKET_MODE_RS232:
-		default:
-			if (info->flags & ROCKET_RTS_TOGGLE)
-				sSetInterfaceMode(cp, InterfaceModeRS232T);
-			else
-				sSetInterfaceMode(cp, InterfaceModeRS232);
-			break;
-		}
-	}
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	struct r_port *info = container_of(port, struct r_port, port);
-	return (sGetChanStatusLo(&info->channel) & CD_ACT) ? 1 : 0;
-}
-
-static void dtr_rts(struct tty_port *port, int on)
-{
-	struct r_port *info = container_of(port, struct r_port, port);
-	if (on) {
-		sSetDTR(&info->channel);
-		sSetRTS(&info->channel);
-	} else {
-		sClrDTR(&info->channel);
-		sClrRTS(&info->channel);
-	}
-}
-
-/*
- *  Exception handler that opens a serial port.  Creates xmit_buf storage, fills in 
- *  port's r_port struct.  Initializes the port hardware.  
- */
-static int rp_open(struct tty_struct *tty, struct file *filp)
-{
-	struct r_port *info;
-	struct tty_port *port;
-	int line = 0, retval;
-	CHANNEL_t *cp;
-	unsigned long page;
-
-	line = tty->index;
-	if (line < 0 || line >= MAX_RP_PORTS || ((info = rp_table[line]) == NULL))
-		return -ENXIO;
-	port = &info->port;
-	
-	page = __get_free_page(GFP_KERNEL);
-	if (!page)
-		return -ENOMEM;
-
-	if (port->flags & ASYNC_CLOSING) {
-		retval = wait_for_completion_interruptible(&info->close_wait);
-		free_page(page);
-		if (retval)
-			return retval;
-		return ((port->flags & ASYNC_HUP_NOTIFY) ? -EAGAIN : -ERESTARTSYS);
-	}
-
-	/*
-	 * We must not sleep from here until the port is marked fully in use.
-	 */
-	if (info->xmit_buf)
-		free_page(page);
-	else
-		info->xmit_buf = (unsigned char *) page;
-
-	tty->driver_data = info;
-	tty_port_tty_set(port, tty);
-
-	if (port->count++ == 0) {
-		atomic_inc(&rp_num_ports_open);
-
-#ifdef ROCKET_DEBUG_OPEN
-		printk(KERN_INFO "rocket mod++ = %d...\n",
-				atomic_read(&rp_num_ports_open));
-#endif
-	}
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "rp_open ttyR%d, count=%d\n", info->line, info->port.count);
-#endif
-
-	/*
-	 * Info->count is now 1; so it's safe to sleep now.
-	 */
-	if (!test_bit(ASYNCB_INITIALIZED, &port->flags)) {
-		cp = &info->channel;
-		sSetRxTrigger(cp, TRIG_1);
-		if (sGetChanStatus(cp) & CD_ACT)
-			info->cd_status = 1;
-		else
-			info->cd_status = 0;
-		sDisRxStatusMode(cp);
-		sFlushRxFIFO(cp);
-		sFlushTxFIFO(cp);
-
-		sEnInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
-		sSetRxTrigger(cp, TRIG_1);
-
-		sGetChanStatus(cp);
-		sDisRxStatusMode(cp);
-		sClrTxXOFF(cp);
-
-		sDisCTSFlowCtl(cp);
-		sDisTxSoftFlowCtl(cp);
-
-		sEnRxFIFO(cp);
-		sEnTransmit(cp);
-
-		set_bit(ASYNCB_INITIALIZED, &info->port.flags);
-
-		/*
-		 * Set up the tty->alt_speed kludge
-		 */
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
-			tty->alt_speed = 57600;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
-			tty->alt_speed = 115200;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
-			tty->alt_speed = 230400;
-		if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
-			tty->alt_speed = 460800;
-
-		configure_r_port(tty, info, NULL);
-		if (tty->termios->c_cflag & CBAUD) {
-			sSetDTR(cp);
-			sSetRTS(cp);
-		}
-	}
-	/*  Starts (or resets) the maint polling loop */
-	mod_timer(&rocket_timer, jiffies + POLL_PERIOD);
-
-	retval = tty_port_block_til_ready(port, tty, filp);
-	if (retval) {
-#ifdef ROCKET_DEBUG_OPEN
-		printk(KERN_INFO "rp_open returning after block_til_ready with %d\n", retval);
-#endif
-		return retval;
-	}
-	return 0;
-}
-
-/*
- *  Exception handler that closes a serial port. info->port.count is considered critical.
- */
-static void rp_close(struct tty_struct *tty, struct file *filp)
-{
-	struct r_port *info = tty->driver_data;
-	struct tty_port *port = &info->port;
-	int timeout;
-	CHANNEL_t *cp;
-	
-	if (rocket_paranoia_check(info, "rp_close"))
-		return;
-
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "rp_close ttyR%d, count = %d\n", info->line, info->port.count);
-#endif
-
-	if (tty_port_close_start(port, tty, filp) == 0)
-		return;
-
-	mutex_lock(&port->mutex);
-	cp = &info->channel;
-	/*
-	 * Before we drop DTR, make sure the UART transmitter
-	 * has completely drained; this is especially
-	 * important if there is a transmit FIFO!
-	 */
-	timeout = (sGetTxCnt(cp) + 1) * HZ / info->cps;
-	if (timeout == 0)
-		timeout = 1;
-	rp_wait_until_sent(tty, timeout);
-	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-	sDisTransmit(cp);
-	sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
-	sDisCTSFlowCtl(cp);
-	sDisTxSoftFlowCtl(cp);
-	sClrTxXOFF(cp);
-	sFlushRxFIFO(cp);
-	sFlushTxFIFO(cp);
-	sClrRTS(cp);
-	if (C_HUPCL(tty))
-		sClrDTR(cp);
-
-	rp_flush_buffer(tty);
-		
-	tty_ldisc_flush(tty);
-
-	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-
-	/* We can't yet use tty_port_close_end as the buffer handling in this
-	   driver is a bit different to the usual */
-
-	if (port->blocked_open) {
-		if (port->close_delay) {
-			msleep_interruptible(jiffies_to_msecs(port->close_delay));
-		}
-		wake_up_interruptible(&port->open_wait);
-	} else {
-		if (info->xmit_buf) {
-			free_page((unsigned long) info->xmit_buf);
-			info->xmit_buf = NULL;
-		}
-	}
-	spin_lock_irq(&port->lock);
-	info->port.flags &= ~(ASYNC_INITIALIZED | ASYNC_CLOSING | ASYNC_NORMAL_ACTIVE);
-	tty->closing = 0;
-	spin_unlock_irq(&port->lock);
-	mutex_unlock(&port->mutex);
-	tty_port_tty_set(port, NULL);
-
-	wake_up_interruptible(&port->close_wait);
-	complete_all(&info->close_wait);
-	atomic_dec(&rp_num_ports_open);
-
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "rocket mod-- = %d...\n",
-			atomic_read(&rp_num_ports_open));
-	printk(KERN_INFO "rp_close ttyR%d complete shutdown\n", info->line);
-#endif
-
-}
-
-static void rp_set_termios(struct tty_struct *tty,
-			   struct ktermios *old_termios)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned cflag;
-
-	if (rocket_paranoia_check(info, "rp_set_termios"))
-		return;
-
-	cflag = tty->termios->c_cflag;
-
-	/*
-	 * This driver doesn't support CS5 or CS6
-	 */
-	if (((cflag & CSIZE) == CS5) || ((cflag & CSIZE) == CS6))
-		tty->termios->c_cflag =
-		    ((cflag & ~CSIZE) | (old_termios->c_cflag & CSIZE));
-	/* Or CMSPAR */
-	tty->termios->c_cflag &= ~CMSPAR;
-
-	configure_r_port(tty, info, old_termios);
-
-	cp = &info->channel;
-
-	/* Handle transition to B0 status */
-	if ((old_termios->c_cflag & CBAUD) && !(tty->termios->c_cflag & CBAUD)) {
-		sClrDTR(cp);
-		sClrRTS(cp);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) && (tty->termios->c_cflag & CBAUD)) {
-		if (!tty->hw_stopped || !(tty->termios->c_cflag & CRTSCTS))
-			sSetRTS(cp);
-		sSetDTR(cp);
-	}
-
-	if ((old_termios->c_cflag & CRTSCTS) && !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		rp_start(tty);
-	}
-}
-
-static int rp_break(struct tty_struct *tty, int break_state)
-{
-	struct r_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_break"))
-		return -EINVAL;
-
-	spin_lock_irqsave(&info->slock, flags);
-	if (break_state == -1)
-		sSendBreak(&info->channel);
-	else
-		sClrBreak(&info->channel);
-	spin_unlock_irqrestore(&info->slock, flags);
-	return 0;
-}
-
-/*
- * sGetChanRI used to be a macro in rocket_int.h. When the functionality for
- * the UPCI boards was added, it was decided to make this a function because
- * the macro was getting too complicated. All cases except the first one
- * (UPCIRingInd) are taken directly from the original macro.
- */
-static int sGetChanRI(CHANNEL_T * ChP)
-{
-	CONTROLLER_t *CtlP = ChP->CtlP;
-	int ChanNum = ChP->ChanNum;
-	int RingInd = 0;
-
-	if (CtlP->UPCIRingInd)
-		RingInd = !(sInB(CtlP->UPCIRingInd) & sBitMapSetTbl[ChanNum]);
-	else if (CtlP->AltChanRingIndicator)
-		RingInd = sInB((ByteIO_t) (ChP->ChanStat + 8)) & DSR_ACT;
-	else if (CtlP->boardType == ROCKET_TYPE_PC104)
-		RingInd = !(sInB(CtlP->AiopIO[3]) & sBitMapSetTbl[ChanNum]);
-
-	return RingInd;
-}
-
-/********************************************************************************************/
-/*  Here are the routines used by rp_ioctl.  These are all called from exception handlers.  */
-
-/*
- *  Returns the state of the serial modem control lines.  These next 2 functions 
- *  are the way kernel versions > 2.5 handle modem control lines rather than IOCTLs.
- */
-static int rp_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct r_port *info = tty->driver_data;
-	unsigned int control, result, ChanStatus;
-
-	ChanStatus = sGetChanStatusLo(&info->channel);
-	control = info->channel.TxControl[3];
-	result = ((control & SET_RTS) ? TIOCM_RTS : 0) | 
-		((control & SET_DTR) ?  TIOCM_DTR : 0) |
-		((ChanStatus & CD_ACT) ? TIOCM_CAR : 0) |
-		(sGetChanRI(&info->channel) ? TIOCM_RNG : 0) |
-		((ChanStatus & DSR_ACT) ? TIOCM_DSR : 0) |
-		((ChanStatus & CTS_ACT) ? TIOCM_CTS : 0);
-
-	return result;
-}
-
-/* 
- *  Sets the modem control lines
- */
-static int rp_tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	struct r_port *info = tty->driver_data;
-
-	if (set & TIOCM_RTS)
-		info->channel.TxControl[3] |= SET_RTS;
-	if (set & TIOCM_DTR)
-		info->channel.TxControl[3] |= SET_DTR;
-	if (clear & TIOCM_RTS)
-		info->channel.TxControl[3] &= ~SET_RTS;
-	if (clear & TIOCM_DTR)
-		info->channel.TxControl[3] &= ~SET_DTR;
-
-	out32(info->channel.IndexAddr, info->channel.TxControl);
-	return 0;
-}
-
-static int get_config(struct r_port *info, struct rocket_config __user *retinfo)
-{
-	struct rocket_config tmp;
-
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof (tmp));
-	mutex_lock(&info->port.mutex);
-	tmp.line = info->line;
-	tmp.flags = info->flags;
-	tmp.close_delay = info->port.close_delay;
-	tmp.closing_wait = info->port.closing_wait;
-	tmp.port = rcktpt_io_addr[(info->line >> 5) & 3];
-	mutex_unlock(&info->port.mutex);
-
-	if (copy_to_user(retinfo, &tmp, sizeof (*retinfo)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_config(struct tty_struct *tty, struct r_port *info,
-					struct rocket_config __user *new_info)
-{
-	struct rocket_config new_serial;
-
-	if (copy_from_user(&new_serial, new_info, sizeof (new_serial)))
-		return -EFAULT;
-
-	mutex_lock(&info->port.mutex);
-	if (!capable(CAP_SYS_ADMIN))
-	{
-		if ((new_serial.flags & ~ROCKET_USR_MASK) != (info->flags & ~ROCKET_USR_MASK)) {
-			mutex_unlock(&info->port.mutex);
-			return -EPERM;
-		}
-		info->flags = ((info->flags & ~ROCKET_USR_MASK) | (new_serial.flags & ROCKET_USR_MASK));
-		configure_r_port(tty, info, NULL);
-		mutex_unlock(&info->port.mutex);
-		return 0;
-	}
-
-	info->flags = ((info->flags & ~ROCKET_FLAGS) | (new_serial.flags & ROCKET_FLAGS));
-	info->port.close_delay = new_serial.close_delay;
-	info->port.closing_wait = new_serial.closing_wait;
-
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_HI)
-		tty->alt_speed = 57600;
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_VHI)
-		tty->alt_speed = 115200;
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_SHI)
-		tty->alt_speed = 230400;
-	if ((info->flags & ROCKET_SPD_MASK) == ROCKET_SPD_WARP)
-		tty->alt_speed = 460800;
-	mutex_unlock(&info->port.mutex);
-
-	configure_r_port(tty, info, NULL);
-	return 0;
-}
-
-/*
- *  This function fills in a rocket_ports struct with information
- *  about what boards/ports are in the system.  This info is passed
- *  to user space.  See setrocket.c where the info is used to create
- *  the /dev/ttyRx ports.
- */
-static int get_ports(struct r_port *info, struct rocket_ports __user *retports)
-{
-	struct rocket_ports tmp;
-	int board;
-
-	if (!retports)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof (tmp));
-	tmp.tty_major = rocket_driver->major;
-
-	for (board = 0; board < 4; board++) {
-		tmp.rocketModel[board].model = rocketModel[board].model;
-		strcpy(tmp.rocketModel[board].modelString, rocketModel[board].modelString);
-		tmp.rocketModel[board].numPorts = rocketModel[board].numPorts;
-		tmp.rocketModel[board].loadrm2 = rocketModel[board].loadrm2;
-		tmp.rocketModel[board].startingPortNumber = rocketModel[board].startingPortNumber;
-	}
-	if (copy_to_user(retports, &tmp, sizeof (*retports)))
-		return -EFAULT;
-	return 0;
-}
-
-static int reset_rm2(struct r_port *info, void __user *arg)
-{
-	int reset;
-
-	if (!capable(CAP_SYS_ADMIN))
-		return -EPERM;
-
-	if (copy_from_user(&reset, arg, sizeof (int)))
-		return -EFAULT;
-	if (reset)
-		reset = 1;
-
-	if (rcktpt_type[info->board] != ROCKET_TYPE_MODEMII &&
-            rcktpt_type[info->board] != ROCKET_TYPE_MODEMIII)
-		return -EINVAL;
-
-	if (info->ctlp->BusType == isISA)
-		sModemReset(info->ctlp, info->chan, reset);
-	else
-		sPCIModemReset(info->ctlp, info->chan, reset);
-
-	return 0;
-}
-
-static int get_version(struct r_port *info, struct rocket_version __user *retvers)
-{
-	if (copy_to_user(retvers, &driver_version, sizeof (*retvers)))
-		return -EFAULT;
-	return 0;
-}
-
-/*  IOCTL call handler into the driver */
-static int rp_ioctl(struct tty_struct *tty, struct file *file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct r_port *info = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int ret = 0;
-
-	if (cmd != RCKP_GET_PORTS && rocket_paranoia_check(info, "rp_ioctl"))
-		return -ENXIO;
-
-	switch (cmd) {
-	case RCKP_GET_STRUCT:
-		if (copy_to_user(argp, info, sizeof (struct r_port)))
-			ret = -EFAULT;
-		break;
-	case RCKP_GET_CONFIG:
-		ret = get_config(info, argp);
-		break;
-	case RCKP_SET_CONFIG:
-		ret = set_config(tty, info, argp);
-		break;
-	case RCKP_GET_PORTS:
-		ret = get_ports(info, argp);
-		break;
-	case RCKP_RESET_RM2:
-		ret = reset_rm2(info, argp);
-		break;
-	case RCKP_GET_VERSION:
-		ret = get_version(info, argp);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-	return ret;
-}
-
-static void rp_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-
-	if (rocket_paranoia_check(info, "rp_send_xchar"))
-		return;
-
-	cp = &info->channel;
-	if (sGetTxCnt(cp))
-		sWriteTxPrioByte(cp, ch);
-	else
-		sWriteTxByte(sGetTxRxDataIO(cp), ch);
-}
-
-static void rp_throttle(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-
-#ifdef ROCKET_DEBUG_THROTTLE
-	printk(KERN_INFO "throttle %s: %d....\n", tty->name,
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (rocket_paranoia_check(info, "rp_throttle"))
-		return;
-
-	cp = &info->channel;
-	if (I_IXOFF(tty))
-		rp_send_xchar(tty, STOP_CHAR(tty));
-
-	sClrRTS(&info->channel);
-}
-
-static void rp_unthrottle(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-#ifdef ROCKET_DEBUG_THROTTLE
-	printk(KERN_INFO "unthrottle %s: %d....\n", tty->name,
-	       tty->ldisc.chars_in_buffer(tty));
-#endif
-
-	if (rocket_paranoia_check(info, "rp_throttle"))
-		return;
-
-	cp = &info->channel;
-	if (I_IXOFF(tty))
-		rp_send_xchar(tty, START_CHAR(tty));
-
-	sSetRTS(&info->channel);
-}
-
-/*
- * ------------------------------------------------------------
- * rp_stop() and rp_start()
- *
- * This routines are called before setting or resetting tty->stopped.
- * They enable or disable transmitter interrupts, as necessary.
- * ------------------------------------------------------------
- */
-static void rp_stop(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_FLOW
-	printk(KERN_INFO "stop %s: %d %d....\n", tty->name,
-	       info->xmit_cnt, info->xmit_fifo_room);
-#endif
-
-	if (rocket_paranoia_check(info, "rp_stop"))
-		return;
-
-	if (sGetTxCnt(&info->channel))
-		sDisTransmit(&info->channel);
-}
-
-static void rp_start(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-
-#ifdef ROCKET_DEBUG_FLOW
-	printk(KERN_INFO "start %s: %d %d....\n", tty->name,
-	       info->xmit_cnt, info->xmit_fifo_room);
-#endif
-
-	if (rocket_paranoia_check(info, "rp_stop"))
-		return;
-
-	sEnTransmit(&info->channel);
-	set_bit((info->aiop * 8) + info->chan,
-		(void *) &xmit_flags[info->board]);
-}
-
-/*
- * rp_wait_until_sent() --- wait until the transmitter is empty
- */
-static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned long orig_jiffies;
-	int check_time, exit_time;
-	int txcnt;
-
-	if (rocket_paranoia_check(info, "rp_wait_until_sent"))
-		return;
-
-	cp = &info->channel;
-
-	orig_jiffies = jiffies;
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_INFO "In RP_wait_until_sent(%d) (jiff=%lu)...\n", timeout,
-	       jiffies);
-	printk(KERN_INFO "cps=%d...\n", info->cps);
-#endif
-	while (1) {
-		txcnt = sGetTxCnt(cp);
-		if (!txcnt) {
-			if (sGetChanStatusLo(cp) & TXSHRMT)
-				break;
-			check_time = (HZ / info->cps) / 5;
-		} else {
-			check_time = HZ * txcnt / info->cps;
-		}
-		if (timeout) {
-			exit_time = orig_jiffies + timeout - jiffies;
-			if (exit_time <= 0)
-				break;
-			if (exit_time < check_time)
-				check_time = exit_time;
-		}
-		if (check_time == 0)
-			check_time = 1;
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
-		printk(KERN_INFO "txcnt = %d (jiff=%lu,check=%d)...\n", txcnt,
-				jiffies, check_time);
-#endif
-		msleep_interruptible(jiffies_to_msecs(check_time));
-		if (signal_pending(current))
-			break;
-	}
-	__set_current_state(TASK_RUNNING);
-#ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
-	printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
-#endif
-}
-
-/*
- * rp_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-static void rp_hangup(struct tty_struct *tty)
-{
-	CHANNEL_t *cp;
-	struct r_port *info = tty->driver_data;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_hangup"))
-		return;
-
-#if (defined(ROCKET_DEBUG_OPEN) || defined(ROCKET_DEBUG_HANGUP))
-	printk(KERN_INFO "rp_hangup of ttyR%d...\n", info->line);
-#endif
-	rp_flush_buffer(tty);
-	spin_lock_irqsave(&info->port.lock, flags);
-	if (info->port.flags & ASYNC_CLOSING) {
-		spin_unlock_irqrestore(&info->port.lock, flags);
-		return;
-	}
-	if (info->port.count)
-		atomic_dec(&rp_num_ports_open);
-	clear_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-	spin_unlock_irqrestore(&info->port.lock, flags);
-
-	tty_port_hangup(&info->port);
-
-	cp = &info->channel;
-	sDisRxFIFO(cp);
-	sDisTransmit(cp);
-	sDisInterrupts(cp, (TXINT_EN | MCINT_EN | RXINT_EN | SRCINT_EN | CHANINT_EN));
-	sDisCTSFlowCtl(cp);
-	sDisTxSoftFlowCtl(cp);
-	sClrTxXOFF(cp);
-	clear_bit(ASYNCB_INITIALIZED, &info->port.flags);
-
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-/*
- *  Exception handler - write char routine.  The RocketPort driver uses a
- *  double-buffering strategy, with the twist that if the in-memory CPU
- *  buffer is empty, and there's space in the transmit FIFO, the
- *  writing routines will write directly to transmit FIFO.
- *  Write buffer and counters protected by spinlocks
- */
-static int rp_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_put_char"))
-		return 0;
-
-	/*
-	 * Grab the port write mutex, locking out other processes that try to
-	 * write to this port
-	 */
-	mutex_lock(&info->write_mtx);
-
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_put_char %c...\n", ch);
-#endif
-
-	spin_lock_irqsave(&info->slock, flags);
-	cp = &info->channel;
-
-	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room == 0)
-		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
-	if (tty->stopped || tty->hw_stopped || info->xmit_fifo_room == 0 || info->xmit_cnt != 0) {
-		info->xmit_buf[info->xmit_head++] = ch;
-		info->xmit_head &= XMIT_BUF_SIZE - 1;
-		info->xmit_cnt++;
-		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-	} else {
-		sOutB(sGetTxRxDataIO(cp), ch);
-		info->xmit_fifo_room--;
-	}
-	spin_unlock_irqrestore(&info->slock, flags);
-	mutex_unlock(&info->write_mtx);
-	return 1;
-}
-
-/*
- *  Exception handler - write routine, called when user app writes to the device.
- *  A per port write mutex is used to protect from another process writing to
- *  this port at the same time.  This other process could be running on the other CPU
- *  or get control of the CPU if the copy_from_user() blocks due to a page fault (swapped out). 
- *  Spinlocks protect the info xmit members.
- */
-static int rp_write(struct tty_struct *tty,
-		    const unsigned char *buf, int count)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	const unsigned char *b;
-	int c, retval = 0;
-	unsigned long flags;
-
-	if (count <= 0 || rocket_paranoia_check(info, "rp_write"))
-		return 0;
-
-	if (mutex_lock_interruptible(&info->write_mtx))
-		return -ERESTARTSYS;
-
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_write %d chars...\n", count);
-#endif
-	cp = &info->channel;
-
-	if (!tty->stopped && !tty->hw_stopped && info->xmit_fifo_room < count)
-		info->xmit_fifo_room = TXFIFO_SIZE - sGetTxCnt(cp);
-
-        /*
-	 *  If the write queue for the port is empty, and there is FIFO space, stuff bytes 
-	 *  into FIFO.  Use the write queue for temp storage.
-         */
-	if (!tty->stopped && !tty->hw_stopped && info->xmit_cnt == 0 && info->xmit_fifo_room > 0) {
-		c = min(count, info->xmit_fifo_room);
-		b = buf;
-
-		/*  Push data into FIFO, 2 bytes at a time */
-		sOutStrW(sGetTxRxDataIO(cp), (unsigned short *) b, c / 2);
-
-		/*  If there is a byte remaining, write it */
-		if (c & 1)
-			sOutB(sGetTxRxDataIO(cp), b[c - 1]);
-
-		retval += c;
-		buf += c;
-		count -= c;
-
-		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_fifo_room -= c;
-		spin_unlock_irqrestore(&info->slock, flags);
-	}
-
-	/* If count is zero, we wrote it all and are done */
-	if (!count)
-		goto end;
-
-	/*  Write remaining data into the port's xmit_buf */
-	while (1) {
-		/* Hung up ? */
-		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);
-		if (c <= 0)
-			break;
-
-		b = buf;
-		memcpy(info->xmit_buf + info->xmit_head, b, c);
-
-		spin_lock_irqsave(&info->slock, flags);
-		info->xmit_head =
-		    (info->xmit_head + c) & (XMIT_BUF_SIZE - 1);
-		info->xmit_cnt += c;
-		spin_unlock_irqrestore(&info->slock, flags);
-
-		buf += c;
-		count -= c;
-		retval += c;
-	}
-
-	if ((retval > 0) && !tty->stopped && !tty->hw_stopped)
-		set_bit((info->aiop * 8) + info->chan, (void *) &xmit_flags[info->board]);
-	
-end:
- 	if (info->xmit_cnt < WAKEUP_CHARS) {
- 		tty_wakeup(tty);
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
-		wake_up_interruptible(&tty->poll_wait);
-#endif
-	}
-	mutex_unlock(&info->write_mtx);
-	return retval;
-}
-
-/*
- * Return the number of characters that can be sent.  We estimate
- * only using the in-memory transmit buffer only, and ignore the
- * potential space in the transmit FIFO.
- */
-static int rp_write_room(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	int ret;
-
-	if (rocket_paranoia_check(info, "rp_write_room"))
-		return 0;
-
-	ret = XMIT_BUF_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_write_room returns %d...\n", ret);
-#endif
-	return ret;
-}
-
-/*
- * Return the number of characters in the buffer.  Again, this only
- * counts those characters in the in-memory transmit buffer.
- */
-static int rp_chars_in_buffer(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-
-	if (rocket_paranoia_check(info, "rp_chars_in_buffer"))
-		return 0;
-
-	cp = &info->channel;
-
-#ifdef ROCKET_DEBUG_WRITE
-	printk(KERN_INFO "rp_chars_in_buffer returns %d...\n", info->xmit_cnt);
-#endif
-	return info->xmit_cnt;
-}
-
-/*
- *  Flushes the TX fifo for a port, deletes data in the xmit_buf stored in the
- *  r_port struct for the port.  Note that spinlock are used to protect info members,
- *  do not call this function if the spinlock is already held.
- */
-static void rp_flush_buffer(struct tty_struct *tty)
-{
-	struct r_port *info = tty->driver_data;
-	CHANNEL_t *cp;
-	unsigned long flags;
-
-	if (rocket_paranoia_check(info, "rp_flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&info->slock, flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	spin_unlock_irqrestore(&info->slock, flags);
-
-#ifdef ROCKETPORT_HAVE_POLL_WAIT
-	wake_up_interruptible(&tty->poll_wait);
-#endif
-	tty_wakeup(tty);
-
-	cp = &info->channel;
-	sFlushTxFIFO(cp);
-}
-
-#ifdef CONFIG_PCI
-
-static struct pci_device_id __devinitdata __used rocket_pci_ids[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_RP, PCI_ANY_ID) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, rocket_pci_ids);
-
-/*
- *  Called when a PCI card is found.  Retrieves and stores model information,
- *  init's aiopic and serial port hardware.
- *  Inputs:  i is the board number (0-n)
- */
-static __init int register_PCI(int i, struct pci_dev *dev)
-{
-	int num_aiops, aiop, max_num_aiops, num_chan, chan;
-	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
-	char *str, *board_type;
-	CONTROLLER_t *ctlp;
-
-	int fast_clock = 0;
-	int altChanRingIndicator = 0;
-	int ports_per_aiop = 8;
-	WordIO_t ConfigIO = 0;
-	ByteIO_t UPCIRingInd = 0;
-
-	if (!dev || pci_enable_device(dev))
-		return 0;
-
-	rcktpt_io_addr[i] = pci_resource_start(dev, 0);
-
-	rcktpt_type[i] = ROCKET_TYPE_NORMAL;
-	rocketModel[i].loadrm2 = 0;
-	rocketModel[i].startingPortNumber = nextLineNumber;
-
-	/*  Depending on the model, set up some config variables */
-	switch (dev->device) {
-	case PCI_DEVICE_ID_RP4QUAD:
-		str = "Quadcable";
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		rocketModel[i].model = MODEL_RP4QUAD;
-		strcpy(rocketModel[i].modelString, "RocketPort 4 port w/quad cable");
-		rocketModel[i].numPorts = 4;
-		break;
-	case PCI_DEVICE_ID_RP8OCTA:
-		str = "Octacable";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8OCTA;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/octa cable");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_URP8OCTA:
-		str = "Octacable";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RP8OCTA;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/octa cable");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP8INTF:
-		str = "8";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/external I/F");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_URP8INTF:
-		str = "8";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RP8INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 8 port w/external I/F");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP8J:
-		str = "8J";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8J;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/RJ11 connectors");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP4J:
-		str = "4J";
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		rocketModel[i].model = MODEL_RP4J;
-		strcpy(rocketModel[i].modelString, "RocketPort 4 port w/RJ45 connectors");
-		rocketModel[i].numPorts = 4;
-		break;
-	case PCI_DEVICE_ID_RP8SNI:
-		str = "8 (DB78 Custom)";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_RP8SNI;
-		strcpy(rocketModel[i].modelString, "RocketPort 8 port w/ custom DB78");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP16SNI:
-		str = "16 (DB78 Custom)";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_RP16SNI;
-		strcpy(rocketModel[i].modelString, "RocketPort 16 port w/ custom DB78");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_RP16INTF:
-		str = "16";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_RP16INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort 16 port w/external I/F");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_URP16INTF:
-		str = "16";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_UPCI_RP16INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 16 port w/external I/F");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_CRP16INTF:
-		str = "16";
-		max_num_aiops = 2;
-		rocketModel[i].model = MODEL_CPCI_RP16INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort Compact PCI 16 port w/external I/F");
-		rocketModel[i].numPorts = 16;
-		break;
-	case PCI_DEVICE_ID_RP32INTF:
-		str = "32";
-		max_num_aiops = 4;
-		rocketModel[i].model = MODEL_RP32INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort 32 port w/external I/F");
-		rocketModel[i].numPorts = 32;
-		break;
-	case PCI_DEVICE_ID_URP32INTF:
-		str = "32";
-		max_num_aiops = 4;
-		rocketModel[i].model = MODEL_UPCI_RP32INTF;
-		strcpy(rocketModel[i].modelString, "RocketPort UPCI 32 port w/external I/F");
-		rocketModel[i].numPorts = 32;
-		break;
-	case PCI_DEVICE_ID_RPP4:
-		str = "Plus Quadcable";
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RPP4;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 4 port");
-		rocketModel[i].numPorts = 4;
-		break;
-	case PCI_DEVICE_ID_RPP8:
-		str = "Plus Octacable";
-		max_num_aiops = 2;
-		ports_per_aiop = 4;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RPP8;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 8 port");
-		rocketModel[i].numPorts = 8;
-		break;
-	case PCI_DEVICE_ID_RP2_232:
-		str = "Plus 2 (RS-232)";
-		max_num_aiops = 1;
-		ports_per_aiop = 2;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RP2_232;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS232");
-		rocketModel[i].numPorts = 2;
-		break;
-	case PCI_DEVICE_ID_RP2_422:
-		str = "Plus 2 (RS-422)";
-		max_num_aiops = 1;
-		ports_per_aiop = 2;
-		altChanRingIndicator++;
-		fast_clock++;
-		rocketModel[i].model = MODEL_RP2_422;
-		strcpy(rocketModel[i].modelString, "RocketPort Plus 2 port RS422");
-		rocketModel[i].numPorts = 2;
-		break;
-	case PCI_DEVICE_ID_RP6M:
-
-		max_num_aiops = 1;
-		ports_per_aiop = 6;
-		str = "6-port";
-
-		/*  If revision is 1, the rocketmodem flash must be loaded.
-		 *  If it is 2 it is a "socketed" version. */
-		if (dev->revision == 1) {
-			rcktpt_type[i] = ROCKET_TYPE_MODEMII;
-			rocketModel[i].loadrm2 = 1;
-		} else {
-			rcktpt_type[i] = ROCKET_TYPE_MODEM;
-		}
-
-		rocketModel[i].model = MODEL_RP6M;
-		strcpy(rocketModel[i].modelString, "RocketModem 6 port");
-		rocketModel[i].numPorts = 6;
-		break;
-	case PCI_DEVICE_ID_RP4M:
-		max_num_aiops = 1;
-		ports_per_aiop = 4;
-		str = "4-port";
-		if (dev->revision == 1) {
-			rcktpt_type[i] = ROCKET_TYPE_MODEMII;
-			rocketModel[i].loadrm2 = 1;
-		} else {
-			rcktpt_type[i] = ROCKET_TYPE_MODEM;
-		}
-
-		rocketModel[i].model = MODEL_RP4M;
-		strcpy(rocketModel[i].modelString, "RocketModem 4 port");
-		rocketModel[i].numPorts = 4;
-		break;
-	default:
-		str = "(unknown/unsupported)";
-		max_num_aiops = 0;
-		break;
-	}
-
-	/*
-	 * Check for UPCI boards.
-	 */
-
-	switch (dev->device) {
-	case PCI_DEVICE_ID_URP32INTF:
-	case PCI_DEVICE_ID_URP8INTF:
-	case PCI_DEVICE_ID_URP16INTF:
-	case PCI_DEVICE_ID_CRP16INTF:
-	case PCI_DEVICE_ID_URP8OCTA:
-		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
-		ConfigIO = pci_resource_start(dev, 1);
-		if (dev->device == PCI_DEVICE_ID_URP8OCTA) {
-			UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-
-			/*
-			 * Check for octa or quad cable.
-			 */
-			if (!
-			    (sInW(ConfigIO + _PCI_9030_GPIO_CTRL) &
-			     PCI_GPIO_CTRL_8PORT)) {
-				str = "Quadcable";
-				ports_per_aiop = 4;
-				rocketModel[i].numPorts = 4;
-			}
-		}
-		break;
-	case PCI_DEVICE_ID_UPCI_RM3_8PORT:
-		str = "8 ports";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RM3_8PORT;
-		strcpy(rocketModel[i].modelString, "RocketModem III 8 port");
-		rocketModel[i].numPorts = 8;
-		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
-		UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-		ConfigIO = pci_resource_start(dev, 1);
-		rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
-		break;
-	case PCI_DEVICE_ID_UPCI_RM3_4PORT:
-		str = "4 ports";
-		max_num_aiops = 1;
-		rocketModel[i].model = MODEL_UPCI_RM3_4PORT;
-		strcpy(rocketModel[i].modelString, "RocketModem III 4 port");
-		rocketModel[i].numPorts = 4;
-		rcktpt_io_addr[i] = pci_resource_start(dev, 2);
-		UPCIRingInd = rcktpt_io_addr[i] + _PCI_9030_RING_IND;
-		ConfigIO = pci_resource_start(dev, 1);
-		rcktpt_type[i] = ROCKET_TYPE_MODEMIII;
-		break;
-	default:
-		break;
-	}
-
-	switch (rcktpt_type[i]) {
-	case ROCKET_TYPE_MODEM:
-		board_type = "RocketModem";
-		break;
-	case ROCKET_TYPE_MODEMII:
-		board_type = "RocketModem II";
-		break;
-	case ROCKET_TYPE_MODEMIII:
-		board_type = "RocketModem III";
-		break;
-	default:
-		board_type = "RocketPort";
-		break;
-	}
-
-	if (fast_clock) {
-		sClockPrescale = 0x12;	/* mod 2 (divide by 3) */
-		rp_baud_base[i] = 921600;
-	} else {
-		/*
-		 * If support_low_speed is set, use the slow clock
-		 * prescale, which supports 50 bps
-		 */
-		if (support_low_speed) {
-			/* mod 9 (divide by 10) prescale */
-			sClockPrescale = 0x19;
-			rp_baud_base[i] = 230400;
-		} else {
-			/* mod 4 (devide by 5) prescale */
-			sClockPrescale = 0x14;
-			rp_baud_base[i] = 460800;
-		}
-	}
-
-	for (aiop = 0; aiop < max_num_aiops; aiop++)
-		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x40);
-	ctlp = sCtlNumToCtlPtr(i);
-	num_aiops = sPCIInitController(ctlp, i, aiopio, max_num_aiops, ConfigIO, 0, FREQ_DIS, 0, altChanRingIndicator, UPCIRingInd);
-	for (aiop = 0; aiop < max_num_aiops; aiop++)
-		ctlp->AiopNumChan[aiop] = ports_per_aiop;
-
-	dev_info(&dev->dev, "comtrol PCI controller #%d found at "
-		"address %04lx, %d AIOP(s) (%s), creating ttyR%d - %ld\n",
-		i, rcktpt_io_addr[i], num_aiops, rocketModel[i].modelString,
-		rocketModel[i].startingPortNumber,
-		rocketModel[i].startingPortNumber + rocketModel[i].numPorts-1);
-
-	if (num_aiops <= 0) {
-		rcktpt_io_addr[i] = 0;
-		return (0);
-	}
-	is_PCI[i] = 1;
-
-	/*  Reset the AIOPIC, init the serial ports */
-	for (aiop = 0; aiop < num_aiops; aiop++) {
-		sResetAiopByNum(ctlp, aiop);
-		num_chan = ports_per_aiop;
-		for (chan = 0; chan < num_chan; chan++)
-			init_r_port(i, aiop, chan, dev);
-	}
-
-	/*  Rocket modems must be reset */
-	if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) ||
-	    (rcktpt_type[i] == ROCKET_TYPE_MODEMII) ||
-	    (rcktpt_type[i] == ROCKET_TYPE_MODEMIII)) {
-		num_chan = ports_per_aiop;
-		for (chan = 0; chan < num_chan; chan++)
-			sPCIModemReset(ctlp, chan, 1);
-		msleep(500);
-		for (chan = 0; chan < num_chan; chan++)
-			sPCIModemReset(ctlp, chan, 0);
-		msleep(500);
-		rmSpeakerReset(ctlp, rocketModel[i].model);
-	}
-	return (1);
-}
-
-/*
- *  Probes for PCI cards, inits them if found
- *  Input:   board_found = number of ISA boards already found, or the
- *           starting board number
- *  Returns: Number of PCI boards found
- */
-static int __init init_PCI(int boards_found)
-{
-	struct pci_dev *dev = NULL;
-	int count = 0;
-
-	/*  Work through the PCI device list, pulling out ours */
-	while ((dev = pci_get_device(PCI_VENDOR_ID_RP, PCI_ANY_ID, dev))) {
-		if (register_PCI(count + boards_found, dev))
-			count++;
-	}
-	return (count);
-}
-
-#endif				/* CONFIG_PCI */
-
-/*
- *  Probes for ISA cards
- *  Input:   i = the board number to look for
- *  Returns: 1 if board found, 0 else
- */
-static int __init init_ISA(int i)
-{
-	int num_aiops, num_chan = 0, total_num_chan = 0;
-	int aiop, chan;
-	unsigned int aiopio[MAX_AIOPS_PER_BOARD];
-	CONTROLLER_t *ctlp;
-	char *type_string;
-
-	/*  If io_addr is zero, no board configured */
-	if (rcktpt_io_addr[i] == 0)
-		return (0);
-
-	/*  Reserve the IO region */
-	if (!request_region(rcktpt_io_addr[i], 64, "Comtrol RocketPort")) {
-		printk(KERN_ERR "Unable to reserve IO region for configured "
-				"ISA RocketPort at address 0x%lx, board not "
-				"installed...\n", rcktpt_io_addr[i]);
-		rcktpt_io_addr[i] = 0;
-		return (0);
-	}
-
-	ctlp = sCtlNumToCtlPtr(i);
-
-	ctlp->boardType = rcktpt_type[i];
-
-	switch (rcktpt_type[i]) {
-	case ROCKET_TYPE_PC104:
-		type_string = "(PC104)";
-		break;
-	case ROCKET_TYPE_MODEM:
-		type_string = "(RocketModem)";
-		break;
-	case ROCKET_TYPE_MODEMII:
-		type_string = "(RocketModem II)";
-		break;
-	default:
-		type_string = "";
-		break;
-	}
-
-	/*
-	 * If support_low_speed is set, use the slow clock prescale,
-	 * which supports 50 bps
-	 */
-	if (support_low_speed) {
-		sClockPrescale = 0x19;	/* mod 9 (divide by 10) prescale */
-		rp_baud_base[i] = 230400;
-	} else {
-		sClockPrescale = 0x14;	/* mod 4 (devide by 5) prescale */
-		rp_baud_base[i] = 460800;
-	}
-
-	for (aiop = 0; aiop < MAX_AIOPS_PER_BOARD; aiop++)
-		aiopio[aiop] = rcktpt_io_addr[i] + (aiop * 0x400);
-
-	num_aiops = sInitController(ctlp, i, controller + (i * 0x400), aiopio,  MAX_AIOPS_PER_BOARD, 0, FREQ_DIS, 0);
-
-	if (ctlp->boardType == ROCKET_TYPE_PC104) {
-		sEnAiop(ctlp, 2);	/* only one AIOPIC, but these */
-		sEnAiop(ctlp, 3);	/* CSels used for other stuff */
-	}
-
-	/*  If something went wrong initing the AIOP's release the ISA IO memory */
-	if (num_aiops <= 0) {
-		release_region(rcktpt_io_addr[i], 64);
-		rcktpt_io_addr[i] = 0;
-		return (0);
-	}
-  
-	rocketModel[i].startingPortNumber = nextLineNumber;
-
-	for (aiop = 0; aiop < num_aiops; aiop++) {
-		sResetAiopByNum(ctlp, aiop);
-		sEnAiop(ctlp, aiop);
-		num_chan = sGetAiopNumChan(ctlp, aiop);
-		total_num_chan += num_chan;
-		for (chan = 0; chan < num_chan; chan++)
-			init_r_port(i, aiop, chan, NULL);
-	}
-	is_PCI[i] = 0;
-	if ((rcktpt_type[i] == ROCKET_TYPE_MODEM) || (rcktpt_type[i] == ROCKET_TYPE_MODEMII)) {
-		num_chan = sGetAiopNumChan(ctlp, 0);
-		total_num_chan = num_chan;
-		for (chan = 0; chan < num_chan; chan++)
-			sModemReset(ctlp, chan, 1);
-		msleep(500);
-		for (chan = 0; chan < num_chan; chan++)
-			sModemReset(ctlp, chan, 0);
-		msleep(500);
-		strcpy(rocketModel[i].modelString, "RocketModem ISA");
-	} else {
-		strcpy(rocketModel[i].modelString, "RocketPort ISA");
-	}
-	rocketModel[i].numPorts = total_num_chan;
-	rocketModel[i].model = MODEL_ISA;
-
-	printk(KERN_INFO "RocketPort ISA card #%d found at 0x%lx - %d AIOPs %s\n", 
-	       i, rcktpt_io_addr[i], num_aiops, type_string);
-
-	printk(KERN_INFO "Installing %s, creating /dev/ttyR%d - %ld\n",
-	       rocketModel[i].modelString,
-	       rocketModel[i].startingPortNumber,
-	       rocketModel[i].startingPortNumber +
-	       rocketModel[i].numPorts - 1);
-
-	return (1);
-}
-
-static const struct tty_operations rocket_ops = {
-	.open = rp_open,
-	.close = rp_close,
-	.write = rp_write,
-	.put_char = rp_put_char,
-	.write_room = rp_write_room,
-	.chars_in_buffer = rp_chars_in_buffer,
-	.flush_buffer = rp_flush_buffer,
-	.ioctl = rp_ioctl,
-	.throttle = rp_throttle,
-	.unthrottle = rp_unthrottle,
-	.set_termios = rp_set_termios,
-	.stop = rp_stop,
-	.start = rp_start,
-	.hangup = rp_hangup,
-	.break_ctl = rp_break,
-	.send_xchar = rp_send_xchar,
-	.wait_until_sent = rp_wait_until_sent,
-	.tiocmget = rp_tiocmget,
-	.tiocmset = rp_tiocmset,
-};
-
-static const struct tty_port_operations rocket_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-/*
- * The module "startup" routine; it's run when the module is loaded.
- */
-static int __init rp_init(void)
-{
-	int ret = -ENOMEM, pci_boards_found, isa_boards_found, i;
-
-	printk(KERN_INFO "RocketPort device driver module, version %s, %s\n",
-	       ROCKET_VERSION, ROCKET_DATE);
-
-	rocket_driver = alloc_tty_driver(MAX_RP_PORTS);
-	if (!rocket_driver)
-		goto err;
-
-	/*
-	 *  If board 1 is non-zero, there is at least one ISA configured.  If controller is 
-	 *  zero, use the default controller IO address of board1 + 0x40.
-	 */
-	if (board1) {
-		if (controller == 0)
-			controller = board1 + 0x40;
-	} else {
-		controller = 0;  /*  Used as a flag, meaning no ISA boards */
-	}
-
-	/*  If an ISA card is configured, reserve the 4 byte IO space for the Mudbac controller */
-	if (controller && (!request_region(controller, 4, "Comtrol RocketPort"))) {
-		printk(KERN_ERR "Unable to reserve IO region for first "
-			"configured ISA RocketPort controller 0x%lx.  "
-			"Driver exiting\n", controller);
-		ret = -EBUSY;
-		goto err_tty;
-	}
-
-	/*  Store ISA variable retrieved from command line or .conf file. */
-	rcktpt_io_addr[0] = board1;
-	rcktpt_io_addr[1] = board2;
-	rcktpt_io_addr[2] = board3;
-	rcktpt_io_addr[3] = board4;
-
-	rcktpt_type[0] = modem1 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[0] = pc104_1[0] ? ROCKET_TYPE_PC104 : rcktpt_type[0];
-	rcktpt_type[1] = modem2 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[1] = pc104_2[0] ? ROCKET_TYPE_PC104 : rcktpt_type[1];
-	rcktpt_type[2] = modem3 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[2] = pc104_3[0] ? ROCKET_TYPE_PC104 : rcktpt_type[2];
-	rcktpt_type[3] = modem4 ? ROCKET_TYPE_MODEM : ROCKET_TYPE_NORMAL;
-	rcktpt_type[3] = pc104_4[0] ? ROCKET_TYPE_PC104 : rcktpt_type[3];
-
-	/*
-	 * Set up the tty driver structure and then register this
-	 * driver with the tty layer.
-	 */
-
-	rocket_driver->owner = THIS_MODULE;
-	rocket_driver->flags = TTY_DRIVER_DYNAMIC_DEV;
-	rocket_driver->name = "ttyR";
-	rocket_driver->driver_name = "Comtrol RocketPort";
-	rocket_driver->major = TTY_ROCKET_MAJOR;
-	rocket_driver->minor_start = 0;
-	rocket_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	rocket_driver->subtype = SERIAL_TYPE_NORMAL;
-	rocket_driver->init_termios = tty_std_termios;
-	rocket_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	rocket_driver->init_termios.c_ispeed = 9600;
-	rocket_driver->init_termios.c_ospeed = 9600;
-#ifdef ROCKET_SOFT_FLOW
-	rocket_driver->flags |= TTY_DRIVER_REAL_RAW;
-#endif
-	tty_set_operations(rocket_driver, &rocket_ops);
-
-	ret = tty_register_driver(rocket_driver);
-	if (ret < 0) {
-		printk(KERN_ERR "Couldn't install tty RocketPort driver\n");
-		goto err_controller;
-	}
-
-#ifdef ROCKET_DEBUG_OPEN
-	printk(KERN_INFO "RocketPort driver is major %d\n", rocket_driver.major);
-#endif
-
-	/*
-	 *  OK, let's probe each of the controllers looking for boards.  Any boards found
-         *  will be initialized here.
-	 */
-	isa_boards_found = 0;
-	pci_boards_found = 0;
-
-	for (i = 0; i < NUM_BOARDS; i++) {
-		if (init_ISA(i))
-			isa_boards_found++;
-	}
-
-#ifdef CONFIG_PCI
-	if (isa_boards_found < NUM_BOARDS)
-		pci_boards_found = init_PCI(isa_boards_found);
-#endif
-
-	max_board = pci_boards_found + isa_boards_found;
-
-	if (max_board == 0) {
-		printk(KERN_ERR "No rocketport ports found; unloading driver\n");
-		ret = -ENXIO;
-		goto err_ttyu;
-	}
-
-	return 0;
-err_ttyu:
-	tty_unregister_driver(rocket_driver);
-err_controller:
-	if (controller)
-		release_region(controller, 4);
-err_tty:
-	put_tty_driver(rocket_driver);
-err:
-	return ret;
-}
-
-
-static void rp_cleanup_module(void)
-{
-	int retval;
-	int i;
-
-	del_timer_sync(&rocket_timer);
-
-	retval = tty_unregister_driver(rocket_driver);
-	if (retval)
-		printk(KERN_ERR "Error %d while trying to unregister "
-		       "rocketport driver\n", -retval);
-
-	for (i = 0; i < MAX_RP_PORTS; i++)
-		if (rp_table[i]) {
-			tty_unregister_device(rocket_driver, i);
-			kfree(rp_table[i]);
-		}
-
-	put_tty_driver(rocket_driver);
-
-	for (i = 0; i < NUM_BOARDS; i++) {
-		if (rcktpt_io_addr[i] <= 0 || is_PCI[i])
-			continue;
-		release_region(rcktpt_io_addr[i], 64);
-	}
-	if (controller)
-		release_region(controller, 4);
-}
-
-/***************************************************************************
-Function: sInitController
-Purpose:  Initialization of controller global registers and controller
-          structure.
-Call:     sInitController(CtlP,CtlNum,MudbacIO,AiopIOList,AiopIOListSize,
-                          IRQNum,Frequency,PeriodicOnly)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int CtlNum; Controller number
-          ByteIO_t MudbacIO; Mudbac base I/O address.
-          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
-             This list must be in the order the AIOPs will be found on the
-             controller.  Once an AIOP in the list is not found, it is
-             assumed that there are no more AIOPs on the controller.
-          int AiopIOListSize; Number of addresses in AiopIOList
-          int IRQNum; Interrupt Request number.  Can be any of the following:
-                         0: Disable global interrupts
-                         3: IRQ 3
-                         4: IRQ 4
-                         5: IRQ 5
-                         9: IRQ 9
-                         10: IRQ 10
-                         11: IRQ 11
-                         12: IRQ 12
-                         15: IRQ 15
-          Byte_t Frequency: A flag identifying the frequency
-                   of the periodic interrupt, can be any one of the following:
-                      FREQ_DIS - periodic interrupt disabled
-                      FREQ_137HZ - 137 Hertz
-                      FREQ_69HZ - 69 Hertz
-                      FREQ_34HZ - 34 Hertz
-                      FREQ_17HZ - 17 Hertz
-                      FREQ_9HZ - 9 Hertz
-                      FREQ_4HZ - 4 Hertz
-                   If IRQNum is set to 0 the Frequency parameter is
-                   overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: 1 if all interrupts except the periodic
-                               interrupt are to be blocked.
-                            0 is both the periodic interrupt and
-                               other channel interrupts are allowed.
-                            If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of 0.
-Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
-               initialization failed.
-
-Comments:
-          If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
-          If interrupts are to be completely disabled set IRQNum to 0.
-
-          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
-          invalid combination.
-
-          This function performs initialization of global interrupt modes,
-          but it does not actually enable global interrupts.  To enable
-          and disable global interrupts use functions sEnGlobalInt() and
-          sDisGlobalInt().  Enabling of global interrupts is normally not
-          done until all other initializations are complete.
-
-          Even if interrupts are globally enabled, they must also be
-          individually enabled for each channel that is to generate
-          interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-
-          After this function all AIOPs on the controller are disabled,
-          they can be enabled with sEnAiop().
-*/
-static int sInitController(CONTROLLER_T * CtlP, int CtlNum, ByteIO_t MudbacIO,
-			   ByteIO_t * AiopIOList, int AiopIOListSize,
-			   int IRQNum, Byte_t Frequency, int PeriodicOnly)
-{
-	int i;
-	ByteIO_t io;
-	int done;
-
-	CtlP->AiopIntrBits = aiop_intr_bits;
-	CtlP->AltChanRingIndicator = 0;
-	CtlP->CtlNum = CtlNum;
-	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
-	CtlP->BusType = isISA;
-	CtlP->MBaseIO = MudbacIO;
-	CtlP->MReg1IO = MudbacIO + 1;
-	CtlP->MReg2IO = MudbacIO + 2;
-	CtlP->MReg3IO = MudbacIO + 3;
-#if 1
-	CtlP->MReg2 = 0;	/* interrupt disable */
-	CtlP->MReg3 = 0;	/* no periodic interrupts */
-#else
-	if (sIRQMap[IRQNum] == 0) {	/* interrupts globally disabled */
-		CtlP->MReg2 = 0;	/* interrupt disable */
-		CtlP->MReg3 = 0;	/* no periodic interrupts */
-	} else {
-		CtlP->MReg2 = sIRQMap[IRQNum];	/* set IRQ number */
-		CtlP->MReg3 = Frequency;	/* set frequency */
-		if (PeriodicOnly) {	/* periodic interrupt only */
-			CtlP->MReg3 |= PERIODIC_ONLY;
-		}
-	}
-#endif
-	sOutB(CtlP->MReg2IO, CtlP->MReg2);
-	sOutB(CtlP->MReg3IO, CtlP->MReg3);
-	sControllerEOI(CtlP);	/* clear EOI if warm init */
-	/* Init AIOPs */
-	CtlP->NumAiop = 0;
-	for (i = done = 0; i < AiopIOListSize; i++) {
-		io = AiopIOList[i];
-		CtlP->AiopIO[i] = (WordIO_t) io;
-		CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-		sOutB(CtlP->MReg2IO, CtlP->MReg2 | (i & 0x03));	/* AIOP index */
-		sOutB(MudbacIO, (Byte_t) (io >> 6));	/* set up AIOP I/O in MUDBAC */
-		if (done)
-			continue;
-		sEnAiop(CtlP, i);	/* enable the AIOP */
-		CtlP->AiopID[i] = sReadAiopID(io);	/* read AIOP ID */
-		if (CtlP->AiopID[i] == AIOPID_NULL)	/* if AIOP does not exist */
-			done = 1;	/* done looking for AIOPs */
-		else {
-			CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io);	/* num channels in AIOP */
-			sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);	/* clock prescaler */
-			sOutB(io + _INDX_DATA, sClockPrescale);
-			CtlP->NumAiop++;	/* bump count of AIOPs */
-		}
-		sDisAiop(CtlP, i);	/* disable AIOP */
-	}
-
-	if (CtlP->NumAiop == 0)
-		return (-1);
-	else
-		return (CtlP->NumAiop);
-}
-
-/***************************************************************************
-Function: sPCIInitController
-Purpose:  Initialization of controller global registers and controller
-          structure.
-Call:     sPCIInitController(CtlP,CtlNum,AiopIOList,AiopIOListSize,
-                          IRQNum,Frequency,PeriodicOnly)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int CtlNum; Controller number
-          ByteIO_t *AiopIOList; List of I/O addresses for each AIOP.
-             This list must be in the order the AIOPs will be found on the
-             controller.  Once an AIOP in the list is not found, it is
-             assumed that there are no more AIOPs on the controller.
-          int AiopIOListSize; Number of addresses in AiopIOList
-          int IRQNum; Interrupt Request number.  Can be any of the following:
-                         0: Disable global interrupts
-                         3: IRQ 3
-                         4: IRQ 4
-                         5: IRQ 5
-                         9: IRQ 9
-                         10: IRQ 10
-                         11: IRQ 11
-                         12: IRQ 12
-                         15: IRQ 15
-          Byte_t Frequency: A flag identifying the frequency
-                   of the periodic interrupt, can be any one of the following:
-                      FREQ_DIS - periodic interrupt disabled
-                      FREQ_137HZ - 137 Hertz
-                      FREQ_69HZ - 69 Hertz
-                      FREQ_34HZ - 34 Hertz
-                      FREQ_17HZ - 17 Hertz
-                      FREQ_9HZ - 9 Hertz
-                      FREQ_4HZ - 4 Hertz
-                   If IRQNum is set to 0 the Frequency parameter is
-                   overidden, it is forced to a value of FREQ_DIS.
-          int PeriodicOnly: 1 if all interrupts except the periodic
-                               interrupt are to be blocked.
-                            0 is both the periodic interrupt and
-                               other channel interrupts are allowed.
-                            If IRQNum is set to 0 the PeriodicOnly parameter is
-                               overidden, it is forced to a value of 0.
-Return:   int: Number of AIOPs on the controller, or CTLID_NULL if controller
-               initialization failed.
-
-Comments:
-          If periodic interrupts are to be disabled but AIOP interrupts
-          are allowed, set Frequency to FREQ_DIS and PeriodicOnly to 0.
-
-          If interrupts are to be completely disabled set IRQNum to 0.
-
-          Setting Frequency to FREQ_DIS and PeriodicOnly to 1 is an
-          invalid combination.
-
-          This function performs initialization of global interrupt modes,
-          but it does not actually enable global interrupts.  To enable
-          and disable global interrupts use functions sEnGlobalInt() and
-          sDisGlobalInt().  Enabling of global interrupts is normally not
-          done until all other initializations are complete.
-
-          Even if interrupts are globally enabled, they must also be
-          individually enabled for each channel that is to generate
-          interrupts.
-
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-
-          After this function all AIOPs on the controller are disabled,
-          they can be enabled with sEnAiop().
-*/
-static int sPCIInitController(CONTROLLER_T * CtlP, int CtlNum,
-			      ByteIO_t * AiopIOList, int AiopIOListSize,
-			      WordIO_t ConfigIO, int IRQNum, Byte_t Frequency,
-			      int PeriodicOnly, int altChanRingIndicator,
-			      int UPCIRingInd)
-{
-	int i;
-	ByteIO_t io;
-
-	CtlP->AltChanRingIndicator = altChanRingIndicator;
-	CtlP->UPCIRingInd = UPCIRingInd;
-	CtlP->CtlNum = CtlNum;
-	CtlP->CtlID = CTLID_0001;	/* controller release 1 */
-	CtlP->BusType = isPCI;	/* controller release 1 */
-
-	if (ConfigIO) {
-		CtlP->isUPCI = 1;
-		CtlP->PCIIO = ConfigIO + _PCI_9030_INT_CTRL;
-		CtlP->PCIIO2 = ConfigIO + _PCI_9030_GPIO_CTRL;
-		CtlP->AiopIntrBits = upci_aiop_intr_bits;
-	} else {
-		CtlP->isUPCI = 0;
-		CtlP->PCIIO =
-		    (WordIO_t) ((ByteIO_t) AiopIOList[0] + _PCI_INT_FUNC);
-		CtlP->AiopIntrBits = aiop_intr_bits;
-	}
-
-	sPCIControllerEOI(CtlP);	/* clear EOI if warm init */
-	/* Init AIOPs */
-	CtlP->NumAiop = 0;
-	for (i = 0; i < AiopIOListSize; i++) {
-		io = AiopIOList[i];
-		CtlP->AiopIO[i] = (WordIO_t) io;
-		CtlP->AiopIntChanIO[i] = io + _INT_CHAN;
-
-		CtlP->AiopID[i] = sReadAiopID(io);	/* read AIOP ID */
-		if (CtlP->AiopID[i] == AIOPID_NULL)	/* if AIOP does not exist */
-			break;	/* done looking for AIOPs */
-
-		CtlP->AiopNumChan[i] = sReadAiopNumChan((WordIO_t) io);	/* num channels in AIOP */
-		sOutW((WordIO_t) io + _INDX_ADDR, _CLK_PRE);	/* clock prescaler */
-		sOutB(io + _INDX_DATA, sClockPrescale);
-		CtlP->NumAiop++;	/* bump count of AIOPs */
-	}
-
-	if (CtlP->NumAiop == 0)
-		return (-1);
-	else
-		return (CtlP->NumAiop);
-}
-
-/***************************************************************************
-Function: sReadAiopID
-Purpose:  Read the AIOP idenfication number directly from an AIOP.
-Call:     sReadAiopID(io)
-          ByteIO_t io: AIOP base I/O address
-Return:   int: Flag AIOPID_XXXX if a valid AIOP is found, where X
-                 is replace by an identifying number.
-          Flag AIOPID_NULL if no valid AIOP is found
-Warnings: No context switches are allowed while executing this function.
-
-*/
-static int sReadAiopID(ByteIO_t io)
-{
-	Byte_t AiopID;		/* ID byte from AIOP */
-
-	sOutB(io + _CMD_REG, RESET_ALL);	/* reset AIOP */
-	sOutB(io + _CMD_REG, 0x0);
-	AiopID = sInW(io + _CHN_STAT0) & 0x07;
-	if (AiopID == 0x06)
-		return (1);
-	else			/* AIOP does not exist */
-		return (-1);
-}
-
-/***************************************************************************
-Function: sReadAiopNumChan
-Purpose:  Read the number of channels available in an AIOP directly from
-          an AIOP.
-Call:     sReadAiopNumChan(io)
-          WordIO_t io: AIOP base I/O address
-Return:   int: The number of channels available
-Comments: The number of channels is determined by write/reads from identical
-          offsets within the SRAM address spaces for channels 0 and 4.
-          If the channel 4 space is mirrored to channel 0 it is a 4 channel
-          AIOP, otherwise it is an 8 channel.
-Warnings: No context switches are allowed while executing this function.
-*/
-static int sReadAiopNumChan(WordIO_t io)
-{
-	Word_t x;
-	static Byte_t R[4] = { 0x00, 0x00, 0x34, 0x12 };
-
-	/* write to chan 0 SRAM */
-	out32((DWordIO_t) io + _INDX_ADDR, R);
-	sOutW(io + _INDX_ADDR, 0);	/* read from SRAM, chan 0 */
-	x = sInW(io + _INDX_DATA);
-	sOutW(io + _INDX_ADDR, 0x4000);	/* read from SRAM, chan 4 */
-	if (x != sInW(io + _INDX_DATA))	/* if different must be 8 chan */
-		return (8);
-	else
-		return (4);
-}
-
-/***************************************************************************
-Function: sInitChan
-Purpose:  Initialization of a channel and channel structure
-Call:     sInitChan(CtlP,ChP,AiopNum,ChanNum)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          CHANNEL_T *ChP; Ptr to channel structure
-          int AiopNum; AIOP number within controller
-          int ChanNum; Channel number within AIOP
-Return:   int: 1 if initialization succeeded, 0 if it fails because channel
-               number exceeds number of channels available in AIOP.
-Comments: This function must be called before a channel can be used.
-Warnings: No range checking on any of the parameters is done.
-
-          No context switches are allowed while executing this function.
-*/
-static int sInitChan(CONTROLLER_T * CtlP, CHANNEL_T * ChP, int AiopNum,
-		     int ChanNum)
-{
-	int i;
-	WordIO_t AiopIO;
-	WordIO_t ChIOOff;
-	Byte_t *ChR;
-	Word_t ChOff;
-	static Byte_t R[4];
-	int brd9600;
-
-	if (ChanNum >= CtlP->AiopNumChan[AiopNum])
-		return 0;	/* exceeds num chans in AIOP */
-
-	/* Channel, AIOP, and controller identifiers */
-	ChP->CtlP = CtlP;
-	ChP->ChanID = CtlP->AiopID[AiopNum];
-	ChP->AiopNum = AiopNum;
-	ChP->ChanNum = ChanNum;
-
-	/* Global direct addresses */
-	AiopIO = CtlP->AiopIO[AiopNum];
-	ChP->Cmd = (ByteIO_t) AiopIO + _CMD_REG;
-	ChP->IntChan = (ByteIO_t) AiopIO + _INT_CHAN;
-	ChP->IntMask = (ByteIO_t) AiopIO + _INT_MASK;
-	ChP->IndexAddr = (DWordIO_t) AiopIO + _INDX_ADDR;
-	ChP->IndexData = AiopIO + _INDX_DATA;
-
-	/* Channel direct addresses */
-	ChIOOff = AiopIO + ChP->ChanNum * 2;
-	ChP->TxRxData = ChIOOff + _TD0;
-	ChP->ChanStat = ChIOOff + _CHN_STAT0;
-	ChP->TxRxCount = ChIOOff + _FIFO_CNT0;
-	ChP->IntID = (ByteIO_t) AiopIO + ChP->ChanNum + _INT_ID0;
-
-	/* Initialize the channel from the RData array */
-	for (i = 0; i < RDATASIZE; i += 4) {
-		R[0] = RData[i];
-		R[1] = RData[i + 1] + 0x10 * ChanNum;
-		R[2] = RData[i + 2];
-		R[3] = RData[i + 3];
-		out32(ChP->IndexAddr, R);
-	}
-
-	ChR = ChP->R;
-	for (i = 0; i < RREGDATASIZE; i += 4) {
-		ChR[i] = RRegData[i];
-		ChR[i + 1] = RRegData[i + 1] + 0x10 * ChanNum;
-		ChR[i + 2] = RRegData[i + 2];
-		ChR[i + 3] = RRegData[i + 3];
-	}
-
-	/* Indexed registers */
-	ChOff = (Word_t) ChanNum *0x1000;
-
-	if (sClockPrescale == 0x14)
-		brd9600 = 47;
-	else
-		brd9600 = 23;
-
-	ChP->BaudDiv[0] = (Byte_t) (ChOff + _BAUD);
-	ChP->BaudDiv[1] = (Byte_t) ((ChOff + _BAUD) >> 8);
-	ChP->BaudDiv[2] = (Byte_t) brd9600;
-	ChP->BaudDiv[3] = (Byte_t) (brd9600 >> 8);
-	out32(ChP->IndexAddr, ChP->BaudDiv);
-
-	ChP->TxControl[0] = (Byte_t) (ChOff + _TX_CTRL);
-	ChP->TxControl[1] = (Byte_t) ((ChOff + _TX_CTRL) >> 8);
-	ChP->TxControl[2] = 0;
-	ChP->TxControl[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxControl);
-
-	ChP->RxControl[0] = (Byte_t) (ChOff + _RX_CTRL);
-	ChP->RxControl[1] = (Byte_t) ((ChOff + _RX_CTRL) >> 8);
-	ChP->RxControl[2] = 0;
-	ChP->RxControl[3] = 0;
-	out32(ChP->IndexAddr, ChP->RxControl);
-
-	ChP->TxEnables[0] = (Byte_t) (ChOff + _TX_ENBLS);
-	ChP->TxEnables[1] = (Byte_t) ((ChOff + _TX_ENBLS) >> 8);
-	ChP->TxEnables[2] = 0;
-	ChP->TxEnables[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxEnables);
-
-	ChP->TxCompare[0] = (Byte_t) (ChOff + _TXCMP1);
-	ChP->TxCompare[1] = (Byte_t) ((ChOff + _TXCMP1) >> 8);
-	ChP->TxCompare[2] = 0;
-	ChP->TxCompare[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxCompare);
-
-	ChP->TxReplace1[0] = (Byte_t) (ChOff + _TXREP1B1);
-	ChP->TxReplace1[1] = (Byte_t) ((ChOff + _TXREP1B1) >> 8);
-	ChP->TxReplace1[2] = 0;
-	ChP->TxReplace1[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxReplace1);
-
-	ChP->TxReplace2[0] = (Byte_t) (ChOff + _TXREP2);
-	ChP->TxReplace2[1] = (Byte_t) ((ChOff + _TXREP2) >> 8);
-	ChP->TxReplace2[2] = 0;
-	ChP->TxReplace2[3] = 0;
-	out32(ChP->IndexAddr, ChP->TxReplace2);
-
-	ChP->TxFIFOPtrs = ChOff + _TXF_OUTP;
-	ChP->TxFIFO = ChOff + _TX_FIFO;
-
-	sOutB(ChP->Cmd, (Byte_t) ChanNum | RESTXFCNT);	/* apply reset Tx FIFO count */
-	sOutB(ChP->Cmd, (Byte_t) ChanNum);	/* remove reset Tx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs);	/* clear Tx in/out ptrs */
-	sOutW(ChP->IndexData, 0);
-	ChP->RxFIFOPtrs = ChOff + _RXF_OUTP;
-	ChP->RxFIFO = ChOff + _RX_FIFO;
-
-	sOutB(ChP->Cmd, (Byte_t) ChanNum | RESRXFCNT);	/* apply reset Rx FIFO count */
-	sOutB(ChP->Cmd, (Byte_t) ChanNum);	/* remove reset Rx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs);	/* clear Rx out ptr */
-	sOutW(ChP->IndexData, 0);
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2);	/* clear Rx in ptr */
-	sOutW(ChP->IndexData, 0);
-	ChP->TxPrioCnt = ChOff + _TXP_CNT;
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioCnt);
-	sOutB(ChP->IndexData, 0);
-	ChP->TxPrioPtr = ChOff + _TXP_PNTR;
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxPrioPtr);
-	sOutB(ChP->IndexData, 0);
-	ChP->TxPrioBuf = ChOff + _TXP_BUF;
-	sEnRxProcessor(ChP);	/* start the Rx processor */
-
-	return 1;
-}
-
-/***************************************************************************
-Function: sStopRxProcessor
-Purpose:  Stop the receive processor from processing a channel.
-Call:     sStopRxProcessor(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-
-Comments: The receive processor can be started again with sStartRxProcessor().
-          This function causes the receive processor to skip over the
-          stopped channel.  It does not stop it from processing other channels.
-
-Warnings: No context switches are allowed while executing this function.
-
-          Do not leave the receive processor stopped for more than one
-          character time.
-
-          After calling this function a delay of 4 uS is required to ensure
-          that the receive processor is no longer processing this channel.
-*/
-static void sStopRxProcessor(CHANNEL_T * ChP)
-{
-	Byte_t R[4];
-
-	R[0] = ChP->R[0];
-	R[1] = ChP->R[1];
-	R[2] = 0x0a;
-	R[3] = ChP->R[3];
-	out32(ChP->IndexAddr, R);
-}
-
-/***************************************************************************
-Function: sFlushRxFIFO
-Purpose:  Flush the Rx FIFO
-Call:     sFlushRxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   void
-Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
-          while it is being flushed the receive processor is stopped
-          and the transmitter is disabled.  After these operations a
-          4 uS delay is done before clearing the pointers to allow
-          the receive processor to stop.  These items are handled inside
-          this function.
-Warnings: No context switches are allowed while executing this function.
-*/
-static void sFlushRxFIFO(CHANNEL_T * ChP)
-{
-	int i;
-	Byte_t Ch;		/* channel number within AIOP */
-	int RxFIFOEnabled;	/* 1 if Rx FIFO enabled */
-
-	if (sGetRxCnt(ChP) == 0)	/* Rx FIFO empty */
-		return;		/* don't need to flush */
-
-	RxFIFOEnabled = 0;
-	if (ChP->R[0x32] == 0x08) {	/* Rx FIFO is enabled */
-		RxFIFOEnabled = 1;
-		sDisRxFIFO(ChP);	/* disable it */
-		for (i = 0; i < 2000 / 200; i++)	/* delay 2 uS to allow proc to disable FIFO */
-			sInB(ChP->IntChan);	/* depends on bus i/o timing */
-	}
-	sGetChanStatus(ChP);	/* clear any pending Rx errors in chan stat */
-	Ch = (Byte_t) sGetChanNum(ChP);
-	sOutB(ChP->Cmd, Ch | RESRXFCNT);	/* apply reset Rx FIFO count */
-	sOutB(ChP->Cmd, Ch);	/* remove reset Rx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs);	/* clear Rx out ptr */
-	sOutW(ChP->IndexData, 0);
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->RxFIFOPtrs + 2);	/* clear Rx in ptr */
-	sOutW(ChP->IndexData, 0);
-	if (RxFIFOEnabled)
-		sEnRxFIFO(ChP);	/* enable Rx FIFO */
-}
-
-/***************************************************************************
-Function: sFlushTxFIFO
-Purpose:  Flush the Tx FIFO
-Call:     sFlushTxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   void
-Comments: To prevent data from being enqueued or dequeued in the Tx FIFO
-          while it is being flushed the receive processor is stopped
-          and the transmitter is disabled.  After these operations a
-          4 uS delay is done before clearing the pointers to allow
-          the receive processor to stop.  These items are handled inside
-          this function.
-Warnings: No context switches are allowed while executing this function.
-*/
-static void sFlushTxFIFO(CHANNEL_T * ChP)
-{
-	int i;
-	Byte_t Ch;		/* channel number within AIOP */
-	int TxEnabled;		/* 1 if transmitter enabled */
-
-	if (sGetTxCnt(ChP) == 0)	/* Tx FIFO empty */
-		return;		/* don't need to flush */
-
-	TxEnabled = 0;
-	if (ChP->TxControl[3] & TX_ENABLE) {
-		TxEnabled = 1;
-		sDisTransmit(ChP);	/* disable transmitter */
-	}
-	sStopRxProcessor(ChP);	/* stop Rx processor */
-	for (i = 0; i < 4000 / 200; i++)	/* delay 4 uS to allow proc to stop */
-		sInB(ChP->IntChan);	/* depends on bus i/o timing */
-	Ch = (Byte_t) sGetChanNum(ChP);
-	sOutB(ChP->Cmd, Ch | RESTXFCNT);	/* apply reset Tx FIFO count */
-	sOutB(ChP->Cmd, Ch);	/* remove reset Tx FIFO count */
-	sOutW((WordIO_t) ChP->IndexAddr, ChP->TxFIFOPtrs);	/* clear Tx in/out ptrs */
-	sOutW(ChP->IndexData, 0);
-	if (TxEnabled)
-		sEnTransmit(ChP);	/* enable transmitter */
-	sStartRxProcessor(ChP);	/* restart Rx processor */
-}
-
-/***************************************************************************
-Function: sWriteTxPrioByte
-Purpose:  Write a byte of priority transmit data to a channel
-Call:     sWriteTxPrioByte(ChP,Data)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Data; The transmit data byte
-
-Return:   int: 1 if the bytes is successfully written, otherwise 0.
-
-Comments: The priority byte is transmitted before any data in the Tx FIFO.
-
-Warnings: No context switches are allowed while executing this function.
-*/
-static int sWriteTxPrioByte(CHANNEL_T * ChP, Byte_t Data)
-{
-	Byte_t DWBuf[4];	/* buffer for double word writes */
-	Word_t *WordPtr;	/* must be far because Win SS != DS */
-	register DWordIO_t IndexAddr;
-
-	if (sGetTxCnt(ChP) > 1) {	/* write it to Tx priority buffer */
-		IndexAddr = ChP->IndexAddr;
-		sOutW((WordIO_t) IndexAddr, ChP->TxPrioCnt);	/* get priority buffer status */
-		if (sInB((ByteIO_t) ChP->IndexData) & PRI_PEND)	/* priority buffer busy */
-			return (0);	/* nothing sent */
-
-		WordPtr = (Word_t *) (&DWBuf[0]);
-		*WordPtr = ChP->TxPrioBuf;	/* data byte address */
-
-		DWBuf[2] = Data;	/* data byte value */
-		out32(IndexAddr, DWBuf);	/* write it out */
-
-		*WordPtr = ChP->TxPrioCnt;	/* Tx priority count address */
-
-		DWBuf[2] = PRI_PEND + 1;	/* indicate 1 byte pending */
-		DWBuf[3] = 0;	/* priority buffer pointer */
-		out32(IndexAddr, DWBuf);	/* write it out */
-	} else {		/* write it to Tx FIFO */
-
-		sWriteTxByte(sGetTxRxDataIO(ChP), Data);
-	}
-	return (1);		/* 1 byte sent */
-}
-
-/***************************************************************************
-Function: sEnInterrupts
-Purpose:  Enable one or more interrupts for a channel
-Call:     sEnInterrupts(ChP,Flags)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Word_t Flags: Interrupt enable flags, can be any combination
-             of the following flags:
-                TXINT_EN:   Interrupt on Tx FIFO empty
-                RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
-                            sSetRxTrigger())
-                SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
-                MCINT_EN:   Interrupt on modem input change
-                CHANINT_EN: Allow channel interrupt signal to the AIOP's
-                            Interrupt Channel Register.
-Return:   void
-Comments: If an interrupt enable flag is set in Flags, that interrupt will be
-          enabled.  If an interrupt enable flag is not set in Flags, that
-          interrupt will not be changed.  Interrupts can be disabled with
-          function sDisInterrupts().
-
-          This function sets the appropriate bit for the channel in the AIOP's
-          Interrupt Mask Register if the CHANINT_EN flag is set.  This allows
-          this channel's bit to be set in the AIOP's Interrupt Channel Register.
-
-          Interrupts must also be globally enabled before channel interrupts
-          will be passed on to the host.  This is done with function
-          sEnGlobalInt().
-
-          In some cases it may be desirable to disable interrupts globally but
-          enable channel interrupts.  This would allow the global interrupt
-          status register to be used to determine which AIOPs need service.
-*/
-static void sEnInterrupts(CHANNEL_T * ChP, Word_t Flags)
-{
-	Byte_t Mask;		/* Interrupt Mask Register */
-
-	ChP->RxControl[2] |=
-	    ((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
-
-	out32(ChP->IndexAddr, ChP->RxControl);
-
-	ChP->TxControl[2] |= ((Byte_t) Flags & TXINT_EN);
-
-	out32(ChP->IndexAddr, ChP->TxControl);
-
-	if (Flags & CHANINT_EN) {
-		Mask = sInB(ChP->IntMask) | sBitMapSetTbl[ChP->ChanNum];
-		sOutB(ChP->IntMask, Mask);
-	}
-}
-
-/***************************************************************************
-Function: sDisInterrupts
-Purpose:  Disable one or more interrupts for a channel
-Call:     sDisInterrupts(ChP,Flags)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Word_t Flags: Interrupt flags, can be any combination
-             of the following flags:
-                TXINT_EN:   Interrupt on Tx FIFO empty
-                RXINT_EN:   Interrupt on Rx FIFO at trigger level (see
-                            sSetRxTrigger())
-                SRCINT_EN:  Interrupt on SRC (Special Rx Condition)
-                MCINT_EN:   Interrupt on modem input change
-                CHANINT_EN: Disable channel interrupt signal to the
-                            AIOP's Interrupt Channel Register.
-Return:   void
-Comments: If an interrupt flag is set in Flags, that interrupt will be
-          disabled.  If an interrupt flag is not set in Flags, that
-          interrupt will not be changed.  Interrupts can be enabled with
-          function sEnInterrupts().
-
-          This function clears the appropriate bit for the channel in the AIOP's
-          Interrupt Mask Register if the CHANINT_EN flag is set.  This blocks
-          this channel's bit from being set in the AIOP's Interrupt Channel
-          Register.
-*/
-static void sDisInterrupts(CHANNEL_T * ChP, Word_t Flags)
-{
-	Byte_t Mask;		/* Interrupt Mask Register */
-
-	ChP->RxControl[2] &=
-	    ~((Byte_t) Flags & (RXINT_EN | SRCINT_EN | MCINT_EN));
-	out32(ChP->IndexAddr, ChP->RxControl);
-	ChP->TxControl[2] &= ~((Byte_t) Flags & TXINT_EN);
-	out32(ChP->IndexAddr, ChP->TxControl);
-
-	if (Flags & CHANINT_EN) {
-		Mask = sInB(ChP->IntMask) & sBitMapClrTbl[ChP->ChanNum];
-		sOutB(ChP->IntMask, Mask);
-	}
-}
-
-static void sSetInterfaceMode(CHANNEL_T * ChP, Byte_t mode)
-{
-	sOutB(ChP->CtlP->AiopIO[2], (mode & 0x18) | ChP->ChanNum);
-}
-
-/*
- *  Not an official SSCI function, but how to reset RocketModems.
- *  ISA bus version
- */
-static void sModemReset(CONTROLLER_T * CtlP, int chan, int on)
-{
-	ByteIO_t addr;
-	Byte_t val;
-
-	addr = CtlP->AiopIO[0] + 0x400;
-	val = sInB(CtlP->MReg3IO);
-	/* if AIOP[1] is not enabled, enable it */
-	if ((val & 2) == 0) {
-		val = sInB(CtlP->MReg2IO);
-		sOutB(CtlP->MReg2IO, (val & 0xfc) | (1 & 0x03));
-		sOutB(CtlP->MBaseIO, (unsigned char) (addr >> 6));
-	}
-
-	sEnAiop(CtlP, 1);
-	if (!on)
-		addr += 8;
-	sOutB(addr + chan, 0);	/* apply or remove reset */
-	sDisAiop(CtlP, 1);
-}
-
-/*
- *  Not an official SSCI function, but how to reset RocketModems.
- *  PCI bus version
- */
-static void sPCIModemReset(CONTROLLER_T * CtlP, int chan, int on)
-{
-	ByteIO_t addr;
-
-	addr = CtlP->AiopIO[0] + 0x40;	/* 2nd AIOP */
-	if (!on)
-		addr += 8;
-	sOutB(addr + chan, 0);	/* apply or remove reset */
-}
-
-/*  Resets the speaker controller on RocketModem II and III devices */
-static void rmSpeakerReset(CONTROLLER_T * CtlP, unsigned long model)
-{
-	ByteIO_t addr;
-
-	/* RocketModem II speaker control is at the 8th port location of offset 0x40 */
-	if ((model == MODEL_RP4M) || (model == MODEL_RP6M)) {
-		addr = CtlP->AiopIO[0] + 0x4F;
-		sOutB(addr, 0);
-	}
-
-	/* RocketModem III speaker control is at the 1st port location of offset 0x80 */
-	if ((model == MODEL_UPCI_RM3_8PORT)
-	    || (model == MODEL_UPCI_RM3_4PORT)) {
-		addr = CtlP->AiopIO[0] + 0x88;
-		sOutB(addr, 0);
-	}
-}
-
-/*  Returns the line number given the controller (board), aiop and channel number */
-static unsigned char GetLineNumber(int ctrl, int aiop, int ch)
-{
-	return lineNumbers[(ctrl << 5) | (aiop << 3) | ch];
-}
-
-/*
- *  Stores the line number associated with a given controller (board), aiop
- *  and channel number.  
- *  Returns:  The line number assigned 
- */
-static unsigned char SetLineNumber(int ctrl, int aiop, int ch)
-{
-	lineNumbers[(ctrl << 5) | (aiop << 3) | ch] = nextLineNumber++;
-	return (nextLineNumber - 1);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/rocket.h linux-libre-2.6.39-gnu/drivers/char/rocket.h
--- linux-libre-2.6.38-gnu/drivers/char/rocket.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rocket.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,111 +0,0 @@
-/*
- * rocket.h --- the exported interface of the rocket driver to its configuration program.
- *
- * Written by Theodore Ts'o, Copyright 1997.
- * Copyright 1997 Comtrol Corporation. 
- *
- */
-
-/*  Model Information Struct */
-typedef struct {
-	unsigned long model;
-	char modelString[80];
-	unsigned long numPorts;
-	int loadrm2;
-	int startingPortNumber;
-} rocketModel_t;
-
-struct rocket_config {
-	int line;
-	int flags;
-	int closing_wait;
-	int close_delay;
-	int port;
-	int reserved[32];
-};
-
-struct rocket_ports {
-	int tty_major;
-	int callout_major;
-	rocketModel_t rocketModel[8];
-};
-
-struct rocket_version {
-	char rocket_version[32];
-	char rocket_date[32];
-	char reserved[64];
-};
-
-/*
- * Rocketport flags
- */
-/*#define ROCKET_CALLOUT_NOHUP    0x00000001 */
-#define ROCKET_FORCE_CD		0x00000002
-#define ROCKET_HUP_NOTIFY	0x00000004
-#define ROCKET_SPLIT_TERMIOS	0x00000008
-#define ROCKET_SPD_MASK		0x00000070
-#define ROCKET_SPD_HI		0x00000010	/* Use 56000 instead of 38400 bps */
-#define ROCKET_SPD_VHI		0x00000020	/* Use 115200 instead of 38400 bps */
-#define ROCKET_SPD_SHI		0x00000030	/* Use 230400 instead of 38400 bps */
-#define ROCKET_SPD_WARP	        0x00000040	/* Use 460800 instead of 38400 bps */
-#define ROCKET_SAK		0x00000080
-#define ROCKET_SESSION_LOCKOUT	0x00000100
-#define ROCKET_PGRP_LOCKOUT	0x00000200
-#define ROCKET_RTS_TOGGLE	0x00000400
-#define ROCKET_MODE_MASK        0x00003000
-#define ROCKET_MODE_RS232       0x00000000
-#define ROCKET_MODE_RS485       0x00001000
-#define ROCKET_MODE_RS422       0x00002000
-#define ROCKET_FLAGS		0x00003FFF
-
-#define ROCKET_USR_MASK 0x0071	/* Legal flags that non-privileged
-				 * users can set or reset */
-
-/*
- * For closing_wait and closing_wait2
- */
-#define ROCKET_CLOSING_WAIT_NONE	ASYNC_CLOSING_WAIT_NONE
-#define ROCKET_CLOSING_WAIT_INF		ASYNC_CLOSING_WAIT_INF
-
-/*
- * Rocketport ioctls -- "RP"
- */
-#define RCKP_GET_STRUCT		0x00525001
-#define RCKP_GET_CONFIG		0x00525002
-#define RCKP_SET_CONFIG		0x00525003
-#define RCKP_GET_PORTS		0x00525004
-#define RCKP_RESET_RM2		0x00525005
-#define RCKP_GET_VERSION	0x00525006
-
-/*  Rocketport Models */
-#define MODEL_RP32INTF        0x0001	/* RP 32 port w/external I/F   */
-#define MODEL_RP8INTF         0x0002	/* RP 8 port w/external I/F    */
-#define MODEL_RP16INTF        0x0003	/* RP 16 port w/external I/F   */
-#define MODEL_RP8OCTA         0x0005	/* RP 8 port w/octa cable      */
-#define MODEL_RP4QUAD         0x0004	/* RP 4 port w/quad cable      */
-#define MODEL_RP8J            0x0006	/* RP 8 port w/RJ11 connectors */
-#define MODEL_RP4J            0x0007	/* RP 4 port w/RJ45 connectors */
-#define MODEL_RP8SNI          0x0008	/* RP 8 port w/ DB78 SNI connector */
-#define MODEL_RP16SNI         0x0009	/* RP 16 port w/ DB78 SNI connector */
-#define MODEL_RPP4            0x000A	/* RP Plus 4 port              */
-#define MODEL_RPP8            0x000B	/* RP Plus 8 port              */
-#define MODEL_RP2_232         0x000E	/* RP Plus 2 port RS232        */
-#define MODEL_RP2_422         0x000F	/* RP Plus 2 port RS232        */
-
-/*  Rocketmodem II Models */
-#define MODEL_RP6M            0x000C	/* RM 6 port                   */
-#define MODEL_RP4M            0x000D	/* RM 4 port                   */
-
-/* Universal PCI boards */
-#define MODEL_UPCI_RP32INTF   0x0801	/* RP UPCI 32 port w/external I/F     */
-#define MODEL_UPCI_RP8INTF    0x0802	/* RP UPCI 8 port w/external I/F      */
-#define MODEL_UPCI_RP16INTF   0x0803	/* RP UPCI 16 port w/external I/F     */
-#define MODEL_UPCI_RP8OCTA    0x0805	/* RP UPCI 8 port w/octa cable        */ 
-#define MODEL_UPCI_RM3_8PORT  0x080C	/* RP UPCI Rocketmodem III 8 port     */
-#define MODEL_UPCI_RM3_4PORT  0x080C	/* RP UPCI Rocketmodem III 4 port     */
-
-/*  Compact PCI 16 port  */
-#define MODEL_CPCI_RP16INTF   0x0903	/* RP Compact PCI 16 port w/external I/F */
-
-/* All ISA boards */
-#define MODEL_ISA             0x1000
diff -druN linux-libre-2.6.38-gnu/drivers/char/rocket_int.h linux-libre-2.6.39-gnu/drivers/char/rocket_int.h
--- linux-libre-2.6.38-gnu/drivers/char/rocket_int.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/rocket_int.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,1214 +0,0 @@
-/*
- * rocket_int.h --- internal header file for rocket.c
- *
- * Written by Theodore Ts'o, Copyright 1997.
- * Copyright 1997 Comtrol Corporation.  
- * 
- */
-
-/*
- * Definition of the types in rcktpt_type
- */
-#define ROCKET_TYPE_NORMAL	0
-#define ROCKET_TYPE_MODEM	1
-#define ROCKET_TYPE_MODEMII	2
-#define ROCKET_TYPE_MODEMIII	3
-#define ROCKET_TYPE_PC104       4
-
-#include <linux/mutex.h>
-
-#include <asm/io.h>
-#include <asm/byteorder.h>
-
-typedef unsigned char Byte_t;
-typedef unsigned int ByteIO_t;
-
-typedef unsigned int Word_t;
-typedef unsigned int WordIO_t;
-
-typedef unsigned int DWordIO_t;
-
-/*
- * Note!  Normally the Linux I/O macros already take care of
- * byte-swapping the I/O instructions.  However, all accesses using
- * sOutDW aren't really 32-bit accesses, but should be handled in byte
- * order.  Hence the use of the cpu_to_le32() macro to byte-swap
- * things to no-op the byte swapping done by the big-endian outl()
- * instruction.
- */
-
-static inline void sOutB(unsigned short port, unsigned char value)
-{
-#ifdef ROCKET_DEBUG_IO
-	printk(KERN_DEBUG "sOutB(%x, %x)...\n", port, value);
-#endif
-	outb_p(value, port);
-}
-
-static inline void sOutW(unsigned short port, unsigned short value)
-{
-#ifdef ROCKET_DEBUG_IO
-	printk(KERN_DEBUG "sOutW(%x, %x)...\n", port, value);
-#endif
-	outw_p(value, port);
-}
-
-static inline void out32(unsigned short port, Byte_t *p)
-{
-	u32 value = get_unaligned_le32(p);
-#ifdef ROCKET_DEBUG_IO
-	printk(KERN_DEBUG "out32(%x, %lx)...\n", port, value);
-#endif
-	outl_p(value, port);
-}
-
-static inline unsigned char sInB(unsigned short port)
-{
-	return inb_p(port);
-}
-
-static inline unsigned short sInW(unsigned short port)
-{
-	return inw_p(port);
-}
-
-/* This is used to move arrays of bytes so byte swapping isn't appropriate. */
-#define sOutStrW(port, addr, count) if (count) outsw(port, addr, count)
-#define sInStrW(port, addr, count) if (count) insw(port, addr, count)
-
-#define CTL_SIZE 8
-#define AIOP_CTL_SIZE 4
-#define CHAN_AIOP_SIZE 8
-#define MAX_PORTS_PER_AIOP 8
-#define MAX_AIOPS_PER_BOARD 4
-#define MAX_PORTS_PER_BOARD 32
-
-/* Bus type ID */
-#define	isISA	0
-#define	isPCI	1
-#define	isMC	2
-
-/* Controller ID numbers */
-#define CTLID_NULL  -1		/* no controller exists */
-#define CTLID_0001  0x0001	/* controller release 1 */
-
-/* AIOP ID numbers, identifies AIOP type implementing channel */
-#define AIOPID_NULL -1		/* no AIOP or channel exists */
-#define AIOPID_0001 0x0001	/* AIOP release 1 */
-
-/************************************************************************
- Global Register Offsets - Direct Access - Fixed values
-************************************************************************/
-
-#define _CMD_REG   0x38		/* Command Register            8    Write */
-#define _INT_CHAN  0x39		/* Interrupt Channel Register  8    Read */
-#define _INT_MASK  0x3A		/* Interrupt Mask Register     8    Read / Write */
-#define _UNUSED    0x3B		/* Unused                      8 */
-#define _INDX_ADDR 0x3C		/* Index Register Address      16   Write */
-#define _INDX_DATA 0x3E		/* Index Register Data         8/16 Read / Write */
-
-/************************************************************************
- Channel Register Offsets for 1st channel in AIOP - Direct Access
-************************************************************************/
-#define _TD0       0x00		/* Transmit Data               16   Write */
-#define _RD0       0x00		/* Receive Data                16   Read */
-#define _CHN_STAT0 0x20		/* Channel Status              8/16 Read / Write */
-#define _FIFO_CNT0 0x10		/* Transmit/Receive FIFO Count 16   Read */
-#define _INT_ID0   0x30		/* Interrupt Identification    8    Read */
-
-/************************************************************************
- Tx Control Register Offsets - Indexed - External - Fixed
-************************************************************************/
-#define _TX_ENBLS  0x980	/* Tx Processor Enables Register 8 Read / Write */
-#define _TXCMP1    0x988	/* Transmit Compare Value #1     8 Read / Write */
-#define _TXCMP2    0x989	/* Transmit Compare Value #2     8 Read / Write */
-#define _TXREP1B1  0x98A	/* Tx Replace Value #1 - Byte 1  8 Read / Write */
-#define _TXREP1B2  0x98B	/* Tx Replace Value #1 - Byte 2  8 Read / Write */
-#define _TXREP2    0x98C	/* Transmit Replace Value #2     8 Read / Write */
-
-/************************************************************************
-Memory Controller Register Offsets - Indexed - External - Fixed
-************************************************************************/
-#define _RX_FIFO    0x000	/* Rx FIFO */
-#define _TX_FIFO    0x800	/* Tx FIFO */
-#define _RXF_OUTP   0x990	/* Rx FIFO OUT pointer        16 Read / Write */
-#define _RXF_INP    0x992	/* Rx FIFO IN pointer         16 Read / Write */
-#define _TXF_OUTP   0x994	/* Tx FIFO OUT pointer        8  Read / Write */
-#define _TXF_INP    0x995	/* Tx FIFO IN pointer         8  Read / Write */
-#define _TXP_CNT    0x996	/* Tx Priority Count          8  Read / Write */
-#define _TXP_PNTR   0x997	/* Tx Priority Pointer        8  Read / Write */
-
-#define PRI_PEND    0x80	/* Priority data pending (bit7, Tx pri cnt) */
-#define TXFIFO_SIZE 255		/* size of Tx FIFO */
-#define RXFIFO_SIZE 1023	/* size of Rx FIFO */
-
-/************************************************************************
-Tx Priority Buffer - Indexed - External - Fixed
-************************************************************************/
-#define _TXP_BUF    0x9C0	/* Tx Priority Buffer  32  Bytes   Read / Write */
-#define TXP_SIZE    0x20	/* 32 bytes */
-
-/************************************************************************
-Channel Register Offsets - Indexed - Internal - Fixed
-************************************************************************/
-
-#define _TX_CTRL    0xFF0	/* Transmit Control               16  Write */
-#define _RX_CTRL    0xFF2	/* Receive Control                 8  Write */
-#define _BAUD       0xFF4	/* Baud Rate                      16  Write */
-#define _CLK_PRE    0xFF6	/* Clock Prescaler                 8  Write */
-
-#define STMBREAK   0x08		/* BREAK */
-#define STMFRAME   0x04		/* framing error */
-#define STMRCVROVR 0x02		/* receiver over run error */
-#define STMPARITY  0x01		/* parity error */
-#define STMERROR   (STMBREAK | STMFRAME | STMPARITY)
-#define STMBREAKH   0x800	/* BREAK */
-#define STMFRAMEH   0x400	/* framing error */
-#define STMRCVROVRH 0x200	/* receiver over run error */
-#define STMPARITYH  0x100	/* parity error */
-#define STMERRORH   (STMBREAKH | STMFRAMEH | STMPARITYH)
-
-#define CTS_ACT   0x20		/* CTS input asserted */
-#define DSR_ACT   0x10		/* DSR input asserted */
-#define CD_ACT    0x08		/* CD input asserted */
-#define TXFIFOMT  0x04		/* Tx FIFO is empty */
-#define TXSHRMT   0x02		/* Tx shift register is empty */
-#define RDA       0x01		/* Rx data available */
-#define DRAINED (TXFIFOMT | TXSHRMT)	/* indicates Tx is drained */
-
-#define STATMODE  0x8000	/* status mode enable bit */
-#define RXFOVERFL 0x2000	/* receive FIFO overflow */
-#define RX2MATCH  0x1000	/* receive compare byte 2 match */
-#define RX1MATCH  0x0800	/* receive compare byte 1 match */
-#define RXBREAK   0x0400	/* received BREAK */
-#define RXFRAME   0x0200	/* received framing error */
-#define RXPARITY  0x0100	/* received parity error */
-#define STATERROR (RXBREAK | RXFRAME | RXPARITY)
-
-#define CTSFC_EN  0x80		/* CTS flow control enable bit */
-#define RTSTOG_EN 0x40		/* RTS toggle enable bit */
-#define TXINT_EN  0x10		/* transmit interrupt enable */
-#define STOP2     0x08		/* enable 2 stop bits (0 = 1 stop) */
-#define PARITY_EN 0x04		/* enable parity (0 = no parity) */
-#define EVEN_PAR  0x02		/* even parity (0 = odd parity) */
-#define DATA8BIT  0x01		/* 8 bit data (0 = 7 bit data) */
-
-#define SETBREAK  0x10		/* send break condition (must clear) */
-#define LOCALLOOP 0x08		/* local loopback set for test */
-#define SET_DTR   0x04		/* assert DTR */
-#define SET_RTS   0x02		/* assert RTS */
-#define TX_ENABLE 0x01		/* enable transmitter */
-
-#define RTSFC_EN  0x40		/* RTS flow control enable */
-#define RXPROC_EN 0x20		/* receive processor enable */
-#define TRIG_NO   0x00		/* Rx FIFO trigger level 0 (no trigger) */
-#define TRIG_1    0x08		/* trigger level 1 char */
-#define TRIG_1_2  0x10		/* trigger level 1/2 */
-#define TRIG_7_8  0x18		/* trigger level 7/8 */
-#define TRIG_MASK 0x18		/* trigger level mask */
-#define SRCINT_EN 0x04		/* special Rx condition interrupt enable */
-#define RXINT_EN  0x02		/* Rx interrupt enable */
-#define MCINT_EN  0x01		/* modem change interrupt enable */
-
-#define RXF_TRIG  0x20		/* Rx FIFO trigger level interrupt */
-#define TXFIFO_MT 0x10		/* Tx FIFO empty interrupt */
-#define SRC_INT   0x08		/* special receive condition interrupt */
-#define DELTA_CD  0x04		/* CD change interrupt */
-#define DELTA_CTS 0x02		/* CTS change interrupt */
-#define DELTA_DSR 0x01		/* DSR change interrupt */
-
-#define REP1W2_EN 0x10		/* replace byte 1 with 2 bytes enable */
-#define IGN2_EN   0x08		/* ignore byte 2 enable */
-#define IGN1_EN   0x04		/* ignore byte 1 enable */
-#define COMP2_EN  0x02		/* compare byte 2 enable */
-#define COMP1_EN  0x01		/* compare byte 1 enable */
-
-#define RESET_ALL 0x80		/* reset AIOP (all channels) */
-#define TXOVERIDE 0x40		/* Transmit software off override */
-#define RESETUART 0x20		/* reset channel's UART */
-#define RESTXFCNT 0x10		/* reset channel's Tx FIFO count register */
-#define RESRXFCNT 0x08		/* reset channel's Rx FIFO count register */
-
-#define INTSTAT0  0x01		/* AIOP 0 interrupt status */
-#define INTSTAT1  0x02		/* AIOP 1 interrupt status */
-#define INTSTAT2  0x04		/* AIOP 2 interrupt status */
-#define INTSTAT3  0x08		/* AIOP 3 interrupt status */
-
-#define INTR_EN   0x08		/* allow interrupts to host */
-#define INT_STROB 0x04		/* strobe and clear interrupt line (EOI) */
-
-/**************************************************************************
- MUDBAC remapped for PCI
-**************************************************************************/
-
-#define _CFG_INT_PCI  0x40
-#define _PCI_INT_FUNC 0x3A
-
-#define PCI_STROB 0x2000	/* bit 13 of int aiop register */
-#define INTR_EN_PCI   0x0010	/* allow interrupts to host */
-
-/*
- * Definitions for Universal PCI board registers
- */
-#define _PCI_9030_INT_CTRL	0x4c          /* Offsets from BAR1 */
-#define _PCI_9030_GPIO_CTRL	0x54
-#define PCI_INT_CTRL_AIOP	0x0001
-#define PCI_GPIO_CTRL_8PORT	0x4000
-#define _PCI_9030_RING_IND	0xc0          /* Offsets from BAR1 */
-
-#define CHAN3_EN  0x08		/* enable AIOP 3 */
-#define CHAN2_EN  0x04		/* enable AIOP 2 */
-#define CHAN1_EN  0x02		/* enable AIOP 1 */
-#define CHAN0_EN  0x01		/* enable AIOP 0 */
-#define FREQ_DIS  0x00
-#define FREQ_274HZ 0x60
-#define FREQ_137HZ 0x50
-#define FREQ_69HZ  0x40
-#define FREQ_34HZ  0x30
-#define FREQ_17HZ  0x20
-#define FREQ_9HZ   0x10
-#define PERIODIC_ONLY 0x80	/* only PERIODIC interrupt */
-
-#define CHANINT_EN 0x0100	/* flags to enable/disable channel ints */
-
-#define RDATASIZE 72
-#define RREGDATASIZE 52
-
-/*
- * AIOP interrupt bits for ISA/PCI boards and UPCI boards.
- */
-#define AIOP_INTR_BIT_0		0x0001
-#define AIOP_INTR_BIT_1		0x0002
-#define AIOP_INTR_BIT_2		0x0004
-#define AIOP_INTR_BIT_3		0x0008
-
-#define AIOP_INTR_BITS ( \
-	AIOP_INTR_BIT_0 \
-	| AIOP_INTR_BIT_1 \
-	| AIOP_INTR_BIT_2 \
-	| AIOP_INTR_BIT_3)
-
-#define UPCI_AIOP_INTR_BIT_0	0x0004
-#define UPCI_AIOP_INTR_BIT_1	0x0020
-#define UPCI_AIOP_INTR_BIT_2	0x0100
-#define UPCI_AIOP_INTR_BIT_3	0x0800
-
-#define UPCI_AIOP_INTR_BITS ( \
-	UPCI_AIOP_INTR_BIT_0 \
-	| UPCI_AIOP_INTR_BIT_1 \
-	| UPCI_AIOP_INTR_BIT_2 \
-	| UPCI_AIOP_INTR_BIT_3)
-
-/* Controller level information structure */
-typedef struct {
-	int CtlID;
-	int CtlNum;
-	int BusType;
-	int boardType;
-	int isUPCI;
-	WordIO_t PCIIO;
-	WordIO_t PCIIO2;
-	ByteIO_t MBaseIO;
-	ByteIO_t MReg1IO;
-	ByteIO_t MReg2IO;
-	ByteIO_t MReg3IO;
-	Byte_t MReg2;
-	Byte_t MReg3;
-	int NumAiop;
-	int AltChanRingIndicator;
-	ByteIO_t UPCIRingInd;
-	WordIO_t AiopIO[AIOP_CTL_SIZE];
-	ByteIO_t AiopIntChanIO[AIOP_CTL_SIZE];
-	int AiopID[AIOP_CTL_SIZE];
-	int AiopNumChan[AIOP_CTL_SIZE];
-	Word_t *AiopIntrBits;
-} CONTROLLER_T;
-
-typedef CONTROLLER_T CONTROLLER_t;
-
-/* Channel level information structure */
-typedef struct {
-	CONTROLLER_T *CtlP;
-	int AiopNum;
-	int ChanID;
-	int ChanNum;
-	int rtsToggle;
-
-	ByteIO_t Cmd;
-	ByteIO_t IntChan;
-	ByteIO_t IntMask;
-	DWordIO_t IndexAddr;
-	WordIO_t IndexData;
-
-	WordIO_t TxRxData;
-	WordIO_t ChanStat;
-	WordIO_t TxRxCount;
-	ByteIO_t IntID;
-
-	Word_t TxFIFO;
-	Word_t TxFIFOPtrs;
-	Word_t RxFIFO;
-	Word_t RxFIFOPtrs;
-	Word_t TxPrioCnt;
-	Word_t TxPrioPtr;
-	Word_t TxPrioBuf;
-
-	Byte_t R[RREGDATASIZE];
-
-	Byte_t BaudDiv[4];
-	Byte_t TxControl[4];
-	Byte_t RxControl[4];
-	Byte_t TxEnables[4];
-	Byte_t TxCompare[4];
-	Byte_t TxReplace1[4];
-	Byte_t TxReplace2[4];
-} CHANNEL_T;
-
-typedef CHANNEL_T CHANNEL_t;
-typedef CHANNEL_T *CHANPTR_T;
-
-#define InterfaceModeRS232  0x00
-#define InterfaceModeRS422  0x08
-#define InterfaceModeRS485  0x10
-#define InterfaceModeRS232T 0x18
-
-/***************************************************************************
-Function: sClrBreak
-Purpose:  Stop sending a transmit BREAK signal
-Call:     sClrBreak(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrBreak(ChP) \
-do { \
-   (ChP)->TxControl[3] &= ~SETBREAK; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrDTR
-Purpose:  Clr the DTR output
-Call:     sClrDTR(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrDTR(ChP) \
-do { \
-   (ChP)->TxControl[3] &= ~SET_DTR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrRTS
-Purpose:  Clr the RTS output
-Call:     sClrRTS(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrRTS(ChP) \
-do { \
-   if ((ChP)->rtsToggle) break; \
-   (ChP)->TxControl[3] &= ~SET_RTS; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sClrTxXOFF
-Purpose:  Clear any existing transmit software flow control off condition
-Call:     sClrTxXOFF(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sClrTxXOFF(ChP) \
-do { \
-   sOutB((ChP)->Cmd,TXOVERIDE | (Byte_t)(ChP)->ChanNum); \
-   sOutB((ChP)->Cmd,(Byte_t)(ChP)->ChanNum); \
-} while (0)
-
-/***************************************************************************
-Function: sCtlNumToCtlPtr
-Purpose:  Convert a controller number to controller structure pointer
-Call:     sCtlNumToCtlPtr(CtlNum)
-          int CtlNum; Controller number
-Return:   CONTROLLER_T *: Ptr to controller structure
-*/
-#define sCtlNumToCtlPtr(CTLNUM) &sController[CTLNUM]
-
-/***************************************************************************
-Function: sControllerEOI
-Purpose:  Strobe the MUDBAC's End Of Interrupt bit.
-Call:     sControllerEOI(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-*/
-#define sControllerEOI(CTLP) sOutB((CTLP)->MReg2IO,(CTLP)->MReg2 | INT_STROB)
-
-/***************************************************************************
-Function: sPCIControllerEOI
-Purpose:  Strobe the PCI End Of Interrupt bit.
-          For the UPCI boards, toggle the AIOP interrupt enable bit
-	  (this was taken from the Windows driver).
-Call:     sPCIControllerEOI(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-*/
-#define sPCIControllerEOI(CTLP) \
-do { \
-    if ((CTLP)->isUPCI) { \
-	Word_t w = sInW((CTLP)->PCIIO); \
-	sOutW((CTLP)->PCIIO, (w ^ PCI_INT_CTRL_AIOP)); \
-	sOutW((CTLP)->PCIIO, w); \
-    } \
-    else { \
-	sOutW((CTLP)->PCIIO, PCI_STROB); \
-    } \
-} while (0)
-
-/***************************************************************************
-Function: sDisAiop
-Purpose:  Disable I/O access to an AIOP
-Call:     sDisAiop(CltP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; Number of AIOP on controller
-*/
-#define sDisAiop(CTLP,AIOPNUM) \
-do { \
-   (CTLP)->MReg3 &= sBitMapClrTbl[AIOPNUM]; \
-   sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-} while (0)
-
-/***************************************************************************
-Function: sDisCTSFlowCtl
-Purpose:  Disable output flow control using CTS
-Call:     sDisCTSFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisCTSFlowCtl(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~CTSFC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisIXANY
-Purpose:  Disable IXANY Software Flow Control
-Call:     sDisIXANY(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisIXANY(ChP) \
-do { \
-   (ChP)->R[0x0e] = 0x86; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
-} while (0)
-
-/***************************************************************************
-Function: DisParity
-Purpose:  Disable parity
-Call:     sDisParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-*/
-#define sDisParity(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~PARITY_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisRTSToggle
-Purpose:  Disable RTS toggle
-Call:     sDisRTSToggle(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisRTSToggle(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~RTSTOG_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-   (ChP)->rtsToggle = 0; \
-} while (0)
-
-/***************************************************************************
-Function: sDisRxFIFO
-Purpose:  Disable Rx FIFO
-Call:     sDisRxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisRxFIFO(ChP) \
-do { \
-   (ChP)->R[0x32] = 0x0a; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
-} while (0)
-
-/***************************************************************************
-Function: sDisRxStatusMode
-Purpose:  Disable the Rx status mode
-Call:     sDisRxStatusMode(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This takes the channel out of the receive status mode.  All
-          subsequent reads of receive data using sReadRxWord() will return
-          two data bytes.
-*/
-#define sDisRxStatusMode(ChP) sOutW((ChP)->ChanStat,0)
-
-/***************************************************************************
-Function: sDisTransmit
-Purpose:  Disable transmit
-Call:     sDisTransmit(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-          This disables movement of Tx data from the Tx FIFO into the 1 byte
-          Tx buffer.  Therefore there could be up to a 2 byte latency
-          between the time sDisTransmit() is called and the transmit buffer
-          and transmit shift register going completely empty.
-*/
-#define sDisTransmit(ChP) \
-do { \
-   (ChP)->TxControl[3] &= ~TX_ENABLE; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sDisTxSoftFlowCtl
-Purpose:  Disable Tx Software Flow Control
-Call:     sDisTxSoftFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sDisTxSoftFlowCtl(ChP) \
-do { \
-   (ChP)->R[0x06] = 0x8a; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sEnAiop
-Purpose:  Enable I/O access to an AIOP
-Call:     sEnAiop(CltP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; Number of AIOP on controller
-*/
-#define sEnAiop(CTLP,AIOPNUM) \
-do { \
-   (CTLP)->MReg3 |= sBitMapSetTbl[AIOPNUM]; \
-   sOutB((CTLP)->MReg3IO,(CTLP)->MReg3); \
-} while (0)
-
-/***************************************************************************
-Function: sEnCTSFlowCtl
-Purpose:  Enable output flow control using CTS
-Call:     sEnCTSFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnCTSFlowCtl(ChP) \
-do { \
-   (ChP)->TxControl[2] |= CTSFC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnIXANY
-Purpose:  Enable IXANY Software Flow Control
-Call:     sEnIXANY(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnIXANY(ChP) \
-do { \
-   (ChP)->R[0x0e] = 0x21; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x0c]); \
-} while (0)
-
-/***************************************************************************
-Function: EnParity
-Purpose:  Enable parity
-Call:     sEnParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: Before enabling parity odd or even parity should be chosen using
-          functions sSetOddParity() or sSetEvenParity().
-*/
-#define sEnParity(ChP) \
-do { \
-   (ChP)->TxControl[2] |= PARITY_EN; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRTSToggle
-Purpose:  Enable RTS toggle
-Call:     sEnRTSToggle(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function will disable RTS flow control and clear the RTS
-          line to allow operation of RTS toggle.
-*/
-#define sEnRTSToggle(ChP) \
-do { \
-   (ChP)->RxControl[2] &= ~RTSFC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->RxControl); \
-   (ChP)->TxControl[2] |= RTSTOG_EN; \
-   (ChP)->TxControl[3] &= ~SET_RTS; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-   (ChP)->rtsToggle = 1; \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxFIFO
-Purpose:  Enable Rx FIFO
-Call:     sEnRxFIFO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnRxFIFO(ChP) \
-do { \
-   (ChP)->R[0x32] = 0x08; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x30]); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxProcessor
-Purpose:  Enable the receive processor
-Call:     sEnRxProcessor(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function is used to start the receive processor.  When
-          the channel is in the reset state the receive processor is not
-          running.  This is done to prevent the receive processor from
-          executing invalid microcode instructions prior to the
-          downloading of the microcode.
-
-Warnings: This function must be called after valid microcode has been
-          downloaded to the AIOP, and it must not be called before the
-          microcode has been downloaded.
-*/
-#define sEnRxProcessor(ChP) \
-do { \
-   (ChP)->RxControl[2] |= RXPROC_EN; \
-   out32((ChP)->IndexAddr,(ChP)->RxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnRxStatusMode
-Purpose:  Enable the Rx status mode
-Call:     sEnRxStatusMode(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This places the channel in the receive status mode.  All subsequent
-          reads of receive data using sReadRxWord() will return a data byte
-          in the low word and a status byte in the high word.
-
-*/
-#define sEnRxStatusMode(ChP) sOutW((ChP)->ChanStat,STATMODE)
-
-/***************************************************************************
-Function: sEnTransmit
-Purpose:  Enable transmit
-Call:     sEnTransmit(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnTransmit(ChP) \
-do { \
-   (ChP)->TxControl[3] |= TX_ENABLE; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sEnTxSoftFlowCtl
-Purpose:  Enable Tx Software Flow Control
-Call:     sEnTxSoftFlowCtl(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sEnTxSoftFlowCtl(ChP) \
-do { \
-   (ChP)->R[0x06] = 0xc5; \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sGetAiopIntStatus
-Purpose:  Get the AIOP interrupt status
-Call:     sGetAiopIntStatus(CtlP,AiopNum)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; AIOP number
-Return:   Byte_t: The AIOP interrupt status.  Bits 0 through 7
-                         represent channels 0 through 7 respectively.  If a
-                         bit is set that channel is interrupting.
-*/
-#define sGetAiopIntStatus(CTLP,AIOPNUM) sInB((CTLP)->AiopIntChanIO[AIOPNUM])
-
-/***************************************************************************
-Function: sGetAiopNumChan
-Purpose:  Get the number of channels supported by an AIOP
-Call:     sGetAiopNumChan(CtlP,AiopNum)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-          int AiopNum; AIOP number
-Return:   int: The number of channels supported by the AIOP
-*/
-#define sGetAiopNumChan(CTLP,AIOPNUM) (CTLP)->AiopNumChan[AIOPNUM]
-
-/***************************************************************************
-Function: sGetChanIntID
-Purpose:  Get a channel's interrupt identification byte
-Call:     sGetChanIntID(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Byte_t: The channel interrupt ID.  Can be any
-             combination of the following flags:
-                RXF_TRIG:     Rx FIFO trigger level interrupt
-                TXFIFO_MT:    Tx FIFO empty interrupt
-                SRC_INT:      Special receive condition interrupt
-                DELTA_CD:     CD change interrupt
-                DELTA_CTS:    CTS change interrupt
-                DELTA_DSR:    DSR change interrupt
-*/
-#define sGetChanIntID(ChP) (sInB((ChP)->IntID) & (RXF_TRIG | TXFIFO_MT | SRC_INT | DELTA_CD | DELTA_CTS | DELTA_DSR))
-
-/***************************************************************************
-Function: sGetChanNum
-Purpose:  Get the number of a channel within an AIOP
-Call:     sGetChanNum(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   int: Channel number within AIOP, or NULLCHAN if channel does
-               not exist.
-*/
-#define sGetChanNum(ChP) (ChP)->ChanNum
-
-/***************************************************************************
-Function: sGetChanStatus
-Purpose:  Get the channel status
-Call:     sGetChanStatus(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Word_t: The channel status.  Can be any combination of
-             the following flags:
-                LOW BYTE FLAGS
-                CTS_ACT:      CTS input asserted
-                DSR_ACT:      DSR input asserted
-                CD_ACT:       CD input asserted
-                TXFIFOMT:     Tx FIFO is empty
-                TXSHRMT:      Tx shift register is empty
-                RDA:          Rx data available
-
-                HIGH BYTE FLAGS
-                STATMODE:     status mode enable bit
-                RXFOVERFL:    receive FIFO overflow
-                RX2MATCH:     receive compare byte 2 match
-                RX1MATCH:     receive compare byte 1 match
-                RXBREAK:      received BREAK
-                RXFRAME:      received framing error
-                RXPARITY:     received parity error
-Warnings: This function will clear the high byte flags in the Channel
-          Status Register.
-*/
-#define sGetChanStatus(ChP) sInW((ChP)->ChanStat)
-
-/***************************************************************************
-Function: sGetChanStatusLo
-Purpose:  Get the low byte only of the channel status
-Call:     sGetChanStatusLo(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Byte_t: The channel status low byte.  Can be any combination
-             of the following flags:
-                CTS_ACT:      CTS input asserted
-                DSR_ACT:      DSR input asserted
-                CD_ACT:       CD input asserted
-                TXFIFOMT:     Tx FIFO is empty
-                TXSHRMT:      Tx shift register is empty
-                RDA:          Rx data available
-*/
-#define sGetChanStatusLo(ChP) sInB((ByteIO_t)(ChP)->ChanStat)
-
-/**********************************************************************
- * Get RI status of channel
- * Defined as a function in rocket.c   -aes
- */
-#if 0
-#define sGetChanRI(ChP) ((ChP)->CtlP->AltChanRingIndicator ? \
-                          (sInB((ByteIO_t)((ChP)->ChanStat+8)) & DSR_ACT) : \
-                            (((ChP)->CtlP->boardType == ROCKET_TYPE_PC104) ? \
-                               (!(sInB((ChP)->CtlP->AiopIO[3]) & sBitMapSetTbl[(ChP)->ChanNum])) : \
-                             0))
-#endif
-
-/***************************************************************************
-Function: sGetControllerIntStatus
-Purpose:  Get the controller interrupt status
-Call:     sGetControllerIntStatus(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-Return:   Byte_t: The controller interrupt status in the lower 4
-                         bits.  Bits 0 through 3 represent AIOP's 0
-                         through 3 respectively.  If a bit is set that
-                         AIOP is interrupting.  Bits 4 through 7 will
-                         always be cleared.
-*/
-#define sGetControllerIntStatus(CTLP) (sInB((CTLP)->MReg1IO) & 0x0f)
-
-/***************************************************************************
-Function: sPCIGetControllerIntStatus
-Purpose:  Get the controller interrupt status
-Call:     sPCIGetControllerIntStatus(CtlP)
-          CONTROLLER_T *CtlP; Ptr to controller structure
-Return:   unsigned char: The controller interrupt status in the lower 4
-                         bits and bit 4.  Bits 0 through 3 represent AIOP's 0
-                         through 3 respectively. Bit 4 is set if the int 
-			 was generated from periodic. If a bit is set the
-			 AIOP is interrupting.
-*/
-#define sPCIGetControllerIntStatus(CTLP) \
-	((CTLP)->isUPCI ? \
-	  (sInW((CTLP)->PCIIO2) & UPCI_AIOP_INTR_BITS) : \
-	  ((sInW((CTLP)->PCIIO) >> 8) & AIOP_INTR_BITS))
-
-/***************************************************************************
-
-Function: sGetRxCnt
-Purpose:  Get the number of data bytes in the Rx FIFO
-Call:     sGetRxCnt(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   int: The number of data bytes in the Rx FIFO.
-Comments: Byte read of count register is required to obtain Rx count.
-
-*/
-#define sGetRxCnt(ChP) sInW((ChP)->TxRxCount)
-
-/***************************************************************************
-Function: sGetTxCnt
-Purpose:  Get the number of data bytes in the Tx FIFO
-Call:     sGetTxCnt(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   Byte_t: The number of data bytes in the Tx FIFO.
-Comments: Byte read of count register is required to obtain Tx count.
-
-*/
-#define sGetTxCnt(ChP) sInB((ByteIO_t)(ChP)->TxRxCount)
-
-/*****************************************************************************
-Function: sGetTxRxDataIO
-Purpose:  Get the I/O address of a channel's TxRx Data register
-Call:     sGetTxRxDataIO(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Return:   WordIO_t: I/O address of a channel's TxRx Data register
-*/
-#define sGetTxRxDataIO(ChP) (ChP)->TxRxData
-
-/***************************************************************************
-Function: sInitChanDefaults
-Purpose:  Initialize a channel structure to it's default state.
-Call:     sInitChanDefaults(ChP)
-          CHANNEL_T *ChP; Ptr to the channel structure
-Comments: This function must be called once for every channel structure
-          that exists before any other SSCI calls can be made.
-
-*/
-#define sInitChanDefaults(ChP) \
-do { \
-   (ChP)->CtlP = NULLCTLPTR; \
-   (ChP)->AiopNum = NULLAIOP; \
-   (ChP)->ChanID = AIOPID_NULL; \
-   (ChP)->ChanNum = NULLCHAN; \
-} while (0)
-
-/***************************************************************************
-Function: sResetAiopByNum
-Purpose:  Reset the AIOP by number
-Call:     sResetAiopByNum(CTLP,AIOPNUM)
-	CONTROLLER_T CTLP; Ptr to controller structure
-	AIOPNUM; AIOP index 
-*/
-#define sResetAiopByNum(CTLP,AIOPNUM) \
-do { \
-   sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,RESET_ALL); \
-   sOutB((CTLP)->AiopIO[(AIOPNUM)]+_CMD_REG,0x0); \
-} while (0)
-
-/***************************************************************************
-Function: sSendBreak
-Purpose:  Send a transmit BREAK signal
-Call:     sSendBreak(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSendBreak(ChP) \
-do { \
-   (ChP)->TxControl[3] |= SETBREAK; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetBaud
-Purpose:  Set baud rate
-Call:     sSetBaud(ChP,Divisor)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Word_t Divisor; 16 bit baud rate divisor for channel
-*/
-#define sSetBaud(ChP,DIVISOR) \
-do { \
-   (ChP)->BaudDiv[2] = (Byte_t)(DIVISOR); \
-   (ChP)->BaudDiv[3] = (Byte_t)((DIVISOR) >> 8); \
-   out32((ChP)->IndexAddr,(ChP)->BaudDiv); \
-} while (0)
-
-/***************************************************************************
-Function: sSetData7
-Purpose:  Set data bits to 7
-Call:     sSetData7(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetData7(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~DATA8BIT; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetData8
-Purpose:  Set data bits to 8
-Call:     sSetData8(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetData8(ChP) \
-do { \
-   (ChP)->TxControl[2] |= DATA8BIT; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetDTR
-Purpose:  Set the DTR output
-Call:     sSetDTR(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetDTR(ChP) \
-do { \
-   (ChP)->TxControl[3] |= SET_DTR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetEvenParity
-Purpose:  Set even parity
-Call:     sSetEvenParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: This function has no effect unless parity is enabled with function
-          sEnParity().
-*/
-#define sSetEvenParity(ChP) \
-do { \
-   (ChP)->TxControl[2] |= EVEN_PAR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetOddParity
-Purpose:  Set odd parity
-Call:     sSetOddParity(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: Function sSetParity() can be used in place of functions sEnParity(),
-          sDisParity(), sSetOddParity(), and sSetEvenParity().
-
-Warnings: This function has no effect unless parity is enabled with function
-          sEnParity().
-*/
-#define sSetOddParity(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~EVEN_PAR; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetRTS
-Purpose:  Set the RTS output
-Call:     sSetRTS(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetRTS(ChP) \
-do { \
-   if ((ChP)->rtsToggle) break; \
-   (ChP)->TxControl[3] |= SET_RTS; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetRxTrigger
-Purpose:  Set the Rx FIFO trigger level
-Call:     sSetRxProcessor(ChP,Level)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Level; Number of characters in Rx FIFO at which the
-             interrupt will be generated.  Can be any of the following flags:
-
-             TRIG_NO:   no trigger
-             TRIG_1:    1 character in FIFO
-             TRIG_1_2:  FIFO 1/2 full
-             TRIG_7_8:  FIFO 7/8 full
-Comments: An interrupt will be generated when the trigger level is reached
-          only if function sEnInterrupt() has been called with flag
-          RXINT_EN set.  The RXF_TRIG flag in the Interrupt Idenfification
-          register will be set whenever the trigger level is reached
-          regardless of the setting of RXINT_EN.
-
-*/
-#define sSetRxTrigger(ChP,LEVEL) \
-do { \
-   (ChP)->RxControl[2] &= ~TRIG_MASK; \
-   (ChP)->RxControl[2] |= LEVEL; \
-   out32((ChP)->IndexAddr,(ChP)->RxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetStop1
-Purpose:  Set stop bits to 1
-Call:     sSetStop1(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetStop1(ChP) \
-do { \
-   (ChP)->TxControl[2] &= ~STOP2; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetStop2
-Purpose:  Set stop bits to 2
-Call:     sSetStop2(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-*/
-#define sSetStop2(ChP) \
-do { \
-   (ChP)->TxControl[2] |= STOP2; \
-   out32((ChP)->IndexAddr,(ChP)->TxControl); \
-} while (0)
-
-/***************************************************************************
-Function: sSetTxXOFFChar
-Purpose:  Set the Tx XOFF flow control character
-Call:     sSetTxXOFFChar(ChP,Ch)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Ch; The value to set the Tx XOFF character to
-*/
-#define sSetTxXOFFChar(ChP,CH) \
-do { \
-   (ChP)->R[0x07] = (CH); \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x04]); \
-} while (0)
-
-/***************************************************************************
-Function: sSetTxXONChar
-Purpose:  Set the Tx XON flow control character
-Call:     sSetTxXONChar(ChP,Ch)
-          CHANNEL_T *ChP; Ptr to channel structure
-          Byte_t Ch; The value to set the Tx XON character to
-*/
-#define sSetTxXONChar(ChP,CH) \
-do { \
-   (ChP)->R[0x0b] = (CH); \
-   out32((ChP)->IndexAddr,&(ChP)->R[0x08]); \
-} while (0)
-
-/***************************************************************************
-Function: sStartRxProcessor
-Purpose:  Start a channel's receive processor
-Call:     sStartRxProcessor(ChP)
-          CHANNEL_T *ChP; Ptr to channel structure
-Comments: This function is used to start a Rx processor after it was
-          stopped with sStopRxProcessor() or sStopSWInFlowCtl().  It
-          will restart both the Rx processor and software input flow control.
-
-*/
-#define sStartRxProcessor(ChP) out32((ChP)->IndexAddr,&(ChP)->R[0])
-
-/***************************************************************************
-Function: sWriteTxByte
-Purpose:  Write a transmit data byte to a channel.
-          ByteIO_t io: Channel transmit register I/O address.  This can
-                           be obtained with sGetTxRxDataIO().
-          Byte_t Data; The transmit data byte.
-Warnings: This function writes the data byte without checking to see if
-          sMaxTxSize is exceeded in the Tx FIFO.
-*/
-#define sWriteTxByte(IO,DATA) sOutB(IO,DATA)
-
-/*
- * Begin Linux specific definitions for the Rocketport driver
- *
- * This code is Copyright Theodore Ts'o, 1995-1997
- */
-
-struct r_port {
-	int magic;
-	struct tty_port port;
-	int line;
-	int flags;		/* Don't yet match the ASY_ flags!! */
-	unsigned int board:3;
-	unsigned int aiop:2;
-	unsigned int chan:3;
-	CONTROLLER_t *ctlp;
-	CHANNEL_t channel;
-	int intmask;
-	int xmit_fifo_room;	/* room in xmit fifo */
-	unsigned char *xmit_buf;
-	int xmit_head;
-	int xmit_tail;
-	int xmit_cnt;
-	int cd_status;
-	int ignore_status_mask;
-	int read_status_mask;
-	int cps;
-
-	struct completion close_wait;	/* Not yet matching the core */
-	spinlock_t slock;
-	struct mutex write_mtx;
-};
-
-#define RPORT_MAGIC 0x525001
-
-#define NUM_BOARDS 8
-#define MAX_RP_PORTS (32*NUM_BOARDS)
-
-/*
- * The size of the xmit buffer is 1 page, or 4096 bytes
- */
-#define XMIT_BUF_SIZE 4096
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-/*
- * Assigned major numbers for the Comtrol Rocketport
- */
-#define TTY_ROCKET_MAJOR	46
-#define CUA_ROCKET_MAJOR	47
-
-#ifdef PCI_VENDOR_ID_RP
-#undef PCI_VENDOR_ID_RP
-#undef PCI_DEVICE_ID_RP8OCTA
-#undef PCI_DEVICE_ID_RP8INTF
-#undef PCI_DEVICE_ID_RP16INTF
-#undef PCI_DEVICE_ID_RP32INTF
-#undef PCI_DEVICE_ID_URP8OCTA
-#undef PCI_DEVICE_ID_URP8INTF
-#undef PCI_DEVICE_ID_URP16INTF
-#undef PCI_DEVICE_ID_CRP16INTF
-#undef PCI_DEVICE_ID_URP32INTF
-#endif
-
-/*  Comtrol PCI Vendor ID */
-#define PCI_VENDOR_ID_RP		0x11fe
-
-/*  Comtrol Device ID's */
-#define PCI_DEVICE_ID_RP32INTF		0x0001	/* Rocketport 32 port w/external I/F     */
-#define PCI_DEVICE_ID_RP8INTF		0x0002	/* Rocketport 8 port w/external I/F      */
-#define PCI_DEVICE_ID_RP16INTF		0x0003	/* Rocketport 16 port w/external I/F     */
-#define PCI_DEVICE_ID_RP4QUAD		0x0004	/* Rocketport 4 port w/quad cable        */
-#define PCI_DEVICE_ID_RP8OCTA		0x0005	/* Rocketport 8 port w/octa cable        */
-#define PCI_DEVICE_ID_RP8J		0x0006	/* Rocketport 8 port w/RJ11 connectors   */
-#define PCI_DEVICE_ID_RP4J		0x0007	/* Rocketport 4 port w/RJ11 connectors   */
-#define PCI_DEVICE_ID_RP8SNI		0x0008	/* Rocketport 8 port w/ DB78 SNI (Siemens) connector */
-#define PCI_DEVICE_ID_RP16SNI		0x0009	/* Rocketport 16 port w/ DB78 SNI (Siemens) connector   */
-#define PCI_DEVICE_ID_RPP4		0x000A	/* Rocketport Plus 4 port                */
-#define PCI_DEVICE_ID_RPP8		0x000B	/* Rocketport Plus 8 port                */
-#define PCI_DEVICE_ID_RP6M		0x000C	/* RocketModem 6 port                    */
-#define PCI_DEVICE_ID_RP4M		0x000D	/* RocketModem 4 port                    */
-#define PCI_DEVICE_ID_RP2_232           0x000E	/* Rocketport Plus 2 port RS232          */
-#define PCI_DEVICE_ID_RP2_422           0x000F	/* Rocketport Plus 2 port RS422          */ 
-
-/* Universal PCI boards  */
-#define PCI_DEVICE_ID_URP32INTF		0x0801	/* Rocketport UPCI 32 port w/external I/F */ 
-#define PCI_DEVICE_ID_URP8INTF		0x0802	/* Rocketport UPCI 8 port w/external I/F  */
-#define PCI_DEVICE_ID_URP16INTF		0x0803	/* Rocketport UPCI 16 port w/external I/F */
-#define PCI_DEVICE_ID_URP8OCTA		0x0805	/* Rocketport UPCI 8 port w/octa cable    */
-#define PCI_DEVICE_ID_UPCI_RM3_8PORT    0x080C	/* Rocketmodem III 8 port                 */
-#define PCI_DEVICE_ID_UPCI_RM3_4PORT    0x080D	/* Rocketmodem III 4 port                 */
-
-/* Compact PCI device */ 
-#define PCI_DEVICE_ID_CRP16INTF		0x0903	/* Rocketport Compact PCI 16 port w/external I/F */
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ser_a2232.c linux-libre-2.6.39-gnu/drivers/char/ser_a2232.c
--- linux-libre-2.6.38-gnu/drivers/char/ser_a2232.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ser_a2232.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,831 +0,0 @@
-/* drivers/char/ser_a2232.c */
-
-/* $Id: ser_a2232.c,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/* Linux serial driver for the Amiga A2232 board */
-
-/* This driver is MAINTAINED. Before applying any changes, please contact
- * the author.
- */
-
-/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
- *                   alias The A2232 driver project <A2232@gmx.net>
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- */
-/***************************** Documentation ************************/
-/*
- * This driver is in EXPERIMENTAL state. That means I could not find
- * someone with five A2232 boards with 35 ports running at 19200 bps
- * at the same time and test the machine's behaviour.
- * However, I know that you can performance-tweak this driver (see
- * the source code).
- * One thing to consider is the time this driver consumes during the
- * Amiga's vertical blank interrupt. Everything that is to be done
- * _IS DONE_ when entering the vertical blank interrupt handler of
- * this driver.
- * However, it would be more sane to only do the job for only ONE card
- * instead of ALL cards at a time; or, more generally, to handle only
- * SOME ports instead of ALL ports at a time.
- * However, as long as no-one runs into problems I guess I shouldn't
- * change the driver as it runs fine for me :) .
- *
- * Version history of this file:
- * 0.4	Resolved licensing issues.
- * 0.3	Inclusion in the Linux/m68k tree, small fixes.
- * 0.2	Added documentation, minor typo fixes.
- * 0.1	Initial release.
- *
- * TO DO:
- * -	Handle incoming BREAK events. I guess "Stevens: Advanced
- *	Programming in the UNIX(R) Environment" is a good reference
- *	on what is to be done.
- * -	When installing as a module, don't simply 'printk' text, but
- *	send it to the TTY used by the user.
- *
- * THANKS TO:
- * -	Jukka Marin (65EC02 code).
- * -	The other NetBSD developers on whose A2232 driver I had a
- *	pretty close look. However, I didn't copy any code so it
- *	is okay to put my code under the GPL and include it into
- *	Linux.
- */
-/***************************** End of Documentation *****************/
-
-/***************************** Defines ******************************/
-/*
- * Enables experimental 115200 (normal) 230400 (turbo) baud rate.
- * The A2232 specification states it can only operate at speeds up to
- * 19200 bits per second, and I was not able to send a file via
- * "sz"/"rz" and a null-modem cable from one A2232 port to another
- * at 115200 bits per second.
- * However, this might work for you.
- */
-#undef A2232_SPEEDHACK
-/*
- * Default is not to use RTS/CTS so you could be talked to death.
- */
-#define A2232_SUPPRESS_RTSCTS_WARNING
-/************************* End of Defines ***************************/
-
-/***************************** Includes *****************************/
-#include <linux/module.h>
-
-#include <linux/types.h>
-#include <linux/interrupt.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/sched.h>
-#include <linux/tty.h>
-
-#include <asm/setup.h>
-#include <asm/amigaints.h>
-#include <asm/amigahw.h>
-#include <linux/zorro.h>
-#include <asm/irq.h>
-#include <linux/mutex.h>
-
-#include <linux/delay.h>
-
-#include <linux/serial.h>
-#include <linux/generic_serial.h>
-#include <linux/tty_flip.h>
-
-#include "ser_a2232.h"
-#include "ser_a2232fw.h"
-/************************* End of Includes **************************/
-
-/***************************** Prototypes ***************************/
-/* The interrupt service routine */
-static irqreturn_t a2232_vbl_inter(int irq, void *data);
-/* Initialize the port structures */
-static void a2232_init_portstructs(void);
-/* Initialize and register TTY drivers. */
-/* returns 0 IFF successful */
-static int a2232_init_drivers(void); 
-
-/* BEGIN GENERIC_SERIAL PROTOTYPES */
-static void a2232_disable_tx_interrupts(void *ptr);
-static void a2232_enable_tx_interrupts(void *ptr);
-static void a2232_disable_rx_interrupts(void *ptr);
-static void a2232_enable_rx_interrupts(void *ptr);
-static int  a2232_carrier_raised(struct tty_port *port);
-static void a2232_shutdown_port(void *ptr);
-static int  a2232_set_real_termios(void *ptr);
-static int  a2232_chars_in_buffer(void *ptr);
-static void a2232_close(void *ptr);
-static void a2232_hungup(void *ptr);
-/* static void a2232_getserial (void *ptr, struct serial_struct *sp); */
-/* END GENERIC_SERIAL PROTOTYPES */
-
-/* Functions that the TTY driver struct expects */
-static int  a2232_ioctl(struct tty_struct *tty, struct file *file,
-										unsigned int cmd, unsigned long arg);
-static void a2232_throttle(struct tty_struct *tty);
-static void a2232_unthrottle(struct tty_struct *tty);
-static int  a2232_open(struct tty_struct * tty, struct file * filp);
-/************************* End of Prototypes ************************/
-
-/***************************** Global variables *********************/
-/*---------------------------------------------------------------------------
- * Interface from generic_serial.c back here
- *--------------------------------------------------------------------------*/
-static struct real_driver a2232_real_driver = {
-        a2232_disable_tx_interrupts,
-        a2232_enable_tx_interrupts,
-        a2232_disable_rx_interrupts,
-        a2232_enable_rx_interrupts,
-        a2232_shutdown_port,
-        a2232_set_real_termios,
-        a2232_chars_in_buffer,
-        a2232_close,
-        a2232_hungup,
-	NULL	/* a2232_getserial */
-};
-
-static void *a2232_driver_ID = &a2232_driver_ID; // Some memory address WE own.
-
-/* Ports structs */
-static struct a2232_port a2232_ports[MAX_A2232_BOARDS*NUMLINES];
-
-/* TTY driver structs */
-static struct tty_driver *a2232_driver;
-
-/* nr of cards completely (all ports) and correctly configured */
-static int nr_a2232; 
-
-/* zorro_dev structs for the A2232's */
-static struct zorro_dev *zd_a2232[MAX_A2232_BOARDS]; 
-/***************************** End of Global variables **************/
-
-/* Helper functions */
-
-static inline volatile struct a2232memory *a2232mem(unsigned int board)
-{
-	return (volatile struct a2232memory *)ZTWO_VADDR(zd_a2232[board]->resource.start);
-}
-
-static inline volatile struct a2232status *a2232stat(unsigned int board,
-						     unsigned int portonboard)
-{
-	volatile struct a2232memory *mem = a2232mem(board);
-	return &(mem->Status[portonboard]);
-}
-
-static inline void a2232_receive_char(struct a2232_port *port, int ch, int err)
-{
-/* 	Mostly stolen from other drivers.
-	Maybe one could implement a more efficient version by not only
-	transferring one character at a time.
-*/
-	struct tty_struct *tty = port->gs.port.tty;
-
-#if 0
-	switch(err) {
-	case TTY_BREAK:
-		break;
-	case TTY_PARITY:
-		break;
-	case TTY_OVERRUN:
-		break;
-	case TTY_FRAME:
-		break;
-	}
-#endif
-
-	tty_insert_flip_char(tty, ch, err);
-	tty_flip_buffer_push(tty);
-}
-
-/***************************** Functions ****************************/
-/*** BEGIN OF REAL_DRIVER FUNCTIONS ***/
-
-static void a2232_disable_tx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-  
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	stat->OutDisable = -1;
-
-	/* Does this here really have to be? */
-	local_irq_save(flags);
-	port->gs.port.flags &= ~GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-static void a2232_enable_tx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	stat->OutDisable = 0;
-
-	/* Does this here really have to be? */
-	local_irq_save(flags);
-	port->gs.port.flags |= GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-static void a2232_disable_rx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	port = ptr;
-	port->disable_rx = -1;
-}
-
-static void a2232_enable_rx_interrupts(void *ptr)
-{
-	struct a2232_port *port;
-	port = ptr;
-	port->disable_rx = 0;
-}
-
-static int  a2232_carrier_raised(struct tty_port *port)
-{
-	struct a2232_port *ap = container_of(port, struct a2232_port, gs.port);
-	return ap->cd_status;
-}
-
-static void a2232_shutdown_port(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *stat;
-	unsigned long flags;
-
-	port = ptr;
-	stat = a2232stat(port->which_a2232, port->which_port_on_a2232);
-
-	local_irq_save(flags);
-
-	port->gs.port.flags &= ~GS_ACTIVE;
-	
-	if (port->gs.port.tty && port->gs.port.tty->termios->c_cflag & HUPCL) {
-		/* Set DTR and RTS to Low, flush output.
-		   The NetBSD driver "msc.c" does it this way. */
-		stat->Command = (	(stat->Command & ~A2232CMD_CMask) | 
-					A2232CMD_Close );
-		stat->OutFlush = -1;
-		stat->Setup = -1;
-	}
-
-	local_irq_restore(flags);
-	
-	/* After analyzing control flow, I think a2232_shutdown_port
-		is actually the last call from the system when at application
-		level someone issues a "echo Hello >>/dev/ttyY0".
-		Therefore I think the MOD_DEC_USE_COUNT should be here and
-		not in "a2232_close()". See the comment in "sx.c", too.
-		If you run into problems, compile this driver into the
-		kernel instead of compiling it as a module. */
-}
-
-static int  a2232_set_real_termios(void *ptr)
-{
-	unsigned int cflag, baud, chsize, stopb, parity, softflow;
-	int rate;
-	int a2232_param, a2232_cmd;
-	unsigned long flags;
-	unsigned int i;
-	struct a2232_port *port = ptr;
-	volatile struct a2232status *status;
-	volatile struct a2232memory *mem;
-
-	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
-
-	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
-	mem = a2232mem(port->which_a2232);
-	
-	a2232_param = a2232_cmd = 0;
-
-	// get baud rate
-	baud = port->gs.baud;
-	if (baud == 0) {
-		/* speed == 0 -> drop DTR, do nothing else */
-		local_irq_save(flags);
-		// Clear DTR (and RTS... mhhh).
-		status->Command = (	(status->Command & ~A2232CMD_CMask) |
-					A2232CMD_Close );
-		status->OutFlush = -1;
-		status->Setup = -1;
-		
-		local_irq_restore(flags);
-		return 0;
-	}
-	
-	rate = A2232_BAUD_TABLE_NOAVAIL;
-	for (i=0; i < A2232_BAUD_TABLE_NUM_RATES * 3; i += 3){
-		if (a2232_baud_table[i] == baud){
-			if (mem->Common.Crystal == A2232_TURBO) rate = a2232_baud_table[i+2];
-			else                                    rate = a2232_baud_table[i+1];
-		}
-	}
-	if (rate == A2232_BAUD_TABLE_NOAVAIL){
-		printk("a2232: Board %d Port %d unsupported baud rate: %d baud. Using another.\n",port->which_a2232,port->which_port_on_a2232,baud);
-		// This is useful for both (turbo or normal) Crystal versions.
-		rate = A2232PARAM_B9600;
-	}
-	a2232_param |= rate;
-
-	cflag  = port->gs.port.tty->termios->c_cflag;
-
-	// get character size
-	chsize = cflag & CSIZE;
-	switch (chsize){
-		case CS8: 	a2232_param |= A2232PARAM_8Bit; break;
-		case CS7: 	a2232_param |= A2232PARAM_7Bit; break;
-		case CS6: 	a2232_param |= A2232PARAM_6Bit; break;
-		case CS5: 	a2232_param |= A2232PARAM_5Bit; break;
-		default:	printk("a2232: Board %d Port %d unsupported character size: %d. Using 8 data bits.\n",
-					port->which_a2232,port->which_port_on_a2232,chsize);
-				a2232_param |= A2232PARAM_8Bit; break;
-	}
-
-	// get number of stop bits
-	stopb  = cflag & CSTOPB;
-	if (stopb){ // two stop bits instead of one
-		printk("a2232: Board %d Port %d 2 stop bits unsupported. Using 1 stop bit.\n",
-			port->which_a2232,port->which_port_on_a2232);
-	}
-
-	// Warn if RTS/CTS not wanted
-	if (!(cflag & CRTSCTS)){
-#ifndef A2232_SUPPRESS_RTSCTS_WARNING
-		printk("a2232: Board %d Port %d cannot switch off firmware-implemented RTS/CTS hardware flow control.\n",
-			port->which_a2232,port->which_port_on_a2232);
-#endif
-	}
-
-	/*	I think this is correct.
-		However, IXOFF means _input_ flow control and I wonder
-		if one should care about IXON _output_ flow control,
-		too. If this makes problems, one should turn the A2232
-		firmware XON/XOFF "SoftFlow" flow control off and use
-		the conventional way of inserting START/STOP characters
-		by hand in throttle()/unthrottle().
-	*/
-	softflow = !!( port->gs.port.tty->termios->c_iflag & IXOFF );
-
-	// get Parity (Enabled/Disabled? If Enabled, Odd or Even?)
-	parity = cflag & (PARENB | PARODD);
-	if (parity & PARENB){
-		if (parity & PARODD){
-			a2232_cmd |= A2232CMD_OddParity;
-		}
-		else{
-			a2232_cmd |= A2232CMD_EvenParity;
-		}
-	}
-	else a2232_cmd |= A2232CMD_NoParity;
-
-
-	/*	Hmm. Maybe an own a2232_port structure
-		member would be cleaner?	*/
-	if (cflag & CLOCAL)
-		port->gs.port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->gs.port.flags |= ASYNC_CHECK_CD;
-
-
-	/* Now we have all parameters and can go to set them: */
-	local_irq_save(flags);
-
-	status->Param = a2232_param | A2232PARAM_RcvBaud;
-	status->Command = a2232_cmd | A2232CMD_Open |  A2232CMD_Enable;
-	status->SoftFlow = softflow;
-	status->OutDisable = 0;
-	status->Setup = -1;
-
-	local_irq_restore(flags);
-	return 0;
-}
-
-static int  a2232_chars_in_buffer(void *ptr)
-{
-	struct a2232_port *port;
-	volatile struct a2232status *status; 
-	unsigned char ret; /* we need modulo-256 arithmetics */
-	port = ptr;
-	status = a2232stat(port->which_a2232, port->which_port_on_a2232);
-#if A2232_IOBUFLEN != 256
-#error "Re-Implement a2232_chars_in_buffer()!"
-#endif
-	ret = (status->OutHead - status->OutTail);
-	return ret;
-}
-
-static void a2232_close(void *ptr)
-{
-	a2232_disable_tx_interrupts(ptr);
-	a2232_disable_rx_interrupts(ptr);
-	/* see the comment in a2232_shutdown_port above. */
-}
-
-static void a2232_hungup(void *ptr)
-{
-	a2232_close(ptr);
-}
-/*** END   OF REAL_DRIVER FUNCTIONS ***/
-
-/*** BEGIN  FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
-static int a2232_ioctl(	struct tty_struct *tty, struct file *file,
-			unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-static void a2232_throttle(struct tty_struct *tty)
-{
-/* Throttle: System cannot take another chars: Drop RTS or
-             send the STOP char or whatever.
-   The A2232 firmware does RTS/CTS anyway, and XON/XOFF
-   if switched on. So the only thing we can do at this
-   layer here is not taking any characters out of the
-   A2232 buffer any more. */
-	struct a2232_port *port = tty->driver_data;
-	port->throttle_input = -1;
-}
-
-static void a2232_unthrottle(struct tty_struct *tty)
-{
-/* Unthrottle: dual to "throttle()" above. */
-	struct a2232_port *port = tty->driver_data;
-	port->throttle_input = 0;
-}
-
-static int  a2232_open(struct tty_struct * tty, struct file * filp)
-{
-/* More or less stolen from other drivers. */
-	int line;
-	int retval;
-	struct a2232_port *port;
-
-	line = tty->index;
-	port = &a2232_ports[line];
-	
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	retval = gs_init_port(&port->gs);
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-	port->gs.port.flags |= GS_ACTIVE;
-	retval = gs_block_til_ready(port, filp);
-
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	a2232_enable_rx_interrupts(port);
-	
-	return 0;
-}
-/*** END OF FUNCTIONS EXPECTED BY TTY DRIVER STRUCTS ***/
-
-static irqreturn_t a2232_vbl_inter(int irq, void *data)
-{
-#if A2232_IOBUFLEN != 256
-#error "Re-Implement a2232_vbl_inter()!"
-#endif
-
-struct a2232_port *port;
-volatile struct a2232memory *mem;
-volatile struct a2232status *status;
-unsigned char newhead;
-unsigned char bufpos; /* Must be unsigned char. We need the modulo-256 arithmetics */
-unsigned char ncd, ocd, ccd; /* names consistent with the NetBSD driver */
-volatile u_char *ibuf, *cbuf, *obuf;
-int ch, err, n, p;
-	for (n = 0; n < nr_a2232; n++){		/* for every completely initialized A2232 board */
-		mem = a2232mem(n);
-		for (p = 0; p < NUMLINES; p++){	/* for every port on this board */
-			err = 0;
-			port = &a2232_ports[n*NUMLINES+p];
-			if ( port->gs.port.flags & GS_ACTIVE ){ /* if the port is used */
-
-				status = a2232stat(n,p);
-
-				if (!port->disable_rx && !port->throttle_input){ /* If input is not disabled */
-					newhead = status->InHead;               /* 65EC02 write pointer */
-					bufpos = status->InTail;
-
-					/* check for input for this port */
-					if (newhead != bufpos) {
-						/* buffer for input chars/events */
-						ibuf = mem->InBuf[p];
- 
-						/* data types of bytes in ibuf */
-						cbuf = mem->InCtl[p];
- 
-						/* do for all chars */
-						while (bufpos != newhead) {
-							/* which type of input data? */
-							switch (cbuf[bufpos]) {
-								/* switch on input event (CD, BREAK, etc.) */
-							case A2232INCTL_EVENT:
-								switch (ibuf[bufpos++]) {
-								case A2232EVENT_Break:
-									/* TODO: Handle BREAK signal */
-									break;
-									/*	A2232EVENT_CarrierOn and A2232EVENT_CarrierOff are
-										handled in a separate queue and should not occur here. */
-								case A2232EVENT_Sync:
-									printk("A2232: 65EC02 software sent SYNC event, don't know what to do. Ignoring.");
-									break;
-								default:
-									printk("A2232: 65EC02 software broken, unknown event type %d occurred.\n",ibuf[bufpos-1]);
-								} /* event type switch */
-								break;
- 							case A2232INCTL_CHAR:
-								/* Receive incoming char */
-								a2232_receive_char(port, ibuf[bufpos], err);
-								bufpos++;
-								break;
- 							default:
-								printk("A2232: 65EC02 software broken, unknown data type %d occurred.\n",cbuf[bufpos]);
-								bufpos++;
-							} /* switch on input data type */
-						} /* while there's something in the buffer */
-
-						status->InTail = bufpos;            /* tell 65EC02 what we've read */
-						
-					} /* if there was something in the buffer */                          
-				} /* If input is not disabled */
-
-				/* Now check if there's something to output */
-				obuf = mem->OutBuf[p];
-				bufpos = status->OutHead;
-				while ( (port->gs.xmit_cnt > 0)		&&
-					(!port->gs.port.tty->stopped)	&&
-					(!port->gs.port.tty->hw_stopped) ){	/* While there are chars to transmit */
-					if (((bufpos+1) & A2232_IOBUFLENMASK) != status->OutTail) { /* If the A2232 buffer is not full */
-						ch = port->gs.xmit_buf[port->gs.xmit_tail];					/* get the next char to transmit */
-						port->gs.xmit_tail = (port->gs.xmit_tail+1) & (SERIAL_XMIT_SIZE-1); /* modulo-addition for the gs.xmit_buf ring-buffer */
-						obuf[bufpos++] = ch;																/* put it into the A2232 buffer */
-						port->gs.xmit_cnt--;
-					}
-					else{																									/* If A2232 the buffer is full */
-						break;																							/* simply stop filling it. */
-					}													
-				}					
-				status->OutHead = bufpos;
-					
-				/* WakeUp if output buffer runs low */
-				if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
-					tty_wakeup(port->gs.port.tty);
-				}
-			} // if the port is used
-		} // for every port on the board
-			
-		/* Now check the CD message queue */
-		newhead = mem->Common.CDHead;
-		bufpos = mem->Common.CDTail;
-		if (newhead != bufpos){				/* There are CD events in queue */
-			ocd = mem->Common.CDStatus; 		/* get old status bits */
-			while (newhead != bufpos){		/* read all events */
-				ncd = mem->CDBuf[bufpos++]; 	/* get one event */
-				ccd = ncd ^ ocd; 		/* mask of changed lines */
-				ocd = ncd; 			/* save new status bits */
-				for(p=0; p < NUMLINES; p++){	/* for all ports */
-					if (ccd & 1){		/* this one changed */
-
-						struct a2232_port *port = &a2232_ports[n*7+p];
-						port->cd_status = !(ncd & 1); /* ncd&1 <=> CD is now off */
-
-						if (!(port->gs.port.flags & ASYNC_CHECK_CD))
-							;	/* Don't report DCD changes */
-						else if (port->cd_status) { // if DCD on: DCD went UP!
-							
-							/* Are we blocking in open?*/
-							wake_up_interruptible(&port->gs.port.open_wait);
-						}
-						else { // if DCD off: DCD went DOWN!
-							if (port->gs.port.tty)
-								tty_hangup (port->gs.port.tty);
-						}
-						
-					} // if CD changed for this port
-					ccd >>= 1;
-					ncd >>= 1;									/* Shift bits for next line */
-				} // for every port
-			} // while CD events in queue
-			mem->Common.CDStatus = ocd; /* save new status */
-			mem->Common.CDTail = bufpos; /* remove events */
-		} // if events in CD queue
-		
-	} // for every completely initialized A2232 board
-	return IRQ_HANDLED;
-}
-
-static const struct tty_port_operations a2232_port_ops = {
-	.carrier_raised = a2232_carrier_raised,
-};
-
-static void a2232_init_portstructs(void)
-{
-	struct a2232_port *port;
-	int i;
-
-	for (i = 0; i < MAX_A2232_BOARDS*NUMLINES; i++) {
-		port = a2232_ports + i;
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &a2232_port_ops;
-		port->which_a2232 = i/NUMLINES;
-		port->which_port_on_a2232 = i%NUMLINES;
-		port->disable_rx = port->throttle_input = port->cd_status = 0;
-		port->gs.magic = A2232_MAGIC;
-		port->gs.close_delay = HZ/2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &a2232_real_driver;
-	}
-}
-
-static const struct tty_operations a2232_ops = {
-	.open = a2232_open,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = a2232_ioctl,
-	.throttle = a2232_throttle,
-	.unthrottle = a2232_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-};
-
-static int a2232_init_drivers(void)
-{
-	int error;
-
-	a2232_driver = alloc_tty_driver(NUMLINES * nr_a2232);
-	if (!a2232_driver)
-		return -ENOMEM;
-	a2232_driver->owner = THIS_MODULE;
-	a2232_driver->driver_name = "commodore_a2232";
-	a2232_driver->name = "ttyY";
-	a2232_driver->major = A2232_NORMAL_MAJOR;
-	a2232_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	a2232_driver->subtype = SERIAL_TYPE_NORMAL;
-	a2232_driver->init_termios = tty_std_termios;
-	a2232_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	a2232_driver->init_termios.c_ispeed = 9600;
-	a2232_driver->init_termios.c_ospeed = 9600;
-	a2232_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(a2232_driver, &a2232_ops);
-	if ((error = tty_register_driver(a2232_driver))) {
-		printk(KERN_ERR "A2232: Couldn't register A2232 driver, error = %d\n",
-		       error);
-		put_tty_driver(a2232_driver);
-		return 1;
-	}
-	return 0;
-}
-
-static int __init a2232board_init(void)
-{
-	struct zorro_dev *z;
-
-	unsigned int boardaddr;
-	int bcount;
-	short start;
-	u_char *from;
-	volatile u_char *to;
-	volatile struct a2232memory *mem;
-	int error, i;
-
-#ifdef CONFIG_SMP
-	return -ENODEV;	/* This driver is not SMP aware. Is there an SMP ZorroII-bus-machine? */
-#endif
-
-	if (!MACH_IS_AMIGA){
-		return -ENODEV;
-	}
-
-	printk("Commodore A2232 driver initializing.\n"); /* Say that we're alive. */
-
-	z = NULL;
-	nr_a2232 = 0;
-	while ( (z = zorro_find_device(ZORRO_WILDCARD, z)) ){
-		if (	(z->id != ZORRO_PROD_CBM_A2232_PROTOTYPE) && 
-			(z->id != ZORRO_PROD_CBM_A2232)	){
-			continue;	// The board found was no A2232
-		}
-		if (!zorro_request_device(z,"A2232 driver"))
-			continue;
-
-		printk("Commodore A2232 found (#%d).\n",nr_a2232);
-
-		zd_a2232[nr_a2232] = z;
-
-		boardaddr = ZTWO_VADDR( z->resource.start );
-		printk("Board is located at address 0x%x, size is 0x%x.\n", boardaddr, (unsigned int) ((z->resource.end+1) - (z->resource.start)));
-
-		mem = (volatile struct a2232memory *) boardaddr;
-
-		(void) mem->Enable6502Reset;   /* copy the code across to the board */
-		to = (u_char *)mem;  from = a2232_65EC02code; bcount = sizeof(a2232_65EC02code) - 2;
-		start = *(short *)from;
-		from += sizeof(start);
-		to += start;
-		while(bcount--) *to++ = *from++;
-		printk("65EC02 software uploaded to the A2232 memory.\n");
-  
-		mem->Common.Crystal = A2232_UNKNOWN;  /* use automatic speed check */
-  
-		/* start 6502 running */
-		(void) mem->ResetBoard;
-		printk("A2232's 65EC02 CPU up and running.\n");
-  
-		/* wait until speed detector has finished */
-		for (bcount = 0; bcount < 2000; bcount++) {
-			udelay(1000);
-			if (mem->Common.Crystal)
-				break;
-		}
-		printk((mem->Common.Crystal?"A2232 oscillator crystal detected by 65EC02 software: ":"65EC02 software could not determine A2232 oscillator crystal: "));
-		switch (mem->Common.Crystal){
-		case A2232_UNKNOWN:
-			printk("Unknown crystal.\n");
-			break;
- 		case A2232_NORMAL:
-			printk ("Normal crystal.\n");
-			break;
-		case A2232_TURBO:
-			printk ("Turbo crystal.\n");
-			break;
-		default:
-			printk ("0x%x. Huh?\n",mem->Common.Crystal);
-		}
-
-		nr_a2232++;
-
-	}	
-
-	printk("Total: %d A2232 boards initialized.\n", nr_a2232); /* Some status report if no card was found */
-
-	a2232_init_portstructs();
-
-	/*
-		a2232_init_drivers also registers the drivers. Must be here because all boards
-		have to be detected first.
-	*/
-	if (a2232_init_drivers()) return -ENODEV; // maybe we should use a different -Exxx?
-
-	error = request_irq(IRQ_AMIGA_VERTB, a2232_vbl_inter, 0,
-			    "A2232 serial VBL", a2232_driver_ID);
-	if (error) {
-		for (i = 0; i < nr_a2232; i++)
-			zorro_release_device(zd_a2232[i]);
-		tty_unregister_driver(a2232_driver);
-		put_tty_driver(a2232_driver);
-	}
-	return error;
-}
-
-static void __exit a2232board_exit(void)
-{
-	int i;
-
-	for (i = 0; i < nr_a2232; i++) {
-		zorro_release_device(zd_a2232[i]);
-	}
-
-	tty_unregister_driver(a2232_driver);
-	put_tty_driver(a2232_driver);
-	free_irq(IRQ_AMIGA_VERTB, a2232_driver_ID);
-}
-
-module_init(a2232board_init);
-module_exit(a2232board_exit);
-
-MODULE_AUTHOR("Enver Haase");
-MODULE_DESCRIPTION("Amiga A2232 multi-serial board driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/char/ser_a2232fw.ax linux-libre-2.6.39-gnu/drivers/char/ser_a2232fw.ax
--- linux-libre-2.6.38-gnu/drivers/char/ser_a2232fw.ax	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ser_a2232fw.ax	1969-12-31 19:00:00.000000000 -0500
@@ -1,529 +0,0 @@
-;.lib "axm"
-;
-;begin
-;title "A2232 serial board driver"
-;
-;set modules "2232"
-;set executable "2232.bin"
-;
-;;;;set nolink
-;
-;set temporary directory "t:"
-;
-;set assembly options "-m6502 -l60:t:list"
-;set link options "bin"; loadadr"
-;;;bin2c 2232.bin msc6502.h msc6502code
-;end
-;
-;
-; ### Commodore A2232 serial board driver for NetBSD by JM v1.3 ###
-;
-; - Created 950501 by JM -
-;
-;
-; Serial board driver software.
-;
-;
-% Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
-% 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, and the entire permission notice in its entirety,
-%    including the disclaimer of warranties.
-% 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. The name of the author may not be used to endorse or promote
-%    products derived from this software without specific prior
-%    written permission.
-%
-% ALTERNATIVELY, this product may be distributed under the terms of
-% the GNU General Public License, in which case the provisions of the
-% GPL are required INSTEAD OF the above restrictions.  (This clause is
-% necessary due to a potential bad interaction between the GPL and
-% the restrictions contained in a BSD-style copyright.)
-%
-% 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.
-;
-;
-; Bugs:
-;
-; - Can't send a break yet
-;
-;
-;
-; Edited:
-;
-; - 950501 by JM -> v0.1	- Created this file.
-; - 951029 by JM -> v1.3	- Carrier Detect events now queued in a separate
-;				  queue.
-;
-;
-
-
-CODE		equ	$3800		; start address for program code
-
-
-CTL_CHAR	equ	$00		; byte in ibuf is a character
-CTL_EVENT	equ	$01		; byte in ibuf is an event
-
-EVENT_BREAK	equ	$01
-EVENT_CDON	equ	$02
-EVENT_CDOFF	equ	$03
-EVENT_SYNC	equ	$04
-
-XON		equ	$11
-XOFF		equ	$13
-
-
-VARBASE		macro	*starting_address	; was VARINIT
-_varbase	set	\1
-		endm
-
-VARDEF		macro	*name space_needs
-\1		equ	_varbase
-_varbase	set	_varbase+\2
-		endm
-
-
-stz		macro	* address
-		 db	$64,\1
-		endm
-
-stzax		macro	* address
-		 db	$9e,<\1,>\1
-		endm
-
-
-biti		macro	* immediate value
-		db	$89,\1
-		endm
-
-smb0		macro	* address
-		db	$87,\1
-		endm
-smb1		macro	* address
-		db	$97,\1
-		endm
-smb2		macro	* address
-		db	$a7,\1
-		endm
-smb3		macro	* address
-		db	$b7,\1
-		endm
-smb4		macro	* address
-		db	$c7,\1
-		endm
-smb5		macro	* address
-		db	$d7,\1
-		endm
-smb6		macro	* address
-		db	$e7,\1
-		endm
-smb7		macro	* address
-		db	$f7,\1
-		endm
-
-
-
-;-----------------------------------------------------------------------;
-;									;
-; stuff common for all ports, non-critical (run once / loop)		;
-;									;
-DO_SLOW		macro	* port_number					;
-		.local			;				;
-		lda	CIA+C_PA	; check all CD inputs		;
-		cmp	CommonCDo	; changed from previous accptd?	;
-		beq	=over		; nope, do nothing else here	;
-					;				;
-		cmp	CommonCDb	; bouncing?			;
-		beq	=nobounce	; nope ->			;
-					;				;
-		sta	CommonCDb	; save current state		;
-		lda	#64		; reinitialize counter		;
-		sta	CommonCDc	;				;
-		jmp	=over		; skip CD save			;
-					;				;
-=nobounce	dec	CommonCDc	; no, decrement bounce counter	;
-		bpl	=over		; not done yet, so skip CD save	;
-					;				;
-=saveCD		ldx	CDHead		; get write index		;
-		sta	cdbuf,x		; save status in buffer		;
-		inx			;				;
-		cpx	CDTail		; buffer full?			;
-		.if	ne		; no: preserve status:		;
-		 stx	CDHead		; update index in RAM		;
-		 sta	CommonCDo	; save state for the next check	;
-		.end			;				;
-=over		.end	local						;
-		endm							;
-									;
-;-----------------------------------------------------------------------;
-
-
-; port specific stuff (no data transfer)
-
-DO_PORT		macro	* port_number
-		.local			;				;
-		lda	SetUp\1		; reconfiguration request?	;
-		.if	ne		; yes:				;
-		 lda	SoftFlow\1	; get XON/XOFF flag		;
-		 sta	XonOff\1	; save it			;
-		 lda	Param\1		; get parameter			;
-		 ora	#%00010000	; use baud generator for Rx	;
-		 sta	ACIA\1+A_CTRL	; store in control register	;
-		 stz	OutDisable\1	; enable transmit output	;
-		 stz	SetUp\1		; no reconfiguration no more	;
-		.end			;				;
-					;				;
-		lda	InHead\1	; get write index		;
-		sbc	InTail\1	; buffer full soon?		;
-		cmp	#200		; 200 chars or more in buffer?	;
-		lda	Command\1	; get Command reg value		;
-		and	#%11110011	; turn RTS OFF by default	;
-		.if	cc		; still room in buffer:		;
-		 ora	#%00001000	; turn RTS ON			;
-		.end			;				;
-		sta	ACIA\1+A_CMD	; set/clear RTS			;
-					;				;
-		lda	OutFlush\1	; request to flush output buffer;
-		.if	ne		; yessh!			;
-		 lda	OutHead\1	; get head			;
-		 sta	OutTail\1	; save as tail			;
-		 stz	OutDisable\1	; enable transmit output	;
-		 stz	OutFlush\1	; clear request			;
-		.end
-		.end	local
-		endm
-
-
-DO_DATA		macro	* port number
-		.local
-		lda	ACIA\1+A_SR	; read ACIA status register	;
-		biti	[1<<3]		; something received?		;
-		.if	ne		; yes:				;
-		 biti	[1<<1]		; framing error?		;
-		 .if	ne		; yes:				;
-		  lda	ACIA\1+A_DATA	; read received character	;
-		  bne	=SEND		; not break -> ignore it	;
-		  ldx	InHead\1	; get write pointer		;
-		  lda	#CTL_EVENT	; get type of byte		;
-		  sta	ictl\1,x	; save it in InCtl buffer	;
-		  lda	#EVENT_BREAK	; event code			;
-		  sta	ibuf\1,x	; save it as well		;
-		  inx			;				;
-		  cpx	InTail\1	; still room in buffer?		;
-		  .if	ne		; absolutely:			;
-		   stx	InHead\1	; update index in memory	;
-		  .end			;				;
-		  jmp	=SEND		; go check if anything to send	;
-		 .end			;				;
-		 			; normal char received:		;
-		 ldx	InHead\1	; get write index		;
-		 lda	ACIA\1+A_DATA	; read received character	;
-		 sta	ibuf\1,x	; save char in buffer		;
-		 stzax	ictl\1		; set type to CTL_CHAR		;
-		 inx			;				;
-		 cpx	InTail\1	; buffer full?			;
-		 .if	ne		; no: preserve character:	;
-		  stx	InHead\1	; update index in RAM		;
-		 .end			;				;
-		 and	#$7f		; mask off parity if any	;
-		 cmp	#XOFF		; XOFF from remote host?	;
-		 .if	eq		; yes:				;
-		  lda	XonOff\1	; if XON/XOFF handshaking..	;
-		  sta	OutDisable\1	; ..disable transmitter		;
-		 .end			;				;
-		.end			;				;
-					;				;
-					; BUFFER FULL CHECK WAS HERE	;
-					;				;
-=SEND		lda	ACIA\1+A_SR	; transmit register empty?	;
-		and	#[1<<4]		;				;
-		.if	ne		; yes:				;
-		 ldx	OutCtrl\1	; sending out XON/XOFF?		;
-		 .if	ne		; yes:				;
-		  lda	CIA+C_PB	; check CTS signal		;
-		  and	#[1<<\1]	; (for this port only)		;
-		  bne	=DONE		; not allowed to send -> done	;
-		  stx	ACIA\1+A_DATA	; transmit control char		;
-		  stz	OutCtrl\1	; clear flag			;
-		  jmp	=DONE		; and we're done		;
-		 .end			;				;
-					;				;
-		 ldx	OutTail\1	; anything to transmit?		;
-		 cpx	OutHead\1	;				;
-		 .if	ne		; yes:				;
-		  lda	OutDisable\1	; allowed to transmit?		;
-		  .if	eq		; yes:				;
-		   lda	CIA+C_PB	; check CTS signal		;
-		   and	#[1<<\1]	; (for this port only)		;
-		   bne	=DONE		; not allowed to send -> done	;
-		   lda	obuf\1,x	; get a char from buffer	;
-		   sta	ACIA\1+A_DATA	; send it away			;
-		   inc	OutTail\1	; update read index		;
-		  .end			;				;
-		 .end			;				;
-		.end			;				;
-=DONE		.end	local
-		endm
-
-
-
-PORTVAR		macro	* port number
-		VARDEF	InHead\1 1
-		VARDEF	InTail\1 1
-		VARDEF	OutDisable\1 1
-		VARDEF	OutHead\1 1
-		VARDEF	OutTail\1 1
-		VARDEF	OutCtrl\1 1
-		VARDEF	OutFlush\1 1
-		VARDEF	SetUp\1 1
-		VARDEF	Param\1 1
-		VARDEF	Command\1 1
-		VARDEF	SoftFlow\1 1
-		; private:
-		VARDEF	XonOff\1 1
-		endm
-
-
- VARBASE 0	; start variables at address $0000
- PORTVAR 0	; define variables for port 0
- PORTVAR 1	; define variables for port 1
- PORTVAR 2	; define variables for port 2
- PORTVAR 3	; define variables for port 3
- PORTVAR 4	; define variables for port 4
- PORTVAR 5	; define variables for port 5
- PORTVAR 6	; define variables for port 6
-
-
-
- VARDEF	Crystal	1	; 0 = unknown, 1 = normal, 2 = turbo
- VARDEF	Pad_a	1
- VARDEF	TimerH	1
- VARDEF	TimerL	1
- VARDEF	CDHead	1
- VARDEF	CDTail	1
- VARDEF	CDStatus 1
- VARDEF	Pad_b	1
-
- VARDEF	CommonCDo 1	; for carrier detect optimization
- VARDEF	CommonCDc 1	; for carrier detect debouncing
- VARDEF	CommonCDb 1	; for carrier detect debouncing
-
-
- VARBASE $0200
- VARDEF	obuf0 256	; output data (characters only)
- VARDEF	obuf1 256
- VARDEF	obuf2 256
- VARDEF	obuf3 256
- VARDEF	obuf4 256
- VARDEF	obuf5 256
- VARDEF	obuf6 256
-
- VARDEF	ibuf0 256	; input data (characters, events etc - see ictl)
- VARDEF	ibuf1 256
- VARDEF	ibuf2 256
- VARDEF	ibuf3 256
- VARDEF	ibuf4 256
- VARDEF	ibuf5 256
- VARDEF	ibuf6 256
-
- VARDEF	ictl0 256	; input control information (type of data in ibuf)
- VARDEF	ictl1 256
- VARDEF	ictl2 256
- VARDEF	ictl3 256
- VARDEF	ictl4 256
- VARDEF	ictl5 256
- VARDEF	ictl6 256
-
- VARDEF	cdbuf 256	; CD event queue
-
-
-ACIA0		equ	$4400
-ACIA1		equ	$4c00
-ACIA2		equ	$5400
-ACIA3		equ	$5c00
-ACIA4		equ	$6400
-ACIA5		equ	$6c00
-ACIA6		equ	$7400
-
-A_DATA		equ	$00
-A_SR		equ	$02
-A_CMD		equ	$04
-A_CTRL		equ	$06
-;  00	write transmit data	read received data
-;  02	reset ACIA		read status register
-;  04	write command register	read command register
-;  06	write control register	read control register
-
-CIA		equ	$7c00		; 8520 CIA
-C_PA		equ	$00		; port A data register
-C_PB		equ	$02		; port B data register
-C_DDRA		equ	$04		; data direction register for port A
-C_DDRB		equ	$06		; data direction register for port B
-C_TAL		equ	$08		; timer A
-C_TAH		equ	$0a
-C_TBL		equ	$0c		; timer B
-C_TBH		equ	$0e
-C_TODL		equ	$10		; TOD LSB
-C_TODM		equ	$12		; TOD middle byte
-C_TODH		equ	$14		; TOD MSB
-C_DATA		equ	$18		; serial data register
-C_INTCTRL	equ	$1a		; interrupt control register
-C_CTRLA		equ	$1c		; control register A
-C_CTRLB		equ	$1e		; control register B
-
-
-
-
-
-		section	main,code,CODE-2
-
-		db	>CODE,<CODE
-
-;-----------------------------------------------------------------------;
-; here's the initialization code:					;
-;									;
-R_RESET		ldx	#$ff						;
-		txs			; initialize stack pointer	;
-		cld			; in case a 6502 is used...	;
-		ldx	#0		;				;
-		lda	#0		;				;
-		ldy	#Crystal	; this many bytes to clear	;
-clr_loop	sta	0,x		; clear zero page variables	;
-		inx			;				;
-		dey			;				;
-		bne	clr_loop	;				;
-					;				;
-		stz	CommonCDo	; force CD test at boot		;
-		stz	CommonCDb	;				;
-		stz	CDHead		; clear queue			;
-		stz	CDTail		;				;
-					;				;
-		lda	#0		;				;
-		sta	Pad_a		;				;
-		lda	#170		; test cmp			;
-		cmp	#100		;				;
-		.if	cs		;				;
-		 inc	Pad_a		; C was set			;
-		.end			;				;
-									;
-;-----------------------------------------------------------------------;
-; Speed check								;
-;-----------------------------------------------------------------------;
-									;
-		lda	Crystal		; speed already set?		;
-		beq	DoSpeedy	;				;
-		jmp	LOOP		; yes, skip speed test		;
-					;				;
-DoSpeedy	lda	#%10011000	; 8N1, 1200/2400 bps		;
-		sta	ACIA0+A_CTRL	;				;
-		lda	#%00001011	; enable DTR			;
-		sta	ACIA0+A_CMD	;				;
-		lda	ACIA0+A_SR	; read status register		;
-					;				;
-		lda	#%10000000	; disable all ints (unnecessary);
-		sta	CIA+C_INTCTRL	;				;
-		lda	#255		; program the timer		;
-		sta	CIA+C_TAL	;				;
-		sta	CIA+C_TAH	;				;
-					;				;
-		ldx	#0		;				;
-		stx	ACIA0+A_DATA	; transmit a zero		;
-		nop			;				;
-		nop			;				;
-		lda	ACIA0+A_SR	; read status			;
-		nop			;				;
-		nop			;				;
-		stx	ACIA0+A_DATA	; transmit a zero		;
-Speedy1		lda	ACIA0+A_SR	; read status			;
-		and	#[1<<4]		; transmit data reg empty?	;
-		beq	Speedy1		; not yet, wait more		;
-					;				;
-		lda	#%00010001	; load & start the timer	;
-		stx	ACIA0+A_DATA	; transmit one more zero	;
-		sta	CIA+C_CTRLA	;				;
-Speedy2		lda	ACIA0+A_SR	; read status			;
-		and	#[1<<4]		; transmit data reg empty?	;
-		beq	Speedy2		; not yet, wait more		;
-		stx	CIA+C_CTRLA	; stop the timer		;
-					;				;
-		lda	CIA+C_TAL	; copy timer value for 68k	;
-		sta	TimerL		;				;
-		lda	CIA+C_TAH	;				;
-		sta	TimerH		;				;
-		cmp	#$d0		; turbo or normal?		;
-		.if	cs		;				;
-		 lda	#2		; turbo! :-)			;
-		.else			;				;
-		 lda	#1		; normal :-(			;
-		.end			;				;
-		sta	Crystal		;				;
-		lda	#0		;				;
-		sta	ACIA0+A_SR	;				;
-		sta	ACIA0+A_CTRL	; reset UART			;
-		sta	ACIA0+A_CMD	;				;
-									;
-		jmp	LOOP						;
-									;
-;									;
-;-----------------------------------------------------------------------;
-;									;
-; The Real Thing:							;
-;									;
-LOOP		DO_SLOW			; do non-critical things	;
-		jsr	do_input	; check for received data
-		DO_PORT	0
-		jsr	do_input
-		DO_PORT	1
-		jsr	do_input
-		DO_PORT	2
-		jsr	do_input
-		DO_PORT	3
-		jsr	do_input
-		DO_PORT	4
-		jsr	do_input
-		DO_PORT	5
-		jsr	do_input
-		DO_PORT	6
-		jsr	do_input
-		jmp	LOOP
-
-
-do_input	DO_DATA	0
-		DO_DATA	1
-		DO_DATA	2
-		DO_DATA	3
-		DO_DATA	4
-		DO_DATA	5
-		DO_DATA	6
-		rts
-
-
-;-----------------------------------------------------------------------;
-		section	vectors,data,$3ffa
-		dw	$d0d0
-		dw	R_RESET
-		dw	$c0ce
-;-----------------------------------------------------------------------;
-
-
-
-		end
-
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/ser_a2232fw.h linux-libre-2.6.39-gnu/drivers/char/ser_a2232fw.h
--- linux-libre-2.6.38-gnu/drivers/char/ser_a2232fw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ser_a2232fw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,306 +0,0 @@
-/* drivers/char/ser_a2232fw.h */
-
-/* $Id: ser_a2232fw.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/*
- * Copyright (c) 1995 Jukka Marin <jmarin@jmp.fi>.
- * 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, and the entire permission notice in its entirety,
- *    including the disclaimer of warranties.
- * 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. The name of the author may not be used to endorse or promote
- *    products derived from this software without specific prior
- *    written permission.
- *
- * ALTERNATIVELY, this product may be distributed under the terms of
- * the GNU Public License, in which case the provisions of the GPL are
- * required INSTEAD OF the above restrictions.  (This clause is
- * necessary due to a potential bad interaction between the GPL and
- * the restrictions contained in a BSD-style copyright.)
- *
- * 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.
- *
- */
-                                      
-/* This is the 65EC02 code by Jukka Marin that is executed by
-   the A2232's 65EC02 processor (base address: 0x3800)
-   Source file:	ser_a2232fw.ax
-   Version:	1.3 (951029)
-   Known Bugs:	Cannot send a break yet
-*/
-static unsigned char a2232_65EC02code[] = {
-	0x38, 0x00, 0xA2, 0xFF, 0x9A, 0xD8, 0xA2, 0x00, 
-	0xA9, 0x00, 0xA0, 0x54, 0x95, 0x00, 0xE8, 0x88, 
-	0xD0, 0xFA, 0x64, 0x5C, 0x64, 0x5E, 0x64, 0x58, 
-	0x64, 0x59, 0xA9, 0x00, 0x85, 0x55, 0xA9, 0xAA, 
-	0xC9, 0x64, 0x90, 0x02, 0xE6, 0x55, 0xA5, 0x54, 
-	0xF0, 0x03, 0x4C, 0x92, 0x38, 0xA9, 0x98, 0x8D, 
-	0x06, 0x44, 0xA9, 0x0B, 0x8D, 0x04, 0x44, 0xAD, 
-	0x02, 0x44, 0xA9, 0x80, 0x8D, 0x1A, 0x7C, 0xA9, 
-	0xFF, 0x8D, 0x08, 0x7C, 0x8D, 0x0A, 0x7C, 0xA2, 
-	0x00, 0x8E, 0x00, 0x44, 0xEA, 0xEA, 0xAD, 0x02, 
-	0x44, 0xEA, 0xEA, 0x8E, 0x00, 0x44, 0xAD, 0x02, 
-	0x44, 0x29, 0x10, 0xF0, 0xF9, 0xA9, 0x11, 0x8E, 
-	0x00, 0x44, 0x8D, 0x1C, 0x7C, 0xAD, 0x02, 0x44, 
-	0x29, 0x10, 0xF0, 0xF9, 0x8E, 0x1C, 0x7C, 0xAD, 
-	0x08, 0x7C, 0x85, 0x57, 0xAD, 0x0A, 0x7C, 0x85, 
-	0x56, 0xC9, 0xD0, 0x90, 0x05, 0xA9, 0x02, 0x4C, 
-	0x82, 0x38, 0xA9, 0x01, 0x85, 0x54, 0xA9, 0x00, 
-	0x8D, 0x02, 0x44, 0x8D, 0x06, 0x44, 0x8D, 0x04, 
-	0x44, 0x4C, 0x92, 0x38, 0xAD, 0x00, 0x7C, 0xC5, 
-	0x5C, 0xF0, 0x1F, 0xC5, 0x5E, 0xF0, 0x09, 0x85, 
-	0x5E, 0xA9, 0x40, 0x85, 0x5D, 0x4C, 0xB8, 0x38, 
-	0xC6, 0x5D, 0x10, 0x0E, 0xA6, 0x58, 0x9D, 0x00, 
-	0x17, 0xE8, 0xE4, 0x59, 0xF0, 0x04, 0x86, 0x58, 
-	0x85, 0x5C, 0x20, 0x23, 0x3A, 0xA5, 0x07, 0xF0, 
-	0x0F, 0xA5, 0x0A, 0x85, 0x0B, 0xA5, 0x08, 0x09, 
-	0x10, 0x8D, 0x06, 0x44, 0x64, 0x02, 0x64, 0x07, 
-	0xA5, 0x00, 0xE5, 0x01, 0xC9, 0xC8, 0xA5, 0x09, 
-	0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 
-	0x44, 0xA5, 0x06, 0xF0, 0x08, 0xA5, 0x03, 0x85, 
-	0x04, 0x64, 0x02, 0x64, 0x06, 0x20, 0x23, 0x3A, 
-	0xA5, 0x13, 0xF0, 0x0F, 0xA5, 0x16, 0x85, 0x17, 
-	0xA5, 0x14, 0x09, 0x10, 0x8D, 0x06, 0x4C, 0x64, 
-	0x0E, 0x64, 0x13, 0xA5, 0x0C, 0xE5, 0x0D, 0xC9, 
-	0xC8, 0xA5, 0x15, 0x29, 0xF3, 0xB0, 0x02, 0x09, 
-	0x08, 0x8D, 0x04, 0x4C, 0xA5, 0x12, 0xF0, 0x08, 
-	0xA5, 0x0F, 0x85, 0x10, 0x64, 0x0E, 0x64, 0x12, 
-	0x20, 0x23, 0x3A, 0xA5, 0x1F, 0xF0, 0x0F, 0xA5, 
-	0x22, 0x85, 0x23, 0xA5, 0x20, 0x09, 0x10, 0x8D, 
-	0x06, 0x54, 0x64, 0x1A, 0x64, 0x1F, 0xA5, 0x18, 
-	0xE5, 0x19, 0xC9, 0xC8, 0xA5, 0x21, 0x29, 0xF3, 
-	0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x54, 0xA5, 
-	0x1E, 0xF0, 0x08, 0xA5, 0x1B, 0x85, 0x1C, 0x64, 
-	0x1A, 0x64, 0x1E, 0x20, 0x23, 0x3A, 0xA5, 0x2B, 
-	0xF0, 0x0F, 0xA5, 0x2E, 0x85, 0x2F, 0xA5, 0x2C, 
-	0x09, 0x10, 0x8D, 0x06, 0x5C, 0x64, 0x26, 0x64, 
-	0x2B, 0xA5, 0x24, 0xE5, 0x25, 0xC9, 0xC8, 0xA5, 
-	0x2D, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 
-	0x04, 0x5C, 0xA5, 0x2A, 0xF0, 0x08, 0xA5, 0x27, 
-	0x85, 0x28, 0x64, 0x26, 0x64, 0x2A, 0x20, 0x23, 
-	0x3A, 0xA5, 0x37, 0xF0, 0x0F, 0xA5, 0x3A, 0x85, 
-	0x3B, 0xA5, 0x38, 0x09, 0x10, 0x8D, 0x06, 0x64, 
-	0x64, 0x32, 0x64, 0x37, 0xA5, 0x30, 0xE5, 0x31, 
-	0xC9, 0xC8, 0xA5, 0x39, 0x29, 0xF3, 0xB0, 0x02, 
-	0x09, 0x08, 0x8D, 0x04, 0x64, 0xA5, 0x36, 0xF0, 
-	0x08, 0xA5, 0x33, 0x85, 0x34, 0x64, 0x32, 0x64, 
-	0x36, 0x20, 0x23, 0x3A, 0xA5, 0x43, 0xF0, 0x0F, 
-	0xA5, 0x46, 0x85, 0x47, 0xA5, 0x44, 0x09, 0x10, 
-	0x8D, 0x06, 0x6C, 0x64, 0x3E, 0x64, 0x43, 0xA5, 
-	0x3C, 0xE5, 0x3D, 0xC9, 0xC8, 0xA5, 0x45, 0x29, 
-	0xF3, 0xB0, 0x02, 0x09, 0x08, 0x8D, 0x04, 0x6C, 
-	0xA5, 0x42, 0xF0, 0x08, 0xA5, 0x3F, 0x85, 0x40, 
-	0x64, 0x3E, 0x64, 0x42, 0x20, 0x23, 0x3A, 0xA5, 
-	0x4F, 0xF0, 0x0F, 0xA5, 0x52, 0x85, 0x53, 0xA5, 
-	0x50, 0x09, 0x10, 0x8D, 0x06, 0x74, 0x64, 0x4A, 
-	0x64, 0x4F, 0xA5, 0x48, 0xE5, 0x49, 0xC9, 0xC8, 
-	0xA5, 0x51, 0x29, 0xF3, 0xB0, 0x02, 0x09, 0x08, 
-	0x8D, 0x04, 0x74, 0xA5, 0x4E, 0xF0, 0x08, 0xA5, 
-	0x4B, 0x85, 0x4C, 0x64, 0x4A, 0x64, 0x4E, 0x20, 
-	0x23, 0x3A, 0x4C, 0x92, 0x38, 0xAD, 0x02, 0x44, 
-	0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 
-	0xAD, 0x00, 0x44, 0xD0, 0x32, 0xA6, 0x00, 0xA9, 
-	0x01, 0x9D, 0x00, 0x10, 0xA9, 0x01, 0x9D, 0x00, 
-	0x09, 0xE8, 0xE4, 0x01, 0xF0, 0x02, 0x86, 0x00, 
-	0x4C, 0x65, 0x3A, 0xA6, 0x00, 0xAD, 0x00, 0x44, 
-	0x9D, 0x00, 0x09, 0x9E, 0x00, 0x10, 0xE8, 0xE4, 
-	0x01, 0xF0, 0x02, 0x86, 0x00, 0x29, 0x7F, 0xC9, 
-	0x13, 0xD0, 0x04, 0xA5, 0x0B, 0x85, 0x02, 0xAD, 
-	0x02, 0x44, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x05, 
-	0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 0xD0, 
-	0x21, 0x8E, 0x00, 0x44, 0x64, 0x05, 0x4C, 0x98, 
-	0x3A, 0xA6, 0x04, 0xE4, 0x03, 0xF0, 0x13, 0xA5, 
-	0x02, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x01, 
-	0xD0, 0x08, 0xBD, 0x00, 0x02, 0x8D, 0x00, 0x44, 
-	0xE6, 0x04, 0xAD, 0x02, 0x4C, 0x89, 0x08, 0xF0, 
-	0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x4C, 
-	0xD0, 0x32, 0xA6, 0x0C, 0xA9, 0x01, 0x9D, 0x00, 
-	0x11, 0xA9, 0x01, 0x9D, 0x00, 0x0A, 0xE8, 0xE4, 
-	0x0D, 0xF0, 0x02, 0x86, 0x0C, 0x4C, 0xDA, 0x3A, 
-	0xA6, 0x0C, 0xAD, 0x00, 0x4C, 0x9D, 0x00, 0x0A, 
-	0x9E, 0x00, 0x11, 0xE8, 0xE4, 0x0D, 0xF0, 0x02, 
-	0x86, 0x0C, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 
-	0xA5, 0x17, 0x85, 0x0E, 0xAD, 0x02, 0x4C, 0x29, 
-	0x10, 0xF0, 0x2C, 0xA6, 0x11, 0xF0, 0x0F, 0xAD, 
-	0x02, 0x7C, 0x29, 0x02, 0xD0, 0x21, 0x8E, 0x00, 
-	0x4C, 0x64, 0x11, 0x4C, 0x0D, 0x3B, 0xA6, 0x10, 
-	0xE4, 0x0F, 0xF0, 0x13, 0xA5, 0x0E, 0xD0, 0x0F, 
-	0xAD, 0x02, 0x7C, 0x29, 0x02, 0xD0, 0x08, 0xBD, 
-	0x00, 0x03, 0x8D, 0x00, 0x4C, 0xE6, 0x10, 0xAD, 
-	0x02, 0x54, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 
-	0xF0, 0x1B, 0xAD, 0x00, 0x54, 0xD0, 0x32, 0xA6, 
-	0x18, 0xA9, 0x01, 0x9D, 0x00, 0x12, 0xA9, 0x01, 
-	0x9D, 0x00, 0x0B, 0xE8, 0xE4, 0x19, 0xF0, 0x02, 
-	0x86, 0x18, 0x4C, 0x4F, 0x3B, 0xA6, 0x18, 0xAD, 
-	0x00, 0x54, 0x9D, 0x00, 0x0B, 0x9E, 0x00, 0x12, 
-	0xE8, 0xE4, 0x19, 0xF0, 0x02, 0x86, 0x18, 0x29, 
-	0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x23, 0x85, 
-	0x1A, 0xAD, 0x02, 0x54, 0x29, 0x10, 0xF0, 0x2C, 
-	0xA6, 0x1D, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
-	0x04, 0xD0, 0x21, 0x8E, 0x00, 0x54, 0x64, 0x1D, 
-	0x4C, 0x82, 0x3B, 0xA6, 0x1C, 0xE4, 0x1B, 0xF0, 
-	0x13, 0xA5, 0x1A, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 
-	0x29, 0x04, 0xD0, 0x08, 0xBD, 0x00, 0x04, 0x8D, 
-	0x00, 0x54, 0xE6, 0x1C, 0xAD, 0x02, 0x5C, 0x89, 
-	0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 
-	0x00, 0x5C, 0xD0, 0x32, 0xA6, 0x24, 0xA9, 0x01, 
-	0x9D, 0x00, 0x13, 0xA9, 0x01, 0x9D, 0x00, 0x0C, 
-	0xE8, 0xE4, 0x25, 0xF0, 0x02, 0x86, 0x24, 0x4C, 
-	0xC4, 0x3B, 0xA6, 0x24, 0xAD, 0x00, 0x5C, 0x9D, 
-	0x00, 0x0C, 0x9E, 0x00, 0x13, 0xE8, 0xE4, 0x25, 
-	0xF0, 0x02, 0x86, 0x24, 0x29, 0x7F, 0xC9, 0x13, 
-	0xD0, 0x04, 0xA5, 0x2F, 0x85, 0x26, 0xAD, 0x02, 
-	0x5C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x29, 0xF0, 
-	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 0x21, 
-	0x8E, 0x00, 0x5C, 0x64, 0x29, 0x4C, 0xF7, 0x3B, 
-	0xA6, 0x28, 0xE4, 0x27, 0xF0, 0x13, 0xA5, 0x26, 
-	0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x08, 0xD0, 
-	0x08, 0xBD, 0x00, 0x05, 0x8D, 0x00, 0x5C, 0xE6, 
-	0x28, 0xAD, 0x02, 0x64, 0x89, 0x08, 0xF0, 0x3B, 
-	0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 0x64, 0xD0, 
-	0x32, 0xA6, 0x30, 0xA9, 0x01, 0x9D, 0x00, 0x14, 
-	0xA9, 0x01, 0x9D, 0x00, 0x0D, 0xE8, 0xE4, 0x31, 
-	0xF0, 0x02, 0x86, 0x30, 0x4C, 0x39, 0x3C, 0xA6, 
-	0x30, 0xAD, 0x00, 0x64, 0x9D, 0x00, 0x0D, 0x9E, 
-	0x00, 0x14, 0xE8, 0xE4, 0x31, 0xF0, 0x02, 0x86, 
-	0x30, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 0x04, 0xA5, 
-	0x3B, 0x85, 0x32, 0xAD, 0x02, 0x64, 0x29, 0x10, 
-	0xF0, 0x2C, 0xA6, 0x35, 0xF0, 0x0F, 0xAD, 0x02, 
-	0x7C, 0x29, 0x10, 0xD0, 0x21, 0x8E, 0x00, 0x64, 
-	0x64, 0x35, 0x4C, 0x6C, 0x3C, 0xA6, 0x34, 0xE4, 
-	0x33, 0xF0, 0x13, 0xA5, 0x32, 0xD0, 0x0F, 0xAD, 
-	0x02, 0x7C, 0x29, 0x10, 0xD0, 0x08, 0xBD, 0x00, 
-	0x06, 0x8D, 0x00, 0x64, 0xE6, 0x34, 0xAD, 0x02, 
-	0x6C, 0x89, 0x08, 0xF0, 0x3B, 0x89, 0x02, 0xF0, 
-	0x1B, 0xAD, 0x00, 0x6C, 0xD0, 0x32, 0xA6, 0x3C, 
-	0xA9, 0x01, 0x9D, 0x00, 0x15, 0xA9, 0x01, 0x9D, 
-	0x00, 0x0E, 0xE8, 0xE4, 0x3D, 0xF0, 0x02, 0x86, 
-	0x3C, 0x4C, 0xAE, 0x3C, 0xA6, 0x3C, 0xAD, 0x00, 
-	0x6C, 0x9D, 0x00, 0x0E, 0x9E, 0x00, 0x15, 0xE8, 
-	0xE4, 0x3D, 0xF0, 0x02, 0x86, 0x3C, 0x29, 0x7F, 
-	0xC9, 0x13, 0xD0, 0x04, 0xA5, 0x47, 0x85, 0x3E, 
-	0xAD, 0x02, 0x6C, 0x29, 0x10, 0xF0, 0x2C, 0xA6, 
-	0x41, 0xF0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x20, 
-	0xD0, 0x21, 0x8E, 0x00, 0x6C, 0x64, 0x41, 0x4C, 
-	0xE1, 0x3C, 0xA6, 0x40, 0xE4, 0x3F, 0xF0, 0x13, 
-	0xA5, 0x3E, 0xD0, 0x0F, 0xAD, 0x02, 0x7C, 0x29, 
-	0x20, 0xD0, 0x08, 0xBD, 0x00, 0x07, 0x8D, 0x00, 
-	0x6C, 0xE6, 0x40, 0xAD, 0x02, 0x74, 0x89, 0x08, 
-	0xF0, 0x3B, 0x89, 0x02, 0xF0, 0x1B, 0xAD, 0x00, 
-	0x74, 0xD0, 0x32, 0xA6, 0x48, 0xA9, 0x01, 0x9D, 
-	0x00, 0x16, 0xA9, 0x01, 0x9D, 0x00, 0x0F, 0xE8, 
-	0xE4, 0x49, 0xF0, 0x02, 0x86, 0x48, 0x4C, 0x23, 
-	0x3D, 0xA6, 0x48, 0xAD, 0x00, 0x74, 0x9D, 0x00, 
-	0x0F, 0x9E, 0x00, 0x16, 0xE8, 0xE4, 0x49, 0xF0, 
-	0x02, 0x86, 0x48, 0x29, 0x7F, 0xC9, 0x13, 0xD0, 
-	0x04, 0xA5, 0x53, 0x85, 0x4A, 0xAD, 0x02, 0x74, 
-	0x29, 0x10, 0xF0, 0x2C, 0xA6, 0x4D, 0xF0, 0x0F, 
-	0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x21, 0x8E, 
-	0x00, 0x74, 0x64, 0x4D, 0x4C, 0x56, 0x3D, 0xA6, 
-	0x4C, 0xE4, 0x4B, 0xF0, 0x13, 0xA5, 0x4A, 0xD0, 
-	0x0F, 0xAD, 0x02, 0x7C, 0x29, 0x40, 0xD0, 0x08, 
-	0xBD, 0x00, 0x08, 0x8D, 0x00, 0x74, 0xE6, 0x4C, 
-	0x60, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 
-	0xFF, 0xFF, 0xFF, 0xFF, 0xD0, 0xD0, 0x00, 0x38, 
-	0xCE, 0xC0, 
-};
diff -druN linux-libre-2.6.38-gnu/drivers/char/ser_a2232.h linux-libre-2.6.39-gnu/drivers/char/ser_a2232.h
--- linux-libre-2.6.38-gnu/drivers/char/ser_a2232.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ser_a2232.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,202 +0,0 @@
-/* drivers/char/ser_a2232.h */
-
-/* $Id: ser_a2232.h,v 0.4 2000/01/25 12:00:00 ehaase Exp $ */
-
-/* Linux serial driver for the Amiga A2232 board */
-
-/* This driver is MAINTAINED. Before applying any changes, please contact
- * the author.
- */
-   
-/* Copyright (c) 2000-2001 Enver Haase    <ehaase@inf.fu-berlin.de>
- *                   alias The A2232 driver project <A2232@gmx.net>
- * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
- *  
- */
-
-#ifndef _SER_A2232_H_
-#define _SER_A2232_H_
-
-/*
-	How many boards are to be supported at maximum;
-	"up to five A2232 Multiport Serial Cards may be installed in a
-	single Amiga 2000" states the A2232 User's Guide. If you have
-	more slots available, you might want to change the value below.
-*/
-#define MAX_A2232_BOARDS 5
-
-#ifndef A2232_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define A2232_NORMAL_MAJOR  224	/* /dev/ttyY* */
-#define A2232_CALLOUT_MAJOR 225	/* /dev/cuy*  */
-#endif
-
-/* Some magic is always good - Who knows :) */
-#define A2232_MAGIC 0x000a2232
-
-/* A2232 port structure to keep track of the
-   status of every single line used */
-struct a2232_port{
-	struct gs_port gs;
-	unsigned int which_a2232;
-	unsigned int which_port_on_a2232;
-	short disable_rx;
-	short throttle_input;
-	short cd_status;
-};
-
-#define	NUMLINES		7	/* number of lines per board */
-#define	A2232_IOBUFLEN		256	/* number of bytes per buffer */
-#define	A2232_IOBUFLENMASK	0xff	/* mask for maximum number of bytes */
-
-
-#define	A2232_UNKNOWN	0	/* crystal not known */
-#define	A2232_NORMAL	1	/* normal A2232 (1.8432 MHz oscillator) */
-#define	A2232_TURBO	2	/* turbo A2232 (3.6864 MHz oscillator) */
-
-
-struct a2232common {
-	char   Crystal;	/* normal (1) or turbo (2) board? */
-	u_char Pad_a;
-	u_char TimerH;	/* timer value after speed check */
-	u_char TimerL;
-	u_char CDHead;	/* head pointer for CD message queue */
-	u_char CDTail;	/* tail pointer for CD message queue */
-	u_char CDStatus;
-	u_char Pad_b;
-};
-
-struct a2232status {
-	u_char InHead;		/* input queue head */
-	u_char InTail;		/* input queue tail */
-	u_char OutDisable;	/* disables output */
-	u_char OutHead;		/* output queue head */
-	u_char OutTail;		/* output queue tail */
-	u_char OutCtrl;		/* soft flow control character to send */
-	u_char OutFlush;	/* flushes output buffer */
-	u_char Setup;		/* causes reconfiguration */
-	u_char Param;		/* parameter byte - see A2232PARAM */
-	u_char Command;		/* command byte - see A2232CMD */
-	u_char SoftFlow;	/* enables xon/xoff flow control */
-	/* private 65EC02 fields: */
-	u_char XonOff;		/* stores XON/XOFF enable/disable */
-};
-
-#define	A2232_MEMPAD1	\
-	(0x0200 - NUMLINES * sizeof(struct a2232status)	-	\
-	sizeof(struct a2232common))
-#define	A2232_MEMPAD2	(0x2000 - NUMLINES * A2232_IOBUFLEN - A2232_IOBUFLEN)
-
-struct a2232memory {
-	struct a2232status Status[NUMLINES];	/* 0x0000-0x006f status areas */
-	struct a2232common Common;		/* 0x0070-0x0077 common flags */
-	u_char Dummy1[A2232_MEMPAD1];		/* 0x00XX-0x01ff */
-	u_char OutBuf[NUMLINES][A2232_IOBUFLEN];/* 0x0200-0x08ff output bufs */
-	u_char InBuf[NUMLINES][A2232_IOBUFLEN];	/* 0x0900-0x0fff input bufs */
-	u_char InCtl[NUMLINES][A2232_IOBUFLEN];	/* 0x1000-0x16ff control data */
-	u_char CDBuf[A2232_IOBUFLEN];		/* 0x1700-0x17ff CD event buffer */
-	u_char Dummy2[A2232_MEMPAD2];		/* 0x1800-0x2fff */
-	u_char Code[0x1000];			/* 0x3000-0x3fff code area */
-	u_short InterruptAck;			/* 0x4000        intr ack */
-	u_char Dummy3[0x3ffe];			/* 0x4002-0x7fff */
-	u_short Enable6502Reset;		/* 0x8000 Stop board, */
-						/*  6502 RESET line held low */
-	u_char Dummy4[0x3ffe];			/* 0x8002-0xbfff */
-	u_short ResetBoard;			/* 0xc000 reset board & run, */
-						/*  6502 RESET line held high */
-};
-
-#undef A2232_MEMPAD1
-#undef A2232_MEMPAD2
-
-#define	A2232INCTL_CHAR		0	/* corresponding byte in InBuf is a character */
-#define	A2232INCTL_EVENT	1	/* corresponding byte in InBuf is an event */
-
-#define	A2232EVENT_Break	1	/* break set */
-#define	A2232EVENT_CarrierOn	2	/* carrier raised */
-#define	A2232EVENT_CarrierOff	3	/* carrier dropped */
-#define A2232EVENT_Sync		4	/* don't know, defined in 2232.ax */
-
-#define	A2232CMD_Enable		0x1	/* enable/DTR bit */
-#define	A2232CMD_Close		0x2	/* close the device */
-#define	A2232CMD_Open		0xb	/* open the device */
-#define	A2232CMD_CMask		0xf	/* command mask */
-#define	A2232CMD_RTSOff		0x0  	/* turn off RTS */
-#define	A2232CMD_RTSOn		0x8	/* turn on RTS */
-#define	A2232CMD_Break		0xd	/* transmit a break */
-#define	A2232CMD_RTSMask	0xc	/* mask for RTS stuff */
-#define	A2232CMD_NoParity	0x00	/* don't use parity */
-#define	A2232CMD_OddParity	0x20	/* odd parity */
-#define	A2232CMD_EvenParity	0x60	/* even parity */
-#define	A2232CMD_ParityMask	0xe0	/* parity mask */
-
-#define	A2232PARAM_B115200	0x0	/* baud rates */
-#define	A2232PARAM_B50		0x1
-#define	A2232PARAM_B75		0x2
-#define	A2232PARAM_B110		0x3
-#define	A2232PARAM_B134		0x4
-#define	A2232PARAM_B150		0x5
-#define	A2232PARAM_B300		0x6
-#define	A2232PARAM_B600		0x7
-#define	A2232PARAM_B1200	0x8
-#define	A2232PARAM_B1800	0x9
-#define	A2232PARAM_B2400	0xa
-#define	A2232PARAM_B3600	0xb
-#define	A2232PARAM_B4800	0xc
-#define	A2232PARAM_B7200	0xd
-#define	A2232PARAM_B9600	0xe
-#define	A2232PARAM_B19200	0xf
-#define	A2232PARAM_BaudMask	0xf	/* baud rate mask */
-#define	A2232PARAM_RcvBaud	0x10	/* enable receive baud rate */
-#define	A2232PARAM_8Bit		0x00	/* numbers of bits */
-#define	A2232PARAM_7Bit		0x20
-#define	A2232PARAM_6Bit		0x40
-#define	A2232PARAM_5Bit		0x60
-#define	A2232PARAM_BitMask	0x60	/* numbers of bits mask */
-
-
-/* Standard speeds tables, -1 means unavailable, -2 means 0 baud: switch off line */
-#define A2232_BAUD_TABLE_NOAVAIL -1
-#define A2232_BAUD_TABLE_NUM_RATES (18)
-static int a2232_baud_table[A2232_BAUD_TABLE_NUM_RATES*3] = {
-	//Baud	//Normal			//Turbo
-	50,	A2232PARAM_B50,			A2232_BAUD_TABLE_NOAVAIL,
-	75,	A2232PARAM_B75,			A2232_BAUD_TABLE_NOAVAIL,
-	110,	A2232PARAM_B110,		A2232_BAUD_TABLE_NOAVAIL,
-	134,	A2232PARAM_B134,		A2232_BAUD_TABLE_NOAVAIL,
-	150,	A2232PARAM_B150,		A2232PARAM_B75,
-	200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-	300,	A2232PARAM_B300,		A2232PARAM_B150,
-	600,	A2232PARAM_B600,		A2232PARAM_B300,
-	1200,	A2232PARAM_B1200,		A2232PARAM_B600,
-	1800,	A2232PARAM_B1800,		A2232_BAUD_TABLE_NOAVAIL,
-	2400,	A2232PARAM_B2400,		A2232PARAM_B1200,
-	4800,	A2232PARAM_B4800,		A2232PARAM_B2400,
-	9600,	A2232PARAM_B9600,		A2232PARAM_B4800,
-	19200,	A2232PARAM_B19200,		A2232PARAM_B9600,
-	38400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B19200,
-	57600,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-#ifdef A2232_SPEEDHACK
-	115200,	A2232PARAM_B115200,		A2232_BAUD_TABLE_NOAVAIL,
-	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232PARAM_B115200
-#else
-	115200,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL,
-	230400,	A2232_BAUD_TABLE_NOAVAIL,	A2232_BAUD_TABLE_NOAVAIL
-#endif
-};
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/char/serial167.c linux-libre-2.6.39-gnu/drivers/char/serial167.c
--- linux-libre-2.6.38-gnu/drivers/char/serial167.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/serial167.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2490 +0,0 @@
-/*
- * linux/drivers/char/serial167.c
- *
- * Driver for MVME166/7 board serial ports, which are via a CD2401.
- * Based very much on cyclades.c.
- *
- * MVME166/7 work by Richard Hirst [richard@sleepie.demon.co.uk]
- *
- * ==============================================================
- *
- * static char rcsid[] =
- * "$Revision: 1.36.1.4 $$Date: 1995/03/29 06:14:14 $";
- *
- *  linux/kernel/cyclades.c
- *
- * Maintained by Marcio Saito (cyclades@netcom.com) and
- * Randolph Bentson (bentson@grieg.seaslug.org)
- *
- * Much of the design and some of the code came from serial.c
- * which was copyright (C) 1991, 1992  Linus Torvalds.  It was
- * extensively rewritten by Theodore Ts'o, 8/16/92 -- 9/14/92,
- * and then fixed as suggested by Michael K. Johnson 12/12/92.
- *
- * This version does not support shared irq's.
- *
- * $Log: cyclades.c,v $
- * Revision 1.36.1.4  1995/03/29  06:14:14  bentson
- * disambiguate between Cyclom-16Y and Cyclom-32Ye;
- *
- * Changes:
- *
- * 200 lines of changes record removed - RGH 11-10-95, starting work on
- * converting this to drive serial ports on mvme166 (cd2401).
- *
- * Arnaldo Carvalho de Melo <acme@conectiva.com.br> - 2000/08/25
- * - get rid of verify_area
- * - use get_user to access memory from userspace in set_threshold,
- *   set_default_threshold and set_timeout
- * - don't use the panic function in serial167_init
- * - do resource release on failure on serial167_init
- * - include missing restore_flags in mvme167_serial_console_setup
- *
- * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
- * - replace bottom half handler with task queue handler
- */
-
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/tty.h>
-#include <linux/interrupt.h>
-#include <linux/serial.h>
-#include <linux/serialP.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/serial167.h>
-#include <linux/delay.h>
-#include <linux/major.h>
-#include <linux/mm.h>
-#include <linux/console.h>
-#include <linux/module.h>
-#include <linux/bitops.h>
-#include <linux/tty_flip.h>
-#include <linux/gfp.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/mvme16xhw.h>
-#include <asm/bootinfo.h>
-#include <asm/setup.h>
-
-#include <linux/types.h>
-#include <linux/kernel.h>
-
-#include <asm/uaccess.h>
-#include <linux/init.h>
-
-#define SERIAL_PARANOIA_CHECK
-#undef  SERIAL_DEBUG_OPEN
-#undef  SERIAL_DEBUG_THROTTLE
-#undef  SERIAL_DEBUG_OTHER
-#undef  SERIAL_DEBUG_IO
-#undef  SERIAL_DEBUG_COUNT
-#undef  SERIAL_DEBUG_DTR
-#undef  CYCLOM_16Y_HACK
-#define  CYCLOM_ENABLE_MONITORING
-
-#define WAKEUP_CHARS 256
-
-#define STD_COM_FLAGS (0)
-
-static struct tty_driver *cy_serial_driver;
-extern int serial_console;
-static struct cyclades_port *serial_console_info = NULL;
-static unsigned int serial_console_cflag = 0;
-u_char initial_console_speed;
-
-/* Base address of cd2401 chip on mvme166/7 */
-
-#define BASE_ADDR (0xfff45000)
-#define pcc2chip	((volatile u_char *)0xfff42000)
-#define PccSCCMICR	0x1d
-#define PccSCCTICR	0x1e
-#define PccSCCRICR	0x1f
-#define PccTPIACKR	0x25
-#define PccRPIACKR	0x27
-#define PccIMLR		0x3f
-
-/* This is the per-port data structure */
-struct cyclades_port cy_port[] = {
-	/* CARD#  */
-	{-1},			/* ttyS0 */
-	{-1},			/* ttyS1 */
-	{-1},			/* ttyS2 */
-	{-1},			/* ttyS3 */
-};
-
-#define NR_PORTS        ARRAY_SIZE(cy_port)
-
-/*
- * This is used to look up the divisor speeds and the timeouts
- * We're normally limited to 15 distinct baud rates.  The extra
- * are accessed via settings in info->flags.
- *         0,     1,     2,     3,     4,     5,     6,     7,     8,     9,
- *        10,    11,    12,    13,    14,    15,    16,    17,    18,    19,
- *                                                  HI            VHI
- */
-static int baud_table[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
-	1800, 2400, 4800, 9600, 19200, 38400, 57600, 76800, 115200, 150000,
-	0
-};
-
-#if 0
-static char baud_co[] = {	/* 25 MHz clock option table */
-	/* value =>    00    01   02    03    04 */
-	/* divide by    8    32   128   512  2048 */
-	0x00, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x02,
-	0x02, 0x02, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-static char baud_bpr[] = {	/* 25 MHz baud rate period table */
-	0x00, 0xf5, 0xa3, 0x6f, 0x5c, 0x51, 0xf5, 0xa3, 0x51, 0xa3,
-	0x6d, 0x51, 0xa3, 0x51, 0xa3, 0x51, 0x36, 0x29, 0x1b, 0x15
-};
-#endif
-
-/* I think 166 brd clocks 2401 at 20MHz.... */
-
-/* These values are written directly to tcor, and >> 5 for writing to rcor */
-static u_char baud_co[] = {	/* 20 MHz clock option table */
-	0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x60, 0x60, 0x40,
-	0x40, 0x40, 0x20, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-/* These values written directly to tbpr/rbpr */
-static u_char baud_bpr[] = {	/* 20 MHz baud rate period table */
-	0x00, 0xc0, 0x80, 0x58, 0x6c, 0x40, 0xc0, 0x81, 0x40, 0x81,
-	0x57, 0x40, 0x81, 0x40, 0x81, 0x40, 0x2b, 0x20, 0x15, 0x10
-};
-
-static u_char baud_cor4[] = {	/* receive threshold */
-	0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a, 0x0a,
-	0x0a, 0x0a, 0x0a, 0x09, 0x09, 0x08, 0x08, 0x08, 0x08, 0x07
-};
-
-static void shutdown(struct cyclades_port *);
-static int startup(struct cyclades_port *);
-static void cy_throttle(struct tty_struct *);
-static void cy_unthrottle(struct tty_struct *);
-static void config_setup(struct cyclades_port *);
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int);
-#endif
-
-/*
- * I have my own version of udelay(), as it is needed when initialising
- * the chip, before the delay loop has been calibrated.  Should probably
- * reference one of the vmechip2 or pccchip2 counter for an accurate
- * delay, but this wild guess will do for now.
- */
-
-void my_udelay(long us)
-{
-	u_char x;
-	volatile u_char *p = &x;
-	int i;
-
-	while (us--)
-		for (i = 100; i; i--)
-			x |= *p;
-}
-
-static inline int serial_paranoia_check(struct cyclades_port *info, char *name,
-		const char *routine)
-{
-#ifdef SERIAL_PARANOIA_CHECK
-	if (!info) {
-		printk("Warning: null cyclades_port for (%s) in %s\n", name,
-				routine);
-		return 1;
-	}
-
-	if (info < &cy_port[0] || info >= &cy_port[NR_PORTS]) {
-		printk("Warning: cyclades_port out of range for (%s) in %s\n",
-				name, routine);
-		return 1;
-	}
-
-	if (info->magic != CYCLADES_MAGIC) {
-		printk("Warning: bad magic number for serial struct (%s) in "
-				"%s\n", name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}				/* serial_paranoia_check */
-
-#if 0
-/* The following diagnostic routines allow the driver to spew
-   information on the screen, even (especially!) during interrupts.
- */
-void SP(char *data)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	printk(KERN_EMERG "%s", data);
-	local_irq_restore(flags);
-}
-
-char scrn[2];
-void CP(char data)
-{
-	unsigned long flags;
-	local_irq_save(flags);
-	scrn[0] = data;
-	printk(KERN_EMERG "%c", scrn);
-	local_irq_restore(flags);
-}				/* CP */
-
-void CP1(int data)
-{
-	(data < 10) ? CP(data + '0') : CP(data + 'A' - 10);
-}				/* CP1 */
-void CP2(int data)
-{
-	CP1((data >> 4) & 0x0f);
-	CP1(data & 0x0f);
-}				/* CP2 */
-void CP4(int data)
-{
-	CP2((data >> 8) & 0xff);
-	CP2(data & 0xff);
-}				/* CP4 */
-void CP8(long data)
-{
-	CP4((data >> 16) & 0xffff);
-	CP4(data & 0xffff);
-}				/* CP8 */
-#endif
-
-/* This routine waits up to 1000 micro-seconds for the previous
-   command to the Cirrus chip to complete and then issues the
-   new command.  An error is returned if the previous command
-   didn't finish within the time limit.
- */
-u_short write_cy_cmd(volatile u_char * base_addr, u_char cmd)
-{
-	unsigned long flags;
-	volatile int i;
-
-	local_irq_save(flags);
-	/* Check to see that the previous command has completed */
-	for (i = 0; i < 100; i++) {
-		if (base_addr[CyCCR] == 0) {
-			break;
-		}
-		my_udelay(10L);
-	}
-	/* if the CCR never cleared, the previous command
-	   didn't finish within the "reasonable time" */
-	if (i == 10) {
-		local_irq_restore(flags);
-		return (-1);
-	}
-
-	/* Issue the new command */
-	base_addr[CyCCR] = cmd;
-	local_irq_restore(flags);
-	return (0);
-}				/* write_cy_cmd */
-
-/* cy_start and cy_stop provide software output flow control as a
-   function of XON/XOFF, software CTS, and other such stuff. */
-
-static void cy_stop(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_stop %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_stop"))
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) (channel);	/* index channel */
-	base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-	local_irq_restore(flags);
-}				/* cy_stop */
-
-static void cy_start(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_start %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_start"))
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) (channel);
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* cy_start */
-
-/* The real interrupt service routines are called
-   whenever the card wants its hand held--chars
-   received, out buffer empty, modem change, etc.
- */
-static irqreturn_t cd2401_rxerr_interrupt(int irq, void *dev_id)
-{
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	unsigned char err, rfoc;
-	int channel;
-	char data;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-
-	if ((err = base_addr[CyRISR]) & CyTIMEOUT) {
-		/* This is a receive timeout interrupt, ignore it */
-		base_addr[CyREOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-
-	/* Read a byte of data if there is any - assume the error
-	 * is associated with this character */
-
-	if ((rfoc = base_addr[CyRFOC]) != 0)
-		data = base_addr[CyRDR];
-	else
-		data = 0;
-
-	/* if there is nowhere to put the data, discard it */
-	if (info->tty == 0) {
-		base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-		return IRQ_HANDLED;
-	} else {		/* there is an open port for this data */
-		tty = info->tty;
-		if (err & info->ignore_status_mask) {
-			base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-			return IRQ_HANDLED;
-		}
-		if (tty_buffer_request_room(tty, 1) != 0) {
-			if (err & info->read_status_mask) {
-				if (err & CyBREAK) {
-					tty_insert_flip_char(tty, data,
-							     TTY_BREAK);
-					if (info->flags & ASYNC_SAK) {
-						do_SAK(tty);
-					}
-				} else if (err & CyFRAME) {
-					tty_insert_flip_char(tty, data,
-							     TTY_FRAME);
-				} else if (err & CyPARITY) {
-					tty_insert_flip_char(tty, data,
-							     TTY_PARITY);
-				} else if (err & CyOVERRUN) {
-					tty_insert_flip_char(tty, 0,
-							     TTY_OVERRUN);
-					/*
-					   If the flip buffer itself is
-					   overflowing, we still lose
-					   the next incoming character.
-					 */
-					if (tty_buffer_request_room(tty, 1) !=
-					    0) {
-						tty_insert_flip_char(tty, data,
-								     TTY_FRAME);
-					}
-					/* These two conditions may imply */
-					/* a normal read should be done. */
-					/* else if(data & CyTIMEOUT) */
-					/* else if(data & CySPECHAR) */
-				} else {
-					tty_insert_flip_char(tty, 0,
-							     TTY_NORMAL);
-				}
-			} else {
-				tty_insert_flip_char(tty, data, TTY_NORMAL);
-			}
-		} else {
-			/* there was a software buffer overrun
-			   and nothing could be done about it!!! */
-		}
-	}
-	tty_schedule_flip(tty);
-	/* end of service */
-	base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_rxerr_interrupt */
-
-static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	int mdm_change;
-	int mdm_status;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-
-	mdm_change = base_addr[CyMISR];
-	mdm_status = base_addr[CyMSVR1];
-
-	if (info->tty == 0) {	/* nowhere to put the data, ignore it */
-		;
-	} else {
-		if ((mdm_change & CyDCD)
-		    && (info->flags & ASYNC_CHECK_CD)) {
-			if (mdm_status & CyDCD) {
-/* CP('!'); */
-				wake_up_interruptible(&info->open_wait);
-			} else {
-/* CP('@'); */
-				tty_hangup(info->tty);
-				wake_up_interruptible(&info->open_wait);
-				info->flags &= ~ASYNC_NORMAL_ACTIVE;
-			}
-		}
-		if ((mdm_change & CyCTS)
-		    && (info->flags & ASYNC_CTS_FLOW)) {
-			if (info->tty->stopped) {
-				if (mdm_status & CyCTS) {
-					/* !!! cy_start isn't used because... */
-					info->tty->stopped = 0;
-					base_addr[CyIER] |= CyTxMpty;
-					tty_wakeup(info->tty);
-				}
-			} else {
-				if (!(mdm_status & CyCTS)) {
-					/* !!! cy_stop isn't used because... */
-					info->tty->stopped = 1;
-					base_addr[CyIER] &=
-					    ~(CyTxMpty | CyTxRdy);
-				}
-			}
-		}
-		if (mdm_status & CyDSR) {
-		}
-	}
-	base_addr[CyMEOIR] = 0;
-	return IRQ_HANDLED;
-}				/* cy_modem_interrupt */
-
-static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
-{
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	int char_count, saved_cnt;
-	int outch;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-
-	/* validate the port number (as configured and open) */
-	if ((channel < 0) || (NR_PORTS <= channel)) {
-		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-		base_addr[CyTEOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-	if (info->tty == 0) {
-		base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-		base_addr[CyTEOIR] = CyNOTRANS;
-		return IRQ_HANDLED;
-	}
-
-	/* load the on-chip space available for outbound data */
-	saved_cnt = char_count = base_addr[CyTFTC];
-
-	if (info->x_char) {	/* send special char */
-		outch = info->x_char;
-		base_addr[CyTDR] = outch;
-		char_count--;
-		info->x_char = 0;
-	}
-
-	if (info->x_break) {
-		/*  The Cirrus chip requires the "Embedded Transmit
-		   Commands" of start break, delay, and end break
-		   sequences to be sent.  The duration of the
-		   break is given in TICs, which runs at HZ
-		   (typically 100) and the PPR runs at 200 Hz,
-		   so the delay is duration * 200/HZ, and thus a
-		   break can run from 1/100 sec to about 5/4 sec.
-		   Need to check these values - RGH 141095.
-		 */
-		base_addr[CyTDR] = 0;	/* start break */
-		base_addr[CyTDR] = 0x81;
-		base_addr[CyTDR] = 0;	/* delay a bit */
-		base_addr[CyTDR] = 0x82;
-		base_addr[CyTDR] = info->x_break * 200 / HZ;
-		base_addr[CyTDR] = 0;	/* terminate break */
-		base_addr[CyTDR] = 0x83;
-		char_count -= 7;
-		info->x_break = 0;
-	}
-
-	while (char_count > 0) {
-		if (!info->xmit_cnt) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		if (info->xmit_buf == 0) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		if (info->tty->stopped || info->tty->hw_stopped) {
-			base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
-			break;
-		}
-		/* Because the Embedded Transmit Commands have been
-		   enabled, we must check to see if the escape
-		   character, NULL, is being sent.  If it is, we
-		   must ensure that there is room for it to be
-		   doubled in the output stream.  Therefore we
-		   no longer advance the pointer when the character
-		   is fetched, but rather wait until after the check
-		   for a NULL output character. (This is necessary
-		   because there may not be room for the two chars
-		   needed to send a NULL.
-		 */
-		outch = info->xmit_buf[info->xmit_tail];
-		if (outch) {
-			info->xmit_cnt--;
-			info->xmit_tail = (info->xmit_tail + 1)
-			    & (PAGE_SIZE - 1);
-			base_addr[CyTDR] = outch;
-			char_count--;
-		} else {
-			if (char_count > 1) {
-				info->xmit_cnt--;
-				info->xmit_tail = (info->xmit_tail + 1)
-				    & (PAGE_SIZE - 1);
-				base_addr[CyTDR] = outch;
-				base_addr[CyTDR] = 0;
-				char_count--;
-				char_count--;
-			} else {
-				break;
-			}
-		}
-	}
-
-	if (info->xmit_cnt < WAKEUP_CHARS)
-		tty_wakeup(info->tty);
-
-	base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_tx_interrupt */
-
-static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
-{
-	struct tty_struct *tty;
-	struct cyclades_port *info;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-	char data;
-	int char_count;
-	int save_cnt;
-
-	/* determine the channel and change to that context */
-	channel = (u_short) (base_addr[CyLICR] >> 2);
-	info = &cy_port[channel];
-	info->last_active = jiffies;
-	save_cnt = char_count = base_addr[CyRFOC];
-
-		/* if there is nowhere to put the data, discard it */
-	if (info->tty == 0) {
-		while (char_count--) {
-			data = base_addr[CyRDR];
-		}
-	} else {		/* there is an open port for this data */
-		tty = info->tty;
-		/* load # characters available from the chip */
-
-#ifdef CYCLOM_ENABLE_MONITORING
-		++info->mon.int_count;
-		info->mon.char_count += char_count;
-		if (char_count > info->mon.char_max)
-			info->mon.char_max = char_count;
-		info->mon.char_last = char_count;
-#endif
-		while (char_count--) {
-			data = base_addr[CyRDR];
-			tty_insert_flip_char(tty, data, TTY_NORMAL);
-#ifdef CYCLOM_16Y_HACK
-			udelay(10L);
-#endif
-		}
-		tty_schedule_flip(tty);
-	}
-	/* end of service */
-	base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
-	return IRQ_HANDLED;
-}				/* cy_rx_interrupt */
-
-/* This is called whenever a port becomes active;
-   interrupts are enabled and DTR & RTS are turned on.
- */
-static int startup(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
-	int channel;
-
-	if (info->flags & ASYNC_INITIALIZED) {
-		return 0;
-	}
-
-	if (!info->type) {
-		if (info->tty) {
-			set_bit(TTY_IO_ERROR, &info->tty->flags);
-		}
-		return 0;
-	}
-	if (!info->xmit_buf) {
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-		if (!info->xmit_buf) {
-			return -ENOMEM;
-		}
-	}
-
-	config_setup(info);
-
-	channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("startup channel %d\n", channel);
-#endif
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
-	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
-	base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('1'); */
-	base_addr[CyMSVR2] = CyDTR;
-
-#ifdef SERIAL_DEBUG_DTR
-	printk("cyc: %d: raising DTR\n", __LINE__);
-	printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-	       base_addr[CyMSVR2]);
-#endif
-
-	base_addr[CyIER] |= CyRxData;
-	info->flags |= ASYNC_INITIALIZED;
-
-	if (info->tty) {
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(" done\n");
-#endif
-	return 0;
-}				/* startup */
-
-void start_xmit(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-	channel = info->line;
-	local_irq_save(flags);
-	base_addr[CyCAR] = channel;
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* start_xmit */
-
-/*
- * This routine shuts down a serial port; interrupts are disabled,
- * and DTR is dropped if the hangup on close termio flag is on.
- */
-static void shutdown(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-	if (!(info->flags & ASYNC_INITIALIZED)) {
-/* CP('$'); */
-		return;
-	}
-
-	channel = info->line;
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk("shutdown channel %d\n", channel);
-#endif
-
-	/* !!! REALLY MUST WAIT FOR LAST CHARACTER TO BE
-	   SENT BEFORE DROPPING THE LINE !!!  (Perhaps
-	   set some flag that is read when XMTY happens.)
-	   Other choices are to delay some fixed interval
-	   or schedule some later processing.
-	 */
-	local_irq_save(flags);
-	if (info->xmit_buf) {
-		free_page((unsigned long)info->xmit_buf);
-		info->xmit_buf = NULL;
-	}
-
-	base_addr[CyCAR] = (u_char) channel;
-	if (!info->tty || (info->tty->termios->c_cflag & HUPCL)) {
-		base_addr[CyMSVR1] = 0;
-/* CP('C');CP('1'); */
-		base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	}
-	write_cy_cmd(base_addr, CyDIS_RCVR);
-	/* it may be appropriate to clear _XMIT at
-	   some later date (after testing)!!! */
-
-	if (info->tty) {
-		set_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-	info->flags &= ~ASYNC_INITIALIZED;
-	local_irq_restore(flags);
-
-#ifdef SERIAL_DEBUG_OPEN
-	printk(" done\n");
-#endif
-}				/* shutdown */
-
-/*
- * This routine finds or computes the various line characteristics.
- */
-static void config_setup(struct cyclades_port *info)
-{
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned cflag;
-	int i;
-	unsigned char ti, need_init_chan = 0;
-
-	if (!info->tty || !info->tty->termios) {
-		return;
-	}
-	if (info->line == -1) {
-		return;
-	}
-	cflag = info->tty->termios->c_cflag;
-
-	/* baud rate */
-	i = cflag & CBAUD;
-#ifdef CBAUDEX
-/* Starting with kernel 1.1.65, there is direct support for
-   higher baud rates.  The following code supports those
-   changes.  The conditional aspect allows this driver to be
-   used for earlier as well as later kernel versions.  (The
-   mapping is slightly different from serial.c because there
-   is still the possibility of supporting 75 kbit/sec with
-   the Cyclades board.)
- */
-	if (i & CBAUDEX) {
-		if (i == B57600)
-			i = 16;
-		else if (i == B115200)
-			i = 18;
-#ifdef B78600
-		else if (i == B78600)
-			i = 17;
-#endif
-		else
-			info->tty->termios->c_cflag &= ~CBAUDEX;
-	}
-#endif
-	if (i == 15) {
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			i += 1;
-		if ((info->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			i += 3;
-	}
-	/* Don't ever change the speed of the console port.  It will
-	 * run at the speed specified in bootinfo, or at 19.2K */
-	/* Actually, it should run at whatever speed 166Bug was using */
-	/* Note info->timeout isn't used at present */
-	if (info != serial_console_info) {
-		info->tbpr = baud_bpr[i];	/* Tx BPR */
-		info->tco = baud_co[i];	/* Tx CO */
-		info->rbpr = baud_bpr[i];	/* Rx BPR */
-		info->rco = baud_co[i] >> 5;	/* Rx CO */
-		if (baud_table[i] == 134) {
-			info->timeout =
-			    (info->xmit_fifo_size * HZ * 30 / 269) + 2;
-			/* get it right for 134.5 baud */
-		} else if (baud_table[i]) {
-			info->timeout =
-			    (info->xmit_fifo_size * HZ * 15 / baud_table[i]) +
-			    2;
-			/* this needs to be propagated into the card info */
-		} else {
-			info->timeout = 0;
-		}
-	}
-	/* By tradition (is it a standard?) a baud rate of zero
-	   implies the line should be/has been closed.  A bit
-	   later in this routine such a test is performed. */
-
-	/* byte size and parity */
-	info->cor7 = 0;
-	info->cor6 = 0;
-	info->cor5 = 0;
-	info->cor4 = (info->default_threshold ? info->default_threshold : baud_cor4[i]);	/* receive threshold */
-	/* Following two lines added 101295, RGH. */
-	/* It is obviously wrong to access CyCORx, and not info->corx here,
-	 * try and remember to fix it later! */
-	channel = info->line;
-	base_addr[CyCAR] = (u_char) channel;
-	if (C_CLOCAL(info->tty)) {
-		if (base_addr[CyIER] & CyMdmCh)
-			base_addr[CyIER] &= ~CyMdmCh;	/* without modem intr */
-		/* ignore 1->0 modem transitions */
-		if (base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR4] &= ~(CyDSR | CyCTS | CyDCD);
-		/* ignore 0->1 modem transitions */
-		if (base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR5] &= ~(CyDSR | CyCTS | CyDCD);
-	} else {
-		if ((base_addr[CyIER] & CyMdmCh) != CyMdmCh)
-			base_addr[CyIER] |= CyMdmCh;	/* with modem intr */
-		/* act on 1->0 modem transitions */
-		if ((base_addr[CyCOR4] & (CyDSR | CyCTS | CyDCD)) !=
-		    (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR4] |= CyDSR | CyCTS | CyDCD;
-		/* act on 0->1 modem transitions */
-		if ((base_addr[CyCOR5] & (CyDSR | CyCTS | CyDCD)) !=
-		    (CyDSR | CyCTS | CyDCD))
-			base_addr[CyCOR5] |= CyDSR | CyCTS | CyDCD;
-	}
-	info->cor3 = (cflag & CSTOPB) ? Cy_2_STOP : Cy_1_STOP;
-	info->cor2 = CyETC;
-	switch (cflag & CSIZE) {
-	case CS5:
-		info->cor1 = Cy_5_BITS;
-		break;
-	case CS6:
-		info->cor1 = Cy_6_BITS;
-		break;
-	case CS7:
-		info->cor1 = Cy_7_BITS;
-		break;
-	case CS8:
-		info->cor1 = Cy_8_BITS;
-		break;
-	}
-	if (cflag & PARENB) {
-		if (cflag & PARODD) {
-			info->cor1 |= CyPARITY_O;
-		} else {
-			info->cor1 |= CyPARITY_E;
-		}
-	} else {
-		info->cor1 |= CyPARITY_NONE;
-	}
-
-	/* CTS flow control flag */
-#if 0
-	/* Don't complcate matters for now! RGH 141095 */
-	if (cflag & CRTSCTS) {
-		info->flags |= ASYNC_CTS_FLOW;
-		info->cor2 |= CyCtsAE;
-	} else {
-		info->flags &= ~ASYNC_CTS_FLOW;
-		info->cor2 &= ~CyCtsAE;
-	}
-#endif
-	if (cflag & CLOCAL)
-		info->flags &= ~ASYNC_CHECK_CD;
-	else
-		info->flags |= ASYNC_CHECK_CD;
-
-     /***********************************************
-	The hardware option, CyRtsAO, presents RTS when
-	the chip has characters to send.  Since most modems
-	use RTS as reverse (inbound) flow control, this
-	option is not used.  If inbound flow control is
-	necessary, DTR can be programmed to provide the
-	appropriate signals for use with a non-standard
-	cable.  Contact Marcio Saito for details.
-     ***********************************************/
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-
-	/* CyCMR set once only in mvme167_init_serial() */
-	if (base_addr[CyLICR] != channel << 2)
-		base_addr[CyLICR] = channel << 2;
-	if (base_addr[CyLIVR] != 0x5c)
-		base_addr[CyLIVR] = 0x5c;
-
-	/* tx and rx baud rate */
-
-	if (base_addr[CyCOR1] != info->cor1)
-		need_init_chan = 1;
-	if (base_addr[CyTCOR] != info->tco)
-		base_addr[CyTCOR] = info->tco;
-	if (base_addr[CyTBPR] != info->tbpr)
-		base_addr[CyTBPR] = info->tbpr;
-	if (base_addr[CyRCOR] != info->rco)
-		base_addr[CyRCOR] = info->rco;
-	if (base_addr[CyRBPR] != info->rbpr)
-		base_addr[CyRBPR] = info->rbpr;
-
-	/* set line characteristics  according configuration */
-
-	if (base_addr[CySCHR1] != START_CHAR(info->tty))
-		base_addr[CySCHR1] = START_CHAR(info->tty);
-	if (base_addr[CySCHR2] != STOP_CHAR(info->tty))
-		base_addr[CySCHR2] = STOP_CHAR(info->tty);
-	if (base_addr[CySCRL] != START_CHAR(info->tty))
-		base_addr[CySCRL] = START_CHAR(info->tty);
-	if (base_addr[CySCRH] != START_CHAR(info->tty))
-		base_addr[CySCRH] = START_CHAR(info->tty);
-	if (base_addr[CyCOR1] != info->cor1)
-		base_addr[CyCOR1] = info->cor1;
-	if (base_addr[CyCOR2] != info->cor2)
-		base_addr[CyCOR2] = info->cor2;
-	if (base_addr[CyCOR3] != info->cor3)
-		base_addr[CyCOR3] = info->cor3;
-	if (base_addr[CyCOR4] != info->cor4)
-		base_addr[CyCOR4] = info->cor4;
-	if (base_addr[CyCOR5] != info->cor5)
-		base_addr[CyCOR5] = info->cor5;
-	if (base_addr[CyCOR6] != info->cor6)
-		base_addr[CyCOR6] = info->cor6;
-	if (base_addr[CyCOR7] != info->cor7)
-		base_addr[CyCOR7] = info->cor7;
-
-	if (need_init_chan)
-		write_cy_cmd(base_addr, CyINIT_CHAN);
-
-	base_addr[CyCAR] = (u_char) channel;	/* !!! Is this needed? */
-
-	/* 2ms default rx timeout */
-	ti = info->default_timeout ? info->default_timeout : 0x02;
-	if (base_addr[CyRTPRL] != ti)
-		base_addr[CyRTPRL] = ti;
-	if (base_addr[CyRTPRH] != 0)
-		base_addr[CyRTPRH] = 0;
-
-	/* Set up RTS here also ????? RGH 141095 */
-	if (i == 0) {		/* baud rate is zero, turn off line */
-		if ((base_addr[CyMSVR2] & CyDTR) == CyDTR)
-			base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	} else {
-		if ((base_addr[CyMSVR2] & CyDTR) != CyDTR)
-			base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-	}
-
-	if (info->tty) {
-		clear_bit(TTY_IO_ERROR, &info->tty->flags);
-	}
-
-	local_irq_restore(flags);
-
-}				/* config_setup */
-
-static int cy_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_put_char %s(0x%02x)\n", tty->name, ch);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_put_char"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	local_irq_save(flags);
-	if (info->xmit_cnt >= PAGE_SIZE - 1) {
-		local_irq_restore(flags);
-		return 0;
-	}
-
-	info->xmit_buf[info->xmit_head++] = ch;
-	info->xmit_head &= PAGE_SIZE - 1;
-	info->xmit_cnt++;
-	local_irq_restore(flags);
-	return 1;
-}				/* cy_put_char */
-
-static void cy_flush_chars(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_flush_chars %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped
-	    || tty->hw_stopped || !info->xmit_buf)
-		return;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = channel;
-	base_addr[CyIER] |= CyTxMpty;
-	local_irq_restore(flags);
-}				/* cy_flush_chars */
-
-/* This routine gets called when tty_write has put something into
-    the write_queue.  If the port is not already transmitting stuff,
-    start it off by enabling interrupts.  The interrupt service
-    routine will then ensure that the characters are sent.  If the
-    port is already active, there is no need to kick it.
- */
-static int cy_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	int c, total = 0;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_write %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write")) {
-		return 0;
-	}
-
-	if (!info->xmit_buf) {
-		return 0;
-	}
-
-	while (1) {
-		local_irq_save(flags);
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-					  SERIAL_XMIT_SIZE - info->xmit_head));
-		if (c <= 0) {
-			local_irq_restore(flags);
-			break;
-		}
-
-		memcpy(info->xmit_buf + info->xmit_head, buf, c);
-		info->xmit_head =
-		    (info->xmit_head + c) & (SERIAL_XMIT_SIZE - 1);
-		info->xmit_cnt += c;
-		local_irq_restore(flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
-		start_xmit(info);
-	}
-	return total;
-}				/* cy_write */
-
-static int cy_write_room(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_write_room %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_write_room"))
-		return 0;
-	ret = PAGE_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-	return ret;
-}				/* cy_write_room */
-
-static int cy_chars_in_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_chars_in_buffer %s %d\n", tty->name, info->xmit_cnt);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_chars_in_buffer"))
-		return 0;
-
-	return info->xmit_cnt;
-}				/* cy_chars_in_buffer */
-
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-
-#ifdef SERIAL_DEBUG_IO
-	printk("cy_flush_buffer %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-		return;
-	local_irq_save(flags);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	local_irq_restore(flags);
-	tty_wakeup(tty);
-}				/* cy_flush_buffer */
-
-/* This routine is called by the upper-layer tty layer to signal
-   that incoming characters should be throttled or that the
-   throttle should be released.
- */
-static void cy_throttle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_THROTTLE
-	char buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-	printk("cy_throttle %s\n", tty->name);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
-		return;
-	}
-
-	if (I_IXOFF(tty)) {
-		info->x_char = STOP_CHAR(tty);
-		/* Should use the "Send Special Character" feature!!! */
-	}
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	base_addr[CyMSVR1] = 0;
-	local_irq_restore(flags);
-}				/* cy_throttle */
-
-static void cy_unthrottle(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-	unsigned long flags;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-
-#ifdef SERIAL_DEBUG_THROTTLE
-	char buf[64];
-
-	printk("throttle %s: %d....\n", tty_name(tty, buf),
-	       tty->ldisc.chars_in_buffer(tty));
-	printk("cy_unthrottle %s\n", tty->name);
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_nthrottle")) {
-		return;
-	}
-
-	if (I_IXOFF(tty)) {
-		info->x_char = START_CHAR(tty);
-		/* Should use the "Send Special Character" feature!!! */
-	}
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	base_addr[CyMSVR1] = CyRTS;
-	local_irq_restore(flags);
-}				/* cy_unthrottle */
-
-static int
-get_serial_info(struct cyclades_port *info,
-		struct serial_struct __user * retinfo)
-{
-	struct serial_struct tmp;
-
-/* CP('g'); */
-	if (!retinfo)
-		return -EFAULT;
-	memset(&tmp, 0, sizeof(tmp));
-	tmp.type = info->type;
-	tmp.line = info->line;
-	tmp.port = info->line;
-	tmp.irq = 0;
-	tmp.flags = info->flags;
-	tmp.baud_base = 0;	/*!!! */
-	tmp.close_delay = info->close_delay;
-	tmp.custom_divisor = 0;	/*!!! */
-	tmp.hub6 = 0;		/*!!! */
-	return copy_to_user(retinfo, &tmp, sizeof(*retinfo)) ? -EFAULT : 0;
-}				/* get_serial_info */
-
-static int
-set_serial_info(struct cyclades_port *info,
-		struct serial_struct __user * new_info)
-{
-	struct serial_struct new_serial;
-	struct cyclades_port old_info;
-
-/* CP('s'); */
-	if (!new_info)
-		return -EFAULT;
-	if (copy_from_user(&new_serial, new_info, sizeof(new_serial)))
-		return -EFAULT;
-	old_info = *info;
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((new_serial.close_delay != info->close_delay) ||
-		    ((new_serial.flags & ASYNC_FLAGS & ~ASYNC_USR_MASK) !=
-		     (info->flags & ASYNC_FLAGS & ~ASYNC_USR_MASK)))
-			return -EPERM;
-		info->flags = ((info->flags & ~ASYNC_USR_MASK) |
-			       (new_serial.flags & ASYNC_USR_MASK));
-		goto check_and_exit;
-	}
-
-	/*
-	 * OK, past this point, all the error checking has been done.
-	 * At this point, we start making changes.....
-	 */
-
-	info->flags = ((info->flags & ~ASYNC_FLAGS) |
-		       (new_serial.flags & ASYNC_FLAGS));
-	info->close_delay = new_serial.close_delay;
-
-check_and_exit:
-	if (info->flags & ASYNC_INITIALIZED) {
-		config_setup(info);
-		return 0;
-	}
-	return startup(info);
-}				/* set_serial_info */
-
-static int cy_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-	unsigned char status;
-
-	channel = info->line;
-
-	local_irq_save(flags);
-	base_addr[CyCAR] = (u_char) channel;
-	status = base_addr[CyMSVR1] | base_addr[CyMSVR2];
-	local_irq_restore(flags);
-
-	return ((status & CyRTS) ? TIOCM_RTS : 0)
-	    | ((status & CyDTR) ? TIOCM_DTR : 0)
-	    | ((status & CyDCD) ? TIOCM_CAR : 0)
-	    | ((status & CyDSR) ? TIOCM_DSR : 0)
-	    | ((status & CyCTS) ? TIOCM_CTS : 0);
-}				/* cy_tiocmget */
-
-static int
-cy_tiocmset(struct tty_struct *tty, struct file *file,
-	    unsigned int set, unsigned int clear)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int channel;
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-
-	channel = info->line;
-
-	if (set & TIOCM_RTS) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = CyRTS;
-		local_irq_restore(flags);
-	}
-	if (set & TIOCM_DTR) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('S');CP('2'); */
-		base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-	}
-
-	if (clear & TIOCM_RTS) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = 0;
-		local_irq_restore(flags);
-	}
-	if (clear & TIOCM_DTR) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('C');CP('2'); */
-		base_addr[CyMSVR2] = 0;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: dropping DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-	}
-
-	return 0;
-}				/* set_modem_info */
-
-static void send_break(struct cyclades_port *info, int duration)
-{				/* Let the transmit ISR take care of this (since it
-				   requires stuffing characters into the output stream).
-				 */
-	info->x_break = duration;
-	if (!info->xmit_cnt) {
-		start_xmit(info);
-	}
-}				/* send_break */
-
-static int
-get_mon_info(struct cyclades_port *info, struct cyclades_monitor __user * mon)
-{
-
-	if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
-		return -EFAULT;
-	info->mon.int_count = 0;
-	info->mon.char_count = 0;
-	info->mon.char_max = 0;
-	info->mon.char_last = 0;
-	return 0;
-}
-
-static int set_threshold(struct cyclades_port *info, unsigned long __user * arg)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long value;
-	int channel;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	channel = info->line;
-	info->cor4 &= ~CyREC_FIFO;
-	info->cor4 |= value & CyREC_FIFO;
-	base_addr[CyCOR4] = info->cor4;
-	return 0;
-}
-
-static int
-get_threshold(struct cyclades_port *info, unsigned long __user * value)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long tmp;
-
-	channel = info->line;
-
-	tmp = base_addr[CyCOR4] & CyREC_FIFO;
-	return put_user(tmp, value);
-}
-
-static int
-set_default_threshold(struct cyclades_port *info, unsigned long __user * arg)
-{
-	unsigned long value;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	info->default_threshold = value & 0x0f;
-	return 0;
-}
-
-static int
-get_default_threshold(struct cyclades_port *info, unsigned long __user * value)
-{
-	return put_user(info->default_threshold, value);
-}
-
-static int set_timeout(struct cyclades_port *info, unsigned long __user * arg)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long value;
-
-	if (get_user(value, arg))
-		return -EFAULT;
-
-	channel = info->line;
-
-	base_addr[CyRTPRL] = value & 0xff;
-	base_addr[CyRTPRH] = (value >> 8) & 0xff;
-	return 0;
-}
-
-static int get_timeout(struct cyclades_port *info, unsigned long __user * value)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	unsigned long tmp;
-
-	channel = info->line;
-
-	tmp = base_addr[CyRTPRL];
-	return put_user(tmp, value);
-}
-
-static int set_default_timeout(struct cyclades_port *info, unsigned long value)
-{
-	info->default_timeout = value & 0xff;
-	return 0;
-}
-
-static int
-get_default_timeout(struct cyclades_port *info, unsigned long __user * value)
-{
-	return put_user(info->default_timeout, value);
-}
-
-static int
-cy_ioctl(struct tty_struct *tty, struct file *file,
-	 unsigned int cmd, unsigned long arg)
-{
-	struct cyclades_port *info = tty->driver_data;
-	int ret_val = 0;
-	void __user *argp = (void __user *)arg;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg);	/* */
-#endif
-
-	tty_lock();
-
-	switch (cmd) {
-	case CYGETMON:
-		ret_val = get_mon_info(info, argp);
-		break;
-	case CYGETTHRESH:
-		ret_val = get_threshold(info, argp);
-		break;
-	case CYSETTHRESH:
-		ret_val = set_threshold(info, argp);
-		break;
-	case CYGETDEFTHRESH:
-		ret_val = get_default_threshold(info, argp);
-		break;
-	case CYSETDEFTHRESH:
-		ret_val = set_default_threshold(info, argp);
-		break;
-	case CYGETTIMEOUT:
-		ret_val = get_timeout(info, argp);
-		break;
-	case CYSETTIMEOUT:
-		ret_val = set_timeout(info, argp);
-		break;
-	case CYGETDEFTIMEOUT:
-		ret_val = get_default_timeout(info, argp);
-		break;
-	case CYSETDEFTIMEOUT:
-		ret_val = set_default_timeout(info, (unsigned long)arg);
-		break;
-	case TCSBRK:		/* SVID version: non-zero arg --> no break */
-		ret_val = tty_check_change(tty);
-		if (ret_val)
-			break;
-		tty_wait_until_sent(tty, 0);
-		if (!arg)
-			send_break(info, HZ / 4);	/* 1/4 second */
-		break;
-	case TCSBRKP:		/* support for POSIX tcsendbreak() */
-		ret_val = tty_check_change(tty);
-		if (ret_val)
-			break;
-		tty_wait_until_sent(tty, 0);
-		send_break(info, arg ? arg * (HZ / 10) : HZ / 4);
-		break;
-
-/* The following commands are incompletely implemented!!! */
-	case TIOCGSERIAL:
-		ret_val = get_serial_info(info, argp);
-		break;
-	case TIOCSSERIAL:
-		ret_val = set_serial_info(info, argp);
-		break;
-	default:
-		ret_val = -ENOIOCTLCMD;
-	}
-	tty_unlock();
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_ioctl done\n");
-#endif
-
-	return ret_val;
-}				/* cy_ioctl */
-
-static void cy_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_set_termios %s\n", tty->name);
-#endif
-
-	if (tty->termios->c_cflag == old_termios->c_cflag)
-		return;
-	config_setup(info);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->stopped = 0;
-		cy_start(tty);
-	}
-#ifdef tytso_patch_94Nov25_1726
-	if (!(old_termios->c_cflag & CLOCAL) &&
-	    (tty->termios->c_cflag & CLOCAL))
-		wake_up_interruptible(&info->open_wait);
-#endif
-}				/* cy_set_termios */
-
-static void cy_close(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-/* CP('C'); */
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_close %s\n", tty->name);
-#endif
-
-	if (!info || serial_paranoia_check(info, tty->name, "cy_close")) {
-		return;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_close %s, count = %d\n", tty->name, info->count);
-#endif
-
-	if ((tty->count == 1) && (info->count != 1)) {
-		/*
-		 * Uh, oh.  tty->count is 1, which means that the tty
-		 * structure will be freed.  Info->count should always
-		 * be one in these conditions.  If it's greater than
-		 * one, we've got real problems, since it means the
-		 * serial port won't be shutdown.
-		 */
-		printk("cy_close: bad serial port count; tty->count is 1, "
-		       "info->count is %d\n", info->count);
-		info->count = 1;
-	}
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: decrementing count to %d\n", __LINE__,
-	       info->count - 1);
-#endif
-	if (--info->count < 0) {
-		printk("cy_close: bad serial port count for ttys%d: %d\n",
-		       info->line, info->count);
-#ifdef SERIAL_DEBUG_COUNT
-		printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-		info->count = 0;
-	}
-	if (info->count)
-		return;
-	info->flags |= ASYNC_CLOSING;
-	if (info->flags & ASYNC_INITIALIZED)
-		tty_wait_until_sent(tty, 3000);	/* 30 seconds timeout */
-	shutdown(info);
-	cy_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	info->tty = NULL;
-	if (info->blocked_open) {
-		if (info->close_delay) {
-			msleep_interruptible(jiffies_to_msecs
-					     (info->close_delay));
-		}
-		wake_up_interruptible(&info->open_wait);
-	}
-	info->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_CLOSING);
-	wake_up_interruptible(&info->close_wait);
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_close done\n");
-#endif
-}				/* cy_close */
-
-/*
- * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
- */
-void cy_hangup(struct tty_struct *tty)
-{
-	struct cyclades_port *info = tty->driver_data;
-
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_hangup %s\n", tty->name);	/* */
-#endif
-
-	if (serial_paranoia_check(info, tty->name, "cy_hangup"))
-		return;
-
-	shutdown(info);
-#if 0
-	info->event = 0;
-	info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: setting count to 0\n", __LINE__);
-#endif
-	info->tty = 0;
-#endif
-	info->flags &= ~ASYNC_NORMAL_ACTIVE;
-	wake_up_interruptible(&info->open_wait);
-}				/* cy_hangup */
-
-/*
- * ------------------------------------------------------------
- * cy_open() and friends
- * ------------------------------------------------------------
- */
-
-static int
-block_til_ready(struct tty_struct *tty, struct file *filp,
-		struct cyclades_port *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	unsigned long flags;
-	int channel;
-	int retval;
-	volatile u_char *base_addr = (u_char *) BASE_ADDR;
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (info->flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&info->close_wait);
-		if (info->flags & ASYNC_HUP_NOTIFY) {
-			return -EAGAIN;
-		} else {
-			return -ERESTARTSYS;
-		}
-	}
-
-	/*
-	 * If non-blocking mode is set, then make the check up front
-	 * and then exit.
-	 */
-	if (filp->f_flags & O_NONBLOCK) {
-		info->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * cy_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&info->open_wait, &wait);
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready before block: %s, count = %d\n",
-	       tty->name, info->count);
-	/**/
-#endif
-	    info->count--;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: decrementing count to %d\n", __LINE__, info->count);
-#endif
-	info->blocked_open++;
-
-	channel = info->line;
-
-	while (1) {
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-		base_addr[CyMSVR1] = CyRTS;
-/* CP('S');CP('4'); */
-		base_addr[CyMSVR2] = CyDTR;
-#ifdef SERIAL_DEBUG_DTR
-		printk("cyc: %d: raising DTR\n", __LINE__);
-		printk("     status: 0x%x, 0x%x\n", base_addr[CyMSVR1],
-		       base_addr[CyMSVR2]);
-#endif
-		local_irq_restore(flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp)
-		    || !(info->flags & ASYNC_INITIALIZED)) {
-			if (info->flags & ASYNC_HUP_NOTIFY) {
-				retval = -EAGAIN;
-			} else {
-				retval = -ERESTARTSYS;
-			}
-			break;
-		}
-		local_irq_save(flags);
-		base_addr[CyCAR] = (u_char) channel;
-/* CP('L');CP1(1 && C_CLOCAL(tty)); CP1(1 && (base_addr[CyMSVR1] & CyDCD) ); */
-		if (!(info->flags & ASYNC_CLOSING)
-		    && (C_CLOCAL(tty)
-			|| (base_addr[CyMSVR1] & CyDCD))) {
-			local_irq_restore(flags);
-			break;
-		}
-		local_irq_restore(flags);
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-#ifdef SERIAL_DEBUG_OPEN
-		printk("block_til_ready blocking: %s, count = %d\n",
-		       tty->name, info->count);
-		/**/
-#endif
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&info->open_wait, &wait);
-	if (!tty_hung_up_p(filp)) {
-		info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-		printk("cyc: %d: incrementing count to %d\n", __LINE__,
-		       info->count);
-#endif
-	}
-	info->blocked_open--;
-#ifdef SERIAL_DEBUG_OPEN
-	printk("block_til_ready after blocking: %s, count = %d\n",
-	       tty->name, info->count);
-	/**/
-#endif
-	    if (retval)
-		return retval;
-	info->flags |= ASYNC_NORMAL_ACTIVE;
-	return 0;
-}				/* block_til_ready */
-
-/*
- * This routine is called whenever a serial port is opened.  It
- * performs the serial-specific initialization for the tty structure.
- */
-int cy_open(struct tty_struct *tty, struct file *filp)
-{
-	struct cyclades_port *info;
-	int retval, line;
-
-/* CP('O'); */
-	line = tty->index;
-	if ((line < 0) || (NR_PORTS <= line)) {
-		return -ENODEV;
-	}
-	info = &cy_port[line];
-	if (info->line < 0) {
-		return -ENODEV;
-	}
-#ifdef SERIAL_DEBUG_OTHER
-	printk("cy_open %s\n", tty->name);	/* */
-#endif
-	if (serial_paranoia_check(info, tty->name, "cy_open")) {
-		return -ENODEV;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open %s, count = %d\n", tty->name, info->count);
-	/**/
-#endif
-	    info->count++;
-#ifdef SERIAL_DEBUG_COUNT
-	printk("cyc: %d: incrementing count to %d\n", __LINE__, info->count);
-#endif
-	tty->driver_data = info;
-	info->tty = tty;
-
-	/*
-	 * Start up serial port
-	 */
-	retval = startup(info);
-	if (retval) {
-		return retval;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-#ifdef SERIAL_DEBUG_OPEN
-		printk("cy_open returning after block_til_ready with %d\n",
-		       retval);
-#endif
-		return retval;
-	}
-#ifdef SERIAL_DEBUG_OPEN
-	printk("cy_open done\n");
-	/**/
-#endif
-	    return 0;
-}				/* cy_open */
-
-/*
- * ---------------------------------------------------------------------
- * serial167_init() and friends
- *
- * serial167_init() is called at boot-time to initialize the serial driver.
- * ---------------------------------------------------------------------
- */
-
-/*
- * This routine prints out the appropriate serial driver version
- * number, and identifies which options were configured into this
- * driver.
- */
-static void show_version(void)
-{
-	printk("MVME166/167 cd2401 driver\n");
-}				/* show_version */
-
-/* initialize chips on card -- return number of valid
-   chips (which is number of ports/4) */
-
-/*
- * This initialises the hardware to a reasonable state.  It should
- * probe the chip first so as to copy 166-Bug setup as a default for
- * port 0.  It initialises CMR to CyASYNC; that is never done again, so
- * as to limit the number of CyINIT_CHAN commands in normal running.
- *
- * ... I wonder what I should do if this fails ...
- */
-
-void mvme167_serial_console_setup(int cflag)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int ch;
-	u_char spd;
-	u_char rcor, rbpr, badspeed = 0;
-	unsigned long flags;
-
-	local_irq_save(flags);
-
-	/*
-	 * First probe channel zero of the chip, to see what speed has
-	 * been selected.
-	 */
-
-	base_addr[CyCAR] = 0;
-
-	rcor = base_addr[CyRCOR] << 5;
-	rbpr = base_addr[CyRBPR];
-
-	for (spd = 0; spd < sizeof(baud_bpr); spd++)
-		if (rbpr == baud_bpr[spd] && rcor == baud_co[spd])
-			break;
-	if (spd >= sizeof(baud_bpr)) {
-		spd = 14;	/* 19200 */
-		badspeed = 1;	/* Failed to identify speed */
-	}
-	initial_console_speed = spd;
-
-	/* OK, we have chosen a speed, now reset and reinitialise */
-
-	my_udelay(20000L);	/* Allow time for any active o/p to complete */
-	if (base_addr[CyCCR] != 0x00) {
-		local_irq_restore(flags);
-		/* printk(" chip is never idle (CCR != 0)\n"); */
-		return;
-	}
-
-	base_addr[CyCCR] = CyCHIP_RESET;	/* Reset the chip */
-	my_udelay(1000L);
-
-	if (base_addr[CyGFRCR] == 0x00) {
-		local_irq_restore(flags);
-		/* printk(" chip is not responding (GFRCR stayed 0)\n"); */
-		return;
-	}
-
-	/*
-	 * System clock is 20Mhz, divided by 2048, so divide by 10 for a 1.0ms
-	 * tick
-	 */
-
-	base_addr[CyTPR] = 10;
-
-	base_addr[CyPILR1] = 0x01;	/* Interrupt level for modem change */
-	base_addr[CyPILR2] = 0x02;	/* Interrupt level for tx ints */
-	base_addr[CyPILR3] = 0x03;	/* Interrupt level for rx ints */
-
-	/*
-	 * Attempt to set up all channels to something reasonable, and
-	 * bang out a INIT_CHAN command.  We should then be able to limit
-	 * the amount of fiddling we have to do in normal running.
-	 */
-
-	for (ch = 3; ch >= 0; ch--) {
-		base_addr[CyCAR] = (u_char) ch;
-		base_addr[CyIER] = 0;
-		base_addr[CyCMR] = CyASYNC;
-		base_addr[CyLICR] = (u_char) ch << 2;
-		base_addr[CyLIVR] = 0x5c;
-		base_addr[CyTCOR] = baud_co[spd];
-		base_addr[CyTBPR] = baud_bpr[spd];
-		base_addr[CyRCOR] = baud_co[spd] >> 5;
-		base_addr[CyRBPR] = baud_bpr[spd];
-		base_addr[CySCHR1] = 'Q' & 0x1f;
-		base_addr[CySCHR2] = 'X' & 0x1f;
-		base_addr[CySCRL] = 0;
-		base_addr[CySCRH] = 0;
-		base_addr[CyCOR1] = Cy_8_BITS | CyPARITY_NONE;
-		base_addr[CyCOR2] = 0;
-		base_addr[CyCOR3] = Cy_1_STOP;
-		base_addr[CyCOR4] = baud_cor4[spd];
-		base_addr[CyCOR5] = 0;
-		base_addr[CyCOR6] = 0;
-		base_addr[CyCOR7] = 0;
-		base_addr[CyRTPRL] = 2;
-		base_addr[CyRTPRH] = 0;
-		base_addr[CyMSVR1] = 0;
-		base_addr[CyMSVR2] = 0;
-		write_cy_cmd(base_addr, CyINIT_CHAN | CyDIS_RCVR | CyDIS_XMTR);
-	}
-
-	/*
-	 * Now do specials for channel zero....
-	 */
-
-	base_addr[CyMSVR1] = CyRTS;
-	base_addr[CyMSVR2] = CyDTR;
-	base_addr[CyIER] = CyRxData;
-	write_cy_cmd(base_addr, CyENB_RCVR | CyENB_XMTR);
-
-	local_irq_restore(flags);
-
-	my_udelay(20000L);	/* Let it all settle down */
-
-	printk("CD2401 initialised,  chip is rev 0x%02x\n", base_addr[CyGFRCR]);
-	if (badspeed)
-		printk
-		    ("  WARNING:  Failed to identify line speed, rcor=%02x,rbpr=%02x\n",
-		     rcor >> 5, rbpr);
-}				/* serial_console_init */
-
-static const struct tty_operations cy_ops = {
-	.open = cy_open,
-	.close = cy_close,
-	.write = cy_write,
-	.put_char = cy_put_char,
-	.flush_chars = cy_flush_chars,
-	.write_room = cy_write_room,
-	.chars_in_buffer = cy_chars_in_buffer,
-	.flush_buffer = cy_flush_buffer,
-	.ioctl = cy_ioctl,
-	.throttle = cy_throttle,
-	.unthrottle = cy_unthrottle,
-	.set_termios = cy_set_termios,
-	.stop = cy_stop,
-	.start = cy_start,
-	.hangup = cy_hangup,
-	.tiocmget = cy_tiocmget,
-	.tiocmset = cy_tiocmset,
-};
-
-/* The serial driver boot-time initialization code!
-    Hardware I/O ports are mapped to character special devices on a
-    first found, first allocated manner.  That is, this code searches
-    for Cyclom cards in the system.  As each is found, it is probed
-    to discover how many chips (and thus how many ports) are present.
-    These ports are mapped to the tty ports 64 and upward in monotonic
-    fashion.  If an 8-port card is replaced with a 16-port card, the
-    port mapping on a following card will shift.
-
-    This approach is different from what is used in the other serial
-    device driver because the Cyclom is more properly a multiplexer,
-    not just an aggregation of serial ports on one card.
-
-    If there are more cards with more ports than have been statically
-    allocated above, a warning is printed and the extra ports are ignored.
- */
-static int __init serial167_init(void)
-{
-	struct cyclades_port *info;
-	int ret = 0;
-	int good_ports = 0;
-	int port_num = 0;
-	int index;
-	int DefSpeed;
-#ifdef notyet
-	struct sigaction sa;
-#endif
-
-	if (!(mvme16x_config & MVME16x_CONFIG_GOT_CD2401))
-		return 0;
-
-	cy_serial_driver = alloc_tty_driver(NR_PORTS);
-	if (!cy_serial_driver)
-		return -ENOMEM;
-
-#if 0
-	scrn[1] = '\0';
-#endif
-
-	show_version();
-
-	/* Has "console=0,9600n8" been used in bootinfo to change speed? */
-	if (serial_console_cflag)
-		DefSpeed = serial_console_cflag & 0017;
-	else {
-		DefSpeed = initial_console_speed;
-		serial_console_info = &cy_port[0];
-		serial_console_cflag = DefSpeed | CS8;
-#if 0
-		serial_console = 64;	/*callout_driver.minor_start */
-#endif
-	}
-
-	/* Initialize the tty_driver structure */
-
-	cy_serial_driver->owner = THIS_MODULE;
-	cy_serial_driver->name = "ttyS";
-	cy_serial_driver->major = TTY_MAJOR;
-	cy_serial_driver->minor_start = 64;
-	cy_serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	cy_serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	cy_serial_driver->init_termios = tty_std_termios;
-	cy_serial_driver->init_termios.c_cflag =
-	    B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	cy_serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(cy_serial_driver, &cy_ops);
-
-	ret = tty_register_driver(cy_serial_driver);
-	if (ret) {
-		printk(KERN_ERR "Couldn't register MVME166/7 serial driver\n");
-		put_tty_driver(cy_serial_driver);
-		return ret;
-	}
-
-	port_num = 0;
-	info = cy_port;
-	for (index = 0; index < 1; index++) {
-
-		good_ports = 4;
-
-		if (port_num < NR_PORTS) {
-			while (good_ports-- && port_num < NR_PORTS) {
-		/*** initialize port ***/
-				info->magic = CYCLADES_MAGIC;
-				info->type = PORT_CIRRUS;
-				info->card = index;
-				info->line = port_num;
-				info->flags = STD_COM_FLAGS;
-				info->tty = NULL;
-				info->xmit_fifo_size = 12;
-				info->cor1 = CyPARITY_NONE | Cy_8_BITS;
-				info->cor2 = CyETC;
-				info->cor3 = Cy_1_STOP;
-				info->cor4 = 0x08;	/* _very_ small receive threshold */
-				info->cor5 = 0;
-				info->cor6 = 0;
-				info->cor7 = 0;
-				info->tbpr = baud_bpr[DefSpeed];	/* Tx BPR */
-				info->tco = baud_co[DefSpeed];	/* Tx CO */
-				info->rbpr = baud_bpr[DefSpeed];	/* Rx BPR */
-				info->rco = baud_co[DefSpeed] >> 5;	/* Rx CO */
-				info->close_delay = 0;
-				info->x_char = 0;
-				info->count = 0;
-#ifdef SERIAL_DEBUG_COUNT
-				printk("cyc: %d: setting count to 0\n",
-				       __LINE__);
-#endif
-				info->blocked_open = 0;
-				info->default_threshold = 0;
-				info->default_timeout = 0;
-				init_waitqueue_head(&info->open_wait);
-				init_waitqueue_head(&info->close_wait);
-				/* info->session */
-				/* info->pgrp */
-/*** !!!!!!!! this may expose new bugs !!!!!!!!! *********/
-				info->read_status_mask =
-				    CyTIMEOUT | CySPECHAR | CyBREAK | CyPARITY |
-				    CyFRAME | CyOVERRUN;
-				/* info->timeout */
-
-				printk("ttyS%d ", info->line);
-				port_num++;
-				info++;
-				if (!(port_num & 7)) {
-					printk("\n               ");
-				}
-			}
-		}
-		printk("\n");
-	}
-	while (port_num < NR_PORTS) {
-		info->line = -1;
-		port_num++;
-		info++;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt, 0,
-			  "cd2401_errors", cd2401_rxerr_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_errors IRQ");
-		goto cleanup_serial_driver;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt, 0,
-			  "cd2401_modem", cd2401_modem_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_modem IRQ");
-		goto cleanup_irq_cd2401_errors;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt, 0,
-			  "cd2401_txints", cd2401_tx_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_txints IRQ");
-		goto cleanup_irq_cd2401_modem;
-	}
-
-	ret = request_irq(MVME167_IRQ_SER_RX, cd2401_rx_interrupt, 0,
-			  "cd2401_rxints", cd2401_rx_interrupt);
-	if (ret) {
-		printk(KERN_ERR "Could't get cd2401_rxints IRQ");
-		goto cleanup_irq_cd2401_txints;
-	}
-
-	/* Now we have registered the interrupt handlers, allow the interrupts */
-
-	pcc2chip[PccSCCMICR] = 0x15;	/* Serial ints are level 5 */
-	pcc2chip[PccSCCTICR] = 0x15;
-	pcc2chip[PccSCCRICR] = 0x15;
-
-	pcc2chip[PccIMLR] = 3;	/* Allow PCC2 ints above 3!? */
-
-	return 0;
-cleanup_irq_cd2401_txints:
-	free_irq(MVME167_IRQ_SER_TX, cd2401_tx_interrupt);
-cleanup_irq_cd2401_modem:
-	free_irq(MVME167_IRQ_SER_MODEM, cd2401_modem_interrupt);
-cleanup_irq_cd2401_errors:
-	free_irq(MVME167_IRQ_SER_ERR, cd2401_rxerr_interrupt);
-cleanup_serial_driver:
-	if (tty_unregister_driver(cy_serial_driver))
-		printk(KERN_ERR
-		       "Couldn't unregister MVME166/7 serial driver\n");
-	put_tty_driver(cy_serial_driver);
-	return ret;
-}				/* serial167_init */
-
-module_init(serial167_init);
-
-#ifdef CYCLOM_SHOW_STATUS
-static void show_status(int line_num)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	int channel;
-	struct cyclades_port *info;
-	unsigned long flags;
-
-	info = &cy_port[line_num];
-	channel = info->line;
-	printk("  channel %d\n", channel);
-	/**/ printk(" cy_port\n");
-	printk("  card line flags = %d %d %x\n",
-	       info->card, info->line, info->flags);
-	printk
-	    ("  *tty read_status_mask timeout xmit_fifo_size = %lx %x %x %x\n",
-	     (long)info->tty, info->read_status_mask, info->timeout,
-	     info->xmit_fifo_size);
-	printk("  cor1,cor2,cor3,cor4,cor5,cor6,cor7 = %x %x %x %x %x %x %x\n",
-	       info->cor1, info->cor2, info->cor3, info->cor4, info->cor5,
-	       info->cor6, info->cor7);
-	printk("  tbpr,tco,rbpr,rco = %d %d %d %d\n", info->tbpr, info->tco,
-	       info->rbpr, info->rco);
-	printk("  close_delay event count = %d %d %d\n", info->close_delay,
-	       info->event, info->count);
-	printk("  x_char blocked_open = %x %x\n", info->x_char,
-	       info->blocked_open);
-	printk("  open_wait = %lx %lx %lx\n", (long)info->open_wait);
-
-	local_irq_save(flags);
-
-/* Global Registers */
-
-	printk(" CyGFRCR %x\n", base_addr[CyGFRCR]);
-	printk(" CyCAR %x\n", base_addr[CyCAR]);
-	printk(" CyRISR %x\n", base_addr[CyRISR]);
-	printk(" CyTISR %x\n", base_addr[CyTISR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
-	printk(" CyRIR %x\n", base_addr[CyRIR]);
-	printk(" CyTIR %x\n", base_addr[CyTIR]);
-	printk(" CyMIR %x\n", base_addr[CyMIR]);
-	printk(" CyTPR %x\n", base_addr[CyTPR]);
-
-	base_addr[CyCAR] = (u_char) channel;
-
-/* Virtual Registers */
-
-#if 0
-	printk(" CyRIVR %x\n", base_addr[CyRIVR]);
-	printk(" CyTIVR %x\n", base_addr[CyTIVR]);
-	printk(" CyMIVR %x\n", base_addr[CyMIVR]);
-	printk(" CyMISR %x\n", base_addr[CyMISR]);
-#endif
-
-/* Channel Registers */
-
-	printk(" CyCCR %x\n", base_addr[CyCCR]);
-	printk(" CyIER %x\n", base_addr[CyIER]);
-	printk(" CyCOR1 %x\n", base_addr[CyCOR1]);
-	printk(" CyCOR2 %x\n", base_addr[CyCOR2]);
-	printk(" CyCOR3 %x\n", base_addr[CyCOR3]);
-	printk(" CyCOR4 %x\n", base_addr[CyCOR4]);
-	printk(" CyCOR5 %x\n", base_addr[CyCOR5]);
-#if 0
-	printk(" CyCCSR %x\n", base_addr[CyCCSR]);
-	printk(" CyRDCR %x\n", base_addr[CyRDCR]);
-#endif
-	printk(" CySCHR1 %x\n", base_addr[CySCHR1]);
-	printk(" CySCHR2 %x\n", base_addr[CySCHR2]);
-#if 0
-	printk(" CySCHR3 %x\n", base_addr[CySCHR3]);
-	printk(" CySCHR4 %x\n", base_addr[CySCHR4]);
-	printk(" CySCRL %x\n", base_addr[CySCRL]);
-	printk(" CySCRH %x\n", base_addr[CySCRH]);
-	printk(" CyLNC %x\n", base_addr[CyLNC]);
-	printk(" CyMCOR1 %x\n", base_addr[CyMCOR1]);
-	printk(" CyMCOR2 %x\n", base_addr[CyMCOR2]);
-#endif
-	printk(" CyRTPRL %x\n", base_addr[CyRTPRL]);
-	printk(" CyRTPRH %x\n", base_addr[CyRTPRH]);
-	printk(" CyMSVR1 %x\n", base_addr[CyMSVR1]);
-	printk(" CyMSVR2 %x\n", base_addr[CyMSVR2]);
-	printk(" CyRBPR %x\n", base_addr[CyRBPR]);
-	printk(" CyRCOR %x\n", base_addr[CyRCOR]);
-	printk(" CyTBPR %x\n", base_addr[CyTBPR]);
-	printk(" CyTCOR %x\n", base_addr[CyTCOR]);
-
-	local_irq_restore(flags);
-}				/* show_status */
-#endif
-
-#if 0
-/* Dummy routine in mvme16x/config.c for now */
-
-/* Serial console setup. Called from linux/init/main.c */
-
-void console_setup(char *str, int *ints)
-{
-	char *s;
-	int baud, bits, parity;
-	int cflag = 0;
-
-	/* Sanity check. */
-	if (ints[0] > 3 || ints[1] > 3)
-		return;
-
-	/* Get baud, bits and parity */
-	baud = 2400;
-	bits = 8;
-	parity = 'n';
-	if (ints[2])
-		baud = ints[2];
-	if ((s = strchr(str, ','))) {
-		do {
-			s++;
-		} while (*s >= '0' && *s <= '9');
-		if (*s)
-			parity = *s++;
-		if (*s)
-			bits = *s - '0';
-	}
-
-	/* Now construct a cflag setting. */
-	switch (baud) {
-	case 1200:
-		cflag |= B1200;
-		break;
-	case 9600:
-		cflag |= B9600;
-		break;
-	case 19200:
-		cflag |= B19200;
-		break;
-	case 38400:
-		cflag |= B38400;
-		break;
-	case 2400:
-	default:
-		cflag |= B2400;
-		break;
-	}
-	switch (bits) {
-	case 7:
-		cflag |= CS7;
-		break;
-	default:
-	case 8:
-		cflag |= CS8;
-		break;
-	}
-	switch (parity) {
-	case 'o':
-	case 'O':
-		cflag |= PARODD;
-		break;
-	case 'e':
-	case 'E':
-		cflag |= PARENB;
-		break;
-	}
-
-	serial_console_info = &cy_port[ints[1]];
-	serial_console_cflag = cflag;
-	serial_console = ints[1] + 64;	/*callout_driver.minor_start */
-}
-#endif
-
-/*
- * The following is probably out of date for 2.1.x serial console stuff.
- *
- * The console is registered early on from arch/m68k/kernel/setup.c, and
- * it therefore relies on the chip being setup correctly by 166-Bug.  This
- * seems reasonable, as the serial port has been used to invoke the system
- * boot.  It also means that this function must not rely on any data
- * initialisation performed by serial167_init() etc.
- *
- * Of course, once the console has been registered, we had better ensure
- * that serial167_init() doesn't leave the chip non-functional.
- *
- * The console must be locked when we get here.
- */
-
-void serial167_console_write(struct console *co, const char *str,
-			     unsigned count)
-{
-	volatile unsigned char *base_addr = (u_char *) BASE_ADDR;
-	unsigned long flags;
-	volatile u_char sink;
-	u_char ier;
-	int port;
-	u_char do_lf = 0;
-	int i = 0;
-
-	local_irq_save(flags);
-
-	/* Ensure transmitter is enabled! */
-
-	port = 0;
-	base_addr[CyCAR] = (u_char) port;
-	while (base_addr[CyCCR])
-		;
-	base_addr[CyCCR] = CyENB_XMTR;
-
-	ier = base_addr[CyIER];
-	base_addr[CyIER] = CyTxMpty;
-
-	while (1) {
-		if (pcc2chip[PccSCCTICR] & 0x20) {
-			/* We have a Tx int. Acknowledge it */
-			sink = pcc2chip[PccTPIACKR];
-			if ((base_addr[CyLICR] >> 2) == port) {
-				if (i == count) {
-					/* Last char of string is now output */
-					base_addr[CyTEOIR] = CyNOTRANS;
-					break;
-				}
-				if (do_lf) {
-					base_addr[CyTDR] = '\n';
-					str++;
-					i++;
-					do_lf = 0;
-				} else if (*str == '\n') {
-					base_addr[CyTDR] = '\r';
-					do_lf = 1;
-				} else {
-					base_addr[CyTDR] = *str++;
-					i++;
-				}
-				base_addr[CyTEOIR] = 0;
-			} else
-				base_addr[CyTEOIR] = CyNOTRANS;
-		}
-	}
-
-	base_addr[CyIER] = ier;
-
-	local_irq_restore(flags);
-}
-
-static struct tty_driver *serial167_console_device(struct console *c,
-						   int *index)
-{
-	*index = c->index;
-	return cy_serial_driver;
-}
-
-static struct console sercons = {
-	.name = "ttyS",
-	.write = serial167_console_write,
-	.device = serial167_console_device,
-	.flags = CON_PRINTBUFFER,
-	.index = -1,
-};
-
-static int __init serial167_console_init(void)
-{
-	if (vme_brdtype == VME_TYPE_MVME166 ||
-	    vme_brdtype == VME_TYPE_MVME167 ||
-	    vme_brdtype == VME_TYPE_MVME177) {
-		mvme167_serial_console_setup(0);
-		register_console(&sercons);
-	}
-	return 0;
-}
-
-console_initcall(serial167_console_init);
-
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/char/sonypi.c linux-libre-2.6.39-gnu/drivers/char/sonypi.c
--- linux-libre-2.6.38-gnu/drivers/char/sonypi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/sonypi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1241,7 +1241,7 @@
 	while (check_ioport && check->port1) {
 		if (!request_region(check->port1,
 				   sonypi_device.region_size,
-				   "Sony Programable I/O Device Check")) {
+				   "Sony Programmable I/O Device Check")) {
 			printk(KERN_ERR "sonypi: ioport 0x%.4x busy, using sony-laptop? "
 					"if not use check_ioport=0\n",
 					check->port1);
@@ -1255,7 +1255,7 @@
 
 		if (request_region(ioport_list->port1,
 				   sonypi_device.region_size,
-				   "Sony Programable I/O Device")) {
+				   "Sony Programmable I/O Device")) {
 			dev->ioport1 = ioport_list->port1;
 			dev->ioport2 = ioport_list->port2;
 			return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/char/specialix.c linux-libre-2.6.39-gnu/drivers/char/specialix.c
--- linux-libre-2.6.38-gnu/drivers/char/specialix.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/specialix.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2368 +0,0 @@
-/*
- *      specialix.c  -- specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997  Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support. But please read the documentation (specialix.txt)
- *      first.
- *
- *      This driver was developped in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- *      This code is firmly based on the riscom/8 serial driver,
- *      written by Dmitry Gorodchanin. The specialix IO8+ card
- *      programming information was obtained from the CL-CD1865 Data
- *      Book, and Specialix document number 6200059: IO8+ Hardware
- *      Functional Specification.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the 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.
- *
- * Revision history:
- *
- * Revision 1.0:  April 1st 1997.
- *                Initial release for alpha testing.
- * Revision 1.1:  April 14th 1997.
- *                Incorporated Richard Hudsons suggestions,
- *                removed some debugging printk's.
- * Revision 1.2:  April 15th 1997.
- *                Ported to 2.1.x kernels.
- * Revision 1.3:  April 17th 1997
- *                Backported to 2.0. (Compatibility macros).
- * Revision 1.4:  April 18th 1997
- *                Fixed DTR/RTS bug that caused the card to indicate
- *                "don't send data" to a modem after the password prompt.
- *                Fixed bug for premature (fake) interrupts.
- * Revision 1.5:  April 19th 1997
- *                fixed a minor typo in the header file, cleanup a little.
- *                performance warnings are now MAXed at once per minute.
- * Revision 1.6:  May 23 1997
- *                Changed the specialix=... format to include interrupt.
- * Revision 1.7:  May 27 1997
- *                Made many more debug printk's a compile time option.
- * Revision 1.8:  Jul 1  1997
- *                port to linux-2.1.43 kernel.
- * Revision 1.9:  Oct 9  1998
- *                Added stuff for the IO8+/PCI version.
- * Revision 1.10: Oct 22  1999 / Jan 21 2000.
- *                Added stuff for setserial.
- *                Nicolas Mailhot (Nicolas.Mailhot@email.enst.fr)
- *
- */
-
-#define VERSION "1.11"
-
-
-/*
- * There is a bunch of documentation about the card, jumpers, config
- * settings, restrictions, cables, device names and numbers in
- * Documentation/serial/specialix.txt
- */
-
-#include <linux/module.h>
-
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/pci.h>
-#include <linux/init.h>
-#include <linux/uaccess.h>
-#include <linux/gfp.h>
-
-#include "specialix_io8.h"
-#include "cd1865.h"
-
-
-/*
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile...
-*/
-#define DEBUG
-
-static int sx_debug;
-static int sx_rxfifo = SPECIALIX_RXFIFO;
-static int sx_rtscts;
-
-#ifdef DEBUG
-#define dprintk(f, str...) if (sx_debug & f) printk(str)
-#else
-#define dprintk(f, str...) /* nothing */
-#endif
-
-#define SX_DEBUG_FLOW    0x0001
-#define SX_DEBUG_DATA    0x0002
-#define SX_DEBUG_PROBE   0x0004
-#define SX_DEBUG_CHAN    0x0008
-#define SX_DEBUG_INIT    0x0010
-#define SX_DEBUG_RX      0x0020
-#define SX_DEBUG_TX      0x0040
-#define SX_DEBUG_IRQ     0x0080
-#define SX_DEBUG_OPEN    0x0100
-#define SX_DEBUG_TERMIOS 0x0200
-#define SX_DEBUG_SIGNALS 0x0400
-#define SX_DEBUG_FIFO    0x0800
-
-
-#define func_enter() dprintk(SX_DEBUG_FLOW, "io8: enter %s\n", __func__)
-#define func_exit()  dprintk(SX_DEBUG_FLOW, "io8: exit  %s\n", __func__)
-
-
-/* Configurable options: */
-
-/* Am I paranoid or not ? ;-) */
-#define SPECIALIX_PARANOIA_CHECK
-
-/*
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#undef SX_REPORT_FIFO
-#undef SX_REPORT_OVERRUN
-
-
-
-
-#define SPECIALIX_LEGAL_FLAGS \
-	(ASYNC_HUP_NOTIFY   | ASYNC_SAK          | ASYNC_SPLIT_TERMIOS   | \
-	 ASYNC_SPD_HI       | ASYNC_SPEED_VHI    | ASYNC_SESSION_LOCKOUT | \
-	 ASYNC_PGRP_LOCKOUT | ASYNC_CALLOUT_NOHUP)
-
-static struct tty_driver *specialix_driver;
-
-static struct specialix_board sx_board[SX_NBOARD] =  {
-	{ 0, SX_IOBASE1,  9, },
-	{ 0, SX_IOBASE2, 11, },
-	{ 0, SX_IOBASE3, 12, },
-	{ 0, SX_IOBASE4, 15, },
-};
-
-static struct specialix_port sx_port[SX_NBOARD * SX_NPORT];
-
-
-static int sx_paranoia_check(struct specialix_port const *port,
-				    char *name, const char *routine)
-{
-#ifdef SPECIALIX_PARANOIA_CHECK
-	static const char *badmagic = KERN_ERR
-	  "sx: Warning: bad specialix port magic number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR
-	  "sx: Warning: null specialix port for device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != SPECIALIX_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#endif
-	return 0;
-}
-
-
-/*
- *
- *  Service functions for specialix IO8+ driver.
- *
- */
-
-/* Get board number from pointer */
-static inline int board_No(struct specialix_board *bp)
-{
-	return bp - sx_board;
-}
-
-
-/* Get port number from pointer */
-static inline int port_No(struct specialix_port const *port)
-{
-	return SX_PORT(port - sx_port);
-}
-
-
-/* Get pointer to board from pointer to port */
-static inline struct specialix_board *port_Board(
-					struct specialix_port const *port)
-{
-	return &sx_board[SX_BOARD(port - sx_port)];
-}
-
-
-/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in(struct specialix_board *bp,
-							unsigned short reg)
-{
-	bp->reg = reg | 0x80;
-	outb(reg | 0x80, bp->base + SX_ADDR_REG);
-	return inb(bp->base + SX_DATA_REG);
-}
-
-
-/* Output Byte to CL CD186x register */
-static inline void sx_out(struct specialix_board *bp, unsigned short reg,
-			  unsigned char val)
-{
-	bp->reg = reg | 0x80;
-	outb(reg | 0x80, bp->base + SX_ADDR_REG);
-	outb(val, bp->base + SX_DATA_REG);
-}
-
-
-/* Input Byte from CL CD186x register */
-static inline unsigned char sx_in_off(struct specialix_board *bp,
-				unsigned short reg)
-{
-	bp->reg = reg;
-	outb(reg, bp->base + SX_ADDR_REG);
-	return inb(bp->base + SX_DATA_REG);
-}
-
-
-/* Output Byte to CL CD186x register */
-static inline void sx_out_off(struct specialix_board  *bp,
-				unsigned short reg, unsigned char val)
-{
-	bp->reg = reg;
-	outb(reg, bp->base + SX_ADDR_REG);
-	outb(val, bp->base + SX_DATA_REG);
-}
-
-
-/* Wait for Channel Command Register ready */
-static void sx_wait_CCR(struct specialix_board  *bp)
-{
-	unsigned long delay, flags;
-	unsigned char ccr;
-
-	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
-		spin_lock_irqsave(&bp->lock, flags);
-		ccr = sx_in(bp, CD186x_CCR);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		if (!ccr)
-			return;
-		udelay(1);
-	}
-
-	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-
-/* Wait for Channel Command Register ready */
-static void sx_wait_CCR_off(struct specialix_board  *bp)
-{
-	unsigned long delay;
-	unsigned char crr;
-	unsigned long flags;
-
-	for (delay = SX_CCR_TIMEOUT; delay; delay--) {
-		spin_lock_irqsave(&bp->lock, flags);
-		crr = sx_in_off(bp, CD186x_CCR);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		if (!crr)
-			return;
-		udelay(1);
-	}
-
-	printk(KERN_ERR "sx%d: Timeout waiting for CCR.\n", board_No(bp));
-}
-
-
-/*
- *  specialix IO8+ IO range functions.
- */
-
-static int sx_request_io_range(struct specialix_board *bp)
-{
-	return request_region(bp->base,
-		bp->flags & SX_BOARD_IS_PCI ? SX_PCI_IO_SPACE : SX_IO_SPACE,
-		"specialix IO8+") == NULL;
-}
-
-
-static void sx_release_io_range(struct specialix_board *bp)
-{
-	release_region(bp->base, bp->flags & SX_BOARD_IS_PCI ?
-					SX_PCI_IO_SPACE : SX_IO_SPACE);
-}
-
-
-/* Set the IRQ using the RTS lines that run to the PAL on the board.... */
-static int sx_set_irq(struct specialix_board *bp)
-{
-	int virq;
-	int i;
-	unsigned long flags;
-
-	if (bp->flags & SX_BOARD_IS_PCI)
-		return 1;
-	switch (bp->irq) {
-	/* In the same order as in the docs... */
-	case 15:
-		virq = 0;
-		break;
-	case 12:
-		virq = 1;
-		break;
-	case 11:
-		virq = 2;
-		break;
-	case 9:
-		virq = 3;
-		break;
-	default:printk(KERN_ERR
-			    "Speclialix: cannot set irq to %d.\n", bp->irq);
-		return 0;
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	for (i = 0; i < 2; i++) {
-		sx_out(bp, CD186x_CAR, i);
-		sx_out(bp, CD186x_MSVRTS, ((virq >> i) & 0x1)? MSVR_RTS:0);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	return 1;
-}
-
-
-/* Reset and setup CD186x chip */
-static int sx_init_CD186x(struct specialix_board  *bp)
-{
-	unsigned long flags;
-	int scaler;
-	int rv = 1;
-
-	func_enter();
-	sx_wait_CCR_off(bp);			   /* Wait for CCR ready        */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out_off(bp, CD186x_CCR, CCR_HARDRESET);      /* Reset CD186x chip          */
-	spin_unlock_irqrestore(&bp->lock, flags);
-	msleep(50);					/* Delay 0.05 sec            */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out_off(bp, CD186x_GIVR, SX_ID);             /* Set ID for this chip      */
-	sx_out_off(bp, CD186x_GICR, 0);                 /* Clear all bits            */
-	sx_out_off(bp, CD186x_PILR1, SX_ACK_MINT);      /* Prio for modem intr       */
-	sx_out_off(bp, CD186x_PILR2, SX_ACK_TINT);      /* Prio for transmitter intr */
-	sx_out_off(bp, CD186x_PILR3, SX_ACK_RINT);      /* Prio for receiver intr    */
-	/* Set RegAckEn */
-	sx_out_off(bp, CD186x_SRCR, sx_in(bp, CD186x_SRCR) | SRCR_REGACKEN);
-
-	/* Setting up prescaler. We need 4 ticks per 1 ms */
-	scaler =  SX_OSCFREQ/SPECIALIX_TPS;
-
-	sx_out_off(bp, CD186x_PPRH, scaler >> 8);
-	sx_out_off(bp, CD186x_PPRL, scaler & 0xff);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	if (!sx_set_irq(bp)) {
-		/* Figure out how to pass this along... */
-		printk(KERN_ERR "Cannot set irq to %d.\n", bp->irq);
-		rv = 0;
-	}
-
-	func_exit();
-	return rv;
-}
-
-
-static int read_cross_byte(struct specialix_board *bp, int reg, int bit)
-{
-	int i;
-	int t;
-	unsigned long flags;
-
-	spin_lock_irqsave(&bp->lock, flags);
-	for (i = 0, t = 0; i < 8; i++) {
-		sx_out_off(bp, CD186x_CAR, i);
-		if (sx_in_off(bp, reg) & bit)
-			t |= 1 << i;
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	return t;
-}
-
-
-/* Main probing routine, also sets irq. */
-static int sx_probe(struct specialix_board *bp)
-{
-	unsigned char val1, val2;
-	int rev;
-	int chip;
-
-	func_enter();
-
-	if (sx_request_io_range(bp)) {
-		func_exit();
-		return 1;
-	}
-
-	/* Are the I/O ports here ? */
-	sx_out_off(bp, CD186x_PPRL, 0x5a);
-	udelay(1);
-	val1 = sx_in_off(bp, CD186x_PPRL);
-
-	sx_out_off(bp, CD186x_PPRL, 0xa5);
-	udelay(1);
-	val2 = sx_in_off(bp, CD186x_PPRL);
-
-
-	if (val1 != 0x5a || val2 != 0xa5) {
-		printk(KERN_INFO
-			"sx%d: specialix IO8+ Board at 0x%03x not found.\n",
-						board_No(bp), bp->base);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-	/* Check the DSR lines that Specialix uses as board
-	   identification */
-	val1 = read_cross_byte(bp, CD186x_MSVR, MSVR_DSR);
-	val2 = read_cross_byte(bp, CD186x_MSVR, MSVR_RTS);
-	dprintk(SX_DEBUG_INIT,
-			"sx%d: DSR lines are: %02x, rts lines are: %02x\n",
-					board_No(bp), val1, val2);
-
-	/* They managed to switch the bit order between the docs and
-	   the IO8+ card. The new PCI card now conforms to old docs.
-	   They changed the PCI docs to reflect the situation on the
-	   old card. */
-	val2 = (bp->flags & SX_BOARD_IS_PCI)?0x4d : 0xb2;
-	if (val1 != val2) {
-		printk(KERN_INFO
-		  "sx%d: specialix IO8+ ID %02x at 0x%03x not found (%02x).\n",
-		       board_No(bp), val2, bp->base, val1);
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-
-	/* Reset CD186x again  */
-	if (!sx_init_CD186x(bp)) {
-		sx_release_io_range(bp);
-		func_exit();
-		return 1;
-	}
-
-	sx_request_io_range(bp);
-	bp->flags |= SX_BOARD_PRESENT;
-
-	/* Chip           revcode   pkgtype
-			  GFRCR     SRCR bit 7
-	   CD180 rev B    0x81      0
-	   CD180 rev C    0x82      0
-	   CD1864 rev A   0x82      1
-	   CD1865 rev A   0x83      1  -- Do not use!!! Does not work.
-	   CD1865 rev B   0x84      1
-	 -- Thanks to Gwen Wang, Cirrus Logic.
-	 */
-
-	switch (sx_in_off(bp, CD186x_GFRCR)) {
-	case 0x82:
-		chip = 1864;
-		rev = 'A';
-		break;
-	case 0x83:
-		chip = 1865;
-		rev = 'A';
-		break;
-	case 0x84:
-		chip = 1865;
-		rev = 'B';
-		break;
-	case 0x85:
-		chip = 1865;
-		rev = 'C';
-		break; /* Does not exist at this time */
-	default:
-		chip = -1;
-		rev = 'x';
-	}
-
-	dprintk(SX_DEBUG_INIT, " GFCR = 0x%02x\n", sx_in_off(bp, CD186x_GFRCR));
-
-	printk(KERN_INFO
-    "sx%d: specialix IO8+ board detected at 0x%03x, IRQ %d, CD%d Rev. %c.\n",
-				board_No(bp), bp->base, bp->irq, chip, rev);
-
-	func_exit();
-	return 0;
-}
-
-/*
- *
- *  Interrupt processing routines.
- * */
-
-static struct specialix_port *sx_get_port(struct specialix_board *bp,
-					       unsigned char const *what)
-{
-	unsigned char channel;
-	struct specialix_port *port = NULL;
-
-	channel = sx_in(bp, CD186x_GICR) >> GICR_CHAN_OFF;
-	dprintk(SX_DEBUG_CHAN, "channel: %d\n", channel);
-	if (channel < CD186x_NCH) {
-		port = &sx_port[board_No(bp) * SX_NPORT + channel];
-		dprintk(SX_DEBUG_CHAN, "port: %d %p flags: 0x%lx\n",
-			board_No(bp) * SX_NPORT + channel,  port,
-			port->port.flags & ASYNC_INITIALIZED);
-
-		if (port->port.flags & ASYNC_INITIALIZED) {
-			dprintk(SX_DEBUG_CHAN, "port: %d %p\n", channel, port);
-			func_exit();
-			return port;
-		}
-	}
-	printk(KERN_INFO "sx%d: %s interrupt from invalid port %d\n",
-	       board_No(bp), what, channel);
-	return NULL;
-}
-
-
-static void sx_receive_exc(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char status;
-	unsigned char ch, flag;
-
-	func_enter();
-
-	port = sx_get_port(bp, "Receive");
-	if (!port) {
-		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
-		func_exit();
-		return;
-	}
-	tty = port->port.tty;
-
-	status = sx_in(bp, CD186x_RCSR);
-
-	dprintk(SX_DEBUG_RX, "status: 0x%x\n", status);
-	if (status & RCSR_OE) {
-		port->overrun++;
-		dprintk(SX_DEBUG_FIFO,
-			"sx%d: port %d: Overrun. Total %ld overruns.\n",
-				board_No(bp), port_No(port), port->overrun);
-	}
-	status &= port->mark_mask;
-
-	/* This flip buffer check needs to be below the reading of the
-	   status register to reset the chip's IRQ.... */
-	if (tty_buffer_request_room(tty, 1) == 0) {
-		dprintk(SX_DEBUG_FIFO,
-		    "sx%d: port %d: Working around flip buffer overflow.\n",
-					board_No(bp), port_No(port));
-		func_exit();
-		return;
-	}
-
-	ch = sx_in(bp, CD186x_RDR);
-	if (!status) {
-		func_exit();
-		return;
-	}
-	if (status & RCSR_TOUT) {
-		printk(KERN_INFO
-		    "sx%d: port %d: Receiver timeout. Hardware problems ?\n",
-					board_No(bp), port_No(port));
-		func_exit();
-		return;
-
-	} else if (status & RCSR_BREAK) {
-		dprintk(SX_DEBUG_RX, "sx%d: port %d: Handling break...\n",
-		       board_No(bp), port_No(port));
-		flag = TTY_BREAK;
-		if (port->port.flags & ASYNC_SAK)
-			do_SAK(tty);
-
-	} else if (status & RCSR_PE)
-		flag = TTY_PARITY;
-
-	else if (status & RCSR_FE)
-		flag = TTY_FRAME;
-
-	else if (status & RCSR_OE)
-		flag = TTY_OVERRUN;
-
-	else
-		flag = TTY_NORMAL;
-
-	if (tty_insert_flip_char(tty, ch, flag))
-		tty_flip_buffer_push(tty);
-	func_exit();
-}
-
-
-static void sx_receive(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	func_enter();
-
-	port = sx_get_port(bp, "Receive");
-	if (port == NULL) {
-		dprintk(SX_DEBUG_RX, "Hmm, couldn't find port.\n");
-		func_exit();
-		return;
-	}
-	tty = port->port.tty;
-
-	count = sx_in(bp, CD186x_RDCR);
-	dprintk(SX_DEBUG_RX, "port: %p: count: %d\n", port, count);
-	port->hits[count > 8 ? 9 : count]++;
-
-	while (count--)
-		tty_insert_flip_char(tty, sx_in(bp, CD186x_RDR), TTY_NORMAL);
-	tty_flip_buffer_push(tty);
-	func_exit();
-}
-
-
-static void sx_transmit(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char count;
-
-	func_enter();
-	port = sx_get_port(bp, "Transmit");
-	if (port == NULL) {
-		func_exit();
-		return;
-	}
-	dprintk(SX_DEBUG_TX, "port: %p\n", port);
-	tty = port->port.tty;
-
-	if (port->IER & IER_TXEMPTY) {
-		/* FIFO drained */
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXEMPTY;
-		sx_out(bp, CD186x_IER, port->IER);
-		func_exit();
-		return;
-	}
-
-	if ((port->xmit_cnt <= 0 && !port->break_length)
-	    || tty->stopped || tty->hw_stopped) {
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		sx_out(bp, CD186x_IER, port->IER);
-		func_exit();
-		return;
-	}
-
-	if (port->break_length) {
-		if (port->break_length > 0) {
-			if (port->COR2 & COR2_ETC) {
-				sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-				sx_out(bp, CD186x_TDR, CD186x_C_SBRK);
-				port->COR2 &= ~COR2_ETC;
-			}
-			count = min_t(int, port->break_length, 0xff);
-			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-			sx_out(bp, CD186x_TDR, CD186x_C_DELAY);
-			sx_out(bp, CD186x_TDR, count);
-			port->break_length -= count;
-			if (port->break_length == 0)
-				port->break_length--;
-		} else {
-			sx_out(bp, CD186x_TDR, CD186x_C_ESC);
-			sx_out(bp, CD186x_TDR, CD186x_C_EBRK);
-			sx_out(bp, CD186x_COR2, port->COR2);
-			sx_wait_CCR(bp);
-			sx_out(bp, CD186x_CCR, CCR_CORCHG2);
-			port->break_length = 0;
-		}
-
-		func_exit();
-		return;
-	}
-
-	count = CD186x_NFIFO;
-	do {
-		sx_out(bp, CD186x_TDR, port->xmit_buf[port->xmit_tail++]);
-		port->xmit_tail = port->xmit_tail & (SERIAL_XMIT_SIZE-1);
-		if (--port->xmit_cnt <= 0)
-			break;
-	} while (--count > 0);
-
-	if (port->xmit_cnt <= 0) {
-		sx_out(bp, CD186x_CAR, port_No(port));
-		port->IER &= ~IER_TXRDY;
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	if (port->xmit_cnt <= port->wakeup_chars)
-		tty_wakeup(tty);
-
-	func_exit();
-}
-
-
-static void sx_check_modem(struct specialix_board *bp)
-{
-	struct specialix_port *port;
-	struct tty_struct *tty;
-	unsigned char mcr;
-	int msvr_cd;
-
-	dprintk(SX_DEBUG_SIGNALS, "Modem intr. ");
-	port = sx_get_port(bp, "Modem");
-	if (port == NULL)
-		return;
-
-	tty = port->port.tty;
-
-	mcr = sx_in(bp, CD186x_MCR);
-
-	if ((mcr & MCR_CDCHG)) {
-		dprintk(SX_DEBUG_SIGNALS, "CD just changed... ");
-		msvr_cd = sx_in(bp, CD186x_MSVR) & MSVR_CD;
-		if (msvr_cd) {
-			dprintk(SX_DEBUG_SIGNALS, "Waking up guys in open.\n");
-			wake_up_interruptible(&port->port.open_wait);
-		} else {
-			dprintk(SX_DEBUG_SIGNALS, "Sending HUP.\n");
-			tty_hangup(tty);
-		}
-	}
-
-#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
-	if (mcr & MCR_CTSCHG) {
-		if (sx_in(bp, CD186x_MSVR) & MSVR_CTS) {
-			tty->hw_stopped = 0;
-			port->IER |= IER_TXRDY;
-			if (port->xmit_cnt <= port->wakeup_chars)
-				tty_wakeup(tty);
-		} else {
-			tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	if (mcr & MCR_DSSXHG) {
-		if (sx_in(bp, CD186x_MSVR) & MSVR_DSR) {
-			tty->hw_stopped = 0;
-			port->IER |= IER_TXRDY;
-			if (port->xmit_cnt <= port->wakeup_chars)
-				tty_wakeup(tty);
-		} else {
-			tty->hw_stopped = 1;
-			port->IER &= ~IER_TXRDY;
-		}
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-#endif /* SPECIALIX_BRAIN_DAMAGED_CTS */
-
-	/* Clear change bits */
-	sx_out(bp, CD186x_MCR, 0);
-}
-
-
-/* The main interrupt processing routine */
-static irqreturn_t sx_interrupt(int dummy, void *dev_id)
-{
-	unsigned char status;
-	unsigned char ack;
-	struct specialix_board *bp = dev_id;
-	unsigned long loop = 0;
-	int saved_reg;
-	unsigned long flags;
-
-	func_enter();
-
-	spin_lock_irqsave(&bp->lock, flags);
-
-	dprintk(SX_DEBUG_FLOW, "enter %s port %d room: %ld\n", __func__,
-		port_No(sx_get_port(bp, "INT")),
-		SERIAL_XMIT_SIZE - sx_get_port(bp, "ITN")->xmit_cnt - 1);
-	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		dprintk(SX_DEBUG_IRQ, "sx: False interrupt. irq %d.\n",
-								bp->irq);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		func_exit();
-		return IRQ_NONE;
-	}
-
-	saved_reg = bp->reg;
-
-	while (++loop < 16) {
-		status = sx_in(bp, CD186x_SRSR) &
-				(SRSR_RREQint | SRSR_TREQint | SRSR_MREQint);
-		if (status == 0)
-			break;
-		if (status & SRSR_RREQint) {
-			ack = sx_in(bp, CD186x_RRAR);
-
-			if (ack == (SX_ID | GIVR_IT_RCV))
-				sx_receive(bp);
-			else if (ack == (SX_ID | GIVR_IT_REXC))
-				sx_receive_exc(bp);
-			else
-				printk(KERN_ERR
-				"sx%d: status: 0x%x Bad receive ack 0x%02x.\n",
-						board_No(bp), status, ack);
-
-		} else if (status & SRSR_TREQint) {
-			ack = sx_in(bp, CD186x_TRAR);
-
-			if (ack == (SX_ID | GIVR_IT_TX))
-				sx_transmit(bp);
-			else
-				printk(KERN_ERR "sx%d: status: 0x%x Bad transmit ack 0x%02x. port: %d\n",
-					board_No(bp), status, ack,
-					port_No(sx_get_port(bp, "Int")));
-		} else if (status & SRSR_MREQint) {
-			ack = sx_in(bp, CD186x_MRAR);
-
-			if (ack == (SX_ID | GIVR_IT_MODEM))
-				sx_check_modem(bp);
-			else
-				printk(KERN_ERR
-				  "sx%d: status: 0x%x Bad modem ack 0x%02x.\n",
-				       board_No(bp), status, ack);
-
-		}
-
-		sx_out(bp, CD186x_EOIR, 0);   /* Mark end of interrupt */
-	}
-	bp->reg = saved_reg;
-	outb(bp->reg, bp->base + SX_ADDR_REG);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-
-/*
- *  Routines for open & close processing.
- */
-
-static void turn_ints_off(struct specialix_board *bp)
-{
-	unsigned long flags;
-
-	func_enter();
-	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in_off(bp, 0); /* Turn off interrupts. */
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-static void turn_ints_on(struct specialix_board *bp)
-{
-	unsigned long flags;
-
-	func_enter();
-
-	spin_lock_irqsave(&bp->lock, flags);
-	(void) sx_in(bp, 0); /* Turn ON interrupts. */
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-/* Called with disabled interrupts */
-static int sx_setup_board(struct specialix_board *bp)
-{
-	int error;
-
-	if (bp->flags & SX_BOARD_ACTIVE)
-		return 0;
-
-	if (bp->flags & SX_BOARD_IS_PCI)
-		error = request_irq(bp->irq, sx_interrupt,
-			IRQF_DISABLED | IRQF_SHARED, "specialix IO8+", bp);
-	else
-		error = request_irq(bp->irq, sx_interrupt,
-			IRQF_DISABLED, "specialix IO8+", bp);
-
-	if (error)
-		return error;
-
-	turn_ints_on(bp);
-	bp->flags |= SX_BOARD_ACTIVE;
-
-	return 0;
-}
-
-
-/* Called with disabled interrupts */
-static void sx_shutdown_board(struct specialix_board *bp)
-{
-	func_enter();
-
-	if (!(bp->flags & SX_BOARD_ACTIVE)) {
-		func_exit();
-		return;
-	}
-
-	bp->flags &= ~SX_BOARD_ACTIVE;
-
-	dprintk(SX_DEBUG_IRQ, "Freeing IRQ%d for board %d.\n",
-		 bp->irq, board_No(bp));
-	free_irq(bp->irq, bp);
-	turn_ints_off(bp);
-	func_exit();
-}
-
-static unsigned int sx_crtscts(struct tty_struct *tty)
-{
-	if (sx_rtscts)
-		return C_CRTSCTS(tty);
-	return 1;
-}
-
-/*
- * Setting up port characteristics.
- * Must be called with disabled interrupts
- */
-static void sx_change_speed(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	struct tty_struct *tty;
-	unsigned long baud;
-	long tmp;
-	unsigned char cor1 = 0, cor3 = 0;
-	unsigned char mcor1 = 0, mcor2 = 0;
-	static unsigned long again;
-	unsigned long flags;
-
-	func_enter();
-
-	tty = port->port.tty;
-	if (!tty || !tty->termios) {
-		func_exit();
-		return;
-	}
-
-	port->IER  = 0;
-	port->COR2 = 0;
-	/* Select port on the board */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-
-	/* The Specialix board doens't implement the RTS lines.
-	   They are used to set the IRQ level. Don't touch them. */
-	if (sx_crtscts(tty))
-		port->MSVR = MSVR_DTR | (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
-	else
-		port->MSVR =  (sx_in(bp, CD186x_MSVR) & MSVR_RTS);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	dprintk(SX_DEBUG_TERMIOS, "sx: got MSVR=%02x.\n", port->MSVR);
-	baud = tty_get_baud_rate(tty);
-
-	if (baud == 38400) {
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baud = 57600;
-		if ((port->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baud = 115200;
-	}
-
-	if (!baud) {
-		/* Drop DTR & exit */
-		dprintk(SX_DEBUG_TERMIOS, "Dropping DTR...  Hmm....\n");
-		if (!sx_crtscts(tty)) {
-			port->MSVR &= ~MSVR_DTR;
-			spin_lock_irqsave(&bp->lock, flags);
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-			spin_unlock_irqrestore(&bp->lock, flags);
-		} else
-			dprintk(SX_DEBUG_TERMIOS, "Can't drop DTR: no DTR.\n");
-		return;
-	} else {
-		/* Set DTR on */
-		if (!sx_crtscts(tty))
-			port->MSVR |= MSVR_DTR;
-	}
-
-	/*
-	 * Now we must calculate some speed depended things
-	 */
-
-	/* Set baud rate for port */
-	tmp = port->custom_divisor ;
-	if (tmp)
-		printk(KERN_INFO
-			"sx%d: Using custom baud rate divisor %ld. \n"
-			"This is an untested option, please be careful.\n",
-							port_No(port), tmp);
-	else
-		tmp = (((SX_OSCFREQ + baud/2) / baud + CD186x_TPC/2) /
-								CD186x_TPC);
-
-	if (tmp < 0x10 && time_before(again, jiffies)) {
-		again = jiffies + HZ * 60;
-		/* Page 48 of version 2.0 of the CL-CD1865 databook */
-		if (tmp >= 12) {
-			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
-				"Performance degradation is possible.\n"
-				"Read specialix.txt for more info.\n",
-						port_No(port), tmp);
-		} else {
-			printk(KERN_INFO "sx%d: Baud rate divisor is %ld. \n"
-		"Warning: overstressing Cirrus chip. This might not work.\n"
-		"Read specialix.txt for more info.\n", port_No(port), tmp);
-		}
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RBPRH, (tmp >> 8) & 0xff);
-	sx_out(bp, CD186x_TBPRH, (tmp >> 8) & 0xff);
-	sx_out(bp, CD186x_RBPRL, tmp & 0xff);
-	sx_out(bp, CD186x_TBPRL, tmp & 0xff);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (port->custom_divisor)
-		baud = (SX_OSCFREQ + port->custom_divisor/2) /
-							port->custom_divisor;
-	baud = (baud + 5) / 10;		/* Estimated CPS */
-
-	/* Two timer ticks seems enough to wakeup something like SLIP driver */
-	tmp = ((baud + HZ/2) / HZ) * 2 - CD186x_NFIFO;
-	port->wakeup_chars = (tmp < 0) ? 0 : ((tmp >= SERIAL_XMIT_SIZE) ?
-					      SERIAL_XMIT_SIZE - 1 : tmp);
-
-	/* Receiver timeout will be transmission time for 1.5 chars */
-	tmp = (SPECIALIX_TPS + SPECIALIX_TPS/2 + baud/2) / baud;
-	tmp = (tmp > 0xff) ? 0xff : tmp;
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_RTPR, tmp);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	switch (C_CSIZE(tty)) {
-	case CS5:
-		cor1 |= COR1_5BITS;
-		break;
-	case CS6:
-		cor1 |= COR1_6BITS;
-		break;
-	case CS7:
-		cor1 |= COR1_7BITS;
-		break;
-	case CS8:
-		cor1 |= COR1_8BITS;
-		break;
-	}
-
-	if (C_CSTOPB(tty))
-		cor1 |= COR1_2SB;
-
-	cor1 |= COR1_IGNORE;
-	if (C_PARENB(tty)) {
-		cor1 |= COR1_NORMPAR;
-		if (C_PARODD(tty))
-			cor1 |= COR1_ODDP;
-		if (I_INPCK(tty))
-			cor1 &= ~COR1_IGNORE;
-	}
-	/* Set marking of some errors */
-	port->mark_mask = RCSR_OE | RCSR_TOUT;
-	if (I_INPCK(tty))
-		port->mark_mask |= RCSR_FE | RCSR_PE;
-	if (I_BRKINT(tty) || I_PARMRK(tty))
-		port->mark_mask |= RCSR_BREAK;
-	if (I_IGNPAR(tty))
-		port->mark_mask &= ~(RCSR_FE | RCSR_PE);
-	if (I_IGNBRK(tty)) {
-		port->mark_mask &= ~RCSR_BREAK;
-		if (I_IGNPAR(tty))
-			/* Real raw mode. Ignore all */
-			port->mark_mask &= ~RCSR_OE;
-	}
-	/* Enable Hardware Flow Control */
-	if (C_CRTSCTS(tty)) {
-#ifdef SPECIALIX_BRAIN_DAMAGED_CTS
-		port->IER |= IER_DSR | IER_CTS;
-		mcor1 |= MCOR1_DSRZD | MCOR1_CTSZD;
-		mcor2 |= MCOR2_DSROD | MCOR2_CTSOD;
-		spin_lock_irqsave(&bp->lock, flags);
-		tty->hw_stopped = !(sx_in(bp, CD186x_MSVR) &
-							(MSVR_CTS|MSVR_DSR));
-		spin_unlock_irqrestore(&bp->lock, flags);
-#else
-		port->COR2 |= COR2_CTSAE;
-#endif
-	}
-	/* Enable Software Flow Control. FIXME: I'm not sure about this */
-	/* Some people reported that it works, but I still doubt it */
-	if (I_IXON(tty)) {
-		port->COR2 |= COR2_TXIBE;
-		cor3 |= (COR3_FCT | COR3_SCDE);
-		if (I_IXANY(tty))
-			port->COR2 |= COR2_IXM;
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_SCHR1, START_CHAR(tty));
-		sx_out(bp, CD186x_SCHR2, STOP_CHAR(tty));
-		sx_out(bp, CD186x_SCHR3, START_CHAR(tty));
-		sx_out(bp, CD186x_SCHR4, STOP_CHAR(tty));
-		spin_unlock_irqrestore(&bp->lock, flags);
-	}
-	if (!C_CLOCAL(tty)) {
-		/* Enable CD check */
-		port->IER |= IER_CD;
-		mcor1 |= MCOR1_CDZD;
-		mcor2 |= MCOR2_CDOD;
-	}
-
-	if (C_CREAD(tty))
-		/* Enable receiver */
-		port->IER |= IER_RXD;
-
-	/* Set input FIFO size (1-8 bytes) */
-	cor3 |= sx_rxfifo;
-	/* Setting up CD186x channel registers */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_COR1, cor1);
-	sx_out(bp, CD186x_COR2, port->COR2);
-	sx_out(bp, CD186x_COR3, cor3);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Make CD186x know about registers change */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_CORCHG1 | CCR_CORCHG2 | CCR_CORCHG3);
-	/* Setting up modem option registers */
-	dprintk(SX_DEBUG_TERMIOS, "Mcor1 = %02x, mcor2 = %02x.\n",
-								mcor1, mcor2);
-	sx_out(bp, CD186x_MCOR1, mcor1);
-	sx_out(bp, CD186x_MCOR2, mcor2);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Enable CD186x transmitter & receiver */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_TXEN | CCR_RXEN);
-	/* Enable interrupts */
-	sx_out(bp, CD186x_IER, port->IER);
-	/* And finally set the modem lines... */
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-/* Must be called with interrupts enabled */
-static int sx_setup_port(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	unsigned long flags;
-
-	func_enter();
-
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		func_exit();
-		return 0;
-	}
-
-	if (!port->xmit_buf) {
-		/* We may sleep in get_zeroed_page() */
-		unsigned long tmp;
-
-		tmp = get_zeroed_page(GFP_KERNEL);
-		if (tmp == 0L) {
-			func_exit();
-			return -ENOMEM;
-		}
-
-		if (port->xmit_buf) {
-			free_page(tmp);
-			func_exit();
-			return -ERESTARTSYS;
-		}
-		port->xmit_buf = (unsigned char *) tmp;
-	}
-
-	spin_lock_irqsave(&port->lock, flags);
-
-	if (port->port.tty)
-		clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
-
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	sx_change_speed(bp, port);
-	port->port.flags |= ASYNC_INITIALIZED;
-
-	spin_unlock_irqrestore(&port->lock, flags);
-
-
-	func_exit();
-	return 0;
-}
-
-
-/* Must be called with interrupts disabled */
-static void sx_shutdown_port(struct specialix_board *bp,
-						struct specialix_port *port)
-{
-	struct tty_struct *tty;
-	int i;
-	unsigned long flags;
-
-	func_enter();
-
-	if (!(port->port.flags & ASYNC_INITIALIZED)) {
-		func_exit();
-		return;
-	}
-
-	if (sx_debug & SX_DEBUG_FIFO) {
-		dprintk(SX_DEBUG_FIFO,
-			"sx%d: port %d: %ld overruns, FIFO hits [ ",
-				board_No(bp), port_No(port), port->overrun);
-		for (i = 0; i < 10; i++)
-			dprintk(SX_DEBUG_FIFO, "%ld ", port->hits[i]);
-		dprintk(SX_DEBUG_FIFO, "].\n");
-	}
-
-	if (port->xmit_buf) {
-		free_page((unsigned long) port->xmit_buf);
-		port->xmit_buf = NULL;
-	}
-
-	/* Select port */
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-
-	tty = port->port.tty;
-	if (tty == NULL || C_HUPCL(tty)) {
-		/* Drop DTR */
-		sx_out(bp, CD186x_MSVDTR, 0);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	/* Reset port */
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_SOFTRESET);
-	/* Disable all interrupts from this port */
-	port->IER = 0;
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (tty)
-		set_bit(TTY_IO_ERROR, &tty->flags);
-	port->port.flags &= ~ASYNC_INITIALIZED;
-
-	if (!bp->count)
-		sx_shutdown_board(bp);
-	func_exit();
-}
-
-
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-						struct specialix_port *port)
-{
-	DECLARE_WAITQUEUE(wait,  current);
-	struct specialix_board *bp = port_Board(port);
-	int    retval;
-	int    do_clocal = 0;
-	int    CD;
-	unsigned long flags;
-
-	func_enter();
-
-	/*
-	 * If the device is in the middle of being closed, then block
-	 * until it's done, and then try again.
-	 */
-	if (tty_hung_up_p(filp) || port->port.flags & ASYNC_CLOSING) {
-		interruptible_sleep_on(&port->port.close_wait);
-		if (port->port.flags & ASYNC_HUP_NOTIFY) {
-			func_exit();
-			return -EAGAIN;
-		} else {
-			func_exit();
-			return -ERESTARTSYS;
-		}
-	}
-
-	/*
-	 * If non-blocking mode is set, or the port is not enabled,
-	 * then make the check up front and then exit.
-	 */
-	if ((filp->f_flags & O_NONBLOCK) ||
-	    (tty->flags & (1 << TTY_IO_ERROR))) {
-		port->port.flags |= ASYNC_NORMAL_ACTIVE;
-		func_exit();
-		return 0;
-	}
-
-	if (C_CLOCAL(tty))
-		do_clocal = 1;
-
-	/*
-	 * Block waiting for the carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, info->count is dropped by one, so that
-	 * rs_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	retval = 0;
-	add_wait_queue(&port->port.open_wait, &wait);
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->port.count--;
-	spin_unlock_irqrestore(&port->lock, flags);
-	port->port.blocked_open++;
-	while (1) {
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		CD = sx_in(bp, CD186x_MSVR) & MSVR_CD;
-		if (sx_crtscts(tty)) {
-			/* Activate RTS */
-			port->MSVR |= MSVR_DTR;		/* WTF? */
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-		} else {
-			/* Activate DTR */
-			port->MSVR |= MSVR_DTR;
-			sx_out(bp, CD186x_MSVR, port->MSVR);
-		}
-		spin_unlock_irqrestore(&bp->lock, flags);
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (tty_hung_up_p(filp) ||
-		    !(port->port.flags & ASYNC_INITIALIZED)) {
-			if (port->port.flags & ASYNC_HUP_NOTIFY)
-				retval = -EAGAIN;
-			else
-				retval = -ERESTARTSYS;
-			break;
-		}
-		if (!(port->port.flags & ASYNC_CLOSING) &&
-		    (do_clocal || CD))
-			break;
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->port.open_wait, &wait);
-	spin_lock_irqsave(&port->lock, flags);
-	if (!tty_hung_up_p(filp))
-		port->port.count++;
-	port->port.blocked_open--;
-	spin_unlock_irqrestore(&port->lock, flags);
-	if (retval) {
-		func_exit();
-		return retval;
-	}
-
-	port->port.flags |= ASYNC_NORMAL_ACTIVE;
-	func_exit();
-	return 0;
-}
-
-
-static int sx_open(struct tty_struct *tty, struct file *filp)
-{
-	int board;
-	int error;
-	struct specialix_port *port;
-	struct specialix_board *bp;
-	int i;
-	unsigned long flags;
-
-	func_enter();
-
-	board = SX_BOARD(tty->index);
-
-	if (board >= SX_NBOARD || !(sx_board[board].flags & SX_BOARD_PRESENT)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = &sx_board[board];
-	port = sx_port + board * SX_NPORT + SX_PORT(tty->index);
-	port->overrun = 0;
-	for (i = 0; i < 10; i++)
-		port->hits[i] = 0;
-
-	dprintk(SX_DEBUG_OPEN,
-			"Board = %d, bp = %p, port = %p, portno = %d.\n",
-				 board, bp, port, SX_PORT(tty->index));
-
-	if (sx_paranoia_check(port, tty->name, "sx_open")) {
-		func_enter();
-		return -ENODEV;
-	}
-
-	error = sx_setup_board(bp);
-	if (error) {
-		func_exit();
-		return error;
-	}
-
-	spin_lock_irqsave(&bp->lock, flags);
-	port->port.count++;
-	bp->count++;
-	tty->driver_data = port;
-	port->port.tty = tty;
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	error = sx_setup_port(bp, port);
-	if (error) {
-		func_enter();
-		return error;
-	}
-
-	error = block_til_ready(tty, filp, port);
-	if (error) {
-		func_enter();
-		return error;
-	}
-
-	func_exit();
-	return 0;
-}
-
-static void sx_flush_buffer(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-	port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-	spin_unlock_irqrestore(&port->lock, flags);
-	tty_wakeup(tty);
-
-	func_exit();
-}
-
-static void sx_close(struct tty_struct *tty, struct file *filp)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-	unsigned long timeout;
-
-	func_enter();
-	if (!port || sx_paranoia_check(port, tty->name, "close")) {
-		func_exit();
-		return;
-	}
-	spin_lock_irqsave(&port->lock, flags);
-
-	if (tty_hung_up_p(filp)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-	if (tty->count == 1 && port->port.count != 1) {
-		printk(KERN_ERR "sx%d: sx_close: bad port count;"
-		       " tty->count is 1, port count is %d\n",
-		       board_No(bp), port->port.count);
-		port->port.count = 1;
-	}
-
-	if (port->port.count > 1) {
-		port->port.count--;
-		bp->count--;
-
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		func_exit();
-		return;
-	}
-	port->port.flags |= ASYNC_CLOSING;
-	/*
-	 * Now we wait for the transmit buffer to clear; and we notify
-	 * the line discipline to only process XON/XOFF characters.
-	 */
-	tty->closing = 1;
-	spin_unlock_irqrestore(&port->lock, flags);
-	dprintk(SX_DEBUG_OPEN, "Closing\n");
-	if (port->port.closing_wait != ASYNC_CLOSING_WAIT_NONE)
-		tty_wait_until_sent(tty, port->port.closing_wait);
-	/*
-	 * At this point we stop accepting input.  To do this, we
-	 * disable the receive line status interrupts, and tell the
-	 * interrupt driver to stop checking the data ready bit in the
-	 * line status register.
-	 */
-	dprintk(SX_DEBUG_OPEN, "Closed\n");
-	port->IER &= ~IER_RXD;
-	if (port->port.flags & ASYNC_INITIALIZED) {
-		port->IER &= ~IER_TXRDY;
-		port->IER |= IER_TXEMPTY;
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		/*
-		 * Before we drop DTR, make sure the UART transmitter
-		 * has completely drained; this is especially
-		 * important if there is a transmit FIFO!
-		 */
-		timeout = jiffies+HZ;
-		while (port->IER & IER_TXEMPTY) {
-			set_current_state(TASK_INTERRUPTIBLE);
-			msleep_interruptible(jiffies_to_msecs(port->timeout));
-			if (time_after(jiffies, timeout)) {
-				printk(KERN_INFO "Timeout waiting for close\n");
-				break;
-			}
-		}
-
-	}
-
-	if (--bp->count < 0) {
-		printk(KERN_ERR
-		    "sx%d: sx_shutdown_port: bad board count: %d port: %d\n",
-				board_No(bp), bp->count, tty->index);
-		bp->count = 0;
-	}
-	if (--port->port.count < 0) {
-		printk(KERN_ERR
-			"sx%d: sx_close: bad port count for tty%d: %d\n",
-				board_No(bp), port_No(port), port->port.count);
-		port->port.count = 0;
-	}
-
-	sx_shutdown_port(bp, port);
-	sx_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	spin_lock_irqsave(&port->lock, flags);
-	tty->closing = 0;
-	port->port.tty = NULL;
-	spin_unlock_irqrestore(&port->lock, flags);
-	if (port->port.blocked_open) {
-		if (port->port.close_delay)
-			msleep_interruptible(
-				jiffies_to_msecs(port->port.close_delay));
-		wake_up_interruptible(&port->port.open_wait);
-	}
-	port->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-	wake_up_interruptible(&port->port.close_wait);
-
-	func_exit();
-}
-
-
-static int sx_write(struct tty_struct *tty,
-					const unsigned char *buf, int count)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	int c, total = 0;
-	unsigned long flags;
-
-	func_enter();
-	if (sx_paranoia_check(port, tty->name, "sx_write")) {
-		func_exit();
-		return 0;
-	}
-
-	bp = port_Board(port);
-
-	if (!port->xmit_buf) {
-		func_exit();
-		return 0;
-	}
-
-	while (1) {
-		spin_lock_irqsave(&port->lock, flags);
-		c = min_t(int, count, min(SERIAL_XMIT_SIZE - port->xmit_cnt - 1,
-				   SERIAL_XMIT_SIZE - port->xmit_head));
-		if (c <= 0) {
-			spin_unlock_irqrestore(&port->lock, flags);
-			break;
-		}
-		memcpy(port->xmit_buf + port->xmit_head, buf, c);
-		port->xmit_head = (port->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-		port->xmit_cnt += c;
-		spin_unlock_irqrestore(&port->lock, flags);
-
-		buf += c;
-		count -= c;
-		total += c;
-	}
-
-	spin_lock_irqsave(&bp->lock, flags);
-	if (port->xmit_cnt && !tty->stopped && !tty->hw_stopped &&
-	    !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-	}
-	spin_unlock_irqrestore(&bp->lock, flags);
-	func_exit();
-
-	return total;
-}
-
-
-static int sx_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_put_char")) {
-		func_exit();
-		return 0;
-	}
-	dprintk(SX_DEBUG_TX, "check tty: %p %p\n", tty, port->xmit_buf);
-	if (!port->xmit_buf) {
-		func_exit();
-		return 0;
-	}
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-
-	dprintk(SX_DEBUG_TX, "xmit_cnt: %d xmit_buf: %p\n",
-					port->xmit_cnt, port->xmit_buf);
-	if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1 || !port->xmit_buf) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		dprintk(SX_DEBUG_TX, "Exit size\n");
-		func_exit();
-		return 0;
-	}
-	dprintk(SX_DEBUG_TX, "Handle xmit: %p %p\n", port, port->xmit_buf);
-	port->xmit_buf[port->xmit_head++] = ch;
-	port->xmit_head &= SERIAL_XMIT_SIZE - 1;
-	port->xmit_cnt++;
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-	return 1;
-}
-
-
-static void sx_flush_chars(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp = port_Board(port);
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_flush_chars")) {
-		func_exit();
-		return;
-	}
-	if (port->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !port->xmit_buf) {
-		func_exit();
-		return;
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	port->IER |= IER_TXRDY;
-	sx_out(port_Board(port), CD186x_CAR, port_No(port));
-	sx_out(port_Board(port), CD186x_IER, port->IER);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-static int sx_write_room(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	int	ret;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_write_room")) {
-		func_exit();
-		return 0;
-	}
-
-	ret = SERIAL_XMIT_SIZE - port->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-
-	func_exit();
-	return ret;
-}
-
-
-static int sx_chars_in_buffer(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_chars_in_buffer")) {
-		func_exit();
-		return 0;
-	}
-	func_exit();
-	return port->xmit_cnt;
-}
-
-static int sx_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned char status;
-	unsigned int result;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, __func__)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	status = sx_in(bp, CD186x_MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	dprintk(SX_DEBUG_INIT, "Got msvr[%d] = %02x, car = %d.\n",
-			port_No(port), status, sx_in(bp, CD186x_CAR));
-	dprintk(SX_DEBUG_INIT, "sx_port = %p, port = %p\n", sx_port, port);
-	if (sx_crtscts(port->port.tty)) {
-		result  = TIOCM_DTR | TIOCM_DSR
-			  |   ((status & MSVR_DTR) ? TIOCM_RTS : 0)
-			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	} else {
-		result  = TIOCM_RTS | TIOCM_DSR
-			  |   ((status & MSVR_DTR) ? TIOCM_DTR : 0)
-			  |   ((status & MSVR_CD)  ? TIOCM_CAR : 0)
-			  |   ((status & MSVR_CTS) ? TIOCM_CTS : 0);
-	}
-
-	func_exit();
-
-	return result;
-}
-
-
-static int sx_tiocmset(struct tty_struct *tty, struct file *file,
-		       unsigned int set, unsigned int clear)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board *bp;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, __func__)) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (sx_crtscts(port->port.tty)) {
-		if (set & TIOCM_RTS)
-			port->MSVR |= MSVR_DTR;
-	} else {
-		if (set & TIOCM_DTR)
-			port->MSVR |= MSVR_DTR;
-	}
-	if (sx_crtscts(port->port.tty)) {
-		if (clear & TIOCM_RTS)
-			port->MSVR &= ~MSVR_DTR;
-	} else {
-		if (clear & TIOCM_DTR)
-			port->MSVR &= ~MSVR_DTR;
-	}
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	func_exit();
-	return 0;
-}
-
-
-static int sx_send_break(struct tty_struct *tty, int length)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp = port_Board(port);
-	unsigned long flags;
-
-	func_enter();
-	if (length == 0 || length == -1)
-		return -EOPNOTSUPP;
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->break_length = SPECIALIX_TPS / HZ * length;
-	port->COR2 |= COR2_ETC;
-	port->IER  |= IER_TXRDY;
-	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(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-	sx_wait_CCR(bp);
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CCR, CCR_CORCHG2);
-	spin_unlock_irqrestore(&bp->lock, flags);
-	sx_wait_CCR(bp);
-
-	func_exit();
-	return 0;
-}
-
-
-static int sx_set_serial_info(struct specialix_port *port,
-					struct serial_struct __user *newinfo)
-{
-	struct serial_struct tmp;
-	struct specialix_board *bp = port_Board(port);
-	int change_speed;
-
-	func_enter();
-
-	if (copy_from_user(&tmp, newinfo, sizeof(tmp))) {
-		func_enter();
-		return -EFAULT;
-	}
-
-	mutex_lock(&port->port.mutex);
-	change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
-			(tmp.flags & ASYNC_SPD_MASK));
-	change_speed |= (tmp.custom_divisor != port->custom_divisor);
-
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((tmp.close_delay != port->port.close_delay) ||
-		    (tmp.closing_wait != port->port.closing_wait) ||
-		    ((tmp.flags & ~ASYNC_USR_MASK) !=
-		     (port->port.flags & ~ASYNC_USR_MASK))) {
-			func_exit();
-			mutex_unlock(&port->port.mutex);
-			return -EPERM;
-		}
-		port->port.flags = ((port->port.flags & ~ASYNC_USR_MASK) |
-						(tmp.flags & ASYNC_USR_MASK));
-		port->custom_divisor = tmp.custom_divisor;
-	} else {
-		port->port.flags = ((port->port.flags & ~ASYNC_FLAGS) |
-						(tmp.flags & ASYNC_FLAGS));
-		port->port.close_delay = tmp.close_delay;
-		port->port.closing_wait = tmp.closing_wait;
-		port->custom_divisor = tmp.custom_divisor;
-	}
-	if (change_speed)
-		sx_change_speed(bp, port);
-
-	func_exit();
-	mutex_unlock(&port->port.mutex);
-	return 0;
-}
-
-
-static int sx_get_serial_info(struct specialix_port *port,
-				     struct serial_struct __user *retinfo)
-{
-	struct serial_struct tmp;
-	struct specialix_board *bp = port_Board(port);
-
-	func_enter();
-
-	memset(&tmp, 0, sizeof(tmp));
-	mutex_lock(&port->port.mutex);
-	tmp.type = PORT_CIRRUS;
-	tmp.line = port - sx_port;
-	tmp.port = bp->base;
-	tmp.irq  = bp->irq;
-	tmp.flags = port->port.flags;
-	tmp.baud_base = (SX_OSCFREQ + CD186x_TPC/2) / CD186x_TPC;
-	tmp.close_delay = port->port.close_delay * HZ/100;
-	tmp.closing_wait = port->port.closing_wait * HZ/100;
-	tmp.custom_divisor =  port->custom_divisor;
-	tmp.xmit_fifo_size = CD186x_NFIFO;
-	mutex_unlock(&port->port.mutex);
-	if (copy_to_user(retinfo, &tmp, sizeof(tmp))) {
-		func_exit();
-		return -EFAULT;
-	}
-
-	func_exit();
-	return 0;
-}
-
-
-static int sx_ioctl(struct tty_struct *tty, struct file *filp,
-				unsigned int cmd, unsigned long arg)
-{
-	struct specialix_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_ioctl")) {
-		func_exit();
-		return -ENODEV;
-	}
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		func_exit();
-		return sx_get_serial_info(port, argp);
-	case TIOCSSERIAL:
-		func_exit();
-		return sx_set_serial_info(port, argp);
-	default:
-		func_exit();
-		return -ENOIOCTLCMD;
-	}
-	func_exit();
-	return 0;
-}
-
-
-static void sx_throttle(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_throttle")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	/* Use DTR instead of RTS ! */
-	if (sx_crtscts(tty))
-		port->MSVR &= ~MSVR_DTR;
-	else {
-		/* Auch!!! I think the system shouldn't call this then. */
-		/* Or maybe we're supposed (allowed?) to do our side of hw
-		   handshake anyway, even when hardware handshake is off.
-		   When you see this in your logs, please report.... */
-		printk(KERN_ERR
-		   "sx%d: Need to throttle, but can't (hardware hs is off)\n",
-							port_No(port));
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock_irqrestore(&bp->lock, flags);
-	if (I_IXOFF(tty)) {
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CCR, CCR_SSCH2);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		sx_wait_CCR(bp);
-	}
-	spin_lock_irqsave(&bp->lock, flags);
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock_irqrestore(&bp->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_unthrottle(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_unthrottle")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	/* XXXX Use DTR INSTEAD???? */
-	if (sx_crtscts(tty))
-		port->MSVR |= MSVR_DTR;
-	/* Else clause: see remark in "sx_throttle"... */
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	spin_unlock(&bp->lock);
-	if (I_IXOFF(tty)) {
-		spin_unlock_irqrestore(&port->lock, flags);
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&bp->lock, flags);
-		sx_out(bp, CD186x_CCR, CCR_SSCH1);
-		spin_unlock_irqrestore(&bp->lock, flags);
-		sx_wait_CCR(bp);
-		spin_lock_irqsave(&port->lock, flags);
-	}
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_MSVR, port->MSVR);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_stop(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_stop")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	port->IER &= ~IER_TXRDY;
-	spin_lock(&bp->lock);
-	sx_out(bp, CD186x_CAR, port_No(port));
-	sx_out(bp, CD186x_IER, port->IER);
-	spin_unlock(&bp->lock);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-
-static void sx_start(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_start")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	spin_lock_irqsave(&port->lock, flags);
-	if (port->xmit_cnt && port->xmit_buf && !(port->IER & IER_TXRDY)) {
-		port->IER |= IER_TXRDY;
-		spin_lock(&bp->lock);
-		sx_out(bp, CD186x_CAR, port_No(port));
-		sx_out(bp, CD186x_IER, port->IER);
-		spin_unlock(&bp->lock);
-	}
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	func_exit();
-}
-
-static void sx_hangup(struct tty_struct *tty)
-{
-	struct specialix_port *port = tty->driver_data;
-	struct specialix_board *bp;
-	unsigned long flags;
-
-	func_enter();
-
-	if (sx_paranoia_check(port, tty->name, "sx_hangup")) {
-		func_exit();
-		return;
-	}
-
-	bp = port_Board(port);
-
-	sx_shutdown_port(bp, port);
-	spin_lock_irqsave(&port->lock, flags);
-	bp->count -= port->port.count;
-	if (bp->count < 0) {
-		printk(KERN_ERR
-			"sx%d: sx_hangup: bad board count: %d port: %d\n",
-					board_No(bp), bp->count, tty->index);
-		bp->count = 0;
-	}
-	port->port.count = 0;
-	port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	port->port.tty = NULL;
-	spin_unlock_irqrestore(&port->lock, flags);
-	wake_up_interruptible(&port->port.open_wait);
-
-	func_exit();
-}
-
-
-static void sx_set_termios(struct tty_struct *tty,
-					struct ktermios *old_termios)
-{
-	struct specialix_port *port = tty->driver_data;
-	unsigned long flags;
-	struct specialix_board  *bp;
-
-	if (sx_paranoia_check(port, tty->name, "sx_set_termios"))
-		return;
-
-	bp = port_Board(port);
-	spin_lock_irqsave(&port->lock, flags);
-	sx_change_speed(port_Board(port), port);
-	spin_unlock_irqrestore(&port->lock, flags);
-
-	if ((old_termios->c_cflag & CRTSCTS) &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		sx_start(tty);
-	}
-}
-
-static const struct tty_operations sx_ops = {
-	.open  = sx_open,
-	.close = sx_close,
-	.write = sx_write,
-	.put_char = sx_put_char,
-	.flush_chars = sx_flush_chars,
-	.write_room = sx_write_room,
-	.chars_in_buffer = sx_chars_in_buffer,
-	.flush_buffer = sx_flush_buffer,
-	.ioctl = sx_ioctl,
-	.throttle = sx_throttle,
-	.unthrottle = sx_unthrottle,
-	.set_termios = sx_set_termios,
-	.stop = sx_stop,
-	.start = sx_start,
-	.hangup = sx_hangup,
-	.tiocmget = sx_tiocmget,
-	.tiocmset = sx_tiocmset,
-	.break_ctl = sx_send_break,
-};
-
-static int sx_init_drivers(void)
-{
-	int error;
-	int i;
-
-	func_enter();
-
-	specialix_driver = alloc_tty_driver(SX_NBOARD * SX_NPORT);
-	if (!specialix_driver) {
-		printk(KERN_ERR "sx: Couldn't allocate tty_driver.\n");
-		func_exit();
-		return 1;
-	}
-
-	specialix_driver->owner = THIS_MODULE;
-	specialix_driver->name = "ttyW";
-	specialix_driver->major = SPECIALIX_NORMAL_MAJOR;
-	specialix_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	specialix_driver->subtype = SERIAL_TYPE_NORMAL;
-	specialix_driver->init_termios = tty_std_termios;
-	specialix_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	specialix_driver->init_termios.c_ispeed = 9600;
-	specialix_driver->init_termios.c_ospeed = 9600;
-	specialix_driver->flags = TTY_DRIVER_REAL_RAW |
-						TTY_DRIVER_HARDWARE_BREAK;
-	tty_set_operations(specialix_driver, &sx_ops);
-
-	error = tty_register_driver(specialix_driver);
-	if (error) {
-		put_tty_driver(specialix_driver);
-		printk(KERN_ERR
-		  "sx: Couldn't register specialix IO8+ driver, error = %d\n",
-								error);
-		func_exit();
-		return 1;
-	}
-	memset(sx_port, 0, sizeof(sx_port));
-	for (i = 0; i < SX_NPORT * SX_NBOARD; i++) {
-		sx_port[i].magic = SPECIALIX_MAGIC;
-		tty_port_init(&sx_port[i].port);
-		spin_lock_init(&sx_port[i].lock);
-	}
-
-	func_exit();
-	return 0;
-}
-
-static void sx_release_drivers(void)
-{
-	func_enter();
-
-	tty_unregister_driver(specialix_driver);
-	put_tty_driver(specialix_driver);
-	func_exit();
-}
-
-/*
- * This routine must be called by kernel at boot time
- */
-static int __init specialix_init(void)
-{
-	int i;
-	int found = 0;
-
-	func_enter();
-
-	printk(KERN_INFO "sx: Specialix IO8+ driver v" VERSION ", (c) R.E.Wolff 1997/1998.\n");
-	printk(KERN_INFO "sx: derived from work (c) D.Gorodchanin 1994-1996.\n");
-	if (sx_rtscts)
-		printk(KERN_INFO
-			"sx: DTR/RTS pin is RTS when CRTSCTS is on.\n");
-	else
-		printk(KERN_INFO "sx: DTR/RTS pin is always RTS.\n");
-
-	for (i = 0; i < SX_NBOARD; i++)
-		spin_lock_init(&sx_board[i].lock);
-
-	if (sx_init_drivers()) {
-		func_exit();
-		return -EIO;
-	}
-
-	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].base && !sx_probe(&sx_board[i]))
-			found++;
-
-#ifdef CONFIG_PCI
-	{
-		struct pci_dev *pdev = NULL;
-
-		i = 0;
-		while (i < SX_NBOARD) {
-			if (sx_board[i].flags & SX_BOARD_PRESENT) {
-				i++;
-				continue;
-			}
-			pdev = pci_get_device(PCI_VENDOR_ID_SPECIALIX,
-					PCI_DEVICE_ID_SPECIALIX_IO8, pdev);
-			if (!pdev)
-				break;
-
-			if (pci_enable_device(pdev))
-				continue;
-
-			sx_board[i].irq = pdev->irq;
-
-			sx_board[i].base = pci_resource_start(pdev, 2);
-
-			sx_board[i].flags |= SX_BOARD_IS_PCI;
-			if (!sx_probe(&sx_board[i]))
-				found++;
-		}
-		/* May exit pci_get sequence early with lots of boards */
-		if (pdev != NULL)
-			pci_dev_put(pdev);
-	}
-#endif
-
-	if (!found) {
-		sx_release_drivers();
-		printk(KERN_INFO "sx: No specialix IO8+ boards detected.\n");
-		func_exit();
-		return -EIO;
-	}
-
-	func_exit();
-	return 0;
-}
-
-static int iobase[SX_NBOARD]  = {0,};
-static int irq[SX_NBOARD] = {0,};
-
-module_param_array(iobase, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param(sx_debug, int, 0);
-module_param(sx_rtscts, int, 0);
-module_param(sx_rxfifo, int, 0);
-
-/*
- * You can setup up to 4 boards.
- * by specifying "iobase=0xXXX,0xXXX ..." as insmod parameter.
- * You should specify the IRQs too in that case "irq=....,...".
- *
- * More than 4 boards in one computer is not possible, as the card can
- * only use 4 different interrupts.
- *
- */
-static int __init specialix_init_module(void)
-{
-	int i;
-
-	func_enter();
-
-	if (iobase[0] || iobase[1] || iobase[2] || iobase[3]) {
-		for (i = 0; i < SX_NBOARD; i++) {
-			sx_board[i].base = iobase[i];
-			sx_board[i].irq = irq[i];
-			sx_board[i].count = 0;
-		}
-	}
-
-	func_exit();
-
-	return specialix_init();
-}
-
-static void __exit specialix_exit_module(void)
-{
-	int i;
-
-	func_enter();
-
-	sx_release_drivers();
-	for (i = 0; i < SX_NBOARD; i++)
-		if (sx_board[i].flags & SX_BOARD_PRESENT)
-			sx_release_io_range(&sx_board[i]);
-	func_exit();
-}
-
-static struct pci_device_id specialx_pci_tbl[] __devinitdata __used = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_IO8) },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, specialx_pci_tbl);
-
-module_init(specialix_init_module);
-module_exit(specialix_exit_module);
-
-MODULE_LICENSE("GPL");
-MODULE_ALIAS_CHARDEV_MAJOR(SPECIALIX_NORMAL_MAJOR);
diff -druN linux-libre-2.6.38-gnu/drivers/char/specialix_io8.h linux-libre-2.6.39-gnu/drivers/char/specialix_io8.h
--- linux-libre-2.6.38-gnu/drivers/char/specialix_io8.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/specialix_io8.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,140 +0,0 @@
-/*
- *      linux/drivers/char/specialix_io8.h  -- 
- *                                   Specialix IO8+ multiport serial driver.
- *
- *      Copyright (C) 1997 Roger Wolff (R.E.Wolff@BitWizard.nl)
- *      Copyright (C) 1994-1996  Dmitry Gorodchanin (pgmdsg@ibi.com)
- *
- *
- *      Specialix pays for the development and support of this driver.
- *      Please DO contact io8-linux@specialix.co.uk if you require
- *      support.
- *
- *      This driver was developped in the BitWizard linux device
- *      driver service. If you require a linux device driver for your
- *      product, please contact devices@BitWizard.nl for a quote.
- *
- *      This code is firmly based on the riscom/8 serial driver,
- *      written by Dmitry Gorodchanin. The specialix IO8+ card
- *      programming information was obtained from the CL-CD1865 Data
- *      Book, and Specialix document number 6200059: IO8+ Hardware
- *      Functional Specification.
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the 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 __LINUX_SPECIALIX_H
-#define __LINUX_SPECIALIX_H
-
-#include <linux/serial.h>
-
-#ifdef __KERNEL__
-
-/* You can have max 4 ISA cards in one PC, and I recommend not much 
-more than a few  PCI versions of the card. */
-
-#define SX_NBOARD		8
-
-/* NOTE: Specialix decoder recognizes 4 addresses, but only two are used.... */
-#define SX_IO_SPACE             4
-/* The PCI version decodes 8 addresses, but still only 2 are used. */
-#define SX_PCI_IO_SPACE         8
-
-/* eight ports per board. */
-#define SX_NPORT        	8
-#define SX_BOARD(line)		((line) / SX_NPORT)
-#define SX_PORT(line)		((line) & (SX_NPORT - 1))
-
-
-#define SX_DATA_REG 0     /* Base+0 : Data register */
-#define SX_ADDR_REG 1     /* base+1 : Address register. */
-
-#define MHz *1000000	/* I'm ashamed of myself. */
-
-/* On-board oscillator frequency */
-#define SX_OSCFREQ      (25 MHz/2)
-/* There is a 25MHz crystal on the board, but the chip is in /2 mode */
-
-
-/* Ticks per sec. Used for setting receiver timeout and break length */
-#define SPECIALIX_TPS		4000
-
-/* Yeah, after heavy testing I decided it must be 6.
- * Sure, You can change it if needed.
- */
-#define SPECIALIX_RXFIFO	6	/* Max. receiver FIFO size (1-8) */
-
-#define SPECIALIX_MAGIC		0x0907
-
-#define SX_CCR_TIMEOUT 10000   /* CCR timeout. You may need to wait upto
-                                  10 milliseconds before the internal
-                                  processor is available again after
-                                  you give it a command */
-
-#define SX_IOBASE1	0x100
-#define SX_IOBASE2	0x180
-#define SX_IOBASE3	0x250
-#define SX_IOBASE4	0x260
-
-struct specialix_board {
-	unsigned long   flags;
-	unsigned short	base;
-	unsigned char 	irq;
-	//signed   char	count;
-	int count;
-	unsigned char	DTR;
-        int reg;
-	spinlock_t lock;
-};
-
-#define SX_BOARD_PRESENT	0x00000001
-#define SX_BOARD_ACTIVE		0x00000002
-#define SX_BOARD_IS_PCI		0x00000004
-
-
-struct specialix_port {
-	int			magic;
-	struct tty_port		port;
-	int			baud_base;
-	int			flags;
-	int			timeout;
-	unsigned char 		* xmit_buf;
-	int			custom_divisor;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	short			wakeup_chars;
-	short			break_length;
-	unsigned char		mark_mask;
-	unsigned char		IER;
-	unsigned char		MSVR;
-	unsigned char		COR2;
-	unsigned long		overrun;
-	unsigned long		hits[10];
-	spinlock_t lock;
-};
-
-#endif /* __KERNEL__ */
-#endif /* __LINUX_SPECIALIX_H */
-
-
-
-
-
-
-
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/stallion.c linux-libre-2.6.39-gnu/drivers/char/stallion.c
--- linux-libre-2.6.38-gnu/drivers/char/stallion.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/stallion.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4652 +0,0 @@
-/*****************************************************************************/
-
-/*
- *	stallion.c  -- stallion multiport serial driver.
- *
- *	Copyright (C) 1996-1999  Stallion Technologies
- *	Copyright (C) 1994-1996  Greg Ungerer.
- *
- *	This code is loosely based on the Linux serial driver, written by
- *	Linus Torvalds, Theodore T'so and others.
- *
- *	This program is free software; you can redistribute it and/or modify
- *	it under the terms of the 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/module.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/seq_file.h>
-#include <linux/cd1400.h>
-#include <linux/sc26198.h>
-#include <linux/comstats.h>
-#include <linux/stallion.h>
-#include <linux/ioport.h>
-#include <linux/init.h>
-#include <linux/device.h>
-#include <linux/delay.h>
-#include <linux/ctype.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-#include <linux/pci.h>
-
-/*****************************************************************************/
-
-/*
- *	Define different board types. Use the standard Stallion "assigned"
- *	board numbers. Boards supported in this driver are abbreviated as
- *	EIO = EasyIO and ECH = EasyConnection 8/32.
- */
-#define	BRD_EASYIO	20
-#define	BRD_ECH		21
-#define	BRD_ECHMC	22
-#define	BRD_ECHPCI	26
-#define	BRD_ECH64PCI	27
-#define	BRD_EASYIOPCI	28
-
-struct stlconf {
-	unsigned int	brdtype;
-	int		ioaddr1;
-	int		ioaddr2;
-	unsigned long	memaddr;
-	int		irq;
-	int		irqtype;
-};
-
-static unsigned int stl_nrbrds;
-
-/*****************************************************************************/
-
-/*
- *	Define some important driver characteristics. Device major numbers
- *	allocated as per Linux Device Registry.
- */
-#ifndef	STL_SIOMEMMAJOR
-#define	STL_SIOMEMMAJOR		28
-#endif
-#ifndef	STL_SERIALMAJOR
-#define	STL_SERIALMAJOR		24
-#endif
-#ifndef	STL_CALLOUTMAJOR
-#define	STL_CALLOUTMAJOR	25
-#endif
-
-/*
- *	Set the TX buffer size. Bigger is better, but we don't want
- *	to chew too much memory with buffers!
- */
-#define	STL_TXBUFLOW		512
-#define	STL_TXBUFSIZE		4096
-
-/*****************************************************************************/
-
-/*
- *	Define our local driver identity first. Set up stuff to deal with
- *	all the local structures required by a serial tty driver.
- */
-static char	*stl_drvtitle = "Stallion Multiport Serial Driver";
-static char	*stl_drvname = "stallion";
-static char	*stl_drvversion = "5.6.0";
-
-static struct tty_driver	*stl_serial;
-
-/*
- *	Define a local default termios struct. All ports will be created
- *	with this termios initially. Basically all it defines is a raw port
- *	at 9600, 8 data bits, 1 stop bit.
- */
-static struct ktermios		stl_deftermios = {
-	.c_cflag	= (B9600 | CS8 | CREAD | HUPCL | CLOCAL),
-	.c_cc		= INIT_C_CC,
-	.c_ispeed	= 9600,
-	.c_ospeed	= 9600,
-};
-
-/*
- *	Define global place to put buffer overflow characters.
- */
-static char		stl_unwanted[SC26198_RXFIFOSIZE];
-
-/*****************************************************************************/
-
-static DEFINE_MUTEX(stl_brdslock);
-static struct stlbrd		*stl_brds[STL_MAXBRDS];
-
-static const struct tty_port_operations stl_port_ops;
-
-/*
- *	Per board state flags. Used with the state field of the board struct.
- *	Not really much here!
- */
-#define	BRD_FOUND	0x1
-#define STL_PROBED	0x2
-
-
-/*
- *	Define the port structure istate flags. These set of flags are
- *	modified at interrupt time - so setting and reseting them needs
- *	to be atomic. Use the bit clear/setting routines for this.
- */
-#define	ASYI_TXBUSY	1
-#define	ASYI_TXLOW	2
-#define	ASYI_TXFLOWED	3
-
-/*
- *	Define an array of board names as printable strings. Handy for
- *	referencing boards when printing trace and stuff.
- */
-static char	*stl_brdnames[] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"EasyIO",
-	"EC8/32-AT",
-	"EC8/32-MC",
-	NULL,
-	NULL,
-	NULL,
-	"EC8/32-PCI",
-	"EC8/64-PCI",
-	"EasyIO-PCI",
-};
-
-/*****************************************************************************/
-
-/*
- *	Define some string labels for arguments passed from the module
- *	load line. These allow for easy board definitions, and easy
- *	modification of the io, memory and irq resoucres.
- */
-static unsigned int stl_nargs;
-static char	*board0[4];
-static char	*board1[4];
-static char	*board2[4];
-static char	*board3[4];
-
-static char	**stl_brdsp[] = {
-	(char **) &board0,
-	(char **) &board1,
-	(char **) &board2,
-	(char **) &board3
-};
-
-/*
- *	Define a set of common board names, and types. This is used to
- *	parse any module arguments.
- */
-
-static struct {
-	char	*name;
-	int	type;
-} stl_brdstr[] = {
-	{ "easyio", BRD_EASYIO },
-	{ "eio", BRD_EASYIO },
-	{ "20", BRD_EASYIO },
-	{ "ec8/32", BRD_ECH },
-	{ "ec8/32-at", BRD_ECH },
-	{ "ec8/32-isa", BRD_ECH },
-	{ "ech", BRD_ECH },
-	{ "echat", BRD_ECH },
-	{ "21", BRD_ECH },
-	{ "ec8/32-mc", BRD_ECHMC },
-	{ "ec8/32-mca", BRD_ECHMC },
-	{ "echmc", BRD_ECHMC },
-	{ "echmca", BRD_ECHMC },
-	{ "22", BRD_ECHMC },
-	{ "ec8/32-pc", BRD_ECHPCI },
-	{ "ec8/32-pci", BRD_ECHPCI },
-	{ "26", BRD_ECHPCI },
-	{ "ec8/64-pc", BRD_ECH64PCI },
-	{ "ec8/64-pci", BRD_ECH64PCI },
-	{ "ech-pci", BRD_ECH64PCI },
-	{ "echpci", BRD_ECH64PCI },
-	{ "echpc", BRD_ECH64PCI },
-	{ "27", BRD_ECH64PCI },
-	{ "easyio-pc", BRD_EASYIOPCI },
-	{ "easyio-pci", BRD_EASYIOPCI },
-	{ "eio-pci", BRD_EASYIOPCI },
-	{ "eiopci", BRD_EASYIOPCI },
-	{ "28", BRD_EASYIOPCI },
-};
-
-/*
- *	Define the module agruments.
- */
-
-module_param_array(board0, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board1, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board2, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
-module_param_array(board3, charp, &stl_nargs, 0);
-MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
-
-/*****************************************************************************/
-
-/*
- *	Hardware ID bits for the EasyIO and ECH boards. These defines apply
- *	to the directly accessible io ports of these boards (not the uarts -
- *	they are in cd1400.h and sc26198.h).
- */
-#define	EIO_8PORTRS	0x04
-#define	EIO_4PORTRS	0x05
-#define	EIO_8PORTDI	0x00
-#define	EIO_8PORTM	0x06
-#define	EIO_MK3		0x03
-#define	EIO_IDBITMASK	0x07
-
-#define	EIO_BRDMASK	0xf0
-#define	ID_BRD4		0x10
-#define	ID_BRD8		0x20
-#define	ID_BRD16	0x30
-
-#define	EIO_INTRPEND	0x08
-#define	EIO_INTEDGE	0x00
-#define	EIO_INTLEVEL	0x08
-#define	EIO_0WS		0x10
-
-#define	ECH_ID		0xa0
-#define	ECH_IDBITMASK	0xe0
-#define	ECH_BRDENABLE	0x08
-#define	ECH_BRDDISABLE	0x00
-#define	ECH_INTENABLE	0x01
-#define	ECH_INTDISABLE	0x00
-#define	ECH_INTLEVEL	0x02
-#define	ECH_INTEDGE	0x00
-#define	ECH_INTRPEND	0x01
-#define	ECH_BRDRESET	0x01
-
-#define	ECHMC_INTENABLE	0x01
-#define	ECHMC_BRDRESET	0x02
-
-#define	ECH_PNLSTATUS	2
-#define	ECH_PNL16PORT	0x20
-#define	ECH_PNLIDMASK	0x07
-#define	ECH_PNLXPID	0x40
-#define	ECH_PNLINTRPEND	0x80
-
-#define	ECH_ADDR2MASK	0x1e0
-
-/*
- *	Define the vector mapping bits for the programmable interrupt board
- *	hardware. These bits encode the interrupt for the board to use - it
- *	is software selectable (except the EIO-8M).
- */
-static unsigned char	stl_vecmap[] = {
-	0xff, 0xff, 0xff, 0x04, 0x06, 0x05, 0xff, 0x07,
-	0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
-};
-
-/*
- *	Lock ordering is that you may not take stallion_lock holding
- *	brd_lock.
- */
-
-static spinlock_t brd_lock; 		/* Guard the board mapping */
-static spinlock_t stallion_lock;	/* Guard the tty driver */
-
-/*
- *	Set up enable and disable macros for the ECH boards. They require
- *	the secondary io address space to be activated and deactivated.
- *	This way all ECH boards can share their secondary io region.
- *	If this is an ECH-PCI board then also need to set the page pointer
- *	to point to the correct page.
- */
-#define	BRDENABLE(brdnr,pagenr)						\
-	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
-		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDENABLE),	\
-			stl_brds[(brdnr)]->ioctrl);			\
-	else if (stl_brds[(brdnr)]->brdtype == BRD_ECHPCI)		\
-		outb((pagenr), stl_brds[(brdnr)]->ioctrl);
-
-#define	BRDDISABLE(brdnr)						\
-	if (stl_brds[(brdnr)]->brdtype == BRD_ECH)			\
-		outb((stl_brds[(brdnr)]->ioctrlval | ECH_BRDDISABLE),	\
-			stl_brds[(brdnr)]->ioctrl);
-
-#define	STL_CD1400MAXBAUD	230400
-#define	STL_SC26198MAXBAUD	460800
-
-#define	STL_BAUDBASE		115200
-#define	STL_CLOSEDELAY		(5 * HZ / 10)
-
-/*****************************************************************************/
-
-/*
- *	Define the Stallion PCI vendor and device IDs.
- */
-#ifndef	PCI_VENDOR_ID_STALLION
-#define	PCI_VENDOR_ID_STALLION		0x124d
-#endif
-#ifndef PCI_DEVICE_ID_ECHPCI832
-#define	PCI_DEVICE_ID_ECHPCI832		0x0000
-#endif
-#ifndef PCI_DEVICE_ID_ECHPCI864
-#define	PCI_DEVICE_ID_ECHPCI864		0x0002
-#endif
-#ifndef PCI_DEVICE_ID_EIOPCI
-#define	PCI_DEVICE_ID_EIOPCI		0x0003
-#endif
-
-/*
- *	Define structure to hold all Stallion PCI boards.
- */
-
-static struct pci_device_id stl_pcibrds[] = {
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI864),
-		.driver_data = BRD_ECH64PCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_EIOPCI),
-		.driver_data = BRD_EASYIOPCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_STALLION, PCI_DEVICE_ID_ECHPCI832),
-		.driver_data = BRD_ECHPCI },
-	{ PCI_DEVICE(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410),
-		.driver_data = BRD_ECHPCI },
-	{ }
-};
-MODULE_DEVICE_TABLE(pci, stl_pcibrds);
-
-/*****************************************************************************/
-
-/*
- *	Define macros to extract a brd/port number from a minor number.
- */
-#define	MINOR2BRD(min)		(((min) & 0xc0) >> 6)
-#define	MINOR2PORT(min)		((min) & 0x3f)
-
-/*
- *	Define a baud rate table that converts termios baud rate selector
- *	into the actual baud rate value. All baud rate calculations are
- *	based on the actual baud rate required.
- */
-static unsigned int	stl_baudrates[] = {
-	0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800,
-	9600, 19200, 38400, 57600, 115200, 230400, 460800, 921600
-};
-
-/*****************************************************************************/
-
-/*
- *	Declare all those functions in this driver!
- */
-
-static long	stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
-static int	stl_brdinit(struct stlbrd *brdp);
-static int	stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
-static int	stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-
-/*
- *	CD1400 uart specific handling functions.
- */
-static void	stl_cd1400setreg(struct stlport *portp, int regnr, int value);
-static int	stl_cd1400getreg(struct stlport *portp, int regnr);
-static int	stl_cd1400updatereg(struct stlport *portp, int regnr, int value);
-static int	stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
-static void	stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-static void	stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp);
-static int	stl_cd1400getsignals(struct stlport *portp);
-static void	stl_cd1400setsignals(struct stlport *portp, int dtr, int rts);
-static void	stl_cd1400ccrwait(struct stlport *portp);
-static void	stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx);
-static void	stl_cd1400startrxtx(struct stlport *portp, int rx, int tx);
-static void	stl_cd1400disableintrs(struct stlport *portp);
-static void	stl_cd1400sendbreak(struct stlport *portp, int len);
-static void	stl_cd1400flowctrl(struct stlport *portp, int state);
-static void	stl_cd1400sendflow(struct stlport *portp, int state);
-static void	stl_cd1400flush(struct stlport *portp);
-static int	stl_cd1400datastate(struct stlport *portp);
-static void	stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_cd1400txisr(struct stlpanel *panelp, int ioaddr);
-static void	stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr);
-static void	stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr);
-
-static inline int	stl_cd1400breakisr(struct stlport *portp, int ioaddr);
-
-/*
- *	SC26198 uart specific handling functions.
- */
-static void	stl_sc26198setreg(struct stlport *portp, int regnr, int value);
-static int	stl_sc26198getreg(struct stlport *portp, int regnr);
-static int	stl_sc26198updatereg(struct stlport *portp, int regnr, int value);
-static int	stl_sc26198getglobreg(struct stlport *portp, int regnr);
-static int	stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp);
-static void	stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-static void	stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp);
-static int	stl_sc26198getsignals(struct stlport *portp);
-static void	stl_sc26198setsignals(struct stlport *portp, int dtr, int rts);
-static void	stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx);
-static void	stl_sc26198startrxtx(struct stlport *portp, int rx, int tx);
-static void	stl_sc26198disableintrs(struct stlport *portp);
-static void	stl_sc26198sendbreak(struct stlport *portp, int len);
-static void	stl_sc26198flowctrl(struct stlport *portp, int state);
-static void	stl_sc26198sendflow(struct stlport *portp, int state);
-static void	stl_sc26198flush(struct stlport *portp);
-static int	stl_sc26198datastate(struct stlport *portp);
-static void	stl_sc26198wait(struct stlport *portp);
-static void	stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty);
-static void	stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase);
-static void	stl_sc26198txisr(struct stlport *port);
-static void	stl_sc26198rxisr(struct stlport *port, unsigned int iack);
-static void	stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch);
-static void	stl_sc26198rxbadchars(struct stlport *portp);
-static void	stl_sc26198otherisr(struct stlport *port, unsigned int iack);
-
-/*****************************************************************************/
-
-/*
- *	Generic UART support structure.
- */
-typedef struct uart {
-	int	(*panelinit)(struct stlbrd *brdp, struct stlpanel *panelp);
-	void	(*portinit)(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp);
-	void	(*setport)(struct stlport *portp, struct ktermios *tiosp);
-	int	(*getsignals)(struct stlport *portp);
-	void	(*setsignals)(struct stlport *portp, int dtr, int rts);
-	void	(*enablerxtx)(struct stlport *portp, int rx, int tx);
-	void	(*startrxtx)(struct stlport *portp, int rx, int tx);
-	void	(*disableintrs)(struct stlport *portp);
-	void	(*sendbreak)(struct stlport *portp, int len);
-	void	(*flowctrl)(struct stlport *portp, int state);
-	void	(*sendflow)(struct stlport *portp, int state);
-	void	(*flush)(struct stlport *portp);
-	int	(*datastate)(struct stlport *portp);
-	void	(*intr)(struct stlpanel *panelp, unsigned int iobase);
-} uart_t;
-
-/*
- *	Define some macros to make calling these functions nice and clean.
- */
-#define	stl_panelinit		(* ((uart_t *) panelp->uartp)->panelinit)
-#define	stl_portinit		(* ((uart_t *) portp->uartp)->portinit)
-#define	stl_setport		(* ((uart_t *) portp->uartp)->setport)
-#define	stl_getsignals		(* ((uart_t *) portp->uartp)->getsignals)
-#define	stl_setsignals		(* ((uart_t *) portp->uartp)->setsignals)
-#define	stl_enablerxtx		(* ((uart_t *) portp->uartp)->enablerxtx)
-#define	stl_startrxtx		(* ((uart_t *) portp->uartp)->startrxtx)
-#define	stl_disableintrs	(* ((uart_t *) portp->uartp)->disableintrs)
-#define	stl_sendbreak		(* ((uart_t *) portp->uartp)->sendbreak)
-#define	stl_flowctrl		(* ((uart_t *) portp->uartp)->flowctrl)
-#define	stl_sendflow		(* ((uart_t *) portp->uartp)->sendflow)
-#define	stl_flush		(* ((uart_t *) portp->uartp)->flush)
-#define	stl_datastate		(* ((uart_t *) portp->uartp)->datastate)
-
-/*****************************************************************************/
-
-/*
- *	CD1400 UART specific data initialization.
- */
-static uart_t stl_cd1400uart = {
-	stl_cd1400panelinit,
-	stl_cd1400portinit,
-	stl_cd1400setport,
-	stl_cd1400getsignals,
-	stl_cd1400setsignals,
-	stl_cd1400enablerxtx,
-	stl_cd1400startrxtx,
-	stl_cd1400disableintrs,
-	stl_cd1400sendbreak,
-	stl_cd1400flowctrl,
-	stl_cd1400sendflow,
-	stl_cd1400flush,
-	stl_cd1400datastate,
-	stl_cd1400eiointr
-};
-
-/*
- *	Define the offsets within the register bank of a cd1400 based panel.
- *	These io address offsets are common to the EasyIO board as well.
- */
-#define	EREG_ADDR	0
-#define	EREG_DATA	4
-#define	EREG_RXACK	5
-#define	EREG_TXACK	6
-#define	EREG_MDACK	7
-
-#define	EREG_BANKSIZE	8
-
-#define	CD1400_CLK	25000000
-#define	CD1400_CLK8M	20000000
-
-/*
- *	Define the cd1400 baud rate clocks. These are used when calculating
- *	what clock and divisor to use for the required baud rate. Also
- *	define the maximum baud rate allowed, and the default base baud.
- */
-static int	stl_cd1400clkdivs[] = {
-	CD1400_CLK0, CD1400_CLK1, CD1400_CLK2, CD1400_CLK3, CD1400_CLK4
-};
-
-/*****************************************************************************/
-
-/*
- *	SC26198 UART specific data initization.
- */
-static uart_t stl_sc26198uart = {
-	stl_sc26198panelinit,
-	stl_sc26198portinit,
-	stl_sc26198setport,
-	stl_sc26198getsignals,
-	stl_sc26198setsignals,
-	stl_sc26198enablerxtx,
-	stl_sc26198startrxtx,
-	stl_sc26198disableintrs,
-	stl_sc26198sendbreak,
-	stl_sc26198flowctrl,
-	stl_sc26198sendflow,
-	stl_sc26198flush,
-	stl_sc26198datastate,
-	stl_sc26198intr
-};
-
-/*
- *	Define the offsets within the register bank of a sc26198 based panel.
- */
-#define	XP_DATA		0
-#define	XP_ADDR		1
-#define	XP_MODID	2
-#define	XP_STATUS	2
-#define	XP_IACK		3
-
-#define	XP_BANKSIZE	4
-
-/*
- *	Define the sc26198 baud rate table. Offsets within the table
- *	represent the actual baud rate selector of sc26198 registers.
- */
-static unsigned int	sc26198_baudtable[] = {
-	50, 75, 150, 200, 300, 450, 600, 900, 1200, 1800, 2400, 3600,
-	4800, 7200, 9600, 14400, 19200, 28800, 38400, 57600, 115200,
-	230400, 460800, 921600
-};
-
-#define	SC26198_NRBAUDS		ARRAY_SIZE(sc26198_baudtable)
-
-/*****************************************************************************/
-
-/*
- *	Define the driver info for a user level control device. Used mainly
- *	to get at port stats - only not using the port device itself.
- */
-static const struct file_operations	stl_fsiomem = {
-	.owner		= THIS_MODULE,
-	.unlocked_ioctl	= stl_memioctl,
-	.llseek		= noop_llseek,
-};
-
-static struct class *stallion_class;
-
-static void stl_cd_change(struct stlport *portp)
-{
-	unsigned int oldsigs = portp->sigs;
-	struct tty_struct *tty = tty_port_tty_get(&portp->port);
-
-	if (!tty)
-		return;
-
-	portp->sigs = stl_getsignals(portp);
-
-	if ((portp->sigs & TIOCM_CD) && ((oldsigs & TIOCM_CD) == 0))
-		wake_up_interruptible(&portp->port.open_wait);
-
-	if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
-		if (portp->port.flags & ASYNC_CHECK_CD)
-			tty_hangup(tty);
-	tty_kref_put(tty);
-}
-
-/*
- *	Check for any arguments passed in on the module load command line.
- */
-
-/*****************************************************************************/
-
-/*
- *	Parse the supplied argument string, into the board conf struct.
- */
-
-static int __init stl_parsebrd(struct stlconf *confp, char **argp)
-{
-	char	*sp;
-	unsigned int i;
-
-	pr_debug("stl_parsebrd(confp=%p,argp=%p)\n", confp, argp);
-
-	if ((argp[0] == NULL) || (*argp[0] == 0))
-		return 0;
-
-	for (sp = argp[0], i = 0; (*sp != 0) && (i < 25); sp++, i++)
-		*sp = tolower(*sp);
-
-	for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++)
-		if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
-			break;
-
-	if (i == ARRAY_SIZE(stl_brdstr)) {
-		printk("STALLION: unknown board name, %s?\n", argp[0]);
-		return 0;
-	}
-
-	confp->brdtype = stl_brdstr[i].type;
-
-	i = 1;
-	if ((argp[i] != NULL) && (*argp[i] != 0))
-		confp->ioaddr1 = simple_strtoul(argp[i], NULL, 0);
-	i++;
-	if (confp->brdtype == BRD_ECH) {
-		if ((argp[i] != NULL) && (*argp[i] != 0))
-			confp->ioaddr2 = simple_strtoul(argp[i], NULL, 0);
-		i++;
-	}
-	if ((argp[i] != NULL) && (*argp[i] != 0))
-		confp->irq = simple_strtoul(argp[i], NULL, 0);
-	return 1;
-}
-
-/*****************************************************************************/
-
-/*
- *	Allocate a new board structure. Fill out the basic info in it.
- */
-
-static struct stlbrd *stl_allocbrd(void)
-{
-	struct stlbrd	*brdp;
-
-	brdp = kzalloc(sizeof(struct stlbrd), GFP_KERNEL);
-	if (!brdp) {
-		printk("STALLION: failed to allocate memory (size=%Zd)\n",
-			sizeof(struct stlbrd));
-		return NULL;
-	}
-
-	brdp->magic = STL_BOARDMAGIC;
-	return brdp;
-}
-
-/*****************************************************************************/
-
-static int stl_activate(struct tty_port *port, struct tty_struct *tty)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	if (!portp->tx.buf) {
-		portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
-		if (!portp->tx.buf)
-			return -ENOMEM;
-		portp->tx.head = portp->tx.buf;
-		portp->tx.tail = portp->tx.buf;
-	}
-	stl_setport(portp, tty->termios);
-	portp->sigs = stl_getsignals(portp);
-	stl_setsignals(portp, 1, 1);
-	stl_enablerxtx(portp, 1, 1);
-	stl_startrxtx(portp, 1, 0);
-	return 0;
-}
-
-static int stl_open(struct tty_struct *tty, struct file *filp)
-{
-	struct stlport	*portp;
-	struct stlbrd	*brdp;
-	unsigned int	minordev, brdnr, panelnr;
-	int		portnr;
-
-	pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
-
-	minordev = tty->index;
-	brdnr = MINOR2BRD(minordev);
-	if (brdnr >= stl_nrbrds)
-		return -ENODEV;
-	brdp = stl_brds[brdnr];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	minordev = MINOR2PORT(minordev);
-	for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
-		if (brdp->panels[panelnr] == NULL)
-			break;
-		if (minordev < brdp->panels[panelnr]->nrports) {
-			portnr = minordev;
-			break;
-		}
-		minordev -= brdp->panels[panelnr]->nrports;
-	}
-	if (portnr < 0)
-		return -ENODEV;
-
-	portp = brdp->panels[panelnr]->ports[portnr];
-	if (portp == NULL)
-		return -ENODEV;
-
-	tty->driver_data = portp;
-	return tty_port_open(&portp->port, tty, filp);
-
-}
-
-/*****************************************************************************/
-
-static int stl_carrier_raised(struct tty_port *port)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	return (portp->sigs & TIOCM_CD) ? 1 : 0;
-}
-
-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, on, on);
-}
-
-/*****************************************************************************/
-
-static void stl_flushbuffer(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_flushbuffer(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	stl_flush(portp);
-	tty_wakeup(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_waituntilsent(struct tty_struct *tty, int timeout)
-{
-	struct stlport	*portp;
-	unsigned long	tend;
-
-	pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (timeout == 0)
-		timeout = HZ;
-	tend = jiffies + timeout;
-
-	while (stl_datastate(portp)) {
-		if (signal_pending(current))
-			break;
-		msleep_interruptible(20);
-		if (time_after_eq(jiffies, tend))
-			break;
-	}
-}
-
-/*****************************************************************************/
-
-static void stl_shutdown(struct tty_port *port)
-{
-	struct stlport *portp = container_of(port, struct stlport, port);
-	stl_disableintrs(portp);
-	stl_enablerxtx(portp, 0, 0);
-	stl_flush(portp);
-	portp->istate = 0;
-	if (portp->tx.buf != NULL) {
-		kfree(portp->tx.buf);
-		portp->tx.buf = NULL;
-		portp->tx.head = NULL;
-		portp->tx.tail = NULL;
-	}
-}
-
-static void stl_close(struct tty_struct *tty, struct file *filp)
-{
-	struct stlport*portp;
-	pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
-
-	portp = tty->driver_data;
-	if(portp == NULL)
-		return;
-	tty_port_close(&portp->port, tty, filp);
-}
-
-/*****************************************************************************/
-
-/*
- *	Write routine. Take data and stuff it in to the TX ring queue.
- *	If transmit interrupts are not running then start them.
- */
-
-static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
-{
-	struct stlport	*portp;
-	unsigned int	len, stlen;
-	unsigned char	*chbuf;
-	char		*head, *tail;
-
-	pr_debug("stl_write(tty=%p,buf=%p,count=%d)\n", tty, buf, count);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-/*
- *	If copying direct from user space we must cater for page faults,
- *	causing us to "sleep" here for a while. To handle this copy in all
- *	the data we need now, into a local buffer. Then when we got it all
- *	copy it into the TX buffer.
- */
-	chbuf = (unsigned char *) buf;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	if (head >= tail) {
-		len = STL_TXBUFSIZE - (head - tail) - 1;
-		stlen = STL_TXBUFSIZE - (head - portp->tx.buf);
-	} else {
-		len = tail - head - 1;
-		stlen = len;
-	}
-
-	len = min(len, (unsigned int)count);
-	count = 0;
-	while (len > 0) {
-		stlen = min(len, stlen);
-		memcpy(head, chbuf, stlen);
-		len -= stlen;
-		chbuf += stlen;
-		count += stlen;
-		head += stlen;
-		if (head >= (portp->tx.buf + STL_TXBUFSIZE)) {
-			head = portp->tx.buf;
-			stlen = tail - head;
-		}
-	}
-	portp->tx.head = head;
-
-	clear_bit(ASYI_TXLOW, &portp->istate);
-	stl_startrxtx(portp, -1, 1);
-
-	return count;
-}
-
-/*****************************************************************************/
-
-static int stl_putchar(struct tty_struct *tty, unsigned char ch)
-{
-	struct stlport	*portp;
-	unsigned int	len;
-	char		*head, *tail;
-
-	pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-	if (portp->tx.buf == NULL)
-		return -EINVAL;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-
-	len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail)) : (tail - head);
-	len--;
-
-	if (len > 0) {
-		*head++ = ch;
-		if (head >= (portp->tx.buf + STL_TXBUFSIZE))
-			head = portp->tx.buf;
-	}	
-	portp->tx.head = head;
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	If there are any characters in the buffer then make sure that TX
- *	interrupts are on and get'em out. Normally used after the putchar
- *	routine has been called.
- */
-
-static void stl_flushchars(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_flushchars(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	if (portp->tx.buf == NULL)
-		return;
-
-	stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-static int stl_writeroom(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-	char		*head, *tail;
-
-	pr_debug("stl_writeroom(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	return (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return number of chars in the TX buffer. Normally we would just
- *	calculate the number of chars in the buffer and return that, but if
- *	the buffer is empty and TX interrupts are still on then we return
- *	that the buffer still has 1 char in it. This way whoever called us
- *	will not think that ALL chars have drained - since the UART still
- *	must have some chars in it (we are busy after all).
- */
-
-static int stl_charsinbuffer(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-	unsigned int	size;
-	char		*head, *tail;
-
-	pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return 0;
-	if (portp->tx.buf == NULL)
-		return 0;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
-		size = 1;
-	return size;
-}
-
-/*****************************************************************************/
-
-/*
- *	Generate the serial struct info.
- */
-
-static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
-{
-	struct serial_struct	sio;
-	struct stlbrd		*brdp;
-
-	pr_debug("stl_getserial(portp=%p,sp=%p)\n", portp, sp);
-
-	memset(&sio, 0, sizeof(struct serial_struct));
-
-	mutex_lock(&portp->port.mutex);
-	sio.line = portp->portnr;
-	sio.port = portp->ioaddr;
-	sio.flags = portp->port.flags;
-	sio.baud_base = portp->baud_base;
-	sio.close_delay = portp->close_delay;
-	sio.closing_wait = portp->closing_wait;
-	sio.custom_divisor = portp->custom_divisor;
-	sio.hub6 = 0;
-	if (portp->uartp == &stl_cd1400uart) {
-		sio.type = PORT_CIRRUS;
-		sio.xmit_fifo_size = CD1400_TXFIFOSIZE;
-	} else {
-		sio.type = PORT_UNKNOWN;
-		sio.xmit_fifo_size = SC26198_TXFIFOSIZE;
-	}
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp != NULL)
-		sio.irq = brdp->irq;
-	mutex_unlock(&portp->port.mutex);
-
-	return copy_to_user(sp, &sio, sizeof(struct serial_struct)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Set port according to the serial struct info.
- *	At this point we do not do any auto-configure stuff, so we will
- *	just quietly ignore any requests to change irq, etc.
- */
-
-static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
-{
-	struct stlport *	portp = tty->driver_data;
-	struct serial_struct	sio;
-
-	pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
-
-	if (copy_from_user(&sio, sp, sizeof(struct serial_struct)))
-		return -EFAULT;
-	mutex_lock(&portp->port.mutex);
-	if (!capable(CAP_SYS_ADMIN)) {
-		if ((sio.baud_base != portp->baud_base) ||
-		    (sio.close_delay != portp->close_delay) ||
-		    ((sio.flags & ~ASYNC_USR_MASK) !=
-		    (portp->port.flags & ~ASYNC_USR_MASK))) {
-			mutex_unlock(&portp->port.mutex);
-			return -EPERM;
-		}
-	} 
-
-	portp->port.flags = (portp->port.flags & ~ASYNC_USR_MASK) |
-		(sio.flags & ASYNC_USR_MASK);
-	portp->baud_base = sio.baud_base;
-	portp->close_delay = sio.close_delay;
-	portp->closing_wait = sio.closing_wait;
-	portp->custom_divisor = sio.custom_divisor;
-	mutex_unlock(&portp->port.mutex);
-	stl_setport(portp, tty->termios);
-	return 0;
-}
-
-/*****************************************************************************/
-
-static int stl_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct stlport	*portp;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	return stl_getsignals(portp);
-}
-
-static int stl_tiocmset(struct tty_struct *tty, struct file *file,
-			unsigned int set, unsigned int clear)
-{
-	struct stlport	*portp;
-	int rts = -1, dtr = -1;
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-	if (tty->flags & (1 << TTY_IO_ERROR))
-		return -EIO;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	stl_setsignals(portp, dtr, rts);
-	return 0;
-}
-
-static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg)
-{
-	struct stlport	*portp;
-	int		rc;
-	void __user *argp = (void __user *)arg;
-
-	pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
-			arg);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
- 	    (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS))
-		if (tty->flags & (1 << TTY_IO_ERROR))
-			return -EIO;
-
-	rc = 0;
-
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = stl_getserial(portp, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = stl_setserial(tty, argp);
-		break;
-	case COM_GETPORTSTATS:
-		rc = stl_getportstats(tty, portp, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stl_clrportstats(portp, argp);
-		break;
-	case TIOCSERCONFIG:
-	case TIOCSERGWILD:
-	case TIOCSERSWILD:
-	case TIOCSERGETLSR:
-	case TIOCSERGSTRUCT:
-	case TIOCSERGETMULTI:
-	case TIOCSERSETMULTI:
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-/*****************************************************************************/
-
-/*
- *	Start the transmitter again. Just turn TX interrupts back on.
- */
-
-static void stl_start(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_start(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_startrxtx(portp, -1, 1);
-}
-
-/*****************************************************************************/
-
-static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
-{
-	struct stlport	*portp;
-	struct ktermios	*tiosp;
-
-	pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	tiosp = tty->termios;
-	if ((tiosp->c_cflag == old->c_cflag) &&
-	    (tiosp->c_iflag == old->c_iflag))
-		return;
-
-	stl_setport(portp, tiosp);
-	stl_setsignals(portp, ((tiosp->c_cflag & (CBAUD & ~CBAUDEX)) ? 1 : 0),
-		-1);
-	if ((old->c_cflag & CRTSCTS) && ((tiosp->c_cflag & CRTSCTS) == 0)) {
-		tty->hw_stopped = 0;
-		stl_start(tty);
-	}
-	if (((old->c_cflag & CLOCAL) == 0) && (tiosp->c_cflag & CLOCAL))
-		wake_up_interruptible(&portp->port.open_wait);
-}
-
-/*****************************************************************************/
-
-/*
- *	Attempt to flow control who ever is sending us data. Based on termios
- *	settings use software or/and hardware flow control.
- */
-
-static void stl_throttle(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_throttle(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_flowctrl(portp, 0);
-}
-
-/*****************************************************************************/
-
-/*
- *	Unflow control the device sending us data...
- */
-
-static void stl_unthrottle(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_unthrottle(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_flowctrl(portp, 1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Stop the transmitter. Basically to do this we will just turn TX
- *	interrupts off.
- */
-
-static void stl_stop(struct tty_struct *tty)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_stop(tty=%p)\n", tty);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-	stl_startrxtx(portp, -1, 0);
-}
-
-/*****************************************************************************/
-
-/*
- *	Hangup this port. This is pretty much like closing the port, only
- *	a little more brutal. No waiting for data to drain. Shutdown the
- *	port and maybe drop signals.
- */
-
-static void stl_hangup(struct tty_struct *tty)
-{
-	struct stlport	*portp = tty->driver_data;
-	pr_debug("stl_hangup(tty=%p)\n", tty);
-
-	if (portp == NULL)
-		return;
-	tty_port_hangup(&portp->port);
-}
-
-/*****************************************************************************/
-
-static int stl_breakctl(struct tty_struct *tty, int state)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return -EINVAL;
-
-	stl_sendbreak(portp, ((state == -1) ? 1 : 2));
-	return 0;
-}
-
-/*****************************************************************************/
-
-static void stl_sendxchar(struct tty_struct *tty, char ch)
-{
-	struct stlport	*portp;
-
-	pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
-
-	portp = tty->driver_data;
-	if (portp == NULL)
-		return;
-
-	if (ch == STOP_CHAR(tty))
-		stl_sendflow(portp, 0);
-	else if (ch == START_CHAR(tty))
-		stl_sendflow(portp, 1);
-	else
-		stl_putchar(tty, ch);
-}
-
-static void stl_portinfo(struct seq_file *m, struct stlport *portp, int portnr)
-{
-	int	sigs;
-	char sep;
-
-	seq_printf(m, "%d: uart:%s tx:%d rx:%d",
-		portnr, (portp->hwid == 1) ? "SC26198" : "CD1400",
-		(int) portp->stats.txtotal, (int) portp->stats.rxtotal);
-
-	if (portp->stats.rxframing)
-		seq_printf(m, " fe:%d", (int) portp->stats.rxframing);
-	if (portp->stats.rxparity)
-		seq_printf(m, " pe:%d", (int) portp->stats.rxparity);
-	if (portp->stats.rxbreaks)
-		seq_printf(m, " brk:%d", (int) portp->stats.rxbreaks);
-	if (portp->stats.rxoverrun)
-		seq_printf(m, " oe:%d", (int) portp->stats.rxoverrun);
-
-	sigs = stl_getsignals(portp);
-	sep = ' ';
-	if (sigs & TIOCM_RTS) {
-		seq_printf(m, "%c%s", sep, "RTS");
-		sep = '|';
-	}
-	if (sigs & TIOCM_CTS) {
-		seq_printf(m, "%c%s", sep, "CTS");
-		sep = '|';
-	}
-	if (sigs & TIOCM_DTR) {
-		seq_printf(m, "%c%s", sep, "DTR");
-		sep = '|';
-	}
-	if (sigs & TIOCM_CD) {
-		seq_printf(m, "%c%s", sep, "DCD");
-		sep = '|';
-	}
-	if (sigs & TIOCM_DSR) {
-		seq_printf(m, "%c%s", sep, "DSR");
-		sep = '|';
-	}
-	seq_putc(m, '\n');
-}
-
-/*****************************************************************************/
-
-/*
- *	Port info, read from the /proc file system.
- */
-
-static int stl_proc_show(struct seq_file *m, void *v)
-{
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-	struct stlport	*portp;
-	unsigned int	brdnr, panelnr, portnr;
-	int		totalport;
-
-	totalport = 0;
-
-	seq_printf(m, "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-/*
- *	We scan through for each board, panel and port. The offset is
- *	calculated on the fly, and irrelevant ports are skipped.
- */
-	for (brdnr = 0; brdnr < stl_nrbrds; brdnr++) {
-		brdp = stl_brds[brdnr];
-		if (brdp == NULL)
-			continue;
-		if (brdp->state == 0)
-			continue;
-
-		totalport = brdnr * STL_MAXPORTS;
-		for (panelnr = 0; panelnr < brdp->nrpanels; panelnr++) {
-			panelp = brdp->panels[panelnr];
-			if (panelp == NULL)
-				continue;
-
-			for (portnr = 0; portnr < panelp->nrports; portnr++,
-			    totalport++) {
-				portp = panelp->ports[portnr];
-				if (portp == NULL)
-					continue;
-				stl_portinfo(m, portp, totalport);
-			}
-		}
-	}
-	return 0;
-}
-
-static int stl_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, stl_proc_show, NULL);
-}
-
-static const struct file_operations stl_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= stl_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*****************************************************************************/
-
-/*
- *	All board interrupts are vectored through here first. This code then
- *	calls off to the approrpriate board interrupt handlers.
- */
-
-static irqreturn_t stl_intr(int irq, void *dev_id)
-{
-	struct stlbrd *brdp = dev_id;
-
-	pr_debug("stl_intr(brdp=%p,irq=%d)\n", brdp, brdp->irq);
-
-	return IRQ_RETVAL((* brdp->isr)(brdp));
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for EasyIO board types.
- */
-
-static int stl_eiointr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	iobase;
-	int		handled = 0;
-
-	spin_lock(&brd_lock);
-	panelp = brdp->panels[0];
-	iobase = panelp->iobase;
-	while (inb(brdp->iostatus) & EIO_INTRPEND) {
-		handled = 1;
-		(* panelp->isr)(panelp, iobase);
-	}
-	spin_unlock(&brd_lock);
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-AT board types.
- */
-
-static int stl_echatintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
-
-	while (inb(brdp->iostatus) & ECH_INTRPEND) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-
-	outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
-
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-MCA board types.
- */
-
-static int stl_echmcaintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	while (inb(brdp->iostatus) & ECH_INTRPEND) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-PCI board types.
- */
-
-static int stl_echpciintr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr, recheck;
-	int		handled = 0;
-
-	while (1) {
-		recheck = 0;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			outb(brdp->bnkpageaddr[bnknr], brdp->ioctrl);
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-				recheck++;
-				handled = 1;
-			}
-		}
-		if (! recheck)
-			break;
-	}
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for ECH-8/64-PCI board types.
- */
-
-static int stl_echpci64intr(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	ioaddr, bnknr;
-	int		handled = 0;
-
-	while (inb(brdp->ioctrl) & 0x1) {
-		handled = 1;
-		for (bnknr = 0; bnknr < brdp->nrbnks; bnknr++) {
-			ioaddr = brdp->bnkstataddr[bnknr];
-			if (inb(ioaddr) & ECH_PNLINTRPEND) {
-				panelp = brdp->bnk2panel[bnknr];
-				(* panelp->isr)(panelp, (ioaddr & 0xfffc));
-			}
-		}
-	}
-
-	return handled;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize all the ports on a panel.
- */
-
-static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	struct stlport *portp;
-	unsigned int i;
-	int chipmask;
-
-	pr_debug("stl_initports(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	chipmask = stl_panelinit(brdp, panelp);
-
-/*
- *	All UART's are initialized (if found!). Now go through and setup
- *	each ports data structures.
- */
-	for (i = 0; i < panelp->nrports; i++) {
-		portp = kzalloc(sizeof(struct stlport), GFP_KERNEL);
-		if (!portp) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlport));
-			break;
-		}
-		tty_port_init(&portp->port);
-		portp->port.ops = &stl_port_ops;
-		portp->magic = STL_PORTMAGIC;
-		portp->portnr = i;
-		portp->brdnr = panelp->brdnr;
-		portp->panelnr = panelp->panelnr;
-		portp->uartp = panelp->uartp;
-		portp->clk = brdp->clk;
-		portp->baud_base = STL_BAUDBASE;
-		portp->close_delay = STL_CLOSEDELAY;
-		portp->closing_wait = 30 * HZ;
-		init_waitqueue_head(&portp->port.open_wait);
-		init_waitqueue_head(&portp->port.close_wait);
-		portp->stats.brd = portp->brdnr;
-		portp->stats.panel = portp->panelnr;
-		portp->stats.port = portp->portnr;
-		panelp->ports[i] = portp;
-		stl_portinit(brdp, panelp, portp);
-	}
-
-	return 0;
-}
-
-static void stl_cleanup_panels(struct stlbrd *brdp)
-{
-	struct stlpanel *panelp;
-	struct stlport *portp;
-	unsigned int j, k;
-	struct tty_struct *tty;
-
-	for (j = 0; j < STL_MAXPANELS; j++) {
-		panelp = brdp->panels[j];
-		if (panelp == NULL)
-			continue;
-		for (k = 0; k < STL_PORTSPERPANEL; k++) {
-			portp = panelp->ports[k];
-			if (portp == NULL)
-				continue;
-			tty = tty_port_tty_get(&portp->port);
-			if (tty != NULL) {
-				stl_hangup(tty);
-				tty_kref_put(tty);
-			}
-			kfree(portp->tx.buf);
-			kfree(portp);
-		}
-		kfree(panelp);
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find and initialize an EasyIO board.
- */
-
-static int __devinit stl_initeio(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	status;
-	char		*name;
-	int		retval;
-
-	pr_debug("stl_initeio(brdp=%p)\n", brdp);
-
-	brdp->ioctrl = brdp->ioaddr1 + 1;
-	brdp->iostatus = brdp->ioaddr1 + 2;
-
-	status = inb(brdp->iostatus);
-	if ((status & EIO_IDBITMASK) == EIO_MK3)
-		brdp->ioctrl++;
-
-/*
- *	Handle board specific stuff now. The real difference is PCI
- *	or not PCI.
- */
-	if (brdp->brdtype == BRD_EASYIOPCI) {
-		brdp->iosize1 = 0x80;
-		brdp->iosize2 = 0x80;
-		name = "serial(EIO-PCI)";
-		outb(0x41, (brdp->ioaddr2 + 0x4c));
-	} else {
-		brdp->iosize1 = 8;
-		name = "serial(EIO)";
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		outb((stl_vecmap[brdp->irq] | EIO_0WS |
-			((brdp->irqtype) ? EIO_INTLEVEL : EIO_INTEDGE)),
-			brdp->ioctrl);
-	}
-
-	retval = -EBUSY;
-	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
-		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
-			"%x conflicts with another device\n", brdp->brdnr, 
-			brdp->ioaddr1);
-		goto err;
-	}
-	
-	if (brdp->iosize2 > 0)
-		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
-			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
-				"address %x conflicts with another device\n",
-				brdp->brdnr, brdp->ioaddr2);
-			printk(KERN_WARNING "STALLION: Warning, also "
-				"releasing board %d I/O address %x \n", 
-				brdp->brdnr, brdp->ioaddr1);
-			goto err_rel1;
-		}
-
-/*
- *	Everything looks OK, so let's go ahead and probe for the hardware.
- */
-	brdp->clk = CD1400_CLK;
-	brdp->isr = stl_eiointr;
-
-	retval = -ENODEV;
-	switch (status & EIO_IDBITMASK) {
-	case EIO_8PORTM:
-		brdp->clk = CD1400_CLK8M;
-		/* fall thru */
-	case EIO_8PORTRS:
-	case EIO_8PORTDI:
-		brdp->nrports = 8;
-		break;
-	case EIO_4PORTRS:
-		brdp->nrports = 4;
-		break;
-	case EIO_MK3:
-		switch (status & EIO_BRDMASK) {
-		case ID_BRD4:
-			brdp->nrports = 4;
-			break;
-		case ID_BRD8:
-			brdp->nrports = 8;
-			break;
-		case ID_BRD16:
-			brdp->nrports = 16;
-			break;
-		default:
-			goto err_rel2;
-		}
-		break;
-	default:
-		goto err_rel2;
-	}
-
-/*
- *	We have verified that the board is actually present, so now we
- *	can complete the setup.
- */
-
-	panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
-	if (!panelp) {
-		printk(KERN_WARNING "STALLION: failed to allocate memory "
-			"(size=%Zd)\n", sizeof(struct stlpanel));
-		retval = -ENOMEM;
-		goto err_rel2;
-	}
-
-	panelp->magic = STL_PANELMAGIC;
-	panelp->brdnr = brdp->brdnr;
-	panelp->panelnr = 0;
-	panelp->nrports = brdp->nrports;
-	panelp->iobase = brdp->ioaddr1;
-	panelp->hwid = status;
-	if ((status & EIO_IDBITMASK) == EIO_MK3) {
-		panelp->uartp = &stl_sc26198uart;
-		panelp->isr = stl_sc26198intr;
-	} else {
-		panelp->uartp = &stl_cd1400uart;
-		panelp->isr = stl_cd1400eiointr;
-	}
-
-	brdp->panels[0] = panelp;
-	brdp->nrpanels = 1;
-	brdp->state |= BRD_FOUND;
-	brdp->hwid = status;
-	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
-		printk("STALLION: failed to register interrupt "
-		    "routine for %s irq=%d\n", name, brdp->irq);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-
-	return 0;
-err_fr:
-	stl_cleanup_panels(brdp);
-err_rel2:
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err_rel1:
-	release_region(brdp->ioaddr1, brdp->iosize1);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Try to find an ECH board and initialize it. This code is capable of
- *	dealing with all types of ECH board.
- */
-
-static int __devinit stl_initech(struct stlbrd *brdp)
-{
-	struct stlpanel	*panelp;
-	unsigned int	status, nxtid, ioaddr, conflict, panelnr, banknr, i;
-	int		retval;
-	char		*name;
-
-	pr_debug("stl_initech(brdp=%p)\n", brdp);
-
-	status = 0;
-	conflict = 0;
-
-/*
- *	Set up the initial board register contents for boards. This varies a
- *	bit between the different board types. So we need to handle each
- *	separately. Also do a check that the supplied IRQ is good.
- */
-	switch (brdp->brdtype) {
-
-	case BRD_ECH:
-		brdp->isr = stl_echatintr;
-		brdp->ioctrl = brdp->ioaddr1 + 1;
-		brdp->iostatus = brdp->ioaddr1 + 1;
-		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID) {
-			retval = -ENODEV;
-			goto err;
-		}
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		status = ((brdp->ioaddr2 & ECH_ADDR2MASK) >> 1);
-		status |= (stl_vecmap[brdp->irq] << 1);
-		outb((status | ECH_BRDRESET), brdp->ioaddr1);
-		brdp->ioctrlval = ECH_INTENABLE |
-			((brdp->irqtype) ? ECH_INTLEVEL : ECH_INTEDGE);
-		for (i = 0; i < 10; i++)
-			outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
-		brdp->iosize1 = 2;
-		brdp->iosize2 = 32;
-		name = "serial(EC8/32)";
-		outb(status, brdp->ioaddr1);
-		break;
-
-	case BRD_ECHMC:
-		brdp->isr = stl_echmcaintr;
-		brdp->ioctrl = brdp->ioaddr1 + 0x20;
-		brdp->iostatus = brdp->ioctrl;
-		status = inb(brdp->iostatus);
-		if ((status & ECH_IDBITMASK) != ECH_ID) {
-			retval = -ENODEV;
-			goto err;
-		}
-		if ((brdp->irq < 0) || (brdp->irq > 15) ||
-		    (stl_vecmap[brdp->irq] == (unsigned char) 0xff)) {
-			printk("STALLION: invalid irq=%d for brd=%d\n",
-				brdp->irq, brdp->brdnr);
-			retval = -EINVAL;
-			goto err;
-		}
-		outb(ECHMC_BRDRESET, brdp->ioctrl);
-		outb(ECHMC_INTENABLE, brdp->ioctrl);
-		brdp->iosize1 = 64;
-		name = "serial(EC8/32-MC)";
-		break;
-
-	case BRD_ECHPCI:
-		brdp->isr = stl_echpciintr;
-		brdp->ioctrl = brdp->ioaddr1 + 2;
-		brdp->iosize1 = 4;
-		brdp->iosize2 = 8;
-		name = "serial(EC8/32-PCI)";
-		break;
-
-	case BRD_ECH64PCI:
-		brdp->isr = stl_echpci64intr;
-		brdp->ioctrl = brdp->ioaddr2 + 0x40;
-		outb(0x43, (brdp->ioaddr1 + 0x4c));
-		brdp->iosize1 = 0x80;
-		brdp->iosize2 = 0x80;
-		name = "serial(EC8/64-PCI)";
-		break;
-
-	default:
-		printk("STALLION: unknown board type=%d\n", brdp->brdtype);
-		retval = -EINVAL;
-		goto err;
-	}
-
-/*
- *	Check boards for possible IO address conflicts and return fail status 
- * 	if an IO conflict found.
- */
-	retval = -EBUSY;
-	if (!request_region(brdp->ioaddr1, brdp->iosize1, name)) {
-		printk(KERN_WARNING "STALLION: Warning, board %d I/O address "
-			"%x conflicts with another device\n", brdp->brdnr, 
-			brdp->ioaddr1);
-		goto err;
-	}
-	
-	if (brdp->iosize2 > 0)
-		if (!request_region(brdp->ioaddr2, brdp->iosize2, name)) {
-			printk(KERN_WARNING "STALLION: Warning, board %d I/O "
-				"address %x conflicts with another device\n",
-				brdp->brdnr, brdp->ioaddr2);
-			printk(KERN_WARNING "STALLION: Warning, also "
-				"releasing board %d I/O address %x \n", 
-				brdp->brdnr, brdp->ioaddr1);
-			goto err_rel1;
-		}
-
-/*
- *	Scan through the secondary io address space looking for panels.
- *	As we find'em allocate and initialize panel structures for each.
- */
-	brdp->clk = CD1400_CLK;
-	brdp->hwid = status;
-
-	ioaddr = brdp->ioaddr2;
-	banknr = 0;
-	panelnr = 0;
-	nxtid = 0;
-
-	for (i = 0; i < STL_MAXPANELS; i++) {
-		if (brdp->brdtype == BRD_ECHPCI) {
-			outb(nxtid, brdp->ioctrl);
-			ioaddr = brdp->ioaddr2;
-		}
-		status = inb(ioaddr + ECH_PNLSTATUS);
-		if ((status & ECH_PNLIDMASK) != nxtid)
-			break;
-		panelp = kzalloc(sizeof(struct stlpanel), GFP_KERNEL);
-		if (!panelp) {
-			printk("STALLION: failed to allocate memory "
-				"(size=%Zd)\n", sizeof(struct stlpanel));
-			retval = -ENOMEM;
-			goto err_fr;
-		}
-		panelp->magic = STL_PANELMAGIC;
-		panelp->brdnr = brdp->brdnr;
-		panelp->panelnr = panelnr;
-		panelp->iobase = ioaddr;
-		panelp->pagenr = nxtid;
-		panelp->hwid = status;
-		brdp->bnk2panel[banknr] = panelp;
-		brdp->bnkpageaddr[banknr] = nxtid;
-		brdp->bnkstataddr[banknr++] = ioaddr + ECH_PNLSTATUS;
-
-		if (status & ECH_PNLXPID) {
-			panelp->uartp = &stl_sc26198uart;
-			panelp->isr = stl_sc26198intr;
-			if (status & ECH_PNL16PORT) {
-				panelp->nrports = 16;
-				brdp->bnk2panel[banknr] = panelp;
-				brdp->bnkpageaddr[banknr] = nxtid;
-				brdp->bnkstataddr[banknr++] = ioaddr + 4 +
-					ECH_PNLSTATUS;
-			} else
-				panelp->nrports = 8;
-		} else {
-			panelp->uartp = &stl_cd1400uart;
-			panelp->isr = stl_cd1400echintr;
-			if (status & ECH_PNL16PORT) {
-				panelp->nrports = 16;
-				panelp->ackmask = 0x80;
-				if (brdp->brdtype != BRD_ECHPCI)
-					ioaddr += EREG_BANKSIZE;
-				brdp->bnk2panel[banknr] = panelp;
-				brdp->bnkpageaddr[banknr] = ++nxtid;
-				brdp->bnkstataddr[banknr++] = ioaddr +
-					ECH_PNLSTATUS;
-			} else {
-				panelp->nrports = 8;
-				panelp->ackmask = 0xc0;
-			}
-		}
-
-		nxtid++;
-		ioaddr += EREG_BANKSIZE;
-		brdp->nrports += panelp->nrports;
-		brdp->panels[panelnr++] = panelp;
-		if ((brdp->brdtype != BRD_ECHPCI) &&
-		    (ioaddr >= (brdp->ioaddr2 + brdp->iosize2))) {
-			retval = -EINVAL;
-			goto err_fr;
-		}
-	}
-
-	brdp->nrpanels = panelnr;
-	brdp->nrbnks = banknr;
-	if (brdp->brdtype == BRD_ECH)
-		outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
-
-	brdp->state |= BRD_FOUND;
-	if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
-		printk("STALLION: failed to register interrupt "
-		    "routine for %s irq=%d\n", name, brdp->irq);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-
-	return 0;
-err_fr:
-	stl_cleanup_panels(brdp);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err_rel1:
-	release_region(brdp->ioaddr1, brdp->iosize1);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize and configure the specified board.
- *	Scan through all the boards in the configuration and see what we
- *	can find. Handle EIO and the ECH boards a little differently here
- *	since the initial search and setup is very different.
- */
-
-static int __devinit stl_brdinit(struct stlbrd *brdp)
-{
-	int i, retval;
-
-	pr_debug("stl_brdinit(brdp=%p)\n", brdp);
-
-	switch (brdp->brdtype) {
-	case BRD_EASYIO:
-	case BRD_EASYIOPCI:
-		retval = stl_initeio(brdp);
-		if (retval)
-			goto err;
-		break;
-	case BRD_ECH:
-	case BRD_ECHMC:
-	case BRD_ECHPCI:
-	case BRD_ECH64PCI:
-		retval = stl_initech(brdp);
-		if (retval)
-			goto err;
-		break;
-	default:
-		printk("STALLION: board=%d is unknown board type=%d\n",
-			brdp->brdnr, brdp->brdtype);
-		retval = -ENODEV;
-		goto err;
-	}
-
-	if ((brdp->state & BRD_FOUND) == 0) {
-		printk("STALLION: %s board not found, board=%d io=%x irq=%d\n",
-			stl_brdnames[brdp->brdtype], brdp->brdnr,
-			brdp->ioaddr1, brdp->irq);
-		goto err_free;
-	}
-
-	for (i = 0; i < STL_MAXPANELS; i++)
-		if (brdp->panels[i] != NULL)
-			stl_initports(brdp, brdp->panels[i]);
-
-	printk("STALLION: %s found, board=%d io=%x irq=%d "
-		"nrpanels=%d nrports=%d\n", stl_brdnames[brdp->brdtype],
-		brdp->brdnr, brdp->ioaddr1, brdp->irq, brdp->nrpanels,
-		brdp->nrports);
-
-	return 0;
-err_free:
-	free_irq(brdp->irq, brdp);
-
-	stl_cleanup_panels(brdp);
-
-	release_region(brdp->ioaddr1, brdp->iosize1);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-err:
-	return retval;
-}
-
-/*****************************************************************************/
-
-/*
- *	Find the next available board number that is free.
- */
-
-static int __devinit stl_getbrdnr(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < STL_MAXBRDS; i++)
-		if (stl_brds[i] == NULL) {
-			if (i >= stl_nrbrds)
-				stl_nrbrds = i + 1;
-			return i;
-		}
-
-	return -1;
-}
-
-/*****************************************************************************/
-/*
- *	We have a Stallion board. Allocate a board structure and
- *	initialize it. Read its IO and IRQ resources from PCI
- *	configuration space.
- */
-
-static int __devinit stl_pciprobe(struct pci_dev *pdev,
-		const struct pci_device_id *ent)
-{
-	struct stlbrd *brdp;
-	unsigned int i, brdtype = ent->driver_data;
-	int brdnr, retval = -ENODEV;
-
-	if ((pdev->class >> 8) == PCI_CLASS_STORAGE_IDE)
-		goto err;
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err;
-	brdp = stl_allocbrd();
-	if (brdp == NULL) {
-		retval = -ENOMEM;
-		goto err;
-	}
-	mutex_lock(&stl_brdslock);
-	brdnr = stl_getbrdnr();
-	if (brdnr < 0) {
-		dev_err(&pdev->dev, "too many boards found, "
-			"maximum supported %d\n", STL_MAXBRDS);
-		mutex_unlock(&stl_brdslock);
-		retval = -ENODEV;
-		goto err_fr;
-	}
-	brdp->brdnr = (unsigned int)brdnr;
-	stl_brds[brdp->brdnr] = brdp;
-	mutex_unlock(&stl_brdslock);
-
-	brdp->brdtype = brdtype;
-	brdp->state |= STL_PROBED;
-
-/*
- *	We have all resources from the board, so let's setup the actual
- *	board structure now.
- */
-	switch (brdtype) {
-	case BRD_ECHPCI:
-		brdp->ioaddr2 = pci_resource_start(pdev, 0);
-		brdp->ioaddr1 = pci_resource_start(pdev, 1);
-		break;
-	case BRD_ECH64PCI:
-		brdp->ioaddr2 = pci_resource_start(pdev, 2);
-		brdp->ioaddr1 = pci_resource_start(pdev, 1);
-		break;
-	case BRD_EASYIOPCI:
-		brdp->ioaddr1 = pci_resource_start(pdev, 2);
-		brdp->ioaddr2 = pci_resource_start(pdev, 1);
-		break;
-	default:
-		dev_err(&pdev->dev, "unknown PCI board type=%u\n", brdtype);
-		break;
-	}
-
-	brdp->irq = pdev->irq;
-	retval = stl_brdinit(brdp);
-	if (retval)
-		goto err_null;
-
-	pci_set_drvdata(pdev, brdp);
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_register_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + i, &pdev->dev);
-
-	return 0;
-err_null:
-	stl_brds[brdp->brdnr] = NULL;
-err_fr:
-	kfree(brdp);
-err:
-	return retval;
-}
-
-static void __devexit stl_pciremove(struct pci_dev *pdev)
-{
-	struct stlbrd *brdp = pci_get_drvdata(pdev);
-	unsigned int i;
-
-	free_irq(brdp->irq, brdp);
-
-	stl_cleanup_panels(brdp);
-
-	release_region(brdp->ioaddr1, brdp->iosize1);
-	if (brdp->iosize2 > 0)
-		release_region(brdp->ioaddr2, brdp->iosize2);
-
-	for (i = 0; i < brdp->nrports; i++)
-		tty_unregister_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + i);
-
-	stl_brds[brdp->brdnr] = NULL;
-	kfree(brdp);
-}
-
-static struct pci_driver stl_pcidriver = {
-	.name = "stallion",
-	.id_table = stl_pcibrds,
-	.probe = stl_pciprobe,
-	.remove = __devexit_p(stl_pciremove)
-};
-
-/*****************************************************************************/
-
-/*
- *	Return the board stats structure to user app.
- */
-
-static int stl_getbrdstats(combrd_t __user *bp)
-{
-	combrd_t	stl_brdstats;
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-	unsigned int i;
-
-	if (copy_from_user(&stl_brdstats, bp, sizeof(combrd_t)))
-		return -EFAULT;
-	if (stl_brdstats.brd >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stl_brds[stl_brdstats.brd];
-	if (brdp == NULL)
-		return -ENODEV;
-
-	memset(&stl_brdstats, 0, sizeof(combrd_t));
-	stl_brdstats.brd = brdp->brdnr;
-	stl_brdstats.type = brdp->brdtype;
-	stl_brdstats.hwid = brdp->hwid;
-	stl_brdstats.state = brdp->state;
-	stl_brdstats.ioaddr = brdp->ioaddr1;
-	stl_brdstats.ioaddr2 = brdp->ioaddr2;
-	stl_brdstats.irq = brdp->irq;
-	stl_brdstats.nrpanels = brdp->nrpanels;
-	stl_brdstats.nrports = brdp->nrports;
-	for (i = 0; i < brdp->nrpanels; i++) {
-		panelp = brdp->panels[i];
-		stl_brdstats.panels[i].panel = i;
-		stl_brdstats.panels[i].hwid = panelp->hwid;
-		stl_brdstats.panels[i].nrports = panelp->nrports;
-	}
-
-	return copy_to_user(bp, &stl_brdstats, sizeof(combrd_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Resolve the referenced port number into a port struct pointer.
- */
-
-static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
-{
-	struct stlbrd	*brdp;
-	struct stlpanel	*panelp;
-
-	if (brdnr < 0 || brdnr >= STL_MAXBRDS)
-		return NULL;
-	brdp = stl_brds[brdnr];
-	if (brdp == NULL)
-		return NULL;
-	if (panelnr < 0 || (unsigned int)panelnr >= brdp->nrpanels)
-		return NULL;
-	panelp = brdp->panels[panelnr];
-	if (panelp == NULL)
-		return NULL;
-	if (portnr < 0 || (unsigned int)portnr >= panelp->nrports)
-		return NULL;
-	return panelp->ports[portnr];
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the port stats structure to user app. A NULL port struct
- *	pointer passed in means that we need to find out from the app
- *	what port to get stats for (used through board control device).
- */
-
-static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
-{
-	comstats_t	stl_comstats;
-	unsigned char	*head, *tail;
-	unsigned long	flags;
-
-	if (!portp) {
-		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-			stl_comstats.port);
-		if (portp == NULL)
-			return -ENODEV;
-	}
-
-	mutex_lock(&portp->port.mutex);
-	portp->stats.state = portp->istate;
-	portp->stats.flags = portp->port.flags;
-	portp->stats.hwid = portp->hwid;
-
-	portp->stats.ttystate = 0;
-	portp->stats.cflags = 0;
-	portp->stats.iflags = 0;
-	portp->stats.oflags = 0;
-	portp->stats.lflags = 0;
-	portp->stats.rxbuffered = 0;
-
-	spin_lock_irqsave(&stallion_lock, flags);
-	if (tty != NULL && portp->port.tty == tty) {
-		portp->stats.ttystate = tty->flags;
-		/* No longer available as a statistic */
-		portp->stats.rxbuffered = 1; /*tty->flip.count; */
-		if (tty->termios != NULL) {
-			portp->stats.cflags = tty->termios->c_cflag;
-			portp->stats.iflags = tty->termios->c_iflag;
-			portp->stats.oflags = tty->termios->c_oflag;
-			portp->stats.lflags = tty->termios->c_lflag;
-		}
-	}
-	spin_unlock_irqrestore(&stallion_lock, flags);
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	portp->stats.txbuffered = (head >= tail) ? (head - tail) :
-		(STL_TXBUFSIZE - (tail - head));
-
-	portp->stats.signals = (unsigned long) stl_getsignals(portp);
-	mutex_unlock(&portp->port.mutex);
-
-	return copy_to_user(cp, &portp->stats,
-			    sizeof(comstats_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Clear the port stats structure. We also return it zeroed out...
- */
-
-static int stl_clrportstats(struct stlport *portp, comstats_t __user *cp)
-{
-	comstats_t	stl_comstats;
-
-	if (!portp) {
-		if (copy_from_user(&stl_comstats, cp, sizeof(comstats_t)))
-			return -EFAULT;
-		portp = stl_getport(stl_comstats.brd, stl_comstats.panel,
-			stl_comstats.port);
-		if (portp == NULL)
-			return -ENODEV;
-	}
-
-	mutex_lock(&portp->port.mutex);
-	memset(&portp->stats, 0, sizeof(comstats_t));
-	portp->stats.brd = portp->brdnr;
-	portp->stats.panel = portp->panelnr;
-	portp->stats.port = portp->portnr;
-	mutex_unlock(&portp->port.mutex);
-	return copy_to_user(cp, &portp->stats,
-			    sizeof(comstats_t)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver ports structure to a user app.
- */
-
-static int stl_getportstruct(struct stlport __user *arg)
-{
-	struct stlport	stl_dummyport;
-	struct stlport	*portp;
-
-	if (copy_from_user(&stl_dummyport, arg, sizeof(struct stlport)))
-		return -EFAULT;
-	portp = stl_getport(stl_dummyport.brdnr, stl_dummyport.panelnr,
-		 stl_dummyport.portnr);
-	if (!portp)
-		return -ENODEV;
-	return copy_to_user(arg, portp, sizeof(struct stlport)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the entire driver board structure to a user app.
- */
-
-static int stl_getbrdstruct(struct stlbrd __user *arg)
-{
-	struct stlbrd	stl_dummybrd;
-	struct stlbrd	*brdp;
-
-	if (copy_from_user(&stl_dummybrd, arg, sizeof(struct stlbrd)))
-		return -EFAULT;
-	if (stl_dummybrd.brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	brdp = stl_brds[stl_dummybrd.brdnr];
-	if (!brdp)
-		return -ENODEV;
-	return copy_to_user(arg, brdp, sizeof(struct stlbrd)) ? -EFAULT : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	The "staliomem" device is also required to do some special operations
- *	on the board and/or ports. In this driver it is mostly used for stats
- *	collection.
- */
-
-static long stl_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
-{
-	int	brdnr, rc;
-	void __user *argp = (void __user *)arg;
-
-	pr_debug("stl_memioctl(fp=%p,cmd=%x,arg=%lx)\n", fp, cmd,arg);
-
-	brdnr = iminor(fp->f_dentry->d_inode);
-	if (brdnr >= STL_MAXBRDS)
-		return -ENODEV;
-	rc = 0;
-
-	switch (cmd) {
-	case COM_GETPORTSTATS:
-		rc = stl_getportstats(NULL, NULL, argp);
-		break;
-	case COM_CLRPORTSTATS:
-		rc = stl_clrportstats(NULL, argp);
-		break;
-	case COM_GETBRDSTATS:
-		rc = stl_getbrdstats(argp);
-		break;
-	case COM_READPORT:
-		rc = stl_getportstruct(argp);
-		break;
-	case COM_READBOARD:
-		rc = stl_getbrdstruct(argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	return rc;
-}
-
-static const struct tty_operations stl_ops = {
-	.open = stl_open,
-	.close = stl_close,
-	.write = stl_write,
-	.put_char = stl_putchar,
-	.flush_chars = stl_flushchars,
-	.write_room = stl_writeroom,
-	.chars_in_buffer = stl_charsinbuffer,
-	.ioctl = stl_ioctl,
-	.set_termios = stl_settermios,
-	.throttle = stl_throttle,
-	.unthrottle = stl_unthrottle,
-	.stop = stl_stop,
-	.start = stl_start,
-	.hangup = stl_hangup,
-	.flush_buffer = stl_flushbuffer,
-	.break_ctl = stl_breakctl,
-	.wait_until_sent = stl_waituntilsent,
-	.send_xchar = stl_sendxchar,
-	.tiocmget = stl_tiocmget,
-	.tiocmset = stl_tiocmset,
-	.proc_fops = &stl_proc_fops,
-};
-
-static const struct tty_port_operations stl_port_ops = {
-	.carrier_raised = stl_carrier_raised,
-	.dtr_rts = stl_dtr_rts,
-	.activate = stl_activate,
-	.shutdown = stl_shutdown,
-};
-
-/*****************************************************************************/
-/*                       CD1400 HARDWARE FUNCTIONS                           */
-/*****************************************************************************/
-
-/*
- *	These functions get/set/update the registers of the cd1400 UARTs.
- *	Access to the cd1400 registers is via an address/data io port pair.
- *	(Maybe should make this inline...)
- */
-
-static int stl_cd1400getreg(struct stlport *portp, int regnr)
-{
-	outb((regnr + portp->uartaddr), portp->ioaddr);
-	return inb(portp->ioaddr + EREG_DATA);
-}
-
-static void stl_cd1400setreg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr + portp->uartaddr, portp->ioaddr);
-	outb(value, portp->ioaddr + EREG_DATA);
-}
-
-static int stl_cd1400updatereg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr + portp->uartaddr, portp->ioaddr);
-	if (inb(portp->ioaddr + EREG_DATA) != value) {
-		outb(value, portp->ioaddr + EREG_DATA);
-		return 1;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Inbitialize the UARTs in a panel. We don't care what sort of board
- *	these ports are on - since the port io registers are almost
- *	identical when dealing with ports.
- */
-
-static int stl_cd1400panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	unsigned int	gfrcr;
-	int		chipmask, i, j;
-	int		nrchips, uartaddr, ioaddr;
-	unsigned long   flags;
-
-	pr_debug("stl_panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- *	Check that each chip is present and started up OK.
- */
-	chipmask = 0;
-	nrchips = panelp->nrports / CD1400_PORTS;
-	for (i = 0; i < nrchips; i++) {
-		if (brdp->brdtype == BRD_ECHPCI) {
-			outb((panelp->pagenr + (i >> 1)), brdp->ioctrl);
-			ioaddr = panelp->iobase;
-		} else
-			ioaddr = panelp->iobase + (EREG_BANKSIZE * (i >> 1));
-		uartaddr = (i & 0x01) ? 0x080 : 0;
-		outb((GFRCR + uartaddr), ioaddr);
-		outb(0, (ioaddr + EREG_DATA));
-		outb((CCR + uartaddr), ioaddr);
-		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
-		outb(CCR_RESETFULL, (ioaddr + EREG_DATA));
-		outb((GFRCR + uartaddr), ioaddr);
-		for (j = 0; j < CCR_MAXWAIT; j++)
-			if ((gfrcr = inb(ioaddr + EREG_DATA)) != 0)
-				break;
-
-		if ((j >= CCR_MAXWAIT) || (gfrcr < 0x40) || (gfrcr > 0x60)) {
-			printk("STALLION: cd1400 not responding, "
-				"brd=%d panel=%d chip=%d\n",
-				panelp->brdnr, panelp->panelnr, i);
-			continue;
-		}
-		chipmask |= (0x1 << i);
-		outb((PPR + uartaddr), ioaddr);
-		outb(PPR_SCALAR, (ioaddr + EREG_DATA));
-	}
-
-	BRDDISABLE(panelp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	return chipmask;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize hardware specific port registers.
- */
-
-static void stl_cd1400portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
-{
-	unsigned long flags;
-	pr_debug("stl_cd1400portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
-			panelp, portp);
-
-	if ((brdp == NULL) || (panelp == NULL) ||
-	    (portp == NULL))
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
-		(portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
-	portp->uartaddr = (portp->portnr & 0x04) << 5;
-	portp->pagenr = panelp->pagenr + (portp->portnr >> 3);
-
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
-	portp->hwid = stl_cd1400getreg(portp, GFRCR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Wait for the command register to be ready. We will poll this,
- *	since it won't usually take too long to be ready.
- */
-
-static void stl_cd1400ccrwait(struct stlport *portp)
-{
-	int	i;
-
-	for (i = 0; i < CCR_MAXWAIT; i++)
-		if (stl_cd1400getreg(portp, CCR) == 0)
-			return;
-
-	printk("STALLION: cd1400 not responding, port=%d panel=%d brd=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up the cd1400 registers for a port based on the termios port
- *	settings.
- */
-
-static void stl_cd1400setport(struct stlport *portp, struct ktermios *tiosp)
-{
-	struct stlbrd	*brdp;
-	unsigned long	flags;
-	unsigned int	clkdiv, baudrate;
-	unsigned char	cor1, cor2, cor3;
-	unsigned char	cor4, cor5, ccr;
-	unsigned char	srer, sreron, sreroff;
-	unsigned char	mcor1, mcor2, rtpr;
-	unsigned char	clk, div;
-
-	cor1 = 0;
-	cor2 = 0;
-	cor3 = 0;
-	cor4 = 0;
-	cor5 = 0;
-	ccr = 0;
-	rtpr = 0;
-	clk = 0;
-	div = 0;
-	mcor1 = 0;
-	mcor2 = 0;
-	sreron = 0;
-	sreroff = 0;
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-/*
- *	Set up the RX char ignore mask with those RX error types we
- *	can ignore. We can get the cd1400 to help us out a little here,
- *	it will ignore parity errors and breaks for us.
- */
-	portp->rxignoremsk = 0;
-	if (tiosp->c_iflag & IGNPAR) {
-		portp->rxignoremsk |= (ST_PARITY | ST_FRAMING | ST_OVERRUN);
-		cor1 |= COR1_PARIGNORE;
-	}
-	if (tiosp->c_iflag & IGNBRK) {
-		portp->rxignoremsk |= ST_BREAK;
-		cor4 |= COR4_IGNBRK;
-	}
-
-	portp->rxmarkmsk = ST_OVERRUN;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		portp->rxmarkmsk |= (ST_PARITY | ST_FRAMING);
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= ST_BREAK;
-
-/*
- *	Go through the char size, parity and stop bits and set all the
- *	option register appropriately.
- */
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		cor1 |= COR1_CHL5;
-		break;
-	case CS6:
-		cor1 |= COR1_CHL6;
-		break;
-	case CS7:
-		cor1 |= COR1_CHL7;
-		break;
-	default:
-		cor1 |= COR1_CHL8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		cor1 |= COR1_STOP2;
-	else
-		cor1 |= COR1_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			cor1 |= (COR1_PARENB | COR1_PARODD);
-		else
-			cor1 |= (COR1_PARENB | COR1_PAREVEN);
-	} else {
-		cor1 |= COR1_PARNONE;
-	}
-
-/*
- *	Set the RX FIFO threshold at 6 chars. This gives a bit of breathing
- *	space for hardware flow control and the like. This should be set to
- *	VMIN. Also here we will set the RX data timeout to 10ms - this should
- *	really be based on VTIME.
- */
-	cor3 |= FIFO_RXTHRESHOLD;
-	rtpr = 2;
-
-/*
- *	Calculate the baud rate timers. For now we will just assume that
- *	the input and output baud are the same. Could have used a baud
- *	table here, but this way we can generate virtually any baud rate
- *	we like!
- */
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
-	baudrate = stl_baudrates[baudrate];
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (portp->baud_base / portp->custom_divisor);
-	}
-	if (baudrate > STL_CD1400MAXBAUD)
-		baudrate = STL_CD1400MAXBAUD;
-
-	if (baudrate > 0) {
-		for (clk = 0; clk < CD1400_NUMCLKS; clk++) {
-			clkdiv = (portp->clk / stl_cd1400clkdivs[clk]) / baudrate;
-			if (clkdiv < 0x100)
-				break;
-		}
-		div = (unsigned char) clkdiv;
-	}
-
-/*
- *	Check what form of modem signaling is required and set it up.
- */
-	if ((tiosp->c_cflag & CLOCAL) == 0) {
-		mcor1 |= MCOR1_DCD;
-		mcor2 |= MCOR2_DCD;
-		sreron |= SRER_MODEM;
-		portp->port.flags |= ASYNC_CHECK_CD;
-	} else
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-
-/*
- *	Setup cd1400 enhanced modes if we can. In particular we want to
- *	handle as much of the flow control as possible automatically. As
- *	well as saving a few CPU cycles it will also greatly improve flow
- *	control reliability.
- */
-	if (tiosp->c_iflag & IXON) {
-		cor2 |= COR2_TXIBE;
-		cor3 |= COR3_SCD12;
-		if (tiosp->c_iflag & IXANY)
-			cor2 |= COR2_IXM;
-	}
-
-	if (tiosp->c_cflag & CRTSCTS) {
-		cor2 |= COR2_CTSAE;
-		mcor1 |= FIFO_RTSTHRESHOLD;
-	}
-
-/*
- *	All cd1400 register values calculated so go through and set
- *	them all up.
- */
-
-	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-	pr_debug("    cor1=%x cor2=%x cor3=%x cor4=%x cor5=%x\n",
-		cor1, cor2, cor3, cor4, cor5);
-	pr_debug("    mcor1=%x mcor2=%x rtpr=%x sreron=%x sreroff=%x\n",
-		mcor1, mcor2, rtpr, sreron, sreroff);
-	pr_debug("    tcor=%x tbpr=%x rcor=%x rbpr=%x\n", clk, div, clk, div);
-	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
-	srer = stl_cd1400getreg(portp, SRER);
-	stl_cd1400setreg(portp, SRER, 0);
-	if (stl_cd1400updatereg(portp, COR1, cor1))
-		ccr = 1;
-	if (stl_cd1400updatereg(portp, COR2, cor2))
-		ccr = 1;
-	if (stl_cd1400updatereg(portp, COR3, cor3))
-		ccr = 1;
-	if (ccr) {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_CORCHANGE);
-	}
-	stl_cd1400setreg(portp, COR4, cor4);
-	stl_cd1400setreg(portp, COR5, cor5);
-	stl_cd1400setreg(portp, MCOR1, mcor1);
-	stl_cd1400setreg(portp, MCOR2, mcor2);
-	if (baudrate > 0) {
-		stl_cd1400setreg(portp, TCOR, clk);
-		stl_cd1400setreg(portp, TBPR, div);
-		stl_cd1400setreg(portp, RCOR, clk);
-		stl_cd1400setreg(portp, RBPR, div);
-	}
-	stl_cd1400setreg(portp, SCHR1, tiosp->c_cc[VSTART]);
-	stl_cd1400setreg(portp, SCHR2, tiosp->c_cc[VSTOP]);
-	stl_cd1400setreg(portp, SCHR3, tiosp->c_cc[VSTART]);
-	stl_cd1400setreg(portp, SCHR4, tiosp->c_cc[VSTOP]);
-	stl_cd1400setreg(portp, RTPR, rtpr);
-	mcor1 = stl_cd1400getreg(portp, MSVR1);
-	if (mcor1 & MSVR1_DCD)
-		portp->sigs |= TIOCM_CD;
-	else
-		portp->sigs &= ~TIOCM_CD;
-	stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set the state of the DTR and RTS signals.
- */
-
-static void stl_cd1400setsignals(struct stlport *portp, int dtr, int rts)
-{
-	unsigned char	msvr1, msvr2;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400setsignals(portp=%p,dtr=%d,rts=%d)\n",
-			portp, dtr, rts);
-
-	msvr1 = 0;
-	msvr2 = 0;
-	if (dtr > 0)
-		msvr1 = MSVR1_DTR;
-	if (rts > 0)
-		msvr2 = MSVR2_RTS;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	if (rts >= 0)
-		stl_cd1400setreg(portp, MSVR2, msvr2);
-	if (dtr >= 0)
-		stl_cd1400setreg(portp, MSVR1, msvr1);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the state of the signals.
- */
-
-static int stl_cd1400getsignals(struct stlport *portp)
-{
-	unsigned char	msvr1, msvr2;
-	unsigned long	flags;
-	int		sigs;
-
-	pr_debug("stl_cd1400getsignals(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	msvr1 = stl_cd1400getreg(portp, MSVR1);
-	msvr2 = stl_cd1400getreg(portp, MSVR2);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	sigs = 0;
-	sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
-	sigs |= (msvr1 & MSVR1_CTS) ? TIOCM_CTS : 0;
-	sigs |= (msvr1 & MSVR1_DTR) ? TIOCM_DTR : 0;
-	sigs |= (msvr2 & MSVR2_RTS) ? TIOCM_RTS : 0;
-#if 0
-	sigs |= (msvr1 & MSVR1_RI) ? TIOCM_RI : 0;
-	sigs |= (msvr1 & MSVR1_DSR) ? TIOCM_DSR : 0;
-#else
-	sigs |= TIOCM_DSR;
-#endif
-	return sigs;
-}
-
-/*****************************************************************************/
-
-/*
- *	Enable/Disable the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400enablerxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	ccr;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	ccr = 0;
-
-	if (tx == 0)
-		ccr |= CCR_TXDISABLE;
-	else if (tx > 0)
-		ccr |= CCR_TXENABLE;
-	if (rx == 0)
-		ccr |= CCR_RXDISABLE;
-	else if (rx > 0)
-		ccr |= CCR_RXENABLE;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400ccrwait(portp);
-	stl_cd1400setreg(portp, CCR, ccr);
-	stl_cd1400ccrwait(portp);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Start/stop the Transmitter and/or Receiver.
- */
-
-static void stl_cd1400startrxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	sreron, sreroff;
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	sreron = 0;
-	sreroff = 0;
-	if (tx == 0)
-		sreroff |= (SRER_TXDATA | SRER_TXEMPTY);
-	else if (tx == 1)
-		sreron |= SRER_TXDATA;
-	else if (tx >= 2)
-		sreron |= SRER_TXEMPTY;
-	if (rx == 0)
-		sreroff |= SRER_RXDATA;
-	else if (rx > 0)
-		sreron |= SRER_RXDATA;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER,
-		((stl_cd1400getreg(portp, SRER) & ~sreroff) | sreron));
-	BRDDISABLE(portp->brdnr);
-	if (tx > 0)
-		set_bit(ASYI_TXBUSY, &portp->istate);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Disable all interrupts from this port.
- */
-
-static void stl_cd1400disableintrs(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400disableintrs(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER, 0);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400sendbreak(struct stlport *portp, int len)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400sendbreak(portp=%p,len=%d)\n", portp, len);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400setreg(portp, SRER,
-		((stl_cd1400getreg(portp, SRER) & ~SRER_TXDATA) |
-		SRER_TXEMPTY));
-	BRDDISABLE(portp->brdnr);
-	portp->brklen = len;
-	if (len == 1)
-		portp->stats.txbreaks++;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Take flow control actions...
- */
-
-static void stl_cd1400flowctrl(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-
-	pr_debug("stl_cd1400flowctrl(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-
-	if (state) {
-		if (tty->termios->c_iflag & IXOFF) {
-			stl_cd1400ccrwait(portp);
-			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-			portp->stats.rxxon++;
-			stl_cd1400ccrwait(portp);
-		}
-/*
- *		Question: should we return RTS to what it was before? It may
- *		have been set by an ioctl... Suppose not, since if you have
- *		hardware flow control set then it is pretty silly to go and
- *		set the RTS line by hand.
- */
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_cd1400setreg(portp, MCOR1,
-				(stl_cd1400getreg(portp, MCOR1) |
-				FIFO_RTSTHRESHOLD));
-			stl_cd1400setreg(portp, MSVR2, MSVR2_RTS);
-			portp->stats.rxrtson++;
-		}
-	} else {
-		if (tty->termios->c_iflag & IXOFF) {
-			stl_cd1400ccrwait(portp);
-			stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-			portp->stats.rxxoff++;
-			stl_cd1400ccrwait(portp);
-		}
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_cd1400setreg(portp, MCOR1,
-				(stl_cd1400getreg(portp, MCOR1) & 0xf0));
-			stl_cd1400setreg(portp, MSVR2, 0);
-			portp->stats.rxrtsoff++;
-		}
-	}
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a flow control character...
- */
-
-static void stl_cd1400sendflow(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-
-	pr_debug("stl_cd1400sendflow(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	if (state) {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR1);
-		portp->stats.rxxon++;
-		stl_cd1400ccrwait(portp);
-	} else {
-		stl_cd1400ccrwait(portp);
-		stl_cd1400setreg(portp, CCR, CCR_SENDSCHR2);
-		portp->stats.rxxoff++;
-		stl_cd1400ccrwait(portp);
-	}
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_cd1400flush(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_cd1400flush(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
-	stl_cd1400ccrwait(portp);
-	stl_cd1400setreg(portp, CCR, CCR_TXFLUSHFIFO);
-	stl_cd1400ccrwait(portp);
-	portp->tx.tail = portp->tx.head;
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the current state of data flow on this port. This is only
- *	really interesting when determining if data has fully completed
- *	transmission or not... This is easy for the cd1400, it accurately
- *	maintains the busy port flag.
- */
-
-static int stl_cd1400datastate(struct stlport *portp)
-{
-	pr_debug("stl_cd1400datastate(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return 0;
-
-	return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for cd1400 EasyIO boards.
- */
-
-static void stl_cd1400eiointr(struct stlpanel *panelp, unsigned int iobase)
-{
-	unsigned char	svrtype;
-
-	pr_debug("stl_cd1400eiointr(panelp=%p,iobase=%x)\n", panelp, iobase);
-
-	spin_lock(&brd_lock);
-	outb(SVRR, iobase);
-	svrtype = inb(iobase + EREG_DATA);
-	if (panelp->nrports > 4) {
-		outb((SVRR + 0x80), iobase);
-		svrtype |= inb(iobase + EREG_DATA);
-	}
-
-	if (svrtype & SVRR_RX)
-		stl_cd1400rxisr(panelp, iobase);
-	else if (svrtype & SVRR_TX)
-		stl_cd1400txisr(panelp, iobase);
-	else if (svrtype & SVRR_MDM)
-		stl_cd1400mdmisr(panelp, iobase);
-
-	spin_unlock(&brd_lock);
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for cd1400 panels.
- */
-
-static void stl_cd1400echintr(struct stlpanel *panelp, unsigned int iobase)
-{
-	unsigned char	svrtype;
-
-	pr_debug("stl_cd1400echintr(panelp=%p,iobase=%x)\n", panelp, iobase);
-
-	outb(SVRR, iobase);
-	svrtype = inb(iobase + EREG_DATA);
-	outb((SVRR + 0x80), iobase);
-	svrtype |= inb(iobase + EREG_DATA);
-	if (svrtype & SVRR_RX)
-		stl_cd1400rxisr(panelp, iobase);
-	else if (svrtype & SVRR_TX)
-		stl_cd1400txisr(panelp, iobase);
-	else if (svrtype & SVRR_MDM)
-		stl_cd1400mdmisr(panelp, iobase);
-}
-
-
-/*****************************************************************************/
-
-/*
- *	Unfortunately we need to handle breaks in the TX data stream, since
- *	this is the only way to generate them on the cd1400.
- */
-
-static int stl_cd1400breakisr(struct stlport *portp, int ioaddr)
-{
-	if (portp->brklen == 1) {
-		outb((COR2 + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) | COR2_ETC),
-			(ioaddr + EREG_DATA));
-		outb((TDR + portp->uartaddr), ioaddr);
-		outb(ETC_CMD, (ioaddr + EREG_DATA));
-		outb(ETC_STARTBREAK, (ioaddr + EREG_DATA));
-		outb((SRER + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
-			(ioaddr + EREG_DATA));
-		return 1;
-	} else if (portp->brklen > 1) {
-		outb((TDR + portp->uartaddr), ioaddr);
-		outb(ETC_CMD, (ioaddr + EREG_DATA));
-		outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
-		portp->brklen = -1;
-		return 1;
-	} else {
-		outb((COR2 + portp->uartaddr), ioaddr);
-		outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
-			(ioaddr + EREG_DATA));
-		portp->brklen = 0;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Transmit interrupt handler. This has gotta be fast!  Handling TX
- *	chars is pretty simple, stuff as many as possible from the TX buffer
- *	into the cd1400 FIFO. Must also handle TX breaks here, since they
- *	are embedded as commands in the data stream. Oh no, had to use a goto!
- *	This could be optimized more, will do when I get time...
- *	In practice it is possible that interrupts are enabled but that the
- *	port has been hung up. Need to handle not having any TX buffer here,
- *	this is done by using the side effect that head and tail will also
- *	be NULL if the buffer has been freed.
- */
-
-static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport	*portp;
-	int		len, stlen;
-	char		*head, *tail;
-	unsigned char	ioack, srer;
-	struct tty_struct *tty;
-
-	pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
-
-	ioack = inb(ioaddr + EREG_TXACK);
-	if (((ioack & panelp->ackmask) != 0) ||
-	    ((ioack & ACK_TYPMASK) != ACK_TYPTX)) {
-		printk("STALLION: bad TX interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-
-/*
- *	Unfortunately we need to handle breaks in the data stream, since
- *	this is the only way to generate them on the cd1400. Do it now if
- *	a break is to be sent.
- */
-	if (portp->brklen != 0)
-		if (stl_cd1400breakisr(portp, ioaddr))
-			goto stl_txalldone;
-
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((len == 0) || ((len < STL_TXBUFLOW) &&
-	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
-		set_bit(ASYI_TXLOW, &portp->istate);
-		tty = tty_port_tty_get(&portp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
-
-	if (len == 0) {
-		outb((SRER + portp->uartaddr), ioaddr);
-		srer = inb(ioaddr + EREG_DATA);
-		if (srer & SRER_TXDATA) {
-			srer = (srer & ~SRER_TXDATA) | SRER_TXEMPTY;
-		} else {
-			srer &= ~(SRER_TXDATA | SRER_TXEMPTY);
-			clear_bit(ASYI_TXBUSY, &portp->istate);
-		}
-		outb(srer, (ioaddr + EREG_DATA));
-	} else {
-		len = min(len, CD1400_TXFIFOSIZE);
-		portp->stats.txtotal += len;
-		stlen = min_t(unsigned int, len,
-				(portp->tx.buf + STL_TXBUFSIZE) - tail);
-		outb((TDR + portp->uartaddr), ioaddr);
-		outsb((ioaddr + EREG_DATA), tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
-			tail = portp->tx.buf;
-		if (len > 0) {
-			outsb((ioaddr + EREG_DATA), tail, len);
-			tail += len;
-		}
-		portp->tx.tail = tail;
-	}
-
-stl_txalldone:
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-/*
- *	Receive character interrupt handler. Determine if we have good chars
- *	or bad chars and then process appropriately. Good chars are easy
- *	just shove the lot into the RX buffer and set all status byte to 0.
- *	If a bad RX char then process as required. This routine needs to be
- *	fast!  In practice it is possible that we get an interrupt on a port
- *	that is closed. This can happen on hangups - since they completely
- *	shutdown a port not in user context. Need to handle this case.
- */
-
-static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport		*portp;
-	struct tty_struct	*tty;
-	unsigned int		ioack, len, buflen;
-	unsigned char		status;
-	char			ch;
-
-	pr_debug("stl_cd1400rxisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
-
-	ioack = inb(ioaddr + EREG_RXACK);
-	if ((ioack & panelp->ackmask) != 0) {
-		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-	tty = tty_port_tty_get(&portp->port);
-
-	if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
-		outb((RDCR + portp->uartaddr), ioaddr);
-		len = inb(ioaddr + EREG_DATA);
-		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-			len = min_t(unsigned int, len, sizeof(stl_unwanted));
-			outb((RDSR + portp->uartaddr), ioaddr);
-			insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
-			portp->stats.rxlost += len;
-			portp->stats.rxtotal += len;
-		} else {
-			len = min(len, buflen);
-			if (len > 0) {
-				unsigned char *ptr;
-				outb((RDSR + portp->uartaddr), ioaddr);
-				tty_prepare_flip_string(tty, &ptr, len);
-				insb((ioaddr + EREG_DATA), ptr, len);
-				tty_schedule_flip(tty);
-				portp->stats.rxtotal += len;
-			}
-		}
-	} else if ((ioack & ACK_TYPMASK) == ACK_TYPRXBAD) {
-		outb((RDSR + portp->uartaddr), ioaddr);
-		status = inb(ioaddr + EREG_DATA);
-		ch = inb(ioaddr + EREG_DATA);
-		if (status & ST_PARITY)
-			portp->stats.rxparity++;
-		if (status & ST_FRAMING)
-			portp->stats.rxframing++;
-		if (status & ST_OVERRUN)
-			portp->stats.rxoverrun++;
-		if (status & ST_BREAK)
-			portp->stats.rxbreaks++;
-		if (status & ST_SCHARMASK) {
-			if ((status & ST_SCHARMASK) == ST_SCHAR1)
-				portp->stats.txxon++;
-			if ((status & ST_SCHARMASK) == ST_SCHAR2)
-				portp->stats.txxoff++;
-			goto stl_rxalldone;
-		}
-		if (tty != NULL && (portp->rxignoremsk & status) == 0) {
-			if (portp->rxmarkmsk & status) {
-				if (status & ST_BREAK) {
-					status = TTY_BREAK;
-					if (portp->port.flags & ASYNC_SAK) {
-						do_SAK(tty);
-						BRDENABLE(portp->brdnr, portp->pagenr);
-					}
-				} else if (status & ST_PARITY)
-					status = TTY_PARITY;
-				else if (status & ST_FRAMING)
-					status = TTY_FRAME;
-				else if(status & ST_OVERRUN)
-					status = TTY_OVERRUN;
-				else
-					status = 0;
-			} else
-				status = 0;
-			tty_insert_flip_char(tty, ch, status);
-			tty_schedule_flip(tty);
-		}
-	} else {
-		printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
-		tty_kref_put(tty);
-		return;
-	}
-
-stl_rxalldone:
-	tty_kref_put(tty);
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-
-/*
- *	Modem interrupt handler. The is called when the modem signal line
- *	(DCD) has changed state. Leave most of the work to the off-level
- *	processing routine.
- */
-
-static void stl_cd1400mdmisr(struct stlpanel *panelp, int ioaddr)
-{
-	struct stlport	*portp;
-	unsigned int	ioack;
-	unsigned char	misr;
-
-	pr_debug("stl_cd1400mdmisr(panelp=%p)\n", panelp);
-
-	ioack = inb(ioaddr + EREG_MDACK);
-	if (((ioack & panelp->ackmask) != 0) ||
-	    ((ioack & ACK_TYPMASK) != ACK_TYPMDM)) {
-		printk("STALLION: bad MODEM interrupt ack value=%x\n", ioack);
-		return;
-	}
-	portp = panelp->ports[(ioack >> 3)];
-
-	outb((MISR + portp->uartaddr), ioaddr);
-	misr = inb(ioaddr + EREG_DATA);
-	if (misr & MISR_DCD) {
-		stl_cd_change(portp);
-		portp->stats.modem++;
-	}
-
-	outb((EOSRR + portp->uartaddr), ioaddr);
-	outb(0, (ioaddr + EREG_DATA));
-}
-
-/*****************************************************************************/
-/*                      SC26198 HARDWARE FUNCTIONS                           */
-/*****************************************************************************/
-
-/*
- *	These functions get/set/update the registers of the sc26198 UARTs.
- *	Access to the sc26198 registers is via an address/data io port pair.
- *	(Maybe should make this inline...)
- */
-
-static int stl_sc26198getreg(struct stlport *portp, int regnr)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	return inb(portp->ioaddr + XP_DATA);
-}
-
-static void stl_sc26198setreg(struct stlport *portp, int regnr, int value)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	outb(value, (portp->ioaddr + XP_DATA));
-}
-
-static int stl_sc26198updatereg(struct stlport *portp, int regnr, int value)
-{
-	outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-	if (inb(portp->ioaddr + XP_DATA) != value) {
-		outb(value, (portp->ioaddr + XP_DATA));
-		return 1;
-	}
-	return 0;
-}
-
-/*****************************************************************************/
-
-/*
- *	Functions to get and set the sc26198 global registers.
- */
-
-static int stl_sc26198getglobreg(struct stlport *portp, int regnr)
-{
-	outb(regnr, (portp->ioaddr + XP_ADDR));
-	return inb(portp->ioaddr + XP_DATA);
-}
-
-#if 0
-static void stl_sc26198setglobreg(struct stlport *portp, int regnr, int value)
-{
-	outb(regnr, (portp->ioaddr + XP_ADDR));
-	outb(value, (portp->ioaddr + XP_DATA));
-}
-#endif
-
-/*****************************************************************************/
-
-/*
- *	Inbitialize the UARTs in a panel. We don't care what sort of board
- *	these ports are on - since the port io registers are almost
- *	identical when dealing with ports.
- */
-
-static int stl_sc26198panelinit(struct stlbrd *brdp, struct stlpanel *panelp)
-{
-	int	chipmask, i;
-	int	nrchips, ioaddr;
-
-	pr_debug("stl_sc26198panelinit(brdp=%p,panelp=%p)\n", brdp, panelp);
-
-	BRDENABLE(panelp->brdnr, panelp->pagenr);
-
-/*
- *	Check that each chip is present and started up OK.
- */
-	chipmask = 0;
-	nrchips = (panelp->nrports + 4) / SC26198_PORTS;
-	if (brdp->brdtype == BRD_ECHPCI)
-		outb(panelp->pagenr, brdp->ioctrl);
-
-	for (i = 0; i < nrchips; i++) {
-		ioaddr = panelp->iobase + (i * 4); 
-		outb(SCCR, (ioaddr + XP_ADDR));
-		outb(CR_RESETALL, (ioaddr + XP_DATA));
-		outb(TSTR, (ioaddr + XP_ADDR));
-		if (inb(ioaddr + XP_DATA) != 0) {
-			printk("STALLION: sc26198 not responding, "
-				"brd=%d panel=%d chip=%d\n",
-				panelp->brdnr, panelp->panelnr, i);
-			continue;
-		}
-		chipmask |= (0x1 << i);
-		outb(GCCR, (ioaddr + XP_ADDR));
-		outb(GCCR_IVRTYPCHANACK, (ioaddr + XP_DATA));
-		outb(WDTRCR, (ioaddr + XP_ADDR));
-		outb(0xff, (ioaddr + XP_DATA));
-	}
-
-	BRDDISABLE(panelp->brdnr);
-	return chipmask;
-}
-
-/*****************************************************************************/
-
-/*
- *	Initialize hardware specific port registers.
- */
-
-static void stl_sc26198portinit(struct stlbrd *brdp, struct stlpanel *panelp, struct stlport *portp)
-{
-	pr_debug("stl_sc26198portinit(brdp=%p,panelp=%p,portp=%p)\n", brdp,
-			panelp, portp);
-
-	if ((brdp == NULL) || (panelp == NULL) ||
-	    (portp == NULL))
-		return;
-
-	portp->ioaddr = panelp->iobase + ((portp->portnr < 8) ? 0 : 4);
-	portp->uartaddr = (portp->portnr & 0x07) << 4;
-	portp->pagenr = panelp->pagenr;
-	portp->hwid = 0x1;
-
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IOPCR, IOPCR_SETSIGS);
-	BRDDISABLE(portp->brdnr);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set up the sc26198 registers for a port based on the termios port
- *	settings.
- */
-
-static void stl_sc26198setport(struct stlport *portp, struct ktermios *tiosp)
-{
-	struct stlbrd	*brdp;
-	unsigned long	flags;
-	unsigned int	baudrate;
-	unsigned char	mr0, mr1, mr2, clk;
-	unsigned char	imron, imroff, iopr, ipr;
-
-	mr0 = 0;
-	mr1 = 0;
-	mr2 = 0;
-	clk = 0;
-	iopr = 0;
-	imron = 0;
-	imroff = 0;
-
-	brdp = stl_brds[portp->brdnr];
-	if (brdp == NULL)
-		return;
-
-/*
- *	Set up the RX char ignore mask with those RX error types we
- *	can ignore.
- */
-	portp->rxignoremsk = 0;
-	if (tiosp->c_iflag & IGNPAR)
-		portp->rxignoremsk |= (SR_RXPARITY | SR_RXFRAMING |
-			SR_RXOVERRUN);
-	if (tiosp->c_iflag & IGNBRK)
-		portp->rxignoremsk |= SR_RXBREAK;
-
-	portp->rxmarkmsk = SR_RXOVERRUN;
-	if (tiosp->c_iflag & (INPCK | PARMRK))
-		portp->rxmarkmsk |= (SR_RXPARITY | SR_RXFRAMING);
-	if (tiosp->c_iflag & BRKINT)
-		portp->rxmarkmsk |= SR_RXBREAK;
-
-/*
- *	Go through the char size, parity and stop bits and set all the
- *	option register appropriately.
- */
-	switch (tiosp->c_cflag & CSIZE) {
-	case CS5:
-		mr1 |= MR1_CS5;
-		break;
-	case CS6:
-		mr1 |= MR1_CS6;
-		break;
-	case CS7:
-		mr1 |= MR1_CS7;
-		break;
-	default:
-		mr1 |= MR1_CS8;
-		break;
-	}
-
-	if (tiosp->c_cflag & CSTOPB)
-		mr2 |= MR2_STOP2;
-	else
-		mr2 |= MR2_STOP1;
-
-	if (tiosp->c_cflag & PARENB) {
-		if (tiosp->c_cflag & PARODD)
-			mr1 |= (MR1_PARENB | MR1_PARODD);
-		else
-			mr1 |= (MR1_PARENB | MR1_PAREVEN);
-	} else
-		mr1 |= MR1_PARNONE;
-
-	mr1 |= MR1_ERRBLOCK;
-
-/*
- *	Set the RX FIFO threshold at 8 chars. This gives a bit of breathing
- *	space for hardware flow control and the like. This should be set to
- *	VMIN.
- */
-	mr2 |= MR2_RXFIFOHALF;
-
-/*
- *	Calculate the baud rate timers. For now we will just assume that
- *	the input and output baud are the same. The sc26198 has a fixed
- *	baud rate table, so only discrete baud rates possible.
- */
-	baudrate = tiosp->c_cflag & CBAUD;
-	if (baudrate & CBAUDEX) {
-		baudrate &= ~CBAUDEX;
-		if ((baudrate < 1) || (baudrate > 4))
-			tiosp->c_cflag &= ~CBAUDEX;
-		else
-			baudrate += 15;
-	}
-	baudrate = stl_baudrates[baudrate];
-	if ((tiosp->c_cflag & CBAUD) == B38400) {
-		if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
-			baudrate = 57600;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
-			baudrate = 115200;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
-			baudrate = 230400;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
-			baudrate = 460800;
-		else if ((portp->port.flags & ASYNC_SPD_MASK) == ASYNC_SPD_CUST)
-			baudrate = (portp->baud_base / portp->custom_divisor);
-	}
-	if (baudrate > STL_SC26198MAXBAUD)
-		baudrate = STL_SC26198MAXBAUD;
-
-	if (baudrate > 0)
-		for (clk = 0; clk < SC26198_NRBAUDS; clk++)
-			if (baudrate <= sc26198_baudtable[clk])
-				break;
-
-/*
- *	Check what form of modem signaling is required and set it up.
- */
-	if (tiosp->c_cflag & CLOCAL) {
-		portp->port.flags &= ~ASYNC_CHECK_CD;
-	} else {
-		iopr |= IOPR_DCDCOS;
-		imron |= IR_IOPORT;
-		portp->port.flags |= ASYNC_CHECK_CD;
-	}
-
-/*
- *	Setup sc26198 enhanced modes if we can. In particular we want to
- *	handle as much of the flow control as possible automatically. As
- *	well as saving a few CPU cycles it will also greatly improve flow
- *	control reliability.
- */
-	if (tiosp->c_iflag & IXON) {
-		mr0 |= MR0_SWFTX | MR0_SWFT;
-		imron |= IR_XONXOFF;
-	} else
-		imroff |= IR_XONXOFF;
-
-	if (tiosp->c_iflag & IXOFF)
-		mr0 |= MR0_SWFRX;
-
-	if (tiosp->c_cflag & CRTSCTS) {
-		mr2 |= MR2_AUTOCTS;
-		mr1 |= MR1_AUTORTS;
-	}
-
-/*
- *	All sc26198 register values calculated so go through and set
- *	them all up.
- */
-
-	pr_debug("SETPORT: portnr=%d panelnr=%d brdnr=%d\n",
-		portp->portnr, portp->panelnr, portp->brdnr);
-	pr_debug("    mr0=%x mr1=%x mr2=%x clk=%x\n", mr0, mr1, mr2, clk);
-	pr_debug("    iopr=%x imron=%x imroff=%x\n", iopr, imron, imroff);
-	pr_debug("    schr1=%x schr2=%x schr3=%x schr4=%x\n",
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP],
-		tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IMR, 0);
-	stl_sc26198updatereg(portp, MR0, mr0);
-	stl_sc26198updatereg(portp, MR1, mr1);
-	stl_sc26198setreg(portp, SCCR, CR_RXERRBLOCK);
-	stl_sc26198updatereg(portp, MR2, mr2);
-	stl_sc26198updatereg(portp, IOPIOR,
-		((stl_sc26198getreg(portp, IOPIOR) & ~IPR_CHANGEMASK) | iopr));
-
-	if (baudrate > 0) {
-		stl_sc26198setreg(portp, TXCSR, clk);
-		stl_sc26198setreg(portp, RXCSR, clk);
-	}
-
-	stl_sc26198setreg(portp, XONCR, tiosp->c_cc[VSTART]);
-	stl_sc26198setreg(portp, XOFFCR, tiosp->c_cc[VSTOP]);
-
-	ipr = stl_sc26198getreg(portp, IPR);
-	if (ipr & IPR_DCD)
-		portp->sigs &= ~TIOCM_CD;
-	else
-		portp->sigs |= TIOCM_CD;
-
-	portp->imr = (portp->imr & ~imroff) | imron;
-	stl_sc26198setreg(portp, IMR, portp->imr);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Set the state of the DTR and RTS signals.
- */
-
-static void stl_sc26198setsignals(struct stlport *portp, int dtr, int rts)
-{
-	unsigned char	iopioron, iopioroff;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198setsignals(portp=%p,dtr=%d,rts=%d)\n", portp,
-			dtr, rts);
-
-	iopioron = 0;
-	iopioroff = 0;
-	if (dtr == 0)
-		iopioroff |= IPR_DTR;
-	else if (dtr > 0)
-		iopioron |= IPR_DTR;
-	if (rts == 0)
-		iopioroff |= IPR_RTS;
-	else if (rts > 0)
-		iopioron |= IPR_RTS;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IOPIOR,
-		((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the state of the signals.
- */
-
-static int stl_sc26198getsignals(struct stlport *portp)
-{
-	unsigned char	ipr;
-	unsigned long	flags;
-	int		sigs;
-
-	pr_debug("stl_sc26198getsignals(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	ipr = stl_sc26198getreg(portp, IPR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	sigs = 0;
-	sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
-	sigs |= (ipr & IPR_CTS) ? 0 : TIOCM_CTS;
-	sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
-	sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
-	sigs |= TIOCM_DSR;
-	return sigs;
-}
-
-/*****************************************************************************/
-
-/*
- *	Enable/Disable the Transmitter and/or Receiver.
- */
-
-static void stl_sc26198enablerxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	ccr;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198enablerxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx,tx);
-
-	ccr = portp->crenable;
-	if (tx == 0)
-		ccr &= ~CR_TXENABLE;
-	else if (tx > 0)
-		ccr |= CR_TXENABLE;
-	if (rx == 0)
-		ccr &= ~CR_RXENABLE;
-	else if (rx > 0)
-		ccr |= CR_RXENABLE;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, SCCR, ccr);
-	BRDDISABLE(portp->brdnr);
-	portp->crenable = ccr;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Start/stop the Transmitter and/or Receiver.
- */
-
-static void stl_sc26198startrxtx(struct stlport *portp, int rx, int tx)
-{
-	unsigned char	imr;
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198startrxtx(portp=%p,rx=%d,tx=%d)\n", portp, rx, tx);
-
-	imr = portp->imr;
-	if (tx == 0)
-		imr &= ~IR_TXRDY;
-	else if (tx == 1)
-		imr |= IR_TXRDY;
-	if (rx == 0)
-		imr &= ~(IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG);
-	else if (rx > 0)
-		imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, IMR, imr);
-	BRDDISABLE(portp->brdnr);
-	portp->imr = imr;
-	if (tx > 0)
-		set_bit(ASYI_TXBUSY, &portp->istate);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Disable all interrupts from this port.
- */
-
-static void stl_sc26198disableintrs(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198disableintrs(portp=%p)\n", portp);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	portp->imr = 0;
-	stl_sc26198setreg(portp, IMR, 0);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-static void stl_sc26198sendbreak(struct stlport *portp, int len)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198sendbreak(portp=%p,len=%d)\n", portp, len);
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	if (len == 1) {
-		stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
-		portp->stats.txbreaks++;
-	} else
-		stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Take flow control actions...
- */
-
-static void stl_sc26198flowctrl(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-	unsigned char		mr0;
-
-	pr_debug("stl_sc26198flowctrl(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-
-	if (state) {
-		if (tty->termios->c_iflag & IXOFF) {
-			mr0 = stl_sc26198getreg(portp, MR0);
-			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-			stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
-			mr0 |= MR0_SWFRX;
-			portp->stats.rxxon++;
-			stl_sc26198wait(portp);
-			stl_sc26198setreg(portp, MR0, mr0);
-		}
-/*
- *		Question: should we return RTS to what it was before? It may
- *		have been set by an ioctl... Suppose not, since if you have
- *		hardware flow control set then it is pretty silly to go and
- *		set the RTS line by hand.
- */
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_sc26198setreg(portp, MR1,
-				(stl_sc26198getreg(portp, MR1) | MR1_AUTORTS));
-			stl_sc26198setreg(portp, IOPIOR,
-				(stl_sc26198getreg(portp, IOPIOR) | IOPR_RTS));
-			portp->stats.rxrtson++;
-		}
-	} else {
-		if (tty->termios->c_iflag & IXOFF) {
-			mr0 = stl_sc26198getreg(portp, MR0);
-			stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-			stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
-			mr0 &= ~MR0_SWFRX;
-			portp->stats.rxxoff++;
-			stl_sc26198wait(portp);
-			stl_sc26198setreg(portp, MR0, mr0);
-		}
-		if (tty->termios->c_cflag & CRTSCTS) {
-			stl_sc26198setreg(portp, MR1,
-				(stl_sc26198getreg(portp, MR1) & ~MR1_AUTORTS));
-			stl_sc26198setreg(portp, IOPIOR,
-				(stl_sc26198getreg(portp, IOPIOR) & ~IOPR_RTS));
-			portp->stats.rxrtsoff++;
-		}
-	}
-
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Send a flow control character.
- */
-
-static void stl_sc26198sendflow(struct stlport *portp, int state)
-{
-	struct tty_struct	*tty;
-	unsigned long		flags;
-	unsigned char		mr0;
-
-	pr_debug("stl_sc26198sendflow(portp=%p,state=%x)\n", portp, state);
-
-	if (portp == NULL)
-		return;
-	tty = tty_port_tty_get(&portp->port);
-	if (tty == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	if (state) {
-		mr0 = stl_sc26198getreg(portp, MR0);
-		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-		stl_sc26198setreg(portp, SCCR, CR_TXSENDXON);
-		mr0 |= MR0_SWFRX;
-		portp->stats.rxxon++;
-		stl_sc26198wait(portp);
-		stl_sc26198setreg(portp, MR0, mr0);
-	} else {
-		mr0 = stl_sc26198getreg(portp, MR0);
-		stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-		stl_sc26198setreg(portp, SCCR, CR_TXSENDXOFF);
-		mr0 &= ~MR0_SWFRX;
-		portp->stats.rxxoff++;
-		stl_sc26198wait(portp);
-		stl_sc26198setreg(portp, MR0, mr0);
-	}
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-static void stl_sc26198flush(struct stlport *portp)
-{
-	unsigned long	flags;
-
-	pr_debug("stl_sc26198flush(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	stl_sc26198setreg(portp, SCCR, CR_TXRESET);
-	stl_sc26198setreg(portp, SCCR, portp->crenable);
-	BRDDISABLE(portp->brdnr);
-	portp->tx.tail = portp->tx.head;
-	spin_unlock_irqrestore(&brd_lock, flags);
-}
-
-/*****************************************************************************/
-
-/*
- *	Return the current state of data flow on this port. This is only
- *	really interesting when determining if data has fully completed
- *	transmission or not... The sc26198 interrupt scheme cannot
- *	determine when all data has actually drained, so we need to
- *	check the port statusy register to be sure.
- */
-
-static int stl_sc26198datastate(struct stlport *portp)
-{
-	unsigned long	flags;
-	unsigned char	sr;
-
-	pr_debug("stl_sc26198datastate(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return 0;
-	if (test_bit(ASYI_TXBUSY, &portp->istate))
-		return 1;
-
-	spin_lock_irqsave(&brd_lock, flags);
-	BRDENABLE(portp->brdnr, portp->pagenr);
-	sr = stl_sc26198getreg(portp, SR);
-	BRDDISABLE(portp->brdnr);
-	spin_unlock_irqrestore(&brd_lock, flags);
-
-	return (sr & SR_TXEMPTY) ? 0 : 1;
-}
-
-/*****************************************************************************/
-
-/*
- *	Delay for a small amount of time, to give the sc26198 a chance
- *	to process a command...
- */
-
-static void stl_sc26198wait(struct stlport *portp)
-{
-	int	i;
-
-	pr_debug("stl_sc26198wait(portp=%p)\n", portp);
-
-	if (portp == NULL)
-		return;
-
-	for (i = 0; i < 20; i++)
-		stl_sc26198getglobreg(portp, TSTR);
-}
-
-/*****************************************************************************/
-
-/*
- *	If we are TX flow controlled and in IXANY mode then we may
- *	need to unflow control here. We gotta do this because of the
- *	automatic flow control modes of the sc26198.
- */
-
-static void stl_sc26198txunflow(struct stlport *portp, struct tty_struct *tty)
-{
-	unsigned char	mr0;
-
-	mr0 = stl_sc26198getreg(portp, MR0);
-	stl_sc26198setreg(portp, MR0, (mr0 & ~MR0_SWFRXTX));
-	stl_sc26198setreg(portp, SCCR, CR_HOSTXON);
-	stl_sc26198wait(portp);
-	stl_sc26198setreg(portp, MR0, mr0);
-	clear_bit(ASYI_TXFLOWED, &portp->istate);
-}
-
-/*****************************************************************************/
-
-/*
- *	Interrupt service routine for sc26198 panels.
- */
-
-static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
-{
-	struct stlport	*portp;
-	unsigned int	iack;
-
-	spin_lock(&brd_lock);
-
-/* 
- *	Work around bug in sc26198 chip... Cannot have A6 address
- *	line of UART high, else iack will be returned as 0.
- */
-	outb(0, (iobase + 1));
-
-	iack = inb(iobase + XP_IACK);
-	portp = panelp->ports[(iack & IVR_CHANMASK) + ((iobase & 0x4) << 1)];
-
-	if (iack & IVR_RXDATA)
-		stl_sc26198rxisr(portp, iack);
-	else if (iack & IVR_TXDATA)
-		stl_sc26198txisr(portp);
-	else
-		stl_sc26198otherisr(portp, iack);
-
-	spin_unlock(&brd_lock);
-}
-
-/*****************************************************************************/
-
-/*
- *	Transmit interrupt handler. This has gotta be fast!  Handling TX
- *	chars is pretty simple, stuff as many as possible from the TX buffer
- *	into the sc26198 FIFO.
- *	In practice it is possible that interrupts are enabled but that the
- *	port has been hung up. Need to handle not having any TX buffer here,
- *	this is done by using the side effect that head and tail will also
- *	be NULL if the buffer has been freed.
- */
-
-static void stl_sc26198txisr(struct stlport *portp)
-{
-	struct tty_struct *tty;
-	unsigned int	ioaddr;
-	unsigned char	mr0;
-	int		len, stlen;
-	char		*head, *tail;
-
-	pr_debug("stl_sc26198txisr(portp=%p)\n", portp);
-
-	ioaddr = portp->ioaddr;
-	head = portp->tx.head;
-	tail = portp->tx.tail;
-	len = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
-	if ((len == 0) || ((len < STL_TXBUFLOW) &&
-	    (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
-		set_bit(ASYI_TXLOW, &portp->istate);
-		tty = tty_port_tty_get(&portp->port);
-		if (tty) {
-			tty_wakeup(tty);
-			tty_kref_put(tty);
-		}
-	}
-
-	if (len == 0) {
-		outb((MR0 | portp->uartaddr), (ioaddr + XP_ADDR));
-		mr0 = inb(ioaddr + XP_DATA);
-		if ((mr0 & MR0_TXMASK) == MR0_TXEMPTY) {
-			portp->imr &= ~IR_TXRDY;
-			outb((IMR | portp->uartaddr), (ioaddr + XP_ADDR));
-			outb(portp->imr, (ioaddr + XP_DATA));
-			clear_bit(ASYI_TXBUSY, &portp->istate);
-		} else {
-			mr0 |= ((mr0 & ~MR0_TXMASK) | MR0_TXEMPTY);
-			outb(mr0, (ioaddr + XP_DATA));
-		}
-	} else {
-		len = min(len, SC26198_TXFIFOSIZE);
-		portp->stats.txtotal += len;
-		stlen = min_t(unsigned int, len,
-				(portp->tx.buf + STL_TXBUFSIZE) - tail);
-		outb(GTXFIFO, (ioaddr + XP_ADDR));
-		outsb((ioaddr + XP_DATA), tail, stlen);
-		len -= stlen;
-		tail += stlen;
-		if (tail >= (portp->tx.buf + STL_TXBUFSIZE))
-			tail = portp->tx.buf;
-		if (len > 0) {
-			outsb((ioaddr + XP_DATA), tail, len);
-			tail += len;
-		}
-		portp->tx.tail = tail;
-	}
-}
-
-/*****************************************************************************/
-
-/*
- *	Receive character interrupt handler. Determine if we have good chars
- *	or bad chars and then process appropriately. Good chars are easy
- *	just shove the lot into the RX buffer and set all status byte to 0.
- *	If a bad RX char then process as required. This routine needs to be
- *	fast!  In practice it is possible that we get an interrupt on a port
- *	that is closed. This can happen on hangups - since they completely
- *	shutdown a port not in user context. Need to handle this case.
- */
-
-static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
-{
-	struct tty_struct	*tty;
-	unsigned int		len, buflen, ioaddr;
-
-	pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
-
-	tty = tty_port_tty_get(&portp->port);
-	ioaddr = portp->ioaddr;
-	outb(GIBCR, (ioaddr + XP_ADDR));
-	len = inb(ioaddr + XP_DATA) + 1;
-
-	if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
-		if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
-			len = min_t(unsigned int, len, sizeof(stl_unwanted));
-			outb(GRXFIFO, (ioaddr + XP_ADDR));
-			insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
-			portp->stats.rxlost += len;
-			portp->stats.rxtotal += len;
-		} else {
-			len = min(len, buflen);
-			if (len > 0) {
-				unsigned char *ptr;
-				outb(GRXFIFO, (ioaddr + XP_ADDR));
-				tty_prepare_flip_string(tty, &ptr, len);
-				insb((ioaddr + XP_DATA), ptr, len);
-				tty_schedule_flip(tty);
-				portp->stats.rxtotal += len;
-			}
-		}
-	} else {
-		stl_sc26198rxbadchars(portp);
-	}
-
-/*
- *	If we are TX flow controlled and in IXANY mode then we may need
- *	to unflow control here. We gotta do this because of the automatic
- *	flow control modes of the sc26198.
- */
-	if (test_bit(ASYI_TXFLOWED, &portp->istate)) {
-		if ((tty != NULL) &&
-		    (tty->termios != NULL) &&
-		    (tty->termios->c_iflag & IXANY)) {
-			stl_sc26198txunflow(portp, tty);
-		}
-	}
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Process an RX bad character.
- */
-
-static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char ch)
-{
-	struct tty_struct	*tty;
-	unsigned int		ioaddr;
-
-	tty = tty_port_tty_get(&portp->port);
-	ioaddr = portp->ioaddr;
-
-	if (status & SR_RXPARITY)
-		portp->stats.rxparity++;
-	if (status & SR_RXFRAMING)
-		portp->stats.rxframing++;
-	if (status & SR_RXOVERRUN)
-		portp->stats.rxoverrun++;
-	if (status & SR_RXBREAK)
-		portp->stats.rxbreaks++;
-
-	if ((tty != NULL) &&
-	    ((portp->rxignoremsk & status) == 0)) {
-		if (portp->rxmarkmsk & status) {
-			if (status & SR_RXBREAK) {
-				status = TTY_BREAK;
-				if (portp->port.flags & ASYNC_SAK) {
-					do_SAK(tty);
-					BRDENABLE(portp->brdnr, portp->pagenr);
-				}
-			} else if (status & SR_RXPARITY)
-				status = TTY_PARITY;
-			else if (status & SR_RXFRAMING)
-				status = TTY_FRAME;
-			else if(status & SR_RXOVERRUN)
-				status = TTY_OVERRUN;
-			else
-				status = 0;
-		} else
-			status = 0;
-
-		tty_insert_flip_char(tty, ch, status);
-		tty_schedule_flip(tty);
-
-		if (status == 0)
-			portp->stats.rxtotal++;
-	}
-	tty_kref_put(tty);
-}
-
-/*****************************************************************************/
-
-/*
- *	Process all characters in the RX FIFO of the UART. Check all char
- *	status bytes as well, and process as required. We need to check
- *	all bytes in the FIFO, in case some more enter the FIFO while we
- *	are here. To get the exact character error type we need to switch
- *	into CHAR error mode (that is why we need to make sure we empty
- *	the FIFO).
- */
-
-static void stl_sc26198rxbadchars(struct stlport *portp)
-{
-	unsigned char	status, mr1;
-	char		ch;
-
-/*
- *	To get the precise error type for each character we must switch
- *	back into CHAR error mode.
- */
-	mr1 = stl_sc26198getreg(portp, MR1);
-	stl_sc26198setreg(portp, MR1, (mr1 & ~MR1_ERRBLOCK));
-
-	while ((status = stl_sc26198getreg(portp, SR)) & SR_RXRDY) {
-		stl_sc26198setreg(portp, SCCR, CR_CLEARRXERR);
-		ch = stl_sc26198getreg(portp, RXFIFO);
-		stl_sc26198rxbadch(portp, status, ch);
-	}
-
-/*
- *	To get correct interrupt class we must switch back into BLOCK
- *	error mode.
- */
-	stl_sc26198setreg(portp, MR1, mr1);
-}
-
-/*****************************************************************************/
-
-/*
- *	Other interrupt handler. This includes modem signals, flow
- *	control actions, etc. Most stuff is left to off-level interrupt
- *	processing time.
- */
-
-static void stl_sc26198otherisr(struct stlport *portp, unsigned int iack)
-{
-	unsigned char	cir, ipr, xisr;
-
-	pr_debug("stl_sc26198otherisr(portp=%p,iack=%x)\n", portp, iack);
-
-	cir = stl_sc26198getglobreg(portp, CIR);
-
-	switch (cir & CIR_SUBTYPEMASK) {
-	case CIR_SUBCOS:
-		ipr = stl_sc26198getreg(portp, IPR);
-		if (ipr & IPR_DCDCHANGE) {
-			stl_cd_change(portp);
-			portp->stats.modem++;
-		}
-		break;
-	case CIR_SUBXONXOFF:
-		xisr = stl_sc26198getreg(portp, XISR);
-		if (xisr & XISR_RXXONGOT) {
-			set_bit(ASYI_TXFLOWED, &portp->istate);
-			portp->stats.txxoff++;
-		}
-		if (xisr & XISR_RXXOFFGOT) {
-			clear_bit(ASYI_TXFLOWED, &portp->istate);
-			portp->stats.txxon++;
-		}
-		break;
-	case CIR_SUBBREAK:
-		stl_sc26198setreg(portp, SCCR, CR_BREAKRESET);
-		stl_sc26198rxbadchars(portp);
-		break;
-	default:
-		break;
-	}
-}
-
-static void stl_free_isabrds(void)
-{
-	struct stlbrd *brdp;
-	unsigned int i;
-
-	for (i = 0; i < stl_nrbrds; i++) {
-		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
-			continue;
-
-		free_irq(brdp->irq, brdp);
-
-		stl_cleanup_panels(brdp);
-
-		release_region(brdp->ioaddr1, brdp->iosize1);
-		if (brdp->iosize2 > 0)
-			release_region(brdp->ioaddr2, brdp->iosize2);
-
-		kfree(brdp);
-		stl_brds[i] = NULL;
-	}
-}
-
-/*
- *	Loadable module initialization stuff.
- */
-static int __init stallion_module_init(void)
-{
-	struct stlbrd	*brdp;
-	struct stlconf	conf;
-	unsigned int i, j;
-	int retval;
-
-	printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
-
-	spin_lock_init(&stallion_lock);
-	spin_lock_init(&brd_lock);
-
-	stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
-	if (!stl_serial) {
-		retval = -ENOMEM;
-		goto err;
-	}
-
-	stl_serial->owner = THIS_MODULE;
-	stl_serial->driver_name = stl_drvname;
-	stl_serial->name = "ttyE";
-	stl_serial->major = STL_SERIALMAJOR;
-	stl_serial->minor_start = 0;
-	stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
-	stl_serial->subtype = SERIAL_TYPE_NORMAL;
-	stl_serial->init_termios = stl_deftermios;
-	stl_serial->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(stl_serial, &stl_ops);
-
-	retval = tty_register_driver(stl_serial);
-	if (retval) {
-		printk("STALLION: failed to register serial driver\n");
-		goto err_frtty;
-	}
-
-/*
- *	Find any dynamically supported boards. That is via module load
- *	line options.
- */
-	for (i = stl_nrbrds; i < stl_nargs; i++) {
-		memset(&conf, 0, sizeof(conf));
-		if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
-			continue;
-		if ((brdp = stl_allocbrd()) == NULL)
-			continue;
-		brdp->brdnr = i;
-		brdp->brdtype = conf.brdtype;
-		brdp->ioaddr1 = conf.ioaddr1;
-		brdp->ioaddr2 = conf.ioaddr2;
-		brdp->irq = conf.irq;
-		brdp->irqtype = conf.irqtype;
-		stl_brds[brdp->brdnr] = brdp;
-		if (stl_brdinit(brdp)) {
-			stl_brds[brdp->brdnr] = NULL;
-			kfree(brdp);
-		} else {
-			for (j = 0; j < brdp->nrports; j++)
-				tty_register_device(stl_serial,
-					brdp->brdnr * STL_MAXPORTS + j, NULL);
-			stl_nrbrds = i + 1;
-		}
-	}
-
-	/* this has to be _after_ isa finding because of locking */
-	retval = pci_register_driver(&stl_pcidriver);
-	if (retval && stl_nrbrds == 0) {
-		printk(KERN_ERR "STALLION: can't register pci driver\n");
-		goto err_unrtty;
-	}
-
-/*
- *	Set up a character driver for per board stuff. This is mainly used
- *	to do stats ioctls on the ports.
- */
-	if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
-		printk("STALLION: failed to register serial board device\n");
-
-	stallion_class = class_create(THIS_MODULE, "staliomem");
-	if (IS_ERR(stallion_class))
-		printk("STALLION: failed to create class\n");
-	for (i = 0; i < 4; i++)
-		device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-			      NULL, "staliomem%d", i);
-
-	return 0;
-err_unrtty:
-	tty_unregister_driver(stl_serial);
-err_frtty:
-	put_tty_driver(stl_serial);
-err:
-	return retval;
-}
-
-static void __exit stallion_module_exit(void)
-{
-	struct stlbrd *brdp;
-	unsigned int i, j;
-
-	pr_debug("cleanup_module()\n");
-
-	printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
-		stl_drvversion);
-
-/*
- *	Free up all allocated resources used by the ports. This includes
- *	memory and interrupts. As part of this process we will also do
- *	a hangup on every open port - to try to flush out any processes
- *	hanging onto ports.
- */
-	for (i = 0; i < stl_nrbrds; i++) {
-		if ((brdp = stl_brds[i]) == NULL || (brdp->state & STL_PROBED))
-			continue;
-		for (j = 0; j < brdp->nrports; j++)
-			tty_unregister_device(stl_serial,
-				brdp->brdnr * STL_MAXPORTS + j);
-	}
-
-	for (i = 0; i < 4; i++)
-		device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
-	unregister_chrdev(STL_SIOMEMMAJOR, "staliomem");
-	class_destroy(stallion_class);
-
-	pci_unregister_driver(&stl_pcidriver);
-
-	stl_free_isabrds();
-
-	tty_unregister_driver(stl_serial);
-	put_tty_driver(stl_serial);
-}
-
-module_init(stallion_module_init);
-module_exit(stallion_module_exit);
-
-MODULE_AUTHOR("Greg Ungerer");
-MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/char/sxboards.h linux-libre-2.6.39-gnu/drivers/char/sxboards.h
--- linux-libre-2.6.38-gnu/drivers/char/sxboards.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/sxboards.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,206 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	SX/SI/XIO Board Hardware Definitions	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	16th March 1998				*/
-/*									*/
-/*	Version		:	3.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
-/*									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the SX/SI/XIO board hardware	*/
-/*									*/
-/************************************************************************/
-
-/* History...
-
-3.0.0	16/03/98 NPV	Creation.
-
-*/
-
-#ifndef	_sxboards_h				/* If SXBOARDS.H not already defined */
-#define	_sxboards_h    1
-
-/*****************************************************************************
-*******************************                 ******************************
-*******************************   Board Types   ******************************
-*******************************                 ******************************
-*****************************************************************************/
-
-/* BUS types... */
-#define		BUS_ISA		0
-#define		BUS_MCA		1
-#define		BUS_EISA	2
-#define		BUS_PCI		3
-
-/* Board phases... */
-#define		SI1_Z280	1
-#define		SI2_Z280	2
-#define		SI3_T225	3
-
-/* Board types... */
-#define		CARD_TYPE(bus,phase)	(bus<<4|phase)
-#define		CARD_BUS(type)		((type>>4)&0xF)
-#define		CARD_PHASE(type)	(type&0xF)
-
-#define		TYPE_SI1_ISA		CARD_TYPE(BUS_ISA,SI1_Z280)
-#define		TYPE_SI2_ISA		CARD_TYPE(BUS_ISA,SI2_Z280)
-#define		TYPE_SI2_EISA		CARD_TYPE(BUS_EISA,SI2_Z280)
-#define		TYPE_SI2_PCI		CARD_TYPE(BUS_PCI,SI2_Z280)
-
-#define		TYPE_SX_ISA		CARD_TYPE(BUS_ISA,SI3_T225)
-#define		TYPE_SX_PCI		CARD_TYPE(BUS_PCI,SI3_T225)
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 1 Z280   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* ISA board details... */
-#define		SI1_ISA_WINDOW_LEN	0x10000		/* 64 Kbyte shared memory window */
-//#define 	SI1_ISA_MEMORY_LEN	0x8000		/* Usable memory  - unused define*/
-//#define		SI1_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
-//#define		SI1_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-//#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
-//#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
-
-/* ISA board, register definitions... */
-//#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
-#define		SI1_ISA_RESET		0x8000		/* WRITE: Host Reset */
-#define		SI1_ISA_RESET_CLEAR	0xc000		/* WRITE: Host Reset clear*/
-#define		SI1_ISA_WAIT	        0x9000		/* WRITE: Host wait */
-#define		SI1_ISA_WAIT_CLEAR	0xd000		/* WRITE: Host wait clear */
-#define		SI1_ISA_INTCL        	0xa000		/* WRITE: Host Reset */
-#define		SI1_ISA_INTCL_CLEAR	0xe000		/* WRITE: Host Reset */
-
-
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 2 Z280   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* ISA board details... */
-#define		SI2_ISA_WINDOW_LEN	0x8000		/* 32 Kbyte shared memory window */
-#define 	SI2_ISA_MEMORY_LEN	0x7FF8		/* Usable memory */
-#define		SI2_ISA_ADDR_LOW	0x0A0000	/* Lowest address = 640 Kbyte */
-#define		SI2_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-#define		SI2_ISA_ADDR_STEP	SI2_ISA_WINDOW_LEN/* ISA board address step */
-#define		SI2_ISA_IRQ_MASK	0x9800		/* IRQs 15,12,11 */
-
-/* ISA board, register definitions... */
-#define		SI2_ISA_ID_BASE		0x7FF8			/* READ:  Board ID string */
-#define		SI2_ISA_RESET		SI2_ISA_ID_BASE		/* WRITE: Host Reset */
-#define		SI2_ISA_IRQ11		(SI2_ISA_ID_BASE+1)	/* WRITE: Set IRQ11 */
-#define		SI2_ISA_IRQ12		(SI2_ISA_ID_BASE+2)	/* WRITE: Set IRQ12 */
-#define		SI2_ISA_IRQ15		(SI2_ISA_ID_BASE+3)	/* WRITE: Set IRQ15 */
-#define		SI2_ISA_IRQSET		(SI2_ISA_ID_BASE+4)	/* WRITE: Set Host Interrupt */
-#define		SI2_ISA_INTCLEAR	(SI2_ISA_ID_BASE+5)	/* WRITE: Enable Host Interrupt */
-
-#define		SI2_ISA_IRQ11_SET	0x10
-#define		SI2_ISA_IRQ11_CLEAR	0x00
-#define		SI2_ISA_IRQ12_SET	0x10
-#define		SI2_ISA_IRQ12_CLEAR	0x00
-#define		SI2_ISA_IRQ15_SET	0x10
-#define		SI2_ISA_IRQ15_CLEAR	0x00
-#define		SI2_ISA_INTCLEAR_SET	0x10
-#define		SI2_ISA_INTCLEAR_CLEAR	0x00
-#define		SI2_ISA_IRQSET_CLEAR	0x10
-#define		SI2_ISA_IRQSET_SET	0x00
-#define		SI2_ISA_RESET_SET	0x00
-#define		SI2_ISA_RESET_CLEAR	0x10
-
-/* PCI board details... */
-#define		SI2_PCI_WINDOW_LEN	0x100000	/* 1 Mbyte memory window */
-
-/* PCI board register definitions... */
-#define		SI2_PCI_SET_IRQ		0x40001		/* Set Host Interrupt  */
-#define		SI2_PCI_RESET		0xC0001		/* Host Reset */
-
-/*****************************************************************************
-******************************                  ******************************
-******************************   Phase 3 T225   ******************************
-******************************                  ******************************
-*****************************************************************************/
-
-/* General board details... */
-#define		SX_WINDOW_LEN		64*1024		/* 64 Kbyte memory window */
-
-/* ISA board details... */
-#define		SX_ISA_ADDR_LOW		0x0A0000	/* Lowest address = 640 Kbyte */
-#define		SX_ISA_ADDR_HIGH	0xFF8000	/* Highest address = 16Mbyte - 32Kbyte */
-#define		SX_ISA_ADDR_STEP	SX_WINDOW_LEN	/* ISA board address step */
-#define		SX_ISA_IRQ_MASK		0x9E00		/* IRQs 15,12,11,10,9 */
-
-/* Hardware register definitions... */
-#define		SX_EVENT_STATUS		0x7800		/* READ:  T225 Event Status */
-#define		SX_EVENT_STROBE		0x7800		/* WRITE: T225 Event Strobe */
-#define		SX_EVENT_ENABLE		0x7880		/* WRITE: T225 Event Enable */
-#define		SX_VPD_ROM		0x7C00		/* READ:  Vital Product Data ROM */
-#define		SX_CONFIG		0x7C00		/* WRITE: Host Configuration Register */
-#define		SX_IRQ_STATUS		0x7C80		/* READ:  Host Interrupt Status */
-#define		SX_SET_IRQ		0x7C80		/* WRITE: Set Host Interrupt */
-#define		SX_RESET_STATUS		0x7D00		/* READ:  Host Reset Status */
-#define		SX_RESET		0x7D00		/* WRITE: Host Reset */
-#define		SX_RESET_IRQ		0x7D80		/* WRITE: Reset Host Interrupt */
-
-/* SX_VPD_ROM definitions... */
-#define		SX_VPD_SLX_ID1		0x00
-#define		SX_VPD_SLX_ID2		0x01
-#define		SX_VPD_HW_REV		0x02
-#define		SX_VPD_HW_ASSEM		0x03
-#define		SX_VPD_UNIQUEID4	0x04
-#define		SX_VPD_UNIQUEID3	0x05
-#define		SX_VPD_UNIQUEID2	0x06
-#define		SX_VPD_UNIQUEID1	0x07
-#define		SX_VPD_MANU_YEAR	0x08
-#define		SX_VPD_MANU_WEEK	0x09
-#define		SX_VPD_IDENT		0x10
-#define		SX_VPD_IDENT_STRING	"JET HOST BY KEV#"
-
-/* SX unique identifiers... */
-#define		SX_UNIQUEID_MASK	0xF0
-#define		SX_ISA_UNIQUEID1	0x20
-#define		SX_PCI_UNIQUEID1	0x50
-
-/* SX_CONFIG definitions... */
-#define		SX_CONF_BUSEN		0x02		/* Enable T225 memory and I/O */
-#define		SX_CONF_HOSTIRQ		0x04		/* Enable board to host interrupt */
-
-/* SX bootstrap... */
-#define		SX_BOOTSTRAP		"\x28\x20\x21\x02\x60\x0a"
-#define		SX_BOOTSTRAP_SIZE	6
-#define		SX_BOOTSTRAP_ADDR	(0x8000-SX_BOOTSTRAP_SIZE)
-
-/*****************************************************************************
-**********************************          **********************************
-**********************************   EISA   **********************************
-**********************************          **********************************
-*****************************************************************************/
-
-#define		SI2_EISA_OFF	 	0x42
-#define		SI2_EISA_VAL	 	0x01
-#define		SI2_EISA_WINDOW_LEN     0x10000
-
-/*****************************************************************************
-***********************************         **********************************
-***********************************   PCI   **********************************
-***********************************         **********************************
-*****************************************************************************/
-
-/* General definitions... */
-
-#define		SPX_VENDOR_ID		0x11CB		/* Assigned by the PCI SIG */
-#define		SPX_DEVICE_ID		0x4000		/* SI/XIO boards */
-#define		SPX_PLXDEVICE_ID	0x2000		/* SX boards */
-
-#define		SPX_SUB_VENDOR_ID	SPX_VENDOR_ID	/* Same as vendor id */
-#define		SI2_SUB_SYS_ID		0x400		/* Phase 2 (Z280) board */
-#define		SX_SUB_SYS_ID		0x200		/* Phase 3 (t225) board */
-
-#endif						/*_sxboards_h */
-
-/* End of SXBOARDS.H */
diff -druN linux-libre-2.6.38-gnu/drivers/char/sx.c linux-libre-2.6.39-gnu/drivers/char/sx.c
--- linux-libre-2.6.38-gnu/drivers/char/sx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/sx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2894 +0,0 @@
-/* sx.c -- driver for the Specialix SX series cards. 
- *
- *  This driver will also support the older SI, and XIO cards.
- *
- *
- *   (C) 1998 - 2004  R.E.Wolff@BitWizard.nl
- *
- *  Simon Allen (simonallen@cix.compulink.co.uk) wrote a previous
- *  version of this driver. Some fragments may have been copied. (none
- *  yet :-)
- *
- * Specialix pays for the development and support of this driver.
- * Please DO contact support@specialix.co.uk if you require
- * support. But please read the documentation (sx.txt) first.
- *
- *
- *
- *      This program is free software; you can redistribute it and/or
- *      modify it under the terms of the 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.
- *
- * Revision history:
- * Revision 1.33  2000/03/09 10:00:00  pvdl,wolff
- * - Fixed module and port counting
- * - Fixed signal handling
- * - Fixed an Ooops
- * 
- * Revision 1.32  2000/03/07 09:00:00  wolff,pvdl
- * - Fixed some sx_dprintk typos
- * - added detection for an invalid board/module configuration
- *
- * Revision 1.31  2000/03/06 12:00:00  wolff,pvdl
- * - Added support for EISA
- *
- * Revision 1.30  2000/01/21 17:43:06  wolff
- * - Added support for SX+
- *
- * Revision 1.26  1999/08/05 15:22:14  wolff
- * - Port to 2.3.x
- * - Reformatted to Linus' liking.
- *
- * Revision 1.25  1999/07/30 14:24:08  wolff
- * Had accidentally left "gs_debug" set to "-1" instead of "off" (=0).
- *
- * Revision 1.24  1999/07/28 09:41:52  wolff
- * - I noticed the remark about use-count straying in sx.txt. I checked
- *   sx_open, and found a few places where that could happen. I hope it's
- *   fixed now.
- *
- * Revision 1.23  1999/07/28 08:56:06  wolff
- * - Fixed crash when sx_firmware run twice.
- * - Added sx_slowpoll as a module parameter (I guess nobody really wanted
- *   to change it from the default... )
- * - Fixed a stupid editing problem I introduced in 1.22.
- * - Fixed dropping characters on a termios change.
- *
- * Revision 1.22  1999/07/26 21:01:43  wolff
- * Russell Brown noticed that I had overlooked 4 out of six modem control
- * signals in sx_getsignals. Ooops.
- *
- * Revision 1.21  1999/07/23 09:11:33  wolff
- * I forgot to free dynamically allocated memory when the driver is unloaded.
- *
- * Revision 1.20  1999/07/20 06:25:26  wolff
- * The "closing wait" wasn't honoured. Thanks to James Griffiths for
- * reporting this.
- *
- * Revision 1.19  1999/07/11 08:59:59  wolff
- * Fixed an oops in close, when an open was pending. Changed the memtest
- * a bit. Should also test the board in word-mode, however my card fails the
- * memtest then. I still have to figure out what is wrong...
- *
- * Revision 1.18  1999/06/10 09:38:42  wolff
- * Changed the format of the firmware revision from %04x to %x.%02x .
- *
- * Revision 1.17  1999/06/04 09:44:35  wolff
- * fixed problem: reference to pci stuff when config_pci was off...
- * Thanks to Jorge Novo for noticing this.
- *
- * Revision 1.16  1999/06/02 08:30:15  wolff
- * added/removed the workaround for the DCD bug in the Firmware.
- * A bit more debugging code to locate that...
- *
- * Revision 1.15  1999/06/01 11:35:30  wolff
- * when DCD is left low (floating?), on TA's the firmware first tells us
- * that DCD is high, but after a short while suddenly comes to the
- * conclusion that it is low. All this would be fine, if it weren't that
- * Unix requires us to send a "hangup" signal in that case. This usually
- * all happens BEFORE the program has had a chance to ioctl the device
- * into clocal mode..
- *
- * Revision 1.14  1999/05/25 11:18:59  wolff
- * Added PCI-fix.
- * Added checks for return code of sx_sendcommand.
- * Don't issue "reconfig" if port isn't open yet. (bit us on TA modules...)
- *
- * Revision 1.13  1999/04/29 15:18:01  wolff
- * Fixed an "oops" that showed on SuSE 6.0 systems.
- * Activate DTR again after stty 0.
- *
- * Revision 1.12  1999/04/29 07:49:52  wolff
- * Improved "stty 0" handling a bit. (used to change baud to 9600 assuming
- *     the connection would be dropped anyway. That is not always the case,
- *     and confuses people).
- * Told the card to always monitor the modem signals.
- * Added support for dynamic  gs_debug adjustments.
- * Now tells the rest of the system the number of ports.
- *
- * Revision 1.11  1999/04/24 11:11:30  wolff
- * Fixed two stupid typos in the memory test.
- *
- * Revision 1.10  1999/04/24 10:53:39  wolff
- * Added some of Christian's suggestions.
- * Fixed an HW_COOK_IN bug (ISIG was not in I_OTHER. We used to trust the
- * card to send the signal to the process.....)
- *
- * Revision 1.9  1999/04/23 07:26:38  wolff
- * Included Christian Lademann's 2.0 compile-warning fixes and interrupt
- *    assignment redesign.
- * Cleanup of some other stuff.
- *
- * Revision 1.8  1999/04/16 13:05:30  wolff
- * fixed a DCD change unnoticed bug.
- *
- * Revision 1.7  1999/04/14 22:19:51  wolff
- * Fixed typo that showed up in 2.0.x builds (get_user instead of Get_user!)
- *
- * Revision 1.6  1999/04/13 18:40:20  wolff
- * changed misc-minor to 161, as assigned by HPA.
- *
- * Revision 1.5  1999/04/13 15:12:25  wolff
- * Fixed use-count leak when "hangup" occurred.
- * Added workaround for a stupid-PCIBIOS bug.
- *
- *
- * Revision 1.4  1999/04/01 22:47:40  wolff
- * Fixed < 1M linux-2.0 problem.
- * (vremap isn't compatible with ioremap in that case)
- *
- * Revision 1.3  1999/03/31 13:45:45  wolff
- * Firmware loading is now done through a separate IOCTL.
- *
- * Revision 1.2  1999/03/28 12:22:29  wolff
- * rcs cleanup
- *
- * Revision 1.1  1999/03/28 12:10:34  wolff
- * Readying for release on 2.0.x (sorry David, 1.01 becomes 1.1 for RCS). 
- *
- * Revision 0.12  1999/03/28 09:20:10  wolff
- * Fixed problem in 0.11, continueing cleanup.
- *
- * Revision 0.11  1999/03/28 08:46:44  wolff
- * cleanup. Not good.
- *
- * Revision 0.10  1999/03/28 08:09:43  wolff
- * Fixed loosing characters on close.
- *
- * Revision 0.9  1999/03/21 22:52:01  wolff
- * Ported back to 2.2.... (minor things)
- *
- * Revision 0.8  1999/03/21 22:40:33  wolff
- * Port to 2.0
- *
- * Revision 0.7  1999/03/21 19:06:34  wolff
- * Fixed hangup processing.
- *
- * Revision 0.6  1999/02/05 08:45:14  wolff
- * fixed real_raw problems. Inclusion into kernel imminent.
- *
- * Revision 0.5  1998/12/21 23:51:06  wolff
- * Snatched a nasty bug: sx_transmit_chars was getting re-entered, and it
- * shouldn't have. THATs why I want to have transmit interrupts even when
- * the buffer is empty.
- *
- * Revision 0.4  1998/12/17 09:34:46  wolff
- * PPP works. ioctl works. Basically works!
- *
- * Revision 0.3  1998/12/15 13:05:18  wolff
- * It works! Wow! Gotta start implementing IOCTL and stuff....
- *
- * Revision 0.2  1998/12/01 08:33:53  wolff
- * moved over to 2.1.130
- *
- * Revision 0.1  1998/11/03 21:23:51  wolff
- * Initial revision. Detects SX card.
- *
- * */
-
-#define SX_VERSION	1.33
-
-#include <linux/module.h>
-#include <linux/kdev_t.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/eisa.h>
-#include <linux/pci.h>
-#include <linux/slab.h>
-#include <linux/init.h>
-#include <linux/miscdevice.h>
-#include <linux/bitops.h>
-
-#include <asm/io.h>
-#include <asm/uaccess.h>
-
-/* The 3.0.0 version of sxboards/sxwindow.h  uses BYTE and WORD.... */
-#define BYTE u8
-#define WORD u16
-
-/* .... but the 3.0.4 version uses _u8 and _u16. */
-#define _u8 u8
-#define _u16 u16
-
-#include "sxboards.h"
-#include "sxwindow.h"
-
-#include <linux/generic_serial.h>
-#include "sx.h"
-
-/* I don't think that this driver can handle more than 256 ports on
-   one machine. You'll have to increase the number of boards in sx.h
-   if you want more than 4 boards.  */
-
-#ifndef PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8
-#define PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8 0x2000
-#endif
-
-/* Configurable options: 
-   (Don't be too sure that it'll work if you toggle them) */
-
-/* Am I paranoid or not ? ;-) */
-#undef SX_PARANOIA_CHECK
-
-/* 20 -> 2000 per second. The card should rate-limit interrupts at 100
-   Hz, but it is user configurable. I don't recommend going above 1000
-   Hz. The interrupt ratelimit might trigger if the interrupt is
-   shared with a very active other device. */
-#define IRQ_RATE_LIMIT 20
-
-/* Sharing interrupts is possible now. If the other device wants more
-   than 2000 interrupts per second, we'd gracefully decline further
-   interrupts. That's not what we want. On the other hand, if the
-   other device interrupts 2000 times a second, don't use the SX
-   interrupt. Use polling. */
-#undef IRQ_RATE_LIMIT
-
-#if 0
-/* Not implemented */
-/* 
- * The following defines are mostly for testing purposes. But if you need
- * some nice reporting in your syslog, you can define them also.
- */
-#define SX_REPORT_FIFO
-#define SX_REPORT_OVERRUN
-#endif
-
-/* Function prototypes */
-static void sx_disable_tx_interrupts(void *ptr);
-static void sx_enable_tx_interrupts(void *ptr);
-static void sx_disable_rx_interrupts(void *ptr);
-static void sx_enable_rx_interrupts(void *ptr);
-static int sx_carrier_raised(struct tty_port *port);
-static void sx_shutdown_port(void *ptr);
-static int sx_set_real_termios(void *ptr);
-static void sx_close(void *ptr);
-static int sx_chars_in_buffer(void *ptr);
-static int sx_init_board(struct sx_board *board);
-static int sx_init_portstructs(int nboards, int nports);
-static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
-						unsigned long arg);
-static int sx_init_drivers(void);
-
-static struct tty_driver *sx_driver;
-
-static DEFINE_MUTEX(sx_boards_lock);
-static struct sx_board boards[SX_NBOARDS];
-static struct sx_port *sx_ports;
-static int sx_initialized;
-static int sx_nports;
-static int sx_debug;
-
-/* You can have the driver poll your card. 
-    - Set sx_poll to 1 to poll every timer tick (10ms on Intel). 
-      This is used when the card cannot use an interrupt for some reason.
-
-    - set sx_slowpoll to 100 to do an extra poll once a second (on Intel). If 
-      the driver misses an interrupt (report this if it DOES happen to you!)
-      everything will continue to work.... 
- */
-static int sx_poll = 1;
-static int sx_slowpoll;
-
-/* The card limits the number of interrupts per second. 
-   At 115k2 "100" should be sufficient. 
-   If you're using higher baudrates, you can increase this...
- */
-
-static int sx_maxints = 100;
-
-#ifdef CONFIG_ISA
-
-/* These are the only open spaces in my computer. Yours may have more
-   or less.... -- REW 
-   duh: Card at 0xa0000 is possible on HP Netserver?? -- pvdl
-*/
-static int sx_probe_addrs[] = {
-	0xc0000, 0xd0000, 0xe0000,
-	0xc8000, 0xd8000, 0xe8000
-};
-static int si_probe_addrs[] = {
-	0xc0000, 0xd0000, 0xe0000,
-	0xc8000, 0xd8000, 0xe8000, 0xa0000
-};
-static int si1_probe_addrs[] = {
-	0xd0000
-};
-
-#define NR_SX_ADDRS ARRAY_SIZE(sx_probe_addrs)
-#define NR_SI_ADDRS ARRAY_SIZE(si_probe_addrs)
-#define NR_SI1_ADDRS ARRAY_SIZE(si1_probe_addrs)
-
-module_param_array(sx_probe_addrs, int, NULL, 0);
-module_param_array(si_probe_addrs, int, NULL, 0);
-#endif
-
-/* Set the mask to all-ones. This alas, only supports 32 interrupts. 
-   Some architectures may need more. */
-static int sx_irqmask = -1;
-
-module_param(sx_poll, int, 0);
-module_param(sx_slowpoll, int, 0);
-module_param(sx_maxints, int, 0);
-module_param(sx_debug, int, 0);
-module_param(sx_irqmask, int, 0);
-
-MODULE_LICENSE("GPL");
-
-static struct real_driver sx_real_driver = {
-	sx_disable_tx_interrupts,
-	sx_enable_tx_interrupts,
-	sx_disable_rx_interrupts,
-	sx_enable_rx_interrupts,
-	sx_shutdown_port,
-	sx_set_real_termios,
-	sx_chars_in_buffer,
-	sx_close,
-};
-
-/* 
-   This driver can spew a whole lot of debugging output at you. If you
-   need maximum performance, you should disable the DEBUG define. To
-   aid in debugging in the field, I'm leaving the compile-time debug
-   features enabled, and disable them "runtime". That allows me to
-   instruct people with problems to enable debugging without requiring
-   them to recompile... 
-*/
-#define DEBUG
-
-#ifdef DEBUG
-#define sx_dprintk(f, str...)	if (sx_debug & f) printk (str)
-#else
-#define sx_dprintk(f, str...)	/* nothing */
-#endif
-
-#define func_enter()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s\n",__func__)
-#define func_exit()	sx_dprintk(SX_DEBUG_FLOW, "sx: exit  %s\n",__func__)
-
-#define func_enter2()	sx_dprintk(SX_DEBUG_FLOW, "sx: enter %s (port %d)\n", \
-				__func__, port->line)
-
-/* 
- *  Firmware loader driver specific routines
- *
- */
-
-static const struct file_operations sx_fw_fops = {
-	.owner = THIS_MODULE,
-	.unlocked_ioctl = sx_fw_ioctl,
-	.llseek = noop_llseek,
-};
-
-static struct miscdevice sx_fw_device = {
-	SXCTL_MISC_MINOR, "sxctl", &sx_fw_fops
-};
-
-#ifdef SX_PARANOIA_CHECK
-
-/* This doesn't work. Who's paranoid around here? Not me! */
-
-static inline int sx_paranoia_check(struct sx_port const *port,
-				    char *name, const char *routine)
-{
-	static const char *badmagic = KERN_ERR "sx: Warning: bad sx port magic "
-			"number for device %s in %s\n";
-	static const char *badinfo = KERN_ERR "sx: Warning: null sx port for "
-			"device %s in %s\n";
-
-	if (!port) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (port->magic != SX_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-
-	return 0;
-}
-#else
-#define sx_paranoia_check(a,b,c) 0
-#endif
-
-/* The timeouts. First try 30 times as fast as possible. Then give
-   the card some time to breathe between accesses. (Otherwise the
-   processor on the card might not be able to access its OWN bus... */
-
-#define TIMEOUT_1 30
-#define TIMEOUT_2 1000000
-
-#ifdef DEBUG
-static void my_hd_io(void __iomem *p, int len)
-{
-	int i, j, ch;
-	unsigned char __iomem *addr = p;
-
-	for (i = 0; i < len; i += 16) {
-		printk("%p ", addr + i);
-		for (j = 0; j < 16; j++) {
-			printk("%02x %s", readb(addr + j + i),
-					(j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = readb(addr + j + i);
-			printk("%c", (ch < 0x20) ? '.' :
-					((ch > 0x7f) ? '.' : ch));
-		}
-		printk("\n");
-	}
-}
-static void my_hd(void *p, int len)
-{
-	int i, j, ch;
-	unsigned char *addr = p;
-
-	for (i = 0; i < len; i += 16) {
-		printk("%p ", addr + i);
-		for (j = 0; j < 16; j++) {
-			printk("%02x %s", addr[j + i], (j == 7) ? " " : "");
-		}
-		for (j = 0; j < 16; j++) {
-			ch = addr[j + i];
-			printk("%c", (ch < 0x20) ? '.' :
-					((ch > 0x7f) ? '.' : ch));
-		}
-		printk("\n");
-	}
-}
-#endif
-
-/* This needs redoing for Alpha -- REW -- Done. */
-
-static inline void write_sx_byte(struct sx_board *board, int offset, u8 byte)
-{
-	writeb(byte, board->base + offset);
-}
-
-static inline u8 read_sx_byte(struct sx_board *board, int offset)
-{
-	return readb(board->base + offset);
-}
-
-static inline void write_sx_word(struct sx_board *board, int offset, u16 word)
-{
-	writew(word, board->base + offset);
-}
-
-static inline u16 read_sx_word(struct sx_board *board, int offset)
-{
-	return readw(board->base + offset);
-}
-
-static int sx_busy_wait_eq(struct sx_board *board,
-		int offset, int mask, int correctval)
-{
-	int i;
-
-	func_enter();
-
-	for (i = 0; i < TIMEOUT_1; i++)
-		if ((read_sx_byte(board, offset) & mask) == correctval) {
-			func_exit();
-			return 1;
-		}
-
-	for (i = 0; i < TIMEOUT_2; i++) {
-		if ((read_sx_byte(board, offset) & mask) == correctval) {
-			func_exit();
-			return 1;
-		}
-		udelay(1);
-	}
-
-	func_exit();
-	return 0;
-}
-
-static int sx_busy_wait_neq(struct sx_board *board,
-		int offset, int mask, int badval)
-{
-	int i;
-
-	func_enter();
-
-	for (i = 0; i < TIMEOUT_1; i++)
-		if ((read_sx_byte(board, offset) & mask) != badval) {
-			func_exit();
-			return 1;
-		}
-
-	for (i = 0; i < TIMEOUT_2; i++) {
-		if ((read_sx_byte(board, offset) & mask) != badval) {
-			func_exit();
-			return 1;
-		}
-		udelay(1);
-	}
-
-	func_exit();
-	return 0;
-}
-
-/* 5.6.4 of 6210028 r2.3 */
-static int sx_reset(struct sx_board *board)
-{
-	func_enter();
-
-	if (IS_SX_BOARD(board)) {
-
-		write_sx_byte(board, SX_CONFIG, 0);
-		write_sx_byte(board, SX_RESET, 1); /* Value doesn't matter */
-
-		if (!sx_busy_wait_eq(board, SX_RESET_STATUS, 1, 0)) {
-			printk(KERN_INFO "sx: Card doesn't respond to "
-					"reset...\n");
-			return 0;
-		}
-	} else if (IS_EISA_BOARD(board)) {
-		outb(board->irq << 4, board->eisa_base + 0xc02);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_RESET, 0);	/*value doesn't matter*/
-	} else {
-		/* Gory details of the SI/ISA board */
-		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_SET);
-		write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_CLEAR);
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_CLEAR);
-		write_sx_byte(board, SI2_ISA_IRQSET, SI2_ISA_IRQSET_CLEAR);
-	}
-
-	func_exit();
-	return 1;
-}
-
-/* This doesn't work on machines where "NULL" isn't 0 */
-/* If you have one of those, someone will need to write 
-   the equivalent of this, which will amount to about 3 lines. I don't
-   want to complicate this right now. -- REW
-   (See, I do write comments every now and then :-) */
-#define OFFSETOF(strct, elem)	((long)&(((struct strct *)NULL)->elem))
-
-#define CHAN_OFFSET(port,elem)	(port->ch_base + OFFSETOF (_SXCHANNEL, elem))
-#define MODU_OFFSET(board,addr,elem)	(addr + OFFSETOF (_SXMODULE, elem))
-#define  BRD_OFFSET(board,elem)	(OFFSETOF (_SXCARD, elem))
-
-#define sx_write_channel_byte(port, elem, val) \
-	write_sx_byte (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_byte(port, elem) \
-	read_sx_byte (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_channel_word(port, elem, val) \
-	write_sx_word (port->board, CHAN_OFFSET (port, elem), val)
-
-#define sx_read_channel_word(port, elem) \
-	read_sx_word (port->board, CHAN_OFFSET (port, elem))
-
-#define sx_write_module_byte(board, addr, elem, val) \
-	write_sx_byte (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_byte(board, addr, elem) \
-	read_sx_byte (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_module_word(board, addr, elem, val) \
-	write_sx_word (board, MODU_OFFSET (board, addr, elem), val)
-
-#define sx_read_module_word(board, addr, elem) \
-	read_sx_word (board, MODU_OFFSET (board, addr, elem))
-
-#define sx_write_board_byte(board, elem, val) \
-	write_sx_byte (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_byte(board, elem) \
-	read_sx_byte (board, BRD_OFFSET (board, elem))
-
-#define sx_write_board_word(board, elem, val) \
-	write_sx_word (board, BRD_OFFSET (board, elem), val)
-
-#define sx_read_board_word(board, elem) \
-	read_sx_word (board, BRD_OFFSET (board, elem))
-
-static int sx_start_board(struct sx_board *board)
-{
-	if (IS_SX_BOARD(board)) {
-		write_sx_byte(board, SX_CONFIG, SX_CONF_BUSEN);
-	} else if (IS_EISA_BOARD(board)) {
-		write_sx_byte(board, SI2_EISA_OFF, SI2_EISA_VAL);
-		outb((board->irq << 4) | 4, board->eisa_base + 0xc02);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_RESET_CLEAR, 0);
-		write_sx_byte(board, SI1_ISA_INTCL, 0);
-	} else {
-		/* Don't bug me about the clear_set. 
-		   I haven't the foggiest idea what it's about -- REW */
-		write_sx_byte(board, SI2_ISA_RESET, SI2_ISA_RESET_CLEAR);
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
-	}
-	return 1;
-}
-
-#define SX_IRQ_REG_VAL(board) \
-	((board->flags & SX_ISA_BOARD) ? (board->irq << 4) : 0)
-
-/* Note. The SX register is write-only. Therefore, we have to enable the
-   bus too. This is a no-op, if you don't mess with this driver... */
-static int sx_start_interrupts(struct sx_board *board)
-{
-
-	/* Don't call this with board->irq == 0 */
-
-	if (IS_SX_BOARD(board)) {
-		write_sx_byte(board, SX_CONFIG, SX_IRQ_REG_VAL(board) |
-				SX_CONF_BUSEN | SX_CONF_HOSTIRQ);
-	} else if (IS_EISA_BOARD(board)) {
-		inb(board->eisa_base + 0xc03);
-	} else if (IS_SI1_BOARD(board)) {
-		write_sx_byte(board, SI1_ISA_INTCL, 0);
-		write_sx_byte(board, SI1_ISA_INTCL_CLEAR, 0);
-	} else {
-		switch (board->irq) {
-		case 11:
-			write_sx_byte(board, SI2_ISA_IRQ11, SI2_ISA_IRQ11_SET);
-			break;
-		case 12:
-			write_sx_byte(board, SI2_ISA_IRQ12, SI2_ISA_IRQ12_SET);
-			break;
-		case 15:
-			write_sx_byte(board, SI2_ISA_IRQ15, SI2_ISA_IRQ15_SET);
-			break;
-		default:
-			printk(KERN_INFO "sx: SI/XIO card doesn't support "
-					"interrupt %d.\n", board->irq);
-			return 0;
-		}
-		write_sx_byte(board, SI2_ISA_INTCLEAR, SI2_ISA_INTCLEAR_SET);
-	}
-
-	return 1;
-}
-
-static int sx_send_command(struct sx_port *port,
-		int command, int mask, int newstat)
-{
-	func_enter2();
-	write_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat), command);
-	func_exit();
-	return sx_busy_wait_eq(port->board, CHAN_OFFSET(port, hi_hstat), mask,
-			newstat);
-}
-
-static char *mod_type_s(int module_type)
-{
-	switch (module_type) {
-	case TA4:
-		return "TA4";
-	case TA8:
-		return "TA8";
-	case TA4_ASIC:
-		return "TA4_ASIC";
-	case TA8_ASIC:
-		return "TA8_ASIC";
-	case MTA_CD1400:
-		return "MTA_CD1400";
-	case SXDC:
-		return "SXDC";
-	default:
-		return "Unknown/invalid";
-	}
-}
-
-static char *pan_type_s(int pan_type)
-{
-	switch (pan_type) {
-	case MOD_RS232DB25:
-		return "MOD_RS232DB25";
-	case MOD_RS232RJ45:
-		return "MOD_RS232RJ45";
-	case MOD_RS422DB25:
-		return "MOD_RS422DB25";
-	case MOD_PARALLEL:
-		return "MOD_PARALLEL";
-	case MOD_2_RS232DB25:
-		return "MOD_2_RS232DB25";
-	case MOD_2_RS232RJ45:
-		return "MOD_2_RS232RJ45";
-	case MOD_2_RS422DB25:
-		return "MOD_2_RS422DB25";
-	case MOD_RS232DB25MALE:
-		return "MOD_RS232DB25MALE";
-	case MOD_2_PARALLEL:
-		return "MOD_2_PARALLEL";
-	case MOD_BLANK:
-		return "empty";
-	default:
-		return "invalid";
-	}
-}
-
-static int mod_compat_type(int module_type)
-{
-	return module_type >> 4;
-}
-
-static void sx_reconfigure_port(struct sx_port *port)
-{
-	if (sx_read_channel_byte(port, hi_hstat) == HS_IDLE_OPEN) {
-		if (sx_send_command(port, HS_CONFIG, -1, HS_IDLE_OPEN) != 1) {
-			printk(KERN_WARNING "sx: Sent reconfigure command, but "
-					"card didn't react.\n");
-		}
-	} else {
-		sx_dprintk(SX_DEBUG_TERMIOS, "sx: Not sending reconfigure: "
-				"port isn't open (%02x).\n",
-				sx_read_channel_byte(port, hi_hstat));
-	}
-}
-
-static void sx_setsignals(struct sx_port *port, int dtr, int rts)
-{
-	int t;
-	func_enter2();
-
-	t = sx_read_channel_byte(port, hi_op);
-	if (dtr >= 0)
-		t = dtr ? (t | OP_DTR) : (t & ~OP_DTR);
-	if (rts >= 0)
-		t = rts ? (t | OP_RTS) : (t & ~OP_RTS);
-	sx_write_channel_byte(port, hi_op, t);
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "setsignals: %d/%d\n", dtr, rts);
-
-	func_exit();
-}
-
-static int sx_getsignals(struct sx_port *port)
-{
-	int i_stat, o_stat;
-
-	o_stat = sx_read_channel_byte(port, hi_op);
-	i_stat = sx_read_channel_byte(port, hi_ip);
-
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "getsignals: %d/%d  (%d/%d) "
-			"%02x/%02x\n",
-			(o_stat & OP_DTR) != 0, (o_stat & OP_RTS) != 0,
-			port->c_dcd, tty_port_carrier_raised(&port->gs.port),
-			sx_read_channel_byte(port, hi_ip),
-			sx_read_channel_byte(port, hi_state));
-
-	return (((o_stat & OP_DTR) ? TIOCM_DTR : 0) |
-		((o_stat & OP_RTS) ? TIOCM_RTS : 0) |
-		((i_stat & IP_CTS) ? TIOCM_CTS : 0) |
-		((i_stat & IP_DCD) ? TIOCM_CAR : 0) |
-		((i_stat & IP_DSR) ? TIOCM_DSR : 0) |
-		((i_stat & IP_RI) ? TIOCM_RNG : 0));
-}
-
-static void sx_set_baud(struct sx_port *port)
-{
-	int t;
-
-	if (port->board->ta_type == MOD_SXDC) {
-		switch (port->gs.baud) {
-			/* Save some typing work... */
-#define e(x) case x: t = BAUD_ ## x; break
-			e(50);
-			e(75);
-			e(110);
-			e(150);
-			e(200);
-			e(300);
-			e(600);
-			e(1200);
-			e(1800);
-			e(2000);
-			e(2400);
-			e(4800);
-			e(7200);
-			e(9600);
-			e(14400);
-			e(19200);
-			e(28800);
-			e(38400);
-			e(56000);
-			e(57600);
-			e(64000);
-			e(76800);
-			e(115200);
-			e(128000);
-			e(150000);
-			e(230400);
-			e(256000);
-			e(460800);
-			e(921600);
-		case 134:
-			t = BAUD_134_5;
-			break;
-		case 0:
-			t = -1;
-			break;
-		default:
-			/* Can I return "invalid"? */
-			t = BAUD_9600;
-			printk(KERN_INFO "sx: unsupported baud rate: %d.\n",
-					port->gs.baud);
-			break;
-		}
-#undef e
-		if (t > 0) {
-/* The baud rate is not set to 0, so we're enabeling DTR... -- REW */
-			sx_setsignals(port, 1, -1);
-			/* XXX This is not TA & MTA compatible */
-			sx_write_channel_byte(port, hi_csr, 0xff);
-
-			sx_write_channel_byte(port, hi_txbaud, t);
-			sx_write_channel_byte(port, hi_rxbaud, t);
-		} else {
-			sx_setsignals(port, 0, -1);
-		}
-	} else {
-		switch (port->gs.baud) {
-#define e(x) case x: t = CSR_ ## x; break
-			e(75);
-			e(150);
-			e(300);
-			e(600);
-			e(1200);
-			e(2400);
-			e(4800);
-			e(1800);
-			e(9600);
-			e(19200);
-			e(57600);
-			e(38400);
-/* TA supports 110, but not 115200, MTA supports 115200, but not 110 */
-		case 110:
-			if (port->board->ta_type == MOD_TA) {
-				t = CSR_110;
-				break;
-			} else {
-				t = CSR_9600;
-				printk(KERN_INFO "sx: Unsupported baud rate: "
-						"%d.\n", port->gs.baud);
-				break;
-			}
-		case 115200:
-			if (port->board->ta_type == MOD_TA) {
-				t = CSR_9600;
-				printk(KERN_INFO "sx: Unsupported baud rate: "
-						"%d.\n", port->gs.baud);
-				break;
-			} else {
-				t = CSR_110;
-				break;
-			}
-		case 0:
-			t = -1;
-			break;
-		default:
-			t = CSR_9600;
-			printk(KERN_INFO "sx: Unsupported baud rate: %d.\n",
-					port->gs.baud);
-			break;
-		}
-#undef e
-		if (t >= 0) {
-			sx_setsignals(port, 1, -1);
-			sx_write_channel_byte(port, hi_csr, t * 0x11);
-		} else {
-			sx_setsignals(port, 0, -1);
-		}
-	}
-}
-
-/* Simon Allen's version of this routine was 225 lines long. 85 is a lot
-   better. -- REW */
-
-static int sx_set_real_termios(void *ptr)
-{
-	struct sx_port *port = ptr;
-
-	func_enter2();
-
-	if (!port->gs.port.tty)
-		return 0;
-
-	/* What is this doing here? -- REW
-	   Ha! figured it out. It is to allow you to get DTR active again
-	   if you've dropped it with stty 0. Moved to set_baud, where it
-	   belongs (next to the drop dtr if baud == 0) -- REW */
-	/* sx_setsignals (port, 1, -1); */
-
-	sx_set_baud(port);
-
-#define CFLAG port->gs.port.tty->termios->c_cflag
-	sx_write_channel_byte(port, hi_mr1,
-			(C_PARENB(port->gs.port.tty) ? MR1_WITH : MR1_NONE) |
-			(C_PARODD(port->gs.port.tty) ? MR1_ODD : MR1_EVEN) |
-			(C_CRTSCTS(port->gs.port.tty) ? MR1_RTS_RXFLOW : 0) |
-			(((CFLAG & CSIZE) == CS8) ? MR1_8_BITS : 0) |
-			(((CFLAG & CSIZE) == CS7) ? MR1_7_BITS : 0) |
-			(((CFLAG & CSIZE) == CS6) ? MR1_6_BITS : 0) |
-			(((CFLAG & CSIZE) == CS5) ? MR1_5_BITS : 0));
-
-	sx_write_channel_byte(port, hi_mr2,
-			(C_CRTSCTS(port->gs.port.tty) ? MR2_CTS_TXFLOW : 0) |
-			(C_CSTOPB(port->gs.port.tty) ? MR2_2_STOP :
-			MR2_1_STOP));
-
-	switch (CFLAG & CSIZE) {
-	case CS8:
-		sx_write_channel_byte(port, hi_mask, 0xff);
-		break;
-	case CS7:
-		sx_write_channel_byte(port, hi_mask, 0x7f);
-		break;
-	case CS6:
-		sx_write_channel_byte(port, hi_mask, 0x3f);
-		break;
-	case CS5:
-		sx_write_channel_byte(port, hi_mask, 0x1f);
-		break;
-	default:
-		printk(KERN_INFO "sx: Invalid wordsize: %u\n",
-			(unsigned int)CFLAG & CSIZE);
-		break;
-	}
-
-	sx_write_channel_byte(port, hi_prtcl,
-			(I_IXON(port->gs.port.tty) ? SP_TXEN : 0) |
-			(I_IXOFF(port->gs.port.tty) ? SP_RXEN : 0) |
-			(I_IXANY(port->gs.port.tty) ? SP_TANY : 0) | SP_DCEN);
-
-	sx_write_channel_byte(port, hi_break,
-			(I_IGNBRK(port->gs.port.tty) ? BR_IGN : 0 |
-			I_BRKINT(port->gs.port.tty) ? BR_INT : 0));
-
-	sx_write_channel_byte(port, hi_txon, START_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_rxon, START_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_txoff, STOP_CHAR(port->gs.port.tty));
-	sx_write_channel_byte(port, hi_rxoff, STOP_CHAR(port->gs.port.tty));
-
-	sx_reconfigure_port(port);
-
-	/* Tell line discipline whether we will do input cooking */
-	if (I_OTHER(port->gs.port.tty)) {
-		clear_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
-	} else {
-		set_bit(TTY_HW_COOK_IN, &port->gs.port.tty->flags);
-	}
-	sx_dprintk(SX_DEBUG_TERMIOS, "iflags: %x(%d) ",
-			(unsigned int)port->gs.port.tty->termios->c_iflag,
-			I_OTHER(port->gs.port.tty));
-
-/* Tell line discipline whether we will do output cooking.
- * If OPOST is set and no other output flags are set then we can do output
- * processing.  Even if only *one* other flag in the O_OTHER group is set
- * we do cooking in software.
- */
-	if (O_OPOST(port->gs.port.tty) && !O_OTHER(port->gs.port.tty)) {
-		set_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
-	} else {
-		clear_bit(TTY_HW_COOK_OUT, &port->gs.port.tty->flags);
-	}
-	sx_dprintk(SX_DEBUG_TERMIOS, "oflags: %x(%d)\n",
-			(unsigned int)port->gs.port.tty->termios->c_oflag,
-			O_OTHER(port->gs.port.tty));
-	/* port->c_dcd = sx_get_CD (port); */
-	func_exit();
-	return 0;
-}
-
-/* ********************************************************************** *
- *                   the interrupt related routines                       *
- * ********************************************************************** */
-
-/* Note:
-   Other drivers use the macro "MIN" to calculate how much to copy.
-   This has the disadvantage that it will evaluate parts twice. That's
-   expensive when it's IO (and the compiler cannot optimize those away!).
-   Moreover, I'm not sure that you're race-free. 
-
-   I assign a value, and then only allow the value to decrease. This
-   is always safe. This makes the code a few lines longer, and you
-   know I'm dead against that, but I think it is required in this
-   case.  */
-
-static void sx_transmit_chars(struct sx_port *port)
-{
-	int c;
-	int tx_ip;
-	int txroom;
-
-	func_enter2();
-	sx_dprintk(SX_DEBUG_TRANSMIT, "Port %p: transmit %d chars\n",
-			port, port->gs.xmit_cnt);
-
-	if (test_and_set_bit(SX_PORT_TRANSMIT_LOCK, &port->locks)) {
-		return;
-	}
-
-	while (1) {
-		c = port->gs.xmit_cnt;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, "Copying %d ", c);
-		tx_ip = sx_read_channel_byte(port, hi_txipos);
-
-		/* Took me 5 minutes to deduce this formula. 
-		   Luckily it is literally in the manual in section 6.5.4.3.5 */
-		txroom = (sx_read_channel_byte(port, hi_txopos) - tx_ip - 1) &
-				0xff;
-
-		/* Don't copy more bytes than there is room for in the buffer */
-		if (c > txroom)
-			c = txroom;
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, txroom);
-
-		/* Don't copy past the end of the hardware transmit buffer */
-		if (c > 0x100 - tx_ip)
-			c = 0x100 - tx_ip;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%d) ", c, 0x100 - tx_ip);
-
-		/* Don't copy pas the end of the source buffer */
-		if (c > SERIAL_XMIT_SIZE - port->gs.xmit_tail)
-			c = SERIAL_XMIT_SIZE - port->gs.xmit_tail;
-
-		sx_dprintk(SX_DEBUG_TRANSMIT, " %d(%ld) \n",
-				c, SERIAL_XMIT_SIZE - port->gs.xmit_tail);
-
-		/* If for one reason or another, we can't copy more data, we're
-		   done! */
-		if (c == 0)
-			break;
-
-		memcpy_toio(port->board->base + CHAN_OFFSET(port, hi_txbuf) +
-			tx_ip, port->gs.xmit_buf + port->gs.xmit_tail, c);
-
-		/* Update the pointer in the card */
-		sx_write_channel_byte(port, hi_txipos, (tx_ip + c) & 0xff);
-
-		/* Update the kernel buffer end */
-		port->gs.xmit_tail = (port->gs.xmit_tail + c) &
-				(SERIAL_XMIT_SIZE - 1);
-
-		/* This one last. (this is essential)
-		   It would allow others to start putting more data into the
-		   buffer! */
-		port->gs.xmit_cnt -= c;
-	}
-
-	if (port->gs.xmit_cnt == 0) {
-		sx_disable_tx_interrupts(port);
-	}
-
-	if ((port->gs.xmit_cnt <= port->gs.wakeup_chars) && port->gs.port.tty) {
-		tty_wakeup(port->gs.port.tty);
-		sx_dprintk(SX_DEBUG_TRANSMIT, "Waking up.... ldisc (%d)....\n",
-				port->gs.wakeup_chars);
-	}
-
-	clear_bit(SX_PORT_TRANSMIT_LOCK, &port->locks);
-	func_exit();
-}
-
-/* Note the symmetry between receiving chars and transmitting them!
-   Note: The kernel should have implemented both a receive buffer and
-   a transmit buffer. */
-
-/* Inlined: Called only once. Remove the inline when you add another call */
-static inline void sx_receive_chars(struct sx_port *port)
-{
-	int c;
-	int rx_op;
-	struct tty_struct *tty;
-	int copied = 0;
-	unsigned char *rp;
-
-	func_enter2();
-	tty = port->gs.port.tty;
-	while (1) {
-		rx_op = sx_read_channel_byte(port, hi_rxopos);
-		c = (sx_read_channel_byte(port, hi_rxipos) - rx_op) & 0xff;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "rxop=%d, c = %d.\n", rx_op, c);
-
-		/* Don't copy past the end of the hardware receive buffer */
-		if (rx_op + c > 0x100)
-			c = 0x100 - rx_op;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
-		/* Don't copy more bytes than there is room for in the buffer */
-
-		c = tty_prepare_flip_string(tty, &rp, c);
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "c = %d.\n", c);
-
-		/* If for one reason or another, we can't copy more data, we're done! */
-		if (c == 0)
-			break;
-
-		sx_dprintk(SX_DEBUG_RECEIVE, "Copying over %d chars. First is "
-				"%d at %lx\n", c, read_sx_byte(port->board,
-					CHAN_OFFSET(port, hi_rxbuf) + rx_op),
-				CHAN_OFFSET(port, hi_rxbuf));
-		memcpy_fromio(rp, port->board->base +
-				CHAN_OFFSET(port, hi_rxbuf) + rx_op, c);
-
-		/* This one last. ( Not essential.)
-		   It allows the card to start putting more data into the
-		   buffer!
-		   Update the pointer in the card */
-		sx_write_channel_byte(port, hi_rxopos, (rx_op + c) & 0xff);
-
-		copied += c;
-	}
-	if (copied) {
-		struct timeval tv;
-
-		do_gettimeofday(&tv);
-		sx_dprintk(SX_DEBUG_RECEIVE, "pushing flipq port %d (%3d "
-				"chars): %d.%06d  (%d/%d)\n", port->line,
-				copied, (int)(tv.tv_sec % 60), (int)tv.tv_usec,
-				tty->raw, tty->real_raw);
-
-		/* Tell the rest of the system the news. Great news. New
-		   characters! */
-		tty_flip_buffer_push(tty);
-		/*    tty_schedule_flip (tty); */
-	}
-
-	func_exit();
-}
-
-/* Inlined: it is called only once. Remove the inline if you add another 
-   call */
-static inline void sx_check_modem_signals(struct sx_port *port)
-{
-	int hi_state;
-	int c_dcd;
-
-	hi_state = sx_read_channel_byte(port, hi_state);
-	sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Checking modem signals (%d/%d)\n",
-			port->c_dcd, tty_port_carrier_raised(&port->gs.port));
-
-	if (hi_state & ST_BREAK) {
-		hi_state &= ~ST_BREAK;
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a break.\n");
-		sx_write_channel_byte(port, hi_state, hi_state);
-		gs_got_break(&port->gs);
-	}
-	if (hi_state & ST_DCD) {
-		hi_state &= ~ST_DCD;
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "got a DCD change.\n");
-		sx_write_channel_byte(port, hi_state, hi_state);
-		c_dcd = tty_port_carrier_raised(&port->gs.port);
-		sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD is now %d\n", c_dcd);
-		if (c_dcd != port->c_dcd) {
-			port->c_dcd = c_dcd;
-			if (tty_port_carrier_raised(&port->gs.port)) {
-				/* DCD went UP */
-				if ((sx_read_channel_byte(port, hi_hstat) !=
-						HS_IDLE_CLOSED) &&
-						!(port->gs.port.tty->termios->
-							c_cflag & CLOCAL)) {
-					/* Are we blocking in open? */
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"active, unblocking open\n");
-					wake_up_interruptible(&port->gs.port.
-							open_wait);
-				} else {
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"raised. Ignoring.\n");
-				}
-			} else {
-				/* DCD went down! */
-				if (!(port->gs.port.tty->termios->c_cflag & CLOCAL)){
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"dropped. hanging up....\n");
-					tty_hangup(port->gs.port.tty);
-				} else {
-					sx_dprintk(SX_DEBUG_MODEMSIGNALS, "DCD "
-						"dropped. ignoring.\n");
-				}
-			}
-		} else {
-			sx_dprintk(SX_DEBUG_MODEMSIGNALS, "Hmmm. card told us "
-				"DCD changed, but it didn't.\n");
-		}
-	}
-}
-
-/* This is what an interrupt routine should look like. 
- * Small, elegant, clear.
- */
-
-static irqreturn_t sx_interrupt(int irq, void *ptr)
-{
-	struct sx_board *board = ptr;
-	struct sx_port *port;
-	int i;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_FLOW, "sx: enter sx_interrupt (%d/%d)\n", irq,
-			board->irq);
-
-	/* AAargh! The order in which to do these things is essential and
-	   not trivial. 
-
-	   - Rate limit goes before "recursive". Otherwise a series of
-	   recursive calls will hang the machine in the interrupt routine.
-
-	   - hardware twiddling goes before "recursive". Otherwise when we
-	   poll the card, and a recursive interrupt happens, we won't
-	   ack the card, so it might keep on interrupting us. (especially
-	   level sensitive interrupt systems like PCI).
-
-	   - Rate limit goes before hardware twiddling. Otherwise we won't
-	   catch a card that has gone bonkers.
-
-	   - The "initialized" test goes after the hardware twiddling. Otherwise
-	   the card will stick us in the interrupt routine again.
-
-	   - The initialized test goes before recursive. 
-	 */
-
-#ifdef IRQ_RATE_LIMIT
-	/* Aaargh! I'm ashamed. This costs more lines-of-code than the
-	   actual interrupt routine!. (Well, used to when I wrote that
-	   comment) */
-	{
-		static int lastjif;
-		static int nintr = 0;
-
-		if (lastjif == jiffies) {
-			if (++nintr > IRQ_RATE_LIMIT) {
-				free_irq(board->irq, board);
-				printk(KERN_ERR "sx: Too many interrupts. "
-						"Turning off interrupt %d.\n",
-						board->irq);
-			}
-		} else {
-			lastjif = jiffies;
-			nintr = 0;
-		}
-	}
-#endif
-
-	if (board->irq == irq) {
-		/* Tell the card we've noticed the interrupt. */
-
-		sx_write_board_word(board, cc_int_pending, 0);
-		if (IS_SX_BOARD(board)) {
-			write_sx_byte(board, SX_RESET_IRQ, 1);
-		} else if (IS_EISA_BOARD(board)) {
-			inb(board->eisa_base + 0xc03);
-			write_sx_word(board, 8, 0);
-		} else {
-			write_sx_byte(board, SI2_ISA_INTCLEAR,
-					SI2_ISA_INTCLEAR_CLEAR);
-			write_sx_byte(board, SI2_ISA_INTCLEAR,
-					SI2_ISA_INTCLEAR_SET);
-		}
-	}
-
-	if (!sx_initialized)
-		return IRQ_HANDLED;
-	if (!(board->flags & SX_BOARD_INITIALIZED))
-		return IRQ_HANDLED;
-
-	if (test_and_set_bit(SX_BOARD_INTR_LOCK, &board->locks)) {
-		printk(KERN_ERR "Recursive interrupt! (%d)\n", board->irq);
-		return IRQ_HANDLED;
-	}
-
-	for (i = 0; i < board->nports; i++) {
-		port = &board->ports[i];
-		if (port->gs.port.flags & GS_ACTIVE) {
-			if (sx_read_channel_byte(port, hi_state)) {
-				sx_dprintk(SX_DEBUG_INTERRUPTS, "Port %d: "
-						"modem signal change?... \n",i);
-				sx_check_modem_signals(port);
-			}
-			if (port->gs.xmit_cnt) {
-				sx_transmit_chars(port);
-			}
-			if (!(port->gs.port.flags & SX_RX_THROTTLE)) {
-				sx_receive_chars(port);
-			}
-		}
-	}
-
-	clear_bit(SX_BOARD_INTR_LOCK, &board->locks);
-
-	sx_dprintk(SX_DEBUG_FLOW, "sx: exit sx_interrupt (%d/%d)\n", irq,
-			board->irq);
-	func_exit();
-	return IRQ_HANDLED;
-}
-
-static void sx_pollfunc(unsigned long data)
-{
-	struct sx_board *board = (struct sx_board *)data;
-
-	func_enter();
-
-	sx_interrupt(0, board);
-
-	mod_timer(&board->timer, jiffies + sx_poll);
-	func_exit();
-}
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *              interface with the generic_serial driver                  *
- * ********************************************************************** */
-
-/* Ehhm. I don't know how to fiddle with interrupts on the SX card. --REW */
-/* Hmm. Ok I figured it out. You don't.  */
-
-static void sx_disable_tx_interrupts(void *ptr)
-{
-	struct sx_port *port = ptr;
-	func_enter2();
-
-	port->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-static void sx_enable_tx_interrupts(void *ptr)
-{
-	struct sx_port *port = ptr;
-	int data_in_buffer;
-	func_enter2();
-
-	/* First transmit the characters that we're supposed to */
-	sx_transmit_chars(port);
-
-	/* The sx card will never interrupt us if we don't fill the buffer
-	   past 25%. So we keep considering interrupts off if that's the case. */
-	data_in_buffer = (sx_read_channel_byte(port, hi_txipos) -
-			  sx_read_channel_byte(port, hi_txopos)) & 0xff;
-
-	/* XXX Must be "HIGH_WATER" for SI card according to doc. */
-	if (data_in_buffer < LOW_WATER)
-		port->gs.port.flags &= ~GS_TX_INTEN;
-
-	func_exit();
-}
-
-static void sx_disable_rx_interrupts(void *ptr)
-{
-	/*  struct sx_port *port = ptr; */
-	func_enter();
-
-	func_exit();
-}
-
-static void sx_enable_rx_interrupts(void *ptr)
-{
-	/*  struct sx_port *port = ptr; */
-	func_enter();
-
-	func_exit();
-}
-
-/* Jeez. Isn't this simple? */
-static int sx_carrier_raised(struct tty_port *port)
-{
-	struct sx_port *sp = container_of(port, struct sx_port, gs.port);
-	return ((sx_read_channel_byte(sp, hi_ip) & IP_DCD) != 0);
-}
-
-/* Jeez. Isn't this simple? */
-static int sx_chars_in_buffer(void *ptr)
-{
-	struct sx_port *port = ptr;
-	func_enter2();
-
-	func_exit();
-	return ((sx_read_channel_byte(port, hi_txipos) -
-		 sx_read_channel_byte(port, hi_txopos)) & 0xff);
-}
-
-static void sx_shutdown_port(void *ptr)
-{
-	struct sx_port *port = ptr;
-
-	func_enter();
-
-	port->gs.port.flags &= ~GS_ACTIVE;
-	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
-		sx_setsignals(port, 0, 0);
-		sx_reconfigure_port(port);
-	}
-
-	func_exit();
-}
-
-/* ********************************************************************** *
- *                Here are the routines that actually                     *
- *               interface with the rest of the system                    *
- * ********************************************************************** */
-
-static int sx_open(struct tty_struct *tty, struct file *filp)
-{
-	struct sx_port *port;
-	int retval, line;
-	unsigned long flags;
-
-	func_enter();
-
-	if (!sx_initialized) {
-		return -EIO;
-	}
-
-	line = tty->index;
-	sx_dprintk(SX_DEBUG_OPEN, "%d: opening line %d. tty=%p ctty=%p, "
-			"np=%d)\n", task_pid_nr(current), line, tty,
-			current->signal->tty, sx_nports);
-
-	if ((line < 0) || (line >= SX_NPORTS) || (line >= sx_nports))
-		return -ENODEV;
-
-	port = &sx_ports[line];
-	port->c_dcd = 0; /* Make sure that the first interrupt doesn't detect a
-			    1 -> 0 transition. */
-
-	sx_dprintk(SX_DEBUG_OPEN, "port = %p c_dcd = %d\n", port, port->c_dcd);
-
-	spin_lock_irqsave(&port->gs.driver_lock, flags);
-
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	spin_unlock_irqrestore(&port->gs.driver_lock, flags);
-
-	sx_dprintk(SX_DEBUG_OPEN, "starting port\n");
-
-	/*
-	 * Start up serial port
-	 */
-	retval = gs_init_port(&port->gs);
-	sx_dprintk(SX_DEBUG_OPEN, "done gs_init\n");
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	port->gs.port.flags |= GS_ACTIVE;
-	if (port->gs.port.count <= 1)
-		sx_setsignals(port, 1, 1);
-
-#if 0
-	if (sx_debug & SX_DEBUG_OPEN)
-		my_hd(port, sizeof(*port));
-#else
-	if (sx_debug & SX_DEBUG_OPEN)
-		my_hd_io(port->board->base + port->ch_base, sizeof(*port));
-#endif
-
-	if (port->gs.port.count <= 1) {
-		if (sx_send_command(port, HS_LOPEN, -1, HS_IDLE_OPEN) != 1) {
-			printk(KERN_ERR "sx: Card didn't respond to LOPEN "
-					"command.\n");
-			spin_lock_irqsave(&port->gs.driver_lock, flags);
-			port->gs.port.count--;
-			spin_unlock_irqrestore(&port->gs.driver_lock, flags);
-			return -EIO;
-		}
-	}
-
-	retval = gs_block_til_ready(port, filp);
-	sx_dprintk(SX_DEBUG_OPEN, "Block til ready returned %d. Count=%d\n",
-			retval, port->gs.port.count);
-
-	if (retval) {
-/*
- * Don't lower gs.port.count here because sx_close() will be called later
- */
-
-		return retval;
-	}
-	/* tty->low_latency = 1; */
-
-	port->c_dcd = sx_carrier_raised(&port->gs.port);
-	sx_dprintk(SX_DEBUG_OPEN, "at open: cd=%d\n", port->c_dcd);
-
-	func_exit();
-	return 0;
-
-}
-
-static void sx_close(void *ptr)
-{
-	struct sx_port *port = ptr;
-	/* Give the port 5 seconds to close down. */
-	int to = 5 * HZ;
-
-	func_enter();
-
-	sx_setsignals(port, 0, 0);
-	sx_reconfigure_port(port);
-	sx_send_command(port, HS_CLOSE, 0, 0);
-
-	while (to-- && (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED))
-		if (msleep_interruptible(10))
-			break;
-	if (sx_read_channel_byte(port, hi_hstat) != HS_IDLE_CLOSED) {
-		if (sx_send_command(port, HS_FORCE_CLOSED, -1, HS_IDLE_CLOSED)
-				!= 1) {
-			printk(KERN_ERR "sx: sent the force_close command, but "
-					"card didn't react\n");
-		} else
-			sx_dprintk(SX_DEBUG_CLOSE, "sent the force_close "
-					"command.\n");
-	}
-
-	sx_dprintk(SX_DEBUG_CLOSE, "waited %d jiffies for close. count=%d\n",
-			5 * HZ - to - 1, port->gs.port.count);
-
-	if (port->gs.port.count) {
-		sx_dprintk(SX_DEBUG_CLOSE, "WARNING port count:%d\n",
-				port->gs.port.count);
-		/*printk("%s SETTING port count to zero: %p count: %d\n",
-				__func__, port, port->gs.port.count);
-		port->gs.port.count = 0;*/
-	}
-
-	func_exit();
-}
-
-/* This is relatively thorough. But then again it is only 20 lines. */
-#define MARCHUP		for (i = min; i < max; i++)
-#define MARCHDOWN	for (i = max - 1; i >= min; i--)
-#define W0		write_sx_byte(board, i, 0x55)
-#define W1		write_sx_byte(board, i, 0xaa)
-#define R0		if (read_sx_byte(board, i) != 0x55) return 1
-#define R1		if (read_sx_byte(board, i) != 0xaa) return 1
-
-/* This memtest takes a human-noticable time. You normally only do it
-   once a boot, so I guess that it is worth it. */
-static int do_memtest(struct sx_board *board, int min, int max)
-{
-	int i;
-
-	/* This is a marchb. Theoretically, marchb catches much more than
-	   simpler tests. In practise, the longer test just catches more
-	   intermittent errors. -- REW
-	   (For the theory behind memory testing see: 
-	   Testing Semiconductor Memories by A.J. van de Goor.) */
-	MARCHUP {
-		W0;
-	}
-	MARCHUP {
-		R0;
-		W1;
-		R1;
-		W0;
-		R0;
-		W1;
-	}
-	MARCHUP {
-		R1;
-		W0;
-		W1;
-	}
-	MARCHDOWN {
-		R1;
-		W0;
-		W1;
-		W0;
-	}
-	MARCHDOWN {
-		R0;
-		W1;
-		W0;
-	}
-
-	return 0;
-}
-
-#undef MARCHUP
-#undef MARCHDOWN
-#undef W0
-#undef W1
-#undef R0
-#undef R1
-
-#define MARCHUP		for (i = min; i < max; i += 2)
-#define MARCHDOWN	for (i = max - 1; i >= min; i -= 2)
-#define W0		write_sx_word(board, i, 0x55aa)
-#define W1		write_sx_word(board, i, 0xaa55)
-#define R0		if (read_sx_word(board, i) != 0x55aa) return 1
-#define R1		if (read_sx_word(board, i) != 0xaa55) return 1
-
-#if 0
-/* This memtest takes a human-noticable time. You normally only do it
-   once a boot, so I guess that it is worth it. */
-static int do_memtest_w(struct sx_board *board, int min, int max)
-{
-	int i;
-
-	MARCHUP {
-		W0;
-	}
-	MARCHUP {
-		R0;
-		W1;
-		R1;
-		W0;
-		R0;
-		W1;
-	}
-	MARCHUP {
-		R1;
-		W0;
-		W1;
-	}
-	MARCHDOWN {
-		R1;
-		W0;
-		W1;
-		W0;
-	}
-	MARCHDOWN {
-		R0;
-		W1;
-		W0;
-	}
-
-	return 0;
-}
-#endif
-
-static long sx_fw_ioctl(struct file *filp, unsigned int cmd,
-							unsigned long arg)
-{
-	long rc = 0;
-	int __user *descr = (int __user *)arg;
-	int i;
-	static struct sx_board *board = NULL;
-	int nbytes, offset;
-	unsigned long data;
-	char *tmp;
-
-	func_enter();
-
-	if (!capable(CAP_SYS_RAWIO))
-		return -EPERM;
-
-	tty_lock();
-
-	sx_dprintk(SX_DEBUG_FIRMWARE, "IOCTL %x: %lx\n", cmd, arg);
-
-	if (!board)
-		board = &boards[0];
-	if (board->flags & SX_BOARD_PRESENT) {
-		sx_dprintk(SX_DEBUG_FIRMWARE, "Board present! (%x)\n",
-				board->flags);
-	} else {
-		sx_dprintk(SX_DEBUG_FIRMWARE, "Board not present! (%x) all:",
-				board->flags);
-		for (i = 0; i < SX_NBOARDS; i++)
-			sx_dprintk(SX_DEBUG_FIRMWARE, "<%x> ", boards[i].flags);
-		sx_dprintk(SX_DEBUG_FIRMWARE, "\n");
-		rc = -EIO;
-		goto out;
-	}
-
-	switch (cmd) {
-	case SXIO_SET_BOARD:
-		sx_dprintk(SX_DEBUG_FIRMWARE, "set board to %ld\n", arg);
-		rc = -EIO;
-		if (arg >= SX_NBOARDS)
-			break;
-		sx_dprintk(SX_DEBUG_FIRMWARE, "not out of range\n");
-		if (!(boards[arg].flags & SX_BOARD_PRESENT))
-			break;
-		sx_dprintk(SX_DEBUG_FIRMWARE, ".. and present!\n");
-		board = &boards[arg];
-		rc = 0;
-		/* FIXME: And this does ... nothing?? */
-		break;
-	case SXIO_GET_TYPE:
-		rc = -ENOENT;	/* If we manage to miss one, return error. */
-		if (IS_SX_BOARD(board))
-			rc = SX_TYPE_SX;
-		if (IS_CF_BOARD(board))
-			rc = SX_TYPE_CF;
-		if (IS_SI_BOARD(board))
-			rc = SX_TYPE_SI;
-		if (IS_SI1_BOARD(board))
-			rc = SX_TYPE_SI;
-		if (IS_EISA_BOARD(board))
-			rc = SX_TYPE_SI;
-		sx_dprintk(SX_DEBUG_FIRMWARE, "returning type= %ld\n", rc);
-		break;
-	case SXIO_DO_RAMTEST:
-		if (sx_initialized) {	/* Already initialized: better not ramtest the board.  */
-			rc = -EPERM;
-			break;
-		}
-		if (IS_SX_BOARD(board)) {
-			rc = do_memtest(board, 0, 0x7000);
-			if (!rc)
-				rc = do_memtest(board, 0, 0x7000);
-			/*if (!rc) rc = do_memtest_w (board, 0, 0x7000); */
-		} else {
-			rc = do_memtest(board, 0, 0x7ff8);
-			/* if (!rc) rc = do_memtest_w (board, 0, 0x7ff8); */
-		}
-		sx_dprintk(SX_DEBUG_FIRMWARE,
-				"returning memtest result= %ld\n", rc);
-		break;
-	case SXIO_DOWNLOAD:
-		if (sx_initialized) {/* Already initialized */
-			rc = -EEXIST;
-			break;
-		}
-		if (!sx_reset(board)) {
-			rc = -EIO;
-			break;
-		}
-		sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-		tmp = kmalloc(SX_CHUNK_SIZE, GFP_USER);
-		if (!tmp) {
-			rc = -ENOMEM;
-			break;
-		}
-		/* FIXME: check returns */
-		get_user(nbytes, descr++);
-		get_user(offset, descr++);
-		get_user(data, descr++);
-		while (nbytes && data) {
-			for (i = 0; i < nbytes; i += SX_CHUNK_SIZE) {
-				if (copy_from_user(tmp, (char __user *)data + i,
-						(i + SX_CHUNK_SIZE > nbytes) ?
-						nbytes - i : SX_CHUNK_SIZE)) {
-					kfree(tmp);
-					rc = -EFAULT;
-					goto out;
-				}
-				memcpy_toio(board->base2 + offset + i, tmp,
-						(i + SX_CHUNK_SIZE > nbytes) ?
-						nbytes - i : SX_CHUNK_SIZE);
-			}
-
-			get_user(nbytes, descr++);
-			get_user(offset, descr++);
-			get_user(data, descr++);
-		}
-		kfree(tmp);
-		sx_nports += sx_init_board(board);
-		rc = sx_nports;
-		break;
-	case SXIO_INIT:
-		if (sx_initialized) {	/* Already initialized */
-			rc = -EEXIST;
-			break;
-		}
-		/* This is not allowed until all boards are initialized... */
-		for (i = 0; i < SX_NBOARDS; i++) {
-			if ((boards[i].flags & SX_BOARD_PRESENT) &&
-				!(boards[i].flags & SX_BOARD_INITIALIZED)) {
-				rc = -EIO;
-				break;
-			}
-		}
-		for (i = 0; i < SX_NBOARDS; i++)
-			if (!(boards[i].flags & SX_BOARD_PRESENT))
-				break;
-
-		sx_dprintk(SX_DEBUG_FIRMWARE, "initing portstructs, %d boards, "
-				"%d channels, first board: %d ports\n",
-				i, sx_nports, boards[0].nports);
-		rc = sx_init_portstructs(i, sx_nports);
-		sx_init_drivers();
-		if (rc >= 0)
-			sx_initialized++;
-		break;
-	case SXIO_SETDEBUG:
-		sx_debug = arg;
-		break;
-	case SXIO_GETDEBUG:
-		rc = sx_debug;
-		break;
-	case SXIO_GETGSDEBUG:
-	case SXIO_SETGSDEBUG:
-		rc = -EINVAL;
-		break;
-	case SXIO_GETNPORTS:
-		rc = sx_nports;
-		break;
-	default:
-		rc = -ENOTTY;
-		break;
-	}
-out:
-	tty_unlock();
-	func_exit();
-	return rc;
-}
-
-static int sx_break(struct tty_struct *tty, int flag)
-{
-	struct sx_port *port = tty->driver_data;
-	int rv;
-
-	func_enter();
-	tty_lock();
-
-	if (flag)
-		rv = sx_send_command(port, HS_START, -1, HS_IDLE_BREAK);
-	else
-		rv = sx_send_command(port, HS_STOP, -1, HS_IDLE_OPEN);
-	if (rv != 1)
-		printk(KERN_ERR "sx: couldn't send break (%x).\n",
-			read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
-	tty_unlock();
-	func_exit();
-	return 0;
-}
-
-static int sx_tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct sx_port *port = tty->driver_data;
-	return sx_getsignals(port);
-}
-
-static int sx_tiocmset(struct tty_struct *tty, struct file *file,
-		unsigned int set, unsigned int clear)
-{
-	struct sx_port *port = tty->driver_data;
-	int rts = -1, dtr = -1;
-
-	if (set & TIOCM_RTS)
-		rts = 1;
-	if (set & TIOCM_DTR)
-		dtr = 1;
-	if (clear & TIOCM_RTS)
-		rts = 0;
-	if (clear & TIOCM_DTR)
-		dtr = 0;
-
-	sx_setsignals(port, dtr, rts);
-	sx_reconfigure_port(port);
-	return 0;
-}
-
-static int sx_ioctl(struct tty_struct *tty, struct file *filp,
-		unsigned int cmd, unsigned long arg)
-{
-	int rc;
-	struct sx_port *port = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	/* func_enter2(); */
-
-	rc = 0;
-	tty_lock();
-	switch (cmd) {
-	case TIOCGSERIAL:
-		rc = gs_getserial(&port->gs, argp);
-		break;
-	case TIOCSSERIAL:
-		rc = gs_setserial(&port->gs, argp);
-		break;
-	default:
-		rc = -ENOIOCTLCMD;
-		break;
-	}
-	tty_unlock();
-
-	/* func_exit(); */
-	return rc;
-}
-
-/* The throttle/unthrottle scheme for the Specialix card is different
- * from other drivers and deserves some explanation. 
- * The Specialix hardware takes care of XON/XOFF
- * and CTS/RTS flow control itself.  This means that all we have to
- * do when signalled by the upper tty layer to throttle/unthrottle is
- * to make a note of it here.  When we come to read characters from the
- * rx buffers on the card (sx_receive_chars()) we look to see if the
- * upper layer can accept more (as noted here in sx_rx_throt[]). 
- * If it can't we simply don't remove chars from the cards buffer. 
- * When the tty layer can accept chars, we again note that here and when
- * sx_receive_chars() is called it will remove them from the cards buffer.
- * The card will notice that a ports buffer has drained below some low
- * water mark and will unflow control the line itself, using whatever
- * flow control scheme is in use for that port. -- Simon Allen
- */
-
-static void sx_throttle(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-
-	func_enter2();
-	/* If the port is using any type of input flow
-	 * control then throttle the port.
-	 */
-	if ((tty->termios->c_cflag & CRTSCTS) || (I_IXOFF(tty))) {
-		port->gs.port.flags |= SX_RX_THROTTLE;
-	}
-	func_exit();
-}
-
-static void sx_unthrottle(struct tty_struct *tty)
-{
-	struct sx_port *port = tty->driver_data;
-
-	func_enter2();
-	/* Always unthrottle even if flow control is not enabled on
-	 * this port in case we disabled flow control while the port
-	 * was throttled
-	 */
-	port->gs.port.flags &= ~SX_RX_THROTTLE;
-	func_exit();
-	return;
-}
-
-/* ********************************************************************** *
- *                    Here are the initialization routines.               *
- * ********************************************************************** */
-
-static int sx_init_board(struct sx_board *board)
-{
-	int addr;
-	int chans;
-	int type;
-
-	func_enter();
-
-	/* This is preceded by downloading the download code. */
-
-	board->flags |= SX_BOARD_INITIALIZED;
-
-	if (read_sx_byte(board, 0))
-		/* CF boards may need this. */
-		write_sx_byte(board, 0, 0);
-
-	/* This resets the processor again, to make sure it didn't do any
-	   foolish things while we were downloading the image */
-	if (!sx_reset(board))
-		return 0;
-
-	sx_start_board(board);
-	udelay(10);
-	if (!sx_busy_wait_neq(board, 0, 0xff, 0)) {
-		printk(KERN_ERR "sx: Ooops. Board won't initialize.\n");
-		return 0;
-	}
-
-	/* Ok. So now the processor on the card is running. It gathered
-	   some info for us... */
-	sx_dprintk(SX_DEBUG_INIT, "The sxcard structure:\n");
-	if (sx_debug & SX_DEBUG_INIT)
-		my_hd_io(board->base, 0x10);
-	sx_dprintk(SX_DEBUG_INIT, "the first sx_module structure:\n");
-	if (sx_debug & SX_DEBUG_INIT)
-		my_hd_io(board->base + 0x80, 0x30);
-
-	sx_dprintk(SX_DEBUG_INIT, "init_status: %x, %dk memory, firmware "
-			"V%x.%02x,\n",
-			read_sx_byte(board, 0), read_sx_byte(board, 1),
-			read_sx_byte(board, 5), read_sx_byte(board, 4));
-
-	if (read_sx_byte(board, 0) == 0xff) {
-		printk(KERN_INFO "sx: No modules found. Sorry.\n");
-		board->nports = 0;
-		return 0;
-	}
-
-	chans = 0;
-
-	if (IS_SX_BOARD(board)) {
-		sx_write_board_word(board, cc_int_count, sx_maxints);
-	} else {
-		if (sx_maxints)
-			sx_write_board_word(board, cc_int_count,
-					SI_PROCESSOR_CLOCK / 8 / sx_maxints);
-	}
-
-	/* grab the first module type... */
-	/* board->ta_type = mod_compat_type (read_sx_byte (board, 0x80 + 0x08)); */
-	board->ta_type = mod_compat_type(sx_read_module_byte(board, 0x80,
-				mc_chip));
-
-	/* XXX byteorder */
-	for (addr = 0x80; addr != 0; addr = read_sx_word(board, addr) & 0x7fff){
-		type = sx_read_module_byte(board, addr, mc_chip);
-		sx_dprintk(SX_DEBUG_INIT, "Module at %x: %d channels\n",
-				addr, read_sx_byte(board, addr + 2));
-
-		chans += sx_read_module_byte(board, addr, mc_type);
-
-		sx_dprintk(SX_DEBUG_INIT, "module is an %s, which has %s/%s "
-				"panels\n",
-				mod_type_s(type),
-				pan_type_s(sx_read_module_byte(board, addr,
-						mc_mods) & 0xf),
-				pan_type_s(sx_read_module_byte(board, addr,
-						mc_mods) >> 4));
-
-		sx_dprintk(SX_DEBUG_INIT, "CD1400 versions: %x/%x, ASIC "
-			"version: %x\n",
-			sx_read_module_byte(board, addr, mc_rev1),
-			sx_read_module_byte(board, addr, mc_rev2),
-			sx_read_module_byte(board, addr, mc_mtaasic_rev));
-
-		/* The following combinations are illegal: It should theoretically
-		   work, but timing problems make the bus HANG. */
-
-		if (mod_compat_type(type) != board->ta_type) {
-			printk(KERN_ERR "sx: This is an invalid "
-				"configuration.\nDon't mix TA/MTA/SXDC on the "
-				"same hostadapter.\n");
-			chans = 0;
-			break;
-		}
-		if ((IS_EISA_BOARD(board) ||
-				IS_SI_BOARD(board)) &&
-				(mod_compat_type(type) == 4)) {
-			printk(KERN_ERR	"sx: This is an invalid "
-				"configuration.\nDon't use SXDCs on an SI/XIO "
-				"adapter.\n");
-			chans = 0;
-			break;
-		}
-#if 0				/* Problem fixed: firmware 3.05 */
-		if (IS_SX_BOARD(board) && (type == TA8)) {
-			/* There are some issues with the firmware and the DCD/RTS
-			   lines. It might work if you tie them together or something.
-			   It might also work if you get a newer sx_firmware.   Therefore
-			   this is just a warning. */
-			printk(KERN_WARNING
-			       "sx: The SX host doesn't work too well "
-			       "with the TA8 adapters.\nSpecialix is working on it.\n");
-		}
-#endif
-	}
-
-	if (chans) {
-		if (board->irq > 0) {
-			/* fixed irq, probably PCI */
-			if (sx_irqmask & (1 << board->irq)) {	/* may we use this irq? */
-				if (request_irq(board->irq, sx_interrupt,
-						IRQF_SHARED | IRQF_DISABLED,
-						"sx", board)) {
-					printk(KERN_ERR "sx: Cannot allocate "
-						"irq %d.\n", board->irq);
-					board->irq = 0;
-				}
-			} else
-				board->irq = 0;
-		} else if (board->irq < 0 && sx_irqmask) {
-			/* auto-allocate irq */
-			int irqnr;
-			int irqmask = sx_irqmask & (IS_SX_BOARD(board) ?
-					SX_ISA_IRQ_MASK : SI2_ISA_IRQ_MASK);
-			for (irqnr = 15; irqnr > 0; irqnr--)
-				if (irqmask & (1 << irqnr))
-					if (!request_irq(irqnr, sx_interrupt,
-						IRQF_SHARED | IRQF_DISABLED,
-						"sx", board))
-						break;
-			if (!irqnr)
-				printk(KERN_ERR "sx: Cannot allocate IRQ.\n");
-			board->irq = irqnr;
-		} else
-			board->irq = 0;
-
-		if (board->irq) {
-			/* Found a valid interrupt, start up interrupts! */
-			sx_dprintk(SX_DEBUG_INIT, "Using irq %d.\n",
-					board->irq);
-			sx_start_interrupts(board);
-			board->poll = sx_slowpoll;
-			board->flags |= SX_IRQ_ALLOCATED;
-		} else {
-			/* no irq: setup board for polled operation */
-			board->poll = sx_poll;
-			sx_dprintk(SX_DEBUG_INIT, "Using poll-interval %d.\n",
-					board->poll);
-		}
-
-		/* The timer should be initialized anyway: That way we can
-		   safely del_timer it when the module is unloaded. */
-		setup_timer(&board->timer, sx_pollfunc, (unsigned long)board);
-
-		if (board->poll)
-			mod_timer(&board->timer, jiffies + board->poll);
-	} else {
-		board->irq = 0;
-	}
-
-	board->nports = chans;
-	sx_dprintk(SX_DEBUG_INIT, "returning %d ports.", board->nports);
-
-	func_exit();
-	return chans;
-}
-
-static void __devinit printheader(void)
-{
-	static int header_printed;
-
-	if (!header_printed) {
-		printk(KERN_INFO "Specialix SX driver "
-			"(C) 1998/1999 R.E.Wolff@BitWizard.nl\n");
-		printk(KERN_INFO "sx: version " __stringify(SX_VERSION) "\n");
-		header_printed = 1;
-	}
-}
-
-static int __devinit probe_sx(struct sx_board *board)
-{
-	struct vpd_prom vpdp;
-	char *p;
-	int i;
-
-	func_enter();
-
-	if (!IS_CF_BOARD(board)) {
-		sx_dprintk(SX_DEBUG_PROBE, "Going to verify vpd prom at %p.\n",
-				board->base + SX_VPD_ROM);
-
-		if (sx_debug & SX_DEBUG_PROBE)
-			my_hd_io(board->base + SX_VPD_ROM, 0x40);
-
-		p = (char *)&vpdp;
-		for (i = 0; i < sizeof(struct vpd_prom); i++)
-			*p++ = read_sx_byte(board, SX_VPD_ROM + i * 2);
-
-		if (sx_debug & SX_DEBUG_PROBE)
-			my_hd(&vpdp, 0x20);
-
-		sx_dprintk(SX_DEBUG_PROBE, "checking identifier...\n");
-
-		if (strncmp(vpdp.identifier, SX_VPD_IDENT_STRING, 16) != 0) {
-			sx_dprintk(SX_DEBUG_PROBE, "Got non-SX identifier: "
-					"'%s'\n", vpdp.identifier);
-			return 0;
-		}
-	}
-
-	printheader();
-
-	if (!IS_CF_BOARD(board)) {
-		printk(KERN_DEBUG "sx: Found an SX board at %lx\n",
-			board->hw_base);
-		printk(KERN_DEBUG "sx: hw_rev: %d, assembly level: %d, "
-				"uniq ID:%08x, ",
-				vpdp.hwrev, vpdp.hwass, vpdp.uniqid);
-		printk("Manufactured: %d/%d\n", 1970 + vpdp.myear, vpdp.mweek);
-
-		if ((((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) !=
-				SX_PCI_UNIQUEID1) && (((vpdp.uniqid >> 24) &
-				SX_UNIQUEID_MASK) != SX_ISA_UNIQUEID1)) {
-			/* This might be a bit harsh. This was the primary
-			   reason the SX/ISA card didn't work at first... */
-			printk(KERN_ERR "sx: Hmm. Not an SX/PCI or SX/ISA "
-					"card. Sorry: giving up.\n");
-			return (0);
-		}
-
-		if (((vpdp.uniqid >> 24) & SX_UNIQUEID_MASK) ==
-				SX_ISA_UNIQUEID1) {
-			if (((unsigned long)board->hw_base) & 0x8000) {
-				printk(KERN_WARNING "sx: Warning: There may be "
-					"hardware problems with the card at "
-					"%lx.\n", board->hw_base);
-				printk(KERN_WARNING "sx: Read sx.txt for more "
-						"info.\n");
-			}
-		}
-	}
-
-	board->nports = -1;
-
-	/* This resets the processor, and keeps it off the bus. */
-	if (!sx_reset(board))
-		return 0;
-	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-	func_exit();
-	return 1;
-}
-
-#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
-
-/* Specialix probes for this card at 32k increments from 640k to 16M.
-   I consider machines with less than 16M unlikely nowadays, so I'm
-   not probing above 1Mb. Also, 0xa0000, 0xb0000, are taken by the VGA
-   card. 0xe0000 and 0xf0000 are taken by the BIOS. That only leaves 
-   0xc0000, 0xc8000, 0xd0000 and 0xd8000 . */
-
-static int __devinit probe_si(struct sx_board *board)
-{
-	int i;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_PROBE, "Going to verify SI signature hw %lx at "
-		"%p.\n", board->hw_base, board->base + SI2_ISA_ID_BASE);
-
-	if (sx_debug & SX_DEBUG_PROBE)
-		my_hd_io(board->base + SI2_ISA_ID_BASE, 0x8);
-
-	if (!IS_EISA_BOARD(board)) {
-		if (IS_SI1_BOARD(board)) {
-			for (i = 0; i < 8; i++) {
-				write_sx_byte(board, SI2_ISA_ID_BASE + 7 - i,i);
-			}
-		}
-		for (i = 0; i < 8; i++) {
-			if ((read_sx_byte(board, SI2_ISA_ID_BASE + 7 - i) & 7)
-					!= i) {
-				func_exit();
-				return 0;
-			}
-		}
-	}
-
-	/* Now we're pretty much convinced that there is an SI board here, 
-	   but to prevent trouble, we'd better double check that we don't
-	   have an SI1 board when we're probing for an SI2 board.... */
-
-	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
-	if (IS_SI1_BOARD(board)) {
-		/* This should be an SI1 board, which has this
-		   location writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
-			func_exit();
-			return 0;
-		}
-	} else {
-		/* This should be an SI2 board, which has the bottom
-		   3 bits non-writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
-			func_exit();
-			return 0;
-		}
-	}
-
-	/* Now we're pretty much convinced that there is an SI board here, 
-	   but to prevent trouble, we'd better double check that we don't
-	   have an SI1 board when we're probing for an SI2 board.... */
-
-	write_sx_byte(board, SI2_ISA_ID_BASE, 0x10);
-	if (IS_SI1_BOARD(board)) {
-		/* This should be an SI1 board, which has this
-		   location writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) != 0x10) {
-			func_exit();
-			return 0;
-		}
-	} else {
-		/* This should be an SI2 board, which has the bottom
-		   3 bits non-writable... */
-		if (read_sx_byte(board, SI2_ISA_ID_BASE) == 0x10) {
-			func_exit();
-			return 0;
-		}
-	}
-
-	printheader();
-
-	printk(KERN_DEBUG "sx: Found an SI board at %lx\n", board->hw_base);
-	/* Compared to the SX boards, it is a complete guess as to what
-	   this card is up to... */
-
-	board->nports = -1;
-
-	/* This resets the processor, and keeps it off the bus. */
-	if (!sx_reset(board))
-		return 0;
-	sx_dprintk(SX_DEBUG_INIT, "reset the board...\n");
-
-	func_exit();
-	return 1;
-}
-#endif
-
-static const struct tty_operations sx_ops = {
-	.break_ctl = sx_break,
-	.open = sx_open,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = sx_ioctl,
-	.throttle = sx_throttle,
-	.unthrottle = sx_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-	.tiocmget = sx_tiocmget,
-	.tiocmset = sx_tiocmset,
-};
-
-static const struct tty_port_operations sx_port_ops = {
-	.carrier_raised = sx_carrier_raised,
-};
-
-static int sx_init_drivers(void)
-{
-	int error;
-
-	func_enter();
-
-	sx_driver = alloc_tty_driver(sx_nports);
-	if (!sx_driver)
-		return 1;
-	sx_driver->owner = THIS_MODULE;
-	sx_driver->driver_name = "specialix_sx";
-	sx_driver->name = "ttyX";
-	sx_driver->major = SX_NORMAL_MAJOR;
-	sx_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	sx_driver->subtype = SERIAL_TYPE_NORMAL;
-	sx_driver->init_termios = tty_std_termios;
-	sx_driver->init_termios.c_cflag = B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	sx_driver->init_termios.c_ispeed = 9600;
-	sx_driver->init_termios.c_ospeed = 9600;
-	sx_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(sx_driver, &sx_ops);
-
-	if ((error = tty_register_driver(sx_driver))) {
-		put_tty_driver(sx_driver);
-		printk(KERN_ERR "sx: Couldn't register sx driver, error = %d\n",
-			error);
-		return 1;
-	}
-	func_exit();
-	return 0;
-}
-
-static int sx_init_portstructs(int nboards, int nports)
-{
-	struct sx_board *board;
-	struct sx_port *port;
-	int i, j;
-	int addr, chans;
-	int portno;
-
-	func_enter();
-
-	/* Many drivers statically allocate the maximum number of ports
-	   There is no reason not to allocate them dynamically.
-	   Is there? -- REW */
-	sx_ports = kcalloc(nports, sizeof(struct sx_port), GFP_KERNEL);
-	if (!sx_ports)
-		return -ENOMEM;
-
-	port = sx_ports;
-	for (i = 0; i < nboards; i++) {
-		board = &boards[i];
-		board->ports = port;
-		for (j = 0; j < boards[i].nports; j++) {
-			sx_dprintk(SX_DEBUG_INIT, "initing port %d\n", j);
-			tty_port_init(&port->gs.port);
-			port->gs.port.ops = &sx_port_ops;
-			port->gs.magic = SX_MAGIC;
-			port->gs.close_delay = HZ / 2;
-			port->gs.closing_wait = 30 * HZ;
-			port->board = board;
-			port->gs.rd = &sx_real_driver;
-#ifdef NEW_WRITE_LOCKING
-			port->gs.port_write_mutex = MUTEX;
-#endif
-			spin_lock_init(&port->gs.driver_lock);
-			/*
-			 * Initializing wait queue
-			 */
-			port++;
-		}
-	}
-
-	port = sx_ports;
-	portno = 0;
-	for (i = 0; i < nboards; i++) {
-		board = &boards[i];
-		board->port_base = portno;
-		/* Possibly the configuration was rejected. */
-		sx_dprintk(SX_DEBUG_PROBE, "Board has %d channels\n",
-				board->nports);
-		if (board->nports <= 0)
-			continue;
-		/* XXX byteorder ?? */
-		for (addr = 0x80; addr != 0;
-				addr = read_sx_word(board, addr) & 0x7fff) {
-			chans = sx_read_module_byte(board, addr, mc_type);
-			sx_dprintk(SX_DEBUG_PROBE, "Module at %x: %d "
-					"channels\n", addr, chans);
-			sx_dprintk(SX_DEBUG_PROBE, "Port at");
-			for (j = 0; j < chans; j++) {
-				/* The "sx-way" is the way it SHOULD be done.
-				   That way in the future, the firmware may for
-				   example pack the structures a bit more
-				   efficient. Neil tells me it isn't going to
-				   happen anytime soon though. */
-				if (IS_SX_BOARD(board))
-					port->ch_base = sx_read_module_word(
-							board, addr + j * 2,
-							mc_chan_pointer);
-				else
-					port->ch_base = addr + 0x100 + 0x300 *j;
-
-				sx_dprintk(SX_DEBUG_PROBE, " %x",
-						port->ch_base);
-				port->line = portno++;
-				port++;
-			}
-			sx_dprintk(SX_DEBUG_PROBE, "\n");
-		}
-		/* This has to be done earlier. */
-		/* board->flags |= SX_BOARD_INITIALIZED; */
-	}
-
-	func_exit();
-	return 0;
-}
-
-static unsigned int sx_find_free_board(void)
-{
-	unsigned int i;
-
-	for (i = 0; i < SX_NBOARDS; i++)
-		if (!(boards[i].flags & SX_BOARD_PRESENT))
-			break;
-
-	return i;
-}
-
-static void __exit sx_release_drivers(void)
-{
-	func_enter();
-	tty_unregister_driver(sx_driver);
-	put_tty_driver(sx_driver);
-	func_exit();
-}
-
-static void __devexit sx_remove_card(struct sx_board *board,
-		struct pci_dev *pdev)
-{
-	if (board->flags & SX_BOARD_INITIALIZED) {
-		/* The board should stop messing with us. (actually I mean the
-		   interrupt) */
-		sx_reset(board);
-		if ((board->irq) && (board->flags & SX_IRQ_ALLOCATED))
-			free_irq(board->irq, board);
-
-		/* It is safe/allowed to del_timer a non-active timer */
-		del_timer(&board->timer);
-		if (pdev) {
-#ifdef CONFIG_PCI
-			iounmap(board->base2);
-			pci_release_region(pdev, IS_CF_BOARD(board) ? 3 : 2);
-#endif
-		} else {
-			iounmap(board->base);
-			release_region(board->hw_base, board->hw_len);
-		}
-
-		board->flags &= ~(SX_BOARD_INITIALIZED | SX_BOARD_PRESENT);
-	}
-}
-
-#ifdef CONFIG_EISA
-
-static int __devinit sx_eisa_probe(struct device *dev)
-{
-	struct eisa_device *edev = to_eisa_device(dev);
-	struct sx_board *board;
-	unsigned long eisa_slot = edev->base_addr;
-	unsigned int i;
-	int retval = -EIO;
-
-	mutex_lock(&sx_boards_lock);
-	i = sx_find_free_board();
-	if (i == SX_NBOARDS) {
-		mutex_unlock(&sx_boards_lock);
-		goto err;
-	}
-	board = &boards[i];
-	board->flags |= SX_BOARD_PRESENT;
-	mutex_unlock(&sx_boards_lock);
-
-	dev_info(dev, "XIO : Signature found in EISA slot %lu, "
-		 "Product %d Rev %d (REPORT THIS TO LKLM)\n",
-		 eisa_slot >> 12,
-		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 2),
-		 inb(eisa_slot + EISA_VENDOR_ID_OFFSET + 3));
-
-	board->eisa_base = eisa_slot;
-	board->flags &= ~SX_BOARD_TYPE;
-	board->flags |= SI_EISA_BOARD;
-
-	board->hw_base = ((inb(eisa_slot + 0xc01) << 8) +
-			  inb(eisa_slot + 0xc00)) << 16;
-	board->hw_len = SI2_EISA_WINDOW_LEN;
-	if (!request_region(board->hw_base, board->hw_len, "sx")) {
-		dev_err(dev, "can't request region\n");
-		goto err_flag;
-	}
-	board->base2 =
-	board->base = ioremap_nocache(board->hw_base, SI2_EISA_WINDOW_LEN);
-	if (!board->base) {
-		dev_err(dev, "can't remap memory\n");
-		goto err_reg;
-	}
-
-	sx_dprintk(SX_DEBUG_PROBE, "IO hw_base address: %lx\n", board->hw_base);
-	sx_dprintk(SX_DEBUG_PROBE, "base: %p\n", board->base);
-	board->irq = inb(eisa_slot + 0xc02) >> 4;
-	sx_dprintk(SX_DEBUG_PROBE, "IRQ: %d\n", board->irq);
-
-	if (!probe_si(board))
-		goto err_unmap;
-
-	dev_set_drvdata(dev, board);
-
-	return 0;
-err_unmap:
-	iounmap(board->base);
-err_reg:
-	release_region(board->hw_base, board->hw_len);
-err_flag:
-	board->flags &= ~SX_BOARD_PRESENT;
-err:
-	return retval;
-}
-
-static int __devexit sx_eisa_remove(struct device *dev)
-{
-	struct sx_board *board = dev_get_drvdata(dev);
-
-	sx_remove_card(board, NULL);
-
-	return 0;
-}
-
-static struct eisa_device_id sx_eisa_tbl[] = {
-	{ "SLX" },
-	{ "" }
-};
-
-MODULE_DEVICE_TABLE(eisa, sx_eisa_tbl);
-
-static struct eisa_driver sx_eisadriver = {
-	.id_table = sx_eisa_tbl,
-	.driver = {
-		.name = "sx",
-		.probe = sx_eisa_probe,
-		.remove = __devexit_p(sx_eisa_remove),
-	}
-};
-
-#endif
-
-#ifdef CONFIG_PCI
- /******************************************************** 
- * Setting bit 17 in the CNTRL register of the PLX 9050  * 
- * chip forces a retry on writes while a read is pending.*
- * This is to prevent the card locking up on Intel Xeon  *
- * multiprocessor systems with the NX chipset.    -- NV  *
- ********************************************************/
-
-/* Newer cards are produced with this bit set from the configuration
-   EEprom.  As the bit is read/write for the CPU, we can fix it here,
-   if we detect that it isn't set correctly. -- REW */
-
-static void __devinit fix_sx_pci(struct pci_dev *pdev, struct sx_board *board)
-{
-	unsigned int hwbase;
-	void __iomem *rebase;
-	unsigned int t;
-
-#define CNTRL_REG_OFFSET	0x50
-#define CNTRL_REG_GOODVALUE	0x18260000
-
-	pci_read_config_dword(pdev, PCI_BASE_ADDRESS_0, &hwbase);
-	hwbase &= PCI_BASE_ADDRESS_MEM_MASK;
-	rebase = ioremap_nocache(hwbase, 0x80);
-	t = readl(rebase + CNTRL_REG_OFFSET);
-	if (t != CNTRL_REG_GOODVALUE) {
-		printk(KERN_DEBUG "sx: performing cntrl reg fix: %08x -> "
-			"%08x\n", t, CNTRL_REG_GOODVALUE);
-		writel(CNTRL_REG_GOODVALUE, rebase + CNTRL_REG_OFFSET);
-	}
-	iounmap(rebase);
-}
-#endif
-
-static int __devinit sx_pci_probe(struct pci_dev *pdev,
-				  const struct pci_device_id *ent)
-{
-#ifdef CONFIG_PCI
-	struct sx_board *board;
-	unsigned int i, reg;
-	int retval = -EIO;
-
-	mutex_lock(&sx_boards_lock);
-	i = sx_find_free_board();
-	if (i == SX_NBOARDS) {
-		mutex_unlock(&sx_boards_lock);
-		goto err;
-	}
-	board = &boards[i];
-	board->flags |= SX_BOARD_PRESENT;
-	mutex_unlock(&sx_boards_lock);
-
-	retval = pci_enable_device(pdev);
-	if (retval)
-		goto err_flag;
-
-	board->flags &= ~SX_BOARD_TYPE;
-	board->flags |= (pdev->subsystem_vendor == 0x200) ? SX_PCI_BOARD :
-		SX_CFPCI_BOARD;
-
-	/* CF boards use base address 3.... */
-	reg = IS_CF_BOARD(board) ? 3 : 2;
-	retval = pci_request_region(pdev, reg, "sx");
-	if (retval) {
-		dev_err(&pdev->dev, "can't request region\n");
-		goto err_flag;
-	}
-	board->hw_base = pci_resource_start(pdev, reg);
-	board->base2 =
-	board->base = ioremap_nocache(board->hw_base, WINDOW_LEN(board));
-	if (!board->base) {
-		dev_err(&pdev->dev, "ioremap failed\n");
-		goto err_reg;
-	}
-
-	/* Most of the stuff on the CF board is offset by 0x18000 ....  */
-	if (IS_CF_BOARD(board))
-		board->base += 0x18000;
-
-	board->irq = pdev->irq;
-
-	dev_info(&pdev->dev, "Got a specialix card: %p(%d) %x.\n", board->base,
-		 board->irq, board->flags);
-
-	if (!probe_sx(board)) {
-		retval = -EIO;
-		goto err_unmap;
-	}
-
-	fix_sx_pci(pdev, board);
-
-	pci_set_drvdata(pdev, board);
-
-	return 0;
-err_unmap:
-	iounmap(board->base2);
-err_reg:
-	pci_release_region(pdev, reg);
-err_flag:
-	board->flags &= ~SX_BOARD_PRESENT;
-err:
-	return retval;
-#else
-	return -ENODEV;
-#endif
-}
-
-static void __devexit sx_pci_remove(struct pci_dev *pdev)
-{
-	struct sx_board *board = pci_get_drvdata(pdev);
-
-	sx_remove_card(board, pdev);
-}
-
-/* Specialix has a whole bunch of cards with 0x2000 as the device ID. They say
-   its because the standard requires it. So check for SUBVENDOR_ID. */
-static struct pci_device_id sx_pci_tbl[] = {
-	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = PCI_ANY_ID, .subdevice = 0x0200 },
-	{ PCI_VENDOR_ID_SPECIALIX, PCI_DEVICE_ID_SPECIALIX_SX_XIO_IO8,
-		.subvendor = PCI_ANY_ID, .subdevice = 0x0300 },
-	{ 0 }
-};
-
-MODULE_DEVICE_TABLE(pci, sx_pci_tbl);
-
-static struct pci_driver sx_pcidriver = {
-	.name = "sx",
-	.id_table = sx_pci_tbl,
-	.probe = sx_pci_probe,
-	.remove = __devexit_p(sx_pci_remove)
-};
-
-static int __init sx_init(void)
-{
-#ifdef CONFIG_EISA
-	int retval1;
-#endif
-#ifdef CONFIG_ISA
-	struct sx_board *board;
-	unsigned int i;
-#endif
-	unsigned int found = 0;
-	int retval;
-
-	func_enter();
-	sx_dprintk(SX_DEBUG_INIT, "Initing sx module... (sx_debug=%d)\n",
-			sx_debug);
-	if (abs((long)(&sx_debug) - sx_debug) < 0x10000) {
-		printk(KERN_WARNING "sx: sx_debug is an address, instead of a "
-				"value. Assuming -1.\n(%p)\n", &sx_debug);
-		sx_debug = -1;
-	}
-
-	if (misc_register(&sx_fw_device) < 0) {
-		printk(KERN_ERR "SX: Unable to register firmware loader "
-				"driver.\n");
-		return -EIO;
-	}
-#ifdef CONFIG_ISA
-	for (i = 0; i < NR_SX_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = sx_probe_addrs[i];
-		board->hw_len = SX_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_sx_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SX_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_sx(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_sx_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-
-	for (i = 0; i < NR_SI_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = si_probe_addrs[i];
-		board->hw_len = SI2_ISA_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_si_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SI_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_si(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_si_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-	for (i = 0; i < NR_SI1_ADDRS; i++) {
-		board = &boards[found];
-		board->hw_base = si1_probe_addrs[i];
-		board->hw_len = SI1_ISA_WINDOW_LEN;
-		if (!request_region(board->hw_base, board->hw_len, "sx"))
-			continue;
-		board->base2 =
-		board->base = ioremap_nocache(board->hw_base, board->hw_len);
-		if (!board->base)
-			goto err_si1_reg;
-		board->flags &= ~SX_BOARD_TYPE;
-		board->flags |= SI1_ISA_BOARD;
-		board->irq = sx_irqmask ? -1 : 0;
-
-		if (probe_si(board)) {
-			board->flags |= SX_BOARD_PRESENT;
-			found++;
-		} else {
-			iounmap(board->base);
-err_si1_reg:
-			release_region(board->hw_base, board->hw_len);
-		}
-	}
-#endif
-#ifdef CONFIG_EISA
-	retval1 = eisa_driver_register(&sx_eisadriver);
-#endif
-	retval = pci_register_driver(&sx_pcidriver);
-
-	if (found) {
-		printk(KERN_INFO "sx: total of %d boards detected.\n", found);
-		retval = 0;
-	} else if (retval) {
-#ifdef CONFIG_EISA
-		retval = retval1;
-		if (retval1)
-#endif
-			misc_deregister(&sx_fw_device);
-	}
-
-	func_exit();
-	return retval;
-}
-
-static void __exit sx_exit(void)
-{
-	int i;
-
-	func_enter();
-#ifdef CONFIG_EISA
-	eisa_driver_unregister(&sx_eisadriver);
-#endif
-	pci_unregister_driver(&sx_pcidriver);
-
-	for (i = 0; i < SX_NBOARDS; i++)
-		sx_remove_card(&boards[i], NULL);
-
-	if (misc_deregister(&sx_fw_device) < 0) {
-		printk(KERN_INFO "sx: couldn't deregister firmware loader "
-				"device\n");
-	}
-	sx_dprintk(SX_DEBUG_CLEANUP, "Cleaning up drivers (%d)\n",
-			sx_initialized);
-	if (sx_initialized)
-		sx_release_drivers();
-
-	kfree(sx_ports);
-	func_exit();
-}
-
-module_init(sx_init);
-module_exit(sx_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/char/sx.h linux-libre-2.6.39-gnu/drivers/char/sx.h
--- linux-libre-2.6.38-gnu/drivers/char/sx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/sx.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,201 +0,0 @@
-
-/*
- *  sx.h
- *
- *  Copyright (C) 1998/1999 R.E.Wolff@BitWizard.nl
- *
- *  SX serial driver.
- *  -- Supports SI, XIO and SX host cards. 
- *  -- Supports TAs, MTAs and SXDCs.
- *
- *  Version 1.3 -- March, 1999. 
- * 
- */
-
-#define SX_NBOARDS        4
-#define SX_PORTSPERBOARD 32
-#define SX_NPORTS        (SX_NBOARDS * SX_PORTSPERBOARD)
-
-#ifdef __KERNEL__
-
-#define SX_MAGIC 0x12345678
-
-struct sx_port {
-  struct gs_port          gs;
-  struct wait_queue       *shutdown_wait;
-  int                     ch_base;
-  int                     c_dcd;
-  struct sx_board         *board;
-  int                     line;
-  unsigned long           locks;
-};
-
-struct sx_board {
-  int magic;
-  void __iomem *base;
-  void __iomem *base2;
-  unsigned long hw_base;
-  resource_size_t hw_len;
-  int eisa_base;
-  int port_base; /* Number of the first port */
-  struct sx_port *ports;
-  int nports;
-  int flags;
-  int irq;
-  int poll;
-  int ta_type;
-  struct timer_list       timer;
-  unsigned long           locks;
-};
-
-struct vpd_prom {
-  unsigned short id;
-  char hwrev;
-  char hwass;
-  int uniqid;
-  char myear;
-  char mweek;
-  char hw_feature[5];
-  char oem_id;
-  char identifier[16];
-};
-
-#ifndef MOD_RS232DB25MALE
-#define MOD_RS232DB25MALE 0x0a
-#endif
-
-#define SI_ISA_BOARD         0x00000001
-#define SX_ISA_BOARD         0x00000002
-#define SX_PCI_BOARD         0x00000004
-#define SX_CFPCI_BOARD       0x00000008
-#define SX_CFISA_BOARD       0x00000010
-#define SI_EISA_BOARD        0x00000020
-#define SI1_ISA_BOARD        0x00000040
-
-#define SX_BOARD_PRESENT     0x00001000
-#define SX_BOARD_INITIALIZED 0x00002000
-#define SX_IRQ_ALLOCATED     0x00004000
-
-#define SX_BOARD_TYPE        0x000000ff
-
-#define IS_SX_BOARD(board) (board->flags & (SX_PCI_BOARD | SX_CFPCI_BOARD | \
-                                            SX_ISA_BOARD | SX_CFISA_BOARD))
-
-#define IS_SI_BOARD(board) (board->flags & SI_ISA_BOARD)
-#define IS_SI1_BOARD(board) (board->flags & SI1_ISA_BOARD)
-
-#define IS_EISA_BOARD(board) (board->flags & SI_EISA_BOARD)
-
-#define IS_CF_BOARD(board) (board->flags & (SX_CFISA_BOARD | SX_CFPCI_BOARD))
-
-/* The SI processor clock is required to calculate the cc_int_count register
-   value for the SI cards. */
-#define SI_PROCESSOR_CLOCK 25000000
-
-
-/* port flags */
-/* Make sure these don't clash with gs flags or async flags */
-#define SX_RX_THROTTLE        0x0000001
-
-
-
-#define SX_PORT_TRANSMIT_LOCK  0
-#define SX_BOARD_INTR_LOCK     0
-
-
-
-/* Debug flags. Add these together to get more debug info. */
-
-#define SX_DEBUG_OPEN          0x00000001
-#define SX_DEBUG_SETTING       0x00000002
-#define SX_DEBUG_FLOW          0x00000004
-#define SX_DEBUG_MODEMSIGNALS  0x00000008
-#define SX_DEBUG_TERMIOS       0x00000010
-#define SX_DEBUG_TRANSMIT      0x00000020
-#define SX_DEBUG_RECEIVE       0x00000040
-#define SX_DEBUG_INTERRUPTS    0x00000080
-#define SX_DEBUG_PROBE         0x00000100
-#define SX_DEBUG_INIT          0x00000200
-#define SX_DEBUG_CLEANUP       0x00000400
-#define SX_DEBUG_CLOSE         0x00000800
-#define SX_DEBUG_FIRMWARE      0x00001000
-#define SX_DEBUG_MEMTEST       0x00002000
-
-#define SX_DEBUG_ALL           0xffffffff
-
-
-#define O_OTHER(tty)    \
-      ((O_OLCUC(tty))  ||\
-      (O_ONLCR(tty))   ||\
-      (O_OCRNL(tty))   ||\
-      (O_ONOCR(tty))   ||\
-      (O_ONLRET(tty))  ||\
-      (O_OFILL(tty))   ||\
-      (O_OFDEL(tty))   ||\
-      (O_NLDLY(tty))   ||\
-      (O_CRDLY(tty))   ||\
-      (O_TABDLY(tty))  ||\
-      (O_BSDLY(tty))   ||\
-      (O_VTDLY(tty))   ||\
-      (O_FFDLY(tty)))
-
-/* Same for input. */
-#define I_OTHER(tty)    \
-      ((I_INLCR(tty))  ||\
-      (I_IGNCR(tty))   ||\
-      (I_ICRNL(tty))   ||\
-      (I_IUCLC(tty))   ||\
-      (L_ISIG(tty)))
-
-#define MOD_TA   (        TA>>4)
-#define MOD_MTA  (MTA_CD1400>>4)
-#define MOD_SXDC (      SXDC>>4)
-
-
-/* We copy the download code over to the card in chunks of ... bytes */
-#define SX_CHUNK_SIZE 128
-
-#endif /* __KERNEL__ */
-
-
-
-/* Specialix document 6210046-11 page 3 */
-#define SPX(X) (('S'<<24) | ('P' << 16) | (X))
-
-/* Specialix-Linux specific IOCTLS. */
-#define SPXL(X) (SPX(('L' << 8) | (X)))
-
-
-#define SXIO_SET_BOARD      SPXL(0x01)
-#define SXIO_GET_TYPE       SPXL(0x02)
-#define SXIO_DOWNLOAD       SPXL(0x03)
-#define SXIO_INIT           SPXL(0x04)
-#define SXIO_SETDEBUG       SPXL(0x05)
-#define SXIO_GETDEBUG       SPXL(0x06)
-#define SXIO_DO_RAMTEST     SPXL(0x07)
-#define SXIO_SETGSDEBUG     SPXL(0x08)
-#define SXIO_GETGSDEBUG     SPXL(0x09)
-#define SXIO_GETNPORTS      SPXL(0x0a)
-
-
-#ifndef SXCTL_MISC_MINOR 
-/* Allow others to gather this into "major.h" or something like that */
-#define SXCTL_MISC_MINOR    167
-#endif
-
-#ifndef SX_NORMAL_MAJOR
-/* This allows overriding on the compiler commandline, or in a "major.h" 
-   include or something like that */
-#define SX_NORMAL_MAJOR  32
-#define SX_CALLOUT_MAJOR 33
-#endif
-
-
-#define SX_TYPE_SX          0x01
-#define SX_TYPE_SI          0x02
-#define SX_TYPE_CF          0x03
-
-
-#define WINDOW_LEN(board) (IS_CF_BOARD(board)?0x20000:SX_WINDOW_LEN)
-/*                         Need a #define for ^^^^^^^ !!! */
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/sxwindow.h linux-libre-2.6.39-gnu/drivers/char/sxwindow.h
--- linux-libre-2.6.38-gnu/drivers/char/sxwindow.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/sxwindow.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,393 +0,0 @@
-/************************************************************************/
-/*									*/
-/*	Title		:	SX Shared Memory Window Structure	*/
-/*									*/
-/*	Author		:	N.P.Vassallo				*/
-/*									*/
-/*	Creation	:	16th March 1998				*/
-/*									*/
-/*	Version		:	3.0.0					*/
-/*									*/
-/*	Copyright	:	(c) Specialix International Ltd. 1998	*/
-/*									*/
-/*	Description	:	Prototypes, structures and definitions	*/
-/*				describing the SX/SI/XIO cards shared	*/
-/*				memory window structure:		*/
-/*					SXCARD				*/
-/*					SXMODULE			*/
-/*					SXCHANNEL			*/
-/*									*/
-/************************************************************************/
-
-/* History...
-
-3.0.0	16/03/98 NPV	Creation. (based on STRUCT.H)
-
-*/
-
-#ifndef	_sxwindow_h				/* If SXWINDOW.H not already defined */
-#define	_sxwindow_h    1
-
-/*****************************************************************************
-***************************                        ***************************
-***************************   Common Definitions   ***************************
-***************************                        ***************************
-*****************************************************************************/
-
-typedef	struct	_SXCARD		*PSXCARD;	/* SXCARD structure pointer */
-typedef	struct	_SXMODULE	*PMOD;		/* SXMODULE structure pointer */
-typedef	struct	_SXCHANNEL	*PCHAN;		/* SXCHANNEL structure pointer */
-
-/*****************************************************************************
-*********************************            *********************************
-*********************************   SXCARD   *********************************
-*********************************            *********************************
-*****************************************************************************/
-
-typedef	struct	_SXCARD
-{
-	BYTE	cc_init_status;			/* 0x00 Initialisation status */
-	BYTE	cc_mem_size;			/* 0x01 Size of memory on card */
-	WORD	cc_int_count;			/* 0x02 Interrupt count */
-	WORD	cc_revision;			/* 0x04 Download code revision */
-	BYTE	cc_isr_count;			/* 0x06 Count when ISR is run */
-	BYTE	cc_main_count;			/* 0x07 Count when main loop is run */
-	WORD	cc_int_pending;			/* 0x08 Interrupt pending */
-	WORD	cc_poll_count;			/* 0x0A Count when poll is run */
-	BYTE	cc_int_set_count;		/* 0x0C Count when host interrupt is set */
-	BYTE	cc_rfu[0x80 - 0x0D];		/* 0x0D Pad structure to 128 bytes (0x80) */
-
-} SXCARD;
-
-/* SXCARD.cc_init_status definitions... */
-#define 	ADAPTERS_FOUND		(BYTE)0x01
-#define 	NO_ADAPTERS_FOUND	(BYTE)0xFF
-
-/* SXCARD.cc_mem_size definitions... */
-#define 	SX_MEMORY_SIZE		(BYTE)0x40
-
-/* SXCARD.cc_int_count definitions... */
-#define 	INT_COUNT_DEFAULT	100	/* Hz */
-
-/*****************************************************************************
-********************************              ********************************
-********************************   SXMODULE   ********************************
-********************************              ********************************
-*****************************************************************************/
-
-#define	TOP_POINTER(a)		((a)|0x8000)	/* Sets top bit of word */
-#define UNTOP_POINTER(a)	((a)&~0x8000)	/* Clears top bit of word */
-
-typedef	struct	_SXMODULE
-{
-	WORD	mc_next;			/* 0x00 Next module "pointer" (ORed with 0x8000) */
-	BYTE	mc_type;			/* 0x02 Type of TA in terms of number of channels */
-	BYTE	mc_mod_no;			/* 0x03 Module number on SI bus cable (0 closest to card) */
-	BYTE	mc_dtr;				/* 0x04 Private DTR copy (TA only) */
-	BYTE	mc_rfu1;			/* 0x05 Reserved */
-	WORD	mc_uart;			/* 0x06 UART base address for this module */
-	BYTE	mc_chip;			/* 0x08 Chip type / number of ports */
-	BYTE	mc_current_uart;		/* 0x09 Current uart selected for this module */
-#ifdef	DOWNLOAD
-	PCHAN	mc_chan_pointer[8];		/* 0x0A Pointer to each channel structure */
-#else
-	WORD	mc_chan_pointer[8];		/* 0x0A Define as WORD if not compiling into download */
-#endif
-	WORD	mc_rfu2;			/* 0x1A Reserved */
-	BYTE	mc_opens1;			/* 0x1C Number of open ports on first four ports on MTA/SXDC */
-	BYTE	mc_opens2;			/* 0x1D Number of open ports on second four ports on MTA/SXDC */
-	BYTE	mc_mods;			/* 0x1E Types of connector module attached to MTA/SXDC */
-	BYTE	mc_rev1;			/* 0x1F Revision of first CD1400 on MTA/SXDC */
-	BYTE	mc_rev2;			/* 0x20 Revision of second CD1400 on MTA/SXDC */
-	BYTE	mc_mtaasic_rev;			/* 0x21 Revision of MTA ASIC 1..4 -> A, B, C, D */
-	BYTE	mc_rfu3[0x100 - 0x22];		/* 0x22 Pad structure to 256 bytes (0x100) */
-
-} SXMODULE;
-
-/* SXMODULE.mc_type definitions... */
-#define		FOUR_PORTS	(BYTE)4
-#define 	EIGHT_PORTS	(BYTE)8
-
-/* SXMODULE.mc_chip definitions... */
-#define 	CHIP_MASK	0xF0
-#define		TA		(BYTE)0
-#define 	TA4		(TA | FOUR_PORTS)
-#define 	TA8		(TA | EIGHT_PORTS)
-#define		TA4_ASIC	(BYTE)0x0A
-#define		TA8_ASIC	(BYTE)0x0B
-#define 	MTA_CD1400	(BYTE)0x28
-#define 	SXDC		(BYTE)0x48
-
-/* SXMODULE.mc_mods definitions... */
-#define		MOD_RS232DB25	0x00		/* RS232 DB25 (socket/plug) */
-#define		MOD_RS232RJ45	0x01		/* RS232 RJ45 (shielded/opto-isolated) */
-#define		MOD_RESERVED_2	0x02		/* Reserved (RS485) */
-#define		MOD_RS422DB25	0x03		/* RS422 DB25 Socket */
-#define		MOD_RESERVED_4	0x04		/* Reserved */
-#define		MOD_PARALLEL	0x05		/* Parallel */
-#define		MOD_RESERVED_6	0x06		/* Reserved (RS423) */
-#define		MOD_RESERVED_7	0x07		/* Reserved */
-#define		MOD_2_RS232DB25	0x08		/* Rev 2.0 RS232 DB25 (socket/plug) */
-#define		MOD_2_RS232RJ45	0x09		/* Rev 2.0 RS232 RJ45 */
-#define		MOD_RESERVED_A	0x0A		/* Rev 2.0 Reserved */
-#define		MOD_2_RS422DB25	0x0B		/* Rev 2.0 RS422 DB25 */
-#define		MOD_RESERVED_C	0x0C		/* Rev 2.0 Reserved */
-#define		MOD_2_PARALLEL	0x0D		/* Rev 2.0 Parallel */
-#define		MOD_RESERVED_E	0x0E		/* Rev 2.0 Reserved */
-#define		MOD_BLANK	0x0F		/* Blank Panel */
-
-/*****************************************************************************
-********************************               *******************************
-********************************   SXCHANNEL   *******************************
-********************************               *******************************
-*****************************************************************************/
-
-#define		TX_BUFF_OFFSET		0x60	/* Transmit buffer offset in channel structure */
-#define		BUFF_POINTER(a)		(((a)+TX_BUFF_OFFSET)|0x8000)
-#define		UNBUFF_POINTER(a)	(jet_channel*)(((a)&~0x8000)-TX_BUFF_OFFSET) 
-#define 	BUFFER_SIZE		256
-#define 	HIGH_WATER		((BUFFER_SIZE / 4) * 3)
-#define 	LOW_WATER		(BUFFER_SIZE / 4)
-
-typedef	struct	_SXCHANNEL
-{
-	WORD	next_item;			/* 0x00 Offset from window base of next channels hi_txbuf (ORred with 0x8000) */
-	WORD 	addr_uart;			/* 0x02 INTERNAL pointer to uart address. Includes FASTPATH bit */
-	WORD	module;				/* 0x04 Offset from window base of parent SXMODULE structure */
-	BYTE 	type;				/* 0x06 Chip type / number of ports (copy of mc_chip) */
-	BYTE	chan_number;			/* 0x07 Channel number on the TA/MTA/SXDC */
-	WORD	xc_status;			/* 0x08 Flow control and I/O status */
-	BYTE	hi_rxipos;			/* 0x0A Receive buffer input index */
-	BYTE	hi_rxopos;			/* 0x0B Receive buffer output index */
-	BYTE	hi_txopos;			/* 0x0C Transmit buffer output index */
-	BYTE	hi_txipos;			/* 0x0D Transmit buffer input index */
-	BYTE	hi_hstat;			/* 0x0E Command register */
-	BYTE	dtr_bit;			/* 0x0F INTERNAL DTR control byte (TA only) */
-	BYTE	txon;				/* 0x10 INTERNAL copy of hi_txon */
-	BYTE	txoff;				/* 0x11 INTERNAL copy of hi_txoff */
-	BYTE	rxon;				/* 0x12 INTERNAL copy of hi_rxon */
-	BYTE	rxoff;				/* 0x13 INTERNAL copy of hi_rxoff */
-	BYTE	hi_mr1;				/* 0x14 Mode Register 1 (databits,parity,RTS rx flow)*/
-	BYTE	hi_mr2;				/* 0x15 Mode Register 2 (stopbits,local,CTS tx flow)*/
-	BYTE	hi_csr;				/* 0x16 Clock Select Register (baud rate) */
-	BYTE	hi_op;				/* 0x17 Modem Output Signal */
-	BYTE	hi_ip;				/* 0x18 Modem Input Signal */
-	BYTE	hi_state;			/* 0x19 Channel status */
-	BYTE	hi_prtcl;			/* 0x1A Channel protocol (flow control) */
-	BYTE	hi_txon;			/* 0x1B Transmit XON character */
-	BYTE	hi_txoff;			/* 0x1C Transmit XOFF character */
-	BYTE	hi_rxon;			/* 0x1D Receive XON character */
-	BYTE	hi_rxoff;			/* 0x1E Receive XOFF character */
-	BYTE	close_prev;			/* 0x1F INTERNAL channel previously closed flag */
-	BYTE	hi_break;			/* 0x20 Break and error control */
-	BYTE	break_state;			/* 0x21 INTERNAL copy of hi_break */
-	BYTE	hi_mask;			/* 0x22 Mask for received data */
-	BYTE	mask;				/* 0x23 INTERNAL copy of hi_mask */
-	BYTE	mod_type;			/* 0x24 MTA/SXDC hardware module type */
-	BYTE	ccr_state;			/* 0x25 INTERNAL MTA/SXDC state of CCR register */
-	BYTE	ip_mask;			/* 0x26 Input handshake mask */
-	BYTE	hi_parallel;			/* 0x27 Parallel port flag */
-	BYTE	par_error;			/* 0x28 Error code for parallel loopback test */
-	BYTE	any_sent;			/* 0x29 INTERNAL data sent flag */
-	BYTE	asic_txfifo_size;		/* 0x2A INTERNAL SXDC transmit FIFO size */
-	BYTE	rfu1[2];			/* 0x2B Reserved */
-	BYTE	csr;				/* 0x2D INTERNAL copy of hi_csr */
-#ifdef	DOWNLOAD
-	PCHAN	nextp;				/* 0x2E Offset from window base of next channel structure */
-#else
-	WORD	nextp;				/* 0x2E Define as WORD if not compiling into download */
-#endif
-	BYTE	prtcl;				/* 0x30 INTERNAL copy of hi_prtcl */
-	BYTE	mr1;				/* 0x31 INTERNAL copy of hi_mr1 */
-	BYTE	mr2;				/* 0x32 INTERNAL copy of hi_mr2 */
-	BYTE	hi_txbaud;			/* 0x33 Extended transmit baud rate (SXDC only if((hi_csr&0x0F)==0x0F) */
-	BYTE	hi_rxbaud;			/* 0x34 Extended receive baud rate  (SXDC only if((hi_csr&0xF0)==0xF0) */
-	BYTE	txbreak_state;			/* 0x35 INTERNAL MTA/SXDC transmit break state */
-	BYTE	txbaud;				/* 0x36 INTERNAL copy of hi_txbaud */
-	BYTE	rxbaud;				/* 0x37 INTERNAL copy of hi_rxbaud */
-	WORD	err_framing;			/* 0x38 Count of receive framing errors */
-	WORD	err_parity;			/* 0x3A Count of receive parity errors */
-	WORD	err_overrun;			/* 0x3C Count of receive overrun errors */
-	WORD	err_overflow;			/* 0x3E Count of receive buffer overflow errors */
-	BYTE	rfu2[TX_BUFF_OFFSET - 0x40];	/* 0x40 Reserved until hi_txbuf */
-	BYTE	hi_txbuf[BUFFER_SIZE];		/* 0x060 Transmit buffer */
-	BYTE	hi_rxbuf[BUFFER_SIZE];		/* 0x160 Receive buffer */
-	BYTE	rfu3[0x300 - 0x260];		/* 0x260 Reserved until 768 bytes (0x300) */
-
-} SXCHANNEL;
-
-/* SXCHANNEL.addr_uart definitions... */
-#define		FASTPATH	0x1000		/* Set to indicate fast rx/tx processing (TA only) */
-
-/* SXCHANNEL.xc_status definitions... */
-#define		X_TANY		0x0001		/* XON is any character (TA only) */
-#define		X_TION		0x0001		/* Tx interrupts on (MTA only) */
-#define		X_TXEN		0x0002		/* Tx XON/XOFF enabled (TA only) */
-#define		X_RTSEN		0x0002		/* RTS FLOW enabled (MTA only) */
-#define		X_TXRC		0x0004		/* XOFF received (TA only) */
-#define		X_RTSLOW	0x0004		/* RTS dropped (MTA only) */
-#define		X_RXEN		0x0008		/* Rx XON/XOFF enabled */
-#define		X_ANYXO		0x0010		/* XOFF pending/sent or RTS dropped */
-#define		X_RXSE		0x0020		/* Rx XOFF sent */
-#define		X_NPEND		0x0040		/* Rx XON pending or XOFF pending */
-#define		X_FPEND		0x0080		/* Rx XOFF pending */
-#define		C_CRSE		0x0100		/* Carriage return sent (TA only) */
-#define		C_TEMR		0x0100		/* Tx empty requested (MTA only) */
-#define		C_TEMA		0x0200		/* Tx empty acked (MTA only) */
-#define		C_ANYP		0x0200		/* Any protocol bar tx XON/XOFF (TA only) */
-#define		C_EN		0x0400		/* Cooking enabled (on MTA means port is also || */
-#define		C_HIGH		0x0800		/* Buffer previously hit high water */
-#define		C_CTSEN		0x1000		/* CTS automatic flow-control enabled */
-#define		C_DCDEN		0x2000		/* DCD/DTR checking enabled */
-#define		C_BREAK		0x4000		/* Break detected */
-#define		C_RTSEN		0x8000		/* RTS automatic flow control enabled (MTA only) */
-#define		C_PARITY	0x8000		/* Parity checking enabled (TA only) */
-
-/* SXCHANNEL.hi_hstat definitions... */
-#define		HS_IDLE_OPEN	0x00		/* Channel open state */
-#define		HS_LOPEN	0x02		/* Local open command (no modem monitoring) */
-#define		HS_MOPEN	0x04		/* Modem open command (wait for DCD signal) */
-#define		HS_IDLE_MPEND	0x06		/* Waiting for DCD signal state */
-#define		HS_CONFIG	0x08		/* Configuration command */
-#define		HS_CLOSE	0x0A		/* Close command */
-#define		HS_START	0x0C		/* Start transmit break command */
-#define		HS_STOP		0x0E		/* Stop transmit break command */
-#define		HS_IDLE_CLOSED	0x10		/* Closed channel state */
-#define		HS_IDLE_BREAK	0x12		/* Transmit break state */
-#define		HS_FORCE_CLOSED	0x14		/* Force close command */
-#define		HS_RESUME	0x16		/* Clear pending XOFF command */
-#define		HS_WFLUSH	0x18		/* Flush transmit buffer command */
-#define		HS_RFLUSH	0x1A		/* Flush receive buffer command */
-#define		HS_SUSPEND	0x1C		/* Suspend output command (like XOFF received) */
-#define		PARALLEL	0x1E		/* Parallel port loopback test command (Diagnostics Only) */
-#define		ENABLE_RX_INTS	0x20		/* Enable receive interrupts command (Diagnostics Only) */
-#define		ENABLE_TX_INTS	0x22		/* Enable transmit interrupts command (Diagnostics Only) */
-#define		ENABLE_MDM_INTS	0x24		/* Enable modem interrupts command (Diagnostics Only) */
-#define		DISABLE_INTS	0x26		/* Disable interrupts command (Diagnostics Only) */
-
-/* SXCHANNEL.hi_mr1 definitions... */
-#define		MR1_BITS	0x03		/* Data bits mask */
-#define		MR1_5_BITS	0x00		/* 5 data bits */
-#define		MR1_6_BITS	0x01		/* 6 data bits */
-#define		MR1_7_BITS	0x02		/* 7 data bits */
-#define		MR1_8_BITS	0x03		/* 8 data bits */
-#define		MR1_PARITY	0x1C		/* Parity mask */
-#define		MR1_ODD		0x04		/* Odd parity */
-#define		MR1_EVEN	0x00		/* Even parity */
-#define		MR1_WITH	0x00		/* Parity enabled */
-#define		MR1_FORCE	0x08		/* Force parity */
-#define		MR1_NONE	0x10		/* No parity */
-#define		MR1_NOPARITY	MR1_NONE		/* No parity */
-#define		MR1_ODDPARITY	(MR1_WITH|MR1_ODD)	/* Odd parity */
-#define		MR1_EVENPARITY	(MR1_WITH|MR1_EVEN)	/* Even parity */
-#define		MR1_MARKPARITY	(MR1_FORCE|MR1_ODD)	/* Mark parity */
-#define		MR1_SPACEPARITY	(MR1_FORCE|MR1_EVEN)	/* Space parity */
-#define		MR1_RTS_RXFLOW	0x80		/* RTS receive flow control */
-
-/* SXCHANNEL.hi_mr2 definitions... */
-#define		MR2_STOP	0x0F		/* Stop bits mask */
-#define		MR2_1_STOP	0x07		/* 1 stop bit */
-#define		MR2_2_STOP	0x0F		/* 2 stop bits */
-#define		MR2_CTS_TXFLOW	0x10		/* CTS transmit flow control */
-#define		MR2_RTS_TOGGLE	0x20		/* RTS toggle on transmit */
-#define		MR2_NORMAL	0x00		/* Normal mode */
-#define		MR2_AUTO	0x40		/* Auto-echo mode (TA only) */
-#define		MR2_LOCAL	0x80		/* Local echo mode */
-#define		MR2_REMOTE	0xC0		/* Remote echo mode (TA only) */
-
-/* SXCHANNEL.hi_csr definitions... */
-#define		CSR_75		0x0		/*    75 baud */
-#define		CSR_110		0x1		/*   110 baud (TA), 115200 (MTA/SXDC) */
-#define		CSR_38400	0x2		/* 38400 baud */
-#define		CSR_150		0x3		/*   150 baud */
-#define		CSR_300		0x4		/*   300 baud */
-#define		CSR_600		0x5		/*   600 baud */
-#define		CSR_1200	0x6		/*  1200 baud */
-#define		CSR_2000	0x7		/*  2000 baud */
-#define		CSR_2400	0x8		/*  2400 baud */
-#define		CSR_4800	0x9		/*  4800 baud */
-#define		CSR_1800	0xA		/*  1800 baud */
-#define		CSR_9600	0xB		/*  9600 baud */
-#define		CSR_19200	0xC		/* 19200 baud */
-#define		CSR_57600	0xD		/* 57600 baud */
-#define		CSR_EXTBAUD	0xF		/* Extended baud rate (hi_txbaud/hi_rxbaud) */
-
-/* SXCHANNEL.hi_op definitions... */
-#define		OP_RTS		0x01		/* RTS modem output signal */
-#define		OP_DTR		0x02		/* DTR modem output signal */
-
-/* SXCHANNEL.hi_ip definitions... */
-#define		IP_CTS		0x02		/* CTS modem input signal */
-#define		IP_DCD		0x04		/* DCD modem input signal */
-#define		IP_DSR		0x20		/* DTR modem input signal */
-#define		IP_RI		0x40		/* RI modem input signal */
-
-/* SXCHANNEL.hi_state definitions... */
-#define		ST_BREAK	0x01		/* Break received (clear with config) */
-#define		ST_DCD		0x02		/* DCD signal changed state */
-
-/* SXCHANNEL.hi_prtcl definitions... */
-#define		SP_TANY		0x01		/* Transmit XON/XANY (if SP_TXEN enabled) */
-#define		SP_TXEN		0x02		/* Transmit XON/XOFF flow control */
-#define		SP_CEN		0x04		/* Cooking enabled */
-#define		SP_RXEN		0x08		/* Rx XON/XOFF enabled */
-#define		SP_DCEN		0x20		/* DCD / DTR check */
-#define		SP_DTR_RXFLOW	0x40		/* DTR receive flow control */
-#define		SP_PAEN		0x80		/* Parity checking enabled */
-
-/* SXCHANNEL.hi_break definitions... */
-#define		BR_IGN		0x01		/* Ignore any received breaks */
-#define		BR_INT		0x02		/* Interrupt on received break */
-#define		BR_PARMRK	0x04		/* Enable parmrk parity error processing */
-#define		BR_PARIGN	0x08		/* Ignore chars with parity errors */
-#define 	BR_ERRINT	0x80		/* Treat parity/framing/overrun errors as exceptions */
-
-/* SXCHANNEL.par_error definitions.. */
-#define		DIAG_IRQ_RX	0x01		/* Indicate serial receive interrupt (diags only) */
-#define		DIAG_IRQ_TX	0x02		/* Indicate serial transmit interrupt (diags only) */
-#define		DIAG_IRQ_MD	0x04		/* Indicate serial modem interrupt (diags only) */
-
-/* SXCHANNEL.hi_txbaud/hi_rxbaud definitions... (SXDC only) */
-#define		BAUD_75		0x00		/*     75 baud */
-#define		BAUD_115200	0x01		/* 115200 baud */
-#define		BAUD_38400	0x02		/*  38400 baud */
-#define		BAUD_150	0x03		/*    150 baud */
-#define		BAUD_300	0x04		/*    300 baud */
-#define		BAUD_600	0x05		/*    600 baud */
-#define		BAUD_1200	0x06		/*   1200 baud */
-#define		BAUD_2000	0x07		/*   2000 baud */
-#define		BAUD_2400	0x08		/*   2400 baud */
-#define		BAUD_4800	0x09		/*   4800 baud */
-#define		BAUD_1800	0x0A		/*   1800 baud */
-#define		BAUD_9600	0x0B		/*   9600 baud */
-#define		BAUD_19200	0x0C		/*  19200 baud */
-#define		BAUD_57600	0x0D		/*  57600 baud */
-#define		BAUD_230400	0x0E		/* 230400 baud */
-#define		BAUD_460800	0x0F		/* 460800 baud */
-#define		BAUD_921600	0x10		/* 921600 baud */
-#define		BAUD_50		0x11    	/*     50 baud */
-#define		BAUD_110	0x12		/*    110 baud */
-#define		BAUD_134_5	0x13		/*  134.5 baud */
-#define		BAUD_200	0x14		/*    200 baud */
-#define		BAUD_7200	0x15		/*   7200 baud */
-#define		BAUD_56000	0x16		/*  56000 baud */
-#define		BAUD_64000	0x17		/*  64000 baud */
-#define		BAUD_76800	0x18		/*  76800 baud */
-#define		BAUD_128000	0x19		/* 128000 baud */
-#define		BAUD_150000	0x1A		/* 150000 baud */
-#define		BAUD_14400	0x1B		/*  14400 baud */
-#define		BAUD_256000	0x1C		/* 256000 baud */
-#define		BAUD_28800	0x1D		/*  28800 baud */
-
-/* SXCHANNEL.txbreak_state definiions... */
-#define		TXBREAK_OFF	0		/* Not sending break */
-#define		TXBREAK_START	1		/* Begin sending break */
-#define		TXBREAK_START1	2		/* Begin sending break, part 1 */
-#define		TXBREAK_ON	3		/* Sending break */
-#define		TXBREAK_STOP	4		/* Stop sending break */
-#define		TXBREAK_STOP1	5		/* Stop sending break, part 1 */
-
-#endif						/* _sxwindow_h */
-
-/* End of SXWINDOW.H */
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/synclink.c linux-libre-2.6.39-gnu/drivers/char/synclink.c
--- linux-libre-2.6.38-gnu/drivers/char/synclink.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/synclink.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,8120 +0,0 @@
-/*
- * linux/drivers/char/synclink.c
- *
- * $Id: synclink.c,v 4.38 2005/11/07 16:30:34 paulkf Exp $
- *
- * Device driver for Microgate SyncLink ISA and PCI
- * high speed multiprotocol serial adapters.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * Derived from serial.c written by Theodore Ts'o and Linus Torvalds
- *
- * Original release 01/11/99
- *
- * This code is released under the GNU General Public License (GPL)
- *
- * This driver is primarily intended for use in synchronous
- * HDLC mode. Asynchronous mode is also provided.
- *
- * When operating in synchronous mode, each call to mgsl_write()
- * contains exactly one complete HDLC frame. Calling mgsl_put_char
- * will start assembling an HDLC frame that will not be sent until
- * mgsl_flush_chars or mgsl_write is called.
- * 
- * Synchronous receive data is reported as complete frames. To accomplish
- * this, the TTY flip buffer is bypassed (too small to hold largest
- * frame and may fragment frames) and the line discipline
- * receive entry point is called directly.
- *
- * This driver has been tested with a slightly modified ppp.c driver
- * for synchronous PPP.
- *
- * 2000/02/16
- * Added interface for syncppp.c driver (an alternate synchronous PPP
- * implementation that also supports Cisco HDLC). Each device instance
- * registers as a tty device AND a network device (if dosyncppp option
- * is set for the device). The functionality is determined by which
- * device interface is opened.
- *
- * 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.
- */
-
-#if defined(__i386__)
-#  define BREAKPOINT() asm("   int $3");
-#else
-#  define BREAKPOINT() { }
-#endif
-
-#define MAX_ISA_DEVICES 10
-#define MAX_PCI_DEVICES 10
-#define MAX_TOTAL_DEVICES 20
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/ioctl.h>
-#include <linux/synclink.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <linux/bitops.h>
-#include <asm/types.h>
-#include <linux/termios.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/dma-mapping.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-#define GET_USER(error,value,addr) error = get_user(value,addr)
-#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
-#define PUT_USER(error,value,addr) error = put_user(value,addr)
-#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
-
-#include <asm/uaccess.h>
-
-#define RCLRVALUE 0xffff
-
-static MGSL_PARAMS default_params = {
-	MGSL_MODE_HDLC,			/* unsigned long mode */
-	0,				/* unsigned char loopback; */
-	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */
-	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */
-	0,				/* unsigned long clock_speed; */
-	0xff,				/* unsigned char addr_filter; */
-	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */
-	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */
-	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */
-	9600,				/* unsigned long data_rate; */
-	8,				/* unsigned char data_bits; */
-	1,				/* unsigned char stop_bits; */
-	ASYNC_PARITY_NONE		/* unsigned char parity; */
-};
-
-#define SHARED_MEM_ADDRESS_SIZE 0x40000
-#define BUFFERLISTSIZE 4096
-#define DMABUFFERSIZE 4096
-#define MAXRXFRAMES 7
-
-typedef struct _DMABUFFERENTRY
-{
-	u32 phys_addr;	/* 32-bit flat physical address of data buffer */
-	volatile u16 count;	/* buffer size/data count */
-	volatile u16 status;	/* Control/status field */
-	volatile u16 rcc;	/* character count field */
-	u16 reserved;	/* padding required by 16C32 */
-	u32 link;	/* 32-bit flat link to next buffer entry */
-	char *virt_addr;	/* virtual address of data buffer */
-	u32 phys_entry;	/* physical address of this buffer entry */
-	dma_addr_t dma_addr;
-} DMABUFFERENTRY, *DMAPBUFFERENTRY;
-
-/* The queue of BH actions to be performed */
-
-#define BH_RECEIVE  1
-#define BH_TRANSMIT 2
-#define BH_STATUS   4
-
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-struct	_input_signal_events {
-	int	ri_up;	
-	int	ri_down;
-	int	dsr_up;
-	int	dsr_down;
-	int	dcd_up;
-	int	dcd_down;
-	int	cts_up;
-	int	cts_down;
-};
-
-/* transmit holding buffer definitions*/
-#define MAX_TX_HOLDING_BUFFERS 5
-struct tx_holding_buffer {
-	int	buffer_size;
-	unsigned char *	buffer;
-};
-
-
-/*
- * Device instance data structure
- */
- 
-struct mgsl_struct {
-	int			magic;
-	struct tty_port		port;
-	int			line;
-	int                     hw_version;
-	
-	struct mgsl_icount	icount;
-	
-	int			timeout;
-	int			x_char;		/* xon/xoff character */
-	u16			read_status_mask;
-	u16			ignore_status_mask;	
-	unsigned char 		*xmit_buf;
-	int			xmit_head;
-	int			xmit_tail;
-	int			xmit_cnt;
-	
-	wait_queue_head_t	status_event_wait_q;
-	wait_queue_head_t	event_wait_q;
-	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
-	struct mgsl_struct	*next_device;	/* device list link */
-	
-	spinlock_t irq_spinlock;		/* spinlock for synchronizing with ISR */
-	struct work_struct task;		/* task structure for scheduling bh */
-
-	u32 EventMask;			/* event trigger mask */
-	u32 RecordedEvents;		/* pending events */
-
-	u32 max_frame_size;		/* as set by device config */
-
-	u32 pending_bh;
-
-	bool bh_running;		/* Protection from multiple */
-	int isr_overflow;
-	bool bh_requested;
-	
-	int dcd_chkcount;		/* check counts to prevent */
-	int cts_chkcount;		/* too many IRQs if a signal */
-	int dsr_chkcount;		/* is floating */
-	int ri_chkcount;
-
-	char *buffer_list;		/* virtual address of Rx & Tx buffer lists */
-	u32 buffer_list_phys;
-	dma_addr_t buffer_list_dma_addr;
-
-	unsigned int rx_buffer_count;	/* count of total allocated Rx buffers */
-	DMABUFFERENTRY *rx_buffer_list;	/* list of receive buffer entries */
-	unsigned int current_rx_buffer;
-
-	int num_tx_dma_buffers;		/* number of tx dma frames required */
- 	int tx_dma_buffers_used;
-	unsigned int tx_buffer_count;	/* count of total allocated Tx buffers */
-	DMABUFFERENTRY *tx_buffer_list;	/* list of transmit buffer entries */
-	int start_tx_dma_buffer;	/* tx dma buffer to start tx dma operation */
-	int current_tx_buffer;          /* next tx dma buffer to be loaded */
-	
-	unsigned char *intermediate_rxbuffer;
-
-	int num_tx_holding_buffers;	/* number of tx holding buffer allocated */
-	int get_tx_holding_index;  	/* next tx holding buffer for adapter to load */
-	int put_tx_holding_index;  	/* next tx holding buffer to store user request */
-	int tx_holding_count;		/* number of tx holding buffers waiting */
-	struct tx_holding_buffer tx_holding_buffers[MAX_TX_HOLDING_BUFFERS];
-
-	bool rx_enabled;
-	bool rx_overflow;
-	bool rx_rcc_underrun;
-
-	bool tx_enabled;
-	bool tx_active;
-	u32 idle_mode;
-
-	u16 cmr_value;
-	u16 tcsr_value;
-
-	char device_name[25];		/* device instance name */
-
-	unsigned int bus_type;	/* expansion bus type (ISA,EISA,PCI) */
-	unsigned char bus;		/* expansion bus number (zero based) */
-	unsigned char function;		/* PCI device number */
-
-	unsigned int io_base;		/* base I/O address of adapter */
-	unsigned int io_addr_size;	/* size of the I/O address range */
-	bool io_addr_requested;		/* true if I/O address requested */
-	
-	unsigned int irq_level;		/* interrupt level */
-	unsigned long irq_flags;
-	bool irq_requested;		/* true if IRQ requested */
-	
-	unsigned int dma_level;		/* DMA channel */
-	bool dma_requested;		/* true if dma channel requested */
-
-	u16 mbre_bit;
-	u16 loopback_bits;
-	u16 usc_idle_mode;
-
-	MGSL_PARAMS params;		/* communications parameters */
-
-	unsigned char serial_signals;	/* current serial signal states */
-
-	bool irq_occurred;		/* for diagnostics use */
-	unsigned int init_error;	/* Initialization startup error 		(DIAGS)	*/
-	int	fDiagnosticsmode;	/* Driver in Diagnostic mode?			(DIAGS)	*/
-
-	u32 last_mem_alloc;
-	unsigned char* memory_base;	/* shared memory address (PCI only) */
-	u32 phys_memory_base;
-	bool shared_mem_requested;
-
-	unsigned char* lcr_base;	/* local config registers (PCI only) */
-	u32 phys_lcr_base;
-	u32 lcr_offset;
-	bool lcr_mem_requested;
-
-	u32 misc_ctrl_value;
-	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
-	char char_buf[MAX_ASYNC_BUFFER_SIZE];	
-	bool drop_rts_on_tx_done;
-
-	bool loopmode_insert_requested;
-	bool loopmode_send_done_requested;
-	
-	struct	_input_signal_events	input_signal_events;
-
-	/* generic HDLC device parts */
-	int netcount;
-	spinlock_t netlock;
-
-#if SYNCLINK_GENERIC_HDLC
-	struct net_device *netdev;
-#endif
-};
-
-#define MGSL_MAGIC 0x5401
-
-/*
- * The size of the serial xmit buffer is 1 page, or 4096 bytes
- */
-#ifndef SERIAL_XMIT_SIZE
-#define SERIAL_XMIT_SIZE 4096
-#endif
-
-/*
- * These macros define the offsets used in calculating the
- * I/O address of the specified USC registers.
- */
-
-
-#define DCPIN 2		/* Bit 1 of I/O address */
-#define SDPIN 4		/* Bit 2 of I/O address */
-
-#define DCAR 0		/* DMA command/address register */
-#define CCAR SDPIN		/* channel command/address register */
-#define DATAREG DCPIN + SDPIN	/* serial data register */
-#define MSBONLY 0x41
-#define LSBONLY 0x40
-
-/*
- * These macros define the register address (ordinal number)
- * used for writing address/value pairs to the USC.
- */
-
-#define CMR	0x02	/* Channel mode Register */
-#define CCSR	0x04	/* Channel Command/status Register */
-#define CCR	0x06	/* Channel Control Register */
-#define PSR	0x08	/* Port status Register */
-#define PCR	0x0a	/* Port Control Register */
-#define TMDR	0x0c	/* Test mode Data Register */
-#define TMCR	0x0e	/* Test mode Control Register */
-#define CMCR	0x10	/* Clock mode Control Register */
-#define HCR	0x12	/* Hardware Configuration Register */
-#define IVR	0x14	/* Interrupt Vector Register */
-#define IOCR	0x16	/* Input/Output Control Register */
-#define ICR	0x18	/* Interrupt Control Register */
-#define DCCR	0x1a	/* Daisy Chain Control Register */
-#define MISR	0x1c	/* Misc Interrupt status Register */
-#define SICR	0x1e	/* status Interrupt Control Register */
-#define RDR	0x20	/* Receive Data Register */
-#define RMR	0x22	/* Receive mode Register */
-#define RCSR	0x24	/* Receive Command/status Register */
-#define RICR	0x26	/* Receive Interrupt Control Register */
-#define RSR	0x28	/* Receive Sync Register */
-#define RCLR	0x2a	/* Receive count Limit Register */
-#define RCCR	0x2c	/* Receive Character count Register */
-#define TC0R	0x2e	/* Time Constant 0 Register */
-#define TDR	0x30	/* Transmit Data Register */
-#define TMR	0x32	/* Transmit mode Register */
-#define TCSR	0x34	/* Transmit Command/status Register */
-#define TICR	0x36	/* Transmit Interrupt Control Register */
-#define TSR	0x38	/* Transmit Sync Register */
-#define TCLR	0x3a	/* Transmit count Limit Register */
-#define TCCR	0x3c	/* Transmit Character count Register */
-#define TC1R	0x3e	/* Time Constant 1 Register */
-
-
-/*
- * MACRO DEFINITIONS FOR DMA REGISTERS
- */
-
-#define DCR	0x06	/* DMA Control Register (shared) */
-#define DACR	0x08	/* DMA Array count Register (shared) */
-#define BDCR	0x12	/* Burst/Dwell Control Register (shared) */
-#define DIVR	0x14	/* DMA Interrupt Vector Register (shared) */	
-#define DICR	0x18	/* DMA Interrupt Control Register (shared) */
-#define CDIR	0x1a	/* Clear DMA Interrupt Register (shared) */
-#define SDIR	0x1c	/* Set DMA Interrupt Register (shared) */
-
-#define TDMR	0x02	/* Transmit DMA mode Register */
-#define TDIAR	0x1e	/* Transmit DMA Interrupt Arm Register */
-#define TBCR	0x2a	/* Transmit Byte count Register */
-#define TARL	0x2c	/* Transmit Address Register (low) */
-#define TARU	0x2e	/* Transmit Address Register (high) */
-#define NTBCR	0x3a	/* Next Transmit Byte count Register */
-#define NTARL	0x3c	/* Next Transmit Address Register (low) */
-#define NTARU	0x3e	/* Next Transmit Address Register (high) */
-
-#define RDMR	0x82	/* Receive DMA mode Register (non-shared) */
-#define RDIAR	0x9e	/* Receive DMA Interrupt Arm Register */
-#define RBCR	0xaa	/* Receive Byte count Register */
-#define RARL	0xac	/* Receive Address Register (low) */
-#define RARU	0xae	/* Receive Address Register (high) */
-#define NRBCR	0xba	/* Next Receive Byte count Register */
-#define NRARL	0xbc	/* Next Receive Address Register (low) */
-#define NRARU	0xbe	/* Next Receive Address Register (high) */
-
-
-/*
- * MACRO DEFINITIONS FOR MODEM STATUS BITS
- */
-
-#define MODEMSTATUS_DTR 0x80
-#define MODEMSTATUS_DSR 0x40
-#define MODEMSTATUS_RTS 0x20
-#define MODEMSTATUS_CTS 0x10
-#define MODEMSTATUS_RI  0x04
-#define MODEMSTATUS_DCD 0x01
-
-
-/*
- * Channel Command/Address Register (CCAR) Command Codes
- */
-
-#define RTCmd_Null			0x0000
-#define RTCmd_ResetHighestIus		0x1000
-#define RTCmd_TriggerChannelLoadDma	0x2000
-#define RTCmd_TriggerRxDma		0x2800
-#define RTCmd_TriggerTxDma		0x3000
-#define RTCmd_TriggerRxAndTxDma		0x3800
-#define RTCmd_PurgeRxFifo		0x4800
-#define RTCmd_PurgeTxFifo		0x5000
-#define RTCmd_PurgeRxAndTxFifo		0x5800
-#define RTCmd_LoadRcc			0x6800
-#define RTCmd_LoadTcc			0x7000
-#define RTCmd_LoadRccAndTcc		0x7800
-#define RTCmd_LoadTC0			0x8800
-#define RTCmd_LoadTC1			0x9000
-#define RTCmd_LoadTC0AndTC1		0x9800
-#define RTCmd_SerialDataLSBFirst	0xa000
-#define RTCmd_SerialDataMSBFirst	0xa800
-#define RTCmd_SelectBigEndian		0xb000
-#define RTCmd_SelectLittleEndian	0xb800
-
-
-/*
- * DMA Command/Address Register (DCAR) Command Codes
- */
-
-#define DmaCmd_Null			0x0000
-#define DmaCmd_ResetTxChannel		0x1000
-#define DmaCmd_ResetRxChannel		0x1200
-#define DmaCmd_StartTxChannel		0x2000
-#define DmaCmd_StartRxChannel		0x2200
-#define DmaCmd_ContinueTxChannel	0x3000
-#define DmaCmd_ContinueRxChannel	0x3200
-#define DmaCmd_PauseTxChannel		0x4000
-#define DmaCmd_PauseRxChannel		0x4200
-#define DmaCmd_AbortTxChannel		0x5000
-#define DmaCmd_AbortRxChannel		0x5200
-#define DmaCmd_InitTxChannel		0x7000
-#define DmaCmd_InitRxChannel		0x7200
-#define DmaCmd_ResetHighestDmaIus	0x8000
-#define DmaCmd_ResetAllChannels		0x9000
-#define DmaCmd_StartAllChannels		0xa000
-#define DmaCmd_ContinueAllChannels	0xb000
-#define DmaCmd_PauseAllChannels		0xc000
-#define DmaCmd_AbortAllChannels		0xd000
-#define DmaCmd_InitAllChannels		0xf000
-
-#define TCmd_Null			0x0000
-#define TCmd_ClearTxCRC			0x2000
-#define TCmd_SelectTicrTtsaData		0x4000
-#define TCmd_SelectTicrTxFifostatus	0x5000
-#define TCmd_SelectTicrIntLevel		0x6000
-#define TCmd_SelectTicrdma_level		0x7000
-#define TCmd_SendFrame			0x8000
-#define TCmd_SendAbort			0x9000
-#define TCmd_EnableDleInsertion		0xc000
-#define TCmd_DisableDleInsertion	0xd000
-#define TCmd_ClearEofEom		0xe000
-#define TCmd_SetEofEom			0xf000
-
-#define RCmd_Null			0x0000
-#define RCmd_ClearRxCRC			0x2000
-#define RCmd_EnterHuntmode		0x3000
-#define RCmd_SelectRicrRtsaData		0x4000
-#define RCmd_SelectRicrRxFifostatus	0x5000
-#define RCmd_SelectRicrIntLevel		0x6000
-#define RCmd_SelectRicrdma_level		0x7000
-
-/*
- * Bits for enabling and disabling IRQs in Interrupt Control Register (ICR)
- */
- 
-#define RECEIVE_STATUS		BIT5
-#define RECEIVE_DATA		BIT4
-#define TRANSMIT_STATUS		BIT3
-#define TRANSMIT_DATA		BIT2
-#define IO_PIN			BIT1
-#define MISC			BIT0
-
-
-/*
- * Receive status Bits in Receive Command/status Register RCSR
- */
-
-#define RXSTATUS_SHORT_FRAME		BIT8
-#define RXSTATUS_CODE_VIOLATION		BIT8
-#define RXSTATUS_EXITED_HUNT		BIT7
-#define RXSTATUS_IDLE_RECEIVED		BIT6
-#define RXSTATUS_BREAK_RECEIVED		BIT5
-#define RXSTATUS_ABORT_RECEIVED		BIT5
-#define RXSTATUS_RXBOUND		BIT4
-#define RXSTATUS_CRC_ERROR		BIT3
-#define RXSTATUS_FRAMING_ERROR		BIT3
-#define RXSTATUS_ABORT			BIT2
-#define RXSTATUS_PARITY_ERROR		BIT2
-#define RXSTATUS_OVERRUN		BIT1
-#define RXSTATUS_DATA_AVAILABLE		BIT0
-#define RXSTATUS_ALL			0x01f6
-#define usc_UnlatchRxstatusBits(a,b) usc_OutReg( (a), RCSR, (u16)((b) & RXSTATUS_ALL) )
-
-/*
- * Values for setting transmit idle mode in 
- * Transmit Control/status Register (TCSR)
- */
-#define IDLEMODE_FLAGS			0x0000
-#define IDLEMODE_ALT_ONE_ZERO		0x0100
-#define IDLEMODE_ZERO			0x0200
-#define IDLEMODE_ONE			0x0300
-#define IDLEMODE_ALT_MARK_SPACE		0x0500
-#define IDLEMODE_SPACE			0x0600
-#define IDLEMODE_MARK			0x0700
-#define IDLEMODE_MASK			0x0700
-
-/*
- * IUSC revision identifiers
- */
-#define	IUSC_SL1660			0x4d44
-#define IUSC_PRE_SL1660			0x4553
-
-/*
- * Transmit status Bits in Transmit Command/status Register (TCSR)
- */
-
-#define TCSR_PRESERVE			0x0F00
-
-#define TCSR_UNDERWAIT			BIT11
-#define TXSTATUS_PREAMBLE_SENT		BIT7
-#define TXSTATUS_IDLE_SENT		BIT6
-#define TXSTATUS_ABORT_SENT		BIT5
-#define TXSTATUS_EOF_SENT		BIT4
-#define TXSTATUS_EOM_SENT		BIT4
-#define TXSTATUS_CRC_SENT		BIT3
-#define TXSTATUS_ALL_SENT		BIT2
-#define TXSTATUS_UNDERRUN		BIT1
-#define TXSTATUS_FIFO_EMPTY		BIT0
-#define TXSTATUS_ALL			0x00fa
-#define usc_UnlatchTxstatusBits(a,b) usc_OutReg( (a), TCSR, (u16)((a)->tcsr_value + ((b) & 0x00FF)) )
-				
-
-#define MISCSTATUS_RXC_LATCHED		BIT15
-#define MISCSTATUS_RXC			BIT14
-#define MISCSTATUS_TXC_LATCHED		BIT13
-#define MISCSTATUS_TXC			BIT12
-#define MISCSTATUS_RI_LATCHED		BIT11
-#define MISCSTATUS_RI			BIT10
-#define MISCSTATUS_DSR_LATCHED		BIT9
-#define MISCSTATUS_DSR			BIT8
-#define MISCSTATUS_DCD_LATCHED		BIT7
-#define MISCSTATUS_DCD			BIT6
-#define MISCSTATUS_CTS_LATCHED		BIT5
-#define MISCSTATUS_CTS			BIT4
-#define MISCSTATUS_RCC_UNDERRUN		BIT3
-#define MISCSTATUS_DPLL_NO_SYNC		BIT2
-#define MISCSTATUS_BRG1_ZERO		BIT1
-#define MISCSTATUS_BRG0_ZERO		BIT0
-
-#define usc_UnlatchIostatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0xaaa0))
-#define usc_UnlatchMiscstatusBits(a,b) usc_OutReg((a),MISR,(u16)((b) & 0x000f))
-
-#define SICR_RXC_ACTIVE			BIT15
-#define SICR_RXC_INACTIVE		BIT14
-#define SICR_RXC			(BIT15+BIT14)
-#define SICR_TXC_ACTIVE			BIT13
-#define SICR_TXC_INACTIVE		BIT12
-#define SICR_TXC			(BIT13+BIT12)
-#define SICR_RI_ACTIVE			BIT11
-#define SICR_RI_INACTIVE		BIT10
-#define SICR_RI				(BIT11+BIT10)
-#define SICR_DSR_ACTIVE			BIT9
-#define SICR_DSR_INACTIVE		BIT8
-#define SICR_DSR			(BIT9+BIT8)
-#define SICR_DCD_ACTIVE			BIT7
-#define SICR_DCD_INACTIVE		BIT6
-#define SICR_DCD			(BIT7+BIT6)
-#define SICR_CTS_ACTIVE			BIT5
-#define SICR_CTS_INACTIVE		BIT4
-#define SICR_CTS			(BIT5+BIT4)
-#define SICR_RCC_UNDERFLOW		BIT3
-#define SICR_DPLL_NO_SYNC		BIT2
-#define SICR_BRG1_ZERO			BIT1
-#define SICR_BRG0_ZERO			BIT0
-
-void usc_DisableMasterIrqBit( struct mgsl_struct *info );
-void usc_EnableMasterIrqBit( struct mgsl_struct *info );
-void usc_EnableInterrupts( struct mgsl_struct *info, u16 IrqMask );
-void usc_DisableInterrupts( struct mgsl_struct *info, u16 IrqMask );
-void usc_ClearIrqPendingBits( struct mgsl_struct *info, u16 IrqMask );
-
-#define usc_EnableInterrupts( a, b ) \
-	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0xc0 + (b)) )
-
-#define usc_DisableInterrupts( a, b ) \
-	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0xff00) + 0x80 + (b)) )
-
-#define usc_EnableMasterIrqBit(a) \
-	usc_OutReg( (a), ICR, (u16)((usc_InReg((a),ICR) & 0x0f00) + 0xb000) )
-
-#define usc_DisableMasterIrqBit(a) \
-	usc_OutReg( (a), ICR, (u16)(usc_InReg((a),ICR) & 0x7f00) )
-
-#define usc_ClearIrqPendingBits( a, b ) usc_OutReg( (a), DCCR, 0x40 + (b) )
-
-/*
- * Transmit status Bits in Transmit Control status Register (TCSR)
- * and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0)
- */
-
-#define TXSTATUS_PREAMBLE_SENT	BIT7
-#define TXSTATUS_IDLE_SENT	BIT6
-#define TXSTATUS_ABORT_SENT	BIT5
-#define TXSTATUS_EOF		BIT4
-#define TXSTATUS_CRC_SENT	BIT3
-#define TXSTATUS_ALL_SENT	BIT2
-#define TXSTATUS_UNDERRUN	BIT1
-#define TXSTATUS_FIFO_EMPTY	BIT0
-
-#define DICR_MASTER		BIT15
-#define DICR_TRANSMIT		BIT0
-#define DICR_RECEIVE		BIT1
-
-#define usc_EnableDmaInterrupts(a,b) \
-	usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) | (b)) )
-
-#define usc_DisableDmaInterrupts(a,b) \
-	usc_OutDmaReg( (a), DICR, (u16)(usc_InDmaReg((a),DICR) & ~(b)) )
-
-#define usc_EnableStatusIrqs(a,b) \
-	usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) | (b)) )
-
-#define usc_DisablestatusIrqs(a,b) \
-	usc_OutReg( (a), SICR, (u16)(usc_InReg((a),SICR) & ~(b)) )
-
-/* Transmit status Bits in Transmit Control status Register (TCSR) */
-/* and Transmit Interrupt Control Register (TICR) (except BIT2, BIT0) */
-
-
-#define DISABLE_UNCONDITIONAL    0
-#define DISABLE_END_OF_FRAME     1
-#define ENABLE_UNCONDITIONAL     2
-#define ENABLE_AUTO_CTS          3
-#define ENABLE_AUTO_DCD          3
-#define usc_EnableTransmitter(a,b) \
-	usc_OutReg( (a), TMR, (u16)((usc_InReg((a),TMR) & 0xfffc) | (b)) )
-#define usc_EnableReceiver(a,b) \
-	usc_OutReg( (a), RMR, (u16)((usc_InReg((a),RMR) & 0xfffc) | (b)) )
-
-static u16  usc_InDmaReg( struct mgsl_struct *info, u16 Port );
-static void usc_OutDmaReg( struct mgsl_struct *info, u16 Port, u16 Value );
-static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd );
-
-static u16  usc_InReg( struct mgsl_struct *info, u16 Port );
-static void usc_OutReg( struct mgsl_struct *info, u16 Port, u16 Value );
-static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd );
-void usc_RCmd( struct mgsl_struct *info, u16 Cmd );
-void usc_TCmd( struct mgsl_struct *info, u16 Cmd );
-
-#define usc_TCmd(a,b) usc_OutReg((a), TCSR, (u16)((a)->tcsr_value + (b)))
-#define usc_RCmd(a,b) usc_OutReg((a), RCSR, (b))
-
-#define usc_SetTransmitSyncChars(a,s0,s1) usc_OutReg((a), TSR, (u16)(((u16)s0<<8)|(u16)s1))
-
-static void usc_process_rxoverrun_sync( struct mgsl_struct *info );
-static void usc_start_receiver( struct mgsl_struct *info );
-static void usc_stop_receiver( struct mgsl_struct *info );
-
-static void usc_start_transmitter( struct mgsl_struct *info );
-static void usc_stop_transmitter( struct mgsl_struct *info );
-static void usc_set_txidle( struct mgsl_struct *info );
-static void usc_load_txfifo( struct mgsl_struct *info );
-
-static void usc_enable_aux_clock( struct mgsl_struct *info, u32 DataRate );
-static void usc_enable_loopback( struct mgsl_struct *info, int enable );
-
-static void usc_get_serial_signals( struct mgsl_struct *info );
-static void usc_set_serial_signals( struct mgsl_struct *info );
-
-static void usc_reset( struct mgsl_struct *info );
-
-static void usc_set_sync_mode( struct mgsl_struct *info );
-static void usc_set_sdlc_mode( struct mgsl_struct *info );
-static void usc_set_async_mode( struct mgsl_struct *info );
-static void usc_enable_async_clock( struct mgsl_struct *info, u32 DataRate );
-
-static void usc_loopback_frame( struct mgsl_struct *info );
-
-static void mgsl_tx_timeout(unsigned long context);
-
-
-static void usc_loopmode_cancel_transmit( struct mgsl_struct * info );
-static void usc_loopmode_insert_request( struct mgsl_struct * info );
-static int usc_loopmode_active( struct mgsl_struct * info);
-static void usc_loopmode_send_done( struct mgsl_struct * info );
-
-static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg);
-
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(struct mgsl_struct *info);
-static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size);
-static int  hdlcdev_init(struct mgsl_struct *info);
-static void hdlcdev_exit(struct mgsl_struct *info);
-#endif
-
-/*
- * Defines a BUS descriptor value for the PCI adapter
- * local bus address ranges.
- */
-
-#define BUS_DESCRIPTOR( WrHold, WrDly, RdDly, Nwdd, Nwad, Nxda, Nrdd, Nrad ) \
-(0x00400020 + \
-((WrHold) << 30) + \
-((WrDly)  << 28) + \
-((RdDly)  << 26) + \
-((Nwdd)   << 20) + \
-((Nwad)   << 15) + \
-((Nxda)   << 13) + \
-((Nrdd)   << 11) + \
-((Nrad)   <<  6) )
-
-static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit);
-
-/*
- * Adapter diagnostic routines
- */
-static bool mgsl_register_test( struct mgsl_struct *info );
-static bool mgsl_irq_test( struct mgsl_struct *info );
-static bool mgsl_dma_test( struct mgsl_struct *info );
-static bool mgsl_memory_test( struct mgsl_struct *info );
-static int mgsl_adapter_test( struct mgsl_struct *info );
-
-/*
- * device and resource management routines
- */
-static int mgsl_claim_resources(struct mgsl_struct *info);
-static void mgsl_release_resources(struct mgsl_struct *info);
-static void mgsl_add_device(struct mgsl_struct *info);
-static struct mgsl_struct* mgsl_allocate_device(void);
-
-/*
- * DMA buffer manupulation functions.
- */
-static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex );
-static bool mgsl_get_rx_frame( struct mgsl_struct *info );
-static bool mgsl_get_raw_rx_frame( struct mgsl_struct *info );
-static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info );
-static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info );
-static int num_free_tx_dma_buffers(struct mgsl_struct *info);
-static void mgsl_load_tx_dma_buffer( struct mgsl_struct *info, const char *Buffer, unsigned int BufferSize);
-static void mgsl_load_pci_memory(char* TargetPtr, const char* SourcePtr, unsigned short count);
-
-/*
- * DMA and Shared Memory buffer allocation and formatting
- */
-static int  mgsl_allocate_dma_buffers(struct mgsl_struct *info);
-static void mgsl_free_dma_buffers(struct mgsl_struct *info);
-static int  mgsl_alloc_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList,int Buffercount);
-static int  mgsl_alloc_buffer_list_memory(struct mgsl_struct *info);
-static void mgsl_free_buffer_list_memory(struct mgsl_struct *info);
-static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info);
-static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info);
-static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info);
-static bool load_next_tx_holding_buffer(struct mgsl_struct *info);
-static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize);
-
-/*
- * Bottom half interrupt handlers
- */
-static void mgsl_bh_handler(struct work_struct *work);
-static void mgsl_bh_receive(struct mgsl_struct *info);
-static void mgsl_bh_transmit(struct mgsl_struct *info);
-static void mgsl_bh_status(struct mgsl_struct *info);
-
-/*
- * Interrupt handler routines and dispatch table.
- */
-static void mgsl_isr_null( struct mgsl_struct *info );
-static void mgsl_isr_transmit_data( struct mgsl_struct *info );
-static void mgsl_isr_receive_data( struct mgsl_struct *info );
-static void mgsl_isr_receive_status( struct mgsl_struct *info );
-static void mgsl_isr_transmit_status( struct mgsl_struct *info );
-static void mgsl_isr_io_pin( struct mgsl_struct *info );
-static void mgsl_isr_misc( struct mgsl_struct *info );
-static void mgsl_isr_receive_dma( struct mgsl_struct *info );
-static void mgsl_isr_transmit_dma( struct mgsl_struct *info );
-
-typedef void (*isr_dispatch_func)(struct mgsl_struct *);
-
-static isr_dispatch_func UscIsrTable[7] =
-{
-	mgsl_isr_null,
-	mgsl_isr_misc,
-	mgsl_isr_io_pin,
-	mgsl_isr_transmit_data,
-	mgsl_isr_transmit_status,
-	mgsl_isr_receive_data,
-	mgsl_isr_receive_status
-};
-
-/*
- * ioctl call handlers
- */
-static int tiocmget(struct tty_struct *tty, struct file *file);
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear);
-static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount
-	__user *user_icount);
-static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS  __user *user_params);
-static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS  __user *new_params);
-static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode);
-static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode);
-static int mgsl_txenable(struct mgsl_struct * info, int enable);
-static int mgsl_txabort(struct mgsl_struct * info);
-static int mgsl_rxenable(struct mgsl_struct * info, int enable);
-static int mgsl_wait_event(struct mgsl_struct * info, int __user *mask);
-static int mgsl_loopmode_send_done( struct mgsl_struct * info );
-
-/* set non-zero on successful registration with PCI subsystem */
-static bool pci_registered;
-
-/*
- * Global linked list of SyncLink devices
- */
-static struct mgsl_struct *mgsl_device_list;
-static int mgsl_device_count;
-
-/*
- * Set this param to non-zero to load eax with the
- * .text section address and breakpoint on module load.
- * This is useful for use with gdb and add-symbol-file command.
- */
-static int break_on_load;
-
-/*
- * Driver major number, defaults to zero to get auto
- * assigned major number. May be forced as module parameter.
- */
-static int ttymajor;
-
-/*
- * Array of user specified options for ISA adapters.
- */
-static int io[MAX_ISA_DEVICES];
-static int irq[MAX_ISA_DEVICES];
-static int dma[MAX_ISA_DEVICES];
-static int debug_level;
-static int maxframe[MAX_TOTAL_DEVICES];
-static int txdmabufs[MAX_TOTAL_DEVICES];
-static int txholdbufs[MAX_TOTAL_DEVICES];
-	
-module_param(break_on_load, bool, 0);
-module_param(ttymajor, int, 0);
-module_param_array(io, int, NULL, 0);
-module_param_array(irq, int, NULL, 0);
-module_param_array(dma, int, NULL, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-module_param_array(txdmabufs, int, NULL, 0);
-module_param_array(txholdbufs, int, NULL, 0);
-
-static char *driver_name = "SyncLink serial driver";
-static char *driver_version = "$Revision: 4.38 $";
-
-static int synclink_init_one (struct pci_dev *dev,
-				     const struct pci_device_id *ent);
-static void synclink_remove_one (struct pci_dev *dev);
-
-static struct pci_device_id synclink_pci_tbl[] = {
-	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_USC, PCI_ANY_ID, PCI_ANY_ID, },
-	{ PCI_VENDOR_ID_MICROGATE, 0x0210, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, synclink_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-static struct pci_driver synclink_pci_driver = {
-	.name		= "synclink",
-	.id_table	= synclink_pci_tbl,
-	.probe		= synclink_init_one,
-	.remove		= __devexit_p(synclink_remove_one),
-};
-
-static struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-
-static void mgsl_change_params(struct mgsl_struct *info);
-static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout);
-
-/*
- * 1st function defined in .text section. Calling this function in
- * init_module() followed by a breakpoint allows a remote debugger
- * (gdb) to get the .text address for the add-symbol-file command.
- * This allows remote debugging of dynamically loadable modules.
- */
-static void* mgsl_get_text_ptr(void)
-{
-	return mgsl_get_text_ptr;
-}
-
-static inline int mgsl_paranoia_check(struct mgsl_struct *info,
-					char *name, const char *routine)
-{
-#ifdef MGSL_PARANOIA_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for mgsl struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null mgsl_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != MGSL_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#else
-	if (!info)
-		return 1;
-#endif
-	return 0;
-}
-
-/**
- * line discipline callback wrappers
- *
- * The wrappers maintain line discipline references
- * while calling into the line discipline.
- *
- * ldisc_receive_buf  - pass receive data to line discipline
- */
-
-static void ldisc_receive_buf(struct tty_struct *tty,
-			      const __u8 *data, char *flags, int count)
-{
-	struct tty_ldisc *ld;
-	if (!tty)
-		return;
-	ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->receive_buf)
-			ld->ops->receive_buf(tty, data, flags, count);
-		tty_ldisc_deref(ld);
-	}
-}
-
-/* mgsl_stop()		throttle (stop) transmitter
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_stop(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_stop"))
-		return;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("mgsl_stop(%s)\n",info->device_name);	
-		
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (info->tx_enabled)
-	 	usc_stop_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-}	/* end of mgsl_stop() */
-
-/* mgsl_start()		release (start) transmitter
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_start(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_start"))
-		return;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("mgsl_start(%s)\n",info->device_name);	
-		
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (!info->tx_enabled)
-	 	usc_start_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-}	/* end of mgsl_start() */
-
-/*
- * Bottom half work queue access functions
- */
-
-/* mgsl_bh_action()	Return next bottom half action to perform.
- * Return Value:	BH action code or 0 if nothing to do.
- */
-static int mgsl_bh_action(struct mgsl_struct *info)
-{
-	unsigned long flags;
-	int rc = 0;
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	if (info->pending_bh & BH_RECEIVE) {
-		info->pending_bh &= ~BH_RECEIVE;
-		rc = BH_RECEIVE;
-	} else if (info->pending_bh & BH_TRANSMIT) {
-		info->pending_bh &= ~BH_TRANSMIT;
-		rc = BH_TRANSMIT;
-	} else if (info->pending_bh & BH_STATUS) {
-		info->pending_bh &= ~BH_STATUS;
-		rc = BH_STATUS;
-	}
-
-	if (!rc) {
-		/* Mark BH routine as complete */
-		info->bh_running = false;
-		info->bh_requested = false;
-	}
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	return rc;
-}
-
-/*
- * 	Perform bottom half processing of work items queued by ISR.
- */
-static void mgsl_bh_handler(struct work_struct *work)
-{
-	struct mgsl_struct *info =
-		container_of(work, struct mgsl_struct, task);
-	int action;
-
-	if (!info)
-		return;
-		
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_handler(%s) entry\n",
-			__FILE__,__LINE__,info->device_name);
-	
-	info->bh_running = true;
-
-	while((action = mgsl_bh_action(info)) != 0) {
-	
-		/* Process work item */
-		if ( debug_level >= DEBUG_LEVEL_BH )
-			printk( "%s(%d):mgsl_bh_handler() work item action=%d\n",
-				__FILE__,__LINE__,action);
-
-		switch (action) {
-		
-		case BH_RECEIVE:
-			mgsl_bh_receive(info);
-			break;
-		case BH_TRANSMIT:
-			mgsl_bh_transmit(info);
-			break;
-		case BH_STATUS:
-			mgsl_bh_status(info);
-			break;
-		default:
-			/* unknown work item ID */
-			printk("Unknown work item ID=%08X!\n", action);
-			break;
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_handler(%s) exit\n",
-			__FILE__,__LINE__,info->device_name);
-}
-
-static void mgsl_bh_receive(struct mgsl_struct *info)
-{
-	bool (*get_rx_frame)(struct mgsl_struct *info) =
-		(info->params.mode == MGSL_MODE_HDLC ? mgsl_get_rx_frame : mgsl_get_raw_rx_frame);
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_receive(%s)\n",
-			__FILE__,__LINE__,info->device_name);
-	
-	do
-	{
-		if (info->rx_rcc_underrun) {
-			unsigned long flags;
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			usc_start_receiver(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			return;
-		}
-	} while(get_rx_frame(info));
-}
-
-static void mgsl_bh_transmit(struct mgsl_struct *info)
-{
-	struct tty_struct *tty = info->port.tty;
-	unsigned long flags;
-	
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_transmit() entry on %s\n",
-			__FILE__,__LINE__,info->device_name);
-
-	if (tty)
-		tty_wakeup(tty);
-
-	/* if transmitter idle and loopmode_send_done_requested
-	 * then start echoing RxD to TxD
-	 */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	if ( !info->tx_active && info->loopmode_send_done_requested )
- 		usc_loopmode_send_done( info );
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-static void mgsl_bh_status(struct mgsl_struct *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):mgsl_bh_status() entry on %s\n",
-			__FILE__,__LINE__,info->device_name);
-
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-}
-
-/* mgsl_isr_receive_status()
- * 
- *	Service a receive status interrupt. The type of status
- *	interrupt is indicated by the state of the RCSR.
- *	This is only used for HDLC mode.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_receive_status( struct mgsl_struct *info )
-{
-	u16 status = usc_InReg( info, RCSR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_receive_status status=%04X\n",
-			__FILE__,__LINE__,status);
-			
- 	if ( (status & RXSTATUS_ABORT_RECEIVED) && 
-		info->loopmode_insert_requested &&
- 		usc_loopmode_active(info) )
- 	{
-		++info->icount.rxabort;
-	 	info->loopmode_insert_requested = false;
- 
- 		/* clear CMR:13 to start echoing RxD to TxD */
-		info->cmr_value &= ~BIT13;
- 		usc_OutReg(info, CMR, info->cmr_value);
- 
-		/* disable received abort irq (no longer required) */
-	 	usc_OutReg(info, RICR,
- 			(usc_InReg(info, RICR) & ~RXSTATUS_ABORT_RECEIVED));
- 	}
-
-	if (status & (RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED)) {
-		if (status & RXSTATUS_EXITED_HUNT)
-			info->icount.exithunt++;
-		if (status & RXSTATUS_IDLE_RECEIVED)
-			info->icount.rxidle++;
-		wake_up_interruptible(&info->event_wait_q);
-	}
-
-	if (status & RXSTATUS_OVERRUN){
-		info->icount.rxover++;
-		usc_process_rxoverrun_sync( info );
-	}
-
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
-	usc_UnlatchRxstatusBits( info, status );
-
-}	/* end of mgsl_isr_receive_status() */
-
-/* mgsl_isr_transmit_status()
- * 
- * 	Service a transmit status interrupt
- *	HDLC mode :end of transmit frame
- *	Async mode:all data is sent
- * 	transmit status is indicated by bits in the TCSR.
- * 
- * Arguments:		info	       pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_transmit_status( struct mgsl_struct *info )
-{
-	u16 status = usc_InReg( info, TCSR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_transmit_status status=%04X\n",
-			__FILE__,__LINE__,status);
-	
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-	usc_UnlatchTxstatusBits( info, status );
-	
-	if ( status & (TXSTATUS_UNDERRUN | TXSTATUS_ABORT_SENT) )
-	{
-		/* finished sending HDLC abort. This may leave	*/
-		/* the TxFifo with data from the aborted frame	*/
-		/* so purge the TxFifo. Also shutdown the DMA	*/
-		/* channel in case there is data remaining in 	*/
-		/* the DMA buffer				*/
- 		usc_DmaCmd( info, DmaCmd_ResetTxChannel );
- 		usc_RTCmd( info, RTCmd_PurgeTxFifo );
-	}
- 
-	if ( status & TXSTATUS_EOF_SENT )
-		info->icount.txok++;
-	else if ( status & TXSTATUS_UNDERRUN )
-		info->icount.txunder++;
-	else if ( status & TXSTATUS_ABORT_SENT )
-		info->icount.txabort++;
-	else
-		info->icount.txunder++;
-			
-	info->tx_active = false;
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	del_timer(&info->tx_timer);	
-	
-	if ( info->drop_rts_on_tx_done ) {
-		usc_get_serial_signals( info );
-		if ( info->serial_signals & SerialSignal_RTS ) {
-			info->serial_signals &= ~SerialSignal_RTS;
-			usc_set_serial_signals( info );
-		}
-		info->drop_rts_on_tx_done = false;
-	}
-
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else 
-#endif
-	{
-		if (info->port.tty->stopped || info->port.tty->hw_stopped) {
-			usc_stop_transmitter(info);
-			return;
-		}
-		info->pending_bh |= BH_TRANSMIT;
-	}
-
-}	/* end of mgsl_isr_transmit_status() */
-
-/* mgsl_isr_io_pin()
- * 
- * 	Service an Input/Output pin interrupt. The type of
- * 	interrupt is indicated by bits in the MISR
- * 	
- * Arguments:		info	       pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_io_pin( struct mgsl_struct *info )
-{
- 	struct	mgsl_icount *icount;
-	u16 status = usc_InReg( info, MISR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_io_pin status=%04X\n",
-			__FILE__,__LINE__,status);
-			
-	usc_ClearIrqPendingBits( info, IO_PIN );
-	usc_UnlatchIostatusBits( info, status );
-
-	if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED |
-	              MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) {
-		icount = &info->icount;
-		/* update input line counters */
-		if (status & MISCSTATUS_RI_LATCHED) {
-			if ((info->ri_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_RI);
-			icount->rng++;
-			if ( status & MISCSTATUS_RI )
-				info->input_signal_events.ri_up++;	
-			else
-				info->input_signal_events.ri_down++;	
-		}
-		if (status & MISCSTATUS_DSR_LATCHED) {
-			if ((info->dsr_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_DSR);
-			icount->dsr++;
-			if ( status & MISCSTATUS_DSR )
-				info->input_signal_events.dsr_up++;
-			else
-				info->input_signal_events.dsr_down++;
-		}
-		if (status & MISCSTATUS_DCD_LATCHED) {
-			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_DCD);
-			icount->dcd++;
-			if (status & MISCSTATUS_DCD) {
-				info->input_signal_events.dcd_up++;
-			} else
-				info->input_signal_events.dcd_down++;
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount) {
-				if (status & MISCSTATUS_DCD)
-					netif_carrier_on(info->netdev);
-				else
-					netif_carrier_off(info->netdev);
-			}
-#endif
-		}
-		if (status & MISCSTATUS_CTS_LATCHED)
-		{
-			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT)
-				usc_DisablestatusIrqs(info,SICR_CTS);
-			icount->cts++;
-			if ( status & MISCSTATUS_CTS )
-				info->input_signal_events.cts_up++;
-			else
-				info->input_signal_events.cts_down++;
-		}
-		wake_up_interruptible(&info->status_event_wait_q);
-		wake_up_interruptible(&info->event_wait_q);
-
-		if ( (info->port.flags & ASYNC_CHECK_CD) && 
-		     (status & MISCSTATUS_DCD_LATCHED) ) {
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s CD now %s...", info->device_name,
-				       (status & MISCSTATUS_DCD) ? "on" : "off");
-			if (status & MISCSTATUS_DCD)
-				wake_up_interruptible(&info->port.open_wait);
-			else {
-				if ( debug_level >= DEBUG_LEVEL_ISR )
-					printk("doing serial hangup...");
-				if (info->port.tty)
-					tty_hangup(info->port.tty);
-			}
-		}
-	
-		if ( (info->port.flags & ASYNC_CTS_FLOW) && 
-		     (status & MISCSTATUS_CTS_LATCHED) ) {
-			if (info->port.tty->hw_stopped) {
-				if (status & MISCSTATUS_CTS) {
-					if ( debug_level >= DEBUG_LEVEL_ISR )
-						printk("CTS tx start...");
-					if (info->port.tty)
-						info->port.tty->hw_stopped = 0;
-					usc_start_transmitter(info);
-					info->pending_bh |= BH_TRANSMIT;
-					return;
-				}
-			} else {
-				if (!(status & MISCSTATUS_CTS)) {
-					if ( debug_level >= DEBUG_LEVEL_ISR )
-						printk("CTS tx stop...");
-					if (info->port.tty)
-						info->port.tty->hw_stopped = 1;
-					usc_stop_transmitter(info);
-				}
-			}
-		}
-	}
-
-	info->pending_bh |= BH_STATUS;
-	
-	/* for diagnostics set IRQ flag */
-	if ( status & MISCSTATUS_TXC_LATCHED ){
-		usc_OutReg( info, SICR,
-			(unsigned short)(usc_InReg(info,SICR) & ~(SICR_TXC_ACTIVE+SICR_TXC_INACTIVE)) );
-		usc_UnlatchIostatusBits( info, MISCSTATUS_TXC_LATCHED );
-		info->irq_occurred = true;
-	}
-
-}	/* end of mgsl_isr_io_pin() */
-
-/* mgsl_isr_transmit_data()
- * 
- * 	Service a transmit data interrupt (async mode only).
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_transmit_data( struct mgsl_struct *info )
-{
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_transmit_data xmit_cnt=%d\n",
-			__FILE__,__LINE__,info->xmit_cnt);
-			
-	usc_ClearIrqPendingBits( info, TRANSMIT_DATA );
-	
-	if (info->port.tty->stopped || info->port.tty->hw_stopped) {
-		usc_stop_transmitter(info);
-		return;
-	}
-	
-	if ( info->xmit_cnt )
-		usc_load_txfifo( info );
-	else
-		info->tx_active = false;
-		
-	if (info->xmit_cnt < WAKEUP_CHARS)
-		info->pending_bh |= BH_TRANSMIT;
-
-}	/* end of mgsl_isr_transmit_data() */
-
-/* mgsl_isr_receive_data()
- * 
- * 	Service a receive data interrupt. This occurs
- * 	when operating in asynchronous interrupt transfer mode.
- *	The receive data FIFO is flushed to the receive data buffers. 
- * 
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_receive_data( struct mgsl_struct *info )
-{
-	int Fifocount;
-	u16 status;
-	int work = 0;
-	unsigned char DataByte;
- 	struct tty_struct *tty = info->port.tty;
- 	struct	mgsl_icount *icount = &info->icount;
-	
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_receive_data\n",
-			__FILE__,__LINE__);
-
-	usc_ClearIrqPendingBits( info, RECEIVE_DATA );
-	
-	/* select FIFO status for RICR readback */
-	usc_RCmd( info, RCmd_SelectRicrRxFifostatus );
-
-	/* clear the Wordstatus bit so that status readback */
-	/* only reflects the status of this byte */
-	usc_OutReg( info, RICR+LSBONLY, (u16)(usc_InReg(info, RICR+LSBONLY) & ~BIT3 ));
-
-	/* flush the receive FIFO */
-
-	while( (Fifocount = (usc_InReg(info,RICR) >> 8)) ) {
-		int flag;
-
-		/* read one byte from RxFIFO */
-		outw( (inw(info->io_base + CCAR) & 0x0780) | (RDR+LSBONLY),
-		      info->io_base + CCAR );
-		DataByte = inb( info->io_base + CCAR );
-
-		/* get the status of the received byte */
-		status = usc_InReg(info, RCSR);
-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) )
-			usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
-		
-		icount->rx++;
-		
-		flag = 0;
-		if ( status & (RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR +
-				RXSTATUS_OVERRUN + RXSTATUS_BREAK_RECEIVED) ) {
-			printk("rxerr=%04X\n",status);					
-			/* update error statistics */
-			if ( status & RXSTATUS_BREAK_RECEIVED ) {
-				status &= ~(RXSTATUS_FRAMING_ERROR + RXSTATUS_PARITY_ERROR);
-				icount->brk++;
-			} else if (status & RXSTATUS_PARITY_ERROR) 
-				icount->parity++;
-			else if (status & RXSTATUS_FRAMING_ERROR)
-				icount->frame++;
-			else if (status & RXSTATUS_OVERRUN) {
-				/* must issue purge fifo cmd before */
-				/* 16C32 accepts more receive chars */
-				usc_RTCmd(info,RTCmd_PurgeRxFifo);
-				icount->overrun++;
-			}
-
-			/* discard char if tty control flags say so */					
-			if (status & info->ignore_status_mask)
-				continue;
-				
-			status &= info->read_status_mask;
-		
-			if (status & RXSTATUS_BREAK_RECEIVED) {
-				flag = TTY_BREAK;
-				if (info->port.flags & ASYNC_SAK)
-					do_SAK(tty);
-			} else if (status & RXSTATUS_PARITY_ERROR)
-				flag = TTY_PARITY;
-			else if (status & RXSTATUS_FRAMING_ERROR)
-				flag = TTY_FRAME;
-		}	/* end of if (error) */
-		tty_insert_flip_char(tty, DataByte, flag);
-		if (status & RXSTATUS_OVERRUN) {
-			/* Overrun is special, since it's
-			 * reported immediately, and doesn't
-			 * affect the current character
-			 */
-			work += tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_ISR ) {
-		printk("%s(%d):rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
-			__FILE__,__LINE__,icount->rx,icount->brk,
-			icount->parity,icount->frame,icount->overrun);
-	}
-			
-	if(work)
-		tty_flip_buffer_push(tty);
-}
-
-/* mgsl_isr_misc()
- * 
- * 	Service a miscellaneous interrupt source.
- * 	
- * Arguments:		info		pointer to device extension (instance data)
- * Return Value:	None
- */
-static void mgsl_isr_misc( struct mgsl_struct *info )
-{
-	u16 status = usc_InReg( info, MISR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_misc status=%04X\n",
-			__FILE__,__LINE__,status);
-			
-	if ((status & MISCSTATUS_RCC_UNDERRUN) &&
-	    (info->params.mode == MGSL_MODE_HDLC)) {
-
-		/* turn off receiver and rx DMA */
-		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
-		usc_DmaCmd(info, DmaCmd_ResetRxChannel);
-		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
-		usc_DisableInterrupts(info, RECEIVE_DATA + RECEIVE_STATUS);
-
-		/* schedule BH handler to restart receiver */
-		info->pending_bh |= BH_RECEIVE;
-		info->rx_rcc_underrun = true;
-	}
-
-	usc_ClearIrqPendingBits( info, MISC );
-	usc_UnlatchMiscstatusBits( info, status );
-
-}	/* end of mgsl_isr_misc() */
-
-/* mgsl_isr_null()
- *
- * 	Services undefined interrupt vectors from the
- * 	USC. (hence this function SHOULD never be called)
- * 
- * Arguments:		info		pointer to device extension (instance data)
- * Return Value:	None
- */
-static void mgsl_isr_null( struct mgsl_struct *info )
-{
-
-}	/* end of mgsl_isr_null() */
-
-/* mgsl_isr_receive_dma()
- * 
- * 	Service a receive DMA channel interrupt.
- * 	For this driver there are two sources of receive DMA interrupts
- * 	as identified in the Receive DMA mode Register (RDMR):
- * 
- * 	BIT3	EOA/EOL		End of List, all receive buffers in receive
- * 				buffer list have been filled (no more free buffers
- * 				available). The DMA controller has shut down.
- * 
- * 	BIT2	EOB		End of Buffer. This interrupt occurs when a receive
- * 				DMA buffer is terminated in response to completion
- * 				of a good frame or a frame with errors. The status
- * 				of the frame is stored in the buffer entry in the
- * 				list of receive buffer entries.
- * 
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_receive_dma( struct mgsl_struct *info )
-{
-	u16 status;
-	
-	/* clear interrupt pending and IUS bit for Rx DMA IRQ */
-	usc_OutDmaReg( info, CDIR, BIT9+BIT1 );
-
-	/* Read the receive DMA status to identify interrupt type. */
-	/* This also clears the status bits. */
-	status = usc_InDmaReg( info, RDMR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk("%s(%d):mgsl_isr_receive_dma(%s) status=%04X\n",
-			__FILE__,__LINE__,info->device_name,status);
-			
-	info->pending_bh |= BH_RECEIVE;
-	
-	if ( status & BIT3 ) {
-		info->rx_overflow = true;
-		info->icount.buf_overrun++;
-	}
-
-}	/* end of mgsl_isr_receive_dma() */
-
-/* mgsl_isr_transmit_dma()
- *
- *	This function services a transmit DMA channel interrupt.
- *
- *	For this driver there is one source of transmit DMA interrupts
- *	as identified in the Transmit DMA Mode Register (TDMR):
- *
- *     	BIT2  EOB       End of Buffer. This interrupt occurs when a
- *     			transmit DMA buffer has been emptied.
- *
- *     	The driver maintains enough transmit DMA buffers to hold at least
- *     	one max frame size transmit frame. When operating in a buffered
- *     	transmit mode, there may be enough transmit DMA buffers to hold at
- *     	least two or more max frame size frames. On an EOB condition,
- *     	determine if there are any queued transmit buffers and copy into
- *     	transmit DMA buffers if we have room.
- *
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_isr_transmit_dma( struct mgsl_struct *info )
-{
-	u16 status;
-
-	/* clear interrupt pending and IUS bit for Tx DMA IRQ */
-	usc_OutDmaReg(info, CDIR, BIT8+BIT0 );
-
-	/* Read the transmit DMA status to identify interrupt type. */
-	/* This also clears the status bits. */
-
-	status = usc_InDmaReg( info, TDMR );
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):mgsl_isr_transmit_dma(%s) status=%04X\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	if ( status & BIT2 ) {
-		--info->tx_dma_buffers_used;
-
-		/* if there are transmit frames queued,
-		 *  try to load the next one
-		 */
-		if ( load_next_tx_holding_buffer(info) ) {
-			/* if call returns non-zero value, we have
-			 * at least one free tx holding buffer
-			 */
-			info->pending_bh |= BH_TRANSMIT;
-		}
-	}
-
-}	/* end of mgsl_isr_transmit_dma() */
-
-/* mgsl_interrupt()
- * 
- * 	Interrupt service routine entry point.
- * 	
- * Arguments:
- * 
- * 	irq		interrupt number that caused interrupt
- * 	dev_id		device ID supplied during interrupt registration
- * 	
- * Return Value: None
- */
-static irqreturn_t mgsl_interrupt(int dummy, void *dev_id)
-{
-	struct mgsl_struct *info = dev_id;
-	u16 UscVector;
-	u16 DmaVector;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)entry.\n",
-			__FILE__, __LINE__, info->irq_level);
-
-	spin_lock(&info->irq_spinlock);
-
-	for(;;) {
-		/* Read the interrupt vectors from hardware. */
-		UscVector = usc_InReg(info, IVR) >> 9;
-		DmaVector = usc_InDmaReg(info, DIVR);
-		
-		if ( debug_level >= DEBUG_LEVEL_ISR )	
-			printk("%s(%d):%s UscVector=%08X DmaVector=%08X\n",
-				__FILE__,__LINE__,info->device_name,UscVector,DmaVector);
-			
-		if ( !UscVector && !DmaVector )
-			break;
-			
-		/* Dispatch interrupt vector */
-		if ( UscVector )
-			(*UscIsrTable[UscVector])(info);
-		else if ( (DmaVector&(BIT10|BIT9)) == BIT10)
-			mgsl_isr_transmit_dma(info);
-		else
-			mgsl_isr_receive_dma(info);
-
-		if ( info->isr_overflow ) {
-			printk(KERN_ERR "%s(%d):%s isr overflow irq=%d\n",
-				__FILE__, __LINE__, info->device_name, info->irq_level);
-			usc_DisableMasterIrqBit(info);
-			usc_DisableDmaInterrupts(info,DICR_MASTER);
-			break;
-		}
-	}
-	
-	/* Request bottom half processing if there's something 
-	 * for it to do and the bh is not already running
-	 */
-
-	if ( info->pending_bh && !info->bh_running && !info->bh_requested ) {
-		if ( debug_level >= DEBUG_LEVEL_ISR )	
-			printk("%s(%d):%s queueing bh task.\n",
-				__FILE__,__LINE__,info->device_name);
-		schedule_work(&info->task);
-		info->bh_requested = true;
-	}
-
-	spin_unlock(&info->irq_spinlock);
-	
-	if ( debug_level >= DEBUG_LEVEL_ISR )	
-		printk(KERN_DEBUG "%s(%d):mgsl_interrupt(%d)exit.\n",
-			__FILE__, __LINE__, info->irq_level);
-
-	return IRQ_HANDLED;
-}	/* end of mgsl_interrupt() */
-
-/* startup()
- * 
- * 	Initialize and start device.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise error code
- */
-static int startup(struct mgsl_struct * info)
-{
-	int retval = 0;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):mgsl_startup(%s)\n",__FILE__,__LINE__,info->device_name);
-		
-	if (info->port.flags & ASYNC_INITIALIZED)
-		return 0;
-	
-	if (!info->xmit_buf) {
-		/* allocate a page of memory for a transmit buffer */
-		info->xmit_buf = (unsigned char *)get_zeroed_page(GFP_KERNEL);
-		if (!info->xmit_buf) {
-			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
-				__FILE__,__LINE__,info->device_name);
-			return -ENOMEM;
-		}
-	}
-
-	info->pending_bh = 0;
-	
-	memset(&info->icount, 0, sizeof(info->icount));
-
-	setup_timer(&info->tx_timer, mgsl_tx_timeout, (unsigned long)info);
-	
-	/* Allocate and claim adapter resources */
-	retval = mgsl_claim_resources(info);
-	
-	/* perform existence check and diagnostics */
-	if ( !retval )
-		retval = mgsl_adapter_test(info);
-		
-	if ( retval ) {
-  		if (capable(CAP_SYS_ADMIN) && info->port.tty)
-			set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-		mgsl_release_resources(info);
-  		return retval;
-  	}
-
-	/* program hardware for current parameters */
-	mgsl_change_params(info);
-	
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags |= ASYNC_INITIALIZED;
-	
-	return 0;
-	
-}	/* end of startup() */
-
-/* shutdown()
- *
- * Called by mgsl_close() and mgsl_hangup() to shutdown hardware
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void shutdown(struct mgsl_struct * info)
-{
-	unsigned long flags;
-	
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_shutdown(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	/* clear status wait queue because status changes */
-	/* can't happen after shutting down the hardware */
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-
-	del_timer_sync(&info->tx_timer);
-
-	if (info->xmit_buf) {
-		free_page((unsigned long) info->xmit_buf);
-		info->xmit_buf = NULL;
-	}
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_DisableMasterIrqBit(info);
-	usc_stop_receiver(info);
-	usc_stop_transmitter(info);
-	usc_DisableInterrupts(info,RECEIVE_DATA + RECEIVE_STATUS +
-		TRANSMIT_DATA + TRANSMIT_STATUS + IO_PIN + MISC );
-	usc_DisableDmaInterrupts(info,DICR_MASTER + DICR_TRANSMIT + DICR_RECEIVE);
-	
-	/* Disable DMAEN (Port 7, Bit 14) */
-	/* This disconnects the DMA request signal from the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) | BIT14));
-	
-	/* Disable INTEN (Port 6, Bit12) */
-	/* This disconnects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) | BIT12));
-	
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
- 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		usc_set_serial_signals(info);
-	}
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	mgsl_release_resources(info);	
-	
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-	
-}	/* end of shutdown() */
-
-static void mgsl_program_hw(struct mgsl_struct *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
-	usc_stop_receiver(info);
-	usc_stop_transmitter(info);
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	
-	if (info->params.mode == MGSL_MODE_HDLC ||
-	    info->params.mode == MGSL_MODE_RAW ||
-	    info->netcount)
-		usc_set_sync_mode(info);
-	else
-		usc_set_async_mode(info);
-		
-	usc_set_serial_signals(info);
-	
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-
-	usc_EnableStatusIrqs(info,SICR_CTS+SICR_DSR+SICR_DCD+SICR_RI);		
-	usc_EnableInterrupts(info, IO_PIN);
-	usc_get_serial_signals(info);
-		
-	if (info->netcount || info->port.tty->termios->c_cflag & CREAD)
-		usc_start_receiver(info);
-		
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-/* Reconfigure adapter based on new parameters
- */
-static void mgsl_change_params(struct mgsl_struct *info)
-{
-	unsigned cflag;
-	int bits_per_char;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_change_params(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	cflag = info->port.tty->termios->c_cflag;
-
-	/* if B0 rate (hangup) specified then negate DTR and RTS */
-	/* otherwise assert DTR and RTS */
- 	if (cflag & CBAUD)
-		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-	
-	/* byte size and parity */
-	
-	switch (cflag & CSIZE) {
-	      case CS5: info->params.data_bits = 5; break;
-	      case CS6: info->params.data_bits = 6; break;
-	      case CS7: info->params.data_bits = 7; break;
-	      case CS8: info->params.data_bits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  info->params.data_bits = 7; break;
-	      }
-	      
-	if (cflag & CSTOPB)
-		info->params.stop_bits = 2;
-	else
-		info->params.stop_bits = 1;
-
-	info->params.parity = ASYNC_PARITY_NONE;
-	if (cflag & PARENB) {
-		if (cflag & PARODD)
-			info->params.parity = ASYNC_PARITY_ODD;
-		else
-			info->params.parity = ASYNC_PARITY_EVEN;
-#ifdef CMSPAR
-		if (cflag & CMSPAR)
-			info->params.parity = ASYNC_PARITY_SPACE;
-#endif
-	}
-
-	/* calculate number of jiffies to transmit a full
-	 * FIFO (32 bytes) at specified data rate
-	 */
-	bits_per_char = info->params.data_bits + 
-			info->params.stop_bits + 1;
-
-	/* if port data rate is set to 460800 or less then
-	 * allow tty settings to override, otherwise keep the
-	 * current data rate.
-	 */
-	if (info->params.data_rate <= 460800)
-		info->params.data_rate = tty_get_baud_rate(info->port.tty);
-	
-	if ( info->params.data_rate ) {
-		info->timeout = (32*HZ*bits_per_char) / 
-				info->params.data_rate;
-	}
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-		
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/* process tty input control flags */
-	
-	info->read_status_mask = RXSTATUS_OVERRUN;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;
- 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- 		info->read_status_mask |= RXSTATUS_BREAK_RECEIVED;
-	
-	if (I_IGNPAR(info->port.tty))
-		info->ignore_status_mask |= RXSTATUS_PARITY_ERROR | RXSTATUS_FRAMING_ERROR;
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask |= RXSTATUS_BREAK_RECEIVED;
-		/* If ignoring parity and break indicators, ignore 
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty))
-			info->ignore_status_mask |= RXSTATUS_OVERRUN;
-	}
-
-	mgsl_program_hw(info);
-
-}	/* end of mgsl_change_params() */
-
-/* mgsl_put_char()
- * 
- * 	Add a character to the transmit buffer.
- * 	
- * Arguments:		tty	pointer to tty information structure
- * 			ch	character to add to transmit buffer
- * 		
- * Return Value:	None
- */
-static int mgsl_put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (debug_level >= DEBUG_LEVEL_INFO) {
-		printk(KERN_DEBUG "%s(%d):mgsl_put_char(%d) on %s\n",
-			__FILE__, __LINE__, ch, info->device_name);
-	}		
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_put_char"))
-		return 0;
-
-	if (!info->xmit_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->irq_spinlock, flags);
-	
-	if ((info->params.mode == MGSL_MODE_ASYNC ) || !info->tx_active) {
-		if (info->xmit_cnt < SERIAL_XMIT_SIZE - 1) {
-			info->xmit_buf[info->xmit_head++] = ch;
-			info->xmit_head &= SERIAL_XMIT_SIZE-1;
-			info->xmit_cnt++;
-			ret = 1;
-		}
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	return ret;
-	
-}	/* end of mgsl_put_char() */
-
-/* mgsl_flush_chars()
- * 
- * 	Enable transmitter so remaining characters in the
- * 	transmit buffer are sent.
- * 	
- * Arguments:		tty	pointer to tty information structure
- * Return Value:	None
- */
-static void mgsl_flush_chars(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-				
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_flush_chars() entry on %s xmit_cnt=%d\n",
-			__FILE__,__LINE__,info->device_name,info->xmit_cnt);
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_chars"))
-		return;
-
-	if (info->xmit_cnt <= 0 || tty->stopped || tty->hw_stopped ||
-	    !info->xmit_buf)
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_flush_chars() entry on %s starting transmitter\n",
-			__FILE__,__LINE__,info->device_name );
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
-	if (!info->tx_active) {
-		if ( (info->params.mode == MGSL_MODE_HDLC ||
-			info->params.mode == MGSL_MODE_RAW) && info->xmit_cnt ) {
-			/* operating in synchronous (frame oriented) mode */
-			/* copy data from circular xmit_buf to */
-			/* transmit DMA buffer. */
-			mgsl_load_tx_dma_buffer(info,
-				 info->xmit_buf,info->xmit_cnt);
-		}
-	 	usc_start_transmitter(info);
-	}
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-}	/* end of mgsl_flush_chars() */
-
-/* mgsl_write()
- * 
- * 	Send a block of data
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty information structure
- * 	buf		pointer to buffer containing send data
- * 	count		size of send data in bytes
- * 	
- * Return Value:	number of characters written
- */
-static int mgsl_write(struct tty_struct * tty,
-		    const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_write(%s) count=%d\n",
-			__FILE__,__LINE__,info->device_name,count);
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_write"))
-		goto cleanup;
-
-	if (!info->xmit_buf)
-		goto cleanup;
-
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-			info->params.mode == MGSL_MODE_RAW ) {
-		/* operating in synchronous (frame oriented) mode */
-		/* operating in synchronous (frame oriented) mode */
-		if (info->tx_active) {
-
-			if ( info->params.mode == MGSL_MODE_HDLC ) {
-				ret = 0;
-				goto cleanup;
-			}
-			/* transmitter is actively sending data -
-			 * if we have multiple transmit dma and
-			 * holding buffers, attempt to queue this
-			 * frame for transmission at a later time.
-			 */
-			if (info->tx_holding_count >= info->num_tx_holding_buffers ) {
-				/* no tx holding buffers available */
-				ret = 0;
-				goto cleanup;
-			}
-
-			/* queue transmit frame request */
-			ret = count;
-			save_tx_buffer_request(info,buf,count);
-
-			/* if we have sufficient tx dma buffers,
-			 * load the next buffered tx request
-			 */
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			load_next_tx_holding_buffer(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			goto cleanup;
-		}
-	
-		/* if operating in HDLC LoopMode and the adapter  */
-		/* has yet to be inserted into the loop, we can't */
-		/* transmit					  */
-
-		if ( (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) &&
-			!usc_loopmode_active(info) )
-		{
-			ret = 0;
-			goto cleanup;
-		}
-
-		if ( info->xmit_cnt ) {
-			/* Send accumulated from send_char() calls */
-			/* as frame and wait before accepting more data. */
-			ret = 0;
-			
-			/* copy data from circular xmit_buf to */
-			/* transmit DMA buffer. */
-			mgsl_load_tx_dma_buffer(info,
-				info->xmit_buf,info->xmit_cnt);
-			if ( debug_level >= DEBUG_LEVEL_INFO )
-				printk( "%s(%d):mgsl_write(%s) sync xmit_cnt flushing\n",
-					__FILE__,__LINE__,info->device_name);
-		} else {
-			if ( debug_level >= DEBUG_LEVEL_INFO )
-				printk( "%s(%d):mgsl_write(%s) sync transmit accepted\n",
-					__FILE__,__LINE__,info->device_name);
-			ret = count;
-			info->xmit_cnt = count;
-			mgsl_load_tx_dma_buffer(info,buf,count);
-		}
-	} else {
-		while (1) {
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			c = min_t(int, count,
-				min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-				    SERIAL_XMIT_SIZE - info->xmit_head));
-			if (c <= 0) {
-				spin_unlock_irqrestore(&info->irq_spinlock,flags);
-				break;
-			}
-			memcpy(info->xmit_buf + info->xmit_head, buf, c);
-			info->xmit_head = ((info->xmit_head + c) &
-					   (SERIAL_XMIT_SIZE-1));
-			info->xmit_cnt += c;
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			buf += c;
-			count -= c;
-			ret += c;
-		}
-	}	
-	
- 	if (info->xmit_cnt && !tty->stopped && !tty->hw_stopped) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!info->tx_active)
-		 	usc_start_transmitter(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
- 	}
-cleanup:	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_write(%s) returning=%d\n",
-			__FILE__,__LINE__,info->device_name,ret);
-			
-	return ret;
-	
-}	/* end of mgsl_write() */
-
-/* mgsl_write_room()
- *
- *	Return the count of free bytes in transmit buffer
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static int mgsl_write_room(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	int	ret;
-				
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_write_room"))
-		return 0;
-	ret = SERIAL_XMIT_SIZE - info->xmit_cnt - 1;
-	if (ret < 0)
-		ret = 0;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_write_room(%s)=%d\n",
-			 __FILE__,__LINE__, info->device_name,ret );
-			 
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		/* operating in synchronous (frame oriented) mode */
-		if ( info->tx_active )
-			return 0;
-		else
-			return HDLC_MAX_FRAME_SIZE;
-	}
-	
-	return ret;
-	
-}	/* end of mgsl_write_room() */
-
-/* mgsl_chars_in_buffer()
- *
- *	Return the count of bytes in transmit buffer
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static int mgsl_chars_in_buffer(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-			 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_chars_in_buffer(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_chars_in_buffer"))
-		return 0;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_chars_in_buffer(%s)=%d\n",
-			 __FILE__,__LINE__, info->device_name,info->xmit_cnt );
-			 
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		/* operating in synchronous (frame oriented) mode */
-		if ( info->tx_active )
-			return info->max_frame_size;
-		else
-			return 0;
-	}
-			 
-	return info->xmit_cnt;
-}	/* end of mgsl_chars_in_buffer() */
-
-/* mgsl_flush_buffer()
- *
- *	Discard all data in the send buffer
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_flush_buffer(struct tty_struct *tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_flush_buffer(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_flush_buffer"))
-		return;
-		
-	spin_lock_irqsave(&info->irq_spinlock,flags); 
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-	del_timer(&info->tx_timer);	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	tty_wakeup(tty);
-}
-
-/* mgsl_send_xchar()
- *
- *	Send a high-priority XON/XOFF character
- * 	
- * Arguments:		tty	pointer to tty info structure
- *			ch	character to send
- * Return Value:	None
- */
-static void mgsl_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_send_xchar(%s,%d)\n",
-			 __FILE__,__LINE__, info->device_name, ch );
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_send_xchar"))
-		return;
-
-	info->x_char = ch;
-	if (ch) {
-		/* Make sure transmit interrupts are on */
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!info->tx_enabled)
-		 	usc_start_transmitter(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-}	/* end of mgsl_send_xchar() */
-
-/* mgsl_throttle()
- * 
- * 	Signal remote device to throttle send data (our receive data)
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_throttle(struct tty_struct * tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_throttle(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_throttle"))
-		return;
-	
-	if (I_IXOFF(tty))
-		mgsl_send_xchar(tty, STOP_CHAR(tty));
- 
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		info->serial_signals &= ~SerialSignal_RTS;
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-}	/* end of mgsl_throttle() */
-
-/* mgsl_unthrottle()
- * 
- * 	Signal remote device to stop throttling send data (our receive data)
- * 	
- * Arguments:		tty	pointer to tty info structure
- * Return Value:	None
- */
-static void mgsl_unthrottle(struct tty_struct * tty)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_unthrottle(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_unthrottle"))
-		return;
-	
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			mgsl_send_xchar(tty, START_CHAR(tty));
-	}
-	
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		info->serial_signals |= SerialSignal_RTS;
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-	
-}	/* end of mgsl_unthrottle() */
-
-/* mgsl_get_stats()
- * 
- * 	get the current serial parameters information
- *
- * Arguments:	info		pointer to device instance data
- * 		user_icount	pointer to buffer to hold returned stats
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_get_stats(struct mgsl_struct * info, struct mgsl_icount __user *user_icount)
-{
-	int err;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_get_params(%s)\n",
-			 __FILE__,__LINE__, info->device_name);
-			
-	if (!user_icount) {
-		memset(&info->icount, 0, sizeof(info->icount));
-	} else {
-		mutex_lock(&info->port.mutex);
-		COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
-		mutex_unlock(&info->port.mutex);
-		if (err)
-			return -EFAULT;
-	}
-	
-	return 0;
-	
-}	/* end of mgsl_get_stats() */
-
-/* mgsl_get_params()
- * 
- * 	get the current serial parameters information
- *
- * Arguments:	info		pointer to device instance data
- * 		user_params	pointer to buffer to hold returned params
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_get_params(struct mgsl_struct * info, MGSL_PARAMS __user *user_params)
-{
-	int err;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_get_params(%s)\n",
-			 __FILE__,__LINE__, info->device_name);
-			
-	mutex_lock(&info->port.mutex);
-	COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
-	mutex_unlock(&info->port.mutex);
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):mgsl_get_params(%s) user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-	
-	return 0;
-	
-}	/* end of mgsl_get_params() */
-
-/* mgsl_set_params()
- * 
- * 	set the serial parameters
- * 	
- * Arguments:
- * 
- * 	info		pointer to device instance data
- * 	new_params	user buffer containing new serial params
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_set_params(struct mgsl_struct * info, MGSL_PARAMS __user *new_params)
-{
- 	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-	int err;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_set_params %s\n", __FILE__,__LINE__,
-			info->device_name );
-	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):mgsl_set_params(%s) user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-	
-	mutex_lock(&info->port.mutex);
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
- 	mgsl_change_params(info);
-	mutex_unlock(&info->port.mutex);
-	
-	return 0;
-	
-}	/* end of mgsl_set_params() */
-
-/* mgsl_get_txidle()
- * 
- * 	get the current transmit idle mode
- *
- * Arguments:	info		pointer to device instance data
- * 		idle_mode	pointer to buffer to hold returned idle mode
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_get_txidle(struct mgsl_struct * info, int __user *idle_mode)
-{
-	int err;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_get_txidle(%s)=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->idle_mode);
-			
-	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):mgsl_get_txidle(%s) user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-	
-	return 0;
-	
-}	/* end of mgsl_get_txidle() */
-
-/* mgsl_set_txidle()	service ioctl to set transmit idle mode
- * 	
- * Arguments:	 	info		pointer to device instance data
- * 			idle_mode	new idle mode
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_set_txidle(struct mgsl_struct * info, int idle_mode)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_set_txidle(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, idle_mode );
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	info->idle_mode = idle_mode;
-	usc_set_txidle( info );
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_set_txidle() */
-
-/* mgsl_txenable()
- * 
- * 	enable or disable the transmitter
- * 	
- * Arguments:
- * 
- * 	info		pointer to device instance data
- * 	enable		1 = enable, 0 = disable
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_txenable(struct mgsl_struct * info, int enable)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_txenable(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, enable);
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if ( enable ) {
-		if ( !info->tx_enabled ) {
-
-			usc_start_transmitter(info);
-			/*--------------------------------------------------
-			 * if HDLC/SDLC Loop mode, attempt to insert the
-			 * station in the 'loop' by setting CMR:13. Upon
-			 * receipt of the next GoAhead (RxAbort) sequence,
-			 * the OnLoop indicator (CCSR:7) should go active
-			 * to indicate that we are on the loop
-			 *--------------------------------------------------*/
-			if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
-				usc_loopmode_insert_request( info );
-		}
-	} else {
-		if ( info->tx_enabled )
-			usc_stop_transmitter(info);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_txenable() */
-
-/* mgsl_txabort()	abort send HDLC frame
- * 	
- * Arguments:	 	info		pointer to device instance data
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_txabort(struct mgsl_struct * info)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_txabort(%s)\n", __FILE__,__LINE__,
-			info->device_name);
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC )
-	{
-		if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
-			usc_loopmode_cancel_transmit( info );
-		else
-			usc_TCmd(info,TCmd_SendAbort);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_txabort() */
-
-/* mgsl_rxenable() 	enable or disable the receiver
- * 	
- * Arguments:	 	info		pointer to device instance data
- * 			enable		1 = enable, 0 = disable
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_rxenable(struct mgsl_struct * info, int enable)
-{
- 	unsigned long flags;
- 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_rxenable(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, enable);
-			
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if ( enable ) {
-		if ( !info->rx_enabled )
-			usc_start_receiver(info);
-	} else {
-		if ( info->rx_enabled )
-			usc_stop_receiver(info);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_rxenable() */
-
-/* mgsl_wait_event() 	wait for specified event to occur
- * 	
- * Arguments:	 	info	pointer to device instance data
- * 			mask	pointer to bitmask of events to wait for
- * Return Value:	0 	if successful and bit mask updated with
- *				of events triggerred,
- * 			otherwise error code
- */
-static int mgsl_wait_event(struct mgsl_struct * info, int __user * mask_ptr)
-{
- 	unsigned long flags;
-	int s;
-	int rc=0;
-	struct mgsl_icount cprev, cnow;
-	int events;
-	int mask;
-	struct	_input_signal_events oldsigs, newsigs;
-	DECLARE_WAITQUEUE(wait, current);
-
-	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
-	if (rc) {
-		return  -EFAULT;
-	}
-		 
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_wait_event(%s,%d)\n", __FILE__,__LINE__,
-			info->device_name, mask);
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	/* return immediately if state matches requested events */
-	usc_get_serial_signals(info);
-	s = info->serial_signals;
-	events = mask &
-		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
- 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
-		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
-		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
-	if (events) {
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		goto exit;
-	}
-
-	/* save current irq counts */
-	cprev = info->icount;
-	oldsigs = info->input_signal_events;
-	
-	/* enable hunt and idle irqs if needed */
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		u16 oldreg = usc_InReg(info,RICR);
-		u16 newreg = oldreg +
-			 (mask & MgslEvent_ExitHuntMode ? RXSTATUS_EXITED_HUNT:0) +
-			 (mask & MgslEvent_IdleReceived ? RXSTATUS_IDLE_RECEIVED:0);
-		if (oldreg != newreg)
-			usc_OutReg(info, RICR, newreg);
-	}
-	
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&info->event_wait_q, &wait);
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-			
-		/* get current irq counts */
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		cnow = info->icount;
-		newsigs = info->input_signal_events;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
-		    newsigs.dsr_down == oldsigs.dsr_down &&
-		    newsigs.dcd_up   == oldsigs.dcd_up   &&
-		    newsigs.dcd_down == oldsigs.dcd_down &&
-		    newsigs.cts_up   == oldsigs.cts_up   &&
-		    newsigs.cts_down == oldsigs.cts_down &&
-		    newsigs.ri_up    == oldsigs.ri_up    &&
-		    newsigs.ri_down  == oldsigs.ri_down  &&
-		    cnow.exithunt    == cprev.exithunt   &&
-		    cnow.rxidle      == cprev.rxidle) {
-			rc = -EIO;
-			break;
-		}
-
-		events = mask &
-			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
-			(newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
-			(newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
-			(newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
-			(newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
-			(newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
-			(newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
-			(newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
-			(cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
-			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
-		if (events)
-			break;
-		
-		cprev = cnow;
-		oldsigs = newsigs;
-	}
-	
-	remove_wait_queue(&info->event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		if (!waitqueue_active(&info->event_wait_q)) {
-			/* disable enable exit hunt mode/idle rcvd IRQs */
-			usc_OutReg(info, RICR, usc_InReg(info,RICR) &
-				~(RXSTATUS_EXITED_HUNT + RXSTATUS_IDLE_RECEIVED));
-		}
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-exit:
-	if ( rc == 0 )
-		PUT_USER(rc, events, mask_ptr);
-		
-	return rc;
-	
-}	/* end of mgsl_wait_event() */
-
-static int modem_input_wait(struct mgsl_struct *info,int arg)
-{
- 	unsigned long flags;
-	int rc;
-	struct mgsl_icount cprev, cnow;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* save current irq counts */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	cprev = info->icount;
-	add_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get new irq counts */
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		cnow = info->icount;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-			rc = -EIO;
-			break;
-		}
-
-		/* check for change in caller specified modem input */
-		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
-		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
-		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
-		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
-			rc = 0;
-			break;
-		}
-
-		cprev = cnow;
-	}
-	remove_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-	return rc;
-}
-
-/* return the state of the serial control and status signals
- */
-static int tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned int result;
- 	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
-		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
-		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
-		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
-		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
-		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmget() value=%08X\n",
-			 __FILE__,__LINE__, info->device_name, result );
-	return result;
-}
-
-/* set modem control signals (DTR/RTS)
- */
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	struct mgsl_struct *info = tty->driver_data;
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmset(%x,%x)\n",
-			__FILE__,__LINE__,info->device_name, set, clear);
-
-	if (set & TIOCM_RTS)
-		info->serial_signals |= SerialSignal_RTS;
-	if (set & TIOCM_DTR)
-		info->serial_signals |= SerialSignal_DTR;
-	if (clear & TIOCM_RTS)
-		info->serial_signals &= ~SerialSignal_RTS;
-	if (clear & TIOCM_DTR)
-		info->serial_signals &= ~SerialSignal_DTR;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	usc_set_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return 0;
-}
-
-/* mgsl_break()		Set or clear transmit break condition
- *
- * Arguments:		tty		pointer to tty instance data
- *			break_state	-1=set break condition, 0=clear
- * Return Value:	error code
- */
-static int mgsl_break(struct tty_struct *tty, int break_state)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_break(%s,%d)\n",
-			 __FILE__,__LINE__, info->device_name, break_state);
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
-		return -EINVAL;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	if (break_state == -1)
-		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) | BIT7));
-	else 
-		usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	return 0;
-	
-}	/* end of mgsl_break() */
-
-/*
- * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
- * Return: write counters to the user passed counter struct
- * NB: both 1->0 and 0->1 transitions are counted except for
- *     RI where only 0->1 is counted.
- */
-static int msgl_get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-
-{
-	struct mgsl_struct * info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-	return 0;
-}
-
-/* mgsl_ioctl()	Service an IOCTL request
- * 	
- * Arguments:
- * 
- * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
- * 	cmd	IOCTL command code
- * 	arg	command argument/context
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
-		    unsigned int cmd, unsigned long arg)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
-			info->device_name, cmd );
-	
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	return mgsl_ioctl_common(info, cmd, arg);
-}
-
-static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
-{
-	void __user *argp = (void __user *)arg;
-	
-	switch (cmd) {
-		case MGSL_IOCGPARAMS:
-			return mgsl_get_params(info, argp);
-		case MGSL_IOCSPARAMS:
-			return mgsl_set_params(info, argp);
-		case MGSL_IOCGTXIDLE:
-			return mgsl_get_txidle(info, argp);
-		case MGSL_IOCSTXIDLE:
-			return mgsl_set_txidle(info,(int)arg);
-		case MGSL_IOCTXENABLE:
-			return mgsl_txenable(info,(int)arg);
-		case MGSL_IOCRXENABLE:
-			return mgsl_rxenable(info,(int)arg);
-		case MGSL_IOCTXABORT:
-			return mgsl_txabort(info);
-		case MGSL_IOCGSTATS:
-			return mgsl_get_stats(info, argp);
-		case MGSL_IOCWAITEVENT:
-			return mgsl_wait_event(info, argp);
-		case MGSL_IOCLOOPTXDONE:
-			return mgsl_loopmode_send_done(info);
-		/* Wait for modem input (DCD,RI,DSR,CTS) change
-		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
-		 */
-		case TIOCMIWAIT:
-			return modem_input_wait(info,(int)arg);
-
-		default:
-			return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-/* mgsl_set_termios()
- * 
- * 	Set new termios settings
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty structure
- * 	termios		pointer to buffer to hold returned old termios
- * 	
- * Return Value:		None
- */
-static void mgsl_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct mgsl_struct *info = tty->driver_data;
-	unsigned long flags;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_set_termios %s\n", __FILE__,__LINE__,
-			tty->driver->name );
-	
-	mgsl_change_params(info);
-
-	/* Handle transition to B0 status */
-	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-	
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
-		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) || 
- 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->serial_signals |= SerialSignal_RTS;
- 		}
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-	 	usc_set_serial_signals(info);
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	}
-	
-	/* Handle turning off CRTSCTS */
-	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		mgsl_start(tty);
-	}
-
-}	/* end of mgsl_set_termios() */
-
-/* mgsl_close()
- * 
- * 	Called when port is closed. Wait for remaining data to be
- * 	sent. Disable port and free resources.
- * 	
- * Arguments:
- * 
- * 	tty	pointer to open tty structure
- * 	filp	pointer to open file object
- * 	
- * Return Value:	None
- */
-static void mgsl_close(struct tty_struct *tty, struct file * filp)
-{
-	struct mgsl_struct * info = tty->driver_data;
-
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_close"))
-		return;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_close(%s) entry, count=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->port.count);
-
-	if (tty_port_close_start(&info->port, tty, filp) == 0)			 
-		goto cleanup;
-
-	mutex_lock(&info->port.mutex);
- 	if (info->port.flags & ASYNC_INITIALIZED)
- 		mgsl_wait_until_sent(tty, info->timeout);
-	mgsl_flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	shutdown(info);
-	mutex_unlock(&info->port.mutex);
-
-	tty_port_close_end(&info->port, tty);	
-	info->port.tty = NULL;
-cleanup:			
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_close(%s) exit, count=%d\n", __FILE__,__LINE__,
-			tty->driver->name, info->port.count);
-			
-}	/* end of mgsl_close() */
-
-/* mgsl_wait_until_sent()
- *
- *	Wait until the transmitter is empty.
- *
- * Arguments:
- *
- *	tty		pointer to tty info structure
- *	timeout		time to wait for send completion
- *
- * Return Value:	None
- */
-static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-
-	if (!info )
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_wait_until_sent(%s) entry\n",
-			 __FILE__,__LINE__, info->device_name );
-      
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_wait_until_sent"))
-		return;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		goto exit;
-	 
-	orig_jiffies = jiffies;
-      
-	/* Set check interval to 1/5 of estimated time to
-	 * send a character, and make it at least 1. The check
-	 * interval should also be less than the timeout.
-	 * Note: use tight timings here to satisfy the NIST-PCTS.
-	 */ 
-
-	if ( info->params.data_rate ) {
-	       	char_time = info->timeout/(32 * 5);
-		if (!char_time)
-			char_time++;
-	} else
-		char_time = 1;
-		
-	if (timeout)
-		char_time = min_t(unsigned long, char_time, timeout);
-		
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		while (info->tx_active) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	} else {
-		while (!(usc_InReg(info,TCSR) & TXSTATUS_ALL_SENT) &&
-			info->tx_enabled) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	}
-      
-exit:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_wait_until_sent(%s) exit\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-}	/* end of mgsl_wait_until_sent() */
-
-/* mgsl_hangup()
- *
- *	Called by tty_hangup() when a hangup is signaled.
- *	This is the same as to closing all open files for the port.
- *
- * Arguments:		tty	pointer to associated tty object
- * Return Value:	None
- */
-static void mgsl_hangup(struct tty_struct *tty)
-{
-	struct mgsl_struct * info = tty->driver_data;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_hangup(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_hangup"))
-		return;
-
-	mgsl_flush_buffer(tty);
-	shutdown(info);
-	
-	info->port.count = 0;	
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-
-	wake_up_interruptible(&info->port.open_wait);
-	
-}	/* end of mgsl_hangup() */
-
-/*
- * carrier_raised()
- *
- *	Return true if carrier is raised
- */
-
-static int carrier_raised(struct tty_port *port)
-{
-	unsigned long flags;
-	struct mgsl_struct *info = container_of(port, struct mgsl_struct, port);
-	
-	spin_lock_irqsave(&info->irq_spinlock, flags);
- 	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
-}
-
-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);
-	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);
-}
-
-
-/* block_til_ready()
- * 
- * 	Block the current process until the specified port
- * 	is ready to be opened.
- * 	
- * Arguments:
- * 
- * 	tty		pointer to tty info structure
- * 	filp		pointer to open file object
- * 	info		pointer to device instance data
- * 	
- * Return Value:	0 if success, otherwise error code
- */
-static int block_til_ready(struct tty_struct *tty, struct file * filp,
-			   struct mgsl_struct *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	bool		do_clocal = false;
-	bool		extra_count = false;
-	unsigned long	flags;
-	int		dcd;
-	struct tty_port *port = &info->port;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):block_til_ready on %s\n",
-			 __FILE__,__LINE__, tty->driver->name );
-
-	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-		/* nonblock mode is set or port is not enabled */
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = true;
-
-	/* Wait for carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * mgsl_close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-	 
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):block_til_ready before block on %s count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-
-	spin_lock_irqsave(&info->irq_spinlock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	port->blocked_open++;
-	
-	while (1) {
-		if (tty->termios->c_cflag & CBAUD)
-			tty_port_raise_dtr_rts(port);
-		
-		set_current_state(TASK_INTERRUPTIBLE);
-		
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
-			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-					-EAGAIN : -ERESTARTSYS;
-			break;
-		}
-		
-		dcd = tty_port_carrier_raised(&info->port);
-		
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || dcd))
- 			break;
-			
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-		
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):block_til_ready blocking on %s count=%d\n",
-				 __FILE__,__LINE__, tty->driver->name, port->count );
-				 
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-	
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-	
-	/* FIXME: Racy on hangup during close wait */
-	if (extra_count)
-		port->count++;
-	port->blocked_open--;
-	
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):block_til_ready after blocking on %s count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-			 
-	if (!retval)
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		
-	return retval;
-	
-}	/* end of block_til_ready() */
-
-/* mgsl_open()
- *
- *	Called when a port is opened.  Init and enable port.
- *	Perform serial-specific initialization for the tty structure.
- *
- * Arguments:		tty	pointer to tty info structure
- *			filp	associated file pointer
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int mgsl_open(struct tty_struct *tty, struct file * filp)
-{
-	struct mgsl_struct	*info;
-	int 			retval, line;
-	unsigned long flags;
-
-	/* verify range of specified line number */	
-	line = tty->index;
-	if ((line < 0) || (line >= mgsl_device_count)) {
-		printk("%s(%d):mgsl_open with invalid line #%d.\n",
-			__FILE__,__LINE__,line);
-		return -ENODEV;
-	}
-
-	/* find the info structure for the specified line */
-	info = mgsl_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (mgsl_paranoia_check(info, tty->name, "mgsl_open"))
-		return -ENODEV;
-	
-	tty->driver_data = info;
-	info->port.tty = tty;
-		
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_open(%s), old ref count = %d\n",
-			 __FILE__,__LINE__,tty->driver->name, info->port.count);
-
-	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-		if (info->port.flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->port.close_wait);
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-	
-	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->netcount) {
-		retval = -EBUSY;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		goto cleanup;
-	}
-	info->port.count++;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	if (info->port.count == 1) {
-		/* 1st open on this device, init hardware */
-		retval = startup(info);
-		if (retval < 0)
-			goto cleanup;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):block_til_ready(%s) returned %d\n",
-				 __FILE__,__LINE__, info->device_name, retval);
-		goto cleanup;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):mgsl_open(%s) success\n",
-			 __FILE__,__LINE__, info->device_name);
-	retval = 0;
-	
-cleanup:			
-	if (retval) {
-		if (tty->count == 1)
-			info->port.tty = NULL; /* tty layer will release tty struct */
-		if(info->port.count)
-			info->port.count--;
-	}
-	
-	return retval;
-	
-}	/* end of mgsl_open() */
-
-/*
- * /proc fs routines....
- */
-
-static inline void line_info(struct seq_file *m, struct mgsl_struct *info)
-{
-	char	stat_buf[30];
-	unsigned long flags;
-
-	if (info->bus_type == MGSL_BUS_TYPE_PCI) {
-		seq_printf(m, "%s:PCI io:%04X irq:%d mem:%08X lcr:%08X",
-			info->device_name, info->io_base, info->irq_level,
-			info->phys_memory_base, info->phys_lcr_base);
-	} else {
-		seq_printf(m, "%s:(E)ISA io:%04X irq:%d dma:%d",
-			info->device_name, info->io_base, 
-			info->irq_level, info->dma_level);
-	}
-
-	/* output current serial signal states */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
- 	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (info->serial_signals & SerialSignal_RTS)
-		strcat(stat_buf, "|RTS");
-	if (info->serial_signals & SerialSignal_CTS)
-		strcat(stat_buf, "|CTS");
-	if (info->serial_signals & SerialSignal_DTR)
-		strcat(stat_buf, "|DTR");
-	if (info->serial_signals & SerialSignal_DSR)
-		strcat(stat_buf, "|DSR");
-	if (info->serial_signals & SerialSignal_DCD)
-		strcat(stat_buf, "|CD");
-	if (info->serial_signals & SerialSignal_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->params.mode == MGSL_MODE_HDLC ||
-	    info->params.mode == MGSL_MODE_RAW ) {
-		seq_printf(m, " HDLC txok:%d rxok:%d",
-			      info->icount.txok, info->icount.rxok);
-		if (info->icount.txunder)
-			seq_printf(m, " txunder:%d", info->icount.txunder);
-		if (info->icount.txabort)
-			seq_printf(m, " txabort:%d", info->icount.txabort);
-		if (info->icount.rxshort)
-			seq_printf(m, " rxshort:%d", info->icount.rxshort);
-		if (info->icount.rxlong)
-			seq_printf(m, " rxlong:%d", info->icount.rxlong);
-		if (info->icount.rxover)
-			seq_printf(m, " rxover:%d", info->icount.rxover);
-		if (info->icount.rxcrc)
-			seq_printf(m, " rxcrc:%d", info->icount.rxcrc);
-	} else {
-		seq_printf(m, " ASYNC tx:%d rx:%d",
-			      info->icount.tx, info->icount.rx);
-		if (info->icount.frame)
-			seq_printf(m, " fe:%d", info->icount.frame);
-		if (info->icount.parity)
-			seq_printf(m, " pe:%d", info->icount.parity);
-		if (info->icount.brk)
-			seq_printf(m, " brk:%d", info->icount.brk);
-		if (info->icount.overrun)
-			seq_printf(m, " oe:%d", info->icount.overrun);
-	}
-	
-	/* Append serial signal status to end */
-	seq_printf(m, " %s\n", stat_buf+1);
-	
-	seq_printf(m, "txactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
-	 info->tx_active,info->bh_requested,info->bh_running,
-	 info->pending_bh);
-	 
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	{	
-	u16 Tcsr = usc_InReg( info, TCSR );
-	u16 Tdmr = usc_InDmaReg( info, TDMR );
-	u16 Ticr = usc_InReg( info, TICR );
-	u16 Rscr = usc_InReg( info, RCSR );
-	u16 Rdmr = usc_InDmaReg( info, RDMR );
-	u16 Ricr = usc_InReg( info, RICR );
-	u16 Icr = usc_InReg( info, ICR );
-	u16 Dccr = usc_InReg( info, DCCR );
-	u16 Tmr = usc_InReg( info, TMR );
-	u16 Tccr = usc_InReg( info, TCCR );
-	u16 Ccar = inw( info->io_base + CCAR );
-	seq_printf(m, "tcsr=%04X tdmr=%04X ticr=%04X rcsr=%04X rdmr=%04X\n"
-                        "ricr=%04X icr =%04X dccr=%04X tmr=%04X tccr=%04X ccar=%04X\n",
-	 		Tcsr,Tdmr,Ticr,Rscr,Rdmr,Ricr,Icr,Dccr,Tmr,Tccr,Ccar );
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-}
-
-/* Called to print information about devices */
-static int mgsl_proc_show(struct seq_file *m, void *v)
-{
-	struct mgsl_struct *info;
-	
-	seq_printf(m, "synclink driver:%s\n", driver_version);
-	
-	info = mgsl_device_list;
-	while( info ) {
-		line_info(m, info);
-		info = info->next_device;
-	}
-	return 0;
-}
-
-static int mgsl_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, mgsl_proc_show, NULL);
-}
-
-static const struct file_operations mgsl_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= mgsl_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/* mgsl_allocate_dma_buffers()
- * 
- * 	Allocate and format DMA buffers (ISA adapter)
- * 	or format shared memory buffers (PCI adapter).
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise error
- */
-static int mgsl_allocate_dma_buffers(struct mgsl_struct *info)
-{
-	unsigned short BuffersPerFrame;
-
-	info->last_mem_alloc = 0;
-
-	/* Calculate the number of DMA buffers necessary to hold the */
-	/* largest allowable frame size. Note: If the max frame size is */
-	/* not an even multiple of the DMA buffer size then we need to */
-	/* round the buffer count per frame up one. */
-
-	BuffersPerFrame = (unsigned short)(info->max_frame_size/DMABUFFERSIZE);
-	if ( info->max_frame_size % DMABUFFERSIZE )
-		BuffersPerFrame++;
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/*
-		 * The PCI adapter has 256KBytes of shared memory to use.
-		 * This is 64 PAGE_SIZE buffers.
-		 *
-		 * The first page is used for padding at this time so the
-		 * buffer list does not begin at offset 0 of the PCI
-		 * adapter's shared memory.
-		 *
-		 * The 2nd page is used for the buffer list. A 4K buffer
-		 * list can hold 128 DMA_BUFFER structures at 32 bytes
-		 * each.
-		 *
-		 * This leaves 62 4K pages.
-		 *
-		 * The next N pages are used for transmit frame(s). We
-		 * reserve enough 4K page blocks to hold the required
-		 * number of transmit dma buffers (num_tx_dma_buffers),
-		 * each of MaxFrameSize size.
-		 *
-		 * Of the remaining pages (62-N), determine how many can
-		 * be used to receive full MaxFrameSize inbound frames
-		 */
-		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
-		info->rx_buffer_count = 62 - info->tx_buffer_count;
-	} else {
-		/* Calculate the number of PAGE_SIZE buffers needed for */
-		/* receive and transmit DMA buffers. */
-
-
-		/* Calculate the number of DMA buffers necessary to */
-		/* hold 7 max size receive frames and one max size transmit frame. */
-		/* The receive buffer count is bumped by one so we avoid an */
-		/* End of List condition if all receive buffers are used when */
-		/* using linked list DMA buffers. */
-
-		info->tx_buffer_count = info->num_tx_dma_buffers * BuffersPerFrame;
-		info->rx_buffer_count = (BuffersPerFrame * MAXRXFRAMES) + 6;
-		
-		/* 
-		 * limit total TxBuffers & RxBuffers to 62 4K total 
-		 * (ala PCI Allocation) 
-		 */
-		
-		if ( (info->tx_buffer_count + info->rx_buffer_count) > 62 )
-			info->rx_buffer_count = 62 - info->tx_buffer_count;
-
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):Allocating %d TX and %d RX DMA buffers.\n",
-			__FILE__,__LINE__, info->tx_buffer_count,info->rx_buffer_count);
-	
-	if ( mgsl_alloc_buffer_list_memory( info ) < 0 ||
-		  mgsl_alloc_frame_memory(info, info->rx_buffer_list, info->rx_buffer_count) < 0 || 
-		  mgsl_alloc_frame_memory(info, info->tx_buffer_list, info->tx_buffer_count) < 0 || 
-		  mgsl_alloc_intermediate_rxbuffer_memory(info) < 0  ||
-		  mgsl_alloc_intermediate_txbuffer_memory(info) < 0 ) {
-		printk("%s(%d):Can't allocate DMA buffer memory\n",__FILE__,__LINE__);
-		return -ENOMEM;
-	}
-	
-	mgsl_reset_rx_dma_buffers( info );
-  	mgsl_reset_tx_dma_buffers( info );
-
-	return 0;
-
-}	/* end of mgsl_allocate_dma_buffers() */
-
-/*
- * mgsl_alloc_buffer_list_memory()
- * 
- * Allocate a common DMA buffer for use as the
- * receive and transmit buffer lists.
- * 
- * A buffer list is a set of buffer entries where each entry contains
- * a pointer to an actual buffer and a pointer to the next buffer entry
- * (plus some other info about the buffer).
- * 
- * The buffer entries for a list are built to form a circular list so
- * that when the entire list has been traversed you start back at the
- * beginning.
- * 
- * This function allocates memory for just the buffer entries.
- * The links (pointer to next entry) are filled in with the physical
- * address of the next entry so the adapter can navigate the list
- * using bus master DMA. The pointers to the actual buffers are filled
- * out later when the actual buffers are allocated.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise error
- */
-static int mgsl_alloc_buffer_list_memory( struct mgsl_struct *info )
-{
-	unsigned int i;
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* PCI adapter uses shared memory. */
-		info->buffer_list = info->memory_base + info->last_mem_alloc;
-		info->buffer_list_phys = info->last_mem_alloc;
-		info->last_mem_alloc += BUFFERLISTSIZE;
-	} else {
-		/* ISA adapter uses system memory. */
-		/* The buffer lists are allocated as a common buffer that both */
-		/* the processor and adapter can access. This allows the driver to */
-		/* inspect portions of the buffer while other portions are being */
-		/* updated by the adapter using Bus Master DMA. */
-
-		info->buffer_list = dma_alloc_coherent(NULL, BUFFERLISTSIZE, &info->buffer_list_dma_addr, GFP_KERNEL);
-		if (info->buffer_list == NULL)
-			return -ENOMEM;
-		info->buffer_list_phys = (u32)(info->buffer_list_dma_addr);
-	}
-
-	/* We got the memory for the buffer entry lists. */
-	/* Initialize the memory block to all zeros. */
-	memset( info->buffer_list, 0, BUFFERLISTSIZE );
-
-	/* Save virtual address pointers to the receive and */
-	/* transmit buffer lists. (Receive 1st). These pointers will */
-	/* be used by the processor to access the lists. */
-	info->rx_buffer_list = (DMABUFFERENTRY *)info->buffer_list;
-	info->tx_buffer_list = (DMABUFFERENTRY *)info->buffer_list;
-	info->tx_buffer_list += info->rx_buffer_count;
-
-	/*
-	 * Build the links for the buffer entry lists such that
-	 * two circular lists are built. (Transmit and Receive).
-	 *
-	 * Note: the links are physical addresses
-	 * which are read by the adapter to determine the next
-	 * buffer entry to use.
-	 */
-
-	for ( i = 0; i < info->rx_buffer_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->rx_buffer_list[i].phys_entry =
-			info->buffer_list_phys + (i * sizeof(DMABUFFERENTRY));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-
-		info->rx_buffer_list[i].link = info->buffer_list_phys;
-
-		if ( i < info->rx_buffer_count - 1 )
-			info->rx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY);
-	}
-
-	for ( i = 0; i < info->tx_buffer_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->tx_buffer_list[i].phys_entry = info->buffer_list_phys +
-			((info->rx_buffer_count + i) * sizeof(DMABUFFERENTRY));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-
-		info->tx_buffer_list[i].link = info->buffer_list_phys +
-			info->rx_buffer_count * sizeof(DMABUFFERENTRY);
-
-		if ( i < info->tx_buffer_count - 1 )
-			info->tx_buffer_list[i].link += (i + 1) * sizeof(DMABUFFERENTRY);
-	}
-
-	return 0;
-
-}	/* end of mgsl_alloc_buffer_list_memory() */
-
-/* Free DMA buffers allocated for use as the
- * receive and transmit buffer lists.
- * Warning:
- * 
- * 	The data transfer buffers associated with the buffer list
- * 	MUST be freed before freeing the buffer list itself because
- * 	the buffer list contains the information necessary to free
- * 	the individual buffers!
- */
-static void mgsl_free_buffer_list_memory( struct mgsl_struct *info )
-{
-	if (info->buffer_list && info->bus_type != MGSL_BUS_TYPE_PCI)
-		dma_free_coherent(NULL, BUFFERLISTSIZE, info->buffer_list, info->buffer_list_dma_addr);
-		
-	info->buffer_list = NULL;
-	info->rx_buffer_list = NULL;
-	info->tx_buffer_list = NULL;
-
-}	/* end of mgsl_free_buffer_list_memory() */
-
-/*
- * mgsl_alloc_frame_memory()
- * 
- * 	Allocate the frame DMA buffers used by the specified buffer list.
- * 	Each DMA buffer will be one memory page in size. This is necessary
- * 	because memory can fragment enough that it may be impossible
- * 	contiguous pages.
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 	BufferList	pointer to list of buffer entries
- * 	Buffercount	count of buffer entries in buffer list
- * 
- * Return Value:	0 if success, otherwise -ENOMEM
- */
-static int mgsl_alloc_frame_memory(struct mgsl_struct *info,DMABUFFERENTRY *BufferList,int Buffercount)
-{
-	int i;
-	u32 phys_addr;
-
-	/* Allocate page sized buffers for the receive buffer list */
-
-	for ( i = 0; i < Buffercount; i++ ) {
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-			/* PCI adapter uses shared memory buffers. */
-			BufferList[i].virt_addr = info->memory_base + info->last_mem_alloc;
-			phys_addr = info->last_mem_alloc;
-			info->last_mem_alloc += DMABUFFERSIZE;
-		} else {
-			/* ISA adapter uses system memory. */
-			BufferList[i].virt_addr = dma_alloc_coherent(NULL, DMABUFFERSIZE, &BufferList[i].dma_addr, GFP_KERNEL);
-			if (BufferList[i].virt_addr == NULL)
-				return -ENOMEM;
-			phys_addr = (u32)(BufferList[i].dma_addr);
-		}
-		BufferList[i].phys_addr = phys_addr;
-	}
-
-	return 0;
-
-}	/* end of mgsl_alloc_frame_memory() */
-
-/*
- * mgsl_free_frame_memory()
- * 
- * 	Free the buffers associated with
- * 	each buffer entry of a buffer list.
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 	BufferList	pointer to list of buffer entries
- * 	Buffercount	count of buffer entries in buffer list
- * 
- * Return Value:	None
- */
-static void mgsl_free_frame_memory(struct mgsl_struct *info, DMABUFFERENTRY *BufferList, int Buffercount)
-{
-	int i;
-
-	if ( BufferList ) {
-		for ( i = 0 ; i < Buffercount ; i++ ) {
-			if ( BufferList[i].virt_addr ) {
-				if ( info->bus_type != MGSL_BUS_TYPE_PCI )
-					dma_free_coherent(NULL, DMABUFFERSIZE, BufferList[i].virt_addr, BufferList[i].dma_addr);
-				BufferList[i].virt_addr = NULL;
-			}
-		}
-	}
-
-}	/* end of mgsl_free_frame_memory() */
-
-/* mgsl_free_dma_buffers()
- * 
- * 	Free DMA buffers
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_free_dma_buffers( struct mgsl_struct *info )
-{
-	mgsl_free_frame_memory( info, info->rx_buffer_list, info->rx_buffer_count );
-	mgsl_free_frame_memory( info, info->tx_buffer_list, info->tx_buffer_count );
-	mgsl_free_buffer_list_memory( info );
-
-}	/* end of mgsl_free_dma_buffers() */
-
-
-/*
- * mgsl_alloc_intermediate_rxbuffer_memory()
- * 
- * 	Allocate a buffer large enough to hold max_frame_size. This buffer
- *	is used to pass an assembled frame to the line discipline.
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 
- * Return Value:	0 if success, otherwise -ENOMEM
- */
-static int mgsl_alloc_intermediate_rxbuffer_memory(struct mgsl_struct *info)
-{
-	info->intermediate_rxbuffer = kmalloc(info->max_frame_size, GFP_KERNEL | GFP_DMA);
-	if ( info->intermediate_rxbuffer == NULL )
-		return -ENOMEM;
-
-	return 0;
-
-}	/* end of mgsl_alloc_intermediate_rxbuffer_memory() */
-
-/*
- * mgsl_free_intermediate_rxbuffer_memory()
- * 
- * 
- * Arguments:
- * 
- *	info		pointer to device instance data
- * 
- * Return Value:	None
- */
-static void mgsl_free_intermediate_rxbuffer_memory(struct mgsl_struct *info)
-{
-	kfree(info->intermediate_rxbuffer);
-	info->intermediate_rxbuffer = NULL;
-
-}	/* end of mgsl_free_intermediate_rxbuffer_memory() */
-
-/*
- * mgsl_alloc_intermediate_txbuffer_memory()
- *
- * 	Allocate intermdiate transmit buffer(s) large enough to hold max_frame_size.
- * 	This buffer is used to load transmit frames into the adapter's dma transfer
- * 	buffers when there is sufficient space.
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- *
- * Return Value:	0 if success, otherwise -ENOMEM
- */
-static int mgsl_alloc_intermediate_txbuffer_memory(struct mgsl_struct *info)
-{
-	int i;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s %s(%d)  allocating %d tx holding buffers\n",
-				info->device_name, __FILE__,__LINE__,info->num_tx_holding_buffers);
-
-	memset(info->tx_holding_buffers,0,sizeof(info->tx_holding_buffers));
-
-	for ( i=0; i<info->num_tx_holding_buffers; ++i) {
-		info->tx_holding_buffers[i].buffer =
-			kmalloc(info->max_frame_size, GFP_KERNEL);
-		if (info->tx_holding_buffers[i].buffer == NULL) {
-			for (--i; i >= 0; i--) {
-				kfree(info->tx_holding_buffers[i].buffer);
-				info->tx_holding_buffers[i].buffer = NULL;
-			}
-			return -ENOMEM;
-		}
-	}
-
-	return 0;
-
-}	/* end of mgsl_alloc_intermediate_txbuffer_memory() */
-
-/*
- * mgsl_free_intermediate_txbuffer_memory()
- *
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- *
- * Return Value:	None
- */
-static void mgsl_free_intermediate_txbuffer_memory(struct mgsl_struct *info)
-{
-	int i;
-
-	for ( i=0; i<info->num_tx_holding_buffers; ++i ) {
-		kfree(info->tx_holding_buffers[i].buffer);
-		info->tx_holding_buffers[i].buffer = NULL;
-	}
-
-	info->get_tx_holding_index = 0;
-	info->put_tx_holding_index = 0;
-	info->tx_holding_count = 0;
-
-}	/* end of mgsl_free_intermediate_txbuffer_memory() */
-
-
-/*
- * load_next_tx_holding_buffer()
- *
- * attempts to load the next buffered tx request into the
- * tx dma buffers
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- *
- * Return Value:	true if next buffered tx request loaded
- * 			into adapter's tx dma buffer,
- * 			false otherwise
- */
-static bool load_next_tx_holding_buffer(struct mgsl_struct *info)
-{
-	bool ret = false;
-
-	if ( info->tx_holding_count ) {
-		/* determine if we have enough tx dma buffers
-		 * to accommodate the next tx frame
-		 */
-		struct tx_holding_buffer *ptx =
-			&info->tx_holding_buffers[info->get_tx_holding_index];
-		int num_free = num_free_tx_dma_buffers(info);
-		int num_needed = ptx->buffer_size / DMABUFFERSIZE;
-		if ( ptx->buffer_size % DMABUFFERSIZE )
-			++num_needed;
-
-		if (num_needed <= num_free) {
-			info->xmit_cnt = ptx->buffer_size;
-			mgsl_load_tx_dma_buffer(info,ptx->buffer,ptx->buffer_size);
-
-			--info->tx_holding_count;
-			if ( ++info->get_tx_holding_index >= info->num_tx_holding_buffers)
-				info->get_tx_holding_index=0;
-
-			/* restart transmit timer */
-			mod_timer(&info->tx_timer, jiffies + msecs_to_jiffies(5000));
-
-			ret = true;
-		}
-	}
-
-	return ret;
-}
-
-/*
- * save_tx_buffer_request()
- *
- * attempt to store transmit frame request for later transmission
- *
- * Arguments:
- *
- *	info		pointer to device instance data
- * 	Buffer		pointer to buffer containing frame to load
- * 	BufferSize	size in bytes of frame in Buffer
- *
- * Return Value:	1 if able to store, 0 otherwise
- */
-static int save_tx_buffer_request(struct mgsl_struct *info,const char *Buffer, unsigned int BufferSize)
-{
-	struct tx_holding_buffer *ptx;
-
-	if ( info->tx_holding_count >= info->num_tx_holding_buffers ) {
-		return 0;	        /* all buffers in use */
-	}
-
-	ptx = &info->tx_holding_buffers[info->put_tx_holding_index];
-	ptx->buffer_size = BufferSize;
-	memcpy( ptx->buffer, Buffer, BufferSize);
-
-	++info->tx_holding_count;
-	if ( ++info->put_tx_holding_index >= info->num_tx_holding_buffers)
-		info->put_tx_holding_index=0;
-
-	return 1;
-}
-
-static int mgsl_claim_resources(struct mgsl_struct *info)
-{
-	if (request_region(info->io_base,info->io_addr_size,"synclink") == NULL) {
-		printk( "%s(%d):I/O address conflict on device %s Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->io_base);
-		return -ENODEV;
-	}
-	info->io_addr_requested = true;
-	
-	if ( request_irq(info->irq_level,mgsl_interrupt,info->irq_flags,
-		info->device_name, info ) < 0 ) {
-		printk( "%s(%d):Cant request interrupt on device %s IRQ=%d\n",
-			__FILE__,__LINE__,info->device_name, info->irq_level );
-		goto errout;
-	}
-	info->irq_requested = true;
-	
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		if (request_mem_region(info->phys_memory_base,0x40000,"synclink") == NULL) {
-			printk( "%s(%d):mem addr conflict device %s Addr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_memory_base);
-			goto errout;
-		}
-		info->shared_mem_requested = true;
-		if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclink") == NULL) {
-			printk( "%s(%d):lcr mem addr conflict device %s Addr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_lcr_base + info->lcr_offset);
-			goto errout;
-		}
-		info->lcr_mem_requested = true;
-
-		info->memory_base = ioremap_nocache(info->phys_memory_base,
-								0x40000);
-		if (!info->memory_base) {
-			printk( "%s(%d):Cant map shared memory on device %s MemAddr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-			goto errout;
-		}
-		
-		if ( !mgsl_memory_test(info) ) {
-			printk( "%s(%d):Failed shared memory test %s MemAddr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-			goto errout;
-		}
-		
-		info->lcr_base = ioremap_nocache(info->phys_lcr_base,
-								PAGE_SIZE);
-		if (!info->lcr_base) {
-			printk( "%s(%d):Cant map LCR memory on device %s MemAddr=%08X\n",
-				__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
-			goto errout;
-		}
-		info->lcr_base += info->lcr_offset;
-		
-	} else {
-		/* claim DMA channel */
-		
-		if (request_dma(info->dma_level,info->device_name) < 0){
-			printk( "%s(%d):Cant request DMA channel on device %s DMA=%d\n",
-				__FILE__,__LINE__,info->device_name, info->dma_level );
-			mgsl_release_resources( info );
-			return -ENODEV;
-		}
-		info->dma_requested = true;
-
-		/* ISA adapter uses bus master DMA */		
-		set_dma_mode(info->dma_level,DMA_MODE_CASCADE);
-		enable_dma(info->dma_level);
-	}
-	
-	if ( mgsl_allocate_dma_buffers(info) < 0 ) {
-		printk( "%s(%d):Cant allocate DMA buffers on device %s DMA=%d\n",
-			__FILE__,__LINE__,info->device_name, info->dma_level );
-		goto errout;
-	}	
-	
-	return 0;
-errout:
-	mgsl_release_resources(info);
-	return -ENODEV;
-
-}	/* end of mgsl_claim_resources() */
-
-static void mgsl_release_resources(struct mgsl_struct *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_release_resources(%s) entry\n",
-			__FILE__,__LINE__,info->device_name );
-			
-	if ( info->irq_requested ) {
-		free_irq(info->irq_level, info);
-		info->irq_requested = false;
-	}
-	if ( info->dma_requested ) {
-		disable_dma(info->dma_level);
-		free_dma(info->dma_level);
-		info->dma_requested = false;
-	}
-	mgsl_free_dma_buffers(info);
-	mgsl_free_intermediate_rxbuffer_memory(info);
-     	mgsl_free_intermediate_txbuffer_memory(info);
-	
-	if ( info->io_addr_requested ) {
-		release_region(info->io_base,info->io_addr_size);
-		info->io_addr_requested = false;
-	}
-	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,0x40000);
-		info->shared_mem_requested = false;
-	}
-	if ( info->lcr_mem_requested ) {
-		release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
-		info->lcr_mem_requested = false;
-	}
-	if (info->memory_base){
-		iounmap(info->memory_base);
-		info->memory_base = NULL;
-	}
-	if (info->lcr_base){
-		iounmap(info->lcr_base - info->lcr_offset);
-		info->lcr_base = NULL;
-	}
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_release_resources(%s) exit\n",
-			__FILE__,__LINE__,info->device_name );
-			
-}	/* end of mgsl_release_resources() */
-
-/* mgsl_add_device()
- * 
- * 	Add the specified device instance data structure to the
- * 	global linked list of devices and increment the device count.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_add_device( struct mgsl_struct *info )
-{
-	info->next_device = NULL;
-	info->line = mgsl_device_count;
-	sprintf(info->device_name,"ttySL%d",info->line);
-	
-	if (info->line < MAX_TOTAL_DEVICES) {
-		if (maxframe[info->line])
-			info->max_frame_size = maxframe[info->line];
-
-		if (txdmabufs[info->line]) {
-			info->num_tx_dma_buffers = txdmabufs[info->line];
-			if (info->num_tx_dma_buffers < 1)
-				info->num_tx_dma_buffers = 1;
-		}
-
-		if (txholdbufs[info->line]) {
-			info->num_tx_holding_buffers = txholdbufs[info->line];
-			if (info->num_tx_holding_buffers < 1)
-				info->num_tx_holding_buffers = 1;
-			else if (info->num_tx_holding_buffers > MAX_TX_HOLDING_BUFFERS)
-				info->num_tx_holding_buffers = MAX_TX_HOLDING_BUFFERS;
-		}
-	}
-
-	mgsl_device_count++;
-	
-	if ( !mgsl_device_list )
-		mgsl_device_list = info;
-	else {	
-		struct mgsl_struct *current_dev = mgsl_device_list;
-		while( current_dev->next_device )
-			current_dev = current_dev->next_device;
-		current_dev->next_device = info;
-	}
-	
-	if ( info->max_frame_size < 4096 )
-		info->max_frame_size = 4096;
-	else if ( info->max_frame_size > 65535 )
-		info->max_frame_size = 65535;
-	
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		printk( "SyncLink PCI v%d %s: IO=%04X IRQ=%d Mem=%08X,%08X MaxFrameSize=%u\n",
-			info->hw_version + 1, info->device_name, info->io_base, info->irq_level,
-			info->phys_memory_base, info->phys_lcr_base,
-		     	info->max_frame_size );
-	} else {
-		printk( "SyncLink ISA %s: IO=%04X IRQ=%d DMA=%d MaxFrameSize=%u\n",
-			info->device_name, info->io_base, info->irq_level, info->dma_level,
-		     	info->max_frame_size );
-	}
-
-#if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
-#endif
-
-}	/* end of mgsl_add_device() */
-
-static const struct tty_port_operations mgsl_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-
-/* mgsl_allocate_device()
- * 
- * 	Allocate and initialize a device instance structure
- * 	
- * Arguments:		none
- * Return Value:	pointer to mgsl_struct if success, otherwise NULL
- */
-static struct mgsl_struct* mgsl_allocate_device(void)
-{
-	struct mgsl_struct *info;
-	
-	info = kzalloc(sizeof(struct mgsl_struct),
-		 GFP_KERNEL);
-		 
-	if (!info) {
-		printk("Error can't allocate device instance data\n");
-	} else {
-		tty_port_init(&info->port);
-		info->port.ops = &mgsl_port_ops;
-		info->magic = MGSL_MAGIC;
-		INIT_WORK(&info->task, mgsl_bh_handler);
-		info->max_frame_size = 4096;
-		info->port.close_delay = 5*HZ/10;
-		info->port.closing_wait = 30*HZ;
-		init_waitqueue_head(&info->status_event_wait_q);
-		init_waitqueue_head(&info->event_wait_q);
-		spin_lock_init(&info->irq_spinlock);
-		spin_lock_init(&info->netlock);
-		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;		
-		info->num_tx_dma_buffers = 1;
-		info->num_tx_holding_buffers = 0;
-	}
-	
-	return info;
-
-}	/* end of mgsl_allocate_device()*/
-
-static const struct tty_operations mgsl_ops = {
-	.open = mgsl_open,
-	.close = mgsl_close,
-	.write = mgsl_write,
-	.put_char = mgsl_put_char,
-	.flush_chars = mgsl_flush_chars,
-	.write_room = mgsl_write_room,
-	.chars_in_buffer = mgsl_chars_in_buffer,
-	.flush_buffer = mgsl_flush_buffer,
-	.ioctl = mgsl_ioctl,
-	.throttle = mgsl_throttle,
-	.unthrottle = mgsl_unthrottle,
-	.send_xchar = mgsl_send_xchar,
-	.break_ctl = mgsl_break,
-	.wait_until_sent = mgsl_wait_until_sent,
-	.set_termios = mgsl_set_termios,
-	.stop = mgsl_stop,
-	.start = mgsl_start,
-	.hangup = mgsl_hangup,
-	.tiocmget = tiocmget,
-	.tiocmset = tiocmset,
-	.get_icount = msgl_get_icount,
-	.proc_fops = &mgsl_proc_fops,
-};
-
-/*
- * perform tty device initialization
- */
-static int mgsl_init_tty(void)
-{
-	int rc;
-
-	serial_driver = alloc_tty_driver(128);
-	if (!serial_driver)
-		return -ENOMEM;
-	
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = "synclink";
-	serial_driver->name = "ttySL";
-	serial_driver->major = ttymajor;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->init_termios.c_ispeed = 9600;
-	serial_driver->init_termios.c_ospeed = 9600;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(serial_driver, &mgsl_ops);
-	if ((rc = tty_register_driver(serial_driver)) < 0) {
-		printk("%s(%d):Couldn't register serial driver\n",
-			__FILE__,__LINE__);
-		put_tty_driver(serial_driver);
-		serial_driver = NULL;
-		return rc;
-	}
-			
- 	printk("%s %s, tty major#%d\n",
-		driver_name, driver_version,
-		serial_driver->major);
-	return 0;
-}
-
-/* enumerate user specified ISA adapters
- */
-static void mgsl_enum_isa_devices(void)
-{
-	struct mgsl_struct *info;
-	int i;
-		
-	/* Check for user specified ISA devices */
-	
-	for (i=0 ;(i < MAX_ISA_DEVICES) && io[i] && irq[i]; i++){
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk("ISA device specified io=%04X,irq=%d,dma=%d\n",
-				io[i], irq[i], dma[i] );
-		
-		info = mgsl_allocate_device();
-		if ( !info ) {
-			/* error allocating device instance data */
-			if ( debug_level >= DEBUG_LEVEL_ERROR )
-				printk( "can't allocate device instance data.\n");
-			continue;
-		}
-		
-		/* Copy user configuration info to device instance data */
-		info->io_base = (unsigned int)io[i];
-		info->irq_level = (unsigned int)irq[i];
-		info->irq_level = irq_canonicalize(info->irq_level);
-		info->dma_level = (unsigned int)dma[i];
-		info->bus_type = MGSL_BUS_TYPE_ISA;
-		info->io_addr_size = 16;
-		info->irq_flags = 0;
-		
-		mgsl_add_device( info );
-	}
-}
-
-static void synclink_cleanup(void)
-{
-	int rc;
-	struct mgsl_struct *info;
-	struct mgsl_struct *tmp;
-
-	printk("Unloading %s: %s\n", driver_name, driver_version);
-
-	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
-			printk("%s(%d) failed to unregister tty driver err=%d\n",
-			       __FILE__,__LINE__,rc);
-		put_tty_driver(serial_driver);
-	}
-
-	info = mgsl_device_list;
-	while(info) {
-#if SYNCLINK_GENERIC_HDLC
-		hdlcdev_exit(info);
-#endif
-		mgsl_release_resources(info);
-		tmp = info;
-		info = info->next_device;
-		kfree(tmp);
-	}
-	
-	if (pci_registered)
-		pci_unregister_driver(&synclink_pci_driver);
-}
-
-static int __init synclink_init(void)
-{
-	int rc;
-
-	if (break_on_load) {
-	 	mgsl_get_text_ptr();
-  		BREAKPOINT();
-	}
-
- 	printk("%s %s\n", driver_name, driver_version);
-
-	mgsl_enum_isa_devices();
-	if ((rc = pci_register_driver(&synclink_pci_driver)) < 0)
-		printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
-	else
-		pci_registered = true;
-
-	if ((rc = mgsl_init_tty()) < 0)
-		goto error;
-
-	return 0;
-
-error:
-	synclink_cleanup();
-	return rc;
-}
-
-static void __exit synclink_exit(void)
-{
-	synclink_cleanup();
-}
-
-module_init(synclink_init);
-module_exit(synclink_exit);
-
-/*
- * usc_RTCmd()
- *
- * Issue a USC Receive/Transmit command to the
- * Channel Command/Address Register (CCAR).
- *
- * Notes:
- *
- *    The command is encoded in the most significant 5 bits <15..11>
- *    of the CCAR value. Bits <10..7> of the CCAR must be preserved
- *    and Bits <6..0> must be written as zeros.
- *
- * Arguments:
- *
- *    info   pointer to device information structure
- *    Cmd    command mask (use symbolic macros)
- *
- * Return Value:
- *
- *    None
- */
-static void usc_RTCmd( struct mgsl_struct *info, u16 Cmd )
-{
-	/* output command to CCAR in bits <15..11> */
-	/* preserve bits <10..7>, bits <6..0> must be zero */
-
-	outw( Cmd + info->loopback_bits, info->io_base + CCAR );
-
-	/* Read to flush write to CCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base + CCAR );
-
-}	/* end of usc_RTCmd() */
-
-/*
- * usc_DmaCmd()
- *
- *    Issue a DMA command to the DMA Command/Address Register (DCAR).
- *
- * Arguments:
- *
- *    info   pointer to device information structure
- *    Cmd    DMA command mask (usc_DmaCmd_XX Macros)
- *
- * Return Value:
- *
- *       None
- */
-static void usc_DmaCmd( struct mgsl_struct *info, u16 Cmd )
-{
-	/* write command mask to DCAR */
-	outw( Cmd + info->mbre_bit, info->io_base );
-
-	/* Read to flush write to DCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base );
-
-}	/* end of usc_DmaCmd() */
-
-/*
- * usc_OutDmaReg()
- *
- *    Write a 16-bit value to a USC DMA register
- *
- * Arguments:
- *
- *    info      pointer to device info structure
- *    RegAddr   register address (number) for write
- *    RegValue  16-bit value to write to register
- *
- * Return Value:
- *
- *    None
- *
- */
-static void usc_OutDmaReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
-{
-	/* Note: The DCAR is located at the adapter base address */
-	/* Note: must preserve state of BIT8 in DCAR */
-
-	outw( RegAddr + info->mbre_bit, info->io_base );
-	outw( RegValue, info->io_base );
-
-	/* Read to flush write to DCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base );
-
-}	/* end of usc_OutDmaReg() */
- 
-/*
- * usc_InDmaReg()
- *
- *    Read a 16-bit value from a DMA register
- *
- * Arguments:
- *
- *    info     pointer to device info structure
- *    RegAddr  register address (number) to read from
- *
- * Return Value:
- *
- *    The 16-bit value read from register
- *
- */
-static u16 usc_InDmaReg( struct mgsl_struct *info, u16 RegAddr )
-{
-	/* Note: The DCAR is located at the adapter base address */
-	/* Note: must preserve state of BIT8 in DCAR */
-
-	outw( RegAddr + info->mbre_bit, info->io_base );
-	return inw( info->io_base );
-
-}	/* end of usc_InDmaReg() */
-
-/*
- *
- * usc_OutReg()
- *
- *    Write a 16-bit value to a USC serial channel register 
- *
- * Arguments:
- *
- *    info      pointer to device info structure
- *    RegAddr   register address (number) to write to
- *    RegValue  16-bit value to write to register
- *
- * Return Value:
- *
- *    None
- *
- */
-static void usc_OutReg( struct mgsl_struct *info, u16 RegAddr, u16 RegValue )
-{
-	outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
-	outw( RegValue, info->io_base + CCAR );
-
-	/* Read to flush write to CCAR */
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		inw( info->io_base + CCAR );
-
-}	/* end of usc_OutReg() */
-
-/*
- * usc_InReg()
- *
- *    Reads a 16-bit value from a USC serial channel register
- *
- * Arguments:
- *
- *    info       pointer to device extension
- *    RegAddr    register address (number) to read from
- *
- * Return Value:
- *
- *    16-bit value read from register
- */
-static u16 usc_InReg( struct mgsl_struct *info, u16 RegAddr )
-{
-	outw( RegAddr + info->loopback_bits, info->io_base + CCAR );
-	return inw( info->io_base + CCAR );
-
-}	/* end of usc_InReg() */
-
-/* usc_set_sdlc_mode()
- *
- *    Set up the adapter for SDLC DMA communications.
- *
- * Arguments:		info    pointer to device instance data
- * Return Value: 	NONE
- */
-static void usc_set_sdlc_mode( struct mgsl_struct *info )
-{
-	u16 RegValue;
-	bool PreSL1660;
-	
-	/*
-	 * determine if the IUSC on the adapter is pre-SL1660. If
-	 * not, take advantage of the UnderWait feature of more
-	 * modern chips. If an underrun occurs and this bit is set,
-	 * the transmitter will idle the programmed idle pattern
-	 * until the driver has time to service the underrun. Otherwise,
-	 * the dma controller may get the cycles previously requested
-	 * and begin transmitting queued tx data.
-	 */
-	usc_OutReg(info,TMCR,0x1f);
-	RegValue=usc_InReg(info,TMDR);
-	PreSL1660 = (RegValue == IUSC_PRE_SL1660);
-
- 	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
- 	{
- 	   /*
- 	   ** Channel Mode Register (CMR)
- 	   **
- 	   ** <15..14>    10    Tx Sub Modes, Send Flag on Underrun
- 	   ** <13>        0     0 = Transmit Disabled (initially)
- 	   ** <12>        0     1 = Consecutive Idles share common 0
- 	   ** <11..8>     1110  Transmitter Mode = HDLC/SDLC Loop
- 	   ** <7..4>      0000  Rx Sub Modes, addr/ctrl field handling
- 	   ** <3..0>      0110  Receiver Mode = HDLC/SDLC
- 	   **
- 	   ** 1000 1110 0000 0110 = 0x8e06
- 	   */
- 	   RegValue = 0x8e06;
- 
- 	   /*--------------------------------------------------
- 	    * ignore user options for UnderRun Actions and
- 	    * preambles
- 	    *--------------------------------------------------*/
- 	}
- 	else
- 	{	
-		/* Channel mode Register (CMR)
-		 *
-		 * <15..14>  00    Tx Sub modes, Underrun Action
-		 * <13>      0     1 = Send Preamble before opening flag
-		 * <12>      0     1 = Consecutive Idles share common 0
-		 * <11..8>   0110  Transmitter mode = HDLC/SDLC
-		 * <7..4>    0000  Rx Sub modes, addr/ctrl field handling
-		 * <3..0>    0110  Receiver mode = HDLC/SDLC
-		 *
-		 * 0000 0110 0000 0110 = 0x0606
-		 */
-		if (info->params.mode == MGSL_MODE_RAW) {
-			RegValue = 0x0001;		/* Set Receive mode = external sync */
-
-			usc_OutReg( info, IOCR,		/* Set IOCR DCD is RxSync Detect Input */
-				(unsigned short)((usc_InReg(info, IOCR) & ~(BIT13|BIT12)) | BIT12));
-
-			/*
-			 * TxSubMode:
-			 * 	CMR <15>		0	Don't send CRC on Tx Underrun
-			 * 	CMR <14>		x	undefined
-			 * 	CMR <13>		0	Send preamble before openning sync
-			 * 	CMR <12>		0	Send 8-bit syncs, 1=send Syncs per TxLength
-			 *
-			 * TxMode:
-			 * 	CMR <11-8)	0100	MonoSync
-			 *
-			 * 	0x00 0100 xxxx xxxx  04xx
-			 */
-			RegValue |= 0x0400;
-		}
-		else {
-
-		RegValue = 0x0606;
-
-		if ( info->params.flags & HDLC_FLAG_UNDERRUN_ABORT15 )
-			RegValue |= BIT14;
-		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_FLAG )
-			RegValue |= BIT15;
-		else if ( info->params.flags & HDLC_FLAG_UNDERRUN_CRC )
-			RegValue |= BIT15 + BIT14;
-		}
-
-		if ( info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE )
-			RegValue |= BIT13;
-	}
-
-	if ( info->params.mode == MGSL_MODE_HDLC &&
-		(info->params.flags & HDLC_FLAG_SHARE_ZERO) )
-		RegValue |= BIT12;
-
-	if ( info->params.addr_filter != 0xff )
-	{
-		/* set up receive address filtering */
-		usc_OutReg( info, RSR, info->params.addr_filter );
-		RegValue |= BIT4;
-	}
-
-	usc_OutReg( info, CMR, RegValue );
-	info->cmr_value = RegValue;
-
-	/* Receiver mode Register (RMR)
-	 *
-	 * <15..13>  000    encoding
-	 * <12..11>  00     FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1)
-	 * <10>      1      1 = Set CRC to all 1s (use for SDLC/HDLC)
-	 * <9>       0      1 = Include Receive chars in CRC
-	 * <8>       1      1 = Use Abort/PE bit as abort indicator
-	 * <7..6>    00     Even parity
-	 * <5>       0      parity disabled
-	 * <4..2>    000    Receive Char Length = 8 bits
-	 * <1..0>    00     Disable Receiver
-	 *
-	 * 0000 0101 0000 0000 = 0x0500
-	 */
-
-	RegValue = 0x0500;
-
-	switch ( info->params.encoding ) {
-	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
-	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
-	case HDLC_ENCODING_NRZI_SPACE:	       RegValue |= BIT14 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
-	}
-
-	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
-		RegValue |= BIT9;
-	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
-		RegValue |= ( BIT12 | BIT10 | BIT9 );
-
-	usc_OutReg( info, RMR, RegValue );
-
-	/* Set the Receive count Limit Register (RCLR) to 0xffff. */
-	/* When an opening flag of an SDLC frame is recognized the */
-	/* Receive Character count (RCC) is loaded with the value in */
-	/* RCLR. The RCC is decremented for each received byte.  The */
-	/* value of RCC is stored after the closing flag of the frame */
-	/* allowing the frame size to be computed. */
-
-	usc_OutReg( info, RCLR, RCLRVALUE );
-
-	usc_RCmd( info, RCmd_SelectRicrdma_level );
-
-	/* Receive Interrupt Control Register (RICR)
-	 *
-	 * <15..8>	?	RxFIFO DMA Request Level
-	 * <7>		0	Exited Hunt IA (Interrupt Arm)
-	 * <6>		0	Idle Received IA
-	 * <5>		0	Break/Abort IA
-	 * <4>		0	Rx Bound IA
-	 * <3>		1	Queued status reflects oldest 2 bytes in FIFO
-	 * <2>		0	Abort/PE IA
-	 * <1>		1	Rx Overrun IA
-	 * <0>		0	Select TC0 value for readback
-	 *
-	 *	0000 0000 0000 1000 = 0x000a
-	 */
-
-	/* Carry over the Exit Hunt and Idle Received bits */
-	/* in case they have been armed by usc_ArmEvents.   */
-
-	RegValue = usc_InReg( info, RICR ) & 0xc0;
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		usc_OutReg( info, RICR, (u16)(0x030a | RegValue) );
-	else
-		usc_OutReg( info, RICR, (u16)(0x140a | RegValue) );
-
-	/* Unlatch all Rx status bits and clear Rx status IRQ Pending */
-
-	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
-
-	/* Transmit mode Register (TMR)
-	 *	
-	 * <15..13>	000	encoding
-	 * <12..11>	00	FCS = 16bit CRC CCITT (x15 + x12 + x5 + 1)
-	 * <10>		1	1 = Start CRC as all 1s (use for SDLC/HDLC)
-	 * <9>		0	1 = Tx CRC Enabled
-	 * <8>		0	1 = Append CRC to end of transmit frame
-	 * <7..6>	00	Transmit parity Even
-	 * <5>		0	Transmit parity Disabled
-	 * <4..2>	000	Tx Char Length = 8 bits
-	 * <1..0>	00	Disable Transmitter
-	 *
-	 * 	0000 0100 0000 0000 = 0x0400
-	 */
-
-	RegValue = 0x0400;
-
-	switch ( info->params.encoding ) {
-	case HDLC_ENCODING_NRZB:               RegValue |= BIT13; break;
-	case HDLC_ENCODING_NRZI_MARK:          RegValue |= BIT14; break;
-	case HDLC_ENCODING_NRZI_SPACE:         RegValue |= BIT14 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_MARK:       RegValue |= BIT15; break;
-	case HDLC_ENCODING_BIPHASE_SPACE:      RegValue |= BIT15 + BIT13; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL:      RegValue |= BIT15 + BIT14; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT15 + BIT14 + BIT13; break;
-	}
-
-	if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_16_CCITT )
-		RegValue |= BIT9 + BIT8;
-	else if ( (info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_32_CCITT )
-		RegValue |= ( BIT12 | BIT10 | BIT9 | BIT8);
-
-	usc_OutReg( info, TMR, RegValue );
-
-	usc_set_txidle( info );
-
-
-	usc_TCmd( info, TCmd_SelectTicrdma_level );
-
-	/* Transmit Interrupt Control Register (TICR)
-	 *
-	 * <15..8>	?	Transmit FIFO DMA Level
-	 * <7>		0	Present IA (Interrupt Arm)
-	 * <6>		0	Idle Sent IA
-	 * <5>		1	Abort Sent IA
-	 * <4>		1	EOF/EOM Sent IA
-	 * <3>		0	CRC Sent IA
-	 * <2>		1	1 = Wait for SW Trigger to Start Frame
-	 * <1>		1	Tx Underrun IA
-	 * <0>		0	TC0 constant on read back
-	 *
-	 *	0000 0000 0011 0110 = 0x0036
-	 */
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-		usc_OutReg( info, TICR, 0x0736 );
-	else								
-		usc_OutReg( info, TICR, 0x1436 );
-
-	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-
-	/*
-	** Transmit Command/Status Register (TCSR)
-	**
-	** <15..12>	0000	TCmd
-	** <11> 	0/1	UnderWait
-	** <10..08>	000	TxIdle
-	** <7>		x	PreSent
-	** <6>         	x	IdleSent
-	** <5>         	x	AbortSent
-	** <4>         	x	EOF/EOM Sent
-	** <3>         	x	CRC Sent
-	** <2>         	x	All Sent
-	** <1>         	x	TxUnder
-	** <0>         	x	TxEmpty
-	** 
-	** 0000 0000 0000 0000 = 0x0000
-	*/
-	info->tcsr_value = 0;
-
-	if ( !PreSL1660 )
-		info->tcsr_value |= TCSR_UNDERWAIT;
-		
-	usc_OutReg( info, TCSR, info->tcsr_value );
-
-	/* Clock mode Control Register (CMCR)
-	 *
-	 * <15..14>	00	counter 1 Source = Disabled
-	 * <13..12> 	00	counter 0 Source = Disabled
-	 * <11..10> 	11	BRG1 Input is TxC Pin
-	 * <9..8>	11	BRG0 Input is TxC Pin
-	 * <7..6>	01	DPLL Input is BRG1 Output
-	 * <5..3>	XXX	TxCLK comes from Port 0
-	 * <2..0>   	XXX	RxCLK comes from Port 1
-	 *
-	 *	0000 1111 0111 0111 = 0x0f77
-	 */
-
-	RegValue = 0x0f40;
-
-	if ( info->params.flags & HDLC_FLAG_RXC_DPLL )
-		RegValue |= 0x0003;	/* RxCLK from DPLL */
-	else if ( info->params.flags & HDLC_FLAG_RXC_BRG )
-		RegValue |= 0x0004;	/* RxCLK from BRG0 */
- 	else if ( info->params.flags & HDLC_FLAG_RXC_TXCPIN)
- 		RegValue |= 0x0006;	/* RxCLK from TXC Input */
-	else
-		RegValue |= 0x0007;	/* RxCLK from Port1 */
-
-	if ( info->params.flags & HDLC_FLAG_TXC_DPLL )
-		RegValue |= 0x0018;	/* TxCLK from DPLL */
-	else if ( info->params.flags & HDLC_FLAG_TXC_BRG )
-		RegValue |= 0x0020;	/* TxCLK from BRG0 */
- 	else if ( info->params.flags & HDLC_FLAG_TXC_RXCPIN)
- 		RegValue |= 0x0038;	/* RxCLK from TXC Input */
-	else
-		RegValue |= 0x0030;	/* TxCLK from Port0 */
-
-	usc_OutReg( info, CMCR, RegValue );
-
-
-	/* Hardware Configuration Register (HCR)
-	 *
-	 * <15..14>	00	CTR0 Divisor:00=32,01=16,10=8,11=4
-	 * <13>		0	CTR1DSel:0=CTR0Div determines CTR0Div
-	 * <12>		0	CVOK:0=report code violation in biphase
-	 * <11..10>	00	DPLL Divisor:00=32,01=16,10=8,11=4
-	 * <9..8>	XX	DPLL mode:00=disable,01=NRZ,10=Biphase,11=Biphase Level
-	 * <7..6>	00	reserved
-	 * <5>		0	BRG1 mode:0=continuous,1=single cycle
-	 * <4>		X	BRG1 Enable
-	 * <3..2>	00	reserved
-	 * <1>		0	BRG0 mode:0=continuous,1=single cycle
-	 * <0>		0	BRG0 Enable
-	 */
-
-	RegValue = 0x0000;
-
-	if ( info->params.flags & (HDLC_FLAG_RXC_DPLL + HDLC_FLAG_TXC_DPLL) ) {
-		u32 XtalSpeed;
-		u32 DpllDivisor;
-		u16 Tc;
-
-		/*  DPLL is enabled. Use BRG1 to provide continuous reference clock  */
-		/*  for DPLL. DPLL mode in HCR is dependent on the encoding used. */
-
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			XtalSpeed = 11059200;
-		else
-			XtalSpeed = 14745600;
-
-		if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
-			DpllDivisor = 16;
-			RegValue |= BIT10;
-		}
-		else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) {
-			DpllDivisor = 8;
-			RegValue |= BIT11;
-		}
-		else
-			DpllDivisor = 32;
-
-		/*  Tc = (Xtal/Speed) - 1 */
-		/*  If twice the remainder of (Xtal/Speed) is greater than Speed */
-		/*  then rounding up gives a more precise time constant. Instead */
-		/*  of rounding up and then subtracting 1 we just don't subtract */
-		/*  the one in this case. */
-
- 		/*--------------------------------------------------
- 		 * ejz: for DPLL mode, application should use the
- 		 * same clock speed as the partner system, even 
- 		 * though clocking is derived from the input RxData.
- 		 * In case the user uses a 0 for the clock speed,
- 		 * default to 0xffffffff and don't try to divide by
- 		 * zero
- 		 *--------------------------------------------------*/
- 		if ( info->params.clock_speed )
- 		{
-			Tc = (u16)((XtalSpeed/DpllDivisor)/info->params.clock_speed);
-			if ( !((((XtalSpeed/DpllDivisor) % info->params.clock_speed) * 2)
-			       / info->params.clock_speed) )
-				Tc--;
- 		}
- 		else
- 			Tc = -1;
- 				  
-
-		/* Write 16-bit Time Constant for BRG1 */
-		usc_OutReg( info, TC1R, Tc );
-
-		RegValue |= BIT4;		/* enable BRG1 */
-
-		switch ( info->params.encoding ) {
-		case HDLC_ENCODING_NRZ:
-		case HDLC_ENCODING_NRZB:
-		case HDLC_ENCODING_NRZI_MARK:
-		case HDLC_ENCODING_NRZI_SPACE: RegValue |= BIT8; break;
-		case HDLC_ENCODING_BIPHASE_MARK:
-		case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT9; break;
-		case HDLC_ENCODING_BIPHASE_LEVEL:
-		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: RegValue |= BIT9 + BIT8; break;
-		}
-	}
-
-	usc_OutReg( info, HCR, RegValue );
-
-
-	/* Channel Control/status Register (CCSR)
-	 *
-	 * <15>		X	RCC FIFO Overflow status (RO)
-	 * <14>		X	RCC FIFO Not Empty status (RO)
-	 * <13>		0	1 = Clear RCC FIFO (WO)
-	 * <12>		X	DPLL Sync (RW)
-	 * <11>		X	DPLL 2 Missed Clocks status (RO)
-	 * <10>		X	DPLL 1 Missed Clock status (RO)
-	 * <9..8>	00	DPLL Resync on rising and falling edges (RW)
-	 * <7>		X	SDLC Loop On status (RO)
-	 * <6>		X	SDLC Loop Send status (RO)
-	 * <5>		1	Bypass counters for TxClk and RxClk (RW)
-	 * <4..2>   	000	Last Char of SDLC frame has 8 bits (RW)
-	 * <1..0>   	00	reserved
-	 *
-	 *	0000 0000 0010 0000 = 0x0020
-	 */
-
-	usc_OutReg( info, CCSR, 0x1020 );
-
-
-	if ( info->params.flags & HDLC_FLAG_AUTO_CTS ) {
-		usc_OutReg( info, SICR,
-			    (u16)(usc_InReg(info,SICR) | SICR_CTS_INACTIVE) );
-	}
-	
-
-	/* enable Master Interrupt Enable bit (MIE) */
-	usc_EnableMasterIrqBit( info );
-
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS + RECEIVE_DATA +
-				TRANSMIT_STATUS + TRANSMIT_DATA + MISC);
-
-	/* arm RCC underflow interrupt */
-	usc_OutReg(info, SICR, (u16)(usc_InReg(info,SICR) | BIT3));
-	usc_EnableInterrupts(info, MISC);
-
-	info->mbre_bit = 0;
-	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
-	usc_DmaCmd( info, DmaCmd_ResetAllChannels );	/* disable both DMA channels */
-	info->mbre_bit = BIT8;
-	outw( BIT8, info->io_base );			/* set Master Bus Enable (DCAR) */
-
-	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
-		/* Enable DMAEN (Port 7, Bit 14) */
-		/* This connects the DMA request signal to the ISA bus */
-		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT15) & ~BIT14));
-	}
-
-	/* DMA Control Register (DCR)
-	 *
-	 * <15..14>	10	Priority mode = Alternating Tx/Rx
-	 *		01	Rx has priority
-	 *		00	Tx has priority
-	 *
-	 * <13>		1	Enable Priority Preempt per DCR<15..14>
-	 *			(WARNING DCR<11..10> must be 00 when this is 1)
-	 *		0	Choose activate channel per DCR<11..10>
-	 *
-	 * <12>		0	Little Endian for Array/List
-	 * <11..10>	00	Both Channels can use each bus grant
-	 * <9..6>	0000	reserved
-	 * <5>		0	7 CLK - Minimum Bus Re-request Interval
-	 * <4>		0	1 = drive D/C and S/D pins
-	 * <3>		1	1 = Add one wait state to all DMA cycles.
-	 * <2>		0	1 = Strobe /UAS on every transfer.
-	 * <1..0>	11	Addr incrementing only affects LS24 bits
-	 *
-	 *	0110 0000 0000 1011 = 0x600b
-	 */
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* PCI adapter does not need DMA wait state */
-		usc_OutDmaReg( info, DCR, 0xa00b );
-	}
-	else
-		usc_OutDmaReg( info, DCR, 0x800b );
-
-
-	/* Receive DMA mode Register (RDMR)
-	 *
-	 * <15..14>	11	DMA mode = Linked List Buffer mode
-	 * <13>		1	RSBinA/L = store Rx status Block in Arrary/List entry
-	 * <12>		1	Clear count of List Entry after fetching
-	 * <11..10>	00	Address mode = Increment
-	 * <9>		1	Terminate Buffer on RxBound
-	 * <8>		0	Bus Width = 16bits
-	 * <7..0>	?	status Bits (write as 0s)
-	 *
-	 * 1111 0010 0000 0000 = 0xf200
-	 */
-
-	usc_OutDmaReg( info, RDMR, 0xf200 );
-
-
-	/* Transmit DMA mode Register (TDMR)
-	 *
-	 * <15..14>	11	DMA mode = Linked List Buffer mode
-	 * <13>		1	TCBinA/L = fetch Tx Control Block from List entry
-	 * <12>		1	Clear count of List Entry after fetching
-	 * <11..10>	00	Address mode = Increment
-	 * <9>		1	Terminate Buffer on end of frame
-	 * <8>		0	Bus Width = 16bits
-	 * <7..0>	?	status Bits (Read Only so write as 0)
-	 *
-	 *	1111 0010 0000 0000 = 0xf200
-	 */
-
-	usc_OutDmaReg( info, TDMR, 0xf200 );
-
-
-	/* DMA Interrupt Control Register (DICR)
-	 *
-	 * <15>		1	DMA Interrupt Enable
-	 * <14>		0	1 = Disable IEO from USC
-	 * <13>		0	1 = Don't provide vector during IntAck
-	 * <12>		1	1 = Include status in Vector
-	 * <10..2>	0	reserved, Must be 0s
-	 * <1>		0	1 = Rx DMA Interrupt Enabled
-	 * <0>		0	1 = Tx DMA Interrupt Enabled
-	 *
-	 *	1001 0000 0000 0000 = 0x9000
-	 */
-
-	usc_OutDmaReg( info, DICR, 0x9000 );
-
-	usc_InDmaReg( info, RDMR );		/* clear pending receive DMA IRQ bits */
-	usc_InDmaReg( info, TDMR );		/* clear pending transmit DMA IRQ bits */
-	usc_OutDmaReg( info, CDIR, 0x0303 );	/* clear IUS and Pending for Tx and Rx */
-
-	/* Channel Control Register (CCR)
-	 *
-	 * <15..14>	10	Use 32-bit Tx Control Blocks (TCBs)
-	 * <13>		0	Trigger Tx on SW Command Disabled
-	 * <12>		0	Flag Preamble Disabled
-	 * <11..10>	00	Preamble Length
-	 * <9..8>	00	Preamble Pattern
-	 * <7..6>	10	Use 32-bit Rx status Blocks (RSBs)
-	 * <5>		0	Trigger Rx on SW Command Disabled
-	 * <4..0>	0	reserved
-	 *
-	 *	1000 0000 1000 0000 = 0x8080
-	 */
-
-	RegValue = 0x8080;
-
-	switch ( info->params.preamble_length ) {
-	case HDLC_PREAMBLE_LENGTH_16BITS: RegValue |= BIT10; break;
-	case HDLC_PREAMBLE_LENGTH_32BITS: RegValue |= BIT11; break;
-	case HDLC_PREAMBLE_LENGTH_64BITS: RegValue |= BIT11 + BIT10; break;
-	}
-
-	switch ( info->params.preamble ) {
-	case HDLC_PREAMBLE_PATTERN_FLAGS: RegValue |= BIT8 + BIT12; break;
-	case HDLC_PREAMBLE_PATTERN_ONES:  RegValue |= BIT8; break;
-	case HDLC_PREAMBLE_PATTERN_10:    RegValue |= BIT9; break;
-	case HDLC_PREAMBLE_PATTERN_01:    RegValue |= BIT9 + BIT8; break;
-	}
-
-	usc_OutReg( info, CCR, RegValue );
-
-
-	/*
-	 * Burst/Dwell Control Register
-	 *
-	 * <15..8>	0x20	Maximum number of transfers per bus grant
-	 * <7..0>	0x00	Maximum number of clock cycles per bus grant
-	 */
-
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		/* don't limit bus occupancy on PCI adapter */
-		usc_OutDmaReg( info, BDCR, 0x0000 );
-	}
-	else
-		usc_OutDmaReg( info, BDCR, 0x2000 );
-
-	usc_stop_transmitter(info);
-	usc_stop_receiver(info);
-	
-}	/* end of usc_set_sdlc_mode() */
-
-/* usc_enable_loopback()
- *
- * Set the 16C32 for internal loopback mode.
- * The TxCLK and RxCLK signals are generated from the BRG0 and
- * the TxD is looped back to the RxD internally.
- *
- * Arguments:		info	pointer to device instance data
- *			enable	1 = enable loopback, 0 = disable
- * Return Value:	None
- */
-static void usc_enable_loopback(struct mgsl_struct *info, int enable)
-{
-	if (enable) {
-		/* blank external TXD output */
-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) | (BIT7+BIT6));
-	
-		/* Clock mode Control Register (CMCR)
-		 *
-		 * <15..14>	00	counter 1 Disabled
-		 * <13..12> 	00	counter 0 Disabled
-		 * <11..10> 	11	BRG1 Input is TxC Pin
-		 * <9..8>	11	BRG0 Input is TxC Pin
-		 * <7..6>	01	DPLL Input is BRG1 Output
-		 * <5..3>	100	TxCLK comes from BRG0
-		 * <2..0>   	100	RxCLK comes from BRG0
-		 *
-		 * 0000 1111 0110 0100 = 0x0f64
-		 */
-
-		usc_OutReg( info, CMCR, 0x0f64 );
-
-		/* Write 16-bit Time Constant for BRG0 */
-		/* use clock speed if available, otherwise use 8 for diagnostics */
-		if (info->params.clock_speed) {
-			if (info->bus_type == MGSL_BUS_TYPE_PCI)
-				usc_OutReg(info, TC0R, (u16)((11059200/info->params.clock_speed)-1));
-			else
-				usc_OutReg(info, TC0R, (u16)((14745600/info->params.clock_speed)-1));
-		} else
-			usc_OutReg(info, TC0R, (u16)8);
-
-		/* Hardware Configuration Register (HCR) Clear Bit 1, BRG0
-		   mode = Continuous Set Bit 0 to enable BRG0.  */
-		usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
-
-		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
-		usc_OutReg(info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004));
-
-		/* set Internal Data loopback mode */
-		info->loopback_bits = 0x300;
-		outw( 0x0300, info->io_base + CCAR );
-	} else {
-		/* enable external TXD output */
-		usc_OutReg(info,IOCR,usc_InReg(info,IOCR) & ~(BIT7+BIT6));
-	
-		/* clear Internal Data loopback mode */
-		info->loopback_bits = 0;
-		outw( 0,info->io_base + CCAR );
-	}
-	
-}	/* end of usc_enable_loopback() */
-
-/* usc_enable_aux_clock()
- *
- * Enabled the AUX clock output at the specified frequency.
- *
- * Arguments:
- *
- *	info		pointer to device extension
- *	data_rate	data rate of clock in bits per second
- *			A data rate of 0 disables the AUX clock.
- *
- * Return Value:	None
- */
-static void usc_enable_aux_clock( struct mgsl_struct *info, u32 data_rate )
-{
-	u32 XtalSpeed;
-	u16 Tc;
-
-	if ( data_rate ) {
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			XtalSpeed = 11059200;
-		else
-			XtalSpeed = 14745600;
-
-
-		/* Tc = (Xtal/Speed) - 1 */
-		/* If twice the remainder of (Xtal/Speed) is greater than Speed */
-		/* then rounding up gives a more precise time constant. Instead */
-		/* of rounding up and then subtracting 1 we just don't subtract */
-		/* the one in this case. */
-
-
-		Tc = (u16)(XtalSpeed/data_rate);
-		if ( !(((XtalSpeed % data_rate) * 2) / data_rate) )
-			Tc--;
-
-		/* Write 16-bit Time Constant for BRG0 */
-		usc_OutReg( info, TC0R, Tc );
-
-		/*
-		 * Hardware Configuration Register (HCR)
-		 * Clear Bit 1, BRG0 mode = Continuous
-		 * Set Bit 0 to enable BRG0.
-		 */
-
-		usc_OutReg( info, HCR, (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
-
-		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
-		usc_OutReg( info, IOCR, (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) );
-	} else {
-		/* data rate == 0 so turn off BRG0 */
-		usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) );
-	}
-
-}	/* end of usc_enable_aux_clock() */
-
-/*
- *
- * usc_process_rxoverrun_sync()
- *
- *		This function processes a receive overrun by resetting the
- *		receive DMA buffers and issuing a Purge Rx FIFO command
- *		to allow the receiver to continue receiving.
- *
- * Arguments:
- *
- *	info		pointer to device extension
- *
- * Return Value: None
- */
-static void usc_process_rxoverrun_sync( struct mgsl_struct *info )
-{
-	int start_index;
-	int end_index;
-	int frame_start_index;
-	bool start_of_frame_found = false;
-	bool end_of_frame_found = false;
-	bool reprogram_dma = false;
-
-	DMABUFFERENTRY *buffer_list = info->rx_buffer_list;
-	u32 phys_addr;
-
-	usc_DmaCmd( info, DmaCmd_PauseRxChannel );
-	usc_RCmd( info, RCmd_EnterHuntmode );
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	/* CurrentRxBuffer points to the 1st buffer of the next */
-	/* possibly available receive frame. */
-	
-	frame_start_index = start_index = end_index = info->current_rx_buffer;
-
-	/* Search for an unfinished string of buffers. This means */
-	/* that a receive frame started (at least one buffer with */
-	/* count set to zero) but there is no terminiting buffer */
-	/* (status set to non-zero). */
-
-	while( !buffer_list[end_index].count )
-	{
-		/* Count field has been reset to zero by 16C32. */
-		/* This buffer is currently in use. */
-
-		if ( !start_of_frame_found )
-		{
-			start_of_frame_found = true;
-			frame_start_index = end_index;
-			end_of_frame_found = false;
-		}
-
-		if ( buffer_list[end_index].status )
-		{
-			/* Status field has been set by 16C32. */
-			/* This is the last buffer of a received frame. */
-
-			/* We want to leave the buffers for this frame intact. */
-			/* Move on to next possible frame. */
-
-			start_of_frame_found = false;
-			end_of_frame_found = true;
-		}
-
-  		/* advance to next buffer entry in linked list */
-  		end_index++;
-  		if ( end_index == info->rx_buffer_count )
-  			end_index = 0;
-
-		if ( start_index == end_index )
-		{
-			/* The entire list has been searched with all Counts == 0 and */
-			/* all Status == 0. The receive buffers are */
-			/* completely screwed, reset all receive buffers! */
-			mgsl_reset_rx_dma_buffers( info );
-			frame_start_index = 0;
-			start_of_frame_found = false;
-			reprogram_dma = true;
-			break;
-		}
-	}
-
-	if ( start_of_frame_found && !end_of_frame_found )
-	{
-		/* There is an unfinished string of receive DMA buffers */
-		/* as a result of the receiver overrun. */
-
-		/* Reset the buffers for the unfinished frame */
-		/* and reprogram the receive DMA controller to start */
-		/* at the 1st buffer of unfinished frame. */
-
-		start_index = frame_start_index;
-
-		do
-		{
-			*((unsigned long *)&(info->rx_buffer_list[start_index++].count)) = DMABUFFERSIZE;
-
-  			/* Adjust index for wrap around. */
-  			if ( start_index == info->rx_buffer_count )
-  				start_index = 0;
-
-		} while( start_index != end_index );
-
-		reprogram_dma = true;
-	}
-
-	if ( reprogram_dma )
-	{
-		usc_UnlatchRxstatusBits(info,RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA|RECEIVE_STATUS);
-		usc_UnlatchRxstatusBits(info, RECEIVE_DATA|RECEIVE_STATUS);
-		
-		usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
-		
-		/* This empties the receive FIFO and loads the RCC with RCLR */
-		usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-
-		/* program 16C32 with physical address of 1st DMA buffer entry */
-		phys_addr = info->rx_buffer_list[frame_start_index].phys_entry;
-		usc_OutDmaReg( info, NRARL, (u16)phys_addr );
-		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
-
-		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-		usc_EnableInterrupts( info, RECEIVE_STATUS );
-
-		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
-		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
-
-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
-		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
-		usc_DmaCmd( info, DmaCmd_InitRxChannel );
-		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
-			usc_EnableReceiver(info,ENABLE_AUTO_DCD);
-		else
-			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-	}
-	else
-	{
-		/* This empties the receive FIFO and loads the RCC with RCLR */
-		usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-		usc_RTCmd( info, RTCmd_PurgeRxFifo );
-	}
-
-}	/* end of usc_process_rxoverrun_sync() */
-
-/* usc_stop_receiver()
- *
- *	Disable USC receiver
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_stop_receiver( struct mgsl_struct *info )
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_stop_receiver(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	/* Disable receive DMA channel. */
-	/* This also disables receive DMA channel interrupts */
-	usc_DmaCmd( info, DmaCmd_ResetRxChannel );
-
-	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-	usc_DisableInterrupts( info, RECEIVE_DATA + RECEIVE_STATUS );
-
-	usc_EnableReceiver(info,DISABLE_UNCONDITIONAL);
-
-	/* This empties the receive FIFO and loads the RCC with RCLR */
-	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	info->rx_enabled = false;
-	info->rx_overflow = false;
-	info->rx_rcc_underrun = false;
-	
-}	/* end of stop_receiver() */
-
-/* usc_start_receiver()
- *
- *	Enable the USC receiver 
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_start_receiver( struct mgsl_struct *info )
-{
-	u32 phys_addr;
-	
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_start_receiver(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	mgsl_reset_rx_dma_buffers( info );
-	usc_stop_receiver( info );
-
-	usc_OutReg( info, CCSR, (u16)(usc_InReg(info,CCSR) | BIT13) );
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	if ( info->params.mode == MGSL_MODE_HDLC ||
-		info->params.mode == MGSL_MODE_RAW ) {
-		/* DMA mode Transfers */
-		/* Program the DMA controller. */
-		/* Enable the DMA controller end of buffer interrupt. */
-
-		/* program 16C32 with physical address of 1st DMA buffer entry */
-		phys_addr = info->rx_buffer_list[0].phys_entry;
-		usc_OutDmaReg( info, NRARL, (u16)phys_addr );
-		usc_OutDmaReg( info, NRARU, (u16)(phys_addr >> 16) );
-
-		usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-		usc_ClearIrqPendingBits( info, RECEIVE_DATA + RECEIVE_STATUS );
-		usc_EnableInterrupts( info, RECEIVE_STATUS );
-
-		/* 1. Arm End of Buffer (EOB) Receive DMA Interrupt (BIT2 of RDIAR) */
-		/* 2. Enable Receive DMA Interrupts (BIT1 of DICR) */
-
-		usc_OutDmaReg( info, RDIAR, BIT3 + BIT2 );
-		usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT1) );
-		usc_DmaCmd( info, DmaCmd_InitRxChannel );
-		if ( info->params.flags & HDLC_FLAG_AUTO_DCD )
-			usc_EnableReceiver(info,ENABLE_AUTO_DCD);
-		else
-			usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-	} else {
-		usc_UnlatchRxstatusBits(info, RXSTATUS_ALL);
-		usc_ClearIrqPendingBits(info, RECEIVE_DATA + RECEIVE_STATUS);
-		usc_EnableInterrupts(info, RECEIVE_DATA);
-
-		usc_RTCmd( info, RTCmd_PurgeRxFifo );
-		usc_RCmd( info, RCmd_EnterHuntmode );
-
-		usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-	}
-
-	usc_OutReg( info, CCSR, 0x1020 );
-
-	info->rx_enabled = true;
-
-}	/* end of usc_start_receiver() */
-
-/* usc_start_transmitter()
- *
- *	Enable the USC transmitter and send a transmit frame if
- *	one is loaded in the DMA buffers.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_start_transmitter( struct mgsl_struct *info )
-{
-	u32 phys_addr;
-	unsigned int FrameSize;
-
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_start_transmitter(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	if ( info->xmit_cnt ) {
-
-		/* If auto RTS enabled and RTS is inactive, then assert */
-		/* RTS and set a flag indicating that the driver should */
-		/* negate RTS when the transmission completes. */
-
-		info->drop_rts_on_tx_done = false;
-
-		if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
-			usc_get_serial_signals( info );
-			if ( !(info->serial_signals & SerialSignal_RTS) ) {
-				info->serial_signals |= SerialSignal_RTS;
-				usc_set_serial_signals( info );
-				info->drop_rts_on_tx_done = true;
-			}
-		}
-
-
-		if ( info->params.mode == MGSL_MODE_ASYNC ) {
-			if ( !info->tx_active ) {
-				usc_UnlatchTxstatusBits(info, TXSTATUS_ALL);
-				usc_ClearIrqPendingBits(info, TRANSMIT_STATUS + TRANSMIT_DATA);
-				usc_EnableInterrupts(info, TRANSMIT_DATA);
-				usc_load_txfifo(info);
-			}
-		} else {
-			/* Disable transmit DMA controller while programming. */
-			usc_DmaCmd( info, DmaCmd_ResetTxChannel );
-			
-			/* Transmit DMA buffer is loaded, so program USC */
-			/* to send the frame contained in the buffers.	 */
-
-			FrameSize = info->tx_buffer_list[info->start_tx_dma_buffer].rcc;
-
-			/* if operating in Raw sync mode, reset the rcc component
-			 * of the tx dma buffer entry, otherwise, the serial controller
-			 * will send a closing sync char after this count.
-			 */
-	    		if ( info->params.mode == MGSL_MODE_RAW )
-				info->tx_buffer_list[info->start_tx_dma_buffer].rcc = 0;
-
-			/* Program the Transmit Character Length Register (TCLR) */
-			/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
-			usc_OutReg( info, TCLR, (u16)FrameSize );
-
-			usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-			/* Program the address of the 1st DMA Buffer Entry in linked list */
-			phys_addr = info->tx_buffer_list[info->start_tx_dma_buffer].phys_entry;
-			usc_OutDmaReg( info, NTARL, (u16)phys_addr );
-			usc_OutDmaReg( info, NTARU, (u16)(phys_addr >> 16) );
-
-			usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-			usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-			usc_EnableInterrupts( info, TRANSMIT_STATUS );
-
-			if ( info->params.mode == MGSL_MODE_RAW &&
-					info->num_tx_dma_buffers > 1 ) {
-			   /* When running external sync mode, attempt to 'stream' transmit  */
-			   /* by filling tx dma buffers as they become available. To do this */
-			   /* we need to enable Tx DMA EOB Status interrupts :               */
-			   /*                                                                */
-			   /* 1. Arm End of Buffer (EOB) Transmit DMA Interrupt (BIT2 of TDIAR) */
-			   /* 2. Enable Transmit DMA Interrupts (BIT0 of DICR) */
-
-			   usc_OutDmaReg( info, TDIAR, BIT2|BIT3 );
-			   usc_OutDmaReg( info, DICR, (u16)(usc_InDmaReg(info,DICR) | BIT0) );
-			}
-
-			/* Initialize Transmit DMA Channel */
-			usc_DmaCmd( info, DmaCmd_InitTxChannel );
-			
-			usc_TCmd( info, TCmd_SendFrame );
-			
-			mod_timer(&info->tx_timer, jiffies +
-					msecs_to_jiffies(5000));
-		}
-		info->tx_active = true;
-	}
-
-	if ( !info->tx_enabled ) {
-		info->tx_enabled = true;
-		if ( info->params.flags & HDLC_FLAG_AUTO_CTS )
-			usc_EnableTransmitter(info,ENABLE_AUTO_CTS);
-		else
-			usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL);
-	}
-
-}	/* end of usc_start_transmitter() */
-
-/* usc_stop_transmitter()
- *
- *	Stops the transmitter and DMA
- *
- * Arguments:		info	pointer to device isntance data
- * Return Value:	None
- */
-static void usc_stop_transmitter( struct mgsl_struct *info )
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):usc_stop_transmitter(%s)\n",
-			 __FILE__,__LINE__, info->device_name );
-			 
-	del_timer(&info->tx_timer);	
-			 
-	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA );
-	usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA );
-
-	usc_EnableTransmitter(info,DISABLE_UNCONDITIONAL);
-	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
-	usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-	info->tx_enabled = false;
-	info->tx_active = false;
-
-}	/* end of usc_stop_transmitter() */
-
-/* usc_load_txfifo()
- *
- *	Fill the transmit FIFO until the FIFO is full or
- *	there is no more data to load.
- *
- * Arguments:		info	pointer to device extension (instance data)
- * Return Value:	None
- */
-static void usc_load_txfifo( struct mgsl_struct *info )
-{
-	int Fifocount;
-	u8 TwoBytes[2];
-	
-	if ( !info->xmit_cnt && !info->x_char )
-		return; 
-		
-	/* Select transmit FIFO status readback in TICR */
-	usc_TCmd( info, TCmd_SelectTicrTxFifostatus );
-
-	/* load the Transmit FIFO until FIFOs full or all data sent */
-
-	while( (Fifocount = usc_InReg(info, TICR) >> 8) && info->xmit_cnt ) {
-		/* there is more space in the transmit FIFO and */
-		/* there is more data in transmit buffer */
-
-		if ( (info->xmit_cnt > 1) && (Fifocount > 1) && !info->x_char ) {
- 			/* write a 16-bit word from transmit buffer to 16C32 */
-				
-			TwoBytes[0] = info->xmit_buf[info->xmit_tail++];
-			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-			TwoBytes[1] = info->xmit_buf[info->xmit_tail++];
-			info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-			
-			outw( *((u16 *)TwoBytes), info->io_base + DATAREG);
-				
-			info->xmit_cnt -= 2;
-			info->icount.tx += 2;
-		} else {
-			/* only 1 byte left to transmit or 1 FIFO slot left */
-			
-			outw( (inw( info->io_base + CCAR) & 0x0780) | (TDR+LSBONLY),
-				info->io_base + CCAR );
-			
-			if (info->x_char) {
-				/* transmit pending high priority char */
-				outw( info->x_char,info->io_base + CCAR );
-				info->x_char = 0;
-			} else {
-				outw( info->xmit_buf[info->xmit_tail++],info->io_base + CCAR );
-				info->xmit_tail = info->xmit_tail & (SERIAL_XMIT_SIZE-1);
-				info->xmit_cnt--;
-			}
-			info->icount.tx++;
-		}
-	}
-
-}	/* end of usc_load_txfifo() */
-
-/* usc_reset()
- *
- *	Reset the adapter to a known state and prepare it for further use.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_reset( struct mgsl_struct *info )
-{
-	if ( info->bus_type == MGSL_BUS_TYPE_PCI ) {
-		int i;
-		u32 readval;
-
-		/* Set BIT30 of Misc Control Register */
-		/* (Local Control Register 0x50) to force reset of USC. */
-
-		volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
-		u32 *LCR0BRDR = (u32 *)(info->lcr_base + 0x28);
-
-		info->misc_ctrl_value |= BIT30;
-		*MiscCtrl = info->misc_ctrl_value;
-
-		/*
-		 * Force at least 170ns delay before clearing 
-		 * reset bit. Each read from LCR takes at least 
-		 * 30ns so 10 times for 300ns to be safe.
-		 */
-		for(i=0;i<10;i++)
-			readval = *MiscCtrl;
-
-		info->misc_ctrl_value &= ~BIT30;
-		*MiscCtrl = info->misc_ctrl_value;
-
-		*LCR0BRDR = BUS_DESCRIPTOR(
-			1,		// Write Strobe Hold (0-3)
-			2,		// Write Strobe Delay (0-3)
-			2,		// Read Strobe Delay  (0-3)
-			0,		// NWDD (Write data-data) (0-3)
-			4,		// NWAD (Write Addr-data) (0-31)
-			0,		// NXDA (Read/Write Data-Addr) (0-3)
-			0,		// NRDD (Read Data-Data) (0-3)
-			5		// NRAD (Read Addr-Data) (0-31)
-			);
-	} else {
-		/* do HW reset */
-		outb( 0,info->io_base + 8 );
-	}
-
-	info->mbre_bit = 0;
-	info->loopback_bits = 0;
-	info->usc_idle_mode = 0;
-
-	/*
-	 * Program the Bus Configuration Register (BCR)
-	 *
-	 * <15>		0	Don't use separate address
-	 * <14..6>	0	reserved
-	 * <5..4>	00	IAckmode = Default, don't care
-	 * <3>		1	Bus Request Totem Pole output
-	 * <2>		1	Use 16 Bit data bus
-	 * <1>		0	IRQ Totem Pole output
-	 * <0>		0	Don't Shift Right Addr
-	 *
-	 * 0000 0000 0000 1100 = 0x000c
-	 *
-	 * By writing to io_base + SDPIN the Wait/Ack pin is
-	 * programmed to work as a Wait pin.
-	 */
-	
-	outw( 0x000c,info->io_base + SDPIN );
-
-
-	outw( 0,info->io_base );
-	outw( 0,info->io_base + CCAR );
-
-	/* select little endian byte ordering */
-	usc_RTCmd( info, RTCmd_SelectLittleEndian );
-
-
-	/* Port Control Register (PCR)
-	 *
-	 * <15..14>	11	Port 7 is Output (~DMAEN, Bit 14 : 0 = Enabled)
-	 * <13..12>	11	Port 6 is Output (~INTEN, Bit 12 : 0 = Enabled)
-	 * <11..10> 	00	Port 5 is Input (No Connect, Don't Care)
-	 * <9..8> 	00	Port 4 is Input (No Connect, Don't Care)
-	 * <7..6>	11	Port 3 is Output (~RTS, Bit 6 : 0 = Enabled )
-	 * <5..4>	11	Port 2 is Output (~DTR, Bit 4 : 0 = Enabled )
-	 * <3..2>	01	Port 1 is Input (Dedicated RxC)
-	 * <1..0>	01	Port 0 is Input (Dedicated TxC)
-	 *
-	 *	1111 0000 1111 0101 = 0xf0f5
-	 */
-
-	usc_OutReg( info, PCR, 0xf0f5 );
-
-
-	/*
-	 * Input/Output Control Register
-	 *
-	 * <15..14>	00	CTS is active low input
-	 * <13..12>	00	DCD is active low input
-	 * <11..10>	00	TxREQ pin is input (DSR)
-	 * <9..8>	00	RxREQ pin is input (RI)
-	 * <7..6>	00	TxD is output (Transmit Data)
-	 * <5..3>	000	TxC Pin in Input (14.7456MHz Clock)
-	 * <2..0>	100	RxC is Output (drive with BRG0)
-	 *
-	 *	0000 0000 0000 0100 = 0x0004
-	 */
-
-	usc_OutReg( info, IOCR, 0x0004 );
-
-}	/* end of usc_reset() */
-
-/* usc_set_async_mode()
- *
- *	Program adapter for asynchronous communications.
- *
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void usc_set_async_mode( struct mgsl_struct *info )
-{
-	u16 RegValue;
-
-	/* disable interrupts while programming USC */
-	usc_DisableMasterIrqBit( info );
-
-	outw( 0, info->io_base ); 			/* clear Master Bus Enable (DCAR) */
-	usc_DmaCmd( info, DmaCmd_ResetAllChannels );	/* disable both DMA channels */
-
-	usc_loopback_frame( info );
-
-	/* Channel mode Register (CMR)
-	 *
-	 * <15..14>	00	Tx Sub modes, 00 = 1 Stop Bit
-	 * <13..12>	00	              00 = 16X Clock
-	 * <11..8>	0000	Transmitter mode = Asynchronous
-	 * <7..6>	00	reserved?
-	 * <5..4>	00	Rx Sub modes, 00 = 16X Clock
-	 * <3..0>	0000	Receiver mode = Asynchronous
-	 *
-	 * 0000 0000 0000 0000 = 0x0
-	 */
-
-	RegValue = 0;
-	if ( info->params.stop_bits != 1 )
-		RegValue |= BIT14;
-	usc_OutReg( info, CMR, RegValue );
-
-	
-	/* Receiver mode Register (RMR)
-	 *
-	 * <15..13>	000	encoding = None
-	 * <12..08>	00000	reserved (Sync Only)
-	 * <7..6>   	00	Even parity
-	 * <5>		0	parity disabled
-	 * <4..2>	000	Receive Char Length = 8 bits
-	 * <1..0>	00	Disable Receiver
-	 *
-	 * 0000 0000 0000 0000 = 0x0
-	 */
-
-	RegValue = 0;
-
-	if ( info->params.data_bits != 8 )
-		RegValue |= BIT4+BIT3+BIT2;
-
-	if ( info->params.parity != ASYNC_PARITY_NONE ) {
-		RegValue |= BIT5;
-		if ( info->params.parity != ASYNC_PARITY_ODD )
-			RegValue |= BIT6;
-	}
-
-	usc_OutReg( info, RMR, RegValue );
-
-
-	/* Set IRQ trigger level */
-
-	usc_RCmd( info, RCmd_SelectRicrIntLevel );
-
-	
-	/* Receive Interrupt Control Register (RICR)
-	 *
-	 * <15..8>	?		RxFIFO IRQ Request Level
-	 *
-	 * Note: For async mode the receive FIFO level must be set
-	 * to 0 to avoid the situation where the FIFO contains fewer bytes
-	 * than the trigger level and no more data is expected.
-	 *
-	 * <7>		0		Exited Hunt IA (Interrupt Arm)
-	 * <6>		0		Idle Received IA
-	 * <5>		0		Break/Abort IA
-	 * <4>		0		Rx Bound IA
-	 * <3>		0		Queued status reflects oldest byte in FIFO
-	 * <2>		0		Abort/PE IA
-	 * <1>		0		Rx Overrun IA
-	 * <0>		0		Select TC0 value for readback
-	 *
-	 * 0000 0000 0100 0000 = 0x0000 + (FIFOLEVEL in MSB)
-	 */
-	
-	usc_OutReg( info, RICR, 0x0000 );
-
-	usc_UnlatchRxstatusBits( info, RXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, RECEIVE_STATUS );
-
-	
-	/* Transmit mode Register (TMR)
-	 *
-	 * <15..13>	000	encoding = None
-	 * <12..08>	00000	reserved (Sync Only)
-	 * <7..6>	00	Transmit parity Even
-	 * <5>		0	Transmit parity Disabled
-	 * <4..2>	000	Tx Char Length = 8 bits
-	 * <1..0>	00	Disable Transmitter
-	 *
-	 * 0000 0000 0000 0000 = 0x0
-	 */
-
-	RegValue = 0;
-
-	if ( info->params.data_bits != 8 )
-		RegValue |= BIT4+BIT3+BIT2;
-
-	if ( info->params.parity != ASYNC_PARITY_NONE ) {
-		RegValue |= BIT5;
-		if ( info->params.parity != ASYNC_PARITY_ODD )
-			RegValue |= BIT6;
-	}
-
-	usc_OutReg( info, TMR, RegValue );
-
-	usc_set_txidle( info );
-
-
-	/* Set IRQ trigger level */
-
-	usc_TCmd( info, TCmd_SelectTicrIntLevel );
-
-	
-	/* Transmit Interrupt Control Register (TICR)
-	 *
-	 * <15..8>	?	Transmit FIFO IRQ Level
-	 * <7>		0	Present IA (Interrupt Arm)
-	 * <6>		1	Idle Sent IA
-	 * <5>		0	Abort Sent IA
-	 * <4>		0	EOF/EOM Sent IA
-	 * <3>		0	CRC Sent IA
-	 * <2>		0	1 = Wait for SW Trigger to Start Frame
-	 * <1>		0	Tx Underrun IA
-	 * <0>		0	TC0 constant on read back
-	 *
-	 *	0000 0000 0100 0000 = 0x0040
-	 */
-
-	usc_OutReg( info, TICR, 0x1f40 );
-
-	usc_UnlatchTxstatusBits( info, TXSTATUS_ALL );
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS );
-
-	usc_enable_async_clock( info, info->params.data_rate );
-
-	
-	/* Channel Control/status Register (CCSR)
-	 *
-	 * <15>		X	RCC FIFO Overflow status (RO)
-	 * <14>		X	RCC FIFO Not Empty status (RO)
-	 * <13>		0	1 = Clear RCC FIFO (WO)
-	 * <12>		X	DPLL in Sync status (RO)
-	 * <11>		X	DPLL 2 Missed Clocks status (RO)
-	 * <10>		X	DPLL 1 Missed Clock status (RO)
-	 * <9..8>	00	DPLL Resync on rising and falling edges (RW)
-	 * <7>		X	SDLC Loop On status (RO)
-	 * <6>		X	SDLC Loop Send status (RO)
-	 * <5>		1	Bypass counters for TxClk and RxClk (RW)
-	 * <4..2>   	000	Last Char of SDLC frame has 8 bits (RW)
-	 * <1..0>   	00	reserved
-	 *
-	 *	0000 0000 0010 0000 = 0x0020
-	 */
-	
-	usc_OutReg( info, CCSR, 0x0020 );
-
-	usc_DisableInterrupts( info, TRANSMIT_STATUS + TRANSMIT_DATA +
-			      RECEIVE_DATA + RECEIVE_STATUS );
-
-	usc_ClearIrqPendingBits( info, TRANSMIT_STATUS + TRANSMIT_DATA +
-				RECEIVE_DATA + RECEIVE_STATUS );
-
-	usc_EnableMasterIrqBit( info );
-
-	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
-		/* Enable INTEN (Port 6, Bit12) */
-		/* This connects the IRQ request signal to the ISA bus */
-		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
-	}
-
-	if (info->params.loopback) {
-		info->loopback_bits = 0x300;
-		outw(0x0300, info->io_base + CCAR);
-	}
-
-}	/* end of usc_set_async_mode() */
-
-/* usc_loopback_frame()
- *
- *	Loop back a small (2 byte) dummy SDLC frame.
- *	Interrupts and DMA are NOT used. The purpose of this is to
- *	clear any 'stale' status info left over from running in	async mode.
- *
- *	The 16C32 shows the strange behaviour of marking the 1st
- *	received SDLC frame with a CRC error even when there is no
- *	CRC error. To get around this a small dummy from of 2 bytes
- *	is looped back when switching from async to sync mode.
- *
- * Arguments:		info		pointer to device instance data
- * Return Value:	None
- */
-static void usc_loopback_frame( struct mgsl_struct *info )
-{
-	int i;
-	unsigned long oldmode = info->params.mode;
-
-	info->params.mode = MGSL_MODE_HDLC;
-	
-	usc_DisableMasterIrqBit( info );
-
-	usc_set_sdlc_mode( info );
-	usc_enable_loopback( info, 1 );
-
-	/* Write 16-bit Time Constant for BRG0 */
-	usc_OutReg( info, TC0R, 0 );
-	
-	/* Channel Control Register (CCR)
-	 *
-	 * <15..14>	00	Don't use 32-bit Tx Control Blocks (TCBs)
-	 * <13>		0	Trigger Tx on SW Command Disabled
-	 * <12>		0	Flag Preamble Disabled
-	 * <11..10>	00	Preamble Length = 8-Bits
-	 * <9..8>	01	Preamble Pattern = flags
-	 * <7..6>	10	Don't use 32-bit Rx status Blocks (RSBs)
-	 * <5>		0	Trigger Rx on SW Command Disabled
-	 * <4..0>	0	reserved
-	 *
-	 *	0000 0001 0000 0000 = 0x0100
-	 */
-
-	usc_OutReg( info, CCR, 0x0100 );
-
-	/* SETUP RECEIVER */
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-	usc_EnableReceiver(info,ENABLE_UNCONDITIONAL);
-
-	/* SETUP TRANSMITTER */
-	/* Program the Transmit Character Length Register (TCLR) */
-	/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
-	usc_OutReg( info, TCLR, 2 );
-	usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-	/* unlatch Tx status bits, and start transmit channel. */
-	usc_UnlatchTxstatusBits(info,TXSTATUS_ALL);
-	outw(0,info->io_base + DATAREG);
-
-	/* ENABLE TRANSMITTER */
-	usc_TCmd( info, TCmd_SendFrame );
-	usc_EnableTransmitter(info,ENABLE_UNCONDITIONAL);
-							
-	/* WAIT FOR RECEIVE COMPLETE */
-	for (i=0 ; i<1000 ; i++)
-		if (usc_InReg( info, RCSR ) & (BIT8 + BIT4 + BIT3 + BIT1))
-			break;
-
-	/* clear Internal Data loopback mode */
-	usc_enable_loopback(info, 0);
-
-	usc_EnableMasterIrqBit(info);
-
-	info->params.mode = oldmode;
-
-}	/* end of usc_loopback_frame() */
-
-/* usc_set_sync_mode()	Programs the USC for SDLC communications.
- *
- * Arguments:		info	pointer to adapter info structure
- * Return Value:	None
- */
-static void usc_set_sync_mode( struct mgsl_struct *info )
-{
-	usc_loopback_frame( info );
-	usc_set_sdlc_mode( info );
-
-	if (info->bus_type == MGSL_BUS_TYPE_ISA) {
-		/* Enable INTEN (Port 6, Bit12) */
-		/* This connects the IRQ request signal to the ISA bus */
-		usc_OutReg(info, PCR, (u16)((usc_InReg(info, PCR) | BIT13) & ~BIT12));
-	}
-
-	usc_enable_aux_clock(info, info->params.clock_speed);
-
-	if (info->params.loopback)
-		usc_enable_loopback(info,1);
-
-}	/* end of mgsl_set_sync_mode() */
-
-/* usc_set_txidle()	Set the HDLC idle mode for the transmitter.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_set_txidle( struct mgsl_struct *info )
-{
-	u16 usc_idle_mode = IDLEMODE_FLAGS;
-
-	/* Map API idle mode to USC register bits */
-
-	switch( info->idle_mode ){
-	case HDLC_TXIDLE_FLAGS:			usc_idle_mode = IDLEMODE_FLAGS; break;
-	case HDLC_TXIDLE_ALT_ZEROS_ONES:	usc_idle_mode = IDLEMODE_ALT_ONE_ZERO; break;
-	case HDLC_TXIDLE_ZEROS:			usc_idle_mode = IDLEMODE_ZERO; break;
-	case HDLC_TXIDLE_ONES:			usc_idle_mode = IDLEMODE_ONE; break;
-	case HDLC_TXIDLE_ALT_MARK_SPACE:	usc_idle_mode = IDLEMODE_ALT_MARK_SPACE; break;
-	case HDLC_TXIDLE_SPACE:			usc_idle_mode = IDLEMODE_SPACE; break;
-	case HDLC_TXIDLE_MARK:			usc_idle_mode = IDLEMODE_MARK; break;
-	}
-
-	info->usc_idle_mode = usc_idle_mode;
-	//usc_OutReg(info, TCSR, usc_idle_mode);
-	info->tcsr_value &= ~IDLEMODE_MASK;	/* clear idle mode bits */
-	info->tcsr_value += usc_idle_mode;
-	usc_OutReg(info, TCSR, info->tcsr_value);
-
-	/*
-	 * if SyncLink WAN adapter is running in external sync mode, the
-	 * transmitter has been set to Monosync in order to try to mimic
-	 * a true raw outbound bit stream. Monosync still sends an open/close
-	 * sync char at the start/end of a frame. Try to match those sync
-	 * patterns to the idle mode set here
-	 */
-	if ( info->params.mode == MGSL_MODE_RAW ) {
-		unsigned char syncpat = 0;
-		switch( info->idle_mode ) {
-		case HDLC_TXIDLE_FLAGS:
-			syncpat = 0x7e;
-			break;
-		case HDLC_TXIDLE_ALT_ZEROS_ONES:
-			syncpat = 0x55;
-			break;
-		case HDLC_TXIDLE_ZEROS:
-		case HDLC_TXIDLE_SPACE:
-			syncpat = 0x00;
-			break;
-		case HDLC_TXIDLE_ONES:
-		case HDLC_TXIDLE_MARK:
-			syncpat = 0xff;
-			break;
-		case HDLC_TXIDLE_ALT_MARK_SPACE:
-			syncpat = 0xaa;
-			break;
-		}
-
-		usc_SetTransmitSyncChars(info,syncpat,syncpat);
-	}
-
-}	/* end of usc_set_txidle() */
-
-/* usc_get_serial_signals()
- *
- *	Query the adapter for the state of the V24 status (input) signals.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_get_serial_signals( struct mgsl_struct *info )
-{
-	u16 status;
-
-	/* clear all serial signals except DTR and RTS */
-	info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
-
-	/* Read the Misc Interrupt status Register (MISR) to get */
-	/* the V24 status signals. */
-
-	status = usc_InReg( info, MISR );
-
-	/* set serial signal bits to reflect MISR */
-
-	if ( status & MISCSTATUS_CTS )
-		info->serial_signals |= SerialSignal_CTS;
-
-	if ( status & MISCSTATUS_DCD )
-		info->serial_signals |= SerialSignal_DCD;
-
-	if ( status & MISCSTATUS_RI )
-		info->serial_signals |= SerialSignal_RI;
-
-	if ( status & MISCSTATUS_DSR )
-		info->serial_signals |= SerialSignal_DSR;
-
-}	/* end of usc_get_serial_signals() */
-
-/* usc_set_serial_signals()
- *
- *	Set the state of DTR and RTS based on contents of
- *	serial_signals member of device extension.
- *	
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void usc_set_serial_signals( struct mgsl_struct *info )
-{
-	u16 Control;
-	unsigned char V24Out = info->serial_signals;
-
-	/* get the current value of the Port Control Register (PCR) */
-
-	Control = usc_InReg( info, PCR );
-
-	if ( V24Out & SerialSignal_RTS )
-		Control &= ~(BIT6);
-	else
-		Control |= BIT6;
-
-	if ( V24Out & SerialSignal_DTR )
-		Control &= ~(BIT4);
-	else
-		Control |= BIT4;
-
-	usc_OutReg( info, PCR, Control );
-
-}	/* end of usc_set_serial_signals() */
-
-/* usc_enable_async_clock()
- *
- *	Enable the async clock at the specified frequency.
- *
- * Arguments:		info		pointer to device instance data
- *			data_rate	data rate of clock in bps
- *					0 disables the AUX clock.
- * Return Value:	None
- */
-static void usc_enable_async_clock( struct mgsl_struct *info, u32 data_rate )
-{
-	if ( data_rate )	{
-		/*
-		 * Clock mode Control Register (CMCR)
-		 * 
-		 * <15..14>     00      counter 1 Disabled
-		 * <13..12>     00      counter 0 Disabled
-		 * <11..10>     11      BRG1 Input is TxC Pin
-		 * <9..8>       11      BRG0 Input is TxC Pin
-		 * <7..6>       01      DPLL Input is BRG1 Output
-		 * <5..3>       100     TxCLK comes from BRG0
-		 * <2..0>       100     RxCLK comes from BRG0
-		 *
-		 * 0000 1111 0110 0100 = 0x0f64
-		 */
-		
-		usc_OutReg( info, CMCR, 0x0f64 );
-
-
-		/*
-		 * Write 16-bit Time Constant for BRG0
-		 * Time Constant = (ClkSpeed / data_rate) - 1
-		 * ClkSpeed = 921600 (ISA), 691200 (PCI)
-		 */
-
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			usc_OutReg( info, TC0R, (u16)((691200/data_rate) - 1) );
-		else
-			usc_OutReg( info, TC0R, (u16)((921600/data_rate) - 1) );
-
-		
-		/*
-		 * Hardware Configuration Register (HCR)
-		 * Clear Bit 1, BRG0 mode = Continuous
-		 * Set Bit 0 to enable BRG0.
-		 */
-
-		usc_OutReg( info, HCR,
-			    (u16)((usc_InReg( info, HCR ) & ~BIT1) | BIT0) );
-
-
-		/* Input/Output Control Reg, <2..0> = 100, Drive RxC pin with BRG0 */
-
-		usc_OutReg( info, IOCR,
-			    (u16)((usc_InReg(info, IOCR) & 0xfff8) | 0x0004) );
-	} else {
-		/* data rate == 0 so turn off BRG0 */
-		usc_OutReg( info, HCR, (u16)(usc_InReg( info, HCR ) & ~BIT0) );
-	}
-
-}	/* end of usc_enable_async_clock() */
-
-/*
- * Buffer Structures:
- *
- * Normal memory access uses virtual addresses that can make discontiguous
- * physical memory pages appear to be contiguous in the virtual address
- * space (the processors memory mapping handles the conversions).
- *
- * DMA transfers require physically contiguous memory. This is because
- * the DMA system controller and DMA bus masters deal with memory using
- * only physical addresses.
- *
- * This causes a problem under Windows NT when large DMA buffers are
- * needed. Fragmentation of the nonpaged pool prevents allocations of
- * physically contiguous buffers larger than the PAGE_SIZE.
- *
- * However the 16C32 supports Bus Master Scatter/Gather DMA which
- * allows DMA transfers to physically discontiguous buffers. Information
- * about each data transfer buffer is contained in a memory structure
- * called a 'buffer entry'. A list of buffer entries is maintained
- * to track and control the use of the data transfer buffers.
- *
- * To support this strategy we will allocate sufficient PAGE_SIZE
- * contiguous memory buffers to allow for the total required buffer
- * space.
- *
- * The 16C32 accesses the list of buffer entries using Bus Master
- * DMA. Control information is read from the buffer entries by the
- * 16C32 to control data transfers. status information is written to
- * the buffer entries by the 16C32 to indicate the status of completed
- * transfers.
- *
- * The CPU writes control information to the buffer entries to control
- * the 16C32 and reads status information from the buffer entries to
- * determine information about received and transmitted frames.
- *
- * Because the CPU and 16C32 (adapter) both need simultaneous access
- * to the buffer entries, the buffer entry memory is allocated with
- * HalAllocateCommonBuffer(). This restricts the size of the buffer
- * entry list to PAGE_SIZE.
- *
- * The actual data buffers on the other hand will only be accessed
- * by the CPU or the adapter but not by both simultaneously. This allows
- * Scatter/Gather packet based DMA procedures for using physically
- * discontiguous pages.
- */
-
-/*
- * mgsl_reset_tx_dma_buffers()
- *
- * 	Set the count for all transmit buffers to 0 to indicate the
- * 	buffer is available for use and set the current buffer to the
- * 	first buffer. This effectively makes all buffers free and
- * 	discards any data in buffers.
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_reset_tx_dma_buffers( struct mgsl_struct *info )
-{
-	unsigned int i;
-
-	for ( i = 0; i < info->tx_buffer_count; i++ ) {
-		*((unsigned long *)&(info->tx_buffer_list[i].count)) = 0;
-	}
-
-	info->current_tx_buffer = 0;
-	info->start_tx_dma_buffer = 0;
-	info->tx_dma_buffers_used = 0;
-
-	info->get_tx_holding_index = 0;
-	info->put_tx_holding_index = 0;
-	info->tx_holding_count = 0;
-
-}	/* end of mgsl_reset_tx_dma_buffers() */
-
-/*
- * num_free_tx_dma_buffers()
- *
- * 	returns the number of free tx dma buffers available
- *
- * Arguments:		info	pointer to device instance data
- * Return Value:	number of free tx dma buffers
- */
-static int num_free_tx_dma_buffers(struct mgsl_struct *info)
-{
-	return info->tx_buffer_count - info->tx_dma_buffers_used;
-}
-
-/*
- * mgsl_reset_rx_dma_buffers()
- * 
- * 	Set the count for all receive buffers to DMABUFFERSIZE
- * 	and set the current buffer to the first buffer. This effectively
- * 	makes all buffers free and discards any data in buffers.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_reset_rx_dma_buffers( struct mgsl_struct *info )
-{
-	unsigned int i;
-
-	for ( i = 0; i < info->rx_buffer_count; i++ ) {
-		*((unsigned long *)&(info->rx_buffer_list[i].count)) = DMABUFFERSIZE;
-//		info->rx_buffer_list[i].count = DMABUFFERSIZE;
-//		info->rx_buffer_list[i].status = 0;
-	}
-
-	info->current_rx_buffer = 0;
-
-}	/* end of mgsl_reset_rx_dma_buffers() */
-
-/*
- * mgsl_free_rx_frame_buffers()
- * 
- * 	Free the receive buffers used by a received SDLC
- * 	frame such that the buffers can be reused.
- * 
- * Arguments:
- * 
- * 	info			pointer to device instance data
- * 	StartIndex		index of 1st receive buffer of frame
- * 	EndIndex		index of last receive buffer of frame
- * 
- * Return Value:	None
- */
-static void mgsl_free_rx_frame_buffers( struct mgsl_struct *info, unsigned int StartIndex, unsigned int EndIndex )
-{
-	bool Done = false;
-	DMABUFFERENTRY *pBufEntry;
-	unsigned int Index;
-
-	/* Starting with 1st buffer entry of the frame clear the status */
-	/* field and set the count field to DMA Buffer Size. */
-
-	Index = StartIndex;
-
-	while( !Done ) {
-		pBufEntry = &(info->rx_buffer_list[Index]);
-
-		if ( Index == EndIndex ) {
-			/* This is the last buffer of the frame! */
-			Done = true;
-		}
-
-		/* reset current buffer for reuse */
-//		pBufEntry->status = 0;
-//		pBufEntry->count = DMABUFFERSIZE;
-		*((unsigned long *)&(pBufEntry->count)) = DMABUFFERSIZE;
-
-		/* advance to next buffer entry in linked list */
-		Index++;
-		if ( Index == info->rx_buffer_count )
-			Index = 0;
-	}
-
-	/* set current buffer to next buffer after last buffer of frame */
-	info->current_rx_buffer = Index;
-
-}	/* end of free_rx_frame_buffers() */
-
-/* mgsl_get_rx_frame()
- * 
- * 	This function attempts to return a received SDLC frame from the
- * 	receive DMA buffers. Only frames received without errors are returned.
- *
- * Arguments:	 	info	pointer to device extension
- * Return Value:	true if frame returned, otherwise false
- */
-static bool mgsl_get_rx_frame(struct mgsl_struct *info)
-{
-	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
-	unsigned short status;
-	DMABUFFERENTRY *pBufEntry;
-	unsigned int framesize = 0;
-	bool ReturnCode = false;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-	bool return_frame = false;
-	
-	/*
-	 * current_rx_buffer points to the 1st buffer of the next available
-	 * receive frame. To find the last buffer of the frame look for
-	 * a non-zero status field in the buffer entries. (The status
-	 * field is set by the 16C32 after completing a receive frame.
-	 */
-
-	StartIndex = EndIndex = info->current_rx_buffer;
-
-	while( !info->rx_buffer_list[EndIndex].status ) {
-		/*
-		 * If the count field of the buffer entry is non-zero then
-		 * this buffer has not been used. (The 16C32 clears the count
-		 * field when it starts using the buffer.) If an unused buffer
-		 * is encountered then there are no frames available.
-		 */
-
-		if ( info->rx_buffer_list[EndIndex].count )
-			goto Cleanup;
-
-		/* advance to next buffer entry in linked list */
-		EndIndex++;
-		if ( EndIndex == info->rx_buffer_count )
-			EndIndex = 0;
-
-		/* if entire list searched then no frame available */
-		if ( EndIndex == StartIndex ) {
-			/* If this occurs then something bad happened,
-			 * all buffers have been 'used' but none mark
-			 * the end of a frame. Reset buffers and receiver.
-			 */
-
-			if ( info->rx_enabled ){
-				spin_lock_irqsave(&info->irq_spinlock,flags);
-				usc_start_receiver(info);
-				spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			}
-			goto Cleanup;
-		}
-	}
-
-
-	/* check status of receive frame */
-	
-	status = info->rx_buffer_list[EndIndex].status;
-
-	if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
-			RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
-		if ( status & RXSTATUS_SHORT_FRAME )
-			info->icount.rxshort++;
-		else if ( status & RXSTATUS_ABORT )
-			info->icount.rxabort++;
-		else if ( status & RXSTATUS_OVERRUN )
-			info->icount.rxover++;
-		else {
-			info->icount.rxcrc++;
-			if ( info->params.crc_type & HDLC_CRC_RETURN_EX )
-				return_frame = true;
-		}
-		framesize = 0;
-#if SYNCLINK_GENERIC_HDLC
-		{
-			info->netdev->stats.rx_errors++;
-			info->netdev->stats.rx_frame_errors++;
-		}
-#endif
-	} else
-		return_frame = true;
-
-	if ( return_frame ) {
-		/* receive frame has no errors, get frame size.
-		 * The frame size is the starting value of the RCC (which was
-		 * set to 0xffff) minus the ending value of the RCC (decremented
-		 * once for each receive character) minus 2 for the 16-bit CRC.
-		 */
-
-		framesize = RCLRVALUE - info->rx_buffer_list[EndIndex].rcc;
-
-		/* adjust frame size for CRC if any */
-		if ( info->params.crc_type == HDLC_CRC_16_CCITT )
-			framesize -= 2;
-		else if ( info->params.crc_type == HDLC_CRC_32_CCITT )
-			framesize -= 4;		
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk("%s(%d):mgsl_get_rx_frame(%s) status=%04X size=%d\n",
-			__FILE__,__LINE__,info->device_name,status,framesize);
-			
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		mgsl_trace_block(info,info->rx_buffer_list[StartIndex].virt_addr,
-			min_t(int, framesize, DMABUFFERSIZE),0);
-		
-	if (framesize) {
-		if ( ( (info->params.crc_type & HDLC_CRC_RETURN_EX) &&
-				((framesize+1) > info->max_frame_size) ) ||
-			(framesize > info->max_frame_size) )
-			info->icount.rxlong++;
-		else {
-			/* copy dma buffer(s) to contiguous intermediate buffer */
-			int copy_count = framesize;
-			int index = StartIndex;
-			unsigned char *ptmp = info->intermediate_rxbuffer;
-
-			if ( !(status & RXSTATUS_CRC_ERROR))
-			info->icount.rxok++;
-			
-			while(copy_count) {
-				int partial_count;
-				if ( copy_count > DMABUFFERSIZE )
-					partial_count = DMABUFFERSIZE;
-				else
-					partial_count = copy_count;
-			
-				pBufEntry = &(info->rx_buffer_list[index]);
-				memcpy( ptmp, pBufEntry->virt_addr, partial_count );
-				ptmp += partial_count;
-				copy_count -= partial_count;
-				
-				if ( ++index == info->rx_buffer_count )
-					index = 0;
-			}
-
-			if ( info->params.crc_type & HDLC_CRC_RETURN_EX ) {
-				++framesize;
-				*ptmp = (status & RXSTATUS_CRC_ERROR ?
-						RX_CRC_ERROR :
-						RX_OK);
-
-				if ( debug_level >= DEBUG_LEVEL_DATA )
-					printk("%s(%d):mgsl_get_rx_frame(%s) rx frame status=%d\n",
-						__FILE__,__LINE__,info->device_name,
-						*ptmp);
-			}
-
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount)
-				hdlcdev_rx(info,info->intermediate_rxbuffer,framesize);
-			else
-#endif
-				ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-		}
-	}
-	/* Free the buffers used by this frame. */
-	mgsl_free_rx_frame_buffers( info, StartIndex, EndIndex );
-
-	ReturnCode = true;
-
-Cleanup:
-
-	if ( info->rx_enabled && info->rx_overflow ) {
-		/* The receiver needs to restarted because of 
-		 * a receive overflow (buffer or FIFO). If the 
-		 * receive buffers are now empty, then restart receiver.
-		 */
-
-		if ( !info->rx_buffer_list[EndIndex].status &&
-			info->rx_buffer_list[EndIndex].count ) {
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			usc_start_receiver(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		}
-	}
-
-	return ReturnCode;
-
-}	/* end of mgsl_get_rx_frame() */
-
-/* mgsl_get_raw_rx_frame()
- *
- *     	This function attempts to return a received frame from the
- *	receive DMA buffers when running in external loop mode. In this mode,
- *	we will return at most one DMABUFFERSIZE frame to the application.
- *	The USC receiver is triggering off of DCD going active to start a new
- *	frame, and DCD going inactive to terminate the frame (similar to
- *	processing a closing flag character).
- *
- *	In this routine, we will return DMABUFFERSIZE "chunks" at a time.
- *	If DCD goes inactive, the last Rx DMA Buffer will have a non-zero
- * 	status field and the RCC field will indicate the length of the
- *	entire received frame. We take this RCC field and get the modulus
- *	of RCC and DMABUFFERSIZE to determine if number of bytes in the
- *	last Rx DMA buffer and return that last portion of the frame.
- *
- * Arguments:	 	info	pointer to device extension
- * Return Value:	true if frame returned, otherwise false
- */
-static bool mgsl_get_raw_rx_frame(struct mgsl_struct *info)
-{
-	unsigned int CurrentIndex, NextIndex;
-	unsigned short status;
-	DMABUFFERENTRY *pBufEntry;
-	unsigned int framesize = 0;
-	bool ReturnCode = false;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-
-	/*
- 	 * current_rx_buffer points to the 1st buffer of the next available
-	 * receive frame. The status field is set by the 16C32 after
-	 * completing a receive frame. If the status field of this buffer
-	 * is zero, either the USC is still filling this buffer or this
-	 * is one of a series of buffers making up a received frame.
-	 *
-	 * If the count field of this buffer is zero, the USC is either
-	 * using this buffer or has used this buffer. Look at the count
-	 * field of the next buffer. If that next buffer's count is
-	 * non-zero, the USC is still actively using the current buffer.
-	 * Otherwise, if the next buffer's count field is zero, the
-	 * current buffer is complete and the USC is using the next
-	 * buffer.
-	 */
-	CurrentIndex = NextIndex = info->current_rx_buffer;
-	++NextIndex;
-	if ( NextIndex == info->rx_buffer_count )
-		NextIndex = 0;
-
-	if ( info->rx_buffer_list[CurrentIndex].status != 0 ||
-		(info->rx_buffer_list[CurrentIndex].count == 0 &&
-			info->rx_buffer_list[NextIndex].count == 0)) {
-		/*
-	 	 * Either the status field of this dma buffer is non-zero
-		 * (indicating the last buffer of a receive frame) or the next
-	 	 * buffer is marked as in use -- implying this buffer is complete
-		 * and an intermediate buffer for this received frame.
-	 	 */
-
-		status = info->rx_buffer_list[CurrentIndex].status;
-
-		if ( status & (RXSTATUS_SHORT_FRAME + RXSTATUS_OVERRUN +
-				RXSTATUS_CRC_ERROR + RXSTATUS_ABORT) ) {
-			if ( status & RXSTATUS_SHORT_FRAME )
-				info->icount.rxshort++;
-			else if ( status & RXSTATUS_ABORT )
-				info->icount.rxabort++;
-			else if ( status & RXSTATUS_OVERRUN )
-				info->icount.rxover++;
-			else
-				info->icount.rxcrc++;
-			framesize = 0;
-		} else {
-			/*
-			 * A receive frame is available, get frame size and status.
-			 *
-			 * The frame size is the starting value of the RCC (which was
-			 * set to 0xffff) minus the ending value of the RCC (decremented
-			 * once for each receive character) minus 2 or 4 for the 16-bit
-			 * or 32-bit CRC.
-			 *
-			 * If the status field is zero, this is an intermediate buffer.
-			 * It's size is 4K.
-			 *
-			 * If the DMA Buffer Entry's Status field is non-zero, the
-			 * receive operation completed normally (ie: DCD dropped). The
-			 * RCC field is valid and holds the received frame size.
-			 * It is possible that the RCC field will be zero on a DMA buffer
-			 * entry with a non-zero status. This can occur if the total
-			 * frame size (number of bytes between the time DCD goes active
-			 * to the time DCD goes inactive) exceeds 65535 bytes. In this
-			 * case the 16C32 has underrun on the RCC count and appears to
-			 * stop updating this counter to let us know the actual received
-			 * frame size. If this happens (non-zero status and zero RCC),
-			 * simply return the entire RxDMA Buffer
-			 */
-			if ( status ) {
-				/*
-				 * In the event that the final RxDMA Buffer is
-				 * terminated with a non-zero status and the RCC
-				 * field is zero, we interpret this as the RCC
-				 * having underflowed (received frame > 65535 bytes).
-				 *
-				 * Signal the event to the user by passing back
-				 * a status of RxStatus_CrcError returning the full
-				 * buffer and let the app figure out what data is
-				 * actually valid
-				 */
-				if ( info->rx_buffer_list[CurrentIndex].rcc )
-					framesize = RCLRVALUE - info->rx_buffer_list[CurrentIndex].rcc;
-				else
-					framesize = DMABUFFERSIZE;
-			}
-			else
-				framesize = DMABUFFERSIZE;
-		}
-
-		if ( framesize > DMABUFFERSIZE ) {
-			/*
-			 * if running in raw sync mode, ISR handler for
-			 * End Of Buffer events terminates all buffers at 4K.
-			 * If this frame size is said to be >4K, get the
-			 * actual number of bytes of the frame in this buffer.
-			 */
-			framesize = framesize % DMABUFFERSIZE;
-		}
-
-
-		if ( debug_level >= DEBUG_LEVEL_BH )
-			printk("%s(%d):mgsl_get_raw_rx_frame(%s) status=%04X size=%d\n",
-				__FILE__,__LINE__,info->device_name,status,framesize);
-
-		if ( debug_level >= DEBUG_LEVEL_DATA )
-			mgsl_trace_block(info,info->rx_buffer_list[CurrentIndex].virt_addr,
-				min_t(int, framesize, DMABUFFERSIZE),0);
-
-		if (framesize) {
-			/* copy dma buffer(s) to contiguous intermediate buffer */
-			/* NOTE: we never copy more than DMABUFFERSIZE bytes	*/
-
-			pBufEntry = &(info->rx_buffer_list[CurrentIndex]);
-			memcpy( info->intermediate_rxbuffer, pBufEntry->virt_addr, framesize);
-			info->icount.rxok++;
-
-			ldisc_receive_buf(tty, info->intermediate_rxbuffer, info->flag_buf, framesize);
-		}
-
-		/* Free the buffers used by this frame. */
-		mgsl_free_rx_frame_buffers( info, CurrentIndex, CurrentIndex );
-
-		ReturnCode = true;
-	}
-
-
-	if ( info->rx_enabled && info->rx_overflow ) {
-		/* The receiver needs to restarted because of
-		 * a receive overflow (buffer or FIFO). If the
-		 * receive buffers are now empty, then restart receiver.
-		 */
-
-		if ( !info->rx_buffer_list[CurrentIndex].status &&
-			info->rx_buffer_list[CurrentIndex].count ) {
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			usc_start_receiver(info);
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		}
-	}
-
-	return ReturnCode;
-
-}	/* end of mgsl_get_raw_rx_frame() */
-
-/* mgsl_load_tx_dma_buffer()
- * 
- * 	Load the transmit DMA buffer with the specified data.
- * 
- * Arguments:
- * 
- * 	info		pointer to device extension
- * 	Buffer		pointer to buffer containing frame to load
- * 	BufferSize	size in bytes of frame in Buffer
- * 
- * Return Value: 	None
- */
-static void mgsl_load_tx_dma_buffer(struct mgsl_struct *info,
-		const char *Buffer, unsigned int BufferSize)
-{
-	unsigned short Copycount;
-	unsigned int i = 0;
-	DMABUFFERENTRY *pBufEntry;
-	
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		mgsl_trace_block(info,Buffer, min_t(int, BufferSize, DMABUFFERSIZE), 1);
-
-	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
-		/* set CMR:13 to start transmit when
-		 * next GoAhead (abort) is received
-		 */
-	 	info->cmr_value |= BIT13;			  
-	}
-		
-	/* begin loading the frame in the next available tx dma
-	 * buffer, remember it's starting location for setting
-	 * up tx dma operation
-	 */
-	i = info->current_tx_buffer;
-	info->start_tx_dma_buffer = i;
-
-	/* Setup the status and RCC (Frame Size) fields of the 1st */
-	/* buffer entry in the transmit DMA buffer list. */
-
-	info->tx_buffer_list[i].status = info->cmr_value & 0xf000;
-	info->tx_buffer_list[i].rcc    = BufferSize;
-	info->tx_buffer_list[i].count  = BufferSize;
-
-	/* Copy frame data from 1st source buffer to the DMA buffers. */
-	/* The frame data may span multiple DMA buffers. */
-
-	while( BufferSize ){
-		/* Get a pointer to next DMA buffer entry. */
-		pBufEntry = &info->tx_buffer_list[i++];
-			
-		if ( i == info->tx_buffer_count )
-			i=0;
-
-		/* Calculate the number of bytes that can be copied from */
-		/* the source buffer to this DMA buffer. */
-		if ( BufferSize > DMABUFFERSIZE )
-			Copycount = DMABUFFERSIZE;
-		else
-			Copycount = BufferSize;
-
-		/* Actually copy data from source buffer to DMA buffer. */
-		/* Also set the data count for this individual DMA buffer. */
-		if ( info->bus_type == MGSL_BUS_TYPE_PCI )
-			mgsl_load_pci_memory(pBufEntry->virt_addr, Buffer,Copycount);
-		else
-			memcpy(pBufEntry->virt_addr, Buffer, Copycount);
-
-		pBufEntry->count = Copycount;
-
-		/* Advance source pointer and reduce remaining data count. */
-		Buffer += Copycount;
-		BufferSize -= Copycount;
-
-		++info->tx_dma_buffers_used;
-	}
-
-	/* remember next available tx dma buffer */
-	info->current_tx_buffer = i;
-
-}	/* end of mgsl_load_tx_dma_buffer() */
-
-/*
- * mgsl_register_test()
- * 
- * 	Performs a register test of the 16C32.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:		true if test passed, otherwise false
- */
-static bool mgsl_register_test( struct mgsl_struct *info )
-{
-	static unsigned short BitPatterns[] =
-		{ 0x0000, 0xffff, 0xaaaa, 0x5555, 0x1234, 0x6969, 0x9696, 0x0f0f };
-	static unsigned int Patterncount = ARRAY_SIZE(BitPatterns);
-	unsigned int i;
-	bool rc = true;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset(info);
-
-	/* Verify the reset state of some registers. */
-
-	if ( (usc_InReg( info, SICR ) != 0) ||
-		  (usc_InReg( info, IVR  ) != 0) ||
-		  (usc_InDmaReg( info, DIVR ) != 0) ){
-		rc = false;
-	}
-
-	if ( rc ){
-		/* Write bit patterns to various registers but do it out of */
-		/* sync, then read back and verify values. */
-
-		for ( i = 0 ; i < Patterncount ; i++ ) {
-			usc_OutReg( info, TC0R, BitPatterns[i] );
-			usc_OutReg( info, TC1R, BitPatterns[(i+1)%Patterncount] );
-			usc_OutReg( info, TCLR, BitPatterns[(i+2)%Patterncount] );
-			usc_OutReg( info, RCLR, BitPatterns[(i+3)%Patterncount] );
-			usc_OutReg( info, RSR,  BitPatterns[(i+4)%Patterncount] );
-			usc_OutDmaReg( info, TBCR, BitPatterns[(i+5)%Patterncount] );
-
-			if ( (usc_InReg( info, TC0R ) != BitPatterns[i]) ||
-				  (usc_InReg( info, TC1R ) != BitPatterns[(i+1)%Patterncount]) ||
-				  (usc_InReg( info, TCLR ) != BitPatterns[(i+2)%Patterncount]) ||
-				  (usc_InReg( info, RCLR ) != BitPatterns[(i+3)%Patterncount]) ||
-				  (usc_InReg( info, RSR )  != BitPatterns[(i+4)%Patterncount]) ||
-				  (usc_InDmaReg( info, TBCR ) != BitPatterns[(i+5)%Patterncount]) ){
-				rc = false;
-				break;
-			}
-		}
-	}
-
-	usc_reset(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return rc;
-
-}	/* end of mgsl_register_test() */
-
-/* mgsl_irq_test() 	Perform interrupt test of the 16C32.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	true if test passed, otherwise false
- */
-static bool mgsl_irq_test( struct mgsl_struct *info )
-{
-	unsigned long EndTime;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset(info);
-
-	/*
-	 * Setup 16C32 to interrupt on TxC pin (14MHz clock) transition. 
-	 * The ISR sets irq_occurred to true.
-	 */
-
-	info->irq_occurred = false;
-
-	/* Enable INTEN gate for ISA adapter (Port 6, Bit12) */
-	/* Enable INTEN (Port 6, Bit12) */
-	/* This connects the IRQ request signal to the ISA bus */
-	/* on the ISA adapter. This has no effect for the PCI adapter */
-	usc_OutReg( info, PCR, (unsigned short)((usc_InReg(info, PCR) | BIT13) & ~BIT12) );
-
-	usc_EnableMasterIrqBit(info);
-	usc_EnableInterrupts(info, IO_PIN);
-	usc_ClearIrqPendingBits(info, IO_PIN);
-	
-	usc_UnlatchIostatusBits(info, MISCSTATUS_TXC_LATCHED);
-	usc_EnableStatusIrqs(info, SICR_TXC_ACTIVE + SICR_TXC_INACTIVE);
-
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	EndTime=100;
-	while( EndTime-- && !info->irq_occurred ) {
-		msleep_interruptible(10);
-	}
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-	return info->irq_occurred;
-
-}	/* end of mgsl_irq_test() */
-
-/* mgsl_dma_test()
- * 
- * 	Perform a DMA test of the 16C32. A small frame is
- * 	transmitted via DMA from a transmit buffer to a receive buffer
- * 	using single buffer DMA mode.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	true if test passed, otherwise false
- */
-static bool mgsl_dma_test( struct mgsl_struct *info )
-{
-	unsigned short FifoLevel;
-	unsigned long phys_addr;
-	unsigned int FrameSize;
-	unsigned int i;
-	char *TmpPtr;
-	bool rc = true;
-	unsigned short status=0;
-	unsigned long EndTime;
-	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-
-	/* save current port options */
-	memcpy(&tmp_params,&info->params,sizeof(MGSL_PARAMS));
-	/* load default port options */
-	memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-	
-#define TESTFRAMESIZE 40
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	
-	/* setup 16C32 for SDLC DMA transfer mode */
-
-	usc_reset(info);
-	usc_set_sdlc_mode(info);
-	usc_enable_loopback(info,1);
-	
-	/* Reprogram the RDMR so that the 16C32 does NOT clear the count
-	 * field of the buffer entry after fetching buffer address. This
-	 * way we can detect a DMA failure for a DMA read (which should be
-	 * non-destructive to system memory) before we try and write to
-	 * memory (where a failure could corrupt system memory).
-	 */
-
-	/* Receive DMA mode Register (RDMR)
-	 * 
-	 * <15..14>	11	DMA mode = Linked List Buffer mode
-	 * <13>		1	RSBinA/L = store Rx status Block in List entry
-	 * <12>		0	1 = Clear count of List Entry after fetching
-	 * <11..10>	00	Address mode = Increment
-	 * <9>		1	Terminate Buffer on RxBound
-	 * <8>		0	Bus Width = 16bits
-	 * <7..0>		?	status Bits (write as 0s)
-	 * 
-	 * 1110 0010 0000 0000 = 0xe200
-	 */
-
-	usc_OutDmaReg( info, RDMR, 0xe200 );
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-
-	/* SETUP TRANSMIT AND RECEIVE DMA BUFFERS */
-
-	FrameSize = TESTFRAMESIZE;
-
-	/* setup 1st transmit buffer entry: */
-	/* with frame size and transmit control word */
-
-	info->tx_buffer_list[0].count  = FrameSize;
-	info->tx_buffer_list[0].rcc    = FrameSize;
-	info->tx_buffer_list[0].status = 0x4000;
-
-	/* build a transmit frame in 1st transmit DMA buffer */
-
-	TmpPtr = info->tx_buffer_list[0].virt_addr;
-	for (i = 0; i < FrameSize; i++ )
-		*TmpPtr++ = i;
-
-	/* setup 1st receive buffer entry: */
-	/* clear status, set max receive buffer size */
-
-	info->rx_buffer_list[0].status = 0;
-	info->rx_buffer_list[0].count = FrameSize + 4;
-
-	/* zero out the 1st receive buffer */
-
-	memset( info->rx_buffer_list[0].virt_addr, 0, FrameSize + 4 );
-
-	/* Set count field of next buffer entries to prevent */
-	/* 16C32 from using buffers after the 1st one. */
-
-	info->tx_buffer_list[1].count = 0;
-	info->rx_buffer_list[1].count = 0;
-	
-
-	/***************************/
-	/* Program 16C32 receiver. */
-	/***************************/
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	/* setup DMA transfers */
-	usc_RTCmd( info, RTCmd_PurgeRxFifo );
-
-	/* program 16C32 receiver with physical address of 1st DMA buffer entry */
-	phys_addr = info->rx_buffer_list[0].phys_entry;
-	usc_OutDmaReg( info, NRARL, (unsigned short)phys_addr );
-	usc_OutDmaReg( info, NRARU, (unsigned short)(phys_addr >> 16) );
-
-	/* Clear the Rx DMA status bits (read RDMR) and start channel */
-	usc_InDmaReg( info, RDMR );
-	usc_DmaCmd( info, DmaCmd_InitRxChannel );
-
-	/* Enable Receiver (RMR <1..0> = 10) */
-	usc_OutReg( info, RMR, (unsigned short)((usc_InReg(info, RMR) & 0xfffc) | 0x0002) );
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-
-	/*************************************************************/
-	/* WAIT FOR RECEIVER TO DMA ALL PARAMETERS FROM BUFFER ENTRY */
-	/*************************************************************/
-
-	/* Wait 100ms for interrupt. */
-	EndTime = jiffies + msecs_to_jiffies(100);
-
-	for(;;) {
-		if (time_after(jiffies, EndTime)) {
-			rc = false;
-			break;
-		}
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		status = usc_InDmaReg( info, RDMR );
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		if ( !(status & BIT4) && (status & BIT5) ) {
-			/* INITG (BIT 4) is inactive (no entry read in progress) AND */
-			/* BUSY  (BIT 5) is active (channel still active). */
-			/* This means the buffer entry read has completed. */
-			break;
-		}
-	}
-
-
-	/******************************/
-	/* Program 16C32 transmitter. */
-	/******************************/
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-
-	/* Program the Transmit Character Length Register (TCLR) */
-	/* and clear FIFO (TCC is loaded with TCLR on FIFO clear) */
-
-	usc_OutReg( info, TCLR, (unsigned short)info->tx_buffer_list[0].count );
-	usc_RTCmd( info, RTCmd_PurgeTxFifo );
-
-	/* Program the address of the 1st DMA Buffer Entry in linked list */
-
-	phys_addr = info->tx_buffer_list[0].phys_entry;
-	usc_OutDmaReg( info, NTARL, (unsigned short)phys_addr );
-	usc_OutDmaReg( info, NTARU, (unsigned short)(phys_addr >> 16) );
-
-	/* unlatch Tx status bits, and start transmit channel. */
-
-	usc_OutReg( info, TCSR, (unsigned short)(( usc_InReg(info, TCSR) & 0x0f00) | 0xfa) );
-	usc_DmaCmd( info, DmaCmd_InitTxChannel );
-
-	/* wait for DMA controller to fill transmit FIFO */
-
-	usc_TCmd( info, TCmd_SelectTicrTxFifostatus );
-	
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-
-	/**********************************/
-	/* WAIT FOR TRANSMIT FIFO TO FILL */
-	/**********************************/
-	
-	/* Wait 100ms */
-	EndTime = jiffies + msecs_to_jiffies(100);
-
-	for(;;) {
-		if (time_after(jiffies, EndTime)) {
-			rc = false;
-			break;
-		}
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		FifoLevel = usc_InReg(info, TICR) >> 8;
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-			
-		if ( FifoLevel < 16 )
-			break;
-		else
-			if ( FrameSize < 32 ) {
-				/* This frame is smaller than the entire transmit FIFO */
-				/* so wait for the entire frame to be loaded. */
-				if ( FifoLevel <= (32 - FrameSize) )
-					break;
-			}
-	}
-
-
-	if ( rc )
-	{
-		/* Enable 16C32 transmitter. */
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		
-		/* Transmit mode Register (TMR), <1..0> = 10, Enable Transmitter */
-		usc_TCmd( info, TCmd_SendFrame );
-		usc_OutReg( info, TMR, (unsigned short)((usc_InReg(info, TMR) & 0xfffc) | 0x0002) );
-		
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-						
-		/******************************/
-		/* WAIT FOR TRANSMIT COMPLETE */
-		/******************************/
-
-		/* Wait 100ms */
-		EndTime = jiffies + msecs_to_jiffies(100);
-
-		/* While timer not expired wait for transmit complete */
-
-		spin_lock_irqsave(&info->irq_spinlock,flags);
-		status = usc_InReg( info, TCSR );
-		spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-		while ( !(status & (BIT6+BIT5+BIT4+BIT2+BIT1)) ) {
-			if (time_after(jiffies, EndTime)) {
-				rc = false;
-				break;
-			}
-
-			spin_lock_irqsave(&info->irq_spinlock,flags);
-			status = usc_InReg( info, TCSR );
-			spin_unlock_irqrestore(&info->irq_spinlock,flags);
-		}
-	}
-
-
-	if ( rc ){
-		/* CHECK FOR TRANSMIT ERRORS */
-		if ( status & (BIT5 + BIT1) ) 
-			rc = false;
-	}
-
-	if ( rc ) {
-		/* WAIT FOR RECEIVE COMPLETE */
-
-		/* Wait 100ms */
-		EndTime = jiffies + msecs_to_jiffies(100);
-
-		/* Wait for 16C32 to write receive status to buffer entry. */
-		status=info->rx_buffer_list[0].status;
-		while ( status == 0 ) {
-			if (time_after(jiffies, EndTime)) {
-				rc = false;
-				break;
-			}
-			status=info->rx_buffer_list[0].status;
-		}
-	}
-
-
-	if ( rc ) {
-		/* CHECK FOR RECEIVE ERRORS */
-		status = info->rx_buffer_list[0].status;
-
-		if ( status & (BIT8 + BIT3 + BIT1) ) {
-			/* receive error has occurred */
-			rc = false;
-		} else {
-			if ( memcmp( info->tx_buffer_list[0].virt_addr ,
-				info->rx_buffer_list[0].virt_addr, FrameSize ) ){
-				rc = false;
-			}
-		}
-	}
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_reset( info );
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	/* restore current port options */
-	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
-	
-	return rc;
-
-}	/* end of mgsl_dma_test() */
-
-/* mgsl_adapter_test()
- * 
- * 	Perform the register, IRQ, and DMA tests for the 16C32.
- * 	
- * Arguments:		info	pointer to device instance data
- * Return Value:	0 if success, otherwise -ENODEV
- */
-static int mgsl_adapter_test( struct mgsl_struct *info )
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):Testing device %s\n",
-			__FILE__,__LINE__,info->device_name );
-			
-	if ( !mgsl_register_test( info ) ) {
-		info->init_error = DiagStatus_AddressFailure;
-		printk( "%s(%d):Register test failure for device %s Addr=%04X\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->io_base) );
-		return -ENODEV;
-	}
-
-	if ( !mgsl_irq_test( info ) ) {
-		info->init_error = DiagStatus_IrqFailure;
-		printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );
-		return -ENODEV;
-	}
-
-	if ( !mgsl_dma_test( info ) ) {
-		info->init_error = DiagStatus_DmaFailure;
-		printk( "%s(%d):DMA test failure for device %s DMA=%d\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->dma_level) );
-		return -ENODEV;
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):device %s passed diagnostics\n",
-			__FILE__,__LINE__,info->device_name );
-			
-	return 0;
-
-}	/* end of mgsl_adapter_test() */
-
-/* mgsl_memory_test()
- * 
- * 	Test the shared memory on a PCI adapter.
- * 
- * Arguments:		info	pointer to device instance data
- * Return Value:	true if test passed, otherwise false
- */
-static bool mgsl_memory_test( struct mgsl_struct *info )
-{
-	static unsigned long BitPatterns[] =
-		{ 0x0, 0x55555555, 0xaaaaaaaa, 0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
-	unsigned long Patterncount = ARRAY_SIZE(BitPatterns);
-	unsigned long i;
-	unsigned long TestLimit = SHARED_MEM_ADDRESS_SIZE/sizeof(unsigned long);
-	unsigned long * TestAddr;
-
-	if ( info->bus_type != MGSL_BUS_TYPE_PCI )
-		return true;
-
-	TestAddr = (unsigned long *)info->memory_base;
-
-	/* Test data lines with test pattern at one location. */
-
-	for ( i = 0 ; i < Patterncount ; i++ ) {
-		*TestAddr = BitPatterns[i];
-		if ( *TestAddr != BitPatterns[i] )
-			return false;
-	}
-
-	/* Test address lines with incrementing pattern over */
-	/* entire address range. */
-
-	for ( i = 0 ; i < TestLimit ; i++ ) {
-		*TestAddr = i * 4;
-		TestAddr++;
-	}
-
-	TestAddr = (unsigned long *)info->memory_base;
-
-	for ( i = 0 ; i < TestLimit ; i++ ) {
-		if ( *TestAddr != i * 4 )
-			return false;
-		TestAddr++;
-	}
-
-	memset( info->memory_base, 0, SHARED_MEM_ADDRESS_SIZE );
-
-	return true;
-
-}	/* End Of mgsl_memory_test() */
-
-
-/* mgsl_load_pci_memory()
- * 
- * 	Load a large block of data into the PCI shared memory.
- * 	Use this instead of memcpy() or memmove() to move data
- * 	into the PCI shared memory.
- * 
- * Notes:
- * 
- * 	This function prevents the PCI9050 interface chip from hogging
- * 	the adapter local bus, which can starve the 16C32 by preventing
- * 	16C32 bus master cycles.
- * 
- * 	The PCI9050 documentation says that the 9050 will always release
- * 	control of the local bus after completing the current read
- * 	or write operation.
- * 
- * 	It appears that as long as the PCI9050 write FIFO is full, the
- * 	PCI9050 treats all of the writes as a single burst transaction
- * 	and will not release the bus. This causes DMA latency problems
- * 	at high speeds when copying large data blocks to the shared
- * 	memory.
- * 
- * 	This function in effect, breaks the a large shared memory write
- * 	into multiple transations by interleaving a shared memory read
- * 	which will flush the write FIFO and 'complete' the write
- * 	transation. This allows any pending DMA request to gain control
- * 	of the local bus in a timely fasion.
- * 
- * Arguments:
- * 
- * 	TargetPtr	pointer to target address in PCI shared memory
- * 	SourcePtr	pointer to source buffer for data
- * 	count		count in bytes of data to copy
- *
- * Return Value:	None
- */
-static void mgsl_load_pci_memory( char* TargetPtr, const char* SourcePtr,
-	unsigned short count )
-{
-	/* 16 32-bit writes @ 60ns each = 960ns max latency on local bus */
-#define PCI_LOAD_INTERVAL 64
-
-	unsigned short Intervalcount = count / PCI_LOAD_INTERVAL;
-	unsigned short Index;
-	unsigned long Dummy;
-
-	for ( Index = 0 ; Index < Intervalcount ; Index++ )
-	{
-		memcpy(TargetPtr, SourcePtr, PCI_LOAD_INTERVAL);
-		Dummy = *((volatile unsigned long *)TargetPtr);
-		TargetPtr += PCI_LOAD_INTERVAL;
-		SourcePtr += PCI_LOAD_INTERVAL;
-	}
-
-	memcpy( TargetPtr, SourcePtr, count % PCI_LOAD_INTERVAL );
-
-}	/* End Of mgsl_load_pci_memory() */
-
-static void mgsl_trace_block(struct mgsl_struct *info,const char* data, int count, int xmit)
-{
-	int i;
-	int linecount;
-	if (xmit)
-		printk("%s tx data:\n",info->device_name);
-	else
-		printk("%s rx data:\n",info->device_name);
-		
-	while(count) {
-		if (count > 16)
-			linecount = 16;
-		else
-			linecount = count;
-			
-		for(i=0;i<linecount;i++)
-			printk("%02X ",(unsigned char)data[i]);
-		for(;i<17;i++)
-			printk("   ");
-		for(i=0;i<linecount;i++) {
-			if (data[i]>=040 && data[i]<=0176)
-				printk("%c",data[i]);
-			else
-				printk(".");
-		}
-		printk("\n");
-		
-		data  += linecount;
-		count -= linecount;
-	}
-}	/* end of mgsl_trace_block() */
-
-/* mgsl_tx_timeout()
- * 
- * 	called when HDLC frame times out
- * 	update stats and do tx completion processing
- * 	
- * Arguments:	context		pointer to device instance data
- * Return Value:	None
- */
-static void mgsl_tx_timeout(unsigned long context)
-{
-	struct mgsl_struct *info = (struct mgsl_struct*)context;
-	unsigned long flags;
-	
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):mgsl_tx_timeout(%s)\n",
-			__FILE__,__LINE__,info->device_name);
-	if(info->tx_active &&
-	   (info->params.mode == MGSL_MODE_HDLC ||
-	    info->params.mode == MGSL_MODE_RAW) ) {
-		info->icount.txtimeout++;
-	}
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	info->tx_active = false;
-	info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-	if ( info->params.flags & HDLC_FLAG_HDLC_LOOPMODE )
-		usc_loopmode_cancel_transmit( info );
-
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-	
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else
-#endif
-		mgsl_bh_transmit(info);
-	
-}	/* end of mgsl_tx_timeout() */
-
-/* signal that there are no more frames to send, so that
- * line is 'released' by echoing RxD to TxD when current
- * transmission is complete (or immediately if no tx in progress).
- */
-static int mgsl_loopmode_send_done( struct mgsl_struct * info )
-{
-	unsigned long flags;
-	
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (info->params.flags & HDLC_FLAG_HDLC_LOOPMODE) {
-		if (info->tx_active)
-			info->loopmode_send_done_requested = true;
-		else
-			usc_loopmode_send_done(info);
-	}
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return 0;
-}
-
-/* release the line by echoing RxD to TxD
- * upon completion of a transmit frame
- */
-static void usc_loopmode_send_done( struct mgsl_struct * info )
-{
- 	info->loopmode_send_done_requested = false;
- 	/* clear CMR:13 to 0 to start echoing RxData to TxData */
- 	info->cmr_value &= ~BIT13;			  
- 	usc_OutReg(info, CMR, info->cmr_value);
-}
-
-/* abort a transmit in progress while in HDLC LoopMode
- */
-static void usc_loopmode_cancel_transmit( struct mgsl_struct * info )
-{
- 	/* reset tx dma channel and purge TxFifo */
- 	usc_RTCmd( info, RTCmd_PurgeTxFifo );
- 	usc_DmaCmd( info, DmaCmd_ResetTxChannel );
-  	usc_loopmode_send_done( info );
-}
-
-/* for HDLC/SDLC LoopMode, setting CMR:13 after the transmitter is enabled
- * is an Insert Into Loop action. Upon receipt of a GoAhead sequence (RxAbort)
- * we must clear CMR:13 to begin repeating TxData to RxData
- */
-static void usc_loopmode_insert_request( struct mgsl_struct * info )
-{
- 	info->loopmode_insert_requested = true;
- 
- 	/* enable RxAbort irq. On next RxAbort, clear CMR:13 to
- 	 * begin repeating TxData on RxData (complete insertion)
-	 */
- 	usc_OutReg( info, RICR, 
-		(usc_InReg( info, RICR ) | RXSTATUS_ABORT_RECEIVED ) );
-		
-	/* set CMR:13 to insert into loop on next GoAhead (RxAbort) */
-	info->cmr_value |= BIT13;
- 	usc_OutReg(info, CMR, info->cmr_value);
-}
-
-/* return 1 if station is inserted into the loop, otherwise 0
- */
-static int usc_loopmode_active( struct mgsl_struct * info)
-{
- 	return usc_InReg( info, CCSR ) & BIT7 ? 1 : 0 ;
-}
-
-#if SYNCLINK_GENERIC_HDLC
-
-/**
- * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
- * set encoding and frame check sequence (FCS) options
- *
- * dev       pointer to network device structure
- * encoding  serial encoding setting
- * parity    FCS setting
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
-			  unsigned short parity)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned char  new_encoding;
-	unsigned short new_crctype;
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	switch (encoding)
-	{
-	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
-	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
-	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
-	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
-	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
-	default: return -EINVAL;
-	}
-
-	switch (parity)
-	{
-	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
-	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
-	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
-	default: return -EINVAL;
-	}
-
-	info->params.encoding = new_encoding;
-	info->params.crc_type = new_crctype;
-
-	/* if network interface up, reprogram hardware */
-	if (info->netcount)
-		mgsl_program_hw(info);
-
-	return 0;
-}
-
-/**
- * called by generic HDLC layer to send frame
- *
- * skb  socket buffer containing HDLC frame
- * dev  pointer to network device structure
- */
-static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
-
-	/* stop sending until this frame completes */
-	netif_stop_queue(dev);
-
-	/* copy data to device buffers */
-	info->xmit_cnt = skb->len;
-	mgsl_load_tx_dma_buffer(info, skb->data, skb->len);
-
-	/* update network statistics */
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
-	/* save start time for transmit timeout detection */
-	dev->trans_start = jiffies;
-
-	/* start hardware transmitter if necessary */
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	if (!info->tx_active)
-	 	usc_start_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * called by network layer when interface enabled
- * claim resources and initialize hardware
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_open(struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	int rc;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
-
-	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
-		return rc;
-
-	/* arbitrate between network and tty opens */
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->port.count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return -EBUSY;
-	}
-	info->netcount=1;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	/* claim resources and init adapter */
-	if ((rc = startup(info)) != 0) {
-		spin_lock_irqsave(&info->netlock, flags);
-		info->netcount=0;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return rc;
-	}
-
-	/* assert DTR and RTS, apply hardware settings */
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	mgsl_program_hw(info);
-
-	/* enable network layer transmit */
-	dev->trans_start = jiffies;
-	netif_start_queue(dev);
-
-	/* inform generic HDLC layer of current DCD status */
-	spin_lock_irqsave(&info->irq_spinlock, flags);
-	usc_get_serial_signals(info);
-	spin_unlock_irqrestore(&info->irq_spinlock, flags);
-	if (info->serial_signals & SerialSignal_DCD)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-	return 0;
-}
-
-/**
- * called by network layer when interface is disabled
- * shutdown hardware and release resources
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_close(struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
-
-	netif_stop_queue(dev);
-
-	/* shutdown adapter and release resources */
-	shutdown(info);
-
-	hdlc_close(dev);
-
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	return 0;
-}
-
-/**
- * called by network layer to process IOCTL call to network device
- *
- * dev  pointer to network device structure
- * ifr  pointer to network interface request structure
- * cmd  IOCTL command code
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line;
-	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned int flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	if (cmd != SIOCWANDEV)
-		return hdlc_ioctl(dev, ifr, cmd);
-
-	switch(ifr->ifr_settings.type) {
-	case IF_GET_IFACE: /* return current sync_serial_settings */
-
-		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
-		if (ifr->ifr_settings.size < size) {
-			ifr->ifr_settings.size = size; /* data size wanted */
-			return -ENOBUFS;
-		}
-
-		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-
-		switch (flags){
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
-		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
-		default: new_line.clock_type = CLOCK_DEFAULT;
-		}
-
-		new_line.clock_rate = info->params.clock_speed;
-		new_line.loopback   = info->params.loopback ? 1:0;
-
-		if (copy_to_user(line, &new_line, size))
-			return -EFAULT;
-		return 0;
-
-	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
-
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&new_line, line, size))
-			return -EFAULT;
-
-		switch (new_line.clock_type)
-		{
-		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
-		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
-		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_DEFAULT:  flags = info->params.flags &
-					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
-		default: return -EINVAL;
-		}
-
-		if (new_line.loopback != 0 && new_line.loopback != 1)
-			return -EINVAL;
-
-		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-		info->params.flags |= flags;
-
-		info->params.loopback = new_line.loopback;
-
-		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
-			info->params.clock_speed = new_line.clock_rate;
-		else
-			info->params.clock_speed = 0;
-
-		/* if network interface up, reprogram hardware */
-		if (info->netcount)
-			mgsl_program_hw(info);
-		return 0;
-
-	default:
-		return hdlc_ioctl(dev, ifr, cmd);
-	}
-}
-
-/**
- * called by network layer when transmit timeout is detected
- *
- * dev  pointer to network device structure
- */
-static void hdlcdev_tx_timeout(struct net_device *dev)
-{
-	struct mgsl_struct *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
-
-	dev->stats.tx_errors++;
-	dev->stats.tx_aborted_errors++;
-
-	spin_lock_irqsave(&info->irq_spinlock,flags);
-	usc_stop_transmitter(info);
-	spin_unlock_irqrestore(&info->irq_spinlock,flags);
-
-	netif_wake_queue(dev);
-}
-
-/**
- * called by device driver when transmit completes
- * reenable network layer transmit if stopped
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_tx_done(struct mgsl_struct *info)
-{
-	if (netif_queue_stopped(info->netdev))
-		netif_wake_queue(info->netdev);
-}
-
-/**
- * called by device driver when frame received
- * pass frame to network layer
- *
- * info  pointer to device instance information
- * buf   pointer to buffer contianing frame data
- * size  count of data bytes in buf
- */
-static void hdlcdev_rx(struct mgsl_struct *info, char *buf, int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size);
-	struct net_device *dev = info->netdev;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_rx(%s)\n", dev->name);
-
-	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-		       dev->name);
-		dev->stats.rx_dropped++;
-		return;
-	}
-
-	memcpy(skb_put(skb, size), buf, size);
-
-	skb->protocol = hdlc_type_trans(skb, dev);
-
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += size;
-
-	netif_rx(skb);
-}
-
-static const struct net_device_ops hdlcdev_ops = {
-	.ndo_open       = hdlcdev_open,
-	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
-	.ndo_start_xmit = hdlc_start_xmit,
-	.ndo_do_ioctl   = hdlcdev_ioctl,
-	.ndo_tx_timeout = hdlcdev_tx_timeout,
-};
-
-/**
- * called by device driver when adding device instance
- * do generic HDLC initialization
- *
- * info  pointer to device instance information
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_init(struct mgsl_struct *info)
-{
-	int rc;
-	struct net_device *dev;
-	hdlc_device *hdlc;
-
-	/* allocate and initialize network and HDLC layer objects */
-
-	if (!(dev = alloc_hdlcdev(info))) {
-		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
-		return -ENOMEM;
-	}
-
-	/* for network layer reporting purposes only */
-	dev->base_addr = info->io_base;
-	dev->irq       = info->irq_level;
-	dev->dma       = info->dma_level;
-
-	/* network layer callbacks and settings */
-	dev->netdev_ops     = &hdlcdev_ops;
-	dev->watchdog_timeo = 10 * HZ;
-	dev->tx_queue_len   = 50;
-
-	/* generic HDLC layer callbacks and settings */
-	hdlc         = dev_to_hdlc(dev);
-	hdlc->attach = hdlcdev_attach;
-	hdlc->xmit   = hdlcdev_xmit;
-
-	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
-		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
-		free_netdev(dev);
-		return rc;
-	}
-
-	info->netdev = dev;
-	return 0;
-}
-
-/**
- * called by device driver when removing device instance
- * do generic HDLC cleanup
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_exit(struct mgsl_struct *info)
-{
-	unregister_hdlc_device(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-}
-
-#endif /* CONFIG_HDLC */
-
-
-static int __devinit synclink_init_one (struct pci_dev *dev,
-					const struct pci_device_id *ent)
-{
-	struct mgsl_struct *info;
-
-	if (pci_enable_device(dev)) {
-		printk("error enabling pci device %p\n", dev);
-		return -EIO;
-	}
-
-	if (!(info = mgsl_allocate_device())) {
-		printk("can't allocate device instance data.\n");
-		return -EIO;
-	}
-
-        /* Copy user configuration info to device instance data */
-		
-	info->io_base = pci_resource_start(dev, 2);
-	info->irq_level = dev->irq;
-	info->phys_memory_base = pci_resource_start(dev, 3);
-				
-        /* Because veremap only works on page boundaries we must map
-	 * a larger area than is actually implemented for the LCR
-	 * memory range. We map a full page starting at the page boundary.
-	 */
-	info->phys_lcr_base = pci_resource_start(dev, 0);
-	info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
-	info->phys_lcr_base &= ~(PAGE_SIZE-1);
-				
-	info->bus_type = MGSL_BUS_TYPE_PCI;
-	info->io_addr_size = 8;
-	info->irq_flags = IRQF_SHARED;
-
-	if (dev->device == 0x0210) {
-		/* Version 1 PCI9030 based universal PCI adapter */
-		info->misc_ctrl_value = 0x007c4080;
-		info->hw_version = 1;
-	} else {
-		/* Version 0 PCI9050 based 5V PCI adapter
-		 * A PCI9050 bug prevents reading LCR registers if 
-		 * LCR base address bit 7 is set. Maintain shadow
-		 * value so we can write to LCR misc control reg.
-		 */
-		info->misc_ctrl_value = 0x087e4546;
-		info->hw_version = 0;
-	}
-				
-	mgsl_add_device(info);
-
-	return 0;
-}
-
-static void __devexit synclink_remove_one (struct pci_dev *dev)
-{
-}
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/synclink_gt.c linux-libre-2.6.39-gnu/drivers/char/synclink_gt.c
--- linux-libre-2.6.38-gnu/drivers/char/synclink_gt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/synclink_gt.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5162 +0,0 @@
-/*
- * Device driver for Microgate SyncLink GT serial adapters.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * This code is released under the GNU General Public License (GPL)
- *
- * 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.
- */
-
-/*
- * DEBUG OUTPUT DEFINITIONS
- *
- * uncomment lines below to enable specific types of debug output
- *
- * DBGINFO   information - most verbose output
- * DBGERR    serious errors
- * DBGBH     bottom half service routine debugging
- * DBGISR    interrupt service routine debugging
- * DBGDATA   output receive and transmit data
- * DBGTBUF   output transmit DMA buffers and registers
- * DBGRBUF   output receive DMA buffers and registers
- */
-
-#define DBGINFO(fmt) if (debug_level >= DEBUG_LEVEL_INFO) printk fmt
-#define DBGERR(fmt) if (debug_level >= DEBUG_LEVEL_ERROR) printk fmt
-#define DBGBH(fmt) if (debug_level >= DEBUG_LEVEL_BH) printk fmt
-#define DBGISR(fmt) if (debug_level >= DEBUG_LEVEL_ISR) printk fmt
-#define DBGDATA(info, buf, size, label) if (debug_level >= DEBUG_LEVEL_DATA) trace_block((info), (buf), (size), (label))
-/*#define DBGTBUF(info) dump_tbufs(info)*/
-/*#define DBGRBUF(info) dump_rbufs(info)*/
-
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-#include <linux/termios.h>
-#include <linux/bitops.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/synclink.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <asm/types.h>
-#include <asm/uaccess.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINK_GT_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-/*
- * module identification
- */
-static char *driver_name     = "SyncLink GT";
-static char *tty_driver_name = "synclink_gt";
-static char *tty_dev_prefix  = "ttySLG";
-MODULE_LICENSE("GPL");
-#define MGSL_MAGIC 0x5401
-#define MAX_DEVICES 32
-
-static struct pci_device_id pci_table[] = {
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT2_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_GT4_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{PCI_VENDOR_ID_MICROGATE, SYNCLINK_AC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,},
-	{0,}, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, pci_table);
-
-static int  init_one(struct pci_dev *dev,const struct pci_device_id *ent);
-static void remove_one(struct pci_dev *dev);
-static struct pci_driver pci_driver = {
-	.name		= "synclink_gt",
-	.id_table	= pci_table,
-	.probe		= init_one,
-	.remove		= __devexit_p(remove_one),
-};
-
-static bool pci_registered;
-
-/*
- * module configuration and status
- */
-static struct slgt_info *slgt_device_list;
-static int slgt_device_count;
-
-static int ttymajor;
-static int debug_level;
-static int maxframe[MAX_DEVICES];
-
-module_param(ttymajor, int, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-
-MODULE_PARM_DESC(ttymajor, "TTY major device number override: 0=auto assigned");
-MODULE_PARM_DESC(debug_level, "Debug syslog output: 0=disabled, 1 to 5=increasing detail");
-MODULE_PARM_DESC(maxframe, "Maximum frame size used by device (4096 to 65535)");
-
-/*
- * tty support and callbacks
- */
-static struct tty_driver *serial_driver;
-
-static int  open(struct tty_struct *tty, struct file * filp);
-static void close(struct tty_struct *tty, struct file * filp);
-static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-
-static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int put_char(struct tty_struct *tty, unsigned char ch);
-static void send_xchar(struct tty_struct *tty, char ch);
-static void wait_until_sent(struct tty_struct *tty, int timeout);
-static int  write_room(struct tty_struct *tty);
-static void flush_chars(struct tty_struct *tty);
-static void flush_buffer(struct tty_struct *tty);
-static void tx_hold(struct tty_struct *tty);
-static void tx_release(struct tty_struct *tty);
-
-static int  ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static int  chars_in_buffer(struct tty_struct *tty);
-static void throttle(struct tty_struct * tty);
-static void unthrottle(struct tty_struct * tty);
-static int set_break(struct tty_struct *tty, int break_state);
-
-/*
- * generic HDLC support and callbacks
- */
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(struct slgt_info *info);
-static void hdlcdev_rx(struct slgt_info *info, char *buf, int size);
-static int  hdlcdev_init(struct slgt_info *info);
-static void hdlcdev_exit(struct slgt_info *info);
-#endif
-
-
-/*
- * device specific structures, macros and functions
- */
-
-#define SLGT_MAX_PORTS 4
-#define SLGT_REG_SIZE  256
-
-/*
- * conditional wait facility
- */
-struct cond_wait {
-	struct cond_wait *next;
-	wait_queue_head_t q;
-	wait_queue_t wait;
-	unsigned int data;
-};
-static void init_cond_wait(struct cond_wait *w, unsigned int data);
-static void add_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void remove_cond_wait(struct cond_wait **head, struct cond_wait *w);
-static void flush_cond_wait(struct cond_wait **head);
-
-/*
- * DMA buffer descriptor and access macros
- */
-struct slgt_desc
-{
-	__le16 count;
-	__le16 status;
-	__le32 pbuf;  /* physical address of data buffer */
-	__le32 next;  /* physical address of next descriptor */
-
-	/* driver book keeping */
-	char *buf;          /* virtual  address of data buffer */
-    	unsigned int pdesc; /* physical address of this descriptor */
-	dma_addr_t buf_dma_addr;
-	unsigned short buf_count;
-};
-
-#define set_desc_buffer(a,b) (a).pbuf = cpu_to_le32((unsigned int)(b))
-#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)
-#define desc_eof(a)        (le16_to_cpu((a).status) & BIT2)
-#define desc_crc_error(a)  (le16_to_cpu((a).status) & BIT1)
-#define desc_abort(a)      (le16_to_cpu((a).status) & BIT0)
-#define desc_residue(a)    ((le16_to_cpu((a).status) & 0x38) >> 3)
-
-struct _input_signal_events {
-	int ri_up;
-	int ri_down;
-	int dsr_up;
-	int dsr_down;
-	int dcd_up;
-	int dcd_down;
-	int cts_up;
-	int cts_down;
-};
-
-/*
- * device instance data structure
- */
-struct slgt_info {
-	void *if_ptr;		/* General purpose pointer (used by SPPP) */
-	struct tty_port port;
-
-	struct slgt_info *next_device;	/* device list link */
-
-	int magic;
-
-	char device_name[25];
-	struct pci_dev *pdev;
-
-	int port_count;  /* count of ports on adapter */
-	int adapter_num; /* adapter instance number */
-	int port_num;    /* port instance number */
-
-	/* array of pointers to port contexts on this adapter */
-	struct slgt_info *port_array[SLGT_MAX_PORTS];
-
-	int			line;		/* tty line instance number */
-
-	struct mgsl_icount	icount;
-
-	int			timeout;
-	int			x_char;		/* xon/xoff character */
-	unsigned int		read_status_mask;
-	unsigned int 		ignore_status_mask;
-
-	wait_queue_head_t	status_event_wait_q;
-	wait_queue_head_t	event_wait_q;
-	struct timer_list	tx_timer;
-	struct timer_list	rx_timer;
-
-	unsigned int            gpio_present;
-	struct cond_wait        *gpio_wait_q;
-
-	spinlock_t lock;	/* spinlock for synchronizing with ISR */
-
-	struct work_struct task;
-	u32 pending_bh;
-	bool bh_requested;
-	bool bh_running;
-
-	int isr_overflow;
-	bool irq_requested;	/* true if IRQ requested */
-	bool irq_occurred;	/* for diagnostics use */
-
-	/* device configuration */
-
-	unsigned int bus_type;
-	unsigned int irq_level;
-	unsigned long irq_flags;
-
-	unsigned char __iomem * reg_addr;  /* memory mapped registers address */
-	u32 phys_reg_addr;
-	bool reg_addr_requested;
-
-	MGSL_PARAMS params;       /* communications parameters */
-	u32 idle_mode;
-	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;
-	unsigned int xsync;
-	unsigned int xctrl;
-
-	/* device status */
-
-	bool rx_enabled;
-	bool rx_restart;
-
-	bool tx_enabled;
-	bool tx_active;
-
-	unsigned char signals;    /* serial signal states */
-	int init_error;  /* initialization error */
-
-	unsigned char *tx_buf;
-	int tx_count;
-
-	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
-	char char_buf[MAX_ASYNC_BUFFER_SIZE];
-	bool drop_rts_on_tx_done;
-	struct	_input_signal_events	input_signal_events;
-
-	int dcd_chkcount;	/* check counts to prevent */
-	int cts_chkcount;	/* too many IRQs if a signal */
-	int dsr_chkcount;	/* is floating */
-	int ri_chkcount;
-
-	char *bufs;		/* virtual address of DMA buffer lists */
-	dma_addr_t bufs_dma_addr; /* physical address of buffer descriptors */
-
-	unsigned int rbuf_count;
-	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;
-	unsigned int tbuf_current;
-	unsigned int tbuf_start;
-
-	unsigned char *tmp_rbuf;
-	unsigned int tmp_rbuf_count;
-
-	/* SPPP/Cisco HDLC device parts */
-
-	int netcount;
-	spinlock_t netlock;
-#if SYNCLINK_GENERIC_HDLC
-	struct net_device *netdev;
-#endif
-
-};
-
-static MGSL_PARAMS default_params = {
-	.mode            = MGSL_MODE_HDLC,
-	.loopback        = 0,
-	.flags           = HDLC_FLAG_UNDERRUN_ABORT15,
-	.encoding        = HDLC_ENCODING_NRZI_SPACE,
-	.clock_speed     = 0,
-	.addr_filter     = 0xff,
-	.crc_type        = HDLC_CRC_16_CCITT,
-	.preamble_length = HDLC_PREAMBLE_LENGTH_8BITS,
-	.preamble        = HDLC_PREAMBLE_PATTERN_NONE,
-	.data_rate       = 9600,
-	.data_bits       = 8,
-	.stop_bits       = 1,
-	.parity          = ASYNC_PARITY_NONE
-};
-
-
-#define BH_RECEIVE  1
-#define BH_TRANSMIT 2
-#define BH_STATUS   4
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-#define DMABUFSIZE 256
-#define DESC_LIST_SIZE 4096
-
-#define MASK_PARITY  BIT1
-#define MASK_FRAMING BIT0
-#define MASK_BREAK   BIT14
-#define MASK_OVERRUN BIT4
-
-#define GSR   0x00 /* global status */
-#define JCR   0x04 /* JTAG control */
-#define IODR  0x08 /* GPIO direction */
-#define IOER  0x0c /* GPIO interrupt enable */
-#define IOVR  0x10 /* GPIO value */
-#define IOSR  0x14 /* GPIO interrupt status */
-#define TDR   0x80 /* tx data */
-#define RDR   0x80 /* rx data */
-#define TCR   0x82 /* tx control */
-#define TIR   0x84 /* tx idle */
-#define TPR   0x85 /* tx preamble */
-#define RCR   0x86 /* rx control */
-#define VCR   0x88 /* V.24 control */
-#define CCR   0x89 /* clock control */
-#define BDR   0x8a /* baud divisor */
-#define SCR   0x8c /* serial control */
-#define SSR   0x8e /* serial status */
-#define RDCSR 0x90 /* rx DMA control/status */
-#define TDCSR 0x94 /* tx DMA control/status */
-#define RDDAR 0x98 /* rx DMA descriptor address */
-#define TDDAR 0x9c /* tx DMA descriptor address */
-#define XSR   0x40 /* extended sync pattern */
-#define XCR   0x44 /* extended control */
-
-#define RXIDLE      BIT14
-#define RXBREAK     BIT14
-#define IRQ_TXDATA  BIT13
-#define IRQ_TXIDLE  BIT12
-#define IRQ_TXUNDER BIT11 /* HDLC */
-#define IRQ_RXDATA  BIT10
-#define IRQ_RXIDLE  BIT9  /* HDLC */
-#define IRQ_RXBREAK BIT9  /* async */
-#define IRQ_RXOVER  BIT8
-#define IRQ_DSR     BIT7
-#define IRQ_CTS     BIT6
-#define IRQ_DCD     BIT5
-#define IRQ_RI      BIT4
-#define IRQ_ALL     0x3ff0
-#define IRQ_MASTER  BIT0
-
-#define slgt_irq_on(info, mask) \
-	wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) | (mask)))
-#define slgt_irq_off(info, mask) \
-	wr_reg16((info), SCR, (unsigned short)(rd_reg16((info), SCR) & ~(mask)))
-
-static __u8  rd_reg8(struct slgt_info *info, unsigned int addr);
-static void  wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value);
-static __u16 rd_reg16(struct slgt_info *info, unsigned int addr);
-static void  wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value);
-static __u32 rd_reg32(struct slgt_info *info, unsigned int addr);
-static void  wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value);
-
-static void  msc_set_vcr(struct slgt_info *info);
-
-static int  startup(struct slgt_info *info);
-static int  block_til_ready(struct tty_struct *tty, struct file * filp,struct slgt_info *info);
-static void shutdown(struct slgt_info *info);
-static void program_hw(struct slgt_info *info);
-static void change_params(struct slgt_info *info);
-
-static int  register_test(struct slgt_info *info);
-static int  irq_test(struct slgt_info *info);
-static int  loopback_test(struct slgt_info *info);
-static int  adapter_test(struct slgt_info *info);
-
-static void reset_adapter(struct slgt_info *info);
-static void reset_port(struct slgt_info *info);
-static void async_mode(struct slgt_info *info);
-static void sync_mode(struct slgt_info *info);
-
-static void rx_stop(struct slgt_info *info);
-static void rx_start(struct slgt_info *info);
-static void reset_rbufs(struct slgt_info *info);
-static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
-static void rdma_reset(struct slgt_info *info);
-static bool rx_get_frame(struct slgt_info *info);
-static bool rx_get_buf(struct slgt_info *info);
-
-static void tx_start(struct slgt_info *info);
-static void tx_stop(struct slgt_info *info);
-static void tx_set_idle(struct slgt_info *info);
-static unsigned int free_tbuf_count(struct slgt_info *info);
-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 bool tx_load(struct slgt_info *info, const char *buf, unsigned int count);
-
-static void get_signals(struct slgt_info *info);
-static void set_signals(struct slgt_info *info);
-static void enable_loopback(struct slgt_info *info);
-static void set_rate(struct slgt_info *info, u32 data_rate);
-
-static int  bh_action(struct slgt_info *info);
-static void bh_handler(struct work_struct *work);
-static void bh_transmit(struct slgt_info *info);
-static void isr_serial(struct slgt_info *info);
-static void isr_rdma(struct slgt_info *info);
-static void isr_txeom(struct slgt_info *info, unsigned short status);
-static void isr_tdma(struct slgt_info *info);
-
-static int  alloc_dma_bufs(struct slgt_info *info);
-static void free_dma_bufs(struct slgt_info *info);
-static int  alloc_desc(struct slgt_info *info);
-static void free_desc(struct slgt_info *info);
-static int  alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count);
-
-static int  alloc_tmp_rbuf(struct slgt_info *info);
-static void free_tmp_rbuf(struct slgt_info *info);
-
-static void tx_timeout(unsigned long context);
-static void rx_timeout(unsigned long context);
-
-/*
- * ioctl handlers
- */
-static int  get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount);
-static int  get_params(struct slgt_info *info, MGSL_PARAMS __user *params);
-static int  set_params(struct slgt_info *info, MGSL_PARAMS __user *params);
-static int  get_txidle(struct slgt_info *info, int __user *idle_mode);
-static int  set_txidle(struct slgt_info *info, int idle_mode);
-static int  tx_enable(struct slgt_info *info, int enable);
-static int  tx_abort(struct slgt_info *info);
-static int  rx_enable(struct slgt_info *info, int enable);
-static int  modem_input_wait(struct slgt_info *info,int arg);
-static int  wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
-static int  tiocmget(struct tty_struct *tty, struct file *file);
-static int  tiocmset(struct tty_struct *tty, struct file *file,
-		     unsigned int set, unsigned int clear);
-static int set_break(struct tty_struct *tty, int break_state);
-static int  get_interface(struct slgt_info *info, int __user *if_mode);
-static int  set_interface(struct slgt_info *info, int if_mode);
-static int  set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int  get_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int  wait_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
-static int  get_xsync(struct slgt_info *info, int __user *if_mode);
-static int  set_xsync(struct slgt_info *info, int if_mode);
-static int  get_xctrl(struct slgt_info *info, int __user *if_mode);
-static int  set_xctrl(struct slgt_info *info, int if_mode);
-
-/*
- * driver functions
- */
-static void add_device(struct slgt_info *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
-static int  claim_resources(struct slgt_info *info);
-static void release_resources(struct slgt_info *info);
-
-/*
- * DEBUG OUTPUT CODE
- */
-#ifndef DBGINFO
-#define DBGINFO(fmt)
-#endif
-#ifndef DBGERR
-#define DBGERR(fmt)
-#endif
-#ifndef DBGBH
-#define DBGBH(fmt)
-#endif
-#ifndef DBGISR
-#define DBGISR(fmt)
-#endif
-
-#ifdef DBGDATA
-static void trace_block(struct slgt_info *info, const char *data, int count, const char *label)
-{
-	int i;
-	int linecount;
-	printk("%s %s data:\n",info->device_name, label);
-	while(count) {
-		linecount = (count > 16) ? 16 : count;
-		for(i=0; i < linecount; i++)
-			printk("%02X ",(unsigned char)data[i]);
-		for(;i<17;i++)
-			printk("   ");
-		for(i=0;i<linecount;i++) {
-			if (data[i]>=040 && data[i]<=0176)
-				printk("%c",data[i]);
-			else
-				printk(".");
-		}
-		printk("\n");
-		data  += linecount;
-		count -= linecount;
-	}
-}
-#else
-#define DBGDATA(info, buf, size, label)
-#endif
-
-#ifdef DBGTBUF
-static void dump_tbufs(struct slgt_info *info)
-{
-	int i;
-	printk("tbuf_current=%d\n", info->tbuf_current);
-	for (i=0 ; i < info->tbuf_count ; i++) {
-		printk("%d: count=%04X status=%04X\n",
-			i, le16_to_cpu(info->tbufs[i].count), le16_to_cpu(info->tbufs[i].status));
-	}
-}
-#else
-#define DBGTBUF(info)
-#endif
-
-#ifdef DBGRBUF
-static void dump_rbufs(struct slgt_info *info)
-{
-	int i;
-	printk("rbuf_current=%d\n", info->rbuf_current);
-	for (i=0 ; i < info->rbuf_count ; i++) {
-		printk("%d: count=%04X status=%04X\n",
-			i, le16_to_cpu(info->rbufs[i].count), le16_to_cpu(info->rbufs[i].status));
-	}
-}
-#else
-#define DBGRBUF(info)
-#endif
-
-static inline int sanity_check(struct slgt_info *info, char *devname, const char *name)
-{
-#ifdef SANITY_CHECK
-	if (!info) {
-		printk("null struct slgt_info for (%s) in %s\n", devname, name);
-		return 1;
-	}
-	if (info->magic != MGSL_MAGIC) {
-		printk("bad magic number struct slgt_info (%s) in %s\n", devname, name);
-		return 1;
-	}
-#else
-	if (!info)
-		return 1;
-#endif
-	return 0;
-}
-
-/**
- * line discipline callback wrappers
- *
- * The wrappers maintain line discipline references
- * while calling into the line discipline.
- *
- * ldisc_receive_buf  - pass receive data to line discipline
- */
-static void ldisc_receive_buf(struct tty_struct *tty,
-			      const __u8 *data, char *flags, int count)
-{
-	struct tty_ldisc *ld;
-	if (!tty)
-		return;
-	ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->receive_buf)
-			ld->ops->receive_buf(tty, data, flags, count);
-		tty_ldisc_deref(ld);
-	}
-}
-
-/* tty callbacks */
-
-static int open(struct tty_struct *tty, struct file *filp)
-{
-	struct slgt_info *info;
-	int retval, line;
-	unsigned long flags;
-
-	line = tty->index;
-	if ((line < 0) || (line >= slgt_device_count)) {
-		DBGERR(("%s: open with invalid line #%d.\n", driver_name, line));
-		return -ENODEV;
-	}
-
-	info = slgt_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (sanity_check(info, tty->name, "open"))
-		return -ENODEV;
-	if (info->init_error) {
-		DBGERR(("%s init error=%d\n", info->device_name, info->init_error));
-		return -ENODEV;
-	}
-
-	tty->driver_data = info;
-	info->port.tty = tty;
-
-	DBGINFO(("%s open, old ref count = %d\n", info->device_name, info->port.count));
-
-	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-		if (info->port.flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->port.close_wait);
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
-	mutex_lock(&info->port.mutex);
-	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->netcount) {
-		retval = -EBUSY;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		mutex_unlock(&info->port.mutex);
-		goto cleanup;
-	}
-	info->port.count++;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	if (info->port.count == 1) {
-		/* 1st open on this device, init hardware */
-		retval = startup(info);
-		if (retval < 0) {
-			mutex_unlock(&info->port.mutex);
-			goto cleanup;
-		}
-	}
-	mutex_unlock(&info->port.mutex);
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		DBGINFO(("%s block_til_ready rc=%d\n", info->device_name, retval));
-		goto cleanup;
-	}
-
-	retval = 0;
-
-cleanup:
-	if (retval) {
-		if (tty->count == 1)
-			info->port.tty = NULL; /* tty layer will release tty struct */
-		if(info->port.count)
-			info->port.count--;
-	}
-
-	DBGINFO(("%s open rc=%d\n", info->device_name, retval));
-	return retval;
-}
-
-static void close(struct tty_struct *tty, struct file *filp)
-{
-	struct slgt_info *info = tty->driver_data;
-
-	if (sanity_check(info, tty->name, "close"))
-		return;
-	DBGINFO(("%s close entry, count=%d\n", info->device_name, info->port.count));
-
-	if (tty_port_close_start(&info->port, tty, filp) == 0)
-		goto cleanup;
-
-	mutex_lock(&info->port.mutex);
- 	if (info->port.flags & ASYNC_INITIALIZED)
- 		wait_until_sent(tty, info->timeout);
-	flush_buffer(tty);
-	tty_ldisc_flush(tty);
-
-	shutdown(info);
-	mutex_unlock(&info->port.mutex);
-
-	tty_port_close_end(&info->port, tty);
-	info->port.tty = NULL;
-cleanup:
-	DBGINFO(("%s close exit, count=%d\n", tty->driver->name, info->port.count));
-}
-
-static void hangup(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "hangup"))
-		return;
-	DBGINFO(("%s hangup\n", info->device_name));
-
-	flush_buffer(tty);
-
-	mutex_lock(&info->port.mutex);
-	shutdown(info);
-
-	spin_lock_irqsave(&info->port.lock, flags);
-	info->port.count = 0;
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-	spin_unlock_irqrestore(&info->port.lock, flags);
-	mutex_unlock(&info->port.mutex);
-
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	DBGINFO(("%s set_termios\n", tty->driver->name));
-
-	change_params(info);
-
-	/* Handle transition to B0 status */
-	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-		spin_lock_irqsave(&info->lock,flags);
-		set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
-		info->signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
- 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->signals |= SerialSignal_RTS;
- 		}
-		spin_lock_irqsave(&info->lock,flags);
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		tx_release(tty);
-	}
-}
-
-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)
-{
-	int ret = 0;
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "write"))
-		return -EIO;
-
-	DBGINFO(("%s write count=%d\n", info->device_name, count));
-
-	if (!info->tx_buf || (count > info->max_frame_size))
-		return -EIO;
-
-	if (!count || tty->stopped || tty->hw_stopped)
-		return 0;
-
-	spin_lock_irqsave(&info->lock, flags);
-
-	if (info->tx_count) {
-		/* send accumulated data from send_char() */
-		if (!tx_load(info, info->tx_buf, info->tx_count))
-			goto cleanup;
-		info->tx_count = 0;
-	}
-
-	if (tx_load(info, buf, count))
-		ret = count;
-
-cleanup:
-	spin_unlock_irqrestore(&info->lock, flags);
-	DBGINFO(("%s write rc=%d\n", info->device_name, ret));
-	return ret;
-}
-
-static int put_char(struct tty_struct *tty, unsigned char ch)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if (sanity_check(info, tty->name, "put_char"))
-		return 0;
-	DBGINFO(("%s put_char(%d)\n", info->device_name, ch));
-	if (!info->tx_buf)
-		return 0;
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_count < info->max_frame_size) {
-		info->tx_buf[info->tx_count++] = ch;
-		ret = 1;
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return ret;
-}
-
-static void send_xchar(struct tty_struct *tty, char ch)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "send_xchar"))
-		return;
-	DBGINFO(("%s send_xchar(%d)\n", info->device_name, ch));
-	info->x_char = ch;
-	if (ch) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_enabled)
-		 	tx_start(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-static void wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-
-	if (!info )
-		return;
-	if (sanity_check(info, tty->name, "wait_until_sent"))
-		return;
-	DBGINFO(("%s wait_until_sent entry\n", info->device_name));
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		goto exit;
-
-	orig_jiffies = jiffies;
-
-	/* Set check interval to 1/5 of estimated time to
-	 * send a character, and make it at least 1. The check
-	 * interval should also be less than the timeout.
-	 * Note: use tight timings here to satisfy the NIST-PCTS.
-	 */
-
-	if (info->params.data_rate) {
-	       	char_time = info->timeout/(32 * 5);
-		if (!char_time)
-			char_time++;
-	} else
-		char_time = 1;
-
-	if (timeout)
-		char_time = min_t(unsigned long, char_time, timeout);
-
-	while (info->tx_active) {
-		msleep_interruptible(jiffies_to_msecs(char_time));
-		if (signal_pending(current))
-			break;
-		if (timeout && time_after(jiffies, orig_jiffies + timeout))
-			break;
-	}
-exit:
-	DBGINFO(("%s wait_until_sent exit\n", info->device_name));
-}
-
-static int write_room(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	int ret;
-
-	if (sanity_check(info, tty->name, "write_room"))
-		return 0;
-	ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
-	DBGINFO(("%s write_room=%d\n", info->device_name, ret));
-	return ret;
-}
-
-static void flush_chars(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "flush_chars"))
-		return;
-	DBGINFO(("%s flush_chars entry tx_count=%d\n", info->device_name, info->tx_count));
-
-	if (info->tx_count <= 0 || tty->stopped ||
-	    tty->hw_stopped || !info->tx_buf)
-		return;
-
-	DBGINFO(("%s flush_chars start transmit\n", info->device_name));
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
-		info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-static void flush_buffer(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "flush_buffer"))
-		return;
-	DBGINFO(("%s flush_buffer\n", info->device_name));
-
-	spin_lock_irqsave(&info->lock, flags);
-	info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	tty_wakeup(tty);
-}
-
-/*
- * throttle (stop) transmitter
- */
-static void tx_hold(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_hold"))
-		return;
-	DBGINFO(("%s tx_hold\n", info->device_name));
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_enabled && info->params.mode == MGSL_MODE_ASYNC)
-	 	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/*
- * release (start) transmitter
- */
-static void tx_release(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_release"))
-		return;
-	DBGINFO(("%s tx_release\n", info->device_name));
-	spin_lock_irqsave(&info->lock, flags);
-	if (info->tx_count && tx_load(info, info->tx_buf, info->tx_count))
-		info->tx_count = 0;
-	spin_unlock_irqrestore(&info->lock, flags);
-}
-
-/*
- * Service an IOCTL request
- *
- * Arguments
- *
- * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
- * 	cmd	IOCTL command code
- * 	arg	command argument/context
- *
- * Return 0 if success, otherwise error code
- */
-static int ioctl(struct tty_struct *tty, struct file *file,
-		 unsigned int cmd, unsigned long arg)
-{
-	struct slgt_info *info = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-	int ret;
-
-	if (sanity_check(info, tty->name, "ioctl"))
-		return -ENODEV;
-	DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-	case MGSL_IOCWAITEVENT:
-		return wait_mgsl_event(info, argp);
-	case TIOCMIWAIT:
-		return modem_input_wait(info,(int)arg);
-	case MGSL_IOCSGPIO:
-		return set_gpio(info, argp);
-	case MGSL_IOCGGPIO:
-		return get_gpio(info, argp);
-	case MGSL_IOCWAITGPIO:
-		return wait_gpio(info, argp);
-	case MGSL_IOCGXSYNC:
-		return get_xsync(info, argp);
-	case MGSL_IOCSXSYNC:
-		return set_xsync(info, (int)arg);
-	case MGSL_IOCGXCTRL:
-		return get_xctrl(info, argp);
-	case MGSL_IOCSXCTRL:
-		return set_xctrl(info, (int)arg);
-	}
-	mutex_lock(&info->port.mutex);
-	switch (cmd) {
-	case MGSL_IOCGPARAMS:
-		ret = get_params(info, argp);
-		break;
-	case MGSL_IOCSPARAMS:
-		ret = set_params(info, argp);
-		break;
-	case MGSL_IOCGTXIDLE:
-		ret = get_txidle(info, argp);
-		break;
-	case MGSL_IOCSTXIDLE:
-		ret = set_txidle(info, (int)arg);
-		break;
-	case MGSL_IOCTXENABLE:
-		ret = tx_enable(info, (int)arg);
-		break;
-	case MGSL_IOCRXENABLE:
-		ret = rx_enable(info, (int)arg);
-		break;
-	case MGSL_IOCTXABORT:
-		ret = tx_abort(info);
-		break;
-	case MGSL_IOCGSTATS:
-		ret = get_stats(info, argp);
-		break;
-	case MGSL_IOCGIF:
-		ret = get_interface(info, argp);
-		break;
-	case MGSL_IOCSIF:
-		ret = set_interface(info,(int)arg);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-	mutex_unlock(&info->port.mutex);
-	return ret;
-}
-
-static int get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-
-{
-	struct slgt_info *info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-/*
- * support for 32 bit ioctl calls on 64 bit systems
- */
-#ifdef CONFIG_COMPAT
-static long get_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *user_params)
-{
-	struct MGSL_PARAMS32 tmp_params;
-
-	DBGINFO(("%s get_params32\n", info->device_name));
-	memset(&tmp_params, 0, sizeof(tmp_params));
-	tmp_params.mode            = (compat_ulong_t)info->params.mode;
-	tmp_params.loopback        = info->params.loopback;
-	tmp_params.flags           = info->params.flags;
-	tmp_params.encoding        = info->params.encoding;
-	tmp_params.clock_speed     = (compat_ulong_t)info->params.clock_speed;
-	tmp_params.addr_filter     = info->params.addr_filter;
-	tmp_params.crc_type        = info->params.crc_type;
-	tmp_params.preamble_length = info->params.preamble_length;
-	tmp_params.preamble        = info->params.preamble;
-	tmp_params.data_rate       = (compat_ulong_t)info->params.data_rate;
-	tmp_params.data_bits       = info->params.data_bits;
-	tmp_params.stop_bits       = info->params.stop_bits;
-	tmp_params.parity          = info->params.parity;
-	if (copy_to_user(user_params, &tmp_params, sizeof(struct MGSL_PARAMS32)))
-		return -EFAULT;
-	return 0;
-}
-
-static long set_params32(struct slgt_info *info, struct MGSL_PARAMS32 __user *new_params)
-{
-	struct MGSL_PARAMS32 tmp_params;
-
-	DBGINFO(("%s set_params32\n", info->device_name));
-	if (copy_from_user(&tmp_params, new_params, sizeof(struct MGSL_PARAMS32)))
-		return -EFAULT;
-
-	spin_lock(&info->lock);
-	if (tmp_params.mode == MGSL_MODE_BASE_CLOCK) {
-		info->base_clock = tmp_params.clock_speed;
-	} else {
-		info->params.mode            = tmp_params.mode;
-		info->params.loopback        = tmp_params.loopback;
-		info->params.flags           = tmp_params.flags;
-		info->params.encoding        = tmp_params.encoding;
-		info->params.clock_speed     = tmp_params.clock_speed;
-		info->params.addr_filter     = tmp_params.addr_filter;
-		info->params.crc_type        = tmp_params.crc_type;
-		info->params.preamble_length = tmp_params.preamble_length;
-		info->params.preamble        = tmp_params.preamble;
-		info->params.data_rate       = tmp_params.data_rate;
-		info->params.data_bits       = tmp_params.data_bits;
-		info->params.stop_bits       = tmp_params.stop_bits;
-		info->params.parity          = tmp_params.parity;
-	}
-	spin_unlock(&info->lock);
-
-	program_hw(info);
-
-	return 0;
-}
-
-static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
-			 unsigned int cmd, unsigned long arg)
-{
-	struct slgt_info *info = tty->driver_data;
-	int rc = -ENOIOCTLCMD;
-
-	if (sanity_check(info, tty->name, "compat_ioctl"))
-		return -ENODEV;
-	DBGINFO(("%s compat_ioctl() cmd=%08X\n", info->device_name, cmd));
-
-	switch (cmd) {
-
-	case MGSL_IOCSPARAMS32:
-		rc = set_params32(info, compat_ptr(arg));
-		break;
-
-	case MGSL_IOCGPARAMS32:
-		rc = get_params32(info, compat_ptr(arg));
-		break;
-
-	case MGSL_IOCGPARAMS:
-	case MGSL_IOCSPARAMS:
-	case MGSL_IOCGTXIDLE:
-	case MGSL_IOCGSTATS:
-	case MGSL_IOCWAITEVENT:
-	case MGSL_IOCGIF:
-	case MGSL_IOCSGPIO:
-	case MGSL_IOCGGPIO:
-	case MGSL_IOCWAITGPIO:
-	case MGSL_IOCGXSYNC:
-	case MGSL_IOCGXCTRL:
-	case MGSL_IOCSTXIDLE:
-	case MGSL_IOCTXENABLE:
-	case MGSL_IOCRXENABLE:
-	case MGSL_IOCTXABORT:
-	case TIOCMIWAIT:
-	case MGSL_IOCSIF:
-	case MGSL_IOCSXSYNC:
-	case MGSL_IOCSXCTRL:
-		rc = ioctl(tty, file, cmd, arg);
-		break;
-	}
-
-	DBGINFO(("%s compat_ioctl() cmd=%08X rc=%d\n", info->device_name, cmd, rc));
-	return rc;
-}
-#else
-#define slgt_compat_ioctl NULL
-#endif /* ifdef CONFIG_COMPAT */
-
-/*
- * proc fs support
- */
-static inline void line_info(struct seq_file *m, struct slgt_info *info)
-{
-	char stat_buf[30];
-	unsigned long flags;
-
-	seq_printf(m, "%s: IO=%08X IRQ=%d MaxFrameSize=%u\n",
-		      info->device_name, info->phys_reg_addr,
-		      info->irq_level, info->max_frame_size);
-
-	/* output current serial signal states */
-	spin_lock_irqsave(&info->lock,flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (info->signals & SerialSignal_RTS)
-		strcat(stat_buf, "|RTS");
-	if (info->signals & SerialSignal_CTS)
-		strcat(stat_buf, "|CTS");
-	if (info->signals & SerialSignal_DTR)
-		strcat(stat_buf, "|DTR");
-	if (info->signals & SerialSignal_DSR)
-		strcat(stat_buf, "|DSR");
-	if (info->signals & SerialSignal_DCD)
-		strcat(stat_buf, "|CD");
-	if (info->signals & SerialSignal_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		seq_printf(m, "\tHDLC txok:%d rxok:%d",
-			       info->icount.txok, info->icount.rxok);
-		if (info->icount.txunder)
-			seq_printf(m, " txunder:%d", info->icount.txunder);
-		if (info->icount.txabort)
-			seq_printf(m, " txabort:%d", info->icount.txabort);
-		if (info->icount.rxshort)
-			seq_printf(m, " rxshort:%d", info->icount.rxshort);
-		if (info->icount.rxlong)
-			seq_printf(m, " rxlong:%d", info->icount.rxlong);
-		if (info->icount.rxover)
-			seq_printf(m, " rxover:%d", info->icount.rxover);
-		if (info->icount.rxcrc)
-			seq_printf(m, " rxcrc:%d", info->icount.rxcrc);
-	} else {
-		seq_printf(m, "\tASYNC tx:%d rx:%d",
-			       info->icount.tx, info->icount.rx);
-		if (info->icount.frame)
-			seq_printf(m, " fe:%d", info->icount.frame);
-		if (info->icount.parity)
-			seq_printf(m, " pe:%d", info->icount.parity);
-		if (info->icount.brk)
-			seq_printf(m, " brk:%d", info->icount.brk);
-		if (info->icount.overrun)
-			seq_printf(m, " oe:%d", info->icount.overrun);
-	}
-
-	/* Append serial signal status to end */
-	seq_printf(m, " %s\n", stat_buf+1);
-
-	seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
-		       info->tx_active,info->bh_requested,info->bh_running,
-		       info->pending_bh);
-}
-
-/* Called to print information about devices
- */
-static int synclink_gt_proc_show(struct seq_file *m, void *v)
-{
-	struct slgt_info *info;
-
-	seq_puts(m, "synclink_gt driver\n");
-
-	info = slgt_device_list;
-	while( info ) {
-		line_info(m, info);
-		info = info->next_device;
-	}
-	return 0;
-}
-
-static int synclink_gt_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, synclink_gt_proc_show, NULL);
-}
-
-static const struct file_operations synclink_gt_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= synclink_gt_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/*
- * return count of bytes in transmit buffer
- */
-static int chars_in_buffer(struct tty_struct *tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	int count;
-	if (sanity_check(info, tty->name, "chars_in_buffer"))
-		return 0;
-	count = tbuf_bytes(info);
-	DBGINFO(("%s chars_in_buffer()=%d\n", info->device_name, count));
-	return count;
-}
-
-/*
- * signal remote device to throttle send data (our receive data)
- */
-static void throttle(struct tty_struct * tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "throttle"))
-		return;
-	DBGINFO(("%s throttle\n", info->device_name));
-	if (I_IXOFF(tty))
-		send_xchar(tty, STOP_CHAR(tty));
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->signals &= ~SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/*
- * signal remote device to stop throttling send data (our receive data)
- */
-static void unthrottle(struct tty_struct * tty)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "unthrottle"))
-		return;
-	DBGINFO(("%s unthrottle\n", info->device_name));
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			send_xchar(tty, START_CHAR(tty));
-	}
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->signals |= SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/*
- * set or clear transmit break condition
- * break_state	-1=set break condition, 0=clear
- */
-static int set_break(struct tty_struct *tty, int break_state)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned short value;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "set_break"))
-		return -EINVAL;
-	DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
-
-	spin_lock_irqsave(&info->lock,flags);
-	value = rd_reg16(info, TCR);
- 	if (break_state == -1)
-		value |= BIT6;
-	else
-		value &= ~BIT6;
-	wr_reg16(info, TCR, value);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-#if SYNCLINK_GENERIC_HDLC
-
-/**
- * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
- * set encoding and frame check sequence (FCS) options
- *
- * dev       pointer to network device structure
- * encoding  serial encoding setting
- * parity    FCS setting
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
-			  unsigned short parity)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned char  new_encoding;
-	unsigned short new_crctype;
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	DBGINFO(("%s hdlcdev_attach\n", info->device_name));
-
-	switch (encoding)
-	{
-	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
-	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
-	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
-	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
-	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
-	default: return -EINVAL;
-	}
-
-	switch (parity)
-	{
-	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
-	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
-	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
-	default: return -EINVAL;
-	}
-
-	info->params.encoding = new_encoding;
-	info->params.crc_type = new_crctype;
-
-	/* if network interface up, reprogram hardware */
-	if (info->netcount)
-		program_hw(info);
-
-	return 0;
-}
-
-/**
- * called by generic HDLC layer to send frame
- *
- * skb  socket buffer containing HDLC frame
- * dev  pointer to network device structure
- */
-static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned long flags;
-
-	DBGINFO(("%s hdlc_xmit\n", dev->name));
-
-	if (!skb->len)
-		return NETDEV_TX_OK;
-
-	/* stop sending until this frame completes */
-	netif_stop_queue(dev);
-
-	/* update network statistics */
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* save start time for transmit timeout detection */
-	dev->trans_start = jiffies;
-
-	spin_lock_irqsave(&info->lock, flags);
-	tx_load(info, skb->data, skb->len);
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * called by network layer when interface enabled
- * claim resources and initialize hardware
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_open(struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	int rc;
-	unsigned long flags;
-
-	if (!try_module_get(THIS_MODULE))
-		return -EBUSY;
-
-	DBGINFO(("%s hdlcdev_open\n", dev->name));
-
-	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
-		return rc;
-
-	/* arbitrate between network and tty opens */
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->port.count != 0 || info->netcount != 0) {
-		DBGINFO(("%s hdlc_open busy\n", dev->name));
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return -EBUSY;
-	}
-	info->netcount=1;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	/* claim resources and init adapter */
-	if ((rc = startup(info)) != 0) {
-		spin_lock_irqsave(&info->netlock, flags);
-		info->netcount=0;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return rc;
-	}
-
-	/* assert DTR and RTS, apply hardware settings */
-	info->signals |= SerialSignal_RTS + SerialSignal_DTR;
-	program_hw(info);
-
-	/* enable network layer transmit */
-	dev->trans_start = jiffies;
-	netif_start_queue(dev);
-
-	/* inform generic HDLC layer of current DCD status */
-	spin_lock_irqsave(&info->lock, flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock, flags);
-	if (info->signals & SerialSignal_DCD)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-	return 0;
-}
-
-/**
- * called by network layer when interface is disabled
- * shutdown hardware and release resources
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_close(struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned long flags;
-
-	DBGINFO(("%s hdlcdev_close\n", dev->name));
-
-	netif_stop_queue(dev);
-
-	/* shutdown adapter and release resources */
-	shutdown(info);
-
-	hdlc_close(dev);
-
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	module_put(THIS_MODULE);
-	return 0;
-}
-
-/**
- * called by network layer to process IOCTL call to network device
- *
- * dev  pointer to network device structure
- * ifr  pointer to network interface request structure
- * cmd  IOCTL command code
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line;
-	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned int flags;
-
-	DBGINFO(("%s hdlcdev_ioctl\n", dev->name));
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	if (cmd != SIOCWANDEV)
-		return hdlc_ioctl(dev, ifr, cmd);
-
-	memset(&new_line, 0, sizeof(new_line));
-
-	switch(ifr->ifr_settings.type) {
-	case IF_GET_IFACE: /* return current sync_serial_settings */
-
-		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
-		if (ifr->ifr_settings.size < size) {
-			ifr->ifr_settings.size = size; /* data size wanted */
-			return -ENOBUFS;
-		}
-
-		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-
-		switch (flags){
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
-		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
-		default: new_line.clock_type = CLOCK_DEFAULT;
-		}
-
-		new_line.clock_rate = info->params.clock_speed;
-		new_line.loopback   = info->params.loopback ? 1:0;
-
-		if (copy_to_user(line, &new_line, size))
-			return -EFAULT;
-		return 0;
-
-	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
-
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&new_line, line, size))
-			return -EFAULT;
-
-		switch (new_line.clock_type)
-		{
-		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
-		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
-		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_DEFAULT:  flags = info->params.flags &
-					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
-		default: return -EINVAL;
-		}
-
-		if (new_line.loopback != 0 && new_line.loopback != 1)
-			return -EINVAL;
-
-		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-		info->params.flags |= flags;
-
-		info->params.loopback = new_line.loopback;
-
-		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
-			info->params.clock_speed = new_line.clock_rate;
-		else
-			info->params.clock_speed = 0;
-
-		/* if network interface up, reprogram hardware */
-		if (info->netcount)
-			program_hw(info);
-		return 0;
-
-	default:
-		return hdlc_ioctl(dev, ifr, cmd);
-	}
-}
-
-/**
- * called by network layer when transmit timeout is detected
- *
- * dev  pointer to network device structure
- */
-static void hdlcdev_tx_timeout(struct net_device *dev)
-{
-	struct slgt_info *info = dev_to_port(dev);
-	unsigned long flags;
-
-	DBGINFO(("%s hdlcdev_tx_timeout\n", dev->name));
-
-	dev->stats.tx_errors++;
-	dev->stats.tx_aborted_errors++;
-
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	netif_wake_queue(dev);
-}
-
-/**
- * called by device driver when transmit completes
- * reenable network layer transmit if stopped
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_tx_done(struct slgt_info *info)
-{
-	if (netif_queue_stopped(info->netdev))
-		netif_wake_queue(info->netdev);
-}
-
-/**
- * called by device driver when frame received
- * pass frame to network layer
- *
- * info  pointer to device instance information
- * buf   pointer to buffer contianing frame data
- * size  count of data bytes in buf
- */
-static void hdlcdev_rx(struct slgt_info *info, char *buf, int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size);
-	struct net_device *dev = info->netdev;
-
-	DBGINFO(("%s hdlcdev_rx\n", dev->name));
-
-	if (skb == NULL) {
-		DBGERR(("%s: can't alloc skb, drop packet\n", dev->name));
-		dev->stats.rx_dropped++;
-		return;
-	}
-
-	memcpy(skb_put(skb, size), buf, size);
-
-	skb->protocol = hdlc_type_trans(skb, dev);
-
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += size;
-
-	netif_rx(skb);
-}
-
-static const struct net_device_ops hdlcdev_ops = {
-	.ndo_open       = hdlcdev_open,
-	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
-	.ndo_start_xmit = hdlc_start_xmit,
-	.ndo_do_ioctl   = hdlcdev_ioctl,
-	.ndo_tx_timeout = hdlcdev_tx_timeout,
-};
-
-/**
- * called by device driver when adding device instance
- * do generic HDLC initialization
- *
- * info  pointer to device instance information
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_init(struct slgt_info *info)
-{
-	int rc;
-	struct net_device *dev;
-	hdlc_device *hdlc;
-
-	/* allocate and initialize network and HDLC layer objects */
-
-	if (!(dev = alloc_hdlcdev(info))) {
-		printk(KERN_ERR "%s hdlc device alloc failure\n", info->device_name);
-		return -ENOMEM;
-	}
-
-	/* for network layer reporting purposes only */
-	dev->mem_start = info->phys_reg_addr;
-	dev->mem_end   = info->phys_reg_addr + SLGT_REG_SIZE - 1;
-	dev->irq       = info->irq_level;
-
-	/* network layer callbacks and settings */
-	dev->netdev_ops	    = &hdlcdev_ops;
-	dev->watchdog_timeo = 10 * HZ;
-	dev->tx_queue_len   = 50;
-
-	/* generic HDLC layer callbacks and settings */
-	hdlc         = dev_to_hdlc(dev);
-	hdlc->attach = hdlcdev_attach;
-	hdlc->xmit   = hdlcdev_xmit;
-
-	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
-		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
-		free_netdev(dev);
-		return rc;
-	}
-
-	info->netdev = dev;
-	return 0;
-}
-
-/**
- * called by device driver when removing device instance
- * do generic HDLC cleanup
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_exit(struct slgt_info *info)
-{
-	unregister_hdlc_device(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-}
-
-#endif /* ifdef CONFIG_HDLC */
-
-/*
- * get async data from rx DMA buffers
- */
-static void rx_async(struct slgt_info *info)
-{
- 	struct tty_struct *tty = info->port.tty;
- 	struct mgsl_icount *icount = &info->icount;
-	unsigned int start, end;
-	unsigned char *p;
-	unsigned char status;
-	struct slgt_desc *bufs = info->rbufs;
-	int i, count;
-	int chars = 0;
-	int stat;
-	unsigned char ch;
-
-	start = end = info->rbuf_current;
-
-	while(desc_complete(bufs[end])) {
-		count = desc_count(bufs[end]) - info->rbuf_index;
-		p     = bufs[end].buf + info->rbuf_index;
-
-		DBGISR(("%s rx_async count=%d\n", info->device_name, count));
-		DBGDATA(info, p, count, "rx");
-
-		for(i=0 ; i < count; i+=2, p+=2) {
-			ch = *p;
-			icount->rx++;
-
-			stat = 0;
-
-			if ((status = *(p+1) & (BIT1 + BIT0))) {
-				if (status & BIT1)
-					icount->parity++;
-				else if (status & BIT0)
-					icount->frame++;
-				/* discard char if tty control flags say so */
-				if (status & info->ignore_status_mask)
-					continue;
-				if (status & BIT1)
-					stat = TTY_PARITY;
-				else if (status & BIT0)
-					stat = TTY_FRAME;
-			}
-			if (tty) {
-				tty_insert_flip_char(tty, ch, stat);
-				chars++;
-			}
-		}
-
-		if (i < count) {
-			/* receive buffer not completed */
-			info->rbuf_index += i;
-			mod_timer(&info->rx_timer, jiffies + 1);
-			break;
-		}
-
-		info->rbuf_index = 0;
-		free_rbufs(info, end, end);
-
-		if (++end == info->rbuf_count)
-			end = 0;
-
-		/* if entire list searched then no frame available */
-		if (end == start)
-			break;
-	}
-
-	if (tty && chars)
-		tty_flip_buffer_push(tty);
-}
-
-/*
- * return next bottom half action to perform
- */
-static int bh_action(struct slgt_info *info)
-{
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if (info->pending_bh & BH_RECEIVE) {
-		info->pending_bh &= ~BH_RECEIVE;
-		rc = BH_RECEIVE;
-	} else if (info->pending_bh & BH_TRANSMIT) {
-		info->pending_bh &= ~BH_TRANSMIT;
-		rc = BH_TRANSMIT;
-	} else if (info->pending_bh & BH_STATUS) {
-		info->pending_bh &= ~BH_STATUS;
-		rc = BH_STATUS;
-	} else {
-		/* Mark BH routine as complete */
-		info->bh_running = false;
-		info->bh_requested = false;
-		rc = 0;
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return rc;
-}
-
-/*
- * perform bottom half processing
- */
-static void bh_handler(struct work_struct *work)
-{
-	struct slgt_info *info = container_of(work, struct slgt_info, task);
-	int action;
-
-	if (!info)
-		return;
-	info->bh_running = true;
-
-	while((action = bh_action(info))) {
-		switch (action) {
-		case BH_RECEIVE:
-			DBGBH(("%s bh receive\n", info->device_name));
-			switch(info->params.mode) {
-			case MGSL_MODE_ASYNC:
-				rx_async(info);
-				break;
-			case MGSL_MODE_HDLC:
-				while(rx_get_frame(info));
-				break;
-			case MGSL_MODE_RAW:
-			case MGSL_MODE_MONOSYNC:
-			case MGSL_MODE_BISYNC:
-			case MGSL_MODE_XSYNC:
-				while(rx_get_buf(info));
-				break;
-			}
-			/* restart receiver if rx DMA buffers exhausted */
-			if (info->rx_restart)
-				rx_start(info);
-			break;
-		case BH_TRANSMIT:
-			bh_transmit(info);
-			break;
-		case BH_STATUS:
-			DBGBH(("%s bh status\n", info->device_name));
-			info->ri_chkcount = 0;
-			info->dsr_chkcount = 0;
-			info->dcd_chkcount = 0;
-			info->cts_chkcount = 0;
-			break;
-		default:
-			DBGBH(("%s unknown action\n", info->device_name));
-			break;
-		}
-	}
-	DBGBH(("%s bh_handler exit\n", info->device_name));
-}
-
-static void bh_transmit(struct slgt_info *info)
-{
-	struct tty_struct *tty = info->port.tty;
-
-	DBGBH(("%s bh_transmit\n", info->device_name));
-	if (tty)
-		tty_wakeup(tty);
-}
-
-static void dsr_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT3) {
-		info->signals |= SerialSignal_DSR;
-		info->input_signal_events.dsr_up++;
-	} else {
-		info->signals &= ~SerialSignal_DSR;
-		info->input_signal_events.dsr_down++;
-	}
-	DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_DSR);
-		return;
-	}
-	info->icount.dsr++;
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-}
-
-static void cts_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT2) {
-		info->signals |= SerialSignal_CTS;
-		info->input_signal_events.cts_up++;
-	} else {
-		info->signals &= ~SerialSignal_CTS;
-		info->input_signal_events.cts_down++;
-	}
-	DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_CTS);
-		return;
-	}
-	info->icount.cts++;
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-
-	if (info->port.flags & ASYNC_CTS_FLOW) {
-		if (info->port.tty) {
-			if (info->port.tty->hw_stopped) {
-				if (info->signals & SerialSignal_CTS) {
-		 			info->port.tty->hw_stopped = 0;
-					info->pending_bh |= BH_TRANSMIT;
-					return;
-				}
-			} else {
-				if (!(info->signals & SerialSignal_CTS))
-		 			info->port.tty->hw_stopped = 1;
-			}
-		}
-	}
-}
-
-static void dcd_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT1) {
-		info->signals |= SerialSignal_DCD;
-		info->input_signal_events.dcd_up++;
-	} else {
-		info->signals &= ~SerialSignal_DCD;
-		info->input_signal_events.dcd_down++;
-	}
-	DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_DCD);
-		return;
-	}
-	info->icount.dcd++;
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount) {
-		if (info->signals & SerialSignal_DCD)
-			netif_carrier_on(info->netdev);
-		else
-			netif_carrier_off(info->netdev);
-	}
-#endif
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	info->pending_bh |= BH_STATUS;
-
-	if (info->port.flags & ASYNC_CHECK_CD) {
-		if (info->signals & SerialSignal_DCD)
-			wake_up_interruptible(&info->port.open_wait);
-		else {
-			if (info->port.tty)
-				tty_hangup(info->port.tty);
-		}
-	}
-}
-
-static void ri_change(struct slgt_info *info, unsigned short status)
-{
-	if (status & BIT0) {
-		info->signals |= SerialSignal_RI;
-		info->input_signal_events.ri_up++;
-	} else {
-		info->signals &= ~SerialSignal_RI;
-		info->input_signal_events.ri_down++;
-	}
-	DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
-	if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
-		slgt_irq_off(info, IRQ_RI);
-		return;
-	}
-	info->icount.rng++;
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-	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);
-
-	DBGISR(("%s isr_serial status=%04X\n", info->device_name, status));
-
-	wr_reg16(info, SSR, status); /* clear pending */
-
-	info->irq_occurred = true;
-
-	if (info->params.mode == MGSL_MODE_ASYNC) {
-		if (status & IRQ_TXIDLE) {
-			if (info->tx_active)
-				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 */
-			if (info->port.tty) {
-				if (!(status & info->ignore_status_mask)) {
-					if (info->read_status_mask & MASK_BREAK) {
-						tty_insert_flip_char(info->port.tty, 0, TTY_BREAK);
-						if (info->port.flags & ASYNC_SAK)
-							do_SAK(info->port.tty);
-					}
-				}
-			}
-		}
-	} 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++;
-			else
-				info->icount.exithunt++;
-			wake_up_interruptible(&info->event_wait_q);
-		}
-
-		if (status & IRQ_RXOVER)
-			rx_start(info);
-	}
-
-	if (status & IRQ_DSR)
-		dsr_change(info, status);
-	if (status & IRQ_CTS)
-		cts_change(info, status);
-	if (status & IRQ_DCD)
-		dcd_change(info, status);
-	if (status & IRQ_RI)
-		ri_change(info, status);
-}
-
-static void isr_rdma(struct slgt_info *info)
-{
-	unsigned int status = rd_reg32(info, RDCSR);
-
-	DBGISR(("%s isr_rdma status=%08x\n", info->device_name, status));
-
-	/* RDCSR (rx DMA control/status)
-	 *
-	 * 31..07  reserved
-	 * 06      save status byte to DMA buffer
-	 * 05      error
-	 * 04      eol (end of list)
-	 * 03      eob (end of buffer)
-	 * 02      IRQ enable
-	 * 01      reset
-	 * 00      enable
-	 */
-	wr_reg32(info, RDCSR, status);	/* clear pending */
-
-	if (status & (BIT5 + BIT4)) {
-		DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
-		info->rx_restart = true;
-	}
-	info->pending_bh |= BH_RECEIVE;
-}
-
-static void isr_tdma(struct slgt_info *info)
-{
-	unsigned int status = rd_reg32(info, TDCSR);
-
-	DBGISR(("%s isr_tdma status=%08x\n", info->device_name, status));
-
-	/* TDCSR (tx DMA control/status)
-	 *
-	 * 31..06  reserved
-	 * 05      error
-	 * 04      eol (end of list)
-	 * 03      eob (end of buffer)
-	 * 02      IRQ enable
-	 * 01      reset
-	 * 00      enable
-	 */
-	wr_reg32(info, TDCSR, status);	/* clear pending */
-
-	if (status & (BIT5 + BIT4 + BIT3)) {
-		// another transmit buffer has completed
-		// run bottom half to get more send data from user
-		info->pending_bh |= BH_TRANSMIT;
-	}
-}
-
-/*
- * return true if there are unsent tx DMA buffers, otherwise false
- *
- * if there are unsent buffers then info->tbuf_start
- * is set to index of first unsent buffer
- */
-static bool unsent_tbufs(struct slgt_info *info)
-{
-	unsigned int i = info->tbuf_current;
-	bool rc = false;
-
-	/*
-	 * search backwards from last loaded buffer (precedes tbuf_current)
-	 * for first unsent buffer (desc_count > 0)
-	 */
-
-	do {
-		if (i)
-			i--;
-		else
-			i = info->tbuf_count - 1;
-		if (!desc_count(info->tbufs[i]))
-			break;
-		info->tbuf_start = i;
-		rc = true;
-	} while (i != info->tbuf_current);
-
-	return rc;
-}
-
-static void isr_txeom(struct slgt_info *info, unsigned short status)
-{
-	DBGISR(("%s txeom status=%04x\n", info->device_name, status));
-
-	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
-	tdma_reset(info);
-	if (status & IRQ_TXUNDER) {
-		unsigned short val = rd_reg16(info, TCR);
-		wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-		wr_reg16(info, TCR, val); /* clear reset bit */
-	}
-
-	if (info->tx_active) {
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			if (status & IRQ_TXUNDER)
-				info->icount.txunder++;
-			else if (status & IRQ_TXIDLE)
-				info->icount.txok++;
-		}
-
-		if (unsent_tbufs(info)) {
-			tx_start(info);
-			update_tx_timer(info);
-			return;
-		}
-		info->tx_active = false;
-
-		del_timer(&info->tx_timer);
-
-		if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
-			info->signals &= ~SerialSignal_RTS;
-			info->drop_rts_on_tx_done = false;
-			set_signals(info);
-		}
-
-#if SYNCLINK_GENERIC_HDLC
-		if (info->netcount)
-			hdlcdev_tx_done(info);
-		else
-#endif
-		{
-			if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
-				tx_stop(info);
-				return;
-			}
-			info->pending_bh |= BH_TRANSMIT;
-		}
-	}
-}
-
-static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int state)
-{
-	struct cond_wait *w, *prev;
-
-	/* wake processes waiting for specific transitions */
-	for (w = info->gpio_wait_q, prev = NULL ; w != NULL ; w = w->next) {
-		if (w->data & changed) {
-			w->data = state;
-			wake_up_interruptible(&w->q);
-			if (prev != NULL)
-				prev->next = w->next;
-			else
-				info->gpio_wait_q = w->next;
-		} else
-			prev = w;
-	}
-}
-
-/* interrupt service routine
- *
- * 	irq	interrupt number
- * 	dev_id	device ID supplied during interrupt registration
- */
-static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
-{
-	struct slgt_info *info = dev_id;
-	unsigned int gsr;
-	unsigned int i;
-
-	DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
-
-	while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
-		DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
-		info->irq_occurred = true;
-		for(i=0; i < info->port_count ; i++) {
-			if (info->port_array[i] == NULL)
-				continue;
-			spin_lock(&info->port_array[i]->lock);
-			if (gsr & (BIT8 << i))
-				isr_serial(info->port_array[i]);
-			if (gsr & (BIT16 << (i*2)))
-				isr_rdma(info->port_array[i]);
-			if (gsr & (BIT17 << (i*2)))
-				isr_tdma(info->port_array[i]);
-			spin_unlock(&info->port_array[i]->lock);
-		}
-	}
-
-	if (info->gpio_present) {
-		unsigned int state;
-		unsigned int changed;
-		spin_lock(&info->lock);
-		while ((changed = rd_reg32(info, IOSR)) != 0) {
-			DBGISR(("%s iosr=%08x\n", info->device_name, changed));
-			/* read latched state of GPIO signals */
-			state = rd_reg32(info, IOVR);
-			/* clear pending GPIO interrupt bits */
-			wr_reg32(info, IOSR, changed);
-			for (i=0 ; i < info->port_count ; i++) {
-				if (info->port_array[i] != NULL)
-					isr_gpio(info->port_array[i], changed, state);
-			}
-		}
-		spin_unlock(&info->lock);
-	}
-
-	for(i=0; i < info->port_count ; i++) {
-		struct slgt_info *port = info->port_array[i];
-		if (port == NULL)
-			continue;
-		spin_lock(&port->lock);
-		if ((port->port.count || port->netcount) &&
-		    port->pending_bh && !port->bh_running &&
-		    !port->bh_requested) {
-			DBGISR(("%s bh queued\n", port->device_name));
-			schedule_work(&port->task);
-			port->bh_requested = true;
-		}
-		spin_unlock(&port->lock);
-	}
-
-	DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
-	return IRQ_HANDLED;
-}
-
-static int startup(struct slgt_info *info)
-{
-	DBGINFO(("%s startup\n", info->device_name));
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		return 0;
-
-	if (!info->tx_buf) {
-		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
-		if (!info->tx_buf) {
-			DBGERR(("%s can't allocate tx buffer\n", info->device_name));
-			return -ENOMEM;
-		}
-	}
-
-	info->pending_bh = 0;
-
-	memset(&info->icount, 0, sizeof(info->icount));
-
-	/* program hardware for current parameters */
-	change_params(info);
-
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags |= ASYNC_INITIALIZED;
-
-	return 0;
-}
-
-/*
- *  called by close() and hangup() to shutdown hardware
- */
-static void shutdown(struct slgt_info *info)
-{
-	unsigned long flags;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	DBGINFO(("%s shutdown\n", info->device_name));
-
-	/* clear status wait queue because status changes */
-	/* can't happen after shutting down the hardware */
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-
-	del_timer_sync(&info->tx_timer);
-	del_timer_sync(&info->rx_timer);
-
-	kfree(info->tx_buf);
-	info->tx_buf = NULL;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	tx_stop(info);
-	rx_stop(info);
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
- 		info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		set_signals(info);
-	}
-
-	flush_cond_wait(&info->gpio_wait_q);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-}
-
-static void program_hw(struct slgt_info *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	rx_stop(info);
-	tx_stop(info);
-
-	if (info->params.mode != MGSL_MODE_ASYNC ||
-	    info->netcount)
-		sync_mode(info);
-	else
-		async_mode(info);
-
-	set_signals(info);
-
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-
-	slgt_irq_on(info, IRQ_DCD | IRQ_CTS | IRQ_DSR | IRQ_RI);
-	get_signals(info);
-
-	if (info->netcount ||
-	    (info->port.tty && info->port.tty->termios->c_cflag & CREAD))
-		rx_start(info);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/*
- * reconfigure adapter based on new parameters
- */
-static void change_params(struct slgt_info *info)
-{
-	unsigned cflag;
-	int bits_per_char;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-	DBGINFO(("%s change_params\n", info->device_name));
-
-	cflag = info->port.tty->termios->c_cflag;
-
-	/* if B0 rate (hangup) specified then negate DTR and RTS */
-	/* otherwise assert DTR and RTS */
- 	if (cflag & CBAUD)
-		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-
-	/* byte size and parity */
-
-	switch (cflag & CSIZE) {
-	case CS5: info->params.data_bits = 5; break;
-	case CS6: info->params.data_bits = 6; break;
-	case CS7: info->params.data_bits = 7; break;
-	case CS8: info->params.data_bits = 8; break;
-	default:  info->params.data_bits = 7; break;
-	}
-
-	info->params.stop_bits = (cflag & CSTOPB) ? 2 : 1;
-
-	if (cflag & PARENB)
-		info->params.parity = (cflag & PARODD) ? ASYNC_PARITY_ODD : ASYNC_PARITY_EVEN;
-	else
-		info->params.parity = ASYNC_PARITY_NONE;
-
-	/* calculate number of jiffies to transmit a full
-	 * FIFO (32 bytes) at specified data rate
-	 */
-	bits_per_char = info->params.data_bits +
-			info->params.stop_bits + 1;
-
-	info->params.data_rate = tty_get_baud_rate(info->port.tty);
-
-	if (info->params.data_rate) {
-		info->timeout = (32*HZ*bits_per_char) /
-				info->params.data_rate;
-	}
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/* process tty input control flags */
-
-	info->read_status_mask = IRQ_RXOVER;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask |= MASK_PARITY | MASK_FRAMING;
- 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- 		info->read_status_mask |= MASK_BREAK;
-	if (I_IGNPAR(info->port.tty))
-		info->ignore_status_mask |= MASK_PARITY | MASK_FRAMING;
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask |= MASK_BREAK;
-		/* If ignoring parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty))
-			info->ignore_status_mask |= MASK_OVERRUN;
-	}
-
-	program_hw(info);
-}
-
-static int get_stats(struct slgt_info *info, struct mgsl_icount __user *user_icount)
-{
-	DBGINFO(("%s get_stats\n",  info->device_name));
-	if (!user_icount) {
-		memset(&info->icount, 0, sizeof(info->icount));
-	} else {
-		if (copy_to_user(user_icount, &info->icount, sizeof(struct mgsl_icount)))
-			return -EFAULT;
-	}
-	return 0;
-}
-
-static int get_params(struct slgt_info *info, MGSL_PARAMS __user *user_params)
-{
-	DBGINFO(("%s get_params\n", info->device_name));
-	if (copy_to_user(user_params, &info->params, sizeof(MGSL_PARAMS)))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_params(struct slgt_info *info, MGSL_PARAMS __user *new_params)
-{
- 	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-
-	DBGINFO(("%s set_params\n", info->device_name));
-	if (copy_from_user(&tmp_params, new_params, sizeof(MGSL_PARAMS)))
-		return -EFAULT;
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (tmp_params.mode == MGSL_MODE_BASE_CLOCK)
-		info->base_clock = tmp_params.clock_speed;
-	else
-		memcpy(&info->params, &tmp_params, sizeof(MGSL_PARAMS));
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	program_hw(info);
-
-	return 0;
-}
-
-static int get_txidle(struct slgt_info *info, int __user *idle_mode)
-{
-	DBGINFO(("%s get_txidle=%d\n", info->device_name, info->idle_mode));
-	if (put_user(info->idle_mode, idle_mode))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_txidle(struct slgt_info *info, int idle_mode)
-{
- 	unsigned long flags;
-	DBGINFO(("%s set_txidle(%d)\n", info->device_name, idle_mode));
-	spin_lock_irqsave(&info->lock,flags);
-	info->idle_mode = idle_mode;
-	if (info->params.mode != MGSL_MODE_ASYNC)
-		tx_set_idle(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int tx_enable(struct slgt_info *info, int enable)
-{
- 	unsigned long flags;
-	DBGINFO(("%s tx_enable(%d)\n", info->device_name, enable));
-	spin_lock_irqsave(&info->lock,flags);
-	if (enable) {
-		if (!info->tx_enabled)
-			tx_start(info);
-	} else {
-		if (info->tx_enabled)
-			tx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/*
- * abort transmit HDLC frame
- */
-static int tx_abort(struct slgt_info *info)
-{
- 	unsigned long flags;
-	DBGINFO(("%s tx_abort\n", info->device_name));
-	spin_lock_irqsave(&info->lock,flags);
-	tdma_reset(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int rx_enable(struct slgt_info *info, int enable)
-{
- 	unsigned long flags;
-	unsigned int rbuf_fill_level;
-	DBGINFO(("%s rx_enable(%08x)\n", info->device_name, enable));
-	spin_lock_irqsave(&info->lock,flags);
-	/*
-	 * enable[31..16] = receive DMA buffer fill level
-	 * 0 = noop (leave fill level unchanged)
-	 * fill level must be multiple of 4 and <= buffer size
-	 */
-	rbuf_fill_level = ((unsigned int)enable) >> 16;
-	if (rbuf_fill_level) {
-		if ((rbuf_fill_level > DMABUFSIZE) || (rbuf_fill_level % 4)) {
-			spin_unlock_irqrestore(&info->lock, flags);
-			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 */
-	}
-
-	/*
-	 * enable[1..0] = receiver enable command
-	 * 0 = disable
-	 * 1 = enable
-	 * 2 = enable or force hunt mode if already enabled
-	 */
-	enable &= 3;
-	if (enable) {
-		if (!info->rx_enabled)
-			rx_start(info);
-		else if (enable == 2) {
-			/* force hunt mode (write 1 to RCR[3]) */
-			wr_reg16(info, RCR, rd_reg16(info, RCR) | BIT3);
-		}
-	} else {
-		if (info->rx_enabled)
-			rx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/*
- *  wait for specified event to occur
- */
-static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr)
-{
- 	unsigned long flags;
-	int s;
-	int rc=0;
-	struct mgsl_icount cprev, cnow;
-	int events;
-	int mask;
-	struct	_input_signal_events oldsigs, newsigs;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (get_user(mask, mask_ptr))
-		return -EFAULT;
-
-	DBGINFO(("%s wait_mgsl_event(%d)\n", info->device_name, mask));
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	/* return immediately if state matches requested events */
-	get_signals(info);
-	s = info->signals;
-
-	events = mask &
-		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
- 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
-		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
-		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
-	if (events) {
-		spin_unlock_irqrestore(&info->lock,flags);
-		goto exit;
-	}
-
-	/* save current irq counts */
-	cprev = info->icount;
-	oldsigs = info->input_signal_events;
-
-	/* enable hunt and idle irqs if needed */
-	if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
-		unsigned short val = rd_reg16(info, SCR);
-		if (!(val & IRQ_RXIDLE))
-			wr_reg16(info, SCR, (unsigned short)(val | IRQ_RXIDLE));
-	}
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&info->event_wait_q, &wait);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get current irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		newsigs = info->input_signal_events;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
-		    newsigs.dsr_down == oldsigs.dsr_down &&
-		    newsigs.dcd_up   == oldsigs.dcd_up   &&
-		    newsigs.dcd_down == oldsigs.dcd_down &&
-		    newsigs.cts_up   == oldsigs.cts_up   &&
-		    newsigs.cts_down == oldsigs.cts_down &&
-		    newsigs.ri_up    == oldsigs.ri_up    &&
-		    newsigs.ri_down  == oldsigs.ri_down  &&
-		    cnow.exithunt    == cprev.exithunt   &&
-		    cnow.rxidle      == cprev.rxidle) {
-			rc = -EIO;
-			break;
-		}
-
-		events = mask &
-			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
-			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
-			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
-			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
-			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
-			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
-			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
-			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
-			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
-			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
-		if (events)
-			break;
-
-		cprev = cnow;
-		oldsigs = newsigs;
-	}
-
-	remove_wait_queue(&info->event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-
-
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!waitqueue_active(&info->event_wait_q)) {
-			/* disable enable exit hunt mode/idle rcvd IRQs */
-			wr_reg16(info, SCR,
-				(unsigned short)(rd_reg16(info, SCR) & ~IRQ_RXIDLE));
-		}
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-exit:
-	if (rc == 0)
-		rc = put_user(events, mask_ptr);
-	return rc;
-}
-
-static int get_interface(struct slgt_info *info, int __user *if_mode)
-{
-	DBGINFO(("%s get_interface=%x\n", info->device_name, info->if_mode));
-	if (put_user(info->if_mode, if_mode))
-		return -EFAULT;
-	return 0;
-}
-
-static int set_interface(struct slgt_info *info, int if_mode)
-{
- 	unsigned long flags;
-	unsigned short val;
-
-	DBGINFO(("%s set_interface=%x)\n", info->device_name, if_mode));
-	spin_lock_irqsave(&info->lock,flags);
-	info->if_mode = if_mode;
-
-	msc_set_vcr(info);
-
-	/* TCR (tx control) 07  1=RTS driver control */
-	val = rd_reg16(info, TCR);
-	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
-		val |= BIT7;
-	else
-		val &= ~BIT7;
-	wr_reg16(info, TCR, val);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int get_xsync(struct slgt_info *info, int __user *xsync)
-{
-	DBGINFO(("%s get_xsync=%x\n", info->device_name, info->xsync));
-	if (put_user(info->xsync, xsync))
-		return -EFAULT;
-	return 0;
-}
-
-/*
- * set extended sync pattern (1 to 4 bytes) for extended sync mode
- *
- * sync pattern is contained in least significant bytes of value
- * most significant byte of sync pattern is oldest (1st sent/detected)
- */
-static int set_xsync(struct slgt_info *info, int xsync)
-{
-	unsigned long flags;
-
-	DBGINFO(("%s set_xsync=%x)\n", info->device_name, xsync));
-	spin_lock_irqsave(&info->lock, flags);
-	info->xsync = xsync;
-	wr_reg32(info, XSR, xsync);
-	spin_unlock_irqrestore(&info->lock, flags);
-	return 0;
-}
-
-static int get_xctrl(struct slgt_info *info, int __user *xctrl)
-{
-	DBGINFO(("%s get_xctrl=%x\n", info->device_name, info->xctrl));
-	if (put_user(info->xctrl, xctrl))
-		return -EFAULT;
-	return 0;
-}
-
-/*
- * set extended control options
- *
- * xctrl[31:19] reserved, must be zero
- * xctrl[18:17] extended sync pattern length in bytes
- *              00 = 1 byte  in xsr[7:0]
- *              01 = 2 bytes in xsr[15:0]
- *              10 = 3 bytes in xsr[23:0]
- *              11 = 4 bytes in xsr[31:0]
- * xctrl[16]    1 = enable terminal count, 0=disabled
- * xctrl[15:0]  receive terminal count for fixed length packets
- *              value is count minus one (0 = 1 byte packet)
- *              when terminal count is reached, receiver
- *              automatically returns to hunt mode and receive
- *              FIFO contents are flushed to DMA buffers with
- *              end of frame (EOF) status
- */
-static int set_xctrl(struct slgt_info *info, int xctrl)
-{
-	unsigned long flags;
-
-	DBGINFO(("%s set_xctrl=%x)\n", info->device_name, xctrl));
-	spin_lock_irqsave(&info->lock, flags);
-	info->xctrl = xctrl;
-	wr_reg32(info, XCR, xctrl);
-	spin_unlock_irqrestore(&info->lock, flags);
-	return 0;
-}
-
-/*
- * set general purpose IO pin state and direction
- *
- * user_gpio fields:
- * state   each bit indicates a pin state
- * smask   set bit indicates pin state to set
- * dir     each bit indicates a pin direction (0=input, 1=output)
- * dmask   set bit indicates pin direction to set
- */
-static int set_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
-{
- 	unsigned long flags;
-	struct gpio_desc gpio;
-	__u32 data;
-
-	if (!info->gpio_present)
-		return -EINVAL;
-	if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
-		return -EFAULT;
-	DBGINFO(("%s set_gpio state=%08x smask=%08x dir=%08x dmask=%08x\n",
-		 info->device_name, gpio.state, gpio.smask,
-		 gpio.dir, gpio.dmask));
-
-	spin_lock_irqsave(&info->port_array[0]->lock, flags);
-	if (gpio.dmask) {
-		data = rd_reg32(info, IODR);
-		data |= gpio.dmask & gpio.dir;
-		data &= ~(gpio.dmask & ~gpio.dir);
-		wr_reg32(info, IODR, data);
-	}
-	if (gpio.smask) {
-		data = rd_reg32(info, IOVR);
-		data |= gpio.smask & gpio.state;
-		data &= ~(gpio.smask & ~gpio.state);
-		wr_reg32(info, IOVR, data);
-	}
-	spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
-
-	return 0;
-}
-
-/*
- * get general purpose IO pin state and direction
- */
-static int get_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
-{
-	struct gpio_desc gpio;
-	if (!info->gpio_present)
-		return -EINVAL;
-	gpio.state = rd_reg32(info, IOVR);
-	gpio.smask = 0xffffffff;
-	gpio.dir   = rd_reg32(info, IODR);
-	gpio.dmask = 0xffffffff;
-	if (copy_to_user(user_gpio, &gpio, sizeof(gpio)))
-		return -EFAULT;
-	DBGINFO(("%s get_gpio state=%08x dir=%08x\n",
-		 info->device_name, gpio.state, gpio.dir));
-	return 0;
-}
-
-/*
- * conditional wait facility
- */
-static void init_cond_wait(struct cond_wait *w, unsigned int data)
-{
-	init_waitqueue_head(&w->q);
-	init_waitqueue_entry(&w->wait, current);
-	w->data = data;
-}
-
-static void add_cond_wait(struct cond_wait **head, struct cond_wait *w)
-{
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&w->q, &w->wait);
-	w->next = *head;
-	*head = w;
-}
-
-static void remove_cond_wait(struct cond_wait **head, struct cond_wait *cw)
-{
-	struct cond_wait *w, *prev;
-	remove_wait_queue(&cw->q, &cw->wait);
-	set_current_state(TASK_RUNNING);
-	for (w = *head, prev = NULL ; w != NULL ; prev = w, w = w->next) {
-		if (w == cw) {
-			if (prev != NULL)
-				prev->next = w->next;
-			else
-				*head = w->next;
-			break;
-		}
-	}
-}
-
-static void flush_cond_wait(struct cond_wait **head)
-{
-	while (*head != NULL) {
-		wake_up_interruptible(&(*head)->q);
-		*head = (*head)->next;
-	}
-}
-
-/*
- * wait for general purpose I/O pin(s) to enter specified state
- *
- * user_gpio fields:
- * state - bit indicates target pin state
- * smask - set bit indicates watched pin
- *
- * The wait ends when at least one watched pin enters the specified
- * state. When 0 (no error) is returned, user_gpio->state is set to the
- * state of all GPIO pins when the wait ends.
- *
- * Note: Each pin may be a dedicated input, dedicated output, or
- * configurable input/output. The number and configuration of pins
- * varies with the specific adapter model. Only input pins (dedicated
- * or configured) can be monitored with this function.
- */
-static int wait_gpio(struct slgt_info *info, struct gpio_desc __user *user_gpio)
-{
- 	unsigned long flags;
-	int rc = 0;
-	struct gpio_desc gpio;
-	struct cond_wait wait;
-	u32 state;
-
-	if (!info->gpio_present)
-		return -EINVAL;
-	if (copy_from_user(&gpio, user_gpio, sizeof(gpio)))
-		return -EFAULT;
-	DBGINFO(("%s wait_gpio() state=%08x smask=%08x\n",
-		 info->device_name, gpio.state, gpio.smask));
-	/* ignore output pins identified by set IODR bit */
-	if ((gpio.smask &= ~rd_reg32(info, IODR)) == 0)
-		return -EINVAL;
-	init_cond_wait(&wait, gpio.smask);
-
-	spin_lock_irqsave(&info->port_array[0]->lock, flags);
-	/* enable interrupts for watched pins */
-	wr_reg32(info, IOER, rd_reg32(info, IOER) | gpio.smask);
-	/* get current pin states */
-	state = rd_reg32(info, IOVR);
-
-	if (gpio.smask & ~(state ^ gpio.state)) {
-		/* already in target state */
-		gpio.state = state;
-	} else {
-		/* wait for target state */
-		add_cond_wait(&info->gpio_wait_q, &wait);
-		spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
-		schedule();
-		if (signal_pending(current))
-			rc = -ERESTARTSYS;
-		else
-			gpio.state = wait.data;
-		spin_lock_irqsave(&info->port_array[0]->lock, flags);
-		remove_cond_wait(&info->gpio_wait_q, &wait);
-	}
-
-	/* disable all GPIO interrupts if no waiting processes */
-	if (info->gpio_wait_q == NULL)
-		wr_reg32(info, IOER, 0);
-	spin_unlock_irqrestore(&info->port_array[0]->lock, flags);
-
-	if ((rc == 0) && copy_to_user(user_gpio, &gpio, sizeof(gpio)))
-		rc = -EFAULT;
-	return rc;
-}
-
-static int modem_input_wait(struct slgt_info *info,int arg)
-{
- 	unsigned long flags;
-	int rc;
-	struct mgsl_icount cprev, cnow;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* save current irq counts */
-	spin_lock_irqsave(&info->lock,flags);
-	cprev = info->icount;
-	add_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get new irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-			rc = -EIO;
-			break;
-		}
-
-		/* check for change in caller specified modem input */
-		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
-		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
-		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
-		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
-			rc = 0;
-			break;
-		}
-
-		cprev = cnow;
-	}
-	remove_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-	return rc;
-}
-
-/*
- *  return state of serial control and status signals
- */
-static int tiocmget(struct tty_struct *tty, struct file *file)
-{
-	struct slgt_info *info = tty->driver_data;
-	unsigned int result;
- 	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	result = ((info->signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
-		((info->signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
-		((info->signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
-		((info->signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
-		((info->signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
-		((info->signals & SerialSignal_CTS) ? TIOCM_CTS:0);
-
-	DBGINFO(("%s tiocmget value=%08X\n", info->device_name, result));
-	return result;
-}
-
-/*
- * set modem control signals (DTR/RTS)
- *
- * 	cmd	signal command: TIOCMBIS = set bit TIOCMBIC = clear bit
- *		TIOCMSET = set/clear signal values
- * 	value	bit mask for command
- */
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	struct slgt_info *info = tty->driver_data;
- 	unsigned long flags;
-
-	DBGINFO(("%s tiocmset(%x,%x)\n", info->device_name, set, clear));
-
-	if (set & TIOCM_RTS)
-		info->signals |= SerialSignal_RTS;
-	if (set & TIOCM_DTR)
-		info->signals |= SerialSignal_DTR;
-	if (clear & TIOCM_RTS)
-		info->signals &= ~SerialSignal_RTS;
-	if (clear & TIOCM_DTR)
-		info->signals &= ~SerialSignal_DTR;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	unsigned long flags;
-	struct slgt_info *info = container_of(port, struct slgt_info, port);
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return (info->signals & SerialSignal_DCD) ? 1 : 0;
-}
-
-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);
-	if (on)
-		info->signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-
-/*
- *  block current process until the device is ready to open
- */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-			   struct slgt_info *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	bool		do_clocal = false;
-	bool		extra_count = false;
-	unsigned long	flags;
-	int		cd;
-	struct tty_port *port = &info->port;
-
-	DBGINFO(("%s block_til_ready\n", tty->driver->name));
-
-	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-		/* nonblock mode is set or port is not enabled */
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = true;
-
-	/* Wait for carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-	port->blocked_open++;
-
-	while (1) {
-		if ((tty->termios->c_cflag & CBAUD))
-			tty_port_raise_dtr_rts(port);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
-			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-					-EAGAIN : -ERESTARTSYS;
-			break;
-		}
-
-		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd ))
- 			break;
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-		DBGINFO(("%s block_til_ready wait\n", tty->driver->name));
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-
-	if (extra_count)
-		port->count++;
-	port->blocked_open--;
-
-	if (!retval)
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-
-	DBGINFO(("%s block_til_ready ready, rc=%d\n", tty->driver->name, retval));
-	return retval;
-}
-
-static int alloc_tmp_rbuf(struct slgt_info *info)
-{
-	info->tmp_rbuf = kmalloc(info->max_frame_size + 5, GFP_KERNEL);
-	if (info->tmp_rbuf == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-static void free_tmp_rbuf(struct slgt_info *info)
-{
-	kfree(info->tmp_rbuf);
-	info->tmp_rbuf = NULL;
-}
-
-/*
- * allocate DMA descriptor lists.
- */
-static int alloc_desc(struct slgt_info *info)
-{
-	unsigned int i;
-	unsigned int pbufs;
-
-	/* allocate memory to hold descriptor lists */
-	info->bufs = pci_alloc_consistent(info->pdev, DESC_LIST_SIZE, &info->bufs_dma_addr);
-	if (info->bufs == NULL)
-		return -ENOMEM;
-
-	memset(info->bufs, 0, DESC_LIST_SIZE);
-
-	info->rbufs = (struct slgt_desc*)info->bufs;
-	info->tbufs = ((struct slgt_desc*)info->bufs) + info->rbuf_count;
-
-	pbufs = (unsigned int)info->bufs_dma_addr;
-
-	/*
-	 * Build circular lists of descriptors
-	 */
-
-	for (i=0; i < info->rbuf_count; i++) {
-		/* physical address of this descriptor */
-		info->rbufs[i].pdesc = pbufs + (i * sizeof(struct slgt_desc));
-
-		/* physical address of next descriptor */
-		if (i == info->rbuf_count - 1)
-			info->rbufs[i].next = cpu_to_le32(pbufs);
-		else
-			info->rbufs[i].next = cpu_to_le32(pbufs + ((i+1) * sizeof(struct slgt_desc)));
-		set_desc_count(info->rbufs[i], DMABUFSIZE);
-	}
-
-	for (i=0; i < info->tbuf_count; i++) {
-		/* physical address of this descriptor */
-		info->tbufs[i].pdesc = pbufs + ((info->rbuf_count + i) * sizeof(struct slgt_desc));
-
-		/* physical address of next descriptor */
-		if (i == info->tbuf_count - 1)
-			info->tbufs[i].next = cpu_to_le32(pbufs + info->rbuf_count * sizeof(struct slgt_desc));
-		else
-			info->tbufs[i].next = cpu_to_le32(pbufs + ((info->rbuf_count + i + 1) * sizeof(struct slgt_desc)));
-	}
-
-	return 0;
-}
-
-static void free_desc(struct slgt_info *info)
-{
-	if (info->bufs != NULL) {
-		pci_free_consistent(info->pdev, DESC_LIST_SIZE, info->bufs, info->bufs_dma_addr);
-		info->bufs  = NULL;
-		info->rbufs = NULL;
-		info->tbufs = NULL;
-	}
-}
-
-static int alloc_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
-{
-	int i;
-	for (i=0; i < count; i++) {
-		if ((bufs[i].buf = pci_alloc_consistent(info->pdev, DMABUFSIZE, &bufs[i].buf_dma_addr)) == NULL)
-			return -ENOMEM;
-		bufs[i].pbuf  = cpu_to_le32((unsigned int)bufs[i].buf_dma_addr);
-	}
-	return 0;
-}
-
-static void free_bufs(struct slgt_info *info, struct slgt_desc *bufs, int count)
-{
-	int i;
-	for (i=0; i < count; i++) {
-		if (bufs[i].buf == NULL)
-			continue;
-		pci_free_consistent(info->pdev, DMABUFSIZE, bufs[i].buf, bufs[i].buf_dma_addr);
-		bufs[i].buf = NULL;
-	}
-}
-
-static int alloc_dma_bufs(struct slgt_info *info)
-{
-	info->rbuf_count = 32;
-	info->tbuf_count = 32;
-
-	if (alloc_desc(info) < 0 ||
-	    alloc_bufs(info, info->rbufs, info->rbuf_count) < 0 ||
-	    alloc_bufs(info, info->tbufs, info->tbuf_count) < 0 ||
-	    alloc_tmp_rbuf(info) < 0) {
-		DBGERR(("%s DMA buffer alloc fail\n", info->device_name));
-		return -ENOMEM;
-	}
-	reset_rbufs(info);
-	return 0;
-}
-
-static void free_dma_bufs(struct slgt_info *info)
-{
-	if (info->bufs) {
-		free_bufs(info, info->rbufs, info->rbuf_count);
-		free_bufs(info, info->tbufs, info->tbuf_count);
-		free_desc(info);
-	}
-	free_tmp_rbuf(info);
-}
-
-static int claim_resources(struct slgt_info *info)
-{
-	if (request_mem_region(info->phys_reg_addr, SLGT_REG_SIZE, "synclink_gt") == NULL) {
-		DBGERR(("%s reg addr conflict, addr=%08X\n",
-			info->device_name, info->phys_reg_addr));
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->reg_addr_requested = true;
-
-	info->reg_addr = ioremap_nocache(info->phys_reg_addr, SLGT_REG_SIZE);
-	if (!info->reg_addr) {
-		DBGERR(("%s cant map device registers, addr=%08X\n",
-			info->device_name, info->phys_reg_addr));
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	return 0;
-
-errout:
-	release_resources(info);
-	return -ENODEV;
-}
-
-static void release_resources(struct slgt_info *info)
-{
-	if (info->irq_requested) {
-		free_irq(info->irq_level, info);
-		info->irq_requested = false;
-	}
-
-	if (info->reg_addr_requested) {
-		release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
-		info->reg_addr_requested = false;
-	}
-
-	if (info->reg_addr) {
-		iounmap(info->reg_addr);
-		info->reg_addr = NULL;
-	}
-}
-
-/* Add the specified device instance data structure to the
- * global linked list of devices and increment the device count.
- */
-static void add_device(struct slgt_info *info)
-{
-	char *devstr;
-
-	info->next_device = NULL;
-	info->line = slgt_device_count;
-	sprintf(info->device_name, "%s%d", tty_dev_prefix, info->line);
-
-	if (info->line < MAX_DEVICES) {
-		if (maxframe[info->line])
-			info->max_frame_size = maxframe[info->line];
-	}
-
-	slgt_device_count++;
-
-	if (!slgt_device_list)
-		slgt_device_list = info;
-	else {
-		struct slgt_info *current_dev = slgt_device_list;
-		while(current_dev->next_device)
-			current_dev = current_dev->next_device;
-		current_dev->next_device = info;
-	}
-
-	if (info->max_frame_size < 4096)
-		info->max_frame_size = 4096;
-	else if (info->max_frame_size > 65535)
-		info->max_frame_size = 65535;
-
-	switch(info->pdev->device) {
-	case SYNCLINK_GT_DEVICE_ID:
-		devstr = "GT";
-		break;
-	case SYNCLINK_GT2_DEVICE_ID:
-		devstr = "GT2";
-		break;
-	case SYNCLINK_GT4_DEVICE_ID:
-		devstr = "GT4";
-		break;
-	case SYNCLINK_AC_DEVICE_ID:
-		devstr = "AC";
-		info->params.mode = MGSL_MODE_ASYNC;
-		break;
-	default:
-		devstr = "(unknown model)";
-	}
-	printk("SyncLink %s %s IO=%08x IRQ=%d MaxFrameSize=%u\n",
-		devstr, info->device_name, info->phys_reg_addr,
-		info->irq_level, info->max_frame_size);
-
-#if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
-#endif
-}
-
-static const struct tty_port_operations slgt_port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-/*
- *  allocate device instance structure, return NULL on failure
- */
-static struct slgt_info *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
-{
-	struct slgt_info *info;
-
-	info = kzalloc(sizeof(struct slgt_info), GFP_KERNEL);
-
-	if (!info) {
-		DBGERR(("%s device alloc failed adapter=%d port=%d\n",
-			driver_name, adapter_num, port_num));
-	} else {
-		tty_port_init(&info->port);
-		info->port.ops = &slgt_port_ops;
-		info->magic = MGSL_MAGIC;
-		INIT_WORK(&info->task, bh_handler);
-		info->max_frame_size = 4096;
-		info->base_clock = 14745600;
-		info->rbuf_fill_level = DMABUFSIZE;
-		info->port.close_delay = 5*HZ/10;
-		info->port.closing_wait = 30*HZ;
-		init_waitqueue_head(&info->status_event_wait_q);
-		init_waitqueue_head(&info->event_wait_q);
-		spin_lock_init(&info->netlock);
-		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;
-		info->adapter_num = adapter_num;
-		info->port_num = port_num;
-
-		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
-		setup_timer(&info->rx_timer, rx_timeout, (unsigned long)info);
-
-		/* Copy configuration info to device instance data */
-		info->pdev = pdev;
-		info->irq_level = pdev->irq;
-		info->phys_reg_addr = pci_resource_start(pdev,0);
-
-		info->bus_type = MGSL_BUS_TYPE_PCI;
-		info->irq_flags = IRQF_SHARED;
-
-		info->init_error = -1; /* assume error, set to 0 on successful init */
-	}
-
-	return info;
-}
-
-static void device_init(int adapter_num, struct pci_dev *pdev)
-{
-	struct slgt_info *port_array[SLGT_MAX_PORTS];
-	int i;
-	int port_count = 1;
-
-	if (pdev->device == SYNCLINK_GT2_DEVICE_ID)
-		port_count = 2;
-	else if (pdev->device == SYNCLINK_GT4_DEVICE_ID)
-		port_count = 4;
-
-	/* allocate device instances for all ports */
-	for (i=0; i < port_count; ++i) {
-		port_array[i] = alloc_dev(adapter_num, i, pdev);
-		if (port_array[i] == NULL) {
-			for (--i; i >= 0; --i)
-				kfree(port_array[i]);
-			return;
-		}
-	}
-
-	/* give copy of port_array to all ports and add to device list  */
-	for (i=0; i < port_count; ++i) {
-		memcpy(port_array[i]->port_array, port_array, sizeof(port_array));
-		add_device(port_array[i]);
-		port_array[i]->port_count = port_count;
-		spin_lock_init(&port_array[i]->lock);
-	}
-
-	/* Allocate and claim adapter resources */
-	if (!claim_resources(port_array[0])) {
-
-		alloc_dma_bufs(port_array[0]);
-
-		/* copy resource information from first port to others */
-		for (i = 1; i < port_count; ++i) {
-			port_array[i]->irq_level = port_array[0]->irq_level;
-			port_array[i]->reg_addr  = port_array[0]->reg_addr;
-			alloc_dma_bufs(port_array[i]);
-		}
-
-		if (request_irq(port_array[0]->irq_level,
-					slgt_interrupt,
-					port_array[0]->irq_flags,
-					port_array[0]->device_name,
-					port_array[0]) < 0) {
-			DBGERR(("%s request_irq failed IRQ=%d\n",
-				port_array[0]->device_name,
-				port_array[0]->irq_level));
-		} else {
-			port_array[0]->irq_requested = true;
-			adapter_test(port_array[0]);
-			for (i=1 ; i < port_count ; i++) {
-				port_array[i]->init_error = port_array[0]->init_error;
-				port_array[i]->gpio_present = port_array[0]->gpio_present;
-			}
-		}
-	}
-
-	for (i=0; i < port_count; ++i)
-		tty_register_device(serial_driver, port_array[i]->line, &(port_array[i]->pdev->dev));
-}
-
-static int __devinit init_one(struct pci_dev *dev,
-			      const struct pci_device_id *ent)
-{
-	if (pci_enable_device(dev)) {
-		printk("error enabling pci device %p\n", dev);
-		return -EIO;
-	}
-	pci_set_master(dev);
-	device_init(slgt_device_count, dev);
-	return 0;
-}
-
-static void __devexit remove_one(struct pci_dev *dev)
-{
-}
-
-static const struct tty_operations ops = {
-	.open = open,
-	.close = close,
-	.write = write,
-	.put_char = put_char,
-	.flush_chars = flush_chars,
-	.write_room = write_room,
-	.chars_in_buffer = chars_in_buffer,
-	.flush_buffer = flush_buffer,
-	.ioctl = ioctl,
-	.compat_ioctl = slgt_compat_ioctl,
-	.throttle = throttle,
-	.unthrottle = unthrottle,
-	.send_xchar = send_xchar,
-	.break_ctl = set_break,
-	.wait_until_sent = wait_until_sent,
-	.set_termios = set_termios,
-	.stop = tx_hold,
-	.start = tx_release,
-	.hangup = hangup,
-	.tiocmget = tiocmget,
-	.tiocmset = tiocmset,
-	.get_icount = get_icount,
-	.proc_fops = &synclink_gt_proc_fops,
-};
-
-static void slgt_cleanup(void)
-{
-	int rc;
-	struct slgt_info *info;
-	struct slgt_info *tmp;
-
-	printk(KERN_INFO "unload %s\n", driver_name);
-
-	if (serial_driver) {
-		for (info=slgt_device_list ; info != NULL ; info=info->next_device)
-			tty_unregister_device(serial_driver, info->line);
-		if ((rc = tty_unregister_driver(serial_driver)))
-			DBGERR(("tty_unregister_driver error=%d\n", rc));
-		put_tty_driver(serial_driver);
-	}
-
-	/* reset devices */
-	info = slgt_device_list;
-	while(info) {
-		reset_port(info);
-		info = info->next_device;
-	}
-
-	/* release devices */
-	info = slgt_device_list;
-	while(info) {
-#if SYNCLINK_GENERIC_HDLC
-		hdlcdev_exit(info);
-#endif
-		free_dma_bufs(info);
-		free_tmp_rbuf(info);
-		if (info->port_num == 0)
-			release_resources(info);
-		tmp = info;
-		info = info->next_device;
-		kfree(tmp);
-	}
-
-	if (pci_registered)
-		pci_unregister_driver(&pci_driver);
-}
-
-/*
- *  Driver initialization entry point.
- */
-static int __init slgt_init(void)
-{
-	int rc;
-
-	printk(KERN_INFO "%s\n", driver_name);
-
-	serial_driver = alloc_tty_driver(MAX_DEVICES);
-	if (!serial_driver) {
-		printk("%s can't allocate tty driver\n", driver_name);
-		return -ENOMEM;
-	}
-
-	/* Initialize the tty_driver structure */
-
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = tty_driver_name;
-	serial_driver->name = tty_dev_prefix;
-	serial_driver->major = ttymajor;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->init_termios.c_ispeed = 9600;
-	serial_driver->init_termios.c_ospeed = 9600;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
-	tty_set_operations(serial_driver, &ops);
-	if ((rc = tty_register_driver(serial_driver)) < 0) {
-		DBGERR(("%s can't register serial driver\n", driver_name));
-		put_tty_driver(serial_driver);
-		serial_driver = NULL;
-		goto error;
-	}
-
-	printk(KERN_INFO "%s, tty major#%d\n",
-	       driver_name, serial_driver->major);
-
-	slgt_device_count = 0;
-	if ((rc = pci_register_driver(&pci_driver)) < 0) {
-		printk("%s pci_register_driver error=%d\n", driver_name, rc);
-		goto error;
-	}
-	pci_registered = true;
-
-	if (!slgt_device_list)
-		printk("%s no devices found\n",driver_name);
-
-	return 0;
-
-error:
-	slgt_cleanup();
-	return rc;
-}
-
-static void __exit slgt_exit(void)
-{
-	slgt_cleanup();
-}
-
-module_init(slgt_init);
-module_exit(slgt_exit);
-
-/*
- * register access routines
- */
-
-#define CALC_REGADDR() \
-	unsigned long reg_addr = ((unsigned long)info->reg_addr) + addr; \
-	if (addr >= 0x80) \
-		reg_addr += (info->port_num) * 32; \
-	else if (addr >= 0x40)	\
-		reg_addr += (info->port_num) * 16;
-
-static __u8 rd_reg8(struct slgt_info *info, unsigned int addr)
-{
-	CALC_REGADDR();
-	return readb((void __iomem *)reg_addr);
-}
-
-static void wr_reg8(struct slgt_info *info, unsigned int addr, __u8 value)
-{
-	CALC_REGADDR();
-	writeb(value, (void __iomem *)reg_addr);
-}
-
-static __u16 rd_reg16(struct slgt_info *info, unsigned int addr)
-{
-	CALC_REGADDR();
-	return readw((void __iomem *)reg_addr);
-}
-
-static void wr_reg16(struct slgt_info *info, unsigned int addr, __u16 value)
-{
-	CALC_REGADDR();
-	writew(value, (void __iomem *)reg_addr);
-}
-
-static __u32 rd_reg32(struct slgt_info *info, unsigned int addr)
-{
-	CALC_REGADDR();
-	return readl((void __iomem *)reg_addr);
-}
-
-static void wr_reg32(struct slgt_info *info, unsigned int addr, __u32 value)
-{
-	CALC_REGADDR();
-	writel(value, (void __iomem *)reg_addr);
-}
-
-static void rdma_reset(struct slgt_info *info)
-{
-	unsigned int i;
-
-	/* set reset bit */
-	wr_reg32(info, RDCSR, BIT1);
-
-	/* wait for enable bit cleared */
-	for(i=0 ; i < 1000 ; i++)
-		if (!(rd_reg32(info, RDCSR) & BIT0))
-			break;
-}
-
-static void tdma_reset(struct slgt_info *info)
-{
-	unsigned int i;
-
-	/* set reset bit */
-	wr_reg32(info, TDCSR, BIT1);
-
-	/* wait for enable bit cleared */
-	for(i=0 ; i < 1000 ; i++)
-		if (!(rd_reg32(info, TDCSR) & BIT0))
-			break;
-}
-
-/*
- * enable internal loopback
- * TxCLK and RxCLK are generated from BRG
- * and TxD is looped back to RxD internally.
- */
-static void enable_loopback(struct slgt_info *info)
-{
-	/* SCR (serial control) BIT2=looopback enable */
-	wr_reg16(info, SCR, (unsigned short)(rd_reg16(info, SCR) | BIT2));
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		/* CCR (clock control)
-		 * 07..05  tx clock source (010 = BRG)
-		 * 04..02  rx clock source (010 = BRG)
-		 * 01      auxclk enable   (0 = disable)
-		 * 00      BRG enable      (1 = enable)
-		 *
-		 * 0100 1001
-		 */
-		wr_reg8(info, CCR, 0x49);
-
-		/* set speed if available, otherwise use default */
-		if (info->params.clock_speed)
-			set_rate(info, info->params.clock_speed);
-		else
-			set_rate(info, 3686400);
-	}
-}
-
-/*
- *  set baud rate generator to specified rate
- */
-static void set_rate(struct slgt_info *info, u32 rate)
-{
-	unsigned int div;
-	unsigned int osc = info->base_clock;
-
-	/* div = osc/rate - 1
-	 *
-	 * Round div up if osc/rate is not integer to
-	 * force to next slowest rate.
-	 */
-
-	if (rate) {
-		div = osc/rate;
-		if (!(osc % rate) && div)
-			div--;
-		wr_reg16(info, BDR, (unsigned short)div);
-	}
-}
-
-static void rx_stop(struct slgt_info *info)
-{
-	unsigned short val;
-
-	/* disable and reset receiver */
-	val = rd_reg16(info, RCR) & ~BIT1;          /* clear enable bit */
-	wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
-	wr_reg16(info, RCR, val);                  /* clear reset bit */
-
-	slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA + IRQ_RXIDLE);
-
-	/* clear pending rx interrupts */
-	wr_reg16(info, SSR, IRQ_RXIDLE + IRQ_RXOVER);
-
-	rdma_reset(info);
-
-	info->rx_enabled = false;
-	info->rx_restart = false;
-}
-
-static void rx_start(struct slgt_info *info)
-{
-	unsigned short val;
-
-	slgt_irq_off(info, IRQ_RXOVER + IRQ_RXDATA);
-
-	/* clear pending rx overrun IRQ */
-	wr_reg16(info, SSR, IRQ_RXOVER);
-
-	/* reset and disable receiver */
-	val = rd_reg16(info, RCR) & ~BIT1; /* clear enable bit */
-	wr_reg16(info, RCR, (unsigned short)(val | BIT2)); /* set reset bit */
-	wr_reg16(info, RCR, val);                  /* clear reset bit */
-
-	rdma_reset(info);
-	reset_rbufs(info);
-
-	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 {
-		/* 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);
-
-	/* enable receiver */
-	wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
-
-	info->rx_restart = false;
-	info->rx_enabled = true;
-}
-
-static void tx_start(struct slgt_info *info)
-{
-	if (!info->tx_enabled) {
-		wr_reg16(info, TCR,
-			 (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
-		info->tx_enabled = true;
-	}
-
-	if (desc_count(info->tbufs[info->tbuf_start])) {
-		info->drop_rts_on_tx_done = false;
-
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
-				get_signals(info);
-				if (!(info->signals & SerialSignal_RTS)) {
-					info->signals |= SerialSignal_RTS;
-					set_signals(info);
-					info->drop_rts_on_tx_done = true;
-				}
-			}
-
-			slgt_irq_off(info, IRQ_TXDATA);
-			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));
-		} else {
-			slgt_irq_off(info, IRQ_TXDATA);
-			slgt_irq_on(info, IRQ_TXIDLE);
-			/* clear tx idle status bit */
-			wr_reg16(info, SSR, IRQ_TXIDLE);
-		}
-		/* 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;
-	}
-}
-
-static void tx_stop(struct slgt_info *info)
-{
-	unsigned short val;
-
-	del_timer(&info->tx_timer);
-
-	tdma_reset(info);
-
-	/* reset and disable transmitter */
-	val = rd_reg16(info, TCR) & ~BIT1;          /* clear enable bit */
-	wr_reg16(info, TCR, (unsigned short)(val | BIT2)); /* set reset bit */
-
-	slgt_irq_off(info, IRQ_TXDATA + IRQ_TXIDLE + IRQ_TXUNDER);
-
-	/* clear tx idle and underrun status bit */
-	wr_reg16(info, SSR, (unsigned short)(IRQ_TXIDLE + IRQ_TXUNDER));
-
-	reset_tbufs(info);
-
-	info->tx_enabled = false;
-	info->tx_active = false;
-}
-
-static void reset_port(struct slgt_info *info)
-{
-	if (!info->reg_addr)
-		return;
-
-	tx_stop(info);
-	rx_stop(info);
-
-	info->signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-	set_signals(info);
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-}
-
-static void reset_adapter(struct slgt_info *info)
-{
-	int i;
-	for (i=0; i < info->port_count; ++i) {
-		if (info->port_array[i])
-			reset_port(info->port_array[i]);
-	}
-}
-
-static void async_mode(struct slgt_info *info)
-{
-  	unsigned short val;
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-	tx_stop(info);
-	rx_stop(info);
-
-	/* TCR (tx control)
-	 *
-	 * 15..13  mode, 010=async
-	 * 12..10  encoding, 000=NRZ
-	 * 09      parity enable
-	 * 08      1=odd parity, 0=even parity
-	 * 07      1=RTS driver control
-	 * 06      1=break enable
-	 * 05..04  character length
-	 *         00=5 bits
-	 *         01=6 bits
-	 *         10=7 bits
-	 *         11=8 bits
-	 * 03      0=1 stop bit, 1=2 stop bits
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-CTS enable
-	 */
-	val = 0x4000;
-
-	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
-		val |= BIT7;
-
-	if (info->params.parity != ASYNC_PARITY_NONE) {
-		val |= BIT9;
-		if (info->params.parity == ASYNC_PARITY_ODD)
-			val |= BIT8;
-	}
-
-	switch (info->params.data_bits)
-	{
-	case 6: val |= BIT4; break;
-	case 7: val |= BIT5; break;
-	case 8: val |= BIT5 + BIT4; break;
-	}
-
-	if (info->params.stop_bits != 1)
-		val |= BIT3;
-
-	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
-		val |= BIT0;
-
-	wr_reg16(info, TCR, val);
-
-	/* RCR (rx control)
-	 *
-	 * 15..13  mode, 010=async
-	 * 12..10  encoding, 000=NRZ
-	 * 09      parity enable
-	 * 08      1=odd parity, 0=even parity
-	 * 07..06  reserved, must be 0
-	 * 05..04  character length
-	 *         00=5 bits
-	 *         01=6 bits
-	 *         10=7 bits
-	 *         11=8 bits
-	 * 03      reserved, must be zero
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-DCD enable
-	 */
-	val = 0x4000;
-
-	if (info->params.parity != ASYNC_PARITY_NONE) {
-		val |= BIT9;
-		if (info->params.parity == ASYNC_PARITY_ODD)
-			val |= BIT8;
-	}
-
-	switch (info->params.data_bits)
-	{
-	case 6: val |= BIT4; break;
-	case 7: val |= BIT5; break;
-	case 8: val |= BIT5 + BIT4; break;
-	}
-
-	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
-		val |= BIT0;
-
-	wr_reg16(info, RCR, val);
-
-	/* CCR (clock control)
-	 *
-	 * 07..05  011 = tx clock source is BRG/16
-	 * 04..02  010 = rx clock source is BRG
-	 * 01      0 = auxclk disabled
-	 * 00      1 = BRG enabled
-	 *
-	 * 0110 1001
-	 */
-	wr_reg8(info, CCR, 0x69);
-
-	msc_set_vcr(info);
-
-	/* SCR (serial control)
-	 *
-	 * 15  1=tx req on FIFO half empty
-	 * 14  1=rx req on FIFO half full
-	 * 13  tx data  IRQ enable
-	 * 12  tx idle  IRQ enable
-	 * 11  rx break on IRQ enable
-	 * 10  rx data  IRQ enable
-	 * 09  rx break off IRQ enable
-	 * 08  overrun  IRQ enable
-	 * 07  DSR      IRQ enable
-	 * 06  CTS      IRQ enable
-	 * 05  DCD      IRQ enable
-	 * 04  RI       IRQ enable
-	 * 03  0=16x sampling, 1=8x sampling
-	 * 02  1=txd->rxd internal loopback enable
-	 * 01  reserved, must be zero
-	 * 00  1=master IRQ enable
-	 */
-	val = BIT15 + BIT14 + BIT0;
-	/* JCR[8] : 1 = x8 async mode feature available */
-	if ((rd_reg32(info, JCR) & BIT8) && info->params.data_rate &&
-	    ((info->base_clock < (info->params.data_rate * 16)) ||
-	     (info->base_clock % (info->params.data_rate * 16)))) {
-		/* use 8x sampling */
-		val |= BIT3;
-		set_rate(info, info->params.data_rate * 8);
-	} else {
-		/* use 16x sampling */
-		set_rate(info, info->params.data_rate * 16);
-	}
-	wr_reg16(info, SCR, val);
-
-	slgt_irq_on(info, IRQ_RXBREAK | IRQ_RXOVER);
-
-	if (info->params.loopback)
-		enable_loopback(info);
-}
-
-static void sync_mode(struct slgt_info *info)
-{
-	unsigned short val;
-
-	slgt_irq_off(info, IRQ_ALL | IRQ_MASTER);
-	tx_stop(info);
-	rx_stop(info);
-
-	/* TCR (tx control)
-	 *
-	 * 15..13  mode
-	 *         000=HDLC/SDLC
-	 *         001=raw bit synchronous
-	 *         010=asynchronous/isochronous
-	 *         011=monosync byte synchronous
-	 *         100=bisync byte synchronous
-	 *         101=xsync byte synchronous
-	 * 12..10  encoding
-	 * 09      CRC enable
-	 * 08      CRC32
-	 * 07      1=RTS driver control
-	 * 06      preamble enable
-	 * 05..04  preamble length
-	 * 03      share open/close flag
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-CTS enable
-	 */
-	val = BIT2;
-
-	switch(info->params.mode) {
-	case MGSL_MODE_XSYNC:
-		val |= BIT15 + BIT13;
-		break;
-	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
-	case MGSL_MODE_BISYNC:   val |= BIT15; break;
-	case MGSL_MODE_RAW:      val |= BIT13; break;
-	}
-	if (info->if_mode & MGSL_INTERFACE_RTS_EN)
-		val |= BIT7;
-
-	switch(info->params.encoding)
-	{
-	case HDLC_ENCODING_NRZB:          val |= BIT10; break;
-	case HDLC_ENCODING_NRZI_MARK:     val |= BIT11; break;
-	case HDLC_ENCODING_NRZI:          val |= BIT11 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_MARK:  val |= BIT12; break;
-	case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
-	}
-
-	switch (info->params.crc_type & HDLC_CRC_MASK)
-	{
-	case HDLC_CRC_16_CCITT: val |= BIT9; break;
-	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
-	}
-
-	if (info->params.preamble != HDLC_PREAMBLE_PATTERN_NONE)
-		val |= BIT6;
-
-	switch (info->params.preamble_length)
-	{
-	case HDLC_PREAMBLE_LENGTH_16BITS: val |= BIT5; break;
-	case HDLC_PREAMBLE_LENGTH_32BITS: val |= BIT4; break;
-	case HDLC_PREAMBLE_LENGTH_64BITS: val |= BIT5 + BIT4; break;
-	}
-
-	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
-		val |= BIT0;
-
-	wr_reg16(info, TCR, val);
-
-	/* TPR (transmit preamble) */
-
-	switch (info->params.preamble)
-	{
-	case HDLC_PREAMBLE_PATTERN_FLAGS: val = 0x7e; break;
-	case HDLC_PREAMBLE_PATTERN_ONES:  val = 0xff; break;
-	case HDLC_PREAMBLE_PATTERN_ZEROS: val = 0x00; break;
-	case HDLC_PREAMBLE_PATTERN_10:    val = 0x55; break;
-	case HDLC_PREAMBLE_PATTERN_01:    val = 0xaa; break;
-	default:                          val = 0x7e; break;
-	}
-	wr_reg8(info, TPR, (unsigned char)val);
-
-	/* RCR (rx control)
-	 *
-	 * 15..13  mode
-	 *         000=HDLC/SDLC
-	 *         001=raw bit synchronous
-	 *         010=asynchronous/isochronous
-	 *         011=monosync byte synchronous
-	 *         100=bisync byte synchronous
-	 *         101=xsync byte synchronous
-	 * 12..10  encoding
-	 * 09      CRC enable
-	 * 08      CRC32
-	 * 07..03  reserved, must be 0
-	 * 02      reset
-	 * 01      enable
-	 * 00      auto-DCD enable
-	 */
-	val = 0;
-
-	switch(info->params.mode) {
-	case MGSL_MODE_XSYNC:
-		val |= BIT15 + BIT13;
-		break;
-	case MGSL_MODE_MONOSYNC: val |= BIT14 + BIT13; break;
-	case MGSL_MODE_BISYNC:   val |= BIT15; break;
-	case MGSL_MODE_RAW:      val |= BIT13; break;
-	}
-
-	switch(info->params.encoding)
-	{
-	case HDLC_ENCODING_NRZB:          val |= BIT10; break;
-	case HDLC_ENCODING_NRZI_MARK:     val |= BIT11; break;
-	case HDLC_ENCODING_NRZI:          val |= BIT11 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_MARK:  val |= BIT12; break;
-	case HDLC_ENCODING_BIPHASE_SPACE: val |= BIT12 + BIT10; break;
-	case HDLC_ENCODING_BIPHASE_LEVEL: val |= BIT12 + BIT11; break;
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: val |= BIT12 + BIT11 + BIT10; break;
-	}
-
-	switch (info->params.crc_type & HDLC_CRC_MASK)
-	{
-	case HDLC_CRC_16_CCITT: val |= BIT9; break;
-	case HDLC_CRC_32_CCITT: val |= BIT9 + BIT8; break;
-	}
-
-	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
-		val |= BIT0;
-
-	wr_reg16(info, RCR, val);
-
-	/* CCR (clock control)
-	 *
-	 * 07..05  tx clock source
-	 * 04..02  rx clock source
-	 * 01      auxclk enable
-	 * 00      BRG enable
-	 */
-	val = 0;
-
-	if (info->params.flags & HDLC_FLAG_TXC_BRG)
-	{
-		// when RxC source is DPLL, BRG generates 16X DPLL
-		// reference clock, so take TxC from BRG/16 to get
-		// transmit clock at actual data rate
-		if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-			val |= BIT6 + BIT5;	/* 011, txclk = BRG/16 */
-		else
-			val |= BIT6;	/* 010, txclk = BRG */
-	}
-	else if (info->params.flags & HDLC_FLAG_TXC_DPLL)
-		val |= BIT7;	/* 100, txclk = DPLL Input */
-	else if (info->params.flags & HDLC_FLAG_TXC_RXCPIN)
-		val |= BIT5;	/* 001, txclk = RXC Input */
-
-	if (info->params.flags & HDLC_FLAG_RXC_BRG)
-		val |= BIT3;	/* 010, rxclk = BRG */
-	else if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-		val |= BIT4;	/* 100, rxclk = DPLL */
-	else if (info->params.flags & HDLC_FLAG_RXC_TXCPIN)
-		val |= BIT2;	/* 001, rxclk = TXC Input */
-
-	if (info->params.clock_speed)
-		val |= BIT1 + BIT0;
-
-	wr_reg8(info, CCR, (unsigned char)val);
-
-	if (info->params.flags & (HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL))
-	{
-		// program DPLL mode
-		switch(info->params.encoding)
-		{
-		case HDLC_ENCODING_BIPHASE_MARK:
-		case HDLC_ENCODING_BIPHASE_SPACE:
-			val = BIT7; break;
-		case HDLC_ENCODING_BIPHASE_LEVEL:
-		case HDLC_ENCODING_DIFF_BIPHASE_LEVEL:
-			val = BIT7 + BIT6; break;
-		default: val = BIT6;	// NRZ encodings
-		}
-		wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | val));
-
-		// DPLL requires a 16X reference clock from BRG
-		set_rate(info, info->params.clock_speed * 16);
-	}
-	else
-		set_rate(info, info->params.clock_speed);
-
-	tx_set_idle(info);
-
-	msc_set_vcr(info);
-
-	/* SCR (serial control)
-	 *
-	 * 15  1=tx req on FIFO half empty
-	 * 14  1=rx req on FIFO half full
-	 * 13  tx data  IRQ enable
-	 * 12  tx idle  IRQ enable
-	 * 11  underrun IRQ enable
-	 * 10  rx data  IRQ enable
-	 * 09  rx idle  IRQ enable
-	 * 08  overrun  IRQ enable
-	 * 07  DSR      IRQ enable
-	 * 06  CTS      IRQ enable
-	 * 05  DCD      IRQ enable
-	 * 04  RI       IRQ enable
-	 * 03  reserved, must be zero
-	 * 02  1=txd->rxd internal loopback enable
-	 * 01  reserved, must be zero
-	 * 00  1=master IRQ enable
-	 */
-	wr_reg16(info, SCR, BIT15 + BIT14 + BIT0);
-
-	if (info->params.loopback)
-		enable_loopback(info);
-}
-
-/*
- *  set transmit idle mode
- */
-static void tx_set_idle(struct slgt_info *info)
-{
-	unsigned char val;
-	unsigned short tcr;
-
-	/* if preamble enabled (tcr[6] == 1) then tx idle size = 8 bits
-	 * else tcr[5:4] = tx idle size: 00 = 8 bits, 01 = 16 bits
-	 */
-	tcr = rd_reg16(info, TCR);
-	if (info->idle_mode & HDLC_TXIDLE_CUSTOM_16) {
-		/* disable preamble, set idle size to 16 bits */
-		tcr = (tcr & ~(BIT6 + BIT5)) | BIT4;
-		/* MSB of 16 bit idle specified in tx preamble register (TPR) */
-		wr_reg8(info, TPR, (unsigned char)((info->idle_mode >> 8) & 0xff));
-	} else if (!(tcr & BIT6)) {
-		/* preamble is disabled, set idle size to 8 bits */
-		tcr &= ~(BIT5 + BIT4);
-	}
-	wr_reg16(info, TCR, tcr);
-
-	if (info->idle_mode & (HDLC_TXIDLE_CUSTOM_8 | HDLC_TXIDLE_CUSTOM_16)) {
-		/* LSB of custom tx idle specified in tx idle register */
-		val = (unsigned char)(info->idle_mode & 0xff);
-	} else {
-		/* standard 8 bit idle patterns */
-		switch(info->idle_mode)
-		{
-		case HDLC_TXIDLE_FLAGS:          val = 0x7e; break;
-		case HDLC_TXIDLE_ALT_ZEROS_ONES:
-		case HDLC_TXIDLE_ALT_MARK_SPACE: val = 0xaa; break;
-		case HDLC_TXIDLE_ZEROS:
-		case HDLC_TXIDLE_SPACE:          val = 0x00; break;
-		default:                         val = 0xff;
-		}
-	}
-
-	wr_reg8(info, TIR, val);
-}
-
-/*
- * get state of V24 status (input) signals
- */
-static void get_signals(struct slgt_info *info)
-{
-	unsigned short status = rd_reg16(info, SSR);
-
-	/* clear all serial signals except DTR and RTS */
-	info->signals &= SerialSignal_DTR + SerialSignal_RTS;
-
-	if (status & BIT3)
-		info->signals |= SerialSignal_DSR;
-	if (status & BIT2)
-		info->signals |= SerialSignal_CTS;
-	if (status & BIT1)
-		info->signals |= SerialSignal_DCD;
-	if (status & BIT0)
-		info->signals |= SerialSignal_RI;
-}
-
-/*
- * set V.24 Control Register based on current configuration
- */
-static void msc_set_vcr(struct slgt_info *info)
-{
-	unsigned char val = 0;
-
-	/* VCR (V.24 control)
-	 *
-	 * 07..04  serial IF select
-	 * 03      DTR
-	 * 02      RTS
-	 * 01      LL
-	 * 00      RL
-	 */
-
-	switch(info->if_mode & MGSL_INTERFACE_MASK)
-	{
-	case MGSL_INTERFACE_RS232:
-		val |= BIT5; /* 0010 */
-		break;
-	case MGSL_INTERFACE_V35:
-		val |= BIT7 + BIT6 + BIT5; /* 1110 */
-		break;
-	case MGSL_INTERFACE_RS422:
-		val |= BIT6; /* 0100 */
-		break;
-	}
-
-	if (info->if_mode & MGSL_INTERFACE_MSB_FIRST)
-		val |= BIT4;
-	if (info->signals & SerialSignal_DTR)
-		val |= BIT3;
-	if (info->signals & SerialSignal_RTS)
-		val |= BIT2;
-	if (info->if_mode & MGSL_INTERFACE_LL)
-		val |= BIT1;
-	if (info->if_mode & MGSL_INTERFACE_RL)
-		val |= BIT0;
-	wr_reg8(info, VCR, val);
-}
-
-/*
- * set state of V24 control (output) signals
- */
-static void set_signals(struct slgt_info *info)
-{
-	unsigned char val = rd_reg8(info, VCR);
-	if (info->signals & SerialSignal_DTR)
-		val |= BIT3;
-	else
-		val &= ~BIT3;
-	if (info->signals & SerialSignal_RTS)
-		val |= BIT2;
-	else
-		val &= ~BIT2;
-	wr_reg8(info, VCR, val);
-}
-
-/*
- * free range of receive DMA buffers (i to last)
- */
-static void free_rbufs(struct slgt_info *info, unsigned int i, unsigned int last)
-{
-	int done = 0;
-
-	while(!done) {
-		/* reset current buffer for reuse */
-		info->rbufs[i].status = 0;
-		set_desc_count(info->rbufs[i], info->rbuf_fill_level);
-		if (i == last)
-			done = 1;
-		if (++i == info->rbuf_count)
-			i = 0;
-	}
-	info->rbuf_current = i;
-}
-
-/*
- * mark all receive DMA buffers as free
- */
-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;
-}
-
-/*
- * pass receive HDLC frame to upper layer
- *
- * return true if frame available, otherwise false
- */
-static bool rx_get_frame(struct slgt_info *info)
-{
-	unsigned int start, end;
-	unsigned short status;
-	unsigned int framesize = 0;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-	unsigned char addr_field = 0xff;
-	unsigned int crc_size = 0;
-
-	switch (info->params.crc_type & HDLC_CRC_MASK) {
-	case HDLC_CRC_16_CCITT: crc_size = 2; break;
-	case HDLC_CRC_32_CCITT: crc_size = 4; break;
-	}
-
-check_again:
-
-	framesize = 0;
-	addr_field = 0xff;
-	start = end = info->rbuf_current;
-
-	for (;;) {
-		if (!desc_complete(info->rbufs[end]))
-			goto cleanup;
-
-		if (framesize == 0 && info->params.addr_filter != 0xff)
-			addr_field = info->rbufs[end].buf[0];
-
-		framesize += desc_count(info->rbufs[end]);
-
-		if (desc_eof(info->rbufs[end]))
-			break;
-
-		if (++end == info->rbuf_count)
-			end = 0;
-
-		if (end == info->rbuf_current) {
-			if (info->rx_enabled){
-				spin_lock_irqsave(&info->lock,flags);
-				rx_start(info);
-				spin_unlock_irqrestore(&info->lock,flags);
-			}
-			goto cleanup;
-		}
-	}
-
-	/* status
-	 *
-	 * 15      buffer complete
-	 * 14..06  reserved
-	 * 05..04  residue
-	 * 02      eof (end of frame)
-	 * 01      CRC error
-	 * 00      abort
-	 */
-	status = desc_status(info->rbufs[end]);
-
-	/* ignore CRC bit if not using CRC (bit is undefined) */
-	if ((info->params.crc_type & HDLC_CRC_MASK) == HDLC_CRC_NONE)
-		status &= ~BIT1;
-
-	if (framesize == 0 ||
-		 (addr_field != 0xff && addr_field != info->params.addr_filter)) {
-		free_rbufs(info, start, end);
-		goto check_again;
-	}
-
-	if (framesize < (2 + crc_size) || status & BIT0) {
-		info->icount.rxshort++;
-		framesize = 0;
-	} else if (status & BIT1) {
-		info->icount.rxcrc++;
-		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX))
-			framesize = 0;
-	}
-
-#if SYNCLINK_GENERIC_HDLC
-	if (framesize == 0) {
-		info->netdev->stats.rx_errors++;
-		info->netdev->stats.rx_frame_errors++;
-	}
-#endif
-
-	DBGBH(("%s rx frame status=%04X size=%d\n",
-		info->device_name, status, framesize));
-	DBGDATA(info, info->rbufs[start].buf, min_t(int, framesize, info->rbuf_fill_level), "rx");
-
-	if (framesize) {
-		if (!(info->params.crc_type & HDLC_CRC_RETURN_EX)) {
-			framesize -= crc_size;
-			crc_size = 0;
-		}
-
-		if (framesize > info->max_frame_size + crc_size)
-			info->icount.rxlong++;
-		else {
-			/* copy dma buffer(s) to contiguous temp buffer */
-			int copy_count = framesize;
-			int i = start;
-			unsigned char *p = info->tmp_rbuf;
-			info->tmp_rbuf_count = framesize;
-
-			info->icount.rxok++;
-
-			while(copy_count) {
-				int partial_count = min_t(int, copy_count, info->rbuf_fill_level);
-				memcpy(p, info->rbufs[i].buf, partial_count);
-				p += partial_count;
-				copy_count -= partial_count;
-				if (++i == info->rbuf_count)
-					i = 0;
-			}
-
-			if (info->params.crc_type & HDLC_CRC_RETURN_EX) {
-				*p = (status & BIT1) ? RX_CRC_ERROR : RX_OK;
-				framesize++;
-			}
-
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount)
-				hdlcdev_rx(info,info->tmp_rbuf, framesize);
-			else
-#endif
-				ldisc_receive_buf(tty, info->tmp_rbuf, info->flag_buf, framesize);
-		}
-	}
-	free_rbufs(info, start, end);
-	return true;
-
-cleanup:
-	return false;
-}
-
-/*
- * pass receive buffer (RAW synchronous mode) to tty layer
- * return true if buffer available, otherwise false
- */
-static bool rx_get_buf(struct slgt_info *info)
-{
-	unsigned int i = info->rbuf_current;
-	unsigned int count;
-
-	if (!desc_complete(info->rbufs[i]))
-		return false;
-	count = desc_count(info->rbufs[i]);
-	switch(info->params.mode) {
-	case MGSL_MODE_MONOSYNC:
-	case MGSL_MODE_BISYNC:
-	case MGSL_MODE_XSYNC:
-		/* ignore residue in byte synchronous modes */
-		if (desc_residue(info->rbufs[i]))
-			count--;
-		break;
-	}
-	DBGDATA(info, info->rbufs[i].buf, count, "rx");
-	DBGINFO(("rx_get_buf size=%d\n", count));
-	if (count)
-		ldisc_receive_buf(info->port.tty, info->rbufs[i].buf,
-				  info->flag_buf, count);
-	free_rbufs(info, i, i);
-	return true;
-}
-
-static void reset_tbufs(struct slgt_info *info)
-{
-	unsigned int i;
-	info->tbuf_current = 0;
-	for (i=0 ; i < info->tbuf_count ; i++) {
-		info->tbufs[i].status = 0;
-		info->tbufs[i].count  = 0;
-	}
-}
-
-/*
- * return number of free transmit DMA buffers
- */
-static unsigned int free_tbuf_count(struct slgt_info *info)
-{
-	unsigned int count = 0;
-	unsigned int i = info->tbuf_current;
-
-	do
-	{
-		if (desc_count(info->tbufs[i]))
-			break; /* buffer in use */
-		++count;
-		if (++i == info->tbuf_count)
-			i=0;
-	} while (i != info->tbuf_current);
-
-	/* if tx DMA active, last zero count buffer is in use */
-	if (count && (rd_reg32(info, TDCSR) & BIT0))
-		--count;
-
-	return count;
-}
-
-/*
- * return number of bytes in unsent transmit DMA buffers
- * and the serial controller tx FIFO
- */
-static unsigned int tbuf_bytes(struct slgt_info *info)
-{
-	unsigned int total_count = 0;
-	unsigned int i = info->tbuf_current;
-	unsigned int reg_value;
-	unsigned int count;
-	unsigned int active_buf_count = 0;
-
-	/*
-	 * Add descriptor counts for all tx DMA buffers.
-	 * If count is zero (cleared by DMA controller after read),
-	 * the buffer is complete or is actively being read from.
-	 *
-	 * Record buf_count of last buffer with zero count starting
-	 * from current ring position. buf_count is mirror
-	 * copy of count and is not cleared by serial controller.
-	 * If DMA controller is active, that buffer is actively
-	 * being read so add to total.
-	 */
-	do {
-		count = desc_count(info->tbufs[i]);
-		if (count)
-			total_count += count;
-		else if (!total_count)
-			active_buf_count = info->tbufs[i].buf_count;
-		if (++i == info->tbuf_count)
-			i = 0;
-	} while (i != info->tbuf_current);
-
-	/* read tx DMA status register */
-	reg_value = rd_reg32(info, TDCSR);
-
-	/* if tx DMA active, last zero count buffer is in use */
-	if (reg_value & BIT0)
-		total_count += active_buf_count;
-
-	/* add tx FIFO count = reg_value[15..8] */
-	total_count += (reg_value >> 8) & 0xff;
-
-	/* if transmitter active add one byte for shift register */
-	if (info->tx_active)
-		total_count++;
-
-	return total_count;
-}
-
-/*
- * load data into transmit DMA buffer ring and start transmitter if needed
- * return true if data accepted, otherwise false (buffers full)
- */
-static bool tx_load(struct slgt_info *info, const char *buf, unsigned int size)
-{
-	unsigned short count;
-	unsigned int i;
-	struct slgt_desc *d;
-
-	/* check required buffer space */
-	if (DIV_ROUND_UP(size, DMABUFSIZE) > free_tbuf_count(info))
-		return false;
-
-	DBGDATA(info, buf, size, "tx");
-
-	/*
-	 * copy data to one or more DMA buffers in circular ring
-	 * tbuf_start   = first buffer for this data
-	 * tbuf_current = next free buffer
-	 *
-	 * Copy all data before making data visible to DMA controller by
-	 * setting descriptor count of the first buffer.
-	 * This prevents an active DMA controller from reading the first DMA
-	 * buffers of a frame and stopping before the final buffers are filled.
-	 */
-
-	info->tbuf_start = i = info->tbuf_current;
-
-	while (size) {
-		d = &info->tbufs[i];
-
-		count = (unsigned short)((size > DMABUFSIZE) ? DMABUFSIZE : size);
-		memcpy(d->buf, buf, count);
-
-		size -= count;
-		buf  += count;
-
-		/*
-		 * set EOF bit for last buffer of HDLC frame or
-		 * for every buffer in raw mode
-		 */
-		if ((!size && info->params.mode == MGSL_MODE_HDLC) ||
-		    info->params.mode == MGSL_MODE_RAW)
-			set_desc_eof(*d, 1);
-		else
-			set_desc_eof(*d, 0);
-
-		/* set descriptor count for all but first buffer */
-		if (i != info->tbuf_start)
-			set_desc_count(*d, count);
-		d->buf_count = count;
-
-		if (++i == info->tbuf_count)
-			i = 0;
-	}
-
-	info->tbuf_current = i;
-
-	/* set first buffer count to make new data visible to DMA controller */
-	d = &info->tbufs[info->tbuf_start];
-	set_desc_count(*d, d->buf_count);
-
-	/* start transmitter if needed and update transmit timeout */
-	if (!info->tx_active)
-		tx_start(info);
-	update_tx_timer(info);
-
-	return true;
-}
-
-static int register_test(struct slgt_info *info)
-{
-	static unsigned short patterns[] =
-		{0x0000, 0xffff, 0xaaaa, 0x5555, 0x6969, 0x9696};
-	static unsigned int count = ARRAY_SIZE(patterns);
-	unsigned int i;
-	int rc = 0;
-
-	for (i=0 ; i < count ; i++) {
-		wr_reg16(info, TIR, patterns[i]);
-		wr_reg16(info, BDR, patterns[(i+1)%count]);
-		if ((rd_reg16(info, TIR) != patterns[i]) ||
-		    (rd_reg16(info, BDR) != patterns[(i+1)%count])) {
-			rc = -ENODEV;
-			break;
-		}
-	}
-	info->gpio_present = (rd_reg32(info, JCR) & BIT5) ? 1 : 0;
-	info->init_error = rc ? 0 : DiagStatus_AddressFailure;
-	return rc;
-}
-
-static int irq_test(struct slgt_info *info)
-{
-	unsigned long timeout;
-	unsigned long flags;
-	struct tty_struct *oldtty = info->port.tty;
-	u32 speed = info->params.data_rate;
-
-	info->params.data_rate = 921600;
-	info->port.tty = NULL;
-
-	spin_lock_irqsave(&info->lock, flags);
-	async_mode(info);
-	slgt_irq_on(info, IRQ_TXIDLE);
-
-	/* enable transmitter */
-	wr_reg16(info, TCR,
-		(unsigned short)(rd_reg16(info, TCR) | BIT1));
-
-	/* write one byte and wait for tx idle */
-	wr_reg16(info, TDR, 0);
-
-	/* assume failure */
-	info->init_error = DiagStatus_IrqFailure;
-	info->irq_occurred = false;
-
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	timeout=100;
-	while(timeout-- && !info->irq_occurred)
-		msleep_interruptible(10);
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	info->params.data_rate = speed;
-	info->port.tty = oldtty;
-
-	info->init_error = info->irq_occurred ? 0 : DiagStatus_IrqFailure;
-	return info->irq_occurred ? 0 : -ENODEV;
-}
-
-static int loopback_test_rx(struct slgt_info *info)
-{
-	unsigned char *src, *dest;
-	int count;
-
-	if (desc_complete(info->rbufs[0])) {
-		count = desc_count(info->rbufs[0]);
-		src   = info->rbufs[0].buf;
-		dest  = info->tmp_rbuf;
-
-		for( ; count ; count-=2, src+=2) {
-			/* src=data byte (src+1)=status byte */
-			if (!(*(src+1) & (BIT9 + BIT8))) {
-				*dest = *src;
-				dest++;
-				info->tmp_rbuf_count++;
-			}
-		}
-		DBGDATA(info, info->tmp_rbuf, info->tmp_rbuf_count, "rx");
-		return 1;
-	}
-	return 0;
-}
-
-static int loopback_test(struct slgt_info *info)
-{
-#define TESTFRAMESIZE 20
-
-	unsigned long timeout;
-	u16 count = TESTFRAMESIZE;
-	unsigned char buf[TESTFRAMESIZE];
-	int rc = -ENODEV;
-	unsigned long flags;
-
-	struct tty_struct *oldtty = info->port.tty;
-	MGSL_PARAMS params;
-
-	memcpy(&params, &info->params, sizeof(params));
-
-	info->params.mode = MGSL_MODE_ASYNC;
-	info->params.data_rate = 921600;
-	info->params.loopback = 1;
-	info->port.tty = NULL;
-
-	/* build and send transmit frame */
-	for (count = 0; count < TESTFRAMESIZE; ++count)
-		buf[count] = (unsigned char)count;
-
-	info->tmp_rbuf_count = 0;
-	memset(info->tmp_rbuf, 0, TESTFRAMESIZE);
-
-	/* program hardware for HDLC and enabled receiver */
-	spin_lock_irqsave(&info->lock,flags);
-	async_mode(info);
-	rx_start(info);
-	tx_load(info, buf, count);
-	spin_unlock_irqrestore(&info->lock, flags);
-
-	/* wait for receive complete */
-	for (timeout = 100; timeout; --timeout) {
-		msleep_interruptible(10);
-		if (loopback_test_rx(info)) {
-			rc = 0;
-			break;
-		}
-	}
-
-	/* verify received frame length and contents */
-	if (!rc && (info->tmp_rbuf_count != count ||
-		  memcmp(buf, info->tmp_rbuf, count))) {
-		rc = -ENODEV;
-	}
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_adapter(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	memcpy(&info->params, &params, sizeof(info->params));
-	info->port.tty = oldtty;
-
-	info->init_error = rc ? DiagStatus_DmaFailure : 0;
-	return rc;
-}
-
-static int adapter_test(struct slgt_info *info)
-{
-	DBGINFO(("testing %s\n", info->device_name));
-	if (register_test(info) < 0) {
-		printk("register test failure %s addr=%08X\n",
-			info->device_name, info->phys_reg_addr);
-	} else if (irq_test(info) < 0) {
-		printk("IRQ test failure %s IRQ=%d\n",
-			info->device_name, info->irq_level);
-	} else if (loopback_test(info) < 0) {
-		printk("loopback test failure %s\n", info->device_name);
-	}
-	return info->init_error;
-}
-
-/*
- * transmit timeout handler
- */
-static void tx_timeout(unsigned long context)
-{
-	struct slgt_info *info = (struct slgt_info*)context;
-	unsigned long flags;
-
-	DBGINFO(("%s tx_timeout\n", info->device_name));
-	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
-		info->icount.txtimeout++;
-	}
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else
-#endif
-		bh_transmit(info);
-}
-
-/*
- * receive buffer polling timer
- */
-static void rx_timeout(unsigned long context)
-{
-	struct slgt_info *info = (struct slgt_info*)context;
-	unsigned long flags;
-
-	DBGINFO(("%s rx_timeout\n", info->device_name));
-	spin_lock_irqsave(&info->lock, flags);
-	info->pending_bh |= BH_RECEIVE;
-	spin_unlock_irqrestore(&info->lock, flags);
-	bh_handler(&info->task);
-}
-
diff -druN linux-libre-2.6.38-gnu/drivers/char/synclinkmp.c linux-libre-2.6.39-gnu/drivers/char/synclinkmp.c
--- linux-libre-2.6.38-gnu/drivers/char/synclinkmp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/synclinkmp.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,5601 +0,0 @@
-/*
- * $Id: synclinkmp.c,v 4.38 2005/07/15 13:29:44 paulkf Exp $
- *
- * Device driver for Microgate SyncLink Multiport
- * high speed multiprotocol serial adapter.
- *
- * written by Paul Fulghum for Microgate Corporation
- * paulkf@microgate.com
- *
- * Microgate and SyncLink are trademarks of Microgate Corporation
- *
- * Derived from serial.c written by Theodore Ts'o and Linus Torvalds
- * This code is released under the GNU General Public License (GPL)
- *
- * 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.
- */
-
-#define VERSION(ver,rel,seq) (((ver)<<16) | ((rel)<<8) | (seq))
-#if defined(__i386__)
-#  define BREAKPOINT() asm("   int $3");
-#else
-#  define BREAKPOINT() { }
-#endif
-
-#define MAX_DEVICES 12
-
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/signal.h>
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/pci.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/serial.h>
-#include <linux/major.h>
-#include <linux/string.h>
-#include <linux/fcntl.h>
-#include <linux/ptrace.h>
-#include <linux/ioport.h>
-#include <linux/mm.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-#include <linux/netdevice.h>
-#include <linux/vmalloc.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/ioctl.h>
-
-#include <asm/system.h>
-#include <asm/io.h>
-#include <asm/irq.h>
-#include <asm/dma.h>
-#include <linux/bitops.h>
-#include <asm/types.h>
-#include <linux/termios.h>
-#include <linux/workqueue.h>
-#include <linux/hdlc.h>
-#include <linux/synclink.h>
-
-#if defined(CONFIG_HDLC) || (defined(CONFIG_HDLC_MODULE) && defined(CONFIG_SYNCLINKMP_MODULE))
-#define SYNCLINK_GENERIC_HDLC 1
-#else
-#define SYNCLINK_GENERIC_HDLC 0
-#endif
-
-#define GET_USER(error,value,addr) error = get_user(value,addr)
-#define COPY_FROM_USER(error,dest,src,size) error = copy_from_user(dest,src,size) ? -EFAULT : 0
-#define PUT_USER(error,value,addr) error = put_user(value,addr)
-#define COPY_TO_USER(error,dest,src,size) error = copy_to_user(dest,src,size) ? -EFAULT : 0
-
-#include <asm/uaccess.h>
-
-static MGSL_PARAMS default_params = {
-	MGSL_MODE_HDLC,			/* unsigned long mode */
-	0,				/* unsigned char loopback; */
-	HDLC_FLAG_UNDERRUN_ABORT15,	/* unsigned short flags; */
-	HDLC_ENCODING_NRZI_SPACE,	/* unsigned char encoding; */
-	0,				/* unsigned long clock_speed; */
-	0xff,				/* unsigned char addr_filter; */
-	HDLC_CRC_16_CCITT,		/* unsigned short crc_type; */
-	HDLC_PREAMBLE_LENGTH_8BITS,	/* unsigned char preamble_length; */
-	HDLC_PREAMBLE_PATTERN_NONE,	/* unsigned char preamble; */
-	9600,				/* unsigned long data_rate; */
-	8,				/* unsigned char data_bits; */
-	1,				/* unsigned char stop_bits; */
-	ASYNC_PARITY_NONE		/* unsigned char parity; */
-};
-
-/* size in bytes of DMA data buffers */
-#define SCABUFSIZE 	1024
-#define SCA_MEM_SIZE	0x40000
-#define SCA_BASE_SIZE   512
-#define SCA_REG_SIZE    16
-#define SCA_MAX_PORTS   4
-#define SCAMAXDESC 	128
-
-#define	BUFFERLISTSIZE	4096
-
-/* SCA-I style DMA buffer descriptor */
-typedef struct _SCADESC
-{
-	u16	next;		/* lower l6 bits of next descriptor addr */
-	u16	buf_ptr;	/* lower 16 bits of buffer addr */
-	u8	buf_base;	/* upper 8 bits of buffer addr */
-	u8	pad1;
-	u16	length;		/* length of buffer */
-	u8	status;		/* status of buffer */
-	u8	pad2;
-} SCADESC, *PSCADESC;
-
-typedef struct _SCADESC_EX
-{
-	/* device driver bookkeeping section */
-	char 	*virt_addr;    	/* virtual address of data buffer */
-	u16	phys_entry;	/* lower 16-bits of physical address of this descriptor */
-} SCADESC_EX, *PSCADESC_EX;
-
-/* The queue of BH actions to be performed */
-
-#define BH_RECEIVE  1
-#define BH_TRANSMIT 2
-#define BH_STATUS   4
-
-#define IO_PIN_SHUTDOWN_LIMIT 100
-
-struct	_input_signal_events {
-	int	ri_up;
-	int	ri_down;
-	int	dsr_up;
-	int	dsr_down;
-	int	dcd_up;
-	int	dcd_down;
-	int	cts_up;
-	int	cts_down;
-};
-
-/*
- * Device instance data structure
- */
-typedef struct _synclinkmp_info {
-	void *if_ptr;				/* General purpose pointer (used by SPPP) */
-	int			magic;
-	struct tty_port		port;
-	int			line;
-	unsigned short		close_delay;
-	unsigned short		closing_wait;	/* time to wait before closing */
-
-	struct mgsl_icount	icount;
-
-	int			timeout;
-	int			x_char;		/* xon/xoff character */
-	u16			read_status_mask1;  /* break detection (SR1 indications) */
-	u16			read_status_mask2;  /* parity/framing/overun (SR2 indications) */
-	unsigned char 		ignore_status_mask1;  /* break detection (SR1 indications) */
-	unsigned char		ignore_status_mask2;  /* parity/framing/overun (SR2 indications) */
-	unsigned char 		*tx_buf;
-	int			tx_put;
-	int			tx_get;
-	int			tx_count;
-
-	wait_queue_head_t	status_event_wait_q;
-	wait_queue_head_t	event_wait_q;
-	struct timer_list	tx_timer;	/* HDLC transmit timeout timer */
-	struct _synclinkmp_info	*next_device;	/* device list link */
-	struct timer_list	status_timer;	/* input signal status check timer */
-
-	spinlock_t lock;		/* spinlock for synchronizing with ISR */
-	struct work_struct task;	 		/* task structure for scheduling bh */
-
-	u32 max_frame_size;			/* as set by device config */
-
-	u32 pending_bh;
-
-	bool bh_running;				/* Protection from multiple */
-	int isr_overflow;
-	bool bh_requested;
-
-	int dcd_chkcount;			/* check counts to prevent */
-	int cts_chkcount;			/* too many IRQs if a signal */
-	int dsr_chkcount;			/* is floating */
-	int ri_chkcount;
-
-	char *buffer_list;			/* virtual address of Rx & Tx buffer lists */
-	unsigned long buffer_list_phys;
-
-	unsigned int rx_buf_count;		/* count of total allocated Rx buffers */
-	SCADESC *rx_buf_list;   		/* list of receive buffer entries */
-	SCADESC_EX rx_buf_list_ex[SCAMAXDESC]; /* list of receive buffer entries */
-	unsigned int current_rx_buf;
-
-	unsigned int tx_buf_count;		/* count of total allocated Tx buffers */
-	SCADESC *tx_buf_list;		/* list of transmit buffer entries */
-	SCADESC_EX tx_buf_list_ex[SCAMAXDESC]; /* list of transmit buffer entries */
-	unsigned int last_tx_buf;
-
-	unsigned char *tmp_rx_buf;
-	unsigned int tmp_rx_buf_count;
-
-	bool rx_enabled;
-	bool rx_overflow;
-
-	bool tx_enabled;
-	bool tx_active;
-	u32 idle_mode;
-
-	unsigned char ie0_value;
-	unsigned char ie1_value;
-	unsigned char ie2_value;
-	unsigned char ctrlreg_value;
-	unsigned char old_signals;
-
-	char device_name[25];			/* device instance name */
-
-	int port_count;
-	int adapter_num;
-	int port_num;
-
-	struct _synclinkmp_info *port_array[SCA_MAX_PORTS];
-
-	unsigned int bus_type;			/* expansion bus type (ISA,EISA,PCI) */
-
-	unsigned int irq_level;			/* interrupt level */
-	unsigned long irq_flags;
-	bool irq_requested;			/* true if IRQ requested */
-
-	MGSL_PARAMS params;			/* communications parameters */
-
-	unsigned char serial_signals;		/* current serial signal states */
-
-	bool irq_occurred;			/* for diagnostics use */
-	unsigned int init_error;		/* Initialization startup error */
-
-	u32 last_mem_alloc;
-	unsigned char* memory_base;		/* shared memory address (PCI only) */
-	u32 phys_memory_base;
-    	int shared_mem_requested;
-
-	unsigned char* sca_base;		/* HD64570 SCA Memory address */
-	u32 phys_sca_base;
-	u32 sca_offset;
-	bool sca_base_requested;
-
-	unsigned char* lcr_base;		/* local config registers (PCI only) */
-	u32 phys_lcr_base;
-	u32 lcr_offset;
-	int lcr_mem_requested;
-
-	unsigned char* statctrl_base;		/* status/control register memory */
-	u32 phys_statctrl_base;
-	u32 statctrl_offset;
-	bool sca_statctrl_requested;
-
-	u32 misc_ctrl_value;
-	char flag_buf[MAX_ASYNC_BUFFER_SIZE];
-	char char_buf[MAX_ASYNC_BUFFER_SIZE];
-	bool drop_rts_on_tx_done;
-
-	struct	_input_signal_events	input_signal_events;
-
-	/* SPPP/Cisco HDLC device parts */
-	int netcount;
-	spinlock_t netlock;
-
-#if SYNCLINK_GENERIC_HDLC
-	struct net_device *netdev;
-#endif
-
-} SLMP_INFO;
-
-#define MGSL_MAGIC 0x5401
-
-/*
- * define serial signal status change macros
- */
-#define	MISCSTATUS_DCD_LATCHED	(SerialSignal_DCD<<8)	/* indicates change in DCD */
-#define MISCSTATUS_RI_LATCHED	(SerialSignal_RI<<8)	/* indicates change in RI */
-#define MISCSTATUS_CTS_LATCHED	(SerialSignal_CTS<<8)	/* indicates change in CTS */
-#define MISCSTATUS_DSR_LATCHED	(SerialSignal_DSR<<8)	/* change in DSR */
-
-/* Common Register macros */
-#define LPR	0x00
-#define PABR0	0x02
-#define PABR1	0x03
-#define WCRL	0x04
-#define WCRM	0x05
-#define WCRH	0x06
-#define DPCR	0x08
-#define DMER	0x09
-#define ISR0	0x10
-#define ISR1	0x11
-#define ISR2	0x12
-#define IER0	0x14
-#define IER1	0x15
-#define IER2	0x16
-#define ITCR	0x18
-#define INTVR 	0x1a
-#define IMVR	0x1c
-
-/* MSCI Register macros */
-#define TRB	0x20
-#define TRBL	0x20
-#define TRBH	0x21
-#define SR0	0x22
-#define SR1	0x23
-#define SR2	0x24
-#define SR3	0x25
-#define FST	0x26
-#define IE0	0x28
-#define IE1	0x29
-#define IE2	0x2a
-#define FIE	0x2b
-#define CMD	0x2c
-#define MD0	0x2e
-#define MD1	0x2f
-#define MD2	0x30
-#define CTL	0x31
-#define SA0	0x32
-#define SA1	0x33
-#define IDL	0x34
-#define TMC	0x35
-#define RXS	0x36
-#define TXS	0x37
-#define TRC0	0x38
-#define TRC1	0x39
-#define RRC	0x3a
-#define CST0	0x3c
-#define CST1	0x3d
-
-/* Timer Register Macros */
-#define TCNT	0x60
-#define TCNTL	0x60
-#define TCNTH	0x61
-#define TCONR	0x62
-#define TCONRL	0x62
-#define TCONRH	0x63
-#define TMCS	0x64
-#define TEPR	0x65
-
-/* DMA Controller Register macros */
-#define DARL	0x80
-#define DARH	0x81
-#define DARB	0x82
-#define BAR	0x80
-#define BARL	0x80
-#define BARH	0x81
-#define BARB	0x82
-#define SAR	0x84
-#define SARL	0x84
-#define SARH	0x85
-#define SARB	0x86
-#define CPB	0x86
-#define CDA	0x88
-#define CDAL	0x88
-#define CDAH	0x89
-#define EDA	0x8a
-#define EDAL	0x8a
-#define EDAH	0x8b
-#define BFL	0x8c
-#define BFLL	0x8c
-#define BFLH	0x8d
-#define BCR	0x8e
-#define BCRL	0x8e
-#define BCRH	0x8f
-#define DSR	0x90
-#define DMR	0x91
-#define FCT	0x93
-#define DIR	0x94
-#define DCMD	0x95
-
-/* combine with timer or DMA register address */
-#define TIMER0	0x00
-#define TIMER1	0x08
-#define TIMER2	0x10
-#define TIMER3	0x18
-#define RXDMA 	0x00
-#define TXDMA 	0x20
-
-/* SCA Command Codes */
-#define NOOP		0x00
-#define TXRESET		0x01
-#define TXENABLE	0x02
-#define TXDISABLE	0x03
-#define TXCRCINIT	0x04
-#define TXCRCEXCL	0x05
-#define TXEOM		0x06
-#define TXABORT		0x07
-#define MPON		0x08
-#define TXBUFCLR	0x09
-#define RXRESET		0x11
-#define RXENABLE	0x12
-#define RXDISABLE	0x13
-#define RXCRCINIT	0x14
-#define RXREJECT	0x15
-#define SEARCHMP	0x16
-#define RXCRCEXCL	0x17
-#define RXCRCCALC	0x18
-#define CHRESET		0x21
-#define HUNT		0x31
-
-/* DMA command codes */
-#define SWABORT		0x01
-#define FEICLEAR	0x02
-
-/* IE0 */
-#define TXINTE 		BIT7
-#define RXINTE 		BIT6
-#define TXRDYE 		BIT1
-#define RXRDYE 		BIT0
-
-/* IE1 & SR1 */
-#define UDRN   	BIT7
-#define IDLE   	BIT6
-#define SYNCD  	BIT4
-#define FLGD   	BIT4
-#define CCTS   	BIT3
-#define CDCD   	BIT2
-#define BRKD   	BIT1
-#define ABTD   	BIT1
-#define GAPD   	BIT1
-#define BRKE   	BIT0
-#define IDLD	BIT0
-
-/* IE2 & SR2 */
-#define EOM	BIT7
-#define PMP	BIT6
-#define SHRT	BIT6
-#define PE	BIT5
-#define ABT	BIT5
-#define FRME	BIT4
-#define RBIT	BIT4
-#define OVRN	BIT3
-#define CRCE	BIT2
-
-
-/*
- * Global linked list of SyncLink devices
- */
-static SLMP_INFO *synclinkmp_device_list = NULL;
-static int synclinkmp_adapter_count = -1;
-static int synclinkmp_device_count = 0;
-
-/*
- * Set this param to non-zero to load eax with the
- * .text section address and breakpoint on module load.
- * This is useful for use with gdb and add-symbol-file command.
- */
-static int break_on_load = 0;
-
-/*
- * Driver major number, defaults to zero to get auto
- * assigned major number. May be forced as module parameter.
- */
-static int ttymajor = 0;
-
-/*
- * Array of user specified options for ISA adapters.
- */
-static int debug_level = 0;
-static int maxframe[MAX_DEVICES] = {0,};
-
-module_param(break_on_load, bool, 0);
-module_param(ttymajor, int, 0);
-module_param(debug_level, int, 0);
-module_param_array(maxframe, int, NULL, 0);
-
-static char *driver_name = "SyncLink MultiPort driver";
-static char *driver_version = "$Revision: 4.38 $";
-
-static int synclinkmp_init_one(struct pci_dev *dev,const struct pci_device_id *ent);
-static void synclinkmp_remove_one(struct pci_dev *dev);
-
-static struct pci_device_id synclinkmp_pci_tbl[] = {
-	{ PCI_VENDOR_ID_MICROGATE, PCI_DEVICE_ID_MICROGATE_SCA, PCI_ANY_ID, PCI_ANY_ID, },
-	{ 0, }, /* terminate list */
-};
-MODULE_DEVICE_TABLE(pci, synclinkmp_pci_tbl);
-
-MODULE_LICENSE("GPL");
-
-static struct pci_driver synclinkmp_pci_driver = {
-	.name		= "synclinkmp",
-	.id_table	= synclinkmp_pci_tbl,
-	.probe		= synclinkmp_init_one,
-	.remove		= __devexit_p(synclinkmp_remove_one),
-};
-
-
-static struct tty_driver *serial_driver;
-
-/* number of characters left in xmit buffer before we ask for more */
-#define WAKEUP_CHARS 256
-
-
-/* tty callbacks */
-
-static int  open(struct tty_struct *tty, struct file * filp);
-static void close(struct tty_struct *tty, struct file * filp);
-static void hangup(struct tty_struct *tty);
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios);
-
-static int  write(struct tty_struct *tty, const unsigned char *buf, int count);
-static int put_char(struct tty_struct *tty, unsigned char ch);
-static void send_xchar(struct tty_struct *tty, char ch);
-static void wait_until_sent(struct tty_struct *tty, int timeout);
-static int  write_room(struct tty_struct *tty);
-static void flush_chars(struct tty_struct *tty);
-static void flush_buffer(struct tty_struct *tty);
-static void tx_hold(struct tty_struct *tty);
-static void tx_release(struct tty_struct *tty);
-
-static int  ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd, unsigned long arg);
-static int  chars_in_buffer(struct tty_struct *tty);
-static void throttle(struct tty_struct * tty);
-static void unthrottle(struct tty_struct * tty);
-static int set_break(struct tty_struct *tty, int break_state);
-
-#if SYNCLINK_GENERIC_HDLC
-#define dev_to_port(D) (dev_to_hdlc(D)->priv)
-static void hdlcdev_tx_done(SLMP_INFO *info);
-static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size);
-static int  hdlcdev_init(SLMP_INFO *info);
-static void hdlcdev_exit(SLMP_INFO *info);
-#endif
-
-/* ioctl handlers */
-
-static int  get_stats(SLMP_INFO *info, struct mgsl_icount __user *user_icount);
-static int  get_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
-static int  set_params(SLMP_INFO *info, MGSL_PARAMS __user *params);
-static int  get_txidle(SLMP_INFO *info, int __user *idle_mode);
-static int  set_txidle(SLMP_INFO *info, int idle_mode);
-static int  tx_enable(SLMP_INFO *info, int enable);
-static int  tx_abort(SLMP_INFO *info);
-static int  rx_enable(SLMP_INFO *info, int enable);
-static int  modem_input_wait(SLMP_INFO *info,int arg);
-static int  wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
-static int  tiocmget(struct tty_struct *tty, struct file *file);
-static int  tiocmset(struct tty_struct *tty, struct file *file,
-		     unsigned int set, unsigned int clear);
-static int  set_break(struct tty_struct *tty, int break_state);
-
-static void add_device(SLMP_INFO *info);
-static void device_init(int adapter_num, struct pci_dev *pdev);
-static int  claim_resources(SLMP_INFO *info);
-static void release_resources(SLMP_INFO *info);
-
-static int  startup(SLMP_INFO *info);
-static int  block_til_ready(struct tty_struct *tty, struct file * filp,SLMP_INFO *info);
-static int carrier_raised(struct tty_port *port);
-static void shutdown(SLMP_INFO *info);
-static void program_hw(SLMP_INFO *info);
-static void change_params(SLMP_INFO *info);
-
-static bool init_adapter(SLMP_INFO *info);
-static bool register_test(SLMP_INFO *info);
-static bool irq_test(SLMP_INFO *info);
-static bool loopback_test(SLMP_INFO *info);
-static int  adapter_test(SLMP_INFO *info);
-static bool memory_test(SLMP_INFO *info);
-
-static void reset_adapter(SLMP_INFO *info);
-static void reset_port(SLMP_INFO *info);
-static void async_mode(SLMP_INFO *info);
-static void hdlc_mode(SLMP_INFO *info);
-
-static void rx_stop(SLMP_INFO *info);
-static void rx_start(SLMP_INFO *info);
-static void rx_reset_buffers(SLMP_INFO *info);
-static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last);
-static bool rx_get_frame(SLMP_INFO *info);
-
-static void tx_start(SLMP_INFO *info);
-static void tx_stop(SLMP_INFO *info);
-static void tx_load_fifo(SLMP_INFO *info);
-static void tx_set_idle(SLMP_INFO *info);
-static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count);
-
-static void get_signals(SLMP_INFO *info);
-static void set_signals(SLMP_INFO *info);
-static void enable_loopback(SLMP_INFO *info, int enable);
-static void set_rate(SLMP_INFO *info, u32 data_rate);
-
-static int  bh_action(SLMP_INFO *info);
-static void bh_handler(struct work_struct *work);
-static void bh_receive(SLMP_INFO *info);
-static void bh_transmit(SLMP_INFO *info);
-static void bh_status(SLMP_INFO *info);
-static void isr_timer(SLMP_INFO *info);
-static void isr_rxint(SLMP_INFO *info);
-static void isr_rxrdy(SLMP_INFO *info);
-static void isr_txint(SLMP_INFO *info);
-static void isr_txrdy(SLMP_INFO *info);
-static void isr_rxdmaok(SLMP_INFO *info);
-static void isr_rxdmaerror(SLMP_INFO *info);
-static void isr_txdmaok(SLMP_INFO *info);
-static void isr_txdmaerror(SLMP_INFO *info);
-static void isr_io_pin(SLMP_INFO *info, u16 status);
-
-static int  alloc_dma_bufs(SLMP_INFO *info);
-static void free_dma_bufs(SLMP_INFO *info);
-static int  alloc_buf_list(SLMP_INFO *info);
-static int  alloc_frame_bufs(SLMP_INFO *info, SCADESC *list, SCADESC_EX *list_ex,int count);
-static int  alloc_tmp_rx_buf(SLMP_INFO *info);
-static void free_tmp_rx_buf(SLMP_INFO *info);
-
-static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count);
-static void trace_block(SLMP_INFO *info, const char* data, int count, int xmit);
-static void tx_timeout(unsigned long context);
-static void status_timeout(unsigned long context);
-
-static unsigned char read_reg(SLMP_INFO *info, unsigned char addr);
-static void write_reg(SLMP_INFO *info, unsigned char addr, unsigned char val);
-static u16 read_reg16(SLMP_INFO *info, unsigned char addr);
-static void write_reg16(SLMP_INFO *info, unsigned char addr, u16 val);
-static unsigned char read_status_reg(SLMP_INFO * info);
-static void write_control_reg(SLMP_INFO * info);
-
-
-static unsigned char rx_active_fifo_level = 16;	// rx request FIFO activation level in bytes
-static unsigned char tx_active_fifo_level = 16;	// tx request FIFO activation level in bytes
-static unsigned char tx_negate_fifo_level = 32;	// tx request FIFO negation level in bytes
-
-static u32 misc_ctrl_value = 0x007e4040;
-static u32 lcr1_brdr_value = 0x00800028;
-
-static u32 read_ahead_count = 8;
-
-/* DPCR, DMA Priority Control
- *
- * 07..05  Not used, must be 0
- * 04      BRC, bus release condition: 0=all transfers complete
- *              1=release after 1 xfer on all channels
- * 03      CCC, channel change condition: 0=every cycle
- *              1=after each channel completes all xfers
- * 02..00  PR<2..0>, priority 100=round robin
- *
- * 00000100 = 0x00
- */
-static unsigned char dma_priority = 0x04;
-
-// Number of bytes that can be written to shared RAM
-// in a single write operation
-static u32 sca_pci_load_interval = 64;
-
-/*
- * 1st function defined in .text section. Calling this function in
- * init_module() followed by a breakpoint allows a remote debugger
- * (gdb) to get the .text address for the add-symbol-file command.
- * This allows remote debugging of dynamically loadable modules.
- */
-static void* synclinkmp_get_text_ptr(void);
-static void* synclinkmp_get_text_ptr(void) {return synclinkmp_get_text_ptr;}
-
-static inline int sanity_check(SLMP_INFO *info,
-			       char *name, const char *routine)
-{
-#ifdef SANITY_CHECK
-	static const char *badmagic =
-		"Warning: bad magic number for synclinkmp_struct (%s) in %s\n";
-	static const char *badinfo =
-		"Warning: null synclinkmp_struct for (%s) in %s\n";
-
-	if (!info) {
-		printk(badinfo, name, routine);
-		return 1;
-	}
-	if (info->magic != MGSL_MAGIC) {
-		printk(badmagic, name, routine);
-		return 1;
-	}
-#else
-	if (!info)
-		return 1;
-#endif
-	return 0;
-}
-
-/**
- * line discipline callback wrappers
- *
- * The wrappers maintain line discipline references
- * while calling into the line discipline.
- *
- * ldisc_receive_buf  - pass receive data to line discipline
- */
-
-static void ldisc_receive_buf(struct tty_struct *tty,
-			      const __u8 *data, char *flags, int count)
-{
-	struct tty_ldisc *ld;
-	if (!tty)
-		return;
-	ld = tty_ldisc_ref(tty);
-	if (ld) {
-		if (ld->ops->receive_buf)
-			ld->ops->receive_buf(tty, data, flags, count);
-		tty_ldisc_deref(ld);
-	}
-}
-
-/* tty callbacks */
-
-/* Called when a port is opened.  Init and enable port.
- */
-static int open(struct tty_struct *tty, struct file *filp)
-{
-	SLMP_INFO *info;
-	int retval, line;
-	unsigned long flags;
-
-	line = tty->index;
-	if ((line < 0) || (line >= synclinkmp_device_count)) {
-		printk("%s(%d): open with invalid line #%d.\n",
-			__FILE__,__LINE__,line);
-		return -ENODEV;
-	}
-
-	info = synclinkmp_device_list;
-	while(info && info->line != line)
-		info = info->next_device;
-	if (sanity_check(info, tty->name, "open"))
-		return -ENODEV;
-	if ( info->init_error ) {
-		printk("%s(%d):%s device is not allocated, init error=%d\n",
-			__FILE__,__LINE__,info->device_name,info->init_error);
-		return -ENODEV;
-	}
-
-	tty->driver_data = info;
-	info->port.tty = tty;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s open(), old ref count = %d\n",
-			 __FILE__,__LINE__,tty->driver->name, info->port.count);
-
-	/* If port is closing, signal caller to try again */
-	if (tty_hung_up_p(filp) || info->port.flags & ASYNC_CLOSING){
-		if (info->port.flags & ASYNC_CLOSING)
-			interruptible_sleep_on(&info->port.close_wait);
-		retval = ((info->port.flags & ASYNC_HUP_NOTIFY) ?
-			-EAGAIN : -ERESTARTSYS);
-		goto cleanup;
-	}
-
-	info->port.tty->low_latency = (info->port.flags & ASYNC_LOW_LATENCY) ? 1 : 0;
-
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->netcount) {
-		retval = -EBUSY;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		goto cleanup;
-	}
-	info->port.count++;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	if (info->port.count == 1) {
-		/* 1st open on this device, init hardware */
-		retval = startup(info);
-		if (retval < 0)
-			goto cleanup;
-	}
-
-	retval = block_til_ready(tty, filp, info);
-	if (retval) {
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):%s block_til_ready() returned %d\n",
-				 __FILE__,__LINE__, info->device_name, retval);
-		goto cleanup;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s open() success\n",
-			 __FILE__,__LINE__, info->device_name);
-	retval = 0;
-
-cleanup:
-	if (retval) {
-		if (tty->count == 1)
-			info->port.tty = NULL; /* tty layer will release tty struct */
-		if(info->port.count)
-			info->port.count--;
-	}
-
-	return retval;
-}
-
-/* Called when port is closed. Wait for remaining data to be
- * sent. Disable port and free resources.
- */
-static void close(struct tty_struct *tty, struct file *filp)
-{
-	SLMP_INFO * info = tty->driver_data;
-
-	if (sanity_check(info, tty->name, "close"))
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s close() entry, count=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->port.count);
-
-	if (tty_port_close_start(&info->port, tty, filp) == 0)
-		goto cleanup;
-
-	mutex_lock(&info->port.mutex);
- 	if (info->port.flags & ASYNC_INITIALIZED)
- 		wait_until_sent(tty, info->timeout);
-
-	flush_buffer(tty);
-	tty_ldisc_flush(tty);
-	shutdown(info);
-	mutex_unlock(&info->port.mutex);
-
-	tty_port_close_end(&info->port, tty);
-	info->port.tty = NULL;
-cleanup:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s close() exit, count=%d\n", __FILE__,__LINE__,
-			tty->driver->name, info->port.count);
-}
-
-/* Called by tty_hangup() when a hangup is signaled.
- * This is the same as closing all open descriptors for the port.
- */
-static void hangup(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s hangup()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "hangup"))
-		return;
-
-	mutex_lock(&info->port.mutex);
-	flush_buffer(tty);
-	shutdown(info);
-
-	spin_lock_irqsave(&info->port.lock, flags);
-	info->port.count = 0;
-	info->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-	info->port.tty = NULL;
-	spin_unlock_irqrestore(&info->port.lock, flags);
-	mutex_unlock(&info->port.mutex);
-
-	wake_up_interruptible(&info->port.open_wait);
-}
-
-/* Set new termios settings
- */
-static void set_termios(struct tty_struct *tty, struct ktermios *old_termios)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_termios()\n", __FILE__,__LINE__,
-			tty->driver->name );
-
-	change_params(info);
-
-	/* Handle transition to B0 status */
-	if (old_termios->c_cflag & CBAUD &&
-	    !(tty->termios->c_cflag & CBAUD)) {
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-		spin_lock_irqsave(&info->lock,flags);
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle transition away from B0 status */
-	if (!(old_termios->c_cflag & CBAUD) &&
-	    tty->termios->c_cflag & CBAUD) {
-		info->serial_signals |= SerialSignal_DTR;
- 		if (!(tty->termios->c_cflag & CRTSCTS) ||
- 		    !test_bit(TTY_THROTTLED, &tty->flags)) {
-			info->serial_signals |= SerialSignal_RTS;
- 		}
-		spin_lock_irqsave(&info->lock,flags);
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-
-	/* Handle turning off CRTSCTS */
-	if (old_termios->c_cflag & CRTSCTS &&
-	    !(tty->termios->c_cflag & CRTSCTS)) {
-		tty->hw_stopped = 0;
-		tx_release(tty);
-	}
-}
-
-/* Send a block of data
- *
- * Arguments:
- *
- * 	tty		pointer to tty information structure
- * 	buf		pointer to buffer containing send data
- * 	count		size of send data in bytes
- *
- * Return Value:	number of characters written
- */
-static int write(struct tty_struct *tty,
-		 const unsigned char *buf, int count)
-{
-	int	c, ret = 0;
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s write() count=%d\n",
-		       __FILE__,__LINE__,info->device_name,count);
-
-	if (sanity_check(info, tty->name, "write"))
-		goto cleanup;
-
-	if (!info->tx_buf)
-		goto cleanup;
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		if (count > info->max_frame_size) {
-			ret = -EIO;
-			goto cleanup;
-		}
-		if (info->tx_active)
-			goto cleanup;
-		if (info->tx_count) {
-			/* send accumulated data from send_char() calls */
-			/* as frame and wait before accepting more data. */
-			tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
-			goto start;
-		}
-		ret = info->tx_count = count;
-		tx_load_dma_buffer(info, buf, count);
-		goto start;
-	}
-
-	for (;;) {
-		c = min_t(int, count,
-			min(info->max_frame_size - info->tx_count - 1,
-			    info->max_frame_size - info->tx_put));
-		if (c <= 0)
-			break;
-			
-		memcpy(info->tx_buf + info->tx_put, buf, c);
-
-		spin_lock_irqsave(&info->lock,flags);
-		info->tx_put += c;
-		if (info->tx_put >= info->max_frame_size)
-			info->tx_put -= info->max_frame_size;
-		info->tx_count += c;
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		buf += c;
-		count -= c;
-		ret += c;
-	}
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		if (count) {
-			ret = info->tx_count = 0;
-			goto cleanup;
-		}
-		tx_load_dma_buffer(info, info->tx_buf, info->tx_count);
-	}
-start:
- 	if (info->tx_count && !tty->stopped && !tty->hw_stopped) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_active)
-		 	tx_start(info);
-		spin_unlock_irqrestore(&info->lock,flags);
- 	}
-
-cleanup:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk( "%s(%d):%s write() returning=%d\n",
-			__FILE__,__LINE__,info->device_name,ret);
-	return ret;
-}
-
-/* Add a character to the transmit buffer.
- */
-static int put_char(struct tty_struct *tty, unsigned char ch)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-	int ret = 0;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO ) {
-		printk( "%s(%d):%s put_char(%d)\n",
-			__FILE__,__LINE__,info->device_name,ch);
-	}
-
-	if (sanity_check(info, tty->name, "put_char"))
-		return 0;
-
-	if (!info->tx_buf)
-		return 0;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if ( (info->params.mode != MGSL_MODE_HDLC) ||
-	     !info->tx_active ) {
-
-		if (info->tx_count < info->max_frame_size - 1) {
-			info->tx_buf[info->tx_put++] = ch;
-			if (info->tx_put >= info->max_frame_size)
-				info->tx_put -= info->max_frame_size;
-			info->tx_count++;
-			ret = 1;
-		}
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-	return ret;
-}
-
-/* Send a high-priority XON/XOFF character
- */
-static void send_xchar(struct tty_struct *tty, char ch)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s send_xchar(%d)\n",
-			 __FILE__,__LINE__, info->device_name, ch );
-
-	if (sanity_check(info, tty->name, "send_xchar"))
-		return;
-
-	info->x_char = ch;
-	if (ch) {
-		/* Make sure transmit interrupts are on */
-		spin_lock_irqsave(&info->lock,flags);
-		if (!info->tx_enabled)
-		 	tx_start(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/* Wait until the transmitter is empty.
- */
-static void wait_until_sent(struct tty_struct *tty, int timeout)
-{
-	SLMP_INFO * info = tty->driver_data;
-	unsigned long orig_jiffies, char_time;
-
-	if (!info )
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s wait_until_sent() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "wait_until_sent"))
-		return;
-
-	if (!test_bit(ASYNCB_INITIALIZED, &info->port.flags))
-		goto exit;
-
-	orig_jiffies = jiffies;
-
-	/* Set check interval to 1/5 of estimated time to
-	 * send a character, and make it at least 1. The check
-	 * interval should also be less than the timeout.
-	 * Note: use tight timings here to satisfy the NIST-PCTS.
-	 */
-
-	if ( info->params.data_rate ) {
-	       	char_time = info->timeout/(32 * 5);
-		if (!char_time)
-			char_time++;
-	} else
-		char_time = 1;
-
-	if (timeout)
-		char_time = min_t(unsigned long, char_time, timeout);
-
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
-		while (info->tx_active) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	} else {
-		/*
-		 * TODO: determine if there is something similar to USC16C32
-		 * 	 TXSTATUS_ALL_SENT status
-		 */
-		while ( info->tx_active && info->tx_enabled) {
-			msleep_interruptible(jiffies_to_msecs(char_time));
-			if (signal_pending(current))
-				break;
-			if (timeout && time_after(jiffies, orig_jiffies + timeout))
-				break;
-		}
-	}
-
-exit:
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s wait_until_sent() exit\n",
-			 __FILE__,__LINE__, info->device_name );
-}
-
-/* Return the count of free bytes in transmit buffer
- */
-static int write_room(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	int ret;
-
-	if (sanity_check(info, tty->name, "write_room"))
-		return 0;
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
-	} else {
-		ret = info->max_frame_size - info->tx_count - 1;
-		if (ret < 0)
-			ret = 0;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s write_room()=%d\n",
-		       __FILE__, __LINE__, info->device_name, ret);
-
-	return ret;
-}
-
-/* enable transmitter and send remaining buffered characters
- */
-static void flush_chars(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s flush_chars() entry tx_count=%d\n",
-			__FILE__,__LINE__,info->device_name,info->tx_count);
-
-	if (sanity_check(info, tty->name, "flush_chars"))
-		return;
-
-	if (info->tx_count <= 0 || tty->stopped || tty->hw_stopped ||
-	    !info->tx_buf)
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s flush_chars() entry, starting transmitter\n",
-			__FILE__,__LINE__,info->device_name );
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if (!info->tx_active) {
-		if ( (info->params.mode == MGSL_MODE_HDLC) &&
-			info->tx_count ) {
-			/* operating in synchronous (frame oriented) mode */
-			/* copy data from circular tx_buf to */
-			/* transmit DMA buffer. */
-			tx_load_dma_buffer(info,
-				 info->tx_buf,info->tx_count);
-		}
-	 	tx_start(info);
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Discard all data in the send buffer
- */
-static void flush_buffer(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s flush_buffer() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "flush_buffer"))
-		return;
-
-	spin_lock_irqsave(&info->lock,flags);
-	info->tx_count = info->tx_put = info->tx_get = 0;
-	del_timer(&info->tx_timer);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	tty_wakeup(tty);
-}
-
-/* throttle (stop) transmitter
- */
-static void tx_hold(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_hold"))
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s tx_hold()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (info->tx_enabled)
-	 	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* release (start) transmitter
- */
-static void tx_release(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (sanity_check(info, tty->name, "tx_release"))
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s tx_release()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if (!info->tx_enabled)
-	 	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Service an IOCTL request
- *
- * Arguments:
- *
- * 	tty	pointer to tty instance data
- * 	file	pointer to associated file object for device
- * 	cmd	IOCTL command code
- * 	arg	command argument/context
- *
- * Return Value:	0 if success, otherwise error code
- */
-static int ioctl(struct tty_struct *tty, struct file *file,
-		 unsigned int cmd, unsigned long arg)
-{
-	SLMP_INFO *info = tty->driver_data;
-	void __user *argp = (void __user *)arg;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s ioctl() cmd=%08X\n", __FILE__,__LINE__,
-			info->device_name, cmd );
-
-	if (sanity_check(info, tty->name, "ioctl"))
-		return -ENODEV;
-
-	if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
-	    (cmd != TIOCMIWAIT)) {
-		if (tty->flags & (1 << TTY_IO_ERROR))
-		    return -EIO;
-	}
-
-	switch (cmd) {
-	case MGSL_IOCGPARAMS:
-		return get_params(info, argp);
-	case MGSL_IOCSPARAMS:
-		return set_params(info, argp);
-	case MGSL_IOCGTXIDLE:
-		return get_txidle(info, argp);
-	case MGSL_IOCSTXIDLE:
-		return set_txidle(info, (int)arg);
-	case MGSL_IOCTXENABLE:
-		return tx_enable(info, (int)arg);
-	case MGSL_IOCRXENABLE:
-		return rx_enable(info, (int)arg);
-	case MGSL_IOCTXABORT:
-		return tx_abort(info);
-	case MGSL_IOCGSTATS:
-		return get_stats(info, argp);
-	case MGSL_IOCWAITEVENT:
-		return wait_mgsl_event(info, argp);
-	case MGSL_IOCLOOPTXDONE:
-		return 0; // TODO: Not supported, need to document
-		/* Wait for modem input (DCD,RI,DSR,CTS) change
-		 * as specified by mask in arg (TIOCM_RNG/DSR/CD/CTS)
-		 */
-	case TIOCMIWAIT:
-		return modem_input_wait(info,(int)arg);
-		
-		/*
-		 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
-		 * Return: write counters to the user passed counter struct
-		 * NB: both 1->0 and 0->1 transitions are counted except for
-		 *     RI where only 0->1 is counted.
-		 */
-	default:
-		return -ENOIOCTLCMD;
-	}
-	return 0;
-}
-
-static int get_icount(struct tty_struct *tty,
-				struct serial_icounter_struct *icount)
-{
-	SLMP_INFO *info = tty->driver_data;
-	struct mgsl_icount cnow;	/* kernel counter temps */
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	cnow = info->icount;
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	icount->cts = cnow.cts;
-	icount->dsr = cnow.dsr;
-	icount->rng = cnow.rng;
-	icount->dcd = cnow.dcd;
-	icount->rx = cnow.rx;
-	icount->tx = cnow.tx;
-	icount->frame = cnow.frame;
-	icount->overrun = cnow.overrun;
-	icount->parity = cnow.parity;
-	icount->brk = cnow.brk;
-	icount->buf_overrun = cnow.buf_overrun;
-
-	return 0;
-}
-
-/*
- * /proc fs routines....
- */
-
-static inline void line_info(struct seq_file *m, SLMP_INFO *info)
-{
-	char	stat_buf[30];
-	unsigned long flags;
-
-	seq_printf(m, "%s: SCABase=%08x Mem=%08X StatusControl=%08x LCR=%08X\n"
-		       "\tIRQ=%d MaxFrameSize=%u\n",
-		info->device_name,
-		info->phys_sca_base,
-		info->phys_memory_base,
-		info->phys_statctrl_base,
-		info->phys_lcr_base,
-		info->irq_level,
-		info->max_frame_size );
-
-	/* output current serial signal states */
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	stat_buf[0] = 0;
-	stat_buf[1] = 0;
-	if (info->serial_signals & SerialSignal_RTS)
-		strcat(stat_buf, "|RTS");
-	if (info->serial_signals & SerialSignal_CTS)
-		strcat(stat_buf, "|CTS");
-	if (info->serial_signals & SerialSignal_DTR)
-		strcat(stat_buf, "|DTR");
-	if (info->serial_signals & SerialSignal_DSR)
-		strcat(stat_buf, "|DSR");
-	if (info->serial_signals & SerialSignal_DCD)
-		strcat(stat_buf, "|CD");
-	if (info->serial_signals & SerialSignal_RI)
-		strcat(stat_buf, "|RI");
-
-	if (info->params.mode == MGSL_MODE_HDLC) {
-		seq_printf(m, "\tHDLC txok:%d rxok:%d",
-			      info->icount.txok, info->icount.rxok);
-		if (info->icount.txunder)
-			seq_printf(m, " txunder:%d", info->icount.txunder);
-		if (info->icount.txabort)
-			seq_printf(m, " txabort:%d", info->icount.txabort);
-		if (info->icount.rxshort)
-			seq_printf(m, " rxshort:%d", info->icount.rxshort);
-		if (info->icount.rxlong)
-			seq_printf(m, " rxlong:%d", info->icount.rxlong);
-		if (info->icount.rxover)
-			seq_printf(m, " rxover:%d", info->icount.rxover);
-		if (info->icount.rxcrc)
-			seq_printf(m, " rxlong:%d", info->icount.rxcrc);
-	} else {
-		seq_printf(m, "\tASYNC tx:%d rx:%d",
-			      info->icount.tx, info->icount.rx);
-		if (info->icount.frame)
-			seq_printf(m, " fe:%d", info->icount.frame);
-		if (info->icount.parity)
-			seq_printf(m, " pe:%d", info->icount.parity);
-		if (info->icount.brk)
-			seq_printf(m, " brk:%d", info->icount.brk);
-		if (info->icount.overrun)
-			seq_printf(m, " oe:%d", info->icount.overrun);
-	}
-
-	/* Append serial signal status to end */
-	seq_printf(m, " %s\n", stat_buf+1);
-
-	seq_printf(m, "\ttxactive=%d bh_req=%d bh_run=%d pending_bh=%x\n",
-	 info->tx_active,info->bh_requested,info->bh_running,
-	 info->pending_bh);
-}
-
-/* Called to print information about devices
- */
-static int synclinkmp_proc_show(struct seq_file *m, void *v)
-{
-	SLMP_INFO *info;
-
-	seq_printf(m, "synclinkmp driver:%s\n", driver_version);
-
-	info = synclinkmp_device_list;
-	while( info ) {
-		line_info(m, info);
-		info = info->next_device;
-	}
-	return 0;
-}
-
-static int synclinkmp_proc_open(struct inode *inode, struct file *file)
-{
-	return single_open(file, synclinkmp_proc_show, NULL);
-}
-
-static const struct file_operations synclinkmp_proc_fops = {
-	.owner		= THIS_MODULE,
-	.open		= synclinkmp_proc_open,
-	.read		= seq_read,
-	.llseek		= seq_lseek,
-	.release	= single_release,
-};
-
-/* Return the count of bytes in transmit buffer
- */
-static int chars_in_buffer(struct tty_struct *tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-
-	if (sanity_check(info, tty->name, "chars_in_buffer"))
-		return 0;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s chars_in_buffer()=%d\n",
-		       __FILE__, __LINE__, info->device_name, info->tx_count);
-
-	return info->tx_count;
-}
-
-/* Signal remote device to throttle send data (our receive data)
- */
-static void throttle(struct tty_struct * tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s throttle() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "throttle"))
-		return;
-
-	if (I_IXOFF(tty))
-		send_xchar(tty, STOP_CHAR(tty));
-
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->serial_signals &= ~SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/* Signal remote device to stop throttling send data (our receive data)
- */
-static void unthrottle(struct tty_struct * tty)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s unthrottle() entry\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	if (sanity_check(info, tty->name, "unthrottle"))
-		return;
-
-	if (I_IXOFF(tty)) {
-		if (info->x_char)
-			info->x_char = 0;
-		else
-			send_xchar(tty, START_CHAR(tty));
-	}
-
- 	if (tty->termios->c_cflag & CRTSCTS) {
-		spin_lock_irqsave(&info->lock,flags);
-		info->serial_signals |= SerialSignal_RTS;
-	 	set_signals(info);
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-}
-
-/* set or clear transmit break condition
- * break_state	-1=set break condition, 0=clear
- */
-static int set_break(struct tty_struct *tty, int break_state)
-{
-	unsigned char RegValue;
-	SLMP_INFO * info = tty->driver_data;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_break(%d)\n",
-			 __FILE__,__LINE__, info->device_name, break_state);
-
-	if (sanity_check(info, tty->name, "set_break"))
-		return -EINVAL;
-
-	spin_lock_irqsave(&info->lock,flags);
-	RegValue = read_reg(info, CTL);
- 	if (break_state == -1)
-		RegValue |= BIT3;
-	else
-		RegValue &= ~BIT3;
-	write_reg(info, CTL, RegValue);
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-#if SYNCLINK_GENERIC_HDLC
-
-/**
- * called by generic HDLC layer when protocol selected (PPP, frame relay, etc.)
- * set encoding and frame check sequence (FCS) options
- *
- * dev       pointer to network device structure
- * encoding  serial encoding setting
- * parity    FCS setting
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_attach(struct net_device *dev, unsigned short encoding,
-			  unsigned short parity)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned char  new_encoding;
-	unsigned short new_crctype;
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	switch (encoding)
-	{
-	case ENCODING_NRZ:        new_encoding = HDLC_ENCODING_NRZ; break;
-	case ENCODING_NRZI:       new_encoding = HDLC_ENCODING_NRZI_SPACE; break;
-	case ENCODING_FM_MARK:    new_encoding = HDLC_ENCODING_BIPHASE_MARK; break;
-	case ENCODING_FM_SPACE:   new_encoding = HDLC_ENCODING_BIPHASE_SPACE; break;
-	case ENCODING_MANCHESTER: new_encoding = HDLC_ENCODING_BIPHASE_LEVEL; break;
-	default: return -EINVAL;
-	}
-
-	switch (parity)
-	{
-	case PARITY_NONE:            new_crctype = HDLC_CRC_NONE; break;
-	case PARITY_CRC16_PR1_CCITT: new_crctype = HDLC_CRC_16_CCITT; break;
-	case PARITY_CRC32_PR1_CCITT: new_crctype = HDLC_CRC_32_CCITT; break;
-	default: return -EINVAL;
-	}
-
-	info->params.encoding = new_encoding;
-	info->params.crc_type = new_crctype;
-
-	/* if network interface up, reprogram hardware */
-	if (info->netcount)
-		program_hw(info);
-
-	return 0;
-}
-
-/**
- * called by generic HDLC layer to send frame
- *
- * skb  socket buffer containing HDLC frame
- * dev  pointer to network device structure
- */
-static netdev_tx_t hdlcdev_xmit(struct sk_buff *skb,
-				      struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk(KERN_INFO "%s:hdlc_xmit(%s)\n",__FILE__,dev->name);
-
-	/* stop sending until this frame completes */
-	netif_stop_queue(dev);
-
-	/* copy data to device buffers */
-	info->tx_count = skb->len;
-	tx_load_dma_buffer(info, skb->data, skb->len);
-
-	/* update network statistics */
-	dev->stats.tx_packets++;
-	dev->stats.tx_bytes += skb->len;
-
-	/* done with socket buffer, so free it */
-	dev_kfree_skb(skb);
-
-	/* 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);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return NETDEV_TX_OK;
-}
-
-/**
- * called by network layer when interface enabled
- * claim resources and initialize hardware
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_open(struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	int rc;
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_open(%s)\n",__FILE__,dev->name);
-
-	/* generic HDLC layer open processing */
-	if ((rc = hdlc_open(dev)))
-		return rc;
-
-	/* arbitrate between network and tty opens */
-	spin_lock_irqsave(&info->netlock, flags);
-	if (info->port.count != 0 || info->netcount != 0) {
-		printk(KERN_WARNING "%s: hdlc_open returning busy\n", dev->name);
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return -EBUSY;
-	}
-	info->netcount=1;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	/* claim resources and init adapter */
-	if ((rc = startup(info)) != 0) {
-		spin_lock_irqsave(&info->netlock, flags);
-		info->netcount=0;
-		spin_unlock_irqrestore(&info->netlock, flags);
-		return rc;
-	}
-
-	/* assert DTR and RTS, apply hardware settings */
-	info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	program_hw(info);
-
-	/* enable network layer transmit */
-	dev->trans_start = jiffies;
-	netif_start_queue(dev);
-
-	/* inform generic HDLC layer of current DCD status */
-	spin_lock_irqsave(&info->lock, flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock, flags);
-	if (info->serial_signals & SerialSignal_DCD)
-		netif_carrier_on(dev);
-	else
-		netif_carrier_off(dev);
-	return 0;
-}
-
-/**
- * called by network layer when interface is disabled
- * shutdown hardware and release resources
- *
- * dev  pointer to network device structure
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_close(struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_close(%s)\n",__FILE__,dev->name);
-
-	netif_stop_queue(dev);
-
-	/* shutdown adapter and release resources */
-	shutdown(info);
-
-	hdlc_close(dev);
-
-	spin_lock_irqsave(&info->netlock, flags);
-	info->netcount=0;
-	spin_unlock_irqrestore(&info->netlock, flags);
-
-	return 0;
-}
-
-/**
- * called by network layer to process IOCTL call to network device
- *
- * dev  pointer to network device structure
- * ifr  pointer to network interface request structure
- * cmd  IOCTL command code
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
-{
-	const size_t size = sizeof(sync_serial_settings);
-	sync_serial_settings new_line;
-	sync_serial_settings __user *line = ifr->ifr_settings.ifs_ifsu.sync;
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned int flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s:hdlcdev_ioctl(%s)\n",__FILE__,dev->name);
-
-	/* return error if TTY interface open */
-	if (info->port.count)
-		return -EBUSY;
-
-	if (cmd != SIOCWANDEV)
-		return hdlc_ioctl(dev, ifr, cmd);
-
-	switch(ifr->ifr_settings.type) {
-	case IF_GET_IFACE: /* return current sync_serial_settings */
-
-		ifr->ifr_settings.type = IF_IFACE_SYNC_SERIAL;
-		if (ifr->ifr_settings.size < size) {
-			ifr->ifr_settings.size = size; /* data size wanted */
-			return -ENOBUFS;
-		}
-
-		flags = info->params.flags & (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-
-		switch (flags){
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN): new_line.clock_type = CLOCK_EXT; break;
-		case (HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_INT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG):    new_line.clock_type = CLOCK_TXINT; break;
-		case (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN): new_line.clock_type = CLOCK_TXFROMRX; break;
-		default: new_line.clock_type = CLOCK_DEFAULT;
-		}
-
-		new_line.clock_rate = info->params.clock_speed;
-		new_line.loopback   = info->params.loopback ? 1:0;
-
-		if (copy_to_user(line, &new_line, size))
-			return -EFAULT;
-		return 0;
-
-	case IF_IFACE_SYNC_SERIAL: /* set sync_serial_settings */
-
-		if(!capable(CAP_NET_ADMIN))
-			return -EPERM;
-		if (copy_from_user(&new_line, line, size))
-			return -EFAULT;
-
-		switch (new_line.clock_type)
-		{
-		case CLOCK_EXT:      flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_TXCPIN; break;
-		case CLOCK_TXFROMRX: flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_RXCPIN; break;
-		case CLOCK_INT:      flags = HDLC_FLAG_RXC_BRG    | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_TXINT:    flags = HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_TXC_BRG;    break;
-		case CLOCK_DEFAULT:  flags = info->params.flags &
-					     (HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					      HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					      HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					      HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN); break;
-		default: return -EINVAL;
-		}
-
-		if (new_line.loopback != 0 && new_line.loopback != 1)
-			return -EINVAL;
-
-		info->params.flags &= ~(HDLC_FLAG_RXC_RXCPIN | HDLC_FLAG_RXC_DPLL |
-					HDLC_FLAG_RXC_BRG    | HDLC_FLAG_RXC_TXCPIN |
-					HDLC_FLAG_TXC_TXCPIN | HDLC_FLAG_TXC_DPLL |
-					HDLC_FLAG_TXC_BRG    | HDLC_FLAG_TXC_RXCPIN);
-		info->params.flags |= flags;
-
-		info->params.loopback = new_line.loopback;
-
-		if (flags & (HDLC_FLAG_RXC_BRG | HDLC_FLAG_TXC_BRG))
-			info->params.clock_speed = new_line.clock_rate;
-		else
-			info->params.clock_speed = 0;
-
-		/* if network interface up, reprogram hardware */
-		if (info->netcount)
-			program_hw(info);
-		return 0;
-
-	default:
-		return hdlc_ioctl(dev, ifr, cmd);
-	}
-}
-
-/**
- * called by network layer when transmit timeout is detected
- *
- * dev  pointer to network device structure
- */
-static void hdlcdev_tx_timeout(struct net_device *dev)
-{
-	SLMP_INFO *info = dev_to_port(dev);
-	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_tx_timeout(%s)\n",dev->name);
-
-	dev->stats.tx_errors++;
-	dev->stats.tx_aborted_errors++;
-
-	spin_lock_irqsave(&info->lock,flags);
-	tx_stop(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	netif_wake_queue(dev);
-}
-
-/**
- * called by device driver when transmit completes
- * reenable network layer transmit if stopped
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_tx_done(SLMP_INFO *info)
-{
-	if (netif_queue_stopped(info->netdev))
-		netif_wake_queue(info->netdev);
-}
-
-/**
- * called by device driver when frame received
- * pass frame to network layer
- *
- * info  pointer to device instance information
- * buf   pointer to buffer contianing frame data
- * size  count of data bytes in buf
- */
-static void hdlcdev_rx(SLMP_INFO *info, char *buf, int size)
-{
-	struct sk_buff *skb = dev_alloc_skb(size);
-	struct net_device *dev = info->netdev;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("hdlcdev_rx(%s)\n",dev->name);
-
-	if (skb == NULL) {
-		printk(KERN_NOTICE "%s: can't alloc skb, dropping packet\n",
-		       dev->name);
-		dev->stats.rx_dropped++;
-		return;
-	}
-
-	memcpy(skb_put(skb, size), buf, size);
-
-	skb->protocol = hdlc_type_trans(skb, dev);
-
-	dev->stats.rx_packets++;
-	dev->stats.rx_bytes += size;
-
-	netif_rx(skb);
-}
-
-static const struct net_device_ops hdlcdev_ops = {
-	.ndo_open       = hdlcdev_open,
-	.ndo_stop       = hdlcdev_close,
-	.ndo_change_mtu = hdlc_change_mtu,
-	.ndo_start_xmit = hdlc_start_xmit,
-	.ndo_do_ioctl   = hdlcdev_ioctl,
-	.ndo_tx_timeout = hdlcdev_tx_timeout,
-};
-
-/**
- * called by device driver when adding device instance
- * do generic HDLC initialization
- *
- * info  pointer to device instance information
- *
- * returns 0 if success, otherwise error code
- */
-static int hdlcdev_init(SLMP_INFO *info)
-{
-	int rc;
-	struct net_device *dev;
-	hdlc_device *hdlc;
-
-	/* allocate and initialize network and HDLC layer objects */
-
-	if (!(dev = alloc_hdlcdev(info))) {
-		printk(KERN_ERR "%s:hdlc device allocation failure\n",__FILE__);
-		return -ENOMEM;
-	}
-
-	/* for network layer reporting purposes only */
-	dev->mem_start = info->phys_sca_base;
-	dev->mem_end   = info->phys_sca_base + SCA_BASE_SIZE - 1;
-	dev->irq       = info->irq_level;
-
-	/* network layer callbacks and settings */
-	dev->netdev_ops	    = &hdlcdev_ops;
-	dev->watchdog_timeo = 10 * HZ;
-	dev->tx_queue_len   = 50;
-
-	/* generic HDLC layer callbacks and settings */
-	hdlc         = dev_to_hdlc(dev);
-	hdlc->attach = hdlcdev_attach;
-	hdlc->xmit   = hdlcdev_xmit;
-
-	/* register objects with HDLC layer */
-	if ((rc = register_hdlc_device(dev))) {
-		printk(KERN_WARNING "%s:unable to register hdlc device\n",__FILE__);
-		free_netdev(dev);
-		return rc;
-	}
-
-	info->netdev = dev;
-	return 0;
-}
-
-/**
- * called by device driver when removing device instance
- * do generic HDLC cleanup
- *
- * info  pointer to device instance information
- */
-static void hdlcdev_exit(SLMP_INFO *info)
-{
-	unregister_hdlc_device(info->netdev);
-	free_netdev(info->netdev);
-	info->netdev = NULL;
-}
-
-#endif /* CONFIG_HDLC */
-
-
-/* Return next bottom half action to perform.
- * Return Value:	BH action code or 0 if nothing to do.
- */
-static int bh_action(SLMP_INFO *info)
-{
-	unsigned long flags;
-	int rc = 0;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	if (info->pending_bh & BH_RECEIVE) {
-		info->pending_bh &= ~BH_RECEIVE;
-		rc = BH_RECEIVE;
-	} else if (info->pending_bh & BH_TRANSMIT) {
-		info->pending_bh &= ~BH_TRANSMIT;
-		rc = BH_TRANSMIT;
-	} else if (info->pending_bh & BH_STATUS) {
-		info->pending_bh &= ~BH_STATUS;
-		rc = BH_STATUS;
-	}
-
-	if (!rc) {
-		/* Mark BH routine as complete */
-		info->bh_running = false;
-		info->bh_requested = false;
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return rc;
-}
-
-/* Perform bottom half processing of work items queued by ISR.
- */
-static void bh_handler(struct work_struct *work)
-{
-	SLMP_INFO *info = container_of(work, SLMP_INFO, task);
-	int action;
-
-	if (!info)
-		return;
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_handler() entry\n",
-			__FILE__,__LINE__,info->device_name);
-
-	info->bh_running = true;
-
-	while((action = bh_action(info)) != 0) {
-
-		/* Process work item */
-		if ( debug_level >= DEBUG_LEVEL_BH )
-			printk( "%s(%d):%s bh_handler() work item action=%d\n",
-				__FILE__,__LINE__,info->device_name, action);
-
-		switch (action) {
-
-		case BH_RECEIVE:
-			bh_receive(info);
-			break;
-		case BH_TRANSMIT:
-			bh_transmit(info);
-			break;
-		case BH_STATUS:
-			bh_status(info);
-			break;
-		default:
-			/* unknown work item ID */
-			printk("%s(%d):%s Unknown work item ID=%08X!\n",
-				__FILE__,__LINE__,info->device_name,action);
-			break;
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_handler() exit\n",
-			__FILE__,__LINE__,info->device_name);
-}
-
-static void bh_receive(SLMP_INFO *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_receive()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	while( rx_get_frame(info) );
-}
-
-static void bh_transmit(SLMP_INFO *info)
-{
-	struct tty_struct *tty = info->port.tty;
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_transmit() entry\n",
-			__FILE__,__LINE__,info->device_name);
-
-	if (tty)
-		tty_wakeup(tty);
-}
-
-static void bh_status(SLMP_INFO *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk( "%s(%d):%s bh_status() entry\n",
-			__FILE__,__LINE__,info->device_name);
-
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-}
-
-static void isr_timer(SLMP_INFO * info)
-{
-	unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
-
-	/* IER2<7..4> = timer<3..0> interrupt enables (0=disabled) */
-	write_reg(info, IER2, 0);
-
-	/* TMCS, Timer Control/Status Register
-	 *
-	 * 07      CMF, Compare match flag (read only) 1=match
-	 * 06      ECMI, CMF Interrupt Enable: 0=disabled
-	 * 05      Reserved, must be 0
-	 * 04      TME, Timer Enable
-	 * 03..00  Reserved, must be 0
-	 *
-	 * 0000 0000
-	 */
-	write_reg(info, (unsigned char)(timer + TMCS), 0);
-
-	info->irq_occurred = true;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_timer()\n",
-			__FILE__,__LINE__,info->device_name);
-}
-
-static void isr_rxint(SLMP_INFO * info)
-{
- 	struct tty_struct *tty = info->port.tty;
- 	struct	mgsl_icount *icount = &info->icount;
-	unsigned char status = read_reg(info, SR1) & info->ie1_value & (FLGD + IDLD + CDCD + BRKD);
-	unsigned char status2 = read_reg(info, SR2) & info->ie2_value & OVRN;
-
-	/* clear status bits */
-	if (status)
-		write_reg(info, SR1, status);
-
-	if (status2)
-		write_reg(info, SR2, status2);
-	
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxint status=%02X %02x\n",
-			__FILE__,__LINE__,info->device_name,status,status2);
-
-	if (info->params.mode == MGSL_MODE_ASYNC) {
-		if (status & BRKD) {
-			icount->brk++;
-
-			/* process break detection if tty control
-			 * is not set to ignore it
-			 */
-			if ( tty ) {
-				if (!(status & info->ignore_status_mask1)) {
-					if (info->read_status_mask1 & BRKD) {
-						tty_insert_flip_char(tty, 0, TTY_BREAK);
-						if (info->port.flags & ASYNC_SAK)
-							do_SAK(tty);
-					}
-				}
-			}
-		}
-	}
-	else {
-		if (status & (FLGD|IDLD)) {
-			if (status & FLGD)
-				info->icount.exithunt++;
-			else if (status & IDLD)
-				info->icount.rxidle++;
-			wake_up_interruptible(&info->event_wait_q);
-		}
-	}
-
-	if (status & CDCD) {
-		/* simulate a common modem status change interrupt
-		 * for our handler
-		 */
-		get_signals( info );
-		isr_io_pin(info,
-			MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD));
-	}
-}
-
-/*
- * handle async rx data interrupts
- */
-static void isr_rxrdy(SLMP_INFO * info)
-{
-	u16 status;
-	unsigned char DataByte;
- 	struct tty_struct *tty = info->port.tty;
- 	struct	mgsl_icount *icount = &info->icount;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxrdy\n",
-			__FILE__,__LINE__,info->device_name);
-
-	while((status = read_reg(info,CST0)) & BIT0)
-	{
-		int flag = 0;
-		bool over = false;
-		DataByte = read_reg(info,TRB);
-
-		icount->rx++;
-
-		if ( status & (PE + FRME + OVRN) ) {
-			printk("%s(%d):%s rxerr=%04X\n",
-				__FILE__,__LINE__,info->device_name,status);
-
-			/* update error statistics */
-			if (status & PE)
-				icount->parity++;
-			else if (status & FRME)
-				icount->frame++;
-			else if (status & OVRN)
-				icount->overrun++;
-
-			/* discard char if tty control flags say so */
-			if (status & info->ignore_status_mask2)
-				continue;
-
-			status &= info->read_status_mask2;
-
-			if ( tty ) {
-				if (status & PE)
-					flag = TTY_PARITY;
-				else if (status & FRME)
-					flag = TTY_FRAME;
-				if (status & OVRN) {
-					/* Overrun is special, since it's
-					 * reported immediately, and doesn't
-					 * affect the current character
-					 */
-					over = true;
-				}
-			}
-		}	/* end of if (error) */
-
-		if ( tty ) {
-			tty_insert_flip_char(tty, DataByte, flag);
-			if (over)
-				tty_insert_flip_char(tty, 0, TTY_OVERRUN);
-		}
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_ISR ) {
-		printk("%s(%d):%s rx=%d brk=%d parity=%d frame=%d overrun=%d\n",
-			__FILE__,__LINE__,info->device_name,
-			icount->rx,icount->brk,icount->parity,
-			icount->frame,icount->overrun);
-	}
-
-	if ( tty )
-		tty_flip_buffer_push(tty);
-}
-
-static void isr_txeom(SLMP_INFO * info, unsigned char status)
-{
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txeom status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	write_reg(info, TXDMA + DIR, 0x00); /* disable Tx DMA IRQs */
-	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
-	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-	if (status & UDRN) {
-		write_reg(info, CMD, TXRESET);
-		write_reg(info, CMD, TXENABLE);
-	} else
-		write_reg(info, CMD, TXBUFCLR);
-
-	/* disable and clear tx interrupts */
-	info->ie0_value &= ~TXRDYE;
-	info->ie1_value &= ~(IDLE + UDRN);
-	write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
-	write_reg(info, SR1, (unsigned char)(UDRN + IDLE));
-
-	if ( info->tx_active ) {
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-			if (status & UDRN)
-				info->icount.txunder++;
-			else if (status & IDLE)
-				info->icount.txok++;
-		}
-
-		info->tx_active = false;
-		info->tx_count = info->tx_put = info->tx_get = 0;
-
-		del_timer(&info->tx_timer);
-
-		if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done ) {
-			info->serial_signals &= ~SerialSignal_RTS;
-			info->drop_rts_on_tx_done = false;
-			set_signals(info);
-		}
-
-#if SYNCLINK_GENERIC_HDLC
-		if (info->netcount)
-			hdlcdev_tx_done(info);
-		else
-#endif
-		{
-			if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
-				tx_stop(info);
-				return;
-			}
-			info->pending_bh |= BH_TRANSMIT;
-		}
-	}
-}
-
-
-/*
- * handle tx status interrupts
- */
-static void isr_txint(SLMP_INFO * info)
-{
-	unsigned char status = read_reg(info, SR1) & info->ie1_value & (UDRN + IDLE + CCTS);
-
-	/* clear status bits */
-	write_reg(info, SR1, status);
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txint status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	if (status & (UDRN + IDLE))
-		isr_txeom(info, status);
-
-	if (status & CCTS) {
-		/* simulate a common modem status change interrupt
-		 * for our handler
-		 */
-		get_signals( info );
-		isr_io_pin(info,
-			MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS));
-
-	}
-}
-
-/*
- * handle async tx data interrupts
- */
-static void isr_txrdy(SLMP_INFO * info)
-{
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txrdy() tx_count=%d\n",
-			__FILE__,__LINE__,info->device_name,info->tx_count);
-
-	if (info->params.mode != MGSL_MODE_ASYNC) {
-		/* disable TXRDY IRQ, enable IDLE IRQ */
-		info->ie0_value &= ~TXRDYE;
-		info->ie1_value |= IDLE;
-		write_reg16(info, IE0, (unsigned short)((info->ie1_value << 8) + info->ie0_value));
-		return;
-	}
-
-	if (info->port.tty && (info->port.tty->stopped || info->port.tty->hw_stopped)) {
-		tx_stop(info);
-		return;
-	}
-
-	if ( info->tx_count )
-		tx_load_fifo( info );
-	else {
-		info->tx_active = false;
-		info->ie0_value &= ~TXRDYE;
-		write_reg(info, IE0, info->ie0_value);
-	}
-
-	if (info->tx_count < WAKEUP_CHARS)
-		info->pending_bh |= BH_TRANSMIT;
-}
-
-static void isr_rxdmaok(SLMP_INFO * info)
-{
-	/* BIT7 = EOT (end of transfer)
-	 * BIT6 = EOM (end of message/frame)
-	 */
-	unsigned char status = read_reg(info,RXDMA + DSR) & 0xc0;
-
-	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
-	write_reg(info, RXDMA + DSR, (unsigned char)(status | 1));
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxdmaok(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	info->pending_bh |= BH_RECEIVE;
-}
-
-static void isr_rxdmaerror(SLMP_INFO * info)
-{
-	/* BIT5 = BOF (buffer overflow)
-	 * BIT4 = COF (counter overflow)
-	 */
-	unsigned char status = read_reg(info,RXDMA + DSR) & 0x30;
-
-	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
-	write_reg(info, RXDMA + DSR, (unsigned char)(status | 1));
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_rxdmaerror(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-
-	info->rx_overflow = true;
-	info->pending_bh |= BH_RECEIVE;
-}
-
-static void isr_txdmaok(SLMP_INFO * info)
-{
-	unsigned char status_reg1 = read_reg(info, SR1);
-
-	write_reg(info, TXDMA + DIR, 0x00);	/* disable Tx DMA IRQs */
-	write_reg(info, TXDMA + DSR, 0xc0); /* clear IRQs and disable DMA */
-	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txdmaok(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status_reg1);
-
-	/* program TXRDY as FIFO empty flag, enable TXRDY IRQ */
-	write_reg16(info, TRC0, 0);
-	info->ie0_value |= TXRDYE;
-	write_reg(info, IE0, info->ie0_value);
-}
-
-static void isr_txdmaerror(SLMP_INFO * info)
-{
-	/* BIT5 = BOF (buffer overflow)
-	 * BIT4 = COF (counter overflow)
-	 */
-	unsigned char status = read_reg(info,TXDMA + DSR) & 0x30;
-
-	/* clear IRQ (BIT0 must be 1 to prevent clearing DE bit) */
-	write_reg(info, TXDMA + DSR, (unsigned char)(status | 1));
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):%s isr_txdmaerror(), status=%02x\n",
-			__FILE__,__LINE__,info->device_name,status);
-}
-
-/* handle input serial signal changes
- */
-static void isr_io_pin( SLMP_INFO *info, u16 status )
-{
- 	struct	mgsl_icount *icount;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk("%s(%d):isr_io_pin status=%04X\n",
-			__FILE__,__LINE__,status);
-
-	if (status & (MISCSTATUS_CTS_LATCHED | MISCSTATUS_DCD_LATCHED |
-	              MISCSTATUS_DSR_LATCHED | MISCSTATUS_RI_LATCHED) ) {
-		icount = &info->icount;
-		/* update input line counters */
-		if (status & MISCSTATUS_RI_LATCHED) {
-			icount->rng++;
-			if ( status & SerialSignal_RI )
-				info->input_signal_events.ri_up++;
-			else
-				info->input_signal_events.ri_down++;
-		}
-		if (status & MISCSTATUS_DSR_LATCHED) {
-			icount->dsr++;
-			if ( status & SerialSignal_DSR )
-				info->input_signal_events.dsr_up++;
-			else
-				info->input_signal_events.dsr_down++;
-		}
-		if (status & MISCSTATUS_DCD_LATCHED) {
-			if ((info->dcd_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) {
-				info->ie1_value &= ~CDCD;
-				write_reg(info, IE1, info->ie1_value);
-			}
-			icount->dcd++;
-			if (status & SerialSignal_DCD) {
-				info->input_signal_events.dcd_up++;
-			} else
-				info->input_signal_events.dcd_down++;
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount) {
-				if (status & SerialSignal_DCD)
-					netif_carrier_on(info->netdev);
-				else
-					netif_carrier_off(info->netdev);
-			}
-#endif
-		}
-		if (status & MISCSTATUS_CTS_LATCHED)
-		{
-			if ((info->cts_chkcount)++ >= IO_PIN_SHUTDOWN_LIMIT) {
-				info->ie1_value &= ~CCTS;
-				write_reg(info, IE1, info->ie1_value);
-			}
-			icount->cts++;
-			if ( status & SerialSignal_CTS )
-				info->input_signal_events.cts_up++;
-			else
-				info->input_signal_events.cts_down++;
-		}
-		wake_up_interruptible(&info->status_event_wait_q);
-		wake_up_interruptible(&info->event_wait_q);
-
-		if ( (info->port.flags & ASYNC_CHECK_CD) &&
-		     (status & MISCSTATUS_DCD_LATCHED) ) {
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s CD now %s...", info->device_name,
-				       (status & SerialSignal_DCD) ? "on" : "off");
-			if (status & SerialSignal_DCD)
-				wake_up_interruptible(&info->port.open_wait);
-			else {
-				if ( debug_level >= DEBUG_LEVEL_ISR )
-					printk("doing serial hangup...");
-				if (info->port.tty)
-					tty_hangup(info->port.tty);
-			}
-		}
-
-		if ( (info->port.flags & ASYNC_CTS_FLOW) &&
-		     (status & MISCSTATUS_CTS_LATCHED) ) {
-			if ( info->port.tty ) {
-				if (info->port.tty->hw_stopped) {
-					if (status & SerialSignal_CTS) {
-						if ( debug_level >= DEBUG_LEVEL_ISR )
-							printk("CTS tx start...");
-			 			info->port.tty->hw_stopped = 0;
-						tx_start(info);
-						info->pending_bh |= BH_TRANSMIT;
-						return;
-					}
-				} else {
-					if (!(status & SerialSignal_CTS)) {
-						if ( debug_level >= DEBUG_LEVEL_ISR )
-							printk("CTS tx stop...");
-			 			info->port.tty->hw_stopped = 1;
-						tx_stop(info);
-					}
-				}
-			}
-		}
-	}
-
-	info->pending_bh |= BH_STATUS;
-}
-
-/* Interrupt service routine entry point.
- *
- * Arguments:
- * 	irq		interrupt number that caused interrupt
- * 	dev_id		device ID supplied during interrupt registration
- * 	regs		interrupted processor context
- */
-static irqreturn_t synclinkmp_interrupt(int dummy, void *dev_id)
-{
-	SLMP_INFO *info = dev_id;
-	unsigned char status, status0, status1=0;
-	unsigned char dmastatus, dmastatus0, dmastatus1=0;
-	unsigned char timerstatus0, timerstatus1=0;
-	unsigned char shift;
-	unsigned int i;
-	unsigned short tmp;
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk(KERN_DEBUG "%s(%d): synclinkmp_interrupt(%d)entry.\n",
-			__FILE__, __LINE__, info->irq_level);
-
-	spin_lock(&info->lock);
-
-	for(;;) {
-
-		/* get status for SCA0 (ports 0-1) */
-		tmp = read_reg16(info, ISR0);	/* get ISR0 and ISR1 in one read */
-		status0 = (unsigned char)tmp;
-		dmastatus0 = (unsigned char)(tmp>>8);
-		timerstatus0 = read_reg(info, ISR2);
-
-		if ( debug_level >= DEBUG_LEVEL_ISR )
-			printk(KERN_DEBUG "%s(%d):%s status0=%02x, dmastatus0=%02x, timerstatus0=%02x\n",
-				__FILE__, __LINE__, info->device_name,
-				status0, dmastatus0, timerstatus0);
-
-		if (info->port_count == 4) {
-			/* get status for SCA1 (ports 2-3) */
-			tmp = read_reg16(info->port_array[2], ISR0);
-			status1 = (unsigned char)tmp;
-			dmastatus1 = (unsigned char)(tmp>>8);
-			timerstatus1 = read_reg(info->port_array[2], ISR2);
-
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s(%d):%s status1=%02x, dmastatus1=%02x, timerstatus1=%02x\n",
-					__FILE__,__LINE__,info->device_name,
-					status1,dmastatus1,timerstatus1);
-		}
-
-		if (!status0 && !dmastatus0 && !timerstatus0 &&
-			 !status1 && !dmastatus1 && !timerstatus1)
-			break;
-
-		for(i=0; i < info->port_count ; i++) {
-			if (info->port_array[i] == NULL)
-				continue;
-			if (i < 2) {
-				status = status0;
-				dmastatus = dmastatus0;
-			} else {
-				status = status1;
-				dmastatus = dmastatus1;
-			}
-
-			shift = i & 1 ? 4 :0;
-
-			if (status & BIT0 << shift)
-				isr_rxrdy(info->port_array[i]);
-			if (status & BIT1 << shift)
-				isr_txrdy(info->port_array[i]);
-			if (status & BIT2 << shift)
-				isr_rxint(info->port_array[i]);
-			if (status & BIT3 << shift)
-				isr_txint(info->port_array[i]);
-
-			if (dmastatus & BIT0 << shift)
-				isr_rxdmaerror(info->port_array[i]);
-			if (dmastatus & BIT1 << shift)
-				isr_rxdmaok(info->port_array[i]);
-			if (dmastatus & BIT2 << shift)
-				isr_txdmaerror(info->port_array[i]);
-			if (dmastatus & BIT3 << shift)
-				isr_txdmaok(info->port_array[i]);
-		}
-
-		if (timerstatus0 & (BIT5 | BIT4))
-			isr_timer(info->port_array[0]);
-		if (timerstatus0 & (BIT7 | BIT6))
-			isr_timer(info->port_array[1]);
-		if (timerstatus1 & (BIT5 | BIT4))
-			isr_timer(info->port_array[2]);
-		if (timerstatus1 & (BIT7 | BIT6))
-			isr_timer(info->port_array[3]);
-	}
-
-	for(i=0; i < info->port_count ; i++) {
-		SLMP_INFO * port = info->port_array[i];
-
-		/* Request bottom half processing if there's something
-		 * for it to do and the bh is not already running.
-		 *
-		 * Note: startup adapter diags require interrupts.
-		 * do not request bottom half processing if the
-		 * device is not open in a normal mode.
-		 */
-		if ( port && (port->port.count || port->netcount) &&
-		     port->pending_bh && !port->bh_running &&
-		     !port->bh_requested ) {
-			if ( debug_level >= DEBUG_LEVEL_ISR )
-				printk("%s(%d):%s queueing bh task.\n",
-					__FILE__,__LINE__,port->device_name);
-			schedule_work(&port->task);
-			port->bh_requested = true;
-		}
-	}
-
-	spin_unlock(&info->lock);
-
-	if ( debug_level >= DEBUG_LEVEL_ISR )
-		printk(KERN_DEBUG "%s(%d):synclinkmp_interrupt(%d)exit.\n",
-			__FILE__, __LINE__, info->irq_level);
-	return IRQ_HANDLED;
-}
-
-/* Initialize and start device.
- */
-static int startup(SLMP_INFO * info)
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s tx_releaseup()\n",__FILE__,__LINE__,info->device_name);
-
-	if (info->port.flags & ASYNC_INITIALIZED)
-		return 0;
-
-	if (!info->tx_buf) {
-		info->tx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
-		if (!info->tx_buf) {
-			printk(KERN_ERR"%s(%d):%s can't allocate transmit buffer\n",
-				__FILE__,__LINE__,info->device_name);
-			return -ENOMEM;
-		}
-	}
-
-	info->pending_bh = 0;
-
-	memset(&info->icount, 0, sizeof(info->icount));
-
-	/* program hardware for current parameters */
-	reset_port(info);
-
-	change_params(info);
-
-	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
-
-	if (info->port.tty)
-		clear_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags |= ASYNC_INITIALIZED;
-
-	return 0;
-}
-
-/* Called by close() and hangup() to shutdown hardware
- */
-static void shutdown(SLMP_INFO * info)
-{
-	unsigned long flags;
-
-	if (!(info->port.flags & ASYNC_INITIALIZED))
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s synclinkmp_shutdown()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	/* clear status wait queue because status changes */
-	/* can't happen after shutting down the hardware */
-	wake_up_interruptible(&info->status_event_wait_q);
-	wake_up_interruptible(&info->event_wait_q);
-
-	del_timer(&info->tx_timer);
-	del_timer(&info->status_timer);
-
-	kfree(info->tx_buf);
-	info->tx_buf = NULL;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	reset_port(info);
-
- 	if (!info->port.tty || info->port.tty->termios->c_cflag & HUPCL) {
- 		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		set_signals(info);
-	}
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	if (info->port.tty)
-		set_bit(TTY_IO_ERROR, &info->port.tty->flags);
-
-	info->port.flags &= ~ASYNC_INITIALIZED;
-}
-
-static void program_hw(SLMP_INFO *info)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	rx_stop(info);
-	tx_stop(info);
-
-	info->tx_count = info->tx_put = info->tx_get = 0;
-
-	if (info->params.mode == MGSL_MODE_HDLC || info->netcount)
-		hdlc_mode(info);
-	else
-		async_mode(info);
-
-	set_signals(info);
-
-	info->dcd_chkcount = 0;
-	info->cts_chkcount = 0;
-	info->ri_chkcount = 0;
-	info->dsr_chkcount = 0;
-
-	info->ie1_value |= (CDCD|CCTS);
-	write_reg(info, IE1, info->ie1_value);
-
-	get_signals(info);
-
-	if (info->netcount || (info->port.tty && info->port.tty->termios->c_cflag & CREAD) )
-		rx_start(info);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-}
-
-/* Reconfigure adapter based on new parameters
- */
-static void change_params(SLMP_INFO *info)
-{
-	unsigned cflag;
-	int bits_per_char;
-
-	if (!info->port.tty || !info->port.tty->termios)
-		return;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s change_params()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	cflag = info->port.tty->termios->c_cflag;
-
-	/* if B0 rate (hangup) specified then negate DTR and RTS */
-	/* otherwise assert DTR and RTS */
- 	if (cflag & CBAUD)
-		info->serial_signals |= SerialSignal_RTS + SerialSignal_DTR;
-	else
-		info->serial_signals &= ~(SerialSignal_RTS + SerialSignal_DTR);
-
-	/* byte size and parity */
-
-	switch (cflag & CSIZE) {
-	      case CS5: info->params.data_bits = 5; break;
-	      case CS6: info->params.data_bits = 6; break;
-	      case CS7: info->params.data_bits = 7; break;
-	      case CS8: info->params.data_bits = 8; break;
-	      /* Never happens, but GCC is too dumb to figure it out */
-	      default:  info->params.data_bits = 7; break;
-	      }
-
-	if (cflag & CSTOPB)
-		info->params.stop_bits = 2;
-	else
-		info->params.stop_bits = 1;
-
-	info->params.parity = ASYNC_PARITY_NONE;
-	if (cflag & PARENB) {
-		if (cflag & PARODD)
-			info->params.parity = ASYNC_PARITY_ODD;
-		else
-			info->params.parity = ASYNC_PARITY_EVEN;
-#ifdef CMSPAR
-		if (cflag & CMSPAR)
-			info->params.parity = ASYNC_PARITY_SPACE;
-#endif
-	}
-
-	/* calculate number of jiffies to transmit a full
-	 * FIFO (32 bytes) at specified data rate
-	 */
-	bits_per_char = info->params.data_bits +
-			info->params.stop_bits + 1;
-
-	/* if port data rate is set to 460800 or less then
-	 * allow tty settings to override, otherwise keep the
-	 * current data rate.
-	 */
-	if (info->params.data_rate <= 460800) {
-		info->params.data_rate = tty_get_baud_rate(info->port.tty);
-	}
-
-	if ( info->params.data_rate ) {
-		info->timeout = (32*HZ*bits_per_char) /
-				info->params.data_rate;
-	}
-	info->timeout += HZ/50;		/* Add .02 seconds of slop */
-
-	if (cflag & CRTSCTS)
-		info->port.flags |= ASYNC_CTS_FLOW;
-	else
-		info->port.flags &= ~ASYNC_CTS_FLOW;
-
-	if (cflag & CLOCAL)
-		info->port.flags &= ~ASYNC_CHECK_CD;
-	else
-		info->port.flags |= ASYNC_CHECK_CD;
-
-	/* process tty input control flags */
-
-	info->read_status_mask2 = OVRN;
-	if (I_INPCK(info->port.tty))
-		info->read_status_mask2 |= PE | FRME;
- 	if (I_BRKINT(info->port.tty) || I_PARMRK(info->port.tty))
- 		info->read_status_mask1 |= BRKD;
-	if (I_IGNPAR(info->port.tty))
-		info->ignore_status_mask2 |= PE | FRME;
-	if (I_IGNBRK(info->port.tty)) {
-		info->ignore_status_mask1 |= BRKD;
-		/* If ignoring parity and break indicators, ignore
-		 * overruns too.  (For real raw support).
-		 */
-		if (I_IGNPAR(info->port.tty))
-			info->ignore_status_mask2 |= OVRN;
-	}
-
-	program_hw(info);
-}
-
-static int get_stats(SLMP_INFO * info, struct mgsl_icount __user *user_icount)
-{
-	int err;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s get_params()\n",
-			 __FILE__,__LINE__, info->device_name);
-
-	if (!user_icount) {
-		memset(&info->icount, 0, sizeof(info->icount));
-	} else {
-		mutex_lock(&info->port.mutex);
-		COPY_TO_USER(err, user_icount, &info->icount, sizeof(struct mgsl_icount));
-		mutex_unlock(&info->port.mutex);
-		if (err)
-			return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int get_params(SLMP_INFO * info, MGSL_PARAMS __user *user_params)
-{
-	int err;
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s get_params()\n",
-			 __FILE__,__LINE__, info->device_name);
-
-	mutex_lock(&info->port.mutex);
-	COPY_TO_USER(err,user_params, &info->params, sizeof(MGSL_PARAMS));
-	mutex_unlock(&info->port.mutex);
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):%s get_params() user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int set_params(SLMP_INFO * info, MGSL_PARAMS __user *new_params)
-{
- 	unsigned long flags;
-	MGSL_PARAMS tmp_params;
-	int err;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_params\n",
-			__FILE__,__LINE__,info->device_name );
-	COPY_FROM_USER(err,&tmp_params, new_params, sizeof(MGSL_PARAMS));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):%s set_params() user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-
-	mutex_lock(&info->port.mutex);
-	spin_lock_irqsave(&info->lock,flags);
-	memcpy(&info->params,&tmp_params,sizeof(MGSL_PARAMS));
-	spin_unlock_irqrestore(&info->lock,flags);
-
- 	change_params(info);
-	mutex_unlock(&info->port.mutex);
-
-	return 0;
-}
-
-static int get_txidle(SLMP_INFO * info, int __user *idle_mode)
-{
-	int err;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s get_txidle()=%d\n",
-			 __FILE__,__LINE__, info->device_name, info->idle_mode);
-
-	COPY_TO_USER(err,idle_mode, &info->idle_mode, sizeof(int));
-	if (err) {
-		if ( debug_level >= DEBUG_LEVEL_INFO )
-			printk( "%s(%d):%s get_txidle() user buffer copy failed\n",
-				__FILE__,__LINE__,info->device_name);
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int set_txidle(SLMP_INFO * info, int idle_mode)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s set_txidle(%d)\n",
-			__FILE__,__LINE__,info->device_name, idle_mode );
-
-	spin_lock_irqsave(&info->lock,flags);
-	info->idle_mode = idle_mode;
-	tx_set_idle( info );
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int tx_enable(SLMP_INFO * info, int enable)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tx_enable(%d)\n",
-			__FILE__,__LINE__,info->device_name, enable);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if ( enable ) {
-		if ( !info->tx_enabled ) {
-			tx_start(info);
-		}
-	} else {
-		if ( info->tx_enabled )
-			tx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/* abort send HDLC frame
- */
-static int tx_abort(SLMP_INFO * info)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tx_abort()\n",
-			__FILE__,__LINE__,info->device_name);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if ( info->tx_active && info->params.mode == MGSL_MODE_HDLC ) {
-		info->ie1_value &= ~UDRN;
-		info->ie1_value |= IDLE;
-		write_reg(info, IE1, info->ie1_value);	/* disable tx status interrupts */
-		write_reg(info, SR1, (unsigned char)(IDLE + UDRN));	/* clear pending */
-
-		write_reg(info, TXDMA + DSR, 0);		/* disable DMA channel */
-		write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-   		write_reg(info, CMD, TXABORT);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-static int rx_enable(SLMP_INFO * info, int enable)
-{
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s rx_enable(%d)\n",
-			__FILE__,__LINE__,info->device_name,enable);
-
-	spin_lock_irqsave(&info->lock,flags);
-	if ( enable ) {
-		if ( !info->rx_enabled )
-			rx_start(info);
-	} else {
-		if ( info->rx_enabled )
-			rx_stop(info);
-	}
-	spin_unlock_irqrestore(&info->lock,flags);
-	return 0;
-}
-
-/* wait for specified event to occur
- */
-static int wait_mgsl_event(SLMP_INFO * info, int __user *mask_ptr)
-{
- 	unsigned long flags;
-	int s;
-	int rc=0;
-	struct mgsl_icount cprev, cnow;
-	int events;
-	int mask;
-	struct	_input_signal_events oldsigs, newsigs;
-	DECLARE_WAITQUEUE(wait, current);
-
-	COPY_FROM_USER(rc,&mask, mask_ptr, sizeof(int));
-	if (rc) {
-		return  -EFAULT;
-	}
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s wait_mgsl_event(%d)\n",
-			__FILE__,__LINE__,info->device_name,mask);
-
-	spin_lock_irqsave(&info->lock,flags);
-
-	/* return immediately if state matches requested events */
-	get_signals(info);
-	s = info->serial_signals;
-
-	events = mask &
-		( ((s & SerialSignal_DSR) ? MgslEvent_DsrActive:MgslEvent_DsrInactive) +
- 		  ((s & SerialSignal_DCD) ? MgslEvent_DcdActive:MgslEvent_DcdInactive) +
-		  ((s & SerialSignal_CTS) ? MgslEvent_CtsActive:MgslEvent_CtsInactive) +
-		  ((s & SerialSignal_RI)  ? MgslEvent_RiActive :MgslEvent_RiInactive) );
-	if (events) {
-		spin_unlock_irqrestore(&info->lock,flags);
-		goto exit;
-	}
-
-	/* save current irq counts */
-	cprev = info->icount;
-	oldsigs = info->input_signal_events;
-
-	/* enable hunt and idle irqs if needed */
-	if (mask & (MgslEvent_ExitHuntMode+MgslEvent_IdleReceived)) {
-		unsigned char oldval = info->ie1_value;
-		unsigned char newval = oldval +
-			 (mask & MgslEvent_ExitHuntMode ? FLGD:0) +
-			 (mask & MgslEvent_IdleReceived ? IDLD:0);
-		if ( oldval != newval ) {
-			info->ie1_value = newval;
-			write_reg(info, IE1, info->ie1_value);
-		}
-	}
-
-	set_current_state(TASK_INTERRUPTIBLE);
-	add_wait_queue(&info->event_wait_q, &wait);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get current irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		newsigs = info->input_signal_events;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (newsigs.dsr_up   == oldsigs.dsr_up   &&
-		    newsigs.dsr_down == oldsigs.dsr_down &&
-		    newsigs.dcd_up   == oldsigs.dcd_up   &&
-		    newsigs.dcd_down == oldsigs.dcd_down &&
-		    newsigs.cts_up   == oldsigs.cts_up   &&
-		    newsigs.cts_down == oldsigs.cts_down &&
-		    newsigs.ri_up    == oldsigs.ri_up    &&
-		    newsigs.ri_down  == oldsigs.ri_down  &&
-		    cnow.exithunt    == cprev.exithunt   &&
-		    cnow.rxidle      == cprev.rxidle) {
-			rc = -EIO;
-			break;
-		}
-
-		events = mask &
-			( (newsigs.dsr_up   != oldsigs.dsr_up   ? MgslEvent_DsrActive:0)   +
-			  (newsigs.dsr_down != oldsigs.dsr_down ? MgslEvent_DsrInactive:0) +
-			  (newsigs.dcd_up   != oldsigs.dcd_up   ? MgslEvent_DcdActive:0)   +
-			  (newsigs.dcd_down != oldsigs.dcd_down ? MgslEvent_DcdInactive:0) +
-			  (newsigs.cts_up   != oldsigs.cts_up   ? MgslEvent_CtsActive:0)   +
-			  (newsigs.cts_down != oldsigs.cts_down ? MgslEvent_CtsInactive:0) +
-			  (newsigs.ri_up    != oldsigs.ri_up    ? MgslEvent_RiActive:0)    +
-			  (newsigs.ri_down  != oldsigs.ri_down  ? MgslEvent_RiInactive:0)  +
-			  (cnow.exithunt    != cprev.exithunt   ? MgslEvent_ExitHuntMode:0) +
-			  (cnow.rxidle      != cprev.rxidle     ? MgslEvent_IdleReceived:0) );
-		if (events)
-			break;
-
-		cprev = cnow;
-		oldsigs = newsigs;
-	}
-
-	remove_wait_queue(&info->event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-
-
-	if (mask & (MgslEvent_ExitHuntMode + MgslEvent_IdleReceived)) {
-		spin_lock_irqsave(&info->lock,flags);
-		if (!waitqueue_active(&info->event_wait_q)) {
-			/* disable enable exit hunt mode/idle rcvd IRQs */
-			info->ie1_value &= ~(FLGD|IDLD);
-			write_reg(info, IE1, info->ie1_value);
-		}
-		spin_unlock_irqrestore(&info->lock,flags);
-	}
-exit:
-	if ( rc == 0 )
-		PUT_USER(rc, events, mask_ptr);
-
-	return rc;
-}
-
-static int modem_input_wait(SLMP_INFO *info,int arg)
-{
- 	unsigned long flags;
-	int rc;
-	struct mgsl_icount cprev, cnow;
-	DECLARE_WAITQUEUE(wait, current);
-
-	/* save current irq counts */
-	spin_lock_irqsave(&info->lock,flags);
-	cprev = info->icount;
-	add_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_INTERRUPTIBLE);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	for(;;) {
-		schedule();
-		if (signal_pending(current)) {
-			rc = -ERESTARTSYS;
-			break;
-		}
-
-		/* get new irq counts */
-		spin_lock_irqsave(&info->lock,flags);
-		cnow = info->icount;
-		set_current_state(TASK_INTERRUPTIBLE);
-		spin_unlock_irqrestore(&info->lock,flags);
-
-		/* if no change, wait aborted for some reason */
-		if (cnow.rng == cprev.rng && cnow.dsr == cprev.dsr &&
-		    cnow.dcd == cprev.dcd && cnow.cts == cprev.cts) {
-			rc = -EIO;
-			break;
-		}
-
-		/* check for change in caller specified modem input */
-		if ((arg & TIOCM_RNG && cnow.rng != cprev.rng) ||
-		    (arg & TIOCM_DSR && cnow.dsr != cprev.dsr) ||
-		    (arg & TIOCM_CD  && cnow.dcd != cprev.dcd) ||
-		    (arg & TIOCM_CTS && cnow.cts != cprev.cts)) {
-			rc = 0;
-			break;
-		}
-
-		cprev = cnow;
-	}
-	remove_wait_queue(&info->status_event_wait_q, &wait);
-	set_current_state(TASK_RUNNING);
-	return rc;
-}
-
-/* return the state of the serial control and status signals
- */
-static int tiocmget(struct tty_struct *tty, struct file *file)
-{
-	SLMP_INFO *info = tty->driver_data;
-	unsigned int result;
- 	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	result = ((info->serial_signals & SerialSignal_RTS) ? TIOCM_RTS:0) +
-		((info->serial_signals & SerialSignal_DTR) ? TIOCM_DTR:0) +
-		((info->serial_signals & SerialSignal_DCD) ? TIOCM_CAR:0) +
-		((info->serial_signals & SerialSignal_RI)  ? TIOCM_RNG:0) +
-		((info->serial_signals & SerialSignal_DSR) ? TIOCM_DSR:0) +
-		((info->serial_signals & SerialSignal_CTS) ? TIOCM_CTS:0);
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmget() value=%08X\n",
-			 __FILE__,__LINE__, info->device_name, result );
-	return result;
-}
-
-/* set modem control signals (DTR/RTS)
- */
-static int tiocmset(struct tty_struct *tty, struct file *file,
-		    unsigned int set, unsigned int clear)
-{
-	SLMP_INFO *info = tty->driver_data;
- 	unsigned long flags;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s tiocmset(%x,%x)\n",
-			__FILE__,__LINE__,info->device_name, set, clear);
-
-	if (set & TIOCM_RTS)
-		info->serial_signals |= SerialSignal_RTS;
-	if (set & TIOCM_DTR)
-		info->serial_signals |= SerialSignal_DTR;
-	if (clear & TIOCM_RTS)
-		info->serial_signals &= ~SerialSignal_RTS;
-	if (clear & TIOCM_DTR)
-		info->serial_signals &= ~SerialSignal_DTR;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	set_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return 0;
-}
-
-static int carrier_raised(struct tty_port *port)
-{
-	SLMP_INFO *info = container_of(port, SLMP_INFO, port);
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
- 	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return (info->serial_signals & SerialSignal_DCD) ? 1 : 0;
-}
-
-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);
-	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);
-}
-
-/* Block the current process until the specified port is ready to open.
- */
-static int block_til_ready(struct tty_struct *tty, struct file *filp,
-			   SLMP_INFO *info)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	int		retval;
-	bool		do_clocal = false;
-	bool		extra_count = false;
-	unsigned long	flags;
-	int		cd;
-	struct tty_port *port = &info->port;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s block_til_ready()\n",
-			 __FILE__,__LINE__, tty->driver->name );
-
-	if (filp->f_flags & O_NONBLOCK || tty->flags & (1 << TTY_IO_ERROR)){
-		/* nonblock mode is set or port is not enabled */
-		/* just verify that callout device is not active */
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-		return 0;
-	}
-
-	if (tty->termios->c_cflag & CLOCAL)
-		do_clocal = true;
-
-	/* Wait for carrier detect and the line to become
-	 * free (i.e., not in use by the callout).  While we are in
-	 * this loop, port->count is dropped by one, so that
-	 * close() knows when to free things.  We restore it upon
-	 * exit, either normal or abnormal.
-	 */
-
-	retval = 0;
-	add_wait_queue(&port->open_wait, &wait);
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s block_til_ready() before block, count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-
-	spin_lock_irqsave(&info->lock, flags);
-	if (!tty_hung_up_p(filp)) {
-		extra_count = true;
-		port->count--;
-	}
-	spin_unlock_irqrestore(&info->lock, flags);
-	port->blocked_open++;
-
-	while (1) {
-		if (tty->termios->c_cflag & CBAUD)
-			tty_port_raise_dtr_rts(port);
-
-		set_current_state(TASK_INTERRUPTIBLE);
-
-		if (tty_hung_up_p(filp) || !(port->flags & ASYNC_INITIALIZED)){
-			retval = (port->flags & ASYNC_HUP_NOTIFY) ?
-					-EAGAIN : -ERESTARTSYS;
-			break;
-		}
-
-		cd = tty_port_carrier_raised(port);
-
- 		if (!(port->flags & ASYNC_CLOSING) && (do_clocal || cd))
- 			break;
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			break;
-		}
-
-		if (debug_level >= DEBUG_LEVEL_INFO)
-			printk("%s(%d):%s block_til_ready() count=%d\n",
-				 __FILE__,__LINE__, tty->driver->name, port->count );
-
-		tty_unlock();
-		schedule();
-		tty_lock();
-	}
-
-	set_current_state(TASK_RUNNING);
-	remove_wait_queue(&port->open_wait, &wait);
-
-	if (extra_count)
-		port->count++;
-	port->blocked_open--;
-
-	if (debug_level >= DEBUG_LEVEL_INFO)
-		printk("%s(%d):%s block_til_ready() after, count=%d\n",
-			 __FILE__,__LINE__, tty->driver->name, port->count );
-
-	if (!retval)
-		port->flags |= ASYNC_NORMAL_ACTIVE;
-
-	return retval;
-}
-
-static int alloc_dma_bufs(SLMP_INFO *info)
-{
-	unsigned short BuffersPerFrame;
-	unsigned short BufferCount;
-
-	// Force allocation to start at 64K boundary for each port.
-	// This is necessary because *all* buffer descriptors for a port
-	// *must* be in the same 64K block. All descriptors on a port
-	// share a common 'base' address (upper 8 bits of 24 bits) programmed
-	// into the CBP register.
-	info->port_array[0]->last_mem_alloc = (SCA_MEM_SIZE/4) * info->port_num;
-
-	/* Calculate the number of DMA buffers necessary to hold the */
-	/* largest allowable frame size. Note: If the max frame size is */
-	/* not an even multiple of the DMA buffer size then we need to */
-	/* round the buffer count per frame up one. */
-
-	BuffersPerFrame = (unsigned short)(info->max_frame_size/SCABUFSIZE);
-	if ( info->max_frame_size % SCABUFSIZE )
-		BuffersPerFrame++;
-
-	/* calculate total number of data buffers (SCABUFSIZE) possible
-	 * in one ports memory (SCA_MEM_SIZE/4) after allocating memory
-	 * for the descriptor list (BUFFERLISTSIZE).
-	 */
-	BufferCount = (SCA_MEM_SIZE/4 - BUFFERLISTSIZE)/SCABUFSIZE;
-
-	/* limit number of buffers to maximum amount of descriptors */
-	if (BufferCount > BUFFERLISTSIZE/sizeof(SCADESC))
-		BufferCount = BUFFERLISTSIZE/sizeof(SCADESC);
-
-	/* use enough buffers to transmit one max size frame */
-	info->tx_buf_count = BuffersPerFrame + 1;
-
-	/* never use more than half the available buffers for transmit */
-	if (info->tx_buf_count > (BufferCount/2))
-		info->tx_buf_count = BufferCount/2;
-
-	if (info->tx_buf_count > SCAMAXDESC)
-		info->tx_buf_count = SCAMAXDESC;
-
-	/* use remaining buffers for receive */
-	info->rx_buf_count = BufferCount - info->tx_buf_count;
-
-	if (info->rx_buf_count > SCAMAXDESC)
-		info->rx_buf_count = SCAMAXDESC;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk("%s(%d):%s Allocating %d TX and %d RX DMA buffers.\n",
-			__FILE__,__LINE__, info->device_name,
-			info->tx_buf_count,info->rx_buf_count);
-
-	if ( alloc_buf_list( info ) < 0 ||
-		alloc_frame_bufs(info,
-		  			info->rx_buf_list,
-		  			info->rx_buf_list_ex,
-					info->rx_buf_count) < 0 ||
-		alloc_frame_bufs(info,
-					info->tx_buf_list,
-					info->tx_buf_list_ex,
-					info->tx_buf_count) < 0 ||
-		alloc_tmp_rx_buf(info) < 0 ) {
-		printk("%s(%d):%s Can't allocate DMA buffer memory\n",
-			__FILE__,__LINE__, info->device_name);
-		return -ENOMEM;
-	}
-
-	rx_reset_buffers( info );
-
-	return 0;
-}
-
-/* Allocate DMA buffers for the transmit and receive descriptor lists.
- */
-static int alloc_buf_list(SLMP_INFO *info)
-{
-	unsigned int i;
-
-	/* build list in adapter shared memory */
-	info->buffer_list = info->memory_base + info->port_array[0]->last_mem_alloc;
-	info->buffer_list_phys = info->port_array[0]->last_mem_alloc;
-	info->port_array[0]->last_mem_alloc += BUFFERLISTSIZE;
-
-	memset(info->buffer_list, 0, BUFFERLISTSIZE);
-
-	/* Save virtual address pointers to the receive and */
-	/* transmit buffer lists. (Receive 1st). These pointers will */
-	/* be used by the processor to access the lists. */
-	info->rx_buf_list = (SCADESC *)info->buffer_list;
-
-	info->tx_buf_list = (SCADESC *)info->buffer_list;
-	info->tx_buf_list += info->rx_buf_count;
-
-	/* Build links for circular buffer entry lists (tx and rx)
-	 *
-	 * Note: links are physical addresses read by the SCA device
-	 * to determine the next buffer entry to use.
-	 */
-
-	for ( i = 0; i < info->rx_buf_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->rx_buf_list_ex[i].phys_entry =
-			info->buffer_list_phys + (i * sizeof(SCABUFSIZE));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-		info->rx_buf_list[i].next = info->buffer_list_phys;
-		if ( i < info->rx_buf_count - 1 )
-			info->rx_buf_list[i].next += (i + 1) * sizeof(SCADESC);
-
-		info->rx_buf_list[i].length = SCABUFSIZE;
-	}
-
-	for ( i = 0; i < info->tx_buf_count; i++ ) {
-		/* calculate and store physical address of this buffer entry */
-		info->tx_buf_list_ex[i].phys_entry = info->buffer_list_phys +
-			((info->rx_buf_count + i) * sizeof(SCADESC));
-
-		/* calculate and store physical address of */
-		/* next entry in cirular list of entries */
-
-		info->tx_buf_list[i].next = info->buffer_list_phys +
-			info->rx_buf_count * sizeof(SCADESC);
-
-		if ( i < info->tx_buf_count - 1 )
-			info->tx_buf_list[i].next += (i + 1) * sizeof(SCADESC);
-	}
-
-	return 0;
-}
-
-/* Allocate the frame DMA buffers used by the specified buffer list.
- */
-static int alloc_frame_bufs(SLMP_INFO *info, SCADESC *buf_list,SCADESC_EX *buf_list_ex,int count)
-{
-	int i;
-	unsigned long phys_addr;
-
-	for ( i = 0; i < count; i++ ) {
-		buf_list_ex[i].virt_addr = info->memory_base + info->port_array[0]->last_mem_alloc;
-		phys_addr = info->port_array[0]->last_mem_alloc;
-		info->port_array[0]->last_mem_alloc += SCABUFSIZE;
-
-		buf_list[i].buf_ptr  = (unsigned short)phys_addr;
-		buf_list[i].buf_base = (unsigned char)(phys_addr >> 16);
-	}
-
-	return 0;
-}
-
-static void free_dma_bufs(SLMP_INFO *info)
-{
-	info->buffer_list = NULL;
-	info->rx_buf_list = NULL;
-	info->tx_buf_list = NULL;
-}
-
-/* allocate buffer large enough to hold max_frame_size.
- * This buffer is used to pass an assembled frame to the line discipline.
- */
-static int alloc_tmp_rx_buf(SLMP_INFO *info)
-{
-	info->tmp_rx_buf = kmalloc(info->max_frame_size, GFP_KERNEL);
-	if (info->tmp_rx_buf == NULL)
-		return -ENOMEM;
-	return 0;
-}
-
-static void free_tmp_rx_buf(SLMP_INFO *info)
-{
-	kfree(info->tmp_rx_buf);
-	info->tmp_rx_buf = NULL;
-}
-
-static int claim_resources(SLMP_INFO *info)
-{
-	if (request_mem_region(info->phys_memory_base,SCA_MEM_SIZE,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->shared_mem_requested = true;
-
-	if (request_mem_region(info->phys_lcr_base + info->lcr_offset,128,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s lcr mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_lcr_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->lcr_mem_requested = true;
-
-	if (request_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s sca mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_sca_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->sca_base_requested = true;
-
-	if (request_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE,"synclinkmp") == NULL) {
-		printk( "%s(%d):%s stat/ctrl mem addr conflict, Addr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base);
-		info->init_error = DiagStatus_AddressConflict;
-		goto errout;
-	}
-	else
-		info->sca_statctrl_requested = true;
-
-	info->memory_base = ioremap_nocache(info->phys_memory_base,
-								SCA_MEM_SIZE);
-	if (!info->memory_base) {
-		printk( "%s(%d):%s Cant map shared memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-
-	info->lcr_base = ioremap_nocache(info->phys_lcr_base, PAGE_SIZE);
-	if (!info->lcr_base) {
-		printk( "%s(%d):%s Cant map LCR memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_lcr_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	info->lcr_base += info->lcr_offset;
-
-	info->sca_base = ioremap_nocache(info->phys_sca_base, PAGE_SIZE);
-	if (!info->sca_base) {
-		printk( "%s(%d):%s Cant map SCA memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_sca_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	info->sca_base += info->sca_offset;
-
-	info->statctrl_base = ioremap_nocache(info->phys_statctrl_base,
-								PAGE_SIZE);
-	if (!info->statctrl_base) {
-		printk( "%s(%d):%s Cant map SCA Status/Control memory, MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_statctrl_base );
-		info->init_error = DiagStatus_CantAssignPciResources;
-		goto errout;
-	}
-	info->statctrl_base += info->statctrl_offset;
-
-	if ( !memory_test(info) ) {
-		printk( "%s(%d):Shared Memory Test failed for device %s MemAddr=%08X\n",
-			__FILE__,__LINE__,info->device_name, info->phys_memory_base );
-		info->init_error = DiagStatus_MemoryError;
-		goto errout;
-	}
-
-	return 0;
-
-errout:
-	release_resources( info );
-	return -ENODEV;
-}
-
-static void release_resources(SLMP_INFO *info)
-{
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s release_resources() entry\n",
-			__FILE__,__LINE__,info->device_name );
-
-	if ( info->irq_requested ) {
-		free_irq(info->irq_level, info);
-		info->irq_requested = false;
-	}
-
-	if ( info->shared_mem_requested ) {
-		release_mem_region(info->phys_memory_base,SCA_MEM_SIZE);
-		info->shared_mem_requested = false;
-	}
-	if ( info->lcr_mem_requested ) {
-		release_mem_region(info->phys_lcr_base + info->lcr_offset,128);
-		info->lcr_mem_requested = false;
-	}
-	if ( info->sca_base_requested ) {
-		release_mem_region(info->phys_sca_base + info->sca_offset,SCA_BASE_SIZE);
-		info->sca_base_requested = false;
-	}
-	if ( info->sca_statctrl_requested ) {
-		release_mem_region(info->phys_statctrl_base + info->statctrl_offset,SCA_REG_SIZE);
-		info->sca_statctrl_requested = false;
-	}
-
-	if (info->memory_base){
-		iounmap(info->memory_base);
-		info->memory_base = NULL;
-	}
-
-	if (info->sca_base) {
-		iounmap(info->sca_base - info->sca_offset);
-		info->sca_base=NULL;
-	}
-
-	if (info->statctrl_base) {
-		iounmap(info->statctrl_base - info->statctrl_offset);
-		info->statctrl_base=NULL;
-	}
-
-	if (info->lcr_base){
-		iounmap(info->lcr_base - info->lcr_offset);
-		info->lcr_base = NULL;
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s release_resources() exit\n",
-			__FILE__,__LINE__,info->device_name );
-}
-
-/* Add the specified device instance data structure to the
- * global linked list of devices and increment the device count.
- */
-static void add_device(SLMP_INFO *info)
-{
-	info->next_device = NULL;
-	info->line = synclinkmp_device_count;
-	sprintf(info->device_name,"ttySLM%dp%d",info->adapter_num,info->port_num);
-
-	if (info->line < MAX_DEVICES) {
-		if (maxframe[info->line])
-			info->max_frame_size = maxframe[info->line];
-	}
-
-	synclinkmp_device_count++;
-
-	if ( !synclinkmp_device_list )
-		synclinkmp_device_list = info;
-	else {
-		SLMP_INFO *current_dev = synclinkmp_device_list;
-		while( current_dev->next_device )
-			current_dev = current_dev->next_device;
-		current_dev->next_device = info;
-	}
-
-	if ( info->max_frame_size < 4096 )
-		info->max_frame_size = 4096;
-	else if ( info->max_frame_size > 65535 )
-		info->max_frame_size = 65535;
-
-	printk( "SyncLink MultiPort %s: "
-		"Mem=(%08x %08X %08x %08X) IRQ=%d MaxFrameSize=%u\n",
-		info->device_name,
-		info->phys_sca_base,
-		info->phys_memory_base,
-		info->phys_statctrl_base,
-		info->phys_lcr_base,
-		info->irq_level,
-		info->max_frame_size );
-
-#if SYNCLINK_GENERIC_HDLC
-	hdlcdev_init(info);
-#endif
-}
-
-static const struct tty_port_operations port_ops = {
-	.carrier_raised = carrier_raised,
-	.dtr_rts = dtr_rts,
-};
-
-/* Allocate and initialize a device instance structure
- *
- * Return Value:	pointer to SLMP_INFO if success, otherwise NULL
- */
-static SLMP_INFO *alloc_dev(int adapter_num, int port_num, struct pci_dev *pdev)
-{
-	SLMP_INFO *info;
-
-	info = kzalloc(sizeof(SLMP_INFO),
-		 GFP_KERNEL);
-
-	if (!info) {
-		printk("%s(%d) Error can't allocate device instance data for adapter %d, port %d\n",
-			__FILE__,__LINE__, adapter_num, port_num);
-	} else {
-		tty_port_init(&info->port);
-		info->port.ops = &port_ops;
-		info->magic = MGSL_MAGIC;
-		INIT_WORK(&info->task, bh_handler);
-		info->max_frame_size = 4096;
-		info->port.close_delay = 5*HZ/10;
-		info->port.closing_wait = 30*HZ;
-		init_waitqueue_head(&info->status_event_wait_q);
-		init_waitqueue_head(&info->event_wait_q);
-		spin_lock_init(&info->netlock);
-		memcpy(&info->params,&default_params,sizeof(MGSL_PARAMS));
-		info->idle_mode = HDLC_TXIDLE_FLAGS;
-		info->adapter_num = adapter_num;
-		info->port_num = port_num;
-
-		/* Copy configuration info to device instance data */
-		info->irq_level = pdev->irq;
-		info->phys_lcr_base = pci_resource_start(pdev,0);
-		info->phys_sca_base = pci_resource_start(pdev,2);
-		info->phys_memory_base = pci_resource_start(pdev,3);
-		info->phys_statctrl_base = pci_resource_start(pdev,4);
-
-		/* Because veremap only works on page boundaries we must map
-		 * a larger area than is actually implemented for the LCR
-		 * memory range. We map a full page starting at the page boundary.
-		 */
-		info->lcr_offset    = info->phys_lcr_base & (PAGE_SIZE-1);
-		info->phys_lcr_base &= ~(PAGE_SIZE-1);
-
-		info->sca_offset    = info->phys_sca_base & (PAGE_SIZE-1);
-		info->phys_sca_base &= ~(PAGE_SIZE-1);
-
-		info->statctrl_offset    = info->phys_statctrl_base & (PAGE_SIZE-1);
-		info->phys_statctrl_base &= ~(PAGE_SIZE-1);
-
-		info->bus_type = MGSL_BUS_TYPE_PCI;
-		info->irq_flags = IRQF_SHARED;
-
-		setup_timer(&info->tx_timer, tx_timeout, (unsigned long)info);
-		setup_timer(&info->status_timer, status_timeout,
-				(unsigned long)info);
-
-		/* Store the PCI9050 misc control register value because a flaw
-		 * in the PCI9050 prevents LCR registers from being read if
-		 * BIOS assigns an LCR base address with bit 7 set.
-		 *
-		 * Only the misc control register is accessed for which only
-		 * write access is needed, so set an initial value and change
-		 * bits to the device instance data as we write the value
-		 * to the actual misc control register.
-		 */
-		info->misc_ctrl_value = 0x087e4546;
-
-		/* initial port state is unknown - if startup errors
-		 * occur, init_error will be set to indicate the
-		 * problem. Once the port is fully initialized,
-		 * this value will be set to 0 to indicate the
-		 * port is available.
-		 */
-		info->init_error = -1;
-	}
-
-	return info;
-}
-
-static void device_init(int adapter_num, struct pci_dev *pdev)
-{
-	SLMP_INFO *port_array[SCA_MAX_PORTS];
-	int port;
-
-	/* allocate device instances for up to SCA_MAX_PORTS devices */
-	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
-		port_array[port] = alloc_dev(adapter_num,port,pdev);
-		if( port_array[port] == NULL ) {
-			for ( --port; port >= 0; --port )
-				kfree(port_array[port]);
-			return;
-		}
-	}
-
-	/* give copy of port_array to all ports and add to device list  */
-	for ( port = 0; port < SCA_MAX_PORTS; ++port ) {
-		memcpy(port_array[port]->port_array,port_array,sizeof(port_array));
-		add_device( port_array[port] );
-		spin_lock_init(&port_array[port]->lock);
-	}
-
-	/* Allocate and claim adapter resources */
-	if ( !claim_resources(port_array[0]) ) {
-
-		alloc_dma_bufs(port_array[0]);
-
-		/* copy resource information from first port to others */
-		for ( port = 1; port < SCA_MAX_PORTS; ++port ) {
-			port_array[port]->lock  = port_array[0]->lock;
-			port_array[port]->irq_level     = port_array[0]->irq_level;
-			port_array[port]->memory_base   = port_array[0]->memory_base;
-			port_array[port]->sca_base      = port_array[0]->sca_base;
-			port_array[port]->statctrl_base = port_array[0]->statctrl_base;
-			port_array[port]->lcr_base      = port_array[0]->lcr_base;
-			alloc_dma_bufs(port_array[port]);
-		}
-
-		if ( request_irq(port_array[0]->irq_level,
-					synclinkmp_interrupt,
-					port_array[0]->irq_flags,
-					port_array[0]->device_name,
-					port_array[0]) < 0 ) {
-			printk( "%s(%d):%s Cant request interrupt, IRQ=%d\n",
-				__FILE__,__LINE__,
-				port_array[0]->device_name,
-				port_array[0]->irq_level );
-		}
-		else {
-			port_array[0]->irq_requested = true;
-			adapter_test(port_array[0]);
-		}
-	}
-}
-
-static const struct tty_operations ops = {
-	.open = open,
-	.close = close,
-	.write = write,
-	.put_char = put_char,
-	.flush_chars = flush_chars,
-	.write_room = write_room,
-	.chars_in_buffer = chars_in_buffer,
-	.flush_buffer = flush_buffer,
-	.ioctl = ioctl,
-	.throttle = throttle,
-	.unthrottle = unthrottle,
-	.send_xchar = send_xchar,
-	.break_ctl = set_break,
-	.wait_until_sent = wait_until_sent,
-	.set_termios = set_termios,
-	.stop = tx_hold,
-	.start = tx_release,
-	.hangup = hangup,
-	.tiocmget = tiocmget,
-	.tiocmset = tiocmset,
-	.get_icount = get_icount,
-	.proc_fops = &synclinkmp_proc_fops,
-};
-
-
-static void synclinkmp_cleanup(void)
-{
-	int rc;
-	SLMP_INFO *info;
-	SLMP_INFO *tmp;
-
-	printk("Unloading %s %s\n", driver_name, driver_version);
-
-	if (serial_driver) {
-		if ((rc = tty_unregister_driver(serial_driver)))
-			printk("%s(%d) failed to unregister tty driver err=%d\n",
-			       __FILE__,__LINE__,rc);
-		put_tty_driver(serial_driver);
-	}
-
-	/* reset devices */
-	info = synclinkmp_device_list;
-	while(info) {
-		reset_port(info);
-		info = info->next_device;
-	}
-
-	/* release devices */
-	info = synclinkmp_device_list;
-	while(info) {
-#if SYNCLINK_GENERIC_HDLC
-		hdlcdev_exit(info);
-#endif
-		free_dma_bufs(info);
-		free_tmp_rx_buf(info);
-		if ( info->port_num == 0 ) {
-			if (info->sca_base)
-				write_reg(info, LPR, 1); /* set low power mode */
-			release_resources(info);
-		}
-		tmp = info;
-		info = info->next_device;
-		kfree(tmp);
-	}
-
-	pci_unregister_driver(&synclinkmp_pci_driver);
-}
-
-/* Driver initialization entry point.
- */
-
-static int __init synclinkmp_init(void)
-{
-	int rc;
-
-	if (break_on_load) {
-	 	synclinkmp_get_text_ptr();
-  		BREAKPOINT();
-	}
-
- 	printk("%s %s\n", driver_name, driver_version);
-
-	if ((rc = pci_register_driver(&synclinkmp_pci_driver)) < 0) {
-		printk("%s:failed to register PCI driver, error=%d\n",__FILE__,rc);
-		return rc;
-	}
-
-	serial_driver = alloc_tty_driver(128);
-	if (!serial_driver) {
-		rc = -ENOMEM;
-		goto error;
-	}
-
-	/* Initialize the tty_driver structure */
-
-	serial_driver->owner = THIS_MODULE;
-	serial_driver->driver_name = "synclinkmp";
-	serial_driver->name = "ttySLM";
-	serial_driver->major = ttymajor;
-	serial_driver->minor_start = 64;
-	serial_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	serial_driver->subtype = SERIAL_TYPE_NORMAL;
-	serial_driver->init_termios = tty_std_termios;
-	serial_driver->init_termios.c_cflag =
-		B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	serial_driver->init_termios.c_ispeed = 9600;
-	serial_driver->init_termios.c_ospeed = 9600;
-	serial_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(serial_driver, &ops);
-	if ((rc = tty_register_driver(serial_driver)) < 0) {
-		printk("%s(%d):Couldn't register serial driver\n",
-			__FILE__,__LINE__);
-		put_tty_driver(serial_driver);
-		serial_driver = NULL;
-		goto error;
-	}
-
- 	printk("%s %s, tty major#%d\n",
-		driver_name, driver_version,
-		serial_driver->major);
-
-	return 0;
-
-error:
-	synclinkmp_cleanup();
-	return rc;
-}
-
-static void __exit synclinkmp_exit(void)
-{
-	synclinkmp_cleanup();
-}
-
-module_init(synclinkmp_init);
-module_exit(synclinkmp_exit);
-
-/* Set the port for internal loopback mode.
- * The TxCLK and RxCLK signals are generated from the BRG and
- * the TxD is looped back to the RxD internally.
- */
-static void enable_loopback(SLMP_INFO *info, int enable)
-{
-	if (enable) {
-		/* MD2 (Mode Register 2)
-		 * 01..00  CNCT<1..0> Channel Connection 11=Local Loopback
-		 */
-		write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) | (BIT1 + BIT0)));
-
-		/* degate external TxC clock source */
-		info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
-		write_control_reg(info);
-
-		/* RXS/TXS (Rx/Tx clock source)
-		 * 07      Reserved, must be 0
-		 * 06..04  Clock Source, 100=BRG
-		 * 03..00  Clock Divisor, 0000=1
-		 */
-		write_reg(info, RXS, 0x40);
-		write_reg(info, TXS, 0x40);
-
-	} else {
-		/* MD2 (Mode Register 2)
-	 	 * 01..00  CNCT<1..0> Channel connection, 0=normal
-		 */
-		write_reg(info, MD2, (unsigned char)(read_reg(info, MD2) & ~(BIT1 + BIT0)));
-
-		/* RXS/TXS (Rx/Tx clock source)
-		 * 07      Reserved, must be 0
-		 * 06..04  Clock Source, 000=RxC/TxC Pin
-		 * 03..00  Clock Divisor, 0000=1
-		 */
-		write_reg(info, RXS, 0x00);
-		write_reg(info, TXS, 0x00);
-	}
-
-	/* set LinkSpeed if available, otherwise default to 2Mbps */
-	if (info->params.clock_speed)
-		set_rate(info, info->params.clock_speed);
-	else
-		set_rate(info, 3686400);
-}
-
-/* Set the baud rate register to the desired speed
- *
- *	data_rate	data rate of clock in bits per second
- *			A data rate of 0 disables the AUX clock.
- */
-static void set_rate( SLMP_INFO *info, u32 data_rate )
-{
-       	u32 TMCValue;
-       	unsigned char BRValue;
-	u32 Divisor=0;
-
-	/* fBRG = fCLK/(TMC * 2^BR)
-	 */
-	if (data_rate != 0) {
-		Divisor = 14745600/data_rate;
-		if (!Divisor)
-			Divisor = 1;
-
-		TMCValue = Divisor;
-
-		BRValue = 0;
-		if (TMCValue != 1 && TMCValue != 2) {
-			/* BRValue of 0 provides 50/50 duty cycle *only* when
-			 * TMCValue is 1 or 2. BRValue of 1 to 9 always provides
-			 * 50/50 duty cycle.
-			 */
-			BRValue = 1;
-			TMCValue >>= 1;
-		}
-
-		/* while TMCValue is too big for TMC register, divide
-		 * by 2 and increment BR exponent.
-		 */
-		for(; TMCValue > 256 && BRValue < 10; BRValue++)
-			TMCValue >>= 1;
-
-		write_reg(info, TXS,
-			(unsigned char)((read_reg(info, TXS) & 0xf0) | BRValue));
-		write_reg(info, RXS,
-			(unsigned char)((read_reg(info, RXS) & 0xf0) | BRValue));
-		write_reg(info, TMC, (unsigned char)TMCValue);
-	}
-	else {
-		write_reg(info, TXS,0);
-		write_reg(info, RXS,0);
-		write_reg(info, TMC, 0);
-	}
-}
-
-/* Disable receiver
- */
-static void rx_stop(SLMP_INFO *info)
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s rx_stop()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	write_reg(info, CMD, RXRESET);
-
-	info->ie0_value &= ~RXRDYE;
-	write_reg(info, IE0, info->ie0_value);	/* disable Rx data interrupts */
-
-	write_reg(info, RXDMA + DSR, 0);	/* disable Rx DMA */
-	write_reg(info, RXDMA + DCMD, SWABORT);	/* reset/init Rx DMA */
-	write_reg(info, RXDMA + DIR, 0);	/* disable Rx DMA interrupts */
-
-	info->rx_enabled = false;
-	info->rx_overflow = false;
-}
-
-/* enable the receiver
- */
-static void rx_start(SLMP_INFO *info)
-{
-	int i;
-
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s rx_start()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	write_reg(info, CMD, RXRESET);
-
-	if ( info->params.mode == MGSL_MODE_HDLC ) {
-		/* HDLC, disabe IRQ on rxdata */
-		info->ie0_value &= ~RXRDYE;
-		write_reg(info, IE0, info->ie0_value);
-
-		/* Reset all Rx DMA buffers and program rx dma */
-		write_reg(info, RXDMA + DSR, 0);		/* disable Rx DMA */
-		write_reg(info, RXDMA + DCMD, SWABORT);	/* reset/init Rx DMA */
-
-		for (i = 0; i < info->rx_buf_count; i++) {
-			info->rx_buf_list[i].status = 0xff;
-
-			// throttle to 4 shared memory writes at a time to prevent
-			// hogging local bus (keep latency time for DMA requests low).
-			if (!(i % 4))
-				read_status_reg(info);
-		}
-		info->current_rx_buf = 0;
-
-		/* set current/1st descriptor address */
-		write_reg16(info, RXDMA + CDA,
-			info->rx_buf_list_ex[0].phys_entry);
-
-		/* set new last rx descriptor address */
-		write_reg16(info, RXDMA + EDA,
-			info->rx_buf_list_ex[info->rx_buf_count - 1].phys_entry);
-
-		/* set buffer length (shared by all rx dma data buffers) */
-		write_reg16(info, RXDMA + BFL, SCABUFSIZE);
-
-		write_reg(info, RXDMA + DIR, 0x60);	/* enable Rx DMA interrupts (EOM/BOF) */
-		write_reg(info, RXDMA + DSR, 0xf2);	/* clear Rx DMA IRQs, enable Rx DMA */
-	} else {
-		/* async, enable IRQ on rxdata */
-		info->ie0_value |= RXRDYE;
-		write_reg(info, IE0, info->ie0_value);
-	}
-
-	write_reg(info, CMD, RXENABLE);
-
-	info->rx_overflow = false;
-	info->rx_enabled = true;
-}
-
-/* Enable the transmitter and send a transmit frame if
- * one is loaded in the DMA buffers.
- */
-static void tx_start(SLMP_INFO *info)
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s tx_start() tx_count=%d\n",
-			 __FILE__,__LINE__, info->device_name,info->tx_count );
-
-	if (!info->tx_enabled ) {
-		write_reg(info, CMD, TXRESET);
-		write_reg(info, CMD, TXENABLE);
-		info->tx_enabled = true;
-	}
-
-	if ( info->tx_count ) {
-
-		/* If auto RTS enabled and RTS is inactive, then assert */
-		/* RTS and set a flag indicating that the driver should */
-		/* negate RTS when the transmission completes. */
-
-		info->drop_rts_on_tx_done = false;
-
-		if (info->params.mode != MGSL_MODE_ASYNC) {
-
-			if ( info->params.flags & HDLC_FLAG_AUTO_RTS ) {
-				get_signals( info );
-				if ( !(info->serial_signals & SerialSignal_RTS) ) {
-					info->serial_signals |= SerialSignal_RTS;
-					set_signals( info );
-					info->drop_rts_on_tx_done = true;
-				}
-			}
-
-			write_reg16(info, TRC0,
-				(unsigned short)(((tx_negate_fifo_level-1)<<8) + tx_active_fifo_level));
-
-			write_reg(info, TXDMA + DSR, 0); 		/* disable DMA channel */
-			write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-	
-			/* set TX CDA (current descriptor address) */
-			write_reg16(info, TXDMA + CDA,
-				info->tx_buf_list_ex[0].phys_entry);
-	
-			/* set TX EDA (last descriptor address) */
-			write_reg16(info, TXDMA + EDA,
-				info->tx_buf_list_ex[info->last_tx_buf].phys_entry);
-	
-			/* enable underrun IRQ */
-			info->ie1_value &= ~IDLE;
-			info->ie1_value |= UDRN;
-			write_reg(info, IE1, info->ie1_value);
-			write_reg(info, SR1, (unsigned char)(IDLE + UDRN));
-	
-			write_reg(info, TXDMA + DIR, 0x40);		/* enable Tx DMA interrupts (EOM) */
-			write_reg(info, TXDMA + DSR, 0xf2);		/* clear Tx DMA IRQs, enable Tx DMA */
-	
-			mod_timer(&info->tx_timer, jiffies +
-					msecs_to_jiffies(5000));
-		}
-		else {
-			tx_load_fifo(info);
-			/* async, enable IRQ on txdata */
-			info->ie0_value |= TXRDYE;
-			write_reg(info, IE0, info->ie0_value);
-		}
-
-		info->tx_active = true;
-	}
-}
-
-/* stop the transmitter and DMA
- */
-static void tx_stop( SLMP_INFO *info )
-{
-	if (debug_level >= DEBUG_LEVEL_ISR)
-		printk("%s(%d):%s tx_stop()\n",
-			 __FILE__,__LINE__, info->device_name );
-
-	del_timer(&info->tx_timer);
-
-	write_reg(info, TXDMA + DSR, 0);		/* disable DMA channel */
-	write_reg(info, TXDMA + DCMD, SWABORT);	/* reset/init DMA channel */
-
-	write_reg(info, CMD, TXRESET);
-
-	info->ie1_value &= ~(UDRN + IDLE);
-	write_reg(info, IE1, info->ie1_value);	/* disable tx status interrupts */
-	write_reg(info, SR1, (unsigned char)(IDLE + UDRN));	/* clear pending */
-
-	info->ie0_value &= ~TXRDYE;
-	write_reg(info, IE0, info->ie0_value);	/* disable tx data interrupts */
-
-	info->tx_enabled = false;
-	info->tx_active = false;
-}
-
-/* Fill the transmit FIFO until the FIFO is full or
- * there is no more data to load.
- */
-static void tx_load_fifo(SLMP_INFO *info)
-{
-	u8 TwoBytes[2];
-
-	/* do nothing is now tx data available and no XON/XOFF pending */
-
-	if ( !info->tx_count && !info->x_char )
-		return;
-
-	/* load the Transmit FIFO until FIFOs full or all data sent */
-
-	while( info->tx_count && (read_reg(info,SR0) & BIT1) ) {
-
-		/* there is more space in the transmit FIFO and */
-		/* there is more data in transmit buffer */
-
-		if ( (info->tx_count > 1) && !info->x_char ) {
- 			/* write 16-bits */
-			TwoBytes[0] = info->tx_buf[info->tx_get++];
-			if (info->tx_get >= info->max_frame_size)
-				info->tx_get -= info->max_frame_size;
-			TwoBytes[1] = info->tx_buf[info->tx_get++];
-			if (info->tx_get >= info->max_frame_size)
-				info->tx_get -= info->max_frame_size;
-
-			write_reg16(info, TRB, *((u16 *)TwoBytes));
-
-			info->tx_count -= 2;
-			info->icount.tx += 2;
-		} else {
-			/* only 1 byte left to transmit or 1 FIFO slot left */
-
-			if (info->x_char) {
-				/* transmit pending high priority char */
-				write_reg(info, TRB, info->x_char);
-				info->x_char = 0;
-			} else {
-				write_reg(info, TRB, info->tx_buf[info->tx_get++]);
-				if (info->tx_get >= info->max_frame_size)
-					info->tx_get -= info->max_frame_size;
-				info->tx_count--;
-			}
-			info->icount.tx++;
-		}
-	}
-}
-
-/* Reset a port to a known state
- */
-static void reset_port(SLMP_INFO *info)
-{
-	if (info->sca_base) {
-
-		tx_stop(info);
-		rx_stop(info);
-
-		info->serial_signals &= ~(SerialSignal_DTR + SerialSignal_RTS);
-		set_signals(info);
-
-		/* disable all port interrupts */
-		info->ie0_value = 0;
-		info->ie1_value = 0;
-		info->ie2_value = 0;
-		write_reg(info, IE0, info->ie0_value);
-		write_reg(info, IE1, info->ie1_value);
-		write_reg(info, IE2, info->ie2_value);
-
-		write_reg(info, CMD, CHRESET);
-	}
-}
-
-/* Reset all the ports to a known state.
- */
-static void reset_adapter(SLMP_INFO *info)
-{
-	int i;
-
-	for ( i=0; i < SCA_MAX_PORTS; ++i) {
-		if (info->port_array[i])
-			reset_port(info->port_array[i]);
-	}
-}
-
-/* Program port for asynchronous communications.
- */
-static void async_mode(SLMP_INFO *info)
-{
-
-  	unsigned char RegValue;
-
-	tx_stop(info);
-	rx_stop(info);
-
-	/* MD0, Mode Register 0
-	 *
-	 * 07..05  PRCTL<2..0>, Protocol Mode, 000=async
-	 * 04      AUTO, Auto-enable (RTS/CTS/DCD)
-	 * 03      Reserved, must be 0
-	 * 02      CRCCC, CRC Calculation, 0=disabled
-	 * 01..00  STOP<1..0> Stop bits (00=1,10=2)
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	if (info->params.stop_bits != 1)
-		RegValue |= BIT1;
-	write_reg(info, MD0, RegValue);
-
-	/* MD1, Mode Register 1
-	 *
-	 * 07..06  BRATE<1..0>, bit rate, 00=1/1 01=1/16 10=1/32 11=1/64
-	 * 05..04  TXCHR<1..0>, tx char size, 00=8 bits,01=7,10=6,11=5
-	 * 03..02  RXCHR<1..0>, rx char size
-	 * 01..00  PMPM<1..0>, Parity mode, 00=none 10=even 11=odd
-	 *
-	 * 0100 0000
-	 */
-	RegValue = 0x40;
-	switch (info->params.data_bits) {
-	case 7: RegValue |= BIT4 + BIT2; break;
-	case 6: RegValue |= BIT5 + BIT3; break;
-	case 5: RegValue |= BIT5 + BIT4 + BIT3 + BIT2; break;
-	}
-	if (info->params.parity != ASYNC_PARITY_NONE) {
-		RegValue |= BIT1;
-		if (info->params.parity == ASYNC_PARITY_ODD)
-			RegValue |= BIT0;
-	}
-	write_reg(info, MD1, RegValue);
-
-	/* MD2, Mode Register 2
-	 *
-	 * 07..02  Reserved, must be 0
-	 * 01..00  CNCT<1..0> Channel connection, 00=normal 11=local loopback
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	if (info->params.loopback)
-		RegValue |= (BIT1 + BIT0);
-	write_reg(info, MD2, RegValue);
-
-	/* RXS, Receive clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=BIT6;
-	write_reg(info, RXS, RegValue);
-
-	/* TXS, Transmit clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=BIT6;
-	write_reg(info, TXS, RegValue);
-
-	/* Control Register
-	 *
-	 * 6,4,2,0  CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out
-	 */
-	info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
-	write_control_reg(info);
-
-	tx_set_idle(info);
-
-	/* RRC Receive Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  RRC<4..0> Rx FIFO trigger active 0x00 = 1 byte
-	 */
-	write_reg(info, RRC, 0x00);
-
-	/* TRC0 Transmit Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger active 0x10 = 16 bytes
-	 */
-	write_reg(info, TRC0, 0x10);
-
-	/* TRC1 Transmit Ready Control 1
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger inactive 0x1e = 31 bytes (full-1)
-	 */
-	write_reg(info, TRC1, 0x1e);
-
-	/* CTL, MSCI control register
-	 *
-	 * 07..06  Reserved, set to 0
-	 * 05      UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC)
-	 * 04      IDLC, idle control, 0=mark 1=idle register
-	 * 03      BRK, break, 0=off 1 =on (async)
-	 * 02      SYNCLD, sync char load enable (BSC) 1=enabled
-	 * 01      GOP, go active on poll (LOOP mode) 1=enabled
-	 * 00      RTS, RTS output control, 0=active 1=inactive
-	 *
-	 * 0001 0001
-	 */
-	RegValue = 0x10;
-	if (!(info->serial_signals & SerialSignal_RTS))
-		RegValue |= 0x01;
-	write_reg(info, CTL, RegValue);
-
-	/* enable status interrupts */
-	info->ie0_value |= TXINTE + RXINTE;
-	write_reg(info, IE0, info->ie0_value);
-
-	/* enable break detect interrupt */
-	info->ie1_value = BRKD;
-	write_reg(info, IE1, info->ie1_value);
-
-	/* enable rx overrun interrupt */
-	info->ie2_value = OVRN;
-	write_reg(info, IE2, info->ie2_value);
-
-	set_rate( info, info->params.data_rate * 16 );
-}
-
-/* Program the SCA for HDLC communications.
- */
-static void hdlc_mode(SLMP_INFO *info)
-{
-	unsigned char RegValue;
-	u32 DpllDivisor;
-
-	// Can't use DPLL because SCA outputs recovered clock on RxC when
-	// DPLL mode selected. This causes output contention with RxC receiver.
-	// Use of DPLL would require external hardware to disable RxC receiver
-	// when DPLL mode selected.
-	info->params.flags &= ~(HDLC_FLAG_TXC_DPLL + HDLC_FLAG_RXC_DPLL);
-
-	/* disable DMA interrupts */
-	write_reg(info, TXDMA + DIR, 0);
-	write_reg(info, RXDMA + DIR, 0);
-
-	/* MD0, Mode Register 0
-	 *
-	 * 07..05  PRCTL<2..0>, Protocol Mode, 100=HDLC
-	 * 04      AUTO, Auto-enable (RTS/CTS/DCD)
-	 * 03      Reserved, must be 0
-	 * 02      CRCCC, CRC Calculation, 1=enabled
-	 * 01      CRC1, CRC selection, 0=CRC-16,1=CRC-CCITT-16
-	 * 00      CRC0, CRC initial value, 1 = all 1s
-	 *
-	 * 1000 0001
-	 */
-	RegValue = 0x81;
-	if (info->params.flags & HDLC_FLAG_AUTO_CTS)
-		RegValue |= BIT4;
-	if (info->params.flags & HDLC_FLAG_AUTO_DCD)
-		RegValue |= BIT4;
-	if (info->params.crc_type == HDLC_CRC_16_CCITT)
-		RegValue |= BIT2 + BIT1;
-	write_reg(info, MD0, RegValue);
-
-	/* MD1, Mode Register 1
-	 *
-	 * 07..06  ADDRS<1..0>, Address detect, 00=no addr check
-	 * 05..04  TXCHR<1..0>, tx char size, 00=8 bits
-	 * 03..02  RXCHR<1..0>, rx char size, 00=8 bits
-	 * 01..00  PMPM<1..0>, Parity mode, 00=no parity
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	write_reg(info, MD1, RegValue);
-
-	/* MD2, Mode Register 2
-	 *
-	 * 07      NRZFM, 0=NRZ, 1=FM
-	 * 06..05  CODE<1..0> Encoding, 00=NRZ
-	 * 04..03  DRATE<1..0> DPLL Divisor, 00=8
-	 * 02      Reserved, must be 0
-	 * 01..00  CNCT<1..0> Channel connection, 0=normal
-	 *
-	 * 0000 0000
-	 */
-	RegValue = 0x00;
-	switch(info->params.encoding) {
-	case HDLC_ENCODING_NRZI:	  RegValue |= BIT5; break;
-	case HDLC_ENCODING_BIPHASE_MARK:  RegValue |= BIT7 + BIT5; break; /* aka FM1 */
-	case HDLC_ENCODING_BIPHASE_SPACE: RegValue |= BIT7 + BIT6; break; /* aka FM0 */
-	case HDLC_ENCODING_BIPHASE_LEVEL: RegValue |= BIT7; break; 	/* aka Manchester */
-#if 0
-	case HDLC_ENCODING_NRZB:	       				/* not supported */
-	case HDLC_ENCODING_NRZI_MARK:          				/* not supported */
-	case HDLC_ENCODING_DIFF_BIPHASE_LEVEL: 				/* not supported */
-#endif
-	}
-	if ( info->params.flags & HDLC_FLAG_DPLL_DIV16 ) {
-		DpllDivisor = 16;
-		RegValue |= BIT3;
-	} else if ( info->params.flags & HDLC_FLAG_DPLL_DIV8 ) {
-		DpllDivisor = 8;
-	} else {
-		DpllDivisor = 32;
-		RegValue |= BIT4;
-	}
-	write_reg(info, MD2, RegValue);
-
-
-	/* RXS, Receive clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=RxC Pin, 100=BRG, 110=DPLL
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=0;
-	if (info->params.flags & HDLC_FLAG_RXC_BRG)
-		RegValue |= BIT6;
-	if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-		RegValue |= BIT6 + BIT5;
-	write_reg(info, RXS, RegValue);
-
-	/* TXS, Transmit clock source
-	 *
-	 * 07      Reserved, must be 0
-	 * 06..04  RXCS<2..0>, clock source, 000=TxC Pin, 100=BRG, 110=Receive Clock
-	 * 03..00  RXBR<3..0>, rate divisor, 0000=1
-	 */
-	RegValue=0;
-	if (info->params.flags & HDLC_FLAG_TXC_BRG)
-		RegValue |= BIT6;
-	if (info->params.flags & HDLC_FLAG_TXC_DPLL)
-		RegValue |= BIT6 + BIT5;
-	write_reg(info, TXS, RegValue);
-
-	if (info->params.flags & HDLC_FLAG_RXC_DPLL)
-		set_rate(info, info->params.clock_speed * DpllDivisor);
-	else
-		set_rate(info, info->params.clock_speed);
-
-	/* GPDATA (General Purpose I/O Data Register)
-	 *
-	 * 6,4,2,0  CLKSEL<3..0>, 0 = TcCLK in, 1 = Auxclk out
-	 */
-	if (info->params.flags & HDLC_FLAG_TXC_BRG)
-		info->port_array[0]->ctrlreg_value |= (BIT0 << (info->port_num * 2));
-	else
-		info->port_array[0]->ctrlreg_value &= ~(BIT0 << (info->port_num * 2));
-	write_control_reg(info);
-
-	/* RRC Receive Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  RRC<4..0> Rx FIFO trigger active
-	 */
-	write_reg(info, RRC, rx_active_fifo_level);
-
-	/* TRC0 Transmit Ready Control 0
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger active
-	 */
-	write_reg(info, TRC0, tx_active_fifo_level);
-
-	/* TRC1 Transmit Ready Control 1
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04..00  TRC<4..0> Tx FIFO trigger inactive 0x1f = 32 bytes (full)
-	 */
-	write_reg(info, TRC1, (unsigned char)(tx_negate_fifo_level - 1));
-
-	/* DMR, DMA Mode Register
-	 *
-	 * 07..05  Reserved, must be 0
-	 * 04      TMOD, Transfer Mode: 1=chained-block
-	 * 03      Reserved, must be 0
-	 * 02      NF, Number of Frames: 1=multi-frame
-	 * 01      CNTE, Frame End IRQ Counter enable: 0=disabled
-	 * 00      Reserved, must be 0
-	 *
-	 * 0001 0100
-	 */
-	write_reg(info, TXDMA + DMR, 0x14);
-	write_reg(info, RXDMA + DMR, 0x14);
-
-	/* Set chain pointer base (upper 8 bits of 24 bit addr) */
-	write_reg(info, RXDMA + CPB,
-		(unsigned char)(info->buffer_list_phys >> 16));
-
-	/* Set chain pointer base (upper 8 bits of 24 bit addr) */
-	write_reg(info, TXDMA + CPB,
-		(unsigned char)(info->buffer_list_phys >> 16));
-
-	/* enable status interrupts. other code enables/disables
-	 * the individual sources for these two interrupt classes.
-	 */
-	info->ie0_value |= TXINTE + RXINTE;
-	write_reg(info, IE0, info->ie0_value);
-
-	/* CTL, MSCI control register
-	 *
-	 * 07..06  Reserved, set to 0
-	 * 05      UDRNC, underrun control, 0=abort 1=CRC+flag (HDLC/BSC)
-	 * 04      IDLC, idle control, 0=mark 1=idle register
-	 * 03      BRK, break, 0=off 1 =on (async)
-	 * 02      SYNCLD, sync char load enable (BSC) 1=enabled
-	 * 01      GOP, go active on poll (LOOP mode) 1=enabled
-	 * 00      RTS, RTS output control, 0=active 1=inactive
-	 *
-	 * 0001 0001
-	 */
-	RegValue = 0x10;
-	if (!(info->serial_signals & SerialSignal_RTS))
-		RegValue |= 0x01;
-	write_reg(info, CTL, RegValue);
-
-	/* preamble not supported ! */
-
-	tx_set_idle(info);
-	tx_stop(info);
-	rx_stop(info);
-
-	set_rate(info, info->params.clock_speed);
-
-	if (info->params.loopback)
-		enable_loopback(info,1);
-}
-
-/* Set the transmit HDLC idle mode
- */
-static void tx_set_idle(SLMP_INFO *info)
-{
-	unsigned char RegValue = 0xff;
-
-	/* Map API idle mode to SCA register bits */
-	switch(info->idle_mode) {
-	case HDLC_TXIDLE_FLAGS:			RegValue = 0x7e; break;
-	case HDLC_TXIDLE_ALT_ZEROS_ONES:	RegValue = 0xaa; break;
-	case HDLC_TXIDLE_ZEROS:			RegValue = 0x00; break;
-	case HDLC_TXIDLE_ONES:			RegValue = 0xff; break;
-	case HDLC_TXIDLE_ALT_MARK_SPACE:	RegValue = 0xaa; break;
-	case HDLC_TXIDLE_SPACE:			RegValue = 0x00; break;
-	case HDLC_TXIDLE_MARK:			RegValue = 0xff; break;
-	}
-
-	write_reg(info, IDL, RegValue);
-}
-
-/* Query the adapter for the state of the V24 status (input) signals.
- */
-static void get_signals(SLMP_INFO *info)
-{
-	u16 status = read_reg(info, SR3);
-	u16 gpstatus = read_status_reg(info);
-	u16 testbit;
-
-	/* clear all serial signals except DTR and RTS */
-	info->serial_signals &= SerialSignal_DTR + SerialSignal_RTS;
-
-	/* set serial signal bits to reflect MISR */
-
-	if (!(status & BIT3))
-		info->serial_signals |= SerialSignal_CTS;
-
-	if ( !(status & BIT2))
-		info->serial_signals |= SerialSignal_DCD;
-
-	testbit = BIT1 << (info->port_num * 2); // Port 0..3 RI is GPDATA<1,3,5,7>
-	if (!(gpstatus & testbit))
-		info->serial_signals |= SerialSignal_RI;
-
-	testbit = BIT0 << (info->port_num * 2); // Port 0..3 DSR is GPDATA<0,2,4,6>
-	if (!(gpstatus & testbit))
-		info->serial_signals |= SerialSignal_DSR;
-}
-
-/* Set the state of DTR and RTS based on contents of
- * serial_signals member of device context.
- */
-static void set_signals(SLMP_INFO *info)
-{
-	unsigned char RegValue;
-	u16 EnableBit;
-
-	RegValue = read_reg(info, CTL);
-	if (info->serial_signals & SerialSignal_RTS)
-		RegValue &= ~BIT0;
-	else
-		RegValue |= BIT0;
-	write_reg(info, CTL, RegValue);
-
-	// Port 0..3 DTR is ctrl reg <1,3,5,7>
-	EnableBit = BIT1 << (info->port_num*2);
-	if (info->serial_signals & SerialSignal_DTR)
-		info->port_array[0]->ctrlreg_value &= ~EnableBit;
-	else
-		info->port_array[0]->ctrlreg_value |= EnableBit;
-	write_control_reg(info);
-}
-
-/*******************/
-/* DMA Buffer Code */
-/*******************/
-
-/* Set the count for all receive buffers to SCABUFSIZE
- * and set the current buffer to the first buffer. This effectively
- * makes all buffers free and discards any data in buffers.
- */
-static void rx_reset_buffers(SLMP_INFO *info)
-{
-	rx_free_frame_buffers(info, 0, info->rx_buf_count - 1);
-}
-
-/* Free the buffers used by a received frame
- *
- * info   pointer to device instance data
- * first  index of 1st receive buffer of frame
- * last   index of last receive buffer of frame
- */
-static void rx_free_frame_buffers(SLMP_INFO *info, unsigned int first, unsigned int last)
-{
-	bool done = false;
-
-	while(!done) {
-	        /* reset current buffer for reuse */
-		info->rx_buf_list[first].status = 0xff;
-
-	        if (first == last) {
-	                done = true;
-	                /* set new last rx descriptor address */
-			write_reg16(info, RXDMA + EDA, info->rx_buf_list_ex[first].phys_entry);
-	        }
-
-	        first++;
-		if (first == info->rx_buf_count)
-			first = 0;
-	}
-
-	/* set current buffer to next buffer after last buffer of frame */
-	info->current_rx_buf = first;
-}
-
-/* Return a received frame from the receive DMA buffers.
- * Only frames received without errors are returned.
- *
- * Return Value:	true if frame returned, otherwise false
- */
-static bool rx_get_frame(SLMP_INFO *info)
-{
-	unsigned int StartIndex, EndIndex;	/* index of 1st and last buffers of Rx frame */
-	unsigned short status;
-	unsigned int framesize = 0;
-	bool ReturnCode = false;
-	unsigned long flags;
-	struct tty_struct *tty = info->port.tty;
-	unsigned char addr_field = 0xff;
-   	SCADESC *desc;
-	SCADESC_EX *desc_ex;
-
-CheckAgain:
-	/* assume no frame returned, set zero length */
-	framesize = 0;
-	addr_field = 0xff;
-
-	/*
-	 * current_rx_buf points to the 1st buffer of the next available
-	 * receive frame. To find the last buffer of the frame look for
-	 * a non-zero status field in the buffer entries. (The status
-	 * field is set by the 16C32 after completing a receive frame.
-	 */
-	StartIndex = EndIndex = info->current_rx_buf;
-
-	for ( ;; ) {
-		desc = &info->rx_buf_list[EndIndex];
-		desc_ex = &info->rx_buf_list_ex[EndIndex];
-
-		if (desc->status == 0xff)
-			goto Cleanup;	/* current desc still in use, no frames available */
-
-		if (framesize == 0 && info->params.addr_filter != 0xff)
-			addr_field = desc_ex->virt_addr[0];
-
-		framesize += desc->length;
-
-		/* Status != 0 means last buffer of frame */
-		if (desc->status)
-			break;
-
-		EndIndex++;
-		if (EndIndex == info->rx_buf_count)
-			EndIndex = 0;
-
-		if (EndIndex == info->current_rx_buf) {
-			/* all buffers have been 'used' but none mark	   */
-			/* the end of a frame. Reset buffers and receiver. */
-			if ( info->rx_enabled ){
-				spin_lock_irqsave(&info->lock,flags);
-				rx_start(info);
-				spin_unlock_irqrestore(&info->lock,flags);
-			}
-			goto Cleanup;
-		}
-
-	}
-
-	/* check status of receive frame */
-
-	/* frame status is byte stored after frame data
-	 *
-	 * 7 EOM (end of msg), 1 = last buffer of frame
-	 * 6 Short Frame, 1 = short frame
-	 * 5 Abort, 1 = frame aborted
-	 * 4 Residue, 1 = last byte is partial
-	 * 3 Overrun, 1 = overrun occurred during frame reception
-	 * 2 CRC,     1 = CRC error detected
-	 *
-	 */
-	status = desc->status;
-
-	/* ignore CRC bit if not using CRC (bit is undefined) */
-	/* Note:CRC is not save to data buffer */
-	if (info->params.crc_type == HDLC_CRC_NONE)
-		status &= ~BIT2;
-
-	if (framesize == 0 ||
-		 (addr_field != 0xff && addr_field != info->params.addr_filter)) {
-		/* discard 0 byte frames, this seems to occur sometime
-		 * when remote is idling flags.
-		 */
-		rx_free_frame_buffers(info, StartIndex, EndIndex);
-		goto CheckAgain;
-	}
-
-	if (framesize < 2)
-		status |= BIT6;
-
-	if (status & (BIT6+BIT5+BIT3+BIT2)) {
-		/* received frame has errors,
-		 * update counts and mark frame size as 0
-		 */
-		if (status & BIT6)
-			info->icount.rxshort++;
-		else if (status & BIT5)
-			info->icount.rxabort++;
-		else if (status & BIT3)
-			info->icount.rxover++;
-		else
-			info->icount.rxcrc++;
-
-		framesize = 0;
-#if SYNCLINK_GENERIC_HDLC
-		{
-			info->netdev->stats.rx_errors++;
-			info->netdev->stats.rx_frame_errors++;
-		}
-#endif
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_BH )
-		printk("%s(%d):%s rx_get_frame() status=%04X size=%d\n",
-			__FILE__,__LINE__,info->device_name,status,framesize);
-
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		trace_block(info,info->rx_buf_list_ex[StartIndex].virt_addr,
-			min_t(int, framesize,SCABUFSIZE),0);
-
-	if (framesize) {
-		if (framesize > info->max_frame_size)
-			info->icount.rxlong++;
-		else {
-			/* copy dma buffer(s) to contiguous intermediate buffer */
-			int copy_count = framesize;
-			int index = StartIndex;
-			unsigned char *ptmp = info->tmp_rx_buf;
-			info->tmp_rx_buf_count = framesize;
-
-			info->icount.rxok++;
-
-			while(copy_count) {
-				int partial_count = min(copy_count,SCABUFSIZE);
-				memcpy( ptmp,
-					info->rx_buf_list_ex[index].virt_addr,
-					partial_count );
-				ptmp += partial_count;
-				copy_count -= partial_count;
-
-				if ( ++index == info->rx_buf_count )
-					index = 0;
-			}
-
-#if SYNCLINK_GENERIC_HDLC
-			if (info->netcount)
-				hdlcdev_rx(info,info->tmp_rx_buf,framesize);
-			else
-#endif
-				ldisc_receive_buf(tty,info->tmp_rx_buf,
-						  info->flag_buf, framesize);
-		}
-	}
-	/* Free the buffers used by this frame. */
-	rx_free_frame_buffers( info, StartIndex, EndIndex );
-
-	ReturnCode = true;
-
-Cleanup:
-	if ( info->rx_enabled && info->rx_overflow ) {
-		/* Receiver is enabled, but needs to restarted due to
-		 * rx buffer overflow. If buffers are empty, restart receiver.
-		 */
-		if (info->rx_buf_list[EndIndex].status == 0xff) {
-			spin_lock_irqsave(&info->lock,flags);
-			rx_start(info);
-			spin_unlock_irqrestore(&info->lock,flags);
-		}
-	}
-
-	return ReturnCode;
-}
-
-/* load the transmit DMA buffer with data
- */
-static void tx_load_dma_buffer(SLMP_INFO *info, const char *buf, unsigned int count)
-{
-	unsigned short copy_count;
-	unsigned int i = 0;
-	SCADESC *desc;
-	SCADESC_EX *desc_ex;
-
-	if ( debug_level >= DEBUG_LEVEL_DATA )
-		trace_block(info,buf, min_t(int, count,SCABUFSIZE), 1);
-
-	/* Copy source buffer to one or more DMA buffers, starting with
-	 * the first transmit dma buffer.
-	 */
-	for(i=0;;)
-	{
-		copy_count = min_t(unsigned short,count,SCABUFSIZE);
-
-		desc = &info->tx_buf_list[i];
-		desc_ex = &info->tx_buf_list_ex[i];
-
-		load_pci_memory(info, desc_ex->virt_addr,buf,copy_count);
-
-		desc->length = copy_count;
-		desc->status = 0;
-
-		buf += copy_count;
-		count -= copy_count;
-
-		if (!count)
-			break;
-
-		i++;
-		if (i >= info->tx_buf_count)
-			i = 0;
-	}
-
-	info->tx_buf_list[i].status = 0x81;	/* set EOM and EOT status */
-	info->last_tx_buf = ++i;
-}
-
-static bool register_test(SLMP_INFO *info)
-{
-	static unsigned char testval[] = {0x00, 0xff, 0xaa, 0x55, 0x69, 0x96};
-	static unsigned int count = ARRAY_SIZE(testval);
-	unsigned int i;
-	bool rc = true;
-	unsigned long flags;
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-
-	/* assume failure */
-	info->init_error = DiagStatus_AddressFailure;
-
-	/* Write bit patterns to various registers but do it out of */
-	/* sync, then read back and verify values. */
-
-	for (i = 0 ; i < count ; i++) {
-		write_reg(info, TMC, testval[i]);
-		write_reg(info, IDL, testval[(i+1)%count]);
-		write_reg(info, SA0, testval[(i+2)%count]);
-		write_reg(info, SA1, testval[(i+3)%count]);
-
-		if ( (read_reg(info, TMC) != testval[i]) ||
-			  (read_reg(info, IDL) != testval[(i+1)%count]) ||
-			  (read_reg(info, SA0) != testval[(i+2)%count]) ||
-			  (read_reg(info, SA1) != testval[(i+3)%count]) )
-		{
-			rc = false;
-			break;
-		}
-	}
-
-	reset_port(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return rc;
-}
-
-static bool irq_test(SLMP_INFO *info)
-{
-	unsigned long timeout;
-	unsigned long flags;
-
-	unsigned char timer = (info->port_num & 1) ? TIMER2 : TIMER0;
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-
-	/* assume failure */
-	info->init_error = DiagStatus_IrqFailure;
-	info->irq_occurred = false;
-
-	/* setup timer0 on SCA0 to interrupt */
-
-	/* IER2<7..4> = timer<3..0> interrupt enables (1=enabled) */
-	write_reg(info, IER2, (unsigned char)((info->port_num & 1) ? BIT6 : BIT4));
-
-	write_reg(info, (unsigned char)(timer + TEPR), 0);	/* timer expand prescale */
-	write_reg16(info, (unsigned char)(timer + TCONR), 1);	/* timer constant */
-
-
-	/* TMCS, Timer Control/Status Register
-	 *
-	 * 07      CMF, Compare match flag (read only) 1=match
-	 * 06      ECMI, CMF Interrupt Enable: 1=enabled
-	 * 05      Reserved, must be 0
-	 * 04      TME, Timer Enable
-	 * 03..00  Reserved, must be 0
-	 *
-	 * 0101 0000
-	 */
-	write_reg(info, (unsigned char)(timer + TMCS), 0x50);
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	timeout=100;
-	while( timeout-- && !info->irq_occurred ) {
-		msleep_interruptible(10);
-	}
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_port(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	return info->irq_occurred;
-}
-
-/* initialize individual SCA device (2 ports)
- */
-static bool sca_init(SLMP_INFO *info)
-{
-	/* set wait controller to single mem partition (low), no wait states */
-	write_reg(info, PABR0, 0);	/* wait controller addr boundary 0 */
-	write_reg(info, PABR1, 0);	/* wait controller addr boundary 1 */
-	write_reg(info, WCRL, 0);	/* wait controller low range */
-	write_reg(info, WCRM, 0);	/* wait controller mid range */
-	write_reg(info, WCRH, 0);	/* wait controller high range */
-
-	/* DPCR, DMA Priority Control
-	 *
-	 * 07..05  Not used, must be 0
-	 * 04      BRC, bus release condition: 0=all transfers complete
-	 * 03      CCC, channel change condition: 0=every cycle
-	 * 02..00  PR<2..0>, priority 100=round robin
-	 *
-	 * 00000100 = 0x04
-	 */
-	write_reg(info, DPCR, dma_priority);
-
-	/* DMA Master Enable, BIT7: 1=enable all channels */
-	write_reg(info, DMER, 0x80);
-
-	/* enable all interrupt classes */
-	write_reg(info, IER0, 0xff);	/* TxRDY,RxRDY,TxINT,RxINT (ports 0-1) */
-	write_reg(info, IER1, 0xff);	/* DMIB,DMIA (channels 0-3) */
-	write_reg(info, IER2, 0xf0);	/* TIRQ (timers 0-3) */
-
-	/* ITCR, interrupt control register
-	 * 07      IPC, interrupt priority, 0=MSCI->DMA
-	 * 06..05  IAK<1..0>, Acknowledge cycle, 00=non-ack cycle
-	 * 04      VOS, Vector Output, 0=unmodified vector
-	 * 03..00  Reserved, must be 0
-	 */
-	write_reg(info, ITCR, 0);
-
-	return true;
-}
-
-/* initialize adapter hardware
- */
-static bool init_adapter(SLMP_INFO *info)
-{
-	int i;
-
-	/* Set BIT30 of Local Control Reg 0x50 to reset SCA */
-	volatile u32 *MiscCtrl = (u32 *)(info->lcr_base + 0x50);
-	u32 readval;
-
-	info->misc_ctrl_value |= BIT30;
-	*MiscCtrl = info->misc_ctrl_value;
-
-	/*
-	 * Force at least 170ns delay before clearing
-	 * reset bit. Each read from LCR takes at least
-	 * 30ns so 10 times for 300ns to be safe.
-	 */
-	for(i=0;i<10;i++)
-		readval = *MiscCtrl;
-
-	info->misc_ctrl_value &= ~BIT30;
-	*MiscCtrl = info->misc_ctrl_value;
-
-	/* init control reg (all DTRs off, all clksel=input) */
-	info->ctrlreg_value = 0xaa;
-	write_control_reg(info);
-
-	{
-		volatile u32 *LCR1BRDR = (u32 *)(info->lcr_base + 0x2c);
-		lcr1_brdr_value &= ~(BIT5 + BIT4 + BIT3);
-
-		switch(read_ahead_count)
-		{
-		case 16:
-			lcr1_brdr_value |= BIT5 + BIT4 + BIT3;
-			break;
-		case 8:
-			lcr1_brdr_value |= BIT5 + BIT4;
-			break;
-		case 4:
-			lcr1_brdr_value |= BIT5 + BIT3;
-			break;
-		case 0:
-			lcr1_brdr_value |= BIT5;
-			break;
-		}
-
-		*LCR1BRDR = lcr1_brdr_value;
-		*MiscCtrl = misc_ctrl_value;
-	}
-
-	sca_init(info->port_array[0]);
-	sca_init(info->port_array[2]);
-
-	return true;
-}
-
-/* Loopback an HDLC frame to test the hardware
- * interrupt and DMA functions.
- */
-static bool loopback_test(SLMP_INFO *info)
-{
-#define TESTFRAMESIZE 20
-
-	unsigned long timeout;
-	u16 count = TESTFRAMESIZE;
-	unsigned char buf[TESTFRAMESIZE];
-	bool rc = false;
-	unsigned long flags;
-
-	struct tty_struct *oldtty = info->port.tty;
-	u32 speed = info->params.clock_speed;
-
-	info->params.clock_speed = 3686400;
-	info->port.tty = NULL;
-
-	/* assume failure */
-	info->init_error = DiagStatus_DmaFailure;
-
-	/* build and send transmit frame */
-	for (count = 0; count < TESTFRAMESIZE;++count)
-		buf[count] = (unsigned char)count;
-
-	memset(info->tmp_rx_buf,0,TESTFRAMESIZE);
-
-	/* program hardware for HDLC and enabled receiver */
-	spin_lock_irqsave(&info->lock,flags);
-	hdlc_mode(info);
-	enable_loopback(info,1);
-       	rx_start(info);
-	info->tx_count = count;
-	tx_load_dma_buffer(info,buf,count);
-	tx_start(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	/* wait for receive complete */
-	/* Set a timeout for waiting for interrupt. */
-	for ( timeout = 100; timeout; --timeout ) {
-		msleep_interruptible(10);
-
-		if (rx_get_frame(info)) {
-			rc = true;
-			break;
-		}
-	}
-
-	/* verify received frame length and contents */
-	if (rc &&
-	    ( info->tmp_rx_buf_count != count ||
-	      memcmp(buf, info->tmp_rx_buf,count))) {
-		rc = false;
-	}
-
-	spin_lock_irqsave(&info->lock,flags);
-	reset_adapter(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	info->params.clock_speed = speed;
-	info->port.tty = oldtty;
-
-	return rc;
-}
-
-/* Perform diagnostics on hardware
- */
-static int adapter_test( SLMP_INFO *info )
-{
-	unsigned long flags;
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):Testing device %s\n",
-			__FILE__,__LINE__,info->device_name );
-
-	spin_lock_irqsave(&info->lock,flags);
-	init_adapter(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	info->port_array[0]->port_count = 0;
-
-	if ( register_test(info->port_array[0]) &&
-		register_test(info->port_array[1])) {
-
-		info->port_array[0]->port_count = 2;
-
-		if ( register_test(info->port_array[2]) &&
-			register_test(info->port_array[3]) )
-			info->port_array[0]->port_count += 2;
-	}
-	else {
-		printk( "%s(%d):Register test failure for device %s Addr=%08lX\n",
-			__FILE__,__LINE__,info->device_name, (unsigned long)(info->phys_sca_base));
-		return -ENODEV;
-	}
-
-	if ( !irq_test(info->port_array[0]) ||
-		!irq_test(info->port_array[1]) ||
-		 (info->port_count == 4 && !irq_test(info->port_array[2])) ||
-		 (info->port_count == 4 && !irq_test(info->port_array[3]))) {
-		printk( "%s(%d):Interrupt test failure for device %s IRQ=%d\n",
-			__FILE__,__LINE__,info->device_name, (unsigned short)(info->irq_level) );
-		return -ENODEV;
-	}
-
-	if (!loopback_test(info->port_array[0]) ||
-		!loopback_test(info->port_array[1]) ||
-		 (info->port_count == 4 && !loopback_test(info->port_array[2])) ||
-		 (info->port_count == 4 && !loopback_test(info->port_array[3]))) {
-		printk( "%s(%d):DMA test failure for device %s\n",
-			__FILE__,__LINE__,info->device_name);
-		return -ENODEV;
-	}
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):device %s passed diagnostics\n",
-			__FILE__,__LINE__,info->device_name );
-
-	info->port_array[0]->init_error = 0;
-	info->port_array[1]->init_error = 0;
-	if ( info->port_count > 2 ) {
-		info->port_array[2]->init_error = 0;
-		info->port_array[3]->init_error = 0;
-	}
-
-	return 0;
-}
-
-/* Test the shared memory on a PCI adapter.
- */
-static bool memory_test(SLMP_INFO *info)
-{
-	static unsigned long testval[] = { 0x0, 0x55555555, 0xaaaaaaaa,
-		0x66666666, 0x99999999, 0xffffffff, 0x12345678 };
-	unsigned long count = ARRAY_SIZE(testval);
-	unsigned long i;
-	unsigned long limit = SCA_MEM_SIZE/sizeof(unsigned long);
-	unsigned long * addr = (unsigned long *)info->memory_base;
-
-	/* Test data lines with test pattern at one location. */
-
-	for ( i = 0 ; i < count ; i++ ) {
-		*addr = testval[i];
-		if ( *addr != testval[i] )
-			return false;
-	}
-
-	/* Test address lines with incrementing pattern over */
-	/* entire address range. */
-
-	for ( i = 0 ; i < limit ; i++ ) {
-		*addr = i * 4;
-		addr++;
-	}
-
-	addr = (unsigned long *)info->memory_base;
-
-	for ( i = 0 ; i < limit ; i++ ) {
-		if ( *addr != i * 4 )
-			return false;
-		addr++;
-	}
-
-	memset( info->memory_base, 0, SCA_MEM_SIZE );
-	return true;
-}
-
-/* Load data into PCI adapter shared memory.
- *
- * The PCI9050 releases control of the local bus
- * after completing the current read or write operation.
- *
- * While the PCI9050 write FIFO not empty, the
- * PCI9050 treats all of the writes as a single transaction
- * and does not release the bus. This causes DMA latency problems
- * at high speeds when copying large data blocks to the shared memory.
- *
- * This function breaks a write into multiple transations by
- * interleaving a read which flushes the write FIFO and 'completes'
- * the write transation. This allows any pending DMA request to gain control
- * of the local bus in a timely fasion.
- */
-static void load_pci_memory(SLMP_INFO *info, char* dest, const char* src, unsigned short count)
-{
-	/* A load interval of 16 allows for 4 32-bit writes at */
-	/* 136ns each for a maximum latency of 542ns on the local bus.*/
-
-	unsigned short interval = count / sca_pci_load_interval;
-	unsigned short i;
-
-	for ( i = 0 ; i < interval ; i++ )
-	{
-		memcpy(dest, src, sca_pci_load_interval);
-		read_status_reg(info);
-		dest += sca_pci_load_interval;
-		src += sca_pci_load_interval;
-	}
-
-	memcpy(dest, src, count % sca_pci_load_interval);
-}
-
-static void trace_block(SLMP_INFO *info,const char* data, int count, int xmit)
-{
-	int i;
-	int linecount;
-	if (xmit)
-		printk("%s tx data:\n",info->device_name);
-	else
-		printk("%s rx data:\n",info->device_name);
-
-	while(count) {
-		if (count > 16)
-			linecount = 16;
-		else
-			linecount = count;
-
-		for(i=0;i<linecount;i++)
-			printk("%02X ",(unsigned char)data[i]);
-		for(;i<17;i++)
-			printk("   ");
-		for(i=0;i<linecount;i++) {
-			if (data[i]>=040 && data[i]<=0176)
-				printk("%c",data[i]);
-			else
-				printk(".");
-		}
-		printk("\n");
-
-		data  += linecount;
-		count -= linecount;
-	}
-}	/* end of trace_block() */
-
-/* called when HDLC frame times out
- * update stats and do tx completion processing
- */
-static void tx_timeout(unsigned long context)
-{
-	SLMP_INFO *info = (SLMP_INFO*)context;
-	unsigned long flags;
-
-	if ( debug_level >= DEBUG_LEVEL_INFO )
-		printk( "%s(%d):%s tx_timeout()\n",
-			__FILE__,__LINE__,info->device_name);
-	if(info->tx_active && info->params.mode == MGSL_MODE_HDLC) {
-		info->icount.txtimeout++;
-	}
-	spin_lock_irqsave(&info->lock,flags);
-	info->tx_active = false;
-	info->tx_count = info->tx_put = info->tx_get = 0;
-
-	spin_unlock_irqrestore(&info->lock,flags);
-
-#if SYNCLINK_GENERIC_HDLC
-	if (info->netcount)
-		hdlcdev_tx_done(info);
-	else
-#endif
-		bh_transmit(info);
-}
-
-/* called to periodically check the DSR/RI modem signal input status
- */
-static void status_timeout(unsigned long context)
-{
-	u16 status = 0;
-	SLMP_INFO *info = (SLMP_INFO*)context;
-	unsigned long flags;
-	unsigned char delta;
-
-
-	spin_lock_irqsave(&info->lock,flags);
-	get_signals(info);
-	spin_unlock_irqrestore(&info->lock,flags);
-
-	/* check for DSR/RI state change */
-
-	delta = info->old_signals ^ info->serial_signals;
-	info->old_signals = info->serial_signals;
-
-	if (delta & SerialSignal_DSR)
-		status |= MISCSTATUS_DSR_LATCHED|(info->serial_signals&SerialSignal_DSR);
-
-	if (delta & SerialSignal_RI)
-		status |= MISCSTATUS_RI_LATCHED|(info->serial_signals&SerialSignal_RI);
-
-	if (delta & SerialSignal_DCD)
-		status |= MISCSTATUS_DCD_LATCHED|(info->serial_signals&SerialSignal_DCD);
-
-	if (delta & SerialSignal_CTS)
-		status |= MISCSTATUS_CTS_LATCHED|(info->serial_signals&SerialSignal_CTS);
-
-	if (status)
-		isr_io_pin(info,status);
-
-	mod_timer(&info->status_timer, jiffies + msecs_to_jiffies(10));
-}
-
-
-/* Register Access Routines -
- * All registers are memory mapped
- */
-#define CALC_REGADDR() \
-	unsigned char * RegAddr = (unsigned char*)(info->sca_base + Addr); \
-	if (info->port_num > 1) \
-		RegAddr += 256;	    		/* port 0-1 SCA0, 2-3 SCA1 */ \
-	if ( info->port_num & 1) { \
-		if (Addr > 0x7f) \
-			RegAddr += 0x40;	/* DMA access */ \
-		else if (Addr > 0x1f && Addr < 0x60) \
-			RegAddr += 0x20;	/* MSCI access */ \
-	}
-
-
-static unsigned char read_reg(SLMP_INFO * info, unsigned char Addr)
-{
-	CALC_REGADDR();
-	return *RegAddr;
-}
-static void write_reg(SLMP_INFO * info, unsigned char Addr, unsigned char Value)
-{
-	CALC_REGADDR();
-	*RegAddr = Value;
-}
-
-static u16 read_reg16(SLMP_INFO * info, unsigned char Addr)
-{
-	CALC_REGADDR();
-	return *((u16 *)RegAddr);
-}
-
-static void write_reg16(SLMP_INFO * info, unsigned char Addr, u16 Value)
-{
-	CALC_REGADDR();
-	*((u16 *)RegAddr) = Value;
-}
-
-static unsigned char read_status_reg(SLMP_INFO * info)
-{
-	unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
-	return *RegAddr;
-}
-
-static void write_control_reg(SLMP_INFO * info)
-{
-	unsigned char *RegAddr = (unsigned char *)info->statctrl_base;
-	*RegAddr = info->port_array[0]->ctrlreg_value;
-}
-
-
-static int __devinit synclinkmp_init_one (struct pci_dev *dev,
-					  const struct pci_device_id *ent)
-{
-	if (pci_enable_device(dev)) {
-		printk("error enabling pci device %p\n", dev);
-		return -EIO;
-	}
-	device_init( ++synclinkmp_adapter_count, dev );
-	return 0;
-}
-
-static void __devexit synclinkmp_remove_one (struct pci_dev *dev)
-{
-}
diff -druN linux-libre-2.6.38-gnu/drivers/char/tpm/tpm.c linux-libre-2.6.39-gnu/drivers/char/tpm/tpm.c
--- linux-libre-2.6.38-gnu/drivers/char/tpm/tpm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/tpm/tpm.c	2011-05-19 00:06:34.000000000 -0400
@@ -980,7 +980,7 @@
 		return -EBUSY;
 	}
 
-	chip->data_buffer = kmalloc(TPM_BUFSIZE * sizeof(u8), GFP_KERNEL);
+	chip->data_buffer = kzalloc(TPM_BUFSIZE, GFP_KERNEL);
 	if (chip->data_buffer == NULL) {
 		clear_bit(0, &chip->is_open);
 		put_device(chip->dev);
diff -druN linux-libre-2.6.38-gnu/drivers/char/ttyprintk.c linux-libre-2.6.39-gnu/drivers/char/ttyprintk.c
--- linux-libre-2.6.38-gnu/drivers/char/ttyprintk.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/ttyprintk.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,7 +144,7 @@
 /*
  * TTY operations ioctl function.
  */
-static int tpk_ioctl(struct tty_struct *tty, struct file *file,
+static int tpk_ioctl(struct tty_struct *tty,
 			unsigned int cmd, unsigned long arg)
 {
 	struct ttyprintk_port *tpkp = tty->driver_data;
diff -druN linux-libre-2.6.38-gnu/drivers/char/virtio_console.c linux-libre-2.6.39-gnu/drivers/char/virtio_console.c
--- linux-libre-2.6.38-gnu/drivers/char/virtio_console.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/virtio_console.c	2011-05-19 00:06:34.000000000 -0400
@@ -1280,18 +1280,7 @@
 		spin_lock_irq(&pdrvdata_lock);
 		list_del(&port->cons.list);
 		spin_unlock_irq(&pdrvdata_lock);
-#if 0
-		/*
-		 * hvc_remove() not called as removing one hvc port
-		 * results in other hvc ports getting frozen.
-		 *
-		 * Once this is resolved in hvc, this functionality
-		 * will be enabled.  Till that is done, the -EPIPE
-		 * return from get_chars() above will help
-		 * hvc_console.c to clean up on ports we remove here.
-		 */
 		hvc_remove(port->cons.hvc);
-#endif
 	}
 
 	/* Remove unused data this port might have received. */
diff -druN linux-libre-2.6.38-gnu/drivers/char/vme_scc.c linux-libre-2.6.39-gnu/drivers/char/vme_scc.c
--- linux-libre-2.6.38-gnu/drivers/char/vme_scc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/vme_scc.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1145 +0,0 @@
-/*
- * drivers/char/vme_scc.c: MVME147, MVME162, BVME6000 SCC serial ports
- * implementation.
- * Copyright 1999 Richard Hirst <richard@sleepie.demon.co.uk>
- *
- * Based on atari_SCC.c which was
- *   Copyright 1994-95 Roman Hodek <Roman.Hodek@informatik.uni-erlangen.de>
- *   Partially based on PC-Linux serial.c by Linus Torvalds and Theodore Ts'o
- *
- * 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/kdev_t.h>
-#include <asm/io.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/interrupt.h>
-#include <linux/errno.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/mm.h>
-#include <linux/serial.h>
-#include <linux/fcntl.h>
-#include <linux/major.h>
-#include <linux/delay.h>
-#include <linux/miscdevice.h>
-#include <linux/console.h>
-#include <linux/init.h>
-#include <asm/setup.h>
-#include <asm/bootinfo.h>
-
-#ifdef CONFIG_MVME147_SCC
-#include <asm/mvme147hw.h>
-#endif
-#ifdef CONFIG_MVME162_SCC
-#include <asm/mvme16xhw.h>
-#endif
-#ifdef CONFIG_BVME6000_SCC
-#include <asm/bvme6000hw.h>
-#endif
-
-#include <linux/generic_serial.h>
-#include "scc.h"
-
-
-#define CHANNEL_A	0
-#define CHANNEL_B	1
-
-#define SCC_MINOR_BASE	64
-
-/* Shadows for all SCC write registers */
-static unsigned char scc_shadow[2][16];
-
-/* Location to access for SCC register access delay */
-static volatile unsigned char *scc_del = NULL;
-
-/* To keep track of STATUS_REG state for detection of Ext/Status int source */
-static unsigned char scc_last_status_reg[2];
-
-/***************************** Prototypes *****************************/
-
-/* Function prototypes */
-static void scc_disable_tx_interrupts(void * ptr);
-static void scc_enable_tx_interrupts(void * ptr);
-static void scc_disable_rx_interrupts(void * ptr);
-static void scc_enable_rx_interrupts(void * ptr);
-static int  scc_carrier_raised(struct tty_port *port);
-static void scc_shutdown_port(void * ptr);
-static int scc_set_real_termios(void  *ptr);
-static void scc_hungup(void  *ptr);
-static void scc_close(void  *ptr);
-static int scc_chars_in_buffer(void * ptr);
-static int scc_open(struct tty_struct * tty, struct file * filp);
-static int scc_ioctl(struct tty_struct * tty, struct file * filp,
-                     unsigned int cmd, unsigned long arg);
-static void scc_throttle(struct tty_struct *tty);
-static void scc_unthrottle(struct tty_struct *tty);
-static irqreturn_t scc_tx_int(int irq, void *data);
-static irqreturn_t scc_rx_int(int irq, void *data);
-static irqreturn_t scc_stat_int(int irq, void *data);
-static irqreturn_t scc_spcond_int(int irq, void *data);
-static void scc_setsignals(struct scc_port *port, int dtr, int rts);
-static int scc_break_ctl(struct tty_struct *tty, int break_state);
-
-static struct tty_driver *scc_driver;
-
-static struct scc_port scc_ports[2];
-
-/*---------------------------------------------------------------------------
- * Interface from generic_serial.c back here
- *--------------------------------------------------------------------------*/
-
-static struct real_driver scc_real_driver = {
-        scc_disable_tx_interrupts,
-        scc_enable_tx_interrupts,
-        scc_disable_rx_interrupts,
-        scc_enable_rx_interrupts,
-        scc_shutdown_port,
-        scc_set_real_termios,
-        scc_chars_in_buffer,
-        scc_close,
-        scc_hungup,
-        NULL
-};
-
-
-static const struct tty_operations scc_ops = {
-	.open	= scc_open,
-	.close = gs_close,
-	.write = gs_write,
-	.put_char = gs_put_char,
-	.flush_chars = gs_flush_chars,
-	.write_room = gs_write_room,
-	.chars_in_buffer = gs_chars_in_buffer,
-	.flush_buffer = gs_flush_buffer,
-	.ioctl = scc_ioctl,
-	.throttle = scc_throttle,
-	.unthrottle = scc_unthrottle,
-	.set_termios = gs_set_termios,
-	.stop = gs_stop,
-	.start = gs_start,
-	.hangup = gs_hangup,
-	.break_ctl = scc_break_ctl,
-};
-
-static const struct tty_port_operations scc_port_ops = {
-	.carrier_raised = scc_carrier_raised,
-};
-
-/*----------------------------------------------------------------------------
- * vme_scc_init() and support functions
- *---------------------------------------------------------------------------*/
-
-static int __init scc_init_drivers(void)
-{
-	int error;
-
-	scc_driver = alloc_tty_driver(2);
-	if (!scc_driver)
-		return -ENOMEM;
-	scc_driver->owner = THIS_MODULE;
-	scc_driver->driver_name = "scc";
-	scc_driver->name = "ttyS";
-	scc_driver->major = TTY_MAJOR;
-	scc_driver->minor_start = SCC_MINOR_BASE;
-	scc_driver->type = TTY_DRIVER_TYPE_SERIAL;
-	scc_driver->subtype = SERIAL_TYPE_NORMAL;
-	scc_driver->init_termios = tty_std_termios;
-	scc_driver->init_termios.c_cflag =
-	  B9600 | CS8 | CREAD | HUPCL | CLOCAL;
-	scc_driver->init_termios.c_ispeed = 9600;
-	scc_driver->init_termios.c_ospeed = 9600;
-	scc_driver->flags = TTY_DRIVER_REAL_RAW;
-	tty_set_operations(scc_driver, &scc_ops);
-
-	if ((error = tty_register_driver(scc_driver))) {
-		printk(KERN_ERR "scc: Couldn't register scc driver, error = %d\n",
-		       error);
-		put_tty_driver(scc_driver);
-		return 1;
-	}
-
-	return 0;
-}
-
-
-/* ports[] array is indexed by line no (i.e. [0] for ttyS0, [1] for ttyS1).
- */
-
-static void __init scc_init_portstructs(void)
-{
-	struct scc_port *port;
-	int i;
-
-	for (i = 0; i < 2; i++) {
-		port = scc_ports + i;
-		tty_port_init(&port->gs.port);
-		port->gs.port.ops = &scc_port_ops;
-		port->gs.magic = SCC_MAGIC;
-		port->gs.close_delay = HZ/2;
-		port->gs.closing_wait = 30 * HZ;
-		port->gs.rd = &scc_real_driver;
-#ifdef NEW_WRITE_LOCKING
-		port->gs.port_write_mutex = MUTEX;
-#endif
-		init_waitqueue_head(&port->gs.port.open_wait);
-		init_waitqueue_head(&port->gs.port.close_wait);
-	}
-}
-
-
-#ifdef CONFIG_MVME147_SCC
-static int __init mvme147_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	printk(KERN_INFO "SCC: MVME147 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)M147_SCC_A_ADDR;
-	port->datap = port->ctrlp + 1;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME147_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(MVME147_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(MVME147_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(MVME147_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, MVME147_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)M147_SCC_B_ADDR;
-	port->datap = port->ctrlp + 1;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME147_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(MVME147_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(MVME147_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(MVME147_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-        /* Ensure interrupts are enabled in the PCC chip */
-        m147_pcc->serial_cntrl=PCC_LEVEL_SERIAL|PCC_INT_ENAB;
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail_free_b_rx:
-	free_irq(MVME147_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(MVME147_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(MVME147_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(MVME147_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(MVME147_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(MVME147_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(MVME147_IRQ_SCCA_TX, port);
-fail:
-	return error;
-}
-#endif
-
-
-#ifdef CONFIG_MVME162_SCC
-static int __init mvme162_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	if (!(mvme16x_config & MVME16x_CONFIG_GOT_SCCA))
-		return (-ENODEV);
-
-	printk(KERN_INFO "SCC: MVME162 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)MVME_SCC_A_ADDR;
-	port->datap = port->ctrlp + 2;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME162_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(MVME162_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(MVME162_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(MVME162_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, MVME162_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)MVME_SCC_B_ADDR;
-	port->datap = port->ctrlp + 2;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(MVME162_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(MVME162_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(MVME162_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(MVME162_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);	/* Either channel will do */
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-        /* Ensure interrupts are enabled in the MC2 chip */
-        *(volatile char *)0xfff4201d = 0x14;
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail_free_b_rx:
-	free_irq(MVME162_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(MVME162_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(MVME162_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(MVME162_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(MVME162_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(MVME162_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(MVME162_IRQ_SCCA_TX, port);
-fail:
-	return error;
-}
-#endif
-
-
-#ifdef CONFIG_BVME6000_SCC
-static int __init bvme6000_scc_init(void)
-{
-	struct scc_port *port;
-	int error;
-
-	printk(KERN_INFO "SCC: BVME6000 Serial Driver\n");
-	/* Init channel A */
-	port = &scc_ports[0];
-	port->channel = CHANNEL_A;
-	port->ctrlp = (volatile unsigned char *)BVME_SCC_A_ADDR;
-	port->datap = port->ctrlp + 4;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(BVME_IRQ_SCCA_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-A TX", port);
-	if (error)
-		goto fail;
-	error = request_irq(BVME_IRQ_SCCA_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-A status", port);
-	if (error)
-		goto fail_free_a_tx;
-	error = request_irq(BVME_IRQ_SCCA_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-A RX", port);
-	if (error)
-		goto fail_free_a_stat;
-	error = request_irq(BVME_IRQ_SCCA_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-A special cond", port);
-	if (error)
-		goto fail_free_a_rx;
-
-	{
-		SCC_ACCESS_INIT(port);
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-		/* Set the interrupt vector */
-		SCCwrite(INT_VECTOR_REG, BVME_IRQ_SCC_BASE);
-		/* Interrupt parameters: vector includes status, status low */
-		SCCwrite(MASTER_INT_CTRL, MIC_VEC_INCL_STAT);
-		SCCmod(MASTER_INT_CTRL, 0xff, MIC_MASTER_INT_ENAB);
-	}
-
-	/* Init channel B */
-	port = &scc_ports[1];
-	port->channel = CHANNEL_B;
-	port->ctrlp = (volatile unsigned char *)BVME_SCC_B_ADDR;
-	port->datap = port->ctrlp + 4;
-	port->port_a = &scc_ports[0];
-	port->port_b = &scc_ports[1];
-	error = request_irq(BVME_IRQ_SCCB_TX, scc_tx_int, IRQF_DISABLED,
-		            "SCC-B TX", port);
-	if (error)
-		goto fail_free_a_spcond;
-	error = request_irq(BVME_IRQ_SCCB_STAT, scc_stat_int, IRQF_DISABLED,
-		            "SCC-B status", port);
-	if (error)
-		goto fail_free_b_tx;
-	error = request_irq(BVME_IRQ_SCCB_RX, scc_rx_int, IRQF_DISABLED,
-		            "SCC-B RX", port);
-	if (error)
-		goto fail_free_b_stat;
-	error = request_irq(BVME_IRQ_SCCB_SPCOND, scc_spcond_int,
-			    IRQF_DISABLED, "SCC-B special cond", port);
-	if (error)
-		goto fail_free_b_rx;
-
-	{
-		SCC_ACCESS_INIT(port);	/* Either channel will do */
-
-		/* disable interrupts for this channel */
-		SCCwrite(INT_AND_DMA_REG, 0);
-	}
-
-	/* Initialise the tty driver structures and register */
-	scc_init_portstructs();
-	scc_init_drivers();
-
-	return 0;
-
-fail:
-	free_irq(BVME_IRQ_SCCA_STAT, port);
-fail_free_a_tx:
-	free_irq(BVME_IRQ_SCCA_RX, port);
-fail_free_a_stat:
-	free_irq(BVME_IRQ_SCCA_SPCOND, port);
-fail_free_a_rx:
-	free_irq(BVME_IRQ_SCCB_TX, port);
-fail_free_a_spcond:
-	free_irq(BVME_IRQ_SCCB_STAT, port);
-fail_free_b_tx:
-	free_irq(BVME_IRQ_SCCB_RX, port);
-fail_free_b_stat:
-	free_irq(BVME_IRQ_SCCB_SPCOND, port);
-fail_free_b_rx:
-	return error;
-}
-#endif
-
-
-static int __init vme_scc_init(void)
-{
-	int res = -ENODEV;
-
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		res = mvme147_scc_init();
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		res = mvme162_scc_init();
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		res = bvme6000_scc_init();
-#endif
-	return res;
-}
-
-module_init(vme_scc_init);
-
-
-/*---------------------------------------------------------------------------
- * Interrupt handlers
- *--------------------------------------------------------------------------*/
-
-static irqreturn_t scc_rx_int(int irq, void *data)
-{
-	unsigned char	ch;
-	struct scc_port *port = data;
-	struct tty_struct *tty = port->gs.port.tty;
-	SCC_ACCESS_INIT(port);
-
-	ch = SCCread_NB(RX_DATA_REG);
-	if (!tty) {
-		printk(KERN_WARNING "scc_rx_int with NULL tty!\n");
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	tty_insert_flip_char(tty, ch, 0);
-
-	/* Check if another character is already ready; in that case, the
-	 * spcond_int() function must be used, because this character may have an
-	 * error condition that isn't signalled by the interrupt vector used!
-	 */
-	if (SCCread(INT_PENDING_REG) &
-	    (port->channel == CHANNEL_A ? IPR_A_RX : IPR_B_RX)) {
-		scc_spcond_int (irq, data);
-		return IRQ_HANDLED;
-	}
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_spcond_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	struct tty_struct *tty = port->gs.port.tty;
-	unsigned char	stat, ch, err;
-	int		int_pending_mask = port->channel == CHANNEL_A ?
-			                   IPR_A_RX : IPR_B_RX;
-	SCC_ACCESS_INIT(port);
-	
-	if (!tty) {
-		printk(KERN_WARNING "scc_spcond_int with NULL tty!\n");
-		SCCwrite(COMMAND_REG, CR_ERROR_RESET);
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	do {
-		stat = SCCread(SPCOND_STATUS_REG);
-		ch = SCCread_NB(RX_DATA_REG);
-
-		if (stat & SCSR_RX_OVERRUN)
-			err = TTY_OVERRUN;
-		else if (stat & SCSR_PARITY_ERR)
-			err = TTY_PARITY;
-		else if (stat & SCSR_CRC_FRAME_ERR)
-			err = TTY_FRAME;
-		else
-			err = 0;
-
-		tty_insert_flip_char(tty, ch, err);
-
-		/* ++TeSche: *All* errors have to be cleared manually,
-		 * else the condition persists for the next chars
-		 */
-		if (err)
-		  SCCwrite(COMMAND_REG, CR_ERROR_RESET);
-
-	} while(SCCread(INT_PENDING_REG) & int_pending_mask);
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-
-	tty_flip_buffer_push(tty);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_tx_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	SCC_ACCESS_INIT(port);
-
-	if (!port->gs.port.tty) {
-		printk(KERN_WARNING "scc_tx_int with NULL tty!\n");
-		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);
-		SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-		return IRQ_HANDLED;
-	}
-	while ((SCCread_NB(STATUS_REG) & SR_TX_BUF_EMPTY)) {
-		if (port->x_char) {
-			SCCwrite(TX_DATA_REG, port->x_char);
-			port->x_char = 0;
-		}
-		else if ((port->gs.xmit_cnt <= 0) ||
-			 port->gs.port.tty->stopped ||
-			 port->gs.port.tty->hw_stopped)
-			break;
-		else {
-			SCCwrite(TX_DATA_REG, port->gs.xmit_buf[port->gs.xmit_tail++]);
-			port->gs.xmit_tail = port->gs.xmit_tail & (SERIAL_XMIT_SIZE-1);
-			if (--port->gs.xmit_cnt <= 0)
-				break;
-		}
-	}
-	if ((port->gs.xmit_cnt <= 0) || port->gs.port.tty->stopped ||
-	    port->gs.port.tty->hw_stopped) {
-		/* disable tx interrupts */
-		SCCmod (INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-		SCCwrite(COMMAND_REG, CR_TX_PENDING_RESET);   /* disable tx_int on next tx underrun? */
-		port->gs.port.flags &= ~GS_TX_INTEN;
-	}
-	if (port->gs.port.tty && port->gs.xmit_cnt <= port->gs.wakeup_chars)
-		tty_wakeup(port->gs.port.tty);
-
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-	return IRQ_HANDLED;
-}
-
-
-static irqreturn_t scc_stat_int(int irq, void *data)
-{
-	struct scc_port *port = data;
-	unsigned channel = port->channel;
-	unsigned char	last_sr, sr, changed;
-	SCC_ACCESS_INIT(port);
-
-	last_sr = scc_last_status_reg[channel];
-	sr = scc_last_status_reg[channel] = SCCread_NB(STATUS_REG);
-	changed = last_sr ^ sr;
-
-	if (changed & SR_DCD) {
-		port->c_dcd = !!(sr & SR_DCD);
-		if (!(port->gs.port.flags & ASYNC_CHECK_CD))
-			;	/* Don't report DCD changes */
-		else if (port->c_dcd) {
-			wake_up_interruptible(&port->gs.port.open_wait);
-		}
-		else {
-			if (port->gs.port.tty)
-				tty_hangup (port->gs.port.tty);
-		}
-	}
-	SCCwrite(COMMAND_REG, CR_EXTSTAT_RESET);
-	SCCwrite_NB(COMMAND_REG, CR_HIGHEST_IUS_RESET);
-	return IRQ_HANDLED;
-}
-
-
-/*---------------------------------------------------------------------------
- * generic_serial.c callback funtions
- *--------------------------------------------------------------------------*/
-
-static void scc_disable_tx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, ~IDR_TX_INT_ENAB, 0);
-	port->gs.port.flags &= ~GS_TX_INTEN;
-	local_irq_restore(flags);
-}
-
-
-static void scc_enable_tx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, 0xff, IDR_TX_INT_ENAB);
-	/* restart the transmitter */
-	scc_tx_int (0, port);
-	local_irq_restore(flags);
-}
-
-
-static void scc_disable_rx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG,
-	    ~(IDR_RX_INT_MASK|IDR_PARERR_AS_SPCOND|IDR_EXTSTAT_INT_ENAB), 0);
-	local_irq_restore(flags);
-}
-
-
-static void scc_enable_rx_interrupts(void *ptr)
-{
-	struct scc_port *port = ptr;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(INT_AND_DMA_REG, 0xff,
-		IDR_EXTSTAT_INT_ENAB|IDR_PARERR_AS_SPCOND|IDR_RX_INT_ALL);
-	local_irq_restore(flags);
-}
-
-
-static int scc_carrier_raised(struct tty_port *port)
-{
-	struct scc_port *sc = container_of(port, struct scc_port, gs.port);
-	unsigned channel = sc->channel;
-
-	return !!(scc_last_status_reg[channel] & SR_DCD);
-}
-
-
-static void scc_shutdown_port(void *ptr)
-{
-	struct scc_port *port = ptr;
-
-	port->gs.port.flags &= ~ GS_ACTIVE;
-	if (port->gs.port.tty && (port->gs.port.tty->termios->c_cflag & HUPCL)) {
-		scc_setsignals (port, 0, 0);
-	}
-}
-
-
-static int scc_set_real_termios (void *ptr)
-{
-	/* the SCC has char sizes 5,7,6,8 in that order! */
-	static int chsize_map[4] = { 0, 2, 1, 3 };
-	unsigned cflag, baud, chsize, channel, brgval = 0;
-	unsigned long flags;
-	struct scc_port *port = ptr;
-	SCC_ACCESS_INIT(port);
-
-	if (!port->gs.port.tty || !port->gs.port.tty->termios) return 0;
-
-	channel = port->channel;
-
-	if (channel == CHANNEL_A)
-		return 0;		/* Settings controlled by boot PROM */
-
-	cflag  = port->gs.port.tty->termios->c_cflag;
-	baud = port->gs.baud;
-	chsize = (cflag & CSIZE) >> 4;
-
-	if (baud == 0) {
-		/* speed == 0 -> drop DTR */
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, ~TCR_DTR, 0);
-		local_irq_restore(flags);
-		return 0;
-	}
-	else if ((MACH_IS_MVME16x && (baud < 50 || baud > 38400)) ||
-		 (MACH_IS_MVME147 && (baud < 50 || baud > 19200)) ||
-		 (MACH_IS_BVME6000 &&(baud < 50 || baud > 76800))) {
-		printk(KERN_NOTICE "SCC: Bad speed requested, %d\n", baud);
-		return 0;
-	}
-
-	if (cflag & CLOCAL)
-		port->gs.port.flags &= ~ASYNC_CHECK_CD;
-	else
-		port->gs.port.flags |= ASYNC_CHECK_CD;
-
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		brgval = (M147_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		brgval = (MVME_SCC_PCLK + baud/2) / (16 * 2 * baud) - 2;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		brgval = (BVME_SCC_RTxC + baud/2) / (16 * 2 * baud) - 2;
-#endif
-	/* Now we have all parameters and can go to set them: */
-	local_irq_save(flags);
-
-	/* receiver's character size and auto-enables */
-	SCCmod(RX_CTRL_REG, ~(RCR_CHSIZE_MASK|RCR_AUTO_ENAB_MODE),
-			(chsize_map[chsize] << 6) |
-			((cflag & CRTSCTS) ? RCR_AUTO_ENAB_MODE : 0));
-	/* parity and stop bits (both, Tx and Rx), clock mode never changes */
-	SCCmod (AUX1_CTRL_REG,
-		~(A1CR_PARITY_MASK | A1CR_MODE_MASK),
-		((cflag & PARENB
-		  ? (cflag & PARODD ? A1CR_PARITY_ODD : A1CR_PARITY_EVEN)
-		  : A1CR_PARITY_NONE)
-		 | (cflag & CSTOPB ? A1CR_MODE_ASYNC_2 : A1CR_MODE_ASYNC_1)));
-	/* sender's character size, set DTR for valid baud rate */
-	SCCmod(TX_CTRL_REG, ~TCR_CHSIZE_MASK, chsize_map[chsize] << 5 | TCR_DTR);
-	/* clock sources never change */
-	/* disable BRG before changing the value */
-	SCCmod(DPLL_CTRL_REG, ~DCR_BRG_ENAB, 0);
-	/* BRG value */
-	SCCwrite(TIMER_LOW_REG, brgval & 0xff);
-	SCCwrite(TIMER_HIGH_REG, (brgval >> 8) & 0xff);
-	/* BRG enable, and clock source never changes */
-	SCCmod(DPLL_CTRL_REG, 0xff, DCR_BRG_ENAB);
-
-	local_irq_restore(flags);
-
-	return 0;
-}
-
-
-static int scc_chars_in_buffer (void *ptr)
-{
-	struct scc_port *port = ptr;
-	SCC_ACCESS_INIT(port);
-
-	return (SCCread (SPCOND_STATUS_REG) & SCSR_ALL_SENT) ? 0  : 1;
-}
-
-
-/* Comment taken from sx.c (2.4.0):
-   I haven't the foggiest why the decrement use count has to happen
-   here. The whole linux serial drivers stuff needs to be redesigned.
-   My guess is that this is a hack to minimize the impact of a bug
-   elsewhere. Thinking about it some more. (try it sometime) Try
-   running minicom on a serial port that is driven by a modularized
-   driver. Have the modem hangup. Then remove the driver module. Then
-   exit minicom.  I expect an "oops".  -- REW */
-
-static void scc_hungup(void *ptr)
-{
-	scc_disable_tx_interrupts(ptr);
-	scc_disable_rx_interrupts(ptr);
-}
-
-
-static void scc_close(void *ptr)
-{
-	scc_disable_tx_interrupts(ptr);
-	scc_disable_rx_interrupts(ptr);
-}
-
-
-/*---------------------------------------------------------------------------
- * Internal support functions
- *--------------------------------------------------------------------------*/
-
-static void scc_setsignals(struct scc_port *port, int dtr, int rts)
-{
-	unsigned long flags;
-	unsigned char t;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	t = SCCread(TX_CTRL_REG);
-	if (dtr >= 0) t = dtr? (t | TCR_DTR): (t & ~TCR_DTR);
-	if (rts >= 0) t = rts? (t | TCR_RTS): (t & ~TCR_RTS);
-	SCCwrite(TX_CTRL_REG, t);
-	local_irq_restore(flags);
-}
-
-
-static void scc_send_xchar(struct tty_struct *tty, char ch)
-{
-	struct scc_port *port = tty->driver_data;
-
-	port->x_char = ch;
-	if (ch)
-		scc_enable_tx_interrupts(port);
-}
-
-
-/*---------------------------------------------------------------------------
- * Driver entrypoints referenced from above
- *--------------------------------------------------------------------------*/
-
-static int scc_open (struct tty_struct * tty, struct file * filp)
-{
-	int line = tty->index;
-	int retval;
-	struct scc_port *port = &scc_ports[line];
-	int i, channel = port->channel;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-#if defined(CONFIG_MVME162_SCC) || defined(CONFIG_MVME147_SCC)
-	static const struct {
-		unsigned reg, val;
-	} mvme_init_tab[] = {
-		/* Values for MVME162 and MVME147 */
-		/* no parity, 1 stop bit, async, 1:16 */
-		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
-		/* parity error is special cond, ints disabled, no DMA */
-		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
-		/* Rx 8 bits/char, no auto enable, Rx off */
-		{ RX_CTRL_REG, RCR_CHSIZE_8 },
-		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
-		{ TX_CTRL_REG, TCR_CHSIZE_8 },
-		/* special features off */
-		{ AUX2_CTRL_REG, 0 },
-		{ CLK_CTRL_REG, CCR_RXCLK_BRG | CCR_TXCLK_BRG },
-		{ DPLL_CTRL_REG, DCR_BRG_ENAB | DCR_BRG_USE_PCLK },
-		/* Start Rx */
-		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
-		/* Start Tx */
-		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
-		/* Ext/Stat ints: DCD only */
-		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
-		/* Reset Ext/Stat ints */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-		/* ...again */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-	};
-#endif
-#if defined(CONFIG_BVME6000_SCC)
-	static const struct {
-		unsigned reg, val;
-	} bvme_init_tab[] = {
-		/* Values for BVME6000 */
-		/* no parity, 1 stop bit, async, 1:16 */
-		{ AUX1_CTRL_REG, A1CR_PARITY_NONE|A1CR_MODE_ASYNC_1|A1CR_CLKMODE_x16 },
-		/* parity error is special cond, ints disabled, no DMA */
-		{ INT_AND_DMA_REG, IDR_PARERR_AS_SPCOND | IDR_RX_INT_DISAB },
-		/* Rx 8 bits/char, no auto enable, Rx off */
-		{ RX_CTRL_REG, RCR_CHSIZE_8 },
-		/* DTR off, Tx 8 bits/char, RTS off, Tx off */
-		{ TX_CTRL_REG, TCR_CHSIZE_8 },
-		/* special features off */
-		{ AUX2_CTRL_REG, 0 },
-		{ CLK_CTRL_REG, CCR_RTxC_XTAL | CCR_RXCLK_BRG | CCR_TXCLK_BRG },
-		{ DPLL_CTRL_REG, DCR_BRG_ENAB },
-		/* Start Rx */
-		{ RX_CTRL_REG, RCR_RX_ENAB | RCR_CHSIZE_8 },
-		/* Start Tx */
-		{ TX_CTRL_REG, TCR_TX_ENAB | TCR_RTS | TCR_DTR | TCR_CHSIZE_8 },
-		/* Ext/Stat ints: DCD only */
-		{ INT_CTRL_REG, ICR_ENAB_DCD_INT },
-		/* Reset Ext/Stat ints */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-		/* ...again */
-		{ COMMAND_REG, CR_EXTSTAT_RESET },
-	};
-#endif
-	if (!(port->gs.port.flags & ASYNC_INITIALIZED)) {
-		local_irq_save(flags);
-#if defined(CONFIG_MVME147_SCC) || defined(CONFIG_MVME162_SCC)
-		if (MACH_IS_MVME147 || MACH_IS_MVME16x) {
-			for (i = 0; i < ARRAY_SIZE(mvme_init_tab); ++i)
-				SCCwrite(mvme_init_tab[i].reg, mvme_init_tab[i].val);
-		}
-#endif
-#if defined(CONFIG_BVME6000_SCC)
-		if (MACH_IS_BVME6000) {
-			for (i = 0; i < ARRAY_SIZE(bvme_init_tab); ++i)
-				SCCwrite(bvme_init_tab[i].reg, bvme_init_tab[i].val);
-		}
-#endif
-
-		/* remember status register for detection of DCD and CTS changes */
-		scc_last_status_reg[channel] = SCCread(STATUS_REG);
-
-		port->c_dcd = 0;	/* Prevent initial 1->0 interrupt */
-		scc_setsignals (port, 1,1);
-		local_irq_restore(flags);
-	}
-
-	tty->driver_data = port;
-	port->gs.port.tty = tty;
-	port->gs.port.count++;
-	retval = gs_init_port(&port->gs);
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-	port->gs.port.flags |= GS_ACTIVE;
-	retval = gs_block_til_ready(port, filp);
-
-	if (retval) {
-		port->gs.port.count--;
-		return retval;
-	}
-
-	port->c_dcd = tty_port_carrier_raised(&port->gs.port);
-
-	scc_enable_rx_interrupts(port);
-
-	return 0;
-}
-
-
-static void scc_throttle (struct tty_struct * tty)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, ~TCR_RTS, 0);
-		local_irq_restore(flags);
-	}
-	if (I_IXOFF(tty))
-		scc_send_xchar(tty, STOP_CHAR(tty));
-}
-
-
-static void scc_unthrottle (struct tty_struct * tty)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	if (tty->termios->c_cflag & CRTSCTS) {
-		local_irq_save(flags);
-		SCCmod(TX_CTRL_REG, 0xff, TCR_RTS);
-		local_irq_restore(flags);
-	}
-	if (I_IXOFF(tty))
-		scc_send_xchar(tty, START_CHAR(tty));
-}
-
-
-static int scc_ioctl(struct tty_struct *tty, struct file *file,
-		     unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
-
-static int scc_break_ctl(struct tty_struct *tty, int break_state)
-{
-	struct scc_port *port = tty->driver_data;
-	unsigned long	flags;
-	SCC_ACCESS_INIT(port);
-
-	local_irq_save(flags);
-	SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 
-			break_state ? TCR_SEND_BREAK : 0);
-	local_irq_restore(flags);
-	return 0;
-}
-
-
-/*---------------------------------------------------------------------------
- * Serial console stuff...
- *--------------------------------------------------------------------------*/
-
-#define scc_delay() do { __asm__ __volatile__ (" nop; nop"); } while (0)
-
-static void scc_ch_write (char ch)
-{
-	volatile char *p = NULL;
-	
-#ifdef CONFIG_MVME147_SCC
-	if (MACH_IS_MVME147)
-		p = (volatile char *)M147_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_MVME162_SCC
-	if (MACH_IS_MVME16x)
-		p = (volatile char *)MVME_SCC_A_ADDR;
-#endif
-#ifdef CONFIG_BVME6000_SCC
-	if (MACH_IS_BVME6000)
-		p = (volatile char *)BVME_SCC_A_ADDR;
-#endif
-
-	do {
-		scc_delay();
-	}
-	while (!(*p & 4));
-	scc_delay();
-	*p = 8;
-	scc_delay();
-	*p = ch;
-}
-
-/* The console must be locked when we get here. */
-
-static void scc_console_write (struct console *co, const char *str, unsigned count)
-{
-	unsigned long	flags;
-
-	local_irq_save(flags);
-
-	while (count--)
-	{
-		if (*str == '\n')
-			scc_ch_write ('\r');
-		scc_ch_write (*str++);
-	}
-	local_irq_restore(flags);
-}
-
-static struct tty_driver *scc_console_device(struct console *c, int *index)
-{
-	*index = c->index;
-	return scc_driver;
-}
-
-static struct console sercons = {
-	.name		= "ttyS",
-	.write		= scc_console_write,
-	.device		= scc_console_device,
-	.flags		= CON_PRINTBUFFER,
-	.index		= -1,
-};
-
-
-static int __init vme_scc_console_init(void)
-{
-	if (vme_brdtype == VME_TYPE_MVME147 ||
-			vme_brdtype == VME_TYPE_MVME162 ||
-			vme_brdtype == VME_TYPE_MVME172 ||
-			vme_brdtype == VME_TYPE_BVME4000 ||
-			vme_brdtype == VME_TYPE_BVME6000)
-		register_console(&sercons);
-	return 0;
-}
-console_initcall(vme_scc_console_init);
diff -druN linux-libre-2.6.38-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c linux-libre-2.6.39-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c
--- linux-libre-2.6.38-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/char/xilinx_hwicap/xilinx_hwicap.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
  * cp foo.bit /dev/icap0
  *
  * Note that unless foo.bit is an appropriately constructed partial
- * bitstream, this has a high likelyhood of overwriting the design
+ * bitstream, this has a high likelihood of overwriting the design
  * currently programmed in the FPGA.
  */
 
@@ -714,20 +714,29 @@
 	return 0;		/* success */
 }
 
-static int __devinit hwicap_drv_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int __devinit hwicap_of_probe(struct platform_device *op,
+				     const struct hwicap_driver_config *config)
 {
-	struct resource *res;
-	const struct config_registers *regs;
+	struct resource res;
+	const unsigned int *id;
 	const char *family;
+	int rc;
+	const struct config_registers *regs;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res)
-		return -ENODEV;
+
+	rc = of_address_to_resource(op->dev.of_node, 0, &res);
+	if (rc) {
+		dev_err(&op->dev, "invalid address\n");
+		return rc;
+	}
+
+	id = of_get_property(op->dev.of_node, "port-number", NULL);
 
 	/* It's most likely that we're using V4, if the family is not
 	   specified */
 	regs = &v4_config_registers;
-	family = pdev->dev.platform_data;
+	family = of_get_property(op->dev.of_node, "xlnx,family", NULL);
 
 	if (family) {
 		if (!strcmp(family, "virtex2p")) {
@@ -738,54 +747,37 @@
 			regs = &v5_config_registers;
 		}
 	}
-
-	return hwicap_setup(&pdev->dev, pdev->id, res,
-			&buffer_icap_config, regs);
+	return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
+			regs);
 }
-
-static int __devexit hwicap_drv_remove(struct platform_device *pdev)
+#else
+static inline int hwicap_of_probe(struct platform_device *op,
+				  const struct hwicap_driver_config *config)
 {
-	return hwicap_remove(&pdev->dev);
+	return -EINVAL;
 }
+#endif /* CONFIG_OF */
 
-static struct platform_driver hwicap_platform_driver = {
-	.probe = hwicap_drv_probe,
-	.remove = hwicap_drv_remove,
-	.driver = {
-		.owner = THIS_MODULE,
-		.name = DRIVER_NAME,
-	},
-};
-
-/* ---------------------------------------------------------------------
- * OF bus binding
- */
-
-#if defined(CONFIG_OF)
-static int __devinit
-hwicap_of_probe(struct platform_device *op, const struct of_device_id *match)
+static const struct of_device_id __devinitconst hwicap_of_match[];
+static int __devinit hwicap_drv_probe(struct platform_device *pdev)
 {
-	struct resource res;
-	const unsigned int *id;
-	const char *family;
-	int rc;
-	const struct hwicap_driver_config *config = match->data;
+	const struct of_device_id *match;
+	struct resource *res;
 	const struct config_registers *regs;
+	const char *family;
 
-	dev_dbg(&op->dev, "hwicap_of_probe(%p, %p)\n", op, match);
-
-	rc = of_address_to_resource(op->dev.of_node, 0, &res);
-	if (rc) {
-		dev_err(&op->dev, "invalid address\n");
-		return rc;
-	}
+	match = of_match_device(hwicap_of_match, &pdev->dev);
+	if (match)
+		return hwicap_of_probe(pdev, match->data);
 
-	id = of_get_property(op->dev.of_node, "port-number", NULL);
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
 
 	/* It's most likely that we're using V4, if the family is not
 	   specified */
 	regs = &v4_config_registers;
-	family = of_get_property(op->dev.of_node, "xlnx,family", NULL);
+	family = pdev->dev.platform_data;
 
 	if (family) {
 		if (!strcmp(family, "virtex2p")) {
@@ -796,50 +788,38 @@
 			regs = &v5_config_registers;
 		}
 	}
-	return hwicap_setup(&op->dev, id ? *id : -1, &res, config,
-			regs);
+
+	return hwicap_setup(&pdev->dev, pdev->id, res,
+			&buffer_icap_config, regs);
 }
 
-static int __devexit hwicap_of_remove(struct platform_device *op)
+static int __devexit hwicap_drv_remove(struct platform_device *pdev)
 {
-	return hwicap_remove(&op->dev);
+	return hwicap_remove(&pdev->dev);
 }
 
-/* Match table for of_platform binding */
+#ifdef CONFIG_OF
+/* Match table for device tree binding */
 static const struct of_device_id __devinitconst hwicap_of_match[] = {
 	{ .compatible = "xlnx,opb-hwicap-1.00.b", .data = &buffer_icap_config},
 	{ .compatible = "xlnx,xps-hwicap-1.00.a", .data = &fifo_icap_config},
 	{},
 };
 MODULE_DEVICE_TABLE(of, hwicap_of_match);
+#else
+#define hwicap_of_match NULL
+#endif
 
-static struct of_platform_driver hwicap_of_driver = {
-	.probe = hwicap_of_probe,
-	.remove = __devexit_p(hwicap_of_remove),
+static struct platform_driver hwicap_platform_driver = {
+	.probe = hwicap_drv_probe,
+	.remove = hwicap_drv_remove,
 	.driver = {
-		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
+		.name = DRIVER_NAME,
 		.of_match_table = hwicap_of_match,
 	},
 };
 
-/* Registration helpers to keep the number of #ifdefs to a minimum */
-static inline int __init hwicap_of_register(void)
-{
-	pr_debug("hwicap: calling of_register_platform_driver()\n");
-	return of_register_platform_driver(&hwicap_of_driver);
-}
-
-static inline void __exit hwicap_of_unregister(void)
-{
-	of_unregister_platform_driver(&hwicap_of_driver);
-}
-#else /* CONFIG_OF */
-/* CONFIG_OF not enabled; do nothing helpers */
-static inline int __init hwicap_of_register(void) { return 0; }
-static inline void __exit hwicap_of_unregister(void) { }
-#endif /* CONFIG_OF */
-
 static int __init hwicap_module_init(void)
 {
 	dev_t devt;
@@ -856,21 +836,12 @@
 		return retval;
 
 	retval = platform_driver_register(&hwicap_platform_driver);
-
-	if (retval)
-		goto failed1;
-
-	retval = hwicap_of_register();
-
 	if (retval)
-		goto failed2;
+		goto failed;
 
 	return retval;
 
- failed2:
-	platform_driver_unregister(&hwicap_platform_driver);
-
- failed1:
+ failed:
 	unregister_chrdev_region(devt, HWICAP_DEVICES);
 
 	return retval;
@@ -884,8 +855,6 @@
 
 	platform_driver_unregister(&hwicap_platform_driver);
 
-	hwicap_of_unregister();
-
 	unregister_chrdev_region(devt, HWICAP_DEVICES);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/clk/clkdev.c linux-libre-2.6.39-gnu/drivers/clk/clkdev.c
--- linux-libre-2.6.38-gnu/drivers/clk/clkdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/clk/clkdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,10 +32,9 @@
  * Then we take the most specific entry - with the following
  * order of precedence: dev+con > dev only > con only.
  */
-static struct clk *clk_find(const char *dev_id, const char *con_id)
+static struct clk_lookup *clk_find(const char *dev_id, const char *con_id)
 {
-	struct clk_lookup *p;
-	struct clk *clk = NULL;
+	struct clk_lookup *p, *cl = NULL;
 	int match, best = 0;
 
 	list_for_each_entry(p, &clocks, node) {
@@ -52,27 +51,27 @@
 		}
 
 		if (match > best) {
-			clk = p->clk;
+			cl = p;
 			if (match != 3)
 				best = match;
 			else
 				break;
 		}
 	}
-	return clk;
+	return cl;
 }
 
 struct clk *clk_get_sys(const char *dev_id, const char *con_id)
 {
-	struct clk *clk;
+	struct clk_lookup *cl;
 
 	mutex_lock(&clocks_mutex);
-	clk = clk_find(dev_id, con_id);
-	if (clk && !__clk_get(clk))
-		clk = NULL;
+	cl = clk_find(dev_id, con_id);
+	if (cl && !__clk_get(cl->clk))
+		cl = NULL;
 	mutex_unlock(&clocks_mutex);
 
-	return clk ? clk : ERR_PTR(-ENOENT);
+	return cl ? cl->clk : ERR_PTR(-ENOENT);
 }
 EXPORT_SYMBOL(clk_get_sys);
 
diff -druN linux-libre-2.6.38-gnu/drivers/connector/cn_queue.c linux-libre-2.6.39-gnu/drivers/connector/cn_queue.c
--- linux-libre-2.6.38-gnu/drivers/connector/cn_queue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/connector/cn_queue.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,24 +31,9 @@
 #include <linux/connector.h>
 #include <linux/delay.h>
 
-void cn_queue_wrapper(struct work_struct *work)
-{
-	struct cn_callback_entry *cbq =
-		container_of(work, struct cn_callback_entry, work);
-	struct cn_callback_data *d = &cbq->data;
-	struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(d->skb));
-	struct netlink_skb_parms *nsp = &NETLINK_CB(d->skb);
-
-	d->callback(msg, nsp);
-
-	kfree_skb(d->skb);
-	d->skb = NULL;
-
-	kfree(d->free);
-}
-
 static struct cn_callback_entry *
-cn_queue_alloc_callback_entry(char *name, struct cb_id *id,
+cn_queue_alloc_callback_entry(struct cn_queue_dev *dev, const char *name,
+			      struct cb_id *id,
 			      void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
 {
 	struct cn_callback_entry *cbq;
@@ -59,17 +44,23 @@
 		return NULL;
 	}
 
+	atomic_set(&cbq->refcnt, 1);
+
+	atomic_inc(&dev->refcnt);
+	cbq->pdev = dev;
+
 	snprintf(cbq->id.name, sizeof(cbq->id.name), "%s", name);
 	memcpy(&cbq->id.id, id, sizeof(struct cb_id));
-	cbq->data.callback = callback;
-
-	INIT_WORK(&cbq->work, &cn_queue_wrapper);
+	cbq->callback = callback;
 	return cbq;
 }
 
-static void cn_queue_free_callback(struct cn_callback_entry *cbq)
+void cn_queue_release_callback(struct cn_callback_entry *cbq)
 {
-	flush_workqueue(cbq->pdev->cn_queue);
+	if (!atomic_dec_and_test(&cbq->refcnt))
+		return;
+
+	atomic_dec(&cbq->pdev->refcnt);
 	kfree(cbq);
 }
 
@@ -78,19 +69,17 @@
 	return ((i1->idx == i2->idx) && (i1->val == i2->val));
 }
 
-int cn_queue_add_callback(struct cn_queue_dev *dev, char *name, struct cb_id *id,
+int cn_queue_add_callback(struct cn_queue_dev *dev, const char *name,
+			  struct cb_id *id,
 			  void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
 {
 	struct cn_callback_entry *cbq, *__cbq;
 	int found = 0;
 
-	cbq = cn_queue_alloc_callback_entry(name, id, callback);
+	cbq = cn_queue_alloc_callback_entry(dev, name, id, callback);
 	if (!cbq)
 		return -ENOMEM;
 
-	atomic_inc(&dev->refcnt);
-	cbq->pdev = dev;
-
 	spin_lock_bh(&dev->queue_lock);
 	list_for_each_entry(__cbq, &dev->queue_list, callback_entry) {
 		if (cn_cb_equal(&__cbq->id.id, id)) {
@@ -103,8 +92,7 @@
 	spin_unlock_bh(&dev->queue_lock);
 
 	if (found) {
-		cn_queue_free_callback(cbq);
-		atomic_dec(&dev->refcnt);
+		cn_queue_release_callback(cbq);
 		return -EINVAL;
 	}
 
@@ -129,13 +117,11 @@
 	}
 	spin_unlock_bh(&dev->queue_lock);
 
-	if (found) {
-		cn_queue_free_callback(cbq);
-		atomic_dec(&dev->refcnt);
-	}
+	if (found)
+		cn_queue_release_callback(cbq);
 }
 
-struct cn_queue_dev *cn_queue_alloc_dev(char *name, struct sock *nls)
+struct cn_queue_dev *cn_queue_alloc_dev(const char *name, struct sock *nls)
 {
 	struct cn_queue_dev *dev;
 
@@ -150,12 +136,6 @@
 
 	dev->nls = nls;
 
-	dev->cn_queue = alloc_ordered_workqueue(dev->name, 0);
-	if (!dev->cn_queue) {
-		kfree(dev);
-		return NULL;
-	}
-
 	return dev;
 }
 
@@ -163,9 +143,6 @@
 {
 	struct cn_callback_entry *cbq, *n;
 
-	flush_workqueue(dev->cn_queue);
-	destroy_workqueue(dev->cn_queue);
-
 	spin_lock_bh(&dev->queue_lock);
 	list_for_each_entry_safe(cbq, n, &dev->queue_list, callback_entry)
 		list_del(&cbq->callback_entry);
diff -druN linux-libre-2.6.38-gnu/drivers/connector/connector.c linux-libre-2.6.39-gnu/drivers/connector/connector.c
--- linux-libre-2.6.38-gnu/drivers/connector/connector.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/connector/connector.c	2011-05-19 00:06:34.000000000 -0400
@@ -122,51 +122,29 @@
  */
 static int cn_call_callback(struct sk_buff *skb)
 {
-	struct cn_callback_entry *__cbq, *__new_cbq;
+	struct cn_callback_entry *i, *cbq = NULL;
 	struct cn_dev *dev = &cdev;
 	struct cn_msg *msg = NLMSG_DATA(nlmsg_hdr(skb));
+	struct netlink_skb_parms *nsp = &NETLINK_CB(skb);
 	int err = -ENODEV;
 
 	spin_lock_bh(&dev->cbdev->queue_lock);
-	list_for_each_entry(__cbq, &dev->cbdev->queue_list, callback_entry) {
-		if (cn_cb_equal(&__cbq->id.id, &msg->id)) {
-			if (likely(!work_pending(&__cbq->work) &&
-					__cbq->data.skb == NULL)) {
-				__cbq->data.skb = skb;
-
-				if (queue_work(dev->cbdev->cn_queue,
-					       &__cbq->work))
-					err = 0;
-				else
-					err = -EINVAL;
-			} else {
-				struct cn_callback_data *d;
-
-				err = -ENOMEM;
-				__new_cbq = kzalloc(sizeof(struct cn_callback_entry), GFP_ATOMIC);
-				if (__new_cbq) {
-					d = &__new_cbq->data;
-					d->skb = skb;
-					d->callback = __cbq->data.callback;
-					d->free = __new_cbq;
-
-					INIT_WORK(&__new_cbq->work,
-							&cn_queue_wrapper);
-
-					if (queue_work(dev->cbdev->cn_queue,
-						       &__new_cbq->work))
-						err = 0;
-					else {
-						kfree(__new_cbq);
-						err = -EINVAL;
-					}
-				}
-			}
+	list_for_each_entry(i, &dev->cbdev->queue_list, callback_entry) {
+		if (cn_cb_equal(&i->id.id, &msg->id)) {
+			atomic_inc(&i->refcnt);
+			cbq = i;
 			break;
 		}
 	}
 	spin_unlock_bh(&dev->cbdev->queue_lock);
 
+	if (cbq != NULL) {
+		cbq->callback(msg, nsp);
+		kfree_skb(skb);
+		cn_queue_release_callback(cbq);
+		err = 0;
+	}
+
 	return err;
 }
 
@@ -205,7 +183,7 @@
  *
  * May sleep.
  */
-int cn_add_callback(struct cb_id *id, char *name,
+int cn_add_callback(struct cb_id *id, const char *name,
 		    void (*callback)(struct cn_msg *, struct netlink_skb_parms *))
 {
 	int err;
diff -druN linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq.c linux-libre-2.6.39-gnu/drivers/cpufreq/cpufreq.c
--- linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cpufreq/cpufreq.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/cpu.h>
 #include <linux/completion.h>
 #include <linux/mutex.h>
+#include <linux/syscore_ops.h>
 
 #include <trace/events/power.h>
 
@@ -1340,50 +1341,45 @@
 }
 EXPORT_SYMBOL(cpufreq_get);
 
+static struct sysdev_driver cpufreq_sysdev_driver = {
+	.add		= cpufreq_add_dev,
+	.remove		= cpufreq_remove_dev,
+};
+
 
 /**
- *	cpufreq_suspend - let the low level driver prepare for suspend
+ * cpufreq_bp_suspend - Prepare the boot CPU for system suspend.
+ *
+ * This function is only executed for the boot processor.  The other CPUs
+ * have been put offline by means of CPU hotplug.
  */
-
-static int cpufreq_suspend(struct sys_device *sysdev, pm_message_t pmsg)
+static int cpufreq_bp_suspend(void)
 {
 	int ret = 0;
 
-	int cpu = sysdev->id;
+	int cpu = smp_processor_id();
 	struct cpufreq_policy *cpu_policy;
 
 	dprintk("suspending cpu %u\n", cpu);
 
-	if (!cpu_online(cpu))
-		return 0;
-
-	/* we may be lax here as interrupts are off. Nonetheless
-	 * we need to grab the correct cpu policy, as to check
-	 * whether we really run on this CPU.
-	 */
-
+	/* If there's no policy for the boot CPU, we have nothing to do. */
 	cpu_policy = cpufreq_cpu_get(cpu);
 	if (!cpu_policy)
-		return -EINVAL;
-
-	/* only handle each CPU group once */
-	if (unlikely(cpu_policy->cpu != cpu))
-		goto out;
+		return 0;
 
 	if (cpufreq_driver->suspend) {
-		ret = cpufreq_driver->suspend(cpu_policy, pmsg);
+		ret = cpufreq_driver->suspend(cpu_policy);
 		if (ret)
 			printk(KERN_ERR "cpufreq: suspend failed in ->suspend "
 					"step on CPU %u\n", cpu_policy->cpu);
 	}
 
-out:
 	cpufreq_cpu_put(cpu_policy);
 	return ret;
 }
 
 /**
- *	cpufreq_resume -  restore proper CPU frequency handling after resume
+ * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU.
  *
  *	1.) resume CPUfreq hardware support (cpufreq_driver->resume())
  *	2.) schedule call cpufreq_update_policy() ASAP as interrupts are
@@ -1391,31 +1387,23 @@
  *	    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...
+ *
+ * This function is only executed for the boot CPU.  The other CPUs have not
+ * been turned on yet.
  */
-static int cpufreq_resume(struct sys_device *sysdev)
+static void cpufreq_bp_resume(void)
 {
 	int ret = 0;
 
-	int cpu = sysdev->id;
+	int cpu = smp_processor_id();
 	struct cpufreq_policy *cpu_policy;
 
 	dprintk("resuming cpu %u\n", cpu);
 
-	if (!cpu_online(cpu))
-		return 0;
-
-	/* we may be lax here as interrupts are off. Nonetheless
-	 * we need to grab the correct cpu policy, as to check
-	 * whether we really run on this CPU.
-	 */
-
+	/* If there's no policy for the boot CPU, we have nothing to do. */
 	cpu_policy = cpufreq_cpu_get(cpu);
 	if (!cpu_policy)
-		return -EINVAL;
-
-	/* only handle each CPU group once */
-	if (unlikely(cpu_policy->cpu != cpu))
-		goto fail;
+		return;
 
 	if (cpufreq_driver->resume) {
 		ret = cpufreq_driver->resume(cpu_policy);
@@ -1430,14 +1418,11 @@
 
 fail:
 	cpufreq_cpu_put(cpu_policy);
-	return ret;
 }
 
-static struct sysdev_driver cpufreq_sysdev_driver = {
-	.add		= cpufreq_add_dev,
-	.remove		= cpufreq_remove_dev,
-	.suspend	= cpufreq_suspend,
-	.resume		= cpufreq_resume,
+static struct syscore_ops cpufreq_syscore_ops = {
+	.suspend	= cpufreq_bp_suspend,
+	.resume		= cpufreq_bp_resume,
 };
 
 
@@ -1797,7 +1782,7 @@
  *	cpufreq_update_policy - re-evaluate an existing cpufreq policy
  *	@cpu: CPU which shall be re-evaluated
  *
- *	Usefull for policy notifiers which have different necessities
+ *	Useful for policy notifiers which have different necessities
  *	at different times.
  */
 int cpufreq_update_policy(unsigned int cpu)
@@ -2002,6 +1987,7 @@
 	cpufreq_global_kobject = kobject_create_and_add("cpufreq",
 						&cpu_sysdev_class.kset.kobj);
 	BUG_ON(!cpufreq_global_kobject);
+	register_syscore_ops(&cpufreq_syscore_ops);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq_conservative.c linux-libre-2.6.39-gnu/drivers/cpufreq/cpufreq_conservative.c
--- linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq_conservative.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cpufreq/cpufreq_conservative.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,13 +76,10 @@
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
- * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
- * different CPUs. It protects dbs_enable in governor start/stop.
+ * dbs_mutex protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
-static struct workqueue_struct	*kconservative_wq;
-
 static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int sampling_down_factor;
@@ -118,7 +115,7 @@
 	if (wall)
 		*wall = (cputime64_t)jiffies_to_usecs(cur_wall_time);
 
-	return (cputime64_t)jiffies_to_usecs(idle_time);;
+	return (cputime64_t)jiffies_to_usecs(idle_time);
 }
 
 static inline cputime64_t get_cpu_idle_time(unsigned int cpu, cputime64_t *wall)
@@ -164,21 +161,12 @@
 };
 
 /************************** sysfs interface ************************/
-static ssize_t show_sampling_rate_max(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
-{
-	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 kobject *kobj,
 				      struct attribute *attr, char *buf)
 {
 	return sprintf(buf, "%u\n", min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_max);
 define_one_global_ro(sampling_rate_min);
 
 /* cpufreq_conservative Governor Tunables */
@@ -195,33 +183,6 @@
 show_one(ignore_nice_load, ignore_nice);
 show_one(freq_step, freq_step);
 
-/*** delete after deprecation time ***/
-#define DEPRECATION_MSG(file_name)					\
-	printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs "	\
-		"interface is deprecated - " #file_name "\n");
-
-#define show_one_old(file_name)						\
-static ssize_t show_##file_name##_old					\
-(struct cpufreq_policy *unused, char *buf)				\
-{									\
-	printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs "	\
-		"interface is deprecated - " #file_name "\n");		\
-	return show_##file_name(NULL, NULL, buf);			\
-}
-show_one_old(sampling_rate);
-show_one_old(sampling_down_factor);
-show_one_old(up_threshold);
-show_one_old(down_threshold);
-show_one_old(ignore_nice_load);
-show_one_old(freq_step);
-show_one_old(sampling_rate_min);
-show_one_old(sampling_rate_max);
-
-cpufreq_freq_attr_ro_old(sampling_rate_min);
-cpufreq_freq_attr_ro_old(sampling_rate_max);
-
-/*** delete after deprecation time ***/
-
 static ssize_t store_sampling_down_factor(struct kobject *a,
 					  struct attribute *b,
 					  const char *buf, size_t count)
@@ -233,10 +194,7 @@
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
 
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_down_factor = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -250,10 +208,7 @@
 	if (ret != 1)
 		return -EINVAL;
 
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -264,16 +219,11 @@
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	mutex_lock(&dbs_mutex);
 	if (ret != 1 || input > 100 ||
-			input <= dbs_tuners_ins.down_threshold) {
-		mutex_unlock(&dbs_mutex);
+			input <= dbs_tuners_ins.down_threshold)
 		return -EINVAL;
-	}
 
 	dbs_tuners_ins.up_threshold = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -284,17 +234,12 @@
 	int ret;
 	ret = sscanf(buf, "%u", &input);
 
-	mutex_lock(&dbs_mutex);
 	/* cannot be lower than 11 otherwise freq will not fall */
 	if (ret != 1 || input < 11 || input > 100 ||
-			input >= dbs_tuners_ins.up_threshold) {
-		mutex_unlock(&dbs_mutex);
+			input >= dbs_tuners_ins.up_threshold)
 		return -EINVAL;
-	}
 
 	dbs_tuners_ins.down_threshold = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -313,11 +258,9 @@
 	if (input > 1)
 		input = 1;
 
-	mutex_lock(&dbs_mutex);
-	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
-		mutex_unlock(&dbs_mutex);
+	if (input == dbs_tuners_ins.ignore_nice) /* nothing to do */
 		return count;
-	}
+
 	dbs_tuners_ins.ignore_nice = input;
 
 	/* we need to re-evaluate prev_cpu_idle */
@@ -329,8 +272,6 @@
 		if (dbs_tuners_ins.ignore_nice)
 			dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
 	}
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -349,10 +290,7 @@
 
 	/* no need to test here if freq_step is zero as the user might actually
 	 * want this, they would be crazy though :) */
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.freq_step = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -364,7 +302,6 @@
 define_one_global_rw(freq_step);
 
 static struct attribute *dbs_attributes[] = {
-	&sampling_rate_max.attr,
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
 	&sampling_down_factor.attr,
@@ -380,49 +317,6 @@
 	.name = "conservative",
 };
 
-/*** delete after deprecation time ***/
-
-#define write_one_old(file_name)					\
-static ssize_t store_##file_name##_old					\
-(struct cpufreq_policy *unused, const char *buf, size_t count)		\
-{									\
-	printk_once(KERN_INFO "CPUFREQ: Per core conservative sysfs "	\
-		"interface is deprecated - " #file_name "\n");	\
-	return store_##file_name(NULL, NULL, buf, count);		\
-}
-write_one_old(sampling_rate);
-write_one_old(sampling_down_factor);
-write_one_old(up_threshold);
-write_one_old(down_threshold);
-write_one_old(ignore_nice_load);
-write_one_old(freq_step);
-
-cpufreq_freq_attr_rw_old(sampling_rate);
-cpufreq_freq_attr_rw_old(sampling_down_factor);
-cpufreq_freq_attr_rw_old(up_threshold);
-cpufreq_freq_attr_rw_old(down_threshold);
-cpufreq_freq_attr_rw_old(ignore_nice_load);
-cpufreq_freq_attr_rw_old(freq_step);
-
-static struct attribute *dbs_attributes_old[] = {
-	&sampling_rate_max_old.attr,
-	&sampling_rate_min_old.attr,
-	&sampling_rate_old.attr,
-	&sampling_down_factor_old.attr,
-	&up_threshold_old.attr,
-	&down_threshold_old.attr,
-	&ignore_nice_load_old.attr,
-	&freq_step_old.attr,
-	NULL
-};
-
-static struct attribute_group dbs_attr_group_old = {
-	.attrs = dbs_attributes_old,
-	.name = "conservative",
-};
-
-/*** delete after deprecation time ***/
-
 /************************** sysfs end ************************/
 
 static void dbs_check_cpu(struct cpu_dbs_info_s *this_dbs_info)
@@ -560,7 +454,7 @@
 
 	dbs_check_cpu(dbs_info);
 
-	queue_delayed_work_on(cpu, kconservative_wq, &dbs_info->work, delay);
+	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
 	mutex_unlock(&dbs_info->timer_mutex);
 }
 
@@ -572,8 +466,7 @@
 
 	dbs_info->enable = 1;
 	INIT_DELAYED_WORK_DEFERRABLE(&dbs_info->work, do_dbs_timer);
-	queue_delayed_work_on(dbs_info->cpu, kconservative_wq, &dbs_info->work,
-				delay);
+	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -599,12 +492,6 @@
 
 		mutex_lock(&dbs_mutex);
 
-		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group_old);
-		if (rc) {
-			mutex_unlock(&dbs_mutex);
-			return rc;
-		}
-
 		for_each_cpu(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
 			j_dbs_info = &per_cpu(cs_cpu_dbs_info, j);
@@ -667,7 +554,6 @@
 		dbs_timer_exit(this_dbs_info);
 
 		mutex_lock(&dbs_mutex);
-		sysfs_remove_group(&policy->kobj, &dbs_attr_group_old);
 		dbs_enable--;
 		mutex_destroy(&this_dbs_info->timer_mutex);
 
@@ -716,25 +602,12 @@
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	int err;
-
-	kconservative_wq = create_workqueue("kconservative");
-	if (!kconservative_wq) {
-		printk(KERN_ERR "Creation of kconservative failed\n");
-		return -EFAULT;
-	}
-
-	err = cpufreq_register_governor(&cpufreq_gov_conservative);
-	if (err)
-		destroy_workqueue(kconservative_wq);
-
-	return err;
+	return cpufreq_register_governor(&cpufreq_gov_conservative);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_conservative);
-	destroy_workqueue(kconservative_wq);
 }
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq_ondemand.c linux-libre-2.6.39-gnu/drivers/cpufreq/cpufreq_ondemand.c
--- linux-libre-2.6.38-gnu/drivers/cpufreq/cpufreq_ondemand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cpufreq/cpufreq_ondemand.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,13 +99,10 @@
 static unsigned int dbs_enable;	/* number of CPUs using this policy */
 
 /*
- * dbs_mutex protects data in dbs_tuners_ins from concurrent changes on
- * different CPUs. It protects dbs_enable in governor start/stop.
+ * dbs_mutex protects dbs_enable in governor start/stop.
  */
 static DEFINE_MUTEX(dbs_mutex);
 
-static struct workqueue_struct	*kondemand_wq;
-
 static struct dbs_tuners {
 	unsigned int sampling_rate;
 	unsigned int up_threshold;
@@ -237,21 +234,12 @@
 
 /************************** sysfs interface ************************/
 
-static ssize_t show_sampling_rate_max(struct kobject *kobj,
-				      struct attribute *attr, char *buf)
-{
-	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 kobject *kobj,
 				      struct attribute *attr, char *buf)
 {
 	return sprintf(buf, "%u\n", min_sampling_rate);
 }
 
-define_one_global_ro(sampling_rate_max);
 define_one_global_ro(sampling_rate_min);
 
 /* cpufreq_ondemand Governor Tunables */
@@ -268,32 +256,6 @@
 show_one(ignore_nice_load, ignore_nice);
 show_one(powersave_bias, powersave_bias);
 
-/*** delete after deprecation time ***/
-
-#define DEPRECATION_MSG(file_name)					\
-	printk_once(KERN_INFO "CPUFREQ: Per core ondemand sysfs "	\
-		    "interface is deprecated - " #file_name "\n");
-
-#define show_one_old(file_name)						\
-static ssize_t show_##file_name##_old					\
-(struct cpufreq_policy *unused, char *buf)				\
-{									\
-	printk_once(KERN_INFO "CPUFREQ: Per core ondemand sysfs "	\
-		    "interface is deprecated - " #file_name "\n");	\
-	return show_##file_name(NULL, NULL, buf);			\
-}
-show_one_old(sampling_rate);
-show_one_old(up_threshold);
-show_one_old(ignore_nice_load);
-show_one_old(powersave_bias);
-show_one_old(sampling_rate_min);
-show_one_old(sampling_rate_max);
-
-cpufreq_freq_attr_ro_old(sampling_rate_min);
-cpufreq_freq_attr_ro_old(sampling_rate_max);
-
-/*** delete after deprecation time ***/
-
 static ssize_t store_sampling_rate(struct kobject *a, struct attribute *b,
 				   const char *buf, size_t count)
 {
@@ -302,11 +264,7 @@
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_rate = max(input, min_sampling_rate);
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -319,11 +277,7 @@
 	ret = sscanf(buf, "%u", &input);
 	if (ret != 1)
 		return -EINVAL;
-
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.io_is_busy = !!input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -338,11 +292,7 @@
 			input < MIN_FREQUENCY_UP_THRESHOLD) {
 		return -EINVAL;
 	}
-
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.up_threshold = input;
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -355,7 +305,6 @@
 
 	if (ret != 1 || input > MAX_SAMPLING_DOWN_FACTOR || input < 1)
 		return -EINVAL;
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.sampling_down_factor = input;
 
 	/* Reset down sampling multiplier in case it was active */
@@ -364,8 +313,6 @@
 		dbs_info = &per_cpu(od_cpu_dbs_info, j);
 		dbs_info->rate_mult = 1;
 	}
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -384,9 +331,7 @@
 	if (input > 1)
 		input = 1;
 
-	mutex_lock(&dbs_mutex);
 	if (input == dbs_tuners_ins.ignore_nice) { /* nothing to do */
-		mutex_unlock(&dbs_mutex);
 		return count;
 	}
 	dbs_tuners_ins.ignore_nice = input;
@@ -401,8 +346,6 @@
 			dbs_info->prev_cpu_nice = kstat_cpu(j).cpustat.nice;
 
 	}
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -419,11 +362,8 @@
 	if (input > 1000)
 		input = 1000;
 
-	mutex_lock(&dbs_mutex);
 	dbs_tuners_ins.powersave_bias = input;
 	ondemand_powersave_bias_init();
-	mutex_unlock(&dbs_mutex);
-
 	return count;
 }
 
@@ -435,7 +375,6 @@
 define_one_global_rw(powersave_bias);
 
 static struct attribute *dbs_attributes[] = {
-	&sampling_rate_max.attr,
 	&sampling_rate_min.attr,
 	&sampling_rate.attr,
 	&up_threshold.attr,
@@ -451,43 +390,6 @@
 	.name = "ondemand",
 };
 
-/*** delete after deprecation time ***/
-
-#define write_one_old(file_name)					\
-static ssize_t store_##file_name##_old					\
-(struct cpufreq_policy *unused, const char *buf, size_t count)		\
-{									\
-       printk_once(KERN_INFO "CPUFREQ: Per core ondemand sysfs "	\
-		   "interface is deprecated - " #file_name "\n");	\
-       return store_##file_name(NULL, NULL, buf, count);		\
-}
-write_one_old(sampling_rate);
-write_one_old(up_threshold);
-write_one_old(ignore_nice_load);
-write_one_old(powersave_bias);
-
-cpufreq_freq_attr_rw_old(sampling_rate);
-cpufreq_freq_attr_rw_old(up_threshold);
-cpufreq_freq_attr_rw_old(ignore_nice_load);
-cpufreq_freq_attr_rw_old(powersave_bias);
-
-static struct attribute *dbs_attributes_old[] = {
-       &sampling_rate_max_old.attr,
-       &sampling_rate_min_old.attr,
-       &sampling_rate_old.attr,
-       &up_threshold_old.attr,
-       &ignore_nice_load_old.attr,
-       &powersave_bias_old.attr,
-       NULL
-};
-
-static struct attribute_group dbs_attr_group_old = {
-       .attrs = dbs_attributes_old,
-       .name = "ondemand",
-};
-
-/*** delete after deprecation time ***/
-
 /************************** sysfs end ************************/
 
 static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq)
@@ -644,12 +546,7 @@
 	unsigned int cpu = dbs_info->cpu;
 	int sample_type = dbs_info->sample_type;
 
-	/* We want all CPUs to do sampling nearly on same jiffy */
-	int delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
-		* dbs_info->rate_mult);
-
-	if (num_online_cpus() > 1)
-		delay -= jiffies % delay;
+	int delay;
 
 	mutex_lock(&dbs_info->timer_mutex);
 
@@ -662,12 +559,22 @@
 			/* Setup timer for SUB_SAMPLE */
 			dbs_info->sample_type = DBS_SUB_SAMPLE;
 			delay = dbs_info->freq_hi_jiffies;
+		} else {
+			/* We want all CPUs to do sampling nearly on
+			 * same jiffy
+			 */
+			delay = usecs_to_jiffies(dbs_tuners_ins.sampling_rate
+				* dbs_info->rate_mult);
+
+			if (num_online_cpus() > 1)
+				delay -= jiffies % delay;
 		}
 	} else {
 		__cpufreq_driver_target(dbs_info->cur_policy,
 			dbs_info->freq_lo, CPUFREQ_RELATION_H);
+		delay = dbs_info->freq_lo_jiffies;
 	}
-	queue_delayed_work_on(cpu, kondemand_wq, &dbs_info->work, delay);
+	schedule_delayed_work_on(cpu, &dbs_info->work, delay);
 	mutex_unlock(&dbs_info->timer_mutex);
 }
 
@@ -681,8 +588,7 @@
 
 	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,
-		delay);
+	schedule_delayed_work_on(dbs_info->cpu, &dbs_info->work, delay);
 }
 
 static inline void dbs_timer_exit(struct cpu_dbs_info_s *dbs_info)
@@ -730,12 +636,6 @@
 
 		mutex_lock(&dbs_mutex);
 
-		rc = sysfs_create_group(&policy->kobj, &dbs_attr_group_old);
-		if (rc) {
-			mutex_unlock(&dbs_mutex);
-			return rc;
-		}
-
 		dbs_enable++;
 		for_each_cpu(j, policy->cpus) {
 			struct cpu_dbs_info_s *j_dbs_info;
@@ -788,7 +688,6 @@
 		dbs_timer_exit(this_dbs_info);
 
 		mutex_lock(&dbs_mutex);
-		sysfs_remove_group(&policy->kobj, &dbs_attr_group_old);
 		mutex_destroy(&this_dbs_info->timer_mutex);
 		dbs_enable--;
 		mutex_unlock(&dbs_mutex);
@@ -814,7 +713,6 @@
 
 static int __init cpufreq_gov_dbs_init(void)
 {
-	int err;
 	cputime64_t wall;
 	u64 idle_time;
 	int cpu = get_cpu();
@@ -838,22 +736,12 @@
 			MIN_SAMPLING_RATE_RATIO * jiffies_to_usecs(10);
 	}
 
-	kondemand_wq = create_workqueue("kondemand");
-	if (!kondemand_wq) {
-		printk(KERN_ERR "Creation of kondemand failed\n");
-		return -EFAULT;
-	}
-	err = cpufreq_register_governor(&cpufreq_gov_ondemand);
-	if (err)
-		destroy_workqueue(kondemand_wq);
-
-	return err;
+	return cpufreq_register_governor(&cpufreq_gov_ondemand);
 }
 
 static void __exit cpufreq_gov_dbs_exit(void)
 {
 	cpufreq_unregister_governor(&cpufreq_gov_ondemand);
-	destroy_workqueue(kondemand_wq);
 }
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/cpuidle/sysfs.c linux-libre-2.6.39-gnu/drivers/cpuidle/sysfs.c
--- linux-libre-2.6.38-gnu/drivers/cpuidle/sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/cpuidle/sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -300,7 +300,7 @@
 	.release = cpuidle_state_sysfs_release,
 };
 
-static void inline cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
+static inline void cpuidle_free_state_kobj(struct cpuidle_device *device, int i)
 {
 	kobject_put(&device->kobjs[i]->kobj);
 	wait_for_completion(&device->kobjs[i]->kobj_unregister);
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/amcc/crypto4xx_core.c linux-libre-2.6.39-gnu/drivers/crypto/amcc/crypto4xx_core.c
--- linux-libre-2.6.38-gnu/drivers/crypto/amcc/crypto4xx_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/amcc/crypto4xx_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1150,8 +1150,7 @@
 /**
  * Module Initialization Routine
  */
-static int __init crypto4xx_probe(struct platform_device *ofdev,
-				  const struct of_device_id *match)
+static int __init crypto4xx_probe(struct platform_device *ofdev)
 {
 	int rc;
 	struct resource res;
@@ -1280,7 +1279,7 @@
 	{ },
 };
 
-static struct of_platform_driver crypto4xx_driver = {
+static struct platform_driver crypto4xx_driver = {
 	.driver = {
 		.name = "crypto4xx",
 		.owner = THIS_MODULE,
@@ -1292,12 +1291,12 @@
 
 static int __init crypto4xx_init(void)
 {
-	return of_register_platform_driver(&crypto4xx_driver);
+	return platform_driver_register(&crypto4xx_driver);
 }
 
 static void __exit crypto4xx_exit(void)
 {
-	of_unregister_platform_driver(&crypto4xx_driver);
+	platform_driver_unregister(&crypto4xx_driver);
 }
 
 module_init(crypto4xx_init);
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/amcc/crypto4xx_sa.c linux-libre-2.6.39-gnu/drivers/crypto/amcc/crypto4xx_sa.c
--- linux-libre-2.6.38-gnu/drivers/crypto/amcc/crypto4xx_sa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/amcc/crypto4xx_sa.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
  * @file crypto4xx_sa.c
  *
  * This file implements the security context
- * assoicate format.
+ * associate format.
  */
 #include <linux/kernel.h>
 #include <linux/module.h>
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/amcc/crypto4xx_sa.h linux-libre-2.6.39-gnu/drivers/crypto/amcc/crypto4xx_sa.h
--- linux-libre-2.6.38-gnu/drivers/crypto/amcc/crypto4xx_sa.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/amcc/crypto4xx_sa.h	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
  * GNU General Public License for more details.
  *
  * This file defines the security context
- * assoicate format.
+ * associate format.
  */
 
 #ifndef __CRYPTO4XX_SA_H__
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/ixp4xx_crypto.c linux-libre-2.6.39-gnu/drivers/crypto/ixp4xx_crypto.c
--- linux-libre-2.6.38-gnu/drivers/crypto/ixp4xx_crypto.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/ixp4xx_crypto.c	2011-05-19 00:06:34.000000000 -0400
@@ -1044,7 +1044,7 @@
 	memcpy(crypt->iv, req->iv, ivsize);
 
 	if (req->src != req->dst) {
-		BUG(); /* -ENOTSUP because of my lazyness */
+		BUG(); /* -ENOTSUP because of my laziness */
 	}
 
 	/* ASSOC data */
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/Kconfig linux-libre-2.6.39-gnu/drivers/crypto/Kconfig
--- linux-libre-2.6.38-gnu/drivers/crypto/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -252,4 +252,21 @@
 	  OMAP processors have AES module accelerator. Select this if you
 	  want to use the OMAP module for AES algorithms.
 
+config CRYPTO_DEV_PICOXCELL
+	tristate "Support for picoXcell IPSEC and Layer2 crypto engines"
+	depends on ARCH_PICOXCELL
+	select CRYPTO_AES
+	select CRYPTO_AUTHENC
+	select CRYPTO_ALGAPI
+	select CRYPTO_DES
+	select CRYPTO_CBC
+	select CRYPTO_ECB
+	select CRYPTO_SEQIV
+	help
+	  This option enables support for the hardware offload engines in the
+	  Picochip picoXcell SoC devices. Select this for IPSEC ESP offload
+	  and for 3gpp Layer 2 ciphering support.
+
+	  Saying m here will build a module named pipcoxcell_crypto.
+
 endif # CRYPTO_HW
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/Makefile linux-libre-2.6.39-gnu/drivers/crypto/Makefile
--- linux-libre-2.6.38-gnu/drivers/crypto/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -10,4 +10,4 @@
 obj-$(CONFIG_CRYPTO_DEV_PPC4XX) += amcc/
 obj-$(CONFIG_CRYPTO_DEV_OMAP_SHAM) += omap-sham.o
 obj-$(CONFIG_CRYPTO_DEV_OMAP_AES) += omap-aes.o
-
+obj-$(CONFIG_CRYPTO_DEV_PICOXCELL) += picoxcell_crypto.o
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/n2_core.c linux-libre-2.6.39-gnu/drivers/crypto/n2_core.c
--- linux-libre-2.6.38-gnu/drivers/crypto/n2_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/n2_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -2004,8 +2004,7 @@
 		pr_info("%s", version);
 }
 
-static int __devinit n2_crypto_probe(struct platform_device *dev,
-				     const struct of_device_id *match)
+static int __devinit n2_crypto_probe(struct platform_device *dev)
 {
 	struct mdesc_handle *mdesc;
 	const char *full_name;
@@ -2116,8 +2115,7 @@
 	kfree(mp);
 }
 
-static int __devinit n2_mau_probe(struct platform_device *dev,
-				     const struct of_device_id *match)
+static int __devinit n2_mau_probe(struct platform_device *dev)
 {
 	struct mdesc_handle *mdesc;
 	const char *full_name;
@@ -2211,7 +2209,7 @@
 
 MODULE_DEVICE_TABLE(of, n2_crypto_match);
 
-static struct of_platform_driver n2_crypto_driver = {
+static struct platform_driver n2_crypto_driver = {
 	.driver = {
 		.name		=	"n2cp",
 		.owner		=	THIS_MODULE,
@@ -2235,7 +2233,7 @@
 
 MODULE_DEVICE_TABLE(of, n2_mau_match);
 
-static struct of_platform_driver n2_mau_driver = {
+static struct platform_driver n2_mau_driver = {
 	.driver = {
 		.name		=	"ncp",
 		.owner		=	THIS_MODULE,
@@ -2247,20 +2245,20 @@
 
 static int __init n2_init(void)
 {
-	int err = of_register_platform_driver(&n2_crypto_driver);
+	int err = platform_driver_register(&n2_crypto_driver);
 
 	if (!err) {
-		err = of_register_platform_driver(&n2_mau_driver);
+		err = platform_driver_register(&n2_mau_driver);
 		if (err)
-			of_unregister_platform_driver(&n2_crypto_driver);
+			platform_driver_unregister(&n2_crypto_driver);
 	}
 	return err;
 }
 
 static void __exit n2_exit(void)
 {
-	of_unregister_platform_driver(&n2_mau_driver);
-	of_unregister_platform_driver(&n2_crypto_driver);
+	platform_driver_unregister(&n2_mau_driver);
+	platform_driver_unregister(&n2_crypto_driver);
 }
 
 module_init(n2_init);
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/omap-aes.c linux-libre-2.6.39-gnu/drivers/crypto/omap-aes.c
--- linux-libre-2.6.38-gnu/drivers/crypto/omap-aes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/omap-aes.c	2011-05-19 00:06:34.000000000 -0400
@@ -839,9 +839,9 @@
 
 	/* Initializing the clock */
 	dd->iclk = clk_get(dev, "ick");
-	if (!dd->iclk) {
+	if (IS_ERR(dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
-		err = -ENODEV;
+		err = PTR_ERR(dd->iclk);
 		goto err_res;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/omap-sham.c linux-libre-2.6.39-gnu/drivers/crypto/omap-sham.c
--- linux-libre-2.6.38-gnu/drivers/crypto/omap-sham.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/omap-sham.c	2011-05-19 00:06:34.000000000 -0400
@@ -1206,9 +1206,9 @@
 
 	/* Initializing the clock */
 	dd->iclk = clk_get(dev, "ick");
-	if (!dd->iclk) {
+	if (IS_ERR(dd->iclk)) {
 		dev_err(dev, "clock intialization failed.\n");
-		err = -ENODEV;
+		err = PTR_ERR(dd->iclk);
 		goto clk_err;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/picoxcell_crypto.c linux-libre-2.6.39-gnu/drivers/crypto/picoxcell_crypto.c
--- linux-libre-2.6.38-gnu/drivers/crypto/picoxcell_crypto.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/crypto/picoxcell_crypto.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1867 @@
+/*
+ * Copyright (c) 2010-2011 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <crypto/aead.h>
+#include <crypto/aes.h>
+#include <crypto/algapi.h>
+#include <crypto/authenc.h>
+#include <crypto/des.h>
+#include <crypto/md5.h>
+#include <crypto/sha.h>
+#include <crypto/internal/skcipher.h>
+#include <linux/clk.h>
+#include <linux/crypto.h>
+#include <linux/delay.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmapool.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pm.h>
+#include <linux/rtnetlink.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/timer.h>
+
+#include "picoxcell_crypto_regs.h"
+
+/*
+ * The threshold for the number of entries in the CMD FIFO available before
+ * the CMD0_CNT interrupt is raised. Increasing this value will reduce the
+ * number of interrupts raised to the CPU.
+ */
+#define CMD0_IRQ_THRESHOLD   1
+
+/*
+ * The timeout period (in jiffies) for a PDU. When the the number of PDUs in
+ * flight is greater than the STAT_IRQ_THRESHOLD or 0 the timer is disabled.
+ * When there are packets in flight but lower than the threshold, we enable
+ * the timer and at expiry, attempt to remove any processed packets from the
+ * queue and if there are still packets left, schedule the timer again.
+ */
+#define PACKET_TIMEOUT	    1
+
+/* The priority to register each algorithm with. */
+#define SPACC_CRYPTO_ALG_PRIORITY	10000
+
+#define SPACC_CRYPTO_KASUMI_F8_KEY_LEN	16
+#define SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ 64
+#define SPACC_CRYPTO_IPSEC_HASH_PG_SZ	64
+#define SPACC_CRYPTO_IPSEC_MAX_CTXS	32
+#define SPACC_CRYPTO_IPSEC_FIFO_SZ	32
+#define SPACC_CRYPTO_L2_CIPHER_PG_SZ	64
+#define SPACC_CRYPTO_L2_HASH_PG_SZ	64
+#define SPACC_CRYPTO_L2_MAX_CTXS	128
+#define SPACC_CRYPTO_L2_FIFO_SZ		128
+
+#define MAX_DDT_LEN			16
+
+/* DDT format. This must match the hardware DDT format exactly. */
+struct spacc_ddt {
+	dma_addr_t	p;
+	u32		len;
+};
+
+/*
+ * Asynchronous crypto request structure.
+ *
+ * This structure defines a request that is either queued for processing or
+ * being processed.
+ */
+struct spacc_req {
+	struct list_head		list;
+	struct spacc_engine		*engine;
+	struct crypto_async_request	*req;
+	int				result;
+	bool				is_encrypt;
+	unsigned			ctx_id;
+	dma_addr_t			src_addr, dst_addr;
+	struct spacc_ddt		*src_ddt, *dst_ddt;
+	void				(*complete)(struct spacc_req *req);
+
+	/* AEAD specific bits. */
+	u8				*giv;
+	size_t				giv_len;
+	dma_addr_t			giv_pa;
+};
+
+struct spacc_engine {
+	void __iomem			*regs;
+	struct list_head		pending;
+	int				next_ctx;
+	spinlock_t			hw_lock;
+	int				in_flight;
+	struct list_head		completed;
+	struct list_head		in_progress;
+	struct tasklet_struct		complete;
+	unsigned long			fifo_sz;
+	void __iomem			*cipher_ctx_base;
+	void __iomem			*hash_key_base;
+	struct spacc_alg		*algs;
+	unsigned			num_algs;
+	struct list_head		registered_algs;
+	size_t				cipher_pg_sz;
+	size_t				hash_pg_sz;
+	const char			*name;
+	struct clk			*clk;
+	struct device			*dev;
+	unsigned			max_ctxs;
+	struct timer_list		packet_timeout;
+	unsigned			stat_irq_thresh;
+	struct dma_pool			*req_pool;
+};
+
+/* Algorithm type mask. */
+#define SPACC_CRYPTO_ALG_MASK		0x7
+
+/* SPACC definition of a crypto algorithm. */
+struct spacc_alg {
+	unsigned long			ctrl_default;
+	unsigned long			type;
+	struct crypto_alg		alg;
+	struct spacc_engine		*engine;
+	struct list_head		entry;
+	int				key_offs;
+	int				iv_offs;
+};
+
+/* Generic context structure for any algorithm type. */
+struct spacc_generic_ctx {
+	struct spacc_engine		*engine;
+	int				flags;
+	int				key_offs;
+	int				iv_offs;
+};
+
+/* Block cipher context. */
+struct spacc_ablk_ctx {
+	struct spacc_generic_ctx	generic;
+	u8				key[AES_MAX_KEY_SIZE];
+	u8				key_len;
+	/*
+	 * The fallback cipher. If the operation can't be done in hardware,
+	 * fallback to a software version.
+	 */
+	struct crypto_ablkcipher	*sw_cipher;
+};
+
+/* AEAD cipher context. */
+struct spacc_aead_ctx {
+	struct spacc_generic_ctx	generic;
+	u8				cipher_key[AES_MAX_KEY_SIZE];
+	u8				hash_ctx[SPACC_CRYPTO_IPSEC_HASH_PG_SZ];
+	u8				cipher_key_len;
+	u8				hash_key_len;
+	struct crypto_aead		*sw_cipher;
+	size_t				auth_size;
+	u8				salt[AES_BLOCK_SIZE];
+};
+
+static inline struct spacc_alg *to_spacc_alg(struct crypto_alg *alg)
+{
+	return alg ? container_of(alg, struct spacc_alg, alg) : NULL;
+}
+
+static inline int spacc_fifo_cmd_full(struct spacc_engine *engine)
+{
+	u32 fifo_stat = readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET);
+
+	return fifo_stat & SPA_FIFO_CMD_FULL;
+}
+
+/*
+ * Given a cipher context, and a context number, get the base address of the
+ * context page.
+ *
+ * Returns the address of the context page where the key/context may
+ * be written.
+ */
+static inline void __iomem *spacc_ctx_page_addr(struct spacc_generic_ctx *ctx,
+						unsigned indx,
+						bool is_cipher_ctx)
+{
+	return is_cipher_ctx ? ctx->engine->cipher_ctx_base +
+			(indx * ctx->engine->cipher_pg_sz) :
+		ctx->engine->hash_key_base + (indx * ctx->engine->hash_pg_sz);
+}
+
+/* The context pages can only be written with 32-bit accesses. */
+static inline void memcpy_toio32(u32 __iomem *dst, const void *src,
+				 unsigned count)
+{
+	const u32 *src32 = (const u32 *) src;
+
+	while (count--)
+		writel(*src32++, dst++);
+}
+
+static void spacc_cipher_write_ctx(struct spacc_generic_ctx *ctx,
+				   void __iomem *page_addr, const u8 *key,
+				   size_t key_len, const u8 *iv, size_t iv_len)
+{
+	void __iomem *key_ptr = page_addr + ctx->key_offs;
+	void __iomem *iv_ptr = page_addr + ctx->iv_offs;
+
+	memcpy_toio32(key_ptr, key, key_len / 4);
+	memcpy_toio32(iv_ptr, iv, iv_len / 4);
+}
+
+/*
+ * Load a context into the engines context memory.
+ *
+ * Returns the index of the context page where the context was loaded.
+ */
+static unsigned spacc_load_ctx(struct spacc_generic_ctx *ctx,
+			       const u8 *ciph_key, size_t ciph_len,
+			       const u8 *iv, size_t ivlen, const u8 *hash_key,
+			       size_t hash_len)
+{
+	unsigned indx = ctx->engine->next_ctx++;
+	void __iomem *ciph_page_addr, *hash_page_addr;
+
+	ciph_page_addr = spacc_ctx_page_addr(ctx, indx, 1);
+	hash_page_addr = spacc_ctx_page_addr(ctx, indx, 0);
+
+	ctx->engine->next_ctx &= ctx->engine->fifo_sz - 1;
+	spacc_cipher_write_ctx(ctx, ciph_page_addr, ciph_key, ciph_len, iv,
+			       ivlen);
+	writel(ciph_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET) |
+	       (1 << SPA_KEY_SZ_CIPHER_OFFSET),
+	       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
+
+	if (hash_key) {
+		memcpy_toio32(hash_page_addr, hash_key, hash_len / 4);
+		writel(hash_len | (indx << SPA_KEY_SZ_CTX_INDEX_OFFSET),
+		       ctx->engine->regs + SPA_KEY_SZ_REG_OFFSET);
+	}
+
+	return indx;
+}
+
+/* Count the number of scatterlist entries in a scatterlist. */
+static int sg_count(struct scatterlist *sg_list, int nbytes)
+{
+	struct scatterlist *sg = sg_list;
+	int sg_nents = 0;
+
+	while (nbytes > 0) {
+		++sg_nents;
+		nbytes -= sg->length;
+		sg = sg_next(sg);
+	}
+
+	return sg_nents;
+}
+
+static inline void ddt_set(struct spacc_ddt *ddt, dma_addr_t phys, size_t len)
+{
+	ddt->p = phys;
+	ddt->len = len;
+}
+
+/*
+ * Take a crypto request and scatterlists for the data and turn them into DDTs
+ * for passing to the crypto engines. This also DMA maps the data so that the
+ * crypto engines can DMA to/from them.
+ */
+static struct spacc_ddt *spacc_sg_to_ddt(struct spacc_engine *engine,
+					 struct scatterlist *payload,
+					 unsigned nbytes,
+					 enum dma_data_direction dir,
+					 dma_addr_t *ddt_phys)
+{
+	unsigned nents, mapped_ents;
+	struct scatterlist *cur;
+	struct spacc_ddt *ddt;
+	int i;
+
+	nents = sg_count(payload, nbytes);
+	mapped_ents = dma_map_sg(engine->dev, payload, nents, dir);
+
+	if (mapped_ents + 1 > MAX_DDT_LEN)
+		goto out;
+
+	ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, ddt_phys);
+	if (!ddt)
+		goto out;
+
+	for_each_sg(payload, cur, mapped_ents, i)
+		ddt_set(&ddt[i], sg_dma_address(cur), sg_dma_len(cur));
+	ddt_set(&ddt[mapped_ents], 0, 0);
+
+	return ddt;
+
+out:
+	dma_unmap_sg(engine->dev, payload, nents, dir);
+	return NULL;
+}
+
+static int spacc_aead_make_ddts(struct spacc_req *req, u8 *giv)
+{
+	struct aead_request *areq = container_of(req->req, struct aead_request,
+						 base);
+	struct spacc_engine *engine = req->engine;
+	struct spacc_ddt *src_ddt, *dst_ddt;
+	unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(areq));
+	unsigned nents = sg_count(areq->src, areq->cryptlen);
+	dma_addr_t iv_addr;
+	struct scatterlist *cur;
+	int i, dst_ents, src_ents, assoc_ents;
+	u8 *iv = giv ? giv : areq->iv;
+
+	src_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->src_addr);
+	if (!src_ddt)
+		return -ENOMEM;
+
+	dst_ddt = dma_pool_alloc(engine->req_pool, GFP_ATOMIC, &req->dst_addr);
+	if (!dst_ddt) {
+		dma_pool_free(engine->req_pool, src_ddt, req->src_addr);
+		return -ENOMEM;
+	}
+
+	req->src_ddt = src_ddt;
+	req->dst_ddt = dst_ddt;
+
+	assoc_ents = dma_map_sg(engine->dev, areq->assoc,
+		sg_count(areq->assoc, areq->assoclen), DMA_TO_DEVICE);
+	if (areq->src != areq->dst) {
+		src_ents = dma_map_sg(engine->dev, areq->src, nents,
+				      DMA_TO_DEVICE);
+		dst_ents = dma_map_sg(engine->dev, areq->dst, nents,
+				      DMA_FROM_DEVICE);
+	} else {
+		src_ents = dma_map_sg(engine->dev, areq->src, nents,
+				      DMA_BIDIRECTIONAL);
+		dst_ents = 0;
+	}
+
+	/*
+	 * Map the IV/GIV. For the GIV it needs to be bidirectional as it is
+	 * formed by the crypto block and sent as the ESP IV for IPSEC.
+	 */
+	iv_addr = dma_map_single(engine->dev, iv, ivsize,
+				 giv ? DMA_BIDIRECTIONAL : DMA_TO_DEVICE);
+	req->giv_pa = iv_addr;
+
+	/*
+	 * Map the associated data. For decryption we don't copy the
+	 * associated data.
+	 */
+	for_each_sg(areq->assoc, cur, assoc_ents, i) {
+		ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
+		if (req->is_encrypt)
+			ddt_set(dst_ddt++, sg_dma_address(cur),
+				sg_dma_len(cur));
+	}
+	ddt_set(src_ddt++, iv_addr, ivsize);
+
+	if (giv || req->is_encrypt)
+		ddt_set(dst_ddt++, iv_addr, ivsize);
+
+	/*
+	 * Now map in the payload for the source and destination and terminate
+	 * with the NULL pointers.
+	 */
+	for_each_sg(areq->src, cur, src_ents, i) {
+		ddt_set(src_ddt++, sg_dma_address(cur), sg_dma_len(cur));
+		if (areq->src == areq->dst)
+			ddt_set(dst_ddt++, sg_dma_address(cur),
+				sg_dma_len(cur));
+	}
+
+	for_each_sg(areq->dst, cur, dst_ents, i)
+		ddt_set(dst_ddt++, sg_dma_address(cur),
+			sg_dma_len(cur));
+
+	ddt_set(src_ddt, 0, 0);
+	ddt_set(dst_ddt, 0, 0);
+
+	return 0;
+}
+
+static void spacc_aead_free_ddts(struct spacc_req *req)
+{
+	struct aead_request *areq = container_of(req->req, struct aead_request,
+						 base);
+	struct spacc_alg *alg = to_spacc_alg(req->req->tfm->__crt_alg);
+	struct spacc_ablk_ctx *aead_ctx = crypto_tfm_ctx(req->req->tfm);
+	struct spacc_engine *engine = aead_ctx->generic.engine;
+	unsigned ivsize = alg->alg.cra_aead.ivsize;
+	unsigned nents = sg_count(areq->src, areq->cryptlen);
+
+	if (areq->src != areq->dst) {
+		dma_unmap_sg(engine->dev, areq->src, nents, DMA_TO_DEVICE);
+		dma_unmap_sg(engine->dev, areq->dst,
+			     sg_count(areq->dst, areq->cryptlen),
+			     DMA_FROM_DEVICE);
+	} else
+		dma_unmap_sg(engine->dev, areq->src, nents, DMA_BIDIRECTIONAL);
+
+	dma_unmap_sg(engine->dev, areq->assoc,
+		     sg_count(areq->assoc, areq->assoclen), DMA_TO_DEVICE);
+
+	dma_unmap_single(engine->dev, req->giv_pa, ivsize, DMA_BIDIRECTIONAL);
+
+	dma_pool_free(engine->req_pool, req->src_ddt, req->src_addr);
+	dma_pool_free(engine->req_pool, req->dst_ddt, req->dst_addr);
+}
+
+static void spacc_free_ddt(struct spacc_req *req, struct spacc_ddt *ddt,
+			   dma_addr_t ddt_addr, struct scatterlist *payload,
+			   unsigned nbytes, enum dma_data_direction dir)
+{
+	unsigned nents = sg_count(payload, nbytes);
+
+	dma_unmap_sg(req->engine->dev, payload, nents, dir);
+	dma_pool_free(req->engine->req_pool, ddt, ddt_addr);
+}
+
+/*
+ * Set key for a DES operation in an AEAD cipher. This also performs weak key
+ * checking if required.
+ */
+static int spacc_aead_des_setkey(struct crypto_aead *aead, const u8 *key,
+				 unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 tmp[DES_EXPKEY_WORDS];
+
+	if (unlikely(!des_ekey(tmp, key)) &&
+	    (crypto_aead_get_flags(aead)) & CRYPTO_TFM_REQ_WEAK_KEY) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
+	memcpy(ctx->cipher_key, key, len);
+	ctx->cipher_key_len = len;
+
+	return 0;
+}
+
+/* Set the key for the AES block cipher component of the AEAD transform. */
+static int spacc_aead_aes_setkey(struct crypto_aead *aead, const u8 *key,
+				 unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	/*
+	 * IPSec engine only supports 128 and 256 bit AES keys. If we get a
+	 * request for any other size (192 bits) then we need to do a software
+	 * fallback.
+	 */
+	if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256) {
+		/*
+		 * Set the fallback transform to use the same request flags as
+		 * the hardware transform.
+		 */
+		ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+		ctx->sw_cipher->base.crt_flags |=
+			tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
+		return crypto_aead_setkey(ctx->sw_cipher, key, len);
+	}
+
+	memcpy(ctx->cipher_key, key, len);
+	ctx->cipher_key_len = len;
+
+	return 0;
+}
+
+static int spacc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
+			     unsigned int keylen)
+{
+	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+	struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
+	struct rtattr *rta = (void *)key;
+	struct crypto_authenc_key_param *param;
+	unsigned int authkeylen, enckeylen;
+	int err = -EINVAL;
+
+	if (!RTA_OK(rta, keylen))
+		goto badkey;
+
+	if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
+		goto badkey;
+
+	if (RTA_PAYLOAD(rta) < sizeof(*param))
+		goto badkey;
+
+	param = RTA_DATA(rta);
+	enckeylen = be32_to_cpu(param->enckeylen);
+
+	key += RTA_ALIGN(rta->rta_len);
+	keylen -= RTA_ALIGN(rta->rta_len);
+
+	if (keylen < enckeylen)
+		goto badkey;
+
+	authkeylen = keylen - enckeylen;
+
+	if (enckeylen > AES_MAX_KEY_SIZE)
+		goto badkey;
+
+	if ((alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
+	    SPA_CTRL_CIPH_ALG_AES)
+		err = spacc_aead_aes_setkey(tfm, key + authkeylen, enckeylen);
+	else
+		err = spacc_aead_des_setkey(tfm, key + authkeylen, enckeylen);
+
+	if (err)
+		goto badkey;
+
+	memcpy(ctx->hash_ctx, key, authkeylen);
+	ctx->hash_key_len = authkeylen;
+
+	return 0;
+
+badkey:
+	crypto_aead_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+	return -EINVAL;
+}
+
+static int spacc_aead_setauthsize(struct crypto_aead *tfm,
+				  unsigned int authsize)
+{
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(crypto_aead_tfm(tfm));
+
+	ctx->auth_size = authsize;
+
+	return 0;
+}
+
+/*
+ * Check if an AEAD request requires a fallback operation. Some requests can't
+ * be completed in hardware because the hardware may not support certain key
+ * sizes. In these cases we need to complete the request in software.
+ */
+static int spacc_aead_need_fallback(struct spacc_req *req)
+{
+	struct aead_request *aead_req;
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	aead_req = container_of(req->req, struct aead_request, base);
+	/*
+	 * If we have a non-supported key-length, then we need to do a
+	 * software fallback.
+	 */
+	if ((spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
+	    SPA_CTRL_CIPH_ALG_AES &&
+	    ctx->cipher_key_len != AES_KEYSIZE_128 &&
+	    ctx->cipher_key_len != AES_KEYSIZE_256)
+		return 1;
+
+	return 0;
+}
+
+static int spacc_aead_do_fallback(struct aead_request *req, unsigned alg_type,
+				  bool is_encrypt)
+{
+	struct crypto_tfm *old_tfm = crypto_aead_tfm(crypto_aead_reqtfm(req));
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(old_tfm);
+	int err;
+
+	if (ctx->sw_cipher) {
+		/*
+		 * Change the request to use the software fallback transform,
+		 * and once the ciphering has completed, put the old transform
+		 * back into the request.
+		 */
+		aead_request_set_tfm(req, ctx->sw_cipher);
+		err = is_encrypt ? crypto_aead_encrypt(req) :
+		    crypto_aead_decrypt(req);
+		aead_request_set_tfm(req, __crypto_aead_cast(old_tfm));
+	} else
+		err = -EINVAL;
+
+	return err;
+}
+
+static void spacc_aead_complete(struct spacc_req *req)
+{
+	spacc_aead_free_ddts(req);
+	req->req->complete(req->req, req->result);
+}
+
+static int spacc_aead_submit(struct spacc_req *req)
+{
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = ctx->generic.engine;
+	u32 ctrl, proc_len, assoc_len;
+	struct aead_request *aead_req =
+		container_of(req->req, struct aead_request, base);
+
+	req->result = -EINPROGRESS;
+	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->cipher_key,
+		ctx->cipher_key_len, aead_req->iv, alg->cra_aead.ivsize,
+		ctx->hash_ctx, ctx->hash_key_len);
+
+	/* Set the source and destination DDT pointers. */
+	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
+	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
+	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
+
+	assoc_len = aead_req->assoclen;
+	proc_len = aead_req->cryptlen + assoc_len;
+
+	/*
+	 * If we aren't generating an IV, then we need to include the IV in the
+	 * associated data so that it is included in the hash.
+	 */
+	if (!req->giv) {
+		assoc_len += crypto_aead_ivsize(crypto_aead_reqtfm(aead_req));
+		proc_len += crypto_aead_ivsize(crypto_aead_reqtfm(aead_req));
+	} else
+		proc_len += req->giv_len;
+
+	/*
+	 * If we are decrypting, we need to take the length of the ICV out of
+	 * the processing length.
+	 */
+	if (!req->is_encrypt)
+		proc_len -= ctx->auth_size;
+
+	writel(proc_len, engine->regs + SPA_PROC_LEN_REG_OFFSET);
+	writel(assoc_len, engine->regs + SPA_AAD_LEN_REG_OFFSET);
+	writel(ctx->auth_size, engine->regs + SPA_ICV_LEN_REG_OFFSET);
+	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
+	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
+
+	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
+		(1 << SPA_CTRL_ICV_APPEND);
+	if (req->is_encrypt)
+		ctrl |= (1 << SPA_CTRL_ENCRYPT_IDX) | (1 << SPA_CTRL_AAD_COPY);
+	else
+		ctrl |= (1 << SPA_CTRL_KEY_EXP);
+
+	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
+
+	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
+
+	return -EINPROGRESS;
+}
+
+/*
+ * Setup an AEAD request for processing. This will configure the engine, load
+ * the context and then start the packet processing.
+ *
+ * @giv Pointer to destination address for a generated IV. If the
+ *	request does not need to generate an IV then this should be set to NULL.
+ */
+static int spacc_aead_setup(struct aead_request *req, u8 *giv,
+			    unsigned alg_type, bool is_encrypt)
+{
+	struct crypto_alg *alg = req->base.tfm->__crt_alg;
+	struct spacc_engine *engine = to_spacc_alg(alg)->engine;
+	struct spacc_req *dev_req = aead_request_ctx(req);
+	int err = -EINPROGRESS;
+	unsigned long flags;
+	unsigned ivsize = crypto_aead_ivsize(crypto_aead_reqtfm(req));
+
+	dev_req->giv		= giv;
+	dev_req->giv_len	= ivsize;
+	dev_req->req		= &req->base;
+	dev_req->is_encrypt	= is_encrypt;
+	dev_req->result		= -EBUSY;
+	dev_req->engine		= engine;
+	dev_req->complete	= spacc_aead_complete;
+
+	if (unlikely(spacc_aead_need_fallback(dev_req)))
+		return spacc_aead_do_fallback(req, alg_type, is_encrypt);
+
+	spacc_aead_make_ddts(dev_req, dev_req->giv);
+
+	err = -EINPROGRESS;
+	spin_lock_irqsave(&engine->hw_lock, flags);
+	if (unlikely(spacc_fifo_cmd_full(engine))) {
+		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
+			err = -EBUSY;
+			spin_unlock_irqrestore(&engine->hw_lock, flags);
+			goto out_free_ddts;
+		}
+		list_add_tail(&dev_req->list, &engine->pending);
+	} else {
+		++engine->in_flight;
+		list_add_tail(&dev_req->list, &engine->in_progress);
+		spacc_aead_submit(dev_req);
+	}
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+
+	goto out;
+
+out_free_ddts:
+	spacc_aead_free_ddts(dev_req);
+out:
+	return err;
+}
+
+static int spacc_aead_encrypt(struct aead_request *req)
+{
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_aead_setup(req, NULL, alg->type, 1);
+}
+
+static int spacc_aead_givencrypt(struct aead_givcrypt_request *req)
+{
+	struct crypto_aead *tfm = aead_givcrypt_reqtfm(req);
+	struct spacc_aead_ctx *ctx = crypto_aead_ctx(tfm);
+	size_t ivsize = crypto_aead_ivsize(tfm);
+	struct spacc_alg *alg = to_spacc_alg(tfm->base.__crt_alg);
+	unsigned len;
+	__be64 seq;
+
+	memcpy(req->areq.iv, ctx->salt, ivsize);
+	len = ivsize;
+	if (ivsize > sizeof(u64)) {
+		memset(req->giv, 0, ivsize - sizeof(u64));
+		len = sizeof(u64);
+	}
+	seq = cpu_to_be64(req->seq);
+	memcpy(req->giv + ivsize - len, &seq, len);
+
+	return spacc_aead_setup(&req->areq, req->giv, alg->type, 1);
+}
+
+static int spacc_aead_decrypt(struct aead_request *req)
+{
+	struct crypto_aead *aead = crypto_aead_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_aead_tfm(aead);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_aead_setup(req, NULL, alg->type, 0);
+}
+
+/*
+ * Initialise a new AEAD context. This is responsible for allocating the
+ * fallback cipher and initialising the context.
+ */
+static int spacc_aead_cra_init(struct crypto_tfm *tfm)
+{
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = spacc_alg->engine;
+
+	ctx->generic.flags = spacc_alg->type;
+	ctx->generic.engine = engine;
+	ctx->sw_cipher = crypto_alloc_aead(alg->cra_name, 0,
+					   CRYPTO_ALG_ASYNC |
+					   CRYPTO_ALG_NEED_FALLBACK);
+	if (IS_ERR(ctx->sw_cipher)) {
+		dev_warn(engine->dev, "failed to allocate fallback for %s\n",
+			 alg->cra_name);
+		ctx->sw_cipher = NULL;
+	}
+	ctx->generic.key_offs = spacc_alg->key_offs;
+	ctx->generic.iv_offs = spacc_alg->iv_offs;
+
+	get_random_bytes(ctx->salt, sizeof(ctx->salt));
+
+	tfm->crt_aead.reqsize = sizeof(struct spacc_req);
+
+	return 0;
+}
+
+/*
+ * Destructor for an AEAD context. This is called when the transform is freed
+ * and must free the fallback cipher.
+ */
+static void spacc_aead_cra_exit(struct crypto_tfm *tfm)
+{
+	struct spacc_aead_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->sw_cipher)
+		crypto_free_aead(ctx->sw_cipher);
+	ctx->sw_cipher = NULL;
+}
+
+/*
+ * Set the DES key for a block cipher transform. This also performs weak key
+ * checking if the transform has requested it.
+ */
+static int spacc_des_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
+			    unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	u32 tmp[DES_EXPKEY_WORDS];
+
+	if (len > DES3_EDE_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	if (unlikely(!des_ekey(tmp, key)) &&
+	    (crypto_ablkcipher_get_flags(cipher) & CRYPTO_TFM_REQ_WEAK_KEY)) {
+		tfm->crt_flags |= CRYPTO_TFM_RES_WEAK_KEY;
+		return -EINVAL;
+	}
+
+	memcpy(ctx->key, key, len);
+	ctx->key_len = len;
+
+	return 0;
+}
+
+/*
+ * Set the key for an AES block cipher. Some key lengths are not supported in
+ * hardware so this must also check whether a fallback is needed.
+ */
+static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
+			    unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	int err = 0;
+
+	if (len > AES_MAX_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		return -EINVAL;
+	}
+
+	/*
+	 * IPSec engine only supports 128 and 256 bit AES keys. If we get a
+	 * request for any other size (192 bits) then we need to do a software
+	 * fallback.
+	 */
+	if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+	    ctx->sw_cipher) {
+		/*
+		 * Set the fallback transform to use the same request flags as
+		 * the hardware transform.
+		 */
+		ctx->sw_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
+		ctx->sw_cipher->base.crt_flags |=
+			cipher->base.crt_flags & CRYPTO_TFM_REQ_MASK;
+
+		err = crypto_ablkcipher_setkey(ctx->sw_cipher, key, len);
+		if (err)
+			goto sw_setkey_failed;
+	} else if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+		   !ctx->sw_cipher)
+		err = -EINVAL;
+
+	memcpy(ctx->key, key, len);
+	ctx->key_len = len;
+
+sw_setkey_failed:
+	if (err && ctx->sw_cipher) {
+		tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
+		tfm->crt_flags |=
+			ctx->sw_cipher->base.crt_flags & CRYPTO_TFM_RES_MASK;
+	}
+
+	return err;
+}
+
+static int spacc_kasumi_f8_setkey(struct crypto_ablkcipher *cipher,
+				  const u8 *key, unsigned int len)
+{
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	int err = 0;
+
+	if (len > AES_MAX_KEY_SIZE) {
+		crypto_ablkcipher_set_flags(cipher, CRYPTO_TFM_RES_BAD_KEY_LEN);
+		err = -EINVAL;
+		goto out;
+	}
+
+	memcpy(ctx->key, key, len);
+	ctx->key_len = len;
+
+out:
+	return err;
+}
+
+static int spacc_ablk_need_fallback(struct spacc_req *req)
+{
+	struct spacc_ablk_ctx *ctx;
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+
+	ctx = crypto_tfm_ctx(tfm);
+
+	return (spacc_alg->ctrl_default & SPACC_CRYPTO_ALG_MASK) ==
+			SPA_CTRL_CIPH_ALG_AES &&
+			ctx->key_len != AES_KEYSIZE_128 &&
+			ctx->key_len != AES_KEYSIZE_256;
+}
+
+static void spacc_ablk_complete(struct spacc_req *req)
+{
+	struct ablkcipher_request *ablk_req =
+		container_of(req->req, struct ablkcipher_request, base);
+
+	if (ablk_req->src != ablk_req->dst) {
+		spacc_free_ddt(req, req->src_ddt, req->src_addr, ablk_req->src,
+			       ablk_req->nbytes, DMA_TO_DEVICE);
+		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
+			       ablk_req->nbytes, DMA_FROM_DEVICE);
+	} else
+		spacc_free_ddt(req, req->dst_ddt, req->dst_addr, ablk_req->dst,
+			       ablk_req->nbytes, DMA_BIDIRECTIONAL);
+
+	req->req->complete(req->req, req->result);
+}
+
+static int spacc_ablk_submit(struct spacc_req *req)
+{
+	struct crypto_tfm *tfm = req->req->tfm;
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct ablkcipher_request *ablk_req = ablkcipher_request_cast(req->req);
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = ctx->generic.engine;
+	u32 ctrl;
+
+	req->ctx_id = spacc_load_ctx(&ctx->generic, ctx->key,
+		ctx->key_len, ablk_req->info, alg->cra_ablkcipher.ivsize,
+		NULL, 0);
+
+	writel(req->src_addr, engine->regs + SPA_SRC_PTR_REG_OFFSET);
+	writel(req->dst_addr, engine->regs + SPA_DST_PTR_REG_OFFSET);
+	writel(0, engine->regs + SPA_OFFSET_REG_OFFSET);
+
+	writel(ablk_req->nbytes, engine->regs + SPA_PROC_LEN_REG_OFFSET);
+	writel(0, engine->regs + SPA_ICV_OFFSET_REG_OFFSET);
+	writel(0, engine->regs + SPA_AUX_INFO_REG_OFFSET);
+	writel(0, engine->regs + SPA_AAD_LEN_REG_OFFSET);
+
+	ctrl = spacc_alg->ctrl_default | (req->ctx_id << SPA_CTRL_CTX_IDX) |
+		(req->is_encrypt ? (1 << SPA_CTRL_ENCRYPT_IDX) :
+		 (1 << SPA_CTRL_KEY_EXP));
+
+	mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
+
+	writel(ctrl, engine->regs + SPA_CTRL_REG_OFFSET);
+
+	return -EINPROGRESS;
+}
+
+static int spacc_ablk_do_fallback(struct ablkcipher_request *req,
+				  unsigned alg_type, bool is_encrypt)
+{
+	struct crypto_tfm *old_tfm =
+	    crypto_ablkcipher_tfm(crypto_ablkcipher_reqtfm(req));
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(old_tfm);
+	int err;
+
+	if (!ctx->sw_cipher)
+		return -EINVAL;
+
+	/*
+	 * Change the request to use the software fallback transform, and once
+	 * the ciphering has completed, put the old transform back into the
+	 * request.
+	 */
+	ablkcipher_request_set_tfm(req, ctx->sw_cipher);
+	err = is_encrypt ? crypto_ablkcipher_encrypt(req) :
+		crypto_ablkcipher_decrypt(req);
+	ablkcipher_request_set_tfm(req, __crypto_ablkcipher_cast(old_tfm));
+
+	return err;
+}
+
+static int spacc_ablk_setup(struct ablkcipher_request *req, unsigned alg_type,
+			    bool is_encrypt)
+{
+	struct crypto_alg *alg = req->base.tfm->__crt_alg;
+	struct spacc_engine *engine = to_spacc_alg(alg)->engine;
+	struct spacc_req *dev_req = ablkcipher_request_ctx(req);
+	unsigned long flags;
+	int err = -ENOMEM;
+
+	dev_req->req		= &req->base;
+	dev_req->is_encrypt	= is_encrypt;
+	dev_req->engine		= engine;
+	dev_req->complete	= spacc_ablk_complete;
+	dev_req->result		= -EINPROGRESS;
+
+	if (unlikely(spacc_ablk_need_fallback(dev_req)))
+		return spacc_ablk_do_fallback(req, alg_type, is_encrypt);
+
+	/*
+	 * Create the DDT's for the engine. If we share the same source and
+	 * destination then we can optimize by reusing the DDT's.
+	 */
+	if (req->src != req->dst) {
+		dev_req->src_ddt = spacc_sg_to_ddt(engine, req->src,
+			req->nbytes, DMA_TO_DEVICE, &dev_req->src_addr);
+		if (!dev_req->src_ddt)
+			goto out;
+
+		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
+			req->nbytes, DMA_FROM_DEVICE, &dev_req->dst_addr);
+		if (!dev_req->dst_ddt)
+			goto out_free_src;
+	} else {
+		dev_req->dst_ddt = spacc_sg_to_ddt(engine, req->dst,
+			req->nbytes, DMA_BIDIRECTIONAL, &dev_req->dst_addr);
+		if (!dev_req->dst_ddt)
+			goto out;
+
+		dev_req->src_ddt = NULL;
+		dev_req->src_addr = dev_req->dst_addr;
+	}
+
+	err = -EINPROGRESS;
+	spin_lock_irqsave(&engine->hw_lock, flags);
+	/*
+	 * Check if the engine will accept the operation now. If it won't then
+	 * we either stick it on the end of a pending list if we can backlog,
+	 * or bailout with an error if not.
+	 */
+	if (unlikely(spacc_fifo_cmd_full(engine))) {
+		if (!(req->base.flags & CRYPTO_TFM_REQ_MAY_BACKLOG)) {
+			err = -EBUSY;
+			spin_unlock_irqrestore(&engine->hw_lock, flags);
+			goto out_free_ddts;
+		}
+		list_add_tail(&dev_req->list, &engine->pending);
+	} else {
+		++engine->in_flight;
+		list_add_tail(&dev_req->list, &engine->in_progress);
+		spacc_ablk_submit(dev_req);
+	}
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+
+	goto out;
+
+out_free_ddts:
+	spacc_free_ddt(dev_req, dev_req->dst_ddt, dev_req->dst_addr, req->dst,
+		       req->nbytes, req->src == req->dst ?
+		       DMA_BIDIRECTIONAL : DMA_FROM_DEVICE);
+out_free_src:
+	if (req->src != req->dst)
+		spacc_free_ddt(dev_req, dev_req->src_ddt, dev_req->src_addr,
+			       req->src, req->nbytes, DMA_TO_DEVICE);
+out:
+	return err;
+}
+
+static int spacc_ablk_cra_init(struct crypto_tfm *tfm)
+{
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+	struct crypto_alg *alg = tfm->__crt_alg;
+	struct spacc_alg *spacc_alg = to_spacc_alg(alg);
+	struct spacc_engine *engine = spacc_alg->engine;
+
+	ctx->generic.flags = spacc_alg->type;
+	ctx->generic.engine = engine;
+	if (alg->cra_flags & CRYPTO_ALG_NEED_FALLBACK) {
+		ctx->sw_cipher = crypto_alloc_ablkcipher(alg->cra_name, 0,
+				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK);
+		if (IS_ERR(ctx->sw_cipher)) {
+			dev_warn(engine->dev, "failed to allocate fallback for %s\n",
+				 alg->cra_name);
+			ctx->sw_cipher = NULL;
+		}
+	}
+	ctx->generic.key_offs = spacc_alg->key_offs;
+	ctx->generic.iv_offs = spacc_alg->iv_offs;
+
+	tfm->crt_ablkcipher.reqsize = sizeof(struct spacc_req);
+
+	return 0;
+}
+
+static void spacc_ablk_cra_exit(struct crypto_tfm *tfm)
+{
+	struct spacc_ablk_ctx *ctx = crypto_tfm_ctx(tfm);
+
+	if (ctx->sw_cipher)
+		crypto_free_ablkcipher(ctx->sw_cipher);
+	ctx->sw_cipher = NULL;
+}
+
+static int spacc_ablk_encrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_ablk_setup(req, alg->type, 1);
+}
+
+static int spacc_ablk_decrypt(struct ablkcipher_request *req)
+{
+	struct crypto_ablkcipher *cipher = crypto_ablkcipher_reqtfm(req);
+	struct crypto_tfm *tfm = crypto_ablkcipher_tfm(cipher);
+	struct spacc_alg *alg = to_spacc_alg(tfm->__crt_alg);
+
+	return spacc_ablk_setup(req, alg->type, 0);
+}
+
+static inline int spacc_fifo_stat_empty(struct spacc_engine *engine)
+{
+	return readl(engine->regs + SPA_FIFO_STAT_REG_OFFSET) &
+		SPA_FIFO_STAT_EMPTY;
+}
+
+static void spacc_process_done(struct spacc_engine *engine)
+{
+	struct spacc_req *req;
+	unsigned long flags;
+
+	spin_lock_irqsave(&engine->hw_lock, flags);
+
+	while (!spacc_fifo_stat_empty(engine)) {
+		req = list_first_entry(&engine->in_progress, struct spacc_req,
+				       list);
+		list_move_tail(&req->list, &engine->completed);
+
+		/* POP the status register. */
+		writel(~0, engine->regs + SPA_STAT_POP_REG_OFFSET);
+		req->result = (readl(engine->regs + SPA_STATUS_REG_OFFSET) &
+		     SPA_STATUS_RES_CODE_MASK) >> SPA_STATUS_RES_CODE_OFFSET;
+
+		/*
+		 * Convert the SPAcc error status into the standard POSIX error
+		 * codes.
+		 */
+		if (unlikely(req->result)) {
+			switch (req->result) {
+			case SPA_STATUS_ICV_FAIL:
+				req->result = -EBADMSG;
+				break;
+
+			case SPA_STATUS_MEMORY_ERROR:
+				dev_warn(engine->dev,
+					 "memory error triggered\n");
+				req->result = -EFAULT;
+				break;
+
+			case SPA_STATUS_BLOCK_ERROR:
+				dev_warn(engine->dev,
+					 "block error triggered\n");
+				req->result = -EIO;
+				break;
+			}
+		}
+	}
+
+	tasklet_schedule(&engine->complete);
+
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+}
+
+static irqreturn_t spacc_spacc_irq(int irq, void *dev)
+{
+	struct spacc_engine *engine = (struct spacc_engine *)dev;
+	u32 spacc_irq_stat = readl(engine->regs + SPA_IRQ_STAT_REG_OFFSET);
+
+	writel(spacc_irq_stat, engine->regs + SPA_IRQ_STAT_REG_OFFSET);
+	spacc_process_done(engine);
+
+	return IRQ_HANDLED;
+}
+
+static void spacc_packet_timeout(unsigned long data)
+{
+	struct spacc_engine *engine = (struct spacc_engine *)data;
+
+	spacc_process_done(engine);
+}
+
+static int spacc_req_submit(struct spacc_req *req)
+{
+	struct crypto_alg *alg = req->req->tfm->__crt_alg;
+
+	if (CRYPTO_ALG_TYPE_AEAD == (CRYPTO_ALG_TYPE_MASK & alg->cra_flags))
+		return spacc_aead_submit(req);
+	else
+		return spacc_ablk_submit(req);
+}
+
+static void spacc_spacc_complete(unsigned long data)
+{
+	struct spacc_engine *engine = (struct spacc_engine *)data;
+	struct spacc_req *req, *tmp;
+	unsigned long flags;
+	int num_removed = 0;
+	LIST_HEAD(completed);
+
+	spin_lock_irqsave(&engine->hw_lock, flags);
+	list_splice_init(&engine->completed, &completed);
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+
+	list_for_each_entry_safe(req, tmp, &completed, list) {
+		++num_removed;
+		req->complete(req);
+	}
+
+	/* Try and fill the engine back up again. */
+	spin_lock_irqsave(&engine->hw_lock, flags);
+
+	engine->in_flight -= num_removed;
+
+	list_for_each_entry_safe(req, tmp, &engine->pending, list) {
+		if (spacc_fifo_cmd_full(engine))
+			break;
+
+		list_move_tail(&req->list, &engine->in_progress);
+		++engine->in_flight;
+		req->result = spacc_req_submit(req);
+	}
+
+	if (engine->in_flight)
+		mod_timer(&engine->packet_timeout, jiffies + PACKET_TIMEOUT);
+
+	spin_unlock_irqrestore(&engine->hw_lock, flags);
+}
+
+#ifdef CONFIG_PM
+static int spacc_suspend(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct spacc_engine *engine = platform_get_drvdata(pdev);
+
+	/*
+	 * We only support standby mode. All we have to do is gate the clock to
+	 * the spacc. The hardware will preserve state until we turn it back
+	 * on again.
+	 */
+	clk_disable(engine->clk);
+
+	return 0;
+}
+
+static int spacc_resume(struct device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev);
+	struct spacc_engine *engine = platform_get_drvdata(pdev);
+
+	return clk_enable(engine->clk);
+}
+
+static const struct dev_pm_ops spacc_pm_ops = {
+	.suspend	= spacc_suspend,
+	.resume		= spacc_resume,
+};
+#endif /* CONFIG_PM */
+
+static inline struct spacc_engine *spacc_dev_to_engine(struct device *dev)
+{
+	return dev ? platform_get_drvdata(to_platform_device(dev)) : NULL;
+}
+
+static ssize_t spacc_stat_irq_thresh_show(struct device *dev,
+					  struct device_attribute *attr,
+					  char *buf)
+{
+	struct spacc_engine *engine = spacc_dev_to_engine(dev);
+
+	return snprintf(buf, PAGE_SIZE, "%u\n", engine->stat_irq_thresh);
+}
+
+static ssize_t spacc_stat_irq_thresh_store(struct device *dev,
+					   struct device_attribute *attr,
+					   const char *buf, size_t len)
+{
+	struct spacc_engine *engine = spacc_dev_to_engine(dev);
+	unsigned long thresh;
+
+	if (strict_strtoul(buf, 0, &thresh))
+		return -EINVAL;
+
+	thresh = clamp(thresh, 1UL, engine->fifo_sz - 1);
+
+	engine->stat_irq_thresh = thresh;
+	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
+	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
+
+	return len;
+}
+static DEVICE_ATTR(stat_irq_thresh, 0644, spacc_stat_irq_thresh_show,
+		   spacc_stat_irq_thresh_store);
+
+static struct spacc_alg ipsec_engine_algs[] = {
+	{
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC,
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.alg = {
+			.cra_name = "cbc(aes)",
+			.cra_driver_name = "cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				     CRYPTO_ALG_ASYNC |
+				     CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_aes_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = AES_MIN_KEY_SIZE,
+				.max_keysize = AES_MAX_KEY_SIZE,
+				.ivsize = AES_BLOCK_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_ECB,
+		.alg = {
+			.cra_name = "ecb(aes)",
+			.cra_driver_name = "ecb-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER |
+				CRYPTO_ALG_ASYNC | CRYPTO_ALG_NEED_FALLBACK,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_aes_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = AES_MIN_KEY_SIZE,
+				.max_keysize = AES_MAX_KEY_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
+		.alg = {
+			.cra_name = "cbc(des)",
+			.cra_driver_name = "cbc-des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES_KEY_SIZE,
+				.max_keysize = DES_KEY_SIZE,
+				.ivsize = DES_BLOCK_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
+		.alg = {
+			.cra_name = "ecb(des)",
+			.cra_driver_name = "ecb-des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES_KEY_SIZE,
+				.max_keysize = DES_KEY_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC,
+		.alg = {
+			.cra_name = "cbc(des3_ede)",
+			.cra_driver_name = "cbc-des3-ede-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES3_EDE_KEY_SIZE,
+				.max_keysize = DES3_EDE_KEY_SIZE,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_ECB,
+		.alg = {
+			.cra_name = "ecb(des3_ede)",
+			.cra_driver_name = "ecb-des3-ede-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_ABLKCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_des_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = DES3_EDE_KEY_SIZE,
+				.max_keysize = DES3_EDE_KEY_SIZE,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+	{
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA | SPA_CTRL_HASH_MODE_HMAC,
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.alg = {
+			.cra_name = "authenc(hmac(sha1),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-sha1-cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = SHA1_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA256 |
+				SPA_CTRL_HASH_MODE_HMAC,
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.alg = {
+			.cra_name = "authenc(hmac(sha256),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-sha256-cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = SHA256_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = 0,
+		.iv_offs = AES_MAX_KEY_SIZE,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_MD5 | SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(md5),cbc(aes))",
+			.cra_driver_name = "authenc-hmac-md5-cbc-aes-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = AES_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = AES_BLOCK_SIZE,
+				.maxauthsize = MD5_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA | SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(sha1),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-sha1-cbc-3des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = SHA1_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_AES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_SHA256 |
+				SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(sha256),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-sha256-cbc-3des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = SHA256_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+	{
+		.key_offs = DES_BLOCK_SIZE,
+		.iv_offs = 0,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_DES | SPA_CTRL_CIPH_MODE_CBC |
+				SPA_CTRL_HASH_ALG_MD5 | SPA_CTRL_HASH_MODE_HMAC,
+		.alg = {
+			.cra_name = "authenc(hmac(md5),cbc(des3_ede))",
+			.cra_driver_name = "authenc-hmac-md5-cbc-3des-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_AEAD | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = DES3_EDE_BLOCK_SIZE,
+			.cra_ctxsize = sizeof(struct spacc_aead_ctx),
+			.cra_type = &crypto_aead_type,
+			.cra_module = THIS_MODULE,
+			.cra_aead = {
+				.setkey = spacc_aead_setkey,
+				.setauthsize = spacc_aead_setauthsize,
+				.encrypt = spacc_aead_encrypt,
+				.decrypt = spacc_aead_decrypt,
+				.givencrypt = spacc_aead_givencrypt,
+				.ivsize = DES3_EDE_BLOCK_SIZE,
+				.maxauthsize = MD5_DIGEST_SIZE,
+			},
+			.cra_init = spacc_aead_cra_init,
+			.cra_exit = spacc_aead_cra_exit,
+		},
+	},
+};
+
+static struct spacc_alg l2_engine_algs[] = {
+	{
+		.key_offs = 0,
+		.iv_offs = SPACC_CRYPTO_KASUMI_F8_KEY_LEN,
+		.ctrl_default = SPA_CTRL_CIPH_ALG_KASUMI |
+				SPA_CTRL_CIPH_MODE_F8,
+		.alg = {
+			.cra_name = "f8(kasumi)",
+			.cra_driver_name = "f8-kasumi-picoxcell",
+			.cra_priority = SPACC_CRYPTO_ALG_PRIORITY,
+			.cra_flags = CRYPTO_ALG_TYPE_GIVCIPHER | CRYPTO_ALG_ASYNC,
+			.cra_blocksize = 8,
+			.cra_ctxsize = sizeof(struct spacc_ablk_ctx),
+			.cra_type = &crypto_ablkcipher_type,
+			.cra_module = THIS_MODULE,
+			.cra_ablkcipher = {
+				.setkey = spacc_kasumi_f8_setkey,
+				.encrypt = spacc_ablk_encrypt,
+				.decrypt = spacc_ablk_decrypt,
+				.min_keysize = 16,
+				.max_keysize = 16,
+				.ivsize = 8,
+			},
+			.cra_init = spacc_ablk_cra_init,
+			.cra_exit = spacc_ablk_cra_exit,
+		},
+	},
+};
+
+static int __devinit spacc_probe(struct platform_device *pdev,
+				 unsigned max_ctxs, size_t cipher_pg_sz,
+				 size_t hash_pg_sz, size_t fifo_sz,
+				 struct spacc_alg *algs, size_t num_algs)
+{
+	int i, err, ret = -EINVAL;
+	struct resource *mem, *irq;
+	struct spacc_engine *engine = devm_kzalloc(&pdev->dev, sizeof(*engine),
+						   GFP_KERNEL);
+	if (!engine)
+		return -ENOMEM;
+
+	engine->max_ctxs	= max_ctxs;
+	engine->cipher_pg_sz	= cipher_pg_sz;
+	engine->hash_pg_sz	= hash_pg_sz;
+	engine->fifo_sz		= fifo_sz;
+	engine->algs		= algs;
+	engine->num_algs	= num_algs;
+	engine->name		= dev_name(&pdev->dev);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!mem || !irq) {
+		dev_err(&pdev->dev, "no memory/irq resource for engine\n");
+		return -ENXIO;
+	}
+
+	if (!devm_request_mem_region(&pdev->dev, mem->start, resource_size(mem),
+				     engine->name))
+		return -ENOMEM;
+
+	engine->regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem));
+	if (!engine->regs) {
+		dev_err(&pdev->dev, "memory map failed\n");
+		return -ENOMEM;
+	}
+
+	if (devm_request_irq(&pdev->dev, irq->start, spacc_spacc_irq, 0,
+			     engine->name, engine)) {
+		dev_err(engine->dev, "failed to request IRQ\n");
+		return -EBUSY;
+	}
+
+	engine->dev		= &pdev->dev;
+	engine->cipher_ctx_base = engine->regs + SPA_CIPH_KEY_BASE_REG_OFFSET;
+	engine->hash_key_base	= engine->regs + SPA_HASH_KEY_BASE_REG_OFFSET;
+
+	engine->req_pool = dmam_pool_create(engine->name, engine->dev,
+		MAX_DDT_LEN * sizeof(struct spacc_ddt), 8, SZ_64K);
+	if (!engine->req_pool)
+		return -ENOMEM;
+
+	spin_lock_init(&engine->hw_lock);
+
+	engine->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(engine->clk)) {
+		dev_info(&pdev->dev, "clk unavailable\n");
+		device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+		return PTR_ERR(engine->clk);
+	}
+
+	if (clk_enable(engine->clk)) {
+		dev_info(&pdev->dev, "unable to enable clk\n");
+		clk_put(engine->clk);
+		return -EIO;
+	}
+
+	err = device_create_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+	if (err) {
+		clk_disable(engine->clk);
+		clk_put(engine->clk);
+		return err;
+	}
+
+
+	/*
+	 * Use an IRQ threshold of 50% as a default. This seems to be a
+	 * reasonable trade off of latency against throughput but can be
+	 * changed at runtime.
+	 */
+	engine->stat_irq_thresh = (engine->fifo_sz / 2);
+
+	/*
+	 * Configure the interrupts. We only use the STAT_CNT interrupt as we
+	 * only submit a new packet for processing when we complete another in
+	 * the queue. This minimizes time spent in the interrupt handler.
+	 */
+	writel(engine->stat_irq_thresh << SPA_IRQ_CTRL_STAT_CNT_OFFSET,
+	       engine->regs + SPA_IRQ_CTRL_REG_OFFSET);
+	writel(SPA_IRQ_EN_STAT_EN | SPA_IRQ_EN_GLBL_EN,
+	       engine->regs + SPA_IRQ_EN_REG_OFFSET);
+
+	setup_timer(&engine->packet_timeout, spacc_packet_timeout,
+		    (unsigned long)engine);
+
+	INIT_LIST_HEAD(&engine->pending);
+	INIT_LIST_HEAD(&engine->completed);
+	INIT_LIST_HEAD(&engine->in_progress);
+	engine->in_flight = 0;
+	tasklet_init(&engine->complete, spacc_spacc_complete,
+		     (unsigned long)engine);
+
+	platform_set_drvdata(pdev, engine);
+
+	INIT_LIST_HEAD(&engine->registered_algs);
+	for (i = 0; i < engine->num_algs; ++i) {
+		engine->algs[i].engine = engine;
+		err = crypto_register_alg(&engine->algs[i].alg);
+		if (!err) {
+			list_add_tail(&engine->algs[i].entry,
+				      &engine->registered_algs);
+			ret = 0;
+		}
+		if (err)
+			dev_err(engine->dev, "failed to register alg \"%s\"\n",
+				engine->algs[i].alg.cra_name);
+		else
+			dev_dbg(engine->dev, "registered alg \"%s\"\n",
+				engine->algs[i].alg.cra_name);
+	}
+
+	return ret;
+}
+
+static int __devexit spacc_remove(struct platform_device *pdev)
+{
+	struct spacc_alg *alg, *next;
+	struct spacc_engine *engine = platform_get_drvdata(pdev);
+
+	del_timer_sync(&engine->packet_timeout);
+	device_remove_file(&pdev->dev, &dev_attr_stat_irq_thresh);
+
+	list_for_each_entry_safe(alg, next, &engine->registered_algs, entry) {
+		list_del(&alg->entry);
+		crypto_unregister_alg(&alg->alg);
+	}
+
+	clk_disable(engine->clk);
+	clk_put(engine->clk);
+
+	return 0;
+}
+
+static int __devinit ipsec_probe(struct platform_device *pdev)
+{
+	return spacc_probe(pdev, SPACC_CRYPTO_IPSEC_MAX_CTXS,
+			   SPACC_CRYPTO_IPSEC_CIPHER_PG_SZ,
+			   SPACC_CRYPTO_IPSEC_HASH_PG_SZ,
+			   SPACC_CRYPTO_IPSEC_FIFO_SZ, ipsec_engine_algs,
+			   ARRAY_SIZE(ipsec_engine_algs));
+}
+
+static struct platform_driver ipsec_driver = {
+	.probe		= ipsec_probe,
+	.remove		= __devexit_p(spacc_remove),
+	.driver		= {
+		.name	= "picoxcell-ipsec",
+#ifdef CONFIG_PM
+		.pm	= &spacc_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __devinit l2_probe(struct platform_device *pdev)
+{
+	return spacc_probe(pdev, SPACC_CRYPTO_L2_MAX_CTXS,
+			   SPACC_CRYPTO_L2_CIPHER_PG_SZ,
+			   SPACC_CRYPTO_L2_HASH_PG_SZ, SPACC_CRYPTO_L2_FIFO_SZ,
+			   l2_engine_algs, ARRAY_SIZE(l2_engine_algs));
+}
+
+static struct platform_driver l2_driver = {
+	.probe		= l2_probe,
+	.remove		= __devexit_p(spacc_remove),
+	.driver		= {
+		.name	= "picoxcell-l2",
+#ifdef CONFIG_PM
+		.pm	= &spacc_pm_ops,
+#endif /* CONFIG_PM */
+	},
+};
+
+static int __init spacc_init(void)
+{
+	int ret = platform_driver_register(&ipsec_driver);
+	if (ret) {
+		pr_err("failed to register ipsec spacc driver");
+		goto out;
+	}
+
+	ret = platform_driver_register(&l2_driver);
+	if (ret) {
+		pr_err("failed to register l2 spacc driver");
+		goto l2_failed;
+	}
+
+	return 0;
+
+l2_failed:
+	platform_driver_unregister(&ipsec_driver);
+out:
+	return ret;
+}
+module_init(spacc_init);
+
+static void __exit spacc_exit(void)
+{
+	platform_driver_unregister(&ipsec_driver);
+	platform_driver_unregister(&l2_driver);
+}
+module_exit(spacc_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jamie Iles");
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/picoxcell_crypto_regs.h linux-libre-2.6.39-gnu/drivers/crypto/picoxcell_crypto_regs.h
--- linux-libre-2.6.38-gnu/drivers/crypto/picoxcell_crypto_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/crypto/picoxcell_crypto_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2010 Picochip Ltd., Jamie Iles
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __PICOXCELL_CRYPTO_REGS_H__
+#define __PICOXCELL_CRYPTO_REGS_H__
+
+#define SPA_STATUS_OK			0
+#define SPA_STATUS_ICV_FAIL		1
+#define SPA_STATUS_MEMORY_ERROR		2
+#define SPA_STATUS_BLOCK_ERROR		3
+
+#define SPA_IRQ_CTRL_STAT_CNT_OFFSET	16
+#define SPA_IRQ_STAT_STAT_MASK		(1 << 4)
+#define SPA_FIFO_STAT_STAT_OFFSET	16
+#define SPA_FIFO_STAT_STAT_CNT_MASK	(0x3F << SPA_FIFO_STAT_STAT_OFFSET)
+#define SPA_STATUS_RES_CODE_OFFSET	24
+#define SPA_STATUS_RES_CODE_MASK	(0x3 << SPA_STATUS_RES_CODE_OFFSET)
+#define SPA_KEY_SZ_CTX_INDEX_OFFSET	8
+#define SPA_KEY_SZ_CIPHER_OFFSET	31
+
+#define SPA_IRQ_EN_REG_OFFSET		0x00000000
+#define SPA_IRQ_STAT_REG_OFFSET		0x00000004
+#define SPA_IRQ_CTRL_REG_OFFSET		0x00000008
+#define SPA_FIFO_STAT_REG_OFFSET	0x0000000C
+#define SPA_SDMA_BRST_SZ_REG_OFFSET	0x00000010
+#define SPA_SRC_PTR_REG_OFFSET		0x00000020
+#define SPA_DST_PTR_REG_OFFSET		0x00000024
+#define SPA_OFFSET_REG_OFFSET		0x00000028
+#define SPA_AAD_LEN_REG_OFFSET		0x0000002C
+#define SPA_PROC_LEN_REG_OFFSET		0x00000030
+#define SPA_ICV_LEN_REG_OFFSET		0x00000034
+#define SPA_ICV_OFFSET_REG_OFFSET	0x00000038
+#define SPA_SW_CTRL_REG_OFFSET		0x0000003C
+#define SPA_CTRL_REG_OFFSET		0x00000040
+#define SPA_AUX_INFO_REG_OFFSET		0x0000004C
+#define SPA_STAT_POP_REG_OFFSET		0x00000050
+#define SPA_STATUS_REG_OFFSET		0x00000054
+#define SPA_KEY_SZ_REG_OFFSET		0x00000100
+#define SPA_CIPH_KEY_BASE_REG_OFFSET	0x00004000
+#define SPA_HASH_KEY_BASE_REG_OFFSET	0x00008000
+#define SPA_RC4_CTX_BASE_REG_OFFSET	0x00020000
+
+#define SPA_IRQ_EN_REG_RESET		0x00000000
+#define SPA_IRQ_CTRL_REG_RESET		0x00000000
+#define SPA_FIFO_STAT_REG_RESET		0x00000000
+#define SPA_SDMA_BRST_SZ_REG_RESET	0x00000000
+#define SPA_SRC_PTR_REG_RESET		0x00000000
+#define SPA_DST_PTR_REG_RESET		0x00000000
+#define SPA_OFFSET_REG_RESET		0x00000000
+#define SPA_AAD_LEN_REG_RESET		0x00000000
+#define SPA_PROC_LEN_REG_RESET		0x00000000
+#define SPA_ICV_LEN_REG_RESET		0x00000000
+#define SPA_ICV_OFFSET_REG_RESET	0x00000000
+#define SPA_SW_CTRL_REG_RESET		0x00000000
+#define SPA_CTRL_REG_RESET		0x00000000
+#define SPA_AUX_INFO_REG_RESET		0x00000000
+#define SPA_STAT_POP_REG_RESET		0x00000000
+#define SPA_STATUS_REG_RESET		0x00000000
+#define SPA_KEY_SZ_REG_RESET		0x00000000
+
+#define SPA_CTRL_HASH_ALG_IDX		4
+#define SPA_CTRL_CIPH_MODE_IDX		8
+#define SPA_CTRL_HASH_MODE_IDX		12
+#define SPA_CTRL_CTX_IDX		16
+#define SPA_CTRL_ENCRYPT_IDX		24
+#define SPA_CTRL_AAD_COPY		25
+#define SPA_CTRL_ICV_PT			26
+#define SPA_CTRL_ICV_ENC		27
+#define SPA_CTRL_ICV_APPEND		28
+#define SPA_CTRL_KEY_EXP		29
+
+#define SPA_KEY_SZ_CXT_IDX		8
+#define SPA_KEY_SZ_CIPHER_IDX		31
+
+#define SPA_IRQ_EN_CMD0_EN		(1 << 0)
+#define SPA_IRQ_EN_STAT_EN		(1 << 4)
+#define SPA_IRQ_EN_GLBL_EN		(1 << 31)
+
+#define SPA_CTRL_CIPH_ALG_NULL		0x00
+#define SPA_CTRL_CIPH_ALG_DES		0x01
+#define SPA_CTRL_CIPH_ALG_AES		0x02
+#define SPA_CTRL_CIPH_ALG_RC4		0x03
+#define SPA_CTRL_CIPH_ALG_MULTI2	0x04
+#define SPA_CTRL_CIPH_ALG_KASUMI	0x05
+
+#define SPA_CTRL_HASH_ALG_NULL		(0x00 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_MD5		(0x01 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA		(0x02 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA224	(0x03 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA256	(0x04 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA384	(0x05 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_SHA512	(0x06 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_AESMAC	(0x07 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_AESCMAC	(0x08 << SPA_CTRL_HASH_ALG_IDX)
+#define SPA_CTRL_HASH_ALG_KASF9		(0x09 << SPA_CTRL_HASH_ALG_IDX)
+
+#define SPA_CTRL_CIPH_MODE_NULL		(0x00 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_ECB		(0x00 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CBC		(0x01 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CTR		(0x02 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CCM		(0x03 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_GCM		(0x05 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_OFB		(0x07 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_CFB		(0x08 << SPA_CTRL_CIPH_MODE_IDX)
+#define SPA_CTRL_CIPH_MODE_F8		(0x09 << SPA_CTRL_CIPH_MODE_IDX)
+
+#define SPA_CTRL_HASH_MODE_RAW		(0x00 << SPA_CTRL_HASH_MODE_IDX)
+#define SPA_CTRL_HASH_MODE_SSLMAC	(0x01 << SPA_CTRL_HASH_MODE_IDX)
+#define SPA_CTRL_HASH_MODE_HMAC		(0x02 << SPA_CTRL_HASH_MODE_IDX)
+
+#define SPA_FIFO_STAT_EMPTY		(1 << 31)
+#define SPA_FIFO_CMD_FULL		(1 << 7)
+
+#endif /* __PICOXCELL_CRYPTO_REGS_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/crypto/talitos.c linux-libre-2.6.39-gnu/drivers/crypto/talitos.c
--- linux-libre-2.6.38-gnu/drivers/crypto/talitos.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/crypto/talitos.c	2011-05-19 00:06:34.000000000 -0400
@@ -2402,8 +2402,7 @@
 	return t_alg;
 }
 
-static int talitos_probe(struct platform_device *ofdev,
-			 const struct of_device_id *match)
+static int talitos_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -2580,7 +2579,7 @@
 };
 MODULE_DEVICE_TABLE(of, talitos_match);
 
-static struct of_platform_driver talitos_driver = {
+static struct platform_driver talitos_driver = {
 	.driver = {
 		.name = "talitos",
 		.owner = THIS_MODULE,
@@ -2592,13 +2591,13 @@
 
 static int __init talitos_init(void)
 {
-	return of_register_platform_driver(&talitos_driver);
+	return platform_driver_register(&talitos_driver);
 }
 module_init(talitos_init);
 
 static void __exit talitos_exit(void)
 {
-	of_unregister_platform_driver(&talitos_driver);
+	platform_driver_unregister(&talitos_driver);
 }
 module_exit(talitos_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/dca/dca-core.c linux-libre-2.6.39-gnu/drivers/dca/dca-core.c
--- linux-libre-2.6.38-gnu/drivers/dca/dca-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dca/dca-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,10 +111,8 @@
 	/* at this point only one domain in the list is expected */
 	domain = list_first_entry(&dca_domains, struct dca_domain, node);
 
-	list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node) {
-		list_del(&dca->node);
-		list_add(&dca->node, &unregistered_providers);
-	}
+	list_for_each_entry_safe(dca, _dca, &domain->dca_providers, node)
+		list_move(&dca->node, &unregistered_providers);
 
 	dca_free_domain(domain);
 
diff -druN linux-libre-2.6.38-gnu/drivers/dma/amba-pl08x.c linux-libre-2.6.39-gnu/drivers/dma/amba-pl08x.c
--- linux-libre-2.6.38-gnu/drivers/dma/amba-pl08x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/amba-pl08x.c	2011-05-19 00:06:34.000000000 -0400
@@ -1845,7 +1845,7 @@
 }
 #endif
 
-static int pl08x_probe(struct amba_device *adev, struct amba_id *id)
+static int pl08x_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct pl08x_driver_data *pl08x;
 	const struct vendor_data *vd = id->data;
diff -druN linux-libre-2.6.38-gnu/drivers/dma/at_hdmac.c linux-libre-2.6.39-gnu/drivers/dma/at_hdmac.c
--- linux-libre-2.6.38-gnu/drivers/dma/at_hdmac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/at_hdmac.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 /**
  * atc_assign_cookie - compute and assign new cookie
  * @atchan: channel we work on
- * @desc: descriptor to asign cookie for
+ * @desc: descriptor to assign cookie for
  *
  * Called with atchan->lock held and bh disabled
  */
diff -druN linux-libre-2.6.38-gnu/drivers/dma/coh901318.c linux-libre-2.6.39-gnu/drivers/dma/coh901318.c
--- linux-libre-2.6.38-gnu/drivers/dma/coh901318.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/coh901318.c	2011-05-19 00:06:34.000000000 -0400
@@ -529,7 +529,7 @@
 	val = readl(virtbase + COH901318_CX_CFG +
 		    COH901318_CX_CFG_SPACING * channel);
 
-	/* Stopping infinit transfer */
+	/* Stopping infinite transfer */
 	if ((val & COH901318_CX_CTRL_TC_ENABLE) == 0 &&
 	    (val & COH901318_CX_CFG_CH_ENABLE))
 		cohc->stopped = 1;
@@ -849,7 +849,7 @@
 
 				/* Must clear TC interrupt before calling
 				 * dma_tc_handle
-				 * in case tc_handle initate a new dma job
+				 * in case tc_handle initiate a new dma job
 				 */
 				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR1);
 
@@ -894,7 +894,7 @@
 				}
 				/* Must clear TC interrupt before calling
 				 * dma_tc_handle
-				 * in case tc_handle initate a new dma job
+				 * in case tc_handle initiate a new dma job
 				 */
 				__set_bit(i, virtbase + COH901318_TC_INT_CLEAR2);
 
diff -druN linux-libre-2.6.38-gnu/drivers/dma/dmatest.c linux-libre-2.6.39-gnu/drivers/dma/dmatest.c
--- linux-libre-2.6.38-gnu/drivers/dma/dmatest.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/dmatest.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,6 +54,11 @@
 MODULE_PARM_DESC(pq_sources,
 		"Number of p+q source buffers (default: 3)");
 
+static int timeout = 3000;
+module_param(timeout, uint, S_IRUGO);
+MODULE_PARM_DESC(timeout, "Transfer Timeout in msec (default: 3000), \
+		Pass -1 for infinite timeout");
+
 /*
  * Initialization patterns. All bytes in the source buffer has bit 7
  * set, all bytes in the destination buffer has bit 7 cleared.
@@ -285,7 +290,12 @@
 
 	set_user_nice(current, 10);
 
-	flags = DMA_CTRL_ACK | DMA_COMPL_SKIP_DEST_UNMAP | DMA_PREP_INTERRUPT;
+	/*
+	 * src buffers are freed by the DMAEngine code with dma_unmap_single()
+	 * dst buffers are freed by ourselves below
+	 */
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT
+	      | DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SRC_UNMAP_SINGLE;
 
 	while (!kthread_should_stop()
 	       && !(iterations && total_tests >= iterations)) {
@@ -294,7 +304,7 @@
 		dma_addr_t dma_srcs[src_cnt];
 		dma_addr_t dma_dsts[dst_cnt];
 		struct completion cmp;
-		unsigned long tmo = msecs_to_jiffies(3000);
+		unsigned long tmo = msecs_to_jiffies(timeout);
 		u8 align = 0;
 
 		total_tests++;
diff -druN linux-libre-2.6.38-gnu/drivers/dma/dw_dmac.c linux-libre-2.6.39-gnu/drivers/dma/dw_dmac.c
--- linux-libre-2.6.38-gnu/drivers/dma/dw_dmac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/dw_dmac.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,26 +32,30 @@
  * which does not support descriptor writeback.
  */
 
-/* NOTE:  DMS+SMS is system-specific. We should get this information
- * from the platform code somehow.
- */
-#define DWC_DEFAULT_CTLLO	(DWC_CTLL_DST_MSIZE(0)		\
-				| DWC_CTLL_SRC_MSIZE(0)		\
-				| DWC_CTLL_DMS(0)		\
-				| DWC_CTLL_SMS(1)		\
-				| DWC_CTLL_LLP_D_EN		\
-				| DWC_CTLL_LLP_S_EN)
+#define DWC_DEFAULT_CTLLO(private) ({				\
+		struct dw_dma_slave *__slave = (private);	\
+		int dms = __slave ? __slave->dst_master : 0;	\
+		int sms = __slave ? __slave->src_master : 1;	\
+		u8 smsize = __slave ? __slave->src_msize : DW_DMA_MSIZE_16; \
+		u8 dmsize = __slave ? __slave->dst_msize : DW_DMA_MSIZE_16; \
+								\
+		(DWC_CTLL_DST_MSIZE(dmsize)			\
+		 | DWC_CTLL_SRC_MSIZE(smsize)			\
+		 | DWC_CTLL_LLP_D_EN				\
+		 | DWC_CTLL_LLP_S_EN				\
+		 | DWC_CTLL_DMS(dms)				\
+		 | DWC_CTLL_SMS(sms));				\
+	})
 
 /*
  * This is configuration-dependent and usually a funny size like 4095.
- * Let's round it down to the nearest power of two.
  *
  * Note that this is a transfer count, i.e. if we transfer 32-bit
- * words, we can do 8192 bytes per descriptor.
+ * words, we can do 16380 bytes per descriptor.
  *
  * This parameter is also system-specific.
  */
-#define DWC_MAX_COUNT	2048U
+#define DWC_MAX_COUNT	4095U
 
 /*
  * Number of descriptors to allocate for each channel. This should be
@@ -84,11 +88,6 @@
 	return list_entry(dwc->active_list.next, struct dw_desc, desc_node);
 }
 
-static struct dw_desc *dwc_first_queued(struct dw_dma_chan *dwc)
-{
-	return list_entry(dwc->queue.next, struct dw_desc, desc_node);
-}
-
 static struct dw_desc *dwc_desc_get(struct dw_dma_chan *dwc)
 {
 	struct dw_desc *desc, *_desc;
@@ -201,6 +200,7 @@
 	dma_async_tx_callback		callback;
 	void				*param;
 	struct dma_async_tx_descriptor	*txd = &desc->txd;
+	struct dw_desc			*child;
 
 	dev_vdbg(chan2dev(&dwc->chan), "descriptor %u complete\n", txd->cookie);
 
@@ -209,6 +209,12 @@
 	param = txd->callback_param;
 
 	dwc_sync_desc_for_cpu(dwc, desc);
+
+	/* async_tx_ack */
+	list_for_each_entry(child, &desc->tx_list, desc_node)
+		async_tx_ack(&child->txd);
+	async_tx_ack(&desc->txd);
+
 	list_splice_init(&desc->tx_list, &dwc->free_list);
 	list_move(&desc->desc_node, &dwc->free_list);
 
@@ -259,10 +265,11 @@
 	 * Submit queued descriptors ASAP, i.e. before we go through
 	 * the completed ones.
 	 */
-	if (!list_empty(&dwc->queue))
-		dwc_dostart(dwc, dwc_first_queued(dwc));
 	list_splice_init(&dwc->active_list, &list);
-	list_splice_init(&dwc->queue, &dwc->active_list);
+	if (!list_empty(&dwc->queue)) {
+		list_move(dwc->queue.next, &dwc->active_list);
+		dwc_dostart(dwc, dwc_first_active(dwc));
+	}
 
 	list_for_each_entry_safe(desc, _desc, &list, desc_node)
 		dwc_descriptor_complete(dwc, desc);
@@ -291,6 +298,9 @@
 		return;
 	}
 
+	if (list_empty(&dwc->active_list))
+		return;
+
 	dev_vdbg(chan2dev(&dwc->chan), "scan_descriptors: llp=0x%x\n", llp);
 
 	list_for_each_entry_safe(desc, _desc, &dwc->active_list, desc_node) {
@@ -319,8 +329,8 @@
 		cpu_relax();
 
 	if (!list_empty(&dwc->queue)) {
-		dwc_dostart(dwc, dwc_first_queued(dwc));
-		list_splice_init(&dwc->queue, &dwc->active_list);
+		list_move(dwc->queue.next, &dwc->active_list);
+		dwc_dostart(dwc, dwc_first_active(dwc));
 	}
 }
 
@@ -346,7 +356,7 @@
 	 */
 	bad_desc = dwc_first_active(dwc);
 	list_del_init(&bad_desc->desc_node);
-	list_splice_init(&dwc->queue, dwc->active_list.prev);
+	list_move(dwc->queue.next, dwc->active_list.prev);
 
 	/* Clear the error flag and try to restart the controller */
 	dma_writel(dw, CLEAR.ERROR, dwc->mask);
@@ -541,8 +551,8 @@
 	if (list_empty(&dwc->active_list)) {
 		dev_vdbg(chan2dev(tx->chan), "tx_submit: started %u\n",
 				desc->txd.cookie);
-		dwc_dostart(dwc, desc);
 		list_add_tail(&desc->desc_node, &dwc->active_list);
+		dwc_dostart(dwc, dwc_first_active(dwc));
 	} else {
 		dev_vdbg(chan2dev(tx->chan), "tx_submit: queued %u\n",
 				desc->txd.cookie);
@@ -581,14 +591,16 @@
 	 * We can be a lot more clever here, but this should take care
 	 * of the most common optimization.
 	 */
-	if (!((src | dest  | len) & 3))
+	if (!((src | dest  | len) & 7))
+		src_width = dst_width = 3;
+	else if (!((src | dest  | len) & 3))
 		src_width = dst_width = 2;
 	else if (!((src | dest | len) & 1))
 		src_width = dst_width = 1;
 	else
 		src_width = dst_width = 0;
 
-	ctllo = DWC_DEFAULT_CTLLO
+	ctllo = DWC_DEFAULT_CTLLO(chan->private)
 			| DWC_CTLL_DST_WIDTH(dst_width)
 			| DWC_CTLL_SRC_WIDTH(src_width)
 			| DWC_CTLL_DST_INC
@@ -669,11 +681,11 @@
 
 	switch (direction) {
 	case DMA_TO_DEVICE:
-		ctllo = (DWC_DEFAULT_CTLLO
+		ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 				| DWC_CTLL_DST_WIDTH(reg_width)
 				| DWC_CTLL_DST_FIX
 				| DWC_CTLL_SRC_INC
-				| DWC_CTLL_FC_M2P);
+				| DWC_CTLL_FC(dws->fc));
 		reg = dws->tx_reg;
 		for_each_sg(sgl, sg, sg_len, i) {
 			struct dw_desc	*desc;
@@ -714,11 +726,11 @@
 		}
 		break;
 	case DMA_FROM_DEVICE:
-		ctllo = (DWC_DEFAULT_CTLLO
+		ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 				| DWC_CTLL_SRC_WIDTH(reg_width)
 				| DWC_CTLL_DST_INC
 				| DWC_CTLL_SRC_FIX
-				| DWC_CTLL_FC_P2M);
+				| DWC_CTLL_FC(dws->fc));
 
 		reg = dws->rx_reg;
 		for_each_sg(sgl, sg, sg_len, i) {
@@ -834,7 +846,9 @@
 
 	ret = dma_async_is_complete(cookie, last_complete, last_used);
 	if (ret != DMA_SUCCESS) {
+		spin_lock_bh(&dwc->lock);
 		dwc_scan_descriptors(to_dw_dma(chan->device), dwc);
+		spin_unlock_bh(&dwc->lock);
 
 		last_complete = dwc->completed;
 		last_used = chan->cookie;
@@ -889,8 +903,11 @@
 		BUG_ON(!dws->dma_dev || dws->dma_dev != dw->dma.dev);
 
 		cfghi = dws->cfg_hi;
-		cfglo = dws->cfg_lo;
+		cfglo = dws->cfg_lo & ~DWC_CFGL_CH_PRIOR_MASK;
 	}
+
+	cfglo |= DWC_CFGL_CH_PRIOR(dwc->priority);
+
 	channel_writel(dwc, CFG_LO, cfglo);
 	channel_writel(dwc, CFG_HI, cfghi);
 
@@ -1126,23 +1143,23 @@
 		case DMA_TO_DEVICE:
 			desc->lli.dar = dws->tx_reg;
 			desc->lli.sar = buf_addr + (period_len * i);
-			desc->lli.ctllo = (DWC_DEFAULT_CTLLO
+			desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 					| DWC_CTLL_DST_WIDTH(reg_width)
 					| DWC_CTLL_SRC_WIDTH(reg_width)
 					| DWC_CTLL_DST_FIX
 					| DWC_CTLL_SRC_INC
-					| DWC_CTLL_FC_M2P
+					| DWC_CTLL_FC(dws->fc)
 					| DWC_CTLL_INT_EN);
 			break;
 		case DMA_FROM_DEVICE:
 			desc->lli.dar = buf_addr + (period_len * i);
 			desc->lli.sar = dws->rx_reg;
-			desc->lli.ctllo = (DWC_DEFAULT_CTLLO
+			desc->lli.ctllo = (DWC_DEFAULT_CTLLO(chan->private)
 					| DWC_CTLL_SRC_WIDTH(reg_width)
 					| DWC_CTLL_DST_WIDTH(reg_width)
 					| DWC_CTLL_DST_INC
 					| DWC_CTLL_SRC_FIX
-					| DWC_CTLL_FC_P2M
+					| DWC_CTLL_FC(dws->fc)
 					| DWC_CTLL_INT_EN);
 			break;
 		default:
@@ -1307,7 +1324,17 @@
 		dwc->chan.device = &dw->dma;
 		dwc->chan.cookie = dwc->completed = 1;
 		dwc->chan.chan_id = i;
-		list_add_tail(&dwc->chan.device_node, &dw->dma.channels);
+		if (pdata->chan_allocation_order == CHAN_ALLOCATION_ASCENDING)
+			list_add_tail(&dwc->chan.device_node,
+					&dw->dma.channels);
+		else
+			list_add(&dwc->chan.device_node, &dw->dma.channels);
+
+		/* 7 is highest priority & 0 is lowest. */
+		if (pdata->chan_priority == CHAN_PRIORITY_ASCENDING)
+			dwc->priority = 7 - i;
+		else
+			dwc->priority = i;
 
 		dwc->ch_regs = &__dw_regs(dw)->CHAN[i];
 		spin_lock_init(&dwc->lock);
@@ -1335,6 +1362,8 @@
 
 	dma_cap_set(DMA_MEMCPY, dw->dma.cap_mask);
 	dma_cap_set(DMA_SLAVE, dw->dma.cap_mask);
+	if (pdata->is_private)
+		dma_cap_set(DMA_PRIVATE, dw->dma.cap_mask);
 	dw->dma.dev = &pdev->dev;
 	dw->dma.device_alloc_chan_resources = dwc_alloc_chan_resources;
 	dw->dma.device_free_chan_resources = dwc_free_chan_resources;
@@ -1447,7 +1476,7 @@
 {
 	return platform_driver_probe(&dw_driver, dw_probe);
 }
-module_init(dw_init);
+subsys_initcall(dw_init);
 
 static void __exit dw_exit(void)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/dma/dw_dmac_regs.h linux-libre-2.6.39-gnu/drivers/dma/dw_dmac_regs.h
--- linux-libre-2.6.38-gnu/drivers/dma/dw_dmac_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/dw_dmac_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -86,6 +86,7 @@
 #define DWC_CTLL_SRC_MSIZE(n)	((n)<<14)
 #define DWC_CTLL_S_GATH_EN	(1 << 17)	/* src gather, !FIX */
 #define DWC_CTLL_D_SCAT_EN	(1 << 18)	/* dst scatter, !FIX */
+#define DWC_CTLL_FC(n)		((n) << 20)
 #define DWC_CTLL_FC_M2M		(0 << 20)	/* mem-to-mem */
 #define DWC_CTLL_FC_M2P		(1 << 20)	/* mem-to-periph */
 #define DWC_CTLL_FC_P2M		(2 << 20)	/* periph-to-mem */
@@ -101,6 +102,8 @@
 #define DWC_CTLH_BLOCK_TS_MASK	0x00000fff
 
 /* Bitfields in CFG_LO. Platform-configurable bits are in <linux/dw_dmac.h> */
+#define DWC_CFGL_CH_PRIOR_MASK	(0x7 << 5)	/* priority mask */
+#define DWC_CFGL_CH_PRIOR(x)	((x) << 5)	/* priority */
 #define DWC_CFGL_CH_SUSP	(1 << 8)	/* pause xfer */
 #define DWC_CFGL_FIFO_EMPTY	(1 << 9)	/* pause xfer */
 #define DWC_CFGL_HS_DST		(1 << 10)	/* handshake w/dst */
@@ -134,6 +137,7 @@
 	struct dma_chan		chan;
 	void __iomem		*ch_regs;
 	u8			mask;
+	u8			priority;
 
 	spinlock_t		lock;
 
@@ -155,9 +159,9 @@
 }
 
 #define channel_readl(dwc, name) \
-	__raw_readl(&(__dwc_regs(dwc)->name))
+	readl(&(__dwc_regs(dwc)->name))
 #define channel_writel(dwc, name, val) \
-	__raw_writel((val), &(__dwc_regs(dwc)->name))
+	writel((val), &(__dwc_regs(dwc)->name))
 
 static inline struct dw_dma_chan *to_dw_dma_chan(struct dma_chan *chan)
 {
@@ -181,9 +185,9 @@
 }
 
 #define dma_readl(dw, name) \
-	__raw_readl(&(__dw_regs(dw)->name))
+	readl(&(__dw_regs(dw)->name))
 #define dma_writel(dw, name, val) \
-	__raw_writel((val), &(__dw_regs(dw)->name))
+	writel((val), &(__dw_regs(dw)->name))
 
 #define channel_set_bit(dw, reg, mask) \
 	dma_writel(dw, reg, ((mask) << 8) | (mask))
diff -druN linux-libre-2.6.38-gnu/drivers/dma/fsldma.c linux-libre-2.6.39-gnu/drivers/dma/fsldma.c
--- linux-libre-2.6.38-gnu/drivers/dma/fsldma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/fsldma.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,35 +37,16 @@
 
 #include "fsldma.h"
 
-static const char msg_ld_oom[] = "No free memory for link descriptor\n";
+#define chan_dbg(chan, fmt, arg...)					\
+	dev_dbg(chan->dev, "%s: " fmt, chan->name, ##arg)
+#define chan_err(chan, fmt, arg...)					\
+	dev_err(chan->dev, "%s: " fmt, chan->name, ##arg)
 
-static void dma_init(struct fsldma_chan *chan)
-{
-	/* Reset the channel */
-	DMA_OUT(chan, &chan->regs->mr, 0, 32);
+static const char msg_ld_oom[] = "No free memory for link descriptor";
 
-	switch (chan->feature & FSL_DMA_IP_MASK) {
-	case FSL_DMA_IP_85XX:
-		/* Set the channel to below modes:
-		 * EIE - Error interrupt enable
-		 * EOSIE - End of segments interrupt enable (basic mode)
-		 * EOLNIE - End of links interrupt enable
-		 * BWC - Bandwidth sharing among channels
-		 */
-		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
-				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE
-				| FSL_DMA_MR_EOSIE, 32);
-		break;
-	case FSL_DMA_IP_83XX:
-		/* Set the channel to below modes:
-		 * EOTIE - End-of-transfer interrupt enable
-		 * PRC_RM - PCI read multiple
-		 */
-		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
-				| FSL_DMA_MR_PRC_RM, 32);
-		break;
-	}
-}
+/*
+ * Register Helpers
+ */
 
 static void set_sr(struct fsldma_chan *chan, u32 val)
 {
@@ -77,14 +58,38 @@
 	return DMA_IN(chan, &chan->regs->sr, 32);
 }
 
+static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
+{
+	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
+}
+
+static dma_addr_t get_cdar(struct fsldma_chan *chan)
+{
+	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
+}
+
+static u32 get_bcr(struct fsldma_chan *chan)
+{
+	return DMA_IN(chan, &chan->regs->bcr, 32);
+}
+
+/*
+ * Descriptor Helpers
+ */
+
 static void set_desc_cnt(struct fsldma_chan *chan,
 				struct fsl_dma_ld_hw *hw, u32 count)
 {
 	hw->count = CPU_TO_DMA(chan, count, 32);
 }
 
+static u32 get_desc_cnt(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
+{
+	return DMA_TO_CPU(chan, desc->hw.count, 32);
+}
+
 static void set_desc_src(struct fsldma_chan *chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t src)
+			 struct fsl_dma_ld_hw *hw, dma_addr_t src)
 {
 	u64 snoop_bits;
 
@@ -93,8 +98,18 @@
 	hw->src_addr = CPU_TO_DMA(chan, snoop_bits | src, 64);
 }
 
+static dma_addr_t get_desc_src(struct fsldma_chan *chan,
+			       struct fsl_desc_sw *desc)
+{
+	u64 snoop_bits;
+
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+		? ((u64)FSL_DMA_SATR_SREADTYPE_SNOOP_READ << 32) : 0;
+	return DMA_TO_CPU(chan, desc->hw.src_addr, 64) & ~snoop_bits;
+}
+
 static void set_desc_dst(struct fsldma_chan *chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t dst)
+			 struct fsl_dma_ld_hw *hw, dma_addr_t dst)
 {
 	u64 snoop_bits;
 
@@ -103,8 +118,18 @@
 	hw->dst_addr = CPU_TO_DMA(chan, snoop_bits | dst, 64);
 }
 
+static dma_addr_t get_desc_dst(struct fsldma_chan *chan,
+			       struct fsl_desc_sw *desc)
+{
+	u64 snoop_bits;
+
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX)
+		? ((u64)FSL_DMA_DATR_DWRITETYPE_SNOOP_WRITE << 32) : 0;
+	return DMA_TO_CPU(chan, desc->hw.dst_addr, 64) & ~snoop_bits;
+}
+
 static void set_desc_next(struct fsldma_chan *chan,
-				struct fsl_dma_ld_hw *hw, dma_addr_t next)
+			  struct fsl_dma_ld_hw *hw, dma_addr_t next)
 {
 	u64 snoop_bits;
 
@@ -113,24 +138,46 @@
 	hw->next_ln_addr = CPU_TO_DMA(chan, snoop_bits | next, 64);
 }
 
-static void set_cdar(struct fsldma_chan *chan, dma_addr_t addr)
+static void set_ld_eol(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
 {
-	DMA_OUT(chan, &chan->regs->cdar, addr | FSL_DMA_SNEN, 64);
-}
+	u64 snoop_bits;
 
-static dma_addr_t get_cdar(struct fsldma_chan *chan)
-{
-	return DMA_IN(chan, &chan->regs->cdar, 64) & ~FSL_DMA_SNEN;
-}
+	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
+		? FSL_DMA_SNEN : 0;
 
-static dma_addr_t get_ndar(struct fsldma_chan *chan)
-{
-	return DMA_IN(chan, &chan->regs->ndar, 64);
+	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
+		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
+			| snoop_bits, 64);
 }
 
-static u32 get_bcr(struct fsldma_chan *chan)
+/*
+ * DMA Engine Hardware Control Helpers
+ */
+
+static void dma_init(struct fsldma_chan *chan)
 {
-	return DMA_IN(chan, &chan->regs->bcr, 32);
+	/* Reset the channel */
+	DMA_OUT(chan, &chan->regs->mr, 0, 32);
+
+	switch (chan->feature & FSL_DMA_IP_MASK) {
+	case FSL_DMA_IP_85XX:
+		/* Set the channel to below modes:
+		 * EIE - Error interrupt enable
+		 * EOLNIE - End of links interrupt enable
+		 * BWC - Bandwidth sharing among channels
+		 */
+		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_BWC
+				| FSL_DMA_MR_EIE | FSL_DMA_MR_EOLNIE, 32);
+		break;
+	case FSL_DMA_IP_83XX:
+		/* Set the channel to below modes:
+		 * EOTIE - End-of-transfer interrupt enable
+		 * PRC_RM - PCI read multiple
+		 */
+		DMA_OUT(chan, &chan->regs->mr, FSL_DMA_MR_EOTIE
+				| FSL_DMA_MR_PRC_RM, 32);
+		break;
+	}
 }
 
 static int dma_is_idle(struct fsldma_chan *chan)
@@ -139,25 +186,32 @@
 	return (!(sr & FSL_DMA_SR_CB)) || (sr & FSL_DMA_SR_CH);
 }
 
+/*
+ * Start the DMA controller
+ *
+ * Preconditions:
+ * - the CDAR register must point to the start descriptor
+ * - the MRn[CS] bit must be cleared
+ */
 static void dma_start(struct fsldma_chan *chan)
 {
 	u32 mode;
 
 	mode = DMA_IN(chan, &chan->regs->mr, 32);
 
-	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
-		if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
-			DMA_OUT(chan, &chan->regs->bcr, 0, 32);
-			mode |= FSL_DMA_MR_EMP_EN;
-		} else {
-			mode &= ~FSL_DMA_MR_EMP_EN;
-		}
+	if (chan->feature & FSL_DMA_CHAN_PAUSE_EXT) {
+		DMA_OUT(chan, &chan->regs->bcr, 0, 32);
+		mode |= FSL_DMA_MR_EMP_EN;
+	} else {
+		mode &= ~FSL_DMA_MR_EMP_EN;
 	}
 
-	if (chan->feature & FSL_DMA_CHAN_START_EXT)
+	if (chan->feature & FSL_DMA_CHAN_START_EXT) {
 		mode |= FSL_DMA_MR_EMS_EN;
-	else
+	} else {
+		mode &= ~FSL_DMA_MR_EMS_EN;
 		mode |= FSL_DMA_MR_CS;
+	}
 
 	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 }
@@ -167,13 +221,26 @@
 	u32 mode;
 	int i;
 
+	/* read the mode register */
 	mode = DMA_IN(chan, &chan->regs->mr, 32);
-	mode |= FSL_DMA_MR_CA;
-	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 
-	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN | FSL_DMA_MR_CA);
+	/*
+	 * The 85xx controller supports channel abort, which will stop
+	 * the current transfer. On 83xx, this bit is the transfer error
+	 * mask bit, which should not be changed.
+	 */
+	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		mode |= FSL_DMA_MR_CA;
+		DMA_OUT(chan, &chan->regs->mr, mode, 32);
+
+		mode &= ~FSL_DMA_MR_CA;
+	}
+
+	/* stop the DMA controller */
+	mode &= ~(FSL_DMA_MR_CS | FSL_DMA_MR_EMS_EN);
 	DMA_OUT(chan, &chan->regs->mr, mode, 32);
 
+	/* wait for the DMA controller to become idle */
 	for (i = 0; i < 100; i++) {
 		if (dma_is_idle(chan))
 			return;
@@ -182,20 +249,7 @@
 	}
 
 	if (!dma_is_idle(chan))
-		dev_err(chan->dev, "DMA halt timeout!\n");
-}
-
-static void set_ld_eol(struct fsldma_chan *chan,
-			struct fsl_desc_sw *desc)
-{
-	u64 snoop_bits;
-
-	snoop_bits = ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_83XX)
-		? FSL_DMA_SNEN : 0;
-
-	desc->hw.next_ln_addr = CPU_TO_DMA(chan,
-		DMA_TO_CPU(chan, desc->hw.next_ln_addr, 64) | FSL_DMA_EOL
-			| snoop_bits, 64);
+		chan_err(chan, "DMA halt timeout!\n");
 }
 
 /**
@@ -321,8 +375,7 @@
 		chan->feature &= ~FSL_DMA_CHAN_START_EXT;
 }
 
-static void append_ld_queue(struct fsldma_chan *chan,
-			    struct fsl_desc_sw *desc)
+static void append_ld_queue(struct fsldma_chan *chan, struct fsl_desc_sw *desc)
 {
 	struct fsl_desc_sw *tail = to_fsl_desc(chan->ld_pending.prev);
 
@@ -363,8 +416,8 @@
 	cookie = chan->common.cookie;
 	list_for_each_entry(child, &desc->tx_list, node) {
 		cookie++;
-		if (cookie < 0)
-			cookie = 1;
+		if (cookie < DMA_MIN_COOKIE)
+			cookie = DMA_MIN_COOKIE;
 
 		child->async_tx.cookie = cookie;
 	}
@@ -385,15 +438,14 @@
  *
  * Return - The descriptor allocated. NULL for failed.
  */
-static struct fsl_desc_sw *fsl_dma_alloc_descriptor(
-					struct fsldma_chan *chan)
+static struct fsl_desc_sw *fsl_dma_alloc_descriptor(struct fsldma_chan *chan)
 {
 	struct fsl_desc_sw *desc;
 	dma_addr_t pdesc;
 
 	desc = dma_pool_alloc(chan->desc_pool, GFP_ATOMIC, &pdesc);
 	if (!desc) {
-		dev_dbg(chan->dev, "out of memory for link desc\n");
+		chan_dbg(chan, "out of memory for link descriptor\n");
 		return NULL;
 	}
 
@@ -403,10 +455,13 @@
 	desc->async_tx.tx_submit = fsl_dma_tx_submit;
 	desc->async_tx.phys = pdesc;
 
+#ifdef FSL_DMA_LD_DEBUG
+	chan_dbg(chan, "LD %p allocated\n", desc);
+#endif
+
 	return desc;
 }
 
-
 /**
  * fsl_dma_alloc_chan_resources - Allocate resources for DMA channel.
  * @chan : Freescale DMA channel
@@ -427,13 +482,11 @@
 	 * We need the descriptor to be aligned to 32bytes
 	 * for meeting FSL DMA specification requirement.
 	 */
-	chan->desc_pool = dma_pool_create("fsl_dma_engine_desc_pool",
-					  chan->dev,
+	chan->desc_pool = dma_pool_create(chan->name, chan->dev,
 					  sizeof(struct fsl_desc_sw),
 					  __alignof__(struct fsl_desc_sw), 0);
 	if (!chan->desc_pool) {
-		dev_err(chan->dev, "unable to allocate channel %d "
-				   "descriptor pool\n", chan->id);
+		chan_err(chan, "unable to allocate descriptor pool\n");
 		return -ENOMEM;
 	}
 
@@ -455,6 +508,9 @@
 
 	list_for_each_entry_safe(desc, _desc, list, node) {
 		list_del(&desc->node);
+#ifdef FSL_DMA_LD_DEBUG
+		chan_dbg(chan, "LD %p free\n", desc);
+#endif
 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
 	}
 }
@@ -466,6 +522,9 @@
 
 	list_for_each_entry_safe_reverse(desc, _desc, list, node) {
 		list_del(&desc->node);
+#ifdef FSL_DMA_LD_DEBUG
+		chan_dbg(chan, "LD %p free\n", desc);
+#endif
 		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
 	}
 }
@@ -479,7 +538,7 @@
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
 	unsigned long flags;
 
-	dev_dbg(chan->dev, "Free all channel resources.\n");
+	chan_dbg(chan, "free all channel resources\n");
 	spin_lock_irqsave(&chan->desc_lock, flags);
 	fsldma_free_desc_list(chan, &chan->ld_pending);
 	fsldma_free_desc_list(chan, &chan->ld_running);
@@ -502,7 +561,7 @@
 
 	new = fsl_dma_alloc_descriptor(chan);
 	if (!new) {
-		dev_err(chan->dev, msg_ld_oom);
+		chan_err(chan, "%s\n", msg_ld_oom);
 		return NULL;
 	}
 
@@ -512,14 +571,15 @@
 	/* Insert the link descriptor to the LD ring */
 	list_add_tail(&new->node, &new->tx_list);
 
-	/* Set End-of-link to the last link descriptor of new list*/
+	/* Set End-of-link to the last link descriptor of new list */
 	set_ld_eol(chan, new);
 
 	return &new->async_tx;
 }
 
-static struct dma_async_tx_descriptor *fsl_dma_prep_memcpy(
-	struct dma_chan *dchan, dma_addr_t dma_dst, dma_addr_t dma_src,
+static struct dma_async_tx_descriptor *
+fsl_dma_prep_memcpy(struct dma_chan *dchan,
+	dma_addr_t dma_dst, dma_addr_t dma_src,
 	size_t len, unsigned long flags)
 {
 	struct fsldma_chan *chan;
@@ -539,12 +599,9 @@
 		/* Allocate the link descriptor from DMA pool */
 		new = fsl_dma_alloc_descriptor(chan);
 		if (!new) {
-			dev_err(chan->dev, msg_ld_oom);
+			chan_err(chan, "%s\n", msg_ld_oom);
 			goto fail;
 		}
-#ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
-#endif
 
 		copy = min(len, (size_t)FSL_DMA_BCR_MAX_CNT);
 
@@ -572,7 +629,7 @@
 	new->async_tx.flags = flags; /* client is in control of this ack */
 	new->async_tx.cookie = -EBUSY;
 
-	/* Set End-of-link to the last link descriptor of new list*/
+	/* Set End-of-link to the last link descriptor of new list */
 	set_ld_eol(chan, new);
 
 	return &first->async_tx;
@@ -627,12 +684,9 @@
 		/* allocate and populate the descriptor */
 		new = fsl_dma_alloc_descriptor(chan);
 		if (!new) {
-			dev_err(chan->dev, msg_ld_oom);
+			chan_err(chan, "%s\n", msg_ld_oom);
 			goto fail;
 		}
-#ifdef FSL_DMA_LD_DEBUG
-		dev_dbg(chan->dev, "new link desc alloc %p\n", new);
-#endif
 
 		set_desc_cnt(chan, &new->hw, len);
 		set_desc_src(chan, &new->hw, src);
@@ -744,14 +798,15 @@
 
 	switch (cmd) {
 	case DMA_TERMINATE_ALL:
+		spin_lock_irqsave(&chan->desc_lock, flags);
+
 		/* Halt the DMA engine */
 		dma_halt(chan);
 
-		spin_lock_irqsave(&chan->desc_lock, flags);
-
 		/* Remove and free all of the descriptors in the LD queue */
 		fsldma_free_desc_list(chan, &chan->ld_pending);
 		fsldma_free_desc_list(chan, &chan->ld_running);
+		chan->idle = true;
 
 		spin_unlock_irqrestore(&chan->desc_lock, flags);
 		return 0;
@@ -789,140 +844,87 @@
 }
 
 /**
- * fsl_dma_update_completed_cookie - Update the completed cookie.
- * @chan : Freescale DMA channel
- *
- * CONTEXT: hardirq
- */
-static void fsl_dma_update_completed_cookie(struct fsldma_chan *chan)
-{
-	struct fsl_desc_sw *desc;
-	unsigned long flags;
-	dma_cookie_t cookie;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
-
-	if (list_empty(&chan->ld_running)) {
-		dev_dbg(chan->dev, "no running descriptors\n");
-		goto out_unlock;
-	}
-
-	/* Get the last descriptor, update the cookie to that */
-	desc = to_fsl_desc(chan->ld_running.prev);
-	if (dma_is_idle(chan))
-		cookie = desc->async_tx.cookie;
-	else {
-		cookie = desc->async_tx.cookie - 1;
-		if (unlikely(cookie < DMA_MIN_COOKIE))
-			cookie = DMA_MAX_COOKIE;
-	}
-
-	chan->completed_cookie = cookie;
-
-out_unlock:
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
-}
-
-/**
- * fsldma_desc_status - Check the status of a descriptor
+ * fsldma_cleanup_descriptor - cleanup and free a single link descriptor
  * @chan: Freescale DMA channel
- * @desc: DMA SW descriptor
- *
- * This function will return the status of the given descriptor
- */
-static enum dma_status fsldma_desc_status(struct fsldma_chan *chan,
-					  struct fsl_desc_sw *desc)
-{
-	return dma_async_is_complete(desc->async_tx.cookie,
-				     chan->completed_cookie,
-				     chan->common.cookie);
-}
-
-/**
- * fsl_chan_ld_cleanup - Clean up link descriptors
- * @chan : Freescale DMA channel
+ * @desc: descriptor to cleanup and free
  *
- * This function clean up the ld_queue of DMA channel.
+ * This function is used on a descriptor which has been executed by the DMA
+ * controller. It will run any callbacks, submit any dependencies, and then
+ * free the descriptor.
  */
-static void fsl_chan_ld_cleanup(struct fsldma_chan *chan)
+static void fsldma_cleanup_descriptor(struct fsldma_chan *chan,
+				      struct fsl_desc_sw *desc)
 {
-	struct fsl_desc_sw *desc, *_desc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
-
-	dev_dbg(chan->dev, "chan completed_cookie = %d\n", chan->completed_cookie);
-	list_for_each_entry_safe(desc, _desc, &chan->ld_running, node) {
-		dma_async_tx_callback callback;
-		void *callback_param;
+	struct dma_async_tx_descriptor *txd = &desc->async_tx;
+	struct device *dev = chan->common.device->dev;
+	dma_addr_t src = get_desc_src(chan, desc);
+	dma_addr_t dst = get_desc_dst(chan, desc);
+	u32 len = get_desc_cnt(chan, desc);
 
-		if (fsldma_desc_status(chan, desc) == DMA_IN_PROGRESS)
-			break;
+	/* Run the link descriptor callback function */
+	if (txd->callback) {
+#ifdef FSL_DMA_LD_DEBUG
+		chan_dbg(chan, "LD %p callback\n", desc);
+#endif
+		txd->callback(txd->callback_param);
+	}
 
-		/* Remove from the list of running transactions */
-		list_del(&desc->node);
+	/* Run any dependencies */
+	dma_run_dependencies(txd);
 
-		/* Run the link descriptor callback function */
-		callback = desc->async_tx.callback;
-		callback_param = desc->async_tx.callback_param;
-		if (callback) {
-			spin_unlock_irqrestore(&chan->desc_lock, flags);
-			dev_dbg(chan->dev, "LD %p callback\n", desc);
-			callback(callback_param);
-			spin_lock_irqsave(&chan->desc_lock, flags);
-		}
+	/* Unmap the dst buffer, if requested */
+	if (!(txd->flags & DMA_COMPL_SKIP_DEST_UNMAP)) {
+		if (txd->flags & DMA_COMPL_DEST_UNMAP_SINGLE)
+			dma_unmap_single(dev, dst, len, DMA_FROM_DEVICE);
+		else
+			dma_unmap_page(dev, dst, len, DMA_FROM_DEVICE);
+	}
 
-		/* Run any dependencies, then free the descriptor */
-		dma_run_dependencies(&desc->async_tx);
-		dma_pool_free(chan->desc_pool, desc, desc->async_tx.phys);
+	/* Unmap the src buffer, if requested */
+	if (!(txd->flags & DMA_COMPL_SKIP_SRC_UNMAP)) {
+		if (txd->flags & DMA_COMPL_SRC_UNMAP_SINGLE)
+			dma_unmap_single(dev, src, len, DMA_TO_DEVICE);
+		else
+			dma_unmap_page(dev, src, len, DMA_TO_DEVICE);
 	}
 
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+#ifdef FSL_DMA_LD_DEBUG
+	chan_dbg(chan, "LD %p free\n", desc);
+#endif
+	dma_pool_free(chan->desc_pool, desc, txd->phys);
 }
 
 /**
  * fsl_chan_xfer_ld_queue - transfer any pending transactions
  * @chan : Freescale DMA channel
  *
- * This will make sure that any pending transactions will be run.
- * If the DMA controller is idle, it will be started. Otherwise,
- * the DMA controller's interrupt handler will start any pending
- * transactions when it becomes idle.
+ * HARDWARE STATE: idle
+ * LOCKING: must hold chan->desc_lock
  */
 static void fsl_chan_xfer_ld_queue(struct fsldma_chan *chan)
 {
 	struct fsl_desc_sw *desc;
-	unsigned long flags;
-
-	spin_lock_irqsave(&chan->desc_lock, flags);
 
 	/*
 	 * If the list of pending descriptors is empty, then we
 	 * don't need to do any work at all
 	 */
 	if (list_empty(&chan->ld_pending)) {
-		dev_dbg(chan->dev, "no pending LDs\n");
-		goto out_unlock;
+		chan_dbg(chan, "no pending LDs\n");
+		return;
 	}
 
 	/*
-	 * The DMA controller is not idle, which means the interrupt
-	 * handler will start any queued transactions when it runs
-	 * at the end of the current transaction
+	 * The DMA controller is not idle, which means that the interrupt
+	 * handler will start any queued transactions when it runs after
+	 * this transaction finishes
 	 */
-	if (!dma_is_idle(chan)) {
-		dev_dbg(chan->dev, "DMA controller still busy\n");
-		goto out_unlock;
+	if (!chan->idle) {
+		chan_dbg(chan, "DMA controller still busy\n");
+		return;
 	}
 
 	/*
-	 * TODO:
-	 * make sure the dma_halt() function really un-wedges the
-	 * controller as much as possible
-	 */
-	dma_halt(chan);
-
-	/*
 	 * If there are some link descriptors which have not been
 	 * transferred, we need to start the controller
 	 */
@@ -931,18 +933,32 @@
 	 * Move all elements from the queue of pending transactions
 	 * onto the list of running transactions
 	 */
+	chan_dbg(chan, "idle, starting controller\n");
 	desc = list_first_entry(&chan->ld_pending, struct fsl_desc_sw, node);
 	list_splice_tail_init(&chan->ld_pending, &chan->ld_running);
 
 	/*
+	 * The 85xx DMA controller doesn't clear the channel start bit
+	 * automatically at the end of a transfer. Therefore we must clear
+	 * it in software before starting the transfer.
+	 */
+	if ((chan->feature & FSL_DMA_IP_MASK) == FSL_DMA_IP_85XX) {
+		u32 mode;
+
+		mode = DMA_IN(chan, &chan->regs->mr, 32);
+		mode &= ~FSL_DMA_MR_CS;
+		DMA_OUT(chan, &chan->regs->mr, mode, 32);
+	}
+
+	/*
 	 * Program the descriptor's address into the DMA controller,
 	 * then start the DMA transaction
 	 */
 	set_cdar(chan, desc->async_tx.phys);
-	dma_start(chan);
+	get_cdar(chan);
 
-out_unlock:
-	spin_unlock_irqrestore(&chan->desc_lock, flags);
+	dma_start(chan);
+	chan->idle = false;
 }
 
 /**
@@ -952,7 +968,11 @@
 static void fsl_dma_memcpy_issue_pending(struct dma_chan *dchan)
 {
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
 	fsl_chan_xfer_ld_queue(chan);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 }
 
 /**
@@ -964,16 +984,18 @@
 					struct dma_tx_state *txstate)
 {
 	struct fsldma_chan *chan = to_fsl_chan(dchan);
-	dma_cookie_t last_used;
 	dma_cookie_t last_complete;
+	dma_cookie_t last_used;
+	unsigned long flags;
 
-	fsl_chan_ld_cleanup(chan);
+	spin_lock_irqsave(&chan->desc_lock, flags);
 
-	last_used = dchan->cookie;
 	last_complete = chan->completed_cookie;
+	last_used = dchan->cookie;
 
-	dma_set_tx_state(txstate, last_complete, last_used, 0);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
 
+	dma_set_tx_state(txstate, last_complete, last_used, 0);
 	return dma_async_is_complete(cookie, last_complete, last_used);
 }
 
@@ -984,21 +1006,20 @@
 static irqreturn_t fsldma_chan_irq(int irq, void *data)
 {
 	struct fsldma_chan *chan = data;
-	int update_cookie = 0;
-	int xfer_ld_q = 0;
 	u32 stat;
 
 	/* save and clear the status register */
 	stat = get_sr(chan);
 	set_sr(chan, stat);
-	dev_dbg(chan->dev, "irq: channel %d, stat = 0x%x\n", chan->id, stat);
+	chan_dbg(chan, "irq: stat = 0x%x\n", stat);
 
+	/* check that this was really our device */
 	stat &= ~(FSL_DMA_SR_CB | FSL_DMA_SR_CH);
 	if (!stat)
 		return IRQ_NONE;
 
 	if (stat & FSL_DMA_SR_TE)
-		dev_err(chan->dev, "Transfer Error!\n");
+		chan_err(chan, "Transfer Error!\n");
 
 	/*
 	 * Programming Error
@@ -1006,29 +1027,10 @@
 	 * triger a PE interrupt.
 	 */
 	if (stat & FSL_DMA_SR_PE) {
-		dev_dbg(chan->dev, "irq: Programming Error INT\n");
-		if (get_bcr(chan) == 0) {
-			/* BCR register is 0, this is a DMA_INTERRUPT async_tx.
-			 * Now, update the completed cookie, and continue the
-			 * next uncompleted transfer.
-			 */
-			update_cookie = 1;
-			xfer_ld_q = 1;
-		}
+		chan_dbg(chan, "irq: Programming Error INT\n");
 		stat &= ~FSL_DMA_SR_PE;
-	}
-
-	/*
-	 * If the link descriptor segment transfer finishes,
-	 * we will recycle the used descriptor.
-	 */
-	if (stat & FSL_DMA_SR_EOSI) {
-		dev_dbg(chan->dev, "irq: End-of-segments INT\n");
-		dev_dbg(chan->dev, "irq: clndar 0x%llx, nlndar 0x%llx\n",
-			(unsigned long long)get_cdar(chan),
-			(unsigned long long)get_ndar(chan));
-		stat &= ~FSL_DMA_SR_EOSI;
-		update_cookie = 1;
+		if (get_bcr(chan) != 0)
+			chan_err(chan, "Programming Error!\n");
 	}
 
 	/*
@@ -1036,10 +1038,8 @@
 	 * and start the next transfer if it exist.
 	 */
 	if (stat & FSL_DMA_SR_EOCDI) {
-		dev_dbg(chan->dev, "irq: End-of-Chain link INT\n");
+		chan_dbg(chan, "irq: End-of-Chain link INT\n");
 		stat &= ~FSL_DMA_SR_EOCDI;
-		update_cookie = 1;
-		xfer_ld_q = 1;
 	}
 
 	/*
@@ -1048,27 +1048,79 @@
 	 * prepare next transfer.
 	 */
 	if (stat & FSL_DMA_SR_EOLNI) {
-		dev_dbg(chan->dev, "irq: End-of-link INT\n");
+		chan_dbg(chan, "irq: End-of-link INT\n");
 		stat &= ~FSL_DMA_SR_EOLNI;
-		xfer_ld_q = 1;
 	}
 
-	if (update_cookie)
-		fsl_dma_update_completed_cookie(chan);
-	if (xfer_ld_q)
-		fsl_chan_xfer_ld_queue(chan);
+	/* check that the DMA controller is really idle */
+	if (!dma_is_idle(chan))
+		chan_err(chan, "irq: controller not idle!\n");
+
+	/* check that we handled all of the bits */
 	if (stat)
-		dev_dbg(chan->dev, "irq: unhandled sr 0x%02x\n", stat);
+		chan_err(chan, "irq: unhandled sr 0x%08x\n", stat);
 
-	dev_dbg(chan->dev, "irq: Exit\n");
+	/*
+	 * Schedule the tasklet to handle all cleanup of the current
+	 * transaction. It will start a new transaction if there is
+	 * one pending.
+	 */
 	tasklet_schedule(&chan->tasklet);
+	chan_dbg(chan, "irq: Exit\n");
 	return IRQ_HANDLED;
 }
 
 static void dma_do_tasklet(unsigned long data)
 {
 	struct fsldma_chan *chan = (struct fsldma_chan *)data;
-	fsl_chan_ld_cleanup(chan);
+	struct fsl_desc_sw *desc, *_desc;
+	LIST_HEAD(ld_cleanup);
+	unsigned long flags;
+
+	chan_dbg(chan, "tasklet entry\n");
+
+	spin_lock_irqsave(&chan->desc_lock, flags);
+
+	/* update the cookie if we have some descriptors to cleanup */
+	if (!list_empty(&chan->ld_running)) {
+		dma_cookie_t cookie;
+
+		desc = to_fsl_desc(chan->ld_running.prev);
+		cookie = desc->async_tx.cookie;
+
+		chan->completed_cookie = cookie;
+		chan_dbg(chan, "completed_cookie=%d\n", cookie);
+	}
+
+	/*
+	 * move the descriptors to a temporary list so we can drop the lock
+	 * during the entire cleanup operation
+	 */
+	list_splice_tail_init(&chan->ld_running, &ld_cleanup);
+
+	/* the hardware is now idle and ready for more */
+	chan->idle = true;
+
+	/*
+	 * Start any pending transactions automatically
+	 *
+	 * In the ideal case, we keep the DMA controller busy while we go
+	 * ahead and free the descriptors below.
+	 */
+	fsl_chan_xfer_ld_queue(chan);
+	spin_unlock_irqrestore(&chan->desc_lock, flags);
+
+	/* Run the callback for each descriptor, in order */
+	list_for_each_entry_safe(desc, _desc, &ld_cleanup, node) {
+
+		/* Remove from the list of transactions */
+		list_del(&desc->node);
+
+		/* Run all cleanup for this descriptor */
+		fsldma_cleanup_descriptor(chan, desc);
+	}
+
+	chan_dbg(chan, "tasklet exit\n");
 }
 
 static irqreturn_t fsldma_ctrl_irq(int irq, void *data)
@@ -1116,7 +1168,7 @@
 	for (i = 0; i < FSL_DMA_MAX_CHANS_PER_DEVICE; i++) {
 		chan = fdev->chan[i];
 		if (chan && chan->irq != NO_IRQ) {
-			dev_dbg(fdev->dev, "free channel %d IRQ\n", chan->id);
+			chan_dbg(chan, "free per-channel IRQ\n");
 			free_irq(chan->irq, chan);
 		}
 	}
@@ -1143,19 +1195,16 @@
 			continue;
 
 		if (chan->irq == NO_IRQ) {
-			dev_err(fdev->dev, "no interrupts property defined for "
-					   "DMA channel %d. Please fix your "
-					   "device tree\n", chan->id);
+			chan_err(chan, "interrupts property missing in device tree\n");
 			ret = -ENODEV;
 			goto out_unwind;
 		}
 
-		dev_dbg(fdev->dev, "request channel %d IRQ\n", chan->id);
+		chan_dbg(chan, "request per-channel IRQ\n");
 		ret = request_irq(chan->irq, fsldma_chan_irq, IRQF_SHARED,
 				  "fsldma-chan", chan);
 		if (ret) {
-			dev_err(fdev->dev, "unable to request IRQ for DMA "
-					   "channel %d\n", chan->id);
+			chan_err(chan, "unable to request per-channel IRQ\n");
 			goto out_unwind;
 		}
 	}
@@ -1230,6 +1279,7 @@
 
 	fdev->chan[chan->id] = chan;
 	tasklet_init(&chan->tasklet, dma_do_tasklet, (unsigned long)chan);
+	snprintf(chan->name, sizeof(chan->name), "chan%d", chan->id);
 
 	/* Initialize the channel */
 	dma_init(chan);
@@ -1250,6 +1300,7 @@
 	spin_lock_init(&chan->desc_lock);
 	INIT_LIST_HEAD(&chan->ld_pending);
 	INIT_LIST_HEAD(&chan->ld_running);
+	chan->idle = true;
 
 	chan->common.device = &fdev->common;
 
@@ -1281,8 +1332,7 @@
 	kfree(chan);
 }
 
-static int __devinit fsldma_of_probe(struct platform_device *op,
-			const struct of_device_id *match)
+static int __devinit fsldma_of_probe(struct platform_device *op)
 {
 	struct fsldma_device *fdev;
 	struct device_node *child;
@@ -1398,7 +1448,7 @@
 	{}
 };
 
-static struct of_platform_driver fsldma_of_driver = {
+static struct platform_driver fsldma_of_driver = {
 	.driver = {
 		.name = "fsl-elo-dma",
 		.owner = THIS_MODULE,
@@ -1414,20 +1464,13 @@
 
 static __init int fsldma_init(void)
 {
-	int ret;
-
 	pr_info("Freescale Elo / Elo Plus DMA driver\n");
-
-	ret = of_register_platform_driver(&fsldma_of_driver);
-	if (ret)
-		pr_err("fsldma: failed to register platform driver\n");
-
-	return ret;
+	return platform_driver_register(&fsldma_of_driver);
 }
 
 static void __exit fsldma_exit(void)
 {
-	of_unregister_platform_driver(&fsldma_of_driver);
+	platform_driver_unregister(&fsldma_of_driver);
 }
 
 subsys_initcall(fsldma_init);
diff -druN linux-libre-2.6.38-gnu/drivers/dma/fsldma.h linux-libre-2.6.39-gnu/drivers/dma/fsldma.h
--- linux-libre-2.6.38-gnu/drivers/dma/fsldma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/fsldma.h	2011-05-19 00:06:34.000000000 -0400
@@ -102,8 +102,8 @@
 } __attribute__((aligned(32)));
 
 struct fsldma_chan_regs {
-	u32 mr;	/* 0x00 - Mode Register */
-	u32 sr;	/* 0x04 - Status Register */
+	u32 mr;		/* 0x00 - Mode Register */
+	u32 sr;		/* 0x04 - Status Register */
 	u64 cdar;	/* 0x08 - Current descriptor address register */
 	u64 sar;	/* 0x10 - Source Address Register */
 	u64 dar;	/* 0x18 - Destination Address Register */
@@ -135,6 +135,7 @@
 #define FSL_DMA_CHAN_START_EXT	0x00002000
 
 struct fsldma_chan {
+	char name[8];			/* Channel name */
 	struct fsldma_chan_regs __iomem *regs;
 	dma_cookie_t completed_cookie;	/* The maximum cookie completed */
 	spinlock_t desc_lock;		/* Descriptor operation lock */
@@ -147,6 +148,7 @@
 	int id;				/* Raw id of this channel */
 	struct tasklet_struct tasklet;
 	u32 feature;
+	bool idle;			/* DMA controller is idle */
 
 	void (*toggle_ext_pause)(struct fsldma_chan *fsl_chan, int enable);
 	void (*toggle_ext_start)(struct fsldma_chan *fsl_chan, int enable);
diff -druN linux-libre-2.6.38-gnu/drivers/dma/intel_mid_dma.c linux-libre-2.6.39-gnu/drivers/dma/intel_mid_dma.c
--- linux-libre-2.6.38-gnu/drivers/dma/intel_mid_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/intel_mid_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -911,8 +911,8 @@
 
 /**
  * midc_handle_error -	Handle DMA txn error
- * @mid: controller where error occured
- * @midc: chan where error occured
+ * @mid: controller where error occurred
+ * @midc: chan where error occurred
  *
  * Scan the descriptor for error
  */
@@ -1099,7 +1099,7 @@
 		dma->mask_reg = ioremap(LNW_PERIPHRAL_MASK_BASE,
 					LNW_PERIPHRAL_MASK_SIZE);
 		if (dma->mask_reg == NULL) {
-			pr_err("ERR_MDMA:Cant map periphral intr space !!\n");
+			pr_err("ERR_MDMA:Can't map periphral intr space !!\n");
 			return -ENOMEM;
 		}
 	} else
@@ -1373,7 +1373,7 @@
 	pci_restore_state(pci);
 	ret = pci_enable_device(pci);
 	if (ret) {
-		pr_err("MDMA: device cant be enabled for %x\n", pci->device);
+		pr_err("MDMA: device can't be enabled for %x\n", pci->device);
 		return ret;
 	}
 	device->state = RUNNING;
diff -druN linux-libre-2.6.38-gnu/drivers/dma/intel_mid_dma_regs.h linux-libre-2.6.39-gnu/drivers/dma/intel_mid_dma_regs.h
--- linux-libre-2.6.38-gnu/drivers/dma/intel_mid_dma_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/intel_mid_dma_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -174,8 +174,8 @@
  * @dma: dma device struture pointer
  * @busy: bool representing if ch is busy (active txn) or not
  * @in_use: bool representing if ch is in use or not
- * @raw_tfr: raw trf interrupt recieved
- * @raw_block: raw block interrupt recieved
+ * @raw_tfr: raw trf interrupt received
+ * @raw_block: raw block interrupt received
  */
 struct intel_mid_dma_chan {
 	struct dma_chan		chan;
diff -druN linux-libre-2.6.38-gnu/drivers/dma/ipu/ipu_irq.c linux-libre-2.6.39-gnu/drivers/dma/ipu/ipu_irq.c
--- linux-libre-2.6.38-gnu/drivers/dma/ipu/ipu_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/ipu/ipu_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,9 +94,9 @@
 	return NULL;
 }
 
-static void ipu_irq_unmask(unsigned int irq)
+static void ipu_irq_unmask(struct irq_data *d)
 {
-	struct ipu_irq_map *map = get_irq_chip_data(irq);
+	struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
 	struct ipu_irq_bank *bank;
 	uint32_t reg;
 	unsigned long lock_flags;
@@ -106,7 +106,7 @@
 	bank = map->bank;
 	if (!bank) {
 		spin_unlock_irqrestore(&bank_lock, lock_flags);
-		pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
 
@@ -117,9 +117,9 @@
 	spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
-static void ipu_irq_mask(unsigned int irq)
+static void ipu_irq_mask(struct irq_data *d)
 {
-	struct ipu_irq_map *map = get_irq_chip_data(irq);
+	struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
 	struct ipu_irq_bank *bank;
 	uint32_t reg;
 	unsigned long lock_flags;
@@ -129,7 +129,7 @@
 	bank = map->bank;
 	if (!bank) {
 		spin_unlock_irqrestore(&bank_lock, lock_flags);
-		pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
 
@@ -140,9 +140,9 @@
 	spin_unlock_irqrestore(&bank_lock, lock_flags);
 }
 
-static void ipu_irq_ack(unsigned int irq)
+static void ipu_irq_ack(struct irq_data *d)
 {
-	struct ipu_irq_map *map = get_irq_chip_data(irq);
+	struct ipu_irq_map *map = irq_data_get_irq_chip_data(d);
 	struct ipu_irq_bank *bank;
 	unsigned long lock_flags;
 
@@ -151,7 +151,7 @@
 	bank = map->bank;
 	if (!bank) {
 		spin_unlock_irqrestore(&bank_lock, lock_flags);
-		pr_err("IPU: %s(%u) - unmapped!\n", __func__, irq);
+		pr_err("IPU: %s(%u) - unmapped!\n", __func__, d->irq);
 		return;
 	}
 
@@ -167,7 +167,7 @@
  */
 bool ipu_irq_status(unsigned int irq)
 {
-	struct ipu_irq_map *map = get_irq_chip_data(irq);
+	struct ipu_irq_map *map = irq_get_chip_data(irq);
 	struct ipu_irq_bank *bank;
 	unsigned long lock_flags;
 	bool ret;
@@ -269,7 +269,7 @@
 /* Chained IRQ handler for IPU error interrupt */
 static void ipu_irq_err(unsigned int irq, struct irq_desc *desc)
 {
-	struct ipu *ipu = get_irq_data(irq);
+	struct ipu *ipu = irq_get_handler_data(irq);
 	u32 status;
 	int i, line;
 
@@ -310,7 +310,7 @@
 /* Chained IRQ handler for IPU function interrupt */
 static void ipu_irq_fn(unsigned int irq, struct irq_desc *desc)
 {
-	struct ipu *ipu = get_irq_data(irq);
+	struct ipu *ipu = irq_desc_get_handler_data(desc);
 	u32 status;
 	int i, line;
 
@@ -345,10 +345,10 @@
 }
 
 static struct irq_chip ipu_irq_chip = {
-	.name	= "ipu_irq",
-	.ack	= ipu_irq_ack,
-	.mask	= ipu_irq_mask,
-	.unmask	= ipu_irq_unmask,
+	.name		= "ipu_irq",
+	.irq_ack	= ipu_irq_ack,
+	.irq_mask	= ipu_irq_mask,
+	.irq_unmask	= ipu_irq_unmask,
 };
 
 /* Install the IRQ handler */
@@ -366,26 +366,26 @@
 		int ret;
 
 		irq = irq_base + i;
-		ret = set_irq_chip(irq, &ipu_irq_chip);
+		ret = irq_set_chip(irq, &ipu_irq_chip);
 		if (ret < 0)
 			return ret;
-		ret = set_irq_chip_data(irq, irq_map + i);
+		ret = irq_set_chip_data(irq, irq_map + i);
 		if (ret < 0)
 			return ret;
 		irq_map[i].ipu = ipu;
 		irq_map[i].irq = irq;
 		irq_map[i].source = -EINVAL;
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_handler(irq, handle_level_irq);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 #endif
 	}
 
-	set_irq_data(ipu->irq_fn, ipu);
-	set_irq_chained_handler(ipu->irq_fn, ipu_irq_fn);
+	irq_set_handler_data(ipu->irq_fn, ipu);
+	irq_set_chained_handler(ipu->irq_fn, ipu_irq_fn);
 
-	set_irq_data(ipu->irq_err, ipu);
-	set_irq_chained_handler(ipu->irq_err, ipu_irq_err);
+	irq_set_handler_data(ipu->irq_err, ipu);
+	irq_set_chained_handler(ipu->irq_err, ipu_irq_err);
 
 	return 0;
 }
@@ -397,17 +397,17 @@
 
 	irq_base = pdata->irq_base;
 
-	set_irq_chained_handler(ipu->irq_fn, NULL);
-	set_irq_data(ipu->irq_fn, NULL);
+	irq_set_chained_handler(ipu->irq_fn, NULL);
+	irq_set_handler_data(ipu->irq_fn, NULL);
 
-	set_irq_chained_handler(ipu->irq_err, NULL);
-	set_irq_data(ipu->irq_err, NULL);
+	irq_set_chained_handler(ipu->irq_err, NULL);
+	irq_set_handler_data(ipu->irq_err, NULL);
 
 	for (irq = irq_base; irq < irq_base + CONFIG_MX3_IPU_IRQS; irq++) {
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip(irq, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip(irq, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/dma/Kconfig linux-libre-2.6.39-gnu/drivers/dma/Kconfig
--- linux-libre-2.6.38-gnu/drivers/dma/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 
 config DW_DMAC
 	tristate "Synopsys DesignWare AHB DMA support"
-	depends on AVR32
+	depends on HAVE_CLK
 	select DMA_ENGINE
 	default y if CPU_AT32AP7000
 	help
@@ -221,12 +221,20 @@
 
 config IMX_DMA
 	tristate "i.MX DMA support"
-	depends on ARCH_MX1 || ARCH_MX21 || MACH_MX27
+	depends on IMX_HAVE_DMA_V1
 	select DMA_ENGINE
 	help
 	  Support the i.MX DMA engine. This engine is integrated into
 	  Freescale i.MX1/21/27 chips.
 
+config MXS_DMA
+	bool "MXS DMA support"
+	depends on SOC_IMX23 || SOC_IMX28
+	select DMA_ENGINE
+	help
+	  Support the MXS DMA engine. This engine including APBH-DMA
+	  and APBX-DMA is integrated into Freescale i.MX23/28 chips.
+
 config DMA_ENGINE
 	bool
 
diff -druN linux-libre-2.6.38-gnu/drivers/dma/Makefile linux-libre-2.6.39-gnu/drivers/dma/Makefile
--- linux-libre-2.6.38-gnu/drivers/dma/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,9 +1,5 @@
-ifeq ($(CONFIG_DMADEVICES_DEBUG),y)
-	ccflags-y	+= -DDEBUG
-endif
-ifeq ($(CONFIG_DMADEVICES_VDEBUG),y)
-	ccflags-y	+= -DVERBOSE_DEBUG
-endif
+ccflags-$(CONFIG_DMADEVICES_DEBUG)  := -DDEBUG
+ccflags-$(CONFIG_DMADEVICES_VDEBUG) += -DVERBOSE_DEBUG
 
 obj-$(CONFIG_DMA_ENGINE) += dmaengine.o
 obj-$(CONFIG_NET_DMA) += iovlock.o
@@ -23,6 +19,7 @@
 obj-$(CONFIG_AMCC_PPC440SPE_ADMA) += ppc4xx/
 obj-$(CONFIG_IMX_SDMA) += imx-sdma.o
 obj-$(CONFIG_IMX_DMA) += imx-dma.o
+obj-$(CONFIG_MXS_DMA) += mxs-dma.o
 obj-$(CONFIG_TIMB_DMA) += timb_dma.o
 obj-$(CONFIG_STE_DMA40) += ste_dma40.o ste_dma40_ll.o
 obj-$(CONFIG_PL330_DMA) += pl330.o
diff -druN linux-libre-2.6.38-gnu/drivers/dma/mpc512x_dma.c linux-libre-2.6.39-gnu/drivers/dma/mpc512x_dma.c
--- linux-libre-2.6.38-gnu/drivers/dma/mpc512x_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/mpc512x_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -328,7 +328,7 @@
 	return IRQ_HANDLED;
 }
 
-/* proccess completed descriptors */
+/* process completed descriptors */
 static void mpc_dma_process_completed(struct mpc_dma *mdma)
 {
 	dma_cookie_t last_cookie = 0;
@@ -649,8 +649,7 @@
 	return &mdesc->desc;
 }
 
-static int __devinit mpc_dma_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc_dma_probe(struct platform_device *op)
 {
 	struct device_node *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -827,7 +826,7 @@
 	{},
 };
 
-static struct of_platform_driver mpc_dma_driver = {
+static struct platform_driver mpc_dma_driver = {
 	.probe		= mpc_dma_probe,
 	.remove		= __devexit_p(mpc_dma_remove),
 	.driver = {
@@ -839,13 +838,13 @@
 
 static int __init mpc_dma_init(void)
 {
-	return of_register_platform_driver(&mpc_dma_driver);
+	return platform_driver_register(&mpc_dma_driver);
 }
 module_init(mpc_dma_init);
 
 static void __exit mpc_dma_exit(void)
 {
-	of_unregister_platform_driver(&mpc_dma_driver);
+	platform_driver_unregister(&mpc_dma_driver);
 }
 module_exit(mpc_dma_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/dma/mxs-dma.c linux-libre-2.6.39-gnu/drivers/dma/mxs-dma.c
--- linux-libre-2.6.38-gnu/drivers/dma/mxs-dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/dma/mxs-dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,724 @@
+/*
+ * Copyright 2011 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * Refer to drivers/dma/imx-sdma.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/init.h>
+#include <linux/types.h>
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/clk.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/semaphore.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/dmaengine.h>
+#include <linux/delay.h>
+
+#include <asm/irq.h>
+#include <mach/mxs.h>
+#include <mach/dma.h>
+#include <mach/common.h>
+
+/*
+ * NOTE: The term "PIO" throughout the mxs-dma implementation means
+ * PIO mode of mxs apbh-dma and apbx-dma.  With this working mode,
+ * dma can program the controller registers of peripheral devices.
+ */
+
+#define MXS_DMA_APBH		0
+#define MXS_DMA_APBX		1
+#define dma_is_apbh()		(mxs_dma->dev_id == MXS_DMA_APBH)
+
+#define APBH_VERSION_LATEST	3
+#define apbh_is_old()		(mxs_dma->version < APBH_VERSION_LATEST)
+
+#define HW_APBHX_CTRL0				0x000
+#define BM_APBH_CTRL0_APB_BURST8_EN		(1 << 29)
+#define BM_APBH_CTRL0_APB_BURST_EN		(1 << 28)
+#define BP_APBH_CTRL0_CLKGATE_CHANNEL		8
+#define BP_APBH_CTRL0_RESET_CHANNEL		16
+#define HW_APBHX_CTRL1				0x010
+#define HW_APBHX_CTRL2				0x020
+#define HW_APBHX_CHANNEL_CTRL			0x030
+#define BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL	16
+#define HW_APBH_VERSION				(cpu_is_mx23() ? 0x3f0 : 0x800)
+#define HW_APBX_VERSION				0x800
+#define BP_APBHX_VERSION_MAJOR			24
+#define HW_APBHX_CHn_NXTCMDAR(n) \
+	(((dma_is_apbh() && apbh_is_old()) ? 0x050 : 0x110) + (n) * 0x70)
+#define HW_APBHX_CHn_SEMA(n) \
+	(((dma_is_apbh() && apbh_is_old()) ? 0x080 : 0x140) + (n) * 0x70)
+
+/*
+ * ccw bits definitions
+ *
+ * COMMAND:		0..1	(2)
+ * CHAIN:		2	(1)
+ * IRQ:			3	(1)
+ * NAND_LOCK:		4	(1) - not implemented
+ * NAND_WAIT4READY:	5	(1) - not implemented
+ * DEC_SEM:		6	(1)
+ * WAIT4END:		7	(1)
+ * HALT_ON_TERMINATE:	8	(1)
+ * TERMINATE_FLUSH:	9	(1)
+ * RESERVED:		10..11	(2)
+ * PIO_NUM:		12..15	(4)
+ */
+#define BP_CCW_COMMAND		0
+#define BM_CCW_COMMAND		(3 << 0)
+#define CCW_CHAIN		(1 << 2)
+#define CCW_IRQ			(1 << 3)
+#define CCW_DEC_SEM		(1 << 6)
+#define CCW_WAIT4END		(1 << 7)
+#define CCW_HALT_ON_TERM	(1 << 8)
+#define CCW_TERM_FLUSH		(1 << 9)
+#define BP_CCW_PIO_NUM		12
+#define BM_CCW_PIO_NUM		(0xf << 12)
+
+#define BF_CCW(value, field)	(((value) << BP_CCW_##field) & BM_CCW_##field)
+
+#define MXS_DMA_CMD_NO_XFER	0
+#define MXS_DMA_CMD_WRITE	1
+#define MXS_DMA_CMD_READ	2
+#define MXS_DMA_CMD_DMA_SENSE	3	/* not implemented */
+
+struct mxs_dma_ccw {
+	u32		next;
+	u16		bits;
+	u16		xfer_bytes;
+#define MAX_XFER_BYTES	0xff00
+	u32		bufaddr;
+#define MXS_PIO_WORDS	16
+	u32		pio_words[MXS_PIO_WORDS];
+};
+
+#define NUM_CCW	(int)(PAGE_SIZE / sizeof(struct mxs_dma_ccw))
+
+struct mxs_dma_chan {
+	struct mxs_dma_engine		*mxs_dma;
+	struct dma_chan			chan;
+	struct dma_async_tx_descriptor	desc;
+	struct tasklet_struct		tasklet;
+	int				chan_irq;
+	struct mxs_dma_ccw		*ccw;
+	dma_addr_t			ccw_phys;
+	dma_cookie_t			last_completed;
+	enum dma_status			status;
+	unsigned int			flags;
+#define MXS_DMA_SG_LOOP			(1 << 0)
+};
+
+#define MXS_DMA_CHANNELS		16
+#define MXS_DMA_CHANNELS_MASK		0xffff
+
+struct mxs_dma_engine {
+	int				dev_id;
+	unsigned int			version;
+	void __iomem			*base;
+	struct clk			*clk;
+	struct dma_device		dma_device;
+	struct device_dma_parameters	dma_parms;
+	struct mxs_dma_chan		mxs_chans[MXS_DMA_CHANNELS];
+};
+
+static void mxs_dma_reset_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << (chan_id + BP_APBH_CTRL0_RESET_CHANNEL),
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	else
+		writel(1 << (chan_id + BP_APBHX_CHANNEL_CTRL_RESET_CHANNEL),
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
+}
+
+static void mxs_dma_enable_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* set cmd_addr up */
+	writel(mxs_chan->ccw_phys,
+		mxs_dma->base + HW_APBHX_CHn_NXTCMDAR(chan_id));
+
+	/* enable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+	}
+
+	/* write 1 to SEMA to kick off the channel */
+	writel(1, mxs_dma->base + HW_APBHX_CHn_SEMA(chan_id));
+}
+
+static void mxs_dma_disable_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* disable apbh channel clock */
+	if (dma_is_apbh()) {
+		if (apbh_is_old())
+			writel(1 << (chan_id + BP_APBH_CTRL0_CLKGATE_CHANNEL),
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+		else
+			writel(1 << chan_id,
+				mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	}
+
+	mxs_chan->status = DMA_SUCCESS;
+}
+
+static void mxs_dma_pause_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* freeze the channel */
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	else
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_SET_ADDR);
+
+	mxs_chan->status = DMA_PAUSED;
+}
+
+static void mxs_dma_resume_chan(struct mxs_dma_chan *mxs_chan)
+{
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int chan_id = mxs_chan->chan.chan_id;
+
+	/* unfreeze the channel */
+	if (dma_is_apbh() && apbh_is_old())
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_CLR_ADDR);
+	else
+		writel(1 << chan_id,
+			mxs_dma->base + HW_APBHX_CHANNEL_CTRL + MXS_CLR_ADDR);
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+}
+
+static dma_cookie_t mxs_dma_assign_cookie(struct mxs_dma_chan *mxs_chan)
+{
+	dma_cookie_t cookie = mxs_chan->chan.cookie;
+
+	if (++cookie < 0)
+		cookie = 1;
+
+	mxs_chan->chan.cookie = cookie;
+	mxs_chan->desc.cookie = cookie;
+
+	return cookie;
+}
+
+static struct mxs_dma_chan *to_mxs_dma_chan(struct dma_chan *chan)
+{
+	return container_of(chan, struct mxs_dma_chan, chan);
+}
+
+static dma_cookie_t mxs_dma_tx_submit(struct dma_async_tx_descriptor *tx)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(tx->chan);
+
+	mxs_dma_enable_chan(mxs_chan);
+
+	return mxs_dma_assign_cookie(mxs_chan);
+}
+
+static void mxs_dma_tasklet(unsigned long data)
+{
+	struct mxs_dma_chan *mxs_chan = (struct mxs_dma_chan *) data;
+
+	if (mxs_chan->desc.callback)
+		mxs_chan->desc.callback(mxs_chan->desc.callback_param);
+}
+
+static irqreturn_t mxs_dma_int_handler(int irq, void *dev_id)
+{
+	struct mxs_dma_engine *mxs_dma = dev_id;
+	u32 stat1, stat2;
+
+	/* completion status */
+	stat1 = readl(mxs_dma->base + HW_APBHX_CTRL1);
+	stat1 &= MXS_DMA_CHANNELS_MASK;
+	writel(stat1, mxs_dma->base + HW_APBHX_CTRL1 + MXS_CLR_ADDR);
+
+	/* error status */
+	stat2 = readl(mxs_dma->base + HW_APBHX_CTRL2);
+	writel(stat2, mxs_dma->base + HW_APBHX_CTRL2 + MXS_CLR_ADDR);
+
+	/*
+	 * When both completion and error of termination bits set at the
+	 * same time, we do not take it as an error.  IOW, it only becomes
+	 * an error we need to handler here in case of ether it's (1) an bus
+	 * error or (2) a termination error with no completion.
+	 */
+	stat2 = ((stat2 >> MXS_DMA_CHANNELS) & stat2) | /* (1) */
+		(~(stat2 >> MXS_DMA_CHANNELS) & stat2 & ~stat1); /* (2) */
+
+	/* combine error and completion status for checking */
+	stat1 = (stat2 << MXS_DMA_CHANNELS) | stat1;
+	while (stat1) {
+		int channel = fls(stat1) - 1;
+		struct mxs_dma_chan *mxs_chan =
+			&mxs_dma->mxs_chans[channel % MXS_DMA_CHANNELS];
+
+		if (channel >= MXS_DMA_CHANNELS) {
+			dev_dbg(mxs_dma->dma_device.dev,
+				"%s: error in channel %d\n", __func__,
+				channel - MXS_DMA_CHANNELS);
+			mxs_chan->status = DMA_ERROR;
+			mxs_dma_reset_chan(mxs_chan);
+		} else {
+			if (mxs_chan->flags & MXS_DMA_SG_LOOP)
+				mxs_chan->status = DMA_IN_PROGRESS;
+			else
+				mxs_chan->status = DMA_SUCCESS;
+		}
+
+		stat1 &= ~(1 << channel);
+
+		if (mxs_chan->status == DMA_SUCCESS)
+			mxs_chan->last_completed = mxs_chan->desc.cookie;
+
+		/* schedule tasklet on this channel */
+		tasklet_schedule(&mxs_chan->tasklet);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_data *data = chan->private;
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int ret;
+
+	if (!data)
+		return -EINVAL;
+
+	mxs_chan->chan_irq = data->chan_irq;
+
+	mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+				&mxs_chan->ccw_phys, GFP_KERNEL);
+	if (!mxs_chan->ccw) {
+		ret = -ENOMEM;
+		goto err_alloc;
+	}
+
+	memset(mxs_chan->ccw, 0, PAGE_SIZE);
+
+	ret = request_irq(mxs_chan->chan_irq, mxs_dma_int_handler,
+				0, "mxs-dma", mxs_dma);
+	if (ret)
+		goto err_irq;
+
+	ret = clk_enable(mxs_dma->clk);
+	if (ret)
+		goto err_clk;
+
+	mxs_dma_reset_chan(mxs_chan);
+
+	dma_async_tx_descriptor_init(&mxs_chan->desc, chan);
+	mxs_chan->desc.tx_submit = mxs_dma_tx_submit;
+
+	/* the descriptor is ready */
+	async_tx_ack(&mxs_chan->desc);
+
+	return 0;
+
+err_clk:
+	free_irq(mxs_chan->chan_irq, mxs_dma);
+err_irq:
+	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+			mxs_chan->ccw, mxs_chan->ccw_phys);
+err_alloc:
+	return ret;
+}
+
+static void mxs_dma_free_chan_resources(struct dma_chan *chan)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+
+	mxs_dma_disable_chan(mxs_chan);
+
+	free_irq(mxs_chan->chan_irq, mxs_dma);
+
+	dma_free_coherent(mxs_dma->dma_device.dev, PAGE_SIZE,
+			mxs_chan->ccw, mxs_chan->ccw_phys);
+
+	clk_disable(mxs_dma->clk);
+}
+
+static struct dma_async_tx_descriptor *mxs_dma_prep_slave_sg(
+		struct dma_chan *chan, struct scatterlist *sgl,
+		unsigned int sg_len, enum dma_data_direction direction,
+		unsigned long append)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	struct mxs_dma_ccw *ccw;
+	struct scatterlist *sg;
+	int i, j;
+	u32 *pio;
+	static int idx;
+
+	if (mxs_chan->status == DMA_IN_PROGRESS && !append)
+		return NULL;
+
+	if (sg_len + (append ? idx : 0) > NUM_CCW) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum number of sg exceeded: %d > %d\n",
+				sg_len, NUM_CCW);
+		goto err_out;
+	}
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+	mxs_chan->flags = 0;
+
+	/*
+	 * If the sg is prepared with append flag set, the sg
+	 * will be appended to the last prepared sg.
+	 */
+	if (append) {
+		BUG_ON(idx < 1);
+		ccw = &mxs_chan->ccw[idx - 1];
+		ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
+		ccw->bits |= CCW_CHAIN;
+		ccw->bits &= ~CCW_IRQ;
+		ccw->bits &= ~CCW_DEC_SEM;
+		ccw->bits &= ~CCW_WAIT4END;
+	} else {
+		idx = 0;
+	}
+
+	if (direction == DMA_NONE) {
+		ccw = &mxs_chan->ccw[idx++];
+		pio = (u32 *) sgl;
+
+		for (j = 0; j < sg_len;)
+			ccw->pio_words[j++] = *pio++;
+
+		ccw->bits = 0;
+		ccw->bits |= CCW_IRQ;
+		ccw->bits |= CCW_DEC_SEM;
+		ccw->bits |= CCW_WAIT4END;
+		ccw->bits |= CCW_HALT_ON_TERM;
+		ccw->bits |= CCW_TERM_FLUSH;
+		ccw->bits |= BF_CCW(sg_len, PIO_NUM);
+		ccw->bits |= BF_CCW(MXS_DMA_CMD_NO_XFER, COMMAND);
+	} else {
+		for_each_sg(sgl, sg, sg_len, i) {
+			if (sg->length > MAX_XFER_BYTES) {
+				dev_err(mxs_dma->dma_device.dev, "maximum bytes for sg entry exceeded: %d > %d\n",
+						sg->length, MAX_XFER_BYTES);
+				goto err_out;
+			}
+
+			ccw = &mxs_chan->ccw[idx++];
+
+			ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * idx;
+			ccw->bufaddr = sg->dma_address;
+			ccw->xfer_bytes = sg->length;
+
+			ccw->bits = 0;
+			ccw->bits |= CCW_CHAIN;
+			ccw->bits |= CCW_HALT_ON_TERM;
+			ccw->bits |= CCW_TERM_FLUSH;
+			ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+					MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ,
+					COMMAND);
+
+			if (i + 1 == sg_len) {
+				ccw->bits &= ~CCW_CHAIN;
+				ccw->bits |= CCW_IRQ;
+				ccw->bits |= CCW_DEC_SEM;
+				ccw->bits |= CCW_WAIT4END;
+			}
+		}
+	}
+
+	return &mxs_chan->desc;
+
+err_out:
+	mxs_chan->status = DMA_ERROR;
+	return NULL;
+}
+
+static struct dma_async_tx_descriptor *mxs_dma_prep_dma_cyclic(
+		struct dma_chan *chan, dma_addr_t dma_addr, size_t buf_len,
+		size_t period_len, enum dma_data_direction direction)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
+	int num_periods = buf_len / period_len;
+	int i = 0, buf = 0;
+
+	if (mxs_chan->status == DMA_IN_PROGRESS)
+		return NULL;
+
+	mxs_chan->status = DMA_IN_PROGRESS;
+	mxs_chan->flags |= MXS_DMA_SG_LOOP;
+
+	if (num_periods > NUM_CCW) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum number of sg exceeded: %d > %d\n",
+				num_periods, NUM_CCW);
+		goto err_out;
+	}
+
+	if (period_len > MAX_XFER_BYTES) {
+		dev_err(mxs_dma->dma_device.dev,
+				"maximum period size exceeded: %d > %d\n",
+				period_len, MAX_XFER_BYTES);
+		goto err_out;
+	}
+
+	while (buf < buf_len) {
+		struct mxs_dma_ccw *ccw = &mxs_chan->ccw[i];
+
+		if (i + 1 == num_periods)
+			ccw->next = mxs_chan->ccw_phys;
+		else
+			ccw->next = mxs_chan->ccw_phys + sizeof(*ccw) * (i + 1);
+
+		ccw->bufaddr = dma_addr;
+		ccw->xfer_bytes = period_len;
+
+		ccw->bits = 0;
+		ccw->bits |= CCW_CHAIN;
+		ccw->bits |= CCW_IRQ;
+		ccw->bits |= CCW_HALT_ON_TERM;
+		ccw->bits |= CCW_TERM_FLUSH;
+		ccw->bits |= BF_CCW(direction == DMA_FROM_DEVICE ?
+				MXS_DMA_CMD_WRITE : MXS_DMA_CMD_READ, COMMAND);
+
+		dma_addr += period_len;
+		buf += period_len;
+
+		i++;
+	}
+
+	return &mxs_chan->desc;
+
+err_out:
+	mxs_chan->status = DMA_ERROR;
+	return NULL;
+}
+
+static int mxs_dma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
+		unsigned long arg)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	int ret = 0;
+
+	switch (cmd) {
+	case DMA_TERMINATE_ALL:
+		mxs_dma_disable_chan(mxs_chan);
+		break;
+	case DMA_PAUSE:
+		mxs_dma_pause_chan(mxs_chan);
+		break;
+	case DMA_RESUME:
+		mxs_dma_resume_chan(mxs_chan);
+		break;
+	default:
+		ret = -ENOSYS;
+	}
+
+	return ret;
+}
+
+static enum dma_status mxs_dma_tx_status(struct dma_chan *chan,
+			dma_cookie_t cookie, struct dma_tx_state *txstate)
+{
+	struct mxs_dma_chan *mxs_chan = to_mxs_dma_chan(chan);
+	dma_cookie_t last_used;
+
+	last_used = chan->cookie;
+	dma_set_tx_state(txstate, mxs_chan->last_completed, last_used, 0);
+
+	return mxs_chan->status;
+}
+
+static void mxs_dma_issue_pending(struct dma_chan *chan)
+{
+	/*
+	 * Nothing to do. We only have a single descriptor.
+	 */
+}
+
+static int __init mxs_dma_init(struct mxs_dma_engine *mxs_dma)
+{
+	int ret;
+
+	ret = clk_enable(mxs_dma->clk);
+	if (ret)
+		goto err_out;
+
+	ret = mxs_reset_block(mxs_dma->base);
+	if (ret)
+		goto err_out;
+
+	/* only major version matters */
+	mxs_dma->version = readl(mxs_dma->base +
+				((mxs_dma->dev_id == MXS_DMA_APBX) ?
+				HW_APBX_VERSION : HW_APBH_VERSION)) >>
+				BP_APBHX_VERSION_MAJOR;
+
+	/* enable apbh burst */
+	if (dma_is_apbh()) {
+		writel(BM_APBH_CTRL0_APB_BURST_EN,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+		writel(BM_APBH_CTRL0_APB_BURST8_EN,
+			mxs_dma->base + HW_APBHX_CTRL0 + MXS_SET_ADDR);
+	}
+
+	/* enable irq for all the channels */
+	writel(MXS_DMA_CHANNELS_MASK << MXS_DMA_CHANNELS,
+		mxs_dma->base + HW_APBHX_CTRL1 + MXS_SET_ADDR);
+
+	clk_disable(mxs_dma->clk);
+
+	return 0;
+
+err_out:
+	return ret;
+}
+
+static int __init mxs_dma_probe(struct platform_device *pdev)
+{
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(pdev);
+	struct mxs_dma_engine *mxs_dma;
+	struct resource *iores;
+	int ret, i;
+
+	mxs_dma = kzalloc(sizeof(*mxs_dma), GFP_KERNEL);
+	if (!mxs_dma)
+		return -ENOMEM;
+
+	mxs_dma->dev_id = id_entry->driver_data;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+
+	if (!request_mem_region(iores->start, resource_size(iores),
+				pdev->name)) {
+		ret = -EBUSY;
+		goto err_request_region;
+	}
+
+	mxs_dma->base = ioremap(iores->start, resource_size(iores));
+	if (!mxs_dma->base) {
+		ret = -ENOMEM;
+		goto err_ioremap;
+	}
+
+	mxs_dma->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(mxs_dma->clk)) {
+		ret = PTR_ERR(mxs_dma->clk);
+		goto err_clk;
+	}
+
+	dma_cap_set(DMA_SLAVE, mxs_dma->dma_device.cap_mask);
+	dma_cap_set(DMA_CYCLIC, mxs_dma->dma_device.cap_mask);
+
+	INIT_LIST_HEAD(&mxs_dma->dma_device.channels);
+
+	/* Initialize channel parameters */
+	for (i = 0; i < MXS_DMA_CHANNELS; i++) {
+		struct mxs_dma_chan *mxs_chan = &mxs_dma->mxs_chans[i];
+
+		mxs_chan->mxs_dma = mxs_dma;
+		mxs_chan->chan.device = &mxs_dma->dma_device;
+
+		tasklet_init(&mxs_chan->tasklet, mxs_dma_tasklet,
+			     (unsigned long) mxs_chan);
+
+
+		/* Add the channel to mxs_chan list */
+		list_add_tail(&mxs_chan->chan.device_node,
+			&mxs_dma->dma_device.channels);
+	}
+
+	ret = mxs_dma_init(mxs_dma);
+	if (ret)
+		goto err_init;
+
+	mxs_dma->dma_device.dev = &pdev->dev;
+
+	/* mxs_dma gets 65535 bytes maximum sg size */
+	mxs_dma->dma_device.dev->dma_parms = &mxs_dma->dma_parms;
+	dma_set_max_seg_size(mxs_dma->dma_device.dev, MAX_XFER_BYTES);
+
+	mxs_dma->dma_device.device_alloc_chan_resources = mxs_dma_alloc_chan_resources;
+	mxs_dma->dma_device.device_free_chan_resources = mxs_dma_free_chan_resources;
+	mxs_dma->dma_device.device_tx_status = mxs_dma_tx_status;
+	mxs_dma->dma_device.device_prep_slave_sg = mxs_dma_prep_slave_sg;
+	mxs_dma->dma_device.device_prep_dma_cyclic = mxs_dma_prep_dma_cyclic;
+	mxs_dma->dma_device.device_control = mxs_dma_control;
+	mxs_dma->dma_device.device_issue_pending = mxs_dma_issue_pending;
+
+	ret = dma_async_device_register(&mxs_dma->dma_device);
+	if (ret) {
+		dev_err(mxs_dma->dma_device.dev, "unable to register\n");
+		goto err_init;
+	}
+
+	dev_info(mxs_dma->dma_device.dev, "initialized\n");
+
+	return 0;
+
+err_init:
+	clk_put(mxs_dma->clk);
+err_clk:
+	iounmap(mxs_dma->base);
+err_ioremap:
+	release_mem_region(iores->start, resource_size(iores));
+err_request_region:
+	kfree(mxs_dma);
+	return ret;
+}
+
+static struct platform_device_id mxs_dma_type[] = {
+	{
+		.name = "mxs-dma-apbh",
+		.driver_data = MXS_DMA_APBH,
+	}, {
+		.name = "mxs-dma-apbx",
+		.driver_data = MXS_DMA_APBX,
+	}
+};
+
+static struct platform_driver mxs_dma_driver = {
+	.driver		= {
+		.name	= "mxs-dma",
+	},
+	.id_table	= mxs_dma_type,
+};
+
+static int __init mxs_dma_module_init(void)
+{
+	return platform_driver_probe(&mxs_dma_driver, mxs_dma_probe);
+}
+subsys_initcall(mxs_dma_module_init);
diff -druN linux-libre-2.6.38-gnu/drivers/dma/pch_dma.c linux-libre-2.6.39-gnu/drivers/dma/pch_dma.c
--- linux-libre-2.6.38-gnu/drivers/dma/pch_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/pch_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 	u32	dma_sts1;
 	u32	reserved2;
 	u32	reserved3;
-	struct pch_dma_desc_regs desc[0];
+	struct pch_dma_desc_regs desc[MAX_CHAN_NR];
 };
 
 struct pch_dma_desc {
@@ -124,7 +124,7 @@
 	struct pci_pool		*pool;
 	struct pch_dma_regs	regs;
 	struct pch_dma_desc_regs ch_regs[MAX_CHAN_NR];
-	struct pch_dma_chan	channels[0];
+	struct pch_dma_chan	channels[MAX_CHAN_NR];
 };
 
 #define PCH_DMA_CTL0	0x00
@@ -366,7 +366,7 @@
 	struct pch_dma_chan *pd_chan = to_pd_chan(txd->chan);
 	dma_cookie_t cookie;
 
-	spin_lock_bh(&pd_chan->lock);
+	spin_lock(&pd_chan->lock);
 	cookie = pdc_assign_cookie(pd_chan, desc);
 
 	if (list_empty(&pd_chan->active_list)) {
@@ -376,7 +376,7 @@
 		list_add_tail(&desc->desc_node, &pd_chan->queue);
 	}
 
-	spin_unlock_bh(&pd_chan->lock);
+	spin_unlock(&pd_chan->lock);
 	return 0;
 }
 
@@ -386,7 +386,7 @@
 	struct pch_dma *pd = to_pd(chan->device);
 	dma_addr_t addr;
 
-	desc = pci_pool_alloc(pd->pool, GFP_KERNEL, &addr);
+	desc = pci_pool_alloc(pd->pool, flags, &addr);
 	if (desc) {
 		memset(desc, 0, sizeof(struct pch_dma_desc));
 		INIT_LIST_HEAD(&desc->tx_list);
@@ -405,7 +405,7 @@
 	struct pch_dma_desc *ret = NULL;
 	int i;
 
-	spin_lock_bh(&pd_chan->lock);
+	spin_lock(&pd_chan->lock);
 	list_for_each_entry_safe(desc, _d, &pd_chan->free_list, desc_node) {
 		i++;
 		if (async_tx_test_ack(&desc->txd)) {
@@ -415,15 +415,15 @@
 		}
 		dev_dbg(chan2dev(&pd_chan->chan), "desc %p not ACKed\n", desc);
 	}
-	spin_unlock_bh(&pd_chan->lock);
+	spin_unlock(&pd_chan->lock);
 	dev_dbg(chan2dev(&pd_chan->chan), "scanned %d descriptors\n", i);
 
 	if (!ret) {
 		ret = pdc_alloc_desc(&pd_chan->chan, GFP_NOIO);
 		if (ret) {
-			spin_lock_bh(&pd_chan->lock);
+			spin_lock(&pd_chan->lock);
 			pd_chan->descs_allocated++;
-			spin_unlock_bh(&pd_chan->lock);
+			spin_unlock(&pd_chan->lock);
 		} else {
 			dev_err(chan2dev(&pd_chan->chan),
 				"failed to alloc desc\n");
@@ -437,10 +437,10 @@
 			 struct pch_dma_desc *desc)
 {
 	if (desc) {
-		spin_lock_bh(&pd_chan->lock);
+		spin_lock(&pd_chan->lock);
 		list_splice_init(&desc->tx_list, &pd_chan->free_list);
 		list_add(&desc->desc_node, &pd_chan->free_list);
-		spin_unlock_bh(&pd_chan->lock);
+		spin_unlock(&pd_chan->lock);
 	}
 }
 
@@ -530,9 +530,9 @@
 	struct pch_dma_chan *pd_chan = to_pd_chan(chan);
 
 	if (pdc_is_idle(pd_chan)) {
-		spin_lock_bh(&pd_chan->lock);
+		spin_lock(&pd_chan->lock);
 		pdc_advance_work(pd_chan);
-		spin_unlock_bh(&pd_chan->lock);
+		spin_unlock(&pd_chan->lock);
 	}
 }
 
@@ -592,7 +592,6 @@
 			goto err_desc_get;
 		}
 
-
 		if (!first) {
 			first = desc;
 		} else {
@@ -641,13 +640,13 @@
 
 	spin_unlock_bh(&pd_chan->lock);
 
-
 	return 0;
 }
 
 static void pdc_tasklet(unsigned long data)
 {
 	struct pch_dma_chan *pd_chan = (struct pch_dma_chan *)data;
+	unsigned long flags;
 
 	if (!pdc_is_idle(pd_chan)) {
 		dev_err(chan2dev(&pd_chan->chan),
@@ -655,12 +654,12 @@
 		return;
 	}
 
-	spin_lock_bh(&pd_chan->lock);
+	spin_lock_irqsave(&pd_chan->lock, flags);
 	if (test_and_clear_bit(0, &pd_chan->err_status))
 		pdc_handle_error(pd_chan);
 	else
 		pdc_advance_work(pd_chan);
-	spin_unlock_bh(&pd_chan->lock);
+	spin_unlock_irqrestore(&pd_chan->lock, flags);
 }
 
 static irqreturn_t pd_irq(int irq, void *devid)
@@ -694,6 +693,7 @@
 	return ret;
 }
 
+#ifdef	CONFIG_PM
 static void pch_dma_save_regs(struct pch_dma *pd)
 {
 	struct pch_dma_chan *pd_chan;
@@ -771,6 +771,7 @@
 
 	return 0;
 }
+#endif
 
 static int __devinit pch_dma_probe(struct pci_dev *pdev,
 				   const struct pci_device_id *id)
diff -druN linux-libre-2.6.38-gnu/drivers/dma/pl330.c linux-libre-2.6.39-gnu/drivers/dma/pl330.c
--- linux-libre-2.6.38-gnu/drivers/dma/pl330.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/pl330.c	2011-05-19 00:06:34.000000000 -0400
@@ -657,7 +657,7 @@
 }
 
 static int __devinit
-pl330_probe(struct amba_device *adev, struct amba_id *id)
+pl330_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct dma_pl330_platdata *pdat;
 	struct dma_pl330_dmac *pdmac;
diff -druN linux-libre-2.6.38-gnu/drivers/dma/ppc4xx/adma.c linux-libre-2.6.39-gnu/drivers/dma/ppc4xx/adma.c
--- linux-libre-2.6.38-gnu/drivers/dma/ppc4xx/adma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/ppc4xx/adma.c	2011-05-19 00:06:34.000000000 -0400
@@ -4393,8 +4393,7 @@
 /**
  * ppc440spe_adma_probe - probe the asynch device
  */
-static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev,
-					  const struct of_device_id *match)
+static int __devinit ppc440spe_adma_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct resource res;
@@ -4944,7 +4943,7 @@
 };
 MODULE_DEVICE_TABLE(of, ppc440spe_adma_of_match);
 
-static struct of_platform_driver ppc440spe_adma_driver = {
+static struct platform_driver ppc440spe_adma_driver = {
 	.probe = ppc440spe_adma_probe,
 	.remove = __devexit_p(ppc440spe_adma_remove),
 	.driver = {
@@ -4962,7 +4961,7 @@
 	if (ret)
 		return ret;
 
-	ret = of_register_platform_driver(&ppc440spe_adma_driver);
+	ret = platform_driver_register(&ppc440spe_adma_driver);
 	if (ret) {
 		pr_err("%s: failed to register platform driver\n",
 			__func__);
@@ -4996,7 +4995,7 @@
 	/* User will not be able to enable h/w RAID-6 */
 	pr_err("%s: failed to create RAID-6 driver interface\n",
 		__func__);
-	of_unregister_platform_driver(&ppc440spe_adma_driver);
+	platform_driver_unregister(&ppc440spe_adma_driver);
 out_reg:
 	dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len);
 	kfree(ppc440spe_dma_fifo_buf);
@@ -5011,7 +5010,7 @@
 			   &driver_attr_enable);
 	driver_remove_file(&ppc440spe_adma_driver.driver,
 			   &driver_attr_devices);
-	of_unregister_platform_driver(&ppc440spe_adma_driver);
+	platform_driver_unregister(&ppc440spe_adma_driver);
 	dcr_unmap(ppc440spe_mq_dcr_host, ppc440spe_mq_dcr_len);
 	kfree(ppc440spe_dma_fifo_buf);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/dma/shdma.c linux-libre-2.6.39-gnu/drivers/dma/shdma.c
--- linux-libre-2.6.38-gnu/drivers/dma/shdma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/shdma.c	2011-05-19 00:06:34.000000000 -0400
@@ -750,7 +750,7 @@
 		return;
 	}
 
-	/* Find the first not transferred desciptor */
+	/* Find the first not transferred descriptor */
 	list_for_each_entry(desc, &sh_chan->ld_queue, node)
 		if (desc->mark == DESC_SUBMITTED) {
 			dev_dbg(sh_chan->dev, "Queue #%d to %d: %u@%x -> %x\n",
@@ -865,7 +865,12 @@
 
 static irqreturn_t sh_dmae_err(int irq, void *data)
 {
-	return IRQ_RETVAL(sh_dmae_reset(data));
+	struct sh_dmae_device *shdev = data;
+
+	if (dmaor_read(shdev) & DMAOR_AE)
+		return IRQ_RETVAL(sh_dmae_reset(data));
+	else
+		return IRQ_NONE;
 }
 
 static void dmae_do_tasklet(unsigned long data)
diff -druN linux-libre-2.6.38-gnu/drivers/dma/ste_dma40.c linux-libre-2.6.39-gnu/drivers/dma/ste_dma40.c
--- linux-libre-2.6.38-gnu/drivers/dma/ste_dma40.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/ste_dma40.c	2011-05-19 00:06:34.000000000 -0400
@@ -68,6 +68,7 @@
  * @base: Pointer to memory area when the pre_alloc_lli's are not large
  * enough, IE bigger than the most common case, 1 dst and 1 src. NULL if
  * pre_alloc_lli is used.
+ * @dma_addr: DMA address, if mapped
  * @size: The size in bytes of the memory at base or the size of pre_alloc_lli.
  * @pre_alloc_lli: Pre allocated area for the most common case of transfers,
  * one buffer to one buffer.
@@ -75,6 +76,7 @@
 struct d40_lli_pool {
 	void	*base;
 	int	 size;
+	dma_addr_t	dma_addr;
 	/* Space for dst and src, plus an extra for padding */
 	u8	 pre_alloc_lli[3 * sizeof(struct d40_phy_lli)];
 };
@@ -88,13 +90,12 @@
  * @lli_log: Same as above but for logical channels.
  * @lli_pool: The pool with two entries pre-allocated.
  * @lli_len: Number of llis of current descriptor.
- * @lli_current: Number of transfered llis.
+ * @lli_current: Number of transferred llis.
  * @lcla_alloc: Number of LCLA entries allocated.
  * @txd: DMA engine struct. Used for among other things for communication
  * during a transfer.
  * @node: List entry.
  * @is_in_client_list: true if the client owns this descriptor.
- * @is_hw_linked: true if this job will automatically be continued for
  * the previous one.
  *
  * This descriptor is used for both logical and physical transfers.
@@ -114,7 +115,7 @@
 	struct list_head		 node;
 
 	bool				 is_in_client_list;
-	bool				 is_hw_linked;
+	bool				 cyclic;
 };
 
 /**
@@ -130,6 +131,7 @@
  */
 struct d40_lcla_pool {
 	void		*base;
+	dma_addr_t	dma_addr;
 	void		*base_unaligned;
 	int		 pages;
 	spinlock_t	 lock;
@@ -303,9 +305,37 @@
 	unsigned int val;
 };
 
-static int d40_pool_lli_alloc(struct d40_desc *d40d,
-			      int lli_len, bool is_log)
+static struct device *chan2dev(struct d40_chan *d40c)
+{
+	return &d40c->chan.dev->device;
+}
+
+static bool chan_is_physical(struct d40_chan *chan)
+{
+	return chan->log_num == D40_PHY_CHAN;
+}
+
+static bool chan_is_logical(struct d40_chan *chan)
+{
+	return !chan_is_physical(chan);
+}
+
+static void __iomem *chan_base(struct d40_chan *chan)
+{
+	return chan->base->virtbase + D40_DREG_PCBASE +
+	       chan->phy_chan->num * D40_DREG_PCDELTA;
+}
+
+#define d40_err(dev, format, arg...)		\
+	dev_err(dev, "[%s] " format, __func__, ## arg)
+
+#define chan_err(d40c, format, arg...)		\
+	d40_err(chan2dev(d40c), format, ## arg)
+
+static int d40_pool_lli_alloc(struct d40_chan *d40c, struct d40_desc *d40d,
+			      int lli_len)
 {
+	bool is_log = chan_is_logical(d40c);
 	u32 align;
 	void *base;
 
@@ -319,7 +349,7 @@
 		d40d->lli_pool.size = sizeof(d40d->lli_pool.pre_alloc_lli);
 		d40d->lli_pool.base = NULL;
 	} else {
-		d40d->lli_pool.size = ALIGN(lli_len * 2 * align, align);
+		d40d->lli_pool.size = lli_len * 2 * align;
 
 		base = kmalloc(d40d->lli_pool.size + align, GFP_NOWAIT);
 		d40d->lli_pool.base = base;
@@ -329,22 +359,37 @@
 	}
 
 	if (is_log) {
-		d40d->lli_log.src = PTR_ALIGN((struct d40_log_lli *) base,
-					      align);
-		d40d->lli_log.dst = PTR_ALIGN(d40d->lli_log.src + lli_len,
-					      align);
+		d40d->lli_log.src = PTR_ALIGN(base, align);
+		d40d->lli_log.dst = d40d->lli_log.src + lli_len;
+
+		d40d->lli_pool.dma_addr = 0;
 	} else {
-		d40d->lli_phy.src = PTR_ALIGN((struct d40_phy_lli *)base,
-					      align);
-		d40d->lli_phy.dst = PTR_ALIGN(d40d->lli_phy.src + lli_len,
-					      align);
+		d40d->lli_phy.src = PTR_ALIGN(base, align);
+		d40d->lli_phy.dst = d40d->lli_phy.src + lli_len;
+
+		d40d->lli_pool.dma_addr = dma_map_single(d40c->base->dev,
+							 d40d->lli_phy.src,
+							 d40d->lli_pool.size,
+							 DMA_TO_DEVICE);
+
+		if (dma_mapping_error(d40c->base->dev,
+				      d40d->lli_pool.dma_addr)) {
+			kfree(d40d->lli_pool.base);
+			d40d->lli_pool.base = NULL;
+			d40d->lli_pool.dma_addr = 0;
+			return -ENOMEM;
+		}
 	}
 
 	return 0;
 }
 
-static void d40_pool_lli_free(struct d40_desc *d40d)
+static void d40_pool_lli_free(struct d40_chan *d40c, struct d40_desc *d40d)
 {
+	if (d40d->lli_pool.dma_addr)
+		dma_unmap_single(d40c->base->dev, d40d->lli_pool.dma_addr,
+				 d40d->lli_pool.size, DMA_TO_DEVICE);
+
 	kfree(d40d->lli_pool.base);
 	d40d->lli_pool.base = NULL;
 	d40d->lli_pool.size = 0;
@@ -391,7 +436,7 @@
 	int i;
 	int ret = -EINVAL;
 
-	if (d40c->log_num == D40_PHY_CHAN)
+	if (chan_is_physical(d40c))
 		return 0;
 
 	spin_lock_irqsave(&d40c->base->lcla_pool.lock, flags);
@@ -430,7 +475,7 @@
 
 		list_for_each_entry_safe(d, _d, &d40c->client, node)
 			if (async_tx_test_ack(&d->txd)) {
-				d40_pool_lli_free(d);
+				d40_pool_lli_free(d40c, d);
 				d40_desc_remove(d);
 				desc = d;
 				memset(desc, 0, sizeof(*desc));
@@ -450,6 +495,7 @@
 static void d40_desc_free(struct d40_chan *d40c, struct d40_desc *d40d)
 {
 
+	d40_pool_lli_free(d40c, d40d);
 	d40_lcla_free_all(d40c, d40d);
 	kmem_cache_free(d40c->base->desc_slab, d40d);
 }
@@ -459,57 +505,128 @@
 	list_add_tail(&desc->node, &d40c->active);
 }
 
-static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d)
+static void d40_phy_lli_load(struct d40_chan *chan, struct d40_desc *desc)
 {
-	int curr_lcla = -EINVAL, next_lcla;
+	struct d40_phy_lli *lli_dst = desc->lli_phy.dst;
+	struct d40_phy_lli *lli_src = desc->lli_phy.src;
+	void __iomem *base = chan_base(chan);
 
-	if (d40c->log_num == D40_PHY_CHAN) {
-		d40_phy_lli_write(d40c->base->virtbase,
-				  d40c->phy_chan->num,
-				  d40d->lli_phy.dst,
-				  d40d->lli_phy.src);
-		d40d->lli_current = d40d->lli_len;
-	} else {
+	writel(lli_src->reg_cfg, base + D40_CHAN_REG_SSCFG);
+	writel(lli_src->reg_elt, base + D40_CHAN_REG_SSELT);
+	writel(lli_src->reg_ptr, base + D40_CHAN_REG_SSPTR);
+	writel(lli_src->reg_lnk, base + D40_CHAN_REG_SSLNK);
 
-		if ((d40d->lli_len - d40d->lli_current) > 1)
-			curr_lcla = d40_lcla_alloc_one(d40c, d40d);
+	writel(lli_dst->reg_cfg, base + D40_CHAN_REG_SDCFG);
+	writel(lli_dst->reg_elt, base + D40_CHAN_REG_SDELT);
+	writel(lli_dst->reg_ptr, base + D40_CHAN_REG_SDPTR);
+	writel(lli_dst->reg_lnk, base + D40_CHAN_REG_SDLNK);
+}
 
-		d40_log_lli_lcpa_write(d40c->lcpa,
-				       &d40d->lli_log.dst[d40d->lli_current],
-				       &d40d->lli_log.src[d40d->lli_current],
-				       curr_lcla);
+static void d40_log_lli_to_lcxa(struct d40_chan *chan, struct d40_desc *desc)
+{
+	struct d40_lcla_pool *pool = &chan->base->lcla_pool;
+	struct d40_log_lli_bidir *lli = &desc->lli_log;
+	int lli_current = desc->lli_current;
+	int lli_len = desc->lli_len;
+	bool cyclic = desc->cyclic;
+	int curr_lcla = -EINVAL;
+	int first_lcla = 0;
+	bool linkback;
 
-		d40d->lli_current++;
-		for (; d40d->lli_current < d40d->lli_len; d40d->lli_current++) {
-			struct d40_log_lli *lcla;
+	/*
+	 * We may have partially running cyclic transfers, in case we did't get
+	 * enough LCLA entries.
+	 */
+	linkback = cyclic && lli_current == 0;
 
-			if (d40d->lli_current + 1 < d40d->lli_len)
-				next_lcla = d40_lcla_alloc_one(d40c, d40d);
-			else
-				next_lcla = -EINVAL;
+	/*
+	 * For linkback, we need one LCLA even with only one link, because we
+	 * can't link back to the one in LCPA space
+	 */
+	if (linkback || (lli_len - lli_current > 1)) {
+		curr_lcla = d40_lcla_alloc_one(chan, desc);
+		first_lcla = curr_lcla;
+	}
 
-			lcla = d40c->base->lcla_pool.base +
-				d40c->phy_chan->num * 1024 +
-				8 * curr_lcla * 2;
+	/*
+	 * For linkback, we normally load the LCPA in the loop since we need to
+	 * link it to the second LCLA and not the first.  However, if we
+	 * couldn't even get a first LCLA, then we have to run in LCPA and
+	 * reload manually.
+	 */
+	if (!linkback || curr_lcla == -EINVAL) {
+		unsigned int flags = 0;
 
-			d40_log_lli_lcla_write(lcla,
-					       &d40d->lli_log.dst[d40d->lli_current],
-					       &d40d->lli_log.src[d40d->lli_current],
-					       next_lcla);
+		if (curr_lcla == -EINVAL)
+			flags |= LLI_TERM_INT;
 
-			(void) dma_map_single(d40c->base->dev, lcla,
-					      2 * sizeof(struct d40_log_lli),
-					      DMA_TO_DEVICE);
+		d40_log_lli_lcpa_write(chan->lcpa,
+				       &lli->dst[lli_current],
+				       &lli->src[lli_current],
+				       curr_lcla,
+				       flags);
+		lli_current++;
+	}
 
-			curr_lcla = next_lcla;
+	if (curr_lcla < 0)
+		goto out;
 
-			if (curr_lcla == -EINVAL) {
-				d40d->lli_current++;
-				break;
-			}
+	for (; lli_current < lli_len; lli_current++) {
+		unsigned int lcla_offset = chan->phy_chan->num * 1024 +
+					   8 * curr_lcla * 2;
+		struct d40_log_lli *lcla = pool->base + lcla_offset;
+		unsigned int flags = 0;
+		int next_lcla;
+
+		if (lli_current + 1 < lli_len)
+			next_lcla = d40_lcla_alloc_one(chan, desc);
+		else
+			next_lcla = linkback ? first_lcla : -EINVAL;
+
+		if (cyclic || next_lcla == -EINVAL)
+			flags |= LLI_TERM_INT;
+
+		if (linkback && curr_lcla == first_lcla) {
+			/* First link goes in both LCPA and LCLA */
+			d40_log_lli_lcpa_write(chan->lcpa,
+					       &lli->dst[lli_current],
+					       &lli->src[lli_current],
+					       next_lcla, flags);
+		}
+
+		/*
+		 * One unused LCLA in the cyclic case if the very first
+		 * next_lcla fails...
+		 */
+		d40_log_lli_lcla_write(lcla,
+				       &lli->dst[lli_current],
+				       &lli->src[lli_current],
+				       next_lcla, flags);
+
+		dma_sync_single_range_for_device(chan->base->dev,
+					pool->dma_addr, lcla_offset,
+					2 * sizeof(struct d40_log_lli),
+					DMA_TO_DEVICE);
 
+		curr_lcla = next_lcla;
+
+		if (curr_lcla == -EINVAL || curr_lcla == first_lcla) {
+			lli_current++;
+			break;
 		}
 	}
+
+out:
+	desc->lli_current = lli_current;
+}
+
+static void d40_desc_load(struct d40_chan *d40c, struct d40_desc *d40d)
+{
+	if (chan_is_physical(d40c)) {
+		d40_phy_lli_load(d40c, d40d);
+		d40d->lli_current = d40d->lli_len;
+	} else
+		d40_log_lli_to_lcxa(d40c, d40d);
 }
 
 static struct d40_desc *d40_first_active_get(struct d40_chan *d40c)
@@ -543,18 +660,6 @@
 	return d;
 }
 
-static struct d40_desc *d40_last_queued(struct d40_chan *d40c)
-{
-	struct d40_desc *d;
-
-	if (list_empty(&d40c->queue))
-		return NULL;
-	list_for_each_entry(d, &d40c->queue, node)
-		if (list_is_last(&d->node, &d40c->queue))
-			break;
-	return d;
-}
-
 static int d40_psize_2_burst_size(bool is_log, int psize)
 {
 	if (is_log) {
@@ -666,9 +771,9 @@
 		}
 
 		if (i == D40_SUSPEND_MAX_IT) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s]: unable to suspend the chl %d (log: %d) status %x\n",
-				__func__, d40c->phy_chan->num, d40c->log_num,
+			chan_err(d40c,
+				"unable to suspend the chl %d (log: %d) status %x\n",
+				d40c->phy_chan->num, d40c->log_num,
 				status);
 			dump_stack();
 			ret = -EBUSY;
@@ -701,17 +806,45 @@
 	d40c->busy = false;
 }
 
+static void __d40_config_set_event(struct d40_chan *d40c, bool enable,
+				   u32 event, int reg)
+{
+	void __iomem *addr = chan_base(d40c) + reg;
+	int tries;
+
+	if (!enable) {
+		writel((D40_DEACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
+		       | ~D40_EVENTLINE_MASK(event), addr);
+		return;
+	}
+
+	/*
+	 * The hardware sometimes doesn't register the enable when src and dst
+	 * event lines are active on the same logical channel.  Retry to ensure
+	 * it does.  Usually only one retry is sufficient.
+	 */
+	tries = 100;
+	while (--tries) {
+		writel((D40_ACTIVATE_EVENTLINE << D40_EVENTLINE_POS(event))
+		       | ~D40_EVENTLINE_MASK(event), addr);
+
+		if (readl(addr) & D40_EVENTLINE_MASK(event))
+			break;
+	}
+
+	if (tries != 99)
+		dev_dbg(chan2dev(d40c),
+			"[%s] workaround enable S%cLNK (%d tries)\n",
+			__func__, reg == D40_CHAN_REG_SSLNK ? 'S' : 'D',
+			100 - tries);
+
+	WARN_ON(!tries);
+}
+
 static void d40_config_set_event(struct d40_chan *d40c, bool do_enable)
 {
-	u32 val;
 	unsigned long flags;
 
-	/* Notice, that disable requires the physical channel to be stopped */
-	if (do_enable)
-		val = D40_ACTIVATE_EVENTLINE;
-	else
-		val = D40_DEACTIVATE_EVENTLINE;
-
 	spin_lock_irqsave(&d40c->phy_chan->lock, flags);
 
 	/* Enable event line connected to device (or memcpy) */
@@ -719,20 +852,15 @@
 	    (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH)) {
 		u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
 
-		writel((val << D40_EVENTLINE_POS(event)) |
-		       ~D40_EVENTLINE_MASK(event),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSLNK);
+		__d40_config_set_event(d40c, do_enable, event,
+				       D40_CHAN_REG_SSLNK);
 	}
+
 	if (d40c->dma_cfg.dir !=  STEDMA40_PERIPH_TO_MEM) {
 		u32 event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
 
-		writel((val << D40_EVENTLINE_POS(event)) |
-		       ~D40_EVENTLINE_MASK(event),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDLNK);
+		__d40_config_set_event(d40c, do_enable, event,
+				       D40_CHAN_REG_SDLNK);
 	}
 
 	spin_unlock_irqrestore(&d40c->phy_chan->lock, flags);
@@ -740,15 +868,12 @@
 
 static u32 d40_chan_has_events(struct d40_chan *d40c)
 {
+	void __iomem *chanbase = chan_base(d40c);
 	u32 val;
 
-	val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		    d40c->phy_chan->num * D40_DREG_PCDELTA +
-		    D40_CHAN_REG_SSLNK);
+	val = readl(chanbase + D40_CHAN_REG_SSLNK);
+	val |= readl(chanbase + D40_CHAN_REG_SDLNK);
 
-	val |= readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		     d40c->phy_chan->num * D40_DREG_PCDELTA +
-		     D40_CHAN_REG_SDLNK);
 	return val;
 }
 
@@ -771,7 +896,7 @@
 			= D40_DREG_PRMO_LCHAN_SRC_LOG_DST_LOG,
 	};
 
-	if (d40c->log_num == D40_PHY_CHAN)
+	if (chan_is_physical(d40c))
 		return phy_map[d40c->dma_cfg.mode_opt];
 	else
 		return log_map[d40c->dma_cfg.mode_opt];
@@ -785,7 +910,7 @@
 	/* Odd addresses are even addresses + 4 */
 	addr_base = (d40c->phy_chan->num % 2) * 4;
 	/* Setup channel mode to logical or physical */
-	var = ((u32)(d40c->log_num != D40_PHY_CHAN) + 1) <<
+	var = ((u32)(chan_is_logical(d40c)) + 1) <<
 		D40_CHAN_POS(d40c->phy_chan->num);
 	writel(var, d40c->base->virtbase + D40_DREG_PRMSE + addr_base);
 
@@ -794,30 +919,18 @@
 
 	writel(var, d40c->base->virtbase + D40_DREG_PRMOE + addr_base);
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	if (chan_is_logical(d40c)) {
+		int lidx = (d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS)
+			   & D40_SREG_ELEM_LOG_LIDX_MASK;
+		void __iomem *chanbase = chan_base(d40c);
+
 		/* Set default config for CFG reg */
-		writel(d40c->src_def_cfg,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSCFG);
-		writel(d40c->dst_def_cfg,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDCFG);
+		writel(d40c->src_def_cfg, chanbase + D40_CHAN_REG_SSCFG);
+		writel(d40c->dst_def_cfg, chanbase + D40_CHAN_REG_SDCFG);
 
 		/* Set LIDX for lcla */
-		writel((d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) &
-		       D40_SREG_ELEM_LOG_LIDX_MASK,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDELT);
-
-		writel((d40c->phy_chan->num << D40_SREG_ELEM_LOG_LIDX_POS) &
-		       D40_SREG_ELEM_LOG_LIDX_MASK,
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSELT);
-
+		writel(lidx, chanbase + D40_CHAN_REG_SSELT);
+		writel(lidx, chanbase + D40_CHAN_REG_SDELT);
 	}
 }
 
@@ -825,15 +938,15 @@
 {
 	u32 num_elt;
 
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		num_elt = (readl(&d40c->lcpa->lcsp2) & D40_MEM_LCSP2_ECNT_MASK)
 			>> D40_MEM_LCSP2_ECNT_POS;
-	else
-		num_elt = (readl(d40c->base->virtbase + D40_DREG_PCBASE +
-				 d40c->phy_chan->num * D40_DREG_PCDELTA +
-				 D40_CHAN_REG_SDELT) &
-			   D40_SREG_ELEM_PHY_ECNT_MASK) >>
-			D40_SREG_ELEM_PHY_ECNT_POS;
+	else {
+		u32 val = readl(chan_base(d40c) + D40_CHAN_REG_SDELT);
+		num_elt = (val & D40_SREG_ELEM_PHY_ECNT_MASK)
+			  >> D40_SREG_ELEM_PHY_ECNT_POS;
+	}
+
 	return num_elt * (1 << d40c->dma_cfg.dst_info.data_width);
 }
 
@@ -841,20 +954,17 @@
 {
 	bool is_link;
 
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		is_link = readl(&d40c->lcpa->lcsp3) &  D40_MEM_LCSP3_DLOS_MASK;
 	else
-		is_link = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-				d40c->phy_chan->num * D40_DREG_PCDELTA +
-				D40_CHAN_REG_SDLNK) &
-			D40_SREG_LNK_PHYS_LNK_MASK;
+		is_link = readl(chan_base(d40c) + D40_CHAN_REG_SDLNK)
+			  & D40_SREG_LNK_PHYS_LNK_MASK;
+
 	return is_link;
 }
 
-static int d40_pause(struct dma_chan *chan)
+static int d40_pause(struct d40_chan *d40c)
 {
-	struct d40_chan *d40c =
-		container_of(chan, struct d40_chan, chan);
 	int res = 0;
 	unsigned long flags;
 
@@ -865,7 +975,7 @@
 
 	res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
 	if (res == 0) {
-		if (d40c->log_num != D40_PHY_CHAN) {
+		if (chan_is_logical(d40c)) {
 			d40_config_set_event(d40c, false);
 			/* Resume the other logical channels if any */
 			if (d40_chan_has_events(d40c))
@@ -878,10 +988,8 @@
 	return res;
 }
 
-static int d40_resume(struct dma_chan *chan)
+static int d40_resume(struct d40_chan *d40c)
 {
-	struct d40_chan *d40c =
-		container_of(chan, struct d40_chan, chan);
 	int res = 0;
 	unsigned long flags;
 
@@ -891,7 +999,7 @@
 	spin_lock_irqsave(&d40c->lock, flags);
 
 	if (d40c->base->rev == 0)
-		if (d40c->log_num != D40_PHY_CHAN) {
+		if (chan_is_logical(d40c)) {
 			res = d40_channel_execute_command(d40c,
 							  D40_DMA_SUSPEND_REQ);
 			goto no_suspend;
@@ -900,7 +1008,7 @@
 	/* If bytes left to transfer or linked tx resume job */
 	if (d40_residue(d40c) || d40_tx_is_linked(d40c)) {
 
-		if (d40c->log_num != D40_PHY_CHAN)
+		if (chan_is_logical(d40c))
 			d40_config_set_event(d40c, true);
 
 		res = d40_channel_execute_command(d40c, D40_DMA_RUN);
@@ -911,75 +1019,20 @@
 	return res;
 }
 
-static void d40_tx_submit_log(struct d40_chan *d40c, struct d40_desc *d40d)
-{
-	/* TODO: Write */
-}
-
-static void d40_tx_submit_phy(struct d40_chan *d40c, struct d40_desc *d40d)
+static int d40_terminate_all(struct d40_chan *chan)
 {
-	struct d40_desc *d40d_prev = NULL;
-	int i;
-	u32 val;
-
-	if (!list_empty(&d40c->queue))
-		d40d_prev = d40_last_queued(d40c);
-	else if (!list_empty(&d40c->active))
-		d40d_prev = d40_first_active_get(d40c);
-
-	if (!d40d_prev)
-		return;
-
-	/* Here we try to join this job with previous jobs */
-	val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		    d40c->phy_chan->num * D40_DREG_PCDELTA +
-		    D40_CHAN_REG_SSLNK);
-
-	/* Figure out which link we're currently transmitting */
-	for (i = 0; i < d40d_prev->lli_len; i++)
-		if (val == d40d_prev->lli_phy.src[i].reg_lnk)
-			break;
-
-	val = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-		    d40c->phy_chan->num * D40_DREG_PCDELTA +
-		    D40_CHAN_REG_SSELT) >> D40_SREG_ELEM_LOG_ECNT_POS;
-
-	if (i == (d40d_prev->lli_len - 1) && val > 0) {
-		/* Change the current one */
-		writel(virt_to_phys(d40d->lli_phy.src),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SSLNK);
-		writel(virt_to_phys(d40d->lli_phy.dst),
-		       d40c->base->virtbase + D40_DREG_PCBASE +
-		       d40c->phy_chan->num * D40_DREG_PCDELTA +
-		       D40_CHAN_REG_SDLNK);
-
-		d40d->is_hw_linked = true;
-
-	} else if (i < d40d_prev->lli_len) {
-		(void) dma_unmap_single(d40c->base->dev,
-					virt_to_phys(d40d_prev->lli_phy.src),
-					d40d_prev->lli_pool.size,
-					DMA_TO_DEVICE);
+	unsigned long flags;
+	int ret = 0;
 
-		/* Keep the settings */
-		val = d40d_prev->lli_phy.src[d40d_prev->lli_len - 1].reg_lnk &
-			~D40_SREG_LNK_PHYS_LNK_MASK;
-		d40d_prev->lli_phy.src[d40d_prev->lli_len - 1].reg_lnk =
-			val | virt_to_phys(d40d->lli_phy.src);
+	ret = d40_pause(chan);
+	if (!ret && chan_is_physical(chan))
+		ret = d40_channel_execute_command(chan, D40_DMA_STOP);
 
-		val = d40d_prev->lli_phy.dst[d40d_prev->lli_len - 1].reg_lnk &
-			~D40_SREG_LNK_PHYS_LNK_MASK;
-		d40d_prev->lli_phy.dst[d40d_prev->lli_len - 1].reg_lnk =
-			val | virt_to_phys(d40d->lli_phy.dst);
+	spin_lock_irqsave(&chan->lock, flags);
+	d40_term_all(chan);
+	spin_unlock_irqrestore(&chan->lock, flags);
 
-		(void) dma_map_single(d40c->base->dev,
-				      d40d_prev->lli_phy.src,
-				      d40d_prev->lli_pool.size,
-				      DMA_TO_DEVICE);
-		d40d->is_hw_linked = true;
-	}
+	return ret;
 }
 
 static dma_cookie_t d40_tx_submit(struct dma_async_tx_descriptor *tx)
@@ -990,8 +1043,6 @@
 	struct d40_desc *d40d = container_of(tx, struct d40_desc, txd);
 	unsigned long flags;
 
-	(void) d40_pause(&d40c->chan);
-
 	spin_lock_irqsave(&d40c->lock, flags);
 
 	d40c->chan.cookie++;
@@ -1001,17 +1052,10 @@
 
 	d40d->txd.cookie = d40c->chan.cookie;
 
-	if (d40c->log_num == D40_PHY_CHAN)
-		d40_tx_submit_phy(d40c, d40d);
-	else
-		d40_tx_submit_log(d40c, d40d);
-
 	d40_desc_queue(d40c, d40d);
 
 	spin_unlock_irqrestore(&d40c->lock, flags);
 
-	(void) d40_resume(&d40c->chan);
-
 	return tx->cookie;
 }
 
@@ -1020,7 +1064,7 @@
 	if (d40c->base->rev == 0) {
 		int err;
 
-		if (d40c->log_num != D40_PHY_CHAN) {
+		if (chan_is_logical(d40c)) {
 			err = d40_channel_execute_command(d40c,
 							  D40_DMA_SUSPEND_REQ);
 			if (err)
@@ -1028,7 +1072,7 @@
 		}
 	}
 
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		d40_config_set_event(d40c, true);
 
 	return d40_channel_execute_command(d40c, D40_DMA_RUN);
@@ -1051,21 +1095,14 @@
 		/* Add to active queue */
 		d40_desc_submit(d40c, d40d);
 
-		/*
-		 * If this job is already linked in hw,
-		 * do not submit it.
-		 */
-
-		if (!d40d->is_hw_linked) {
-			/* Initiate DMA job */
-			d40_desc_load(d40c, d40d);
+		/* Initiate DMA job */
+		d40_desc_load(d40c, d40d);
 
-			/* Start dma job */
-			err = d40_start(d40c);
+		/* Start dma job */
+		err = d40_start(d40c);
 
-			if (err)
-				return NULL;
-		}
+		if (err)
+			return NULL;
 	}
 
 	return d40d;
@@ -1082,17 +1119,36 @@
 	if (d40d == NULL)
 		return;
 
-	d40_lcla_free_all(d40c, d40d);
+	if (d40d->cyclic) {
+		/*
+		 * If this was a paritially loaded list, we need to reloaded
+		 * it, and only when the list is completed.  We need to check
+		 * for done because the interrupt will hit for every link, and
+		 * not just the last one.
+		 */
+		if (d40d->lli_current < d40d->lli_len
+		    && !d40_tx_is_linked(d40c)
+		    && !d40_residue(d40c)) {
+			d40_lcla_free_all(d40c, d40d);
+			d40_desc_load(d40c, d40d);
+			(void) d40_start(d40c);
 
-	if (d40d->lli_current < d40d->lli_len) {
-		d40_desc_load(d40c, d40d);
-		/* Start dma job */
-		(void) d40_start(d40c);
-		return;
-	}
+			if (d40d->lli_current == d40d->lli_len)
+				d40d->lli_current = 0;
+		}
+	} else {
+		d40_lcla_free_all(d40c, d40d);
 
-	if (d40_queue_start(d40c) == NULL)
-		d40c->busy = false;
+		if (d40d->lli_current < d40d->lli_len) {
+			d40_desc_load(d40c, d40d);
+			/* Start dma job */
+			(void) d40_start(d40c);
+			return;
+		}
+
+		if (d40_queue_start(d40c) == NULL)
+			d40c->busy = false;
+	}
 
 	d40c->pending_tx++;
 	tasklet_schedule(&d40c->tasklet);
@@ -1111,11 +1167,11 @@
 
 	/* Get first active entry from list */
 	d40d = d40_first_active_get(d40c);
-
 	if (d40d == NULL)
 		goto err;
 
-	d40c->completed = d40d->txd.cookie;
+	if (!d40d->cyclic)
+		d40c->completed = d40d->txd.cookie;
 
 	/*
 	 * If terminating a channel pending_tx is set to zero.
@@ -1130,16 +1186,18 @@
 	callback = d40d->txd.callback;
 	callback_param = d40d->txd.callback_param;
 
-	if (async_tx_test_ack(&d40d->txd)) {
-		d40_pool_lli_free(d40d);
-		d40_desc_remove(d40d);
-		d40_desc_free(d40c, d40d);
-	} else {
-		if (!d40d->is_in_client_list) {
+	if (!d40d->cyclic) {
+		if (async_tx_test_ack(&d40d->txd)) {
+			d40_pool_lli_free(d40c, d40d);
 			d40_desc_remove(d40d);
-			d40_lcla_free_all(d40c, d40d);
-			list_add_tail(&d40d->node, &d40c->client);
-			d40d->is_in_client_list = true;
+			d40_desc_free(d40c, d40d);
+		} else {
+			if (!d40d->is_in_client_list) {
+				d40_desc_remove(d40d);
+				d40_lcla_free_all(d40c, d40d);
+				list_add_tail(&d40d->node, &d40c->client);
+				d40d->is_in_client_list = true;
+			}
 		}
 	}
 
@@ -1156,7 +1214,7 @@
 	return;
 
  err:
-	/* Rescue manouver if receiving double interrupts */
+	/* Rescue manoeuvre if receiving double interrupts */
 	if (d40c->pending_tx > 0)
 		d40c->pending_tx--;
 	spin_unlock_irqrestore(&d40c->lock, flags);
@@ -1216,9 +1274,8 @@
 		if (!il[row].is_error)
 			dma_tc_handle(d40c);
 		else
-			dev_err(base->dev,
-				"[%s] IRQ chan: %ld offset %d idx %d\n",
-				__func__, chan, il[row].offset, idx);
+			d40_err(base->dev, "IRQ chan: %ld offset %d idx %d\n",
+				chan, il[row].offset, idx);
 
 		spin_unlock(&d40c->lock);
 	}
@@ -1237,8 +1294,7 @@
 	bool is_log = conf->mode == STEDMA40_MODE_LOGICAL;
 
 	if (!conf->dir) {
-		dev_err(&d40c->chan.dev->device, "[%s] Invalid direction.\n",
-			__func__);
+		chan_err(d40c, "Invalid direction.\n");
 		res = -EINVAL;
 	}
 
@@ -1246,46 +1302,40 @@
 	    d40c->base->plat_data->dev_tx[conf->dst_dev_type] == 0 &&
 	    d40c->runtime_addr == 0) {
 
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Invalid TX channel address (%d)\n",
-			__func__, conf->dst_dev_type);
+		chan_err(d40c, "Invalid TX channel address (%d)\n",
+			 conf->dst_dev_type);
 		res = -EINVAL;
 	}
 
 	if (conf->src_dev_type != STEDMA40_DEV_SRC_MEMORY &&
 	    d40c->base->plat_data->dev_rx[conf->src_dev_type] == 0 &&
 	    d40c->runtime_addr == 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Invalid RX channel address (%d)\n",
-			__func__, conf->src_dev_type);
+		chan_err(d40c, "Invalid RX channel address (%d)\n",
+			conf->src_dev_type);
 		res = -EINVAL;
 	}
 
 	if (conf->dir == STEDMA40_MEM_TO_PERIPH &&
 	    dst_event_group == STEDMA40_DEV_DST_MEMORY) {
-		dev_err(&d40c->chan.dev->device, "[%s] Invalid dst\n",
-			__func__);
+		chan_err(d40c, "Invalid dst\n");
 		res = -EINVAL;
 	}
 
 	if (conf->dir == STEDMA40_PERIPH_TO_MEM &&
 	    src_event_group == STEDMA40_DEV_SRC_MEMORY) {
-		dev_err(&d40c->chan.dev->device, "[%s] Invalid src\n",
-			__func__);
+		chan_err(d40c, "Invalid src\n");
 		res = -EINVAL;
 	}
 
 	if (src_event_group == STEDMA40_DEV_SRC_MEMORY &&
 	    dst_event_group == STEDMA40_DEV_DST_MEMORY && is_log) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] No event line\n", __func__);
+		chan_err(d40c, "No event line\n");
 		res = -EINVAL;
 	}
 
 	if (conf->dir == STEDMA40_PERIPH_TO_PERIPH &&
 	    (src_event_group != dst_event_group)) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Invalid event group\n", __func__);
+		chan_err(d40c, "Invalid event group\n");
 		res = -EINVAL;
 	}
 
@@ -1294,9 +1344,7 @@
 		 * DMAC HW supports it. Will be added to this driver,
 		 * in case any dma client requires it.
 		 */
-		dev_err(&d40c->chan.dev->device,
-			"[%s] periph to periph not supported\n",
-			__func__);
+		chan_err(d40c, "periph to periph not supported\n");
 		res = -EINVAL;
 	}
 
@@ -1309,9 +1357,7 @@
 		 * src (burst x width) == dst (burst x width)
 		 */
 
-		dev_err(&d40c->chan.dev->device,
-			"[%s] src (burst x width) != dst (burst x width)\n",
-			__func__);
+		chan_err(d40c, "src (burst x width) != dst (burst x width)\n");
 		res = -EINVAL;
 	}
 
@@ -1514,8 +1560,7 @@
 		   dma_has_cap(DMA_SLAVE, cap)) {
 		d40c->dma_cfg = *d40c->base->plat_data->memcpy_conf_phy;
 	} else {
-		dev_err(&d40c->chan.dev->device, "[%s] No memcpy\n",
-			__func__);
+		chan_err(d40c, "No memcpy\n");
 		return -EINVAL;
 	}
 
@@ -1540,21 +1585,19 @@
 	/* Release client owned descriptors */
 	if (!list_empty(&d40c->client))
 		list_for_each_entry_safe(d, _d, &d40c->client, node) {
-			d40_pool_lli_free(d);
+			d40_pool_lli_free(d40c, d);
 			d40_desc_remove(d);
 			d40_desc_free(d40c, d);
 		}
 
 	if (phy == NULL) {
-		dev_err(&d40c->chan.dev->device, "[%s] phy == null\n",
-			__func__);
+		chan_err(d40c, "phy == null\n");
 		return -EINVAL;
 	}
 
 	if (phy->allocated_src == D40_ALLOC_FREE &&
 	    phy->allocated_dst == D40_ALLOC_FREE) {
-		dev_err(&d40c->chan.dev->device, "[%s] channel already free\n",
-			__func__);
+		chan_err(d40c, "channel already free\n");
 		return -EINVAL;
 	}
 
@@ -1566,19 +1609,17 @@
 		event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
 		is_src = true;
 	} else {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unknown direction\n", __func__);
+		chan_err(d40c, "Unknown direction\n");
 		return -EINVAL;
 	}
 
 	res = d40_channel_execute_command(d40c, D40_DMA_SUSPEND_REQ);
 	if (res) {
-		dev_err(&d40c->chan.dev->device, "[%s] suspend failed\n",
-			__func__);
+		chan_err(d40c, "suspend failed\n");
 		return res;
 	}
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	if (chan_is_logical(d40c)) {
 		/* Release logical channel, deactivate the event line */
 
 		d40_config_set_event(d40c, false);
@@ -1594,9 +1635,8 @@
 				res = d40_channel_execute_command(d40c,
 								  D40_DMA_RUN);
 				if (res) {
-					dev_err(&d40c->chan.dev->device,
-						"[%s] Executing RUN command\n",
-						__func__);
+					chan_err(d40c,
+						"Executing RUN command\n");
 					return res;
 				}
 			}
@@ -1609,8 +1649,7 @@
 	/* Release physical channel */
 	res = d40_channel_execute_command(d40c, D40_DMA_STOP);
 	if (res) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to stop channel\n", __func__);
+		chan_err(d40c, "Failed to stop channel\n");
 		return res;
 	}
 	d40c->phy_chan = NULL;
@@ -1622,6 +1661,7 @@
 
 static bool d40_is_paused(struct d40_chan *d40c)
 {
+	void __iomem *chanbase = chan_base(d40c);
 	bool is_paused = false;
 	unsigned long flags;
 	void __iomem *active_reg;
@@ -1630,7 +1670,7 @@
 
 	spin_lock_irqsave(&d40c->lock, flags);
 
-	if (d40c->log_num == D40_PHY_CHAN) {
+	if (chan_is_physical(d40c)) {
 		if (d40c->phy_chan->num % 2 == 0)
 			active_reg = d40c->base->virtbase + D40_DREG_ACTIVE;
 		else
@@ -1648,17 +1688,12 @@
 	if (d40c->dma_cfg.dir == STEDMA40_MEM_TO_PERIPH ||
 	    d40c->dma_cfg.dir == STEDMA40_MEM_TO_MEM) {
 		event = D40_TYPE_TO_EVENT(d40c->dma_cfg.dst_dev_type);
-		status = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-			       d40c->phy_chan->num * D40_DREG_PCDELTA +
-			       D40_CHAN_REG_SDLNK);
+		status = readl(chanbase + D40_CHAN_REG_SDLNK);
 	} else if (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_MEM) {
 		event = D40_TYPE_TO_EVENT(d40c->dma_cfg.src_dev_type);
-		status = readl(d40c->base->virtbase + D40_DREG_PCBASE +
-			       d40c->phy_chan->num * D40_DREG_PCDELTA +
-			       D40_CHAN_REG_SSLNK);
+		status = readl(chanbase + D40_CHAN_REG_SSLNK);
 	} else {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unknown direction\n", __func__);
+		chan_err(d40c, "Unknown direction\n");
 		goto _exit;
 	}
 
@@ -1688,114 +1723,184 @@
 	return bytes_left;
 }
 
-struct dma_async_tx_descriptor *stedma40_memcpy_sg(struct dma_chan *chan,
-						   struct scatterlist *sgl_dst,
-						   struct scatterlist *sgl_src,
-						   unsigned int sgl_len,
-						   unsigned long dma_flags)
+static int
+d40_prep_sg_log(struct d40_chan *chan, struct d40_desc *desc,
+		struct scatterlist *sg_src, struct scatterlist *sg_dst,
+		unsigned int sg_len, dma_addr_t src_dev_addr,
+		dma_addr_t dst_dev_addr)
 {
-	int res;
-	struct d40_desc *d40d;
-	struct d40_chan *d40c = container_of(chan, struct d40_chan,
-					     chan);
-	unsigned long flags;
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	struct stedma40_half_channel_info *src_info = &cfg->src_info;
+	struct stedma40_half_channel_info *dst_info = &cfg->dst_info;
+	int ret;
 
-	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unallocated channel.\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
+	ret = d40_log_sg_to_lli(sg_src, sg_len,
+				src_dev_addr,
+				desc->lli_log.src,
+				chan->log_def.lcsp1,
+				src_info->data_width,
+				dst_info->data_width);
 
-	spin_lock_irqsave(&d40c->lock, flags);
-	d40d = d40_desc_get(d40c);
+	ret = d40_log_sg_to_lli(sg_dst, sg_len,
+				dst_dev_addr,
+				desc->lli_log.dst,
+				chan->log_def.lcsp3,
+				dst_info->data_width,
+				src_info->data_width);
 
-	if (d40d == NULL)
+	return ret < 0 ? ret : 0;
+}
+
+static int
+d40_prep_sg_phy(struct d40_chan *chan, struct d40_desc *desc,
+		struct scatterlist *sg_src, struct scatterlist *sg_dst,
+		unsigned int sg_len, dma_addr_t src_dev_addr,
+		dma_addr_t dst_dev_addr)
+{
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	struct stedma40_half_channel_info *src_info = &cfg->src_info;
+	struct stedma40_half_channel_info *dst_info = &cfg->dst_info;
+	unsigned long flags = 0;
+	int ret;
+
+	if (desc->cyclic)
+		flags |= LLI_CYCLIC | LLI_TERM_INT;
+
+	ret = d40_phy_sg_to_lli(sg_src, sg_len, src_dev_addr,
+				desc->lli_phy.src,
+				virt_to_phys(desc->lli_phy.src),
+				chan->src_def_cfg,
+				src_info, dst_info, flags);
+
+	ret = d40_phy_sg_to_lli(sg_dst, sg_len, dst_dev_addr,
+				desc->lli_phy.dst,
+				virt_to_phys(desc->lli_phy.dst),
+				chan->dst_def_cfg,
+				dst_info, src_info, flags);
+
+	dma_sync_single_for_device(chan->base->dev, desc->lli_pool.dma_addr,
+				   desc->lli_pool.size, DMA_TO_DEVICE);
+
+	return ret < 0 ? ret : 0;
+}
+
+
+static struct d40_desc *
+d40_prep_desc(struct d40_chan *chan, struct scatterlist *sg,
+	      unsigned int sg_len, unsigned long dma_flags)
+{
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	struct d40_desc *desc;
+	int ret;
+
+	desc = d40_desc_get(chan);
+	if (!desc)
+		return NULL;
+
+	desc->lli_len = d40_sg_2_dmalen(sg, sg_len, cfg->src_info.data_width,
+					cfg->dst_info.data_width);
+	if (desc->lli_len < 0) {
+		chan_err(chan, "Unaligned size\n");
 		goto err;
+	}
 
-	d40d->lli_len = d40_sg_2_dmalen(sgl_dst, sgl_len,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
+	ret = d40_pool_lli_alloc(chan, desc, desc->lli_len);
+	if (ret < 0) {
+		chan_err(chan, "Could not allocate lli\n");
 		goto err;
 	}
 
-	d40d->lli_current = 0;
-	d40d->txd.flags = dma_flags;
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	desc->lli_current = 0;
+	desc->txd.flags = dma_flags;
+	desc->txd.tx_submit = d40_tx_submit;
 
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
+	dma_async_tx_descriptor_init(&desc->txd, &chan->chan);
 
-		(void) d40_log_sg_to_lli(sgl_src,
-					 sgl_len,
-					 d40d->lli_log.src,
-					 d40c->log_def.lcsp1,
-					 d40c->dma_cfg.src_info.data_width,
-					 d40c->dma_cfg.dst_info.data_width);
+	return desc;
 
-		(void) d40_log_sg_to_lli(sgl_dst,
-					 sgl_len,
-					 d40d->lli_log.dst,
-					 d40c->log_def.lcsp3,
-					 d40c->dma_cfg.dst_info.data_width,
-					 d40c->dma_cfg.src_info.data_width);
-	} else {
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
+err:
+	d40_desc_free(chan, desc);
+	return NULL;
+}
 
-		res = d40_phy_sg_to_lli(sgl_src,
-					sgl_len,
-					0,
-					d40d->lli_phy.src,
-					virt_to_phys(d40d->lli_phy.src),
-					d40c->src_def_cfg,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width,
-					d40c->dma_cfg.src_info.psize);
+static dma_addr_t
+d40_get_dev_addr(struct d40_chan *chan, enum dma_data_direction direction)
+{
+	struct stedma40_platform_data *plat = chan->base->plat_data;
+	struct stedma40_chan_cfg *cfg = &chan->dma_cfg;
+	dma_addr_t addr;
 
-		if (res < 0)
-			goto err;
+	if (chan->runtime_addr)
+		return chan->runtime_addr;
 
-		res = d40_phy_sg_to_lli(sgl_dst,
-					sgl_len,
-					0,
-					d40d->lli_phy.dst,
-					virt_to_phys(d40d->lli_phy.dst),
-					d40c->dst_def_cfg,
-					d40c->dma_cfg.dst_info.data_width,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.psize);
+	if (direction == DMA_FROM_DEVICE)
+		addr = plat->dev_rx[cfg->src_dev_type];
+	else if (direction == DMA_TO_DEVICE)
+		addr = plat->dev_tx[cfg->dst_dev_type];
 
-		if (res < 0)
-			goto err;
+	return addr;
+}
 
-		(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
-				      d40d->lli_pool.size, DMA_TO_DEVICE);
+static struct dma_async_tx_descriptor *
+d40_prep_sg(struct dma_chan *dchan, struct scatterlist *sg_src,
+	    struct scatterlist *sg_dst, unsigned int sg_len,
+	    enum dma_data_direction direction, unsigned long dma_flags)
+{
+	struct d40_chan *chan = container_of(dchan, struct d40_chan, chan);
+	dma_addr_t src_dev_addr = 0;
+	dma_addr_t dst_dev_addr = 0;
+	struct d40_desc *desc;
+	unsigned long flags;
+	int ret;
+
+	if (!chan->phy_chan) {
+		chan_err(chan, "Cannot prepare unallocated channel\n");
+		return NULL;
 	}
 
-	dma_async_tx_descriptor_init(&d40d->txd, chan);
 
-	d40d->txd.tx_submit = d40_tx_submit;
+	spin_lock_irqsave(&chan->lock, flags);
 
-	spin_unlock_irqrestore(&d40c->lock, flags);
+	desc = d40_prep_desc(chan, sg_src, sg_len, dma_flags);
+	if (desc == NULL)
+		goto err;
+
+	if (sg_next(&sg_src[sg_len - 1]) == sg_src)
+		desc->cyclic = true;
+
+	if (direction != DMA_NONE) {
+		dma_addr_t dev_addr = d40_get_dev_addr(chan, direction);
+
+		if (direction == DMA_FROM_DEVICE)
+			src_dev_addr = dev_addr;
+		else if (direction == DMA_TO_DEVICE)
+			dst_dev_addr = dev_addr;
+	}
+
+	if (chan_is_logical(chan))
+		ret = d40_prep_sg_log(chan, desc, sg_src, sg_dst,
+				      sg_len, src_dev_addr, dst_dev_addr);
+	else
+		ret = d40_prep_sg_phy(chan, desc, sg_src, sg_dst,
+				      sg_len, src_dev_addr, dst_dev_addr);
+
+	if (ret) {
+		chan_err(chan, "Failed to prepare %s sg job: %d\n",
+			 chan_is_logical(chan) ? "log" : "phy", ret);
+		goto err;
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return &desc->txd;
 
-	return &d40d->txd;
 err:
-	if (d40d)
-		d40_desc_free(d40c, d40d);
-	spin_unlock_irqrestore(&d40c->lock, flags);
+	if (desc)
+		d40_desc_free(chan, desc);
+	spin_unlock_irqrestore(&chan->lock, flags);
 	return NULL;
 }
-EXPORT_SYMBOL(stedma40_memcpy_sg);
 
 bool stedma40_filter(struct dma_chan *chan, void *data)
 {
@@ -1818,6 +1923,38 @@
 }
 EXPORT_SYMBOL(stedma40_filter);
 
+static void __d40_set_prio_rt(struct d40_chan *d40c, int dev_type, bool src)
+{
+	bool realtime = d40c->dma_cfg.realtime;
+	bool highprio = d40c->dma_cfg.high_priority;
+	u32 prioreg = highprio ? D40_DREG_PSEG1 : D40_DREG_PCEG1;
+	u32 rtreg = realtime ? D40_DREG_RSEG1 : D40_DREG_RCEG1;
+	u32 event = D40_TYPE_TO_EVENT(dev_type);
+	u32 group = D40_TYPE_TO_GROUP(dev_type);
+	u32 bit = 1 << event;
+
+	/* Destination event lines are stored in the upper halfword */
+	if (!src)
+		bit <<= 16;
+
+	writel(bit, d40c->base->virtbase + prioreg + group * 4);
+	writel(bit, d40c->base->virtbase + rtreg + group * 4);
+}
+
+static void d40_set_prio_realtime(struct d40_chan *d40c)
+{
+	if (d40c->base->rev < 3)
+		return;
+
+	if ((d40c->dma_cfg.dir ==  STEDMA40_PERIPH_TO_MEM) ||
+	    (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
+		__d40_set_prio_rt(d40c, d40c->dma_cfg.src_dev_type, true);
+
+	if ((d40c->dma_cfg.dir ==  STEDMA40_MEM_TO_PERIPH) ||
+	    (d40c->dma_cfg.dir == STEDMA40_PERIPH_TO_PERIPH))
+		__d40_set_prio_rt(d40c, d40c->dma_cfg.dst_dev_type, false);
+}
+
 /* DMA ENGINE functions */
 static int d40_alloc_chan_resources(struct dma_chan *chan)
 {
@@ -1834,9 +1971,7 @@
 	if (!d40c->configured) {
 		err = d40_config_memcpy(d40c);
 		if (err) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Failed to configure memcpy channel\n",
-				__func__);
+			chan_err(d40c, "Failed to configure memcpy channel\n");
 			goto fail;
 		}
 	}
@@ -1844,16 +1979,17 @@
 
 	err = d40_allocate_channel(d40c);
 	if (err) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to allocate channel\n", __func__);
+		chan_err(d40c, "Failed to allocate channel\n");
 		goto fail;
 	}
 
 	/* Fill in basic CFG register values */
 	d40_phy_cfg(&d40c->dma_cfg, &d40c->src_def_cfg,
-		    &d40c->dst_def_cfg, d40c->log_num != D40_PHY_CHAN);
+		    &d40c->dst_def_cfg, chan_is_logical(d40c));
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	d40_set_prio_realtime(d40c);
+
+	if (chan_is_logical(d40c)) {
 		d40_log_cfg(&d40c->dma_cfg,
 			    &d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
 
@@ -1886,8 +2022,7 @@
 	unsigned long flags;
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Cannot free unallocated channel\n", __func__);
+		chan_err(d40c, "Cannot free unallocated channel\n");
 		return;
 	}
 
@@ -1897,8 +2032,7 @@
 	err = d40_free_dma(d40c);
 
 	if (err)
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to free channel\n", __func__);
+		chan_err(d40c, "Failed to free channel\n");
 	spin_unlock_irqrestore(&d40c->lock, flags);
 }
 
@@ -1908,251 +2042,31 @@
 						       size_t size,
 						       unsigned long dma_flags)
 {
-	struct d40_desc *d40d;
-	struct d40_chan *d40c = container_of(chan, struct d40_chan,
-					     chan);
-	unsigned long flags;
-
-	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Channel is not allocated.\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
-
-	spin_lock_irqsave(&d40c->lock, flags);
-	d40d = d40_desc_get(d40c);
-
-	if (d40d == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Descriptor is NULL\n", __func__);
-		goto err;
-	}
-
-	d40d->txd.flags = dma_flags;
-	d40d->lli_len = d40_size_2_dmalen(size,
-					  d40c->dma_cfg.src_info.data_width,
-					  d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
-		goto err;
-	}
-
-
-	dma_async_tx_descriptor_init(&d40d->txd, chan);
-
-	d40d->txd.tx_submit = d40_tx_submit;
-
-	if (d40c->log_num != D40_PHY_CHAN) {
-
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
-		d40d->lli_current = 0;
-
-		if (d40_log_buf_to_lli(d40d->lli_log.src,
-				       src,
-				       size,
-				       d40c->log_def.lcsp1,
-				       d40c->dma_cfg.src_info.data_width,
-				       d40c->dma_cfg.dst_info.data_width,
-				       true) == NULL)
-			goto err;
-
-		if (d40_log_buf_to_lli(d40d->lli_log.dst,
-				       dst,
-				       size,
-				       d40c->log_def.lcsp3,
-				       d40c->dma_cfg.dst_info.data_width,
-				       d40c->dma_cfg.src_info.data_width,
-				       true) == NULL)
-			goto err;
-
-	} else {
-
-		if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
-			dev_err(&d40c->chan.dev->device,
-				"[%s] Out of memory\n", __func__);
-			goto err;
-		}
-
-		if (d40_phy_buf_to_lli(d40d->lli_phy.src,
-				       src,
-				       size,
-				       d40c->dma_cfg.src_info.psize,
-				       0,
-				       d40c->src_def_cfg,
-				       true,
-				       d40c->dma_cfg.src_info.data_width,
-				       d40c->dma_cfg.dst_info.data_width,
-				       false) == NULL)
-			goto err;
+	struct scatterlist dst_sg;
+	struct scatterlist src_sg;
 
-		if (d40_phy_buf_to_lli(d40d->lli_phy.dst,
-				       dst,
-				       size,
-				       d40c->dma_cfg.dst_info.psize,
-				       0,
-				       d40c->dst_def_cfg,
-				       true,
-				       d40c->dma_cfg.dst_info.data_width,
-				       d40c->dma_cfg.src_info.data_width,
-				       false) == NULL)
-			goto err;
+	sg_init_table(&dst_sg, 1);
+	sg_init_table(&src_sg, 1);
 
-		(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
-				      d40d->lli_pool.size, DMA_TO_DEVICE);
-	}
+	sg_dma_address(&dst_sg) = dst;
+	sg_dma_address(&src_sg) = src;
 
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return &d40d->txd;
+	sg_dma_len(&dst_sg) = size;
+	sg_dma_len(&src_sg) = size;
 
-err:
-	if (d40d)
-		d40_desc_free(d40c, d40d);
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return NULL;
+	return d40_prep_sg(chan, &src_sg, &dst_sg, 1, DMA_NONE, dma_flags);
 }
 
 static struct dma_async_tx_descriptor *
-d40_prep_sg(struct dma_chan *chan,
-	    struct scatterlist *dst_sg, unsigned int dst_nents,
-	    struct scatterlist *src_sg, unsigned int src_nents,
-	    unsigned long dma_flags)
+d40_prep_memcpy_sg(struct dma_chan *chan,
+		   struct scatterlist *dst_sg, unsigned int dst_nents,
+		   struct scatterlist *src_sg, unsigned int src_nents,
+		   unsigned long dma_flags)
 {
 	if (dst_nents != src_nents)
 		return NULL;
 
-	return stedma40_memcpy_sg(chan, dst_sg, src_sg, dst_nents, dma_flags);
-}
-
-static int d40_prep_slave_sg_log(struct d40_desc *d40d,
-				 struct d40_chan *d40c,
-				 struct scatterlist *sgl,
-				 unsigned int sg_len,
-				 enum dma_data_direction direction,
-				 unsigned long dma_flags)
-{
-	dma_addr_t dev_addr = 0;
-	int total_size;
-
-	d40d->lli_len = d40_sg_2_dmalen(sgl, sg_len,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
-		return -EINVAL;
-	}
-
-	if (d40_pool_lli_alloc(d40d, d40d->lli_len, true) < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Out of memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	d40d->lli_current = 0;
-
-	if (direction == DMA_FROM_DEVICE)
-		if (d40c->runtime_addr)
-			dev_addr = d40c->runtime_addr;
-		else
-			dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type];
-	else if (direction == DMA_TO_DEVICE)
-		if (d40c->runtime_addr)
-			dev_addr = d40c->runtime_addr;
-		else
-			dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type];
-
-	else
-		return -EINVAL;
-
-	total_size = d40_log_sg_to_dev(sgl, sg_len,
-				       &d40d->lli_log,
-				       &d40c->log_def,
-				       d40c->dma_cfg.src_info.data_width,
-				       d40c->dma_cfg.dst_info.data_width,
-				       direction,
-				       dev_addr);
-
-	if (total_size < 0)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int d40_prep_slave_sg_phy(struct d40_desc *d40d,
-				 struct d40_chan *d40c,
-				 struct scatterlist *sgl,
-				 unsigned int sgl_len,
-				 enum dma_data_direction direction,
-				 unsigned long dma_flags)
-{
-	dma_addr_t src_dev_addr;
-	dma_addr_t dst_dev_addr;
-	int res;
-
-	d40d->lli_len = d40_sg_2_dmalen(sgl, sgl_len,
-					d40c->dma_cfg.src_info.data_width,
-					d40c->dma_cfg.dst_info.data_width);
-	if (d40d->lli_len < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Unaligned size\n", __func__);
-		return -EINVAL;
-	}
-
-	if (d40_pool_lli_alloc(d40d, d40d->lli_len, false) < 0) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Out of memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	d40d->lli_current = 0;
-
-	if (direction == DMA_FROM_DEVICE) {
-		dst_dev_addr = 0;
-		if (d40c->runtime_addr)
-			src_dev_addr = d40c->runtime_addr;
-		else
-			src_dev_addr = d40c->base->plat_data->dev_rx[d40c->dma_cfg.src_dev_type];
-	} else if (direction == DMA_TO_DEVICE) {
-		if (d40c->runtime_addr)
-			dst_dev_addr = d40c->runtime_addr;
-		else
-			dst_dev_addr = d40c->base->plat_data->dev_tx[d40c->dma_cfg.dst_dev_type];
-		src_dev_addr = 0;
-	} else
-		return -EINVAL;
-
-	res = d40_phy_sg_to_lli(sgl,
-				sgl_len,
-				src_dev_addr,
-				d40d->lli_phy.src,
-				virt_to_phys(d40d->lli_phy.src),
-				d40c->src_def_cfg,
-				d40c->dma_cfg.src_info.data_width,
-				d40c->dma_cfg.dst_info.data_width,
-				d40c->dma_cfg.src_info.psize);
-	if (res < 0)
-		return res;
-
-	res = d40_phy_sg_to_lli(sgl,
-				sgl_len,
-				dst_dev_addr,
-				d40d->lli_phy.dst,
-				virt_to_phys(d40d->lli_phy.dst),
-				d40c->dst_def_cfg,
-				d40c->dma_cfg.dst_info.data_width,
-				d40c->dma_cfg.src_info.data_width,
-				d40c->dma_cfg.dst_info.psize);
-	if (res < 0)
-		return res;
-
-	(void) dma_map_single(d40c->base->dev, d40d->lli_phy.src,
-			      d40d->lli_pool.size, DMA_TO_DEVICE);
-	return 0;
+	return d40_prep_sg(chan, src_sg, dst_sg, src_nents, DMA_NONE, dma_flags);
 }
 
 static struct dma_async_tx_descriptor *d40_prep_slave_sg(struct dma_chan *chan,
@@ -2161,52 +2075,40 @@
 							 enum dma_data_direction direction,
 							 unsigned long dma_flags)
 {
-	struct d40_desc *d40d;
-	struct d40_chan *d40c = container_of(chan, struct d40_chan,
-					     chan);
-	unsigned long flags;
-	int err;
-
-	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Cannot prepare unallocated channel\n", __func__);
-		return ERR_PTR(-EINVAL);
-	}
+	if (direction != DMA_FROM_DEVICE && direction != DMA_TO_DEVICE)
+		return NULL;
 
-	spin_lock_irqsave(&d40c->lock, flags);
-	d40d = d40_desc_get(d40c);
+	return d40_prep_sg(chan, sgl, sgl, sg_len, direction, dma_flags);
+}
 
-	if (d40d == NULL)
-		goto err;
+static struct dma_async_tx_descriptor *
+dma40_prep_dma_cyclic(struct dma_chan *chan, dma_addr_t dma_addr,
+		     size_t buf_len, size_t period_len,
+		     enum dma_data_direction direction)
+{
+	unsigned int periods = buf_len / period_len;
+	struct dma_async_tx_descriptor *txd;
+	struct scatterlist *sg;
+	int i;
 
-	if (d40c->log_num != D40_PHY_CHAN)
-		err = d40_prep_slave_sg_log(d40d, d40c, sgl, sg_len,
-					    direction, dma_flags);
-	else
-		err = d40_prep_slave_sg_phy(d40d, d40c, sgl, sg_len,
-					    direction, dma_flags);
-	if (err) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Failed to prepare %s slave sg job: %d\n",
-			__func__,
-			d40c->log_num != D40_PHY_CHAN ? "log" : "phy", err);
-		goto err;
+	sg = kcalloc(periods + 1, sizeof(struct scatterlist), GFP_KERNEL);
+	for (i = 0; i < periods; i++) {
+		sg_dma_address(&sg[i]) = dma_addr;
+		sg_dma_len(&sg[i]) = period_len;
+		dma_addr += period_len;
 	}
 
-	d40d->txd.flags = dma_flags;
-
-	dma_async_tx_descriptor_init(&d40d->txd, chan);
+	sg[periods].offset = 0;
+	sg[periods].length = 0;
+	sg[periods].page_link =
+		((unsigned long)sg | 0x01) & ~0x02;
 
-	d40d->txd.tx_submit = d40_tx_submit;
+	txd = d40_prep_sg(chan, sg, sg, periods, direction,
+			  DMA_PREP_INTERRUPT);
 
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return &d40d->txd;
+	kfree(sg);
 
-err:
-	if (d40d)
-		d40_desc_free(d40c, d40d);
-	spin_unlock_irqrestore(&d40c->lock, flags);
-	return NULL;
+	return txd;
 }
 
 static enum dma_status d40_tx_status(struct dma_chan *chan,
@@ -2219,9 +2121,7 @@
 	int ret;
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Cannot read status of unallocated channel\n",
-			__func__);
+		chan_err(d40c, "Cannot read status of unallocated channel\n");
 		return -EINVAL;
 	}
 
@@ -2245,8 +2145,7 @@
 	unsigned long flags;
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Channel is not allocated!\n", __func__);
+		chan_err(d40c, "Channel is not allocated!\n");
 		return;
 	}
 
@@ -2339,7 +2238,7 @@
 		return;
 	}
 
-	if (d40c->log_num != D40_PHY_CHAN) {
+	if (chan_is_logical(d40c)) {
 		if (config_maxburst >= 16)
 			psize = STEDMA40_PSIZE_LOG_16;
 		else if (config_maxburst >= 8)
@@ -2372,7 +2271,7 @@
 	cfg->dst_info.flow_ctrl = STEDMA40_NO_FLOW_CTRL;
 
 	/* Fill in register values */
-	if (d40c->log_num != D40_PHY_CHAN)
+	if (chan_is_logical(d40c))
 		d40_log_cfg(cfg, &d40c->log_def.lcsp1, &d40c->log_def.lcsp3);
 	else
 		d40_phy_cfg(cfg, &d40c->src_def_cfg,
@@ -2393,25 +2292,20 @@
 static int d40_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd,
 		       unsigned long arg)
 {
-	unsigned long flags;
 	struct d40_chan *d40c = container_of(chan, struct d40_chan, chan);
 
 	if (d40c->phy_chan == NULL) {
-		dev_err(&d40c->chan.dev->device,
-			"[%s] Channel is not allocated!\n", __func__);
+		chan_err(d40c, "Channel is not allocated!\n");
 		return -EINVAL;
 	}
 
 	switch (cmd) {
 	case DMA_TERMINATE_ALL:
-		spin_lock_irqsave(&d40c->lock, flags);
-		d40_term_all(d40c);
-		spin_unlock_irqrestore(&d40c->lock, flags);
-		return 0;
+		return d40_terminate_all(d40c);
 	case DMA_PAUSE:
-		return d40_pause(chan);
+		return d40_pause(d40c);
 	case DMA_RESUME:
-		return d40_resume(chan);
+		return d40_resume(d40c);
 	case DMA_SLAVE_CONFIG:
 		d40_set_runtime_config(chan,
 			(struct dma_slave_config *) arg);
@@ -2456,6 +2350,35 @@
 	}
 }
 
+static void d40_ops_init(struct d40_base *base, struct dma_device *dev)
+{
+	if (dma_has_cap(DMA_SLAVE, dev->cap_mask))
+		dev->device_prep_slave_sg = d40_prep_slave_sg;
+
+	if (dma_has_cap(DMA_MEMCPY, dev->cap_mask)) {
+		dev->device_prep_dma_memcpy = d40_prep_memcpy;
+
+		/*
+		 * This controller can only access address at even
+		 * 32bit boundaries, i.e. 2^2
+		 */
+		dev->copy_align = 2;
+	}
+
+	if (dma_has_cap(DMA_SG, dev->cap_mask))
+		dev->device_prep_dma_sg = d40_prep_memcpy_sg;
+
+	if (dma_has_cap(DMA_CYCLIC, dev->cap_mask))
+		dev->device_prep_dma_cyclic = dma40_prep_dma_cyclic;
+
+	dev->device_alloc_chan_resources = d40_alloc_chan_resources;
+	dev->device_free_chan_resources = d40_free_chan_resources;
+	dev->device_issue_pending = d40_issue_pending;
+	dev->device_tx_status = d40_tx_status;
+	dev->device_control = d40_control;
+	dev->dev = base->dev;
+}
+
 static int __init d40_dmaengine_init(struct d40_base *base,
 				     int num_reserved_chans)
 {
@@ -2466,23 +2389,14 @@
 
 	dma_cap_zero(base->dma_slave.cap_mask);
 	dma_cap_set(DMA_SLAVE, base->dma_slave.cap_mask);
+	dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask);
 
-	base->dma_slave.device_alloc_chan_resources = d40_alloc_chan_resources;
-	base->dma_slave.device_free_chan_resources = d40_free_chan_resources;
-	base->dma_slave.device_prep_dma_memcpy = d40_prep_memcpy;
-	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
-	base->dma_slave.device_prep_slave_sg = d40_prep_slave_sg;
-	base->dma_slave.device_tx_status = d40_tx_status;
-	base->dma_slave.device_issue_pending = d40_issue_pending;
-	base->dma_slave.device_control = d40_control;
-	base->dma_slave.dev = base->dev;
+	d40_ops_init(base, &base->dma_slave);
 
 	err = dma_async_device_register(&base->dma_slave);
 
 	if (err) {
-		dev_err(base->dev,
-			"[%s] Failed to register slave channels\n",
-			__func__);
+		d40_err(base->dev, "Failed to register slave channels\n");
 		goto failure1;
 	}
 
@@ -2491,29 +2405,15 @@
 
 	dma_cap_zero(base->dma_memcpy.cap_mask);
 	dma_cap_set(DMA_MEMCPY, base->dma_memcpy.cap_mask);
-	dma_cap_set(DMA_SG, base->dma_slave.cap_mask);
+	dma_cap_set(DMA_SG, base->dma_memcpy.cap_mask);
 
-	base->dma_memcpy.device_alloc_chan_resources = d40_alloc_chan_resources;
-	base->dma_memcpy.device_free_chan_resources = d40_free_chan_resources;
-	base->dma_memcpy.device_prep_dma_memcpy = d40_prep_memcpy;
-	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
-	base->dma_memcpy.device_prep_slave_sg = d40_prep_slave_sg;
-	base->dma_memcpy.device_tx_status = d40_tx_status;
-	base->dma_memcpy.device_issue_pending = d40_issue_pending;
-	base->dma_memcpy.device_control = d40_control;
-	base->dma_memcpy.dev = base->dev;
-	/*
-	 * This controller can only access address at even
-	 * 32bit boundaries, i.e. 2^2
-	 */
-	base->dma_memcpy.copy_align = 2;
+	d40_ops_init(base, &base->dma_memcpy);
 
 	err = dma_async_device_register(&base->dma_memcpy);
 
 	if (err) {
-		dev_err(base->dev,
-			"[%s] Failed to regsiter memcpy only channels\n",
-			__func__);
+		d40_err(base->dev,
+			"Failed to regsiter memcpy only channels\n");
 		goto failure2;
 	}
 
@@ -2523,24 +2423,15 @@
 	dma_cap_zero(base->dma_both.cap_mask);
 	dma_cap_set(DMA_SLAVE, base->dma_both.cap_mask);
 	dma_cap_set(DMA_MEMCPY, base->dma_both.cap_mask);
-	dma_cap_set(DMA_SG, base->dma_slave.cap_mask);
+	dma_cap_set(DMA_SG, base->dma_both.cap_mask);
+	dma_cap_set(DMA_CYCLIC, base->dma_slave.cap_mask);
 
-	base->dma_both.device_alloc_chan_resources = d40_alloc_chan_resources;
-	base->dma_both.device_free_chan_resources = d40_free_chan_resources;
-	base->dma_both.device_prep_dma_memcpy = d40_prep_memcpy;
-	base->dma_slave.device_prep_dma_sg = d40_prep_sg;
-	base->dma_both.device_prep_slave_sg = d40_prep_slave_sg;
-	base->dma_both.device_tx_status = d40_tx_status;
-	base->dma_both.device_issue_pending = d40_issue_pending;
-	base->dma_both.device_control = d40_control;
-	base->dma_both.dev = base->dev;
-	base->dma_both.copy_align = 2;
+	d40_ops_init(base, &base->dma_both);
 	err = dma_async_device_register(&base->dma_both);
 
 	if (err) {
-		dev_err(base->dev,
-			"[%s] Failed to register logical and physical capable channels\n",
-			__func__);
+		d40_err(base->dev,
+			"Failed to register logical and physical capable channels\n");
 		goto failure3;
 	}
 	return 0;
@@ -2616,9 +2507,10 @@
 		{ .reg = D40_DREG_PERIPHID1, .val = 0x0000},
 		/*
 		 * D40_DREG_PERIPHID2 Depends on HW revision:
-		 *  MOP500/HREF ED has 0x0008,
+		 *  DB8500ed has 0x0008,
 		 *  ? has 0x0018,
-		 *  HREF V1 has 0x0028
+		 *  DB8500v1 has 0x0028
+		 *  DB8500v2 has 0x0038
 		 */
 		{ .reg = D40_DREG_PERIPHID3, .val = 0x0000},
 
@@ -2642,8 +2534,7 @@
 	clk = clk_get(&pdev->dev, NULL);
 
 	if (IS_ERR(clk)) {
-		dev_err(&pdev->dev, "[%s] No matching clock found\n",
-			__func__);
+		d40_err(&pdev->dev, "No matching clock found\n");
 		goto failure;
 	}
 
@@ -2666,9 +2557,8 @@
 	for (i = 0; i < ARRAY_SIZE(dma_id_regs); i++) {
 		if (dma_id_regs[i].val !=
 		    readl(virtbase + dma_id_regs[i].reg)) {
-			dev_err(&pdev->dev,
-				"[%s] Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n",
-				__func__,
+			d40_err(&pdev->dev,
+				"Unknown hardware! Expected 0x%x at 0x%x but got 0x%x\n",
 				dma_id_regs[i].val,
 				dma_id_regs[i].reg,
 				readl(virtbase + dma_id_regs[i].reg));
@@ -2681,9 +2571,8 @@
 
 	if ((val & D40_DREG_PERIPHID2_DESIGNER_MASK) !=
 	    D40_HW_DESIGNER) {
-		dev_err(&pdev->dev,
-			"[%s] Unknown designer! Got %x wanted %x\n",
-			__func__, val & D40_DREG_PERIPHID2_DESIGNER_MASK,
+		d40_err(&pdev->dev, "Unknown designer! Got %x wanted %x\n",
+			val & D40_DREG_PERIPHID2_DESIGNER_MASK,
 			D40_HW_DESIGNER);
 		goto failure;
 	}
@@ -2713,7 +2602,7 @@
 		       sizeof(struct d40_chan), GFP_KERNEL);
 
 	if (base == NULL) {
-		dev_err(&pdev->dev, "[%s] Out of memory\n", __func__);
+		d40_err(&pdev->dev, "Out of memory\n");
 		goto failure;
 	}
 
@@ -2860,6 +2749,7 @@
 
 static int __init d40_lcla_allocate(struct d40_base *base)
 {
+	struct d40_lcla_pool *pool = &base->lcla_pool;
 	unsigned long *page_list;
 	int i, j;
 	int ret = 0;
@@ -2885,9 +2775,8 @@
 						base->lcla_pool.pages);
 		if (!page_list[i]) {
 
-			dev_err(base->dev,
-				"[%s] Failed to allocate %d pages.\n",
-				__func__, base->lcla_pool.pages);
+			d40_err(base->dev, "Failed to allocate %d pages.\n",
+				base->lcla_pool.pages);
 
 			for (j = 0; j < i; j++)
 				free_pages(page_list[j], base->lcla_pool.pages);
@@ -2925,6 +2814,15 @@
 						 LCLA_ALIGNMENT);
 	}
 
+	pool->dma_addr = dma_map_single(base->dev, pool->base,
+					SZ_1K * base->num_phy_chans,
+					DMA_TO_DEVICE);
+	if (dma_mapping_error(base->dev, pool->dma_addr)) {
+		pool->dma_addr = 0;
+		ret = -ENOMEM;
+		goto failure;
+	}
+
 	writel(virt_to_phys(base->lcla_pool.base),
 	       base->virtbase + D40_DREG_LCLA);
 failure:
@@ -2957,9 +2855,7 @@
 	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "lcpa");
 	if (!res) {
 		ret = -ENOENT;
-		dev_err(&pdev->dev,
-			"[%s] No \"lcpa\" memory resource\n",
-			__func__);
+		d40_err(&pdev->dev, "No \"lcpa\" memory resource\n");
 		goto failure;
 	}
 	base->lcpa_size = resource_size(res);
@@ -2968,9 +2864,9 @@
 	if (request_mem_region(res->start, resource_size(res),
 			       D40_NAME " I/O lcpa") == NULL) {
 		ret = -EBUSY;
-		dev_err(&pdev->dev,
-			"[%s] Failed to request LCPA region 0x%x-0x%x\n",
-			__func__, res->start, res->end);
+		d40_err(&pdev->dev,
+			"Failed to request LCPA region 0x%x-0x%x\n",
+			res->start, res->end);
 		goto failure;
 	}
 
@@ -2986,16 +2882,13 @@
 	base->lcpa_base = ioremap(res->start, resource_size(res));
 	if (!base->lcpa_base) {
 		ret = -ENOMEM;
-		dev_err(&pdev->dev,
-			"[%s] Failed to ioremap LCPA region\n",
-			__func__);
+		d40_err(&pdev->dev, "Failed to ioremap LCPA region\n");
 		goto failure;
 	}
 
 	ret = d40_lcla_allocate(base);
 	if (ret) {
-		dev_err(&pdev->dev, "[%s] Failed to allocate LCLA area\n",
-			__func__);
+		d40_err(&pdev->dev, "Failed to allocate LCLA area\n");
 		goto failure;
 	}
 
@@ -3004,9 +2897,8 @@
 	base->irq = platform_get_irq(pdev, 0);
 
 	ret = request_irq(base->irq, d40_handle_interrupt, 0, D40_NAME, base);
-
 	if (ret) {
-		dev_err(&pdev->dev, "[%s] No IRQ defined\n", __func__);
+		d40_err(&pdev->dev, "No IRQ defined\n");
 		goto failure;
 	}
 
@@ -3025,6 +2917,12 @@
 			kmem_cache_destroy(base->desc_slab);
 		if (base->virtbase)
 			iounmap(base->virtbase);
+
+		if (base->lcla_pool.dma_addr)
+			dma_unmap_single(base->dev, base->lcla_pool.dma_addr,
+					 SZ_1K * base->num_phy_chans,
+					 DMA_TO_DEVICE);
+
 		if (!base->lcla_pool.base_unaligned && base->lcla_pool.base)
 			free_pages((unsigned long)base->lcla_pool.base,
 				   base->lcla_pool.pages);
@@ -3049,7 +2947,7 @@
 		kfree(base);
 	}
 
-	dev_err(&pdev->dev, "[%s] probe failed\n", __func__);
+	d40_err(&pdev->dev, "probe failed\n");
 	return ret;
 }
 
@@ -3060,7 +2958,7 @@
 	},
 };
 
-int __init stedma40_init(void)
+static int __init stedma40_init(void)
 {
 	return platform_driver_probe(&d40_driver, d40_probe);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/dma/ste_dma40_ll.c linux-libre-2.6.39-gnu/drivers/dma/ste_dma40_ll.c
--- linux-libre-2.6.38-gnu/drivers/dma/ste_dma40_ll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/ste_dma40_ll.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,13 +125,15 @@
 static int d40_phy_fill_lli(struct d40_phy_lli *lli,
 			    dma_addr_t data,
 			    u32 data_size,
-			    int psize,
 			    dma_addr_t next_lli,
 			    u32 reg_cfg,
-			    bool term_int,
-			    u32 data_width,
-			    bool is_device)
+			    struct stedma40_half_channel_info *info,
+			    unsigned int flags)
 {
+	bool addr_inc = flags & LLI_ADDR_INC;
+	bool term_int = flags & LLI_TERM_INT;
+	unsigned int data_width = info->data_width;
+	int psize = info->psize;
 	int num_elems;
 
 	if (psize == STEDMA40_PSIZE_PHY_1)
@@ -154,7 +156,7 @@
 	 * Distance to next element sized entry.
 	 * Usually the size of the element unless you want gaps.
 	 */
-	if (!is_device)
+	if (addr_inc)
 		lli->reg_elt |= (0x1 << data_width) <<
 			D40_SREG_ELEM_PHY_EIDX_POS;
 
@@ -198,47 +200,51 @@
 	return seg_max;
 }
 
-struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli,
-				       dma_addr_t addr,
-				       u32 size,
-				       int psize,
-				       dma_addr_t lli_phys,
-				       u32 reg_cfg,
-				       bool term_int,
-				       u32 data_width1,
-				       u32 data_width2,
-				       bool is_device)
+static struct d40_phy_lli *
+d40_phy_buf_to_lli(struct d40_phy_lli *lli, dma_addr_t addr, u32 size,
+		   dma_addr_t lli_phys, dma_addr_t first_phys, u32 reg_cfg,
+		   struct stedma40_half_channel_info *info,
+		   struct stedma40_half_channel_info *otherinfo,
+		   unsigned long flags)
 {
+	bool lastlink = flags & LLI_LAST_LINK;
+	bool addr_inc = flags & LLI_ADDR_INC;
+	bool term_int = flags & LLI_TERM_INT;
+	bool cyclic = flags & LLI_CYCLIC;
 	int err;
 	dma_addr_t next = lli_phys;
 	int size_rest = size;
 	int size_seg = 0;
 
+	/*
+	 * This piece may be split up based on d40_seg_size(); we only want the
+	 * term int on the last part.
+	 */
+	if (term_int)
+		flags &= ~LLI_TERM_INT;
+
 	do {
-		size_seg = d40_seg_size(size_rest, data_width1, data_width2);
+		size_seg = d40_seg_size(size_rest, info->data_width,
+					otherinfo->data_width);
 		size_rest -= size_seg;
 
-		if (term_int && size_rest == 0)
-			next = 0;
+		if (size_rest == 0 && term_int)
+			flags |= LLI_TERM_INT;
+
+		if (size_rest == 0 && lastlink)
+			next = cyclic ? first_phys : 0;
 		else
 			next = ALIGN(next + sizeof(struct d40_phy_lli),
 				     D40_LLI_ALIGN);
 
-		err = d40_phy_fill_lli(lli,
-				       addr,
-				       size_seg,
-				       psize,
-				       next,
-				       reg_cfg,
-				       !next,
-				       data_width1,
-				       is_device);
+		err = d40_phy_fill_lli(lli, addr, size_seg, next,
+				       reg_cfg, info, flags);
 
 		if (err)
 			goto err;
 
 		lli++;
-		if (!is_device)
+		if (addr_inc)
 			addr += size_seg;
 	} while (size_rest);
 
@@ -254,39 +260,35 @@
 		      struct d40_phy_lli *lli_sg,
 		      dma_addr_t lli_phys,
 		      u32 reg_cfg,
-		      u32 data_width1,
-		      u32 data_width2,
-		      int psize)
+		      struct stedma40_half_channel_info *info,
+		      struct stedma40_half_channel_info *otherinfo,
+		      unsigned long flags)
 {
 	int total_size = 0;
 	int i;
 	struct scatterlist *current_sg = sg;
-	dma_addr_t dst;
 	struct d40_phy_lli *lli = lli_sg;
 	dma_addr_t l_phys = lli_phys;
 
+	if (!target)
+		flags |= LLI_ADDR_INC;
+
 	for_each_sg(sg, current_sg, sg_len, i) {
+		dma_addr_t sg_addr = sg_dma_address(current_sg);
+		unsigned int len = sg_dma_len(current_sg);
+		dma_addr_t dst = target ?: sg_addr;
 
 		total_size += sg_dma_len(current_sg);
 
-		if (target)
-			dst = target;
-		else
-			dst = sg_phys(current_sg);
+		if (i == sg_len - 1)
+			flags |= LLI_TERM_INT | LLI_LAST_LINK;
 
 		l_phys = ALIGN(lli_phys + (lli - lli_sg) *
 			       sizeof(struct d40_phy_lli), D40_LLI_ALIGN);
 
-		lli = d40_phy_buf_to_lli(lli,
-					 dst,
-					 sg_dma_len(current_sg),
-					 psize,
-					 l_phys,
-					 reg_cfg,
-					 sg_len - 1 == i,
-					 data_width1,
-					 data_width2,
-					 target == dst);
+		lli = d40_phy_buf_to_lli(lli, dst, len, l_phys, lli_phys,
+					 reg_cfg, info, otherinfo, flags);
+
 		if (lli == NULL)
 			return -EINVAL;
 	}
@@ -295,45 +297,22 @@
 }
 
 
-void d40_phy_lli_write(void __iomem *virtbase,
-		       u32 phy_chan_num,
-		       struct d40_phy_lli *lli_dst,
-		       struct d40_phy_lli *lli_src)
-{
-
-	writel(lli_src->reg_cfg, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSCFG);
-	writel(lli_src->reg_elt, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSELT);
-	writel(lli_src->reg_ptr, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSPTR);
-	writel(lli_src->reg_lnk, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SSLNK);
-
-	writel(lli_dst->reg_cfg, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDCFG);
-	writel(lli_dst->reg_elt, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDELT);
-	writel(lli_dst->reg_ptr, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDPTR);
-	writel(lli_dst->reg_lnk, virtbase + D40_DREG_PCBASE +
-	       phy_chan_num * D40_DREG_PCDELTA + D40_CHAN_REG_SDLNK);
-
-}
-
 /* DMA logical lli operations */
 
 static void d40_log_lli_link(struct d40_log_lli *lli_dst,
 			     struct d40_log_lli *lli_src,
-			     int next)
+			     int next, unsigned int flags)
 {
+	bool interrupt = flags & LLI_TERM_INT;
 	u32 slos = 0;
 	u32 dlos = 0;
 
 	if (next != -EINVAL) {
 		slos = next * 2;
 		dlos = next * 2 + 1;
-	} else {
+	}
+
+	if (interrupt) {
 		lli_dst->lcsp13 |= D40_MEM_LCSP1_SCFG_TIM_MASK;
 		lli_dst->lcsp13 |= D40_MEM_LCSP3_DTCP_MASK;
 	}
@@ -348,9 +327,9 @@
 void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
 			   struct d40_log_lli *lli_dst,
 			   struct d40_log_lli *lli_src,
-			   int next)
+			   int next, unsigned int flags)
 {
-	d40_log_lli_link(lli_dst, lli_src, next);
+	d40_log_lli_link(lli_dst, lli_src, next, flags);
 
 	writel(lli_src->lcsp02, &lcpa[0].lcsp0);
 	writel(lli_src->lcsp13, &lcpa[0].lcsp1);
@@ -361,9 +340,9 @@
 void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
 			   struct d40_log_lli *lli_dst,
 			   struct d40_log_lli *lli_src,
-			   int next)
+			   int next, unsigned int flags)
 {
-	d40_log_lli_link(lli_dst, lli_src, next);
+	d40_log_lli_link(lli_dst, lli_src, next, flags);
 
 	writel(lli_src->lcsp02, &lcla[0].lcsp02);
 	writel(lli_src->lcsp13, &lcla[0].lcsp13);
@@ -375,8 +354,10 @@
 			     dma_addr_t data, u32 data_size,
 			     u32 reg_cfg,
 			     u32 data_width,
-			     bool addr_inc)
+			     unsigned int flags)
 {
+	bool addr_inc = flags & LLI_ADDR_INC;
+
 	lli->lcsp13 = reg_cfg;
 
 	/* The number of elements to transfer */
@@ -395,67 +376,15 @@
 
 }
 
-int d40_log_sg_to_dev(struct scatterlist *sg,
-		      int sg_len,
-		      struct d40_log_lli_bidir *lli,
-		      struct d40_def_lcsp *lcsp,
-		      u32 src_data_width,
-		      u32 dst_data_width,
-		      enum dma_data_direction direction,
-		      dma_addr_t dev_addr)
-{
-	int total_size = 0;
-	struct scatterlist *current_sg = sg;
-	int i;
-	struct d40_log_lli *lli_src = lli->src;
-	struct d40_log_lli *lli_dst = lli->dst;
-
-	for_each_sg(sg, current_sg, sg_len, i) {
-		total_size += sg_dma_len(current_sg);
-
-		if (direction == DMA_TO_DEVICE) {
-			lli_src =
-				d40_log_buf_to_lli(lli_src,
-						   sg_phys(current_sg),
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp1, src_data_width,
-						   dst_data_width,
-						   true);
-			lli_dst =
-				d40_log_buf_to_lli(lli_dst,
-						   dev_addr,
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp3, dst_data_width,
-						   src_data_width,
-						   false);
-		} else {
-			lli_dst =
-				d40_log_buf_to_lli(lli_dst,
-						   sg_phys(current_sg),
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp3, dst_data_width,
-						   src_data_width,
-						   true);
-			lli_src =
-				d40_log_buf_to_lli(lli_src,
-						   dev_addr,
-						   sg_dma_len(current_sg),
-						   lcsp->lcsp1, src_data_width,
-						   dst_data_width,
-						   false);
-		}
-	}
-	return total_size;
-}
-
-struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
+static struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
 				       dma_addr_t addr,
 				       int size,
 				       u32 lcsp13, /* src or dst*/
 				       u32 data_width1,
 				       u32 data_width2,
-				       bool addr_inc)
+				       unsigned int flags)
 {
+	bool addr_inc = flags & LLI_ADDR_INC;
 	struct d40_log_lli *lli = lli_sg;
 	int size_rest = size;
 	int size_seg = 0;
@@ -468,7 +397,7 @@
 				 addr,
 				 size_seg,
 				 lcsp13, data_width1,
-				 addr_inc);
+				 flags);
 		if (addr_inc)
 			addr += size_seg;
 		lli++;
@@ -479,6 +408,7 @@
 
 int d40_log_sg_to_lli(struct scatterlist *sg,
 		      int sg_len,
+		      dma_addr_t dev_addr,
 		      struct d40_log_lli *lli_sg,
 		      u32 lcsp13, /* src or dst*/
 		      u32 data_width1, u32 data_width2)
@@ -487,14 +417,24 @@
 	struct scatterlist *current_sg = sg;
 	int i;
 	struct d40_log_lli *lli = lli_sg;
+	unsigned long flags = 0;
+
+	if (!dev_addr)
+		flags |= LLI_ADDR_INC;
 
 	for_each_sg(sg, current_sg, sg_len, i) {
+		dma_addr_t sg_addr = sg_dma_address(current_sg);
+		unsigned int len = sg_dma_len(current_sg);
+		dma_addr_t addr = dev_addr ?: sg_addr;
+
 		total_size += sg_dma_len(current_sg);
-		lli = d40_log_buf_to_lli(lli,
-					 sg_phys(current_sg),
-					 sg_dma_len(current_sg),
+
+		lli = d40_log_buf_to_lli(lli, addr, len,
 					 lcsp13,
-					 data_width1, data_width2, true);
+					 data_width1,
+					 data_width2,
+					 flags);
 	}
+
 	return total_size;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/dma/ste_dma40_ll.h linux-libre-2.6.39-gnu/drivers/dma/ste_dma40_ll.h
--- linux-libre-2.6.38-gnu/drivers/dma/ste_dma40_ll.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/ste_dma40_ll.h	2011-05-19 00:06:34.000000000 -0400
@@ -163,6 +163,22 @@
 #define D40_DREG_LCEIS1		0x0B4
 #define D40_DREG_LCEIS2		0x0B8
 #define D40_DREG_LCEIS3		0x0BC
+#define D40_DREG_PSEG1		0x110
+#define D40_DREG_PSEG2		0x114
+#define D40_DREG_PSEG3		0x118
+#define D40_DREG_PSEG4		0x11C
+#define D40_DREG_PCEG1		0x120
+#define D40_DREG_PCEG2		0x124
+#define D40_DREG_PCEG3		0x128
+#define D40_DREG_PCEG4		0x12C
+#define D40_DREG_RSEG1		0x130
+#define D40_DREG_RSEG2		0x134
+#define D40_DREG_RSEG3		0x138
+#define D40_DREG_RSEG4		0x13C
+#define D40_DREG_RCEG1		0x140
+#define D40_DREG_RCEG2		0x144
+#define D40_DREG_RCEG3		0x148
+#define D40_DREG_RCEG4		0x14C
 #define D40_DREG_STFU		0xFC8
 #define D40_DREG_ICFG		0xFCC
 #define D40_DREG_PERIPHID0	0xFE0
@@ -277,6 +293,13 @@
 
 /* Physical channels */
 
+enum d40_lli_flags {
+	LLI_ADDR_INC	= 1 << 0,
+	LLI_TERM_INT	= 1 << 1,
+	LLI_CYCLIC	= 1 << 2,
+	LLI_LAST_LINK	= 1 << 3,
+};
+
 void d40_phy_cfg(struct stedma40_chan_cfg *cfg,
 		 u32 *src_cfg,
 		 u32 *dst_cfg,
@@ -292,46 +315,15 @@
 		      struct d40_phy_lli *lli,
 		      dma_addr_t lli_phys,
 		      u32 reg_cfg,
-		      u32 data_width1,
-		      u32 data_width2,
-		      int psize);
-
-struct d40_phy_lli *d40_phy_buf_to_lli(struct d40_phy_lli *lli,
-				       dma_addr_t data,
-				       u32 data_size,
-				       int psize,
-				       dma_addr_t next_lli,
-				       u32 reg_cfg,
-				       bool term_int,
-				       u32 data_width1,
-				       u32 data_width2,
-				       bool is_device);
-
-void d40_phy_lli_write(void __iomem *virtbase,
-		       u32 phy_chan_num,
-		       struct d40_phy_lli *lli_dst,
-		       struct d40_phy_lli *lli_src);
+		      struct stedma40_half_channel_info *info,
+		      struct stedma40_half_channel_info *otherinfo,
+		      unsigned long flags);
 
 /* Logical channels */
 
-struct d40_log_lli *d40_log_buf_to_lli(struct d40_log_lli *lli_sg,
-				       dma_addr_t addr,
-				       int size,
-				       u32 lcsp13, /* src or dst*/
-				       u32 data_width1, u32 data_width2,
-				       bool addr_inc);
-
-int d40_log_sg_to_dev(struct scatterlist *sg,
-		      int sg_len,
-		      struct d40_log_lli_bidir *lli,
-		      struct d40_def_lcsp *lcsp,
-		      u32 src_data_width,
-		      u32 dst_data_width,
-		      enum dma_data_direction direction,
-		      dma_addr_t dev_addr);
-
 int d40_log_sg_to_lli(struct scatterlist *sg,
 		      int sg_len,
+		      dma_addr_t dev_addr,
 		      struct d40_log_lli *lli_sg,
 		      u32 lcsp13, /* src or dst*/
 		      u32 data_width1, u32 data_width2);
@@ -339,11 +331,11 @@
 void d40_log_lli_lcpa_write(struct d40_log_lli_full *lcpa,
 			    struct d40_log_lli *lli_dst,
 			    struct d40_log_lli *lli_src,
-			    int next);
+			    int next, unsigned int flags);
 
 void d40_log_lli_lcla_write(struct d40_log_lli *lcla,
 			    struct d40_log_lli *lli_dst,
 			    struct d40_log_lli *lli_src,
-			    int next);
+			    int next, unsigned int flags);
 
 #endif /* STE_DMA40_LLI_H */
diff -druN linux-libre-2.6.38-gnu/drivers/dma/timb_dma.c linux-libre-2.6.39-gnu/drivers/dma/timb_dma.c
--- linux-libre-2.6.38-gnu/drivers/dma/timb_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/dma/timb_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/io.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/slab.h>
 
 #include <linux/timb_dma.h>
@@ -629,7 +630,7 @@
 		desc_node)
 		list_move(&td_desc->desc_node, &td_chan->free_list);
 
-	/* now tear down the runnning */
+	/* now tear down the running */
 	__td_finish(td_chan);
 	spin_unlock_bh(&td_chan->lock);
 
@@ -684,7 +685,7 @@
 
 static int __devinit td_probe(struct platform_device *pdev)
 {
-	struct timb_dma_platform_data *pdata = pdev->dev.platform_data;
+	struct timb_dma_platform_data *pdata = mfd_get_data(pdev);
 	struct timb_dma *td;
 	struct resource *iomem;
 	int irq;
diff -druN linux-libre-2.6.38-gnu/drivers/edac/amd64_edac.c linux-libre-2.6.39-gnu/drivers/edac/amd64_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/amd64_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/amd64_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,59 +25,12 @@
 static struct ecc_settings **ecc_stngs;
 
 /*
- * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and
- * later.
- */
-static int ddr2_dbam_revCG[] = {
-			   [0]		= 32,
-			   [1]		= 64,
-			   [2]		= 128,
-			   [3]		= 256,
-			   [4]		= 512,
-			   [5]		= 1024,
-			   [6]		= 2048,
-};
-
-static int ddr2_dbam_revD[] = {
-			   [0]		= 32,
-			   [1]		= 64,
-			   [2 ... 3]	= 128,
-			   [4]		= 256,
-			   [5]		= 512,
-			   [6]		= 256,
-			   [7]		= 512,
-			   [8 ... 9]	= 1024,
-			   [10]		= 2048,
-};
-
-static int ddr2_dbam[] = { [0]		= 128,
-			   [1]		= 256,
-			   [2 ... 4]	= 512,
-			   [5 ... 6]	= 1024,
-			   [7 ... 8]	= 2048,
-			   [9 ... 10]	= 4096,
-			   [11]		= 8192,
-};
-
-static int ddr3_dbam[] = { [0]		= -1,
-			   [1]		= 256,
-			   [2]		= 512,
-			   [3 ... 4]	= -1,
-			   [5 ... 6]	= 1024,
-			   [7 ... 8]	= 2048,
-			   [9 ... 10]	= 4096,
-			   [11]		= 8192,
-};
-
-/*
  * 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 {
        u32 scrubval;           /* bit pattern for scrub rate */
        u32 bandwidth;          /* bandwidth consumed (bytes/sec) */
@@ -107,6 +60,79 @@
 	{ 0x00, 0UL},        /* scrubbing off */
 };
 
+static int __amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
+				      u32 *val, const char *func)
+{
+	int err = 0;
+
+	err = pci_read_config_dword(pdev, offset, val);
+	if (err)
+		amd64_warn("%s: error reading F%dx%03x.\n",
+			   func, PCI_FUNC(pdev->devfn), offset);
+
+	return err;
+}
+
+int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
+				u32 val, const char *func)
+{
+	int err = 0;
+
+	err = pci_write_config_dword(pdev, offset, val);
+	if (err)
+		amd64_warn("%s: error writing to F%dx%03x.\n",
+			   func, PCI_FUNC(pdev->devfn), offset);
+
+	return err;
+}
+
+/*
+ *
+ * Depending on the family, F2 DCT reads need special handling:
+ *
+ * K8: has a single DCT only
+ *
+ * F10h: each DCT has its own set of regs
+ *	DCT0 -> F2x040..
+ *	DCT1 -> F2x140..
+ *
+ * F15h: we select which DCT we access using F1x10C[DctCfgSel]
+ *
+ */
+static int k8_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
+			       const char *func)
+{
+	if (addr >= 0x100)
+		return -EINVAL;
+
+	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
+}
+
+static int f10_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
+				 const char *func)
+{
+	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
+}
+
+static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val,
+				 const char *func)
+{
+	u32 reg = 0;
+	u8 dct  = 0;
+
+	if (addr >= 0x140 && addr <= 0x1a0) {
+		dct   = 1;
+		addr -= 0x100;
+	}
+
+	amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, &reg);
+	reg &= 0xfffffffe;
+	reg |= dct;
+	amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg);
+
+	return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func);
+}
+
 /*
  * 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
@@ -156,7 +182,7 @@
 
 	scrubval = scrubrates[i].scrubval;
 
-	pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F);
+	pci_write_bits32(ctl, SCRCTRL, scrubval, 0x001F);
 
 	if (scrubval)
 		return scrubrates[i].bandwidth;
@@ -167,8 +193,12 @@
 static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
+	u32 min_scrubrate = 0x5;
 
-	return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate);
+	if (boot_cpu_data.x86 == 0xf)
+		min_scrubrate = 0x0;
+
+	return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate);
 }
 
 static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
@@ -177,12 +207,10 @@
 	u32 scrubval = 0;
 	int i, retval = -EINVAL;
 
-	amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval);
+	amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval);
 
 	scrubval = scrubval & 0x001F;
 
-	amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval);
-
 	for (i = 0; i < ARRAY_SIZE(scrubrates); i++) {
 		if (scrubrates[i].scrubval == scrubval) {
 			retval = scrubrates[i].bandwidth;
@@ -192,63 +220,14 @@
 	return retval;
 }
 
-/* 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)
-{
-	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F)
-		return csrow;
-	else
-		return csrow >> 1;
-}
-
-/* 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
+ * returns true if the SysAddr given by sys_addr matches the
+ * DRAM base/limit associated with node_id
  */
-static int amd64_base_limit_match(struct amd64_pvt *pvt,
-					u64 sys_addr, int node_id)
+static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr,
+				   unsigned nid)
 {
-	u64 base, limit, addr;
-
-	amd64_get_base_and_limit(pvt, node_id, &base, &limit);
+	u64 addr;
 
 	/* 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.
@@ -258,7 +237,8 @@
 	 */
 	addr = sys_addr & 0x000000ffffffffffull;
 
-	return (addr >= base) && (addr <= limit);
+	return ((addr >= get_dram_base(pvt, nid)) &&
+		(addr <= get_dram_limit(pvt, nid)));
 }
 
 /*
@@ -271,7 +251,7 @@
 						u64 sys_addr)
 {
 	struct amd64_pvt *pvt;
-	int node_id;
+	unsigned node_id;
 	u32 intlv_en, bits;
 
 	/*
@@ -285,10 +265,10 @@
 	 * registers.  Therefore we arbitrarily choose to read it from the
 	 * register for node 0.
 	 */
-	intlv_en = pvt->dram_IntlvEn[0];
+	intlv_en = dram_intlv_en(pvt, 0);
 
 	if (intlv_en == 0) {
-		for (node_id = 0; node_id < DRAM_REG_COUNT; node_id++) {
+		for (node_id = 0; node_id < DRAM_RANGES; node_id++) {
 			if (amd64_base_limit_match(pvt, sys_addr, node_id))
 				goto found;
 		}
@@ -305,10 +285,10 @@
 	bits = (((u32) sys_addr) >> 12) & intlv_en;
 
 	for (node_id = 0; ; ) {
-		if ((pvt->dram_IntlvSel[node_id] & intlv_en) == bits)
+		if ((dram_intlv_sel(pvt, node_id) & intlv_en) == bits)
 			break;	/* intlv_sel field matches */
 
-		if (++node_id >= DRAM_REG_COUNT)
+		if (++node_id >= DRAM_RANGES)
 			goto err_no_match;
 	}
 
@@ -321,7 +301,7 @@
 	}
 
 found:
-	return edac_mc_find(node_id);
+	return edac_mc_find((int)node_id);
 
 err_no_match:
 	debugf2("sys_addr 0x%lx doesn't match any node\n",
@@ -331,37 +311,50 @@
 }
 
 /*
- * 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.
+ * compute the CS base address of the @csrow on the DRAM controller @dct.
+ * For details see F2x[5C:40] in the processor's BKDG
  */
-static u64 mask_from_dct_mask(struct amd64_pvt *pvt, int csrow)
+static void get_cs_base_and_mask(struct amd64_pvt *pvt, int csrow, u8 dct,
+				 u64 *base, u64 *mask)
 {
-	u64 dcsm_bits, other_bits;
-	u64 mask;
+	u64 csbase, csmask, base_bits, mask_bits;
+	u8 addr_shift;
 
-	/* Extract bits from DRAM CS Mask. */
-	dcsm_bits = amd64_get_dct_mask(pvt, 0, csrow) & pvt->dcsm_mask;
+	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) {
+		csbase		= pvt->csels[dct].csbases[csrow];
+		csmask		= pvt->csels[dct].csmasks[csrow];
+		base_bits	= GENMASK(21, 31) | GENMASK(9, 15);
+		mask_bits	= GENMASK(21, 29) | GENMASK(9, 15);
+		addr_shift	= 4;
+	} else {
+		csbase		= pvt->csels[dct].csbases[csrow];
+		csmask		= pvt->csels[dct].csmasks[csrow >> 1];
+		addr_shift	= 8;
 
-	other_bits = pvt->dcsm_mask;
-	other_bits = ~(other_bits << pvt->dcs_shift);
+		if (boot_cpu_data.x86 == 0x15)
+			base_bits = mask_bits = GENMASK(19,30) | GENMASK(5,13);
+		else
+			base_bits = mask_bits = GENMASK(19,28) | GENMASK(5,13);
+	}
 
-	/*
-	 * 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;
+	*base  = (csbase & base_bits) << addr_shift;
 
-	return mask;
+	*mask  = ~0ULL;
+	/* poke holes for the csmask */
+	*mask &= ~(mask_bits << addr_shift);
+	/* OR them in */
+	*mask |= (csmask & mask_bits) << addr_shift;
 }
 
+#define for_each_chip_select(i, dct, pvt) \
+	for (i = 0; i < pvt->csels[dct].b_cnt; i++)
+
+#define chip_select_base(i, dct, pvt) \
+	pvt->csels[dct].csbases[i]
+
+#define for_each_chip_select_mask(i, dct, pvt) \
+	for (i = 0; i < pvt->csels[dct].m_cnt; i++)
+
 /*
  * @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).
@@ -374,19 +367,13 @@
 
 	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 < pvt->cs_count; csrow++) {
-
-		/* This DRAM chip select is disabled on this node */
-		if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0)
+	for_each_chip_select(csrow, 0, pvt) {
+		if (!csrow_enabled(csrow, 0, pvt))
 			continue;
 
-		base = base_from_dct_base(pvt, csrow);
-		mask = ~mask_from_dct_mask(pvt, csrow);
+		get_cs_base_and_mask(pvt, csrow, 0, &base, &mask);
+
+		mask = ~mask;
 
 		if ((input_addr & mask) == (base & mask)) {
 			debugf2("InputAddr 0x%lx matches csrow %d (node %d)\n",
@@ -396,7 +383,6 @@
 			return csrow;
 		}
 	}
-
 	debugf2("no matching csrow for InputAddr 0x%lx (MC node %d)\n",
 		(unsigned long)input_addr, pvt->mc_node_id);
 
@@ -404,19 +390,6 @@
 }
 
 /*
- * 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
@@ -445,14 +418,13 @@
 		return 1;
 	}
 
-	/* only valid for Fam10h */
-	if (boot_cpu_data.x86 == 0x10 &&
-	    (pvt->dhar & F10_DRAM_MEM_HOIST_VALID) == 0) {
+	/* valid for Fam10h and above */
+	if (boot_cpu_data.x86 >= 0x10 && !dhar_mem_hoist_valid(pvt)) {
 		debugf1("  Dram Memory Hoisting is DISABLED on this system\n");
 		return 1;
 	}
 
-	if ((pvt->dhar & DHAR_VALID) == 0) {
+	if (!dhar_valid(pvt)) {
 		debugf1("  Dram Memory Hoisting is DISABLED on this node %d\n",
 			pvt->mc_node_id);
 		return 1;
@@ -476,15 +448,15 @@
 	 * addresses in the hole so that they start at 0x100000000.
 	 */
 
-	base = dhar_base(pvt->dhar);
+	base = dhar_base(pvt);
 
 	*hole_base = base;
 	*hole_size = (0x1ull << 32) - base;
 
 	if (boot_cpu_data.x86 > 0xf)
-		*hole_offset = f10_dhar_offset(pvt->dhar);
+		*hole_offset = f10_dhar_offset(pvt);
 	else
-		*hole_offset = k8_dhar_offset(pvt->dhar);
+		*hole_offset = k8_dhar_offset(pvt);
 
 	debugf1("  DHAR info for node %d base 0x%lx offset 0x%lx size 0x%lx\n",
 		pvt->mc_node_id, (unsigned long)*hole_base,
@@ -525,10 +497,11 @@
  */
 static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr)
 {
+	struct amd64_pvt *pvt = mci->pvt_info;
 	u64 dram_base, hole_base, hole_offset, hole_size, dram_addr;
 	int ret = 0;
 
-	dram_base = get_dram_base(mci);
+	dram_base = get_dram_base(pvt, pvt->mc_node_id);
 
 	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
 				      &hole_size);
@@ -556,7 +529,7 @@
 	 * 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;
+	dram_addr = (sys_addr & GENMASK(0, 39)) - dram_base;
 
 	debugf2("using DRAM Base register to translate SysAddr 0x%lx to "
 		"DramAddr 0x%lx\n", (unsigned long)sys_addr,
@@ -592,9 +565,9 @@
 	 * 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);
+	intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
+	input_addr = ((dram_addr >> intlv_shift) & GENMASK(12, 35)) +
+		      (dram_addr & 0xfff);
 
 	debugf2("  Intlv Shift=%d DramAddr=0x%lx maps to InputAddr=0x%lx\n",
 		intlv_shift, (unsigned long)dram_addr,
@@ -628,7 +601,7 @@
 static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr)
 {
 	struct amd64_pvt *pvt;
-	int node_id, intlv_shift;
+	unsigned node_id, intlv_shift;
 	u64 bits, dram_addr;
 	u32 intlv_sel;
 
@@ -642,10 +615,10 @@
 	 */
 	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]);
+	BUG_ON(node_id > 7);
 
+	intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0));
 	if (intlv_shift == 0) {
 		debugf1("    InputAddr 0x%lx translates to DramAddr of "
 			"same value\n",	(unsigned long)input_addr);
@@ -653,10 +626,10 @@
 		return input_addr;
 	}
 
-	bits = ((input_addr & 0xffffff000ull) << intlv_shift) +
-	    (input_addr & 0xfff);
+	bits = ((input_addr & GENMASK(12, 35)) << intlv_shift) +
+		(input_addr & 0xfff);
 
-	intlv_sel = pvt->dram_IntlvSel[node_id] & ((1 << intlv_shift) - 1);
+	intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1);
 	dram_addr = bits + (intlv_sel << 12);
 
 	debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx "
@@ -673,7 +646,7 @@
 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;
+	u64 hole_base, hole_offset, hole_size, base, sys_addr;
 	int ret = 0;
 
 	ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset,
@@ -691,7 +664,7 @@
 		}
 	}
 
-	amd64_get_base_and_limit(pvt, pvt->mc_node_id, &base, &limit);
+	base     = get_dram_base(pvt, pvt->mc_node_id);
 	sys_addr = dram_addr + base;
 
 	/*
@@ -736,13 +709,12 @@
 	u64 base, mask;
 
 	pvt = mci->pvt_info;
-	BUG_ON((csrow < 0) || (csrow >= pvt->cs_count));
+	BUG_ON((csrow < 0) || (csrow >= pvt->csels[0].b_cnt));
 
-	base = base_from_dct_base(pvt, csrow);
-	mask = mask_from_dct_mask(pvt, csrow);
+	get_cs_base_and_mask(pvt, csrow, 0, &base, &mask);
 
 	*input_addr_min = base & ~mask;
-	*input_addr_max = base | mask | pvt->dcs_mask_notused;
+	*input_addr_max = base | mask;
 }
 
 /* Map the Error address to a PAGE and PAGE OFFSET. */
@@ -775,18 +747,13 @@
 
 static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16);
 
-static u16 extract_syndrome(struct err_regs *err)
-{
-	return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00);
-}
-
 /*
  * 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;
+	u8 bit;
 	enum dev_type edac_cap = EDAC_FLAG_NONE;
 
 	bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F)
@@ -799,8 +766,7 @@
 	return edac_cap;
 }
 
-
-static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt);
+static void amd64_debug_display_dimm_sizes(struct amd64_pvt *, u8);
 
 static void amd64_dump_dramcfg_low(u32 dclr, int chan)
 {
@@ -813,8 +779,9 @@
 	debugf1("  PAR/ERR parity: %s\n",
 		(dclr & BIT(8)) ?  "enabled" : "disabled");
 
-	debugf1("  DCT 128bit mode width: %s\n",
-		(dclr & BIT(11)) ?  "128b" : "64b");
+	if (boot_cpu_data.x86 == 0x10)
+		debugf1("  DCT 128bit mode width: %s\n",
+			(dclr & BIT(11)) ?  "128b" : "64b");
 
 	debugf1("  x4 logical DIMMs present: L0: %s L1: %s L2: %s L3: %s\n",
 		(dclr & BIT(12)) ?  "yes" : "no",
@@ -824,16 +791,16 @@
 }
 
 /* Display and decode various NB registers for debug purposes. */
-static void amd64_dump_misc_regs(struct amd64_pvt *pvt)
+static void dump_misc_regs(struct amd64_pvt *pvt)
 {
 	debugf1("F3xE8 (NB Cap): 0x%08x\n", pvt->nbcap);
 
 	debugf1("  NB two channel DRAM capable: %s\n",
-		(pvt->nbcap & K8_NBCAP_DCT_DUAL) ? "yes" : "no");
+		(pvt->nbcap & NBCAP_DCT_DUAL) ? "yes" : "no");
 
 	debugf1("  ECC capable: %s, ChipKill ECC capable: %s\n",
-		(pvt->nbcap & K8_NBCAP_SECDED) ? "yes" : "no",
-		(pvt->nbcap & K8_NBCAP_CHIPKILL) ? "yes" : "no");
+		(pvt->nbcap & NBCAP_SECDED) ? "yes" : "no",
+		(pvt->nbcap & NBCAP_CHIPKILL) ? "yes" : "no");
 
 	amd64_dump_dramcfg_low(pvt->dclr0, 0);
 
@@ -841,130 +808,84 @@
 
 	debugf1("F1xF0 (DRAM Hole Address): 0x%08x, base: 0x%08x, "
 			"offset: 0x%08x\n",
-			pvt->dhar,
-			dhar_base(pvt->dhar),
-			(boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt->dhar)
-						   : f10_dhar_offset(pvt->dhar));
+			pvt->dhar, dhar_base(pvt),
+			(boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt)
+						   : f10_dhar_offset(pvt));
 
-	debugf1("  DramHoleValid: %s\n",
-		(pvt->dhar & DHAR_VALID) ? "yes" : "no");
+	debugf1("  DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no");
 
-	amd64_debug_display_dimm_sizes(0, pvt);
+	amd64_debug_display_dimm_sizes(pvt, 0);
 
 	/* everything below this point is Fam10h and above */
 	if (boot_cpu_data.x86 == 0xf)
 		return;
 
-	amd64_debug_display_dimm_sizes(1, pvt);
+	amd64_debug_display_dimm_sizes(pvt, 1);
 
-	amd64_info("using %s syndromes.\n", ((pvt->syn_type == 8) ? "x8" : "x4"));
+	amd64_info("using %s syndromes.\n", ((pvt->ecc_sym_sz == 8) ? "x8" : "x4"));
 
 	/* Only if NOT ganged does dclr1 have valid info */
 	if (!dct_ganging_enabled(pvt))
 		amd64_dump_dramcfg_low(pvt->dclr1, 1);
 }
 
-/* Read in both of DBAM registers */
-static void amd64_read_dbam_reg(struct amd64_pvt *pvt)
-{
-	amd64_read_pci_cfg(pvt->F2, DBAM0, &pvt->dbam0);
-
-	if (boot_cpu_data.x86 >= 0x10)
-		amd64_read_pci_cfg(pvt->F2, DBAM1, &pvt->dbam1);
-}
-
 /*
- * 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.
+ * see BKDG, F2x[1,0][5C:40], F2[1,0][6C:60]
  */
-static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt)
+static void prep_chip_selects(struct amd64_pvt *pvt)
 {
-
 	if (boot_cpu_data.x86 == 0xf && pvt->ext_model < K8_REV_F) {
-		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->cs_count		= 8;
-		pvt->num_dcsm		= 8;
+		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
+		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8;
 	} else {
-		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;
-		pvt->cs_count		= 8;
-		pvt->num_dcsm		= 4;
+		pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8;
+		pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4;
 	}
 }
 
 /*
- * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask hw registers
+ * Function 2 Offset F10_DCSB0; read in the DCS Base and DCS Mask registers
  */
-static void amd64_read_dct_base_mask(struct amd64_pvt *pvt)
+static void read_dct_base_mask(struct amd64_pvt *pvt)
 {
-	int cs, reg;
+	int cs;
 
-	amd64_set_dct_base_and_mask(pvt);
+	prep_chip_selects(pvt);
 
-	for (cs = 0; cs < pvt->cs_count; cs++) {
-		reg = K8_DCSB0 + (cs * 4);
-		if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsb0[cs]))
+	for_each_chip_select(cs, 0, pvt) {
+		int reg0   = DCSB0 + (cs * 4);
+		int reg1   = DCSB1 + (cs * 4);
+		u32 *base0 = &pvt->csels[0].csbases[cs];
+		u32 *base1 = &pvt->csels[1].csbases[cs];
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg0, base0))
 			debugf0("  DCSB0[%d]=0x%08x reg: F2x%x\n",
-				cs, pvt->dcsb0[cs], reg);
+				cs, *base0, reg0);
 
-		/* 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);
-			if (!amd64_read_pci_cfg(pvt->F2, reg,
-						&pvt->dcsb1[cs]))
-				debugf0("  DCSB1[%d]=0x%08x reg: F2x%x\n",
-					cs, pvt->dcsb1[cs], reg);
-		} else {
-			pvt->dcsb1[cs] = 0;
-		}
+		if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt))
+			continue;
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg1, base1))
+			debugf0("  DCSB1[%d]=0x%08x reg: F2x%x\n",
+				cs, *base1, reg1);
 	}
 
-	for (cs = 0; cs < pvt->num_dcsm; cs++) {
-		reg = K8_DCSM0 + (cs * 4);
-		if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsm0[cs]))
+	for_each_chip_select_mask(cs, 0, pvt) {
+		int reg0   = DCSM0 + (cs * 4);
+		int reg1   = DCSM1 + (cs * 4);
+		u32 *mask0 = &pvt->csels[0].csmasks[cs];
+		u32 *mask1 = &pvt->csels[1].csmasks[cs];
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg0, mask0))
 			debugf0("    DCSM0[%d]=0x%08x reg: F2x%x\n",
-				cs, pvt->dcsm0[cs], reg);
+				cs, *mask0, reg0);
 
-		/* 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);
-			if (!amd64_read_pci_cfg(pvt->F2, reg,
-						&pvt->dcsm1[cs]))
-				debugf0("    DCSM1[%d]=0x%08x reg: F2x%x\n",
-					cs, pvt->dcsm1[cs], reg);
-		} else {
-			pvt->dcsm1[cs] = 0;
-		}
+		if (boot_cpu_data.x86 == 0xf || dct_ganging_enabled(pvt))
+			continue;
+
+		if (!amd64_read_dct_pci_cfg(pvt, reg1, mask1))
+			debugf0("    DCSM1[%d]=0x%08x reg: F2x%x\n",
+				cs, *mask1, reg1);
 	}
 }
 
@@ -972,7 +893,10 @@
 {
 	enum mem_type type;
 
-	if (boot_cpu_data.x86 >= 0x10 || pvt->ext_model >= K8_REV_F) {
+	/* F15h supports only DDR3 */
+	if (boot_cpu_data.x86 >= 0x15)
+		type = (pvt->dclr0 & BIT(16)) ?	MEM_DDR3 : MEM_RDDR3;
+	else if (boot_cpu_data.x86 == 0x10 || pvt->ext_model >= K8_REV_F) {
 		if (pvt->dchr0 & DDR3_MODE)
 			type = (pvt->dclr0 & BIT(16)) ?	MEM_DDR3 : MEM_RDDR3;
 		else
@@ -986,26 +910,14 @@
 	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
- */
+/* Get the number of DCT channels the memory controller is using. */
 static int k8_early_channel_count(struct amd64_pvt *pvt)
 {
-	int flag, err = 0;
-
-	err = amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0);
-	if (err)
-		return err;
+	int flag;
 
 	if (pvt->ext_model >= K8_REV_F)
 		/* RevF (NPT) and later */
-		flag = pvt->dclr0 & F10_WIDTH_128;
+		flag = pvt->dclr0 & WIDTH_128;
 	else
 		/* RevE and earlier */
 		flag = pvt->dclr0 & REVE_WIDTH_128;
@@ -1016,55 +928,121 @@
 	return (flag) ? 2 : 1;
 }
 
-/* extract the ERROR ADDRESS for the K8 CPUs */
-static u64 k8_get_error_address(struct mem_ctl_info *mci,
-				struct err_regs *info)
+/* On F10h and later ErrAddr is MC4_ADDR[47:1] */
+static u64 get_error_address(struct mce *m)
 {
-	return (((u64) (info->nbeah & 0xff)) << 32) +
-			(info->nbeal & ~0x03);
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+	u64 addr;
+	u8 start_bit = 1;
+	u8 end_bit   = 47;
+
+	if (c->x86 == 0xf) {
+		start_bit = 3;
+		end_bit   = 39;
+	}
+
+	addr = m->addr & GENMASK(start_bit, end_bit);
+
+	/*
+	 * Erratum 637 workaround
+	 */
+	if (c->x86 == 0x15) {
+		struct amd64_pvt *pvt;
+		u64 cc6_base, tmp_addr;
+		u32 tmp;
+		u8 mce_nid, intlv_en;
+
+		if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
+			return addr;
+
+		mce_nid	= amd_get_nb_id(m->extcpu);
+		pvt	= mcis[mce_nid]->pvt_info;
+
+		amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp);
+		intlv_en = tmp >> 21 & 0x7;
+
+		/* add [47:27] + 3 trailing bits */
+		cc6_base  = (tmp & GENMASK(0, 20)) << 3;
+
+		/* reverse and add DramIntlvEn */
+		cc6_base |= intlv_en ^ 0x7;
+
+		/* pin at [47:24] */
+		cc6_base <<= 24;
+
+		if (!intlv_en)
+			return cc6_base | (addr & GENMASK(0, 23));
+
+		amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp);
+
+							/* faster log2 */
+		tmp_addr  = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1);
+
+		/* OR DramIntlvSel into bits [14:12] */
+		tmp_addr |= (tmp & GENMASK(21, 23)) >> 9;
+
+		/* add remaining [11:0] bits from original MC4_ADDR */
+		tmp_addr |= addr & GENMASK(0, 11);
+
+		return cc6_base | tmp_addr;
+	}
+
+	return addr;
 }
 
-/*
- * 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)
+static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
 {
-	u32 low;
-	u32 off = dram << 3;	/* 8 bytes between DRAM entries */
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+	int off = range << 3;
 
-	amd64_read_pci_cfg(pvt->F1, K8_DRAM_BASE_LOW + off, &low);
+	amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off,  &pvt->ranges[range].base.lo);
+	amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo);
 
-	/* 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);
+	if (c->x86 == 0xf)
+		return;
 
-	amd64_read_pci_cfg(pvt->F1, K8_DRAM_LIMIT_LOW + off, &low);
+	if (!dram_rw(pvt, range))
+		return;
 
-	/*
-	 * 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);
+	amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off,  &pvt->ranges[range].base.hi);
+	amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi);
+
+	/* Factor in CC6 save area by reading dst node's limit reg */
+	if (c->x86 == 0x15) {
+		struct pci_dev *f1 = NULL;
+		u8 nid = dram_dst_node(pvt, range);
+		u32 llim;
+
+		f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1));
+		if (WARN_ON(!f1))
+			return;
+
+		amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim);
+
+		pvt->ranges[range].lim.lo &= GENMASK(0, 15);
+
+					    /* {[39:27],111b} */
+		pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
+
+		pvt->ranges[range].lim.hi &= GENMASK(0, 7);
+
+					    /* [47:40] */
+		pvt->ranges[range].lim.hi |= llim >> 13;
+
+		pci_dev_put(f1);
+	}
 }
 
-static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
-				    struct err_regs *err_info, u64 sys_addr)
+static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
+				    u16 syndrome)
 {
 	struct mem_ctl_info *src_mci;
+	struct amd64_pvt *pvt = mci->pvt_info;
 	int channel, csrow;
 	u32 page, offset;
-	u16 syndrome;
-
-	syndrome = extract_syndrome(err_info);
 
 	/* CHIPKILL enabled */
-	if (err_info->nbcfg & K8_NBCFG_CHIPKILL) {
+	if (pvt->nbcfg & NBCFG_CHIPKILL) {
 		channel = get_channel_from_ecc_syndrome(mci, syndrome);
 		if (channel < 0) {
 			/*
@@ -1113,18 +1091,41 @@
 	}
 }
 
-static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode)
+static int ddr2_cs_size(unsigned i, bool dct_width)
 {
-	int *dbam_map;
+	unsigned shift = 0;
 
-	if (pvt->ext_model >= K8_REV_F)
-		dbam_map = ddr2_dbam;
-	else if (pvt->ext_model >= K8_REV_D)
-		dbam_map = ddr2_dbam_revD;
+	if (i <= 2)
+		shift = i;
+	else if (!(i & 0x1))
+		shift = i >> 1;
 	else
-		dbam_map = ddr2_dbam_revCG;
+		shift = (i + 1) >> 1;
 
-	return dbam_map[cs_mode];
+	return 128 << (shift + !!dct_width);
+}
+
+static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+				  unsigned cs_mode)
+{
+	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
+
+	if (pvt->ext_model >= K8_REV_F) {
+		WARN_ON(cs_mode > 11);
+		return ddr2_cs_size(cs_mode, dclr & WIDTH_128);
+	}
+	else if (pvt->ext_model >= K8_REV_D) {
+		WARN_ON(cs_mode > 10);
+
+		if (cs_mode == 3 || cs_mode == 8)
+			return 32 << (cs_mode - 1);
+		else
+			return 32 << cs_mode;
+	}
+	else {
+		WARN_ON(cs_mode > 6);
+		return 32 << cs_mode;
+	}
 }
 
 /*
@@ -1135,17 +1136,13 @@
  * Pass back:
  *	contents of the DCL0_LOW register
  */
-static int f10_early_channel_count(struct amd64_pvt *pvt)
+static int f1x_early_channel_count(struct amd64_pvt *pvt)
 {
-	int dbams[] = { DBAM0, DBAM1 };
 	int i, j, channels = 0;
-	u32 dbam;
 
-	/* If we are in 128 bit mode, then we are using 2 channels */
-	if (pvt->dclr0 & F10_WIDTH_128) {
-		channels = 2;
-		return channels;
-	}
+	/* On F10h, if we are in 128 bit mode, then we are using 2 channels */
+	if (boot_cpu_data.x86 == 0x10 && (pvt->dclr0 & WIDTH_128))
+		return 2;
 
 	/*
 	 * Need to check if in unganged mode: In such, there are 2 channels,
@@ -1162,9 +1159,8 @@
 	 * is more than just one DIMM present in unganged mode. Need to check
 	 * both controllers since DIMMs can be placed in either one.
 	 */
-	for (i = 0; i < ARRAY_SIZE(dbams); i++) {
-		if (amd64_read_pci_cfg(pvt->F2, dbams[i], &dbam))
-			goto err_reg;
+	for (i = 0; i < 2; i++) {
+		u32 dbam = (i ? pvt->dbam1 : pvt->dbam0);
 
 		for (j = 0; j < 4; j++) {
 			if (DBAM_DIMM(j, dbam) > 0) {
@@ -1180,216 +1176,191 @@
 	amd64_info("MCT channel count: %d\n", channels);
 
 	return channels;
-
-err_reg:
-	return -1;
-
 }
 
-static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode)
+static int ddr3_cs_size(unsigned i, bool dct_width)
 {
-	int *dbam_map;
+	unsigned shift = 0;
+	int cs_size = 0;
 
-	if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE)
-		dbam_map = ddr3_dbam;
+	if (i == 0 || i == 3 || i == 4)
+		cs_size = -1;
+	else if (i <= 2)
+		shift = i;
+	else if (i == 12)
+		shift = 7;
+	else if (!(i & 0x1))
+		shift = i >> 1;
 	else
-		dbam_map = ddr2_dbam;
+		shift = (i + 1) >> 1;
 
-	return dbam_map[cs_mode];
+	if (cs_size != -1)
+		cs_size = (128 * (1 << !!dct_width)) << shift;
+
+	return cs_size;
 }
 
-static u64 f10_get_error_address(struct mem_ctl_info *mci,
-			struct err_regs *info)
+static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+				   unsigned cs_mode)
 {
-	return (((u64) (info->nbeah & 0xffff)) << 32) +
-			(info->nbeal & ~0x01);
+	u32 dclr = dct ? pvt->dclr1 : pvt->dclr0;
+
+	WARN_ON(cs_mode > 11);
+
+	if (pvt->dchr0 & DDR3_MODE || pvt->dchr1 & DDR3_MODE)
+		return ddr3_cs_size(cs_mode, dclr & WIDTH_128);
+	else
+		return ddr2_cs_size(cs_mode, dclr & WIDTH_128);
 }
 
 /*
- * 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.
+ * F15h supports only 64bit DCT interfaces
  */
-static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram)
+static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct,
+				   unsigned cs_mode)
 {
-	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 */
-	amd64_read_pci_cfg(pvt->F1, low_offset, &low_base);
-	amd64_read_pci_cfg(pvt->F1, 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) << 40) |
-			       (((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 */
-	amd64_read_pci_cfg(pvt->F1, low_offset, &low_limit);
-	amd64_read_pci_cfg(pvt->F1, high_offset, &high_limit);
-
-	pvt->dram_DstNode[dram] = (low_limit & 0x7);
-	pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7;
+	WARN_ON(cs_mode > 12);
 
-	/*
-	 * 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.
-	 */
-	pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) |
-				(((u64) low_limit & 0xFFFF0000) << 8) |
-				0x00FFFFFF;
+	return ddr3_cs_size(cs_mode, false);
 }
 
-static void f10_read_dram_ctl_register(struct amd64_pvt *pvt)
+static void read_dram_ctl_register(struct amd64_pvt *pvt)
 {
 
-	if (!amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_LOW,
-				&pvt->dram_ctl_select_low)) {
-		debugf0("F2x110 (DCTL Sel. Low): 0x%08x, "
-			"High range addresses at: 0x%x\n",
-			pvt->dram_ctl_select_low,
-			dct_sel_baseaddr(pvt));
+	if (boot_cpu_data.x86 == 0xf)
+		return;
 
-		debugf0("  DCT mode: %s, All DCTs on: %s\n",
-			(dct_ganging_enabled(pvt) ? "ganged" : "unganged"),
-			(dct_dram_enabled(pvt) ? "yes"   : "no"));
+	if (!amd64_read_dct_pci_cfg(pvt, DCT_SEL_LO, &pvt->dct_sel_lo)) {
+		debugf0("F2x110 (DCTSelLow): 0x%08x, High range addrs at: 0x%x\n",
+			pvt->dct_sel_lo, dct_sel_baseaddr(pvt));
+
+		debugf0("  DCTs operate in %s mode.\n",
+			(dct_ganging_enabled(pvt) ? "ganged" : "unganged"));
 
 		if (!dct_ganging_enabled(pvt))
 			debugf0("  Address range split per DCT: %s\n",
 				(dct_high_range_enabled(pvt) ? "yes" : "no"));
 
-		debugf0("  DCT data interleave for ECC: %s, "
+		debugf0("  data interleave for ECC: %s, "
 			"DRAM cleared since last warm reset: %s\n",
 			(dct_data_intlv_enabled(pvt) ? "enabled" : "disabled"),
 			(dct_memory_cleared(pvt) ? "yes" : "no"));
 
-		debugf0("  DCT channel interleave: %s, "
-			"DCT interleave bits selector: 0x%x\n",
+		debugf0("  channel interleave: %s, "
+			"interleave bits selector: 0x%x\n",
 			(dct_interleave_enabled(pvt) ? "enabled" : "disabled"),
 			dct_sel_interleave_addr(pvt));
 	}
 
-	amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_HIGH,
-			   &pvt->dram_ctl_select_high);
+	amd64_read_dct_pci_cfg(pvt, DCT_SEL_HI, &pvt->dct_sel_hi);
 }
 
 /*
- * determine channel based on the interleaving mode: F10h BKDG, 2.8.9 Memory
+ * Determine channel (DCT) 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)
+static u8 f1x_determine_channel(struct amd64_pvt *pvt, u64 sys_addr,
+				bool hi_range_sel, u8 intlv_en)
 {
-	u32 cs, temp, dct_sel_high = (pvt->dram_ctl_select_low >> 1) & 1;
+	u8 dct_sel_high = (pvt->dct_sel_lo >> 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;
+		return 0;
 
-			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;
+	if (hi_range_sel)
+		return dct_sel_high;
 
-	return cs;
-}
+	/*
+	 * see F2x110[DctSelIntLvAddr] - channel interleave mode
+	 */
+	if (dct_interleave_enabled(pvt)) {
+		u8 intlv_addr = dct_sel_interleave_addr(pvt);
 
-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 DCT select function: 0=DCT0, 1=DCT1 */
+		if (!intlv_addr)
+			return sys_addr >> 6 & 1;
+
+		if (intlv_addr & 0x2) {
+			u8 shift = intlv_addr & 0x1 ? 9 : 6;
+			u32 temp = hweight_long((u32) ((sys_addr >> 16) & 0x1F)) % 2;
+
+			return ((sys_addr >> shift) & 1) ^ temp;
+		}
+
+		return (sys_addr >> (12 + hweight8(intlv_en))) & 1;
+	}
+
+	if (dct_high_range_enabled(pvt))
+		return ~dct_sel_high & 1;
 
 	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)
+/* Convert the sys_addr to the normalized DCT address */
+static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, unsigned range,
+				 u64 sys_addr, bool hi_rng,
+				 u32 dct_sel_base_addr)
 {
 	u64 chan_off;
+	u64 dram_base		= get_dram_base(pvt, range);
+	u64 hole_off		= f10_dhar_offset(pvt);
+	u64 dct_sel_base_off	= (pvt->dct_sel_hi & 0xFFFFFC00) << 16;
 
-	if (hi_range_sel) {
-		if (!(dct_sel_base_addr & 0xFFFF0000) &&
-		   hole_valid && (sys_addr >= 0x100000000ULL))
-			chan_off = hole_off << 16;
+	if (hi_rng) {
+		/*
+		 * if
+		 * base address of high range is below 4Gb
+		 * (bits [47:27] at [31:11])
+		 * DRAM address space on this DCT is hoisted above 4Gb	&&
+		 * sys_addr > 4Gb
+		 *
+		 *	remove hole offset from sys_addr
+		 * else
+		 *	remove high range offset from sys_addr
+		 */
+		if ((!(dct_sel_base_addr >> 16) ||
+		     dct_sel_base_addr < dhar_base(pvt)) &&
+		    dhar_valid(pvt) &&
+		    (sys_addr >= BIT_64(32)))
+			chan_off = hole_off;
 		else
 			chan_off = dct_sel_base_off;
 	} else {
-		if (hole_valid && (sys_addr >= 0x100000000ULL))
-			chan_off = hole_off << 16;
+		/*
+		 * if
+		 * we have a valid hole		&&
+		 * sys_addr > 4Gb
+		 *
+		 *	remove hole
+		 * else
+		 *	remove dram base to normalize to DCT address
+		 */
+		if (dhar_valid(pvt) && (sys_addr >= BIT_64(32)))
+			chan_off = hole_off;
 		else
-			chan_off = dram_base & 0xFFFFF8000000ULL;
+			chan_off = dram_base;
 	}
 
-	return (sys_addr & 0x0000FFFFFFFFFFC0ULL) -
-			(chan_off & 0x0000FFFFFF800000ULL);
+	return (sys_addr & GENMASK(6,47)) - (chan_off & GENMASK(23,47));
 }
 
-/* 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)
+static int f10_process_possible_spare(struct amd64_pvt *pvt, u8 dct, int csrow)
 {
-	u32 swap_done;
-	u32 bad_dram_cs;
+	int tmp_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;
+	if (online_spare_swap_done(pvt, dct) &&
+	    csrow == online_spare_bad_dramcs(pvt, dct)) {
+
+		for_each_chip_select(tmp_cs, dct, pvt) {
+			if (chip_select_base(tmp_cs, dct, pvt) & 0x2) {
+				csrow = tmp_cs;
+				break;
+			}
+		}
 	}
 	return csrow;
 }
@@ -1402,11 +1373,11 @@
  *	-EINVAL:  NOT FOUND
  *	0..csrow = Chip-Select Row
  */
-static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs)
+static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct)
 {
 	struct mem_ctl_info *mci;
 	struct amd64_pvt *pvt;
-	u32 cs_base, cs_mask;
+	u64 cs_base, cs_mask;
 	int cs_found = -EINVAL;
 	int csrow;
 
@@ -1416,39 +1387,25 @@
 
 	pvt = mci->pvt_info;
 
-	debugf1("InputAddr=0x%x  channelselect=%d\n", in_addr, cs);
-
-	for (csrow = 0; csrow < pvt->cs_count; csrow++) {
+	debugf1("input addr: 0x%llx, DCT: %d\n", in_addr, dct);
 
-		cs_base = amd64_get_dct_base(pvt, cs, csrow);
-		if (!(cs_base & K8_DCSB_CS_ENABLE))
+	for_each_chip_select(csrow, dct, pvt) {
+		if (!csrow_enabled(csrow, dct, pvt))
 			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);
+		get_cs_base_and_mask(pvt, csrow, dct, &cs_base, &cs_mask);
 
-		debugf1("    CSROW=%d CSBase=0x%x RAW CSMask=0x%x\n",
-				csrow, cs_base, cs_mask);
+		debugf1("    CSROW=%d CSBase=0x%llx CSMask=0x%llx\n",
+			csrow, cs_base, cs_mask);
 
-		cs_mask = (cs_mask | 0x0007C01F) & 0x1FFFFFFF;
+		cs_mask = ~cs_mask;
 
-		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));
+		debugf1("    (InputAddr & ~CSMask)=0x%llx "
+			"(CSBase & ~CSMask)=0x%llx\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);
+		if ((in_addr & cs_mask) == (cs_base & cs_mask)) {
+			cs_found = f10_process_possible_spare(pvt, dct, csrow);
 
 			debugf1(" MATCH csrow=%d\n", cs_found);
 			break;
@@ -1457,39 +1414,72 @@
 	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)
+/*
+ * See F2x10C. Non-interleaved graphics framebuffer memory under the 16G is
+ * swapped with a region located at the bottom of memory so that the GPU can use
+ * the interleaved region and thus two channels.
+ */
+static u64 f1x_swap_interleaved_region(struct amd64_pvt *pvt, u64 sys_addr)
 {
-	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;
+	u32 swap_reg, swap_base, swap_limit, rgn_size, tmp_addr;
 
-	dram_base = pvt->dram_base[dram_range];
-	intlv_en = pvt->dram_IntlvEn[dram_range];
+	if (boot_cpu_data.x86 == 0x10) {
+		/* only revC3 and revE have that feature */
+		if (boot_cpu_data.x86_model < 4 ||
+		    (boot_cpu_data.x86_model < 0xa &&
+		     boot_cpu_data.x86_mask < 3))
+			return sys_addr;
+	}
 
-	node_id = pvt->dram_DstNode[dram_range];
-	intlv_sel = pvt->dram_IntlvSel[dram_range];
+	amd64_read_dct_pci_cfg(pvt, SWAP_INTLV_REG, &swap_reg);
 
-	debugf1("(dram=%d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n",
-		dram_range, dram_base, sys_addr, pvt->dram_limit[dram_range]);
+	if (!(swap_reg & 0x1))
+		return sys_addr;
 
-	/*
-	 * 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;
+	swap_base	= (swap_reg >> 3) & 0x7f;
+	swap_limit	= (swap_reg >> 11) & 0x7f;
+	rgn_size	= (swap_reg >> 20) & 0x7f;
+	tmp_addr	= sys_addr >> 27;
 
-	debugf1("   HoleOffset=0x%x  HoleValid=0x%x IntlvSel=0x%x\n",
-			hole_off, hole_valid, intlv_sel);
+	if (!(sys_addr >> 34) &&
+	    (((tmp_addr >= swap_base) &&
+	     (tmp_addr <= swap_limit)) ||
+	     (tmp_addr < rgn_size)))
+		return sys_addr ^ (u64)swap_base << 27;
 
-	if (intlv_en &&
-	    (intlv_sel != ((sys_addr >> 12) & intlv_en)))
+	return sys_addr;
+}
+
+/* For a given @dram_range, check if @sys_addr falls within it. */
+static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
+				  u64 sys_addr, int *nid, int *chan_sel)
+{
+	int cs_found = -EINVAL;
+	u64 chan_addr;
+	u32 dct_sel_base;
+	u8 channel;
+	bool high_range = false;
+
+	u8 node_id    = dram_dst_node(pvt, range);
+	u8 intlv_en   = dram_intlv_en(pvt, range);
+	u32 intlv_sel = dram_intlv_sel(pvt, range);
+
+	debugf1("(range %d) SystemAddr= 0x%llx Limit=0x%llx\n",
+		range, sys_addr, get_dram_limit(pvt, range));
+
+	if (dhar_valid(pvt) &&
+	    dhar_base(pvt) <= sys_addr &&
+	    sys_addr < BIT_64(32)) {
+		amd64_warn("Huh? Address is in the MMIO hole: 0x%016llx\n",
+			    sys_addr);
+		return -EINVAL;
+	}
+
+	if (intlv_en && (intlv_sel != ((sys_addr >> 12) & intlv_en)))
 		return -EINVAL;
 
+	sys_addr = f1x_swap_interleaved_region(pvt, sys_addr);
+
 	dct_sel_base = dct_sel_baseaddr(pvt);
 
 	/*
@@ -1499,38 +1489,41 @@
 	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);
+		high_range = true;
 
-	intlv_shift = f10_map_intlv_en_to_shift(intlv_en);
+	channel = f1x_determine_channel(pvt, sys_addr, high_range, intlv_en);
 
-	/* remove Node ID (in case of memory interleaving) */
-	tmp = chan_addr & 0xFC0;
+	chan_addr = f1x_get_norm_dct_addr(pvt, range, sys_addr,
+					  high_range, dct_sel_base);
 
-	chan_addr = ((chan_addr >> intlv_shift) & 0xFFFFFFFFF000ULL) | tmp;
+	/* Remove node interleaving, see F1x120 */
+	if (intlv_en)
+		chan_addr = ((chan_addr >> (12 + hweight8(intlv_en))) << 12) |
+			    (chan_addr & 0xfff);
 
-	/* remove channel interleave and hash */
+	/* remove channel interleave */
 	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;
-		}
+
+		if (dct_sel_interleave_addr(pvt) != 1) {
+			if (dct_sel_interleave_addr(pvt) == 0x3)
+				/* hash 9 */
+				chan_addr = ((chan_addr >> 10) << 9) |
+					     (chan_addr & 0x1ff);
+			else
+				/* A[6] or hash 6 */
+				chan_addr = ((chan_addr >> 7) << 6) |
+					     (chan_addr & 0x3f);
+		} else
+			/* A[12] */
+			chan_addr = ((chan_addr >> 13) << 12) |
+				     (chan_addr & 0xfff);
 	}
 
-	debugf1("   (ChannelAddrLong=0x%llx) >> 8 becomes InputAddr=0x%x\n",
-		chan_addr, (u32)(chan_addr >> 8));
+	debugf1("   Normalized DCT addr: 0x%llx\n", chan_addr);
 
-	cs_found = f10_lookup_addr_in_dct(chan_addr >> 8, node_id, channel);
+	cs_found = f1x_lookup_addr_in_dct(chan_addr, node_id, channel);
 
 	if (cs_found >= 0) {
 		*nid = node_id;
@@ -1539,23 +1532,21 @@
 	return cs_found;
 }
 
-static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr,
+static int f1x_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;
+	int cs_found = -EINVAL;
+	unsigned range;
 
-	for (dram_range = 0; dram_range < DRAM_REG_COUNT; dram_range++) {
+	for (range = 0; range < DRAM_RANGES; range++) {
 
-		if (!pvt->dram_rw_en[dram_range])
+		if (!dram_rw(pvt, 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)) {
+		if ((get_dram_base(pvt, range)  <= sys_addr) &&
+		    (get_dram_limit(pvt, range) >= sys_addr)) {
 
-			cs_found = f10_match_to_this_node(pvt, dram_range,
+			cs_found = f1x_match_to_this_node(pvt, range,
 							  sys_addr, node,
 							  chan_sel);
 			if (cs_found >= 0)
@@ -1572,16 +1563,14 @@
  * The @sys_addr is usually an error address received from the hardware
  * (MCX_ADDR).
  */
-static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci,
-				     struct err_regs *err_info,
-				     u64 sys_addr)
+static void f1x_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
+				     u16 syndrome)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u32 page, offset;
 	int nid, csrow, chan = 0;
-	u16 syndrome;
 
-	csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
+	csrow = f1x_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan);
 
 	if (csrow < 0) {
 		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
@@ -1590,14 +1579,12 @@
 
 	error_address_to_page_and_offset(sys_addr, &page, &offset);
 
-	syndrome = extract_syndrome(err_info);
-
 	/*
 	 * We need the syndromes for channel detection only when we're
 	 * ganged. Otherwise @chan should already contain the channel at
 	 * this point.
 	 */
-	if (dct_ganging_enabled(pvt) && (pvt->nbcfg & K8_NBCFG_CHIPKILL))
+	if (dct_ganging_enabled(pvt))
 		chan = get_channel_from_ecc_syndrome(mci, syndrome);
 
 	if (chan >= 0)
@@ -1614,16 +1601,16 @@
 
 /*
  * debug routine to display the memory sizes of all logical DIMMs and its
- * CSROWs as well
+ * CSROWs
  */
-static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt)
+static void amd64_debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl)
 {
 	int dimm, size0, size1, factor = 0;
-	u32 dbam;
-	u32 *dcsb;
+	u32 *dcsb = ctrl ? pvt->csels[1].csbases : pvt->csels[0].csbases;
+	u32 dbam  = ctrl ? pvt->dbam1 : pvt->dbam0;
 
 	if (boot_cpu_data.x86 == 0xf) {
-		if (pvt->dclr0 & F10_WIDTH_128)
+		if (pvt->dclr0 & WIDTH_128)
 			factor = 1;
 
 		/* K8 families < revF not supported yet */
@@ -1634,7 +1621,8 @@
 	}
 
 	dbam = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dbam1 : pvt->dbam0;
-	dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->dcsb1 : pvt->dcsb0;
+	dcsb = (ctrl && !dct_ganging_enabled(pvt)) ? pvt->csels[1].csbases
+						   : pvt->csels[0].csbases;
 
 	debugf1("F2x%d80 (DRAM Bank Address Mapping): 0x%08x\n", ctrl, dbam);
 
@@ -1644,12 +1632,14 @@
 	for (dimm = 0; dimm < 4; dimm++) {
 
 		size0 = 0;
-		if (dcsb[dimm*2] & K8_DCSB_CS_ENABLE)
-			size0 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam));
+		if (dcsb[dimm*2] & DCSB_CS_ENABLE)
+			size0 = pvt->ops->dbam_to_cs(pvt, ctrl,
+						     DBAM_DIMM(dimm, dbam));
 
 		size1 = 0;
-		if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE)
-			size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam));
+		if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE)
+			size1 = pvt->ops->dbam_to_cs(pvt, ctrl,
+						     DBAM_DIMM(dimm, dbam));
 
 		amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n",
 				dimm * 2,     size0 << factor,
@@ -1664,10 +1654,9 @@
 		.f3_id = 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_to_cs		= k8_dbam_to_chip_select,
+			.read_dct_pci_cfg	= k8_read_dct_pci_cfg,
 		}
 	},
 	[F10_CPUS] = {
@@ -1675,12 +1664,21 @@
 		.f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP,
 		.f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC,
 		.ops = {
-			.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,
+			.early_channel_count	= f1x_early_channel_count,
+			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
 			.dbam_to_cs		= f10_dbam_to_chip_select,
+			.read_dct_pci_cfg	= f10_read_dct_pci_cfg,
+		}
+	},
+	[F15_CPUS] = {
+		.ctl_name = "F15h",
+		.f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1,
+		.f3_id = PCI_DEVICE_ID_AMD_15H_NB_F3,
+		.ops = {
+			.early_channel_count	= f1x_early_channel_count,
+			.map_sysaddr_to_csrow	= f1x_map_sysaddr_to_csrow,
+			.dbam_to_cs		= f15_dbam_to_chip_select,
+			.read_dct_pci_cfg	= f15_read_dct_pci_cfg,
 		}
 	},
 };
@@ -1770,15 +1768,15 @@
 	0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
 };
 
-static int decode_syndrome(u16 syndrome, u16 *vectors, int num_vecs,
-			   int v_dim)
+static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs,
+			   unsigned v_dim)
 {
 	unsigned int i, err_sym;
 
 	for (err_sym = 0; err_sym < num_vecs / v_dim; err_sym++) {
 		u16 s = syndrome;
-		int v_idx =  err_sym * v_dim;
-		int v_end = (err_sym + 1) * v_dim;
+		unsigned v_idx =  err_sym * v_dim;
+		unsigned v_end = (err_sym + 1) * v_dim;
 
 		/* walk over all 16 bits of the syndrome */
 		for (i = 1; i < (1U << 16); i <<= 1) {
@@ -1850,51 +1848,50 @@
 	struct amd64_pvt *pvt = mci->pvt_info;
 	int err_sym = -1;
 
-	if (pvt->syn_type == 8)
+	if (pvt->ecc_sym_sz == 8)
 		err_sym = decode_syndrome(syndrome, x8_vectors,
 					  ARRAY_SIZE(x8_vectors),
-					  pvt->syn_type);
-	else if (pvt->syn_type == 4)
+					  pvt->ecc_sym_sz);
+	else if (pvt->ecc_sym_sz == 4)
 		err_sym = decode_syndrome(syndrome, x4_vectors,
 					  ARRAY_SIZE(x4_vectors),
-					  pvt->syn_type);
+					  pvt->ecc_sym_sz);
 	else {
-		amd64_warn("Illegal syndrome type: %u\n", pvt->syn_type);
+		amd64_warn("Illegal syndrome type: %u\n", pvt->ecc_sym_sz);
 		return err_sym;
 	}
 
-	return map_err_sym_to_channel(err_sym, pvt->syn_type);
+	return map_err_sym_to_channel(err_sym, pvt->ecc_sym_sz);
 }
 
 /*
  * 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 err_regs *info)
+static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m)
 {
 	struct amd64_pvt *pvt = mci->pvt_info;
 	u64 sys_addr;
+	u16 syndrome;
 
 	/* Ensure that the Error Address is VALID */
-	if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) {
+	if (!(m->status & MCI_STATUS_ADDRV)) {
 		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
 		edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR);
 		return;
 	}
 
-	sys_addr = pvt->ops->get_error_address(mci, info);
+	sys_addr = get_error_address(m);
+	syndrome = extract_syndrome(m->status);
 
 	amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr);
 
-	pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr);
+	pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, syndrome);
 }
 
 /* Handle any Un-correctable Errors (UEs) */
-static void amd64_handle_ue(struct mem_ctl_info *mci,
-			    struct err_regs *info)
+static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m)
 {
-	struct amd64_pvt *pvt = mci->pvt_info;
 	struct mem_ctl_info *log_mci, *src_mci = NULL;
 	int csrow;
 	u64 sys_addr;
@@ -1902,13 +1899,13 @@
 
 	log_mci = mci;
 
-	if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) {
+	if (!(m->status & MCI_STATUS_ADDRV)) {
 		amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n");
 		edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR);
 		return;
 	}
 
-	sys_addr = pvt->ops->get_error_address(mci, info);
+	sys_addr = get_error_address(m);
 
 	/*
 	 * Find out which node the error address belongs to. This may be
@@ -1936,14 +1933,14 @@
 }
 
 static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci,
-					    struct err_regs *info)
+					    struct mce *m)
 {
-	u16 ec = EC(info->nbsl);
-	u8 xec = XEC(info->nbsl, 0x1f);
-	int ecc_type = (info->nbsh >> 13) & 0x3;
+	u16 ec = EC(m->status);
+	u8 xec = XEC(m->status, 0x1f);
+	u8 ecc_type = (m->status >> 45) & 0x3;
 
 	/* Bail early out if this was an 'observed' error */
-	if (PP(ec) == K8_NBSL_PP_OBS)
+	if (PP(ec) == NBSL_PP_OBS)
 		return;
 
 	/* Do only ECC errors */
@@ -1951,34 +1948,16 @@
 		return;
 
 	if (ecc_type == 2)
-		amd64_handle_ce(mci, info);
+		amd64_handle_ce(mci, m);
 	else if (ecc_type == 1)
-		amd64_handle_ue(mci, info);
+		amd64_handle_ue(mci, m);
 }
 
 void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg)
 {
 	struct mem_ctl_info *mci = mcis[node_id];
-	struct err_regs regs;
-
-	regs.nbsl  = (u32) m->status;
-	regs.nbsh  = (u32)(m->status >> 32);
-	regs.nbeal = (u32) m->addr;
-	regs.nbeah = (u32)(m->addr >> 32);
-	regs.nbcfg = nbcfg;
-
-	__amd64_decode_bus_error(mci, &regs);
-
-	/*
-	 * 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.
-	 *
-	 * FIXME: this should go somewhere else, if at all.
-	 */
-	if (regs.nbsh & K8_NBSH_UC_ERR && !report_gart_errors)
-		edac_mc_handle_ue_no_info(mci, "UE bit is set");
 
+	__amd64_decode_bus_error(mci, m);
 }
 
 /*
@@ -2027,9 +2006,10 @@
  */
 static void read_mc_regs(struct amd64_pvt *pvt)
 {
+	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u64 msr_val;
 	u32 tmp;
-	int dram;
+	unsigned range;
 
 	/*
 	 * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since
@@ -2046,75 +2026,66 @@
 	} else
 		debugf0("  TOP_MEM2 disabled.\n");
 
-	amd64_read_pci_cfg(pvt->F3, K8_NBCAP, &pvt->nbcap);
+	amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap);
 
-	if (pvt->ops->read_dram_ctl_register)
-		pvt->ops->read_dram_ctl_register(pvt);
+	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);
+	for (range = 0; range < DRAM_RANGES; range++) {
+		u8 rw;
 
-		/*
-		 * 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%016llx "
-				"DRAM-LIMIT:  0x%016llx\n",
-				dram,
-				pvt->dram_base[dram],
-				pvt->dram_limit[dram]);
+		/* read settings for this DRAM range */
+		read_dram_base_limit_regs(pvt, range);
 
-			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]);
-		}
+		rw = dram_rw(pvt, range);
+		if (!rw)
+			continue;
+
+		debugf1("  DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n",
+			range,
+			get_dram_base(pvt, range),
+			get_dram_limit(pvt, range));
+
+		debugf1("   IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n",
+			dram_intlv_en(pvt, range) ? "Enabled" : "Disabled",
+			(rw & 0x1) ? "R" : "-",
+			(rw & 0x2) ? "W" : "-",
+			dram_intlv_sel(pvt, range),
+			dram_dst_node(pvt, range));
 	}
 
-	amd64_read_dct_base_mask(pvt);
+	read_dct_base_mask(pvt);
 
-	amd64_read_pci_cfg(pvt->F1, K8_DHAR, &pvt->dhar);
-	amd64_read_dbam_reg(pvt);
+	amd64_read_pci_cfg(pvt->F1, DHAR, &pvt->dhar);
+	amd64_read_dct_pci_cfg(pvt, DBAM0, &pvt->dbam0);
 
 	amd64_read_pci_cfg(pvt->F3, F10_ONLINE_SPARE, &pvt->online_spare);
 
-	amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0);
-	amd64_read_pci_cfg(pvt->F2, F10_DCHR_0, &pvt->dchr0);
+	amd64_read_dct_pci_cfg(pvt, DCLR0, &pvt->dclr0);
+	amd64_read_dct_pci_cfg(pvt, DCHR0, &pvt->dchr0);
 
-	if (boot_cpu_data.x86 >= 0x10) {
-		if (!dct_ganging_enabled(pvt)) {
-			amd64_read_pci_cfg(pvt->F2, F10_DCLR_1, &pvt->dclr1);
-			amd64_read_pci_cfg(pvt->F2, F10_DCHR_1, &pvt->dchr1);
-		}
-		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
+	if (!dct_ganging_enabled(pvt)) {
+		amd64_read_dct_pci_cfg(pvt, DCLR1, &pvt->dclr1);
+		amd64_read_dct_pci_cfg(pvt, DCHR1, &pvt->dchr1);
 	}
 
-	if (boot_cpu_data.x86 == 0x10 &&
-	    boot_cpu_data.x86_model > 7 &&
-	    /* F3x180[EccSymbolSize]=1 => x8 symbols */
-	    tmp & BIT(25))
-		pvt->syn_type = 8;
-	else
-		pvt->syn_type = 4;
+	pvt->ecc_sym_sz = 4;
 
-	amd64_dump_misc_regs(pvt);
+	if (c->x86 >= 0x10) {
+		amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp);
+		amd64_read_dct_pci_cfg(pvt, DBAM1, &pvt->dbam1);
+
+		/* F10h, revD and later can do x8 ECC too */
+		if ((c->x86 > 0x10 || c->x86_model > 7) && tmp & BIT(25))
+			pvt->ecc_sym_sz = 8;
+	}
+	dump_misc_regs(pvt);
 }
 
 /*
  * NOTE: CPU Revision Dependent code
  *
  * Input:
- *	@csrow_nr ChipSelect Row Number (0..pvt->cs_count-1)
+ *	@csrow_nr ChipSelect Row Number (0..NUM_CHIPSELECTS-1)
  *	k8 private pointer to -->
  *			DRAM Bank Address mapping register
  *			node_id
@@ -2144,7 +2115,7 @@
  *	encompasses
  *
  */
-static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt)
+static u32 amd64_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr)
 {
 	u32 cs_mode, nr_pages;
 
@@ -2157,7 +2128,7 @@
 	 */
 	cs_mode = (pvt->dbam0 >> ((csrow_nr / 2) * 4)) & 0xF;
 
-	nr_pages = pvt->ops->dbam_to_cs(pvt, cs_mode) << (20 - PAGE_SHIFT);
+	nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT);
 
 	/*
 	 * If dual channel then double the memory size of single channel.
@@ -2180,23 +2151,22 @@
 {
 	struct csrow_info *csrow;
 	struct amd64_pvt *pvt = mci->pvt_info;
-	u64 input_addr_min, input_addr_max, sys_addr;
+	u64 input_addr_min, input_addr_max, sys_addr, base, mask;
 	u32 val;
 	int i, empty = 1;
 
-	amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &val);
+	amd64_read_pci_cfg(pvt->F3, NBCFG, &val);
 
 	pvt->nbcfg = val;
-	pvt->ctl_error_info.nbcfg = val;
 
 	debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
 		pvt->mc_node_id, val,
-		!!(val & K8_NBCFG_CHIPKILL), !!(val & K8_NBCFG_ECC_ENABLE));
+		!!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE));
 
-	for (i = 0; i < pvt->cs_count; i++) {
+	for_each_chip_select(i, 0, pvt) {
 		csrow = &mci->csrows[i];
 
-		if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) {
+		if (!csrow_enabled(i, 0, pvt)) {
 			debugf1("----CSROW %d EMPTY for node %d\n", i,
 				pvt->mc_node_id);
 			continue;
@@ -2206,13 +2176,15 @@
 			i, pvt->mc_node_id);
 
 		empty = 0;
-		csrow->nr_pages = amd64_csrow_nr_pages(i, pvt);
+		csrow->nr_pages = amd64_csrow_nr_pages(pvt, 0, i);
 		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);
+
+		get_cs_base_and_mask(pvt, i, 0, &base, &mask);
+		csrow->page_mask = ~mask;
 		/* 8 bytes of resolution */
 
 		csrow->mtype = amd64_determine_memory_type(pvt, i);
@@ -2231,9 +2203,9 @@
 		/*
 		 * determine whether CHIPKILL or JUST ECC or NO ECC is operating
 		 */
-		if (pvt->nbcfg & K8_NBCFG_ECC_ENABLE)
+		if (pvt->nbcfg & NBCFG_ECC_ENABLE)
 			csrow->edac_mode =
-			    (pvt->nbcfg & K8_NBCFG_CHIPKILL) ?
+			    (pvt->nbcfg & NBCFG_CHIPKILL) ?
 			    EDAC_S4ECD4ED : EDAC_SECDED;
 		else
 			csrow->edac_mode = EDAC_NONE;
@@ -2243,7 +2215,7 @@
 }
 
 /* get all cores on this DCT */
-static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, int nid)
+static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid)
 {
 	int cpu;
 
@@ -2253,7 +2225,7 @@
 }
 
 /* check MCG_CTL on all the cpus on this node */
-static bool amd64_nb_mce_bank_enabled_on_node(int nid)
+static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid)
 {
 	cpumask_var_t mask;
 	int cpu, nbe;
@@ -2270,7 +2242,7 @@
 
 	for_each_cpu(cpu, mask) {
 		struct msr *reg = per_cpu_ptr(msrs, cpu);
-		nbe = reg->l & K8_MSR_MCGCTL_NBE;
+		nbe = reg->l & MSR_MCGCTL_NBE;
 
 		debugf0("core: %u, MCG_CTL: 0x%llx, NB MSR is %s\n",
 			cpu, reg->q,
@@ -2305,16 +2277,16 @@
 		struct msr *reg = per_cpu_ptr(msrs, cpu);
 
 		if (on) {
-			if (reg->l & K8_MSR_MCGCTL_NBE)
+			if (reg->l & MSR_MCGCTL_NBE)
 				s->flags.nb_mce_enable = 1;
 
-			reg->l |= K8_MSR_MCGCTL_NBE;
+			reg->l |= MSR_MCGCTL_NBE;
 		} else {
 			/*
 			 * Turn off NB MCE reporting only when it was off before
 			 */
 			if (!s->flags.nb_mce_enable)
-				reg->l &= ~K8_MSR_MCGCTL_NBE;
+				reg->l &= ~MSR_MCGCTL_NBE;
 		}
 	}
 	wrmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs);
@@ -2328,40 +2300,38 @@
 				       struct pci_dev *F3)
 {
 	bool ret = true;
-	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+	u32 value, mask = 0x3;		/* UECC/CECC enable */
 
 	if (toggle_ecc_err_reporting(s, nid, ON)) {
 		amd64_warn("Error enabling ECC reporting over MCGCTL!\n");
 		return false;
 	}
 
-	amd64_read_pci_cfg(F3, K8_NBCTL, &value);
+	amd64_read_pci_cfg(F3, NBCTL, &value);
 
-	/* turn on UECCEn and CECCEn bits */
 	s->old_nbctl   = value & mask;
 	s->nbctl_valid = true;
 
 	value |= mask;
-	pci_write_config_dword(F3, K8_NBCTL, value);
+	amd64_write_pci_cfg(F3, NBCTL, value);
 
-	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
+	amd64_read_pci_cfg(F3, NBCFG, &value);
 
-	debugf0("1: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
-		nid, value,
-		!!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE));
+	debugf0("1: node %d, NBCFG=0x%08x[DramEccEn: %d]\n",
+		nid, value, !!(value & NBCFG_ECC_ENABLE));
 
-	if (!(value & K8_NBCFG_ECC_ENABLE)) {
+	if (!(value & NBCFG_ECC_ENABLE)) {
 		amd64_warn("DRAM ECC disabled on this node, enabling...\n");
 
 		s->flags.nb_ecc_prev = 0;
 
 		/* Attempt to turn on DRAM ECC Enable */
-		value |= K8_NBCFG_ECC_ENABLE;
-		pci_write_config_dword(F3, K8_NBCFG, value);
+		value |= NBCFG_ECC_ENABLE;
+		amd64_write_pci_cfg(F3, NBCFG, value);
 
-		amd64_read_pci_cfg(F3, K8_NBCFG, &value);
+		amd64_read_pci_cfg(F3, NBCFG, &value);
 
-		if (!(value & K8_NBCFG_ECC_ENABLE)) {
+		if (!(value & NBCFG_ECC_ENABLE)) {
 			amd64_warn("Hardware rejected DRAM ECC enable,"
 				   "check memory DIMM configuration.\n");
 			ret = false;
@@ -2372,9 +2342,8 @@
 		s->flags.nb_ecc_prev = 1;
 	}
 
-	debugf0("2: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n",
-		nid, value,
-		!!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE));
+	debugf0("2: node %d, NBCFG=0x%08x[DramEccEn: %d]\n",
+		nid, value, !!(value & NBCFG_ECC_ENABLE));
 
 	return ret;
 }
@@ -2382,22 +2351,23 @@
 static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid,
 					struct pci_dev *F3)
 {
-	u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn;
+	u32 value, mask = 0x3;		/* UECC/CECC enable */
+
 
 	if (!s->nbctl_valid)
 		return;
 
-	amd64_read_pci_cfg(F3, K8_NBCTL, &value);
+	amd64_read_pci_cfg(F3, NBCTL, &value);
 	value &= ~mask;
 	value |= s->old_nbctl;
 
-	pci_write_config_dword(F3, K8_NBCTL, value);
+	amd64_write_pci_cfg(F3, NBCTL, value);
 
 	/* restore previous BIOS DRAM ECC "off" setting we force-enabled */
 	if (!s->flags.nb_ecc_prev) {
-		amd64_read_pci_cfg(F3, K8_NBCFG, &value);
-		value &= ~K8_NBCFG_ECC_ENABLE;
-		pci_write_config_dword(F3, K8_NBCFG, value);
+		amd64_read_pci_cfg(F3, NBCFG, &value);
+		value &= ~NBCFG_ECC_ENABLE;
+		amd64_write_pci_cfg(F3, NBCFG, value);
 	}
 
 	/* restore the NB Enable MCGCTL bit */
@@ -2423,9 +2393,9 @@
 	u8 ecc_en = 0;
 	bool nb_mce_en = false;
 
-	amd64_read_pci_cfg(F3, K8_NBCFG, &value);
+	amd64_read_pci_cfg(F3, NBCFG, &value);
 
-	ecc_en = !!(value & K8_NBCFG_ECC_ENABLE);
+	ecc_en = !!(value & NBCFG_ECC_ENABLE);
 	amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled"));
 
 	nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid);
@@ -2463,23 +2433,24 @@
 	mci->mc_driver_sysfs_attributes = sysfs_attrs;
 }
 
-static void setup_mci_misc_attrs(struct mem_ctl_info *mci)
+static void setup_mci_misc_attrs(struct mem_ctl_info *mci,
+				 struct amd64_family_type *fam)
 {
 	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)
+	if (pvt->nbcap & NBCAP_SECDED)
 		mci->edac_ctl_cap |= EDAC_FLAG_SECDED;
 
-	if (pvt->nbcap & K8_NBCAP_CHIPKILL)
+	if (pvt->nbcap & 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		= pvt->ctl_name;
+	mci->ctl_name		= fam->ctl_name;
 	mci->dev_name		= pci_name(pvt->F2);
 	mci->ctl_page_to_phys	= NULL;
 
@@ -2500,14 +2471,16 @@
 	case 0xf:
 		fam_type		= &amd64_family_types[K8_CPUS];
 		pvt->ops		= &amd64_family_types[K8_CPUS].ops;
-		pvt->ctl_name		= fam_type->ctl_name;
-		pvt->min_scrubrate	= K8_MIN_SCRUB_RATE_BITS;
 		break;
+
 	case 0x10:
 		fam_type		= &amd64_family_types[F10_CPUS];
 		pvt->ops		= &amd64_family_types[F10_CPUS].ops;
-		pvt->ctl_name		= fam_type->ctl_name;
-		pvt->min_scrubrate	= F10_MIN_SCRUB_RATE_BITS;
+		break;
+
+	case 0x15:
+		fam_type		= &amd64_family_types[F15_CPUS];
+		pvt->ops		= &amd64_family_types[F15_CPUS].ops;
 		break;
 
 	default:
@@ -2517,7 +2490,7 @@
 
 	pvt->ext_model = boot_cpu_data.x86_model >> 4;
 
-	amd64_info("%s %sdetected (node %d).\n", pvt->ctl_name,
+	amd64_info("%s %sdetected (node %d).\n", fam_type->ctl_name,
 		     (fam == 0xf ?
 				(pvt->ext_model >= K8_REV_F  ? "revF or later "
 							     : "revE or earlier ")
@@ -2564,14 +2537,14 @@
 		goto err_siblings;
 
 	ret = -ENOMEM;
-	mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, nid);
+	mci = edac_mc_alloc(0, pvt->csels[0].b_cnt, pvt->channel_count, nid);
 	if (!mci)
 		goto err_siblings;
 
 	mci->pvt_info = pvt;
 	mci->dev = &pvt->F2->dev;
 
-	setup_mci_misc_attrs(mci);
+	setup_mci_misc_attrs(mci, fam_type);
 
 	if (init_csrows(mci))
 		mci->edac_cap = EDAC_FLAG_NONE;
@@ -2714,6 +2687,15 @@
 		.class		= 0,
 		.class_mask	= 0,
 	},
+	{
+		.vendor		= PCI_VENDOR_ID_AMD,
+		.device		= PCI_DEVICE_ID_AMD_15H_NB_F2,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.class		= 0,
+		.class_mask	= 0,
+	},
+
 	{0, }
 };
 MODULE_DEVICE_TABLE(pci, amd64_pci_table);
@@ -2754,7 +2736,7 @@
 {
 	int err = -ENODEV;
 
-	edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n");
+	printk(KERN_INFO "AMD64 EDAC driver v%s\n", EDAC_AMD64_VERSION);
 
 	opstate_init();
 
@@ -2765,7 +2747,7 @@
 	mcis	  = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL);
 	ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL);
 	if (!(mcis && ecc_stngs))
-		goto err_ret;
+		goto err_free;
 
 	msrs = msrs_alloc();
 	if (!msrs)
diff -druN linux-libre-2.6.38-gnu/drivers/edac/amd64_edac.h linux-libre-2.6.39-gnu/drivers/edac/amd64_edac.h
--- linux-libre-2.6.38-gnu/drivers/edac/amd64_edac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/amd64_edac.h	2011-05-19 00:06:34.000000000 -0400
@@ -144,7 +144,7 @@
  *         sections 3.5.4 and 3.5.5 for more information.
  */
 
-#define EDAC_AMD64_VERSION		"v3.3.0"
+#define EDAC_AMD64_VERSION		"3.4.0"
 #define EDAC_MOD_STR			"amd64_edac"
 
 /* Extended Model from CPUID, for CPU Revision numbers */
@@ -153,85 +153,67 @@
 #define K8_REV_F			4
 
 /* Hardware limit on ChipSelect rows per MC and processors per system */
-#define MAX_CS_COUNT			8
-#define DRAM_REG_COUNT			8
+#define NUM_CHIPSELECTS			8
+#define DRAM_RANGES			8
 
 #define ON true
 #define OFF false
 
 /*
+ * Create a contiguous bitmask starting at bit position @lo and ending at
+ * position @hi. For example
+ *
+ * GENMASK(21, 39) gives us the 64bit vector 0x000000ffffe00000.
+ */
+#define GENMASK(lo, hi)			(((1ULL << ((hi) - (lo) + 1)) - 1) << (lo))
+
+/*
  * PCI-defined configuration space registers
  */
+#define PCI_DEVICE_ID_AMD_15H_NB_F1	0x1601
+#define PCI_DEVICE_ID_AMD_15H_NB_F2	0x1602
 
 
 /*
  * 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 DRAM_BASE_LO			0x40
+#define DRAM_LIMIT_LO			0x44
 
-#define DHAR_BASE_MASK			0xff000000
-#define dhar_base(dhar)			(dhar & DHAR_BASE_MASK)
+#define dram_intlv_en(pvt, i)		((u8)((pvt->ranges[i].base.lo >> 8) & 0x7))
+#define dram_rw(pvt, i)			((u8)(pvt->ranges[i].base.lo & 0x3))
+#define dram_intlv_sel(pvt, i)		((u8)((pvt->ranges[i].lim.lo >> 8) & 0x7))
+#define dram_dst_node(pvt, i)		((u8)(pvt->ranges[i].lim.lo & 0x7))
 
-#define K8_DHAR_OFFSET_MASK		0x0000ff00
-#define k8_dhar_offset(dhar)		((dhar & K8_DHAR_OFFSET_MASK) << 16)
+#define DHAR				0xf0
+#define dhar_valid(pvt)			((pvt)->dhar & BIT(0))
+#define dhar_mem_hoist_valid(pvt)	((pvt)->dhar & BIT(1))
+#define dhar_base(pvt)			((pvt)->dhar & 0xff000000)
+#define k8_dhar_offset(pvt)		(((pvt)->dhar & 0x0000ff00) << 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
-
+#define f10_dhar_offset(pvt)		(((pvt)->dhar & 0x0000ff80) << 16)
 
-/*
- * Function 2 - DRAM controller
- */
-#define K8_DCSB0			0x40
-#define F10_DCSB1			0x140
+#define DCT_CFG_SEL			0x10C
 
-#define K8_DCSB_CS_ENABLE		BIT(0)
-#define K8_DCSB_NPT_SPARE		BIT(1)
-#define K8_DCSB_NPT_TESTFAIL		BIT(2)
+#define DRAM_LOCAL_NODE_BASE		0x120
+#define DRAM_LOCAL_NODE_LIM		0x124
 
-/*
- * 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 DRAM_BASE_HI			0x140
+#define DRAM_LIMIT_HI			0x144
 
-#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
+ * Function 2 - DRAM controller
  */
-#define REV_F_DCSB_BASE_BITS		(0x1FF83FE0ULL)
-#define REV_F_DCS_SHIFT			8
-
-/* 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
+#define DCSB0				0x40
+#define DCSB1				0x140
+#define DCSB_CS_ENABLE			BIT(0)
 
-/* REV F and later: select [28:19] and [13:5] from DCSM */
-#define REV_F_F1Xh_DCSM_MASK_BITS	0x1FF83FE0
+#define DCSM0				0x60
+#define DCSM1				0x160
 
-/* unused bits [26:22] and [12:0] */
-#define REV_F_F1Xh_DCS_NOTUSED_BITS	0x07C01FFF
+#define csrow_enabled(i, dct, pvt)	((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE)
 
 #define DBAM0				0x80
 #define DBAM1				0x180
@@ -241,148 +223,84 @@
 
 #define DBAM_MAX_VALUE			11
 
-
-#define F10_DCLR_0			0x90
-#define F10_DCLR_1			0x190
+#define DCLR0				0x90
+#define DCLR1				0x190
 #define REVE_WIDTH_128			BIT(16)
-#define F10_WIDTH_128			BIT(11)
+#define WIDTH_128			BIT(11)
 
+#define DCHR0				0x94
+#define DCHR1				0x194
+#define DDR3_MODE			BIT(8)
 
-#define F10_DCHR_0			0x94
-#define F10_DCHR_1			0x194
+#define DCT_SEL_LO			0x110
+#define dct_sel_baseaddr(pvt)		((pvt)->dct_sel_lo & 0xFFFFF800)
+#define dct_sel_interleave_addr(pvt)	(((pvt)->dct_sel_lo >> 6) & 0x3)
+#define dct_high_range_enabled(pvt)	((pvt)->dct_sel_lo & BIT(0))
+#define dct_interleave_enabled(pvt)	((pvt)->dct_sel_lo & BIT(2))
 
-#define F10_DCHR_FOUR_RANK_DIMM		BIT(18)
-#define DDR3_MODE			BIT(8)
-#define F10_DCHR_MblMode		BIT(6)
+#define dct_ganging_enabled(pvt)	((boot_cpu_data.x86 == 0x10) && ((pvt)->dct_sel_lo & BIT(4)))
 
+#define dct_data_intlv_enabled(pvt)	((pvt)->dct_sel_lo & BIT(5))
+#define dct_memory_cleared(pvt)		((pvt)->dct_sel_lo & BIT(10))
 
-#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)
-#define dct_high_range_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(0))
-#define dct_interleave_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(2))
-#define dct_ganging_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(4))
-#define dct_data_intlv_enabled(pvt)	(pvt->dram_ctl_select_low & BIT(5))
-#define dct_dram_enabled(pvt)		(pvt->dram_ctl_select_low & BIT(8))
-#define dct_memory_cleared(pvt)		(pvt->dram_ctl_select_low & BIT(10))
+#define SWAP_INTLV_REG			0x10c
 
-#define F10_DCTL_SEL_HIGH		0x114
+#define DCT_SEL_HI			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 NBCTL				0x40
 
+#define NBCFG				0x44
+#define NBCFG_CHIPKILL			BIT(23)
+#define NBCFG_ECC_ENABLE		BIT(22)
 
-/* Family F10h: Normalized Extended Error Codes */
-#define F10_NBSL_EXT_ERR_RES		0x0
+/* F3x48: NBSL */
 #define F10_NBSL_EXT_ERR_ECC		0x8
+#define NBSL_PP_OBS			0x2
 
-/* 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
-
-/*
- * 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 EXTRACT_ERR_CPU_MAP(x)		((x) & 0xF)
-
-#define K8_NBEAL			0x50
-#define K8_NBEAH			0x54
-#define K8_SCRCTRL			0x58
-
-#define F10_NB_CFG_LOW			0x88
+#define SCRCTRL				0x58
 
 #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 online_spare_swap_done(pvt, c)	(((pvt)->online_spare >> (1 + 2 * (c))) & 0x1)
+#define online_spare_bad_dramcs(pvt, c)	(((pvt)->online_spare >> (4 + 4 * (c))) & 0x7)
 
 #define F10_NB_ARRAY_ADDR		0xB8
-
-#define F10_NB_ARRAY_DRAM_ECC		0x80000000
+#define F10_NB_ARRAY_DRAM_ECC		BIT(31)
 
 /* 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)
-
 #define SET_NB_DRAM_INJECTION_READ(word, bits)  \
 					(BIT(((word) & 0xF) + 20) | \
 					BIT(16) |  bits)
 
-#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_DCT_DUAL		BIT(0)
+#define NBCAP				0xE8
+#define NBCAP_CHIPKILL			BIT(4)
+#define NBCAP_SECDED			BIT(3)
+#define NBCAP_DCT_DUAL			BIT(0)
 
 #define EXT_NB_MCA_CFG			0x180
 
 /* MSRs */
-#define K8_MSR_MCGCTL_NBE		BIT(4)
-
-#define K8_MSR_MC4CTL			0x0410
-#define K8_MSR_MC4STAT			0x0411
-#define K8_MSR_MC4ADDR			0x0412
+#define MSR_MCGCTL_NBE			BIT(4)
 
 /* AMD sets the first MC device at device ID 0x18. */
-static inline int get_node_id(struct pci_dev *pdev)
+static inline u8 get_node_id(struct pci_dev *pdev)
 {
 	return PCI_SLOT(pdev->devfn) - 0x18;
 }
 
-enum amd64_chipset_families {
+enum amd_families {
 	K8_CPUS = 0,
 	F10_CPUS,
+	F15_CPUS,
+	NUM_FAMILIES,
 };
 
 /* Error injection control structure */
@@ -392,13 +310,35 @@
 	u32	bit_map;
 };
 
+/* low and high part of PCI config space regs */
+struct reg_pair {
+	u32 lo, hi;
+};
+
+/*
+ * See F1x[1, 0][7C:40] DRAM Base/Limit Registers
+ */
+struct dram_range {
+	struct reg_pair base;
+	struct reg_pair lim;
+};
+
+/* A DCT chip selects collection */
+struct chip_select {
+	u32 csbases[NUM_CHIPSELECTS];
+	u8 b_cnt;
+
+	u32 csmasks[NUM_CHIPSELECTS];
+	u8 m_cnt;
+};
+
 struct amd64_pvt {
 	struct low_ops *ops;
 
 	/* pci_device handles which we utilize */
 	struct pci_dev *F1, *F2, *F3;
 
-	int mc_node_id;		/* MC index of this MC node */
+	unsigned mc_node_id;	/* MC index of this MC node */
 	int ext_model;		/* extended model value of this node */
 	int channel_count;
 
@@ -414,60 +354,50 @@
 	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[MAX_CS_COUNT];
-	u32 dcsb1[MAX_CS_COUNT];
-
-	/* DRAM CS Mask Registers F2x[1,0][6C:60] */
-	u32 dcsm0[MAX_CS_COUNT];
-	u32 dcsm1[MAX_CS_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];
+	/* one for each DCT */
+	struct chip_select csels[2];
 
-	/*
-	 * 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 cs_count;		/* num chip selects (== num DCSB registers) */
-	u32 num_dcsm;		/* Number of DCSM registers */
-	u32 dcs_mask_notused;	/* DCSM notused mask bits */
-	u32 dcs_shift;		/* DCSB and DCSM shift value */
+	/* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */
+	struct dram_range ranges[DRAM_RANGES];
 
 	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 */
+	u32 dct_sel_lo;		/* DRAM Controller Select Low */
+	u32 dct_sel_hi;		/* DRAM Controller Select High */
+	u32 online_spare;	/* On-Line spare Reg */
 
 	/* x4 or x8 syndromes in use */
-	u8 syn_type;
-
-	/* temp storage for when input is received from sysfs */
-	struct err_regs ctl_error_info;
+	u8 ecc_sym_sz;
 
 	/* place to store error injection parameters prior to issue */
 	struct error_injection injection;
+};
 
-	/* DCT per-family scrubrate setting */
-	u32 min_scrubrate;
+static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i)
+{
+	u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
 
-	/* family name this instance is running on */
-	const char *ctl_name;
+	if (boot_cpu_data.x86 == 0xf)
+		return addr;
 
-};
+	return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr;
+}
+
+static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i)
+{
+	u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff;
+
+	if (boot_cpu_data.x86 == 0xf)
+		return lim;
+
+	return (((u64)pvt->ranges[i].lim.hi & 0x000000ff) << 40) | lim;
+}
+
+static inline u16 extract_syndrome(u64 status)
+{
+	return ((status >> 47) & 0xff) | ((status >> 16) & 0xff00);
+}
 
 /*
  * per-node ECC settings descriptor
@@ -482,14 +412,6 @@
 	} flags;
 };
 
-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 *htlink_msgs[8];
-
 #ifdef CONFIG_EDAC_DEBUG
 #define NUM_DBG_ATTRS 5
 #else
@@ -511,14 +433,11 @@
  */
 struct low_ops {
 	int (*early_channel_count)	(struct amd64_pvt *pvt);
-
-	u64 (*get_error_address)	(struct mem_ctl_info *mci,
-					 struct err_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 err_regs *info, u64 SystemAddr);
-	int (*dbam_to_cs)		(struct amd64_pvt *pvt, int cs_mode);
+	void (*map_sysaddr_to_csrow)	(struct mem_ctl_info *mci, u64 sys_addr,
+					 u16 syndrome);
+	int (*dbam_to_cs)		(struct amd64_pvt *pvt, u8 dct, unsigned cs_mode);
+	int (*read_dct_pci_cfg)		(struct amd64_pvt *pvt, int offset,
+					 u32 *val, const char *func);
 };
 
 struct amd64_family_type {
@@ -527,28 +446,17 @@
 	struct low_ops ops;
 };
 
-static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset,
-					   u32 *val, const char *func)
-{
-	int err = 0;
-
-	err = pci_read_config_dword(pdev, offset, val);
-	if (err)
-		amd64_warn("%s: error reading F%dx%x.\n",
-			   func, PCI_FUNC(pdev->devfn), offset);
-
-	return err;
-}
+int __amd64_write_pci_cfg_dword(struct pci_dev *pdev, int offset,
+				u32 val, const char *func);
 
 #define amd64_read_pci_cfg(pdev, offset, val)	\
-	amd64_read_pci_cfg_dword(pdev, offset, val, __func__)
+	__amd64_read_pci_cfg_dword(pdev, offset, val, __func__)
 
-/*
- * 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 amd64_write_pci_cfg(pdev, offset, val)	\
+	__amd64_write_pci_cfg_dword(pdev, offset, val, __func__)
+
+#define amd64_read_dct_pci_cfg(pvt, offset, val) \
+	pvt->ops->read_dct_pci_cfg(pvt, offset, val, __func__)
 
 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.38-gnu/drivers/edac/amd64_edac_inj.c linux-libre-2.6.39-gnu/drivers/edac/amd64_edac_inj.c
--- linux-libre-2.6.38-gnu/drivers/edac/amd64_edac_inj.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/amd64_edac_inj.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,13 +117,13 @@
 		/* 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->F3, F10_NB_ARRAY_ADDR, section);
+		amd64_write_pci_cfg(pvt->F3, 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->F3, F10_NB_ARRAY_DATA, word_bits);
+		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
@@ -150,13 +150,13 @@
 		/* 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->F3, F10_NB_ARRAY_ADDR, section);
+		amd64_write_pci_cfg(pvt->F3, 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->F3, F10_NB_ARRAY_DATA, word_bits);
+		amd64_write_pci_cfg(pvt->F3, F10_NB_ARRAY_DATA, word_bits);
 
 		debugf0("section=0x%x word_bits=0x%x\n", section, word_bits);
 
diff -druN linux-libre-2.6.38-gnu/drivers/edac/cpc925_edac.c linux-libre-2.6.39-gnu/drivers/edac/cpc925_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/cpc925_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/cpc925_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -817,7 +817,7 @@
 	}
 }
 
-/* Convert current back-ground scrub rate into byte/sec bandwith */
+/* Convert current back-ground scrub rate into byte/sec bandwidth */
 static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci)
 {
 	struct cpc925_mc_pdata *pdata = mci->pvt_info;
diff -druN linux-libre-2.6.38-gnu/drivers/edac/edac_core.h linux-libre-2.6.39-gnu/drivers/edac/edac_core.h
--- linux-libre-2.6.38-gnu/drivers/edac/edac_core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/edac_core.h	2011-05-19 00:06:34.000000000 -0400
@@ -164,7 +164,7 @@
 /* chipset Error Detection and Correction capabilities and mode */
 enum edac_type {
 	EDAC_UNKNOWN = 0,	/* Unknown if ECC is available */
-	EDAC_NONE,		/* Doesnt support ECC */
+	EDAC_NONE,		/* Doesn't support ECC */
 	EDAC_RESERVED,		/* Reserved ECC type */
 	EDAC_PARITY,		/* Detects parity errors */
 	EDAC_EC,		/* Error Checking - no correction */
@@ -233,7 +233,7 @@
  *			of these in parallel provides 64 bits which is common
  *			for a memory stick.
  *
- * Memory Stick:	A printed circuit board that agregates multiple
+ * Memory Stick:	A printed circuit board that aggregates multiple
  *			memory devices in parallel.  This is the atomic
  *			memory component that is purchaseable by Joe consumer
  *			and loaded into a memory socket.
@@ -385,7 +385,7 @@
 
 	/* Get the current sdram memory scrub rate from the internal
 	   representation and converts it to the closest matching
-	   bandwith in bytes/sec.
+	   bandwidth in bytes/sec.
 	 */
 	int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci);
 
@@ -823,7 +823,7 @@
  * There are a limited number of error logging registers that can
  * be exausted.  When all registers are exhausted and an additional
  * error occurs then an error overflow register records that an
- * error occured and the type of error, but doesn't have any
+ * error occurred and the type of error, but doesn't have any
  * further information.  The ce/ue versions make for cleaner
  * reporting logic and function interface - reduces conditional
  * statement clutter and extra function arguments.
diff -druN linux-libre-2.6.38-gnu/drivers/edac/edac_device.c linux-libre-2.6.39-gnu/drivers/edac/edac_device.c
--- linux-libre-2.6.38-gnu/drivers/edac/edac_device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/edac_device.c	2011-05-19 00:06:34.000000000 -0400
@@ -672,7 +672,7 @@
 		block->counters.ce_count++;
 	}
 
-	/* Propogate the count up the 'totals' tree */
+	/* Propagate the count up the 'totals' tree */
 	instance->counters.ce_count++;
 	edac_dev->counters.ce_count++;
 
@@ -718,7 +718,7 @@
 		block->counters.ue_count++;
 	}
 
-	/* Propogate the count up the 'totals' tree */
+	/* Propagate the count up the 'totals' tree */
 	instance->counters.ue_count++;
 	edac_dev->counters.ue_count++;
 
diff -druN linux-libre-2.6.38-gnu/drivers/edac/edac_device_sysfs.c linux-libre-2.6.39-gnu/drivers/edac/edac_device_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/edac/edac_device_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/edac_device_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -533,7 +533,7 @@
 	memset(&block->kobj, 0, sizeof(struct kobject));
 
 	/* bump the main kobject's reference count for this controller
-	 * and this instance is dependant on the main
+	 * and this instance is dependent on the main
 	 */
 	main_kobj = kobject_get(&edac_dev->kobj);
 	if (!main_kobj) {
@@ -635,7 +635,7 @@
 	instance->ctl = edac_dev;
 
 	/* bump the main kobject's reference count for this controller
-	 * and this instance is dependant on the main
+	 * and this instance is dependent on the main
 	 */
 	main_kobj = kobject_get(&edac_dev->kobj);
 	if (!main_kobj) {
diff -druN linux-libre-2.6.38-gnu/drivers/edac/edac_mc.c linux-libre-2.6.39-gnu/drivers/edac/edac_mc.c
--- linux-libre-2.6.38-gnu/drivers/edac/edac_mc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/edac_mc.c	2011-05-19 00:06:34.000000000 -0400
@@ -724,7 +724,7 @@
 		 * Some MC's can remap memory so that it is still available
 		 * at a different address when PCI devices map into memory.
 		 * MC's that can't do this lose the memory where PCI devices
-		 * are mapped.  This mapping is MC dependant and so we call
+		 * are mapped.  This mapping is MC dependent and so we call
 		 * back into the MC driver for it to map the MC page to
 		 * a physical (CPU) page which can then be mapped to a virtual
 		 * page - which can then be scrubbed.
diff -druN linux-libre-2.6.38-gnu/drivers/edac/edac_mc_sysfs.c linux-libre-2.6.39-gnu/drivers/edac/edac_mc_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/edac/edac_mc_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/edac_mc_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -458,13 +458,13 @@
 		return -EINVAL;
 
 	new_bw = mci->set_sdram_scrub_rate(mci, bandwidth);
-	if (new_bw >= 0) {
-		edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw);
-		return count;
+	if (new_bw < 0) {
+		edac_printk(KERN_WARNING, EDAC_MC,
+			    "Error setting scrub rate to: %lu\n", bandwidth);
+		return -EINVAL;
 	}
 
-	edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth);
-	return -EINVAL;
+	return count;
 }
 
 /*
@@ -483,7 +483,6 @@
 		return bandwidth;
 	}
 
-	edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth);
 	return sprintf(data, "%d\n", bandwidth);
 }
 
@@ -785,10 +784,10 @@
 {
 	int err;
 
-	debugf1("%s()\n", __func__);
+	debugf4("%s()\n", __func__);
 
 	while (sysfs_attrib) {
-		debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
+		debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 		if (sysfs_attrib->grp) {
 			struct mcidev_sysfs_group_kobj *grp_kobj;
 
@@ -818,7 +817,7 @@
 			if (err < 0)
 				return err;
 		} else if (sysfs_attrib->attr.name) {
-			debugf0("%s() file %s\n", __func__,
+			debugf4("%s() file %s\n", __func__,
 				sysfs_attrib->attr.name);
 
 			err = sysfs_create_file(kobj, &sysfs_attrib->attr);
@@ -850,29 +849,29 @@
 
 	/*
 	 * loop if there are attributes and until we hit a NULL entry
-	 * Remove first all the atributes
+	 * Remove first all the attributes
 	 */
 	while (sysfs_attrib) {
-		debugf1("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
+		debugf4("%s() sysfs_attrib = %p\n",__func__, sysfs_attrib);
 		if (sysfs_attrib->grp) {
-			debugf1("%s() seeking for group %s\n",
+			debugf4("%s() seeking for group %s\n",
 				__func__, sysfs_attrib->grp->name);
 			list_for_each_entry(grp_kobj,
 					    &mci->grp_kobj_list, list) {
-				debugf1("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
+				debugf4("%s() grp_kobj->grp = %p\n",__func__, grp_kobj->grp);
 				if (grp_kobj->grp == sysfs_attrib->grp) {
 					edac_remove_mci_instance_attributes(mci,
 						    grp_kobj->grp->mcidev_attr,
 						    &grp_kobj->kobj, count + 1);
-					debugf0("%s() group %s\n", __func__,
+					debugf4("%s() group %s\n", __func__,
 						sysfs_attrib->grp->name);
 					kobject_put(&grp_kobj->kobj);
 				}
 			}
-			debugf1("%s() end of seeking for group %s\n",
+			debugf4("%s() end of seeking for group %s\n",
 				__func__, sysfs_attrib->grp->name);
 		} else if (sysfs_attrib->attr.name) {
-			debugf0("%s() file %s\n", __func__,
+			debugf4("%s() file %s\n", __func__,
 				sysfs_attrib->attr.name);
 			sysfs_remove_file(kobj, &sysfs_attrib->attr);
 		} else
@@ -979,7 +978,7 @@
 	debugf0("%s()\n", __func__);
 
 	/* remove all csrow kobjects */
-	debugf0("%s()  unregister this mci kobj\n", __func__);
+	debugf4("%s()  unregister this mci kobj\n", __func__);
 	for (i = 0; i < mci->nr_csrows; i++) {
 		if (mci->csrows[i].nr_pages > 0) {
 			debugf0("%s()  unreg csrow-%d\n", __func__, i);
@@ -989,18 +988,18 @@
 
 	/* remove this mci instance's attribtes */
 	if (mci->mc_driver_sysfs_attributes) {
-		debugf0("%s()  unregister mci private attributes\n", __func__);
+		debugf4("%s()  unregister mci private attributes\n", __func__);
 		edac_remove_mci_instance_attributes(mci,
 						mci->mc_driver_sysfs_attributes,
 						&mci->edac_mci_kobj, 0);
 	}
 
 	/* remove the symlink */
-	debugf0("%s()  remove_link\n", __func__);
+	debugf4("%s()  remove_link\n", __func__);
 	sysfs_remove_link(&mci->edac_mci_kobj, EDAC_DEVICE_SYMLINK);
 
 	/* unregister this instance's kobject */
-	debugf0("%s()  remove_mci_instance\n", __func__);
+	debugf4("%s()  remove_mci_instance\n", __func__);
 	kobject_put(&mci->edac_mci_kobj);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/edac/edac_pci_sysfs.c linux-libre-2.6.39-gnu/drivers/edac/edac_pci_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/edac/edac_pci_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/edac_pci_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -352,7 +352,7 @@
 		return 0;
 
 	/* First time, so create the main kobject and its
-	 * controls and atributes
+	 * controls and attributes
 	 */
 	edac_class = edac_get_sysfs_class();
 	if (edac_class == NULL) {
@@ -551,7 +551,7 @@
 /*
  *  PCI Parity polling
  *
- *	Fucntion to retrieve the current parity status
+ *	Function to retrieve the current parity status
  *	and decode it
  *
  */
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i5000_edac.c linux-libre-2.6.39-gnu/drivers/edac/i5000_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i5000_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i5000_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -1372,7 +1372,7 @@
 	 * actual number of slots/dimms per channel, we thus utilize the
 	 * resource as specified by the chipset. Thus, we might have
 	 * have more DIMMs per channel than actually on the mobo, but this
-	 * allows the driver to support upto the chipset max, without
+	 * allows the driver to support up to the chipset max, without
 	 * some fancy mobo determination.
 	 */
 	i5000_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel,
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i5100_edac.c linux-libre-2.6.39-gnu/drivers/edac/i5100_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i5100_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i5100_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
  *
  * The intel 5100 has two independent channels. EDAC core currently
  * can not reflect this configuration so instead the chip-select
- * rows for each respective channel are layed out one after another,
+ * rows for each respective channel are laid out one after another,
  * the first half belonging to channel 0, the second half belonging
  * to channel 1.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i5400_edac.c linux-libre-2.6.39-gnu/drivers/edac/i5400_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i5400_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i5400_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -648,7 +648,7 @@
 		return;
 	}
 
-	/* Miscelaneous errors */
+	/* Miscellaneous errors */
 	errnum = find_first_bit(&allErrors, ARRAY_SIZE(error_name));
 
 	branch = extract_fbdchan_indx(info->ferr_nf_fbd);
@@ -1240,7 +1240,7 @@
 	 * actual number of slots/dimms per channel, we thus utilize the
 	 * resource as specified by the chipset. Thus, we might have
 	 * have more DIMMs per channel than actually on the mobo, but this
-	 * allows the driver to support upto the chipset max, without
+	 * allows the driver to support up to the chipset max, without
 	 * some fancy mobo determination.
 	 */
 	num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL;
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i7300_edac.c linux-libre-2.6.39-gnu/drivers/edac/i7300_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i7300_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i7300_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -162,7 +162,7 @@
 #define AMBPRESENT_0	0x64
 #define AMBPRESENT_1	0x66
 
-const static u16 mtr_regs[MAX_SLOTS] = {
+static const u16 mtr_regs[MAX_SLOTS] = {
 	0x80, 0x84, 0x88, 0x8c,
 	0x82, 0x86, 0x8a, 0x8e
 };
@@ -1065,7 +1065,7 @@
 	 * actual number of slots/dimms per channel, we thus utilize the
 	 * resource as specified by the chipset. Thus, we might have
 	 * have more DIMMs per channel than actually on the mobo, but this
-	 * allows the driver to support upto the chipset max, without
+	 * allows the driver to support up to the chipset max, without
 	 * some fancy mobo determination.
 	 */
 	num_dimms_per_channel = MAX_SLOTS;
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i7core_edac.c linux-libre-2.6.39-gnu/drivers/edac/i7core_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i7core_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i7core_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -1772,7 +1772,7 @@
 	/*
 	 * MCE first step: Copy all mce errors into a temporary buffer
 	 * We use a double buffering here, to reduce the risk of
-	 * loosing an error.
+	 * losing an error.
 	 */
 	smp_rmb();
 	count = (pvt->mce_out + MCE_LOG_LEN - pvt->mce_in)
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i82443bxgx_edac.c linux-libre-2.6.39-gnu/drivers/edac/i82443bxgx_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i82443bxgx_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i82443bxgx_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -203,7 +203,7 @@
 		row_high_limit = ((u32) drbar << 23);
 		/* find the DRAM Chip Select Base address and mask */
 		debugf1("MC%d: %s: %s() Row=%d, "
-			"Boundry Address=%#0x, Last = %#0x\n",
+			"Boundary Address=%#0x, Last = %#0x\n",
 			mci->mc_idx, __FILE__, __func__, index, row_high_limit,
 			row_high_limit_last);
 
@@ -305,7 +305,7 @@
 	i82443bxgx_init_csrows(mci, pdev, edac_mode, mtype);
 
 	/* Many BIOSes don't clear error flags on boot, so do this
-	 * here, or we get "phantom" errors occuring at module-load
+	 * here, or we get "phantom" errors occurring at module-load
 	 * time. */
 	pci_write_bits32(pdev, I82443BXGX_EAP,
 			(I82443BXGX_EAP_OFFSET_SBE |
diff -druN linux-libre-2.6.38-gnu/drivers/edac/i82975x_edac.c linux-libre-2.6.39-gnu/drivers/edac/i82975x_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/i82975x_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/i82975x_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,8 +160,8 @@
 					 * 3:2  Rank 1 architecture
 					 * 1:0  Rank 0 architecture
 					 *
-					 * 00 => x16 devices; i.e 4 banks
-					 * 01 => x8  devices; i.e 8 banks
+					 * 00 => 4 banks
+					 * 01 => 8 banks
 					 */
 #define I82975X_C0BNKARC	0x10e
 #define I82975X_C1BNKARC	0x18e
@@ -278,6 +278,7 @@
 		struct i82975x_error_info *info, int handle_errors)
 {
 	int row, multi_chan, chan;
+	unsigned long offst, page;
 
 	multi_chan = mci->csrows[0].nr_channels - 1;
 
@@ -292,17 +293,19 @@
 		info->errsts = info->errsts2;
 	}
 
-	chan = info->eap & 1;
-	info->eap >>= 1;
-	if (info->xeap )
-		info->eap |= 0x80000000;
-	info->eap >>= PAGE_SHIFT;
-	row = edac_mc_find_csrow_by_page(mci, info->eap);
+	page = (unsigned long) info->eap;
+	if (info->xeap & 1)
+		page |= 0x100000000ul;
+	chan = page & 1;
+	page >>= 1;
+	offst = page & ((1 << PAGE_SHIFT) - 1);
+	page >>= PAGE_SHIFT;
+	row = edac_mc_find_csrow_by_page(mci, page);
 
 	if (info->errsts & 0x0002)
-		edac_mc_handle_ue(mci, info->eap, 0, row, "i82975x UE");
+		edac_mc_handle_ue(mci, page, offst , row, "i82975x UE");
 	else
-		edac_mc_handle_ce(mci, info->eap, 0, info->derrsyn, row,
+		edac_mc_handle_ce(mci, page, offst, info->derrsyn, row,
 				multi_chan ? chan : 0,
 				"i82975x CE");
 
@@ -344,11 +347,7 @@
 static enum dev_type i82975x_dram_type(void __iomem *mch_window, int rank)
 {
 	/*
-	 * ASUS P5W DH either does not program this register or programs
-	 * it wrong!
-	 * ECC is possible on i92975x ONLY with DEV_X8 which should mean 'val'
-	 * for each rank should be 01b - the LSB of the word should be 0x55;
-	 * but it reads 0!
+	 * ECC is possible on i92975x ONLY with DEV_X8
 	 */
 	return DEV_X8;
 }
@@ -356,11 +355,15 @@
 static void i82975x_init_csrows(struct mem_ctl_info *mci,
 		struct pci_dev *pdev, void __iomem *mch_window)
 {
+	static const char *labels[4] = {
+							"DIMM A1", "DIMM A2",
+							"DIMM B1", "DIMM B2"
+						};
 	struct csrow_info *csrow;
 	unsigned long last_cumul_size;
 	u8 value;
 	u32 cumul_size;
-	int index;
+	int index, chan;
 
 	last_cumul_size = 0;
 
@@ -369,11 +372,7 @@
 	 * The dram row boundary (DRB) reg values are boundary address
 	 * for each DRAM row with a granularity of 32 or 64MB (single/dual
 	 * channel operation).  DRB regs are cumulative; therefore DRB7 will
-	 * contain the total memory contained in all eight rows.
-	 *
-	 * FIXME:
-	 *  EDAC currently works for Dual-channel Interleaved configuration.
-	 *  Other configurations, which the chip supports, need fixing/testing.
+	 * contain the total memory contained in all rows.
 	 *
 	 */
 
@@ -384,8 +383,26 @@
 					((index >= 4) ? 0x80 : 0));
 		cumul_size = value;
 		cumul_size <<= (I82975X_DRB_SHIFT - PAGE_SHIFT);
+		/*
+		 * Adjust cumul_size w.r.t number of channels
+		 *
+		 */
+		if (csrow->nr_channels > 1)
+			cumul_size <<= 1;
 		debugf3("%s(): (%d) cumul_size 0x%x\n", __func__, index,
 			cumul_size);
+
+		/*
+		 * Initialise dram labels
+		 * index values:
+		 *   [0-7] for single-channel; i.e. csrow->nr_channels = 1
+		 *   [0-3] for dual-channel; i.e. csrow->nr_channels = 2
+		 */
+		for (chan = 0; chan < csrow->nr_channels; chan++)
+			strncpy(csrow->channels[chan].label,
+					labels[(index >> 1) + (chan * 2)],
+					EDAC_MC_LABEL_LEN);
+
 		if (cumul_size == last_cumul_size)
 			continue;	/* not populated */
 
@@ -393,8 +410,8 @@
 		csrow->last_page = cumul_size - 1;
 		csrow->nr_pages = cumul_size - last_cumul_size;
 		last_cumul_size = cumul_size;
-		csrow->grain = 1 << 7;	/* I82975X_EAP has 128B resolution */
-		csrow->mtype = MEM_DDR; /* i82975x supports only DDR2 */
+		csrow->grain = 1 << 6;	/* I82975X_EAP has 64B resolution */
+		csrow->mtype = MEM_DDR2; /* I82975x supports only DDR2 */
 		csrow->dtype = i82975x_dram_type(mch_window, index);
 		csrow->edac_mode = EDAC_SECDED; /* only supported */
 	}
@@ -515,18 +532,20 @@
 
 	debugf3("%s(): init mci\n", __func__);
 	mci->dev = &pdev->dev;
-	mci->mtype_cap = MEM_FLAG_DDR;
+	mci->mtype_cap = MEM_FLAG_DDR2;
 	mci->edac_ctl_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
 	mci->edac_cap = EDAC_FLAG_NONE | EDAC_FLAG_SECDED;
 	mci->mod_name = EDAC_MOD_STR;
 	mci->mod_ver = I82975X_REVISION;
 	mci->ctl_name = i82975x_devs[dev_idx].ctl_name;
+	mci->dev_name = pci_name(pdev);
 	mci->edac_check = i82975x_check;
 	mci->ctl_page_to_phys = NULL;
 	debugf3("%s(): init pvt\n", __func__);
 	pvt = (struct i82975x_pvt *) mci->pvt_info;
 	pvt->mch_window = mch_window;
 	i82975x_init_csrows(mci, pdev, mch_window);
+	mci->scrub_mode = SCRUB_HW_SRC;
 	i82975x_get_error_info(mci, &discard);  /* clear counters */
 
 	/* finalize this instance of memory controller with edac core */
@@ -664,7 +683,7 @@
 module_exit(i82975x_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Arvind R. <arvind@acarlab.com>");
+MODULE_AUTHOR("Arvind R. <arvino55@gmail.com>");
 MODULE_DESCRIPTION("MC support for Intel 82975 memory hub controllers");
 
 module_param(edac_op_state, int, 0444);
diff -druN linux-libre-2.6.38-gnu/drivers/edac/Kconfig linux-libre-2.6.39-gnu/drivers/edac/Kconfig
--- linux-libre-2.6.38-gnu/drivers/edac/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,7 @@
 menuconfig EDAC
 	bool "EDAC (Error Detection And Correction) reporting"
 	depends on HAS_IOMEM
-	depends on X86 || PPC
+	depends on X86 || PPC || TILE
 	help
 	  EDAC is designed to report errors in the core system.
 	  These are low-level errors that are reported in the CPU or
@@ -45,7 +45,7 @@
 	default y
 	---help---
 	  Enable this option if you want to decode Machine Check Exceptions
-	  occuring on your machine in human-readable form.
+	  occurring on your machine in human-readable form.
 
 	  You should definitely say Y here in case you want to decode MCEs
 	  which occur really early upon boot, before the module infrastructure
@@ -282,4 +282,12 @@
 	  a companion chip to the PowerPC 970 family of
 	  processors.
 
+config EDAC_TILE
+	tristate "Tilera Memory Controller"
+	depends on EDAC_MM_EDAC && TILE
+	default y
+	help
+	  Support for error detection and correction on the
+	  Tilera memory controller.
+
 endif # EDAC
diff -druN linux-libre-2.6.38-gnu/drivers/edac/Makefile linux-libre-2.6.39-gnu/drivers/edac/Makefile
--- linux-libre-2.6.38-gnu/drivers/edac/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -54,3 +54,4 @@
 obj-$(CONFIG_EDAC_AMD8111)		+= amd8111_edac.o
 obj-$(CONFIG_EDAC_AMD8131)		+= amd8131_edac.o
 
+obj-$(CONFIG_EDAC_TILE)			+= tile_edac.o
diff -druN linux-libre-2.6.38-gnu/drivers/edac/mce_amd.c linux-libre-2.6.39-gnu/drivers/edac/mce_amd.c
--- linux-libre-2.6.38-gnu/drivers/edac/mce_amd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/mce_amd.c	2011-05-19 00:06:34.000000000 -0400
@@ -594,6 +594,7 @@
 
 void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg)
 {
+	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u16 ec   = EC(m->status);
 	u8 xec   = XEC(m->status, 0x1f);
 	u32 nbsh = (u32)(m->status >> 32);
@@ -602,9 +603,8 @@
 	pr_emerg(HW_ERR "Northbridge Error (node %d", node_id);
 
 	/* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */
-	if ((boot_cpu_data.x86 == 0x10) &&
-	    (boot_cpu_data.x86_model > 7)) {
-		if (nbsh & K8_NBSH_ERR_CPU_VAL)
+	if (c->x86 == 0x10 && c->x86_model > 7) {
+		if (nbsh & NBSH_ERR_CPU_VAL)
 			core = nbsh & nb_err_cpumask;
 	} else {
 		u8 assoc_cpus = nbsh & nb_err_cpumask;
@@ -646,7 +646,7 @@
 	if (!fam_ops->nb_mce(ec, xec))
 		goto wrong_nb_mce;
 
-	if (boot_cpu_data.x86 == 0xf || boot_cpu_data.x86 == 0x10)
+	if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15)
 		if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder)
 			nb_bus_decoder(node_id, m, nbcfg);
 
diff -druN linux-libre-2.6.38-gnu/drivers/edac/mce_amd.h linux-libre-2.6.39-gnu/drivers/edac/mce_amd.h
--- linux-libre-2.6.38-gnu/drivers/edac/mce_amd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/mce_amd.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,19 +31,10 @@
 #define R4(x)				(((x) >> 4) & 0xf)
 #define R4_MSG(x)			((R4(x) < 9) ?  rrrr_msgs[R4(x)] : "Wrong R4!")
 
-#define K8_NBSH				0x4C
-
-#define K8_NBSH_VALID_BIT		BIT(31)
-#define K8_NBSH_OVERFLOW		BIT(30)
-#define K8_NBSH_UC_ERR			BIT(29)
-#define K8_NBSH_ERR_EN			BIT(28)
-#define K8_NBSH_MISCV			BIT(27)
-#define K8_NBSH_VALID_ERROR_ADDR	BIT(26)
-#define K8_NBSH_PCC			BIT(25)
-#define K8_NBSH_ERR_CPU_VAL		BIT(24)
-#define K8_NBSH_CECC			BIT(14)
-#define K8_NBSH_UECC			BIT(13)
-#define K8_NBSH_ERR_SCRUBER		BIT(8)
+/*
+ * F3x4C bits (MCi_STATUS' high half)
+ */
+#define NBSH_ERR_CPU_VAL		BIT(24)
 
 enum tt_ids {
 	TT_INSTR = 0,
@@ -86,17 +77,6 @@
 extern const char *ii_msgs[];
 
 /*
- * relevant NB regs
- */
-struct err_regs {
-	u32 nbcfg;
-	u32 nbsh;
-	u32 nbsl;
-	u32 nbeah;
-	u32 nbeal;
-};
-
-/*
  * per-family decoder ops
  */
 struct amd_decoder_ops {
diff -druN linux-libre-2.6.38-gnu/drivers/edac/mce_amd_inj.c linux-libre-2.6.39-gnu/drivers/edac/mce_amd_inj.c
--- linux-libre-2.6.38-gnu/drivers/edac/mce_amd_inj.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/mce_amd_inj.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,7 +90,7 @@
 
 	if (value > 5)
 		if (boot_cpu_data.x86 != 0x15 || value > 6) {
-			printk(KERN_ERR "Non-existant MCE bank: %lu\n", value);
+			printk(KERN_ERR "Non-existent MCE bank: %lu\n", value);
 			return -EINVAL;
 		}
 
diff -druN linux-libre-2.6.38-gnu/drivers/edac/mpc85xx_edac.c linux-libre-2.6.39-gnu/drivers/edac/mpc85xx_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/mpc85xx_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/mpc85xx_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -200,8 +200,7 @@
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_pci_err_probe(struct platform_device *op,
-					   const struct of_device_id *match)
+static int __devinit mpc85xx_pci_err_probe(struct platform_device *op)
 {
 	struct edac_pci_ctl_info *pci;
 	struct mpc85xx_pci_pdata *pdata;
@@ -338,7 +337,7 @@
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_pci_err_of_match);
 
-static struct of_platform_driver mpc85xx_pci_err_driver = {
+static struct platform_driver mpc85xx_pci_err_driver = {
 	.probe = mpc85xx_pci_err_probe,
 	.remove = __devexit_p(mpc85xx_pci_err_remove),
 	.driver = {
@@ -503,8 +502,7 @@
 	return IRQ_HANDLED;
 }
 
-static int __devinit mpc85xx_l2_err_probe(struct platform_device *op,
-					  const struct of_device_id *match)
+static int __devinit mpc85xx_l2_err_probe(struct platform_device *op)
 {
 	struct edac_device_ctl_info *edac_dev;
 	struct mpc85xx_l2_pdata *pdata;
@@ -656,7 +654,7 @@
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_l2_err_of_match);
 
-static struct of_platform_driver mpc85xx_l2_err_driver = {
+static struct platform_driver mpc85xx_l2_err_driver = {
 	.probe = mpc85xx_l2_err_probe,
 	.remove = mpc85xx_l2_err_remove,
 	.driver = {
@@ -956,8 +954,7 @@
 	}
 }
 
-static int __devinit mpc85xx_mc_err_probe(struct platform_device *op,
-					  const struct of_device_id *match)
+static int __devinit mpc85xx_mc_err_probe(struct platform_device *op)
 {
 	struct mem_ctl_info *mci;
 	struct mpc85xx_mc_pdata *pdata;
@@ -1136,7 +1133,7 @@
 };
 MODULE_DEVICE_TABLE(of, mpc85xx_mc_err_of_match);
 
-static struct of_platform_driver mpc85xx_mc_err_driver = {
+static struct platform_driver mpc85xx_mc_err_driver = {
 	.probe = mpc85xx_mc_err_probe,
 	.remove = mpc85xx_mc_err_remove,
 	.driver = {
@@ -1150,13 +1147,14 @@
 static void __init mpc85xx_mc_clear_rfxe(void *data)
 {
 	orig_hid1[smp_processor_id()] = mfspr(SPRN_HID1);
-	mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~0x20000));
+	mtspr(SPRN_HID1, (orig_hid1[smp_processor_id()] & ~HID1_RFXE));
 }
 #endif
 
 static int __init mpc85xx_mc_init(void)
 {
 	int res = 0;
+	u32 pvr = 0;
 
 	printk(KERN_INFO "Freescale(R) MPC85xx EDAC driver, "
 	       "(C) 2006 Montavista Software\n");
@@ -1171,27 +1169,32 @@
 		break;
 	}
 
-	res = of_register_platform_driver(&mpc85xx_mc_err_driver);
+	res = platform_driver_register(&mpc85xx_mc_err_driver);
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "MC fails to register\n");
 
-	res = of_register_platform_driver(&mpc85xx_l2_err_driver);
+	res = platform_driver_register(&mpc85xx_l2_err_driver);
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "L2 fails to register\n");
 
 #ifdef CONFIG_PCI
-	res = of_register_platform_driver(&mpc85xx_pci_err_driver);
+	res = platform_driver_register(&mpc85xx_pci_err_driver);
 	if (res)
 		printk(KERN_WARNING EDAC_MOD_STR "PCI fails to register\n");
 #endif
 
 #ifdef CONFIG_FSL_SOC_BOOKE
-	/*
-	 * need to clear HID1[RFXE] to disable machine check int
-	 * so we can catch it
-	 */
-	if (edac_op_state == EDAC_OPSTATE_INT)
-		on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
+	pvr = mfspr(SPRN_PVR);
+
+	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
+	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
+		/*
+		 * need to clear HID1[RFXE] to disable machine check int
+		 * so we can catch it
+		 */
+		if (edac_op_state == EDAC_OPSTATE_INT)
+			on_each_cpu(mpc85xx_mc_clear_rfxe, NULL, 0);
+	}
 #endif
 
 	return 0;
@@ -1209,13 +1212,18 @@
 static void __exit mpc85xx_mc_exit(void)
 {
 #ifdef CONFIG_FSL_SOC_BOOKE
-	on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
+	u32 pvr = mfspr(SPRN_PVR);
+
+	if ((PVR_VER(pvr) == PVR_VER_E500V1) ||
+	    (PVR_VER(pvr) == PVR_VER_E500V2)) {
+		on_each_cpu(mpc85xx_mc_restore_hid1, NULL, 0);
+	}
 #endif
 #ifdef CONFIG_PCI
-	of_unregister_platform_driver(&mpc85xx_pci_err_driver);
+	platform_driver_unregister(&mpc85xx_pci_err_driver);
 #endif
-	of_unregister_platform_driver(&mpc85xx_l2_err_driver);
-	of_unregister_platform_driver(&mpc85xx_mc_err_driver);
+	platform_driver_unregister(&mpc85xx_l2_err_driver);
+	platform_driver_unregister(&mpc85xx_mc_err_driver);
 }
 
 module_exit(mpc85xx_mc_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/edac/ppc4xx_edac.c linux-libre-2.6.39-gnu/drivers/edac/ppc4xx_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/ppc4xx_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/ppc4xx_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -184,8 +184,7 @@
 
 /* Function Prototypes */
 
-static int ppc4xx_edac_probe(struct platform_device *device,
-			     const struct of_device_id *device_id);
+static int ppc4xx_edac_probe(struct platform_device *device)
 static int ppc4xx_edac_remove(struct platform_device *device);
 
 /* Global Variables */
@@ -201,7 +200,7 @@
 	{ }
 };
 
-static struct of_platform_driver ppc4xx_edac_driver = {
+static struct platform_driver ppc4xx_edac_driver = {
 	.probe			= ppc4xx_edac_probe,
 	.remove			= ppc4xx_edac_remove,
 	.driver = {
@@ -997,9 +996,6 @@
  *       initialized.
  * @op: A pointer to the OpenFirmware device tree node associated
  *      with the controller this EDAC instance is bound to.
- * @match: A pointer to the OpenFirmware device tree match
- *         information associated with the controller this EDAC instance
- *         is bound to.
  * @dcr_host: A pointer to the DCR data containing the DCR mapping
  *            for this controller instance.
  * @mcopt1: The 32-bit Memory Controller Option 1 register value
@@ -1015,7 +1011,6 @@
 static int __devinit
 ppc4xx_edac_mc_init(struct mem_ctl_info *mci,
 		    struct platform_device *op,
-		    const struct of_device_id *match,
 		    const dcr_host_t *dcr_host,
 		    u32 mcopt1)
 {
@@ -1024,7 +1019,7 @@
 	struct ppc4xx_edac_pdata *pdata = NULL;
 	const struct device_node *np = op->dev.of_node;
 
-	if (match == NULL)
+	if (of_match_device(ppc4xx_edac_match, &op->dev) == NULL)
 		return -EINVAL;
 
 	/* Initial driver pointers and private data */
@@ -1227,9 +1222,6 @@
  * ppc4xx_edac_probe - check controller and bind driver
  * @op: A pointer to the OpenFirmware device tree node associated
  *      with the controller being probed for driver binding.
- * @match: A pointer to the OpenFirmware device tree match
- *         information associated with the controller being probed
- *         for driver binding.
  *
  * This routine probes a specific ibm,sdram-4xx-ddr2 controller
  * instance for binding with the driver.
@@ -1237,8 +1229,7 @@
  * Returns 0 if the controller instance was successfully bound to the
  * driver; otherwise, < 0 on error.
  */
-static int __devinit
-ppc4xx_edac_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit ppc4xx_edac_probe(struct platform_device *op)
 {
 	int status = 0;
 	u32 mcopt1, memcheck;
@@ -1304,7 +1295,7 @@
 		goto done;
 	}
 
-	status = ppc4xx_edac_mc_init(mci, op, match, &dcr_host, mcopt1);
+	status = ppc4xx_edac_mc_init(mci, op, &dcr_host, mcopt1);
 
 	if (status) {
 		ppc4xx_edac_mc_printk(KERN_ERR, mci,
@@ -1421,7 +1412,7 @@
 
 	ppc4xx_edac_opstate_init();
 
-	return of_register_platform_driver(&ppc4xx_edac_driver);
+	return platform_driver_register(&ppc4xx_edac_driver);
 }
 
 /**
@@ -1434,7 +1425,7 @@
 static void __exit
 ppc4xx_edac_exit(void)
 {
-	of_unregister_platform_driver(&ppc4xx_edac_driver);
+	platform_driver_unregister(&ppc4xx_edac_driver);
 }
 
 module_init(ppc4xx_edac_init);
diff -druN linux-libre-2.6.38-gnu/drivers/edac/r82600_edac.c linux-libre-2.6.39-gnu/drivers/edac/r82600_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/r82600_edac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/edac/r82600_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -120,7 +120,7 @@
 				 *        write 0=NOP
 				 */
 
-#define R82600_DRBA	0x60	/* + 0x60..0x63 SDRAM Row Boundry Address
+#define R82600_DRBA	0x60	/* + 0x60..0x63 SDRAM Row Boundary Address
 				 *  Registers
 				 *
 				 * 7:0  Address lines 30:24 - upper limit of
@@ -217,7 +217,7 @@
 {
 	struct csrow_info *csrow;
 	int index;
-	u8 drbar;		/* SDRAM Row Boundry Address Register */
+	u8 drbar;		/* SDRAM Row Boundary Address Register */
 	u32 row_high_limit, row_high_limit_last;
 	u32 reg_sdram, ecc_on, row_base;
 
@@ -236,7 +236,7 @@
 		row_high_limit = ((u32) drbar << 24);
 /*		row_high_limit = ((u32)drbar << 24) | 0xffffffUL; */
 
-		debugf1("%s() Row=%d, Boundry Address=%#0x, Last = %#0x\n",
+		debugf1("%s() Row=%d, Boundary Address=%#0x, Last = %#0x\n",
 			__func__, index, row_high_limit, row_high_limit_last);
 
 		/* Empty row [p.57] */
diff -druN linux-libre-2.6.38-gnu/drivers/edac/tile_edac.c linux-libre-2.6.39-gnu/drivers/edac/tile_edac.c
--- linux-libre-2.6.38-gnu/drivers/edac/tile_edac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/edac/tile_edac.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,254 @@
+/*
+ * Copyright 2011 Tilera 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
+ *   as published by the Free Software Foundation, version 2.
+ *
+ *   This program is distributed in the hope that it will be useful, but
+ *   WITHOUT ANY WARRANTY; without even the implied warranty of
+ *   MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ *   NON INFRINGEMENT.  See the GNU General Public License for
+ *   more details.
+ * Tilera-specific EDAC driver.
+ *
+ * This source code is derived from the following driver:
+ *
+ * Cell MIC driver for ECC counting
+ *
+ * Copyright 2007 Benjamin Herrenschmidt, IBM Corp.
+ *                <benh@kernel.crashing.org>
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/uaccess.h>
+#include <linux/edac.h>
+#include <hv/hypervisor.h>
+#include <hv/drv_mshim_intf.h>
+
+#include "edac_core.h"
+
+#define DRV_NAME	"tile-edac"
+
+/* Number of cs_rows needed per memory controller on TILEPro. */
+#define TILE_EDAC_NR_CSROWS	1
+
+/* Number of channels per memory controller on TILEPro. */
+#define TILE_EDAC_NR_CHANS	1
+
+/* Granularity of reported error in bytes on TILEPro. */
+#define TILE_EDAC_ERROR_GRAIN	8
+
+/* TILE processor has multiple independent memory controllers. */
+struct platform_device *mshim_pdev[TILE_MAX_MSHIMS];
+
+struct tile_edac_priv {
+	int		hv_devhdl;	/* Hypervisor device handle. */
+	int		node;		/* Memory controller instance #. */
+	unsigned int	ce_count;	/*
+					 * Correctable-error counter
+					 * kept by the driver.
+					 */
+};
+
+static void tile_edac_check(struct mem_ctl_info *mci)
+{
+	struct tile_edac_priv	*priv = mci->pvt_info;
+	struct mshim_mem_error	mem_error;
+
+	if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_error,
+		sizeof(struct mshim_mem_error), MSHIM_MEM_ERROR_OFF) !=
+		sizeof(struct mshim_mem_error)) {
+		pr_err(DRV_NAME ": MSHIM_MEM_ERROR_OFF pread failure.\n");
+		return;
+	}
+
+	/* Check if the current error count is different from the saved one. */
+	if (mem_error.sbe_count != priv->ce_count) {
+		dev_dbg(mci->dev, "ECC CE err on node %d\n", priv->node);
+		priv->ce_count = mem_error.sbe_count;
+		edac_mc_handle_ce(mci, 0, 0, 0, 0, 0, mci->ctl_name);
+	}
+}
+
+/*
+ * Initialize the 'csrows' table within the mci control structure with the
+ * addressing of memory.
+ */
+static int __devinit tile_edac_init_csrows(struct mem_ctl_info *mci)
+{
+	struct csrow_info	*csrow = &mci->csrows[0];
+	struct tile_edac_priv	*priv = mci->pvt_info;
+	struct mshim_mem_info	mem_info;
+
+	if (hv_dev_pread(priv->hv_devhdl, 0, (HV_VirtAddr)&mem_info,
+		sizeof(struct mshim_mem_info), MSHIM_MEM_INFO_OFF) !=
+		sizeof(struct mshim_mem_info)) {
+		pr_err(DRV_NAME ": MSHIM_MEM_INFO_OFF pread failure.\n");
+		return -1;
+	}
+
+	if (mem_info.mem_ecc)
+		csrow->edac_mode = EDAC_SECDED;
+	else
+		csrow->edac_mode = EDAC_NONE;
+	switch (mem_info.mem_type) {
+	case DDR2:
+		csrow->mtype = MEM_DDR2;
+		break;
+
+	case DDR3:
+		csrow->mtype = MEM_DDR3;
+		break;
+
+	default:
+		return -1;
+	}
+
+	csrow->first_page = 0;
+	csrow->nr_pages = mem_info.mem_size >> PAGE_SHIFT;
+	csrow->last_page = csrow->first_page + csrow->nr_pages - 1;
+	csrow->grain = TILE_EDAC_ERROR_GRAIN;
+	csrow->dtype = DEV_UNKNOWN;
+
+	return 0;
+}
+
+static int __devinit tile_edac_mc_probe(struct platform_device *pdev)
+{
+	char			hv_file[32];
+	int			hv_devhdl;
+	struct mem_ctl_info	*mci;
+	struct tile_edac_priv	*priv;
+	int			rc;
+
+	sprintf(hv_file, "mshim/%d", pdev->id);
+	hv_devhdl = hv_dev_open((HV_VirtAddr)hv_file, 0);
+	if (hv_devhdl < 0)
+		return -EINVAL;
+
+	/* A TILE MC has a single channel and one chip-select row. */
+	mci = edac_mc_alloc(sizeof(struct tile_edac_priv),
+		TILE_EDAC_NR_CSROWS, TILE_EDAC_NR_CHANS, pdev->id);
+	if (mci == NULL)
+		return -ENOMEM;
+	priv = mci->pvt_info;
+	priv->node = pdev->id;
+	priv->hv_devhdl = hv_devhdl;
+
+	mci->dev = &pdev->dev;
+	mci->mtype_cap = MEM_FLAG_DDR2;
+	mci->edac_ctl_cap = EDAC_FLAG_SECDED;
+
+	mci->mod_name = DRV_NAME;
+	mci->ctl_name = "TILEPro_Memory_Controller";
+	mci->dev_name = dev_name(&pdev->dev);
+	mci->edac_check = tile_edac_check;
+
+	/*
+	 * Initialize the MC control structure 'csrows' table
+	 * with the mapping and control information.
+	 */
+	if (tile_edac_init_csrows(mci)) {
+		/* No csrows found. */
+		mci->edac_cap = EDAC_FLAG_NONE;
+	} else {
+		mci->edac_cap = EDAC_FLAG_SECDED;
+	}
+
+	platform_set_drvdata(pdev, mci);
+
+	/* Register with EDAC core */
+	rc = edac_mc_add_mc(mci);
+	if (rc) {
+		dev_err(&pdev->dev, "failed to register with EDAC core\n");
+		edac_mc_free(mci);
+		return rc;
+	}
+
+	return 0;
+}
+
+static int __devexit tile_edac_mc_remove(struct platform_device *pdev)
+{
+	struct mem_ctl_info *mci = platform_get_drvdata(pdev);
+
+	edac_mc_del_mc(&pdev->dev);
+	if (mci)
+		edac_mc_free(mci);
+	return 0;
+}
+
+static struct platform_driver tile_edac_mc_driver = {
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+	.probe		= tile_edac_mc_probe,
+	.remove		= __devexit_p(tile_edac_mc_remove),
+};
+
+/*
+ * Driver init routine.
+ */
+static int __init tile_edac_init(void)
+{
+	char	hv_file[32];
+	struct platform_device *pdev;
+	int i, err, num = 0;
+
+	/* Only support POLL mode. */
+	edac_op_state = EDAC_OPSTATE_POLL;
+
+	err = platform_driver_register(&tile_edac_mc_driver);
+	if (err)
+		return err;
+
+	for (i = 0; i < TILE_MAX_MSHIMS; i++) {
+		/*
+		 * Not all memory controllers are configured such as in the
+		 * case of a simulator. So we register only those mshims
+		 * that are configured by the hypervisor.
+		 */
+		sprintf(hv_file, "mshim/%d", i);
+		if (hv_dev_open((HV_VirtAddr)hv_file, 0) < 0)
+			continue;
+
+		pdev = platform_device_register_simple(DRV_NAME, i, NULL, 0);
+		if (IS_ERR(pdev))
+			continue;
+		mshim_pdev[i] = pdev;
+		num++;
+	}
+
+	if (num == 0) {
+		platform_driver_unregister(&tile_edac_mc_driver);
+		return -ENODEV;
+	}
+	return 0;
+}
+
+/*
+ * Driver cleanup routine.
+ */
+static void __exit tile_edac_exit(void)
+{
+	int i;
+
+	for (i = 0; i < TILE_MAX_MSHIMS; i++) {
+		struct platform_device *pdev = mshim_pdev[i];
+		if (!pdev)
+			continue;
+
+		platform_set_drvdata(pdev, NULL);
+		platform_device_unregister(pdev);
+	}
+	platform_driver_unregister(&tile_edac_mc_driver);
+}
+
+module_init(tile_edac_init);
+module_exit(tile_edac_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/core-card.c linux-libre-2.6.39-gnu/drivers/firewire/core-card.c
--- linux-libre-2.6.38-gnu/drivers/firewire/core-card.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/core-card.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,6 +75,13 @@
 #define BIB_IRMC		((1) << 31)
 #define NODE_CAPABILITIES	0x0c0083c0 /* per IEEE 1394 clause 8.3.2.6.5.2 */
 
+/*
+ * IEEE-1394 specifies a default SPLIT_TIMEOUT value of 800 cycles (100 ms),
+ * but we have to make it longer because there are many devices whose firmware
+ * is just too slow for that.
+ */
+#define DEFAULT_SPLIT_TIMEOUT	(2 * 8000)
+
 #define CANON_OUI		0x000085
 
 static void generate_config_rom(struct fw_card *card, __be32 *config_rom)
@@ -233,7 +240,7 @@
 
 	/* Delay for 2s after last reset per IEEE 1394 clause 8.2.1. */
 	if (card->reset_jiffies != 0 &&
-	    time_is_after_jiffies(card->reset_jiffies + 2 * HZ)) {
+	    time_before64(get_jiffies_64(), card->reset_jiffies + 2 * HZ)) {
 		if (!schedule_delayed_work(&card->br_work, 2 * HZ))
 			fw_card_put(card);
 		return;
@@ -316,7 +323,8 @@
 	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));
+	grace = time_after64(get_jiffies_64(),
+			     card->reset_jiffies + DIV_ROUND_UP(HZ, 8));
 
 	if ((is_next_generation(generation, card->bm_generation) &&
 	     !card->bm_abdicate) ||
@@ -511,10 +519,11 @@
 	card->device = device;
 	card->current_tlabel = 0;
 	card->tlabel_mask = 0;
-	card->split_timeout_hi = 0;
-	card->split_timeout_lo = 800 << 19;
-	card->split_timeout_cycles = 800;
-	card->split_timeout_jiffies = DIV_ROUND_UP(HZ, 10);
+	card->split_timeout_hi = DEFAULT_SPLIT_TIMEOUT / 8000;
+	card->split_timeout_lo = (DEFAULT_SPLIT_TIMEOUT % 8000) << 19;
+	card->split_timeout_cycles = DEFAULT_SPLIT_TIMEOUT;
+	card->split_timeout_jiffies =
+			DIV_ROUND_UP(DEFAULT_SPLIT_TIMEOUT * HZ, 8000);
 	card->color = 0;
 	card->broadcast_channel = BROADCAST_CHANNEL_INITIAL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/core-cdev.c linux-libre-2.6.39-gnu/drivers/firewire/core-cdev.c
--- linux-libre-2.6.38-gnu/drivers/firewire/core-cdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/core-cdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,6 +64,7 @@
 	struct idr resource_idr;
 	struct list_head event_list;
 	wait_queue_head_t wait;
+	wait_queue_head_t tx_flush_wait;
 	u64 bus_reset_closure;
 
 	struct fw_iso_context *iso_context;
@@ -251,6 +252,7 @@
 	idr_init(&client->resource_idr);
 	INIT_LIST_HEAD(&client->event_list);
 	init_waitqueue_head(&client->wait);
+	init_waitqueue_head(&client->tx_flush_wait);
 	INIT_LIST_HEAD(&client->phy_receiver_link);
 	kref_init(&client->kref);
 
@@ -520,10 +522,6 @@
 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,
@@ -540,22 +538,9 @@
 		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);
-	}
+	idr_remove(&client->resource_idr, e->r.resource.handle);
+	if (client->in_shutdown)
+		wake_up(&client->tx_flush_wait);
 	spin_unlock_irqrestore(&client->lock, flags);
 
 	rsp->type = FW_CDEV_EVENT_RESPONSE;
@@ -575,7 +560,7 @@
 		queue_event(client, &e->event, rsp, sizeof(*rsp) + rsp->length,
 			    NULL, 0);
 
-	/* Drop the transaction callback's reference */
+	/* Drop the idr's reference */
 	client_put(client);
 }
 
@@ -614,9 +599,6 @@
 	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,
@@ -1223,7 +1205,8 @@
 	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)) {
+	    time_before64(get_jiffies_64(),
+			  client->device->card->reset_jiffies + HZ)) {
 		schedule_iso_resource(r, DIV_ROUND_UP(HZ, 3));
 		skip = true;
 	} else {
@@ -1678,6 +1661,25 @@
 	return ret;
 }
 
+static int is_outbound_transaction_resource(int id, void *p, void *data)
+{
+	struct client_resource *resource = p;
+
+	return resource->release == release_transaction;
+}
+
+static int has_outbound_transactions(struct client *client)
+{
+	int ret;
+
+	spin_lock_irq(&client->lock);
+	ret = idr_for_each(&client->resource_idr,
+			   is_outbound_transaction_resource, NULL);
+	spin_unlock_irq(&client->lock);
+
+	return ret;
+}
+
 static int shutdown_resource(int id, void *p, void *data)
 {
 	struct client_resource *resource = p;
@@ -1713,6 +1715,8 @@
 	client->in_shutdown = true;
 	spin_unlock_irq(&client->lock);
 
+	wait_event(client->tx_flush_wait, !has_outbound_transactions(client));
+
 	idr_for_each(&client->resource_idr, shutdown_resource, client);
 	idr_remove_all(&client->resource_idr);
 	idr_destroy(&client->resource_idr);
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/core-device.c linux-libre-2.6.39-gnu/drivers/firewire/core-device.c
--- linux-libre-2.6.38-gnu/drivers/firewire/core-device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/core-device.c	2011-05-19 00:06:34.000000000 -0400
@@ -747,7 +747,8 @@
 		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)
+	if (time_before64(get_jiffies_64(),
+			  device->card->reset_jiffies + SHUTDOWN_DELAY)
 	    && !list_empty(&device->card->link)) {
 		schedule_delayed_work(&device->work, SHUTDOWN_DELAY);
 		return;
@@ -954,8 +955,9 @@
 			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->link_on)
+				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);
@@ -1168,9 +1170,12 @@
 
 	switch (event) {
 	case FW_NODE_CREATED:
-	case FW_NODE_LINK_ON:
-		if (!node->link_on)
-			break;
+		/*
+		 * Attempt to scan the node, regardless whether its self ID has
+		 * the L (link active) flag set or not.  Some broken devices
+		 * send L=0 but have an up-and-running link; others send L=1
+		 * without actually having a link.
+		 */
  create:
 		device = kzalloc(sizeof(*device), GFP_ATOMIC);
 		if (device == NULL)
@@ -1213,6 +1218,7 @@
 		break;
 
 	case FW_NODE_INITIATED_RESET:
+	case FW_NODE_LINK_ON:
 		device = node->data;
 		if (device == NULL)
 			goto create;
@@ -1230,10 +1236,10 @@
 		break;
 
 	case FW_NODE_UPDATED:
-		if (!node->link_on || node->data == NULL)
+		device = node->data;
+		if (device == NULL)
 			break;
 
-		device = node->data;
 		device->node_id = node->node_id;
 		smp_wmb();  /* update node_id before generation */
 		device->generation = card->generation;
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/core.h linux-libre-2.6.39-gnu/drivers/firewire/core.h
--- linux-libre-2.6.38-gnu/drivers/firewire/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/core.h	2011-05-19 00:06:34.000000000 -0400
@@ -147,9 +147,6 @@
 /* -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 */
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/core-iso.c linux-libre-2.6.39-gnu/drivers/firewire/core-iso.c
--- linux-libre-2.6.38-gnu/drivers/firewire/core-iso.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/core-iso.c	2011-05-19 00:06:34.000000000 -0400
@@ -235,45 +235,45 @@
 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, ret = -EIO, retry = 5;
+	__be32 bit, all, old;
+	int channel, ret = -EIO, retry = 5;
 
 	old = all = allocate ? cpu_to_be32(~0) : 0;
 
-	for (i = 0; i < 32; i++) {
-		if (!(channels_mask & 1 << i))
+	for (channel = 0; channel < 32; channel++) {
+		if (!(channels_mask & 1 << channel))
 			continue;
 
 		ret = -EBUSY;
 
-		c = cpu_to_be32(1 << (31 - i));
-		if ((old & c) != (all & c))
+		bit = cpu_to_be32(1 << (31 - channel));
+		if ((old & bit) != (all & bit))
 			continue;
 
 		data[0] = old;
-		data[1] = old ^ c;
+		data[1] = old ^ bit;
 		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;
+			return allocate ? -EAGAIN : channel;
 
 		case RCODE_COMPLETE:
 			if (data[0] == old)
-				return i;
+				return channel;
 
 			old = data[0];
 
 			/* Is the IRM 1394a-2000 compliant? */
-			if ((data[0] & c) == (data[1] & c))
+			if ((data[0] & bit) == (data[1] & bit))
 				continue;
 
 			/* 1394-1995 IRM, fall through to retry. */
 		default:
 			if (retry) {
 				retry--;
-				i--;
+				channel--;
 			} else {
 				ret = -EIO;
 			}
@@ -362,3 +362,4 @@
 		*channel = ret;
 	}
 }
+EXPORT_SYMBOL(fw_iso_resource_manage);
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/core-topology.c linux-libre-2.6.39-gnu/drivers/firewire/core-topology.c
--- linux-libre-2.6.38-gnu/drivers/firewire/core-topology.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/core-topology.c	2011-05-19 00:06:34.000000000 -0400
@@ -545,7 +545,7 @@
 	 */
 	smp_wmb();
 	card->generation = generation;
-	card->reset_jiffies = jiffies;
+	card->reset_jiffies = get_jiffies_64();
 	card->bm_node_id  = 0xffff;
 	card->bm_abdicate = bm_abdicate;
 	fw_schedule_bm_work(card, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/Kconfig linux-libre-2.6.39-gnu/drivers/firewire/Kconfig
--- linux-libre-2.6.38-gnu/drivers/firewire/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,8 @@
 	  The following cards are known to be based on PCILynx or PCILynx-2:
 	  IOI IOI-1394TT (PCI card), Unibrain Fireboard 400 PCI Lynx-2
 	  (PCI card), Newer Technology FireWire 2 Go (CardBus card),
-	  Apple Power Mac G3 blue & white (onboard controller).
+	  Apple Power Mac G3 blue & white and G4 with PCI graphics
+	  (onboard controller).
 
 	  To compile this driver as a module, say M here:  The module will be
 	  called nosy.  Source code of a userspace interface to nosy, called
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/net.c linux-libre-2.6.39-gnu/drivers/firewire/net.c
--- linux-libre-2.6.38-gnu/drivers/firewire/net.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/net.c	2011-05-19 00:06:34.000000000 -0400
@@ -453,7 +453,7 @@
 	memcpy(pd->pbuf + frag_off, frag_buf, frag_len);
 
 	/*
-	 * Move list entry to beginnig of list so that oldest partial
+	 * Move list entry to beginning of list so that oldest partial
 	 * datagrams percolate to the end of the list
 	 */
 	list_move_tail(&pd->pd_link, &peer->pd_list);
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/ohci.c linux-libre-2.6.39-gnu/drivers/firewire/ohci.c
--- linux-libre-2.6.38-gnu/drivers/firewire/ohci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/ohci.c	2011-05-19 00:06:34.000000000 -0400
@@ -208,9 +208,11 @@
 	struct context at_request_ctx;
 	struct context at_response_ctx;
 
+	u32 it_context_support;
 	u32 it_context_mask;     /* unoccupied IT contexts */
 	struct iso_context *it_context_list;
 	u64 ir_context_channels; /* unoccupied channels */
+	u32 ir_context_support;
 	u32 ir_context_mask;     /* unoccupied IR contexts */
 	struct iso_context *ir_context_list;
 	u64 mc_channels; /* channels in use by the multichannel IR context */
@@ -338,7 +340,7 @@
 	    !(evt & OHCI1394_busReset))
 		return;
 
-	fw_notify("IRQ %08x%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", evt,
+	fw_notify("IRQ %08x%s%s%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"		: "",
@@ -351,6 +353,7 @@
 	    evt & OHCI1394_cycle64Seconds	? " cycle64Seconds"	: "",
 	    evt & OHCI1394_cycleInconsistent	? " cycleInconsistent"	: "",
 	    evt & OHCI1394_regAccessFail	? " regAccessFail"	: "",
+	    evt & OHCI1394_unrecoverableError	? " unrecoverableError"	: "",
 	    evt & OHCI1394_busReset		? " busReset"		: "",
 	    evt & ~(OHCI1394_selfIDComplete | OHCI1394_RQPkt |
 		    OHCI1394_RSPkt | OHCI1394_reqTxComplete |
@@ -1326,21 +1329,8 @@
 				     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: Test of IntEvent.busReset may no longer be necessary since we
-	 *        flush AT queues in bus_reset_tasklet.
-	 * FIXME: Document how the locking works.
-	 */
-	if (ohci->generation != packet->generation ||
-	    reg_read(ohci, OHCI1394_IntEventSet) & OHCI1394_busReset) {
+	/* FIXME: Document how the locking works. */
+	if (ohci->generation != packet->generation) {
 		if (packet->payload_mapped)
 			dma_unmap_single(ohci->card.device, payload_bus,
 					 packet->payload_length, DMA_TO_DEVICE);
@@ -1590,6 +1580,47 @@
 
 }
 
+static void detect_dead_context(struct fw_ohci *ohci,
+				const char *name, unsigned int regs)
+{
+	u32 ctl;
+
+	ctl = reg_read(ohci, CONTROL_SET(regs));
+	if (ctl & CONTEXT_DEAD) {
+#ifdef CONFIG_FIREWIRE_OHCI_DEBUG
+		fw_error("DMA context %s has stopped, error code: %s\n",
+			 name, evts[ctl & 0x1f]);
+#else
+		fw_error("DMA context %s has stopped, error code: %#x\n",
+			 name, ctl & 0x1f);
+#endif
+	}
+}
+
+static void handle_dead_contexts(struct fw_ohci *ohci)
+{
+	unsigned int i;
+	char name[8];
+
+	detect_dead_context(ohci, "ATReq", OHCI1394_AsReqTrContextBase);
+	detect_dead_context(ohci, "ATRsp", OHCI1394_AsRspTrContextBase);
+	detect_dead_context(ohci, "ARReq", OHCI1394_AsReqRcvContextBase);
+	detect_dead_context(ohci, "ARRsp", OHCI1394_AsRspRcvContextBase);
+	for (i = 0; i < 32; ++i) {
+		if (!(ohci->it_context_support & (1 << i)))
+			continue;
+		sprintf(name, "IT%u", i);
+		detect_dead_context(ohci, name, OHCI1394_IsoXmitContextBase(i));
+	}
+	for (i = 0; i < 32; ++i) {
+		if (!(ohci->ir_context_support & (1 << i)))
+			continue;
+		sprintf(name, "IR%u", i);
+		detect_dead_context(ohci, name, OHCI1394_IsoRcvContextBase(i));
+	}
+	/* TODO: maybe try to flush and restart the dead contexts */
+}
+
 static u32 cycle_timer_ticks(u32 cycle_timer)
 {
 	u32 ticks;
@@ -1904,6 +1935,9 @@
 			fw_notify("isochronous cycle inconsistent\n");
 	}
 
+	if (unlikely(event & OHCI1394_unrecoverableError))
+		handle_dead_contexts(ohci);
+
 	if (event & OHCI1394_cycle64Seconds) {
 		spin_lock(&ohci->lock);
 		update_bus_time(ohci);
@@ -2141,7 +2175,9 @@
 		OHCI1394_selfIDComplete |
 		OHCI1394_regAccessFail |
 		OHCI1394_cycle64Seconds |
-		OHCI1394_cycleInconsistent | OHCI1394_cycleTooLong |
+		OHCI1394_cycleInconsistent |
+		OHCI1394_unrecoverableError |
+		OHCI1394_cycleTooLong |
 		OHCI1394_masterIntEnable;
 	if (param_debug & OHCI_PARAM_DEBUG_BUSRESETS)
 		irqs |= OHCI1394_busReset;
@@ -2163,7 +2199,6 @@
 {
 	struct fw_ohci *ohci;
 	unsigned long flags;
-	int ret = -EBUSY;
 	__be32 *next_config_rom;
 	dma_addr_t uninitialized_var(next_config_rom_bus);
 
@@ -2204,22 +2239,37 @@
 
 	spin_lock_irqsave(&ohci->lock, flags);
 
+	/*
+	 * If there is not an already pending config_rom update,
+	 * push our new allocation into the ohci->next_config_rom
+	 * and then mark the local variable as null so that we
+	 * won't deallocate the new buffer.
+	 *
+	 * OTOH, if there is a pending config_rom update, just
+	 * use that buffer with the new config_rom data, and
+	 * let this routine free the unused DMA allocation.
+	 */
+
 	if (ohci->next_config_rom == NULL) {
 		ohci->next_config_rom = next_config_rom;
 		ohci->next_config_rom_bus = next_config_rom_bus;
+		next_config_rom = NULL;
+	}
 
-		copy_config_rom(ohci->next_config_rom, config_rom, length);
+	copy_config_rom(ohci->next_config_rom, config_rom, length);
 
-		ohci->next_header = config_rom[0];
-		ohci->next_config_rom[0] = 0;
+	ohci->next_header = config_rom[0];
+	ohci->next_config_rom[0] = 0;
 
-		reg_write(ohci, OHCI1394_ConfigROMmap,
-			  ohci->next_config_rom_bus);
-		ret = 0;
-	}
+	reg_write(ohci, OHCI1394_ConfigROMmap, ohci->next_config_rom_bus);
 
 	spin_unlock_irqrestore(&ohci->lock, flags);
 
+	/* If we didn't use the DMA allocation, delete it. */
+	if (next_config_rom != NULL)
+		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
+				  next_config_rom, next_config_rom_bus);
+
 	/*
 	 * Now initiate a bus reset to have the changes take
 	 * effect. We clean up the old config rom memory and DMA
@@ -2227,13 +2277,10 @@
 	 * controller could need to access it before the bus reset
 	 * takes effect.
 	 */
-	if (ret == 0)
-		fw_schedule_bus_reset(&ohci->card, true, true);
-	else
-		dma_free_coherent(ohci->card.device, CONFIG_ROM_SIZE,
-				  next_config_rom, next_config_rom_bus);
 
-	return ret;
+	fw_schedule_bus_reset(&ohci->card, true, true);
+
+	return 0;
 }
 
 static void ohci_send_request(struct fw_card *card, struct fw_packet *packet)
@@ -2657,6 +2704,10 @@
 	u32 control = IR_CONTEXT_ISOCH_HEADER, match;
 	int index;
 
+	/* the controller cannot start without any queued packets */
+	if (ctx->context.last->branch_address == 0)
+		return -ENODATA;
+
 	switch (ctx->base.type) {
 	case FW_ISO_CONTEXT_TRANSMIT:
 		index = ctx - ohci->it_context_list;
@@ -2715,6 +2766,7 @@
 	}
 	flush_writes(ohci);
 	context_stop(&ctx->context);
+	tasklet_kill(&ctx->context.tasklet);
 
 	return 0;
 }
@@ -3207,15 +3259,17 @@
 
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskSet, ~0);
 	ohci->ir_context_channels = ~0ULL;
-	ohci->ir_context_mask = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
+	ohci->ir_context_support = reg_read(ohci, OHCI1394_IsoRecvIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, ~0);
+	ohci->ir_context_mask = ohci->ir_context_support;
 	ohci->n_ir = hweight32(ohci->ir_context_mask);
 	size = sizeof(struct iso_context) * ohci->n_ir;
 	ohci->ir_context_list = kzalloc(size, GFP_KERNEL);
 
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskSet, ~0);
-	ohci->it_context_mask = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
+	ohci->it_context_support = reg_read(ohci, OHCI1394_IsoXmitIntMaskSet);
 	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, ~0);
+	ohci->it_context_mask = ohci->it_context_support;
 	ohci->n_it = hweight32(ohci->it_context_mask);
 	size = sizeof(struct iso_context) * ohci->n_it;
 	ohci->it_context_list = kzalloc(size, GFP_KERNEL);
@@ -3266,7 +3320,7 @@
  fail_disable:
 	pci_disable_device(dev);
  fail_free:
-	kfree(&ohci->card);
+	kfree(ohci);
 	pmac_ohci_off(dev);
  fail:
 	if (err == -ENOMEM)
@@ -3310,7 +3364,7 @@
 	pci_iounmap(dev, ohci->registers);
 	pci_release_region(dev, 0);
 	pci_disable_device(dev);
-	kfree(&ohci->card);
+	kfree(ohci);
 	pmac_ohci_off(dev);
 
 	fw_notify("Removed fw-ohci device.\n");
diff -druN linux-libre-2.6.38-gnu/drivers/firewire/sbp2.c linux-libre-2.6.39-gnu/drivers/firewire/sbp2.c
--- linux-libre-2.6.38-gnu/drivers/firewire/sbp2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firewire/sbp2.c	2011-05-19 00:06:34.000000000 -0400
@@ -472,18 +472,12 @@
 	 * 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.
-	 *
-	 * Here we treat RCODE_CANCELLED like RCODE_COMPLETE because some
-	 * OXUF936QSE firmwares occasionally respond after Split_Timeout and
-	 * complete the ORB just fine.  Note, we also get RCODE_CANCELLED
-	 * from sbp2_cancel_orbs() if fw_cancel_transaction() == 0.
 	 */
 	spin_lock_irqsave(&card->lock, flags);
 
 	if (orb->rcode == -1)
 		orb->rcode = rcode;
-
-	if (orb->rcode != RCODE_COMPLETE && orb->rcode != RCODE_CANCELLED) {
+	if (orb->rcode != RCODE_COMPLETE) {
 		list_del(&orb->link);
 		spin_unlock_irqrestore(&card->lock, flags);
 
@@ -532,7 +526,8 @@
 
 	list_for_each_entry_safe(orb, next, &list, link) {
 		retval = 0;
-		fw_cancel_transaction(device->card, &orb->t);
+		if (fw_cancel_transaction(device->card, &orb->t) == 0)
+			continue;
 
 		orb->rcode = RCODE_CANCELLED;
 		orb->callback(orb, NULL);
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/dcdbas.c linux-libre-2.6.39-gnu/drivers/firmware/dcdbas.c
--- linux-libre-2.6.38-gnu/drivers/firmware/dcdbas.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firmware/dcdbas.c	2011-05-19 00:06:34.000000000 -0400
@@ -268,8 +268,10 @@
 	}
 
 	/* generate SMI */
+	/* inb to force posted write through and make SMI happen now */
 	asm volatile (
-		"outb %b0,%w1"
+		"outb %b0,%w1\n"
+		"inb %w1"
 		: /* no output args */
 		: "a" (smi_cmd->command_code),
 		  "d" (smi_cmd->command_address),
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/dmi-sysfs.c linux-libre-2.6.39-gnu/drivers/firmware/dmi-sysfs.c
--- linux-libre-2.6.38-gnu/drivers/firmware/dmi-sysfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/firmware/dmi-sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,696 @@
+/*
+ * dmi-sysfs.c
+ *
+ * This module exports the DMI tables read-only to userspace through the
+ * sysfs file system.
+ *
+ * Data is currently found below
+ *    /sys/firmware/dmi/...
+ *
+ * DMI attributes are presented in attribute files with names
+ * formatted using %d-%d, so that the first integer indicates the
+ * structure type (0-255), and the second field is the instance of that
+ * entry.
+ *
+ * Copyright 2011 Google, Inc.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/kobject.h>
+#include <linux/dmi.h>
+#include <linux/capability.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/io.h>
+
+#define MAX_ENTRY_TYPE 255 /* Most of these aren't used, but we consider
+			      the top entry type is only 8 bits */
+
+struct dmi_sysfs_entry {
+	struct dmi_header dh;
+	struct kobject kobj;
+	int instance;
+	int position;
+	struct list_head list;
+	struct kobject *child;
+};
+
+/*
+ * Global list of dmi_sysfs_entry.  Even though this should only be
+ * manipulated at setup and teardown, the lazy nature of the kobject
+ * system means we get lazy removes.
+ */
+static LIST_HEAD(entry_list);
+static DEFINE_SPINLOCK(entry_list_lock);
+
+/* dmi_sysfs_attribute - Top level attribute. used by all entries. */
+struct dmi_sysfs_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct dmi_sysfs_entry *entry, char *buf);
+};
+
+#define DMI_SYSFS_ATTR(_entry, _name) \
+struct dmi_sysfs_attribute dmi_sysfs_attr_##_entry##_##_name = { \
+	.attr = {.name = __stringify(_name), .mode = 0400}, \
+	.show = dmi_sysfs_##_entry##_##_name, \
+}
+
+/*
+ * dmi_sysfs_mapped_attribute - Attribute where we require the entry be
+ * mapped in.  Use in conjunction with dmi_sysfs_specialize_attr_ops.
+ */
+struct dmi_sysfs_mapped_attribute {
+	struct attribute attr;
+	ssize_t (*show)(struct dmi_sysfs_entry *entry,
+			const struct dmi_header *dh,
+			char *buf);
+};
+
+#define DMI_SYSFS_MAPPED_ATTR(_entry, _name) \
+struct dmi_sysfs_mapped_attribute dmi_sysfs_attr_##_entry##_##_name = { \
+	.attr = {.name = __stringify(_name), .mode = 0400}, \
+	.show = dmi_sysfs_##_entry##_##_name, \
+}
+
+/*************************************************
+ * Generic DMI entry support.
+ *************************************************/
+static void dmi_entry_free(struct kobject *kobj)
+{
+	kfree(kobj);
+}
+
+static struct dmi_sysfs_entry *to_entry(struct kobject *kobj)
+{
+	return container_of(kobj, struct dmi_sysfs_entry, kobj);
+}
+
+static struct dmi_sysfs_attribute *to_attr(struct attribute *attr)
+{
+	return container_of(attr, struct dmi_sysfs_attribute, attr);
+}
+
+static ssize_t dmi_sysfs_attr_show(struct kobject *kobj,
+				   struct attribute *_attr, char *buf)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj);
+	struct dmi_sysfs_attribute *attr = to_attr(_attr);
+
+	/* DMI stuff is only ever admin visible */
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	return attr->show(entry, buf);
+}
+
+static const struct sysfs_ops dmi_sysfs_attr_ops = {
+	.show = dmi_sysfs_attr_show,
+};
+
+typedef ssize_t (*dmi_callback)(struct dmi_sysfs_entry *,
+				const struct dmi_header *dh, void *);
+
+struct find_dmi_data {
+	struct dmi_sysfs_entry	*entry;
+	dmi_callback		callback;
+	void			*private;
+	int			instance_countdown;
+	ssize_t			ret;
+};
+
+static void find_dmi_entry_helper(const struct dmi_header *dh,
+				  void *_data)
+{
+	struct find_dmi_data *data = _data;
+	struct dmi_sysfs_entry *entry = data->entry;
+
+	/* Is this the entry we want? */
+	if (dh->type != entry->dh.type)
+		return;
+
+	if (data->instance_countdown != 0) {
+		/* try the next instance? */
+		data->instance_countdown--;
+		return;
+	}
+
+	/*
+	 * Don't ever revisit the instance.  Short circuit later
+	 * instances by letting the instance_countdown run negative
+	 */
+	data->instance_countdown--;
+
+	/* Found the entry */
+	data->ret = data->callback(entry, dh, data->private);
+}
+
+/* State for passing the read parameters through dmi_find_entry() */
+struct dmi_read_state {
+	char *buf;
+	loff_t pos;
+	size_t count;
+};
+
+static ssize_t find_dmi_entry(struct dmi_sysfs_entry *entry,
+			      dmi_callback callback, void *private)
+{
+	struct find_dmi_data data = {
+		.entry = entry,
+		.callback = callback,
+		.private = private,
+		.instance_countdown = entry->instance,
+		.ret = -EIO,  /* To signal the entry disappeared */
+	};
+	int ret;
+
+	ret = dmi_walk(find_dmi_entry_helper, &data);
+	/* This shouldn't happen, but just in case. */
+	if (ret)
+		return -EINVAL;
+	return data.ret;
+}
+
+/*
+ * Calculate and return the byte length of the dmi entry identified by
+ * dh.  This includes both the formatted portion as well as the
+ * unformatted string space, including the two trailing nul characters.
+ */
+static size_t dmi_entry_length(const struct dmi_header *dh)
+{
+	const char *p = (const char *)dh;
+
+	p += dh->length;
+
+	while (p[0] || p[1])
+		p++;
+
+	return 2 + p - (const char *)dh;
+}
+
+/*************************************************
+ * Support bits for specialized DMI entry support
+ *************************************************/
+struct dmi_entry_attr_show_data {
+	struct attribute *attr;
+	char *buf;
+};
+
+static ssize_t dmi_entry_attr_show_helper(struct dmi_sysfs_entry *entry,
+					  const struct dmi_header *dh,
+					  void *_data)
+{
+	struct dmi_entry_attr_show_data *data = _data;
+	struct dmi_sysfs_mapped_attribute *attr;
+
+	attr = container_of(data->attr,
+			    struct dmi_sysfs_mapped_attribute, attr);
+	return attr->show(entry, dh, data->buf);
+}
+
+static ssize_t dmi_entry_attr_show(struct kobject *kobj,
+				   struct attribute *attr,
+				   char *buf)
+{
+	struct dmi_entry_attr_show_data data = {
+		.attr = attr,
+		.buf  = buf,
+	};
+	/* Find the entry according to our parent and call the
+	 * normalized show method hanging off of the attribute */
+	return find_dmi_entry(to_entry(kobj->parent),
+			      dmi_entry_attr_show_helper, &data);
+}
+
+static const struct sysfs_ops dmi_sysfs_specialize_attr_ops = {
+	.show = dmi_entry_attr_show,
+};
+
+/*************************************************
+ * Specialized DMI entry support.
+ *************************************************/
+
+/*** Type 15 - System Event Table ***/
+
+#define DMI_SEL_ACCESS_METHOD_IO8	0x00
+#define DMI_SEL_ACCESS_METHOD_IO2x8	0x01
+#define DMI_SEL_ACCESS_METHOD_IO16	0x02
+#define DMI_SEL_ACCESS_METHOD_PHYS32	0x03
+#define DMI_SEL_ACCESS_METHOD_GPNV	0x04
+
+struct dmi_system_event_log {
+	struct dmi_header header;
+	u16	area_length;
+	u16	header_start_offset;
+	u16	data_start_offset;
+	u8	access_method;
+	u8	status;
+	u32	change_token;
+	union {
+		struct {
+			u16 index_addr;
+			u16 data_addr;
+		} io;
+		u32	phys_addr32;
+		u16	gpnv_handle;
+		u32	access_method_address;
+	};
+	u8	header_format;
+	u8	type_descriptors_supported_count;
+	u8	per_log_type_descriptor_length;
+	u8	supported_log_type_descriptos[0];
+} __packed;
+
+#define DMI_SYSFS_SEL_FIELD(_field) \
+static ssize_t dmi_sysfs_sel_##_field(struct dmi_sysfs_entry *entry, \
+				      const struct dmi_header *dh, \
+				      char *buf) \
+{ \
+	struct dmi_system_event_log sel; \
+	if (sizeof(sel) > dmi_entry_length(dh)) \
+		return -EIO; \
+	memcpy(&sel, dh, sizeof(sel)); \
+	return sprintf(buf, "%u\n", sel._field); \
+} \
+static DMI_SYSFS_MAPPED_ATTR(sel, _field)
+
+DMI_SYSFS_SEL_FIELD(area_length);
+DMI_SYSFS_SEL_FIELD(header_start_offset);
+DMI_SYSFS_SEL_FIELD(data_start_offset);
+DMI_SYSFS_SEL_FIELD(access_method);
+DMI_SYSFS_SEL_FIELD(status);
+DMI_SYSFS_SEL_FIELD(change_token);
+DMI_SYSFS_SEL_FIELD(access_method_address);
+DMI_SYSFS_SEL_FIELD(header_format);
+DMI_SYSFS_SEL_FIELD(type_descriptors_supported_count);
+DMI_SYSFS_SEL_FIELD(per_log_type_descriptor_length);
+
+static struct attribute *dmi_sysfs_sel_attrs[] = {
+	&dmi_sysfs_attr_sel_area_length.attr,
+	&dmi_sysfs_attr_sel_header_start_offset.attr,
+	&dmi_sysfs_attr_sel_data_start_offset.attr,
+	&dmi_sysfs_attr_sel_access_method.attr,
+	&dmi_sysfs_attr_sel_status.attr,
+	&dmi_sysfs_attr_sel_change_token.attr,
+	&dmi_sysfs_attr_sel_access_method_address.attr,
+	&dmi_sysfs_attr_sel_header_format.attr,
+	&dmi_sysfs_attr_sel_type_descriptors_supported_count.attr,
+	&dmi_sysfs_attr_sel_per_log_type_descriptor_length.attr,
+	NULL,
+};
+
+
+static struct kobj_type dmi_system_event_log_ktype = {
+	.release = dmi_entry_free,
+	.sysfs_ops = &dmi_sysfs_specialize_attr_ops,
+	.default_attrs = dmi_sysfs_sel_attrs,
+};
+
+typedef u8 (*sel_io_reader)(const struct dmi_system_event_log *sel,
+			    loff_t offset);
+
+static DEFINE_MUTEX(io_port_lock);
+
+static u8 read_sel_8bit_indexed_io(const struct dmi_system_event_log *sel,
+				   loff_t offset)
+{
+	u8 ret;
+
+	mutex_lock(&io_port_lock);
+	outb((u8)offset, sel->io.index_addr);
+	ret = inb(sel->io.data_addr);
+	mutex_unlock(&io_port_lock);
+	return ret;
+}
+
+static u8 read_sel_2x8bit_indexed_io(const struct dmi_system_event_log *sel,
+				     loff_t offset)
+{
+	u8 ret;
+
+	mutex_lock(&io_port_lock);
+	outb((u8)offset, sel->io.index_addr);
+	outb((u8)(offset >> 8), sel->io.index_addr + 1);
+	ret = inb(sel->io.data_addr);
+	mutex_unlock(&io_port_lock);
+	return ret;
+}
+
+static u8 read_sel_16bit_indexed_io(const struct dmi_system_event_log *sel,
+				    loff_t offset)
+{
+	u8 ret;
+
+	mutex_lock(&io_port_lock);
+	outw((u16)offset, sel->io.index_addr);
+	ret = inb(sel->io.data_addr);
+	mutex_unlock(&io_port_lock);
+	return ret;
+}
+
+static sel_io_reader sel_io_readers[] = {
+	[DMI_SEL_ACCESS_METHOD_IO8]	= read_sel_8bit_indexed_io,
+	[DMI_SEL_ACCESS_METHOD_IO2x8]	= read_sel_2x8bit_indexed_io,
+	[DMI_SEL_ACCESS_METHOD_IO16]	= read_sel_16bit_indexed_io,
+};
+
+static ssize_t dmi_sel_raw_read_io(struct dmi_sysfs_entry *entry,
+				   const struct dmi_system_event_log *sel,
+				   char *buf, loff_t pos, size_t count)
+{
+	ssize_t wrote = 0;
+
+	sel_io_reader io_reader = sel_io_readers[sel->access_method];
+
+	while (count && pos < sel->area_length) {
+		count--;
+		*(buf++) = io_reader(sel, pos++);
+		wrote++;
+	}
+
+	return wrote;
+}
+
+static ssize_t dmi_sel_raw_read_phys32(struct dmi_sysfs_entry *entry,
+				       const struct dmi_system_event_log *sel,
+				       char *buf, loff_t pos, size_t count)
+{
+	u8 __iomem *mapped;
+	ssize_t wrote = 0;
+
+	mapped = ioremap(sel->access_method_address, sel->area_length);
+	if (!mapped)
+		return -EIO;
+
+	while (count && pos < sel->area_length) {
+		count--;
+		*(buf++) = readb(mapped + pos++);
+		wrote++;
+	}
+
+	iounmap(mapped);
+	return wrote;
+}
+
+static ssize_t dmi_sel_raw_read_helper(struct dmi_sysfs_entry *entry,
+				       const struct dmi_header *dh,
+				       void *_state)
+{
+	struct dmi_read_state *state = _state;
+	struct dmi_system_event_log sel;
+
+	if (sizeof(sel) > dmi_entry_length(dh))
+		return -EIO;
+
+	memcpy(&sel, dh, sizeof(sel));
+
+	switch (sel.access_method) {
+	case DMI_SEL_ACCESS_METHOD_IO8:
+	case DMI_SEL_ACCESS_METHOD_IO2x8:
+	case DMI_SEL_ACCESS_METHOD_IO16:
+		return dmi_sel_raw_read_io(entry, &sel, state->buf,
+					   state->pos, state->count);
+	case DMI_SEL_ACCESS_METHOD_PHYS32:
+		return dmi_sel_raw_read_phys32(entry, &sel, state->buf,
+					       state->pos, state->count);
+	case DMI_SEL_ACCESS_METHOD_GPNV:
+		pr_info("dmi-sysfs: GPNV support missing.\n");
+		return -EIO;
+	default:
+		pr_info("dmi-sysfs: Unknown access method %02x\n",
+			sel.access_method);
+		return -EIO;
+	}
+}
+
+static ssize_t dmi_sel_raw_read(struct file *filp, struct kobject *kobj,
+				struct bin_attribute *bin_attr,
+				char *buf, loff_t pos, size_t count)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj->parent);
+	struct dmi_read_state state = {
+		.buf = buf,
+		.pos = pos,
+		.count = count,
+	};
+
+	return find_dmi_entry(entry, dmi_sel_raw_read_helper, &state);
+}
+
+static struct bin_attribute dmi_sel_raw_attr = {
+	.attr = {.name = "raw_event_log", .mode = 0400},
+	.read = dmi_sel_raw_read,
+};
+
+static int dmi_system_event_log(struct dmi_sysfs_entry *entry)
+{
+	int ret;
+
+	entry->child = kzalloc(sizeof(*entry->child), GFP_KERNEL);
+	if (!entry->child)
+		return -ENOMEM;
+	ret = kobject_init_and_add(entry->child,
+				   &dmi_system_event_log_ktype,
+				   &entry->kobj,
+				   "system_event_log");
+	if (ret)
+		goto out_free;
+
+	ret = sysfs_create_bin_file(entry->child, &dmi_sel_raw_attr);
+	if (ret)
+		goto out_del;
+
+	return 0;
+
+out_del:
+	kobject_del(entry->child);
+out_free:
+	kfree(entry->child);
+	return ret;
+}
+
+/*************************************************
+ * Generic DMI entry support.
+ *************************************************/
+
+static ssize_t dmi_sysfs_entry_length(struct dmi_sysfs_entry *entry, char *buf)
+{
+	return sprintf(buf, "%d\n", entry->dh.length);
+}
+
+static ssize_t dmi_sysfs_entry_handle(struct dmi_sysfs_entry *entry, char *buf)
+{
+	return sprintf(buf, "%d\n", entry->dh.handle);
+}
+
+static ssize_t dmi_sysfs_entry_type(struct dmi_sysfs_entry *entry, char *buf)
+{
+	return sprintf(buf, "%d\n", entry->dh.type);
+}
+
+static ssize_t dmi_sysfs_entry_instance(struct dmi_sysfs_entry *entry,
+					char *buf)
+{
+	return sprintf(buf, "%d\n", entry->instance);
+}
+
+static ssize_t dmi_sysfs_entry_position(struct dmi_sysfs_entry *entry,
+					char *buf)
+{
+	return sprintf(buf, "%d\n", entry->position);
+}
+
+static DMI_SYSFS_ATTR(entry, length);
+static DMI_SYSFS_ATTR(entry, handle);
+static DMI_SYSFS_ATTR(entry, type);
+static DMI_SYSFS_ATTR(entry, instance);
+static DMI_SYSFS_ATTR(entry, position);
+
+static struct attribute *dmi_sysfs_entry_attrs[] = {
+	&dmi_sysfs_attr_entry_length.attr,
+	&dmi_sysfs_attr_entry_handle.attr,
+	&dmi_sysfs_attr_entry_type.attr,
+	&dmi_sysfs_attr_entry_instance.attr,
+	&dmi_sysfs_attr_entry_position.attr,
+	NULL,
+};
+
+static ssize_t dmi_entry_raw_read_helper(struct dmi_sysfs_entry *entry,
+					 const struct dmi_header *dh,
+					 void *_state)
+{
+	struct dmi_read_state *state = _state;
+	size_t entry_length;
+
+	entry_length = dmi_entry_length(dh);
+
+	return memory_read_from_buffer(state->buf, state->count,
+				       &state->pos, dh, entry_length);
+}
+
+static ssize_t dmi_entry_raw_read(struct file *filp,
+				  struct kobject *kobj,
+				  struct bin_attribute *bin_attr,
+				  char *buf, loff_t pos, size_t count)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj);
+	struct dmi_read_state state = {
+		.buf = buf,
+		.pos = pos,
+		.count = count,
+	};
+
+	return find_dmi_entry(entry, dmi_entry_raw_read_helper, &state);
+}
+
+static const struct bin_attribute dmi_entry_raw_attr = {
+	.attr = {.name = "raw", .mode = 0400},
+	.read = dmi_entry_raw_read,
+};
+
+static void dmi_sysfs_entry_release(struct kobject *kobj)
+{
+	struct dmi_sysfs_entry *entry = to_entry(kobj);
+	sysfs_remove_bin_file(&entry->kobj, &dmi_entry_raw_attr);
+	spin_lock(&entry_list_lock);
+	list_del(&entry->list);
+	spin_unlock(&entry_list_lock);
+	kfree(entry);
+}
+
+static struct kobj_type dmi_sysfs_entry_ktype = {
+	.release = dmi_sysfs_entry_release,
+	.sysfs_ops = &dmi_sysfs_attr_ops,
+	.default_attrs = dmi_sysfs_entry_attrs,
+};
+
+static struct kobject *dmi_kobj;
+static struct kset *dmi_kset;
+
+/* Global count of all instances seen.  Only for setup */
+static int __initdata instance_counts[MAX_ENTRY_TYPE + 1];
+
+/* Global positional count of all entries seen.  Only for setup */
+static int __initdata position_count;
+
+static void __init dmi_sysfs_register_handle(const struct dmi_header *dh,
+					     void *_ret)
+{
+	struct dmi_sysfs_entry *entry;
+	int *ret = _ret;
+
+	/* If a previous entry saw an error, short circuit */
+	if (*ret)
+		return;
+
+	/* Allocate and register a new entry into the entries set */
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry) {
+		*ret = -ENOMEM;
+		return;
+	}
+
+	/* Set the key */
+	memcpy(&entry->dh, dh, sizeof(*dh));
+	entry->instance = instance_counts[dh->type]++;
+	entry->position = position_count++;
+
+	entry->kobj.kset = dmi_kset;
+	*ret = kobject_init_and_add(&entry->kobj, &dmi_sysfs_entry_ktype, NULL,
+				    "%d-%d", dh->type, entry->instance);
+
+	if (*ret) {
+		kfree(entry);
+		return;
+	}
+
+	/* Thread on the global list for cleanup */
+	spin_lock(&entry_list_lock);
+	list_add_tail(&entry->list, &entry_list);
+	spin_unlock(&entry_list_lock);
+
+	/* Handle specializations by type */
+	switch (dh->type) {
+	case DMI_ENTRY_SYSTEM_EVENT_LOG:
+		*ret = dmi_system_event_log(entry);
+		break;
+	default:
+		/* No specialization */
+		break;
+	}
+	if (*ret)
+		goto out_err;
+
+	/* Create the raw binary file to access the entry */
+	*ret = sysfs_create_bin_file(&entry->kobj, &dmi_entry_raw_attr);
+	if (*ret)
+		goto out_err;
+
+	return;
+out_err:
+	kobject_put(entry->child);
+	kobject_put(&entry->kobj);
+	return;
+}
+
+static void cleanup_entry_list(void)
+{
+	struct dmi_sysfs_entry *entry, *next;
+
+	/* No locks, we are on our way out */
+	list_for_each_entry_safe(entry, next, &entry_list, list) {
+		kobject_put(entry->child);
+		kobject_put(&entry->kobj);
+	}
+}
+
+static int __init dmi_sysfs_init(void)
+{
+	int error = -ENOMEM;
+	int val;
+
+	/* Set up our directory */
+	dmi_kobj = kobject_create_and_add("dmi", firmware_kobj);
+	if (!dmi_kobj)
+		goto err;
+
+	dmi_kset = kset_create_and_add("entries", NULL, dmi_kobj);
+	if (!dmi_kset)
+		goto err;
+
+	val = 0;
+	error = dmi_walk(dmi_sysfs_register_handle, &val);
+	if (error)
+		goto err;
+	if (val) {
+		error = val;
+		goto err;
+	}
+
+	pr_debug("dmi-sysfs: loaded.\n");
+
+	return 0;
+err:
+	cleanup_entry_list();
+	kset_unregister(dmi_kset);
+	kobject_put(dmi_kobj);
+	return error;
+}
+
+/* clean up everything. */
+static void __exit dmi_sysfs_exit(void)
+{
+	pr_debug("dmi-sysfs: unloading.\n");
+	cleanup_entry_list();
+	kset_unregister(dmi_kset);
+	kobject_put(dmi_kobj);
+}
+
+module_init(dmi_sysfs_init);
+module_exit(dmi_sysfs_exit);
+
+MODULE_AUTHOR("Mike Waychison <mikew@google.com>");
+MODULE_DESCRIPTION("DMI sysfs support");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/efivars.c linux-libre-2.6.39-gnu/drivers/firmware/efivars.c
--- linux-libre-2.6.38-gnu/drivers/firmware/efivars.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firmware/efivars.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,17 +90,6 @@
 MODULE_VERSION(EFIVARS_VERSION);
 
 /*
- * efivars_lock protects two things:
- * 1) efivar_list - adds, removals, reads, writes
- * 2) efi.[gs]et_variable() calls.
- * It must not be held when creating sysfs entries or calling kmalloc.
- * efi.get_next_variable() is only called from efivars_init(),
- * which is protected by the BKL, so that path is safe.
- */
-static DEFINE_SPINLOCK(efivars_lock);
-static LIST_HEAD(efivar_list);
-
-/*
  * The maximum size of VariableName + Data = 1024
  * Therefore, it's reasonable to save that much
  * space in each part of the structure,
@@ -118,6 +107,7 @@
 
 
 struct efivar_entry {
+	struct efivars *efivars;
 	struct efi_variable var;
 	struct list_head list;
 	struct kobject kobj;
@@ -144,9 +134,10 @@
  * Prototype for sysfs creation function
  */
 static int
-efivar_create_sysfs_entry(unsigned long variable_name_size,
-				efi_char16_t *variable_name,
-				efi_guid_t *vendor_guid);
+efivar_create_sysfs_entry(struct efivars *efivars,
+			  unsigned long variable_name_size,
+			  efi_char16_t *variable_name,
+			  efi_guid_t *vendor_guid);
 
 /* Return the number of unicode characters in data */
 static unsigned long
@@ -170,18 +161,18 @@
 }
 
 static efi_status_t
-get_var_data(struct efi_variable *var)
+get_var_data(struct efivars *efivars, struct efi_variable *var)
 {
 	efi_status_t status;
 
-	spin_lock(&efivars_lock);
+	spin_lock(&efivars->lock);
 	var->DataSize = 1024;
-	status = efi.get_variable(var->VariableName,
-				&var->VendorGuid,
-				&var->Attributes,
-				&var->DataSize,
-				var->Data);
-	spin_unlock(&efivars_lock);
+	status = efivars->ops->get_variable(var->VariableName,
+					    &var->VendorGuid,
+					    &var->Attributes,
+					    &var->DataSize,
+					    var->Data);
+	spin_unlock(&efivars->lock);
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: get_variable() failed 0x%lx!\n",
 			status);
@@ -215,7 +206,7 @@
 	if (!entry || !buf)
 		return -EINVAL;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -238,7 +229,7 @@
 	if (!entry || !buf)
 		return -EINVAL;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -255,7 +246,7 @@
 	if (!entry || !buf)
 		return -EINVAL;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -270,6 +261,7 @@
 efivar_store_raw(struct efivar_entry *entry, const char *buf, size_t count)
 {
 	struct efi_variable *new_var, *var = &entry->var;
+	struct efivars *efivars = entry->efivars;
 	efi_status_t status = EFI_NOT_FOUND;
 
 	if (count != sizeof(struct efi_variable))
@@ -291,14 +283,14 @@
 		return -EINVAL;
 	}
 
-	spin_lock(&efivars_lock);
-	status = efi.set_variable(new_var->VariableName,
-					&new_var->VendorGuid,
-					new_var->Attributes,
-					new_var->DataSize,
-					new_var->Data);
+	spin_lock(&efivars->lock);
+	status = efivars->ops->set_variable(new_var->VariableName,
+					    &new_var->VendorGuid,
+					    new_var->Attributes,
+					    new_var->DataSize,
+					    new_var->Data);
 
-	spin_unlock(&efivars_lock);
+	spin_unlock(&efivars->lock);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
@@ -319,7 +311,7 @@
 	if (!entry || !buf)
 		return 0;
 
-	status = get_var_data(var);
+	status = get_var_data(entry->efivars, var);
 	if (status != EFI_SUCCESS)
 		return -EIO;
 
@@ -407,6 +399,7 @@
 			     char *buf, loff_t pos, size_t count)
 {
 	struct efi_variable *new_var = (struct efi_variable *)buf;
+	struct efivars *efivars = bin_attr->private;
 	struct efivar_entry *search_efivar, *n;
 	unsigned long strsize1, strsize2;
 	efi_status_t status = EFI_NOT_FOUND;
@@ -415,12 +408,12 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	spin_lock(&efivars_lock);
+	spin_lock(&efivars->lock);
 
 	/*
 	 * Does this variable already exist?
 	 */
-	list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
+	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
 		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 		strsize2 = utf8_strsize(new_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
@@ -433,28 +426,31 @@
 		}
 	}
 	if (found) {
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EINVAL;
 	}
 
 	/* now *really* create the variable via EFI */
-	status = efi.set_variable(new_var->VariableName,
-			&new_var->VendorGuid,
-			new_var->Attributes,
-			new_var->DataSize,
-			new_var->Data);
+	status = efivars->ops->set_variable(new_var->VariableName,
+					    &new_var->VendorGuid,
+					    new_var->Attributes,
+					    new_var->DataSize,
+					    new_var->Data);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 			status);
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EIO;
 	}
-	spin_unlock(&efivars_lock);
+	spin_unlock(&efivars->lock);
 
 	/* Create the entry in sysfs.  Locking is not required here */
-	status = efivar_create_sysfs_entry(utf8_strsize(new_var->VariableName,
-			1024), new_var->VariableName, &new_var->VendorGuid);
+	status = efivar_create_sysfs_entry(efivars,
+					   utf8_strsize(new_var->VariableName,
+							1024),
+					   new_var->VariableName,
+					   &new_var->VendorGuid);
 	if (status) {
 		printk(KERN_WARNING "efivars: variable created, but sysfs entry wasn't.\n");
 	}
@@ -466,6 +462,7 @@
 			     char *buf, loff_t pos, size_t count)
 {
 	struct efi_variable *del_var = (struct efi_variable *)buf;
+	struct efivars *efivars = bin_attr->private;
 	struct efivar_entry *search_efivar, *n;
 	unsigned long strsize1, strsize2;
 	efi_status_t status = EFI_NOT_FOUND;
@@ -474,12 +471,12 @@
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	spin_lock(&efivars_lock);
+	spin_lock(&efivars->lock);
 
 	/*
 	 * Does this variable already exist?
 	 */
-	list_for_each_entry_safe(search_efivar, n, &efivar_list, list) {
+	list_for_each_entry_safe(search_efivar, n, &efivars->list, list) {
 		strsize1 = utf8_strsize(search_efivar->var.VariableName, 1024);
 		strsize2 = utf8_strsize(del_var->VariableName, 1024);
 		if (strsize1 == strsize2 &&
@@ -492,44 +489,34 @@
 		}
 	}
 	if (!found) {
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EINVAL;
 	}
 	/* force the Attributes/DataSize to 0 to ensure deletion */
 	del_var->Attributes = 0;
 	del_var->DataSize = 0;
 
-	status = efi.set_variable(del_var->VariableName,
-			&del_var->VendorGuid,
-			del_var->Attributes,
-			del_var->DataSize,
-			del_var->Data);
+	status = efivars->ops->set_variable(del_var->VariableName,
+					    &del_var->VendorGuid,
+					    del_var->Attributes,
+					    del_var->DataSize,
+					    del_var->Data);
 
 	if (status != EFI_SUCCESS) {
 		printk(KERN_WARNING "efivars: set_variable() failed: status=%lx\n",
 			status);
-		spin_unlock(&efivars_lock);
+		spin_unlock(&efivars->lock);
 		return -EIO;
 	}
 	list_del(&search_efivar->list);
 	/* We need to release this lock before unregistering. */
-	spin_unlock(&efivars_lock);
+	spin_unlock(&efivars->lock);
 	efivar_unregister(search_efivar);
 
 	/* It's dead Jim.... */
 	return count;
 }
 
-static struct bin_attribute var_subsys_attr_new_var = {
-	.attr = {.name = "new_var", .mode = 0200},
-	.write = efivar_create,
-};
-
-static struct bin_attribute var_subsys_attr_del_var = {
-	.attr = {.name = "del_var", .mode = 0200},
-	.write = efivar_delete,
-};
-
 /*
  * Let's not leave out systab information that snuck into
  * the efivars driver
@@ -572,8 +559,6 @@
 	.attrs = efi_subsys_attrs,
 };
 
-
-static struct kset *vars_kset;
 static struct kobject *efi_kobj;
 
 /*
@@ -582,13 +567,14 @@
  *    variable_name_size = number of bytes required to hold
  *                         variable_name (not counting the NULL
  *                         character at the end.
- *    efivars_lock is not held on entry or exit.
+ *    efivars->lock is not held on entry or exit.
  * Returns 1 on failure, 0 on success
  */
 static int
-efivar_create_sysfs_entry(unsigned long variable_name_size,
-			efi_char16_t *variable_name,
-			efi_guid_t *vendor_guid)
+efivar_create_sysfs_entry(struct efivars *efivars,
+			  unsigned long variable_name_size,
+			  efi_char16_t *variable_name,
+			  efi_guid_t *vendor_guid)
 {
 	int i, short_name_size = variable_name_size / sizeof(efi_char16_t) + 38;
 	char *short_name;
@@ -603,6 +589,7 @@
 		return 1;
 	}
 
+	new_efivar->efivars = efivars;
 	memcpy(new_efivar->var.VariableName, variable_name,
 		variable_name_size);
 	memcpy(&(new_efivar->var.VendorGuid), vendor_guid, sizeof(efi_guid_t));
@@ -618,7 +605,7 @@
 	*(short_name + strlen(short_name)) = '-';
 	efi_guid_unparse(vendor_guid, short_name + strlen(short_name));
 
-	new_efivar->kobj.kset = vars_kset;
+	new_efivar->kobj.kset = efivars->kset;
 	i = kobject_init_and_add(&new_efivar->kobj, &efivar_ktype, NULL,
 				 "%s", short_name);
 	if (i) {
@@ -631,22 +618,95 @@
 	kfree(short_name);
 	short_name = NULL;
 
-	spin_lock(&efivars_lock);
-	list_add(&new_efivar->list, &efivar_list);
-	spin_unlock(&efivars_lock);
+	spin_lock(&efivars->lock);
+	list_add(&new_efivar->list, &efivars->list);
+	spin_unlock(&efivars->lock);
 
 	return 0;
 }
-/*
- * For now we register the efi subsystem with the firmware subsystem
- * and the vars subsystem with the efi subsystem.  In the future, it
- * might make sense to split off the efi subsystem into its own
- * driver, but for now only efivars will register with it, so just
- * include it here.
- */
 
-static int __init
-efivars_init(void)
+static int
+create_efivars_bin_attributes(struct efivars *efivars)
+{
+	struct bin_attribute *attr;
+	int error;
+
+	/* new_var */
+	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr)
+		return -ENOMEM;
+
+	attr->attr.name = "new_var";
+	attr->attr.mode = 0200;
+	attr->write = efivar_create;
+	attr->private = efivars;
+	efivars->new_var = attr;
+
+	/* del_var */
+	attr = kzalloc(sizeof(*attr), GFP_KERNEL);
+	if (!attr) {
+		error = -ENOMEM;
+		goto out_free;
+	}
+	attr->attr.name = "del_var";
+	attr->attr.mode = 0200;
+	attr->write = efivar_delete;
+	attr->private = efivars;
+	efivars->del_var = attr;
+
+	sysfs_bin_attr_init(efivars->new_var);
+	sysfs_bin_attr_init(efivars->del_var);
+
+	/* Register */
+	error = sysfs_create_bin_file(&efivars->kset->kobj,
+				      efivars->new_var);
+	if (error) {
+		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
+			" due to error %d\n", error);
+		goto out_free;
+	}
+	error = sysfs_create_bin_file(&efivars->kset->kobj,
+				      efivars->del_var);
+	if (error) {
+		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
+			" due to error %d\n", error);
+		sysfs_remove_bin_file(&efivars->kset->kobj,
+				      efivars->new_var);
+		goto out_free;
+	}
+
+	return 0;
+out_free:
+	kfree(efivars->new_var);
+	efivars->new_var = NULL;
+	kfree(efivars->new_var);
+	efivars->new_var = NULL;
+	return error;
+}
+
+void unregister_efivars(struct efivars *efivars)
+{
+	struct efivar_entry *entry, *n;
+
+	list_for_each_entry_safe(entry, n, &efivars->list, list) {
+		spin_lock(&efivars->lock);
+		list_del(&entry->list);
+		spin_unlock(&efivars->lock);
+		efivar_unregister(entry);
+	}
+	if (efivars->new_var)
+		sysfs_remove_bin_file(&efivars->kset->kobj, efivars->new_var);
+	if (efivars->del_var)
+		sysfs_remove_bin_file(&efivars->kset->kobj, efivars->del_var);
+	kfree(efivars->new_var);
+	kfree(efivars->del_var);
+	kset_unregister(efivars->kset);
+}
+EXPORT_SYMBOL_GPL(unregister_efivars);
+
+int register_efivars(struct efivars *efivars,
+		     const struct efivar_operations *ops,
+		     struct kobject *parent_kobj)
 {
 	efi_status_t status = EFI_NOT_FOUND;
 	efi_guid_t vendor_guid;
@@ -654,31 +714,21 @@
 	unsigned long variable_name_size = 1024;
 	int error = 0;
 
-	if (!efi_enabled)
-		return -ENODEV;
-
 	variable_name = kzalloc(variable_name_size, GFP_KERNEL);
 	if (!variable_name) {
 		printk(KERN_ERR "efivars: Memory allocation failed.\n");
 		return -ENOMEM;
 	}
 
-	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
-	       EFIVARS_DATE);
-
-	/* For now we'll register the efi directory at /sys/firmware/efi */
-	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
-	if (!efi_kobj) {
-		printk(KERN_ERR "efivars: Firmware registration failed.\n");
-		error = -ENOMEM;
-		goto out_free;
-	}
+	spin_lock_init(&efivars->lock);
+	INIT_LIST_HEAD(&efivars->list);
+	efivars->ops = ops;
 
-	vars_kset = kset_create_and_add("vars", NULL, efi_kobj);
-	if (!vars_kset) {
+	efivars->kset = kset_create_and_add("vars", NULL, parent_kobj);
+	if (!efivars->kset) {
 		printk(KERN_ERR "efivars: Subsystem registration failed.\n");
 		error = -ENOMEM;
-		goto out_firmware_unregister;
+		goto out;
 	}
 
 	/*
@@ -689,14 +739,15 @@
 	do {
 		variable_name_size = 1024;
 
-		status = efi.get_next_variable(&variable_name_size,
+		status = ops->get_next_variable(&variable_name_size,
 						variable_name,
 						&vendor_guid);
 		switch (status) {
 		case EFI_SUCCESS:
-			efivar_create_sysfs_entry(variable_name_size,
-							variable_name,
-							&vendor_guid);
+			efivar_create_sysfs_entry(efivars,
+						  variable_name_size,
+						  variable_name,
+						  &vendor_guid);
 			break;
 		case EFI_NOT_FOUND:
 			break;
@@ -708,35 +759,60 @@
 		}
 	} while (status != EFI_NOT_FOUND);
 
-	/*
-	 * Now add attributes to allow creation of new vars
-	 * and deletion of existing ones...
-	 */
-	error = sysfs_create_bin_file(&vars_kset->kobj,
-				      &var_subsys_attr_new_var);
-	if (error)
-		printk(KERN_ERR "efivars: unable to create new_var sysfs file"
-			" due to error %d\n", error);
-	error = sysfs_create_bin_file(&vars_kset->kobj,
-				      &var_subsys_attr_del_var);
+	error = create_efivars_bin_attributes(efivars);
 	if (error)
-		printk(KERN_ERR "efivars: unable to create del_var sysfs file"
-			" due to error %d\n", error);
+		unregister_efivars(efivars);
 
-	/* Don't forget the systab entry */
-	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
-	if (error)
-		printk(KERN_ERR "efivars: Sysfs attribute export failed with error %d.\n", error);
-	else
-		goto out_free;
+out:
+	kfree(variable_name);
 
-	kset_unregister(vars_kset);
+	return error;
+}
+EXPORT_SYMBOL_GPL(register_efivars);
 
-out_firmware_unregister:
-	kobject_put(efi_kobj);
+static struct efivars __efivars;
+static struct efivar_operations ops;
 
-out_free:
-	kfree(variable_name);
+/*
+ * For now we register the efi subsystem with the firmware subsystem
+ * and the vars subsystem with the efi subsystem.  In the future, it
+ * might make sense to split off the efi subsystem into its own
+ * driver, but for now only efivars will register with it, so just
+ * include it here.
+ */
+
+static int __init
+efivars_init(void)
+{
+	int error = 0;
+
+	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
+	       EFIVARS_DATE);
+
+	if (!efi_enabled)
+		return 0;
+
+	/* For now we'll register the efi directory at /sys/firmware/efi */
+	efi_kobj = kobject_create_and_add("efi", firmware_kobj);
+	if (!efi_kobj) {
+		printk(KERN_ERR "efivars: Firmware registration failed.\n");
+		return -ENOMEM;
+	}
+
+	ops.get_variable = efi.get_variable;
+	ops.set_variable = efi.set_variable;
+	ops.get_next_variable = efi.get_next_variable;
+	error = register_efivars(&__efivars, &ops, efi_kobj);
+
+	/* Don't forget the systab entry */
+	error = sysfs_create_group(efi_kobj, &efi_subsys_attr_group);
+	if (error) {
+		printk(KERN_ERR
+		       "efivars: Sysfs attribute export failed with error %d.\n",
+		       error);
+		unregister_efivars(&__efivars);
+		kobject_put(efi_kobj);
+	}
 
 	return error;
 }
@@ -744,16 +820,7 @@
 static void __exit
 efivars_exit(void)
 {
-	struct efivar_entry *entry, *n;
-
-	list_for_each_entry_safe(entry, n, &efivar_list, list) {
-		spin_lock(&efivars_lock);
-		list_del(&entry->list);
-		spin_unlock(&efivars_lock);
-		efivar_unregister(entry);
-	}
-
-	kset_unregister(vars_kset);
+	unregister_efivars(&__efivars);
 	kobject_put(efi_kobj);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/Kconfig linux-libre-2.6.39-gnu/drivers/firmware/Kconfig
--- linux-libre-2.6.38-gnu/drivers/firmware/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firmware/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -113,6 +113,17 @@
 	  information from userspace through /sys/class/dmi/id/ or if you want
 	  DMI-based module auto-loading.
 
+config DMI_SYSFS
+	tristate "DMI table support in sysfs"
+	depends on SYSFS && DMI
+	default n
+	help
+	  Say Y or M here to enable the exporting of the raw DMI table
+	  data via sysfs.  This is useful for consuming the data without
+	  requiring any access to /dev/mem at all.  Tables are found
+	  under /sys/firmware/dmi when this option is enabled and
+	  loaded.
+
 config ISCSI_IBFT_FIND
 	bool "iSCSI Boot Firmware Table Attributes"
 	depends on X86
@@ -134,4 +145,16 @@
 	  detect iSCSI boot parameters dynamically during system boot, say Y.
 	  Otherwise, say N.
 
+config SIGMA
+	tristate "SigmaStudio firmware loader"
+	depends on I2C
+	select CRC32
+	default n
+	help
+	  Enable helper functions for working with Analog Devices SigmaDSP
+	  parts and binary firmwares produced by Analog Devices SigmaStudio.
+
+	  If unsure, say N here.  Drivers that need these helpers will select
+	  this option automatically.
+
 endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/Makefile linux-libre-2.6.39-gnu/drivers/firmware/Makefile
--- linux-libre-2.6.38-gnu/drivers/firmware/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/firmware/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,7 @@
 # Makefile for the linux kernel.
 #
 obj-$(CONFIG_DMI)		+= dmi_scan.o
+obj-$(CONFIG_DMI_SYSFS)		+= dmi-sysfs.o
 obj-$(CONFIG_EDD)		+= edd.o
 obj-$(CONFIG_EFI_VARS)		+= efivars.o
 obj-$(CONFIG_EFI_PCDP)		+= pcdp.o
@@ -11,3 +12,4 @@
 obj-$(CONFIG_ISCSI_IBFT_FIND)	+= iscsi_ibft_find.o
 obj-$(CONFIG_ISCSI_IBFT)	+= iscsi_ibft.o
 obj-$(CONFIG_FIRMWARE_MEMMAP)	+= memmap.o
+obj-$(CONFIG_SIGMA)		+= sigma.o
diff -druN linux-libre-2.6.38-gnu/drivers/firmware/sigma.c linux-libre-2.6.39-gnu/drivers/firmware/sigma.c
--- linux-libre-2.6.38-gnu/drivers/firmware/sigma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/firmware/sigma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,115 @@
+/*
+ * Load Analog Devices SigmaStudio firmware files
+ *
+ * Copyright 2009-2011 Analog Devices Inc.
+ *
+ * Licensed under the GPL-2 or later.
+ */
+
+#include <linux/crc32.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/sigma.h>
+
+/* Return: 0==OK, <0==error, =1 ==no more actions */
+static int
+process_sigma_action(struct i2c_client *client, struct sigma_firmware *ssfw)
+{
+	struct sigma_action *sa = (void *)(ssfw->fw->data + ssfw->pos);
+	size_t len = sigma_action_len(sa);
+	int ret = 0;
+
+	pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
+		sa->instr, sa->addr, len);
+
+	switch (sa->instr) {
+	case SIGMA_ACTION_WRITEXBYTES:
+	case SIGMA_ACTION_WRITESINGLE:
+	case SIGMA_ACTION_WRITESAFELOAD:
+		if (ssfw->fw->size < ssfw->pos + len)
+			return -EINVAL;
+		ret = i2c_master_send(client, (void *)&sa->addr, len);
+		if (ret < 0)
+			return -EINVAL;
+		break;
+
+	case SIGMA_ACTION_DELAY:
+		ret = 0;
+		udelay(len);
+		len = 0;
+		break;
+
+	case SIGMA_ACTION_END:
+		return 1;
+
+	default:
+		return -EINVAL;
+	}
+
+	/* when arrive here ret=0 or sent data */
+	ssfw->pos += sigma_action_size(sa, len);
+	return ssfw->pos == ssfw->fw->size;
+}
+
+static int
+process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
+{
+	pr_debug("%s: processing %p\n", __func__, ssfw);
+
+	while (1) {
+		int ret = process_sigma_action(client, ssfw);
+		pr_debug("%s: action returned %i\n", __func__, ret);
+		if (ret == 1)
+			return 0;
+		else if (ret)
+			return ret;
+	}
+}
+
+int process_sigma_firmware(struct i2c_client *client, const char *name)
+{
+	int ret;
+	struct sigma_firmware_header *ssfw_head;
+	struct sigma_firmware ssfw;
+	const struct firmware *fw;
+	u32 crc;
+
+	pr_debug("%s: loading firmware %s\n", __func__, name);
+
+	/* first load the blob */
+	ret = request_firmware(&fw, name, &client->dev);
+	if (ret) {
+		pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
+		return ret;
+	}
+	ssfw.fw = fw;
+
+	/* then verify the header */
+	ret = -EINVAL;
+	if (fw->size < sizeof(*ssfw_head))
+		goto done;
+
+	ssfw_head = (void *)fw->data;
+	if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
+		goto done;
+
+	crc = crc32(0, fw->data, fw->size);
+	pr_debug("%s: crc=%x\n", __func__, crc);
+	if (crc != ssfw_head->crc)
+		goto done;
+
+	ssfw.pos = sizeof(*ssfw_head);
+
+	/* finally process all of the actions */
+	ret = process_sigma_actions(client, &ssfw);
+
+ done:
+	release_firmware(fw);
+
+	pr_debug("%s: loaded %s\n", __func__, name);
+
+	return ret;
+}
+EXPORT_SYMBOL(process_sigma_firmware);
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/74x164.c linux-libre-2.6.39-gnu/drivers/gpio/74x164.c
--- linux-libre-2.6.38-gnu/drivers/gpio/74x164.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/74x164.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,7 @@
 	return ret;
 }
 
-static int gen_74x164_remove(struct spi_device *spi)
+static int __devexit gen_74x164_remove(struct spi_device *spi)
 {
 	struct gen_74x164_chip *chip;
 	int ret;
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/ab8500-gpio.c linux-libre-2.6.39-gnu/drivers/gpio/ab8500-gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/ab8500-gpio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/gpio/ab8500-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,522 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2011
+ *
+ * Author: BIBEK BASU <bibek.basu@stericsson.com>
+ * License terms: GNU General Public License (GPL) version 2
+ *
+ * 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/slab.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/gpio.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500/gpio.h>
+
+/*
+ * GPIO registers offset
+ * Bank: 0x10
+ */
+#define AB8500_GPIO_SEL1_REG	0x00
+#define AB8500_GPIO_SEL2_REG	0x01
+#define AB8500_GPIO_SEL3_REG	0x02
+#define AB8500_GPIO_SEL4_REG	0x03
+#define AB8500_GPIO_SEL5_REG	0x04
+#define AB8500_GPIO_SEL6_REG	0x05
+
+#define AB8500_GPIO_DIR1_REG	0x10
+#define AB8500_GPIO_DIR2_REG	0x11
+#define AB8500_GPIO_DIR3_REG	0x12
+#define AB8500_GPIO_DIR4_REG	0x13
+#define AB8500_GPIO_DIR5_REG	0x14
+#define AB8500_GPIO_DIR6_REG	0x15
+
+#define AB8500_GPIO_OUT1_REG	0x20
+#define AB8500_GPIO_OUT2_REG	0x21
+#define AB8500_GPIO_OUT3_REG	0x22
+#define AB8500_GPIO_OUT4_REG	0x23
+#define AB8500_GPIO_OUT5_REG	0x24
+#define AB8500_GPIO_OUT6_REG	0x25
+
+#define AB8500_GPIO_PUD1_REG	0x30
+#define AB8500_GPIO_PUD2_REG	0x31
+#define AB8500_GPIO_PUD3_REG	0x32
+#define AB8500_GPIO_PUD4_REG	0x33
+#define AB8500_GPIO_PUD5_REG	0x34
+#define AB8500_GPIO_PUD6_REG	0x35
+
+#define AB8500_GPIO_IN1_REG	0x40
+#define AB8500_GPIO_IN2_REG	0x41
+#define AB8500_GPIO_IN3_REG	0x42
+#define AB8500_GPIO_IN4_REG	0x43
+#define AB8500_GPIO_IN5_REG	0x44
+#define AB8500_GPIO_IN6_REG	0x45
+#define AB8500_GPIO_ALTFUN_REG	0x45
+#define ALTFUN_REG_INDEX	6
+#define AB8500_NUM_GPIO		42
+#define AB8500_NUM_VIR_GPIO_IRQ	16
+
+enum ab8500_gpio_action {
+	NONE,
+	STARTUP,
+	SHUTDOWN,
+	MASK,
+	UNMASK
+};
+
+struct ab8500_gpio {
+	struct gpio_chip chip;
+	struct ab8500 *parent;
+	struct device *dev;
+	struct mutex lock;
+	u32 irq_base;
+	enum ab8500_gpio_action irq_action;
+	u16 rising;
+	u16 falling;
+};
+/**
+ * to_ab8500_gpio() - get the pointer to ab8500_gpio
+ * @chip:	Member of the structure ab8500_gpio
+ */
+static inline struct ab8500_gpio *to_ab8500_gpio(struct gpio_chip *chip)
+{
+	return container_of(chip, struct ab8500_gpio, chip);
+}
+
+static int ab8500_gpio_set_bits(struct gpio_chip *chip, u8 reg,
+					unsigned offset, int val)
+{
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	u8 pos = offset % 8;
+	int ret;
+
+	reg = reg + (offset / 8);
+	ret = abx500_mask_and_set_register_interruptible(ab8500_gpio->dev,
+				AB8500_MISC, reg, 1 << pos, val << pos);
+	if (ret < 0)
+		dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+	return ret;
+}
+/**
+ * ab8500_gpio_get() - Get the particular GPIO value
+ * @chip: Gpio device
+ * @offset: GPIO number to read
+ */
+static int ab8500_gpio_get(struct gpio_chip *chip, unsigned offset)
+{
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	u8 mask = 1 << (offset % 8);
+	u8 reg = AB8500_GPIO_OUT1_REG + (offset / 8);
+	int ret;
+	u8 data;
+	ret = abx500_get_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+						reg, &data);
+	if (ret < 0) {
+		dev_err(ab8500_gpio->dev, "%s read failed\n", __func__);
+		return ret;
+	}
+	return (data & mask) >> (offset % 8);
+}
+
+static void ab8500_gpio_set(struct gpio_chip *chip, unsigned offset, int val)
+{
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	int ret;
+	/* Write the data */
+	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, 1);
+	if (ret < 0)
+		dev_err(ab8500_gpio->dev, "%s write failed\n", __func__);
+}
+
+static int ab8500_gpio_direction_output(struct gpio_chip *chip, unsigned offset,
+					int val)
+{
+	int ret;
+	/* set direction as output */
+	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 1);
+	if (ret < 0)
+		return ret;
+	/* disable pull down */
+	ret = ab8500_gpio_set_bits(chip, AB8500_GPIO_PUD1_REG, offset, 1);
+	if (ret < 0)
+		return ret;
+	/* set the output as 1 or 0 */
+	return ab8500_gpio_set_bits(chip, AB8500_GPIO_OUT1_REG, offset, val);
+
+}
+
+static int ab8500_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
+{
+	/* set the register as input */
+	return ab8500_gpio_set_bits(chip, AB8500_GPIO_DIR1_REG, offset, 0);
+}
+
+static int ab8500_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
+{
+	/*
+	 * Only some GPIOs are interrupt capable, and they are
+	 * organized in discontiguous clusters:
+	 *
+	 *	GPIO6 to GPIO13
+	 *	GPIO24 and GPIO25
+	 *	GPIO36 to GPIO41
+	 */
+	static struct ab8500_gpio_irq_cluster {
+		int start;
+		int end;
+	} clusters[] = {
+		{.start = 6,  .end = 13},
+		{.start = 24, .end = 25},
+		{.start = 36, .end = 41},
+	};
+	struct ab8500_gpio *ab8500_gpio = to_ab8500_gpio(chip);
+	int base = ab8500_gpio->irq_base;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(clusters); i++) {
+		struct ab8500_gpio_irq_cluster *cluster = &clusters[i];
+
+		if (offset >= cluster->start && offset <= cluster->end)
+			return base + offset - cluster->start;
+
+		/* Advance by the number of gpios in this cluster */
+		base += cluster->end - cluster->start + 1;
+	}
+
+	return -EINVAL;
+}
+
+static struct gpio_chip ab8500gpio_chip = {
+	.label			= "ab8500_gpio",
+	.owner			= THIS_MODULE,
+	.direction_input	= ab8500_gpio_direction_input,
+	.get			= ab8500_gpio_get,
+	.direction_output	= ab8500_gpio_direction_output,
+	.set			= ab8500_gpio_set,
+	.to_irq			= ab8500_gpio_to_irq,
+};
+
+static unsigned int irq_to_rising(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+	int new_irq = offset +  AB8500_INT_GPIO6R
+			+ ab8500_gpio->parent->irq_base;
+	return new_irq;
+}
+
+static unsigned int irq_to_falling(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+	int new_irq = offset +  AB8500_INT_GPIO6F
+			+  ab8500_gpio->parent->irq_base;
+	return new_irq;
+
+}
+
+static unsigned int rising_to_irq(unsigned int irq, void *dev)
+{
+	struct ab8500_gpio *ab8500_gpio = dev;
+	int offset = irq - AB8500_INT_GPIO6R
+			- ab8500_gpio->parent->irq_base ;
+	int new_irq = offset + ab8500_gpio->irq_base;
+	return new_irq;
+}
+
+static unsigned int falling_to_irq(unsigned int irq, void *dev)
+{
+	struct ab8500_gpio *ab8500_gpio = dev;
+	int offset = irq - AB8500_INT_GPIO6F
+			- ab8500_gpio->parent->irq_base ;
+	int new_irq = offset + ab8500_gpio->irq_base;
+	return new_irq;
+
+}
+
+/*
+ * IRQ handler
+ */
+
+static irqreturn_t handle_rising(int irq, void *dev)
+{
+
+	handle_nested_irq(rising_to_irq(irq , dev));
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t handle_falling(int irq, void *dev)
+{
+
+	handle_nested_irq(falling_to_irq(irq, dev));
+	return IRQ_HANDLED;
+}
+
+static void ab8500_gpio_irq_lock(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	mutex_lock(&ab8500_gpio->lock);
+}
+
+static void ab8500_gpio_irq_sync_unlock(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+	bool rising = ab8500_gpio->rising & BIT(offset);
+	bool falling = ab8500_gpio->falling & BIT(offset);
+	int ret;
+
+	switch (ab8500_gpio->irq_action)	{
+	case STARTUP:
+		if (rising)
+			ret = request_threaded_irq(irq_to_rising(irq),
+					NULL, handle_rising,
+					IRQF_TRIGGER_RISING,
+					"ab8500-gpio-r", ab8500_gpio);
+		if (falling)
+			ret = request_threaded_irq(irq_to_falling(irq),
+				       NULL, handle_falling,
+				       IRQF_TRIGGER_FALLING,
+				       "ab8500-gpio-f", ab8500_gpio);
+		break;
+	case SHUTDOWN:
+		if (rising)
+			free_irq(irq_to_rising(irq), ab8500_gpio);
+		if (falling)
+			free_irq(irq_to_falling(irq), ab8500_gpio);
+		break;
+	case MASK:
+		if (rising)
+			disable_irq(irq_to_rising(irq));
+		if (falling)
+			disable_irq(irq_to_falling(irq));
+		break;
+	case UNMASK:
+		if (rising)
+			enable_irq(irq_to_rising(irq));
+		if (falling)
+			enable_irq(irq_to_falling(irq));
+		break;
+	case NONE:
+		break;
+	}
+	ab8500_gpio->irq_action = NONE;
+	ab8500_gpio->rising &= ~(BIT(offset));
+	ab8500_gpio->falling &= ~(BIT(offset));
+	mutex_unlock(&ab8500_gpio->lock);
+}
+
+
+static void ab8500_gpio_irq_mask(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = MASK;
+}
+
+static void ab8500_gpio_irq_unmask(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = UNMASK;
+}
+
+static int ab8500_gpio_irq_set_type(unsigned int irq, unsigned int type)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	int offset = irq - ab8500_gpio->irq_base;
+
+	if (type == IRQ_TYPE_EDGE_BOTH) {
+		ab8500_gpio->rising =  BIT(offset);
+		ab8500_gpio->falling = BIT(offset);
+	} else if (type == IRQ_TYPE_EDGE_RISING) {
+		ab8500_gpio->rising =  BIT(offset);
+	} else  {
+		ab8500_gpio->falling = BIT(offset);
+	}
+	return 0;
+}
+
+unsigned int ab8500_gpio_irq_startup(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = STARTUP;
+	return 0;
+}
+
+void ab8500_gpio_irq_shutdown(unsigned int irq)
+{
+	struct ab8500_gpio *ab8500_gpio = get_irq_chip_data(irq);
+	ab8500_gpio->irq_action = SHUTDOWN;
+}
+
+static struct irq_chip ab8500_gpio_irq_chip = {
+	.name			= "ab8500-gpio",
+	.startup		= ab8500_gpio_irq_startup,
+	.shutdown		= ab8500_gpio_irq_shutdown,
+	.bus_lock		= ab8500_gpio_irq_lock,
+	.bus_sync_unlock	= ab8500_gpio_irq_sync_unlock,
+	.mask			= ab8500_gpio_irq_mask,
+	.unmask			= ab8500_gpio_irq_unmask,
+	.set_type		= ab8500_gpio_irq_set_type,
+};
+
+static int ab8500_gpio_irq_init(struct ab8500_gpio *ab8500_gpio)
+{
+	u32 base = ab8500_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ ; irq++) {
+		set_irq_chip_data(irq, ab8500_gpio);
+		set_irq_chip_and_handler(irq, &ab8500_gpio_irq_chip,
+				handle_simple_irq);
+		set_irq_nested_thread(irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, IRQF_VALID);
+#else
+		set_irq_noprobe(irq);
+#endif
+	}
+
+	return 0;
+}
+
+static void ab8500_gpio_irq_remove(struct ab8500_gpio *ab8500_gpio)
+{
+	int base = ab8500_gpio->irq_base;
+	int irq;
+
+	for (irq = base; irq < base + AB8500_NUM_VIR_GPIO_IRQ; irq++) {
+#ifdef CONFIG_ARM
+		set_irq_flags(irq, 0);
+#endif
+		set_irq_chip_and_handler(irq, NULL, NULL);
+		set_irq_chip_data(irq, NULL);
+	}
+}
+
+static int __devinit ab8500_gpio_probe(struct platform_device *pdev)
+{
+	struct ab8500_platform_data *ab8500_pdata =
+				dev_get_platdata(pdev->dev.parent);
+	struct ab8500_gpio_platform_data *pdata;
+	struct ab8500_gpio *ab8500_gpio;
+	int ret;
+	int i;
+
+	pdata = ab8500_pdata->gpio;
+	if (!pdata)	{
+		dev_err(&pdev->dev, "gpio platform data missing\n");
+		return -ENODEV;
+	}
+
+	ab8500_gpio = kzalloc(sizeof(struct ab8500_gpio), GFP_KERNEL);
+	if (ab8500_gpio == NULL) {
+		dev_err(&pdev->dev, "failed to allocate memory\n");
+		return -ENOMEM;
+	}
+	ab8500_gpio->dev = &pdev->dev;
+	ab8500_gpio->parent = dev_get_drvdata(pdev->dev.parent);
+	ab8500_gpio->chip = ab8500gpio_chip;
+	ab8500_gpio->chip.ngpio = AB8500_NUM_GPIO;
+	ab8500_gpio->chip.dev = &pdev->dev;
+	ab8500_gpio->chip.base = pdata->gpio_base;
+	ab8500_gpio->irq_base = pdata->irq_base;
+	/* initialize the lock */
+	mutex_init(&ab8500_gpio->lock);
+	/*
+	 * AB8500 core will handle and clear the IRQ
+	 * configre GPIO based on config-reg value.
+	 * These values are for selecting the PINs as
+	 * GPIO or alternate function
+	 */
+	for (i = AB8500_GPIO_SEL1_REG; i <= AB8500_GPIO_SEL6_REG; i++)	{
+		ret = abx500_set_register_interruptible(ab8500_gpio->dev,
+				AB8500_MISC, i,
+				pdata->config_reg[i]);
+		if (ret < 0)
+			goto out_free;
+	}
+	ret = abx500_set_register_interruptible(ab8500_gpio->dev, AB8500_MISC,
+				AB8500_GPIO_ALTFUN_REG,
+				pdata->config_reg[ALTFUN_REG_INDEX]);
+	if (ret < 0)
+		goto out_free;
+
+	ret = ab8500_gpio_irq_init(ab8500_gpio);
+	if (ret)
+		goto out_free;
+	ret = gpiochip_add(&ab8500_gpio->chip);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to add gpiochip: %d\n",
+				ret);
+		goto out_rem_irq;
+	}
+	platform_set_drvdata(pdev, ab8500_gpio);
+	return 0;
+
+out_rem_irq:
+	ab8500_gpio_irq_remove(ab8500_gpio);
+out_free:
+	mutex_destroy(&ab8500_gpio->lock);
+	kfree(ab8500_gpio);
+	return ret;
+}
+
+/*
+ * ab8500_gpio_remove() - remove Ab8500-gpio driver
+ * @pdev :	Platform device registered
+ */
+static int __devexit ab8500_gpio_remove(struct platform_device *pdev)
+{
+	struct ab8500_gpio *ab8500_gpio = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = gpiochip_remove(&ab8500_gpio->chip);
+	if (ret < 0) {
+		dev_err(ab8500_gpio->dev, "unable to remove gpiochip:\
+				%d\n", ret);
+		return ret;
+	}
+
+	platform_set_drvdata(pdev, NULL);
+	mutex_destroy(&ab8500_gpio->lock);
+	kfree(ab8500_gpio);
+
+	return 0;
+}
+
+static struct platform_driver ab8500_gpio_driver = {
+	.driver = {
+		.name = "ab8500-gpio",
+		.owner = THIS_MODULE,
+	},
+	.probe = ab8500_gpio_probe,
+	.remove = __devexit_p(ab8500_gpio_remove),
+};
+
+static int __init ab8500_gpio_init(void)
+{
+	return platform_driver_register(&ab8500_gpio_driver);
+}
+arch_initcall(ab8500_gpio_init);
+
+static void __exit ab8500_gpio_exit(void)
+{
+	platform_driver_unregister(&ab8500_gpio_driver);
+}
+module_exit(ab8500_gpio_exit);
+
+MODULE_AUTHOR("BIBEK BASU <bibek.basu@stericsson.com>");
+MODULE_DESCRIPTION("Driver allows to use AB8500 unused pins\
+			to be used as GPIO");
+MODULE_ALIAS("AB8500 GPIO driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/adp5588-gpio.c linux-libre-2.6.39-gnu/drivers/gpio/adp5588-gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/adp5588-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/adp5588-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -289,10 +289,10 @@
 
 	for (gpio = 0; gpio < dev->gpio_chip.ngpio; gpio++) {
 		int irq = gpio + dev->irq_base;
-		set_irq_chip_data(irq, dev);
-		set_irq_chip_and_handler(irq, &adp5588_irq_chip,
+		irq_set_chip_data(irq, dev);
+		irq_set_chip_and_handler(irq, &adp5588_irq_chip,
 					 handle_level_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		/*
 		 * ARM needs us to explicitly flag the IRQ as VALID,
@@ -300,7 +300,7 @@
 		 */
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/cs5535-gpio.c linux-libre-2.6.39-gnu/drivers/gpio/cs5535-gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/cs5535-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/cs5535-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -373,7 +373,7 @@
 	return 0;
 }
 
-static struct platform_driver cs5535_gpio_drv = {
+static struct platform_driver cs5535_gpio_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -384,12 +384,12 @@
 
 static int __init cs5535_gpio_init(void)
 {
-	return platform_driver_register(&cs5535_gpio_drv);
+	return platform_driver_register(&cs5535_gpio_driver);
 }
 
 static void __exit cs5535_gpio_exit(void)
 {
-	platform_driver_unregister(&cs5535_gpio_drv);
+	platform_driver_unregister(&cs5535_gpio_driver);
 }
 
 module_init(cs5535_gpio_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/gpiolib.c linux-libre-2.6.39-gnu/drivers/gpio/gpiolib.c
--- linux-libre-2.6.38-gnu/drivers/gpio/gpiolib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/gpiolib.c	2011-05-19 00:06:34.000000000 -0400
@@ -1656,51 +1656,6 @@
 			chip->get
 				? (chip->get(chip, i) ? "hi" : "lo")
 				: "?  ");
-
-		if (!is_out) {
-			int		irq = gpio_to_irq(gpio);
-			struct irq_desc	*desc = irq_to_desc(irq);
-
-			/* This races with request_irq(), set_irq_type(),
-			 * and set_irq_wake() ... but those are "rare".
-			 *
-			 * More significantly, trigger type flags aren't
-			 * currently maintained by genirq.
-			 */
-			if (irq >= 0 && desc->action) {
-				char *trigger;
-
-				switch (desc->status & IRQ_TYPE_SENSE_MASK) {
-				case IRQ_TYPE_NONE:
-					trigger = "(default)";
-					break;
-				case IRQ_TYPE_EDGE_FALLING:
-					trigger = "edge-falling";
-					break;
-				case IRQ_TYPE_EDGE_RISING:
-					trigger = "edge-rising";
-					break;
-				case IRQ_TYPE_EDGE_BOTH:
-					trigger = "edge-both";
-					break;
-				case IRQ_TYPE_LEVEL_HIGH:
-					trigger = "level-high";
-					break;
-				case IRQ_TYPE_LEVEL_LOW:
-					trigger = "level-low";
-					break;
-				default:
-					trigger = "?trigger?";
-					break;
-				}
-
-				seq_printf(s, " irq-%d %s%s",
-					irq, trigger,
-					(desc->status & IRQ_WAKEUP)
-						? " wakeup" : "");
-			}
-		}
-
 		seq_printf(s, "\n");
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/janz-ttl.c linux-libre-2.6.39-gnu/drivers/gpio/janz-ttl.c
--- linux-libre-2.6.38-gnu/drivers/gpio/janz-ttl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/janz-ttl.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
@@ -149,7 +150,7 @@
 	struct resource *res;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = mfd_get_data(pdev);
 	if (!pdata) {
 		dev_err(dev, "no platform data\n");
 		ret = -ENXIO;
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/Kconfig linux-libre-2.6.39-gnu/drivers/gpio/Kconfig
--- linux-libre-2.6.38-gnu/drivers/gpio/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -100,18 +100,21 @@
 	  Say yes here to support the NEC VR4100 series General-purpose I/O Uint
 
 config GPIO_SCH
-	tristate "Intel SCH GPIO"
-	depends on GPIOLIB && PCI
+	tristate "Intel SCH/TunnelCreek GPIO"
+	depends on GPIOLIB && PCI && X86
 	select MFD_CORE
 	select LPC_SCH
 	help
-	  Say yes here to support GPIO interface on Intel Poulsbo SCH.
+	  Say yes here to support GPIO interface on Intel Poulsbo SCH
+	  or Intel Tunnel Creek processor.
 	  The Intel SCH contains a total of 14 GPIO pins. Ten GPIOs are
 	  powered by the core power rail and are turned off during sleep
 	  modes (S3 and higher). The remaining four GPIOs are powered by
 	  the Intel SCH suspend power supply. These GPIOs remain
 	  active during S3. The suspend powered GPIOs can be used to wake the
 	  system from the Suspend-to-RAM state.
+	  The Intel Tunnel Creek processor has 5 GPIOs powered by the
+	  core power rail and 9 from suspend power supply.
 
 	  This driver can also be built as a module. If so, the module
 	  will be called sch-gpio.
@@ -321,13 +324,13 @@
 
 config GPIO_LANGWELL
 	bool "Intel Langwell/Penwell GPIO support"
-	depends on PCI
+	depends on PCI && X86
 	help
 	  Say Y here to support Intel Langwell/Penwell GPIO.
 
 config GPIO_PCH
 	tristate "PCH GPIO of Intel Topcliff"
-	depends on PCI
+	depends on PCI && X86
 	help
 	  This driver is for PCH(Platform controller Hub) GPIO of Intel Topcliff
 	  which is an IOH(Input/Output Hub) for x86 embedded processor.
@@ -368,11 +371,11 @@
 	  GPIO driver for Maxim MAX7301 SPI-based GPIO expander.
 
 config GPIO_MCP23S08
-	tristate "Microchip MCP23S08 I/O expander"
+	tristate "Microchip MCP23Sxx I/O expander"
 	depends on SPI_MASTER
 	help
-	  SPI driver for Microchip MCP23S08 I/O expander.  This provides
-	  a GPIO interface supporting inputs and outputs.
+	  SPI driver for Microchip MCP23S08/MPC23S17 I/O expanders.
+	  This provides a GPIO interface supporting inputs and outputs.
 
 config GPIO_MC33880
 	tristate "Freescale MC33880 high-side/low-side switch"
@@ -411,4 +414,9 @@
 	  This driver provides support for driving the pins in output
 	  mode only. Input mode is not supported.
 
+config AB8500_GPIO
+	bool "ST-Ericsson AB8500 Mixed Signal Circuit gpio functions"
+	depends on AB8500_CORE && BROKEN
+	help
+	  Select this to enable the AB8500 IC GPIO driver
 endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/langwell_gpio.c linux-libre-2.6.39-gnu/drivers/gpio/langwell_gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/langwell_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/langwell_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -187,31 +187,28 @@
 
 static void lnw_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct lnw_gpio *lnw = get_irq_data(irq);
-	u32 base, gpio;
+	struct irq_data *data = irq_desc_get_irq_data(desc);
+	struct lnw_gpio *lnw = irq_data_get_irq_handler_data(data);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	u32 base, gpio, mask;
+	unsigned long pending;
 	void __iomem *gedr;
-	u32 gedr_v;
 
 	/* check GPIO controller to check which pin triggered the interrupt */
 	for (base = 0; base < lnw->chip.ngpio; base += 32) {
 		gedr = gpio_reg(&lnw->chip, base, GEDR);
-		gedr_v = readl(gedr);
-		if (!gedr_v)
-			continue;
-		for (gpio = base; gpio < base + 32; gpio++)
-			if (gedr_v & BIT(gpio % 32)) {
-				pr_debug("pin %d triggered\n", gpio);
-				generic_handle_irq(lnw->irq_base + gpio);
-			}
-		/* clear the edge detect status bit */
-		writel(gedr_v, gedr);
+		pending = readl(gedr);
+		while (pending) {
+			gpio = __ffs(pending) - 1;
+			mask = BIT(gpio);
+			pending &= ~mask;
+			/* Clear before handling so we can't lose an edge */
+			writel(mask, gedr);
+			generic_handle_irq(lnw->irq_base + base + gpio);
+		}
 	}
 
-	if (desc->chip->irq_eoi)
-		desc->chip->irq_eoi(irq_get_irq_data(irq));
-	else
-		dev_warn(lnw->chip.dev, "missing EOI handler for irq %d\n", irq);
-
+	chip->irq_eoi(data);
 }
 
 static int __devinit lnw_gpio_probe(struct pci_dev *pdev,
@@ -279,12 +276,12 @@
 		dev_err(&pdev->dev, "langwell gpiochip_add error %d\n", retval);
 		goto err5;
 	}
-	set_irq_data(pdev->irq, lnw);
-	set_irq_chained_handler(pdev->irq, lnw_irq_handler);
+	irq_set_handler_data(pdev->irq, lnw);
+	irq_set_chained_handler(pdev->irq, lnw_irq_handler);
 	for (i = 0; i < lnw->chip.ngpio; i++) {
-		set_irq_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
-					handle_simple_irq, "demux");
-		set_irq_chip_data(i + lnw->irq_base, lnw);
+		irq_set_chip_and_handler_name(i + lnw->irq_base, &lnw_irqchip,
+					      handle_simple_irq, "demux");
+		irq_set_chip_data(i + lnw->irq_base, lnw);
 	}
 
 	spin_lock_init(&lnw->lock);
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/Makefile linux-libre-2.6.39-gnu/drivers/gpio/Makefile
--- linux-libre-2.6.38-gnu/drivers/gpio/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -42,3 +42,4 @@
 obj-$(CONFIG_GPIO_SX150X)	+= sx150x.o
 obj-$(CONFIG_GPIO_VX855)	+= vx855_gpio.o
 obj-$(CONFIG_GPIO_ML_IOH)	+= ml_ioh_gpio.o
+obj-$(CONFIG_AB8500_GPIO)       += ab8500-gpio.o
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/max732x.c linux-libre-2.6.39-gnu/drivers/gpio/max732x.c
--- linux-libre-2.6.38-gnu/drivers/gpio/max732x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/max732x.c	2011-05-19 00:06:34.000000000 -0400
@@ -470,14 +470,14 @@
 			if (!(chip->dir_input & (1 << lvl)))
 				continue;
 
-			set_irq_chip_data(irq, chip);
-			set_irq_chip_and_handler(irq, &max732x_irq_chip,
+			irq_set_chip_data(irq, chip);
+			irq_set_chip_and_handler(irq, &max732x_irq_chip,
 						 handle_edge_irq);
-			set_irq_nested_thread(irq, 1);
+			irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 			set_irq_flags(irq, IRQF_VALID);
 #else
-			set_irq_noprobe(irq);
+			irq_set_noprobe(irq);
 #endif
 		}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/mc33880.c linux-libre-2.6.39-gnu/drivers/gpio/mc33880.c
--- linux-libre-2.6.38-gnu/drivers/gpio/mc33880.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/mc33880.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
  * To save time we cache them here in memory
  */
 struct mc33880 {
-	struct mutex	lock;	/* protect from simultanous accesses */
+	struct mutex	lock;	/* protect from simultaneous accesses */
 	u8		port_config;
 	struct gpio_chip chip;
 	struct spi_device *spi;
@@ -146,7 +146,7 @@
 	return ret;
 }
 
-static int mc33880_remove(struct spi_device *spi)
+static int __devexit mc33880_remove(struct spi_device *spi)
 {
 	struct mc33880 *mc;
 	int ret;
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/mcp23s08.c linux-libre-2.6.39-gnu/drivers/gpio/mcp23s08.c
--- linux-libre-2.6.38-gnu/drivers/gpio/mcp23s08.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/mcp23s08.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,7 +10,13 @@
 #include <linux/spi/spi.h>
 #include <linux/spi/mcp23s08.h>
 #include <linux/slab.h>
+#include <asm/byteorder.h>
 
+/**
+ * MCP types supported by driver
+ */
+#define MCP_TYPE_S08	0
+#define MCP_TYPE_S17	1
 
 /* Registers are all 8 bits wide.
  *
@@ -35,27 +41,38 @@
 #define MCP_GPIO	0x09
 #define MCP_OLAT	0x0a
 
+struct mcp23s08;
+
+struct mcp23s08_ops {
+	int	(*read)(struct mcp23s08 *mcp, unsigned reg);
+	int	(*write)(struct mcp23s08 *mcp, unsigned reg, unsigned val);
+	int	(*read_regs)(struct mcp23s08 *mcp, unsigned reg,
+			     u16 *vals, unsigned n);
+};
+
 struct mcp23s08 {
 	struct spi_device	*spi;
 	u8			addr;
 
-	u8			cache[11];
+	u16			cache[11];
 	/* lock protects the cached values */
 	struct mutex		lock;
 
 	struct gpio_chip	chip;
 
 	struct work_struct	work;
+
+	const struct mcp23s08_ops	*ops;
 };
 
-/* A given spi_device can represent up to four mcp23s08 chips
+/* A given spi_device can represent up to eight mcp23sxx chips
  * sharing the same chipselect but using different addresses
  * (e.g. chips #0 and #3 might be populated, but not #1 or $2).
  * Driver data holds all the per-chip data.
  */
 struct mcp23s08_driver_data {
 	unsigned		ngpio;
-	struct mcp23s08		*mcp[4];
+	struct mcp23s08		*mcp[8];
 	struct mcp23s08		chip[];
 };
 
@@ -70,7 +87,7 @@
 	return (status < 0) ? status : rx[0];
 }
 
-static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, u8 val)
+static int mcp23s08_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
 {
 	u8	tx[3];
 
@@ -81,17 +98,81 @@
 }
 
 static int
-mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u8 *vals, unsigned n)
+mcp23s08_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
 {
-	u8	tx[2];
+	u8	tx[2], *tmp;
+	int	status;
 
 	if ((n + reg) > sizeof mcp->cache)
 		return -EINVAL;
 	tx[0] = mcp->addr | 0x01;
 	tx[1] = reg;
-	return spi_write_then_read(mcp->spi, tx, sizeof tx, vals, n);
+
+	tmp = (u8 *)vals;
+	status = spi_write_then_read(mcp->spi, tx, sizeof tx, tmp, n);
+	if (status >= 0) {
+		while (n--)
+			vals[n] = tmp[n]; /* expand to 16bit */
+	}
+	return status;
+}
+
+static int mcp23s17_read(struct mcp23s08 *mcp, unsigned reg)
+{
+	u8	tx[2], rx[2];
+	int	status;
+
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg << 1;
+	status = spi_write_then_read(mcp->spi, tx, sizeof tx, rx, sizeof rx);
+	return (status < 0) ? status : (rx[0] | (rx[1] << 8));
+}
+
+static int mcp23s17_write(struct mcp23s08 *mcp, unsigned reg, unsigned val)
+{
+	u8	tx[4];
+
+	tx[0] = mcp->addr;
+	tx[1] = reg << 1;
+	tx[2] = val;
+	tx[3] = val >> 8;
+	return spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+}
+
+static int
+mcp23s17_read_regs(struct mcp23s08 *mcp, unsigned reg, u16 *vals, unsigned n)
+{
+	u8	tx[2];
+	int	status;
+
+	if ((n + reg) > sizeof mcp->cache)
+		return -EINVAL;
+	tx[0] = mcp->addr | 0x01;
+	tx[1] = reg << 1;
+
+	status = spi_write_then_read(mcp->spi, tx, sizeof tx,
+				     (u8 *)vals, n * 2);
+	if (status >= 0) {
+		while (n--)
+			vals[n] = __le16_to_cpu((__le16)vals[n]);
+	}
+
+	return status;
 }
 
+static const struct mcp23s08_ops mcp23s08_ops = {
+	.read		= mcp23s08_read,
+	.write		= mcp23s08_write,
+	.read_regs	= mcp23s08_read_regs,
+};
+
+static const struct mcp23s08_ops mcp23s17_ops = {
+	.read		= mcp23s17_read,
+	.write		= mcp23s17_write,
+	.read_regs	= mcp23s17_read_regs,
+};
+
+
 /*----------------------------------------------------------------------*/
 
 static int mcp23s08_direction_input(struct gpio_chip *chip, unsigned offset)
@@ -101,7 +182,7 @@
 
 	mutex_lock(&mcp->lock);
 	mcp->cache[MCP_IODIR] |= (1 << offset);
-	status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+	status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 	mutex_unlock(&mcp->lock);
 	return status;
 }
@@ -114,7 +195,7 @@
 	mutex_lock(&mcp->lock);
 
 	/* REVISIT reading this clears any IRQ ... */
-	status = mcp23s08_read(mcp, MCP_GPIO);
+	status = mcp->ops->read(mcp, MCP_GPIO);
 	if (status < 0)
 		status = 0;
 	else {
@@ -127,20 +208,20 @@
 
 static int __mcp23s08_set(struct mcp23s08 *mcp, unsigned mask, int value)
 {
-	u8 olat = mcp->cache[MCP_OLAT];
+	unsigned olat = mcp->cache[MCP_OLAT];
 
 	if (value)
 		olat |= mask;
 	else
 		olat &= ~mask;
 	mcp->cache[MCP_OLAT] = olat;
-	return mcp23s08_write(mcp, MCP_OLAT, olat);
+	return mcp->ops->write(mcp, MCP_OLAT, olat);
 }
 
 static void mcp23s08_set(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	u8 mask = 1 << offset;
+	unsigned mask = 1 << offset;
 
 	mutex_lock(&mcp->lock);
 	__mcp23s08_set(mcp, mask, value);
@@ -151,14 +232,14 @@
 mcp23s08_direction_output(struct gpio_chip *chip, unsigned offset, int value)
 {
 	struct mcp23s08	*mcp = container_of(chip, struct mcp23s08, chip);
-	u8 mask = 1 << offset;
+	unsigned mask = 1 << offset;
 	int status;
 
 	mutex_lock(&mcp->lock);
 	status = __mcp23s08_set(mcp, mask, value);
 	if (status == 0) {
 		mcp->cache[MCP_IODIR] &= ~mask;
-		status = mcp23s08_write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
+		status = mcp->ops->write(mcp, MCP_IODIR, mcp->cache[MCP_IODIR]);
 	}
 	mutex_unlock(&mcp->lock);
 	return status;
@@ -184,16 +265,16 @@
 	mcp = container_of(chip, struct mcp23s08, chip);
 
 	/* NOTE: we only handle one bank for now ... */
-	bank = '0' + ((mcp->addr >> 1) & 0x3);
+	bank = '0' + ((mcp->addr >> 1) & 0x7);
 
 	mutex_lock(&mcp->lock);
-	t = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
+	t = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
 	if (t < 0) {
 		seq_printf(s, " I/O ERROR %d\n", t);
 		goto done;
 	}
 
-	for (t = 0, mask = 1; t < 8; t++, mask <<= 1) {
+	for (t = 0, mask = 1; t < chip->ngpio; t++, mask <<= 1) {
 		const char	*label;
 
 		label = gpiochip_is_requested(chip, t);
@@ -219,28 +300,33 @@
 /*----------------------------------------------------------------------*/
 
 static int mcp23s08_probe_one(struct spi_device *spi, unsigned addr,
-		unsigned base, unsigned pullups)
+			      unsigned type, unsigned base, unsigned pullups)
 {
 	struct mcp23s08_driver_data	*data = spi_get_drvdata(spi);
 	struct mcp23s08			*mcp = data->mcp[addr];
 	int				status;
-	int				do_update = 0;
 
 	mutex_init(&mcp->lock);
 
 	mcp->spi = spi;
 	mcp->addr = 0x40 | (addr << 1);
 
-	mcp->chip.label = "mcp23s08",
-
 	mcp->chip.direction_input = mcp23s08_direction_input;
 	mcp->chip.get = mcp23s08_get;
 	mcp->chip.direction_output = mcp23s08_direction_output;
 	mcp->chip.set = mcp23s08_set;
 	mcp->chip.dbg_show = mcp23s08_dbg_show;
 
+	if (type == MCP_TYPE_S17) {
+		mcp->ops = &mcp23s17_ops;
+		mcp->chip.ngpio = 16;
+		mcp->chip.label = "mcp23s17";
+	} else {
+		mcp->ops = &mcp23s08_ops;
+		mcp->chip.ngpio = 8;
+		mcp->chip.label = "mcp23s08";
+	}
 	mcp->chip.base = base;
-	mcp->chip.ngpio = 8;
 	mcp->chip.can_sleep = 1;
 	mcp->chip.dev = &spi->dev;
 	mcp->chip.owner = THIS_MODULE;
@@ -248,45 +334,39 @@
 	/* verify MCP_IOCON.SEQOP = 0, so sequential reads work,
 	 * and MCP_IOCON.HAEN = 1, so we work with all chips.
 	 */
-	status = mcp23s08_read(mcp, MCP_IOCON);
+	status = mcp->ops->read(mcp, MCP_IOCON);
 	if (status < 0)
 		goto fail;
 	if ((status & IOCON_SEQOP) || !(status & IOCON_HAEN)) {
-		status &= ~IOCON_SEQOP;
-		status |= IOCON_HAEN;
-		status = mcp23s08_write(mcp, MCP_IOCON, (u8) status);
+		/* mcp23s17 has IOCON twice, make sure they are in sync */
+		status &= ~(IOCON_SEQOP | (IOCON_SEQOP << 8));
+		status |= IOCON_HAEN | (IOCON_HAEN << 8);
+		status = mcp->ops->write(mcp, MCP_IOCON, status);
 		if (status < 0)
 			goto fail;
 	}
 
 	/* configure ~100K pullups */
-	status = mcp23s08_write(mcp, MCP_GPPU, pullups);
+	status = mcp->ops->write(mcp, MCP_GPPU, pullups);
 	if (status < 0)
 		goto fail;
 
-	status = mcp23s08_read_regs(mcp, 0, mcp->cache, sizeof mcp->cache);
+	status = mcp->ops->read_regs(mcp, 0, mcp->cache, ARRAY_SIZE(mcp->cache));
 	if (status < 0)
 		goto fail;
 
 	/* disable inverter on input */
 	if (mcp->cache[MCP_IPOL] != 0) {
 		mcp->cache[MCP_IPOL] = 0;
-		do_update = 1;
+		status = mcp->ops->write(mcp, MCP_IPOL, 0);
+		if (status < 0)
+			goto fail;
 	}
 
 	/* disable irqs */
 	if (mcp->cache[MCP_GPINTEN] != 0) {
 		mcp->cache[MCP_GPINTEN] = 0;
-		do_update = 1;
-	}
-
-	if (do_update) {
-		u8 tx[4];
-
-		tx[0] = mcp->addr;
-		tx[1] = MCP_IPOL;
-		memcpy(&tx[2], &mcp->cache[MCP_IPOL], sizeof(tx) - 2);
-		status = spi_write_then_read(mcp->spi, tx, sizeof tx, NULL, 0);
+		status = mcp->ops->write(mcp, MCP_GPINTEN, 0);
 		if (status < 0)
 			goto fail;
 	}
@@ -305,19 +385,26 @@
 	unsigned			addr;
 	unsigned			chips = 0;
 	struct mcp23s08_driver_data	*data;
-	int				status;
+	int				status, type;
 	unsigned			base;
 
+	type = spi_get_device_id(spi)->driver_data;
+
 	pdata = spi->dev.platform_data;
 	if (!pdata || !gpio_is_valid(pdata->base)) {
 		dev_dbg(&spi->dev, "invalid or missing platform data\n");
 		return -EINVAL;
 	}
 
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
 		if (!pdata->chip[addr].is_present)
 			continue;
 		chips++;
+		if ((type == MCP_TYPE_S08) && (addr > 3)) {
+			dev_err(&spi->dev,
+				"mcp23s08 only supports address 0..3\n");
+			return -EINVAL;
+		}
 	}
 	if (!chips)
 		return -ENODEV;
@@ -329,16 +416,17 @@
 	spi_set_drvdata(spi, data);
 
 	base = pdata->base;
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(pdata->chip); addr++) {
 		if (!pdata->chip[addr].is_present)
 			continue;
 		chips--;
 		data->mcp[addr] = &data->chip[chips];
-		status = mcp23s08_probe_one(spi, addr, base,
-				pdata->chip[addr].pullups);
+		status = mcp23s08_probe_one(spi, addr, type, base,
+					    pdata->chip[addr].pullups);
 		if (status < 0)
 			goto fail;
-		base += 8;
+
+		base += (type == MCP_TYPE_S17) ? 16 : 8;
 	}
 	data->ngpio = base - pdata->base;
 
@@ -358,7 +446,7 @@
 	return 0;
 
 fail:
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
 		int tmp;
 
 		if (!data->mcp[addr])
@@ -388,7 +476,7 @@
 		}
 	}
 
-	for (addr = 0; addr < 4; addr++) {
+	for (addr = 0; addr < ARRAY_SIZE(data->mcp); addr++) {
 		int tmp;
 
 		if (!data->mcp[addr])
@@ -405,9 +493,17 @@
 	return status;
 }
 
+static const struct spi_device_id mcp23s08_ids[] = {
+	{ "mcp23s08", MCP_TYPE_S08 },
+	{ "mcp23s17", MCP_TYPE_S17 },
+	{ },
+};
+MODULE_DEVICE_TABLE(spi, mcp23s08_ids);
+
 static struct spi_driver mcp23s08_driver = {
 	.probe		= mcp23s08_probe,
 	.remove		= mcp23s08_remove,
+	.id_table	= mcp23s08_ids,
 	.driver = {
 		.name	= "mcp23s08",
 		.owner	= THIS_MODULE,
@@ -432,4 +528,3 @@
 module_exit(mcp23s08_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:mcp23s08");
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/ml_ioh_gpio.c linux-libre-2.6.39-gnu/drivers/gpio/ml_ioh_gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/ml_ioh_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/ml_ioh_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,6 +116,7 @@
 		reg_val |= (1 << nr);
 	else
 		reg_val &= ~(1 << nr);
+	iowrite32(reg_val, &chip->reg->regs[chip->ch].po);
 
 	mutex_unlock(&chip->lock);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/pca953x.c linux-libre-2.6.39-gnu/drivers/gpio/pca953x.c
--- linux-libre-2.6.38-gnu/drivers/gpio/pca953x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/pca953x.c	2011-05-19 00:06:34.000000000 -0400
@@ -395,13 +395,13 @@
 		for (lvl = 0; lvl < chip->gpio_chip.ngpio; lvl++) {
 			int irq = lvl + chip->irq_base;
 
-			set_irq_chip_data(irq, chip);
-			set_irq_chip_and_handler(irq, &pca953x_irq_chip,
+			irq_set_chip_data(irq, chip);
+			irq_set_chip_and_handler(irq, &pca953x_irq_chip,
 						 handle_edge_irq);
 #ifdef CONFIG_ARM
 			set_irq_flags(irq, IRQF_VALID);
 #else
-			set_irq_noprobe(irq);
+			irq_set_noprobe(irq);
 #endif
 		}
 
@@ -462,7 +462,8 @@
 {
 	struct pca953x_platform_data *pdata;
 	struct device_node *node;
-	const uint16_t *val;
+	const __be32 *val;
+	int size;
 
 	node = client->dev.of_node;
 	if (node == NULL)
@@ -475,13 +476,13 @@
 	}
 
 	pdata->gpio_base = -1;
-	val = of_get_property(node, "linux,gpio-base", NULL);
+	val = of_get_property(node, "linux,gpio-base", &size);
 	if (val) {
-		if (*val < 0)
-			dev_warn(&client->dev,
-				 "invalid gpio-base in device tree\n");
+		if (size != sizeof(*val))
+			dev_warn(&client->dev, "%s: wrong linux,gpio-base\n",
+				 node->full_name);
 		else
-			pdata->gpio_base = *val;
+			pdata->gpio_base = be32_to_cpup(val);
 	}
 
 	val = of_get_property(node, "polarity", NULL);
@@ -557,7 +558,7 @@
 
 	ret = gpiochip_add(&chip->gpio_chip);
 	if (ret)
-		goto out_failed;
+		goto out_failed_irq;
 
 	if (pdata->setup) {
 		ret = pdata->setup(client, chip->gpio_chip.base,
@@ -569,8 +570,9 @@
 	i2c_set_clientdata(client, chip);
 	return 0;
 
-out_failed:
+out_failed_irq:
 	pca953x_irq_teardown(chip);
+out_failed:
 	kfree(chip->dyn_pdata);
 	kfree(chip);
 	return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/pch_gpio.c linux-libre-2.6.39-gnu/drivers/gpio/pch_gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/pch_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/pch_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,6 +105,7 @@
 		reg_val |= (1 << nr);
 	else
 		reg_val &= ~(1 << nr);
+	iowrite32(reg_val, &chip->reg->po);
 
 	mutex_unlock(&chip->lock);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/pl061.c linux-libre-2.6.39-gnu/drivers/gpio/pl061.c
--- linux-libre-2.6.38-gnu/drivers/gpio/pl061.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/pl061.c	2011-05-19 00:06:34.000000000 -0400
@@ -210,7 +210,7 @@
 
 static void pl061_irq_handler(unsigned irq, struct irq_desc *desc)
 {
-	struct list_head *chip_list = get_irq_data(irq);
+	struct list_head *chip_list = irq_get_handler_data(irq);
 	struct list_head *ptr;
 	struct pl061_gpio *chip;
 
@@ -232,7 +232,7 @@
 	desc->irq_data.chip->irq_unmask(&desc->irq_data);
 }
 
-static int pl061_probe(struct amba_device *dev, struct amba_id *id)
+static int pl061_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct pl061_platform_data *pdata;
 	struct pl061_gpio *chip;
@@ -294,7 +294,7 @@
 		ret = -ENODEV;
 		goto iounmap;
 	}
-	set_irq_chained_handler(irq, pl061_irq_handler);
+	irq_set_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) {
@@ -303,9 +303,9 @@
 			goto iounmap;
 		}
 		INIT_LIST_HEAD(chip_list);
-		set_irq_data(irq, chip_list);
+		irq_set_handler_data(irq, chip_list);
 	} else
-		chip_list = get_irq_data(irq);
+		chip_list = irq_get_handler_data(irq);
 	list_add(&chip->list, chip_list);
 
 	for (i = 0; i < PL061_GPIO_NR; i++) {
@@ -315,10 +315,10 @@
 		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);
+		irq_set_chip_and_handler(i + chip->irq_base, &pl061_irqchip,
+					 handle_simple_irq);
 		set_irq_flags(i+chip->irq_base, IRQF_VALID);
-		set_irq_chip_data(i+chip->irq_base, chip);
+		irq_set_chip_data(i + chip->irq_base, chip);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/rdc321x-gpio.c linux-libre-2.6.39-gnu/drivers/gpio/rdc321x-gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/rdc321x-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/rdc321x-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/pci.h>
 #include <linux/gpio.h>
 #include <linux/mfd/rdc321x.h>
+#include <linux/mfd/core.h>
 #include <linux/slab.h>
 
 struct rdc321x_gpio {
@@ -135,7 +136,7 @@
 	struct rdc321x_gpio *rdc321x_gpio_dev;
 	struct rdc321x_gpio_pdata *pdata;
 
-	pdata = platform_get_drvdata(pdev);
+	pdata = mfd_get_data(pdev);
 	if (!pdata) {
 		dev_err(&pdev->dev, "no platform data supplied\n");
 		return -ENODEV;
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/sch_gpio.c linux-libre-2.6.39-gnu/drivers/gpio/sch_gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/sch_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/sch_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/errno.h>
 #include <linux/acpi.h>
 #include <linux/platform_device.h>
+#include <linux/pci_ids.h>
 
 #include <linux/gpio.h>
 
@@ -187,7 +188,11 @@
 static int __devinit sch_gpio_probe(struct platform_device *pdev)
 {
 	struct resource *res;
-	int err;
+	int err, id;
+
+	id = pdev->id;
+	if (!id)
+		return -ENODEV;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	if (!res)
@@ -198,12 +203,40 @@
 
 	gpio_ba = res->start;
 
-	sch_gpio_core.base = 0;
-	sch_gpio_core.ngpio = 10;
-	sch_gpio_core.dev = &pdev->dev;
+	switch (id) {
+		case PCI_DEVICE_ID_INTEL_SCH_LPC:
+			sch_gpio_core.base = 0;
+			sch_gpio_core.ngpio = 10;
 
-	sch_gpio_resume.base = 10;
-	sch_gpio_resume.ngpio = 4;
+			sch_gpio_resume.base = 10;
+			sch_gpio_resume.ngpio = 4;
+
+			/*
+			 * GPIO[6:0] enabled by default
+			 * GPIO7 is configured by the CMC as SLPIOVR
+			 * Enable GPIO[9:8] core powered gpios explicitly
+			 */
+			outb(0x3, gpio_ba + CGEN + 1);
+			/*
+			 * SUS_GPIO[2:0] enabled by default
+			 * Enable SUS_GPIO3 resume powered gpio explicitly
+			 */
+			outb(0x8, gpio_ba + RGEN);
+			break;
+
+		case PCI_DEVICE_ID_INTEL_ITC_LPC:
+			sch_gpio_core.base = 0;
+			sch_gpio_core.ngpio = 5;
+
+			sch_gpio_resume.base = 5;
+			sch_gpio_resume.ngpio = 9;
+			break;
+
+		default:
+			return -ENODEV;
+	}
+
+	sch_gpio_core.dev = &pdev->dev;
 	sch_gpio_resume.dev = &pdev->dev;
 
 	err = gpiochip_add(&sch_gpio_core);
@@ -214,18 +247,6 @@
 	if (err < 0)
 		goto err_sch_gpio_resume;
 
-	/*
-	 * GPIO[6:0] enabled by default
-	 * GPIO7 is configured by the CMC as SLPIOVR
-	 * Enable GPIO[9:8] core powered gpios explicitly
-	 */
-	outb(0x3, gpio_ba + CGEN + 1);
-	/*
-	 * SUS_GPIO[2:0] enabled by default
-	 * Enable SUS_GPIO3 resume powered gpio explicitly
-	 */
-	outb(0x8, gpio_ba + RGEN);
-
 	return 0;
 
 err_sch_gpio_resume:
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/stmpe-gpio.c linux-libre-2.6.39-gnu/drivers/gpio/stmpe-gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/stmpe-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/stmpe-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -254,14 +254,14 @@
 	int irq;
 
 	for (irq = base; irq < base + stmpe_gpio->chip.ngpio; irq++) {
-		set_irq_chip_data(irq, stmpe_gpio);
-		set_irq_chip_and_handler(irq, &stmpe_gpio_irq_chip,
+		irq_set_chip_data(irq, stmpe_gpio);
+		irq_set_chip_and_handler(irq, &stmpe_gpio_irq_chip,
 					 handle_simple_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -277,8 +277,8 @@
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/sx150x.c linux-libre-2.6.39-gnu/drivers/gpio/sx150x.c
--- linux-libre-2.6.38-gnu/drivers/gpio/sx150x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/sx150x.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,8 @@
 #include <linux/workqueue.h>
 #include <linux/i2c/sx150x.h>
 
+#define NO_UPDATE_PENDING	-1
+
 struct sx150x_device_data {
 	u8 reg_pullup;
 	u8 reg_pulldn;
@@ -47,8 +49,11 @@
 	const struct sx150x_device_data *dev_cfg;
 	int                              irq_summary;
 	int                              irq_base;
+	int				 irq_update;
 	u32                              irq_sense;
-	unsigned long                    irq_set_type_pending;
+	u32				 irq_masked;
+	u32				 dev_sense;
+	u32				 dev_masked;
 	struct irq_chip                  irq_chip;
 	struct mutex                     lock;
 };
@@ -312,9 +317,8 @@
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
-
-	sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
-	sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
+	chip->irq_masked |= (1 << n);
+	chip->irq_update = n;
 }
 
 static void sx150x_irq_unmask(struct irq_data *d)
@@ -326,9 +330,8 @@
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
 	n = d->irq - chip->irq_base;
 
-	sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
-	sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
-			 chip->irq_sense >> (n * 2));
+	chip->irq_masked &= ~(1 << n);
+	chip->irq_update = n;
 }
 
 static int sx150x_irq_set_type(struct irq_data *d, unsigned int flow_type)
@@ -350,7 +353,7 @@
 
 	chip->irq_sense &= ~(3UL << (n * 2));
 	chip->irq_sense |= val << (n * 2);
-	chip->irq_set_type_pending |= BIT(n);
+	chip->irq_update = n;
 	return 0;
 }
 
@@ -404,15 +407,29 @@
 
 	chip = container_of(ic, struct sx150x_chip, irq_chip);
 
-	while (chip->irq_set_type_pending) {
-		n = __ffs(chip->irq_set_type_pending);
-		chip->irq_set_type_pending &= ~BIT(n);
-		if (!(irq_to_desc(n + chip->irq_base)->status & IRQ_MASKED))
-			sx150x_write_cfg(chip, n, 2,
-					chip->dev_cfg->reg_sense,
-					chip->irq_sense >> (n * 2));
-	}
+	if (chip->irq_update == NO_UPDATE_PENDING)
+		goto out;
+
+	n = chip->irq_update;
+	chip->irq_update = NO_UPDATE_PENDING;
 
+	/* Avoid updates if nothing changed */
+	if (chip->dev_sense == chip->irq_sense &&
+	    chip->dev_sense == chip->irq_masked)
+		goto out;
+
+	chip->dev_sense = chip->irq_sense;
+	chip->dev_masked = chip->irq_masked;
+
+	if (chip->irq_masked & (1 << n)) {
+		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 1);
+		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense, 0);
+	} else {
+		sx150x_write_cfg(chip, n, 1, chip->dev_cfg->reg_irq_mask, 0);
+		sx150x_write_cfg(chip, n, 2, chip->dev_cfg->reg_sense,
+				 chip->irq_sense >> (n * 2));
+	}
+out:
 	mutex_unlock(&chip->lock);
 }
 
@@ -445,8 +462,11 @@
 	chip->irq_chip.irq_bus_sync_unlock = sx150x_irq_bus_sync_unlock;
 	chip->irq_summary                  = -1;
 	chip->irq_base                     = -1;
+	chip->irq_masked                   = ~0;
 	chip->irq_sense                    = 0;
-	chip->irq_set_type_pending         = 0;
+	chip->dev_masked                   = ~0;
+	chip->dev_sense                    = 0;
+	chip->irq_update		   = NO_UPDATE_PENDING;
 }
 
 static int sx150x_init_io(struct sx150x_chip *chip, u8 base, u16 cfg)
@@ -531,12 +551,12 @@
 
 	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
 		irq = irq_base + n;
-		set_irq_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_chip_and_handler(irq, &chip->irq_chip, handle_edge_irq);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -563,8 +583,7 @@
 
 	for (n = 0; n < chip->dev_cfg->ngpios; ++n) {
 		irq = chip->irq_base + n;
-		set_irq_handler(irq, NULL);
-		set_irq_chip(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/tc3589x-gpio.c linux-libre-2.6.39-gnu/drivers/gpio/tc3589x-gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/tc3589x-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/tc3589x-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -239,14 +239,14 @@
 	int irq;
 
 	for (irq = base; irq < base + tc3589x_gpio->chip.ngpio; irq++) {
-		set_irq_chip_data(irq, tc3589x_gpio);
-		set_irq_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
+		irq_set_chip_data(irq, tc3589x_gpio);
+		irq_set_chip_and_handler(irq, &tc3589x_gpio_irq_chip,
 					 handle_simple_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -262,8 +262,8 @@
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/timbgpio.c linux-libre-2.6.39-gnu/drivers/gpio/timbgpio.c
--- linux-libre-2.6.38-gnu/drivers/gpio/timbgpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/timbgpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include <linux/module.h>
 #include <linux/gpio.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/timb_gpio.h>
@@ -195,7 +196,7 @@
 
 static void timbgpio_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct timbgpio *tgpio = get_irq_data(irq);
+	struct timbgpio *tgpio = irq_get_handler_data(irq);
 	unsigned long ipr;
 	int offset;
 
@@ -228,7 +229,7 @@
 	struct gpio_chip *gc;
 	struct timbgpio *tgpio;
 	struct resource *iomem;
-	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
+	struct timbgpio_platform_data *pdata = mfd_get_data(pdev);
 	int irq = platform_get_irq(pdev, 0);
 
 	if (!pdata || pdata->nr_pins > 32) {
@@ -291,16 +292,16 @@
 		return 0;
 
 	for (i = 0; i < pdata->nr_pins; i++) {
-		set_irq_chip_and_handler_name(tgpio->irq_base + i,
+		irq_set_chip_and_handler_name(tgpio->irq_base + i,
 			&timbgpio_irqchip, handle_simple_irq, "mux");
-		set_irq_chip_data(tgpio->irq_base + i, tgpio);
+		irq_set_chip_data(tgpio->irq_base + i, tgpio);
 #ifdef CONFIG_ARM
 		set_irq_flags(tgpio->irq_base + i, IRQF_VALID | IRQF_PROBE);
 #endif
 	}
 
-	set_irq_data(irq, tgpio);
-	set_irq_chained_handler(irq, timbgpio_irq);
+	irq_set_handler_data(irq, tgpio);
+	irq_set_chained_handler(irq, timbgpio_irq);
 
 	return 0;
 
@@ -319,20 +320,19 @@
 static int __devexit timbgpio_remove(struct platform_device *pdev)
 {
 	int err;
-	struct timbgpio_platform_data *pdata = pdev->dev.platform_data;
 	struct timbgpio *tgpio = platform_get_drvdata(pdev);
 	struct resource *iomem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	int irq = platform_get_irq(pdev, 0);
 
 	if (irq >= 0 && tgpio->irq_base > 0) {
 		int i;
-		for (i = 0; i < pdata->nr_pins; i++) {
-			set_irq_chip(tgpio->irq_base + i, NULL);
-			set_irq_chip_data(tgpio->irq_base + i, NULL);
+		for (i = 0; i < tgpio->gpio.ngpio; i++) {
+			irq_set_chip(tgpio->irq_base + i, NULL);
+			irq_set_chip_data(tgpio->irq_base + i, NULL);
 		}
 
-		set_irq_handler(irq, NULL);
-		set_irq_data(irq, NULL);
+		irq_set_handler(irq, NULL);
+		irq_set_handler_data(irq, NULL);
 	}
 
 	err = gpiochip_remove(&tgpio->gpio);
diff -druN linux-libre-2.6.38-gnu/drivers/gpio/vr41xx_giu.c linux-libre-2.6.39-gnu/drivers/gpio/vr41xx_giu.c
--- linux-libre-2.6.38-gnu/drivers/gpio/vr41xx_giu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpio/vr41xx_giu.c	2011-05-19 00:06:34.000000000 -0400
@@ -238,13 +238,13 @@
 					break;
 				}
 			}
-			set_irq_chip_and_handler(GIU_IRQ(pin),
+			irq_set_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),
+			irq_set_chip_and_handler(GIU_IRQ(pin),
 						 &giuint_low_irq_chip,
 						 handle_level_irq);
 		}
@@ -273,13 +273,13 @@
 					break;
 				}
 			}
-			set_irq_chip_and_handler(GIU_IRQ(pin),
+			irq_set_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),
+			irq_set_chip_and_handler(GIU_IRQ(pin),
 						 &giuint_high_irq_chip,
 						 handle_level_irq);
 		}
@@ -539,9 +539,9 @@
 			chip = &giuint_high_irq_chip;
 
 		if (trigger & (1 << pin))
-			set_irq_chip_and_handler(i, chip, handle_edge_irq);
+			irq_set_chip_and_handler(i, chip, handle_edge_irq);
 		else
-			set_irq_chip_and_handler(i, chip, handle_level_irq);
+			irq_set_chip_and_handler(i, chip, handle_level_irq);
 
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_crtc.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_crtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -1073,6 +1073,9 @@
 	uint32_t __user *encoder_id;
 	struct drm_mode_group *mode_group;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	/*
@@ -1244,6 +1247,9 @@
 	struct drm_mode_object *obj;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, crtc_resp->crtc_id,
@@ -1312,6 +1318,9 @@
 	uint64_t __user *prop_values;
 	uint32_t __user *encoder_ptr;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	memset(&u_mode, 0, sizeof(struct drm_mode_modeinfo));
 
 	DRM_DEBUG_KMS("[CONNECTOR:%d:?]\n", out_resp->connector_id);
@@ -1431,6 +1440,9 @@
 	struct drm_encoder *encoder;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, enc_resp->encoder_id,
 				   DRM_MODE_OBJECT_ENCODER);
@@ -1486,6 +1498,9 @@
 	int ret = 0;
 	int i;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, crtc_req->crtc_id,
 				   DRM_MODE_OBJECT_CRTC);
@@ -1603,6 +1618,9 @@
 	struct drm_crtc *crtc;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	if (!req->flags) {
 		DRM_ERROR("no operation set\n");
 		return -EINVAL;
@@ -1667,6 +1685,9 @@
 	struct drm_framebuffer *fb;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	if ((config->min_width > r->width) || (r->width > config->max_width)) {
 		DRM_ERROR("mode new framebuffer width not within limits\n");
 		return -EINVAL;
@@ -1678,7 +1699,7 @@
 
 	mutex_lock(&dev->mode_config.mutex);
 
-	/* TODO check buffer is sufficently large */
+	/* TODO check buffer is sufficiently large */
 	/* TODO setup destructor callback */
 
 	fb = dev->mode_config.funcs->fb_create(dev, file_priv, r);
@@ -1724,9 +1745,12 @@
 	int ret = 0;
 	int found = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, *id, DRM_MODE_OBJECT_FB);
-	/* TODO check that we realy get a framebuffer back. */
+	/* TODO check that we really get a framebuffer back. */
 	if (!obj) {
 		DRM_ERROR("mode invalid framebuffer id\n");
 		ret = -EINVAL;
@@ -1780,6 +1804,9 @@
 	struct drm_framebuffer *fb;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
 	if (!obj) {
@@ -1813,6 +1840,9 @@
 	int num_clips;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, r->fb_id, DRM_MODE_OBJECT_FB);
 	if (!obj) {
@@ -1996,6 +2026,9 @@
 	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2042,6 +2075,9 @@
 	struct drm_mode_modeinfo *umode = &mode_cmd->mode;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, mode_cmd->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2211,6 +2247,9 @@
 	uint64_t __user *values_ptr;
 	uint32_t __user *blob_length_ptr;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, out_resp->prop_id, DRM_MODE_OBJECT_PROPERTY);
 	if (!obj) {
@@ -2333,6 +2372,9 @@
 	int ret = 0;
 	void *blob_ptr;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, out_resp->blob_id, DRM_MODE_OBJECT_BLOB);
 	if (!obj) {
@@ -2393,6 +2435,9 @@
 	int ret = -EINVAL;
 	int i;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 
 	obj = drm_mode_object_find(dev, out_resp->connector_id, DRM_MODE_OBJECT_CONNECTOR);
@@ -2509,6 +2554,9 @@
 	int size;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
@@ -2560,6 +2608,9 @@
 	int size;
 	int ret = 0;
 
+	if (!drm_core_check_feature(dev, DRIVER_MODESET))
+		return -EINVAL;
+
 	mutex_lock(&dev->mode_config.mutex);
 	obj = drm_mode_object_find(dev, crtc_lut->crtc_id, DRM_MODE_OBJECT_CRTC);
 	if (!obj) {
@@ -2694,3 +2745,36 @@
 			connector->funcs->reset(connector);
 }
 EXPORT_SYMBOL(drm_mode_config_reset);
+
+int drm_mode_create_dumb_ioctl(struct drm_device *dev,
+			       void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_create_dumb *args = data;
+
+	if (!dev->driver->dumb_create)
+		return -ENOSYS;
+	return dev->driver->dumb_create(file_priv, dev, args);
+}
+
+int drm_mode_mmap_dumb_ioctl(struct drm_device *dev,
+			     void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_map_dumb *args = data;
+
+	/* call driver ioctl to get mmap offset */
+	if (!dev->driver->dumb_map_offset)
+		return -ENOSYS;
+
+	return dev->driver->dumb_map_offset(file_priv, dev, args->handle, &args->offset);
+}
+
+int drm_mode_destroy_dumb_ioctl(struct drm_device *dev,
+				void *data, struct drm_file *file_priv)
+{
+	struct drm_mode_destroy_dumb *args = data;
+
+	if (!dev->driver->dumb_destroy)
+		return -ENOSYS;
+
+	return dev->driver->dumb_destroy(file_priv, dev, args->handle);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,6 +67,7 @@
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_MAP, drm_getmap, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_CLIENT, drm_getclient, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_GET_STATS, drm_getstats, 0),
+	DRM_IOCTL_DEF(DRM_IOCTL_GET_CAP, drm_getcap, 0),
 	DRM_IOCTL_DEF(DRM_IOCTL_SET_VERSION, drm_setversion, DRM_MASTER),
 
 	DRM_IOCTL_DEF(DRM_IOCTL_SET_UNIQUE, drm_setunique, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -150,7 +151,10 @@
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
 	DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
-	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_CREATE_DUMB, drm_mode_create_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_MAP_DUMB, drm_mode_mmap_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
+	DRM_IOCTL_DEF(DRM_IOCTL_MODE_DESTROY_DUMB, drm_mode_destroy_dumb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
 };
 
 #define DRM_CORE_IOCTL_COUNT	ARRAY_SIZE( drm_ioctls )
@@ -234,49 +238,6 @@
 	return 0;
 }
 
-/**
- * Module initialization. Called via init_module at module load time, or via
- * linux/init/main.c (this is not currently supported).
- *
- * \return zero on success or a negative number on failure.
- *
- * Initializes an array of drm_device structures, and attempts to
- * initialize all available devices, using consecutive minors, registering the
- * stubs and initializing the device.
- *
- * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
- * after the initialization for driver customization.
- */
-int drm_init(struct drm_driver *driver)
-{
-	DRM_DEBUG("\n");
-	INIT_LIST_HEAD(&driver->device_list);
-
-	if (driver->driver_features & DRIVER_USE_PLATFORM_DEVICE)
-		return drm_platform_init(driver);
-	else
-		return drm_pci_init(driver);
-}
-
-EXPORT_SYMBOL(drm_init);
-
-void drm_exit(struct drm_driver *driver)
-{
-	struct drm_device *dev, *tmp;
-	DRM_DEBUG("\n");
-
-	if (driver->driver_features & DRIVER_MODESET) {
-		pci_unregister_driver(&driver->pci_driver);
-	} else {
-		list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
-			drm_put_dev(dev);
-	}
-
-	DRM_INFO("Module unloaded\n");
-}
-
-EXPORT_SYMBOL(drm_exit);
-
 /** File operations structure */
 static const struct file_operations drm_stub_fops = {
 	.owner = THIS_MODULE,
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_edid.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_edid.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_edid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_edid.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,24 +230,32 @@
 		      int block, int len)
 {
 	unsigned char start = block * EDID_LENGTH;
-	struct i2c_msg msgs[] = {
-		{
-			.addr	= DDC_ADDR,
-			.flags	= 0,
-			.len	= 1,
-			.buf	= &start,
-		}, {
-			.addr	= DDC_ADDR,
-			.flags	= I2C_M_RD,
-			.len	= len,
-			.buf	= buf,
-		}
-	};
+	int ret, retries = 5;
 
-	if (i2c_transfer(adapter, msgs, 2) == 2)
-		return 0;
+	/* The core i2c driver will automatically retry the transfer if the
+	 * adapter reports EAGAIN. However, we find that bit-banging transfers
+	 * are susceptible to errors under a heavily loaded machine and
+	 * generate spurious NAKs and timeouts. Retrying the transfer
+	 * of the individual block a few times seems to overcome this.
+	 */
+	do {
+		struct i2c_msg msgs[] = {
+			{
+				.addr	= DDC_ADDR,
+				.flags	= 0,
+				.len	= 1,
+				.buf	= &start,
+			}, {
+				.addr	= DDC_ADDR,
+				.flags	= I2C_M_RD,
+				.len	= len,
+				.buf	= buf,
+			}
+		};
+		ret = i2c_transfer(adapter, msgs, 2);
+	} while (ret != 2 && --retries);
 
-	return -1;
+	return ret == 2 ? 0 : -1;
 }
 
 static u8 *
@@ -449,12 +457,11 @@
 struct drm_display_mode *drm_mode_find_dmt(struct drm_device *dev,
 					   int hsize, int vsize, int fresh)
 {
+	struct drm_display_mode *mode = NULL;
 	int i;
-	struct drm_display_mode *ptr, *mode;
 
-	mode = NULL;
 	for (i = 0; i < drm_num_dmt_modes; i++) {
-		ptr = &drm_dmt_modes[i];
+		const struct drm_display_mode *ptr = &drm_dmt_modes[i];
 		if (hsize == ptr->hdisplay &&
 			vsize == ptr->vdisplay &&
 			fresh == drm_mode_vrefresh(ptr)) {
@@ -885,7 +892,7 @@
 }
 
 static bool
-mode_is_rb(struct drm_display_mode *mode)
+mode_is_rb(const struct drm_display_mode *mode)
 {
 	return (mode->htotal - mode->hdisplay == 160) &&
 	       (mode->hsync_end - mode->hdisplay == 80) &&
@@ -894,7 +901,8 @@
 }
 
 static bool
-mode_in_hsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
+mode_in_hsync_range(const struct drm_display_mode *mode,
+		    struct edid *edid, u8 *t)
 {
 	int hsync, hmin, hmax;
 
@@ -910,7 +918,8 @@
 }
 
 static bool
-mode_in_vsync_range(struct drm_display_mode *mode, struct edid *edid, u8 *t)
+mode_in_vsync_range(const struct drm_display_mode *mode,
+		    struct edid *edid, u8 *t)
 {
 	int vsync, vmin, vmax;
 
@@ -941,7 +950,7 @@
 }
 
 static bool
-mode_in_range(struct drm_display_mode *mode, struct edid *edid,
+mode_in_range(const struct drm_display_mode *mode, struct edid *edid,
 	      struct detailed_timing *timing)
 {
 	u32 max_clock;
@@ -1288,7 +1297,7 @@
 /**
  * Search EDID for CEA extension block.
  */
-static u8 *drm_find_cea_extension(struct edid *edid)
+u8 *drm_find_cea_extension(struct edid *edid)
 {
 	u8 *edid_ext = NULL;
 	int i;
@@ -1309,6 +1318,7 @@
 
 	return edid_ext;
 }
+EXPORT_SYMBOL(drm_find_cea_extension);
 
 /**
  * drm_detect_hdmi_monitor - detect whether monitor is hdmi.
@@ -1472,7 +1482,7 @@
 			int hdisplay, int vdisplay)
 {
 	int i, count, num_modes = 0;
-	struct drm_display_mode *mode, *ptr;
+	struct drm_display_mode *mode;
 	struct drm_device *dev = connector->dev;
 
 	count = sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
@@ -1482,7 +1492,7 @@
 		vdisplay = 0;
 
 	for (i = 0; i < count; i++) {
-		ptr = &drm_dmt_modes[i];
+		const struct drm_display_mode *ptr = &drm_dmt_modes[i];
 		if (hdisplay && vdisplay) {
 			/*
 			 * Only when two are valid, they will be used to check
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_edid_modes.h linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_edid_modes.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_edid_modes.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_edid_modes.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
  * This table is copied from xfree86/modes/xf86EdidModes.c.
  * But the mode with Reduced blank feature is deleted.
  */
-static struct drm_display_mode drm_dmt_modes[] = {
+static const struct drm_display_mode drm_dmt_modes[] = {
 	/* 640x350@85Hz */
 	{ DRM_MODE("640x350", DRM_MODE_TYPE_DRIVER, 31500, 640, 672,
 		   736, 832, 0, 350, 382, 385, 445, 0,
@@ -266,7 +266,7 @@
 static const int drm_num_dmt_modes =
 	sizeof(drm_dmt_modes) / sizeof(struct drm_display_mode);
 
-static struct drm_display_mode edid_est_modes[] = {
+static const struct drm_display_mode edid_est_modes[] = {
 	{ DRM_MODE("800x600", DRM_MODE_TYPE_DRIVER, 40000, 800, 840,
 		   968, 1056, 0, 600, 601, 605, 628, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) }, /* 800x600@60Hz */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_fb_helper.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_fb_helper.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_fb_helper.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_fb_helper.c	2011-05-19 00:06:34.000000000 -0400
@@ -342,9 +342,22 @@
 }
 EXPORT_SYMBOL(drm_fb_helper_debug_leave);
 
+bool drm_fb_helper_restore_fbdev_mode(struct drm_fb_helper *fb_helper)
+{
+	bool error = false;
+	int i, ret;
+	for (i = 0; i < fb_helper->crtc_count; i++) {
+		struct drm_mode_set *mode_set = &fb_helper->crtc_info[i].mode_set;
+		ret = drm_crtc_helper_set_config(mode_set);
+		if (ret)
+			error = true;
+	}
+	return error;
+}
+EXPORT_SYMBOL(drm_fb_helper_restore_fbdev_mode);
+
 bool drm_fb_helper_force_kernel_mode(void)
 {
-	int i = 0;
 	bool ret, error = false;
 	struct drm_fb_helper *helper;
 
@@ -352,12 +365,12 @@
 		return false;
 
 	list_for_each_entry(helper, &kernel_fb_helper_list, kernel_fb_list) {
-		for (i = 0; i < helper->crtc_count; i++) {
-			struct drm_mode_set *mode_set = &helper->crtc_info[i].mode_set;
-			ret = drm_crtc_helper_set_config(mode_set);
-			if (ret)
-				error = true;
-		}
+		if (helper->dev->switch_power_state == DRM_SWITCH_POWER_OFF)
+			continue;
+
+		ret = drm_fb_helper_restore_fbdev_mode(helper);
+		if (ret)
+			error = true;
 	}
 	return error;
 }
@@ -627,6 +640,11 @@
 		value = (red << info->var.red.offset) |
 			(green << info->var.green.offset) |
 			(blue << info->var.blue.offset);
+		if (info->var.transp.length > 0) {
+			u32 mask = (1 << info->var.transp.length) - 1;
+			mask <<= info->var.transp.offset;
+			value |= mask;
+		}
 		palette[regno] = value;
 		return 0;
 	}
@@ -1498,17 +1516,33 @@
 }
 EXPORT_SYMBOL(drm_fb_helper_initial_config);
 
-bool drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
+/**
+ * drm_fb_helper_hotplug_event - respond to a hotplug notification by
+ *                               probing all the outputs attached to the fb.
+ * @fb_helper: the drm_fb_helper
+ *
+ * LOCKING:
+ * Called at runtime, must take mode config lock.
+ *
+ * Scan the connectors attached to the fb_helper and try to put together a
+ * setup after *notification of a change in output configuration.
+ *
+ * RETURNS:
+ * 0 on success and a non-zero error code otherwise.
+ */
+int drm_fb_helper_hotplug_event(struct drm_fb_helper *fb_helper)
 {
+	struct drm_device *dev = fb_helper->dev;
 	int count = 0;
 	u32 max_width, max_height, bpp_sel;
 	bool bound = false, crtcs_bound = false;
 	struct drm_crtc *crtc;
 
 	if (!fb_helper->fb)
-		return false;
+		return 0;
 
-	list_for_each_entry(crtc, &fb_helper->dev->mode_config.crtc_list, head) {
+	mutex_lock(&dev->mode_config.mutex);
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
 		if (crtc->fb)
 			crtcs_bound = true;
 		if (crtc->fb == fb_helper->fb)
@@ -1517,7 +1551,8 @@
 
 	if (!bound && crtcs_bound) {
 		fb_helper->delayed_hotplug = true;
-		return false;
+		mutex_unlock(&dev->mode_config.mutex);
+		return 0;
 	}
 	DRM_DEBUG_KMS("\n");
 
@@ -1528,6 +1563,7 @@
 	count = drm_fb_helper_probe_connector_modes(fb_helper, max_width,
 						    max_height);
 	drm_setup_crtcs(fb_helper);
+	mutex_unlock(&dev->mode_config.mutex);
 
 	return drm_fb_helper_single_fb_probe(fb_helper, bpp_sel);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_gem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_gem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_gem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_gem.c	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 
 	dev->mm_private = mm;
 
-	if (drm_ht_create(&mm->offset_hash, 19)) {
+	if (drm_ht_create(&mm->offset_hash, 12)) {
 		kfree(mm);
 		return -ENOMEM;
 	}
@@ -181,7 +181,7 @@
 /**
  * Removes the mapping from handle to filp for this object.
  */
-static int
+int
 drm_gem_handle_delete(struct drm_file *filp, u32 handle)
 {
 	struct drm_device *dev;
@@ -214,6 +214,7 @@
 
 	return 0;
 }
+EXPORT_SYMBOL(drm_gem_handle_delete);
 
 /**
  * Create a handle for this object. This adds a handle reference
@@ -498,11 +499,12 @@
 void drm_gem_vm_close(struct vm_area_struct *vma)
 {
 	struct drm_gem_object *obj = vma->vm_private_data;
+	struct drm_device *dev = obj->dev;
 
-	mutex_lock(&obj->dev->struct_mutex);
+	mutex_lock(&dev->struct_mutex);
 	drm_vm_close_locked(vma);
 	drm_gem_object_unreference(obj);
-	mutex_unlock(&obj->dev->struct_mutex);
+	mutex_unlock(&dev->struct_mutex);
 }
 EXPORT_SYMBOL(drm_gem_vm_close);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_hashtab.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_hashtab.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_hashtab.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_hashtab.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,27 +39,18 @@
 
 int drm_ht_create(struct drm_open_hash *ht, unsigned int order)
 {
-	unsigned int i;
+	unsigned int size = 1 << order;
 
-	ht->size = 1 << order;
 	ht->order = order;
-	ht->fill = 0;
 	ht->table = NULL;
-	ht->use_vmalloc = ((ht->size * sizeof(*ht->table)) > PAGE_SIZE);
-	if (!ht->use_vmalloc) {
-		ht->table = kcalloc(ht->size, sizeof(*ht->table), GFP_KERNEL);
-	}
-	if (!ht->table) {
-		ht->use_vmalloc = 1;
-		ht->table = vmalloc(ht->size*sizeof(*ht->table));
-	}
+	if (size <= PAGE_SIZE / sizeof(*ht->table))
+		ht->table = kcalloc(size, sizeof(*ht->table), GFP_KERNEL);
+	else
+		ht->table = vzalloc(size*sizeof(*ht->table));
 	if (!ht->table) {
 		DRM_ERROR("Out of memory for hash table\n");
 		return -ENOMEM;
 	}
-	for (i=0; i< ht->size; ++i) {
-		INIT_HLIST_HEAD(&ht->table[i]);
-	}
 	return 0;
 }
 EXPORT_SYMBOL(drm_ht_create);
@@ -180,7 +171,6 @@
 	list = drm_ht_find_key(ht, key);
 	if (list) {
 		hlist_del_init(list);
-		ht->fill--;
 		return 0;
 	}
 	return -EINVAL;
@@ -189,7 +179,6 @@
 int drm_ht_remove_item(struct drm_open_hash *ht, struct drm_hash_item *item)
 {
 	hlist_del_init(&item->head);
-	ht->fill--;
 	return 0;
 }
 EXPORT_SYMBOL(drm_ht_remove_item);
@@ -197,10 +186,10 @@
 void drm_ht_remove(struct drm_open_hash *ht)
 {
 	if (ht->table) {
-		if (ht->use_vmalloc)
-			vfree(ht->table);
-		else
+		if ((PAGE_SIZE / sizeof(*ht->table)) >> ht->order)
 			kfree(ht->table);
+		else
+			vfree(ht->table);
 		ht->table = NULL;
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_info.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_info.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_info.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_info.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,30 +47,19 @@
 	struct drm_minor *minor = node->minor;
 	struct drm_device *dev = minor->dev;
 	struct drm_master *master = minor->master;
-
+	const char *bus_name;
 	if (!master)
 		return 0;
 
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
-		if (master->unique) {
-			seq_printf(m, "%s %s %s\n",
-					dev->driver->platform_device->name,
-					dev_name(dev->dev), master->unique);
-		} else {
-			seq_printf(m, "%s\n",
-				dev->driver->platform_device->name);
-		}
+	bus_name = dev->driver->bus->get_name(dev);
+	if (master->unique) {
+		seq_printf(m, "%s %s %s\n",
+			   bus_name,
+			   dev_name(dev->dev), master->unique);
 	} else {
-		if (master->unique) {
-			seq_printf(m, "%s %s %s\n",
-				dev->driver->pci_driver.name,
-				dev_name(dev->dev), master->unique);
-		} else {
-			seq_printf(m, "%s %s\n", dev->driver->pci_driver.name,
-				dev_name(dev->dev));
-		}
+		seq_printf(m, "%s %s\n",
+			   bus_name, dev_name(dev->dev));
 	}
-
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_ioctl.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_ioctl.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 {
 	struct drm_unique *u = data;
 	struct drm_master *master = file_priv->master;
-	int domain, bus, slot, func, ret;
+	int ret;
 
 	if (master->unique_len || master->unique)
 		return -EBUSY;
@@ -104,50 +104,12 @@
 	if (!u->unique_len || u->unique_len > 1024)
 		return -EINVAL;
 
-	master->unique_len = u->unique_len;
-	master->unique_size = u->unique_len + 1;
-	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-	if (!master->unique) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	if (copy_from_user(master->unique, u->unique, master->unique_len)) {
-		ret = -EFAULT;
-		goto err;
-	}
-
-	master->unique[master->unique_len] = '\0';
-
-	dev->devname = kmalloc(strlen(dev->driver->pci_driver.name) +
-			       strlen(master->unique) + 2, GFP_KERNEL);
-	if (!dev->devname) {
-		ret = -ENOMEM;
-		goto err;
-	}
-
-	sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-		master->unique);
-
-	/* Return error if the busid submitted doesn't match the device's actual
-	 * busid.
-	 */
-	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
-	if (ret != 3) {
-		ret = -EINVAL;
-		goto err;
-	}
-
-	domain = bus >> 8;
-	bus &= 0xff;
+	if (!dev->driver->bus->set_unique)
+		return -EINVAL;
 
-	if ((domain != drm_get_pci_domain(dev)) ||
-	    (bus != dev->pdev->bus->number) ||
-	    (slot != PCI_SLOT(dev->pdev->devfn)) ||
-	    (func != PCI_FUNC(dev->pdev->devfn))) {
-		ret = -EINVAL;
+	ret = dev->driver->bus->set_unique(dev, master, u);
+	if (ret)
 		goto err;
-	}
 
 	return 0;
 
@@ -159,74 +121,15 @@
 static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
 {
 	struct drm_master *master = file_priv->master;
-	int len, ret;
+	int ret;
 
 	if (master->unique != NULL)
 		drm_unset_busid(dev, master);
 
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE)) {
-		master->unique_len = 10 + strlen(dev->platformdev->name);
-		master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
-
-		if (master->unique == NULL)
-			return -ENOMEM;
-
-		len = snprintf(master->unique, master->unique_len,
-			"platform:%s", dev->platformdev->name);
-
-		if (len > master->unique_len) {
-			DRM_ERROR("Unique buffer overflowed\n");
-			ret = -EINVAL;
-			goto err;
-		}
-
-		dev->devname =
-			kmalloc(strlen(dev->platformdev->name) +
-				master->unique_len + 2, GFP_KERNEL);
-
-		if (dev->devname == NULL) {
-			ret = -ENOMEM;
-			goto err;
-		}
-
-		sprintf(dev->devname, "%s@%s", dev->platformdev->name,
-			master->unique);
-
-	} else {
-		master->unique_len = 40;
-		master->unique_size = master->unique_len;
-		master->unique = kmalloc(master->unique_size, GFP_KERNEL);
-		if (master->unique == NULL)
-			return -ENOMEM;
-
-		len = snprintf(master->unique, master->unique_len,
-			"pci:%04x:%02x:%02x.%d",
-			drm_get_pci_domain(dev),
-			dev->pdev->bus->number,
-			PCI_SLOT(dev->pdev->devfn),
-			PCI_FUNC(dev->pdev->devfn));
-		if (len >= master->unique_len) {
-			DRM_ERROR("buffer overflow");
-			ret = -EINVAL;
-			goto err;
-		} else
-			master->unique_len = len;
-
-		dev->devname =
-			kmalloc(strlen(dev->driver->pci_driver.name) +
-				master->unique_len + 2, GFP_KERNEL);
-
-		if (dev->devname == NULL) {
-			ret = -ENOMEM;
-			goto err;
-		}
-
-		sprintf(dev->devname, "%s@%s", dev->driver->pci_driver.name,
-			master->unique);
-	}
-
+	ret = dev->driver->bus->set_busid(dev, master);
+	if (ret)
+		goto err;
 	return 0;
-
 err:
 	drm_unset_busid(dev, master);
 	return ret;
@@ -364,6 +267,28 @@
 	return 0;
 }
 
+/**
+ * Get device/driver capabilities
+ */
+int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
+{
+	struct drm_get_cap *req = data;
+
+	req->value = 0;
+	switch (req->capability) {
+	case DRM_CAP_DUMB_BUFFER:
+		if (dev->driver->dumb_create)
+			req->value = 1;
+		break;
+	case DRM_CAP_VBLANK_HIGH_CRTC:
+		req->value = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
 /**
  * Setversion ioctl.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_irq.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_irq.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,23 +74,13 @@
 {
 	struct drm_irq_busid *p = data;
 
-	if (drm_core_check_feature(dev, DRIVER_USE_PLATFORM_DEVICE))
+	if (!dev->driver->bus->irq_by_busid)
 		return -EINVAL;
 
 	if (!drm_core_check_feature(dev, DRIVER_HAVE_IRQ))
 		return -EINVAL;
 
-	if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
-	    (p->busnum & 0xff) != dev->pdev->bus->number ||
-	    p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
-		return -EINVAL;
-
-	p->irq = dev->pdev->irq;
-
-	DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
-		  p->irq);
-
-	return 0;
+	return dev->driver->bus->irq_by_busid(dev, p);
 }
 
 /*
@@ -942,11 +932,34 @@
 
 void drm_vblank_off(struct drm_device *dev, int crtc)
 {
+	struct drm_pending_vblank_event *e, *t;
+	struct timeval now;
 	unsigned long irqflags;
+	unsigned int seq;
 
 	spin_lock_irqsave(&dev->vbl_lock, irqflags);
 	vblank_disable_and_save(dev, crtc);
 	DRM_WAKEUP(&dev->vbl_queue[crtc]);
+
+	/* Send any queued vblank events, lest the natives grow disquiet */
+	seq = drm_vblank_count_and_time(dev, crtc, &now);
+	list_for_each_entry_safe(e, t, &dev->vblank_event_list, base.link) {
+		if (e->pipe != crtc)
+			continue;
+		DRM_DEBUG("Sending premature vblank event on disable: \
+			  wanted %d, current %d\n",
+			  e->event.sequence, seq);
+
+		e->event.sequence = seq;
+		e->event.tv_sec = now.tv_sec;
+		e->event.tv_usec = now.tv_usec;
+		drm_vblank_put(dev, e->pipe);
+		list_move_tail(&e->base.link, &e->base.file_priv->event_list);
+		wake_up_interruptible(&e->base.file_priv->event_wait);
+		trace_drm_vblank_event_delivered(e->base.pid, e->pipe,
+						 e->event.sequence);
+	}
+
 	spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
 }
 EXPORT_SYMBOL(drm_vblank_off);
@@ -1135,7 +1148,7 @@
 {
 	union drm_wait_vblank *vblwait = data;
 	int ret = 0;
-	unsigned int flags, seq, crtc;
+	unsigned int flags, seq, crtc, high_crtc;
 
 	if ((!drm_dev_to_irq(dev)) || (!dev->irq_enabled))
 		return -EINVAL;
@@ -1144,16 +1157,21 @@
 		return -EINVAL;
 
 	if (vblwait->request.type &
-	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK)) {
+	    ~(_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
+	      _DRM_VBLANK_HIGH_CRTC_MASK)) {
 		DRM_ERROR("Unsupported type value 0x%x, supported mask 0x%x\n",
 			  vblwait->request.type,
-			  (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK));
+			  (_DRM_VBLANK_TYPES_MASK | _DRM_VBLANK_FLAGS_MASK |
+			   _DRM_VBLANK_HIGH_CRTC_MASK));
 		return -EINVAL;
 	}
 
 	flags = vblwait->request.type & _DRM_VBLANK_FLAGS_MASK;
-	crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
-
+	high_crtc = (vblwait->request.type & _DRM_VBLANK_HIGH_CRTC_MASK);
+	if (high_crtc)
+		crtc = high_crtc >> _DRM_VBLANK_HIGH_CRTC_SHIFT;
+	else
+		crtc = flags & _DRM_VBLANK_SECONDARY ? 1 : 0;
 	if (crtc >= dev->num_crtcs)
 		return -EINVAL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_mm.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_mm.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_mm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_mm.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,8 +64,8 @@
 		else {
 			child =
 			    list_entry(mm->unused_nodes.next,
-				       struct drm_mm_node, free_stack);
-			list_del(&child->free_stack);
+				       struct drm_mm_node, node_list);
+			list_del(&child->node_list);
 			--mm->num_unused;
 		}
 		spin_unlock(&mm->unused_lock);
@@ -94,195 +94,242 @@
 			return ret;
 		}
 		++mm->num_unused;
-		list_add_tail(&node->free_stack, &mm->unused_nodes);
+		list_add_tail(&node->node_list, &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, int atomic)
+static inline unsigned long drm_mm_hole_node_start(struct drm_mm_node *hole_node)
 {
-	struct drm_mm_node *child;
-
-	child = drm_mm_kmalloc(mm, atomic);
-	if (unlikely(child == NULL))
-		return -ENOMEM;
-
-	child->free = 1;
-	child->size = size;
-	child->start = start;
-	child->mm = mm;
+	return hole_node->start + hole_node->size;
+}
 
-	list_add_tail(&child->node_list, &mm->node_list);
-	list_add_tail(&child->free_stack, &mm->free_stack);
+static inline unsigned long drm_mm_hole_node_end(struct drm_mm_node *hole_node)
+{
+	struct drm_mm_node *next_node =
+		list_entry(hole_node->node_list.next, struct drm_mm_node,
+			   node_list);
 
-	return 0;
+	return next_node->start;
 }
 
-static struct drm_mm_node *drm_mm_split_at_start(struct drm_mm_node *parent,
-						 unsigned long size,
-						 int atomic)
+static void drm_mm_insert_helper(struct drm_mm_node *hole_node,
+				 struct drm_mm_node *node,
+				 unsigned long size, unsigned alignment)
 {
-	struct drm_mm_node *child;
+	struct drm_mm *mm = hole_node->mm;
+	unsigned long tmp = 0, wasted = 0;
+	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
+	unsigned long hole_end = drm_mm_hole_node_end(hole_node);
 
-	child = drm_mm_kmalloc(parent->mm, atomic);
-	if (unlikely(child == NULL))
-		return NULL;
+	BUG_ON(!hole_node->hole_follows || node->allocated);
 
-	INIT_LIST_HEAD(&child->free_stack);
+	if (alignment)
+		tmp = hole_start % alignment;
 
-	child->size = size;
-	child->start = parent->start;
-	child->mm = parent->mm;
+	if (!tmp) {
+		hole_node->hole_follows = 0;
+		list_del_init(&hole_node->hole_stack);
+	} else
+		wasted = alignment - tmp;
 
-	list_add_tail(&child->node_list, &parent->node_list);
-	INIT_LIST_HEAD(&child->free_stack);
+	node->start = hole_start + wasted;
+	node->size = size;
+	node->mm = mm;
+	node->allocated = 1;
 
-	parent->size -= size;
-	parent->start += size;
-	return child;
-}
+	INIT_LIST_HEAD(&node->hole_stack);
+	list_add(&node->node_list, &hole_node->node_list);
 
+	BUG_ON(node->start + node->size > hole_end);
 
-struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *node,
+	if (node->start + node->size < hole_end) {
+		list_add(&node->hole_stack, &mm->hole_stack);
+		node->hole_follows = 1;
+	} else {
+		node->hole_follows = 0;
+	}
+}
+
+struct drm_mm_node *drm_mm_get_block_generic(struct drm_mm_node *hole_node,
 					     unsigned long size,
 					     unsigned alignment,
 					     int atomic)
 {
+	struct drm_mm_node *node;
 
-	struct drm_mm_node *align_splitoff = NULL;
-	unsigned tmp = 0;
+	node = drm_mm_kmalloc(hole_node->mm, atomic);
+	if (unlikely(node == NULL))
+		return NULL;
 
-	if (alignment)
-		tmp = node->start % alignment;
+	drm_mm_insert_helper(hole_node, node, size, alignment);
 
-	if (tmp) {
-		align_splitoff =
-		    drm_mm_split_at_start(node, alignment - tmp, atomic);
-		if (unlikely(align_splitoff == NULL))
-			return NULL;
-	}
+	return node;
+}
+EXPORT_SYMBOL(drm_mm_get_block_generic);
 
-	if (node->size == size) {
-		list_del_init(&node->free_stack);
-		node->free = 0;
-	} else {
-		node = drm_mm_split_at_start(node, size, atomic);
-	}
+/**
+ * Search for free space and insert a preallocated memory node. Returns
+ * -ENOSPC if no suitable free area is available. The preallocated memory node
+ * must be cleared.
+ */
+int drm_mm_insert_node(struct drm_mm *mm, struct drm_mm_node *node,
+		       unsigned long size, unsigned alignment)
+{
+	struct drm_mm_node *hole_node;
 
-	if (align_splitoff)
-		drm_mm_put_block(align_splitoff);
+	hole_node = drm_mm_search_free(mm, size, alignment, 0);
+	if (!hole_node)
+		return -ENOSPC;
 
-	return node;
+	drm_mm_insert_helper(hole_node, node, size, alignment);
+
+	return 0;
 }
-EXPORT_SYMBOL(drm_mm_get_block_generic);
+EXPORT_SYMBOL(drm_mm_insert_node);
 
-struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *node,
-						unsigned long size,
-						unsigned alignment,
-						unsigned long start,
-						unsigned long end,
-						int atomic)
+static void drm_mm_insert_helper_range(struct drm_mm_node *hole_node,
+				       struct drm_mm_node *node,
+				       unsigned long size, unsigned alignment,
+				       unsigned long start, unsigned long end)
 {
-	struct drm_mm_node *align_splitoff = NULL;
-	unsigned tmp = 0;
-	unsigned wasted = 0;
+	struct drm_mm *mm = hole_node->mm;
+	unsigned long tmp = 0, wasted = 0;
+	unsigned long hole_start = drm_mm_hole_node_start(hole_node);
+	unsigned long hole_end = drm_mm_hole_node_end(hole_node);
 
-	if (node->start < start)
-		wasted += start - node->start;
+	BUG_ON(!hole_node->hole_follows || node->allocated);
+
+	if (hole_start < start)
+		wasted += start - hole_start;
 	if (alignment)
-		tmp = ((node->start + wasted) % alignment);
+		tmp = (hole_start + wasted) % alignment;
 
 	if (tmp)
 		wasted += alignment - tmp;
-	if (wasted) {
-		align_splitoff = drm_mm_split_at_start(node, wasted, atomic);
-		if (unlikely(align_splitoff == NULL))
-			return NULL;
+
+	if (!wasted) {
+		hole_node->hole_follows = 0;
+		list_del_init(&hole_node->hole_stack);
 	}
 
-	if (node->size == size) {
-		list_del_init(&node->free_stack);
-		node->free = 0;
+	node->start = hole_start + wasted;
+	node->size = size;
+	node->mm = mm;
+	node->allocated = 1;
+
+	INIT_LIST_HEAD(&node->hole_stack);
+	list_add(&node->node_list, &hole_node->node_list);
+
+	BUG_ON(node->start + node->size > hole_end);
+	BUG_ON(node->start + node->size > end);
+
+	if (node->start + node->size < hole_end) {
+		list_add(&node->hole_stack, &mm->hole_stack);
+		node->hole_follows = 1;
 	} else {
-		node = drm_mm_split_at_start(node, size, atomic);
+		node->hole_follows = 0;
 	}
+}
 
-	if (align_splitoff)
-		drm_mm_put_block(align_splitoff);
+struct drm_mm_node *drm_mm_get_block_range_generic(struct drm_mm_node *hole_node,
+						unsigned long size,
+						unsigned alignment,
+						unsigned long start,
+						unsigned long end,
+						int atomic)
+{
+	struct drm_mm_node *node;
+
+	node = drm_mm_kmalloc(hole_node->mm, atomic);
+	if (unlikely(node == NULL))
+		return NULL;
+
+	drm_mm_insert_helper_range(hole_node, node, size, alignment,
+				   start, end);
 
 	return node;
 }
 EXPORT_SYMBOL(drm_mm_get_block_range_generic);
 
-/*
- * Put a block. Merge with the previous and / or next block if they are free.
- * Otherwise add to the free stack.
+/**
+ * Search for free space and insert a preallocated memory node. Returns
+ * -ENOSPC if no suitable free area is available. This is for range
+ * restricted allocations. The preallocated memory node must be cleared.
  */
+int drm_mm_insert_node_in_range(struct drm_mm *mm, struct drm_mm_node *node,
+				unsigned long size, unsigned alignment,
+				unsigned long start, unsigned long end)
+{
+	struct drm_mm_node *hole_node;
 
-void drm_mm_put_block(struct drm_mm_node *cur)
+	hole_node = drm_mm_search_free_in_range(mm, size, alignment,
+						start, end, 0);
+	if (!hole_node)
+		return -ENOSPC;
+
+	drm_mm_insert_helper_range(hole_node, node, size, alignment,
+				   start, end);
+
+	return 0;
+}
+EXPORT_SYMBOL(drm_mm_insert_node_in_range);
+
+/**
+ * Remove a memory node from the allocator.
+ */
+void drm_mm_remove_node(struct drm_mm_node *node)
 {
+	struct drm_mm *mm = node->mm;
+	struct drm_mm_node *prev_node;
 
-	struct drm_mm *mm = cur->mm;
-	struct list_head *cur_head = &cur->node_list;
-	struct list_head *root_head = &mm->node_list;
-	struct drm_mm_node *prev_node = NULL;
-	struct drm_mm_node *next_node;
+	BUG_ON(node->scanned_block || node->scanned_prev_free
+				   || node->scanned_next_free);
 
-	int merged = 0;
+	prev_node =
+	    list_entry(node->node_list.prev, struct drm_mm_node, node_list);
 
-	BUG_ON(cur->scanned_block || cur->scanned_prev_free
-				  || cur->scanned_next_free);
+	if (node->hole_follows) {
+		BUG_ON(drm_mm_hole_node_start(node)
+				== drm_mm_hole_node_end(node));
+		list_del(&node->hole_stack);
+	} else
+		BUG_ON(drm_mm_hole_node_start(node)
+				!= drm_mm_hole_node_end(node));
 
-	if (cur_head->prev != root_head) {
-		prev_node =
-		    list_entry(cur_head->prev, struct drm_mm_node, node_list);
-		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, node_list);
-		if (next_node->free) {
-			if (merged) {
-				prev_node->size += next_node->size;
-				list_del(&next_node->node_list);
-				list_del(&next_node->free_stack);
-				spin_lock(&mm->unused_lock);
-				if (mm->num_unused < MM_UNUSED_TARGET) {
-					list_add(&next_node->free_stack,
-						 &mm->unused_nodes);
-					++mm->num_unused;
-				} else
-					kfree(next_node);
-				spin_unlock(&mm->unused_lock);
-			} else {
-				next_node->size += cur->size;
-				next_node->start = cur->start;
-				merged = 1;
-			}
-		}
-	}
-	if (!merged) {
-		cur->free = 1;
-		list_add(&cur->free_stack, &mm->free_stack);
-	} else {
-		list_del(&cur->node_list);
-		spin_lock(&mm->unused_lock);
-		if (mm->num_unused < MM_UNUSED_TARGET) {
-			list_add(&cur->free_stack, &mm->unused_nodes);
-			++mm->num_unused;
-		} else
-			kfree(cur);
-		spin_unlock(&mm->unused_lock);
-	}
+	if (!prev_node->hole_follows) {
+		prev_node->hole_follows = 1;
+		list_add(&prev_node->hole_stack, &mm->hole_stack);
+	} else
+		list_move(&prev_node->hole_stack, &mm->hole_stack);
+
+	list_del(&node->node_list);
+	node->allocated = 0;
 }
+EXPORT_SYMBOL(drm_mm_remove_node);
+
+/*
+ * Remove a memory node from the allocator and free the allocated struct
+ * drm_mm_node. Only to be used on a struct drm_mm_node obtained by one of the
+ * drm_mm_get_block functions.
+ */
+void drm_mm_put_block(struct drm_mm_node *node)
+{
 
+	struct drm_mm *mm = node->mm;
+
+	drm_mm_remove_node(node);
+
+	spin_lock(&mm->unused_lock);
+	if (mm->num_unused < MM_UNUSED_TARGET) {
+		list_add(&node->node_list, &mm->unused_nodes);
+		++mm->num_unused;
+	} else
+		kfree(node);
+	spin_unlock(&mm->unused_lock);
+}
 EXPORT_SYMBOL(drm_mm_put_block);
 
 static int check_free_hole(unsigned long start, unsigned long end,
@@ -319,8 +366,10 @@
 	best = NULL;
 	best_size = ~0UL;
 
-	list_for_each_entry(entry, &mm->free_stack, free_stack) {
-		if (!check_free_hole(entry->start, entry->start + entry->size,
+	list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
+		BUG_ON(!entry->hole_follows);
+		if (!check_free_hole(drm_mm_hole_node_start(entry),
+				     drm_mm_hole_node_end(entry),
 				     size, alignment))
 			continue;
 
@@ -353,12 +402,13 @@
 	best = NULL;
 	best_size = ~0UL;
 
-	list_for_each_entry(entry, &mm->free_stack, free_stack) {
-		unsigned long adj_start = entry->start < start ?
-			start : entry->start;
-		unsigned long adj_end = entry->start + entry->size > end ?
-			end : entry->start + entry->size;
+	list_for_each_entry(entry, &mm->hole_stack, hole_stack) {
+		unsigned long adj_start = drm_mm_hole_node_start(entry) < start ?
+			start : drm_mm_hole_node_start(entry);
+		unsigned long adj_end = drm_mm_hole_node_end(entry) > end ?
+			end : drm_mm_hole_node_end(entry);
 
+		BUG_ON(!entry->hole_follows);
 		if (!check_free_hole(adj_start, adj_end, size, alignment))
 			continue;
 
@@ -376,6 +426,23 @@
 EXPORT_SYMBOL(drm_mm_search_free_in_range);
 
 /**
+ * Moves an allocation. To be used with embedded struct drm_mm_node.
+ */
+void drm_mm_replace_node(struct drm_mm_node *old, struct drm_mm_node *new)
+{
+	list_replace(&old->node_list, &new->node_list);
+	list_replace(&old->hole_stack, &new->hole_stack);
+	new->hole_follows = old->hole_follows;
+	new->mm = old->mm;
+	new->start = old->start;
+	new->size = old->size;
+
+	old->allocated = 0;
+	new->allocated = 1;
+}
+EXPORT_SYMBOL(drm_mm_replace_node);
+
+/**
  * Initializa lru scanning.
  *
  * This simply sets up the scanning routines with the parameters for the desired
@@ -393,6 +460,7 @@
 	mm->scan_hit_start = 0;
 	mm->scan_hit_size = 0;
 	mm->scan_check_range = 0;
+	mm->prev_scanned_node = NULL;
 }
 EXPORT_SYMBOL(drm_mm_init_scan);
 
@@ -418,6 +486,7 @@
 	mm->scan_start = start;
 	mm->scan_end = end;
 	mm->scan_check_range = 1;
+	mm->prev_scanned_node = NULL;
 }
 EXPORT_SYMBOL(drm_mm_init_scan_with_range);
 
@@ -430,70 +499,42 @@
 int drm_mm_scan_add_block(struct drm_mm_node *node)
 {
 	struct drm_mm *mm = node->mm;
-	struct list_head *prev_free, *next_free;
-	struct drm_mm_node *prev_node, *next_node;
+	struct drm_mm_node *prev_node;
+	unsigned long hole_start, hole_end;
 	unsigned long adj_start;
 	unsigned long adj_end;
 
 	mm->scanned_blocks++;
 
-	prev_free = next_free = NULL;
-
-	BUG_ON(node->free);
+	BUG_ON(node->scanned_block);
 	node->scanned_block = 1;
-	node->free = 1;
-
-	if (node->node_list.prev != &mm->node_list) {
-		prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
-				       node_list);
-
-		if (prev_node->free) {
-			list_del(&prev_node->node_list);
-
-			node->start = prev_node->start;
-			node->size += prev_node->size;
 
-			prev_node->scanned_prev_free = 1;
-
-			prev_free = &prev_node->free_stack;
-		}
-	}
-
-	if (node->node_list.next != &mm->node_list) {
-		next_node = list_entry(node->node_list.next, struct drm_mm_node,
-				       node_list);
-
-		if (next_node->free) {
-			list_del(&next_node->node_list);
-
-			node->size += next_node->size;
-
-			next_node->scanned_next_free = 1;
-
-			next_free = &next_node->free_stack;
-		}
-	}
+	prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
+			       node_list);
 
-	/* The free_stack list is not used for allocated objects, so these two
-	 * pointers can be abused (as long as no allocations in this memory
-	 * manager happens). */
-	node->free_stack.prev = prev_free;
-	node->free_stack.next = next_free;
+	node->scanned_preceeds_hole = prev_node->hole_follows;
+	prev_node->hole_follows = 1;
+	list_del(&node->node_list);
+	node->node_list.prev = &prev_node->node_list;
+	node->node_list.next = &mm->prev_scanned_node->node_list;
+	mm->prev_scanned_node = node;
 
+	hole_start = drm_mm_hole_node_start(prev_node);
+	hole_end = drm_mm_hole_node_end(prev_node);
 	if (mm->scan_check_range) {
-		adj_start = node->start < mm->scan_start ?
-			mm->scan_start : node->start;
-		adj_end = node->start + node->size > mm->scan_end ?
-			mm->scan_end : node->start + node->size;
+		adj_start = hole_start < mm->scan_start ?
+			mm->scan_start : hole_start;
+		adj_end = hole_end > mm->scan_end ?
+			mm->scan_end : hole_end;
 	} else {
-		adj_start = node->start;
-		adj_end = node->start + node->size;
+		adj_start = hole_start;
+		adj_end = hole_end;
 	}
 
 	if (check_free_hole(adj_start , adj_end,
 			    mm->scan_size, mm->scan_alignment)) {
-		mm->scan_hit_start = node->start;
-		mm->scan_hit_size = node->size;
+		mm->scan_hit_start = hole_start;
+		mm->scan_hit_size = hole_end;
 
 		return 1;
 	}
@@ -510,7 +551,7 @@
  * corrupted.
  *
  * When the scan list is empty, the selected memory nodes can be freed. An
- * immediatly following drm_mm_search_free with best_match = 0 will then return
+ * immediately following drm_mm_search_free with best_match = 0 will then return
  * the just freed block (because its at the top of the free_stack list).
  *
  * Returns one if this block should be evicted, zero otherwise. Will always
@@ -519,39 +560,19 @@
 int drm_mm_scan_remove_block(struct drm_mm_node *node)
 {
 	struct drm_mm *mm = node->mm;
-	struct drm_mm_node *prev_node, *next_node;
+	struct drm_mm_node *prev_node;
 
 	mm->scanned_blocks--;
 
 	BUG_ON(!node->scanned_block);
 	node->scanned_block = 0;
-	node->free = 0;
-
-	prev_node = list_entry(node->free_stack.prev, struct drm_mm_node,
-			       free_stack);
-	next_node = list_entry(node->free_stack.next, struct drm_mm_node,
-			       free_stack);
-
-	if (prev_node) {
-		BUG_ON(!prev_node->scanned_prev_free);
-		prev_node->scanned_prev_free = 0;
-
-		list_add_tail(&prev_node->node_list, &node->node_list);
-
-		node->start = prev_node->start + prev_node->size;
-		node->size -= prev_node->size;
-	}
 
-	if (next_node) {
-		BUG_ON(!next_node->scanned_next_free);
-		next_node->scanned_next_free = 0;
-
-		list_add(&next_node->node_list, &node->node_list);
-
-		node->size -= next_node->size;
-	}
+	prev_node = list_entry(node->node_list.prev, struct drm_mm_node,
+			       node_list);
 
-	INIT_LIST_HEAD(&node->free_stack);
+	prev_node->hole_follows = node->scanned_preceeds_hole;
+	INIT_LIST_HEAD(&node->node_list);
+	list_add(&node->node_list, &prev_node->node_list);
 
 	/* Only need to check for containement because start&size for the
 	 * complete resulting free block (not just the desired part) is
@@ -568,7 +589,7 @@
 
 int drm_mm_clean(struct drm_mm * mm)
 {
-	struct list_head *head = &mm->node_list;
+	struct list_head *head = &mm->head_node.node_list;
 
 	return (head->next->next == head);
 }
@@ -576,38 +597,40 @@
 
 int drm_mm_init(struct drm_mm * mm, unsigned long start, unsigned long size)
 {
-	INIT_LIST_HEAD(&mm->node_list);
-	INIT_LIST_HEAD(&mm->free_stack);
+	INIT_LIST_HEAD(&mm->hole_stack);
 	INIT_LIST_HEAD(&mm->unused_nodes);
 	mm->num_unused = 0;
 	mm->scanned_blocks = 0;
 	spin_lock_init(&mm->unused_lock);
 
-	return drm_mm_create_tail_node(mm, start, size, 0);
+	/* Clever trick to avoid a special case in the free hole tracking. */
+	INIT_LIST_HEAD(&mm->head_node.node_list);
+	INIT_LIST_HEAD(&mm->head_node.hole_stack);
+	mm->head_node.hole_follows = 1;
+	mm->head_node.scanned_block = 0;
+	mm->head_node.scanned_prev_free = 0;
+	mm->head_node.scanned_next_free = 0;
+	mm->head_node.mm = mm;
+	mm->head_node.start = start + size;
+	mm->head_node.size = start - mm->head_node.start;
+	list_add_tail(&mm->head_node.hole_stack, &mm->hole_stack);
+
+	return 0;
 }
 EXPORT_SYMBOL(drm_mm_init);
 
 void drm_mm_takedown(struct drm_mm * mm)
 {
-	struct list_head *bnode = mm->free_stack.next;
-	struct drm_mm_node *entry;
-	struct drm_mm_node *next;
-
-	entry = list_entry(bnode, struct drm_mm_node, free_stack);
+	struct drm_mm_node *entry, *next;
 
-	if (entry->node_list.next != &mm->node_list ||
-	    entry->free_stack.next != &mm->free_stack) {
+	if (!list_empty(&mm->head_node.node_list)) {
 		DRM_ERROR("Memory manager not clean. Delaying takedown\n");
 		return;
 	}
 
-	list_del(&entry->free_stack);
-	list_del(&entry->node_list);
-	kfree(entry);
-
 	spin_lock(&mm->unused_lock);
-	list_for_each_entry_safe(entry, next, &mm->unused_nodes, free_stack) {
-		list_del(&entry->free_stack);
+	list_for_each_entry_safe(entry, next, &mm->unused_nodes, node_list) {
+		list_del(&entry->node_list);
 		kfree(entry);
 		--mm->num_unused;
 	}
@@ -620,19 +643,37 @@
 void drm_mm_debug_table(struct drm_mm *mm, const char *prefix)
 {
 	struct drm_mm_node *entry;
-	int total_used = 0, total_free = 0, total = 0;
+	unsigned long total_used = 0, total_free = 0, total = 0;
+	unsigned long hole_start, hole_end, hole_size;
 
-	list_for_each_entry(entry, &mm->node_list, node_list) {
-		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8ld: %s\n",
+	hole_start = drm_mm_hole_node_start(&mm->head_node);
+	hole_end = drm_mm_hole_node_end(&mm->head_node);
+	hole_size = hole_end - hole_start;
+	if (hole_size)
+		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
+			prefix, hole_start, hole_end,
+			hole_size);
+	total_free += hole_size;
+
+	drm_mm_for_each_node(entry, mm) {
+		printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: used\n",
 			prefix, entry->start, entry->start + entry->size,
-			entry->size, entry->free ? "free" : "used");
-		total += entry->size;
-		if (entry->free)
-			total_free += entry->size;
-		else
-			total_used += entry->size;
+			entry->size);
+		total_used += entry->size;
+
+		if (entry->hole_follows) {
+			hole_start = drm_mm_hole_node_start(entry);
+			hole_end = drm_mm_hole_node_end(entry);
+			hole_size = hole_end - hole_start;
+			printk(KERN_DEBUG "%s 0x%08lx-0x%08lx: %8lu: free\n",
+				prefix, hole_start, hole_end,
+				hole_size);
+			total_free += hole_size;
+		}
 	}
-	printk(KERN_DEBUG "%s total: %d, used %d free %d\n", prefix, total,
+	total = total_free + total_used;
+
+	printk(KERN_DEBUG "%s total: %lu, used %lu free %lu\n", prefix, total,
 		total_used, total_free);
 }
 EXPORT_SYMBOL(drm_mm_debug_table);
@@ -641,17 +682,34 @@
 int drm_mm_dump_table(struct seq_file *m, struct drm_mm *mm)
 {
 	struct drm_mm_node *entry;
-	int total_used = 0, total_free = 0, total = 0;
+	unsigned long total_used = 0, total_free = 0, total = 0;
+	unsigned long hole_start, hole_end, hole_size;
 
-	list_for_each_entry(entry, &mm->node_list, node_list) {
-		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: %s\n", entry->start, entry->start + entry->size, entry->size, entry->free ? "free" : "used");
-		total += entry->size;
-		if (entry->free)
-			total_free += entry->size;
-		else
-			total_used += entry->size;
+	hole_start = drm_mm_hole_node_start(&mm->head_node);
+	hole_end = drm_mm_hole_node_end(&mm->head_node);
+	hole_size = hole_end - hole_start;
+	if (hole_size)
+		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
+				hole_start, hole_end, hole_size);
+	total_free += hole_size;
+
+	drm_mm_for_each_node(entry, mm) {
+		seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: used\n",
+				entry->start, entry->start + entry->size,
+				entry->size);
+		total_used += entry->size;
+		if (entry->hole_follows) {
+			hole_start = drm_mm_hole_node_start(entry);
+			hole_end = drm_mm_hole_node_end(entry);
+			hole_size = hole_end - hole_start;
+			seq_printf(m, "0x%08lx-0x%08lx: 0x%08lx: free\n",
+					hole_start, hole_end, hole_size);
+			total_free += hole_size;
+		}
 	}
-	seq_printf(m, "total: %d, used %d free %d\n", total, total_used, total_free);
+	total = total_free + total_used;
+
+	seq_printf(m, "total: %lu, used %lu free %lu\n", total, total_used, total_free);
 	return 0;
 }
 EXPORT_SYMBOL(drm_mm_dump_table);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_modes.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_modes.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_modes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_modes.c	2011-05-19 00:06:34.000000000 -0400
@@ -593,7 +593,7 @@
  *
  * Return @modes's hsync rate in kHz, rounded to the nearest int.
  */
-int drm_mode_hsync(struct drm_display_mode *mode)
+int drm_mode_hsync(const struct drm_display_mode *mode)
 {
 	unsigned int calc_val;
 
@@ -627,7 +627,7 @@
  * If it is 70.288, it will return 70Hz.
  * If it is 59.6, it will return 60Hz.
  */
-int drm_mode_vrefresh(struct drm_display_mode *mode)
+int drm_mode_vrefresh(const struct drm_display_mode *mode)
 {
 	int refresh = 0;
 	unsigned int calc_val;
@@ -725,7 +725,7 @@
  * a pointer to it.  Used to create new instances of established modes.
  */
 struct drm_display_mode *drm_mode_duplicate(struct drm_device *dev,
-					    struct drm_display_mode *mode)
+					    const struct drm_display_mode *mode)
 {
 	struct drm_display_mode *nmode;
 	int new_id;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_pci.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_pci.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,6 +125,176 @@
 EXPORT_SYMBOL(drm_pci_free);
 
 #ifdef CONFIG_PCI
+
+static int drm_get_pci_domain(struct drm_device *dev)
+{
+#ifndef __alpha__
+	/* For historical reasons, drm_get_pci_domain() is busticated
+	 * on most archs and has to remain so for userspace interface
+	 * < 1.4, except on alpha which was right from the beginning
+	 */
+	if (dev->if_version < 0x10004)
+		return 0;
+#endif /* __alpha__ */
+
+	return pci_domain_nr(dev->pdev->bus);
+}
+
+static int drm_pci_get_irq(struct drm_device *dev)
+{
+	return dev->pdev->irq;
+}
+
+static const char *drm_pci_get_name(struct drm_device *dev)
+{
+	struct pci_driver *pdriver = dev->driver->kdriver.pci;
+	return pdriver->name;
+}
+
+int drm_pci_set_busid(struct drm_device *dev, struct drm_master *master)
+{
+	int len, ret;
+	struct pci_driver *pdriver = dev->driver->kdriver.pci;
+	master->unique_len = 40;
+	master->unique_size = master->unique_len;
+	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+	if (master->unique == NULL)
+		return -ENOMEM;
+
+
+	len = snprintf(master->unique, master->unique_len,
+		       "pci:%04x:%02x:%02x.%d",
+		       drm_get_pci_domain(dev),
+		       dev->pdev->bus->number,
+		       PCI_SLOT(dev->pdev->devfn),
+		       PCI_FUNC(dev->pdev->devfn));
+
+	if (len >= master->unique_len) {
+		DRM_ERROR("buffer overflow");
+		ret = -EINVAL;
+		goto err;
+	} else
+		master->unique_len = len;
+
+	dev->devname =
+		kmalloc(strlen(pdriver->name) +
+			master->unique_len + 2, GFP_KERNEL);
+
+	if (dev->devname == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sprintf(dev->devname, "%s@%s", pdriver->name,
+		master->unique);
+
+	return 0;
+err:
+	return ret;
+}
+
+int drm_pci_set_unique(struct drm_device *dev,
+		       struct drm_master *master,
+		       struct drm_unique *u)
+{
+	int domain, bus, slot, func, ret;
+	const char *bus_name;
+
+	master->unique_len = u->unique_len;
+	master->unique_size = u->unique_len + 1;
+	master->unique = kmalloc(master->unique_size, GFP_KERNEL);
+	if (!master->unique) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (copy_from_user(master->unique, u->unique, master->unique_len)) {
+		ret = -EFAULT;
+		goto err;
+	}
+
+	master->unique[master->unique_len] = '\0';
+
+	bus_name = dev->driver->bus->get_name(dev);
+	dev->devname = kmalloc(strlen(bus_name) +
+			       strlen(master->unique) + 2, GFP_KERNEL);
+	if (!dev->devname) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sprintf(dev->devname, "%s@%s", bus_name,
+		master->unique);
+
+	/* Return error if the busid submitted doesn't match the device's actual
+	 * busid.
+	 */
+	ret = sscanf(master->unique, "PCI:%d:%d:%d", &bus, &slot, &func);
+	if (ret != 3) {
+		ret = -EINVAL;
+		goto err;
+	}
+
+	domain = bus >> 8;
+	bus &= 0xff;
+
+	if ((domain != drm_get_pci_domain(dev)) ||
+	    (bus != dev->pdev->bus->number) ||
+	    (slot != PCI_SLOT(dev->pdev->devfn)) ||
+	    (func != PCI_FUNC(dev->pdev->devfn))) {
+		ret = -EINVAL;
+		goto err;
+	}
+	return 0;
+err:
+	return ret;
+}
+
+
+int drm_pci_irq_by_busid(struct drm_device *dev, struct drm_irq_busid *p)
+{
+	if ((p->busnum >> 8) != drm_get_pci_domain(dev) ||
+	    (p->busnum & 0xff) != dev->pdev->bus->number ||
+	    p->devnum != PCI_SLOT(dev->pdev->devfn) || p->funcnum != PCI_FUNC(dev->pdev->devfn))
+		return -EINVAL;
+
+	p->irq = dev->pdev->irq;
+
+	DRM_DEBUG("%d:%d:%d => IRQ %d\n", p->busnum, p->devnum, p->funcnum,
+		  p->irq);
+	return 0;
+}
+
+int drm_pci_agp_init(struct drm_device *dev)
+{
+	if (drm_core_has_AGP(dev)) {
+		if (drm_pci_device_is_agp(dev))
+			dev->agp = drm_agp_init(dev);
+		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
+		    && (dev->agp == NULL)) {
+			DRM_ERROR("Cannot initialize the agpgart module.\n");
+			return -EINVAL;
+		}
+		if (drm_core_has_MTRR(dev)) {
+			if (dev->agp)
+				dev->agp->agp_mtrr =
+					mtrr_add(dev->agp->agp_info.aper_base,
+						 dev->agp->agp_info.aper_size *
+						 1024 * 1024, MTRR_TYPE_WRCOMB, 1);
+		}
+	}
+	return 0;
+}
+
+static struct drm_bus drm_pci_bus = {
+	.bus_type = DRIVER_BUS_PCI,
+	.get_irq = drm_pci_get_irq,
+	.get_name = drm_pci_get_name,
+	.set_busid = drm_pci_set_busid,
+	.set_unique = drm_pci_set_unique,
+	.agp_init = drm_pci_agp_init,
+};
+
 /**
  * Register.
  *
@@ -219,7 +389,7 @@
 EXPORT_SYMBOL(drm_get_pci_dev);
 
 /**
- * PCI device initialization. Called via drm_init at module load time,
+ * PCI device initialization. Called direct from modules at load time.
  *
  * \return zero on success or a negative number on failure.
  *
@@ -229,18 +399,24 @@
  * Expands the \c DRIVER_PREINIT and \c DRIVER_POST_INIT macros before and
  * after the initialization for driver customization.
  */
-int drm_pci_init(struct drm_driver *driver)
+int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 {
 	struct pci_dev *pdev = NULL;
 	const struct pci_device_id *pid;
 	int i;
 
+	DRM_DEBUG("\n");
+
+	INIT_LIST_HEAD(&driver->device_list);
+	driver->kdriver.pci = pdriver;
+	driver->bus = &drm_pci_bus;
+
 	if (driver->driver_features & DRIVER_MODESET)
-		return pci_register_driver(&driver->pci_driver);
+		return pci_register_driver(pdriver);
 
 	/* If not using KMS, fall back to stealth mode manual scanning. */
-	for (i = 0; driver->pci_driver.id_table[i].vendor != 0; i++) {
-		pid = &driver->pci_driver.id_table[i];
+	for (i = 0; pdriver->id_table[i].vendor != 0; i++) {
+		pid = &pdriver->id_table[i];
 
 		/* Loop around setting up a DRM device for each PCI device
 		 * matching our ID and device class.  If we had the internal
@@ -265,10 +441,27 @@
 
 #else
 
-int drm_pci_init(struct drm_driver *driver)
+int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver)
 {
 	return -1;
 }
 
 #endif
+
+EXPORT_SYMBOL(drm_pci_init);
+
 /*@}*/
+void drm_pci_exit(struct drm_driver *driver, struct pci_driver *pdriver)
+{
+	struct drm_device *dev, *tmp;
+	DRM_DEBUG("\n");
+
+	if (driver->driver_features & DRIVER_MODESET) {
+		pci_unregister_driver(pdriver);
+	} else {
+		list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+			drm_put_dev(dev);
+	}
+	DRM_INFO("Module unloaded\n");
+}
+EXPORT_SYMBOL(drm_pci_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_platform.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_platform.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -109,8 +109,60 @@
 }
 EXPORT_SYMBOL(drm_get_platform_dev);
 
+static int drm_platform_get_irq(struct drm_device *dev)
+{
+	return platform_get_irq(dev->platformdev, 0);
+}
+
+static const char *drm_platform_get_name(struct drm_device *dev)
+{
+	return dev->platformdev->name;
+}
+
+static int drm_platform_set_busid(struct drm_device *dev, struct drm_master *master)
+{
+	int len, ret;
+
+	master->unique_len = 10 + strlen(dev->platformdev->name);
+	master->unique = kmalloc(master->unique_len + 1, GFP_KERNEL);
+
+	if (master->unique == NULL)
+		return -ENOMEM;
+
+	len = snprintf(master->unique, master->unique_len,
+		       "platform:%s", dev->platformdev->name);
+
+	if (len > master->unique_len) {
+		DRM_ERROR("Unique buffer overflowed\n");
+		ret = -EINVAL;
+		goto err;
+	}
+
+	dev->devname =
+		kmalloc(strlen(dev->platformdev->name) +
+			master->unique_len + 2, GFP_KERNEL);
+
+	if (dev->devname == NULL) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	sprintf(dev->devname, "%s@%s", dev->platformdev->name,
+		master->unique);
+	return 0;
+err:
+	return ret;
+}
+
+static struct drm_bus drm_platform_bus = {
+	.bus_type = DRIVER_BUS_PLATFORM,
+	.get_irq = drm_platform_get_irq,
+	.get_name = drm_platform_get_name,
+	.set_busid = drm_platform_set_busid,
+};
+
 /**
- * Platform device initialization. Called via drm_init at module load time,
+ * Platform device initialization. Called direct from modules.
  *
  * \return zero on success or a negative number on failure.
  *
@@ -121,7 +173,24 @@
  * after the initialization for driver customization.
  */
 
-int drm_platform_init(struct drm_driver *driver)
+int drm_platform_init(struct drm_driver *driver, struct platform_device *platform_device)
 {
-	return drm_get_platform_dev(driver->platform_device, driver);
+	DRM_DEBUG("\n");
+
+	driver->kdriver.platform_device = platform_device;
+	driver->bus = &drm_platform_bus;
+	INIT_LIST_HEAD(&driver->device_list);
+	return drm_get_platform_dev(platform_device, driver);
+}
+EXPORT_SYMBOL(drm_platform_init);
+
+void drm_platform_exit(struct drm_driver *driver, struct platform_device *platform_device)
+{
+	struct drm_device *dev, *tmp;
+	DRM_DEBUG("\n");
+
+	list_for_each_entry_safe(dev, tmp, &driver->device_list, driver_item)
+		drm_put_dev(dev);
+	DRM_INFO("Module unloaded\n");
 }
+EXPORT_SYMBOL(drm_platform_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_sman.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_sman.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_sman.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_sman.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,9 +59,7 @@
 {
 	int ret = 0;
 
-	sman->mm = (struct drm_sman_mm *) kcalloc(num_managers,
-						  sizeof(*sman->mm),
-						  GFP_KERNEL);
+	sman->mm = kcalloc(num_managers, sizeof(*sman->mm), GFP_KERNEL);
 	if (!sman->mm) {
 		ret = -ENOMEM;
 		goto out;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_stub.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_stub.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_stub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_stub.c	2011-05-19 00:06:34.000000000 -0400
@@ -269,25 +269,14 @@
 
 	dev->driver = driver;
 
-	if (drm_core_has_AGP(dev)) {
-		if (drm_device_is_agp(dev))
-			dev->agp = drm_agp_init(dev);
-		if (drm_core_check_feature(dev, DRIVER_REQUIRE_AGP)
-		    && (dev->agp == NULL)) {
-			DRM_ERROR("Cannot initialize the agpgart module.\n");
-			retcode = -EINVAL;
+	if (dev->driver->bus->agp_init) {
+		retcode = dev->driver->bus->agp_init(dev);
+		if (retcode)
 			goto error_out_unreg;
-		}
-		if (drm_core_has_MTRR(dev)) {
-			if (dev->agp)
-				dev->agp->agp_mtrr =
-				    mtrr_add(dev->agp->agp_info.aper_base,
-					     dev->agp->agp_info.aper_size *
-					     1024 * 1024, MTRR_TYPE_WRCOMB, 1);
-		}
 	}
 
 
+
 	retcode = drm_ctxbitmap_init(dev);
 	if (retcode) {
 		DRM_ERROR("Cannot allocate memory for context bitmap.\n");
@@ -425,7 +414,6 @@
  *
  * Cleans up all DRM device, calling drm_lastclose().
  *
- * \sa drm_init
  */
 void drm_put_dev(struct drm_device *dev)
 {
@@ -475,6 +463,7 @@
 
 	drm_put_minor(&dev->primary);
 
+	list_del(&dev->driver_item);
 	if (dev->devname) {
 		kfree(dev->devname);
 		dev->devname = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_sysfs.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,8 +158,15 @@
 {
 	struct drm_connector *connector = to_drm_connector(device);
 	enum drm_connector_status status;
+	int ret;
+
+	ret = mutex_lock_interruptible(&connector->dev->mode_config.mutex);
+	if (ret)
+		return ret;
 
 	status = connector->funcs->detect(connector, true);
+	mutex_unlock(&connector->dev->mode_config.mutex);
+
 	return snprintf(buf, PAGE_SIZE, "%s\n",
 			drm_get_connector_status_name(status));
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_usb.c linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_usb.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/drm_usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/drm_usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,117 @@
+#include "drmP.h"
+#include <linux/usb.h>
+
+#ifdef CONFIG_USB
+int drm_get_usb_dev(struct usb_interface *interface,
+		    const struct usb_device_id *id,
+		    struct drm_driver *driver)
+{
+	struct drm_device *dev;
+	struct usb_device *usbdev;
+	int ret;
+
+	DRM_DEBUG("\n");
+
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (!dev)
+		return -ENOMEM;
+
+	usbdev = interface_to_usbdev(interface);
+	dev->usbdev = usbdev;
+	dev->dev = &usbdev->dev;
+
+	mutex_lock(&drm_global_mutex);
+
+	ret = drm_fill_in_dev(dev, NULL, driver);
+	if (ret) {
+		printk(KERN_ERR "DRM: Fill_in_dev failed.\n");
+		goto err_g1;
+	}
+
+	usb_set_intfdata(interface, dev);
+	ret = drm_get_minor(dev, &dev->control, DRM_MINOR_CONTROL);
+	if (ret)
+		goto err_g1;
+
+	ret = drm_get_minor(dev, &dev->primary, DRM_MINOR_LEGACY);
+	if (ret)
+		goto err_g2;
+
+	if (dev->driver->load) {
+		ret = dev->driver->load(dev, 0);
+		if (ret)
+			goto err_g3;
+	}
+
+	/* setup the grouping for the legacy output */
+	ret = drm_mode_group_init_legacy_group(dev,
+					       &dev->primary->mode_group);
+	if (ret)
+		goto err_g3;
+
+	list_add_tail(&dev->driver_item, &driver->device_list);
+
+	mutex_unlock(&drm_global_mutex);
+
+	DRM_INFO("Initialized %s %d.%d.%d %s on minor %d\n",
+		 driver->name, driver->major, driver->minor, driver->patchlevel,
+		 driver->date, dev->primary->index);
+
+	return 0;
+
+err_g3:
+	drm_put_minor(&dev->primary);
+err_g2:
+	drm_put_minor(&dev->control);
+err_g1:
+	kfree(dev);
+	mutex_unlock(&drm_global_mutex);
+	return ret;
+
+}
+EXPORT_SYMBOL(drm_get_usb_dev);
+
+static int drm_usb_get_irq(struct drm_device *dev)
+{
+	return 0;
+}
+
+static const char *drm_usb_get_name(struct drm_device *dev)
+{
+	return "USB";
+}
+
+static int drm_usb_set_busid(struct drm_device *dev,
+			       struct drm_master *master)
+{
+	return 0;
+}
+
+static struct drm_bus drm_usb_bus = {
+	.bus_type = DRIVER_BUS_USB,
+	.get_irq = drm_usb_get_irq,
+	.get_name = drm_usb_get_name,
+	.set_busid = drm_usb_set_busid,
+};
+    
+int drm_usb_init(struct drm_driver *driver, struct usb_driver *udriver)
+{
+	int res;
+	DRM_DEBUG("\n");
+
+	INIT_LIST_HEAD(&driver->device_list);
+	driver->kdriver.usb = udriver;
+	driver->bus = &drm_usb_bus;
+
+	res = usb_register(udriver);
+	return res;
+}
+EXPORT_SYMBOL(drm_usb_init);
+
+void drm_usb_exit(struct drm_driver *driver,
+		  struct usb_driver *udriver)
+{
+	usb_deregister(udriver);
+}
+EXPORT_SYMBOL(drm_usb_exit);
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i810/i810_dma.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i810/i810_dma.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i810/i810_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i810/i810_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,6 @@
 #include <linux/interrupt.h>	/* For task queue support */
 #include <linux/delay.h>
 #include <linux/slab.h>
-#include <linux/smp_lock.h>
 #include <linux/pagemap.h>
 
 #define I810_BUF_FREE		2
@@ -94,7 +93,6 @@
 	struct drm_buf *buf;
 	drm_i810_buf_priv_t *buf_priv;
 
-	lock_kernel();
 	dev = priv->minor->dev;
 	dev_priv = dev->dev_private;
 	buf = dev_priv->mmap_buffer;
@@ -104,7 +102,6 @@
 	vma->vm_file = filp;
 
 	buf_priv->currently_mapped = I810_BUF_MAPPED;
-	unlock_kernel();
 
 	if (io_remap_pfn_range(vma, vma->vm_start,
 			       vma->vm_pgoff,
@@ -116,7 +113,7 @@
 static const struct file_operations i810_buffer_fops = {
 	.open = drm_open,
 	.release = drm_release,
-	.unlocked_ioctl = i810_ioctl,
+	.unlocked_ioctl = drm_ioctl,
 	.mmap = i810_mmap_buffers,
 	.fasync = drm_fasync,
 	.llseek = noop_llseek,
@@ -1242,19 +1239,6 @@
 	return 0;
 }
 
-/*
- * call the drm_ioctl under the big kernel lock because
- * to lock against the i810_mmap_buffers function.
- */
-long i810_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	lock_kernel();
-	ret = drm_ioctl(file, cmd, arg);
-	unlock_kernel();
-	return ret;
-}
-
 struct drm_ioctl_desc i810_ioctls[] = {
 	DRM_IOCTL_DEF_DRV(I810_INIT, i810_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
 	DRM_IOCTL_DEF_DRV(I810_VERTEX, i810_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i810/i810_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i810/i810_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i810/i810_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i810/i810_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,18 +57,13 @@
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
 		 .release = drm_release,
-		 .unlocked_ioctl = i810_ioctl,
+		 .unlocked_ioctl = drm_ioctl,
 		 .mmap = drm_mmap,
 		 .poll = drm_poll,
 		 .fasync = drm_fasync,
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -77,15 +72,24 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver i810_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init i810_init(void)
 {
+	if (num_possible_cpus() > 1) {
+		pr_err("drm/i810 does not support SMP\n");
+		return -EINVAL;
+	}
 	driver.num_ioctls = i810_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &i810_pci_driver);
 }
 
 static void __exit i810_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &i810_pci_driver);
 }
 
 module_init(i810_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_dma.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_dma.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_dma.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1560 +0,0 @@
-/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, 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
- * 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: Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *	    Keith Whitwell <keith@tungstengraphics.com>
- *	    Abraham vd Merwe <abraham@2d3d.co.za>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/smp_lock.h>
-#include <linux/pagemap.h>
-#include <linux/delay.h>
-#include <linux/slab.h>
-#include <asm/uaccess.h>
-
-#define I830_BUF_FREE		2
-#define I830_BUF_CLIENT		1
-#define I830_BUF_HARDWARE	0
-
-#define I830_BUF_UNMAPPED 0
-#define I830_BUF_MAPPED   1
-
-static struct drm_buf *i830_freelist_get(struct drm_device * dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int i;
-	int used;
-
-	/* Linear search might not be the best solution */
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-		/* In use is already a pointer */
-		used = cmpxchg(buf_priv->in_use, I830_BUF_FREE,
-			       I830_BUF_CLIENT);
-		if (used == I830_BUF_FREE)
-			return buf;
-	}
-	return NULL;
-}
-
-/* This should only be called if the buffer is not sent to the hardware
- * yet, the hardware updates in use for us once its on the ring buffer.
- */
-
-static int i830_freelist_put(struct drm_device *dev, struct drm_buf *buf)
-{
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	int used;
-
-	/* In use is already a pointer */
-	used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT, I830_BUF_FREE);
-	if (used != I830_BUF_CLIENT) {
-		DRM_ERROR("Freeing buffer thats not in use : %d\n", buf->idx);
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int i830_mmap_buffers(struct file *filp, struct vm_area_struct *vma)
-{
-	struct drm_file *priv = filp->private_data;
-	struct drm_device *dev;
-	drm_i830_private_t *dev_priv;
-	struct drm_buf *buf;
-	drm_i830_buf_priv_t *buf_priv;
-
-	lock_kernel();
-	dev = priv->minor->dev;
-	dev_priv = dev->dev_private;
-	buf = dev_priv->mmap_buffer;
-	buf_priv = buf->dev_private;
-
-	vma->vm_flags |= (VM_IO | VM_DONTCOPY);
-	vma->vm_file = filp;
-
-	buf_priv->currently_mapped = I830_BUF_MAPPED;
-	unlock_kernel();
-
-	if (io_remap_pfn_range(vma, vma->vm_start,
-			       vma->vm_pgoff,
-			       vma->vm_end - vma->vm_start, vma->vm_page_prot))
-		return -EAGAIN;
-	return 0;
-}
-
-static const struct file_operations i830_buffer_fops = {
-	.open = drm_open,
-	.release = drm_release,
-	.unlocked_ioctl = i830_ioctl,
-	.mmap = i830_mmap_buffers,
-	.fasync = drm_fasync,
-	.llseek = noop_llseek,
-};
-
-static int i830_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
-{
-	struct drm_device *dev = file_priv->minor->dev;
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	const struct file_operations *old_fops;
-	unsigned long virtual;
-	int retcode = 0;
-
-	if (buf_priv->currently_mapped == I830_BUF_MAPPED)
-		return -EINVAL;
-
-	down_write(&current->mm->mmap_sem);
-	old_fops = file_priv->filp->f_op;
-	file_priv->filp->f_op = &i830_buffer_fops;
-	dev_priv->mmap_buffer = buf;
-	virtual = do_mmap(file_priv->filp, 0, buf->total, PROT_READ | PROT_WRITE,
-			  MAP_SHARED, buf->bus_address);
-	dev_priv->mmap_buffer = NULL;
-	file_priv->filp->f_op = old_fops;
-	if (IS_ERR((void *)virtual)) {	/* ugh */
-		/* Real error */
-		DRM_ERROR("mmap error\n");
-		retcode = PTR_ERR((void *)virtual);
-		buf_priv->virtual = NULL;
-	} else {
-		buf_priv->virtual = (void __user *)virtual;
-	}
-	up_write(&current->mm->mmap_sem);
-
-	return retcode;
-}
-
-static int i830_unmap_buffer(struct drm_buf *buf)
-{
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	int retcode = 0;
-
-	if (buf_priv->currently_mapped != I830_BUF_MAPPED)
-		return -EINVAL;
-
-	down_write(&current->mm->mmap_sem);
-	retcode = do_munmap(current->mm,
-			    (unsigned long)buf_priv->virtual,
-			    (size_t) buf->total);
-	up_write(&current->mm->mmap_sem);
-
-	buf_priv->currently_mapped = I830_BUF_UNMAPPED;
-	buf_priv->virtual = NULL;
-
-	return retcode;
-}
-
-static int i830_dma_get_buffer(struct drm_device *dev, drm_i830_dma_t *d,
-			       struct drm_file *file_priv)
-{
-	struct drm_buf *buf;
-	drm_i830_buf_priv_t *buf_priv;
-	int retcode = 0;
-
-	buf = i830_freelist_get(dev);
-	if (!buf) {
-		retcode = -ENOMEM;
-		DRM_DEBUG("retcode=%d\n", retcode);
-		return retcode;
-	}
-
-	retcode = i830_map_buffer(buf, file_priv);
-	if (retcode) {
-		i830_freelist_put(dev, buf);
-		DRM_ERROR("mapbuf failed, retcode %d\n", retcode);
-		return retcode;
-	}
-	buf->file_priv = file_priv;
-	buf_priv = buf->dev_private;
-	d->granted = 1;
-	d->request_idx = buf->idx;
-	d->request_size = buf->total;
-	d->virtual = buf_priv->virtual;
-
-	return retcode;
-}
-
-static int i830_dma_cleanup(struct drm_device *dev)
-{
-	struct drm_device_dma *dma = dev->dma;
-
-	/* Make sure interrupts are disabled here because the uninstall ioctl
-	 * may not have been called from userspace and after dev_private
-	 * is freed, it's too late.
-	 */
-	if (dev->irq_enabled)
-		drm_irq_uninstall(dev);
-
-	if (dev->dev_private) {
-		int i;
-		drm_i830_private_t *dev_priv =
-		    (drm_i830_private_t *) dev->dev_private;
-
-		if (dev_priv->ring.virtual_start)
-			drm_core_ioremapfree(&dev_priv->ring.map, dev);
-		if (dev_priv->hw_status_page) {
-			pci_free_consistent(dev->pdev, PAGE_SIZE,
-					    dev_priv->hw_status_page,
-					    dev_priv->dma_status_page);
-			/* Need to rewrite hardware status page */
-			I830_WRITE(0x02080, 0x1ffff000);
-		}
-
-		kfree(dev->dev_private);
-		dev->dev_private = NULL;
-
-		for (i = 0; i < dma->buf_count; i++) {
-			struct drm_buf *buf = dma->buflist[i];
-			drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-			if (buf_priv->kernel_virtual && buf->total)
-				drm_core_ioremapfree(&buf_priv->map, dev);
-		}
-	}
-	return 0;
-}
-
-int i830_wait_ring(struct drm_device *dev, int n, const char *caller)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-	int iters = 0;
-	unsigned long end;
-	unsigned int last_head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-
-	end = jiffies + (HZ * 3);
-	while (ring->space < n) {
-		ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-		ring->space = ring->head - (ring->tail + 8);
-		if (ring->space < 0)
-			ring->space += ring->Size;
-
-		if (ring->head != last_head) {
-			end = jiffies + (HZ * 3);
-			last_head = ring->head;
-		}
-
-		iters++;
-		if (time_before(end, jiffies)) {
-			DRM_ERROR("space: %d wanted %d\n", ring->space, n);
-			DRM_ERROR("lockup\n");
-			goto out_wait_ring;
-		}
-		udelay(1);
-		dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
-	}
-
-out_wait_ring:
-	return iters;
-}
-
-static void i830_kernel_lost_context(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_ring_buffer_t *ring = &(dev_priv->ring);
-
-	ring->head = I830_READ(LP_RING + RING_HEAD) & HEAD_ADDR;
-	ring->tail = I830_READ(LP_RING + RING_TAIL) & TAIL_ADDR;
-	ring->space = ring->head - (ring->tail + 8);
-	if (ring->space < 0)
-		ring->space += ring->Size;
-
-	if (ring->head == ring->tail)
-		dev_priv->sarea_priv->perf_boxes |= I830_BOX_RING_EMPTY;
-}
-
-static int i830_freelist_init(struct drm_device *dev, drm_i830_private_t *dev_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int my_idx = 36;
-	u32 *hw_status = (u32 *) (dev_priv->hw_status_page + my_idx);
-	int i;
-
-	if (dma->buf_count > 1019) {
-		/* Not enough space in the status page for the freelist */
-		return -EINVAL;
-	}
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-		buf_priv->in_use = hw_status++;
-		buf_priv->my_use_idx = my_idx;
-		my_idx += 4;
-
-		*buf_priv->in_use = I830_BUF_FREE;
-
-		buf_priv->map.offset = buf->bus_address;
-		buf_priv->map.size = buf->total;
-		buf_priv->map.type = _DRM_AGP;
-		buf_priv->map.flags = 0;
-		buf_priv->map.mtrr = 0;
-
-		drm_core_ioremap(&buf_priv->map, dev);
-		buf_priv->kernel_virtual = buf_priv->map.handle;
-	}
-	return 0;
-}
-
-static int i830_dma_initialize(struct drm_device *dev,
-			       drm_i830_private_t *dev_priv,
-			       drm_i830_init_t *init)
-{
-	struct drm_map_list *r_list;
-
-	memset(dev_priv, 0, sizeof(drm_i830_private_t));
-
-	list_for_each_entry(r_list, &dev->maplist, head) {
-		if (r_list->map &&
-		    r_list->map->type == _DRM_SHM &&
-		    r_list->map->flags & _DRM_CONTAINS_LOCK) {
-			dev_priv->sarea_map = r_list->map;
-			break;
-		}
-	}
-
-	if (!dev_priv->sarea_map) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not find sarea!\n");
-		return -EINVAL;
-	}
-	dev_priv->mmio_map = drm_core_findmap(dev, init->mmio_offset);
-	if (!dev_priv->mmio_map) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not find mmio map!\n");
-		return -EINVAL;
-	}
-	dev->agp_buffer_token = init->buffers_offset;
-	dev->agp_buffer_map = drm_core_findmap(dev, init->buffers_offset);
-	if (!dev->agp_buffer_map) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not find dma buffer map!\n");
-		return -EINVAL;
-	}
-
-	dev_priv->sarea_priv = (drm_i830_sarea_t *)
-	    ((u8 *) dev_priv->sarea_map->handle + init->sarea_priv_offset);
-
-	dev_priv->ring.Start = init->ring_start;
-	dev_priv->ring.End = init->ring_end;
-	dev_priv->ring.Size = init->ring_size;
-
-	dev_priv->ring.map.offset = dev->agp->base + init->ring_start;
-	dev_priv->ring.map.size = init->ring_size;
-	dev_priv->ring.map.type = _DRM_AGP;
-	dev_priv->ring.map.flags = 0;
-	dev_priv->ring.map.mtrr = 0;
-
-	drm_core_ioremap(&dev_priv->ring.map, dev);
-
-	if (dev_priv->ring.map.handle == NULL) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("can not ioremap virtual address for"
-			  " ring buffer\n");
-		return -ENOMEM;
-	}
-
-	dev_priv->ring.virtual_start = dev_priv->ring.map.handle;
-
-	dev_priv->ring.tail_mask = dev_priv->ring.Size - 1;
-
-	dev_priv->w = init->w;
-	dev_priv->h = init->h;
-	dev_priv->pitch = init->pitch;
-	dev_priv->back_offset = init->back_offset;
-	dev_priv->depth_offset = init->depth_offset;
-	dev_priv->front_offset = init->front_offset;
-
-	dev_priv->front_di1 = init->front_offset | init->pitch_bits;
-	dev_priv->back_di1 = init->back_offset | init->pitch_bits;
-	dev_priv->zi1 = init->depth_offset | init->pitch_bits;
-
-	DRM_DEBUG("front_di1 %x\n", dev_priv->front_di1);
-	DRM_DEBUG("back_offset %x\n", dev_priv->back_offset);
-	DRM_DEBUG("back_di1 %x\n", dev_priv->back_di1);
-	DRM_DEBUG("pitch_bits %x\n", init->pitch_bits);
-
-	dev_priv->cpp = init->cpp;
-	/* We are using separate values as placeholders for mechanisms for
-	 * private backbuffer/depthbuffer usage.
-	 */
-
-	dev_priv->back_pitch = init->back_pitch;
-	dev_priv->depth_pitch = init->depth_pitch;
-	dev_priv->do_boxes = 0;
-	dev_priv->use_mi_batchbuffer_start = 0;
-
-	/* Program Hardware Status Page */
-	dev_priv->hw_status_page =
-	    pci_alloc_consistent(dev->pdev, PAGE_SIZE,
-				 &dev_priv->dma_status_page);
-	if (!dev_priv->hw_status_page) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("Can not allocate hardware status page\n");
-		return -ENOMEM;
-	}
-	memset(dev_priv->hw_status_page, 0, PAGE_SIZE);
-	DRM_DEBUG("hw status page @ %p\n", dev_priv->hw_status_page);
-
-	I830_WRITE(0x02080, dev_priv->dma_status_page);
-	DRM_DEBUG("Enabled hardware status page\n");
-
-	/* Now we need to init our freelist */
-	if (i830_freelist_init(dev, dev_priv) != 0) {
-		dev->dev_private = (void *)dev_priv;
-		i830_dma_cleanup(dev);
-		DRM_ERROR("Not enough space in the status page for"
-			  " the freelist\n");
-		return -ENOMEM;
-	}
-	dev->dev_private = (void *)dev_priv;
-
-	return 0;
-}
-
-static int i830_dma_init(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv;
-	drm_i830_init_t *init = data;
-	int retcode = 0;
-
-	switch (init->func) {
-	case I830_INIT_DMA:
-		dev_priv = kmalloc(sizeof(drm_i830_private_t), GFP_KERNEL);
-		if (dev_priv == NULL)
-			return -ENOMEM;
-		retcode = i830_dma_initialize(dev, dev_priv, init);
-		break;
-	case I830_CLEANUP_DMA:
-		retcode = i830_dma_cleanup(dev);
-		break;
-	default:
-		retcode = -EINVAL;
-		break;
-	}
-
-	return retcode;
-}
-
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define ST1_ENABLE               (1<<16)
-#define ST1_MASK                 (0xffff)
-
-/* Most efficient way to verify state for the i830 is as it is
- * emitted.  Non-conformant state is silently dropped.
- */
-static void i830EmitContextVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i, j = 0;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	BEGIN_LP_RING(I830_CTX_SETUP_SIZE + 4);
-
-	for (i = 0; i < I830_CTXREG_BLENDCOLR0; i++) {
-		tmp = code[i];
-		if ((tmp & (7 << 29)) == CMD_3D &&
-		    (tmp & (0x1f << 24)) < (0x1d << 24)) {
-			OUT_RING(tmp);
-			j++;
-		} else {
-			DRM_ERROR("Skipping %d\n", i);
-		}
-	}
-
-	OUT_RING(STATE3D_CONST_BLEND_COLOR_CMD);
-	OUT_RING(code[I830_CTXREG_BLENDCOLR]);
-	j += 2;
-
-	for (i = I830_CTXREG_VF; i < I830_CTXREG_MCSB0; i++) {
-		tmp = code[i];
-		if ((tmp & (7 << 29)) == CMD_3D &&
-		    (tmp & (0x1f << 24)) < (0x1d << 24)) {
-			OUT_RING(tmp);
-			j++;
-		} else {
-			DRM_ERROR("Skipping %d\n", i);
-		}
-	}
-
-	OUT_RING(STATE3D_MAP_COORD_SETBIND_CMD);
-	OUT_RING(code[I830_CTXREG_MCSB1]);
-	j += 2;
-
-	if (j & 1)
-		OUT_RING(0);
-
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitTexVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i, j = 0;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	if (code[I830_TEXREG_MI0] == GFX_OP_MAP_INFO ||
-	    (code[I830_TEXREG_MI0] & ~(0xf * LOAD_TEXTURE_MAP0)) ==
-	    (STATE3D_LOAD_STATE_IMMEDIATE_2 | 4)) {
-
-		BEGIN_LP_RING(I830_TEX_SETUP_SIZE);
-
-		OUT_RING(code[I830_TEXREG_MI0]);	/* TM0LI */
-		OUT_RING(code[I830_TEXREG_MI1]);	/* TM0S0 */
-		OUT_RING(code[I830_TEXREG_MI2]);	/* TM0S1 */
-		OUT_RING(code[I830_TEXREG_MI3]);	/* TM0S2 */
-		OUT_RING(code[I830_TEXREG_MI4]);	/* TM0S3 */
-		OUT_RING(code[I830_TEXREG_MI5]);	/* TM0S4 */
-
-		for (i = 6; i < I830_TEX_SETUP_SIZE; i++) {
-			tmp = code[i];
-			OUT_RING(tmp);
-			j++;
-		}
-
-		if (j & 1)
-			OUT_RING(0);
-
-		ADVANCE_LP_RING();
-	} else
-		printk("rejected packet %x\n", code[0]);
-}
-
-static void i830EmitTexBlendVerified(struct drm_device *dev,
-				     unsigned int *code, unsigned int num)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i, j = 0;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	if (!num)
-		return;
-
-	BEGIN_LP_RING(num + 1);
-
-	for (i = 0; i < num; i++) {
-		tmp = code[i];
-		OUT_RING(tmp);
-		j++;
-	}
-
-	if (j & 1)
-		OUT_RING(0);
-
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitTexPalette(struct drm_device *dev,
-			       unsigned int *palette, int number, int is_shared)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	int i;
-	RING_LOCALS;
-
-	return;
-
-	BEGIN_LP_RING(258);
-
-	if (is_shared == 1) {
-		OUT_RING(CMD_OP_MAP_PALETTE_LOAD |
-			 MAP_PALETTE_NUM(0) | MAP_PALETTE_BOTH);
-	} else {
-		OUT_RING(CMD_OP_MAP_PALETTE_LOAD | MAP_PALETTE_NUM(number));
-	}
-	for (i = 0; i < 256; i++)
-		OUT_RING(palette[i]);
-	OUT_RING(0);
-	/* KW:  WHERE IS THE ADVANCE_LP_RING?  This is effectively a noop!
-	 */
-}
-
-/* Need to do some additional checking when setting the dest buffer.
- */
-static void i830EmitDestVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	unsigned int tmp;
-	RING_LOCALS;
-
-	BEGIN_LP_RING(I830_DEST_SETUP_SIZE + 10);
-
-	tmp = code[I830_DESTREG_CBUFADDR];
-	if (tmp == dev_priv->front_di1 || tmp == dev_priv->back_di1) {
-		if (((int)outring) & 8) {
-			OUT_RING(0);
-			OUT_RING(0);
-		}
-
-		OUT_RING(CMD_OP_DESTBUFFER_INFO);
-		OUT_RING(BUF_3D_ID_COLOR_BACK |
-			 BUF_3D_PITCH(dev_priv->back_pitch * dev_priv->cpp) |
-			 BUF_3D_USE_FENCE);
-		OUT_RING(tmp);
-		OUT_RING(0);
-
-		OUT_RING(CMD_OP_DESTBUFFER_INFO);
-		OUT_RING(BUF_3D_ID_DEPTH | BUF_3D_USE_FENCE |
-			 BUF_3D_PITCH(dev_priv->depth_pitch * dev_priv->cpp));
-		OUT_RING(dev_priv->zi1);
-		OUT_RING(0);
-	} else {
-		DRM_ERROR("bad di1 %x (allow %x or %x)\n",
-			  tmp, dev_priv->front_di1, dev_priv->back_di1);
-	}
-
-	/* invarient:
-	 */
-
-	OUT_RING(GFX_OP_DESTBUFFER_VARS);
-	OUT_RING(code[I830_DESTREG_DV1]);
-
-	OUT_RING(GFX_OP_DRAWRECT_INFO);
-	OUT_RING(code[I830_DESTREG_DR1]);
-	OUT_RING(code[I830_DESTREG_DR2]);
-	OUT_RING(code[I830_DESTREG_DR3]);
-	OUT_RING(code[I830_DESTREG_DR4]);
-
-	/* Need to verify this */
-	tmp = code[I830_DESTREG_SENABLE];
-	if ((tmp & ~0x3) == GFX_OP_SCISSOR_ENABLE) {
-		OUT_RING(tmp);
-	} else {
-		DRM_ERROR("bad scissor enable\n");
-		OUT_RING(0);
-	}
-
-	OUT_RING(GFX_OP_SCISSOR_RECT);
-	OUT_RING(code[I830_DESTREG_SR1]);
-	OUT_RING(code[I830_DESTREG_SR2]);
-	OUT_RING(0);
-
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitStippleVerified(struct drm_device *dev, unsigned int *code)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	BEGIN_LP_RING(2);
-	OUT_RING(GFX_OP_STIPPLE);
-	OUT_RING(code[1]);
-	ADVANCE_LP_RING();
-}
-
-static void i830EmitState(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	unsigned int dirty = sarea_priv->dirty;
-
-	DRM_DEBUG("%s %x\n", __func__, dirty);
-
-	if (dirty & I830_UPLOAD_BUFFERS) {
-		i830EmitDestVerified(dev, sarea_priv->BufferState);
-		sarea_priv->dirty &= ~I830_UPLOAD_BUFFERS;
-	}
-
-	if (dirty & I830_UPLOAD_CTX) {
-		i830EmitContextVerified(dev, sarea_priv->ContextState);
-		sarea_priv->dirty &= ~I830_UPLOAD_CTX;
-	}
-
-	if (dirty & I830_UPLOAD_TEX0) {
-		i830EmitTexVerified(dev, sarea_priv->TexState[0]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX0;
-	}
-
-	if (dirty & I830_UPLOAD_TEX1) {
-		i830EmitTexVerified(dev, sarea_priv->TexState[1]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX1;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND0) {
-		i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[0],
-					 sarea_priv->TexBlendStateWordsUsed[0]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND0;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND1) {
-		i830EmitTexBlendVerified(dev, sarea_priv->TexBlendState[1],
-					 sarea_priv->TexBlendStateWordsUsed[1]);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND1;
-	}
-
-	if (dirty & I830_UPLOAD_TEX_PALETTE_SHARED) {
-		i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 1);
-	} else {
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(0)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette[0], 0, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(0);
-		}
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(1)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette[1], 1, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(1);
-		}
-
-		/* 1.3:
-		 */
-#if 0
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(2)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette2[0], 0, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
-		}
-		if (dirty & I830_UPLOAD_TEX_PALETTE_N(3)) {
-			i830EmitTexPalette(dev, sarea_priv->Palette2[1], 1, 0);
-			sarea_priv->dirty &= ~I830_UPLOAD_TEX_PALETTE_N(2);
-		}
-#endif
-	}
-
-	/* 1.3:
-	 */
-	if (dirty & I830_UPLOAD_STIPPLE) {
-		i830EmitStippleVerified(dev, sarea_priv->StippleState);
-		sarea_priv->dirty &= ~I830_UPLOAD_STIPPLE;
-	}
-
-	if (dirty & I830_UPLOAD_TEX2) {
-		i830EmitTexVerified(dev, sarea_priv->TexState2);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX2;
-	}
-
-	if (dirty & I830_UPLOAD_TEX3) {
-		i830EmitTexVerified(dev, sarea_priv->TexState3);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEX3;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND2) {
-		i830EmitTexBlendVerified(dev,
-					 sarea_priv->TexBlendState2,
-					 sarea_priv->TexBlendStateWordsUsed2);
-
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND2;
-	}
-
-	if (dirty & I830_UPLOAD_TEXBLEND3) {
-		i830EmitTexBlendVerified(dev,
-					 sarea_priv->TexBlendState3,
-					 sarea_priv->TexBlendStateWordsUsed3);
-		sarea_priv->dirty &= ~I830_UPLOAD_TEXBLEND3;
-	}
-}
-
-/* ================================================================
- * Performance monitoring functions
- */
-
-static void i830_fill_box(struct drm_device *dev,
-			  int x, int y, int w, int h, int r, int g, int b)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	u32 color;
-	unsigned int BR13, CMD;
-	RING_LOCALS;
-
-	BR13 = (0xF0 << 16) | (dev_priv->pitch * dev_priv->cpp) | (1 << 24);
-	CMD = XY_COLOR_BLT_CMD;
-	x += dev_priv->sarea_priv->boxes[0].x1;
-	y += dev_priv->sarea_priv->boxes[0].y1;
-
-	if (dev_priv->cpp == 4) {
-		BR13 |= (1 << 25);
-		CMD |= (XY_COLOR_BLT_WRITE_ALPHA | XY_COLOR_BLT_WRITE_RGB);
-		color = (((0xff) << 24) | (r << 16) | (g << 8) | b);
-	} else {
-		color = (((r & 0xf8) << 8) |
-			 ((g & 0xfc) << 3) | ((b & 0xf8) >> 3));
-	}
-
-	BEGIN_LP_RING(6);
-	OUT_RING(CMD);
-	OUT_RING(BR13);
-	OUT_RING((y << 16) | x);
-	OUT_RING(((y + h) << 16) | (x + w));
-
-	if (dev_priv->current_page == 1)
-		OUT_RING(dev_priv->front_offset);
-	else
-		OUT_RING(dev_priv->back_offset);
-
-	OUT_RING(color);
-	ADVANCE_LP_RING();
-}
-
-static void i830_cp_performance_boxes(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	/* Purple box for page flipping
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_FLIP)
-		i830_fill_box(dev, 4, 4, 8, 8, 255, 0, 255);
-
-	/* Red box if we have to wait for idle at any point
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_WAIT)
-		i830_fill_box(dev, 16, 4, 8, 8, 255, 0, 0);
-
-	/* Blue box: lost context?
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_LOST_CONTEXT)
-		i830_fill_box(dev, 28, 4, 8, 8, 0, 0, 255);
-
-	/* Yellow box for texture swaps
-	 */
-	if (dev_priv->sarea_priv->perf_boxes & I830_BOX_TEXTURE_LOAD)
-		i830_fill_box(dev, 40, 4, 8, 8, 255, 255, 0);
-
-	/* Green box if hardware never idles (as far as we can tell)
-	 */
-	if (!(dev_priv->sarea_priv->perf_boxes & I830_BOX_RING_EMPTY))
-		i830_fill_box(dev, 64, 4, 8, 8, 0, 255, 0);
-
-	/* Draw bars indicating number of buffers allocated
-	 * (not a great measure, easily confused)
-	 */
-	if (dev_priv->dma_used) {
-		int bar = dev_priv->dma_used / 10240;
-		if (bar > 100)
-			bar = 100;
-		if (bar < 1)
-			bar = 1;
-		i830_fill_box(dev, 4, 16, bar, 4, 196, 128, 128);
-		dev_priv->dma_used = 0;
-	}
-
-	dev_priv->sarea_priv->perf_boxes = 0;
-}
-
-static void i830_dma_dispatch_clear(struct drm_device *dev, int flags,
-				    unsigned int clear_color,
-				    unsigned int clear_zval,
-				    unsigned int clear_depthmask)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	int pitch = dev_priv->pitch;
-	int cpp = dev_priv->cpp;
-	int i;
-	unsigned int BR13, CMD, D_CMD;
-	RING_LOCALS;
-
-	if (dev_priv->current_page == 1) {
-		unsigned int tmp = flags;
-
-		flags &= ~(I830_FRONT | I830_BACK);
-		if (tmp & I830_FRONT)
-			flags |= I830_BACK;
-		if (tmp & I830_BACK)
-			flags |= I830_FRONT;
-	}
-
-	i830_kernel_lost_context(dev);
-
-	switch (cpp) {
-	case 2:
-		BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
-		D_CMD = CMD = XY_COLOR_BLT_CMD;
-		break;
-	case 4:
-		BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24) | (1 << 25);
-		CMD = (XY_COLOR_BLT_CMD | XY_COLOR_BLT_WRITE_ALPHA |
-		       XY_COLOR_BLT_WRITE_RGB);
-		D_CMD = XY_COLOR_BLT_CMD;
-		if (clear_depthmask & 0x00ffffff)
-			D_CMD |= XY_COLOR_BLT_WRITE_RGB;
-		if (clear_depthmask & 0xff000000)
-			D_CMD |= XY_COLOR_BLT_WRITE_ALPHA;
-		break;
-	default:
-		BR13 = (0xF0 << 16) | (pitch * cpp) | (1 << 24);
-		D_CMD = CMD = XY_COLOR_BLT_CMD;
-		break;
-	}
-
-	if (nbox > I830_NR_SAREA_CLIPRECTS)
-		nbox = I830_NR_SAREA_CLIPRECTS;
-
-	for (i = 0; i < nbox; i++, pbox++) {
-		if (pbox->x1 > pbox->x2 ||
-		    pbox->y1 > pbox->y2 ||
-		    pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-			continue;
-
-		if (flags & I830_FRONT) {
-			DRM_DEBUG("clear front\n");
-			BEGIN_LP_RING(6);
-			OUT_RING(CMD);
-			OUT_RING(BR13);
-			OUT_RING((pbox->y1 << 16) | pbox->x1);
-			OUT_RING((pbox->y2 << 16) | pbox->x2);
-			OUT_RING(dev_priv->front_offset);
-			OUT_RING(clear_color);
-			ADVANCE_LP_RING();
-		}
-
-		if (flags & I830_BACK) {
-			DRM_DEBUG("clear back\n");
-			BEGIN_LP_RING(6);
-			OUT_RING(CMD);
-			OUT_RING(BR13);
-			OUT_RING((pbox->y1 << 16) | pbox->x1);
-			OUT_RING((pbox->y2 << 16) | pbox->x2);
-			OUT_RING(dev_priv->back_offset);
-			OUT_RING(clear_color);
-			ADVANCE_LP_RING();
-		}
-
-		if (flags & I830_DEPTH) {
-			DRM_DEBUG("clear depth\n");
-			BEGIN_LP_RING(6);
-			OUT_RING(D_CMD);
-			OUT_RING(BR13);
-			OUT_RING((pbox->y1 << 16) | pbox->x1);
-			OUT_RING((pbox->y2 << 16) | pbox->x2);
-			OUT_RING(dev_priv->depth_offset);
-			OUT_RING(clear_zval);
-			ADVANCE_LP_RING();
-		}
-	}
-}
-
-static void i830_dma_dispatch_swap(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	int nbox = sarea_priv->nbox;
-	struct drm_clip_rect *pbox = sarea_priv->boxes;
-	int pitch = dev_priv->pitch;
-	int cpp = dev_priv->cpp;
-	int i;
-	unsigned int CMD, BR13;
-	RING_LOCALS;
-
-	DRM_DEBUG("swapbuffers\n");
-
-	i830_kernel_lost_context(dev);
-
-	if (dev_priv->do_boxes)
-		i830_cp_performance_boxes(dev);
-
-	switch (cpp) {
-	case 2:
-		BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
-		CMD = XY_SRC_COPY_BLT_CMD;
-		break;
-	case 4:
-		BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24) | (1 << 25);
-		CMD = (XY_SRC_COPY_BLT_CMD | XY_SRC_COPY_BLT_WRITE_ALPHA |
-		       XY_SRC_COPY_BLT_WRITE_RGB);
-		break;
-	default:
-		BR13 = (pitch * cpp) | (0xCC << 16) | (1 << 24);
-		CMD = XY_SRC_COPY_BLT_CMD;
-		break;
-	}
-
-	if (nbox > I830_NR_SAREA_CLIPRECTS)
-		nbox = I830_NR_SAREA_CLIPRECTS;
-
-	for (i = 0; i < nbox; i++, pbox++) {
-		if (pbox->x1 > pbox->x2 ||
-		    pbox->y1 > pbox->y2 ||
-		    pbox->x2 > dev_priv->w || pbox->y2 > dev_priv->h)
-			continue;
-
-		DRM_DEBUG("dispatch swap %d,%d-%d,%d!\n",
-			  pbox->x1, pbox->y1, pbox->x2, pbox->y2);
-
-		BEGIN_LP_RING(8);
-		OUT_RING(CMD);
-		OUT_RING(BR13);
-		OUT_RING((pbox->y1 << 16) | pbox->x1);
-		OUT_RING((pbox->y2 << 16) | pbox->x2);
-
-		if (dev_priv->current_page == 0)
-			OUT_RING(dev_priv->front_offset);
-		else
-			OUT_RING(dev_priv->back_offset);
-
-		OUT_RING((pbox->y1 << 16) | pbox->x1);
-		OUT_RING(BR13 & 0xffff);
-
-		if (dev_priv->current_page == 0)
-			OUT_RING(dev_priv->back_offset);
-		else
-			OUT_RING(dev_priv->front_offset);
-
-		ADVANCE_LP_RING();
-	}
-}
-
-static void i830_dma_dispatch_flip(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	DRM_DEBUG("%s: page=%d pfCurrentPage=%d\n",
-		  __func__,
-		  dev_priv->current_page,
-		  dev_priv->sarea_priv->pf_current_page);
-
-	i830_kernel_lost_context(dev);
-
-	if (dev_priv->do_boxes) {
-		dev_priv->sarea_priv->perf_boxes |= I830_BOX_FLIP;
-		i830_cp_performance_boxes(dev);
-	}
-
-	BEGIN_LP_RING(2);
-	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	BEGIN_LP_RING(6);
-	OUT_RING(CMD_OP_DISPLAYBUFFER_INFO | ASYNC_FLIP);
-	OUT_RING(0);
-	if (dev_priv->current_page == 0) {
-		OUT_RING(dev_priv->back_offset);
-		dev_priv->current_page = 1;
-	} else {
-		OUT_RING(dev_priv->front_offset);
-		dev_priv->current_page = 0;
-	}
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	BEGIN_LP_RING(2);
-	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_PLANE_A_FLIP);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static void i830_dma_dispatch_vertex(struct drm_device *dev,
-				     struct drm_buf *buf, int discard, int used)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-	drm_i830_sarea_t *sarea_priv = dev_priv->sarea_priv;
-	struct drm_clip_rect *box = sarea_priv->boxes;
-	int nbox = sarea_priv->nbox;
-	unsigned long address = (unsigned long)buf->bus_address;
-	unsigned long start = address - dev->agp->base;
-	int i = 0, u;
-	RING_LOCALS;
-
-	i830_kernel_lost_context(dev);
-
-	if (nbox > I830_NR_SAREA_CLIPRECTS)
-		nbox = I830_NR_SAREA_CLIPRECTS;
-
-	if (discard) {
-		u = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-			    I830_BUF_HARDWARE);
-		if (u != I830_BUF_CLIENT)
-			DRM_DEBUG("xxxx 2\n");
-	}
-
-	if (used > 4 * 1023)
-		used = 0;
-
-	if (sarea_priv->dirty)
-		i830EmitState(dev);
-
-	DRM_DEBUG("dispatch vertex addr 0x%lx, used 0x%x nbox %d\n",
-		  address, used, nbox);
-
-	dev_priv->counter++;
-	DRM_DEBUG("dispatch counter : %ld\n", dev_priv->counter);
-	DRM_DEBUG("i830_dma_dispatch\n");
-	DRM_DEBUG("start : %lx\n", start);
-	DRM_DEBUG("used : %d\n", used);
-	DRM_DEBUG("start + used - 4 : %ld\n", start + used - 4);
-
-	if (buf_priv->currently_mapped == I830_BUF_MAPPED) {
-		u32 *vp = buf_priv->kernel_virtual;
-
-		vp[0] = (GFX_OP_PRIMITIVE |
-			 sarea_priv->vertex_prim | ((used / 4) - 2));
-
-		if (dev_priv->use_mi_batchbuffer_start) {
-			vp[used / 4] = MI_BATCH_BUFFER_END;
-			used += 4;
-		}
-
-		if (used & 4) {
-			vp[used / 4] = 0;
-			used += 4;
-		}
-
-		i830_unmap_buffer(buf);
-	}
-
-	if (used) {
-		do {
-			if (i < nbox) {
-				BEGIN_LP_RING(6);
-				OUT_RING(GFX_OP_DRAWRECT_INFO);
-				OUT_RING(sarea_priv->
-					 BufferState[I830_DESTREG_DR1]);
-				OUT_RING(box[i].x1 | (box[i].y1 << 16));
-				OUT_RING(box[i].x2 | (box[i].y2 << 16));
-				OUT_RING(sarea_priv->
-					 BufferState[I830_DESTREG_DR4]);
-				OUT_RING(0);
-				ADVANCE_LP_RING();
-			}
-
-			if (dev_priv->use_mi_batchbuffer_start) {
-				BEGIN_LP_RING(2);
-				OUT_RING(MI_BATCH_BUFFER_START | (2 << 6));
-				OUT_RING(start | MI_BATCH_NON_SECURE);
-				ADVANCE_LP_RING();
-			} else {
-				BEGIN_LP_RING(4);
-				OUT_RING(MI_BATCH_BUFFER);
-				OUT_RING(start | MI_BATCH_NON_SECURE);
-				OUT_RING(start + used - 4);
-				OUT_RING(0);
-				ADVANCE_LP_RING();
-			}
-
-		} while (++i < nbox);
-	}
-
-	if (discard) {
-		dev_priv->counter++;
-
-		(void)cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-			      I830_BUF_HARDWARE);
-
-		BEGIN_LP_RING(8);
-		OUT_RING(CMD_STORE_DWORD_IDX);
-		OUT_RING(20);
-		OUT_RING(dev_priv->counter);
-		OUT_RING(CMD_STORE_DWORD_IDX);
-		OUT_RING(buf_priv->my_use_idx);
-		OUT_RING(I830_BUF_FREE);
-		OUT_RING(CMD_REPORT_HEAD);
-		OUT_RING(0);
-		ADVANCE_LP_RING();
-	}
-}
-
-static void i830_dma_quiescent(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	i830_kernel_lost_context(dev);
-
-	BEGIN_LP_RING(4);
-	OUT_RING(INST_PARSER_CLIENT | INST_OP_FLUSH | INST_FLUSH_MAP_CACHE);
-	OUT_RING(CMD_REPORT_HEAD);
-	OUT_RING(0);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-}
-
-static int i830_flush_queue(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	struct drm_device_dma *dma = dev->dma;
-	int i, ret = 0;
-	RING_LOCALS;
-
-	i830_kernel_lost_context(dev);
-
-	BEGIN_LP_RING(2);
-	OUT_RING(CMD_REPORT_HEAD);
-	OUT_RING(0);
-	ADVANCE_LP_RING();
-
-	i830_wait_ring(dev, dev_priv->ring.Size - 8, __func__);
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-		int used = cmpxchg(buf_priv->in_use, I830_BUF_HARDWARE,
-				   I830_BUF_FREE);
-
-		if (used == I830_BUF_HARDWARE)
-			DRM_DEBUG("reclaimed from HARDWARE\n");
-		if (used == I830_BUF_CLIENT)
-			DRM_DEBUG("still on client\n");
-	}
-
-	return ret;
-}
-
-/* Must be called with the lock held */
-static void i830_reclaim_buffers(struct drm_device *dev, struct drm_file *file_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	int i;
-
-	if (!dma)
-		return;
-	if (!dev->dev_private)
-		return;
-	if (!dma->buflist)
-		return;
-
-	i830_flush_queue(dev);
-
-	for (i = 0; i < dma->buf_count; i++) {
-		struct drm_buf *buf = dma->buflist[i];
-		drm_i830_buf_priv_t *buf_priv = buf->dev_private;
-
-		if (buf->file_priv == file_priv && buf_priv) {
-			int used = cmpxchg(buf_priv->in_use, I830_BUF_CLIENT,
-					   I830_BUF_FREE);
-
-			if (used == I830_BUF_CLIENT)
-				DRM_DEBUG("reclaimed from client\n");
-			if (buf_priv->currently_mapped == I830_BUF_MAPPED)
-				buf_priv->currently_mapped = I830_BUF_UNMAPPED;
-		}
-	}
-}
-
-static int i830_flush_ioctl(struct drm_device *dev, void *data,
-			    struct drm_file *file_priv)
-{
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	i830_flush_queue(dev);
-	return 0;
-}
-
-static int i830_dma_vertex(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	struct drm_device_dma *dma = dev->dma;
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u32 *hw_status = dev_priv->hw_status_page;
-	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-	    dev_priv->sarea_priv;
-	drm_i830_vertex_t *vertex = data;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	DRM_DEBUG("i830 dma vertex, idx %d used %d discard %d\n",
-		  vertex->idx, vertex->used, vertex->discard);
-
-	if (vertex->idx < 0 || vertex->idx > dma->buf_count)
-		return -EINVAL;
-
-	i830_dma_dispatch_vertex(dev,
-				 dma->buflist[vertex->idx],
-				 vertex->discard, vertex->used);
-
-	sarea_priv->last_enqueue = dev_priv->counter - 1;
-	sarea_priv->last_dispatch = (int)hw_status[5];
-
-	return 0;
-}
-
-static int i830_clear_bufs(struct drm_device *dev, void *data,
-			   struct drm_file *file_priv)
-{
-	drm_i830_clear_t *clear = data;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	/* GH: Someone's doing nasty things... */
-	if (!dev->dev_private)
-		return -EINVAL;
-
-	i830_dma_dispatch_clear(dev, clear->flags,
-				clear->clear_color,
-				clear->clear_depth, clear->clear_depthmask);
-	return 0;
-}
-
-static int i830_swap_bufs(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
-{
-	DRM_DEBUG("i830_swap_bufs\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	i830_dma_dispatch_swap(dev);
-	return 0;
-}
-
-/* Not sure why this isn't set all the time:
- */
-static void i830_do_init_pageflip(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("%s\n", __func__);
-	dev_priv->page_flipping = 1;
-	dev_priv->current_page = 0;
-	dev_priv->sarea_priv->pf_current_page = dev_priv->current_page;
-}
-
-static int i830_do_cleanup_pageflip(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("%s\n", __func__);
-	if (dev_priv->current_page != 0)
-		i830_dma_dispatch_flip(dev);
-
-	dev_priv->page_flipping = 0;
-	return 0;
-}
-
-static int i830_flip_bufs(struct drm_device *dev, void *data,
-			  struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (!dev_priv->page_flipping)
-		i830_do_init_pageflip(dev);
-
-	i830_dma_dispatch_flip(dev);
-	return 0;
-}
-
-static int i830_getage(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u32 *hw_status = dev_priv->hw_status_page;
-	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-	    dev_priv->sarea_priv;
-
-	sarea_priv->last_dispatch = (int)hw_status[5];
-	return 0;
-}
-
-static int i830_getbuf(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	int retcode = 0;
-	drm_i830_dma_t *d = data;
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u32 *hw_status = dev_priv->hw_status_page;
-	drm_i830_sarea_t *sarea_priv = (drm_i830_sarea_t *)
-	    dev_priv->sarea_priv;
-
-	DRM_DEBUG("getbuf\n");
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	d->granted = 0;
-
-	retcode = i830_dma_get_buffer(dev, d, file_priv);
-
-	DRM_DEBUG("i830_dma: %d returning %d, granted = %d\n",
-		  task_pid_nr(current), retcode, d->granted);
-
-	sarea_priv->last_dispatch = (int)hw_status[5];
-
-	return retcode;
-}
-
-static int i830_copybuf(struct drm_device *dev, void *data,
-			struct drm_file *file_priv)
-{
-	/* Never copy - 2.4.x doesn't need it */
-	return 0;
-}
-
-static int i830_docopy(struct drm_device *dev, void *data,
-		       struct drm_file *file_priv)
-{
-	return 0;
-}
-
-static int i830_getparam(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_getparam_t *param = data;
-	int value;
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	switch (param->param) {
-	case I830_PARAM_IRQ_ACTIVE:
-		value = dev->irq_enabled;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (copy_to_user(param->value, &value, sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-static int i830_setparam(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_setparam_t *param = data;
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	switch (param->param) {
-	case I830_SETPARAM_USE_MI_BATCHBUFFER_START:
-		dev_priv->use_mi_batchbuffer_start = param->value;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-int i830_driver_load(struct drm_device *dev, unsigned long flags)
-{
-	/* i830 has 4 more counters */
-	dev->counters += 4;
-	dev->types[6] = _DRM_STAT_IRQ;
-	dev->types[7] = _DRM_STAT_PRIMARY;
-	dev->types[8] = _DRM_STAT_SECONDARY;
-	dev->types[9] = _DRM_STAT_DMA;
-
-	return 0;
-}
-
-void i830_driver_lastclose(struct drm_device *dev)
-{
-	i830_dma_cleanup(dev);
-}
-
-void i830_driver_preclose(struct drm_device *dev, struct drm_file *file_priv)
-{
-	if (dev->dev_private) {
-		drm_i830_private_t *dev_priv = dev->dev_private;
-		if (dev_priv->page_flipping)
-			i830_do_cleanup_pageflip(dev);
-	}
-}
-
-void i830_driver_reclaim_buffers_locked(struct drm_device *dev, struct drm_file *file_priv)
-{
-	i830_reclaim_buffers(dev, file_priv);
-}
-
-int i830_driver_dma_quiescent(struct drm_device *dev)
-{
-	i830_dma_quiescent(dev);
-	return 0;
-}
-
-/*
- * call the drm_ioctl under the big kernel lock because
- * to lock against the i830_mmap_buffers function.
- */
-long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
-{
-	int ret;
-	lock_kernel();
-	ret = drm_ioctl(file, cmd, arg);
-	unlock_kernel();
-	return ret;
-}
-
-struct drm_ioctl_desc i830_ioctls[] = {
-	DRM_IOCTL_DEF_DRV(I830_INIT, i830_dma_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_VERTEX, i830_dma_vertex, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_CLEAR, i830_clear_bufs, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_FLUSH, i830_flush_ioctl, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_GETAGE, i830_getage, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_GETBUF, i830_getbuf, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_SWAP, i830_swap_bufs, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_COPY, i830_copybuf, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_DOCOPY, i830_docopy, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_FLIP, i830_flip_bufs, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_IRQ_EMIT, i830_irq_emit, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_IRQ_WAIT, i830_irq_wait, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_GETPARAM, i830_getparam, DRM_AUTH|DRM_UNLOCKED),
-	DRM_IOCTL_DEF_DRV(I830_SETPARAM, i830_setparam, DRM_AUTH|DRM_UNLOCKED),
-};
-
-int i830_max_ioctl = DRM_ARRAY_SIZE(i830_ioctls);
-
-/**
- * Determine if the device really is AGP or not.
- *
- * All Intel graphics chipsets are treated as AGP, even if they are really
- * PCI-e.
- *
- * \param dev   The device to be tested.
- *
- * \returns
- * A value of 1 is always retured to indictate every i8xx is AGP.
- */
-int i830_driver_device_is_agp(struct drm_device *dev)
-{
-	return 1;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_drv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,107 +0,0 @@
-/* i830_drv.c -- I810 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:56:22 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, 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
- * 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
- * VA LINUX SYSTEMS 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:
- *    Rickard E. (Rik) Faith <faith@valinux.com>
- *    Jeff Hartmann <jhartmann@valinux.com>
- *    Gareth Hughes <gareth@valinux.com>
- *    Abraham vd Merwe <abraham@2d3d.co.za>
- *    Keith Whitwell <keith@tungstengraphics.com>
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-
-#include "drm_pciids.h"
-
-static struct pci_device_id pciidlist[] = {
-	i830_PCI_IDS
-};
-
-static struct drm_driver driver = {
-	.driver_features =
-	    DRIVER_USE_AGP | DRIVER_REQUIRE_AGP | DRIVER_USE_MTRR |
-	    DRIVER_HAVE_DMA | DRIVER_DMA_QUEUE,
-#if USE_IRQS
-	.driver_features |= DRIVER_HAVE_IRQ | DRIVER_SHARED_IRQ,
-#endif
-	.dev_priv_size = sizeof(drm_i830_buf_priv_t),
-	.load = i830_driver_load,
-	.lastclose = i830_driver_lastclose,
-	.preclose = i830_driver_preclose,
-	.device_is_agp = i830_driver_device_is_agp,
-	.reclaim_buffers_locked = i830_driver_reclaim_buffers_locked,
-	.dma_quiescent = i830_driver_dma_quiescent,
-#if USE_IRQS
-	.irq_preinstall = i830_driver_irq_preinstall,
-	.irq_postinstall = i830_driver_irq_postinstall,
-	.irq_uninstall = i830_driver_irq_uninstall,
-	.irq_handler = i830_driver_irq_handler,
-#endif
-	.ioctls = i830_ioctls,
-	.fops = {
-		 .owner = THIS_MODULE,
-		 .open = drm_open,
-		 .release = drm_release,
-		 .unlocked_ioctl = i830_ioctl,
-		 .mmap = drm_mmap,
-		 .poll = drm_poll,
-		 .fasync = drm_fasync,
-		 .llseek = noop_llseek,
-	},
-
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
-	.name = DRIVER_NAME,
-	.desc = DRIVER_DESC,
-	.date = DRIVER_DATE,
-	.major = DRIVER_MAJOR,
-	.minor = DRIVER_MINOR,
-	.patchlevel = DRIVER_PATCHLEVEL,
-};
-
-static int __init i830_init(void)
-{
-	driver.num_ioctls = i830_max_ioctl;
-	return drm_init(&driver);
-}
-
-static void __exit i830_exit(void)
-{
-	drm_exit(&driver);
-}
-
-module_init(i830_init);
-module_exit(i830_exit);
-
-MODULE_AUTHOR(DRIVER_AUTHOR);
-MODULE_DESCRIPTION(DRIVER_DESC);
-MODULE_LICENSE("GPL and additional rights");
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_drv.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_drv.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_drv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_drv.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,295 +0,0 @@
-/* i830_drv.h -- Private header for the I830 driver -*- linux-c -*-
- * Created: Mon Dec 13 01:50:01 1999 by jhartmann@precisioninsight.com
- *
- * Copyright 1999 Precision Insight, Inc., Cedar Park, Texas.
- * Copyright 2000 VA Linux Systems, Inc., Sunnyvale, 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
- * 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: Rickard E. (Rik) Faith <faith@valinux.com>
- *	    Jeff Hartmann <jhartmann@valinux.com>
- *
- */
-
-#ifndef _I830_DRV_H_
-#define _I830_DRV_H_
-
-/* General customization:
- */
-
-#define DRIVER_AUTHOR		"VA Linux Systems Inc."
-
-#define DRIVER_NAME		"i830"
-#define DRIVER_DESC		"Intel 830M"
-#define DRIVER_DATE		"20021108"
-
-/* Interface history:
- *
- * 1.1: Original.
- * 1.2: ?
- * 1.3: New irq emit/wait ioctls.
- *      New pageflip ioctl.
- *      New getparam ioctl.
- *      State for texunits 3&4 in sarea.
- *      New (alternative) layout for texture state.
- */
-#define DRIVER_MAJOR		1
-#define DRIVER_MINOR		3
-#define DRIVER_PATCHLEVEL	2
-
-/* Driver will work either way: IRQ's save cpu time when waiting for
- * the card, but are subject to subtle interactions between bios,
- * hardware and the driver.
- */
-/* XXX: Add vblank support? */
-#define USE_IRQS 0
-
-typedef struct drm_i830_buf_priv {
-	u32 *in_use;
-	int my_use_idx;
-	int currently_mapped;
-	void __user *virtual;
-	void *kernel_virtual;
-	drm_local_map_t map;
-} drm_i830_buf_priv_t;
-
-typedef struct _drm_i830_ring_buffer {
-	int tail_mask;
-	unsigned long Start;
-	unsigned long End;
-	unsigned long Size;
-	u8 *virtual_start;
-	int head;
-	int tail;
-	int space;
-	drm_local_map_t map;
-} drm_i830_ring_buffer_t;
-
-typedef struct drm_i830_private {
-	struct drm_local_map *sarea_map;
-	struct drm_local_map *mmio_map;
-
-	drm_i830_sarea_t *sarea_priv;
-	drm_i830_ring_buffer_t ring;
-
-	void *hw_status_page;
-	unsigned long counter;
-
-	dma_addr_t dma_status_page;
-
-	struct drm_buf *mmap_buffer;
-
-	u32 front_di1, back_di1, zi1;
-
-	int back_offset;
-	int depth_offset;
-	int front_offset;
-	int w, h;
-	int pitch;
-	int back_pitch;
-	int depth_pitch;
-	unsigned int cpp;
-
-	int do_boxes;
-	int dma_used;
-
-	int current_page;
-	int page_flipping;
-
-	wait_queue_head_t irq_queue;
-	atomic_t irq_received;
-	atomic_t irq_emitted;
-
-	int use_mi_batchbuffer_start;
-
-} drm_i830_private_t;
-
-long i830_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
-extern struct drm_ioctl_desc i830_ioctls[];
-extern int i830_max_ioctl;
-
-/* i830_irq.c */
-extern int i830_irq_emit(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv);
-extern int i830_irq_wait(struct drm_device *dev, void *data,
-			 struct drm_file *file_priv);
-
-extern irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS);
-extern void i830_driver_irq_preinstall(struct drm_device *dev);
-extern void i830_driver_irq_postinstall(struct drm_device *dev);
-extern void i830_driver_irq_uninstall(struct drm_device *dev);
-extern int i830_driver_load(struct drm_device *, unsigned long flags);
-extern void i830_driver_preclose(struct drm_device *dev,
-				 struct drm_file *file_priv);
-extern void i830_driver_lastclose(struct drm_device *dev);
-extern void i830_driver_reclaim_buffers_locked(struct drm_device *dev,
-					       struct drm_file *file_priv);
-extern int i830_driver_dma_quiescent(struct drm_device *dev);
-extern int i830_driver_device_is_agp(struct drm_device *dev);
-
-#define I830_READ(reg)		DRM_READ32(dev_priv->mmio_map, reg)
-#define I830_WRITE(reg, val)	DRM_WRITE32(dev_priv->mmio_map, reg, val)
-#define I830_READ16(reg)	DRM_READ16(dev_priv->mmio_map, reg)
-#define I830_WRITE16(reg, val)	DRM_WRITE16(dev_priv->mmio_map, reg, val)
-
-#define I830_VERBOSE 0
-
-#define RING_LOCALS	unsigned int outring, ringmask, outcount; \
-			volatile char *virt;
-
-#define BEGIN_LP_RING(n) do {				\
-	if (I830_VERBOSE)				\
-		printk("BEGIN_LP_RING(%d)\n", (n));	\
-	if (dev_priv->ring.space < n*4)			\
-		i830_wait_ring(dev, n*4, __func__);	\
-	outcount = 0;					\
-	outring = dev_priv->ring.tail;			\
-	ringmask = dev_priv->ring.tail_mask;		\
-	virt = dev_priv->ring.virtual_start;		\
-} while (0)
-
-#define OUT_RING(n) do {					\
-	if (I830_VERBOSE)					\
-		printk("   OUT_RING %x\n", (int)(n));		\
-	*(volatile unsigned int *)(virt + outring) = n;		\
-	outcount++;						\
-	outring += 4;						\
-	outring &= ringmask;					\
-} while (0)
-
-#define ADVANCE_LP_RING() do {					\
-	if (I830_VERBOSE)					\
-		printk("ADVANCE_LP_RING %x\n", outring);	\
-	dev_priv->ring.tail = outring;				\
-	dev_priv->ring.space -= outcount * 4;			\
-	I830_WRITE(LP_RING + RING_TAIL, outring);		\
-} while (0)
-
-extern int i830_wait_ring(struct drm_device *dev, int n, const char *caller);
-
-#define GFX_OP_USER_INTERRUPT		((0<<29)|(2<<23))
-#define GFX_OP_BREAKPOINT_INTERRUPT	((0<<29)|(1<<23))
-#define CMD_REPORT_HEAD			(7<<23)
-#define CMD_STORE_DWORD_IDX		((0x21<<23) | 0x1)
-#define CMD_OP_BATCH_BUFFER  ((0x0<<29)|(0x30<<23)|0x1)
-
-#define STATE3D_LOAD_STATE_IMMEDIATE_2      ((0x3<<29)|(0x1d<<24)|(0x03<<16))
-#define LOAD_TEXTURE_MAP0                   (1<<11)
-
-#define INST_PARSER_CLIENT   0x00000000
-#define INST_OP_FLUSH        0x02000000
-#define INST_FLUSH_MAP_CACHE 0x00000001
-
-#define BB1_START_ADDR_MASK   (~0x7)
-#define BB1_PROTECTED         (1<<0)
-#define BB1_UNPROTECTED       (0<<0)
-#define BB2_END_ADDR_MASK     (~0x7)
-
-#define I830REG_HWSTAM		0x02098
-#define I830REG_INT_IDENTITY_R	0x020a4
-#define I830REG_INT_MASK_R	0x020a8
-#define I830REG_INT_ENABLE_R	0x020a0
-
-#define I830_IRQ_RESERVED ((1<<13)|(3<<2))
-
-#define LP_RING			0x2030
-#define HP_RING			0x2040
-#define RING_TAIL		0x00
-#define TAIL_ADDR		0x001FFFF8
-#define RING_HEAD		0x04
-#define HEAD_WRAP_COUNT		0xFFE00000
-#define HEAD_WRAP_ONE		0x00200000
-#define HEAD_ADDR		0x001FFFFC
-#define RING_START		0x08
-#define START_ADDR		0x0xFFFFF000
-#define RING_LEN		0x0C
-#define RING_NR_PAGES		0x001FF000
-#define RING_REPORT_MASK	0x00000006
-#define RING_REPORT_64K		0x00000002
-#define RING_REPORT_128K	0x00000004
-#define RING_NO_REPORT		0x00000000
-#define RING_VALID_MASK		0x00000001
-#define RING_VALID		0x00000001
-#define RING_INVALID		0x00000000
-
-#define GFX_OP_SCISSOR         ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define SC_UPDATE_SCISSOR       (0x1<<1)
-#define SC_ENABLE_MASK          (0x1<<0)
-#define SC_ENABLE               (0x1<<0)
-
-#define GFX_OP_SCISSOR_INFO    ((0x3<<29)|(0x1d<<24)|(0x81<<16)|(0x1))
-#define SCI_YMIN_MASK      (0xffff<<16)
-#define SCI_XMIN_MASK      (0xffff<<0)
-#define SCI_YMAX_MASK      (0xffff<<16)
-#define SCI_XMAX_MASK      (0xffff<<0)
-
-#define GFX_OP_SCISSOR_ENABLE	 ((0x3<<29)|(0x1c<<24)|(0x10<<19))
-#define GFX_OP_SCISSOR_RECT	 ((0x3<<29)|(0x1d<<24)|(0x81<<16)|1)
-#define GFX_OP_COLOR_FACTOR      ((0x3<<29)|(0x1d<<24)|(0x1<<16)|0x0)
-#define GFX_OP_STIPPLE           ((0x3<<29)|(0x1d<<24)|(0x83<<16))
-#define GFX_OP_MAP_INFO          ((0x3<<29)|(0x1d<<24)|0x4)
-#define GFX_OP_DESTBUFFER_VARS   ((0x3<<29)|(0x1d<<24)|(0x85<<16)|0x0)
-#define GFX_OP_DRAWRECT_INFO     ((0x3<<29)|(0x1d<<24)|(0x80<<16)|(0x3))
-#define GFX_OP_PRIMITIVE         ((0x3<<29)|(0x1f<<24))
-
-#define CMD_OP_DESTBUFFER_INFO	 ((0x3<<29)|(0x1d<<24)|(0x8e<<16)|1)
-
-#define CMD_OP_DISPLAYBUFFER_INFO ((0x0<<29)|(0x14<<23)|2)
-#define ASYNC_FLIP                (1<<22)
-
-#define CMD_3D                          (0x3<<29)
-#define STATE3D_CONST_BLEND_COLOR_CMD   (CMD_3D|(0x1d<<24)|(0x88<<16))
-#define STATE3D_MAP_COORD_SETBIND_CMD   (CMD_3D|(0x1d<<24)|(0x02<<16))
-
-#define BR00_BITBLT_CLIENT   0x40000000
-#define BR00_OP_COLOR_BLT    0x10000000
-#define BR00_OP_SRC_COPY_BLT 0x10C00000
-#define BR13_SOLID_PATTERN   0x80000000
-
-#define BUF_3D_ID_COLOR_BACK    (0x3<<24)
-#define BUF_3D_ID_DEPTH         (0x7<<24)
-#define BUF_3D_USE_FENCE        (1<<23)
-#define BUF_3D_PITCH(x)         (((x)/4)<<2)
-
-#define CMD_OP_MAP_PALETTE_LOAD	((3<<29)|(0x1d<<24)|(0x82<<16)|255)
-#define MAP_PALETTE_NUM(x)	((x<<8) & (1<<8))
-#define MAP_PALETTE_BOTH	(1<<11)
-
-#define XY_COLOR_BLT_CMD		((2<<29)|(0x50<<22)|0x4)
-#define XY_COLOR_BLT_WRITE_ALPHA	(1<<21)
-#define XY_COLOR_BLT_WRITE_RGB		(1<<20)
-
-#define XY_SRC_COPY_BLT_CMD             ((2<<29)|(0x53<<22)|6)
-#define XY_SRC_COPY_BLT_WRITE_ALPHA     (1<<21)
-#define XY_SRC_COPY_BLT_WRITE_RGB       (1<<20)
-
-#define MI_BATCH_BUFFER		((0x30<<23)|1)
-#define MI_BATCH_BUFFER_START	(0x31<<23)
-#define MI_BATCH_BUFFER_END	(0xA<<23)
-#define MI_BATCH_NON_SECURE	(1)
-
-#define MI_WAIT_FOR_EVENT       ((0x3<<23))
-#define MI_WAIT_FOR_PLANE_A_FLIP      (1<<2)
-#define MI_WAIT_FOR_PLANE_A_SCANLINES (1<<1)
-
-#define MI_LOAD_SCAN_LINES_INCL  ((0x12<<23))
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_irq.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_irq.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/i830_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/i830_irq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,186 +0,0 @@
-/* i830_dma.c -- DMA support for the I830 -*- linux-c -*-
- *
- * Copyright 2002 Tungsten Graphics, Inc.
- * 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
- * TUNGSTEN GRAPHICS 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: Keith Whitwell <keith@tungstengraphics.com>
- *
- */
-
-#include "drmP.h"
-#include "drm.h"
-#include "i830_drm.h"
-#include "i830_drv.h"
-#include <linux/interrupt.h>	/* For task queue support */
-#include <linux/delay.h>
-
-irqreturn_t i830_driver_irq_handler(DRM_IRQ_ARGS)
-{
-	struct drm_device *dev = (struct drm_device *) arg;
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	u16 temp;
-
-	temp = I830_READ16(I830REG_INT_IDENTITY_R);
-	DRM_DEBUG("%x\n", temp);
-
-	if (!(temp & 2))
-		return IRQ_NONE;
-
-	I830_WRITE16(I830REG_INT_IDENTITY_R, temp);
-
-	atomic_inc(&dev_priv->irq_received);
-	wake_up_interruptible(&dev_priv->irq_queue);
-
-	return IRQ_HANDLED;
-}
-
-static int i830_emit_irq(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	RING_LOCALS;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	atomic_inc(&dev_priv->irq_emitted);
-
-	BEGIN_LP_RING(2);
-	OUT_RING(0);
-	OUT_RING(GFX_OP_USER_INTERRUPT);
-	ADVANCE_LP_RING();
-
-	return atomic_read(&dev_priv->irq_emitted);
-}
-
-static int i830_wait_irq(struct drm_device *dev, int irq_nr)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	DECLARE_WAITQUEUE(entry, current);
-	unsigned long end = jiffies + HZ * 3;
-	int ret = 0;
-
-	DRM_DEBUG("%s\n", __func__);
-
-	if (atomic_read(&dev_priv->irq_received) >= irq_nr)
-		return 0;
-
-	dev_priv->sarea_priv->perf_boxes |= I830_BOX_WAIT;
-
-	add_wait_queue(&dev_priv->irq_queue, &entry);
-
-	for (;;) {
-		__set_current_state(TASK_INTERRUPTIBLE);
-		if (atomic_read(&dev_priv->irq_received) >= irq_nr)
-			break;
-		if ((signed)(end - jiffies) <= 0) {
-			DRM_ERROR("timeout iir %x imr %x ier %x hwstam %x\n",
-				  I830_READ16(I830REG_INT_IDENTITY_R),
-				  I830_READ16(I830REG_INT_MASK_R),
-				  I830_READ16(I830REG_INT_ENABLE_R),
-				  I830_READ16(I830REG_HWSTAM));
-
-			ret = -EBUSY;	/* Lockup?  Missed irq? */
-			break;
-		}
-		schedule_timeout(HZ * 3);
-		if (signal_pending(current)) {
-			ret = -EINTR;
-			break;
-		}
-	}
-
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&dev_priv->irq_queue, &entry);
-	return ret;
-}
-
-/* Needs the lock as it touches the ring.
- */
-int i830_irq_emit(struct drm_device *dev, void *data,
-		  struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_irq_emit_t *emit = data;
-	int result;
-
-	LOCK_TEST_WITH_RETURN(dev, file_priv);
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	result = i830_emit_irq(dev);
-
-	if (copy_to_user(emit->irq_seq, &result, sizeof(int))) {
-		DRM_ERROR("copy_to_user\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-
-/* Doesn't need the hardware lock.
- */
-int i830_irq_wait(struct drm_device *dev, void *data,
-		  struct drm_file *file_priv)
-{
-	drm_i830_private_t *dev_priv = dev->dev_private;
-	drm_i830_irq_wait_t *irqwait = data;
-
-	if (!dev_priv) {
-		DRM_ERROR("%s called with no initialization\n", __func__);
-		return -EINVAL;
-	}
-
-	return i830_wait_irq(dev, irqwait->irq_seq);
-}
-
-/* drm_dma.h hooks
-*/
-void i830_driver_irq_preinstall(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-
-	I830_WRITE16(I830REG_HWSTAM, 0xffff);
-	I830_WRITE16(I830REG_INT_MASK_R, 0x0);
-	I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
-	atomic_set(&dev_priv->irq_received, 0);
-	atomic_set(&dev_priv->irq_emitted, 0);
-	init_waitqueue_head(&dev_priv->irq_queue);
-}
-
-void i830_driver_irq_postinstall(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-
-	I830_WRITE16(I830REG_INT_ENABLE_R, 0x2);
-}
-
-void i830_driver_irq_uninstall(struct drm_device *dev)
-{
-	drm_i830_private_t *dev_priv = (drm_i830_private_t *) dev->dev_private;
-	if (!dev_priv)
-		return;
-
-	I830_WRITE16(I830REG_INT_MASK_R, 0xffff);
-	I830_WRITE16(I830REG_INT_ENABLE_R, 0x0);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/Makefile linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/Makefile
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i830/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i830/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-#
-# Makefile for the drm device driver.  This driver provides support for the
-# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
-
-ccflags-y := -Iinclude/drm
-i830-y := i830_drv.o i830_dma.o i830_irq.o
-
-obj-$(CONFIG_DRM_I830) += i830.o
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_debugfs.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_debugfs.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -326,21 +326,21 @@
 	struct intel_crtc *crtc;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, base.head) {
-		const char *pipe = crtc->pipe ? "B" : "A";
-		const char *plane = crtc->plane ? "B" : "A";
+		const char pipe = pipe_name(crtc->pipe);
+		const char plane = plane_name(crtc->plane);
 		struct intel_unpin_work *work;
 
 		spin_lock_irqsave(&dev->event_lock, flags);
 		work = crtc->unpin_work;
 		if (work == NULL) {
-			seq_printf(m, "No flip due on pipe %s (plane %s)\n",
+			seq_printf(m, "No flip due on pipe %c (plane %c)\n",
 				   pipe, plane);
 		} else {
 			if (!work->pending) {
-				seq_printf(m, "Flip queued on pipe %s (plane %s)\n",
+				seq_printf(m, "Flip queued on pipe %c (plane %c)\n",
 					   pipe, plane);
 			} else {
-				seq_printf(m, "Flip pending (waiting for vsync) on pipe %s (plane %s)\n",
+				seq_printf(m, "Flip pending (waiting for vsync) on pipe %c (plane %c)\n",
 					   pipe, plane);
 			}
 			if (work->enable_stall_check)
@@ -458,7 +458,7 @@
 	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;
-	int ret, i;
+	int ret, i, pipe;
 
 	ret = mutex_lock_interruptible(&dev->struct_mutex);
 	if (ret)
@@ -471,10 +471,10 @@
 			   I915_READ(IIR));
 		seq_printf(m, "Interrupt mask:      %08x\n",
 			   I915_READ(IMR));
-		seq_printf(m, "Pipe A stat:         %08x\n",
-			   I915_READ(PIPEASTAT));
-		seq_printf(m, "Pipe B stat:         %08x\n",
-			   I915_READ(PIPEBSTAT));
+		for_each_pipe(pipe)
+			seq_printf(m, "Pipe %c stat:         %08x\n",
+				   pipe_name(pipe),
+				   I915_READ(PIPESTAT(pipe)));
 	} else {
 		seq_printf(m, "North Display Interrupt enable:		%08x\n",
 			   I915_READ(DEIER));
@@ -544,11 +544,11 @@
 	struct drm_device *dev = node->minor->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *ring;
-	volatile u32 *hws;
+	const volatile u32 __iomem *hws;
 	int i;
 
 	ring = &dev_priv->ring[(uintptr_t)node->info_ent->data];
-	hws = (volatile u32 *)ring->status_page.page_addr;
+	hws = (volatile u32 __iomem *)ring->status_page.page_addr;
 	if (hws == NULL)
 		return 0;
 
@@ -615,7 +615,7 @@
 	if (!ring->obj) {
 		seq_printf(m, "No ringbuffer setup\n");
 	} else {
-		u8 *virt = ring->virtual_start;
+		const u8 __iomem *virt = ring->virtual_start;
 		uint32_t off;
 
 		for (off = 0; off < ring->size; off += 4) {
@@ -805,15 +805,20 @@
 		}
 	}
 
-	if (error->ringbuffer) {
-		struct drm_i915_error_object *obj = error->ringbuffer;
-
-		seq_printf(m, "--- ringbuffer = 0x%08x\n", obj->gtt_offset);
-		offset = 0;
-		for (page = 0; page < obj->page_count; page++) {
-			for (elt = 0; elt < PAGE_SIZE/4; elt++) {
-				seq_printf(m, "%08x :  %08x\n", offset, obj->pages[page][elt]);
-				offset += 4;
+	for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++) {
+		if (error->ringbuffer[i]) {
+			struct drm_i915_error_object *obj = error->ringbuffer[i];
+			seq_printf(m, "%s --- ringbuffer = 0x%08x\n",
+				   dev_priv->ring[i].name,
+				   obj->gtt_offset);
+			offset = 0;
+			for (page = 0; page < obj->page_count; page++) {
+				for (elt = 0; elt < PAGE_SIZE/4; elt++) {
+					seq_printf(m, "%08x :  %08x\n",
+						   offset,
+						   obj->pages[page][elt]);
+					offset += 4;
+				}
 			}
 		}
 	}
@@ -862,31 +867,56 @@
 		u32 gt_perf_status = I915_READ(GEN6_GT_PERF_STATUS);
 		u32 rp_state_limits = I915_READ(GEN6_RP_STATE_LIMITS);
 		u32 rp_state_cap = I915_READ(GEN6_RP_STATE_CAP);
+		u32 rpstat;
+		u32 rpupei, rpcurup, rpprevup;
+		u32 rpdownei, rpcurdown, rpprevdown;
 		int max_freq;
 
 		/* RPSTAT1 is in the GT power well */
 		__gen6_gt_force_wake_get(dev_priv);
 
+		rpstat = I915_READ(GEN6_RPSTAT1);
+		rpupei = I915_READ(GEN6_RP_CUR_UP_EI);
+		rpcurup = I915_READ(GEN6_RP_CUR_UP);
+		rpprevup = I915_READ(GEN6_RP_PREV_UP);
+		rpdownei = I915_READ(GEN6_RP_CUR_DOWN_EI);
+		rpcurdown = I915_READ(GEN6_RP_CUR_DOWN);
+		rpprevdown = I915_READ(GEN6_RP_PREV_DOWN);
+
 		seq_printf(m, "GT_PERF_STATUS: 0x%08x\n", gt_perf_status);
-		seq_printf(m, "RPSTAT1: 0x%08x\n", I915_READ(GEN6_RPSTAT1));
+		seq_printf(m, "RPSTAT1: 0x%08x\n", rpstat);
 		seq_printf(m, "Render p-state ratio: %d\n",
 			   (gt_perf_status & 0xff00) >> 8);
 		seq_printf(m, "Render p-state VID: %d\n",
 			   gt_perf_status & 0xff);
 		seq_printf(m, "Render p-state limit: %d\n",
 			   rp_state_limits & 0xff);
+		seq_printf(m, "CAGF: %dMHz\n", ((rpstat & GEN6_CAGF_MASK) >>
+						GEN6_CAGF_SHIFT) * 50);
+		seq_printf(m, "RP CUR UP EI: %dus\n", rpupei &
+			   GEN6_CURICONT_MASK);
+		seq_printf(m, "RP CUR UP: %dus\n", rpcurup &
+			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP PREV UP: %dus\n", rpprevup &
+			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP CUR DOWN EI: %dus\n", rpdownei &
+			   GEN6_CURIAVG_MASK);
+		seq_printf(m, "RP CUR DOWN: %dus\n", rpcurdown &
+			   GEN6_CURBSYTAVG_MASK);
+		seq_printf(m, "RP PREV DOWN: %dus\n", rpprevdown &
+			   GEN6_CURBSYTAVG_MASK);
 
 		max_freq = (rp_state_cap & 0xff0000) >> 16;
 		seq_printf(m, "Lowest (RPN) frequency: %dMHz\n",
-			   max_freq * 100);
+			   max_freq * 50);
 
 		max_freq = (rp_state_cap & 0xff00) >> 8;
 		seq_printf(m, "Nominal (RP1) frequency: %dMHz\n",
-			   max_freq * 100);
+			   max_freq * 50);
 
 		max_freq = rp_state_cap & 0xff;
 		seq_printf(m, "Max non-overclocked (RP0) frequency: %dMHz\n",
-			   max_freq * 100);
+			   max_freq * 50);
 
 		__gen6_gt_force_wake_put(dev_priv);
 	} else {
@@ -1259,7 +1289,7 @@
 }
 
 static struct drm_info_list i915_debugfs_list[] = {
-	{"i915_capabilities", i915_capabilities, 0, 0},
+	{"i915_capabilities", i915_capabilities, 0},
 	{"i915_gem_objects", i915_gem_object_info, 0},
 	{"i915_gem_gtt", i915_gem_gtt_info, 0},
 	{"i915_gem_active", i915_gem_object_list_info, 0, (void *) ACTIVE_LIST},
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_dma.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_dma.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,17 @@
 #include <linux/slab.h>
 #include <acpi/video.h>
 
+static void i915_write_hws_pga(struct drm_device *dev)
+{
+	drm_i915_private_t *dev_priv = dev->dev_private;
+	u32 addr;
+
+	addr = dev_priv->status_page_dmah->busaddr;
+	if (INTEL_INFO(dev)->gen >= 4)
+		addr |= (dev_priv->status_page_dmah->busaddr >> 28) & 0xf0;
+	I915_WRITE(HWS_PGA, addr);
+}
+
 /**
  * Sets up the hardware status page for devices that need a physical address
  * in the register.
@@ -60,16 +71,13 @@
 		DRM_ERROR("Can not allocate hardware status page\n");
 		return -ENOMEM;
 	}
-	ring->status_page.page_addr = dev_priv->status_page_dmah->vaddr;
-	dev_priv->dma_status_page = dev_priv->status_page_dmah->busaddr;
+	ring->status_page.page_addr =
+		(void __force __iomem *)dev_priv->status_page_dmah->vaddr;
 
-	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+	memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
 
-	if (INTEL_INFO(dev)->gen >= 4)
-		dev_priv->dma_status_page |= (dev_priv->dma_status_page >> 28) &
-					     0xf0;
+	i915_write_hws_pga(dev);
 
-	I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
 	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 	return 0;
 }
@@ -216,7 +224,7 @@
 	if (ring->status_page.gfx_addr != 0)
 		intel_ring_setup_status_page(ring);
 	else
-		I915_WRITE(HWS_PGA, dev_priv->dma_status_page);
+		i915_write_hws_pga(dev);
 
 	DRM_DEBUG_DRIVER("Enabled hardware status page\n");
 
@@ -771,6 +779,9 @@
 	case I915_PARAM_HAS_EXEC_CONSTANTS:
 		value = INTEL_INFO(dev)->gen >= 4;
 		break;
+	case I915_PARAM_HAS_RELAXED_DELTA:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG_DRIVER("Unknown parameter %d\n",
 				 param->param);
@@ -859,8 +870,9 @@
 				" G33 hw status page\n");
 		return -ENOMEM;
 	}
-	ring->status_page.page_addr = dev_priv->hws_map.handle;
-	memset(ring->status_page.page_addr, 0, PAGE_SIZE);
+	ring->status_page.page_addr =
+		(void __force __iomem *)dev_priv->hws_map.handle;
+	memset_io(ring->status_page.page_addr, 0, PAGE_SIZE);
 	I915_WRITE(HWS_PGA, ring->status_page.gfx_addr);
 
 	DRM_DEBUG_DRIVER("load hws HWS_PGA with gfx mem 0x%x\n",
@@ -2013,9 +2025,13 @@
 
 	spin_lock_init(&dev_priv->irq_lock);
 	spin_lock_init(&dev_priv->error_lock);
-	dev_priv->trace_irq_seqno = 0;
 
-	ret = drm_vblank_init(dev, I915_NUM_PIPE);
+	if (IS_MOBILE(dev) || !IS_GEN2(dev))
+		dev_priv->num_pipe = 2;
+	else
+		dev_priv->num_pipe = 1;
+
+	ret = drm_vblank_init(dev, dev_priv->num_pipe);
 	if (ret)
 		goto out_gem_unload;
 
@@ -2191,7 +2207,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 
 	if (!dev_priv || drm_core_check_feature(dev, DRIVER_MODESET)) {
-		drm_fb_helper_restore();
+		intel_fb_restore_mode(dev);
 		vga_switcheroo_process_delayed_switch();
 		return;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,9 @@
 unsigned int i915_fbpercrtc = 0;
 module_param_named(fbpercrtc, i915_fbpercrtc, int, 0400);
 
+int i915_panel_ignore_lid = 0;
+module_param_named(panel_ignore_lid, i915_panel_ignore_lid, int, 0600);
+
 unsigned int i915_powersave = 1;
 module_param_named(powersave, i915_powersave, int, 0600);
 
@@ -58,7 +61,10 @@
 unsigned int i915_panel_use_ssc = 1;
 module_param_named(lvds_use_ssc, i915_panel_use_ssc, int, 0600);
 
-bool i915_try_reset = true;
+int i915_vbt_sdvo_panel_type = -1;
+module_param_named(vbt_sdvo_panel_type, i915_vbt_sdvo_panel_type, int, 0600);
+
+static bool i915_try_reset = true;
 module_param_named(reset, i915_try_reset, bool, 0600);
 
 static struct drm_driver driver;
@@ -716,6 +722,9 @@
 	.gem_init_object = i915_gem_init_object,
 	.gem_free_object = i915_gem_free_object,
 	.gem_vm_ops = &i915_gem_vm_ops,
+	.dumb_create = i915_gem_dumb_create,
+	.dumb_map_offset = i915_gem_mmap_gtt,
+	.dumb_destroy = i915_gem_dumb_destroy,
 	.ioctls = i915_ioctls,
 	.fops = {
 		 .owner = THIS_MODULE,
@@ -732,14 +741,6 @@
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-		 .probe = i915_pci_probe,
-		 .remove = i915_pci_remove,
-		 .driver.pm = &i915_pm_ops,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -748,6 +749,14 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver i915_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+	.probe = i915_pci_probe,
+	.remove = i915_pci_remove,
+	.driver.pm = &i915_pm_ops,
+};
+
 static int __init i915_init(void)
 {
 	if (!intel_agp_enabled) {
@@ -781,12 +790,12 @@
 	if (!(driver.driver_features & DRIVER_MODESET))
 		driver.get_vblank_timestamp = NULL;
 
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &i915_pci_driver);
 }
 
 static void __exit i915_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &i915_pci_driver);
 }
 
 module_init(i915_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_drv.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_drv.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_drv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_drv.h	2011-05-19 00:06:34.000000000 -0400
@@ -49,17 +49,22 @@
 enum pipe {
 	PIPE_A = 0,
 	PIPE_B,
+	PIPE_C,
+	I915_MAX_PIPES
 };
+#define pipe_name(p) ((p) + 'A')
 
 enum plane {
 	PLANE_A = 0,
 	PLANE_B,
+	PLANE_C,
 };
-
-#define I915_NUM_PIPE	2
+#define plane_name(p) ((p) + 'A')
 
 #define I915_GEM_GPU_DOMAINS	(~(I915_GEM_DOMAIN_CPU | I915_GEM_DOMAIN_GTT))
 
+#define for_each_pipe(p) for ((p) = 0; (p) < dev_priv->num_pipe; (p)++)
+
 /* Interface history:
  *
  * 1.1: Original.
@@ -75,10 +80,7 @@
 #define DRIVER_PATCHLEVEL	0
 
 #define WATCH_COHERENCY	0
-#define WATCH_EXEC	0
-#define WATCH_RELOC	0
 #define WATCH_LISTS	0
-#define WATCH_PWRITE	0
 
 #define I915_GEM_PHYS_CURSOR_0 1
 #define I915_GEM_PHYS_CURSOR_1 2
@@ -111,6 +113,7 @@
 	struct opregion_swsci *swsci;
 	struct opregion_asle *asle;
 	void *vbt;
+	u32 __iomem *lid_state;
 };
 #define OPREGION_SIZE            (8*1024)
 
@@ -144,8 +147,7 @@
 struct drm_i915_error_state {
 	u32 eir;
 	u32 pgtbl_er;
-	u32 pipeastat;
-	u32 pipebstat;
+	u32 pipestat[I915_MAX_PIPES];
 	u32 ipeir;
 	u32 ipehr;
 	u32 instdone;
@@ -172,7 +174,7 @@
 		int page_count;
 		u32 gtt_offset;
 		u32 *pages[0];
-	} *ringbuffer, *batchbuffer[I915_NUM_RINGS];
+	} *ringbuffer[I915_NUM_RINGS], *batchbuffer[I915_NUM_RINGS];
 	struct drm_i915_error_buffer {
 		u32 size;
 		u32 name;
@@ -200,9 +202,7 @@
 	void (*disable_fbc)(struct drm_device *dev);
 	int (*get_display_clock_speed)(struct drm_device *dev);
 	int (*get_fifo_size)(struct drm_device *dev, int plane);
-	void (*update_wm)(struct drm_device *dev, int planea_clock,
-			  int planeb_clock, int sr_hdisplay, int sr_htotal,
-			  int pixel_size);
+	void (*update_wm)(struct drm_device *dev);
 	/* clock updates for mode set */
 	/* cursor updates */
 	/* render clock increase/decrease */
@@ -274,7 +274,6 @@
 	uint32_t next_seqno;
 
 	drm_dma_handle_t *status_page_dmah;
-	dma_addr_t dma_status_page;
 	uint32_t counter;
 	drm_local_map_t hws_map;
 	struct drm_i915_gem_object *pwrctx;
@@ -289,7 +288,6 @@
 	int page_flipping;
 
 	atomic_t irq_received;
-	u32 trace_irq_seqno;
 
 	/* protects the irq masks */
 	spinlock_t irq_lock;
@@ -324,8 +322,6 @@
 	int cfb_plane;
 	int cfb_y;
 
-	int irq_enabled;
-
 	struct intel_opregion opregion;
 
 	/* overlay */
@@ -615,6 +611,12 @@
 		struct delayed_work retire_work;
 
 		/**
+		 * Are we in a non-interruptible section of code like
+		 * modesetting?
+		 */
+		bool interruptible;
+
+		/**
 		 * Flag if the X Server, and thus DRM, is not currently in
 		 * control of the device.
 		 *
@@ -628,7 +630,7 @@
 		 * Flag if the hardware appears to be wedged.
 		 *
 		 * This is set when attempts to idle the device timeout.
-		 * It prevents command submission from occuring and makes
+		 * It prevents command submission from occurring and makes
 		 * every pending request fail
 		 */
 		atomic_t wedged;
@@ -652,6 +654,7 @@
 	unsigned int lvds_border_bits;
 	/* Panel fitter placement and size for Ironlake+ */
 	u32 pch_pf_pos, pch_pf_size;
+	int panel_t3, panel_t12;
 
 	struct drm_crtc *plane_to_crtc_mapping[2];
 	struct drm_crtc *pipe_to_crtc_mapping[2];
@@ -698,6 +701,8 @@
 
 	/* list of fbdev register on this device */
 	struct intel_fbdev *fbdev;
+
+	struct drm_property *broadcast_rgb_property;
 } drm_i915_private_t;
 
 struct drm_i915_gem_object {
@@ -955,10 +960,12 @@
 extern struct drm_ioctl_desc i915_ioctls[];
 extern int i915_max_ioctl;
 extern unsigned int i915_fbpercrtc;
+extern int i915_panel_ignore_lid;
 extern unsigned int i915_powersave;
 extern unsigned int i915_semaphores;
 extern unsigned int i915_lvds_downclock;
 extern unsigned int i915_panel_use_ssc;
+extern int i915_vbt_sdvo_panel_type;
 extern unsigned int i915_enable_rc6;
 
 extern int i915_suspend(struct drm_device *dev, pm_message_t state);
@@ -998,8 +1005,6 @@
 			 struct drm_file *file_priv);
 extern int i915_irq_wait(struct drm_device *dev, void *data,
 			 struct drm_file *file_priv);
-void i915_trace_irq_get(struct drm_device *dev, u32 seqno);
-extern void i915_enable_interrupt (struct drm_device *dev);
 
 extern irqreturn_t i915_driver_irq_handler(DRM_IRQ_ARGS);
 extern void i915_driver_irq_preinstall(struct drm_device * dev);
@@ -1051,7 +1056,6 @@
 extern void i915_mem_release(struct drm_device * dev,
 			     struct drm_file *file_priv, struct mem_block *heap);
 /* i915_gem.c */
-int i915_gem_check_is_wedged(struct drm_device *dev);
 int i915_gem_init_ioctl(struct drm_device *dev, void *data,
 			struct drm_file *file_priv);
 int i915_gem_create_ioctl(struct drm_device *dev, void *data,
@@ -1094,8 +1098,7 @@
 				struct drm_file *file_priv);
 void i915_gem_load(struct drm_device *dev);
 int i915_gem_init_object(struct drm_gem_object *obj);
-int __must_check i915_gem_flush_ring(struct drm_device *dev,
-				     struct intel_ring_buffer *ring,
+int __must_check i915_gem_flush_ring(struct intel_ring_buffer *ring,
 				     uint32_t invalidate_domains,
 				     uint32_t flush_domains);
 struct drm_i915_gem_object *i915_gem_alloc_object(struct drm_device *dev,
@@ -1110,12 +1113,18 @@
 void i915_gem_lastclose(struct drm_device *dev);
 
 int __must_check i915_mutex_lock_interruptible(struct drm_device *dev);
-int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
-						bool interruptible);
+int __must_check i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj);
 void i915_gem_object_move_to_active(struct drm_i915_gem_object *obj,
 				    struct intel_ring_buffer *ring,
 				    u32 seqno);
 
+int i915_gem_dumb_create(struct drm_file *file_priv,
+			 struct drm_device *dev,
+			 struct drm_mode_create_dumb *args);
+int i915_gem_mmap_gtt(struct drm_file *file_priv, struct drm_device *dev,
+		      uint32_t handle, uint64_t *offset);
+int i915_gem_dumb_destroy(struct drm_file *file_priv, struct drm_device *dev,
+			  uint32_t handle);			  
 /**
  * Returns true if seq1 is later than seq2.
  */
@@ -1126,16 +1135,14 @@
 }
 
 static inline u32
-i915_gem_next_request_seqno(struct drm_device *dev,
-			    struct intel_ring_buffer *ring)
+i915_gem_next_request_seqno(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	return ring->outstanding_lazy_request = dev_priv->next_seqno;
 }
 
 int __must_check i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
-					   struct intel_ring_buffer *pipelined,
-					   bool interruptible);
+					   struct intel_ring_buffer *pipelined);
 int __must_check i915_gem_object_put_fence(struct drm_i915_gem_object *obj);
 
 void i915_gem_retire_requests(struct drm_device *dev);
@@ -1144,8 +1151,7 @@
 int __must_check i915_gem_object_set_domain(struct drm_i915_gem_object *obj,
 					    uint32_t read_domains,
 					    uint32_t write_domain);
-int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
-					   bool interruptible);
+int __must_check i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj);
 int __must_check i915_gem_init_ringbuffer(struct drm_device *dev);
 void i915_gem_cleanup_ringbuffer(struct drm_device *dev);
 void i915_gem_do_init(struct drm_device *dev,
@@ -1154,14 +1160,11 @@
 		      unsigned long end);
 int __must_check i915_gpu_idle(struct drm_device *dev);
 int __must_check i915_gem_idle(struct drm_device *dev);
-int __must_check i915_add_request(struct drm_device *dev,
-				  struct drm_file *file_priv,
-				  struct drm_i915_gem_request *request,
-				  struct intel_ring_buffer *ring);
-int __must_check i915_do_wait_request(struct drm_device *dev,
-				      uint32_t seqno,
-				      bool interruptible,
-				      struct intel_ring_buffer *ring);
+int __must_check i915_add_request(struct intel_ring_buffer *ring,
+				  struct drm_file *file,
+				  struct drm_i915_gem_request *request);
+int __must_check i915_wait_request(struct intel_ring_buffer *ring,
+				   uint32_t seqno);
 int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf);
 int __must_check
 i915_gem_object_set_to_gtt_domain(struct drm_i915_gem_object *obj,
@@ -1313,7 +1316,7 @@
 #define __i915_read(x, y) \
 static inline u##x i915_read##x(struct drm_i915_private *dev_priv, u32 reg) { \
 	u##x val = read##y(dev_priv->regs + reg); \
-	trace_i915_reg_rw('R', reg, val, sizeof(val)); \
+	trace_i915_reg_rw(false, reg, val, sizeof(val)); \
 	return val; \
 }
 __i915_read(8, b)
@@ -1324,7 +1327,7 @@
 
 #define __i915_write(x, y) \
 static inline void i915_write##x(struct drm_i915_private *dev_priv, u32 reg, u##x val) { \
-	trace_i915_reg_rw('W', reg, val, sizeof(val)); \
+	trace_i915_reg_rw(true, reg, val, sizeof(val)); \
 	write##y(val, dev_priv->regs + reg); \
 }
 __i915_write(8, b)
@@ -1382,47 +1385,4 @@
 		__gen6_gt_wait_for_fifo(dev_priv);
 	I915_WRITE(reg, val);
 }
-
-static inline void
-i915_write(struct drm_i915_private *dev_priv, u32 reg, u64 val, int len)
-{
-       /* Trace down the write operation before the real write */
-       trace_i915_reg_rw('W', reg, val, len);
-       switch (len) {
-       case 8:
-               writeq(val, dev_priv->regs + reg);
-               break;
-       case 4:
-               writel(val, dev_priv->regs + reg);
-               break;
-       case 2:
-               writew(val, dev_priv->regs + reg);
-               break;
-       case 1:
-               writeb(val, dev_priv->regs + reg);
-               break;
-       }
-}
-
-/**
- * Reads a dword out of the status page, which is written to from the command
- * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
- * MI_STORE_DATA_IMM.
- *
- * The following dwords have a reserved meaning:
- * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
- * 0x04: ring 0 head pointer
- * 0x05: ring 1 head pointer (915-class)
- * 0x06: ring 2 head pointer (915-class)
- * 0x10-0x1b: Context status DWords (GM45)
- * 0x1f: Last written status offset. (GM45)
- *
- * The area from dword 0x20 to 0x3ff is available for driver usage.
- */
-#define READ_HWSP(dev_priv, reg)  (((volatile u32 *)\
-			(LP_RING(dev_priv)->status_page.page_addr))[reg])
-#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
-#define I915_GEM_HWS_INDEX		0x20
-#define I915_BREADCRUMB_INDEX		0x21
-
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,8 +75,8 @@
 	dev_priv->mm.object_memory -= size;
 }
 
-int
-i915_gem_check_is_wedged(struct drm_device *dev)
+static int
+i915_gem_wait_for_error(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct completion *x = &dev_priv->error_completion;
@@ -90,27 +90,24 @@
 	if (ret)
 		return ret;
 
-	/* Success, we reset the GPU! */
-	if (!atomic_read(&dev_priv->mm.wedged))
-		return 0;
-
-	/* GPU is hung, bump the completion count to account for
-	 * the token we just consumed so that we never hit zero and
-	 * end up waiting upon a subsequent completion event that
-	 * will never happen.
-	 */
-	spin_lock_irqsave(&x->wait.lock, flags);
-	x->done++;
-	spin_unlock_irqrestore(&x->wait.lock, flags);
-	return -EIO;
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		/* GPU is hung, bump the completion count to account for
+		 * the token we just consumed so that we never hit zero and
+		 * end up waiting upon a subsequent completion event that
+		 * will never happen.
+		 */
+		spin_lock_irqsave(&x->wait.lock, flags);
+		x->done++;
+		spin_unlock_irqrestore(&x->wait.lock, flags);
+	}
+	return 0;
 }
 
 int i915_mutex_lock_interruptible(struct drm_device *dev)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret;
 
-	ret = i915_gem_check_is_wedged(dev);
+	ret = i915_gem_wait_for_error(dev);
 	if (ret)
 		return ret;
 
@@ -118,11 +115,6 @@
 	if (ret)
 		return ret;
 
-	if (atomic_read(&dev_priv->mm.wedged)) {
-		mutex_unlock(&dev->struct_mutex);
-		return -EAGAIN;
-	}
-
 	WARN_ON(i915_verify_lists(dev));
 	return 0;
 }
@@ -193,22 +185,20 @@
 	return 0;
 }
 
-/**
- * Creates a new mm object and returns a handle to it.
- */
-int
-i915_gem_create_ioctl(struct drm_device *dev, void *data,
-		      struct drm_file *file)
+static int
+i915_gem_create(struct drm_file *file,
+		struct drm_device *dev,
+		uint64_t size,
+		uint32_t *handle_p)
 {
-	struct drm_i915_gem_create *args = data;
 	struct drm_i915_gem_object *obj;
 	int ret;
 	u32 handle;
 
-	args->size = roundup(args->size, PAGE_SIZE);
+	size = roundup(size, PAGE_SIZE);
 
 	/* Allocate the new object */
-	obj = i915_gem_alloc_object(dev, args->size);
+	obj = i915_gem_alloc_object(dev, size);
 	if (obj == NULL)
 		return -ENOMEM;
 
@@ -224,10 +214,41 @@
 	drm_gem_object_unreference(&obj->base);
 	trace_i915_gem_object_create(obj);
 
-	args->handle = handle;
+	*handle_p = handle;
 	return 0;
 }
 
+int
+i915_gem_dumb_create(struct drm_file *file,
+		     struct drm_device *dev,
+		     struct drm_mode_create_dumb *args)
+{
+	/* have to work out size/pitch and return them */
+	args->pitch = ALIGN(args->width * ((args->bpp + 7) / 8), 64);
+	args->size = args->pitch * args->height;
+	return i915_gem_create(file, dev,
+			       args->size, &args->handle);
+}
+
+int i915_gem_dumb_destroy(struct drm_file *file,
+			  struct drm_device *dev,
+			  uint32_t handle)
+{
+	return drm_gem_handle_delete(file, handle);
+}
+
+/**
+ * Creates a new mm object and returns a handle to it.
+ */
+int
+i915_gem_create_ioctl(struct drm_device *dev, void *data,
+		      struct drm_file *file)
+{
+	struct drm_i915_gem_create *args = data;
+	return i915_gem_create(file, dev,
+			       args->size, &args->handle);
+}
+
 static int i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
 {
 	drm_i915_private_t *dev_priv = obj->base.dev->dev_private;
@@ -514,7 +535,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -526,6 +547,8 @@
 		goto out;
 	}
 
+	trace_i915_gem_object_pread(obj, args->offset, args->size);
+
 	ret = i915_gem_object_set_cpu_read_domain_range(obj,
 							args->offset,
 							args->size);
@@ -955,7 +978,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -967,6 +990,8 @@
 		goto out;
 	}
 
+	trace_i915_gem_object_pwrite(obj, args->offset, args->size);
+
 	/* We can only do the GTT pwrite on untiled buffers, as otherwise
 	 * it would end up going through the fenced access, and we'll get
 	 * different detiling behavior between reading and writing.
@@ -1049,7 +1074,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -1092,7 +1117,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -1121,7 +1146,6 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_gem_mmap *args = data;
 	struct drm_gem_object *obj;
-	loff_t offset;
 	unsigned long addr;
 
 	if (!(dev->driver->driver_features & DRIVER_GEM))
@@ -1136,8 +1160,6 @@
 		return -E2BIG;
 	}
 
-	offset = args->offset;
-
 	down_write(&current->mm->mmap_sem);
 	addr = do_mmap(obj->filp, 0, args->size,
 		       PROT_READ | PROT_WRITE, MAP_SHARED,
@@ -1182,9 +1204,13 @@
 	page_offset = ((unsigned long)vmf->virtual_address - vma->vm_start) >>
 		PAGE_SHIFT;
 
-	/* Now bind it into the GTT if needed */
-	mutex_lock(&dev->struct_mutex);
+	ret = i915_mutex_lock_interruptible(dev);
+	if (ret)
+		goto out;
 
+	trace_i915_gem_object_fault(obj, page_offset, true, write);
+
+	/* Now bind it into the GTT if needed */
 	if (!obj->map_and_fenceable) {
 		ret = i915_gem_object_unbind(obj);
 		if (ret)
@@ -1203,7 +1229,7 @@
 	if (obj->tiling_mode == I915_TILING_NONE)
 		ret = i915_gem_object_put_fence(obj);
 	else
-		ret = i915_gem_object_get_fence(obj, NULL, true);
+		ret = i915_gem_object_get_fence(obj, NULL);
 	if (ret)
 		goto unlock;
 
@@ -1219,12 +1245,21 @@
 	ret = vm_insert_pfn(vma, (unsigned long)vmf->virtual_address, pfn);
 unlock:
 	mutex_unlock(&dev->struct_mutex);
-
+out:
 	switch (ret) {
+	case -EIO:
 	case -EAGAIN:
+		/* Give the error handler a chance to run and move the
+		 * objects off the GPU active list. Next time we service the
+		 * fault, we should be able to transition the page into the
+		 * GTT without touching the GPU (and so avoid further
+		 * EIO/EGAIN). If the GPU is wedged, then there is no issue
+		 * with coherency, just lost writes.
+		 */
 		set_need_resched();
 	case 0:
 	case -ERESTARTSYS:
+	case -EINTR:
 		return VM_FAULT_NOPAGE;
 	case -ENOMEM:
 		return VM_FAULT_OOM;
@@ -1321,9 +1356,10 @@
 	if (!obj->fault_mappable)
 		return;
 
-	unmap_mapping_range(obj->base.dev->dev_mapping,
-			    (loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT,
-			    obj->base.size, 1);
+	if (obj->base.dev->dev_mapping)
+		unmap_mapping_range(obj->base.dev->dev_mapping,
+				    (loff_t)obj->base.map_list.hash.key<<PAGE_SHIFT,
+				    obj->base.size, 1);
 
 	obj->fault_mappable = false;
 }
@@ -1425,27 +1461,13 @@
 	return tile_height * obj->stride * 2;
 }
 
-/**
- * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
- * @dev: DRM device
- * @data: GTT mapping ioctl data
- * @file: GEM object info
- *
- * Simply returns the fake offset to userspace so it can mmap it.
- * The mmap call will end up in drm_gem_mmap(), which will set things
- * up so we can get faults in the handler above.
- *
- * The fault handler will take care of binding the object into the GTT
- * (since it may have been evicted to make room for something), allocating
- * a fence register, and mapping the appropriate aperture address into
- * userspace.
- */
 int
-i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
-			struct drm_file *file)
+i915_gem_mmap_gtt(struct drm_file *file,
+		  struct drm_device *dev,
+		  uint32_t handle,
+		  uint64_t *offset)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_i915_gem_mmap_gtt *args = data;
 	struct drm_i915_gem_object *obj;
 	int ret;
 
@@ -1456,8 +1478,8 @@
 	if (ret)
 		return ret;
 
-	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -1479,7 +1501,7 @@
 			goto out;
 	}
 
-	args->offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
+	*offset = (u64)obj->base.map_list.hash.key << PAGE_SHIFT;
 
 out:
 	drm_gem_object_unreference(&obj->base);
@@ -1488,6 +1510,34 @@
 	return ret;
 }
 
+/**
+ * i915_gem_mmap_gtt_ioctl - prepare an object for GTT mmap'ing
+ * @dev: DRM device
+ * @data: GTT mapping ioctl data
+ * @file: GEM object info
+ *
+ * Simply returns the fake offset to userspace so it can mmap it.
+ * The mmap call will end up in drm_gem_mmap(), which will set things
+ * up so we can get faults in the handler above.
+ *
+ * The fault handler will take care of binding the object into the GTT
+ * (since it may have been evicted to make room for something), allocating
+ * a fence register, and mapping the appropriate aperture address into
+ * userspace.
+ */
+int
+i915_gem_mmap_gtt_ioctl(struct drm_device *dev, void *data,
+			struct drm_file *file)
+{
+	struct drm_i915_gem_mmap_gtt *args = data;
+
+	if (!(dev->driver->driver_features & DRIVER_GEM))
+		return -ENODEV;
+
+	return i915_gem_mmap_gtt(file, dev, args->handle, &args->offset);
+}
+
+
 static int
 i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj,
 			      gfp_t gfpmask)
@@ -1669,9 +1719,8 @@
 }
 
 static void
-i915_gem_process_flushing_list(struct drm_device *dev,
-			       uint32_t flush_domains,
-			       struct intel_ring_buffer *ring)
+i915_gem_process_flushing_list(struct intel_ring_buffer *ring,
+			       uint32_t flush_domains)
 {
 	struct drm_i915_gem_object *obj, *next;
 
@@ -1684,7 +1733,7 @@
 			obj->base.write_domain = 0;
 			list_del_init(&obj->gpu_write_list);
 			i915_gem_object_move_to_active(obj, ring,
-						       i915_gem_next_request_seqno(dev, ring));
+						       i915_gem_next_request_seqno(ring));
 
 			trace_i915_gem_object_change_domain(obj,
 							    obj->base.read_domains,
@@ -1694,27 +1743,22 @@
 }
 
 int
-i915_add_request(struct drm_device *dev,
+i915_add_request(struct intel_ring_buffer *ring,
 		 struct drm_file *file,
-		 struct drm_i915_gem_request *request,
-		 struct intel_ring_buffer *ring)
+		 struct drm_i915_gem_request *request)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
-	struct drm_i915_file_private *file_priv = NULL;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	uint32_t seqno;
 	int was_empty;
 	int ret;
 
 	BUG_ON(request == NULL);
 
-	if (file != NULL)
-		file_priv = file->driver_priv;
-
 	ret = ring->add_request(ring, &seqno);
 	if (ret)
 	    return ret;
 
-	ring->outstanding_lazy_request = false;
+	trace_i915_gem_request_add(ring, seqno);
 
 	request->seqno = seqno;
 	request->ring = ring;
@@ -1722,7 +1766,9 @@
 	was_empty = list_empty(&ring->request_list);
 	list_add_tail(&request->list, &ring->request_list);
 
-	if (file_priv) {
+	if (file) {
+		struct drm_i915_file_private *file_priv = file->driver_priv;
+
 		spin_lock(&file_priv->mm.lock);
 		request->file_priv = file_priv;
 		list_add_tail(&request->client_list,
@@ -1730,6 +1776,8 @@
 		spin_unlock(&file_priv->mm.lock);
 	}
 
+	ring->outstanding_lazy_request = false;
+
 	if (!dev_priv->mm.suspended) {
 		mod_timer(&dev_priv->hangcheck_timer,
 			  jiffies + msecs_to_jiffies(DRM_I915_HANGCHECK_PERIOD));
@@ -1749,8 +1797,10 @@
 		return;
 
 	spin_lock(&file_priv->mm.lock);
-	list_del(&request->client_list);
-	request->file_priv = NULL;
+	if (request->file_priv) {
+		list_del(&request->client_list);
+		request->file_priv = NULL;
+	}
 	spin_unlock(&file_priv->mm.lock);
 }
 
@@ -1846,18 +1896,15 @@
  * This function clears the request list as sequence numbers are passed.
  */
 static void
-i915_gem_retire_requests_ring(struct drm_device *dev,
-			      struct intel_ring_buffer *ring)
+i915_gem_retire_requests_ring(struct intel_ring_buffer *ring)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	uint32_t seqno;
 	int i;
 
-	if (!ring->status_page.page_addr ||
-	    list_empty(&ring->request_list))
+	if (list_empty(&ring->request_list))
 		return;
 
-	WARN_ON(i915_verify_lists(dev));
+	WARN_ON(i915_verify_lists(ring->dev));
 
 	seqno = ring->get_seqno(ring);
 
@@ -1875,7 +1922,7 @@
 		if (!i915_seqno_passed(seqno, request->seqno))
 			break;
 
-		trace_i915_gem_request_retire(dev, request->seqno);
+		trace_i915_gem_request_retire(ring, request->seqno);
 
 		list_del(&request->list);
 		i915_gem_request_remove_from_client(request);
@@ -1901,13 +1948,13 @@
 			i915_gem_object_move_to_inactive(obj);
 	}
 
-	if (unlikely (dev_priv->trace_irq_seqno &&
-		      i915_seqno_passed(dev_priv->trace_irq_seqno, seqno))) {
+	if (unlikely(ring->trace_irq_seqno &&
+		     i915_seqno_passed(seqno, ring->trace_irq_seqno))) {
 		ring->irq_put(ring);
-		dev_priv->trace_irq_seqno = 0;
+		ring->trace_irq_seqno = 0;
 	}
 
-	WARN_ON(i915_verify_lists(dev));
+	WARN_ON(i915_verify_lists(ring->dev));
 }
 
 void
@@ -1931,7 +1978,7 @@
 	}
 
 	for (i = 0; i < I915_NUM_RINGS; i++)
-		i915_gem_retire_requests_ring(dev, &dev_priv->ring[i]);
+		i915_gem_retire_requests_ring(&dev_priv->ring[i]);
 }
 
 static void
@@ -1965,11 +2012,11 @@
 			struct drm_i915_gem_request *request;
 			int ret;
 
-			ret = i915_gem_flush_ring(dev, ring, 0,
-						  I915_GEM_GPU_DOMAINS);
+			ret = i915_gem_flush_ring(ring,
+						  0, I915_GEM_GPU_DOMAINS);
 			request = kzalloc(sizeof(*request), GFP_KERNEL);
 			if (ret || request == NULL ||
-			    i915_add_request(dev, NULL, request, ring))
+			    i915_add_request(ring, NULL, request))
 			    kfree(request);
 		}
 
@@ -1982,18 +2029,32 @@
 	mutex_unlock(&dev->struct_mutex);
 }
 
+/**
+ * Waits for a sequence number to be signaled, and cleans up the
+ * request and object lists appropriately for that event.
+ */
 int
-i915_do_wait_request(struct drm_device *dev, uint32_t seqno,
-		     bool interruptible, struct intel_ring_buffer *ring)
+i915_wait_request(struct intel_ring_buffer *ring,
+		  uint32_t seqno)
 {
-	drm_i915_private_t *dev_priv = dev->dev_private;
+	drm_i915_private_t *dev_priv = ring->dev->dev_private;
 	u32 ier;
 	int ret = 0;
 
 	BUG_ON(seqno == 0);
 
-	if (atomic_read(&dev_priv->mm.wedged))
-		return -EAGAIN;
+	if (atomic_read(&dev_priv->mm.wedged)) {
+		struct completion *x = &dev_priv->error_completion;
+		bool recovery_complete;
+		unsigned long flags;
+
+		/* Give the error handler a chance to run. */
+		spin_lock_irqsave(&x->wait.lock, flags);
+		recovery_complete = x->done > 0;
+		spin_unlock_irqrestore(&x->wait.lock, flags);
+
+		return recovery_complete ? -EIO : -EAGAIN;
+	}
 
 	if (seqno == ring->outstanding_lazy_request) {
 		struct drm_i915_gem_request *request;
@@ -2002,7 +2063,7 @@
 		if (request == NULL)
 			return -ENOMEM;
 
-		ret = i915_add_request(dev, NULL, request, ring);
+		ret = i915_add_request(ring, NULL, request);
 		if (ret) {
 			kfree(request);
 			return ret;
@@ -2012,22 +2073,22 @@
 	}
 
 	if (!i915_seqno_passed(ring->get_seqno(ring), seqno)) {
-		if (HAS_PCH_SPLIT(dev))
+		if (HAS_PCH_SPLIT(ring->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");
-			i915_driver_irq_preinstall(dev);
-			i915_driver_irq_postinstall(dev);
+			i915_driver_irq_preinstall(ring->dev);
+			i915_driver_irq_postinstall(ring->dev);
 		}
 
-		trace_i915_gem_request_wait_begin(dev, seqno);
+		trace_i915_gem_request_wait_begin(ring, seqno);
 
 		ring->waiting_seqno = seqno;
 		if (ring->irq_get(ring)) {
-			if (interruptible)
+			if (dev_priv->mm.interruptible)
 				ret = wait_event_interruptible(ring->irq_queue,
 							       i915_seqno_passed(ring->get_seqno(ring), seqno)
 							       || atomic_read(&dev_priv->mm.wedged));
@@ -2043,7 +2104,7 @@
 			ret = -EBUSY;
 		ring->waiting_seqno = 0;
 
-		trace_i915_gem_request_wait_end(dev, seqno);
+		trace_i915_gem_request_wait_end(ring, seqno);
 	}
 	if (atomic_read(&dev_priv->mm.wedged))
 		ret = -EAGAIN;
@@ -2059,31 +2120,18 @@
 	 * a separate wait queue to handle that.
 	 */
 	if (ret == 0)
-		i915_gem_retire_requests_ring(dev, ring);
+		i915_gem_retire_requests_ring(ring);
 
 	return ret;
 }
 
 /**
- * Waits for a sequence number to be signaled, and cleans up the
- * request and object lists appropriately for that event.
- */
-static int
-i915_wait_request(struct drm_device *dev, uint32_t seqno,
-		  struct intel_ring_buffer *ring)
-{
-	return i915_do_wait_request(dev, seqno, 1, ring);
-}
-
-/**
  * Ensures that all rendering to the object has completed and the object is
  * safe to unbind from the GTT or access from the CPU.
  */
 int
-i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj,
-			       bool interruptible)
+i915_gem_object_wait_rendering(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
 	int ret;
 
 	/* This function only exists to support waiting for existing rendering,
@@ -2095,10 +2143,7 @@
 	 * it.
 	 */
 	if (obj->active) {
-		ret = i915_do_wait_request(dev,
-					   obj->last_rendering_seqno,
-					   interruptible,
-					   obj->ring);
+		ret = i915_wait_request(obj->ring, obj->last_rendering_seqno);
 		if (ret)
 			return ret;
 	}
@@ -2148,6 +2193,8 @@
 	if (ret == -ERESTARTSYS)
 		return ret;
 
+	trace_i915_gem_object_unbind(obj);
+
 	i915_gem_gtt_unbind_object(obj);
 	i915_gem_object_put_pages_gtt(obj);
 
@@ -2163,29 +2210,32 @@
 	if (i915_gem_object_is_purgeable(obj))
 		i915_gem_object_truncate(obj);
 
-	trace_i915_gem_object_unbind(obj);
-
 	return ret;
 }
 
 int
-i915_gem_flush_ring(struct drm_device *dev,
-		    struct intel_ring_buffer *ring,
+i915_gem_flush_ring(struct intel_ring_buffer *ring,
 		    uint32_t invalidate_domains,
 		    uint32_t flush_domains)
 {
 	int ret;
 
+	if (((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) == 0)
+		return 0;
+
+	trace_i915_gem_ring_flush(ring, invalidate_domains, flush_domains);
+
 	ret = ring->flush(ring, invalidate_domains, flush_domains);
 	if (ret)
 		return ret;
 
-	i915_gem_process_flushing_list(dev, flush_domains, ring);
+	if (flush_domains & I915_GEM_GPU_DOMAINS)
+		i915_gem_process_flushing_list(ring, flush_domains);
+
 	return 0;
 }
 
-static int i915_ring_idle(struct drm_device *dev,
-			  struct intel_ring_buffer *ring)
+static int i915_ring_idle(struct intel_ring_buffer *ring)
 {
 	int ret;
 
@@ -2193,15 +2243,13 @@
 		return 0;
 
 	if (!list_empty(&ring->gpu_write_list)) {
-		ret = i915_gem_flush_ring(dev, ring,
+		ret = i915_gem_flush_ring(ring,
 				    I915_GEM_GPU_DOMAINS, I915_GEM_GPU_DOMAINS);
 		if (ret)
 			return ret;
 	}
 
-	return i915_wait_request(dev,
-				 i915_gem_next_request_seqno(dev, ring),
-				 ring);
+	return i915_wait_request(ring, i915_gem_next_request_seqno(ring));
 }
 
 int
@@ -2218,7 +2266,7 @@
 
 	/* Flush everything onto the inactive list. */
 	for (i = 0; i < I915_NUM_RINGS; i++) {
-		ret = i915_ring_idle(dev, &dev_priv->ring[i]);
+		ret = i915_ring_idle(&dev_priv->ring[i]);
 		if (ret)
 			return ret;
 	}
@@ -2402,15 +2450,13 @@
 
 static int
 i915_gem_object_flush_fence(struct drm_i915_gem_object *obj,
-			    struct intel_ring_buffer *pipelined,
-			    bool interruptible)
+			    struct intel_ring_buffer *pipelined)
 {
 	int ret;
 
 	if (obj->fenced_gpu_access) {
 		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-			ret = i915_gem_flush_ring(obj->base.dev,
-						  obj->last_fenced_ring,
+			ret = i915_gem_flush_ring(obj->last_fenced_ring,
 						  0, obj->base.write_domain);
 			if (ret)
 				return ret;
@@ -2422,10 +2468,8 @@
 	if (obj->last_fenced_seqno && pipelined != obj->last_fenced_ring) {
 		if (!ring_passed_seqno(obj->last_fenced_ring,
 				       obj->last_fenced_seqno)) {
-			ret = i915_do_wait_request(obj->base.dev,
-						   obj->last_fenced_seqno,
-						   interruptible,
-						   obj->last_fenced_ring);
+			ret = i915_wait_request(obj->last_fenced_ring,
+						obj->last_fenced_seqno);
 			if (ret)
 				return ret;
 		}
@@ -2451,7 +2495,7 @@
 	if (obj->tiling_mode)
 		i915_gem_release_mmap(obj);
 
-	ret = i915_gem_object_flush_fence(obj, NULL, true);
+	ret = i915_gem_object_flush_fence(obj, NULL);
 	if (ret)
 		return ret;
 
@@ -2528,8 +2572,7 @@
  */
 int
 i915_gem_object_get_fence(struct drm_i915_gem_object *obj,
-			  struct intel_ring_buffer *pipelined,
-			  bool interruptible)
+			  struct intel_ring_buffer *pipelined)
 {
 	struct drm_device *dev = obj->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2544,17 +2587,30 @@
 		reg = &dev_priv->fence_regs[obj->fence_reg];
 		list_move_tail(&reg->lru_list, &dev_priv->mm.fence_list);
 
-		if (!obj->fenced_gpu_access && !obj->last_fenced_seqno)
-			pipelined = NULL;
+		if (obj->tiling_changed) {
+			ret = i915_gem_object_flush_fence(obj, pipelined);
+			if (ret)
+				return ret;
+
+			if (!obj->fenced_gpu_access && !obj->last_fenced_seqno)
+				pipelined = NULL;
+
+			if (pipelined) {
+				reg->setup_seqno =
+					i915_gem_next_request_seqno(pipelined);
+				obj->last_fenced_seqno = reg->setup_seqno;
+				obj->last_fenced_ring = pipelined;
+			}
+
+			goto update;
+		}
 
 		if (!pipelined) {
 			if (reg->setup_seqno) {
 				if (!ring_passed_seqno(obj->last_fenced_ring,
 						       reg->setup_seqno)) {
-					ret = i915_do_wait_request(obj->base.dev,
-								   reg->setup_seqno,
-								   interruptible,
-								   obj->last_fenced_ring);
+					ret = i915_wait_request(obj->last_fenced_ring,
+								reg->setup_seqno);
 					if (ret)
 						return ret;
 				}
@@ -2563,36 +2619,9 @@
 			}
 		} else if (obj->last_fenced_ring &&
 			   obj->last_fenced_ring != pipelined) {
-			ret = i915_gem_object_flush_fence(obj,
-							  pipelined,
-							  interruptible);
+			ret = i915_gem_object_flush_fence(obj, pipelined);
 			if (ret)
 				return ret;
-		} else if (obj->tiling_changed) {
-			if (obj->fenced_gpu_access) {
-				if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-					ret = i915_gem_flush_ring(obj->base.dev, obj->ring,
-								  0, obj->base.write_domain);
-					if (ret)
-						return ret;
-				}
-
-				obj->fenced_gpu_access = false;
-			}
-		}
-
-		if (!obj->fenced_gpu_access && !obj->last_fenced_seqno)
-			pipelined = NULL;
-		BUG_ON(!pipelined && reg->setup_seqno);
-
-		if (obj->tiling_changed) {
-			if (pipelined) {
-				reg->setup_seqno =
-					i915_gem_next_request_seqno(dev, pipelined);
-				obj->last_fenced_seqno = reg->setup_seqno;
-				obj->last_fenced_ring = pipelined;
-			}
-			goto update;
 		}
 
 		return 0;
@@ -2602,7 +2631,7 @@
 	if (reg == NULL)
 		return -ENOSPC;
 
-	ret = i915_gem_object_flush_fence(obj, pipelined, interruptible);
+	ret = i915_gem_object_flush_fence(obj, pipelined);
 	if (ret)
 		return ret;
 
@@ -2614,9 +2643,7 @@
 		if (old->tiling_mode)
 			i915_gem_release_mmap(old);
 
-		ret = i915_gem_object_flush_fence(old,
-						  pipelined,
-						  interruptible);
+		ret = i915_gem_object_flush_fence(old, pipelined);
 		if (ret) {
 			drm_gem_object_unreference(&old->base);
 			return ret;
@@ -2628,7 +2655,7 @@
 		old->fence_reg = I915_FENCE_REG_NONE;
 		old->last_fenced_ring = pipelined;
 		old->last_fenced_seqno =
-			pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0;
+			pipelined ? i915_gem_next_request_seqno(pipelined) : 0;
 
 		drm_gem_object_unreference(&old->base);
 	} else if (obj->last_fenced_seqno == 0)
@@ -2640,7 +2667,7 @@
 	obj->last_fenced_ring = pipelined;
 
 	reg->setup_seqno =
-		pipelined ? i915_gem_next_request_seqno(dev, pipelined) : 0;
+		pipelined ? i915_gem_next_request_seqno(pipelined) : 0;
 	obj->last_fenced_seqno = reg->setup_seqno;
 
 update:
@@ -2837,7 +2864,7 @@
 
 	obj->map_and_fenceable = mappable && fenceable;
 
-	trace_i915_gem_object_bind(obj, obj->gtt_offset, map_and_fenceable);
+	trace_i915_gem_object_bind(obj, map_and_fenceable);
 	return 0;
 }
 
@@ -2860,13 +2887,11 @@
 static int
 i915_gem_object_flush_gpu_write_domain(struct drm_i915_gem_object *obj)
 {
-	struct drm_device *dev = obj->base.dev;
-
 	if ((obj->base.write_domain & I915_GEM_GPU_DOMAINS) == 0)
 		return 0;
 
 	/* Queue the GPU write cache flushing we need. */
-	return i915_gem_flush_ring(dev, obj->ring, 0, obj->base.write_domain);
+	return i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
 }
 
 /** Flushes the GTT write domain for the object if it's dirty. */
@@ -2933,12 +2958,15 @@
 	if (obj->gtt_space == NULL)
 		return -EINVAL;
 
+	if (obj->base.write_domain == I915_GEM_DOMAIN_GTT)
+		return 0;
+
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
 	if (ret)
 		return ret;
 
 	if (obj->pending_gpu_write || write) {
-		ret = i915_gem_object_wait_rendering(obj, true);
+		ret = i915_gem_object_wait_rendering(obj);
 		if (ret)
 			return ret;
 	}
@@ -2988,7 +3016,7 @@
 
 	/* Currently, we are always called from an non-interruptible context. */
 	if (pipelined != obj->ring) {
-		ret = i915_gem_object_wait_rendering(obj, false);
+		ret = i915_gem_object_wait_rendering(obj);
 		if (ret)
 			return ret;
 	}
@@ -3006,8 +3034,7 @@
 }
 
 int
-i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj,
-			  bool interruptible)
+i915_gem_object_flush_gpu(struct drm_i915_gem_object *obj)
 {
 	int ret;
 
@@ -3015,13 +3042,12 @@
 		return 0;
 
 	if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-		ret = i915_gem_flush_ring(obj->base.dev, obj->ring,
-					  0, obj->base.write_domain);
+		ret = i915_gem_flush_ring(obj->ring, 0, obj->base.write_domain);
 		if (ret)
 			return ret;
 	}
 
-	return i915_gem_object_wait_rendering(obj, interruptible);
+	return i915_gem_object_wait_rendering(obj);
 }
 
 /**
@@ -3036,11 +3062,14 @@
 	uint32_t old_write_domain, old_read_domains;
 	int ret;
 
+	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU)
+		return 0;
+
 	ret = i915_gem_object_flush_gpu_write_domain(obj);
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_wait_rendering(obj, true);
+	ret = i915_gem_object_wait_rendering(obj);
 	if (ret)
 		return ret;
 
@@ -3138,7 +3167,7 @@
 	if (ret)
 		return ret;
 
-	ret = i915_gem_object_wait_rendering(obj, true);
+	ret = i915_gem_object_wait_rendering(obj);
 	if (ret)
 		return ret;
 
@@ -3209,6 +3238,9 @@
 	u32 seqno = 0;
 	int ret;
 
+	if (atomic_read(&dev_priv->mm.wedged))
+		return -EIO;
+
 	spin_lock(&file_priv->mm.lock);
 	list_for_each_entry(request, &file_priv->mm.request_list, client_list) {
 		if (time_after_eq(request->emitted_jiffies, recent_enough))
@@ -3324,7 +3356,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3375,7 +3407,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3412,7 +3444,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3430,7 +3462,7 @@
 		 * flush earlier is beneficial.
 		 */
 		if (obj->base.write_domain & I915_GEM_GPU_DOMAINS) {
-			ret = i915_gem_flush_ring(dev, obj->ring,
+			ret = i915_gem_flush_ring(obj->ring,
 						  0, obj->base.write_domain);
 		} else if (obj->ring->outstanding_lazy_request ==
 			   obj->last_rendering_seqno) {
@@ -3441,9 +3473,7 @@
 			 */
 			request = kzalloc(sizeof(*request), GFP_KERNEL);
 			if (request)
-				ret = i915_add_request(dev,
-						       NULL, request,
-						       obj->ring);
+				ret = i915_add_request(obj->ring, NULL,request);
 			else
 				ret = -ENOMEM;
 		}
@@ -3453,7 +3483,7 @@
 		 * are actually unmasked, and our working set ends up being
 		 * larger than required.
 		 */
-		i915_gem_retire_requests_ring(dev, obj->ring);
+		i915_gem_retire_requests_ring(obj->ring);
 
 		args->busy = obj->active;
 	}
@@ -3492,7 +3522,7 @@
 		return ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file_priv, args->handle));
-	if (obj == NULL) {
+	if (&obj->base == NULL) {
 		ret = -ENOENT;
 		goto unlock;
 	}
@@ -3574,6 +3604,8 @@
 		return;
 	}
 
+	trace_i915_gem_object_destroy(obj);
+
 	if (obj->base.map_list.map)
 		i915_gem_free_mmap_offset(obj);
 
@@ -3590,8 +3622,6 @@
 	struct drm_i915_gem_object *obj = to_intel_bo(gem_obj);
 	struct drm_device *dev = obj->base.dev;
 
-	trace_i915_gem_object_destroy(obj);
-
 	while (obj->pin_count > 0)
 		i915_gem_object_unpin(obj);
 
@@ -3837,6 +3867,8 @@
 	i915_gem_detect_bit_6_swizzle(dev);
 	init_waitqueue_head(&dev_priv->pending_flip_queue);
 
+	dev_priv->mm.interruptible = true;
+
 	dev_priv->mm.inactive_shrinker.shrink = i915_gem_inactive_shrink;
 	dev_priv->mm.inactive_shrinker.seeks = DEFAULT_SEEKS;
 	register_shrinker(&dev_priv->mm.inactive_shrinker);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_debug.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_debug.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,51 +134,6 @@
 }
 #endif /* WATCH_INACTIVE */
 
-
-#if WATCH_EXEC | WATCH_PWRITE
-static void
-i915_gem_dump_page(struct page *page, uint32_t start, uint32_t end,
-		   uint32_t bias, uint32_t mark)
-{
-	uint32_t *mem = kmap_atomic(page, KM_USER0);
-	int i;
-	for (i = start; i < end; i += 4)
-		DRM_INFO("%08x: %08x%s\n",
-			  (int) (bias + i), mem[i / 4],
-			  (bias + i == mark) ? " ********" : "");
-	kunmap_atomic(mem, KM_USER0);
-	/* give syslog time to catch up */
-	msleep(1);
-}
-
-void
-i915_gem_dump_object(struct drm_i915_gem_object *obj, int len,
-		     const char *where, uint32_t mark)
-{
-	int page;
-
-	DRM_INFO("%s: object at offset %08x\n", where, obj->gtt_offset);
-	for (page = 0; page < (len + PAGE_SIZE-1) / PAGE_SIZE; page++) {
-		int page_len, chunk, chunk_len;
-
-		page_len = len - page * PAGE_SIZE;
-		if (page_len > PAGE_SIZE)
-			page_len = PAGE_SIZE;
-
-		for (chunk = 0; chunk < page_len; chunk += 128) {
-			chunk_len = page_len - chunk;
-			if (chunk_len > 128)
-				chunk_len = 128;
-			i915_gem_dump_page(obj->pages[page],
-					   chunk, chunk + chunk_len,
-					   obj->gtt_offset +
-					   page * PAGE_SIZE,
-					   mark);
-		}
-	}
-}
-#endif
-
 #if WATCH_COHERENCY
 void
 i915_gem_object_check_coherency(struct drm_i915_gem_object *obj, int handle)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_evict.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_evict.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_evict.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_evict.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include "drm.h"
 #include "i915_drv.h"
 #include "i915_drm.h"
+#include "i915_trace.h"
 
 static bool
 mark_free(struct drm_i915_gem_object *obj, struct list_head *unwind)
@@ -63,6 +64,8 @@
 			return 0;
 	}
 
+	trace_i915_gem_evict(dev, min_size, alignment, mappable);
+
 	/*
 	 * The goal is to evict objects and amalgamate space in LRU order.
 	 * The oldest idle objects reside on the inactive list, which is in
@@ -189,6 +192,8 @@
 	if (lists_empty)
 		return -ENOSPC;
 
+	trace_i915_gem_evict_everything(dev, purgeable_only);
+
 	/* Flush everything (on to the inactive lists) and evict */
 	ret = i915_gpu_idle(dev);
 	if (ret)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_execbuffer.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,6 +37,7 @@
 	uint32_t invalidate_domains;
 	uint32_t flush_domains;
 	uint32_t flush_rings;
+	uint32_t flips;
 };
 
 /*
@@ -190,6 +191,9 @@
 	if ((flush_domains | invalidate_domains) & I915_GEM_DOMAIN_GTT)
 		i915_gem_release_mmap(obj);
 
+	if (obj->base.pending_write_domain)
+		cd->flips |= atomic_read(&obj->pending_flip);
+
 	/* The actual obj->write_domain will be updated with
 	 * pending_write_domain after we emit the accumulated flush for all
 	 * of our domain changes in execbuffers (which clears objects'
@@ -282,21 +286,6 @@
 
 	target_offset = to_intel_bo(target_obj)->gtt_offset;
 
-#if WATCH_RELOC
-	DRM_INFO("%s: obj %p offset %08x target %d "
-		 "read %08x write %08x gtt %08x "
-		 "presumed %08x delta %08x\n",
-		 __func__,
-		 obj,
-		 (int) reloc->offset,
-		 (int) reloc->target_handle,
-		 (int) reloc->read_domains,
-		 (int) reloc->write_domain,
-		 (int) target_offset,
-		 (int) reloc->presumed_offset,
-		 reloc->delta);
-#endif
-
 	/* The target buffer should have appeared before us in the
 	 * exec_object list, so it should have a GTT space bound by now.
 	 */
@@ -365,16 +354,6 @@
 		return ret;
 	}
 
-	/* and points to somewhere within the target object. */
-	if (unlikely(reloc->delta >= target_obj->size)) {
-		DRM_ERROR("Relocation beyond target object bounds: "
-			  "obj %p target %d delta %d size %d.\n",
-			  obj, reloc->target_handle,
-			  (int) reloc->delta,
-			  (int) target_obj->size);
-		return ret;
-	}
-
 	reloc->delta += target_offset;
 	if (obj->base.write_domain == I915_GEM_DOMAIN_CPU) {
 		uint32_t page_offset = reloc->offset & ~PAGE_MASK;
@@ -388,6 +367,10 @@
 		uint32_t __iomem *reloc_entry;
 		void __iomem *reloc_page;
 
+		/* We can't wait for rendering with pagefaults disabled */
+		if (obj->active && in_atomic())
+			return -EFAULT;
+
 		ret = i915_gem_object_set_to_gtt_domain(obj, 1);
 		if (ret)
 			return ret;
@@ -461,15 +444,24 @@
 			     struct list_head *objects)
 {
 	struct drm_i915_gem_object *obj;
-	int ret;
+	int ret = 0;
 
+	/* This is the fast path and we cannot handle a pagefault whilst
+	 * holding the struct mutex lest the user pass in the relocations
+	 * contained within a mmaped bo. For in such a case we, the page
+	 * fault handler would call i915_gem_fault() and we would try to
+	 * acquire the struct mutex again. Obviously this is bad and so
+	 * lockdep complains vehemently.
+	 */
+	pagefault_disable();
 	list_for_each_entry(obj, objects, exec_list) {
 		ret = i915_gem_execbuffer_relocate_object(obj, eb);
 		if (ret)
-			return ret;
+			break;
 	}
+	pagefault_enable();
 
-	return 0;
+	return ret;
 }
 
 static int
@@ -575,7 +567,7 @@
 
 			if (has_fenced_gpu_access) {
 				if (need_fence) {
-					ret = i915_gem_object_get_fence(obj, ring, 1);
+					ret = i915_gem_object_get_fence(obj, ring);
 					if (ret)
 						break;
 				} else if (entry->flags & EXEC_OBJECT_NEEDS_FENCE &&
@@ -690,11 +682,9 @@
 	/* reacquire the objects */
 	eb_reset(eb);
 	for (i = 0; i < count; i++) {
-		struct drm_i915_gem_object *obj;
-
 		obj = to_intel_bo(drm_gem_object_lookup(dev, file,
 							exec[i].handle));
-		if (obj == NULL) {
+		if (&obj->base == NULL) {
 			DRM_ERROR("Invalid object handle %d at index %d\n",
 				   exec[i].handle, i);
 			ret = -ENOENT;
@@ -749,8 +739,7 @@
 	if ((flush_domains | invalidate_domains) & I915_GEM_GPU_DOMAINS) {
 		for (i = 0; i < I915_NUM_RINGS; i++)
 			if (flush_rings & (1 << i)) {
-				ret = i915_gem_flush_ring(dev,
-							  &dev_priv->ring[i],
+				ret = i915_gem_flush_ring(&dev_priv->ring[i],
 							  invalidate_domains,
 							  flush_domains);
 				if (ret)
@@ -774,7 +763,7 @@
 
 	/* XXX gpu semaphores are implicated in various hard hangs on SNB */
 	if (INTEL_INFO(obj->base.dev)->gen < 6 || !i915_semaphores)
-		return i915_gem_object_wait_rendering(obj, true);
+		return i915_gem_object_wait_rendering(obj);
 
 	idx = intel_ring_sync_index(from, to);
 
@@ -789,7 +778,7 @@
 		if (request == NULL)
 			return -ENOMEM;
 
-		ret = i915_add_request(obj->base.dev, NULL, request, from);
+		ret = i915_add_request(from, NULL, request);
 		if (ret) {
 			kfree(request);
 			return ret;
@@ -803,6 +792,39 @@
 }
 
 static int
+i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring, u32 flips)
+{
+	u32 plane, flip_mask;
+	int ret;
+
+	/* Check for any pending flips. As we only maintain a flip queue depth
+	 * of 1, we can simply insert a WAIT for the next display flip prior
+	 * to executing the batch and avoid stalling the CPU.
+	 */
+
+	for (plane = 0; flips >> plane; plane++) {
+		if (((flips >> plane) & 1) == 0)
+			continue;
+
+		if (plane)
+			flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
+		else
+			flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
+
+		ret = intel_ring_begin(ring, 2);
+		if (ret)
+			return ret;
+
+		intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
+		intel_ring_emit(ring, MI_NOOP);
+		intel_ring_advance(ring);
+	}
+
+	return 0;
+}
+
+
+static int
 i915_gem_execbuffer_move_to_gpu(struct intel_ring_buffer *ring,
 				struct list_head *objects)
 {
@@ -810,19 +832,11 @@
 	struct change_domains cd;
 	int ret;
 
-	cd.invalidate_domains = 0;
-	cd.flush_domains = 0;
-	cd.flush_rings = 0;
+	memset(&cd, 0, sizeof(cd));
 	list_for_each_entry(obj, objects, exec_list)
 		i915_gem_object_set_to_gpu_domain(obj, ring, &cd);
 
 	if (cd.invalidate_domains | cd.flush_domains) {
-#if WATCH_EXEC
-		DRM_INFO("%s: invalidate_domains %08x flush_domains %08x\n",
-			  __func__,
-			 cd.invalidate_domains,
-			 cd.flush_domains);
-#endif
 		ret = i915_gem_execbuffer_flush(ring->dev,
 						cd.invalidate_domains,
 						cd.flush_domains,
@@ -831,6 +845,12 @@
 			return ret;
 	}
 
+	if (cd.flips) {
+		ret = i915_gem_execbuffer_wait_for_flips(ring, cd.flips);
+		if (ret)
+			return ret;
+	}
+
 	list_for_each_entry(obj, objects, exec_list) {
 		ret = i915_gem_execbuffer_sync_rings(obj, ring);
 		if (ret)
@@ -877,47 +897,6 @@
 	return 0;
 }
 
-static int
-i915_gem_execbuffer_wait_for_flips(struct intel_ring_buffer *ring,
-				   struct list_head *objects)
-{
-	struct drm_i915_gem_object *obj;
-	int flips;
-
-	/* Check for any pending flips. As we only maintain a flip queue depth
-	 * of 1, we can simply insert a WAIT for the next display flip prior
-	 * to executing the batch and avoid stalling the CPU.
-	 */
-	flips = 0;
-	list_for_each_entry(obj, objects, exec_list) {
-		if (obj->base.write_domain)
-			flips |= atomic_read(&obj->pending_flip);
-	}
-	if (flips) {
-		int plane, flip_mask, ret;
-
-		for (plane = 0; flips >> plane; plane++) {
-			if (((flips >> plane) & 1) == 0)
-				continue;
-
-			if (plane)
-				flip_mask = MI_WAIT_FOR_PLANE_B_FLIP;
-			else
-				flip_mask = MI_WAIT_FOR_PLANE_A_FLIP;
-
-			ret = intel_ring_begin(ring, 2);
-			if (ret)
-				return ret;
-
-			intel_ring_emit(ring, MI_WAIT_FOR_EVENT | flip_mask);
-			intel_ring_emit(ring, MI_NOOP);
-			intel_ring_advance(ring);
-		}
-	}
-
-	return 0;
-}
-
 static void
 i915_gem_execbuffer_move_to_active(struct list_head *objects,
 				   struct intel_ring_buffer *ring,
@@ -926,6 +905,10 @@
 	struct drm_i915_gem_object *obj;
 
 	list_for_each_entry(obj, objects, exec_list) {
+		  u32 old_read = obj->base.read_domains;
+		  u32 old_write = obj->base.write_domain;
+
+
 		obj->base.read_domains = obj->base.pending_read_domains;
 		obj->base.write_domain = obj->base.pending_write_domain;
 		obj->fenced_gpu_access = obj->pending_fenced_gpu_access;
@@ -939,9 +922,7 @@
 			intel_mark_busy(ring->dev, obj);
 		}
 
-		trace_i915_gem_object_change_domain(obj,
-						    obj->base.read_domains,
-						    obj->base.write_domain);
+		trace_i915_gem_object_change_domain(obj, old_read, old_write);
 	}
 }
 
@@ -963,14 +944,14 @@
 	if (INTEL_INFO(dev)->gen >= 4)
 		invalidate |= I915_GEM_DOMAIN_SAMPLER;
 	if (ring->flush(ring, invalidate, 0)) {
-		i915_gem_next_request_seqno(dev, ring);
+		i915_gem_next_request_seqno(ring);
 		return;
 	}
 
 	/* Add a breadcrumb for the completion of the batch buffer */
 	request = kzalloc(sizeof(*request), GFP_KERNEL);
-	if (request == NULL || i915_add_request(dev, file, request, ring)) {
-		i915_gem_next_request_seqno(dev, ring);
+	if (request == NULL || i915_add_request(ring, file, request)) {
+		i915_gem_next_request_seqno(ring);
 		kfree(request);
 	}
 }
@@ -1000,10 +981,6 @@
 	if (ret)
 		return ret;
 
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
 	switch (args->flags & I915_EXEC_RING_MASK) {
 	case I915_EXEC_DEFAULT:
 	case I915_EXEC_RENDER:
@@ -1113,7 +1090,7 @@
 
 		obj = to_intel_bo(drm_gem_object_lookup(dev, file,
 							exec[i].handle));
-		if (obj == NULL) {
+		if (&obj->base == NULL) {
 			DRM_ERROR("Invalid object handle %d at index %d\n",
 				   exec[i].handle, i);
 			/* prevent error path from reading uninitialized data */
@@ -1170,11 +1147,7 @@
 	if (ret)
 		goto err;
 
-	ret = i915_gem_execbuffer_wait_for_flips(ring, &objects);
-	if (ret)
-		goto err;
-
-	seqno = i915_gem_next_request_seqno(dev, ring);
+	seqno = i915_gem_next_request_seqno(ring);
 	for (i = 0; i < ARRAY_SIZE(ring->sync_seqno); i++) {
 		if (seqno < ring->sync_seqno[i]) {
 			/* The GPU can not handle its semaphore value wrapping,
@@ -1189,6 +1162,8 @@
 		}
 	}
 
+	trace_i915_gem_ring_dispatch(ring, seqno);
+
 	exec_start = batch_obj->gtt_offset + args->batch_start_offset;
 	exec_len = args->batch_len;
 	if (cliprects) {
@@ -1245,11 +1220,6 @@
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 	int ret, i;
 
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-
 	if (args->buffer_count < 1) {
 		DRM_ERROR("execbuf with %d buffers\n", args->buffer_count);
 		return -EINVAL;
@@ -1330,17 +1300,16 @@
 	struct drm_i915_gem_exec_object2 *exec2_list = NULL;
 	int ret;
 
-#if WATCH_EXEC
-	DRM_INFO("buffers_ptr %d buffer_count %d len %08x\n",
-		  (int) args->buffers_ptr, args->buffer_count, args->batch_len);
-#endif
-
 	if (args->buffer_count < 1) {
 		DRM_ERROR("execbuf2 with %d buffers\n", args->buffer_count);
 		return -EINVAL;
 	}
 
-	exec2_list = drm_malloc_ab(sizeof(*exec2_list), args->buffer_count);
+	exec2_list = kmalloc(sizeof(*exec2_list)*args->buffer_count,
+			     GFP_KERNEL | __GFP_NOWARN | __GFP_NORETRY);
+	if (exec2_list == NULL)
+		exec2_list = drm_malloc_ab(sizeof(*exec2_list),
+					   args->buffer_count);
 	if (exec2_list == NULL) {
 		DRM_ERROR("Failed to allocate exec list for %d buffers\n",
 			  args->buffer_count);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_gem_tiling.c	2011-05-19 00:06:34.000000000 -0400
@@ -284,14 +284,10 @@
 	struct drm_i915_gem_set_tiling *args = data;
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct drm_i915_gem_object *obj;
-	int ret;
-
-	ret = i915_gem_check_is_wedged(dev);
-	if (ret)
-		return ret;
+	int ret = 0;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL)
+	if (&obj->base == NULL)
 		return -ENOENT;
 
 	if (!i915_tiling_ok(dev,
@@ -384,7 +380,7 @@
 	struct drm_i915_gem_object *obj;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, args->handle));
-	if (obj == NULL)
+	if (&obj->base == NULL)
 		return -ENOENT;
 
 	mutex_lock(&dev->struct_mutex);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_irq.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_irq.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,21 +85,11 @@
 	}
 }
 
-static inline u32
-i915_pipestat(int pipe)
-{
-	if (pipe == 0)
-		return PIPEASTAT;
-	if (pipe == 1)
-		return PIPEBSTAT;
-	BUG();
-}
-
 void
 i915_enable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 {
 	if ((dev_priv->pipestat[pipe] & mask) != mask) {
-		u32 reg = i915_pipestat(pipe);
+		u32 reg = PIPESTAT(pipe);
 
 		dev_priv->pipestat[pipe] |= mask;
 		/* Enable the interrupt, clear any pending status */
@@ -112,7 +102,7 @@
 i915_disable_pipestat(drm_i915_private_t *dev_priv, int pipe, u32 mask)
 {
 	if ((dev_priv->pipestat[pipe] & mask) != 0) {
-		u32 reg = i915_pipestat(pipe);
+		u32 reg = PIPESTAT(pipe);
 
 		dev_priv->pipestat[pipe] &= ~mask;
 		I915_WRITE(reg, dev_priv->pipestat[pipe]);
@@ -171,12 +161,12 @@
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
-				"pipe %d\n", pipe);
+				"pipe %c\n", pipe_name(pipe));
 		return 0;
 	}
 
-	high_frame = pipe ? PIPEBFRAMEHIGH : PIPEAFRAMEHIGH;
-	low_frame = pipe ? PIPEBFRAMEPIXEL : PIPEAFRAMEPIXEL;
+	high_frame = PIPEFRAME(pipe);
+	low_frame = PIPEFRAMEPIXEL(pipe);
 
 	/*
 	 * High & low register fields aren't synchronized, so make sure
@@ -197,11 +187,11 @@
 u32 gm45_get_vblank_counter(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	int reg = pipe ? PIPEB_FRMCOUNT_GM45 : PIPEA_FRMCOUNT_GM45;
+	int reg = PIPE_FRMCOUNT_GM45(pipe);
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get vblank count for disabled "
-					"pipe %d\n", pipe);
+				 "pipe %c\n", pipe_name(pipe));
 		return 0;
 	}
 
@@ -219,7 +209,7 @@
 
 	if (!i915_pipe_enabled(dev, pipe)) {
 		DRM_DEBUG_DRIVER("trying to get scanoutpos for disabled "
-					"pipe %d\n", pipe);
+				 "pipe %c\n", pipe_name(pipe));
 		return 0;
 	}
 
@@ -367,7 +357,7 @@
 		return;
 
 	seqno = ring->get_seqno(ring);
-	trace_i915_gem_request_complete(dev, seqno);
+	trace_i915_gem_request_complete(ring, seqno);
 
 	ring->irq_seqno = seqno;
 	wake_up_all(&ring->irq_queue);
@@ -419,6 +409,7 @@
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	u32 pch_iir;
+	int pipe;
 
 	pch_iir = I915_READ(SDEIIR);
 
@@ -439,13 +430,11 @@
 	if (pch_iir & SDE_POISON)
 		DRM_ERROR("PCH poison interrupt\n");
 
-	if (pch_iir & SDE_FDI_MASK) {
-		u32 fdia, fdib;
-
-		fdia = I915_READ(FDI_RXA_IIR);
-		fdib = I915_READ(FDI_RXB_IIR);
-		DRM_DEBUG_DRIVER("PCH FDI RX interrupt; FDI RXA IIR: 0x%08x, FDI RXB IIR: 0x%08x\n", fdia, fdib);
-	}
+	if (pch_iir & SDE_FDI_MASK)
+		for_each_pipe(pipe)
+			DRM_DEBUG_DRIVER("  pipe %c FDI IIR: 0x%08x\n",
+					 pipe_name(pipe),
+					 I915_READ(FDI_RX_IIR(pipe)));
 
 	if (pch_iir & (SDE_TRANSB_CRC_DONE | SDE_TRANSA_CRC_DONE))
 		DRM_DEBUG_DRIVER("PCH transcoder CRC done interrupt\n");
@@ -650,9 +639,14 @@
 i915_error_state_free(struct drm_device *dev,
 		      struct drm_i915_error_state *error)
 {
-	i915_error_object_free(error->batchbuffer[0]);
-	i915_error_object_free(error->batchbuffer[1]);
-	i915_error_object_free(error->ringbuffer);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(error->batchbuffer); i++)
+		i915_error_object_free(error->batchbuffer[i]);
+
+	for (i = 0; i < ARRAY_SIZE(error->ringbuffer); i++)
+		i915_error_object_free(error->ringbuffer[i]);
+
 	kfree(error->active_bo);
 	kfree(error->overlay);
 	kfree(error);
@@ -767,7 +761,7 @@
 	struct drm_i915_gem_object *obj;
 	struct drm_i915_error_state *error;
 	unsigned long flags;
-	int i;
+	int i, pipe;
 
 	spin_lock_irqsave(&dev_priv->error_lock, flags);
 	error = dev_priv->first_error;
@@ -775,19 +769,21 @@
 	if (error)
 		return;
 
+	/* Account for pipe specific data like PIPE*STAT */
 	error = kmalloc(sizeof(*error), GFP_ATOMIC);
 	if (!error) {
 		DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
 		return;
 	}
 
-	DRM_DEBUG_DRIVER("generating error event\n");
+	DRM_INFO("capturing error event; look for more information in /debug/dri/%d/i915_error_state\n",
+		 dev->primary->index);
 
 	error->seqno = dev_priv->ring[RCS].get_seqno(&dev_priv->ring[RCS]);
 	error->eir = I915_READ(EIR);
 	error->pgtbl_er = I915_READ(PGTBL_ER);
-	error->pipeastat = I915_READ(PIPEASTAT);
-	error->pipebstat = I915_READ(PIPEBSTAT);
+	for_each_pipe(pipe)
+		error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 	error->instpm = I915_READ(INSTPM);
 	error->error = 0;
 	if (INTEL_INFO(dev)->gen >= 6) {
@@ -826,15 +822,16 @@
 	}
 	i915_gem_record_fences(dev, error);
 
-	/* Record the active batchbuffers */
-	for (i = 0; i < I915_NUM_RINGS; i++)
+	/* Record the active batch and ring buffers */
+	for (i = 0; i < I915_NUM_RINGS; i++) {
 		error->batchbuffer[i] =
 			i915_error_first_batchbuffer(dev_priv,
 						     &dev_priv->ring[i]);
 
-	/* Record the ringbuffer */
-	error->ringbuffer = i915_error_object_create(dev_priv,
-						     dev_priv->ring[RCS].obj);
+		error->ringbuffer[i] =
+			i915_error_object_create(dev_priv,
+						 dev_priv->ring[i].obj);
+	}
 
 	/* Record buffers on the active and pinned lists. */
 	error->active_bo = NULL;
@@ -907,6 +904,7 @@
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 eir = I915_READ(EIR);
+	int pipe;
 
 	if (!eir)
 		return;
@@ -955,14 +953,10 @@
 	}
 
 	if (eir & I915_ERROR_MEMORY_REFRESH) {
-		u32 pipea_stats = I915_READ(PIPEASTAT);
-		u32 pipeb_stats = I915_READ(PIPEBSTAT);
-
-		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);
+		printk(KERN_ERR "memory refresh error:\n");
+		for_each_pipe(pipe)
+			printk(KERN_ERR "pipe %c stat: 0x%08x\n",
+			       pipe_name(pipe), I915_READ(PIPESTAT(pipe)));
 		/* pipestat has already been acked */
 	}
 	if (eir & I915_ERROR_INSTRUCTION) {
@@ -1076,10 +1070,10 @@
 	/* Potential stall - if we see that the flip has happened, assume a missed interrupt */
 	obj = work->pending_flip_obj;
 	if (INTEL_INFO(dev)->gen >= 4) {
-		int dspsurf = intel_crtc->plane == 0 ? DSPASURF : DSPBSURF;
+		int dspsurf = DSPSURF(intel_crtc->plane);
 		stall_detected = I915_READ(dspsurf) == obj->gtt_offset;
 	} else {
-		int dspaddr = intel_crtc->plane == 0 ? DSPAADDR : DSPBADDR;
+		int dspaddr = DSPADDR(intel_crtc->plane);
 		stall_detected = I915_READ(dspaddr) == (obj->gtt_offset +
 							crtc->y * crtc->fb->pitch +
 							crtc->x * crtc->fb->bits_per_pixel/8);
@@ -1099,12 +1093,13 @@
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
 	struct drm_i915_master_private *master_priv;
 	u32 iir, new_iir;
-	u32 pipea_stats, pipeb_stats;
+	u32 pipe_stats[I915_MAX_PIPES];
 	u32 vblank_status;
 	int vblank = 0;
 	unsigned long irqflags;
 	int irq_received;
-	int ret = IRQ_NONE;
+	int ret = IRQ_NONE, pipe;
+	bool blc_event = false;
 
 	atomic_inc(&dev_priv->irq_received);
 
@@ -1127,27 +1122,23 @@
 		 * interrupts (for non-MSI).
 		 */
 		spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
-		pipea_stats = I915_READ(PIPEASTAT);
-		pipeb_stats = I915_READ(PIPEBSTAT);
-
 		if (iir & I915_RENDER_COMMAND_PARSER_ERROR_INTERRUPT)
 			i915_handle_error(dev, false);
 
-		/*
-		 * Clear the PIPE(A|B)STAT regs before the IIR
-		 */
-		if (pipea_stats & 0x8000ffff) {
-			if (pipea_stats &  PIPE_FIFO_UNDERRUN_STATUS)
-				DRM_DEBUG_DRIVER("pipe a underrun\n");
-			I915_WRITE(PIPEASTAT, pipea_stats);
-			irq_received = 1;
-		}
+		for_each_pipe(pipe) {
+			int reg = PIPESTAT(pipe);
+			pipe_stats[pipe] = I915_READ(reg);
 
-		if (pipeb_stats & 0x8000ffff) {
-			if (pipeb_stats &  PIPE_FIFO_UNDERRUN_STATUS)
-				DRM_DEBUG_DRIVER("pipe b underrun\n");
-			I915_WRITE(PIPEBSTAT, pipeb_stats);
-			irq_received = 1;
+			/*
+			 * Clear the PIPE*STAT regs before the IIR
+			 */
+			if (pipe_stats[pipe] & 0x8000ffff) {
+				if (pipe_stats[pipe] & PIPE_FIFO_UNDERRUN_STATUS)
+					DRM_DEBUG_DRIVER("pipe %c underrun\n",
+							 pipe_name(pipe));
+				I915_WRITE(reg, pipe_stats[pipe]);
+				irq_received = 1;
+			}
 		}
 		spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 
@@ -1198,27 +1189,22 @@
 				intel_finish_page_flip_plane(dev, 1);
 		}
 
-		if (pipea_stats & vblank_status &&
-		    drm_handle_vblank(dev, 0)) {
-			vblank++;
-			if (!dev_priv->flip_pending_is_done) {
-				i915_pageflip_stall_check(dev, 0);
-				intel_finish_page_flip(dev, 0);
+		for_each_pipe(pipe) {
+			if (pipe_stats[pipe] & vblank_status &&
+			    drm_handle_vblank(dev, pipe)) {
+				vblank++;
+				if (!dev_priv->flip_pending_is_done) {
+					i915_pageflip_stall_check(dev, pipe);
+					intel_finish_page_flip(dev, pipe);
+				}
 			}
-		}
 
-		if (pipeb_stats & vblank_status &&
-		    drm_handle_vblank(dev, 1)) {
-			vblank++;
-			if (!dev_priv->flip_pending_is_done) {
-				i915_pageflip_stall_check(dev, 1);
-				intel_finish_page_flip(dev, 1);
-			}
+			if (pipe_stats[pipe] & PIPE_LEGACY_BLC_EVENT_STATUS)
+				blc_event = true;
 		}
 
-		if ((pipea_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
-		    (pipeb_stats & PIPE_LEGACY_BLC_EVENT_STATUS) ||
-		    (iir & I915_ASLE_INTERRUPT))
+
+		if (blc_event || (iir & I915_ASLE_INTERRUPT))
 			intel_opregion_asle_intr(dev);
 
 		/* With MSI, interrupts are only generated when iir
@@ -1268,16 +1254,6 @@
 	return dev_priv->counter;
 }
 
-void i915_trace_irq_get(struct drm_device *dev, u32 seqno)
-{
-	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
-	struct intel_ring_buffer *ring = LP_RING(dev_priv);
-
-	if (dev_priv->trace_irq_seqno == 0 &&
-	    ring->irq_get(ring))
-		dev_priv->trace_irq_seqno = seqno;
-}
-
 static int i915_wait_irq(struct drm_device * dev, int irq_nr)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
@@ -1377,7 +1353,12 @@
 	else
 		i915_enable_pipestat(dev_priv, pipe,
 				     PIPE_VBLANK_INTERRUPT_ENABLE);
+
+	/* maintain vblank delivery even in deep C-states */
+	if (dev_priv->info->gen == 3)
+		I915_WRITE(INSTPM, INSTPM_AGPBUSY_DIS << 16);
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
+
 	return 0;
 }
 
@@ -1390,6 +1371,10 @@
 	unsigned long irqflags;
 
 	spin_lock_irqsave(&dev_priv->irq_lock, irqflags);
+	if (dev_priv->info->gen == 3)
+		I915_WRITE(INSTPM,
+			   INSTPM_AGPBUSY_DIS << 16 | INSTPM_AGPBUSY_DIS);
+
 	if (HAS_PCH_SPLIT(dev))
 		ironlake_disable_display_irq(dev_priv, (pipe == 0) ?
 					     DE_PIPEA_VBLANK: DE_PIPEB_VBLANK);
@@ -1400,16 +1385,6 @@
 	spin_unlock_irqrestore(&dev_priv->irq_lock, irqflags);
 }
 
-void i915_enable_interrupt (struct drm_device *dev)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-
-	if (!HAS_PCH_SPLIT(dev))
-		intel_opregion_enable_asle(dev);
-	dev_priv->irq_enabled = 1;
-}
-
-
 /* Set the vblank monitor pipe
  */
 int i915_vblank_pipe_set(struct drm_device *dev, void *data,
@@ -1646,12 +1621,16 @@
 	POSTING_READ(GTIER);
 
 	if (HAS_PCH_CPT(dev)) {
-		hotplug_mask = SDE_CRT_HOTPLUG_CPT | SDE_PORTB_HOTPLUG_CPT  |
-			       SDE_PORTC_HOTPLUG_CPT | SDE_PORTD_HOTPLUG_CPT ;
+		hotplug_mask = (SDE_CRT_HOTPLUG_CPT |
+				SDE_PORTB_HOTPLUG_CPT |
+				SDE_PORTC_HOTPLUG_CPT |
+				SDE_PORTD_HOTPLUG_CPT);
 	} else {
-		hotplug_mask = SDE_CRT_HOTPLUG | SDE_PORTB_HOTPLUG |
-			       SDE_PORTC_HOTPLUG | SDE_PORTD_HOTPLUG;
-		hotplug_mask |= SDE_AUX_MASK;
+		hotplug_mask = (SDE_CRT_HOTPLUG |
+				SDE_PORTB_HOTPLUG |
+				SDE_PORTC_HOTPLUG |
+				SDE_PORTD_HOTPLUG |
+				SDE_AUX_MASK);
 	}
 
 	dev_priv->pch_irq_mask = ~hotplug_mask;
@@ -1674,6 +1653,7 @@
 void i915_driver_irq_preinstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
 
 	atomic_set(&dev_priv->irq_received, 0);
 
@@ -1691,8 +1671,8 @@
 	}
 
 	I915_WRITE(HWSTAM, 0xeffe);
-	I915_WRITE(PIPEASTAT, 0);
-	I915_WRITE(PIPEBSTAT, 0);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 	POSTING_READ(IER);
@@ -1804,6 +1784,7 @@
 void i915_driver_irq_uninstall(struct drm_device * dev)
 {
 	drm_i915_private_t *dev_priv = (drm_i915_private_t *) dev->dev_private;
+	int pipe;
 
 	if (!dev_priv)
 		return;
@@ -1821,12 +1802,13 @@
 	}
 
 	I915_WRITE(HWSTAM, 0xffffffff);
-	I915_WRITE(PIPEASTAT, 0);
-	I915_WRITE(PIPEBSTAT, 0);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe), 0);
 	I915_WRITE(IMR, 0xffffffff);
 	I915_WRITE(IER, 0x0);
 
-	I915_WRITE(PIPEASTAT, I915_READ(PIPEASTAT) & 0x8000ffff);
-	I915_WRITE(PIPEBSTAT, I915_READ(PIPEBSTAT) & 0x8000ffff);
+	for_each_pipe(pipe)
+		I915_WRITE(PIPESTAT(pipe),
+			   I915_READ(PIPESTAT(pipe)) & 0x8000ffff);
 	I915_WRITE(IIR, I915_READ(IIR));
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_reg.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_reg.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -405,9 +405,12 @@
 #define   I915_ERROR_INSTRUCTION			(1<<0)
 #define INSTPM	        0x020c0
 #define   INSTPM_SELF_EN (1<<12) /* 915GM only */
+#define   INSTPM_AGPBUSY_DIS (1<<11) /* gen3: when disabled, pending interrupts
+					will not assert AGPBUSY# and will only
+					be delivered when out of C3. */
 #define ACTHD	        0x020c8
 #define FW_BLC		0x020d8
-#define FW_BLC2	 	0x020dc
+#define FW_BLC2		0x020dc
 #define FW_BLC_SELF	0x020e0 /* 915+ only */
 #define   FW_BLC_SELF_EN_MASK      (1<<31)
 #define   FW_BLC_SELF_FIFO_MASK    (1<<16) /* 945 only */
@@ -706,9 +709,9 @@
 #define   VGA1_PD_P1_DIV_2	(1 << 13)
 #define   VGA1_PD_P1_SHIFT	8
 #define   VGA1_PD_P1_MASK	(0x1f << 8)
-#define DPLL_A	0x06014
-#define DPLL_B	0x06018
-#define DPLL(pipe) _PIPE(pipe, DPLL_A, DPLL_B)
+#define _DPLL_A	0x06014
+#define _DPLL_B	0x06018
+#define DPLL(pipe) _PIPE(pipe, _DPLL_A, _DPLL_B)
 #define   DPLL_VCO_ENABLE		(1 << 31)
 #define   DPLL_DVO_HIGH_SPEED		(1 << 30)
 #define   DPLL_SYNCLOCK_ENABLE		(1 << 29)
@@ -779,7 +782,7 @@
 #define   SDVO_MULTIPLIER_MASK			0x000000ff
 #define   SDVO_MULTIPLIER_SHIFT_HIRES		4
 #define   SDVO_MULTIPLIER_SHIFT_VGA		0
-#define DPLL_A_MD 0x0601c /* 965+ only */
+#define _DPLL_A_MD 0x0601c /* 965+ only */
 /*
  * UDI pixel divider, controlling how many pixels are stuffed into a packet.
  *
@@ -816,14 +819,14 @@
  */
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_MASK	0x0000003f
 #define   DPLL_MD_VGA_UDI_MULTIPLIER_SHIFT	0
-#define DPLL_B_MD 0x06020 /* 965+ only */
-#define DPLL_MD(pipe) _PIPE(pipe, DPLL_A_MD, DPLL_B_MD)
-#define FPA0	0x06040
-#define FPA1	0x06044
-#define FPB0	0x06048
-#define FPB1	0x0604c
-#define FP0(pipe) _PIPE(pipe, FPA0, FPB0)
-#define FP1(pipe) _PIPE(pipe, FPA1, FPB1)
+#define _DPLL_B_MD 0x06020 /* 965+ only */
+#define DPLL_MD(pipe) _PIPE(pipe, _DPLL_A_MD, _DPLL_B_MD)
+#define _FPA0	0x06040
+#define _FPA1	0x06044
+#define _FPB0	0x06048
+#define _FPB1	0x0604c
+#define FP0(pipe) _PIPE(pipe, _FPA0, _FPB0)
+#define FP1(pipe) _PIPE(pipe, _FPA1, _FPB1)
 #define   FP_N_DIV_MASK		0x003f0000
 #define   FP_N_PINEVIEW_DIV_MASK	0x00ff0000
 #define   FP_N_DIV_SHIFT		16
@@ -962,8 +965,9 @@
  * Palette regs
  */
 
-#define PALETTE_A		0x0a000
-#define PALETTE_B		0x0a800
+#define _PALETTE_A		0x0a000
+#define _PALETTE_B		0x0a800
+#define PALETTE(pipe) _PIPE(pipe, _PALETTE_A, _PALETTE_B)
 
 /* MCH MMIO space */
 
@@ -1267,32 +1271,32 @@
  */
 
 /* Pipe A timing regs */
-#define HTOTAL_A	0x60000
-#define HBLANK_A	0x60004
-#define HSYNC_A		0x60008
-#define VTOTAL_A	0x6000c
-#define VBLANK_A	0x60010
-#define VSYNC_A		0x60014
-#define PIPEASRC	0x6001c
-#define BCLRPAT_A	0x60020
+#define _HTOTAL_A	0x60000
+#define _HBLANK_A	0x60004
+#define _HSYNC_A		0x60008
+#define _VTOTAL_A	0x6000c
+#define _VBLANK_A	0x60010
+#define _VSYNC_A		0x60014
+#define _PIPEASRC	0x6001c
+#define _BCLRPAT_A	0x60020
 
 /* Pipe B timing regs */
-#define HTOTAL_B	0x61000
-#define HBLANK_B	0x61004
-#define HSYNC_B		0x61008
-#define VTOTAL_B	0x6100c
-#define VBLANK_B	0x61010
-#define VSYNC_B		0x61014
-#define PIPEBSRC	0x6101c
-#define BCLRPAT_B	0x61020
+#define _HTOTAL_B	0x61000
+#define _HBLANK_B	0x61004
+#define _HSYNC_B		0x61008
+#define _VTOTAL_B	0x6100c
+#define _VBLANK_B	0x61010
+#define _VSYNC_B		0x61014
+#define _PIPEBSRC	0x6101c
+#define _BCLRPAT_B	0x61020
 
-#define HTOTAL(pipe) _PIPE(pipe, HTOTAL_A, HTOTAL_B)
-#define HBLANK(pipe) _PIPE(pipe, HBLANK_A, HBLANK_B)
-#define HSYNC(pipe) _PIPE(pipe, HSYNC_A, HSYNC_B)
-#define VTOTAL(pipe) _PIPE(pipe, VTOTAL_A, VTOTAL_B)
-#define VBLANK(pipe) _PIPE(pipe, VBLANK_A, VBLANK_B)
-#define VSYNC(pipe) _PIPE(pipe, VSYNC_A, VSYNC_B)
-#define BCLRPAT(pipe) _PIPE(pipe, BCLRPAT_A, BCLRPAT_B)
+#define HTOTAL(pipe) _PIPE(pipe, _HTOTAL_A, _HTOTAL_B)
+#define HBLANK(pipe) _PIPE(pipe, _HBLANK_A, _HBLANK_B)
+#define HSYNC(pipe) _PIPE(pipe, _HSYNC_A, _HSYNC_B)
+#define VTOTAL(pipe) _PIPE(pipe, _VTOTAL_A, _VTOTAL_B)
+#define VBLANK(pipe) _PIPE(pipe, _VBLANK_A, _VBLANK_B)
+#define VSYNC(pipe) _PIPE(pipe, _VSYNC_A, _VSYNC_B)
+#define BCLRPAT(pipe) _PIPE(pipe, _BCLRPAT_A, _BCLRPAT_B)
 
 /* VGA port control */
 #define ADPA			0x61100
@@ -1386,6 +1390,7 @@
 #define   SDVO_ENCODING_HDMI		(0x2 << 10)
 /** Requird for HDMI operation */
 #define   SDVO_NULL_PACKETS_DURING_VSYNC (1 << 9)
+#define   SDVO_COLOR_RANGE_16_235	(1 << 8)
 #define   SDVO_BORDER_ENABLE		(1 << 7)
 #define   SDVO_AUDIO_ENABLE		(1 << 6)
 /** New with 965, default is to be set */
@@ -1441,8 +1446,13 @@
 #define   LVDS_PORT_EN			(1 << 31)
 /* Selects pipe B for LVDS data.  Must be set on pre-965. */
 #define   LVDS_PIPEB_SELECT		(1 << 30)
+#define   LVDS_PIPE_MASK		(1 << 30)
 /* LVDS dithering flag on 965/g4x platform */
 #define   LVDS_ENABLE_DITHER		(1 << 25)
+/* LVDS sync polarity flags. Set to invert (i.e. negative) */
+#define   LVDS_VSYNC_POLARITY		(1 << 21)
+#define   LVDS_HSYNC_POLARITY		(1 << 20)
+
 /* Enable border for unscaled (or aspect-scaled) display */
 #define   LVDS_BORDER_ENABLE		(1 << 15)
 /*
@@ -1476,6 +1486,9 @@
 #define   LVDS_B0B3_POWER_DOWN		(0 << 2)
 #define   LVDS_B0B3_POWER_UP		(3 << 2)
 
+#define LVDS_PIPE_ENABLED(V, P) \
+	(((V) & (LVDS_PIPE_MASK | LVDS_PORT_EN)) == ((P) << 30 | LVDS_PORT_EN))
+
 /* Video Data Island Packet control */
 #define VIDEO_DIP_DATA		0x61178
 #define VIDEO_DIP_CTL		0x61170
@@ -2064,6 +2077,10 @@
 
 #define   DP_PORT_EN			(1 << 31)
 #define   DP_PIPEB_SELECT		(1 << 30)
+#define   DP_PIPE_MASK			(1 << 30)
+
+#define DP_PIPE_ENABLED(V, P) \
+	(((V) & (DP_PIPE_MASK | DP_PORT_EN)) == ((P) << 30 | DP_PORT_EN))
 
 /* Link training mode - select a suitable mode for each stage */
 #define   DP_LINK_TRAIN_PAT_1		(0 << 28)
@@ -2206,8 +2223,8 @@
  * 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
+#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)
@@ -2215,8 +2232,8 @@
 
 #define   PIPE_GMCH_DATA_M_MASK			(0xffffff)
 
-#define PIPEA_GMCH_DATA_N			0x70054
-#define PIPEB_GMCH_DATA_N			0x71054
+#define _PIPEA_GMCH_DATA_N			0x70054
+#define _PIPEB_GMCH_DATA_N			0x71054
 #define   PIPE_GMCH_DATA_N_MASK			(0xffffff)
 
 /*
@@ -2230,20 +2247,25 @@
  * Attributes and VB-ID.
  */
 
-#define PIPEA_DP_LINK_M				0x70060
-#define PIPEB_DP_LINK_M				0x71060
+#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				0x70064
+#define _PIPEB_DP_LINK_N				0x71064
 #define   PIPEA_DP_LINK_N_MASK			(0xffffff)
 
+#define PIPE_GMCH_DATA_M(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_M, _PIPEB_GMCH_DATA_M)
+#define PIPE_GMCH_DATA_N(pipe) _PIPE(pipe, _PIPEA_GMCH_DATA_N, _PIPEB_GMCH_DATA_N)
+#define PIPE_DP_LINK_M(pipe) _PIPE(pipe, _PIPEA_DP_LINK_M, _PIPEB_DP_LINK_M)
+#define PIPE_DP_LINK_N(pipe) _PIPE(pipe, _PIPEA_DP_LINK_N, _PIPEB_DP_LINK_N)
+
 /* Display & cursor control */
 
 /* Pipe A */
-#define PIPEADSL		0x70000
+#define _PIPEADSL		0x70000
 #define   DSL_LINEMASK		0x00000fff
-#define PIPEACONF		0x70008
+#define _PIPEACONF		0x70008
 #define   PIPECONF_ENABLE	(1<<31)
 #define   PIPECONF_DISABLE	0
 #define   PIPECONF_DOUBLE_WIDE	(1<<30)
@@ -2269,7 +2291,7 @@
 #define   PIPECONF_DITHER_TYPE_ST1 (1<<2)
 #define   PIPECONF_DITHER_TYPE_ST2 (2<<2)
 #define   PIPECONF_DITHER_TYPE_TEMP (3<<2)
-#define PIPEASTAT		0x70024
+#define _PIPEASTAT		0x70024
 #define   PIPE_FIFO_UNDERRUN_STATUS		(1UL<<31)
 #define   PIPE_CRC_ERROR_ENABLE			(1UL<<29)
 #define   PIPE_CRC_DONE_ENABLE			(1UL<<28)
@@ -2305,10 +2327,12 @@
 #define   PIPE_6BPC				(2 << 5)
 #define   PIPE_12BPC				(3 << 5)
 
-#define PIPESRC(pipe) _PIPE(pipe, PIPEASRC, PIPEBSRC)
-#define PIPECONF(pipe) _PIPE(pipe, PIPEACONF, PIPEBCONF)
-#define PIPEDSL(pipe)  _PIPE(pipe, PIPEADSL, PIPEBDSL)
-#define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, PIPEAFRAMEPIXEL, PIPEBFRAMEPIXEL)
+#define PIPESRC(pipe) _PIPE(pipe, _PIPEASRC, _PIPEBSRC)
+#define PIPECONF(pipe) _PIPE(pipe, _PIPEACONF, _PIPEBCONF)
+#define PIPEDSL(pipe)  _PIPE(pipe, _PIPEADSL, _PIPEBDSL)
+#define PIPEFRAME(pipe) _PIPE(pipe, _PIPEAFRAMEHIGH, _PIPEBFRAMEHIGH)
+#define PIPEFRAMEPIXEL(pipe)  _PIPE(pipe, _PIPEAFRAMEPIXEL, _PIPEBFRAMEPIXEL)
+#define PIPESTAT(pipe) _PIPE(pipe, _PIPEASTAT, _PIPEBSTAT)
 
 #define DSPARB			0x70030
 #define   DSPARB_CSTART_MASK	(0x7f << 7)
@@ -2470,20 +2494,21 @@
  *  } while (high1 != high2);
  *  frame = (high1 << 8) | low1;
  */
-#define PIPEAFRAMEHIGH          0x70040
+#define _PIPEAFRAMEHIGH          0x70040
 #define   PIPE_FRAME_HIGH_MASK    0x0000ffff
 #define   PIPE_FRAME_HIGH_SHIFT   0
-#define PIPEAFRAMEPIXEL         0x70044
+#define _PIPEAFRAMEPIXEL         0x70044
 #define   PIPE_FRAME_LOW_MASK     0xff000000
 #define   PIPE_FRAME_LOW_SHIFT    24
 #define   PIPE_PIXEL_MASK         0x00ffffff
 #define   PIPE_PIXEL_SHIFT        0
 /* GM45+ just has to be different */
-#define PIPEA_FRMCOUNT_GM45	0x70040
-#define PIPEA_FLIPCOUNT_GM45	0x70044
+#define _PIPEA_FRMCOUNT_GM45	0x70040
+#define _PIPEA_FLIPCOUNT_GM45	0x70044
+#define PIPE_FRMCOUNT_GM45(pipe) _PIPE(pipe, _PIPEA_FRMCOUNT_GM45, _PIPEB_FRMCOUNT_GM45)
 
 /* Cursor A & B regs */
-#define CURACNTR		0x70080
+#define _CURACNTR		0x70080
 /* Old style CUR*CNTR flags (desktop 8xx) */
 #define   CURSOR_ENABLE		0x80000000
 #define   CURSOR_GAMMA_ENABLE	0x40000000
@@ -2504,23 +2529,23 @@
 #define   MCURSOR_PIPE_A	0x00
 #define   MCURSOR_PIPE_B	(1 << 28)
 #define   MCURSOR_GAMMA_ENABLE  (1 << 26)
-#define CURABASE		0x70084
-#define CURAPOS			0x70088
+#define _CURABASE		0x70084
+#define _CURAPOS			0x70088
 #define   CURSOR_POS_MASK       0x007FF
 #define   CURSOR_POS_SIGN       0x8000
 #define   CURSOR_X_SHIFT        0
 #define   CURSOR_Y_SHIFT        16
 #define CURSIZE			0x700a0
-#define CURBCNTR		0x700c0
-#define CURBBASE		0x700c4
-#define CURBPOS			0x700c8
+#define _CURBCNTR		0x700c0
+#define _CURBBASE		0x700c4
+#define _CURBPOS			0x700c8
 
-#define CURCNTR(pipe) _PIPE(pipe, CURACNTR, CURBCNTR)
-#define CURBASE(pipe) _PIPE(pipe, CURABASE, CURBBASE)
-#define CURPOS(pipe) _PIPE(pipe, CURAPOS, CURBPOS)
+#define CURCNTR(pipe) _PIPE(pipe, _CURACNTR, _CURBCNTR)
+#define CURBASE(pipe) _PIPE(pipe, _CURABASE, _CURBBASE)
+#define CURPOS(pipe) _PIPE(pipe, _CURAPOS, _CURBPOS)
 
 /* Display A control */
-#define DSPACNTR                0x70180
+#define _DSPACNTR                0x70180
 #define   DISPLAY_PLANE_ENABLE			(1<<31)
 #define   DISPLAY_PLANE_DISABLE			0
 #define   DISPPLANE_GAMMA_ENABLE		(1<<30)
@@ -2534,9 +2559,10 @@
 #define   DISPPLANE_32BPP_30BIT_NO_ALPHA	(0xa<<26)
 #define   DISPPLANE_STEREO_ENABLE		(1<<25)
 #define   DISPPLANE_STEREO_DISABLE		0
-#define   DISPPLANE_SEL_PIPE_MASK		(1<<24)
+#define   DISPPLANE_SEL_PIPE_SHIFT		24
+#define   DISPPLANE_SEL_PIPE_MASK		(3<<DISPPLANE_SEL_PIPE_SHIFT)
 #define   DISPPLANE_SEL_PIPE_A			0
-#define   DISPPLANE_SEL_PIPE_B			(1<<24)
+#define   DISPPLANE_SEL_PIPE_B			(1<<DISPPLANE_SEL_PIPE_SHIFT)
 #define   DISPPLANE_SRC_KEY_ENABLE		(1<<22)
 #define   DISPPLANE_SRC_KEY_DISABLE		0
 #define   DISPPLANE_LINE_DOUBLE			(1<<20)
@@ -2545,20 +2571,20 @@
 #define   DISPPLANE_STEREO_POLARITY_SECOND	(1<<18)
 #define   DISPPLANE_TRICKLE_FEED_DISABLE	(1<<14) /* Ironlake */
 #define   DISPPLANE_TILED			(1<<10)
-#define DSPAADDR		0x70184
-#define DSPASTRIDE		0x70188
-#define DSPAPOS			0x7018C /* reserved */
-#define DSPASIZE		0x70190
-#define DSPASURF		0x7019C /* 965+ only */
-#define DSPATILEOFF		0x701A4 /* 965+ only */
+#define _DSPAADDR		0x70184
+#define _DSPASTRIDE		0x70188
+#define _DSPAPOS			0x7018C /* reserved */
+#define _DSPASIZE		0x70190
+#define _DSPASURF		0x7019C /* 965+ only */
+#define _DSPATILEOFF		0x701A4 /* 965+ only */
 
-#define DSPCNTR(plane) _PIPE(plane, DSPACNTR, DSPBCNTR)
-#define DSPADDR(plane) _PIPE(plane, DSPAADDR, DSPBADDR)
-#define DSPSTRIDE(plane) _PIPE(plane, DSPASTRIDE, DSPBSTRIDE)
-#define DSPPOS(plane) _PIPE(plane, DSPAPOS, DSPBPOS)
-#define DSPSIZE(plane) _PIPE(plane, DSPASIZE, DSPBSIZE)
-#define DSPSURF(plane) _PIPE(plane, DSPASURF, DSPBSURF)
-#define DSPTILEOFF(plane) _PIPE(plane, DSPATILEOFF, DSPBTILEOFF)
+#define DSPCNTR(plane) _PIPE(plane, _DSPACNTR, _DSPBCNTR)
+#define DSPADDR(plane) _PIPE(plane, _DSPAADDR, _DSPBADDR)
+#define DSPSTRIDE(plane) _PIPE(plane, _DSPASTRIDE, _DSPBSTRIDE)
+#define DSPPOS(plane) _PIPE(plane, _DSPAPOS, _DSPBPOS)
+#define DSPSIZE(plane) _PIPE(plane, _DSPASIZE, _DSPBSIZE)
+#define DSPSURF(plane) _PIPE(plane, _DSPASURF, _DSPBSURF)
+#define DSPTILEOFF(plane) _PIPE(plane, _DSPATILEOFF, _DSPBTILEOFF)
 
 /* VBIOS flags */
 #define SWF00			0x71410
@@ -2576,27 +2602,27 @@
 #define SWF32			0x7241c
 
 /* Pipe B */
-#define PIPEBDSL		0x71000
-#define PIPEBCONF		0x71008
-#define PIPEBSTAT		0x71024
-#define PIPEBFRAMEHIGH		0x71040
-#define PIPEBFRAMEPIXEL		0x71044
-#define PIPEB_FRMCOUNT_GM45	0x71040
-#define PIPEB_FLIPCOUNT_GM45	0x71044
+#define _PIPEBDSL		0x71000
+#define _PIPEBCONF		0x71008
+#define _PIPEBSTAT		0x71024
+#define _PIPEBFRAMEHIGH		0x71040
+#define _PIPEBFRAMEPIXEL		0x71044
+#define _PIPEB_FRMCOUNT_GM45	0x71040
+#define _PIPEB_FLIPCOUNT_GM45	0x71044
 
 
 /* Display B control */
-#define DSPBCNTR		0x71180
+#define _DSPBCNTR		0x71180
 #define   DISPPLANE_ALPHA_TRANS_ENABLE		(1<<15)
 #define   DISPPLANE_ALPHA_TRANS_DISABLE		0
 #define   DISPPLANE_SPRITE_ABOVE_DISPLAY	0
 #define   DISPPLANE_SPRITE_ABOVE_OVERLAY	(1)
-#define DSPBADDR		0x71184
-#define DSPBSTRIDE		0x71188
-#define DSPBPOS			0x7118C
-#define DSPBSIZE		0x71190
-#define DSPBSURF		0x7119C
-#define DSPBTILEOFF		0x711A4
+#define _DSPBADDR		0x71184
+#define _DSPBSTRIDE		0x71188
+#define _DSPBPOS			0x7118C
+#define _DSPBSIZE		0x71190
+#define _DSPBSURF		0x7119C
+#define _DSPBTILEOFF		0x711A4
 
 /* VBIOS regs */
 #define VGACNTRL		0x71400
@@ -2650,68 +2676,80 @@
 #define  FDI_PLL_FREQ_DISABLE_COUNT_LIMIT_MASK  0xff
 
 
-#define PIPEA_DATA_M1           0x60030
+#define _PIPEA_DATA_M1           0x60030
 #define  TU_SIZE(x)             (((x)-1) << 25) /* default size 64 */
 #define  TU_SIZE_MASK           0x7e000000
 #define  PIPE_DATA_M1_OFFSET    0
-#define PIPEA_DATA_N1           0x60034
+#define _PIPEA_DATA_N1           0x60034
 #define  PIPE_DATA_N1_OFFSET    0
 
-#define PIPEA_DATA_M2           0x60038
+#define _PIPEA_DATA_M2           0x60038
 #define  PIPE_DATA_M2_OFFSET    0
-#define PIPEA_DATA_N2           0x6003c
+#define _PIPEA_DATA_N2           0x6003c
 #define  PIPE_DATA_N2_OFFSET    0
 
-#define PIPEA_LINK_M1           0x60040
+#define _PIPEA_LINK_M1           0x60040
 #define  PIPE_LINK_M1_OFFSET    0
-#define PIPEA_LINK_N1           0x60044
+#define _PIPEA_LINK_N1           0x60044
 #define  PIPE_LINK_N1_OFFSET    0
 
-#define PIPEA_LINK_M2           0x60048
+#define _PIPEA_LINK_M2           0x60048
 #define  PIPE_LINK_M2_OFFSET    0
-#define PIPEA_LINK_N2           0x6004c
+#define _PIPEA_LINK_N2           0x6004c
 #define  PIPE_LINK_N2_OFFSET    0
 
 /* PIPEB timing regs are same start from 0x61000 */
 
-#define PIPEB_DATA_M1           0x61030
-#define PIPEB_DATA_N1           0x61034
+#define _PIPEB_DATA_M1           0x61030
+#define _PIPEB_DATA_N1           0x61034
 
-#define PIPEB_DATA_M2           0x61038
-#define PIPEB_DATA_N2           0x6103c
+#define _PIPEB_DATA_M2           0x61038
+#define _PIPEB_DATA_N2           0x6103c
 
-#define PIPEB_LINK_M1           0x61040
-#define PIPEB_LINK_N1           0x61044
+#define _PIPEB_LINK_M1           0x61040
+#define _PIPEB_LINK_N1           0x61044
 
-#define PIPEB_LINK_M2           0x61048
-#define PIPEB_LINK_N2           0x6104c
+#define _PIPEB_LINK_M2           0x61048
+#define _PIPEB_LINK_N2           0x6104c
 
-#define PIPE_DATA_M1(pipe) _PIPE(pipe, PIPEA_DATA_M1, PIPEB_DATA_M1)
-#define PIPE_DATA_N1(pipe) _PIPE(pipe, PIPEA_DATA_N1, PIPEB_DATA_N1)
-#define PIPE_DATA_M2(pipe) _PIPE(pipe, PIPEA_DATA_M2, PIPEB_DATA_M2)
-#define PIPE_DATA_N2(pipe) _PIPE(pipe, PIPEA_DATA_N2, PIPEB_DATA_N2)
-#define PIPE_LINK_M1(pipe) _PIPE(pipe, PIPEA_LINK_M1, PIPEB_LINK_M1)
-#define PIPE_LINK_N1(pipe) _PIPE(pipe, PIPEA_LINK_N1, PIPEB_LINK_N1)
-#define PIPE_LINK_M2(pipe) _PIPE(pipe, PIPEA_LINK_M2, PIPEB_LINK_M2)
-#define PIPE_LINK_N2(pipe) _PIPE(pipe, PIPEA_LINK_N2, PIPEB_LINK_N2)
+#define PIPE_DATA_M1(pipe) _PIPE(pipe, _PIPEA_DATA_M1, _PIPEB_DATA_M1)
+#define PIPE_DATA_N1(pipe) _PIPE(pipe, _PIPEA_DATA_N1, _PIPEB_DATA_N1)
+#define PIPE_DATA_M2(pipe) _PIPE(pipe, _PIPEA_DATA_M2, _PIPEB_DATA_M2)
+#define PIPE_DATA_N2(pipe) _PIPE(pipe, _PIPEA_DATA_N2, _PIPEB_DATA_N2)
+#define PIPE_LINK_M1(pipe) _PIPE(pipe, _PIPEA_LINK_M1, _PIPEB_LINK_M1)
+#define PIPE_LINK_N1(pipe) _PIPE(pipe, _PIPEA_LINK_N1, _PIPEB_LINK_N1)
+#define PIPE_LINK_M2(pipe) _PIPE(pipe, _PIPEA_LINK_M2, _PIPEB_LINK_M2)
+#define PIPE_LINK_N2(pipe) _PIPE(pipe, _PIPEA_LINK_N2, _PIPEB_LINK_N2)
 
 /* CPU panel fitter */
-#define PFA_CTL_1               0x68080
-#define PFB_CTL_1               0x68880
+/* IVB+ has 3 fitters, 0 is 7x5 capable, the other two only 3x3 */
+#define _PFA_CTL_1               0x68080
+#define _PFB_CTL_1               0x68880
 #define  PF_ENABLE              (1<<31)
 #define  PF_FILTER_MASK		(3<<23)
 #define  PF_FILTER_PROGRAMMED	(0<<23)
 #define  PF_FILTER_MED_3x3	(1<<23)
 #define  PF_FILTER_EDGE_ENHANCE	(2<<23)
 #define  PF_FILTER_EDGE_SOFTEN	(3<<23)
-#define PFA_WIN_SZ		0x68074
-#define PFB_WIN_SZ		0x68874
-#define PFA_WIN_POS		0x68070
-#define PFB_WIN_POS		0x68870
+#define _PFA_WIN_SZ		0x68074
+#define _PFB_WIN_SZ		0x68874
+#define _PFA_WIN_POS		0x68070
+#define _PFB_WIN_POS		0x68870
+#define _PFA_VSCALE		0x68084
+#define _PFB_VSCALE		0x68884
+#define _PFA_HSCALE		0x68090
+#define _PFB_HSCALE		0x68890
+
+#define PF_CTL(pipe)		_PIPE(pipe, _PFA_CTL_1, _PFB_CTL_1)
+#define PF_WIN_SZ(pipe)		_PIPE(pipe, _PFA_WIN_SZ, _PFB_WIN_SZ)
+#define PF_WIN_POS(pipe)	_PIPE(pipe, _PFA_WIN_POS, _PFB_WIN_POS)
+#define PF_VSCALE(pipe)		_PIPE(pipe, _PFA_VSCALE, _PFB_VSCALE)
+#define PF_HSCALE(pipe)		_PIPE(pipe, _PFA_HSCALE, _PFB_HSCALE)
 
 /* legacy palette */
-#define LGC_PALETTE_A           0x4a000
-#define LGC_PALETTE_B           0x4a800
+#define _LGC_PALETTE_A           0x4a000
+#define _LGC_PALETTE_B           0x4a800
+#define LGC_PALETTE(pipe) _PIPE(pipe, _LGC_PALETTE_A, _LGC_PALETTE_B)
 
 /* interrupts */
 #define DE_MASTER_IRQ_CONTROL   (1 << 31)
@@ -2877,17 +2915,17 @@
 #define PCH_GMBUS4		0xc5110
 #define PCH_GMBUS5		0xc5120
 
-#define PCH_DPLL_A              0xc6014
-#define PCH_DPLL_B              0xc6018
-#define PCH_DPLL(pipe) _PIPE(pipe, PCH_DPLL_A, PCH_DPLL_B)
+#define _PCH_DPLL_A              0xc6014
+#define _PCH_DPLL_B              0xc6018
+#define PCH_DPLL(pipe) _PIPE(pipe, _PCH_DPLL_A, _PCH_DPLL_B)
 
-#define PCH_FPA0                0xc6040
+#define _PCH_FPA0                0xc6040
 #define  FP_CB_TUNE		(0x3<<22)
-#define PCH_FPA1                0xc6044
-#define PCH_FPB0                0xc6048
-#define PCH_FPB1                0xc604c
-#define PCH_FP0(pipe) _PIPE(pipe, PCH_FPA0, PCH_FPB0)
-#define PCH_FP1(pipe) _PIPE(pipe, PCH_FPA1, PCH_FPB1)
+#define _PCH_FPA1                0xc6044
+#define _PCH_FPB0                0xc6048
+#define _PCH_FPB1                0xc604c
+#define PCH_FP0(pipe) _PIPE(pipe, _PCH_FPA0, _PCH_FPB0)
+#define PCH_FP1(pipe) _PIPE(pipe, _PCH_FPA1, _PCH_FPB1)
 
 #define PCH_DPLL_TEST           0xc606c
 
@@ -2906,6 +2944,7 @@
 #define  DREF_NONSPREAD_SOURCE_MASK		(3<<9)
 #define  DREF_SUPERSPREAD_SOURCE_DISABLE        (0<<7)
 #define  DREF_SUPERSPREAD_SOURCE_ENABLE         (2<<7)
+#define  DREF_SUPERSPREAD_SOURCE_MASK		(3<<7)
 #define  DREF_SSC4_DOWNSPREAD                   (0<<6)
 #define  DREF_SSC4_CENTERSPREAD                 (1<<6)
 #define  DREF_SSC1_DISABLE                      (0<<1)
@@ -2938,60 +2977,69 @@
 
 /* transcoder */
 
-#define TRANS_HTOTAL_A          0xe0000
+#define _TRANS_HTOTAL_A          0xe0000
 #define  TRANS_HTOTAL_SHIFT     16
 #define  TRANS_HACTIVE_SHIFT    0
-#define TRANS_HBLANK_A          0xe0004
+#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_A           0xe0008
 #define  TRANS_HSYNC_END_SHIFT  16
 #define  TRANS_HSYNC_START_SHIFT 0
-#define TRANS_VTOTAL_A          0xe000c
+#define _TRANS_VTOTAL_A          0xe000c
 #define  TRANS_VTOTAL_SHIFT     16
 #define  TRANS_VACTIVE_SHIFT    0
-#define TRANS_VBLANK_A          0xe0010
+#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_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 _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 _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 TRANS_HTOTAL(pipe) _PIPE(pipe, TRANS_HTOTAL_A, TRANS_HTOTAL_B)
-#define TRANS_HBLANK(pipe) _PIPE(pipe, TRANS_HBLANK_A, TRANS_HBLANK_B)
-#define TRANS_HSYNC(pipe) _PIPE(pipe, TRANS_HSYNC_A, TRANS_HSYNC_B)
-#define TRANS_VTOTAL(pipe) _PIPE(pipe, TRANS_VTOTAL_A, TRANS_VTOTAL_B)
-#define TRANS_VBLANK(pipe) _PIPE(pipe, TRANS_VBLANK_A, TRANS_VBLANK_B)
-#define TRANS_VSYNC(pipe) _PIPE(pipe, TRANS_VSYNC_A, TRANS_VSYNC_B)
+#define TRANS_HTOTAL(pipe) _PIPE(pipe, _TRANS_HTOTAL_A, _TRANS_HTOTAL_B)
+#define TRANS_HBLANK(pipe) _PIPE(pipe, _TRANS_HBLANK_A, _TRANS_HBLANK_B)
+#define TRANS_HSYNC(pipe) _PIPE(pipe, _TRANS_HSYNC_A, _TRANS_HSYNC_B)
+#define TRANS_VTOTAL(pipe) _PIPE(pipe, _TRANS_VTOTAL_A, _TRANS_VTOTAL_B)
+#define TRANS_VBLANK(pipe) _PIPE(pipe, _TRANS_VBLANK_A, _TRANS_VBLANK_B)
+#define TRANS_VSYNC(pipe) _PIPE(pipe, _TRANS_VSYNC_A, _TRANS_VSYNC_B)
 
-#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 _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 TRANSCONF(plane) _PIPE(plane, TRANSACONF, TRANSBCONF)
+#define TRANSDATA_M1(pipe) _PIPE(pipe, _TRANSA_DATA_M1, _TRANSB_DATA_M1)
+#define TRANSDATA_N1(pipe) _PIPE(pipe, _TRANSA_DATA_N1, _TRANSB_DATA_N1)
+#define TRANSDATA_M2(pipe) _PIPE(pipe, _TRANSA_DATA_M2, _TRANSB_DATA_M2)
+#define TRANSDATA_N2(pipe) _PIPE(pipe, _TRANSA_DATA_N2, _TRANSB_DATA_N2)
+#define TRANSDPLINK_M1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M1, _TRANSB_DP_LINK_M1)
+#define TRANSDPLINK_N1(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N1, _TRANSB_DP_LINK_N1)
+#define TRANSDPLINK_M2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_M2, _TRANSB_DP_LINK_M2)
+#define TRANSDPLINK_N2(pipe) _PIPE(pipe, _TRANSA_DP_LINK_N2, _TRANSB_DP_LINK_N2)
+
+#define _TRANSACONF              0xf0008
+#define _TRANSBCONF              0xf1008
+#define TRANSCONF(plane) _PIPE(plane, _TRANSACONF, _TRANSBCONF)
 #define  TRANS_DISABLE          (0<<31)
 #define  TRANS_ENABLE           (1<<31)
 #define  TRANS_STATE_MASK       (1<<30)
@@ -3009,18 +3057,19 @@
 #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)
-#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, FDI_RXA_CHICKEN, FDI_RXB_CHICKEN)
+#define _FDI_RXA_CHICKEN         0xc200c
+#define _FDI_RXB_CHICKEN         0xc2010
+#define  FDI_RX_PHASE_SYNC_POINTER_OVR	(1<<1)
+#define  FDI_RX_PHASE_SYNC_POINTER_EN	(1<<0)
+#define FDI_RX_CHICKEN(pipe) _PIPE(pipe, _FDI_RXA_CHICKEN, _FDI_RXB_CHICKEN)
 
 #define SOUTH_DSPCLK_GATE_D	0xc2020
 #define  PCH_DPLSUNIT_CLOCK_GATE_DISABLE (1<<29)
 
 /* CPU: FDI_TX */
-#define FDI_TXA_CTL             0x60100
-#define FDI_TXB_CTL             0x61100
-#define FDI_TX_CTL(pipe) _PIPE(pipe, FDI_TXA_CTL, FDI_TXB_CTL)
+#define _FDI_TXA_CTL             0x60100
+#define _FDI_TXB_CTL             0x61100
+#define FDI_TX_CTL(pipe) _PIPE(pipe, _FDI_TXA_CTL, _FDI_TXB_CTL)
 #define  FDI_TX_DISABLE         (0<<31)
 #define  FDI_TX_ENABLE          (1<<31)
 #define  FDI_LINK_TRAIN_PATTERN_1       (0<<28)
@@ -3060,9 +3109,9 @@
 #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_CTL(pipe) _PIPE(pipe, FDI_RXA_CTL, FDI_RXB_CTL)
+#define _FDI_RXA_CTL             0xf000c
+#define _FDI_RXB_CTL             0xf100c
+#define FDI_RX_CTL(pipe) _PIPE(pipe, _FDI_RXA_CTL, _FDI_RXB_CTL)
 #define  FDI_RX_ENABLE          (1<<31)
 /* train, dp width same as FDI_TX */
 #define  FDI_DP_PORT_WIDTH_X8           (7<<19)
@@ -3087,15 +3136,15 @@
 #define  FDI_LINK_TRAIN_NORMAL_CPT		(3<<8)
 #define  FDI_LINK_TRAIN_PATTERN_MASK_CPT	(3<<8)
 
-#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
-#define FDI_RX_MISC(pipe) _PIPE(pipe, FDI_RXA_MISC, FDI_RXB_MISC)
-#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, FDI_RXA_TUSIZE1, FDI_RXB_TUSIZE1)
-#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, FDI_RXA_TUSIZE2, FDI_RXB_TUSIZE2)
+#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
+#define FDI_RX_MISC(pipe) _PIPE(pipe, _FDI_RXA_MISC, _FDI_RXB_MISC)
+#define FDI_RX_TUSIZE1(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE1, _FDI_RXB_TUSIZE1)
+#define FDI_RX_TUSIZE2(pipe) _PIPE(pipe, _FDI_RXA_TUSIZE2, _FDI_RXB_TUSIZE2)
 
 /* FDI_RX interrupt register format */
 #define FDI_RX_INTER_LANE_ALIGN         (1<<10)
@@ -3110,12 +3159,12 @@
 #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_RX_IIR(pipe) _PIPE(pipe, FDI_RXA_IIR, FDI_RXB_IIR)
-#define FDI_RX_IMR(pipe) _PIPE(pipe, FDI_RXA_IMR, FDI_RXB_IMR)
+#define _FDI_RXA_IIR             0xf0014
+#define _FDI_RXA_IMR             0xf0018
+#define _FDI_RXB_IIR             0xf1014
+#define _FDI_RXB_IMR             0xf1018
+#define FDI_RX_IIR(pipe) _PIPE(pipe, _FDI_RXA_IIR, _FDI_RXB_IIR)
+#define FDI_RX_IMR(pipe) _PIPE(pipe, _FDI_RXA_IMR, _FDI_RXB_IMR)
 
 #define FDI_PLL_CTL_1           0xfe000
 #define FDI_PLL_CTL_2           0xfe004
@@ -3145,11 +3194,15 @@
 #define  ADPA_CRT_HOTPLUG_VOLREF_475MV  (1<<17)
 #define  ADPA_CRT_HOTPLUG_FORCE_TRIGGER (1<<16)
 
+#define ADPA_PIPE_ENABLED(V, P) \
+	(((V) & (ADPA_TRANS_SELECT_MASK | ADPA_DAC_ENABLE)) == ((P) << 30 | ADPA_DAC_ENABLE))
+
 /* or SDVOB */
 #define HDMIB   0xe1140
 #define  PORT_ENABLE    (1 << 31)
 #define  TRANSCODER_A   (0)
 #define  TRANSCODER_B   (1 << 30)
+#define  TRANSCODER_MASK   (1 << 30)
 #define  COLOR_FORMAT_8bpc      (0)
 #define  COLOR_FORMAT_12bpc     (3 << 26)
 #define  SDVOB_HOTPLUG_ENABLE   (1 << 23)
@@ -3165,6 +3218,9 @@
 #define  HSYNC_ACTIVE_HIGH      (1 << 3)
 #define  PORT_DETECTED          (1 << 2)
 
+#define HDMI_PIPE_ENABLED(V, P) \
+	(((V) & (TRANSCODER_MASK | PORT_ENABLE)) == ((P) << 30 | PORT_ENABLE))
+
 /* PCH SDVOB multiplex with HDMIB */
 #define PCH_SDVOB	HDMIB
 
@@ -3240,6 +3296,7 @@
 #define  TRANS_DP_PORT_SEL_B	(0<<29)
 #define  TRANS_DP_PORT_SEL_C	(1<<29)
 #define  TRANS_DP_PORT_SEL_D	(2<<29)
+#define  TRANS_DP_PORT_SEL_NONE	(3<<29)
 #define  TRANS_DP_PORT_SEL_MASK	(3<<29)
 #define  TRANS_DP_AUDIO_ONLY	(1<<26)
 #define  TRANS_DP_ENH_FRAMING	(1<<18)
@@ -3290,15 +3347,28 @@
 #define GEN6_RP_DOWN_TIMEOUT			0xA010
 #define GEN6_RP_INTERRUPT_LIMITS		0xA014
 #define GEN6_RPSTAT1				0xA01C
+#define   GEN6_CAGF_SHIFT			8
+#define   GEN6_CAGF_MASK			(0x7f << GEN6_CAGF_SHIFT)
 #define GEN6_RP_CONTROL				0xA024
 #define   GEN6_RP_MEDIA_TURBO			(1<<11)
 #define   GEN6_RP_USE_NORMAL_FREQ		(1<<9)
 #define   GEN6_RP_MEDIA_IS_GFX			(1<<8)
 #define   GEN6_RP_ENABLE			(1<<7)
-#define   GEN6_RP_UP_BUSY_MAX			(0x2<<3)
-#define   GEN6_RP_DOWN_BUSY_MIN			(0x2<<0)
+#define   GEN6_RP_UP_IDLE_MIN			(0x1<<3)
+#define   GEN6_RP_UP_BUSY_AVG			(0x2<<3)
+#define   GEN6_RP_UP_BUSY_CONT			(0x4<<3)
+#define   GEN6_RP_DOWN_IDLE_CONT		(0x1<<0)
 #define GEN6_RP_UP_THRESHOLD			0xA02C
 #define GEN6_RP_DOWN_THRESHOLD			0xA030
+#define GEN6_RP_CUR_UP_EI			0xA050
+#define   GEN6_CURICONT_MASK			0xffffff
+#define GEN6_RP_CUR_UP				0xA054
+#define   GEN6_CURBSYTAVG_MASK			0xffffff
+#define GEN6_RP_PREV_UP				0xA058
+#define GEN6_RP_CUR_DOWN_EI			0xA05C
+#define   GEN6_CURIAVG_MASK			0xffffff
+#define GEN6_RP_CUR_DOWN			0xA060
+#define GEN6_RP_PREV_DOWN			0xA064
 #define GEN6_RP_UP_EI				0xA068
 #define GEN6_RP_DOWN_EI				0xA06C
 #define GEN6_RP_IDLE_HYSTERSIS			0xA070
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_suspend.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_suspend.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_suspend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_suspend.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,11 +34,10 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32	dpll_reg;
 
-	if (HAS_PCH_SPLIT(dev)) {
-		dpll_reg = (pipe == PIPE_A) ? PCH_DPLL_A: PCH_DPLL_B;
-	} else {
-		dpll_reg = (pipe == PIPE_A) ? DPLL_A: DPLL_B;
-	}
+	if (HAS_PCH_SPLIT(dev))
+		dpll_reg = (pipe == PIPE_A) ? _PCH_DPLL_A : _PCH_DPLL_B;
+	else
+		dpll_reg = (pipe == PIPE_A) ? _DPLL_A : _DPLL_B;
 
 	return (I915_READ(dpll_reg) & DPLL_VCO_ENABLE);
 }
@@ -46,7 +45,7 @@
 static void i915_save_palette(struct drm_device *dev, enum pipe pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
 	u32 *array;
 	int i;
 
@@ -54,7 +53,7 @@
 		return;
 
 	if (HAS_PCH_SPLIT(dev))
-		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
 		array = dev_priv->save_palette_a;
@@ -68,7 +67,7 @@
 static void i915_restore_palette(struct drm_device *dev, enum pipe pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long reg = (pipe == PIPE_A ? PALETTE_A : PALETTE_B);
+	unsigned long reg = (pipe == PIPE_A ? _PALETTE_A : _PALETTE_B);
 	u32 *array;
 	int i;
 
@@ -76,7 +75,7 @@
 		return;
 
 	if (HAS_PCH_SPLIT(dev))
-		reg = (pipe == PIPE_A) ? LGC_PALETTE_A : LGC_PALETTE_B;
+		reg = (pipe == PIPE_A) ? _LGC_PALETTE_A : _LGC_PALETTE_B;
 
 	if (pipe == PIPE_A)
 		array = dev_priv->save_palette_a;
@@ -241,12 +240,12 @@
 		return;
 
 	/* 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);
+	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_GEN2(dev))
 		dev_priv->saveCURSIZE = I915_READ(CURSIZE);
 
@@ -256,118 +255,118 @@
 	}
 
 	/* Pipe & plane A info */
-	dev_priv->savePIPEACONF = I915_READ(PIPEACONF);
-	dev_priv->savePIPEASRC = I915_READ(PIPEASRC);
+	dev_priv->savePIPEACONF = I915_READ(_PIPEACONF);
+	dev_priv->savePIPEASRC = I915_READ(_PIPEASRC);
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveFPA0 = I915_READ(PCH_FPA0);
-		dev_priv->saveFPA1 = I915_READ(PCH_FPA1);
-		dev_priv->saveDPLL_A = I915_READ(PCH_DPLL_A);
+		dev_priv->saveFPA0 = I915_READ(_PCH_FPA0);
+		dev_priv->saveFPA1 = I915_READ(_PCH_FPA1);
+		dev_priv->saveDPLL_A = I915_READ(_PCH_DPLL_A);
 	} else {
-		dev_priv->saveFPA0 = I915_READ(FPA0);
-		dev_priv->saveFPA1 = I915_READ(FPA1);
-		dev_priv->saveDPLL_A = I915_READ(DPLL_A);
+		dev_priv->saveFPA0 = I915_READ(_FPA0);
+		dev_priv->saveFPA1 = I915_READ(_FPA1);
+		dev_priv->saveDPLL_A = I915_READ(_DPLL_A);
 	}
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		dev_priv->saveDPLL_A_MD = I915_READ(DPLL_A_MD);
-	dev_priv->saveHTOTAL_A = I915_READ(HTOTAL_A);
-	dev_priv->saveHBLANK_A = I915_READ(HBLANK_A);
-	dev_priv->saveHSYNC_A = I915_READ(HSYNC_A);
-	dev_priv->saveVTOTAL_A = I915_READ(VTOTAL_A);
-	dev_priv->saveVBLANK_A = I915_READ(VBLANK_A);
-	dev_priv->saveVSYNC_A = I915_READ(VSYNC_A);
+		dev_priv->saveDPLL_A_MD = I915_READ(_DPLL_A_MD);
+	dev_priv->saveHTOTAL_A = I915_READ(_HTOTAL_A);
+	dev_priv->saveHBLANK_A = I915_READ(_HBLANK_A);
+	dev_priv->saveHSYNC_A = I915_READ(_HSYNC_A);
+	dev_priv->saveVTOTAL_A = I915_READ(_VTOTAL_A);
+	dev_priv->saveVBLANK_A = I915_READ(_VBLANK_A);
+	dev_priv->saveVSYNC_A = I915_READ(_VSYNC_A);
 	if (!HAS_PCH_SPLIT(dev))
-		dev_priv->saveBCLRPAT_A = I915_READ(BCLRPAT_A);
+		dev_priv->saveBCLRPAT_A = I915_READ(_BCLRPAT_A);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePIPEA_DATA_M1 = I915_READ(PIPEA_DATA_M1);
-		dev_priv->savePIPEA_DATA_N1 = I915_READ(PIPEA_DATA_N1);
-		dev_priv->savePIPEA_LINK_M1 = I915_READ(PIPEA_LINK_M1);
-		dev_priv->savePIPEA_LINK_N1 = I915_READ(PIPEA_LINK_N1);
+		dev_priv->savePIPEA_DATA_M1 = I915_READ(_PIPEA_DATA_M1);
+		dev_priv->savePIPEA_DATA_N1 = I915_READ(_PIPEA_DATA_N1);
+		dev_priv->savePIPEA_LINK_M1 = I915_READ(_PIPEA_LINK_M1);
+		dev_priv->savePIPEA_LINK_N1 = I915_READ(_PIPEA_LINK_N1);
 
-		dev_priv->saveFDI_TXA_CTL = I915_READ(FDI_TXA_CTL);
-		dev_priv->saveFDI_RXA_CTL = I915_READ(FDI_RXA_CTL);
+		dev_priv->saveFDI_TXA_CTL = I915_READ(_FDI_TXA_CTL);
+		dev_priv->saveFDI_RXA_CTL = I915_READ(_FDI_RXA_CTL);
 
-		dev_priv->savePFA_CTL_1 = I915_READ(PFA_CTL_1);
-		dev_priv->savePFA_WIN_SZ = I915_READ(PFA_WIN_SZ);
-		dev_priv->savePFA_WIN_POS = I915_READ(PFA_WIN_POS);
+		dev_priv->savePFA_CTL_1 = I915_READ(_PFA_CTL_1);
+		dev_priv->savePFA_WIN_SZ = I915_READ(_PFA_WIN_SZ);
+		dev_priv->savePFA_WIN_POS = I915_READ(_PFA_WIN_POS);
 
-		dev_priv->saveTRANSACONF = I915_READ(TRANSACONF);
-		dev_priv->saveTRANS_HTOTAL_A = I915_READ(TRANS_HTOTAL_A);
-		dev_priv->saveTRANS_HBLANK_A = I915_READ(TRANS_HBLANK_A);
-		dev_priv->saveTRANS_HSYNC_A = I915_READ(TRANS_HSYNC_A);
-		dev_priv->saveTRANS_VTOTAL_A = I915_READ(TRANS_VTOTAL_A);
-		dev_priv->saveTRANS_VBLANK_A = I915_READ(TRANS_VBLANK_A);
-		dev_priv->saveTRANS_VSYNC_A = I915_READ(TRANS_VSYNC_A);
+		dev_priv->saveTRANSACONF = I915_READ(_TRANSACONF);
+		dev_priv->saveTRANS_HTOTAL_A = I915_READ(_TRANS_HTOTAL_A);
+		dev_priv->saveTRANS_HBLANK_A = I915_READ(_TRANS_HBLANK_A);
+		dev_priv->saveTRANS_HSYNC_A = I915_READ(_TRANS_HSYNC_A);
+		dev_priv->saveTRANS_VTOTAL_A = I915_READ(_TRANS_VTOTAL_A);
+		dev_priv->saveTRANS_VBLANK_A = I915_READ(_TRANS_VBLANK_A);
+		dev_priv->saveTRANS_VSYNC_A = I915_READ(_TRANS_VSYNC_A);
 	}
 
-	dev_priv->saveDSPACNTR = I915_READ(DSPACNTR);
-	dev_priv->saveDSPASTRIDE = I915_READ(DSPASTRIDE);
-	dev_priv->saveDSPASIZE = I915_READ(DSPASIZE);
-	dev_priv->saveDSPAPOS = I915_READ(DSPAPOS);
-	dev_priv->saveDSPAADDR = I915_READ(DSPAADDR);
+	dev_priv->saveDSPACNTR = I915_READ(_DSPACNTR);
+	dev_priv->saveDSPASTRIDE = I915_READ(_DSPASTRIDE);
+	dev_priv->saveDSPASIZE = I915_READ(_DSPASIZE);
+	dev_priv->saveDSPAPOS = I915_READ(_DSPAPOS);
+	dev_priv->saveDSPAADDR = I915_READ(_DSPAADDR);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		dev_priv->saveDSPASURF = I915_READ(DSPASURF);
-		dev_priv->saveDSPATILEOFF = I915_READ(DSPATILEOFF);
+		dev_priv->saveDSPASURF = I915_READ(_DSPASURF);
+		dev_priv->saveDSPATILEOFF = I915_READ(_DSPATILEOFF);
 	}
 	i915_save_palette(dev, PIPE_A);
-	dev_priv->savePIPEASTAT = I915_READ(PIPEASTAT);
+	dev_priv->savePIPEASTAT = I915_READ(_PIPEASTAT);
 
 	/* Pipe & plane B info */
-	dev_priv->savePIPEBCONF = I915_READ(PIPEBCONF);
-	dev_priv->savePIPEBSRC = I915_READ(PIPEBSRC);
+	dev_priv->savePIPEBCONF = I915_READ(_PIPEBCONF);
+	dev_priv->savePIPEBSRC = I915_READ(_PIPEBSRC);
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->saveFPB0 = I915_READ(PCH_FPB0);
-		dev_priv->saveFPB1 = I915_READ(PCH_FPB1);
-		dev_priv->saveDPLL_B = I915_READ(PCH_DPLL_B);
+		dev_priv->saveFPB0 = I915_READ(_PCH_FPB0);
+		dev_priv->saveFPB1 = I915_READ(_PCH_FPB1);
+		dev_priv->saveDPLL_B = I915_READ(_PCH_DPLL_B);
 	} else {
-		dev_priv->saveFPB0 = I915_READ(FPB0);
-		dev_priv->saveFPB1 = I915_READ(FPB1);
-		dev_priv->saveDPLL_B = I915_READ(DPLL_B);
+		dev_priv->saveFPB0 = I915_READ(_FPB0);
+		dev_priv->saveFPB1 = I915_READ(_FPB1);
+		dev_priv->saveDPLL_B = I915_READ(_DPLL_B);
 	}
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev))
-		dev_priv->saveDPLL_B_MD = I915_READ(DPLL_B_MD);
-	dev_priv->saveHTOTAL_B = I915_READ(HTOTAL_B);
-	dev_priv->saveHBLANK_B = I915_READ(HBLANK_B);
-	dev_priv->saveHSYNC_B = I915_READ(HSYNC_B);
-	dev_priv->saveVTOTAL_B = I915_READ(VTOTAL_B);
-	dev_priv->saveVBLANK_B = I915_READ(VBLANK_B);
-	dev_priv->saveVSYNC_B = I915_READ(VSYNC_B);
+		dev_priv->saveDPLL_B_MD = I915_READ(_DPLL_B_MD);
+	dev_priv->saveHTOTAL_B = I915_READ(_HTOTAL_B);
+	dev_priv->saveHBLANK_B = I915_READ(_HBLANK_B);
+	dev_priv->saveHSYNC_B = I915_READ(_HSYNC_B);
+	dev_priv->saveVTOTAL_B = I915_READ(_VTOTAL_B);
+	dev_priv->saveVBLANK_B = I915_READ(_VBLANK_B);
+	dev_priv->saveVSYNC_B = I915_READ(_VSYNC_B);
 	if (!HAS_PCH_SPLIT(dev))
-		dev_priv->saveBCLRPAT_B = I915_READ(BCLRPAT_B);
+		dev_priv->saveBCLRPAT_B = I915_READ(_BCLRPAT_B);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dev_priv->savePIPEB_DATA_M1 = I915_READ(PIPEB_DATA_M1);
-		dev_priv->savePIPEB_DATA_N1 = I915_READ(PIPEB_DATA_N1);
-		dev_priv->savePIPEB_LINK_M1 = I915_READ(PIPEB_LINK_M1);
-		dev_priv->savePIPEB_LINK_N1 = I915_READ(PIPEB_LINK_N1);
+		dev_priv->savePIPEB_DATA_M1 = I915_READ(_PIPEB_DATA_M1);
+		dev_priv->savePIPEB_DATA_N1 = I915_READ(_PIPEB_DATA_N1);
+		dev_priv->savePIPEB_LINK_M1 = I915_READ(_PIPEB_LINK_M1);
+		dev_priv->savePIPEB_LINK_N1 = I915_READ(_PIPEB_LINK_N1);
 
-		dev_priv->saveFDI_TXB_CTL = I915_READ(FDI_TXB_CTL);
-		dev_priv->saveFDI_RXB_CTL = I915_READ(FDI_RXB_CTL);
+		dev_priv->saveFDI_TXB_CTL = I915_READ(_FDI_TXB_CTL);
+		dev_priv->saveFDI_RXB_CTL = I915_READ(_FDI_RXB_CTL);
 
-		dev_priv->savePFB_CTL_1 = I915_READ(PFB_CTL_1);
-		dev_priv->savePFB_WIN_SZ = I915_READ(PFB_WIN_SZ);
-		dev_priv->savePFB_WIN_POS = I915_READ(PFB_WIN_POS);
+		dev_priv->savePFB_CTL_1 = I915_READ(_PFB_CTL_1);
+		dev_priv->savePFB_WIN_SZ = I915_READ(_PFB_WIN_SZ);
+		dev_priv->savePFB_WIN_POS = I915_READ(_PFB_WIN_POS);
 
-		dev_priv->saveTRANSBCONF = I915_READ(TRANSBCONF);
-		dev_priv->saveTRANS_HTOTAL_B = I915_READ(TRANS_HTOTAL_B);
-		dev_priv->saveTRANS_HBLANK_B = I915_READ(TRANS_HBLANK_B);
-		dev_priv->saveTRANS_HSYNC_B = I915_READ(TRANS_HSYNC_B);
-		dev_priv->saveTRANS_VTOTAL_B = I915_READ(TRANS_VTOTAL_B);
-		dev_priv->saveTRANS_VBLANK_B = I915_READ(TRANS_VBLANK_B);
-		dev_priv->saveTRANS_VSYNC_B = I915_READ(TRANS_VSYNC_B);
+		dev_priv->saveTRANSBCONF = I915_READ(_TRANSBCONF);
+		dev_priv->saveTRANS_HTOTAL_B = I915_READ(_TRANS_HTOTAL_B);
+		dev_priv->saveTRANS_HBLANK_B = I915_READ(_TRANS_HBLANK_B);
+		dev_priv->saveTRANS_HSYNC_B = I915_READ(_TRANS_HSYNC_B);
+		dev_priv->saveTRANS_VTOTAL_B = I915_READ(_TRANS_VTOTAL_B);
+		dev_priv->saveTRANS_VBLANK_B = I915_READ(_TRANS_VBLANK_B);
+		dev_priv->saveTRANS_VSYNC_B = I915_READ(_TRANS_VSYNC_B);
 	}
 
-	dev_priv->saveDSPBCNTR = I915_READ(DSPBCNTR);
-	dev_priv->saveDSPBSTRIDE = I915_READ(DSPBSTRIDE);
-	dev_priv->saveDSPBSIZE = I915_READ(DSPBSIZE);
-	dev_priv->saveDSPBPOS = I915_READ(DSPBPOS);
-	dev_priv->saveDSPBADDR = I915_READ(DSPBADDR);
+	dev_priv->saveDSPBCNTR = I915_READ(_DSPBCNTR);
+	dev_priv->saveDSPBSTRIDE = I915_READ(_DSPBSTRIDE);
+	dev_priv->saveDSPBSIZE = I915_READ(_DSPBSIZE);
+	dev_priv->saveDSPBPOS = I915_READ(_DSPBPOS);
+	dev_priv->saveDSPBADDR = I915_READ(_DSPBADDR);
 	if (INTEL_INFO(dev)->gen >= 4) {
-		dev_priv->saveDSPBSURF = I915_READ(DSPBSURF);
-		dev_priv->saveDSPBTILEOFF = I915_READ(DSPBTILEOFF);
+		dev_priv->saveDSPBSURF = I915_READ(_DSPBSURF);
+		dev_priv->saveDSPBTILEOFF = I915_READ(_DSPBTILEOFF);
 	}
 	i915_save_palette(dev, PIPE_B);
-	dev_priv->savePIPEBSTAT = I915_READ(PIPEBSTAT);
+	dev_priv->savePIPEBSTAT = I915_READ(_PIPEBSTAT);
 
 	/* Fences */
 	switch (INTEL_INFO(dev)->gen) {
@@ -426,19 +425,19 @@
 
 
 	if (HAS_PCH_SPLIT(dev)) {
-		dpll_a_reg = PCH_DPLL_A;
-		dpll_b_reg = PCH_DPLL_B;
-		fpa0_reg = PCH_FPA0;
-		fpb0_reg = PCH_FPB0;
-		fpa1_reg = PCH_FPA1;
-		fpb1_reg = PCH_FPB1;
+		dpll_a_reg = _PCH_DPLL_A;
+		dpll_b_reg = _PCH_DPLL_B;
+		fpa0_reg = _PCH_FPA0;
+		fpb0_reg = _PCH_FPB0;
+		fpa1_reg = _PCH_FPA1;
+		fpb1_reg = _PCH_FPB1;
 	} else {
-		dpll_a_reg = DPLL_A;
-		dpll_b_reg = DPLL_B;
-		fpa0_reg = FPA0;
-		fpb0_reg = FPB0;
-		fpa1_reg = FPA1;
-		fpb1_reg = FPB1;
+		dpll_a_reg = _DPLL_A;
+		dpll_b_reg = _DPLL_B;
+		fpa0_reg = _FPA0;
+		fpb0_reg = _FPB0;
+		fpa1_reg = _FPA1;
+		fpb1_reg = _FPB1;
 	}
 
 	if (HAS_PCH_SPLIT(dev)) {
@@ -461,60 +460,60 @@
 	POSTING_READ(dpll_a_reg);
 	udelay(150);
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(DPLL_A_MD, dev_priv->saveDPLL_A_MD);
-		POSTING_READ(DPLL_A_MD);
+		I915_WRITE(_DPLL_A_MD, dev_priv->saveDPLL_A_MD);
+		POSTING_READ(_DPLL_A_MD);
 	}
 	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(_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);
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(BCLRPAT_A, dev_priv->saveBCLRPAT_A);
+		I915_WRITE(_BCLRPAT_A, dev_priv->saveBCLRPAT_A);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
-		I915_WRITE(PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
-		I915_WRITE(PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
-		I915_WRITE(PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
+		I915_WRITE(_PIPEA_DATA_M1, dev_priv->savePIPEA_DATA_M1);
+		I915_WRITE(_PIPEA_DATA_N1, dev_priv->savePIPEA_DATA_N1);
+		I915_WRITE(_PIPEA_LINK_M1, dev_priv->savePIPEA_LINK_M1);
+		I915_WRITE(_PIPEA_LINK_N1, dev_priv->savePIPEA_LINK_N1);
 
-		I915_WRITE(FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
-		I915_WRITE(FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
+		I915_WRITE(_FDI_RXA_CTL, dev_priv->saveFDI_RXA_CTL);
+		I915_WRITE(_FDI_TXA_CTL, dev_priv->saveFDI_TXA_CTL);
 
-		I915_WRITE(PFA_CTL_1, dev_priv->savePFA_CTL_1);
-		I915_WRITE(PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
-		I915_WRITE(PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
+		I915_WRITE(_PFA_CTL_1, dev_priv->savePFA_CTL_1);
+		I915_WRITE(_PFA_WIN_SZ, dev_priv->savePFA_WIN_SZ);
+		I915_WRITE(_PFA_WIN_POS, dev_priv->savePFA_WIN_POS);
 
-		I915_WRITE(TRANSACONF, dev_priv->saveTRANSACONF);
-		I915_WRITE(TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
-		I915_WRITE(TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
-		I915_WRITE(TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
-		I915_WRITE(TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
-		I915_WRITE(TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
-		I915_WRITE(TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_A);
+		I915_WRITE(_TRANSACONF, dev_priv->saveTRANSACONF);
+		I915_WRITE(_TRANS_HTOTAL_A, dev_priv->saveTRANS_HTOTAL_A);
+		I915_WRITE(_TRANS_HBLANK_A, dev_priv->saveTRANS_HBLANK_A);
+		I915_WRITE(_TRANS_HSYNC_A, dev_priv->saveTRANS_HSYNC_A);
+		I915_WRITE(_TRANS_VTOTAL_A, dev_priv->saveTRANS_VTOTAL_A);
+		I915_WRITE(_TRANS_VBLANK_A, dev_priv->saveTRANS_VBLANK_A);
+		I915_WRITE(_TRANS_VSYNC_A, dev_priv->saveTRANS_VSYNC_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);
+	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 (INTEL_INFO(dev)->gen >= 4) {
-		I915_WRITE(DSPASURF, dev_priv->saveDSPASURF);
-		I915_WRITE(DSPATILEOFF, dev_priv->saveDSPATILEOFF);
+		I915_WRITE(_DSPASURF, dev_priv->saveDSPASURF);
+		I915_WRITE(_DSPATILEOFF, dev_priv->saveDSPATILEOFF);
 	}
 
-	I915_WRITE(PIPEACONF, dev_priv->savePIPEACONF);
+	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));
+	I915_WRITE(_DSPACNTR, dev_priv->saveDSPACNTR);
+	I915_WRITE(_DSPAADDR, I915_READ(_DSPAADDR));
 
 	/* Pipe & plane B info */
 	if (dev_priv->saveDPLL_B & DPLL_VCO_ENABLE) {
@@ -530,68 +529,68 @@
 	POSTING_READ(dpll_b_reg);
 	udelay(150);
 	if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(DPLL_B_MD, dev_priv->saveDPLL_B_MD);
-		POSTING_READ(DPLL_B_MD);
+		I915_WRITE(_DPLL_B_MD, dev_priv->saveDPLL_B_MD);
+		POSTING_READ(_DPLL_B_MD);
 	}
 	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(_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);
 	if (!HAS_PCH_SPLIT(dev))
-		I915_WRITE(BCLRPAT_B, dev_priv->saveBCLRPAT_B);
+		I915_WRITE(_BCLRPAT_B, dev_priv->saveBCLRPAT_B);
 
 	if (HAS_PCH_SPLIT(dev)) {
-		I915_WRITE(PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
-		I915_WRITE(PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
-		I915_WRITE(PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
-		I915_WRITE(PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
+		I915_WRITE(_PIPEB_DATA_M1, dev_priv->savePIPEB_DATA_M1);
+		I915_WRITE(_PIPEB_DATA_N1, dev_priv->savePIPEB_DATA_N1);
+		I915_WRITE(_PIPEB_LINK_M1, dev_priv->savePIPEB_LINK_M1);
+		I915_WRITE(_PIPEB_LINK_N1, dev_priv->savePIPEB_LINK_N1);
 
-		I915_WRITE(FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
-		I915_WRITE(FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
+		I915_WRITE(_FDI_RXB_CTL, dev_priv->saveFDI_RXB_CTL);
+		I915_WRITE(_FDI_TXB_CTL, dev_priv->saveFDI_TXB_CTL);
 
-		I915_WRITE(PFB_CTL_1, dev_priv->savePFB_CTL_1);
-		I915_WRITE(PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
-		I915_WRITE(PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
+		I915_WRITE(_PFB_CTL_1, dev_priv->savePFB_CTL_1);
+		I915_WRITE(_PFB_WIN_SZ, dev_priv->savePFB_WIN_SZ);
+		I915_WRITE(_PFB_WIN_POS, dev_priv->savePFB_WIN_POS);
 
-		I915_WRITE(TRANSBCONF, dev_priv->saveTRANSBCONF);
-		I915_WRITE(TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
-		I915_WRITE(TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
-		I915_WRITE(TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
-		I915_WRITE(TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
-		I915_WRITE(TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
-		I915_WRITE(TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_B);
+		I915_WRITE(_TRANSBCONF, dev_priv->saveTRANSBCONF);
+		I915_WRITE(_TRANS_HTOTAL_B, dev_priv->saveTRANS_HTOTAL_B);
+		I915_WRITE(_TRANS_HBLANK_B, dev_priv->saveTRANS_HBLANK_B);
+		I915_WRITE(_TRANS_HSYNC_B, dev_priv->saveTRANS_HSYNC_B);
+		I915_WRITE(_TRANS_VTOTAL_B, dev_priv->saveTRANS_VTOTAL_B);
+		I915_WRITE(_TRANS_VBLANK_B, dev_priv->saveTRANS_VBLANK_B);
+		I915_WRITE(_TRANS_VSYNC_B, dev_priv->saveTRANS_VSYNC_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);
+	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 (INTEL_INFO(dev)->gen >= 4) {
-		I915_WRITE(DSPBSURF, dev_priv->saveDSPBSURF);
-		I915_WRITE(DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
+		I915_WRITE(_DSPBSURF, dev_priv->saveDSPBSURF);
+		I915_WRITE(_DSPBTILEOFF, dev_priv->saveDSPBTILEOFF);
 	}
 
-	I915_WRITE(PIPEBCONF, dev_priv->savePIPEBCONF);
+	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));
+	I915_WRITE(_DSPBCNTR, dev_priv->saveDSPBCNTR);
+	I915_WRITE(_DSPBADDR, I915_READ(_DSPBADDR));
 
 	/* 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);
+	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_GEN2(dev))
 		I915_WRITE(CURSIZE, dev_priv->saveCURSIZE);
 
@@ -653,14 +652,14 @@
 		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);
+		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 */
 
@@ -699,14 +698,14 @@
 
 	/* 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(_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);
 	}
 
 	/* This is only meaningful in non-KMS mode */
@@ -808,8 +807,8 @@
 		dev_priv->saveDEIMR = I915_READ(DEIMR);
 		dev_priv->saveGTIER = I915_READ(GTIER);
 		dev_priv->saveGTIMR = I915_READ(GTIMR);
-		dev_priv->saveFDI_RXA_IMR = I915_READ(FDI_RXA_IMR);
-		dev_priv->saveFDI_RXB_IMR = I915_READ(FDI_RXB_IMR);
+		dev_priv->saveFDI_RXA_IMR = I915_READ(_FDI_RXA_IMR);
+		dev_priv->saveFDI_RXB_IMR = I915_READ(_FDI_RXB_IMR);
 		dev_priv->saveMCHBAR_RENDER_STANDBY =
 			I915_READ(RSTDBYCTL);
 	} else {
@@ -857,11 +856,11 @@
 		I915_WRITE(DEIMR, dev_priv->saveDEIMR);
 		I915_WRITE(GTIER, dev_priv->saveGTIER);
 		I915_WRITE(GTIMR, dev_priv->saveGTIMR);
-		I915_WRITE(FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
-		I915_WRITE(FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
+		I915_WRITE(_FDI_RXA_IMR, dev_priv->saveFDI_RXA_IMR);
+		I915_WRITE(_FDI_RXB_IMR, dev_priv->saveFDI_RXB_IMR);
 	} else {
-		I915_WRITE (IER, dev_priv->saveIER);
-		I915_WRITE (IMR,  dev_priv->saveIMR);
+		I915_WRITE(IER, dev_priv->saveIER);
+		I915_WRITE(IMR, dev_priv->saveIMR);
 	}
 
 	/* Clock gating state */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_trace.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_trace.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/i915_trace.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/i915_trace.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,7 @@
 
 #include <drm/drmP.h>
 #include "i915_drv.h"
+#include "intel_ringbuffer.h"
 
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM i915
@@ -16,9 +17,7 @@
 /* object tracking */
 
 TRACE_EVENT(i915_gem_object_create,
-
 	    TP_PROTO(struct drm_i915_gem_object *obj),
-
 	    TP_ARGS(obj),
 
 	    TP_STRUCT__entry(
@@ -35,33 +34,51 @@
 );
 
 TRACE_EVENT(i915_gem_object_bind,
-
-	    TP_PROTO(struct drm_i915_gem_object *obj, u32 gtt_offset, bool mappable),
-
-	    TP_ARGS(obj, gtt_offset, mappable),
+	    TP_PROTO(struct drm_i915_gem_object *obj, bool mappable),
+	    TP_ARGS(obj, mappable),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
-			     __field(u32, gtt_offset)
+			     __field(u32, offset)
+			     __field(u32, size)
 			     __field(bool, mappable)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
-			   __entry->gtt_offset = gtt_offset;
+			   __entry->offset = obj->gtt_space->start;
+			   __entry->size = obj->gtt_space->size;
 			   __entry->mappable = mappable;
 			   ),
 
-	    TP_printk("obj=%p, gtt_offset=%08x%s",
-		      __entry->obj, __entry->gtt_offset,
+	    TP_printk("obj=%p, offset=%08x size=%x%s",
+		      __entry->obj, __entry->offset, __entry->size,
 		      __entry->mappable ? ", mappable" : "")
 );
 
-TRACE_EVENT(i915_gem_object_change_domain,
+TRACE_EVENT(i915_gem_object_unbind,
+	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_ARGS(obj),
 
-	    TP_PROTO(struct drm_i915_gem_object *obj, uint32_t old_read_domains, uint32_t old_write_domain),
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, offset)
+			     __field(u32, size)
+			     ),
 
-	    TP_ARGS(obj, old_read_domains, old_write_domain),
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->offset = obj->gtt_space->start;
+			   __entry->size = obj->gtt_space->size;
+			   ),
+
+	    TP_printk("obj=%p, offset=%08x size=%x",
+		      __entry->obj, __entry->offset, __entry->size)
+);
+
+TRACE_EVENT(i915_gem_object_change_domain,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 old_read, u32 old_write),
+	    TP_ARGS(obj, old_read, old_write),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
@@ -71,177 +88,264 @@
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
-			   __entry->read_domains = obj->base.read_domains | (old_read_domains << 16);
-			   __entry->write_domain = obj->base.write_domain | (old_write_domain << 16);
+			   __entry->read_domains = obj->base.read_domains | (old_read << 16);
+			   __entry->write_domain = obj->base.write_domain | (old_write << 16);
 			   ),
 
-	    TP_printk("obj=%p, read=%04x, write=%04x",
+	    TP_printk("obj=%p, read=%02x=>%02x, write=%02x=>%02x",
 		      __entry->obj,
-		      __entry->read_domains, __entry->write_domain)
+		      __entry->read_domains >> 16,
+		      __entry->read_domains & 0xffff,
+		      __entry->write_domain >> 16,
+		      __entry->write_domain & 0xffff)
 );
 
-DECLARE_EVENT_CLASS(i915_gem_object,
+TRACE_EVENT(i915_gem_object_pwrite,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len),
+	    TP_ARGS(obj, offset, len),
 
-	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, offset)
+			     __field(u32, len)
+			     ),
 
-	    TP_ARGS(obj),
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->offset = offset;
+			   __entry->len = len;
+			   ),
+
+	    TP_printk("obj=%p, offset=%u, len=%u",
+		      __entry->obj, __entry->offset, __entry->len)
+);
+
+TRACE_EVENT(i915_gem_object_pread,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 offset, u32 len),
+	    TP_ARGS(obj, offset, len),
 
 	    TP_STRUCT__entry(
 			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, offset)
+			     __field(u32, len)
 			     ),
 
 	    TP_fast_assign(
 			   __entry->obj = obj;
+			   __entry->offset = offset;
+			   __entry->len = len;
 			   ),
 
-	    TP_printk("obj=%p", __entry->obj)
+	    TP_printk("obj=%p, offset=%u, len=%u",
+		      __entry->obj, __entry->offset, __entry->len)
 );
 
-DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
+TRACE_EVENT(i915_gem_object_fault,
+	    TP_PROTO(struct drm_i915_gem_object *obj, u32 index, bool gtt, bool write),
+	    TP_ARGS(obj, index, gtt, write),
+
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     __field(u32, index)
+			     __field(bool, gtt)
+			     __field(bool, write)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   __entry->index = index;
+			   __entry->gtt = gtt;
+			   __entry->write = write;
+			   ),
 
+	    TP_printk("obj=%p, %s index=%u %s",
+		      __entry->obj,
+		      __entry->gtt ? "GTT" : "CPU",
+		      __entry->index,
+		      __entry->write ? ", writable" : "")
+);
+
+DECLARE_EVENT_CLASS(i915_gem_object,
 	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_ARGS(obj),
 
-	    TP_ARGS(obj)
+	    TP_STRUCT__entry(
+			     __field(struct drm_i915_gem_object *, obj)
+			     ),
+
+	    TP_fast_assign(
+			   __entry->obj = obj;
+			   ),
+
+	    TP_printk("obj=%p", __entry->obj)
 );
 
-DEFINE_EVENT(i915_gem_object, i915_gem_object_unbind,
+DEFINE_EVENT(i915_gem_object, i915_gem_object_clflush,
+	     TP_PROTO(struct drm_i915_gem_object *obj),
+	     TP_ARGS(obj)
+);
 
+DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
 	    TP_PROTO(struct drm_i915_gem_object *obj),
-
 	    TP_ARGS(obj)
 );
 
-DEFINE_EVENT(i915_gem_object, i915_gem_object_destroy,
+TRACE_EVENT(i915_gem_evict,
+	    TP_PROTO(struct drm_device *dev, u32 size, u32 align, bool mappable),
+	    TP_ARGS(dev, size, align, mappable),
 
-	    TP_PROTO(struct drm_i915_gem_object *obj),
+	    TP_STRUCT__entry(
+			     __field(u32, dev)
+			     __field(u32, size)
+			     __field(u32, align)
+			     __field(bool, mappable)
+			    ),
 
-	    TP_ARGS(obj)
+	    TP_fast_assign(
+			   __entry->dev = dev->primary->index;
+			   __entry->size = size;
+			   __entry->align = align;
+			   __entry->mappable = mappable;
+			  ),
+
+	    TP_printk("dev=%d, size=%d, align=%d %s",
+		      __entry->dev, __entry->size, __entry->align,
+		      __entry->mappable ? ", mappable" : "")
 );
 
-/* batch tracing */
+TRACE_EVENT(i915_gem_evict_everything,
+	    TP_PROTO(struct drm_device *dev, bool purgeable),
+	    TP_ARGS(dev, purgeable),
 
-TRACE_EVENT(i915_gem_request_submit,
+	    TP_STRUCT__entry(
+			     __field(u32, dev)
+			     __field(bool, purgeable)
+			    ),
 
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+	    TP_fast_assign(
+			   __entry->dev = dev->primary->index;
+			   __entry->purgeable = purgeable;
+			  ),
 
-	    TP_ARGS(dev, seqno),
+	    TP_printk("dev=%d%s",
+		      __entry->dev,
+		      __entry->purgeable ? ", purgeable only" : "")
+);
+
+TRACE_EVENT(i915_gem_ring_dispatch,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(u32, ring)
 			     __field(u32, seqno)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
 			   __entry->seqno = seqno;
-			   i915_trace_irq_get(dev, seqno);
+			   i915_trace_irq_get(ring, seqno);
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
+	    TP_printk("dev=%u, ring=%u, seqno=%u",
+		      __entry->dev, __entry->ring, __entry->seqno)
 );
 
-TRACE_EVENT(i915_gem_request_flush,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno,
-		     u32 flush_domains, u32 invalidate_domains),
-
-	    TP_ARGS(dev, seqno, flush_domains, invalidate_domains),
+TRACE_EVENT(i915_gem_ring_flush,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 invalidate, u32 flush),
+	    TP_ARGS(ring, invalidate, flush),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
-			     __field(u32, seqno)
-			     __field(u32, flush_domains)
-			     __field(u32, invalidate_domains)
+			     __field(u32, ring)
+			     __field(u32, invalidate)
+			     __field(u32, flush)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
-			   __entry->seqno = seqno;
-			   __entry->flush_domains = flush_domains;
-			   __entry->invalidate_domains = invalidate_domains;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
+			   __entry->invalidate = invalidate;
+			   __entry->flush = flush;
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u, flush=%04x, invalidate=%04x",
-		      __entry->dev, __entry->seqno,
-		      __entry->flush_domains, __entry->invalidate_domains)
+	    TP_printk("dev=%u, ring=%x, invalidate=%04x, flush=%04x",
+		      __entry->dev, __entry->ring,
+		      __entry->invalidate, __entry->flush)
 );
 
 DECLARE_EVENT_CLASS(i915_gem_request,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno),
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(u32, ring)
 			     __field(u32, seqno)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
 			   __entry->seqno = seqno;
 			   ),
 
-	    TP_printk("dev=%u, seqno=%u", __entry->dev, __entry->seqno)
+	    TP_printk("dev=%u, ring=%u, seqno=%u",
+		      __entry->dev, __entry->ring, __entry->seqno)
 );
 
-DEFINE_EVENT(i915_gem_request, i915_gem_request_complete,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
+DEFINE_EVENT(i915_gem_request, i915_gem_request_add,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
+);
 
-	    TP_ARGS(dev, seqno)
+DEFINE_EVENT(i915_gem_request, i915_gem_request_complete,
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_retire,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno)
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_begin,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno)
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DEFINE_EVENT(i915_gem_request, i915_gem_request_wait_end,
-
-	    TP_PROTO(struct drm_device *dev, u32 seqno),
-
-	    TP_ARGS(dev, seqno)
+	    TP_PROTO(struct intel_ring_buffer *ring, u32 seqno),
+	    TP_ARGS(ring, seqno)
 );
 
 DECLARE_EVENT_CLASS(i915_ring,
-
-	    TP_PROTO(struct drm_device *dev),
-
-	    TP_ARGS(dev),
+	    TP_PROTO(struct intel_ring_buffer *ring),
+	    TP_ARGS(ring),
 
 	    TP_STRUCT__entry(
 			     __field(u32, dev)
+			     __field(u32, ring)
 			     ),
 
 	    TP_fast_assign(
-			   __entry->dev = dev->primary->index;
+			   __entry->dev = ring->dev->primary->index;
+			   __entry->ring = ring->id;
 			   ),
 
-	    TP_printk("dev=%u", __entry->dev)
+	    TP_printk("dev=%u, ring=%u", __entry->dev, __entry->ring)
 );
 
 DEFINE_EVENT(i915_ring, i915_ring_wait_begin,
-
-	    TP_PROTO(struct drm_device *dev),
-
-	    TP_ARGS(dev)
+	    TP_PROTO(struct intel_ring_buffer *ring),
+	    TP_ARGS(ring)
 );
 
 DEFINE_EVENT(i915_ring, i915_ring_wait_end,
-
-	    TP_PROTO(struct drm_device *dev),
-
-	    TP_ARGS(dev)
+	    TP_PROTO(struct intel_ring_buffer *ring),
+	    TP_ARGS(ring)
 );
 
 TRACE_EVENT(i915_flip_request,
@@ -281,26 +385,29 @@
 );
 
 TRACE_EVENT(i915_reg_rw,
-           TP_PROTO(int cmd, uint32_t reg, uint64_t val, int len),
+           TP_PROTO(bool write, u32 reg, u64 val, int len),
 
-           TP_ARGS(cmd, reg, val, len),
+           TP_ARGS(write, reg, val, len),
 
            TP_STRUCT__entry(
-                   __field(int, cmd)
-                   __field(uint32_t, reg)
-                   __field(uint64_t, val)
-                   __field(int, len)
+                   __field(u64, val)
+                   __field(u32, reg)
+                   __field(u16, write)
+                   __field(u16, len)
                    ),
 
            TP_fast_assign(
-                   __entry->cmd = cmd;
+                   __entry->val = (u64)val;
                    __entry->reg = reg;
-                   __entry->val = (uint64_t)val;
+                   __entry->write = write;
                    __entry->len = len;
                    ),
 
-           TP_printk("cmd=%c, reg=0x%x, val=0x%llx, len=%d",
-                     __entry->cmd, __entry->reg, __entry->val, __entry->len)
+           TP_printk("%s reg=0x%x, len=%d, val=(0x%x, 0x%x)",
+                     __entry->write ? "write" : "read",
+		     __entry->reg, __entry->len,
+		     (u32)(__entry->val & 0xffffffff),
+		     (u32)(__entry->val >> 32))
 );
 
 #endif /* _I915_TRACE_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_bios.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_bios.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_bios.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_bios.c	2011-05-19 00:06:34.000000000 -0400
@@ -226,29 +226,49 @@
 parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
 		      struct bdb_header *bdb)
 {
-	struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 	struct lvds_dvo_timing *dvo_timing;
 	struct drm_display_mode *panel_fixed_mode;
+	int index;
 
-	sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
-	if (!sdvo_lvds_options)
-		return;
+	index = i915_vbt_sdvo_panel_type;
+	if (index == -1) {
+		struct bdb_sdvo_lvds_options *sdvo_lvds_options;
+
+		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+		if (!sdvo_lvds_options)
+			return;
+
+		index = sdvo_lvds_options->panel_type;
+	}
 
 	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
 	if (!dvo_timing)
 		return;
 
 	panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
-
 	if (!panel_fixed_mode)
 		return;
 
-	fill_detail_timing_data(panel_fixed_mode,
-			dvo_timing + sdvo_lvds_options->panel_type);
+	fill_detail_timing_data(panel_fixed_mode, dvo_timing + index);
 
 	dev_priv->sdvo_lvds_vbt_mode = panel_fixed_mode;
 
-	return;
+	DRM_DEBUG_KMS("Found SDVO panel mode in BIOS VBT tables:\n");
+	drm_mode_debug_printmodeline(panel_fixed_mode);
+}
+
+static int intel_bios_ssc_frequency(struct drm_device *dev,
+				    bool alternate)
+{
+	switch (INTEL_INFO(dev)->gen) {
+	case 2:
+		return alternate ? 66 : 48;
+	case 3:
+	case 4:
+		return alternate ? 100 : 96;
+	default:
+		return alternate ? 100 : 120;
+	}
 }
 
 static void
@@ -263,13 +283,8 @@
 		dev_priv->int_tv_support = general->int_tv_support;
 		dev_priv->int_crt_support = general->int_crt_support;
 		dev_priv->lvds_use_ssc = general->enable_ssc;
-
-		if (IS_I85X(dev))
-			dev_priv->lvds_ssc_freq = general->ssc_freq ? 66 : 48;
-		else if (IS_GEN5(dev) || IS_GEN6(dev))
-			dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 120;
-		else
-			dev_priv->lvds_ssc_freq = general->ssc_freq ? 100 : 96;
+		dev_priv->lvds_ssc_freq =
+			intel_bios_ssc_frequency(dev, general->ssc_freq);
 	}
 }
 
@@ -553,6 +568,8 @@
 static void
 init_vbt_defaults(struct drm_i915_private *dev_priv)
 {
+	struct drm_device *dev = dev_priv->dev;
+
 	dev_priv->crt_ddc_pin = GMBUS_PORT_VGADDC;
 
 	/* LFP panel data */
@@ -565,7 +582,11 @@
 	/* general features */
 	dev_priv->int_tv_support = 1;
 	dev_priv->int_crt_support = 1;
-	dev_priv->lvds_use_ssc = 0;
+
+	/* Default to using SSC */
+	dev_priv->lvds_use_ssc = 1;
+	dev_priv->lvds_ssc_freq = intel_bios_ssc_frequency(dev, 1);
+	DRM_DEBUG("Set default to SSC at %dMHz\n", dev_priv->lvds_ssc_freq);
 
 	/* eDP data */
 	dev_priv->edp.bpp = 18;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_crt.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_crt.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_crt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_crt.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,10 +129,7 @@
 	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;
+	dpll_md_reg = DPLL_MD(intel_crtc->pipe);
 
 	if (HAS_PCH_SPLIT(dev))
 		adpa_reg = PCH_ADPA;
@@ -160,17 +157,16 @@
 			adpa |= PORT_TRANS_A_SEL_CPT;
 		else
 			adpa |= ADPA_PIPE_A_SELECT;
-		if (!HAS_PCH_SPLIT(dev))
-			I915_WRITE(BCLRPAT_A, 0);
 	} else {
 		if (HAS_PCH_CPT(dev))
 			adpa |= PORT_TRANS_B_SEL_CPT;
 		else
 			adpa |= ADPA_PIPE_B_SELECT;
-		if (!HAS_PCH_SPLIT(dev))
-			I915_WRITE(BCLRPAT_B, 0);
 	}
 
+	if (!HAS_PCH_SPLIT(dev))
+		I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
+
 	I915_WRITE(adpa_reg, adpa);
 }
 
@@ -273,21 +269,6 @@
 	return ret;
 }
 
-static bool intel_crt_ddc_probe(struct drm_i915_private *dev_priv, int ddc_bus)
-{
-	u8 buf;
-	struct i2c_msg msgs[] = {
-		{
-			.addr = 0xA0,
-			.flags = 0,
-			.len = 1,
-			.buf = &buf,
-		},
-	};
-	/* DDC monitor detect: Does it ACK a write to 0xA0? */
-	return i2c_transfer(&dev_priv->gmbus[ddc_bus].adapter, msgs, 1) == 1;
-}
-
 static bool intel_crt_detect_ddc(struct drm_connector *connector)
 {
 	struct intel_crt *crt = intel_attached_crt(connector);
@@ -297,11 +278,6 @@
 	if (crt->base.type != INTEL_OUTPUT_ANALOG)
 		return false;
 
-	if (intel_crt_ddc_probe(dev_priv, dev_priv->crt_ddc_pin)) {
-		DRM_DEBUG_KMS("CRT detected via DDC:0xa0\n");
-		return true;
-	}
-
 	if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) {
 		struct edid *edid;
 		bool is_digital = false;
@@ -353,21 +329,12 @@
 
 	DRM_DEBUG_KMS("starting load-detect on CRT\n");
 
-	if (pipe == 0) {
-		bclrpat_reg = BCLRPAT_A;
-		vtotal_reg = VTOTAL_A;
-		vblank_reg = VBLANK_A;
-		vsync_reg = VSYNC_A;
-		pipeconf_reg = PIPEACONF;
-		pipe_dsl_reg = PIPEADSL;
-	} else {
-		bclrpat_reg = BCLRPAT_B;
-		vtotal_reg = VTOTAL_B;
-		vblank_reg = VBLANK_B;
-		vsync_reg = VSYNC_B;
-		pipeconf_reg = PIPEBCONF;
-		pipe_dsl_reg = PIPEBDSL;
-	}
+	bclrpat_reg = BCLRPAT(pipe);
+	vtotal_reg = VTOTAL(pipe);
+	vblank_reg = VBLANK(pipe);
+	vsync_reg = VSYNC(pipe);
+	pipeconf_reg = PIPECONF(pipe);
+	pipe_dsl_reg = PIPEDSL(pipe);
 
 	save_bclrpat = I915_READ(bclrpat_reg);
 	save_vtotal = I915_READ(vtotal_reg);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_display.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_display.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_display.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_display.c	2011-05-19 00:06:34.000000000 -0400
@@ -989,7 +989,7 @@
 void intel_wait_for_vblank(struct drm_device *dev, int pipe)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int pipestat_reg = (pipe == 0 ? PIPEASTAT : PIPEBSTAT);
+	int pipestat_reg = PIPESTAT(pipe);
 
 	/* Clear existing vblank status. Note this will clear any other
 	 * sticky status fields as well.
@@ -1058,6 +1058,616 @@
 	}
 }
 
+static const char *state_string(bool enabled)
+{
+	return enabled ? "on" : "off";
+}
+
+/* Only for pre-ILK configs */
+static void assert_pll(struct drm_i915_private *dev_priv,
+		       enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = DPLL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & DPLL_VCO_ENABLE);
+	WARN(cur_state != state,
+	     "PLL state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_pll_enabled(d, p) assert_pll(d, p, true)
+#define assert_pll_disabled(d, p) assert_pll(d, p, false)
+
+/* For ILK+ */
+static void assert_pch_pll(struct drm_i915_private *dev_priv,
+			   enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = PCH_DPLL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & DPLL_VCO_ENABLE);
+	WARN(cur_state != state,
+	     "PCH PLL state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_pch_pll_enabled(d, p) assert_pch_pll(d, p, true)
+#define assert_pch_pll_disabled(d, p) assert_pch_pll(d, p, false)
+
+static void assert_fdi_tx(struct drm_i915_private *dev_priv,
+			  enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = FDI_TX_CTL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & FDI_TX_ENABLE);
+	WARN(cur_state != state,
+	     "FDI TX state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_fdi_tx_enabled(d, p) assert_fdi_tx(d, p, true)
+#define assert_fdi_tx_disabled(d, p) assert_fdi_tx(d, p, false)
+
+static void assert_fdi_rx(struct drm_i915_private *dev_priv,
+			  enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = FDI_RX_CTL(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & FDI_RX_ENABLE);
+	WARN(cur_state != state,
+	     "FDI RX state assertion failure (expected %s, current %s)\n",
+	     state_string(state), state_string(cur_state));
+}
+#define assert_fdi_rx_enabled(d, p) assert_fdi_rx(d, p, true)
+#define assert_fdi_rx_disabled(d, p) assert_fdi_rx(d, p, false)
+
+static void assert_fdi_tx_pll_enabled(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* ILK FDI PLL is always enabled */
+	if (dev_priv->info->gen == 5)
+		return;
+
+	reg = FDI_TX_CTL(pipe);
+	val = I915_READ(reg);
+	WARN(!(val & FDI_TX_PLL_ENABLE), "FDI TX PLL assertion failure, should be active but is disabled\n");
+}
+
+static void assert_fdi_rx_pll_enabled(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	reg = FDI_RX_CTL(pipe);
+	val = I915_READ(reg);
+	WARN(!(val & FDI_RX_PLL_ENABLE), "FDI RX PLL assertion failure, should be active but is disabled\n");
+}
+
+static void assert_panel_unlocked(struct drm_i915_private *dev_priv,
+				  enum pipe pipe)
+{
+	int pp_reg, lvds_reg;
+	u32 val;
+	enum pipe panel_pipe = PIPE_A;
+	bool locked = locked;
+
+	if (HAS_PCH_SPLIT(dev_priv->dev)) {
+		pp_reg = PCH_PP_CONTROL;
+		lvds_reg = PCH_LVDS;
+	} else {
+		pp_reg = PP_CONTROL;
+		lvds_reg = LVDS;
+	}
+
+	val = I915_READ(pp_reg);
+	if (!(val & PANEL_POWER_ON) ||
+	    ((val & PANEL_UNLOCK_REGS) == PANEL_UNLOCK_REGS))
+		locked = false;
+
+	if (I915_READ(lvds_reg) & LVDS_PIPEB_SELECT)
+		panel_pipe = PIPE_B;
+
+	WARN(panel_pipe == pipe && locked,
+	     "panel assertion failure, pipe %c regs locked\n",
+	     pipe_name(pipe));
+}
+
+static void assert_pipe(struct drm_i915_private *dev_priv,
+			enum pipe pipe, bool state)
+{
+	int reg;
+	u32 val;
+	bool cur_state;
+
+	reg = PIPECONF(pipe);
+	val = I915_READ(reg);
+	cur_state = !!(val & PIPECONF_ENABLE);
+	WARN(cur_state != state,
+	     "pipe %c assertion failure (expected %s, current %s)\n",
+	     pipe_name(pipe), state_string(state), state_string(cur_state));
+}
+#define assert_pipe_enabled(d, p) assert_pipe(d, p, true)
+#define assert_pipe_disabled(d, p) assert_pipe(d, p, false)
+
+static void assert_plane_enabled(struct drm_i915_private *dev_priv,
+				 enum plane plane)
+{
+	int reg;
+	u32 val;
+
+	reg = DSPCNTR(plane);
+	val = I915_READ(reg);
+	WARN(!(val & DISPLAY_PLANE_ENABLE),
+	     "plane %c assertion failure, should be active but is disabled\n",
+	     plane_name(plane));
+}
+
+static void assert_planes_disabled(struct drm_i915_private *dev_priv,
+				   enum pipe pipe)
+{
+	int reg, i;
+	u32 val;
+	int cur_pipe;
+
+	/* Planes are fixed to pipes on ILK+ */
+	if (HAS_PCH_SPLIT(dev_priv->dev))
+		return;
+
+	/* Need to check both planes against the pipe */
+	for (i = 0; i < 2; i++) {
+		reg = DSPCNTR(i);
+		val = I915_READ(reg);
+		cur_pipe = (val & DISPPLANE_SEL_PIPE_MASK) >>
+			DISPPLANE_SEL_PIPE_SHIFT;
+		WARN((val & DISPLAY_PLANE_ENABLE) && pipe == cur_pipe,
+		     "plane %c assertion failure, should be off on pipe %c but is still active\n",
+		     plane_name(i), pipe_name(pipe));
+	}
+}
+
+static void assert_pch_refclk_enabled(struct drm_i915_private *dev_priv)
+{
+	u32 val;
+	bool enabled;
+
+	val = I915_READ(PCH_DREF_CONTROL);
+	enabled = !!(val & (DREF_SSC_SOURCE_MASK | DREF_NONSPREAD_SOURCE_MASK |
+			    DREF_SUPERSPREAD_SOURCE_MASK));
+	WARN(!enabled, "PCH refclk assertion failure, should be active but is disabled\n");
+}
+
+static void assert_transcoder_disabled(struct drm_i915_private *dev_priv,
+				       enum pipe pipe)
+{
+	int reg;
+	u32 val;
+	bool enabled;
+
+	reg = TRANSCONF(pipe);
+	val = I915_READ(reg);
+	enabled = !!(val & TRANS_ENABLE);
+	WARN(enabled,
+	     "transcoder assertion failed, should be off on pipe %c but is still active\n",
+	     pipe_name(pipe));
+}
+
+static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
+				   enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	WARN(DP_PIPE_ENABLED(val, pipe),
+	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
+	     reg, pipe_name(pipe));
+}
+
+static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
+				     enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	WARN(HDMI_PIPE_ENABLED(val, pipe),
+	     "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
+	     reg, pipe_name(pipe));
+}
+
+static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
+				      enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_B);
+	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_C);
+	assert_pch_dp_disabled(dev_priv, pipe, PCH_DP_D);
+
+	reg = PCH_ADPA;
+	val = I915_READ(reg);
+	WARN(ADPA_PIPE_ENABLED(val, pipe),
+	     "PCH VGA enabled on transcoder %c, should be disabled\n",
+	     pipe_name(pipe));
+
+	reg = PCH_LVDS;
+	val = I915_READ(reg);
+	WARN(LVDS_PIPE_ENABLED(val, pipe),
+	     "PCH LVDS enabled on transcoder %c, should be disabled\n",
+	     pipe_name(pipe));
+
+	assert_pch_hdmi_disabled(dev_priv, pipe, HDMIB);
+	assert_pch_hdmi_disabled(dev_priv, pipe, HDMIC);
+	assert_pch_hdmi_disabled(dev_priv, pipe, HDMID);
+}
+
+/**
+ * intel_enable_pll - enable a PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * Enable @pipe's PLL so we can start pumping pixels from a plane.  Check to
+ * make sure the PLL reg is writable first though, since the panel write
+ * protect mechanism may be enabled.
+ *
+ * Note!  This is for pre-ILK only.
+ */
+static void intel_enable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* No really, not for ILK+ */
+	BUG_ON(dev_priv->info->gen >= 5);
+
+	/* PLL is protected by panel, make sure we can write it */
+	if (IS_MOBILE(dev_priv->dev) && !IS_I830(dev_priv->dev))
+		assert_panel_unlocked(dev_priv, pipe);
+
+	reg = DPLL(pipe);
+	val = I915_READ(reg);
+	val |= DPLL_VCO_ENABLE;
+
+	/* We do this three times for luck */
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(150); /* wait for warmup */
+}
+
+/**
+ * intel_disable_pll - disable a PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to disable
+ *
+ * Disable the PLL for @pipe, making sure the pipe is off first.
+ *
+ * Note!  This is for pre-ILK only.
+ */
+static void intel_disable_pll(struct drm_i915_private *dev_priv, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* Don't disable pipe A or pipe A PLLs if needed */
+	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+		return;
+
+	/* Make sure the pipe isn't still relying on us */
+	assert_pipe_disabled(dev_priv, pipe);
+
+	reg = DPLL(pipe);
+	val = I915_READ(reg);
+	val &= ~DPLL_VCO_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+}
+
+/**
+ * intel_enable_pch_pll - enable PCH PLL
+ * @dev_priv: i915 private structure
+ * @pipe: pipe PLL to enable
+ *
+ * The PCH PLL needs to be enabled before the PCH transcoder, since it
+ * drives the transcoder clock.
+ */
+static void intel_enable_pch_pll(struct drm_i915_private *dev_priv,
+				 enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* PCH refclock must be enabled first */
+	assert_pch_refclk_enabled(dev_priv);
+
+	reg = PCH_DPLL(pipe);
+	val = I915_READ(reg);
+	val |= DPLL_VCO_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(200);
+}
+
+static void intel_disable_pch_pll(struct drm_i915_private *dev_priv,
+				  enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* Make sure transcoder isn't still depending on us */
+	assert_transcoder_disabled(dev_priv, pipe);
+
+	reg = PCH_DPLL(pipe);
+	val = I915_READ(reg);
+	val &= ~DPLL_VCO_ENABLE;
+	I915_WRITE(reg, val);
+	POSTING_READ(reg);
+	udelay(200);
+}
+
+static void intel_enable_transcoder(struct drm_i915_private *dev_priv,
+				    enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* PCH only available on ILK+ */
+	BUG_ON(dev_priv->info->gen < 5);
+
+	/* Make sure PCH DPLL is enabled */
+	assert_pch_pll_enabled(dev_priv, pipe);
+
+	/* FDI must be feeding us bits for PCH ports */
+	assert_fdi_tx_enabled(dev_priv, pipe);
+	assert_fdi_rx_enabled(dev_priv, pipe);
+
+	reg = TRANSCONF(pipe);
+	val = I915_READ(reg);
+	/*
+	 * make the BPC in transcoder be consistent with
+	 * that in pipeconf reg.
+	 */
+	val &= ~PIPE_BPC_MASK;
+	val |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
+	I915_WRITE(reg, val | TRANS_ENABLE);
+	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
+		DRM_ERROR("failed to enable transcoder %d\n", pipe);
+}
+
+static void intel_disable_transcoder(struct drm_i915_private *dev_priv,
+				     enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* FDI relies on the transcoder */
+	assert_fdi_tx_disabled(dev_priv, pipe);
+	assert_fdi_rx_disabled(dev_priv, pipe);
+
+	/* Ports must be off as well */
+	assert_pch_ports_disabled(dev_priv, pipe);
+
+	reg = TRANSCONF(pipe);
+	val = I915_READ(reg);
+	val &= ~TRANS_ENABLE;
+	I915_WRITE(reg, val);
+	/* wait for PCH transcoder off, transcoder state */
+	if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
+		DRM_ERROR("failed to disable transcoder\n");
+}
+
+/**
+ * intel_enable_pipe - enable a pipe, asserting requirements
+ * @dev_priv: i915 private structure
+ * @pipe: pipe to enable
+ * @pch_port: on ILK+, is this pipe driving a PCH port or not
+ *
+ * Enable @pipe, making sure that various hardware specific requirements
+ * are met, if applicable, e.g. PLL enabled, LVDS pairs enabled, etc.
+ *
+ * @pipe should be %PIPE_A or %PIPE_B.
+ *
+ * Will wait until the pipe is actually running (i.e. first vblank) before
+ * returning.
+ */
+static void intel_enable_pipe(struct drm_i915_private *dev_priv, enum pipe pipe,
+			      bool pch_port)
+{
+	int reg;
+	u32 val;
+
+	/*
+	 * A pipe without a PLL won't actually be able to drive bits from
+	 * a plane.  On ILK+ the pipe PLLs are integrated, so we don't
+	 * need the check.
+	 */
+	if (!HAS_PCH_SPLIT(dev_priv->dev))
+		assert_pll_enabled(dev_priv, pipe);
+	else {
+		if (pch_port) {
+			/* if driving the PCH, we need FDI enabled */
+			assert_fdi_rx_pll_enabled(dev_priv, pipe);
+			assert_fdi_tx_pll_enabled(dev_priv, pipe);
+		}
+		/* FIXME: assert CPU port conditions for SNB+ */
+	}
+
+	reg = PIPECONF(pipe);
+	val = I915_READ(reg);
+	if (val & PIPECONF_ENABLE)
+		return;
+
+	I915_WRITE(reg, val | PIPECONF_ENABLE);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
+}
+
+/**
+ * intel_disable_pipe - disable a pipe, asserting requirements
+ * @dev_priv: i915 private structure
+ * @pipe: pipe to disable
+ *
+ * Disable @pipe, making sure that various hardware specific requirements
+ * are met, if applicable, e.g. plane disabled, panel fitter off, etc.
+ *
+ * @pipe should be %PIPE_A or %PIPE_B.
+ *
+ * Will wait until the pipe has shut down before returning.
+ */
+static void intel_disable_pipe(struct drm_i915_private *dev_priv,
+			       enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/*
+	 * Make sure planes won't keep trying to pump pixels to us,
+	 * or we might hang the display.
+	 */
+	assert_planes_disabled(dev_priv, pipe);
+
+	/* Don't disable pipe A or pipe A PLLs if needed */
+	if (pipe == PIPE_A && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
+		return;
+
+	reg = PIPECONF(pipe);
+	val = I915_READ(reg);
+	if ((val & PIPECONF_ENABLE) == 0)
+		return;
+
+	I915_WRITE(reg, val & ~PIPECONF_ENABLE);
+	intel_wait_for_pipe_off(dev_priv->dev, pipe);
+}
+
+/**
+ * intel_enable_plane - enable a display plane on a given pipe
+ * @dev_priv: i915 private structure
+ * @plane: plane to enable
+ * @pipe: pipe being fed
+ *
+ * Enable @plane on @pipe, making sure that @pipe is running first.
+ */
+static void intel_enable_plane(struct drm_i915_private *dev_priv,
+			       enum plane plane, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	/* If the pipe isn't enabled, we can't pump pixels and may hang */
+	assert_pipe_enabled(dev_priv, pipe);
+
+	reg = DSPCNTR(plane);
+	val = I915_READ(reg);
+	if (val & DISPLAY_PLANE_ENABLE)
+		return;
+
+	I915_WRITE(reg, val | DISPLAY_PLANE_ENABLE);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
+}
+
+/*
+ * Plane regs are double buffered, going from enabled->disabled needs a
+ * trigger in order to latch.  The display address reg provides this.
+ */
+static void intel_flush_display_plane(struct drm_i915_private *dev_priv,
+				      enum plane plane)
+{
+	u32 reg = DSPADDR(plane);
+	I915_WRITE(reg, I915_READ(reg));
+}
+
+/**
+ * intel_disable_plane - disable a display plane
+ * @dev_priv: i915 private structure
+ * @plane: plane to disable
+ * @pipe: pipe consuming the data
+ *
+ * Disable @plane; should be an independent operation.
+ */
+static void intel_disable_plane(struct drm_i915_private *dev_priv,
+				enum plane plane, enum pipe pipe)
+{
+	int reg;
+	u32 val;
+
+	reg = DSPCNTR(plane);
+	val = I915_READ(reg);
+	if ((val & DISPLAY_PLANE_ENABLE) == 0)
+		return;
+
+	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
+	intel_flush_display_plane(dev_priv, plane);
+	intel_wait_for_vblank(dev_priv->dev, pipe);
+}
+
+static void disable_pch_dp(struct drm_i915_private *dev_priv,
+			   enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	if (DP_PIPE_ENABLED(val, pipe))
+		I915_WRITE(reg, val & ~DP_PORT_EN);
+}
+
+static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
+			     enum pipe pipe, int reg)
+{
+	u32 val = I915_READ(reg);
+	if (HDMI_PIPE_ENABLED(val, pipe))
+		I915_WRITE(reg, val & ~PORT_ENABLE);
+}
+
+/* Disable any ports connected to this transcoder */
+static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
+				    enum pipe pipe)
+{
+	u32 reg, val;
+
+	val = I915_READ(PCH_PP_CONTROL);
+	I915_WRITE(PCH_PP_CONTROL, val | PANEL_UNLOCK_REGS);
+
+	disable_pch_dp(dev_priv, pipe, PCH_DP_B);
+	disable_pch_dp(dev_priv, pipe, PCH_DP_C);
+	disable_pch_dp(dev_priv, pipe, PCH_DP_D);
+
+	reg = PCH_ADPA;
+	val = I915_READ(reg);
+	if (ADPA_PIPE_ENABLED(val, pipe))
+		I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
+
+	reg = PCH_LVDS;
+	val = I915_READ(reg);
+	if (LVDS_PIPE_ENABLED(val, pipe)) {
+		I915_WRITE(reg, val & ~LVDS_PORT_EN);
+		POSTING_READ(reg);
+		udelay(100);
+	}
+
+	disable_pch_hdmi(dev_priv, pipe, HDMIB);
+	disable_pch_hdmi(dev_priv, pipe, HDMIC);
+	disable_pch_hdmi(dev_priv, pipe, HDMID);
+}
+
 static void i8xx_enable_fbc(struct drm_crtc *crtc, unsigned long interval)
 {
 	struct drm_device *dev = crtc->dev;
@@ -1163,7 +1773,6 @@
 			return;
 
 		I915_WRITE(DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-		POSTING_READ(DPFC_CONTROL);
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
 	}
 
@@ -1255,7 +1864,6 @@
 			return;
 
 		I915_WRITE(ILK_DPFC_CONTROL, dpfc_ctl & ~DPFC_CTL_EN);
-		POSTING_READ(ILK_DPFC_CONTROL);
 		intel_wait_for_vblank(dev, intel_crtc->pipe);
 	}
 
@@ -1390,7 +1998,7 @@
 	 *   - going to an unsupported config (interlace, pixel multiply, etc.)
 	 */
 	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-		if (tmp_crtc->enabled) {
+		if (tmp_crtc->enabled && tmp_crtc->fb) {
 			if (crtc) {
 				DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
 				dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
@@ -1461,6 +2069,7 @@
 			   struct drm_i915_gem_object *obj,
 			   struct intel_ring_buffer *pipelined)
 {
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	u32 alignment;
 	int ret;
 
@@ -1485,9 +2094,10 @@
 		BUG();
 	}
 
+	dev_priv->mm.interruptible = false;
 	ret = i915_gem_object_pin(obj, alignment, true);
 	if (ret)
-		return ret;
+		goto err_interruptible;
 
 	ret = i915_gem_object_set_to_display_plane(obj, pipelined);
 	if (ret)
@@ -1499,15 +2109,18 @@
 	 * a fence as the cost is not that onerous.
 	 */
 	if (obj->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence(obj, pipelined, false);
+		ret = i915_gem_object_get_fence(obj, pipelined);
 		if (ret)
 			goto err_unpin;
 	}
 
+	dev_priv->mm.interruptible = true;
 	return 0;
 
 err_unpin:
 	i915_gem_object_unpin(obj);
+err_interruptible:
+	dev_priv->mm.interruptible = true;
 	return ret;
 }
 
@@ -1641,7 +2254,7 @@
 		 * This should only fail upon a hung GPU, in which case we
 		 * can safely continue.
 		 */
-		ret = i915_gem_object_flush_gpu(obj, false);
+		ret = i915_gem_object_flush_gpu(obj);
 		(void) ret;
 	}
 
@@ -1753,8 +2366,13 @@
 	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;
 	u32 reg, temp, tries;
 
+	/* FDI needs bits from pipe & plane first */
+	assert_pipe_enabled(dev_priv, pipe);
+	assert_plane_enabled(dev_priv, plane);
+
 	/* Train 1: umask FDI RX Interrupt symbol_lock and bit_lock bit
 	   for train result */
 	reg = FDI_RX_IMR(pipe);
@@ -1784,7 +2402,11 @@
 	udelay(150);
 
 	/* Ironlake workaround, enable clock pointer after FDI enable*/
-	I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_ENABLE);
+	if (HAS_PCH_IBX(dev)) {
+		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
+		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR |
+			   FDI_RX_PHASE_SYNC_POINTER_EN);
+	}
 
 	reg = FDI_RX_IIR(pipe);
 	for (tries = 0; tries < 5; tries++) {
@@ -1834,7 +2456,7 @@
 
 }
 
-static const int const snb_b_fdi_train_param [] = {
+static const int snb_b_fdi_train_param [] = {
 	FDI_LINK_TRAIN_400MV_0DB_SNB_B,
 	FDI_LINK_TRAIN_400MV_6DB_SNB_B,
 	FDI_LINK_TRAIN_600MV_3_5DB_SNB_B,
@@ -2003,12 +2625,60 @@
 	}
 }
 
-static void intel_flush_display_plane(struct drm_device *dev,
-				      int plane)
+static void ironlake_fdi_disable(struct drm_crtc *crtc)
 {
+	struct drm_device *dev = crtc->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	u32 reg = DSPADDR(plane);
-	I915_WRITE(reg, I915_READ(reg));
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
+	int pipe = intel_crtc->pipe;
+	u32 reg, temp;
+
+	/* disable CPU FDI tx and PCH FDI rx */
+	reg = FDI_TX_CTL(pipe);
+	temp = I915_READ(reg);
+	I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
+	POSTING_READ(reg);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	temp &= ~(0x7 << 16);
+	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
+
+	POSTING_READ(reg);
+	udelay(100);
+
+	/* Ironlake workaround, disable clock pointer after downing FDI */
+	if (HAS_PCH_IBX(dev)) {
+		I915_WRITE(FDI_RX_CHICKEN(pipe), FDI_RX_PHASE_SYNC_POINTER_OVR);
+		I915_WRITE(FDI_RX_CHICKEN(pipe),
+			   I915_READ(FDI_RX_CHICKEN(pipe) &
+				     ~FDI_RX_PHASE_SYNC_POINTER_EN));
+	}
+
+	/* still set train pattern 1 */
+	reg = FDI_TX_CTL(pipe);
+	temp = I915_READ(reg);
+	temp &= ~FDI_LINK_TRAIN_NONE;
+	temp |= FDI_LINK_TRAIN_PATTERN_1;
+	I915_WRITE(reg, temp);
+
+	reg = FDI_RX_CTL(pipe);
+	temp = I915_READ(reg);
+	if (HAS_PCH_CPT(dev)) {
+		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
+		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
+	} else {
+		temp &= ~FDI_LINK_TRAIN_NONE;
+		temp |= FDI_LINK_TRAIN_PATTERN_1;
+	}
+	/* BPC in FDI rx is consistent with that in PIPECONF */
+	temp &= ~(0x07 << 16);
+	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
+	I915_WRITE(reg, temp);
+
+	POSTING_READ(reg);
+	udelay(100);
 }
 
 /*
@@ -2070,114 +2740,21 @@
 	return true;
 }
 
-static void ironlake_crtc_enable(struct drm_crtc *crtc)
+/*
+ * Enable PCH resources required for PCH ports:
+ *   - PCH PLLs
+ *   - FDI training & RX/TX
+ *   - update transcoder timings
+ *   - DP transcoding bits
+ *   - transcoder
+ */
+static void ironlake_pch_enable(struct drm_crtc *crtc)
 {
 	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;
 	u32 reg, temp;
-	bool is_pch_port = false;
-
-	if (intel_crtc->active)
-		return;
-
-	intel_crtc->active = true;
-	intel_update_watermarks(dev);
-
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		temp = I915_READ(PCH_LVDS);
-		if ((temp & LVDS_PORT_EN) == 0)
-			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
-	}
-
-	is_pch_port = intel_crtc_driving_pch(crtc);
-
-	if (is_pch_port)
-		ironlake_fdi_enable(crtc);
-	else {
-		/* disable CPU FDI tx and PCH FDI rx */
-		reg = FDI_TX_CTL(pipe);
-		temp = I915_READ(reg);
-		I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
-		POSTING_READ(reg);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = I915_READ(reg);
-		temp &= ~(0x7 << 16);
-		temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-		I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
-
-		POSTING_READ(reg);
-		udelay(100);
-
-		/* Ironlake workaround, disable clock pointer after downing FDI */
-		if (HAS_PCH_IBX(dev))
-			I915_WRITE(FDI_RX_CHICKEN(pipe),
-				   I915_READ(FDI_RX_CHICKEN(pipe) &
-					     ~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
-
-		/* still set train pattern 1 */
-		reg = FDI_TX_CTL(pipe);
-		temp = I915_READ(reg);
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_1;
-		I915_WRITE(reg, temp);
-
-		reg = FDI_RX_CTL(pipe);
-		temp = I915_READ(reg);
-		if (HAS_PCH_CPT(dev)) {
-			temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-			temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-		} else {
-			temp &= ~FDI_LINK_TRAIN_NONE;
-			temp |= FDI_LINK_TRAIN_PATTERN_1;
-		}
-		/* BPC in FDI rx is consistent with that in PIPECONF */
-		temp &= ~(0x07 << 16);
-		temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-		I915_WRITE(reg, temp);
-
-		POSTING_READ(reg);
-		udelay(100);
-	}
-
-	/* Enable panel fitting for LVDS */
-	if (dev_priv->pch_pf_size &&
-	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
-		/* Force use of hard-coded filter coefficients
-		 * as some pre-programmed values are broken,
-		 * e.g. x201.
-		 */
-		I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1,
-			   PF_ENABLE | PF_FILTER_MED_3x3);
-		I915_WRITE(pipe ? PFB_WIN_POS : PFA_WIN_POS,
-			   dev_priv->pch_pf_pos);
-		I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ,
-			   dev_priv->pch_pf_size);
-	}
-
-	/* Enable CPU pipe */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if ((temp & PIPECONF_ENABLE) == 0) {
-		I915_WRITE(reg, temp | PIPECONF_ENABLE);
-		POSTING_READ(reg);
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
-	}
-
-	/* configure and enable CPU plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-		I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
-		intel_flush_display_plane(dev, plane);
-	}
-
-	/* Skip the PCH stuff if possible */
-	if (!is_pch_port)
-		goto done;
 
 	/* For PCH output, training FDI link */
 	if (IS_GEN6(dev))
@@ -2185,14 +2762,7 @@
 	else
 		ironlake_fdi_link_train(crtc);
 
-	/* enable PCH DPLL */
-	reg = PCH_DPLL(pipe);
-	temp = I915_READ(reg);
-	if ((temp & DPLL_VCO_ENABLE) == 0) {
-		I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-		POSTING_READ(reg);
-		udelay(200);
-	}
+	intel_enable_pch_pll(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
 		/* Be sure PCH DPLL SEL is set */
@@ -2204,7 +2774,8 @@
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
-	/* set transcoder timing */
+	/* set transcoder timing, panel must allow it */
+	assert_panel_unlocked(dev_priv, pipe);
 	I915_WRITE(TRANS_HTOTAL(pipe), I915_READ(HTOTAL(pipe)));
 	I915_WRITE(TRANS_HBLANK(pipe), I915_READ(HBLANK(pipe)));
 	I915_WRITE(TRANS_HSYNC(pipe),  I915_READ(HSYNC(pipe)));
@@ -2251,19 +2822,56 @@
 		I915_WRITE(reg, temp);
 	}
 
-	/* enable PCH transcoder */
-	reg = TRANSCONF(pipe);
-	temp = I915_READ(reg);
-	/*
-	 * make the BPC in transcoder be consistent with
-	 * that in pipeconf reg.
-	 */
-	temp &= ~PIPE_BPC_MASK;
-	temp |= I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK;
-	I915_WRITE(reg, temp | TRANS_ENABLE);
-	if (wait_for(I915_READ(reg) & TRANS_STATE_ENABLE, 100))
-		DRM_ERROR("failed to enable transcoder %d\n", pipe);
-done:
+	intel_enable_transcoder(dev_priv, pipe);
+}
+
+static void ironlake_crtc_enable(struct drm_crtc *crtc)
+{
+	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;
+	u32 temp;
+	bool is_pch_port;
+
+	if (intel_crtc->active)
+		return;
+
+	intel_crtc->active = true;
+	intel_update_watermarks(dev);
+
+	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
+		temp = I915_READ(PCH_LVDS);
+		if ((temp & LVDS_PORT_EN) == 0)
+			I915_WRITE(PCH_LVDS, temp | LVDS_PORT_EN);
+	}
+
+	is_pch_port = intel_crtc_driving_pch(crtc);
+
+	if (is_pch_port)
+		ironlake_fdi_enable(crtc);
+	else
+		ironlake_fdi_disable(crtc);
+
+	/* Enable panel fitting for LVDS */
+	if (dev_priv->pch_pf_size &&
+	    (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS) || HAS_eDP)) {
+		/* Force use of hard-coded filter coefficients
+		 * as some pre-programmed values are broken,
+		 * e.g. x201.
+		 */
+		I915_WRITE(PF_CTL(pipe), PF_ENABLE | PF_FILTER_MED_3x3);
+		I915_WRITE(PF_WIN_POS(pipe), dev_priv->pch_pf_pos);
+		I915_WRITE(PF_WIN_SZ(pipe), dev_priv->pch_pf_size);
+	}
+
+	intel_enable_pipe(dev_priv, pipe, is_pch_port);
+	intel_enable_plane(dev_priv, plane, pipe);
+
+	if (is_pch_port)
+		ironlake_pch_enable(crtc);
+
 	intel_crtc_load_lut(crtc);
 	intel_update_fbc(dev);
 	intel_crtc_update_cursor(crtc, true);
@@ -2285,116 +2893,58 @@
 	drm_vblank_off(dev, pipe);
 	intel_crtc_update_cursor(crtc, false);
 
-	/* Disable display plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if (temp & DISPLAY_PLANE_ENABLE) {
-		I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
-		intel_flush_display_plane(dev, plane);
-	}
+	intel_disable_plane(dev_priv, plane, pipe);
 
 	if (dev_priv->cfb_plane == plane &&
 	    dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
 
-	/* disable cpu pipe, disable after all planes disabled */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if (temp & PIPECONF_ENABLE) {
-		I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
-		POSTING_READ(reg);
-		/* wait for cpu pipe off, pipe state */
-		intel_wait_for_pipe_off(dev, intel_crtc->pipe);
-	}
+	intel_disable_pipe(dev_priv, pipe);
 
 	/* Disable PF */
-	I915_WRITE(pipe ? PFB_CTL_1 : PFA_CTL_1, 0);
-	I915_WRITE(pipe ? PFB_WIN_SZ : PFA_WIN_SZ, 0);
-
-	/* disable CPU FDI tx and PCH FDI rx */
-	reg = FDI_TX_CTL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~FDI_TX_ENABLE);
-	POSTING_READ(reg);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	temp &= ~(0x7 << 16);
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-	I915_WRITE(reg, temp & ~FDI_RX_ENABLE);
-
-	POSTING_READ(reg);
-	udelay(100);
-
-	/* Ironlake workaround, disable clock pointer after downing FDI */
-	if (HAS_PCH_IBX(dev))
-		I915_WRITE(FDI_RX_CHICKEN(pipe),
-			   I915_READ(FDI_RX_CHICKEN(pipe) &
-				     ~FDI_RX_PHASE_SYNC_POINTER_ENABLE));
-
-	/* still set train pattern 1 */
-	reg = FDI_TX_CTL(pipe);
-	temp = I915_READ(reg);
-	temp &= ~FDI_LINK_TRAIN_NONE;
-	temp |= FDI_LINK_TRAIN_PATTERN_1;
-	I915_WRITE(reg, temp);
-
-	reg = FDI_RX_CTL(pipe);
-	temp = I915_READ(reg);
-	if (HAS_PCH_CPT(dev)) {
-		temp &= ~FDI_LINK_TRAIN_PATTERN_MASK_CPT;
-		temp |= FDI_LINK_TRAIN_PATTERN_1_CPT;
-	} else {
-		temp &= ~FDI_LINK_TRAIN_NONE;
-		temp |= FDI_LINK_TRAIN_PATTERN_1;
-	}
-	/* BPC in FDI rx is consistent with that in PIPECONF */
-	temp &= ~(0x07 << 16);
-	temp |= (I915_READ(PIPECONF(pipe)) & PIPE_BPC_MASK) << 11;
-	I915_WRITE(reg, temp);
+	I915_WRITE(PF_CTL(pipe), 0);
+	I915_WRITE(PF_WIN_SZ(pipe), 0);
 
-	POSTING_READ(reg);
-	udelay(100);
+	ironlake_fdi_disable(crtc);
 
-	if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS)) {
-		temp = I915_READ(PCH_LVDS);
-		if (temp & LVDS_PORT_EN) {
-			I915_WRITE(PCH_LVDS, temp & ~LVDS_PORT_EN);
-			POSTING_READ(PCH_LVDS);
-			udelay(100);
-		}
-	}
+	/* This is a horrible layering violation; we should be doing this in
+	 * the connector/encoder ->prepare instead, but we don't always have
+	 * enough information there about the config to know whether it will
+	 * actually be necessary or just cause undesired flicker.
+	 */
+	intel_disable_pch_ports(dev_priv, pipe);
 
-	/* disable PCH transcoder */
-	reg = TRANSCONF(plane);
-	temp = I915_READ(reg);
-	if (temp & TRANS_ENABLE) {
-		I915_WRITE(reg, temp & ~TRANS_ENABLE);
-		/* wait for PCH transcoder off, transcoder state */
-		if (wait_for((I915_READ(reg) & TRANS_STATE_ENABLE) == 0, 50))
-			DRM_ERROR("failed to disable transcoder\n");
-	}
+	intel_disable_transcoder(dev_priv, pipe);
 
 	if (HAS_PCH_CPT(dev)) {
 		/* disable TRANS_DP_CTL */
 		reg = TRANS_DP_CTL(pipe);
 		temp = I915_READ(reg);
 		temp &= ~(TRANS_DP_OUTPUT_ENABLE | TRANS_DP_PORT_SEL_MASK);
+		temp |= TRANS_DP_PORT_SEL_NONE;
 		I915_WRITE(reg, temp);
 
 		/* disable DPLL_SEL */
 		temp = I915_READ(PCH_DPLL_SEL);
-		if (pipe == 0)
-			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLB_SEL);
-		else
+		switch (pipe) {
+		case 0:
+			temp &= ~(TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL);
+			break;
+		case 1:
 			temp &= ~(TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL);
+			break;
+		case 2:
+			/* FIXME: manage transcoder PLLs? */
+			temp &= ~(TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL);
+			break;
+		default:
+			BUG(); /* wtf */
+		}
 		I915_WRITE(PCH_DPLL_SEL, temp);
 	}
 
 	/* disable PCH DPLL */
-	reg = PCH_DPLL(pipe);
-	temp = I915_READ(reg);
-	I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
+	intel_disable_pch_pll(dev_priv, pipe);
 
 	/* Switch from PCDclk to Rawclk */
 	reg = FDI_RX_CTL(pipe);
@@ -2451,9 +3001,12 @@
 {
 	if (!enable && intel_crtc->overlay) {
 		struct drm_device *dev = intel_crtc->base.dev;
+		struct drm_i915_private *dev_priv = dev->dev_private;
 
 		mutex_lock(&dev->struct_mutex);
-		(void) intel_overlay_switch_off(intel_crtc->overlay, false);
+		dev_priv->mm.interruptible = false;
+		(void) intel_overlay_switch_off(intel_crtc->overlay);
+		dev_priv->mm.interruptible = true;
 		mutex_unlock(&dev->struct_mutex);
 	}
 
@@ -2469,7 +3022,6 @@
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
-	u32 reg, temp;
 
 	if (intel_crtc->active)
 		return;
@@ -2477,42 +3029,9 @@
 	intel_crtc->active = true;
 	intel_update_watermarks(dev);
 
-	/* Enable the DPLL */
-	reg = DPLL(pipe);
-	temp = I915_READ(reg);
-	if ((temp & DPLL_VCO_ENABLE) == 0) {
-		I915_WRITE(reg, temp);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(reg);
-		udelay(150);
-
-		I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(reg);
-		udelay(150);
-
-		I915_WRITE(reg, temp | DPLL_VCO_ENABLE);
-
-		/* Wait for the clocks to stabilize. */
-		POSTING_READ(reg);
-		udelay(150);
-	}
-
-	/* Enable the pipe */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if ((temp & PIPECONF_ENABLE) == 0)
-		I915_WRITE(reg, temp | PIPECONF_ENABLE);
-
-	/* Enable the plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if ((temp & DISPLAY_PLANE_ENABLE) == 0) {
-		I915_WRITE(reg, temp | DISPLAY_PLANE_ENABLE);
-		intel_flush_display_plane(dev, plane);
-	}
+	intel_enable_pll(dev_priv, pipe);
+	intel_enable_pipe(dev_priv, pipe, false);
+	intel_enable_plane(dev_priv, plane, pipe);
 
 	intel_crtc_load_lut(crtc);
 	intel_update_fbc(dev);
@@ -2529,7 +3048,6 @@
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	int plane = intel_crtc->plane;
-	u32 reg, temp;
 
 	if (!intel_crtc->active)
 		return;
@@ -2544,45 +3062,10 @@
 	    dev_priv->display.disable_fbc)
 		dev_priv->display.disable_fbc(dev);
 
-	/* Disable display plane */
-	reg = DSPCNTR(plane);
-	temp = I915_READ(reg);
-	if (temp & DISPLAY_PLANE_ENABLE) {
-		I915_WRITE(reg, temp & ~DISPLAY_PLANE_ENABLE);
-		/* Flush the plane changes */
-		intel_flush_display_plane(dev, plane);
-
-		/* Wait for vblank for the disable to take effect */
-		if (IS_GEN2(dev))
-			intel_wait_for_vblank(dev, pipe);
-	}
-
-	/* Don't disable pipe A or pipe A PLLs if needed */
-	if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
-		goto done;
-
-	/* Next, disable display pipes */
-	reg = PIPECONF(pipe);
-	temp = I915_READ(reg);
-	if (temp & PIPECONF_ENABLE) {
-		I915_WRITE(reg, temp & ~PIPECONF_ENABLE);
-
-		/* Wait for the pipe to turn off */
-		POSTING_READ(reg);
-		intel_wait_for_pipe_off(dev, pipe);
-	}
-
-	reg = DPLL(pipe);
-	temp = I915_READ(reg);
-	if (temp & DPLL_VCO_ENABLE) {
-		I915_WRITE(reg, temp & ~DPLL_VCO_ENABLE);
-
-		/* Wait for the clocks to turn off. */
-		POSTING_READ(reg);
-		udelay(150);
-	}
+	intel_disable_plane(dev_priv, plane, pipe);
+	intel_disable_pipe(dev_priv, pipe);
+	intel_disable_pll(dev_priv, pipe);
 
-done:
 	intel_crtc->active = false;
 	intel_update_fbc(dev);
 	intel_update_watermarks(dev);
@@ -2644,7 +3127,7 @@
 		master_priv->sarea_priv->pipeB_h = enabled ? crtc->mode.vdisplay : 0;
 		break;
 	default:
-		DRM_ERROR("Can't update pipe %d in SAREA\n", pipe);
+		DRM_ERROR("Can't update pipe %c in SAREA\n", pipe_name(pipe));
 		break;
 	}
 }
@@ -2841,77 +3324,77 @@
 };
 
 /* Pineview has different values for various configs */
-static struct intel_watermark_params pineview_display_wm = {
+static const struct intel_watermark_params pineview_display_wm = {
 	PINEVIEW_DISPLAY_FIFO,
 	PINEVIEW_MAX_WM,
 	PINEVIEW_DFT_WM,
 	PINEVIEW_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params pineview_display_hplloff_wm = {
+static const struct intel_watermark_params pineview_display_hplloff_wm = {
 	PINEVIEW_DISPLAY_FIFO,
 	PINEVIEW_MAX_WM,
 	PINEVIEW_DFT_HPLLOFF_WM,
 	PINEVIEW_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params pineview_cursor_wm = {
+static const struct intel_watermark_params pineview_cursor_wm = {
 	PINEVIEW_CURSOR_FIFO,
 	PINEVIEW_CURSOR_MAX_WM,
 	PINEVIEW_CURSOR_DFT_WM,
 	PINEVIEW_CURSOR_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params pineview_cursor_hplloff_wm = {
+static const struct intel_watermark_params pineview_cursor_hplloff_wm = {
 	PINEVIEW_CURSOR_FIFO,
 	PINEVIEW_CURSOR_MAX_WM,
 	PINEVIEW_CURSOR_DFT_WM,
 	PINEVIEW_CURSOR_GUARD_WM,
 	PINEVIEW_FIFO_LINE_SIZE
 };
-static struct intel_watermark_params g4x_wm_info = {
+static const struct intel_watermark_params g4x_wm_info = {
 	G4X_FIFO_SIZE,
 	G4X_MAX_WM,
 	G4X_MAX_WM,
 	2,
 	G4X_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params g4x_cursor_wm_info = {
+static const struct intel_watermark_params g4x_cursor_wm_info = {
 	I965_CURSOR_FIFO,
 	I965_CURSOR_MAX_WM,
 	I965_CURSOR_DFT_WM,
 	2,
 	G4X_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params i965_cursor_wm_info = {
+static const struct intel_watermark_params i965_cursor_wm_info = {
 	I965_CURSOR_FIFO,
 	I965_CURSOR_MAX_WM,
 	I965_CURSOR_DFT_WM,
 	2,
 	I915_FIFO_LINE_SIZE,
 };
-static struct intel_watermark_params i945_wm_info = {
+static const 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 = {
+static const 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 = {
+static const 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 = {
+static const struct intel_watermark_params i830_wm_info = {
 	I830_FIFO_SIZE,
 	I915_MAX_WM,
 	1,
@@ -2919,31 +3402,28 @@
 	I830_FIFO_LINE_SIZE
 };
 
-static struct intel_watermark_params ironlake_display_wm_info = {
+static const struct intel_watermark_params ironlake_display_wm_info = {
 	ILK_DISPLAY_FIFO,
 	ILK_DISPLAY_MAXWM,
 	ILK_DISPLAY_DFTWM,
 	2,
 	ILK_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params ironlake_cursor_wm_info = {
+static const struct intel_watermark_params ironlake_cursor_wm_info = {
 	ILK_CURSOR_FIFO,
 	ILK_CURSOR_MAXWM,
 	ILK_CURSOR_DFTWM,
 	2,
 	ILK_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params ironlake_display_srwm_info = {
+static const struct intel_watermark_params ironlake_display_srwm_info = {
 	ILK_DISPLAY_SR_FIFO,
 	ILK_DISPLAY_MAX_SRWM,
 	ILK_DISPLAY_DFT_SRWM,
 	2,
 	ILK_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params ironlake_cursor_srwm_info = {
+static const struct intel_watermark_params ironlake_cursor_srwm_info = {
 	ILK_CURSOR_SR_FIFO,
 	ILK_CURSOR_MAX_SRWM,
 	ILK_CURSOR_DFT_SRWM,
@@ -2951,31 +3431,28 @@
 	ILK_FIFO_LINE_SIZE
 };
 
-static struct intel_watermark_params sandybridge_display_wm_info = {
+static const struct intel_watermark_params sandybridge_display_wm_info = {
 	SNB_DISPLAY_FIFO,
 	SNB_DISPLAY_MAXWM,
 	SNB_DISPLAY_DFTWM,
 	2,
 	SNB_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params sandybridge_cursor_wm_info = {
+static const struct intel_watermark_params sandybridge_cursor_wm_info = {
 	SNB_CURSOR_FIFO,
 	SNB_CURSOR_MAXWM,
 	SNB_CURSOR_DFTWM,
 	2,
 	SNB_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params sandybridge_display_srwm_info = {
+static const struct intel_watermark_params sandybridge_display_srwm_info = {
 	SNB_DISPLAY_SR_FIFO,
 	SNB_DISPLAY_MAX_SRWM,
 	SNB_DISPLAY_DFT_SRWM,
 	2,
 	SNB_FIFO_LINE_SIZE
 };
-
-static struct intel_watermark_params sandybridge_cursor_srwm_info = {
+static const struct intel_watermark_params sandybridge_cursor_srwm_info = {
 	SNB_CURSOR_SR_FIFO,
 	SNB_CURSOR_MAX_SRWM,
 	SNB_CURSOR_DFT_SRWM,
@@ -3003,7 +3480,8 @@
  * 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,
+					const struct intel_watermark_params *wm,
+					int fifo_size,
 					int pixel_size,
 					unsigned long latency_ns)
 {
@@ -3021,7 +3499,7 @@
 
 	DRM_DEBUG_KMS("FIFO entries required for mode: %d\n", entries_required);
 
-	wm_size = wm->fifo_size - (entries_required + wm->guard_size);
+	wm_size = fifo_size - (entries_required + wm->guard_size);
 
 	DRM_DEBUG_KMS("FIFO watermark level: %d\n", wm_size);
 
@@ -3194,15 +3672,28 @@
 	return size;
 }
 
-static void pineview_update_wm(struct drm_device *dev,  int planea_clock,
-			       int planeb_clock, int sr_hdisplay, int unused,
-			       int pixel_size)
+static struct drm_crtc *single_enabled_crtc(struct drm_device *dev)
+{
+	struct drm_crtc *crtc, *enabled = NULL;
+
+	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
+		if (crtc->enabled && crtc->fb) {
+			if (enabled)
+				return NULL;
+			enabled = crtc;
+		}
+	}
+
+	return enabled;
+}
+
+static void pineview_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_crtc *crtc;
 	const struct cxsr_latency *latency;
 	u32 reg;
 	unsigned long wm;
-	int sr_clock;
 
 	latency = intel_get_cxsr_latency(IS_PINEVIEW_G(dev), dev_priv->is_ddr3,
 					 dev_priv->fsb_freq, dev_priv->mem_freq);
@@ -3212,11 +3703,14 @@
 		return;
 	}
 
-	if (!planea_clock || !planeb_clock) {
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
+	crtc = single_enabled_crtc(dev);
+	if (crtc) {
+		int clock = crtc->mode.clock;
+		int pixel_size = crtc->fb->bits_per_pixel / 8;
 
 		/* Display SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_display_wm,
+		wm = intel_calculate_wm(clock, &pineview_display_wm,
+					pineview_display_wm.fifo_size,
 					pixel_size, latency->display_sr);
 		reg = I915_READ(DSPFW1);
 		reg &= ~DSPFW_SR_MASK;
@@ -3225,7 +3719,8 @@
 		DRM_DEBUG_KMS("DSPFW1 register is %x\n", reg);
 
 		/* cursor SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_cursor_wm,
+		wm = intel_calculate_wm(clock, &pineview_cursor_wm,
+					pineview_display_wm.fifo_size,
 					pixel_size, latency->cursor_sr);
 		reg = I915_READ(DSPFW3);
 		reg &= ~DSPFW_CURSOR_SR_MASK;
@@ -3233,7 +3728,8 @@
 		I915_WRITE(DSPFW3, reg);
 
 		/* Display HPLL off SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_display_hplloff_wm,
+		wm = intel_calculate_wm(clock, &pineview_display_hplloff_wm,
+					pineview_display_hplloff_wm.fifo_size,
 					pixel_size, latency->display_hpll_disable);
 		reg = I915_READ(DSPFW3);
 		reg &= ~DSPFW_HPLL_SR_MASK;
@@ -3241,7 +3737,8 @@
 		I915_WRITE(DSPFW3, reg);
 
 		/* cursor HPLL off SR */
-		wm = intel_calculate_wm(sr_clock, &pineview_cursor_hplloff_wm,
+		wm = intel_calculate_wm(clock, &pineview_cursor_hplloff_wm,
+					pineview_display_hplloff_wm.fifo_size,
 					pixel_size, latency->cursor_hpll_disable);
 		reg = I915_READ(DSPFW3);
 		reg &= ~DSPFW_HPLL_CURSOR_MASK;
@@ -3259,125 +3756,229 @@
 	}
 }
 
-static void g4x_update_wm(struct drm_device *dev,  int planea_clock,
-			  int planeb_clock, int sr_hdisplay, int sr_htotal,
-			  int pixel_size)
+static bool g4x_compute_wm0(struct drm_device *dev,
+			    int plane,
+			    const struct intel_watermark_params *display,
+			    int display_latency_ns,
+			    const struct intel_watermark_params *cursor,
+			    int cursor_latency_ns,
+			    int *plane_wm,
+			    int *cursor_wm)
 {
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	int total_size, cacheline_size;
-	int planea_wm, planeb_wm, cursora_wm, cursorb_wm, cursor_sr;
-	struct intel_watermark_params planea_params, planeb_params;
-	unsigned long line_time_us;
-	int sr_clock, sr_entries = 0, entries_required;
+	struct drm_crtc *crtc;
+	int htotal, hdisplay, clock, pixel_size;
+	int line_time_us, line_count;
+	int entries, tlb_miss;
 
-	/* Create copies of the base settings for each pipe */
-	planea_params = planeb_params = g4x_wm_info;
+	crtc = intel_get_crtc_for_plane(dev, plane);
+	if (crtc->fb == NULL || !crtc->enabled) {
+		*cursor_wm = cursor->guard_size;
+		*plane_wm = display->guard_size;
+		return false;
+	}
 
-	/* Grab a couple of global values before we overwrite them */
-	total_size = planea_params.fifo_size;
-	cacheline_size = planea_params.cacheline_size;
+	htotal = crtc->mode.htotal;
+	hdisplay = crtc->mode.hdisplay;
+	clock = crtc->mode.clock;
+	pixel_size = crtc->fb->bits_per_pixel / 8;
 
-	/*
-	 * Note: we need to make sure we don't overflow for various clock &
-	 * latency values.
-	 * clocks go from a few thousand to several hundred thousand.
-	 * latency is usually a few thousand
-	 */
-	entries_required = ((planea_clock / 1000) * pixel_size * latency_ns) /
-		1000;
-	entries_required = DIV_ROUND_UP(entries_required, G4X_FIFO_LINE_SIZE);
-	planea_wm = entries_required + planea_params.guard_size;
+	/* Use the small buffer method to calculate plane watermark */
+	entries = ((clock * pixel_size / 1000) * display_latency_ns) / 1000;
+	tlb_miss = display->fifo_size*display->cacheline_size - hdisplay * 8;
+	if (tlb_miss > 0)
+		entries += tlb_miss;
+	entries = DIV_ROUND_UP(entries, display->cacheline_size);
+	*plane_wm = entries + display->guard_size;
+	if (*plane_wm > (int)display->max_wm)
+		*plane_wm = display->max_wm;
 
-	entries_required = ((planeb_clock / 1000) * pixel_size * latency_ns) /
-		1000;
-	entries_required = DIV_ROUND_UP(entries_required, G4X_FIFO_LINE_SIZE);
-	planeb_wm = entries_required + planeb_params.guard_size;
+	/* Use the large buffer method to calculate cursor watermark */
+	line_time_us = ((htotal * 1000) / clock);
+	line_count = (cursor_latency_ns / line_time_us + 1000) / 1000;
+	entries = line_count * 64 * pixel_size;
+	tlb_miss = cursor->fifo_size*cursor->cacheline_size - hdisplay * 8;
+	if (tlb_miss > 0)
+		entries += tlb_miss;
+	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+	*cursor_wm = entries + cursor->guard_size;
+	if (*cursor_wm > (int)cursor->max_wm)
+		*cursor_wm = (int)cursor->max_wm;
 
-	cursora_wm = cursorb_wm = 16;
-	cursor_sr = 32;
+	return true;
+}
 
-	DRM_DEBUG("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
+/*
+ * Check the wm result.
+ *
+ * If any calculated watermark values is larger than the maximum value that
+ * can be programmed into the associated watermark register, that watermark
+ * must be disabled.
+ */
+static bool g4x_check_srwm(struct drm_device *dev,
+			   int display_wm, int cursor_wm,
+			   const struct intel_watermark_params *display,
+			   const struct intel_watermark_params *cursor)
+{
+	DRM_DEBUG_KMS("SR watermark: display plane %d, cursor %d\n",
+		      display_wm, cursor_wm);
 
-	/* Calc sr entries for one plane configs */
-	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
-		/* self-refresh has much higher latency */
-		static const int sr_latency_ns = 12000;
+	if (display_wm > display->max_wm) {
+		DRM_DEBUG_KMS("display watermark is too large(%d), disabling\n",
+			      display_wm, display->max_wm);
+		return false;
+	}
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = ((sr_htotal * 1000) / sr_clock);
+	if (cursor_wm > cursor->max_wm) {
+		DRM_DEBUG_KMS("cursor watermark is too large(%d), disabling\n",
+			      cursor_wm, cursor->max_wm);
+		return false;
+	}
 
-		/* Use ns/us then divide to preserve precision */
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			pixel_size * sr_hdisplay;
-		sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size);
+	if (!(display_wm || cursor_wm)) {
+		DRM_DEBUG_KMS("SR latency is 0, disabling\n");
+		return false;
+	}
 
-		entries_required = (((sr_latency_ns / line_time_us) +
-				     1000) / 1000) * pixel_size * 64;
-		entries_required = DIV_ROUND_UP(entries_required,
-						g4x_cursor_wm_info.cacheline_size);
-		cursor_sr = entries_required + g4x_cursor_wm_info.guard_size;
+	return true;
+}
 
-		if (cursor_sr > g4x_cursor_wm_info.max_wm)
-			cursor_sr = g4x_cursor_wm_info.max_wm;
-		DRM_DEBUG_KMS("self-refresh watermark: display plane %d "
-			      "cursor %d\n", sr_entries, cursor_sr);
+static bool g4x_compute_srwm(struct drm_device *dev,
+			     int plane,
+			     int latency_ns,
+			     const struct intel_watermark_params *display,
+			     const struct intel_watermark_params *cursor,
+			     int *display_wm, int *cursor_wm)
+{
+	struct drm_crtc *crtc;
+	int hdisplay, htotal, pixel_size, clock;
+	unsigned long line_time_us;
+	int line_count, line_size;
+	int small, large;
+	int entries;
 
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
-	} else {
-		/* Turn off self refresh if both pipes are enabled */
-		I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-			   & ~FW_BLC_SELF_EN);
+	if (!latency_ns) {
+		*display_wm = *cursor_wm = 0;
+		return false;
 	}
 
-	DRM_DEBUG("Setting FIFO watermarks - A: %d, B: %d, SR %d\n",
-		  planea_wm, planeb_wm, sr_entries);
+	crtc = intel_get_crtc_for_plane(dev, plane);
+	hdisplay = crtc->mode.hdisplay;
+	htotal = crtc->mode.htotal;
+	clock = crtc->mode.clock;
+	pixel_size = crtc->fb->bits_per_pixel / 8;
 
-	planea_wm &= 0x3f;
-	planeb_wm &= 0x3f;
+	line_time_us = (htotal * 1000) / clock;
+	line_count = (latency_ns / line_time_us + 1000) / 1000;
+	line_size = hdisplay * pixel_size;
 
-	I915_WRITE(DSPFW1, (sr_entries << DSPFW_SR_SHIFT) |
+	/* Use the minimum of the small and large buffer method for primary */
+	small = ((clock * pixel_size / 1000) * latency_ns) / 1000;
+	large = line_count * line_size;
+
+	entries = DIV_ROUND_UP(min(small, large), display->cacheline_size);
+	*display_wm = entries + display->guard_size;
+
+	/* calculate the self-refresh watermark for display cursor */
+	entries = line_count * pixel_size * 64;
+	entries = DIV_ROUND_UP(entries, cursor->cacheline_size);
+	*cursor_wm = entries + cursor->guard_size;
+
+	return g4x_check_srwm(dev,
+			      *display_wm, *cursor_wm,
+			      display, cursor);
+}
+
+#define single_plane_enabled(mask) is_power_of_2(mask)
+
+static void g4x_update_wm(struct drm_device *dev)
+{
+	static const int sr_latency_ns = 12000;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	int planea_wm, planeb_wm, cursora_wm, cursorb_wm;
+	int plane_sr, cursor_sr;
+	unsigned int enabled = 0;
+
+	if (g4x_compute_wm0(dev, 0,
+			    &g4x_wm_info, latency_ns,
+			    &g4x_cursor_wm_info, latency_ns,
+			    &planea_wm, &cursora_wm))
+		enabled |= 1;
+
+	if (g4x_compute_wm0(dev, 1,
+			    &g4x_wm_info, latency_ns,
+			    &g4x_cursor_wm_info, latency_ns,
+			    &planeb_wm, &cursorb_wm))
+		enabled |= 2;
+
+	plane_sr = cursor_sr = 0;
+	if (single_plane_enabled(enabled) &&
+	    g4x_compute_srwm(dev, ffs(enabled) - 1,
+			     sr_latency_ns,
+			     &g4x_wm_info,
+			     &g4x_cursor_wm_info,
+			     &plane_sr, &cursor_sr))
+		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN);
+	else
+		I915_WRITE(FW_BLC_SELF,
+			   I915_READ(FW_BLC_SELF) & ~FW_BLC_SELF_EN);
+
+	DRM_DEBUG_KMS("Setting FIFO watermarks - A: plane=%d, cursor=%d, B: plane=%d, cursor=%d, SR: plane=%d, cursor=%d\n",
+		      planea_wm, cursora_wm,
+		      planeb_wm, cursorb_wm,
+		      plane_sr, cursor_sr);
+
+	I915_WRITE(DSPFW1,
+		   (plane_sr << DSPFW_SR_SHIFT) |
 		   (cursorb_wm << DSPFW_CURSORB_SHIFT) |
-		   (planeb_wm << DSPFW_PLANEB_SHIFT) | planea_wm);
-	I915_WRITE(DSPFW2, (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
+		   (planeb_wm << DSPFW_PLANEB_SHIFT) |
+		   planea_wm);
+	I915_WRITE(DSPFW2,
+		   (I915_READ(DSPFW2) & DSPFW_CURSORA_MASK) |
 		   (cursora_wm << DSPFW_CURSORA_SHIFT));
 	/* HPLL off in SR has some issues on G4x... disable it */
-	I915_WRITE(DSPFW3, (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
+	I915_WRITE(DSPFW3,
+		   (I915_READ(DSPFW3) & ~DSPFW_HPLL_SR_EN) |
 		   (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i965_update_wm(struct drm_device *dev, int planea_clock,
-			   int planeb_clock, int sr_hdisplay, int sr_htotal,
-			   int pixel_size)
+static void i965_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	unsigned long line_time_us;
-	int sr_clock, sr_entries, srwm = 1;
+	struct drm_crtc *crtc;
+	int srwm = 1;
 	int cursor_sr = 16;
 
 	/* Calc sr entries for one plane configs */
-	if (sr_hdisplay && (!planea_clock || !planeb_clock)) {
+	crtc = single_enabled_crtc(dev);
+	if (crtc) {
 		/* self-refresh has much higher latency */
 		static const int sr_latency_ns = 12000;
+		int clock = crtc->mode.clock;
+		int htotal = crtc->mode.htotal;
+		int hdisplay = crtc->mode.hdisplay;
+		int pixel_size = crtc->fb->bits_per_pixel / 8;
+		unsigned long line_time_us;
+		int entries;
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = ((sr_htotal * 1000) / sr_clock);
+		line_time_us = ((htotal * 1000) / clock);
 
 		/* Use ns/us then divide to preserve precision */
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			pixel_size * sr_hdisplay;
-		sr_entries = DIV_ROUND_UP(sr_entries, I915_FIFO_LINE_SIZE);
-		DRM_DEBUG("self-refresh entries: %d\n", sr_entries);
-		srwm = I965_FIFO_SIZE - sr_entries;
+		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+			pixel_size * hdisplay;
+		entries = DIV_ROUND_UP(entries, I915_FIFO_LINE_SIZE);
+		srwm = I965_FIFO_SIZE - entries;
 		if (srwm < 0)
 			srwm = 1;
 		srwm &= 0x1ff;
+		DRM_DEBUG_KMS("self-refresh entries: %d, wm: %d\n",
+			      entries, srwm);
 
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
 			pixel_size * 64;
-		sr_entries = DIV_ROUND_UP(sr_entries,
+		entries = DIV_ROUND_UP(entries,
 					  i965_cursor_wm_info.cacheline_size);
 		cursor_sr = i965_cursor_wm_info.fifo_size -
-			(sr_entries + i965_cursor_wm_info.guard_size);
+			(entries + i965_cursor_wm_info.guard_size);
 
 		if (cursor_sr > i965_cursor_wm_info.max_wm)
 			cursor_sr = i965_cursor_wm_info.max_wm;
@@ -3398,46 +3999,56 @@
 		      srwm);
 
 	/* 965 has limitations... */
-	I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) | (8 << 16) | (8 << 8) |
-		   (8 << 0));
+	I915_WRITE(DSPFW1, (srwm << DSPFW_SR_SHIFT) |
+		   (8 << 16) | (8 << 8) | (8 << 0));
 	I915_WRITE(DSPFW2, (8 << 8) | (8 << 0));
 	/* update cursor SR watermark */
 	I915_WRITE(DSPFW3, (cursor_sr << DSPFW_CURSOR_SR_SHIFT));
 }
 
-static void i9xx_update_wm(struct drm_device *dev, int planea_clock,
-			   int planeb_clock, int sr_hdisplay, int sr_htotal,
-			   int pixel_size)
+static void i9xx_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	const struct intel_watermark_params *wm_info;
 	uint32_t fwater_lo;
 	uint32_t fwater_hi;
-	int total_size, cacheline_size, cwm, srwm = 1;
+	int cwm, srwm = 1;
+	int fifo_size;
 	int planea_wm, planeb_wm;
-	struct intel_watermark_params planea_params, planeb_params;
-	unsigned long line_time_us;
-	int sr_clock, sr_entries = 0;
+	struct drm_crtc *crtc, *enabled = NULL;
 
-	/* Create copies of the base settings for each pipe */
-	if (IS_CRESTLINE(dev) || IS_I945GM(dev))
-		planea_params = planeb_params = i945_wm_info;
+	if (IS_I945GM(dev))
+		wm_info = &i945_wm_info;
 	else if (!IS_GEN2(dev))
-		planea_params = planeb_params = i915_wm_info;
+		wm_info = &i915_wm_info;
 	else
-		planea_params = planeb_params = i855_wm_info;
+		wm_info = &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;
+	fifo_size = dev_priv->display.get_fifo_size(dev, 0);
+	crtc = intel_get_crtc_for_plane(dev, 0);
+	if (crtc->enabled && crtc->fb) {
+		planea_wm = intel_calculate_wm(crtc->mode.clock,
+					       wm_info, fifo_size,
+					       crtc->fb->bits_per_pixel / 8,
+					       latency_ns);
+		enabled = crtc;
+	} else
+		planea_wm = fifo_size - wm_info->guard_size;
 
-	/* Update per-plane FIFO sizes */
-	planea_params.fifo_size = dev_priv->display.get_fifo_size(dev, 0);
-	planeb_params.fifo_size = dev_priv->display.get_fifo_size(dev, 1);
+	fifo_size = dev_priv->display.get_fifo_size(dev, 1);
+	crtc = intel_get_crtc_for_plane(dev, 1);
+	if (crtc->enabled && crtc->fb) {
+		planeb_wm = intel_calculate_wm(crtc->mode.clock,
+					       wm_info, fifo_size,
+					       crtc->fb->bits_per_pixel / 8,
+					       latency_ns);
+		if (enabled == NULL)
+			enabled = crtc;
+		else
+			enabled = NULL;
+	} else
+		planeb_wm = fifo_size - wm_info->guard_size;
 
-	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_KMS("FIFO watermarks - A: %d, B: %d\n", planea_wm, planeb_wm);
 
 	/*
@@ -3445,39 +4056,39 @@
 	 */
 	cwm = 2;
 
+	/* Play safe and disable self-refresh before adjusting watermarks. */
+	if (IS_I945G(dev) || IS_I945GM(dev))
+		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | 0);
+	else if (IS_I915GM(dev))
+		I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
+
 	/* Calc sr entries for one plane configs */
-	if (HAS_FW_BLC(dev) && sr_hdisplay &&
-	    (!planea_clock || !planeb_clock)) {
+	if (HAS_FW_BLC(dev) && enabled) {
 		/* self-refresh has much higher latency */
 		static const int sr_latency_ns = 6000;
+		int clock = enabled->mode.clock;
+		int htotal = enabled->mode.htotal;
+		int hdisplay = enabled->mode.hdisplay;
+		int pixel_size = enabled->fb->bits_per_pixel / 8;
+		unsigned long line_time_us;
+		int entries;
 
-		sr_clock = planea_clock ? planea_clock : planeb_clock;
-		line_time_us = ((sr_htotal * 1000) / sr_clock);
+		line_time_us = (htotal * 1000) / clock;
 
 		/* Use ns/us then divide to preserve precision */
-		sr_entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
-			pixel_size * sr_hdisplay;
-		sr_entries = DIV_ROUND_UP(sr_entries, cacheline_size);
-		DRM_DEBUG_KMS("self-refresh entries: %d\n", sr_entries);
-		srwm = total_size - sr_entries;
+		entries = (((sr_latency_ns / line_time_us) + 1000) / 1000) *
+			pixel_size * hdisplay;
+		entries = DIV_ROUND_UP(entries, wm_info->cacheline_size);
+		DRM_DEBUG_KMS("self-refresh entries: %d\n", entries);
+		srwm = wm_info->fifo_size - entries;
 		if (srwm < 0)
 			srwm = 1;
 
 		if (IS_I945G(dev) || IS_I945GM(dev))
-			I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
-		else if (IS_I915GM(dev)) {
-			/* 915M has a smaller SRWM field */
+			I915_WRITE(FW_BLC_SELF,
+				   FW_BLC_SELF_FIFO_MASK | (srwm & 0xff));
+		else if (IS_I915GM(dev))
 			I915_WRITE(FW_BLC_SELF, srwm & 0x3f);
-			I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
-		}
-	} else {
-		/* Turn off self refresh if both pipes are enabled */
-		if (IS_I945G(dev) || IS_I945GM(dev)) {
-			I915_WRITE(FW_BLC_SELF, I915_READ(FW_BLC_SELF)
-				   & ~FW_BLC_SELF_EN);
-		} else if (IS_I915GM(dev)) {
-			I915_WRITE(INSTPM, I915_READ(INSTPM) & ~INSTPM_SELF_EN);
-		}
 	}
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d, B: %d, C: %d, SR %d\n",
@@ -3492,19 +4103,36 @@
 
 	I915_WRITE(FW_BLC, fwater_lo);
 	I915_WRITE(FW_BLC2, fwater_hi);
+
+	if (HAS_FW_BLC(dev)) {
+		if (enabled) {
+			if (IS_I945G(dev) || IS_I945GM(dev))
+				I915_WRITE(FW_BLC_SELF,
+					   FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
+			else if (IS_I915GM(dev))
+				I915_WRITE(INSTPM, I915_READ(INSTPM) | INSTPM_SELF_EN);
+			DRM_DEBUG_KMS("memory self refresh enabled\n");
+		} else
+			DRM_DEBUG_KMS("memory self refresh disabled\n");
+	}
 }
 
-static void i830_update_wm(struct drm_device *dev, int planea_clock, int unused,
-			   int unused2, int unused3, int pixel_size)
+static void i830_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	uint32_t fwater_lo = I915_READ(FW_BLC) & ~0xfff;
+	struct drm_crtc *crtc;
+	uint32_t fwater_lo;
 	int planea_wm;
 
-	i830_wm_info.fifo_size = dev_priv->display.get_fifo_size(dev, 0);
+	crtc = single_enabled_crtc(dev);
+	if (crtc == NULL)
+		return;
 
-	planea_wm = intel_calculate_wm(planea_clock, &i830_wm_info,
-				       pixel_size, latency_ns);
+	planea_wm = intel_calculate_wm(crtc->mode.clock, &i830_wm_info,
+				       dev_priv->display.get_fifo_size(dev, 0),
+				       crtc->fb->bits_per_pixel / 8,
+				       latency_ns);
+	fwater_lo = I915_READ(FW_BLC) & ~0xfff;
 	fwater_lo |= (3<<8) | planea_wm;
 
 	DRM_DEBUG_KMS("Setting FIFO watermarks - A: %d\n", planea_wm);
@@ -3613,15 +4241,15 @@
 /*
  * Compute watermark values of WM[1-3],
  */
-static bool ironlake_compute_srwm(struct drm_device *dev, int level,
-				  int hdisplay, int htotal,
-				  int pixel_size, int clock, int latency_ns,
+static bool ironlake_compute_srwm(struct drm_device *dev, int level, int plane,
+				  int latency_ns,
 				  const struct intel_watermark_params *display,
 				  const struct intel_watermark_params *cursor,
 				  int *fbc_wm, int *display_wm, int *cursor_wm)
 {
-
+	struct drm_crtc *crtc;
 	unsigned long line_time_us;
+	int hdisplay, htotal, pixel_size, clock;
 	int line_count, line_size;
 	int small, large;
 	int entries;
@@ -3631,6 +4259,12 @@
 		return false;
 	}
 
+	crtc = intel_get_crtc_for_plane(dev, plane);
+	hdisplay = crtc->mode.hdisplay;
+	htotal = crtc->mode.htotal;
+	clock = crtc->mode.clock;
+	pixel_size = crtc->fb->bits_per_pixel / 8;
+
 	line_time_us = (htotal * 1000) / clock;
 	line_count = (latency_ns / line_time_us + 1000) / 1000;
 	line_size = hdisplay * pixel_size;
@@ -3658,14 +4292,11 @@
 				   display, cursor);
 }
 
-static void ironlake_update_wm(struct drm_device *dev,
-			       int planea_clock, int planeb_clock,
-			       int hdisplay, int htotal,
-			       int pixel_size)
+static void ironlake_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	int fbc_wm, plane_wm, cursor_wm, enabled;
-	int clock;
+	int fbc_wm, plane_wm, cursor_wm;
+	unsigned int enabled;
 
 	enabled = 0;
 	if (ironlake_compute_wm0(dev, 0,
@@ -3679,7 +4310,7 @@
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 1;
 	}
 
 	if (ironlake_compute_wm0(dev, 1,
@@ -3693,7 +4324,7 @@
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 2;
 	}
 
 	/*
@@ -3704,14 +4335,13 @@
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
-	if (enabled != 1)
+	if (!single_plane_enabled(enabled))
 		return;
-
-	clock = planea_clock ? planea_clock : planeb_clock;
+	enabled = ffs(enabled) - 1;
 
 	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
-				   clock, ILK_READ_WM1_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 1, enabled,
+				   ILK_READ_WM1_LATENCY() * 500,
 				   &ironlake_display_srwm_info,
 				   &ironlake_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3725,8 +4355,8 @@
 		   cursor_wm);
 
 	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2, hdisplay, htotal, pixel_size,
-				   clock, ILK_READ_WM2_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 2, enabled,
+				   ILK_READ_WM2_LATENCY() * 500,
 				   &ironlake_display_srwm_info,
 				   &ironlake_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3745,15 +4375,12 @@
 	 */
 }
 
-static void sandybridge_update_wm(struct drm_device *dev,
-			       int planea_clock, int planeb_clock,
-			       int hdisplay, int htotal,
-			       int pixel_size)
+static void sandybridge_update_wm(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int latency = SNB_READ_WM0_LATENCY() * 100;	/* In unit 0.1us */
-	int fbc_wm, plane_wm, cursor_wm, enabled;
-	int clock;
+	int fbc_wm, plane_wm, cursor_wm;
+	unsigned int enabled;
 
 	enabled = 0;
 	if (ironlake_compute_wm0(dev, 0,
@@ -3765,7 +4392,7 @@
 		DRM_DEBUG_KMS("FIFO watermarks For pipe A -"
 			      " plane %d, " "cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 1;
 	}
 
 	if (ironlake_compute_wm0(dev, 1,
@@ -3777,7 +4404,7 @@
 		DRM_DEBUG_KMS("FIFO watermarks For pipe B -"
 			      " plane %d, cursor: %d\n",
 			      plane_wm, cursor_wm);
-		enabled++;
+		enabled |= 2;
 	}
 
 	/*
@@ -3794,14 +4421,13 @@
 	I915_WRITE(WM2_LP_ILK, 0);
 	I915_WRITE(WM1_LP_ILK, 0);
 
-	if (enabled != 1)
+	if (!single_plane_enabled(enabled))
 		return;
-
-	clock = planea_clock ? planea_clock : planeb_clock;
+	enabled = ffs(enabled) - 1;
 
 	/* WM1 */
-	if (!ironlake_compute_srwm(dev, 1, hdisplay, htotal, pixel_size,
-				   clock, SNB_READ_WM1_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 1, enabled,
+				   SNB_READ_WM1_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3815,9 +4441,8 @@
 		   cursor_wm);
 
 	/* WM2 */
-	if (!ironlake_compute_srwm(dev, 2,
-				   hdisplay, htotal, pixel_size,
-				   clock, SNB_READ_WM2_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 2, enabled,
+				   SNB_READ_WM2_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3831,9 +4456,8 @@
 		   cursor_wm);
 
 	/* WM3 */
-	if (!ironlake_compute_srwm(dev, 3,
-				   hdisplay, htotal, pixel_size,
-				   clock, SNB_READ_WM3_LATENCY() * 500,
+	if (!ironlake_compute_srwm(dev, 3, enabled,
+				   SNB_READ_WM3_LATENCY() * 500,
 				   &sandybridge_display_srwm_info,
 				   &sandybridge_cursor_srwm_info,
 				   &fbc_wm, &plane_wm, &cursor_wm))
@@ -3882,44 +4506,9 @@
 static void intel_update_watermarks(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct drm_crtc *crtc;
-	int sr_hdisplay = 0;
-	unsigned long planea_clock = 0, planeb_clock = 0, sr_clock = 0;
-	int enabled = 0, pixel_size = 0;
-	int sr_htotal = 0;
-
-	if (!dev_priv->display.update_wm)
-		return;
 
-	/* Get the clock config from both planes */
-	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-		if (intel_crtc->active) {
-			enabled++;
-			if (intel_crtc->plane == 0) {
-				DRM_DEBUG_KMS("plane A (pipe %d) clock: %d\n",
-					      intel_crtc->pipe, crtc->mode.clock);
-				planea_clock = crtc->mode.clock;
-			} else {
-				DRM_DEBUG_KMS("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;
-			sr_htotal = crtc->mode.htotal;
-			if (crtc->fb)
-				pixel_size = crtc->fb->bits_per_pixel / 8;
-			else
-				pixel_size = 4; /* by default */
-		}
-	}
-
-	if (enabled <= 0)
-		return;
-
-	dev_priv->display.update_wm(dev, planea_clock, planeb_clock,
-				    sr_hdisplay, sr_htotal, pixel_size);
+	if (dev_priv->display.update_wm)
+		dev_priv->display.update_wm(dev);
 }
 
 static inline bool intel_panel_use_ssc(struct drm_i915_private *dev_priv)
@@ -3951,6 +4540,7 @@
 	int ret;
 	struct fdi_m_n m_n = {0};
 	u32 reg, temp;
+	u32 lvds_sync = 0;
 	int target_clock;
 
 	drm_vblank_pre_modeset(dev, pipe);
@@ -4322,9 +4912,8 @@
 			pipeconf &= ~PIPECONF_DOUBLE_WIDE;
 	}
 
-	dspcntr |= DISPLAY_PLANE_ENABLE;
-	pipeconf |= PIPECONF_ENABLE;
-	dpll |= DPLL_VCO_ENABLE;
+	if (!HAS_PCH_SPLIT(dev))
+		dpll |= DPLL_VCO_ENABLE;
 
 	DRM_DEBUG_KMS("Mode for pipe %c:\n", pipe == 0 ? 'A' : 'B');
 	drm_mode_debug_printmodeline(mode);
@@ -4350,10 +4939,20 @@
 	/* enable transcoder DPLL */
 	if (HAS_PCH_CPT(dev)) {
 		temp = I915_READ(PCH_DPLL_SEL);
-		if (pipe == 0)
+		switch (pipe) {
+		case 0:
 			temp |= TRANSA_DPLL_ENABLE | TRANSA_DPLLA_SEL;
-		else
+			break;
+		case 1:
 			temp |=	TRANSB_DPLL_ENABLE | TRANSB_DPLLB_SEL;
+			break;
+		case 2:
+			/* FIXME: manage transcoder PLLs? */
+			temp |= TRANSC_DPLL_ENABLE | TRANSC_DPLLB_SEL;
+			break;
+		default:
+			BUG();
+		}
 		I915_WRITE(PCH_DPLL_SEL, temp);
 
 		POSTING_READ(PCH_DPLL_SEL);
@@ -4403,6 +5002,22 @@
 			else
 				temp &= ~LVDS_ENABLE_DITHER;
 		}
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC)
+			lvds_sync |= LVDS_HSYNC_POLARITY;
+		if (adjusted_mode->flags & DRM_MODE_FLAG_NVSYNC)
+			lvds_sync |= LVDS_VSYNC_POLARITY;
+		if ((temp & (LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY))
+		    != lvds_sync) {
+			char flags[2] = "-+";
+			DRM_INFO("Changing LVDS panel from "
+				 "(%chsync, %cvsync) to (%chsync, %cvsync)\n",
+				 flags[!(temp & LVDS_HSYNC_POLARITY)],
+				 flags[!(temp & LVDS_VSYNC_POLARITY)],
+				 flags[!(lvds_sync & LVDS_HSYNC_POLARITY)],
+				 flags[!(lvds_sync & LVDS_VSYNC_POLARITY)]);
+			temp &= ~(LVDS_HSYNC_POLARITY | LVDS_VSYNC_POLARITY);
+			temp |= lvds_sync;
+		}
 		I915_WRITE(reg, temp);
 	}
 
@@ -4420,17 +5035,10 @@
 		intel_dp_set_m_n(crtc, mode, adjusted_mode);
 	} else if (HAS_PCH_SPLIT(dev)) {
 		/* For non-DP output, clear any trans DP clock recovery setting.*/
-		if (pipe == 0) {
-			I915_WRITE(TRANSA_DATA_M1, 0);
-			I915_WRITE(TRANSA_DATA_N1, 0);
-			I915_WRITE(TRANSA_DP_LINK_M1, 0);
-			I915_WRITE(TRANSA_DP_LINK_N1, 0);
-		} else {
-			I915_WRITE(TRANSB_DATA_M1, 0);
-			I915_WRITE(TRANSB_DATA_N1, 0);
-			I915_WRITE(TRANSB_DP_LINK_M1, 0);
-			I915_WRITE(TRANSB_DP_LINK_N1, 0);
-		}
+		I915_WRITE(TRANSDATA_M1(pipe), 0);
+		I915_WRITE(TRANSDATA_N1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_M1(pipe), 0);
+		I915_WRITE(TRANSDPLINK_N1(pipe), 0);
 	}
 
 	if (!has_edp_encoder || intel_encoder_is_pch_edp(&has_edp_encoder->base)) {
@@ -4533,6 +5141,8 @@
 
 	I915_WRITE(PIPECONF(pipe), pipeconf);
 	POSTING_READ(PIPECONF(pipe));
+	if (!HAS_PCH_SPLIT(dev))
+		intel_enable_pipe(dev_priv, pipe, false);
 
 	intel_wait_for_vblank(dev, pipe);
 
@@ -4543,6 +5153,9 @@
 	}
 
 	I915_WRITE(DSPCNTR(plane), dspcntr);
+	POSTING_READ(DSPCNTR(plane));
+	if (!HAS_PCH_SPLIT(dev))
+		intel_enable_plane(dev_priv, plane, pipe);
 
 	ret = intel_pipe_set_base(crtc, x, y, old_fb);
 
@@ -4559,7 +5172,7 @@
 	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 palreg = (intel_crtc->pipe == 0) ? PALETTE_A : PALETTE_B;
+	int palreg = PALETTE(intel_crtc->pipe);
 	int i;
 
 	/* The clocks have to be on to load the palette. */
@@ -4568,8 +5181,7 @@
 
 	/* use legacy palette for Ironlake */
 	if (HAS_PCH_SPLIT(dev))
-		palreg = (intel_crtc->pipe == 0) ? LGC_PALETTE_A :
-						   LGC_PALETTE_B;
+		palreg = LGC_PALETTE(intel_crtc->pipe);
 
 	for (i = 0; i < 256; i++) {
 		I915_WRITE(palreg + 4 * i,
@@ -4590,12 +5202,12 @@
 	if (intel_crtc->cursor_visible == visible)
 		return;
 
-	cntl = I915_READ(CURACNTR);
+	cntl = I915_READ(_CURACNTR);
 	if (visible) {
 		/* On these chipsets we can only modify the base whilst
 		 * the cursor is disabled.
 		 */
-		I915_WRITE(CURABASE, base);
+		I915_WRITE(_CURABASE, base);
 
 		cntl &= ~(CURSOR_FORMAT_MASK);
 		/* XXX width must be 64, stride 256 => 0x00 << 28 */
@@ -4604,7 +5216,7 @@
 			CURSOR_FORMAT_ARGB;
 	} else
 		cntl &= ~(CURSOR_ENABLE | CURSOR_GAMMA_ENABLE);
-	I915_WRITE(CURACNTR, cntl);
+	I915_WRITE(_CURACNTR, cntl);
 
 	intel_crtc->cursor_visible = visible;
 }
@@ -4618,7 +5230,7 @@
 	bool visible = base != 0;
 
 	if (intel_crtc->cursor_visible != visible) {
-		uint32_t cntl = I915_READ(pipe == 0 ? CURACNTR : CURBCNTR);
+		uint32_t cntl = I915_READ(CURCNTR(pipe));
 		if (base) {
 			cntl &= ~(CURSOR_MODE | MCURSOR_PIPE_SELECT);
 			cntl |= CURSOR_MODE_64_ARGB_AX | MCURSOR_GAMMA_ENABLE;
@@ -4627,12 +5239,12 @@
 			cntl &= ~(CURSOR_MODE | MCURSOR_GAMMA_ENABLE);
 			cntl |= CURSOR_MODE_DISABLE;
 		}
-		I915_WRITE(pipe == 0 ? CURACNTR : CURBCNTR, cntl);
+		I915_WRITE(CURCNTR(pipe), cntl);
 
 		intel_crtc->cursor_visible = visible;
 	}
 	/* and commit changes on next vblank */
-	I915_WRITE(pipe == 0 ? CURABASE : CURBBASE, base);
+	I915_WRITE(CURBASE(pipe), base);
 }
 
 /* If no-part of the cursor is visible on the framebuffer, then the GPU may hang... */
@@ -4682,7 +5294,7 @@
 	if (!visible && !intel_crtc->cursor_visible)
 		return;
 
-	I915_WRITE(pipe == 0 ? CURAPOS : CURBPOS, pos);
+	I915_WRITE(CURPOS(pipe), pos);
 	if (IS_845G(dev) || IS_I865G(dev))
 		i845_update_cursor(crtc, base);
 	else
@@ -4722,7 +5334,7 @@
 	}
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, file, handle));
-	if (!obj)
+	if (&obj->base == NULL)
 		return -ENOENT;
 
 	if (obj->base.size < width * height * 4) {
@@ -4988,14 +5600,14 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	u32 dpll = I915_READ((pipe == 0) ? DPLL_A : DPLL_B);
+	u32 dpll = I915_READ(DPLL(pipe));
 	u32 fp;
 	intel_clock_t clock;
 
 	if ((dpll & DISPLAY_RATE_SELECT_FPA1) == 0)
-		fp = I915_READ((pipe == 0) ? FPA0 : FPB0);
+		fp = I915_READ(FP0(pipe));
 	else
-		fp = I915_READ((pipe == 0) ? FPA1 : FPB1);
+		fp = I915_READ(FP1(pipe));
 
 	clock.m1 = (fp & FP_M1_DIV_MASK) >> FP_M1_DIV_SHIFT;
 	if (IS_PINEVIEW(dev)) {
@@ -5077,10 +5689,10 @@
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
 	struct drm_display_mode *mode;
-	int htot = I915_READ((pipe == 0) ? HTOTAL_A : HTOTAL_B);
-	int hsync = I915_READ((pipe == 0) ? HSYNC_A : HSYNC_B);
-	int vtot = I915_READ((pipe == 0) ? VTOTAL_A : VTOTAL_B);
-	int vsync = I915_READ((pipe == 0) ? VSYNC_A : VSYNC_B);
+	int htot = I915_READ(HTOTAL(pipe));
+	int hsync = I915_READ(HSYNC(pipe));
+	int vtot = I915_READ(VTOTAL(pipe));
+	int vsync = I915_READ(VSYNC(pipe));
 
 	mode = kzalloc(sizeof(*mode), GFP_KERNEL);
 	if (!mode)
@@ -5167,7 +5779,6 @@
 
 		dpll &= ~DISPLAY_RATE_SELECT_FPA1;
 		I915_WRITE(dpll_reg, dpll);
-		POSTING_READ(dpll_reg);
 		intel_wait_for_vblank(dev, pipe);
 
 		dpll = I915_READ(dpll_reg);
@@ -5189,7 +5800,7 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int pipe = intel_crtc->pipe;
-	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dpll_reg = DPLL(pipe);
 	int dpll = I915_READ(dpll_reg);
 
 	if (HAS_PCH_SPLIT(dev))
@@ -5211,7 +5822,6 @@
 
 		dpll |= DISPLAY_RATE_SELECT_FPA1;
 		I915_WRITE(dpll_reg, dpll);
-		dpll = I915_READ(dpll_reg);
 		intel_wait_for_vblank(dev, pipe);
 		dpll = I915_READ(dpll_reg);
 		if (!(dpll & DISPLAY_RATE_SELECT_FPA1))
@@ -5237,7 +5847,6 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_crtc *crtc;
 	struct intel_crtc *intel_crtc;
-	int enabled = 0;
 
 	if (!i915_powersave)
 		return;
@@ -5251,16 +5860,11 @@
 		if (!crtc->fb)
 			continue;
 
-		enabled++;
 		intel_crtc = to_intel_crtc(crtc);
 		if (!intel_crtc->busy)
 			intel_decrease_pllclock(crtc);
 	}
 
-	if ((enabled == 1) && (IS_I945G(dev) || IS_I945GM(dev))) {
-		DRM_DEBUG_DRIVER("enable memory self refresh on 945\n");
-		I915_WRITE(FW_BLC_SELF, FW_BLC_SELF_EN_MASK | FW_BLC_SELF_EN);
-	}
 
 	mutex_unlock(&dev->struct_mutex);
 }
@@ -5285,17 +5889,9 @@
 	if (!drm_core_check_feature(dev, DRIVER_MODESET))
 		return;
 
-	if (!dev_priv->busy) {
-		if (IS_I945G(dev) || IS_I945GM(dev)) {
-			u32 fw_blc_self;
-
-			DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
-			fw_blc_self = I915_READ(FW_BLC_SELF);
-			fw_blc_self &= ~FW_BLC_SELF_EN;
-			I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
-		}
+	if (!dev_priv->busy)
 		dev_priv->busy = true;
-	} else
+	else
 		mod_timer(&dev_priv->idle_timer, jiffies +
 			  msecs_to_jiffies(GPU_IDLE_TIMEOUT));
 
@@ -5307,14 +5903,6 @@
 		intel_fb = to_intel_framebuffer(crtc->fb);
 		if (intel_fb->obj == obj) {
 			if (!intel_crtc->busy) {
-				if (IS_I945G(dev) || IS_I945GM(dev)) {
-					u32 fw_blc_self;
-
-					DRM_DEBUG_DRIVER("disable memory self refresh on 945\n");
-					fw_blc_self = I915_READ(FW_BLC_SELF);
-					fw_blc_self &= ~FW_BLC_SELF_EN;
-					I915_WRITE(FW_BLC_SELF, fw_blc_self | FW_BLC_SELF_EN_MASK);
-				}
 				/* Non-busy -> busy, upclock */
 				intel_increase_pllclock(crtc);
 				intel_crtc->busy = true;
@@ -5592,7 +6180,7 @@
 		 * pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
 		 */
 		pf = 0;
-		pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
+		pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff;
 		OUT_RING(pf | pipesrc);
 		break;
 
@@ -5602,8 +6190,8 @@
 		OUT_RING(fb->pitch | obj->tiling_mode);
 		OUT_RING(obj->gtt_offset);
 
-		pf = I915_READ(pipe == 0 ? PFA_CTL_1 : PFB_CTL_1) & PF_ENABLE;
-		pipesrc = I915_READ(pipe == 0 ? PIPEASRC : PIPEBSRC) & 0x0fff0fff;
+		pf = I915_READ(PF_CTL(pipe)) & PF_ENABLE;
+		pipesrc = I915_READ(PIPESRC(pipe)) & 0x0fff0fff;
 		OUT_RING(pf | pipesrc);
 		break;
 	}
@@ -5630,36 +6218,6 @@
 	return ret;
 }
 
-static void intel_crtc_reset(struct drm_crtc *crtc)
-{
-	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
-
-	/* Reset flags back to the 'unknown' status so that they
-	 * will be correctly set on the initial modeset.
-	 */
-	intel_crtc->dpms_mode = -1;
-}
-
-static struct drm_crtc_helper_funcs intel_helper_funcs = {
-	.dpms = intel_crtc_dpms,
-	.mode_fixup = intel_crtc_mode_fixup,
-	.mode_set = intel_crtc_mode_set,
-	.mode_set_base = intel_pipe_set_base,
-	.mode_set_base_atomic = intel_pipe_set_base_atomic,
-	.load_lut = intel_crtc_load_lut,
-	.disable = intel_crtc_disable,
-};
-
-static const struct drm_crtc_funcs intel_crtc_funcs = {
-	.reset = intel_crtc_reset,
-	.cursor_set = intel_crtc_cursor_set,
-	.cursor_move = intel_crtc_cursor_move,
-	.gamma_set = intel_crtc_gamma_set,
-	.set_config = drm_crtc_helper_set_config,
-	.destroy = intel_crtc_destroy,
-	.page_flip = intel_crtc_page_flip,
-};
-
 static void intel_sanitize_modesetting(struct drm_device *dev,
 				       int pipe, int plane)
 {
@@ -5692,24 +6250,46 @@
 	pipe = !pipe;
 
 	/* Disable the plane and wait for it to stop reading from the pipe. */
-	I915_WRITE(reg, val & ~DISPLAY_PLANE_ENABLE);
-	intel_flush_display_plane(dev, plane);
+	intel_disable_plane(dev_priv, plane, pipe);
+	intel_disable_pipe(dev_priv, pipe);
+}
 
-	if (IS_GEN2(dev))
-		intel_wait_for_vblank(dev, pipe);
+static void intel_crtc_reset(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	if (pipe == 0 && (dev_priv->quirks & QUIRK_PIPEA_FORCE))
-		return;
+	/* Reset flags back to the 'unknown' status so that they
+	 * will be correctly set on the initial modeset.
+	 */
+	intel_crtc->dpms_mode = -1;
 
-	/* Switch off the pipe. */
-	reg = PIPECONF(pipe);
-	val = I915_READ(reg);
-	if (val & PIPECONF_ENABLE) {
-		I915_WRITE(reg, val & ~PIPECONF_ENABLE);
-		intel_wait_for_pipe_off(dev, pipe);
-	}
+	/* We need to fix up any BIOS configuration that conflicts with
+	 * our expectations.
+	 */
+	intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
+static struct drm_crtc_helper_funcs intel_helper_funcs = {
+	.dpms = intel_crtc_dpms,
+	.mode_fixup = intel_crtc_mode_fixup,
+	.mode_set = intel_crtc_mode_set,
+	.mode_set_base = intel_pipe_set_base,
+	.mode_set_base_atomic = intel_pipe_set_base_atomic,
+	.load_lut = intel_crtc_load_lut,
+	.disable = intel_crtc_disable,
+};
+
+static const struct drm_crtc_funcs intel_crtc_funcs = {
+	.reset = intel_crtc_reset,
+	.cursor_set = intel_crtc_cursor_set,
+	.cursor_move = intel_crtc_cursor_move,
+	.gamma_set = intel_crtc_gamma_set,
+	.set_config = drm_crtc_helper_set_config,
+	.destroy = intel_crtc_destroy,
+	.page_flip = intel_crtc_page_flip,
+};
+
 static void intel_crtc_init(struct drm_device *dev, int pipe)
 {
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -5759,8 +6339,6 @@
 
 	setup_timer(&intel_crtc->idle_timer, intel_crtc_idle_timer,
 		    (unsigned long)intel_crtc);
-
-	intel_sanitize_modesetting(dev, intel_crtc->pipe, intel_crtc->plane);
 }
 
 int intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
@@ -5997,12 +6575,14 @@
 	int ret;
 
 	obj = to_intel_bo(drm_gem_object_lookup(dev, filp, mode_cmd->handle));
-	if (!obj)
+	if (&obj->base == NULL)
 		return ERR_PTR(-ENOENT);
 
 	intel_fb = kzalloc(sizeof(*intel_fb), GFP_KERNEL);
-	if (!intel_fb)
+	if (!intel_fb) {
+		drm_gem_object_unreference_unlocked(&obj->base);
 		return ERR_PTR(-ENOMEM);
+	}
 
 	ret = intel_framebuffer_init(dev, intel_fb, mode_cmd, obj);
 	if (ret) {
@@ -6319,18 +6899,18 @@
 	I915_WRITE(GEN6_RP_INTERRUPT_LIMITS,
 		   18 << 24 |
 		   6 << 16);
-	I915_WRITE(GEN6_RP_UP_THRESHOLD, 90000);
-	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 100000);
+	I915_WRITE(GEN6_RP_UP_THRESHOLD, 10000);
+	I915_WRITE(GEN6_RP_DOWN_THRESHOLD, 1000000);
 	I915_WRITE(GEN6_RP_UP_EI, 100000);
-	I915_WRITE(GEN6_RP_DOWN_EI, 300000);
+	I915_WRITE(GEN6_RP_DOWN_EI, 5000000);
 	I915_WRITE(GEN6_RP_IDLE_HYSTERSIS, 10);
 	I915_WRITE(GEN6_RP_CONTROL,
 		   GEN6_RP_MEDIA_TURBO |
 		   GEN6_RP_USE_NORMAL_FREQ |
 		   GEN6_RP_MEDIA_IS_GFX |
 		   GEN6_RP_ENABLE |
-		   GEN6_RP_UP_BUSY_MAX |
-		   GEN6_RP_DOWN_BUSY_MIN);
+		   GEN6_RP_UP_BUSY_AVG |
+		   GEN6_RP_DOWN_IDLE_CONT);
 
 	if (wait_for((I915_READ(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY) == 0,
 		     500))
@@ -6359,7 +6939,7 @@
 		DRM_ERROR("timeout waiting for pcode mailbox to finish\n");
 	if (pcu_mbox & (1<<31)) { /* OC supported */
 		max_freq = pcu_mbox & 0xff;
-		DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 100);
+		DRM_DEBUG_DRIVER("overclocking supported, adjusting frequency max to %dMHz\n", pcu_mbox * 50);
 	}
 
 	/* In units of 100MHz */
@@ -6386,6 +6966,7 @@
 void intel_enable_clock_gating(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
+	int pipe;
 
 	/*
 	 * Disable clock gating reported to work incorrectly according to the
@@ -6495,12 +7076,10 @@
 				   ILK_DPARB_CLK_GATE  |
 				   ILK_DPFD_CLK_GATE);
 
-			I915_WRITE(DSPACNTR,
-				   I915_READ(DSPACNTR) |
-				   DISPPLANE_TRICKLE_FEED_DISABLE);
-			I915_WRITE(DSPBCNTR,
-				   I915_READ(DSPBCNTR) |
-				   DISPPLANE_TRICKLE_FEED_DISABLE);
+			for_each_pipe(pipe)
+				I915_WRITE(DSPCNTR(pipe),
+					   I915_READ(DSPCNTR(pipe)) |
+					   DISPPLANE_TRICKLE_FEED_DISABLE);
 		}
 	} else if (IS_G4X(dev)) {
 		uint32_t dspclk_gate;
@@ -6855,10 +7434,6 @@
 	}
 	dev->mode_config.fb_base = dev->agp->base;
 
-	if (IS_MOBILE(dev) || !IS_GEN2(dev))
-		dev_priv->num_pipe = 2;
-	else
-		dev_priv->num_pipe = 1;
 	DRM_DEBUG_KMS("%d display pipe%s available.\n",
 		      dev_priv->num_pipe, dev_priv->num_pipe > 1 ? "s" : "");
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_dp.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_dp.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_dp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_dp.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,6 +49,7 @@
 	uint8_t  link_configuration[DP_LINK_CONFIGURATION_SIZE];
 	bool has_audio;
 	int force_audio;
+	uint32_t color_range;
 	int dpms_mode;
 	uint8_t link_bw;
 	uint8_t lane_count;
@@ -212,7 +213,7 @@
 			return MODE_PANEL;
 	}
 
-	/* only refuse the mode on non eDP since we have seen some wierd eDP panels
+	/* only refuse the mode on non eDP since we have seen some weird eDP panels
 	   which are outside spec tolerances but somehow work by magic */
 	if (!is_edp(intel_dp) &&
 	    (intel_dp_link_required(connector->dev, intel_dp, mode->clock)
@@ -685,6 +686,7 @@
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 	int lane_count = 4, bpp = 24;
 	struct intel_dp_m_n m_n;
+	int pipe = intel_crtc->pipe;
 
 	/*
 	 * Find the lane count in the intel_encoder private
@@ -715,39 +717,19 @@
 			     mode->clock, adjusted_mode->clock, &m_n);
 
 	if (HAS_PCH_SPLIT(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);
-		}
+		I915_WRITE(TRANSDATA_M1(pipe),
+			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+			   m_n.gmch_m);
+		I915_WRITE(TRANSDATA_N1(pipe), m_n.gmch_n);
+		I915_WRITE(TRANSDPLINK_M1(pipe), m_n.link_m);
+		I915_WRITE(TRANSDPLINK_N1(pipe), 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);
-		}
+		I915_WRITE(PIPE_GMCH_DATA_M(pipe),
+			   ((m_n.tu - 1) << PIPE_GMCH_DATA_M_TU_SIZE_SHIFT) |
+			   m_n.gmch_m);
+		I915_WRITE(PIPE_GMCH_DATA_N(pipe), m_n.gmch_n);
+		I915_WRITE(PIPE_DP_LINK_M(pipe), m_n.link_m);
+		I915_WRITE(PIPE_DP_LINK_N(pipe), m_n.link_n);
 	}
 }
 
@@ -760,8 +742,8 @@
 	struct drm_crtc *crtc = intel_dp->base.base.crtc;
 	struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
 
-	intel_dp->DP = (DP_VOLTAGE_0_4 |
-		       DP_PRE_EMPHASIS_0);
+	intel_dp->DP = DP_VOLTAGE_0_4 | DP_PRE_EMPHASIS_0;
+	intel_dp->DP |= intel_dp->color_range;
 
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
 		intel_dp->DP |= DP_SYNC_HS_HIGH;
@@ -813,6 +795,40 @@
 	}
 }
 
+static void ironlake_edp_panel_vdd_on(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp;
+
+	/*
+	 * If the panel wasn't on, make sure there's not a currently
+	 * active PP sequence before enabling AUX VDD.
+	 */
+	if (!(I915_READ(PCH_PP_STATUS) & PP_ON))
+		msleep(dev_priv->panel_t3);
+
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp |= EDP_FORCE_VDD;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
+}
+
+static void ironlake_edp_panel_vdd_off(struct intel_dp *intel_dp)
+{
+	struct drm_device *dev = intel_dp->base.base.dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp;
+
+	pp = I915_READ(PCH_PP_CONTROL);
+	pp &= ~EDP_FORCE_VDD;
+	I915_WRITE(PCH_PP_CONTROL, pp);
+	POSTING_READ(PCH_PP_CONTROL);
+
+	/* Make sure sequencer is idle before allowing subsequent activity */
+	msleep(dev_priv->panel_t12);
+}
+
 /* Returns true if the panel was already on when called */
 static bool ironlake_edp_panel_on (struct intel_dp *intel_dp)
 {
@@ -834,11 +850,6 @@
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
 
-	/* Ouch. We need to wait here for some panels, like Dell e6510
-	 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
-	 */
-	msleep(300);
-
 	if (wait_for((I915_READ(PCH_PP_STATUS) & idle_on_mask) == idle_on_mask,
 		     5000))
 		DRM_ERROR("panel on wait timed out: 0x%08x\n",
@@ -875,11 +886,6 @@
 	pp |= PANEL_POWER_RESET; /* restore panel reset bit */
 	I915_WRITE(PCH_PP_CONTROL, pp);
 	POSTING_READ(PCH_PP_CONTROL);
-
-	/* Ouch. We need to wait here for some panels, like Dell e6510
-	 * https://bugs.freedesktop.org/show_bug.cgi?id=29278i
-	 */
-	msleep(300);
 }
 
 static void ironlake_edp_backlight_on (struct drm_device *dev)
@@ -945,7 +951,7 @@
 
 	if (is_edp(intel_dp)) {
 		ironlake_edp_backlight_off(dev);
-		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_off(dev);
 		if (!is_pch_edp(intel_dp))
 			ironlake_edp_pll_on(encoder);
 		else
@@ -959,10 +965,15 @@
 	struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
 	struct drm_device *dev = encoder->dev;
 
+	if (is_edp(intel_dp))
+		ironlake_edp_panel_vdd_on(intel_dp);
+
 	intel_dp_start_link_train(intel_dp);
 
-	if (is_edp(intel_dp))
+	if (is_edp(intel_dp)) {
 		ironlake_edp_panel_on(intel_dp);
+		ironlake_edp_panel_vdd_off(intel_dp);
+	}
 
 	intel_dp_complete_link_train(intel_dp);
 
@@ -988,9 +999,13 @@
 			ironlake_edp_pll_off(encoder);
 	} else {
 		if (is_edp(intel_dp))
-			ironlake_edp_panel_on(intel_dp);
+			ironlake_edp_panel_vdd_on(intel_dp);
 		if (!(dp_reg & DP_PORT_EN)) {
 			intel_dp_start_link_train(intel_dp);
+			if (is_edp(intel_dp)) {
+				ironlake_edp_panel_on(intel_dp);
+				ironlake_edp_panel_vdd_off(intel_dp);
+			}
 			intel_dp_complete_link_train(intel_dp);
 		}
 		if (is_edp(intel_dp))
@@ -1455,7 +1470,8 @@
 
 	if (!HAS_PCH_CPT(dev) &&
 	    I915_READ(intel_dp->output_reg) & DP_PIPEB_SELECT) {
-		struct intel_crtc *intel_crtc = to_intel_crtc(intel_dp->base.base.crtc);
+		struct drm_crtc *crtc = intel_dp->base.base.crtc;
+
 		/* Hardware workaround: leaving our transcoder select
 		 * set to transcoder B while it's off will prevent the
 		 * corresponding HDMI output on transcoder A.
@@ -1470,7 +1486,19 @@
 		/* Changes to enable or select take place the vblank
 		 * after being written.
 		 */
-		intel_wait_for_vblank(dev, intel_crtc->pipe);
+		if (crtc == NULL) {
+			/* We can arrive here never having been attached
+			 * to a CRTC, for instance, due to inheriting
+			 * random state from the BIOS.
+			 *
+			 * If the pipe is not running, play safe and
+			 * wait for the clocks to stabilise before
+			 * continuing.
+			 */
+			POSTING_READ(intel_dp->output_reg);
+			msleep(50);
+		} else
+			intel_wait_for_vblank(dev, to_intel_crtc(crtc)->pipe);
 	}
 
 	I915_WRITE(intel_dp->output_reg, DP & ~DP_PORT_EN);
@@ -1508,9 +1536,13 @@
 {
 	enum drm_connector_status status;
 
-	/* Can't disconnect eDP */
-	if (is_edp(intel_dp))
-		return connector_status_connected;
+	/* Can't disconnect eDP, but you can close the lid... */
+	if (is_edp(intel_dp)) {
+		status = intel_panel_detect(intel_dp->base.base.dev);
+		if (status == connector_status_unknown)
+			status = connector_status_connected;
+		return status;
+	}
 
 	status = connector_status_disconnected;
 	if (intel_dp_aux_native_read(intel_dp,
@@ -1662,6 +1694,7 @@
 		      struct drm_property *property,
 		      uint64_t val)
 {
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	struct intel_dp *intel_dp = intel_attached_dp(connector);
 	int ret;
 
@@ -1690,6 +1723,14 @@
 		goto done;
 	}
 
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_dp->color_range)
+			return 0;
+
+		intel_dp->color_range = val ? DP_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
@@ -1809,6 +1850,8 @@
 		intel_dp->force_audio_property->values[1] = 1;
 		drm_connector_attach_property(connector, intel_dp->force_audio_property, 0);
 	}
+
+	intel_attach_broadcast_rgb_property(connector);
 }
 
 void
@@ -1826,6 +1869,9 @@
 	if (!intel_dp)
 		return;
 
+	intel_dp->output_reg = output_reg;
+	intel_dp->dpms_mode = -1;
+
 	intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL);
 	if (!intel_connector) {
 		kfree(intel_dp);
@@ -1865,10 +1911,6 @@
 	connector->interlace_allowed = true;
 	connector->doublescan_allowed = 0;
 
-	intel_dp->output_reg = output_reg;
-	intel_dp->has_audio = false;
-	intel_dp->dpms_mode = DRM_MODE_DPMS_ON;
-
 	drm_encoder_init(dev, &intel_encoder->base, &intel_dp_enc_funcs,
 			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(&intel_encoder->base, &intel_dp_helper_funcs);
@@ -1906,21 +1948,33 @@
 	/* Cache some DPCD data in the eDP case */
 	if (is_edp(intel_dp)) {
 		int ret;
-		bool was_on;
+		u32 pp_on, pp_div;
 
-		was_on = ironlake_edp_panel_on(intel_dp);
+		pp_on = I915_READ(PCH_PP_ON_DELAYS);
+		pp_div = I915_READ(PCH_PP_DIVISOR);
+
+		/* Get T3 & T12 values (note: VESA not bspec terminology) */
+		dev_priv->panel_t3 = (pp_on & 0x1fff0000) >> 16;
+		dev_priv->panel_t3 /= 10; /* t3 in 100us units */
+		dev_priv->panel_t12 = pp_div & 0xf;
+		dev_priv->panel_t12 *= 100; /* t12 in 100ms units */
+
+		ironlake_edp_panel_vdd_on(intel_dp);
 		ret = intel_dp_aux_native_read(intel_dp, DP_DPCD_REV,
 					       intel_dp->dpcd,
 					       sizeof(intel_dp->dpcd));
+		ironlake_edp_panel_vdd_off(intel_dp);
 		if (ret == sizeof(intel_dp->dpcd)) {
 			if (intel_dp->dpcd[0] >= 0x11)
 				dev_priv->no_aux_handshake = intel_dp->dpcd[3] &
 					DP_NO_AUX_HANDSHAKE_LINK_TRAINING;
 		} else {
-			DRM_ERROR("failed to retrieve link info\n");
+			/* if this fails, presume the device is a ghost */
+			DRM_INFO("failed to retrieve link info, disabling eDP\n");
+			intel_dp_encoder_destroy(&intel_dp->base.base);
+			intel_dp_destroy(&intel_connector->base);
+			return;
 		}
-		if (!was_on)
-			ironlake_edp_panel_off(dev);
 	}
 
 	intel_encoder->hot_plug = intel_dp_hot_plug;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_drv.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_drv.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_drv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_drv.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 			ret__ = -ETIMEDOUT;				\
 			break;						\
 		}							\
-		if (W && !in_dbg_master()) msleep(W);			\
+		if (W && !(in_atomic() || in_dbg_master())) msleep(W);	\
 	}								\
 	ret__;								\
 })
@@ -217,6 +217,13 @@
 	return dev_priv->pipe_to_crtc_mapping[pipe];
 }
 
+static inline struct drm_crtc *
+intel_get_crtc_for_plane(struct drm_device *dev, int plane)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	return dev_priv->plane_to_crtc_mapping[plane];
+}
+
 struct intel_unpin_work {
 	struct work_struct work;
 	struct drm_device *dev;
@@ -230,6 +237,8 @@
 int intel_ddc_get_modes(struct drm_connector *c, struct i2c_adapter *adapter);
 extern bool intel_ddc_probe(struct intel_encoder *intel_encoder, int ddc_bus);
 
+extern void intel_attach_broadcast_rgb_property(struct drm_connector *connector);
+
 extern void intel_crt_init(struct drm_device *dev);
 extern void intel_hdmi_init(struct drm_device *dev, int sdvox_reg);
 void intel_dip_infoframe_csum(struct dip_infoframe *avi_if);
@@ -260,6 +269,7 @@
 extern void intel_panel_setup_backlight(struct drm_device *dev);
 extern void intel_panel_enable_backlight(struct drm_device *dev);
 extern void intel_panel_disable_backlight(struct drm_device *dev);
+extern enum drm_connector_status intel_panel_detect(struct drm_device *dev);
 
 extern void intel_crtc_load_lut(struct drm_crtc *crtc);
 extern void intel_encoder_prepare (struct drm_encoder *encoder);
@@ -321,12 +331,12 @@
 
 extern void intel_setup_overlay(struct drm_device *dev);
 extern void intel_cleanup_overlay(struct drm_device *dev);
-extern int intel_overlay_switch_off(struct intel_overlay *overlay,
-				    bool interruptible);
+extern int intel_overlay_switch_off(struct intel_overlay *overlay);
 extern int intel_overlay_put_image(struct drm_device *dev, void *data,
 				   struct drm_file *file_priv);
 extern int intel_overlay_attrs(struct drm_device *dev, void *data,
 			       struct drm_file *file_priv);
 
 extern void intel_fb_output_poll_changed(struct drm_device *dev);
+extern void intel_fb_restore_mode(struct drm_device *dev);
 #endif /* __INTEL_DRV_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_dvo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_dvo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_dvo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_dvo.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,7 @@
 	int pipe = intel_crtc->pipe;
 	u32 dvo_val;
 	u32 dvo_reg = intel_dvo->dev.dvo_reg, dvo_srcdim_reg;
-	int dpll_reg = (pipe == 0) ? DPLL_A : DPLL_B;
+	int dpll_reg = DPLL(pipe);
 
 	switch (dvo_reg) {
 	case DVOA:
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_fb.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_fb.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_fb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_fb.c	2011-05-19 00:06:34.000000000 -0400
@@ -264,3 +264,13 @@
 	drm_i915_private_t *dev_priv = dev->dev_private;
 	drm_fb_helper_hotplug_event(&dev_priv->fbdev->helper);
 }
+
+void intel_fb_restore_mode(struct drm_device *dev)
+{
+	int ret;
+	drm_i915_private_t *dev_priv = dev->dev_private;
+
+	ret = drm_fb_helper_restore_fbdev_mode(&dev_priv->fbdev->helper);
+	if (ret)
+		DRM_DEBUG("failed to restore crtc mode\n");
+}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_hdmi.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_hdmi.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_hdmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,6 +41,7 @@
 	struct intel_encoder base;
 	u32 sdvox_reg;
 	int ddc_bus;
+	uint32_t color_range;
 	bool has_hdmi_sink;
 	bool has_audio;
 	int force_audio;
@@ -124,6 +125,7 @@
 	u32 sdvox;
 
 	sdvox = SDVO_ENCODING_HDMI | SDVO_BORDER_ENABLE;
+	sdvox |= intel_hdmi->color_range;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
 		sdvox |= SDVO_VSYNC_ACTIVE_HIGH;
 	if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC)
@@ -278,6 +280,7 @@
 		      uint64_t val)
 {
 	struct intel_hdmi *intel_hdmi = intel_attached_hdmi(connector);
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	int ret;
 
 	ret = drm_connector_property_set_value(connector, property, val);
@@ -305,6 +308,14 @@
 		goto done;
 	}
 
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_hdmi->color_range)
+			return 0;
+
+		intel_hdmi->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
 	return -EINVAL;
 
 done:
@@ -363,6 +374,8 @@
 		intel_hdmi->force_audio_property->values[1] = 1;
 		drm_connector_attach_property(connector, intel_hdmi->force_audio_property, 0);
 	}
+
+	intel_attach_broadcast_rgb_property(connector);
 }
 
 void intel_hdmi_init(struct drm_device *dev, int sdvox_reg)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_i2c.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_i2c.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -259,7 +259,7 @@
 				if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
 					goto timeout;
 				if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
-					return 0;
+					goto clear_err;
 
 				val = I915_READ(GMBUS3 + reg_offset);
 				do {
@@ -287,7 +287,7 @@
 				if (wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_RDY), 50))
 					goto timeout;
 				if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
-					return 0;
+					goto clear_err;
 
 				val = loop = 0;
 				do {
@@ -302,14 +302,31 @@
 		if (i + 1 < num && wait_for(I915_READ(GMBUS2 + reg_offset) & (GMBUS_SATOER | GMBUS_HW_WAIT_PHASE), 50))
 			goto timeout;
 		if (I915_READ(GMBUS2 + reg_offset) & GMBUS_SATOER)
-			return 0;
+			goto clear_err;
 	}
 
-	return num;
+	goto done;
+
+clear_err:
+	/* Toggle the Software Clear Interrupt bit. This has the effect
+	 * of resetting the GMBUS controller and so clearing the
+	 * BUS_ERROR raised by the slave's NAK.
+	 */
+	I915_WRITE(GMBUS1 + reg_offset, GMBUS_SW_CLR_INT);
+	I915_WRITE(GMBUS1 + reg_offset, 0);
+
+done:
+	/* Mark the GMBUS interface as disabled. We will re-enable it at the
+	 * start of the next xfer, till then let it sleep.
+	 */
+	I915_WRITE(GMBUS0 + reg_offset, 0);
+	return i;
 
 timeout:
 	DRM_INFO("GMBUS timed out, falling back to bit banging on pin %d [%s]\n",
 		 bus->reg0 & 0xff, bus->adapter.name);
+	I915_WRITE(GMBUS0 + reg_offset, 0);
+
 	/* Hardware may not support GMBUS over these pins? Try GPIO bitbanging instead. */
 	bus->force_bit = intel_gpio_create(dev_priv, bus->reg0 & 0xff);
 	if (!bus->force_bit)
@@ -384,7 +401,8 @@
 		bus->reg0 = i | GMBUS_RATE_100KHZ;
 
 		/* XXX force bit banging until GMBUS is fully debugged */
-		bus->force_bit = intel_gpio_create(dev_priv, i);
+		if (IS_GEN2(dev))
+			bus->force_bit = intel_gpio_create(dev_priv, i);
 	}
 
 	intel_i2c_reset(dev_priv->dev);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_lvds.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_lvds.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_lvds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_lvds.c	2011-05-19 00:06:34.000000000 -0400
@@ -231,6 +231,7 @@
 	struct intel_lvds *intel_lvds = to_intel_lvds(encoder);
 	struct drm_encoder *tmp_encoder;
 	u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0;
+	int pipe;
 
 	/* Should never happen!! */
 	if (INTEL_INFO(dev)->gen < 4 && intel_crtc->pipe == 0) {
@@ -277,8 +278,8 @@
 	 * 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);
+	for_each_pipe(pipe)
+		I915_WRITE(BCLRPAT(pipe), 0);
 
 	switch (intel_lvds->fitting_mode) {
 	case DRM_MODE_SCALE_CENTER:
@@ -472,15 +473,13 @@
 intel_lvds_detect(struct drm_connector *connector, bool force)
 {
 	struct drm_device *dev = connector->dev;
-	enum drm_connector_status status = connector_status_connected;
+	enum drm_connector_status status;
 
-	/* ACPI lid methods were generally unreliable in this generation, so
-	 * don't even bother.
-	 */
-	if (IS_GEN2(dev) || IS_GEN3(dev))
-		return connector_status_connected;
+	status = intel_panel_detect(dev);
+	if (status != connector_status_unknown)
+		return status;
 
-	return status;
+	return connector_status_connected;
 }
 
 /**
@@ -496,7 +495,7 @@
 		return drm_add_edid_modes(connector, intel_lvds->edid);
 
 	mode = drm_mode_duplicate(dev, intel_lvds->fixed_mode);
-	if (mode == 0)
+	if (mode == NULL)
 		return 0;
 
 	drm_mode_probed_add(connector, mode);
@@ -540,6 +539,9 @@
 	struct drm_device *dev = dev_priv->dev;
 	struct drm_connector *connector = dev_priv->int_lvds_connector;
 
+	if (dev->switch_power_state != DRM_SWITCH_POWER_ON)
+		return NOTIFY_OK;
+
 	/*
 	 * check and update the status of LVDS connector after receiving
 	 * the LID nofication event.
@@ -830,25 +832,6 @@
 	return false;
 }
 
-static bool intel_lvds_ddc_probe(struct drm_device *dev, u8 pin)
-{
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	u8 buf = 0;
-	struct i2c_msg msgs[] = {
-		{
-			.addr = 0xA0,
-			.flags = 0,
-			.len = 1,
-			.buf = &buf,
-		},
-	};
-	struct i2c_adapter *i2c = &dev_priv->gmbus[pin].adapter;
-	/* XXX this only appears to work when using GMBUS */
-	if (intel_gmbus_is_forced_bit(i2c))
-		return true;
-	return i2c_transfer(i2c, msgs, 1) == 1;
-}
-
 /**
  * intel_lvds_init - setup LVDS connectors on this device
  * @dev: drm device
@@ -889,11 +872,6 @@
 		}
 	}
 
-	if (!intel_lvds_ddc_probe(dev, pin)) {
-		DRM_DEBUG_KMS("LVDS did not respond to DDC probe\n");
-		return false;
-	}
-
 	intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL);
 	if (!intel_lvds) {
 		return false;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_modes.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_modes.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_modes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_modes.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,3 +80,33 @@
 
 	return ret;
 }
+
+static const char *broadcast_rgb_names[] = {
+	"Full",
+	"Limited 16:235",
+};
+
+void
+intel_attach_broadcast_rgb_property(struct drm_connector *connector)
+{
+	struct drm_device *dev = connector->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct drm_property *prop;
+	int i;
+
+	prop = dev_priv->broadcast_rgb_property;
+	if (prop == NULL) {
+		prop = drm_property_create(dev, DRM_MODE_PROP_ENUM,
+					   "Broadcast RGB",
+					   ARRAY_SIZE(broadcast_rgb_names));
+		if (prop == NULL)
+			return;
+
+		for (i = 0; i < ARRAY_SIZE(broadcast_rgb_names); i++)
+			drm_property_add_enum(prop, i, i, broadcast_rgb_names[i]);
+
+		dev_priv->broadcast_rgb_property = prop;
+	}
+
+	drm_connector_attach_property(connector, prop, 0);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_opregion.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_opregion.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_opregion.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_opregion.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,8 @@
 
 #define OPREGION_HEADER_OFFSET 0
 #define OPREGION_ACPI_OFFSET   0x100
+#define   ACPI_CLID 0x01ac /* current lid state indicator */
+#define   ACPI_CDCK 0x01b0 /* current docking state indicator */
 #define OPREGION_SWSCI_OFFSET  0x200
 #define OPREGION_ASLE_OFFSET   0x300
 #define OPREGION_VBT_OFFSET    0x400
@@ -489,6 +491,8 @@
 	opregion->header = base;
 	opregion->vbt = base + OPREGION_VBT_OFFSET;
 
+	opregion->lid_state = base + ACPI_CLID;
+
 	mboxes = opregion->header->mboxes;
 	if (mboxes & MBOX_ACPI) {
 		DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_overlay.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_overlay.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_overlay.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_overlay.c	2011-05-19 00:06:34.000000000 -0400
@@ -213,7 +213,6 @@
 
 static int intel_overlay_do_wait_request(struct intel_overlay *overlay,
 					 struct drm_i915_gem_request *request,
-					 bool interruptible,
 					 void (*tail)(struct intel_overlay *))
 {
 	struct drm_device *dev = overlay->dev;
@@ -221,16 +220,14 @@
 	int ret;
 
 	BUG_ON(overlay->last_flip_req);
-	ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
 	if (ret) {
 	    kfree(request);
 	    return ret;
 	}
 	overlay->last_flip_req = request->seqno;
 	overlay->flip_tail = tail;
-	ret = i915_do_wait_request(dev,
-				   overlay->last_flip_req, true,
-				   LP_RING(dev_priv));
+	ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req);
 	if (ret)
 		return ret;
 
@@ -256,7 +253,7 @@
 		return 0;
 
 	/* most i8xx have pipe a forced on, so don't trust dpms mode */
-	if (I915_READ(PIPEACONF) & PIPECONF_ENABLE)
+	if (I915_READ(_PIPEACONF) & PIPECONF_ENABLE)
 		return 0;
 
 	crtc_funcs = crtc->base.helper_private;
@@ -322,7 +319,7 @@
 	OUT_RING(MI_NOOP);
 	ADVANCE_LP_RING();
 
-	ret = intel_overlay_do_wait_request(overlay, request, true, NULL);
+	ret = intel_overlay_do_wait_request(overlay, request, NULL);
 out:
 	if (pipe_a_quirk)
 		i830_deactivate_pipe_a(dev);
@@ -364,7 +361,7 @@
 	OUT_RING(flip_addr);
         ADVANCE_LP_RING();
 
-	ret = i915_add_request(dev, NULL, request, LP_RING(dev_priv));
+	ret = i915_add_request(LP_RING(dev_priv), NULL, request);
 	if (ret) {
 		kfree(request);
 		return ret;
@@ -401,8 +398,7 @@
 }
 
 /* overlay needs to be disabled in OCMD reg */
-static int intel_overlay_off(struct intel_overlay *overlay,
-			     bool interruptible)
+static int intel_overlay_off(struct intel_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -437,14 +433,13 @@
 	OUT_RING(MI_WAIT_FOR_EVENT | MI_WAIT_FOR_OVERLAY_FLIP);
 	ADVANCE_LP_RING();
 
-	return intel_overlay_do_wait_request(overlay, request, interruptible,
+	return intel_overlay_do_wait_request(overlay, request,
 					     intel_overlay_off_tail);
 }
 
 /* recover from an interruption due to a signal
  * We have to be careful not to repeat work forever an make forward progess. */
-static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay,
-						bool interruptible)
+static int intel_overlay_recover_from_interrupt(struct intel_overlay *overlay)
 {
 	struct drm_device *dev = overlay->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -453,8 +448,7 @@
 	if (overlay->last_flip_req == 0)
 		return 0;
 
-	ret = i915_do_wait_request(dev, overlay->last_flip_req,
-				   interruptible, LP_RING(dev_priv));
+	ret = i915_wait_request(LP_RING(dev_priv), overlay->last_flip_req);
 	if (ret)
 		return ret;
 
@@ -499,7 +493,7 @@
 		OUT_RING(MI_NOOP);
 		ADVANCE_LP_RING();
 
-		ret = intel_overlay_do_wait_request(overlay, request, true,
+		ret = intel_overlay_do_wait_request(overlay, request,
 						    intel_overlay_release_old_vid_tail);
 		if (ret)
 			return ret;
@@ -868,8 +862,7 @@
 	return ret;
 }
 
-int intel_overlay_switch_off(struct intel_overlay *overlay,
-			     bool interruptible)
+int intel_overlay_switch_off(struct intel_overlay *overlay)
 {
 	struct overlay_registers *regs;
 	struct drm_device *dev = overlay->dev;
@@ -878,7 +871,7 @@
 	BUG_ON(!mutex_is_locked(&dev->struct_mutex));
 	BUG_ON(!mutex_is_locked(&dev->mode_config.mutex));
 
-	ret = intel_overlay_recover_from_interrupt(overlay, interruptible);
+	ret = intel_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
 		return ret;
 
@@ -893,7 +886,7 @@
 	regs->OCMD = 0;
 	intel_overlay_unmap_regs(overlay, regs);
 
-	ret = intel_overlay_off(overlay, interruptible);
+	ret = intel_overlay_off(overlay);
 	if (ret != 0)
 		return ret;
 
@@ -1135,7 +1128,7 @@
 		mutex_lock(&dev->mode_config.mutex);
 		mutex_lock(&dev->struct_mutex);
 
-		ret = intel_overlay_switch_off(overlay, true);
+		ret = intel_overlay_switch_off(overlay);
 
 		mutex_unlock(&dev->struct_mutex);
 		mutex_unlock(&dev->mode_config.mutex);
@@ -1157,7 +1150,7 @@
 
 	new_bo = to_intel_bo(drm_gem_object_lookup(dev, file_priv,
 						   put_image_rec->bo_handle));
-	if (!new_bo) {
+	if (&new_bo->base == NULL) {
 		ret = -ENOENT;
 		goto out_free;
 	}
@@ -1171,13 +1164,13 @@
 		goto out_unlock;
 	}
 
-	ret = intel_overlay_recover_from_interrupt(overlay, true);
+	ret = intel_overlay_recover_from_interrupt(overlay);
 	if (ret != 0)
 		goto out_unlock;
 
 	if (overlay->crtc != crtc) {
 		struct drm_display_mode *mode = &crtc->base.mode;
-		ret = intel_overlay_switch_off(overlay, true);
+		ret = intel_overlay_switch_off(overlay);
 		if (ret != 0)
 			goto out_unlock;
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_panel.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_panel.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_panel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_panel.c	2011-05-19 00:06:34.000000000 -0400
@@ -280,3 +280,28 @@
 	dev_priv->backlight_level = intel_panel_get_backlight(dev);
 	dev_priv->backlight_enabled = dev_priv->backlight_level != 0;
 }
+
+enum drm_connector_status
+intel_panel_detect(struct drm_device *dev)
+{
+#if 0
+	struct drm_i915_private *dev_priv = dev->dev_private;
+#endif
+
+	if (i915_panel_ignore_lid)
+		return i915_panel_ignore_lid > 0 ?
+			connector_status_connected :
+			connector_status_disconnected;
+
+	/* opregion lid state on HP 2540p is wrong at boot up,
+	 * appears to be either the BIOS or Linux ACPI fault */
+#if 0
+	/* Assume that the BIOS does not lie through the OpRegion... */
+	if (dev_priv->opregion.lid_state)
+		return ioread32(dev_priv->opregion.lid_state) & 0x1 ?
+			connector_status_connected :
+			connector_status_disconnected;
+#endif
+
+	return connector_status_unknown;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_ringbuffer.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,77 +62,63 @@
 		  u32	flush_domains)
 {
 	struct drm_device *dev = ring->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	u32 cmd;
 	int ret;
 
-#if WATCH_EXEC
-	DRM_INFO("%s: invalidate %08x flush %08x\n", __func__,
-		  invalidate_domains, flush_domains);
-#endif
-
-	trace_i915_gem_request_flush(dev, dev_priv->next_seqno,
-				     invalidate_domains, flush_domains);
+	/*
+	 * read/write caches:
+	 *
+	 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
+	 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
+	 * also flushed at 2d versus 3d pipeline switches.
+	 *
+	 * read-only caches:
+	 *
+	 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
+	 * MI_READ_FLUSH is set, and is always flushed on 965.
+	 *
+	 * I915_GEM_DOMAIN_COMMAND may not exist?
+	 *
+	 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
+	 * invalidated when MI_EXE_FLUSH is set.
+	 *
+	 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
+	 * invalidated with every MI_FLUSH.
+	 *
+	 * TLBs:
+	 *
+	 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
+	 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
+	 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
+	 * are flushed at any MI_FLUSH.
+	 */
 
-	if ((invalidate_domains | flush_domains) & I915_GEM_GPU_DOMAINS) {
+	cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
+	if ((invalidate_domains|flush_domains) &
+	    I915_GEM_DOMAIN_RENDER)
+		cmd &= ~MI_NO_WRITE_FLUSH;
+	if (INTEL_INFO(dev)->gen < 4) {
 		/*
-		 * read/write caches:
-		 *
-		 * I915_GEM_DOMAIN_RENDER is always invalidated, but is
-		 * only flushed if MI_NO_WRITE_FLUSH is unset.  On 965, it is
-		 * also flushed at 2d versus 3d pipeline switches.
-		 *
-		 * read-only caches:
-		 *
-		 * I915_GEM_DOMAIN_SAMPLER is flushed on pre-965 if
-		 * MI_READ_FLUSH is set, and is always flushed on 965.
-		 *
-		 * I915_GEM_DOMAIN_COMMAND may not exist?
-		 *
-		 * I915_GEM_DOMAIN_INSTRUCTION, which exists on 965, is
-		 * invalidated when MI_EXE_FLUSH is set.
-		 *
-		 * I915_GEM_DOMAIN_VERTEX, which exists on 965, is
-		 * invalidated with every MI_FLUSH.
-		 *
-		 * TLBs:
-		 *
-		 * On 965, TLBs associated with I915_GEM_DOMAIN_COMMAND
-		 * and I915_GEM_DOMAIN_CPU in are invalidated at PTE write and
-		 * I915_GEM_DOMAIN_RENDER and I915_GEM_DOMAIN_SAMPLER
-		 * are flushed at any MI_FLUSH.
+		 * On the 965, the sampler cache always gets flushed
+		 * and this bit is reserved.
 		 */
+		if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
+			cmd |= MI_READ_FLUSH;
+	}
+	if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
+		cmd |= MI_EXE_FLUSH;
 
-		cmd = MI_FLUSH | MI_NO_WRITE_FLUSH;
-		if ((invalidate_domains|flush_domains) &
-		    I915_GEM_DOMAIN_RENDER)
-			cmd &= ~MI_NO_WRITE_FLUSH;
-		if (INTEL_INFO(dev)->gen < 4) {
-			/*
-			 * On the 965, the sampler cache always gets flushed
-			 * and this bit is reserved.
-			 */
-			if (invalidate_domains & I915_GEM_DOMAIN_SAMPLER)
-				cmd |= MI_READ_FLUSH;
-		}
-		if (invalidate_domains & I915_GEM_DOMAIN_INSTRUCTION)
-			cmd |= MI_EXE_FLUSH;
-
-		if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&
-		    (IS_G4X(dev) || IS_GEN5(dev)))
-			cmd |= MI_INVALIDATE_ISP;
+	if (invalidate_domains & I915_GEM_DOMAIN_COMMAND &&
+	    (IS_G4X(dev) || IS_GEN5(dev)))
+		cmd |= MI_INVALIDATE_ISP;
 
-#if WATCH_EXEC
-		DRM_INFO("%s: queue flush %08x to ring\n", __func__, cmd);
-#endif
-		ret = intel_ring_begin(ring, 2);
-		if (ret)
-			return ret;
+	ret = intel_ring_begin(ring, 2);
+	if (ret)
+		return ret;
 
-		intel_ring_emit(ring, cmd);
-		intel_ring_emit(ring, MI_NOOP);
-		intel_ring_advance(ring);
-	}
+	intel_ring_emit(ring, cmd);
+	intel_ring_emit(ring, MI_NOOP);
+	intel_ring_advance(ring);
 
 	return 0;
 }
@@ -580,9 +566,6 @@
 {
 	int ret;
 
-	if ((flush_domains & I915_GEM_DOMAIN_RENDER) == 0)
-		return 0;
-
 	ret = intel_ring_begin(ring, 2);
 	if (ret)
 		return ret;
@@ -612,7 +595,6 @@
 	intel_ring_emit(ring, MI_USER_INTERRUPT);
 	intel_ring_advance(ring);
 
-	DRM_DEBUG_DRIVER("%s %d\n", ring->name, seqno);
 	*result = seqno;
 	return 0;
 }
@@ -715,11 +697,8 @@
 				u32 offset, u32 len)
 {
 	struct drm_device *dev = ring->dev;
-	drm_i915_private_t *dev_priv = dev->dev_private;
 	int ret;
 
-	trace_i915_gem_request_submit(dev, dev_priv->next_seqno + 1);
-
 	if (IS_I830(dev) || IS_845G(dev)) {
 		ret = intel_ring_begin(ring, 4);
 		if (ret)
@@ -894,6 +873,10 @@
 	/* Disable the ring buffer. The ring must be idle at this point */
 	dev_priv = ring->dev->dev_private;
 	ret = intel_wait_ring_buffer(ring, ring->size - 8);
+	if (ret)
+		DRM_ERROR("failed to quiesce %s whilst cleaning up: %d\n",
+			  ring->name, ret);
+
 	I915_WRITE_CTL(ring, 0);
 
 	drm_core_ioremapfree(&ring->map, ring->dev);
@@ -950,13 +933,13 @@
 			return 0;
 	}
 
-	trace_i915_ring_wait_begin (dev);
+	trace_i915_ring_wait_begin(ring);
 	end = jiffies + 3 * HZ;
 	do {
 		ring->head = I915_READ_HEAD(ring);
 		ring->space = ring_space(ring);
 		if (ring->space >= n) {
-			trace_i915_ring_wait_end(dev);
+			trace_i915_ring_wait_end(ring);
 			return 0;
 		}
 
@@ -970,16 +953,20 @@
 		if (atomic_read(&dev_priv->mm.wedged))
 			return -EAGAIN;
 	} while (!time_after(jiffies, end));
-	trace_i915_ring_wait_end (dev);
+	trace_i915_ring_wait_end(ring);
 	return -EBUSY;
 }
 
 int intel_ring_begin(struct intel_ring_buffer *ring,
 		     int num_dwords)
 {
+	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	int n = 4*num_dwords;
 	int ret;
 
+	if (unlikely(atomic_read(&dev_priv->mm.wedged)))
+		return -EIO;
+
 	if (unlikely(ring->tail + n > ring->effective_size)) {
 		ret = intel_wrap_ring_buffer(ring);
 		if (unlikely(ret))
@@ -1064,9 +1051,6 @@
 	uint32_t cmd;
 	int ret;
 
-	if (((invalidate | flush) & I915_GEM_GPU_DOMAINS) == 0)
-		return 0;
-
 	ret = intel_ring_begin(ring, 4);
 	if (ret)
 		return ret;
@@ -1238,9 +1222,6 @@
 	uint32_t cmd;
 	int ret;
 
-	if (((invalidate | flush) & I915_GEM_DOMAIN_RENDER) == 0)
-		return 0;
-
 	ret = blt_ring_begin(ring, 4);
 	if (ret)
 		return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_ringbuffer.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,7 @@
 		RING_BLT = 0x4,
 	} id;
 	u32		mmio_base;
-	void		*virtual_start;
+	void		__iomem *virtual_start;
 	struct		drm_device *dev;
 	struct		drm_i915_gem_object *obj;
 
@@ -59,6 +59,7 @@
 	u32		irq_refcount;
 	u32		irq_mask;
 	u32		irq_seqno;		/* last seq seem at irq time */
+	u32		trace_irq_seqno;
 	u32		waiting_seqno;
 	u32		sync_seqno[I915_NUM_RINGS-1];
 	bool __must_check (*irq_get)(struct intel_ring_buffer *ring);
@@ -142,6 +143,26 @@
 	return ioread32(ring->status_page.page_addr + reg);
 }
 
+/**
+ * Reads a dword out of the status page, which is written to from the command
+ * queue by automatic updates, MI_REPORT_HEAD, MI_STORE_DATA_INDEX, or
+ * MI_STORE_DATA_IMM.
+ *
+ * The following dwords have a reserved meaning:
+ * 0x00: ISR copy, updated when an ISR bit not set in the HWSTAM changes.
+ * 0x04: ring 0 head pointer
+ * 0x05: ring 1 head pointer (915-class)
+ * 0x06: ring 2 head pointer (915-class)
+ * 0x10-0x1b: Context status DWords (GM45)
+ * 0x1f: Last written status offset. (GM45)
+ *
+ * The area from dword 0x20 to 0x3ff is available for driver usage.
+ */
+#define READ_HWSP(dev_priv, reg) intel_read_status_page(LP_RING(dev_priv), reg)
+#define READ_BREADCRUMB(dev_priv) READ_HWSP(dev_priv, I915_BREADCRUMB_INDEX)
+#define I915_GEM_HWS_INDEX		0x20
+#define I915_BREADCRUMB_INDEX		0x21
+
 void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring);
 int __must_check intel_wait_ring_buffer(struct intel_ring_buffer *ring, int n);
 int __must_check intel_ring_begin(struct intel_ring_buffer *ring, int n);
@@ -167,6 +188,12 @@
 u32 intel_ring_get_active_head(struct intel_ring_buffer *ring);
 void intel_ring_setup_status_page(struct intel_ring_buffer *ring);
 
+static inline void i915_trace_irq_get(struct intel_ring_buffer *ring, u32 seqno)
+{
+	if (ring->trace_irq_seqno == 0 && ring->irq_get(ring))
+		ring->trace_irq_seqno = seqno;
+}
+
 /* DRI warts */
 int intel_render_ring_init_dri(struct drm_device *dev, u64 start, u32 size);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_sdvo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_sdvo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_sdvo.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,6 +93,12 @@
 	uint16_t attached_output;
 
 	/**
+	 * This is used to select the color range of RBG outputs in HDMI mode.
+	 * It is only valid when using TMDS encoding and 8 bit per color mode.
+	 */
+	uint32_t color_range;
+
+	/**
 	 * This is set if we're going to treat the device as TV-out.
 	 *
 	 * While we have these nice friendly flags for output types that ought
@@ -585,6 +591,7 @@
 {
 	struct intel_sdvo_get_trained_inputs_response response;
 
+	BUILD_BUG_ON(sizeof(response) != 1);
 	if (!intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_TRAINED_INPUTS,
 				  &response, sizeof(response)))
 		return false;
@@ -632,6 +639,7 @@
 {
 	struct intel_sdvo_pixel_clock_range clocks;
 
+	BUILD_BUG_ON(sizeof(clocks) != 4);
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_INPUT_PIXEL_CLOCK_RANGE,
 				  &clocks, sizeof(clocks)))
@@ -699,6 +707,8 @@
 static bool intel_sdvo_get_preferred_input_timing(struct intel_sdvo *intel_sdvo,
 						  struct intel_sdvo_dtd *dtd)
 {
+	BUILD_BUG_ON(sizeof(dtd->part1) != 8);
+	BUILD_BUG_ON(sizeof(dtd->part2) != 8);
 	return intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART1,
 				    &dtd->part1, sizeof(dtd->part1)) &&
 		intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_PREFERRED_INPUT_TIMING_PART2,
@@ -796,6 +806,7 @@
 {
 	struct intel_sdvo_encode encode;
 
+	BUILD_BUG_ON(sizeof(encode) != 2);
 	return intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_SUPP_ENCODE,
 				  &encode, sizeof(encode));
@@ -1051,6 +1062,8 @@
 	/* Set the SDVO control regs. */
 	if (INTEL_INFO(dev)->gen >= 4) {
 		sdvox = 0;
+		if (intel_sdvo->is_hdmi)
+			sdvox |= intel_sdvo->color_range;
 		if (INTEL_INFO(dev)->gen < 5)
 			sdvox |= SDVO_BORDER_ENABLE;
 		if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC)
@@ -1162,6 +1175,7 @@
 
 static bool intel_sdvo_get_capabilities(struct intel_sdvo *intel_sdvo, struct intel_sdvo_caps *caps)
 {
+	BUILD_BUG_ON(sizeof(*caps) != 8);
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_DEVICE_CAPS,
 				  caps, sizeof(*caps)))
@@ -1268,33 +1282,9 @@
 static bool
 intel_sdvo_multifunc_encoder(struct intel_sdvo *intel_sdvo)
 {
-	int caps = 0;
-
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_TMDS0 | SDVO_OUTPUT_TMDS1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_RGB0 | SDVO_OUTPUT_RGB1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_SVID0 | SDVO_OUTPUT_SVID1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_CVBS0 | SDVO_OUTPUT_CVBS1))
-		caps++;
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_YPRPB0 | SDVO_OUTPUT_YPRPB1))
-		caps++;
-
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_SCART0 | SDVO_OUTPUT_SCART1))
-		caps++;
-
-	if (intel_sdvo->caps.output_flags &
-		(SDVO_OUTPUT_LVDS0 | SDVO_OUTPUT_LVDS1))
-		caps++;
-
-	return (caps > 1);
+	/* Is there more than one type of output? */
+	int caps = intel_sdvo->caps.output_flags & 0xf;
+	return caps & -caps;
 }
 
 static struct edid *
@@ -1482,7 +1472,7 @@
  * Note!  This is in reply order (see loop in get_tv_modes).
  * XXX: all 60Hz refresh?
  */
-struct drm_display_mode sdvo_tv_modes[] = {
+static const struct drm_display_mode sdvo_tv_modes[] = {
 	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 5815, 320, 321, 384,
 		   416, 0, 200, 201, 232, 233, 0,
 		   DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC) },
@@ -1713,6 +1703,7 @@
 {
 	struct intel_sdvo *intel_sdvo = intel_attached_sdvo(connector);
 	struct intel_sdvo_connector *intel_sdvo_connector = to_intel_sdvo_connector(connector);
+	struct drm_i915_private *dev_priv = connector->dev->dev_private;
 	uint16_t temp_value;
 	uint8_t cmd;
 	int ret;
@@ -1742,6 +1733,14 @@
 		goto done;
 	}
 
+	if (property == dev_priv->broadcast_rgb_property) {
+		if (val == !!intel_sdvo->color_range)
+			return 0;
+
+		intel_sdvo->color_range = val ? SDVO_COLOR_RANGE_16_235 : 0;
+		goto done;
+	}
+
 #define CHECK_PROPERTY(name, NAME) \
 	if (intel_sdvo_connector->name == property) { \
 		if (intel_sdvo_connector->cur_##name == temp_value) return 0; \
@@ -2046,6 +2045,9 @@
 		drm_connector_attach_property(&connector->base.base,
 					      connector->force_audio_property, 0);
 	}
+
+	if (INTEL_INFO(dev)->gen >= 4 && IS_MOBILE(dev))
+		intel_attach_broadcast_rgb_property(&connector->base.base);
 }
 
 static bool
@@ -2268,6 +2270,7 @@
 	if (!intel_sdvo_set_target_output(intel_sdvo, type))
 		return false;
 
+	BUILD_BUG_ON(sizeof(format) != 6);
 	if (!intel_sdvo_get_value(intel_sdvo,
 				  SDVO_CMD_GET_SUPPORTED_TV_FORMATS,
 				  &format, sizeof(format)))
@@ -2474,6 +2477,8 @@
 		uint16_t response;
 	} enhancements;
 
+	BUILD_BUG_ON(sizeof(enhancements) != 2);
+
 	enhancements.response = 0;
 	intel_sdvo_get_value(intel_sdvo,
 			     SDVO_CMD_GET_SUPPORTED_ENHANCEMENTS,
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_sdvo_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -230,7 +230,7 @@
 } __attribute__((packed));
 
 /**
- * Takes a struct intel_sdvo_output_flags of which outputs are targetted by
+ * Takes a struct intel_sdvo_output_flags of which outputs are targeted by
  * future output commands.
  *
  * Affected commands inclue SET_OUTPUT_TIMINGS_PART[12],
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_tv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_tv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/i915/intel_tv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/i915/intel_tv.c	2011-05-19 00:06:34.000000000 -0400
@@ -1006,6 +1006,7 @@
 	const struct video_levels *video_levels;
 	const struct color_conversion *color_conversion;
 	bool burst_ena;
+	int pipe = intel_crtc->pipe;
 
 	if (!tv_mode)
 		return;	/* can't happen (mode_prepare prevents this) */
@@ -1149,14 +1150,11 @@
 			   ((video_levels->black << TV_BLACK_LEVEL_SHIFT) |
 			    (video_levels->blank << TV_BLANK_LEVEL_SHIFT)));
 	{
-		int pipeconf_reg = (intel_crtc->pipe == 0) ?
-			PIPEACONF : PIPEBCONF;
-		int dspcntr_reg = (intel_crtc->plane == 0) ?
-			DSPACNTR : DSPBCNTR;
+		int pipeconf_reg = PIPECONF(pipe);
+		int dspcntr_reg = DSPCNTR(intel_crtc->plane);
 		int pipeconf = I915_READ(pipeconf_reg);
 		int dspcntr = I915_READ(dspcntr_reg);
-		int dspbase_reg = (intel_crtc->plane == 0) ?
-			DSPAADDR : DSPBADDR;
+		int dspbase_reg = DSPADDR(intel_crtc->plane);
 		int xpos = 0x0, ypos = 0x0;
 		unsigned int xsize, ysize;
 		/* Pipe must be off here */
@@ -1380,7 +1378,9 @@
 	if (type < 0)
 		return connector_status_disconnected;
 
+	intel_tv->type = type;
 	intel_tv_find_better_format(connector);
+
 	return connector_status_connected;
 }
 
@@ -1672,8 +1672,7 @@
 	 *
 	 * More recent chipsets favour HDMI rather than integrated S-Video.
 	 */
-	connector->polled =
-		DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
+	connector->polled = DRM_CONNECTOR_POLL_CONNECT;
 
 	drm_connector_init(dev, connector, &intel_tv_connector_funcs,
 			   DRM_MODE_CONNECTOR_SVIDEO);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/Kconfig linux-libre-2.6.39-gnu/drivers/gpu/drm/Kconfig
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 	depends on DRM
 	select FB
 	select FRAMEBUFFER_CONSOLE if !EXPERT
+	select FRAMEBUFFER_CONSOLE_DETECT_PRIMARY if FRAMEBUFFER_CONSOLE
 	help
 	  FB and CRTC helpers for KMS drivers.
 
@@ -73,32 +74,17 @@
 
 config DRM_I810
 	tristate "Intel I810"
-	# BKL usage in order to avoid AB-BA deadlocks, may become BROKEN_ON_SMP
-	depends on DRM && AGP && AGP_INTEL && BKL
+	# !PREEMPT because of missing ioctl locking
+	depends on DRM && AGP && AGP_INTEL && (!PREEMPT || BROKEN)
 	help
 	  Choose this option if you have an Intel I810 graphics card.  If M is
 	  selected, the module will be called i810.  AGP support is required
 	  for this driver to work.
 
-choice
-	prompt "Intel 830M, 845G, 852GM, 855GM, 865G"
-	depends on DRM && AGP && AGP_INTEL
-	optional
-
-config DRM_I830
-	tristate "i830 driver"
-	# BKL usage in order to avoid AB-BA deadlocks, i830 may get removed
-	depends on BKL
-	help
-	  Choose this option if you have a system that has Intel 830M, 845G,
-	  852GM, 855GM or 865G integrated graphics.  If M is selected, the
-	  module will be called i830.  AGP support is required for this driver
-	  to work. This driver is used by the older X releases X.org 6.7 and
-	  XFree86 4.3. If unsure, build this and i915 as modules and the X server
-	  will load the correct one.
-
 config DRM_I915
-	tristate "i915 driver"
+	tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics"
+	depends on DRM
+	depends on AGP
 	depends on AGP_INTEL
 	# we need shmfs for the swappable backing store, and in particular
 	# the shmem_readpage() which depends upon tmpfs
@@ -111,16 +97,25 @@
 	# i915 depends on ACPI_VIDEO when ACPI is enabled
 	# but for select to work, need to select ACPI_VIDEO's dependencies, ick
 	select BACKLIGHT_CLASS_DEVICE if ACPI
+	select VIDEO_OUTPUT_CONTROL if ACPI
 	select INPUT if ACPI
 	select ACPI_VIDEO if ACPI
 	select ACPI_BUTTON if ACPI
 	help
-	  Choose this option if you have a system that has Intel 830M, 845G,
-	  852GM, 855GM 865G or 915G integrated graphics.  If M is selected, the
-	  module will be called i915.  AGP support is required for this driver
-	  to work. This driver is used by the Intel driver in X.org 6.8 and
-	  XFree86 4.4 and above. If unsure, build this and i830 as modules and
-	  the X server will load the correct one.
+	  Choose this option if you have a system that has "Intel Graphics
+	  Media Accelerator" or "HD Graphics" integrated graphics,
+	  including 830M, 845G, 852GM, 855GM, 865G, 915G, 945G, 965G,
+	  G35, G41, G43, G45 chipsets and Celeron, Pentium, Core i3,
+	  Core i5, Core i7 as well as Atom CPUs with integrated graphics.
+	  If M is selected, the module will be called i915.  AGP support
+	  is required for this driver to work. This driver is used by
+	  the Intel driver in X.org 6.8 and XFree86 4.4 and above. It
+	  replaces the older i830 module that supported a subset of the
+	  hardware in older X.org releases.
+
+	  Note that the older i810/i815 chipsets require the use of the
+	  i810 driver instead, and the Atom z5xx series has an entirely
+	  different implementation.
 
 config DRM_I915_KMS
 	bool "Enable modesetting on intel by default"
@@ -132,8 +127,6 @@
 	  the driver to bind to PCI devices, which precludes loading things
 	  like intelfb.
 
-endchoice
-
 config DRM_MGA
 	tristate "Matrox g200/g400"
 	depends on DRM && PCI
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/Makefile linux-libre-2.6.39-gnu/drivers/gpu/drm/Makefile
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
 		drm_platform.o drm_sysfs.o drm_hashtab.o drm_sman.o drm_mm.o \
 		drm_crtc.o drm_modes.o drm_edid.o \
 		drm_info.o drm_debugfs.o drm_encoder_slave.o \
-		drm_trace_points.o drm_global.o
+		drm_trace_points.o drm_global.o drm_usb.o
 
 drm-$(CONFIG_COMPAT) += drm_ioc32.o
 
@@ -29,7 +29,6 @@
 obj-$(CONFIG_DRM_RADEON)+= radeon/
 obj-$(CONFIG_DRM_MGA)	+= mga/
 obj-$(CONFIG_DRM_I810)	+= i810/
-obj-$(CONFIG_DRM_I830)	+= i830/
 obj-$(CONFIG_DRM_I915)  += i915/
 obj-$(CONFIG_DRM_SIS)   += sis/
 obj-$(CONFIG_DRM_SAVAGE)+= savage/
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/mga/mga_dma.c linux-libre-2.6.39-gnu/drivers/gpu/drm/mga/mga_dma.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/mga/mga_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/mga/mga_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -426,7 +426,7 @@
  * Bootstrap the driver for AGP DMA.
  *
  * \todo
- * Investigate whether there is any benifit to storing the WARP microcode in
+ * Investigate whether there is any benefit to storing the WARP microcode in
  * AGP memory.  If not, the microcode may as well always be put in PCI
  * memory.
  *
@@ -703,7 +703,7 @@
 static int mga_do_dma_bootstrap(struct drm_device *dev,
 				drm_mga_dma_bootstrap_t *dma_bs)
 {
-	const int is_agp = (dma_bs->agp_mode != 0) && drm_device_is_agp(dev);
+	const int is_agp = (dma_bs->agp_mode != 0) && drm_pci_device_is_agp(dev);
 	int err;
 	drm_mga_private_t *const dev_priv =
 	    (drm_mga_private_t *) dev->dev_private;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/mga/mga_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/mga/mga_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/mga/mga_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/mga/mga_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,10 +75,6 @@
 #endif
 		.llseek = noop_llseek,
 	},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -88,15 +84,20 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver mga_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init mga_init(void)
 {
 	driver.num_ioctls = mga_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &mga_pci_driver);
 }
 
 static void __exit mga_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &mga_pci_driver);
 }
 
 module_init(mga_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_backlight.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,18 +88,20 @@
 	.update_status = nv50_set_intensity,
 };
 
-static int nouveau_nv40_backlight_init(struct drm_device *dev)
+static int nouveau_nv40_backlight_init(struct drm_connector *connector)
 {
-	struct backlight_properties props;
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
 	struct backlight_device *bd;
 
 	if (!(nv_rd32(dev, NV40_PMC_BACKLIGHT) & NV40_PMC_BACKLIGHT_MASK))
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 31;
-	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
 				       &nv40_bl_ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -111,18 +113,20 @@
 	return 0;
 }
 
-static int nouveau_nv50_backlight_init(struct drm_device *dev)
+static int nouveau_nv50_backlight_init(struct drm_connector *connector)
 {
-	struct backlight_properties props;
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct backlight_properties props;
 	struct backlight_device *bd;
 
 	if (!nv_rd32(dev, NV50_PDISPLAY_SOR_BACKLIGHT))
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 1025;
-	bd = backlight_device_register("nv_backlight", &dev->pdev->dev, dev,
+	bd = backlight_device_register("nv_backlight", &connector->kdev, dev,
 				       &nv50_bl_ops, &props);
 	if (IS_ERR(bd))
 		return PTR_ERR(bd);
@@ -133,8 +137,9 @@
 	return 0;
 }
 
-int nouveau_backlight_init(struct drm_device *dev)
+int nouveau_backlight_init(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 #ifdef CONFIG_ACPI
@@ -147,9 +152,9 @@
 
 	switch (dev_priv->card_type) {
 	case NV_40:
-		return nouveau_nv40_backlight_init(dev);
+		return nouveau_nv40_backlight_init(connector);
 	case NV_50:
-		return nouveau_nv50_backlight_init(dev);
+		return nouveau_nv50_backlight_init(connector);
 	default:
 		break;
 	}
@@ -157,8 +162,9 @@
 	return 0;
 }
 
-void nouveau_backlight_exit(struct drm_device *dev)
+void nouveau_backlight_exit(struct drm_connector *connector)
 {
+	struct drm_device *dev = connector->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	if (dev_priv->backlight) {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_bios.c	2011-05-19 00:06:34.000000000 -0400
@@ -269,7 +269,7 @@
 	int (*handler)(struct nvbios *, uint16_t, struct init_exec *);
 };
 
-static int parse_init_table(struct nvbios *, unsigned int, struct init_exec *);
+static int parse_init_table(struct nvbios *, uint16_t, struct init_exec *);
 
 #define MACRO_INDEX_SIZE	2
 #define MACRO_SIZE		8
@@ -282,7 +282,7 @@
 {
 #if 0
 	sync();
-	msleep(2);
+	mdelay(2);
 #endif
 }
 
@@ -1904,7 +1904,7 @@
 			BIOSLOG(bios, "0x%04X: "
 				"Condition not met, sleeping for 20ms\n",
 								offset);
-			msleep(20);
+			mdelay(20);
 		}
 	}
 
@@ -1938,7 +1938,7 @@
 	BIOSLOG(bios, "0x%04X: Sleeping for 0x%04X milliseconds\n",
 		offset, time);
 
-	msleep(time);
+	mdelay(time);
 
 	return 3;
 }
@@ -2011,6 +2011,27 @@
 }
 
 static int
+init_jump(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
+{
+	/*
+	 * INIT_JUMP   opcode: 0x5C ('\')
+	 *
+	 * offset      (8  bit): opcode
+	 * offset + 1  (16 bit): offset (in bios)
+	 *
+	 * Continue execution of init table from 'offset'
+	 */
+
+	uint16_t jmp_offset = ROM16(bios->data[offset + 1]);
+
+	if (!iexec->execute)
+		return 3;
+
+	BIOSLOG(bios, "0x%04X: Jump to 0x%04X\n", offset, jmp_offset);
+	return jmp_offset - offset;
+}
+
+static int
 init_i2c_if(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
 	/*
@@ -2962,7 +2983,7 @@
 	if (time < 1000)
 		udelay(time);
 	else
-		msleep((time + 900) / 1000);
+		mdelay((time + 900) / 1000);
 
 	return 3;
 }
@@ -3659,6 +3680,7 @@
 	{ "INIT_ZM_REG_SEQUENCE"              , 0x58, init_zm_reg_sequence            },
 	/* INIT_INDIRECT_REG (0x5A, 7, 0, 0) removed due to no example of use */
 	{ "INIT_SUB_DIRECT"                   , 0x5B, init_sub_direct                 },
+	{ "INIT_JUMP"                         , 0x5C, init_jump                       },
 	{ "INIT_I2C_IF"                       , 0x5E, init_i2c_if                     },
 	{ "INIT_COPY_NV_REG"                  , 0x5F, init_copy_nv_reg                },
 	{ "INIT_ZM_INDEX_IO"                  , 0x62, init_zm_index_io                },
@@ -3700,8 +3722,7 @@
 #define MAX_TABLE_OPS 1000
 
 static int
-parse_init_table(struct nvbios *bios, unsigned int offset,
-		 struct init_exec *iexec)
+parse_init_table(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
 {
 	/*
 	 * Parses all commands in an init table.
@@ -3856,7 +3877,7 @@
 
 	if (script == LVDS_PANEL_OFF) {
 		/* off-on delay in ms */
-		msleep(ROM16(bios->data[bios->fp.xlated_entry + 7]));
+		mdelay(ROM16(bios->data[bios->fp.xlated_entry + 7]));
 	}
 #ifdef __powerpc__
 	/* Powerbook specific quirks */
@@ -5950,6 +5971,11 @@
 	}
 }
 
+static const u8 hpd_gpio[16] = {
+	0xff, 0x07, 0x08, 0xff, 0xff, 0x51, 0x52, 0xff,
+	0xff, 0xff, 0xff, 0xff, 0xff, 0x5e, 0x5f, 0x60,
+};
+
 static void
 parse_dcb_connector_table(struct nvbios *bios)
 {
@@ -5986,23 +6012,9 @@
 
 		cte->type  = (cte->entry & 0x000000ff) >> 0;
 		cte->index2 = (cte->entry & 0x00000f00) >> 8;
-		switch (cte->entry & 0x00033000) {
-		case 0x00001000:
-			cte->gpio_tag = 0x07;
-			break;
-		case 0x00002000:
-			cte->gpio_tag = 0x08;
-			break;
-		case 0x00010000:
-			cte->gpio_tag = 0x51;
-			break;
-		case 0x00020000:
-			cte->gpio_tag = 0x52;
-			break;
-		default:
-			cte->gpio_tag = 0xff;
-			break;
-		}
+
+		cte->gpio_tag = ffs((cte->entry & 0x07033000) >> 12);
+		cte->gpio_tag = hpd_gpio[cte->gpio_tag];
 
 		if (cte->type == 0xff)
 			continue;
@@ -6342,6 +6354,32 @@
 		}
 	}
 
+	/* XFX GT-240X-YA
+	 *
+	 * So many things wrong here, replace the entire encoder table..
+	 */
+	if (nv_match_device(dev, 0x0ca3, 0x1682, 0x3003)) {
+		if (idx == 0) {
+			*conn = 0x02001300; /* VGA, connector 1 */
+			*conf = 0x00000028;
+		} else
+		if (idx == 1) {
+			*conn = 0x01010312; /* DVI, connector 0 */
+			*conf = 0x00020030;
+		} else
+		if (idx == 2) {
+			*conn = 0x01010310; /* VGA, connector 0 */
+			*conf = 0x00000028;
+		} else
+		if (idx == 3) {
+			*conn = 0x02022362; /* HDMI, connector 2 */
+			*conf = 0x00020010;
+		} else {
+			*conn = 0x0000000e; /* EOL */
+			*conf = 0x00000000;
+		}
+	}
+
 	return true;
 }
 
@@ -6702,11 +6740,11 @@
 	struct nvbios *bios = &dev_priv->vbios;
 	struct init_exec iexec = { true, false };
 
-	mutex_lock(&bios->lock);
+	spin_lock_bh(&bios->lock);
 	bios->display.output = dcbent;
 	parse_init_table(bios, table, &iexec);
 	bios->display.output = NULL;
-	mutex_unlock(&bios->lock);
+	spin_unlock_bh(&bios->lock);
 }
 
 static bool NVInitVBIOS(struct drm_device *dev)
@@ -6715,7 +6753,7 @@
 	struct nvbios *bios = &dev_priv->vbios;
 
 	memset(bios, 0, sizeof(struct nvbios));
-	mutex_init(&bios->lock);
+	spin_lock_init(&bios->lock);
 	bios->dev = dev;
 
 	if (!NVShadowVBIOS(dev, bios->data))
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_bios.h	2011-05-19 00:06:34.000000000 -0400
@@ -251,7 +251,7 @@
 	uint8_t digital_min_front_porch;
 	bool fp_no_ddc;
 
-	struct mutex lock;
+	spinlock_t lock;
 
 	uint8_t data[NV_PROM_SIZE];
 	unsigned int length;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_bo.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,8 +57,8 @@
 }
 
 static void
-nouveau_bo_fixup_align(struct nouveau_bo *nvbo, int *align, int *size,
-		       int *page_shift)
+nouveau_bo_fixup_align(struct nouveau_bo *nvbo, u32 flags,
+		       int *align, int *size, int *page_shift)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(nvbo->bo.bdev);
 
@@ -83,7 +83,7 @@
 		}
 	} else {
 		if (likely(dev_priv->chan_vm)) {
-			if (*size > 256 * 1024)
+			if (!(flags & TTM_PL_FLAG_TT) &&  *size > 256 * 1024)
 				*page_shift = dev_priv->chan_vm->lpg_shift;
 			else
 				*page_shift = dev_priv->chan_vm->spg_shift;
@@ -101,8 +101,7 @@
 int
 nouveau_bo_new(struct drm_device *dev, struct nouveau_channel *chan,
 	       int size, int align, uint32_t flags, uint32_t tile_mode,
-	       uint32_t tile_flags, bool no_vm, bool mappable,
-	       struct nouveau_bo **pnvbo)
+	       uint32_t tile_flags, struct nouveau_bo **pnvbo)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
@@ -113,16 +112,14 @@
 		return -ENOMEM;
 	INIT_LIST_HEAD(&nvbo->head);
 	INIT_LIST_HEAD(&nvbo->entry);
-	nvbo->mappable = mappable;
-	nvbo->no_vm = no_vm;
 	nvbo->tile_mode = tile_mode;
 	nvbo->tile_flags = tile_flags;
 	nvbo->bo.bdev = &dev_priv->ttm.bdev;
 
-	nouveau_bo_fixup_align(nvbo, &align, &size, &page_shift);
+	nouveau_bo_fixup_align(nvbo, flags, &align, &size, &page_shift);
 	align >>= PAGE_SHIFT;
 
-	if (!nvbo->no_vm && dev_priv->chan_vm) {
+	if (dev_priv->chan_vm) {
 		ret = nouveau_vm_get(dev_priv->chan_vm, size, page_shift,
 				     NV_MEM_ACCESS_RW, &nvbo->vma);
 		if (ret) {
@@ -144,11 +141,8 @@
 	}
 	nvbo->channel = NULL;
 
-	if (nvbo->vma.node) {
-		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
-			nvbo->bo.offset = nvbo->vma.offset;
-	}
-
+	if (nvbo->vma.node)
+		nvbo->bo.offset = nvbo->vma.offset;
 	*pnvbo = nvbo;
 	return 0;
 }
@@ -318,11 +312,8 @@
 	if (ret)
 		return ret;
 
-	if (nvbo->vma.node) {
-		if (nvbo->bo.mem.mem_type == TTM_PL_VRAM)
-			nvbo->bo.offset = nvbo->vma.offset;
-	}
-
+	if (nvbo->vma.node)
+		nvbo->bo.offset = nvbo->vma.offset;
 	return 0;
 }
 
@@ -385,7 +376,8 @@
 	case NOUVEAU_GART_AGP:
 		return ttm_agp_backend_init(bdev, dev->agp->bridge);
 #endif
-	case NOUVEAU_GART_SGDMA:
+	case NOUVEAU_GART_PDMA:
+	case NOUVEAU_GART_HW:
 		return nouveau_sgdma_init_ttm(dev);
 	default:
 		NV_ERROR(dev, "Unknown GART type %d\n",
@@ -431,7 +423,10 @@
 		man->default_caching = TTM_PL_FLAG_WC;
 		break;
 	case TTM_PL_TT:
-		man->func = &ttm_bo_manager_func;
+		if (dev_priv->card_type >= NV_50)
+			man->func = &nouveau_gart_manager;
+		else
+			man->func = &ttm_bo_manager_func;
 		switch (dev_priv->gart_info.type) {
 		case NOUVEAU_GART_AGP:
 			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE;
@@ -439,7 +434,8 @@
 				TTM_PL_FLAG_WC;
 			man->default_caching = TTM_PL_FLAG_WC;
 			break;
-		case NOUVEAU_GART_SGDMA:
+		case NOUVEAU_GART_PDMA:
+		case NOUVEAU_GART_HW:
 			man->flags = TTM_MEMTYPE_FLAG_MAPPABLE |
 				     TTM_MEMTYPE_FLAG_CMA;
 			man->available_caching = TTM_PL_MASK_CACHING;
@@ -501,45 +497,22 @@
 	return ret;
 }
 
-static inline uint32_t
-nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
-		      struct nouveau_channel *chan, struct ttm_mem_reg *mem)
-{
-	struct nouveau_bo *nvbo = nouveau_bo(bo);
-
-	if (nvbo->no_vm) {
-		if (mem->mem_type == TTM_PL_TT)
-			return NvDmaGART;
-		return NvDmaVRAM;
-	}
-
-	if (mem->mem_type == TTM_PL_TT)
-		return chan->gart_handle;
-	return chan->vram_handle;
-}
-
 static int
 nvc0_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_mem *old_node = old_mem->mm_node;
+	struct nouveau_mem *new_node = new_mem->mm_node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	u64 src_offset = old_mem->start << PAGE_SHIFT;
-	u64 dst_offset = new_mem->start << PAGE_SHIFT;
 	u32 page_count = new_mem->num_pages;
+	u64 src_offset, dst_offset;
 	int ret;
 
-	if (!nvbo->no_vm) {
-		if (old_mem->mem_type == TTM_PL_VRAM)
-			src_offset  = nvbo->vma.offset;
-		else
-			src_offset += dev_priv->gart_info.aper_base;
-
-		if (new_mem->mem_type == TTM_PL_VRAM)
-			dst_offset  = nvbo->vma.offset;
-		else
-			dst_offset += dev_priv->gart_info.aper_base;
-	}
+	src_offset = old_node->tmp_vma.offset;
+	if (new_node->tmp_vma.node)
+		dst_offset = new_node->tmp_vma.offset;
+	else
+		dst_offset = nvbo->vma.offset;
 
 	page_count = new_mem->num_pages;
 	while (page_count) {
@@ -574,33 +547,18 @@
 nv50_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
 {
-	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_mem *old_node = old_mem->mm_node;
+	struct nouveau_mem *new_node = new_mem->mm_node;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
 	u64 length = (new_mem->num_pages << PAGE_SHIFT);
 	u64 src_offset, dst_offset;
 	int ret;
 
-	src_offset = old_mem->start << PAGE_SHIFT;
-	dst_offset = new_mem->start << PAGE_SHIFT;
-	if (!nvbo->no_vm) {
-		if (old_mem->mem_type == TTM_PL_VRAM)
-			src_offset  = nvbo->vma.offset;
-		else
-			src_offset += dev_priv->gart_info.aper_base;
-
-		if (new_mem->mem_type == TTM_PL_VRAM)
-			dst_offset  = nvbo->vma.offset;
-		else
-			dst_offset += dev_priv->gart_info.aper_base;
-	}
-
-	ret = RING_SPACE(chan, 3);
-	if (ret)
-		return ret;
-
-	BEGIN_RING(chan, NvSubM2MF, 0x0184, 2);
-	OUT_RING  (chan, nouveau_bo_mem_ctxdma(bo, chan, old_mem));
-	OUT_RING  (chan, nouveau_bo_mem_ctxdma(bo, chan, new_mem));
+	src_offset = old_node->tmp_vma.offset;
+	if (new_node->tmp_vma.node)
+		dst_offset = new_node->tmp_vma.offset;
+	else
+		dst_offset = nvbo->vma.offset;
 
 	while (length) {
 		u32 amount, stride, height;
@@ -681,6 +639,15 @@
 	return 0;
 }
 
+static inline uint32_t
+nouveau_bo_mem_ctxdma(struct ttm_buffer_object *bo,
+		      struct nouveau_channel *chan, struct ttm_mem_reg *mem)
+{
+	if (mem->mem_type == TTM_PL_TT)
+		return chan->gart_handle;
+	return chan->vram_handle;
+}
+
 static int
 nv04_bo_move_m2mf(struct nouveau_channel *chan, struct ttm_buffer_object *bo,
 		  struct ttm_mem_reg *old_mem, struct ttm_mem_reg *new_mem)
@@ -734,15 +701,43 @@
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct ttm_mem_reg *old_mem = &bo->mem;
 	struct nouveau_channel *chan;
 	int ret;
 
 	chan = nvbo->channel;
-	if (!chan || nvbo->no_vm) {
+	if (!chan) {
 		chan = dev_priv->channel;
 		mutex_lock_nested(&chan->mutex, NOUVEAU_KCHANNEL_MUTEX);
 	}
 
+	/* create temporary vma for old memory, this will get cleaned
+	 * up after ttm destroys the ttm_mem_reg
+	 */
+	if (dev_priv->card_type >= NV_50) {
+		struct nouveau_mem *node = old_mem->mm_node;
+		if (!node->tmp_vma.node) {
+			u32 page_shift = nvbo->vma.node->type;
+			if (old_mem->mem_type == TTM_PL_TT)
+				page_shift = nvbo->vma.vm->spg_shift;
+
+			ret = nouveau_vm_get(chan->vm,
+					     old_mem->num_pages << PAGE_SHIFT,
+					     page_shift, NV_MEM_ACCESS_RO,
+					     &node->tmp_vma);
+			if (ret)
+				goto out;
+		}
+
+		if (old_mem->mem_type == TTM_PL_VRAM)
+			nouveau_vm_map(&node->tmp_vma, node);
+		else {
+			nouveau_vm_map_sg(&node->tmp_vma, 0,
+					  old_mem->num_pages << PAGE_SHIFT,
+					  node, node->pages);
+		}
+	}
+
 	if (dev_priv->card_type < NV_50)
 		ret = nv04_bo_move_m2mf(chan, bo, &bo->mem, new_mem);
 	else
@@ -756,6 +751,7 @@
 						    no_wait_gpu, new_mem);
 	}
 
+out:
 	if (chan == dev_priv->channel)
 		mutex_unlock(&chan->mutex);
 	return ret;
@@ -766,6 +762,7 @@
 		      bool no_wait_reserve, bool no_wait_gpu,
 		      struct ttm_mem_reg *new_mem)
 {
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	u32 placement_memtype = TTM_PL_FLAG_TT | TTM_PL_MASK_CACHING;
 	struct ttm_placement placement;
 	struct ttm_mem_reg tmp_mem;
@@ -785,7 +782,23 @@
 	if (ret)
 		goto out;
 
+	if (dev_priv->card_type >= NV_50) {
+		struct nouveau_bo *nvbo = nouveau_bo(bo);
+		struct nouveau_mem *node = tmp_mem.mm_node;
+		struct nouveau_vma *vma = &nvbo->vma;
+		if (vma->node->type != vma->vm->spg_shift)
+			vma = &node->tmp_vma;
+		nouveau_vm_map_sg(vma, 0, tmp_mem.num_pages << PAGE_SHIFT,
+				  node, node->pages);
+	}
+
 	ret = nouveau_bo_move_m2mf(bo, true, intr, no_wait_reserve, no_wait_gpu, &tmp_mem);
+
+	if (dev_priv->card_type >= NV_50) {
+		struct nouveau_bo *nvbo = nouveau_bo(bo);
+		nouveau_vm_unmap(&nvbo->vma);
+	}
+
 	if (ret)
 		goto out;
 
@@ -828,6 +841,36 @@
 	return ret;
 }
 
+static void
+nouveau_bo_move_ntfy(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_mem *node = new_mem->mm_node;
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct nouveau_vma *vma = &nvbo->vma;
+	struct nouveau_vm *vm = vma->vm;
+
+	if (dev_priv->card_type < NV_50)
+		return;
+
+	switch (new_mem->mem_type) {
+	case TTM_PL_VRAM:
+		nouveau_vm_map(vma, node);
+		break;
+	case TTM_PL_TT:
+		if (vma->node->type != vm->spg_shift) {
+			nouveau_vm_unmap(vma);
+			vma = &node->tmp_vma;
+		}
+		nouveau_vm_map_sg(vma, 0, new_mem->num_pages << PAGE_SHIFT,
+				  node, node->pages);
+		break;
+	default:
+		nouveau_vm_unmap(&nvbo->vma);
+		break;
+	}
+}
+
 static int
 nouveau_bo_vm_bind(struct ttm_buffer_object *bo, struct ttm_mem_reg *new_mem,
 		   struct nouveau_tile_reg **new_tile)
@@ -835,19 +878,13 @@
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = dev_priv->dev;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	uint64_t offset;
+	u64 offset = new_mem->start << PAGE_SHIFT;
 
-	if (nvbo->no_vm || new_mem->mem_type != TTM_PL_VRAM) {
-		/* Nothing to do. */
-		*new_tile = NULL;
+	*new_tile = NULL;
+	if (new_mem->mem_type != TTM_PL_VRAM)
 		return 0;
-	}
-
-	offset = new_mem->start << PAGE_SHIFT;
 
-	if (dev_priv->chan_vm) {
-		nouveau_vm_map(&nvbo->vma, new_mem->mm_node);
-	} else if (dev_priv->card_type >= NV_10) {
+	if (dev_priv->card_type >= NV_10) {
 		*new_tile = nv10_mem_set_tiling(dev, offset, new_mem->size,
 						nvbo->tile_mode,
 						nvbo->tile_flags);
@@ -864,11 +901,8 @@
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
 	struct drm_device *dev = dev_priv->dev;
 
-	if (dev_priv->card_type >= NV_10 &&
-	    dev_priv->card_type < NV_50) {
-		nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
-		*old_tile = new_tile;
-	}
+	nv10_mem_put_tile_region(dev, *old_tile, bo->sync_obj);
+	*old_tile = new_tile;
 }
 
 static int
@@ -882,9 +916,11 @@
 	struct nouveau_tile_reg *new_tile = NULL;
 	int ret = 0;
 
-	ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
-	if (ret)
-		return ret;
+	if (dev_priv->card_type < NV_50) {
+		ret = nouveau_bo_vm_bind(bo, new_mem, &new_tile);
+		if (ret)
+			return ret;
+	}
 
 	/* Fake bo copy. */
 	if (old_mem->mem_type == TTM_PL_SYSTEM && !bo->ttm) {
@@ -915,10 +951,12 @@
 	ret = ttm_bo_move_memcpy(bo, evict, no_wait_reserve, no_wait_gpu, new_mem);
 
 out:
-	if (ret)
-		nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
-	else
-		nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+	if (dev_priv->card_type < NV_50) {
+		if (ret)
+			nouveau_bo_vm_cleanup(bo, NULL, &new_tile);
+		else
+			nouveau_bo_vm_cleanup(bo, new_tile, &nvbo->tile);
+	}
 
 	return ret;
 }
@@ -959,7 +997,7 @@
 		break;
 	case TTM_PL_VRAM:
 	{
-		struct nouveau_vram *vram = mem->mm_node;
+		struct nouveau_mem *node = mem->mm_node;
 		u8 page_shift;
 
 		if (!dev_priv->bar1_vm) {
@@ -970,23 +1008,23 @@
 		}
 
 		if (dev_priv->card_type == NV_C0)
-			page_shift = vram->page_shift;
+			page_shift = node->page_shift;
 		else
 			page_shift = 12;
 
 		ret = nouveau_vm_get(dev_priv->bar1_vm, mem->bus.size,
 				     page_shift, NV_MEM_ACCESS_RW,
-				     &vram->bar_vma);
+				     &node->bar_vma);
 		if (ret)
 			return ret;
 
-		nouveau_vm_map(&vram->bar_vma, vram);
+		nouveau_vm_map(&node->bar_vma, node);
 		if (ret) {
-			nouveau_vm_put(&vram->bar_vma);
+			nouveau_vm_put(&node->bar_vma);
 			return ret;
 		}
 
-		mem->bus.offset = vram->bar_vma.offset;
+		mem->bus.offset = node->bar_vma.offset;
 		if (dev_priv->card_type == NV_50) /*XXX*/
 			mem->bus.offset -= 0x0020000000ULL;
 		mem->bus.base = pci_resource_start(dev->pdev, 1);
@@ -1003,16 +1041,16 @@
 nouveau_ttm_io_mem_free(struct ttm_bo_device *bdev, struct ttm_mem_reg *mem)
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(bdev);
-	struct nouveau_vram *vram = mem->mm_node;
+	struct nouveau_mem *node = mem->mm_node;
 
 	if (!dev_priv->bar1_vm || mem->mem_type != TTM_PL_VRAM)
 		return;
 
-	if (!vram->bar_vma.node)
+	if (!node->bar_vma.node)
 		return;
 
-	nouveau_vm_unmap(&vram->bar_vma);
-	nouveau_vm_put(&vram->bar_vma);
+	nouveau_vm_unmap(&node->bar_vma);
+	nouveau_vm_put(&node->bar_vma);
 }
 
 static int
@@ -1062,6 +1100,7 @@
 	.invalidate_caches = nouveau_bo_invalidate_caches,
 	.init_mem_type = nouveau_bo_init_mem_type,
 	.evict_flags = nouveau_bo_evict_flags,
+	.move_notify = nouveau_bo_move_ntfy,
 	.move = nouveau_bo_move,
 	.verify_access = nouveau_bo_verify_access,
 	.sync_obj_signaled = __nouveau_fence_signalled,
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_channel.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *pb = chan->pushbuf_bo;
 	struct nouveau_gpuobj *pushbuf = NULL;
-	int ret;
+	int ret = 0;
 
 	if (dev_priv->card_type >= NV_50) {
 		if (dev_priv->card_type < NV_C0) {
@@ -90,8 +90,7 @@
 	else
 		location = TTM_PL_FLAG_TT;
 
-	ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, false,
-			     true, &pushbuf);
+	ret = nouveau_bo_new(dev, NULL, 65536, 0, location, 0, 0x0000, &pushbuf);
 	if (ret) {
 		NV_ERROR(dev, "error allocating DMA push buffer: %d\n", ret);
 		return NULL;
@@ -201,7 +200,7 @@
 	/* disable the fifo caches */
 	pfifo->reassign(dev, false);
 
-	/* Construct inital RAMFC for new channel */
+	/* Construct initial RAMFC for new channel */
 	ret = pfifo->create_context(chan);
 	if (ret) {
 		nouveau_channel_put(&chan);
@@ -279,7 +278,7 @@
 		return;
 	}
 
-	/* noone wants the channel anymore */
+	/* no one wants the channel anymore */
 	NV_DEBUG(dev, "freeing channel %d\n", chan->id);
 	nouveau_debugfs_channel_fini(chan);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_connector.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,6 +116,10 @@
 				      nouveau_connector_hotplug, connector);
 	}
 
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nouveau_backlight_exit(connector);
+
 	kfree(nv_connector->edid);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -894,6 +898,11 @@
 	}
 
 	drm_sysfs_connector_add(connector);
+
+	if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS ||
+	    connector->connector_type == DRM_MODE_CONNECTOR_eDP)
+		nouveau_backlight_init(connector);
+
 	dcb->drm = connector;
 	return dcb->drm;
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_display.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_display.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_display.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include "nouveau_hw.h"
 #include "nouveau_crtc.h"
 #include "nouveau_dma.h"
+#include "nv50_display.h"
 
 static void
 nouveau_user_framebuffer_destroy(struct drm_framebuffer *drm_fb)
@@ -61,18 +62,59 @@
 };
 
 int
-nouveau_framebuffer_init(struct drm_device *dev, struct nouveau_framebuffer *nouveau_fb,
-			 struct drm_mode_fb_cmd *mode_cmd, struct nouveau_bo *nvbo)
+nouveau_framebuffer_init(struct drm_device *dev,
+			 struct nouveau_framebuffer *nv_fb,
+			 struct drm_mode_fb_cmd *mode_cmd,
+			 struct nouveau_bo *nvbo)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct drm_framebuffer *fb = &nv_fb->base;
 	int ret;
 
-	ret = drm_framebuffer_init(dev, &nouveau_fb->base, &nouveau_framebuffer_funcs);
+	ret = drm_framebuffer_init(dev, fb, &nouveau_framebuffer_funcs);
 	if (ret) {
 		return ret;
 	}
 
-	drm_helper_mode_fill_fb_struct(&nouveau_fb->base, mode_cmd);
-	nouveau_fb->nvbo = nvbo;
+	drm_helper_mode_fill_fb_struct(fb, mode_cmd);
+	nv_fb->nvbo = nvbo;
+
+	if (dev_priv->card_type >= NV_50) {
+		u32 tile_flags = nouveau_bo_tile_layout(nvbo);
+		if (tile_flags == 0x7a00 ||
+		    tile_flags == 0xfe00)
+			nv_fb->r_dma = NvEvoFB32;
+		else
+		if (tile_flags == 0x7000)
+			nv_fb->r_dma = NvEvoFB16;
+		else
+			nv_fb->r_dma = NvEvoVRAM_LP;
+
+		switch (fb->depth) {
+		case  8: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_8; break;
+		case 15: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_15; break;
+		case 16: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_16; break;
+		case 24:
+		case 32: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_24; break;
+		case 30: nv_fb->r_format = NV50_EVO_CRTC_FB_DEPTH_30; break;
+		default:
+			 NV_ERROR(dev, "unknown depth %d\n", fb->depth);
+			 return -EINVAL;
+		}
+
+		if (dev_priv->chipset == 0x50)
+			nv_fb->r_format |= (tile_flags << 8);
+
+		if (!tile_flags)
+			nv_fb->r_pitch = 0x00100000 | fb->pitch;
+		else {
+			u32 mode = nvbo->tile_mode;
+			if (dev_priv->card_type >= NV_C0)
+				mode >>= 4;
+			nv_fb->r_pitch = ((fb->pitch / 4) << 4) | mode;
+		}
+	}
+
 	return 0;
 }
 
@@ -182,6 +224,7 @@
 		       struct nouveau_page_flip_state *s,
 		       struct nouveau_fence **pfence)
 {
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
 	struct drm_device *dev = chan->dev;
 	unsigned long flags;
 	int ret;
@@ -201,9 +244,12 @@
 	if (ret)
 		goto fail;
 
-	BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
-	OUT_RING(chan, 0);
-	FIRE_RING(chan);
+	if (dev_priv->card_type < NV_C0)
+		BEGIN_RING(chan, NvSubSw, NV_SW_PAGE_FLIP, 1);
+	else
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0500, 1);
+	OUT_RING  (chan, 0);
+	FIRE_RING (chan);
 
 	ret = nouveau_fence_new(chan, pfence, true);
 	if (ret)
@@ -244,7 +290,7 @@
 
 	/* Initialize a page flip struct */
 	*s = (struct nouveau_page_flip_state)
-		{ { }, s->event, nouveau_crtc(crtc)->index,
+		{ { }, event, nouveau_crtc(crtc)->index,
 		  fb->bits_per_pixel, fb->pitch, crtc->x, crtc->y,
 		  new_bo->bo.offset };
 
@@ -255,6 +301,14 @@
 	mutex_lock(&chan->mutex);
 
 	/* Emit a page flip */
+	if (dev_priv->card_type >= NV_50) {
+		ret = nv50_display_flip_next(crtc, fb, chan);
+		if (ret) {
+			nouveau_channel_put(&chan);
+			goto fail_unreserve;
+		}
+	}
+
 	ret = nouveau_page_flip_emit(chan, old_bo, new_bo, s, &fence);
 	nouveau_channel_put(&chan);
 	if (ret)
@@ -305,7 +359,8 @@
 	}
 
 	list_del(&s->head);
-	*ps = *s;
+	if (ps)
+		*ps = *s;
 	kfree(s);
 
 	spin_unlock_irqrestore(&dev->event_lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -83,7 +83,7 @@
 		return ret;
 
 	/* NV_MEMORY_TO_MEMORY_FORMAT requires a notifier object */
-	ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfd0, 0x1000,
+	ret = nouveau_notifier_alloc(chan, NvNotify0, 32, 0xfe0, 0x1000,
 				     &chan->m2mf_ntfy);
 	if (ret)
 		return ret;
@@ -97,13 +97,15 @@
 		OUT_RING(chan, 0);
 
 	/* Initialise NV_MEMORY_TO_MEMORY_FORMAT */
-	ret = RING_SPACE(chan, 4);
+	ret = RING_SPACE(chan, 6);
 	if (ret)
 		return ret;
 	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_NAME, 1);
-	OUT_RING(chan, NvM2MF);
-	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 1);
-	OUT_RING(chan, NvNotify0);
+	OUT_RING  (chan, NvM2MF);
+	BEGIN_RING(chan, NvSubM2MF, NV_MEMORY_TO_MEMORY_FORMAT_DMA_NOTIFY, 3);
+	OUT_RING  (chan, NvNotify0);
+	OUT_RING  (chan, chan->vram_handle);
+	OUT_RING  (chan, chan->gart_handle);
 
 	/* Sit back and pray the channel works.. */
 	FIRE_RING(chan);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,8 +61,6 @@
 	NvM2MF		= 0x80000001,
 	NvDmaFB		= 0x80000002,
 	NvDmaTT		= 0x80000003,
-	NvDmaVRAM	= 0x80000004,
-	NvDmaGART	= 0x80000005,
 	NvNotify0       = 0x80000006,
 	Nv2D		= 0x80000007,
 	NvCtxSurf2D	= 0x80000008,
@@ -73,12 +71,15 @@
 	NvImageBlit	= 0x8000000d,
 	NvSw		= 0x8000000e,
 	NvSema		= 0x8000000f,
+	NvEvoSema0	= 0x80000010,
+	NvEvoSema1	= 0x80000011,
 
 	/* G80+ display objects */
 	NvEvoVRAM	= 0x01000000,
 	NvEvoFB16	= 0x01000001,
 	NvEvoFB32	= 0x01000002,
-	NvEvoVRAM_LP	= 0x01000003
+	NvEvoVRAM_LP	= 0x01000003,
+	NvEvoSync	= 0xcafe0000
 };
 
 #define NV_MEMORY_TO_MEMORY_FORMAT                                    0x00000039
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_dp.c	2011-05-19 00:06:34.000000000 -0400
@@ -175,7 +175,6 @@
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct bit_displayport_encoder_table_entry *dpse;
 	struct bit_displayport_encoder_table *dpe;
 	int ret, i, dpe_headerlen, vs = 0, pre = 0;
 	uint8_t request[2];
@@ -183,7 +182,6 @@
 	dpe = nouveau_bios_dp_table(dev, nv_encoder->dcb, &dpe_headerlen);
 	if (!dpe)
 		return false;
-	dpse = (void *)((char *)dpe + dpe_headerlen);
 
 	ret = auxch_rd(encoder, DP_ADJUST_REQUEST_LANE0_1, request, 2);
 	if (ret)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -408,14 +408,6 @@
 #endif
 		.llseek = noop_llseek,
 	},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-		.probe = nouveau_pci_probe,
-		.remove = nouveau_pci_remove,
-		.suspend = nouveau_pci_suspend,
-		.resume = nouveau_pci_resume
-	},
 
 	.gem_init_object = nouveau_gem_object_new,
 	.gem_free_object = nouveau_gem_object_del,
@@ -432,6 +424,15 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver nouveau_pci_driver = {
+		.name = DRIVER_NAME,
+		.id_table = pciidlist,
+		.probe = nouveau_pci_probe,
+		.remove = nouveau_pci_remove,
+		.suspend = nouveau_pci_suspend,
+		.resume = nouveau_pci_resume
+};
+
 static int __init nouveau_init(void)
 {
 	driver.num_ioctls = nouveau_max_ioctl;
@@ -449,7 +450,7 @@
 		return 0;
 
 	nouveau_register_dsm_handler();
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &nouveau_pci_driver);
 }
 
 static void __exit nouveau_exit(void)
@@ -457,7 +458,7 @@
 	if (!nouveau_modeset)
 		return;
 
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &nouveau_pci_driver);
 	nouveau_unregister_dsm_handler();
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_drv.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 #include "nouveau_util.h"
 
 struct nouveau_grctx;
-struct nouveau_vram;
+struct nouveau_mem;
 #include "nouveau_vm.h"
 
 #define MAX_NUM_DCB_ENTRIES 16
@@ -65,13 +65,16 @@
 #define NOUVEAU_MAX_CHANNEL_NR 128
 #define NOUVEAU_MAX_TILE_NR 15
 
-struct nouveau_vram {
+struct nouveau_mem {
 	struct drm_device *dev;
 
 	struct nouveau_vma bar_vma;
+	struct nouveau_vma tmp_vma;
 	u8  page_shift;
 
+	struct drm_mm_node *tag;
 	struct list_head regions;
+	dma_addr_t *pages;
 	u32 memtype;
 	u64 offset;
 	u64 size;
@@ -90,6 +93,7 @@
 struct nouveau_bo {
 	struct ttm_buffer_object bo;
 	struct ttm_placement placement;
+	u32 valid_domains;
 	u32 placements[3];
 	u32 busy_placements[3];
 	struct ttm_bo_kmap_obj kmap;
@@ -104,8 +108,6 @@
 	struct nouveau_channel *channel;
 
 	struct nouveau_vma vma;
-	bool mappable;
-	bool no_vm;
 
 	uint32_t tile_mode;
 	uint32_t tile_flags;
@@ -214,7 +216,7 @@
 	/* mapping of the fifo itself */
 	struct drm_local_map *map;
 
-	/* mapping of the regs controling the fifo */
+	/* mapping of the regs controlling the fifo */
 	void __iomem *user;
 	uint32_t user_get;
 	uint32_t user_put;
@@ -387,6 +389,7 @@
 };
 
 struct nouveau_display_engine {
+	void *priv;
 	int (*early_init)(struct drm_device *);
 	void (*late_takedown)(struct drm_device *);
 	int (*create)(struct drm_device *);
@@ -509,8 +512,8 @@
 struct nouveau_vram_engine {
 	int  (*init)(struct drm_device *);
 	int  (*get)(struct drm_device *, u64, u32 align, u32 size_nc,
-		    u32 type, struct nouveau_vram **);
-	void (*put)(struct drm_device *, struct nouveau_vram **);
+		    u32 type, struct nouveau_mem **);
+	void (*put)(struct drm_device *, struct nouveau_mem **);
 
 	bool (*flags_valid)(struct drm_device *, u32 tile_flags);
 };
@@ -652,8 +655,6 @@
 	/* interrupt handling */
 	void (*irq_handler[32])(struct drm_device *);
 	bool msi_enabled;
-	struct workqueue_struct *wq;
-	struct work_struct irq_work;
 
 	struct list_head vbl_waiting;
 
@@ -681,6 +682,9 @@
 	/* For PFIFO and PGRAPH. */
 	spinlock_t context_switch_lock;
 
+	/* VM/PRAMIN flush, legacy PRAMIN aperture */
+	spinlock_t vm_lock;
+
 	/* RAMIN configuration, RAMFC, RAMHT and RAMRO offsets */
 	struct nouveau_ramht  *ramht;
 	struct nouveau_gpuobj *ramfc;
@@ -691,15 +695,22 @@
 	struct {
 		enum {
 			NOUVEAU_GART_NONE = 0,
-			NOUVEAU_GART_AGP,
-			NOUVEAU_GART_SGDMA
+			NOUVEAU_GART_AGP,	/* AGP */
+			NOUVEAU_GART_PDMA,	/* paged dma object */
+			NOUVEAU_GART_HW		/* on-chip gart/vm */
 		} type;
 		uint64_t aper_base;
 		uint64_t aper_size;
 		uint64_t aper_free;
 
+		struct ttm_backend_func *func;
+
+		struct {
+			struct page *page;
+			dma_addr_t   addr;
+		} dummy;
+
 		struct nouveau_gpuobj *sg_ctxdma;
-		struct nouveau_vma vma;
 	} gart_info;
 
 	/* nv10-nv40 tiling regions */
@@ -740,14 +751,6 @@
 
 	struct backlight_device *backlight;
 
-	struct nouveau_channel *evo;
-	u32 evo_alloc;
-	struct {
-		struct dcb_entry *dcb;
-		u16 script;
-		u32 pclk;
-	} evo_irq;
-
 	struct {
 		struct dentry *channel_root;
 	} debugfs;
@@ -847,6 +850,7 @@
 				     struct nouveau_tile_reg *tile,
 				     struct nouveau_fence *fence);
 extern const struct ttm_mem_type_manager_func nouveau_vram_manager;
+extern const struct ttm_mem_type_manager_func nouveau_gart_manager;
 
 /* nouveau_notifier.c */
 extern int  nouveau_notifier_init_channel(struct nouveau_channel *);
@@ -998,15 +1002,15 @@
 
 /* nouveau_backlight.c */
 #ifdef CONFIG_DRM_NOUVEAU_BACKLIGHT
-extern int nouveau_backlight_init(struct drm_device *);
-extern void nouveau_backlight_exit(struct drm_device *);
+extern int nouveau_backlight_init(struct drm_connector *);
+extern void nouveau_backlight_exit(struct drm_connector *);
 #else
-static inline int nouveau_backlight_init(struct drm_device *dev)
+static inline int nouveau_backlight_init(struct drm_connector *dev)
 {
 	return 0;
 }
 
-static inline void nouveau_backlight_exit(struct drm_device *dev) { }
+static inline void nouveau_backlight_exit(struct drm_connector *dev) { }
 #endif
 
 /* nouveau_bios.c */
@@ -1076,7 +1080,7 @@
 /* nv50_fb.c */
 extern int  nv50_fb_init(struct drm_device *);
 extern void nv50_fb_takedown(struct drm_device *);
-extern void nv50_fb_vm_trap(struct drm_device *, int display, const char *);
+extern void nv50_fb_vm_trap(struct drm_device *, int display);
 
 /* nvc0_fb.c */
 extern int  nvc0_fb_init(struct drm_device *);
@@ -1189,7 +1193,7 @@
 extern int  nv50_graph_unload_context(struct drm_device *);
 extern int  nv50_grctx_init(struct nouveau_grctx *);
 extern void nv50_graph_tlb_flush(struct drm_device *dev);
-extern void nv86_graph_tlb_flush(struct drm_device *dev);
+extern void nv84_graph_tlb_flush(struct drm_device *dev);
 extern struct nouveau_enum nv50_data_error_names[];
 
 /* nvc0_graph.c */
@@ -1295,7 +1299,7 @@
 extern int nouveau_bo_new(struct drm_device *, struct nouveau_channel *,
 			  int size, int align, uint32_t flags,
 			  uint32_t tile_mode, uint32_t tile_flags,
-			  bool no_vm, bool mappable, struct nouveau_bo **);
+			  struct nouveau_bo **);
 extern int nouveau_bo_pin(struct nouveau_bo *, uint32_t flags);
 extern int nouveau_bo_unpin(struct nouveau_bo *);
 extern int nouveau_bo_map(struct nouveau_bo *);
@@ -1356,9 +1360,9 @@
 
 /* nouveau_gem.c */
 extern int nouveau_gem_new(struct drm_device *, struct nouveau_channel *,
-			   int size, int align, uint32_t flags,
+			   int size, int align, uint32_t domain,
 			   uint32_t tile_mode, uint32_t tile_flags,
-			   bool no_vm, bool mappable, struct nouveau_bo **);
+			   struct nouveau_bo **);
 extern int nouveau_gem_object_new(struct drm_gem_object *);
 extern void nouveau_gem_object_del(struct drm_gem_object *);
 extern int nouveau_gem_ioctl_new(struct drm_device *, void *,
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_fbcon.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,13 +181,13 @@
 		OUT_RING  (chan, 0);
 	}
 
-	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy + 3, 0xffffffff);
+	nouveau_bo_wr32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3, 0xffffffff);
 	FIRE_RING(chan);
 	mutex_unlock(&chan->mutex);
 
 	ret = -EBUSY;
 	for (i = 0; i < 100000; i++) {
-		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy + 3)) {
+		if (!nouveau_bo_rd32(chan->notifier_bo, chan->m2mf_ntfy/4 + 3)) {
 			ret = 0;
 			break;
 		}
@@ -296,8 +296,8 @@
 	size = mode_cmd.pitch * mode_cmd.height;
 	size = roundup(size, PAGE_SIZE);
 
-	ret = nouveau_gem_new(dev, dev_priv->channel, size, 0, TTM_PL_FLAG_VRAM,
-			      0, 0x0000, false, true, &nvbo);
+	ret = nouveau_gem_new(dev, dev_priv->channel, size, 0,
+			      NOUVEAU_GEM_DOMAIN_VRAM, 0, 0x0000, &nvbo);
 	if (ret) {
 		NV_ERROR(dev, "failed to allocate framebuffer\n");
 		goto out;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fb.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_fb.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_fb.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,9 @@
 struct nouveau_framebuffer {
 	struct drm_framebuffer base;
 	struct nouveau_bo *nvbo;
+	u32 r_dma;
+	u32 r_format;
+	u32 r_pitch;
 };
 
 static inline struct nouveau_framebuffer *
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_fence.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,13 +27,15 @@
 #include "drmP.h"
 #include "drm.h"
 
+#include <linux/ktime.h>
+#include <linux/hrtimer.h>
+
 #include "nouveau_drv.h"
 #include "nouveau_ramht.h"
 #include "nouveau_dma.h"
 
 #define USE_REFCNT(dev) (nouveau_private(dev)->chipset >= 0x10)
-#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17 && \
-		       nouveau_private(dev)->card_type < NV_C0)
+#define USE_SEMA(dev) (nouveau_private(dev)->chipset >= 0x17)
 
 struct nouveau_fence {
 	struct nouveau_channel *channel;
@@ -230,7 +232,8 @@
 __nouveau_fence_wait(void *sync_obj, void *sync_arg, bool lazy, bool intr)
 {
 	unsigned long timeout = jiffies + (3 * DRM_HZ);
-	unsigned long sleep_time = jiffies + 1;
+	unsigned long sleep_time = NSEC_PER_MSEC / 1000;
+	ktime_t t;
 	int ret = 0;
 
 	while (1) {
@@ -244,8 +247,13 @@
 
 		__set_current_state(intr ? TASK_INTERRUPTIBLE
 			: TASK_UNINTERRUPTIBLE);
-		if (lazy && time_after_eq(jiffies, sleep_time))
-			schedule_timeout(1);
+		if (lazy) {
+			t = ktime_set(0, sleep_time);
+			schedule_hrtimeout(&t, HRTIMER_MODE_REL);
+			sleep_time *= 2;
+			if (sleep_time > NSEC_PER_MSEC)
+				sleep_time = NSEC_PER_MSEC;
+		}
 
 		if (intr && signal_pending(current)) {
 			ret = -ERESTARTSYS;
@@ -259,11 +267,12 @@
 }
 
 static struct nouveau_semaphore *
-alloc_semaphore(struct drm_device *dev)
+semaphore_alloc(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_semaphore *sema;
-	int ret;
+	int size = (dev_priv->chipset < 0x84) ? 4 : 16;
+	int ret, i;
 
 	if (!USE_SEMA(dev))
 		return NULL;
@@ -277,9 +286,9 @@
 		goto fail;
 
 	spin_lock(&dev_priv->fence.lock);
-	sema->mem = drm_mm_search_free(&dev_priv->fence.heap, 4, 0, 0);
+	sema->mem = drm_mm_search_free(&dev_priv->fence.heap, size, 0, 0);
 	if (sema->mem)
-		sema->mem = drm_mm_get_block_atomic(sema->mem, 4, 0);
+		sema->mem = drm_mm_get_block_atomic(sema->mem, size, 0);
 	spin_unlock(&dev_priv->fence.lock);
 
 	if (!sema->mem)
@@ -287,7 +296,8 @@
 
 	kref_init(&sema->ref);
 	sema->dev = dev;
-	nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 0);
+	for (i = sema->mem->start; i < sema->mem->start + size; i += 4)
+		nouveau_bo_wr32(dev_priv->fence.bo, i / 4, 0);
 
 	return sema;
 fail:
@@ -296,7 +306,7 @@
 }
 
 static void
-free_semaphore(struct kref *ref)
+semaphore_free(struct kref *ref)
 {
 	struct nouveau_semaphore *sema =
 		container_of(ref, struct nouveau_semaphore, ref);
@@ -318,61 +328,107 @@
 	if (unlikely(!signalled))
 		nouveau_bo_wr32(dev_priv->fence.bo, sema->mem->start / 4, 1);
 
-	kref_put(&sema->ref, free_semaphore);
+	kref_put(&sema->ref, semaphore_free);
 }
 
 static int
-emit_semaphore(struct nouveau_channel *chan, int method,
-	       struct nouveau_semaphore *sema)
+semaphore_acquire(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
 {
-	struct drm_nouveau_private *dev_priv = sema->dev->dev_private;
-	struct nouveau_fence *fence;
-	bool smart = (dev_priv->card_type >= NV_50);
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_fence *fence = NULL;
 	int ret;
 
-	ret = RING_SPACE(chan, smart ? 8 : 4);
+	if (dev_priv->chipset < 0x84) {
+		ret = RING_SPACE(chan, 3);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 2);
+		OUT_RING  (chan, sema->mem->start);
+		OUT_RING  (chan, 1);
+	} else
+	if (dev_priv->chipset < 0xc0) {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 1); /* ACQUIRE_EQ */
+	} else {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0x1001); /* ACQUIRE_EQ */
+	}
+
+	/* Delay semaphore destruction until its work is done */
+	ret = nouveau_fence_new(chan, &fence, true);
 	if (ret)
 		return ret;
 
-	if (smart) {
-		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
-		OUT_RING(chan, NvSema);
-	}
-	BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1);
-	OUT_RING(chan, sema->mem->start);
+	kref_get(&sema->ref);
+	nouveau_fence_work(fence, semaphore_work, sema);
+	nouveau_fence_unref(&fence);
+	return 0;
+}
 
-	if (smart && method == NV_SW_SEMAPHORE_ACQUIRE) {
-		/*
-		 * NV50 tries to be too smart and context-switch
-		 * between semaphores instead of doing a "first come,
-		 * first served" strategy like previous cards
-		 * do.
-		 *
-		 * That's bad because the ACQUIRE latency can get as
-		 * large as the PFIFO context time slice in the
-		 * typical DRI2 case where you have several
-		 * outstanding semaphores at the same moment.
-		 *
-		 * If we're going to ACQUIRE, force the card to
-		 * context switch before, just in case the matching
-		 * RELEASE is already scheduled to be executed in
-		 * another channel.
-		 */
-		BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1);
-		OUT_RING(chan, 0);
-	}
+static int
+semaphore_release(struct nouveau_channel *chan, struct nouveau_semaphore *sema)
+{
+	struct drm_nouveau_private *dev_priv = chan->dev->dev_private;
+	struct nouveau_fence *fence = NULL;
+	int ret;
 
-	BEGIN_RING(chan, NvSubSw, method, 1);
-	OUT_RING(chan, 1);
+	if (dev_priv->chipset < 0x84) {
+		ret = RING_SPACE(chan, 4);
+		if (ret)
+			return ret;
 
-	if (smart && method == NV_SW_SEMAPHORE_RELEASE) {
-		/*
-		 * Force the card to context switch, there may be
-		 * another channel waiting for the semaphore we just
-		 * released.
-		 */
-		BEGIN_RING(chan, NvSubSw, NV_SW_YIELD, 1);
-		OUT_RING(chan, 0);
+		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_OFFSET, 1);
+		OUT_RING  (chan, sema->mem->start);
+		BEGIN_RING(chan, NvSubSw, NV_SW_SEMAPHORE_RELEASE, 1);
+		OUT_RING  (chan, 1);
+	} else
+	if (dev_priv->chipset < 0xc0) {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_RING(chan, NvSubSw, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 2); /* RELEASE */
+	} else {
+		struct nouveau_vma *vma = &dev_priv->fence.bo->vma;
+		u64 offset = vma->offset + sema->mem->start;
+
+		ret = RING_SPACE(chan, 5);
+		if (ret)
+			return ret;
+
+		BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+		OUT_RING  (chan, upper_32_bits(offset));
+		OUT_RING  (chan, lower_32_bits(offset));
+		OUT_RING  (chan, 1);
+		OUT_RING  (chan, 0x1002); /* RELEASE */
 	}
 
 	/* Delay semaphore destruction until its work is done */
@@ -383,7 +439,6 @@
 	kref_get(&sema->ref);
 	nouveau_fence_work(fence, semaphore_work, sema);
 	nouveau_fence_unref(&fence);
-
 	return 0;
 }
 
@@ -400,7 +455,7 @@
 		   nouveau_fence_signalled(fence)))
 		goto out;
 
-	sema = alloc_semaphore(dev);
+	sema = semaphore_alloc(dev);
 	if (!sema) {
 		/* Early card or broken userspace, fall back to
 		 * software sync. */
@@ -418,17 +473,17 @@
 	}
 
 	/* Make wchan wait until it gets signalled */
-	ret = emit_semaphore(wchan, NV_SW_SEMAPHORE_ACQUIRE, sema);
+	ret = semaphore_acquire(wchan, sema);
 	if (ret)
 		goto out_unlock;
 
 	/* Signal the semaphore from chan */
-	ret = emit_semaphore(chan, NV_SW_SEMAPHORE_RELEASE, sema);
+	ret = semaphore_release(chan, sema);
 
 out_unlock:
 	mutex_unlock(&chan->mutex);
 out_unref:
-	kref_put(&sema->ref, free_semaphore);
+	kref_put(&sema->ref, semaphore_free);
 out:
 	if (chan)
 		nouveau_channel_put_unlocked(&chan);
@@ -449,22 +504,23 @@
 	struct nouveau_gpuobj *obj = NULL;
 	int ret;
 
+	if (dev_priv->card_type >= NV_C0)
+		goto out_initialised;
+
 	/* Create an NV_SW object for various sync purposes */
 	ret = nouveau_gpuobj_gr_new(chan, NvSw, NV_SW);
 	if (ret)
 		return ret;
 
 	/* we leave subchannel empty for nvc0 */
-	if (dev_priv->card_type < NV_C0) {
-		ret = RING_SPACE(chan, 2);
-		if (ret)
-			return ret;
-		BEGIN_RING(chan, NvSubSw, 0, 1);
-		OUT_RING(chan, NvSw);
-	}
+	ret = RING_SPACE(chan, 2);
+	if (ret)
+		return ret;
+	BEGIN_RING(chan, NvSubSw, 0, 1);
+	OUT_RING(chan, NvSw);
 
 	/* Create a DMA object for the shared cross-channel sync area. */
-	if (USE_SEMA(dev)) {
+	if (USE_SEMA(dev) && dev_priv->chipset < 0x84) {
 		struct ttm_mem_reg *mem = &dev_priv->fence.bo->bo.mem;
 
 		ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY,
@@ -484,14 +540,20 @@
 			return ret;
 		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
 		OUT_RING(chan, NvSema);
+	} else {
+		ret = RING_SPACE(chan, 2);
+		if (ret)
+			return ret;
+		BEGIN_RING(chan, NvSubSw, NV_SW_DMA_SEMAPHORE, 1);
+		OUT_RING  (chan, chan->vram_handle); /* whole VM */
 	}
 
 	FIRE_RING(chan);
 
+out_initialised:
 	INIT_LIST_HEAD(&chan->fence.pending);
 	spin_lock_init(&chan->fence.lock);
 	atomic_set(&chan->fence.last_sequence_irq, 0);
-
 	return 0;
 }
 
@@ -519,12 +581,13 @@
 nouveau_fence_init(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int size = (dev_priv->chipset < 0x84) ? 4096 : 16384;
 	int ret;
 
 	/* Create a shared VRAM heap for cross-channel sync. */
 	if (USE_SEMA(dev)) {
-		ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM,
-				     0, 0, false, true, &dev_priv->fence.bo);
+		ret = nouveau_bo_new(dev, NULL, size, 0, TTM_PL_FLAG_VRAM,
+				     0, 0, &dev_priv->fence.bo);
 		if (ret)
 			return ret;
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_gem.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,26 +61,43 @@
 
 int
 nouveau_gem_new(struct drm_device *dev, struct nouveau_channel *chan,
-		int size, int align, uint32_t flags, uint32_t tile_mode,
-		uint32_t tile_flags, bool no_vm, bool mappable,
-		struct nouveau_bo **pnvbo)
+		int size, int align, uint32_t domain, uint32_t tile_mode,
+		uint32_t tile_flags, struct nouveau_bo **pnvbo)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_bo *nvbo;
+	u32 flags = 0;
 	int ret;
 
+	if (domain & NOUVEAU_GEM_DOMAIN_VRAM)
+		flags |= TTM_PL_FLAG_VRAM;
+	if (domain & NOUVEAU_GEM_DOMAIN_GART)
+		flags |= TTM_PL_FLAG_TT;
+	if (!flags || domain & NOUVEAU_GEM_DOMAIN_CPU)
+		flags |= TTM_PL_FLAG_SYSTEM;
+
 	ret = nouveau_bo_new(dev, chan, size, align, flags, tile_mode,
-			     tile_flags, no_vm, mappable, pnvbo);
+			     tile_flags, pnvbo);
 	if (ret)
 		return ret;
 	nvbo = *pnvbo;
 
+	/* we restrict allowed domains on nv50+ to only the types
+	 * that were requested at creation time.  not possibly on
+	 * earlier chips without busting the ABI.
+	 */
+	nvbo->valid_domains = NOUVEAU_GEM_DOMAIN_VRAM |
+			      NOUVEAU_GEM_DOMAIN_GART;
+	if (dev_priv->card_type >= NV_50)
+		nvbo->valid_domains &= domain;
+
 	nvbo->gem = drm_gem_object_alloc(dev, nvbo->bo.mem.size);
 	if (!nvbo->gem) {
 		nouveau_bo_ref(NULL, pnvbo);
 		return -ENOMEM;
 	}
 
-	nvbo->bo.persistant_swap_storage = nvbo->gem->filp;
+	nvbo->bo.persistent_swap_storage = nvbo->gem->filp;
 	nvbo->gem->driver_private = nvbo;
 	return 0;
 }
@@ -97,7 +114,7 @@
 
 	rep->size = nvbo->bo.mem.num_pages << PAGE_SHIFT;
 	rep->offset = nvbo->bo.offset;
-	rep->map_handle = nvbo->mappable ? nvbo->bo.addr_space_offset : 0;
+	rep->map_handle = nvbo->bo.addr_space_offset;
 	rep->tile_mode = nvbo->tile_mode;
 	rep->tile_flags = nvbo->tile_flags;
 	return 0;
@@ -111,19 +128,11 @@
 	struct drm_nouveau_gem_new *req = data;
 	struct nouveau_bo *nvbo = NULL;
 	struct nouveau_channel *chan = NULL;
-	uint32_t flags = 0;
 	int ret = 0;
 
 	if (unlikely(dev_priv->ttm.bdev.dev_mapping == NULL))
 		dev_priv->ttm.bdev.dev_mapping = dev_priv->dev->dev_mapping;
 
-	if (req->info.domain & NOUVEAU_GEM_DOMAIN_VRAM)
-		flags |= TTM_PL_FLAG_VRAM;
-	if (req->info.domain & NOUVEAU_GEM_DOMAIN_GART)
-		flags |= TTM_PL_FLAG_TT;
-	if (!flags || req->info.domain & NOUVEAU_GEM_DOMAIN_CPU)
-		flags |= TTM_PL_FLAG_SYSTEM;
-
 	if (!dev_priv->engine.vram.flags_valid(dev, req->info.tile_flags)) {
 		NV_ERROR(dev, "bad page flags: 0x%08x\n", req->info.tile_flags);
 		return -EINVAL;
@@ -135,10 +144,9 @@
 			return PTR_ERR(chan);
 	}
 
-	ret = nouveau_gem_new(dev, chan, req->info.size, req->align, flags,
-			      req->info.tile_mode, req->info.tile_flags, false,
-			      (req->info.domain & NOUVEAU_GEM_DOMAIN_MAPPABLE),
-			      &nvbo);
+	ret = nouveau_gem_new(dev, chan, req->info.size, req->align,
+			      req->info.domain, req->info.tile_mode,
+			      req->info.tile_flags, &nvbo);
 	if (chan)
 		nouveau_channel_put(&chan);
 	if (ret)
@@ -161,7 +169,7 @@
 {
 	struct nouveau_bo *nvbo = gem->driver_private;
 	struct ttm_buffer_object *bo = &nvbo->bo;
-	uint32_t domains = valid_domains &
+	uint32_t domains = valid_domains & nvbo->valid_domains &
 		(write_domains ? write_domains : read_domains);
 	uint32_t pref_flags = 0, valid_flags = 0;
 
@@ -592,7 +600,7 @@
 		if (push[i].bo_index >= req->nr_buffers) {
 			NV_ERROR(dev, "push %d buffer not in list\n", i);
 			ret = -EINVAL;
-			goto out;
+			goto out_prevalid;
 		}
 
 		bo[push[i].bo_index].read_domains |= (1 << 31);
@@ -604,7 +612,7 @@
 	if (ret) {
 		if (ret != -ERESTARTSYS)
 			NV_ERROR(dev, "validate: %d\n", ret);
-		goto out;
+		goto out_prevalid;
 	}
 
 	/* Apply any relocations that are required */
@@ -697,6 +705,8 @@
 out:
 	validate_fini(&op, fence);
 	nouveau_fence_unref(&fence);
+
+out_prevalid:
 	kfree(bo);
 	kfree(push);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_mem.c	2011-05-19 00:06:34.000000000 -0400
@@ -152,9 +152,6 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
-	nouveau_bo_unpin(dev_priv->vga_ram);
-	nouveau_bo_ref(NULL, &dev_priv->vga_ram);
-
 	ttm_bo_device_release(&dev_priv->ttm.bdev);
 
 	nouveau_ttm_global_release(dev_priv);
@@ -393,11 +390,17 @@
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	int ret, dma_bits;
 
-	if (dev_priv->card_type >= NV_50 &&
-	    pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
-		dma_bits = 40;
-	else
-		dma_bits = 32;
+	dma_bits = 32;
+	if (dev_priv->card_type >= NV_50) {
+		if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(40)))
+			dma_bits = 40;
+	} else
+	if (drm_pci_device_is_pcie(dev) &&
+	    dev_priv->chipset  > 0x40 &&
+	    dev_priv->chipset != 0x45) {
+		if (pci_dma_supported(dev->pdev, DMA_BIT_MASK(39)))
+			dma_bits = 39;
+	}
 
 	ret = pci_set_dma_mask(dev->pdev, DMA_BIT_MASK(dma_bits));
 	if (ret)
@@ -419,14 +422,32 @@
 	}
 
 	/* reserve space at end of VRAM for PRAMIN */
-	if (dev_priv->chipset == 0x40 || dev_priv->chipset == 0x47 ||
-	    dev_priv->chipset == 0x49 || dev_priv->chipset == 0x4b)
-		dev_priv->ramin_rsvd_vram = (2 * 1024 * 1024);
-	else
-	if (dev_priv->card_type >= NV_40)
-		dev_priv->ramin_rsvd_vram = (1 * 1024 * 1024);
-	else
-		dev_priv->ramin_rsvd_vram = (512 * 1024);
+	if (dev_priv->card_type >= NV_50) {
+		dev_priv->ramin_rsvd_vram = 1 * 1024 * 1024;
+	} else
+	if (dev_priv->card_type >= NV_40) {
+		u32 vs = hweight8((nv_rd32(dev, 0x001540) & 0x0000ff00) >> 8);
+		u32 rsvd;
+
+		/* estimate grctx size, the magics come from nv40_grctx.c */
+		if      (dev_priv->chipset == 0x40) rsvd = 0x6aa0 * vs;
+		else if (dev_priv->chipset  < 0x43) rsvd = 0x4f00 * vs;
+		else if (nv44_graph_class(dev))	    rsvd = 0x4980 * vs;
+		else				    rsvd = 0x4a40 * vs;
+		rsvd += 16 * 1024;
+		rsvd *= dev_priv->engine.fifo.channels;
+
+		/* pciegart table */
+		if (drm_pci_device_is_pcie(dev))
+			rsvd += 512 * 1024;
+
+		/* object storage */
+		rsvd += 512 * 1024;
+
+		dev_priv->ramin_rsvd_vram = round_up(rsvd, 4096);
+	} else {
+		dev_priv->ramin_rsvd_vram = 512 * 1024;
+	}
 
 	ret = dev_priv->engine.vram.init(dev);
 	if (ret)
@@ -455,13 +476,17 @@
 		return ret;
 	}
 
-	ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
-			     0, 0, true, true, &dev_priv->vga_ram);
-	if (ret == 0)
-		ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
-	if (ret) {
-		NV_WARN(dev, "failed to reserve VGA memory\n");
-		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+	if (dev_priv->card_type < NV_50) {
+		ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
+				     0, 0, &dev_priv->vga_ram);
+		if (ret == 0)
+			ret = nouveau_bo_pin(dev_priv->vga_ram,
+					     TTM_PL_FLAG_VRAM);
+
+		if (ret) {
+			NV_WARN(dev, "failed to reserve VGA memory\n");
+			nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+		}
 	}
 
 	dev_priv->fb_mtrr = drm_mtrr_add(pci_resource_start(dev->pdev, 1),
@@ -480,7 +505,7 @@
 	dev_priv->gart_info.type = NOUVEAU_GART_NONE;
 
 #if !defined(__powerpc__) && !defined(__ia64__)
-	if (drm_device_is_agp(dev) && dev->agp && nouveau_agpmode) {
+	if (drm_pci_device_is_agp(dev) && dev->agp && nouveau_agpmode) {
 		ret = nouveau_mem_init_agp(dev);
 		if (ret)
 			NV_ERROR(dev, "Error initialising AGP: %d\n", ret);
@@ -525,6 +550,7 @@
 	u8 tRC;		/* Byte 9 */
 	u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
 	u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
+	u8 magic_number = 0; /* Yeah... sorry*/
 	u8 *mem = NULL, *entry;
 	int i, recordlen, entries;
 
@@ -569,6 +595,12 @@
 	if (!memtimings->timing)
 		return;
 
+	/* Get "some number" from the timing reg for NV_40
+	 * Used in calculations later */
+	if(dev_priv->card_type == NV_40) {
+		magic_number = (nv_rd32(dev,0x100228) & 0x0f000000) >> 24;
+	}
+
 	entry = mem + mem[1];
 	for (i = 0; i < entries; i++, entry += recordlen) {
 		struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
@@ -608,36 +640,51 @@
 
 		/* XXX: I don't trust the -1's and +1's... they must come
 		 *      from somewhere! */
-		timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 |
+		timing->reg_100224 = (tUNK_0 + tUNK_19 + 1 + magic_number) << 24 |
 				      tUNK_18 << 16 |
-				      (tUNK_1 + tUNK_19 + 1) << 8 |
-				      (tUNK_2 - 1));
+				      (tUNK_1 + tUNK_19 + 1 + magic_number) << 8;
+		if(dev_priv->chipset == 0xa8) {
+			timing->reg_100224 |= (tUNK_2 - 1);
+		} else {
+			timing->reg_100224 |= (tUNK_2 + 2 - magic_number);
+		}
 
 		timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
-		if(recordlen > 19) {
-			timing->reg_100228 += (tUNK_19 - 1) << 24;
-		}/* I cannot back-up this else-statement right now
-			 else {
-			timing->reg_100228 += tUNK_12 << 24;
-		}*/
+		if(dev_priv->chipset >= 0xa3 && dev_priv->chipset < 0xaa) {
+			timing->reg_100228 |= (tUNK_19 - 1) << 24;
+		}
 
-		/* XXX: reg_10022c */
-		timing->reg_10022c = tUNK_2 - 1;
+		if(dev_priv->card_type == NV_40) {
+			/* NV40: don't know what the rest of the regs are..
+			 * And don't need to know either */
+			timing->reg_100228 |= 0x20200000 | magic_number << 24;
+		} else if(dev_priv->card_type >= NV_50) {
+			/* XXX: reg_10022c */
+			timing->reg_10022c = tUNK_2 - 1;
 
-		timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
-				      tUNK_13 << 8  | tUNK_13);
+			timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
+						  tUNK_13 << 8  | tUNK_13);
 
-		/* XXX: +6? */
-		timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC);
-		timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;
+			timing->reg_100234 = (tRAS << 24 | tRC);
+			timing->reg_100234 += max(tUNK_10,tUNK_11) << 16;
 
-		/* XXX; reg_100238, reg_10023c
-		 * reg: 0x00??????
-		 * reg_10023c:
-		 *      0 for pre-NV50 cards
-		 *      0x????0202 for NV50+ cards (empirical evidence) */
-		if(dev_priv->card_type >= NV_50) {
+			if(dev_priv->chipset < 0xa3) {
+				timing->reg_100234 |= (tUNK_2 + 2) << 8;
+			} else {
+				/* XXX: +6? */
+				timing->reg_100234 |= (tUNK_19 + 6) << 8;
+			}
+
+			/* XXX; reg_100238, reg_10023c
+			 * reg_100238: 0x00??????
+			 * reg_10023c: 0x!!??0202 for NV50+ cards (empirical evidence) */
 			timing->reg_10023c = 0x202;
+			if(dev_priv->chipset < 0xa3) {
+				timing->reg_10023c |= 0x4000000 | (tUNK_2 - 1) << 16;
+			} else {
+				/* currently unknown
+				 * 10023c seen as 06xxxxxx, 0bxxxxxx or 0fxxxxxx */
+			}
 		}
 
 		NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
@@ -648,7 +695,7 @@
 			 timing->reg_100238, timing->reg_10023c);
 	}
 
-	memtimings->nr_timing  = entries;
+	memtimings->nr_timing = entries;
 	memtimings->supported = true;
 }
 
@@ -666,13 +713,14 @@
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 	struct nouveau_mm *mm;
-	u32 b_size;
+	u64 size, block, rsvd;
 	int ret;
 
-	p_size = (p_size << PAGE_SHIFT) >> 12;
-	b_size = dev_priv->vram_rblock_size >> 12;
+	rsvd  = (256 * 1024); /* vga memory */
+	size  = (p_size << PAGE_SHIFT) - rsvd;
+	block = dev_priv->vram_rblock_size;
 
-	ret = nouveau_mm_init(&mm, 0, p_size, b_size);
+	ret = nouveau_mm_init(&mm, rsvd >> 12, size >> 12, block >> 12);
 	if (ret)
 		return ret;
 
@@ -700,9 +748,15 @@
 {
 	struct drm_nouveau_private *dev_priv = nouveau_bdev(man->bdev);
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
+	struct nouveau_mem *node = mem->mm_node;
 	struct drm_device *dev = dev_priv->dev;
 
-	vram->put(dev, (struct nouveau_vram **)&mem->mm_node);
+	if (node->tmp_vma.node) {
+		nouveau_vm_unmap(&node->tmp_vma);
+		nouveau_vm_put(&node->tmp_vma);
+	}
+
+	vram->put(dev, (struct nouveau_mem **)&mem->mm_node);
 }
 
 static int
@@ -715,7 +769,7 @@
 	struct nouveau_vram_engine *vram = &dev_priv->engine.vram;
 	struct drm_device *dev = dev_priv->dev;
 	struct nouveau_bo *nvbo = nouveau_bo(bo);
-	struct nouveau_vram *node;
+	struct nouveau_mem *node;
 	u32 size_nc = 0;
 	int ret;
 
@@ -724,7 +778,7 @@
 
 	ret = vram->get(dev, mem->num_pages << PAGE_SHIFT,
 			mem->page_alignment << PAGE_SHIFT, size_nc,
-			(nvbo->tile_flags >> 8) & 0xff, &node);
+			(nvbo->tile_flags >> 8) & 0x3ff, &node);
 	if (ret) {
 		mem->mm_node = NULL;
 		return (ret == -ENOSPC) ? 0 : ret;
@@ -771,3 +825,84 @@
 	nouveau_vram_manager_del,
 	nouveau_vram_manager_debug
 };
+
+static int
+nouveau_gart_manager_init(struct ttm_mem_type_manager *man, unsigned long psize)
+{
+	return 0;
+}
+
+static int
+nouveau_gart_manager_fini(struct ttm_mem_type_manager *man)
+{
+	return 0;
+}
+
+static void
+nouveau_gart_manager_del(struct ttm_mem_type_manager *man,
+			 struct ttm_mem_reg *mem)
+{
+	struct nouveau_mem *node = mem->mm_node;
+
+	if (node->tmp_vma.node) {
+		nouveau_vm_unmap(&node->tmp_vma);
+		nouveau_vm_put(&node->tmp_vma);
+	}
+	mem->mm_node = NULL;
+}
+
+static int
+nouveau_gart_manager_new(struct ttm_mem_type_manager *man,
+			 struct ttm_buffer_object *bo,
+			 struct ttm_placement *placement,
+			 struct ttm_mem_reg *mem)
+{
+	struct drm_nouveau_private *dev_priv = nouveau_bdev(bo->bdev);
+	struct nouveau_bo *nvbo = nouveau_bo(bo);
+	struct nouveau_vma *vma = &nvbo->vma;
+	struct nouveau_vm *vm = vma->vm;
+	struct nouveau_mem *node;
+	int ret;
+
+	if (unlikely((mem->num_pages << PAGE_SHIFT) >=
+		     dev_priv->gart_info.aper_size))
+		return -ENOMEM;
+
+	node = kzalloc(sizeof(*node), GFP_KERNEL);
+	if (!node)
+		return -ENOMEM;
+
+	/* This node must be for evicting large-paged VRAM
+	 * to system memory.  Due to a nv50 limitation of
+	 * not being able to mix large/small pages within
+	 * the same PDE, we need to create a temporary
+	 * small-paged VMA for the eviction.
+	 */
+	if (vma->node->type != vm->spg_shift) {
+		ret = nouveau_vm_get(vm, (u64)vma->node->length << 12,
+				     vm->spg_shift, NV_MEM_ACCESS_RW,
+				     &node->tmp_vma);
+		if (ret) {
+			kfree(node);
+			return ret;
+		}
+	}
+
+	node->page_shift = nvbo->vma.node->type;
+	mem->mm_node = node;
+	mem->start   = 0;
+	return 0;
+}
+
+void
+nouveau_gart_manager_debug(struct ttm_mem_type_manager *man, const char *prefix)
+{
+}
+
+const struct ttm_mem_type_manager_func nouveau_gart_manager = {
+	nouveau_gart_manager_init,
+	nouveau_gart_manager_fini,
+	nouveau_gart_manager_new,
+	nouveau_gart_manager_del,
+	nouveau_gart_manager_debug
+};
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_mm.h	2011-05-19 00:06:34.000000000 -0400
@@ -53,13 +53,13 @@
 
 int  nv50_vram_init(struct drm_device *);
 int  nv50_vram_new(struct drm_device *, u64 size, u32 align, u32 size_nc,
-		    u32 memtype, struct nouveau_vram **);
-void nv50_vram_del(struct drm_device *, struct nouveau_vram **);
+		    u32 memtype, struct nouveau_mem **);
+void nv50_vram_del(struct drm_device *, struct nouveau_mem **);
 bool nv50_vram_flags_valid(struct drm_device *, u32 tile_flags);
 
 int  nvc0_vram_init(struct drm_device *);
 int  nvc0_vram_new(struct drm_device *, u64 size, u32 align, u32 ncmin,
-		    u32 memtype, struct nouveau_vram **);
+		    u32 memtype, struct nouveau_mem **);
 bool nvc0_vram_flags_valid(struct drm_device *, u32 tile_flags);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_notifier.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_notifier.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_notifier.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_notifier.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,20 +35,22 @@
 {
 	struct drm_device *dev = chan->dev;
 	struct nouveau_bo *ntfy = NULL;
-	uint32_t flags;
+	uint32_t flags, ttmpl;
 	int ret;
 
-	if (nouveau_vram_notify)
-		flags = TTM_PL_FLAG_VRAM;
-	else
-		flags = TTM_PL_FLAG_TT;
+	if (nouveau_vram_notify) {
+		flags = NOUVEAU_GEM_DOMAIN_VRAM;
+		ttmpl = TTM_PL_FLAG_VRAM;
+	} else {
+		flags = NOUVEAU_GEM_DOMAIN_GART;
+		ttmpl = TTM_PL_FLAG_TT;
+	}
 
-	ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags,
-			      0, 0x0000, false, true, &ntfy);
+	ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags, 0, 0, &ntfy);
 	if (ret)
 		return ret;
 
-	ret = nouveau_bo_pin(ntfy, flags);
+	ret = nouveau_bo_pin(ntfy, ttmpl);
 	if (ret)
 		goto out_err;
 
@@ -100,6 +102,7 @@
 		       uint32_t *b_offset)
 {
 	struct drm_device *dev = chan->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *nobj = NULL;
 	struct drm_mm_node *mem;
 	uint32_t offset;
@@ -114,11 +117,16 @@
 		return -ENOMEM;
 	}
 
-	if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM)
-		target = NV_MEM_TARGET_VRAM;
-	else
-		target = NV_MEM_TARGET_GART;
-	offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+	if (dev_priv->card_type < NV_50) {
+		if (chan->notifier_bo->bo.mem.mem_type == TTM_PL_VRAM)
+			target = NV_MEM_TARGET_VRAM;
+		else
+			target = NV_MEM_TARGET_GART;
+		offset  = chan->notifier_bo->bo.mem.start << PAGE_SHIFT;
+	} else {
+		target = NV_MEM_TARGET_VM;
+		offset = chan->notifier_bo->vma.offset;
+	}
 	offset += mem->start;
 
 	ret = nouveau_gpuobj_dma_new(chan, NV_CLASS_DMA_IN_MEMORY, offset,
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_object.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_object.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_object.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_object.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,7 @@
 #include "nouveau_drm.h"
 #include "nouveau_ramht.h"
 #include "nouveau_vm.h"
+#include "nv50_display.h"
 
 struct nouveau_gpuobj_method {
 	struct list_head head;
@@ -490,16 +491,22 @@
 	}
 
 	if (target == NV_MEM_TARGET_GART) {
-		if (dev_priv->gart_info.type == NOUVEAU_GART_AGP) {
-			target = NV_MEM_TARGET_PCI_NOSNOOP;
-			base  += dev_priv->gart_info.aper_base;
-		} else
-		if (base != 0) {
-			base = nouveau_sgdma_get_physical(dev, base);
+		struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
+
+		if (dev_priv->gart_info.type == NOUVEAU_GART_PDMA) {
+			if (base == 0) {
+				nouveau_gpuobj_ref(gart, pobj);
+				return 0;
+			}
+
+			base   = nouveau_sgdma_get_physical(dev, base);
 			target = NV_MEM_TARGET_PCI;
 		} else {
-			nouveau_gpuobj_ref(dev_priv->gart_info.sg_ctxdma, pobj);
-			return 0;
+			base += dev_priv->gart_info.aper_base;
+			if (dev_priv->gart_info.type == NOUVEAU_GART_AGP)
+				target = NV_MEM_TARGET_PCI_NOSNOOP;
+			else
+				target = NV_MEM_TARGET_PCI;
 		}
 	}
 
@@ -776,7 +783,7 @@
 	struct drm_device *dev = chan->dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *vram = NULL, *tt = NULL;
-	int ret;
+	int ret, i;
 
 	NV_DEBUG(dev, "ch%d vram=0x%08x tt=0x%08x\n", chan->id, vram_h, tt_h);
 
@@ -841,6 +848,25 @@
 		nouveau_gpuobj_ref(NULL, &ramht);
 		if (ret)
 			return ret;
+
+		/* dma objects for display sync channel semaphore blocks */
+		for (i = 0; i < 2; i++) {
+			struct nouveau_gpuobj *sem = NULL;
+			struct nv50_display_crtc *dispc =
+				&nv50_display(dev)->crtc[i];
+			u64 offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+
+			ret = nouveau_gpuobj_dma_new(chan, 0x3d, offset, 0xfff,
+						     NV_MEM_ACCESS_RW,
+						     NV_MEM_TARGET_VRAM, &sem);
+			if (ret)
+				return ret;
+
+			ret = nouveau_ramht_insert(chan, NvEvoSema0 + i, sem);
+			nouveau_gpuobj_ref(NULL, &sem);
+			if (ret)
+				return ret;
+		}
 	}
 
 	/* VRAM ctxdma */
@@ -909,7 +935,7 @@
 	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
 	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
 
-	if (chan->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
 }
@@ -1013,19 +1039,20 @@
 {
 	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
 	struct drm_device *dev = gpuobj->dev;
+	unsigned long flags;
 
 	if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
 		u64  ptr = gpuobj->vinst + offset;
 		u32 base = ptr >> 16;
 		u32  val;
 
-		spin_lock(&dev_priv->ramin_lock);
+		spin_lock_irqsave(&dev_priv->vm_lock, flags);
 		if (dev_priv->ramin_base != base) {
 			dev_priv->ramin_base = base;
 			nv_wr32(dev, 0x001700, dev_priv->ramin_base);
 		}
 		val = nv_rd32(dev, 0x700000 + (ptr & 0xffff));
-		spin_unlock(&dev_priv->ramin_lock);
+		spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 		return val;
 	}
 
@@ -1037,18 +1064,19 @@
 {
 	struct drm_nouveau_private *dev_priv = gpuobj->dev->dev_private;
 	struct drm_device *dev = gpuobj->dev;
+	unsigned long flags;
 
 	if (gpuobj->pinst == ~0 || !dev_priv->ramin_available) {
 		u64  ptr = gpuobj->vinst + offset;
 		u32 base = ptr >> 16;
 
-		spin_lock(&dev_priv->ramin_lock);
+		spin_lock_irqsave(&dev_priv->vm_lock, flags);
 		if (dev_priv->ramin_base != base) {
 			dev_priv->ramin_base = base;
 			nv_wr32(dev, 0x001700, dev_priv->ramin_base);
 		}
 		nv_wr32(dev, 0x700000 + (ptr & 0xffff), val);
-		spin_unlock(&dev_priv->ramin_lock);
+		spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 		return;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_perf.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,7 +134,7 @@
 		case 0x13:
 		case 0x15:
 			perflvl->fanspeed = entry[55];
-			perflvl->voltage = entry[56];
+			perflvl->voltage = (recordlen > 56) ? entry[56] : 0;
 			perflvl->core = ROM32(entry[1]) * 10;
 			perflvl->memory = ROM32(entry[5]) * 20;
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_ramht.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_ramht.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_ramht.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_ramht.c	2011-05-19 00:06:34.000000000 -0400
@@ -114,7 +114,9 @@
 		      (gpuobj->engine << NV40_RAMHT_CONTEXT_ENGINE_SHIFT);
 	} else {
 		if (gpuobj->engine == NVOBJ_ENGINE_DISPLAY) {
-			ctx = (gpuobj->cinst << 10) | chan->id;
+			ctx = (gpuobj->cinst << 10) |
+			      (chan->id << 28) |
+			      chan->id; /* HASH_TAG */
 		} else {
 			ctx = (gpuobj->cinst >> 4) |
 			      ((gpuobj->engine <<
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_sgdma.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 	struct drm_device *dev;
 
 	dma_addr_t *pages;
+	bool *ttm_alloced;
 	unsigned nr_pages;
 
 	u64 offset;
@@ -20,7 +21,8 @@
 
 static int
 nouveau_sgdma_populate(struct ttm_backend *be, unsigned long num_pages,
-		       struct page **pages, struct page *dummy_read_page)
+		       struct page **pages, struct page *dummy_read_page,
+		       dma_addr_t *dma_addrs)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
@@ -34,15 +36,27 @@
 	if (!nvbe->pages)
 		return -ENOMEM;
 
+	nvbe->ttm_alloced = kmalloc(sizeof(bool) * num_pages, GFP_KERNEL);
+	if (!nvbe->ttm_alloced)
+		return -ENOMEM;
+
 	nvbe->nr_pages = 0;
 	while (num_pages--) {
-		nvbe->pages[nvbe->nr_pages] =
-			pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
+		/* this code path isn't called and is incorrect anyways */
+		if (0) { /*dma_addrs[nvbe->nr_pages] != DMA_ERROR_CODE)*/
+			nvbe->pages[nvbe->nr_pages] =
+					dma_addrs[nvbe->nr_pages];
+		 	nvbe->ttm_alloced[nvbe->nr_pages] = true;
+		} else {
+			nvbe->pages[nvbe->nr_pages] =
+				pci_map_page(dev->pdev, pages[nvbe->nr_pages], 0,
 				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
-		if (pci_dma_mapping_error(dev->pdev,
-					  nvbe->pages[nvbe->nr_pages])) {
-			be->func->clear(be);
-			return -EFAULT;
+			if (pci_dma_mapping_error(dev->pdev,
+						  nvbe->pages[nvbe->nr_pages])) {
+				be->func->clear(be);
+				return -EFAULT;
+			}
+			nvbe->ttm_alloced[nvbe->nr_pages] = false;
 		}
 
 		nvbe->nr_pages++;
@@ -65,17 +79,36 @@
 			be->func->unbind(be);
 
 		while (nvbe->nr_pages--) {
-			pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
+			if (!nvbe->ttm_alloced[nvbe->nr_pages])
+				pci_unmap_page(dev->pdev, nvbe->pages[nvbe->nr_pages],
 				       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 		}
 		kfree(nvbe->pages);
+		kfree(nvbe->ttm_alloced);
 		nvbe->pages = NULL;
+		nvbe->ttm_alloced = NULL;
 		nvbe->nr_pages = 0;
 	}
 }
 
+static void
+nouveau_sgdma_destroy(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+
+	if (be) {
+		NV_DEBUG(nvbe->dev, "\n");
+
+		if (nvbe) {
+			if (nvbe->pages)
+				be->func->clear(be);
+			kfree(nvbe);
+		}
+	}
+}
+
 static int
-nouveau_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+nv04_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
@@ -102,7 +135,7 @@
 }
 
 static int
-nouveau_sgdma_unbind(struct ttm_backend *be)
+nv04_sgdma_unbind(struct ttm_backend *be)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_device *dev = nvbe->dev;
@@ -125,59 +158,245 @@
 	return 0;
 }
 
+static struct ttm_backend_func nv04_sgdma_backend = {
+	.populate		= nouveau_sgdma_populate,
+	.clear			= nouveau_sgdma_clear,
+	.bind			= nv04_sgdma_bind,
+	.unbind			= nv04_sgdma_unbind,
+	.destroy		= nouveau_sgdma_destroy
+};
+
 static void
-nouveau_sgdma_destroy(struct ttm_backend *be)
+nv41_sgdma_flush(struct nouveau_sgdma_be *nvbe)
+{
+	struct drm_device *dev = nvbe->dev;
+
+	nv_wr32(dev, 0x100810, 0x00000022);
+	if (!nv_wait(dev, 0x100810, 0x00000100, 0x00000100))
+		NV_ERROR(dev, "vm flush timeout: 0x%08x\n",
+			 nv_rd32(dev, 0x100810));
+	nv_wr32(dev, 0x100810, 0x00000000);
+}
+
+static int
+nv41_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	dma_addr_t *list = nvbe->pages;
+	u32 pte = mem->start << 2;
+	u32 cnt = nvbe->nr_pages;
 
-	if (be) {
-		NV_DEBUG(nvbe->dev, "\n");
+	nvbe->offset = mem->start << PAGE_SHIFT;
 
-		if (nvbe) {
-			if (nvbe->pages)
-				be->func->clear(be);
-			kfree(nvbe);
+	while (cnt--) {
+		nv_wo32(pgt, pte, (*list++ >> 7) | 1);
+		pte += 4;
+	}
+
+	nv41_sgdma_flush(nvbe);
+	nvbe->bound = true;
+	return 0;
+}
+
+static int
+nv41_sgdma_unbind(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	u32 pte = (nvbe->offset >> 12) << 2;
+	u32 cnt = nvbe->nr_pages;
+
+	while (cnt--) {
+		nv_wo32(pgt, pte, 0x00000000);
+		pte += 4;
+	}
+
+	nv41_sgdma_flush(nvbe);
+	nvbe->bound = false;
+	return 0;
+}
+
+static struct ttm_backend_func nv41_sgdma_backend = {
+	.populate		= nouveau_sgdma_populate,
+	.clear			= nouveau_sgdma_clear,
+	.bind			= nv41_sgdma_bind,
+	.unbind			= nv41_sgdma_unbind,
+	.destroy		= nouveau_sgdma_destroy
+};
+
+static void
+nv44_sgdma_flush(struct nouveau_sgdma_be *nvbe)
+{
+	struct drm_device *dev = nvbe->dev;
+
+	nv_wr32(dev, 0x100814, (nvbe->nr_pages - 1) << 12);
+	nv_wr32(dev, 0x100808, nvbe->offset | 0x20);
+	if (!nv_wait(dev, 0x100808, 0x00000001, 0x00000001))
+		NV_ERROR(dev, "gart flush timeout: 0x%08x\n",
+			 nv_rd32(dev, 0x100808));
+	nv_wr32(dev, 0x100808, 0x00000000);
+}
+
+static void
+nv44_sgdma_fill(struct nouveau_gpuobj *pgt, dma_addr_t *list, u32 base, u32 cnt)
+{
+	struct drm_nouveau_private *dev_priv = pgt->dev->dev_private;
+	dma_addr_t dummy = dev_priv->gart_info.dummy.addr;
+	u32 pte, tmp[4];
+
+	pte   = base >> 2;
+	base &= ~0x0000000f;
+
+	tmp[0] = nv_ro32(pgt, base + 0x0);
+	tmp[1] = nv_ro32(pgt, base + 0x4);
+	tmp[2] = nv_ro32(pgt, base + 0x8);
+	tmp[3] = nv_ro32(pgt, base + 0xc);
+	while (cnt--) {
+		u32 addr = list ? (*list++ >> 12) : (dummy >> 12);
+		switch (pte++ & 0x3) {
+		case 0:
+			tmp[0] &= ~0x07ffffff;
+			tmp[0] |= addr;
+			break;
+		case 1:
+			tmp[0] &= ~0xf8000000;
+			tmp[0] |= addr << 27;
+			tmp[1] &= ~0x003fffff;
+			tmp[1] |= addr >> 5;
+			break;
+		case 2:
+			tmp[1] &= ~0xffc00000;
+			tmp[1] |= addr << 22;
+			tmp[2] &= ~0x0001ffff;
+			tmp[2] |= addr >> 10;
+			break;
+		case 3:
+			tmp[2] &= ~0xfffe0000;
+			tmp[2] |= addr << 17;
+			tmp[3] &= ~0x00000fff;
+			tmp[3] |= addr >> 15;
+			break;
 		}
 	}
+
+	tmp[3] |= 0x40000000;
+
+	nv_wo32(pgt, base + 0x0, tmp[0]);
+	nv_wo32(pgt, base + 0x4, tmp[1]);
+	nv_wo32(pgt, base + 0x8, tmp[2]);
+	nv_wo32(pgt, base + 0xc, tmp[3]);
 }
 
 static int
-nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+nv44_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	dma_addr_t *list = nvbe->pages;
+	u32 pte = mem->start << 2, tmp[4];
+	u32 cnt = nvbe->nr_pages;
+	int i;
 
 	nvbe->offset = mem->start << PAGE_SHIFT;
 
-	nouveau_vm_map_sg(&dev_priv->gart_info.vma, nvbe->offset,
-			  nvbe->nr_pages << PAGE_SHIFT, nvbe->pages);
+	if (pte & 0x0000000c) {
+		u32  max = 4 - ((pte >> 2) & 0x3);
+		u32 part = (cnt > max) ? max : cnt;
+		nv44_sgdma_fill(pgt, list, pte, part);
+		pte  += (part << 2);
+		list += part;
+		cnt  -= part;
+	}
+
+	while (cnt >= 4) {
+		for (i = 0; i < 4; i++)
+			tmp[i] = *list++ >> 12;
+		nv_wo32(pgt, pte + 0x0, tmp[0] >>  0 | tmp[1] << 27);
+		nv_wo32(pgt, pte + 0x4, tmp[1] >>  5 | tmp[2] << 22);
+		nv_wo32(pgt, pte + 0x8, tmp[2] >> 10 | tmp[3] << 17);
+		nv_wo32(pgt, pte + 0xc, tmp[3] >> 15 | 0x40000000);
+		pte  += 0x10;
+		cnt  -= 4;
+	}
+
+	if (cnt)
+		nv44_sgdma_fill(pgt, list, pte, cnt);
+
+	nv44_sgdma_flush(nvbe);
 	nvbe->bound = true;
 	return 0;
 }
 
 static int
-nv50_sgdma_unbind(struct ttm_backend *be)
+nv44_sgdma_unbind(struct ttm_backend *be)
 {
 	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
 	struct drm_nouveau_private *dev_priv = nvbe->dev->dev_private;
+	struct nouveau_gpuobj *pgt = dev_priv->gart_info.sg_ctxdma;
+	u32 pte = (nvbe->offset >> 12) << 2;
+	u32 cnt = nvbe->nr_pages;
 
-	if (!nvbe->bound)
-		return 0;
+	if (pte & 0x0000000c) {
+		u32  max = 4 - ((pte >> 2) & 0x3);
+		u32 part = (cnt > max) ? max : cnt;
+		nv44_sgdma_fill(pgt, NULL, pte, part);
+		pte  += (part << 2);
+		cnt  -= part;
+	}
 
-	nouveau_vm_unmap_at(&dev_priv->gart_info.vma, nvbe->offset,
-			    nvbe->nr_pages << PAGE_SHIFT);
+	while (cnt >= 4) {
+		nv_wo32(pgt, pte + 0x0, 0x00000000);
+		nv_wo32(pgt, pte + 0x4, 0x00000000);
+		nv_wo32(pgt, pte + 0x8, 0x00000000);
+		nv_wo32(pgt, pte + 0xc, 0x00000000);
+		pte  += 0x10;
+		cnt  -= 4;
+	}
+
+	if (cnt)
+		nv44_sgdma_fill(pgt, NULL, pte, cnt);
+
+	nv44_sgdma_flush(nvbe);
 	nvbe->bound = false;
 	return 0;
 }
 
-static struct ttm_backend_func nouveau_sgdma_backend = {
+static struct ttm_backend_func nv44_sgdma_backend = {
 	.populate		= nouveau_sgdma_populate,
 	.clear			= nouveau_sgdma_clear,
-	.bind			= nouveau_sgdma_bind,
-	.unbind			= nouveau_sgdma_unbind,
+	.bind			= nv44_sgdma_bind,
+	.unbind			= nv44_sgdma_unbind,
 	.destroy		= nouveau_sgdma_destroy
 };
 
+static int
+nv50_sgdma_bind(struct ttm_backend *be, struct ttm_mem_reg *mem)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct nouveau_mem *node = mem->mm_node;
+	/* noop: bound in move_notify() */
+	node->pages = nvbe->pages;
+	nvbe->pages = (dma_addr_t *)node;
+	nvbe->bound = true;
+	return 0;
+}
+
+static int
+nv50_sgdma_unbind(struct ttm_backend *be)
+{
+	struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
+	struct nouveau_mem *node = (struct nouveau_mem *)nvbe->pages;
+	/* noop: unbound in move_notify() */
+	nvbe->pages = node->pages;
+	node->pages = NULL;
+	nvbe->bound = false;
+	return 0;
+}
+
 static struct ttm_backend_func nv50_sgdma_backend = {
 	.populate		= nouveau_sgdma_populate,
 	.clear			= nouveau_sgdma_clear,
@@ -198,10 +417,7 @@
 
 	nvbe->dev = dev;
 
-	if (dev_priv->card_type < NV_50)
-		nvbe->backend.func = &nouveau_sgdma_backend;
-	else
-		nvbe->backend.func = &nv50_sgdma_backend;
+	nvbe->backend.func = dev_priv->gart_info.func;
 	return &nvbe->backend;
 }
 
@@ -210,21 +426,64 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpuobj *gpuobj = NULL;
-	uint32_t aper_size, obj_size;
-	int i, ret;
+	u32 aper_size, align;
+	int ret;
 
-	if (dev_priv->card_type < NV_50) {
-		if(dev_priv->ramin_rsvd_vram < 2 * 1024 * 1024)
-			aper_size = 64 * 1024 * 1024;
-		else
-			aper_size = 512 * 1024 * 1024;
+	if (dev_priv->card_type >= NV_40 && drm_pci_device_is_pcie(dev))
+		aper_size = 512 * 1024 * 1024;
+	else
+		aper_size = 64 * 1024 * 1024;
 
-		obj_size  = (aper_size >> NV_CTXDMA_PAGE_SHIFT) * 4;
-		obj_size += 8; /* ctxdma header */
+	/* Dear NVIDIA, NV44+ would like proper present bits in PTEs for
+	 * christmas.  The cards before it have them, the cards after
+	 * it have them, why is NV44 so unloved?
+	 */
+	dev_priv->gart_info.dummy.page = alloc_page(GFP_DMA32 | GFP_KERNEL);
+	if (!dev_priv->gart_info.dummy.page)
+		return -ENOMEM;
 
-		ret = nouveau_gpuobj_new(dev, NULL, obj_size, 16,
-					      NVOBJ_FLAG_ZERO_ALLOC |
-					      NVOBJ_FLAG_ZERO_FREE, &gpuobj);
+	dev_priv->gart_info.dummy.addr =
+		pci_map_page(dev->pdev, dev_priv->gart_info.dummy.page,
+			     0, PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+	if (pci_dma_mapping_error(dev->pdev, dev_priv->gart_info.dummy.addr)) {
+		NV_ERROR(dev, "error mapping dummy page\n");
+		__free_page(dev_priv->gart_info.dummy.page);
+		dev_priv->gart_info.dummy.page = NULL;
+		return -ENOMEM;
+	}
+
+	if (dev_priv->card_type >= NV_50) {
+		dev_priv->gart_info.aper_base = 0;
+		dev_priv->gart_info.aper_size = aper_size;
+		dev_priv->gart_info.type = NOUVEAU_GART_HW;
+		dev_priv->gart_info.func = &nv50_sgdma_backend;
+	} else
+	if (drm_pci_device_is_pcie(dev) &&
+	    dev_priv->chipset > 0x40 && dev_priv->chipset != 0x45) {
+		if (nv44_graph_class(dev)) {
+			dev_priv->gart_info.func = &nv44_sgdma_backend;
+			align = 512 * 1024;
+		} else {
+			dev_priv->gart_info.func = &nv41_sgdma_backend;
+			align = 16;
+		}
+
+		ret = nouveau_gpuobj_new(dev, NULL, aper_size / 1024, align,
+					 NVOBJ_FLAG_ZERO_ALLOC |
+					 NVOBJ_FLAG_ZERO_FREE, &gpuobj);
+		if (ret) {
+			NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
+			return ret;
+		}
+
+		dev_priv->gart_info.sg_ctxdma = gpuobj;
+		dev_priv->gart_info.aper_base = 0;
+		dev_priv->gart_info.aper_size = aper_size;
+		dev_priv->gart_info.type = NOUVEAU_GART_HW;
+	} else {
+		ret = nouveau_gpuobj_new(dev, NULL, (aper_size / 1024) + 8, 16,
+					 NVOBJ_FLAG_ZERO_ALLOC |
+					 NVOBJ_FLAG_ZERO_FREE, &gpuobj);
 		if (ret) {
 			NV_ERROR(dev, "Error creating sgdma object: %d\n", ret);
 			return ret;
@@ -236,25 +495,14 @@
 				   (0 << 14) /* RW */ |
 				   (2 << 16) /* PCI */);
 		nv_wo32(gpuobj, 4, aper_size - 1);
-		for (i = 2; i < 2 + (aper_size >> 12); i++)
-			nv_wo32(gpuobj, i * 4, 0x00000000);
 
 		dev_priv->gart_info.sg_ctxdma = gpuobj;
 		dev_priv->gart_info.aper_base = 0;
 		dev_priv->gart_info.aper_size = aper_size;
-	} else
-	if (dev_priv->chan_vm) {
-		ret = nouveau_vm_get(dev_priv->chan_vm, 512 * 1024 * 1024,
-				     12, NV_MEM_ACCESS_RW,
-				     &dev_priv->gart_info.vma);
-		if (ret)
-			return ret;
-
-		dev_priv->gart_info.aper_base = dev_priv->gart_info.vma.offset;
-		dev_priv->gart_info.aper_size = 512 * 1024 * 1024;
+		dev_priv->gart_info.type = NOUVEAU_GART_PDMA;
+		dev_priv->gart_info.func = &nv04_sgdma_backend;
 	}
 
-	dev_priv->gart_info.type      = NOUVEAU_GART_SGDMA;
 	return 0;
 }
 
@@ -264,7 +512,13 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 
 	nouveau_gpuobj_ref(NULL, &dev_priv->gart_info.sg_ctxdma);
-	nouveau_vm_put(&dev_priv->gart_info.vma);
+
+	if (dev_priv->gart_info.dummy.page) {
+		pci_unmap_page(dev->pdev, dev_priv->gart_info.dummy.addr,
+			       PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
+		__free_page(dev_priv->gart_info.dummy.page);
+		dev_priv->gart_info.dummy.page = NULL;
+	}
 }
 
 uint32_t
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_state.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_state.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_state.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_state.c	2011-05-19 00:06:34.000000000 -0400
@@ -376,15 +376,11 @@
 		engine->graph.destroy_context	= nv50_graph_destroy_context;
 		engine->graph.load_context	= nv50_graph_load_context;
 		engine->graph.unload_context	= nv50_graph_unload_context;
-		if (dev_priv->chipset != 0x86)
+		if (dev_priv->chipset == 0x50 ||
+		    dev_priv->chipset == 0xac)
 			engine->graph.tlb_flush	= nv50_graph_tlb_flush;
-		else {
-			/* from what i can see nvidia do this on every
-			 * pre-NVA3 board except NVAC, but, we've only
-			 * ever seen problems on NV86
-			 */
-			engine->graph.tlb_flush	= nv86_graph_tlb_flush;
-		}
+		else
+			engine->graph.tlb_flush	= nv84_graph_tlb_flush;
 		engine->fifo.channels		= 128;
 		engine->fifo.init		= nv50_fifo_init;
 		engine->fifo.takedown		= nv50_fifo_takedown;
@@ -544,7 +540,6 @@
 nouveau_card_init_channel(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_gpuobj *gpuobj = NULL;
 	int ret;
 
 	ret = nouveau_channel_alloc(dev, &dev_priv->channel,
@@ -552,41 +547,8 @@
 	if (ret)
 		return ret;
 
-	/* no dma objects on fermi... */
-	if (dev_priv->card_type >= NV_C0)
-		goto out_done;
-
-	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
-				     0, dev_priv->vram_size,
-				     NV_MEM_ACCESS_RW, NV_MEM_TARGET_VRAM,
-				     &gpuobj);
-	if (ret)
-		goto out_err;
-
-	ret = nouveau_ramht_insert(dev_priv->channel, NvDmaVRAM, gpuobj);
-	nouveau_gpuobj_ref(NULL, &gpuobj);
-	if (ret)
-		goto out_err;
-
-	ret = nouveau_gpuobj_dma_new(dev_priv->channel, NV_CLASS_DMA_IN_MEMORY,
-				     0, dev_priv->gart_info.aper_size,
-				     NV_MEM_ACCESS_RW, NV_MEM_TARGET_GART,
-				     &gpuobj);
-	if (ret)
-		goto out_err;
-
-	ret = nouveau_ramht_insert(dev_priv->channel, NvDmaGART, gpuobj);
-	nouveau_gpuobj_ref(NULL, &gpuobj);
-	if (ret)
-		goto out_err;
-
-out_done:
 	mutex_unlock(&dev_priv->channel->mutex);
 	return 0;
-
-out_err:
-	nouveau_channel_put(&dev_priv->channel);
-	return ret;
 }
 
 static void nouveau_switcheroo_set_state(struct pci_dev *pdev,
@@ -646,6 +608,7 @@
 	spin_lock_init(&dev_priv->channels.lock);
 	spin_lock_init(&dev_priv->tile.lock);
 	spin_lock_init(&dev_priv->context_switch_lock);
+	spin_lock_init(&dev_priv->vm_lock);
 
 	/* Make the CRTCs and I2C buses accessible */
 	ret = engine->display.early_init(dev);
@@ -738,10 +701,6 @@
 			goto out_fence;
 	}
 
-	ret = nouveau_backlight_init(dev);
-	if (ret)
-		NV_ERROR(dev, "Error %d registering backlight\n", ret);
-
 	nouveau_fbcon_init(dev);
 	drm_kms_helper_poll_init(dev);
 	return 0;
@@ -793,8 +752,6 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_engine *engine = &dev_priv->engine;
 
-	nouveau_backlight_exit(dev);
-
 	if (!engine->graph.accel_blocked) {
 		nouveau_fence_fini(dev);
 		nouveau_channel_put_unlocked(&dev_priv->channel);
@@ -811,6 +768,11 @@
 	engine->mc.takedown(dev);
 	engine->display.late_takedown(dev);
 
+	if (dev_priv->vga_ram) {
+		nouveau_bo_unpin(dev_priv->vga_ram);
+		nouveau_bo_ref(NULL, &dev_priv->vga_ram);
+	}
+
 	mutex_lock(&dev->struct_mutex);
 	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
 	ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT);
@@ -929,12 +891,6 @@
 	NV_DEBUG(dev, "vendor: 0x%X device: 0x%X class: 0x%X\n",
 		 dev->pci_vendor, dev->pci_device, dev->pdev->class);
 
-	dev_priv->wq = create_workqueue("nouveau");
-	if (!dev_priv->wq) {
-		ret = -EINVAL;
-		goto err_priv;
-	}
-
 	/* resource 0 is mmio regs */
 	/* resource 1 is linear FB */
 	/* resource 2 is RAMIN (mmio regs + 0x1000000) */
@@ -947,7 +903,7 @@
 		NV_ERROR(dev, "Unable to initialize the mmio mapping. "
 			 "Please report your setup to " DRIVER_EMAIL "\n");
 		ret = -EINVAL;
-		goto err_wq;
+		goto err_priv;
 	}
 	NV_DEBUG(dev, "regs mapped ok at 0x%llx\n",
 					(unsigned long long)mmio_start_offs);
@@ -1009,7 +965,7 @@
 	if (ret)
 		goto err_mmio;
 
-	/* Map PRAMIN BAR, or on older cards, the aperture withing BAR0 */
+	/* Map PRAMIN BAR, or on older cards, the aperture within BAR0 */
 	if (dev_priv->card_type >= NV_40) {
 		int ramin_bar = 2;
 		if (pci_resource_len(dev->pdev, ramin_bar) == 0)
@@ -1054,8 +1010,6 @@
 	iounmap(dev_priv->ramin);
 err_mmio:
 	iounmap(dev_priv->mmio);
-err_wq:
-	destroy_workqueue(dev_priv->wq);
 err_priv:
 	kfree(dev_priv);
 	dev->dev_private = NULL;
@@ -1103,9 +1057,9 @@
 		getparam->value = dev->pci_device;
 		break;
 	case NOUVEAU_GETPARAM_BUS_TYPE:
-		if (drm_device_is_agp(dev))
+		if (drm_pci_device_is_agp(dev))
 			getparam->value = NV_AGP;
-		else if (drm_device_is_pcie(dev))
+		else if (drm_pci_device_is_pcie(dev))
 			getparam->value = NV_PCIE;
 		else
 			getparam->value = NV_PCI;
@@ -1126,7 +1080,7 @@
 		getparam->value = 1;
 		break;
 	case NOUVEAU_GETPARAM_HAS_PAGEFLIP:
-		getparam->value = (dev_priv->card_type < NV_50);
+		getparam->value = 1;
 		break;
 	case NOUVEAU_GETPARAM_GRAPH_UNITS:
 		/* NV40 and NV50 versions are quite different, but register
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_temp.c	2011-05-19 00:06:34.000000000 -0400
@@ -239,11 +239,9 @@
 probe_monitoring_device(struct nouveau_i2c_chan *i2c,
 			struct i2c_board_info *info)
 {
-	char modalias[16] = "i2c:";
 	struct i2c_client *client;
 
-	strlcat(modalias, info->type, sizeof(modalias));
-	request_module(modalias);
+	request_module("%s%s", I2C_MODULE_PREFIX, info->type);
 
 	client = i2c_new_device(&i2c->adapter, info);
 	if (!client)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_util.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_util.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_util.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_util.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,18 +47,27 @@
 		printk(" (unknown bits 0x%08x)", value);
 }
 
-void
-nouveau_enum_print(const struct nouveau_enum *en, u32 value)
+const struct nouveau_enum *
+nouveau_enum_find(const struct nouveau_enum *en, u32 value)
 {
 	while (en->name) {
-		if (value == en->value) {
-			printk("%s", en->name);
-			return;
-		}
-
+		if (en->value == value)
+			return en;
 		en++;
 	}
 
+	return NULL;
+}
+
+void
+nouveau_enum_print(const struct nouveau_enum *en, u32 value)
+{
+	en = nouveau_enum_find(en, value);
+	if (en) {
+		printk("%s", en->name);
+		return;
+	}
+
 	printk("(unknown enum 0x%08x)", value);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_util.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_util.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_util.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_util.h	2011-05-19 00:06:34.000000000 -0400
@@ -36,10 +36,14 @@
 struct nouveau_enum {
 	u32 value;
 	const char *name;
+	void *data;
 };
 
 void nouveau_bitfield_print(const struct nouveau_bitfield *, u32 value);
 void nouveau_enum_print(const struct nouveau_enum *, u32 value);
+const struct nouveau_enum *
+nouveau_enum_find(const struct nouveau_enum *, u32 value);
+
 int nouveau_ratelimit(void);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_vm.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,7 @@
 #include "nouveau_vm.h"
 
 void
-nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_vram *vram)
+nouveau_vm_map_at(struct nouveau_vma *vma, u64 delta, struct nouveau_mem *node)
 {
 	struct nouveau_vm *vm = vma->vm;
 	struct nouveau_mm_node *r;
@@ -40,7 +40,8 @@
 	u32 max  = 1 << (vm->pgt_bits - bits);
 	u32 end, len;
 
-	list_for_each_entry(r, &vram->regions, rl_entry) {
+	delta = 0;
+	list_for_each_entry(r, &node->regions, rl_entry) {
 		u64 phys = (u64)r->offset << 12;
 		u32 num  = r->length >> bits;
 
@@ -52,7 +53,7 @@
 				end = max;
 			len = end - pte;
 
-			vm->map(vma, pgt, vram, pte, len, phys);
+			vm->map(vma, pgt, node, pte, len, phys, delta);
 
 			num -= len;
 			pte += len;
@@ -60,6 +61,8 @@
 				pde++;
 				pte = 0;
 			}
+
+			delta += (u64)len << vma->node->type;
 		}
 	}
 
@@ -67,14 +70,14 @@
 }
 
 void
-nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_vram *vram)
+nouveau_vm_map(struct nouveau_vma *vma, struct nouveau_mem *node)
 {
-	nouveau_vm_map_at(vma, 0, vram);
+	nouveau_vm_map_at(vma, 0, node);
 }
 
 void
 nouveau_vm_map_sg(struct nouveau_vma *vma, u64 delta, u64 length,
-		  dma_addr_t *list)
+		  struct nouveau_mem *mem, dma_addr_t *list)
 {
 	struct nouveau_vm *vm = vma->vm;
 	int big = vma->node->type != vm->spg_shift;
@@ -94,7 +97,7 @@
 			end = max;
 		len = end - pte;
 
-		vm->map_sg(vma, pgt, pte, list, len);
+		vm->map_sg(vma, pgt, mem, pte, len, list);
 
 		num  -= len;
 		pte  += len;
@@ -311,18 +314,7 @@
 		vm->spg_shift = 12;
 		vm->lpg_shift = 17;
 		pgt_bits = 27;
-
-		/* Should be 4096 everywhere, this is a hack that's
-		 * currently necessary to avoid an elusive bug that
-		 * causes corruption when mixing small/large pages
-		 */
-		if (length < (1ULL << 40))
-			block = 4096;
-		else {
-			block = (1 << pgt_bits);
-			if (length < block)
-				block = length;
-		}
+		block = 4096;
 	} else {
 		kfree(vm);
 		return -ENOSYS;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nouveau_vm.h	2011-05-19 00:06:34.000000000 -0400
@@ -67,9 +67,10 @@
 	void (*map_pgt)(struct nouveau_gpuobj *pgd, u32 pde,
 			struct nouveau_gpuobj *pgt[2]);
 	void (*map)(struct nouveau_vma *, struct nouveau_gpuobj *,
-		    struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+		    struct nouveau_mem *, u32 pte, u32 cnt,
+		    u64 phys, u64 delta);
 	void (*map_sg)(struct nouveau_vma *, struct nouveau_gpuobj *,
-		       u32 pte, dma_addr_t *, u32 cnt);
+		       struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
 	void (*unmap)(struct nouveau_gpuobj *pgt, u32 pte, u32 cnt);
 	void (*flush)(struct nouveau_vm *);
 };
@@ -82,20 +83,20 @@
 int  nouveau_vm_get(struct nouveau_vm *, u64 size, u32 page_shift,
 		    u32 access, struct nouveau_vma *);
 void nouveau_vm_put(struct nouveau_vma *);
-void nouveau_vm_map(struct nouveau_vma *, struct nouveau_vram *);
-void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_vram *);
+void nouveau_vm_map(struct nouveau_vma *, struct nouveau_mem *);
+void nouveau_vm_map_at(struct nouveau_vma *, u64 offset, struct nouveau_mem *);
 void nouveau_vm_unmap(struct nouveau_vma *);
 void nouveau_vm_unmap_at(struct nouveau_vma *, u64 offset, u64 length);
 void nouveau_vm_map_sg(struct nouveau_vma *, u64 offset, u64 length,
-		       dma_addr_t *);
+		       struct nouveau_mem *, dma_addr_t *);
 
 /* nv50_vm.c */
 void nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 		     struct nouveau_gpuobj *pgt[2]);
 void nv50_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
-		 struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+		 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
 void nv50_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
-		    u32 pte, dma_addr_t *, u32 cnt);
+		    struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
 void nv50_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
 void nv50_vm_flush(struct nouveau_vm *);
 void nv50_vm_flush_engine(struct drm_device *, int engine);
@@ -104,9 +105,9 @@
 void nvc0_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 		     struct nouveau_gpuobj *pgt[2]);
 void nvc0_vm_map(struct nouveau_vma *, struct nouveau_gpuobj *,
-		 struct nouveau_vram *, u32 pte, u32 cnt, u64 phys);
+		 struct nouveau_mem *, u32 pte, u32 cnt, u64 phys, u64 delta);
 void nvc0_vm_map_sg(struct nouveau_vma *, struct nouveau_gpuobj *,
-		    u32 pte, dma_addr_t *, u32 cnt);
+		    struct nouveau_mem *, u32 pte, u32 cnt, dma_addr_t *);
 void nvc0_vm_unmap(struct nouveau_gpuobj *, u32 pte, u32 cnt);
 void nvc0_vm_flush(struct nouveau_vm *);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv04_crtc.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv04_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv04_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv04_crtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -164,7 +164,7 @@
 	NV_DEBUG_KMS(dev, "Setting dpms mode %d on CRTC %d\n", mode,
 							nv_crtc->index);
 
-	if (nv_crtc->last_dpms == mode) /* Don't do unnecesary mode changes. */
+	if (nv_crtc->last_dpms == mode) /* Don't do unnecessary mode changes. */
 		return;
 
 	nv_crtc->last_dpms = mode;
@@ -677,7 +677,7 @@
 
 	NVBlankScreen(dev, nv_crtc->index, true);
 
-	/* Some more preperation. */
+	/* Some more preparation. */
 	NVWriteCRTC(dev, nv_crtc->index, NV_PCRTC_CONFIG, NV_PCRTC_CONFIG_START_ADDRESS_NON_VGA);
 	if (dev_priv->card_type == NV_40) {
 		uint32_t reg900 = NVReadRAMDAC(dev, nv_crtc->index, NV_PRAMDAC_900);
@@ -1031,7 +1031,7 @@
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
 	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
-			     0, 0x0000, false, true, &nv_crtc->cursor.nvbo);
+			     0, 0x0000, &nv_crtc->cursor.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv04_dfp.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv04_dfp.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv04_dfp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv04_dfp.c	2011-05-19 00:06:34.000000000 -0400
@@ -581,12 +581,13 @@
 	int head = nv_encoder->restore.head;
 
 	if (nv_encoder->dcb->type == OUTPUT_LVDS) {
-		struct drm_display_mode *native_mode = nouveau_encoder_connector_get(nv_encoder)->native_mode;
-		if (native_mode)
-			call_lvds_script(dev, nv_encoder->dcb, head, LVDS_PANEL_ON,
-					 native_mode->clock);
-		else
-			NV_ERROR(dev, "Not restoring LVDS without native mode\n");
+		struct nouveau_connector *connector =
+			nouveau_encoder_connector_get(nv_encoder);
+
+		if (connector && connector->native_mode)
+			call_lvds_script(dev, nv_encoder->dcb, head,
+					 LVDS_PANEL_ON,
+					 connector->native_mode->clock);
 
 	} else if (nv_encoder->dcb->type == OUTPUT_TMDS) {
 		int clock = nouveau_hw_pllvals_to_clk
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv04_fifo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv04_fifo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv04_fifo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv04_fifo.c	2011-05-19 00:06:34.000000000 -0400
@@ -379,6 +379,15 @@
 	return handled;
 }
 
+static const char *nv_dma_state_err(u32 state)
+{
+	static const char * const desc[] = {
+		"NONE", "CALL_SUBR_ACTIVE", "INVALID_MTHD", "RET_SUBR_INACTIVE",
+		"INVALID_CMD", "IB_EMPTY"/* NV50+ */, "MEM_FAULT", "UNK"
+	};
+	return desc[(state >> 29) & 0x7];
+}
+
 void
 nv04_fifo_isr(struct drm_device *dev)
 {
@@ -460,9 +469,10 @@
 				if (nouveau_ratelimit())
 					NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%02x%08x "
 					     "Put 0x%02x%08x IbGet 0x%08x IbPut 0x%08x "
-					     "State 0x%08x Push 0x%08x\n",
+					     "State 0x%08x (err: %s) Push 0x%08x\n",
 						chid, ho_get, dma_get, ho_put,
 						dma_put, ib_get, ib_put, state,
+						nv_dma_state_err(state),
 						push);
 
 				/* METHOD_COUNT, in DMA_STATE on earlier chipsets */
@@ -476,8 +486,9 @@
 				}
 			} else {
 				NV_INFO(dev, "PFIFO_DMA_PUSHER - Ch %d Get 0x%08x "
-					     "Put 0x%08x State 0x%08x Push 0x%08x\n",
-					chid, dma_get, dma_put, state, push);
+					     "Put 0x%08x State 0x%08x (err: %s) Push 0x%08x\n",
+					chid, dma_get, dma_put, state,
+					nv_dma_state_err(state), push);
 
 				if (dma_get != dma_put)
 					nv_wr32(dev, 0x003244, dma_put);
@@ -505,7 +516,7 @@
 
 		if (dev_priv->card_type == NV_50) {
 			if (status & 0x00000010) {
-				nv50_fb_vm_trap(dev, 1, "PFIFO_BAR_FAULT");
+				nv50_fb_vm_trap(dev, nouveau_ratelimit());
 				status &= ~0x00000010;
 				nv_wr32(dev, 0x002100, 0x00000010);
 			}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv17_tv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv17_tv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv17_tv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv17_tv.c	2011-05-19 00:06:34.000000000 -0400
@@ -197,10 +197,12 @@
 				struct drm_connector *connector)
 {
 	struct nv17_tv_norm_params *tv_norm = get_tv_norm(encoder);
-	struct drm_display_mode *mode, *tv_mode;
+	const struct drm_display_mode *tv_mode;
 	int n = 0;
 
 	for (tv_mode = nv17_tv_modes; tv_mode->hdisplay; tv_mode++) {
+		struct drm_display_mode *mode;
+
 		mode = drm_mode_duplicate(encoder->dev, tv_mode);
 
 		mode->clock = tv_norm->tv_enc_mode.vrefresh *
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv17_tv.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv17_tv.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv17_tv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv17_tv.h	2011-05-19 00:06:34.000000000 -0400
@@ -112,7 +112,7 @@
 } nv17_tv_norms[NUM_TV_NORMS];
 #define get_tv_norm(enc) (&nv17_tv_norms[to_tv_enc(enc)->tv_norm])
 
-extern struct drm_display_mode nv17_tv_modes[];
+extern const struct drm_display_mode nv17_tv_modes[];
 
 static inline int interpolate(int y0, int y1, int y2, int x)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv17_tv_modes.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv17_tv_modes.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv17_tv_modes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv17_tv_modes.c	2011-05-19 00:06:34.000000000 -0400
@@ -438,7 +438,7 @@
 
 /* Timings similar to the ones the blob sets */
 
-struct drm_display_mode nv17_tv_modes[] = {
+const struct drm_display_mode nv17_tv_modes[] = {
 	{ DRM_MODE("320x200", DRM_MODE_TYPE_DRIVER, 0,
 		   320, 344, 392, 560, 0, 200, 200, 202, 220, 0,
 		   DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv40_fb.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv40_fb.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv40_fb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv40_fb.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,53 @@
 	}
 }
 
+static void
+nv40_fb_init_gart(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
+
+	if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
+		nv_wr32(dev, 0x100800, 0x00000001);
+		return;
+	}
+
+	nv_wr32(dev, 0x100800, gart->pinst | 0x00000002);
+	nv_mask(dev, 0x10008c, 0x00000100, 0x00000100);
+	nv_wr32(dev, 0x100820, 0x00000000);
+}
+
+static void
+nv44_fb_init_gart(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_gpuobj *gart = dev_priv->gart_info.sg_ctxdma;
+	u32 vinst;
+
+	if (dev_priv->gart_info.type != NOUVEAU_GART_HW) {
+		nv_wr32(dev, 0x100850, 0x80000000);
+		nv_wr32(dev, 0x100800, 0x00000001);
+		return;
+	}
+
+	/* calculate vram address of this PRAMIN block, object
+	 * must be allocated on 512KiB alignment, and not exceed
+	 * a total size of 512KiB for this to work correctly
+	 */
+	vinst  = nv_rd32(dev, 0x10020c);
+	vinst -= ((gart->pinst >> 19) + 1) << 19;
+
+	nv_wr32(dev, 0x100850, 0x80000000);
+	nv_wr32(dev, 0x100818, dev_priv->gart_info.dummy.addr);
+
+	nv_wr32(dev, 0x100804, dev_priv->gart_info.aper_size);
+	nv_wr32(dev, 0x100850, 0x00008000);
+	nv_mask(dev, 0x10008c, 0x00000200, 0x00000200);
+	nv_wr32(dev, 0x100820, 0x00000000);
+	nv_wr32(dev, 0x10082c, 0x00000001);
+	nv_wr32(dev, 0x100800, vinst | 0x00000010);
+}
+
 int
 nv40_fb_init(struct drm_device *dev)
 {
@@ -32,12 +79,12 @@
 	uint32_t tmp;
 	int i;
 
-	/* This is strictly a NV4x register (don't know about NV5x). */
-	/* The blob sets these to all kinds of values, and they mess up our setup. */
-	/* I got value 0x52802 instead. For some cards the blob even sets it back to 0x1. */
-	/* Note: the blob doesn't read this value, so i'm pretty sure this is safe for all cards. */
-	/* Any idea what this is? */
-	nv_wr32(dev, NV40_PFB_UNK_800, 0x1);
+	if (dev_priv->chipset != 0x40 && dev_priv->chipset != 0x45) {
+		if (nv44_graph_class(dev))
+			nv44_fb_init_gart(dev);
+		else
+			nv40_fb_init_gart(dev);
+	}
 
 	switch (dev_priv->chipset) {
 	case 0x40:
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv40_graph.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv40_graph.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv40_graph.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv40_graph.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,7 +181,7 @@
 		  NV40_PGRAPH_CTXCTL_CUR_LOADED);
 	/* 0x32E0 records the instance address of the active FIFO's PGRAPH
 	 * context.  If at any time this doesn't match 0x40032C, you will
-	 * recieve PGRAPH_INTR_CONTEXT_SWITCH
+	 * receive PGRAPH_INTR_CONTEXT_SWITCH
 	 */
 	nv_wr32(dev, NV40_PFIFO_GRCTX_INSTANCE, inst);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_crtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
 {
 	struct drm_device *dev = nv_crtc->base.dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int index = nv_crtc->index, ret;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
@@ -135,8 +135,7 @@
 nv50_crtc_set_dither(struct nouveau_crtc *nv_crtc, bool on, bool update)
 {
 	struct drm_device *dev = nv_crtc->base.dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "\n");
@@ -186,8 +185,7 @@
 	struct nouveau_connector *nv_connector =
 		nouveau_crtc_connector_get(nv_crtc);
 	struct drm_device *dev = nv_crtc->base.dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct drm_display_mode *native_mode = NULL;
 	struct drm_display_mode *mode = &nv_crtc->base.mode;
 	uint32_t outX, outY, horiz, vert;
@@ -445,6 +443,39 @@
 {
 }
 
+static int
+nv50_crtc_wait_complete(struct drm_crtc *crtc)
+{
+	struct drm_device *dev = crtc->dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
+	struct nv50_display *disp = nv50_display(dev);
+	struct nouveau_channel *evo = disp->master;
+	u64 start;
+	int ret;
+
+	ret = RING_SPACE(evo, 6);
+	if (ret)
+		return ret;
+	BEGIN_RING(evo, 0, 0x0084, 1);
+	OUT_RING  (evo, 0x80000000);
+	BEGIN_RING(evo, 0, 0x0080, 1);
+	OUT_RING  (evo, 0);
+	BEGIN_RING(evo, 0, 0x0084, 1);
+	OUT_RING  (evo, 0x00000000);
+
+	nv_wo32(disp->ntfy, 0x000, 0x00000000);
+	FIRE_RING (evo);
+
+	start = ptimer->read(dev);
+	do {
+		if (nv_ro32(disp->ntfy, 0x000))
+			return 0;
+	} while (ptimer->read(dev) - start < 2000000000ULL);
+
+	return -EBUSY;
+}
+
 static void
 nv50_crtc_prepare(struct drm_crtc *crtc)
 {
@@ -453,6 +484,7 @@
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
+	nv50_display_flip_stop(crtc);
 	drm_vblank_pre_modeset(dev, nv_crtc->index);
 	nv50_crtc_blank(nv_crtc, true);
 }
@@ -461,24 +493,14 @@
 nv50_crtc_commit(struct drm_crtc *crtc)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
-	int ret;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
 	nv50_crtc_blank(nv_crtc, false);
 	drm_vblank_post_modeset(dev, nv_crtc->index);
-
-	ret = RING_SPACE(evo, 2);
-	if (ret) {
-		NV_ERROR(dev, "no space while committing crtc\n");
-		return;
-	}
-	BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
-	OUT_RING  (evo, 0);
-	FIRE_RING (evo);
+	nv50_crtc_wait_complete(crtc);
+	nv50_display_flip_next(crtc, crtc->fb, NULL);
 }
 
 static bool
@@ -491,15 +513,15 @@
 static int
 nv50_crtc_do_mode_set_base(struct drm_crtc *crtc,
 			   struct drm_framebuffer *passed_fb,
-			   int x, int y, bool update, bool atomic)
+			   int x, int y, bool atomic)
 {
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct drm_device *dev = nv_crtc->base.dev;
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct drm_framebuffer *drm_fb = nv_crtc->base.fb;
 	struct nouveau_framebuffer *fb = nouveau_framebuffer(drm_fb);
-	int ret, format;
+	int ret;
 
 	NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index);
 
@@ -525,28 +547,6 @@
 		}
 	}
 
-	switch (drm_fb->depth) {
-	case  8:
-		format = NV50_EVO_CRTC_FB_DEPTH_8;
-		break;
-	case 15:
-		format = NV50_EVO_CRTC_FB_DEPTH_15;
-		break;
-	case 16:
-		format = NV50_EVO_CRTC_FB_DEPTH_16;
-		break;
-	case 24:
-	case 32:
-		format = NV50_EVO_CRTC_FB_DEPTH_24;
-		break;
-	case 30:
-		format = NV50_EVO_CRTC_FB_DEPTH_30;
-		break;
-	default:
-		 NV_ERROR(dev, "unknown depth %d\n", drm_fb->depth);
-		 return -EINVAL;
-	}
-
 	nv_crtc->fb.offset = fb->nvbo->bo.mem.start << PAGE_SHIFT;
 	nv_crtc->fb.tile_flags = nouveau_bo_tile_layout(fb->nvbo);
 	nv_crtc->fb.cpp = drm_fb->bits_per_pixel / 8;
@@ -556,14 +556,7 @@
 			return ret;
 
 		BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_DMA), 1);
-		if (nv_crtc->fb.tile_flags == 0x7a00 ||
-		    nv_crtc->fb.tile_flags == 0xfe00)
-			OUT_RING(evo, NvEvoFB32);
-		else
-		if (nv_crtc->fb.tile_flags == 0x7000)
-			OUT_RING(evo, NvEvoFB16);
-		else
-			OUT_RING(evo, NvEvoVRAM_LP);
+		OUT_RING  (evo, fb->r_dma);
 	}
 
 	ret = RING_SPACE(evo, 12);
@@ -571,45 +564,26 @@
 		return ret;
 
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_OFFSET), 5);
-	OUT_RING(evo, nv_crtc->fb.offset >> 8);
-	OUT_RING(evo, 0);
-	OUT_RING(evo, (drm_fb->height << 16) | drm_fb->width);
-	if (!nv_crtc->fb.tile_flags) {
-		OUT_RING(evo, drm_fb->pitch | (1 << 20));
-	} else {
-		u32 tile_mode = fb->nvbo->tile_mode;
-		if (dev_priv->card_type >= NV_C0)
-			tile_mode >>= 4;
-		OUT_RING(evo, ((drm_fb->pitch / 4) << 4) | tile_mode);
-	}
-	if (dev_priv->chipset == 0x50)
-		OUT_RING(evo, (nv_crtc->fb.tile_flags << 8) | format);
-	else
-		OUT_RING(evo, format);
+	OUT_RING  (evo, nv_crtc->fb.offset >> 8);
+	OUT_RING  (evo, 0);
+	OUT_RING  (evo, (drm_fb->height << 16) | drm_fb->width);
+	OUT_RING  (evo, fb->r_pitch);
+	OUT_RING  (evo, fb->r_format);
 
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, CLUT_MODE), 1);
-	OUT_RING(evo, fb->base.depth == 8 ?
-		 NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
+	OUT_RING  (evo, fb->base.depth == 8 ?
+		   NV50_EVO_CRTC_CLUT_MODE_OFF : NV50_EVO_CRTC_CLUT_MODE_ON);
 
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, COLOR_CTRL), 1);
-	OUT_RING(evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
+	OUT_RING  (evo, NV50_EVO_CRTC_COLOR_CTRL_COLOR);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(nv_crtc->index, FB_POS), 1);
-	OUT_RING(evo, (y << 16) | x);
+	OUT_RING  (evo, (y << 16) | x);
 
 	if (nv_crtc->lut.depth != fb->base.depth) {
 		nv_crtc->lut.depth = fb->base.depth;
 		nv50_crtc_lut_load(crtc);
 	}
 
-	if (update) {
-		ret = RING_SPACE(evo, 2);
-		if (ret)
-			return ret;
-		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
-		OUT_RING(evo, 0);
-		FIRE_RING(evo);
-	}
-
 	return 0;
 }
 
@@ -619,8 +593,7 @@
 		   struct drm_framebuffer *old_fb)
 {
 	struct drm_device *dev = crtc->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
 	struct nouveau_connector *nv_connector = NULL;
 	uint32_t hsync_dur,  vsync_dur, hsync_start_to_end, vsync_start_to_end;
@@ -700,14 +673,25 @@
 	nv_crtc->set_dither(nv_crtc, nv_connector->use_dithering, false);
 	nv_crtc->set_scale(nv_crtc, nv_connector->scaling_mode, false);
 
-	return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false, false);
+	return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
 }
 
 static int
 nv50_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y,
 			struct drm_framebuffer *old_fb)
 {
-	return nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, true, false);
+	int ret;
+
+	nv50_display_flip_stop(crtc);
+	ret = nv50_crtc_do_mode_set_base(crtc, old_fb, x, y, false);
+	if (ret)
+		return ret;
+
+	ret = nv50_crtc_wait_complete(crtc);
+	if (ret)
+		return ret;
+
+	return nv50_display_flip_next(crtc, crtc->fb, NULL);
 }
 
 static int
@@ -715,7 +699,14 @@
 			       struct drm_framebuffer *fb,
 			       int x, int y, enum mode_set_atomic state)
 {
-	return nv50_crtc_do_mode_set_base(crtc, fb, x, y, true, true);
+	int ret;
+
+	nv50_display_flip_stop(crtc);
+	ret = nv50_crtc_do_mode_set_base(crtc, fb, x, y, true);
+	if (ret)
+		return ret;
+
+	return nv50_crtc_wait_complete(crtc);
 }
 
 static const struct drm_crtc_helper_funcs nv50_crtc_helper_funcs = {
@@ -758,7 +749,7 @@
 	nv_crtc->lut.depth = 0;
 
 	ret = nouveau_bo_new(dev, NULL, 4096, 0x100, TTM_PL_FLAG_VRAM,
-			     0, 0x0000, false, true, &nv_crtc->lut.nvbo);
+			     0, 0x0000, &nv_crtc->lut.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->lut.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
@@ -784,7 +775,7 @@
 	drm_mode_crtc_set_gamma_size(&nv_crtc->base, 256);
 
 	ret = nouveau_bo_new(dev, NULL, 64*64*4, 0x100, TTM_PL_FLAG_VRAM,
-			     0, 0x0000, false, true, &nv_crtc->cursor.nvbo);
+			     0, 0x0000, &nv_crtc->cursor.nvbo);
 	if (!ret) {
 		ret = nouveau_bo_pin(nv_crtc->cursor.nvbo, TTM_PL_FLAG_VRAM);
 		if (!ret)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_cursor.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,9 +36,9 @@
 static void
 nv50_cursor_show(struct nouveau_crtc *nv_crtc, bool update)
 {
-	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "\n");
@@ -71,9 +71,9 @@
 static void
 nv50_cursor_hide(struct nouveau_crtc *nv_crtc, bool update)
 {
-	struct drm_nouveau_private *dev_priv = nv_crtc->base.dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
 	struct drm_device *dev = nv_crtc->base.dev;
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	NV_DEBUG_KMS(dev, "\n");
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_dac.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_dac.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_dac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_dac.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,8 +41,7 @@
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	if (!nv_encoder->crtc)
@@ -216,8 +215,7 @@
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
 	uint32_t mode_ctl = 0, mode_ctl2 = 0;
 	int ret;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_display.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_display.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_display.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
  *
  */
 
+#define NOUVEAU_DMA_DEBUG (nouveau_reg_debug & NOUVEAU_REG_DEBUG_EVO)
 #include "nv50_display.h"
 #include "nouveau_crtc.h"
 #include "nouveau_encoder.h"
@@ -34,6 +35,7 @@
 #include "drm_crtc_helper.h"
 
 static void nv50_display_isr(struct drm_device *);
+static void nv50_display_bh(unsigned long);
 
 static inline int
 nv50_sor_nr(struct drm_device *dev)
@@ -172,16 +174,16 @@
 	ret = nv50_evo_init(dev);
 	if (ret)
 		return ret;
-	evo = dev_priv->evo;
+	evo = nv50_display(dev)->master;
 
 	nv_wr32(dev, NV50_PDISPLAY_OBJECTS, (evo->ramin->vinst >> 8) | 9);
 
-	ret = RING_SPACE(evo, 11);
+	ret = RING_SPACE(evo, 15);
 	if (ret)
 		return ret;
 	BEGIN_RING(evo, 0, NV50_EVO_UNK84, 2);
 	OUT_RING(evo, NV50_EVO_UNK84_NOTIFY_DISABLED);
-	OUT_RING(evo, NV50_EVO_DMA_NOTIFY_HANDLE_NONE);
+	OUT_RING(evo, NvEvoSync);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, FB_DMA), 1);
 	OUT_RING(evo, NV50_EVO_CRTC_FB_DMA_HANDLE_NONE);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK0800), 1);
@@ -190,6 +192,11 @@
 	OUT_RING(evo, 0);
 	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK082C), 1);
 	OUT_RING(evo, 0);
+	/* required to make display sync channels not hate life */
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(0, UNK900), 1);
+	OUT_RING  (evo, 0x00000311);
+	BEGIN_RING(evo, 0, NV50_EVO_CRTC(1, UNK900), 1);
+	OUT_RING  (evo, 0x00000311);
 	FIRE_RING(evo);
 	if (!nv_wait(dev, 0x640004, 0xffffffff, evo->dma.put << 2))
 		NV_ERROR(dev, "evo pushbuf stalled\n");
@@ -201,6 +208,8 @@
 static int nv50_display_disable(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
+	struct nouveau_channel *evo = disp->master;
 	struct drm_crtc *drm_crtc;
 	int ret, i;
 
@@ -212,12 +221,12 @@
 		nv50_crtc_blank(crtc, true);
 	}
 
-	ret = RING_SPACE(dev_priv->evo, 2);
+	ret = RING_SPACE(evo, 2);
 	if (ret == 0) {
-		BEGIN_RING(dev_priv->evo, 0, NV50_EVO_UPDATE, 1);
-		OUT_RING(dev_priv->evo, 0);
+		BEGIN_RING(evo, 0, NV50_EVO_UPDATE, 1);
+		OUT_RING(evo, 0);
 	}
-	FIRE_RING(dev_priv->evo);
+	FIRE_RING(evo);
 
 	/* Almost like ack'ing a vblank interrupt, maybe in the spirit of
 	 * cleaning up?
@@ -267,10 +276,16 @@
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct dcb_table *dcb = &dev_priv->vbios.dcb;
 	struct drm_connector *connector, *ct;
+	struct nv50_display *priv;
 	int ret, i;
 
 	NV_DEBUG_KMS(dev, "\n");
 
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv)
+		return -ENOMEM;
+	dev_priv->engine.display.priv = priv;
+
 	/* init basic kernel modesetting */
 	drm_mode_config_init(dev);
 
@@ -330,7 +345,7 @@
 		}
 	}
 
-	INIT_WORK(&dev_priv->irq_work, nv50_display_irq_handler_bh);
+	tasklet_init(&priv->tasklet, nv50_display_bh, (unsigned long)dev);
 	nouveau_irq_register(dev, 26, nv50_display_isr);
 
 	ret = nv50_display_init(dev);
@@ -345,12 +360,131 @@
 void
 nv50_display_destroy(struct drm_device *dev)
 {
+	struct nv50_display *disp = nv50_display(dev);
+
 	NV_DEBUG_KMS(dev, "\n");
 
 	drm_mode_config_cleanup(dev);
 
 	nv50_display_disable(dev);
 	nouveau_irq_unregister(dev, 26);
+	kfree(disp);
+}
+
+void
+nv50_display_flip_stop(struct drm_crtc *crtc)
+{
+	struct nv50_display *disp = nv50_display(crtc->dev);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index];
+	struct nouveau_channel *evo = dispc->sync;
+	int ret;
+
+	ret = RING_SPACE(evo, 8);
+	if (ret) {
+		WARN_ON(1);
+		return;
+	}
+
+	BEGIN_RING(evo, 0, 0x0084, 1);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x0094, 1);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x00c0, 1);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x0080, 1);
+	OUT_RING  (evo, 0x00000000);
+	FIRE_RING (evo);
+}
+
+int
+nv50_display_flip_next(struct drm_crtc *crtc, struct drm_framebuffer *fb,
+		       struct nouveau_channel *chan)
+{
+	struct drm_nouveau_private *dev_priv = crtc->dev->dev_private;
+	struct nouveau_framebuffer *nv_fb = nouveau_framebuffer(fb);
+	struct nv50_display *disp = nv50_display(crtc->dev);
+	struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
+	struct nv50_display_crtc *dispc = &disp->crtc[nv_crtc->index];
+	struct nouveau_channel *evo = dispc->sync;
+	int ret;
+
+	ret = RING_SPACE(evo, 24);
+	if (unlikely(ret))
+		return ret;
+
+	/* synchronise with the rendering channel, if necessary */
+	if (likely(chan)) {
+		u64 offset = dispc->sem.bo->vma.offset + dispc->sem.offset;
+
+		ret = RING_SPACE(chan, 10);
+		if (ret) {
+			WIND_RING(evo);
+			return ret;
+		}
+
+		if (dev_priv->chipset < 0xc0) {
+			BEGIN_RING(chan, NvSubSw, 0x0060, 2);
+			OUT_RING  (chan, NvEvoSema0 + nv_crtc->index);
+			OUT_RING  (chan, dispc->sem.offset);
+			BEGIN_RING(chan, NvSubSw, 0x006c, 1);
+			OUT_RING  (chan, 0xf00d0000 | dispc->sem.value);
+			BEGIN_RING(chan, NvSubSw, 0x0064, 2);
+			OUT_RING  (chan, dispc->sem.offset ^ 0x10);
+			OUT_RING  (chan, 0x74b1e000);
+			BEGIN_RING(chan, NvSubSw, 0x0060, 1);
+			if (dev_priv->chipset < 0x84)
+				OUT_RING  (chan, NvSema);
+			else
+				OUT_RING  (chan, chan->vram_handle);
+		} else {
+			BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+			OUT_RING  (chan, upper_32_bits(offset));
+			OUT_RING  (chan, lower_32_bits(offset));
+			OUT_RING  (chan, 0xf00d0000 | dispc->sem.value);
+			OUT_RING  (chan, 0x1002);
+			BEGIN_NVC0(chan, 2, NvSubM2MF, 0x0010, 4);
+			OUT_RING  (chan, upper_32_bits(offset));
+			OUT_RING  (chan, lower_32_bits(offset ^ 0x10));
+			OUT_RING  (chan, 0x74b1e000);
+			OUT_RING  (chan, 0x1001);
+		}
+		FIRE_RING (chan);
+	} else {
+		nouveau_bo_wr32(dispc->sem.bo, dispc->sem.offset / 4,
+				0xf00d0000 | dispc->sem.value);
+	}
+
+	/* queue the flip on the crtc's "display sync" channel */
+	BEGIN_RING(evo, 0, 0x0100, 1);
+	OUT_RING  (evo, 0xfffe0000);
+	BEGIN_RING(evo, 0, 0x0084, 5);
+	OUT_RING  (evo, chan ? 0x00000100 : 0x00000010);
+	OUT_RING  (evo, dispc->sem.offset);
+	OUT_RING  (evo, 0xf00d0000 | dispc->sem.value);
+	OUT_RING  (evo, 0x74b1e000);
+	OUT_RING  (evo, NvEvoSync);
+	BEGIN_RING(evo, 0, 0x00a0, 2);
+	OUT_RING  (evo, 0x00000000);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x00c0, 1);
+	OUT_RING  (evo, nv_fb->r_dma);
+	BEGIN_RING(evo, 0, 0x0110, 2);
+	OUT_RING  (evo, 0x00000000);
+	OUT_RING  (evo, 0x00000000);
+	BEGIN_RING(evo, 0, 0x0800, 5);
+	OUT_RING  (evo, (nv_fb->nvbo->bo.mem.start << PAGE_SHIFT) >> 8);
+	OUT_RING  (evo, 0);
+	OUT_RING  (evo, (fb->height << 16) | fb->width);
+	OUT_RING  (evo, nv_fb->r_pitch);
+	OUT_RING  (evo, nv_fb->r_format);
+	BEGIN_RING(evo, 0, 0x0080, 1);
+	OUT_RING  (evo, 0x00000000);
+	FIRE_RING (evo);
+
+	dispc->sem.offset ^= 0x10;
+	dispc->sem.value++;
+	return 0;
 }
 
 static u16
@@ -466,11 +600,12 @@
 nv50_display_unk10_handler(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	u32 unk30 = nv_rd32(dev, 0x610030), mc;
 	int i, crtc, or, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
-	dev_priv->evo_irq.dcb = NULL;
+	disp->irq.dcb = NULL;
 
 	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) & ~8);
 
@@ -541,7 +676,7 @@
 
 		if (dcb->type == type && (dcb->or & (1 << or))) {
 			nouveau_bios_run_display_table(dev, dcb, 0, -1);
-			dev_priv->evo_irq.dcb = dcb;
+			disp->irq.dcb = dcb;
 			goto ack;
 		}
 	}
@@ -587,15 +722,16 @@
 nv50_display_unk20_handler(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc;
+	struct nv50_display *disp = nv50_display(dev);
+	u32 unk30 = nv_rd32(dev, 0x610030), tmp, pclk, script, mc = 0;
 	struct dcb_entry *dcb;
 	int i, crtc, or, type = OUTPUT_ANY;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
-	dcb = dev_priv->evo_irq.dcb;
+	dcb = disp->irq.dcb;
 	if (dcb) {
 		nouveau_bios_run_display_table(dev, dcb, 0, -2);
-		dev_priv->evo_irq.dcb = NULL;
+		disp->irq.dcb = NULL;
 	}
 
 	/* CRTC clock change requested? */
@@ -692,9 +828,9 @@
 		nv_wr32(dev, NV50_PDISPLAY_DAC_CLK_CTRL2(or), 0);
 	}
 
-	dev_priv->evo_irq.dcb = dcb;
-	dev_priv->evo_irq.pclk = pclk;
-	dev_priv->evo_irq.script = script;
+	disp->irq.dcb = dcb;
+	disp->irq.pclk = pclk;
+	disp->irq.script = script;
 
 ack:
 	nv_wr32(dev, NV50_PDISPLAY_INTR_1, NV50_PDISPLAY_INTR_1_CLK_UNK20);
@@ -735,13 +871,13 @@
 static void
 nv50_display_unk40_handler(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct dcb_entry *dcb = dev_priv->evo_irq.dcb;
-	u16 script = dev_priv->evo_irq.script;
-	u32 unk30 = nv_rd32(dev, 0x610030), pclk = dev_priv->evo_irq.pclk;
+	struct nv50_display *disp = nv50_display(dev);
+	struct dcb_entry *dcb = disp->irq.dcb;
+	u16 script = disp->irq.script;
+	u32 unk30 = nv_rd32(dev, 0x610030), pclk = disp->irq.pclk;
 
 	NV_DEBUG_KMS(dev, "0x610030: 0x%08x\n", unk30);
-	dev_priv->evo_irq.dcb = NULL;
+	disp->irq.dcb = NULL;
 	if (!dcb)
 		goto ack;
 
@@ -754,12 +890,10 @@
 	nv_wr32(dev, 0x619494, nv_rd32(dev, 0x619494) | 8);
 }
 
-void
-nv50_display_irq_handler_bh(struct work_struct *work)
+static void
+nv50_display_bh(unsigned long data)
 {
-	struct drm_nouveau_private *dev_priv =
-		container_of(work, struct drm_nouveau_private, irq_work);
-	struct drm_device *dev = dev_priv->dev;
+	struct drm_device *dev = (struct drm_device *)data;
 
 	for (;;) {
 		uint32_t intr0 = nv_rd32(dev, NV50_PDISPLAY_INTR_0);
@@ -807,7 +941,7 @@
 static void
 nv50_display_isr(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	uint32_t delayed = 0;
 
 	while (nv_rd32(dev, NV50_PMC_INTR_0) & NV50_PMC_INTR_0_DISPLAY) {
@@ -835,8 +969,7 @@
 				  NV50_PDISPLAY_INTR_1_CLK_UNK40));
 		if (clock) {
 			nv_wr32(dev, NV03_PMC_INTR_EN_0, 0);
-			if (!work_pending(&dev_priv->irq_work))
-				queue_work(dev_priv->wq, &dev_priv->irq_work);
+			tasklet_schedule(&disp->tasklet);
 			delayed |= clock;
 			intr1 &= ~clock;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_display.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_display.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_display.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_display.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,36 @@
 #include "nouveau_crtc.h"
 #include "nv50_evo.h"
 
-void nv50_display_irq_handler_bh(struct work_struct *work);
+struct nv50_display_crtc {
+	struct nouveau_channel *sync;
+	struct {
+		struct nouveau_bo *bo;
+		u32 offset;
+		u16 value;
+	} sem;
+};
+
+struct nv50_display {
+	struct nouveau_channel *master;
+	struct nouveau_gpuobj *ntfy;
+
+	struct nv50_display_crtc crtc[2];
+
+	struct tasklet_struct tasklet;
+	struct {
+		struct dcb_entry *dcb;
+		u16 script;
+		u32 pclk;
+	} irq;
+};
+
+static inline struct nv50_display *
+nv50_display(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	return dev_priv->engine.display.priv;
+}
+
 int nv50_display_early_init(struct drm_device *dev);
 void nv50_display_late_takedown(struct drm_device *dev);
 int nv50_display_create(struct drm_device *dev);
@@ -44,4 +73,15 @@
 int nv50_crtc_blank(struct nouveau_crtc *, bool blank);
 int nv50_crtc_set_clock(struct drm_device *, int head, int pclk);
 
+int  nv50_display_flip_next(struct drm_crtc *, struct drm_framebuffer *,
+			    struct nouveau_channel *chan);
+void nv50_display_flip_stop(struct drm_crtc *);
+
+int  nv50_evo_init(struct drm_device *dev);
+void nv50_evo_fini(struct drm_device *dev);
+void nv50_evo_dmaobj_init(struct nouveau_gpuobj *, u32 memtype, u64 base,
+			  u64 size);
+int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 handle, u32 memtype,
+			 u64 base, u64 size, struct nouveau_gpuobj **);
+
 #endif /* __NV50_DISPLAY_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_evo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_evo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_evo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_evo.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,20 +27,17 @@
 #include "nouveau_drv.h"
 #include "nouveau_dma.h"
 #include "nouveau_ramht.h"
+#include "nv50_display.h"
 
 static void
 nv50_evo_channel_del(struct nouveau_channel **pevo)
 {
-	struct drm_nouveau_private *dev_priv;
 	struct nouveau_channel *evo = *pevo;
 
 	if (!evo)
 		return;
 	*pevo = NULL;
 
-	dev_priv = evo->dev->dev_private;
-	dev_priv->evo_alloc &= ~(1 << evo->id);
-
 	nouveau_gpuobj_channel_takedown(evo);
 	nouveau_bo_unmap(evo->pushbuf_bo);
 	nouveau_bo_ref(NULL, &evo->pushbuf_bo);
@@ -51,42 +48,61 @@
 	kfree(evo);
 }
 
+void
+nv50_evo_dmaobj_init(struct nouveau_gpuobj *obj, u32 memtype, u64 base, u64 size)
+{
+	struct drm_nouveau_private *dev_priv = obj->dev->dev_private;
+	u32 flags5;
+
+	if (dev_priv->chipset < 0xc0) {
+		/* not supported on 0x50, specified in format mthd */
+		if (dev_priv->chipset == 0x50)
+			memtype = 0;
+		flags5 = 0x00010000;
+	} else {
+		if (memtype & 0x80000000)
+			flags5 = 0x00000000; /* large pages */
+		else
+			flags5 = 0x00020000;
+	}
+
+	nv50_gpuobj_dma_init(obj, 0, 0x3d, base, size, NV_MEM_TARGET_VRAM,
+			     NV_MEM_ACCESS_RW, (memtype >> 8) & 0xff, 0);
+	nv_wo32(obj, 0x14, flags5);
+	dev_priv->engine.instmem.flush(obj->dev);
+}
+
 int
-nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 class, u32 name,
-		    u32 tile_flags, u32 magic_flags, u32 offset, u32 limit,
-		    u32 flags5)
+nv50_evo_dmaobj_new(struct nouveau_channel *evo, u32 handle, u32 memtype,
+		    u64 base, u64 size, struct nouveau_gpuobj **pobj)
 {
-	struct drm_nouveau_private *dev_priv = evo->dev->dev_private;
-	struct drm_device *dev = evo->dev;
+	struct nv50_display *disp = nv50_display(evo->dev);
 	struct nouveau_gpuobj *obj = NULL;
 	int ret;
 
-	ret = nouveau_gpuobj_new(dev, dev_priv->evo, 6*4, 32, 0, &obj);
+	ret = nouveau_gpuobj_new(evo->dev, disp->master, 6*4, 32, 0, &obj);
 	if (ret)
 		return ret;
 	obj->engine = NVOBJ_ENGINE_DISPLAY;
 
-	nv_wo32(obj,  0, (tile_flags << 22) | (magic_flags << 16) | class);
-	nv_wo32(obj,  4, limit);
-	nv_wo32(obj,  8, offset);
-	nv_wo32(obj, 12, 0x00000000);
-	nv_wo32(obj, 16, 0x00000000);
-	nv_wo32(obj, 20, flags5);
-	dev_priv->engine.instmem.flush(dev);
+	nv50_evo_dmaobj_init(obj, memtype, base, size);
 
-	ret = nouveau_ramht_insert(evo, name, obj);
-	nouveau_gpuobj_ref(NULL, &obj);
-	if (ret) {
-		return ret;
-	}
+	ret = nouveau_ramht_insert(evo, handle, obj);
+	if (ret)
+		goto out;
 
-	return 0;
+	if (pobj)
+		nouveau_gpuobj_ref(obj, pobj);
+out:
+	nouveau_gpuobj_ref(NULL, &obj);
+	return ret;
 }
 
 static int
-nv50_evo_channel_new(struct drm_device *dev, struct nouveau_channel **pevo)
+nv50_evo_channel_new(struct drm_device *dev, int chid,
+		     struct nouveau_channel **pevo)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	struct nouveau_channel *evo;
 	int ret;
 
@@ -95,25 +111,13 @@
 		return -ENOMEM;
 	*pevo = evo;
 
-	for (evo->id = 0; evo->id < 5; evo->id++) {
-		if (dev_priv->evo_alloc & (1 << evo->id))
-			continue;
-
-		dev_priv->evo_alloc |= (1 << evo->id);
-		break;
-	}
-
-	if (evo->id == 5) {
-		kfree(evo);
-		return -ENODEV;
-	}
-
+	evo->id = chid;
 	evo->dev = dev;
 	evo->user_get = 4;
 	evo->user_put = 0;
 
 	ret = nouveau_bo_new(dev, NULL, 4096, 0, TTM_PL_FLAG_VRAM, 0, 0,
-			     false, true, &evo->pushbuf_bo);
+			     &evo->pushbuf_bo);
 	if (ret == 0)
 		ret = nouveau_bo_pin(evo->pushbuf_bo, TTM_PL_FLAG_VRAM);
 	if (ret) {
@@ -138,8 +142,8 @@
 	}
 
 	/* bind primary evo channel's ramht to the channel */
-	if (dev_priv->evo && evo != dev_priv->evo)
-		nouveau_ramht_ref(dev_priv->evo->ramht, &evo->ramht, NULL);
+	if (disp->master && evo != disp->master)
+		nouveau_ramht_ref(disp->master->ramht, &evo->ramht, NULL);
 
 	return 0;
 }
@@ -182,6 +186,7 @@
 	nv_mask(dev, 0x610028, 0x00000000, 0x00010001 << id);
 
 	evo->dma.max = (4096/4) - 2;
+	evo->dma.max &= ~7;
 	evo->dma.put = 0;
 	evo->dma.cur = evo->dma.put;
 	evo->dma.free = evo->dma.max - evo->dma.cur;
@@ -212,21 +217,39 @@
 	}
 }
 
+static void
+nv50_evo_destroy(struct drm_device *dev)
+{
+	struct nv50_display *disp = nv50_display(dev);
+	int i;
+
+	for (i = 0; i < 2; i++) {
+		if (disp->crtc[i].sem.bo) {
+			nouveau_bo_unmap(disp->crtc[i].sem.bo);
+			nouveau_bo_ref(NULL, &disp->crtc[i].sem.bo);
+		}
+		nv50_evo_channel_del(&disp->crtc[i].sync);
+	}
+	nouveau_gpuobj_ref(NULL, &disp->ntfy);
+	nv50_evo_channel_del(&disp->master);
+}
+
 static int
 nv50_evo_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
 	struct nouveau_gpuobj *ramht = NULL;
 	struct nouveau_channel *evo;
-	int ret;
+	int ret, i, j;
 
 	/* create primary evo channel, the one we use for modesetting
 	 * purporses
 	 */
-	ret = nv50_evo_channel_new(dev, &dev_priv->evo);
+	ret = nv50_evo_channel_new(dev, 0, &disp->master);
 	if (ret)
 		return ret;
-	evo = dev_priv->evo;
+	evo = disp->master;
 
 	/* setup object management on it, any other evo channel will
 	 * use this also as there's no per-channel support on the
@@ -236,109 +259,167 @@
 				 NVOBJ_FLAG_ZERO_ALLOC, &evo->ramin);
 	if (ret) {
 		NV_ERROR(dev, "Error allocating EVO channel memory: %d\n", ret);
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
+		goto err;
 	}
 
 	ret = drm_mm_init(&evo->ramin_heap, 0, 32768);
 	if (ret) {
 		NV_ERROR(dev, "Error initialising EVO PRAMIN heap: %d\n", ret);
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
+		goto err;
 	}
 
 	ret = nouveau_gpuobj_new(dev, evo, 4096, 16, 0, &ramht);
 	if (ret) {
 		NV_ERROR(dev, "Unable to allocate EVO RAMHT: %d\n", ret);
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
+		goto err;
 	}
 
 	ret = nouveau_ramht_new(dev, ramht, &evo->ramht);
 	nouveau_gpuobj_ref(NULL, &ramht);
-	if (ret) {
-		nv50_evo_channel_del(&dev_priv->evo);
-		return ret;
-	}
+	if (ret)
+		goto err;
+
+	/* not sure exactly what this is..
+	 *
+	 * the first dword of the structure is used by nvidia to wait on
+	 * full completion of an EVO "update" command.
+	 *
+	 * method 0x8c on the master evo channel will fill a lot more of
+	 * this structure with some undefined info
+	 */
+	ret = nouveau_gpuobj_new(dev, disp->master, 0x1000, 0,
+				 NVOBJ_FLAG_ZERO_ALLOC, &disp->ntfy);
+	if (ret)
+		goto err;
+
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoSync, 0x0000,
+				  disp->ntfy->vinst, disp->ntfy->size, NULL);
+	if (ret)
+		goto err;
 
 	/* create some default objects for the scanout memtypes we support */
-	if (dev_priv->card_type >= NV_C0) {
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0xfe, 0x19,
-					  0, 0xffffffff, 0x00000000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM, 0x0000,
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00020000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoVRAM_LP, 0x80000000,
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00000000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
-	} else {
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB16, 0x70, 0x19,
-					  0, 0xffffffff, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB32, 0x80000000 |
+				  (dev_priv->chipset < 0xc0 ? 0x7a00 : 0xfe00),
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
+	ret = nv50_evo_dmaobj_new(disp->master, NvEvoFB16, 0x80000000 |
+				  (dev_priv->chipset < 0xc0 ? 0x7000 : 0xfe00),
+				  0, dev_priv->vram_size, NULL);
+	if (ret)
+		goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoFB32, 0x7a, 0x19,
-					  0, 0xffffffff, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+	/* create "display sync" channels and other structures we need
+	 * to implement page flipping
+	 */
+	for (i = 0; i < 2; i++) {
+		struct nv50_display_crtc *dispc = &disp->crtc[i];
+		u64 offset;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
-		}
+		ret = nv50_evo_channel_new(dev, 1 + i, &dispc->sync);
+		if (ret)
+			goto err;
 
-		ret = nv50_evo_dmaobj_new(evo, 0x3d, NvEvoVRAM_LP, 0, 0x19,
-					  0, dev_priv->vram_size, 0x00010000);
-		if (ret) {
-			nv50_evo_channel_del(&dev_priv->evo);
-			return ret;
+		ret = nouveau_bo_new(dev, NULL, 4096, 0x1000, TTM_PL_FLAG_VRAM,
+				     0, 0x0000, &dispc->sem.bo);
+		if (!ret) {
+			offset = dispc->sem.bo->bo.mem.start << PAGE_SHIFT;
+
+			ret = nouveau_bo_pin(dispc->sem.bo, TTM_PL_FLAG_VRAM);
+			if (!ret)
+				ret = nouveau_bo_map(dispc->sem.bo);
+			if (ret)
+				nouveau_bo_ref(NULL, &dispc->sem.bo);
 		}
+
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoSync, 0x0000,
+					  offset, 4096, NULL);
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoVRAM_LP, 0x80000000,
+					  0, dev_priv->vram_size, NULL);
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB32, 0x80000000 |
+					  (dev_priv->chipset < 0xc0 ?
+					  0x7a00 : 0xfe00),
+					  0, dev_priv->vram_size, NULL);
+		if (ret)
+			goto err;
+
+		ret = nv50_evo_dmaobj_new(dispc->sync, NvEvoFB16, 0x80000000 |
+					  (dev_priv->chipset < 0xc0 ?
+					  0x7000 : 0xfe00),
+					  0, dev_priv->vram_size, NULL);
+		if (ret)
+			goto err;
+
+		for (j = 0; j < 4096; j += 4)
+			nouveau_bo_wr32(dispc->sem.bo, j / 4, 0x74b1e000);
+		dispc->sem.offset = 0;
 	}
 
 	return 0;
+
+err:
+	nv50_evo_destroy(dev);
+	return ret;
 }
 
 int
 nv50_evo_init(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	int ret;
+	struct nv50_display *disp = nv50_display(dev);
+	int ret, i;
 
-	if (!dev_priv->evo) {
+	if (!disp->master) {
 		ret = nv50_evo_create(dev);
 		if (ret)
 			return ret;
 	}
 
-	return nv50_evo_channel_init(dev_priv->evo);
+	ret = nv50_evo_channel_init(disp->master);
+	if (ret)
+		return ret;
+
+	for (i = 0; i < 2; i++) {
+		ret = nv50_evo_channel_init(disp->crtc[i].sync);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
 }
 
 void
 nv50_evo_fini(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nv50_display *disp = nv50_display(dev);
+	int i;
 
-	if (dev_priv->evo) {
-		nv50_evo_channel_fini(dev_priv->evo);
-		nv50_evo_channel_del(&dev_priv->evo);
+	for (i = 0; i < 2; i++) {
+		if (disp->crtc[i].sync)
+			nv50_evo_channel_fini(disp->crtc[i].sync);
 	}
+
+	if (disp->master)
+		nv50_evo_channel_fini(disp->master);
+
+	nv50_evo_destroy(dev);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_evo.h linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_evo.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_evo.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_evo.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,12 +27,6 @@
 #ifndef __NV50_EVO_H__
 #define __NV50_EVO_H__
 
-int  nv50_evo_init(struct drm_device *dev);
-void nv50_evo_fini(struct drm_device *dev);
-int  nv50_evo_dmaobj_new(struct nouveau_channel *, u32 class, u32 name,
-			 u32 tile_flags, u32 magic_flags,
-			 u32 offset, u32 limit);
-
 #define NV50_EVO_UPDATE                                              0x00000080
 #define NV50_EVO_UNK84                                               0x00000084
 #define NV50_EVO_UNK84_NOTIFY                                        0x40000000
@@ -119,5 +113,7 @@
 /* Both of these are needed, otherwise nothing happens. */
 #define NV50_EVO_CRTC_SCALE_RES1                                     0x000008d8
 #define NV50_EVO_CRTC_SCALE_RES2                                     0x000008dc
+#define NV50_EVO_CRTC_UNK900                                         0x00000900
+#define NV50_EVO_CRTC_UNK904                                         0x00000904
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_fb.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_fb.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_fb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_fb.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,31 +8,61 @@
 	dma_addr_t r100c08;
 };
 
+static void
+nv50_fb_destroy(struct drm_device *dev)
+{
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+	struct nv50_fb_priv *priv = pfb->priv;
+
+	if (drm_mm_initialized(&pfb->tag_heap))
+		drm_mm_takedown(&pfb->tag_heap);
+
+	if (priv->r100c08_page) {
+		pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
+			       PCI_DMA_BIDIRECTIONAL);
+		__free_page(priv->r100c08_page);
+	}
+
+	kfree(priv);
+	pfb->priv = NULL;
+}
+
 static int
 nv50_fb_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
 	struct nv50_fb_priv *priv;
+	u32 tagmem;
+	int ret;
 
 	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 	if (!priv)
 		return -ENOMEM;
+	pfb->priv = priv;
 
 	priv->r100c08_page = alloc_page(GFP_KERNEL | __GFP_ZERO);
 	if (!priv->r100c08_page) {
-		kfree(priv);
+		nv50_fb_destroy(dev);
 		return -ENOMEM;
 	}
 
 	priv->r100c08 = pci_map_page(dev->pdev, priv->r100c08_page, 0,
 				     PAGE_SIZE, PCI_DMA_BIDIRECTIONAL);
 	if (pci_dma_mapping_error(dev->pdev, priv->r100c08)) {
-		__free_page(priv->r100c08_page);
-		kfree(priv);
+		nv50_fb_destroy(dev);
 		return -EFAULT;
 	}
 
-	dev_priv->engine.fb.priv = priv;
+	tagmem = nv_rd32(dev, 0x100320);
+	NV_DEBUG(dev, "%d tags available\n", tagmem);
+	ret = drm_mm_init(&pfb->tag_heap, 0, tagmem);
+	if (ret) {
+		nv50_fb_destroy(dev);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -81,26 +111,112 @@
 void
 nv50_fb_takedown(struct drm_device *dev)
 {
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nv50_fb_priv *priv;
+	nv50_fb_destroy(dev);
+}
 
-	priv = dev_priv->engine.fb.priv;
-	if (!priv)
-		return;
-	dev_priv->engine.fb.priv = NULL;
+static struct nouveau_enum vm_dispatch_subclients[] = {
+	{ 0x00000000, "GRCTX", NULL },
+	{ 0x00000001, "NOTIFY", NULL },
+	{ 0x00000002, "QUERY", NULL },
+	{ 0x00000003, "COND", NULL },
+	{ 0x00000004, "M2M_IN", NULL },
+	{ 0x00000005, "M2M_OUT", NULL },
+	{ 0x00000006, "M2M_NOTIFY", NULL },
+	{}
+};
 
-	pci_unmap_page(dev->pdev, priv->r100c08, PAGE_SIZE,
-		       PCI_DMA_BIDIRECTIONAL);
-	__free_page(priv->r100c08_page);
-	kfree(priv);
-}
+static struct nouveau_enum vm_ccache_subclients[] = {
+	{ 0x00000000, "CB", NULL },
+	{ 0x00000001, "TIC", NULL },
+	{ 0x00000002, "TSC", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_prop_subclients[] = {
+	{ 0x00000000, "RT0", NULL },
+	{ 0x00000001, "RT1", NULL },
+	{ 0x00000002, "RT2", NULL },
+	{ 0x00000003, "RT3", NULL },
+	{ 0x00000004, "RT4", NULL },
+	{ 0x00000005, "RT5", NULL },
+	{ 0x00000006, "RT6", NULL },
+	{ 0x00000007, "RT7", NULL },
+	{ 0x00000008, "ZETA", NULL },
+	{ 0x00000009, "LOCAL", NULL },
+	{ 0x0000000a, "GLOBAL", NULL },
+	{ 0x0000000b, "STACK", NULL },
+	{ 0x0000000c, "DST2D", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_pfifo_subclients[] = {
+	{ 0x00000000, "PUSHBUF", NULL },
+	{ 0x00000001, "SEMAPHORE", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_bar_subclients[] = {
+	{ 0x00000000, "FB", NULL },
+	{ 0x00000001, "IN", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_client[] = {
+	{ 0x00000000, "STRMOUT", NULL },
+	{ 0x00000003, "DISPATCH", vm_dispatch_subclients },
+	{ 0x00000004, "PFIFO_WRITE", NULL },
+	{ 0x00000005, "CCACHE", vm_ccache_subclients },
+	{ 0x00000006, "PPPP", NULL },
+	{ 0x00000007, "CLIPID", NULL },
+	{ 0x00000008, "PFIFO_READ", NULL },
+	{ 0x00000009, "VFETCH", NULL },
+	{ 0x0000000a, "TEXTURE", NULL },
+	{ 0x0000000b, "PROP", vm_prop_subclients },
+	{ 0x0000000c, "PVP", NULL },
+	{ 0x0000000d, "PBSP", NULL },
+	{ 0x0000000e, "PCRYPT", NULL },
+	{ 0x0000000f, "PCOUNTER", NULL },
+	{ 0x00000011, "PDAEMON", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_engine[] = {
+	{ 0x00000000, "PGRAPH", NULL },
+	{ 0x00000001, "PVP", NULL },
+	{ 0x00000004, "PEEPHOLE", NULL },
+	{ 0x00000005, "PFIFO", vm_pfifo_subclients },
+	{ 0x00000006, "BAR", vm_bar_subclients },
+	{ 0x00000008, "PPPP", NULL },
+	{ 0x00000009, "PBSP", NULL },
+	{ 0x0000000a, "PCRYPT", NULL },
+	{ 0x0000000b, "PCOUNTER", NULL },
+	{ 0x0000000c, "SEMAPHORE_BG", NULL },
+	{ 0x0000000d, "PCOPY", NULL },
+	{ 0x0000000e, "PDAEMON", NULL },
+	{}
+};
+
+static struct nouveau_enum vm_fault[] = {
+	{ 0x00000000, "PT_NOT_PRESENT", NULL },
+	{ 0x00000001, "PT_TOO_SHORT", NULL },
+	{ 0x00000002, "PAGE_NOT_PRESENT", NULL },
+	{ 0x00000003, "PAGE_SYSTEM_ONLY", NULL },
+	{ 0x00000004, "PAGE_READ_ONLY", NULL },
+	{ 0x00000006, "NULL_DMAOBJ", NULL },
+	{ 0x00000007, "WRONG_MEMTYPE", NULL },
+	{ 0x0000000b, "VRAM_LIMIT", NULL },
+	{ 0x0000000f, "DMAOBJ_LIMIT", NULL },
+	{}
+};
 
 void
-nv50_fb_vm_trap(struct drm_device *dev, int display, const char *name)
+nv50_fb_vm_trap(struct drm_device *dev, int display)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	const struct nouveau_enum *en, *cl;
 	unsigned long flags;
 	u32 trap[6], idx, chinst;
+	u8 st0, st1, st2, st3;
 	int i, ch;
 
 	idx = nv_rd32(dev, 0x100c90);
@@ -117,8 +233,8 @@
 	if (!display)
 		return;
 
+	/* lookup channel id */
 	chinst = (trap[2] << 16) | trap[1];
-
 	spin_lock_irqsave(&dev_priv->channels.lock, flags);
 	for (ch = 0; ch < dev_priv->engine.fifo.channels; ch++) {
 		struct nouveau_channel *chan = dev_priv->channels.ptr[ch];
@@ -131,9 +247,48 @@
 	}
 	spin_unlock_irqrestore(&dev_priv->channels.lock, flags);
 
-	NV_INFO(dev, "%s - VM: Trapped %s at %02x%04x%04x status %08x "
-		     "channel %d (0x%08x)\n",
-		name, (trap[5] & 0x100 ? "read" : "write"),
-		trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff,
-		trap[0], ch, chinst);
+	/* decode status bits into something more useful */
+	if (dev_priv->chipset  < 0xa3 ||
+	    dev_priv->chipset == 0xaa || dev_priv->chipset == 0xac) {
+		st0 = (trap[0] & 0x0000000f) >> 0;
+		st1 = (trap[0] & 0x000000f0) >> 4;
+		st2 = (trap[0] & 0x00000f00) >> 8;
+		st3 = (trap[0] & 0x0000f000) >> 12;
+	} else {
+		st0 = (trap[0] & 0x000000ff) >> 0;
+		st1 = (trap[0] & 0x0000ff00) >> 8;
+		st2 = (trap[0] & 0x00ff0000) >> 16;
+		st3 = (trap[0] & 0xff000000) >> 24;
+	}
+
+	NV_INFO(dev, "VM: trapped %s at 0x%02x%04x%04x on ch %d [0x%08x] ",
+		(trap[5] & 0x00000100) ? "read" : "write",
+		trap[5] & 0xff, trap[4] & 0xffff, trap[3] & 0xffff, ch, chinst);
+
+	en = nouveau_enum_find(vm_engine, st0);
+	if (en)
+		printk("%s/", en->name);
+	else
+		printk("%02x/", st0);
+
+	cl = nouveau_enum_find(vm_client, st2);
+	if (cl)
+		printk("%s/", cl->name);
+	else
+		printk("%02x/", st2);
+
+	if      (cl && cl->data) cl = nouveau_enum_find(cl->data, st3);
+	else if (en && en->data) cl = nouveau_enum_find(en->data, st3);
+	else                     cl = NULL;
+	if (cl)
+		printk("%s", cl->name);
+	else
+		printk("%02x", st3);
+
+	printk(" reason: ");
+	en = nouveau_enum_find(vm_fault, st1);
+	if (en)
+		printk("%s\n", en->name);
+	else
+		printk("0x%08x\n", st1);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_fifo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_fifo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_fifo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_fifo.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,6 +149,7 @@
 	nv_wr32(dev, 0x3204, 0);
 	nv_wr32(dev, 0x3210, 0);
 	nv_wr32(dev, 0x3270, 0);
+	nv_wr32(dev, 0x2044, 0x01003fff);
 
 	/* Enable dummy channels setup by nv50_instmem.c */
 	nv50_fifo_channel_enable(dev, 0);
@@ -273,7 +274,7 @@
 	nv_wo32(ramfc, 0x80, ((chan->ramht->bits - 9) << 27) |
 			     (4 << 24) /* SEARCH_FULL */ |
 			     (chan->ramht->gpuobj->cinst >> 4));
-	nv_wo32(ramfc, 0x44, 0x2101ffff);
+	nv_wo32(ramfc, 0x44, 0x01003fff);
 	nv_wo32(ramfc, 0x60, 0x7fffffff);
 	nv_wo32(ramfc, 0x40, 0x00000000);
 	nv_wo32(ramfc, 0x7c, 0x30000001);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -137,6 +137,7 @@
 	struct nv50_gpio_priv *priv = pgpio->priv;
 	struct nv50_gpio_handler *gpioh, *tmp;
 	struct dcb_gpio_entry *gpio;
+	LIST_HEAD(tofree);
 	unsigned long flags;
 
 	gpio = nouveau_bios_gpio_entry(dev, tag);
@@ -149,10 +150,14 @@
 		    gpioh->handler != handler ||
 		    gpioh->data != data)
 			continue;
-		list_del(&gpioh->head);
-		kfree(gpioh);
+		list_move(&gpioh->head, &tofree);
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	list_for_each_entry_safe(gpioh, tmp, &tofree, head) {
+		flush_work_sync(&gpioh->work);
+		kfree(gpioh);
+	}
 }
 
 bool
@@ -205,7 +210,6 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_gpio_engine *pgpio = &dev_priv->engine.gpio;
-	struct nv50_gpio_priv *priv;
 	int ret;
 
 	if (!pgpio->priv) {
@@ -213,7 +217,6 @@
 		if (ret)
 			return ret;
 	}
-	priv = pgpio->priv;
 
 	/* disable, and ack any pending gpio interrupts */
 	nv_wr32(dev, 0xe050, 0x00000000);
@@ -293,7 +296,7 @@
 			continue;
 		gpioh->inhibit = true;
 
-		queue_work(dev_priv->wq, &gpioh->work);
+		schedule_work(&gpioh->work);
 	}
 	spin_unlock(&priv->lock);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_graph.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_graph.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_graph.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_graph.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,13 +95,41 @@
 }
 
 static void
-nv50_graph_init_regs(struct drm_device *dev)
+nv50_graph_init_zcull(struct drm_device *dev)
 {
+	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	int i;
+
 	NV_DEBUG(dev, "\n");
 
-	nv_wr32(dev, NV04_PGRAPH_DEBUG_3,
-				(1 << 2) /* HW_CONTEXT_SWITCH_ENABLED */);
-	nv_wr32(dev, 0x402ca8, 0x800);
+	switch (dev_priv->chipset & 0xf0) {
+	case 0x50:
+	case 0x80:
+	case 0x90:
+		nv_wr32(dev, 0x402ca8, 0x00000800);
+		break;
+	case 0xa0:
+	default:
+		nv_wr32(dev, 0x402cc0, 0x00000000);
+		if (dev_priv->chipset == 0xa0 ||
+		    dev_priv->chipset == 0xaa ||
+		    dev_priv->chipset == 0xac) {
+			nv_wr32(dev, 0x402ca8, 0x00000802);
+		} else {
+			nv_wr32(dev, 0x402cc0, 0x00000000);
+			nv_wr32(dev, 0x402ca8, 0x00000002);
+		}
+
+		break;
+	}
+
+	/* zero out zcull regions */
+	for (i = 0; i < 8; i++) {
+		nv_wr32(dev, 0x402c20 + (i * 8), 0x00000000);
+		nv_wr32(dev, 0x402c24 + (i * 8), 0x00000000);
+		nv_wr32(dev, 0x402c28 + (i * 8), 0x00000000);
+		nv_wr32(dev, 0x402c2c + (i * 8), 0x00000000);
+	}
 }
 
 static int
@@ -136,6 +164,7 @@
 	}
 	kfree(cp);
 
+	nv_wr32(dev, 0x40008c, 0x00000004); /* HW_CTX_SWITCH_ENABLED */
 	nv_wr32(dev, 0x400320, 4);
 	nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, 0);
 	nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, 0);
@@ -151,7 +180,7 @@
 
 	nv50_graph_init_reset(dev);
 	nv50_graph_init_regs__nv(dev);
-	nv50_graph_init_regs(dev);
+	nv50_graph_init_zcull(dev);
 
 	ret = nv50_graph_init_ctxctl(dev);
 	if (ret)
@@ -409,12 +438,7 @@
 nv50_graph_nvsw_mthd_page_flip(struct nouveau_channel *chan,
 			       u32 class, u32 mthd, u32 data)
 {
-	struct nouveau_page_flip_state s;
-
-	if (!nouveau_finish_page_flip(chan, &s)) {
-		/* XXX - Do something here */
-	}
-
+	nouveau_finish_page_flip(chan, NULL);
 	return 0;
 }
 
@@ -479,7 +503,7 @@
 }
 
 void
-nv86_graph_tlb_flush(struct drm_device *dev)
+nv84_graph_tlb_flush(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_timer_engine *ptimer = &dev_priv->engine.timer;
@@ -526,11 +550,11 @@
 
 static struct nouveau_enum nv50_mp_exec_error_names[] =
 {
-	{ 3, "STACK_UNDERFLOW" },
-	{ 4, "QUADON_ACTIVE" },
-	{ 8, "TIMEOUT" },
-	{ 0x10, "INVALID_OPCODE" },
-	{ 0x40, "BREAKPOINT" },
+	{ 3, "STACK_UNDERFLOW", NULL },
+	{ 4, "QUADON_ACTIVE", NULL },
+	{ 8, "TIMEOUT", NULL },
+	{ 0x10, "INVALID_OPCODE", NULL },
+	{ 0x40, "BREAKPOINT", NULL },
 	{}
 };
 
@@ -558,47 +582,47 @@
 
 /* There must be a *lot* of these. Will take some time to gather them up. */
 struct nouveau_enum nv50_data_error_names[] = {
-	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE" },
-	{ 0x00000004, "INVALID_VALUE" },
-	{ 0x00000005, "INVALID_ENUM" },
-	{ 0x00000008, "INVALID_OBJECT" },
-	{ 0x00000009, "READ_ONLY_OBJECT" },
-	{ 0x0000000a, "SUPERVISOR_OBJECT" },
-	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT" },
-	{ 0x0000000c, "INVALID_BITFIELD" },
-	{ 0x0000000d, "BEGIN_END_ACTIVE" },
-	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT" },
-	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP" },
-	{ 0x00000010, "RT_DOUBLE_BIND" },
-	{ 0x00000011, "RT_TYPES_MISMATCH" },
-	{ 0x00000012, "RT_LINEAR_WITH_ZETA" },
-	{ 0x00000015, "FP_TOO_FEW_REGS" },
-	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH" },
-	{ 0x00000017, "RT_LINEAR_WITH_MSAA" },
-	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT" },
-	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT" },
-	{ 0x0000001a, "RT_INVALID_ALIGNMENT" },
-	{ 0x0000001b, "SAMPLER_OVER_LIMIT" },
-	{ 0x0000001c, "TEXTURE_OVER_LIMIT" },
-	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS" },
-	{ 0x0000001f, "RT_BPP128_WITH_MS8" },
-	{ 0x00000021, "Z_OUT_OF_BOUNDS" },
-	{ 0x00000023, "XY_OUT_OF_BOUNDS" },
-	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED" },
-	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED" },
-	{ 0x00000029, "CP_NO_REG_SPACE_PACKED" },
-	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS" },
-	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH" },
-	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS" },
-	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS" },
-	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH" },
-	{ 0x00000031, "ENG2D_FORMAT_MISMATCH" },
-	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP" },
-	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT" },
-	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT" },
-	{ 0x00000046, "LAYER_ID_NEEDS_GP" },
-	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT" },
-	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT" },
+	{ 0x00000003, "INVALID_QUERY_OR_TEXTURE", NULL },
+	{ 0x00000004, "INVALID_VALUE", NULL },
+	{ 0x00000005, "INVALID_ENUM", NULL },
+	{ 0x00000008, "INVALID_OBJECT", NULL },
+	{ 0x00000009, "READ_ONLY_OBJECT", NULL },
+	{ 0x0000000a, "SUPERVISOR_OBJECT", NULL },
+	{ 0x0000000b, "INVALID_ADDRESS_ALIGNMENT", NULL },
+	{ 0x0000000c, "INVALID_BITFIELD", NULL },
+	{ 0x0000000d, "BEGIN_END_ACTIVE", NULL },
+	{ 0x0000000e, "SEMANTIC_COLOR_BACK_OVER_LIMIT", NULL },
+	{ 0x0000000f, "VIEWPORT_ID_NEEDS_GP", NULL },
+	{ 0x00000010, "RT_DOUBLE_BIND", NULL },
+	{ 0x00000011, "RT_TYPES_MISMATCH", NULL },
+	{ 0x00000012, "RT_LINEAR_WITH_ZETA", NULL },
+	{ 0x00000015, "FP_TOO_FEW_REGS", NULL },
+	{ 0x00000016, "ZETA_FORMAT_CSAA_MISMATCH", NULL },
+	{ 0x00000017, "RT_LINEAR_WITH_MSAA", NULL },
+	{ 0x00000018, "FP_INTERPOLANT_START_OVER_LIMIT", NULL },
+	{ 0x00000019, "SEMANTIC_LAYER_OVER_LIMIT", NULL },
+	{ 0x0000001a, "RT_INVALID_ALIGNMENT", NULL },
+	{ 0x0000001b, "SAMPLER_OVER_LIMIT", NULL },
+	{ 0x0000001c, "TEXTURE_OVER_LIMIT", NULL },
+	{ 0x0000001e, "GP_TOO_MANY_OUTPUTS", NULL },
+	{ 0x0000001f, "RT_BPP128_WITH_MS8", NULL },
+	{ 0x00000021, "Z_OUT_OF_BOUNDS", NULL },
+	{ 0x00000023, "XY_OUT_OF_BOUNDS", NULL },
+	{ 0x00000027, "CP_MORE_PARAMS_THAN_SHARED", NULL },
+	{ 0x00000028, "CP_NO_REG_SPACE_STRIPED", NULL },
+	{ 0x00000029, "CP_NO_REG_SPACE_PACKED", NULL },
+	{ 0x0000002a, "CP_NOT_ENOUGH_WARPS", NULL },
+	{ 0x0000002b, "CP_BLOCK_SIZE_MISMATCH", NULL },
+	{ 0x0000002c, "CP_NOT_ENOUGH_LOCAL_WARPS", NULL },
+	{ 0x0000002d, "CP_NOT_ENOUGH_STACK_WARPS", NULL },
+	{ 0x0000002e, "CP_NO_BLOCKDIM_LATCH", NULL },
+	{ 0x00000031, "ENG2D_FORMAT_MISMATCH", NULL },
+	{ 0x0000003f, "PRIMITIVE_ID_NEEDS_GP", NULL },
+	{ 0x00000044, "SEMANTIC_VIEWPORT_OVER_LIMIT", NULL },
+	{ 0x00000045, "SEMANTIC_COLOR_FRONT_OVER_LIMIT", NULL },
+	{ 0x00000046, "LAYER_ID_NEEDS_GP", NULL },
+	{ 0x00000047, "SEMANTIC_CLIP_OVER_LIMIT", NULL },
+	{ 0x00000048, "SEMANTIC_PTSZ_OVER_LIMIT", NULL },
 	{}
 };
 
@@ -678,7 +702,6 @@
 		tps++;
 		switch (type) {
 		case 6: /* texture error... unknown for now */
-			nv50_fb_vm_trap(dev, display, name);
 			if (display) {
 				NV_ERROR(dev, "magic set %d:\n", i);
 				for (r = ustatus_addr + 4; r <= ustatus_addr + 0x10; r += 4)
@@ -701,7 +724,6 @@
 			uint32_t e1c = nv_rd32(dev, ustatus_addr + 0x14);
 			uint32_t e20 = nv_rd32(dev, ustatus_addr + 0x18);
 			uint32_t e24 = nv_rd32(dev, ustatus_addr + 0x1c);
-			nv50_fb_vm_trap(dev, display, name);
 			/* 2d engine destination */
 			if (ustatus & 0x00000010) {
 				if (display) {
@@ -912,10 +934,10 @@
 			printk("\n");
 			NV_INFO(dev, "PGRAPH - TRAP_CCACHE %08x %08x %08x %08x"
 				     " %08x %08x %08x\n",
-				nv_rd32(dev, 0x405800), nv_rd32(dev, 0x405804),
-				nv_rd32(dev, 0x405808), nv_rd32(dev, 0x40580c),
-				nv_rd32(dev, 0x405810), nv_rd32(dev, 0x405814),
-				nv_rd32(dev, 0x40581c));
+				nv_rd32(dev, 0x405000), nv_rd32(dev, 0x405004),
+				nv_rd32(dev, 0x405008), nv_rd32(dev, 0x40500c),
+				nv_rd32(dev, 0x405010), nv_rd32(dev, 0x405014),
+				nv_rd32(dev, 0x40501c));
 
 		}
 
@@ -1044,6 +1066,7 @@
 			NV_INFO(dev, "PGRAPH - ch %d (0x%010llx) subc %d "
 				     "class 0x%04x mthd 0x%04x data 0x%08x\n",
 				chid, inst, subc, class, mthd, data);
+			nv50_fb_vm_trap(dev, 1);
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_instmem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_instmem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_instmem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_instmem.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
 	nouveau_gpuobj_ref(NULL, &chan->ramfc);
 	nouveau_vm_ref(NULL, &chan->vm, chan->vm_pd);
 	nouveau_gpuobj_ref(NULL, &chan->vm_pd);
-	if (chan->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
 	kfree(chan);
@@ -259,7 +259,7 @@
 	nouveau_gpuobj_ref(NULL, &dev_priv->bar3_vm->pgt[0].obj[0]);
 	nouveau_vm_ref(NULL, &dev_priv->bar3_vm, NULL);
 
-	if (dev_priv->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&dev_priv->ramin_heap))
 		drm_mm_takedown(&dev_priv->ramin_heap);
 
 	dev_priv->engine.instmem.priv = NULL;
@@ -300,7 +300,7 @@
 }
 
 struct nv50_gpuobj_node {
-	struct nouveau_vram *vram;
+	struct nouveau_mem *vram;
 	struct nouveau_vma chan_vma;
 	u32 align;
 };
@@ -404,23 +404,25 @@
 nv50_instmem_flush(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 
-	spin_lock(&dev_priv->ramin_lock);
+	spin_lock_irqsave(&dev_priv->vm_lock, flags);
 	nv_wr32(dev, 0x00330c, 0x00000001);
 	if (!nv_wait(dev, 0x00330c, 0x00000002, 0x00000000))
 		NV_ERROR(dev, "PRAMIN flush timeout\n");
-	spin_unlock(&dev_priv->ramin_lock);
+	spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
 
 void
 nv84_instmem_flush(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 
-	spin_lock(&dev_priv->ramin_lock);
+	spin_lock_irqsave(&dev_priv->vm_lock, flags);
 	nv_wr32(dev, 0x070000, 0x00000001);
 	if (!nv_wait(dev, 0x070000, 0x00000002, 0x00000000))
 		NV_ERROR(dev, "PRAMIN flush timeout\n");
-	spin_unlock(&dev_priv->ramin_lock);
+	spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_sor.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_sor.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_sor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_sor.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,8 +41,7 @@
 {
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
-	struct drm_nouveau_private *dev_priv = dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(dev)->master;
 	int ret;
 
 	if (!nv_encoder->crtc)
@@ -184,8 +183,7 @@
 nv50_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *mode,
 		  struct drm_display_mode *adjusted_mode)
 {
-	struct drm_nouveau_private *dev_priv = encoder->dev->dev_private;
-	struct nouveau_channel *evo = dev_priv->evo;
+	struct nouveau_channel *evo = nv50_display(encoder->dev)->master;
 	struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder);
 	struct drm_device *dev = encoder->dev;
 	struct nouveau_crtc *crtc = nouveau_crtc(encoder->crtc);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_vm.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_vm.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_vm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_vm.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,6 @@
 nv50_vm_map_pgt(struct nouveau_gpuobj *pgd, u32 pde,
 		struct nouveau_gpuobj *pgt[2])
 {
-	struct drm_nouveau_private *dev_priv = pgd->dev->dev_private;
 	u64 phys = 0xdeadcafe00000000ULL;
 	u32 coverage = 0;
 
@@ -58,10 +57,9 @@
 }
 
 static inline u64
-nv50_vm_addr(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	     u64 phys, u32 memtype, u32 target)
+nv50_vm_addr(struct nouveau_vma *vma, u64 phys, u32 memtype, u32 target)
 {
-	struct drm_nouveau_private *dev_priv = pgt->dev->dev_private;
+	struct drm_nouveau_private *dev_priv = vma->vm->dev->dev_private;
 
 	phys |= 1; /* present */
 	phys |= (u64)memtype << 40;
@@ -85,12 +83,13 @@
 
 void
 nv50_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	    struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys)
+	    struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
 {
+	u32 comp = (mem->memtype & 0x180) >> 7;
 	u32 block;
 	int i;
 
-	phys  = nv50_vm_addr(vma, pgt, phys, mem->memtype, 0);
+	phys  = nv50_vm_addr(vma, phys, mem->memtype, 0);
 	pte <<= 3;
 	cnt <<= 3;
 
@@ -107,6 +106,11 @@
 
 		phys += block << (vma->node->type - 3);
 		cnt  -= block;
+		if (comp) {
+			u32 tag = mem->tag->start + ((delta >> 16) * comp);
+			offset_h |= (tag << 17);
+			delta    += block << (vma->node->type - 3);
+		}
 
 		while (block) {
 			nv_wo32(pgt, pte + 0, offset_l);
@@ -119,11 +123,11 @@
 
 void
 nv50_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	       u32 pte, dma_addr_t *list, u32 cnt)
+	       struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
 	pte <<= 3;
 	while (cnt--) {
-		u64 phys = nv50_vm_addr(vma, pgt, (u64)*list++, 0, 2);
+		u64 phys = nv50_vm_addr(vma, (u64)*list++, mem->memtype, 2);
 		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
 		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
 		pte += 8;
@@ -170,10 +174,11 @@
 nv50_vm_flush_engine(struct drm_device *dev, int engine)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
+	unsigned long flags;
 
-	spin_lock(&dev_priv->ramin_lock);
+	spin_lock_irqsave(&dev_priv->vm_lock, flags);
 	nv_wr32(dev, 0x100c80, (engine << 16) | 1);
 	if (!nv_wait(dev, 0x100c80, 0x00000001, 0x00000000))
 		NV_ERROR(dev, "vm flush timeout: engine %d\n", engine);
-	spin_unlock(&dev_priv->ramin_lock);
+	spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_vram.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_vram.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv50_vram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv50_vram.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,42 +48,49 @@
 }
 
 void
-nv50_vram_del(struct drm_device *dev, struct nouveau_vram **pvram)
+nv50_vram_del(struct drm_device *dev, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
 	struct nouveau_mm *mm = man->priv;
 	struct nouveau_mm_node *this;
-	struct nouveau_vram *vram;
+	struct nouveau_mem *mem;
 
-	vram = *pvram;
-	*pvram = NULL;
-	if (unlikely(vram == NULL))
+	mem = *pmem;
+	*pmem = NULL;
+	if (unlikely(mem == NULL))
 		return;
 
 	mutex_lock(&mm->mutex);
-	while (!list_empty(&vram->regions)) {
-		this = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
+	while (!list_empty(&mem->regions)) {
+		this = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
 
 		list_del(&this->rl_entry);
 		nouveau_mm_put(mm, this);
 	}
+
+	if (mem->tag) {
+		drm_mm_put_block(mem->tag);
+		mem->tag = NULL;
+	}
 	mutex_unlock(&mm->mutex);
 
-	kfree(vram);
+	kfree(mem);
 }
 
 int
 nv50_vram_new(struct drm_device *dev, u64 size, u32 align, u32 size_nc,
-	      u32 type, struct nouveau_vram **pvram)
+	      u32 memtype, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
 	struct nouveau_mm *mm = man->priv;
 	struct nouveau_mm_node *r;
-	struct nouveau_vram *vram;
+	struct nouveau_mem *mem;
+	int comp = (memtype & 0x300) >> 8;
+	int type = (memtype & 0x07f);
 	int ret;
 
 	if (!types[type])
@@ -92,32 +99,46 @@
 	align >>= 12;
 	size_nc >>= 12;
 
-	vram = kzalloc(sizeof(*vram), GFP_KERNEL);
-	if (!vram)
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&vram->regions);
-	vram->dev = dev_priv->dev;
-	vram->memtype = type;
-	vram->size = size;
-
 	mutex_lock(&mm->mutex);
+	if (comp) {
+		if (align == 16) {
+			struct nouveau_fb_engine *pfb = &dev_priv->engine.fb;
+			int n = (size >> 4) * comp;
+
+			mem->tag = drm_mm_search_free(&pfb->tag_heap, n, 0, 0);
+			if (mem->tag)
+				mem->tag = drm_mm_get_block(mem->tag, n, 0);
+		}
+
+		if (unlikely(!mem->tag))
+			comp = 0;
+	}
+
+	INIT_LIST_HEAD(&mem->regions);
+	mem->dev = dev_priv->dev;
+	mem->memtype = (comp << 7) | type;
+	mem->size = size;
+
 	do {
 		ret = nouveau_mm_get(mm, types[type], size, size_nc, align, &r);
 		if (ret) {
 			mutex_unlock(&mm->mutex);
-			nv50_vram_del(dev, &vram);
+			nv50_vram_del(dev, &mem);
 			return ret;
 		}
 
-		list_add_tail(&r->rl_entry, &vram->regions);
+		list_add_tail(&r->rl_entry, &mem->regions);
 		size -= r->length;
 	} while (size);
 	mutex_unlock(&mm->mutex);
 
-	r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
-	vram->offset = (u64)r->offset << 12;
-	*pvram = vram;
+	r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
+	mem->offset = (u64)r->offset << 12;
+	*pmem = mem;
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv84_crypt.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv84_crypt.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nv84_crypt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nv84_crypt.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,5 +136,5 @@
 	nv_wr32(dev, 0x102130, stat);
 	nv_wr32(dev, 0x10200c, 0x10);
 
-	nv50_fb_vm_trap(dev, show, "PCRYPT");
+	nv50_fb_vm_trap(dev, show);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_fifo.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,7 @@
 
 	/* allocate vram for control regs, map into polling area */
 	ret = nouveau_bo_new(dev, NULL, 0x1000, 0, TTM_PL_FLAG_VRAM,
-			     0, 0, true, true, &fifoch->user);
+			     0, 0, &fifoch->user);
 	if (ret)
 		goto error;
 
@@ -418,6 +418,12 @@
 {
 	u32 stat = nv_rd32(dev, 0x002100);
 
+	if (stat & 0x00000100) {
+		NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
+		nv_wr32(dev, 0x002100, 0x00000100);
+		stat &= ~0x00000100;
+	}
+
 	if (stat & 0x10000000) {
 		u32 units = nv_rd32(dev, 0x00259c);
 		u32 u = units;
@@ -446,10 +452,15 @@
 		stat &= ~0x20000000;
 	}
 
+	if (stat & 0x40000000) {
+		NV_INFO(dev, "PFIFO: unknown status 0x40000000\n");
+		nv_mask(dev, 0x002a00, 0x00000000, 0x00000000);
+		stat &= ~0x40000000;
+	}
+
 	if (stat) {
 		NV_INFO(dev, "PFIFO: unhandled status 0x%08x\n", stat);
 		nv_wr32(dev, 0x002100, stat);
+		nv_wr32(dev, 0x002140, 0);
 	}
-
-	nv_wr32(dev, 0x2140, 0);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c	2012-03-24 01:00:18.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_graph.c	2012-03-24 03:26:26.000000000 -0400
@@ -299,6 +299,14 @@
 }
 
 static int
+nvc0_graph_mthd_page_flip(struct nouveau_channel *chan,
+			  u32 class, u32 mthd, u32 data)
+{
+	nouveau_finish_page_flip(chan, NULL);
+	return 0;
+}
+
+static int
 nvc0_graph_create(struct drm_device *dev)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
@@ -395,6 +403,7 @@
 	nouveau_irq_register(dev, 25, nvc0_runk140_isr);
 	NVOBJ_CLASS(dev, 0x902d, GR); /* 2D */
 	NVOBJ_CLASS(dev, 0x9039, GR); /* M2MF */
+	NVOBJ_MTHD (dev, 0x9039, 0x0500, nvc0_graph_mthd_page_flip);
 	NVOBJ_CLASS(dev, 0x9097, GR); /* 3D */
 	NVOBJ_CLASS(dev, 0x90c0, GR); /* COMPUTE */
 	return 0;
@@ -640,7 +649,6 @@
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph;
-	struct nvc0_graph_priv *priv;
 	int ret;
 
 	dev_priv->engine.graph.accel_blocked = true;
@@ -665,7 +673,6 @@
 		if (ret)
 			return ret;
 	}
-	priv = pgraph->priv;
 
 	nvc0_graph_init_obj418880(dev);
 	nvc0_graph_init_regs(dev);
@@ -730,9 +737,12 @@
 	u32 class = nv_rd32(dev, 0x404200 + (subc * 4));
 
 	if (stat & 0x00000010) {
-		NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] subc %d "
-			     "class 0x%04x mthd 0x%04x data 0x%08x\n",
-			chid, inst, subc, class, mthd, data);
+		if (nouveau_gpuobj_mthd_call2(dev, chid, class, mthd, data)) {
+			NV_INFO(dev, "PGRAPH: ILLEGAL_MTHD ch %d [0x%010llx] "
+				     "subc %d class 0x%04x mthd 0x%04x "
+				     "data 0x%08x\n",
+				chid, inst, subc, class, mthd, data);
+		}
 		nv_wr32(dev, 0x400100, 0x00000010);
 		stat &= ~0x00000010;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_instmem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_instmem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_instmem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_instmem.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
 		return;
 
 	nouveau_vm_ref(NULL, &chan->vm, NULL);
-	if (chan->ramin_heap.free_stack.next)
+	if (drm_mm_initialized(&chan->ramin_heap))
 		drm_mm_takedown(&chan->ramin_heap);
 	nouveau_gpuobj_ref(NULL, &chan->ramin);
 	kfree(chan);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_vm.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_vm.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_vm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_vm.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,7 +59,7 @@
 
 void
 nvc0_vm_map(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	    struct nouveau_vram *mem, u32 pte, u32 cnt, u64 phys)
+	    struct nouveau_mem *mem, u32 pte, u32 cnt, u64 phys, u64 delta)
 {
 	u32 next = 1 << (vma->node->type - 8);
 
@@ -75,11 +75,11 @@
 
 void
 nvc0_vm_map_sg(struct nouveau_vma *vma, struct nouveau_gpuobj *pgt,
-	       u32 pte, dma_addr_t *list, u32 cnt)
+	       struct nouveau_mem *mem, u32 pte, u32 cnt, dma_addr_t *list)
 {
 	pte <<= 3;
 	while (cnt--) {
-		u64 phys = nvc0_vm_addr(vma, *list++, 0, 5);
+		u64 phys = nvc0_vm_addr(vma, *list++, mem->memtype, 5);
 		nv_wo32(pgt, pte + 0, lower_32_bits(phys));
 		nv_wo32(pgt, pte + 4, upper_32_bits(phys));
 		pte += 8;
@@ -104,20 +104,27 @@
 	struct nouveau_instmem_engine *pinstmem = &dev_priv->engine.instmem;
 	struct drm_device *dev = vm->dev;
 	struct nouveau_vm_pgd *vpgd;
-	u32 r100c80, engine;
+	unsigned long flags;
+	u32 engine = (dev_priv->chan_vm == vm) ? 1 : 5;
 
 	pinstmem->flush(vm->dev);
 
-	if (vm == dev_priv->chan_vm)
-		engine = 1;
-	else
-		engine = 5;
-
+	spin_lock_irqsave(&dev_priv->vm_lock, flags);
 	list_for_each_entry(vpgd, &vm->pgd_list, head) {
-		r100c80 = nv_rd32(dev, 0x100c80);
+		/* looks like maybe a "free flush slots" counter, the
+		 * faster you write to 0x100cbc to more it decreases
+		 */
+		if (!nv_wait_ne(dev, 0x100c80, 0x00ff0000, 0x00000000)) {
+			NV_ERROR(dev, "vm timeout 0: 0x%08x %d\n",
+				 nv_rd32(dev, 0x100c80), engine);
+		}
 		nv_wr32(dev, 0x100cb8, vpgd->obj->vinst >> 8);
 		nv_wr32(dev, 0x100cbc, 0x80000000 | engine);
-		if (!nv_wait(dev, 0x100c80, 0xffffffff, r100c80))
-			NV_ERROR(dev, "vm flush timeout eng %d\n", engine);
+		/* wait for flush to be queued? */
+		if (!nv_wait(dev, 0x100c80, 0x00008000, 0x00008000)) {
+			NV_ERROR(dev, "vm timeout 1: 0x%08x %d\n",
+				 nv_rd32(dev, 0x100c80), engine);
+		}
 	}
+	spin_unlock_irqrestore(&dev_priv->vm_lock, flags);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/nouveau/nvc0_vram.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,64 +26,78 @@
 #include "nouveau_drv.h"
 #include "nouveau_mm.h"
 
+/* 0 = unsupported
+ * 1 = non-compressed
+ * 3 = compressed
+ */
+static const u8 types[256] = {
+	1, 1, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
+	0, 1, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3,
+	3, 3, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 3, 3, 3, 3, 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, 1, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 0, 1, 1, 1, 1, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 3, 3, 3, 3, 1, 1, 1, 1, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
+	3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3,
+	3, 3, 0, 0, 0, 0, 0, 0, 3, 0, 0, 3, 0, 3, 0, 3,
+	3, 0, 3, 3, 3, 3, 3, 0, 0, 3, 0, 3, 0, 3, 3, 0,
+	3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 1, 1, 0
+};
+
 bool
 nvc0_vram_flags_valid(struct drm_device *dev, u32 tile_flags)
 {
-	switch (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) {
-	case 0x0000:
-	case 0xfe00:
-	case 0xdb00:
-	case 0x1100:
-		return true;
-	default:
-		break;
-	}
-
-	return false;
+	u8 memtype = (tile_flags & NOUVEAU_GEM_TILE_LAYOUT_MASK) >> 8;
+	return likely((types[memtype] == 1));
 }
 
 int
 nvc0_vram_new(struct drm_device *dev, u64 size, u32 align, u32 ncmin,
-	      u32 type, struct nouveau_vram **pvram)
+	      u32 type, struct nouveau_mem **pmem)
 {
 	struct drm_nouveau_private *dev_priv = dev->dev_private;
 	struct ttm_bo_device *bdev = &dev_priv->ttm.bdev;
 	struct ttm_mem_type_manager *man = &bdev->man[TTM_PL_VRAM];
 	struct nouveau_mm *mm = man->priv;
 	struct nouveau_mm_node *r;
-	struct nouveau_vram *vram;
+	struct nouveau_mem *mem;
 	int ret;
 
 	size  >>= 12;
 	align >>= 12;
 	ncmin >>= 12;
 
-	vram = kzalloc(sizeof(*vram), GFP_KERNEL);
-	if (!vram)
+	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
+	if (!mem)
 		return -ENOMEM;
 
-	INIT_LIST_HEAD(&vram->regions);
-	vram->dev = dev_priv->dev;
-	vram->memtype = type;
-	vram->size = size;
+	INIT_LIST_HEAD(&mem->regions);
+	mem->dev = dev_priv->dev;
+	mem->memtype = (type & 0xff);
+	mem->size = size;
 
 	mutex_lock(&mm->mutex);
 	do {
 		ret = nouveau_mm_get(mm, 1, size, ncmin, align, &r);
 		if (ret) {
 			mutex_unlock(&mm->mutex);
-			nv50_vram_del(dev, &vram);
+			nv50_vram_del(dev, &mem);
 			return ret;
 		}
 
-		list_add_tail(&r->rl_entry, &vram->regions);
+		list_add_tail(&r->rl_entry, &mem->regions);
 		size -= r->length;
 	} while (size);
 	mutex_unlock(&mm->mutex);
 
-	r = list_first_entry(&vram->regions, struct nouveau_mm_node, rl_entry);
-	vram->offset = (u64)r->offset << 12;
-	*pvram = vram;
+	r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
+	mem->offset = (u64)r->offset << 12;
+	*pmem = mem;
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/r128/r128_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/r128/r128_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/r128/r128_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/r128/r128_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,10 +71,7 @@
 #endif
 		.llseek = noop_llseek,
 	},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-	},
+
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -89,16 +86,21 @@
 	return drm_vblank_init(dev, 1);
 }
 
+static struct pci_driver r128_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init r128_init(void)
 {
 	driver.num_ioctls = r128_max_ioctl;
 
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &r128_pci_driver);
 }
 
 static void __exit r128_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &r128_pci_driver);
 }
 
 module_init(r128_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atombios_crtc.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/atombios_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/atombios_crtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,8 +61,8 @@
 			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_hdisplay - (a2 / mode->crtc_vdisplay)) / 2);
 		} else if (a2 > a1) {
-			args.usOverscanLeft = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
-			args.usOverscanRight = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanTop = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
+			args.usOverscanBottom = cpu_to_le16((adjusted_mode->crtc_vdisplay - (a1 / mode->crtc_hdisplay)) / 2);
 		}
 		break;
 	case RMX_FULL:
@@ -531,6 +531,9 @@
 			pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV;
 		else
 			pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV;
+
+		if (rdev->family < CHIP_RV770)
+			pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
 	} else {
 		pll->flags |= RADEON_PLL_LEGACY;
 
@@ -559,7 +562,6 @@
 			if (radeon_encoder->devices & (ATOM_DEVICE_LCD_SUPPORT)) {
 				if (ss_enabled) {
 					if (ss->refdiv) {
-						pll->flags |= RADEON_PLL_PREFER_MINM_OVER_MAXP;
 						pll->flags |= RADEON_PLL_USE_REF_DIV;
 						pll->reference_div = ss->refdiv;
 						if (ASIC_IS_AVIVO(rdev))
@@ -957,7 +959,11 @@
 	/* adjust pixel clock as needed */
 	adjusted_clock = atombios_adjust_pll(crtc, mode, pll, ss_enabled, &ss);
 
-	if (ASIC_IS_AVIVO(rdev))
+	if (radeon_encoder->active_device & (ATOM_DEVICE_TV_SUPPORT))
+		/* TV seems to prefer the legacy algo on some boards */
+		radeon_compute_pll_legacy(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
+					  &ref_div, &post_div);
+	else if (ASIC_IS_AVIVO(rdev))
 		radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div,
 					 &ref_div, &post_div);
 	else
@@ -1005,6 +1011,7 @@
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 	u32 fb_swap = EVERGREEN_GRPH_ENDIAN_SWAP(EVERGREEN_GRPH_ENDIAN_NONE);
+	u32 tmp;
 	int r;
 
 	/* no fb bound */
@@ -1026,7 +1033,7 @@
 	 * just update base pointers
 	 */
 	obj = radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -1133,9 +1140,18 @@
 	WREG32(EVERGREEN_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
 
+	/* pageflip setup */
+	/* make sure flip is at vb rather than hb */
+	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
+	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
+	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
+
+	/* set pageflip to happen anywhere in vblank interval */
+	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
-		rbo = radeon_fb->obj->driver_private;
+		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r != 0))
 			return r;
@@ -1163,6 +1179,7 @@
 	uint64_t fb_location;
 	uint32_t fb_format, fb_pitch_pixels, tiling_flags;
 	u32 fb_swap = R600_D1GRPH_SWAP_ENDIAN_NONE;
+	u32 tmp;
 	int r;
 
 	/* no fb bound */
@@ -1181,7 +1198,7 @@
 	}
 
 	obj = radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -1290,9 +1307,18 @@
 	WREG32(AVIVO_D1MODE_VIEWPORT_SIZE + radeon_crtc->crtc_offset,
 	       (crtc->mode.hdisplay << 16) | crtc->mode.vdisplay);
 
+	/* pageflip setup */
+	/* make sure flip is at vb rather than hb */
+	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
+	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
+	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
+
+	/* set pageflip to happen anywhere in vblank interval */
+	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
+
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
-		rbo = radeon_fb->obj->driver_private;
+		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r != 0))
 			return r;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atombios.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/atombios.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atombios.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/atombios.h	2011-05-19 00:06:34.000000000 -0400
@@ -738,13 +738,13 @@
 {
 #if ATOM_BIG_ENDIAN
     UCHAR ucReserved1:1;
-    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F)
     UCHAR ucReserved:3;
     UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
 #else
     UCHAR ucDPLinkRate:1;         // =0: 1.62Ghz, =1: 2.7Ghz
     UCHAR ucReserved:3;
-    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F)
     UCHAR ucReserved1:1;
 #endif
 }ATOM_DIG_ENCODER_CONFIG_V3;
@@ -785,13 +785,13 @@
 {
 #if ATOM_BIG_ENDIAN
     UCHAR ucReserved1:1;
-    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F)
     UCHAR ucReserved:2;
     UCHAR ucDPLinkRate:2;         // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz    <= Changed comparing to previous version
 #else
     UCHAR ucDPLinkRate:2;         // =0: 1.62Ghz, =1: 2.7Ghz, 2=5.4Ghz    <= Changed comparing to previous version
     UCHAR ucReserved:2;
-    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also refered as DIGA/B/C/D/E/F)
+    UCHAR ucDigSel:3;             // =0/1/2/3/4/5: DIG0/1/2/3/4/5 (In register spec also referred as DIGA/B/C/D/E/F)
     UCHAR ucReserved1:1;
 #endif
 }ATOM_DIG_ENCODER_CONFIG_V4;
@@ -2126,7 +2126,7 @@
 // Structures used in FirmwareInfoTable
 /****************************************************************************/	
 
-// usBIOSCapability Defintion:
+// usBIOSCapability Definition:
 // 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; 
@@ -3341,7 +3341,7 @@
 /****************************************************************************/	
 // Structure used in AnalogTV_InfoTable (Top level)
 /****************************************************************************/	
-//ucTVBootUpDefaultStd definiton:
+//ucTVBootUpDefaultStd definition:
 
 //ATOM_TV_NTSC                1
 //ATOM_TV_NTSCJ               2
@@ -3816,7 +3816,7 @@
   UCHAR                    Reserved [6];                          // for potential expansion
 }ATOM_EXTERNAL_DISPLAY_CONNECTION_INFO;
 
-//Related definitions, all records are differnt but they have a commond header
+//Related definitions, all records are different but they have a commond header
 typedef struct _ATOM_COMMON_RECORD_HEADER
 {
   UCHAR               ucRecordType;                      //An emun to indicate the record type
@@ -4365,14 +4365,14 @@
 ulCSR_M3_ARB_CNTL_DEFAULT[10]:    Arrays with values for CSR M3 arbiter for default
 ulCSR_M3_ARB_CNTL_UVD[10]:        Arrays with values for CSR M3 arbiter for UVD playback.
 ulCSR_M3_ARB_CNTL_FS3D[10]:       Arrays with values for CSR M3 arbiter for Full Screen 3D applications.
-sAvail_SCLK[5]:                   Arrays to provide availabe list of SLCK and corresponding voltage, order from low to high  
+sAvail_SCLK[5]:                   Arrays to provide available list of SLCK and corresponding voltage, order from low to high  
 ulGMCRestoreResetTime:            GMC power restore and GMC reset time to calculate data reconnection latency. Unit in ns. 
 ulMinimumNClk:                    Minimum NCLK speed among all NB-Pstates to calcualte data reconnection latency. Unit in 10kHz. 
 ulIdleNClk:                       NCLK speed while memory runs in self-refresh state. Unit in 10kHz.
 ulDDR_DLL_PowerUpTime:            DDR PHY DLL power up time. Unit in ns.
 ulDDR_PLL_PowerUpTime:            DDR PHY PLL power up time. Unit in ns.
-usPCIEClkSSPercentage:            PCIE Clock Spred Spectrum Percentage in unit 0.01%; 100 mean 1%.
-usPCIEClkSSType:                  PCIE Clock Spred Spectrum Type. 0 for Down spread(default); 1 for Center spread.
+usPCIEClkSSPercentage:            PCIE Clock Spread Spectrum Percentage in unit 0.01%; 100 mean 1%.
+usPCIEClkSSType:                  PCIE Clock Spread Spectrum Type. 0 for Down spread(default); 1 for Center spread.
 usLvdsSSPercentage:               LVDS panel ( not include eDP ) Spread Spectrum Percentage in unit of 0.01%, =0, use VBIOS default setting. 
 usLvdsSSpreadRateIn10Hz:          LVDS panel ( not include eDP ) Spread Spectrum frequency in unit of 10Hz, =0, use VBIOS default setting. 
 usHDMISSPercentage:               HDMI Spread Spectrum Percentage in unit 0.01%; 100 mean 1%,  =0, use VBIOS default setting. 
@@ -4555,7 +4555,7 @@
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LITEAC 3
 #define ATOM_S0_SYSTEM_POWER_STATE_VALUE_LIT2AC 4
 
-//Byte aligned defintion for BIOS usage
+//Byte aligned definition 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)
@@ -4621,7 +4621,7 @@
 #define ATOM_S2_DISPLAY_ROTATION_ANGLE_MASK   0xC0000000L
 
 
-//Byte aligned defintion for BIOS usage
+//Byte aligned definition for BIOS usage
 #define ATOM_S2_TV1_STANDARD_MASKb0     0x0F
 #define ATOM_S2_CURRENT_BL_LEVEL_MASKb1 0xFF
 #define ATOM_S2_DEVICE_DPMS_STATEb2     0x01
@@ -4671,7 +4671,7 @@
 #define ATOM_S3_ALLOW_FAST_PWR_SWITCH   0x40000000L
 #define ATOM_S3_RQST_GPU_USE_MIN_PWR    0x80000000L
 
-//Byte aligned defintion for BIOS usage
+//Byte aligned definition for BIOS usage
 #define ATOM_S3_CRT1_ACTIVEb0           0x01
 #define ATOM_S3_LCD1_ACTIVEb0           0x02
 #define ATOM_S3_TV1_ACTIVEb0            0x04
@@ -4707,7 +4707,7 @@
 #define ATOM_S4_LCD1_REFRESH_MASK       0x0000FF00L
 #define ATOM_S4_LCD1_REFRESH_SHIFT      8
 
-//Byte aligned defintion for BIOS usage
+//Byte aligned definition 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
@@ -4786,7 +4786,7 @@
 #define ATOM_S6_VRI_BRIGHTNESS_CHANGE       0x40000000L
 #define ATOM_S6_CONFIG_DISPLAY_CHANGE_MASK  0x80000000L
 
-//Byte aligned defintion for BIOS usage
+//Byte aligned definition for BIOS usage
 #define ATOM_S6_DEVICE_CHANGEb0         0x01
 #define ATOM_S6_SCALER_CHANGEb0         0x02
 #define ATOM_S6_LID_CHANGEb0            0x04
@@ -5027,7 +5027,7 @@
 
 typedef struct _MEMORY_CLEAN_UP_PARAMETERS
 {
-  USHORT  usMemoryStart;                //in 8Kb boundry, offset from memory base address
+  USHORT  usMemoryStart;                //in 8Kb boundary, offset from memory base address
   USHORT  usMemorySize;                 //8Kb blocks aligned
 }MEMORY_CLEAN_UP_PARAMETERS;
 #define MEMORY_CLEAN_UP_PS_ALLOCATION MEMORY_CLEAN_UP_PARAMETERS
@@ -6855,7 +6855,7 @@
 /**************************************************************************/
 
 
-// Following definitions are for compatiblity issue in different SW components. 
+// Following definitions are for compatibility issue in different SW components. 
 #define ATOM_MASTER_DATA_TABLE_REVISION   0x01
 #define Object_Info												Object_Header			
 #define	AdjustARB_SEQ											MC_InitParameter
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atom.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/atom.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/atom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/atom.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include "atom.h"
 #include "atom-names.h"
 #include "atom-bits.h"
+#include "radeon.h"
 
 #define ATOM_COND_ABOVE		0
 #define ATOM_COND_ABOVEOREQUAL	1
@@ -101,7 +102,9 @@
 static uint32_t atom_iio_execute(struct atom_context *ctx, int base,
 				 uint32_t index, uint32_t data)
 {
+	struct radeon_device *rdev = ctx->card->dev->dev_private;
 	uint32_t temp = 0xCDCDCDCD;
+
 	while (1)
 		switch (CU8(base)) {
 		case ATOM_IIO_NOP:
@@ -112,7 +115,8 @@
 			base += 3;
 			break;
 		case ATOM_IIO_WRITE:
-			(void)ctx->card->ioreg_read(ctx->card, CU16(base + 1));
+			if (rdev->family == CHIP_RV515)
+				(void)ctx->card->ioreg_read(ctx->card, CU16(base + 1));
 			ctx->card->ioreg_write(ctx->card, CU16(base + 1), temp);
 			base += 3;
 			break;
@@ -131,7 +135,7 @@
 		case ATOM_IIO_MOVE_INDEX:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((index >> CU8(base + 2)) &
 			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -141,7 +145,7 @@
 		case ATOM_IIO_MOVE_DATA:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((data >> CU8(base + 2)) &
 			     (0xFFFFFFFF >> (32 - CU8(base + 1)))) << CU8(base +
@@ -151,7 +155,7 @@
 		case ATOM_IIO_MOVE_ATTR:
 			temp &=
 			    ~((0xFFFFFFFF >> (32 - CU8(base + 1))) <<
-			      CU8(base + 2));
+			      CU8(base + 3));
 			temp |=
 			    ((ctx->
 			      io_attr >> CU8(base + 2)) & (0xFFFFFFFF >> (32 -
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2010 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 (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 COPYRIGHT HOLDER(S) 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:
+ *     Alex Deucher <alexander.deucher@amd.com>
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+
+/*
+ * evergreen cards need to use the 3D engine to blit data which requires
+ * quite a bit of hw state setup.  Rather than pull the whole 3D driver
+ * (which normally generates the 3D state) into the DRM, we opt to use
+ * statically generated state tables.  The regsiter state and shaders
+ * were hand generated to support blitting functionality.  See the 3D
+ * driver or documentation for descriptions of the registers and
+ * shader instructions.
+ */
+
+const u32 cayman_default_state[] =
+{
+	/* XXX fill in additional blit state */
+
+	0xc0026900,
+	0x00000316,
+	0x0000000e, /* VGT_VERTEX_REUSE_BLOCK_CNTL */
+	0x00000010, /*  */
+
+	0xc0026900,
+	0x000000d9,
+	0x00000000, /* CP_RINGID */
+	0x00000000, /* CP_VMID */
+};
+
+const u32 cayman_default_size = ARRAY_SIZE(cayman_default_state);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/cayman_blit_shaders.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2010 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 (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 COPYRIGHT HOLDER(S) 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.
+ *
+ */
+
+#ifndef CAYMAN_BLIT_SHADERS_H
+#define CAYMAN_BLIT_SHADERS_H
+
+extern const u32 cayman_default_state[];
+
+extern const u32 cayman_default_size;
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreen_blit_kms.c	2011-05-19 00:06:34.000000000 -0400
@@ -579,7 +579,7 @@
 	obj_size += evergreen_ps_size * 4;
 	obj_size = ALIGN(obj_size, 256);
 
-	r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				&rdev->r600_blit.shader_obj);
 	if (r) {
 		DRM_ERROR("evergreen failed to allocate shader\n");
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreen.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreen.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,17 +43,6 @@
 
 void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
-	u32 tmp;
-
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(EVERGREEN_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
 	/* enable the pflip int */
 	radeon_irq_kms_pflip_irq_get(rdev, crtc);
 }
@@ -131,11 +120,16 @@
 	struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
 	struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;
 
-	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
-		if (voltage->voltage != rdev->pm.current_vddc) {
-			radeon_atom_set_voltage(rdev, voltage->voltage);
+	if (voltage->type == VOLTAGE_SW) {
+		if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
+			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
 			rdev->pm.current_vddc = voltage->voltage;
-			DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
+			DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
+		}
+		if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
+			radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
+			rdev->pm.current_vddci = voltage->vddci;
+			DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci);
 		}
 	}
 }
@@ -359,7 +353,7 @@
 					struct drm_display_mode *mode,
 					struct drm_display_mode *other_mode)
 {
-	u32 tmp = 0;
+	u32 tmp;
 	/*
 	 * Line Buffer Setup
 	 * There are 3 line buffers, each one shared by 2 display controllers.
@@ -369,64 +363,63 @@
 	 * first display controller
 	 *  0 - first half of lb (3840 * 2)
 	 *  1 - first 3/4 of lb (5760 * 2)
-	 *  2 - whole lb (7680 * 2)
+	 *  2 - whole lb (7680 * 2), other crtc must be disabled
 	 *  3 - first 1/4 of lb (1920 * 2)
 	 * second display controller
 	 *  4 - second half of lb (3840 * 2)
 	 *  5 - second 3/4 of lb (5760 * 2)
-	 *  6 - whole lb (7680 * 2)
+	 *  6 - whole lb (7680 * 2), other crtc must be disabled
 	 *  7 - last 1/4 of lb (1920 * 2)
 	 */
-	if (mode && other_mode) {
-		if (mode->hdisplay > other_mode->hdisplay) {
-			if (mode->hdisplay > 2560)
-				tmp = 1; /* 3/4 */
-			else
-				tmp = 0; /* 1/2 */
-		} else if (other_mode->hdisplay > mode->hdisplay) {
-			if (other_mode->hdisplay > 2560)
-				tmp = 3; /* 1/4 */
-			else
-				tmp = 0; /* 1/2 */
-		} else
+	/* this can get tricky if we have two large displays on a paired group
+	 * of crtcs.  Ideally for multiple large displays we'd assign them to
+	 * non-linked crtcs for maximum line buffer allocation.
+	 */
+	if (radeon_crtc->base.enabled && mode) {
+		if (other_mode)
 			tmp = 0; /* 1/2 */
-	} else if (mode)
-		tmp = 2; /* whole */
-	else if (other_mode)
-		tmp = 3; /* 1/4 */
+		else
+			tmp = 2; /* whole */
+	} else
+		tmp = 0;
 
 	/* second controller of the pair uses second half of the lb */
 	if (radeon_crtc->crtc_id % 2)
 		tmp += 4;
 	WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp);
 
-	switch (tmp) {
-	case 0:
-	case 4:
-	default:
-		if (ASIC_IS_DCE5(rdev))
-			return 4096 * 2;
-		else
-			return 3840 * 2;
-	case 1:
-	case 5:
-		if (ASIC_IS_DCE5(rdev))
-			return 6144 * 2;
-		else
-			return 5760 * 2;
-	case 2:
-	case 6:
-		if (ASIC_IS_DCE5(rdev))
-			return 8192 * 2;
-		else
-			return 7680 * 2;
-	case 3:
-	case 7:
-		if (ASIC_IS_DCE5(rdev))
-			return 2048 * 2;
-		else
-			return 1920 * 2;
+	if (radeon_crtc->base.enabled && mode) {
+		switch (tmp) {
+		case 0:
+		case 4:
+		default:
+			if (ASIC_IS_DCE5(rdev))
+				return 4096 * 2;
+			else
+				return 3840 * 2;
+		case 1:
+		case 5:
+			if (ASIC_IS_DCE5(rdev))
+				return 6144 * 2;
+			else
+				return 5760 * 2;
+		case 2:
+		case 6:
+			if (ASIC_IS_DCE5(rdev))
+				return 8192 * 2;
+			else
+				return 7680 * 2;
+		case 3:
+		case 7:
+			if (ASIC_IS_DCE5(rdev))
+				return 2048 * 2;
+			else
+				return 1920 * 2;
+		}
 	}
+
+	/* controller not enabled, so no lb used */
+	return 0;
 }
 
 static u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev)
@@ -804,7 +797,7 @@
 	}
 }
 
-static int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
+int evergreen_mc_wait_for_idle(struct radeon_device *rdev)
 {
 	unsigned i;
 	u32 tmp;
@@ -869,9 +862,15 @@
 		SYSTEM_ACCESS_MODE_NOT_IN_SYS |
 		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU |
 		EFFECTIVE_L1_TLB_SIZE(5) | EFFECTIVE_L1_QUEUE_SIZE(5);
-	WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
-	WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
-	WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	if (rdev->flags & RADEON_IS_IGP) {
+		WREG32(FUS_MC_VM_MD_L1_TLB0_CNTL, tmp);
+		WREG32(FUS_MC_VM_MD_L1_TLB1_CNTL, tmp);
+		WREG32(FUS_MC_VM_MD_L1_TLB2_CNTL, tmp);
+	} else {
+		WREG32(MC_VM_MD_L1_TLB0_CNTL, tmp);
+		WREG32(MC_VM_MD_L1_TLB1_CNTL, tmp);
+		WREG32(MC_VM_MD_L1_TLB2_CNTL, tmp);
+	}
 	WREG32(MC_VM_MB_L1_TLB0_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB1_CNTL, tmp);
 	WREG32(MC_VM_MB_L1_TLB2_CNTL, tmp);
@@ -957,7 +956,7 @@
 	WREG32(VM_CONTEXT1_CNTL, 0);
 }
 
-static void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
+void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save)
 {
 	save->vga_control[0] = RREG32(D1VGA_CONTROL);
 	save->vga_control[1] = RREG32(D2VGA_CONTROL);
@@ -1011,7 +1010,7 @@
 	WREG32(EVERGREEN_D6VGA_CONTROL, 0);
 }
 
-static void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
+void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save)
 {
 	WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + EVERGREEN_CRTC0_REGISTER_OFFSET,
 	       upper_32_bits(rdev->mc.vram_start));
@@ -1108,7 +1107,7 @@
 	WREG32(VGA_RENDER_CONTROL, save->vga_render_control);
 }
 
-static void evergreen_mc_program(struct radeon_device *rdev)
+void evergreen_mc_program(struct radeon_device *rdev)
 {
 	struct evergreen_mc_save save;
 	u32 tmp;
@@ -1781,7 +1780,10 @@
 
 
 	mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
-	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
+	if (rdev->flags & RADEON_IS_IGP)
+		mc_arb_ramcfg = RREG32(FUS_MC_ARB_RAMCFG);
+	else
+		mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
 
 	switch (rdev->config.evergreen.max_tile_pipes) {
 	case 1:
@@ -2576,7 +2578,7 @@
 	evergreen_disable_interrupt_state(rdev);
 }
 
-static void evergreen_irq_suspend(struct radeon_device *rdev)
+void evergreen_irq_suspend(struct radeon_device *rdev)
 {
 	evergreen_irq_disable(rdev);
 	r600_rlc_stop(rdev);
@@ -2587,7 +2589,7 @@
 	u32 wptr, tmp;
 
 	if (rdev->wb.enabled)
-		wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4];
+		wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]);
 	else
 		wptr = RREG32(IH_RB_WPTR);
 
@@ -2899,7 +2901,7 @@
 				return r;
 			}
 		}
-		r = btc_mc_load_microcode(rdev);
+		r = ni_mc_load_microcode(rdev);
 		if (r) {
 			DRM_ERROR("Failed to load MC firmware!\n");
 			return r;
@@ -2930,11 +2932,6 @@
 		rdev->asic->copy = NULL;
 		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
 	}
-	/* XXX: ontario has problems blitting to gart at the moment */
-	if (rdev->family == CHIP_PALM) {
-		rdev->asic->copy = NULL;
-		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
-	}
 
 	/* allocate wb buffer */
 	r = radeon_wb_init(rdev);
@@ -2981,13 +2978,13 @@
 
 	r = evergreen_startup(rdev);
 	if (r) {
-		DRM_ERROR("r600 startup failed on resume\n");
+		DRM_ERROR("evergreen startup failed on resume\n");
 		return r;
 	}
 
 	r = r600_ib_test(rdev);
 	if (r) {
-		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		DRM_ERROR("radeon: failed testing IB (%d).\n", r);
 		return r;
 	}
 
@@ -3047,9 +3044,6 @@
 {
 	int r;
 
-	r = radeon_dummy_page_init(rdev);
-	if (r)
-		return r;
 	/* This don't do much */
 	r = radeon_gem_init(rdev);
 	if (r)
@@ -3061,7 +3055,7 @@
 	}
 	/* Must be an ATOMBIOS */
 	if (!rdev->is_atom_bios) {
-		dev_err(rdev->dev, "Expecting atombios for R600 GPU\n");
+		dev_err(rdev->dev, "Expecting atombios for evergreen GPU\n");
 		return -EINVAL;
 	}
 	r = radeon_atombios_init(rdev);
@@ -3161,7 +3155,6 @@
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
-	radeon_dummy_page_fini(rdev);
 }
 
 static void evergreen_pcie_gen2_enable(struct radeon_device *rdev)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen_cs.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreen_cs.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreen_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include "radeon.h"
 #include "evergreend.h"
 #include "evergreen_reg_safe.h"
+#include "cayman_reg_safe.h"
 
 static int evergreen_cs_packet_next_reloc(struct radeon_cs_parser *p,
 					  struct radeon_cs_reloc **cs_reloc);
@@ -292,33 +293,28 @@
 	if (wait_reg_mem.type != PACKET_TYPE3 ||
 	    wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
 		DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
 	/* bit 4 is reg (0) or mem (1) */
 	if (wait_reg_mem_info & 0x10) {
 		DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	/* waiting for value to be equal */
 	if ((wait_reg_mem_info & 0x7) != 0x3) {
 		DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != EVERGREEN_VLINE_STATUS) {
 		DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != EVERGREEN_VLINE_STAT) {
 		DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	/* jump over the NOP */
@@ -336,8 +332,7 @@
 	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;
+		return -EINVAL;
 	}
 	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
@@ -362,12 +357,10 @@
 			break;
 		default:
 			DRM_ERROR("unknown crtc reloc\n");
-			r = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 	}
-out:
-	return r;
+	return 0;
 }
 
 static int evergreen_packet0_check(struct radeon_cs_parser *p,
@@ -425,21 +418,31 @@
 {
 	struct evergreen_cs_track *track = (struct evergreen_cs_track *)p->track;
 	struct radeon_cs_reloc *reloc;
-	u32 last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+	u32 last_reg;
 	u32 m, i, tmp, *ib;
 	int r;
 
+	if (p->rdev->family >= CHIP_CAYMAN)
+		last_reg = ARRAY_SIZE(cayman_reg_safe_bm);
+	else
+		last_reg = ARRAY_SIZE(evergreen_reg_safe_bm);
+
 	i = (reg >> 7);
 	if (i > last_reg) {
 		dev_warn(p->dev, "forbidden register 0x%08x at %d\n", reg, idx);
 		return -EINVAL;
 	}
 	m = 1 << ((reg >> 2) & 31);
-	if (!(evergreen_reg_safe_bm[i] & m))
-		return 0;
+	if (p->rdev->family >= CHIP_CAYMAN) {
+		if (!(cayman_reg_safe_bm[i] & m))
+			return 0;
+	} else {
+		if (!(evergreen_reg_safe_bm[i] & m))
+			return 0;
+	}
 	ib = p->ib->ptr;
 	switch (reg) {
-	/* force following reg to 0 in an attemp to disable out buffer
+	/* force following reg to 0 in an attempt to disable out buffer
 	 * which will need us to better understand how it works to perform
 	 * security check on it (Jerome)
 	 */
@@ -468,12 +471,42 @@
 	case SQ_VSTMP_RING_ITEMSIZE:
 	case VGT_TF_RING_SIZE:
 		/* get value to populate the IB don't remove */
-		tmp =radeon_get_ib_value(p, idx);
-		ib[idx] = 0;
+		/*tmp =radeon_get_ib_value(p, idx);
+		  ib[idx] = 0;*/
+		break;
+	case SQ_ESGS_RING_BASE:
+	case SQ_GSVS_RING_BASE:
+	case SQ_ESTMP_RING_BASE:
+	case SQ_GSTMP_RING_BASE:
+	case SQ_HSTMP_RING_BASE:
+	case SQ_LSTMP_RING_BASE:
+	case SQ_PSTMP_RING_BASE:
+	case SQ_VSTMP_RING_BASE:
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+					"0x%04X\n", reg);
+			return -EINVAL;
+		}
+		ib[idx] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff);
 		break;
 	case DB_DEPTH_CONTROL:
 		track->db_depth_control = radeon_get_ib_value(p, idx);
 		break;
+	case CAYMAN_DB_EQAA:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		break;
+	case CAYMAN_DB_DEPTH_INFO:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		break;
 	case DB_Z_INFO:
 		r = evergreen_cs_packet_next_reloc(p, &reloc);
 		if (r) {
@@ -559,9 +592,23 @@
 		track->cb_shader_mask = radeon_get_ib_value(p, idx);
 		break;
 	case PA_SC_AA_CONFIG:
+		if (p->rdev->family >= CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
 		tmp = radeon_get_ib_value(p, idx) & MSAA_NUM_SAMPLES_MASK;
 		track->nsamples = 1 << tmp;
 		break;
+	case CAYMAN_PA_SC_AA_CONFIG:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			dev_warn(p->dev, "bad SET_CONTEXT_REG "
+				 "0x%04X\n", reg);
+			return -EINVAL;
+		}
+		tmp = radeon_get_ib_value(p, idx) & CAYMAN_MSAA_NUM_SAMPLES_MASK;
+		track->nsamples = 1 << tmp;
+		break;
 	case CB_COLOR0_VIEW:
 	case CB_COLOR1_VIEW:
 	case CB_COLOR2_VIEW:
@@ -942,6 +989,37 @@
 	idx_value = radeon_get_ib_value(p, idx);
 
 	switch (pkt->opcode) {
+	case PACKET3_SET_PREDICATION:
+	{
+		int pred_op;
+		int tmp;
+		if (pkt->count != 1) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		tmp = radeon_get_ib_value(p, idx + 1);
+		pred_op = (tmp >> 16) & 0x7;
+
+		/* for the clear predicate operation */
+		if (pred_op == 0)
+			return 0;
+
+		if (pred_op > 2) {
+			DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
+			return -EINVAL;
+		}
+
+		r = evergreen_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+		ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);
+	}
+	break;
 	case PACKET3_CONTEXT_CONTROL:
 		if (pkt->count != 1) {
 			DRM_ERROR("bad CONTEXT_CONTROL\n");
@@ -954,6 +1032,16 @@
 		if (pkt->count) {
 			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
 			return -EINVAL;
+		}
+		break;
+	case CAYMAN_PACKET3_DEALLOC_STATE:
+		if (p->rdev->family < CHIP_CAYMAN) {
+			DRM_ERROR("bad PACKET3_DEALLOC_STATE\n");
+			return -EINVAL;
+		}
+		if (pkt->count) {
+			DRM_ERROR("bad INDEX_TYPE/NUM_INSTANCES/CLEAR_STATE\n");
+			return -EINVAL;
 		}
 		break;
 	case PACKET3_INDEX_BASE:
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreend.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreend.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/evergreend.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/evergreend.h	2011-05-19 00:06:34.000000000 -0400
@@ -200,6 +200,7 @@
 #define		BURSTLENGTH_SHIFT				9
 #define		BURSTLENGTH_MASK				0x00000200
 #define		CHANSIZE_OVERRIDE				(1 << 11)
+#define	FUS_MC_ARB_RAMCFG				0x2768
 #define	MC_VM_AGP_TOP					0x2028
 #define	MC_VM_AGP_BOT					0x202C
 #define	MC_VM_AGP_BASE					0x2030
@@ -221,6 +222,11 @@
 #define	MC_VM_MD_L1_TLB0_CNTL				0x2654
 #define	MC_VM_MD_L1_TLB1_CNTL				0x2658
 #define	MC_VM_MD_L1_TLB2_CNTL				0x265C
+
+#define	FUS_MC_VM_MD_L1_TLB0_CNTL			0x265C
+#define	FUS_MC_VM_MD_L1_TLB1_CNTL			0x2660
+#define	FUS_MC_VM_MD_L1_TLB2_CNTL			0x2664
+
 #define	MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR		0x203C
 #define	MC_VM_SYSTEM_APERTURE_HIGH_ADDR			0x2038
 #define	MC_VM_SYSTEM_APERTURE_LOW_ADDR			0x2034
@@ -755,13 +761,21 @@
 
 #define SQ_CONST_MEM_BASE				0x8df8
 
+#define SQ_ESGS_RING_BASE				0x8c40
 #define SQ_ESGS_RING_SIZE				0x8c44
+#define SQ_GSVS_RING_BASE				0x8c48
 #define SQ_GSVS_RING_SIZE				0x8c4c
+#define SQ_ESTMP_RING_BASE				0x8c50
 #define SQ_ESTMP_RING_SIZE				0x8c54
+#define SQ_GSTMP_RING_BASE				0x8c58
 #define SQ_GSTMP_RING_SIZE				0x8c5c
+#define SQ_VSTMP_RING_BASE				0x8c60
 #define SQ_VSTMP_RING_SIZE				0x8c64
+#define SQ_PSTMP_RING_BASE				0x8c68
 #define SQ_PSTMP_RING_SIZE				0x8c6c
+#define SQ_LSTMP_RING_BASE				0x8e10
 #define SQ_LSTMP_RING_SIZE				0x8e14
+#define SQ_HSTMP_RING_BASE				0x8e18
 #define SQ_HSTMP_RING_SIZE				0x8e1c
 #define VGT_TF_RING_SIZE				0x8988
 
@@ -1093,5 +1107,14 @@
 #define SQ_TEX_RESOURCE_WORD6_0                         0x30018
 #define SQ_TEX_RESOURCE_WORD7_0                         0x3001c
 
+/* cayman 3D regs */
+#define CAYMAN_VGT_OFFCHIP_LDS_BASE			0x89B0
+#define CAYMAN_DB_EQAA					0x28804
+#define CAYMAN_DB_DEPTH_INFO				0x2803C
+#define CAYMAN_PA_SC_AA_CONFIG				0x28BE0
+#define         CAYMAN_MSAA_NUM_SAMPLES_SHIFT           0
+#define         CAYMAN_MSAA_NUM_SAMPLES_MASK            0x7
+/* cayman packet3 addition */
+#define	CAYMAN_PACKET3_DEALLOC_STATE			0x14
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/Kconfig linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/Kconfig
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,7 @@
 config DRM_RADEON_KMS
 	bool "Enable modesetting on radeon by default - NEW DRIVER"
 	depends on DRM_RADEON
+	select BACKLIGHT_CLASS_DEVICE
 	help
 	  Choose this option if you want kernel modesetting enabled by default.
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/Makefile linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/Makefile
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,9 @@
 $(obj)/evergreen_reg_safe.h: $(src)/reg_srcs/evergreen $(obj)/mkregtable
 	$(call if_changed,mkregtable)
 
+$(obj)/cayman_reg_safe.h: $(src)/reg_srcs/cayman $(obj)/mkregtable
+	$(call if_changed,mkregtable)
+
 $(obj)/r100.o: $(obj)/r100_reg_safe.h $(obj)/rn50_reg_safe.h
 
 $(obj)/r200.o: $(obj)/r200_reg_safe.h
@@ -50,7 +53,7 @@
 
 $(obj)/r600_cs.o: $(obj)/r600_reg_safe.h
 
-$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h
+$(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h $(obj)/cayman_reg_safe.h
 
 radeon-y := radeon_drv.o radeon_cp.o radeon_state.o radeon_mem.o \
 	radeon_irq.o r300_cmdbuf.o r600_cp.o
@@ -66,7 +69,7 @@
 	r200.o radeon_legacy_tv.o r600_cs.o r600_blit.o r600_blit_shaders.o \
 	r600_blit_kms.o radeon_pm.o atombios_dp.o r600_audio.o r600_hdmi.o \
 	evergreen.o evergreen_cs.o evergreen_blit_shaders.o evergreen_blit_kms.o \
-	radeon_trace_points.o ni.o
+	radeon_trace_points.o ni.o cayman_blit_shaders.o
 
 radeon-$(CONFIG_COMPAT) += radeon_ioc32.o
 radeon-$(CONFIG_VGA_SWITCHEROO) += radeon_atpx_handler.o
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/ni.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/ni.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/ni.c	2012-03-24 01:00:53.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/ni.c	2012-03-24 03:26:48.000000000 -0400
@@ -31,12 +31,25 @@
 #include "nid.h"
 #include "atom.h"
 #include "ni_reg.h"
+#include "cayman_blit_shaders.h"
+
+extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
+extern int evergreen_mc_wait_for_idle(struct radeon_device *rdev);
+extern void evergreen_mc_program(struct radeon_device *rdev);
+extern void evergreen_irq_suspend(struct radeon_device *rdev);
+extern int evergreen_mc_init(struct radeon_device *rdev);
 
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
 #define EVERGREEN_RLC_UCODE_SIZE 768
 #define BTC_MC_UCODE_SIZE 6024
 
+#define CAYMAN_PFP_UCODE_SIZE 2176
+#define CAYMAN_PM4_UCODE_SIZE 2176
+#define CAYMAN_RLC_UCODE_SIZE 1024
+#define CAYMAN_MC_UCODE_SIZE 6037
+
 /* Firmware Names */
 /*(DEBLOBBED)*/
 
@@ -138,12 +151,16 @@
 	{0x0000009f, 0x00916a00}
 };
 
-int btc_mc_load_microcode(struct radeon_device *rdev)
+static const u32 cayman_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
+	{/*(DEBLOBBED)*/}
+};
+
+int ni_mc_load_microcode(struct radeon_device *rdev)
 {
 	const __be32 *fw_data;
 	u32 mem_type, running, blackout = 0;
 	u32 *io_mc_regs;
-	int i;
+	int i, ucode_size, regs_size;
 
 	if (!rdev->mc_fw)
 		return -EINVAL;
@@ -151,13 +168,24 @@
 	switch (rdev->family) {
 	case CHIP_BARTS:
 		io_mc_regs = (u32 *)&barts_io_mc_regs;
+		ucode_size = BTC_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_TURKS:
 		io_mc_regs = (u32 *)&turks_io_mc_regs;
+		ucode_size = BTC_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
 		break;
 	case CHIP_CAICOS:
 	default:
 		io_mc_regs = (u32 *)&caicos_io_mc_regs;
+		ucode_size = BTC_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
+		break;
+	case CHIP_CAYMAN:
+		io_mc_regs = (u32 *)&cayman_io_mc_regs;
+		ucode_size = CAYMAN_MC_UCODE_SIZE;
+		regs_size = BTC_IO_MC_REGS_SIZE;
 		break;
 	}
 
@@ -175,13 +203,13 @@
 		WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
 
 		/* load mc io regs */
-		for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) {
+		for (i = 0; i < regs_size; i++) {
 			WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
 			WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
 		}
 		/* load the MC ucode */
 		fw_data = (const __be32 *)rdev->mc_fw->data;
-		for (i = 0; i < BTC_MC_UCODE_SIZE; i++)
+		for (i = 0; i < ucode_size; i++)
 			WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
 
 		/* put the engine back into the active state */
@@ -222,23 +250,38 @@
 	case CHIP_BARTS:
 		chip_name = "BARTS";
 		rlc_chip_name = "BTC";
+		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+		mc_req_size = BTC_MC_UCODE_SIZE * 4;
 		break;
 	case CHIP_TURKS:
 		chip_name = "TURKS";
 		rlc_chip_name = "BTC";
+		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+		mc_req_size = BTC_MC_UCODE_SIZE * 4;
 		break;
 	case CHIP_CAICOS:
 		chip_name = "CAICOS";
 		rlc_chip_name = "BTC";
+		pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
+		me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
+		mc_req_size = BTC_MC_UCODE_SIZE * 4;
+		break;
+	case CHIP_CAYMAN:
+		chip_name = "CAYMAN";
+		rlc_chip_name = "CAYMAN";
+		pfp_req_size = CAYMAN_PFP_UCODE_SIZE * 4;
+		me_req_size = CAYMAN_PM4_UCODE_SIZE * 4;
+		rlc_req_size = CAYMAN_RLC_UCODE_SIZE * 4;
+		mc_req_size = CAYMAN_MC_UCODE_SIZE * 4;
 		break;
 	default: BUG();
 	}
 
-	pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
-	me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
-	rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
-	mc_req_size = BTC_MC_UCODE_SIZE * 4;
-
 	DRM_INFO("Loading %s Microcode\n", chip_name);
 
 	snprintf(fw_name, sizeof(fw_name), "/*(DEBLOBBED)*/", chip_name);
@@ -305,3 +348,1204 @@
 	return err;
 }
 
+/*
+ * Core functions
+ */
+static u32 cayman_get_tile_pipe_to_backend_map(struct radeon_device *rdev,
+					       u32 num_tile_pipes,
+					       u32 num_backends_per_asic,
+					       u32 *backend_disable_mask_per_asic,
+					       u32 num_shader_engines)
+{
+	u32 backend_map = 0;
+	u32 enabled_backends_mask = 0;
+	u32 enabled_backends_count = 0;
+	u32 num_backends_per_se;
+	u32 cur_pipe;
+	u32 swizzle_pipe[CAYMAN_MAX_PIPES];
+	u32 cur_backend = 0;
+	u32 i;
+	bool force_no_swizzle;
+
+	/* force legal values */
+	if (num_tile_pipes < 1)
+		num_tile_pipes = 1;
+	if (num_tile_pipes > rdev->config.cayman.max_tile_pipes)
+		num_tile_pipes = rdev->config.cayman.max_tile_pipes;
+	if (num_shader_engines < 1)
+		num_shader_engines = 1;
+	if (num_shader_engines > rdev->config.cayman.max_shader_engines)
+		num_shader_engines = rdev->config.cayman.max_shader_engines;
+	if (num_backends_per_asic > num_shader_engines)
+		num_backends_per_asic = num_shader_engines;
+	if (num_backends_per_asic > (rdev->config.cayman.max_backends_per_se * num_shader_engines))
+		num_backends_per_asic = rdev->config.cayman.max_backends_per_se * num_shader_engines;
+
+	/* make sure we have the same number of backends per se */
+	num_backends_per_asic = ALIGN(num_backends_per_asic, num_shader_engines);
+	/* set up the number of backends per se */
+	num_backends_per_se = num_backends_per_asic / num_shader_engines;
+	if (num_backends_per_se > rdev->config.cayman.max_backends_per_se) {
+		num_backends_per_se = rdev->config.cayman.max_backends_per_se;
+		num_backends_per_asic = num_backends_per_se * num_shader_engines;
+	}
+
+	/* create enable mask and count for enabled backends */
+	for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) {
+		if (((*backend_disable_mask_per_asic >> i) & 1) == 0) {
+			enabled_backends_mask |= (1 << i);
+			++enabled_backends_count;
+		}
+		if (enabled_backends_count == num_backends_per_asic)
+			break;
+	}
+
+	/* force the backends mask to match the current number of backends */
+	if (enabled_backends_count != num_backends_per_asic) {
+		u32 this_backend_enabled;
+		u32 shader_engine;
+		u32 backend_per_se;
+
+		enabled_backends_mask = 0;
+		enabled_backends_count = 0;
+		*backend_disable_mask_per_asic = CAYMAN_MAX_BACKENDS_MASK;
+		for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) {
+			/* calc the current se */
+			shader_engine = i / rdev->config.cayman.max_backends_per_se;
+			/* calc the backend per se */
+			backend_per_se = i % rdev->config.cayman.max_backends_per_se;
+			/* default to not enabled */
+			this_backend_enabled = 0;
+			if ((shader_engine < num_shader_engines) &&
+			    (backend_per_se < num_backends_per_se))
+				this_backend_enabled = 1;
+			if (this_backend_enabled) {
+				enabled_backends_mask |= (1 << i);
+				*backend_disable_mask_per_asic &= ~(1 << i);
+				++enabled_backends_count;
+			}
+		}
+	}
+
+
+	memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * CAYMAN_MAX_PIPES);
+	switch (rdev->family) {
+	case CHIP_CAYMAN:
+		force_no_swizzle = true;
+		break;
+	default:
+		force_no_swizzle = false;
+		break;
+	}
+	if (force_no_swizzle) {
+		bool last_backend_enabled = false;
+
+		force_no_swizzle = false;
+		for (i = 0; i < CAYMAN_MAX_BACKENDS; ++i) {
+			if (((enabled_backends_mask >> i) & 1) == 1) {
+				if (last_backend_enabled)
+					force_no_swizzle = true;
+				last_backend_enabled = true;
+			} else
+				last_backend_enabled = false;
+		}
+	}
+
+	switch (num_tile_pipes) {
+	case 1:
+	case 3:
+	case 5:
+	case 7:
+		DRM_ERROR("odd number of pipes!\n");
+		break;
+	case 2:
+		swizzle_pipe[0] = 0;
+		swizzle_pipe[1] = 1;
+		break;
+	case 4:
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 1;
+			swizzle_pipe[3] = 3;
+		}
+		break;
+	case 6:
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 1;
+			swizzle_pipe[4] = 3;
+			swizzle_pipe[5] = 5;
+		}
+		break;
+	case 8:
+		if (force_no_swizzle) {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 1;
+			swizzle_pipe[2] = 2;
+			swizzle_pipe[3] = 3;
+			swizzle_pipe[4] = 4;
+			swizzle_pipe[5] = 5;
+			swizzle_pipe[6] = 6;
+			swizzle_pipe[7] = 7;
+		} else {
+			swizzle_pipe[0] = 0;
+			swizzle_pipe[1] = 2;
+			swizzle_pipe[2] = 4;
+			swizzle_pipe[3] = 6;
+			swizzle_pipe[4] = 1;
+			swizzle_pipe[5] = 3;
+			swizzle_pipe[6] = 5;
+			swizzle_pipe[7] = 7;
+		}
+		break;
+	}
+
+	for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) {
+		while (((1 << cur_backend) & enabled_backends_mask) == 0)
+			cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS;
+
+		backend_map |= (((cur_backend & 0xf) << (swizzle_pipe[cur_pipe] * 4)));
+
+		cur_backend = (cur_backend + 1) % CAYMAN_MAX_BACKENDS;
+	}
+
+	return backend_map;
+}
+
+static void cayman_program_channel_remap(struct radeon_device *rdev)
+{
+	u32 tcp_chan_steer_lo, tcp_chan_steer_hi, mc_shared_chremap, tmp;
+
+	tmp = RREG32(MC_SHARED_CHMAP);
+	switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
+	case 0:
+	case 1:
+	case 2:
+	case 3:
+	default:
+		/* default mapping */
+		mc_shared_chremap = 0x00fac688;
+		break;
+	}
+
+	switch (rdev->family) {
+	case CHIP_CAYMAN:
+	default:
+		//tcp_chan_steer_lo = 0x54763210
+		tcp_chan_steer_lo = 0x76543210;
+		tcp_chan_steer_hi = 0x0000ba98;
+		break;
+	}
+
+	WREG32(TCP_CHAN_STEER_LO, tcp_chan_steer_lo);
+	WREG32(TCP_CHAN_STEER_HI, tcp_chan_steer_hi);
+	WREG32(MC_SHARED_CHREMAP, mc_shared_chremap);
+}
+
+static u32 cayman_get_disable_mask_per_asic(struct radeon_device *rdev,
+					    u32 disable_mask_per_se,
+					    u32 max_disable_mask_per_se,
+					    u32 num_shader_engines)
+{
+	u32 disable_field_width_per_se = r600_count_pipe_bits(disable_mask_per_se);
+	u32 disable_mask_per_asic = disable_mask_per_se & max_disable_mask_per_se;
+
+	if (num_shader_engines == 1)
+		return disable_mask_per_asic;
+	else if (num_shader_engines == 2)
+		return disable_mask_per_asic | (disable_mask_per_asic << disable_field_width_per_se);
+	else
+		return 0xffffffff;
+}
+
+static void cayman_gpu_init(struct radeon_device *rdev)
+{
+	u32 cc_rb_backend_disable = 0;
+	u32 cc_gc_shader_pipe_config;
+	u32 gb_addr_config = 0;
+	u32 mc_shared_chmap, mc_arb_ramcfg;
+	u32 gb_backend_map;
+	u32 cgts_tcc_disable;
+	u32 sx_debug_1;
+	u32 smx_dc_ctl0;
+	u32 gc_user_shader_pipe_config;
+	u32 gc_user_rb_backend_disable;
+	u32 cgts_user_tcc_disable;
+	u32 cgts_sm_ctrl_reg;
+	u32 hdp_host_path_cntl;
+	u32 tmp;
+	int i, j;
+
+	switch (rdev->family) {
+	case CHIP_CAYMAN:
+	default:
+		rdev->config.cayman.max_shader_engines = 2;
+		rdev->config.cayman.max_pipes_per_simd = 4;
+		rdev->config.cayman.max_tile_pipes = 8;
+		rdev->config.cayman.max_simds_per_se = 12;
+		rdev->config.cayman.max_backends_per_se = 4;
+		rdev->config.cayman.max_texture_channel_caches = 8;
+		rdev->config.cayman.max_gprs = 256;
+		rdev->config.cayman.max_threads = 256;
+		rdev->config.cayman.max_gs_threads = 32;
+		rdev->config.cayman.max_stack_entries = 512;
+		rdev->config.cayman.sx_num_of_sets = 8;
+		rdev->config.cayman.sx_max_export_size = 256;
+		rdev->config.cayman.sx_max_export_pos_size = 64;
+		rdev->config.cayman.sx_max_export_smx_size = 192;
+		rdev->config.cayman.max_hw_contexts = 8;
+		rdev->config.cayman.sq_num_cf_insts = 2;
+
+		rdev->config.cayman.sc_prim_fifo_size = 0x100;
+		rdev->config.cayman.sc_hiz_tile_fifo_size = 0x30;
+		rdev->config.cayman.sc_earlyz_tile_fifo_size = 0x130;
+		break;
+	}
+
+	/* Initialize HDP */
+	for (i = 0, j = 0; i < 32; i++, j += 0x18) {
+		WREG32((0x2c14 + j), 0x00000000);
+		WREG32((0x2c18 + j), 0x00000000);
+		WREG32((0x2c1c + j), 0x00000000);
+		WREG32((0x2c20 + j), 0x00000000);
+		WREG32((0x2c24 + j), 0x00000000);
+	}
+
+	WREG32(GRBM_CNTL, GRBM_READ_TIMEOUT(0xff));
+
+	mc_shared_chmap = RREG32(MC_SHARED_CHMAP);
+	mc_arb_ramcfg = RREG32(MC_ARB_RAMCFG);
+
+	cc_rb_backend_disable = RREG32(CC_RB_BACKEND_DISABLE);
+	cc_gc_shader_pipe_config = RREG32(CC_GC_SHADER_PIPE_CONFIG);
+	cgts_tcc_disable = 0xff000000;
+	gc_user_rb_backend_disable = RREG32(GC_USER_RB_BACKEND_DISABLE);
+	gc_user_shader_pipe_config = RREG32(GC_USER_SHADER_PIPE_CONFIG);
+	cgts_user_tcc_disable = RREG32(CGTS_USER_TCC_DISABLE);
+
+	rdev->config.cayman.num_shader_engines = rdev->config.cayman.max_shader_engines;
+	tmp = ((~gc_user_shader_pipe_config) & INACTIVE_QD_PIPES_MASK) >> INACTIVE_QD_PIPES_SHIFT;
+	rdev->config.cayman.num_shader_pipes_per_simd = r600_count_pipe_bits(tmp);
+	rdev->config.cayman.num_tile_pipes = rdev->config.cayman.max_tile_pipes;
+	tmp = ((~gc_user_shader_pipe_config) & INACTIVE_SIMDS_MASK) >> INACTIVE_SIMDS_SHIFT;
+	rdev->config.cayman.num_simds_per_se = r600_count_pipe_bits(tmp);
+	tmp = ((~gc_user_rb_backend_disable) & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT;
+	rdev->config.cayman.num_backends_per_se = r600_count_pipe_bits(tmp);
+	tmp = (gc_user_rb_backend_disable & BACKEND_DISABLE_MASK) >> BACKEND_DISABLE_SHIFT;
+	rdev->config.cayman.backend_disable_mask_per_asic =
+		cayman_get_disable_mask_per_asic(rdev, tmp, CAYMAN_MAX_BACKENDS_PER_SE_MASK,
+						 rdev->config.cayman.num_shader_engines);
+	rdev->config.cayman.backend_map =
+		cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes,
+						    rdev->config.cayman.num_backends_per_se *
+						    rdev->config.cayman.num_shader_engines,
+						    &rdev->config.cayman.backend_disable_mask_per_asic,
+						    rdev->config.cayman.num_shader_engines);
+	tmp = ((~cgts_user_tcc_disable) & TCC_DISABLE_MASK) >> TCC_DISABLE_SHIFT;
+	rdev->config.cayman.num_texture_channel_caches = r600_count_pipe_bits(tmp);
+	tmp = (mc_arb_ramcfg & BURSTLENGTH_MASK) >> BURSTLENGTH_SHIFT;
+	rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256;
+	if (rdev->config.cayman.mem_max_burst_length_bytes > 512)
+		rdev->config.cayman.mem_max_burst_length_bytes = 512;
+	tmp = (mc_arb_ramcfg & NOOFCOLS_MASK) >> NOOFCOLS_SHIFT;
+	rdev->config.cayman.mem_row_size_in_kb = (4 * (1 << (8 + tmp))) / 1024;
+	if (rdev->config.cayman.mem_row_size_in_kb > 4)
+		rdev->config.cayman.mem_row_size_in_kb = 4;
+	/* XXX use MC settings? */
+	rdev->config.cayman.shader_engine_tile_size = 32;
+	rdev->config.cayman.num_gpus = 1;
+	rdev->config.cayman.multi_gpu_tile_size = 64;
+
+	//gb_addr_config = 0x02011003
+#if 0
+	gb_addr_config = RREG32(GB_ADDR_CONFIG);
+#else
+	gb_addr_config = 0;
+	switch (rdev->config.cayman.num_tile_pipes) {
+	case 1:
+	default:
+		gb_addr_config |= NUM_PIPES(0);
+		break;
+	case 2:
+		gb_addr_config |= NUM_PIPES(1);
+		break;
+	case 4:
+		gb_addr_config |= NUM_PIPES(2);
+		break;
+	case 8:
+		gb_addr_config |= NUM_PIPES(3);
+		break;
+	}
+
+	tmp = (rdev->config.cayman.mem_max_burst_length_bytes / 256) - 1;
+	gb_addr_config |= PIPE_INTERLEAVE_SIZE(tmp);
+	gb_addr_config |= NUM_SHADER_ENGINES(rdev->config.cayman.num_shader_engines - 1);
+	tmp = (rdev->config.cayman.shader_engine_tile_size / 16) - 1;
+	gb_addr_config |= SHADER_ENGINE_TILE_SIZE(tmp);
+	switch (rdev->config.cayman.num_gpus) {
+	case 1:
+	default:
+		gb_addr_config |= NUM_GPUS(0);
+		break;
+	case 2:
+		gb_addr_config |= NUM_GPUS(1);
+		break;
+	case 4:
+		gb_addr_config |= NUM_GPUS(2);
+		break;
+	}
+	switch (rdev->config.cayman.multi_gpu_tile_size) {
+	case 16:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(0);
+		break;
+	case 32:
+	default:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(1);
+		break;
+	case 64:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(2);
+		break;
+	case 128:
+		gb_addr_config |= MULTI_GPU_TILE_SIZE(3);
+		break;
+	}
+	switch (rdev->config.cayman.mem_row_size_in_kb) {
+	case 1:
+	default:
+		gb_addr_config |= ROW_SIZE(0);
+		break;
+	case 2:
+		gb_addr_config |= ROW_SIZE(1);
+		break;
+	case 4:
+		gb_addr_config |= ROW_SIZE(2);
+		break;
+	}
+#endif
+
+	tmp = (gb_addr_config & NUM_PIPES_MASK) >> NUM_PIPES_SHIFT;
+	rdev->config.cayman.num_tile_pipes = (1 << tmp);
+	tmp = (gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
+	rdev->config.cayman.mem_max_burst_length_bytes = (tmp + 1) * 256;
+	tmp = (gb_addr_config & NUM_SHADER_ENGINES_MASK) >> NUM_SHADER_ENGINES_SHIFT;
+	rdev->config.cayman.num_shader_engines = tmp + 1;
+	tmp = (gb_addr_config & NUM_GPUS_MASK) >> NUM_GPUS_SHIFT;
+	rdev->config.cayman.num_gpus = tmp + 1;
+	tmp = (gb_addr_config & MULTI_GPU_TILE_SIZE_MASK) >> MULTI_GPU_TILE_SIZE_SHIFT;
+	rdev->config.cayman.multi_gpu_tile_size = 1 << tmp;
+	tmp = (gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT;
+	rdev->config.cayman.mem_row_size_in_kb = 1 << tmp;
+
+	//gb_backend_map = 0x76541032;
+#if 0
+	gb_backend_map = RREG32(GB_BACKEND_MAP);
+#else
+	gb_backend_map =
+		cayman_get_tile_pipe_to_backend_map(rdev, rdev->config.cayman.num_tile_pipes,
+						    rdev->config.cayman.num_backends_per_se *
+						    rdev->config.cayman.num_shader_engines,
+						    &rdev->config.cayman.backend_disable_mask_per_asic,
+						    rdev->config.cayman.num_shader_engines);
+#endif
+	/* setup tiling info dword.  gb_addr_config is not adequate since it does
+	 * not have bank info, so create a custom tiling dword.
+	 * bits 3:0   num_pipes
+	 * bits 7:4   num_banks
+	 * bits 11:8  group_size
+	 * bits 15:12 row_size
+	 */
+	rdev->config.cayman.tile_config = 0;
+	switch (rdev->config.cayman.num_tile_pipes) {
+	case 1:
+	default:
+		rdev->config.cayman.tile_config |= (0 << 0);
+		break;
+	case 2:
+		rdev->config.cayman.tile_config |= (1 << 0);
+		break;
+	case 4:
+		rdev->config.cayman.tile_config |= (2 << 0);
+		break;
+	case 8:
+		rdev->config.cayman.tile_config |= (3 << 0);
+		break;
+	}
+	rdev->config.cayman.tile_config |=
+		((mc_arb_ramcfg & NOOFBANK_MASK) >> NOOFBANK_SHIFT) << 4;
+	rdev->config.cayman.tile_config |=
+		(gb_addr_config & PIPE_INTERLEAVE_SIZE_MASK) >> PIPE_INTERLEAVE_SIZE_SHIFT;
+	rdev->config.cayman.tile_config |=
+		((gb_addr_config & ROW_SIZE_MASK) >> ROW_SIZE_SHIFT) << 12;
+
+	WREG32(GB_BACKEND_MAP, gb_backend_map);
+	WREG32(GB_ADDR_CONFIG, gb_addr_config);
+	WREG32(DMIF_ADDR_CONFIG, gb_addr_config);
+	WREG32(HDP_ADDR_CONFIG, gb_addr_config);
+
+	cayman_program_channel_remap(rdev);
+
+	/* primary versions */
+	WREG32(CC_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+
+	WREG32(CGTS_TCC_DISABLE, cgts_tcc_disable);
+	WREG32(CGTS_SYS_TCC_DISABLE, cgts_tcc_disable);
+
+	/* user versions */
+	WREG32(GC_USER_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(GC_USER_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable);
+	WREG32(GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config);
+
+	WREG32(CGTS_USER_SYS_TCC_DISABLE, cgts_tcc_disable);
+	WREG32(CGTS_USER_TCC_DISABLE, cgts_tcc_disable);
+
+	/* reprogram the shader complex */
+	cgts_sm_ctrl_reg = RREG32(CGTS_SM_CTRL_REG);
+	for (i = 0; i < 16; i++)
+		WREG32(CGTS_SM_CTRL_REG, OVERRIDE);
+	WREG32(CGTS_SM_CTRL_REG, cgts_sm_ctrl_reg);
+
+	/* set HW defaults for 3D engine */
+	WREG32(CP_MEQ_THRESHOLDS, MEQ1_START(0x30) | MEQ2_START(0x60));
+
+	sx_debug_1 = RREG32(SX_DEBUG_1);
+	sx_debug_1 |= ENABLE_NEW_SMX_ADDRESS;
+	WREG32(SX_DEBUG_1, sx_debug_1);
+
+	smx_dc_ctl0 = RREG32(SMX_DC_CTL0);
+	smx_dc_ctl0 &= ~NUMBER_OF_SETS(0x1ff);
+	smx_dc_ctl0 |= NUMBER_OF_SETS(rdev->config.cayman.sx_num_of_sets);
+	WREG32(SMX_DC_CTL0, smx_dc_ctl0);
+
+	WREG32(SPI_CONFIG_CNTL_1, VTX_DONE_DELAY(4) | CRC_SIMD_ID_WADDR_DISABLE);
+
+	/* need to be explicitly zero-ed */
+	WREG32(VGT_OFFCHIP_LDS_BASE, 0);
+	WREG32(SQ_LSTMP_RING_BASE, 0);
+	WREG32(SQ_HSTMP_RING_BASE, 0);
+	WREG32(SQ_ESTMP_RING_BASE, 0);
+	WREG32(SQ_GSTMP_RING_BASE, 0);
+	WREG32(SQ_VSTMP_RING_BASE, 0);
+	WREG32(SQ_PSTMP_RING_BASE, 0);
+
+	WREG32(TA_CNTL_AUX, DISABLE_CUBE_ANISO);
+
+	WREG32(SX_EXPORT_BUFFER_SIZES, (COLOR_BUFFER_SIZE((rdev->config.cayman.sx_max_export_size / 4) - 1) |
+					POSITION_BUFFER_SIZE((rdev->config.cayman.sx_max_export_pos_size / 4) - 1) |
+					SMX_BUFFER_SIZE((rdev->config.cayman.sx_max_export_smx_size / 4) - 1)));
+
+	WREG32(PA_SC_FIFO_SIZE, (SC_PRIM_FIFO_SIZE(rdev->config.cayman.sc_prim_fifo_size) |
+				 SC_HIZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_hiz_tile_fifo_size) |
+				 SC_EARLYZ_TILE_FIFO_SIZE(rdev->config.cayman.sc_earlyz_tile_fifo_size)));
+
+
+	WREG32(VGT_NUM_INSTANCES, 1);
+
+	WREG32(CP_PERFMON_CNTL, 0);
+
+	WREG32(SQ_MS_FIFO_SIZES, (CACHE_FIFO_SIZE(16 * rdev->config.cayman.sq_num_cf_insts) |
+				  FETCH_FIFO_HIWATER(0x4) |
+				  DONE_FIFO_HIWATER(0xe0) |
+				  ALU_UPDATE_FIFO_HIWATER(0x8)));
+
+	WREG32(SQ_GPR_RESOURCE_MGMT_1, NUM_CLAUSE_TEMP_GPRS(4));
+	WREG32(SQ_CONFIG, (VC_ENABLE |
+			   EXPORT_SRC_C |
+			   GFX_PRIO(0) |
+			   CS1_PRIO(0) |
+			   CS2_PRIO(1)));
+	WREG32(SQ_DYN_GPR_CNTL_PS_FLUSH_REQ, DYN_GPR_ENABLE);
+
+	WREG32(PA_SC_FORCE_EOV_MAX_CNTS, (FORCE_EOV_MAX_CLK_CNT(4095) |
+					  FORCE_EOV_MAX_REZ_CNT(255)));
+
+	WREG32(VGT_CACHE_INVALIDATION, CACHE_INVALIDATION(VC_AND_TC) |
+	       AUTO_INVLD_EN(ES_AND_GS_AUTO));
+
+	WREG32(VGT_GS_VERTEX_REUSE, 16);
+	WREG32(PA_SC_LINE_STIPPLE_STATE, 0);
+
+	WREG32(CB_PERF_CTR0_SEL_0, 0);
+	WREG32(CB_PERF_CTR0_SEL_1, 0);
+	WREG32(CB_PERF_CTR1_SEL_0, 0);
+	WREG32(CB_PERF_CTR1_SEL_1, 0);
+	WREG32(CB_PERF_CTR2_SEL_0, 0);
+	WREG32(CB_PERF_CTR2_SEL_1, 0);
+	WREG32(CB_PERF_CTR3_SEL_0, 0);
+	WREG32(CB_PERF_CTR3_SEL_1, 0);
+
+	hdp_host_path_cntl = RREG32(HDP_HOST_PATH_CNTL);
+	WREG32(HDP_HOST_PATH_CNTL, hdp_host_path_cntl);
+
+	WREG32(PA_CL_ENHANCE, CLIP_VTX_REORDER_ENA | NUM_CLIP_SEQ(3));
+
+	udelay(50);
+}
+
+/*
+ * GART
+ */
+void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev)
+{
+	/* flush hdp cache */
+	WREG32(HDP_MEM_COHERENCY_FLUSH_CNTL, 0x1);
+
+	/* bits 0-7 are the VM contexts0-7 */
+	WREG32(VM_INVALIDATE_REQUEST, 1);
+}
+
+int cayman_pcie_gart_enable(struct radeon_device *rdev)
+{
+	int r;
+
+	if (rdev->gart.table.vram.robj == NULL) {
+		dev_err(rdev->dev, "No VRAM object for PCIE GART.\n");
+		return -EINVAL;
+	}
+	r = radeon_gart_table_vram_pin(rdev);
+	if (r)
+		return r;
+	radeon_gart_restore(rdev);
+	/* Setup TLB control */
+	WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_TLB |
+	       ENABLE_L1_FRAGMENT_PROCESSING |
+	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_CACHE |
+	       ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
+	       EFFECTIVE_L2_QUEUE_SIZE(7) |
+	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
+	WREG32(VM_L2_CNTL2, INVALIDATE_ALL_L1_TLBS | INVALIDATE_L2_CACHE);
+	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
+	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
+	/* setup context0 */
+	WREG32(VM_CONTEXT0_PAGE_TABLE_START_ADDR, rdev->mc.gtt_start >> 12);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_END_ADDR, rdev->mc.gtt_end >> 12);
+	WREG32(VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, rdev->gart.table_addr >> 12);
+	WREG32(VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR,
+			(u32)(rdev->dummy_page.addr >> 12));
+	WREG32(VM_CONTEXT0_CNTL2, 0);
+	WREG32(VM_CONTEXT0_CNTL, ENABLE_CONTEXT | PAGE_TABLE_DEPTH(0) |
+				RANGE_PROTECTION_FAULT_ENABLE_DEFAULT);
+	/* disable context1-7 */
+	WREG32(VM_CONTEXT1_CNTL2, 0);
+	WREG32(VM_CONTEXT1_CNTL, 0);
+
+	cayman_pcie_gart_tlb_flush(rdev);
+	rdev->gart.ready = true;
+	return 0;
+}
+
+void cayman_pcie_gart_disable(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Disable all tables */
+	WREG32(VM_CONTEXT0_CNTL, 0);
+	WREG32(VM_CONTEXT1_CNTL, 0);
+	/* Setup TLB control */
+	WREG32(MC_VM_MX_L1_TLB_CNTL, ENABLE_L1_FRAGMENT_PROCESSING |
+	       SYSTEM_ACCESS_MODE_NOT_IN_SYS |
+	       SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU);
+	/* Setup L2 cache */
+	WREG32(VM_L2_CNTL, ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE |
+	       ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE |
+	       EFFECTIVE_L2_QUEUE_SIZE(7) |
+	       CONTEXT1_IDENTITY_ACCESS_MODE(1));
+	WREG32(VM_L2_CNTL2, 0);
+	WREG32(VM_L2_CNTL3, L2_CACHE_BIGK_ASSOCIATIVITY |
+	       L2_CACHE_BIGK_FRAGMENT_SIZE(6));
+	if (rdev->gart.table.vram.robj) {
+		r = radeon_bo_reserve(rdev->gart.table.vram.robj, false);
+		if (likely(r == 0)) {
+			radeon_bo_kunmap(rdev->gart.table.vram.robj);
+			radeon_bo_unpin(rdev->gart.table.vram.robj);
+			radeon_bo_unreserve(rdev->gart.table.vram.robj);
+		}
+	}
+}
+
+void cayman_pcie_gart_fini(struct radeon_device *rdev)
+{
+	cayman_pcie_gart_disable(rdev);
+	radeon_gart_table_vram_free(rdev);
+	radeon_gart_fini(rdev);
+}
+
+/*
+ * CP.
+ */
+static void cayman_cp_enable(struct radeon_device *rdev, bool enable)
+{
+	if (enable)
+		WREG32(CP_ME_CNTL, 0);
+	else {
+		radeon_ttm_set_active_vram_size(rdev, rdev->mc.visible_vram_size);
+		WREG32(CP_ME_CNTL, (CP_ME_HALT | CP_PFP_HALT));
+		WREG32(SCRATCH_UMSK, 0);
+	}
+}
+
+static int cayman_cp_load_microcode(struct radeon_device *rdev)
+{
+	const __be32 *fw_data;
+	int i;
+
+	if (!rdev->me_fw || !rdev->pfp_fw)
+		return -EINVAL;
+
+	cayman_cp_enable(rdev, false);
+
+	fw_data = (const __be32 *)rdev->pfp_fw->data;
+	WREG32(CP_PFP_UCODE_ADDR, 0);
+	for (i = 0; i < CAYMAN_PFP_UCODE_SIZE; i++)
+		WREG32(CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++));
+	WREG32(CP_PFP_UCODE_ADDR, 0);
+
+	fw_data = (const __be32 *)rdev->me_fw->data;
+	WREG32(CP_ME_RAM_WADDR, 0);
+	for (i = 0; i < CAYMAN_PM4_UCODE_SIZE; i++)
+		WREG32(CP_ME_RAM_DATA, be32_to_cpup(fw_data++));
+
+	WREG32(CP_PFP_UCODE_ADDR, 0);
+	WREG32(CP_ME_RAM_WADDR, 0);
+	WREG32(CP_ME_RAM_RADDR, 0);
+	return 0;
+}
+
+static int cayman_cp_start(struct radeon_device *rdev)
+{
+	int r, i;
+
+	r = radeon_ring_lock(rdev, 7);
+	if (r) {
+		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+		return r;
+	}
+	radeon_ring_write(rdev, PACKET3(PACKET3_ME_INITIALIZE, 5));
+	radeon_ring_write(rdev, 0x1);
+	radeon_ring_write(rdev, 0x0);
+	radeon_ring_write(rdev, rdev->config.cayman.max_hw_contexts - 1);
+	radeon_ring_write(rdev, PACKET3_ME_INITIALIZE_DEVICE_ID(1));
+	radeon_ring_write(rdev, 0);
+	radeon_ring_write(rdev, 0);
+	radeon_ring_unlock_commit(rdev);
+
+	cayman_cp_enable(rdev, true);
+
+	r = radeon_ring_lock(rdev, cayman_default_size + 19);
+	if (r) {
+		DRM_ERROR("radeon: cp failed to lock ring (%d).\n", r);
+		return r;
+	}
+
+	/* setup clear context state */
+	radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
+	radeon_ring_write(rdev, PACKET3_PREAMBLE_BEGIN_CLEAR_STATE);
+
+	for (i = 0; i < cayman_default_size; i++)
+		radeon_ring_write(rdev, cayman_default_state[i]);
+
+	radeon_ring_write(rdev, PACKET3(PACKET3_PREAMBLE_CNTL, 0));
+	radeon_ring_write(rdev, PACKET3_PREAMBLE_END_CLEAR_STATE);
+
+	/* set clear context state */
+	radeon_ring_write(rdev, PACKET3(PACKET3_CLEAR_STATE, 0));
+	radeon_ring_write(rdev, 0);
+
+	/* SQ_VTX_BASE_VTX_LOC */
+	radeon_ring_write(rdev, 0xc0026f00);
+	radeon_ring_write(rdev, 0x00000000);
+	radeon_ring_write(rdev, 0x00000000);
+	radeon_ring_write(rdev, 0x00000000);
+
+	/* Clear consts */
+	radeon_ring_write(rdev, 0xc0036f00);
+	radeon_ring_write(rdev, 0x00000bc4);
+	radeon_ring_write(rdev, 0xffffffff);
+	radeon_ring_write(rdev, 0xffffffff);
+	radeon_ring_write(rdev, 0xffffffff);
+
+	radeon_ring_write(rdev, 0xc0026900);
+	radeon_ring_write(rdev, 0x00000316);
+	radeon_ring_write(rdev, 0x0000000e); /* VGT_VERTEX_REUSE_BLOCK_CNTL */
+	radeon_ring_write(rdev, 0x00000010); /*  */
+
+	radeon_ring_unlock_commit(rdev);
+
+	/* XXX init other rings */
+
+	return 0;
+}
+
+static void cayman_cp_fini(struct radeon_device *rdev)
+{
+	cayman_cp_enable(rdev, false);
+	radeon_ring_fini(rdev);
+}
+
+int cayman_cp_resume(struct radeon_device *rdev)
+{
+	u32 tmp;
+	u32 rb_bufsz;
+	int r;
+
+	/* Reset cp; if cp is reset, then PA, SH, VGT also need to be reset */
+	WREG32(GRBM_SOFT_RESET, (SOFT_RESET_CP |
+				 SOFT_RESET_PA |
+				 SOFT_RESET_SH |
+				 SOFT_RESET_VGT |
+				 SOFT_RESET_SX));
+	RREG32(GRBM_SOFT_RESET);
+	mdelay(15);
+	WREG32(GRBM_SOFT_RESET, 0);
+	RREG32(GRBM_SOFT_RESET);
+
+	WREG32(CP_SEM_WAIT_TIMER, 0x4);
+
+	/* Set the write pointer delay */
+	WREG32(CP_RB_WPTR_DELAY, 0);
+
+	WREG32(CP_DEBUG, (1 << 27));
+
+	/* ring 0 - compute and gfx */
+	/* Set ring buffer size */
+	rb_bufsz = drm_order(rdev->cp.ring_size / 8);
+	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+	tmp |= BUF_SWAP_32BIT;
+#endif
+	WREG32(CP_RB0_CNTL, tmp);
+
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32(CP_RB0_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(CP_RB0_WPTR, 0);
+
+	/* set the wb address wether it's enabled or not */
+	WREG32(CP_RB0_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB0_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP_RPTR_OFFSET) & 0xFF);
+	WREG32(SCRATCH_ADDR, ((rdev->wb.gpu_addr + RADEON_WB_SCRATCH_OFFSET) >> 8) & 0xFFFFFFFF);
+
+	if (rdev->wb.enabled)
+		WREG32(SCRATCH_UMSK, 0xff);
+	else {
+		tmp |= RB_NO_UPDATE;
+		WREG32(SCRATCH_UMSK, 0);
+	}
+
+	mdelay(1);
+	WREG32(CP_RB0_CNTL, tmp);
+
+	WREG32(CP_RB0_BASE, rdev->cp.gpu_addr >> 8);
+
+	rdev->cp.rptr = RREG32(CP_RB0_RPTR);
+	rdev->cp.wptr = RREG32(CP_RB0_WPTR);
+
+	/* ring1  - compute only */
+	/* Set ring buffer size */
+	rb_bufsz = drm_order(rdev->cp1.ring_size / 8);
+	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+	tmp |= BUF_SWAP_32BIT;
+#endif
+	WREG32(CP_RB1_CNTL, tmp);
+
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32(CP_RB1_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(CP_RB1_WPTR, 0);
+
+	/* set the wb address wether it's enabled or not */
+	WREG32(CP_RB1_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB1_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP1_RPTR_OFFSET) & 0xFF);
+
+	mdelay(1);
+	WREG32(CP_RB1_CNTL, tmp);
+
+	WREG32(CP_RB1_BASE, rdev->cp1.gpu_addr >> 8);
+
+	rdev->cp1.rptr = RREG32(CP_RB1_RPTR);
+	rdev->cp1.wptr = RREG32(CP_RB1_WPTR);
+
+	/* ring2 - compute only */
+	/* Set ring buffer size */
+	rb_bufsz = drm_order(rdev->cp2.ring_size / 8);
+	tmp = (drm_order(RADEON_GPU_PAGE_SIZE/8) << 8) | rb_bufsz;
+#ifdef __BIG_ENDIAN
+	tmp |= BUF_SWAP_32BIT;
+#endif
+	WREG32(CP_RB2_CNTL, tmp);
+
+	/* Initialize the ring buffer's read and write pointers */
+	WREG32(CP_RB2_CNTL, tmp | RB_RPTR_WR_ENA);
+	WREG32(CP_RB2_WPTR, 0);
+
+	/* set the wb address wether it's enabled or not */
+	WREG32(CP_RB2_RPTR_ADDR, (rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFFFFFFFC);
+	WREG32(CP_RB2_RPTR_ADDR_HI, upper_32_bits(rdev->wb.gpu_addr + RADEON_WB_CP2_RPTR_OFFSET) & 0xFF);
+
+	mdelay(1);
+	WREG32(CP_RB2_CNTL, tmp);
+
+	WREG32(CP_RB2_BASE, rdev->cp2.gpu_addr >> 8);
+
+	rdev->cp2.rptr = RREG32(CP_RB2_RPTR);
+	rdev->cp2.wptr = RREG32(CP_RB2_WPTR);
+
+	/* start the rings */
+	cayman_cp_start(rdev);
+	rdev->cp.ready = true;
+	rdev->cp1.ready = true;
+	rdev->cp2.ready = true;
+	/* this only test cp0 */
+	r = radeon_ring_test(rdev);
+	if (r) {
+		rdev->cp.ready = false;
+		rdev->cp1.ready = false;
+		rdev->cp2.ready = false;
+		return r;
+	}
+
+	return 0;
+}
+
+bool cayman_gpu_is_lockup(struct radeon_device *rdev)
+{
+	u32 srbm_status;
+	u32 grbm_status;
+	u32 grbm_status_se0, grbm_status_se1;
+	struct r100_gpu_lockup *lockup = &rdev->config.cayman.lockup;
+	int r;
+
+	srbm_status = RREG32(SRBM_STATUS);
+	grbm_status = RREG32(GRBM_STATUS);
+	grbm_status_se0 = RREG32(GRBM_STATUS_SE0);
+	grbm_status_se1 = RREG32(GRBM_STATUS_SE1);
+	if (!(grbm_status & GUI_ACTIVE)) {
+		r100_gpu_lockup_update(lockup, &rdev->cp);
+		return false;
+	}
+	/* force CP activities */
+	r = radeon_ring_lock(rdev, 2);
+	if (!r) {
+		/* PACKET2 NOP */
+		radeon_ring_write(rdev, 0x80000000);
+		radeon_ring_write(rdev, 0x80000000);
+		radeon_ring_unlock_commit(rdev);
+	}
+	/* XXX deal with CP0,1,2 */
+	rdev->cp.rptr = RREG32(CP_RB0_RPTR);
+	return r100_gpu_cp_is_lockup(rdev, lockup, &rdev->cp);
+}
+
+static int cayman_gpu_soft_reset(struct radeon_device *rdev)
+{
+	struct evergreen_mc_save save;
+	u32 grbm_reset = 0;
+
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		return 0;
+
+	dev_info(rdev->dev, "GPU softreset \n");
+	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+		RREG32(GRBM_STATUS));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+		RREG32(GRBM_STATUS_SE0));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+		RREG32(GRBM_STATUS_SE1));
+	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+		RREG32(SRBM_STATUS));
+	evergreen_mc_stop(rdev, &save);
+	if (evergreen_mc_wait_for_idle(rdev)) {
+		dev_warn(rdev->dev, "Wait for MC idle timedout !\n");
+	}
+	/* Disable CP parsing/prefetching */
+	WREG32(CP_ME_CNTL, CP_ME_HALT | CP_PFP_HALT);
+
+	/* reset all the gfx blocks */
+	grbm_reset = (SOFT_RESET_CP |
+		      SOFT_RESET_CB |
+		      SOFT_RESET_DB |
+		      SOFT_RESET_GDS |
+		      SOFT_RESET_PA |
+		      SOFT_RESET_SC |
+		      SOFT_RESET_SPI |
+		      SOFT_RESET_SH |
+		      SOFT_RESET_SX |
+		      SOFT_RESET_TC |
+		      SOFT_RESET_TA |
+		      SOFT_RESET_VGT |
+		      SOFT_RESET_IA);
+
+	dev_info(rdev->dev, "  GRBM_SOFT_RESET=0x%08X\n", grbm_reset);
+	WREG32(GRBM_SOFT_RESET, grbm_reset);
+	(void)RREG32(GRBM_SOFT_RESET);
+	udelay(50);
+	WREG32(GRBM_SOFT_RESET, 0);
+	(void)RREG32(GRBM_SOFT_RESET);
+	/* Wait a little for things to settle down */
+	udelay(50);
+	dev_info(rdev->dev, "  GRBM_STATUS=0x%08X\n",
+		RREG32(GRBM_STATUS));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE0=0x%08X\n",
+		RREG32(GRBM_STATUS_SE0));
+	dev_info(rdev->dev, "  GRBM_STATUS_SE1=0x%08X\n",
+		RREG32(GRBM_STATUS_SE1));
+	dev_info(rdev->dev, "  SRBM_STATUS=0x%08X\n",
+		RREG32(SRBM_STATUS));
+	evergreen_mc_resume(rdev, &save);
+	return 0;
+}
+
+int cayman_asic_reset(struct radeon_device *rdev)
+{
+	return cayman_gpu_soft_reset(rdev);
+}
+
+static int cayman_startup(struct radeon_device *rdev)
+{
+	int r;
+
+	if (!rdev->me_fw || !rdev->pfp_fw || !rdev->rlc_fw || !rdev->mc_fw) {
+		r = ni_init_microcode(rdev);
+		if (r) {
+			DRM_ERROR("Failed to load firmware!\n");
+			return r;
+		}
+	}
+	r = ni_mc_load_microcode(rdev);
+	if (r) {
+		DRM_ERROR("Failed to load MC firmware!\n");
+		return r;
+	}
+
+	evergreen_mc_program(rdev);
+	r = cayman_pcie_gart_enable(rdev);
+	if (r)
+		return r;
+	cayman_gpu_init(rdev);
+
+#if 0
+	r = cayman_blit_init(rdev);
+	if (r) {
+		cayman_blit_fini(rdev);
+		rdev->asic->copy = NULL;
+		dev_warn(rdev->dev, "failed blitter (%d) falling back to memcpy\n", r);
+	}
+#endif
+
+	/* allocate wb buffer */
+	r = radeon_wb_init(rdev);
+	if (r)
+		return r;
+
+	/* Enable IRQ */
+	r = r600_irq_init(rdev);
+	if (r) {
+		DRM_ERROR("radeon: IH init failed (%d).\n", r);
+		radeon_irq_kms_fini(rdev);
+		return r;
+	}
+	evergreen_irq_set(rdev);
+
+	r = radeon_ring_init(rdev, rdev->cp.ring_size);
+	if (r)
+		return r;
+	r = cayman_cp_load_microcode(rdev);
+	if (r)
+		return r;
+	r = cayman_cp_resume(rdev);
+	if (r)
+		return r;
+
+	return 0;
+}
+
+int cayman_resume(struct radeon_device *rdev)
+{
+	int r;
+
+	/* Do not reset GPU before posting, on rv770 hw unlike on r500 hw,
+	 * posting will perform necessary task to bring back GPU into good
+	 * shape.
+	 */
+	/* post card */
+	atom_asic_init(rdev->mode_info.atom_context);
+
+	r = cayman_startup(rdev);
+	if (r) {
+		DRM_ERROR("cayman startup failed on resume\n");
+		return r;
+	}
+
+	r = r600_ib_test(rdev);
+	if (r) {
+		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		return r;
+	}
+
+	return r;
+
+}
+
+int cayman_suspend(struct radeon_device *rdev)
+{
+	/* int r; */
+
+	/* FIXME: we should wait for ring to be empty */
+	cayman_cp_enable(rdev, false);
+	rdev->cp.ready = false;
+	evergreen_irq_suspend(rdev);
+	radeon_wb_disable(rdev);
+	cayman_pcie_gart_disable(rdev);
+
+#if 0
+	/* unpin shaders bo */
+	r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false);
+	if (likely(r == 0)) {
+		radeon_bo_unpin(rdev->r600_blit.shader_obj);
+		radeon_bo_unreserve(rdev->r600_blit.shader_obj);
+	}
+#endif
+	return 0;
+}
+
+/* Plan is to move initialization in that function and use
+ * helper function so that radeon_device_init pretty much
+ * do nothing more than calling asic specific function. This
+ * should also allow to remove a bunch of callback function
+ * like vram_info.
+ */
+int cayman_init(struct radeon_device *rdev)
+{
+	int r;
+
+	/* This don't do much */
+	r = radeon_gem_init(rdev);
+	if (r)
+		return r;
+	/* Read BIOS */
+	if (!radeon_get_bios(rdev)) {
+		if (ASIC_IS_AVIVO(rdev))
+			return -EINVAL;
+	}
+	/* Must be an ATOMBIOS */
+	if (!rdev->is_atom_bios) {
+		dev_err(rdev->dev, "Expecting atombios for cayman GPU\n");
+		return -EINVAL;
+	}
+	r = radeon_atombios_init(rdev);
+	if (r)
+		return r;
+
+	/* Post card if necessary */
+	if (!radeon_card_posted(rdev)) {
+		if (!rdev->bios) {
+			dev_err(rdev->dev, "Card not posted and no BIOS - ignoring\n");
+			return -EINVAL;
+		}
+		DRM_INFO("GPU not posted. posting now...\n");
+		atom_asic_init(rdev->mode_info.atom_context);
+	}
+	/* Initialize scratch registers */
+	r600_scratch_init(rdev);
+	/* Initialize surface registers */
+	radeon_surface_init(rdev);
+	/* Initialize clocks */
+	radeon_get_clock_info(rdev->ddev);
+	/* Fence driver */
+	r = radeon_fence_driver_init(rdev);
+	if (r)
+		return r;
+	/* initialize memory controller */
+	r = evergreen_mc_init(rdev);
+	if (r)
+		return r;
+	/* Memory manager */
+	r = radeon_bo_init(rdev);
+	if (r)
+		return r;
+
+	r = radeon_irq_kms_init(rdev);
+	if (r)
+		return r;
+
+	rdev->cp.ring_obj = NULL;
+	r600_ring_init(rdev, 1024 * 1024);
+
+	rdev->ih.ring_obj = NULL;
+	r600_ih_ring_init(rdev, 64 * 1024);
+
+	r = r600_pcie_gart_init(rdev);
+	if (r)
+		return r;
+
+	rdev->accel_working = true;
+	r = cayman_startup(rdev);
+	if (r) {
+		dev_err(rdev->dev, "disabling GPU acceleration\n");
+		cayman_cp_fini(rdev);
+		r600_irq_fini(rdev);
+		radeon_wb_fini(rdev);
+		radeon_irq_kms_fini(rdev);
+		cayman_pcie_gart_fini(rdev);
+		rdev->accel_working = false;
+	}
+	if (rdev->accel_working) {
+		r = radeon_ib_pool_init(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r);
+			rdev->accel_working = false;
+		}
+		r = r600_ib_test(rdev);
+		if (r) {
+			DRM_ERROR("radeon: failed testing IB (%d).\n", r);
+			rdev->accel_working = false;
+		}
+	}
+
+	/* Don't start up if the MC ucode is missing.
+	 * The default clocks and voltages before the MC ucode
+	 * is loaded are not suffient for advanced operations.
+	 */
+	if (!rdev->mc_fw) {
+		DRM_ERROR("radeon: MC ucode required for NI+.\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+void cayman_fini(struct radeon_device *rdev)
+{
+	/* cayman_blit_fini(rdev); */
+	cayman_cp_fini(rdev);
+	r600_irq_fini(rdev);
+	radeon_wb_fini(rdev);
+	radeon_irq_kms_fini(rdev);
+	cayman_pcie_gart_fini(rdev);
+	radeon_gem_fini(rdev);
+	radeon_fence_driver_fini(rdev);
+	radeon_bo_fini(rdev);
+	radeon_atombios_fini(rdev);
+	kfree(rdev->bios);
+	rdev->bios = NULL;
+}
+
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/nid.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/nid.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/nid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/nid.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,101 @@
 #ifndef NI_H
 #define NI_H
 
+#define CAYMAN_MAX_SH_GPRS           256
+#define CAYMAN_MAX_TEMP_GPRS         16
+#define CAYMAN_MAX_SH_THREADS        256
+#define CAYMAN_MAX_SH_STACK_ENTRIES  4096
+#define CAYMAN_MAX_FRC_EOV_CNT       16384
+#define CAYMAN_MAX_BACKENDS          8
+#define CAYMAN_MAX_BACKENDS_MASK     0xFF
+#define CAYMAN_MAX_BACKENDS_PER_SE_MASK 0xF
+#define CAYMAN_MAX_SIMDS             16
+#define CAYMAN_MAX_SIMDS_MASK        0xFFFF
+#define CAYMAN_MAX_SIMDS_PER_SE_MASK 0xFFF
+#define CAYMAN_MAX_PIPES             8
+#define CAYMAN_MAX_PIPES_MASK        0xFF
+#define CAYMAN_MAX_LDS_NUM           0xFFFF
+#define CAYMAN_MAX_TCC               16
+#define CAYMAN_MAX_TCC_MASK          0xFF
+
+#define DMIF_ADDR_CONFIG  				0xBD4
+#define	SRBM_STATUS				        0x0E50
+
+#define VM_CONTEXT0_REQUEST_RESPONSE			0x1470
+#define		REQUEST_TYPE(x)					(((x) & 0xf) << 0)
+#define		RESPONSE_TYPE_MASK				0x000000F0
+#define		RESPONSE_TYPE_SHIFT				4
+#define VM_L2_CNTL					0x1400
+#define		ENABLE_L2_CACHE					(1 << 0)
+#define		ENABLE_L2_FRAGMENT_PROCESSING			(1 << 1)
+#define		ENABLE_L2_PTE_CACHE_LRU_UPDATE_BY_WRITE		(1 << 9)
+#define		ENABLE_L2_PDE0_CACHE_LRU_UPDATE_BY_WRITE	(1 << 10)
+#define		EFFECTIVE_L2_QUEUE_SIZE(x)			(((x) & 7) << 14)
+#define		CONTEXT1_IDENTITY_ACCESS_MODE(x)		(((x) & 3) << 18)
+/* CONTEXT1_IDENTITY_ACCESS_MODE
+ * 0 physical = logical
+ * 1 logical via context1 page table
+ * 2 inside identity aperture use translation, outside physical = logical
+ * 3 inside identity aperture physical = logical, outside use translation
+ */
+#define VM_L2_CNTL2					0x1404
+#define		INVALIDATE_ALL_L1_TLBS				(1 << 0)
+#define		INVALIDATE_L2_CACHE				(1 << 1)
+#define VM_L2_CNTL3					0x1408
+#define		BANK_SELECT(x)					((x) << 0)
+#define		CACHE_UPDATE_MODE(x)				((x) << 6)
+#define		L2_CACHE_BIGK_ASSOCIATIVITY			(1 << 20)
+#define		L2_CACHE_BIGK_FRAGMENT_SIZE(x)			((x) << 15)
+#define	VM_L2_STATUS					0x140C
+#define		L2_BUSY						(1 << 0)
+#define VM_CONTEXT0_CNTL				0x1410
+#define		ENABLE_CONTEXT					(1 << 0)
+#define		PAGE_TABLE_DEPTH(x)				(((x) & 3) << 1)
+#define		RANGE_PROTECTION_FAULT_ENABLE_DEFAULT		(1 << 4)
+#define VM_CONTEXT1_CNTL				0x1414
+#define VM_CONTEXT0_CNTL2				0x1430
+#define VM_CONTEXT1_CNTL2				0x1434
+#define VM_INVALIDATE_REQUEST				0x1478
+#define VM_INVALIDATE_RESPONSE				0x147c
+#define VM_CONTEXT0_PROTECTION_FAULT_DEFAULT_ADDR	0x1518
+#define VM_CONTEXT1_PROTECTION_FAULT_DEFAULT_ADDR	0x151c
+#define	VM_CONTEXT0_PAGE_TABLE_BASE_ADDR		0x153C
+#define	VM_CONTEXT0_PAGE_TABLE_START_ADDR		0x155C
+#define	VM_CONTEXT0_PAGE_TABLE_END_ADDR			0x157C
+
+#define MC_SHARED_CHMAP						0x2004
+#define		NOOFCHAN_SHIFT					12
+#define		NOOFCHAN_MASK					0x00003000
+#define MC_SHARED_CHREMAP					0x2008
+
+#define	MC_VM_SYSTEM_APERTURE_LOW_ADDR			0x2034
+#define	MC_VM_SYSTEM_APERTURE_HIGH_ADDR			0x2038
+#define	MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR		0x203C
+#define	MC_VM_MX_L1_TLB_CNTL				0x2064
+#define		ENABLE_L1_TLB					(1 << 0)
+#define		ENABLE_L1_FRAGMENT_PROCESSING			(1 << 1)
+#define		SYSTEM_ACCESS_MODE_PA_ONLY			(0 << 3)
+#define		SYSTEM_ACCESS_MODE_USE_SYS_MAP			(1 << 3)
+#define		SYSTEM_ACCESS_MODE_IN_SYS			(2 << 3)
+#define		SYSTEM_ACCESS_MODE_NOT_IN_SYS			(3 << 3)
+#define		SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU	(0 << 5)
+#define		ENABLE_ADVANCED_DRIVER_MODEL			(1 << 6)
+
 #define MC_SHARED_BLACKOUT_CNTL           		0x20ac
+#define	MC_ARB_RAMCFG					0x2760
+#define		NOOFBANK_SHIFT					0
+#define		NOOFBANK_MASK					0x00000003
+#define		NOOFRANK_SHIFT					2
+#define		NOOFRANK_MASK					0x00000004
+#define		NOOFROWS_SHIFT					3
+#define		NOOFROWS_MASK					0x00000038
+#define		NOOFCOLS_SHIFT					6
+#define		NOOFCOLS_MASK					0x000000C0
+#define		CHANSIZE_SHIFT					8
+#define		CHANSIZE_MASK					0x00000100
+#define		BURSTLENGTH_SHIFT				9
+#define		BURSTLENGTH_MASK				0x00000200
+#define		CHANSIZE_OVERRIDE				(1 << 11)
 #define MC_SEQ_SUP_CNTL           			0x28c8
 #define		RUN_MASK      				(1 << 0)
 #define MC_SEQ_SUP_PGM           			0x28cc
@@ -37,5 +131,406 @@
 #define MC_SEQ_IO_DEBUG_INDEX           		0x2a44
 #define MC_SEQ_IO_DEBUG_DATA           			0x2a48
 
+#define	HDP_HOST_PATH_CNTL				0x2C00
+#define	HDP_NONSURFACE_BASE				0x2C04
+#define	HDP_NONSURFACE_INFO				0x2C08
+#define	HDP_NONSURFACE_SIZE				0x2C0C
+#define HDP_ADDR_CONFIG  				0x2F48
+
+#define	CC_SYS_RB_BACKEND_DISABLE			0x3F88
+#define	GC_USER_SYS_RB_BACKEND_DISABLE			0x3F8C
+#define	CGTS_SYS_TCC_DISABLE				0x3F90
+#define	CGTS_USER_SYS_TCC_DISABLE			0x3F94
+
+#define	CONFIG_MEMSIZE					0x5428
+
+#define HDP_MEM_COHERENCY_FLUSH_CNTL			0x5480
+#define HDP_REG_COHERENCY_FLUSH_CNTL			0x54A0
+
+#define	GRBM_CNTL					0x8000
+#define		GRBM_READ_TIMEOUT(x)				((x) << 0)
+#define	GRBM_STATUS					0x8010
+#define		CMDFIFO_AVAIL_MASK				0x0000000F
+#define		RING2_RQ_PENDING				(1 << 4)
+#define		SRBM_RQ_PENDING					(1 << 5)
+#define		RING1_RQ_PENDING				(1 << 6)
+#define		CF_RQ_PENDING					(1 << 7)
+#define		PF_RQ_PENDING					(1 << 8)
+#define		GDS_DMA_RQ_PENDING				(1 << 9)
+#define		GRBM_EE_BUSY					(1 << 10)
+#define		SX_CLEAN					(1 << 11)
+#define		DB_CLEAN					(1 << 12)
+#define		CB_CLEAN					(1 << 13)
+#define		TA_BUSY 					(1 << 14)
+#define		GDS_BUSY 					(1 << 15)
+#define		VGT_BUSY_NO_DMA					(1 << 16)
+#define		VGT_BUSY					(1 << 17)
+#define		IA_BUSY_NO_DMA					(1 << 18)
+#define		IA_BUSY						(1 << 19)
+#define		SX_BUSY 					(1 << 20)
+#define		SH_BUSY 					(1 << 21)
+#define		SPI_BUSY					(1 << 22)
+#define		SC_BUSY 					(1 << 24)
+#define		PA_BUSY 					(1 << 25)
+#define		DB_BUSY 					(1 << 26)
+#define		CP_COHERENCY_BUSY      				(1 << 28)
+#define		CP_BUSY 					(1 << 29)
+#define		CB_BUSY 					(1 << 30)
+#define		GUI_ACTIVE					(1 << 31)
+#define	GRBM_STATUS_SE0					0x8014
+#define	GRBM_STATUS_SE1					0x8018
+#define		SE_SX_CLEAN					(1 << 0)
+#define		SE_DB_CLEAN					(1 << 1)
+#define		SE_CB_CLEAN					(1 << 2)
+#define		SE_VGT_BUSY					(1 << 23)
+#define		SE_PA_BUSY					(1 << 24)
+#define		SE_TA_BUSY					(1 << 25)
+#define		SE_SX_BUSY					(1 << 26)
+#define		SE_SPI_BUSY					(1 << 27)
+#define		SE_SH_BUSY					(1 << 28)
+#define		SE_SC_BUSY					(1 << 29)
+#define		SE_DB_BUSY					(1 << 30)
+#define		SE_CB_BUSY					(1 << 31)
+#define	GRBM_SOFT_RESET					0x8020
+#define		SOFT_RESET_CP					(1 << 0)
+#define		SOFT_RESET_CB					(1 << 1)
+#define		SOFT_RESET_DB					(1 << 3)
+#define		SOFT_RESET_GDS					(1 << 4)
+#define		SOFT_RESET_PA					(1 << 5)
+#define		SOFT_RESET_SC					(1 << 6)
+#define		SOFT_RESET_SPI					(1 << 8)
+#define		SOFT_RESET_SH					(1 << 9)
+#define		SOFT_RESET_SX					(1 << 10)
+#define		SOFT_RESET_TC					(1 << 11)
+#define		SOFT_RESET_TA					(1 << 12)
+#define		SOFT_RESET_VGT					(1 << 14)
+#define		SOFT_RESET_IA					(1 << 15)
+
+#define	SCRATCH_REG0					0x8500
+#define	SCRATCH_REG1					0x8504
+#define	SCRATCH_REG2					0x8508
+#define	SCRATCH_REG3					0x850C
+#define	SCRATCH_REG4					0x8510
+#define	SCRATCH_REG5					0x8514
+#define	SCRATCH_REG6					0x8518
+#define	SCRATCH_REG7					0x851C
+#define	SCRATCH_UMSK					0x8540
+#define	SCRATCH_ADDR					0x8544
+#define	CP_SEM_WAIT_TIMER				0x85BC
+#define CP_ME_CNTL					0x86D8
+#define		CP_ME_HALT					(1 << 28)
+#define		CP_PFP_HALT					(1 << 26)
+#define	CP_RB2_RPTR					0x86f8
+#define	CP_RB1_RPTR					0x86fc
+#define	CP_RB0_RPTR					0x8700
+#define	CP_RB_WPTR_DELAY				0x8704
+#define CP_MEQ_THRESHOLDS				0x8764
+#define		MEQ1_START(x)				((x) << 0)
+#define		MEQ2_START(x)				((x) << 8)
+#define	CP_PERFMON_CNTL					0x87FC
+
+#define	VGT_CACHE_INVALIDATION				0x88C4
+#define		CACHE_INVALIDATION(x)				((x) << 0)
+#define			VC_ONLY						0
+#define			TC_ONLY						1
+#define			VC_AND_TC					2
+#define		AUTO_INVLD_EN(x)				((x) << 6)
+#define			NO_AUTO						0
+#define			ES_AUTO						1
+#define			GS_AUTO						2
+#define			ES_AND_GS_AUTO					3
+#define	VGT_GS_VERTEX_REUSE				0x88D4
+
+#define CC_GC_SHADER_PIPE_CONFIG			0x8950
+#define	GC_USER_SHADER_PIPE_CONFIG			0x8954
+#define		INACTIVE_QD_PIPES(x)				((x) << 8)
+#define		INACTIVE_QD_PIPES_MASK				0x0000FF00
+#define		INACTIVE_QD_PIPES_SHIFT				8
+#define		INACTIVE_SIMDS(x)				((x) << 16)
+#define		INACTIVE_SIMDS_MASK				0xFFFF0000
+#define		INACTIVE_SIMDS_SHIFT				16
+
+#define VGT_PRIMITIVE_TYPE                              0x8958
+#define	VGT_NUM_INSTANCES				0x8974
+#define VGT_TF_RING_SIZE				0x8988
+#define VGT_OFFCHIP_LDS_BASE				0x89b4
+
+#define	PA_SC_LINE_STIPPLE_STATE			0x8B10
+#define	PA_CL_ENHANCE					0x8A14
+#define		CLIP_VTX_REORDER_ENA				(1 << 0)
+#define		NUM_CLIP_SEQ(x)					((x) << 1)
+#define	PA_SC_FIFO_SIZE					0x8BCC
+#define		SC_PRIM_FIFO_SIZE(x)				((x) << 0)
+#define		SC_HIZ_TILE_FIFO_SIZE(x)			((x) << 12)
+#define		SC_EARLYZ_TILE_FIFO_SIZE(x)			((x) << 20)
+#define	PA_SC_FORCE_EOV_MAX_CNTS			0x8B24
+#define		FORCE_EOV_MAX_CLK_CNT(x)			((x) << 0)
+#define		FORCE_EOV_MAX_REZ_CNT(x)			((x) << 16)
+
+#define	SQ_CONFIG					0x8C00
+#define		VC_ENABLE					(1 << 0)
+#define		EXPORT_SRC_C					(1 << 1)
+#define		GFX_PRIO(x)					((x) << 2)
+#define		CS1_PRIO(x)					((x) << 4)
+#define		CS2_PRIO(x)					((x) << 6)
+#define	SQ_GPR_RESOURCE_MGMT_1				0x8C04
+#define		NUM_PS_GPRS(x)					((x) << 0)
+#define		NUM_VS_GPRS(x)					((x) << 16)
+#define		NUM_CLAUSE_TEMP_GPRS(x)				((x) << 28)
+#define SQ_ESGS_RING_SIZE				0x8c44
+#define SQ_GSVS_RING_SIZE				0x8c4c
+#define SQ_ESTMP_RING_BASE				0x8c50
+#define SQ_ESTMP_RING_SIZE				0x8c54
+#define SQ_GSTMP_RING_BASE				0x8c58
+#define SQ_GSTMP_RING_SIZE				0x8c5c
+#define SQ_VSTMP_RING_BASE				0x8c60
+#define SQ_VSTMP_RING_SIZE				0x8c64
+#define SQ_PSTMP_RING_BASE				0x8c68
+#define SQ_PSTMP_RING_SIZE				0x8c6c
+#define	SQ_MS_FIFO_SIZES				0x8CF0
+#define		CACHE_FIFO_SIZE(x)				((x) << 0)
+#define		FETCH_FIFO_HIWATER(x)				((x) << 8)
+#define		DONE_FIFO_HIWATER(x)				((x) << 16)
+#define		ALU_UPDATE_FIFO_HIWATER(x)			((x) << 24)
+#define SQ_LSTMP_RING_BASE				0x8e10
+#define SQ_LSTMP_RING_SIZE				0x8e14
+#define SQ_HSTMP_RING_BASE				0x8e18
+#define SQ_HSTMP_RING_SIZE				0x8e1c
+#define	SQ_DYN_GPR_CNTL_PS_FLUSH_REQ    		0x8D8C
+#define		DYN_GPR_ENABLE					(1 << 8)
+#define SQ_CONST_MEM_BASE				0x8df8
+
+#define	SX_EXPORT_BUFFER_SIZES				0x900C
+#define		COLOR_BUFFER_SIZE(x)				((x) << 0)
+#define		POSITION_BUFFER_SIZE(x)				((x) << 8)
+#define		SMX_BUFFER_SIZE(x)				((x) << 16)
+#define	SX_DEBUG_1					0x9058
+#define		ENABLE_NEW_SMX_ADDRESS				(1 << 16)
+
+#define	SPI_CONFIG_CNTL					0x9100
+#define		GPR_WRITE_PRIORITY(x)				((x) << 0)
+#define	SPI_CONFIG_CNTL_1				0x913C
+#define		VTX_DONE_DELAY(x)				((x) << 0)
+#define		INTERP_ONE_PRIM_PER_ROW				(1 << 4)
+#define		CRC_SIMD_ID_WADDR_DISABLE			(1 << 8)
+
+#define	CGTS_TCC_DISABLE				0x9148
+#define	CGTS_USER_TCC_DISABLE				0x914C
+#define		TCC_DISABLE_MASK				0xFFFF0000
+#define		TCC_DISABLE_SHIFT				16
+#define	CGTS_SM_CTRL_REG				0x915C
+#define		OVERRIDE				(1 << 21)
+
+#define	TA_CNTL_AUX					0x9508
+#define		DISABLE_CUBE_WRAP				(1 << 0)
+#define		DISABLE_CUBE_ANISO				(1 << 1)
+
+#define	TCP_CHAN_STEER_LO				0x960c
+#define	TCP_CHAN_STEER_HI				0x9610
+
+#define CC_RB_BACKEND_DISABLE				0x98F4
+#define		BACKEND_DISABLE(x)     			((x) << 16)
+#define GB_ADDR_CONFIG  				0x98F8
+#define		NUM_PIPES(x)				((x) << 0)
+#define		NUM_PIPES_MASK				0x00000007
+#define		NUM_PIPES_SHIFT				0
+#define		PIPE_INTERLEAVE_SIZE(x)			((x) << 4)
+#define		PIPE_INTERLEAVE_SIZE_MASK		0x00000070
+#define		PIPE_INTERLEAVE_SIZE_SHIFT		4
+#define		BANK_INTERLEAVE_SIZE(x)			((x) << 8)
+#define		NUM_SHADER_ENGINES(x)			((x) << 12)
+#define		NUM_SHADER_ENGINES_MASK			0x00003000
+#define		NUM_SHADER_ENGINES_SHIFT		12
+#define		SHADER_ENGINE_TILE_SIZE(x)     		((x) << 16)
+#define		SHADER_ENGINE_TILE_SIZE_MASK		0x00070000
+#define		SHADER_ENGINE_TILE_SIZE_SHIFT		16
+#define		NUM_GPUS(x)     			((x) << 20)
+#define		NUM_GPUS_MASK				0x00700000
+#define		NUM_GPUS_SHIFT				20
+#define		MULTI_GPU_TILE_SIZE(x)     		((x) << 24)
+#define		MULTI_GPU_TILE_SIZE_MASK		0x03000000
+#define		MULTI_GPU_TILE_SIZE_SHIFT		24
+#define		ROW_SIZE(x)             		((x) << 28)
+#define		ROW_SIZE_MASK				0x30000007
+#define		ROW_SIZE_SHIFT				28
+#define		NUM_LOWER_PIPES(x)			((x) << 30)
+#define		NUM_LOWER_PIPES_MASK			0x40000000
+#define		NUM_LOWER_PIPES_SHIFT			30
+#define GB_BACKEND_MAP  				0x98FC
+
+#define CB_PERF_CTR0_SEL_0				0x9A20
+#define CB_PERF_CTR0_SEL_1				0x9A24
+#define CB_PERF_CTR1_SEL_0				0x9A28
+#define CB_PERF_CTR1_SEL_1				0x9A2C
+#define CB_PERF_CTR2_SEL_0				0x9A30
+#define CB_PERF_CTR2_SEL_1				0x9A34
+#define CB_PERF_CTR3_SEL_0				0x9A38
+#define CB_PERF_CTR3_SEL_1				0x9A3C
+
+#define	GC_USER_RB_BACKEND_DISABLE			0x9B7C
+#define		BACKEND_DISABLE_MASK			0x00FF0000
+#define		BACKEND_DISABLE_SHIFT			16
+
+#define	SMX_DC_CTL0					0xA020
+#define		USE_HASH_FUNCTION				(1 << 0)
+#define		NUMBER_OF_SETS(x)				((x) << 1)
+#define		FLUSH_ALL_ON_EVENT				(1 << 10)
+#define		STALL_ON_EVENT					(1 << 11)
+#define	SMX_EVENT_CTL					0xA02C
+#define		ES_FLUSH_CTL(x)					((x) << 0)
+#define		GS_FLUSH_CTL(x)					((x) << 3)
+#define		ACK_FLUSH_CTL(x)				((x) << 6)
+#define		SYNC_FLUSH_CTL					(1 << 8)
+
+#define	CP_RB0_BASE					0xC100
+#define	CP_RB0_CNTL					0xC104
+#define		RB_BUFSZ(x)					((x) << 0)
+#define		RB_BLKSZ(x)					((x) << 8)
+#define		RB_NO_UPDATE					(1 << 27)
+#define		RB_RPTR_WR_ENA					(1 << 31)
+#define		BUF_SWAP_32BIT					(2 << 16)
+#define	CP_RB0_RPTR_ADDR				0xC10C
+#define	CP_RB0_RPTR_ADDR_HI				0xC110
+#define	CP_RB0_WPTR					0xC114
+#define	CP_RB1_BASE					0xC180
+#define	CP_RB1_CNTL					0xC184
+#define	CP_RB1_RPTR_ADDR				0xC188
+#define	CP_RB1_RPTR_ADDR_HI				0xC18C
+#define	CP_RB1_WPTR					0xC190
+#define	CP_RB2_BASE					0xC194
+#define	CP_RB2_CNTL					0xC198
+#define	CP_RB2_RPTR_ADDR				0xC19C
+#define	CP_RB2_RPTR_ADDR_HI				0xC1A0
+#define	CP_RB2_WPTR					0xC1A4
+#define	CP_PFP_UCODE_ADDR				0xC150
+#define	CP_PFP_UCODE_DATA				0xC154
+#define	CP_ME_RAM_RADDR					0xC158
+#define	CP_ME_RAM_WADDR					0xC15C
+#define	CP_ME_RAM_DATA					0xC160
+#define	CP_DEBUG					0xC1FC
+
+/*
+ * PM4
+ */
+#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) & 0xFFFF) << 2)
+#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF)
+#define PACKET0(reg, n)	((PACKET_TYPE0 << 30) |				\
+			 (((reg) >> 2) & 0xFFFF) |			\
+			 ((n) & 0x3FFF) << 16)
+#define CP_PACKET2			0x80000000
+#define		PACKET2_PAD_SHIFT		0
+#define		PACKET2_PAD_MASK		(0x3fffffff << 0)
+
+#define PACKET2(v)	(CP_PACKET2 | REG_SET(PACKET2_PAD, (v)))
+
+#define PACKET3(op, n)	((PACKET_TYPE3 << 30) |				\
+			 (((op) & 0xFF) << 8) |				\
+			 ((n) & 0x3FFF) << 16)
+
+/* Packet 3 types */
+#define	PACKET3_NOP					0x10
+#define	PACKET3_SET_BASE				0x11
+#define	PACKET3_CLEAR_STATE				0x12
+#define	PACKET3_INDEX_BUFFER_SIZE			0x13
+#define	PACKET3_DEALLOC_STATE				0x14
+#define	PACKET3_DISPATCH_DIRECT				0x15
+#define	PACKET3_DISPATCH_INDIRECT			0x16
+#define	PACKET3_INDIRECT_BUFFER_END			0x17
+#define	PACKET3_SET_PREDICATION				0x20
+#define	PACKET3_REG_RMW					0x21
+#define	PACKET3_COND_EXEC				0x22
+#define	PACKET3_PRED_EXEC				0x23
+#define	PACKET3_DRAW_INDIRECT				0x24
+#define	PACKET3_DRAW_INDEX_INDIRECT			0x25
+#define	PACKET3_INDEX_BASE				0x26
+#define	PACKET3_DRAW_INDEX_2				0x27
+#define	PACKET3_CONTEXT_CONTROL				0x28
+#define	PACKET3_DRAW_INDEX_OFFSET			0x29
+#define	PACKET3_INDEX_TYPE				0x2A
+#define	PACKET3_DRAW_INDEX				0x2B
+#define	PACKET3_DRAW_INDEX_AUTO				0x2D
+#define	PACKET3_DRAW_INDEX_IMMD				0x2E
+#define	PACKET3_NUM_INSTANCES				0x2F
+#define	PACKET3_DRAW_INDEX_MULTI_AUTO			0x30
+#define	PACKET3_INDIRECT_BUFFER				0x32
+#define	PACKET3_STRMOUT_BUFFER_UPDATE			0x34
+#define	PACKET3_DRAW_INDEX_OFFSET_2			0x35
+#define	PACKET3_DRAW_INDEX_MULTI_ELEMENT		0x36
+#define	PACKET3_WRITE_DATA				0x37
+#define	PACKET3_MEM_SEMAPHORE				0x39
+#define	PACKET3_MPEG_INDEX				0x3A
+#define	PACKET3_WAIT_REG_MEM				0x3C
+#define	PACKET3_MEM_WRITE				0x3D
+#define	PACKET3_SURFACE_SYNC				0x43
+#              define PACKET3_CB0_DEST_BASE_ENA    (1 << 6)
+#              define PACKET3_CB1_DEST_BASE_ENA    (1 << 7)
+#              define PACKET3_CB2_DEST_BASE_ENA    (1 << 8)
+#              define PACKET3_CB3_DEST_BASE_ENA    (1 << 9)
+#              define PACKET3_CB4_DEST_BASE_ENA    (1 << 10)
+#              define PACKET3_CB5_DEST_BASE_ENA    (1 << 11)
+#              define PACKET3_CB6_DEST_BASE_ENA    (1 << 12)
+#              define PACKET3_CB7_DEST_BASE_ENA    (1 << 13)
+#              define PACKET3_DB_DEST_BASE_ENA     (1 << 14)
+#              define PACKET3_CB8_DEST_BASE_ENA    (1 << 15)
+#              define PACKET3_CB9_DEST_BASE_ENA    (1 << 16)
+#              define PACKET3_CB10_DEST_BASE_ENA   (1 << 17)
+#              define PACKET3_CB11_DEST_BASE_ENA   (1 << 18)
+#              define PACKET3_FULL_CACHE_ENA       (1 << 20)
+#              define PACKET3_TC_ACTION_ENA        (1 << 23)
+#              define PACKET3_CB_ACTION_ENA        (1 << 25)
+#              define PACKET3_DB_ACTION_ENA        (1 << 26)
+#              define PACKET3_SH_ACTION_ENA        (1 << 27)
+#              define PACKET3_SX_ACTION_ENA        (1 << 28)
+#define	PACKET3_ME_INITIALIZE				0x44
+#define		PACKET3_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16)
+#define	PACKET3_COND_WRITE				0x45
+#define	PACKET3_EVENT_WRITE				0x46
+#define	PACKET3_EVENT_WRITE_EOP				0x47
+#define	PACKET3_EVENT_WRITE_EOS				0x48
+#define	PACKET3_PREAMBLE_CNTL				0x4A
+#              define PACKET3_PREAMBLE_BEGIN_CLEAR_STATE     (2 << 28)
+#              define PACKET3_PREAMBLE_END_CLEAR_STATE       (3 << 28)
+#define	PACKET3_ALU_PS_CONST_BUFFER_COPY		0x4C
+#define	PACKET3_ALU_VS_CONST_BUFFER_COPY		0x4D
+#define	PACKET3_ALU_PS_CONST_UPDATE		        0x4E
+#define	PACKET3_ALU_VS_CONST_UPDATE		        0x4F
+#define	PACKET3_ONE_REG_WRITE				0x57
+#define	PACKET3_SET_CONFIG_REG				0x68
+#define		PACKET3_SET_CONFIG_REG_START			0x00008000
+#define		PACKET3_SET_CONFIG_REG_END			0x0000ac00
+#define	PACKET3_SET_CONTEXT_REG				0x69
+#define		PACKET3_SET_CONTEXT_REG_START			0x00028000
+#define		PACKET3_SET_CONTEXT_REG_END			0x00029000
+#define	PACKET3_SET_ALU_CONST				0x6A
+/* alu const buffers only; no reg file */
+#define	PACKET3_SET_BOOL_CONST				0x6B
+#define		PACKET3_SET_BOOL_CONST_START			0x0003a500
+#define		PACKET3_SET_BOOL_CONST_END			0x0003a518
+#define	PACKET3_SET_LOOP_CONST				0x6C
+#define		PACKET3_SET_LOOP_CONST_START			0x0003a200
+#define		PACKET3_SET_LOOP_CONST_END			0x0003a500
+#define	PACKET3_SET_RESOURCE				0x6D
+#define		PACKET3_SET_RESOURCE_START			0x00030000
+#define		PACKET3_SET_RESOURCE_END			0x00038000
+#define	PACKET3_SET_SAMPLER				0x6E
+#define		PACKET3_SET_SAMPLER_START			0x0003c000
+#define		PACKET3_SET_SAMPLER_END				0x0003c600
+#define	PACKET3_SET_CTL_CONST				0x6F
+#define		PACKET3_SET_CTL_CONST_START			0x0003cff0
+#define		PACKET3_SET_CTL_CONST_END			0x0003ff0c
+#define	PACKET3_SET_RESOURCE_OFFSET			0x70
+#define	PACKET3_SET_ALU_CONST_VS			0x71
+#define	PACKET3_SET_ALU_CONST_DI			0x72
+#define	PACKET3_SET_CONTEXT_REG_INDIRECT		0x73
+#define	PACKET3_SET_RESOURCE_INDIRECT			0x74
+#define	PACKET3_SET_APPEND_CNT			        0x75
+
 #endif
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r100.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r100.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r100.c	2012-03-24 01:00:37.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r100.c	2012-03-24 03:26:39.000000000 -0400
@@ -1199,14 +1199,12 @@
 	if (waitreloc.reg != RADEON_WAIT_UNTIL ||
 	    waitreloc.count != 0) {
 		DRM_ERROR("vline wait had illegal wait until segment\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	if (radeon_get_ib_value(p, waitreloc.idx + 1) != RADEON_WAIT_CRTC_VLINE) {
 		DRM_ERROR("vline wait had illegal wait until\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	/* jump over the NOP */
@@ -1224,8 +1222,7 @@
 	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;
+		return -EINVAL;
 	}
 	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
@@ -1247,14 +1244,13 @@
 			break;
 		default:
 			DRM_ERROR("unknown crtc reloc\n");
-			r = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 		ib[h_idx] = header;
 		ib[h_idx + 3] |= RADEON_ENG_DISPLAY_SELECT_CRTC1;
 	}
-out:
-	return r;
+
+	return 0;
 }
 
 /**
@@ -3615,7 +3611,7 @@
 	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",
+		DRM_ERROR("radeon: ib test failed (scratch(0x%04X)=0x%08X)\n",
 			  scratch, tmp);
 		r = -EINVAL;
 	}
@@ -3635,13 +3631,13 @@
 
 	r = radeon_ib_pool_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB pool (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB pool (%d).\n", r);
 		r100_ib_fini(rdev);
 		return r;
 	}
 	r = r100_ib_test(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled testing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed testing IB (%d).\n", r);
 		r100_ib_fini(rdev);
 		return r;
 	}
@@ -3797,12 +3793,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r300.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r300.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r300.c	2011-05-19 00:06:34.000000000 -0400
@@ -437,7 +437,7 @@
 	status = RREG32(R_000E40_RBBM_STATUS);
 	dev_info(rdev->dev, "(%s:%d) RBBM_STATUS=0x%08X\n", __func__, __LINE__, status);
 	/* resetting the CP seems to be problematic sometimes it end up
-	 * hard locking the computer, but it's necessary for successfull
+	 * hard locking the computer, but it's necessary for successful
 	 * reset more test & playing is needed on R3XX/R4XX to find a
 	 * reliable (if any solution)
 	 */
@@ -1401,12 +1401,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r300_reg.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r300_reg.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r300_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r300_reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -608,7 +608,7 @@
  * My guess is that there are two bits for each zbias primitive
  * (FILL, LINE, POINT).
  *  One to enable depth test and one for depth write.
- * Yet this doesnt explain why depth writes work ...
+ * Yet this doesn't explain why depth writes work ...
  */
 #define R300_RE_OCCLUSION_CNTL		    0x42B4
 #	define R300_OCCLUSION_ON		(1<<1)
@@ -817,7 +817,7 @@
 #	define R300_TX_MIN_FILTER_LINEAR_MIP_NEAREST        (6  <<  11)
 #	define R300_TX_MIN_FILTER_LINEAR_MIP_LINEAR         (10 <<  11)
 
-/* NOTE: NEAREST doesnt seem to exist.
+/* NOTE: NEAREST doesn't seem to exist.
  * Im not seting MAG_FILTER_MASK and (3 << 11) on for all
  * anisotropy modes because that would void selected mag filter
  */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r420.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r420.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r420.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r420.c	2011-05-19 00:06:34.000000000 -0400
@@ -260,13 +260,13 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r420_cp_errata_init(rdev);
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r520.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r520.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r520.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r520.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,12 +193,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_audio.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_audio.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_audio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_audio.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include "drmP.h"
 #include "radeon.h"
 #include "radeon_reg.h"
+#include "radeon_asic.h"
 #include "atom.h"
 
 #define AUDIO_TIMER_INTERVALL 100 /* 1/10 sekund should be enough */
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_blit_kms.c	2011-05-19 00:06:34.000000000 -0400
@@ -512,7 +512,7 @@
 	obj_size += r6xx_ps_size * 4;
 	obj_size = ALIGN(obj_size, 256);
 
-	r = radeon_bo_create(rdev, NULL, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_create(rdev, obj_size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				&rdev->r600_blit.shader_obj);
 	if (r) {
 		DRM_ERROR("r600 failed to allocate shader\n");
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600.c	2012-03-24 01:00:43.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600.c	2012-03-24 03:26:42.000000000 -0400
@@ -47,6 +47,7 @@
 #define EVERGREEN_PFP_UCODE_SIZE 1120
 #define EVERGREEN_PM4_UCODE_SIZE 1376
 #define EVERGREEN_RLC_UCODE_SIZE 768
+#define CAYMAN_RLC_UCODE_SIZE 1024
 
 /* Firmware Names */
 /*(DEBLOBBED)*/
@@ -550,7 +551,7 @@
 
 	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
 		if (voltage->voltage != rdev->pm.current_vddc) {
-			radeon_atom_set_voltage(rdev, voltage->voltage);
+			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
 			rdev->pm.current_vddc = voltage->voltage;
 			DRM_DEBUG_DRIVER("Setting: v: %d\n", voltage->voltage);
 		}
@@ -2427,7 +2428,7 @@
 
 	r = r600_ib_test(rdev);
 	if (r) {
-		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		DRM_ERROR("radeon: failed testing IB (%d).\n", r);
 		return r;
 	}
 
@@ -2472,9 +2473,6 @@
 {
 	int r;
 
-	r = radeon_dummy_page_init(rdev);
-	if (r)
-		return r;
 	if (r600_debugfs_mc_info_init(rdev)) {
 		DRM_ERROR("Failed to register debugfs file for mc !\n");
 	}
@@ -2588,7 +2586,6 @@
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
-	radeon_dummy_page_fini(rdev);
 }
 
 
@@ -2703,7 +2700,7 @@
 
 	/* Allocate ring buffer */
 	if (rdev->ih.ring_obj == NULL) {
-		r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size,
+		r = radeon_bo_create(rdev, rdev->ih.ring_size,
 				     PAGE_SIZE, true,
 				     RADEON_GEM_DOMAIN_GTT,
 				     &rdev->ih.ring_obj);
@@ -2784,13 +2781,20 @@
 	WREG32(RLC_HB_CNTL, 0);
 	WREG32(RLC_HB_RPTR, 0);
 	WREG32(RLC_HB_WPTR, 0);
-	WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
-	WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
+	if (rdev->family <= CHIP_CAICOS) {
+		WREG32(RLC_HB_WPTR_LSB_ADDR, 0);
+		WREG32(RLC_HB_WPTR_MSB_ADDR, 0);
+	}
 	WREG32(RLC_MC_CNTL, 0);
 	WREG32(RLC_UCODE_CNTL, 0);
 
 	fw_data = (const __be32 *)rdev->rlc_fw->data;
-	if (rdev->family >= CHIP_CEDAR) {
+	if (rdev->family >= CHIP_CAYMAN) {
+		for (i = 0; i < CAYMAN_RLC_UCODE_SIZE; i++) {
+			WREG32(RLC_UCODE_ADDR, i);
+			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
+		}
+	} else if (rdev->family >= CHIP_CEDAR) {
 		for (i = 0; i < EVERGREEN_RLC_UCODE_SIZE; i++) {
 			WREG32(RLC_UCODE_ADDR, i);
 			WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++));
@@ -3191,7 +3195,7 @@
 	u32 wptr, tmp;
 
 	if (rdev->wb.enabled)
-		wptr = rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4];
+		wptr = le32_to_cpu(rdev->wb.wb[R600_WB_IH_WPTR_OFFSET/4]);
 	else
 		wptr = RREG32(IH_RB_WPTR);
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_cs.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_cs.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,75 +71,167 @@
 	u64			db_bo_mc;
 };
 
+#define FMT_8_BIT(fmt, vc) [fmt] = { 1, 1, 1, vc }
+#define FMT_16_BIT(fmt, vc) [fmt] = { 1, 1, 2, vc }
+#define FMT_24_BIT(fmt) [fmt] = { 1, 1, 3, 0 }
+#define FMT_32_BIT(fmt, vc) [fmt] = { 1, 1, 4, vc }
+#define FMT_48_BIT(fmt) [fmt] = { 1, 1, 6, 0 }
+#define FMT_64_BIT(fmt, vc) [fmt] = { 1, 1, 8, vc }
+#define FMT_96_BIT(fmt) [fmt] = { 1, 1, 12, 0 }
+#define FMT_128_BIT(fmt, vc) [fmt] = { 1, 1, 16, vc }
+
+struct gpu_formats {
+	unsigned blockwidth;
+	unsigned blockheight;
+	unsigned blocksize;
+	unsigned valid_color;
+};
+
+static const struct gpu_formats color_formats_table[] = {
+	/* 8 bit */
+	FMT_8_BIT(V_038004_COLOR_8, 1),
+	FMT_8_BIT(V_038004_COLOR_4_4, 1),
+	FMT_8_BIT(V_038004_COLOR_3_3_2, 1),
+	FMT_8_BIT(V_038004_FMT_1, 0),
+
+	/* 16-bit */
+	FMT_16_BIT(V_038004_COLOR_16, 1),
+	FMT_16_BIT(V_038004_COLOR_16_FLOAT, 1),
+	FMT_16_BIT(V_038004_COLOR_8_8, 1),
+	FMT_16_BIT(V_038004_COLOR_5_6_5, 1),
+	FMT_16_BIT(V_038004_COLOR_6_5_5, 1),
+	FMT_16_BIT(V_038004_COLOR_1_5_5_5, 1),
+	FMT_16_BIT(V_038004_COLOR_4_4_4_4, 1),
+	FMT_16_BIT(V_038004_COLOR_5_5_5_1, 1),
+
+	/* 24-bit */
+	FMT_24_BIT(V_038004_FMT_8_8_8),
+					       
+	/* 32-bit */
+	FMT_32_BIT(V_038004_COLOR_32, 1),
+	FMT_32_BIT(V_038004_COLOR_32_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_16_16, 1),
+	FMT_32_BIT(V_038004_COLOR_16_16_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_8_24, 1),
+	FMT_32_BIT(V_038004_COLOR_8_24_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_24_8, 1),
+	FMT_32_BIT(V_038004_COLOR_24_8_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_10_11_11, 1),
+	FMT_32_BIT(V_038004_COLOR_10_11_11_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_11_11_10, 1),
+	FMT_32_BIT(V_038004_COLOR_11_11_10_FLOAT, 1),
+	FMT_32_BIT(V_038004_COLOR_2_10_10_10, 1),
+	FMT_32_BIT(V_038004_COLOR_8_8_8_8, 1),
+	FMT_32_BIT(V_038004_COLOR_10_10_10_2, 1),
+	FMT_32_BIT(V_038004_FMT_5_9_9_9_SHAREDEXP, 0),
+	FMT_32_BIT(V_038004_FMT_32_AS_8, 0),
+	FMT_32_BIT(V_038004_FMT_32_AS_8_8, 0),
+
+	/* 48-bit */
+	FMT_48_BIT(V_038004_FMT_16_16_16),
+	FMT_48_BIT(V_038004_FMT_16_16_16_FLOAT),
+
+	/* 64-bit */
+	FMT_64_BIT(V_038004_COLOR_X24_8_32_FLOAT, 1),
+	FMT_64_BIT(V_038004_COLOR_32_32, 1),
+	FMT_64_BIT(V_038004_COLOR_32_32_FLOAT, 1),
+	FMT_64_BIT(V_038004_COLOR_16_16_16_16, 1),
+	FMT_64_BIT(V_038004_COLOR_16_16_16_16_FLOAT, 1),
+
+	FMT_96_BIT(V_038004_FMT_32_32_32),
+	FMT_96_BIT(V_038004_FMT_32_32_32_FLOAT),
+
+	/* 128-bit */
+	FMT_128_BIT(V_038004_COLOR_32_32_32_32, 1),
+	FMT_128_BIT(V_038004_COLOR_32_32_32_32_FLOAT, 1),
+
+	[V_038004_FMT_GB_GR] = { 2, 1, 4, 0 },
+	[V_038004_FMT_BG_RG] = { 2, 1, 4, 0 },
+
+	/* block compressed formats */
+	[V_038004_FMT_BC1] = { 4, 4, 8, 0 },
+	[V_038004_FMT_BC2] = { 4, 4, 16, 0 },
+	[V_038004_FMT_BC3] = { 4, 4, 16, 0 },
+	[V_038004_FMT_BC4] = { 4, 4, 8, 0 },
+	[V_038004_FMT_BC5] = { 4, 4, 16, 0},
+
+};
+
+static inline bool fmt_is_valid_color(u32 format)
+{
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return false;
+	
+	if (color_formats_table[format].valid_color)
+		return true;
+
+	return false;
+}
+
+static inline bool fmt_is_valid_texture(u32 format)
+{
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return false;
+	
+	if (color_formats_table[format].blockwidth > 0)
+		return true;
+
+	return false;
+}
+
+static inline int fmt_get_blocksize(u32 format)
+{
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return 0;
+
+	return color_formats_table[format].blocksize;
+}
+
+static inline int fmt_get_nblocksx(u32 format, u32 w)
+{
+	unsigned bw;
+
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return 0;
+
+	bw = color_formats_table[format].blockwidth;
+	if (bw == 0)
+		return 0;
+
+	return (w + bw - 1) / bw;
+}
+
+static inline int fmt_get_nblocksy(u32 format, u32 h)
+{
+	unsigned bh;
+
+	if (format >= ARRAY_SIZE(color_formats_table))
+		return 0;
+
+	bh = color_formats_table[format].blockheight;
+	if (bh == 0)
+		return 0;
+
+	return (h + bh - 1) / bh;
+}
+
 static inline int r600_bpe_from_format(u32 *bpe, u32 format)
 {
-	switch (format) {
-	case V_038004_COLOR_8:
-	case V_038004_COLOR_4_4:
-	case V_038004_COLOR_3_3_2:
-	case V_038004_FMT_1:
-		*bpe = 1;
-		break;
-	case V_038004_COLOR_16:
-	case V_038004_COLOR_16_FLOAT:
-	case V_038004_COLOR_8_8:
-	case V_038004_COLOR_5_6_5:
-	case V_038004_COLOR_6_5_5:
-	case V_038004_COLOR_1_5_5_5:
-	case V_038004_COLOR_4_4_4_4:
-	case V_038004_COLOR_5_5_5_1:
-		*bpe = 2;
-		break;
-	case V_038004_FMT_8_8_8:
-		*bpe = 3;
-		break;
-	case V_038004_COLOR_32:
-	case V_038004_COLOR_32_FLOAT:
-	case V_038004_COLOR_16_16:
-	case V_038004_COLOR_16_16_FLOAT:
-	case V_038004_COLOR_8_24:
-	case V_038004_COLOR_8_24_FLOAT:
-	case V_038004_COLOR_24_8:
-	case V_038004_COLOR_24_8_FLOAT:
-	case V_038004_COLOR_10_11_11:
-	case V_038004_COLOR_10_11_11_FLOAT:
-	case V_038004_COLOR_11_11_10:
-	case V_038004_COLOR_11_11_10_FLOAT:
-	case V_038004_COLOR_2_10_10_10:
-	case V_038004_COLOR_8_8_8_8:
-	case V_038004_COLOR_10_10_10_2:
-	case V_038004_FMT_5_9_9_9_SHAREDEXP:
-	case V_038004_FMT_32_AS_8:
-	case V_038004_FMT_32_AS_8_8:
-		*bpe = 4;
-		break;
-	case V_038004_COLOR_X24_8_32_FLOAT:
-	case V_038004_COLOR_32_32:
-	case V_038004_COLOR_32_32_FLOAT:
-	case V_038004_COLOR_16_16_16_16:
-	case V_038004_COLOR_16_16_16_16_FLOAT:
-		*bpe = 8;
-		break;
-	case V_038004_FMT_16_16_16:
-	case V_038004_FMT_16_16_16_FLOAT:
-		*bpe = 6;
-		break;
-	case V_038004_FMT_32_32_32:
-	case V_038004_FMT_32_32_32_FLOAT:
-		*bpe = 12;
-		break;
-	case V_038004_COLOR_32_32_32_32:
-	case V_038004_COLOR_32_32_32_32_FLOAT:
-		*bpe = 16;
-		break;
-	case V_038004_FMT_GB_GR:
-	case V_038004_FMT_BG_RG:
-	case V_038004_COLOR_INVALID:
-	default:
-		*bpe = 16;
-		return -EINVAL;
-	}
+ 	unsigned res;
+
+	if (format >= ARRAY_SIZE(color_formats_table))
+		goto fail;
+
+	res = color_formats_table[format].blocksize;
+	if (res == 0)
+		goto fail;
+
+	*bpe = res;
 	return 0;
+
+fail:
+	*bpe = 16;
+	return -EINVAL;
 }
 
 struct array_mode_checker {
@@ -148,7 +240,7 @@
 	u32 nbanks;
 	u32 npipes;
 	u32 nsamples;
-	u32 bpe;
+	u32 blocksize;
 };
 
 /* returns alignment in pixels for pitch/height/depth and bytes for base */
@@ -162,7 +254,7 @@
 	u32 tile_height = 8;
 	u32 macro_tile_width = values->nbanks;
 	u32 macro_tile_height = values->npipes;
-	u32 tile_bytes = tile_width * tile_height * values->bpe * values->nsamples;
+	u32 tile_bytes = tile_width * tile_height * values->blocksize * values->nsamples;
 	u32 macro_tile_bytes = macro_tile_width * macro_tile_height * tile_bytes;
 
 	switch (values->array_mode) {
@@ -174,7 +266,7 @@
 		*base_align = 1;
 		break;
 	case ARRAY_LINEAR_ALIGNED:
-		*pitch_align = max((u32)64, (u32)(values->group_size / values->bpe));
+		*pitch_align = max((u32)64, (u32)(values->group_size / values->blocksize));
 		*height_align = tile_height;
 		*depth_align = 1;
 		*base_align = values->group_size;
@@ -182,7 +274,7 @@
 	case ARRAY_1D_TILED_THIN1:
 		*pitch_align = max((u32)tile_width,
 				   (u32)(values->group_size /
-					 (tile_height * values->bpe * values->nsamples)));
+					 (tile_height * values->blocksize * values->nsamples)));
 		*height_align = tile_height;
 		*depth_align = 1;
 		*base_align = values->group_size;
@@ -190,12 +282,12 @@
 	case ARRAY_2D_TILED_THIN1:
 		*pitch_align = max((u32)macro_tile_width,
 				  (u32)(((values->group_size / tile_height) /
-					 (values->bpe * values->nsamples)) *
+					 (values->blocksize * values->nsamples)) *
 					values->nbanks)) * tile_width;
 		*height_align = macro_tile_height * tile_height;
 		*depth_align = 1;
 		*base_align = max(macro_tile_bytes,
-				  (*pitch_align) * values->bpe * (*height_align) * values->nsamples);
+				  (*pitch_align) * values->blocksize * (*height_align) * values->nsamples);
 		break;
 	default:
 		return -EINVAL;
@@ -234,21 +326,22 @@
 static inline int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 {
 	struct r600_cs_track *track = p->track;
-	u32 bpe = 0, slice_tile_max, size, tmp;
+	u32 slice_tile_max, size, tmp;
 	u32 height, height_align, pitch, pitch_align, depth_align;
 	u64 base_offset, base_align;
 	struct array_mode_checker array_check;
 	volatile u32 *ib = p->ib->ptr;
 	unsigned array_mode;
-
+	u32 format;
 	if (G_0280A0_TILE_MODE(track->cb_color_info[i])) {
 		dev_warn(p->dev, "FMASK or CMASK buffer are not supported by this kernel\n");
 		return -EINVAL;
 	}
 	size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
-	if (r600_bpe_from_format(&bpe, G_0280A0_FORMAT(track->cb_color_info[i]))) {
+	format = G_0280A0_FORMAT(track->cb_color_info[i]);
+	if (!fmt_is_valid_color(format)) {
 		dev_warn(p->dev, "%s:%d cb invalid format %d for %d (0x%08X)\n",
-			 __func__, __LINE__, G_0280A0_FORMAT(track->cb_color_info[i]),
+			 __func__, __LINE__, format,
 			i, track->cb_color_info[i]);
 		return -EINVAL;
 	}
@@ -267,7 +360,7 @@
 	array_check.nbanks = track->nbanks;
 	array_check.npipes = track->npipes;
 	array_check.nsamples = track->nsamples;
-	array_check.bpe = bpe;
+	array_check.blocksize = fmt_get_blocksize(format);
 	if (r600_get_array_mode_alignment(&array_check,
 					  &pitch_align, &height_align, &depth_align, &base_align)) {
 		dev_warn(p->dev, "%s invalid tiling %d for %d (0x%08X)\n", __func__,
@@ -311,7 +404,7 @@
 	}
 
 	/* check offset */
-	tmp = height * pitch * bpe;
+	tmp = fmt_get_nblocksy(format, height) * fmt_get_nblocksx(format, pitch) * fmt_get_blocksize(format);
 	if ((tmp + track->cb_color_bo_offset[i]) > radeon_bo_size(track->cb_color_bo[i])) {
 		if (array_mode == V_0280A0_ARRAY_LINEAR_GENERAL) {
 			/* the initial DDX does bad things with the CB size occasionally */
@@ -436,7 +529,7 @@
 			array_check.nbanks = track->nbanks;
 			array_check.npipes = track->npipes;
 			array_check.nsamples = track->nsamples;
-			array_check.bpe = bpe;
+			array_check.blocksize = bpe;
 			if (r600_get_array_mode_alignment(&array_check,
 							  &pitch_align, &height_align, &depth_align, &base_align)) {
 				dev_warn(p->dev, "%s invalid tiling %d (0x%08X)\n", __func__,
@@ -687,33 +780,28 @@
 	if (wait_reg_mem.type != PACKET_TYPE3 ||
 	    wait_reg_mem.opcode != PACKET3_WAIT_REG_MEM) {
 		DRM_ERROR("vline wait missing WAIT_REG_MEM segment\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	wait_reg_mem_info = radeon_get_ib_value(p, wait_reg_mem.idx + 1);
 	/* bit 4 is reg (0) or mem (1) */
 	if (wait_reg_mem_info & 0x10) {
 		DRM_ERROR("vline WAIT_REG_MEM waiting on MEM rather than REG\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	/* waiting for value to be equal */
 	if ((wait_reg_mem_info & 0x7) != 0x3) {
 		DRM_ERROR("vline WAIT_REG_MEM function not equal\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 	if ((radeon_get_ib_value(p, wait_reg_mem.idx + 2) << 2) != AVIVO_D1MODE_VLINE_STATUS) {
 		DRM_ERROR("vline WAIT_REG_MEM bad reg\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	if (radeon_get_ib_value(p, wait_reg_mem.idx + 5) != AVIVO_D1MODE_VLINE_STAT) {
 		DRM_ERROR("vline WAIT_REG_MEM bad bit mask\n");
-		r = -EINVAL;
-		return r;
+		return -EINVAL;
 	}
 
 	/* jump over the NOP */
@@ -732,8 +820,7 @@
 	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;
+		return -EINVAL;
 	}
 	crtc = obj_to_crtc(obj);
 	radeon_crtc = to_radeon_crtc(crtc);
@@ -756,14 +843,13 @@
 			break;
 		default:
 			DRM_ERROR("unknown crtc reloc\n");
-			r = -EINVAL;
-			goto out;
+			return -EINVAL;
 		}
 		ib[h_idx] = header;
 		ib[h_idx + 4] = AVIVO_D2MODE_VLINE_STATUS >> 2;
 	}
-out:
-	return r;
+
+	return 0;
 }
 
 static int r600_packet0_check(struct radeon_cs_parser *p,
@@ -835,7 +921,7 @@
 		return 0;
 	ib = p->ib->ptr;
 	switch (reg) {
-	/* force following reg to 0 in an attemp to disable out buffer
+	/* force following reg to 0 in an attempt to disable out buffer
 	 * which will need us to better understand how it works to perform
 	 * security check on it (Jerome)
 	 */
@@ -1113,39 +1199,61 @@
 	return 0;
 }
 
-static inline unsigned minify(unsigned size, unsigned levels)
+static inline unsigned mip_minify(unsigned size, unsigned level)
 {
-	size = size >> levels;
-	if (size < 1)
-		size = 1;
-	return size;
+	unsigned val;
+
+	val = max(1U, size >> level);
+	if (level > 0)
+		val = roundup_pow_of_two(val);
+	return val;
 }
 
-static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned nlevels,
-			      unsigned w0, unsigned h0, unsigned d0, unsigned bpe,
-			      unsigned pitch_align,
+static void r600_texture_size(unsigned nfaces, unsigned blevel, unsigned llevel,
+			      unsigned w0, unsigned h0, unsigned d0, unsigned format,
+			      unsigned block_align, unsigned height_align, unsigned base_align,
 			      unsigned *l0_size, unsigned *mipmap_size)
 {
-	unsigned offset, i, level, face;
-	unsigned width, height, depth, rowstride, size;
+	unsigned offset, i, level;
+	unsigned width, height, depth, size;
+	unsigned blocksize;
+	unsigned nbx, nby;
+	unsigned nlevels = llevel - blevel + 1;
 
-	w0 = minify(w0, 0);
-	h0 = minify(h0, 0);
-	d0 = minify(d0, 0);
+	*l0_size = -1;
+	blocksize = fmt_get_blocksize(format);
+
+	w0 = mip_minify(w0, 0);
+	h0 = mip_minify(h0, 0);
+	d0 = mip_minify(d0, 0);
 	for(i = 0, offset = 0, level = blevel; i < nlevels; i++, level++) {
-		width = minify(w0, i);
-		height = minify(h0, i);
-		depth = minify(d0, i);
-		for(face = 0; face < nfaces; face++) {
-			rowstride = ALIGN((width * bpe), pitch_align);
-			size = height * rowstride * depth;
-			offset += size;
-			offset = (offset + 0x1f) & ~0x1f;
-		}
+		width = mip_minify(w0, i);
+		nbx = fmt_get_nblocksx(format, width);
+
+		nbx = round_up(nbx, block_align);
+
+		height = mip_minify(h0, i);
+		nby = fmt_get_nblocksy(format, height);
+		nby = round_up(nby, height_align);
+
+		depth = mip_minify(d0, i);
+
+		size = nbx * nby * blocksize;
+		if (nfaces)
+			size *= nfaces;
+		else
+			size *= depth;
+
+		if (i == 0)
+			*l0_size = size;
+
+		if (i == 0 || i == 1)
+			offset = round_up(offset, base_align);
+
+		offset += size;
 	}
-	*l0_size = ALIGN((w0 * bpe), pitch_align) * h0 * d0;
 	*mipmap_size = offset;
-	if (!nlevels)
+	if (llevel == 0)
 		*mipmap_size = *l0_size;
 	if (!blevel)
 		*mipmap_size -= *l0_size;
@@ -1169,11 +1277,13 @@
 					      u32 tiling_flags)
 {
 	struct r600_cs_track *track = p->track;
-	u32 nfaces, nlevels, blevel, w0, h0, d0, bpe = 0;
-	u32 word0, word1, l0_size, mipmap_size;
+	u32 nfaces, llevel, blevel, w0, h0, d0;
+	u32 word0, word1, l0_size, mipmap_size, word2, word3;
 	u32 height_align, pitch, pitch_align, depth_align;
+	u32 array, barray, larray;
 	u64 base_align;
 	struct array_mode_checker array_check;
+	u32 format;
 
 	/* on legacy kernel we don't perform advanced check */
 	if (p->rdev == NULL)
@@ -1199,19 +1309,25 @@
 	case V_038000_SQ_TEX_DIM_3D:
 		break;
 	case V_038000_SQ_TEX_DIM_CUBEMAP:
-		nfaces = 6;
+		if (p->family >= CHIP_RV770)
+			nfaces = 8;
+		else
+			nfaces = 6;
 		break;
 	case V_038000_SQ_TEX_DIM_1D_ARRAY:
 	case V_038000_SQ_TEX_DIM_2D_ARRAY:
+		array = 1;
+		break;
 	case V_038000_SQ_TEX_DIM_2D_MSAA:
 	case V_038000_SQ_TEX_DIM_2D_ARRAY_MSAA:
 	default:
 		dev_warn(p->dev, "this kernel doesn't support %d texture dim\n", G_038000_DIM(word0));
 		return -EINVAL;
 	}
-	if (r600_bpe_from_format(&bpe,  G_038004_DATA_FORMAT(word1))) {
+	format = G_038004_DATA_FORMAT(word1);
+	if (!fmt_is_valid_texture(format)) {
 		dev_warn(p->dev, "%s:%d texture invalid format %d\n",
-			 __func__, __LINE__, G_038004_DATA_FORMAT(word1));
+			 __func__, __LINE__, format);
 		return -EINVAL;
 	}
 
@@ -1222,7 +1338,7 @@
 	array_check.nbanks = track->nbanks;
 	array_check.npipes = track->npipes;
 	array_check.nsamples = 1;
-	array_check.bpe = bpe;
+	array_check.blocksize = fmt_get_blocksize(format);
 	if (r600_get_array_mode_alignment(&array_check,
 					  &pitch_align, &height_align, &depth_align, &base_align)) {
 		dev_warn(p->dev, "%s:%d tex array mode (%d) invalid\n",
@@ -1248,25 +1364,34 @@
 		return -EINVAL;
 	}
 
+	word2 = radeon_get_ib_value(p, idx + 2) << 8;
+	word3 = radeon_get_ib_value(p, idx + 3) << 8;
+
 	word0 = radeon_get_ib_value(p, idx + 4);
 	word1 = radeon_get_ib_value(p, idx + 5);
 	blevel = G_038010_BASE_LEVEL(word0);
-	nlevels = G_038014_LAST_LEVEL(word1);
-	r600_texture_size(nfaces, blevel, nlevels, w0, h0, d0, bpe,
-			  (pitch_align * bpe),
+	llevel = G_038014_LAST_LEVEL(word1);
+	if (array == 1) {
+		barray = G_038014_BASE_ARRAY(word1);
+		larray = G_038014_LAST_ARRAY(word1);
+
+		nfaces = larray - barray + 1;
+	}
+	r600_texture_size(nfaces, blevel, llevel, w0, h0, d0, format,
+			  pitch_align, height_align, base_align,
 			  &l0_size, &mipmap_size);
 	/* using get ib will give us the offset into the texture bo */
-	word0 = radeon_get_ib_value(p, idx + 2) << 8;
-	if ((l0_size + word0) > radeon_bo_size(texture)) {
+	if ((l0_size + word2) > radeon_bo_size(texture)) {
 		dev_warn(p->dev, "texture bo too small (%d %d %d %d -> %d have %ld)\n",
-			w0, h0, bpe, word0, l0_size, radeon_bo_size(texture));
+			w0, h0, format, word2, l0_size, radeon_bo_size(texture));
+		dev_warn(p->dev, "alignments %d %d %d %lld\n", pitch, pitch_align, height_align, base_align);
 		return -EINVAL;
 	}
 	/* using get ib will give us the offset into the mipmap bo */
-	word0 = radeon_get_ib_value(p, idx + 3) << 8;
-	if ((mipmap_size + word0) > radeon_bo_size(mipmap)) {
+	word3 = radeon_get_ib_value(p, idx + 3) << 8;
+	if ((mipmap_size + word3) > radeon_bo_size(mipmap)) {
 		/*dev_warn(p->dev, "mipmap bo too small (%d %d %d %d %d %d -> %d have %ld)\n",
-		  w0, h0, bpe, blevel, nlevels, word0, mipmap_size, radeon_bo_size(texture));*/
+		  w0, h0, format, blevel, nlevels, word3, mipmap_size, radeon_bo_size(texture));*/
 	}
 	return 0;
 }
@@ -1289,6 +1414,38 @@
 	idx_value = radeon_get_ib_value(p, idx);
 
 	switch (pkt->opcode) {
+	case PACKET3_SET_PREDICATION:
+	{
+		int pred_op;
+		int tmp;
+		if (pkt->count != 1) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		tmp = radeon_get_ib_value(p, idx + 1);
+		pred_op = (tmp >> 16) & 0x7;
+
+		/* for the clear predicate operation */
+		if (pred_op == 0)
+			return 0;
+
+		if (pred_op > 2) {
+			DRM_ERROR("bad SET PREDICATION operation %d\n", pred_op);
+			return -EINVAL;
+		}
+
+		r = r600_cs_packet_next_reloc(p, &reloc);
+		if (r) {
+			DRM_ERROR("bad SET PREDICATION\n");
+			return -EINVAL;
+		}
+
+		ib[idx + 0] = idx_value + (u32)(reloc->lobj.gpu_offset & 0xffffffff);
+		ib[idx + 1] = tmp + (upper_32_bits(reloc->lobj.gpu_offset) & 0xff);
+	}
+	break;
+
 	case PACKET3_START_3D_CMDBUF:
 		if (p->family >= CHIP_RV770 || pkt->count) {
 			DRM_ERROR("bad START_3D\n");
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600d.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600d.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600d.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600d.h	2011-05-19 00:06:34.000000000 -0400
@@ -1304,6 +1304,11 @@
 #define     V_038004_FMT_16_16_16_FLOAT                0x0000002E
 #define     V_038004_FMT_32_32_32                      0x0000002F
 #define     V_038004_FMT_32_32_32_FLOAT                0x00000030
+#define     V_038004_FMT_BC1                           0x00000031
+#define     V_038004_FMT_BC2                           0x00000032
+#define     V_038004_FMT_BC3                           0x00000033
+#define     V_038004_FMT_BC4                           0x00000034
+#define     V_038004_FMT_BC5                           0x00000035
 #define R_038010_SQ_TEX_RESOURCE_WORD4_0             0x038010
 #define   S_038010_FORMAT_COMP_X(x)                    (((x) & 0x3) << 0)
 #define   G_038010_FORMAT_COMP_X(x)                    (((x) >> 0) & 0x3)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_hdmi.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_hdmi.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/r600_hdmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/r600_hdmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include "drmP.h"
 #include "radeon_drm.h"
 #include "radeon.h"
+#include "radeon_asic.h"
 #include "atom.h"
 
 /*
@@ -333,7 +334,7 @@
 	r600_hdmi_videoinfoframe(encoder, RGB, 0, 0, 0, 0,
 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
 
-	/* it's unknown what these bits do excatly, but it's indeed quite usefull for debugging */
+	/* it's unknown what these bits do excatly, but it's indeed quite useful for debugging */
 	WREG32(offset+R600_HDMI_AUDIO_DEBUG_0, 0x00FFFFFF);
 	WREG32(offset+R600_HDMI_AUDIO_DEBUG_1, 0x007FFFFF);
 	WREG32(offset+R600_HDMI_AUDIO_DEBUG_2, 0x00000001);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_asic.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_asic.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_asic.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,7 @@
 		rdev->mc_rreg = &rs600_mc_rreg;
 		rdev->mc_wreg = &rs600_mc_wreg;
 	}
-	if ((rdev->family >= CHIP_R600) && (rdev->family <= CHIP_HEMLOCK)) {
+	if (rdev->family >= CHIP_R600) {
 		rdev->pciep_rreg = &r600_pciep_rreg;
 		rdev->pciep_wreg = &r600_pciep_wreg;
 	}
@@ -885,6 +885,52 @@
 	.post_page_flip = &evergreen_post_page_flip,
 };
 
+static struct radeon_asic cayman_asic = {
+	.init = &cayman_init,
+	.fini = &cayman_fini,
+	.suspend = &cayman_suspend,
+	.resume = &cayman_resume,
+	.cp_commit = &r600_cp_commit,
+	.gpu_is_lockup = &cayman_gpu_is_lockup,
+	.asic_reset = &cayman_asic_reset,
+	.vga_set_state = &r600_vga_set_state,
+	.gart_tlb_flush = &cayman_pcie_gart_tlb_flush,
+	.gart_set_page = &rs600_gart_set_page,
+	.ring_test = &r600_ring_test,
+	.ring_ib_execute = &evergreen_ring_ib_execute,
+	.irq_set = &evergreen_irq_set,
+	.irq_process = &evergreen_irq_process,
+	.get_vblank_counter = &evergreen_get_vblank_counter,
+	.fence_ring_emit = &r600_fence_ring_emit,
+	.cs_parse = &evergreen_cs_parse,
+	.copy_blit = NULL,
+	.copy_dma = NULL,
+	.copy = NULL,
+	.get_engine_clock = &radeon_atom_get_engine_clock,
+	.set_engine_clock = &radeon_atom_set_engine_clock,
+	.get_memory_clock = &radeon_atom_get_memory_clock,
+	.set_memory_clock = &radeon_atom_set_memory_clock,
+	.get_pcie_lanes = NULL,
+	.set_pcie_lanes = NULL,
+	.set_clock_gating = NULL,
+	.set_surface_reg = r600_set_surface_reg,
+	.clear_surface_reg = r600_clear_surface_reg,
+	.bandwidth_update = &evergreen_bandwidth_update,
+	.hpd_init = &evergreen_hpd_init,
+	.hpd_fini = &evergreen_hpd_fini,
+	.hpd_sense = &evergreen_hpd_sense,
+	.hpd_set_polarity = &evergreen_hpd_set_polarity,
+	.gui_idle = &r600_gui_idle,
+	.pm_misc = &evergreen_pm_misc,
+	.pm_prepare = &evergreen_pm_prepare,
+	.pm_finish = &evergreen_pm_finish,
+	.pm_init_profile = &r600_pm_init_profile,
+	.pm_get_dynpm_state = &r600_pm_get_dynpm_state,
+	.pre_page_flip = &evergreen_pre_page_flip,
+	.page_flip = &evergreen_page_flip,
+	.post_page_flip = &evergreen_post_page_flip,
+};
+
 int radeon_asic_init(struct radeon_device *rdev)
 {
 	radeon_register_accessor_init(rdev);
@@ -977,6 +1023,9 @@
 	case CHIP_CAICOS:
 		rdev->asic = &btc_asic;
 		break;
+	case CHIP_CAYMAN:
+		rdev->asic = &cayman_asic;
+		break;
 	default:
 		/* FIXME: not supported yet */
 		return -EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_asic.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_asic.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_asic.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,8 +57,6 @@
 void r100_fini(struct radeon_device *rdev);
 int r100_suspend(struct radeon_device *rdev);
 int r100_resume(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_vga_set_state(struct radeon_device *rdev, bool state);
 bool r100_gpu_is_lockup(struct radeon_device *rdev);
 int r100_asic_reset(struct radeon_device *rdev);
@@ -164,8 +162,6 @@
 extern int r300_cs_parse(struct radeon_cs_parser *p);
 extern void rv370_pcie_gart_tlb_flush(struct radeon_device *rdev);
 extern int rv370_pcie_gart_set_page(struct radeon_device *rdev, int i, uint64_t addr);
-extern uint32_t rv370_pcie_rreg(struct radeon_device *rdev, uint32_t reg);
-extern void rv370_pcie_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v);
 extern void rv370_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int rv370_get_pcie_lanes(struct radeon_device *rdev);
 extern void r300_set_reg_safe(struct radeon_device *rdev);
@@ -208,7 +204,6 @@
 void rs400_gart_disable(struct radeon_device *rdev);
 void rs400_gart_fini(struct radeon_device *rdev);
 
-
 /*
  * rs600.
  */
@@ -270,8 +265,6 @@
 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);
 int rv515_resume(struct radeon_device *rdev);
 int rv515_suspend(struct radeon_device *rdev);
@@ -307,14 +300,13 @@
 int r600_cs_parse(struct radeon_cs_parser *p);
 void r600_fence_ring_emit(struct radeon_device *rdev,
 			  struct radeon_fence *fence);
-int r600_irq_process(struct radeon_device *rdev);
-int r600_irq_set(struct radeon_device *rdev);
 bool r600_gpu_is_lockup(struct radeon_device *rdev);
 int r600_asic_reset(struct radeon_device *rdev);
 int r600_set_surface_reg(struct radeon_device *rdev, int reg,
 			 uint32_t tiling_flags, uint32_t pitch,
 			 uint32_t offset, uint32_t obj_size);
 void r600_clear_surface_reg(struct radeon_device *rdev, int reg);
+int r600_ib_test(struct radeon_device *rdev);
 void r600_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib);
 int r600_ring_test(struct radeon_device *rdev);
 int r600_copy_blit(struct radeon_device *rdev,
@@ -333,6 +325,50 @@
 extern void r600_pm_get_dynpm_state(struct radeon_device *rdev);
 extern void r600_set_pcie_lanes(struct radeon_device *rdev, int lanes);
 extern int r600_get_pcie_lanes(struct radeon_device *rdev);
+bool r600_card_posted(struct radeon_device *rdev);
+void r600_cp_stop(struct radeon_device *rdev);
+int r600_cp_start(struct radeon_device *rdev);
+void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
+int r600_cp_resume(struct radeon_device *rdev);
+void r600_cp_fini(struct radeon_device *rdev);
+int r600_count_pipe_bits(uint32_t val);
+int r600_mc_wait_for_idle(struct radeon_device *rdev);
+int r600_pcie_gart_init(struct radeon_device *rdev);
+void r600_scratch_init(struct radeon_device *rdev);
+int r600_blit_init(struct radeon_device *rdev);
+void r600_blit_fini(struct radeon_device *rdev);
+int r600_init_microcode(struct radeon_device *rdev);
+/* r600 irq */
+int r600_irq_process(struct radeon_device *rdev);
+int r600_irq_init(struct radeon_device *rdev);
+void r600_irq_fini(struct radeon_device *rdev);
+void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
+int r600_irq_set(struct radeon_device *rdev);
+void r600_irq_suspend(struct radeon_device *rdev);
+void r600_disable_interrupts(struct radeon_device *rdev);
+void r600_rlc_stop(struct radeon_device *rdev);
+/* r600 audio */
+int r600_audio_init(struct radeon_device *rdev);
+int r600_audio_tmds_index(struct drm_encoder *encoder);
+void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
+int r600_audio_channels(struct radeon_device *rdev);
+int r600_audio_bits_per_sample(struct radeon_device *rdev);
+int r600_audio_rate(struct radeon_device *rdev);
+uint8_t r600_audio_status_bits(struct radeon_device *rdev);
+uint8_t r600_audio_category_code(struct radeon_device *rdev);
+void r600_audio_schedule_polling(struct radeon_device *rdev);
+void r600_audio_enable_polling(struct drm_encoder *encoder);
+void r600_audio_disable_polling(struct drm_encoder *encoder);
+void r600_audio_fini(struct radeon_device *rdev);
+void r600_hdmi_init(struct drm_encoder *encoder);
+int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
+void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
+/* r600 blit */
+int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
+void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
+void r600_kms_blit_copy(struct radeon_device *rdev,
+			u64 src_gpu_addr, u64 dst_gpu_addr,
+			int size_bytes);
 
 /*
  * rv770,rv730,rv710,rv740
@@ -341,12 +377,21 @@
 void rv770_fini(struct radeon_device *rdev);
 int rv770_suspend(struct radeon_device *rdev);
 int rv770_resume(struct radeon_device *rdev);
-extern void rv770_pm_misc(struct radeon_device *rdev);
-extern u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+void rv770_pm_misc(struct radeon_device *rdev);
+u32 rv770_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
+void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
+void r700_cp_stop(struct radeon_device *rdev);
+void r700_cp_fini(struct radeon_device *rdev);
 
 /*
  * evergreen
  */
+struct evergreen_mc_save {
+	u32 vga_control[6];
+	u32 vga_render_control;
+	u32 vga_hdp_control;
+	u32 crtc_control[6];
+};
 void evergreen_pcie_gart_tlb_flush(struct radeon_device *rdev);
 int evergreen_init(struct radeon_device *rdev);
 void evergreen_fini(struct radeon_device *rdev);
@@ -374,5 +419,25 @@
 extern void evergreen_pre_page_flip(struct radeon_device *rdev, int crtc);
 extern u32 evergreen_page_flip(struct radeon_device *rdev, int crtc, u64 crtc_base);
 extern void evergreen_post_page_flip(struct radeon_device *rdev, int crtc);
+void evergreen_disable_interrupt_state(struct radeon_device *rdev);
+int evergreen_blit_init(struct radeon_device *rdev);
+void evergreen_blit_fini(struct radeon_device *rdev);
+/* evergreen blit */
+int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
+void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
+void evergreen_kms_blit_copy(struct radeon_device *rdev,
+			     u64 src_gpu_addr, u64 dst_gpu_addr,
+			     int size_bytes);
+
+/*
+ * cayman
+ */
+void cayman_pcie_gart_tlb_flush(struct radeon_device *rdev);
+int cayman_init(struct radeon_device *rdev);
+void cayman_fini(struct radeon_device *rdev);
+int cayman_suspend(struct radeon_device *rdev);
+int cayman_resume(struct radeon_device *rdev);
+bool cayman_gpu_is_lockup(struct radeon_device *rdev);
+int cayman_asic_reset(struct radeon_device *rdev);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_atombios.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_atombios.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_atombios.c	2011-05-19 00:06:34.000000000 -0400
@@ -431,7 +431,7 @@
 		}
 	}
 
-	/* Acer laptop (Acer TravelMate 5730G) has an HDMI port
+	/* Acer laptop (Acer TravelMate 5730/5730G) has an HDMI port
 	 * on the laptop and a DVI port on the docking station and
 	 * both share the same encoder, hpd pin, and ddc line.
 	 * So while the bios table is technically correct,
@@ -440,7 +440,7 @@
 	 * with different crtcs which isn't possible on the hardware
 	 * side and leaves no crtcs for LVDS or VGA.
 	 */
-	if ((dev->pdev->device == 0x95c4) &&
+	if (((dev->pdev->device == 0x95c4) || (dev->pdev->device == 0x9591)) &&
 	    (dev->pdev->subsystem_vendor == 0x1025) &&
 	    (dev->pdev->subsystem_device == 0x013c)) {
 		if ((*connector_type == DRM_MODE_CONNECTOR_DVII) &&
@@ -675,7 +675,8 @@
 							ATOM_ENCODER_CAP_RECORD *cap_record;
 							u16 caps = 0;
 
-							while (record->ucRecordType > 0 &&
+							while (record->ucRecordSize > 0 &&
+							       record->ucRecordType > 0 &&
 							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
 								switch (record->ucRecordType) {
 								case ATOM_ENCODER_CAP_RECORD_TYPE:
@@ -720,7 +721,8 @@
 									break;
 							}
 
-							while (record->ucRecordType > 0 &&
+							while (record->ucRecordSize > 0 &&
+							       record->ucRecordType > 0 &&
 							       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
 								switch (record->ucRecordType) {
 								case ATOM_I2C_RECORD_TYPE:
@@ -782,10 +784,9 @@
 						ATOM_HPD_INT_RECORD *hpd_record;
 						ATOM_I2C_ID_CONFIG_ACCESS *i2c_config;
 
-						while (record->ucRecordType > 0
-						       && record->
-						       ucRecordType <=
-						       ATOM_MAX_OBJECT_RECORD_NUMBER) {
+						while (record->ucRecordSize > 0 &&
+						       record->ucRecordType > 0 &&
+						       record->ucRecordType <= ATOM_MAX_OBJECT_RECORD_NUMBER) {
 							switch (record->ucRecordType) {
 							case ATOM_I2C_RECORD_TYPE:
 								i2c_record =
@@ -1573,9 +1574,17 @@
 			ATOM_FAKE_EDID_PATCH_RECORD *fake_edid_record;
 			ATOM_PANEL_RESOLUTION_PATCH_RECORD *panel_res_record;
 			bool bad_record = false;
-			u8 *record = (u8 *)(mode_info->atom_context->bios +
-					    data_offset +
-					    le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+			u8 *record;
+
+			if ((frev == 1) && (crev < 2))
+				/* absolute */
+				record = (u8 *)(mode_info->atom_context->bios +
+						le16_to_cpu(lvds_info->info.usModePatchTableOffset));
+			else
+				/* relative */
+				record = (u8 *)(mode_info->atom_context->bios +
+						data_offset +
+						le16_to_cpu(lvds_info->info.usModePatchTableOffset));
 			while (*record != ATOM_RECORD_END_TYPE) {
 				switch (*record) {
 				case LCD_MODE_PATCH_RECORD_MODE_TYPE:
@@ -1598,9 +1607,10 @@
 							memcpy((u8 *)edid, (u8 *)&fake_edid_record->ucFakeEDIDString[0],
 							       fake_edid_record->ucFakeEDIDLength);
 
-							if (drm_edid_is_valid(edid))
+							if (drm_edid_is_valid(edid)) {
 								rdev->mode_info.bios_hardcoded_edid = edid;
-							else
+								rdev->mode_info.bios_hardcoded_edid_size = edid_size;
+							} else
 								kfree(edid);
 						}
 					}
@@ -2175,24 +2185,27 @@
 	}
 }
 
-static u16 radeon_atombios_get_default_vddc(struct radeon_device *rdev)
+static void radeon_atombios_get_default_voltages(struct radeon_device *rdev,
+						 u16 *vddc, u16 *vddci)
 {
 	struct radeon_mode_info *mode_info = &rdev->mode_info;
 	int index = GetIndexIntoMasterTable(DATA, FirmwareInfo);
 	u8 frev, crev;
 	u16 data_offset;
 	union firmware_info *firmware_info;
-	u16 vddc = 0;
+
+	*vddc = 0;
+	*vddci = 0;
 
 	if (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);
-		vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
+		*vddc = le16_to_cpu(firmware_info->info_14.usBootUpVDDCVoltage);
+		if ((frev == 2) && (crev >= 2))
+			*vddci = le16_to_cpu(firmware_info->info_22.usBootUpVDDCIVoltage);
 	}
-
-	return vddc;
 }
 
 static void radeon_atombios_parse_pplib_non_clock_info(struct radeon_device *rdev,
@@ -2202,7 +2215,9 @@
 	int j;
 	u32 misc = le32_to_cpu(non_clock_info->ulCapsAndSettings);
 	u32 misc2 = le16_to_cpu(non_clock_info->usClassification);
-	u16 vddc = radeon_atombios_get_default_vddc(rdev);
+	u16 vddc, vddci;
+
+	radeon_atombios_get_default_voltages(rdev, &vddc, &vddci);
 
 	rdev->pm.power_state[state_index].misc = misc;
 	rdev->pm.power_state[state_index].misc2 = misc2;
@@ -2243,6 +2258,7 @@
 			rdev->pm.default_sclk = rdev->pm.power_state[state_index].clock_info[0].sclk;
 			rdev->pm.default_mclk = rdev->pm.power_state[state_index].clock_info[0].mclk;
 			rdev->pm.default_vddc = rdev->pm.power_state[state_index].clock_info[0].voltage.voltage;
+			rdev->pm.default_vddci = rdev->pm.power_state[state_index].clock_info[0].voltage.vddci;
 		} else {
 			/* patch the table values with the default slck/mclk from firmware info */
 			for (j = 0; j < mode_index; j++) {
@@ -2285,6 +2301,8 @@
 			VOLTAGE_SW;
 		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.voltage =
 			le16_to_cpu(clock_info->evergreen.usVDDC);
+		rdev->pm.power_state[state_index].clock_info[mode_index].voltage.vddci =
+			le16_to_cpu(clock_info->evergreen.usVDDCI);
 	} else {
 		sclk = le16_to_cpu(clock_info->r600.usEngineClockLow);
 		sclk |= clock_info->r600.ucEngineClockHigh << 16;
@@ -2576,25 +2594,25 @@
 	struct _SET_VOLTAGE_PARAMETERS_V2 v2;
 };
 
-void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level)
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type)
 {
 	union set_voltage args;
 	int index = GetIndexIntoMasterTable(COMMAND, SetVoltage);
-	u8 frev, crev, volt_index = level;
+	u8 frev, crev, volt_index = voltage_level;
 
 	if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
 		return;
 
 	switch (crev) {
 	case 1:
-		args.v1.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+		args.v1.ucVoltageType = voltage_type;
 		args.v1.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_ALL_SOURCE;
 		args.v1.ucVoltageIndex = volt_index;
 		break;
 	case 2:
-		args.v2.ucVoltageType = SET_VOLTAGE_TYPE_ASIC_VDDC;
+		args.v2.ucVoltageType = voltage_type;
 		args.v2.ucVoltageMode = SET_ASIC_VOLTAGE_MODE_SET_VOLTAGE;
-		args.v2.usVoltageLevel = cpu_to_le16(level);
+		args.v2.usVoltageLevel = cpu_to_le16(voltage_level);
 		break;
 	default:
 		DRM_ERROR("Unknown table version %d, %d\n", frev, crev);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_atpx_handler.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,9 @@
 #define ATPX_VERSION 0
 #define ATPX_GPU_PWR 2
 #define ATPX_MUX_SELECT 3
+#define ATPX_I2C_MUX_SELECT 4
+#define ATPX_SWITCH_START 5
+#define ATPX_SWITCH_END 6
 
 #define ATPX_INTEGRATED 0
 #define ATPX_DISCRETE 1
@@ -149,13 +152,35 @@
 	return radeon_atpx_execute(handle, ATPX_MUX_SELECT, mux_id);
 }
 
+static int radeon_atpx_switch_i2c_mux(acpi_handle handle, int mux_id)
+{
+	return radeon_atpx_execute(handle, ATPX_I2C_MUX_SELECT, mux_id);
+}
+
+static int radeon_atpx_switch_start(acpi_handle handle, int gpu_id)
+{
+	return radeon_atpx_execute(handle, ATPX_SWITCH_START, gpu_id);
+}
+
+static int radeon_atpx_switch_end(acpi_handle handle, int gpu_id)
+{
+	return radeon_atpx_execute(handle, ATPX_SWITCH_END, gpu_id);
+}
 
 static int radeon_atpx_switchto(enum vga_switcheroo_client_id id)
 {
+	int gpu_id;
+
 	if (id == VGA_SWITCHEROO_IGD)
-		radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 0);
+		gpu_id = ATPX_INTEGRATED;
 	else
-		radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, 1);
+		gpu_id = ATPX_DISCRETE;
+
+	radeon_atpx_switch_start(radeon_atpx_priv.atpx_handle, gpu_id);
+	radeon_atpx_switch_mux(radeon_atpx_priv.atpx_handle, gpu_id);
+	radeon_atpx_switch_i2c_mux(radeon_atpx_priv.atpx_handle, gpu_id);
+	radeon_atpx_switch_end(radeon_atpx_priv.atpx_handle, gpu_id);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_benchmark.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
 
 	size = bsize;
 	n = 1024;
-	r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, sdomain, &sobj);
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, sdomain, &sobj);
 	if (r) {
 		goto out_cleanup;
 	}
@@ -53,7 +53,7 @@
 	if (r) {
 		goto out_cleanup;
 	}
-	r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, ddomain, &dobj);
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, ddomain, &dobj);
 	if (r) {
 		goto out_cleanup;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_combios.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_combios.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_combios.c	2011-05-19 00:06:34.000000000 -0400
@@ -448,7 +448,7 @@
 
 bool radeon_combios_check_hardcoded_edid(struct radeon_device *rdev)
 {
-	int edid_info;
+	int edid_info, size;
 	struct edid *edid;
 	unsigned char *raw;
 	edid_info = combios_get_table_offset(rdev->ddev, COMBIOS_HARDCODED_EDID_TABLE);
@@ -456,11 +456,12 @@
 		return false;
 
 	raw = rdev->bios + edid_info;
-	edid = kmalloc(EDID_LENGTH * (raw[0x7e] + 1), GFP_KERNEL);
+	size = EDID_LENGTH * (raw[0x7e] + 1);
+	edid = kmalloc(size, GFP_KERNEL);
 	if (edid == NULL)
 		return false;
 
-	memcpy((unsigned char *)edid, raw, EDID_LENGTH * (raw[0x7e] + 1));
+	memcpy((unsigned char *)edid, raw, size);
 
 	if (!drm_edid_is_valid(edid)) {
 		kfree(edid);
@@ -468,6 +469,7 @@
 	}
 
 	rdev->mode_info.bios_hardcoded_edid = edid;
+	rdev->mode_info.bios_hardcoded_edid_size = size;
 	return true;
 }
 
@@ -475,8 +477,17 @@
 struct edid *
 radeon_bios_get_hardcoded_edid(struct radeon_device *rdev)
 {
-	if (rdev->mode_info.bios_hardcoded_edid)
-		return rdev->mode_info.bios_hardcoded_edid;
+	struct edid *edid;
+
+	if (rdev->mode_info.bios_hardcoded_edid) {
+		edid = kmalloc(rdev->mode_info.bios_hardcoded_edid_size, GFP_KERNEL);
+		if (edid) {
+			memcpy((unsigned char *)edid,
+			       (unsigned char *)rdev->mode_info.bios_hardcoded_edid,
+			       rdev->mode_info.bios_hardcoded_edid_size);
+			return edid;
+		}
+	}
 	return NULL;
 }
 
@@ -2068,6 +2079,19 @@
 					    DRM_MODE_CONNECTOR_DVII, &ddc_i2c,
 					    CONNECTOR_OBJECT_ID_SINGLE_LINK_DVI_I,
 					    &hpd);
+		/* TV - TV DAC */
+		ddc_i2c.valid = false;
+		hpd.hpd = RADEON_HPD_NONE;
+		radeon_add_legacy_encoder(dev,
+					  radeon_get_encoder_enum(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,
+					    CONNECTOR_OBJECT_ID_SVIDEO,
+					    &hpd);
 		break;
 	default:
 		DRM_INFO("Connector table: %d (invalid)\n",
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_connectors.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_connectors.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_connectors.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,10 @@
 				       struct drm_encoder *encoder,
 				       bool connected);
 
+extern void
+radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+			     struct drm_connector *drm_connector);
+
 void radeon_connector_hotplug(struct drm_connector *connector)
 {
 	struct drm_device *dev = connector->dev;
@@ -629,6 +633,8 @@
 static enum drm_connector_status
 radeon_vga_detect(struct drm_connector *connector, bool force)
 {
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder;
 	struct drm_encoder_helper_funcs *encoder_funcs;
@@ -679,6 +685,17 @@
 
 	if (ret == connector_status_connected)
 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
+
+	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
+	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
+	 * by other means, assume the CRT is connected and use that EDID.
+	 */
+	if ((!rdev->is_atom_bios) &&
+	    (ret == connector_status_disconnected) &&
+	    rdev->mode_info.bios_hardcoded_edid_size) {
+		ret = connector_status_connected;
+	}
+
 	radeon_connector_update_scratch_regs(connector, ret);
 	return ret;
 }
@@ -790,6 +807,8 @@
 static enum drm_connector_status
 radeon_dvi_detect(struct drm_connector *connector, bool force)
 {
+	struct drm_device *dev = connector->dev;
+	struct radeon_device *rdev = dev->dev_private;
 	struct radeon_connector *radeon_connector = to_radeon_connector(connector);
 	struct drm_encoder *encoder = NULL;
 	struct drm_encoder_helper_funcs *encoder_funcs;
@@ -829,8 +848,6 @@
 			 * you don't really know what's connected to which port as both are digital.
 			 */
 			if (radeon_connector->shared_ddc && (ret == connector_status_connected)) {
-				struct drm_device *dev = connector->dev;
-				struct radeon_device *rdev = dev->dev_private;
 				struct drm_connector *list_connector;
 				struct radeon_connector *list_radeon_connector;
 				list_for_each_entry(list_connector, &dev->mode_config.connector_list, head) {
@@ -895,6 +912,19 @@
 		ret = radeon_connector_analog_encoder_conflict_solve(connector, encoder, ret, true);
 	}
 
+	/* RN50 and some RV100 asics in servers often have a hardcoded EDID in the
+	 * vbios to deal with KVMs. If we have one and are not able to detect a monitor
+	 * by other means, assume the DFP is connected and use that EDID.  In most
+	 * cases the DVI port is actually a virtual KVM port connected to the service
+	 * processor.
+	 */
+	if ((!rdev->is_atom_bios) &&
+	    (ret == connector_status_disconnected) &&
+	    rdev->mode_info.bios_hardcoded_edid_size) {
+		radeon_connector->use_digital = true;
+		ret = connector_status_connected;
+	}
+
 out:
 	/* updated in get modes as well since we need to know if it's analog or digital */
 	radeon_connector_update_scratch_regs(connector, ret);
@@ -972,7 +1002,16 @@
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_DUAL_LINK_DVI_D) ||
 		    (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_B))
 			return MODE_OK;
-		else
+		else if (radeon_connector->connector_object_id == CONNECTOR_OBJECT_ID_HDMI_TYPE_A) {
+			if (ASIC_IS_DCE3(rdev)) {
+				/* HDMI 1.3+ supports max clock of 340 Mhz */
+				if (mode->clock > 340000)
+					return MODE_CLOCK_HIGH;
+				else
+					return MODE_OK;
+			} else
+				return MODE_CLOCK_HIGH;
+		} else
 			return MODE_CLOCK_HIGH;
 	}
 	return MODE_OK;
@@ -1160,7 +1199,7 @@
 	if (router->ddc_valid || router->cd_valid) {
 		radeon_connector->router_bus = radeon_i2c_lookup(rdev, &router->i2c_info);
 		if (!radeon_connector->router_bus)
-			goto failed;
+			DRM_ERROR("Failed to assign router i2c bus! Check dmesg for i2c errors.\n");
 	}
 	switch (connector_type) {
 	case DRM_MODE_CONNECTOR_VGA:
@@ -1169,7 +1208,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		radeon_connector->dac_load_detect = true;
 		drm_connector_attach_property(&radeon_connector->base,
@@ -1187,7 +1226,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		radeon_connector->dac_load_detect = true;
 		drm_connector_attach_property(&radeon_connector->base,
@@ -1210,7 +1249,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		subpixel_order = SubPixelHorizontalRGB;
 		drm_connector_attach_property(&radeon_connector->base,
@@ -1251,7 +1290,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("HDMI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		drm_connector_attach_property(&radeon_connector->base,
 					      rdev->mode_info.coherent_mode_property,
@@ -1290,10 +1329,10 @@
 			else
 				radeon_dig_connector->dp_i2c_bus = radeon_i2c_create_dp(dev, i2c_bus, "DP-auxch");
 			if (!radeon_dig_connector->dp_i2c_bus)
-				goto failed;
+				DRM_ERROR("DP: Failed to assign dp ddc bus! Check dmesg for i2c errors.\n");
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("DP: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		subpixel_order = SubPixelHorizontalRGB;
 		drm_connector_attach_property(&radeon_connector->base,
@@ -1342,7 +1381,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		drm_connector_attach_property(&radeon_connector->base,
 					      dev->mode_config.scaling_mode_property,
@@ -1418,7 +1457,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("VGA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		radeon_connector->dac_load_detect = true;
 		drm_connector_attach_property(&radeon_connector->base,
@@ -1436,7 +1475,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("DVIA: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		radeon_connector->dac_load_detect = true;
 		drm_connector_attach_property(&radeon_connector->base,
@@ -1454,7 +1493,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("DVI: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		if (connector_type == DRM_MODE_CONNECTOR_DVII) {
 			radeon_connector->dac_load_detect = true;
@@ -1499,7 +1538,7 @@
 		if (i2c_bus->valid) {
 			radeon_connector->ddc_bus = radeon_i2c_lookup(rdev, i2c_bus);
 			if (!radeon_connector->ddc_bus)
-				goto failed;
+				DRM_ERROR("LVDS: Failed to assign ddc bus! Check dmesg for i2c errors.\n");
 		}
 		drm_connector_attach_property(&radeon_connector->base,
 					      dev->mode_config.scaling_mode_property,
@@ -1517,9 +1556,15 @@
 		connector->polled = DRM_CONNECTOR_POLL_HPD;
 	connector->display_info.subpixel_order = subpixel_order;
 	drm_sysfs_connector_add(connector);
-	return;
+	if (connector_type == DRM_MODE_CONNECTOR_LVDS) {
+		struct drm_encoder *drm_encoder;
 
-failed:
-	drm_connector_cleanup(connector);
-	kfree(connector);
+		list_for_each_entry(drm_encoder, &dev->mode_config.encoder_list, head) {
+			struct radeon_encoder *radeon_encoder;
+
+			radeon_encoder = to_radeon_encoder(drm_encoder);
+			if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_LVDS)
+				radeon_legacy_backlight_init(radeon_encoder, connector);
+		}
+	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_cp.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_cp.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_cp.c	2012-03-24 01:00:31.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_cp.c	2012-03-24 03:26:35.000000000 -0400
@@ -238,7 +238,7 @@
 	u32 agp_base_lo = agp_base & 0xffffffff;
 	u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff;
 
-	/* R6xx/R7xx must be aligned to a 4MB boundry */
+	/* R6xx/R7xx must be aligned to a 4MB boundary */
 	if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)
 		RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base);
 	else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600)
@@ -2107,9 +2107,9 @@
 		break;
 	}
 
-	if (drm_device_is_agp(dev))
+	if (drm_pci_device_is_agp(dev))
 		dev_priv->flags |= RADEON_IS_AGP;
-	else if (drm_device_is_pcie(dev))
+	else if (drm_pci_device_is_pcie(dev))
 		dev_priv->flags |= RADEON_IS_PCIE;
 	else
 		dev_priv->flags |= RADEON_IS_PCI;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_cs.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_cs.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 				return -ENOENT;
 			}
 			p->relocs_ptr[i] = &p->relocs[i];
-			p->relocs[i].robj = p->relocs[i].gobj->driver_private;
+			p->relocs[i].robj = gem_to_radeon_bo(p->relocs[i].gobj);
 			p->relocs[i].lobj.bo = p->relocs[i].robj;
 			p->relocs[i].lobj.wdomain = r->write_domain;
 			p->relocs[i].lobj.rdomain = r->read_domains;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_cursor.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_cursor.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_cursor.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,9 +167,6 @@
 		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);
@@ -180,6 +177,9 @@
 	if (ret)
 		goto fail;
 
+	radeon_crtc->cursor_width = width;
+	radeon_crtc->cursor_height = height;
+
 	radeon_lock_cursor(crtc, true);
 	/* XXX only 27 bit offset for legacy cursor */
 	radeon_set_cursor(crtc, obj, gpu_addr);
@@ -226,7 +226,7 @@
 		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
+		/* avivo cursor image can't end on 128 pixel boundary 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) {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_device.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_device.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_device.c	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 	"BARTS",
 	"TURKS",
 	"CAICOS",
+	"CAYMAN",
 	"LAST",
 };
 
@@ -184,7 +185,7 @@
 	int r;
 
 	if (rdev->wb.wb_obj == NULL) {
-		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
+		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true,
 				RADEON_GEM_DOMAIN_GTT, &rdev->wb.wb_obj);
 		if (r) {
 			dev_warn(rdev->dev, "(%d) create WB bo failed\n", r);
@@ -261,7 +262,7 @@
  * Note: GTT start, end, size should be initialized before calling this
  * function on AGP platform.
  *
- * Note: We don't explictly enforce VRAM start to be aligned on VRAM size,
+ * Note: We don't explicitly enforce VRAM start to be aligned on VRAM size,
  * this shouldn't be a problem as we are using the PCI aperture as a reference.
  * Otherwise this would be needed for rv280, all r3xx, and all r4xx, but
  * not IGP.
@@ -860,7 +861,7 @@
 		if (rfb == NULL || rfb->obj == NULL) {
 			continue;
 		}
-		robj = rfb->obj->driver_private;
+		robj = gem_to_radeon_bo(rfb->obj);
 		/* don't unpin kernel fb objects */
 		if (!radeon_fbdev_robj_is_fb(rdev, robj)) {
 			r = radeon_bo_reserve(robj, false);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_display.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_display.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_display.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_display.c	2011-05-19 00:06:34.000000000 -0400
@@ -371,7 +371,7 @@
 	new_radeon_fb = to_radeon_framebuffer(fb);
 	/* schedule unpin of the old buffer */
 	obj = old_radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	work->old_rbo = rbo;
 	INIT_WORK(&work->work, radeon_unpin_work_func);
 
@@ -391,7 +391,7 @@
 
 	/* pin the new buffer */
 	obj = new_radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 
 	DRM_DEBUG_DRIVER("flip-ioctl() cur_fbo = %p, cur_bbo = %p\n",
 			 work->old_rbo, rbo);
@@ -1492,7 +1492,7 @@
  *
  * \return Flags, or'ed together as follows:
  *
- * DRM_SCANOUTPOS_VALID = Query successfull.
+ * DRM_SCANOUTPOS_VALID = Query successful.
  * DRM_SCANOUTPOS_INVBL = Inside vblank.
  * DRM_SCANOUTPOS_ACCURATE = Returned position is accurate. A lack of
  * this flag means that returned position may be offset by a constant but
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,9 +49,10 @@
  * - 2.6.0 - add tiling config query (r6xx+), add initial HiZ support (r300->r500)
  *   2.7.0 - fixups for r600 2D tiling support. (no external ABI change), add eg dyn gpr regs
  *   2.8.0 - pageflip support, r500 US_FORMAT regs. r500 ARGB2101010 colorbuf, r300->r500 CMASK, clock crystal query
+ *   2.9.0 - r600 tiling (s3tc,rgtc) working, SET_PREDICATION packet 3 on r600 + eg, backend query
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	8
+#define KMS_DRIVER_MINOR	9
 #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);
@@ -84,6 +85,16 @@
 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);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+			  struct drm_device *dev,
+			  uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    struct drm_mode_create_dumb *args);
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+			     struct drm_device *dev,
+			     uint32_t handle);
+
 #if defined(CONFIG_DEBUG_FS)
 int radeon_debugfs_init(struct drm_minor *minor);
 void radeon_debugfs_cleanup(struct drm_minor *minor);
@@ -228,11 +239,6 @@
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -322,6 +328,9 @@
 	.gem_init_object = radeon_gem_object_init,
 	.gem_free_object = radeon_gem_object_free,
 	.dma_ioctl = radeon_dma_ioctl_kms,
+	.dumb_create = radeon_mode_dumb_create,
+	.dumb_map_offset = radeon_mode_dumb_mmap,
+	.dumb_destroy = radeon_mode_dumb_destroy,
 	.fops = {
 		 .owner = THIS_MODULE,
 		 .open = drm_open,
@@ -336,15 +345,6 @@
 #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,
@@ -354,15 +354,32 @@
 };
 
 static struct drm_driver *driver;
+static struct pci_driver *pdriver;
+
+static struct pci_driver radeon_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
+static struct pci_driver radeon_kms_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+	.probe = radeon_pci_probe,
+	.remove = radeon_pci_remove,
+	.suspend = radeon_pci_suspend,
+	.resume = radeon_pci_resume,
+};
 
 static int __init radeon_init(void)
 {
 	driver = &driver_old;
+	pdriver = &radeon_pci_driver;
 	driver->num_ioctls = radeon_max_ioctl;
 #ifdef CONFIG_VGA_CONSOLE
 	if (vgacon_text_force() && radeon_modeset == -1) {
 		DRM_INFO("VGACON disable radeon kernel modesetting.\n");
 		driver = &driver_old;
+		pdriver = &radeon_pci_driver;
 		driver->driver_features &= ~DRIVER_MODESET;
 		radeon_modeset = 0;
 	}
@@ -380,18 +397,19 @@
 	if (radeon_modeset == 1) {
 		DRM_INFO("radeon kernel modesetting enabled.\n");
 		driver = &kms_driver;
+		pdriver = &radeon_kms_pci_driver;
 		driver->driver_features |= DRIVER_MODESET;
 		driver->num_ioctls = radeon_max_kms_ioctl;
 		radeon_register_atpx_handler();
 	}
 	/* if the vga console setting is enabled still
 	 * let modprobe override it */
-	return drm_init(driver);
+	return drm_pci_init(driver, pdriver);
 }
 
 static void __exit radeon_exit(void)
 {
-	drm_exit(driver);
+	drm_pci_exit(driver, pdriver);
 	radeon_unregister_atpx_handler();
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_drv.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_drv.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_drv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_drv.h	2011-05-19 00:06:34.000000000 -0400
@@ -271,7 +271,7 @@
 
 	int have_z_offset;
 
-	/* starting from here on, data is preserved accross an open */
+	/* starting from here on, data is preserved across an open */
 	uint32_t flags;		/* see radeon_chip_flags */
 	resource_size_t fb_aper_offset;
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_family.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_family.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_family.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_family.h	2011-05-19 00:06:34.000000000 -0400
@@ -84,6 +84,7 @@
 	CHIP_BARTS,
 	CHIP_TURKS,
 	CHIP_CAICOS,
+	CHIP_CAYMAN,
 	CHIP_LAST,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_fb.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_fb.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_fb.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,7 @@
 };
 
 
-static int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled)
+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;
@@ -90,7 +90,7 @@
 
 static void radeonfb_destroy_pinned_object(struct drm_gem_object *gobj)
 {
-	struct radeon_bo *rbo = gobj->driver_private;
+	struct radeon_bo *rbo = gem_to_radeon_bo(gobj);
 	int ret;
 
 	ret = radeon_bo_reserve(rbo, false);
@@ -131,7 +131,7 @@
 		       aligned_size);
 		return -ENOMEM;
 	}
-	rbo = gobj->driver_private;
+	rbo = gem_to_radeon_bo(gobj);
 
 	if (fb_tiled)
 		tiling_flags = RADEON_TILING_MACRO;
@@ -205,7 +205,7 @@
 	mode_cmd.depth = sizes->surface_depth;
 
 	ret = radeonfb_create_pinned_object(rfbdev, &mode_cmd, &gobj);
-	rbo = gobj->driver_private;
+	rbo = gem_to_radeon_bo(gobj);
 
 	/* okay we have an object now allocate the framebuffer */
 	info = framebuffer_alloc(0, device);
@@ -406,14 +406,14 @@
 	struct radeon_bo *robj;
 	int size = 0;
 
-	robj = rdev->mode_info.rfbdev->rfb.obj->driver_private;
+	robj = gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj);
 	size += radeon_bo_size(robj);
 	return size;
 }
 
 bool radeon_fbdev_robj_is_fb(struct radeon_device *rdev, struct radeon_bo *robj)
 {
-	if (robj == rdev->mode_info.rfbdev->rfb.obj->driver_private)
+	if (robj == gem_to_radeon_bo(rdev->mode_info.rfbdev->rfb.obj))
 		return true;
 	return false;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_fence.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_fence.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_fence.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,8 +60,7 @@
 
 	trace_radeon_fence_emit(rdev->ddev, fence->seq);
 	fence->emited = true;
-	list_del(&fence->list);
-	list_add_tail(&fence->list, &rdev->fence_drv.emited);
+	list_move_tail(&fence->list, &rdev->fence_drv.emited);
 	write_unlock_irqrestore(&rdev->fence_drv.lock, irq_flags);
 	return 0;
 }
@@ -80,7 +79,7 @@
 			scratch_index = R600_WB_EVENT_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
 		else
 			scratch_index = RADEON_WB_SCRATCH_OFFSET + rdev->fence_drv.scratch_reg - rdev->scratch.reg_base;
-		seq = rdev->wb.wb[scratch_index/4];
+		seq = le32_to_cpu(rdev->wb.wb[scratch_index/4]);
 	} else
 		seq = RREG32(rdev->fence_drv.scratch_reg);
 	if (seq != rdev->fence_drv.last_seq) {
@@ -121,8 +120,7 @@
 		i = n;
 		do {
 			n = i->prev;
-			list_del(i);
-			list_add_tail(i, &rdev->fence_drv.signaled);
+			list_move_tail(i, &rdev->fence_drv.signaled);
 			fence = list_entry(i, struct radeon_fence, list);
 			fence->signaled = true;
 			i = n;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_gart.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_gart.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_gart.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
 	int r;
 
 	if (rdev->gart.table.vram.robj == NULL) {
-		r = radeon_bo_create(rdev, NULL, rdev->gart.table_size,
+		r = radeon_bo_create(rdev, rdev->gart.table_size,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				     &rdev->gart.table.vram.robj);
 		if (r) {
@@ -149,8 +149,9 @@
 	p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 	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);
+			if (!rdev->gart.ttm_alloced[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] = rdev->dummy_page.addr;
 			page_base = rdev->gart.pages_addr[p];
@@ -165,7 +166,7 @@
 }
 
 int radeon_gart_bind(struct radeon_device *rdev, unsigned offset,
-		     int pages, struct page **pagelist)
+		     int pages, struct page **pagelist, dma_addr_t *dma_addr)
 {
 	unsigned t;
 	unsigned p;
@@ -180,15 +181,22 @@
 	p = t / (PAGE_SIZE / RADEON_GPU_PAGE_SIZE);
 
 	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],
+		/* we reverted the patch using dma_addr in TTM for now but this
+		 * code stops building on alpha so just comment it out for now */
+		if (0) { /*dma_addr[i] != DMA_ERROR_CODE) */
+			rdev->gart.ttm_alloced[p] = true;
+			rdev->gart.pages_addr[p] = dma_addr[i];
+		} else {
+			/* 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;
+			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];
@@ -251,6 +259,12 @@
 		radeon_gart_fini(rdev);
 		return -ENOMEM;
 	}
+	rdev->gart.ttm_alloced = kzalloc(sizeof(bool) *
+					 rdev->gart.num_cpu_pages, GFP_KERNEL);
+	if (rdev->gart.ttm_alloced == NULL) {
+		radeon_gart_fini(rdev);
+		return -ENOMEM;
+	}
 	/* set GART entry to point to the dummy page by default */
 	for (i = 0; i < rdev->gart.num_cpu_pages; i++) {
 		rdev->gart.pages_addr[i] = rdev->dummy_page.addr;
@@ -267,6 +281,10 @@
 	rdev->gart.ready = false;
 	kfree(rdev->gart.pages);
 	kfree(rdev->gart.pages_addr);
+	kfree(rdev->gart.ttm_alloced);
 	rdev->gart.pages = NULL;
 	rdev->gart.pages_addr = NULL;
+	rdev->gart.ttm_alloced = NULL;
+
+	radeon_dummy_page_fini(rdev);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_gem.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_gem.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_gem.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,21 +32,18 @@
 
 int radeon_gem_object_init(struct drm_gem_object *obj)
 {
-	/* we do nothings here */
+	BUG();
+
 	return 0;
 }
 
 void radeon_gem_object_free(struct drm_gem_object *gobj)
 {
-	struct radeon_bo *robj = gobj->driver_private;
+	struct radeon_bo *robj = gem_to_radeon_bo(gobj);
 
-	gobj->driver_private = NULL;
 	if (robj) {
 		radeon_bo_unref(&robj);
 	}
-
-	drm_gem_object_release(gobj);
-	kfree(gobj);
 }
 
 int radeon_gem_object_create(struct radeon_device *rdev, int size,
@@ -54,36 +51,34 @@
 				bool discardable, bool kernel,
 				struct drm_gem_object **obj)
 {
-	struct drm_gem_object *gobj;
 	struct radeon_bo *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_bo_create(rdev, gobj, size, alignment, kernel, initial_domain, &robj);
+	r = radeon_bo_create(rdev, size, alignment, kernel, initial_domain, &robj);
 	if (r) {
 		if (r != -ERESTARTSYS)
 			DRM_ERROR("Failed to allocate GEM object (%d, %d, %u, %d)\n",
 				  size, initial_domain, alignment, r);
-		drm_gem_object_unreference_unlocked(gobj);
 		return r;
 	}
-	gobj->driver_private = robj;
-	*obj = gobj;
+	*obj = &robj->gem_base;
+
+	mutex_lock(&rdev->gem.mutex);
+	list_add_tail(&robj->list, &rdev->gem.objects);
+	mutex_unlock(&rdev->gem.mutex);
+
 	return 0;
 }
 
 int radeon_gem_object_pin(struct drm_gem_object *obj, uint32_t pin_domain,
 			  uint64_t *gpu_addr)
 {
-	struct radeon_bo *robj = obj->driver_private;
+	struct radeon_bo *robj = gem_to_radeon_bo(obj);
 	int r;
 
 	r = radeon_bo_reserve(robj, false);
@@ -96,7 +91,7 @@
 
 void radeon_gem_object_unpin(struct drm_gem_object *obj)
 {
-	struct radeon_bo *robj = obj->driver_private;
+	struct radeon_bo *robj = gem_to_radeon_bo(obj);
 	int r;
 
 	r = radeon_bo_reserve(robj, false);
@@ -114,7 +109,7 @@
 	int r;
 
 	/* FIXME: reeimplement */
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	/* work out where to validate the buffer to */
 	domain = wdomain;
 	if (!domain) {
@@ -231,7 +226,7 @@
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 
 	r = radeon_gem_set_domain(gobj, args->read_domains, args->write_domain);
 
@@ -239,23 +234,31 @@
 	return r;
 }
 
-int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
-			  struct drm_file *filp)
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+			  struct drm_device *dev,
+			  uint32_t handle, uint64_t *offset_p)
 {
-	struct drm_radeon_gem_mmap *args = data;
 	struct drm_gem_object *gobj;
 	struct radeon_bo *robj;
 
-	gobj = drm_gem_object_lookup(dev, filp, args->handle);
+	gobj = drm_gem_object_lookup(dev, filp, handle);
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
-	args->addr_ptr = radeon_bo_mmap_offset(robj);
+	robj = gem_to_radeon_bo(gobj);
+	*offset_p = radeon_bo_mmap_offset(robj);
 	drm_gem_object_unreference_unlocked(gobj);
 	return 0;
 }
 
+int radeon_gem_mmap_ioctl(struct drm_device *dev, void *data,
+			  struct drm_file *filp)
+{
+	struct drm_radeon_gem_mmap *args = data;
+
+	return radeon_mode_dumb_mmap(filp, dev, args->handle, &args->addr_ptr);
+}
+
 int radeon_gem_busy_ioctl(struct drm_device *dev, void *data,
 			  struct drm_file *filp)
 {
@@ -269,7 +272,7 @@
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	r = radeon_bo_wait(robj, &cur_placement, true);
 	switch (cur_placement) {
 	case TTM_PL_VRAM:
@@ -299,7 +302,7 @@
 	if (gobj == NULL) {
 		return -ENOENT;
 	}
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	r = radeon_bo_wait(robj, NULL, false);
 	/* callback hw specific functions if any */
 	if (robj->rdev->asic->ioctl_wait_idle)
@@ -320,7 +323,7 @@
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
-	robj = gobj->driver_private;
+	robj = gem_to_radeon_bo(gobj);
 	r = radeon_bo_set_tiling_flags(robj, args->tiling_flags, args->pitch);
 	drm_gem_object_unreference_unlocked(gobj);
 	return r;
@@ -338,7 +341,7 @@
 	gobj = drm_gem_object_lookup(dev, filp, args->handle);
 	if (gobj == NULL)
 		return -ENOENT;
-	rbo = gobj->driver_private;
+	rbo = gem_to_radeon_bo(gobj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		goto out;
@@ -348,3 +351,40 @@
 	drm_gem_object_unreference_unlocked(gobj);
 	return r;
 }
+
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    struct drm_mode_create_dumb *args)
+{
+	struct radeon_device *rdev = dev->dev_private;
+	struct drm_gem_object *gobj;
+	uint32_t handle;
+	int r;
+
+	args->pitch = radeon_align_pitch(rdev, args->width, args->bpp, 0) * ((args->bpp + 1) / 8);
+	args->size = args->pitch * args->height;
+	args->size = ALIGN(args->size, PAGE_SIZE);
+
+	r = radeon_gem_object_create(rdev, args->size, 0,
+				     RADEON_GEM_DOMAIN_VRAM,
+				     false, ttm_bo_type_device,
+				     &gobj);
+	if (r)
+		return -ENOMEM;
+
+	r = drm_gem_handle_create(file_priv, gobj, &handle);
+	/* drop reference from allocate - handle holds it now */
+	drm_gem_object_unreference_unlocked(gobj);
+	if (r) {
+		return r;
+	}
+	args->handle = handle;
+	return 0;
+}
+
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+			     struct drm_device *dev,
+			     uint32_t handle)
+{
+	return drm_gem_handle_delete(file_priv, handle);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon.h	2011-05-19 00:06:34.000000000 -0400
@@ -177,7 +177,7 @@
 void radeon_pm_resume(struct radeon_device *rdev);
 void radeon_combios_get_power_modes(struct radeon_device *rdev);
 void radeon_atombios_get_power_modes(struct radeon_device *rdev);
-void radeon_atom_set_voltage(struct radeon_device *rdev, u16 level);
+void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type);
 void rs690_pm_info(struct radeon_device *rdev);
 extern int rv6xx_get_temp(struct radeon_device *rdev);
 extern int rv770_get_temp(struct radeon_device *rdev);
@@ -258,8 +258,9 @@
 	int				surface_reg;
 	/* Constant after initialization */
 	struct radeon_device		*rdev;
-	struct drm_gem_object		*gobj;
+	struct drm_gem_object		gem_base;
 };
+#define gem_to_radeon_bo(gobj) container_of((gobj), struct radeon_bo, gem_base)
 
 struct radeon_bo_list {
 	struct ttm_validate_buffer tv;
@@ -288,6 +289,15 @@
 			  uint64_t *gpu_addr);
 void radeon_gem_object_unpin(struct drm_gem_object *obj);
 
+int radeon_mode_dumb_create(struct drm_file *file_priv,
+			    struct drm_device *dev,
+			    struct drm_mode_create_dumb *args);
+int radeon_mode_dumb_mmap(struct drm_file *filp,
+			  struct drm_device *dev,
+			  uint32_t handle, uint64_t *offset_p);
+int radeon_mode_dumb_destroy(struct drm_file *file_priv,
+			     struct drm_device *dev,
+			     uint32_t handle);
 
 /*
  * GART structures, functions & helpers
@@ -319,6 +329,7 @@
 	union radeon_gart_table		table;
 	struct page			**pages;
 	dma_addr_t			*pages_addr;
+	bool				*ttm_alloced;
 	bool				ready;
 };
 
@@ -331,7 +342,8 @@
 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);
+		     int pages, struct page **pagelist,
+		     dma_addr_t *dma_addr);
 
 
 /*
@@ -651,6 +663,8 @@
 
 #define RADEON_WB_SCRATCH_OFFSET 0
 #define RADEON_WB_CP_RPTR_OFFSET 1024
+#define RADEON_WB_CP1_RPTR_OFFSET 1280
+#define RADEON_WB_CP2_RPTR_OFFSET 1536
 #define R600_WB_IH_WPTR_OFFSET   2048
 #define R600_WB_EVENT_OFFSET     3072
 
@@ -665,11 +679,11 @@
  * @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)
+ * @sclk:          	GPU clock Mhz (core bandwidth 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.
+ * Bandwidth 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, ...)
  */
@@ -753,7 +767,9 @@
 	u8 vddci_id; /* index into vddci voltage table */
 	bool vddci_enabled;
 	/* r6xx+ sw */
-	u32 voltage;
+	u16 voltage;
+	/* evergreen+ vddci */
+	u16 vddci;
 };
 
 /* clock mode flags */
@@ -821,10 +837,12 @@
 	int                     default_power_state_index;
 	u32                     current_sclk;
 	u32                     current_mclk;
-	u32                     current_vddc;
+	u16                     current_vddc;
+	u16                     current_vddci;
 	u32                     default_sclk;
 	u32                     default_mclk;
-	u32                     default_vddc;
+	u16                     default_vddc;
+	u16                     default_vddci;
 	struct radeon_i2c_chan *i2c_bus;
 	/* selected pm method */
 	enum radeon_pm_method     pm_method;
@@ -1037,12 +1055,52 @@
 	struct r100_gpu_lockup	lockup;
 };
 
+struct cayman_asic {
+	unsigned max_shader_engines;
+	unsigned max_pipes_per_simd;
+	unsigned max_tile_pipes;
+	unsigned max_simds_per_se;
+	unsigned max_backends_per_se;
+	unsigned max_texture_channel_caches;
+	unsigned max_gprs;
+	unsigned max_threads;
+	unsigned max_gs_threads;
+	unsigned max_stack_entries;
+	unsigned sx_num_of_sets;
+	unsigned sx_max_export_size;
+	unsigned sx_max_export_pos_size;
+	unsigned sx_max_export_smx_size;
+	unsigned max_hw_contexts;
+	unsigned sq_num_cf_insts;
+	unsigned sc_prim_fifo_size;
+	unsigned sc_hiz_tile_fifo_size;
+	unsigned sc_earlyz_tile_fifo_size;
+
+	unsigned num_shader_engines;
+	unsigned num_shader_pipes_per_simd;
+	unsigned num_tile_pipes;
+	unsigned num_simds_per_se;
+	unsigned num_backends_per_se;
+	unsigned backend_disable_mask_per_asic;
+	unsigned backend_map;
+	unsigned num_texture_channel_caches;
+	unsigned mem_max_burst_length_bytes;
+	unsigned mem_row_size_in_kb;
+	unsigned shader_engine_tile_size;
+	unsigned num_gpus;
+	unsigned multi_gpu_tile_size;
+
+	unsigned tile_config;
+	struct r100_gpu_lockup	lockup;
+};
+
 union radeon_asic_config {
 	struct r300_asic	r300;
 	struct r100_asic	r100;
 	struct r600_asic	r600;
 	struct rv770_asic	rv770;
 	struct evergreen_asic	evergreen;
+	struct cayman_asic	cayman;
 };
 
 /*
@@ -1133,6 +1191,9 @@
 	struct radeon_mman		mman;
 	struct radeon_fence_driver	fence_drv;
 	struct radeon_cp		cp;
+	/* cayman compute rings */
+	struct radeon_cp		cp1;
+	struct radeon_cp		cp2;
 	struct radeon_ib_pool		ib_pool;
 	struct radeon_irq		irq;
 	struct radeon_asic		*asic;
@@ -1185,19 +1246,6 @@
 void radeon_device_fini(struct radeon_device *rdev);
 int radeon_gpu_wait_for_idle(struct radeon_device *rdev);
 
-/* r600 blit */
-int r600_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
-void r600_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
-void r600_kms_blit_copy(struct radeon_device *rdev,
-			u64 src_gpu_addr, u64 dst_gpu_addr,
-			int size_bytes);
-/* evergreen blit */
-int evergreen_blit_prepare_copy(struct radeon_device *rdev, int size_bytes);
-void evergreen_blit_done_copy(struct radeon_device *rdev, struct radeon_fence *fence);
-void evergreen_kms_blit_copy(struct radeon_device *rdev,
-			     u64 src_gpu_addr, u64 dst_gpu_addr,
-			     int size_bytes);
-
 static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg)
 {
 	if (reg < rdev->rmmio_size)
@@ -1449,62 +1497,15 @@
 extern int radeon_suspend_kms(struct drm_device *dev, pm_message_t state);
 extern void radeon_ttm_set_active_vram_size(struct radeon_device *rdev, u64 size);
 
-/* r600, rv610, rv630, rv620, rv635, rv670, rs780, rs880 */
-extern bool r600_card_posted(struct radeon_device *rdev);
-extern void r600_cp_stop(struct radeon_device *rdev);
-extern int r600_cp_start(struct radeon_device *rdev);
-extern void r600_ring_init(struct radeon_device *rdev, unsigned ring_size);
-extern int r600_cp_resume(struct radeon_device *rdev);
-extern void r600_cp_fini(struct radeon_device *rdev);
-extern int r600_count_pipe_bits(uint32_t val);
-extern int r600_mc_wait_for_idle(struct radeon_device *rdev);
-extern int r600_pcie_gart_init(struct radeon_device *rdev);
-extern void r600_pcie_gart_tlb_flush(struct radeon_device *rdev);
-extern int r600_ib_test(struct radeon_device *rdev);
-extern int r600_ring_test(struct radeon_device *rdev);
-extern void r600_scratch_init(struct radeon_device *rdev);
-extern int r600_blit_init(struct radeon_device *rdev);
-extern void r600_blit_fini(struct radeon_device *rdev);
-extern int r600_init_microcode(struct radeon_device *rdev);
-extern int r600_asic_reset(struct radeon_device *rdev);
-/* r600 irq */
-extern int r600_irq_init(struct radeon_device *rdev);
-extern void r600_irq_fini(struct radeon_device *rdev);
-extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size);
-extern int r600_irq_set(struct radeon_device *rdev);
-extern void r600_irq_suspend(struct radeon_device *rdev);
-extern void r600_disable_interrupts(struct radeon_device *rdev);
-extern void r600_rlc_stop(struct radeon_device *rdev);
-/* r600 audio */
-extern int r600_audio_init(struct radeon_device *rdev);
-extern int r600_audio_tmds_index(struct drm_encoder *encoder);
-extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
-extern int r600_audio_channels(struct radeon_device *rdev);
-extern int r600_audio_bits_per_sample(struct radeon_device *rdev);
-extern int r600_audio_rate(struct radeon_device *rdev);
-extern uint8_t r600_audio_status_bits(struct radeon_device *rdev);
-extern uint8_t r600_audio_category_code(struct radeon_device *rdev);
-extern void r600_audio_schedule_polling(struct radeon_device *rdev);
-extern void r600_audio_enable_polling(struct drm_encoder *encoder);
-extern void r600_audio_disable_polling(struct drm_encoder *encoder);
-extern void r600_audio_fini(struct radeon_device *rdev);
-extern void r600_hdmi_init(struct drm_encoder *encoder);
+/*
+ * r600 functions used by radeon_encoder.c
+ */
 extern void r600_hdmi_enable(struct drm_encoder *encoder);
 extern void r600_hdmi_disable(struct drm_encoder *encoder);
 extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
-extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
-extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder);
-
-extern void r700_vram_gtt_location(struct radeon_device *rdev, struct radeon_mc *mc);
-extern void r700_cp_stop(struct radeon_device *rdev);
-extern void r700_cp_fini(struct radeon_device *rdev);
-extern void evergreen_disable_interrupt_state(struct radeon_device *rdev);
-extern int evergreen_irq_set(struct radeon_device *rdev);
-extern int evergreen_blit_init(struct radeon_device *rdev);
-extern void evergreen_blit_fini(struct radeon_device *rdev);
 
 extern int ni_init_microcode(struct radeon_device *rdev);
-extern int btc_mc_load_microcode(struct radeon_device *rdev);
+extern int ni_mc_load_microcode(struct radeon_device *rdev);
 
 /* radeon_acpi.c */ 
 #if defined(CONFIG_ACPI) 
@@ -1513,14 +1514,6 @@
 static inline int radeon_acpi_init(struct radeon_device *rdev) { return 0; } 
 #endif 
 
-/* evergreen */
-struct evergreen_mc_save {
-	u32 vga_control[6];
-	u32 vga_render_control;
-	u32 vga_hdp_control;
-	u32 crtc_control[6];
-};
-
 #include "radeon_object.h"
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_i2c.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_i2c.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -1062,7 +1062,7 @@
 		*val = in_buf[0];
 		DRM_DEBUG("val = 0x%02x\n", *val);
 	} else {
-		DRM_ERROR("i2c 0x%02x 0x%02x read failed\n",
+		DRM_DEBUG("i2c 0x%02x 0x%02x read failed\n",
 			  addr, *val);
 	}
 }
@@ -1084,7 +1084,7 @@
 	out_buf[1] = val;
 
 	if (i2c_transfer(&i2c_bus->adapter, &msg, 1) != 1)
-		DRM_ERROR("i2c 0x%02x 0x%02x write failed\n",
+		DRM_DEBUG("i2c 0x%02x 0x%02x write failed\n",
 			  addr, val);
 }
 
@@ -1096,6 +1096,9 @@
 	if (!radeon_connector->router.ddc_valid)
 		return;
 
+	if (!radeon_connector->router_bus)
+		return;
+
 	radeon_i2c_get_byte(radeon_connector->router_bus,
 			    radeon_connector->router.i2c_addr,
 			    0x3, &val);
@@ -1121,6 +1124,9 @@
 	if (!radeon_connector->router.cd_valid)
 		return;
 
+	if (!radeon_connector->router_bus)
+		return;
+
 	radeon_i2c_get_byte(radeon_connector->router_bus,
 			    radeon_connector->router.i2c_addr,
 			    0x3, &val);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_kms.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_kms.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_kms.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,9 +58,9 @@
 	dev->dev_private = (void *)rdev;
 
 	/* update BUS flag */
-	if (drm_device_is_agp(dev)) {
+	if (drm_pci_device_is_agp(dev)) {
 		flags |= RADEON_IS_AGP;
-	} else if (drm_device_is_pcie(dev)) {
+	} else if (drm_pci_device_is_pcie(dev)) {
 		flags |= RADEON_IS_PCIE;
 	} else {
 		flags |= RADEON_IS_PCI;
@@ -169,7 +169,9 @@
 		value = rdev->accel_working;
 		break;
 	case RADEON_INFO_TILING_CONFIG:
-		if (rdev->family >= CHIP_CEDAR)
+		if (rdev->family >= CHIP_CAYMAN)
+			value = rdev->config.cayman.tile_config;
+		else if (rdev->family >= CHIP_CEDAR)
 			value = rdev->config.evergreen.tile_config;
 		else if (rdev->family >= CHIP_RV770)
 			value = rdev->config.rv770.tile_config;
@@ -205,6 +207,36 @@
 		/* return clock value in KHz */
 		value = rdev->clock.spll.reference_freq * 10;
 		break;
+	case RADEON_INFO_NUM_BACKENDS:
+		if (rdev->family >= CHIP_CAYMAN)
+			value = rdev->config.cayman.max_backends_per_se *
+				rdev->config.cayman.max_shader_engines;
+		else if (rdev->family >= CHIP_CEDAR)
+			value = rdev->config.evergreen.max_backends;
+		else if (rdev->family >= CHIP_RV770)
+			value = rdev->config.rv770.max_backends;
+		else if (rdev->family >= CHIP_R600)
+			value = rdev->config.r600.max_backends;
+		else {
+			return -EINVAL;
+		}
+		break;
+	case RADEON_INFO_NUM_TILE_PIPES:
+		if (rdev->family >= CHIP_CAYMAN)
+			value = rdev->config.cayman.max_tile_pipes;
+		else if (rdev->family >= CHIP_CEDAR)
+			value = rdev->config.evergreen.max_tile_pipes;
+		else if (rdev->family >= CHIP_RV770)
+			value = rdev->config.rv770.max_tile_pipes;
+		else if (rdev->family >= CHIP_R600)
+			value = rdev->config.r600.max_tile_pipes;
+		else {
+			return -EINVAL;
+		}
+		break;
+	case RADEON_INFO_FUSION_GART_WORKING:
+		value = 1;
+		break;
 	default:
 		DRM_DEBUG_KMS("Invalid request %d\n", info->request);
 		return -EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_legacy_crtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -415,7 +415,7 @@
 
 	/* Pin framebuffer & get tilling informations */
 	obj = radeon_fb->obj;
-	rbo = obj->driver_private;
+	rbo = gem_to_radeon_bo(obj);
 	r = radeon_bo_reserve(rbo, false);
 	if (unlikely(r != 0))
 		return r;
@@ -521,7 +521,7 @@
 
 	if (!atomic && fb && fb != crtc->fb) {
 		radeon_fb = to_radeon_framebuffer(fb);
-		rbo = radeon_fb->obj->driver_private;
+		rbo = gem_to_radeon_bo(radeon_fb->obj);
 		r = radeon_bo_reserve(rbo, false);
 		if (unlikely(r != 0))
 			return r;
@@ -889,7 +889,7 @@
 		}
 
 		if (rdev->flags & RADEON_IS_MOBILITY) {
-			/* A temporal workaround for the occational blanking on certain laptop panels.
+			/* A temporal workaround for the occasional 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.
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_legacy_encoders.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,10 @@
 #include "radeon_drm.h"
 #include "radeon.h"
 #include "atom.h"
+#include <linux/backlight.h>
+#ifdef CONFIG_PMAC_BACKLIGHT
+#include <asm/backlight.h>
+#endif
 
 static void radeon_legacy_encoder_disable(struct drm_encoder *encoder)
 {
@@ -39,7 +43,7 @@
 	radeon_encoder->active_device = 0;
 }
 
-static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+static void radeon_legacy_lvds_update(struct drm_encoder *encoder, int mode)
 {
 	struct drm_device *dev = encoder->dev;
 	struct radeon_device *rdev = dev->dev_private;
@@ -47,15 +51,23 @@
 	uint32_t lvds_gen_cntl, lvds_pll_cntl, pixclks_cntl, disp_pwr_man;
 	int panel_pwr_delay = 2000;
 	bool is_mac = false;
+	uint8_t backlight_level;
 	DRM_DEBUG_KMS("\n");
 
+	lvds_gen_cntl = RREG32(RADEON_LVDS_GEN_CNTL);
+	backlight_level = (lvds_gen_cntl >> RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
 	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;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		} else {
 			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
 			panel_pwr_delay = lvds->panel_pwr_delay;
+			if (lvds->bl_dev)
+				backlight_level = lvds->backlight_level;
 		}
 	}
 
@@ -82,11 +94,13 @@
 		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 |
+				   RADEON_LVDS_BL_MOD_LEVEL_MASK);
+		lvds_gen_cntl |= (RADEON_LVDS_ON | RADEON_LVDS_EN |
+				  RADEON_LVDS_DIGON | RADEON_LVDS_BLON |
+				  (backlight_level << RADEON_LVDS_BL_MOD_LEVEL_SHIFT));
 		if (is_mac)
 			lvds_gen_cntl |= RADEON_LVDS_BL_MOD_EN;
-		lvds_gen_cntl &= ~(RADEON_LVDS_DISPLAY_DIS);
 		udelay(panel_pwr_delay * 1000);
 		WREG32(RADEON_LVDS_GEN_CNTL, lvds_gen_cntl);
 		break;
@@ -95,7 +109,6 @@
 	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;
 		if (is_mac) {
 			lvds_gen_cntl &= ~RADEON_LVDS_BL_MOD_EN;
@@ -119,6 +132,25 @@
 
 }
 
+static void radeon_legacy_lvds_dpms(struct drm_encoder *encoder, int mode)
+{
+	struct radeon_device *rdev = encoder->dev->dev_private;
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+	DRM_DEBUG("\n");
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			lvds->dpms_mode = mode;
+		}
+	}
+
+	radeon_legacy_lvds_update(encoder, mode);
+}
+
 static void radeon_legacy_lvds_prepare(struct drm_encoder *encoder)
 {
 	struct radeon_device *rdev = encoder->dev->dev_private;
@@ -237,9 +269,222 @@
 	.disable = radeon_legacy_encoder_disable,
 };
 
+#if defined(CONFIG_BACKLIGHT_CLASS_DEVICE) || defined(CONFIG_BACKLIGHT_CLASS_DEVICE_MODULE)
+
+#define MAX_RADEON_LEVEL 0xFF
+
+struct radeon_backlight_privdata {
+	struct radeon_encoder *encoder;
+	uint8_t negative;
+};
+
+static uint8_t radeon_legacy_lvds_level(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	uint8_t level;
+
+	/* Convert brightness to hardware level */
+	if (bd->props.brightness < 0)
+		level = 0;
+	else if (bd->props.brightness > MAX_RADEON_LEVEL)
+		level = MAX_RADEON_LEVEL;
+	else
+		level = bd->props.brightness;
+
+	if (pdata->negative)
+		level = MAX_RADEON_LEVEL - level;
+
+	return level;
+}
+
+static int radeon_legacy_backlight_update_status(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	int dpms_mode = DRM_MODE_DPMS_ON;
+
+	if (radeon_encoder->enc_priv) {
+		if (rdev->is_atom_bios) {
+			struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		} else {
+			struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+			dpms_mode = lvds->dpms_mode;
+			lvds->backlight_level = radeon_legacy_lvds_level(bd);
+		}
+	}
+
+	if (bd->props.brightness > 0)
+		radeon_legacy_lvds_update(&radeon_encoder->base, dpms_mode);
+	else
+		radeon_legacy_lvds_update(&radeon_encoder->base, DRM_MODE_DPMS_OFF);
+
+	return 0;
+}
+
+static int radeon_legacy_backlight_get_brightness(struct backlight_device *bd)
+{
+	struct radeon_backlight_privdata *pdata = bl_get_data(bd);
+	struct radeon_encoder *radeon_encoder = pdata->encoder;
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	uint8_t backlight_level;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	return pdata->negative ? MAX_RADEON_LEVEL - backlight_level : backlight_level;
+}
+
+static const struct backlight_ops radeon_backlight_ops = {
+	.get_brightness = radeon_legacy_backlight_get_brightness,
+	.update_status	= radeon_legacy_backlight_update_status,
+};
+
+void radeon_legacy_backlight_init(struct radeon_encoder *radeon_encoder,
+				  struct drm_connector *drm_connector)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	struct radeon_backlight_privdata *pdata;
+	uint8_t backlight_level;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+	if (!pmac_has_backlight_type("ati") &&
+	    !pmac_has_backlight_type("mnca"))
+		return;
+#endif
+
+	pdata = kmalloc(sizeof(struct radeon_backlight_privdata), GFP_KERNEL);
+	if (!pdata) {
+		DRM_ERROR("Memory allocation failed\n");
+		goto error;
+	}
+
+	props.max_brightness = MAX_RADEON_LEVEL;
+	props.type = BACKLIGHT_RAW;
+	bd = backlight_device_register("radeon_bl", &drm_connector->kdev,
+				       pdata, &radeon_backlight_ops, &props);
+	if (IS_ERR(bd)) {
+		DRM_ERROR("Backlight registration failed\n");
+		goto error;
+	}
+
+	pdata->encoder = radeon_encoder;
+
+	backlight_level = (RREG32(RADEON_LVDS_GEN_CNTL) >>
+			   RADEON_LVDS_BL_MOD_LEVEL_SHIFT) & 0xff;
+
+	/* First, try to detect backlight level sense based on the assumption
+	 * that firmware set it up at full brightness
+	 */
+	if (backlight_level == 0)
+		pdata->negative = true;
+	else if (backlight_level == 0xff)
+		pdata->negative = false;
+	else {
+		/* XXX hack... maybe some day we can figure out in what direction
+		 * backlight should work on a given panel?
+		 */
+		pdata->negative = (rdev->family != CHIP_RV200 &&
+				   rdev->family != CHIP_RV250 &&
+				   rdev->family != CHIP_RV280 &&
+				   rdev->family != CHIP_RV350);
+
+#ifdef CONFIG_PMAC_BACKLIGHT
+		pdata->negative = (pdata->negative ||
+				   of_machine_is_compatible("PowerBook4,3") ||
+				   of_machine_is_compatible("PowerBook6,3") ||
+				   of_machine_is_compatible("PowerBook6,5"));
+#endif
+	}
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		lvds->bl_dev = bd;
+	}
+
+	bd->props.brightness = radeon_legacy_backlight_get_brightness(bd);
+	bd->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(bd);
+
+	DRM_INFO("radeon legacy LVDS backlight initialized\n");
+
+	return;
+
+error:
+	kfree(pdata);
+	return;
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *radeon_encoder)
+{
+	struct drm_device *dev = radeon_encoder->base.dev;
+	struct radeon_device *rdev = dev->dev_private;
+	struct backlight_device *bd = NULL;
+
+	if (!radeon_encoder->enc_priv)
+		return;
+
+	if (rdev->is_atom_bios) {
+		struct radeon_encoder_atom_dig *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	} else {
+		struct radeon_encoder_lvds *lvds = radeon_encoder->enc_priv;
+		bd = lvds->bl_dev;
+		lvds->bl_dev = NULL;
+	}
+
+	if (bd) {
+		struct radeon_legacy_backlight_privdata *pdata;
+
+		pdata = bl_get_data(bd);
+		backlight_device_unregister(bd);
+		kfree(pdata);
+
+		DRM_INFO("radeon legacy LVDS backlight unloaded\n");
+	}
+}
+
+#else /* !CONFIG_BACKLIGHT_CLASS_DEVICE */
+
+void radeon_legacy_backlight_init(struct radeon_encoder *encoder)
+{
+}
+
+static void radeon_legacy_backlight_exit(struct radeon_encoder *encoder)
+{
+}
+
+#endif
+
+
+static void radeon_lvds_enc_destroy(struct drm_encoder *encoder)
+{
+	struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+
+	if (radeon_encoder->enc_priv) {
+		radeon_legacy_backlight_exit(radeon_encoder);
+		kfree(radeon_encoder->enc_priv);
+	}
+	drm_encoder_cleanup(encoder);
+	kfree(radeon_encoder);
+}
 
 static const struct drm_encoder_funcs radeon_legacy_lvds_enc_funcs = {
-	.destroy = radeon_enc_destroy,
+	.destroy = radeon_lvds_enc_destroy,
 };
 
 static void radeon_legacy_primary_dac_dpms(struct drm_encoder *encoder, int mode)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_mode.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_mode.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_mode.h	2011-05-19 00:06:34.000000000 -0400
@@ -239,6 +239,7 @@
 	struct drm_property *underscan_vborder_property;
 	/* hardcoded DFP edid from BIOS */
 	struct edid *bios_hardcoded_edid;
+	int bios_hardcoded_edid_size;
 
 	/* pointer to fbdev info structure */
 	struct radeon_fbdev *rfbdev;
@@ -302,6 +303,9 @@
 	uint32_t lvds_gen_cntl;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int      dpms_mode;
+	uint8_t  backlight_level;
 };
 
 struct radeon_encoder_tv_dac {
@@ -355,6 +359,9 @@
 	uint32_t lcd_ss_id;
 	/* panel mode */
 	struct drm_display_mode native_mode;
+	struct backlight_device *bl_dev;
+	int dpms_mode;
+	uint8_t backlight_level;
 };
 
 struct radeon_encoder_atom_dac {
@@ -676,4 +683,5 @@
 
 void radeon_crtc_handle_flip(struct radeon_device *rdev, int crtc_id);
 
+int radeon_align_pitch(struct radeon_device *rdev, int width, int bpp, bool tiled);
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_object.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_object.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_object.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_object.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,6 +55,7 @@
 	list_del_init(&bo->list);
 	mutex_unlock(&bo->rdev->gem.mutex);
 	radeon_bo_clear_surface_reg(bo);
+	drm_gem_object_release(&bo->gem_base);
 	kfree(bo);
 }
 
@@ -86,7 +87,7 @@
 	rbo->placement.num_busy_placement = c;
 }
 
-int radeon_bo_create(struct radeon_device *rdev, struct drm_gem_object *gobj,
+int radeon_bo_create(struct radeon_device *rdev,
 		     unsigned long size, int byte_align, bool kernel, u32 domain,
 		     struct radeon_bo **bo_ptr)
 {
@@ -96,6 +97,8 @@
 	unsigned long max_size = 0;
 	int r;
 
+	size = ALIGN(size, PAGE_SIZE);
+
 	if (unlikely(rdev->mman.bdev.dev_mapping == NULL)) {
 		rdev->mman.bdev.dev_mapping = rdev->ddev->dev_mapping;
 	}
@@ -118,8 +121,13 @@
 	bo = kzalloc(sizeof(struct radeon_bo), GFP_KERNEL);
 	if (bo == NULL)
 		return -ENOMEM;
+	r = drm_gem_object_init(rdev->ddev, &bo->gem_base, size);
+	if (unlikely(r)) {
+		kfree(bo);
+		return r;
+	}
 	bo->rdev = rdev;
-	bo->gobj = gobj;
+	bo->gem_base.driver_private = NULL;
 	bo->surface_reg = -1;
 	INIT_LIST_HEAD(&bo->list);
 	radeon_ttm_placement_from_domain(bo, domain);
@@ -142,12 +150,9 @@
 		return r;
 	}
 	*bo_ptr = bo;
-	if (gobj) {
-		mutex_lock(&bo->rdev->gem.mutex);
-		list_add_tail(&bo->list, &rdev->gem.objects);
-		mutex_unlock(&bo->rdev->gem.mutex);
-	}
+
 	trace_radeon_bo_create(bo);
+
 	return 0;
 }
 
@@ -260,7 +265,6 @@
 void radeon_bo_force_delete(struct radeon_device *rdev)
 {
 	struct radeon_bo *bo, *n;
-	struct drm_gem_object *gobj;
 
 	if (list_empty(&rdev->gem.objects)) {
 		return;
@@ -268,16 +272,14 @@
 	dev_err(rdev->dev, "Userspace still has active objects !\n");
 	list_for_each_entry_safe(bo, n, &rdev->gem.objects, list) {
 		mutex_lock(&rdev->ddev->struct_mutex);
-		gobj = bo->gobj;
 		dev_err(rdev->dev, "%p %p %lu %lu force free\n",
-			gobj, bo, (unsigned long)gobj->size,
-			*((unsigned long *)&gobj->refcount));
+			&bo->gem_base, bo, (unsigned long)bo->gem_base.size,
+			*((unsigned long *)&bo->gem_base.refcount));
 		mutex_lock(&bo->rdev->gem.mutex);
 		list_del_init(&bo->list);
 		mutex_unlock(&bo->rdev->gem.mutex);
-		radeon_bo_unref(&bo);
-		gobj->driver_private = NULL;
-		drm_gem_object_unreference(gobj);
+		/* this should unref the ttm bo */
+		drm_gem_object_unreference(&bo->gem_base);
 		mutex_unlock(&rdev->ddev->struct_mutex);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_object.h linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_object.h
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_object.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_object.h	2011-05-19 00:06:34.000000000 -0400
@@ -87,7 +87,7 @@
  * Returns current GPU offset of the object.
  *
  * Note: object should either be pinned or reserved when calling this
- * function, it might be usefull to add check for this for debugging.
+ * function, it might be useful to add check for this for debugging.
  */
 static inline u64 radeon_bo_gpu_offset(struct radeon_bo *bo)
 {
@@ -137,10 +137,9 @@
 }
 
 extern int radeon_bo_create(struct radeon_device *rdev,
-			    struct drm_gem_object *gobj, unsigned long size,
-			    int byte_align,
-			    bool kernel, u32 domain,
-			    struct radeon_bo **bo_ptr);
+				unsigned long size, int byte_align,
+				bool kernel, u32 domain,
+				struct radeon_bo **bo_ptr);
 extern int radeon_bo_kmap(struct radeon_bo *bo, void **ptr);
 extern void radeon_bo_kunmap(struct radeon_bo *bo);
 extern void radeon_bo_unref(struct radeon_bo **bo);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_pm.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_pm.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 #include "drmP.h"
 #include "radeon.h"
 #include "avivod.h"
+#include "atom.h"
 #ifdef CONFIG_ACPI
 #include <linux/acpi.h>
 #endif
@@ -365,12 +366,14 @@
 		else if (strncmp("high", buf, strlen("high")) == 0)
 			rdev->pm.profile = PM_PROFILE_HIGH;
 		else {
-			DRM_ERROR("invalid power profile!\n");
+			count = -EINVAL;
 			goto fail;
 		}
 		radeon_pm_update_profile(rdev);
 		radeon_pm_set_clocks(rdev);
-	}
+	} else
+		count = -EINVAL;
+
 fail:
 	mutex_unlock(&rdev->pm.mutex);
 
@@ -413,7 +416,7 @@
 		mutex_unlock(&rdev->pm.mutex);
 		cancel_delayed_work_sync(&rdev->pm.dynpm_idle_work);
 	} else {
-		DRM_ERROR("invalid power method!\n");
+		count = -EINVAL;
 		goto fail;
 	}
 	radeon_pm_compute_clocks(rdev);
@@ -533,7 +536,11 @@
 	/* set up the default clocks if the MC ucode is loaded */
 	if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
 		if (rdev->pm.default_vddc)
-			radeon_atom_set_voltage(rdev, rdev->pm.default_vddc);
+			radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+						SET_VOLTAGE_TYPE_ASIC_VDDC);
+		if (rdev->pm.default_vddci)
+			radeon_atom_set_voltage(rdev, rdev->pm.default_vddci,
+						SET_VOLTAGE_TYPE_ASIC_VDDCI);
 		if (rdev->pm.default_sclk)
 			radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
 		if (rdev->pm.default_mclk)
@@ -546,6 +553,7 @@
 	rdev->pm.current_sclk = rdev->pm.default_sclk;
 	rdev->pm.current_mclk = rdev->pm.default_mclk;
 	rdev->pm.current_vddc = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.voltage;
+	rdev->pm.current_vddci = rdev->pm.power_state[rdev->pm.default_power_state_index].clock_info[0].voltage.vddci;
 	if (rdev->pm.pm_method == PM_METHOD_DYNPM
 	    && rdev->pm.dynpm_state == DYNPM_STATE_SUSPENDED) {
 		rdev->pm.dynpm_state = DYNPM_STATE_ACTIVE;
@@ -583,7 +591,8 @@
 		/* set up the default clocks if the MC ucode is loaded */
 		if (ASIC_IS_DCE5(rdev) && rdev->mc_fw) {
 			if (rdev->pm.default_vddc)
-				radeon_atom_set_voltage(rdev, rdev->pm.default_vddc);
+				radeon_atom_set_voltage(rdev, rdev->pm.default_vddc,
+							SET_VOLTAGE_TYPE_ASIC_VDDC);
 			if (rdev->pm.default_sclk)
 				radeon_set_engine_clock(rdev, rdev->pm.default_sclk);
 			if (rdev->pm.default_mclk)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_ring.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_ring.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_ring.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,7 +151,7 @@
 	/* 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);
+		DRM_ERROR("radeon: scheduling IB failed (%d).\n", r);
 		return r;
 	}
 	radeon_ring_ib_execute(rdev, ib);
@@ -175,7 +175,7 @@
 		return 0;
 	INIT_LIST_HEAD(&rdev->ib_pool.bogus_ib);
 	/* Allocate 1M object buffer */
-	r = radeon_bo_create(rdev, NULL,  RADEON_IB_POOL_SIZE*64*1024,
+	r = radeon_bo_create(rdev, RADEON_IB_POOL_SIZE*64*1024,
 			     PAGE_SIZE, true, RADEON_GEM_DOMAIN_GTT,
 			     &rdev->ib_pool.robj);
 	if (r) {
@@ -248,7 +248,7 @@
 void radeon_ring_free_size(struct radeon_device *rdev)
 {
 	if (rdev->wb.enabled)
-		rdev->cp.rptr = rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4];
+		rdev->cp.rptr = le32_to_cpu(rdev->wb.wb[RADEON_WB_CP_RPTR_OFFSET/4]);
 	else {
 		if (rdev->family >= CHIP_R600)
 			rdev->cp.rptr = RREG32(R600_CP_RB_RPTR);
@@ -332,7 +332,7 @@
 	rdev->cp.ring_size = ring_size;
 	/* Allocate ring buffer */
 	if (rdev->cp.ring_obj == NULL) {
-		r = radeon_bo_create(rdev, NULL, rdev->cp.ring_size, PAGE_SIZE, true,
+		r = radeon_bo_create(rdev, rdev->cp.ring_size, PAGE_SIZE, true,
 					RADEON_GEM_DOMAIN_GTT,
 					&rdev->cp.ring_obj);
 		if (r) {
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_state.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_state.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_state.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_state.c	2011-05-19 00:06:34.000000000 -0400
@@ -980,7 +980,7 @@
 	}
 
 	/* hyper z clear */
-	/* no docs available, based on reverse engeneering by Stephane Marchesin */
+	/* no docs available, based on reverse engineering by Stephane Marchesin */
 	if ((flags & (RADEON_DEPTH | RADEON_STENCIL))
 	    && (flags & RADEON_CLEAR_FASTZ)) {
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_test.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_test.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_test.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_test.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,7 +52,7 @@
 		goto out_cleanup;
 	}
 
-	r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
+	r = radeon_bo_create(rdev, size, PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				&vram_obj);
 	if (r) {
 		DRM_ERROR("Failed to create VRAM object\n");
@@ -71,7 +71,7 @@
 		void **gtt_start, **gtt_end;
 		void **vram_start, **vram_end;
 
-		r = radeon_bo_create(rdev, NULL, size, PAGE_SIZE, true,
+		r = radeon_bo_create(rdev, size, PAGE_SIZE, true,
 					 RADEON_GEM_DOMAIN_GTT, gtt_obj + i);
 		if (r) {
 			DRM_ERROR("Failed to create GTT object %d\n", i);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_ttm.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_ttm.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/radeon_ttm.c	2011-05-19 00:06:34.000000000 -0400
@@ -529,7 +529,7 @@
 		DRM_ERROR("Failed initializing VRAM heap.\n");
 		return r;
 	}
-	r = radeon_bo_create(rdev, NULL, 256 * 1024, PAGE_SIZE, true,
+	r = radeon_bo_create(rdev, 256 * 1024, PAGE_SIZE, true,
 				RADEON_GEM_DOMAIN_VRAM,
 				&rdev->stollen_vga_memory);
 	if (r) {
@@ -661,6 +661,7 @@
 	unsigned long			num_pages;
 	struct page			**pages;
 	struct page			*dummy_read_page;
+	dma_addr_t			*dma_addrs;
 	bool				populated;
 	bool				bound;
 	unsigned			offset;
@@ -669,12 +670,14 @@
 static int radeon_ttm_backend_populate(struct ttm_backend *backend,
 				       unsigned long num_pages,
 				       struct page **pages,
-				       struct page *dummy_read_page)
+				       struct page *dummy_read_page,
+				       dma_addr_t *dma_addrs)
 {
 	struct radeon_ttm_backend *gtt;
 
 	gtt = container_of(backend, struct radeon_ttm_backend, backend);
 	gtt->pages = pages;
+	gtt->dma_addrs = dma_addrs;
 	gtt->num_pages = num_pages;
 	gtt->dummy_read_page = dummy_read_page;
 	gtt->populated = true;
@@ -687,6 +690,7 @@
 
 	gtt = container_of(backend, struct radeon_ttm_backend, backend);
 	gtt->pages = NULL;
+	gtt->dma_addrs = NULL;
 	gtt->num_pages = 0;
 	gtt->dummy_read_page = NULL;
 	gtt->populated = false;
@@ -707,7 +711,7 @@
 		     gtt->num_pages, bo_mem, backend);
 	}
 	r = radeon_gart_bind(gtt->rdev, gtt->offset,
-			     gtt->num_pages, gtt->pages);
+			     gtt->num_pages, gtt->pages, gtt->dma_addrs);
 	if (r) {
 		DRM_ERROR("failed to bind %lu pages at 0x%08X\n",
 			  gtt->num_pages, gtt->offset);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/reg_srcs/cayman linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/reg_srcs/cayman
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/reg_srcs/cayman	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/reg_srcs/cayman	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,620 @@
+cayman 0x9400
+0x0000802C GRBM_GFX_INDEX
+0x000088B0 VGT_VTX_VECT_EJECT_REG
+0x000088C4 VGT_CACHE_INVALIDATION
+0x000088D4 VGT_GS_VERTEX_REUSE
+0x00008958 VGT_PRIMITIVE_TYPE
+0x0000895C VGT_INDEX_TYPE
+0x00008970 VGT_NUM_INDICES
+0x00008974 VGT_NUM_INSTANCES
+0x00008990 VGT_COMPUTE_DIM_X
+0x00008994 VGT_COMPUTE_DIM_Y
+0x00008998 VGT_COMPUTE_DIM_Z
+0x0000899C VGT_COMPUTE_START_X
+0x000089A0 VGT_COMPUTE_START_Y
+0x000089A4 VGT_COMPUTE_START_Z
+0x000089A8 VGT_COMPUTE_INDEX
+0x000089AC VGT_COMPUTE_THREAD_GOURP_SIZE
+0x000089B0 VGT_HS_OFFCHIP_PARAM
+0x00008A14 PA_CL_ENHANCE
+0x00008A60 PA_SC_LINE_STIPPLE_VALUE
+0x00008B10 PA_SC_LINE_STIPPLE_STATE
+0x00008BF0 PA_SC_ENHANCE
+0x00008D8C SQ_DYN_GPR_CNTL_PS_FLUSH_REQ
+0x00008D94 SQ_DYN_GPR_SIMD_LOCK_EN
+0x00008C00 SQ_CONFIG
+0x00008C04 SQ_GPR_RESOURCE_MGMT_1
+0x00008C10 SQ_GLOBAL_GPR_RESOURCE_MGMT_1
+0x00008C14 SQ_GLOBAL_GPR_RESOURCE_MGMT_2
+0x00008DF8 SQ_CONST_MEM_BASE
+0x00008E20 SQ_STATIC_THREAD_MGMT_1
+0x00008E24 SQ_STATIC_THREAD_MGMT_2
+0x00008E28 SQ_STATIC_THREAD_MGMT_3
+0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
+0x00009100 SPI_CONFIG_CNTL
+0x0000913C SPI_CONFIG_CNTL_1
+0x00009508 TA_CNTL_AUX
+0x00009830 DB_DEBUG
+0x00009834 DB_DEBUG2
+0x00009838 DB_DEBUG3
+0x0000983C DB_DEBUG4
+0x00009854 DB_WATERMARKS
+0x0000A400 TD_PS_BORDER_COLOR_INDEX
+0x0000A404 TD_PS_BORDER_COLOR_RED
+0x0000A408 TD_PS_BORDER_COLOR_GREEN
+0x0000A40C TD_PS_BORDER_COLOR_BLUE
+0x0000A410 TD_PS_BORDER_COLOR_ALPHA
+0x0000A414 TD_VS_BORDER_COLOR_INDEX
+0x0000A418 TD_VS_BORDER_COLOR_RED
+0x0000A41C TD_VS_BORDER_COLOR_GREEN
+0x0000A420 TD_VS_BORDER_COLOR_BLUE
+0x0000A424 TD_VS_BORDER_COLOR_ALPHA
+0x0000A428 TD_GS_BORDER_COLOR_INDEX
+0x0000A42C TD_GS_BORDER_COLOR_RED
+0x0000A430 TD_GS_BORDER_COLOR_GREEN
+0x0000A434 TD_GS_BORDER_COLOR_BLUE
+0x0000A438 TD_GS_BORDER_COLOR_ALPHA
+0x0000A43C TD_HS_BORDER_COLOR_INDEX
+0x0000A440 TD_HS_BORDER_COLOR_RED
+0x0000A444 TD_HS_BORDER_COLOR_GREEN
+0x0000A448 TD_HS_BORDER_COLOR_BLUE
+0x0000A44C TD_HS_BORDER_COLOR_ALPHA
+0x0000A450 TD_LS_BORDER_COLOR_INDEX
+0x0000A454 TD_LS_BORDER_COLOR_RED
+0x0000A458 TD_LS_BORDER_COLOR_GREEN
+0x0000A45C TD_LS_BORDER_COLOR_BLUE
+0x0000A460 TD_LS_BORDER_COLOR_ALPHA
+0x0000A464 TD_CS_BORDER_COLOR_INDEX
+0x0000A468 TD_CS_BORDER_COLOR_RED
+0x0000A46C TD_CS_BORDER_COLOR_GREEN
+0x0000A470 TD_CS_BORDER_COLOR_BLUE
+0x0000A474 TD_CS_BORDER_COLOR_ALPHA
+0x00028000 DB_RENDER_CONTROL
+0x00028004 DB_COUNT_CONTROL
+0x0002800C DB_RENDER_OVERRIDE
+0x00028010 DB_RENDER_OVERRIDE2
+0x00028028 DB_STENCIL_CLEAR
+0x0002802C DB_DEPTH_CLEAR
+0x00028030 PA_SC_SCREEN_SCISSOR_TL
+0x00028034 PA_SC_SCREEN_SCISSOR_BR
+0x0002805C DB_DEPTH_SLICE
+0x00028140 SQ_ALU_CONST_BUFFER_SIZE_PS_0
+0x00028144 SQ_ALU_CONST_BUFFER_SIZE_PS_1
+0x00028148 SQ_ALU_CONST_BUFFER_SIZE_PS_2
+0x0002814C SQ_ALU_CONST_BUFFER_SIZE_PS_3
+0x00028150 SQ_ALU_CONST_BUFFER_SIZE_PS_4
+0x00028154 SQ_ALU_CONST_BUFFER_SIZE_PS_5
+0x00028158 SQ_ALU_CONST_BUFFER_SIZE_PS_6
+0x0002815C SQ_ALU_CONST_BUFFER_SIZE_PS_7
+0x00028160 SQ_ALU_CONST_BUFFER_SIZE_PS_8
+0x00028164 SQ_ALU_CONST_BUFFER_SIZE_PS_9
+0x00028168 SQ_ALU_CONST_BUFFER_SIZE_PS_10
+0x0002816C SQ_ALU_CONST_BUFFER_SIZE_PS_11
+0x00028170 SQ_ALU_CONST_BUFFER_SIZE_PS_12
+0x00028174 SQ_ALU_CONST_BUFFER_SIZE_PS_13
+0x00028178 SQ_ALU_CONST_BUFFER_SIZE_PS_14
+0x0002817C SQ_ALU_CONST_BUFFER_SIZE_PS_15
+0x00028180 SQ_ALU_CONST_BUFFER_SIZE_VS_0
+0x00028184 SQ_ALU_CONST_BUFFER_SIZE_VS_1
+0x00028188 SQ_ALU_CONST_BUFFER_SIZE_VS_2
+0x0002818C SQ_ALU_CONST_BUFFER_SIZE_VS_3
+0x00028190 SQ_ALU_CONST_BUFFER_SIZE_VS_4
+0x00028194 SQ_ALU_CONST_BUFFER_SIZE_VS_5
+0x00028198 SQ_ALU_CONST_BUFFER_SIZE_VS_6
+0x0002819C SQ_ALU_CONST_BUFFER_SIZE_VS_7
+0x000281A0 SQ_ALU_CONST_BUFFER_SIZE_VS_8
+0x000281A4 SQ_ALU_CONST_BUFFER_SIZE_VS_9
+0x000281A8 SQ_ALU_CONST_BUFFER_SIZE_VS_10
+0x000281AC SQ_ALU_CONST_BUFFER_SIZE_VS_11
+0x000281B0 SQ_ALU_CONST_BUFFER_SIZE_VS_12
+0x000281B4 SQ_ALU_CONST_BUFFER_SIZE_VS_13
+0x000281B8 SQ_ALU_CONST_BUFFER_SIZE_VS_14
+0x000281BC SQ_ALU_CONST_BUFFER_SIZE_VS_15
+0x000281C0 SQ_ALU_CONST_BUFFER_SIZE_GS_0
+0x000281C4 SQ_ALU_CONST_BUFFER_SIZE_GS_1
+0x000281C8 SQ_ALU_CONST_BUFFER_SIZE_GS_2
+0x000281CC SQ_ALU_CONST_BUFFER_SIZE_GS_3
+0x000281D0 SQ_ALU_CONST_BUFFER_SIZE_GS_4
+0x000281D4 SQ_ALU_CONST_BUFFER_SIZE_GS_5
+0x000281D8 SQ_ALU_CONST_BUFFER_SIZE_GS_6
+0x000281DC SQ_ALU_CONST_BUFFER_SIZE_GS_7
+0x000281E0 SQ_ALU_CONST_BUFFER_SIZE_GS_8
+0x000281E4 SQ_ALU_CONST_BUFFER_SIZE_GS_9
+0x000281E8 SQ_ALU_CONST_BUFFER_SIZE_GS_10
+0x000281EC SQ_ALU_CONST_BUFFER_SIZE_GS_11
+0x000281F0 SQ_ALU_CONST_BUFFER_SIZE_GS_12
+0x000281F4 SQ_ALU_CONST_BUFFER_SIZE_GS_13
+0x000281F8 SQ_ALU_CONST_BUFFER_SIZE_GS_14
+0x000281FC SQ_ALU_CONST_BUFFER_SIZE_GS_15
+0x00028200 PA_SC_WINDOW_OFFSET
+0x00028204 PA_SC_WINDOW_SCISSOR_TL
+0x00028208 PA_SC_WINDOW_SCISSOR_BR
+0x0002820C PA_SC_CLIPRECT_RULE
+0x00028210 PA_SC_CLIPRECT_0_TL
+0x00028214 PA_SC_CLIPRECT_0_BR
+0x00028218 PA_SC_CLIPRECT_1_TL
+0x0002821C PA_SC_CLIPRECT_1_BR
+0x00028220 PA_SC_CLIPRECT_2_TL
+0x00028224 PA_SC_CLIPRECT_2_BR
+0x00028228 PA_SC_CLIPRECT_3_TL
+0x0002822C PA_SC_CLIPRECT_3_BR
+0x00028230 PA_SC_EDGERULE
+0x00028234 PA_SU_HARDWARE_SCREEN_OFFSET
+0x00028240 PA_SC_GENERIC_SCISSOR_TL
+0x00028244 PA_SC_GENERIC_SCISSOR_BR
+0x00028250 PA_SC_VPORT_SCISSOR_0_TL
+0x00028254 PA_SC_VPORT_SCISSOR_0_BR
+0x00028258 PA_SC_VPORT_SCISSOR_1_TL
+0x0002825C PA_SC_VPORT_SCISSOR_1_BR
+0x00028260 PA_SC_VPORT_SCISSOR_2_TL
+0x00028264 PA_SC_VPORT_SCISSOR_2_BR
+0x00028268 PA_SC_VPORT_SCISSOR_3_TL
+0x0002826C PA_SC_VPORT_SCISSOR_3_BR
+0x00028270 PA_SC_VPORT_SCISSOR_4_TL
+0x00028274 PA_SC_VPORT_SCISSOR_4_BR
+0x00028278 PA_SC_VPORT_SCISSOR_5_TL
+0x0002827C PA_SC_VPORT_SCISSOR_5_BR
+0x00028280 PA_SC_VPORT_SCISSOR_6_TL
+0x00028284 PA_SC_VPORT_SCISSOR_6_BR
+0x00028288 PA_SC_VPORT_SCISSOR_7_TL
+0x0002828C PA_SC_VPORT_SCISSOR_7_BR
+0x00028290 PA_SC_VPORT_SCISSOR_8_TL
+0x00028294 PA_SC_VPORT_SCISSOR_8_BR
+0x00028298 PA_SC_VPORT_SCISSOR_9_TL
+0x0002829C PA_SC_VPORT_SCISSOR_9_BR
+0x000282A0 PA_SC_VPORT_SCISSOR_10_TL
+0x000282A4 PA_SC_VPORT_SCISSOR_10_BR
+0x000282A8 PA_SC_VPORT_SCISSOR_11_TL
+0x000282AC PA_SC_VPORT_SCISSOR_11_BR
+0x000282B0 PA_SC_VPORT_SCISSOR_12_TL
+0x000282B4 PA_SC_VPORT_SCISSOR_12_BR
+0x000282B8 PA_SC_VPORT_SCISSOR_13_TL
+0x000282BC PA_SC_VPORT_SCISSOR_13_BR
+0x000282C0 PA_SC_VPORT_SCISSOR_14_TL
+0x000282C4 PA_SC_VPORT_SCISSOR_14_BR
+0x000282C8 PA_SC_VPORT_SCISSOR_15_TL
+0x000282CC PA_SC_VPORT_SCISSOR_15_BR
+0x000282D0 PA_SC_VPORT_ZMIN_0
+0x000282D4 PA_SC_VPORT_ZMAX_0
+0x000282D8 PA_SC_VPORT_ZMIN_1
+0x000282DC PA_SC_VPORT_ZMAX_1
+0x000282E0 PA_SC_VPORT_ZMIN_2
+0x000282E4 PA_SC_VPORT_ZMAX_2
+0x000282E8 PA_SC_VPORT_ZMIN_3
+0x000282EC PA_SC_VPORT_ZMAX_3
+0x000282F0 PA_SC_VPORT_ZMIN_4
+0x000282F4 PA_SC_VPORT_ZMAX_4
+0x000282F8 PA_SC_VPORT_ZMIN_5
+0x000282FC PA_SC_VPORT_ZMAX_5
+0x00028300 PA_SC_VPORT_ZMIN_6
+0x00028304 PA_SC_VPORT_ZMAX_6
+0x00028308 PA_SC_VPORT_ZMIN_7
+0x0002830C PA_SC_VPORT_ZMAX_7
+0x00028310 PA_SC_VPORT_ZMIN_8
+0x00028314 PA_SC_VPORT_ZMAX_8
+0x00028318 PA_SC_VPORT_ZMIN_9
+0x0002831C PA_SC_VPORT_ZMAX_9
+0x00028320 PA_SC_VPORT_ZMIN_10
+0x00028324 PA_SC_VPORT_ZMAX_10
+0x00028328 PA_SC_VPORT_ZMIN_11
+0x0002832C PA_SC_VPORT_ZMAX_11
+0x00028330 PA_SC_VPORT_ZMIN_12
+0x00028334 PA_SC_VPORT_ZMAX_12
+0x00028338 PA_SC_VPORT_ZMIN_13
+0x0002833C PA_SC_VPORT_ZMAX_13
+0x00028340 PA_SC_VPORT_ZMIN_14
+0x00028344 PA_SC_VPORT_ZMAX_14
+0x00028348 PA_SC_VPORT_ZMIN_15
+0x0002834C PA_SC_VPORT_ZMAX_15
+0x00028350 SX_MISC
+0x00028354 SX_SURFACE_SYNC
+0x00028380 SQ_VTX_SEMANTIC_0
+0x00028384 SQ_VTX_SEMANTIC_1
+0x00028388 SQ_VTX_SEMANTIC_2
+0x0002838C SQ_VTX_SEMANTIC_3
+0x00028390 SQ_VTX_SEMANTIC_4
+0x00028394 SQ_VTX_SEMANTIC_5
+0x00028398 SQ_VTX_SEMANTIC_6
+0x0002839C SQ_VTX_SEMANTIC_7
+0x000283A0 SQ_VTX_SEMANTIC_8
+0x000283A4 SQ_VTX_SEMANTIC_9
+0x000283A8 SQ_VTX_SEMANTIC_10
+0x000283AC SQ_VTX_SEMANTIC_11
+0x000283B0 SQ_VTX_SEMANTIC_12
+0x000283B4 SQ_VTX_SEMANTIC_13
+0x000283B8 SQ_VTX_SEMANTIC_14
+0x000283BC SQ_VTX_SEMANTIC_15
+0x000283C0 SQ_VTX_SEMANTIC_16
+0x000283C4 SQ_VTX_SEMANTIC_17
+0x000283C8 SQ_VTX_SEMANTIC_18
+0x000283CC SQ_VTX_SEMANTIC_19
+0x000283D0 SQ_VTX_SEMANTIC_20
+0x000283D4 SQ_VTX_SEMANTIC_21
+0x000283D8 SQ_VTX_SEMANTIC_22
+0x000283DC SQ_VTX_SEMANTIC_23
+0x000283E0 SQ_VTX_SEMANTIC_24
+0x000283E4 SQ_VTX_SEMANTIC_25
+0x000283E8 SQ_VTX_SEMANTIC_26
+0x000283EC SQ_VTX_SEMANTIC_27
+0x000283F0 SQ_VTX_SEMANTIC_28
+0x000283F4 SQ_VTX_SEMANTIC_29
+0x000283F8 SQ_VTX_SEMANTIC_30
+0x000283FC SQ_VTX_SEMANTIC_31
+0x00028400 VGT_MAX_VTX_INDX
+0x00028404 VGT_MIN_VTX_INDX
+0x00028408 VGT_INDX_OFFSET
+0x0002840C VGT_MULTI_PRIM_IB_RESET_INDX
+0x00028410 SX_ALPHA_TEST_CONTROL
+0x00028414 CB_BLEND_RED
+0x00028418 CB_BLEND_GREEN
+0x0002841C CB_BLEND_BLUE
+0x00028420 CB_BLEND_ALPHA
+0x00028430 DB_STENCILREFMASK
+0x00028434 DB_STENCILREFMASK_BF
+0x00028438 SX_ALPHA_REF
+0x0002843C PA_CL_VPORT_XSCALE_0
+0x00028440 PA_CL_VPORT_XOFFSET_0
+0x00028444 PA_CL_VPORT_YSCALE_0
+0x00028448 PA_CL_VPORT_YOFFSET_0
+0x0002844C PA_CL_VPORT_ZSCALE_0
+0x00028450 PA_CL_VPORT_ZOFFSET_0
+0x00028454 PA_CL_VPORT_XSCALE_1
+0x00028458 PA_CL_VPORT_XOFFSET_1
+0x0002845C PA_CL_VPORT_YSCALE_1
+0x00028460 PA_CL_VPORT_YOFFSET_1
+0x00028464 PA_CL_VPORT_ZSCALE_1
+0x00028468 PA_CL_VPORT_ZOFFSET_1
+0x0002846C PA_CL_VPORT_XSCALE_2
+0x00028470 PA_CL_VPORT_XOFFSET_2
+0x00028474 PA_CL_VPORT_YSCALE_2
+0x00028478 PA_CL_VPORT_YOFFSET_2
+0x0002847C PA_CL_VPORT_ZSCALE_2
+0x00028480 PA_CL_VPORT_ZOFFSET_2
+0x00028484 PA_CL_VPORT_XSCALE_3
+0x00028488 PA_CL_VPORT_XOFFSET_3
+0x0002848C PA_CL_VPORT_YSCALE_3
+0x00028490 PA_CL_VPORT_YOFFSET_3
+0x00028494 PA_CL_VPORT_ZSCALE_3
+0x00028498 PA_CL_VPORT_ZOFFSET_3
+0x0002849C PA_CL_VPORT_XSCALE_4
+0x000284A0 PA_CL_VPORT_XOFFSET_4
+0x000284A4 PA_CL_VPORT_YSCALE_4
+0x000284A8 PA_CL_VPORT_YOFFSET_4
+0x000284AC PA_CL_VPORT_ZSCALE_4
+0x000284B0 PA_CL_VPORT_ZOFFSET_4
+0x000284B4 PA_CL_VPORT_XSCALE_5
+0x000284B8 PA_CL_VPORT_XOFFSET_5
+0x000284BC PA_CL_VPORT_YSCALE_5
+0x000284C0 PA_CL_VPORT_YOFFSET_5
+0x000284C4 PA_CL_VPORT_ZSCALE_5
+0x000284C8 PA_CL_VPORT_ZOFFSET_5
+0x000284CC PA_CL_VPORT_XSCALE_6
+0x000284D0 PA_CL_VPORT_XOFFSET_6
+0x000284D4 PA_CL_VPORT_YSCALE_6
+0x000284D8 PA_CL_VPORT_YOFFSET_6
+0x000284DC PA_CL_VPORT_ZSCALE_6
+0x000284E0 PA_CL_VPORT_ZOFFSET_6
+0x000284E4 PA_CL_VPORT_XSCALE_7
+0x000284E8 PA_CL_VPORT_XOFFSET_7
+0x000284EC PA_CL_VPORT_YSCALE_7
+0x000284F0 PA_CL_VPORT_YOFFSET_7
+0x000284F4 PA_CL_VPORT_ZSCALE_7
+0x000284F8 PA_CL_VPORT_ZOFFSET_7
+0x000284FC PA_CL_VPORT_XSCALE_8
+0x00028500 PA_CL_VPORT_XOFFSET_8
+0x00028504 PA_CL_VPORT_YSCALE_8
+0x00028508 PA_CL_VPORT_YOFFSET_8
+0x0002850C PA_CL_VPORT_ZSCALE_8
+0x00028510 PA_CL_VPORT_ZOFFSET_8
+0x00028514 PA_CL_VPORT_XSCALE_9
+0x00028518 PA_CL_VPORT_XOFFSET_9
+0x0002851C PA_CL_VPORT_YSCALE_9
+0x00028520 PA_CL_VPORT_YOFFSET_9
+0x00028524 PA_CL_VPORT_ZSCALE_9
+0x00028528 PA_CL_VPORT_ZOFFSET_9
+0x0002852C PA_CL_VPORT_XSCALE_10
+0x00028530 PA_CL_VPORT_XOFFSET_10
+0x00028534 PA_CL_VPORT_YSCALE_10
+0x00028538 PA_CL_VPORT_YOFFSET_10
+0x0002853C PA_CL_VPORT_ZSCALE_10
+0x00028540 PA_CL_VPORT_ZOFFSET_10
+0x00028544 PA_CL_VPORT_XSCALE_11
+0x00028548 PA_CL_VPORT_XOFFSET_11
+0x0002854C PA_CL_VPORT_YSCALE_11
+0x00028550 PA_CL_VPORT_YOFFSET_11
+0x00028554 PA_CL_VPORT_ZSCALE_11
+0x00028558 PA_CL_VPORT_ZOFFSET_11
+0x0002855C PA_CL_VPORT_XSCALE_12
+0x00028560 PA_CL_VPORT_XOFFSET_12
+0x00028564 PA_CL_VPORT_YSCALE_12
+0x00028568 PA_CL_VPORT_YOFFSET_12
+0x0002856C PA_CL_VPORT_ZSCALE_12
+0x00028570 PA_CL_VPORT_ZOFFSET_12
+0x00028574 PA_CL_VPORT_XSCALE_13
+0x00028578 PA_CL_VPORT_XOFFSET_13
+0x0002857C PA_CL_VPORT_YSCALE_13
+0x00028580 PA_CL_VPORT_YOFFSET_13
+0x00028584 PA_CL_VPORT_ZSCALE_13
+0x00028588 PA_CL_VPORT_ZOFFSET_13
+0x0002858C PA_CL_VPORT_XSCALE_14
+0x00028590 PA_CL_VPORT_XOFFSET_14
+0x00028594 PA_CL_VPORT_YSCALE_14
+0x00028598 PA_CL_VPORT_YOFFSET_14
+0x0002859C PA_CL_VPORT_ZSCALE_14
+0x000285A0 PA_CL_VPORT_ZOFFSET_14
+0x000285A4 PA_CL_VPORT_XSCALE_15
+0x000285A8 PA_CL_VPORT_XOFFSET_15
+0x000285AC PA_CL_VPORT_YSCALE_15
+0x000285B0 PA_CL_VPORT_YOFFSET_15
+0x000285B4 PA_CL_VPORT_ZSCALE_15
+0x000285B8 PA_CL_VPORT_ZOFFSET_15
+0x000285BC PA_CL_UCP_0_X
+0x000285C0 PA_CL_UCP_0_Y
+0x000285C4 PA_CL_UCP_0_Z
+0x000285C8 PA_CL_UCP_0_W
+0x000285CC PA_CL_UCP_1_X
+0x000285D0 PA_CL_UCP_1_Y
+0x000285D4 PA_CL_UCP_1_Z
+0x000285D8 PA_CL_UCP_1_W
+0x000285DC PA_CL_UCP_2_X
+0x000285E0 PA_CL_UCP_2_Y
+0x000285E4 PA_CL_UCP_2_Z
+0x000285E8 PA_CL_UCP_2_W
+0x000285EC PA_CL_UCP_3_X
+0x000285F0 PA_CL_UCP_3_Y
+0x000285F4 PA_CL_UCP_3_Z
+0x000285F8 PA_CL_UCP_3_W
+0x000285FC PA_CL_UCP_4_X
+0x00028600 PA_CL_UCP_4_Y
+0x00028604 PA_CL_UCP_4_Z
+0x00028608 PA_CL_UCP_4_W
+0x0002860C PA_CL_UCP_5_X
+0x00028610 PA_CL_UCP_5_Y
+0x00028614 PA_CL_UCP_5_Z
+0x00028618 PA_CL_UCP_5_W
+0x0002861C SPI_VS_OUT_ID_0
+0x00028620 SPI_VS_OUT_ID_1
+0x00028624 SPI_VS_OUT_ID_2
+0x00028628 SPI_VS_OUT_ID_3
+0x0002862C SPI_VS_OUT_ID_4
+0x00028630 SPI_VS_OUT_ID_5
+0x00028634 SPI_VS_OUT_ID_6
+0x00028638 SPI_VS_OUT_ID_7
+0x0002863C SPI_VS_OUT_ID_8
+0x00028640 SPI_VS_OUT_ID_9
+0x00028644 SPI_PS_INPUT_CNTL_0
+0x00028648 SPI_PS_INPUT_CNTL_1
+0x0002864C SPI_PS_INPUT_CNTL_2
+0x00028650 SPI_PS_INPUT_CNTL_3
+0x00028654 SPI_PS_INPUT_CNTL_4
+0x00028658 SPI_PS_INPUT_CNTL_5
+0x0002865C SPI_PS_INPUT_CNTL_6
+0x00028660 SPI_PS_INPUT_CNTL_7
+0x00028664 SPI_PS_INPUT_CNTL_8
+0x00028668 SPI_PS_INPUT_CNTL_9
+0x0002866C SPI_PS_INPUT_CNTL_10
+0x00028670 SPI_PS_INPUT_CNTL_11
+0x00028674 SPI_PS_INPUT_CNTL_12
+0x00028678 SPI_PS_INPUT_CNTL_13
+0x0002867C SPI_PS_INPUT_CNTL_14
+0x00028680 SPI_PS_INPUT_CNTL_15
+0x00028684 SPI_PS_INPUT_CNTL_16
+0x00028688 SPI_PS_INPUT_CNTL_17
+0x0002868C SPI_PS_INPUT_CNTL_18
+0x00028690 SPI_PS_INPUT_CNTL_19
+0x00028694 SPI_PS_INPUT_CNTL_20
+0x00028698 SPI_PS_INPUT_CNTL_21
+0x0002869C SPI_PS_INPUT_CNTL_22
+0x000286A0 SPI_PS_INPUT_CNTL_23
+0x000286A4 SPI_PS_INPUT_CNTL_24
+0x000286A8 SPI_PS_INPUT_CNTL_25
+0x000286AC SPI_PS_INPUT_CNTL_26
+0x000286B0 SPI_PS_INPUT_CNTL_27
+0x000286B4 SPI_PS_INPUT_CNTL_28
+0x000286B8 SPI_PS_INPUT_CNTL_29
+0x000286BC SPI_PS_INPUT_CNTL_30
+0x000286C0 SPI_PS_INPUT_CNTL_31
+0x000286C4 SPI_VS_OUT_CONFIG
+0x000286C8 SPI_THREAD_GROUPING
+0x000286CC SPI_PS_IN_CONTROL_0
+0x000286D0 SPI_PS_IN_CONTROL_1
+0x000286D4 SPI_INTERP_CONTROL_0
+0x000286D8 SPI_INPUT_Z
+0x000286DC SPI_FOG_CNTL
+0x000286E0 SPI_BARYC_CNTL
+0x000286E4 SPI_PS_IN_CONTROL_2
+0x000286E8 SPI_COMPUTE_INPUT_CNTL
+0x000286EC SPI_COMPUTE_NUM_THREAD_X
+0x000286F0 SPI_COMPUTE_NUM_THREAD_Y
+0x000286F4 SPI_COMPUTE_NUM_THREAD_Z
+0x000286F8 SPI_GPR_MGMT
+0x000286FC SPI_LDS_MGMT
+0x00028700 SPI_STACK_MGMT
+0x00028704 SPI_WAVE_MGMT_1
+0x00028708 SPI_WAVE_MGMT_2
+0x00028724 GDS_ADDR_SIZE
+0x00028780 CB_BLEND0_CONTROL
+0x00028784 CB_BLEND1_CONTROL
+0x00028788 CB_BLEND2_CONTROL
+0x0002878C CB_BLEND3_CONTROL
+0x00028790 CB_BLEND4_CONTROL
+0x00028794 CB_BLEND5_CONTROL
+0x00028798 CB_BLEND6_CONTROL
+0x0002879C CB_BLEND7_CONTROL
+0x000287CC CS_COPY_STATE
+0x000287D0 GFX_COPY_STATE
+0x000287D4 PA_CL_POINT_X_RAD
+0x000287D8 PA_CL_POINT_Y_RAD
+0x000287DC PA_CL_POINT_SIZE
+0x000287E0 PA_CL_POINT_CULL_RAD
+0x00028808 CB_COLOR_CONTROL
+0x0002880C DB_SHADER_CONTROL
+0x00028810 PA_CL_CLIP_CNTL
+0x00028814 PA_SU_SC_MODE_CNTL
+0x00028818 PA_CL_VTE_CNTL
+0x0002881C PA_CL_VS_OUT_CNTL
+0x00028820 PA_CL_NANINF_CNTL
+0x00028824 PA_SU_LINE_STIPPLE_CNTL
+0x00028828 PA_SU_LINE_STIPPLE_SCALE
+0x0002882C PA_SU_PRIM_FILTER_CNTL
+0x00028844 SQ_PGM_RESOURCES_PS
+0x00028848 SQ_PGM_RESOURCES_2_PS
+0x0002884C SQ_PGM_EXPORTS_PS
+0x00028860 SQ_PGM_RESOURCES_VS
+0x00028864 SQ_PGM_RESOURCES_2_VS
+0x00028878 SQ_PGM_RESOURCES_GS
+0x0002887C SQ_PGM_RESOURCES_2_GS
+0x00028890 SQ_PGM_RESOURCES_ES
+0x00028894 SQ_PGM_RESOURCES_2_ES
+0x000288A8 SQ_PGM_RESOURCES_FS
+0x000288BC SQ_PGM_RESOURCES_HS
+0x000288C0 SQ_PGM_RESOURCES_2_HS
+0x000288D4 SQ_PGM_RESOURCES_LS
+0x000288D8 SQ_PGM_RESOURCES_2_LS
+0x000288E8 SQ_LDS_ALLOC
+0x000288EC SQ_LDS_ALLOC_PS
+0x000288F0 SQ_VTX_SEMANTIC_CLEAR
+0x00028A00 PA_SU_POINT_SIZE
+0x00028A04 PA_SU_POINT_MINMAX
+0x00028A08 PA_SU_LINE_CNTL
+0x00028A0C PA_SC_LINE_STIPPLE
+0x00028A10 VGT_OUTPUT_PATH_CNTL
+0x00028A14 VGT_HOS_CNTL
+0x00028A18 VGT_HOS_MAX_TESS_LEVEL
+0x00028A1C VGT_HOS_MIN_TESS_LEVEL
+0x00028A20 VGT_HOS_REUSE_DEPTH
+0x00028A24 VGT_GROUP_PRIM_TYPE
+0x00028A28 VGT_GROUP_FIRST_DECR
+0x00028A2C VGT_GROUP_DECR
+0x00028A30 VGT_GROUP_VECT_0_CNTL
+0x00028A34 VGT_GROUP_VECT_1_CNTL
+0x00028A38 VGT_GROUP_VECT_0_FMT_CNTL
+0x00028A3C VGT_GROUP_VECT_1_FMT_CNTL
+0x00028A40 VGT_GS_MODE
+0x00028A48 PA_SC_MODE_CNTL_0
+0x00028A4C PA_SC_MODE_CNTL_1
+0x00028A50 VGT_ENHANCE
+0x00028A54 VGT_GS_PER_ES
+0x00028A58 VGT_ES_PER_GS
+0x00028A5C VGT_GS_PER_VS
+0x00028A6C VGT_GS_OUT_PRIM_TYPE
+0x00028A70 IA_ENHANCE
+0x00028A84 VGT_PRIMITIVEID_EN
+0x00028A94 VGT_MULTI_PRIM_IB_RESET_EN
+0x00028AA0 VGT_INSTANCE_STEP_RATE_0
+0x00028AA4 VGT_INSTANCE_STEP_RATE_1
+0x00028AA8 IA_MULTI_VGT_PARAM
+0x00028AB4 VGT_REUSE_OFF
+0x00028AB8 VGT_VTX_CNT_EN
+0x00028ABC DB_HTILE_SURFACE
+0x00028AC0 DB_SRESULTS_COMPARE_STATE0
+0x00028AC4 DB_SRESULTS_COMPARE_STATE1
+0x00028AC8 DB_PRELOAD_CONTROL
+0x00028B38 VGT_GS_MAX_VERT_OUT
+0x00028B54 VGT_SHADER_STAGES_EN
+0x00028B58 VGT_LS_HS_CONFIG
+0x00028B6C VGT_TF_PARAM
+0x00028B70 DB_ALPHA_TO_MASK
+0x00028B74 VGT_DISPATCH_INITIATOR
+0x00028B78 PA_SU_POLY_OFFSET_DB_FMT_CNTL
+0x00028B7C PA_SU_POLY_OFFSET_CLAMP
+0x00028B80 PA_SU_POLY_OFFSET_FRONT_SCALE
+0x00028B84 PA_SU_POLY_OFFSET_FRONT_OFFSET
+0x00028B88 PA_SU_POLY_OFFSET_BACK_SCALE
+0x00028B8C PA_SU_POLY_OFFSET_BACK_OFFSET
+0x00028B74 VGT_GS_INSTANCE_CNT
+0x00028BD4 PA_SC_CENTROID_PRIORITY_0
+0x00028BD8 PA_SC_CENTROID_PRIORITY_1
+0x00028BDC PA_SC_LINE_CNTL
+0x00028BE4 PA_SU_VTX_CNTL
+0x00028BE8 PA_CL_GB_VERT_CLIP_ADJ
+0x00028BEC PA_CL_GB_VERT_DISC_ADJ
+0x00028BF0 PA_CL_GB_HORZ_CLIP_ADJ
+0x00028BF4 PA_CL_GB_HORZ_DISC_ADJ
+0x00028BF8 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_0
+0x00028BFC PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_1
+0x00028C00 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_2
+0x00028C04 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y0_3
+0x00028C08 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_0
+0x00028C0C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_1
+0x00028C10 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_2
+0x00028C14 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y0_3
+0x00028C18 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_0
+0x00028C1C PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_1
+0x00028C20 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_2
+0x00028C24 PA_SC_AA_SAMPLE_LOCS_PIXEL_X0_Y1_3
+0x00028C28 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_0
+0x00028C2C PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_1
+0x00028C30 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_2
+0x00028C34 PA_SC_AA_SAMPLE_LOCS_PIXEL_X1_Y1_3
+0x00028C38 PA_SC_AA_MASK_X0_Y0_X1_Y0
+0x00028C3C PA_SC_AA_MASK_X0_Y1_X1_Y1
+0x00028C8C CB_COLOR0_CLEAR_WORD0
+0x00028C90 CB_COLOR0_CLEAR_WORD1
+0x00028C94 CB_COLOR0_CLEAR_WORD2
+0x00028C98 CB_COLOR0_CLEAR_WORD3
+0x00028CC8 CB_COLOR1_CLEAR_WORD0
+0x00028CCC CB_COLOR1_CLEAR_WORD1
+0x00028CD0 CB_COLOR1_CLEAR_WORD2
+0x00028CD4 CB_COLOR1_CLEAR_WORD3
+0x00028D04 CB_COLOR2_CLEAR_WORD0
+0x00028D08 CB_COLOR2_CLEAR_WORD1
+0x00028D0C CB_COLOR2_CLEAR_WORD2
+0x00028D10 CB_COLOR2_CLEAR_WORD3
+0x00028D40 CB_COLOR3_CLEAR_WORD0
+0x00028D44 CB_COLOR3_CLEAR_WORD1
+0x00028D48 CB_COLOR3_CLEAR_WORD2
+0x00028D4C CB_COLOR3_CLEAR_WORD3
+0x00028D7C CB_COLOR4_CLEAR_WORD0
+0x00028D80 CB_COLOR4_CLEAR_WORD1
+0x00028D84 CB_COLOR4_CLEAR_WORD2
+0x00028D88 CB_COLOR4_CLEAR_WORD3
+0x00028DB8 CB_COLOR5_CLEAR_WORD0
+0x00028DBC CB_COLOR5_CLEAR_WORD1
+0x00028DC0 CB_COLOR5_CLEAR_WORD2
+0x00028DC4 CB_COLOR5_CLEAR_WORD3
+0x00028DF4 CB_COLOR6_CLEAR_WORD0
+0x00028DF8 CB_COLOR6_CLEAR_WORD1
+0x00028DFC CB_COLOR6_CLEAR_WORD2
+0x00028E00 CB_COLOR6_CLEAR_WORD3
+0x00028E30 CB_COLOR7_CLEAR_WORD0
+0x00028E34 CB_COLOR7_CLEAR_WORD1
+0x00028E38 CB_COLOR7_CLEAR_WORD2
+0x00028E3C CB_COLOR7_CLEAR_WORD3
+0x00028F80 SQ_ALU_CONST_BUFFER_SIZE_HS_0
+0x00028F84 SQ_ALU_CONST_BUFFER_SIZE_HS_1
+0x00028F88 SQ_ALU_CONST_BUFFER_SIZE_HS_2
+0x00028F8C SQ_ALU_CONST_BUFFER_SIZE_HS_3
+0x00028F90 SQ_ALU_CONST_BUFFER_SIZE_HS_4
+0x00028F94 SQ_ALU_CONST_BUFFER_SIZE_HS_5
+0x00028F98 SQ_ALU_CONST_BUFFER_SIZE_HS_6
+0x00028F9C SQ_ALU_CONST_BUFFER_SIZE_HS_7
+0x00028FA0 SQ_ALU_CONST_BUFFER_SIZE_HS_8
+0x00028FA4 SQ_ALU_CONST_BUFFER_SIZE_HS_9
+0x00028FA8 SQ_ALU_CONST_BUFFER_SIZE_HS_10
+0x00028FAC SQ_ALU_CONST_BUFFER_SIZE_HS_11
+0x00028FB0 SQ_ALU_CONST_BUFFER_SIZE_HS_12
+0x00028FB4 SQ_ALU_CONST_BUFFER_SIZE_HS_13
+0x00028FB8 SQ_ALU_CONST_BUFFER_SIZE_HS_14
+0x00028FBC SQ_ALU_CONST_BUFFER_SIZE_HS_15
+0x00028FC0 SQ_ALU_CONST_BUFFER_SIZE_LS_0
+0x00028FC4 SQ_ALU_CONST_BUFFER_SIZE_LS_1
+0x00028FC8 SQ_ALU_CONST_BUFFER_SIZE_LS_2
+0x00028FCC SQ_ALU_CONST_BUFFER_SIZE_LS_3
+0x00028FD0 SQ_ALU_CONST_BUFFER_SIZE_LS_4
+0x00028FD4 SQ_ALU_CONST_BUFFER_SIZE_LS_5
+0x00028FD8 SQ_ALU_CONST_BUFFER_SIZE_LS_6
+0x00028FDC SQ_ALU_CONST_BUFFER_SIZE_LS_7
+0x00028FE0 SQ_ALU_CONST_BUFFER_SIZE_LS_8
+0x00028FE4 SQ_ALU_CONST_BUFFER_SIZE_LS_9
+0x00028FE8 SQ_ALU_CONST_BUFFER_SIZE_LS_10
+0x00028FEC SQ_ALU_CONST_BUFFER_SIZE_LS_11
+0x00028FF0 SQ_ALU_CONST_BUFFER_SIZE_LS_12
+0x00028FF4 SQ_ALU_CONST_BUFFER_SIZE_LS_13
+0x00028FF8 SQ_ALU_CONST_BUFFER_SIZE_LS_14
+0x00028FFC SQ_ALU_CONST_BUFFER_SIZE_LS_15
+0x0003CFF0 SQ_VTX_BASE_VTX_LOC
+0x0003CFF4 SQ_VTX_START_INST_LOC
+0x0003FF00 SQ_TEX_SAMPLER_CLEAR
+0x0003FF04 SQ_TEX_RESOURCE_CLEAR
+0x0003FF08 SQ_LOOP_BOOL_CLEAR
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/reg_srcs/evergreen linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/reg_srcs/evergreen
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/reg_srcs/evergreen	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/reg_srcs/evergreen	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,5 @@
 evergreen 0x9400
+0x0000802C GRBM_GFX_INDEX
 0x00008040 WAIT_UNTIL
 0x00008044 WAIT_UNTIL_POLL_CNTL
 0x00008048 WAIT_UNTIL_POLL_MASK
@@ -45,6 +46,7 @@
 0x00008E48 SQ_EX_ALLOC_TABLE_SLOTS
 0x00009100 SPI_CONFIG_CNTL
 0x0000913C SPI_CONFIG_CNTL_1
+0x00009508 TA_CNTL_AUX
 0x00009700 VC_CNTL
 0x00009714 VC_ENHANCE
 0x00009830 DB_DEBUG
@@ -220,6 +222,7 @@
 0x00028348 PA_SC_VPORT_ZMIN_15
 0x0002834C PA_SC_VPORT_ZMAX_15
 0x00028350 SX_MISC
+0x00028354 SX_SURFACE_SYNC
 0x00028380 SQ_VTX_SEMANTIC_0
 0x00028384 SQ_VTX_SEMANTIC_1
 0x00028388 SQ_VTX_SEMANTIC_2
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/reg_srcs/r600 linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/reg_srcs/r600
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/reg_srcs/r600	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/reg_srcs/r600	2011-05-19 00:06:34.000000000 -0400
@@ -708,6 +708,7 @@
 0x00028D0C DB_RENDER_CONTROL
 0x00028D10 DB_RENDER_OVERRIDE
 0x0002880C DB_SHADER_CONTROL
+0x00028D28 DB_SRESULTS_COMPARE_STATE0
 0x00028D2C DB_SRESULTS_COMPARE_STATE1
 0x00028430 DB_STENCILREFMASK
 0x00028434 DB_STENCILREFMASK_BF
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rs400.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rs400.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rs400.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rs400.c	2011-05-19 00:06:34.000000000 -0400
@@ -412,12 +412,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rs600.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rs600.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rs600.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rs600.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,17 +48,6 @@
 
 void rs600_pre_page_flip(struct radeon_device *rdev, int crtc)
 {
-	struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc];
-	u32 tmp;
-
-	/* make sure flip is at vb rather than hb */
-	tmp = RREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset);
-	tmp &= ~AVIVO_D1GRPH_SURFACE_UPDATE_H_RETRACE_EN;
-	WREG32(AVIVO_D1GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset, tmp);
-
-	/* set pageflip to happen anywhere in vblank interval */
-	WREG32(AVIVO_D1MODE_MASTER_UPDATE_MODE + radeon_crtc->crtc_offset, 0);
-
 	/* enable the pflip int */
 	radeon_irq_kms_pflip_irq_get(rdev, crtc);
 }
@@ -125,7 +114,7 @@
 				udelay(voltage->delay);
 		}
 	} else if (voltage->type == VOLTAGE_VDDC)
-		radeon_atom_set_voltage(rdev, voltage->vddc_id);
+		radeon_atom_set_voltage(rdev, voltage->vddc_id, SET_VOLTAGE_TYPE_ASIC_VDDC);
 
 	dyn_pwrmgt_sclk_length = RREG32_PLL(DYN_PWRMGT_SCLK_LENGTH);
 	dyn_pwrmgt_sclk_length &= ~REDUCED_POWER_SCLK_HILEN(0xf);
@@ -865,12 +854,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rs690.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rs690.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rs690.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rs690.c	2011-05-19 00:06:34.000000000 -0400
@@ -627,12 +627,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rv515.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rv515.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rv515.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rv515.c	2011-05-19 00:06:34.000000000 -0400
@@ -398,12 +398,12 @@
 	/* 1M ring buffer */
 	r = r100_cp_init(rdev, 1024 * 1024);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing CP (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing CP (%d).\n", r);
 		return r;
 	}
 	r = r100_ib_init(rdev);
 	if (r) {
-		dev_err(rdev->dev, "failled initializing IB (%d).\n", r);
+		dev_err(rdev->dev, "failed initializing IB (%d).\n", r);
 		return r;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rv770.c linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rv770.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/radeon/rv770.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/radeon/rv770.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 
 	if ((voltage->type == VOLTAGE_SW) && voltage->voltage) {
 		if (voltage->voltage != rdev->pm.current_vddc) {
-			radeon_atom_set_voltage(rdev, voltage->voltage);
+			radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
 			rdev->pm.current_vddc = voltage->voltage;
 			DRM_DEBUG("Setting: v: %d\n", voltage->voltage);
 		}
@@ -1003,7 +1003,7 @@
 	u64 gpu_addr;
 
 	if (rdev->vram_scratch.robj == NULL) {
-		r = radeon_bo_create(rdev, NULL, RADEON_GPU_PAGE_SIZE,
+		r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE,
 				     PAGE_SIZE, true, RADEON_GEM_DOMAIN_VRAM,
 				     &rdev->vram_scratch.robj);
 		if (r) {
@@ -1209,7 +1209,7 @@
 
 	r = r600_ib_test(rdev);
 	if (r) {
-		DRM_ERROR("radeon: failled testing IB (%d).\n", r);
+		DRM_ERROR("radeon: failed testing IB (%d).\n", r);
 		return r;
 	}
 
@@ -1255,9 +1255,6 @@
 {
 	int r;
 
-	r = radeon_dummy_page_init(rdev);
-	if (r)
-		return r;
 	/* This don't do much */
 	r = radeon_gem_init(rdev);
 	if (r)
@@ -1372,7 +1369,6 @@
 	radeon_atombios_fini(rdev);
 	kfree(rdev->bios);
 	rdev->bios = NULL;
-	radeon_dummy_page_fini(rdev);
 }
 
 static void rv770_pcie_gen2_enable(struct radeon_device *rdev)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/savage/savage_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/savage/savage_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/savage/savage_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/savage/savage_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,11 +55,6 @@
 		 .llseek = noop_llseek,
 	},
 
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
-
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
@@ -68,15 +63,20 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver savage_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init savage_init(void)
 {
 	driver.num_ioctls = savage_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &savage_pci_driver);
 }
 
 static void __exit savage_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &savage_pci_driver);
 }
 
 module_init(savage_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/sis/sis_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/sis/sis_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/sis/sis_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/sis/sis_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,10 +82,6 @@
 		 .fasync = drm_fasync,
 		 .llseek = noop_llseek,
 	},
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -95,15 +91,20 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver sis_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init sis_init(void)
 {
 	driver.num_ioctls = sis_max_ioctl;
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &sis_pci_driver);
 }
 
 static void __exit sis_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &sis_pci_driver);
 }
 
 module_init(sis_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/tdfx/tdfx_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,10 +52,6 @@
 		 .fasync = drm_fasync,
 		 .llseek = noop_llseek,
 	},
-	.pci_driver = {
-		 .name = DRIVER_NAME,
-		 .id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -65,14 +61,19 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver tdfx_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init tdfx_init(void)
 {
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &tdfx_pci_driver);
 }
 
 static void __exit tdfx_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &tdfx_pci_driver);
 }
 
 module_init(tdfx_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_agp_backend.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,8 @@
 
 static int ttm_agp_populate(struct ttm_backend *backend,
 			    unsigned long num_pages, struct page **pages,
-			    struct page *dummy_read_page)
+			    struct page *dummy_read_page,
+			    dma_addr_t *dma_addrs)
 {
 	struct ttm_agp_backend *agp_be =
 	    container_of(backend, struct ttm_agp_backend, backend);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_bo.c linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_bo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_bo.c	2011-05-19 00:06:34.000000000 -0400
@@ -406,11 +406,12 @@
 		}
 
 		if (bo->mem.mem_type == TTM_PL_SYSTEM) {
+			if (bdev->driver->move_notify)
+				bdev->driver->move_notify(bo, mem);
 			bo->mem = *mem;
 			mem->mm_node = NULL;
 			goto moved;
 		}
-
 	}
 
 	if (bdev->driver->move_notify)
@@ -1167,7 +1168,7 @@
 		uint32_t page_alignment,
 		unsigned long buffer_start,
 		bool interruptible,
-		struct file *persistant_swap_storage,
+		struct file *persistent_swap_storage,
 		size_t acc_size,
 		void (*destroy) (struct ttm_buffer_object *))
 {
@@ -1210,7 +1211,7 @@
 	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->persistent_swap_storage = persistent_swap_storage;
 	bo->acc_size = acc_size;
 	atomic_inc(&bo->glob->bo_count);
 
@@ -1259,7 +1260,7 @@
 			uint32_t page_alignment,
 			unsigned long buffer_start,
 			bool interruptible,
-			struct file *persistant_swap_storage,
+			struct file *persistent_swap_storage,
 			struct ttm_buffer_object **p_bo)
 {
 	struct ttm_buffer_object *bo;
@@ -1281,7 +1282,7 @@
 
 	ret = ttm_bo_init(bdev, bo, size, type, placement, page_alignment,
 				buffer_start, interruptible,
-				persistant_swap_storage, acc_size, NULL);
+				persistent_swap_storage, acc_size, NULL);
 	if (likely(ret == 0))
 		*p_bo = bo;
 
@@ -1862,7 +1863,7 @@
 	if (bo->bdev->driver->swap_notify)
 		bo->bdev->driver->swap_notify(bo);
 
-	ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage);
+	ret = ttm_tt_swapout(bo->ttm, bo->persistent_swap_storage);
 out:
 
 	/**
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_page_alloc.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,7 @@
 #include <linux/mm.h>
 #include <linux/seq_file.h> /* for seq_printf */
 #include <linux/slab.h>
+#include <linux/dma-mapping.h>
 
 #include <asm/atomic.h>
 
@@ -662,7 +663,8 @@
  * cached pages.
  */
 int ttm_get_pages(struct list_head *pages, int flags,
-		enum ttm_caching_state cstate, unsigned count)
+		  enum ttm_caching_state cstate, unsigned count,
+		  dma_addr_t *dma_address)
 {
 	struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
 	struct page *p = NULL;
@@ -720,7 +722,7 @@
 			printk(KERN_ERR TTM_PFX
 			       "Failed to allocate extra pages "
 			       "for large request.");
-			ttm_put_pages(pages, 0, flags, cstate);
+			ttm_put_pages(pages, 0, flags, cstate, NULL);
 			return r;
 		}
 	}
@@ -731,7 +733,7 @@
 
 /* Put all pages in pages list to correct pool to wait for reuse */
 void ttm_put_pages(struct list_head *pages, unsigned page_count, int flags,
-		enum ttm_caching_state cstate)
+		   enum ttm_caching_state cstate, dma_addr_t *dma_address)
 {
 	unsigned long irq_flags;
 	struct ttm_page_pool *pool = ttm_get_pool(flags, cstate);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_tt.c linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_tt.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/ttm/ttm_tt.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,12 +49,16 @@
 static void ttm_tt_alloc_page_directory(struct ttm_tt *ttm)
 {
 	ttm->pages = drm_calloc_large(ttm->num_pages, sizeof(*ttm->pages));
+	ttm->dma_address = drm_calloc_large(ttm->num_pages,
+					    sizeof(*ttm->dma_address));
 }
 
 static void ttm_tt_free_page_directory(struct ttm_tt *ttm)
 {
 	drm_free_large(ttm->pages);
 	ttm->pages = NULL;
+	drm_free_large(ttm->dma_address);
+	ttm->dma_address = NULL;
 }
 
 static void ttm_tt_free_user_pages(struct ttm_tt *ttm)
@@ -105,7 +109,8 @@
 
 		INIT_LIST_HEAD(&h);
 
-		ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1);
+		ret = ttm_get_pages(&h, ttm->page_flags, ttm->caching_state, 1,
+				    &ttm->dma_address[index]);
 
 		if (ret != 0)
 			return NULL;
@@ -164,7 +169,7 @@
 	}
 
 	be->func->populate(be, ttm->num_pages, ttm->pages,
-			   ttm->dummy_read_page);
+			   ttm->dummy_read_page, ttm->dma_address);
 	ttm->state = tt_unbound;
 	return 0;
 }
@@ -298,7 +303,8 @@
 			count++;
 		}
 	}
-	ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state);
+	ttm_put_pages(&h, count, ttm->page_flags, ttm->caching_state,
+		      ttm->dma_address);
 	ttm->state = tt_unpopulated;
 	ttm->first_himem_page = ttm->num_pages;
 	ttm->last_lomem_page = -1;
@@ -326,7 +332,7 @@
 		ttm_tt_free_page_directory(ttm);
 	}
 
-	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP) &&
+	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP) &&
 	    ttm->swap_storage)
 		fput(ttm->swap_storage);
 
@@ -497,7 +503,7 @@
 		page_cache_release(from_page);
 	}
 
-	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTANT_SWAP))
+	if (!(ttm->page_flags & TTM_PAGE_FLAG_PERSISTENT_SWAP))
 		fput(swap_storage);
 	ttm->swap_storage = NULL;
 	ttm->page_flags &= ~TTM_PAGE_FLAG_SWAPPED;
@@ -508,7 +514,7 @@
 	return ret;
 }
 
-int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistant_swap_storage)
+int ttm_tt_swapout(struct ttm_tt *ttm, struct file *persistent_swap_storage)
 {
 	struct address_space *swap_space;
 	struct file *swap_storage;
@@ -534,7 +540,7 @@
 		return 0;
 	}
 
-	if (!persistant_swap_storage) {
+	if (!persistent_swap_storage) {
 		swap_storage = shmem_file_setup("ttm swap",
 						ttm->num_pages << PAGE_SHIFT,
 						0);
@@ -543,7 +549,7 @@
 			return PTR_ERR(swap_storage);
 		}
 	} else
-		swap_storage = persistant_swap_storage;
+		swap_storage = persistent_swap_storage;
 
 	swap_space = swap_storage->f_path.dentry->d_inode->i_mapping;
 
@@ -571,12 +577,12 @@
 	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;
+	if (persistent_swap_storage)
+		ttm->page_flags |= TTM_PAGE_FLAG_PERSISTENT_SWAP;
 
 	return 0;
 out_err:
-	if (!persistant_swap_storage)
+	if (!persistent_swap_storage)
 		fput(swap_storage);
 
 	return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/via/via_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/via/via_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/via/via_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/via/via_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,10 +62,6 @@
 		.fasync = drm_fasync,
 		.llseek = noop_llseek,
 		},
-	.pci_driver = {
-		.name = DRIVER_NAME,
-		.id_table = pciidlist,
-	},
 
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
@@ -75,16 +71,21 @@
 	.patchlevel = DRIVER_PATCHLEVEL,
 };
 
+static struct pci_driver via_pci_driver = {
+	.name = DRIVER_NAME,
+	.id_table = pciidlist,
+};
+
 static int __init via_init(void)
 {
 	driver.num_ioctls = via_max_ioctl;
 	via_init_command_verifier();
-	return drm_init(&driver);
+	return drm_pci_init(&driver, &via_pci_driver);
 }
 
 static void __exit via_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &via_pci_driver);
 }
 
 module_init(via_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,8 @@
 
 static int vmw_ttm_populate(struct ttm_backend *backend,
 			    unsigned long num_pages, struct page **pages,
-			    struct page *dummy_read_page)
+			    struct page *dummy_read_page,
+			    dma_addr_t *dma_addrs)
 {
 	struct vmw_ttm_backend *vmw_be =
 	    container_of(backend, struct vmw_ttm_backend, backend);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -909,15 +909,6 @@
 #endif
 		 .llseek = noop_llseek,
 	},
-	.pci_driver = {
-		 .name = VMWGFX_DRIVER_NAME,
-		 .id_table = vmw_pci_id_list,
-		 .probe = vmw_probe,
-		 .remove = vmw_remove,
-		 .driver = {
-			 .pm = &vmw_pm_ops
-		 }
-	 },
 	.name = VMWGFX_DRIVER_NAME,
 	.desc = VMWGFX_DRIVER_DESC,
 	.date = VMWGFX_DRIVER_DATE,
@@ -926,6 +917,16 @@
 	.patchlevel = VMWGFX_DRIVER_PATCHLEVEL
 };
 
+static struct pci_driver vmw_pci_driver = {
+	.name = VMWGFX_DRIVER_NAME,
+	.id_table = vmw_pci_id_list,
+	.probe = vmw_probe,
+	.remove = vmw_remove,
+	.driver = {
+		.pm = &vmw_pm_ops
+	}
+};
+
 static int vmw_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
 	return drm_get_pci_dev(pdev, ent, &driver);
@@ -934,7 +935,7 @@
 static int __init vmwgfx_init(void)
 {
 	int ret;
-	ret = drm_init(&driver);
+	ret = drm_pci_init(&driver, &vmw_pci_driver);
 	if (ret)
 		DRM_ERROR("Failed initializing DRM.\n");
 	return ret;
@@ -942,7 +943,7 @@
 
 static void __exit vmwgfx_exit(void)
 {
-	drm_exit(&driver);
+	drm_pci_exit(&driver, &vmw_pci_driver);
 }
 
 module_init(vmwgfx_init);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c	2011-05-19 00:06:34.000000000 -0400
@@ -245,7 +245,7 @@
 		/* TODO handle none page aligned offsets */
 		/* TODO handle partial uploads and pitch != 256 */
 		/* TODO handle more then one copy (size != 64) */
-		DRM_ERROR("lazy programer, cant handle wierd stuff\n");
+		DRM_ERROR("lazy programmer, can't handle weird stuff\n");
 		return;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c
--- linux-libre-2.6.38-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/drm/vmwgfx/vmwgfx_ldu.c	2011-05-19 00:06:34.000000000 -0400
@@ -345,7 +345,7 @@
 	return connector_status_disconnected;
 }
 
-static struct drm_display_mode vmw_ldu_connector_builtin[] = {
+static const struct drm_display_mode vmw_ldu_connector_builtin[] = {
 	/* 640x480@60Hz */
 	{ DRM_MODE("640x480", DRM_MODE_TYPE_DRIVER, 25175, 640, 656,
 		   752, 800, 0, 480, 489, 492, 525, 0,
@@ -429,7 +429,6 @@
 	struct drm_device *dev = connector->dev;
 	struct vmw_private *dev_priv = vmw_priv(dev);
 	struct drm_display_mode *mode = NULL;
-	struct drm_display_mode *bmode;
 	struct drm_display_mode prefmode = { DRM_MODE("preferred",
 		DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED,
 		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
@@ -459,6 +458,8 @@
 	}
 
 	for (i = 0; vmw_ldu_connector_builtin[i].type != 0; i++) {
+		const struct drm_display_mode *bmode;
+
 		bmode = &vmw_ldu_connector_builtin[i];
 		if (bmode->hdisplay > max_width ||
 		    bmode->vdisplay > max_height)
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/stub/Kconfig linux-libre-2.6.39-gnu/drivers/gpu/stub/Kconfig
--- linux-libre-2.6.38-gnu/drivers/gpu/stub/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/stub/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,7 @@
 	# Poulsbo stub depends on ACPI_VIDEO when ACPI is enabled
 	# but for select to work, need to select ACPI_VIDEO's dependencies, ick
 	select BACKLIGHT_CLASS_DEVICE if ACPI
+	select VIDEO_OUTPUT_CONTROL if ACPI
 	select INPUT if ACPI
 	select ACPI_VIDEO if ACPI
 	select THERMAL if ACPI
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/vga/vgaarb.c linux-libre-2.6.39-gnu/drivers/gpu/vga/vgaarb.c
--- linux-libre-2.6.38-gnu/drivers/gpu/vga/vgaarb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/vga/vgaarb.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,7 +151,7 @@
 static void vga_check_first_use(void)
 {
 	/* we should inform all GPUs in the system that
-	 * VGA arb has occured and to try and disable resources
+	 * VGA arb has occurred and to try and disable resources
 	 * if they can */
 	if (!vga_arbiter_used) {
 		vga_arbiter_used = true;
@@ -774,7 +774,7 @@
 	 */
 	spin_lock_irqsave(&vga_lock, flags);
 
-	/* If we are targetting the default, use it */
+	/* If we are targeting the default, use it */
 	pdev = priv->target;
 	if (pdev == NULL || pdev == PCI_INVALID_CARD) {
 		spin_unlock_irqrestore(&vga_lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/gpu/vga/vga_switcheroo.c linux-libre-2.6.39-gnu/drivers/gpu/vga/vga_switcheroo.c
--- linux-libre-2.6.38-gnu/drivers/gpu/vga/vga_switcheroo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/gpu/vga/vga_switcheroo.c	2011-05-19 00:06:34.000000000 -0400
@@ -219,9 +219,6 @@
 	int i;
 	struct vga_switcheroo_client *active = NULL;
 
-	if (new_client->active == true)
-		return 0;
-
 	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
 		if (vgasr_priv.clients[i].active == true) {
 			active = &vgasr_priv.clients[i];
@@ -372,6 +369,9 @@
 		goto out;
 	}
 
+	if (client->active == true)
+		goto out;
+
 	/* okay we want a switch - test if devices are willing to switch */
 	can_switch = true;
 	for (i = 0; i < VGA_SWITCHEROO_MAX_CLIENTS; i++) {
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-apple.c linux-libre-2.6.39-gnu/drivers/hid/hid-apple.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-apple.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-apple.c	2011-05-19 00:06:34.000000000 -0400
@@ -481,6 +481,12 @@
 		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
 		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+		.driver_data = APPLE_HAS_FN },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+		.driver_data = APPLE_HAS_FN | APPLE_ISO_KEYBOARD },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
+		.driver_data = APPLE_HAS_FN | APPLE_RDESC_JIS },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI),
 		.driver_data = APPLE_NUMLOCK_EMULATION | APPLE_HAS_FN },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO),
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-axff.c linux-libre-2.6.39-gnu/drivers/hid/hid-axff.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-axff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-axff.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,8 @@
 #include <linux/hid.h>
 
 #include "hid-ids.h"
+
+#ifdef CONFIG_HID_ACRUX_FF
 #include "usbhid/usbhid.h"
 
 struct axff_device {
@@ -109,6 +111,12 @@
 	kfree(axff);
 	return error;
 }
+#else
+static inline int axff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
 
 static int ax_probe(struct hid_device *hdev, const struct hid_device_id *id)
 {
@@ -139,9 +147,25 @@
 			 error);
 	}
 
+	/*
+	 * We need to start polling device right away, otherwise
+	 * it will go into a coma.
+	 */
+	error = hid_hw_open(hdev);
+	if (error) {
+		dev_err(&hdev->dev, "hw open failed\n");
+		return error;
+	}
+
 	return 0;
 }
 
+static void ax_remove(struct hid_device *hdev)
+{
+	hid_hw_close(hdev);
+	hid_hw_stop(hdev);
+}
+
 static const struct hid_device_id ax_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802), },
 	{ }
@@ -149,9 +173,10 @@
 MODULE_DEVICE_TABLE(hid, ax_devices);
 
 static struct hid_driver ax_driver = {
-	.name = "acrux",
-	.id_table = ax_devices,
-	.probe = ax_probe,
+	.name		= "acrux",
+	.id_table	= ax_devices,
+	.probe		= ax_probe,
+	.remove		= ax_remove,
 };
 
 static int __init ax_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-core.c linux-libre-2.6.39-gnu/drivers/hid/hid-core.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -306,7 +306,7 @@
 	case HID_GLOBAL_ITEM_TAG_PUSH:
 
 		if (parser->global_stack_ptr == HID_GLOBAL_STACK_SIZE) {
-			dbg_hid("global enviroment stack overflow\n");
+			dbg_hid("global environment stack overflow\n");
 			return -1;
 		}
 
@@ -317,7 +317,7 @@
 	case HID_GLOBAL_ITEM_TAG_POP:
 
 		if (!parser->global_stack_ptr) {
-			dbg_hid("global enviroment stack underflow\n");
+			dbg_hid("global environment stack underflow\n");
 			return -1;
 		}
 
@@ -1159,6 +1159,32 @@
 	return !!hid_match_id(hdev, hid_hiddev_list);
 }
 
+
+static ssize_t
+read_report_descriptor(struct file *filp, struct kobject *kobj,
+		struct bin_attribute *attr,
+		char *buf, loff_t off, size_t count)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct hid_device *hdev = container_of(dev, struct hid_device, dev);
+
+	if (off >= hdev->rsize)
+		return 0;
+
+	if (off + count > hdev->rsize)
+		count = hdev->rsize - off;
+
+	memcpy(buf, hdev->rdesc + off, count);
+
+	return count;
+}
+
+static struct bin_attribute dev_bin_attr_report_desc = {
+	.attr = { .name = "report_descriptor", .mode = 0444 },
+	.read = read_report_descriptor,
+	.size = HID_MAX_DESCRIPTOR_SIZE,
+};
+
 int hid_connect(struct hid_device *hdev, unsigned int connect_mask)
 {
 	static const char *types[] = { "Device", "Pointer", "Mouse", "Device",
@@ -1169,6 +1195,7 @@
 	char buf[64];
 	unsigned int i;
 	int len;
+	int ret;
 
 	if (hdev->quirks & HID_QUIRK_HIDDEV_FORCE)
 		connect_mask |= (HID_CONNECT_HIDDEV_FORCE | HID_CONNECT_HIDDEV);
@@ -1230,6 +1257,11 @@
 		bus = "<UNKNOWN>";
 	}
 
+	ret = device_create_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
+	if (ret)
+		hid_warn(hdev,
+			 "can't create sysfs report descriptor attribute err: %d\n", ret);
+
 	hid_info(hdev, "%s: %s HID v%x.%02x %s [%s] on %s\n",
 		 buf, bus, hdev->version >> 8, hdev->version & 0xff,
 		 type, hdev->name, hdev->phys);
@@ -1240,6 +1272,7 @@
 
 void hid_disconnect(struct hid_device *hdev)
 {
+	device_remove_bin_file(&hdev->dev, &dev_bin_attr_report_desc);
 	if (hdev->claimed & HID_CLAIMED_INPUT)
 		hidinput_disconnect(hdev);
 	if (hdev->claimed & HID_CLAIMED_HIDDEV)
@@ -1256,9 +1289,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_WCP32PU) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_X5_005D) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_A4TECH, USB_DEVICE_ID_A4TECH_RP_649) },
-#if defined(CONFIG_HID_ACRUX_FF) || defined(CONFIG_HID_ACRUX_FF_MODULE)
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ACRUX, 0x0802) },
-#endif
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ATV_IRCONTROL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_IRCONTROL4) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_MIGHTYMOUSE) },
@@ -1302,6 +1333,9 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS) },
@@ -1328,6 +1362,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_MOUSE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_CYPRESS, USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV, USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
@@ -1345,9 +1380,12 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_2) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_GYRATION, USB_DEVICE_ID_GYRATION_REMOTE_3) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_HANVON, USB_DEVICE_ID_HANVON_MULTITOUCH) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS, USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KENSINGTON, USB_DEVICE_ID_KS_SLIMBLADE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_ERGO_525V) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1368,6 +1406,7 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_FLIGHT_SYSTEM_G940) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_MOMO_WHEEL2) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_RUMBLEPAD2) },
@@ -1400,15 +1439,20 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_16) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_17) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_NTRIG, USB_DEVICE_ID_NTRIG_TOUCH_SCREEN_18) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_QUANTA_OPTICAL_TOUCH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONEPLUS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_IR_REMOTE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SAMSUNG, USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_PS3_CONTROLLER) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_SONY, USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE) },
@@ -1801,6 +1845,9 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_ISO) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_WELLSPRING5_JIS) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_FOUNTAIN_TP_ONLY) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_APPLE, USB_DEVICE_ID_APPLE_GEYSER1_TP_ONLY) },
 	{ }
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-debug.c linux-libre-2.6.39-gnu/drivers/hid/hid-debug.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -341,7 +341,7 @@
     { 0x85, 0x83, "DesignCapacity" },
     { 0x85, 0x85, "ManufacturerDate" },
     { 0x85, 0x89, "iDeviceChemistry" },
-    { 0x85, 0x8b, "Rechargable" },
+    { 0x85, 0x8b, "Rechargeable" },
     { 0x85, 0x8f, "iOEMInformation" },
     { 0x85, 0x8d, "CapacityGranularity1" },
     { 0x85, 0xd0, "ACPresent" },
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-dr.c linux-libre-2.6.39-gnu/drivers/hid/hid-dr.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-dr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-dr.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,312 @@
+/*
+ * Force feedback support for DragonRise Inc. game controllers
+ *
+ * From what I have gathered, these devices are mass produced in China and are
+ * distributed under several vendors. They often share the same design as
+ * the original PlayStation DualShock controller.
+ *
+ * 0079:0006 "DragonRise Inc.   Generic   USB  Joystick  "
+ *  - tested with a Tesun USB-703 game controller.
+ *
+ * Copyright (c) 2009 Richard Walmsley <richwalm@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/hid.h>
+
+#include "hid-ids.h"
+
+#ifdef CONFIG_DRAGONRISE_FF
+#include "usbhid/usbhid.h"
+
+struct drff_device {
+	struct hid_report *report;
+};
+
+static int drff_play(struct input_dev *dev, void *data,
+				 struct ff_effect *effect)
+{
+	struct hid_device *hid = input_get_drvdata(dev);
+	struct drff_device *drff = data;
+	int strong, weak;
+
+	strong = effect->u.rumble.strong_magnitude;
+	weak = effect->u.rumble.weak_magnitude;
+
+	dbg_hid("called with 0x%04x 0x%04x", strong, weak);
+
+	if (strong || weak) {
+		strong = strong * 0xff / 0xffff;
+		weak = weak * 0xff / 0xffff;
+
+		/* While reverse engineering this device, I found that when
+		   this value is set, it causes the strong rumble to function
+		   at a near maximum speed, so we'll bypass it. */
+		if (weak == 0x0a)
+			weak = 0x0b;
+
+		drff->report->field[0]->value[0] = 0x51;
+		drff->report->field[0]->value[1] = 0x00;
+		drff->report->field[0]->value[2] = weak;
+		drff->report->field[0]->value[4] = strong;
+		usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+
+		drff->report->field[0]->value[0] = 0xfa;
+		drff->report->field[0]->value[1] = 0xfe;
+	} else {
+		drff->report->field[0]->value[0] = 0xf3;
+		drff->report->field[0]->value[1] = 0x00;
+	}
+
+	drff->report->field[0]->value[2] = 0x00;
+	drff->report->field[0]->value[4] = 0x00;
+	dbg_hid("running with 0x%02x 0x%02x", strong, weak);
+	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+
+	return 0;
+}
+
+static int drff_init(struct hid_device *hid)
+{
+	struct drff_device *drff;
+	struct hid_report *report;
+	struct hid_input *hidinput = list_first_entry(&hid->inputs,
+						struct hid_input, list);
+	struct list_head *report_list =
+			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
+	struct input_dev *dev = hidinput->input;
+	int error;
+
+	if (list_empty(report_list)) {
+		hid_err(hid, "no output reports found\n");
+		return -ENODEV;
+	}
+
+	report = list_first_entry(report_list, struct hid_report, list);
+	if (report->maxfield < 1) {
+		hid_err(hid, "no fields in the report\n");
+		return -ENODEV;
+	}
+
+	if (report->field[0]->report_count < 7) {
+		hid_err(hid, "not enough values in the field\n");
+		return -ENODEV;
+	}
+
+	drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL);
+	if (!drff)
+		return -ENOMEM;
+
+	set_bit(FF_RUMBLE, dev->ffbit);
+
+	error = input_ff_create_memless(dev, drff, drff_play);
+	if (error) {
+		kfree(drff);
+		return error;
+	}
+
+	drff->report = report;
+	drff->report->field[0]->value[0] = 0xf3;
+	drff->report->field[0]->value[1] = 0x00;
+	drff->report->field[0]->value[2] = 0x00;
+	drff->report->field[0]->value[3] = 0x00;
+	drff->report->field[0]->value[4] = 0x00;
+	drff->report->field[0]->value[5] = 0x00;
+	drff->report->field[0]->value[6] = 0x00;
+	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
+
+	hid_info(hid, "Force Feedback for DragonRise Inc. "
+		 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
+
+	return 0;
+}
+#else
+static inline int drff_init(struct hid_device *hid)
+{
+	return 0;
+}
+#endif
+
+/*
+ * The original descriptor of joystick with PID 0x0011, represented by DVTech PC
+ * JS19. It seems both copied from another device and a result of confusion
+ * either about the specification or about the program used to create the
+ * descriptor. In any case, it's a wonder it works on Windows.
+ *
+ *  Usage Page (Desktop),             ; Generic desktop controls (01h)
+ *  Usage (Joystik),                  ; Joystik (04h, application collection)
+ *  Collection (Application),
+ *    Collection (Logical),
+ *      Report Size (8),
+ *      Report Count (5),
+ *      Logical Minimum (0),
+ *      Logical Maximum (255),
+ *      Physical Minimum (0),
+ *      Physical Maximum (255),
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (X),                    ; X (30h, dynamic value)
+ *      Usage (Y),                    ; Y (31h, dynamic value)
+ *      Input (Variable),
+ *      Report Size (4),
+ *      Report Count (1),
+ *      Logical Maximum (7),
+ *      Physical Maximum (315),
+ *      Unit (Degrees),
+ *      Usage (00h),
+ *      Input (Variable, Null State),
+ *      Unit,
+ *      Report Size (1),
+ *      Report Count (10),
+ *      Logical Maximum (1),
+ *      Physical Maximum (1),
+ *      Usage Page (Button),          ; Button (09h)
+ *      Usage Minimum (01h),
+ *      Usage Maximum (0Ah),
+ *      Input (Variable),
+ *      Usage Page (FF00h),           ; FF00h, vendor-defined
+ *      Report Size (1),
+ *      Report Count (10),
+ *      Logical Maximum (1),
+ *      Physical Maximum (1),
+ *      Usage (01h),
+ *      Input (Variable),
+ *    End Collection,
+ *    Collection (Logical),
+ *      Report Size (8),
+ *      Report Count (4),
+ *      Physical Maximum (255),
+ *      Logical Maximum (255),
+ *      Usage (02h),
+ *      Output (Variable),
+ *    End Collection,
+ *  End Collection
+ */
+
+/* Size of the original descriptor of the PID 0x0011 joystick */
+#define PID0011_RDESC_ORIG_SIZE	101
+
+/* Fixed report descriptor for PID 0x011 joystick */
+static __u8 pid0011_rdesc_fixed[] = {
+	0x05, 0x01,         /*  Usage Page (Desktop),           */
+	0x09, 0x04,         /*  Usage (Joystik),                */
+	0xA1, 0x01,         /*  Collection (Application),       */
+	0xA1, 0x02,         /*      Collection (Logical),       */
+	0x14,               /*          Logical Minimum (0),    */
+	0x75, 0x08,         /*          Report Size (8),        */
+	0x95, 0x03,         /*          Report Count (3),       */
+	0x81, 0x01,         /*          Input (Constant),       */
+	0x26, 0xFF, 0x00,   /*          Logical Maximum (255),  */
+	0x95, 0x02,         /*          Report Count (2),       */
+	0x09, 0x30,         /*          Usage (X),              */
+	0x09, 0x31,         /*          Usage (Y),              */
+	0x81, 0x02,         /*          Input (Variable),       */
+	0x75, 0x01,         /*          Report Size (1),        */
+	0x95, 0x04,         /*          Report Count (4),       */
+	0x81, 0x01,         /*          Input (Constant),       */
+	0x25, 0x01,         /*          Logical Maximum (1),    */
+	0x95, 0x0A,         /*          Report Count (10),      */
+	0x05, 0x09,         /*          Usage Page (Button),    */
+	0x19, 0x01,         /*          Usage Minimum (01h),    */
+	0x29, 0x0A,         /*          Usage Maximum (0Ah),    */
+	0x81, 0x02,         /*          Input (Variable),       */
+	0x95, 0x0A,         /*          Report Count (10),      */
+	0x81, 0x01,         /*          Input (Constant),       */
+	0xC0,               /*      End Collection,             */
+	0xC0                /*  End Collection                  */
+};
+
+static __u8 *dr_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+				unsigned int *rsize)
+{
+	switch (hdev->product) {
+	case 0x0011:
+		if (*rsize == PID0011_RDESC_ORIG_SIZE) {
+			rdesc = pid0011_rdesc_fixed;
+			*rsize = sizeof(pid0011_rdesc_fixed);
+		}
+		break;
+	}
+	return rdesc;
+}
+
+static int dr_probe(struct hid_device *hdev, const struct hid_device_id *id)
+{
+	int ret;
+
+	dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe...");
+
+	ret = hid_parse(hdev);
+	if (ret) {
+		hid_err(hdev, "parse failed\n");
+		goto err;
+	}
+
+	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
+	if (ret) {
+		hid_err(hdev, "hw start failed\n");
+		goto err;
+	}
+
+	switch (hdev->product) {
+	case 0x0006:
+		ret = drff_init(hdev);
+		if (ret) {
+			dev_err(&hdev->dev, "force feedback init failed\n");
+			hid_hw_stop(hdev);
+			goto err;
+		}
+		break;
+	}
+
+	return 0;
+err:
+	return ret;
+}
+
+static const struct hid_device_id dr_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006),  },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0011),  },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, dr_devices);
+
+static struct hid_driver dr_driver = {
+	.name = "dragonrise",
+	.id_table = dr_devices,
+	.report_fixup = dr_report_fixup,
+	.probe = dr_probe,
+};
+
+static int __init dr_init(void)
+{
+	return hid_register_driver(&dr_driver);
+}
+
+static void __exit dr_exit(void)
+{
+	hid_unregister_driver(&dr_driver);
+}
+
+module_init(dr_init);
+module_exit(dr_exit);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-drff.c linux-libre-2.6.39-gnu/drivers/hid/hid-drff.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-drff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-drff.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,197 +0,0 @@
-/*
- * Force feedback support for DragonRise Inc. game controllers
- *
- * From what I have gathered, these devices are mass produced in China and are
- * distributed under several vendors. They often share the same design as
- * the original PlayStation DualShock controller.
- *
- * 0079:0006 "DragonRise Inc.   Generic   USB  Joystick  "
- *  - tested with a Tesun USB-703 game controller.
- *
- * Copyright (c) 2009 Richard Walmsley <richwalm@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- */
-
-#include <linux/input.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-#include <linux/hid.h>
-
-#include "hid-ids.h"
-
-#ifdef CONFIG_DRAGONRISE_FF
-#include "usbhid/usbhid.h"
-
-struct drff_device {
-	struct hid_report *report;
-};
-
-static int drff_play(struct input_dev *dev, void *data,
-				 struct ff_effect *effect)
-{
-	struct hid_device *hid = input_get_drvdata(dev);
-	struct drff_device *drff = data;
-	int strong, weak;
-
-	strong = effect->u.rumble.strong_magnitude;
-	weak = effect->u.rumble.weak_magnitude;
-
-	dbg_hid("called with 0x%04x 0x%04x", strong, weak);
-
-	if (strong || weak) {
-		strong = strong * 0xff / 0xffff;
-		weak = weak * 0xff / 0xffff;
-
-		/* While reverse engineering this device, I found that when
-		   this value is set, it causes the strong rumble to function
-		   at a near maximum speed, so we'll bypass it. */
-		if (weak == 0x0a)
-			weak = 0x0b;
-
-		drff->report->field[0]->value[0] = 0x51;
-		drff->report->field[0]->value[1] = 0x00;
-		drff->report->field[0]->value[2] = weak;
-		drff->report->field[0]->value[4] = strong;
-		usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
-
-		drff->report->field[0]->value[0] = 0xfa;
-		drff->report->field[0]->value[1] = 0xfe;
-	} else {
-		drff->report->field[0]->value[0] = 0xf3;
-		drff->report->field[0]->value[1] = 0x00;
-	}
-
-	drff->report->field[0]->value[2] = 0x00;
-	drff->report->field[0]->value[4] = 0x00;
-	dbg_hid("running with 0x%02x 0x%02x", strong, weak);
-	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
-
-	return 0;
-}
-
-static int drff_init(struct hid_device *hid)
-{
-	struct drff_device *drff;
-	struct hid_report *report;
-	struct hid_input *hidinput = list_first_entry(&hid->inputs,
-						struct hid_input, list);
-	struct list_head *report_list =
-			&hid->report_enum[HID_OUTPUT_REPORT].report_list;
-	struct input_dev *dev = hidinput->input;
-	int error;
-
-	if (list_empty(report_list)) {
-		hid_err(hid, "no output reports found\n");
-		return -ENODEV;
-	}
-
-	report = list_first_entry(report_list, struct hid_report, list);
-	if (report->maxfield < 1) {
-		hid_err(hid, "no fields in the report\n");
-		return -ENODEV;
-	}
-
-	if (report->field[0]->report_count < 7) {
-		hid_err(hid, "not enough values in the field\n");
-		return -ENODEV;
-	}
-
-	drff = kzalloc(sizeof(struct drff_device), GFP_KERNEL);
-	if (!drff)
-		return -ENOMEM;
-
-	set_bit(FF_RUMBLE, dev->ffbit);
-
-	error = input_ff_create_memless(dev, drff, drff_play);
-	if (error) {
-		kfree(drff);
-		return error;
-	}
-
-	drff->report = report;
-	drff->report->field[0]->value[0] = 0xf3;
-	drff->report->field[0]->value[1] = 0x00;
-	drff->report->field[0]->value[2] = 0x00;
-	drff->report->field[0]->value[3] = 0x00;
-	drff->report->field[0]->value[4] = 0x00;
-	drff->report->field[0]->value[5] = 0x00;
-	drff->report->field[0]->value[6] = 0x00;
-	usbhid_submit_report(hid, drff->report, USB_DIR_OUT);
-
-	hid_info(hid, "Force Feedback for DragonRise Inc. "
-		 "game controllers by Richard Walmsley <richwalm@gmail.com>\n");
-
-	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)
-{
-	int ret;
-
-	dev_dbg(&hdev->dev, "DragonRise Inc. HID hardware probe...");
-
-	ret = hid_parse(hdev);
-	if (ret) {
-		hid_err(hdev, "parse failed\n");
-		goto err;
-	}
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT & ~HID_CONNECT_FF);
-	if (ret) {
-		hid_err(hdev, "hw start failed\n");
-		goto err;
-	}
-
-	drff_init(hdev);
-
-	return 0;
-err:
-	return ret;
-}
-
-static const struct hid_device_id dr_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DRAGONRISE, 0x0006),  },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, dr_devices);
-
-static struct hid_driver dr_driver = {
-	.name = "dragonrise",
-	.id_table = dr_devices,
-	.probe = dr_probe,
-};
-
-static int __init dr_init(void)
-{
-	return hid_register_driver(&dr_driver);
-}
-
-static void __exit dr_exit(void)
-{
-	hid_unregister_driver(&dr_driver);
-}
-
-module_init(dr_init);
-module_exit(dr_exit);
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-egalax.c linux-libre-2.6.39-gnu/drivers/hid/hid-egalax.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-egalax.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-egalax.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,279 +0,0 @@
-/*
- *  HID driver for eGalax dual-touch panels
- *
- *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
- *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
- *  Copyright (c) 2010 Canonical, 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.
- */
-
-#include <linux/device.h>
-#include <linux/hid.h>
-#include <linux/module.h>
-#include <linux/usb.h>
-#include <linux/input/mt.h>
-#include <linux/slab.h>
-#include "usbhid/usbhid.h"
-
-MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
-MODULE_DESCRIPTION("eGalax dual-touch panel");
-MODULE_LICENSE("GPL");
-
-#include "hid-ids.h"
-
-#define MAX_SLOTS		2
-
-/* estimated signal-to-noise ratios */
-#define SN_MOVE			4096
-#define SN_PRESSURE		32
-
-struct egalax_data {
-	int valid;
-	int slot;
-	int touch;
-	int x, y, z;
-};
-
-static void set_abs(struct input_dev *input, unsigned int code,
-		    struct hid_field *field, int snratio)
-{
-	int fmin = field->logical_minimum;
-	int fmax = field->logical_maximum;
-	int fuzz = snratio ? (fmax - fmin) / snratio : 0;
-	input_set_abs_params(input, code, fmin, fmax, fuzz, 0);
-}
-
-static int egalax_input_mapping(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	struct input_dev *input = hi->input;
-
-	switch (usage->hid & HID_USAGE_PAGE) {
-
-	case HID_UP_GENDESK:
-		switch (usage->hid) {
-		case HID_GD_X:
-			field->logical_maximum = 32760;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_X);
-			set_abs(input, ABS_MT_POSITION_X, field, SN_MOVE);
-			/* touchscreen emulation */
-			set_abs(input, ABS_X, field, SN_MOVE);
-			return 1;
-		case HID_GD_Y:
-			field->logical_maximum = 32760;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_POSITION_Y);
-			set_abs(input, ABS_MT_POSITION_Y, field, SN_MOVE);
-			/* touchscreen emulation */
-			set_abs(input, ABS_Y, field, SN_MOVE);
-			return 1;
-		}
-		return 0;
-
-	case HID_UP_DIGITIZER:
-		switch (usage->hid) {
-		case HID_DG_TIPSWITCH:
-			/* touchscreen emulation */
-			hid_map_usage(hi, usage, bit, max, EV_KEY, BTN_TOUCH);
-			input_set_capability(input, EV_KEY, BTN_TOUCH);
-			return 1;
-		case HID_DG_INRANGE:
-		case HID_DG_CONFIDENCE:
-		case HID_DG_CONTACTCOUNT:
-		case HID_DG_CONTACTMAX:
-			return -1;
-		case HID_DG_CONTACTID:
-			input_mt_init_slots(input, MAX_SLOTS);
-			return 1;
-		case HID_DG_TIPPRESSURE:
-			field->logical_minimum = 0;
-			hid_map_usage(hi, usage, bit, max,
-					EV_ABS, ABS_MT_PRESSURE);
-			set_abs(input, ABS_MT_PRESSURE, field, SN_PRESSURE);
-			/* touchscreen emulation */
-			set_abs(input, ABS_PRESSURE, field, SN_PRESSURE);
-			return 1;
-		}
-		return 0;
-	}
-
-	/* ignore others (from other reports we won't get anyway) */
-	return -1;
-}
-
-static int egalax_input_mapped(struct hid_device *hdev, struct hid_input *hi,
-		struct hid_field *field, struct hid_usage *usage,
-		unsigned long **bit, int *max)
-{
-	/* tell hid-input to skip setup of these event types */
-	if (usage->type == EV_KEY || usage->type == EV_ABS)
-		set_bit(usage->type, hi->input->evbit);
-	return -1;
-}
-
-/*
- * this function is called when a whole finger has been parsed,
- * so that it can decide what to send to the input layer.
- */
-static void egalax_filter_event(struct egalax_data *td, struct input_dev *input)
-{
-	input_mt_slot(input, td->slot);
-	input_mt_report_slot_state(input, MT_TOOL_FINGER, td->touch);
-	if (td->touch) {
-		input_event(input, EV_ABS, ABS_MT_POSITION_X, td->x);
-		input_event(input, EV_ABS, ABS_MT_POSITION_Y, td->y);
-		input_event(input, EV_ABS, ABS_MT_PRESSURE, td->z);
-	}
-	input_mt_report_pointer_emulation(input, true);
-}
-
-static int egalax_event(struct hid_device *hid, struct hid_field *field,
-				struct hid_usage *usage, __s32 value)
-{
-	struct egalax_data *td = hid_get_drvdata(hid);
-
-	/* Note, eGalax has two product lines: the first is resistive and
-	 * uses a standard parallel multitouch protocol (product ID ==
-	 * 48xx).  The second is capacitive and uses an unusual "serial"
-	 * protocol with a different message for each multitouch finger
-	 * (product ID == 72xx).
-	 */
-	if (hid->claimed & HID_CLAIMED_INPUT) {
-		struct input_dev *input = field->hidinput->input;
-
-		switch (usage->hid) {
-		case HID_DG_INRANGE:
-			td->valid = value;
-			break;
-		case HID_DG_CONFIDENCE:
-			/* avoid interference from generic hidinput handling */
-			break;
-		case HID_DG_TIPSWITCH:
-			td->touch = value;
-			break;
-		case HID_DG_TIPPRESSURE:
-			td->z = value;
-			break;
-		case HID_DG_CONTACTID:
-			td->slot = clamp_val(value, 0, MAX_SLOTS - 1);
-			break;
-		case HID_GD_X:
-			td->x = value;
-			break;
-		case HID_GD_Y:
-			td->y = value;
-			/* this is the last field in a finger */
-			if (td->valid)
-				egalax_filter_event(td, input);
-			break;
-		case HID_DG_CONTACTCOUNT:
-			/* touch emulation: this is the last field in a frame */
-			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 egalax_probe(struct hid_device *hdev, const struct hid_device_id *id)
-{
-	int ret;
-	struct egalax_data *td;
-	struct hid_report *report;
-
-	td = kzalloc(sizeof(struct egalax_data), GFP_KERNEL);
-	if (!td) {
-		hid_err(hdev, "cannot allocate eGalax data\n");
-		return -ENOMEM;
-	}
-	hid_set_drvdata(hdev, td);
-
-	ret = hid_parse(hdev);
-	if (ret)
-		goto end;
-
-	ret = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
-	if (ret)
-		goto end;
-
-	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[5]; 
-	if (report) {
-		report->field[0]->value[0] = 2;
-		usbhid_submit_report(hdev, report, USB_DIR_OUT);
-	}
-
-end:
-	if (ret)
-		kfree(td);
-
-	return ret;
-}
-
-static void egalax_remove(struct hid_device *hdev)
-{
-	hid_hw_stop(hdev);
-	kfree(hid_get_drvdata(hdev));
-	hid_set_drvdata(hdev, NULL);
-}
-
-static const struct hid_device_id egalax_devices[] = {
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
-	{ HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
-			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
-	{ }
-};
-MODULE_DEVICE_TABLE(hid, egalax_devices);
-
-static const struct hid_usage_id egalax_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 egalax_driver = {
-	.name = "egalax-touch",
-	.id_table = egalax_devices,
-	.probe = egalax_probe,
-	.remove = egalax_remove,
-	.input_mapping = egalax_input_mapping,
-	.input_mapped = egalax_input_mapped,
-	.usage_table = egalax_grabbed_usages,
-	.event = egalax_event,
-};
-
-static int __init egalax_init(void)
-{
-	return hid_register_driver(&egalax_driver);
-}
-
-static void __exit egalax_exit(void)
-{
-	hid_unregister_driver(&egalax_driver);
-}
-
-module_init(egalax_init);
-module_exit(egalax_exit);
-
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-gyration.c linux-libre-2.6.39-gnu/drivers/hid/hid-gyration.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-gyration.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-gyration.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,11 @@
 	case 0x048: gy_map_key_clear(KEY_MEDIA);	break;
 	case 0x049: gy_map_key_clear(KEY_CAMERA);	break;
 	case 0x04a: gy_map_key_clear(KEY_VIDEO);	break;
+	case 0x05a: gy_map_key_clear(KEY_TEXT);		break;
+	case 0x05b: gy_map_key_clear(KEY_RED);		break;
+	case 0x05c: gy_map_key_clear(KEY_GREEN);	break;
+	case 0x05d: gy_map_key_clear(KEY_YELLOW);	break;
+	case 0x05e: gy_map_key_clear(KEY_BLUE);		break;
 
 	default:
 		return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-ids.h linux-libre-2.6.39-gnu/drivers/hid/hid-ids.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-ids.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-ids.h	2011-05-19 00:06:34.000000000 -0400
@@ -103,6 +103,9 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI	0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO	0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS	0x0247
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ANSI  0x0239
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_ISO   0x023a
 #define USB_DEVICE_ID_APPLE_ALU_WIRELESS_2009_JIS   0x023b
@@ -147,6 +150,7 @@
 #define USB_DEVICE_ID_CANDO_MULTI_TOUCH_15_6 0x0f01
 
 #define USB_VENDOR_ID_CH		0x068e
+#define USB_DEVICE_ID_CH_PRO_THROTTLE	0x00f1
 #define USB_DEVICE_ID_CH_PRO_PEDALS	0x00f2
 #define USB_DEVICE_ID_CH_COMBATSTICK	0x00f4
 #define USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE       0x0051
@@ -333,6 +337,9 @@
 #define USB_VENDOR_ID_IMATION		0x0718
 #define USB_DEVICE_ID_DISC_STAKKA	0xd000
 
+#define USB_VENDOR_ID_IRTOUCHSYSTEMS	0x6615
+#define USB_DEVICE_ID_IRTOUCH_INFRARED_USB	0x0070
+
 #define USB_VENDOR_ID_JESS		0x0c45
 #define USB_DEVICE_ID_JESS_YUREX	0x1010
 
@@ -345,6 +352,9 @@
 #define USB_VENDOR_ID_KWORLD		0x1b80
 #define USB_DEVICE_ID_KWORLD_RADIO_FM700	0xd700
 
+#define USB_VENDOR_ID_KEYTOUCH		0x0926
+#define USB_DEVICE_ID_KEYTOUCH_IEC	0x3333
+
 #define USB_VENDOR_ID_KYE		0x0458
 #define USB_DEVICE_ID_KYE_ERGO_525V	0x0087
 #define USB_DEVICE_ID_KYE_GPEN_560	0x5003
@@ -352,6 +362,9 @@
 #define USB_VENDOR_ID_LABTEC		0x1020
 #define USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD	0x0006
 
+#define USB_VENDOR_ID_LCPOWER		0x1241
+#define USB_DEVICE_ID_LCPOWER_LC1000	0xf767
+
 #define USB_VENDOR_ID_LD		0x0f11
 #define USB_DEVICE_ID_LD_CASSY		0x1000
 #define USB_DEVICE_ID_LD_POCKETCASSY	0x1010
@@ -383,6 +396,7 @@
 #define USB_DEVICE_ID_LOGITECH_WHEEL	0xc294
 #define USB_DEVICE_ID_LOGITECH_WINGMAN_FFG	0xc293
 #define USB_DEVICE_ID_LOGITECH_MOMO_WHEEL	0xc295
+#define USB_DEVICE_ID_LOGITECH_DFP_WHEEL	0xc298
 #define USB_DEVICE_ID_LOGITECH_G25_WHEEL	0xc299
 #define USB_DEVICE_ID_LOGITECH_WII_WHEEL	0xc29c
 #define USB_DEVICE_ID_LOGITECH_ELITE_KBD	0xc30a
@@ -466,6 +480,7 @@
 #define USB_DEVICE_ID_ONTRAK_ADU100	0x0064
 
 #define USB_VENDOR_ID_ORTEK		0x05a4
+#define USB_DEVICE_ID_ORTEK_PKB1700	0x1700
 #define USB_DEVICE_ID_ORTEK_WKB2000	0x2000
 
 #define USB_VENDOR_ID_PANJIT		0x134c
@@ -496,8 +511,10 @@
 #define USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN	0x3001
 
 #define USB_VENDOR_ID_ROCCAT		0x1e7d
+#define USB_DEVICE_ID_ROCCAT_ARVO	0x30d4
 #define USB_DEVICE_ID_ROCCAT_KONE	0x2ced
 #define USB_DEVICE_ID_ROCCAT_KONEPLUS	0x2d51
+#define USB_DEVICE_ID_ROCCAT_KOVAPLUS	0x2d50
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRED	0x2c24
 #define USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS	0x2cf6
 
@@ -508,6 +525,9 @@
 #define USB_DEVICE_ID_SAMSUNG_IR_REMOTE	0x0001
 #define USB_DEVICE_ID_SAMSUNG_WIRELESS_KBD_MOUSE	0x0600
 
+#define USB_VENDOR_ID_SKYCABLE			0x1223
+#define	USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER	0x3F07
+
 #define USB_VENDOR_ID_SONY			0x054c
 #define USB_DEVICE_ID_SONY_VAIO_VGX_MOUSE	0x024b
 #define USB_DEVICE_ID_SONY_PS3_CONTROLLER	0x0268
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-input.c linux-libre-2.6.39-gnu/drivers/hid/hid-input.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-input.c	2011-05-19 00:06:34.000000000 -0400
@@ -290,14 +290,6 @@
 		goto ignore;
 	}
 
-	if (field->report_type == HID_FEATURE_REPORT) {
-		if (device->driver->feature_mapping) {
-			device->driver->feature_mapping(device, hidinput, field,
-				usage);
-		}
-		goto ignore;
-	}
-
 	if (device->driver->input_mapping) {
 		int ret = device->driver->input_mapping(device, hidinput, field,
 				usage, &bit, &max);
@@ -835,6 +827,24 @@
 	hid_hw_close(hid);
 }
 
+static void report_features(struct hid_device *hid)
+{
+	struct hid_driver *drv = hid->driver;
+	struct hid_report_enum *rep_enum;
+	struct hid_report *rep;
+	int i, j;
+
+	if (!drv->feature_mapping)
+		return;
+
+	rep_enum = &hid->report_enum[HID_FEATURE_REPORT];
+	list_for_each_entry(rep, &rep_enum->report_list, list)
+		for (i = 0; i < rep->maxfield; i++)
+			for (j = 0; j < rep->field[i]->maxusage; j++)
+				drv->feature_mapping(hid, rep->field[i],
+						     rep->field[i]->usage + j);
+}
+
 /*
  * Register the input device; print a message.
  * Configure the input layer interface
@@ -863,7 +873,9 @@
 			return -1;
 	}
 
-	for (k = HID_INPUT_REPORT; k <= HID_FEATURE_REPORT; k++) {
+	report_features(hid);
+
+	for (k = HID_INPUT_REPORT; k <= HID_OUTPUT_REPORT; k++) {
 		if (k == HID_OUTPUT_REPORT &&
 			hid->quirks & HID_QUIRK_SKIP_OUTPUT_REPORTS)
 			continue;
@@ -888,8 +900,8 @@
 					hid->ll_driver->hidinput_input_event;
 				input_dev->open = hidinput_open;
 				input_dev->close = hidinput_close;
-				input_dev->setkeycode_new = hidinput_setkeycode;
-				input_dev->getkeycode_new = hidinput_getkeycode;
+				input_dev->setkeycode = hidinput_setkeycode;
+				input_dev->getkeycode = hidinput_getkeycode;
 
 				input_dev->name = hid->name;
 				input_dev->phys = hid->phys;
@@ -928,6 +940,7 @@
 	return 0;
 
 out_cleanup:
+	list_del(&hidinput->list);
 	input_free_device(hidinput->input);
 	kfree(hidinput);
 out_unwind:
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-keytouch.c linux-libre-2.6.39-gnu/drivers/hid/hid-keytouch.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-keytouch.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-keytouch.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,66 @@
+/*
+ *  HID driver for Keytouch devices not fully compliant with HID standard
+ *
+ *  Copyright (c) 2011 Jiri Kosina
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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"
+
+/* Replace the broken report descriptor of this device with rather
+ * a default one */
+static __u8 keytouch_fixed_rdesc[] = {
+0x05, 0x01, 0x09, 0x06, 0xa1, 0x01, 0x05, 0x07, 0x19, 0xe0, 0x29, 0xe7, 0x15,
+0x00, 0x25, 0x01, 0x75, 0x01, 0x95, 0x08, 0x81, 0x02, 0x95, 0x01, 0x75, 0x08,
+0x81, 0x01, 0x95, 0x03, 0x75, 0x01, 0x05, 0x08, 0x19, 0x01, 0x29, 0x03, 0x91,
+0x02, 0x95, 0x05, 0x75, 0x01, 0x91, 0x01, 0x95, 0x06, 0x75, 0x08, 0x15, 0x00,
+0x26, 0xff, 0x00, 0x05, 0x07, 0x19, 0x00, 0x2a, 0xff, 0x00, 0x81, 0x00, 0xc0
+};
+
+static __u8 *keytouch_report_fixup(struct hid_device *hdev, __u8 *rdesc,
+		unsigned int *rsize)
+{
+	hid_info(hdev, "fixing up Keytouch IEC report descriptor\n");
+
+	rdesc = keytouch_fixed_rdesc;
+	*rsize = sizeof(keytouch_fixed_rdesc);
+
+	return rdesc;
+}
+
+static const struct hid_device_id keytouch_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_KEYTOUCH, USB_DEVICE_ID_KEYTOUCH_IEC) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, keytouch_devices);
+
+static struct hid_driver keytouch_driver = {
+	.name = "keytouch",
+	.id_table = keytouch_devices,
+	.report_fixup = keytouch_report_fixup,
+};
+
+static int __init keytouch_init(void)
+{
+	return hid_register_driver(&keytouch_driver);
+}
+
+static void __exit keytouch_exit(void)
+{
+	hid_unregister_driver(&keytouch_driver);
+}
+
+module_init(keytouch_init);
+module_exit(keytouch_exit);
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jiri Kosina");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-lcpower.c linux-libre-2.6.39-gnu/drivers/hid/hid-lcpower.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-lcpower.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-lcpower.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ *  HID driver for LC Power Model RC1000MCE
+ *
+ *  Copyright (c) 2011 Chris Schlund 
+ *  based on hid-topseed module
+ */
+
+/*
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the 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"
+
+#define ts_map_key_clear(c)	hid_map_usage_clear(hi, usage, bit, max, \
+					EV_KEY, (c))
+static int ts_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) != 0x0ffbc0000)
+		return 0;
+
+	switch (usage->hid & HID_USAGE) {
+        case 0x046: ts_map_key_clear(KEY_YELLOW);         break;
+        case 0x047: ts_map_key_clear(KEY_GREEN);          break;
+        case 0x049: ts_map_key_clear(KEY_BLUE);           break;
+        case 0x04a: ts_map_key_clear(KEY_RED);		  break;
+        case 0x00d: ts_map_key_clear(KEY_HOME);           break;
+        case 0x025: ts_map_key_clear(KEY_TV);             break;
+        case 0x048: ts_map_key_clear(KEY_VCR);            break;
+        case 0x024: ts_map_key_clear(KEY_MENU);           break;
+        default:
+        return 0;
+	}
+
+	return 1;
+}
+
+static const struct hid_device_id ts_devices[] = {
+	{ HID_USB_DEVICE( USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000) },
+	{ }
+};
+MODULE_DEVICE_TABLE(hid, ts_devices);
+
+static struct hid_driver ts_driver = {
+	.name = "LC RC1000MCE",
+	.id_table = ts_devices,
+	.input_mapping = ts_input_mapping,
+};
+
+static int __init ts_init(void)
+{
+	return hid_register_driver(&ts_driver);
+}
+
+static void __exit ts_exit(void)
+{
+	hid_unregister_driver(&ts_driver);
+}
+
+module_init(ts_init);
+module_exit(ts_exit);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-lg.c linux-libre-2.6.39-gnu/drivers/hid/hid-lg.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-lg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-lg.c	2011-05-19 00:06:34.000000000 -0400
@@ -377,6 +377,8 @@
 		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_G25_WHEEL),
 		.driver_data = LG_FF },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_DFP_WHEEL),
+		.driver_data = LG_FF },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WII_WHEEL),
 		.driver_data = LG_FF4 },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_LOGITECH_WINGMAN_FFG ),
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-lgff.c linux-libre-2.6.39-gnu/drivers/hid/hid-lgff.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-lgff.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-lgff.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,6 +73,8 @@
 	{ 0x046d, 0xc293, ff_joystick },
 	{ 0x046d, 0xc294, ff_wheel },
 	{ 0x046d, 0xc295, ff_joystick },
+	{ 0x046d, 0xc298, ff_wheel },
+	{ 0x046d, 0xc299, ff_wheel },
 	{ 0x046d, 0xca03, ff_wheel },
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-magicmouse.c linux-libre-2.6.39-gnu/drivers/hid/hid-magicmouse.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-magicmouse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-magicmouse.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
  * This is true when single_touch_id is equal to NO_TOUCHES. If multiple touches
  * are down and the touch providing for single touch emulation is lifted,
  * single_touch_id is equal to SINGLE_TOUCH_UP. While single touch emulation is
- * occuring, single_touch_id corresponds with the tracking id of the touch used.
+ * occurring, single_touch_id corresponds with the tracking id of the touch used.
  */
 #define NO_TOUCHES -1
 #define SINGLE_TOUCH_UP -2
@@ -258,7 +258,7 @@
 		input_report_abs(input, ABS_MT_TRACKING_ID, id);
 		input_report_abs(input, ABS_MT_TOUCH_MAJOR, touch_major << 2);
 		input_report_abs(input, ABS_MT_TOUCH_MINOR, touch_minor << 2);
-		input_report_abs(input, ABS_MT_ORIENTATION, orientation);
+		input_report_abs(input, ABS_MT_ORIENTATION, -orientation);
 		input_report_abs(input, ABS_MT_POSITION_X, x);
 		input_report_abs(input, ABS_MT_POSITION_Y, y);
 
@@ -397,7 +397,7 @@
 		input_set_abs_params(input, ABS_MT_TRACKING_ID, 0, 15, 0, 0);
 		input_set_abs_params(input, ABS_MT_TOUCH_MAJOR, 0, 255, 4, 0);
 		input_set_abs_params(input, ABS_MT_TOUCH_MINOR, 0, 255, 4, 0);
-		input_set_abs_params(input, ABS_MT_ORIENTATION, -32, 31, 1, 0);
+		input_set_abs_params(input, ABS_MT_ORIENTATION, -31, 32, 1, 0);
 
 		/* Note: Touch Y position from the device is inverted relative
 		 * to how pointer motion is reported (and relative to how USB
@@ -418,6 +418,8 @@
 			input_set_abs_params(input, ABS_MT_POSITION_Y, -2456,
 				2565, 4, 0);
 		}
+
+		input_set_events_per_packet(input, 60);
 	}
 
 	if (report_undeciphered) {
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-multitouch.c linux-libre-2.6.39-gnu/drivers/hid/hid-multitouch.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-multitouch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-multitouch.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,12 @@
  *  Copyright (c) 2010-2011 Benjamin Tissoires <benjamin.tissoires@gmail.com>
  *  Copyright (c) 2010-2011 Ecole Nationale de l'Aviation Civile, France
  *
+ *  This code is partly based on hid-egalax.c:
+ *
+ *  Copyright (c) 2010 Stephane Chatty <chatty@enac.fr>
+ *  Copyright (c) 2010 Henrik Rydberg <rydberg@euromail.se>
+ *  Copyright (c) 2010 Canonical, Ltd.
+ *
  */
 
 /*
@@ -24,6 +30,7 @@
 
 
 MODULE_AUTHOR("Stephane Chatty <chatty@enac.fr>");
+MODULE_AUTHOR("Benjamin Tissoires <benjamin.tissoires@gmail.com>");
 MODULE_DESCRIPTION("HID multitouch panels");
 MODULE_LICENSE("GPL");
 
@@ -36,6 +43,7 @@
 #define MT_QUIRK_SLOT_IS_CONTACTNUMBER	(1 << 3)
 #define MT_QUIRK_VALID_IS_INRANGE	(1 << 4)
 #define MT_QUIRK_VALID_IS_CONFIDENCE	(1 << 5)
+#define MT_QUIRK_EGALAX_XYZ_FIXUP	(1 << 6)
 
 struct mt_slot {
 	__s32 x, y, p, w, h;
@@ -65,10 +73,11 @@
 };
 
 /* classes of device behavior */
-#define MT_CLS_DEFAULT	1
-#define MT_CLS_DUAL1	2
-#define MT_CLS_DUAL2	3
-#define MT_CLS_CYPRESS	4
+#define MT_CLS_DEFAULT				1
+#define MT_CLS_DUAL_INRANGE_CONTACTID		2
+#define MT_CLS_DUAL_INRANGE_CONTACTNUMBER	3
+#define MT_CLS_CYPRESS				4
+#define MT_CLS_EGALAX				5
 
 /*
  * these device-dependent functions determine what slot corresponds
@@ -104,13 +113,13 @@
 
 struct mt_class mt_classes[] = {
 	{ .name = MT_CLS_DEFAULT,
-		.quirks = MT_QUIRK_VALID_IS_INRANGE,
+		.quirks = MT_QUIRK_NOT_SEEN_MEANS_UP,
 		.maxcontacts = 10 },
-	{ .name = MT_CLS_DUAL1,
+	{ .name = MT_CLS_DUAL_INRANGE_CONTACTID,
 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
 			MT_QUIRK_SLOT_IS_CONTACTID,
 		.maxcontacts = 2 },
-	{ .name = MT_CLS_DUAL2,
+	{ .name = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
 		.quirks = MT_QUIRK_VALID_IS_INRANGE |
 			MT_QUIRK_SLOT_IS_CONTACTNUMBER,
 		.maxcontacts = 2 },
@@ -119,10 +128,18 @@
 			MT_QUIRK_CYPRESS,
 		.maxcontacts = 10 },
 
+	{ .name = MT_CLS_EGALAX,
+		.quirks =  MT_QUIRK_SLOT_IS_CONTACTID |
+			MT_QUIRK_VALID_IS_INRANGE |
+			MT_QUIRK_EGALAX_XYZ_FIXUP,
+		.maxcontacts = 2,
+		.sn_move = 4096,
+		.sn_pressure = 32,
+	},
 	{ }
 };
 
-static void mt_feature_mapping(struct hid_device *hdev, struct hid_input *hi,
+static void mt_feature_mapping(struct hid_device *hdev,
 		struct hid_field *field, struct hid_usage *usage)
 {
 	if (usage->hid == HID_DG_INPUTMODE) {
@@ -146,11 +163,15 @@
 {
 	struct mt_device *td = hid_get_drvdata(hdev);
 	struct mt_class *cls = td->mtclass;
+	__s32 quirks = cls->quirks;
+
 	switch (usage->hid & HID_USAGE_PAGE) {
 
 	case HID_UP_GENDESK:
 		switch (usage->hid) {
 		case HID_GD_X:
+			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
+				field->logical_maximum = 32760;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_X);
 			set_abs(hi->input, ABS_MT_POSITION_X, field,
@@ -160,6 +181,8 @@
 			td->last_slot_field = usage->hid;
 			return 1;
 		case HID_GD_Y:
+			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
+				field->logical_maximum = 32760;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_POSITION_Y);
 			set_abs(hi->input, ABS_MT_POSITION_Y, field,
@@ -203,6 +226,8 @@
 			td->last_slot_field = usage->hid;
 			return 1;
 		case HID_DG_TIPPRESSURE:
+			if (quirks & MT_QUIRK_EGALAX_XYZ_FIXUP)
+				field->logical_minimum = 0;
 			hid_map_usage(hi, usage, bit, max,
 					EV_ABS, ABS_MT_PRESSURE);
 			set_abs(hi->input, ABS_MT_PRESSURE, field,
@@ -363,8 +388,11 @@
 			return 0;
 		}
 
-		if (usage->hid == td->last_slot_field)
+		if (usage->hid == td->last_slot_field) {
 			mt_complete_slot(td);
+			if (!td->last_field_index)
+				mt_emit_event(td, field->hidinput->input);
+		}
 
 		if (field->index == td->last_field_index
 			&& td->num_received >= td->num_expected)
@@ -466,18 +494,42 @@
 			USB_DEVICE_ID_CYPRESS_TRUETOUCH) },
 
 	/* GeneralTouch panel */
-	{ .driver_data = MT_CLS_DUAL2,
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTNUMBER,
 		HID_USB_DEVICE(USB_VENDOR_ID_GENERAL_TOUCH,
 			USB_DEVICE_ID_GENERAL_TOUCH_WIN7_TWOFINGERS) },
 
+	/* IRTOUCH panels */
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
+		HID_USB_DEVICE(USB_VENDOR_ID_IRTOUCHSYSTEMS,
+			USB_DEVICE_ID_IRTOUCH_INFRARED_USB) },
+
 	/* PixCir-based panels */
-	{ .driver_data = MT_CLS_DUAL1,
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
 		HID_USB_DEVICE(USB_VENDOR_ID_HANVON,
 			USB_DEVICE_ID_HANVON_MULTITOUCH) },
-	{ .driver_data = MT_CLS_DUAL1,
+	{ .driver_data = MT_CLS_DUAL_INRANGE_CONTACTID,
 		HID_USB_DEVICE(USB_VENDOR_ID_CANDO,
 			USB_DEVICE_ID_CANDO_PIXCIR_MULTI_TOUCH) },
 
+	/* Resistive eGalax devices */
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH) },
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH3) },
+
+	/* Capacitive eGalax devices */
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH1) },
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH2) },
+	{  .driver_data = MT_CLS_EGALAX,
+		HID_USB_DEVICE(USB_VENDOR_ID_DWAV,
+			USB_DEVICE_ID_DWAV_EGALAX_MULTITOUCH4) },
+
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, mt_devices);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-ntrig.c linux-libre-2.6.39-gnu/drivers/hid/hid-ntrig.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-ntrig.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-ntrig.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,6 +110,36 @@
 	return sprintf(buf, "%u.%u.%u.%u.%u", a, b, c, d, e);
 }
 
+static inline int ntrig_get_mode(struct hid_device *hdev)
+{
+	struct hid_report *report = hdev->report_enum[HID_FEATURE_REPORT].
+				    report_id_hash[0x0d];
+
+	if (!report)
+		return -EINVAL;
+
+	usbhid_submit_report(hdev, report, USB_DIR_IN);
+	usbhid_wait_io(hdev);
+	return (int)report->field[0]->value[0];
+}
+
+static inline void ntrig_set_mode(struct hid_device *hdev, const int mode)
+{
+	struct hid_report *report;
+	__u8 mode_commands[4] = { 0xe, 0xf, 0x1b, 0x10 };
+
+	if (mode < 0 || mode > 3)
+		return;
+
+	report = hdev->report_enum[HID_FEATURE_REPORT].
+		 report_id_hash[mode_commands[mode]];
+
+	if (!report)
+		return;
+
+	usbhid_submit_report(hdev, report, USB_DIR_IN);
+}
+
 static void ntrig_report_version(struct hid_device *hdev)
 {
 	int ret;
@@ -539,277 +569,288 @@
 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);
+	struct input_dev *input;
+
+	/* Skip processing if not a claimed input */
+	if (!(hid->claimed & HID_CLAIMED_INPUT))
+		goto not_claimed_input;
+
+	/* This function is being called before the structures are fully
+	 * initialized */
+	if(!(field->hidinput && field->hidinput->input))
+		return -EINVAL;
+
+	input = field->hidinput->input;
 
 	/* No special handling needed for the pen */
 	if (field->application == HID_DG_PEN)
 		return 0;
 
-        if (hid->claimed & HID_CLAIMED_INPUT) {
-		switch (usage->hid) {
-		case 0xff000001:
-			/* Tag indicating the start of a multitouch group */
-			nd->reading_mt = 1;
-			nd->first_contact_touch = 0;
-			break;
-		case HID_DG_TIPSWITCH:
-			nd->tipswitch = value;
-			/* Prevent emission of touch until validated */
-			return 1;
-		case HID_DG_CONFIDENCE:
-			nd->confidence = value;
-			break;
-		case HID_GD_X:
-			nd->x = value;
-			/* Clear the contact footer */
-			nd->mt_foot_count = 0;
-			break;
-		case HID_GD_Y:
-			nd->y = value;
-			break;
-		case HID_DG_CONTACTID:
-			nd->id = value;
-			break;
-		case HID_DG_WIDTH:
-			nd->w = value;
-			break;
-		case HID_DG_HEIGHT:
-			nd->h = value;
+	switch (usage->hid) {
+	case 0xff000001:
+		/* Tag indicating the start of a multitouch group */
+		nd->reading_mt = 1;
+		nd->first_contact_touch = 0;
+		break;
+	case HID_DG_TIPSWITCH:
+		nd->tipswitch = value;
+		/* Prevent emission of touch until validated */
+		return 1;
+	case HID_DG_CONFIDENCE:
+		nd->confidence = value;
+		break;
+	case HID_GD_X:
+		nd->x = value;
+		/* Clear the contact footer */
+		nd->mt_foot_count = 0;
+		break;
+	case HID_GD_Y:
+		nd->y = value;
+		break;
+	case HID_DG_CONTACTID:
+		nd->id = value;
+		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->reading_mt) {
 			/*
-			 * when in single touch mode, this is the last
-			 * report received in a finger event. We want
-			 * to emit a normal (X, Y) position
+			 * TipSwitch indicates the presence of a
+			 * finger in single touch mode.
 			 */
-			if (!nd->reading_mt) {
-				/*
-				 * TipSwitch indicates the presence of a
-				 * finger in single touch mode.
-				 */
-				input_report_key(input, BTN_TOUCH,
-						 nd->tipswitch);
-				input_report_key(input, BTN_TOOL_DOUBLETAP,
-						 nd->tipswitch);
-				input_event(input, EV_ABS, ABS_X, nd->x);
-				input_event(input, EV_ABS, ABS_Y, nd->y);
-			}
+			input_report_key(input, BTN_TOUCH,
+					 nd->tipswitch);
+			input_report_key(input, BTN_TOOL_DOUBLETAP,
+					 nd->tipswitch);
+			input_event(input, EV_ABS, ABS_X, nd->x);
+			input_event(input, EV_ABS, ABS_Y, nd->y);
+		}
+		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
+		 */
+
+		/* Shouldn't get more than 4 footer packets, so skip */
+		if (nd->mt_foot_count >= 4)
 			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
-			 */
 
-			/* Shouldn't get more than 4 footer packets, so skip */
-			if (nd->mt_foot_count >= 4)
-				break;
+		nd->mt_footer[nd->mt_foot_count++] = value;
 
-			nd->mt_footer[nd->mt_foot_count++] = value;
+		/* if the footer isn't complete break */
+		if (nd->mt_foot_count != 4)
+			break;
 
-			/* if the footer isn't complete break */
-			if (nd->mt_foot_count != 4)
-				break;
+		/* Pen activity signal. */
+		if (nd->mt_footer[2]) {
+			/*
+			 * When the pen deactivates touch, we see a
+			 * bogus frame with ContactCount > 0.
+			 * We can
+			 * save a bit of work by ensuring act_state < 0
+			 * even if deactivation slack is turned off.
+			 */
+			nd->act_state = deactivate_slack - 1;
+			nd->confidence = 0;
+			break;
+		}
 
-			/* Pen activity signal. */
-			if (nd->mt_footer[2]) {
-				/*
-				 * When the pen deactivates touch, we see a
-				 * bogus frame with ContactCount > 0.
-				 * We can
-				 * save a bit of work by ensuring act_state < 0
-				 * even if deactivation slack is turned off.
-				 */
-				nd->act_state = deactivate_slack - 1;
+		/*
+		 * The first footer value indicates the presence of a
+		 * finger.
+		 */
+		if (nd->mt_footer[0]) {
+			/*
+			 * We do not want to process contacts under
+			 * the size threshold, but do not want to
+			 * ignore them for activation state
+			 */
+			if (nd->w < nd->min_width ||
+			    nd->h < nd->min_height)
 				nd->confidence = 0;
-				break;
-			}
+		} else
+			break;
 
+		if (nd->act_state > 0) {
 			/*
-			 * The first footer value indicates the presence of a
-			 * finger.
+			 * Contact meets the activation size threshold
 			 */
-			if (nd->mt_footer[0]) {
-				/*
-				 * We do not want to process contacts under
-				 * the size threshold, but do not want to
-				 * ignore them for activation state
-				 */
-				if (nd->w < nd->min_width ||
-				    nd->h < nd->min_height)
-					nd->confidence = 0;
-			} else
-				break;
-
-			if (nd->act_state > 0) {
-				/*
-				 * Contact meets the activation size threshold
-				 */
-				if (nd->w >= nd->activation_width &&
-				    nd->h >= nd->activation_height) {
-					if (nd->id)
-						/*
-						 * first contact, activate now
-						 */
-						nd->act_state = 0;
-					else {
-						/*
-						 * avoid corrupting this frame
-						 * but ensure next frame will
-						 * be active
-						 */
-						nd->act_state = 1;
-						break;
-					}
-				} else
+			if (nd->w >= nd->activation_width &&
+			    nd->h >= nd->activation_height) {
+				if (nd->id)
 					/*
-					 * Defer adjusting the activation state
-					 * until the end of the frame.
+					 * first contact, activate now
 					 */
+					nd->act_state = 0;
+				else {
+					/*
+					 * avoid corrupting this frame
+					 * but ensure next frame will
+					 * be active
+					 */
+					nd->act_state = 1;
 					break;
-			}
-
-			/* Discarding this contact */
-			if (!nd->confidence)
-				break;
-
-			/* emit a normal (X, Y) for the first point only */
-			if (nd->id == 0) {
+				}
+			} else
 				/*
-				 * TipSwitch is superfluous in multitouch
-				 * mode.  The footer events tell us
-				 * if there is a finger on the screen or
-				 * not.
+				 * Defer adjusting the activation state
+				 * until the end of the frame.
 				 */
-				nd->first_contact_touch = nd->confidence;
-				input_event(input, EV_ABS, ABS_X, nd->x);
-				input_event(input, EV_ABS, ABS_Y, nd->y);
-			}
+				break;
+		}
 
-			/* Emit MT events */
-			input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
-			input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
+		/* Discarding this contact */
+		if (!nd->confidence)
+			break;
 
+		/* emit a normal (X, Y) for the first point only */
+		if (nd->id == 0) {
 			/*
-			 * Translate from height and width to size
-			 * and orientation.
+			 * TipSwitch is superfluous in multitouch
+			 * mode.  The footer events tell us
+			 * if there is a finger on the screen or
+			 * not.
 			 */
-			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);
-			break;
+			nd->first_contact_touch = nd->confidence;
+			input_event(input, EV_ABS, ABS_X, nd->x);
+			input_event(input, EV_ABS, ABS_Y, nd->y);
+		}
 
-		case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
-			if (!nd->reading_mt) /* Just to be sure */
-				break;
+		/* Emit MT events */
+		input_event(input, EV_ABS, ABS_MT_POSITION_X, nd->x);
+		input_event(input, EV_ABS, ABS_MT_POSITION_Y, nd->y);
 
-			nd->reading_mt = 0;
+		/*
+		 * Translate from height and width to size
+		 * and orientation.
+		 */
+		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);
+		break;
 
+	case HID_DG_CONTACTCOUNT: /* End of a multitouch group */
+		if (!nd->reading_mt) /* Just to be sure */
+			break;
 
-			/*
-			 * Activation state machine logic:
-			 *
-			 * Fundamental states:
-			 *	state >  0: Inactive
-			 *	state <= 0: Active
-			 *	state <  -deactivate_slack:
-			 *		 Pen termination of touch
-			 *
-			 * Specific values of interest
-			 *	state == activate_slack
-			 *		 no valid input since the last reset
-			 *
-			 *	state == 0
-			 *		 general operational state
-			 *
-			 *	state == -deactivate_slack
-			 *		 read sufficient empty frames to accept
-			 *		 the end of input and reset
-			 */
+		nd->reading_mt = 0;
 
-			if (nd->act_state > 0) { /* Currently inactive */
-				if (value)
-					/*
-					 * Consider each live contact as
-					 * evidence of intentional activity.
-					 */
-					nd->act_state = (nd->act_state > value)
-							? nd->act_state - value
-							: 0;
-				else
-					/*
-					 * Empty frame before we hit the
-					 * activity threshold, reset.
-					 */
-					nd->act_state = nd->activate_slack;
 
+		/*
+		 * Activation state machine logic:
+		 *
+		 * Fundamental states:
+		 *	state >  0: Inactive
+		 *	state <= 0: Active
+		 *	state <  -deactivate_slack:
+		 *		 Pen termination of touch
+		 *
+		 * Specific values of interest
+		 *	state == activate_slack
+		 *		 no valid input since the last reset
+		 *
+		 *	state == 0
+		 *		 general operational state
+		 *
+		 *	state == -deactivate_slack
+		 *		 read sufficient empty frames to accept
+		 *		 the end of input and reset
+		 */
+
+		if (nd->act_state > 0) { /* Currently inactive */
+			if (value)
 				/*
-				 * Entered this block inactive and no
-				 * coordinates sent this frame, so hold off
-				 * on button state.
+				 * Consider each live contact as
+				 * evidence of intentional activity.
 				 */
-				break;
-			} else { /* Currently active */
-				if (value && nd->act_state >=
-					     nd->deactivate_slack)
-					/*
-					 * Live point: clear accumulated
-					 * deactivation count.
-					 */
-					nd->act_state = 0;
-				else if (nd->act_state <= nd->deactivate_slack)
-					/*
-					 * We've consumed the deactivation
-					 * slack, time to deactivate and reset.
-					 */
-					nd->act_state =
-						nd->activate_slack;
-				else { /* Move towards deactivation */
-					nd->act_state--;
-					break;
-				}
-			}
+				nd->act_state = (nd->act_state > value)
+						? nd->act_state - value
+						: 0;
+			else
+				/*
+				 * Empty frame before we hit the
+				 * activity threshold, reset.
+				 */
+				nd->act_state = nd->activate_slack;
 
-			if (nd->first_contact_touch && nd->act_state <= 0) {
+			/*
+			 * Entered this block inactive and no
+			 * coordinates sent this frame, so hold off
+			 * on button state.
+			 */
+			break;
+		} else { /* Currently active */
+			if (value && nd->act_state >=
+				     nd->deactivate_slack)
 				/*
-				 * Check to see if we're ready to start
-				 * emitting touch events.
-				 *
-				 * Note: activation slack will decrease over
-				 * the course of the frame, and it will be
-				 * inconsistent from the start to the end of
-				 * the frame.  However if the frame starts
-				 * with slack, first_contact_touch will still
-				 * be 0 and we will not get to this point.
+				 * Live point: clear accumulated
+				 * deactivation count.
 				 */
-				input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
-				input_report_key(input, BTN_TOUCH, 1);
-			} else {
-				input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
-				input_report_key(input, BTN_TOUCH, 0);
+				nd->act_state = 0;
+			else if (nd->act_state <= nd->deactivate_slack)
+				/*
+				 * We've consumed the deactivation
+				 * slack, time to deactivate and reset.
+				 */
+				nd->act_state =
+					nd->activate_slack;
+			else { /* Move towards deactivation */
+				nd->act_state--;
+				break;
 			}
-			break;
+		}
 
-		default:
-			/* fall-back to the generic hidinput handling */
-			return 0;
+		if (nd->first_contact_touch && nd->act_state <= 0) {
+			/*
+			 * Check to see if we're ready to start
+			 * emitting touch events.
+			 *
+			 * Note: activation slack will decrease over
+			 * the course of the frame, and it will be
+			 * inconsistent from the start to the end of
+			 * the frame.  However if the frame starts
+			 * with slack, first_contact_touch will still
+			 * be 0 and we will not get to this point.
+			 */
+			input_report_key(input, BTN_TOOL_DOUBLETAP, 1);
+			input_report_key(input, BTN_TOUCH, 1);
+		} else {
+			input_report_key(input, BTN_TOOL_DOUBLETAP, 0);
+			input_report_key(input, BTN_TOUCH, 0);
 		}
+		break;
+
+	default:
+		/* fall-back to the generic hidinput handling */
+		return 0;
 	}
 
+not_claimed_input:
+
 	/* 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);
@@ -826,7 +867,8 @@
 	struct hid_report *report;
 
 	if (id->driver_data)
-		hdev->quirks |= HID_QUIRK_MULTI_INPUT;
+		hdev->quirks |= HID_QUIRK_MULTI_INPUT
+				| HID_QUIRK_NO_INIT_REPORTS;
 
 	nd = kmalloc(sizeof(struct ntrig_data), GFP_KERNEL);
 	if (!nd) {
@@ -893,8 +935,19 @@
 
 	/* This is needed for devices with more recent firmware versions */
 	report = hdev->report_enum[HID_FEATURE_REPORT].report_id_hash[0x0a];
-	if (report)
-		usbhid_submit_report(hdev, report, USB_DIR_OUT);
+	if (report) {
+		/* Let the device settle to ensure the wakeup message gets
+		 * through */
+		usbhid_wait_io(hdev);
+		usbhid_submit_report(hdev, report, USB_DIR_IN);
+
+		/*
+		 * Sanity check: if the current mode is invalid reset it to
+		 * something reasonable.
+		 */
+		if (ntrig_get_mode(hdev) >= 4)
+			ntrig_set_mode(hdev, 3);
+	}
 
 	ntrig_report_version(hdev);
 
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-ortek.c linux-libre-2.6.39-gnu/drivers/hid/hid-ortek.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-ortek.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-ortek.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,9 +1,14 @@
 /*
- *  HID driver for Ortek WKB-2000 (wireless keyboard + mouse trackpad).
- *  Fixes LogicalMaximum error in USB report description, see
- *  http://bugzilla.kernel.org/show_bug.cgi?id=14787
+ *  HID driver for various devices which are apparently based on the same chipset
+ *  from certain vendor which produces chips that contain wrong LogicalMaximum
+ *  value in their HID report descriptor. Currently supported devices are:
+ *
+ *    Ortek PKB-1700
+ *    Ortek WKB-2000
+ *    Skycable wireless presenter
  *
  *  Copyright (c) 2010 Johnathon Harris <jmharris@gmail.com>
+ *  Copyright (c) 2011 Jiri Kosina
  */
 
 /*
@@ -23,14 +28,19 @@
 		unsigned int *rsize)
 {
 	if (*rsize >= 56 && rdesc[54] == 0x25 && rdesc[55] == 0x01) {
-		hid_info(hdev, "Fixing up Ortek WKB-2000 report descriptor\n");
+		hid_info(hdev, "Fixing up logical minimum in report descriptor (Ortek)\n");
 		rdesc[55] = 0x92;
+	} else if (*rsize >= 54 && rdesc[52] == 0x25 && rdesc[53] == 0x01) {
+		hid_info(hdev, "Fixing up logical minimum in report descriptor (Skycable)\n");
+		rdesc[53] = 0x65;
 	}
 	return rdesc;
 }
 
 static const struct hid_device_id ortek_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_PKB1700) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
+	{ HID_USB_DEVICE(USB_VENDOR_ID_SKYCABLE, USB_DEVICE_ID_SKYCABLE_WIRELESS_PRESENTER) },
 	{ }
 };
 MODULE_DEVICE_TABLE(hid, ortek_devices);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-picolcd.c linux-libre-2.6.39-gnu/drivers/hid/hid-picolcd.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-picolcd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-picolcd.c	2011-05-19 00:06:34.000000000 -0400
@@ -944,6 +944,7 @@
 	}
 
 	memset(&props, 0, sizeof(props));
+	props.type = BACKLIGHT_RAW;
 	props.max_brightness = 0xff;
 	bdev = backlight_device_register(dev_name(dev), dev, data,
 			&picolcd_blops, &props);
@@ -1805,13 +1806,13 @@
 /*
  * Notes:
  * - concurrent writing is prevented by mutex and all writes must be
- *   n*64 bytes and 64-byte aligned, each write being preceeded by an
+ *   n*64 bytes and 64-byte aligned, each write being preceded by an
  *   ERASE which erases a 64byte block.
  *   If less than requested was written or an error is returned for an
  *   otherwise correct write request the next 64-byte block which should
  *   have been written is in undefined state (mostly: original, erased,
  *   (half-)written with write error)
- * - reading can happend without special restriction
+ * - reading can happen without special restriction
  */
 static const struct file_operations picolcd_debug_flash_fops = {
 	.owner    = THIS_MODULE,
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hidraw.c linux-libre-2.6.39-gnu/drivers/hid/hidraw.c
--- linux-libre-2.6.38-gnu/drivers/hid/hidraw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hidraw.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
 			ret = -EFAULT;
 			goto out;
 		}
-		ret += len;
+		ret = len;
 
 		kfree(list->buffer[list->tail].value);
 		list->tail = (list->tail + 1) & (HIDRAW_BUFFER_SIZE - 1);
@@ -102,15 +102,14 @@
 }
 
 /* the first byte is expected to be a report number */
-static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+/* This function is to be called with the minors_lock mutex held */
+static ssize_t hidraw_send_report(struct file *file, const char __user *buffer, size_t count, unsigned char report_type)
 {
 	unsigned int minor = iminor(file->f_path.dentry->d_inode);
 	struct hid_device *dev;
 	__u8 *buf;
 	int ret = 0;
 
-	mutex_lock(&minors_lock);
-
 	if (!hidraw_table[minor]) {
 		ret = -ENODEV;
 		goto out;
@@ -148,14 +147,92 @@
 		goto out_free;
 	}
 
-	ret = dev->hid_output_raw_report(dev, buf, count, HID_OUTPUT_REPORT);
+	ret = dev->hid_output_raw_report(dev, buf, count, report_type);
 out_free:
 	kfree(buf);
 out:
+	return ret;
+}
+
+/* the first byte is expected to be a report number */
+static ssize_t hidraw_write(struct file *file, const char __user *buffer, size_t count, loff_t *ppos)
+{
+	ssize_t ret;
+	mutex_lock(&minors_lock);
+	ret = hidraw_send_report(file, buffer, count, HID_OUTPUT_REPORT);
 	mutex_unlock(&minors_lock);
 	return ret;
 }
 
+
+/* This function performs a Get_Report transfer over the control endpoint
+   per section 7.2.1 of the HID specification, version 1.1.  The first byte
+   of buffer is the report number to request, or 0x0 if the defice does not
+   use numbered reports. The report_type parameter can be HID_FEATURE_REPORT
+   or HID_INPUT_REPORT.  This function is to be called with the minors_lock
+   mutex held.  */
+static ssize_t hidraw_get_report(struct file *file, char __user *buffer, size_t count, unsigned char report_type)
+{
+	unsigned int minor = iminor(file->f_path.dentry->d_inode);
+	struct hid_device *dev;
+	__u8 *buf;
+	int ret = 0, len;
+	unsigned char report_number;
+
+	dev = hidraw_table[minor]->hid;
+
+	if (!dev->hid_get_raw_report) {
+		ret = -ENODEV;
+		goto out;
+	}
+
+	if (count > HID_MAX_BUFFER_SIZE) {
+		printk(KERN_WARNING "hidraw: pid %d passed too large report\n",
+				task_pid_nr(current));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (count < 2) {
+		printk(KERN_WARNING "hidraw: pid %d passed too short report\n",
+				task_pid_nr(current));
+		ret = -EINVAL;
+		goto out;
+	}
+
+	buf = kmalloc(count * sizeof(__u8), GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Read the first byte from the user. This is the report number,
+	   which is passed to dev->hid_get_raw_report(). */
+	if (copy_from_user(&report_number, buffer, 1)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	ret = dev->hid_get_raw_report(dev, report_number, buf, count, report_type);
+
+	if (ret < 0)
+		goto out_free;
+
+	len = (ret < count) ? ret : count;
+
+	if (copy_to_user(buffer, buf, len)) {
+		ret = -EFAULT;
+		goto out_free;
+	}
+
+	ret = len;
+
+out_free:
+	kfree(buf);
+out:
+	return ret;
+}
+
 static unsigned int hidraw_poll(struct file *file, poll_table *wait)
 {
 	struct hidraw_list *list = file->private_data;
@@ -295,7 +372,24 @@
 		default:
 			{
 				struct hid_device *hid = dev->hid;
-				if (_IOC_TYPE(cmd) != 'H' || _IOC_DIR(cmd) != _IOC_READ) {
+				if (_IOC_TYPE(cmd) != 'H') {
+					ret = -EINVAL;
+					break;
+				}
+
+				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCSFEATURE(0))) {
+					int len = _IOC_SIZE(cmd);
+					ret = hidraw_send_report(file, user_arg, len, HID_FEATURE_REPORT);
+					break;
+				}
+				if (_IOC_NR(cmd) == _IOC_NR(HIDIOCGFEATURE(0))) {
+					int len = _IOC_SIZE(cmd);
+					ret = hidraw_get_report(file, user_arg, len, HID_FEATURE_REPORT);
+					break;
+				}
+
+				/* Begin Read-only ioctls. */
+				if (_IOC_DIR(cmd) != _IOC_READ) {
 					ret = -EINVAL;
 					break;
 				}
@@ -327,7 +421,7 @@
 						-EFAULT : len;
 					break;
 				}
-		}
+			}
 
 		ret = -ENOTTY;
 	}
@@ -428,12 +522,12 @@
 
 	hidraw->exist = 0;
 
+	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
+
 	mutex_lock(&minors_lock);
 	hidraw_table[hidraw->minor] = NULL;
 	mutex_unlock(&minors_lock);
 
-	device_destroy(hidraw_class, MKDEV(hidraw_major, hidraw->minor));
-
 	if (hidraw->open) {
 		hid_hw_close(hid);
 		wake_up_interruptible(&hidraw->wait);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-arvo.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-arvo.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-arvo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-arvo.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,450 @@
+/*
+ * Roccat Arvo driver for Linux
+ *
+ * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.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.
+ */
+
+/*
+ * Roccat Arvo is a gamer keyboard with 5 macro keys that can be configured in
+ * 5 profiles.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-arvo.h"
+
+static struct class *arvo_class;
+
+static ssize_t arvo_sysfs_show_mode_key(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_mode_key temp_buf;
+	int retval;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+			&temp_buf, sizeof(struct arvo_mode_key));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.state);
+}
+
+static ssize_t arvo_sysfs_set_mode_key(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_mode_key temp_buf;
+	unsigned long state;
+	int retval;
+
+	retval = strict_strtoul(buf, 10, &state);
+	if (retval)
+		return retval;
+
+	temp_buf.command = ARVO_COMMAND_MODE_KEY;
+	temp_buf.state = state;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_MODE_KEY,
+			&temp_buf, sizeof(struct arvo_mode_key));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+static ssize_t arvo_sysfs_show_key_mask(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_key_mask temp_buf;
+	int retval;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+			&temp_buf, sizeof(struct arvo_key_mask));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", temp_buf.key_mask);
+}
+
+static ssize_t arvo_sysfs_set_key_mask(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_key_mask temp_buf;
+	unsigned long key_mask;
+	int retval;
+
+	retval = strict_strtoul(buf, 10, &key_mask);
+	if (retval)
+		return retval;
+
+	temp_buf.command = ARVO_COMMAND_KEY_MASK;
+	temp_buf.key_mask = key_mask;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_KEY_MASK,
+			&temp_buf, sizeof(struct arvo_key_mask));
+	mutex_unlock(&arvo->arvo_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+/* retval is 1-5 on success, < 0 on error */
+static int arvo_get_actual_profile(struct usb_device *usb_dev)
+{
+	struct arvo_actual_profile temp_buf;
+	int retval;
+
+	retval = roccat_common_receive(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+			&temp_buf, sizeof(struct arvo_actual_profile));
+
+	if (retval)
+		return retval;
+
+	return temp_buf.actual_profile;
+}
+
+static ssize_t arvo_sysfs_show_actual_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", arvo->actual_profile);
+}
+
+static ssize_t arvo_sysfs_set_actual_profile(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct arvo_device *arvo =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	struct usb_device *usb_dev =
+			interface_to_usbdev(to_usb_interface(dev->parent->parent));
+	struct arvo_actual_profile temp_buf;
+	unsigned long profile;
+	int retval;
+
+	retval = strict_strtoul(buf, 10, &profile);
+	if (retval)
+		return retval;
+
+	temp_buf.command = ARVO_COMMAND_ACTUAL_PROFILE;
+	temp_buf.actual_profile = profile;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, ARVO_USB_COMMAND_ACTUAL_PROFILE,
+			&temp_buf, sizeof(struct arvo_actual_profile));
+	if (!retval) {
+		arvo->actual_profile = profile;
+		retval = size;
+	}
+	mutex_unlock(&arvo->arvo_lock);
+	return retval;
+}
+
+static ssize_t arvo_sysfs_write(struct file *fp,
+		struct kobject *kobj, void const *buf,
+		loff_t off, size_t count, size_t real_size, uint command)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_send(usb_dev, command, buf, real_size);
+	mutex_unlock(&arvo->arvo_lock);
+
+	return (retval ? retval : real_size);
+}
+
+static ssize_t arvo_sysfs_read(struct file *fp,
+		struct kobject *kobj, void *buf, loff_t off,
+		size_t count, size_t real_size, uint command)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct arvo_device *arvo = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval;
+
+	if (off >= real_size)
+		return 0;
+
+	if (off != 0 || count != real_size)
+		return -EINVAL;
+
+	mutex_lock(&arvo->arvo_lock);
+	retval = roccat_common_receive(usb_dev, command, buf, real_size);
+	mutex_unlock(&arvo->arvo_lock);
+
+	return (retval ? retval : real_size);
+}
+
+static ssize_t arvo_sysfs_write_button(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return arvo_sysfs_write(fp, kobj, buf, off, count,
+			sizeof(struct arvo_button), ARVO_USB_COMMAND_BUTTON);
+}
+
+static ssize_t arvo_sysfs_read_info(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	return arvo_sysfs_read(fp, kobj, buf, off, count,
+			sizeof(struct arvo_info), ARVO_USB_COMMAND_INFO);
+}
+
+
+static struct device_attribute arvo_attributes[] = {
+	__ATTR(mode_key, 0660,
+			arvo_sysfs_show_mode_key, arvo_sysfs_set_mode_key),
+	__ATTR(key_mask, 0660,
+			arvo_sysfs_show_key_mask, arvo_sysfs_set_key_mask),
+	__ATTR(actual_profile, 0660,
+			arvo_sysfs_show_actual_profile,
+			arvo_sysfs_set_actual_profile),
+	__ATTR_NULL
+};
+
+static struct bin_attribute arvo_bin_attributes[] = {
+	{
+		.attr = { .name = "button", .mode = 0220 },
+		.size = sizeof(struct arvo_button),
+		.write = arvo_sysfs_write_button
+	},
+	{
+		.attr = { .name = "info", .mode = 0440 },
+		.size = sizeof(struct arvo_info),
+		.read = arvo_sysfs_read_info
+	},
+	__ATTR_NULL
+};
+
+static int arvo_init_arvo_device_struct(struct usb_device *usb_dev,
+		struct arvo_device *arvo)
+{
+	int retval;
+
+	mutex_init(&arvo->arvo_lock);
+
+	retval = arvo_get_actual_profile(usb_dev);
+	if (retval < 0)
+		return retval;
+	arvo->actual_profile = retval;
+
+	return 0;
+}
+
+static int arvo_init_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	struct arvo_device *arvo;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_KEYBOARD) {
+		hid_set_drvdata(hdev, NULL);
+		return 0;
+	}
+
+	arvo = kzalloc(sizeof(*arvo), GFP_KERNEL);
+	if (!arvo) {
+		hid_err(hdev, "can't alloc device descriptor\n");
+		return -ENOMEM;
+	}
+	hid_set_drvdata(hdev, arvo);
+
+	retval = arvo_init_arvo_device_struct(usb_dev, arvo);
+	if (retval) {
+		hid_err(hdev, "couldn't init struct arvo_device\n");
+		goto exit_free;
+	}
+
+	retval = roccat_connect(arvo_class, hdev,
+			sizeof(struct arvo_roccat_report));
+	if (retval < 0) {
+		hid_err(hdev, "couldn't init char dev\n");
+	} else {
+		arvo->chrdev_minor = retval;
+		arvo->roccat_claimed = 1;
+	}
+
+	return 0;
+exit_free:
+	kfree(arvo);
+	return retval;
+}
+
+static void arvo_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct arvo_device *arvo;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_KEYBOARD)
+		return;
+
+	arvo = hid_get_drvdata(hdev);
+	if (arvo->roccat_claimed)
+		roccat_disconnect(arvo->chrdev_minor);
+	kfree(arvo);
+}
+
+static int arvo_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	int retval;
+
+	retval = hid_parse(hdev);
+	if (retval) {
+		hid_err(hdev, "parse failed\n");
+		goto exit;
+	}
+
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		hid_err(hdev, "hw start failed\n");
+		goto exit;
+	}
+
+	retval = arvo_init_specials(hdev);
+	if (retval) {
+		hid_err(hdev, "couldn't install keyboard\n");
+		goto exit_stop;
+	}
+
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void arvo_remove(struct hid_device *hdev)
+{
+	arvo_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static void arvo_report_to_chrdev(struct arvo_device const *arvo,
+		u8 const *data)
+{
+	struct arvo_special_report const *special_report;
+	struct arvo_roccat_report roccat_report;
+
+	special_report = (struct arvo_special_report const *)data;
+
+	roccat_report.profile = arvo->actual_profile;
+	roccat_report.button = special_report->event &
+			ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON;
+	if ((special_report->event & ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION) ==
+			ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS)
+		roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_PRESS;
+	else
+		roccat_report.action = ARVO_ROCCAT_REPORT_ACTION_RELEASE;
+
+	roccat_report_event(arvo->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+}
+
+static int arvo_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	struct arvo_device *arvo = hid_get_drvdata(hdev);
+
+	if (size != 3)
+		return 0;
+
+	if (arvo->roccat_claimed)
+		arvo_report_to_chrdev(arvo, data);
+
+	return 0;
+}
+
+static const struct hid_device_id arvo_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, arvo_devices);
+
+static struct hid_driver arvo_driver = {
+	.name = "arvo",
+	.id_table = arvo_devices,
+	.probe = arvo_probe,
+	.remove = arvo_remove,
+	.raw_event = arvo_raw_event
+};
+
+static int __init arvo_init(void)
+{
+	int retval;
+
+	arvo_class = class_create(THIS_MODULE, "arvo");
+	if (IS_ERR(arvo_class))
+		return PTR_ERR(arvo_class);
+	arvo_class->dev_attrs = arvo_attributes;
+	arvo_class->dev_bin_attrs = arvo_bin_attributes;
+
+	retval = hid_register_driver(&arvo_driver);
+	if (retval)
+		class_destroy(arvo_class);
+	return retval;
+}
+
+static void __exit arvo_exit(void)
+{
+	hid_unregister_driver(&arvo_driver);
+	class_destroy(arvo_class);
+}
+
+module_init(arvo_init);
+module_exit(arvo_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Arvo driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-arvo.h linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-arvo.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-arvo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-arvo.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+#ifndef __HID_ROCCAT_ARVO_H
+#define __HID_ROCCAT_ARVO_H
+
+/*
+ * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.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/types.h>
+
+struct arvo_mode_key { /* 2 bytes */
+	uint8_t command; /* ARVO_COMMAND_MODE_KEY */
+	uint8_t state;
+} __packed;
+
+struct arvo_button {
+	uint8_t unknown[24];
+} __packed;
+
+struct arvo_info {
+	uint8_t unknown[8];
+} __packed;
+
+struct arvo_key_mask { /* 2 bytes */
+	uint8_t command; /* ARVO_COMMAND_KEY_MASK */
+	uint8_t key_mask;
+} __packed;
+
+/* selected profile is persistent */
+struct arvo_actual_profile { /* 2 bytes */
+	uint8_t command; /* ARVO_COMMAND_ACTUAL_PROFILE */
+	uint8_t actual_profile;
+} __packed;
+
+enum arvo_commands {
+	ARVO_COMMAND_MODE_KEY = 0x3,
+	ARVO_COMMAND_BUTTON = 0x4,
+	ARVO_COMMAND_INFO = 0x5,
+	ARVO_COMMAND_KEY_MASK = 0x6,
+	ARVO_COMMAND_ACTUAL_PROFILE = 0x7,
+};
+
+enum arvo_usb_commands {
+	ARVO_USB_COMMAND_MODE_KEY = 0x303,
+	/*
+	 * read/write
+	 * Read uses both index bytes as profile/key indexes
+	 * Write has index 0, profile/key is determined by payload
+	 */
+	ARVO_USB_COMMAND_BUTTON = 0x304,
+	ARVO_USB_COMMAND_INFO = 0x305,
+	ARVO_USB_COMMAND_KEY_MASK = 0x306,
+	ARVO_USB_COMMAND_ACTUAL_PROFILE = 0x307,
+};
+
+struct arvo_special_report {
+	uint8_t unknown1; /* always 0x01 */
+	uint8_t event;
+	uint8_t unknown2; /* always 0x70 */
+} __packed;
+
+enum arvo_special_report_events {
+	ARVO_SPECIAL_REPORT_EVENT_ACTION_PRESS = 0x10,
+	ARVO_SPECIAL_REPORT_EVENT_ACTION_RELEASE = 0x0,
+};
+
+enum arvo_special_report_event_masks {
+	ARVO_SPECIAL_REPORT_EVENT_MASK_ACTION = 0xf0,
+	ARVO_SPECIAL_REPORT_EVENT_MASK_BUTTON = 0x0f,
+};
+
+struct arvo_roccat_report {
+	uint8_t profile;
+	uint8_t button;
+	uint8_t action;
+} __packed;
+
+enum arvo_roccat_report_action {
+	ARVO_ROCCAT_REPORT_ACTION_RELEASE = 0,
+	ARVO_ROCCAT_REPORT_ACTION_PRESS = 1,
+};
+
+struct arvo_device {
+	int roccat_claimed;
+	int chrdev_minor;
+
+	struct mutex arvo_lock;
+
+	int actual_profile;
+};
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,8 +26,7 @@
 #include <linux/cdev.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
-
-#include "hid-roccat.h"
+#include <linux/hid-roccat.h>
 
 #define ROCCAT_FIRST_MINOR 0
 #define ROCCAT_MAX_DEVICES 8
@@ -37,11 +36,11 @@
 
 struct roccat_report {
 	uint8_t *value;
-	int len;
 };
 
 struct roccat_device {
 	unsigned int minor;
+	int report_size;
 	int open;
 	int exist;
 	wait_queue_head_t wait;
@@ -123,7 +122,7 @@
 	 * If report is larger than requested amount of data, rest of report
 	 * is lost!
 	 */
-	len = report->len > count ? count : report->len;
+	len = device->report_size > count ? count : device->report_size;
 
 	if (copy_to_user(buffer, report->value, len)) {
 		retval = -EFAULT;
@@ -248,26 +247,25 @@
  *
  * This is called from interrupt handler.
  */
-int roccat_report_event(int minor, u8 const *data, int len)
+int roccat_report_event(int minor, u8 const *data)
 {
 	struct roccat_device *device;
 	struct roccat_reader *reader;
 	struct roccat_report *report;
 	uint8_t *new_value;
 
-	new_value = kmemdup(data, len, GFP_ATOMIC);
+	device = devices[minor];
+
+	new_value = kmemdup(data, device->report_size, GFP_ATOMIC);
 	if (!new_value)
 		return -ENOMEM;
 
-	device = devices[minor];
-
 	report = &device->cbuf[device->cbuf_end];
 
 	/* passing NULL is safe */
 	kfree(report->value);
 
 	report->value = new_value;
-	report->len = len;
 	device->cbuf_end = (device->cbuf_end + 1) % ROCCAT_CBUF_SIZE;
 
 	list_for_each_entry(reader, &device->readers, node) {
@@ -295,7 +293,7 @@
  * Return value is minor device number in Range [0, ROCCAT_MAX_DEVICES] on
  * success, a negative error code on failure.
  */
-int roccat_connect(struct class *klass, struct hid_device *hid)
+int roccat_connect(struct class *klass, struct hid_device *hid, int report_size)
 {
 	unsigned int minor;
 	struct roccat_device *device;
@@ -343,6 +341,7 @@
 	device->hid = hid;
 	device->exist = 1;
 	device->cbuf_end = 0;
+	device->report_size = report_size;
 
 	return minor;
 }
@@ -357,13 +356,16 @@
 
 	mutex_lock(&devices_lock);
 	device = devices[minor];
-	devices[minor] = NULL;
 	mutex_unlock(&devices_lock);
 
 	device->exist = 0; /* TODO exist maybe not needed */
 
 	device_destroy(device->dev->class, MKDEV(roccat_major, minor));
 
+	mutex_lock(&devices_lock);
+	devices[minor] = NULL;
+	mutex_unlock(&devices_lock);
+	
 	if (device->open) {
 		hid_hw_close(device->hid);
 		wake_up_interruptible(&device->wait);
@@ -373,6 +375,34 @@
 }
 EXPORT_SYMBOL_GPL(roccat_disconnect);
 
+static long roccat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+{
+	struct inode *inode = file->f_path.dentry->d_inode;
+	struct roccat_device *device;
+	unsigned int minor = iminor(inode);
+	long retval = 0;
+
+	mutex_lock(&devices_lock);
+
+	device = devices[minor];
+	if (!device) {
+		retval = -ENODEV;
+		goto out;
+	}
+
+	switch (cmd) {
+	case ROCCATIOCGREPSIZE:
+		if (put_user(device->report_size, (int __user *)arg))
+			retval = -EFAULT;
+		break;
+	default:
+		retval = -ENOTTY;
+	}
+out:
+	mutex_unlock(&devices_lock);
+	return retval;
+}
+
 static const struct file_operations roccat_ops = {
 	.owner = THIS_MODULE,
 	.read = roccat_read,
@@ -380,6 +410,7 @@
 	.open = roccat_open,
 	.release = roccat_release,
 	.llseek = noop_llseek,
+	.unlocked_ioctl = roccat_ioctl,
 };
 
 static int __init roccat_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-common.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-common.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Roccat common functions for device specific drivers
+ *
+ * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.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/slab.h>
+#include "hid-roccat-common.h"
+
+int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+		void *data, uint size)
+{
+	char *buf;
+	int len;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
+			USB_REQ_CLEAR_FEATURE,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	memcpy(data, buf, size);
+	kfree(buf);
+	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+EXPORT_SYMBOL_GPL(roccat_common_receive);
+
+int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+		void const *data, uint size)
+{
+	char *buf;
+	int len;
+
+	buf = kmalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	memcpy(buf, data, size);
+
+	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
+			USB_REQ_SET_CONFIGURATION,
+			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
+			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+
+	kfree(buf);
+	return ((len < 0) ? len : ((len != size) ? -EIO : 0));
+}
+EXPORT_SYMBOL_GPL(roccat_common_send);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat common driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-common.h linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-common.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-common.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+#ifndef __HID_ROCCAT_COMMON_H
+#define __HID_ROCCAT_COMMON_H
+
+/*
+ * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.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/usb.h>
+#include <linux/types.h>
+
+int roccat_common_receive(struct usb_device *usb_dev, uint usb_command,
+		void *data, uint size);
+int roccat_common_send(struct usb_device *usb_dev, uint usb_command,
+		void const *data, uint size);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat.h linux-libre-2.6.39-gnu/drivers/hid/hid-roccat.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-#ifndef __HID_ROCCAT_H
-#define __HID_ROCCAT_H
-
-/*
- * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.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/hid.h>
-#include <linux/types.h>
-
-#if defined(CONFIG_HID_ROCCAT) || defined(CONFIG_HID_ROCCAT_MODULE)
-int roccat_connect(struct class *klass, struct hid_device *hid);
-void roccat_disconnect(int minor);
-int roccat_report_event(int minor, u8 const *data, int len);
-#else
-static inline int roccat_connect(struct class *klass,
-		struct hid_device *hid) { return -1; }
-static inline void roccat_disconnect(int minor) {}
-static inline int roccat_report_event(int minor, u8 const *data, int len)
-{
-	return 0;
-}
-#endif
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kone.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kone.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kone.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kone.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,11 +28,11 @@
 #include <linux/device.h>
 #include <linux/input.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/hid-roccat.h>
 #include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
 #include "hid-roccat-kone.h"
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -58,12 +58,8 @@
  */
 static int kone_check_write(struct usb_device *usb_dev)
 {
-	int len;
-	unsigned char *data;
-
-	data = kmalloc(1, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	int retval;
+	uint8_t data;
 
 	do {
 		/*
@@ -72,56 +68,36 @@
 		 */
 		msleep(80);
 
-		len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-				USB_REQ_CLEAR_FEATURE,
-				USB_TYPE_CLASS | USB_RECIP_INTERFACE |
-				USB_DIR_IN,
-				kone_command_confirm_write, 0, data, 1,
-				USB_CTRL_SET_TIMEOUT);
-
-		if (len != 1) {
-			kfree(data);
-			return -EIO;
-		}
+		retval = roccat_common_receive(usb_dev,
+				kone_command_confirm_write, &data, 1);
+		if (retval)
+			return retval;
 
 		/*
 		 * value of 3 seems to mean something like
 		 * "not finished yet, but it looks good"
 		 * So check again after a moment.
 		 */
-	} while (*data == 3);
+	} while (data == 3);
 
-	if (*data == 1) { /* everything alright */
-		kfree(data);
+	if (data == 1) /* everything alright */
 		return 0;
-	} else { /* unknown answer */
-		hid_err(usb_dev, "got retval %d when checking write\n", *data);
-		kfree(data);
-		return -EIO;
-	}
+
+	/* unknown answer */
+	hid_err(usb_dev, "got retval %d when checking write\n", data);
+	return -EIO;
 }
 
 /*
  * Reads settings from mouse and stores it in @buf
- * @buf has to be alloced with GFP_KERNEL
  * On success returns 0
  * On failure returns errno
  */
 static int kone_get_settings(struct usb_device *usb_dev,
 		struct kone_settings *buf)
 {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			kone_command_settings, 0, buf,
-			sizeof(struct kone_settings), USB_CTRL_SET_TIMEOUT);
-
-	if (len != sizeof(struct kone_settings))
-		return -EIO;
-
-	return 0;
+	return roccat_common_receive(usb_dev, kone_command_settings, buf,
+			sizeof(struct kone_settings));
 }
 
 /*
@@ -132,22 +108,12 @@
 static int kone_set_settings(struct usb_device *usb_dev,
 		struct kone_settings const *settings)
 {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			kone_command_settings, 0, (char *)settings,
-			sizeof(struct kone_settings),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (len != sizeof(struct kone_settings))
-		return -EIO;
-
-	if (kone_check_write(usb_dev))
-		return -EIO;
-
-	return 0;
+	int retval;
+	retval = roccat_common_send(usb_dev, kone_command_settings,
+			settings, sizeof(struct kone_settings));
+	if (retval)
+		return retval;
+	return kone_check_write(usb_dev);
 }
 
 /*
@@ -193,7 +159,7 @@
 	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
 			USB_REQ_SET_CONFIGURATION,
 			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			kone_command_profile, number, (char *)profile,
+			kone_command_profile, number, (void *)profile,
 			sizeof(struct kone_profile),
 			USB_CTRL_SET_TIMEOUT);
 
@@ -213,24 +179,15 @@
  */
 static int kone_get_weight(struct usb_device *usb_dev, int *result)
 {
-	int len;
-	uint8_t *data;
+	int retval;
+	uint8_t data;
 
-	data = kmalloc(1, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	retval = roccat_common_receive(usb_dev, kone_command_weight, &data, 1);
 
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			kone_command_weight, 0, data, 1, USB_CTRL_SET_TIMEOUT);
+	if (retval)
+		return retval;
 
-	if (len != 1) {
-		kfree(data);
-		return -EIO;
-	}
-	*result = (int)*data;
-	kfree(data);
+	*result = (int)data;
 	return 0;
 }
 
@@ -241,25 +198,15 @@
  */
 static int kone_get_firmware_version(struct usb_device *usb_dev, int *result)
 {
-	int len;
-	unsigned char *data;
-
-	data = kmalloc(2, GFP_KERNEL);
-	if (!data)
-		return -ENOMEM;
+	int retval;
+	uint16_t data;
 
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			kone_command_firmware_version, 0, data, 2,
-			USB_CTRL_SET_TIMEOUT);
+	retval = roccat_common_receive(usb_dev, kone_command_firmware_version,
+			&data, 2);
+	if (retval)
+		return retval;
 
-	if (len != 2) {
-		kfree(data);
-		return -EIO;
-	}
-	*result = le16_to_cpu(*data);
-	kfree(data);
+	*result = le16_to_cpu(data);
 	return 0;
 }
 
@@ -435,23 +382,9 @@
 
 static int kone_tcu_command(struct usb_device *usb_dev, int number)
 {
-	int len;
-	char *value;
-
-	value = kmalloc(1, GFP_KERNEL);
-	if (!value)
-		return -ENOMEM;
-
-	*value = number;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			kone_command_calibrate, 0, value, 1,
-			USB_CTRL_SET_TIMEOUT);
-
-	kfree(value);
-	return ((len != 1) ? -EIO : 0);
+	unsigned char value;
+	value = number;
+	return roccat_common_send(usb_dev, kone_command_calibrate, &value, 1);
 }
 
 /*
@@ -727,7 +660,8 @@
 			goto exit_free;
 		}
 
-		retval = roccat_connect(kone_class, hdev);
+		retval = roccat_connect(kone_class, hdev,
+				sizeof(struct kone_roccat_report));
 		if (retval < 0) {
 			hid_err(hdev, "couldn't init char dev\n");
 			/* be tolerant about not getting chrdev */
@@ -827,8 +761,7 @@
 		roccat_report.value = event->value;
 		roccat_report.key = 0;
 		roccat_report_event(kone->chrdev_minor,
-				(uint8_t *)&roccat_report,
-				sizeof(struct kone_roccat_report));
+				(uint8_t *)&roccat_report);
 		break;
 	case kone_mouse_event_call_overlong_macro:
 		if (event->value == kone_keystroke_action_press) {
@@ -836,8 +769,7 @@
 			roccat_report.value = kone->actual_profile;
 			roccat_report.key = event->macro_key;
 			roccat_report_event(kone->chrdev_minor,
-					(uint8_t *)&roccat_report,
-					sizeof(struct kone_roccat_report));
+					(uint8_t *)&roccat_report);
 		}
 		break;
 	}
@@ -912,8 +844,8 @@
 
 static void __exit kone_exit(void)
 {
-	class_destroy(kone_class);
 	hid_unregister_driver(&kone_driver);
+	class_destroy(kone_class);
 }
 
 module_init(kone_init);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kone.h linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kone.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kone.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kone.h	2011-05-19 00:06:34.000000000 -0400
@@ -166,7 +166,7 @@
 	/* osd events are thought to be display on screen */
 	kone_mouse_event_osd_dpi = 0xa0,
 	kone_mouse_event_osd_profile = 0xb0,
-	/* TODO clarify meaning and occurence of kone_mouse_event_calibration */
+	/* TODO clarify meaning and occurrence of kone_mouse_event_calibration */
 	kone_mouse_event_calibration = 0xc0,
 	kone_mouse_event_call_overlong_macro = 0xe0,
 	/* switch events notify if user changed values with mousebutton click */
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-koneplus.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-koneplus.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-koneplus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-koneplus.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,11 +19,11 @@
 #include <linux/device.h>
 #include <linux/input.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/hid-roccat.h>
 #include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
 #include "hid-roccat-koneplus.h"
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -39,110 +39,63 @@
 static int koneplus_send_control(struct usb_device *usb_dev, uint value,
 		enum koneplus_control_requests request)
 {
-	int len;
-	struct koneplus_control *control;
+	struct koneplus_control control;
 
 	if ((request == KONEPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
 			request == KONEPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
 			value > 4)
 		return -EINVAL;
 
-	control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
-	if (!control)
-		return -ENOMEM;
-
-	control->command = KONEPLUS_COMMAND_CONTROL;
-	control->value = value;
-	control->request = request;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			KONEPLUS_USB_COMMAND_CONTROL, 0, control,
-			sizeof(struct koneplus_control),
-			USB_CTRL_SET_TIMEOUT);
-
-	kfree(control);
-
-	if (len != sizeof(struct koneplus_control))
-		return len;
-
-	return 0;
-}
-
-static int koneplus_receive(struct usb_device *usb_dev, uint usb_command,
-		void *buf, uint size) {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			usb_command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
+	control.command = KONEPLUS_COMMAND_CONTROL;
+	control.value = value;
+	control.request = request;
 
-	return (len != size) ? -EIO : 0;
+	return roccat_common_send(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+			&control, sizeof(struct koneplus_control));
 }
 
 static int koneplus_receive_control_status(struct usb_device *usb_dev)
 {
 	int retval;
-	struct koneplus_control *control;
-
-	control = kmalloc(sizeof(struct koneplus_control), GFP_KERNEL);
-	if (!control)
-		return -ENOMEM;
+	struct koneplus_control control;
 
 	do {
-		retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
-				control, sizeof(struct koneplus_control));
+		retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_CONTROL,
+				&control, sizeof(struct koneplus_control));
 
 		/* check if we get a completely wrong answer */
 		if (retval)
-			goto out;
+			return retval;
 
-		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OK) {
-			retval = 0;
-			goto out;
-		}
+		if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OK)
+			return 0;
 
 		/* indicates that hardware needs some more time to complete action */
-		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
+		if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_WAIT) {
 			msleep(500); /* windows driver uses 1000 */
 			continue;
 		}
 
 		/* seems to be critical - replug necessary */
-		if (control->value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD) {
-			retval = -EINVAL;
-			goto out;
-		}
-
-		dev_err(&usb_dev->dev, "koneplus_receive_control_status: "
-				"unknown response value 0x%x\n", control->value);
-		retval = -EINVAL;
-		goto out;
+		if (control.value == KONEPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
+			return -EINVAL;
 
+		hid_err(usb_dev, "koneplus_receive_control_status: "
+				"unknown response value 0x%x\n", control.value);
+		return -EINVAL;
 	} while (1);
-out:
-	kfree(control);
-	return retval;
 }
 
 static int koneplus_send(struct usb_device *usb_dev, uint command,
-		void *buf, uint size) {
-	int len;
-
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			command, 0, buf, size, USB_CTRL_SET_TIMEOUT);
-
-	if (len != size)
-		return -EIO;
+		void const *buf, uint size)
+{
+	int retval;
 
-	if (koneplus_receive_control_status(usb_dev))
-		return -EIO;
+	retval = roccat_common_send(usb_dev, command, buf, size);
+	if (retval)
+		return retval;
 
-	return 0;
+	return koneplus_receive_control_status(usb_dev);
 }
 
 static int koneplus_select_profile(struct usb_device *usb_dev, uint number,
@@ -167,7 +120,7 @@
 static int koneplus_get_info(struct usb_device *usb_dev,
 		struct koneplus_info *buf)
 {
-	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
+	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_INFO,
 			buf, sizeof(struct koneplus_info));
 }
 
@@ -181,7 +134,7 @@
 	if (retval)
 		return retval;
 
-	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
+	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
 			buf, sizeof(struct koneplus_profile_settings));
 }
 
@@ -189,7 +142,7 @@
 		struct koneplus_profile_settings const *settings)
 {
 	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_SETTINGS,
-			(void *)settings, sizeof(struct koneplus_profile_settings));
+			settings, sizeof(struct koneplus_profile_settings));
 }
 
 static int koneplus_get_profile_buttons(struct usb_device *usb_dev,
@@ -202,7 +155,7 @@
 	if (retval)
 		return retval;
 
-	return koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
+	return roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
 			buf, sizeof(struct koneplus_profile_buttons));
 }
 
@@ -210,27 +163,19 @@
 		struct koneplus_profile_buttons const *buttons)
 {
 	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_PROFILE_BUTTONS,
-			(void *)buttons, sizeof(struct koneplus_profile_buttons));
+			buttons, sizeof(struct koneplus_profile_buttons));
 }
 
 /* retval is 0-4 on success, < 0 on error */
 static int koneplus_get_startup_profile(struct usb_device *usb_dev)
 {
-	struct koneplus_startup_profile *buf;
+	struct koneplus_startup_profile buf;
 	int retval;
 
-	buf = kmalloc(sizeof(struct koneplus_startup_profile), GFP_KERNEL);
-
-	retval = koneplus_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
-			buf, sizeof(struct koneplus_startup_profile));
-
-	if (retval)
-		goto out;
+	retval = roccat_common_receive(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
+			&buf, sizeof(struct koneplus_startup_profile));
 
-	retval = buf->startup_profile;
-out:
-	kfree(buf);
-	return retval;
+	return retval ? retval : buf.startup_profile;
 }
 
 static int koneplus_set_startup_profile(struct usb_device *usb_dev,
@@ -243,7 +188,7 @@
 	buf.startup_profile = startup_profile;
 
 	return koneplus_send(usb_dev, KONEPLUS_USB_COMMAND_STARTUP_PROFILE,
-			(char *)&buf, sizeof(struct koneplus_profile_buttons));
+			&buf, sizeof(struct koneplus_profile_buttons));
 }
 
 static ssize_t koneplus_sysfs_read(struct file *fp, struct kobject *kobj,
@@ -256,11 +201,14 @@
 	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
 	int retval;
 
+	if (off >= real_size)
+		return 0;
+
 	if (off != 0 || count != real_size)
 		return -EINVAL;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	retval = koneplus_receive(usb_dev, command, buf, real_size);
+	retval = roccat_common_receive(usb_dev, command, buf, real_size);
 	mutex_unlock(&koneplus->koneplus_lock);
 
 	if (retval)
@@ -283,7 +231,7 @@
 		return -EINVAL;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	retval = koneplus_send(usb_dev, command, (void *)buf, real_size);
+	retval = koneplus_send(usb_dev, command, buf, real_size);
 	mutex_unlock(&koneplus->koneplus_lock);
 
 	if (retval)
@@ -347,7 +295,7 @@
 		count = sizeof(struct koneplus_profile_settings) - off;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	memcpy(buf, ((void const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
+	memcpy(buf, ((char const *)&koneplus->profile_settings[*(uint *)(attr->private)]) + off,
 			count);
 	mutex_unlock(&koneplus->koneplus_lock);
 
@@ -406,7 +354,7 @@
 		count = sizeof(struct koneplus_profile_buttons) - off;
 
 	mutex_lock(&koneplus->koneplus_lock);
-	memcpy(buf, ((void const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
+	memcpy(buf, ((char const *)&koneplus->profile_buttons[*(uint *)(attr->private)]) + off,
 			count);
 	mutex_unlock(&koneplus->koneplus_lock);
 
@@ -512,7 +460,7 @@
 
 static struct bin_attribute koneplus_bin_attributes[] = {
 	{
-		.attr = { .name = "sensor", .mode = 0220 },
+		.attr = { .name = "sensor", .mode = 0660 },
 		.size = sizeof(struct koneplus_sensor),
 		.read = koneplus_sysfs_read_sensor,
 		.write = koneplus_sysfs_write_sensor
@@ -609,11 +557,13 @@
 		struct koneplus_device *koneplus)
 {
 	int retval, i;
-	static uint wait = 70; /* device will freeze with just 60 */
+	static uint wait = 100; /* device will freeze with just 60 */
 
 	mutex_init(&koneplus->koneplus_lock);
 
 	koneplus->startup_profile = koneplus_get_startup_profile(usb_dev);
+	if (koneplus->startup_profile < 0)
+		return koneplus->startup_profile;
 
 	msleep(wait);
 	retval = koneplus_get_info(usb_dev, &koneplus->info);
@@ -651,21 +601,21 @@
 
 		koneplus = kzalloc(sizeof(*koneplus), GFP_KERNEL);
 		if (!koneplus) {
-			dev_err(&hdev->dev, "can't alloc device descriptor\n");
+			hid_err(hdev, "can't alloc device descriptor\n");
 			return -ENOMEM;
 		}
 		hid_set_drvdata(hdev, koneplus);
 
 		retval = koneplus_init_koneplus_device_struct(usb_dev, koneplus);
 		if (retval) {
-			dev_err(&hdev->dev,
-					"couldn't init struct koneplus_device\n");
+			hid_err(hdev, "couldn't init struct koneplus_device\n");
 			goto exit_free;
 		}
 
-		retval = roccat_connect(koneplus_class, hdev);
+		retval = roccat_connect(koneplus_class, hdev,
+				sizeof(struct koneplus_roccat_report));
 		if (retval < 0) {
-			dev_err(&hdev->dev, "couldn't init char dev\n");
+			hid_err(hdev, "couldn't init char dev\n");
 		} else {
 			koneplus->chrdev_minor = retval;
 			koneplus->roccat_claimed = 1;
@@ -701,19 +651,19 @@
 
 	retval = hid_parse(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "parse failed\n");
+		hid_err(hdev, "parse failed\n");
 		goto exit;
 	}
 
 	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
 	if (retval) {
-		dev_err(&hdev->dev, "hw start failed\n");
+		hid_err(hdev, "hw start failed\n");
 		goto exit;
 	}
 
 	retval = koneplus_init_specials(hdev);
 	if (retval) {
-		dev_err(&hdev->dev, "couldn't install mouse\n");
+		hid_err(hdev, "couldn't install mouse\n");
 		goto exit_stop;
 	}
 
@@ -769,8 +719,7 @@
 	roccat_report.data2 = button_report->data2;
 	roccat_report.profile = koneplus->actual_profile + 1;
 	roccat_report_event(koneplus->chrdev_minor,
-			(uint8_t const *)&roccat_report,
-			sizeof(struct koneplus_roccat_report));
+			(uint8_t const *)&roccat_report);
 }
 
 static int koneplus_raw_event(struct hid_device *hdev,
@@ -825,8 +774,8 @@
 
 static void __exit koneplus_exit(void)
 {
-	class_destroy(koneplus_class);
 	hid_unregister_driver(&koneplus_driver);
+	class_destroy(koneplus_class);
 }
 
 module_init(koneplus_init);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kovaplus.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kovaplus.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kovaplus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kovaplus.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,715 @@
+/*
+ * Roccat Kova[+] driver for Linux
+ *
+ * Copyright (c) 2011 Stefan Achatz <erazor_de@users.sourceforge.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.
+ */
+
+/*
+ * Roccat Kova[+] is a bigger version of the Pyra with two more side buttons.
+ */
+
+#include <linux/device.h>
+#include <linux/input.h>
+#include <linux/hid.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/hid-roccat.h>
+#include "hid-ids.h"
+#include "hid-roccat-common.h"
+#include "hid-roccat-kovaplus.h"
+
+static uint profile_numbers[5] = {0, 1, 2, 3, 4};
+
+static struct class *kovaplus_class;
+
+static uint kovaplus_convert_event_cpi(uint value)
+{
+	return (value == 7 ? 4 : (value == 4 ? 3 : value));
+}
+
+static void kovaplus_profile_activated(struct kovaplus_device *kovaplus,
+		uint new_profile_index)
+{
+	kovaplus->actual_profile = new_profile_index;
+	kovaplus->actual_cpi = kovaplus->profile_settings[new_profile_index].cpi_startup_level;
+	kovaplus->actual_x_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_x;
+	kovaplus->actual_y_sensitivity = kovaplus->profile_settings[new_profile_index].sensitivity_y;
+}
+
+static int kovaplus_send_control(struct usb_device *usb_dev, uint value,
+		enum kovaplus_control_requests request)
+{
+	int retval;
+	struct kovaplus_control control;
+
+	if ((request == KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS ||
+			request == KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS) &&
+			value > 4)
+		return -EINVAL;
+
+	control.command = KOVAPLUS_COMMAND_CONTROL;
+	control.value = value;
+	control.request = request;
+
+	retval = roccat_common_send(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+			&control, sizeof(struct kovaplus_control));
+
+	return retval;
+}
+
+static int kovaplus_receive_control_status(struct usb_device *usb_dev)
+{
+	int retval;
+	struct kovaplus_control control;
+
+	do {
+		retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_CONTROL,
+				&control, sizeof(struct kovaplus_control));
+
+		/* check if we get a completely wrong answer */
+		if (retval)
+			return retval;
+
+		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OK)
+			return 0;
+
+		/* indicates that hardware needs some more time to complete action */
+		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT) {
+			msleep(500); /* windows driver uses 1000 */
+			continue;
+		}
+
+		/* seems to be critical - replug necessary */
+		if (control.value == KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD)
+			return -EINVAL;
+
+		hid_err(usb_dev, "kovaplus_receive_control_status: "
+				"unknown response value 0x%x\n", control.value);
+		return -EINVAL;
+	} while (1);
+}
+
+static int kovaplus_send(struct usb_device *usb_dev, uint command,
+		void const *buf, uint size)
+{
+	int retval;
+
+	retval = roccat_common_send(usb_dev, command, buf, size);
+	if (retval)
+		return retval;
+
+	msleep(100);
+
+	return kovaplus_receive_control_status(usb_dev);
+}
+
+static int kovaplus_select_profile(struct usb_device *usb_dev, uint number,
+		enum kovaplus_control_requests request)
+{
+	return kovaplus_send_control(usb_dev, number, request);
+}
+
+static int kovaplus_get_info(struct usb_device *usb_dev,
+		struct kovaplus_info *buf)
+{
+	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_INFO,
+			buf, sizeof(struct kovaplus_info));
+}
+
+static int kovaplus_get_profile_settings(struct usb_device *usb_dev,
+		struct kovaplus_profile_settings *buf, uint number)
+{
+	int retval;
+
+	retval = kovaplus_select_profile(usb_dev, number,
+			KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS);
+	if (retval)
+		return retval;
+
+	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+			buf, sizeof(struct kovaplus_profile_settings));
+}
+
+static int kovaplus_set_profile_settings(struct usb_device *usb_dev,
+		struct kovaplus_profile_settings const *settings)
+{
+	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS,
+			settings, sizeof(struct kovaplus_profile_settings));
+}
+
+static int kovaplus_get_profile_buttons(struct usb_device *usb_dev,
+		struct kovaplus_profile_buttons *buf, int number)
+{
+	int retval;
+
+	retval = kovaplus_select_profile(usb_dev, number,
+			KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS);
+	if (retval)
+		return retval;
+
+	return roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+			buf, sizeof(struct kovaplus_profile_buttons));
+}
+
+static int kovaplus_set_profile_buttons(struct usb_device *usb_dev,
+		struct kovaplus_profile_buttons const *buttons)
+{
+	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS,
+			buttons, sizeof(struct kovaplus_profile_buttons));
+}
+
+/* retval is 0-4 on success, < 0 on error */
+static int kovaplus_get_actual_profile(struct usb_device *usb_dev)
+{
+	struct kovaplus_actual_profile buf;
+	int retval;
+
+	retval = roccat_common_receive(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+			&buf, sizeof(struct kovaplus_actual_profile));
+
+	return retval ? retval : buf.actual_profile;
+}
+
+static int kovaplus_set_actual_profile(struct usb_device *usb_dev,
+		int new_profile)
+{
+	struct kovaplus_actual_profile buf;
+
+	buf.command = KOVAPLUS_COMMAND_ACTUAL_PROFILE;
+	buf.size = sizeof(struct kovaplus_actual_profile);
+	buf.actual_profile = new_profile;
+
+	return kovaplus_send(usb_dev, KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE,
+			&buf, sizeof(struct kovaplus_actual_profile));
+}
+
+static ssize_t kovaplus_sysfs_read_profilex_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct kovaplus_profile_settings))
+		return 0;
+
+	if (off + count > sizeof(struct kovaplus_profile_settings))
+		count = sizeof(struct kovaplus_profile_settings) - off;
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	memcpy(buf, ((char const *)&kovaplus->profile_settings[*(uint *)(attr->private)]) + off,
+			count);
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	return count;
+}
+
+static ssize_t kovaplus_sysfs_write_profile_settings(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+	int profile_index;
+	struct kovaplus_profile_settings *profile_settings;
+
+	if (off != 0 || count != sizeof(struct kovaplus_profile_settings))
+		return -EINVAL;
+
+	profile_index = ((struct kovaplus_profile_settings const *)buf)->profile_index;
+	profile_settings = &kovaplus->profile_settings[profile_index];
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	difference = memcmp(buf, profile_settings,
+			sizeof(struct kovaplus_profile_settings));
+	if (difference) {
+		retval = kovaplus_set_profile_settings(usb_dev,
+				(struct kovaplus_profile_settings const *)buf);
+		if (!retval)
+			memcpy(profile_settings, buf,
+					sizeof(struct kovaplus_profile_settings));
+	}
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct kovaplus_profile_settings);
+}
+
+static ssize_t kovaplus_sysfs_read_profilex_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+
+	if (off >= sizeof(struct kovaplus_profile_buttons))
+		return 0;
+
+	if (off + count > sizeof(struct kovaplus_profile_buttons))
+		count = sizeof(struct kovaplus_profile_buttons) - off;
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	memcpy(buf, ((char const *)&kovaplus->profile_buttons[*(uint *)(attr->private)]) + off,
+			count);
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	return count;
+}
+
+static ssize_t kovaplus_sysfs_write_profile_buttons(struct file *fp,
+		struct kobject *kobj, struct bin_attribute *attr, char *buf,
+		loff_t off, size_t count)
+{
+	struct device *dev =
+			container_of(kobj, struct device, kobj)->parent->parent;
+	struct kovaplus_device *kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	struct usb_device *usb_dev = interface_to_usbdev(to_usb_interface(dev));
+	int retval = 0;
+	int difference;
+	uint profile_index;
+	struct kovaplus_profile_buttons *profile_buttons;
+
+	if (off != 0 || count != sizeof(struct kovaplus_profile_buttons))
+		return -EINVAL;
+
+	profile_index = ((struct kovaplus_profile_buttons const *)buf)->profile_index;
+	profile_buttons = &kovaplus->profile_buttons[profile_index];
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	difference = memcmp(buf, profile_buttons,
+			sizeof(struct kovaplus_profile_buttons));
+	if (difference) {
+		retval = kovaplus_set_profile_buttons(usb_dev,
+				(struct kovaplus_profile_buttons const *)buf);
+		if (!retval)
+			memcpy(profile_buttons, buf,
+					sizeof(struct kovaplus_profile_buttons));
+	}
+	mutex_unlock(&kovaplus->kovaplus_lock);
+
+	if (retval)
+		return retval;
+
+	return sizeof(struct kovaplus_profile_buttons);
+}
+
+static ssize_t kovaplus_sysfs_show_actual_profile(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_profile);
+}
+
+static ssize_t kovaplus_sysfs_set_actual_profile(struct device *dev,
+		struct device_attribute *attr, char const *buf, size_t size)
+{
+	struct kovaplus_device *kovaplus;
+	struct usb_device *usb_dev;
+	unsigned long profile;
+	int retval;
+
+	dev = dev->parent->parent;
+	kovaplus = hid_get_drvdata(dev_get_drvdata(dev));
+	usb_dev = interface_to_usbdev(to_usb_interface(dev));
+
+	retval = strict_strtoul(buf, 10, &profile);
+	if (retval)
+		return retval;
+
+	if (profile >= 5)
+		return -EINVAL;
+
+	mutex_lock(&kovaplus->kovaplus_lock);
+	retval = kovaplus_set_actual_profile(usb_dev, profile);
+	kovaplus->actual_profile = profile;
+	mutex_unlock(&kovaplus->kovaplus_lock);
+	if (retval)
+		return retval;
+
+	return size;
+}
+
+static ssize_t kovaplus_sysfs_show_actual_cpi(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_cpi);
+}
+
+static ssize_t kovaplus_sysfs_show_actual_sensitivity_x(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_x_sensitivity);
+}
+
+static ssize_t kovaplus_sysfs_show_actual_sensitivity_y(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->actual_y_sensitivity);
+}
+
+static ssize_t kovaplus_sysfs_show_firmware_version(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kovaplus_device *kovaplus =
+			hid_get_drvdata(dev_get_drvdata(dev->parent->parent));
+	return snprintf(buf, PAGE_SIZE, "%d\n", kovaplus->info.firmware_version);
+}
+
+static struct device_attribute kovaplus_attributes[] = {
+	__ATTR(actual_cpi, 0440,
+		kovaplus_sysfs_show_actual_cpi, NULL),
+	__ATTR(firmware_version, 0440,
+		kovaplus_sysfs_show_firmware_version, NULL),
+	__ATTR(actual_profile, 0660,
+		kovaplus_sysfs_show_actual_profile,
+		kovaplus_sysfs_set_actual_profile),
+	__ATTR(actual_sensitivity_x, 0440,
+		kovaplus_sysfs_show_actual_sensitivity_x, NULL),
+	__ATTR(actual_sensitivity_y, 0440,
+		kovaplus_sysfs_show_actual_sensitivity_y, NULL),
+	__ATTR_NULL
+};
+
+static struct bin_attribute kovaplus_bin_attributes[] = {
+	{
+		.attr = { .name = "profile_settings", .mode = 0220 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.write = kovaplus_sysfs_write_profile_settings
+	},
+	{
+		.attr = { .name = "profile1_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5_settings", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_settings),
+		.read = kovaplus_sysfs_read_profilex_settings,
+		.private = &profile_numbers[4]
+	},
+	{
+		.attr = { .name = "profile_buttons", .mode = 0220 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.write = kovaplus_sysfs_write_profile_buttons
+	},
+	{
+		.attr = { .name = "profile1_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[0]
+	},
+	{
+		.attr = { .name = "profile2_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[1]
+	},
+	{
+		.attr = { .name = "profile3_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[2]
+	},
+	{
+		.attr = { .name = "profile4_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[3]
+	},
+	{
+		.attr = { .name = "profile5_buttons", .mode = 0440 },
+		.size = sizeof(struct kovaplus_profile_buttons),
+		.read = kovaplus_sysfs_read_profilex_buttons,
+		.private = &profile_numbers[4]
+	},
+	__ATTR_NULL
+};
+
+static int kovaplus_init_kovaplus_device_struct(struct usb_device *usb_dev,
+		struct kovaplus_device *kovaplus)
+{
+	int retval, i;
+	static uint wait = 70; /* device will freeze with just 60 */
+
+	mutex_init(&kovaplus->kovaplus_lock);
+
+	retval = kovaplus_get_info(usb_dev, &kovaplus->info);
+	if (retval)
+		return retval;
+
+	for (i = 0; i < 5; ++i) {
+		msleep(wait);
+		retval = kovaplus_get_profile_settings(usb_dev,
+				&kovaplus->profile_settings[i], i);
+		if (retval)
+			return retval;
+
+		msleep(wait);
+		retval = kovaplus_get_profile_buttons(usb_dev,
+				&kovaplus->profile_buttons[i], i);
+		if (retval)
+			return retval;
+	}
+
+	msleep(wait);
+	retval = kovaplus_get_actual_profile(usb_dev);
+	if (retval < 0)
+		return retval;
+	kovaplus_profile_activated(kovaplus, retval);
+
+	return 0;
+}
+
+static int kovaplus_init_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct usb_device *usb_dev = interface_to_usbdev(intf);
+	struct kovaplus_device *kovaplus;
+	int retval;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+
+		kovaplus = kzalloc(sizeof(*kovaplus), GFP_KERNEL);
+		if (!kovaplus) {
+			hid_err(hdev, "can't alloc device descriptor\n");
+			return -ENOMEM;
+		}
+		hid_set_drvdata(hdev, kovaplus);
+
+		retval = kovaplus_init_kovaplus_device_struct(usb_dev, kovaplus);
+		if (retval) {
+			hid_err(hdev, "couldn't init struct kovaplus_device\n");
+			goto exit_free;
+		}
+
+		retval = roccat_connect(kovaplus_class, hdev,
+				sizeof(struct kovaplus_roccat_report));
+		if (retval < 0) {
+			hid_err(hdev, "couldn't init char dev\n");
+		} else {
+			kovaplus->chrdev_minor = retval;
+			kovaplus->roccat_claimed = 1;
+		}
+
+	} else {
+		hid_set_drvdata(hdev, NULL);
+	}
+
+	return 0;
+exit_free:
+	kfree(kovaplus);
+	return retval;
+}
+
+static void kovaplus_remove_specials(struct hid_device *hdev)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct kovaplus_device *kovaplus;
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			== USB_INTERFACE_PROTOCOL_MOUSE) {
+		kovaplus = hid_get_drvdata(hdev);
+		if (kovaplus->roccat_claimed)
+			roccat_disconnect(kovaplus->chrdev_minor);
+		kfree(kovaplus);
+	}
+}
+
+static int kovaplus_probe(struct hid_device *hdev,
+		const struct hid_device_id *id)
+{
+	int retval;
+
+	retval = hid_parse(hdev);
+	if (retval) {
+		hid_err(hdev, "parse failed\n");
+		goto exit;
+	}
+
+	retval = hid_hw_start(hdev, HID_CONNECT_DEFAULT);
+	if (retval) {
+		hid_err(hdev, "hw start failed\n");
+		goto exit;
+	}
+
+	retval = kovaplus_init_specials(hdev);
+	if (retval) {
+		hid_err(hdev, "couldn't install mouse\n");
+		goto exit_stop;
+	}
+
+	return 0;
+
+exit_stop:
+	hid_hw_stop(hdev);
+exit:
+	return retval;
+}
+
+static void kovaplus_remove(struct hid_device *hdev)
+{
+	kovaplus_remove_specials(hdev);
+	hid_hw_stop(hdev);
+}
+
+static void kovaplus_keep_values_up_to_date(struct kovaplus_device *kovaplus,
+		u8 const *data)
+{
+	struct kovaplus_mouse_report_button const *button_report;
+
+	if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON)
+		return;
+
+	button_report = (struct kovaplus_mouse_report_button const *)data;
+
+	switch (button_report->type) {
+	case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1:
+		kovaplus_profile_activated(kovaplus, button_report->data1 - 1);
+		break;
+	case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI:
+		kovaplus->actual_cpi = kovaplus_convert_event_cpi(button_report->data1);
+	case KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY:
+		kovaplus->actual_x_sensitivity = button_report->data1;
+		kovaplus->actual_y_sensitivity = button_report->data2;
+	}
+}
+
+static void kovaplus_report_to_chrdev(struct kovaplus_device const *kovaplus,
+		u8 const *data)
+{
+	struct kovaplus_roccat_report roccat_report;
+	struct kovaplus_mouse_report_button const *button_report;
+
+	if (data[0] != KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON)
+		return;
+
+	button_report = (struct kovaplus_mouse_report_button const *)data;
+
+	if (button_report->type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2)
+		return;
+
+	roccat_report.type = button_report->type;
+	roccat_report.profile = kovaplus->actual_profile + 1;
+
+	if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO ||
+			roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT ||
+			roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH ||
+			roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER)
+		roccat_report.button = button_report->data1;
+	else
+		roccat_report.button = 0;
+
+	if (roccat_report.type == KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI)
+		roccat_report.data1 = kovaplus_convert_event_cpi(button_report->data1);
+	else
+		roccat_report.data1 = button_report->data1;
+
+	roccat_report.data2 = button_report->data2;
+
+	roccat_report_event(kovaplus->chrdev_minor,
+			(uint8_t const *)&roccat_report);
+}
+
+static int kovaplus_raw_event(struct hid_device *hdev,
+		struct hid_report *report, u8 *data, int size)
+{
+	struct usb_interface *intf = to_usb_interface(hdev->dev.parent);
+	struct kovaplus_device *kovaplus = hid_get_drvdata(hdev);
+
+	if (intf->cur_altsetting->desc.bInterfaceProtocol
+			!= USB_INTERFACE_PROTOCOL_MOUSE)
+		return 0;
+
+	kovaplus_keep_values_up_to_date(kovaplus, data);
+
+	if (kovaplus->roccat_claimed)
+		kovaplus_report_to_chrdev(kovaplus, data);
+
+	return 0;
+}
+
+static const struct hid_device_id kovaplus_devices[] = {
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KOVAPLUS) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(hid, kovaplus_devices);
+
+static struct hid_driver kovaplus_driver = {
+		.name = "kovaplus",
+		.id_table = kovaplus_devices,
+		.probe = kovaplus_probe,
+		.remove = kovaplus_remove,
+		.raw_event = kovaplus_raw_event
+};
+
+static int __init kovaplus_init(void)
+{
+	int retval;
+
+	kovaplus_class = class_create(THIS_MODULE, "kovaplus");
+	if (IS_ERR(kovaplus_class))
+		return PTR_ERR(kovaplus_class);
+	kovaplus_class->dev_attrs = kovaplus_attributes;
+	kovaplus_class->dev_bin_attrs = kovaplus_bin_attributes;
+
+	retval = hid_register_driver(&kovaplus_driver);
+	if (retval)
+		class_destroy(kovaplus_class);
+	return retval;
+}
+
+static void __exit kovaplus_exit(void)
+{
+	hid_unregister_driver(&kovaplus_driver);
+	class_destroy(kovaplus_class);
+}
+
+module_init(kovaplus_init);
+module_exit(kovaplus_exit);
+
+MODULE_AUTHOR("Stefan Achatz");
+MODULE_DESCRIPTION("USB Roccat Kova[+] driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kovaplus.h linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kovaplus.h
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-kovaplus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-kovaplus.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,157 @@
+#ifndef __HID_ROCCAT_KOVAPLUS_H
+#define __HID_ROCCAT_KOVAPLUS_H
+
+/*
+ * Copyright (c) 2010 Stefan Achatz <erazor_de@users.sourceforge.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/types.h>
+
+struct kovaplus_control {
+	uint8_t command; /* KOVAPLUS_COMMAND_CONTROL */
+	uint8_t value;
+	uint8_t request;
+} __packed;
+
+enum kovaplus_control_requests {
+	/* read after write; value = 1 */
+	KOVAPLUS_CONTROL_REQUEST_STATUS = 0x0,
+	/* write; value = profile number range 0-4 */
+	KOVAPLUS_CONTROL_REQUEST_PROFILE_SETTINGS = 0x10,
+	/* write; value = profile number range 0-4 */
+	KOVAPLUS_CONTROL_REQUEST_PROFILE_BUTTONS = 0x20,
+};
+
+enum kovaplus_control_values {
+	KOVAPLUS_CONTROL_REQUEST_STATUS_OVERLOAD = 0, /* supposed */
+	KOVAPLUS_CONTROL_REQUEST_STATUS_OK = 1,
+	KOVAPLUS_CONTROL_REQUEST_STATUS_WAIT = 3, /* supposed */
+};
+
+struct kovaplus_actual_profile {
+	uint8_t command; /* KOVAPLUS_COMMAND_ACTUAL_PROFILE */
+	uint8_t size; /* always 3 */
+	uint8_t actual_profile; /* Range 0-4! */
+} __packed;
+
+struct kovaplus_profile_settings {
+	uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_SETTINGS */
+	uint8_t size; /* 16 */
+	uint8_t profile_index; /* range 0-4 */
+	uint8_t unknown1;
+	uint8_t sensitivity_x; /* range 1-10 */
+	uint8_t sensitivity_y; /* range 1-10 */
+	uint8_t cpi_levels_enabled;
+	uint8_t cpi_startup_level; /* range 1-4 */
+	uint8_t data[8];
+} __packed;
+
+struct kovaplus_profile_buttons {
+	uint8_t command; /* KOVAPLUS_COMMAND_PROFILE_BUTTONS */
+	uint8_t size; /* 23 */
+	uint8_t profile_index; /* range 0-4 */
+	uint8_t data[20];
+} __packed;
+
+struct kovaplus_info {
+	uint8_t command; /* KOVAPLUS_COMMAND_INFO */
+	uint8_t size; /* 6 */
+	uint8_t firmware_version;
+	uint8_t unknown[3];
+} __packed;
+
+/* writes 1 on plugin */
+struct kovaplus_a {
+	uint8_t command; /* KOVAPLUS_COMMAND_A */
+	uint8_t size; /* 3 */
+	uint8_t unknown;
+} __packed;
+
+enum kovaplus_commands {
+	KOVAPLUS_COMMAND_CONTROL = 0x4,
+	KOVAPLUS_COMMAND_ACTUAL_PROFILE = 0x5,
+	KOVAPLUS_COMMAND_PROFILE_SETTINGS = 0x6,
+	KOVAPLUS_COMMAND_PROFILE_BUTTONS = 0x7,
+	KOVAPLUS_COMMAND_INFO = 0x9,
+	KOVAPLUS_COMMAND_A = 0xa,
+};
+
+enum kovaplus_usb_commands {
+	KOVAPLUS_USB_COMMAND_CONTROL = 0x304,
+	KOVAPLUS_USB_COMMAND_ACTUAL_PROFILE = 0x305,
+	KOVAPLUS_USB_COMMAND_PROFILE_SETTINGS = 0x306,
+	KOVAPLUS_USB_COMMAND_PROFILE_BUTTONS = 0x307,
+	KOVAPLUS_USB_COMMAND_INFO = 0x309,
+	KOVAPLUS_USB_COMMAND_A = 0x30a,
+};
+
+enum kovaplus_mouse_report_numbers {
+	KOVAPLUS_MOUSE_REPORT_NUMBER_MOUSE = 1,
+	KOVAPLUS_MOUSE_REPORT_NUMBER_AUDIO = 2,
+	KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON = 3,
+	KOVAPLUS_MOUSE_REPORT_NUMBER_KBD = 4,
+};
+
+struct kovaplus_mouse_report_button {
+	uint8_t report_number; /* KOVAPLUS_MOUSE_REPORT_NUMBER_BUTTON */
+	uint8_t unknown1;
+	uint8_t type;
+	uint8_t data1;
+	uint8_t data2;
+} __packed;
+
+enum kovaplus_mouse_report_button_types {
+	/* data1 = profile_number range 1-5; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_1 = 0x20,
+	/* data1 = profile_number range 1-5; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_PROFILE_2 = 0x30,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MACRO = 0x40,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SHORTCUT = 0x50,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_QUICKLAUNCH = 0x60,
+	/* data1 = button_number range 1-18; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_TIMER = 0x80,
+	/* data1 = 1 = 400, 2 = 800, 4 = 1600, 7 = 3200; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_CPI = 0xb0,
+	/* data1 + data2 = sense range 1-10; no release event */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_SENSITIVITY = 0xc0,
+	/* data1 = type as in profile_buttons; data2 = action */
+	KOVAPLUS_MOUSE_REPORT_BUTTON_TYPE_MULTIMEDIA = 0xf0,
+};
+
+enum kovaplus_mouse_report_button_actions {
+	KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_PRESS = 0,
+	KOVAPLUS_MOUSE_REPORT_BUTTON_ACTION_RELEASE = 1,
+};
+
+struct kovaplus_roccat_report {
+	uint8_t type;
+	uint8_t profile;
+	uint8_t button;
+	uint8_t data1;
+	uint8_t data2;
+} __packed;
+
+struct kovaplus_device {
+	int actual_profile;
+	int actual_cpi;
+	int actual_x_sensitivity;
+	int actual_y_sensitivity;
+	int roccat_claimed;
+	int chrdev_minor;
+	struct mutex kovaplus_lock;
+	struct kovaplus_info info;
+	struct kovaplus_profile_settings profile_settings[5];
+	struct kovaplus_profile_buttons profile_buttons[5];
+};
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-pyra.c linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-pyra.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-roccat-pyra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-roccat-pyra.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,11 +20,11 @@
 #include <linux/device.h>
 #include <linux/input.h>
 #include <linux/hid.h>
-#include <linux/usb.h>
 #include <linux/module.h>
 #include <linux/slab.h>
+#include <linux/hid-roccat.h>
 #include "hid-ids.h"
-#include "hid-roccat.h"
+#include "hid-roccat-common.h"
 #include "hid-roccat-pyra.h"
 
 static uint profile_numbers[5] = {0, 1, 2, 3, 4};
@@ -42,7 +42,6 @@
 static int pyra_send_control(struct usb_device *usb_dev, int value,
 		enum pyra_control_requests request)
 {
-	int len;
 	struct pyra_control control;
 
 	if ((request == PYRA_CONTROL_REQUEST_PROFILE_SETTINGS ||
@@ -54,47 +53,31 @@
 	control.value = value;
 	control.request = request;
 
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_CONTROL, 0, (char *)&control,
-			sizeof(struct pyra_control),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (len != sizeof(struct pyra_control))
-		return len;
-
-	return 0;
+	return roccat_common_send(usb_dev, PYRA_USB_COMMAND_CONTROL,
+			&control, sizeof(struct pyra_control));
 }
 
 static int pyra_receive_control_status(struct usb_device *usb_dev)
 {
-	int len;
+	int retval;
 	struct pyra_control control;
 
 	do {
 		msleep(10);
-
-		len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-				USB_REQ_CLEAR_FEATURE,
-				USB_TYPE_CLASS | USB_RECIP_INTERFACE |
-				USB_DIR_IN,
-				PYRA_USB_COMMAND_CONTROL, 0, (char *)&control,
-				sizeof(struct pyra_control),
-				USB_CTRL_SET_TIMEOUT);
+		retval = roccat_common_receive(usb_dev, PYRA_USB_COMMAND_CONTROL,
+				&control, sizeof(struct pyra_control));
 
 		/* requested too early, try again */
-	} while (len == -EPROTO);
+	} while (retval == -EPROTO);
 
-	if (len == sizeof(struct pyra_control) &&
-			control.command == PYRA_COMMAND_CONTROL &&
+	if (!retval && control.command == PYRA_COMMAND_CONTROL &&
 			control.request == PYRA_CONTROL_REQUEST_STATUS &&
 			control.value == 1)
-			return 0;
+		return 0;
 	else {
 		hid_err(usb_dev, "receive control status: unknown response 0x%x 0x%x\n",
 			control.request, control.value);
-		return -EINVAL;
+		return retval ? retval : -EINVAL;
 	}
 }
 
@@ -102,125 +85,72 @@
 		struct pyra_profile_settings *buf, int number)
 {
 	int retval;
-
 	retval = pyra_send_control(usb_dev, number,
 			PYRA_CONTROL_REQUEST_PROFILE_SETTINGS);
-
 	if (retval)
 		return retval;
-
-	retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)buf,
-			sizeof(struct pyra_profile_settings),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (retval != sizeof(struct pyra_profile_settings))
-		return retval;
-
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS,
+			buf, sizeof(struct pyra_profile_settings));
 }
 
 static int pyra_get_profile_buttons(struct usb_device *usb_dev,
 		struct pyra_profile_buttons *buf, int number)
 {
 	int retval;
-
 	retval = pyra_send_control(usb_dev, number,
 			PYRA_CONTROL_REQUEST_PROFILE_BUTTONS);
-
 	if (retval)
 		return retval;
-
-	retval = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buf,
-			sizeof(struct pyra_profile_buttons),
-			USB_CTRL_SET_TIMEOUT);
-
-	if (retval != sizeof(struct pyra_profile_buttons))
-		return retval;
-
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS,
+			buf, sizeof(struct pyra_profile_buttons));
 }
 
 static int pyra_get_settings(struct usb_device *usb_dev,
 		struct pyra_settings *buf)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_SETTINGS, 0, buf,
-			sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_settings))
-		return -EIO;
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_SETTINGS,
+			buf, sizeof(struct pyra_settings));
 }
 
 static int pyra_get_info(struct usb_device *usb_dev, struct pyra_info *buf)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_rcvctrlpipe(usb_dev, 0),
-			USB_REQ_CLEAR_FEATURE,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_IN,
-			PYRA_USB_COMMAND_INFO, 0, buf,
-			sizeof(struct pyra_info), USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_info))
-		return -EIO;
-	return 0;
+	return roccat_common_receive(usb_dev, PYRA_USB_COMMAND_INFO,
+			buf, sizeof(struct pyra_info));
+}
+
+static int pyra_send(struct usb_device *usb_dev, uint command,
+		void const *buf, uint size)
+{
+	int retval;
+	retval = roccat_common_send(usb_dev, command, buf, size);
+	if (retval)
+		return retval;
+	return pyra_receive_control_status(usb_dev);
 }
 
 static int pyra_set_profile_settings(struct usb_device *usb_dev,
 		struct pyra_profile_settings const *settings)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_PROFILE_SETTINGS, 0, (char *)settings,
-			sizeof(struct pyra_profile_settings),
-			USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_profile_settings))
-		return -EIO;
-	if (pyra_receive_control_status(usb_dev))
-		return -EIO;
-	return 0;
+	return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_SETTINGS, settings,
+			sizeof(struct pyra_profile_settings));
 }
 
 static int pyra_set_profile_buttons(struct usb_device *usb_dev,
 		struct pyra_profile_buttons const *buttons)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_PROFILE_BUTTONS, 0, (char *)buttons,
-			sizeof(struct pyra_profile_buttons),
-			USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_profile_buttons))
-		return -EIO;
-	if (pyra_receive_control_status(usb_dev))
-		return -EIO;
-	return 0;
+	return pyra_send(usb_dev, PYRA_USB_COMMAND_PROFILE_BUTTONS, buttons,
+			sizeof(struct pyra_profile_buttons));
 }
 
 static int pyra_set_settings(struct usb_device *usb_dev,
 		struct pyra_settings const *settings)
 {
-	int len;
-	len = usb_control_msg(usb_dev, usb_sndctrlpipe(usb_dev, 0),
-			USB_REQ_SET_CONFIGURATION,
-			USB_TYPE_CLASS | USB_RECIP_INTERFACE | USB_DIR_OUT,
-			PYRA_USB_COMMAND_SETTINGS, 0, (char *)settings,
-			sizeof(struct pyra_settings), USB_CTRL_SET_TIMEOUT);
-	if (len != sizeof(struct pyra_settings))
-		return -EIO;
-	if (pyra_receive_control_status(usb_dev))
-		return -EIO;
-	return 0;
+	int retval;
+	retval = roccat_common_send(usb_dev, PYRA_USB_COMMAND_SETTINGS, settings,
+			sizeof(struct pyra_settings));
+	if (retval)
+		return retval;
+	return pyra_receive_control_status(usb_dev);
 }
 
 static ssize_t pyra_sysfs_read_profilex_settings(struct file *fp,
@@ -521,21 +451,16 @@
 static int pyra_init_pyra_device_struct(struct usb_device *usb_dev,
 		struct pyra_device *pyra)
 {
-	struct pyra_info *info;
+	struct pyra_info info;
 	int retval, i;
 
 	mutex_init(&pyra->pyra_lock);
 
-	info = kmalloc(sizeof(struct pyra_info), GFP_KERNEL);
-	if (!info)
-		return -ENOMEM;
-	retval = pyra_get_info(usb_dev, info);
-	if (retval) {
-		kfree(info);
+	retval = pyra_get_info(usb_dev, &info);
+	if (retval)
 		return retval;
-	}
-	pyra->firmware_version = info->firmware_version;
-	kfree(info);
+
+	pyra->firmware_version = info.firmware_version;
 
 	retval = pyra_get_settings(usb_dev, &pyra->settings);
 	if (retval)
@@ -581,7 +506,8 @@
 			goto exit_free;
 		}
 
-		retval = roccat_connect(pyra_class, hdev);
+		retval = roccat_connect(pyra_class, hdev,
+				sizeof(struct pyra_roccat_report));
 		if (retval < 0) {
 			hid_err(hdev, "couldn't init char dev\n");
 		} else {
@@ -685,8 +611,7 @@
 		roccat_report.value = button_event->data1;
 		roccat_report.key = 0;
 		roccat_report_event(pyra->chrdev_minor,
-				(uint8_t const *)&roccat_report,
-				sizeof(struct pyra_roccat_report));
+				(uint8_t const *)&roccat_report);
 		break;
 	case PYRA_MOUSE_EVENT_BUTTON_TYPE_MACRO:
 	case PYRA_MOUSE_EVENT_BUTTON_TYPE_SHORTCUT:
@@ -700,8 +625,7 @@
 			 */
 			roccat_report.value = pyra->actual_profile + 1;
 			roccat_report_event(pyra->chrdev_minor,
-					(uint8_t const *)&roccat_report,
-					sizeof(struct pyra_roccat_report));
+					(uint8_t const *)&roccat_report);
 		}
 		break;
 	}
@@ -728,7 +652,8 @@
 static const struct hid_device_id pyra_devices[] = {
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT,
 			USB_DEVICE_ID_ROCCAT_PYRA_WIRED) },
-	/* TODO add USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS after testing */
+	{ HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT,
+			USB_DEVICE_ID_ROCCAT_PYRA_WIRELESS) },
 	{ }
 };
 
@@ -761,8 +686,8 @@
 
 static void __exit pyra_exit(void)
 {
-	class_destroy(pyra_class);
 	hid_unregister_driver(&pyra_driver);
+	class_destroy(pyra_class);
 }
 
 module_init(pyra_init);
diff -druN linux-libre-2.6.38-gnu/drivers/hid/hid-sony.c linux-libre-2.6.39-gnu/drivers/hid/hid-sony.c
--- linux-libre-2.6.38-gnu/drivers/hid/hid-sony.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/hid-sony.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,6 +46,16 @@
 	return rdesc;
 }
 
+/*
+ * The Sony Sixaxis does not handle HID Output Reports on the Interrupt EP
+ * like it should according to usbhid/hid-core.c::usbhid_output_raw_report()
+ * so we need to override that forcing HID Output Reports on the Control EP.
+ *
+ * There is also another issue about HID Output Reports via USB, the Sixaxis
+ * does not want the report_id as part of the data packet, so we have to
+ * discard buf[0] when sending the actual control message, even for numbered
+ * reports, humpf!
+ */
 static int sixaxis_usb_output_raw_report(struct hid_device *hid, __u8 *buf,
 		size_t count, unsigned char report_type)
 {
@@ -55,6 +65,12 @@
 	int report_id = buf[0];
 	int ret;
 
+	if (report_type == HID_OUTPUT_REPORT) {
+		/* Don't send the Report ID */
+		buf++;
+		count--;
+	}
+
 	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
 		HID_REQ_SET_REPORT,
 		USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
@@ -62,6 +78,10 @@
 		interface->desc.bInterfaceNumber, buf, count,
 		USB_CTRL_SET_TIMEOUT);
 
+	/* Count also the Report ID, in case of an Output report. */
+	if (ret > 0 && report_type == HID_OUTPUT_REPORT)
+		ret++;
+
 	return ret;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/hid/Kconfig linux-libre-2.6.39-gnu/drivers/hid/Kconfig
--- linux-libre-2.6.38-gnu/drivers/hid/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -68,9 +68,15 @@
 	---help---
 	Support for A4 tech X5 and WOP-35 / Trust 450L mice.
 
-config HID_ACRUX_FF
-	tristate "ACRUX force feedback"
+config HID_ACRUX
+	tristate "ACRUX game controller support"
 	depends on USB_HID
+	---help---
+	Say Y here if you want to enable support for ACRUX game controllers.
+
+config HID_ACRUX_FF
+	tristate "ACRUX force feedback support"
+	depends on HID_ACRUX
 	select INPUT_FF_MEMLESS
 	---help---
 	Say Y here if you want to enable force feedback support for ACRUX
@@ -140,7 +146,12 @@
 	tristate "DragonRise Inc. game controller"
 	depends on USB_HID
 	---help---
-	Say Y here if you have DragonRise Inc.game controllers.
+	Say Y here if you have DragonRise Inc. game controllers.
+	These might be branded as:
+	- Tesun USB-703
+	- Media-tech MT1504 "Rogue"
+	- DVTech JS19 "Gear"
+	- Defender Game Master
 
 config DRAGONRISE_FF
 	bool "DragonRise Inc. force feedback"
@@ -160,13 +171,6 @@
 	Currently the following devices are known to be supported:
 	 - Trio Linker Plus II
 
-config HID_EGALAX
-	tristate "eGalax multi-touch panel"
-	depends on USB_HID
-	---help---
-	Support for the eGalax dual-touch panels, including the
-	Joojoo and Wetab tablets.
-
 config HID_ELECOM
 	tristate "ELECOM BM084 bluetooth mouse"
 	depends on BT_HIDP
@@ -180,6 +184,14 @@
 	---help---
 	Support for Ezkey BTC 8193 keyboard.
 
+config HID_KEYTOUCH
+	tristate "Keytouch HID devices"
+	depends on USB_HID
+	---help---
+	Support for Keytouch HID devices not fully compliant with
+	the specification. Currently supported:
+		- Keytouch IEC 60945
+
 config HID_KYE
 	tristate "Kye/Genius Ergo Mouse" if EXPERT
 	depends on USB_HID
@@ -218,6 +230,12 @@
 	---help---
 	Support for Kensington Slimblade Trackball.
 
+config HID_LCPOWER
+	tristate "LC-Power"
+	depends on USB_HID
+	---help---
+	Support for LC-Power RC1000MCE RF remote control.
+
 config HID_LOGITECH
 	tristate "Logitech devices" if EXPERT
 	depends on USB_HID
@@ -304,8 +322,11 @@
 	  Say Y here if you have one of the following devices:
 	  - Cypress TrueTouch panels
 	  - Hanvon dual touch panels
+	  - IrTouch Infrared USB panels
 	  - Pixcir dual touch panels
 	  - 'Sensing Win7-TwoFinger' panel by GeneralTouch
+          - eGalax dual-touch panels, including the
+	    Joojoo and Wetab tablets
 
 	  If unsure, say N.
 
@@ -319,10 +340,17 @@
 	Support for N-Trig touch screen.
 
 config HID_ORTEK
-	tristate "Ortek WKB-2000 wireless keyboard and mouse trackpad"
+	tristate "Ortek PKB-1700/WKB-2000/Skycable wireless keyboard and mouse trackpad"
 	depends on USB_HID
 	---help---
-	Support for Ortek WKB-2000 wireless keyboard + mouse trackpad.
+	There are certain devices which have LogicalMaximum wrong in the keyboard
+	usage page of their report descriptor. The most prevailing ones so far
+	are manufactured by Ortek, thus the name of the driver. Currently
+	supported devices by this driver are
+
+	   - Ortek PKB-1700
+	   - Ortek WKB-2000
+	   - Skycable wireless presenter
 
 config HID_PANTHERLORD
 	tristate "Pantherlord/GreenAsia game controller"
@@ -417,10 +445,22 @@
 	Say Y here if you have a Roccat mouse or keyboard and want OSD or
 	macro execution support.
 
+config HID_ROCCAT_COMMON
+	tristate
+
+config HID_ROCCAT_ARVO
+	tristate "Roccat Arvo keyboard support"
+	depends on USB_HID
+	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
+	---help---
+	Support for Roccat Arvo keyboard.
+
 config HID_ROCCAT_KONE
 	tristate "Roccat Kone Mouse support"
 	depends on USB_HID
 	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat Kone mouse.
 
@@ -428,13 +468,23 @@
 	tristate "Roccat Kone[+] mouse support"
 	depends on USB_HID
 	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat Kone[+] mouse.
 
+config HID_ROCCAT_KOVAPLUS
+	tristate "Roccat Kova[+] mouse support"
+	depends on USB_HID
+	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
+	---help---
+	Support for Roccat Kova[+] mouse.
+
 config HID_ROCCAT_PYRA
 	tristate "Roccat Pyra mouse support"
 	depends on USB_HID
 	select HID_ROCCAT
+	select HID_ROCCAT_COMMON
 	---help---
 	Support for Roccat Pyra mouse.
 
diff -druN linux-libre-2.6.38-gnu/drivers/hid/Makefile linux-libre-2.6.39-gnu/drivers/hid/Makefile
--- linux-libre-2.6.38-gnu/drivers/hid/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -27,21 +27,22 @@
 
 obj-$(CONFIG_HID_3M_PCT)	+= hid-3m-pct.o
 obj-$(CONFIG_HID_A4TECH)	+= hid-a4tech.o
-obj-$(CONFIG_HID_ACRUX_FF)	+= hid-axff.o
+obj-$(CONFIG_HID_ACRUX)		+= hid-axff.o
 obj-$(CONFIG_HID_APPLE)		+= hid-apple.o
 obj-$(CONFIG_HID_BELKIN)	+= hid-belkin.o
 obj-$(CONFIG_HID_CANDO)		+= hid-cando.o
 obj-$(CONFIG_HID_CHERRY)	+= hid-cherry.o
 obj-$(CONFIG_HID_CHICONY)	+= hid-chicony.o
 obj-$(CONFIG_HID_CYPRESS)	+= hid-cypress.o
-obj-$(CONFIG_HID_DRAGONRISE)	+= hid-drff.o
+obj-$(CONFIG_HID_DRAGONRISE)	+= hid-dr.o
 obj-$(CONFIG_HID_EMS_FF)	+= hid-emsff.o
-obj-$(CONFIG_HID_EGALAX)	+= hid-egalax.o
 obj-$(CONFIG_HID_ELECOM)	+= hid-elecom.o
 obj-$(CONFIG_HID_EZKEY)		+= hid-ezkey.o
 obj-$(CONFIG_HID_GYRATION)	+= hid-gyration.o
 obj-$(CONFIG_HID_KENSINGTON)	+= hid-kensington.o
+obj-$(CONFIG_HID_KEYTOUCH)	+= hid-keytouch.o
 obj-$(CONFIG_HID_KYE)		+= hid-kye.o
+obj-$(CONFIG_HID_LCPOWER)       += hid-lcpower.o
 obj-$(CONFIG_HID_LOGITECH)	+= hid-logitech.o
 obj-$(CONFIG_HID_MAGICMOUSE)    += hid-magicmouse.o
 obj-$(CONFIG_HID_MICROSOFT)	+= hid-microsoft.o
@@ -56,8 +57,11 @@
 obj-$(CONFIG_HID_PETALYNX)	+= hid-petalynx.o
 obj-$(CONFIG_HID_PICOLCD)	+= hid-picolcd.o
 obj-$(CONFIG_HID_ROCCAT)	+= hid-roccat.o
+obj-$(CONFIG_HID_ROCCAT_COMMON)	+= hid-roccat-common.o
+obj-$(CONFIG_HID_ROCCAT_ARVO)	+= hid-roccat-arvo.o
 obj-$(CONFIG_HID_ROCCAT_KONE)	+= hid-roccat-kone.o
 obj-$(CONFIG_HID_ROCCAT_KONEPLUS)	+= hid-roccat-koneplus.o
+obj-$(CONFIG_HID_ROCCAT_KOVAPLUS)	+= hid-roccat-kovaplus.o
 obj-$(CONFIG_HID_ROCCAT_PYRA)	+= hid-roccat-pyra.o
 obj-$(CONFIG_HID_SAMSUNG)	+= hid-samsung.o
 obj-$(CONFIG_HID_SMARTJOYPLUS)	+= hid-sjoy.o
diff -druN linux-libre-2.6.38-gnu/drivers/hid/usbhid/hid-core.c linux-libre-2.6.39-gnu/drivers/hid/usbhid/hid-core.c
--- linux-libre-2.6.38-gnu/drivers/hid/usbhid/hid-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/usbhid/hid-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -799,6 +799,40 @@
 	return 0;
 }
 
+static int usbhid_get_raw_report(struct hid_device *hid,
+		unsigned char report_number, __u8 *buf, size_t count,
+		unsigned char report_type)
+{
+	struct usbhid_device *usbhid = hid->driver_data;
+	struct usb_device *dev = hid_to_usb_dev(hid);
+	struct usb_interface *intf = usbhid->intf;
+	struct usb_host_interface *interface = intf->cur_altsetting;
+	int skipped_report_id = 0;
+	int ret;
+
+	/* Byte 0 is the report number. Report data starts at byte 1.*/
+	buf[0] = report_number;
+	if (report_number == 0x0) {
+		/* Offset the return buffer by 1, so that the report ID
+		   will remain in byte 0. */
+		buf++;
+		count--;
+		skipped_report_id = 1;
+	}
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+		HID_REQ_GET_REPORT,
+		USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE,
+		((report_type + 1) << 8) | report_number,
+		interface->desc.bInterfaceNumber, buf, count,
+		USB_CTRL_SET_TIMEOUT);
+
+	/* count also the report id */
+	if (ret > 0 && skipped_report_id)
+		ret++;
+
+	return ret;
+}
+
 static int usbhid_output_raw_report(struct hid_device *hid, __u8 *buf, size_t count,
 		unsigned char report_type)
 {
@@ -1139,6 +1173,7 @@
 
 	usb_set_intfdata(intf, hid);
 	hid->ll_driver = &usb_hid_driver;
+	hid->hid_get_raw_report = usbhid_get_raw_report;
 	hid->hid_output_raw_report = usbhid_output_raw_report;
 	hid->ff_init = hid_pidff_init;
 #ifdef CONFIG_USB_HIDDEV
diff -druN linux-libre-2.6.38-gnu/drivers/hid/usbhid/hid-quirks.c linux-libre-2.6.39-gnu/drivers/hid/usbhid/hid-quirks.c
--- linux-libre-2.6.38-gnu/drivers/hid/usbhid/hid-quirks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hid/usbhid/hid-quirks.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,6 +59,7 @@
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_COMBATSTICK, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_ECLIPSE_YOKE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_FLIGHT_SIM_YOKE, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_THROTTLE, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_PRO_PEDALS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_3AXIS_5BUTTON_STICK, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/abituguru3.c linux-libre-2.6.39-gnu/drivers/hwmon/abituguru3.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/abituguru3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/abituguru3.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
     abituguru3.c
 
-    Copyright (c) 2006-2008 Hans de Goede <j.w.r.degoede@hhs.nl>
+    Copyright (c) 2006-2008 Hans de Goede <hdegoede@redhat.com>
     Copyright (c) 2008 Alistair John Strachan <alistair@devzero.co.uk>
 
     This program is free software; you can redistribute it and/or modify
@@ -151,7 +151,7 @@
 	/* Pointer to the sensors info for the detected motherboard */
 	const struct abituguru3_sensor_info *sensors;
 
-	/* The abituguru3 supports upto 48 sensors, and thus has registers
+	/* The abituguru3 supports up to 48 sensors, and thus has registers
 	   sets for 48 sensors, for convienence reasons / simplicity of the
 	   code we always read and store all registers for all 48 sensors */
 
@@ -1266,7 +1266,7 @@
 	platform_driver_unregister(&abituguru3_driver);
 }
 
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
 MODULE_LICENSE("GPL");
 
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/abituguru.c linux-libre-2.6.39-gnu/drivers/hwmon/abituguru.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/abituguru.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/abituguru.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
-    abituguru.c Copyright (c) 2005-2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+    abituguru.c Copyright (c) 2005-2006 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
@@ -1422,7 +1422,7 @@
 	   at DATA and 0xAC, when this driver has already been loaded once
 	   DATA will hold 0x08. For most uGuru's CMD will hold 0xAC in either
 	   scenario but some will hold 0x00.
-	   Some uGuru's initally hold 0x09 at DATA and will only hold 0x08
+	   Some uGuru's initially hold 0x09 at DATA and will only hold 0x08
 	   after reading CMD first, so CMD must be read first! */
 	u8 cmd_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_CMD);
 	u8 data_val = inb_p(ABIT_UGURU_BASE + ABIT_UGURU_DATA);
@@ -1505,7 +1505,7 @@
 	platform_driver_unregister(&abituguru_driver);
 }
 
-MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
 MODULE_DESCRIPTION("Abit uGuru Sensor device");
 MODULE_LICENSE("GPL");
 
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/adm1026.c linux-libre-2.6.39-gnu/drivers/hwmon/adm1026.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/adm1026.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/adm1026.c	2011-05-19 00:06:34.000000000 -0400
@@ -175,7 +175,7 @@
  * these macros are called: arguments may be evaluated more than once.
  */
 
-/* IN are scaled acording to built-in resistors.  These are the
+/* IN are scaled according to built-in resistors.  These are the
  *   voltages corresponding to 3/4 of full scale (192 or 0xc0)
  *   NOTE: The -12V input needs an additional factor to account
  *      for the Vref pullup resistor.
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/ads1015.c linux-libre-2.6.39-gnu/drivers/hwmon/ads1015.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/ads1015.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/ads1015.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,337 @@
+/*
+ * ads1015.c - lm_sensors driver for ads1015 12-bit 4-input ADC
+ * (C) Copyright 2010
+ * Dirk Eibach, Guntermann & Drunck GmbH <eibach@gdsys.de>
+ *
+ * Based on the ads7828 driver by Steve Hardy.
+ *
+ * Datasheet available at: http://focus.ti.com/lit/ds/symlink/ads1015.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/of.h>
+
+#include <linux/i2c/ads1015.h>
+
+/* ADS1015 registers */
+enum {
+	ADS1015_CONVERSION = 0,
+	ADS1015_CONFIG = 1,
+};
+
+/* PGA fullscale voltages in mV */
+static const unsigned int fullscale_table[8] = {
+	6144, 4096, 2048, 1024, 512, 256, 256, 256 };
+
+/* Data rates in samples per second */
+static const unsigned int data_rate_table[8] = {
+	128, 250, 490, 920, 1600, 2400, 3300, 3300 };
+
+#define ADS1015_DEFAULT_CHANNELS 0xff
+#define ADS1015_DEFAULT_PGA 2
+#define ADS1015_DEFAULT_DATA_RATE 4
+
+struct ads1015_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock; /* mutex protect updates */
+	struct ads1015_channel_data channel_data[ADS1015_CHANNELS];
+};
+
+static s32 ads1015_read_reg(struct i2c_client *client, unsigned int reg)
+{
+	s32 data = i2c_smbus_read_word_data(client, reg);
+
+	return (data < 0) ? data : swab16(data);
+}
+
+static s32 ads1015_write_reg(struct i2c_client *client, unsigned int reg,
+			     u16 val)
+{
+	return i2c_smbus_write_word_data(client, reg, swab16(val));
+}
+
+static int ads1015_read_value(struct i2c_client *client, unsigned int channel,
+			      int *value)
+{
+	u16 config;
+	s16 conversion;
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	unsigned int pga = data->channel_data[channel].pga;
+	int fullscale;
+	unsigned int data_rate = data->channel_data[channel].data_rate;
+	unsigned int conversion_time_ms;
+	int res;
+
+	mutex_lock(&data->update_lock);
+
+	/* get channel parameters */
+	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	if (res < 0)
+		goto err_unlock;
+	config = res;
+	fullscale = fullscale_table[pga];
+	conversion_time_ms = DIV_ROUND_UP(1000, data_rate_table[data_rate]);
+
+	/* setup and start single conversion */
+	config &= 0x001f;
+	config |= (1 << 15) | (1 << 8);
+	config |= (channel & 0x0007) << 12;
+	config |= (pga & 0x0007) << 9;
+	config |= (data_rate & 0x0007) << 5;
+
+	res = ads1015_write_reg(client, ADS1015_CONFIG, config);
+	if (res < 0)
+		goto err_unlock;
+
+	/* wait until conversion finished */
+	msleep(conversion_time_ms);
+	res = ads1015_read_reg(client, ADS1015_CONFIG);
+	if (res < 0)
+		goto err_unlock;
+	config = res;
+	if (!(config & (1 << 15))) {
+		/* conversion not finished in time */
+		res = -EIO;
+		goto err_unlock;
+	}
+
+	res = ads1015_read_reg(client, ADS1015_CONVERSION);
+	if (res < 0)
+		goto err_unlock;
+	conversion = res;
+
+	mutex_unlock(&data->update_lock);
+
+	*value = DIV_ROUND_CLOSEST(conversion * fullscale, 0x7ff0);
+
+	return 0;
+
+err_unlock:
+	mutex_unlock(&data->update_lock);
+	return res;
+}
+
+/* sysfs callback function */
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+	char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	int in;
+	int res;
+
+	res = ads1015_read_value(client, attr->index, &in);
+
+	return (res < 0) ? res : sprintf(buf, "%d\n", in);
+}
+
+static const struct sensor_device_attribute ads1015_in[] = {
+	SENSOR_ATTR(in0_input, S_IRUGO, show_in, NULL, 0),
+	SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
+	SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
+	SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
+	SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
+	SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
+	SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
+	SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
+};
+
+/*
+ * Driver interface
+ */
+
+static int ads1015_remove(struct i2c_client *client)
+{
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	int k;
+
+	hwmon_device_unregister(data->hwmon_dev);
+	for (k = 0; k < ADS1015_CHANNELS; ++k)
+		device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
+	kfree(data);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static int ads1015_get_channels_config_of(struct i2c_client *client)
+{
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	struct device_node *node;
+
+	if (!client->dev.of_node
+	    || !of_get_next_child(client->dev.of_node, NULL))
+		return -EINVAL;
+
+	for_each_child_of_node(client->dev.of_node, node) {
+		const __be32 *property;
+		int len;
+		unsigned int channel;
+		unsigned int pga = ADS1015_DEFAULT_PGA;
+		unsigned int data_rate = ADS1015_DEFAULT_DATA_RATE;
+
+		property = of_get_property(node, "reg", &len);
+		if (!property || len != sizeof(int)) {
+			dev_err(&client->dev, "invalid reg on %s\n",
+				node->full_name);
+			continue;
+		}
+
+		channel = be32_to_cpup(property);
+		if (channel > ADS1015_CHANNELS) {
+			dev_err(&client->dev,
+				"invalid channel index %d on %s\n",
+				channel, node->full_name);
+			continue;
+		}
+
+		property = of_get_property(node, "ti,gain", &len);
+		if (property && len == sizeof(int)) {
+			pga = be32_to_cpup(property);
+			if (pga > 6) {
+				dev_err(&client->dev,
+					"invalid gain on %s\n",
+					node->full_name);
+			}
+		}
+
+		property = of_get_property(node, "ti,datarate", &len);
+		if (property && len == sizeof(int)) {
+			data_rate = be32_to_cpup(property);
+			if (data_rate > 7) {
+				dev_err(&client->dev,
+					"invalid data_rate on %s\n",
+					node->full_name);
+			}
+		}
+
+		data->channel_data[channel].enabled = true;
+		data->channel_data[channel].pga = pga;
+		data->channel_data[channel].data_rate = data_rate;
+	}
+
+	return 0;
+}
+#endif
+
+static void ads1015_get_channels_config(struct i2c_client *client)
+{
+	unsigned int k;
+	struct ads1015_data *data = i2c_get_clientdata(client);
+	struct ads1015_platform_data *pdata = dev_get_platdata(&client->dev);
+
+	/* prefer platform data */
+	if (pdata) {
+		memcpy(data->channel_data, pdata->channel_data,
+		       sizeof(data->channel_data));
+		return;
+	}
+
+#ifdef CONFIG_OF
+	if (!ads1015_get_channels_config_of(client))
+		return;
+#endif
+
+	/* fallback on default configuration */
+	for (k = 0; k < ADS1015_CHANNELS; ++k) {
+		data->channel_data[k].enabled = true;
+		data->channel_data[k].pga = ADS1015_DEFAULT_PGA;
+		data->channel_data[k].data_rate = ADS1015_DEFAULT_DATA_RATE;
+	}
+}
+
+static int ads1015_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct ads1015_data *data;
+	int err;
+	unsigned int k;
+
+	data = kzalloc(sizeof(struct ads1015_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* build sysfs attribute group */
+	ads1015_get_channels_config(client);
+	for (k = 0; k < ADS1015_CHANNELS; ++k) {
+		if (!data->channel_data[k].enabled)
+			continue;
+		err = device_create_file(&client->dev, &ads1015_in[k].dev_attr);
+		if (err)
+			goto exit_free;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto exit_remove;
+	}
+
+	return 0;
+
+exit_remove:
+	for (k = 0; k < ADS1015_CHANNELS; ++k)
+		device_remove_file(&client->dev, &ads1015_in[k].dev_attr);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static const struct i2c_device_id ads1015_id[] = {
+	{ "ads1015", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ads1015_id);
+
+static struct i2c_driver ads1015_driver = {
+	.driver = {
+		.name = "ads1015",
+	},
+	.probe = ads1015_probe,
+	.remove = ads1015_remove,
+	.id_table = ads1015_id,
+};
+
+static int __init sensors_ads1015_init(void)
+{
+	return i2c_add_driver(&ads1015_driver);
+}
+
+static void __exit sensors_ads1015_exit(void)
+{
+	i2c_del_driver(&ads1015_driver);
+}
+
+MODULE_AUTHOR("Dirk Eibach <eibach@gdsys.de>");
+MODULE_DESCRIPTION("ADS1015 driver");
+MODULE_LICENSE("GPL");
+
+module_init(sensors_ads1015_init);
+module_exit(sensors_ads1015_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/f71882fg.c linux-libre-2.6.39-gnu/drivers/hwmon/f71882fg.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/f71882fg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/f71882fg.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /***************************************************************************
  *   Copyright (C) 2006 by Hans Edgington <hans@edgington.nl>              *
- *   Copyright (C) 2007-2009 Hans de Goede <hdegoede@redhat.com>           *
+ *   Copyright (C) 2007-2011 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  *
@@ -47,22 +47,25 @@
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
 
 #define SIO_FINTEK_ID		0x1934	/* Manufacturers ID */
+#define SIO_F71808E_ID		0x0901	/* Chipset ID */
 #define SIO_F71858_ID		0x0507  /* Chipset ID */
 #define SIO_F71862_ID		0x0601	/* Chipset ID */
+#define SIO_F71869_ID		0x0814	/* Chipset ID */
 #define SIO_F71882_ID		0x0541	/* Chipset ID */
 #define SIO_F71889_ID		0x0723	/* Chipset ID */
+#define SIO_F71889E_ID		0x0909	/* Chipset ID */
+#define SIO_F71889A_ID		0x1005	/* Chipset ID */
 #define SIO_F8000_ID		0x0581	/* Chipset ID */
+#define SIO_F81865_ID		0x0704	/* Chipset ID */
 
 #define REGION_LENGTH		8
 #define ADDR_REG_OFFSET		5
 #define DATA_REG_OFFSET		6
 
-#define F71882FG_REG_PECI		0x0A
-
-#define F71882FG_REG_IN_STATUS		0x12 /* f71882fg only */
-#define F71882FG_REG_IN_BEEP		0x13 /* f71882fg only */
+#define F71882FG_REG_IN_STATUS		0x12 /* f7188x only */
+#define F71882FG_REG_IN_BEEP		0x13 /* f7188x only */
 #define F71882FG_REG_IN(nr)		(0x20  + (nr))
-#define F71882FG_REG_IN1_HIGH		0x32 /* f71882fg only */
+#define F71882FG_REG_IN1_HIGH		0x32 /* f7188x only */
 
 #define F71882FG_REG_FAN(nr)		(0xA0 + (16 * (nr)))
 #define F71882FG_REG_FAN_TARGET(nr)	(0xA2 + (16 * (nr)))
@@ -86,26 +89,103 @@
 
 #define F71882FG_REG_FAN_HYST(nr)	(0x98 + (nr))
 
+#define F71882FG_REG_FAN_FAULT_T	0x9F
+#define F71882FG_FAN_NEG_TEMP_EN	0x20
+#define F71882FG_FAN_PROG_SEL		0x80
+
 #define F71882FG_REG_POINT_PWM(pwm, point)	(0xAA + (point) + (16 * (pwm)))
 #define F71882FG_REG_POINT_TEMP(pwm, point)	(0xA6 + (point) + (16 * (pwm)))
 #define F71882FG_REG_POINT_MAPPING(nr)		(0xAF + 16 * (nr))
 
 #define	F71882FG_REG_START		0x01
 
+#define F71882FG_MAX_INS		9
+
 #define FAN_MIN_DETECT			366 /* Lowest detectable fanspeed */
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
-enum chips { f71858fg, f71862fg, f71882fg, f71889fg, f8000 };
+enum chips { f71808e, f71858fg, f71862fg, f71869, f71882fg, f71889fg,
+	     f71889ed, f71889a, f8000, f81865f };
 
 static const char *f71882fg_names[] = {
+	"f71808e",
 	"f71858fg",
 	"f71862fg",
+	"f71869", /* Both f71869f and f71869e, reg. compatible and same id */
 	"f71882fg",
-	"f71889fg",
+	"f71889fg", /* f81801u too, same id */
+	"f71889ed",
+	"f71889a",
 	"f8000",
+	"f81865f",
+};
+
+static const char f71882fg_has_in[][F71882FG_MAX_INS] = {
+	[f71808e]	= { 1, 1, 1, 1, 1, 1, 0, 1, 1 },
+	[f71858fg]	= { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
+	[f71862fg]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+	[f71869]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+	[f71882fg]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+	[f71889fg]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+	[f71889ed]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+	[f71889a]	= { 1, 1, 1, 1, 1, 1, 1, 1, 1 },
+	[f8000]		= { 1, 1, 1, 0, 0, 0, 0, 0, 0 },
+	[f81865f]	= { 1, 1, 1, 1, 1, 1, 1, 0, 0 },
+};
+
+static const char f71882fg_has_in1_alarm[] = {
+	[f71808e]	= 0,
+	[f71858fg]	= 0,
+	[f71862fg]	= 0,
+	[f71869]	= 0,
+	[f71882fg]	= 1,
+	[f71889fg]	= 1,
+	[f71889ed]	= 1,
+	[f71889a]	= 1,
+	[f8000]		= 0,
+	[f81865f]	= 1,
+};
+
+static const char f71882fg_has_beep[] = {
+	[f71808e]	= 0,
+	[f71858fg]	= 0,
+	[f71862fg]	= 1,
+	[f71869]	= 1,
+	[f71882fg]	= 1,
+	[f71889fg]	= 1,
+	[f71889ed]	= 1,
+	[f71889a]	= 1,
+	[f8000]		= 0,
+	[f81865f]	= 1,
+};
+
+static const char f71882fg_nr_fans[] = {
+	[f71808e]	= 3,
+	[f71858fg]	= 3,
+	[f71862fg]	= 3,
+	[f71869]	= 3,
+	[f71882fg]	= 4,
+	[f71889fg]	= 3,
+	[f71889ed]	= 3,
+	[f71889a]	= 3,
+	[f8000]		= 3,
+	[f81865f]	= 2,
+};
+
+static const char f71882fg_nr_temps[] = {
+	[f71808e]	= 2,
+	[f71858fg]	= 3,
+	[f71862fg]	= 3,
+	[f71869]	= 3,
+	[f71882fg]	= 3,
+	[f71889fg]	= 3,
+	[f71889ed]	= 3,
+	[f71889a]	= 3,
+	[f8000]		= 3,
+	[f81865f]	= 2,
 };
 
 static struct platform_device *f71882fg_pdev;
@@ -129,11 +209,12 @@
 	struct mutex update_lock;
 	int temp_start;			/* temp numbering start (0 or 1) */
 	char valid;			/* !=0 if following fields are valid */
+	char auto_point_temp_signed;
 	unsigned long last_updated;	/* In jiffies */
 	unsigned long last_limits;	/* In jiffies */
 
 	/* Register Values */
-	u8	in[9];
+	u8	in[F71882FG_MAX_INS];
 	u8	in1_max;
 	u8	in_status;
 	u8	in_beep;
@@ -142,7 +223,7 @@
 	u16	fan_full_speed[4];
 	u8	fan_status;
 	u8	fan_beep;
-	/* Note: all models have only 3 temperature channels, but on some
+	/* Note: all models have max 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 */
 	u16	temp[4];
@@ -262,13 +343,9 @@
 
 static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
-/* Temp and in attr for the f71858fg, the f71858fg is special as it
-   has its temperature indexes start at 0 (the others start at 1) and
-   it only has 3 voltage inputs */
-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),
+/* Temp attr for the f71858fg, the f71858fg is special as it has its
+   temperature indexes start at 0 (the others start at 1) */
+static struct sensor_device_attribute_2 f71858fg_temp_attr[] = {
 	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),
@@ -292,7 +369,6 @@
 	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,
@@ -308,17 +384,8 @@
 	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
 };
 
-/* Temp and in attr common to the f71862fg, f71882fg and f71889fg */
-static struct sensor_device_attribute_2 fxxxx_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(in3_input, S_IRUGO, show_in, NULL, 0, 3),
-	SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
-	SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
-	SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
-	SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
-	SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+/* Temp attr for the standard models */
+static struct sensor_device_attribute_2 fxxxx_temp_attr[3][9] = { {
 	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 1),
 	SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 1),
@@ -328,17 +395,14 @@
 	   the max and crit alarms separately and lm_sensors v2 depends on the
 	   presence of temp#_alarm files. The same goes for temp2/3 _alarm. */
 	SENSOR_ATTR_2(temp1_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 1),
-	SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 1),
 	SENSOR_ATTR_2(temp1_crit, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 1),
 	SENSOR_ATTR_2(temp1_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 1),
 	SENSOR_ATTR_2(temp1_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 5),
-	SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 5),
 	SENSOR_ATTR_2(temp1_type, S_IRUGO, show_temp_type, NULL, 0, 1),
 	SENSOR_ATTR_2(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0, 1),
+}, {
 	SENSOR_ATTR_2(temp2_input, S_IRUGO, show_temp, NULL, 0, 2),
 	SENSOR_ATTR_2(temp2_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 2),
@@ -346,17 +410,14 @@
 		store_temp_max_hyst, 0, 2),
 	/* Should be temp2_max_alarm, see temp1_alarm note */
 	SENSOR_ATTR_2(temp2_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 2),
-	SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 2),
 	SENSOR_ATTR_2(temp2_crit, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 2),
 	SENSOR_ATTR_2(temp2_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 2),
 	SENSOR_ATTR_2(temp2_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 6),
-	SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 6),
 	SENSOR_ATTR_2(temp2_type, S_IRUGO, show_temp_type, NULL, 0, 2),
 	SENSOR_ATTR_2(temp2_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
+}, {
 	SENSOR_ATTR_2(temp3_input, S_IRUGO, show_temp, NULL, 0, 3),
 	SENSOR_ATTR_2(temp3_max, S_IRUGO|S_IWUSR, show_temp_max,
 		store_temp_max, 0, 3),
@@ -364,37 +425,39 @@
 		store_temp_max_hyst, 0, 3),
 	/* Should be temp3_max_alarm, see temp1_alarm note */
 	SENSOR_ATTR_2(temp3_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 3),
-	SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 3),
 	SENSOR_ATTR_2(temp3_crit, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 3),
 	SENSOR_ATTR_2(temp3_crit_hyst, S_IRUGO, show_temp_crit_hyst, NULL,
 		0, 3),
 	SENSOR_ATTR_2(temp3_crit_alarm, S_IRUGO, show_temp_alarm, NULL, 0, 7),
-	SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
-		store_temp_beep, 0, 7),
 	SENSOR_ATTR_2(temp3_type, S_IRUGO, show_temp_type, NULL, 0, 3),
 	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 3),
-};
+} };
 
-/* For models with in1 alarm capability */
-static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
-	SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
-		0, 1),
-	SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
-		0, 1),
-	SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
-};
+/* Temp attr for models which can beep on temp alarm */
+static struct sensor_device_attribute_2 fxxxx_temp_beep_attr[3][2] = { {
+	SENSOR_ATTR_2(temp1_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 1),
+	SENSOR_ATTR_2(temp1_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 5),
+}, {
+	SENSOR_ATTR_2(temp2_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 2),
+	SENSOR_ATTR_2(temp2_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 6),
+}, {
+	SENSOR_ATTR_2(temp3_max_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 3),
+	SENSOR_ATTR_2(temp3_crit_beep, S_IRUGO|S_IWUSR, show_temp_beep,
+		store_temp_beep, 0, 7),
+} };
 
-/* Temp and in attr for the f8000
+/* Temp attr for the f8000
    Note on the f8000 temp_ovt (crit) is used as max, and temp_high (max)
    is used as hysteresis value to clear alarms
    Also like the f71858fg its temperature indexes start at 0
  */
-static struct sensor_device_attribute_2 f8000_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),
+static struct sensor_device_attribute_2 f8000_temp_attr[] = {
 	SENSOR_ATTR_2(temp1_input, S_IRUGO, show_temp, NULL, 0, 0),
 	SENSOR_ATTR_2(temp1_max, S_IRUGO|S_IWUSR, show_temp_crit,
 		store_temp_crit, 0, 0),
@@ -408,7 +471,6 @@
 	SENSOR_ATTR_2(temp2_max_hyst, S_IRUGO|S_IWUSR, show_temp_max,
 		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,
@@ -419,6 +481,28 @@
 	SENSOR_ATTR_2(temp3_fault, S_IRUGO, show_temp_fault, NULL, 0, 2),
 };
 
+/* in attr for all models */
+static struct sensor_device_attribute_2 fxxxx_in_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(in3_input, S_IRUGO, show_in, NULL, 0, 3),
+	SENSOR_ATTR_2(in4_input, S_IRUGO, show_in, NULL, 0, 4),
+	SENSOR_ATTR_2(in5_input, S_IRUGO, show_in, NULL, 0, 5),
+	SENSOR_ATTR_2(in6_input, S_IRUGO, show_in, NULL, 0, 6),
+	SENSOR_ATTR_2(in7_input, S_IRUGO, show_in, NULL, 0, 7),
+	SENSOR_ATTR_2(in8_input, S_IRUGO, show_in, NULL, 0, 8),
+};
+
+/* For models with in1 alarm capability */
+static struct sensor_device_attribute_2 fxxxx_in1_alarm_attr[] = {
+	SENSOR_ATTR_2(in1_max, S_IRUGO|S_IWUSR, show_in_max, store_in_max,
+		0, 1),
+	SENSOR_ATTR_2(in1_beep, S_IRUGO|S_IWUSR, show_in_beep, store_in_beep,
+		0, 1),
+	SENSOR_ATTR_2(in1_alarm, S_IRUGO, show_in_alarm, NULL, 0, 1),
+};
+
 /* Fan / PWM attr common to all models */
 static struct sensor_device_attribute_2 fxxxx_fan_attr[4][6] = { {
 	SENSOR_ATTR_2(fan1_input, S_IRUGO, show_fan, NULL, 0, 0),
@@ -479,7 +563,7 @@
 };
 
 /* PWM attr for the f71862fg, fewer pwms and fewer zones per pwm than the
-   f71858fg / f71882fg / f71889fg */
+   standard models */
 static struct sensor_device_attribute_2 f71862fg_auto_pwm_attr[] = {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
@@ -548,7 +632,87 @@
 		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
 };
 
-/* PWM attr common to the f71858fg, f71882fg and f71889fg */
+/* PWM attr for the f71808e/f71869, almost identical to the f71862fg, but the
+   pwm setting when the temperature is above the pwmX_auto_point1_temp can be
+   programmed instead of being hardcoded to 0xff */
+static struct sensor_device_attribute_2 f71869_auto_pwm_attr[] = {
+	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_channel,
+		      store_pwm_auto_point_channel, 0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      1, 0),
+	SENSOR_ATTR_2(pwm1_auto_point3_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      4, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      3, 0),
+	SENSOR_ATTR_2(pwm1_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp_hyst,
+		      store_pwm_auto_point_temp_hyst,
+		      0, 0),
+	SENSOR_ATTR_2(pwm1_auto_point2_temp_hyst, S_IRUGO,
+		      show_pwm_auto_point_temp_hyst, NULL, 3, 0),
+
+	SENSOR_ATTR_2(pwm2_auto_channels_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_channel,
+		      store_pwm_auto_point_channel, 0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point1_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      1, 1),
+	SENSOR_ATTR_2(pwm2_auto_point3_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      4, 1),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      3, 1),
+	SENSOR_ATTR_2(pwm2_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp_hyst,
+		      store_pwm_auto_point_temp_hyst,
+		      0, 1),
+	SENSOR_ATTR_2(pwm2_auto_point2_temp_hyst, S_IRUGO,
+		      show_pwm_auto_point_temp_hyst, NULL, 3, 1),
+
+	SENSOR_ATTR_2(pwm3_auto_channels_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_channel,
+		      store_pwm_auto_point_channel, 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),
+	SENSOR_ATTR_2(pwm3_auto_point2_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      1, 2),
+	SENSOR_ATTR_2(pwm3_auto_point3_pwm, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_pwm, store_pwm_auto_point_pwm,
+		      4, 2),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      0, 2),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp, store_pwm_auto_point_temp,
+		      3, 2),
+	SENSOR_ATTR_2(pwm3_auto_point1_temp_hyst, S_IRUGO|S_IWUSR,
+		      show_pwm_auto_point_temp_hyst,
+		      store_pwm_auto_point_temp_hyst,
+		      0, 2),
+	SENSOR_ATTR_2(pwm3_auto_point2_temp_hyst, S_IRUGO,
+		      show_pwm_auto_point_temp_hyst, NULL, 3, 2),
+};
+
+/* PWM attr for the standard models */
 static struct sensor_device_attribute_2 fxxxx_auto_pwm_attr[4][14] = { {
 	SENSOR_ATTR_2(pwm1_auto_channels_temp, S_IRUGO|S_IWUSR,
 		      show_pwm_auto_point_channel,
@@ -943,16 +1107,16 @@
 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 == f71858fg || data->type == f8000) ? 3 : 9;
+	int nr_fans = f71882fg_nr_fans[data->type];
+	int nr_temps = f71882fg_nr_temps[data->type];
+	int nr, reg, point;
 
 	mutex_lock(&data->update_lock);
 
 	/* Update once every 60 seconds */
 	if (time_after(jiffies, data->last_limits + 60 * HZ) ||
 			!data->valid) {
-		if (data->type == f71882fg || data->type == f71889fg) {
+		if (f71882fg_has_in1_alarm[data->type]) {
 			data->in1_max =
 				f71882fg_read8(data, F71882FG_REG_IN1_HIGH);
 			data->in_beep =
@@ -960,7 +1124,8 @@
 		}
 
 		/* Get High & boundary temps*/
-		for (nr = data->temp_start; nr < 3 + data->temp_start; nr++) {
+		for (nr = data->temp_start; nr < nr_temps + data->temp_start;
+									nr++) {
 			data->temp_ovt[nr] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_OVT(nr));
 			data->temp_high[nr] = f71882fg_read8(data,
@@ -973,44 +1138,19 @@
 			data->temp_hyst[1] = f71882fg_read8(data,
 						F71882FG_REG_TEMP_HYST(1));
 		}
+		/* All but the f71858fg / f8000 have this register */
+		if ((data->type != f71858fg) && (data->type != f8000)) {
+			reg  = f71882fg_read8(data, F71882FG_REG_TEMP_TYPE);
+			data->temp_type[1] = (reg & 0x02) ? 2 : 4;
+			data->temp_type[2] = (reg & 0x04) ? 2 : 4;
+			data->temp_type[3] = (reg & 0x08) ? 2 : 4;
+		}
 
-		if (data->type == f71862fg || data->type == f71882fg ||
-		    data->type == f71889fg) {
+		if (f71882fg_has_beep[data->type]) {
 			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;
-			data->temp_type[3] = (reg & 0x08) ? 2 : 4;
-		}
-		/* Determine temp index 1 sensor type */
-		if (data->type == f71889fg) {
-			reg2 = f71882fg_read8(data, F71882FG_REG_START);
-			switch ((reg2 & 0x60) >> 5) {
-			case 0x00: /* BJT / Thermistor */
-				data->temp_type[1] = (reg & 0x02) ? 2 : 4;
-				break;
-			case 0x01: /* AMDSI */
-				data->temp_type[1] = 5;
-				break;
-			case 0x02: /* PECI */
-			case 0x03: /* Ibex Peak ?? Report as PECI for now */
-				data->temp_type[1] = 6;
-				break;
-			}
-		} else {
-			reg2 = f71882fg_read8(data, F71882FG_REG_PECI);
-			if ((reg2 & 0x03) == 0x01)
-				data->temp_type[1] = 6; /* PECI */
-			else if ((reg2 & 0x03) == 0x02)
-				data->temp_type[1] = 5; /* AMDSI */
-			else if (data->type == f71862fg ||
-				 data->type == f71882fg)
-				data->temp_type[1] = (reg & 0x02) ? 2 : 4;
-			else /* f71858fg and f8000 only support BJT */
-				data->temp_type[1] = 2;
 		}
 
 		data->pwm_enable = f71882fg_read8(data,
@@ -1025,8 +1165,8 @@
 			    f71882fg_read8(data,
 					   F71882FG_REG_POINT_MAPPING(nr));
 
-			if (data->type != f71862fg) {
-				int point;
+			switch (data->type) {
+			default:
 				for (point = 0; point < 5; point++) {
 					data->pwm_auto_point_pwm[nr][point] =
 						f71882fg_read8(data,
@@ -1039,7 +1179,14 @@
 							F71882FG_REG_POINT_TEMP
 							(nr, point));
 				}
-			} else {
+				break;
+			case f71808e:
+			case f71869:
+				data->pwm_auto_point_pwm[nr][0] =
+					f71882fg_read8(data,
+						F71882FG_REG_POINT_PWM(nr, 0));
+				/* Fall through */
+			case f71862fg:
 				data->pwm_auto_point_pwm[nr][1] =
 					f71882fg_read8(data,
 						F71882FG_REG_POINT_PWM
@@ -1056,6 +1203,7 @@
 					f71882fg_read8(data,
 						F71882FG_REG_POINT_TEMP
 						(nr, 3));
+				break;
 			}
 		}
 		data->last_limits = jiffies;
@@ -1067,7 +1215,8 @@
 						F71882FG_REG_TEMP_STATUS);
 		data->temp_diode_open = f71882fg_read8(data,
 						F71882FG_REG_TEMP_DIODE_OPEN);
-		for (nr = data->temp_start; nr < 3 + data->temp_start; nr++)
+		for (nr = data->temp_start; nr < nr_temps + data->temp_start;
+									nr++)
 			data->temp[nr] = f71882fg_read_temp(data, nr);
 
 		data->fan_status = f71882fg_read8(data,
@@ -1083,17 +1232,18 @@
 			data->pwm[nr] =
 			    f71882fg_read8(data, F71882FG_REG_PWM(nr));
 		}
-
 		/* The f8000 can monitor 1 more fan, but has no pwm for it */
 		if (data->type == f8000)
 			data->fan[3] = f71882fg_read16(data,
 						F71882FG_REG_FAN(3));
-		if (data->type == f71882fg || data->type == f71889fg)
+
+		if (f71882fg_has_in1_alarm[data->type])
 			data->in_status = f71882fg_read8(data,
 						F71882FG_REG_IN_STATUS);
-		for (nr = 0; nr < nr_ins; nr++)
-			data->in[nr] = f71882fg_read8(data,
-						F71882FG_REG_IN(nr));
+		for (nr = 0; nr < F71882FG_MAX_INS; nr++)
+			if (f71882fg_has_in[data->type][nr])
+				data->in[nr] = f71882fg_read8(data,
+							F71882FG_REG_IN(nr));
 
 		data->last_updated = jiffies;
 		data->valid = 1;
@@ -1882,7 +2032,7 @@
 
 	val /= 1000;
 
-	if (data->type == f71889fg)
+	if (data->auto_point_temp_signed)
 		val = SENSORS_LIMIT(val, -128, 127);
 	else
 		val = SENSORS_LIMIT(val, 0, 127);
@@ -1928,8 +2078,10 @@
 {
 	struct f71882fg_data *data;
 	struct f71882fg_sio_data *sio_data = pdev->dev.platform_data;
-	int err, i, nr_fans = (sio_data->type == f71882fg) ? 4 : 3;
-	u8 start_reg;
+	int nr_fans = f71882fg_nr_fans[sio_data->type];
+	int nr_temps = f71882fg_nr_temps[sio_data->type];
+	int err, i;
+	u8 start_reg, reg;
 
 	data = kzalloc(sizeof(struct f71882fg_data), GFP_KERNEL);
 	if (!data)
@@ -1968,37 +2120,73 @@
 				/* 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));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			else
 				err = f71882fg_create_sysfs_files(pdev,
-					f71858fg_in_temp_attr,
-					ARRAY_SIZE(f71858fg_in_temp_attr));
-			break;
-		case f71882fg:
-		case f71889fg:
-			err = f71882fg_create_sysfs_files(pdev,
-					fxxxx_in1_alarm_attr,
-					ARRAY_SIZE(fxxxx_in1_alarm_attr));
-			if (err)
-				goto exit_unregister_sysfs;
-			/* fall through! */
-		case f71862fg:
-			err = f71882fg_create_sysfs_files(pdev,
-					fxxxx_in_temp_attr,
-					ARRAY_SIZE(fxxxx_in_temp_attr));
+					f71858fg_temp_attr,
+					ARRAY_SIZE(f71858fg_temp_attr));
 			break;
 		case f8000:
 			err = f71882fg_create_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			break;
+		default:
+			err = f71882fg_create_sysfs_files(pdev,
+				&fxxxx_temp_attr[0][0],
+				ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
 		}
 		if (err)
 			goto exit_unregister_sysfs;
+
+		if (f71882fg_has_beep[data->type]) {
+			err = f71882fg_create_sysfs_files(pdev,
+					&fxxxx_temp_beep_attr[0][0],
+					ARRAY_SIZE(fxxxx_temp_beep_attr[0])
+						* nr_temps);
+			if (err)
+				goto exit_unregister_sysfs;
+		}
+
+		for (i = 0; i < F71882FG_MAX_INS; i++) {
+			if (f71882fg_has_in[data->type][i]) {
+				err = device_create_file(&pdev->dev,
+						&fxxxx_in_attr[i].dev_attr);
+				if (err)
+					goto exit_unregister_sysfs;
+			}
+		}
+		if (f71882fg_has_in1_alarm[data->type]) {
+			err = f71882fg_create_sysfs_files(pdev,
+					fxxxx_in1_alarm_attr,
+					ARRAY_SIZE(fxxxx_in1_alarm_attr));
+			if (err)
+				goto exit_unregister_sysfs;
+		}
 	}
 
 	if (start_reg & 0x02) {
+		switch (data->type) {
+		case f71808e:
+		case f71869:
+			/* These always have signed auto point temps */
+			data->auto_point_temp_signed = 1;
+			/* Fall through to select correct fan/pwm reg bank! */
+		case f71889fg:
+		case f71889ed:
+		case f71889a:
+			reg = f71882fg_read8(data, F71882FG_REG_FAN_FAULT_T);
+			if (reg & F71882FG_FAN_NEG_TEMP_EN)
+				data->auto_point_temp_signed = 1;
+			/* Ensure banked pwm registers point to right bank */
+			reg &= ~F71882FG_FAN_PROG_SEL;
+			f71882fg_write8(data, F71882FG_REG_FAN_FAULT_T, reg);
+			break;
+		default:
+			break;
+		}
+
 		data->pwm_enable =
 			f71882fg_read8(data, F71882FG_REG_PWM_ENABLE);
 
@@ -2013,13 +2201,12 @@
 		case f71862fg:
 			err = (data->pwm_enable & 0x15) != 0x15;
 			break;
-		case f71882fg:
-		case f71889fg:
-			err = 0;
-			break;
 		case f8000:
 			err = data->pwm_enable & 0x20;
 			break;
+		default:
+			err = 0;
+			break;
 		}
 		if (err) {
 			dev_err(&pdev->dev,
@@ -2034,8 +2221,7 @@
 		if (err)
 			goto exit_unregister_sysfs;
 
-		if (data->type == f71862fg || data->type == f71882fg ||
-		    data->type == f71889fg) {
+		if (f71882fg_has_beep[data->type]) {
 			err = f71882fg_create_sysfs_files(pdev,
 					fxxxx_fan_beep_attr, nr_fans);
 			if (err)
@@ -2043,11 +2229,43 @@
 		}
 
 		switch (data->type) {
+		case f71808e:
+		case f71869:
+		case f71889fg:
+		case f71889ed:
+		case f71889a:
+			for (i = 0; i < nr_fans; i++) {
+				data->pwm_auto_point_mapping[i] =
+					f71882fg_read8(data,
+						F71882FG_REG_POINT_MAPPING(i));
+				if ((data->pwm_auto_point_mapping[i] & 0x80) ||
+				    (data->pwm_auto_point_mapping[i] & 3) == 0)
+					break;
+			}
+			if (i != nr_fans) {
+				dev_warn(&pdev->dev,
+					 "Auto pwm controlled by raw digital "
+					 "data, disabling pwm auto_point "
+					 "sysfs attributes\n");
+				goto no_pwm_auto_point;
+			}
+			break;
+		default:
+			break;
+		}
+
+		switch (data->type) {
 		case f71862fg:
 			err = f71882fg_create_sysfs_files(pdev,
 					f71862fg_auto_pwm_attr,
 					ARRAY_SIZE(f71862fg_auto_pwm_attr));
 			break;
+		case f71808e:
+		case f71869:
+			err = f71882fg_create_sysfs_files(pdev,
+					f71869_auto_pwm_attr,
+					ARRAY_SIZE(f71869_auto_pwm_attr));
+			break;
 		case f8000:
 			err = f71882fg_create_sysfs_files(pdev,
 					f8000_fan_attr,
@@ -2058,23 +2276,7 @@
 					f8000_auto_pwm_attr,
 					ARRAY_SIZE(f8000_auto_pwm_attr));
 			break;
-		case f71889fg:
-			for (i = 0; i < nr_fans; i++) {
-				data->pwm_auto_point_mapping[i] =
-					f71882fg_read8(data,
-						F71882FG_REG_POINT_MAPPING(i));
-				if (data->pwm_auto_point_mapping[i] & 0x80)
-					break;
-			}
-			if (i != nr_fans) {
-				dev_warn(&pdev->dev,
-					 "Auto pwm controlled by raw digital "
-					 "data, disabling pwm auto_point "
-					 "sysfs attributes\n");
-				break;
-			}
-			/* fall through */
-		default: /* f71858fg / f71882fg */
+		default:
 			err = f71882fg_create_sysfs_files(pdev,
 				&fxxxx_auto_pwm_attr[0][0],
 				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
@@ -2082,6 +2284,7 @@
 		if (err)
 			goto exit_unregister_sysfs;
 
+no_pwm_auto_point:
 		for (i = 0; i < nr_fans; i++)
 			dev_info(&pdev->dev, "Fan: %d is in %s mode\n", i + 1,
 				 (data->pwm_enable & (1 << 2 * i)) ?
@@ -2108,7 +2311,9 @@
 static int f71882fg_remove(struct platform_device *pdev)
 {
 	struct f71882fg_data *data = platform_get_drvdata(pdev);
-	int nr_fans = (data->type == f71882fg) ? 4 : 3;
+	int nr_fans = f71882fg_nr_fans[data->type];
+	int nr_temps = f71882fg_nr_temps[data->type];
+	int i;
 	u8 start_reg = f71882fg_read8(data, F71882FG_REG_START);
 
 	if (data->hwmon_dev)
@@ -2121,29 +2326,39 @@
 		case f71858fg:
 			if (data->temp_config & 0x10)
 				f71882fg_remove_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			else
 				f71882fg_remove_sysfs_files(pdev,
-					f71858fg_in_temp_attr,
-					ARRAY_SIZE(f71858fg_in_temp_attr));
-			break;
-		case f71882fg:
-		case f71889fg:
-			f71882fg_remove_sysfs_files(pdev,
-					fxxxx_in1_alarm_attr,
-					ARRAY_SIZE(fxxxx_in1_alarm_attr));
-			/* fall through! */
-		case f71862fg:
-			f71882fg_remove_sysfs_files(pdev,
-					fxxxx_in_temp_attr,
-					ARRAY_SIZE(fxxxx_in_temp_attr));
+					f71858fg_temp_attr,
+					ARRAY_SIZE(f71858fg_temp_attr));
 			break;
 		case f8000:
 			f71882fg_remove_sysfs_files(pdev,
-					f8000_in_temp_attr,
-					ARRAY_SIZE(f8000_in_temp_attr));
+					f8000_temp_attr,
+					ARRAY_SIZE(f8000_temp_attr));
 			break;
+		default:
+			f71882fg_remove_sysfs_files(pdev,
+				&fxxxx_temp_attr[0][0],
+				ARRAY_SIZE(fxxxx_temp_attr[0]) * nr_temps);
+		}
+		if (f71882fg_has_beep[data->type]) {
+			f71882fg_remove_sysfs_files(pdev,
+			       &fxxxx_temp_beep_attr[0][0],
+			       ARRAY_SIZE(fxxxx_temp_beep_attr[0]) * nr_temps);
+		}
+
+		for (i = 0; i < F71882FG_MAX_INS; i++) {
+			if (f71882fg_has_in[data->type][i]) {
+				device_remove_file(&pdev->dev,
+						&fxxxx_in_attr[i].dev_attr);
+			}
+		}
+		if (f71882fg_has_in1_alarm[data->type]) {
+			f71882fg_remove_sysfs_files(pdev,
+					fxxxx_in1_alarm_attr,
+					ARRAY_SIZE(fxxxx_in1_alarm_attr));
 		}
 	}
 
@@ -2151,10 +2366,10 @@
 		f71882fg_remove_sysfs_files(pdev, &fxxxx_fan_attr[0][0],
 				ARRAY_SIZE(fxxxx_fan_attr[0]) * nr_fans);
 
-		if (data->type == f71862fg || data->type == f71882fg ||
-		    data->type == f71889fg)
+		if (f71882fg_has_beep[data->type]) {
 			f71882fg_remove_sysfs_files(pdev,
 					fxxxx_fan_beep_attr, nr_fans);
+		}
 
 		switch (data->type) {
 		case f71862fg:
@@ -2162,6 +2377,12 @@
 					f71862fg_auto_pwm_attr,
 					ARRAY_SIZE(f71862fg_auto_pwm_attr));
 			break;
+		case f71808e:
+		case f71869:
+			f71882fg_remove_sysfs_files(pdev,
+					f71869_auto_pwm_attr,
+					ARRAY_SIZE(f71869_auto_pwm_attr));
+			break;
 		case f8000:
 			f71882fg_remove_sysfs_files(pdev,
 					f8000_fan_attr,
@@ -2170,7 +2391,7 @@
 					f8000_auto_pwm_attr,
 					ARRAY_SIZE(f8000_auto_pwm_attr));
 			break;
-		default: /* f71858fg / f71882fg / f71889fg */
+		default:
 			f71882fg_remove_sysfs_files(pdev,
 				&fxxxx_auto_pwm_attr[0][0],
 				ARRAY_SIZE(fxxxx_auto_pwm_attr[0]) * nr_fans);
@@ -2200,21 +2421,36 @@
 
 	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
 	switch (devid) {
+	case SIO_F71808E_ID:
+		sio_data->type = f71808e;
+		break;
 	case SIO_F71858_ID:
 		sio_data->type = f71858fg;
 		break;
 	case SIO_F71862_ID:
 		sio_data->type = f71862fg;
 		break;
+	case SIO_F71869_ID:
+		sio_data->type = f71869;
+		break;
 	case SIO_F71882_ID:
 		sio_data->type = f71882fg;
 		break;
 	case SIO_F71889_ID:
 		sio_data->type = f71889fg;
 		break;
+	case SIO_F71889E_ID:
+		sio_data->type = f71889ed;
+		break;
+	case SIO_F71889A_ID:
+		sio_data->type = f71889a;
+		break;
 	case SIO_F8000_ID:
 		sio_data->type = f8000;
 		break;
+	case SIO_F81865_ID:
+		sio_data->type = f81865f;
+		break;
 	default:
 		pr_info("Unsupported Fintek device: %04x\n",
 			(unsigned int)devid);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/gpio-fan.c linux-libre-2.6.39-gnu/drivers/hwmon/gpio-fan.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/gpio-fan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/gpio-fan.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,7 @@
 		return 0;
 
 	INIT_WORK(&fan_data->alarm_work, fan_alarm_notify);
-	set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(alarm_irq, IRQ_TYPE_EDGE_BOTH);
 	err = request_irq(alarm_irq, fan_alarm_irq_handler, IRQF_SHARED,
 			  "GPIO fan alarm", fan_data);
 	if (err)
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/hp_accel.c linux-libre-2.6.39-gnu/drivers/hwmon/hp_accel.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/hp_accel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/hp_accel.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,405 +0,0 @@
-/*
- *  hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008-2009 Pavel Machek
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/leds.h>
-#include <acpi/acpi_drivers.h>
-#include <asm/atomic.h>
-#include "lis3lv02d.h"
-
-#define DRIVER_NAME     "lis3lv02d"
-#define ACPI_MDPS_CLASS "accelerometer"
-
-/* Delayed LEDs infrastructure ------------------------------------ */
-
-/* Special LED class that can defer work */
-struct delayed_led_classdev {
-	struct led_classdev led_classdev;
-	struct work_struct work;
-	enum led_brightness new_brightness;
-
-	unsigned int led;		/* For driver */
-	void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
-};
-
-static inline void delayed_set_status_worker(struct work_struct *work)
-{
-	struct delayed_led_classdev *data =
-			container_of(work, struct delayed_led_classdev, work);
-
-	data->set_brightness(data, data->new_brightness);
-}
-
-static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
-			      enum led_brightness brightness)
-{
-	struct delayed_led_classdev *data = container_of(led_cdev,
-			     struct delayed_led_classdev, led_classdev);
-	data->new_brightness = brightness;
-	schedule_work(&data->work);
-}
-
-/* HP-specific accelerometer driver ------------------------------------ */
-
-/* For automatic insertion of the module */
-static struct acpi_device_id lis3lv02d_device_ids[] = {
-	{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
-	{"", 0},
-};
-MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
-
-
-/**
- * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
- * @lis3: pointer to the device struct
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
-{
-	struct acpi_device *dev = lis3->bus_priv;
-	if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
-				 NULL, NULL) != AE_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-/**
- * lis3lv02d_acpi_read - ACPI ALRD method: read a register
- * @lis3: pointer to the device struct
- * @reg:    the register to read
- * @ret:    result of the operation
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
-{
-	struct acpi_device *dev = lis3->bus_priv;
-	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
-	struct acpi_object_list args = { 1, &arg0 };
-	unsigned long long lret;
-	acpi_status status;
-
-	arg0.integer.value = reg;
-
-	status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
-	*ret = lret;
-	return (status != AE_OK) ? -EINVAL : 0;
-}
-
-/**
- * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
- * @lis3: pointer to the device struct
- * @reg:    the register to write to
- * @val:    the value to write
- *
- * Returns 0 on success.
- */
-int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
-{
-	struct acpi_device *dev = lis3->bus_priv;
-	unsigned long long ret; /* Not used when writting */
-	union acpi_object in_obj[2];
-	struct acpi_object_list args = { 2, in_obj };
-
-	in_obj[0].type          = ACPI_TYPE_INTEGER;
-	in_obj[0].integer.value = reg;
-	in_obj[1].type          = ACPI_TYPE_INTEGER;
-	in_obj[1].integer.value = val;
-
-	if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
-		return -EINVAL;
-
-	return 0;
-}
-
-static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
-{
-	lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
-	pr_info("hardware type %s found\n", dmi->ident);
-
-	return 1;
-}
-
-/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
- * If the value is negative, the opposite of the hw value is used. */
-#define DEFINE_CONV(name, x, y, z)			      \
-	static union axis_conversion lis3lv02d_axis_##name = \
-		{ .as_array = { x, y, z } }
-DEFINE_CONV(normal, 1, 2, 3);
-DEFINE_CONV(y_inverted, 1, -2, 3);
-DEFINE_CONV(x_inverted, -1, 2, 3);
-DEFINE_CONV(z_inverted, 1, 2, -3);
-DEFINE_CONV(xy_swap, 2, 1, 3);
-DEFINE_CONV(xy_rotated_left, -2, 1, 3);
-DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
-DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
-DEFINE_CONV(xy_rotated_right, 2, -1, 3);
-DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
-
-#define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
-	.ident = _ident,				\
-	.callback = lis3lv02d_dmi_matched,		\
-	.matches = {					\
-		DMI_MATCH(DMI_PRODUCT_NAME, _name)	\
-	},						\
-	.driver_data = &lis3lv02d_axis_##_axis		\
-}
-
-#define AXIS_DMI_MATCH2(_ident, _class1, _name1,	\
-				_class2, _name2,	\
-				_axis) {		\
-	.ident = _ident,				\
-	.callback = lis3lv02d_dmi_matched,		\
-	.matches = {					\
-		DMI_MATCH(DMI_##_class1, _name1),	\
-		DMI_MATCH(DMI_##_class2, _name2),	\
-	},						\
-	.driver_data = &lis3lv02d_axis_##_axis		\
-}
-static struct dmi_system_id lis3lv02d_dmi_ids[] = {
-	/* product names are truncated to match all kinds of a same model */
-	AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
-	AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
-	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("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
-	AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
-	AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
-	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),
-	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
-	/* Intel-based HP Pavilion dv5 */
-	AXIS_DMI_MATCH2("HPDV5_I",
-			PRODUCT_NAME, "HP Pavilion dv5",
-			BOARD_NAME, "3603",
-			x_inverted),
-	/* AMD-based HP Pavilion dv5 */
-	AXIS_DMI_MATCH2("HPDV5_A",
-			PRODUCT_NAME, "HP Pavilion dv5",
-			BOARD_NAME, "3600",
-			y_inverted),
-	AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
-	AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
-	AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
-	AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
-	AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
-	AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
-	AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
-	AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
-	AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
-	{ NULL, }
-/* Laptop models without axis info (yet):
- * "NC6910" "HP Compaq 6910"
- * "NC2400" "HP Compaq nc2400"
- * "NX74x0" "HP Compaq nx74"
- * "NX6325" "HP Compaq nx6325"
- * "NC4400" "HP Compaq nc4400"
- */
-};
-
-static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
-{
-	struct acpi_device *dev = lis3_dev.bus_priv;
-	unsigned long long ret; /* Not used when writing */
-	union acpi_object in_obj[1];
-	struct acpi_object_list args = { 1, in_obj };
-
-	in_obj[0].type          = ACPI_TYPE_INTEGER;
-	in_obj[0].integer.value = !!value;
-
-	acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
-}
-
-static struct delayed_led_classdev hpled_led = {
-	.led_classdev = {
-		.name			= "hp::hddprotect",
-		.default_trigger	= "none",
-		.brightness_set		= delayed_sysfs_set,
-		.flags                  = LED_CORE_SUSPENDRESUME,
-	},
-	.set_brightness = hpled_set,
-};
-
-static acpi_status
-lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
-{
-	if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
-		struct acpi_resource_extended_irq *irq;
-		u32 *device_irq = context;
-
-		irq = &resource->data.extended_irq;
-		*device_irq = irq->interrupts[0];
-	}
-
-	return AE_OK;
-}
-
-static void lis3lv02d_enum_resources(struct acpi_device *device)
-{
-	acpi_status status;
-
-	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
-					lis3lv02d_get_resource, &lis3_dev.irq);
-	if (ACPI_FAILURE(status))
-		printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
-}
-
-static int lis3lv02d_add(struct acpi_device *device)
-{
-	int ret;
-
-	if (!device)
-		return -EINVAL;
-
-	lis3_dev.bus_priv = device;
-	lis3_dev.init = lis3lv02d_acpi_init;
-	lis3_dev.read = lis3lv02d_acpi_read;
-	lis3_dev.write = lis3lv02d_acpi_write;
-	strcpy(acpi_device_name(device), DRIVER_NAME);
-	strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
-	device->driver_data = &lis3_dev;
-
-	/* obtain IRQ number of our device from ACPI */
-	lis3lv02d_enum_resources(device);
-
-	/* If possible use a "standard" axes order */
-	if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
-		pr_info("Using custom axes %d,%d,%d\n",
-			lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
-	} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
-		pr_info("laptop model unknown, using default axes configuration\n");
-		lis3_dev.ac = lis3lv02d_axis_normal;
-	}
-
-	/* call the core layer do its init */
-	ret = lis3lv02d_init_device(&lis3_dev);
-	if (ret)
-		return ret;
-
-	INIT_WORK(&hpled_led.work, delayed_set_status_worker);
-	ret = led_classdev_register(NULL, &hpled_led.led_classdev);
-	if (ret) {
-		lis3lv02d_joystick_disable();
-		lis3lv02d_poweroff(&lis3_dev);
-		flush_work(&hpled_led.work);
-		return ret;
-	}
-
-	return ret;
-}
-
-static int lis3lv02d_remove(struct acpi_device *device, int type)
-{
-	if (!device)
-		return -EINVAL;
-
-	lis3lv02d_joystick_disable();
-	lis3lv02d_poweroff(&lis3_dev);
-
-	led_classdev_unregister(&hpled_led.led_classdev);
-	flush_work(&hpled_led.work);
-
-	return lis3lv02d_remove_fs(&lis3_dev);
-}
-
-
-#ifdef CONFIG_PM
-static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
-{
-	/* make sure the device is off when we suspend */
-	lis3lv02d_poweroff(&lis3_dev);
-	return 0;
-}
-
-static int lis3lv02d_resume(struct acpi_device *device)
-{
-	lis3lv02d_poweron(&lis3_dev);
-	return 0;
-}
-#else
-#define lis3lv02d_suspend NULL
-#define lis3lv02d_resume NULL
-#endif
-
-/* For the HP MDPS aka 3D Driveguard */
-static struct acpi_driver lis3lv02d_driver = {
-	.name  = DRIVER_NAME,
-	.class = ACPI_MDPS_CLASS,
-	.ids   = lis3lv02d_device_ids,
-	.ops = {
-		.add     = lis3lv02d_add,
-		.remove  = lis3lv02d_remove,
-		.suspend = lis3lv02d_suspend,
-		.resume  = lis3lv02d_resume,
-	}
-};
-
-static int __init lis3lv02d_init_module(void)
-{
-	int ret;
-
-	if (acpi_disabled)
-		return -ENODEV;
-
-	ret = acpi_bus_register_driver(&lis3lv02d_driver);
-	if (ret < 0)
-		return ret;
-
-	pr_info("driver loaded\n");
-
-	return 0;
-}
-
-static void __exit lis3lv02d_exit_module(void)
-{
-	acpi_bus_unregister_driver(&lis3lv02d_driver);
-}
-
-MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
-MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
-MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init_module);
-module_exit(lis3lv02d_exit_module);
-
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/jz4740-hwmon.c linux-libre-2.6.39-gnu/drivers/hwmon/jz4740-hwmon.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/jz4740-hwmon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/jz4740-hwmon.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 
 	int irq;
 
-	struct mfd_cell *cell;
+	const struct mfd_cell *cell;
 	struct device *hwmon;
 
 	struct completion read_completion;
@@ -112,7 +112,7 @@
 		return -ENOMEM;
 	}
 
-	hwmon->cell = pdev->dev.platform_data;
+	hwmon->cell = mfd_get_cell(pdev);
 
 	hwmon->irq = platform_get_irq(pdev, 0);
 	if (hwmon->irq < 0) {
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/Kconfig linux-libre-2.6.39-gnu/drivers/hwmon/Kconfig
--- linux-libre-2.6.38-gnu/drivers/hwmon/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -110,8 +110,7 @@
 	help
 	  If you say yes here you get support for Analog Devices ADM1021
 	  and ADM1023 sensor chips and clones: Maxim MAX1617 and MAX1617A,
-	  Genesys Logic GL523SM, National Semiconductor LM84, TI THMC10,
-	  and the XEON processor built-in sensor.
+	  Genesys Logic GL523SM, National Semiconductor LM84 and TI THMC10.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called adm1021.
@@ -315,11 +314,22 @@
 	  will be called f71805f.
 
 config SENSORS_F71882FG
-	tristate "Fintek F71858FG, F71862FG, F71882FG, F71889FG and F8000"
+	tristate "Fintek F71882FG and compatibles"
 	help
 	  If you say yes here you get support for hardware monitoring
-	  features of the Fintek F71858FG, F71862FG/71863FG, F71882FG/F71883FG,
-	  F71889FG and F8000 Super-I/O chips.
+	  features of many Fintek Super-I/O (LPC) chips. The currently
+	  supported chips are:
+	    F71808E
+	    F71858FG
+	    F71862FG
+	    F71863FG
+	    F71869F/E
+	    F71882FG
+	    F71883FG
+	    F71889FG/ED/A
+	    F8000
+	    F81801U
+	    F81865F
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called f71882fg.
@@ -467,6 +477,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called jc42.
 
+config SENSORS_LINEAGE
+	tristate "Lineage Compact Power Line Power Entry Module"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the Lineage Compact Power Line
+	  series of DC/DC and AC/DC converters such as CP1800, CP2000AC,
+	  CP2000DC, CP2725, and others.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lineage-pem.
+
 config SENSORS_LM63
 	tristate "National Semiconductor LM63 and LM64"
 	depends on I2C
@@ -510,7 +531,7 @@
 		- Dallas Semiconductor DS75 and DS1775
 		- Maxim MAX6625 and MAX6626
 		- Microchip MCP980x
-		- National Semiconductor LM75
+		- National Semiconductor LM75, LM75A
 		- NXP's LM75A
 		- ST Microelectronics STDS75
 		- TelCom (now Microchip) TCN75
@@ -596,10 +617,10 @@
 	depends on I2C
 	help
 	  If you say yes here you get support for National Semiconductor LM90,
-	  LM86, LM89 and LM99, Analog Devices ADM1032 and ADT7461, Maxim
-	  MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
-	  MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, and Winbond/Nuvoton
-	  W83L771W/G/AWG/ASG sensor chips.
+	  LM86, LM89 and LM99, Analog Devices ADM1032, ADT7461, and ADT7461A,
+	  Maxim MAX6646, MAX6647, MAX6648, MAX6649, MAX6657, MAX6658, MAX6659,
+	  MAX6680, MAX6681, MAX6692, MAX6695, MAX6696, ON Semiconductor NCT1008,
+	  and Winbond/Nuvoton W83L771W/G/AWG/ASG sensor chips.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm90.
@@ -625,6 +646,17 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm93.
 
+config SENSORS_LTC4151
+	tristate "Linear Technology LTC4151"
+	depends on I2C
+	default n
+	help
+	  If you say yes here you get support for Linear Technology LTC4151
+	  High Voltage I2C Current and Voltage Monitor interface.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called ltc4151.
+
 config SENSORS_LTC4215
 	tristate "Linear Technology LTC4215"
 	depends on I2C && EXPERIMENTAL
@@ -685,6 +717,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called max1619.
 
+config SENSORS_MAX6639
+	tristate "Maxim MAX6639 sensor chip"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the MAX6639
+	  sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called max6639.
+
 config SENSORS_MAX6650
 	tristate "Maxim MAX6650 sensor chip"
 	depends on I2C && EXPERIMENTAL
@@ -735,6 +777,61 @@
 	  These devices are hard to detect and rarely found on mainstream
 	  hardware.  If unsure, say N.
 
+config PMBUS
+	tristate "PMBus support"
+	depends on I2C && EXPERIMENTAL
+	default n
+	help
+	  Say yes here if you want to enable PMBus support.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called pmbus_core.
+
+if PMBUS
+
+config SENSORS_PMBUS
+	tristate "Generic PMBus devices"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for generic
+	  PMBus devices, including but not limited to BMR450, BMR451, BMR453,
+	  BMR454, and LTC2978.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called pmbus.
+
+config SENSORS_MAX16064
+	tristate "Maxim MAX16064"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Maxim
+	  MAX16064.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max16064.
+
+config SENSORS_MAX34440
+	tristate "Maxim MAX34440/MAX34441"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Maxim
+	  MAX34440 and MAX34441.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max34440.
+
+config SENSORS_MAX8688
+	tristate "Maxim MAX8688"
+	default n
+	help
+	  If you say yes here you get hardware monitoring support for Maxim
+	  MAX8688.
+
+	  This driver can also be built as a module. If so, the module will
+	  be called max8688.
+
+endif # PMBUS
+
 config SENSORS_SHT15
 	tristate "Sensiron humidity and temperature sensors. SHT15 and compat."
 	depends on GENERIC_GPIO
@@ -872,6 +969,25 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47b397.
 
+config SENSORS_SCH5627
+	tristate "SMSC SCH5627"
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  features of the SMSC SCH5627 Super-I/O chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called sch5627.
+
+config SENSORS_ADS1015
+	tristate "Texas Instruments ADS1015"
+	depends on I2C
+	help
+	  If you say yes here you get support for Texas Instruments ADS1015
+	  12-bit 4-input ADC device.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called ads1015.
+
 config SENSORS_ADS7828
 	tristate "Texas Instruments ADS7828"
 	depends on I2C
@@ -941,6 +1057,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp421.
 
+config SENSORS_TWL4030_MADC
+	tristate "Texas Instruments TWL4030 MADC Hwmon"
+	depends on TWL4030_MADC
+	help
+	If you say yes here you get hwmon support for triton
+	TWL4030-MADC.
+
+	This driver can also be built as a module. If so it will be called
+	twl4030-madc-hwmon.
+
 config SENSORS_VIA_CPUTEMP
 	tristate "VIA CPU temperature sensor"
 	depends on X86
@@ -1083,7 +1209,7 @@
 	  will be called w83627hf.
 
 config SENSORS_W83627EHF
-	tristate "Winbond W83627EHF/EHG/DHG, W83667HG"
+	tristate "Winbond W83627EHF/EHG/DHG, W83667HG, NCT6775F, NCT6776F"
 	select HWMON_VID
 	help
 	  If you say yes here you get support for the hardware
@@ -1094,7 +1220,8 @@
 	  chip suited for specific Intel processors that use PECI such as
 	  the Core 2 Duo.
 
-	  This driver also supports the W83667HG chip.
+	  This driver also supports Nuvoton W83667HG, W83667HG-B, NCT6775F
+	  (also known as W83667HG-I), and NCT6776F.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627ehf.
@@ -1127,40 +1254,6 @@
 	  This driver provides support for the Ultra45 workstation environmental
 	  sensors.
 
-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
-	  via SPI. The accelerometer data is readable via
-	  /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  the laptop to act as a pinball machine-esque joystick.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for the SPI transport
-	  is called lis3lv02d_spi.
-
-config SENSORS_LIS3_I2C
-	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
-	depends on I2C && INPUT
-	select INPUT_POLLDEV
-	default n
-	help
-	  This driver provides support for the LIS3LV02Dx accelerometer connected
-	  via I2C. The accelerometer data is readable via
-	  /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  the device to act as a pinball machine-esque joystick.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for the I2C transport
-	  is called lis3lv02d_i2c.
-
 config SENSORS_APPLESMC
 	tristate "Apple SMC (Motion sensor, light sensor, keyboard backlight)"
 	depends on INPUT && X86
@@ -1208,36 +1301,6 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called asus_atk0110.
 
-config SENSORS_LIS3LV02D
-	tristate "STMicroeletronics LIS3* three-axis digital accelerometer"
-	depends on INPUT
-	select INPUT_POLLDEV
-	select NEW_LEDS
-	select LEDS_CLASS
-	default n
-	help
-	  This driver provides support for the LIS3* accelerometers, such as the
-	  LIS3LV02DL or the LIS331DL. In particular, it can be found in a number
-	  of HP laptops, which have the "Mobile Data Protection System 3D" or
-	  "3D DriveGuard" feature. On such systems the driver should load
-	  automatically (via ACPI alias). The accelerometer might also be found
-	  in other systems, connected via SPI or I2C. The accelerometer data is
-	  readable via /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  a laptop to act as a pinball machine-esque joystick. It provides also
-	  a misc device which can be used to detect free-fall. On HP laptops,
-	  if the led infrastructure is activated, support for a led indicating
-	  disk protection will be provided as hp::hddprotect. For more
-	  information on the feature, refer to Documentation/hwmon/lis3lv02d.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for HP laptops will be
-	  called hp_accel.
-
-	  Say Y here if you have an applicable laptop and want to experience
-	  the awesome power of lis3lv02d.
-
 endif # ACPI
 
 endif # HWMON
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lineage-pem.c linux-libre-2.6.39-gnu/drivers/hwmon/lineage-pem.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lineage-pem.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lineage-pem.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,586 @@
+/*
+ * Driver for Lineage Compact Power Line series of power entry modules.
+ *
+ * Copyright (C) 2010, 2011 Ericsson AB.
+ *
+ * Documentation:
+ *  http://www.lineagepower.com/oem/pdf/CPLI2C.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/*
+ * This driver supports various Lineage Compact Power Line DC/DC and AC/DC
+ * converters such as CP1800, CP2000AC, CP2000DC, CP2100DC, and others.
+ *
+ * The devices are nominally PMBus compliant. However, most standard PMBus
+ * commands are not supported. Specifically, all hardware monitoring and
+ * status reporting commands are non-standard. For this reason, a standard
+ * PMBus driver can not be used.
+ *
+ * All Lineage CPL devices have a built-in I2C bus master selector (PCA9541).
+ * To ensure device access, this driver should only be used as client driver
+ * to the pca9541 I2C master selector driver.
+ */
+
+/* Command codes */
+#define PEM_OPERATION		0x01
+#define PEM_CLEAR_INFO_FLAGS	0x03
+#define PEM_VOUT_COMMAND	0x21
+#define PEM_VOUT_OV_FAULT_LIMIT	0x40
+#define PEM_READ_DATA_STRING	0xd0
+#define PEM_READ_INPUT_STRING	0xdc
+#define PEM_READ_FIRMWARE_REV	0xdd
+#define PEM_READ_RUN_TIMER	0xde
+#define PEM_FAN_HI_SPEED	0xdf
+#define PEM_FAN_NORMAL_SPEED	0xe0
+#define PEM_READ_FAN_SPEED	0xe1
+
+/* offsets in data string */
+#define PEM_DATA_STATUS_2	0
+#define PEM_DATA_STATUS_1	1
+#define PEM_DATA_ALARM_2	2
+#define PEM_DATA_ALARM_1	3
+#define PEM_DATA_VOUT_LSB	4
+#define PEM_DATA_VOUT_MSB	5
+#define PEM_DATA_CURRENT	6
+#define PEM_DATA_TEMP		7
+
+/* Virtual entries, to report constants */
+#define PEM_DATA_TEMP_MAX	10
+#define PEM_DATA_TEMP_CRIT	11
+
+/* offsets in input string */
+#define PEM_INPUT_VOLTAGE	0
+#define PEM_INPUT_POWER_LSB	1
+#define PEM_INPUT_POWER_MSB	2
+
+/* offsets in fan data */
+#define PEM_FAN_ADJUSTMENT	0
+#define PEM_FAN_FAN1		1
+#define PEM_FAN_FAN2		2
+#define PEM_FAN_FAN3		3
+
+/* Status register bits */
+#define STS1_OUTPUT_ON		(1 << 0)
+#define STS1_LEDS_FLASHING	(1 << 1)
+#define STS1_EXT_FAULT		(1 << 2)
+#define STS1_SERVICE_LED_ON	(1 << 3)
+#define STS1_SHUTDOWN_OCCURRED	(1 << 4)
+#define STS1_INT_FAULT		(1 << 5)
+#define STS1_ISOLATION_TEST_OK	(1 << 6)
+
+#define STS2_ENABLE_PIN_HI	(1 << 0)
+#define STS2_DATA_OUT_RANGE	(1 << 1)
+#define STS2_RESTARTED_OK	(1 << 1)
+#define STS2_ISOLATION_TEST_FAIL (1 << 3)
+#define STS2_HIGH_POWER_CAP	(1 << 4)
+#define STS2_INVALID_INSTR	(1 << 5)
+#define STS2_WILL_RESTART	(1 << 6)
+#define STS2_PEC_ERR		(1 << 7)
+
+/* Alarm register bits */
+#define ALRM1_VIN_OUT_LIMIT	(1 << 0)
+#define ALRM1_VOUT_OUT_LIMIT	(1 << 1)
+#define ALRM1_OV_VOLT_SHUTDOWN	(1 << 2)
+#define ALRM1_VIN_OVERCURRENT	(1 << 3)
+#define ALRM1_TEMP_WARNING	(1 << 4)
+#define ALRM1_TEMP_SHUTDOWN	(1 << 5)
+#define ALRM1_PRIMARY_FAULT	(1 << 6)
+#define ALRM1_POWER_LIMIT	(1 << 7)
+
+#define ALRM2_5V_OUT_LIMIT	(1 << 1)
+#define ALRM2_TEMP_FAULT	(1 << 2)
+#define ALRM2_OV_LOW		(1 << 3)
+#define ALRM2_DCDC_TEMP_HIGH	(1 << 4)
+#define ALRM2_PRI_TEMP_HIGH	(1 << 5)
+#define ALRM2_NO_PRIMARY	(1 << 6)
+#define ALRM2_FAN_FAULT		(1 << 7)
+
+#define FIRMWARE_REV_LEN	4
+#define DATA_STRING_LEN		9
+#define INPUT_STRING_LEN	5	/* 4 for most devices	*/
+#define FAN_SPEED_LEN		5
+
+struct pem_data {
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	bool valid;
+	bool fans_supported;
+	int input_length;
+	unsigned long last_updated;	/* in jiffies */
+
+	u8 firmware_rev[FIRMWARE_REV_LEN];
+	u8 data_string[DATA_STRING_LEN];
+	u8 input_string[INPUT_STRING_LEN];
+	u8 fan_speed[FAN_SPEED_LEN];
+};
+
+static int pem_read_block(struct i2c_client *client, u8 command, u8 *data,
+			  int data_len)
+{
+	u8 block_buffer[I2C_SMBUS_BLOCK_MAX];
+	int result;
+
+	result = i2c_smbus_read_block_data(client, command, block_buffer);
+	if (unlikely(result < 0))
+		goto abort;
+	if (unlikely(result == 0xff || result != data_len)) {
+		result = -EIO;
+		goto abort;
+	}
+	memcpy(data, block_buffer, data_len);
+	result = 0;
+abort:
+	return result;
+}
+
+static struct pem_data *pem_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pem_data *data = i2c_get_clientdata(client);
+	struct pem_data *ret = data;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		int result;
+
+		/* Read data string */
+		result = pem_read_block(client, PEM_READ_DATA_STRING,
+					data->data_string,
+					sizeof(data->data_string));
+		if (unlikely(result < 0)) {
+			ret = ERR_PTR(result);
+			goto abort;
+		}
+
+		/* Read input string */
+		if (data->input_length) {
+			result = pem_read_block(client, PEM_READ_INPUT_STRING,
+						data->input_string,
+						data->input_length);
+			if (unlikely(result < 0)) {
+				ret = ERR_PTR(result);
+				goto abort;
+			}
+		}
+
+		/* Read fan speeds */
+		if (data->fans_supported) {
+			result = pem_read_block(client, PEM_READ_FAN_SPEED,
+						data->fan_speed,
+						sizeof(data->fan_speed));
+			if (unlikely(result < 0)) {
+				ret = ERR_PTR(result);
+				goto abort;
+			}
+		}
+
+		i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static long pem_get_data(u8 *data, int len, int index)
+{
+	long val;
+
+	switch (index) {
+	case PEM_DATA_VOUT_LSB:
+		val = (data[index] + (data[index+1] << 8)) * 5 / 2;
+		break;
+	case PEM_DATA_CURRENT:
+		val = data[index] * 200;
+		break;
+	case PEM_DATA_TEMP:
+		val = data[index] * 1000;
+		break;
+	case PEM_DATA_TEMP_MAX:
+		val = 97 * 1000;	/* 97 degrees C per datasheet */
+		break;
+	case PEM_DATA_TEMP_CRIT:
+		val = 107 * 1000;	/* 107 degrees C per datasheet */
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		val = 0;
+	}
+	return val;
+}
+
+static long pem_get_input(u8 *data, int len, int index)
+{
+	long val;
+
+	switch (index) {
+	case PEM_INPUT_VOLTAGE:
+		if (len == INPUT_STRING_LEN)
+			val = (data[index] + (data[index+1] << 8) - 75) * 1000;
+		else
+			val = (data[index] - 75) * 1000;
+		break;
+	case PEM_INPUT_POWER_LSB:
+		if (len == INPUT_STRING_LEN)
+			index++;
+		val = (data[index] + (data[index+1] << 8)) * 1000000L;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		val = 0;
+	}
+	return val;
+}
+
+static long pem_get_fan(u8 *data, int len, int index)
+{
+	long val;
+
+	switch (index) {
+	case PEM_FAN_FAN1:
+	case PEM_FAN_FAN2:
+	case PEM_FAN_FAN3:
+		val = data[index] * 100;
+		break;
+	default:
+		WARN_ON_ONCE(1);
+		val = 0;
+	}
+	return val;
+}
+
+/*
+ * Show boolean, either a fault or an alarm.
+ * .nr points to the register, .index is the bit mask to check
+ */
+static ssize_t pem_show_bool(struct device *dev,
+			     struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(da);
+	struct pem_data *data = pem_update_device(dev);
+	u8 status;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	status = data->data_string[attr->nr] & attr->index;
+	return snprintf(buf, PAGE_SIZE, "%d\n", !!status);
+}
+
+static ssize_t pem_show_data(struct device *dev, struct device_attribute *da,
+			     char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pem_data *data = pem_update_device(dev);
+	long value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = pem_get_data(data->data_string, sizeof(data->data_string),
+			     attr->index);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+}
+
+static ssize_t pem_show_input(struct device *dev, struct device_attribute *da,
+			      char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pem_data *data = pem_update_device(dev);
+	long value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = pem_get_input(data->input_string, sizeof(data->input_string),
+			      attr->index);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+}
+
+static ssize_t pem_show_fan(struct device *dev, struct device_attribute *da,
+			    char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pem_data *data = pem_update_device(dev);
+	long value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = pem_get_fan(data->fan_speed, sizeof(data->fan_speed),
+			    attr->index);
+
+	return snprintf(buf, PAGE_SIZE, "%ld\n", value);
+}
+
+/* Voltages */
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_VOUT_LSB);
+static SENSOR_DEVICE_ATTR_2(in1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_VOUT_OUT_LIMIT);
+static SENSOR_DEVICE_ATTR_2(in1_crit_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_OV_VOLT_SHUTDOWN);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, pem_show_input, NULL,
+			  PEM_INPUT_VOLTAGE);
+static SENSOR_DEVICE_ATTR_2(in2_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1,
+			    ALRM1_VIN_OUT_LIMIT | ALRM1_PRIMARY_FAULT);
+
+/* Currents */
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_CURRENT);
+static SENSOR_DEVICE_ATTR_2(curr1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_VIN_OVERCURRENT);
+
+/* Power */
+static SENSOR_DEVICE_ATTR(power1_input, S_IRUGO, pem_show_input, NULL,
+			  PEM_INPUT_POWER_LSB);
+static SENSOR_DEVICE_ATTR_2(power1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_POWER_LIMIT);
+
+/* Fans */
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, pem_show_fan, NULL,
+			  PEM_FAN_FAN1);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, pem_show_fan, NULL,
+			  PEM_FAN_FAN2);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, pem_show_fan, NULL,
+			  PEM_FAN_FAN3);
+static SENSOR_DEVICE_ATTR_2(fan1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_2, ALRM2_FAN_FAULT);
+
+/* Temperatures */
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_TEMP);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_TEMP_MAX);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, pem_show_data, NULL,
+			  PEM_DATA_TEMP_CRIT);
+static SENSOR_DEVICE_ATTR_2(temp1_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_TEMP_WARNING);
+static SENSOR_DEVICE_ATTR_2(temp1_crit_alarm, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_1, ALRM1_TEMP_SHUTDOWN);
+static SENSOR_DEVICE_ATTR_2(temp1_fault, S_IRUGO, pem_show_bool, NULL,
+			    PEM_DATA_ALARM_2, ALRM2_TEMP_FAULT);
+
+static struct attribute *pem_attributes[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_alarm.dev_attr.attr,
+	&sensor_dev_attr_in1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_in2_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_power1_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_alarm.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
+
+	NULL,
+};
+
+static const struct attribute_group pem_group = {
+	.attrs = pem_attributes,
+};
+
+static struct attribute *pem_input_attributes[] = {
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+	&sensor_dev_attr_power1_input.dev_attr.attr,
+};
+
+static const struct attribute_group pem_input_group = {
+	.attrs = pem_input_attributes,
+};
+
+static struct attribute *pem_fan_attributes[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+};
+
+static const struct attribute_group pem_fan_group = {
+	.attrs = pem_fan_attributes,
+};
+
+static int pem_probe(struct i2c_client *client,
+		     const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct pem_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BLOCK_DATA
+				     | I2C_FUNC_SMBUS_WRITE_BYTE))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/*
+	 * We use the next two commands to determine if the device is really
+	 * there.
+	 */
+	ret = pem_read_block(client, PEM_READ_FIRMWARE_REV,
+			     data->firmware_rev, sizeof(data->firmware_rev));
+	if (ret < 0)
+		goto out_kfree;
+
+	ret = i2c_smbus_write_byte(client, PEM_CLEAR_INFO_FLAGS);
+	if (ret < 0)
+		goto out_kfree;
+
+	dev_info(&client->dev, "Firmware revision %d.%d.%d\n",
+		 data->firmware_rev[0], data->firmware_rev[1],
+		 data->firmware_rev[2]);
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&client->dev.kobj, &pem_group);
+	if (ret)
+		goto out_kfree;
+
+	/*
+	 * Check if input readings are supported.
+	 * This is the case if we can read input data,
+	 * and if the returned data is not all zeros.
+	 * Note that input alarms are always supported.
+	 */
+	ret = pem_read_block(client, PEM_READ_INPUT_STRING,
+			     data->input_string,
+			     sizeof(data->input_string) - 1);
+	if (!ret && (data->input_string[0] || data->input_string[1] ||
+		     data->input_string[2]))
+		data->input_length = sizeof(data->input_string) - 1;
+	else if (ret < 0) {
+		/* Input string is one byte longer for some devices */
+		ret = pem_read_block(client, PEM_READ_INPUT_STRING,
+				    data->input_string,
+				    sizeof(data->input_string));
+		if (!ret && (data->input_string[0] || data->input_string[1] ||
+			    data->input_string[2] || data->input_string[3]))
+			data->input_length = sizeof(data->input_string);
+	}
+	ret = 0;
+	if (data->input_length) {
+		ret = sysfs_create_group(&client->dev.kobj, &pem_input_group);
+		if (ret)
+			goto out_remove_groups;
+	}
+
+	/*
+	 * Check if fan speed readings are supported.
+	 * This is the case if we can read fan speed data,
+	 * and if the returned data is not all zeros.
+	 * Note that the fan alarm is always supported.
+	 */
+	ret = pem_read_block(client, PEM_READ_FAN_SPEED,
+			     data->fan_speed,
+			     sizeof(data->fan_speed));
+	if (!ret && (data->fan_speed[0] || data->fan_speed[1] ||
+		     data->fan_speed[2] || data->fan_speed[3])) {
+		data->fans_supported = true;
+		ret = sysfs_create_group(&client->dev.kobj, &pem_fan_group);
+		if (ret)
+			goto out_remove_groups;
+	}
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto out_remove_groups;
+	}
+
+	return 0;
+
+out_remove_groups:
+	sysfs_remove_group(&client->dev.kobj, &pem_input_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_group);
+out_kfree:
+	kfree(data);
+	return ret;
+}
+
+static int pem_remove(struct i2c_client *client)
+{
+	struct pem_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+
+	sysfs_remove_group(&client->dev.kobj, &pem_input_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_fan_group);
+	sysfs_remove_group(&client->dev.kobj, &pem_group);
+
+	kfree(data);
+	return 0;
+}
+
+static const struct i2c_device_id pem_id[] = {
+	{"lineage_pem", 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, pem_id);
+
+static struct i2c_driver pem_driver = {
+	.driver = {
+		   .name = "lineage_pem",
+		   },
+	.probe = pem_probe,
+	.remove = pem_remove,
+	.id_table = pem_id,
+};
+
+static int __init pem_init(void)
+{
+	return i2c_add_driver(&pem_driver);
+}
+
+static void __exit pem_exit(void)
+{
+	i2c_del_driver(&pem_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION("Lineage CPL PEM hardware monitoring driver");
+MODULE_LICENSE("GPL");
+
+module_init(pem_init);
+module_exit(pem_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d.c linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1000 +0,0 @@
-/*
- *  lis3lv02d.c - ST LIS3LV02DL accelerometer driver
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008 Eric Piel
- *  Copyright (C) 2008-2009 Pavel Machek
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/dmi.h>
-#include <linux/module.h>
-#include <linux/types.h>
-#include <linux/platform_device.h>
-#include <linux/interrupt.h>
-#include <linux/input-polldev.h>
-#include <linux/delay.h>
-#include <linux/wait.h>
-#include <linux/poll.h>
-#include <linux/slab.h>
-#include <linux/freezer.h>
-#include <linux/uaccess.h>
-#include <linux/miscdevice.h>
-#include <linux/pm_runtime.h>
-#include <asm/atomic.h>
-#include "lis3lv02d.h"
-
-#define DRIVER_NAME     "lis3lv02d"
-
-/* joystick device poll interval in milliseconds */
-#define MDPS_POLL_INTERVAL 50
-#define MDPS_POLL_MIN	   0
-#define MDPS_POLL_MAX	   2000
-
-#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
-
-#define SELFTEST_OK	       0
-#define SELFTEST_FAIL	       -1
-#define SELFTEST_IRQ	       -2
-
-#define IRQ_LINE0	       0
-#define IRQ_LINE1	       1
-
-/*
- * The sensor can also generate interrupts (DRDY) but it's pretty pointless
- * because they are generated even if the data do not change. So it's better
- * to keep the interrupt for the free-fall event. The values are updated at
- * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
- * some low processor, we poll the sensor only at 20Hz... enough for the
- * joystick.
- */
-
-#define LIS3_PWRON_DELAY_WAI_12B	(5000)
-#define LIS3_PWRON_DELAY_WAI_8B		(3000)
-
-/*
- * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
- * LIS302D spec says: 18 mG / digit
- * LIS3_ACCURACY is used to increase accuracy of the intermediate
- * calculation results.
- */
-#define LIS3_ACCURACY			1024
-/* Sensitivity values for -2G +2G scale */
-#define LIS3_SENSITIVITY_12B		((LIS3_ACCURACY * 1000) / 1024)
-#define LIS3_SENSITIVITY_8B		(18 * LIS3_ACCURACY)
-
-#define LIS3_DEFAULT_FUZZ_12B		3
-#define LIS3_DEFAULT_FLAT_12B		3
-#define LIS3_DEFAULT_FUZZ_8B		1
-#define LIS3_DEFAULT_FLAT_8B		1
-
-struct lis3lv02d lis3_dev = {
-	.misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
-};
-
-EXPORT_SYMBOL_GPL(lis3_dev);
-
-/* just like param_set_int() but does sanity-check so that it won't point
- * over the axis array size
- */
-static int param_set_axis(const char *val, const struct kernel_param *kp)
-{
-	int ret = param_set_int(val, kp);
-	if (!ret) {
-		int val = *(int *)kp->arg;
-		if (val < 0)
-			val = -val;
-		if (!val || val > 3)
-			return -EINVAL;
-	}
-	return ret;
-}
-
-static struct kernel_param_ops param_ops_axis = {
-	.set = param_set_axis,
-	.get = param_get_int,
-};
-
-module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
-MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
-
-static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
-{
-	s8 lo;
-	if (lis3->read(lis3, reg, &lo) < 0)
-		return 0;
-
-	return lo;
-}
-
-static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
-{
-	u8 lo, hi;
-
-	lis3->read(lis3, reg - 1, &lo);
-	lis3->read(lis3, reg, &hi);
-	/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
-	return (s16)((hi << 8) | lo);
-}
-
-/**
- * lis3lv02d_get_axis - For the given axis, give the value converted
- * @axis:      1,2,3 - can also be negative
- * @hw_values: raw values returned by the hardware
- *
- * Returns the converted value.
- */
-static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
-{
-	if (axis > 0)
-		return hw_values[axis - 1];
-	else
-		return -hw_values[-axis - 1];
-}
-
-/**
- * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
- * @lis3: pointer to the device struct
- * @x:    where to store the X axis value
- * @y:    where to store the Y axis value
- * @z:    where to store the Z axis value
- *
- * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
- */
-static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
-{
-	int position[3];
-	int i;
-
-	if (lis3->blkread) {
-		if (lis3_dev.whoami == WAI_12B) {
-			u16 data[3];
-			lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
-			for (i = 0; i < 3; i++)
-				position[i] = (s16)le16_to_cpu(data[i]);
-		} else {
-			u8 data[5];
-			/* Data: x, dummy, y, dummy, z */
-			lis3->blkread(lis3, OUTX, 5, data);
-			for (i = 0; i < 3; i++)
-				position[i] = (s8)data[i * 2];
-		}
-	} else {
-		position[0] = lis3->read_data(lis3, OUTX);
-		position[1] = lis3->read_data(lis3, OUTY);
-		position[2] = lis3->read_data(lis3, OUTZ);
-	}
-
-	for (i = 0; i < 3; i++)
-		position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
-
-	*x = lis3lv02d_get_axis(lis3->ac.x, position);
-	*y = lis3lv02d_get_axis(lis3->ac.y, position);
-	*z = lis3lv02d_get_axis(lis3->ac.z, position);
-}
-
-/* conversion btw sampling rate and the register values */
-static int lis3_12_rates[4] = {40, 160, 640, 2560};
-static int lis3_8_rates[2] = {100, 400};
-static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
-
-/* ODR is Output Data Rate */
-static int lis3lv02d_get_odr(void)
-{
-	u8 ctrl;
-	int shift;
-
-	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-	ctrl &= lis3_dev.odr_mask;
-	shift = ffs(lis3_dev.odr_mask) - 1;
-	return lis3_dev.odrs[(ctrl >> shift)];
-}
-
-static int lis3lv02d_set_odr(int rate)
-{
-	u8 ctrl;
-	int i, len, shift;
-
-	if (!rate)
-		return -EINVAL;
-
-	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
-	ctrl &= ~lis3_dev.odr_mask;
-	len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
-	shift = ffs(lis3_dev.odr_mask) - 1;
-
-	for (i = 0; i < len; i++)
-		if (lis3_dev.odrs[i] == rate) {
-			lis3_dev.write(&lis3_dev, CTRL_REG1,
-					ctrl | (i << shift));
-			return 0;
-		}
-	return -EINVAL;
-}
-
-static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
-{
-	u8 ctlreg, reg;
-	s16 x, y, z;
-	u8 selftest;
-	int ret;
-	u8 ctrl_reg_data;
-	unsigned char irq_cfg;
-
-	mutex_lock(&lis3->mutex);
-
-	irq_cfg = lis3->irq_cfg;
-	if (lis3_dev.whoami == WAI_8B) {
-		lis3->data_ready_count[IRQ_LINE0] = 0;
-		lis3->data_ready_count[IRQ_LINE1] = 0;
-
-		/* Change interrupt cfg to data ready for selftest */
-		atomic_inc(&lis3_dev.wake_thread);
-		lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
-		lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
-		lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
-				~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
-				(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
-	}
-
-	if (lis3_dev.whoami == WAI_3DC) {
-		ctlreg = CTRL_REG4;
-		selftest = CTRL4_ST0;
-	} else {
-		ctlreg = CTRL_REG1;
-		if (lis3_dev.whoami == WAI_12B)
-			selftest = CTRL1_ST;
-		else
-			selftest = CTRL1_STP;
-	}
-
-	lis3->read(lis3, ctlreg, &reg);
-	lis3->write(lis3, ctlreg, (reg | selftest));
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-	/* Read directly to avoid axis remap */
-	x = lis3->read_data(lis3, OUTX);
-	y = lis3->read_data(lis3, OUTY);
-	z = lis3->read_data(lis3, OUTZ);
-
-	/* back to normal settings */
-	lis3->write(lis3, ctlreg, reg);
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-	results[0] = x - lis3->read_data(lis3, OUTX);
-	results[1] = y - lis3->read_data(lis3, OUTY);
-	results[2] = z - lis3->read_data(lis3, OUTZ);
-
-	ret = 0;
-
-	if (lis3_dev.whoami == WAI_8B) {
-		/* Restore original interrupt configuration */
-		atomic_dec(&lis3_dev.wake_thread);
-		lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
-		lis3->irq_cfg = irq_cfg;
-
-		if ((irq_cfg & LIS3_IRQ1_MASK) &&
-			lis3->data_ready_count[IRQ_LINE0] < 2) {
-			ret = SELFTEST_IRQ;
-			goto fail;
-		}
-
-		if ((irq_cfg & LIS3_IRQ2_MASK) &&
-			lis3->data_ready_count[IRQ_LINE1] < 2) {
-			ret = SELFTEST_IRQ;
-			goto fail;
-		}
-	}
-
-	if (lis3->pdata) {
-		int i;
-		for (i = 0; i < 3; i++) {
-			/* Check against selftest acceptance limits */
-			if ((results[i] < lis3->pdata->st_min_limits[i]) ||
-			    (results[i] > lis3->pdata->st_max_limits[i])) {
-				ret = SELFTEST_FAIL;
-				goto fail;
-			}
-		}
-	}
-
-	/* test passed */
-fail:
-	mutex_unlock(&lis3->mutex);
-	return ret;
-}
-
-/*
- * Order of registers in the list affects to order of the restore process.
- * Perhaps it is a good idea to set interrupt enable register as a last one
- * after all other configurations
- */
-static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
-			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
-			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
-			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
-			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
-
-static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
-			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
-			       DD_THSE_L, DD_THSE_H,
-			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
-
-static inline void lis3_context_save(struct lis3lv02d *lis3)
-{
-	int i;
-	for (i = 0; i < lis3->regs_size; i++)
-		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
-	lis3->regs_stored = true;
-}
-
-static inline void lis3_context_restore(struct lis3lv02d *lis3)
-{
-	int i;
-	if (lis3->regs_stored)
-		for (i = 0; i < lis3->regs_size; i++)
-			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
-}
-
-void lis3lv02d_poweroff(struct lis3lv02d *lis3)
-{
-	if (lis3->reg_ctrl)
-		lis3_context_save(lis3);
-	/* disable X,Y,Z axis and power down */
-	lis3->write(lis3, CTRL_REG1, 0x00);
-	if (lis3->reg_ctrl)
-		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
-
-void lis3lv02d_poweron(struct lis3lv02d *lis3)
-{
-	u8 reg;
-
-	lis3->init(lis3);
-
-	/*
-	 * Common configuration
-	 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
-	 *      both have been read. So the value read will always be correct.
-	 * Set BOOT bit to refresh factory tuning values.
-	 */
-	lis3->read(lis3, CTRL_REG2, &reg);
-	if (lis3->whoami ==  WAI_12B)
-		reg |= CTRL2_BDU | CTRL2_BOOT;
-	else
-		reg |= CTRL2_BOOT_8B;
-	lis3->write(lis3, CTRL_REG2, reg);
-
-	/* LIS3 power on delay is quite long */
-	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
-
-	if (lis3->reg_ctrl)
-		lis3_context_restore(lis3);
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
-
-
-static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
-{
-	int x, y, z;
-
-	mutex_lock(&lis3_dev.mutex);
-	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-	input_report_abs(pidev->input, ABS_X, x);
-	input_report_abs(pidev->input, ABS_Y, y);
-	input_report_abs(pidev->input, ABS_Z, z);
-	input_sync(pidev->input);
-	mutex_unlock(&lis3_dev.mutex);
-}
-
-static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
-{
-	if (lis3_dev.pm_dev)
-		pm_runtime_get_sync(lis3_dev.pm_dev);
-
-	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
-		atomic_set(&lis3_dev.wake_thread, 1);
-	/*
-	 * Update coordinates for the case where poll interval is 0 and
-	 * the chip in running purely under interrupt control
-	 */
-	lis3lv02d_joystick_poll(pidev);
-}
-
-static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
-{
-	atomic_set(&lis3_dev.wake_thread, 0);
-	if (lis3_dev.pm_dev)
-		pm_runtime_put(lis3_dev.pm_dev);
-}
-
-static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
-{
-	if (!test_bit(0, &lis3_dev.misc_opened))
-		goto out;
-
-	/*
-	 * Be careful: on some HP laptops the bios force DD when on battery and
-	 * the lid is closed. This leads to interrupts as soon as a little move
-	 * is done.
-	 */
-	atomic_inc(&lis3_dev.count);
-
-	wake_up_interruptible(&lis3_dev.misc_wait);
-	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
-out:
-	if (atomic_read(&lis3_dev.wake_thread))
-		return IRQ_WAKE_THREAD;
-	return IRQ_HANDLED;
-}
-
-static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
-{
-	struct input_dev *dev = lis3->idev->input;
-	u8 click_src;
-
-	mutex_lock(&lis3->mutex);
-	lis3->read(lis3, CLICK_SRC, &click_src);
-
-	if (click_src & CLICK_SINGLE_X) {
-		input_report_key(dev, lis3->mapped_btns[0], 1);
-		input_report_key(dev, lis3->mapped_btns[0], 0);
-	}
-
-	if (click_src & CLICK_SINGLE_Y) {
-		input_report_key(dev, lis3->mapped_btns[1], 1);
-		input_report_key(dev, lis3->mapped_btns[1], 0);
-	}
-
-	if (click_src & CLICK_SINGLE_Z) {
-		input_report_key(dev, lis3->mapped_btns[2], 1);
-		input_report_key(dev, lis3->mapped_btns[2], 0);
-	}
-	input_sync(dev);
-	mutex_unlock(&lis3->mutex);
-}
-
-static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
-{
-	int dummy;
-
-	/* Dummy read to ack interrupt */
-	lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
-	lis3->data_ready_count[index]++;
-}
-
-static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
-{
-	struct lis3lv02d *lis3 = data;
-	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
-
-	if (irq_cfg == LIS3_IRQ1_CLICK)
-		lis302dl_interrupt_handle_click(lis3);
-	else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
-		lis302dl_data_ready(lis3, IRQ_LINE0);
-	else
-		lis3lv02d_joystick_poll(lis3->idev);
-
-	return IRQ_HANDLED;
-}
-
-static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
-{
-	struct lis3lv02d *lis3 = data;
-	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
-
-	if (irq_cfg == LIS3_IRQ2_CLICK)
-		lis302dl_interrupt_handle_click(lis3);
-	else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
-		lis302dl_data_ready(lis3, IRQ_LINE1);
-	else
-		lis3lv02d_joystick_poll(lis3->idev);
-
-	return IRQ_HANDLED;
-}
-
-static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
-{
-	if (test_and_set_bit(0, &lis3_dev.misc_opened))
-		return -EBUSY; /* already open */
-
-	if (lis3_dev.pm_dev)
-		pm_runtime_get_sync(lis3_dev.pm_dev);
-
-	atomic_set(&lis3_dev.count, 0);
-	return 0;
-}
-
-static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
-{
-	fasync_helper(-1, file, 0, &lis3_dev.async_queue);
-	clear_bit(0, &lis3_dev.misc_opened); /* release the device */
-	if (lis3_dev.pm_dev)
-		pm_runtime_put(lis3_dev.pm_dev);
-	return 0;
-}
-
-static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
-				size_t count, loff_t *pos)
-{
-	DECLARE_WAITQUEUE(wait, current);
-	u32 data;
-	unsigned char byte_data;
-	ssize_t retval = 1;
-
-	if (count < 1)
-		return -EINVAL;
-
-	add_wait_queue(&lis3_dev.misc_wait, &wait);
-	while (true) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		data = atomic_xchg(&lis3_dev.count, 0);
-		if (data)
-			break;
-
-		if (file->f_flags & O_NONBLOCK) {
-			retval = -EAGAIN;
-			goto out;
-		}
-
-		if (signal_pending(current)) {
-			retval = -ERESTARTSYS;
-			goto out;
-		}
-
-		schedule();
-	}
-
-	if (data < 255)
-		byte_data = data;
-	else
-		byte_data = 255;
-
-	/* make sure we are not going into copy_to_user() with
-	 * TASK_INTERRUPTIBLE state */
-	set_current_state(TASK_RUNNING);
-	if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
-		retval = -EFAULT;
-
-out:
-	__set_current_state(TASK_RUNNING);
-	remove_wait_queue(&lis3_dev.misc_wait, &wait);
-
-	return retval;
-}
-
-static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
-{
-	poll_wait(file, &lis3_dev.misc_wait, wait);
-	if (atomic_read(&lis3_dev.count))
-		return POLLIN | POLLRDNORM;
-	return 0;
-}
-
-static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
-{
-	return fasync_helper(fd, file, on, &lis3_dev.async_queue);
-}
-
-static const struct file_operations lis3lv02d_misc_fops = {
-	.owner   = THIS_MODULE,
-	.llseek  = no_llseek,
-	.read    = lis3lv02d_misc_read,
-	.open    = lis3lv02d_misc_open,
-	.release = lis3lv02d_misc_release,
-	.poll    = lis3lv02d_misc_poll,
-	.fasync  = lis3lv02d_misc_fasync,
-};
-
-static struct miscdevice lis3lv02d_misc_device = {
-	.minor   = MISC_DYNAMIC_MINOR,
-	.name    = "freefall",
-	.fops    = &lis3lv02d_misc_fops,
-};
-
-int lis3lv02d_joystick_enable(void)
-{
-	struct input_dev *input_dev;
-	int err;
-	int max_val, fuzz, flat;
-	int btns[] = {BTN_X, BTN_Y, BTN_Z};
-
-	if (lis3_dev.idev)
-		return -EINVAL;
-
-	lis3_dev.idev = input_allocate_polled_device();
-	if (!lis3_dev.idev)
-		return -ENOMEM;
-
-	lis3_dev.idev->poll = lis3lv02d_joystick_poll;
-	lis3_dev.idev->open = lis3lv02d_joystick_open;
-	lis3_dev.idev->close = lis3lv02d_joystick_close;
-	lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
-	lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
-	lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
-	input_dev = lis3_dev.idev->input;
-
-	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, input_dev->evbit);
-	max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
-	if (lis3_dev.whoami == WAI_12B) {
-		fuzz = LIS3_DEFAULT_FUZZ_12B;
-		flat = LIS3_DEFAULT_FLAT_12B;
-	} else {
-		fuzz = LIS3_DEFAULT_FUZZ_8B;
-		flat = LIS3_DEFAULT_FLAT_8B;
-	}
-	fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
-	flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
-
-	input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
-	input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
-	input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
-
-	lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
-	lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
-	lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
-
-	err = input_register_polled_device(lis3_dev.idev);
-	if (err) {
-		input_free_polled_device(lis3_dev.idev);
-		lis3_dev.idev = NULL;
-	}
-
-	return err;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
-
-void lis3lv02d_joystick_disable(void)
-{
-	if (lis3_dev.irq)
-		free_irq(lis3_dev.irq, &lis3_dev);
-	if (lis3_dev.pdata && lis3_dev.pdata->irq2)
-		free_irq(lis3_dev.pdata->irq2, &lis3_dev);
-
-	if (!lis3_dev.idev)
-		return;
-
-	if (lis3_dev.irq)
-		misc_deregister(&lis3lv02d_misc_device);
-	input_unregister_polled_device(lis3_dev.idev);
-	input_free_polled_device(lis3_dev.idev);
-	lis3_dev.idev = NULL;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
-
-/* Sysfs stuff */
-static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
-{
-	/*
-	 * SYSFS functions are fast visitors so put-call
-	 * immediately after the get-call. However, keep
-	 * chip running for a while and schedule delayed
-	 * suspend. This way periodic sysfs calls doesn't
-	 * suffer from relatively long power up time.
-	 */
-
-	if (lis3->pm_dev) {
-		pm_runtime_get_sync(lis3->pm_dev);
-		pm_runtime_put_noidle(lis3->pm_dev);
-		pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
-	}
-}
-
-static ssize_t lis3lv02d_selftest_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	s16 values[3];
-
-	static const char ok[] = "OK";
-	static const char fail[] = "FAIL";
-	static const char irq[] = "FAIL_IRQ";
-	const char *res;
-
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	switch (lis3lv02d_selftest(&lis3_dev, values)) {
-	case SELFTEST_FAIL:
-		res = fail;
-		break;
-	case SELFTEST_IRQ:
-		res = irq;
-		break;
-	case SELFTEST_OK:
-	default:
-		res = ok;
-		break;
-	}
-	return sprintf(buf, "%s %d %d %d\n", res,
-		values[0], values[1], values[2]);
-}
-
-static ssize_t lis3lv02d_position_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	int x, y, z;
-
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	mutex_lock(&lis3_dev.mutex);
-	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
-	mutex_unlock(&lis3_dev.mutex);
-	return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
-}
-
-static ssize_t lis3lv02d_rate_show(struct device *dev,
-			struct device_attribute *attr, char *buf)
-{
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	return sprintf(buf, "%d\n", lis3lv02d_get_odr());
-}
-
-static ssize_t lis3lv02d_rate_set(struct device *dev,
-				struct device_attribute *attr, const char *buf,
-				size_t count)
-{
-	unsigned long rate;
-
-	if (strict_strtoul(buf, 0, &rate))
-		return -EINVAL;
-
-	lis3lv02d_sysfs_poweron(&lis3_dev);
-	if (lis3lv02d_set_odr(rate))
-		return -EINVAL;
-
-	return count;
-}
-
-static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
-static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
-static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
-					    lis3lv02d_rate_set);
-
-static struct attribute *lis3lv02d_attributes[] = {
-	&dev_attr_selftest.attr,
-	&dev_attr_position.attr,
-	&dev_attr_rate.attr,
-	NULL
-};
-
-static struct attribute_group lis3lv02d_attribute_group = {
-	.attrs = lis3lv02d_attributes
-};
-
-
-static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
-{
-	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->pdev->dev.kobj, &lis3lv02d_attribute_group);
-}
-
-int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
-{
-	sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
-	platform_device_unregister(lis3->pdev);
-	if (lis3->pm_dev) {
-		/* Barrier after the sysfs remove */
-		pm_runtime_barrier(lis3->pm_dev);
-
-		/* SYSFS may have left chip running. Turn off if necessary */
-		if (!pm_runtime_suspended(lis3->pm_dev))
-			lis3lv02d_poweroff(&lis3_dev);
-
-		pm_runtime_disable(lis3->pm_dev);
-		pm_runtime_set_suspended(lis3->pm_dev);
-	}
-	kfree(lis3->reg_cache);
-	return 0;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
-
-static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
-				struct lis3lv02d_platform_data *p)
-{
-	int err;
-	int ctrl2 = p->hipass_ctrl;
-
-	if (p->click_flags) {
-		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 (dev->idev) {
-			struct input_dev *input_dev = lis3_dev.idev->input;
-			input_set_capability(input_dev, EV_KEY, BTN_X);
-			input_set_capability(input_dev, EV_KEY, BTN_Y);
-			input_set_capability(input_dev, EV_KEY, BTN_Z);
-		}
-	}
-
-	if (p->wakeup_flags) {
-		dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
-		dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
-		/* pdata value + 1 to keep this backward compatible*/
-		dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
-		ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
-	}
-
-	if (p->wakeup_flags2) {
-		dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
-		dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
-		/* pdata value + 1 to keep this backward compatible*/
-		dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
-		ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
-	}
-	/* Configure hipass filters */
-	dev->write(dev, CTRL_REG2, ctrl2);
-
-	if (p->irq2) {
-		err = request_threaded_irq(p->irq2,
-					NULL,
-					lis302dl_interrupt_thread2_8b,
-					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
-					(p->irq_flags2 & IRQF_TRIGGER_MASK),
-					DRIVER_NAME, &lis3_dev);
-		if (err < 0)
-			pr_err("No second IRQ. Limited functionality\n");
-	}
-}
-
-/*
- * Initialise the accelerometer and the various subsystems.
- * Should be rather independent of the bus system.
- */
-int lis3lv02d_init_device(struct lis3lv02d *dev)
-{
-	int err;
-	irq_handler_t thread_fn;
-	int irq_flags = 0;
-
-	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
-
-	switch (dev->whoami) {
-	case WAI_12B:
-		pr_info("12 bits sensor found\n");
-		dev->read_data = lis3lv02d_read_12;
-		dev->mdps_max_val = 2048;
-		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
-		dev->odrs = lis3_12_rates;
-		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
-		dev->scale = LIS3_SENSITIVITY_12B;
-		dev->regs = lis3_wai12_regs;
-		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
-		break;
-	case WAI_8B:
-		pr_info("8 bits sensor found\n");
-		dev->read_data = lis3lv02d_read_8;
-		dev->mdps_max_val = 128;
-		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
-		dev->odrs = lis3_8_rates;
-		dev->odr_mask = CTRL1_DR;
-		dev->scale = LIS3_SENSITIVITY_8B;
-		dev->regs = lis3_wai8_regs;
-		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
-		break;
-	case WAI_3DC:
-		pr_info("8 bits 3DC sensor found\n");
-		dev->read_data = lis3lv02d_read_8;
-		dev->mdps_max_val = 128;
-		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
-		dev->odrs = lis3_3dc_rates;
-		dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
-		dev->scale = LIS3_SENSITIVITY_8B;
-		break;
-	default:
-		pr_err("unknown sensor type 0x%X\n", dev->whoami);
-		return -EINVAL;
-	}
-
-	dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
-				     sizeof(lis3_wai12_regs)), GFP_KERNEL);
-
-	if (dev->reg_cache == NULL) {
-		printk(KERN_ERR DRIVER_NAME "out of memory\n");
-		return -ENOMEM;
-	}
-
-	mutex_init(&dev->mutex);
-	atomic_set(&dev->wake_thread, 0);
-
-	lis3lv02d_add_fs(dev);
-	lis3lv02d_poweron(dev);
-
-	if (dev->pm_dev) {
-		pm_runtime_set_active(dev->pm_dev);
-		pm_runtime_enable(dev->pm_dev);
-	}
-
-	if (lis3lv02d_joystick_enable())
-		pr_err("joystick initialization failed\n");
-
-	/* 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 (dev->whoami == WAI_8B)
-			lis3lv02d_8b_configure(dev, p);
-
-		irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
-
-		dev->irq_cfg = p->irq_cfg;
-		if (p->irq_cfg)
-			dev->write(dev, CTRL_REG3, p->irq_cfg);
-
-		if (p->default_rate)
-			lis3lv02d_set_odr(p->default_rate);
-	}
-
-	/* bail if we did not get an IRQ from the bus layer */
-	if (!dev->irq) {
-		pr_debug("No IRQ. Disabling /dev/freefall\n");
-		goto out;
-	}
-
-	/*
-	 * The sensor can generate interrupts for free-fall and direction
-	 * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
-	 * the things simple and _fast_ we activate it only for free-fall, so
-	 * no need to read register (very slow with ACPI). For the same reason,
-	 * we forbid shared interrupts.
-	 *
-	 * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
-	 * io-apic is not configurable (and generates a warning) but I keep it
-	 * in case of support for other hardware.
-	 */
-	if (dev->pdata && dev->whoami == WAI_8B)
-		thread_fn = lis302dl_interrupt_thread1_8b;
-	else
-		thread_fn = NULL;
-
-	err = request_threaded_irq(dev->irq, lis302dl_interrupt,
-				thread_fn,
-				IRQF_TRIGGER_RISING | IRQF_ONESHOT |
-				irq_flags,
-				DRIVER_NAME, &lis3_dev);
-
-	if (err < 0) {
-		pr_err("Cannot get IRQ\n");
-		goto out;
-	}
-
-	if (misc_register(&lis3lv02d_misc_device))
-		pr_err("misc_register failed\n");
-out:
-	return 0;
-}
-EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
-
-MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
-MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d.h linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d.h
--- linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,291 +0,0 @@
-/*
- *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
- *
- *  Copyright (C) 2007-2008 Yan Burman
- *  Copyright (C) 2008-2009 Eric Piel
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the 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/input-polldev.h>
-#include <linux/regulator/consumer.h>
-
-/*
- * This driver tries to support the "digital" accelerometer chips from
- * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
- * LIS35DE, or LIS202DL. They are very similar in terms of programming, with
- * almost the same registers. In addition to differing on physical properties,
- * they differ on the number of axes (2/3), precision (8/12 bits), and special
- * features (freefall detection, click...). Unfortunately, not all the
- * differences can be probed via a register.
- * They can be connected either via IÂ²C or SPI.
- */
-
-#include <linux/lis3lv02d.h>
-
-enum lis3_reg {
-	WHO_AM_I	= 0x0F,
-	OFFSET_X	= 0x16,
-	OFFSET_Y	= 0x17,
-	OFFSET_Z	= 0x18,
-	GAIN_X		= 0x19,
-	GAIN_Y		= 0x1A,
-	GAIN_Z		= 0x1B,
-	CTRL_REG1	= 0x20,
-	CTRL_REG2	= 0x21,
-	CTRL_REG3	= 0x22,
-	CTRL_REG4	= 0x23,
-	HP_FILTER_RESET	= 0x23,
-	STATUS_REG	= 0x27,
-	OUTX_L		= 0x28,
-	OUTX_H		= 0x29,
-	OUTX		= 0x29,
-	OUTY_L		= 0x2A,
-	OUTY_H		= 0x2B,
-	OUTY		= 0x2B,
-	OUTZ_L		= 0x2C,
-	OUTZ_H		= 0x2D,
-	OUTZ		= 0x2D,
-};
-
-enum lis302d_reg {
-	FF_WU_CFG_1	= 0x30,
-	FF_WU_SRC_1	= 0x31,
-	FF_WU_THS_1	= 0x32,
-	FF_WU_DURATION_1 = 0x33,
-	FF_WU_CFG_2	= 0x34,
-	FF_WU_SRC_2	= 0x35,
-	FF_WU_THS_2	= 0x36,
-	FF_WU_DURATION_2 = 0x37,
-	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 {
-	FF_WU_CFG	= 0x30,
-	FF_WU_SRC	= 0x31,
-	FF_WU_ACK	= 0x32,
-	FF_WU_THS_L	= 0x34,
-	FF_WU_THS_H	= 0x35,
-	FF_WU_DURATION	= 0x36,
-	DD_CFG		= 0x38,
-	DD_SRC		= 0x39,
-	DD_ACK		= 0x3A,
-	DD_THSI_L	= 0x3C,
-	DD_THSI_H	= 0x3D,
-	DD_THSE_L	= 0x3E,
-	DD_THSE_H	= 0x3F,
-};
-
-enum lis3_who_am_i {
-	WAI_3DC		= 0x33,	/* 8 bits: LIS3DC, HP3DC */
-	WAI_12B		= 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
-	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
-	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
-};
-
-enum lis3lv02d_ctrl1_12b {
-	CTRL1_Xen	= 0x01,
-	CTRL1_Yen	= 0x02,
-	CTRL1_Zen	= 0x04,
-	CTRL1_ST	= 0x08,
-	CTRL1_DF0	= 0x10,
-	CTRL1_DF1	= 0x20,
-	CTRL1_PD0	= 0x40,
-	CTRL1_PD1	= 0x80,
-};
-
-/* Delta to ctrl1_12b version */
-enum lis3lv02d_ctrl1_8b {
-	CTRL1_STM	= 0x08,
-	CTRL1_STP	= 0x10,
-	CTRL1_FS	= 0x20,
-	CTRL1_PD	= 0x40,
-	CTRL1_DR	= 0x80,
-};
-
-enum lis3lv02d_ctrl1_3dc {
-	CTRL1_ODR0	= 0x10,
-	CTRL1_ODR1	= 0x20,
-	CTRL1_ODR2	= 0x40,
-	CTRL1_ODR3	= 0x80,
-};
-
-enum lis3lv02d_ctrl2 {
-	CTRL2_DAS	= 0x01,
-	CTRL2_SIM	= 0x02,
-	CTRL2_DRDY	= 0x04,
-	CTRL2_IEN	= 0x08,
-	CTRL2_BOOT	= 0x10,
-	CTRL2_BLE	= 0x20,
-	CTRL2_BDU	= 0x40, /* Block Data Update */
-	CTRL2_FS	= 0x80, /* Full Scale selection */
-};
-
-enum lis3lv02d_ctrl4_3dc {
-	CTRL4_SIM	= 0x01,
-	CTRL4_ST0	= 0x02,
-	CTRL4_ST1	= 0x04,
-	CTRL4_FS0	= 0x10,
-	CTRL4_FS1	= 0x20,
-};
-
-enum lis302d_ctrl2 {
-	HP_FF_WU2	= 0x08,
-	HP_FF_WU1	= 0x04,
-	CTRL2_BOOT_8B   = 0x40,
-};
-
-enum lis3lv02d_ctrl3 {
-	CTRL3_CFS0	= 0x01,
-	CTRL3_CFS1	= 0x02,
-	CTRL3_FDS	= 0x10,
-	CTRL3_HPFF	= 0x20,
-	CTRL3_HPDD	= 0x40,
-	CTRL3_ECK	= 0x80,
-};
-
-enum lis3lv02d_status_reg {
-	STATUS_XDA	= 0x01,
-	STATUS_YDA	= 0x02,
-	STATUS_ZDA	= 0x04,
-	STATUS_XYZDA	= 0x08,
-	STATUS_XOR	= 0x10,
-	STATUS_YOR	= 0x20,
-	STATUS_ZOR	= 0x40,
-	STATUS_XYZOR	= 0x80,
-};
-
-enum lis3lv02d_ff_wu_cfg {
-	FF_WU_CFG_XLIE	= 0x01,
-	FF_WU_CFG_XHIE	= 0x02,
-	FF_WU_CFG_YLIE	= 0x04,
-	FF_WU_CFG_YHIE	= 0x08,
-	FF_WU_CFG_ZLIE	= 0x10,
-	FF_WU_CFG_ZHIE	= 0x20,
-	FF_WU_CFG_LIR	= 0x40,
-	FF_WU_CFG_AOI	= 0x80,
-};
-
-enum lis3lv02d_ff_wu_src {
-	FF_WU_SRC_XL	= 0x01,
-	FF_WU_SRC_XH	= 0x02,
-	FF_WU_SRC_YL	= 0x04,
-	FF_WU_SRC_YH	= 0x08,
-	FF_WU_SRC_ZL	= 0x10,
-	FF_WU_SRC_ZH	= 0x20,
-	FF_WU_SRC_IA	= 0x40,
-};
-
-enum lis3lv02d_dd_cfg {
-	DD_CFG_XLIE	= 0x01,
-	DD_CFG_XHIE	= 0x02,
-	DD_CFG_YLIE	= 0x04,
-	DD_CFG_YHIE	= 0x08,
-	DD_CFG_ZLIE	= 0x10,
-	DD_CFG_ZHIE	= 0x20,
-	DD_CFG_LIR	= 0x40,
-	DD_CFG_IEND	= 0x80,
-};
-
-enum lis3lv02d_dd_src {
-	DD_SRC_XL	= 0x01,
-	DD_SRC_XH	= 0x02,
-	DD_SRC_YL	= 0x04,
-	DD_SRC_YH	= 0x08,
-	DD_SRC_ZL	= 0x10,
-	DD_SRC_ZH	= 0x20,
-	DD_SRC_IA	= 0x40,
-};
-
-enum lis3lv02d_click_src_8b {
-	CLICK_SINGLE_X	= 0x01,
-	CLICK_DOUBLE_X	= 0x02,
-	CLICK_SINGLE_Y	= 0x04,
-	CLICK_DOUBLE_Y	= 0x08,
-	CLICK_SINGLE_Z	= 0x10,
-	CLICK_DOUBLE_Z	= 0x20,
-	CLICK_IA	= 0x40,
-};
-
-enum lis3lv02d_reg_state {
-	LIS3_REG_OFF	= 0x00,
-	LIS3_REG_ON	= 0x01,
-};
-
-union axis_conversion {
-	struct {
-		int x, y, z;
-	};
-	int as_array[3];
-
-};
-
-struct lis3lv02d {
-	void			*bus_priv; /* used by the bus layer only */
-	struct device		*pm_dev; /* for pm_runtime purposes */
-	int (*init) (struct lis3lv02d *lis3);
-	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
-	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
-	int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
-	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
-
-	int                     *odrs;     /* Supported output data rates */
-	u8			*regs;	   /* Regs to store / restore */
-	int			regs_size;
-	u8                      *reg_cache;
-	bool			regs_stored;
-	u8                      odr_mask;  /* ODR bit mask */
-	u8			whoami;    /* indicates measurement precision */
-	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
-	int			mdps_max_val;
-	int			pwron_delay;
-	int                     scale; /*
-					* relationship between 1 LBS and mG
-					* (1/1000th of earth gravity)
-					*/
-
-	struct input_polled_dev	*idev;     /* input device */
-	struct platform_device	*pdev;     /* platform device */
-	struct regulator_bulk_data regulators[2];
-	atomic_t		count;     /* interrupt count after last read */
-	union axis_conversion	ac;        /* hw -> logical axis */
-	int			mapped_btns[3];
-
-	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 */
-	int                     data_ready_count[2];
-	atomic_t		wake_thread;
-	unsigned char           irq_cfg;
-
-	struct lis3lv02d_platform_data *pdata;	/* for passing board config */
-	struct mutex		mutex;     /* Serialize poll and selftest */
-};
-
-int lis3lv02d_init_device(struct lis3lv02d *lis3);
-int lis3lv02d_joystick_enable(void);
-void lis3lv02d_joystick_disable(void);
-void lis3lv02d_poweroff(struct lis3lv02d *lis3);
-void lis3lv02d_poweron(struct lis3lv02d *lis3);
-int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
-
-extern struct lis3lv02d lis3_dev;
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d_i2c.c linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d_i2c.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d_i2c.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,279 +0,0 @@
-/*
- * drivers/hwmon/lis3lv02d_i2c.c
- *
- * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
- * Driver is based on corresponding SPI driver written by Daniel Mack
- * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
- *
- * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
- *
- * Contact: Samu Onkalo <samu.p.onkalo@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
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/i2c.h>
-#include <linux/pm_runtime.h>
-#include <linux/delay.h>
-#include "lis3lv02d.h"
-
-#define DRV_NAME 	"lis3lv02d_i2c"
-
-static const char reg_vdd[]    = "Vdd";
-static const char reg_vdd_io[] = "Vdd_IO";
-
-static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
-{
-	int ret;
-	if (state == LIS3_REG_OFF) {
-		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
-					lis3->regulators);
-	} else {
-		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
-					lis3->regulators);
-		/* Chip needs time to wakeup. Not mentioned in datasheet */
-		usleep_range(10000, 20000);
-	}
-	return ret;
-}
-
-static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
-{
-	struct i2c_client *c = lis3->bus_priv;
-	return i2c_smbus_write_byte_data(c, reg, value);
-}
-
-static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
-{
-	struct i2c_client *c = lis3->bus_priv;
-	*v = i2c_smbus_read_byte_data(c, reg);
-	return 0;
-}
-
-static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
-				u8 *v)
-{
-	struct i2c_client *c = lis3->bus_priv;
-	reg |= (1 << 7); /* 7th bit enables address auto incrementation */
-	return i2c_smbus_read_i2c_block_data(c, reg, len, v);
-}
-
-static int lis3_i2c_init(struct lis3lv02d *lis3)
-{
-	u8 reg;
-	int ret;
-
-	if (lis3->reg_ctrl)
-		lis3_reg_ctrl(lis3, LIS3_REG_ON);
-
-	lis3->read(lis3, WHO_AM_I, &reg);
-	if (reg != lis3->whoami)
-		printk(KERN_ERR "lis3: power on failure\n");
-
-	/* power up the device */
-	ret = lis3->read(lis3, CTRL_REG1, &reg);
-	if (ret < 0)
-		return ret;
-
-	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
-	return lis3->write(lis3, CTRL_REG1, reg);
-}
-
-/* Default axis mapping but it can be overwritten by platform data */
-static union axis_conversion lis3lv02d_axis_map =
-	{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
-
-static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
-					const struct i2c_device_id *id)
-{
-	int ret = 0;
-	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
-
-	if (pdata) {
-		/* Regulator control is optional */
-		if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
-			lis3_dev.reg_ctrl = lis3_reg_ctrl;
-
-		if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
-			(i2c_check_functionality(client->adapter,
-						I2C_FUNC_SMBUS_I2C_BLOCK)))
-			lis3_dev.blkread  = lis3_i2c_blockread;
-
-		if (pdata->axis_x)
-			lis3lv02d_axis_map.x = pdata->axis_x;
-
-		if (pdata->axis_y)
-			lis3lv02d_axis_map.y = pdata->axis_y;
-
-		if (pdata->axis_z)
-			lis3lv02d_axis_map.z = pdata->axis_z;
-
-		if (pdata->setup_resources)
-			ret = pdata->setup_resources();
-
-		if (ret)
-			goto fail;
-	}
-
-	if (lis3_dev.reg_ctrl) {
-		lis3_dev.regulators[0].supply = reg_vdd;
-		lis3_dev.regulators[1].supply = reg_vdd_io;
-		ret = regulator_bulk_get(&client->dev,
-					ARRAY_SIZE(lis3_dev.regulators),
-					lis3_dev.regulators);
-		if (ret < 0)
-			goto fail;
-	}
-
-	lis3_dev.pdata	  = pdata;
-	lis3_dev.bus_priv = client;
-	lis3_dev.init	  = lis3_i2c_init;
-	lis3_dev.read	  = lis3_i2c_read;
-	lis3_dev.write	  = lis3_i2c_write;
-	lis3_dev.irq	  = client->irq;
-	lis3_dev.ac	  = lis3lv02d_axis_map;
-	lis3_dev.pm_dev	  = &client->dev;
-
-	i2c_set_clientdata(client, &lis3_dev);
-
-	/* Provide power over the init call */
-	if (lis3_dev.reg_ctrl)
-		lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
-
-	ret = lis3lv02d_init_device(&lis3_dev);
-
-	if (lis3_dev.reg_ctrl)
-		lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
-
-	if (ret == 0)
-		return 0;
-fail:
-	if (pdata && pdata->release_resources)
-		pdata->release_resources();
-	return ret;
-}
-
-static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
-{
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
-
-	if (pdata && pdata->release_resources)
-		pdata->release_resources();
-
-	lis3lv02d_joystick_disable();
-	lis3lv02d_remove_fs(&lis3_dev);
-
-	if (lis3_dev.reg_ctrl)
-		regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
-				lis3_dev.regulators);
-	return 0;
-}
-
-#ifdef CONFIG_PM_SLEEP
-static int lis3lv02d_i2c_suspend(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-		lis3lv02d_poweroff(lis3);
-	return 0;
-}
-
-static int lis3lv02d_i2c_resume(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	/*
-	 * pm_runtime documentation says that devices should always
-	 * be powered on at resume. Pm_runtime turns them off after system
-	 * wide resume is complete.
-	 */
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
-		pm_runtime_suspended(dev))
-		lis3lv02d_poweron(lis3);
-
-	return 0;
-}
-#endif /* CONFIG_PM_SLEEP */
-
-#ifdef CONFIG_PM_RUNTIME
-static int lis3_i2c_runtime_suspend(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	lis3lv02d_poweroff(lis3);
-	return 0;
-}
-
-static int lis3_i2c_runtime_resume(struct device *dev)
-{
-	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
-	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
-
-	lis3lv02d_poweron(lis3);
-	return 0;
-}
-#endif /* CONFIG_PM_RUNTIME */
-
-static const struct i2c_device_id lis3lv02d_id[] = {
-	{"lis3lv02d", 0 },
-	{}
-};
-
-MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
-
-static const struct dev_pm_ops lis3_pm_ops = {
-	SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
-				lis3lv02d_i2c_resume)
-	SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
-			   lis3_i2c_runtime_resume,
-			   NULL)
-};
-
-static struct i2c_driver lis3lv02d_i2c_driver = {
-	.driver	 = {
-		.name   = DRV_NAME,
-		.owner  = THIS_MODULE,
-		.pm     = &lis3_pm_ops,
-	},
-	.probe	= lis3lv02d_i2c_probe,
-	.remove	= __devexit_p(lis3lv02d_i2c_remove),
-	.id_table = lis3lv02d_id,
-};
-
-static int __init lis3lv02d_init(void)
-{
-	return i2c_add_driver(&lis3lv02d_i2c_driver);
-}
-
-static void __exit lis3lv02d_exit(void)
-{
-	i2c_del_driver(&lis3lv02d_i2c_driver);
-}
-
-MODULE_AUTHOR("Nokia Corporation");
-MODULE_DESCRIPTION("lis3lv02d I2C interface");
-MODULE_LICENSE("GPL");
-
-module_init(lis3lv02d_init);
-module_exit(lis3lv02d_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d_spi.c linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d_spi.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lis3lv02d_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lis3lv02d_spi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,144 +0,0 @@
-/*
- * lis3lv02d_spi - SPI glue layer for lis3lv02d
- *
- * Copyright (c) 2009 Daniel Mack <daniel@caiaq.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
- *  publishhed by the Free Software Foundation.
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/workqueue.h>
-#include <linux/spi/spi.h>
-
-#include "lis3lv02d.h"
-
-#define DRV_NAME 	"lis3lv02d_spi"
-#define LIS3_SPI_READ	0x80
-
-static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
-{
-	struct spi_device *spi = lis3->bus_priv;
-	int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
-	if (ret < 0)
-		return -EINVAL;
-
-	*v = (u8) ret;
-	return 0;
-}
-
-static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
-{
-	u8 tmp[2] = { reg, val };
-	struct spi_device *spi = lis3->bus_priv;
-	return spi_write(spi, tmp, sizeof(tmp));
-}
-
-static int lis3_spi_init(struct lis3lv02d *lis3)
-{
-	u8 reg;
-	int ret;
-
-	/* power up the device */
-	ret = lis3->read(lis3, CTRL_REG1, &reg);
-	if (ret < 0)
-		return ret;
-
-	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
-	return lis3->write(lis3, CTRL_REG1, reg);
-}
-
-static union axis_conversion lis3lv02d_axis_normal =
-	{ .as_array = { 1, 2, 3 } };
-
-static int __devinit lis302dl_spi_probe(struct spi_device *spi)
-{
-	int ret;
-
-	spi->bits_per_word = 8;
-	spi->mode = SPI_MODE_0;
-	ret = spi_setup(spi);
-	if (ret < 0)
-		return ret;
-
-	lis3_dev.bus_priv	= spi;
-	lis3_dev.init		= lis3_spi_init;
-	lis3_dev.read		= lis3_spi_read;
-	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);
-
-	return lis3lv02d_init_device(&lis3_dev);
-}
-
-static int __devexit lis302dl_spi_remove(struct spi_device *spi)
-{
-	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-	lis3lv02d_joystick_disable();
-	lis3lv02d_poweroff(lis3);
-
-	return lis3lv02d_remove_fs(&lis3_dev);
-}
-
-#ifdef CONFIG_PM
-static int lis3lv02d_spi_suspend(struct spi_device *spi, pm_message_t mesg)
-{
-	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-		lis3lv02d_poweroff(&lis3_dev);
-
-	return 0;
-}
-
-static int lis3lv02d_spi_resume(struct spi_device *spi)
-{
-	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
-
-	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
-		lis3lv02d_poweron(lis3);
-
-	return 0;
-}
-
-#else
-#define lis3lv02d_spi_suspend	NULL
-#define lis3lv02d_spi_resume	NULL
-#endif
-
-static struct spi_driver lis302dl_spi_driver = {
-	.driver	 = {
-		.name   = DRV_NAME,
-		.owner  = THIS_MODULE,
-	},
-	.probe	= lis302dl_spi_probe,
-	.remove	= __devexit_p(lis302dl_spi_remove),
-	.suspend = lis3lv02d_spi_suspend,
-	.resume  = lis3lv02d_spi_resume,
-};
-
-static int __init lis302dl_init(void)
-{
-	return spi_register_driver(&lis302dl_spi_driver);
-}
-
-static void __exit lis302dl_exit(void)
-{
-	spi_unregister_driver(&lis302dl_spi_driver);
-}
-
-module_init(lis302dl_init);
-module_exit(lis302dl_exit);
-
-MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
-MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("spi:" DRV_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lm75.c linux-libre-2.6.39-gnu/drivers/hwmon/lm75.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lm75.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lm75.c	2011-05-19 00:06:34.000000000 -0400
@@ -232,13 +232,16 @@
 };
 MODULE_DEVICE_TABLE(i2c, lm75_ids);
 
+#define LM75A_ID 0xA1
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm75_detect(struct i2c_client *new_client,
 		       struct i2c_board_info *info)
 {
 	struct i2c_adapter *adapter = new_client->adapter;
 	int i;
-	int cur, conf, hyst, os;
+	int conf, hyst, os;
+	bool is_lm75a = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
 				     I2C_FUNC_SMBUS_WORD_DATA))
@@ -250,37 +253,58 @@
 	   addresses 0x04-0x07 returning the last read value.
 	   The cycling+unused addresses combination is not tested,
 	   since it would significantly slow the detection down and would
-	   hardly add any value. */
+	   hardly add any value.
 
-	/* Unused addresses */
-	cur = i2c_smbus_read_word_data(new_client, 0);
-	conf = i2c_smbus_read_byte_data(new_client, 1);
-	hyst = i2c_smbus_read_word_data(new_client, 2);
-	if (i2c_smbus_read_word_data(new_client, 4) != hyst
-	 || i2c_smbus_read_word_data(new_client, 5) != hyst
-	 || i2c_smbus_read_word_data(new_client, 6) != hyst
-	 || i2c_smbus_read_word_data(new_client, 7) != hyst)
-		return -ENODEV;
-	os = i2c_smbus_read_word_data(new_client, 3);
-	if (i2c_smbus_read_word_data(new_client, 4) != os
-	 || i2c_smbus_read_word_data(new_client, 5) != os
-	 || i2c_smbus_read_word_data(new_client, 6) != os
-	 || i2c_smbus_read_word_data(new_client, 7) != os)
-		return -ENODEV;
+	   The National Semiconductor LM75A is different than earlier
+	   LM75s.  It has an ID byte of 0xaX (where X is the chip
+	   revision, with 1 being the only revision in existence) in
+	   register 7, and unused registers return 0xff rather than the
+	   last read value. */
 
 	/* Unused bits */
+	conf = i2c_smbus_read_byte_data(new_client, 1);
 	if (conf & 0xe0)
 		return -ENODEV;
 
+	/* First check for LM75A */
+	if (i2c_smbus_read_byte_data(new_client, 7) == LM75A_ID) {
+		/* LM75A returns 0xff on unused registers so
+		   just to be sure we check for that too. */
+		if (i2c_smbus_read_byte_data(new_client, 4) != 0xff
+		 || i2c_smbus_read_byte_data(new_client, 5) != 0xff
+		 || i2c_smbus_read_byte_data(new_client, 6) != 0xff)
+			return -ENODEV;
+		is_lm75a = 1;
+		hyst = i2c_smbus_read_byte_data(new_client, 2);
+		os = i2c_smbus_read_byte_data(new_client, 3);
+	} else { /* Traditional style LM75 detection */
+		/* Unused addresses */
+		hyst = i2c_smbus_read_byte_data(new_client, 2);
+		if (i2c_smbus_read_byte_data(new_client, 4) != hyst
+		 || i2c_smbus_read_byte_data(new_client, 5) != hyst
+		 || i2c_smbus_read_byte_data(new_client, 6) != hyst
+		 || i2c_smbus_read_byte_data(new_client, 7) != hyst)
+			return -ENODEV;
+		os = i2c_smbus_read_byte_data(new_client, 3);
+		if (i2c_smbus_read_byte_data(new_client, 4) != os
+		 || i2c_smbus_read_byte_data(new_client, 5) != os
+		 || i2c_smbus_read_byte_data(new_client, 6) != os
+		 || i2c_smbus_read_byte_data(new_client, 7) != os)
+			return -ENODEV;
+	}
+
 	/* Addresses cycling */
-	for (i = 8; i < 0xff; i += 8) {
+	for (i = 8; i <= 248; i += 40) {
 		if (i2c_smbus_read_byte_data(new_client, i + 1) != conf
-		 || i2c_smbus_read_word_data(new_client, i + 2) != hyst
-		 || i2c_smbus_read_word_data(new_client, i + 3) != os)
+		 || i2c_smbus_read_byte_data(new_client, i + 2) != hyst
+		 || i2c_smbus_read_byte_data(new_client, i + 3) != os)
+			return -ENODEV;
+		if (is_lm75a && i2c_smbus_read_byte_data(new_client, i + 7)
+				!= LM75A_ID)
 			return -ENODEV;
 	}
 
-	strlcpy(info->type, "lm75", I2C_NAME_SIZE);
+	strlcpy(info->type, is_lm75a ? "lm75a" : "lm75", I2C_NAME_SIZE);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lm85.c linux-libre-2.6.39-gnu/drivers/hwmon/lm85.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lm85.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lm85.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
 enum chips {
 	any_chip, lm85b, lm85c,
 	adm1027, adt7463, adt7468,
-	emc6d100, emc6d102, emc6d103
+	emc6d100, emc6d102, emc6d103, emc6d103s
 };
 
 /* The LM85 registers */
@@ -130,7 +130,7 @@
    these macros are called: arguments may be evaluated more than once.
  */
 
-/* IN are scaled acording to built-in resistors */
+/* IN are scaled according to built-in resistors */
 static const int lm85_scaling[] = {  /* .001 Volts */
 	2500, 2250, 3300, 5000, 12000,
 	3300, 1500, 1800 /*EMC6D100*/
@@ -283,10 +283,6 @@
 	u8 hyst;	/* Low limit hysteresis. (0-15) */
 	u8 range;	/* Temp range, encoded */
 	s8 critical;	/* "All fans ON" temp limit */
-	u8 off_desired; /* Actual "off" temperature specified.  Preserved
-			 * to prevent "drift" as other autofan control
-			 * values change.
-			 */
 	u8 max_desired; /* Actual "max" temperature specified.  Preserved
 			 * to prevent "drift" as other autofan control
 			 * values change.
@@ -306,6 +302,8 @@
 	const int *freq_map;
 	enum chips type;
 
+	bool has_vid5;	/* true if VID5 is configured for ADT7463 or ADT7468 */
+
 	struct mutex update_lock;
 	int valid;		/* !=0 if following fields are valid */
 	unsigned long last_reading;	/* In jiffies */
@@ -352,6 +350,7 @@
 	{ "emc6d101", emc6d100 },
 	{ "emc6d102", emc6d102 },
 	{ "emc6d103", emc6d103 },
+	{ "emc6d103s", emc6d103s },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, lm85_id);
@@ -420,8 +419,7 @@
 	struct lm85_data *data = lm85_update_device(dev);
 	int vid;
 
-	if ((data->type == adt7463 || data->type == adt7468) &&
-	    (data->vid & 0x80)) {
+	if (data->has_vid5) {
 		/* 6-pin VID (VRM 10) */
 		vid = vid_from_reg(data->vid & 0x3f, data->vrm);
 	} else {
@@ -891,7 +889,6 @@
 
 	mutex_lock(&data->update_lock);
 	min = TEMP_FROM_REG(data->zone[nr].limit);
-	data->zone[nr].off_desired = TEMP_TO_REG(val);
 	data->zone[nr].hyst = HYST_TO_REG(min - val);
 	if (nr == 0 || nr == 1) {
 		lm85_write_value(client, LM85_REG_AFAN_HYST1,
@@ -934,18 +931,6 @@
 		((data->zone[nr].range & 0x0f) << 4)
 		| (data->pwm_freq[nr] & 0x07));
 
-/* Update temp_auto_hyst and temp_auto_off */
-	data->zone[nr].hyst = HYST_TO_REG(TEMP_FROM_REG(
-		data->zone[nr].limit) - TEMP_FROM_REG(
-		data->zone[nr].off_desired));
-	if (nr == 0 || nr == 1) {
-		lm85_write_value(client, LM85_REG_AFAN_HYST1,
-			(data->zone[0].hyst << 4)
-			| data->zone[1].hyst);
-	} else {
-		lm85_write_value(client, LM85_REG_AFAN_HYST2,
-			(data->zone[2].hyst << 4));
-	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1084,13 +1069,7 @@
 	&sensor_dev_attr_pwm1_auto_pwm_min.dev_attr.attr,
 	&sensor_dev_attr_pwm2_auto_pwm_min.dev_attr.attr,
 	&sensor_dev_attr_pwm3_auto_pwm_min.dev_attr.attr,
-	&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
-	&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
-	&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
 
-	&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
-	&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
-	&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
 	&sensor_dev_attr_temp1_auto_temp_min.dev_attr.attr,
 	&sensor_dev_attr_temp2_auto_temp_min.dev_attr.attr,
 	&sensor_dev_attr_temp3_auto_temp_min.dev_attr.attr,
@@ -1111,6 +1090,28 @@
 	.attrs = lm85_attributes,
 };
 
+static struct attribute *lm85_attributes_minctl[] = {
+	&sensor_dev_attr_pwm1_auto_pwm_minctl.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_pwm_minctl.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_pwm_minctl.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group lm85_group_minctl = {
+	.attrs = lm85_attributes_minctl,
+};
+
+static struct attribute *lm85_attributes_temp_off[] = {
+	&sensor_dev_attr_temp1_auto_temp_off.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_temp_off.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_temp_off.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group lm85_group_temp_off = {
+	.attrs = lm85_attributes_temp_off,
+};
+
 static struct attribute *lm85_attributes_in4[] = {
 	&sensor_dev_attr_in4_input.dev_attr.attr,
 	&sensor_dev_attr_in4_min.dev_attr.attr,
@@ -1258,16 +1259,9 @@
 		case LM85_VERSTEP_EMC6D103_A1:
 			type_name = "emc6d103";
 			break;
-		/*
-		 * Registers apparently missing in EMC6D103S/EMC6D103:A2
-		 * compared to EMC6D103:A0, EMC6D103:A1, and EMC6D102
-		 * (according to the data sheets), but used unconditionally
-		 * in the driver: 62[5:7], 6D[0:7], and 6E[0:7].
-		 * So skip EMC6D103S for now.
 		case LM85_VERSTEP_EMC6D103S:
 			type_name = "emc6d103s";
 			break;
-		 */
 		}
 	} else {
 		dev_dbg(&adapter->dev,
@@ -1280,6 +1274,19 @@
 	return 0;
 }
 
+static void lm85_remove_files(struct i2c_client *client, struct lm85_data *data)
+{
+	sysfs_remove_group(&client->dev.kobj, &lm85_group);
+	if (data->type != emc6d103s) {
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_minctl);
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_temp_off);
+	}
+	if (!data->has_vid5)
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
+	if (data->type == emc6d100)
+		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
+}
+
 static int lm85_probe(struct i2c_client *client,
 		      const struct i2c_device_id *id)
 {
@@ -1302,6 +1309,7 @@
 	case emc6d100:
 	case emc6d102:
 	case emc6d103:
+	case emc6d103s:
 		data->freq_map = adm1027_freq_map;
 		break;
 	default:
@@ -1319,11 +1327,26 @@
 	if (err)
 		goto err_kfree;
 
+	/* minctl and temp_off exist on all chips except emc6d103s */
+	if (data->type != emc6d103s) {
+		err = sysfs_create_group(&client->dev.kobj, &lm85_group_minctl);
+		if (err)
+			goto err_remove_files;
+		err = sysfs_create_group(&client->dev.kobj,
+					 &lm85_group_temp_off);
+		if (err)
+			goto err_remove_files;
+	}
+
 	/* The ADT7463/68 have an optional VRM 10 mode where pin 21 is used
 	   as a sixth digital VID input rather than an analog input. */
-	data->vid = lm85_read_value(client, LM85_REG_VID);
-	if (!((data->type == adt7463 || data->type == adt7468) &&
-	    (data->vid & 0x80)))
+	if (data->type == adt7463 || data->type == adt7468) {
+		u8 vid = lm85_read_value(client, LM85_REG_VID);
+		if (vid & 0x80)
+			data->has_vid5 = true;
+	}
+
+	if (!data->has_vid5)
 		if ((err = sysfs_create_group(&client->dev.kobj,
 					&lm85_group_in4)))
 			goto err_remove_files;
@@ -1344,10 +1367,7 @@
 
 	/* Error out and cleanup code */
  err_remove_files:
-	sysfs_remove_group(&client->dev.kobj, &lm85_group);
-	sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
-	if (data->type == emc6d100)
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
+	lm85_remove_files(client, data);
  err_kfree:
 	kfree(data);
 	return err;
@@ -1357,10 +1377,7 @@
 {
 	struct lm85_data *data = i2c_get_clientdata(client);
 	hwmon_device_unregister(data->hwmon_dev);
-	sysfs_remove_group(&client->dev.kobj, &lm85_group);
-	sysfs_remove_group(&client->dev.kobj, &lm85_group_in4);
-	if (data->type == emc6d100)
-		sysfs_remove_group(&client->dev.kobj, &lm85_group_in567);
+	lm85_remove_files(client, data);
 	kfree(data);
 	return 0;
 }
@@ -1457,11 +1474,8 @@
 			    lm85_read_value(client, LM85_REG_FAN(i));
 		}
 
-		if (!((data->type == adt7463 || data->type == adt7468) &&
-		    (data->vid & 0x80))) {
-			data->in[4] = lm85_read_value(client,
-				      LM85_REG_IN(4));
-		}
+		if (!data->has_vid5)
+			data->in[4] = lm85_read_value(client, LM85_REG_IN(4));
 
 		if (data->type == adt7468)
 			data->cfg5 = lm85_read_value(client, ADT7468_REG_CFG5);
@@ -1487,7 +1501,8 @@
 			/* More alarm bits */
 			data->alarms |= lm85_read_value(client,
 						EMC6D100_REG_ALARM3) << 16;
-		} else if (data->type == emc6d102 || data->type == emc6d103) {
+		} else if (data->type == emc6d102 || data->type == emc6d103 ||
+			   data->type == emc6d103s) {
 			/* Have to read LSB bits after the MSB ones because
 			   the reading of the MSB bits has frozen the
 			   LSBs (backward from the ADM1027).
@@ -1528,8 +1543,7 @@
 			    lm85_read_value(client, LM85_REG_FAN_MIN(i));
 		}
 
-		if (!((data->type == adt7463 || data->type == adt7468) &&
-		    (data->vid & 0x80))) {
+		if (!data->has_vid5)  {
 			data->in_min[4] = lm85_read_value(client,
 					  LM85_REG_IN_MIN(4));
 			data->in_max[4] = lm85_read_value(client,
@@ -1573,17 +1587,19 @@
 			}
 		}
 
-		i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
-		data->autofan[0].min_off = (i & 0x20) != 0;
-		data->autofan[1].min_off = (i & 0x40) != 0;
-		data->autofan[2].min_off = (i & 0x80) != 0;
+		if (data->type != emc6d103s) {
+			i = lm85_read_value(client, LM85_REG_AFAN_SPIKE1);
+			data->autofan[0].min_off = (i & 0x20) != 0;
+			data->autofan[1].min_off = (i & 0x40) != 0;
+			data->autofan[2].min_off = (i & 0x80) != 0;
 
-		i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
-		data->zone[0].hyst = i >> 4;
-		data->zone[1].hyst = i & 0x0f;
+			i = lm85_read_value(client, LM85_REG_AFAN_HYST1);
+			data->zone[0].hyst = i >> 4;
+			data->zone[1].hyst = i & 0x0f;
 
-		i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
-		data->zone[2].hyst = i >> 4;
+			i = lm85_read_value(client, LM85_REG_AFAN_HYST2);
+			data->zone[2].hyst = i >> 4;
+		}
 
 		data->last_config = jiffies;
 	}  /* last_config */
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/lm90.c linux-libre-2.6.39-gnu/drivers/hwmon/lm90.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/lm90.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/lm90.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,10 +49,10 @@
  * chips, but support three temperature sensors instead of two. MAX6695
  * and MAX6696 only differ in the pinout so they can be treated identically.
  *
- * This driver also supports the ADT7461 chip from Analog Devices.
- * It's supported in both compatibility and extended mode. It is mostly
- * compatible with LM90 except for a data format difference for the
- * temperature value registers.
+ * This driver also supports ADT7461 and ADT7461A from Analog Devices as well as
+ * NCT1008 from ON Semiconductor. The chips are supported in both compatibility
+ * and extended mode. They are mostly compatible with LM90 except for a data
+ * format difference for the temperature value registers.
  *
  * Since the LM90 was the first chipset supported by this driver, most
  * comments will refer to this chipset, but are actually general and
@@ -88,9 +88,10 @@
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
  * MAX6659, MAX6680 and MAX6681.
- * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6649, MAX6657,
- * MAX6658 and W83L771 have address 0x4c.
- * ADM1032-2, ADT7461-2, LM89-1, LM99-1 and MAX6646 have address 0x4d.
+ * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, ADT7461A, MAX6649,
+ * MAX6657, MAX6658, NCT1008 and W83L771 have address 0x4c.
+ * ADM1032-2, ADT7461-2, ADT7461A-2, LM89-1, LM99-1, MAX6646, and NCT1008D
+ * have address 0x4d.
  * MAX6647 has address 0x4e.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e.
  * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
@@ -174,6 +175,7 @@
 static const struct i2c_device_id lm90_id[] = {
 	{ "adm1032", adm1032 },
 	{ "adt7461", adt7461 },
+	{ "adt7461a", adt7461 },
 	{ "lm90", lm90 },
 	{ "lm86", lm86 },
 	{ "lm89", lm86 },
@@ -188,6 +190,7 @@
 	{ "max6681", max6680 },
 	{ "max6695", max6696 },
 	{ "max6696", max6696 },
+	{ "nct1008", adt7461 },
 	{ "w83l771", w83l771 },
 	{ }
 };
@@ -356,7 +359,7 @@
 	/*
 	 * There is a trick here. We have to read two registers to have the
 	 * sensor temperature, but we have to beware a conversion could occur
-	 * inbetween the readings. The datasheet says we should either use
+	 * between the readings. The datasheet says we should either use
 	 * the one-shot conversion register, which we don't want to do
 	 * (disables hardware monitoring) or monitor the busy bit, which is
 	 * impossible (we can't read the values and monitor that bit at the
@@ -1153,6 +1156,11 @@
 		 && (reg_config1 & 0x1B) == 0x00
 		 && reg_convrate <= 0x0A) {
 			name = "adt7461";
+		} else
+		if (chip_id == 0x57 /* ADT7461A, NCT1008 */
+		 && (reg_config1 & 0x1B) == 0x00
+		 && reg_convrate <= 0x0A) {
+			name = "adt7461a";
 		}
 	} else
 	if (man_id == 0x4D) { /* Maxim */
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/ltc4151.c linux-libre-2.6.39-gnu/drivers/hwmon/ltc4151.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/ltc4151.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/ltc4151.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,256 @@
+/*
+ * Driver for Linear Technology LTC4151 High Voltage I2C Current
+ * and Voltage Monitor
+ *
+ * Copyright (C) 2011 AppearTV AS
+ *
+ * Derived from:
+ *
+ *  Driver for Linear Technology LTC4261 I2C Negative Voltage Hot
+ *  Swap Controller
+ *  Copyright (C) 2010 Ericsson AB.
+ *
+ * Datasheet: http://www.linear.com/docs/Datasheet/4151fc.pdf
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+
+/* chip registers */
+#define LTC4151_SENSE_H	0x00
+#define LTC4151_SENSE_L	0x01
+#define LTC4151_VIN_H	0x02
+#define LTC4151_VIN_L	0x03
+#define LTC4151_ADIN_H	0x04
+#define LTC4151_ADIN_L	0x05
+
+struct ltc4151_data {
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	bool valid;
+	unsigned long last_updated; /* in jiffies */
+
+	/* Registers */
+	u8 regs[6];
+};
+
+static struct ltc4151_data *ltc4151_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ltc4151_data *data = i2c_get_clientdata(client);
+	struct ltc4151_data *ret = data;
+
+	mutex_lock(&data->update_lock);
+
+	/*
+	 * The chip's A/D updates 6 times per second
+	 * (Conversion Rate 6 - 9 Hz)
+	 */
+	if (time_after(jiffies, data->last_updated + HZ / 6) || !data->valid) {
+		int i;
+
+		dev_dbg(&client->dev, "Starting ltc4151 update\n");
+
+		/* Read all registers */
+		for (i = 0; i < ARRAY_SIZE(data->regs); i++) {
+			int val;
+
+			val = i2c_smbus_read_byte_data(client, i);
+			if (unlikely(val < 0)) {
+				dev_dbg(dev,
+					"Failed to read ADC value: error %d\n",
+					val);
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->regs[i] = val;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+/* Return the voltage from the given register in mV */
+static int ltc4151_get_value(struct ltc4151_data *data, u8 reg)
+{
+	u32 val;
+
+	val = (data->regs[reg] << 4) + (data->regs[reg + 1] >> 4);
+
+	switch (reg) {
+	case LTC4151_ADIN_H:
+		/* 500uV resolution. Convert to mV. */
+		val = val * 500 / 1000;
+		break;
+	case LTC4151_SENSE_H:
+		/*
+		 * 20uV resolution. Convert to current as measured with
+		 * an 1 mOhm sense resistor, in mA.
+		 */
+		val = val * 20;
+		break;
+	case LTC4151_VIN_H:
+		/* 25 mV per increment */
+		val = val * 25;
+		break;
+	default:
+		/* If we get here, the developer messed up */
+		WARN_ON_ONCE(1);
+		val = 0;
+		break;
+	}
+
+	return val;
+}
+
+static ssize_t ltc4151_show_value(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ltc4151_data *data = ltc4151_update_device(dev);
+	int value;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	value = ltc4151_get_value(data, attr->index);
+	return snprintf(buf, PAGE_SIZE, "%d\n", value);
+}
+
+/*
+ * Input voltages.
+ */
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, \
+	ltc4151_show_value, NULL, LTC4151_VIN_H);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, \
+	ltc4151_show_value, NULL, LTC4151_ADIN_H);
+
+/* Currents (via sense resistor) */
+static SENSOR_DEVICE_ATTR(curr1_input, S_IRUGO, \
+	ltc4151_show_value, NULL, LTC4151_SENSE_H);
+
+/* Finally, construct an array of pointers to members of the above objects,
+ * as required for sysfs_create_group()
+ */
+static struct attribute *ltc4151_attributes[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+
+	&sensor_dev_attr_curr1_input.dev_attr.attr,
+
+	NULL,
+};
+
+static const struct attribute_group ltc4151_group = {
+	.attrs = ltc4151_attributes,
+};
+
+static int ltc4151_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	struct ltc4151_data *data;
+	int ret;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		ret = -ENOMEM;
+		goto out_kzalloc;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Register sysfs hooks */
+	ret = sysfs_create_group(&client->dev.kobj, &ltc4151_group);
+	if (ret)
+		goto out_sysfs_create_group;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		goto out_hwmon_device_register;
+	}
+
+	return 0;
+
+out_hwmon_device_register:
+	sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
+out_sysfs_create_group:
+	kfree(data);
+out_kzalloc:
+	return ret;
+}
+
+static int ltc4151_remove(struct i2c_client *client)
+{
+	struct ltc4151_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &ltc4151_group);
+
+	kfree(data);
+
+	return 0;
+}
+
+static const struct i2c_device_id ltc4151_id[] = {
+	{ "ltc4151", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ltc4151_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver ltc4151_driver = {
+	.driver = {
+		.name	= "ltc4151",
+	},
+	.probe		= ltc4151_probe,
+	.remove		= ltc4151_remove,
+	.id_table	= ltc4151_id,
+};
+
+static int __init ltc4151_init(void)
+{
+	return i2c_add_driver(&ltc4151_driver);
+}
+
+static void __exit ltc4151_exit(void)
+{
+	i2c_del_driver(&ltc4151_driver);
+}
+
+MODULE_AUTHOR("Per Dalen <per.dalen@appeartv.com>");
+MODULE_DESCRIPTION("LTC4151 driver");
+MODULE_LICENSE("GPL");
+
+module_init(ltc4151_init);
+module_exit(ltc4151_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/Makefile linux-libre-2.6.39-gnu/drivers/hwmon/Makefile
--- linux-libre-2.6.38-gnu/drivers/hwmon/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 obj-$(CONFIG_SENSORS_ADM1029)	+= adm1029.o
 obj-$(CONFIG_SENSORS_ADM1031)	+= adm1031.o
 obj-$(CONFIG_SENSORS_ADM9240)	+= adm9240.o
+obj-$(CONFIG_SENSORS_ADS1015)	+= ads1015.o
 obj-$(CONFIG_SENSORS_ADS7828)	+= ads7828.o
 obj-$(CONFIG_SENSORS_ADS7871)	+= ads7871.o
 obj-$(CONFIG_SENSORS_ADT7411)	+= adt7411.o
@@ -62,9 +63,7 @@
 obj-$(CONFIG_SENSORS_JZ4740)	+= jz4740-hwmon.o
 obj-$(CONFIG_SENSORS_K8TEMP)	+= k8temp.o
 obj-$(CONFIG_SENSORS_K10TEMP)	+= k10temp.o
-obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o hp_accel.o
-obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d.o lis3lv02d_spi.o
-obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d.o lis3lv02d_i2c.o
+obj-$(CONFIG_SENSORS_LINEAGE)	+= lineage-pem.o
 obj-$(CONFIG_SENSORS_LM63)	+= lm63.o
 obj-$(CONFIG_SENSORS_LM70)	+= lm70.o
 obj-$(CONFIG_SENSORS_LM73)	+= lm73.o
@@ -79,17 +78,20 @@
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
 obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
 obj-$(CONFIG_SENSORS_LM95241)	+= lm95241.o
+obj-$(CONFIG_SENSORS_LTC4151)	+= ltc4151.o
 obj-$(CONFIG_SENSORS_LTC4215)	+= ltc4215.o
 obj-$(CONFIG_SENSORS_LTC4245)	+= ltc4245.o
 obj-$(CONFIG_SENSORS_LTC4261)	+= ltc4261.o
 obj-$(CONFIG_SENSORS_MAX1111)	+= max1111.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
+obj-$(CONFIG_SENSORS_MAX6639)	+= max6639.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_MC13783_ADC)+= mc13783-adc.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
 obj-$(CONFIG_SENSORS_PC87427)	+= pc87427.o
 obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_S3C)	+= s3c-hwmon.o
+obj-$(CONFIG_SENSORS_SCH5627)	+= sch5627.o
 obj-$(CONFIG_SENSORS_SHT15)	+= sht15.o
 obj-$(CONFIG_SENSORS_SHT21)	+= sht21.o
 obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
@@ -102,6 +104,7 @@
 obj-$(CONFIG_SENSORS_TMP102)	+= tmp102.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
+obj-$(CONFIG_SENSORS_TWL4030_MADC)+= twl4030-madc-hwmon.o
 obj-$(CONFIG_SENSORS_VIA_CPUTEMP)+= via-cputemp.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
@@ -112,7 +115,12 @@
 obj-$(CONFIG_SENSORS_WM831X)	+= wm831x-hwmon.o
 obj-$(CONFIG_SENSORS_WM8350)	+= wm8350-hwmon.o
 
-ifeq ($(CONFIG_HWMON_DEBUG_CHIP),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+# PMBus drivers
+obj-$(CONFIG_PMBUS)		+= pmbus_core.o
+obj-$(CONFIG_SENSORS_PMBUS)	+= pmbus.o
+obj-$(CONFIG_SENSORS_MAX16064)	+= max16064.o
+obj-$(CONFIG_SENSORS_MAX34440)	+= max34440.o
+obj-$(CONFIG_SENSORS_MAX8688)	+= max8688.o
+
+ccflags-$(CONFIG_HWMON_DEBUG_CHIP) := -DDEBUG
 
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/max16064.c linux-libre-2.6.39-gnu/drivers/hwmon/max16064.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/max16064.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/max16064.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,91 @@
+/*
+ * Hardware monitoring driver for Maxim MAX16064
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+static struct pmbus_driver_info max16064_info = {
+	.pages = 4,
+	.direct[PSC_VOLTAGE_IN] = true,
+	.direct[PSC_VOLTAGE_OUT] = true,
+	.direct[PSC_TEMPERATURE] = true,
+	.m[PSC_VOLTAGE_IN] = 19995,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = -1,
+	.m[PSC_VOLTAGE_OUT] = 19995,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = -1,
+	.m[PSC_TEMPERATURE] = -7612,
+	.b[PSC_TEMPERATURE] = 335,
+	.R[PSC_TEMPERATURE] = -3,
+	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_TEMP
+		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_TEMP,
+	.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+	.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+	.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT,
+};
+
+static int max16064_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &max16064_info);
+}
+
+static int max16064_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id max16064_id[] = {
+	{"max16064", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, max16064_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max16064_driver = {
+	.driver = {
+		   .name = "max16064",
+		   },
+	.probe = max16064_probe,
+	.remove = max16064_remove,
+	.id_table = max16064_id,
+};
+
+static int __init max16064_init(void)
+{
+	return i2c_add_driver(&max16064_driver);
+}
+
+static void __exit max16064_exit(void)
+{
+	i2c_del_driver(&max16064_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX16064");
+MODULE_LICENSE("GPL");
+module_init(max16064_init);
+module_exit(max16064_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/max34440.c linux-libre-2.6.39-gnu/drivers/hwmon/max34440.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/max34440.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/max34440.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,199 @@
+/*
+ * Hardware monitoring driver for Maxim MAX34440/MAX34441
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+enum chips { max34440, max34441 };
+
+#define MAX34440_STATUS_OC_WARN		(1 << 0)
+#define MAX34440_STATUS_OC_FAULT	(1 << 1)
+#define MAX34440_STATUS_OT_FAULT	(1 << 5)
+#define MAX34440_STATUS_OT_WARN		(1 << 6)
+
+static int max34440_get_status(struct i2c_client *client, int page, int reg)
+{
+	int ret;
+	int mfg_status;
+
+	ret = pmbus_set_page(client, page);
+	if (ret < 0)
+		return ret;
+
+	switch (reg) {
+	case PMBUS_STATUS_IOUT:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  PMBUS_STATUS_MFR_SPECIFIC);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX34440_STATUS_OC_WARN)
+			ret |= PB_IOUT_OC_WARNING;
+		if (mfg_status & MAX34440_STATUS_OC_FAULT)
+			ret |= PB_IOUT_OC_FAULT;
+		break;
+	case PMBUS_STATUS_TEMPERATURE:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  PMBUS_STATUS_MFR_SPECIFIC);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX34440_STATUS_OT_WARN)
+			ret |= PB_TEMP_OT_WARNING;
+		if (mfg_status & MAX34440_STATUS_OT_FAULT)
+			ret |= PB_TEMP_OT_FAULT;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static struct pmbus_driver_info max34440_info[] = {
+	[max34440] = {
+		.pages = 14,
+		.direct[PSC_VOLTAGE_IN] = true,
+		.direct[PSC_VOLTAGE_OUT] = true,
+		.direct[PSC_TEMPERATURE] = true,
+		.direct[PSC_CURRENT_OUT] = true,
+		.m[PSC_VOLTAGE_IN] = 1,
+		.b[PSC_VOLTAGE_IN] = 0,
+		.R[PSC_VOLTAGE_IN] = 3,	    /* R = 0 in datasheet reflects mV */
+		.m[PSC_VOLTAGE_OUT] = 1,
+		.b[PSC_VOLTAGE_OUT] = 0,
+		.R[PSC_VOLTAGE_OUT] = 3,    /* R = 0 in datasheet reflects mV */
+		.m[PSC_CURRENT_OUT] = 1,
+		.b[PSC_CURRENT_OUT] = 0,
+		.R[PSC_CURRENT_OUT] = 3,    /* R = 0 in datasheet reflects mA */
+		.m[PSC_TEMPERATURE] = 1,
+		.b[PSC_TEMPERATURE] = 0,
+		.R[PSC_TEMPERATURE] = 2,
+		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[5] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[12] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[13] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.get_status = max34440_get_status,
+	},
+	[max34441] = {
+		.pages = 12,
+		.direct[PSC_VOLTAGE_IN] = true,
+		.direct[PSC_VOLTAGE_OUT] = true,
+		.direct[PSC_TEMPERATURE] = true,
+		.direct[PSC_CURRENT_OUT] = true,
+		.direct[PSC_FAN] = true,
+		.m[PSC_VOLTAGE_IN] = 1,
+		.b[PSC_VOLTAGE_IN] = 0,
+		.R[PSC_VOLTAGE_IN] = 3,
+		.m[PSC_VOLTAGE_OUT] = 1,
+		.b[PSC_VOLTAGE_OUT] = 0,
+		.R[PSC_VOLTAGE_OUT] = 3,
+		.m[PSC_CURRENT_OUT] = 1,
+		.b[PSC_CURRENT_OUT] = 0,
+		.R[PSC_CURRENT_OUT] = 3,
+		.m[PSC_TEMPERATURE] = 1,
+		.b[PSC_TEMPERATURE] = 0,
+		.R[PSC_TEMPERATURE] = 2,
+		.m[PSC_FAN] = 1,
+		.b[PSC_FAN] = 0,
+		.R[PSC_FAN] = 0,
+		.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[1] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[2] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[3] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[4] = PMBUS_HAVE_VOUT | PMBUS_HAVE_STATUS_VOUT
+		  | PMBUS_HAVE_IOUT | PMBUS_HAVE_STATUS_IOUT,
+		.func[5] = PMBUS_HAVE_FAN12 | PMBUS_HAVE_STATUS_FAN12,
+		.func[6] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[7] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[8] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[9] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[10] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.func[11] = PMBUS_HAVE_TEMP | PMBUS_HAVE_STATUS_TEMP,
+		.get_status = max34440_get_status,
+	},
+};
+
+static int max34440_probe(struct i2c_client *client,
+			  const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &max34440_info[id->driver_data]);
+}
+
+static int max34440_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id max34440_id[] = {
+	{"max34440", max34440},
+	{"max34441", max34441},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, max34440_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max34440_driver = {
+	.driver = {
+		   .name = "max34440",
+		   },
+	.probe = max34440_probe,
+	.remove = max34440_remove,
+	.id_table = max34440_id,
+};
+
+static int __init max34440_init(void)
+{
+	return i2c_add_driver(&max34440_driver);
+}
+
+static void __exit max34440_exit(void)
+{
+	i2c_del_driver(&max34440_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX34440/MAX34441");
+MODULE_LICENSE("GPL");
+module_init(max34440_init);
+module_exit(max34440_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/max6639.c linux-libre-2.6.39-gnu/drivers/hwmon/max6639.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/max6639.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/max6639.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,653 @@
+/*
+ * max6639.c - Support for Maxim MAX6639
+ *
+ * 2-Channel Temperature Monitor with Dual PWM Fan-Speed Controller
+ *
+ * Copyright (C) 2010, 2011 Roland Stigge <stigge@antcom.de>
+ *
+ * based on the initial MAX6639 support from semptian.net
+ * by He Changqing <hechangqing@semptian.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/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/i2c/max6639.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2e, 0x2f, I2C_CLIENT_END };
+
+/* The MAX6639 registers, valid channel numbers: 0, 1 */
+#define MAX6639_REG_TEMP(ch)			(0x00 + (ch))
+#define MAX6639_REG_STATUS			0x02
+#define MAX6639_REG_OUTPUT_MASK			0x03
+#define MAX6639_REG_GCONFIG			0x04
+#define MAX6639_REG_TEMP_EXT(ch)		(0x05 + (ch))
+#define MAX6639_REG_ALERT_LIMIT(ch)		(0x08 + (ch))
+#define MAX6639_REG_OT_LIMIT(ch)		(0x0A + (ch))
+#define MAX6639_REG_THERM_LIMIT(ch)		(0x0C + (ch))
+#define MAX6639_REG_FAN_CONFIG1(ch)		(0x10 + (ch) * 4)
+#define MAX6639_REG_FAN_CONFIG2a(ch)		(0x11 + (ch) * 4)
+#define MAX6639_REG_FAN_CONFIG2b(ch)		(0x12 + (ch) * 4)
+#define MAX6639_REG_FAN_CONFIG3(ch)		(0x13 + (ch) * 4)
+#define MAX6639_REG_FAN_CNT(ch)			(0x20 + (ch))
+#define MAX6639_REG_TARGET_CNT(ch)		(0x22 + (ch))
+#define MAX6639_REG_FAN_PPR(ch)			(0x24 + (ch))
+#define MAX6639_REG_TARGTDUTY(ch)		(0x26 + (ch))
+#define MAX6639_REG_FAN_START_TEMP(ch)		(0x28 + (ch))
+#define MAX6639_REG_DEVID			0x3D
+#define MAX6639_REG_MANUID			0x3E
+#define MAX6639_REG_DEVREV			0x3F
+
+/* Register bits */
+#define MAX6639_GCONFIG_STANDBY			0x80
+#define MAX6639_GCONFIG_POR			0x40
+#define MAX6639_GCONFIG_DISABLE_TIMEOUT		0x20
+#define MAX6639_GCONFIG_CH2_LOCAL		0x10
+#define MAX6639_GCONFIG_PWM_FREQ_HI		0x08
+
+#define MAX6639_FAN_CONFIG1_PWM			0x80
+
+#define MAX6639_FAN_CONFIG3_THERM_FULL_SPEED	0x40
+
+static const int rpm_ranges[] = { 2000, 4000, 8000, 16000 };
+
+#define FAN_FROM_REG(val, div, rpm_range)	((val) == 0 ? -1 : \
+	(val) == 255 ? 0 : (rpm_ranges[rpm_range] * 30) / ((div + 1) * (val)))
+#define TEMP_LIMIT_TO_REG(val)	SENSORS_LIMIT((val) / 1000, 0, 255)
+
+/*
+ * Client data (each client gets its own)
+ */
+struct max6639_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* Register values sampled regularly */
+	u16 temp[2];		/* Temperature, in 1/8 C, 0..255 C */
+	bool temp_fault[2];	/* Detected temperature diode failure */
+	u8 fan[2];		/* Register value: TACH count for fans >=30 */
+	u8 status;		/* Detected channel alarms and fan failures */
+
+	/* Register values only written to */
+	u8 pwm[2];		/* Register value: Duty cycle 0..120 */
+	u8 temp_therm[2];	/* THERM Temperature, 0..255 C (->_max) */
+	u8 temp_alert[2];	/* ALERT Temperature, 0..255 C (->_crit) */
+	u8 temp_ot[2];		/* OT Temperature, 0..255 C (->_emergency) */
+
+	/* Register values initialized only once */
+	u8 ppr;			/* Pulses per rotation 0..3 for 1..4 ppr */
+	u8 rpm_range;		/* Index in above rpm_ranges table */
+};
+
+static struct max6639_data *max6639_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct max6639_data *ret = data;
+	int i;
+	int status_reg;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
+		int res;
+
+		dev_dbg(&client->dev, "Starting max6639 update\n");
+
+		status_reg = i2c_smbus_read_byte_data(client,
+						      MAX6639_REG_STATUS);
+		if (status_reg < 0) {
+			ret = ERR_PTR(status_reg);
+			goto abort;
+		}
+
+		data->status = status_reg;
+
+		for (i = 0; i < 2; i++) {
+			res = i2c_smbus_read_byte_data(client,
+					MAX6639_REG_FAN_CNT(i));
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+			data->fan[i] = res;
+
+			res = i2c_smbus_read_byte_data(client,
+					MAX6639_REG_TEMP_EXT(i));
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+			data->temp[i] = res >> 5;
+			data->temp_fault[i] = res & 0x01;
+
+			res = i2c_smbus_read_byte_data(client,
+					MAX6639_REG_TEMP(i));
+			if (res < 0) {
+				ret = ERR_PTR(res);
+				goto abort;
+			}
+			data->temp[i] |= res << 3;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+
+	return ret;
+}
+
+static ssize_t show_temp_input(struct device *dev,
+			       struct device_attribute *dev_attr, char *buf)
+{
+	long temp;
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	temp = data->temp[attr->index] * 125;
+	return sprintf(buf, "%ld\n", temp);
+}
+
+static ssize_t show_temp_fault(struct device *dev,
+			       struct device_attribute *dev_attr, char *buf)
+{
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", data->temp_fault[attr->index]);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *dev_attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", (data->temp_therm[attr->index] * 1000));
+}
+
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *dev_attr,
+			    const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	mutex_lock(&data->update_lock);
+	data->temp_therm[attr->index] = TEMP_LIMIT_TO_REG(val);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_THERM_LIMIT(attr->index),
+				  data->temp_therm[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp_crit(struct device *dev,
+			      struct device_attribute *dev_attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", (data->temp_alert[attr->index] * 1000));
+}
+
+static ssize_t set_temp_crit(struct device *dev,
+			     struct device_attribute *dev_attr,
+			     const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	mutex_lock(&data->update_lock);
+	data->temp_alert[attr->index] = TEMP_LIMIT_TO_REG(val);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_ALERT_LIMIT(attr->index),
+				  data->temp_alert[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp_emergency(struct device *dev,
+				   struct device_attribute *dev_attr,
+				   char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", (data->temp_ot[attr->index] * 1000));
+}
+
+static ssize_t set_temp_emergency(struct device *dev,
+				  struct device_attribute *dev_attr,
+				  const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	mutex_lock(&data->update_lock);
+	data->temp_ot[attr->index] = TEMP_LIMIT_TO_REG(val);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_OT_LIMIT(attr->index),
+				  data->temp_ot[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_pwm(struct device *dev,
+			struct device_attribute *dev_attr, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	return sprintf(buf, "%d\n", data->pwm[attr->index] * 255 / 120);
+}
+
+static ssize_t set_pwm(struct device *dev,
+		       struct device_attribute *dev_attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+	unsigned long val;
+	int res;
+
+	res = strict_strtoul(buf, 10, &val);
+	if (res)
+		return res;
+
+	val = SENSORS_LIMIT(val, 0, 255);
+
+	mutex_lock(&data->update_lock);
+	data->pwm[attr->index] = (u8)(val * 120 / 255);
+	i2c_smbus_write_byte_data(client,
+				  MAX6639_REG_TARGTDUTY(attr->index),
+				  data->pwm[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_fan_input(struct device *dev,
+			      struct device_attribute *dev_attr, char *buf)
+{
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[attr->index],
+		       data->ppr, data->rpm_range));
+}
+
+static ssize_t show_alarm(struct device *dev,
+			  struct device_attribute *dev_attr, char *buf)
+{
+	struct max6639_data *data = max6639_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(dev_attr);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return sprintf(buf, "%d\n", !!(data->status & (1 << attr->index)));
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+		set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
+		set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IWUSR | S_IRUGO, show_temp_crit,
+		set_temp_crit, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IWUSR | S_IRUGO, show_temp_crit,
+		set_temp_crit, 1);
+static SENSOR_DEVICE_ATTR(temp1_emergency, S_IWUSR | S_IRUGO,
+		show_temp_emergency, set_temp_emergency, 0);
+static SENSOR_DEVICE_ATTR(temp2_emergency, S_IWUSR | S_IRUGO,
+		show_temp_emergency, set_temp_emergency, 1);
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1);
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_alarm, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_alarm, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp1_emergency_alarm, S_IRUGO, show_alarm, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp2_emergency_alarm, S_IRUGO, show_alarm, NULL, 4);
+
+
+static struct attribute *max6639_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency.dev_attr.attr,
+	&sensor_dev_attr_temp2_emergency.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
+	&sensor_dev_attr_fan2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_emergency_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp2_emergency_alarm.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group max6639_group = {
+	.attrs = max6639_attributes,
+};
+
+/*
+ *  returns respective index in rpm_ranges table
+ *  1 by default on invalid range
+ */
+static int rpm_range_to_reg(int range)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(rpm_ranges); i++) {
+		if (rpm_ranges[i] == range)
+			return i;
+	}
+
+	return 1; /* default: 4000 RPM */
+}
+
+static int max6639_init_client(struct i2c_client *client)
+{
+	struct max6639_data *data = i2c_get_clientdata(client);
+	struct max6639_platform_data *max6639_info =
+		client->dev.platform_data;
+	int i = 0;
+	int rpm_range = 1; /* default: 4000 RPM */
+	int err = 0;
+
+	/* Reset chip to default values, see below for GCONFIG setup */
+	err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG,
+				  MAX6639_GCONFIG_POR);
+	if (err)
+		goto exit;
+
+	/* Fans pulse per revolution is 2 by default */
+	if (max6639_info && max6639_info->ppr > 0 &&
+			max6639_info->ppr < 5)
+		data->ppr = max6639_info->ppr;
+	else
+		data->ppr = 2;
+	data->ppr -= 1;
+	err = i2c_smbus_write_byte_data(client,
+			MAX6639_REG_FAN_PPR(i),
+			data->ppr << 5);
+	if (err)
+		goto exit;
+
+	if (max6639_info)
+		rpm_range = rpm_range_to_reg(max6639_info->rpm_range);
+	data->rpm_range = rpm_range;
+
+	for (i = 0; i < 2; i++) {
+
+		/* Fans config PWM, RPM */
+		err = i2c_smbus_write_byte_data(client,
+			MAX6639_REG_FAN_CONFIG1(i),
+			MAX6639_FAN_CONFIG1_PWM | rpm_range);
+		if (err)
+			goto exit;
+
+		/* Fans PWM polarity high by default */
+		if (max6639_info && max6639_info->pwm_polarity == 0)
+			err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_FAN_CONFIG2a(i), 0x00);
+		else
+			err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_FAN_CONFIG2a(i), 0x02);
+		if (err)
+			goto exit;
+
+		/*
+		 * /THERM full speed enable,
+		 * PWM frequency 25kHz, see also GCONFIG below
+		 */
+		err = i2c_smbus_write_byte_data(client,
+			MAX6639_REG_FAN_CONFIG3(i),
+			MAX6639_FAN_CONFIG3_THERM_FULL_SPEED | 0x03);
+		if (err)
+			goto exit;
+
+		/* Max. temp. 80C/90C/100C */
+		data->temp_therm[i] = 80;
+		data->temp_alert[i] = 90;
+		data->temp_ot[i] = 100;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_THERM_LIMIT(i),
+				data->temp_therm[i]);
+		if (err)
+			goto exit;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_ALERT_LIMIT(i),
+				data->temp_alert[i]);
+		if (err)
+			goto exit;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_OT_LIMIT(i), data->temp_ot[i]);
+		if (err)
+			goto exit;
+
+		/* PWM 120/120 (i.e. 100%) */
+		data->pwm[i] = 120;
+		err = i2c_smbus_write_byte_data(client,
+				MAX6639_REG_TARGTDUTY(i), data->pwm[i]);
+		if (err)
+			goto exit;
+	}
+	/* Start monitoring */
+	err = i2c_smbus_write_byte_data(client, MAX6639_REG_GCONFIG,
+		MAX6639_GCONFIG_DISABLE_TIMEOUT | MAX6639_GCONFIG_CH2_LOCAL |
+		MAX6639_GCONFIG_PWM_FREQ_HI);
+exit:
+	return err;
+}
+
+/* Return 0 if detection is successful, -ENODEV otherwise */
+static int max6639_detect(struct i2c_client *client,
+			  struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	int dev_id, manu_id;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	/* Actual detection via device and manufacturer ID */
+	dev_id = i2c_smbus_read_byte_data(client, MAX6639_REG_DEVID);
+	manu_id = i2c_smbus_read_byte_data(client, MAX6639_REG_MANUID);
+	if (dev_id != 0x58 || manu_id != 0x4D)
+		return -ENODEV;
+
+	strlcpy(info->type, "max6639", I2C_NAME_SIZE);
+
+	return 0;
+}
+
+static int max6639_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct max6639_data *data;
+	int err;
+
+	data = kzalloc(sizeof(struct max6639_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/* Initialize the max6639 chip */
+	err = max6639_init_client(client);
+	if (err < 0)
+		goto error_free;
+
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&client->dev.kobj, &max6639_group);
+	if (err)
+		goto error_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		goto error_remove;
+	}
+
+	dev_info(&client->dev, "temperature sensor and fan control found\n");
+
+	return 0;
+
+error_remove:
+	sysfs_remove_group(&client->dev.kobj, &max6639_group);
+error_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int max6639_remove(struct i2c_client *client)
+{
+	struct max6639_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &max6639_group);
+
+	kfree(data);
+	return 0;
+}
+
+static int max6639_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
+	if (data < 0)
+		return data;
+
+	return i2c_smbus_write_byte_data(client,
+			MAX6639_REG_GCONFIG, data | MAX6639_GCONFIG_STANDBY);
+}
+
+static int max6639_resume(struct i2c_client *client)
+{
+	int data = i2c_smbus_read_byte_data(client, MAX6639_REG_GCONFIG);
+	if (data < 0)
+		return data;
+
+	return i2c_smbus_write_byte_data(client,
+			MAX6639_REG_GCONFIG, data & ~MAX6639_GCONFIG_STANDBY);
+}
+
+static const struct i2c_device_id max6639_id[] = {
+	{"max6639", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, max6639_id);
+
+static struct i2c_driver max6639_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		   .name = "max6639",
+		   },
+	.probe = max6639_probe,
+	.remove = max6639_remove,
+	.suspend = max6639_suspend,
+	.resume = max6639_resume,
+	.id_table = max6639_id,
+	.detect = max6639_detect,
+	.address_list = normal_i2c,
+};
+
+static int __init max6639_init(void)
+{
+	return i2c_add_driver(&max6639_driver);
+}
+
+static void __exit max6639_exit(void)
+{
+	i2c_del_driver(&max6639_driver);
+}
+
+MODULE_AUTHOR("Roland Stigge <stigge@antcom.de>");
+MODULE_DESCRIPTION("max6639 driver");
+MODULE_LICENSE("GPL");
+
+module_init(max6639_init);
+module_exit(max6639_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/max8688.c linux-libre-2.6.39-gnu/drivers/hwmon/max8688.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/max8688.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/max8688.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,158 @@
+/*
+ * Hardware monitoring driver for Maxim MAX8688
+ *
+ * Copyright (c) 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+#define MAX8688_MFG_STATUS		0xd8
+
+#define MAX8688_STATUS_OC_FAULT		(1 << 4)
+#define MAX8688_STATUS_OV_FAULT		(1 << 5)
+#define MAX8688_STATUS_OV_WARNING	(1 << 8)
+#define MAX8688_STATUS_UV_FAULT		(1 << 9)
+#define MAX8688_STATUS_UV_WARNING	(1 << 10)
+#define MAX8688_STATUS_UC_FAULT		(1 << 11)
+#define MAX8688_STATUS_OC_WARNING	(1 << 12)
+#define MAX8688_STATUS_OT_FAULT		(1 << 13)
+#define MAX8688_STATUS_OT_WARNING	(1 << 14)
+
+static int max8688_get_status(struct i2c_client *client, int page, int reg)
+{
+	int ret = 0;
+	int mfg_status;
+
+	if (page)
+		return -EINVAL;
+
+	switch (reg) {
+	case PMBUS_STATUS_VOUT:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  MAX8688_MFG_STATUS);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX8688_STATUS_UV_WARNING)
+			ret |= PB_VOLTAGE_UV_WARNING;
+		if (mfg_status & MAX8688_STATUS_UV_FAULT)
+			ret |= PB_VOLTAGE_UV_FAULT;
+		if (mfg_status & MAX8688_STATUS_OV_WARNING)
+			ret |= PB_VOLTAGE_OV_WARNING;
+		if (mfg_status & MAX8688_STATUS_OV_FAULT)
+			ret |= PB_VOLTAGE_OV_FAULT;
+		break;
+	case PMBUS_STATUS_IOUT:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  MAX8688_MFG_STATUS);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX8688_STATUS_UC_FAULT)
+			ret |= PB_IOUT_UC_FAULT;
+		if (mfg_status & MAX8688_STATUS_OC_WARNING)
+			ret |= PB_IOUT_OC_WARNING;
+		if (mfg_status & MAX8688_STATUS_OC_FAULT)
+			ret |= PB_IOUT_OC_FAULT;
+		break;
+	case PMBUS_STATUS_TEMPERATURE:
+		mfg_status = pmbus_read_word_data(client, 0,
+						  MAX8688_MFG_STATUS);
+		if (mfg_status < 0)
+			return mfg_status;
+		if (mfg_status & MAX8688_STATUS_OT_WARNING)
+			ret |= PB_TEMP_OT_WARNING;
+		if (mfg_status & MAX8688_STATUS_OT_FAULT)
+			ret |= PB_TEMP_OT_FAULT;
+		break;
+	default:
+		ret = -ENODATA;
+		break;
+	}
+	return ret;
+}
+
+static struct pmbus_driver_info max8688_info = {
+	.pages = 1,
+	.direct[PSC_VOLTAGE_IN] = true,
+	.direct[PSC_VOLTAGE_OUT] = true,
+	.direct[PSC_TEMPERATURE] = true,
+	.direct[PSC_CURRENT_OUT] = true,
+	.m[PSC_VOLTAGE_IN] = 19995,
+	.b[PSC_VOLTAGE_IN] = 0,
+	.R[PSC_VOLTAGE_IN] = -1,
+	.m[PSC_VOLTAGE_OUT] = 19995,
+	.b[PSC_VOLTAGE_OUT] = 0,
+	.R[PSC_VOLTAGE_OUT] = -1,
+	.m[PSC_CURRENT_OUT] = 23109,
+	.b[PSC_CURRENT_OUT] = 0,
+	.R[PSC_CURRENT_OUT] = -2,
+	.m[PSC_TEMPERATURE] = -7612,
+	.b[PSC_TEMPERATURE] = 335,
+	.R[PSC_TEMPERATURE] = -3,
+	.func[0] = PMBUS_HAVE_VOUT | PMBUS_HAVE_IOUT | PMBUS_HAVE_TEMP
+		| PMBUS_HAVE_STATUS_VOUT | PMBUS_HAVE_STATUS_IOUT
+		| PMBUS_HAVE_STATUS_TEMP,
+	.get_status = max8688_get_status,
+};
+
+static int max8688_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	return pmbus_do_probe(client, id, &max8688_info);
+}
+
+static int max8688_remove(struct i2c_client *client)
+{
+	return pmbus_do_remove(client);
+}
+
+static const struct i2c_device_id max8688_id[] = {
+	{"max8688", 0},
+	{ }
+};
+
+MODULE_DEVICE_TABLE(i2c, max8688_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver max8688_driver = {
+	.driver = {
+		   .name = "max8688",
+		   },
+	.probe = max8688_probe,
+	.remove = max8688_remove,
+	.id_table = max8688_id,
+};
+
+static int __init max8688_init(void)
+{
+	return i2c_add_driver(&max8688_driver);
+}
+
+static void __exit max8688_exit(void)
+{
+	i2c_del_driver(&max8688_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus driver for Maxim MAX8688");
+MODULE_LICENSE("GPL");
+module_init(max8688_init);
+module_exit(max8688_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/pmbus.c linux-libre-2.6.39-gnu/drivers/hwmon/pmbus.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/pmbus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/pmbus.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,203 @@
+/*
+ * Hardware monitoring driver for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/slab.h>
+#include <linux/mutex.h>
+#include <linux/i2c.h>
+#include "pmbus.h"
+
+/*
+ * Find sensor groups and status registers on each page.
+ */
+static void pmbus_find_sensor_groups(struct i2c_client *client,
+				     struct pmbus_driver_info *info)
+{
+	int page;
+
+	/* Sensors detected on page 0 only */
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_VIN))
+		info->func[0] |= PMBUS_HAVE_VIN;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_VCAP))
+		info->func[0] |= PMBUS_HAVE_VCAP;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_IIN))
+		info->func[0] |= PMBUS_HAVE_IIN;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_PIN))
+		info->func[0] |= PMBUS_HAVE_PIN;
+	if (info->func[0]
+	    && pmbus_check_byte_register(client, 0, PMBUS_STATUS_INPUT))
+		info->func[0] |= PMBUS_HAVE_STATUS_INPUT;
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_1)) {
+		info->func[0] |= PMBUS_HAVE_FAN12;
+		if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_12))
+			info->func[0] |= PMBUS_HAVE_STATUS_FAN12;
+	}
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_FAN_SPEED_3)) {
+		info->func[0] |= PMBUS_HAVE_FAN34;
+		if (pmbus_check_byte_register(client, 0, PMBUS_STATUS_FAN_34))
+			info->func[0] |= PMBUS_HAVE_STATUS_FAN34;
+	}
+	if (pmbus_check_word_register(client, 0, PMBUS_READ_TEMPERATURE_1)) {
+		info->func[0] |= PMBUS_HAVE_TEMP;
+		if (pmbus_check_byte_register(client, 0,
+					      PMBUS_STATUS_TEMPERATURE))
+			info->func[0] |= PMBUS_HAVE_STATUS_TEMP;
+	}
+
+	/* Sensors detected on all pages */
+	for (page = 0; page < info->pages; page++) {
+		if (pmbus_check_word_register(client, page, PMBUS_READ_VOUT)) {
+			info->func[page] |= PMBUS_HAVE_VOUT;
+			if (pmbus_check_byte_register(client, page,
+						      PMBUS_STATUS_VOUT))
+				info->func[page] |= PMBUS_HAVE_STATUS_VOUT;
+		}
+		if (pmbus_check_word_register(client, page, PMBUS_READ_IOUT)) {
+			info->func[page] |= PMBUS_HAVE_IOUT;
+			if (pmbus_check_byte_register(client, 0,
+						      PMBUS_STATUS_IOUT))
+				info->func[page] |= PMBUS_HAVE_STATUS_IOUT;
+		}
+		if (pmbus_check_word_register(client, page, PMBUS_READ_POUT))
+			info->func[page] |= PMBUS_HAVE_POUT;
+	}
+}
+
+/*
+ * Identify chip parameters.
+ */
+static int pmbus_identify(struct i2c_client *client,
+			  struct pmbus_driver_info *info)
+{
+	if (!info->pages) {
+		/*
+		 * Check if the PAGE command is supported. If it is,
+		 * keep setting the page number until it fails or until the
+		 * maximum number of pages has been reached. Assume that
+		 * this is the number of pages supported by the chip.
+		 */
+		if (pmbus_check_byte_register(client, 0, PMBUS_PAGE)) {
+			int page;
+
+			for (page = 1; page < PMBUS_PAGES; page++) {
+				if (pmbus_set_page(client, page) < 0)
+					break;
+			}
+			pmbus_set_page(client, 0);
+			info->pages = page;
+		} else {
+			info->pages = 1;
+		}
+	}
+
+	/*
+	 * We should check if the COEFFICIENTS register is supported.
+	 * If it is, and the chip is configured for direct mode, we can read
+	 * the coefficients from the chip, one set per group of sensor
+	 * registers.
+	 *
+	 * To do this, we will need access to a chip which actually supports the
+	 * COEFFICIENTS command, since the command is too complex to implement
+	 * without testing it.
+	 */
+
+	/* Try to find sensor groups  */
+	pmbus_find_sensor_groups(client, info);
+
+	return 0;
+}
+
+static int pmbus_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct pmbus_driver_info *info;
+	int ret;
+
+	info = kzalloc(sizeof(struct pmbus_driver_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	info->pages = id->driver_data;
+	info->identify = pmbus_identify;
+
+	ret = pmbus_do_probe(client, id, info);
+	if (ret < 0)
+		goto out;
+	return 0;
+
+out:
+	kfree(info);
+	return ret;
+}
+
+static int pmbus_remove(struct i2c_client *client)
+{
+	int ret;
+	const struct pmbus_driver_info *info;
+
+	info = pmbus_get_driver_info(client);
+	ret = pmbus_do_remove(client);
+	kfree(info);
+	return ret;
+}
+
+/*
+ * Use driver_data to set the number of pages supported by the chip.
+ */
+static const struct i2c_device_id pmbus_id[] = {
+	{"bmr450", 1},
+	{"bmr451", 1},
+	{"bmr453", 1},
+	{"bmr454", 1},
+	{"ltc2978", 8},
+	{"pmbus", 0},
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, pmbus_id);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pmbus_driver = {
+	.driver = {
+		   .name = "pmbus",
+		   },
+	.probe = pmbus_probe,
+	.remove = pmbus_remove,
+	.id_table = pmbus_id,
+};
+
+static int __init pmbus_init(void)
+{
+	return i2c_add_driver(&pmbus_driver);
+}
+
+static void __exit pmbus_exit(void)
+{
+	i2c_del_driver(&pmbus_driver);
+}
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("Generic PMBus driver");
+MODULE_LICENSE("GPL");
+module_init(pmbus_init);
+module_exit(pmbus_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/pmbus_core.c linux-libre-2.6.39-gnu/drivers/hwmon/pmbus_core.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/pmbus_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/pmbus_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1659 @@
+/*
+ * Hardware monitoring driver for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/err.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/delay.h>
+#include <linux/i2c/pmbus.h>
+#include "pmbus.h"
+
+/*
+ * Constants needed to determine number of sensors, booleans, and labels.
+ */
+#define PMBUS_MAX_INPUT_SENSORS		11	/* 6*volt, 3*curr, 2*power */
+#define PMBUS_VOUT_SENSORS_PER_PAGE	5	/* input, min, max, lcrit,
+						   crit */
+#define PMBUS_IOUT_SENSORS_PER_PAGE	4	/* input, min, max, crit */
+#define PMBUS_POUT_SENSORS_PER_PAGE	4	/* input, cap, max, crit */
+#define PMBUS_MAX_SENSORS_PER_FAN	1	/* input */
+#define PMBUS_MAX_SENSORS_PER_TEMP	5	/* input, min, max, lcrit,
+						   crit */
+
+#define PMBUS_MAX_INPUT_BOOLEANS	7	/* v: min_alarm, max_alarm,
+						   lcrit_alarm, crit_alarm;
+						   c: alarm, crit_alarm;
+						   p: crit_alarm */
+#define PMBUS_VOUT_BOOLEANS_PER_PAGE	4	/* min_alarm, max_alarm,
+						   lcrit_alarm, crit_alarm */
+#define PMBUS_IOUT_BOOLEANS_PER_PAGE	3	/* alarm, lcrit_alarm,
+						   crit_alarm */
+#define PMBUS_POUT_BOOLEANS_PER_PAGE	2	/* alarm, crit_alarm */
+#define PMBUS_MAX_BOOLEANS_PER_FAN	2	/* alarm, fault */
+#define PMBUS_MAX_BOOLEANS_PER_TEMP	4	/* min_alarm, max_alarm,
+						   lcrit_alarm, crit_alarm */
+
+#define PMBUS_MAX_INPUT_LABELS		4	/* vin, vcap, iin, pin */
+
+/*
+ * status, status_vout, status_iout, status_fans, status_fan34, and status_temp
+ * are paged. status_input is unpaged.
+ */
+#define PB_NUM_STATUS_REG	(PMBUS_PAGES * 6 + 1)
+
+/*
+ * Index into status register array, per status register group
+ */
+#define PB_STATUS_BASE		0
+#define PB_STATUS_VOUT_BASE	(PB_STATUS_BASE + PMBUS_PAGES)
+#define PB_STATUS_IOUT_BASE	(PB_STATUS_VOUT_BASE + PMBUS_PAGES)
+#define PB_STATUS_FAN_BASE	(PB_STATUS_IOUT_BASE + PMBUS_PAGES)
+#define PB_STATUS_FAN34_BASE	(PB_STATUS_FAN_BASE + PMBUS_PAGES)
+#define PB_STATUS_INPUT_BASE	(PB_STATUS_FAN34_BASE + PMBUS_PAGES)
+#define PB_STATUS_TEMP_BASE	(PB_STATUS_INPUT_BASE + 1)
+
+struct pmbus_sensor {
+	char name[I2C_NAME_SIZE];	/* sysfs sensor name */
+	struct sensor_device_attribute attribute;
+	u8 page;		/* page number */
+	u8 reg;			/* register */
+	enum pmbus_sensor_classes class;	/* sensor class */
+	bool update;		/* runtime sensor update needed */
+	int data;		/* Sensor data.
+				   Negative if there was a read error */
+};
+
+struct pmbus_boolean {
+	char name[I2C_NAME_SIZE];	/* sysfs boolean name */
+	struct sensor_device_attribute attribute;
+};
+
+struct pmbus_label {
+	char name[I2C_NAME_SIZE];	/* sysfs label name */
+	struct sensor_device_attribute attribute;
+	char label[I2C_NAME_SIZE];	/* label */
+};
+
+struct pmbus_data {
+	struct device *hwmon_dev;
+
+	u32 flags;		/* from platform data */
+
+	int exponent;		/* linear mode: exponent for output voltages */
+
+	const struct pmbus_driver_info *info;
+
+	int max_attributes;
+	int num_attributes;
+	struct attribute **attributes;
+	struct attribute_group group;
+
+	/*
+	 * Sensors cover both sensor and limit registers.
+	 */
+	int max_sensors;
+	int num_sensors;
+	struct pmbus_sensor *sensors;
+	/*
+	 * Booleans are used for alarms.
+	 * Values are determined from status registers.
+	 */
+	int max_booleans;
+	int num_booleans;
+	struct pmbus_boolean *booleans;
+	/*
+	 * Labels are used to map generic names (e.g., "in1")
+	 * to PMBus specific names (e.g., "vin" or "vout1").
+	 */
+	int max_labels;
+	int num_labels;
+	struct pmbus_label *labels;
+
+	struct mutex update_lock;
+	bool valid;
+	unsigned long last_updated;	/* in jiffies */
+
+	/*
+	 * A single status register covers multiple attributes,
+	 * so we keep them all together.
+	 */
+	u8 status[PB_NUM_STATUS_REG];
+
+	u8 currpage;
+};
+
+int pmbus_set_page(struct i2c_client *client, u8 page)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	int rv = 0;
+	int newpage;
+
+	if (page != data->currpage) {
+		rv = i2c_smbus_write_byte_data(client, PMBUS_PAGE, page);
+		newpage = i2c_smbus_read_byte_data(client, PMBUS_PAGE);
+		if (newpage != page)
+			rv = -EINVAL;
+		else
+			data->currpage = page;
+	}
+	return rv;
+}
+EXPORT_SYMBOL_GPL(pmbus_set_page);
+
+static int pmbus_write_byte(struct i2c_client *client, u8 page, u8 value)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_write_byte(client, value);
+}
+
+static int pmbus_write_word_data(struct i2c_client *client, u8 page, u8 reg,
+				 u16 word)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_write_word_data(client, reg, word);
+}
+
+int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_read_word_data(client, reg);
+}
+EXPORT_SYMBOL_GPL(pmbus_read_word_data);
+
+static int pmbus_read_byte_data(struct i2c_client *client, u8 page, u8 reg)
+{
+	int rv;
+
+	rv = pmbus_set_page(client, page);
+	if (rv < 0)
+		return rv;
+
+	return i2c_smbus_read_byte_data(client, reg);
+}
+
+static void pmbus_clear_fault_page(struct i2c_client *client, int page)
+{
+	pmbus_write_byte(client, page, PMBUS_CLEAR_FAULTS);
+}
+
+void pmbus_clear_faults(struct i2c_client *client)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	int i;
+
+	for (i = 0; i < data->info->pages; i++)
+		pmbus_clear_fault_page(client, i);
+}
+EXPORT_SYMBOL_GPL(pmbus_clear_faults);
+
+static int pmbus_check_status_cml(struct i2c_client *client, int page)
+{
+	int status, status2;
+
+	status = pmbus_read_byte_data(client, page, PMBUS_STATUS_BYTE);
+	if (status < 0 || (status & PB_STATUS_CML)) {
+		status2 = pmbus_read_byte_data(client, page, PMBUS_STATUS_CML);
+		if (status2 < 0 || (status2 & PB_CML_FAULT_INVALID_COMMAND))
+			return -EINVAL;
+	}
+	return 0;
+}
+
+bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg)
+{
+	int rv;
+	struct pmbus_data *data = i2c_get_clientdata(client);
+
+	rv = pmbus_read_byte_data(client, page, reg);
+	if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
+		rv = pmbus_check_status_cml(client, page);
+	pmbus_clear_fault_page(client, page);
+	return rv >= 0;
+}
+EXPORT_SYMBOL_GPL(pmbus_check_byte_register);
+
+bool pmbus_check_word_register(struct i2c_client *client, int page, int reg)
+{
+	int rv;
+	struct pmbus_data *data = i2c_get_clientdata(client);
+
+	rv = pmbus_read_word_data(client, page, reg);
+	if (rv >= 0 && !(data->flags & PMBUS_SKIP_STATUS_CHECK))
+		rv = pmbus_check_status_cml(client, page);
+	pmbus_clear_fault_page(client, page);
+	return rv >= 0;
+}
+EXPORT_SYMBOL_GPL(pmbus_check_word_register);
+
+const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client *client)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+
+	return data->info;
+}
+EXPORT_SYMBOL_GPL(pmbus_get_driver_info);
+
+static int pmbus_get_status(struct i2c_client *client, int page, int reg)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	const struct pmbus_driver_info *info = data->info;
+	int status;
+
+	if (info->get_status) {
+		status = info->get_status(client, page, reg);
+		if (status != -ENODATA)
+			return status;
+	}
+	return  pmbus_read_byte_data(client, page, reg);
+}
+
+static struct pmbus_data *pmbus_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	const struct pmbus_driver_info *info = data->info;
+
+	mutex_lock(&data->update_lock);
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		int i;
+
+		for (i = 0; i < info->pages; i++)
+			data->status[PB_STATUS_BASE + i]
+			    = pmbus_read_byte_data(client, i,
+						   PMBUS_STATUS_BYTE);
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_VOUT))
+				continue;
+			data->status[PB_STATUS_VOUT_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_VOUT);
+		}
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_IOUT))
+				continue;
+			data->status[PB_STATUS_IOUT_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_IOUT);
+		}
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_TEMP))
+				continue;
+			data->status[PB_STATUS_TEMP_BASE + i]
+			  = pmbus_get_status(client, i,
+					     PMBUS_STATUS_TEMPERATURE);
+		}
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN12))
+				continue;
+			data->status[PB_STATUS_FAN_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_FAN_12);
+		}
+
+		for (i = 0; i < info->pages; i++) {
+			if (!(info->func[i] & PMBUS_HAVE_STATUS_FAN34))
+				continue;
+			data->status[PB_STATUS_FAN34_BASE + i]
+			  = pmbus_get_status(client, i, PMBUS_STATUS_FAN_34);
+		}
+
+		if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
+			data->status[PB_STATUS_INPUT_BASE]
+			  = pmbus_get_status(client, 0, PMBUS_STATUS_INPUT);
+
+		for (i = 0; i < data->num_sensors; i++) {
+			struct pmbus_sensor *sensor = &data->sensors[i];
+
+			if (!data->valid || sensor->update)
+				sensor->data
+				    = pmbus_read_word_data(client, sensor->page,
+							   sensor->reg);
+		}
+		pmbus_clear_faults(client);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/*
+ * Convert linear sensor values to milli- or micro-units
+ * depending on sensor type.
+ */
+static int pmbus_reg2data_linear(struct pmbus_data *data,
+				 struct pmbus_sensor *sensor)
+{
+	s16 exponent;
+	s32 mantissa;
+	long val;
+
+	if (sensor->class == PSC_VOLTAGE_OUT) {	/* LINEAR16 */
+		exponent = data->exponent;
+		mantissa = (u16) sensor->data;
+	} else {				/* LINEAR11 */
+		exponent = (sensor->data >> 11) & 0x001f;
+		mantissa = sensor->data & 0x07ff;
+
+		if (exponent > 0x0f)
+			exponent |= 0xffe0;	/* sign extend exponent */
+		if (mantissa > 0x03ff)
+			mantissa |= 0xfffff800;	/* sign extend mantissa */
+	}
+
+	val = mantissa;
+
+	/* scale result to milli-units for all sensors except fans */
+	if (sensor->class != PSC_FAN)
+		val = val * 1000L;
+
+	/* scale result to micro-units for power sensors */
+	if (sensor->class == PSC_POWER)
+		val = val * 1000L;
+
+	if (exponent >= 0)
+		val <<= exponent;
+	else
+		val >>= -exponent;
+
+	return (int)val;
+}
+
+/*
+ * Convert direct sensor values to milli- or micro-units
+ * depending on sensor type.
+ */
+static int pmbus_reg2data_direct(struct pmbus_data *data,
+				 struct pmbus_sensor *sensor)
+{
+	long val = (s16) sensor->data;
+	long m, b, R;
+
+	m = data->info->m[sensor->class];
+	b = data->info->b[sensor->class];
+	R = data->info->R[sensor->class];
+
+	if (m == 0)
+		return 0;
+
+	/* X = 1/m * (Y * 10^-R - b) */
+	R = -R;
+	/* scale result to milli-units for everything but fans */
+	if (sensor->class != PSC_FAN) {
+		R += 3;
+		b *= 1000;
+	}
+
+	/* scale result to micro-units for power sensors */
+	if (sensor->class == PSC_POWER) {
+		R += 3;
+		b *= 1000;
+	}
+
+	while (R > 0) {
+		val *= 10;
+		R--;
+	}
+	while (R < 0) {
+		val = DIV_ROUND_CLOSEST(val, 10);
+		R++;
+	}
+
+	return (int)((val - b) / m);
+}
+
+static int pmbus_reg2data(struct pmbus_data *data, struct pmbus_sensor *sensor)
+{
+	int val;
+
+	if (data->info->direct[sensor->class])
+		val = pmbus_reg2data_direct(data, sensor);
+	else
+		val = pmbus_reg2data_linear(data, sensor);
+
+	return val;
+}
+
+#define MAX_MANTISSA	(1023 * 1000)
+#define MIN_MANTISSA	(511 * 1000)
+
+static u16 pmbus_data2reg_linear(struct pmbus_data *data,
+				 enum pmbus_sensor_classes class, long val)
+{
+	s16 exponent = 0, mantissa;
+	bool negative = false;
+
+	/* simple case */
+	if (val == 0)
+		return 0;
+
+	if (class == PSC_VOLTAGE_OUT) {
+		/* LINEAR16 does not support negative voltages */
+		if (val < 0)
+			return 0;
+
+		/*
+		 * For a static exponents, we don't have a choice
+		 * but to adjust the value to it.
+		 */
+		if (data->exponent < 0)
+			val <<= -data->exponent;
+		else
+			val >>= data->exponent;
+		val = DIV_ROUND_CLOSEST(val, 1000);
+		return val & 0xffff;
+	}
+
+	if (val < 0) {
+		negative = true;
+		val = -val;
+	}
+
+	/* Power is in uW. Convert to mW before converting. */
+	if (class == PSC_POWER)
+		val = DIV_ROUND_CLOSEST(val, 1000L);
+
+	/*
+	 * For simplicity, convert fan data to milli-units
+	 * before calculating the exponent.
+	 */
+	if (class == PSC_FAN)
+		val = val * 1000;
+
+	/* Reduce large mantissa until it fits into 10 bit */
+	while (val >= MAX_MANTISSA && exponent < 15) {
+		exponent++;
+		val >>= 1;
+	}
+	/* Increase small mantissa to improve precision */
+	while (val < MIN_MANTISSA && exponent > -15) {
+		exponent--;
+		val <<= 1;
+	}
+
+	/* Convert mantissa from milli-units to units */
+	mantissa = DIV_ROUND_CLOSEST(val, 1000);
+
+	/* Ensure that resulting number is within range */
+	if (mantissa > 0x3ff)
+		mantissa = 0x3ff;
+
+	/* restore sign */
+	if (negative)
+		mantissa = -mantissa;
+
+	/* Convert to 5 bit exponent, 11 bit mantissa */
+	return (mantissa & 0x7ff) | ((exponent << 11) & 0xf800);
+}
+
+static u16 pmbus_data2reg_direct(struct pmbus_data *data,
+				 enum pmbus_sensor_classes class, long val)
+{
+	long m, b, R;
+
+	m = data->info->m[class];
+	b = data->info->b[class];
+	R = data->info->R[class];
+
+	/* Power is in uW. Adjust R and b. */
+	if (class == PSC_POWER) {
+		R -= 3;
+		b *= 1000;
+	}
+
+	/* Calculate Y = (m * X + b) * 10^R */
+	if (class != PSC_FAN) {
+		R -= 3;		/* Adjust R and b for data in milli-units */
+		b *= 1000;
+	}
+	val = val * m + b;
+
+	while (R > 0) {
+		val *= 10;
+		R--;
+	}
+	while (R < 0) {
+		val = DIV_ROUND_CLOSEST(val, 10);
+		R++;
+	}
+
+	return val;
+}
+
+static u16 pmbus_data2reg(struct pmbus_data *data,
+			  enum pmbus_sensor_classes class, long val)
+{
+	u16 regval;
+
+	if (data->info->direct[class])
+		regval = pmbus_data2reg_direct(data, class, val);
+	else
+		regval = pmbus_data2reg_linear(data, class, val);
+
+	return regval;
+}
+
+/*
+ * Return boolean calculated from converted data.
+ * <index> defines a status register index and mask, and optionally
+ * two sensor indexes.
+ * The upper half-word references the two sensors,
+ * two sensor indices.
+ * The upper half-word references the two optional sensors,
+ * the lower half word references status register and mask.
+ * The function returns true if (status[reg] & mask) is true and,
+ * if specified, if v1 >= v2.
+ * To determine if an object exceeds upper limits, specify <v, limit>.
+ * To determine if an object exceeds lower limits, specify <limit, v>.
+ *
+ * For booleans created with pmbus_add_boolean_reg(), only the lower 16 bits of
+ * index are set. s1 and s2 (the sensor index values) are zero in this case.
+ * The function returns true if (status[reg] & mask) is true.
+ *
+ * If the boolean was created with pmbus_add_boolean_cmp(), a comparison against
+ * a specified limit has to be performed to determine the boolean result.
+ * In this case, the function returns true if v1 >= v2 (where v1 and v2 are
+ * sensor values referenced by sensor indices s1 and s2).
+ *
+ * To determine if an object exceeds upper limits, specify <s1,s2> = <v,limit>.
+ * To determine if an object exceeds lower limits, specify <s1,s2> = <limit,v>.
+ *
+ * If a negative value is stored in any of the referenced registers, this value
+ * reflects an error code which will be returned.
+ */
+static int pmbus_get_boolean(struct pmbus_data *data, int index, int *val)
+{
+	u8 s1 = (index >> 24) & 0xff;
+	u8 s2 = (index >> 16) & 0xff;
+	u8 reg = (index >> 8) & 0xff;
+	u8 mask = index & 0xff;
+	int status;
+	u8 regval;
+
+	status = data->status[reg];
+	if (status < 0)
+		return status;
+
+	regval = status & mask;
+	if (!s1 && !s2)
+		*val = !!regval;
+	else {
+		int v1, v2;
+		struct pmbus_sensor *sensor1, *sensor2;
+
+		sensor1 = &data->sensors[s1];
+		if (sensor1->data < 0)
+			return sensor1->data;
+		sensor2 = &data->sensors[s2];
+		if (sensor2->data < 0)
+			return sensor2->data;
+
+		v1 = pmbus_reg2data(data, sensor1);
+		v2 = pmbus_reg2data(data, sensor2);
+		*val = !!(regval && v1 >= v2);
+	}
+	return 0;
+}
+
+static ssize_t pmbus_show_boolean(struct device *dev,
+				  struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pmbus_data *data = pmbus_update_device(dev);
+	int val;
+	int err;
+
+	err = pmbus_get_boolean(data, attr->index, &val);
+	if (err)
+		return err;
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t pmbus_show_sensor(struct device *dev,
+				 struct device_attribute *da, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct pmbus_data *data = pmbus_update_device(dev);
+	struct pmbus_sensor *sensor;
+
+	sensor = &data->sensors[attr->index];
+	if (sensor->data < 0)
+		return sensor->data;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", pmbus_reg2data(data, sensor));
+}
+
+static ssize_t pmbus_set_sensor(struct device *dev,
+				struct device_attribute *devattr,
+				const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	struct pmbus_sensor *sensor = &data->sensors[attr->index];
+	ssize_t rv = count;
+	long val = 0;
+	int ret;
+	u16 regval;
+
+	if (strict_strtol(buf, 10, &val) < 0)
+		return -EINVAL;
+
+	mutex_lock(&data->update_lock);
+	regval = pmbus_data2reg(data, sensor->class, val);
+	ret = pmbus_write_word_data(client, sensor->page, sensor->reg, regval);
+	if (ret < 0)
+		rv = ret;
+	else
+		data->sensors[attr->index].data = regval;
+	mutex_unlock(&data->update_lock);
+	return rv;
+}
+
+static ssize_t pmbus_show_label(struct device *dev,
+				struct device_attribute *da, char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			data->labels[attr->index].label);
+}
+
+#define PMBUS_ADD_ATTR(data, _name, _idx, _mode, _type, _show, _set)	\
+do {									\
+	struct sensor_device_attribute *a				\
+	    = &data->_type##s[data->num_##_type##s].attribute;		\
+	BUG_ON(data->num_attributes >= data->max_attributes);		\
+	a->dev_attr.attr.name = _name;					\
+	a->dev_attr.attr.mode = _mode;					\
+	a->dev_attr.show = _show;					\
+	a->dev_attr.store = _set;					\
+	a->index = _idx;						\
+	data->attributes[data->num_attributes] = &a->dev_attr.attr;	\
+	data->num_attributes++;						\
+} while (0)
+
+#define PMBUS_ADD_GET_ATTR(data, _name, _type, _idx)			\
+	PMBUS_ADD_ATTR(data, _name, _idx, S_IRUGO, _type,		\
+		       pmbus_show_##_type,  NULL)
+
+#define PMBUS_ADD_SET_ATTR(data, _name, _type, _idx)			\
+	PMBUS_ADD_ATTR(data, _name, _idx, S_IWUSR | S_IRUGO, _type,	\
+		       pmbus_show_##_type, pmbus_set_##_type)
+
+static void pmbus_add_boolean(struct pmbus_data *data,
+			      const char *name, const char *type, int seq,
+			      int idx)
+{
+	struct pmbus_boolean *boolean;
+
+	BUG_ON(data->num_booleans >= data->max_booleans);
+
+	boolean = &data->booleans[data->num_booleans];
+
+	snprintf(boolean->name, sizeof(boolean->name), "%s%d_%s",
+		 name, seq, type);
+	PMBUS_ADD_GET_ATTR(data, boolean->name, boolean, idx);
+	data->num_booleans++;
+}
+
+static void pmbus_add_boolean_reg(struct pmbus_data *data,
+				  const char *name, const char *type,
+				  int seq, int reg, int bit)
+{
+	pmbus_add_boolean(data, name, type, seq, (reg << 8) | bit);
+}
+
+static void pmbus_add_boolean_cmp(struct pmbus_data *data,
+				  const char *name, const char *type,
+				  int seq, int i1, int i2, int reg, int mask)
+{
+	pmbus_add_boolean(data, name, type, seq,
+			  (i1 << 24) | (i2 << 16) | (reg << 8) | mask);
+}
+
+static void pmbus_add_sensor(struct pmbus_data *data,
+			     const char *name, const char *type, int seq,
+			     int page, int reg, enum pmbus_sensor_classes class,
+			     bool update, bool readonly)
+{
+	struct pmbus_sensor *sensor;
+
+	BUG_ON(data->num_sensors >= data->max_sensors);
+
+	sensor = &data->sensors[data->num_sensors];
+	snprintf(sensor->name, sizeof(sensor->name), "%s%d_%s",
+		 name, seq, type);
+	sensor->page = page;
+	sensor->reg = reg;
+	sensor->class = class;
+	sensor->update = update;
+	if (readonly)
+		PMBUS_ADD_GET_ATTR(data, sensor->name, sensor,
+				   data->num_sensors);
+	else
+		PMBUS_ADD_SET_ATTR(data, sensor->name, sensor,
+				   data->num_sensors);
+	data->num_sensors++;
+}
+
+static void pmbus_add_label(struct pmbus_data *data,
+			    const char *name, int seq,
+			    const char *lstring, int index)
+{
+	struct pmbus_label *label;
+
+	BUG_ON(data->num_labels >= data->max_labels);
+
+	label = &data->labels[data->num_labels];
+	snprintf(label->name, sizeof(label->name), "%s%d_label", name, seq);
+	if (!index)
+		strncpy(label->label, lstring, sizeof(label->label) - 1);
+	else
+		snprintf(label->label, sizeof(label->label), "%s%d", lstring,
+			 index);
+
+	PMBUS_ADD_GET_ATTR(data, label->name, label, data->num_labels);
+	data->num_labels++;
+}
+
+static const int pmbus_temp_registers[] = {
+	PMBUS_READ_TEMPERATURE_1,
+	PMBUS_READ_TEMPERATURE_2,
+	PMBUS_READ_TEMPERATURE_3
+};
+
+static const int pmbus_temp_flags[] = {
+	PMBUS_HAVE_TEMP,
+	PMBUS_HAVE_TEMP2,
+	PMBUS_HAVE_TEMP3
+};
+
+static const int pmbus_fan_registers[] = {
+	PMBUS_READ_FAN_SPEED_1,
+	PMBUS_READ_FAN_SPEED_2,
+	PMBUS_READ_FAN_SPEED_3,
+	PMBUS_READ_FAN_SPEED_4
+};
+
+static const int pmbus_fan_config_registers[] = {
+	PMBUS_FAN_CONFIG_12,
+	PMBUS_FAN_CONFIG_12,
+	PMBUS_FAN_CONFIG_34,
+	PMBUS_FAN_CONFIG_34
+};
+
+static const int pmbus_fan_status_registers[] = {
+	PMBUS_STATUS_FAN_12,
+	PMBUS_STATUS_FAN_12,
+	PMBUS_STATUS_FAN_34,
+	PMBUS_STATUS_FAN_34
+};
+
+static const u32 pmbus_fan_flags[] = {
+	PMBUS_HAVE_FAN12,
+	PMBUS_HAVE_FAN12,
+	PMBUS_HAVE_FAN34,
+	PMBUS_HAVE_FAN34
+};
+
+static const u32 pmbus_fan_status_flags[] = {
+	PMBUS_HAVE_STATUS_FAN12,
+	PMBUS_HAVE_STATUS_FAN12,
+	PMBUS_HAVE_STATUS_FAN34,
+	PMBUS_HAVE_STATUS_FAN34
+};
+
+/*
+ * Determine maximum number of sensors, booleans, and labels.
+ * To keep things simple, only make a rough high estimate.
+ */
+static void pmbus_find_max_attr(struct i2c_client *client,
+				struct pmbus_data *data)
+{
+	const struct pmbus_driver_info *info = data->info;
+	int page, max_sensors, max_booleans, max_labels;
+
+	max_sensors = PMBUS_MAX_INPUT_SENSORS;
+	max_booleans = PMBUS_MAX_INPUT_BOOLEANS;
+	max_labels = PMBUS_MAX_INPUT_LABELS;
+
+	for (page = 0; page < info->pages; page++) {
+		if (info->func[page] & PMBUS_HAVE_VOUT) {
+			max_sensors += PMBUS_VOUT_SENSORS_PER_PAGE;
+			max_booleans += PMBUS_VOUT_BOOLEANS_PER_PAGE;
+			max_labels++;
+		}
+		if (info->func[page] & PMBUS_HAVE_IOUT) {
+			max_sensors += PMBUS_IOUT_SENSORS_PER_PAGE;
+			max_booleans += PMBUS_IOUT_BOOLEANS_PER_PAGE;
+			max_labels++;
+		}
+		if (info->func[page] & PMBUS_HAVE_POUT) {
+			max_sensors += PMBUS_POUT_SENSORS_PER_PAGE;
+			max_booleans += PMBUS_POUT_BOOLEANS_PER_PAGE;
+			max_labels++;
+		}
+		if (info->func[page] & PMBUS_HAVE_FAN12) {
+			max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
+			max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
+		}
+		if (info->func[page] & PMBUS_HAVE_FAN34) {
+			max_sensors += 2 * PMBUS_MAX_SENSORS_PER_FAN;
+			max_booleans += 2 * PMBUS_MAX_BOOLEANS_PER_FAN;
+		}
+		if (info->func[page] & PMBUS_HAVE_TEMP) {
+			max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
+			max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
+		}
+		if (info->func[page] & PMBUS_HAVE_TEMP2) {
+			max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
+			max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
+		}
+		if (info->func[page] & PMBUS_HAVE_TEMP3) {
+			max_sensors += PMBUS_MAX_SENSORS_PER_TEMP;
+			max_booleans += PMBUS_MAX_BOOLEANS_PER_TEMP;
+		}
+	}
+	data->max_sensors = max_sensors;
+	data->max_booleans = max_booleans;
+	data->max_labels = max_labels;
+	data->max_attributes = max_sensors + max_booleans + max_labels;
+}
+
+/*
+ * Search for attributes. Allocate sensors, booleans, and labels as needed.
+ */
+static void pmbus_find_attributes(struct i2c_client *client,
+				  struct pmbus_data *data)
+{
+	const struct pmbus_driver_info *info = data->info;
+	int page, i0, i1, in_index;
+
+	/*
+	 * Input voltage sensors
+	 */
+	in_index = 1;
+	if (info->func[0] & PMBUS_HAVE_VIN) {
+		bool have_alarm = false;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "in", in_index, "vin", 0);
+		pmbus_add_sensor(data, "in", "input", in_index, 0,
+				 PMBUS_READ_VIN, PSC_VOLTAGE_IN, true, true);
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_UV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "min", in_index,
+					 0, PMBUS_VIN_UV_WARN_LIMIT,
+					 PSC_VOLTAGE_IN, false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "min_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_UV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_UV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "lcrit", in_index,
+					 0, PMBUS_VIN_UV_FAULT_LIMIT,
+					 PSC_VOLTAGE_IN, false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "lcrit_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_UV_FAULT);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_OV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "max", in_index,
+					 0, PMBUS_VIN_OV_WARN_LIMIT,
+					 PSC_VOLTAGE_IN, false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "max_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_OV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_VIN_OV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "crit", in_index,
+					 0, PMBUS_VIN_OV_FAULT_LIMIT,
+					 PSC_VOLTAGE_IN, false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "in", "crit_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_VOLTAGE_OV_FAULT);
+				have_alarm = true;
+			}
+		}
+		/*
+		 * Add generic alarm attribute only if there are no individual
+		 * attributes.
+		 */
+		if (!have_alarm)
+			pmbus_add_boolean_reg(data, "in", "alarm",
+					      in_index,
+					      PB_STATUS_BASE,
+					      PB_STATUS_VIN_UV);
+		in_index++;
+	}
+	if (info->func[0] & PMBUS_HAVE_VCAP) {
+		pmbus_add_label(data, "in", in_index, "vcap", 0);
+		pmbus_add_sensor(data, "in", "input", in_index, 0,
+				 PMBUS_READ_VCAP, PSC_VOLTAGE_IN, true, true);
+		in_index++;
+	}
+
+	/*
+	 * Output voltage sensors
+	 */
+	for (page = 0; page < info->pages; page++) {
+		bool have_alarm = false;
+
+		if (!(info->func[page] & PMBUS_HAVE_VOUT))
+			continue;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "in", in_index, "vout", page + 1);
+		pmbus_add_sensor(data, "in", "input", in_index, page,
+				 PMBUS_READ_VOUT, PSC_VOLTAGE_OUT, true, true);
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_UV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "min", in_index, page,
+					 PMBUS_VOUT_UV_WARN_LIMIT,
+					 PSC_VOLTAGE_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "min_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_UV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_UV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "lcrit", in_index, page,
+					 PMBUS_VOUT_UV_FAULT_LIMIT,
+					 PSC_VOLTAGE_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "lcrit_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_UV_FAULT);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_OV_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "max", in_index, page,
+					 PMBUS_VOUT_OV_WARN_LIMIT,
+					 PSC_VOLTAGE_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "max_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_OV_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_VOUT_OV_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "in", "crit", in_index, page,
+					 PMBUS_VOUT_OV_FAULT_LIMIT,
+					 PSC_VOLTAGE_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_VOUT) {
+				pmbus_add_boolean_reg(data, "in", "crit_alarm",
+						      in_index,
+						      PB_STATUS_VOUT_BASE +
+						      page,
+						      PB_VOLTAGE_OV_FAULT);
+				have_alarm = true;
+			}
+		}
+		/*
+		 * Add generic alarm attribute only if there are no individual
+		 * attributes.
+		 */
+		if (!have_alarm)
+			pmbus_add_boolean_reg(data, "in", "alarm",
+					      in_index,
+					      PB_STATUS_BASE + page,
+					      PB_STATUS_VOUT_OV);
+		in_index++;
+	}
+
+	/*
+	 * Current sensors
+	 */
+
+	/*
+	 * Input current sensors
+	 */
+	in_index = 1;
+	if (info->func[0] & PMBUS_HAVE_IIN) {
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "curr", in_index, "iin", 0);
+		pmbus_add_sensor(data, "curr", "input", in_index, 0,
+				 PMBUS_READ_IIN, PSC_CURRENT_IN, true, true);
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_IIN_OC_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "max", in_index,
+					 0, PMBUS_IIN_OC_WARN_LIMIT,
+					 PSC_CURRENT_IN, false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT) {
+				pmbus_add_boolean_reg(data, "curr", "max_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_IIN_OC_WARNING);
+			}
+		}
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_IIN_OC_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "crit", in_index,
+					 0, PMBUS_IIN_OC_FAULT_LIMIT,
+					 PSC_CURRENT_IN, false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
+				pmbus_add_boolean_reg(data, "curr",
+						      "crit_alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_IIN_OC_FAULT);
+		}
+		in_index++;
+	}
+
+	/*
+	 * Output current sensors
+	 */
+	for (page = 0; page < info->pages; page++) {
+		bool have_alarm = false;
+
+		if (!(info->func[page] & PMBUS_HAVE_IOUT))
+			continue;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "curr", in_index, "iout", page + 1);
+		pmbus_add_sensor(data, "curr", "input", in_index, page,
+				 PMBUS_READ_IOUT, PSC_CURRENT_OUT, true, true);
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_IOUT_OC_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "max", in_index, page,
+					 PMBUS_IOUT_OC_WARN_LIMIT,
+					 PSC_CURRENT_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
+				pmbus_add_boolean_reg(data, "curr", "max_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE +
+						      page, PB_IOUT_OC_WARNING);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_IOUT_UC_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "lcrit", in_index, page,
+					 PMBUS_IOUT_UC_FAULT_LIMIT,
+					 PSC_CURRENT_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
+				pmbus_add_boolean_reg(data, "curr",
+						      "lcrit_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE +
+						      page, PB_IOUT_UC_FAULT);
+				have_alarm = true;
+			}
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_IOUT_OC_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "curr", "crit", in_index, page,
+					 PMBUS_IOUT_OC_FAULT_LIMIT,
+					 PSC_CURRENT_OUT, false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT) {
+				pmbus_add_boolean_reg(data, "curr",
+						      "crit_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE +
+						      page, PB_IOUT_OC_FAULT);
+				have_alarm = true;
+			}
+		}
+		/*
+		 * Add generic alarm attribute only if there are no individual
+		 * attributes.
+		 */
+		if (!have_alarm)
+			pmbus_add_boolean_reg(data, "curr", "alarm",
+					      in_index,
+					      PB_STATUS_BASE + page,
+					      PB_STATUS_IOUT_OC);
+		in_index++;
+	}
+
+	/*
+	 * Power sensors
+	 */
+	/*
+	 * Input Power sensors
+	 */
+	in_index = 1;
+	if (info->func[0] & PMBUS_HAVE_PIN) {
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "power", in_index, "pin", 0);
+		pmbus_add_sensor(data, "power", "input", in_index,
+				 0, PMBUS_READ_PIN, PSC_POWER, true, true);
+		if (pmbus_check_word_register(client, 0,
+					      PMBUS_PIN_OP_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "max", in_index,
+					 0, PMBUS_PIN_OP_WARN_LIMIT, PSC_POWER,
+					 false, false);
+			if (info->func[0] & PMBUS_HAVE_STATUS_INPUT)
+				pmbus_add_boolean_reg(data, "power",
+						      "alarm",
+						      in_index,
+						      PB_STATUS_INPUT_BASE,
+						      PB_PIN_OP_WARNING);
+		}
+		in_index++;
+	}
+
+	/*
+	 * Output Power sensors
+	 */
+	for (page = 0; page < info->pages; page++) {
+		bool need_alarm = false;
+
+		if (!(info->func[page] & PMBUS_HAVE_POUT))
+			continue;
+
+		i0 = data->num_sensors;
+		pmbus_add_label(data, "power", in_index, "pout", page + 1);
+		pmbus_add_sensor(data, "power", "input", in_index, page,
+				 PMBUS_READ_POUT, PSC_POWER, true, true);
+		/*
+		 * Per hwmon sysfs API, power_cap is to be used to limit output
+		 * power.
+		 * We have two registers related to maximum output power,
+		 * PMBUS_POUT_MAX and PMBUS_POUT_OP_WARN_LIMIT.
+		 * PMBUS_POUT_MAX matches the powerX_cap attribute definition.
+		 * There is no attribute in the API to match
+		 * PMBUS_POUT_OP_WARN_LIMIT. We use powerX_max for now.
+		 */
+		if (pmbus_check_word_register(client, page, PMBUS_POUT_MAX)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "cap", in_index, page,
+					 PMBUS_POUT_MAX, PSC_POWER,
+					 false, false);
+			need_alarm = true;
+		}
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_POUT_OP_WARN_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "max", in_index, page,
+					 PMBUS_POUT_OP_WARN_LIMIT, PSC_POWER,
+					 false, false);
+			need_alarm = true;
+		}
+		if (need_alarm && (info->func[page] & PMBUS_HAVE_STATUS_IOUT))
+			pmbus_add_boolean_reg(data, "power", "alarm",
+					      in_index,
+					      PB_STATUS_IOUT_BASE + page,
+					      PB_POUT_OP_WARNING
+					      | PB_POWER_LIMITING);
+
+		if (pmbus_check_word_register(client, page,
+					      PMBUS_POUT_OP_FAULT_LIMIT)) {
+			i1 = data->num_sensors;
+			pmbus_add_sensor(data, "power", "crit", in_index, page,
+					 PMBUS_POUT_OP_FAULT_LIMIT, PSC_POWER,
+					 false, false);
+			if (info->func[page] & PMBUS_HAVE_STATUS_IOUT)
+				pmbus_add_boolean_reg(data, "power",
+						      "crit_alarm",
+						      in_index,
+						      PB_STATUS_IOUT_BASE
+						      + page,
+						      PB_POUT_OP_FAULT);
+		}
+		in_index++;
+	}
+
+	/*
+	 * Temperature sensors
+	 */
+	in_index = 1;
+	for (page = 0; page < info->pages; page++) {
+		int t;
+
+		for (t = 0; t < ARRAY_SIZE(pmbus_temp_registers); t++) {
+			bool have_alarm = false;
+
+			/*
+			 * A PMBus chip may support any combination of
+			 * temperature registers on any page. So we can not
+			 * abort after a failure to detect a register, but have
+			 * to continue checking for all registers on all pages.
+			 */
+			if (!(info->func[page] & pmbus_temp_flags[t]))
+				continue;
+
+			if (!pmbus_check_word_register
+			    (client, page, pmbus_temp_registers[t]))
+				continue;
+
+			i0 = data->num_sensors;
+			pmbus_add_sensor(data, "temp", "input", in_index, page,
+					 pmbus_temp_registers[t],
+					 PSC_TEMPERATURE, true, true);
+
+			/*
+			 * PMBus provides only one status register for TEMP1-3.
+			 * Thus, we can not use the status register to determine
+			 * which of the three sensors actually caused an alarm.
+			 * Always compare current temperature against the limit
+			 * registers to determine alarm conditions for a
+			 * specific sensor.
+			 *
+			 * Since there is only one set of limit registers for
+			 * up to three temperature sensors, we need to update
+			 * all limit registers after the limit was changed for
+			 * one of the sensors. This ensures that correct limits
+			 * are reported for all temperature sensors.
+			 */
+			if (pmbus_check_word_register
+			    (client, page, PMBUS_UT_WARN_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "min", in_index,
+						 page, PMBUS_UT_WARN_LIMIT,
+						 PSC_TEMPERATURE, true, false);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"min_alarm", in_index, i1, i0,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_UT_WARNING);
+					have_alarm = true;
+				}
+			}
+			if (pmbus_check_word_register(client, page,
+						      PMBUS_UT_FAULT_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "lcrit",
+						 in_index, page,
+						 PMBUS_UT_FAULT_LIMIT,
+						 PSC_TEMPERATURE, true, false);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"lcrit_alarm", in_index, i1, i0,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_UT_FAULT);
+					have_alarm = true;
+				}
+			}
+			if (pmbus_check_word_register
+			    (client, page, PMBUS_OT_WARN_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "max", in_index,
+						 page, PMBUS_OT_WARN_LIMIT,
+						 PSC_TEMPERATURE, true, false);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"max_alarm", in_index, i0, i1,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_OT_WARNING);
+					have_alarm = true;
+				}
+			}
+			if (pmbus_check_word_register(client, page,
+						      PMBUS_OT_FAULT_LIMIT)) {
+				i1 = data->num_sensors;
+				pmbus_add_sensor(data, "temp", "crit", in_index,
+						 page, PMBUS_OT_FAULT_LIMIT,
+						 PSC_TEMPERATURE, true, false);
+				if (info->func[page] & PMBUS_HAVE_STATUS_TEMP) {
+					pmbus_add_boolean_cmp(data, "temp",
+						"crit_alarm", in_index, i0, i1,
+						PB_STATUS_TEMP_BASE + page,
+						PB_TEMP_OT_FAULT);
+					have_alarm = true;
+				}
+			}
+			/*
+			 * Last resort - we were not able to create any alarm
+			 * registers. Report alarm for all sensors using the
+			 * status register temperature alarm bit.
+			 */
+			if (!have_alarm)
+				pmbus_add_boolean_reg(data, "temp", "alarm",
+						      in_index,
+						      PB_STATUS_BASE + page,
+						      PB_STATUS_TEMPERATURE);
+			in_index++;
+		}
+	}
+
+	/*
+	 * Fans
+	 */
+	in_index = 1;
+	for (page = 0; page < info->pages; page++) {
+		int f;
+
+		for (f = 0; f < ARRAY_SIZE(pmbus_fan_registers); f++) {
+			int regval;
+
+			if (!(info->func[page] & pmbus_fan_flags[f]))
+				break;
+
+			if (!pmbus_check_word_register(client, page,
+						       pmbus_fan_registers[f])
+			    || !pmbus_check_byte_register(client, page,
+						pmbus_fan_config_registers[f]))
+				break;
+
+			/*
+			 * Skip fan if not installed.
+			 * Each fan configuration register covers multiple fans,
+			 * so we have to do some magic.
+			 */
+			regval = pmbus_read_byte_data(client, page,
+				pmbus_fan_config_registers[f]);
+			if (regval < 0 ||
+			    (!(regval & (PB_FAN_1_INSTALLED >> ((f & 1) * 4)))))
+				continue;
+
+			i0 = data->num_sensors;
+			pmbus_add_sensor(data, "fan", "input", in_index, page,
+					 pmbus_fan_registers[f], PSC_FAN, true,
+					 true);
+
+			/*
+			 * Each fan status register covers multiple fans,
+			 * so we have to do some magic.
+			 */
+			if ((info->func[page] & pmbus_fan_status_flags[f]) &&
+			    pmbus_check_byte_register(client,
+					page, pmbus_fan_status_registers[f])) {
+				int base;
+
+				if (f > 1)	/* fan 3, 4 */
+					base = PB_STATUS_FAN34_BASE + page;
+				else
+					base = PB_STATUS_FAN_BASE + page;
+				pmbus_add_boolean_reg(data, "fan", "alarm",
+					in_index, base,
+					PB_FAN_FAN1_WARNING >> (f & 1));
+				pmbus_add_boolean_reg(data, "fan", "fault",
+					in_index, base,
+					PB_FAN_FAN1_FAULT >> (f & 1));
+			}
+			in_index++;
+		}
+	}
+}
+
+/*
+ * Identify chip parameters.
+ * This function is called for all chips.
+ */
+static int pmbus_identify_common(struct i2c_client *client,
+				 struct pmbus_data *data)
+{
+	int vout_mode = -1, exponent;
+
+	if (pmbus_check_byte_register(client, 0, PMBUS_VOUT_MODE))
+		vout_mode = pmbus_read_byte_data(client, 0, PMBUS_VOUT_MODE);
+	if (vout_mode >= 0 && vout_mode != 0xff) {
+		/*
+		 * Not all chips support the VOUT_MODE command,
+		 * so a failure to read it is not an error.
+		 */
+		switch (vout_mode >> 5) {
+		case 0:	/* linear mode      */
+			if (data->info->direct[PSC_VOLTAGE_OUT])
+				return -ENODEV;
+
+			exponent = vout_mode & 0x1f;
+			/* and sign-extend it */
+			if (exponent & 0x10)
+				exponent |= ~0x1f;
+			data->exponent = exponent;
+			break;
+		case 2:	/* direct mode      */
+			if (!data->info->direct[PSC_VOLTAGE_OUT])
+				return -ENODEV;
+			break;
+		default:
+			return -ENODEV;
+		}
+	}
+
+	/* Determine maximum number of sensors, booleans, and labels */
+	pmbus_find_max_attr(client, data);
+	pmbus_clear_fault_page(client, 0);
+	return 0;
+}
+
+int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+		   struct pmbus_driver_info *info)
+{
+	const struct pmbus_platform_data *pdata = client->dev.platform_data;
+	struct pmbus_data *data;
+	int ret;
+
+	if (!info) {
+		dev_err(&client->dev, "Missing chip information");
+		return -ENODEV;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_WRITE_BYTE
+				     | I2C_FUNC_SMBUS_BYTE_DATA
+				     | I2C_FUNC_SMBUS_WORD_DATA))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(&client->dev, "No memory to allocate driver data\n");
+		return -ENOMEM;
+	}
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+
+	/*
+	 * Bail out if status register or PMBus revision register
+	 * does not exist.
+	 */
+	if (i2c_smbus_read_byte_data(client, PMBUS_STATUS_BYTE) < 0
+	    || i2c_smbus_read_byte_data(client, PMBUS_REVISION) < 0) {
+		dev_err(&client->dev,
+			"Status or revision register not found\n");
+		ret = -ENODEV;
+		goto out_data;
+	}
+
+	if (pdata)
+		data->flags = pdata->flags;
+	data->info = info;
+
+	pmbus_clear_faults(client);
+
+	if (info->identify) {
+		ret = (*info->identify)(client, info);
+		if (ret < 0) {
+			dev_err(&client->dev, "Chip identification failed\n");
+			goto out_data;
+		}
+	}
+
+	if (info->pages <= 0 || info->pages > PMBUS_PAGES) {
+		dev_err(&client->dev, "Bad number of PMBus pages: %d\n",
+			info->pages);
+		ret = -EINVAL;
+		goto out_data;
+	}
+	/*
+	 * Bail out if more than one page was configured, but we can not
+	 * select the highest page. This is an indication that the wrong
+	 * chip type was selected. Better bail out now than keep
+	 * returning errors later on.
+	 */
+	if (info->pages > 1 && pmbus_set_page(client, info->pages - 1) < 0) {
+		dev_err(&client->dev, "Failed to select page %d\n",
+			info->pages - 1);
+		ret = -EINVAL;
+		goto out_data;
+	}
+
+	ret = pmbus_identify_common(client, data);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed to identify chip capabilities\n");
+		goto out_data;
+	}
+
+	ret = -ENOMEM;
+	data->sensors = kzalloc(sizeof(struct pmbus_sensor) * data->max_sensors,
+				GFP_KERNEL);
+	if (!data->sensors) {
+		dev_err(&client->dev, "No memory to allocate sensor data\n");
+		goto out_data;
+	}
+
+	data->booleans = kzalloc(sizeof(struct pmbus_boolean)
+				 * data->max_booleans, GFP_KERNEL);
+	if (!data->booleans) {
+		dev_err(&client->dev, "No memory to allocate boolean data\n");
+		goto out_sensors;
+	}
+
+	data->labels = kzalloc(sizeof(struct pmbus_label) * data->max_labels,
+			       GFP_KERNEL);
+	if (!data->labels) {
+		dev_err(&client->dev, "No memory to allocate label data\n");
+		goto out_booleans;
+	}
+
+	data->attributes = kzalloc(sizeof(struct attribute *)
+				   * data->max_attributes, GFP_KERNEL);
+	if (!data->attributes) {
+		dev_err(&client->dev, "No memory to allocate attribute data\n");
+		goto out_labels;
+	}
+
+	pmbus_find_attributes(client, data);
+
+	/*
+	 * If there are no attributes, something is wrong.
+	 * Bail out instead of trying to register nothing.
+	 */
+	if (!data->num_attributes) {
+		dev_err(&client->dev, "No attributes found\n");
+		ret = -ENODEV;
+		goto out_attributes;
+	}
+
+	/* Register sysfs hooks */
+	data->group.attrs = data->attributes;
+	ret = sysfs_create_group(&client->dev.kobj, &data->group);
+	if (ret) {
+		dev_err(&client->dev, "Failed to create sysfs entries\n");
+		goto out_attributes;
+	}
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		ret = PTR_ERR(data->hwmon_dev);
+		dev_err(&client->dev, "Failed to register hwmon device\n");
+		goto out_hwmon_device_register;
+	}
+	return 0;
+
+out_hwmon_device_register:
+	sysfs_remove_group(&client->dev.kobj, &data->group);
+out_attributes:
+	kfree(data->attributes);
+out_labels:
+	kfree(data->labels);
+out_booleans:
+	kfree(data->booleans);
+out_sensors:
+	kfree(data->sensors);
+out_data:
+	kfree(data);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(pmbus_do_probe);
+
+int pmbus_do_remove(struct i2c_client *client)
+{
+	struct pmbus_data *data = i2c_get_clientdata(client);
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &data->group);
+	kfree(data->attributes);
+	kfree(data->labels);
+	kfree(data->booleans);
+	kfree(data->sensors);
+	kfree(data);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(pmbus_do_remove);
+
+MODULE_AUTHOR("Guenter Roeck");
+MODULE_DESCRIPTION("PMBus core driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/pmbus.h linux-libre-2.6.39-gnu/drivers/hwmon/pmbus.h
--- linux-libre-2.6.38-gnu/drivers/hwmon/pmbus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/pmbus.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,313 @@
+/*
+ * pmbus.h - Common defines and structures for PMBus devices
+ *
+ * Copyright (c) 2010, 2011 Ericsson AB.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 PMBUS_H
+#define PMBUS_H
+
+/*
+ * Registers
+ */
+#define PMBUS_PAGE			0x00
+#define PMBUS_OPERATION			0x01
+#define PMBUS_ON_OFF_CONFIG		0x02
+#define PMBUS_CLEAR_FAULTS		0x03
+#define PMBUS_PHASE			0x04
+
+#define PMBUS_CAPABILITY		0x19
+#define PMBUS_QUERY			0x1A
+
+#define PMBUS_VOUT_MODE			0x20
+#define PMBUS_VOUT_COMMAND		0x21
+#define PMBUS_VOUT_TRIM			0x22
+#define PMBUS_VOUT_CAL_OFFSET		0x23
+#define PMBUS_VOUT_MAX			0x24
+#define PMBUS_VOUT_MARGIN_HIGH		0x25
+#define PMBUS_VOUT_MARGIN_LOW		0x26
+#define PMBUS_VOUT_TRANSITION_RATE	0x27
+#define PMBUS_VOUT_DROOP		0x28
+#define PMBUS_VOUT_SCALE_LOOP		0x29
+#define PMBUS_VOUT_SCALE_MONITOR	0x2A
+
+#define PMBUS_COEFFICIENTS		0x30
+#define PMBUS_POUT_MAX			0x31
+
+#define PMBUS_FAN_CONFIG_12		0x3A
+#define PMBUS_FAN_COMMAND_1		0x3B
+#define PMBUS_FAN_COMMAND_2		0x3C
+#define PMBUS_FAN_CONFIG_34		0x3D
+#define PMBUS_FAN_COMMAND_3		0x3E
+#define PMBUS_FAN_COMMAND_4		0x3F
+
+#define PMBUS_VOUT_OV_FAULT_LIMIT	0x40
+#define PMBUS_VOUT_OV_FAULT_RESPONSE	0x41
+#define PMBUS_VOUT_OV_WARN_LIMIT	0x42
+#define PMBUS_VOUT_UV_WARN_LIMIT	0x43
+#define PMBUS_VOUT_UV_FAULT_LIMIT	0x44
+#define PMBUS_VOUT_UV_FAULT_RESPONSE	0x45
+#define PMBUS_IOUT_OC_FAULT_LIMIT	0x46
+#define PMBUS_IOUT_OC_FAULT_RESPONSE	0x47
+#define PMBUS_IOUT_OC_LV_FAULT_LIMIT	0x48
+#define PMBUS_IOUT_OC_LV_FAULT_RESPONSE	0x49
+#define PMBUS_IOUT_OC_WARN_LIMIT	0x4A
+#define PMBUS_IOUT_UC_FAULT_LIMIT	0x4B
+#define PMBUS_IOUT_UC_FAULT_RESPONSE	0x4C
+
+#define PMBUS_OT_FAULT_LIMIT		0x4F
+#define PMBUS_OT_FAULT_RESPONSE		0x50
+#define PMBUS_OT_WARN_LIMIT		0x51
+#define PMBUS_UT_WARN_LIMIT		0x52
+#define PMBUS_UT_FAULT_LIMIT		0x53
+#define PMBUS_UT_FAULT_RESPONSE		0x54
+#define PMBUS_VIN_OV_FAULT_LIMIT	0x55
+#define PMBUS_VIN_OV_FAULT_RESPONSE	0x56
+#define PMBUS_VIN_OV_WARN_LIMIT		0x57
+#define PMBUS_VIN_UV_WARN_LIMIT		0x58
+#define PMBUS_VIN_UV_FAULT_LIMIT	0x59
+
+#define PMBUS_IIN_OC_FAULT_LIMIT	0x5B
+#define PMBUS_IIN_OC_WARN_LIMIT		0x5D
+
+#define PMBUS_POUT_OP_FAULT_LIMIT	0x68
+#define PMBUS_POUT_OP_WARN_LIMIT	0x6A
+#define PMBUS_PIN_OP_WARN_LIMIT		0x6B
+
+#define PMBUS_STATUS_BYTE		0x78
+#define PMBUS_STATUS_WORD		0x79
+#define PMBUS_STATUS_VOUT		0x7A
+#define PMBUS_STATUS_IOUT		0x7B
+#define PMBUS_STATUS_INPUT		0x7C
+#define PMBUS_STATUS_TEMPERATURE	0x7D
+#define PMBUS_STATUS_CML		0x7E
+#define PMBUS_STATUS_OTHER		0x7F
+#define PMBUS_STATUS_MFR_SPECIFIC	0x80
+#define PMBUS_STATUS_FAN_12		0x81
+#define PMBUS_STATUS_FAN_34		0x82
+
+#define PMBUS_READ_VIN			0x88
+#define PMBUS_READ_IIN			0x89
+#define PMBUS_READ_VCAP			0x8A
+#define PMBUS_READ_VOUT			0x8B
+#define PMBUS_READ_IOUT			0x8C
+#define PMBUS_READ_TEMPERATURE_1	0x8D
+#define PMBUS_READ_TEMPERATURE_2	0x8E
+#define PMBUS_READ_TEMPERATURE_3	0x8F
+#define PMBUS_READ_FAN_SPEED_1		0x90
+#define PMBUS_READ_FAN_SPEED_2		0x91
+#define PMBUS_READ_FAN_SPEED_3		0x92
+#define PMBUS_READ_FAN_SPEED_4		0x93
+#define PMBUS_READ_DUTY_CYCLE		0x94
+#define PMBUS_READ_FREQUENCY		0x95
+#define PMBUS_READ_POUT			0x96
+#define PMBUS_READ_PIN			0x97
+
+#define PMBUS_REVISION			0x98
+#define PMBUS_MFR_ID			0x99
+#define PMBUS_MFR_MODEL			0x9A
+#define PMBUS_MFR_REVISION		0x9B
+#define PMBUS_MFR_LOCATION		0x9C
+#define PMBUS_MFR_DATE			0x9D
+#define PMBUS_MFR_SERIAL		0x9E
+
+/*
+ * CAPABILITY
+ */
+#define PB_CAPABILITY_SMBALERT		(1<<4)
+#define PB_CAPABILITY_ERROR_CHECK	(1<<7)
+
+/*
+ * VOUT_MODE
+ */
+#define PB_VOUT_MODE_MODE_MASK		0xe0
+#define PB_VOUT_MODE_PARAM_MASK		0x1f
+
+#define PB_VOUT_MODE_LINEAR		0x00
+#define PB_VOUT_MODE_VID		0x20
+#define PB_VOUT_MODE_DIRECT		0x40
+
+/*
+ * Fan configuration
+ */
+#define PB_FAN_2_PULSE_MASK		((1 << 0) | (1 << 1))
+#define PB_FAN_2_RPM			(1 << 2)
+#define PB_FAN_2_INSTALLED		(1 << 3)
+#define PB_FAN_1_PULSE_MASK		((1 << 4) | (1 << 5))
+#define PB_FAN_1_RPM			(1 << 6)
+#define PB_FAN_1_INSTALLED		(1 << 7)
+
+/*
+ * STATUS_BYTE, STATUS_WORD (lower)
+ */
+#define PB_STATUS_NONE_ABOVE		(1<<0)
+#define PB_STATUS_CML			(1<<1)
+#define PB_STATUS_TEMPERATURE		(1<<2)
+#define PB_STATUS_VIN_UV		(1<<3)
+#define PB_STATUS_IOUT_OC		(1<<4)
+#define PB_STATUS_VOUT_OV		(1<<5)
+#define PB_STATUS_OFF			(1<<6)
+#define PB_STATUS_BUSY			(1<<7)
+
+/*
+ * STATUS_WORD (upper)
+ */
+#define PB_STATUS_UNKNOWN		(1<<8)
+#define PB_STATUS_OTHER			(1<<9)
+#define PB_STATUS_FANS			(1<<10)
+#define PB_STATUS_POWER_GOOD_N		(1<<11)
+#define PB_STATUS_WORD_MFR		(1<<12)
+#define PB_STATUS_INPUT			(1<<13)
+#define PB_STATUS_IOUT_POUT		(1<<14)
+#define PB_STATUS_VOUT			(1<<15)
+
+/*
+ * STATUS_IOUT
+ */
+#define PB_POUT_OP_WARNING		(1<<0)
+#define PB_POUT_OP_FAULT		(1<<1)
+#define PB_POWER_LIMITING		(1<<2)
+#define PB_CURRENT_SHARE_FAULT		(1<<3)
+#define PB_IOUT_UC_FAULT		(1<<4)
+#define PB_IOUT_OC_WARNING		(1<<5)
+#define PB_IOUT_OC_LV_FAULT		(1<<6)
+#define PB_IOUT_OC_FAULT		(1<<7)
+
+/*
+ * STATUS_VOUT, STATUS_INPUT
+ */
+#define PB_VOLTAGE_UV_FAULT		(1<<4)
+#define PB_VOLTAGE_UV_WARNING		(1<<5)
+#define PB_VOLTAGE_OV_WARNING		(1<<6)
+#define PB_VOLTAGE_OV_FAULT		(1<<7)
+
+/*
+ * STATUS_INPUT
+ */
+#define PB_PIN_OP_WARNING		(1<<0)
+#define PB_IIN_OC_WARNING		(1<<1)
+#define PB_IIN_OC_FAULT			(1<<2)
+
+/*
+ * STATUS_TEMPERATURE
+ */
+#define PB_TEMP_UT_FAULT		(1<<4)
+#define PB_TEMP_UT_WARNING		(1<<5)
+#define PB_TEMP_OT_WARNING		(1<<6)
+#define PB_TEMP_OT_FAULT		(1<<7)
+
+/*
+ * STATUS_FAN
+ */
+#define PB_FAN_AIRFLOW_WARNING		(1<<0)
+#define PB_FAN_AIRFLOW_FAULT		(1<<1)
+#define PB_FAN_FAN2_SPEED_OVERRIDE	(1<<2)
+#define PB_FAN_FAN1_SPEED_OVERRIDE	(1<<3)
+#define PB_FAN_FAN2_WARNING		(1<<4)
+#define PB_FAN_FAN1_WARNING		(1<<5)
+#define PB_FAN_FAN2_FAULT		(1<<6)
+#define PB_FAN_FAN1_FAULT		(1<<7)
+
+/*
+ * CML_FAULT_STATUS
+ */
+#define PB_CML_FAULT_OTHER_MEM_LOGIC	(1<<0)
+#define PB_CML_FAULT_OTHER_COMM		(1<<1)
+#define PB_CML_FAULT_PROCESSOR		(1<<3)
+#define PB_CML_FAULT_MEMORY		(1<<4)
+#define PB_CML_FAULT_PACKET_ERROR	(1<<5)
+#define PB_CML_FAULT_INVALID_DATA	(1<<6)
+#define PB_CML_FAULT_INVALID_COMMAND	(1<<7)
+
+enum pmbus_sensor_classes {
+	PSC_VOLTAGE_IN = 0,
+	PSC_VOLTAGE_OUT,
+	PSC_CURRENT_IN,
+	PSC_CURRENT_OUT,
+	PSC_POWER,
+	PSC_TEMPERATURE,
+	PSC_FAN,
+	PSC_NUM_CLASSES		/* Number of power sensor classes */
+};
+
+#define PMBUS_PAGES	32	/* Per PMBus specification */
+
+/* Functionality bit mask */
+#define PMBUS_HAVE_VIN		(1 << 0)
+#define PMBUS_HAVE_VCAP		(1 << 1)
+#define PMBUS_HAVE_VOUT		(1 << 2)
+#define PMBUS_HAVE_IIN		(1 << 3)
+#define PMBUS_HAVE_IOUT		(1 << 4)
+#define PMBUS_HAVE_PIN		(1 << 5)
+#define PMBUS_HAVE_POUT		(1 << 6)
+#define PMBUS_HAVE_FAN12	(1 << 7)
+#define PMBUS_HAVE_FAN34	(1 << 8)
+#define PMBUS_HAVE_TEMP		(1 << 9)
+#define PMBUS_HAVE_TEMP2	(1 << 10)
+#define PMBUS_HAVE_TEMP3	(1 << 11)
+#define PMBUS_HAVE_STATUS_VOUT	(1 << 12)
+#define PMBUS_HAVE_STATUS_IOUT	(1 << 13)
+#define PMBUS_HAVE_STATUS_INPUT	(1 << 14)
+#define PMBUS_HAVE_STATUS_TEMP	(1 << 15)
+#define PMBUS_HAVE_STATUS_FAN12	(1 << 16)
+#define PMBUS_HAVE_STATUS_FAN34	(1 << 17)
+
+struct pmbus_driver_info {
+	int pages;		/* Total number of pages */
+	bool direct[PSC_NUM_CLASSES];
+				/* true if device uses direct data format
+				   for the given sensor class */
+	/*
+	 * Support one set of coefficients for each sensor type
+	 * Used for chips providing data in direct mode.
+	 */
+	int m[PSC_NUM_CLASSES];	/* mantissa for direct data format */
+	int b[PSC_NUM_CLASSES];	/* offset */
+	int R[PSC_NUM_CLASSES];	/* exponent */
+
+	u32 func[PMBUS_PAGES];	/* Functionality, per page */
+	/*
+	 * The get_status function maps manufacturing specific status values
+	 * into PMBus standard status values.
+	 * This function is optional and only necessary if chip specific status
+	 * register values have to be mapped into standard PMBus status register
+	 * values.
+	 */
+	int (*get_status)(struct i2c_client *client, int page, int reg);
+	/*
+	 * The identify function determines supported PMBus functionality.
+	 * This function is only necessary if a chip driver supports multiple
+	 * chips, and the chip functionality is not pre-determined.
+	 */
+	int (*identify)(struct i2c_client *client,
+			struct pmbus_driver_info *info);
+};
+
+/* Function declarations */
+
+int pmbus_set_page(struct i2c_client *client, u8 page);
+int pmbus_read_word_data(struct i2c_client *client, u8 page, u8 reg);
+void pmbus_clear_faults(struct i2c_client *client);
+bool pmbus_check_byte_register(struct i2c_client *client, int page, int reg);
+bool pmbus_check_word_register(struct i2c_client *client, int page, int reg);
+int pmbus_do_probe(struct i2c_client *client, const struct i2c_device_id *id,
+		   struct pmbus_driver_info *info);
+int pmbus_do_remove(struct i2c_client *client);
+const struct pmbus_driver_info *pmbus_get_driver_info(struct i2c_client
+						      *client);
+
+#endif /* PMBUS_H */
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/sch5627.c linux-libre-2.6.39-gnu/drivers/hwmon/sch5627.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/sch5627.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/sch5627.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,858 @@
+/***************************************************************************
+ *   Copyright (C) 2010-2011 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  *
+ *   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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+#include <linux/delay.h>
+
+#define DRVNAME "sch5627"
+#define DEVNAME DRVNAME /* We only support one model */
+
+#define SIO_SCH5627_EM_LD	0x0C	/* Embedded Microcontroller LD */
+#define SIO_UNLOCK_KEY		0x55	/* Key to enable Super-I/O */
+#define SIO_LOCK_KEY		0xAA	/* Key to disable Super-I/O */
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x66	/* Logical device address (2 bytes) */
+
+#define SIO_SCH5627_ID		0xC6	/* Chipset ID */
+
+#define REGION_LENGTH		9
+
+#define SCH5627_HWMON_ID		0xa5
+#define SCH5627_COMPANY_ID		0x5c
+#define SCH5627_PRIMARY_ID		0xa0
+
+#define SCH5627_REG_BUILD_CODE		0x39
+#define SCH5627_REG_BUILD_ID		0x3a
+#define SCH5627_REG_HWMON_ID		0x3c
+#define SCH5627_REG_HWMON_REV		0x3d
+#define SCH5627_REG_COMPANY_ID		0x3e
+#define SCH5627_REG_PRIMARY_ID		0x3f
+#define SCH5627_REG_CTRL		0x40
+
+#define SCH5627_NO_TEMPS		8
+#define SCH5627_NO_FANS			4
+#define SCH5627_NO_IN			5
+
+static const u16 SCH5627_REG_TEMP_MSB[SCH5627_NO_TEMPS] = {
+	0x2B, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x180, 0x181 };
+static const u16 SCH5627_REG_TEMP_LSN[SCH5627_NO_TEMPS] = {
+	0xE2, 0xE1, 0xE1, 0xE5, 0xE5, 0xE6, 0x182, 0x182 };
+static const u16 SCH5627_REG_TEMP_HIGH_NIBBLE[SCH5627_NO_TEMPS] = {
+	0, 0, 1, 1, 0, 0, 0, 1 };
+static const u16 SCH5627_REG_TEMP_HIGH[SCH5627_NO_TEMPS] = {
+	0x61, 0x57, 0x59, 0x5B, 0x5D, 0x5F, 0x184, 0x186 };
+static const u16 SCH5627_REG_TEMP_ABS[SCH5627_NO_TEMPS] = {
+	0x9B, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x1A8, 0x1A9 };
+
+static const u16 SCH5627_REG_FAN[SCH5627_NO_FANS] = {
+	0x2C, 0x2E, 0x30, 0x32 };
+static const u16 SCH5627_REG_FAN_MIN[SCH5627_NO_FANS] = {
+	0x62, 0x64, 0x66, 0x68 };
+
+static const u16 SCH5627_REG_IN_MSB[SCH5627_NO_IN] = {
+	0x22, 0x23, 0x24, 0x25, 0x189 };
+static const u16 SCH5627_REG_IN_LSN[SCH5627_NO_IN] = {
+	0xE4, 0xE4, 0xE3, 0xE3, 0x18A };
+static const u16 SCH5627_REG_IN_HIGH_NIBBLE[SCH5627_NO_IN] = {
+	1, 0, 1, 0, 1 };
+static const u16 SCH5627_REG_IN_FACTOR[SCH5627_NO_IN] = {
+	10745, 3660, 9765, 10745, 3660 };
+static const char * const SCH5627_IN_LABELS[SCH5627_NO_IN] = {
+	"VCC", "VTT", "VBAT", "VTR", "V_IN" };
+
+struct sch5627_data {
+	unsigned short addr;
+	struct device *hwmon_dev;
+	u8 temp_max[SCH5627_NO_TEMPS];
+	u8 temp_crit[SCH5627_NO_TEMPS];
+	u16 fan_min[SCH5627_NO_FANS];
+
+	struct mutex update_lock;
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	u16 temp[SCH5627_NO_TEMPS];
+	u16 fan[SCH5627_NO_FANS];
+	u16 in[SCH5627_NO_IN];
+};
+
+static struct platform_device *sch5627_pdev;
+
+/* Super I/O functions */
+static inline int superio_inb(int base, int reg)
+{
+	outb(reg, base);
+	return inb(base + 1);
+}
+
+static inline int superio_enter(int base)
+{
+	/* Don't step on other drivers' I/O space by accident */
+	if (!request_muxed_region(base, 2, DRVNAME)) {
+		pr_err("I/O address 0x%04x already in use\n", base);
+		return -EBUSY;
+	}
+
+	outb(SIO_UNLOCK_KEY, base);
+
+	return 0;
+}
+
+static inline void superio_select(int base, int ld)
+{
+	outb(SIO_REG_LDSEL, base);
+	outb(ld, base + 1);
+}
+
+static inline void superio_exit(int base)
+{
+	outb(SIO_LOCK_KEY, base);
+	release_region(base, 2);
+}
+
+static int sch5627_read_virtual_reg(struct sch5627_data *data, u16 reg)
+{
+	u8 val;
+	int i;
+	/*
+	 * According to SMSC for the commands we use the maximum time for
+	 * the EM to respond is 15 ms, but testing shows in practice it
+	 * responds within 15-32 reads, so we first busy poll, and if
+	 * that fails sleep a bit and try again until we are way past
+	 * the 15 ms maximum response time.
+	 */
+	const int max_busy_polls = 64;
+	const int max_lazy_polls = 32;
+
+	/* (Optional) Write-Clear the EC to Host Mailbox Register */
+	val = inb(data->addr + 1);
+	outb(val, data->addr + 1);
+
+	/* Set Mailbox Address Pointer to first location in Region 1 */
+	outb(0x00, data->addr + 2);
+	outb(0x80, data->addr + 3);
+
+	/* Write Request Packet Header */
+	outb(0x02, data->addr + 4); /* Access Type: VREG read */
+	outb(0x01, data->addr + 5); /* # of Entries: 1 Byte (8-bit) */
+	outb(0x04, data->addr + 2); /* Mailbox AP to first data entry loc. */
+
+	/* Write Address field */
+	outb(reg & 0xff, data->addr + 6);
+	outb(reg >> 8, data->addr + 7);
+
+	/* Execute the Random Access Command */
+	outb(0x01, data->addr); /* Write 01h to the Host-to-EC register */
+
+	/* EM Interface Polling "Algorithm" */
+	for (i = 0; i < max_busy_polls + max_lazy_polls; i++) {
+		if (i >= max_busy_polls)
+			msleep(1);
+		/* Read Interrupt source Register */
+		val = inb(data->addr + 8);
+		/* Write Clear the interrupt source bits */
+		if (val)
+			outb(val, data->addr + 8);
+		/* Command Completed ? */
+		if (val & 0x01)
+			break;
+	}
+	if (i == max_busy_polls + max_lazy_polls) {
+		pr_err("Max retries exceeded reading virtual "
+		       "register 0x%04hx (%d)\n", reg, 1);
+		return -EIO;
+	}
+
+	/*
+	 * According to SMSC we may need to retry this, but sofar I've always
+	 * seen this succeed in 1 try.
+	 */
+	for (i = 0; i < max_busy_polls; i++) {
+		/* Read EC-to-Host Register */
+		val = inb(data->addr + 1);
+		/* Command Completed ? */
+		if (val == 0x01)
+			break;
+
+		if (i == 0)
+			pr_warn("EC reports: 0x%02x reading virtual register "
+				"0x%04hx\n", (unsigned int)val, reg);
+	}
+	if (i == max_busy_polls) {
+		pr_err("Max retries exceeded reading virtual "
+		       "register 0x%04hx (%d)\n", reg, 2);
+		return -EIO;
+	}
+
+	/*
+	 * According to the SMSC app note we should now do:
+	 *
+	 * Set Mailbox Address Pointer to first location in Region 1 *
+	 * outb(0x00, data->addr + 2);
+	 * outb(0x80, data->addr + 3);
+	 *
+	 * But if we do that things don't work, so let's not.
+	 */
+
+	/* Read Data from Mailbox */
+	return inb(data->addr + 4);
+}
+
+static int sch5627_read_virtual_reg16(struct sch5627_data *data, u16 reg)
+{
+	int lsb, msb;
+
+	/* Read LSB first, this will cause the matching MSB to be latched */
+	lsb = sch5627_read_virtual_reg(data, reg);
+	if (lsb < 0)
+		return lsb;
+
+	msb = sch5627_read_virtual_reg(data, reg + 1);
+	if (msb < 0)
+		return msb;
+
+	return lsb | (msb << 8);
+}
+
+static int sch5627_read_virtual_reg12(struct sch5627_data *data, u16 msb_reg,
+				      u16 lsn_reg, int high_nibble)
+{
+	int msb, lsn;
+
+	/* Read MSB first, this will cause the matching LSN to be latched */
+	msb = sch5627_read_virtual_reg(data, msb_reg);
+	if (msb < 0)
+		return msb;
+
+	lsn = sch5627_read_virtual_reg(data, lsn_reg);
+	if (lsn < 0)
+		return lsn;
+
+	if (high_nibble)
+		return (msb << 4) | (lsn >> 4);
+	else
+		return (msb << 4) | (lsn & 0x0f);
+}
+
+static struct sch5627_data *sch5627_update_device(struct device *dev)
+{
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	struct sch5627_data *ret = data;
+	int i, val;
+
+	mutex_lock(&data->update_lock);
+
+	/* Cache the values for 1 second */
+	if (time_after(jiffies, data->last_updated + HZ) || !data->valid) {
+		for (i = 0; i < SCH5627_NO_TEMPS; i++) {
+			val = sch5627_read_virtual_reg12(data,
+				SCH5627_REG_TEMP_MSB[i],
+				SCH5627_REG_TEMP_LSN[i],
+				SCH5627_REG_TEMP_HIGH_NIBBLE[i]);
+			if (unlikely(val < 0)) {
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->temp[i] = val;
+		}
+
+		for (i = 0; i < SCH5627_NO_FANS; i++) {
+			val = sch5627_read_virtual_reg16(data,
+							 SCH5627_REG_FAN[i]);
+			if (unlikely(val < 0)) {
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->fan[i] = val;
+		}
+
+		for (i = 0; i < SCH5627_NO_IN; i++) {
+			val = sch5627_read_virtual_reg12(data,
+				SCH5627_REG_IN_MSB[i],
+				SCH5627_REG_IN_LSN[i],
+				SCH5627_REG_IN_HIGH_NIBBLE[i]);
+			if (unlikely(val < 0)) {
+				ret = ERR_PTR(val);
+				goto abort;
+			}
+			data->in[i] = val;
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+abort:
+	mutex_unlock(&data->update_lock);
+	return ret;
+}
+
+static int __devinit sch5627_read_limits(struct sch5627_data *data)
+{
+	int i, val;
+
+	for (i = 0; i < SCH5627_NO_TEMPS; i++) {
+		/*
+		 * Note what SMSC calls ABS, is what lm_sensors calls max
+		 * (aka high), and HIGH is what lm_sensors calls crit.
+		 */
+		val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_ABS[i]);
+		if (val < 0)
+			return val;
+		data->temp_max[i] = val;
+
+		val = sch5627_read_virtual_reg(data, SCH5627_REG_TEMP_HIGH[i]);
+		if (val < 0)
+			return val;
+		data->temp_crit[i] = val;
+	}
+	for (i = 0; i < SCH5627_NO_FANS; i++) {
+		val = sch5627_read_virtual_reg16(data, SCH5627_REG_FAN_MIN[i]);
+		if (val < 0)
+			return val;
+		data->fan_min[i] = val;
+	}
+
+	return 0;
+}
+
+static int reg_to_temp(u16 reg)
+{
+	return (reg * 625) / 10 - 64000;
+}
+
+static int reg_to_temp_limit(u8 reg)
+{
+	return (reg - 64) * 1000;
+}
+
+static int reg_to_rpm(u16 reg)
+{
+	if (reg == 0)
+		return -EIO;
+	if (reg == 0xffff)
+		return 0;
+
+	return 5400540 / reg;
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute *devattr,
+	char *buf)
+{
+	return snprintf(buf, PAGE_SIZE, "%s\n", DEVNAME);
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = reg_to_temp(data->temp[attr->index]);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_fault(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", data->temp[attr->index] == 0);
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	int val;
+
+	val = reg_to_temp_limit(data->temp_max[attr->index]);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	int val;
+
+	val = reg_to_temp_limit(data->temp_crit[attr->index]);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = reg_to_rpm(data->fan[attr->index]);
+	if (val < 0)
+		return val;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_fan_fault(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	return snprintf(buf, PAGE_SIZE, "%d\n",
+			data->fan[attr->index] == 0xffff);
+}
+
+static ssize_t show_fan_min(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = dev_get_drvdata(dev);
+	int val = reg_to_rpm(data->fan_min[attr->index]);
+	if (val < 0)
+		return val;
+
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct sch5627_data *data = sch5627_update_device(dev);
+	int val;
+
+	if (IS_ERR(data))
+		return PTR_ERR(data);
+
+	val = DIV_ROUND_CLOSEST(
+		data->in[attr->index] * SCH5627_REG_IN_FACTOR[attr->index],
+		10000);
+	return snprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
+static ssize_t show_in_label(struct device *dev, struct device_attribute
+	*devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+
+	return snprintf(buf, PAGE_SIZE, "%s\n",
+			SCH5627_IN_LABELS[attr->index]);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_fault, S_IRUGO, show_temp_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_temp_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_temp_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_temp_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_fault, S_IRUGO, show_temp_fault, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_fault, S_IRUGO, show_temp_fault, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_fault, S_IRUGO, show_temp_fault, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_fault, S_IRUGO, show_temp_fault, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_max, S_IRUGO, show_temp_max, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_max, S_IRUGO, show_temp_max, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_max, S_IRUGO, show_temp_max, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_max, S_IRUGO, show_temp_max, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_max, S_IRUGO, show_temp_max, NULL, 7);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp_crit, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp5_crit, S_IRUGO, show_temp_crit, NULL, 4);
+static SENSOR_DEVICE_ATTR(temp6_crit, S_IRUGO, show_temp_crit, NULL, 5);
+static SENSOR_DEVICE_ATTR(temp7_crit, S_IRUGO, show_temp_crit, NULL, 6);
+static SENSOR_DEVICE_ATTR(temp8_crit, S_IRUGO, show_temp_crit, NULL, 7);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_fault, S_IRUGO, show_fan_fault, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_fault, S_IRUGO, show_fan_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_fault, S_IRUGO, show_fan_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_fault, S_IRUGO, show_fan_fault, NULL, 3);
+static SENSOR_DEVICE_ATTR(fan1_min, S_IRUGO, show_fan_min, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IRUGO, show_fan_min, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IRUGO, show_fan_min, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IRUGO, show_fan_min, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in0_label, S_IRUGO, show_in_label, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_label, S_IRUGO, show_in_label, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_label, S_IRUGO, show_in_label, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_label, S_IRUGO, show_in_label, NULL, 3);
+
+static struct attribute *sch5627_attributes[] = {
+	&dev_attr_name.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp5_input.dev_attr.attr,
+	&sensor_dev_attr_temp6_input.dev_attr.attr,
+	&sensor_dev_attr_temp7_input.dev_attr.attr,
+	&sensor_dev_attr_temp8_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
+	&sensor_dev_attr_temp5_fault.dev_attr.attr,
+	&sensor_dev_attr_temp6_fault.dev_attr.attr,
+	&sensor_dev_attr_temp7_fault.dev_attr.attr,
+	&sensor_dev_attr_temp8_fault.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp4_max.dev_attr.attr,
+	&sensor_dev_attr_temp5_max.dev_attr.attr,
+	&sensor_dev_attr_temp6_max.dev_attr.attr,
+	&sensor_dev_attr_temp7_max.dev_attr.attr,
+	&sensor_dev_attr_temp8_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	&sensor_dev_attr_temp4_crit.dev_attr.attr,
+	&sensor_dev_attr_temp5_crit.dev_attr.attr,
+	&sensor_dev_attr_temp6_crit.dev_attr.attr,
+	&sensor_dev_attr_temp7_crit.dev_attr.attr,
+	&sensor_dev_attr_temp8_crit.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_fault.dev_attr.attr,
+	&sensor_dev_attr_fan2_fault.dev_attr.attr,
+	&sensor_dev_attr_fan3_fault.dev_attr.attr,
+	&sensor_dev_attr_fan4_fault.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan4_min.dev_attr.attr,
+
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in0_label.dev_attr.attr,
+	&sensor_dev_attr_in1_label.dev_attr.attr,
+	&sensor_dev_attr_in2_label.dev_attr.attr,
+	&sensor_dev_attr_in3_label.dev_attr.attr,
+	/* No in4_label as in4 is a generic input pin */
+
+	NULL
+};
+
+static const struct attribute_group sch5627_group = {
+	.attrs = sch5627_attributes,
+};
+
+static int sch5627_remove(struct platform_device *pdev)
+{
+	struct sch5627_data *data = platform_get_drvdata(pdev);
+
+	if (data->hwmon_dev)
+		hwmon_device_unregister(data->hwmon_dev);
+
+	sysfs_remove_group(&pdev->dev.kobj, &sch5627_group);
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+
+	return 0;
+}
+
+static int __devinit sch5627_probe(struct platform_device *pdev)
+{
+	struct sch5627_data *data;
+	int err, build_code, build_id, hwmon_rev, val;
+
+	data = kzalloc(sizeof(struct sch5627_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+	mutex_init(&data->update_lock);
+	platform_set_drvdata(pdev, data);
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_ID);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (val != SCH5627_HWMON_ID) {
+		pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "hwmon",
+		       val, SCH5627_HWMON_ID);
+		err = -ENODEV;
+		goto error;
+	}
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_COMPANY_ID);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (val != SCH5627_COMPANY_ID) {
+		pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "company",
+		       val, SCH5627_COMPANY_ID);
+		err = -ENODEV;
+		goto error;
+	}
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_PRIMARY_ID);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (val != SCH5627_PRIMARY_ID) {
+		pr_err("invalid %s id: 0x%02X (expected 0x%02X)\n", "primary",
+		       val, SCH5627_PRIMARY_ID);
+		err = -ENODEV;
+		goto error;
+	}
+
+	build_code = sch5627_read_virtual_reg(data, SCH5627_REG_BUILD_CODE);
+	if (build_code < 0) {
+		err = build_code;
+		goto error;
+	}
+
+	build_id = sch5627_read_virtual_reg16(data, SCH5627_REG_BUILD_ID);
+	if (build_id < 0) {
+		err = build_id;
+		goto error;
+	}
+
+	hwmon_rev = sch5627_read_virtual_reg(data, SCH5627_REG_HWMON_REV);
+	if (hwmon_rev < 0) {
+		err = hwmon_rev;
+		goto error;
+	}
+
+	val = sch5627_read_virtual_reg(data, SCH5627_REG_CTRL);
+	if (val < 0) {
+		err = val;
+		goto error;
+	}
+	if (!(val & 0x01)) {
+		pr_err("hardware monitoring not enabled\n");
+		err = -ENODEV;
+		goto error;
+	}
+
+	/*
+	 * Read limits, we do this only once as reading a register on
+	 * the sch5627 is quite expensive (and they don't change).
+	 */
+	err = sch5627_read_limits(data);
+	if (err)
+		goto error;
+
+	pr_info("firmware build: code 0x%02X, id 0x%04X, hwmon: rev 0x%02X\n",
+		build_code, build_id, hwmon_rev);
+
+	/* Register sysfs interface files */
+	err = sysfs_create_group(&pdev->dev.kobj, &sch5627_group);
+	if (err)
+		goto error;
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		goto error;
+	}
+
+	return 0;
+
+error:
+	sch5627_remove(pdev);
+	return err;
+}
+
+static int __init sch5627_find(int sioaddr, unsigned short *address)
+{
+	u8 devid;
+	int err = superio_enter(sioaddr);
+	if (err)
+		return err;
+
+	devid = superio_inb(sioaddr, SIO_REG_DEVID);
+	if (devid != SIO_SCH5627_ID) {
+		pr_debug("Unsupported device id: 0x%02x\n",
+			 (unsigned int)devid);
+		err = -ENODEV;
+		goto exit;
+	}
+
+	superio_select(sioaddr, SIO_SCH5627_EM_LD);
+
+	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+		pr_warn("Device not activated\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/*
+	 * Warning the order of the low / high byte is the other way around
+	 * as on most other superio devices!!
+	 */
+	*address = superio_inb(sioaddr, SIO_REG_ADDR) |
+		   superio_inb(sioaddr, SIO_REG_ADDR + 1) << 8;
+	if (*address == 0) {
+		pr_warn("Base address not set\n");
+		err = -ENODEV;
+		goto exit;
+	}
+
+	pr_info("Found %s chip at %#hx\n", DEVNAME, *address);
+exit:
+	superio_exit(sioaddr);
+	return err;
+}
+
+static int __init sch5627_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + REGION_LENGTH - 1,
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	sch5627_pdev = platform_device_alloc(DRVNAME, address);
+	if (!sch5627_pdev)
+		return -ENOMEM;
+
+	res.name = sch5627_pdev->name;
+	err = acpi_check_resource_conflict(&res);
+	if (err)
+		goto exit_device_put;
+
+	err = platform_device_add_resources(sch5627_pdev, &res, 1);
+	if (err) {
+		pr_err("Device resource addition failed\n");
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(sch5627_pdev);
+	if (err) {
+		pr_err("Device addition failed\n");
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(sch5627_pdev);
+
+	return err;
+}
+
+static struct platform_driver sch5627_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= sch5627_probe,
+	.remove		= sch5627_remove,
+};
+
+static int __init sch5627_init(void)
+{
+	int err = -ENODEV;
+	unsigned short address;
+
+	if (sch5627_find(0x4e, &address) && sch5627_find(0x2e, &address))
+		goto exit;
+
+	err = platform_driver_register(&sch5627_driver);
+	if (err)
+		goto exit;
+
+	err = sch5627_device_add(address);
+	if (err)
+		goto exit_driver;
+
+	return 0;
+
+exit_driver:
+	platform_driver_unregister(&sch5627_driver);
+exit:
+	return err;
+}
+
+static void __exit sch5627_exit(void)
+{
+	platform_device_unregister(sch5627_pdev);
+	platform_driver_unregister(&sch5627_driver);
+}
+
+MODULE_DESCRIPTION("SMSC SCH5627 Hardware Monitoring Driver");
+MODULE_AUTHOR("Hans de Goede (hdegoede@redhat.com)");
+MODULE_LICENSE("GPL");
+
+module_init(sch5627_init);
+module_exit(sch5627_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/sht15.c linux-libre-2.6.39-gnu/drivers/hwmon/sht15.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/sht15.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/sht15.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,7 +52,7 @@
 #define SHT15_TSU		150	/* data setup time */
 
 /**
- * struct sht15_temppair - elements of voltage dependant temp calc
+ * struct sht15_temppair - elements of voltage dependent temp calc
  * @vdd:	supply voltage in microvolts
  * @d1:		see data sheet
  */
@@ -251,7 +251,7 @@
 	enable_irq(gpio_to_irq(data->pdata->gpio_data));
 	if (gpio_get_value(data->pdata->gpio_data) == 0) {
 		disable_irq_nosync(gpio_to_irq(data->pdata->gpio_data));
-		/* Only relevant if the interrupt hasn't occured. */
+		/* Only relevant if the interrupt hasn't occurred. */
 		if (!atomic_read(&data->interrupt_handled))
 			schedule_work(&data->read_work);
 	}
@@ -333,11 +333,11 @@
 
 	const int c1 = -4;
 	const int c2 = 40500; /* x 10 ^ -6 */
-	const int c3 = -2800; /* x10 ^ -9 */
+	const int c3 = -28; /* x 10 ^ -7 */
 
 	RHlinear = c1*1000
 		+ c2 * data->val_humid/1000
-		+ (data->val_humid * data->val_humid * c3)/1000000;
+		+ (data->val_humid * data->val_humid * c3) / 10000;
 	return (temp - 25000) * (10000 + 80 * data->val_humid)
 		/ 1000000 + RHlinear;
 }
@@ -452,7 +452,7 @@
 		*/
 		atomic_set(&data->interrupt_handled, 0);
 		enable_irq(gpio_to_irq(data->pdata->gpio_data));
-		/* If still not occured or another handler has been scheduled */
+		/* If still not occurred or another handler has been scheduled */
 		if (gpio_get_value(data->pdata->gpio_data)
 		    || atomic_read(&data->interrupt_handled))
 			return;
@@ -610,7 +610,7 @@
 	struct sht15_data *data = platform_get_drvdata(pdev);
 
 	/* Make sure any reads from the device are done and
-	 * prevent new ones beginnning */
+	 * prevent new ones from beginning */
 	mutex_lock(&data->read_lock);
 	hwmon_device_unregister(data->hwmon_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &sht15_attr_group);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/tmp102.c linux-libre-2.6.39-gnu/drivers/hwmon/tmp102.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/tmp102.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/tmp102.c	2011-05-19 00:06:34.000000000 -0400
@@ -166,7 +166,7 @@
 
 	if (!i2c_check_functionality(client->adapter,
 				     I2C_FUNC_SMBUS_WORD_DATA)) {
-		dev_err(&client->dev, "adapter doesnt support SMBus word "
+		dev_err(&client->dev, "adapter doesn't support SMBus word "
 			"transactions\n");
 		return -ENODEV;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/twl4030-madc-hwmon.c linux-libre-2.6.39-gnu/drivers/hwmon/twl4030-madc-hwmon.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/twl4030-madc-hwmon.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwmon/twl4030-madc-hwmon.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,156 @@
+/*
+ *
+ * TWL4030 MADC Hwmon driver-This driver monitors the real time
+ * conversion of analog signals like battery temperature,
+ * battery type, battery level etc. User can ask for the conversion on a
+ * particular channel using the sysfs nodes.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * J Keerthy <j-keerthy@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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/module.h>
+#include <linux/kernel.h>
+#include <linux/i2c/twl.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/twl4030-madc.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/stddef.h>
+#include <linux/sysfs.h>
+#include <linux/err.h>
+#include <linux/types.h>
+
+/*
+ * sysfs hook function
+ */
+static ssize_t madc_read(struct device *dev,
+			 struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	struct twl4030_madc_request req;
+	long val;
+
+	req.channels = (1 << attr->index);
+	req.method = TWL4030_MADC_SW2;
+	req.func_cb = NULL;
+	val = twl4030_madc_conversion(&req);
+	if (val < 0)
+		return val;
+
+	return sprintf(buf, "%d\n", req.rbuf[attr->index]);
+}
+
+/* sysfs nodes to read individual channels from user side */
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, madc_read, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, madc_read, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, madc_read, NULL, 2);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, madc_read, NULL, 3);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, madc_read, NULL, 4);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, madc_read, NULL, 5);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, madc_read, NULL, 6);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, madc_read, NULL, 7);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, madc_read, NULL, 8);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, madc_read, NULL, 9);
+static SENSOR_DEVICE_ATTR(curr10_input, S_IRUGO, madc_read, NULL, 10);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, madc_read, NULL, 11);
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, madc_read, NULL, 12);
+static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, madc_read, NULL, 15);
+
+static struct attribute *twl4030_madc_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in9_input.dev_attr.attr,
+	&sensor_dev_attr_curr10_input.dev_attr.attr,
+	&sensor_dev_attr_in11_input.dev_attr.attr,
+	&sensor_dev_attr_in12_input.dev_attr.attr,
+	&sensor_dev_attr_in15_input.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group twl4030_madc_group = {
+	.attrs = twl4030_madc_attributes,
+};
+
+static int __devinit twl4030_madc_hwmon_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct device *hwmon;
+
+	ret = sysfs_create_group(&pdev->dev.kobj, &twl4030_madc_group);
+	if (ret)
+		goto err_sysfs;
+	hwmon = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(hwmon)) {
+		dev_err(&pdev->dev, "hwmon_device_register failed.\n");
+		ret = PTR_ERR(hwmon);
+		goto err_reg;
+	}
+
+	return 0;
+
+err_reg:
+	sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
+err_sysfs:
+
+	return ret;
+}
+
+static int __devexit twl4030_madc_hwmon_remove(struct platform_device *pdev)
+{
+	hwmon_device_unregister(&pdev->dev);
+	sysfs_remove_group(&pdev->dev.kobj, &twl4030_madc_group);
+
+	return 0;
+}
+
+static struct platform_driver twl4030_madc_hwmon_driver = {
+	.probe = twl4030_madc_hwmon_probe,
+	.remove = __exit_p(twl4030_madc_hwmon_remove),
+	.driver = {
+		   .name = "twl4030_madc_hwmon",
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static int __init twl4030_madc_hwmon_init(void)
+{
+	return platform_driver_register(&twl4030_madc_hwmon_driver);
+}
+
+module_init(twl4030_madc_hwmon_init);
+
+static void __exit twl4030_madc_hwmon_exit(void)
+{
+	platform_driver_unregister(&twl4030_madc_hwmon_driver);
+}
+
+module_exit(twl4030_madc_hwmon_exit);
+
+MODULE_DESCRIPTION("TWL4030 ADC Hwmon driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("J Keerthy");
+MODULE_ALIAS("platform:twl4030_madc_hwmon");
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/ultra45_env.c linux-libre-2.6.39-gnu/drivers/hwmon/ultra45_env.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/ultra45_env.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/ultra45_env.c	2011-05-19 00:06:34.000000000 -0400
@@ -234,8 +234,7 @@
 	.attrs = env_attributes,
 };
 
-static int __devinit env_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit env_probe(struct platform_device *op)
 {
 	struct env *p = kzalloc(sizeof(*p), GFP_KERNEL);
 	int err = -ENOMEM;
@@ -299,7 +298,7 @@
 };
 MODULE_DEVICE_TABLE(of, env_match);
 
-static struct of_platform_driver env_driver = {
+static struct platform_driver env_driver = {
 	.driver = {
 		.name = "ultra45_env",
 		.owner = THIS_MODULE,
@@ -311,12 +310,12 @@
 
 static int __init env_init(void)
 {
-	return of_register_platform_driver(&env_driver);
+	return platform_driver_register(&env_driver);
 }
 
 static void __exit env_exit(void)
 {
-	of_unregister_platform_driver(&env_driver);
+	platform_driver_unregister(&env_driver);
 }
 
 module_init(env_init);
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/w83627ehf.c linux-libre-2.6.39-gnu/drivers/hwmon/w83627ehf.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/w83627ehf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/w83627ehf.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,11 +1,12 @@
 /*
     w83627ehf - Driver for the hardware monitoring functionality of
-                the Winbond W83627EHF Super-I/O chip
+		the Winbond W83627EHF Super-I/O chip
     Copyright (C) 2005  Jean Delvare <khali@linux-fr.org>
     Copyright (C) 2006  Yuan Mu (Winbond),
-                        Rudolf Marek <r.marek@assembler.cz>
-                        David Hubbard <david.c.hubbard@gmail.com>
+			Rudolf Marek <r.marek@assembler.cz>
+			David Hubbard <david.c.hubbard@gmail.com>
 			Daniel J Blueman <daniel.blueman@gmail.com>
+    Copyright (C) 2010  Sheng-Yuan Huang (Nuvoton) (PS00)
 
     Shamelessly ripped from the w83627hf driver
     Copyright (C) 2003  Mark Studebaker
@@ -35,11 +36,13 @@
 
     Chip        #vin    #fan    #pwm    #temp  chip IDs       man ID
     w83627ehf   10      5       4       3      0x8850 0x88    0x5ca3
-                                               0x8860 0xa1
+					       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
-    w83667hg-b   9      5       3       3      0xb350 0xc1    0x5ca3
+    w83667hg-b   9      5       3       4      0xb350 0xc1    0x5ca3
+    nct6775f     9      4       3       9      0xb470 0xc1    0x5ca3
+    nct6776f     9      5       3       9      0xC330 0xc1    0x5ca3
 */
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -58,21 +61,28 @@
 #include <linux/io.h>
 #include "lm75.h"
 
-enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b };
+enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg, w83667hg_b, nct6775,
+	nct6776 };
 
 /* used to set data->name = w83627ehf_device_names[data->sio_kind] */
-static const char * w83627ehf_device_names[] = {
+static const char * const w83627ehf_device_names[] = {
 	"w83627ehf",
 	"w83627dhg",
 	"w83627dhg",
 	"w83667hg",
 	"w83667hg",
+	"nct6775",
+	"nct6776",
 };
 
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 MODULE_PARM_DESC(force_id, "Override the detected device ID");
 
+static unsigned short fan_debounce;
+module_param(fan_debounce, ushort, 0);
+MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
+
 #define DRVNAME "w83627ehf"
 
 /*
@@ -80,7 +90,7 @@
  */
 
 #define W83627EHF_LD_HWM	0x0b
-#define W83667HG_LD_VID 	0x0d
+#define W83667HG_LD_VID		0x0d
 
 #define SIO_REG_LDSEL		0x07	/* Logical device select */
 #define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
@@ -94,8 +104,10 @@
 #define SIO_W83627EHG_ID	0x8860
 #define SIO_W83627DHG_ID	0xa020
 #define SIO_W83627DHG_P_ID	0xb070
-#define SIO_W83667HG_ID 	0xa510
+#define SIO_W83667HG_ID		0xa510
 #define SIO_W83667HG_B_ID	0xb350
+#define SIO_NCT6775_ID		0xb470
+#define SIO_NCT6776_ID		0xc330
 #define SIO_ID_MASK		0xFFF0
 
 static inline void
@@ -138,7 +150,7 @@
  * ISA constants
  */
 
-#define IOREGION_ALIGNMENT	~7
+#define IOREGION_ALIGNMENT	(~7)
 #define IOREGION_OFFSET		5
 #define IOREGION_LENGTH		2
 #define ADDR_REG_OFFSET		0
@@ -164,13 +176,10 @@
 #define W83627EHF_REG_IN(nr)		((nr < 7) ? (0x20 + (nr)) : \
 					 (0x550 + (nr) - 7))
 
-#define W83627EHF_REG_TEMP1		0x27
-#define W83627EHF_REG_TEMP1_HYST	0x3a
-#define W83627EHF_REG_TEMP1_OVER	0x39
-static const u16 W83627EHF_REG_TEMP[] = { 0x150, 0x250 };
-static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x153, 0x253 };
-static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x155, 0x255 };
-static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0x152, 0x252 };
+static const u16 W83627EHF_REG_TEMP[] = { 0x27, 0x150, 0x250, 0x7e };
+static const u16 W83627EHF_REG_TEMP_HYST[] = { 0x3a, 0x153, 0x253, 0 };
+static const u16 W83627EHF_REG_TEMP_OVER[] = { 0x39, 0x155, 0x255, 0 };
+static const u16 W83627EHF_REG_TEMP_CONFIG[] = { 0, 0x152, 0x252, 0 };
 
 /* Fan clock dividers are spread over the following five registers */
 #define W83627EHF_REG_FANDIV1		0x47
@@ -179,6 +188,11 @@
 #define W83627EHF_REG_DIODE		0x59
 #define W83627EHF_REG_SMI_OVT		0x4C
 
+/* NCT6775F has its own fan divider registers */
+#define NCT6775_REG_FANDIV1		0x506
+#define NCT6775_REG_FANDIV2		0x507
+#define NCT6775_REG_FAN_DEBOUNCE	0xf0
+
 #define W83627EHF_REG_ALARM1		0x459
 #define W83627EHF_REG_ALARM2		0x45A
 #define W83627EHF_REG_ALARM3		0x45B
@@ -199,22 +213,123 @@
 static const u8 W83627EHF_PWM_ENABLE_SHIFT[] = { 2, 4, 1, 4 };
 
 /* FAN Duty Cycle, be used to control */
-static const u8 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
-static const u8 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
+static const u16 W83627EHF_REG_PWM[] = { 0x01, 0x03, 0x11, 0x61 };
+static const u16 W83627EHF_REG_TARGET[] = { 0x05, 0x06, 0x13, 0x63 };
 static const u8 W83627EHF_REG_TOLERANCE[] = { 0x07, 0x07, 0x14, 0x62 };
 
 /* Advanced Fan control, some values are common for all fans */
-static const u8 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
-static const u8 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
-static const u8 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
+static const u16 W83627EHF_REG_FAN_START_OUTPUT[] = { 0x0a, 0x0b, 0x16, 0x65 };
+static const u16 W83627EHF_REG_FAN_STOP_OUTPUT[] = { 0x08, 0x09, 0x15, 0x64 };
+static const u16 W83627EHF_REG_FAN_STOP_TIME[] = { 0x0c, 0x0d, 0x17, 0x66 };
 
-static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[]
+static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_COMMON[]
 						= { 0xff, 0x67, 0xff, 0x69 };
-static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
+static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_COMMON[]
 						= { 0xff, 0x68, 0xff, 0x6a };
 
-static const u8 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
-static const u8 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[] = { 0x68, 0x6a, 0x6c };
+static const u16 W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B[] = { 0x67, 0x69, 0x6b };
+static const u16 W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B[]
+						= { 0x68, 0x6a, 0x6c };
+
+static const u16 NCT6775_REG_TARGET[] = { 0x101, 0x201, 0x301 };
+static const u16 NCT6775_REG_FAN_MODE[] = { 0x102, 0x202, 0x302 };
+static const u16 NCT6775_REG_FAN_STOP_OUTPUT[] = { 0x105, 0x205, 0x305 };
+static const u16 NCT6775_REG_FAN_START_OUTPUT[] = { 0x106, 0x206, 0x306 };
+static const u16 NCT6775_REG_FAN_STOP_TIME[] = { 0x107, 0x207, 0x307 };
+static const u16 NCT6775_REG_PWM[] = { 0x109, 0x209, 0x309 };
+static const u16 NCT6775_REG_FAN_MAX_OUTPUT[] = { 0x10a, 0x20a, 0x30a };
+static const u16 NCT6775_REG_FAN_STEP_OUTPUT[] = { 0x10b, 0x20b, 0x30b };
+static const u16 NCT6775_REG_FAN[] = { 0x630, 0x632, 0x634, 0x636, 0x638 };
+static const u16 NCT6776_REG_FAN_MIN[] = { 0x63a, 0x63c, 0x63e, 0x640, 0x642};
+
+static const u16 NCT6775_REG_TEMP[]
+	= { 0x27, 0x150, 0x250, 0x73, 0x75, 0x77, 0x62b, 0x62c, 0x62d };
+static const u16 NCT6775_REG_TEMP_CONFIG[]
+	= { 0, 0x152, 0x252, 0, 0, 0, 0x628, 0x629, 0x62A };
+static const u16 NCT6775_REG_TEMP_HYST[]
+	= { 0x3a, 0x153, 0x253, 0, 0, 0, 0x673, 0x678, 0x67D };
+static const u16 NCT6775_REG_TEMP_OVER[]
+	= { 0x39, 0x155, 0x255, 0, 0, 0, 0x672, 0x677, 0x67C };
+static const u16 NCT6775_REG_TEMP_SOURCE[]
+	= { 0x621, 0x622, 0x623, 0x100, 0x200, 0x300, 0x624, 0x625, 0x626 };
+
+static const char *const w83667hg_b_temp_label[] = {
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"AMDTSI",
+	"PECI Agent 1",
+	"PECI Agent 2",
+	"PECI Agent 3",
+	"PECI Agent 4"
+};
+
+static const char *const nct6775_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"AMD SB-TSI",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PECI Agent 2",
+	"PECI Agent 3",
+	"PECI Agent 4",
+	"PECI Agent 5",
+	"PECI Agent 6",
+	"PECI Agent 7",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP"
+};
+
+static const char *const nct6776_temp_label[] = {
+	"",
+	"SYSTIN",
+	"CPUTIN",
+	"AUXTIN",
+	"SMBUSMASTER 0",
+	"SMBUSMASTER 1",
+	"SMBUSMASTER 2",
+	"SMBUSMASTER 3",
+	"SMBUSMASTER 4",
+	"SMBUSMASTER 5",
+	"SMBUSMASTER 6",
+	"SMBUSMASTER 7",
+	"PECI Agent 0",
+	"PECI Agent 1",
+	"PCH_CHIP_CPU_MAX_TEMP",
+	"PCH_CHIP_TEMP",
+	"PCH_CPU_TEMP",
+	"PCH_MCH_TEMP",
+	"PCH_DIM0_TEMP",
+	"PCH_DIM1_TEMP",
+	"PCH_DIM2_TEMP",
+	"PCH_DIM3_TEMP",
+	"BYTE_TEMP"
+};
+
+#define NUM_REG_TEMP	ARRAY_SIZE(NCT6775_REG_TEMP)
+
+static inline int is_word_sized(u16 reg)
+{
+	return ((((reg & 0xff00) == 0x100
+	      || (reg & 0xff00) == 0x200)
+	     && ((reg & 0x00ff) == 0x50
+	      || (reg & 0x00ff) == 0x53
+	      || (reg & 0x00ff) == 0x55))
+	     || (reg & 0xfff0) == 0x630
+	     || reg == 0x640 || reg == 0x642
+	     || ((reg & 0xfff0) == 0x650
+		 && (reg & 0x000f) >= 0x06)
+	     || reg == 0x73 || reg == 0x75 || reg == 0x77
+		);
+}
 
 /*
  * Conversions
@@ -232,12 +347,36 @@
 						(msec + 200) / 400), 1, 255);
 }
 
-static inline unsigned int
-fan_from_reg(u8 reg, unsigned int div)
+static unsigned int fan_from_reg8(u16 reg, unsigned int divreg)
 {
 	if (reg == 0 || reg == 255)
 		return 0;
-	return 1350000U / (reg * div);
+	return 1350000U / (reg << divreg);
+}
+
+static unsigned int fan_from_reg13(u16 reg, unsigned int divreg)
+{
+	if ((reg & 0xff1f) == 0xff1f)
+		return 0;
+
+	reg = (reg & 0x1f) | ((reg & 0xff00) >> 3);
+
+	if (reg == 0)
+		return 0;
+
+	return 1350000U / reg;
+}
+
+static unsigned int fan_from_reg16(u16 reg, unsigned int divreg)
+{
+	if (reg == 0 || reg == 0xffff)
+		return 0;
+
+	/*
+	 * Even though the registers are 16 bit wide, the fan divisor
+	 * still applies.
+	 */
+	return 1350000U / (reg << divreg);
 }
 
 static inline unsigned int
@@ -247,21 +386,19 @@
 }
 
 static inline int
-temp1_from_reg(s8 reg)
+temp_from_reg(u16 reg, s16 regval)
 {
-	return reg * 1000;
+	if (is_word_sized(reg))
+		return LM75_TEMP_FROM_REG(regval);
+	return regval * 1000;
 }
 
-static inline s8
-temp1_to_reg(long temp, int min, int max)
+static inline u16
+temp_to_reg(u16 reg, long temp)
 {
-	if (temp <= min)
-		return min / 1000;
-	if (temp >= max)
-		return max / 1000;
-	if (temp < 0)
-		return (temp - 500) / 1000;
-	return (temp + 500) / 1000;
+	if (is_word_sized(reg))
+		return LM75_TEMP_TO_REG(temp);
+	return DIV_ROUND_CLOSEST(SENSORS_LIMIT(temp, -127000, 128000), 1000);
 }
 
 /* Some of analog inputs have internal scaling (2x), 8mV is ADC LSB */
@@ -275,7 +412,8 @@
 
 static inline u8 in_to_reg(u32 val, u8 nr)
 {
-	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0, 255);
+	return SENSORS_LIMIT(((val + (scale_in[nr] / 2)) / scale_in[nr]), 0,
+			     255);
 }
 
 /*
@@ -289,38 +427,57 @@
 	struct device *hwmon_dev;
 	struct mutex lock;
 
-	const u8 *REG_FAN_START_OUTPUT;
-	const u8 *REG_FAN_STOP_OUTPUT;
-	const u8 *REG_FAN_MAX_OUTPUT;
-	const u8 *REG_FAN_STEP_OUTPUT;
+	u16 reg_temp[NUM_REG_TEMP];
+	u16 reg_temp_over[NUM_REG_TEMP];
+	u16 reg_temp_hyst[NUM_REG_TEMP];
+	u16 reg_temp_config[NUM_REG_TEMP];
+	u8 temp_src[NUM_REG_TEMP];
+	const char * const *temp_label;
+
+	const u16 *REG_PWM;
+	const u16 *REG_TARGET;
+	const u16 *REG_FAN;
+	const u16 *REG_FAN_MIN;
+	const u16 *REG_FAN_START_OUTPUT;
+	const u16 *REG_FAN_STOP_OUTPUT;
+	const u16 *REG_FAN_STOP_TIME;
+	const u16 *REG_FAN_MAX_OUTPUT;
+	const u16 *REG_FAN_STEP_OUTPUT;
+
+	unsigned int (*fan_from_reg)(u16 reg, unsigned int divreg);
+	unsigned int (*fan_from_reg_min)(u16 reg, unsigned int divreg);
 
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
 	/* Register values */
+	u8 bank;		/* current register bank */
 	u8 in_num;		/* number of in inputs we have */
 	u8 in[10];		/* Register value */
 	u8 in_max[10];		/* Register value */
 	u8 in_min[10];		/* Register value */
-	u8 fan[5];
-	u8 fan_min[5];
+	unsigned int rpm[5];
+	u16 fan_min[5];
 	u8 fan_div[5];
 	u8 has_fan;		/* some fan inputs can be disabled */
+	u8 has_fan_min;		/* some fans don't have min register */
+	bool has_fan_div;
 	u8 temp_type[3];
-	s8 temp1;
-	s8 temp1_max;
-	s8 temp1_max_hyst;
-	s16 temp[2];
-	s16 temp_max[2];
-	s16 temp_max_hyst[2];
+	s16 temp[9];
+	s16 temp_max[9];
+	s16 temp_max_hyst[9];
 	u32 alarms;
 
 	u8 pwm_mode[4]; /* 0->DC variable voltage, 1->PWM variable duty cycle */
 	u8 pwm_enable[4]; /* 1->manual
 			     2->thermal cruise mode (also called SmartFan I)
 			     3->fan speed cruise mode
-			     4->variable thermal cruise (also called SmartFan III) */
+			     4->variable thermal cruise (also called
+				SmartFan III)
+			     5->enhanced variable thermal cruise (also called
+				SmartFan IV) */
+	u8 pwm_enable_orig[4];	/* original value of pwm_enable */
 	u8 pwm_num;		/* number of pwm */
 	u8 pwm[4];
 	u8 target_temp[4];
@@ -335,7 +492,7 @@
 	u8 vid;
 	u8 vrm;
 
-	u8 temp3_disable;
+	u16 have_temp;
 	u8 in6_skip;
 };
 
@@ -344,30 +501,19 @@
 	enum kinds kind;
 };
 
-static inline int is_word_sized(u16 reg)
-{
-	return (((reg & 0xff00) == 0x100
-	      || (reg & 0xff00) == 0x200)
-	     && ((reg & 0x00ff) == 0x50
-	      || (reg & 0x00ff) == 0x53
-	      || (reg & 0x00ff) == 0x55));
-}
-
-/* Registers 0x50-0x5f are banked */
+/*
+ * On older chips, only registers 0x50-0x5f are banked.
+ * On more recent chips, all registers are banked.
+ * Assume that is the case and set the bank number for each access.
+ * Cache the bank number so it only needs to be set if it changes.
+ */
 static inline void w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg)
 {
-	if ((reg & 0x00f0) == 0x50) {
-		outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
-		outb_p(reg >> 8, data->addr + DATA_REG_OFFSET);
-	}
-}
-
-/* Not strictly necessary, but play it safe for now */
-static inline void w83627ehf_reset_bank(struct w83627ehf_data *data, u16 reg)
-{
-	if (reg & 0xff00) {
+	u8 bank = reg >> 8;
+	if (data->bank != bank) {
 		outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
-		outb_p(0, data->addr + DATA_REG_OFFSET);
+		outb_p(bank, data->addr + DATA_REG_OFFSET);
+		data->bank = bank;
 	}
 }
 
@@ -385,14 +531,13 @@
 		       data->addr + ADDR_REG_OFFSET);
 		res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
 	}
-	w83627ehf_reset_bank(data, reg);
 
 	mutex_unlock(&data->lock);
-
 	return res;
 }
 
-static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg, u16 value)
+static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg,
+				 u16 value)
 {
 	int word_sized = is_word_sized(reg);
 
@@ -406,13 +551,40 @@
 		       data->addr + ADDR_REG_OFFSET);
 	}
 	outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
-	w83627ehf_reset_bank(data, reg);
 
 	mutex_unlock(&data->lock);
 	return 0;
 }
 
 /* This function assumes that the caller holds data->update_lock */
+static void nct6775_write_fan_div(struct w83627ehf_data *data, int nr)
+{
+	u8 reg;
+
+	switch (nr) {
+	case 0:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x70)
+		    | (data->fan_div[0] & 0x7);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg);
+		break;
+	case 1:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV1) & 0x7)
+		    | ((data->fan_div[1] << 4) & 0x70);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV1, reg);
+	case 2:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x70)
+		    | (data->fan_div[2] & 0x7);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	case 3:
+		reg = (w83627ehf_read_value(data, NCT6775_REG_FANDIV2) & 0x7)
+		    | ((data->fan_div[3] << 4) & 0x70);
+		w83627ehf_write_value(data, NCT6775_REG_FANDIV2, reg);
+		break;
+	}
+}
+
+/* This function assumes that the caller holds data->update_lock */
 static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr)
 {
 	u8 reg;
@@ -463,6 +635,32 @@
 	}
 }
 
+static void w83627ehf_write_fan_div_common(struct device *dev,
+					   struct w83627ehf_data *data, int nr)
+{
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	if (sio_data->kind == nct6776)
+		; /* no dividers, do nothing */
+	else if (sio_data->kind == nct6775)
+		nct6775_write_fan_div(data, nr);
+	else
+		w83627ehf_write_fan_div(data, nr);
+}
+
+static void nct6775_update_fan_div(struct w83627ehf_data *data)
+{
+	u8 i;
+
+	i = w83627ehf_read_value(data, NCT6775_REG_FANDIV1);
+	data->fan_div[0] = i & 0x7;
+	data->fan_div[1] = (i & 0x70) >> 4;
+	i = w83627ehf_read_value(data, NCT6775_REG_FANDIV2);
+	data->fan_div[2] = i & 0x7;
+	if (data->has_fan & (1<<3))
+		data->fan_div[3] = (i & 0x70) >> 4;
+}
+
 static void w83627ehf_update_fan_div(struct w83627ehf_data *data)
 {
 	int i;
@@ -488,10 +686,79 @@
 	}
 }
 
+static void w83627ehf_update_fan_div_common(struct device *dev,
+					    struct w83627ehf_data *data)
+{
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	if (sio_data->kind == nct6776)
+		; /* no dividers, do nothing */
+	else if (sio_data->kind == nct6775)
+		nct6775_update_fan_div(data);
+	else
+		w83627ehf_update_fan_div(data);
+}
+
+static void nct6775_update_pwm(struct w83627ehf_data *data)
+{
+	int i;
+	int pwmcfg, fanmodecfg;
+
+	for (i = 0; i < data->pwm_num; i++) {
+		pwmcfg = w83627ehf_read_value(data,
+					      W83627EHF_REG_PWM_ENABLE[i]);
+		fanmodecfg = w83627ehf_read_value(data,
+						  NCT6775_REG_FAN_MODE[i]);
+		data->pwm_mode[i] =
+		  ((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1;
+		data->pwm_enable[i] = ((fanmodecfg >> 4) & 7) + 1;
+		data->tolerance[i] = fanmodecfg & 0x0f;
+		data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]);
+	}
+}
+
+static void w83627ehf_update_pwm(struct w83627ehf_data *data)
+{
+	int i;
+	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
+
+	for (i = 0; i < data->pwm_num; i++) {
+		if (!(data->has_fan & (1 << i)))
+			continue;
+
+		/* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
+		if (i != 1) {
+			pwmcfg = w83627ehf_read_value(data,
+					W83627EHF_REG_PWM_ENABLE[i]);
+			tolerance = w83627ehf_read_value(data,
+					W83627EHF_REG_TOLERANCE[i]);
+		}
+		data->pwm_mode[i] =
+			((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1) ? 0 : 1;
+		data->pwm_enable[i] = ((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
+				       & 3) + 1;
+		data->pwm[i] = w83627ehf_read_value(data, data->REG_PWM[i]);
+
+		data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0)) & 0x0f;
+	}
+}
+
+static void w83627ehf_update_pwm_common(struct device *dev,
+					struct w83627ehf_data *data)
+{
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776)
+		nct6775_update_pwm(data);
+	else
+		w83627ehf_update_pwm(data);
+}
+
 static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
-	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
+
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -499,7 +766,7 @@
 	if (time_after(jiffies, data->last_updated + HZ + HZ/2)
 	 || !data->valid) {
 		/* Fan clock dividers */
-		w83627ehf_update_fan_div(data);
+		w83627ehf_update_fan_div_common(dev, data);
 
 		/* Measured voltages and limits */
 		for (i = 0; i < data->in_num; i++) {
@@ -513,92 +780,90 @@
 
 		/* Measured fan speeds and limits */
 		for (i = 0; i < 5; i++) {
+			u16 reg;
+
 			if (!(data->has_fan & (1 << i)))
 				continue;
 
-			data->fan[i] = w83627ehf_read_value(data,
-				       W83627EHF_REG_FAN[i]);
-			data->fan_min[i] = w83627ehf_read_value(data,
-					   W83627EHF_REG_FAN_MIN[i]);
+			reg = w83627ehf_read_value(data, data->REG_FAN[i]);
+			data->rpm[i] = data->fan_from_reg(reg,
+							  data->fan_div[i]);
+
+			if (data->has_fan_min & (1 << i))
+				data->fan_min[i] = w83627ehf_read_value(data,
+					   data->REG_FAN_MIN[i]);
 
 			/* If we failed to measure the fan speed and clock
 			   divider can be increased, let's try that for next
 			   time */
-			if (data->fan[i] == 0xff
-			 && data->fan_div[i] < 0x07) {
-			 	dev_dbg(dev, "Increasing fan%d "
+			if (data->has_fan_div
+			    && (reg >= 0xff || (sio_data->kind == nct6775
+						&& reg == 0x00))
+			    && data->fan_div[i] < 0x07) {
+				dev_dbg(dev, "Increasing fan%d "
 					"clock divider from %u to %u\n",
 					i + 1, div_from_reg(data->fan_div[i]),
 					div_from_reg(data->fan_div[i] + 1));
 				data->fan_div[i]++;
-				w83627ehf_write_fan_div(data, i);
+				w83627ehf_write_fan_div_common(dev, data, i);
 				/* Preserve min limit if possible */
-				if (data->fan_min[i] >= 2
+				if ((data->has_fan_min & (1 << i))
+				 && data->fan_min[i] >= 2
 				 && data->fan_min[i] != 255)
 					w83627ehf_write_value(data,
-						W83627EHF_REG_FAN_MIN[i],
+						data->REG_FAN_MIN[i],
 						(data->fan_min[i] /= 2));
 			}
 		}
 
+		w83627ehf_update_pwm_common(dev, data);
+
 		for (i = 0; i < data->pwm_num; i++) {
 			if (!(data->has_fan & (1 << i)))
 				continue;
 
-			/* pwmcfg, tolerance mapped for i=0, i=1 to same reg */
-			if (i != 1) {
-				pwmcfg = w83627ehf_read_value(data,
-						W83627EHF_REG_PWM_ENABLE[i]);
-				tolerance = w83627ehf_read_value(data,
-						W83627EHF_REG_TOLERANCE[i]);
-			}
-			data->pwm_mode[i] =
-				((pwmcfg >> W83627EHF_PWM_MODE_SHIFT[i]) & 1)
-				? 0 : 1;
-			data->pwm_enable[i] =
-					((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
-						& 3) + 1;
-			data->pwm[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_PWM[i]);
-			data->fan_start_output[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_FAN_START_OUTPUT[i]);
-			data->fan_stop_output[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_FAN_STOP_OUTPUT[i]);
-			data->fan_stop_time[i] = w83627ehf_read_value(data,
-						W83627EHF_REG_FAN_STOP_TIME[i]);
+			data->fan_start_output[i] =
+			  w83627ehf_read_value(data,
+					       data->REG_FAN_START_OUTPUT[i]);
+			data->fan_stop_output[i] =
+			  w83627ehf_read_value(data,
+					       data->REG_FAN_STOP_OUTPUT[i]);
+			data->fan_stop_time[i] =
+			  w83627ehf_read_value(data,
+					       data->REG_FAN_STOP_TIME[i]);
 
-			if (data->REG_FAN_MAX_OUTPUT[i] != 0xff)
+			if (data->REG_FAN_MAX_OUTPUT &&
+			    data->REG_FAN_MAX_OUTPUT[i] != 0xff)
 				data->fan_max_output[i] =
 				  w83627ehf_read_value(data,
-					       data->REG_FAN_MAX_OUTPUT[i]);
+						data->REG_FAN_MAX_OUTPUT[i]);
 
-			if (data->REG_FAN_STEP_OUTPUT[i] != 0xff)
+			if (data->REG_FAN_STEP_OUTPUT &&
+			    data->REG_FAN_STEP_OUTPUT[i] != 0xff)
 				data->fan_step_output[i] =
 				  w83627ehf_read_value(data,
-					       data->REG_FAN_STEP_OUTPUT[i]);
+						data->REG_FAN_STEP_OUTPUT[i]);
 
 			data->target_temp[i] =
 				w83627ehf_read_value(data,
-					W83627EHF_REG_TARGET[i]) &
+					data->REG_TARGET[i]) &
 					(data->pwm_mode[i] == 1 ? 0x7f : 0xff);
-			data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
-									& 0x0f;
 		}
 
 		/* Measured temperatures and limits */
-		data->temp1 = w83627ehf_read_value(data,
-			      W83627EHF_REG_TEMP1);
-		data->temp1_max = w83627ehf_read_value(data,
-				  W83627EHF_REG_TEMP1_OVER);
-		data->temp1_max_hyst = w83627ehf_read_value(data,
-				       W83627EHF_REG_TEMP1_HYST);
-		for (i = 0; i < 2; i++) {
+		for (i = 0; i < NUM_REG_TEMP; i++) {
+			if (!(data->have_temp & (1 << i)))
+				continue;
 			data->temp[i] = w83627ehf_read_value(data,
-					W83627EHF_REG_TEMP[i]);
-			data->temp_max[i] = w83627ehf_read_value(data,
-					    W83627EHF_REG_TEMP_OVER[i]);
-			data->temp_max_hyst[i] = w83627ehf_read_value(data,
-						 W83627EHF_REG_TEMP_HYST[i]);
+						data->reg_temp[i]);
+			if (data->reg_temp_over[i])
+				data->temp_max[i]
+				  = w83627ehf_read_value(data,
+						data->reg_temp_over[i]);
+			if (data->reg_temp_hyst[i])
+				data->temp_max_hyst[i]
+				  = w83627ehf_read_value(data,
+						data->reg_temp_hyst[i]);
 		}
 
 		data->alarms = w83627ehf_read_value(data,
@@ -625,7 +890,8 @@
 	   char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%ld\n", in_from_reg(data->reg[nr], nr)); \
 }
@@ -635,14 +901,18 @@
 
 #define store_in_reg(REG, reg) \
 static ssize_t \
-store_in_##reg (struct device *dev, struct device_attribute *attr, \
-			const char *buf, size_t count) \
+store_in_##reg(struct device *dev, struct device_attribute *attr, \
+	       const char *buf, size_t count) \
 { \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	u32 val = simple_strtoul(buf, NULL, 10); \
- \
+	unsigned long val; \
+	int err; \
+	err = strict_strtoul(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = in_to_reg(val, nr); \
 	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
@@ -654,7 +924,8 @@
 store_in_reg(MIN, min)
 store_in_reg(MAX, max)
 
-static ssize_t show_alarm(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
+			  char *buf)
 {
 	struct w83627ehf_data *data = w83627ehf_update_device(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
@@ -689,45 +960,50 @@
 };
 
 static struct sensor_device_attribute sda_in_min[] = {
-       SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
-       SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
-       SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
-       SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
-       SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
-       SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
-       SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
-       SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
-       SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
-       SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
+	SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 0),
+	SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 1),
+	SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 2),
+	SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 3),
+	SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 4),
+	SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 5),
+	SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 6),
+	SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 7),
+	SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 8),
+	SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, store_in_min, 9),
 };
 
 static struct sensor_device_attribute sda_in_max[] = {
-       SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
-       SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
-       SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
-       SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
-       SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
-       SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
-       SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
-       SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
-       SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
-       SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
+	SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 0),
+	SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 1),
+	SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 2),
+	SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 3),
+	SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 4),
+	SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 5),
+	SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 6),
+	SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 7),
+	SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 8),
+	SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, store_in_max, 9),
 };
 
-#define show_fan_reg(reg) \
-static ssize_t \
-show_##reg(struct device *dev, struct device_attribute *attr, \
-	   char *buf) \
-{ \
-	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
-	int nr = sensor_attr->index; \
-	return sprintf(buf, "%d\n", \
-		       fan_from_reg(data->reg[nr], \
-				    div_from_reg(data->fan_div[nr]))); \
+static ssize_t
+show_fan(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%d\n", data->rpm[nr]);
+}
+
+static ssize_t
+show_fan_min(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%d\n",
+		       data->fan_from_reg_min(data->fan_min[nr],
+					      data->fan_div[nr]));
 }
-show_fan_reg(fan);
-show_fan_reg(fan_min);
 
 static ssize_t
 show_fan_div(struct device *dev, struct device_attribute *attr,
@@ -746,11 +1022,32 @@
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	unsigned int val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
 	unsigned int reg;
 	u8 new_div;
 
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
 	mutex_lock(&data->update_lock);
+	if (!data->has_fan_div) {
+		/*
+		 * Only NCT6776F for now, so we know that this is a 13 bit
+		 * register
+		 */
+		if (!val) {
+			val = 0xff1f;
+		} else {
+			if (val > 1350000U)
+				val = 135000U;
+			val = 1350000U / val;
+			val = (val & 0x1f) | ((val << 3) & 0xff00);
+		}
+		data->fan_min[nr] = val;
+		goto done;	/* Leave fan divider alone */
+	}
 	if (!val) {
 		/* No min limit, alarm disabled */
 		data->fan_min[nr] = 255;
@@ -761,15 +1058,17 @@
 		   even with the highest divider (128) */
 		data->fan_min[nr] = 254;
 		new_div = 7; /* 128 == (1 << 7) */
-		dev_warn(dev, "fan%u low limit %u below minimum %u, set to "
-			 "minimum\n", nr + 1, val, fan_from_reg(254, 128));
+		dev_warn(dev, "fan%u low limit %lu below minimum %u, set to "
+			 "minimum\n", nr + 1, val,
+			 data->fan_from_reg_min(254, 7));
 	} else if (!reg) {
 		/* Speed above this value cannot possibly be represented,
 		   even with the lowest divider (1) */
 		data->fan_min[nr] = 1;
 		new_div = 0; /* 1 == (1 << 0) */
-		dev_warn(dev, "fan%u low limit %u above maximum %u, set to "
-			 "maximum\n", nr + 1, val, fan_from_reg(1, 1));
+		dev_warn(dev, "fan%u low limit %lu above maximum %u, set to "
+			 "maximum\n", nr + 1, val,
+			 data->fan_from_reg_min(1, 0));
 	} else {
 		/* Automatically pick the best divider, i.e. the one such
 		   that the min limit will correspond to a register value
@@ -785,25 +1084,16 @@
 	/* Write both the fan clock divider (if it changed) and the new
 	   fan min (unconditionally) */
 	if (new_div != data->fan_div[nr]) {
-		/* Preserve the fan speed reading */
-		if (data->fan[nr] != 0xff) {
-			if (new_div > data->fan_div[nr])
-				data->fan[nr] >>= new_div - data->fan_div[nr];
-			else if (data->fan[nr] & 0x80)
-				data->fan[nr] = 0xff;
-			else
-				data->fan[nr] <<= data->fan_div[nr] - new_div;
-		}
-
 		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
 			nr + 1, div_from_reg(data->fan_div[nr]),
 			div_from_reg(new_div));
 		data->fan_div[nr] = new_div;
-		w83627ehf_write_fan_div(data, nr);
+		w83627ehf_write_fan_div_common(dev, data, nr);
 		/* Give the chip time to sample a new speed value */
 		data->last_updated = jiffies;
 	}
-	w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[nr],
+done:
+	w83627ehf_write_value(data, data->REG_FAN_MIN[nr],
 			      data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 
@@ -847,70 +1137,54 @@
 	SENSOR_ATTR(fan5_div, S_IRUGO, show_fan_div, NULL, 4),
 };
 
-#define show_temp1_reg(reg) \
-static ssize_t \
-show_##reg(struct device *dev, struct device_attribute *attr, \
-	   char *buf) \
-{ \
-	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	return sprintf(buf, "%d\n", temp1_from_reg(data->reg)); \
-}
-show_temp1_reg(temp1);
-show_temp1_reg(temp1_max);
-show_temp1_reg(temp1_max_hyst);
-
-#define store_temp1_reg(REG, reg) \
-static ssize_t \
-store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
-		  const char *buf, size_t count) \
-{ \
-	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	long val = simple_strtol(buf, NULL, 10); \
- \
-	mutex_lock(&data->update_lock); \
-	data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
-	w83627ehf_write_value(data, W83627EHF_REG_TEMP1_##REG, \
-			      data->temp1_##reg); \
-	mutex_unlock(&data->update_lock); \
-	return count; \
+static ssize_t
+show_temp_label(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%s\n", data->temp_label[data->temp_src[nr]]);
 }
-store_temp1_reg(OVER, max);
-store_temp1_reg(HYST, max_hyst);
 
-#define show_temp_reg(reg) \
+#define show_temp_reg(addr, reg) \
 static ssize_t \
 show_##reg(struct device *dev, struct device_attribute *attr, \
 	   char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", \
-		       LM75_TEMP_FROM_REG(data->reg[nr])); \
+		       temp_from_reg(data->addr[nr], data->reg[nr])); \
 }
-show_temp_reg(temp);
-show_temp_reg(temp_max);
-show_temp_reg(temp_max_hyst);
+show_temp_reg(reg_temp, temp);
+show_temp_reg(reg_temp_over, temp_max);
+show_temp_reg(reg_temp_hyst, temp_max_hyst);
 
-#define store_temp_reg(REG, reg) \
+#define store_temp_reg(addr, reg) \
 static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 	    const char *buf, size_t count) \
 { \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	long val = simple_strtol(buf, NULL, 10); \
- \
+	int err; \
+	long val; \
+	err = strict_strtol(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
 	mutex_lock(&data->update_lock); \
-	data->reg[nr] = LM75_TEMP_TO_REG(val); \
-	w83627ehf_write_value(data, W83627EHF_REG_TEMP_##REG[nr], \
+	data->reg[nr] = temp_to_reg(data->addr[nr], val); \
+	w83627ehf_write_value(data, data->addr[nr], \
 			      data->reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
-store_temp_reg(OVER, temp_max);
-store_temp_reg(HYST, temp_max_hyst);
+store_temp_reg(reg_temp_over, temp_max);
+store_temp_reg(reg_temp_hyst, temp_max_hyst);
 
 static ssize_t
 show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
@@ -922,27 +1196,69 @@
 }
 
 static struct sensor_device_attribute sda_temp_input[] = {
-	SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
-	SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
-	SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 1),
+	SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
+	SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
+	SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
+	SENSOR_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3),
+	SENSOR_ATTR(temp5_input, S_IRUGO, show_temp, NULL, 4),
+	SENSOR_ATTR(temp6_input, S_IRUGO, show_temp, NULL, 5),
+	SENSOR_ATTR(temp7_input, S_IRUGO, show_temp, NULL, 6),
+	SENSOR_ATTR(temp8_input, S_IRUGO, show_temp, NULL, 7),
+	SENSOR_ATTR(temp9_input, S_IRUGO, show_temp, NULL, 8),
+};
+
+static struct sensor_device_attribute sda_temp_label[] = {
+	SENSOR_ATTR(temp1_label, S_IRUGO, show_temp_label, NULL, 0),
+	SENSOR_ATTR(temp2_label, S_IRUGO, show_temp_label, NULL, 1),
+	SENSOR_ATTR(temp3_label, S_IRUGO, show_temp_label, NULL, 2),
+	SENSOR_ATTR(temp4_label, S_IRUGO, show_temp_label, NULL, 3),
+	SENSOR_ATTR(temp5_label, S_IRUGO, show_temp_label, NULL, 4),
+	SENSOR_ATTR(temp6_label, S_IRUGO, show_temp_label, NULL, 5),
+	SENSOR_ATTR(temp7_label, S_IRUGO, show_temp_label, NULL, 6),
+	SENSOR_ATTR(temp8_label, S_IRUGO, show_temp_label, NULL, 7),
+	SENSOR_ATTR(temp9_label, S_IRUGO, show_temp_label, NULL, 8),
 };
 
 static struct sensor_device_attribute sda_temp_max[] = {
-	SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp1_max,
-		    store_temp1_max, 0),
-	SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
+	SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR, show_temp_max,
 		    store_temp_max, 0),
-	SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
+	SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR, show_temp_max,
 		    store_temp_max, 1),
+	SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 2),
+	SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 3),
+	SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 4),
+	SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 5),
+	SENSOR_ATTR(temp7_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 6),
+	SENSOR_ATTR(temp8_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 7),
+	SENSOR_ATTR(temp9_max, S_IRUGO | S_IWUSR, show_temp_max,
+		    store_temp_max, 8),
 };
 
 static struct sensor_device_attribute sda_temp_max_hyst[] = {
-	SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp1_max_hyst,
-		    store_temp1_max_hyst, 0),
-	SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+	SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
 		    store_temp_max_hyst, 0),
-	SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+	SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
 		    store_temp_max_hyst, 1),
+	SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 2),
+	SENSOR_ATTR(temp4_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 3),
+	SENSOR_ATTR(temp5_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 4),
+	SENSOR_ATTR(temp6_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 5),
+	SENSOR_ATTR(temp7_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 6),
+	SENSOR_ATTR(temp8_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 7),
+	SENSOR_ATTR(temp9_max_hyst, S_IRUGO | S_IWUSR, show_temp_max_hyst,
+		    store_temp_max_hyst, 8),
 };
 
 static struct sensor_device_attribute sda_temp_alarm[] = {
@@ -958,11 +1274,12 @@
 };
 
 #define show_pwm_reg(reg) \
-static ssize_t show_##reg (struct device *dev, struct device_attribute *attr, \
-				char *buf) \
+static ssize_t show_##reg(struct device *dev, struct device_attribute *attr, \
+			  char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", data->reg[nr]); \
 }
@@ -978,9 +1295,14 @@
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
 	u16 reg;
 
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
 	if (val > 1)
 		return -EINVAL;
 	mutex_lock(&data->update_lock);
@@ -1001,11 +1323,18 @@
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
+	unsigned long val;
+	int err;
+
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(val, 0, 255);
 
 	mutex_lock(&data->update_lock);
 	data->pwm[nr] = val;
-	w83627ehf_write_value(data, W83627EHF_REG_PWM[nr], val);
+	w83627ehf_write_value(data, data->REG_PWM[nr], val);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1015,19 +1344,38 @@
 			const char *buf, size_t count)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u32 val = simple_strtoul(buf, NULL, 10);
+	unsigned long val;
+	int err;
 	u16 reg;
 
-	if (!val || (val > 4))
+	err = strict_strtoul(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	if (!val || (val > 4 && val != data->pwm_enable_orig[nr]))
 		return -EINVAL;
+	/* SmartFan III mode is not supported on NCT6776F */
+	if (sio_data->kind == nct6776 && val == 4)
+		return -EINVAL;
+
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
 	data->pwm_enable[nr] = val;
-	reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
-	reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
-	w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		reg = w83627ehf_read_value(data,
+					   NCT6775_REG_FAN_MODE[nr]);
+		reg &= 0x0f;
+		reg |= (val - 1) << 4;
+		w83627ehf_write_value(data,
+				      NCT6775_REG_FAN_MODE[nr], reg);
+	} else {
+		reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
+		reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
+		reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
+		w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	}
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1038,9 +1386,10 @@
 				char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	return sprintf(buf, "%d\n", temp1_from_reg(data->reg[nr])); \
+	return sprintf(buf, "%d\n", data->reg[nr] * 1000); \
 }
 
 show_tol_temp(tolerance)
@@ -1053,11 +1402,18 @@
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
+	long val;
+	int err;
+
+	err = strict_strtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 127);
 
 	mutex_lock(&data->update_lock);
 	data->target_temp[nr] = val;
-	w83627ehf_write_value(data, W83627EHF_REG_TARGET[nr], val);
+	w83627ehf_write_value(data, data->REG_TARGET[nr], val);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1067,20 +1423,37 @@
 			const char *buf, size_t count)
 {
 	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u16 reg;
+	long val;
+	int err;
+
+	err = strict_strtol(buf, 10, &val);
+	if (err < 0)
+		return err;
+
 	/* Limit the temp to 0C - 15C */
-	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
+	val = SENSORS_LIMIT(DIV_ROUND_CLOSEST(val, 1000), 0, 15);
 
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
-	data->tolerance[nr] = val;
-	if (nr == 1)
-		reg = (reg & 0x0f) | (val << 4);
-	else
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		/* Limit tolerance further for NCT6776F */
+		if (sio_data->kind == nct6776 && val > 7)
+			val = 7;
+		reg = w83627ehf_read_value(data, NCT6775_REG_FAN_MODE[nr]);
 		reg = (reg & 0xf0) | val;
-	w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg);
+		w83627ehf_write_value(data, NCT6775_REG_FAN_MODE[nr], reg);
+	} else {
+		reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
+		if (nr == 1)
+			reg = (reg & 0x0f) | (val << 4);
+		else
+			reg = (reg & 0xf0) | val;
+		w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg);
+	}
+	data->tolerance[nr] = val;
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1143,18 +1516,25 @@
 		       char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", data->reg[nr]); \
-}\
+} \
 static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 			    const char *buf, size_t count) \
-{\
+{ \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
+	unsigned long val; \
+	int err; \
+	err = strict_strtoul(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
+	val = SENSORS_LIMIT(val, 1, 255); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
 	w83627ehf_write_value(data, data->REG_##REG[nr], val); \
@@ -1172,10 +1552,12 @@
 				char *buf) \
 { \
 	struct w83627ehf_data *data = w83627ehf_update_device(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	return sprintf(buf, "%d\n", \
-			step_time_from_reg(data->reg[nr], data->pwm_mode[nr])); \
+			step_time_from_reg(data->reg[nr], \
+					   data->pwm_mode[nr])); \
 } \
 \
 static ssize_t \
@@ -1183,10 +1565,15 @@
 			const char *buf, size_t count) \
 { \
 	struct w83627ehf_data *data = dev_get_drvdata(dev); \
-	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
+	struct sensor_device_attribute *sensor_attr = \
+		to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
-	u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
-					data->pwm_mode[nr]); \
+	unsigned long val; \
+	int err; \
+	err = strict_strtoul(buf, 10, &val); \
+	if (err < 0) \
+		return err; \
+	val = step_time_to_reg(val, data->pwm_mode[nr]); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
 	w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \
@@ -1283,7 +1670,8 @@
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
 		struct sensor_device_attribute *attr =
 		  &sda_sf3_max_step_arrays[i];
-		if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
+		if (data->REG_FAN_STEP_OUTPUT &&
+		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff)
 			device_remove_file(dev, &attr->dev_attr);
 	}
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
@@ -1309,12 +1697,15 @@
 		device_remove_file(dev, &sda_target_temp[i].dev_attr);
 		device_remove_file(dev, &sda_tolerance[i].dev_attr);
 	}
-	for (i = 0; i < 3; i++) {
-		if ((i == 2) && data->temp3_disable)
+	for (i = 0; i < NUM_REG_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
 			continue;
 		device_remove_file(dev, &sda_temp_input[i].dev_attr);
+		device_remove_file(dev, &sda_temp_label[i].dev_attr);
 		device_remove_file(dev, &sda_temp_max[i].dev_attr);
 		device_remove_file(dev, &sda_temp_max_hyst[i].dev_attr);
+		if (i > 2)
+			continue;
 		device_remove_file(dev, &sda_temp_alarm[i].dev_attr);
 		device_remove_file(dev, &sda_temp_type[i].dev_attr);
 	}
@@ -1335,15 +1726,17 @@
 		w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
 				      tmp | 0x01);
 
-	/* Enable temp2 and temp3 if needed */
-	for (i = 0; i < 2; i++) {
-		tmp = w83627ehf_read_value(data,
-					   W83627EHF_REG_TEMP_CONFIG[i]);
-		if ((i == 1) && data->temp3_disable)
+	/* Enable temperature sensors if needed */
+	for (i = 0; i < NUM_REG_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
 			continue;
+		if (!data->reg_temp_config[i])
+			continue;
+		tmp = w83627ehf_read_value(data,
+					   data->reg_temp_config[i]);
 		if (tmp & 0x01)
 			w83627ehf_write_value(data,
-					      W83627EHF_REG_TEMP_CONFIG[i],
+					      data->reg_temp_config[i],
 					      tmp & 0xfe);
 	}
 
@@ -1362,13 +1755,39 @@
 	}
 }
 
+static void w82627ehf_swap_tempreg(struct w83627ehf_data *data,
+				   int r1, int r2)
+{
+	u16 tmp;
+
+	tmp = data->temp_src[r1];
+	data->temp_src[r1] = data->temp_src[r2];
+	data->temp_src[r2] = tmp;
+
+	tmp = data->reg_temp[r1];
+	data->reg_temp[r1] = data->reg_temp[r2];
+	data->reg_temp[r2] = tmp;
+
+	tmp = data->reg_temp_over[r1];
+	data->reg_temp_over[r1] = data->reg_temp_over[r2];
+	data->reg_temp_over[r2] = tmp;
+
+	tmp = data->reg_temp_hyst[r1];
+	data->reg_temp_hyst[r1] = data->reg_temp_hyst[r2];
+	data->reg_temp_hyst[r2] = tmp;
+
+	tmp = data->reg_temp_config[r1];
+	data->reg_temp_config[r1] = data->reg_temp_config[r2];
+	data->reg_temp_config[r2] = tmp;
+}
+
 static int __devinit w83627ehf_probe(struct platform_device *pdev)
 {
 	struct device *dev = &pdev->dev;
 	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct w83627ehf_data *data;
 	struct resource *res;
-	u8 fan4pin, fan5pin, en_vrm10;
+	u8 fan3pin, fan4pin, fan4min, fan5pin, en_vrm10;
 	int i, err = 0;
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1380,7 +1799,8 @@
 		goto exit;
 	}
 
-	if (!(data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL))) {
+	data = kzalloc(sizeof(struct w83627ehf_data), GFP_KERNEL);
+	if (!data) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
@@ -1393,25 +1813,202 @@
 
 	/* 627EHG and 627EHF have 10 voltage inputs; 627DHG and 667HG have 9 */
 	data->in_num = (sio_data->kind == w83627ehf) ? 10 : 9;
-	/* 667HG has 3 pwms */
+	/* 667HG, NCT6775F, and NCT6776F have 3 pwms */
 	data->pwm_num = (sio_data->kind == w83667hg
-			 || sio_data->kind == w83667hg_b) ? 3 : 4;
+			 || sio_data->kind == w83667hg_b
+			 || sio_data->kind == nct6775
+			 || sio_data->kind == nct6776) ? 3 : 4;
 
+	data->have_temp = 0x07;
 	/* Check temp3 configuration bit for 667HG */
-	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
-		data->temp3_disable = w83627ehf_read_value(data,
-					W83627EHF_REG_TEMP_CONFIG[1]) & 0x01;
-		data->in6_skip = !data->temp3_disable;
+	if (sio_data->kind == w83667hg) {
+		u8 reg;
+
+		reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
+		if (reg & 0x01)
+			data->have_temp &= ~(1 << 2);
+		else
+			data->in6_skip = 1;	/* either temp3 or in6 */
 	}
 
-	data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
-	data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
-	if (sio_data->kind == w83667hg_b) {
+	/* Deal with temperature register setup first. */
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		int mask = 0;
+
+		/*
+		 * Display temperature sensor output only if it monitors
+		 * a source other than one already reported. Always display
+		 * first three temperature registers, though.
+		 */
+		for (i = 0; i < NUM_REG_TEMP; i++) {
+			u8 src;
+
+			data->reg_temp[i] = NCT6775_REG_TEMP[i];
+			data->reg_temp_over[i] = NCT6775_REG_TEMP_OVER[i];
+			data->reg_temp_hyst[i] = NCT6775_REG_TEMP_HYST[i];
+			data->reg_temp_config[i] = NCT6775_REG_TEMP_CONFIG[i];
+
+			src = w83627ehf_read_value(data,
+						   NCT6775_REG_TEMP_SOURCE[i]);
+			src &= 0x1f;
+			if (src && !(mask & (1 << src))) {
+				data->have_temp |= 1 << i;
+				mask |= 1 << src;
+			}
+
+			data->temp_src[i] = src;
+
+			/*
+			 * Now do some register swapping if index 0..2 don't
+			 * point to SYSTIN(1), CPUIN(2), and AUXIN(3).
+			 * Idea is to have the first three attributes
+			 * report SYSTIN, CPUIN, and AUXIN if possible
+			 * without overriding the basic system configuration.
+			 */
+			if (i > 0 && data->temp_src[0] != 1
+			    && data->temp_src[i] == 1)
+				w82627ehf_swap_tempreg(data, 0, i);
+			if (i > 1 && data->temp_src[1] != 2
+			    && data->temp_src[i] == 2)
+				w82627ehf_swap_tempreg(data, 1, i);
+			if (i > 2 && data->temp_src[2] != 3
+			    && data->temp_src[i] == 3)
+				w82627ehf_swap_tempreg(data, 2, i);
+		}
+		if (sio_data->kind == nct6776) {
+			/*
+			 * On NCT6776, AUXTIN and VIN3 pins are shared.
+			 * Only way to detect it is to check if AUXTIN is used
+			 * as a temperature source, and if that source is
+			 * enabled.
+			 *
+			 * If that is the case, disable in6, which reports VIN3.
+			 * Otherwise disable temp3.
+			 */
+			if (data->temp_src[2] == 3) {
+				u8 reg;
+
+				if (data->reg_temp_config[2])
+					reg = w83627ehf_read_value(data,
+						data->reg_temp_config[2]);
+				else
+					reg = 0; /* Assume AUXTIN is used */
+
+				if (reg & 0x01)
+					data->have_temp &= ~(1 << 2);
+				else
+					data->in6_skip = 1;
+			}
+			data->temp_label = nct6776_temp_label;
+		} else {
+			data->temp_label = nct6775_temp_label;
+		}
+	} else if (sio_data->kind == w83667hg_b) {
+		u8 reg;
+
+		/*
+		 * Temperature sources are selected with bank 0, registers 0x49
+		 * and 0x4a.
+		 */
+		for (i = 0; i < ARRAY_SIZE(W83627EHF_REG_TEMP); i++) {
+			data->reg_temp[i] = W83627EHF_REG_TEMP[i];
+			data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
+			data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
+			data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+		}
+		reg = w83627ehf_read_value(data, 0x4a);
+		data->temp_src[0] = reg >> 5;
+		reg = w83627ehf_read_value(data, 0x49);
+		data->temp_src[1] = reg & 0x07;
+		data->temp_src[2] = (reg >> 4) & 0x07;
+
+		/*
+		 * W83667HG-B has another temperature register at 0x7e.
+		 * The temperature source is selected with register 0x7d.
+		 * Support it if the source differs from already reported
+		 * sources.
+		 */
+		reg = w83627ehf_read_value(data, 0x7d);
+		reg &= 0x07;
+		if (reg != data->temp_src[0] && reg != data->temp_src[1]
+		    && reg != data->temp_src[2]) {
+			data->temp_src[3] = reg;
+			data->have_temp |= 1 << 3;
+		}
+
+		/*
+		 * Chip supports either AUXTIN or VIN3. Try to find out which
+		 * one.
+		 */
+		reg = w83627ehf_read_value(data, W83627EHF_REG_TEMP_CONFIG[2]);
+		if (data->temp_src[2] == 2 && (reg & 0x01))
+			data->have_temp &= ~(1 << 2);
+
+		if ((data->temp_src[2] == 2 && (data->have_temp & (1 << 2)))
+		    || (data->temp_src[3] == 2 && (data->have_temp & (1 << 3))))
+			data->in6_skip = 1;
+
+		data->temp_label = w83667hg_b_temp_label;
+	} else {
+		/* Temperature sources are fixed */
+		for (i = 0; i < 3; i++) {
+			data->reg_temp[i] = W83627EHF_REG_TEMP[i];
+			data->reg_temp_over[i] = W83627EHF_REG_TEMP_OVER[i];
+			data->reg_temp_hyst[i] = W83627EHF_REG_TEMP_HYST[i];
+			data->reg_temp_config[i] = W83627EHF_REG_TEMP_CONFIG[i];
+		}
+	}
+
+	if (sio_data->kind == nct6775) {
+		data->has_fan_div = true;
+		data->fan_from_reg = fan_from_reg16;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->REG_PWM = NCT6775_REG_PWM;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME;
+		data->REG_FAN_MAX_OUTPUT = NCT6775_REG_FAN_MAX_OUTPUT;
+		data->REG_FAN_STEP_OUTPUT = NCT6775_REG_FAN_STEP_OUTPUT;
+	} else if (sio_data->kind == nct6776) {
+		data->has_fan_div = false;
+		data->fan_from_reg = fan_from_reg13;
+		data->fan_from_reg_min = fan_from_reg13;
+		data->REG_PWM = NCT6775_REG_PWM;
+		data->REG_TARGET = NCT6775_REG_TARGET;
+		data->REG_FAN = NCT6775_REG_FAN;
+		data->REG_FAN_MIN = NCT6776_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = NCT6775_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = NCT6775_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = NCT6775_REG_FAN_STOP_TIME;
+	} else if (sio_data->kind == w83667hg_b) {
+		data->has_fan_div = true;
+		data->fan_from_reg = fan_from_reg8;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->REG_PWM = W83627EHF_REG_PWM;
+		data->REG_TARGET = W83627EHF_REG_TARGET;
+		data->REG_FAN = W83627EHF_REG_FAN;
+		data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME;
 		data->REG_FAN_MAX_OUTPUT =
 		  W83627EHF_REG_FAN_MAX_OUTPUT_W83667_B;
 		data->REG_FAN_STEP_OUTPUT =
 		  W83627EHF_REG_FAN_STEP_OUTPUT_W83667_B;
 	} else {
+		data->has_fan_div = true;
+		data->fan_from_reg = fan_from_reg8;
+		data->fan_from_reg_min = fan_from_reg8;
+		data->REG_PWM = W83627EHF_REG_PWM;
+		data->REG_TARGET = W83627EHF_REG_TARGET;
+		data->REG_FAN = W83627EHF_REG_FAN;
+		data->REG_FAN_MIN = W83627EHF_REG_FAN_MIN;
+		data->REG_FAN_START_OUTPUT = W83627EHF_REG_FAN_START_OUTPUT;
+		data->REG_FAN_STOP_OUTPUT = W83627EHF_REG_FAN_STOP_OUTPUT;
+		data->REG_FAN_STOP_TIME = W83627EHF_REG_FAN_STOP_TIME;
 		data->REG_FAN_MAX_OUTPUT =
 		  W83627EHF_REG_FAN_MAX_OUTPUT_COMMON;
 		data->REG_FAN_STEP_OUTPUT =
@@ -1424,7 +2021,8 @@
 	data->vrm = vid_which_vrm();
 	superio_enter(sio_data->sioreg);
 	/* Read VID value */
-	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
+	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b ||
+	    sio_data->kind == nct6775 || sio_data->kind == nct6776) {
 		/* W83667HG has different pins for VID input and output, so
 		we can get the VID input values directly at logical device D
 		0xe3. */
@@ -1475,13 +2073,44 @@
 	}
 
 	/* fan4 and fan5 share some pins with the GPIO and serial flash */
-	if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
-		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+	if (sio_data->kind == nct6775) {
+		/* On NCT6775, fan4 shares pins with the fdc interface */
+		fan3pin = 1;
+		fan4pin = !(superio_inb(sio_data->sioreg, 0x2A) & 0x80);
+		fan4min = 0;
+		fan5pin = 0;
+	} else if (sio_data->kind == nct6776) {
+		fan3pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x40);
+		fan4pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x01);
+		fan5pin = !!(superio_inb(sio_data->sioreg, 0x1C) & 0x02);
+		fan4min = fan4pin;
+	} else if (sio_data->kind == w83667hg || sio_data->kind == w83667hg_b) {
+		fan3pin = 1;
 		fan4pin = superio_inb(sio_data->sioreg, 0x27) & 0x40;
+		fan5pin = superio_inb(sio_data->sioreg, 0x27) & 0x20;
+		fan4min = fan4pin;
 	} else {
-		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+		fan3pin = 1;
 		fan4pin = !(superio_inb(sio_data->sioreg, 0x29) & 0x06);
+		fan5pin = !(superio_inb(sio_data->sioreg, 0x24) & 0x02);
+		fan4min = fan4pin;
+	}
+
+	if (fan_debounce &&
+	    (sio_data->kind == nct6775 || sio_data->kind == nct6776)) {
+		u8 tmp;
+
+		superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+		tmp = superio_inb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE);
+		if (sio_data->kind == nct6776)
+			superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE,
+				     0x3e | tmp);
+		else
+			superio_outb(sio_data->sioreg, NCT6775_REG_FAN_DEBOUNCE,
+				     0x1e | tmp);
+		pr_info("Enabled fan debounce for chip %s\n", data->name);
 	}
+
 	superio_exit(sio_data->sioreg);
 
 	/* It looks like fan4 and fan5 pins can be alternatively used
@@ -1490,26 +2119,54 @@
 	   connected fan5 as input unless they are emitting log 1, which
 	   is not the default. */
 
-	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
-	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
-	if ((i & (1 << 2)) && fan4pin)
-		data->has_fan |= (1 << 3);
-	if (!(i & (1 << 1)) && fan5pin)
-		data->has_fan |= (1 << 4);
+	data->has_fan = data->has_fan_min = 0x03; /* fan1 and fan2 */
+
+	data->has_fan |= (fan3pin << 2);
+	data->has_fan_min |= (fan3pin << 2);
+
+	/*
+	 * NCT6775F and NCT6776F don't have the W83627EHF_REG_FANDIV1 register
+	 */
+	if (sio_data->kind == nct6775 || sio_data->kind == nct6776) {
+		data->has_fan |= (fan4pin << 3) | (fan5pin << 4);
+		data->has_fan_min |= (fan4min << 3) | (fan5pin << 4);
+	} else {
+		i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
+		if ((i & (1 << 2)) && fan4pin) {
+			data->has_fan |= (1 << 3);
+			data->has_fan_min |= (1 << 3);
+		}
+		if (!(i & (1 << 1)) && fan5pin) {
+			data->has_fan |= (1 << 4);
+			data->has_fan_min |= (1 << 4);
+		}
+	}
 
 	/* Read fan clock dividers immediately */
-	w83627ehf_update_fan_div(data);
+	w83627ehf_update_fan_div_common(dev, data);
+
+	/* Read pwm data to save original values */
+	w83627ehf_update_pwm_common(dev, data);
+	for (i = 0; i < data->pwm_num; i++)
+		data->pwm_enable_orig[i] = data->pwm_enable[i];
+
+	/* Read pwm data to save original values */
+	w83627ehf_update_pwm_common(dev, data);
+	for (i = 0; i < data->pwm_num; i++)
+		data->pwm_enable_orig[i] = data->pwm_enable[i];
 
 	/* Register sysfs hooks */
-  	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
-		if ((err = device_create_file(dev,
-			&sda_sf3_arrays[i].dev_attr)))
+	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++) {
+		err = device_create_file(dev, &sda_sf3_arrays[i].dev_attr);
+		if (err)
 			goto exit_remove;
+	}
 
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_max_step_arrays); i++) {
 		struct sensor_device_attribute *attr =
 		  &sda_sf3_max_step_arrays[i];
-		if (data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) {
+		if (data->REG_FAN_STEP_OUTPUT &&
+		    data->REG_FAN_STEP_OUTPUT[attr->index] != 0xff) {
 			err = device_create_file(dev, &attr->dev_attr);
 			if (err)
 				goto exit_remove;
@@ -1518,8 +2175,9 @@
 	/* if fan4 is enabled create the sf3 files for it */
 	if ((data->has_fan & (1 << 3)) && data->pwm_num >= 4)
 		for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++) {
-			if ((err = device_create_file(dev,
-				&sda_sf3_arrays_fan4[i].dev_attr)))
+			err = device_create_file(dev,
+					&sda_sf3_arrays_fan4[i].dev_attr);
+			if (err)
 				goto exit_remove;
 		}
 
@@ -1541,12 +2199,20 @@
 			if ((err = device_create_file(dev,
 					&sda_fan_input[i].dev_attr))
 				|| (err = device_create_file(dev,
-					&sda_fan_alarm[i].dev_attr))
-				|| (err = device_create_file(dev,
-					&sda_fan_div[i].dev_attr))
-				|| (err = device_create_file(dev,
-					&sda_fan_min[i].dev_attr)))
+					&sda_fan_alarm[i].dev_attr)))
 				goto exit_remove;
+			if (sio_data->kind != nct6776) {
+				err = device_create_file(dev,
+						&sda_fan_div[i].dev_attr);
+				if (err)
+					goto exit_remove;
+			}
+			if (data->has_fan_min & (1 << i)) {
+				err = device_create_file(dev,
+						&sda_fan_min[i].dev_attr);
+				if (err)
+					goto exit_remove;
+			}
 			if (i < data->pwm_num &&
 				((err = device_create_file(dev,
 					&sda_pwm[i].dev_attr))
@@ -1562,16 +2228,33 @@
 		}
 	}
 
-	for (i = 0; i < 3; i++) {
-		if ((i == 2) && data->temp3_disable)
+	for (i = 0; i < NUM_REG_TEMP; i++) {
+		if (!(data->have_temp & (1 << i)))
+			continue;
+		err = device_create_file(dev, &sda_temp_input[i].dev_attr);
+		if (err)
+			goto exit_remove;
+		if (data->temp_label) {
+			err = device_create_file(dev,
+						 &sda_temp_label[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp_over[i]) {
+			err = device_create_file(dev,
+				&sda_temp_max[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (data->reg_temp_hyst[i]) {
+			err = device_create_file(dev,
+				&sda_temp_max_hyst[i].dev_attr);
+			if (err)
+				goto exit_remove;
+		}
+		if (i > 2)
 			continue;
 		if ((err = device_create_file(dev,
-				&sda_temp_input[i].dev_attr))
-			|| (err = device_create_file(dev,
-				&sda_temp_max[i].dev_attr))
-			|| (err = device_create_file(dev,
-				&sda_temp_max_hyst[i].dev_attr))
-			|| (err = device_create_file(dev,
 				&sda_temp_alarm[i].dev_attr))
 			|| (err = device_create_file(dev,
 				&sda_temp_type[i].dev_attr)))
@@ -1632,6 +2315,8 @@
 	static const char __initdata sio_name_W83627DHG_P[] = "W83627DHG-P";
 	static const char __initdata sio_name_W83667HG[] = "W83667HG";
 	static const char __initdata sio_name_W83667HG_B[] = "W83667HG-B";
+	static const char __initdata sio_name_NCT6775[] = "NCT6775F";
+	static const char __initdata sio_name_NCT6776[] = "NCT6776F";
 
 	u16 val;
 	const char *sio_name;
@@ -1668,6 +2353,14 @@
 		sio_data->kind = w83667hg_b;
 		sio_name = sio_name_W83667HG_B;
 		break;
+	case SIO_NCT6775_ID:
+		sio_data->kind = nct6775;
+		sio_name = sio_name_NCT6775;
+		break;
+	case SIO_NCT6776_ID:
+		sio_data->kind = nct6776;
+		sio_name = sio_name_NCT6776;
+		break;
 	default:
 		if (val != 0xffff)
 			pr_debug("unsupported chip ID: 0x%04x\n", val);
@@ -1689,7 +2382,8 @@
 	/* Activate logical device if needed */
 	val = superio_inb(sioaddr, SIO_REG_ENABLE);
 	if (!(val & 0x01)) {
-		pr_warn("Forcibly enabling Super-I/O. Sensor is probably unusable.\n");
+		pr_warn("Forcibly enabling Super-I/O. "
+			"Sensor is probably unusable.\n");
 		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
 	}
 
@@ -1726,7 +2420,8 @@
 	if (err)
 		goto exit;
 
-	if (!(pdev = platform_device_alloc(DRVNAME, address))) {
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
 		err = -ENOMEM;
 		pr_err("Device allocation failed\n");
 		goto exit_unregister;
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/w83791d.c linux-libre-2.6.39-gnu/drivers/hwmon/w83791d.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/w83791d.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/w83791d.c	2011-05-19 00:06:34.000000000 -0400
@@ -556,7 +556,7 @@
 
 /* Note: we save and restore the fan minimum here, because its value is
    determined in part by the fan divisor.  This follows the principle of
-   least suprise; the user doesn't expect the fan minimum to change just
+   least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t store_fan_div(struct device *dev, struct device_attribute *attr,
 				const char *buf, size_t count)
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/w83792d.c linux-libre-2.6.39-gnu/drivers/hwmon/w83792d.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/w83792d.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/w83792d.c	2011-05-19 00:06:34.000000000 -0400
@@ -244,7 +244,7 @@
 #define TEMP1_TO_REG(val)	(SENSORS_LIMIT(((val) < 0 ? (val)+0x100*1000 \
 					: (val)) / 1000, 0, 0xff))
 #define TEMP1_FROM_REG(val)	(((val) & 0x80 ? (val)-0x100 : (val)) * 1000)
-/* for temp2 and temp3, because they need addtional resolution */
+/* for temp2 and temp3, because they need additional resolution */
 #define TEMP_ADD_FROM_REG(val1, val2) \
 	((((val1) & 0x80 ? (val1)-0x100 \
 		: (val1)) * 1000) + ((val2 & 0x80) ? 500 : 0))
diff -druN linux-libre-2.6.38-gnu/drivers/hwmon/w83793.c linux-libre-2.6.39-gnu/drivers/hwmon/w83793.c
--- linux-libre-2.6.38-gnu/drivers/hwmon/w83793.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/hwmon/w83793.c	2011-05-19 00:06:34.000000000 -0400
@@ -1921,7 +1921,7 @@
 	struct w83793_data *data = i2c_get_clientdata(client);
 	int i, j;
 	/*
-	   They are somewhat "stable" registers, and to update them everytime
+	   They are somewhat "stable" registers, and to update them every time
 	   takes so much time, it's just not worthy. Update them in a long
 	   interval to avoid exception.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/hwspinlock/hwspinlock_core.c linux-libre-2.6.39-gnu/drivers/hwspinlock/hwspinlock_core.c
--- linux-libre-2.6.38-gnu/drivers/hwspinlock/hwspinlock_core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwspinlock/hwspinlock_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,548 @@
+/*
+ * Hardware spinlock framework
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#define pr_fmt(fmt)    "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/err.h>
+#include <linux/jiffies.h>
+#include <linux/radix-tree.h>
+#include <linux/hwspinlock.h>
+#include <linux/pm_runtime.h>
+
+#include "hwspinlock_internal.h"
+
+/* radix tree tags */
+#define HWSPINLOCK_UNUSED	(0) /* tags an hwspinlock as unused */
+
+/*
+ * A radix tree is used to maintain the available hwspinlock instances.
+ * The tree associates hwspinlock pointers with their integer key id,
+ * and provides easy-to-use API which makes the hwspinlock core code simple
+ * and easy to read.
+ *
+ * Radix trees are quick on lookups, and reasonably efficient in terms of
+ * storage, especially with high density usages such as this framework
+ * requires (a continuous range of integer keys, beginning with zero, is
+ * used as the ID's of the hwspinlock instances).
+ *
+ * The radix tree API supports tagging items in the tree, which this
+ * framework uses to mark unused hwspinlock instances (see the
+ * HWSPINLOCK_UNUSED tag above). As a result, the process of querying the
+ * tree, looking for an unused hwspinlock instance, is now reduced to a
+ * single radix tree API call.
+ */
+static RADIX_TREE(hwspinlock_tree, GFP_KERNEL);
+
+/*
+ * Synchronization of access to the tree is achieved using this spinlock,
+ * as the radix-tree API requires that users provide all synchronisation.
+ */
+static DEFINE_SPINLOCK(hwspinlock_tree_lock);
+
+/**
+ * __hwspin_trylock() - attempt to lock a specific hwspinlock
+ * @hwlock: an hwspinlock which we want to trylock
+ * @mode: controls whether local interrupts are disabled or not
+ * @flags: a pointer where the caller's interrupt state will be saved at (if
+ *         requested)
+ *
+ * This function attempts to lock an hwspinlock, and will immediately
+ * fail if the hwspinlock is already taken.
+ *
+ * Upon a successful return from this function, preemption (and possibly
+ * interrupts) is disabled, so the caller must not sleep, and is advised to
+ * release the hwspinlock as soon as possible. This is required in order to
+ * minimize remote cores polling on the hardware interconnect.
+ *
+ * The user decides whether local interrupts are disabled or not, and if yes,
+ * whether he wants their previous state to be saved. It is up to the user
+ * to choose the appropriate @mode of operation, exactly the same way users
+ * should decide between spin_trylock, spin_trylock_irq and
+ * spin_trylock_irqsave.
+ *
+ * Returns 0 if we successfully locked the hwspinlock or -EBUSY if
+ * the hwspinlock was already taken.
+ * This function will never sleep.
+ */
+int __hwspin_trylock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
+{
+	int ret;
+
+	BUG_ON(!hwlock);
+	BUG_ON(!flags && mode == HWLOCK_IRQSTATE);
+
+	/*
+	 * This spin_lock{_irq, _irqsave} serves three purposes:
+	 *
+	 * 1. Disable preemption, in order to minimize the period of time
+	 *    in which the hwspinlock is taken. This is important in order
+	 *    to minimize the possible polling on the hardware interconnect
+	 *    by a remote user of this lock.
+	 * 2. Make the hwspinlock SMP-safe (so we can take it from
+	 *    additional contexts on the local host).
+	 * 3. Ensure that in_atomic/might_sleep checks catch potential
+	 *    problems with hwspinlock usage (e.g. scheduler checks like
+	 *    'scheduling while atomic' etc.)
+	 */
+	if (mode == HWLOCK_IRQSTATE)
+		ret = spin_trylock_irqsave(&hwlock->lock, *flags);
+	else if (mode == HWLOCK_IRQ)
+		ret = spin_trylock_irq(&hwlock->lock);
+	else
+		ret = spin_trylock(&hwlock->lock);
+
+	/* is lock already taken by another context on the local cpu ? */
+	if (!ret)
+		return -EBUSY;
+
+	/* try to take the hwspinlock device */
+	ret = hwlock->ops->trylock(hwlock);
+
+	/* if hwlock is already taken, undo spin_trylock_* and exit */
+	if (!ret) {
+		if (mode == HWLOCK_IRQSTATE)
+			spin_unlock_irqrestore(&hwlock->lock, *flags);
+		else if (mode == HWLOCK_IRQ)
+			spin_unlock_irq(&hwlock->lock);
+		else
+			spin_unlock(&hwlock->lock);
+
+		return -EBUSY;
+	}
+
+	/*
+	 * We can be sure the other core's memory operations
+	 * are observable to us only _after_ we successfully take
+	 * the hwspinlock, and we must make sure that subsequent memory
+	 * operations (both reads and writes) will not be reordered before
+	 * we actually took the hwspinlock.
+	 *
+	 * Note: the implicit memory barrier of the spinlock above is too
+	 * early, so we need this additional explicit memory barrier.
+	 */
+	mb();
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(__hwspin_trylock);
+
+/**
+ * __hwspin_lock_timeout() - lock an hwspinlock with timeout limit
+ * @hwlock: the hwspinlock to be locked
+ * @timeout: timeout value in msecs
+ * @mode: mode which controls whether local interrupts are disabled or not
+ * @flags: a pointer to where the caller's interrupt state will be saved at (if
+ *         requested)
+ *
+ * This function locks the given @hwlock. If the @hwlock
+ * is already taken, the function will busy loop waiting for it to
+ * be released, but give up after @timeout msecs have elapsed.
+ *
+ * Upon a successful return from this function, preemption is disabled
+ * (and possibly local interrupts, too), so the caller must not sleep,
+ * and is advised to release the hwspinlock as soon as possible.
+ * This is required in order to minimize remote cores polling on the
+ * hardware interconnect.
+ *
+ * The user decides whether local interrupts are disabled or not, and if yes,
+ * whether he wants their previous state to be saved. It is up to the user
+ * to choose the appropriate @mode of operation, exactly the same way users
+ * should decide between spin_lock, spin_lock_irq and spin_lock_irqsave.
+ *
+ * Returns 0 when the @hwlock was successfully taken, and an appropriate
+ * error code otherwise (most notably -ETIMEDOUT if the @hwlock is still
+ * busy after @timeout msecs). The function will never sleep.
+ */
+int __hwspin_lock_timeout(struct hwspinlock *hwlock, unsigned int to,
+					int mode, unsigned long *flags)
+{
+	int ret;
+	unsigned long expire;
+
+	expire = msecs_to_jiffies(to) + jiffies;
+
+	for (;;) {
+		/* Try to take the hwspinlock */
+		ret = __hwspin_trylock(hwlock, mode, flags);
+		if (ret != -EBUSY)
+			break;
+
+		/*
+		 * The lock is already taken, let's check if the user wants
+		 * us to try again
+		 */
+		if (time_is_before_eq_jiffies(expire))
+			return -ETIMEDOUT;
+
+		/*
+		 * Allow platform-specific relax handlers to prevent
+		 * hogging the interconnect (no sleeping, though)
+		 */
+		if (hwlock->ops->relax)
+			hwlock->ops->relax(hwlock);
+	}
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(__hwspin_lock_timeout);
+
+/**
+ * __hwspin_unlock() - unlock a specific hwspinlock
+ * @hwlock: a previously-acquired hwspinlock which we want to unlock
+ * @mode: controls whether local interrupts needs to be restored or not
+ * @flags: previous caller's interrupt state to restore (if requested)
+ *
+ * This function will unlock a specific hwspinlock, enable preemption and
+ * (possibly) enable interrupts or restore their previous state.
+ * @hwlock must be already locked before calling this function: it is a bug
+ * to call unlock on a @hwlock that is already unlocked.
+ *
+ * The user decides whether local interrupts should be enabled or not, and
+ * if yes, whether he wants their previous state to be restored. It is up
+ * to the user to choose the appropriate @mode of operation, exactly the
+ * same way users decide between spin_unlock, spin_unlock_irq and
+ * spin_unlock_irqrestore.
+ *
+ * The function will never sleep.
+ */
+void __hwspin_unlock(struct hwspinlock *hwlock, int mode, unsigned long *flags)
+{
+	BUG_ON(!hwlock);
+	BUG_ON(!flags && mode == HWLOCK_IRQSTATE);
+
+	/*
+	 * We must make sure that memory operations (both reads and writes),
+	 * done before unlocking the hwspinlock, will not be reordered
+	 * after the lock is released.
+	 *
+	 * That's the purpose of this explicit memory barrier.
+	 *
+	 * Note: the memory barrier induced by the spin_unlock below is too
+	 * late; the other core is going to access memory soon after it will
+	 * take the hwspinlock, and by then we want to be sure our memory
+	 * operations are already observable.
+	 */
+	mb();
+
+	hwlock->ops->unlock(hwlock);
+
+	/* Undo the spin_trylock{_irq, _irqsave} called while locking */
+	if (mode == HWLOCK_IRQSTATE)
+		spin_unlock_irqrestore(&hwlock->lock, *flags);
+	else if (mode == HWLOCK_IRQ)
+		spin_unlock_irq(&hwlock->lock);
+	else
+		spin_unlock(&hwlock->lock);
+}
+EXPORT_SYMBOL_GPL(__hwspin_unlock);
+
+/**
+ * hwspin_lock_register() - register a new hw spinlock
+ * @hwlock: hwspinlock to register.
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to register a new hwspinlock instance.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context.
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_register(struct hwspinlock *hwlock)
+{
+	struct hwspinlock *tmp;
+	int ret;
+
+	if (!hwlock || !hwlock->ops ||
+		!hwlock->ops->trylock || !hwlock->ops->unlock) {
+		pr_err("invalid parameters\n");
+		return -EINVAL;
+	}
+
+	spin_lock_init(&hwlock->lock);
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	ret = radix_tree_insert(&hwspinlock_tree, hwlock->id, hwlock);
+	if (ret)
+		goto out;
+
+	/* mark this hwspinlock as available */
+	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+
+	/* self-sanity check which should never fail */
+	WARN_ON(tmp != hwlock);
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_register);
+
+/**
+ * hwspin_lock_unregister() - unregister an hw spinlock
+ * @id: index of the specific hwspinlock to unregister
+ *
+ * This function should be called from the underlying platform-specific
+ * implementation, to unregister an existing (and unused) hwspinlock.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context.
+ *
+ * Returns the address of hwspinlock @id on success, or NULL on failure
+ */
+struct hwspinlock *hwspin_lock_unregister(unsigned int id)
+{
+	struct hwspinlock *hwlock = NULL;
+	int ret;
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* make sure the hwspinlock is not in use (tag is set) */
+	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
+	if (ret == 0) {
+		pr_err("hwspinlock %d still in use (or not present)\n", id);
+		goto out;
+	}
+
+	hwlock = radix_tree_delete(&hwspinlock_tree, id);
+	if (!hwlock) {
+		pr_err("failed to delete hwspinlock %d\n", id);
+		goto out;
+	}
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return hwlock;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_unregister);
+
+/**
+ * __hwspin_lock_request() - tag an hwspinlock as used and power it up
+ *
+ * This is an internal function that prepares an hwspinlock instance
+ * before it is given to the user. The function assumes that
+ * hwspinlock_tree_lock is taken.
+ *
+ * Returns 0 or positive to indicate success, and a negative value to
+ * indicate an error (with the appropriate error code)
+ */
+static int __hwspin_lock_request(struct hwspinlock *hwlock)
+{
+	struct hwspinlock *tmp;
+	int ret;
+
+	/* prevent underlying implementation from being removed */
+	if (!try_module_get(hwlock->owner)) {
+		dev_err(hwlock->dev, "%s: can't get owner\n", __func__);
+		return -EINVAL;
+	}
+
+	/* notify PM core that power is now needed */
+	ret = pm_runtime_get_sync(hwlock->dev);
+	if (ret < 0) {
+		dev_err(hwlock->dev, "%s: can't power on device\n", __func__);
+		return ret;
+	}
+
+	/* mark hwspinlock as used, should not fail */
+	tmp = radix_tree_tag_clear(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+
+	/* self-sanity check that should never fail */
+	WARN_ON(tmp != hwlock);
+
+	return ret;
+}
+
+/**
+ * hwspin_lock_get_id() - retrieve id number of a given hwspinlock
+ * @hwlock: a valid hwspinlock instance
+ *
+ * Returns the id number of a given @hwlock, or -EINVAL if @hwlock is invalid.
+ */
+int hwspin_lock_get_id(struct hwspinlock *hwlock)
+{
+	if (!hwlock) {
+		pr_err("invalid hwlock\n");
+		return -EINVAL;
+	}
+
+	return hwlock->id;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_get_id);
+
+/**
+ * hwspin_lock_request() - request an hwspinlock
+ *
+ * This function should be called by users of the hwspinlock device,
+ * in order to dynamically assign them an unused hwspinlock.
+ * Usually the user of this lock will then have to communicate the lock's id
+ * to the remote core before it can be used for synchronization (to get the
+ * id of a given hwlock, use hwspin_lock_get_id()).
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context (simply because there is no use case for
+ * that yet).
+ *
+ * Returns the address of the assigned hwspinlock, or NULL on error
+ */
+struct hwspinlock *hwspin_lock_request(void)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* look for an unused lock */
+	ret = radix_tree_gang_lookup_tag(&hwspinlock_tree, (void **)&hwlock,
+						0, 1, HWSPINLOCK_UNUSED);
+	if (ret == 0) {
+		pr_warn("a free hwspinlock is not available\n");
+		hwlock = NULL;
+		goto out;
+	}
+
+	/* sanity check that should never fail */
+	WARN_ON(ret > 1);
+
+	/* mark as used and power up */
+	ret = __hwspin_lock_request(hwlock);
+	if (ret < 0)
+		hwlock = NULL;
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return hwlock;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_request);
+
+/**
+ * hwspin_lock_request_specific() - request for a specific hwspinlock
+ * @id: index of the specific hwspinlock that is requested
+ *
+ * This function should be called by users of the hwspinlock module,
+ * in order to assign them a specific hwspinlock.
+ * Usually early board code will be calling this function in order to
+ * reserve specific hwspinlock ids for predefined purposes.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context (simply because there is no use case for
+ * that yet).
+ *
+ * Returns the address of the assigned hwspinlock, or NULL on error
+ */
+struct hwspinlock *hwspin_lock_request_specific(unsigned int id)
+{
+	struct hwspinlock *hwlock;
+	int ret;
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* make sure this hwspinlock exists */
+	hwlock = radix_tree_lookup(&hwspinlock_tree, id);
+	if (!hwlock) {
+		pr_warn("hwspinlock %u does not exist\n", id);
+		goto out;
+	}
+
+	/* sanity check (this shouldn't happen) */
+	WARN_ON(hwlock->id != id);
+
+	/* make sure this hwspinlock is unused */
+	ret = radix_tree_tag_get(&hwspinlock_tree, id, HWSPINLOCK_UNUSED);
+	if (ret == 0) {
+		pr_warn("hwspinlock %u is already in use\n", id);
+		hwlock = NULL;
+		goto out;
+	}
+
+	/* mark as used and power up */
+	ret = __hwspin_lock_request(hwlock);
+	if (ret < 0)
+		hwlock = NULL;
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return hwlock;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
+
+/**
+ * hwspin_lock_free() - free a specific hwspinlock
+ * @hwlock: the specific hwspinlock to free
+ *
+ * This function mark @hwlock as free again.
+ * Should only be called with an @hwlock that was retrieved from
+ * an earlier call to omap_hwspin_lock_request{_specific}.
+ *
+ * Can be called from an atomic context (will not sleep) but not from
+ * within interrupt context (simply because there is no use case for
+ * that yet).
+ *
+ * Returns 0 on success, or an appropriate error code on failure
+ */
+int hwspin_lock_free(struct hwspinlock *hwlock)
+{
+	struct hwspinlock *tmp;
+	int ret;
+
+	if (!hwlock) {
+		pr_err("invalid hwlock\n");
+		return -EINVAL;
+	}
+
+	spin_lock(&hwspinlock_tree_lock);
+
+	/* make sure the hwspinlock is used */
+	ret = radix_tree_tag_get(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+	if (ret == 1) {
+		dev_err(hwlock->dev, "%s: hwlock is already free\n", __func__);
+		dump_stack();
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* notify the underlying device that power is not needed */
+	ret = pm_runtime_put(hwlock->dev);
+	if (ret < 0)
+		goto out;
+
+	/* mark this hwspinlock as available */
+	tmp = radix_tree_tag_set(&hwspinlock_tree, hwlock->id,
+							HWSPINLOCK_UNUSED);
+
+	/* sanity check (this shouldn't happen) */
+	WARN_ON(tmp != hwlock);
+
+	module_put(hwlock->owner);
+
+out:
+	spin_unlock(&hwspinlock_tree_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(hwspin_lock_free);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware spinlock interface");
+MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/hwspinlock/hwspinlock_internal.h linux-libre-2.6.39-gnu/drivers/hwspinlock/hwspinlock_internal.h
--- linux-libre-2.6.38-gnu/drivers/hwspinlock/hwspinlock_internal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwspinlock/hwspinlock_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Hardware spinlocks internal header
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#ifndef __HWSPINLOCK_HWSPINLOCK_H
+#define __HWSPINLOCK_HWSPINLOCK_H
+
+#include <linux/spinlock.h>
+#include <linux/device.h>
+
+/**
+ * struct hwspinlock_ops - platform-specific hwspinlock handlers
+ *
+ * @trylock: make a single attempt to take the lock. returns 0 on
+ *	     failure and true on success. may _not_ sleep.
+ * @unlock:  release the lock. always succeed. may _not_ sleep.
+ * @relax:   optional, platform-specific relax handler, called by hwspinlock
+ *	     core while spinning on a lock, between two successive
+ *	     invocations of @trylock. may _not_ sleep.
+ */
+struct hwspinlock_ops {
+	int (*trylock)(struct hwspinlock *lock);
+	void (*unlock)(struct hwspinlock *lock);
+	void (*relax)(struct hwspinlock *lock);
+};
+
+/**
+ * struct hwspinlock - this struct represents a single hwspinlock instance
+ *
+ * @dev: underlying device, will be used to invoke runtime PM api
+ * @ops: platform-specific hwspinlock handlers
+ * @id: a global, unique, system-wide, index of the lock.
+ * @lock: initialized and used by hwspinlock core
+ * @owner: underlying implementation module, used to maintain module ref count
+ *
+ * Note: currently simplicity was opted for, but later we can squeeze some
+ * memory bytes by grouping the dev, ops and owner members in a single
+ * per-platform struct, and have all hwspinlocks point at it.
+ */
+struct hwspinlock {
+	struct device *dev;
+	const struct hwspinlock_ops *ops;
+	int id;
+	spinlock_t lock;
+	struct module *owner;
+};
+
+#endif /* __HWSPINLOCK_HWSPINLOCK_H */
diff -druN linux-libre-2.6.38-gnu/drivers/hwspinlock/Kconfig linux-libre-2.6.39-gnu/drivers/hwspinlock/Kconfig
--- linux-libre-2.6.38-gnu/drivers/hwspinlock/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwspinlock/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,23 @@
+#
+# Generic HWSPINLOCK framework
+#
+
+config HWSPINLOCK
+	tristate "Generic Hardware Spinlock framework"
+	depends on ARCH_OMAP4
+	help
+	  Say y here to support the generic hardware spinlock framework.
+	  You only need to enable this if you have hardware spinlock module
+	  on your system (usually only relevant if your system has remote slave
+	  coprocessors).
+
+	  If unsure, say N.
+
+config HWSPINLOCK_OMAP
+	tristate "OMAP Hardware Spinlock device"
+	depends on HWSPINLOCK && ARCH_OMAP4
+	help
+	  Say y here to support the OMAP Hardware Spinlock device (firstly
+	  introduced in OMAP4).
+
+	  If unsure, say N.
diff -druN linux-libre-2.6.38-gnu/drivers/hwspinlock/Makefile linux-libre-2.6.39-gnu/drivers/hwspinlock/Makefile
--- linux-libre-2.6.38-gnu/drivers/hwspinlock/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwspinlock/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+#
+# Generic Hardware Spinlock framework
+#
+
+obj-$(CONFIG_HWSPINLOCK)		+= hwspinlock_core.o
+obj-$(CONFIG_HWSPINLOCK_OMAP)		+= omap_hwspinlock.o
diff -druN linux-libre-2.6.38-gnu/drivers/hwspinlock/omap_hwspinlock.c linux-libre-2.6.39-gnu/drivers/hwspinlock/omap_hwspinlock.c
--- linux-libre-2.6.38-gnu/drivers/hwspinlock/omap_hwspinlock.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/hwspinlock/omap_hwspinlock.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,231 @@
+/*
+ * OMAP hardware spinlock driver
+ *
+ * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * Contact: Simon Que <sque@ti.com>
+ *          Hari Kanigeri <h-kanigeri2@ti.com>
+ *          Ohad Ben-Cohen <ohad@wizery.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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/pm_runtime.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/hwspinlock.h>
+#include <linux/platform_device.h>
+
+#include "hwspinlock_internal.h"
+
+/* Spinlock register offsets */
+#define SYSSTATUS_OFFSET		0x0014
+#define LOCK_BASE_OFFSET		0x0800
+
+#define SPINLOCK_NUMLOCKS_BIT_OFFSET	(24)
+
+/* Possible values of SPINLOCK_LOCK_REG */
+#define SPINLOCK_NOTTAKEN		(0)	/* free */
+#define SPINLOCK_TAKEN			(1)	/* locked */
+
+#define to_omap_hwspinlock(lock)	\
+	container_of(lock, struct omap_hwspinlock, lock)
+
+struct omap_hwspinlock {
+	struct hwspinlock lock;
+	void __iomem *addr;
+};
+
+struct omap_hwspinlock_state {
+	int num_locks;			/* Total number of locks in system */
+	void __iomem *io_base;		/* Mapped base address */
+};
+
+static int omap_hwspinlock_trylock(struct hwspinlock *lock)
+{
+	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+
+	/* attempt to acquire the lock by reading its value */
+	return (SPINLOCK_NOTTAKEN == readl(omap_lock->addr));
+}
+
+static void omap_hwspinlock_unlock(struct hwspinlock *lock)
+{
+	struct omap_hwspinlock *omap_lock = to_omap_hwspinlock(lock);
+
+	/* release the lock by writing 0 to it */
+	writel(SPINLOCK_NOTTAKEN, omap_lock->addr);
+}
+
+/*
+ * relax the OMAP interconnect while spinning on it.
+ *
+ * The specs recommended that the retry delay time will be
+ * just over half of the time that a requester would be
+ * expected to hold the lock.
+ *
+ * The number below is taken from an hardware specs example,
+ * obviously it is somewhat arbitrary.
+ */
+static void omap_hwspinlock_relax(struct hwspinlock *lock)
+{
+	ndelay(50);
+}
+
+static const struct hwspinlock_ops omap_hwspinlock_ops = {
+	.trylock = omap_hwspinlock_trylock,
+	.unlock = omap_hwspinlock_unlock,
+	.relax = omap_hwspinlock_relax,
+};
+
+static int __devinit omap_hwspinlock_probe(struct platform_device *pdev)
+{
+	struct omap_hwspinlock *omap_lock;
+	struct omap_hwspinlock_state *state;
+	struct hwspinlock *lock;
+	struct resource *res;
+	void __iomem *io_base;
+	int i, ret;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	state = kzalloc(sizeof(*state), GFP_KERNEL);
+	if (!state)
+		return -ENOMEM;
+
+	io_base = ioremap(res->start, resource_size(res));
+	if (!io_base) {
+		ret = -ENOMEM;
+		goto free_state;
+	}
+
+	/* Determine number of locks */
+	i = readl(io_base + SYSSTATUS_OFFSET);
+	i >>= SPINLOCK_NUMLOCKS_BIT_OFFSET;
+
+	/* one of the four lsb's must be set, and nothing else */
+	if (hweight_long(i & 0xf) != 1 || i > 8) {
+		ret = -EINVAL;
+		goto iounmap_base;
+	}
+
+	state->num_locks = i * 32;
+	state->io_base = io_base;
+
+	platform_set_drvdata(pdev, state);
+
+	/*
+	 * runtime PM will make sure the clock of this module is
+	 * enabled iff at least one lock is requested
+	 */
+	pm_runtime_enable(&pdev->dev);
+
+	for (i = 0; i < state->num_locks; i++) {
+		omap_lock = kzalloc(sizeof(*omap_lock), GFP_KERNEL);
+		if (!omap_lock) {
+			ret = -ENOMEM;
+			goto free_locks;
+		}
+
+		omap_lock->lock.dev = &pdev->dev;
+		omap_lock->lock.owner = THIS_MODULE;
+		omap_lock->lock.id = i;
+		omap_lock->lock.ops = &omap_hwspinlock_ops;
+		omap_lock->addr = io_base + LOCK_BASE_OFFSET + sizeof(u32) * i;
+
+		ret = hwspin_lock_register(&omap_lock->lock);
+		if (ret) {
+			kfree(omap_lock);
+			goto free_locks;
+		}
+	}
+
+	return 0;
+
+free_locks:
+	while (--i >= 0) {
+		lock = hwspin_lock_unregister(i);
+		/* this should't happen, but let's give our best effort */
+		if (!lock) {
+			dev_err(&pdev->dev, "%s: cleanups failed\n", __func__);
+			continue;
+		}
+		omap_lock = to_omap_hwspinlock(lock);
+		kfree(omap_lock);
+	}
+	pm_runtime_disable(&pdev->dev);
+iounmap_base:
+	iounmap(io_base);
+free_state:
+	kfree(state);
+	return ret;
+}
+
+static int omap_hwspinlock_remove(struct platform_device *pdev)
+{
+	struct omap_hwspinlock_state *state = platform_get_drvdata(pdev);
+	struct hwspinlock *lock;
+	struct omap_hwspinlock *omap_lock;
+	int i;
+
+	for (i = 0; i < state->num_locks; i++) {
+		lock = hwspin_lock_unregister(i);
+		/* this shouldn't happen at this point. if it does, at least
+		 * don't continue with the remove */
+		if (!lock) {
+			dev_err(&pdev->dev, "%s: failed on %d\n", __func__, i);
+			return -EBUSY;
+		}
+
+		omap_lock = to_omap_hwspinlock(lock);
+		kfree(omap_lock);
+	}
+
+	pm_runtime_disable(&pdev->dev);
+	iounmap(state->io_base);
+	kfree(state);
+
+	return 0;
+}
+
+static struct platform_driver omap_hwspinlock_driver = {
+	.probe		= omap_hwspinlock_probe,
+	.remove		= omap_hwspinlock_remove,
+	.driver		= {
+		.name	= "omap_hwspinlock",
+	},
+};
+
+static int __init omap_hwspinlock_init(void)
+{
+	return platform_driver_register(&omap_hwspinlock_driver);
+}
+/* board init code might need to reserve hwspinlocks for predefined purposes */
+postcore_initcall(omap_hwspinlock_init);
+
+static void __exit omap_hwspinlock_exit(void)
+{
+	platform_driver_unregister(&omap_hwspinlock_driver);
+}
+module_exit(omap_hwspinlock_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Hardware spinlock driver for OMAP");
+MODULE_AUTHOR("Simon Que <sque@ti.com>");
+MODULE_AUTHOR("Hari Kanigeri <h-kanigeri2@ti.com>");
+MODULE_AUTHOR("Ohad Ben-Cohen <ohad@wizery.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/algos/i2c-algo-bit.c linux-libre-2.6.39-gnu/drivers/i2c/algos/i2c-algo-bit.c
--- linux-libre-2.6.38-gnu/drivers/i2c/algos/i2c-algo-bit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/algos/i2c-algo-bit.c	2011-05-19 00:06:34.000000000 -0400
@@ -232,9 +232,17 @@
  * Sanity check for the adapter hardware - check the reaction of
  * the bus lines only if it seems to be idle.
  */
-static int test_bus(struct i2c_algo_bit_data *adap, char *name)
+static int test_bus(struct i2c_adapter *i2c_adap)
 {
-	int scl, sda;
+	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
+	const char *name = i2c_adap->name;
+	int scl, sda, ret;
+
+	if (adap->pre_xfer) {
+		ret = adap->pre_xfer(i2c_adap);
+		if (ret < 0)
+			return -ENODEV;
+	}
 
 	if (adap->getscl == NULL)
 		pr_info("%s: Testing SDA only, SCL is not readable\n", name);
@@ -297,11 +305,19 @@
 		       "while pulling SCL high!\n", name);
 		goto bailout;
 	}
+
+	if (adap->post_xfer)
+		adap->post_xfer(i2c_adap);
+
 	pr_info("%s: Test OK\n", name);
 	return 0;
 bailout:
 	sdahi(adap);
 	sclhi(adap);
+
+	if (adap->post_xfer)
+		adap->post_xfer(i2c_adap);
+
 	return -ENODEV;
 }
 
@@ -607,7 +623,7 @@
 	int ret;
 
 	if (bit_test) {
-		ret = test_bus(bit_adap, adap->name);
+		ret = test_bus(adap);
 		if (ret < 0)
 			return -ENODEV;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/algos/i2c-algo-pca.c linux-libre-2.6.39-gnu/drivers/i2c/algos/i2c-algo-pca.c
--- linux-libre-2.6.38-gnu/drivers/i2c/algos/i2c-algo-pca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/algos/i2c-algo-pca.c	2011-05-19 00:06:34.000000000 -0400
@@ -343,7 +343,7 @@
 
 	ret = curmsg;
  out:
-	DEB1("}}} transfered %d/%d messages. "
+	DEB1("}}} transferred %d/%d messages. "
 	     "status is %#04x. control is %#04x\n",
 	     curmsg, num, pca_status(adap),
 	     pca_get_con(adap));
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ali1535.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ali1535.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ali1535.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ali1535.c	2011-05-19 00:06:34.000000000 -0400
@@ -295,7 +295,7 @@
 	}
 
 	/* Unfortunately the ALI SMB controller maps "no response" and "bus
-	 * collision" into a single bit. No reponse is the usual case so don't
+	 * collision" into a single bit. No response is the usual case so don't
 	 * do a printk.  This means that bus collisions go unreported.
 	 */
 	if (temp & ALI1535_STS_BUSERR) {
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ali15x3.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ali15x3.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ali15x3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ali15x3.c	2011-05-19 00:06:34.000000000 -0400
@@ -318,7 +318,7 @@
 
 	/*
 	  Unfortunately the ALI SMB controller maps "no response" and "bus
-	  collision" into a single bit. No reponse is the usual case so don't
+	  collision" into a single bit. No response is the usual case so don't
 	  do a printk.
 	  This means that bus collisions go unreported.
 	*/
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-cpm.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-cpm.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-cpm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-cpm.c	2011-05-19 00:06:34.000000000 -0400
@@ -634,8 +634,7 @@
 		cpm_muram_free(cpm->i2c_addr);
 }
 
-static int __devinit cpm_i2c_probe(struct platform_device *ofdev,
-			 const struct of_device_id *match)
+static int __devinit cpm_i2c_probe(struct platform_device *ofdev)
 {
 	int result, len;
 	struct cpm_i2c *cpm;
@@ -718,7 +717,7 @@
 
 MODULE_DEVICE_TABLE(of, cpm_i2c_match);
 
-static struct of_platform_driver cpm_i2c_driver = {
+static struct platform_driver cpm_i2c_driver = {
 	.probe		= cpm_i2c_probe,
 	.remove		= __devexit_p(cpm_i2c_remove),
 	.driver = {
@@ -730,12 +729,12 @@
 
 static int __init cpm_i2c_init(void)
 {
-	return of_register_platform_driver(&cpm_i2c_driver);
+	return platform_driver_register(&cpm_i2c_driver);
 }
 
 static void __exit cpm_i2c_exit(void)
 {
-	of_unregister_platform_driver(&cpm_i2c_driver);
+	platform_driver_unregister(&cpm_i2c_driver);
 }
 
 module_init(cpm_i2c_init);
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-davinci.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-davinci.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-davinci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-davinci.c	2011-05-19 00:06:34.000000000 -0400
@@ -355,7 +355,7 @@
 	/*
 	 * Write mode register first as needed for correct behaviour
 	 * on OMAP-L138, but don't set STT yet to avoid a race with XRDY
-	 * occuring before we have loaded DXR
+	 * occurring before we have loaded DXR
 	 */
 	davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-designware.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-designware.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-designware.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-designware.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,7 @@
  * @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: points to an array of messages currently being transferred
  * @msgs_num: the number of elements in msgs
  * @msg_write_idx: the element index of the current tx message in the msgs
  *	array
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-diolan-u2c.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-diolan-u2c.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-diolan-u2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-diolan-u2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,535 @@
+/*
+ * Driver for the Diolan u2c-12 USB-I2C adapter
+ *
+ * Copyright (c) 2010-2011 Ericsson AB
+ *
+ * Derived from:
+ *  i2c-tiny-usb.c
+ *  Copyright (C) 2006-2007 Till Harbaum (Till@Harbaum.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, version 2.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/i2c.h>
+
+#define DRIVER_NAME		"i2c-diolan-u2c"
+
+#define USB_VENDOR_ID_DIOLAN		0x0abf
+#define USB_DEVICE_ID_DIOLAN_U2C	0x3370
+
+#define DIOLAN_OUT_EP		0x02
+#define DIOLAN_IN_EP		0x84
+
+/* commands via USB, must match command ids in the firmware */
+#define CMD_I2C_READ		0x01
+#define CMD_I2C_WRITE		0x02
+#define CMD_I2C_SCAN		0x03	/* Returns list of detected devices */
+#define CMD_I2C_RELEASE_SDA	0x04
+#define CMD_I2C_RELEASE_SCL	0x05
+#define CMD_I2C_DROP_SDA	0x06
+#define CMD_I2C_DROP_SCL	0x07
+#define CMD_I2C_READ_SDA	0x08
+#define CMD_I2C_READ_SCL	0x09
+#define CMD_GET_FW_VERSION	0x0a
+#define CMD_GET_SERIAL		0x0b
+#define CMD_I2C_START		0x0c
+#define CMD_I2C_STOP		0x0d
+#define CMD_I2C_REPEATED_START	0x0e
+#define CMD_I2C_PUT_BYTE	0x0f
+#define CMD_I2C_GET_BYTE	0x10
+#define CMD_I2C_PUT_ACK		0x11
+#define CMD_I2C_GET_ACK		0x12
+#define CMD_I2C_PUT_BYTE_ACK	0x13
+#define CMD_I2C_GET_BYTE_ACK	0x14
+#define CMD_I2C_SET_SPEED	0x1b
+#define CMD_I2C_GET_SPEED	0x1c
+#define CMD_I2C_SET_CLK_SYNC	0x24
+#define CMD_I2C_GET_CLK_SYNC	0x25
+#define CMD_I2C_SET_CLK_SYNC_TO	0x26
+#define CMD_I2C_GET_CLK_SYNC_TO	0x27
+
+#define RESP_OK			0x00
+#define RESP_FAILED		0x01
+#define RESP_BAD_MEMADDR	0x04
+#define RESP_DATA_ERR		0x05
+#define RESP_NOT_IMPLEMENTED	0x06
+#define RESP_NACK		0x07
+#define RESP_TIMEOUT		0x09
+
+#define U2C_I2C_SPEED_FAST	0	/* 400 kHz */
+#define U2C_I2C_SPEED_STD	1	/* 100 kHz */
+#define U2C_I2C_SPEED_2KHZ	242	/* 2 kHz, minimum speed */
+#define U2C_I2C_SPEED(f)	((DIV_ROUND_UP(1000000, (f)) - 10) / 2 + 1)
+
+#define U2C_I2C_FREQ_FAST	400000
+#define U2C_I2C_FREQ_STD	100000
+#define U2C_I2C_FREQ(s)		(1000000 / (2 * (s - 1) + 10))
+
+#define DIOLAN_USB_TIMEOUT	100	/* in ms */
+#define DIOLAN_SYNC_TIMEOUT	20	/* in ms */
+
+#define DIOLAN_OUTBUF_LEN	128
+#define DIOLAN_FLUSH_LEN	(DIOLAN_OUTBUF_LEN - 4)
+#define DIOLAN_INBUF_LEN	256	/* Maximum supported receive length */
+
+/* Structure to hold all of our device specific stuff */
+struct i2c_diolan_u2c {
+	u8 obuffer[DIOLAN_OUTBUF_LEN];	/* output buffer */
+	u8 ibuffer[DIOLAN_INBUF_LEN];	/* input buffer */
+	struct usb_device *usb_dev;	/* the usb device for this device */
+	struct usb_interface *interface;/* the interface for this device */
+	struct i2c_adapter adapter;	/* i2c related things */
+	int olen;			/* Output buffer length */
+	int ocount;			/* Number of enqueued messages */
+};
+
+static uint frequency = U2C_I2C_FREQ_STD;	/* I2C clock frequency in Hz */
+
+module_param(frequency, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(frequency, "I2C clock frequency in hertz");
+
+/* usb layer */
+
+/* Send command to device, and get response. */
+static int diolan_usb_transfer(struct i2c_diolan_u2c *dev)
+{
+	int ret = 0;
+	int actual;
+	int i;
+
+	if (!dev->olen || !dev->ocount)
+		return -EINVAL;
+
+	ret = usb_bulk_msg(dev->usb_dev,
+			   usb_sndbulkpipe(dev->usb_dev, DIOLAN_OUT_EP),
+			   dev->obuffer, dev->olen, &actual,
+			   DIOLAN_USB_TIMEOUT);
+	if (!ret) {
+		for (i = 0; i < dev->ocount; i++) {
+			int tmpret;
+
+			tmpret = usb_bulk_msg(dev->usb_dev,
+					      usb_rcvbulkpipe(dev->usb_dev,
+							      DIOLAN_IN_EP),
+					      dev->ibuffer,
+					      sizeof(dev->ibuffer), &actual,
+					      DIOLAN_USB_TIMEOUT);
+			/*
+			 * Stop command processing if a previous command
+			 * returned an error.
+			 * Note that we still need to retrieve all messages.
+			 */
+			if (ret < 0)
+				continue;
+			ret = tmpret;
+			if (ret == 0 && actual > 0) {
+				switch (dev->ibuffer[actual - 1]) {
+				case RESP_NACK:
+					/*
+					 * Return ENXIO if NACK was received as
+					 * response to the address phase,
+					 * EIO otherwise
+					 */
+					ret = i == 1 ? -ENXIO : -EIO;
+					break;
+				case RESP_TIMEOUT:
+					ret = -ETIMEDOUT;
+					break;
+				case RESP_OK:
+					/* strip off return code */
+					ret = actual - 1;
+					break;
+				default:
+					ret = -EIO;
+					break;
+				}
+			}
+		}
+	}
+	dev->olen = 0;
+	dev->ocount = 0;
+	return ret;
+}
+
+static int diolan_write_cmd(struct i2c_diolan_u2c *dev, bool flush)
+{
+	if (flush || dev->olen >= DIOLAN_FLUSH_LEN)
+		return diolan_usb_transfer(dev);
+	return 0;
+}
+
+/* Send command (no data) */
+static int diolan_usb_cmd(struct i2c_diolan_u2c *dev, u8 command, bool flush)
+{
+	dev->obuffer[dev->olen++] = command;
+	dev->ocount++;
+	return diolan_write_cmd(dev, flush);
+}
+
+/* Send command with one byte of data */
+static int diolan_usb_cmd_data(struct i2c_diolan_u2c *dev, u8 command, u8 data,
+			       bool flush)
+{
+	dev->obuffer[dev->olen++] = command;
+	dev->obuffer[dev->olen++] = data;
+	dev->ocount++;
+	return diolan_write_cmd(dev, flush);
+}
+
+/* Send command with two bytes of data */
+static int diolan_usb_cmd_data2(struct i2c_diolan_u2c *dev, u8 command, u8 d1,
+				u8 d2, bool flush)
+{
+	dev->obuffer[dev->olen++] = command;
+	dev->obuffer[dev->olen++] = d1;
+	dev->obuffer[dev->olen++] = d2;
+	dev->ocount++;
+	return diolan_write_cmd(dev, flush);
+}
+
+/*
+ * Flush input queue.
+ * If we don't do this at startup and the controller has queued up
+ * messages which were not retrieved, it will stop responding
+ * at some point.
+ */
+static void diolan_flush_input(struct i2c_diolan_u2c *dev)
+{
+	int i;
+
+	for (i = 0; i < 10; i++) {
+		int actual = 0;
+		int ret;
+
+		ret = usb_bulk_msg(dev->usb_dev,
+				   usb_rcvbulkpipe(dev->usb_dev, DIOLAN_IN_EP),
+				   dev->ibuffer, sizeof(dev->ibuffer), &actual,
+				   DIOLAN_USB_TIMEOUT);
+		if (ret < 0 || actual == 0)
+			break;
+	}
+	if (i == 10)
+		dev_err(&dev->interface->dev, "Failed to flush input buffer\n");
+}
+
+static int diolan_i2c_start(struct i2c_diolan_u2c *dev)
+{
+	return diolan_usb_cmd(dev, CMD_I2C_START, false);
+}
+
+static int diolan_i2c_repeated_start(struct i2c_diolan_u2c *dev)
+{
+	return diolan_usb_cmd(dev, CMD_I2C_REPEATED_START, false);
+}
+
+static int diolan_i2c_stop(struct i2c_diolan_u2c *dev)
+{
+	return diolan_usb_cmd(dev, CMD_I2C_STOP, true);
+}
+
+static int diolan_i2c_get_byte_ack(struct i2c_diolan_u2c *dev, bool ack,
+				   u8 *byte)
+{
+	int ret;
+
+	ret = diolan_usb_cmd_data(dev, CMD_I2C_GET_BYTE_ACK, ack, true);
+	if (ret > 0)
+		*byte = dev->ibuffer[0];
+	else if (ret == 0)
+		ret = -EIO;
+
+	return ret;
+}
+
+static int diolan_i2c_put_byte_ack(struct i2c_diolan_u2c *dev, u8 byte)
+{
+	return diolan_usb_cmd_data(dev, CMD_I2C_PUT_BYTE_ACK, byte, false);
+}
+
+static int diolan_set_speed(struct i2c_diolan_u2c *dev, u8 speed)
+{
+	return diolan_usb_cmd_data(dev, CMD_I2C_SET_SPEED, speed, true);
+}
+
+/* Enable or disable clock synchronization (stretching) */
+static int diolan_set_clock_synch(struct i2c_diolan_u2c *dev, bool enable)
+{
+	return diolan_usb_cmd_data(dev, CMD_I2C_SET_CLK_SYNC, enable, true);
+}
+
+/* Set clock synchronization timeout in ms */
+static int diolan_set_clock_synch_timeout(struct i2c_diolan_u2c *dev, int ms)
+{
+	int to_val = ms * 10;
+
+	return diolan_usb_cmd_data2(dev, CMD_I2C_SET_CLK_SYNC_TO,
+				    to_val & 0xff, (to_val >> 8) & 0xff, true);
+}
+
+static void diolan_fw_version(struct i2c_diolan_u2c *dev)
+{
+	int ret;
+
+	ret = diolan_usb_cmd(dev, CMD_GET_FW_VERSION, true);
+	if (ret >= 2)
+		dev_info(&dev->interface->dev,
+			 "Diolan U2C firmware version %u.%u\n",
+			 (unsigned int)dev->ibuffer[0],
+			 (unsigned int)dev->ibuffer[1]);
+}
+
+static void diolan_get_serial(struct i2c_diolan_u2c *dev)
+{
+	int ret;
+	u32 serial;
+
+	ret = diolan_usb_cmd(dev, CMD_GET_SERIAL, true);
+	if (ret >= 4) {
+		serial = le32_to_cpu(*(u32 *)dev->ibuffer);
+		dev_info(&dev->interface->dev,
+			 "Diolan U2C serial number %u\n", serial);
+	}
+}
+
+static int diolan_init(struct i2c_diolan_u2c *dev)
+{
+	int speed, ret;
+
+	if (frequency >= 200000) {
+		speed = U2C_I2C_SPEED_FAST;
+		frequency = U2C_I2C_FREQ_FAST;
+	} else if (frequency >= 100000 || frequency == 0) {
+		speed = U2C_I2C_SPEED_STD;
+		frequency = U2C_I2C_FREQ_STD;
+	} else {
+		speed = U2C_I2C_SPEED(frequency);
+		if (speed > U2C_I2C_SPEED_2KHZ)
+			speed = U2C_I2C_SPEED_2KHZ;
+		frequency = U2C_I2C_FREQ(speed);
+	}
+
+	dev_info(&dev->interface->dev,
+		 "Diolan U2C at USB bus %03d address %03d speed %d Hz\n",
+		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum, frequency);
+
+	diolan_flush_input(dev);
+	diolan_fw_version(dev);
+	diolan_get_serial(dev);
+
+	/* Set I2C speed */
+	ret = diolan_set_speed(dev, speed);
+	if (ret < 0)
+		return ret;
+
+	/* Configure I2C clock synchronization */
+	ret = diolan_set_clock_synch(dev, speed != U2C_I2C_SPEED_FAST);
+	if (ret < 0)
+		return ret;
+
+	if (speed != U2C_I2C_SPEED_FAST)
+		ret = diolan_set_clock_synch_timeout(dev, DIOLAN_SYNC_TIMEOUT);
+
+	return ret;
+}
+
+/* i2c layer */
+
+static int diolan_usb_xfer(struct i2c_adapter *adapter, struct i2c_msg *msgs,
+			   int num)
+{
+	struct i2c_diolan_u2c *dev = i2c_get_adapdata(adapter);
+	struct i2c_msg *pmsg;
+	int i, j;
+	int ret, sret;
+
+	ret = diolan_i2c_start(dev);
+	if (ret < 0)
+		return ret;
+
+	for (i = 0; i < num; i++) {
+		pmsg = &msgs[i];
+		if (i) {
+			ret = diolan_i2c_repeated_start(dev);
+			if (ret < 0)
+				goto abort;
+		}
+		if (pmsg->flags & I2C_M_RD) {
+			ret =
+			    diolan_i2c_put_byte_ack(dev, (pmsg->addr << 1) | 1);
+			if (ret < 0)
+				goto abort;
+			for (j = 0; j < pmsg->len; j++) {
+				u8 byte;
+				bool ack = j < pmsg->len - 1;
+
+				/*
+				 * Don't send NACK if this is the first byte
+				 * of a SMBUS_BLOCK message.
+				 */
+				if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN))
+					ack = true;
+
+				ret = diolan_i2c_get_byte_ack(dev, ack, &byte);
+				if (ret < 0)
+					goto abort;
+				/*
+				 * Adjust count if first received byte is length
+				 */
+				if (j == 0 && (pmsg->flags & I2C_M_RECV_LEN)) {
+					if (byte == 0
+					    || byte > I2C_SMBUS_BLOCK_MAX) {
+						ret = -EPROTO;
+						goto abort;
+					}
+					pmsg->len += byte;
+				}
+				pmsg->buf[j] = byte;
+			}
+		} else {
+			ret = diolan_i2c_put_byte_ack(dev, pmsg->addr << 1);
+			if (ret < 0)
+				goto abort;
+			for (j = 0; j < pmsg->len; j++) {
+				ret = diolan_i2c_put_byte_ack(dev,
+							      pmsg->buf[j]);
+				if (ret < 0)
+					goto abort;
+			}
+		}
+	}
+abort:
+	sret = diolan_i2c_stop(dev);
+	if (sret < 0 && ret >= 0)
+		ret = sret;
+	return ret;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 diolan_usb_func(struct i2c_adapter *a)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL |
+	       I2C_FUNC_SMBUS_READ_BLOCK_DATA | I2C_FUNC_SMBUS_BLOCK_PROC_CALL;
+}
+
+static const struct i2c_algorithm diolan_usb_algorithm = {
+	.master_xfer = diolan_usb_xfer,
+	.functionality = diolan_usb_func,
+};
+
+/* device layer */
+
+static const struct usb_device_id diolan_u2c_table[] = {
+	{ USB_DEVICE(USB_VENDOR_ID_DIOLAN, USB_DEVICE_ID_DIOLAN_U2C) },
+	{ }
+};
+
+MODULE_DEVICE_TABLE(usb, diolan_u2c_table);
+
+static void diolan_u2c_free(struct i2c_diolan_u2c *dev)
+{
+	usb_put_dev(dev->usb_dev);
+	kfree(dev);
+}
+
+static int diolan_u2c_probe(struct usb_interface *interface,
+			    const struct usb_device_id *id)
+{
+	struct i2c_diolan_u2c *dev;
+	int ret;
+
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		dev_err(&interface->dev, "no memory for device state\n");
+		ret = -ENOMEM;
+		goto error;
+	}
+
+	dev->usb_dev = usb_get_dev(interface_to_usbdev(interface));
+	dev->interface = interface;
+
+	/* save our data pointer in this interface device */
+	usb_set_intfdata(interface, dev);
+
+	/* setup i2c adapter description */
+	dev->adapter.owner = THIS_MODULE;
+	dev->adapter.class = I2C_CLASS_HWMON;
+	dev->adapter.algo = &diolan_usb_algorithm;
+	i2c_set_adapdata(&dev->adapter, dev);
+	snprintf(dev->adapter.name, sizeof(dev->adapter.name),
+		 DRIVER_NAME " at bus %03d device %03d",
+		 dev->usb_dev->bus->busnum, dev->usb_dev->devnum);
+
+	dev->adapter.dev.parent = &dev->interface->dev;
+
+	/* initialize diolan i2c interface */
+	ret = diolan_init(dev);
+	if (ret < 0) {
+		dev_err(&interface->dev, "failed to initialize adapter\n");
+		goto error_free;
+	}
+
+	/* and finally attach to i2c layer */
+	ret = i2c_add_adapter(&dev->adapter);
+	if (ret < 0) {
+		dev_err(&interface->dev, "failed to add I2C adapter\n");
+		goto error_free;
+	}
+
+	dev_dbg(&interface->dev, "connected " DRIVER_NAME "\n");
+
+	return 0;
+
+error_free:
+	usb_set_intfdata(interface, NULL);
+	diolan_u2c_free(dev);
+error:
+	return ret;
+}
+
+static void diolan_u2c_disconnect(struct usb_interface *interface)
+{
+	struct i2c_diolan_u2c *dev = usb_get_intfdata(interface);
+
+	i2c_del_adapter(&dev->adapter);
+	usb_set_intfdata(interface, NULL);
+	diolan_u2c_free(dev);
+
+	dev_dbg(&interface->dev, "disconnected\n");
+}
+
+static struct usb_driver diolan_u2c_driver = {
+	.name = DRIVER_NAME,
+	.probe = diolan_u2c_probe,
+	.disconnect = diolan_u2c_disconnect,
+	.id_table = diolan_u2c_table,
+};
+
+static int __init diolan_u2c_init(void)
+{
+	/* register this driver with the USB subsystem */
+	return usb_register(&diolan_u2c_driver);
+}
+
+static void __exit diolan_u2c_exit(void)
+{
+	/* deregister this driver with the USB subsystem */
+	usb_deregister(&diolan_u2c_driver);
+}
+
+module_init(diolan_u2c_init);
+module_exit(diolan_u2c_exit);
+
+MODULE_AUTHOR("Guenter Roeck <guenter.roeck@ericsson.com>");
+MODULE_DESCRIPTION(DRIVER_NAME " driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-eg20t.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-eg20t.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-eg20t.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-eg20t.c	2011-05-19 00:06:34.000000000 -0400
@@ -132,6 +132,13 @@
 #define pch_pci_dbg(pdev, fmt, arg...)  \
 	dev_dbg(&pdev->dev, "%s :" fmt, __func__, ##arg)
 
+/*
+Set the number of I2C instance max
+Intel EG20T PCH :		1ch
+OKI SEMICONDUCTOR ML7213 IOH :	2ch
+*/
+#define PCH_I2C_MAX_DEV			2
+
 /**
  * struct i2c_algo_pch_data - for I2C driver functionalities
  * @pch_adapter:		stores the reference to i2c_adapter structure
@@ -156,12 +163,14 @@
  * @pch_data:		stores a list of i2c_algo_pch_data
  * @pch_i2c_suspended:	specifies whether the system is suspended or not
  *			perhaps with more lines and words.
+ * @ch_num:		specifies the number of i2c instance
  *
  * pch_data has as many elements as maximum I2C channels
  */
 struct adapter_info {
-	struct i2c_algo_pch_data pch_data;
+	struct i2c_algo_pch_data pch_data[PCH_I2C_MAX_DEV];
 	bool pch_i2c_suspended;
+	int ch_num;
 };
 
 
@@ -170,8 +179,13 @@
 static wait_queue_head_t pch_event;
 static DEFINE_MUTEX(pch_mutex);
 
+/* Definition for ML7213 by OKI SEMICONDUCTOR */
+#define PCI_VENDOR_ID_ROHM		0x10DB
+#define PCI_DEVICE_ID_ML7213_I2C	0x802D
+
 static struct pci_device_id __devinitdata pch_pcidev_id[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH_I2C)},
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH_I2C),   1, },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ML7213_I2C), 2, },
 	{0,}
 };
 
@@ -212,8 +226,7 @@
 	/* Initialize I2C registers */
 	iowrite32(0x21, p + PCH_I2CNF);
 
-	pch_setbit(adap->pch_base_address, PCH_I2CCTL,
-			  PCH_I2CCTL_I2CMEN);
+	pch_setbit(adap->pch_base_address, PCH_I2CCTL, PCH_I2CCTL_I2CMEN);
 
 	if (pch_i2c_speed != 400)
 		pch_i2c_speed = 100;
@@ -255,7 +268,7 @@
  * @timeout:	waiting time counter (us).
  */
 static s32 pch_i2c_wait_for_bus_idle(struct i2c_algo_pch_data *adap,
-				 s32 timeout)
+				     s32 timeout)
 {
 	void __iomem *p = adap->pch_base_address;
 
@@ -475,8 +488,8 @@
  * @last:	specifies whether last message or not.
  * @first:	specifies whether first message or not.
  */
-s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
-		  u32 last, u32 first)
+static s32 pch_i2c_readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs,
+			     u32 last, u32 first)
 {
 	struct i2c_algo_pch_data *adap = i2c_adap->algo_data;
 
@@ -569,10 +582,10 @@
 }
 
 /**
- * pch_i2c_cb_ch0() - Interrupt handler Call back function
+ * pch_i2c_cb() - Interrupt handler Call back function
  * @adap:	Pointer to struct i2c_algo_pch_data.
  */
-static void pch_i2c_cb_ch0(struct i2c_algo_pch_data *adap)
+static void pch_i2c_cb(struct i2c_algo_pch_data *adap)
 {
 	u32 sts;
 	void __iomem *p = adap->pch_base_address;
@@ -600,24 +613,30 @@
  */
 static irqreturn_t pch_i2c_handler(int irq, void *pData)
 {
-	s32 reg_val;
-
-	struct i2c_algo_pch_data *adap_data = (struct i2c_algo_pch_data *)pData;
-	void __iomem *p = adap_data->pch_base_address;
-	u32 mode = ioread32(p + PCH_I2CMOD) & (BUFFER_MODE | EEPROM_SR_MODE);
+	u32 reg_val;
+	int flag;
+	int i;
+	struct adapter_info *adap_info = pData;
+	void __iomem *p;
+	u32 mode;
 
-	if (mode != NORMAL_MODE) {
-		pch_err(adap_data, "I2C mode is not supported\n");
-		return IRQ_NONE;
+	for (i = 0, flag = 0; i < adap_info->ch_num; i++) {
+		p = adap_info->pch_data[i].pch_base_address;
+		mode = ioread32(p + PCH_I2CMOD);
+		mode &= BUFFER_MODE | EEPROM_SR_MODE;
+		if (mode != NORMAL_MODE) {
+			pch_err(adap_info->pch_data,
+				"I2C-%d mode(%d) is not supported\n", mode, i);
+			continue;
+		}
+		reg_val = ioread32(p + PCH_I2CSR);
+		if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT)) {
+			pch_i2c_cb(&adap_info->pch_data[i]);
+			flag = 1;
+		}
 	}
 
-	reg_val = ioread32(p + PCH_I2CSR);
-	if (reg_val & (I2CMAL_BIT | I2CMCF_BIT | I2CMIF_BIT))
-		pch_i2c_cb_ch0(adap_data);
-	else
-		return IRQ_NONE;
-
-	return IRQ_HANDLED;
+	return flag ? IRQ_HANDLED : IRQ_NONE;
 }
 
 /**
@@ -627,7 +646,7 @@
  * @num:	number of messages.
  */
 static s32 pch_i2c_xfer(struct i2c_adapter *i2c_adap,
-		    struct i2c_msg *msgs, s32 num)
+			struct i2c_msg *msgs, s32 num)
 {
 	struct i2c_msg *pmsg;
 	u32 i = 0;
@@ -710,11 +729,13 @@
 }
 
 static int __devinit pch_i2c_probe(struct pci_dev *pdev,
-			       const struct pci_device_id *id)
+				   const struct pci_device_id *id)
 {
 	void __iomem *base_addr;
-	s32 ret;
+	int ret;
+	int i, j;
 	struct adapter_info *adap_info;
+	struct i2c_adapter *pch_adap;
 
 	pch_pci_dbg(pdev, "Entered.\n");
 
@@ -744,44 +765,48 @@
 		goto err_pci_iomap;
 	}
 
-	adap_info->pch_i2c_suspended = false;
+	/* Set the number of I2C channel instance */
+	adap_info->ch_num = id->driver_data;
 
-	adap_info->pch_data.p_adapter_info = adap_info;
+	for (i = 0; i < adap_info->ch_num; i++) {
+		pch_adap = &adap_info->pch_data[i].pch_adapter;
+		adap_info->pch_i2c_suspended = false;
 
-	adap_info->pch_data.pch_adapter.owner = THIS_MODULE;
-	adap_info->pch_data.pch_adapter.class = I2C_CLASS_HWMON;
-	strcpy(adap_info->pch_data.pch_adapter.name, KBUILD_MODNAME);
-	adap_info->pch_data.pch_adapter.algo = &pch_algorithm;
-	adap_info->pch_data.pch_adapter.algo_data =
-						&adap_info->pch_data;
+		adap_info->pch_data[i].p_adapter_info = adap_info;
 
-	/* (i * 0x80) + base_addr; */
-	adap_info->pch_data.pch_base_address = base_addr;
+		pch_adap->owner = THIS_MODULE;
+		pch_adap->class = I2C_CLASS_HWMON;
+		strcpy(pch_adap->name, KBUILD_MODNAME);
+		pch_adap->algo = &pch_algorithm;
+		pch_adap->algo_data = &adap_info->pch_data[i];
 
-	adap_info->pch_data.pch_adapter.dev.parent = &pdev->dev;
+		/* base_addr + offset; */
+		adap_info->pch_data[i].pch_base_address = base_addr + 0x100 * i;
 
-	ret = i2c_add_adapter(&(adap_info->pch_data.pch_adapter));
+		pch_adap->dev.parent = &pdev->dev;
 
-	if (ret) {
-		pch_pci_err(pdev, "i2c_add_adapter FAILED\n");
-		goto err_i2c_add_adapter;
-	}
+		ret = i2c_add_adapter(pch_adap);
+		if (ret) {
+			pch_pci_err(pdev, "i2c_add_adapter[ch:%d] FAILED\n", i);
+			goto err_i2c_add_adapter;
+		}
 
-	pch_i2c_init(&adap_info->pch_data);
+		pch_i2c_init(&adap_info->pch_data[i]);
+	}
 	ret = request_irq(pdev->irq, pch_i2c_handler, IRQF_SHARED,
-		  KBUILD_MODNAME, &adap_info->pch_data);
+		  KBUILD_MODNAME, adap_info);
 	if (ret) {
 		pch_pci_err(pdev, "request_irq FAILED\n");
-		goto err_request_irq;
+		goto err_i2c_add_adapter;
 	}
 
 	pci_set_drvdata(pdev, adap_info);
 	pch_pci_dbg(pdev, "returns %d.\n", ret);
 	return 0;
 
-err_request_irq:
-	i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
 err_i2c_add_adapter:
+	for (j = 0; j < i; j++)
+		i2c_del_adapter(&adap_info->pch_data[j].pch_adapter);
 	pci_iounmap(pdev, base_addr);
 err_pci_iomap:
 	pci_release_regions(pdev);
@@ -794,17 +819,22 @@
 
 static void __devexit pch_i2c_remove(struct pci_dev *pdev)
 {
+	int i;
 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
 
-	pch_i2c_disbl_int(&adap_info->pch_data);
-	free_irq(pdev->irq, &adap_info->pch_data);
-	i2c_del_adapter(&(adap_info->pch_data.pch_adapter));
+	free_irq(pdev->irq, adap_info);
 
-	if (adap_info->pch_data.pch_base_address) {
-		pci_iounmap(pdev, adap_info->pch_data.pch_base_address);
-		adap_info->pch_data.pch_base_address = 0;
+	for (i = 0; i < adap_info->ch_num; i++) {
+		pch_i2c_disbl_int(&adap_info->pch_data[i]);
+		i2c_del_adapter(&adap_info->pch_data[i].pch_adapter);
 	}
 
+	if (adap_info->pch_data[0].pch_base_address)
+		pci_iounmap(pdev, adap_info->pch_data[0].pch_base_address);
+
+	for (i = 0; i < adap_info->ch_num; i++)
+		adap_info->pch_data[i].pch_base_address = 0;
+
 	pci_set_drvdata(pdev, NULL);
 
 	pci_release_regions(pdev);
@@ -817,17 +847,22 @@
 static int pch_i2c_suspend(struct pci_dev *pdev, pm_message_t state)
 {
 	int ret;
+	int i;
 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
-	void __iomem *p = adap_info->pch_data.pch_base_address;
+	void __iomem *p = adap_info->pch_data[0].pch_base_address;
 
 	adap_info->pch_i2c_suspended = true;
 
-	while ((adap_info->pch_data.pch_i2c_xfer_in_progress)) {
-		/* Wait until all channel transfers are completed */
-		msleep(20);
+	for (i = 0; i < adap_info->ch_num; i++) {
+		while ((adap_info->pch_data[i].pch_i2c_xfer_in_progress)) {
+			/* Wait until all channel transfers are completed */
+			msleep(20);
+		}
 	}
+
 	/* Disable the i2c interrupts */
-	pch_i2c_disbl_int(&adap_info->pch_data);
+	for (i = 0; i < adap_info->ch_num; i++)
+		pch_i2c_disbl_int(&adap_info->pch_data[i]);
 
 	pch_pci_dbg(pdev, "I2CSR = %x I2CBUFSTA = %x I2CESRSTA = %x "
 		"invoked function pch_i2c_disbl_int successfully\n",
@@ -850,6 +885,7 @@
 
 static int pch_i2c_resume(struct pci_dev *pdev)
 {
+	int i;
 	struct adapter_info *adap_info = pci_get_drvdata(pdev);
 
 	pci_set_power_state(pdev, PCI_D0);
@@ -862,7 +898,8 @@
 
 	pci_enable_wake(pdev, PCI_D3hot, 0);
 
-	pch_i2c_init(&adap_info->pch_data);
+	for (i = 0; i < adap_info->ch_num; i++)
+		pch_i2c_init(&adap_info->pch_data[i]);
 
 	adap_info->pch_i2c_suspended = false;
 
@@ -894,7 +931,7 @@
 }
 module_exit(pch_pci_exit);
 
-MODULE_DESCRIPTION("PCH I2C PCI Driver");
+MODULE_DESCRIPTION("Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH I2C Driver");
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tomoya MORINAGA. <tomoya-linux@dsn.okisemi.com>");
 module_param(pch_i2c_speed, int, (S_IRUSR | S_IWUSR));
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-elektor.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-elektor.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-elektor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-elektor.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
 /* With some changes from KyÃ¶sti MÃ¤lkki <kmalkki@cc.hut.fi> and even
    Frodo Looijaard <frodol@dds.nl> */
 
-/* Partialy rewriten by Oleg I. Vdovikin for mmapped support of
+/* Partially rewriten by Oleg I. Vdovikin for mmapped support of
    for Alpha Processor Inc. UP-2000(+) boards */
 
 #include <linux/kernel.h>
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-i801.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-i801.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-i801.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-i801.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,11 +44,12 @@
   ICH10                 0x3a30     32     hard     yes     yes     yes
   ICH10                 0x3a60     32     hard     yes     yes     yes
   5/3400 Series (PCH)   0x3b30     32     hard     yes     yes     yes
-  Cougar Point (PCH)    0x1c22     32     hard     yes     yes     yes
+  6 Series (PCH)        0x1c22     32     hard     yes     yes     yes
   Patsburg (PCH)        0x1d22     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d70     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d71     32     hard     yes     yes     yes
   Patsburg (PCH) IDF    0x1d72     32     hard     yes     yes     yes
+  DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
@@ -95,7 +96,7 @@
 #define SMBHSTCFG_SMB_SMI_EN	2
 #define SMBHSTCFG_I2C_EN	4
 
-/* Auxillary control register bits, ICH4+ only */
+/* Auxiliary control register bits, ICH4+ only */
 #define SMBAUXCTL_CRC		1
 #define SMBAUXCTL_E32B		2
 
@@ -133,10 +134,15 @@
 				 SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
 				 SMBHSTSTS_INTR)
 
+/* Older devices have their ID defined in <linux/pci_ids.h> */
+#define PCI_DEVICE_ID_INTEL_COUGARPOINT_SMBUS	0x1c22
+#define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS	0x1d22
 /* Patsburg also has three 'Integrated Device Function' SMBus controllers */
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0	0x1d70
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1	0x1d71
 #define PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2	0x1d72
+#define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS	0x2330
+#define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS	0x3b30
 
 struct i801_priv {
 	struct i2c_adapter adapter;
@@ -621,6 +627,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF0) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF1) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PATSBURG_SMBUS_IDF2) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
 	{ 0, }
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ibm_iic.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ibm_iic.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ibm_iic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ibm_iic.c	2011-05-19 00:06:34.000000000 -0400
@@ -494,7 +494,7 @@
 		if (unlikely(ret < 0))
 			break;
 		else if (unlikely(ret != count)){
-			DBG("%d: xfer_bytes, requested %d, transfered %d\n",
+			DBG("%d: xfer_bytes, requested %d, transferred %d\n",
 				dev->idx, count, ret);
 
 			/* If it's not a last part of xfer, abort it */
@@ -593,7 +593,7 @@
 	if (unlikely((in_8(&iic->extsts) & EXTSTS_BCS_MASK) != EXTSTS_BCS_FREE)){
 		DBG("%d: iic_xfer, bus is not free\n", dev->idx);
 
-		/* Usually it means something serious has happend.
+		/* Usually it means something serious has happened.
 		 * We *cannot* have unfinished previous transfer
 		 * so it doesn't make any sense to try to stop it.
 		 * Probably we were not able to recover from the
@@ -691,8 +691,7 @@
 /*
  * Register single IIC interface
  */
-static int __devinit iic_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit iic_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct ibm_iic_private *dev;
@@ -806,7 +805,7 @@
 	{}
 };
 
-static struct of_platform_driver ibm_iic_driver = {
+static struct platform_driver ibm_iic_driver = {
 	.driver = {
 		.name = "ibm-iic",
 		.owner = THIS_MODULE,
@@ -818,12 +817,12 @@
 
 static int __init iic_init(void)
 {
-	return of_register_platform_driver(&ibm_iic_driver);
+	return platform_driver_register(&ibm_iic_driver);
 }
 
 static void __exit iic_exit(void)
 {
-	of_unregister_platform_driver(&ibm_iic_driver);
+	platform_driver_unregister(&ibm_iic_driver);
 }
 
 module_init(iic_init);
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-intel-mid.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-intel-mid.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-intel-mid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-intel-mid.c	2011-05-19 00:06:34.000000000 -0400
@@ -170,8 +170,8 @@
 /* Raw Interrupt Status Register */
 #define IC_RAW_INTR_STAT	0x34		/* Read Only */
 #define GEN_CALL		(1 << 11)	/* General call */
-#define START_DET		(1 << 10)	/* (RE)START occured */
-#define STOP_DET		(1 << 9)	/* STOP occured */
+#define START_DET		(1 << 10)	/* (RE)START occurred */
+#define STOP_DET		(1 << 9)	/* STOP occurred */
 #define ACTIVITY		(1 << 8)	/* Bus busy */
 #define RX_DONE			(1 << 7)	/* Not used in Master mode */
 #define	TX_ABRT			(1 << 6)	/* Transmit Abort */
@@ -375,7 +375,7 @@
  * I2C should be disabled prior to other register operation. If failed, an
  * errno is returned. Mask and Clear all interrpts, this should be done at
  * first.  Set common registers which will not be modified during normal
- * transfers, including: controll register, FIFO threshold and clock freq.
+ * transfers, including: control register, FIFO threshold and clock freq.
  * Check APB data width at last.
  */
 static int intel_mid_i2c_hwinit(struct intel_mid_i2c_private *i2c)
@@ -455,7 +455,7 @@
  *
  * By reading register IC_TX_ABRT_SOURCE, various transfer errors can be
  * distingushed. At present, no circumstances have been found out that
- * multiple errors would be occured simutaneously, so we simply use the
+ * multiple errors would be occurred simutaneously, so we simply use the
  * register value directly.
  *
  * At last the error bits are cleared. (Note clear ABRT_SBYTE_NORSTRT bit need
@@ -469,7 +469,7 @@
 
 	/* Single transfer error check:
 	 * According to databook, TX/RX FIFOs would be flushed when
-	 * the abort interrupt occured.
+	 * the abort interrupt occurred.
 	 */
 	if (abort & ABRT_MASTER_DIS)
 		dev_err(&adap->dev,
@@ -569,7 +569,7 @@
  * Return Values:
  * 0	if the read transfer succeeds
  * -ETIMEDOUT	if we cannot read the "raw" interrupt register
- * -EINVAL	if a transfer abort occured
+ * -EINVAL	if a transfer abort occurred
  *
  * For every byte, a "WRITE" command will be loaded into IC_DATA_CMD prior to
  * data transfer. The actual "write" operation will be performed when the
@@ -697,7 +697,7 @@
  * @num: number of i2c_msg
  *
  * Return Values:
- * +		number of messages transfered
+ * +		number of messages transferred
  * -ETIMEDOUT	If cannot disable I2C controller or read IC_STATUS
  * -EINVAL	If the address in i2c_msg is invalid
  *
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-isch.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-isch.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-isch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-isch.c	2011-05-19 00:06:34.000000000 -0400
@@ -141,7 +141,7 @@
  * This is the main access entry for i2c-sch access
  * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write
  * (0 for read and 1 for write), size is i2c transaction type and data is the
- * union of transaction for data to be transfered or data read from bus.
+ * union of transaction for data to be transferred or data read from bus.
  * return 0 for success and others for failure.
  */
 static s32 sch_access(struct i2c_adapter *adap, u16 addr,
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-mpc.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-mpc.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-mpc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-mpc.c	2011-05-19 00:06:34.000000000 -0400
@@ -560,15 +560,20 @@
 	.timeout = HZ,
 };
 
-static int __devinit fsl_i2c_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static const struct of_device_id mpc_i2c_of_match[];
+static int __devinit fsl_i2c_probe(struct platform_device *op)
 {
+	const struct of_device_id *match;
 	struct mpc_i2c *i2c;
 	const u32 *prop;
 	u32 clock = MPC_I2C_CLOCK_LEGACY;
 	int result = 0;
 	int plen;
 
+	match = of_match_device(mpc_i2c_of_match, &op->dev);
+	if (!match)
+		return -EINVAL;
+
 	i2c = kzalloc(sizeof(*i2c), GFP_KERNEL);
 	if (!i2c)
 		return -ENOMEM;
@@ -700,7 +705,7 @@
 MODULE_DEVICE_TABLE(of, mpc_i2c_of_match);
 
 /* Structure for a device driver */
-static struct of_platform_driver mpc_i2c_driver = {
+static struct platform_driver mpc_i2c_driver = {
 	.probe		= fsl_i2c_probe,
 	.remove		= __devexit_p(fsl_i2c_remove),
 	.driver = {
@@ -712,18 +717,12 @@
 
 static int __init fsl_i2c_init(void)
 {
-	int rv;
-
-	rv = of_register_platform_driver(&mpc_i2c_driver);
-	if (rv)
-		printk(KERN_ERR DRV_NAME
-		       " of_register_platform_driver failed (%i)\n", rv);
-	return rv;
+	return platform_driver_register(&mpc_i2c_driver);
 }
 
 static void __exit fsl_i2c_exit(void)
 {
-	of_unregister_platform_driver(&mpc_i2c_driver);
+	platform_driver_unregister(&mpc_i2c_driver);
 }
 
 module_init(fsl_i2c_init);
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-mxs.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-mxs.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-mxs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-mxs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,412 @@
+/*
+ * Freescale MXS I2C bus driver
+ *
+ * Copyright (C) 2011 Wolfram Sang, Pengutronix e.K.
+ *
+ * based on a (non-working) driver which was:
+ *
+ * Copyright (C) 2009-2010 Freescale Semiconductor, Inc. All Rights Reserved.
+ *
+ * TODO: add dma-support if platform-support for it is available
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/slab.h>
+#include <linux/device.h>
+#include <linux/module.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/jiffies.h>
+#include <linux/io.h>
+
+#include <mach/common.h>
+
+#define DRIVER_NAME "mxs-i2c"
+
+#define MXS_I2C_CTRL0		(0x00)
+#define MXS_I2C_CTRL0_SET	(0x04)
+
+#define MXS_I2C_CTRL0_SFTRST			0x80000000
+#define MXS_I2C_CTRL0_SEND_NAK_ON_LAST		0x02000000
+#define MXS_I2C_CTRL0_RETAIN_CLOCK		0x00200000
+#define MXS_I2C_CTRL0_POST_SEND_STOP		0x00100000
+#define MXS_I2C_CTRL0_PRE_SEND_START		0x00080000
+#define MXS_I2C_CTRL0_MASTER_MODE		0x00020000
+#define MXS_I2C_CTRL0_DIRECTION			0x00010000
+#define MXS_I2C_CTRL0_XFER_COUNT(v)		((v) & 0x0000FFFF)
+
+#define MXS_I2C_CTRL1		(0x40)
+#define MXS_I2C_CTRL1_SET	(0x44)
+#define MXS_I2C_CTRL1_CLR	(0x48)
+
+#define MXS_I2C_CTRL1_BUS_FREE_IRQ		0x80
+#define MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ	0x40
+#define MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ		0x20
+#define MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ	0x10
+#define MXS_I2C_CTRL1_EARLY_TERM_IRQ		0x08
+#define MXS_I2C_CTRL1_MASTER_LOSS_IRQ		0x04
+#define MXS_I2C_CTRL1_SLAVE_STOP_IRQ		0x02
+#define MXS_I2C_CTRL1_SLAVE_IRQ			0x01
+
+#define MXS_I2C_IRQ_MASK	(MXS_I2C_CTRL1_DATA_ENGINE_CMPLT_IRQ | \
+				 MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ | \
+				 MXS_I2C_CTRL1_EARLY_TERM_IRQ | \
+				 MXS_I2C_CTRL1_MASTER_LOSS_IRQ | \
+				 MXS_I2C_CTRL1_SLAVE_STOP_IRQ | \
+				 MXS_I2C_CTRL1_SLAVE_IRQ)
+
+#define MXS_I2C_QUEUECTRL	(0x60)
+#define MXS_I2C_QUEUECTRL_SET	(0x64)
+#define MXS_I2C_QUEUECTRL_CLR	(0x68)
+
+#define MXS_I2C_QUEUECTRL_QUEUE_RUN		0x20
+#define MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE	0x04
+
+#define MXS_I2C_QUEUESTAT	(0x70)
+#define MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY        0x00002000
+
+#define MXS_I2C_QUEUECMD	(0x80)
+
+#define MXS_I2C_QUEUEDATA	(0x90)
+
+#define MXS_I2C_DATA		(0xa0)
+
+
+#define MXS_CMD_I2C_SELECT	(MXS_I2C_CTRL0_RETAIN_CLOCK |	\
+				 MXS_I2C_CTRL0_PRE_SEND_START |	\
+				 MXS_I2C_CTRL0_MASTER_MODE |	\
+				 MXS_I2C_CTRL0_DIRECTION |	\
+				 MXS_I2C_CTRL0_XFER_COUNT(1))
+
+#define MXS_CMD_I2C_WRITE	(MXS_I2C_CTRL0_PRE_SEND_START |	\
+				 MXS_I2C_CTRL0_MASTER_MODE |	\
+				 MXS_I2C_CTRL0_DIRECTION)
+
+#define MXS_CMD_I2C_READ	(MXS_I2C_CTRL0_SEND_NAK_ON_LAST | \
+				 MXS_I2C_CTRL0_MASTER_MODE)
+
+/**
+ * struct mxs_i2c_dev - per device, private MXS-I2C data
+ *
+ * @dev: driver model device node
+ * @regs: IO registers pointer
+ * @cmd_complete: completion object for transaction wait
+ * @cmd_err: error code for last transaction
+ * @adapter: i2c subsystem adapter node
+ */
+struct mxs_i2c_dev {
+	struct device *dev;
+	void __iomem *regs;
+	struct completion cmd_complete;
+	u32 cmd_err;
+	struct i2c_adapter adapter;
+};
+
+/*
+ * TODO: check if calls to here are really needed. If not, we could get rid of
+ * mxs_reset_block and the mach-dependency. Needs an I2C analyzer, probably.
+ */
+static void mxs_i2c_reset(struct mxs_i2c_dev *i2c)
+{
+	mxs_reset_block(i2c->regs);
+	writel(MXS_I2C_IRQ_MASK << 8, i2c->regs + MXS_I2C_CTRL1_SET);
+	writel(MXS_I2C_QUEUECTRL_PIO_QUEUE_MODE,
+			i2c->regs + MXS_I2C_QUEUECTRL_SET);
+}
+
+static void mxs_i2c_pioq_setup_read(struct mxs_i2c_dev *i2c, u8 addr, int len,
+					int flags)
+{
+	u32 data;
+
+	writel(MXS_CMD_I2C_SELECT, i2c->regs + MXS_I2C_QUEUECMD);
+
+	data = (addr << 1) | I2C_SMBUS_READ;
+	writel(data, i2c->regs + MXS_I2C_DATA);
+
+	data = MXS_CMD_I2C_READ | MXS_I2C_CTRL0_XFER_COUNT(len) | flags;
+	writel(data, i2c->regs + MXS_I2C_QUEUECMD);
+}
+
+static void mxs_i2c_pioq_setup_write(struct mxs_i2c_dev *i2c,
+				    u8 addr, u8 *buf, int len, int flags)
+{
+	u32 data;
+	int i, shifts_left;
+
+	data = MXS_CMD_I2C_WRITE | MXS_I2C_CTRL0_XFER_COUNT(len + 1) | flags;
+	writel(data, i2c->regs + MXS_I2C_QUEUECMD);
+
+	/*
+	 * We have to copy the slave address (u8) and buffer (arbitrary number
+	 * of u8) into the data register (u32). To achieve that, the u8 are put
+	 * into the MSBs of 'data' which is then shifted for the next u8. When
+	 * appropriate, 'data' is written to MXS_I2C_DATA. So, the first u32
+	 * looks like this:
+	 *
+	 *  3          2          1          0
+	 * 10987654|32109876|54321098|76543210
+	 * --------+--------+--------+--------
+	 * buffer+2|buffer+1|buffer+0|slave_addr
+	 */
+
+	data = ((addr << 1) | I2C_SMBUS_WRITE) << 24;
+
+	for (i = 0; i < len; i++) {
+		data >>= 8;
+		data |= buf[i] << 24;
+		if ((i & 3) == 2)
+			writel(data, i2c->regs + MXS_I2C_DATA);
+	}
+
+	/* Write out the remaining bytes if any */
+	shifts_left = 24 - (i & 3) * 8;
+	if (shifts_left)
+		writel(data >> shifts_left, i2c->regs + MXS_I2C_DATA);
+}
+
+/*
+ * TODO: should be replaceable with a waitqueue and RD_QUEUE_IRQ (setting the
+ * rd_threshold to 1). Couldn't get this to work, though.
+ */
+static int mxs_i2c_wait_for_data(struct mxs_i2c_dev *i2c)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+	while (readl(i2c->regs + MXS_I2C_QUEUESTAT)
+			& MXS_I2C_QUEUESTAT_RD_QUEUE_EMPTY) {
+			if (time_after(jiffies, timeout))
+				return -ETIMEDOUT;
+			cond_resched();
+	}
+
+	return 0;
+}
+
+static int mxs_i2c_finish_read(struct mxs_i2c_dev *i2c, u8 *buf, int len)
+{
+	u32 data;
+	int i;
+
+	for (i = 0; i < len; i++) {
+		if ((i & 3) == 0) {
+			if (mxs_i2c_wait_for_data(i2c))
+				return -ETIMEDOUT;
+			data = readl(i2c->regs + MXS_I2C_QUEUEDATA);
+		}
+		buf[i] = data & 0xff;
+		data >>= 8;
+	}
+
+	return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int mxs_i2c_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg,
+				int stop)
+{
+	struct mxs_i2c_dev *i2c = i2c_get_adapdata(adap);
+	int ret;
+	int flags;
+
+	init_completion(&i2c->cmd_complete);
+
+	dev_dbg(i2c->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+		msg->addr, msg->len, msg->flags, stop);
+
+	if (msg->len == 0)
+		return -EINVAL;
+
+	flags = stop ? MXS_I2C_CTRL0_POST_SEND_STOP : 0;
+
+	if (msg->flags & I2C_M_RD)
+		mxs_i2c_pioq_setup_read(i2c, msg->addr, msg->len, flags);
+	else
+		mxs_i2c_pioq_setup_write(i2c, msg->addr, msg->buf, msg->len,
+					flags);
+
+	writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+			i2c->regs + MXS_I2C_QUEUECTRL_SET);
+
+	ret = wait_for_completion_timeout(&i2c->cmd_complete,
+						msecs_to_jiffies(1000));
+	if (ret == 0)
+		goto timeout;
+
+	if ((!i2c->cmd_err) && (msg->flags & I2C_M_RD)) {
+		ret = mxs_i2c_finish_read(i2c, msg->buf, msg->len);
+		if (ret)
+			goto timeout;
+	}
+
+	if (i2c->cmd_err == -ENXIO)
+		mxs_i2c_reset(i2c);
+
+	dev_dbg(i2c->dev, "Done with err=%d\n", i2c->cmd_err);
+
+	return i2c->cmd_err;
+
+timeout:
+	dev_dbg(i2c->dev, "Timeout!\n");
+	mxs_i2c_reset(i2c);
+	return -ETIMEDOUT;
+}
+
+static int mxs_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+			int num)
+{
+	int i;
+	int err;
+
+	for (i = 0; i < num; i++) {
+		err = mxs_i2c_xfer_msg(adap, &msgs[i], i == (num - 1));
+		if (err)
+			return err;
+	}
+
+	return num;
+}
+
+static u32 mxs_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static irqreturn_t mxs_i2c_isr(int this_irq, void *dev_id)
+{
+	struct mxs_i2c_dev *i2c = dev_id;
+	u32 stat = readl(i2c->regs + MXS_I2C_CTRL1) & MXS_I2C_IRQ_MASK;
+
+	if (!stat)
+		return IRQ_NONE;
+
+	if (stat & MXS_I2C_CTRL1_NO_SLAVE_ACK_IRQ)
+		i2c->cmd_err = -ENXIO;
+	else if (stat & (MXS_I2C_CTRL1_EARLY_TERM_IRQ |
+		    MXS_I2C_CTRL1_MASTER_LOSS_IRQ |
+		    MXS_I2C_CTRL1_SLAVE_STOP_IRQ | MXS_I2C_CTRL1_SLAVE_IRQ))
+		/* MXS_I2C_CTRL1_OVERSIZE_XFER_TERM_IRQ is only for slaves */
+		i2c->cmd_err = -EIO;
+	else
+		i2c->cmd_err = 0;
+
+	complete(&i2c->cmd_complete);
+
+	writel(stat, i2c->regs + MXS_I2C_CTRL1_CLR);
+	return IRQ_HANDLED;
+}
+
+static const struct i2c_algorithm mxs_i2c_algo = {
+	.master_xfer = mxs_i2c_xfer,
+	.functionality = mxs_i2c_func,
+};
+
+static int __devinit mxs_i2c_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct mxs_i2c_dev *i2c;
+	struct i2c_adapter *adap;
+	struct resource *res;
+	resource_size_t res_size;
+	int err, irq;
+
+	i2c = devm_kzalloc(dev, sizeof(struct mxs_i2c_dev), GFP_KERNEL);
+	if (!i2c)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENOENT;
+
+	res_size = resource_size(res);
+	if (!devm_request_mem_region(dev, res->start, res_size, res->name))
+		return -EBUSY;
+
+	i2c->regs = devm_ioremap_nocache(dev, res->start, res_size);
+	if (!i2c->regs)
+		return -EBUSY;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	err = devm_request_irq(dev, irq, mxs_i2c_isr, 0, dev_name(dev), i2c);
+	if (err)
+		return err;
+
+	i2c->dev = dev;
+	platform_set_drvdata(pdev, i2c);
+
+	/* Do reset to enforce correct startup after pinmuxing */
+	mxs_i2c_reset(i2c);
+
+	adap = &i2c->adapter;
+	strlcpy(adap->name, "MXS I2C adapter", sizeof(adap->name));
+	adap->owner = THIS_MODULE;
+	adap->algo = &mxs_i2c_algo;
+	adap->dev.parent = dev;
+	adap->nr = pdev->id;
+	i2c_set_adapdata(adap, i2c);
+	err = i2c_add_numbered_adapter(adap);
+	if (err) {
+		dev_err(dev, "Failed to add adapter (%d)\n", err);
+		writel(MXS_I2C_CTRL0_SFTRST,
+				i2c->regs + MXS_I2C_CTRL0_SET);
+		return err;
+	}
+
+	return 0;
+}
+
+static int __devexit mxs_i2c_remove(struct platform_device *pdev)
+{
+	struct mxs_i2c_dev *i2c = platform_get_drvdata(pdev);
+	int ret;
+
+	ret = i2c_del_adapter(&i2c->adapter);
+	if (ret)
+		return -EBUSY;
+
+	writel(MXS_I2C_QUEUECTRL_QUEUE_RUN,
+			i2c->regs + MXS_I2C_QUEUECTRL_CLR);
+	writel(MXS_I2C_CTRL0_SFTRST, i2c->regs + MXS_I2C_CTRL0_SET);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+static struct platform_driver mxs_i2c_driver = {
+	.driver = {
+		   .name = DRIVER_NAME,
+		   .owner = THIS_MODULE,
+		   },
+	.remove = __devexit_p(mxs_i2c_remove),
+};
+
+static int __init mxs_i2c_init(void)
+{
+	return platform_driver_probe(&mxs_i2c_driver, mxs_i2c_probe);
+}
+subsys_initcall(mxs_i2c_init);
+
+static void __exit mxs_i2c_exit(void)
+{
+	platform_driver_unregister(&mxs_i2c_driver);
+}
+module_exit(mxs_i2c_exit);
+
+MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>");
+MODULE_DESCRIPTION("MXS I2C Bus Driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-nomadik.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-nomadik.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-nomadik.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-nomadik.c	2011-05-19 00:06:34.000000000 -0400
@@ -126,9 +126,9 @@
 /**
  * struct i2c_nmk_client - client specific data
  * @slave_adr: 7-bit slave address
- * @count: no. bytes to be transfered
+ * @count: no. bytes to be transferred
  * @buffer: client data buffer
- * @xfer_bytes: bytes transfered till now
+ * @xfer_bytes: bytes transferred till now
  * @operation: current I2C operation
  */
 struct i2c_nmk_client {
@@ -330,7 +330,7 @@
 	 * slsu defines the data setup time after SCL clock
 	 * stretching in terms of i2c clk cycles. The
 	 * needed setup time for the three modes are 250ns,
-	 * 100ns, 10ns repectively thus leading to the values
+	 * 100ns, 10ns respectively thus leading to the values
 	 * of 14, 6, 2 for a 48 MHz i2c clk.
 	 */
 	writel(dev->cfg.slsu << 16, dev->virtbase + I2C_SCR);
@@ -364,7 +364,7 @@
 	/*
 	 * set the speed mode. Currently we support
 	 * only standard and fast mode of operation
-	 * TODO - support for fast mode plus (upto 1Mb/s)
+	 * TODO - support for fast mode plus (up to 1Mb/s)
 	 * and high speed (up to 3.4 Mb/s)
 	 */
 	if (dev->cfg.sm > I2C_FREQ_MODE_FAST) {
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ocores.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ocores.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-ocores.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-ocores.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,6 +49,7 @@
 #include <linux/init.h>
 #include <linux/errno.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
@@ -305,7 +306,7 @@
 		return -EIO;
 	}
 
-	pdata = pdev->dev.platform_data;
+	pdata = mfd_get_data(pdev);
 	if (pdata) {
 		i2c->regstep = pdata->regstep;
 		i2c->clock_khz = pdata->clock_khz;
@@ -330,9 +331,7 @@
 	i2c->adap = ocores_adapter;
 	i2c_set_adapdata(&i2c->adap, i2c);
 	i2c->adap.dev.parent = &pdev->dev;
-#ifdef CONFIG_OF
 	i2c->adap.dev.of_node = pdev->dev.of_node;
-#endif
 
 	/* add i2c adapter to i2c tree */
 	ret = i2c_add_adapter(&i2c->adap);
@@ -390,15 +389,11 @@
 #define ocores_i2c_resume	NULL
 #endif
 
-#ifdef CONFIG_OF
 static struct of_device_id ocores_i2c_match[] = {
-        {
-                .compatible = "opencores,i2c-ocores",
-        },
-        {},
+	{ .compatible = "opencores,i2c-ocores", },
+	{},
 };
 MODULE_DEVICE_TABLE(of, ocores_i2c_match);
-#endif
 
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:ocores-i2c");
@@ -411,9 +406,7 @@
 	.driver  = {
 		.owner = THIS_MODULE,
 		.name = "ocores-i2c",
-#ifdef CONFIG_OF
-                .of_match_table = ocores_i2c_match,
-#endif
+		.of_match_table = ocores_i2c_match,
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-parport.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-parport.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-parport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-parport.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /* ------------------------------------------------------------------------ *
  * i2c-parport.c I2C bus over parallel port                                 *
  * ------------------------------------------------------------------------ *
-   Copyright (C) 2003-2010 Jean Delvare <khali@linux-fr.org>
+   Copyright (C) 2003-2011 Jean Delvare <khali@linux-fr.org>
    
    Based on older i2c-philips-par.c driver
    Copyright (C) 1995-2000 Simon G. Vogl
@@ -33,6 +33,8 @@
 #include <linux/i2c-algo-bit.h>
 #include <linux/i2c-smbus.h>
 #include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
 #include "i2c-parport.h"
 
 /* ----- Device list ------------------------------------------------------ */
@@ -43,10 +45,11 @@
 	struct i2c_algo_bit_data algo_data;
 	struct i2c_smbus_alert_setup alert_data;
 	struct i2c_client *ara;
-	struct i2c_par *next;
+	struct list_head node;
 };
 
-static struct i2c_par *adapter_list;
+static LIST_HEAD(adapter_list);
+static DEFINE_MUTEX(adapter_list_lock);
 
 /* ----- Low-level parallel port access ----------------------------------- */
 
@@ -228,8 +231,9 @@
 	}
 
 	/* Add the new adapter to the list */
-	adapter->next = adapter_list;
-	adapter_list = adapter;
+	mutex_lock(&adapter_list_lock);
+	list_add_tail(&adapter->node, &adapter_list);
+	mutex_unlock(&adapter_list_lock);
         return;
 
 ERROR1:
@@ -241,11 +245,11 @@
 
 static void i2c_parport_detach (struct parport *port)
 {
-	struct i2c_par *adapter, *prev;
+	struct i2c_par *adapter, *_n;
 
 	/* Walk the list */
-	for (prev = NULL, adapter = adapter_list; adapter;
-	     prev = adapter, adapter = adapter->next) {
+	mutex_lock(&adapter_list_lock);
+	list_for_each_entry_safe(adapter, _n, &adapter_list, node) {
 		if (adapter->pdev->port == port) {
 			if (adapter->ara) {
 				parport_disable_irq(port);
@@ -259,14 +263,11 @@
 				
 			parport_release(adapter->pdev);
 			parport_unregister_device(adapter->pdev);
-			if (prev)
-				prev->next = adapter->next;
-			else
-				adapter_list = adapter->next;
+			list_del(&adapter->node);
 			kfree(adapter);
-			return;
 		}
 	}
+	mutex_unlock(&adapter_list_lock);
 }
 
 static struct parport_driver i2c_parport_driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-pnx.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-pnx.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-pnx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-pnx.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
 		jiffies, expires);
 
 	timer->expires = jiffies + expires;
-	timer->data = (unsigned long)&alg_data;
+	timer->data = (unsigned long)alg_data;
 
 	add_timer(timer);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-puv3.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-puv3.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-puv3.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-puv3.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,306 @@
+/*
+ * I2C driver for PKUnity-v3 SoC
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2010 Guan Xuetao
+ *
+ * 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/err.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/clk.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <mach/hardware.h>
+
+/*
+ * Poll the i2c status register until the specified bit is set.
+ * Returns 0 if timed out (100 msec).
+ */
+static short poll_status(unsigned long bit)
+{
+	int loop_cntr = 1000;
+
+	if (bit & I2C_STATUS_TFNF) {
+		do {
+			udelay(10);
+		} while (!(readl(I2C_STATUS) & bit) && (--loop_cntr > 0));
+	} else {
+		/* RXRDY handler */
+		do {
+			if (readl(I2C_TAR) == I2C_TAR_EEPROM)
+				msleep(20);
+			else
+				udelay(10);
+		} while (!(readl(I2C_RXFLR) & 0xf) && (--loop_cntr > 0));
+	}
+
+	return (loop_cntr > 0);
+}
+
+static int xfer_read(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+	int i2c_reg = *buf;
+
+	/* Read data */
+	while (length--) {
+		if (!poll_status(I2C_STATUS_TFNF)) {
+			dev_dbg(&adap->dev, "Tx FIFO Not Full timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		/* send addr */
+		writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
+
+		/* get ready to next write */
+		i2c_reg++;
+
+		/* send read CMD */
+		writel(I2C_DATACMD_READ, I2C_DATACMD);
+
+		/* wait until the Rx FIFO have available */
+		if (!poll_status(I2C_STATUS_RFNE)) {
+			dev_dbg(&adap->dev, "RXRDY timeout\n");
+			return -ETIMEDOUT;
+		}
+
+		/* read the data to buf */
+		*buf = (readl(I2C_DATACMD) & I2C_DATACMD_DAT_MASK);
+		buf++;
+	}
+
+	return 0;
+}
+
+static int xfer_write(struct i2c_adapter *adap, unsigned char *buf, int length)
+{
+	int i2c_reg = *buf;
+
+	/* Do nothing but storing the reg_num to a static variable */
+	if (i2c_reg == -1) {
+		printk(KERN_WARNING "Error i2c reg\n");
+		return -ETIMEDOUT;
+	}
+
+	if (length == 1)
+		return 0;
+
+	buf++;
+	length--;
+	while (length--) {
+		/* send addr */
+		writel(i2c_reg | I2C_DATACMD_WRITE, I2C_DATACMD);
+
+		/* send write CMD */
+		writel(*buf | I2C_DATACMD_WRITE, I2C_DATACMD);
+
+		/* wait until the Rx FIFO have available */
+		msleep(20);
+
+		/* read the data to buf */
+		i2c_reg++;
+		buf++;
+	}
+
+	return 0;
+}
+
+/*
+ * Generic i2c master transfer entrypoint.
+ *
+ */
+static int puv3_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *pmsg,
+		int num)
+{
+	int i, ret;
+	unsigned char swap;
+
+	/* Disable i2c */
+	writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
+
+	/* Set the work mode and speed*/
+	writel(I2C_CON_MASTER | I2C_CON_SPEED_STD | I2C_CON_SLAVEDISABLE, I2C_CON);
+
+	writel(pmsg->addr, I2C_TAR);
+
+	/* Enable i2c */
+	writel(I2C_ENABLE_ENABLE, I2C_ENABLE);
+
+	dev_dbg(&adap->dev, "puv3_i2c_xfer: processing %d messages:\n", num);
+
+	for (i = 0; i < num; i++) {
+		dev_dbg(&adap->dev, " #%d: %sing %d byte%s %s 0x%02x\n", i,
+			pmsg->flags & I2C_M_RD ? "read" : "writ",
+			pmsg->len, pmsg->len > 1 ? "s" : "",
+			pmsg->flags & I2C_M_RD ? "from" : "to",	pmsg->addr);
+
+		if (pmsg->len && pmsg->buf) {	/* sanity check */
+			if (pmsg->flags & I2C_M_RD)
+				ret = xfer_read(adap, pmsg->buf, pmsg->len);
+			else
+				ret = xfer_write(adap, pmsg->buf, pmsg->len);
+
+			if (ret)
+				return ret;
+
+		}
+		dev_dbg(&adap->dev, "transfer complete\n");
+		pmsg++;		/* next message */
+	}
+
+	/* XXX: fixup be16_to_cpu in bq27x00_battery.c */
+	if (pmsg->addr == I2C_TAR_PWIC) {
+		swap = pmsg->buf[0];
+		pmsg->buf[0] = pmsg->buf[1];
+		pmsg->buf[1] = swap;
+	}
+
+	return i;
+}
+
+/*
+ * Return list of supported functionality.
+ */
+static u32 puv3_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm puv3_i2c_algorithm = {
+	.master_xfer	= puv3_i2c_xfer,
+	.functionality	= puv3_i2c_func,
+};
+
+/*
+ * Main initialization routine.
+ */
+static int __devinit puv3_i2c_probe(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter;
+	struct resource *mem;
+	int rc;
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem)
+		return -ENODEV;
+
+	if (!request_mem_region(mem->start, resource_size(mem), "puv3_i2c"))
+		return -EBUSY;
+
+	adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
+	if (adapter == NULL) {
+		dev_err(&pdev->dev, "can't allocate inteface!\n");
+		rc = -ENOMEM;
+		goto fail_nomem;
+	}
+	snprintf(adapter->name, sizeof(adapter->name), "PUV3-I2C at 0x%08x",
+			mem->start);
+	adapter->algo = &puv3_i2c_algorithm;
+	adapter->class = I2C_CLASS_HWMON;
+	adapter->dev.parent = &pdev->dev;
+
+	platform_set_drvdata(pdev, adapter);
+
+	adapter->nr = pdev->id;
+	rc = i2c_add_numbered_adapter(adapter);
+	if (rc) {
+		dev_err(&pdev->dev, "Adapter '%s' registration failed\n",
+				adapter->name);
+		goto fail_add_adapter;
+	}
+
+	dev_info(&pdev->dev, "PKUnity v3 i2c bus adapter.\n");
+	return 0;
+
+fail_add_adapter:
+	platform_set_drvdata(pdev, NULL);
+	kfree(adapter);
+fail_nomem:
+	release_mem_region(mem->start, resource_size(mem));
+
+	return rc;
+}
+
+static int __devexit puv3_i2c_remove(struct platform_device *pdev)
+{
+	struct i2c_adapter *adapter = platform_get_drvdata(pdev);
+	struct resource *mem;
+	int rc;
+
+	rc = i2c_del_adapter(adapter);
+	if (rc) {
+		dev_err(&pdev->dev, "Adapter '%s' delete fail\n",
+				adapter->name);
+		return rc;
+	}
+
+	put_device(&pdev->dev);
+	platform_set_drvdata(pdev, NULL);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+	return rc;
+}
+
+#ifdef CONFIG_PM
+static int puv3_i2c_suspend(struct platform_device *dev, pm_message_t state)
+{
+	int poll_count;
+	/* Disable the IIC */
+	writel(I2C_ENABLE_DISABLE, I2C_ENABLE);
+	for (poll_count = 0; poll_count < 50; poll_count++) {
+		if (readl(I2C_ENSTATUS) & I2C_ENSTATUS_ENABLE)
+			udelay(25);
+	}
+
+	return 0;
+}
+
+static int puv3_i2c_resume(struct platform_device *dev)
+{
+	return 0 ;
+}
+#else
+#define puv3_i2c_suspend NULL
+#define puv3_i2c_resume NULL
+#endif
+
+MODULE_ALIAS("platform:puv3_i2c");
+
+static struct platform_driver puv3_i2c_driver = {
+	.probe		= puv3_i2c_probe,
+	.remove		= __devexit_p(puv3_i2c_remove),
+	.suspend	= puv3_i2c_suspend,
+	.resume		= puv3_i2c_resume,
+	.driver		= {
+		.name	= "PKUnity-v3-I2C",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init puv3_i2c_init(void)
+{
+	return platform_driver_register(&puv3_i2c_driver);
+}
+
+static void __exit puv3_i2c_exit(void)
+{
+	platform_driver_unregister(&puv3_i2c_driver);
+}
+
+module_init(puv3_i2c_init);
+module_exit(puv3_i2c_exit);
+
+MODULE_DESCRIPTION("PKUnity v3 I2C driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-pxa.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-pxa.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-pxa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-pxa.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,38 +29,75 @@
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/i2c-pxa.h>
+#include <linux/of_i2c.h>
 #include <linux/platform_device.h>
 #include <linux/err.h>
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/io.h>
+#include <linux/i2c/pxa-i2c.h>
 
 #include <asm/irq.h>
-#include <plat/i2c.h>
+
+#ifndef CONFIG_HAVE_CLK
+#define clk_get(dev, id)	NULL
+#define clk_put(clk)		do { } while (0)
+#define clk_disable(clk)	do { } while (0)
+#define clk_enable(clk)		do { } while (0)
+#endif
+
+struct pxa_reg_layout {
+	u32 ibmr;
+	u32 idbr;
+	u32 icr;
+	u32 isr;
+	u32 isar;
+};
+
+enum pxa_i2c_types {
+	REGS_PXA2XX,
+	REGS_PXA3XX,
+	REGS_CE4100,
+};
 
 /*
- * I2C register offsets will be shifted 0 or 1 bit left, depending on
- * different SoCs
+ * I2C registers definitions
  */
-#define REG_SHIFT_0	(0 << 0)
-#define REG_SHIFT_1	(1 << 0)
-#define REG_SHIFT(d)	((d) & 0x1)
+static struct pxa_reg_layout pxa_reg_layout[] = {
+	[REGS_PXA2XX] = {
+		.ibmr =	0x00,
+		.idbr =	0x08,
+		.icr =	0x10,
+		.isr =	0x18,
+		.isar =	0x20,
+	},
+	[REGS_PXA3XX] = {
+		.ibmr =	0x00,
+		.idbr =	0x04,
+		.icr =	0x08,
+		.isr =	0x0c,
+		.isar =	0x10,
+	},
+	[REGS_CE4100] = {
+		.ibmr =	0x14,
+		.idbr =	0x0c,
+		.icr =	0x00,
+		.isr =	0x04,
+		/* no isar register */
+	},
+};
 
 static const struct platform_device_id i2c_pxa_id_table[] = {
-	{ "pxa2xx-i2c",		REG_SHIFT_1 },
-	{ "pxa3xx-pwri2c",	REG_SHIFT_0 },
+	{ "pxa2xx-i2c",		REGS_PXA2XX },
+	{ "pxa3xx-pwri2c",	REGS_PXA3XX },
+	{ "ce4100-i2c",		REGS_CE4100 },
 	{ },
 };
 MODULE_DEVICE_TABLE(platform, i2c_pxa_id_table);
 
 /*
- * I2C registers and bit definitions
+ * I2C bit definitions
  */
-#define IBMR		(0x00)
-#define IDBR		(0x08)
-#define ICR		(0x10)
-#define ISR		(0x18)
-#define ISAR		(0x20)
 
 #define ICR_START	(1 << 0)	   /* start bit */
 #define ICR_STOP	(1 << 1)	   /* stop bit */
@@ -111,7 +148,11 @@
 	u32			icrlog[32];
 
 	void __iomem		*reg_base;
-	unsigned int		reg_shift;
+	void __iomem		*reg_ibmr;
+	void __iomem		*reg_idbr;
+	void __iomem		*reg_icr;
+	void __iomem		*reg_isr;
+	void __iomem		*reg_isar;
 
 	unsigned long		iobase;
 	unsigned long		iosize;
@@ -121,11 +162,11 @@
 	unsigned int		fast_mode :1;
 };
 
-#define _IBMR(i2c)	((i2c)->reg_base + (0x0 << (i2c)->reg_shift))
-#define _IDBR(i2c)	((i2c)->reg_base + (0x4 << (i2c)->reg_shift))
-#define _ICR(i2c)	((i2c)->reg_base + (0x8 << (i2c)->reg_shift))
-#define _ISR(i2c)	((i2c)->reg_base + (0xc << (i2c)->reg_shift))
-#define _ISAR(i2c)	((i2c)->reg_base + (0x10 << (i2c)->reg_shift))
+#define _IBMR(i2c)	((i2c)->reg_ibmr)
+#define _IDBR(i2c)	((i2c)->reg_idbr)
+#define _ICR(i2c)	((i2c)->reg_icr)
+#define _ISR(i2c)	((i2c)->reg_isr)
+#define _ISAR(i2c)	((i2c)->reg_isar)
 
 /*
  * I2C Slave mode address
@@ -418,7 +459,8 @@
 	writel(I2C_ISR_INIT, _ISR(i2c));
 	writel(readl(_ICR(i2c)) & ~ICR_UR, _ICR(i2c));
 
-	writel(i2c->slave_addr, _ISAR(i2c));
+	if (i2c->reg_isar)
+		writel(i2c->slave_addr, _ISAR(i2c));
 
 	/* set control register values */
 	writel(I2C_ICR_INIT | (i2c->fast_mode ? ICR_FM : 0), _ICR(i2c));
@@ -729,8 +771,10 @@
 	 */
 	ret = i2c->msg_idx;
 
-	if (timeout == 0)
+	if (!timeout && i2c->msg_num) {
 		i2c_pxa_scream_blue_murder(i2c, "timeout");
+		ret = I2C_RETRY;
+	}
 
  out:
 	return ret;
@@ -915,11 +959,16 @@
 	writel(icr, _ICR(i2c));
 }
 
+#define VALID_INT_SOURCE	(ISR_SSD | ISR_ALD | ISR_ITE | ISR_IRF | \
+				ISR_SAD | ISR_BED)
 static irqreturn_t i2c_pxa_handler(int this_irq, void *dev_id)
 {
 	struct pxa_i2c *i2c = dev_id;
 	u32 isr = readl(_ISR(i2c));
 
+	if (!(isr & VALID_INT_SOURCE))
+		return IRQ_NONE;
+
 	if (i2c_debug > 2 && 0) {
 		dev_dbg(&i2c->adap.dev, "%s: ISR=%08x, ICR=%08x, IBMR=%02x\n",
 			__func__, isr, readl(_ICR(i2c)), readl(_IBMR(i2c)));
@@ -934,7 +983,7 @@
 	/*
 	 * Always clear all pending IRQs.
 	 */
-	writel(isr & (ISR_SSD|ISR_ALD|ISR_ITE|ISR_IRF|ISR_SAD|ISR_BED), _ISR(i2c));
+	writel(isr & VALID_INT_SOURCE, _ISR(i2c));
 
 	if (isr & ISR_SAD)
 		i2c_pxa_slave_start(i2c, isr);
@@ -1001,6 +1050,7 @@
 	struct resource *res;
 	struct i2c_pxa_platform_data *plat = dev->dev.platform_data;
 	const struct platform_device_id *id = platform_get_device_id(dev);
+	enum pxa_i2c_types i2c_type = id->driver_data;
 	int ret;
 	int irq;
 
@@ -1044,7 +1094,13 @@
 		ret = -EIO;
 		goto eremap;
 	}
-	i2c->reg_shift = REG_SHIFT(id->driver_data);
+
+	i2c->reg_ibmr = i2c->reg_base + pxa_reg_layout[i2c_type].ibmr;
+	i2c->reg_idbr = i2c->reg_base + pxa_reg_layout[i2c_type].idbr;
+	i2c->reg_icr = i2c->reg_base + pxa_reg_layout[i2c_type].icr;
+	i2c->reg_isr = i2c->reg_base + pxa_reg_layout[i2c_type].isr;
+	if (i2c_type != REGS_CE4100)
+		i2c->reg_isar = i2c->reg_base + pxa_reg_layout[i2c_type].isar;
 
 	i2c->iobase = res->start;
 	i2c->iosize = resource_size(res);
@@ -1072,7 +1128,7 @@
 		i2c->adap.algo = &i2c_pxa_pio_algorithm;
 	} else {
 		i2c->adap.algo = &i2c_pxa_algorithm;
-		ret = request_irq(irq, i2c_pxa_handler, IRQF_DISABLED,
+		ret = request_irq(irq, i2c_pxa_handler, IRQF_SHARED,
 				  i2c->adap.name, i2c);
 		if (ret)
 			goto ereqirq;
@@ -1082,12 +1138,19 @@
 
 	i2c->adap.algo_data = i2c;
 	i2c->adap.dev.parent = &dev->dev;
+#ifdef CONFIG_OF
+	i2c->adap.dev.of_node = dev->dev.of_node;
+#endif
 
-	ret = i2c_add_numbered_adapter(&i2c->adap);
+	if (i2c_type == REGS_CE4100)
+		ret = i2c_add_adapter(&i2c->adap);
+	else
+		ret = i2c_add_numbered_adapter(&i2c->adap);
 	if (ret < 0) {
 		printk(KERN_INFO "I2C: Failed to add bus\n");
 		goto eadapt;
 	}
+	of_i2c_register_devices(&i2c->adap);
 
 	platform_set_drvdata(dev, i2c);
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-pxa-pci.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-pxa-pci.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-pxa-pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-pxa-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,176 @@
+/*
+ * The CE4100's I2C device is more or less the same one as found on PXA.
+ * It does not support slave mode, the register slightly moved. This PCI
+ * device provides three bars, every contains a single I2C controller.
+ */
+#include <linux/pci.h>
+#include <linux/platform_device.h>
+#include <linux/i2c/pxa-i2c.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/of_address.h>
+
+#define CE4100_PCI_I2C_DEVS	3
+
+struct ce4100_devices {
+	struct platform_device *pdev[CE4100_PCI_I2C_DEVS];
+};
+
+static struct platform_device *add_i2c_device(struct pci_dev *dev, int bar)
+{
+	struct platform_device *pdev;
+	struct i2c_pxa_platform_data pdata;
+	struct resource res[2];
+	struct device_node *child;
+	static int devnum;
+	int ret;
+
+	memset(&pdata, 0, sizeof(struct i2c_pxa_platform_data));
+	memset(&res, 0, sizeof(res));
+
+	res[0].flags = IORESOURCE_MEM;
+	res[0].start = pci_resource_start(dev, bar);
+	res[0].end = pci_resource_end(dev, bar);
+
+	res[1].flags = IORESOURCE_IRQ;
+	res[1].start = dev->irq;
+	res[1].end = dev->irq;
+
+	for_each_child_of_node(dev->dev.of_node, child) {
+		const void *prop;
+		struct resource r;
+		int ret;
+
+		ret = of_address_to_resource(child, 0, &r);
+		if (ret < 0)
+			continue;
+		if (r.start != res[0].start)
+			continue;
+		if (r.end != res[0].end)
+			continue;
+		if (r.flags != res[0].flags)
+			continue;
+
+		prop = of_get_property(child, "fast-mode", NULL);
+		if (prop)
+			pdata.fast_mode = 1;
+
+		break;
+	}
+
+	if (!child) {
+		dev_err(&dev->dev, "failed to match a DT node for bar %d.\n",
+				bar);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	pdev = platform_device_alloc("ce4100-i2c", devnum);
+	if (!pdev) {
+		of_node_put(child);
+		ret = -ENOMEM;
+		goto out;
+	}
+	pdev->dev.parent = &dev->dev;
+	pdev->dev.of_node = child;
+
+	ret = platform_device_add_resources(pdev, res, ARRAY_SIZE(res));
+	if (ret)
+		goto err;
+
+	ret = platform_device_add_data(pdev, &pdata, sizeof(pdata));
+	if (ret)
+		goto err;
+
+	ret = platform_device_add(pdev);
+	if (ret)
+		goto err;
+	devnum++;
+	return pdev;
+err:
+	platform_device_put(pdev);
+out:
+	return ERR_PTR(ret);
+}
+
+static int __devinit ce4100_i2c_probe(struct pci_dev *dev,
+		const struct pci_device_id *ent)
+{
+	int ret;
+	int i;
+	struct ce4100_devices *sds;
+
+	ret = pci_enable_device_mem(dev);
+	if (ret)
+		return ret;
+
+	if (!dev->dev.of_node) {
+		dev_err(&dev->dev, "Missing device tree node.\n");
+		return -EINVAL;
+	}
+	sds = kzalloc(sizeof(*sds), GFP_KERNEL);
+	if (!sds)
+		goto err_mem;
+
+	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++) {
+		sds->pdev[i] = add_i2c_device(dev, i);
+		if (IS_ERR(sds->pdev[i])) {
+			while (--i >= 0)
+				platform_device_unregister(sds->pdev[i]);
+			goto err_dev_add;
+		}
+	}
+	pci_set_drvdata(dev, sds);
+	return 0;
+
+err_dev_add:
+	pci_set_drvdata(dev, NULL);
+	kfree(sds);
+err_mem:
+	pci_disable_device(dev);
+	return ret;
+}
+
+static void __devexit ce4100_i2c_remove(struct pci_dev *dev)
+{
+	struct ce4100_devices *sds;
+	unsigned int i;
+
+	sds = pci_get_drvdata(dev);
+	pci_set_drvdata(dev, NULL);
+
+	for (i = 0; i < ARRAY_SIZE(sds->pdev); i++)
+		platform_device_unregister(sds->pdev[i]);
+
+	pci_disable_device(dev);
+	kfree(sds);
+}
+
+static struct pci_device_id ce4100_i2c_devices[] __devinitdata = {
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x2e68)},
+	{ },
+};
+MODULE_DEVICE_TABLE(pci, ce4100_i2c_devices);
+
+static struct pci_driver ce4100_i2c_driver = {
+	.name           = "ce4100_i2c",
+	.id_table       = ce4100_i2c_devices,
+	.probe          = ce4100_i2c_probe,
+	.remove         = __devexit_p(ce4100_i2c_remove),
+};
+
+static int __init ce4100_i2c_init(void)
+{
+	return pci_register_driver(&ce4100_i2c_driver);
+}
+module_init(ce4100_i2c_init);
+
+static void __exit ce4100_i2c_exit(void)
+{
+	pci_unregister_driver(&ce4100_i2c_driver);
+}
+module_exit(ce4100_i2c_exit);
+
+MODULE_DESCRIPTION("CE4100 PCI-I2C glue code for PXA's driver");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-s6000.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-s6000.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-s6000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-s6000.c	2011-05-19 00:06:34.000000000 -0400
@@ -318,7 +318,7 @@
 	rc = request_irq(iface->irq, s6i2c_interrupt_entry,
 			 IRQF_SHARED, dev->name, iface);
 	if (rc) {
-		dev_err(&p_adap->dev, "s6i2c: cant get IRQ %d\n", iface->irq);
+		dev_err(&p_adap->dev, "s6i2c: can't get IRQ %d\n", iface->irq);
 		goto err_clk_dis;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-stu300.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-stu300.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-stu300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-stu300.c	2011-05-19 00:06:34.000000000 -0400
@@ -497,7 +497,7 @@
 	u32 val;
 	int i = 0;
 
-	/* Locate the apropriate clock setting */
+	/* Locate the appropriate clock setting */
 	while (i < ARRAY_SIZE(stu300_clktable) - 1 &&
 	       stu300_clktable[i].rate < clkrate)
 		i++;
@@ -644,7 +644,7 @@
 	ret = stu300_await_event(dev, STU300_EVENT_6);
 
 	/*
-	 * Clear any pending EVENT 6 no matter what happend during
+	 * Clear any pending EVENT 6 no matter what happened during
 	 * await_event.
 	 */
 	val = stu300_r8(dev->virtbase + I2C_CR);
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-tegra.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-tegra.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-tegra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-tegra.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,700 @@
+/*
+ * drivers/i2c/busses/i2c-tegra.c
+ *
+ * Copyright (C) 2010 Google, Inc.
+ * Author: Colin Cross <ccross@android.com>
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; 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/platform_device.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/i2c-tegra.h>
+
+#include <asm/unaligned.h>
+
+#include <mach/clk.h>
+
+#define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000))
+#define BYTES_PER_FIFO_WORD 4
+
+#define I2C_CNFG				0x000
+#define I2C_CNFG_PACKET_MODE_EN			(1<<10)
+#define I2C_CNFG_NEW_MASTER_FSM			(1<<11)
+#define I2C_SL_CNFG				0x020
+#define I2C_SL_CNFG_NEWSL			(1<<2)
+#define I2C_SL_ADDR1				0x02c
+#define I2C_TX_FIFO				0x050
+#define I2C_RX_FIFO				0x054
+#define I2C_PACKET_TRANSFER_STATUS		0x058
+#define I2C_FIFO_CONTROL			0x05c
+#define I2C_FIFO_CONTROL_TX_FLUSH		(1<<1)
+#define I2C_FIFO_CONTROL_RX_FLUSH		(1<<0)
+#define I2C_FIFO_CONTROL_TX_TRIG_SHIFT		5
+#define I2C_FIFO_CONTROL_RX_TRIG_SHIFT		2
+#define I2C_FIFO_STATUS				0x060
+#define I2C_FIFO_STATUS_TX_MASK			0xF0
+#define I2C_FIFO_STATUS_TX_SHIFT		4
+#define I2C_FIFO_STATUS_RX_MASK			0x0F
+#define I2C_FIFO_STATUS_RX_SHIFT		0
+#define I2C_INT_MASK				0x064
+#define I2C_INT_STATUS				0x068
+#define I2C_INT_PACKET_XFER_COMPLETE		(1<<7)
+#define I2C_INT_ALL_PACKETS_XFER_COMPLETE	(1<<6)
+#define I2C_INT_TX_FIFO_OVERFLOW		(1<<5)
+#define I2C_INT_RX_FIFO_UNDERFLOW		(1<<4)
+#define I2C_INT_NO_ACK				(1<<3)
+#define I2C_INT_ARBITRATION_LOST		(1<<2)
+#define I2C_INT_TX_FIFO_DATA_REQ		(1<<1)
+#define I2C_INT_RX_FIFO_DATA_REQ		(1<<0)
+#define I2C_CLK_DIVISOR				0x06c
+
+#define DVC_CTRL_REG1				0x000
+#define DVC_CTRL_REG1_INTR_EN			(1<<10)
+#define DVC_CTRL_REG2				0x004
+#define DVC_CTRL_REG3				0x008
+#define DVC_CTRL_REG3_SW_PROG			(1<<26)
+#define DVC_CTRL_REG3_I2C_DONE_INTR_EN		(1<<30)
+#define DVC_STATUS				0x00c
+#define DVC_STATUS_I2C_DONE_INTR		(1<<30)
+
+#define I2C_ERR_NONE				0x00
+#define I2C_ERR_NO_ACK				0x01
+#define I2C_ERR_ARBITRATION_LOST		0x02
+
+#define PACKET_HEADER0_HEADER_SIZE_SHIFT	28
+#define PACKET_HEADER0_PACKET_ID_SHIFT		16
+#define PACKET_HEADER0_CONT_ID_SHIFT		12
+#define PACKET_HEADER0_PROTOCOL_I2C		(1<<4)
+
+#define I2C_HEADER_HIGHSPEED_MODE		(1<<22)
+#define I2C_HEADER_CONT_ON_NAK			(1<<21)
+#define I2C_HEADER_SEND_START_BYTE		(1<<20)
+#define I2C_HEADER_READ				(1<<19)
+#define I2C_HEADER_10BIT_ADDR			(1<<18)
+#define I2C_HEADER_IE_ENABLE			(1<<17)
+#define I2C_HEADER_REPEAT_START			(1<<16)
+#define I2C_HEADER_MASTER_ADDR_SHIFT		12
+#define I2C_HEADER_SLAVE_ADDR_SHIFT		1
+
+/**
+ * struct tegra_i2c_dev	- per device i2c context
+ * @dev: device reference for power management
+ * @adapter: core i2c layer adapter information
+ * @clk: clock reference for i2c controller
+ * @i2c_clk: clock reference for i2c bus
+ * @iomem: memory resource for registers
+ * @base: ioremapped registers cookie
+ * @cont_id: i2c controller id, used for for packet header
+ * @irq: irq number of transfer complete interrupt
+ * @is_dvc: identifies the DVC i2c controller, has a different register layout
+ * @msg_complete: transfer completion notifier
+ * @msg_err: error code for completed message
+ * @msg_buf: pointer to current message data
+ * @msg_buf_remaining: size of unsent data in the message buffer
+ * @msg_read: identifies read transfers
+ * @bus_clk_rate: current i2c bus clock rate
+ * @is_suspended: prevents i2c controller accesses after suspend is called
+ */
+struct tegra_i2c_dev {
+	struct device *dev;
+	struct i2c_adapter adapter;
+	struct clk *clk;
+	struct clk *i2c_clk;
+	struct resource *iomem;
+	void __iomem *base;
+	int cont_id;
+	int irq;
+	int is_dvc;
+	struct completion msg_complete;
+	int msg_err;
+	u8 *msg_buf;
+	size_t msg_buf_remaining;
+	int msg_read;
+	unsigned long bus_clk_rate;
+	bool is_suspended;
+};
+
+static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg)
+{
+	writel(val, i2c_dev->base + reg);
+}
+
+static u32 dvc_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
+{
+	return readl(i2c_dev->base + reg);
+}
+
+/*
+ * i2c_writel and i2c_readl will offset the register if necessary to talk
+ * to the I2C block inside the DVC block
+ */
+static unsigned long tegra_i2c_reg_addr(struct tegra_i2c_dev *i2c_dev,
+	unsigned long reg)
+{
+	if (i2c_dev->is_dvc)
+		reg += (reg >= I2C_TX_FIFO) ? 0x10 : 0x40;
+	return reg;
+}
+
+static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val,
+	unsigned long reg)
+{
+	writel(val, i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+}
+
+static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg)
+{
+	return readl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg));
+}
+
+static void i2c_writesl(struct tegra_i2c_dev *i2c_dev, void *data,
+	unsigned long reg, int len)
+{
+	writesl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+}
+
+static void i2c_readsl(struct tegra_i2c_dev *i2c_dev, void *data,
+	unsigned long reg, int len)
+{
+	readsl(i2c_dev->base + tegra_i2c_reg_addr(i2c_dev, reg), data, len);
+}
+
+static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
+{
+	u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK);
+	int_mask &= ~mask;
+	i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
+}
+
+static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask)
+{
+	u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK);
+	int_mask |= mask;
+	i2c_writel(i2c_dev, int_mask, I2C_INT_MASK);
+}
+
+static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev)
+{
+	unsigned long timeout = jiffies + HZ;
+	u32 val = i2c_readl(i2c_dev, I2C_FIFO_CONTROL);
+	val |= I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH;
+	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+
+	while (i2c_readl(i2c_dev, I2C_FIFO_CONTROL) &
+		(I2C_FIFO_CONTROL_TX_FLUSH | I2C_FIFO_CONTROL_RX_FLUSH)) {
+		if (time_after(jiffies, timeout)) {
+			dev_warn(i2c_dev->dev, "timeout waiting for fifo flush\n");
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+	}
+	return 0;
+}
+
+static int tegra_i2c_empty_rx_fifo(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val;
+	int rx_fifo_avail;
+	u8 *buf = i2c_dev->msg_buf;
+	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	int words_to_transfer;
+
+	val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+	rx_fifo_avail = (val & I2C_FIFO_STATUS_RX_MASK) >>
+		I2C_FIFO_STATUS_RX_SHIFT;
+
+	/* Rounds down to not include partial word at the end of buf */
+	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
+	if (words_to_transfer > rx_fifo_avail)
+		words_to_transfer = rx_fifo_avail;
+
+	i2c_readsl(i2c_dev, buf, I2C_RX_FIFO, words_to_transfer);
+
+	buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+	buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+	rx_fifo_avail -= words_to_transfer;
+
+	/*
+	 * If there is a partial word at the end of buf, handle it manually to
+	 * prevent overwriting past the end of buf
+	 */
+	if (rx_fifo_avail > 0 && buf_remaining > 0) {
+		BUG_ON(buf_remaining > 3);
+		val = i2c_readl(i2c_dev, I2C_RX_FIFO);
+		memcpy(buf, &val, buf_remaining);
+		buf_remaining = 0;
+		rx_fifo_avail--;
+	}
+
+	BUG_ON(rx_fifo_avail > 0 && buf_remaining > 0);
+	i2c_dev->msg_buf_remaining = buf_remaining;
+	i2c_dev->msg_buf = buf;
+	return 0;
+}
+
+static int tegra_i2c_fill_tx_fifo(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val;
+	int tx_fifo_avail;
+	u8 *buf = i2c_dev->msg_buf;
+	size_t buf_remaining = i2c_dev->msg_buf_remaining;
+	int words_to_transfer;
+
+	val = i2c_readl(i2c_dev, I2C_FIFO_STATUS);
+	tx_fifo_avail = (val & I2C_FIFO_STATUS_TX_MASK) >>
+		I2C_FIFO_STATUS_TX_SHIFT;
+
+	/* Rounds down to not include partial word at the end of buf */
+	words_to_transfer = buf_remaining / BYTES_PER_FIFO_WORD;
+	if (words_to_transfer > tx_fifo_avail)
+		words_to_transfer = tx_fifo_avail;
+
+	i2c_writesl(i2c_dev, buf, I2C_TX_FIFO, words_to_transfer);
+
+	buf += words_to_transfer * BYTES_PER_FIFO_WORD;
+	buf_remaining -= words_to_transfer * BYTES_PER_FIFO_WORD;
+	tx_fifo_avail -= words_to_transfer;
+
+	/*
+	 * If there is a partial word at the end of buf, handle it manually to
+	 * prevent reading past the end of buf, which could cross a page
+	 * boundary and fault.
+	 */
+	if (tx_fifo_avail > 0 && buf_remaining > 0) {
+		BUG_ON(buf_remaining > 3);
+		memcpy(&val, buf, buf_remaining);
+		i2c_writel(i2c_dev, val, I2C_TX_FIFO);
+		buf_remaining = 0;
+		tx_fifo_avail--;
+	}
+
+	BUG_ON(tx_fifo_avail > 0 && buf_remaining > 0);
+	i2c_dev->msg_buf_remaining = buf_remaining;
+	i2c_dev->msg_buf = buf;
+	return 0;
+}
+
+/*
+ * One of the Tegra I2C blocks is inside the DVC (Digital Voltage Controller)
+ * block.  This block is identical to the rest of the I2C blocks, except that
+ * it only supports master mode, it has registers moved around, and it needs
+ * some extra init to get it into I2C mode.  The register moves are handled
+ * by i2c_readl and i2c_writel
+ */
+static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val = 0;
+	val = dvc_readl(i2c_dev, DVC_CTRL_REG3);
+	val |= DVC_CTRL_REG3_SW_PROG;
+	val |= DVC_CTRL_REG3_I2C_DONE_INTR_EN;
+	dvc_writel(i2c_dev, val, DVC_CTRL_REG3);
+
+	val = dvc_readl(i2c_dev, DVC_CTRL_REG1);
+	val |= DVC_CTRL_REG1_INTR_EN;
+	dvc_writel(i2c_dev, val, DVC_CTRL_REG1);
+}
+
+static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev)
+{
+	u32 val;
+	int err = 0;
+
+	clk_enable(i2c_dev->clk);
+
+	tegra_periph_reset_assert(i2c_dev->clk);
+	udelay(2);
+	tegra_periph_reset_deassert(i2c_dev->clk);
+
+	if (i2c_dev->is_dvc)
+		tegra_dvc_init(i2c_dev);
+
+	val = I2C_CNFG_NEW_MASTER_FSM | I2C_CNFG_PACKET_MODE_EN;
+	i2c_writel(i2c_dev, val, I2C_CNFG);
+	i2c_writel(i2c_dev, 0, I2C_INT_MASK);
+	clk_set_rate(i2c_dev->clk, i2c_dev->bus_clk_rate * 8);
+
+	val = 7 << I2C_FIFO_CONTROL_TX_TRIG_SHIFT |
+		0 << I2C_FIFO_CONTROL_RX_TRIG_SHIFT;
+	i2c_writel(i2c_dev, val, I2C_FIFO_CONTROL);
+
+	if (tegra_i2c_flush_fifos(i2c_dev))
+		err = -ETIMEDOUT;
+
+	clk_disable(i2c_dev->clk);
+	return err;
+}
+
+static irqreturn_t tegra_i2c_isr(int irq, void *dev_id)
+{
+	u32 status;
+	const u32 status_err = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
+	struct tegra_i2c_dev *i2c_dev = dev_id;
+
+	status = i2c_readl(i2c_dev, I2C_INT_STATUS);
+
+	if (status == 0) {
+		dev_warn(i2c_dev->dev, "interrupt with no status\n");
+		return IRQ_NONE;
+	}
+
+	if (unlikely(status & status_err)) {
+		if (status & I2C_INT_NO_ACK)
+			i2c_dev->msg_err |= I2C_ERR_NO_ACK;
+		if (status & I2C_INT_ARBITRATION_LOST)
+			i2c_dev->msg_err |= I2C_ERR_ARBITRATION_LOST;
+		complete(&i2c_dev->msg_complete);
+		goto err;
+	}
+
+	if (i2c_dev->msg_read && (status & I2C_INT_RX_FIFO_DATA_REQ)) {
+		if (i2c_dev->msg_buf_remaining)
+			tegra_i2c_empty_rx_fifo(i2c_dev);
+		else
+			BUG();
+	}
+
+	if (!i2c_dev->msg_read && (status & I2C_INT_TX_FIFO_DATA_REQ)) {
+		if (i2c_dev->msg_buf_remaining)
+			tegra_i2c_fill_tx_fifo(i2c_dev);
+		else
+			tegra_i2c_mask_irq(i2c_dev, I2C_INT_TX_FIFO_DATA_REQ);
+	}
+
+	if ((status & I2C_INT_PACKET_XFER_COMPLETE) &&
+			!i2c_dev->msg_buf_remaining)
+		complete(&i2c_dev->msg_complete);
+
+	i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+	if (i2c_dev->is_dvc)
+		dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS);
+	return IRQ_HANDLED;
+err:
+	/* An error occurred, mask all interrupts */
+	tegra_i2c_mask_irq(i2c_dev, I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST |
+		I2C_INT_PACKET_XFER_COMPLETE | I2C_INT_TX_FIFO_DATA_REQ |
+		I2C_INT_RX_FIFO_DATA_REQ);
+	i2c_writel(i2c_dev, status, I2C_INT_STATUS);
+	return IRQ_HANDLED;
+}
+
+static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev,
+	struct i2c_msg *msg, int stop)
+{
+	u32 packet_header;
+	u32 int_mask;
+	int ret;
+
+	tegra_i2c_flush_fifos(i2c_dev);
+	i2c_writel(i2c_dev, 0xFF, I2C_INT_STATUS);
+
+	if (msg->len == 0)
+		return -EINVAL;
+
+	i2c_dev->msg_buf = msg->buf;
+	i2c_dev->msg_buf_remaining = msg->len;
+	i2c_dev->msg_err = I2C_ERR_NONE;
+	i2c_dev->msg_read = (msg->flags & I2C_M_RD);
+	INIT_COMPLETION(i2c_dev->msg_complete);
+
+	packet_header = (0 << PACKET_HEADER0_HEADER_SIZE_SHIFT) |
+			PACKET_HEADER0_PROTOCOL_I2C |
+			(i2c_dev->cont_id << PACKET_HEADER0_CONT_ID_SHIFT) |
+			(1 << PACKET_HEADER0_PACKET_ID_SHIFT);
+	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	packet_header = msg->len - 1;
+	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	packet_header = msg->addr << I2C_HEADER_SLAVE_ADDR_SHIFT;
+	packet_header |= I2C_HEADER_IE_ENABLE;
+	if (msg->flags & I2C_M_TEN)
+		packet_header |= I2C_HEADER_10BIT_ADDR;
+	if (msg->flags & I2C_M_IGNORE_NAK)
+		packet_header |= I2C_HEADER_CONT_ON_NAK;
+	if (msg->flags & I2C_M_NOSTART)
+		packet_header |= I2C_HEADER_REPEAT_START;
+	if (msg->flags & I2C_M_RD)
+		packet_header |= I2C_HEADER_READ;
+	i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO);
+
+	if (!(msg->flags & I2C_M_RD))
+		tegra_i2c_fill_tx_fifo(i2c_dev);
+
+	int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST;
+	if (msg->flags & I2C_M_RD)
+		int_mask |= I2C_INT_RX_FIFO_DATA_REQ;
+	else if (i2c_dev->msg_buf_remaining)
+		int_mask |= I2C_INT_TX_FIFO_DATA_REQ;
+	tegra_i2c_unmask_irq(i2c_dev, int_mask);
+	dev_dbg(i2c_dev->dev, "unmasked irq: %02x\n",
+		i2c_readl(i2c_dev, I2C_INT_MASK));
+
+	ret = wait_for_completion_timeout(&i2c_dev->msg_complete, TEGRA_I2C_TIMEOUT);
+	tegra_i2c_mask_irq(i2c_dev, int_mask);
+
+	if (WARN_ON(ret == 0)) {
+		dev_err(i2c_dev->dev, "i2c transfer timed out\n");
+
+		tegra_i2c_init(i2c_dev);
+		return -ETIMEDOUT;
+	}
+
+	dev_dbg(i2c_dev->dev, "transfer complete: %d %d %d\n",
+		ret, completion_done(&i2c_dev->msg_complete), i2c_dev->msg_err);
+
+	if (likely(i2c_dev->msg_err == I2C_ERR_NONE))
+		return 0;
+
+	tegra_i2c_init(i2c_dev);
+	if (i2c_dev->msg_err == I2C_ERR_NO_ACK) {
+		if (msg->flags & I2C_M_IGNORE_NAK)
+			return 0;
+		return -EREMOTEIO;
+	}
+
+	return -EIO;
+}
+
+static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
+	int num)
+{
+	struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap);
+	int i;
+	int ret = 0;
+
+	if (i2c_dev->is_suspended)
+		return -EBUSY;
+
+	clk_enable(i2c_dev->clk);
+	for (i = 0; i < num; i++) {
+		int stop = (i == (num - 1)) ? 1  : 0;
+		ret = tegra_i2c_xfer_msg(i2c_dev, &msgs[i], stop);
+		if (ret)
+			break;
+	}
+	clk_disable(i2c_dev->clk);
+	return ret ?: i;
+}
+
+static u32 tegra_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C;
+}
+
+static const struct i2c_algorithm tegra_i2c_algo = {
+	.master_xfer	= tegra_i2c_xfer,
+	.functionality	= tegra_i2c_func,
+};
+
+static int tegra_i2c_probe(struct platform_device *pdev)
+{
+	struct tegra_i2c_dev *i2c_dev;
+	struct tegra_i2c_platform_data *pdata = pdev->dev.platform_data;
+	struct resource *res;
+	struct resource *iomem;
+	struct clk *clk;
+	struct clk *i2c_clk;
+	void *base;
+	int irq;
+	int ret = 0;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no mem resource\n");
+		return -EINVAL;
+	}
+	iomem = request_mem_region(res->start, resource_size(res), pdev->name);
+	if (!iomem) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	base = ioremap(iomem->start, resource_size(iomem));
+	if (!base) {
+		dev_err(&pdev->dev, "Cannot ioremap I2C region\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "no irq resource\n");
+		ret = -EINVAL;
+		goto err_iounmap;
+	}
+	irq = res->start;
+
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "missing controller clock");
+		ret = PTR_ERR(clk);
+		goto err_release_region;
+	}
+
+	i2c_clk = clk_get(&pdev->dev, "i2c");
+	if (IS_ERR(i2c_clk)) {
+		dev_err(&pdev->dev, "missing bus clock");
+		ret = PTR_ERR(i2c_clk);
+		goto err_clk_put;
+	}
+
+	i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL);
+	if (!i2c_dev) {
+		ret = -ENOMEM;
+		goto err_i2c_clk_put;
+	}
+
+	i2c_dev->base = base;
+	i2c_dev->clk = clk;
+	i2c_dev->i2c_clk = i2c_clk;
+	i2c_dev->iomem = iomem;
+	i2c_dev->adapter.algo = &tegra_i2c_algo;
+	i2c_dev->irq = irq;
+	i2c_dev->cont_id = pdev->id;
+	i2c_dev->dev = &pdev->dev;
+	i2c_dev->bus_clk_rate = pdata ? pdata->bus_clk_rate : 100000;
+
+	if (pdev->id == 3)
+		i2c_dev->is_dvc = 1;
+	init_completion(&i2c_dev->msg_complete);
+
+	platform_set_drvdata(pdev, i2c_dev);
+
+	ret = tegra_i2c_init(i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to initialize i2c controller");
+		goto err_free;
+	}
+
+	ret = request_irq(i2c_dev->irq, tegra_i2c_isr, 0, pdev->name, i2c_dev);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to request irq %i\n", i2c_dev->irq);
+		goto err_free;
+	}
+
+	clk_enable(i2c_dev->i2c_clk);
+
+	i2c_set_adapdata(&i2c_dev->adapter, i2c_dev);
+	i2c_dev->adapter.owner = THIS_MODULE;
+	i2c_dev->adapter.class = I2C_CLASS_HWMON;
+	strlcpy(i2c_dev->adapter.name, "Tegra I2C adapter",
+		sizeof(i2c_dev->adapter.name));
+	i2c_dev->adapter.algo = &tegra_i2c_algo;
+	i2c_dev->adapter.dev.parent = &pdev->dev;
+	i2c_dev->adapter.nr = pdev->id;
+
+	ret = i2c_add_numbered_adapter(&i2c_dev->adapter);
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to add I2C adapter\n");
+		goto err_free_irq;
+	}
+
+	return 0;
+err_free_irq:
+	free_irq(i2c_dev->irq, i2c_dev);
+err_free:
+	kfree(i2c_dev);
+err_i2c_clk_put:
+	clk_put(i2c_clk);
+err_clk_put:
+	clk_put(clk);
+err_release_region:
+	release_mem_region(iomem->start, resource_size(iomem));
+err_iounmap:
+	iounmap(base);
+	return ret;
+}
+
+static int tegra_i2c_remove(struct platform_device *pdev)
+{
+	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+	i2c_del_adapter(&i2c_dev->adapter);
+	free_irq(i2c_dev->irq, i2c_dev);
+	clk_put(i2c_dev->i2c_clk);
+	clk_put(i2c_dev->clk);
+	release_mem_region(i2c_dev->iomem->start,
+		resource_size(i2c_dev->iomem));
+	iounmap(i2c_dev->base);
+	kfree(i2c_dev);
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+
+	i2c_lock_adapter(&i2c_dev->adapter);
+	i2c_dev->is_suspended = true;
+	i2c_unlock_adapter(&i2c_dev->adapter);
+
+	return 0;
+}
+
+static int tegra_i2c_resume(struct platform_device *pdev)
+{
+	struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev);
+	int ret;
+
+	i2c_lock_adapter(&i2c_dev->adapter);
+
+	ret = tegra_i2c_init(i2c_dev);
+
+	if (ret) {
+		i2c_unlock_adapter(&i2c_dev->adapter);
+		return ret;
+	}
+
+	i2c_dev->is_suspended = false;
+
+	i2c_unlock_adapter(&i2c_dev->adapter);
+
+	return 0;
+}
+#endif
+
+static struct platform_driver tegra_i2c_driver = {
+	.probe   = tegra_i2c_probe,
+	.remove  = tegra_i2c_remove,
+#ifdef CONFIG_PM
+	.suspend = tegra_i2c_suspend,
+	.resume  = tegra_i2c_resume,
+#endif
+	.driver  = {
+		.name  = "tegra-i2c",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init tegra_i2c_init_driver(void)
+{
+	return platform_driver_register(&tegra_i2c_driver);
+}
+
+static void __exit tegra_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&tegra_i2c_driver);
+}
+
+subsys_initcall(tegra_i2c_init_driver);
+module_exit(tegra_i2c_exit_driver);
+
+MODULE_DESCRIPTION("nVidia Tegra2 I2C Bus Controller driver");
+MODULE_AUTHOR("Colin Cross");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-xiic.c linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-xiic.c
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/i2c-xiic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/i2c-xiic.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
  * to the automotive development board Russellville. The copyright holder
  * as seen in the header is Intel corporation.
  * Mocean Laboratories forked off the GNU/Linux platform work into a
- * separate company called Pelagicore AB, which commited the code to the
+ * separate company called Pelagicore AB, which committed the code to the
  * kernel.
  */
 
@@ -34,6 +34,7 @@
 #include <linux/errno.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/i2c.h>
 #include <linux/interrupt.h>
 #include <linux/wait.h>
@@ -704,7 +705,7 @@
 	if (irq < 0)
 		goto resource_missing;
 
-	pdata = (struct xiic_i2c_platform_data *) pdev->dev.platform_data;
+	pdata = mfd_get_data(pdev);
 	if (!pdata)
 		return -EINVAL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/Kconfig linux-libre-2.6.39-gnu/drivers/i2c/busses/Kconfig
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -98,8 +98,9 @@
 	    EP80579 (Tolapai)
 	    ICH10
 	    5/3400 Series (PCH)
-	    Cougar Point (PCH)
+	    6 Series (PCH)
 	    Patsburg (PCH)
+	    DH89xxCC (PCH)
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-i801.
@@ -433,7 +434,7 @@
 
 config I2C_MPC
 	tristate "MPC107/824x/85xx/512x/52xx/83xx/86xx"
-	depends on PPC32
+	depends on PPC
 	help
 	  If you say yes to this option, support will be included for the
 	  built-in I2C interface on the MPC107, Tsi107, MPC512x, MPC52xx,
@@ -452,6 +453,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-mv64xxx.
 
+config I2C_MXS
+	tristate "Freescale i.MX28 I2C interface"
+	depends on SOC_IMX28
+	help
+	  Say Y here if you want to use the I2C bus controller on
+	  the Freescale i.MX28 processors.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-mxs.
+
 config I2C_NOMADIK
 	tristate "ST-Ericsson Nomadik/Ux500 I2C Controller"
 	depends on PLAT_NOMADIK
@@ -523,17 +534,31 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pnx.
 
+config I2C_PUV3
+	tristate "PKUnity v3 I2C bus support"
+	depends on UNICORE32 && ARCH_PUV3
+	select I2C_ALGOBIT
+	help
+	  This driver supports the I2C IP inside the PKUnity-v3 SoC.
+	  This I2C bus controller is under AMBA/AXI bus.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-puv3.
+
 config I2C_PXA
 	tristate "Intel PXA2XX I2C adapter"
-	depends on ARCH_PXA || ARCH_MMP
+	depends on ARCH_PXA || ARCH_MMP || (X86_32 && PCI && OF)
 	help
 	  If you have devices in the PXA I2C bus, say yes to this option.
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-pxa.
 
+config I2C_PXA_PCI
+	def_bool I2C_PXA && X86_32 && PCI && OF
+
 config I2C_PXA_SLAVE
 	bool "Intel PXA2XX I2C Slave comms support"
-	depends on I2C_PXA
+	depends on I2C_PXA && !X86_32
 	help
 	  Support I2C slave mode communications on the PXA I2C bus.  This
 	  is necessary for systems where the PXA may be a target on the
@@ -607,6 +632,13 @@
 	  This driver can also be built as a module. If so, the module
 	  will be called i2c-stu300.
 
+config I2C_TEGRA
+	tristate "NVIDIA Tegra internal I2C controller"
+	depends on ARCH_TEGRA
+	help
+	  If you say yes to this option, support will be included for the
+	  I2C controller embedded in NVIDIA Tegra SOCs
+
 config I2C_VERSATILE
 	tristate "ARM Versatile/Realview I2C bus support"
 	depends on ARCH_VERSATILE || ARCH_REALVIEW || ARCH_VEXPRESS
@@ -639,15 +671,28 @@
 	  will be called xilinx_i2c.
 
 config I2C_EG20T
-        tristate "PCH I2C of Intel EG20T"
-        depends on PCI
-        help
-          This driver is for PCH(Platform controller Hub) I2C of EG20T which
-          is an IOH(Input/Output Hub) for x86 embedded processor.
-          This driver can access PCH I2C bus device.
+	tristate "Intel EG20T PCH/OKI SEMICONDUCTOR ML7213 IOH"
+	depends on PCI
+	help
+	  This driver is for PCH(Platform controller Hub) I2C of EG20T which
+	  is an IOH(Input/Output Hub) for x86 embedded processor.
+	  This driver can access PCH I2C bus device.
+
+	  This driver also supports the ML7213, a companion chip for the
+	  Atom E6xx series and compatible with the Intel EG20T PCH.
 
 comment "External I2C/SMBus adapter drivers"
 
+config I2C_DIOLAN_U2C
+	tristate "Diolan U2C-12 USB adapter"
+	depends on USB
+	help
+	  If you say yes to this option, support will be included for Diolan
+	  U2C-12, a USB to I2C interface.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-diolan-u2c.
+
 config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on PARPORT
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/busses/Makefile linux-libre-2.6.39-gnu/drivers/i2c/busses/Makefile
--- linux-libre-2.6.38-gnu/drivers/i2c/busses/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/busses/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,7 @@
 obj-$(CONFIG_I2C_IXP2000)	+= i2c-ixp2000.o
 obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
+obj-$(CONFIG_I2C_MXS)		+= i2c-mxs.o
 obj-$(CONFIG_I2C_NOMADIK)	+= i2c-nomadik.o
 obj-$(CONFIG_I2C_NUC900)	+= i2c-nuc900.o
 obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
@@ -51,19 +52,23 @@
 obj-$(CONFIG_I2C_PCA_PLATFORM)	+= i2c-pca-platform.o
 obj-$(CONFIG_I2C_PMCMSP)	+= i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)		+= i2c-pnx.o
+obj-$(CONFIG_I2C_PUV3)		+= i2c-puv3.o
 obj-$(CONFIG_I2C_PXA)		+= i2c-pxa.o
+obj-$(CONFIG_I2C_PXA_PCI)	+= i2c-pxa-pci.o
 obj-$(CONFIG_I2C_S3C2410)	+= i2c-s3c2410.o
 obj-$(CONFIG_I2C_S6000)		+= i2c-s6000.o
 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_TEGRA)		+= i2c-tegra.o
 obj-$(CONFIG_I2C_VERSATILE)	+= i2c-versatile.o
 obj-$(CONFIG_I2C_OCTEON)	+= i2c-octeon.o
 obj-$(CONFIG_I2C_XILINX)	+= i2c-xiic.o
 obj-$(CONFIG_I2C_EG20T)         += i2c-eg20t.o
 
 # External I2C/SMBus adapter drivers
+obj-$(CONFIG_I2C_DIOLAN_U2C)	+= i2c-diolan-u2c.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_TAOS_EVM)	+= i2c-taos-evm.o
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/i2c-boardinfo.c linux-libre-2.6.39-gnu/drivers/i2c/i2c-boardinfo.c
--- linux-libre-2.6.38-gnu/drivers/i2c/i2c-boardinfo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/i2c-boardinfo.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * i2c-boardinfo.h - collect pre-declarations of I2C devices
+ * i2c-boardinfo.c - collect pre-declarations of I2C devices
  *
  * This 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.38-gnu/drivers/i2c/i2c-core.c linux-libre-2.6.39-gnu/drivers/i2c/i2c-core.c
--- linux-libre-2.6.38-gnu/drivers/i2c/i2c-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/i2c-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -348,7 +348,7 @@
 
 
 /* This is a permissive address validity check, I2C address map constraints
- * are purposedly not enforced, except for the general call address. */
+ * are purposely not enforced, except for the general call address. */
 static int i2c_check_client_addr_validity(const struct i2c_client *client)
 {
 	if (client->flags & I2C_CLIENT_TEN) {
@@ -537,9 +537,7 @@
 	client->dev.parent = &client->adapter->dev;
 	client->dev.bus = &i2c_bus_type;
 	client->dev.type = &i2c_client_type;
-#ifdef CONFIG_OF
 	client->dev.of_node = info->of_node;
-#endif
 
 	dev_set_name(&client->dev, "%d-%04x", i2c_adapter_id(adap),
 		     client->addr);
@@ -799,6 +797,10 @@
 
 	/* Let legacy drivers scan this bus for matching devices */
 	if (driver->attach_adapter) {
+		dev_warn(&adap->dev, "%s: attach_adapter method is deprecated\n",
+			 driver->driver.name);
+		dev_warn(&adap->dev, "Please use another way to instantiate "
+			 "your i2c_client\n");
 		/* We ignore the return code; if it fails, too bad */
 		driver->attach_adapter(adap);
 	}
@@ -983,6 +985,8 @@
 
 	if (!driver->detach_adapter)
 		return 0;
+	dev_warn(&adapter->dev, "%s: detach_adapter method is deprecated\n",
+		 driver->driver.name);
 	res = driver->detach_adapter(adapter);
 	if (res)
 		dev_err(&adapter->dev, "detach_adapter failed (%d) "
@@ -1093,6 +1097,18 @@
 
 /* ------------------------------------------------------------------------- */
 
+int i2c_for_each_dev(void *data, int (*fn)(struct device *, void *))
+{
+	int res;
+
+	mutex_lock(&core_lock);
+	res = bus_for_each_dev(&i2c_bus_type, NULL, data, fn);
+	mutex_unlock(&core_lock);
+
+	return res;
+}
+EXPORT_SYMBOL_GPL(i2c_for_each_dev);
+
 static int __process_new_driver(struct device *dev, void *data)
 {
 	if (dev->type != &i2c_adapter_type)
@@ -1136,9 +1152,7 @@
 
 	INIT_LIST_HEAD(&driver->clients);
 	/* Walk the adapters that are already present */
-	mutex_lock(&core_lock);
-	bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
-	mutex_unlock(&core_lock);
+	i2c_for_each_dev(driver, __process_new_driver);
 
 	return 0;
 }
@@ -1158,9 +1172,7 @@
  */
 void i2c_del_driver(struct i2c_driver *driver)
 {
-	mutex_lock(&core_lock);
-	bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);
-	mutex_unlock(&core_lock);
+	i2c_for_each_dev(driver, __process_removed_driver);
 
 	driver_unregister(&driver->driver);
 	pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
@@ -1583,12 +1595,12 @@
 }
 EXPORT_SYMBOL_GPL(i2c_new_probed_device);
 
-struct i2c_adapter *i2c_get_adapter(int id)
+struct i2c_adapter *i2c_get_adapter(int nr)
 {
 	struct i2c_adapter *adapter;
 
 	mutex_lock(&core_lock);
-	adapter = idr_find(&i2c_adapter_idr, id);
+	adapter = idr_find(&i2c_adapter_idr, nr);
 	if (adapter && !try_module_get(adapter->owner))
 		adapter = NULL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/i2c-dev.c linux-libre-2.6.39-gnu/drivers/i2c/i2c-dev.c
--- linux-libre-2.6.38-gnu/drivers/i2c/i2c-dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/i2c-dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,8 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/device.h>
+#include <linux/notifier.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/init.h>
@@ -37,16 +39,13 @@
 #include <linux/jiffies.h>
 #include <linux/uaccess.h>
 
-static struct i2c_driver i2cdev_driver;
-
 /*
  * An i2c_dev represents an i2c_adapter ... an I2C or SMBus master, not a
  * slave (i2c_client) with which messages will be exchanged.  It's coupled
  * with a character special file which is accessed by user mode drivers.
  *
  * The list of i2c_dev structures is parallel to the i2c_adapter lists
- * maintained by the driver model, and is updated using notifications
- * delivered to the i2cdev_driver.
+ * maintained by the driver model, and is updated using bus notifications.
  */
 struct i2c_dev {
 	struct list_head list;
@@ -491,7 +490,6 @@
 		return -ENOMEM;
 	}
 	snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
-	client->driver = &i2cdev_driver;
 
 	client->adapter = adap;
 	file->private_data = client;
@@ -522,19 +520,18 @@
 
 /* ------------------------------------------------------------------------- */
 
-/*
- * The legacy "i2cdev_driver" is used primarily to get notifications when
- * I2C adapters are added or removed, so that each one gets an i2c_dev
- * and is thus made available to userspace driver code.
- */
-
 static struct class *i2c_dev_class;
 
-static int i2cdev_attach_adapter(struct i2c_adapter *adap)
+static int i2cdev_attach_adapter(struct device *dev, void *dummy)
 {
+	struct i2c_adapter *adap;
 	struct i2c_dev *i2c_dev;
 	int res;
 
+	if (dev->type != &i2c_adapter_type)
+		return 0;
+	adap = to_i2c_adapter(dev);
+
 	i2c_dev = get_free_i2c_dev(adap);
 	if (IS_ERR(i2c_dev))
 		return PTR_ERR(i2c_dev);
@@ -561,10 +558,15 @@
 	return res;
 }
 
-static int i2cdev_detach_adapter(struct i2c_adapter *adap)
+static int i2cdev_detach_adapter(struct device *dev, void *dummy)
 {
+	struct i2c_adapter *adap;
 	struct i2c_dev *i2c_dev;
 
+	if (dev->type != &i2c_adapter_type)
+		return 0;
+	adap = to_i2c_adapter(dev);
+
 	i2c_dev = i2c_dev_get_by_minor(adap->nr);
 	if (!i2c_dev) /* attach_adapter must have failed */
 		return 0;
@@ -577,12 +579,23 @@
 	return 0;
 }
 
-static struct i2c_driver i2cdev_driver = {
-	.driver = {
-		.name	= "dev_driver",
-	},
-	.attach_adapter	= i2cdev_attach_adapter,
-	.detach_adapter	= i2cdev_detach_adapter,
+int i2cdev_notifier_call(struct notifier_block *nb, unsigned long action,
+			 void *data)
+{
+	struct device *dev = data;
+
+	switch (action) {
+	case BUS_NOTIFY_ADD_DEVICE:
+		return i2cdev_attach_adapter(dev, NULL);
+	case BUS_NOTIFY_DEL_DEVICE:
+		return i2cdev_detach_adapter(dev, NULL);
+	}
+
+	return 0;
+}
+
+static struct notifier_block i2cdev_notifier = {
+	.notifier_call = i2cdev_notifier_call,
 };
 
 /* ------------------------------------------------------------------------- */
@@ -607,10 +620,14 @@
 		goto out_unreg_chrdev;
 	}
 
-	res = i2c_add_driver(&i2cdev_driver);
+	/* Keep track of adapters which will be added or removed later */
+	res = bus_register_notifier(&i2c_bus_type, &i2cdev_notifier);
 	if (res)
 		goto out_unreg_class;
 
+	/* Bind to already existing adapters right away */
+	i2c_for_each_dev(NULL, i2cdev_attach_adapter);
+
 	return 0;
 
 out_unreg_class:
@@ -624,7 +641,8 @@
 
 static void __exit i2c_dev_exit(void)
 {
-	i2c_del_driver(&i2cdev_driver);
+	bus_unregister_notifier(&i2c_bus_type, &i2cdev_notifier);
+	i2c_for_each_dev(NULL, i2cdev_detach_adapter);
 	class_destroy(i2c_dev_class);
 	unregister_chrdev(I2C_MAJOR, "i2c");
 }
diff -druN linux-libre-2.6.38-gnu/drivers/i2c/Makefile linux-libre-2.6.39-gnu/drivers/i2c/Makefile
--- linux-libre-2.6.38-gnu/drivers/i2c/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/i2c/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -10,3 +10,4 @@
 obj-y				+= algos/ busses/ muxes/
 
 ccflags-$(CONFIG_I2C_DEBUG_CORE) := -DDEBUG
+CFLAGS_i2c-core.o := -Wno-deprecated-declarations
diff -druN linux-libre-2.6.38-gnu/drivers/ide/cy82c693.c linux-libre-2.6.39-gnu/drivers/ide/cy82c693.c
--- linux-libre-2.6.38-gnu/drivers/ide/cy82c693.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/cy82c693.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
 
 	/*
 	 * note: below we set the value for Bus Master IDE TimeOut Register
-	 * I'm not absolutly sure what this does, but it solved my problem
+	 * I'm not absolutely sure what this does, but it solved my problem
 	 * with IDE DMA and sound, so I now can play sound and work with
 	 * my IDE driver at the same time :-)
 	 *
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-atapi.c linux-libre-2.6.39-gnu/drivers/ide/ide-atapi.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-atapi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-atapi.c	2011-05-19 00:06:34.000000000 -0400
@@ -233,8 +233,7 @@
 
 	drive->hwif->rq = NULL;
 
-	elv_add_request(drive->queue, &drive->sense_rq,
-			ELEVATOR_INSERT_FRONT, 0);
+	elv_add_request(drive->queue, &drive->sense_rq, ELEVATOR_INSERT_FRONT);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-cd.c linux-libre-2.6.39-gnu/drivers/ide/ide-cd.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-cd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-cd.c	2011-05-19 00:06:34.000000000 -0400
@@ -258,17 +258,10 @@
 	if (time_after(jiffies, info->write_timeout))
 		return 0;
 	else {
-		struct request_queue *q = drive->queue;
-		unsigned long flags;
-
 		/*
-		 * take a breather relying on the unplug timer to kick us again
+		 * take a breather
 		 */
-
-		spin_lock_irqsave(q->queue_lock, flags);
-		blk_plug_device(q);
-		spin_unlock_irqrestore(q->queue_lock, flags);
-
+		blk_delay_queue(drive->queue, 1);
 		return 1;
 	}
 }
@@ -1177,7 +1170,7 @@
 	.open			= ide_cdrom_open_real,
 	.release		= ide_cdrom_release_real,
 	.drive_status		= ide_cdrom_drive_status,
-	.media_changed		= ide_cdrom_check_media_change_real,
+	.check_events		= ide_cdrom_check_events_real,
 	.tray_move		= ide_cdrom_tray_move,
 	.lock_door		= ide_cdrom_lock_door,
 	.select_speed		= ide_cdrom_select_speed,
@@ -1514,8 +1507,6 @@
 	blk_queue_dma_alignment(q, 31);
 	blk_queue_update_dma_pad(q, 15);
 
-	q->unplug_delay = max((1 * HZ) / 1000, 1);
-
 	drive->dev_flags |= IDE_DFLAG_MEDIA_CHANGED;
 	drive->atapi_flags = IDE_AFLAG_NO_EJECT | ide_cd_flags(id);
 
@@ -1702,10 +1693,11 @@
 }
 
 
-static int idecd_media_changed(struct gendisk *disk)
+static unsigned int idecd_check_events(struct gendisk *disk,
+				       unsigned int clearing)
 {
 	struct cdrom_info *info = ide_drv_g(disk, cdrom_info);
-	return cdrom_media_changed(&info->devinfo);
+	return cdrom_check_events(&info->devinfo, clearing);
 }
 
 static int idecd_revalidate_disk(struct gendisk *disk)
@@ -1723,7 +1715,7 @@
 	.open			= idecd_open,
 	.release		= idecd_release,
 	.ioctl			= idecd_ioctl,
-	.media_changed		= idecd_media_changed,
+	.check_events		= idecd_check_events,
 	.revalidate_disk	= idecd_revalidate_disk
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-cd.h linux-libre-2.6.39-gnu/drivers/ide/ide-cd.h
--- linux-libre-2.6.38-gnu/drivers/ide/ide-cd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-cd.h	2011-05-19 00:06:34.000000000 -0400
@@ -111,7 +111,8 @@
 int ide_cdrom_open_real(struct cdrom_device_info *, int);
 void ide_cdrom_release_real(struct cdrom_device_info *);
 int ide_cdrom_drive_status(struct cdrom_device_info *, int);
-int ide_cdrom_check_media_change_real(struct cdrom_device_info *, int);
+unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *,
+					 unsigned int clearing, int slot_nr);
 int ide_cdrom_tray_move(struct cdrom_device_info *, int);
 int ide_cdrom_lock_door(struct cdrom_device_info *, int);
 int ide_cdrom_select_speed(struct cdrom_device_info *, int);
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-cd_ioctl.c linux-libre-2.6.39-gnu/drivers/ide/ide-cd_ioctl.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-cd_ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-cd_ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -79,8 +79,14 @@
 	return CDS_DRIVE_NOT_READY;
 }
 
-int ide_cdrom_check_media_change_real(struct cdrom_device_info *cdi,
-				       int slot_nr)
+/*
+ * ide-cd always generates media changed event if media is missing, which
+ * makes it impossible to use for proper event reporting, so disk->events
+ * is cleared to 0 and the following function is used only to trigger
+ * revalidation and never propagated to userland.
+ */
+unsigned int ide_cdrom_check_events_real(struct cdrom_device_info *cdi,
+					 unsigned int clearing, int slot_nr)
 {
 	ide_drive_t *drive = cdi->handle;
 	int retval;
@@ -89,9 +95,9 @@
 		(void) cdrom_check_status(drive, NULL);
 		retval = (drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED) ? 1 : 0;
 		drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
-		return retval;
+		return retval ? DISK_EVENT_MEDIA_CHANGE : 0;
 	} else {
-		return -EINVAL;
+		return 0;
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-floppy.c linux-libre-2.6.39-gnu/drivers/ide/ide-floppy.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-floppy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-floppy.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,7 +107,7 @@
 static void ide_floppy_report_error(struct ide_disk_obj *floppy,
 				    struct ide_atapi_pc *pc)
 {
-	/* supress error messages resulting from Medium not present */
+	/* suppress error messages resulting from Medium not present */
 	if (floppy->sense_key == 0x02 &&
 	    floppy->asc       == 0x3a &&
 	    floppy->ascq      == 0x00)
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-gd.c linux-libre-2.6.39-gnu/drivers/ide/ide-gd.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-gd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-gd.c	2011-05-19 00:06:34.000000000 -0400
@@ -285,11 +285,12 @@
 	return 0;
 }
 
-static int ide_gd_media_changed(struct gendisk *disk)
+static unsigned int ide_gd_check_events(struct gendisk *disk,
+					unsigned int clearing)
 {
 	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 	ide_drive_t *drive = idkp->drive;
-	int ret;
+	bool ret;
 
 	/* do not scan partitions twice if this is a removable device */
 	if (drive->dev_flags & IDE_DFLAG_ATTACH) {
@@ -297,10 +298,16 @@
 		return 0;
 	}
 
-	ret = !!(drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED);
+	/*
+	 * The following is used to force revalidation on the first open on
+	 * removeable devices, and never gets reported to userland as
+	 * genhd->events is 0.  This is intended as removeable ide disk
+	 * can't really detect MEDIA_CHANGE events.
+	 */
+	ret = drive->dev_flags & IDE_DFLAG_MEDIA_CHANGED;
 	drive->dev_flags &= ~IDE_DFLAG_MEDIA_CHANGED;
 
-	return ret;
+	return ret ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 static void ide_gd_unlock_native_capacity(struct gendisk *disk)
@@ -318,7 +325,7 @@
 	struct ide_disk_obj *idkp = ide_drv_g(disk, ide_disk_obj);
 	ide_drive_t *drive = idkp->drive;
 
-	if (ide_gd_media_changed(disk))
+	if (ide_gd_check_events(disk, 0))
 		drive->disk_ops->get_capacity(drive);
 
 	set_capacity(disk, ide_gd_capacity(drive));
@@ -340,7 +347,7 @@
 	.release		= ide_gd_release,
 	.ioctl			= ide_gd_ioctl,
 	.getgeo			= ide_gd_getgeo,
-	.media_changed		= ide_gd_media_changed,
+	.check_events		= ide_gd_check_events,
 	.unlock_native_capacity	= ide_gd_unlock_native_capacity,
 	.revalidate_disk	= ide_gd_revalidate_disk
 };
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-io.c linux-libre-2.6.39-gnu/drivers/ide/ide-io.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-io.c	2011-05-19 00:06:34.000000000 -0400
@@ -430,6 +430,26 @@
 	}
 }
 
+static void __ide_requeue_and_plug(struct request_queue *q, struct request *rq)
+{
+	if (rq)
+		blk_requeue_request(q, rq);
+	if (rq || blk_peek_request(q)) {
+		/* Use 3ms as that was the old plug delay */
+		blk_delay_queue(q, 3);
+	}
+}
+
+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);
+	__ide_requeue_and_plug(q, rq);
+	spin_unlock_irqrestore(q->queue_lock, flags);
+}
+
 /*
  * Issue a new request to a device.
  */
@@ -440,6 +460,7 @@
 	struct ide_host *host = hwif->host;
 	struct request	*rq = NULL;
 	ide_startstop_t	startstop;
+	unsigned long queue_run_ms = 3; /* old plug delay */
 
 	spin_unlock_irq(q->queue_lock);
 
@@ -459,6 +480,9 @@
 		prev_port = hwif->host->cur_port;
 		if (drive->dev_flags & IDE_DFLAG_SLEEPING &&
 		    time_after(drive->sleep, jiffies)) {
+			unsigned long left = jiffies - drive->sleep;
+
+			queue_run_ms = jiffies_to_msecs(left + 1);
 			ide_unlock_port(hwif);
 			goto plug_device;
 		}
@@ -546,26 +570,7 @@
 	ide_unlock_host(host);
 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);
-}
-
-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);
+	__ide_requeue_and_plug(q, rq);
 }
 
 static int drive_is_ready(ide_drive_t *drive)
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-park.c linux-libre-2.6.39-gnu/drivers/ide/ide-park.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-park.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-park.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,7 +52,7 @@
 	rq->cmd[0] = REQ_UNPARK_HEADS;
 	rq->cmd_len = 1;
 	rq->cmd_type = REQ_TYPE_SPECIAL;
-	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1);
+	elv_add_request(q, rq, ELEVATOR_INSERT_FRONT);
 
 out:
 	return;
diff -druN linux-libre-2.6.38-gnu/drivers/ide/ide-taskfile.c linux-libre-2.6.39-gnu/drivers/ide/ide-taskfile.c
--- linux-libre-2.6.38-gnu/drivers/ide/ide-taskfile.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/ide-taskfile.c	2011-05-19 00:06:34.000000000 -0400
@@ -201,7 +201,7 @@
 	u8 stat;
 
 	/*
-	 * Last sector was transfered, wait until device is ready.  This can
+	 * Last sector was transferred, wait until device is ready.  This can
 	 * take up to 6 ms on some ATAPI devices, so we will wait max 10 ms.
 	 */
 	for (retries = 0; retries < 1000; retries++) {
diff -druN linux-libre-2.6.38-gnu/drivers/ide/Makefile linux-libre-2.6.39-gnu/drivers/ide/Makefile
--- linux-libre-2.6.38-gnu/drivers/ide/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
 # link order is important here
 #
 
-EXTRA_CFLAGS				+= -Idrivers/ide
+ccflags-y				:= -Idrivers/ide
 
 ide-core-y += ide.o ide-ioctls.o ide-io.o ide-iops.o ide-lib.o ide-probe.o \
 	      ide-taskfile.o ide-pm.o ide-park.o ide-sysfs.o ide-devsets.o \
diff -druN linux-libre-2.6.38-gnu/drivers/ide/piix.c linux-libre-2.6.39-gnu/drivers/ide/piix.c
--- linux-libre-2.6.38-gnu/drivers/ide/piix.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/piix.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,8 +8,8 @@
  *
  * Documentation:
  *
- *	Publically available from Intel web site. Errata documentation
- * is also publically available. As an aide to anyone hacking on this
+ *	Publicly available from Intel web site. Errata documentation
+ * is also publicly available. As an aide to anyone hacking on this
  * driver the list of errata that are relevant is below.going back to
  * PIIX4. Older device documentation is now a bit tricky to find.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/ide/sis5513.c linux-libre-2.6.39-gnu/drivers/ide/sis5513.c
--- linux-libre-2.6.38-gnu/drivers/ide/sis5513.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/sis5513.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 
 #define DRV_NAME "sis5513"
 
-/* registers layout and init values are chipset family dependant */
+/* registers layout and init values are chipset family dependent */
 
 #define ATA_16		0x01
 #define ATA_33		0x02
@@ -406,7 +406,7 @@
 					pci_name(dev));
 				chipset_family = ATA_133;
 
-				/* Check for 5513 compability mapping
+				/* Check for 5513 compatibility mapping
 				 * We must use this, else the port enabled code will fail,
 				 * as it expects the enablebits at 0x4a.
 				 */
diff -druN linux-libre-2.6.38-gnu/drivers/ide/triflex.c linux-libre-2.6.39-gnu/drivers/ide/triflex.c
--- linux-libre-2.6.38-gnu/drivers/ide/triflex.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/triflex.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
  * Loosely based on the piix & svwks drivers.
  *
  * Documentation:
- *	Not publically available.
+ *	Not publicly available.
  */
 
 #include <linux/types.h>
diff -druN linux-libre-2.6.38-gnu/drivers/ide/via82cxxx.c linux-libre-2.6.39-gnu/drivers/ide/via82cxxx.c
--- linux-libre-2.6.38-gnu/drivers/ide/via82cxxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ide/via82cxxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
  *	Andre Hedrick
  *
  * Documentation:
- *	Obsolete device documentation publically available from via.com.tw
+ *	Obsolete device documentation publicly available from via.com.tw
  *	Current device documentation available under NDA only
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/idle/intel_idle.c linux-libre-2.6.39-gnu/drivers/idle/intel_idle.c
--- linux-libre-2.6.38-gnu/drivers/idle/intel_idle.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/idle/intel_idle.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,7 +107,7 @@
 static struct cpuidle_state nehalem_cstates[MWAIT_MAX_NUM_CSTATES] = {
 	{ /* MWAIT C0 */ },
 	{ /* MWAIT C1 */
-		.name = "NHM-C1",
+		.name = "C1-NHM",
 		.desc = "MWAIT 0x00",
 		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
@@ -115,7 +115,7 @@
 		.target_residency = 6,
 		.enter = &intel_idle },
 	{ /* MWAIT C2 */
-		.name = "NHM-C3",
+		.name = "C3-NHM",
 		.desc = "MWAIT 0x10",
 		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
@@ -123,7 +123,7 @@
 		.target_residency = 80,
 		.enter = &intel_idle },
 	{ /* MWAIT C3 */
-		.name = "NHM-C6",
+		.name = "C6-NHM",
 		.desc = "MWAIT 0x20",
 		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
@@ -135,7 +135,7 @@
 static struct cpuidle_state snb_cstates[MWAIT_MAX_NUM_CSTATES] = {
 	{ /* MWAIT C0 */ },
 	{ /* MWAIT C1 */
-		.name = "SNB-C1",
+		.name = "C1-SNB",
 		.desc = "MWAIT 0x00",
 		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
@@ -143,7 +143,7 @@
 		.target_residency = 1,
 		.enter = &intel_idle },
 	{ /* MWAIT C2 */
-		.name = "SNB-C3",
+		.name = "C3-SNB",
 		.desc = "MWAIT 0x10",
 		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
@@ -151,7 +151,7 @@
 		.target_residency = 211,
 		.enter = &intel_idle },
 	{ /* MWAIT C3 */
-		.name = "SNB-C6",
+		.name = "C6-SNB",
 		.desc = "MWAIT 0x20",
 		.driver_data = (void *) 0x20,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
@@ -159,7 +159,7 @@
 		.target_residency = 345,
 		.enter = &intel_idle },
 	{ /* MWAIT C4 */
-		.name = "SNB-C7",
+		.name = "C7-SNB",
 		.desc = "MWAIT 0x30",
 		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
@@ -171,7 +171,7 @@
 static struct cpuidle_state atom_cstates[MWAIT_MAX_NUM_CSTATES] = {
 	{ /* MWAIT C0 */ },
 	{ /* MWAIT C1 */
-		.name = "ATM-C1",
+		.name = "C1-ATM",
 		.desc = "MWAIT 0x00",
 		.driver_data = (void *) 0x00,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
@@ -179,7 +179,7 @@
 		.target_residency = 4,
 		.enter = &intel_idle },
 	{ /* MWAIT C2 */
-		.name = "ATM-C2",
+		.name = "C2-ATM",
 		.desc = "MWAIT 0x10",
 		.driver_data = (void *) 0x10,
 		.flags = CPUIDLE_FLAG_TIME_VALID,
@@ -188,7 +188,7 @@
 		.enter = &intel_idle },
 	{ /* MWAIT C3 */ },
 	{ /* MWAIT C4 */
-		.name = "ATM-C4",
+		.name = "C4-ATM",
 		.desc = "MWAIT 0x30",
 		.driver_data = (void *) 0x30,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
@@ -197,7 +197,7 @@
 		.enter = &intel_idle },
 	{ /* MWAIT C5 */ },
 	{ /* MWAIT C6 */
-		.name = "ATM-C6",
+		.name = "C6-ATM",
 		.desc = "MWAIT 0x52",
 		.driver_data = (void *) 0x52,
 		.flags = CPUIDLE_FLAG_TIME_VALID | CPUIDLE_FLAG_TLB_FLUSHED,
diff -druN linux-libre-2.6.38-gnu/drivers/ieee802154/Makefile linux-libre-2.6.39-gnu/drivers/ieee802154/Makefile
--- linux-libre-2.6.38-gnu/drivers/ieee802154/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ieee802154/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,3 +1,3 @@
 obj-$(CONFIG_IEEE802154_FAKEHARD) += fakehard.o
 
-EXTRA_CFLAGS += -DDEBUG -DCONFIG_FFD
+ccflags-y := -DDEBUG -DCONFIG_FFD
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/core/addr.c linux-libre-2.6.39-gnu/drivers/infiniband/core/addr.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/core/addr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/core/addr.c	2011-05-19 00:06:34.000000000 -0400
@@ -183,20 +183,15 @@
 {
 	__be32 src_ip = src_in->sin_addr.s_addr;
 	__be32 dst_ip = dst_in->sin_addr.s_addr;
-	struct flowi fl;
 	struct rtable *rt;
 	struct neighbour *neigh;
 	int ret;
 
-	memset(&fl, 0, sizeof fl);
-	fl.nl_u.ip4_u.daddr = dst_ip;
-	fl.nl_u.ip4_u.saddr = src_ip;
-	fl.oif = addr->bound_dev_if;
-
-	ret = ip_route_output_key(&init_net, &rt, &fl);
-	if (ret)
+	rt = ip_route_output(&init_net, dst_ip, src_ip, 0, addr->bound_dev_if);
+	if (IS_ERR(rt)) {
+		ret = PTR_ERR(rt);
 		goto out;
-
+	}
 	src_in->sin_family = AF_INET;
 	src_in->sin_addr.s_addr = rt->rt_src;
 
@@ -209,7 +204,7 @@
 
 	/* If the device does ARP internally, return 'done' */
 	if (rt->dst.dev->flags & IFF_NOARP) {
-		rdma_copy_addr(addr, rt->dst.dev, NULL);
+		ret = rdma_copy_addr(addr, rt->dst.dev, NULL);
 		goto put;
 	}
 
@@ -236,28 +231,28 @@
 			 struct sockaddr_in6 *dst_in,
 			 struct rdma_dev_addr *addr)
 {
-	struct flowi fl;
+	struct flowi6 fl6;
 	struct neighbour *neigh;
 	struct dst_entry *dst;
 	int ret;
 
-	memset(&fl, 0, sizeof fl);
-	ipv6_addr_copy(&fl.fl6_dst, &dst_in->sin6_addr);
-	ipv6_addr_copy(&fl.fl6_src, &src_in->sin6_addr);
-	fl.oif = addr->bound_dev_if;
+	memset(&fl6, 0, sizeof fl6);
+	ipv6_addr_copy(&fl6.daddr, &dst_in->sin6_addr);
+	ipv6_addr_copy(&fl6.saddr, &src_in->sin6_addr);
+	fl6.flowi6_oif = addr->bound_dev_if;
 
-	dst = ip6_route_output(&init_net, NULL, &fl);
+	dst = ip6_route_output(&init_net, NULL, &fl6);
 	if ((ret = dst->error))
 		goto put;
 
-	if (ipv6_addr_any(&fl.fl6_src)) {
+	if (ipv6_addr_any(&fl6.saddr)) {
 		ret = ipv6_dev_get_saddr(&init_net, ip6_dst_idev(dst)->dev,
-					 &fl.fl6_dst, 0, &fl.fl6_src);
+					 &fl6.daddr, 0, &fl6.saddr);
 		if (ret)
 			goto put;
 
 		src_in->sin6_family = AF_INET6;
-		ipv6_addr_copy(&src_in->sin6_addr, &fl.fl6_src);
+		ipv6_addr_copy(&src_in->sin6_addr, &fl6.saddr);
 	}
 
 	if (dst->dev->flags & IFF_LOOPBACK) {
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/core/agent.c linux-libre-2.6.39-gnu/drivers/infiniband/core/agent.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/core/agent.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/core/agent.c	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,8 @@
 	agent = port_priv->agent[qpn];
 	ah = ib_create_ah_from_wc(agent->qp->pd, wc, grh, port_num);
 	if (IS_ERR(ah)) {
-		printk(KERN_ERR SPFX "ib_create_ah_from_wc error\n");
+		printk(KERN_ERR SPFX "ib_create_ah_from_wc error %ld\n",
+			PTR_ERR(ah));
 		return;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/core/cma.c linux-libre-2.6.39-gnu/drivers/infiniband/core/cma.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/core/cma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/core/cma.c	2011-05-19 00:06:34.000000000 -0400
@@ -308,11 +308,13 @@
 	kfree(mc);
 }
 
-static void cma_detach_from_dev(struct rdma_id_private *id_priv)
+static void cma_release_dev(struct rdma_id_private *id_priv)
 {
+	mutex_lock(&lock);
 	list_del(&id_priv->list);
 	cma_deref_dev(id_priv->cma_dev);
 	id_priv->cma_dev = NULL;
+	mutex_unlock(&lock);
 }
 
 static int cma_set_qkey(struct rdma_id_private *id_priv)
@@ -373,6 +375,7 @@
 	enum rdma_link_layer dev_ll = dev_addr->dev_type == ARPHRD_INFINIBAND ?
 		IB_LINK_LAYER_INFINIBAND : IB_LINK_LAYER_ETHERNET;
 
+	mutex_lock(&lock);
 	iboe_addr_get_sgid(dev_addr, &iboe_gid);
 	memcpy(&gid, dev_addr->src_dev_addr +
 	       rdma_addr_gid_offset(dev_addr), sizeof gid);
@@ -398,6 +401,7 @@
 	if (!ret)
 		cma_attach_to_dev(id_priv, cma_dev);
 
+	mutex_unlock(&lock);
 	return ret;
 }
 
@@ -904,9 +908,14 @@
 	state = cma_exch(id_priv, CMA_DESTROYING);
 	cma_cancel_operation(id_priv, state);
 
-	mutex_lock(&lock);
+	/*
+	 * Wait for any active callback to finish.  New callbacks will find
+	 * the id_priv state set to destroying and abort.
+	 */
+	mutex_lock(&id_priv->handler_mutex);
+	mutex_unlock(&id_priv->handler_mutex);
+
 	if (id_priv->cma_dev) {
-		mutex_unlock(&lock);
 		switch (rdma_node_get_transport(id_priv->id.device->node_type)) {
 		case RDMA_TRANSPORT_IB:
 			if (id_priv->cm_id.ib && !IS_ERR(id_priv->cm_id.ib))
@@ -920,10 +929,8 @@
 			break;
 		}
 		cma_leave_mc_groups(id_priv);
-		mutex_lock(&lock);
-		cma_detach_from_dev(id_priv);
+		cma_release_dev(id_priv);
 	}
-	mutex_unlock(&lock);
 
 	cma_release_port(id_priv);
 	cma_deref_id(id_priv);
@@ -1200,9 +1207,7 @@
 	}
 
 	mutex_lock_nested(&conn_id->handler_mutex, SINGLE_DEPTH_NESTING);
-	mutex_lock(&lock);
 	ret = cma_acquire_dev(conn_id);
-	mutex_unlock(&lock);
 	if (ret)
 		goto release_conn_id;
 
@@ -1210,6 +1215,11 @@
 	cm_id->context = conn_id;
 	cm_id->cm_handler = cma_ib_handler;
 
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (!ret) {
 		/*
@@ -1222,8 +1232,10 @@
 			ib_send_cm_mra(cm_id, CMA_CM_MRA_SETTING, NULL, 0);
 		mutex_unlock(&lock);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		goto out;
 	}
+	cma_deref_id(conn_id);
 
 	/* Destroy the CM ID by returning a non-zero value. */
 	conn_id->cm_id.ib = NULL;
@@ -1394,9 +1406,7 @@
 		goto out;
 	}
 
-	mutex_lock(&lock);
 	ret = cma_acquire_dev(conn_id);
-	mutex_unlock(&lock);
 	if (ret) {
 		mutex_unlock(&conn_id->handler_mutex);
 		rdma_destroy_id(new_cm_id);
@@ -1425,17 +1435,25 @@
 	event.param.conn.private_data_len = iw_event->private_data_len;
 	event.param.conn.initiator_depth = attr.max_qp_init_rd_atom;
 	event.param.conn.responder_resources = attr.max_qp_rd_atom;
+
+	/*
+	 * Protect against the user destroying conn_id from another thread
+	 * until we're done accessing it.
+	 */
+	atomic_inc(&conn_id->refcount);
 	ret = conn_id->id.event_handler(&conn_id->id, &event);
 	if (ret) {
 		/* User wants to destroy the CM ID */
 		conn_id->cm_id.iw = NULL;
 		cma_exch(conn_id, CMA_DESTROYING);
 		mutex_unlock(&conn_id->handler_mutex);
+		cma_deref_id(conn_id);
 		rdma_destroy_id(&conn_id->id);
 		goto out;
 	}
 
 	mutex_unlock(&conn_id->handler_mutex);
+	cma_deref_id(conn_id);
 
 out:
 	if (dev)
@@ -1951,20 +1969,11 @@
 
 	memset(&event, 0, sizeof event);
 	mutex_lock(&id_priv->handler_mutex);
-
-	/*
-	 * Grab mutex to block rdma_destroy_id() from removing the device while
-	 * we're trying to acquire it.
-	 */
-	mutex_lock(&lock);
-	if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED)) {
-		mutex_unlock(&lock);
+	if (!cma_comp_exch(id_priv, CMA_ADDR_QUERY, CMA_ADDR_RESOLVED))
 		goto out;
-	}
 
 	if (!status && !id_priv->cma_dev)
 		status = cma_acquire_dev(id_priv);
-	mutex_unlock(&lock);
 
 	if (status) {
 		if (!cma_comp_exch(id_priv, CMA_ADDR_RESOLVED, CMA_ADDR_BOUND))
@@ -2265,9 +2274,7 @@
 		if (ret)
 			goto err1;
 
-		mutex_lock(&lock);
 		ret = cma_acquire_dev(id_priv);
-		mutex_unlock(&lock);
 		if (ret)
 			goto err1;
 	}
@@ -2279,11 +2286,8 @@
 
 	return 0;
 err2:
-	if (id_priv->cma_dev) {
-		mutex_lock(&lock);
-		cma_detach_from_dev(id_priv);
-		mutex_unlock(&lock);
-	}
+	if (id_priv->cma_dev)
+		cma_release_dev(id_priv);
 err1:
 	cma_comp_exch(id_priv, CMA_ADDR_BOUND, CMA_IDLE);
 	return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/core/cm.c linux-libre-2.6.39-gnu/drivers/infiniband/core/cm.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/core/cm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/core/cm.c	2011-05-19 00:06:34.000000000 -0400
@@ -1988,6 +1988,10 @@
 		goto out;
 	}
 
+	if (cm_id->lap_state == IB_CM_LAP_SENT ||
+	    cm_id->lap_state == IB_CM_MRA_LAP_RCVD)
+		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
+
 	ret = cm_alloc_msg(cm_id_priv, &msg);
 	if (ret) {
 		cm_enter_timewait(cm_id_priv);
@@ -2129,6 +2133,10 @@
 		ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
 		break;
 	case IB_CM_ESTABLISHED:
+		if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT ||
+		    cm_id_priv->id.lap_state == IB_CM_MRA_LAP_RCVD)
+			ib_cancel_mad(cm_id_priv->av.port->mad_agent, cm_id_priv->msg);
+		break;
 	case IB_CM_MRA_REP_RCVD:
 		break;
 	case IB_CM_TIMEWAIT:
@@ -2349,9 +2357,18 @@
 		/* fall through */
 	case IB_CM_REP_RCVD:
 	case IB_CM_MRA_REP_SENT:
-	case IB_CM_ESTABLISHED:
 		cm_enter_timewait(cm_id_priv);
 		break;
+	case IB_CM_ESTABLISHED:
+		if (cm_id_priv->id.lap_state == IB_CM_LAP_UNINIT ||
+		    cm_id_priv->id.lap_state == IB_CM_LAP_SENT) {
+			if (cm_id_priv->id.lap_state == IB_CM_LAP_SENT)
+				ib_cancel_mad(cm_id_priv->av.port->mad_agent,
+					      cm_id_priv->msg);
+			cm_enter_timewait(cm_id_priv);
+			break;
+		}
+		/* fall through */
 	default:
 		spin_unlock_irq(&cm_id_priv->lock);
 		ret = -EINVAL;
@@ -2989,6 +3006,7 @@
 		goto out; /* No match. */
 	}
 	atomic_inc(&cur_cm_id_priv->refcount);
+	atomic_inc(&cm_id_priv->refcount);
 	spin_unlock_irq(&cm.lock);
 
 	cm_id_priv->id.cm_handler = cur_cm_id_priv->id.cm_handler;
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/amso1100/c2_ae.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/amso1100/c2_ae.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/amso1100/c2_ae.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/amso1100/c2_ae.c	2011-05-19 00:06:34.000000000 -0400
@@ -157,7 +157,7 @@
 	int status;
 
 	/*
-	 * retreive the message
+	 * retrieve the message
 	 */
 	wr = c2_mq_consume(mq);
 	if (!wr)
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/amso1100/c2_qp.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/amso1100/c2_qp.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/amso1100/c2_qp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/amso1100/c2_qp.c	2011-05-19 00:06:34.000000000 -0400
@@ -612,7 +612,7 @@
 	c2_unlock_cqs(send_cq, recv_cq);
 
 	/*
-	 * Destory qp in the rnic...
+	 * Destroy qp in the rnic...
 	 */
 	destroy_qp(c2dev, qp);
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/amso1100/c2_wr.h linux-libre-2.6.39-gnu/drivers/infiniband/hw/amso1100/c2_wr.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/amso1100/c2_wr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/amso1100/c2_wr.h	2011-05-19 00:06:34.000000000 -0400
@@ -131,7 +131,7 @@
 	 *          All the preceding IDs are fixed, and must not change.
 	 *          You can add new IDs, but must not remove or reorder
 	 *          any IDs. If you do, YOU will ruin any hope of
-	 *          compatability between versions.
+	 *          compatibility between versions.
 	 */
 	CCWR_LAST,
 
@@ -242,7 +242,7 @@
 /*
  *  to fix bug 1815 we define the max size allowable of the
  *  terminate message (per the IETF spec).Refer to the IETF
- *  protocal specification, section 12.1.6, page 64)
+ *  protocol specification, section 12.1.6, page 64)
  *  The message is prefixed by 20 types of DDP info.
  *
  *  Then the message has 6 bytes for the terminate control
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb3/iwch_cm.c	2011-05-19 00:06:34.000000000 -0400
@@ -338,23 +338,11 @@
 				 __be16 peer_port, u8 tos)
 {
 	struct rtable *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			 .ip4_u = {
-				   .daddr = peer_ip,
-				   .saddr = local_ip,
-				   .tos = tos}
-			 },
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			  .ports = {
-				    .sport = local_port,
-				    .dport = peer_port}
-			  }
-	};
 
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+	rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip,
+				   peer_port, local_port, IPPROTO_TCP,
+				   tos, 0);
+	if (IS_ERR(rt))
 		return NULL;
 	return rt;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/cm.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/cm.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/cm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/cm.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,9 +61,9 @@
 	NULL,
 };
 
-static int dack_mode;
+static int dack_mode = 1;
 module_param(dack_mode, int, 0644);
-MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=0)");
+MODULE_PARM_DESC(dack_mode, "Delayed ack mode (default=1)");
 
 int c4iw_max_read_depth = 8;
 module_param(c4iw_max_read_depth, int, 0644);
@@ -315,23 +315,11 @@
 				 __be16 peer_port, u8 tos)
 {
 	struct rtable *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			 .ip4_u = {
-				   .daddr = peer_ip,
-				   .saddr = local_ip,
-				   .tos = tos}
-			 },
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			  .ports = {
-				    .sport = local_port,
-				    .dport = peer_port}
-			  }
-	};
 
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+	rt = ip_route_output_ports(&init_net, NULL, peer_ip, local_ip,
+				   peer_port, local_port, IPPROTO_TCP,
+				   tos, 0);
+	if (IS_ERR(rt))
 		return NULL;
 	return rt;
 }
@@ -482,6 +470,7 @@
 	       TX_CHAN(ep->tx_chan) |
 	       SMAC_SEL(ep->smac_idx) |
 	       DSCP(ep->tos) |
+	       ULP_MODE(ULP_MODE_TCPDDP) |
 	       RCV_BUFSIZ(rcv_win>>10);
 	opt2 = RX_CHANNEL(0) |
 	       RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
@@ -1274,6 +1263,7 @@
 	       TX_CHAN(ep->tx_chan) |
 	       SMAC_SEL(ep->smac_idx) |
 	       DSCP(ep->tos) |
+	       ULP_MODE(ULP_MODE_TCPDDP) |
 	       RCV_BUFSIZ(rcv_win>>10);
 	opt2 = RX_CHANNEL(0) |
 	       RSS_QUEUE_VALID | RSS_QUEUE(ep->rss_qid);
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/device.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/device.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/device.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,17 +87,22 @@
 		return 1;
 
 	if (qp->ep)
-		cc = snprintf(qpd->buf + qpd->pos, space, "qp id %u state %u "
+		cc = snprintf(qpd->buf + qpd->pos, space,
+			     "qp sq id %u rq id %u state %u onchip %u "
 			     "ep tid %u state %u %pI4:%u->%pI4:%u\n",
-			     qp->wq.sq.qid, (int)qp->attr.state,
+			     qp->wq.sq.qid, qp->wq.rq.qid, (int)qp->attr.state,
+			     qp->wq.sq.flags & T4_SQ_ONCHIP,
 			     qp->ep->hwtid, (int)qp->ep->com.state,
 			     &qp->ep->com.local_addr.sin_addr.s_addr,
 			     ntohs(qp->ep->com.local_addr.sin_port),
 			     &qp->ep->com.remote_addr.sin_addr.s_addr,
 			     ntohs(qp->ep->com.remote_addr.sin_port));
 	else
-		cc = snprintf(qpd->buf + qpd->pos, space, "qp id %u state %u\n",
-			      qp->wq.sq.qid, (int)qp->attr.state);
+		cc = snprintf(qpd->buf + qpd->pos, space,
+			     "qp sq id %u rq id %u state %u onchip %u\n",
+			      qp->wq.sq.qid, qp->wq.rq.qid,
+			      (int)qp->attr.state,
+			      qp->wq.sq.flags & T4_SQ_ONCHIP);
 	if (cc < space)
 		qpd->pos += cc;
 	return 0;
@@ -368,7 +373,6 @@
 static void c4iw_remove(struct c4iw_dev *dev)
 {
 	PDBG("%s c4iw_dev %p\n", __func__,  dev);
-	cancel_delayed_work_sync(&dev->db_drop_task);
 	list_del(&dev->entry);
 	if (dev->registered)
 		c4iw_unregister_device(dev);
@@ -523,8 +527,16 @@
 	case CXGB4_STATE_START_RECOVERY:
 		printk(KERN_INFO MOD "%s: Fatal Error\n",
 		       pci_name(dev->rdev.lldi.pdev));
-		if (dev->registered)
+		dev->rdev.flags |= T4_FATAL_ERROR;
+		if (dev->registered) {
+			struct ib_event event;
+
+			memset(&event, 0, sizeof event);
+			event.event  = IB_EVENT_DEVICE_FATAL;
+			event.device = &dev->ibdev;
+			ib_dispatch_event(&event);
 			c4iw_unregister_device(dev);
+		}
 		break;
 	case CXGB4_STATE_DETACH:
 		printk(KERN_INFO MOD "%s: Detach\n",
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/iw_cxgb4.h	2011-05-19 00:06:34.000000000 -0400
@@ -176,7 +176,6 @@
 	struct idr mmidr;
 	spinlock_t lock;
 	struct list_head entry;
-	struct delayed_work db_drop_task;
 	struct dentry *debugfs_root;
 	u8 registered;
 };
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/qp.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/qp.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/qp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/qp.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,9 +31,9 @@
  */
 #include "iw_cxgb4.h"
 
-static int ocqp_support;
+static int ocqp_support = 1;
 module_param(ocqp_support, int, 0644);
-MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=0)");
+MODULE_PARM_DESC(ocqp_support, "Support on-chip SQs (default=1)");
 
 static void set_state(struct c4iw_qp *qhp, enum c4iw_qp_state state)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/t4.h linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/t4.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/cxgb4/t4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/cxgb4/t4.h	2011-05-19 00:06:34.000000000 -0400
@@ -507,8 +507,14 @@
 static inline void t4_hwcq_consume(struct t4_cq *cq)
 {
 	cq->bits_type_ts = cq->queue[cq->cidx].bits_type_ts;
-	if (++cq->cidx_inc == cq->size)
+	if (++cq->cidx_inc == (cq->size >> 4)) {
+		u32 val;
+
+		val = SEINTARM(0) | CIDXINC(cq->cidx_inc) | TIMERREG(7) |
+		      INGRESSQID(cq->cqid);
+		writel(val, cq->gts);
 		cq->cidx_inc = 0;
+	}
 	if (++cq->cidx == cq->size) {
 		cq->cidx = 0;
 		cq->gen ^= 1;
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_driver.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_driver.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -2392,7 +2392,7 @@
 	/*
 	 * clear SerdesEnable and turn the leds off; do this here because
 	 * we are unloading, so don't count on interrupts to move along
-	 * Turn the LEDs off explictly for the same reason.
+	 * Turn the LEDs off explicitly for the same reason.
 	 */
 	dd->ipath_f_quiet_serdes(dd);
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_file_ops.c	2011-05-19 00:06:34.000000000 -0400
@@ -1972,7 +1972,7 @@
 	 * 0 to 1.  So for those chips, we turn it off and then back on.
 	 * This will (very briefly) affect any other open ports, but the
 	 * duration is very short, and therefore isn't an issue.  We
-	 * explictly set the in-memory tail copy to 0 beforehand, so we
+	 * explicitly set the in-memory tail copy to 0 beforehand, so we
 	 * don't have to wait to be sure the DMA update has happened
 	 * (chip resets head/tail to 0 on transition to enable).
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_init_chip.c	2011-05-19 00:06:34.000000000 -0400
@@ -335,7 +335,7 @@
  * @dd: the infinipath device
  *
  * sanity check at least some of the values after reset, and
- * ensure no receive or transmit (explictly, in case reset
+ * ensure no receive or transmit (explicitly, in case reset
  * failed
  */
 static int init_chip_reset(struct ipath_devdata *dd)
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -557,6 +557,7 @@
 		dev_info(dev,"Unit %d is disabled, can't reset\n",
 			 dd->ipath_unit);
 		ret = -EINVAL;
+		goto bail;
 	}
 	ret = ipath_reset_device(dd->ipath_unit);
 bail:
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_ud.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_ud.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_ud.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_ud.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 	}
 
 	/*
-	 * A GRH is expected to preceed the data even if not
+	 * A GRH is expected to precede the data even if not
 	 * present on the wire.
 	 */
 	length = swqe->length;
@@ -515,7 +515,7 @@
 	}
 
 	/*
-	 * A GRH is expected to preceed the data even if not
+	 * A GRH is expected to precede the data even if not
 	 * present on the wire.
 	 */
 	wc.byte_len = tlen + sizeof(struct ib_grh);
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_user_pages.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,8 +53,8 @@
 }
 
 /* call with current->mm->mmap_sem held */
-static int __get_user_pages(unsigned long start_page, size_t num_pages,
-			struct page **p, struct vm_area_struct **vma)
+static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages,
+				  struct page **p, struct vm_area_struct **vma)
 {
 	unsigned long lock_limit;
 	size_t got;
@@ -165,7 +165,7 @@
 
 	down_write(&current->mm->mmap_sem);
 
-	ret = __get_user_pages(start_page, num_pages, p, NULL);
+	ret = __ipath_get_user_pages(start_page, num_pages, p, NULL);
 
 	up_write(&current->mm->mmap_sem);
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_user_sdma.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_user_sdma.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/ipath/ipath_user_sdma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/ipath/ipath_user_sdma.c	2011-05-19 00:06:34.000000000 -0400
@@ -236,7 +236,7 @@
 	return 1 + ((epage - spage) >> PAGE_SHIFT);
 }
 
-/* truncate length to page boundry */
+/* truncate length to page boundary */
 static int ipath_user_sdma_page_length(unsigned long addr, unsigned long len)
 {
 	const unsigned long offset = addr & ~PAGE_MASK;
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/mlx4/main.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/mlx4/main.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/mlx4/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/mlx4/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -625,7 +625,7 @@
 
 	err = mlx4_multicast_attach(mdev->dev, &mqp->mqp, gid->raw,
 				    !!(mqp->flags & MLX4_IB_QP_BLOCK_MULTICAST_LOOPBACK),
-				    MLX4_PROTOCOL_IB);
+				    MLX4_PROT_IB_IPV6);
 	if (err)
 		return err;
 
@@ -636,7 +636,7 @@
 	return 0;
 
 err_add:
-	mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
+	mlx4_multicast_detach(mdev->dev, &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6);
 	return err;
 }
 
@@ -666,7 +666,7 @@
 	struct mlx4_ib_gid_entry *ge;
 
 	err = mlx4_multicast_detach(mdev->dev,
-				    &mqp->mqp, gid->raw, MLX4_PROTOCOL_IB);
+				    &mqp->mqp, gid->raw, MLX4_PROT_IB_IPV6);
 	if (err)
 		return err;
 
@@ -721,7 +721,6 @@
 	if (err)
 		goto out;
 
-	dev->dev->rev_id = be32_to_cpup((__be32 *) (out_mad->data + 32));
 	memcpy(&dev->ib_dev.node_guid, out_mad->data + 12, 8);
 
 out:
@@ -954,7 +953,7 @@
 	mlx4_foreach_ib_transport_port(port, ibdev->dev) {
 		oldnd = iboe->netdevs[port - 1];
 		iboe->netdevs[port - 1] =
-			mlx4_get_protocol_dev(ibdev->dev, MLX4_PROTOCOL_EN, port);
+			mlx4_get_protocol_dev(ibdev->dev, MLX4_PROT_ETH, port);
 		if (oldnd != iboe->netdevs[port - 1]) {
 			if (iboe->netdevs[port - 1])
 				netdev_added(ibdev, port);
@@ -1207,7 +1206,7 @@
 	.add		= mlx4_ib_add,
 	.remove		= mlx4_ib_remove,
 	.event		= mlx4_ib_event,
-	.protocol	= MLX4_PROTOCOL_IB
+	.protocol	= MLX4_PROT_IB_IPV6
 };
 
 static int __init mlx4_ib_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/mthca/mthca_main.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/mthca/mthca_main.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/mthca/mthca_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/mthca/mthca_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -1043,6 +1043,9 @@
 		}
 	}
 
+	/* We can handle large RDMA requests, so allow larger segments. */
+	dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
+
 	mdev = (struct mthca_dev *) ib_alloc_device(sizeof *mdev);
 	if (!mdev) {
 		dev_err(&pdev->dev, "Device struct alloc failed, "
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes.c	2011-05-19 00:06:34.000000000 -0400
@@ -153,7 +153,8 @@
 				nesdev, nesdev->netdev[0]->name);
 		netdev = nesdev->netdev[0];
 		nesvnic = netdev_priv(netdev);
-		is_bonded = (netdev->master == event_netdev);
+		is_bonded = netif_is_bond_slave(netdev) &&
+			    (netdev->master == event_netdev);
 		if ((netdev == event_netdev) || is_bonded) {
 			if (nesvnic->rdma_enabled == 0) {
 				nes_debug(NES_DBG_NETDEV, "Returning without processing event for %s since"
@@ -693,7 +694,7 @@
 	nesdev->netdev_count++;
 	nesdev->nesadapter->netdev_count++;
 
-	printk(KERN_ERR PFX "%s: NetEffect RNIC driver successfully loaded.\n",
+	printk(KERN_INFO PFX "%s: NetEffect RNIC driver successfully loaded.\n",
 			pci_name(pcidev));
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes_cm.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes_cm.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes_cm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes_cm.c	2011-05-19 00:06:34.000000000 -0400
@@ -1104,21 +1104,19 @@
 static int nes_addr_resolve_neigh(struct nes_vnic *nesvnic, u32 dst_ip, int arpindex)
 {
 	struct rtable *rt;
-	struct flowi fl;
 	struct neighbour *neigh;
 	int rc = arpindex;
 	struct net_device *netdev;
 	struct nes_adapter *nesadapter = nesvnic->nesdev->nesadapter;
 
-	memset(&fl, 0, sizeof fl);
-	fl.nl_u.ip4_u.daddr = htonl(dst_ip);
-	if (ip_route_output_key(&init_net, &rt, &fl)) {
+	rt = ip_route_output(&init_net, htonl(dst_ip), 0, 0, 0);
+	if (IS_ERR(rt)) {
 		printk(KERN_ERR "%s: ip_route_output_key failed for 0x%08X\n",
 				__func__, dst_ip);
 		return rc;
 	}
 
-	if (nesvnic->netdev->master)
+	if (netif_is_bond_slave(nesvnic->netdev))
 		netdev = nesvnic->netdev->master;
 	else
 		netdev = nesvnic->netdev;
@@ -1399,7 +1397,7 @@
 		cleanup_retrans_entry(cm_node);
 		cm_node->state = NES_CM_STATE_CLOSING;
 		send_ack(cm_node, NULL);
-		/* Wait for ACK as this is simultanous close..
+		/* Wait for ACK as this is simultaneous close..
 		* After we receive ACK, do not send anything..
 		* Just rm the node.. Done.. */
 		break;
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes_hw.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes_hw.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes_hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes_hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,7 +80,7 @@
 
 #ifdef CONFIG_INFINIBAND_NES_DEBUG
 static unsigned char *nes_iwarp_state_str[] = {
-	"Non-Existant",
+	"Non-Existent",
 	"Idle",
 	"RTS",
 	"Closing",
@@ -91,7 +91,7 @@
 };
 
 static unsigned char *nes_tcp_state_str[] = {
-	"Non-Existant",
+	"Non-Existent",
 	"Closed",
 	"Listen",
 	"SYN Sent",
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes_nic.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes_nic.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/nes/nes_nic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/nes/nes_nic.c	2011-05-19 00:06:34.000000000 -0400
@@ -902,7 +902,7 @@
 		nes_write_indexed(nesdev, NES_IDX_NIC_UNICAST_ALL, nic_active);
 	}
 
-	nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscous = %d, All Multicast = %d.\n",
+	nes_debug(NES_DBG_NIC_RX, "Number of MC entries = %d, Promiscuous = %d, All Multicast = %d.\n",
 		  mc_count, !!(netdev->flags & IFF_PROMISC),
 		  !!(netdev->flags & IFF_ALLMULTI));
 	if (!mc_all_on) {
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_file_ops.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_file_ops.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_file_ops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_file_ops.c	2011-05-19 00:06:34.000000000 -0400
@@ -1539,7 +1539,7 @@
 
 		/*
 		 * If process has NOT already set it's affinity, select and
-		 * reserve a processor for it, as a rendevous for all
+		 * reserve a processor for it, as a rendezvous for all
 		 * users of the driver.  If they don't actually later
 		 * set affinity to this cpu, or set it to some other cpu,
 		 * it just means that sooner or later we don't recommend
@@ -1657,7 +1657,7 @@
 	 * 0 to 1.  So for those chips, we turn it off and then back on.
 	 * This will (very briefly) affect any other open ctxts, but the
 	 * duration is very short, and therefore isn't an issue.  We
-	 * explictly set the in-memory tail copy to 0 beforehand, so we
+	 * explicitly set the in-memory tail copy to 0 beforehand, so we
 	 * don't have to wait to be sure the DMA update has happened
 	 * (chip resets head/tail to 0 on transition to enable).
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib.h linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib.h	2011-05-19 00:06:34.000000000 -0400
@@ -653,7 +653,7 @@
 
 /* device data struct now contains only "general per-device" info.
  * fields related to a physical IB port are in a qib_pportdata struct,
- * described above) while fields only used by a particualr chip-type are in
+ * described above) while fields only used by a particular chip-type are in
  * a qib_chipdata struct, whose contents are opaque to this file.
  */
 struct qib_devdata {
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_iba6120.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_iba6120.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_iba6120.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_iba6120.c	2011-05-19 00:06:34.000000000 -0400
@@ -1799,7 +1799,7 @@
 	/*
 	 * Keep chip from being accessed until we are ready.  Use
 	 * writeq() directly, to allow the write even though QIB_PRESENT
-	 * isnt' set.
+	 * isn't set.
 	 */
 	dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
 	dd->int_counter = 0; /* so we check interrupts work again */
@@ -2171,7 +2171,7 @@
 		 * Init the context registers also; if we were
 		 * disabled, tail and head should both be zero
 		 * already from the enable, but since we don't
-		 * know, we have to do it explictly.
+		 * know, we have to do it explicitly.
 		 */
 		val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt);
 		qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt);
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_iba7220.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_iba7220.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_iba7220.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_iba7220.c	2011-05-19 00:06:34.000000000 -0400
@@ -2111,7 +2111,7 @@
 	/*
 	 * Keep chip from being accessed until we are ready.  Use
 	 * writeq() directly, to allow the write even though QIB_PRESENT
-	 * isnt' set.
+	 * isn't set.
 	 */
 	dd->flags &= ~(QIB_INITTED | QIB_PRESENT);
 	dd->int_counter = 0; /* so we check interrupts work again */
@@ -2479,7 +2479,7 @@
 		 * we command the link down.  As with width, only write the
 		 * actual register if the link is currently down, otherwise
 		 * takes effect on next link change.  Since setting is being
-		 * explictly requested (via MAD or sysfs), clear autoneg
+		 * explicitly requested (via MAD or sysfs), clear autoneg
 		 * failure status if speed autoneg is enabled.
 		 */
 		ppd->link_speed_enabled = val;
@@ -2778,7 +2778,7 @@
 		 * Init the context registers also; if we were
 		 * disabled, tail and head should both be zero
 		 * already from the enable, but since we don't
-		 * know, we have to do it explictly.
+		 * know, we have to do it explicitly.
 		 */
 		val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt);
 		qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt);
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_iba7322.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_iba7322.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_iba7322.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_iba7322.c	2011-05-19 00:06:34.000000000 -0400
@@ -3299,7 +3299,7 @@
 	/*
 	 * Keep chip from being accessed until we are ready.  Use
 	 * writeq() directly, to allow the write even though QIB_PRESENT
-	 * isnt' set.
+	 * isn't set.
 	 */
 	dd->flags &= ~(QIB_INITTED | QIB_PRESENT | QIB_BADINTR);
 	dd->flags |= QIB_DOING_RESET;
@@ -3727,7 +3727,7 @@
 		/*
 		 * As with width, only write the actual register if the
 		 * link is currently down, otherwise takes effect on next
-		 * link change.  Since setting is being explictly requested
+		 * link change.  Since setting is being explicitly requested
 		 * (via MAD or sysfs), clear autoneg failure status if speed
 		 * autoneg is enabled.
 		 */
@@ -4163,7 +4163,7 @@
 		 * Init the context registers also; if we were
 		 * disabled, tail and head should both be zero
 		 * already from the enable, but since we don't
-		 * know, we have to do it explictly.
+		 * know, we have to do it explicitly.
 		 */
 		val = qib_read_ureg32(dd, ur_rcvegrindextail, ctxt);
 		qib_write_ureg(dd, ur_rcvegrindexhead, val, ctxt);
@@ -5582,9 +5582,16 @@
 	 * even on failure to read cable information.  We don't
 	 * get here for QME, so IS_QME check not needed here.
 	 */
-	le2 = (!ret && qd->cache.atten[1] >= qib_long_atten &&
-	       !ppd->dd->cspec->r1 && QSFP_IS_CU(qd->cache.tech)) ?
-		LE2_5m : LE2_DEFAULT;
+	if (!ret && !ppd->dd->cspec->r1) {
+		if (QSFP_IS_ACTIVE_FAR(qd->cache.tech))
+			le2 = LE2_QME;
+		else if (qd->cache.atten[1] >= qib_long_atten &&
+			 QSFP_IS_CU(qd->cache.tech))
+			le2 = LE2_5m;
+		else
+			le2 = LE2_DEFAULT;
+	} else
+		le2 = LE2_DEFAULT;
 	ibsd_wr_allchans(ppd, 13, (le2 << 7), BMASK(9, 7));
 	init_txdds_table(ppd, 0);
 }
@@ -7476,7 +7483,7 @@
 	/*       Baseline Wander Correction Gain [13:4-0] (leave as default) */
 	/*       Baseline Wander Correction Gain [3:7-5] (leave as default) */
 	/*       Data Rate Select [5:7-6] (leave as default) */
-	/*       RX Parralel Word Width [3:10-8] (leave as default) */
+	/*       RX Parallel Word Width [3:10-8] (leave as default) */
 
 	/* RX REST */
 	/*       Single- or Multi-channel reset */
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_init.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_init.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -346,7 +346,7 @@
  * @dd: the qlogic_ib device
  *
  * sanity check at least some of the values after reset, and
- * ensure no receive or transmit (explictly, in case reset
+ * ensure no receive or transmit (explicitly, in case reset
  * failed
  */
 static int init_after_reset(struct qib_devdata *dd)
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_mad.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_mad.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_mad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_mad.c	2011-05-19 00:06:34.000000000 -0400
@@ -464,8 +464,9 @@
 	memset(smp->data, 0, sizeof(smp->data));
 
 	/* Only return the mkey if the protection field allows it. */
-	if (smp->method == IB_MGMT_METHOD_SET || ibp->mkey == smp->mkey ||
-	    ibp->mkeyprot == 0)
+	if (!(smp->method == IB_MGMT_METHOD_GET &&
+	      ibp->mkey != smp->mkey &&
+	      ibp->mkeyprot == 1))
 		pip->mkey = ibp->mkey;
 	pip->gid_prefix = ibp->gid_prefix;
 	lid = ppd->lid;
@@ -705,7 +706,7 @@
 	lwe = pip->link_width_enabled;
 	if (lwe) {
 		if (lwe == 0xFF)
-			lwe = ppd->link_width_supported;
+			set_link_width_enabled(ppd, ppd->link_width_supported);
 		else if (lwe >= 16 || (lwe & ~ppd->link_width_supported))
 			smp->status |= IB_SMP_INVALID_FIELD;
 		else if (lwe != ppd->link_width_enabled)
@@ -720,7 +721,8 @@
 		 * speeds.
 		 */
 		if (lse == 15)
-			lse = ppd->link_speed_supported;
+			set_link_speed_enabled(ppd,
+					       ppd->link_speed_supported);
 		else if (lse >= 8 || (lse & ~ppd->link_speed_supported))
 			smp->status |= IB_SMP_INVALID_FIELD;
 		else if (lse != ppd->link_speed_enabled)
@@ -849,7 +851,7 @@
 	if (clientrereg)
 		pip->clientrereg_resv_subnetto |= 0x80;
 
-	goto done;
+	goto get_only;
 
 err:
 	smp->status |= IB_SMP_INVALID_FIELD;
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_mad.h linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_mad.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_mad.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_mad.h	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
 
 		struct {
 			__be16	reserved;
-			__be16	lid;		/* LID where change occured */
+			__be16	lid;		/* LID where change occurred */
 			u8	reserved2;
 			u8	local_changes;	/* low bit - local changes */
 			__be32	new_cap_mask;	/* new capability mask */
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_qsfp.h linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_qsfp.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_qsfp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_qsfp.h	2011-05-19 00:06:34.000000000 -0400
@@ -79,6 +79,8 @@
 extern const char *const qib_qsfp_devtech[16];
 /* Active Equalization includes fiber, copper full EQ, and copper near Eq */
 #define QSFP_IS_ACTIVE(tech) ((0xA2FF >> ((tech) >> 4)) & 1)
+/* Active Equalization includes fiber, copper full EQ, and copper far Eq */
+#define QSFP_IS_ACTIVE_FAR(tech) ((0x32FF >> ((tech) >> 4)) & 1)
 /* Attenuation should be valid for copper other than full/near Eq */
 #define QSFP_HAS_ATTEN(tech) ((0x4D00 >> ((tech) >> 4)) & 1)
 /* Length is only valid if technology is "copper" */
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_twsi.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_twsi.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_twsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_twsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
  * QLogic_IB "Two Wire Serial Interface" driver.
  * Originally written for a not-quite-i2c serial eeprom, which is
  * still used on some supported boards. Later boards have added a
- * variety of other uses, most board-specific, so teh bit-boffing
+ * variety of other uses, most board-specific, so the bit-boffing
  * part has been split off to this file, while the other parts
  * have been moved to chip-specific files.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_ud.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_ud.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_ud.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_ud.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,7 @@
 	}
 
 	/*
-	 * A GRH is expected to preceed the data even if not
+	 * A GRH is expected to precede the data even if not
 	 * present on the wire.
 	 */
 	length = swqe->length;
@@ -520,7 +520,7 @@
 		goto drop;
 
 	/*
-	 * A GRH is expected to preceed the data even if not
+	 * A GRH is expected to precede the data even if not
 	 * present on the wire.
 	 */
 	wc.byte_len = tlen + sizeof(struct ib_grh);
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_user_pages.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_user_pages.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_user_pages.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_user_pages.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,8 +51,8 @@
 /*
  * Call with current->mm->mmap_sem held.
  */
-static int __get_user_pages(unsigned long start_page, size_t num_pages,
-			    struct page **p, struct vm_area_struct **vma)
+static int __qib_get_user_pages(unsigned long start_page, size_t num_pages,
+				struct page **p, struct vm_area_struct **vma)
 {
 	unsigned long lock_limit;
 	size_t got;
@@ -136,7 +136,7 @@
 
 	down_write(&current->mm->mmap_sem);
 
-	ret = __get_user_pages(start_page, num_pages, p, NULL);
+	ret = __qib_get_user_pages(start_page, num_pages, p, NULL);
 
 	up_write(&current->mm->mmap_sem);
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_user_sdma.c linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_user_sdma.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/hw/qib/qib_user_sdma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/hw/qib/qib_user_sdma.c	2011-05-19 00:06:34.000000000 -0400
@@ -239,7 +239,7 @@
 }
 
 /*
- * Truncate length to page boundry.
+ * Truncate length to page boundary.
  */
 static int qib_user_sdma_page_length(unsigned long addr, unsigned long len)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c linux-libre-2.6.39-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/ulp/iser/iscsi_iser.c	2011-05-19 00:06:34.000000000 -0400
@@ -532,6 +532,29 @@
 	stats->custom[3].value = conn->fmr_unalign_cnt;
 }
 
+static int iscsi_iser_get_ep_param(struct iscsi_endpoint *ep,
+				   enum iscsi_param param, char *buf)
+{
+	struct iser_conn *ib_conn = ep->dd_data;
+	int len;
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_PORT:
+	case ISCSI_PARAM_CONN_ADDRESS:
+		if (!ib_conn || !ib_conn->cma_id)
+			return -ENOTCONN;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+					&ib_conn->cma_id->route.addr.dst_addr,
+					param, buf);
+		break;
+	default:
+		return -ENOSYS;
+	}
+
+	return len;
+}
+
 static struct iscsi_endpoint *
 iscsi_iser_ep_connect(struct Scsi_Host *shost, struct sockaddr *dst_addr,
 		      int non_blocking)
@@ -637,6 +660,8 @@
 				  ISCSI_MAX_BURST |
 				  ISCSI_PDU_INORDER_EN |
 				  ISCSI_DATASEQ_INORDER_EN |
+				  ISCSI_CONN_PORT |
+				  ISCSI_CONN_ADDRESS |
 				  ISCSI_EXP_STATSN |
 				  ISCSI_PERSISTENT_PORT |
 				  ISCSI_PERSISTENT_ADDRESS |
@@ -659,6 +684,7 @@
 	.destroy_conn           = iscsi_iser_conn_destroy,
 	.set_param              = iscsi_iser_set_param,
 	.get_conn_param		= iscsi_conn_get_param,
+	.get_ep_param		= iscsi_iser_get_ep_param,
 	.get_session_param	= iscsi_session_get_param,
 	.start_conn             = iscsi_iser_conn_start,
 	.stop_conn              = iscsi_iser_conn_stop,
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h linux-libre-2.6.39-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/ulp/iser/iscsi_iser.h	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
 #define SIZE_4K	(1UL << SHIFT_4K)
 #define MASK_4K	(~(SIZE_4K-1))
 
-					/* support upto 512KB in one RDMA */
+					/* support up to 512KB in one RDMA */
 #define ISCSI_ISER_SG_TABLESIZE         (0x80000 >> SHIFT_4K)
 #define ISER_DEF_CMD_PER_LUN		128
 
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/ulp/srp/ib_srp.c linux-libre-2.6.39-gnu/drivers/infiniband/ulp/srp/ib_srp.c
--- linux-libre-2.6.38-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/ulp/srp/ib_srp.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,25 +59,31 @@
 		   "v" DRV_VERSION " (" DRV_RELDATE ")");
 MODULE_LICENSE("Dual BSD/GPL");
 
-static int srp_sg_tablesize = SRP_DEF_SG_TABLESIZE;
-static int srp_max_iu_len;
+static unsigned int srp_sg_tablesize;
+static unsigned int cmd_sg_entries;
+static unsigned int indirect_sg_entries;
+static bool allow_ext_sg;
+static int topspin_workarounds = 1;
 
-module_param(srp_sg_tablesize, int, 0444);
-MODULE_PARM_DESC(srp_sg_tablesize,
-		 "Max number of gather/scatter entries per I/O (default is 12, max 255)");
+module_param(srp_sg_tablesize, uint, 0444);
+MODULE_PARM_DESC(srp_sg_tablesize, "Deprecated name for cmd_sg_entries");
 
-static int topspin_workarounds = 1;
+module_param(cmd_sg_entries, uint, 0444);
+MODULE_PARM_DESC(cmd_sg_entries,
+		 "Default number of gather/scatter entries in the SRP command (default is 12, max 255)");
+
+module_param(indirect_sg_entries, uint, 0444);
+MODULE_PARM_DESC(indirect_sg_entries,
+		 "Default max number of gather/scatter entries (default is 12, max is " __stringify(SCSI_MAX_SG_CHAIN_SEGMENTS) ")");
+
+module_param(allow_ext_sg, bool, 0444);
+MODULE_PARM_DESC(allow_ext_sg,
+		  "Default behavior when there are more than cmd_sg_entries S/G entries after mapping; fails the request when false (default false)");
 
 module_param(topspin_workarounds, int, 0444);
 MODULE_PARM_DESC(topspin_workarounds,
 		 "Enable workarounds for Topspin/Cisco SRP target bugs if != 0");
 
-static int mellanox_workarounds = 1;
-
-module_param(mellanox_workarounds, int, 0444);
-MODULE_PARM_DESC(mellanox_workarounds,
-		 "Enable workarounds for Mellanox SRP target bugs if != 0");
-
 static void srp_add_one(struct ib_device *device);
 static void srp_remove_one(struct ib_device *device);
 static void srp_recv_completion(struct ib_cq *cq, void *target_ptr);
@@ -114,14 +120,6 @@
 		 !memcmp(&target->ioc_guid, cisco_oui, sizeof cisco_oui));
 }
 
-static int srp_target_is_mellanox(struct srp_target_port *target)
-{
-	static const u8 mellanox_oui[3] = { 0x00, 0x02, 0xc9 };
-
-	return mellanox_workarounds &&
-		!memcmp(&target->ioc_guid, mellanox_oui, sizeof mellanox_oui);
-}
-
 static struct srp_iu *srp_alloc_iu(struct srp_host *host, size_t size,
 				   gfp_t gfp_mask,
 				   enum dma_data_direction direction)
@@ -378,7 +376,7 @@
 
 	req->priv.opcode     	= SRP_LOGIN_REQ;
 	req->priv.tag        	= 0;
-	req->priv.req_it_iu_len = cpu_to_be32(srp_max_iu_len);
+	req->priv.req_it_iu_len = cpu_to_be32(target->max_iu_len);
 	req->priv.req_buf_fmt 	= cpu_to_be16(SRP_BUF_FORMAT_DIRECT |
 					      SRP_BUF_FORMAT_INDIRECT);
 	/*
@@ -456,6 +454,24 @@
 	return changed;
 }
 
+static void srp_free_req_data(struct srp_target_port *target)
+{
+	struct ib_device *ibdev = target->srp_host->srp_dev->dev;
+	struct srp_request *req;
+	int i;
+
+	for (i = 0, req = target->req_ring; i < SRP_CMD_SQ_SIZE; ++i, ++req) {
+		kfree(req->fmr_list);
+		kfree(req->map_page);
+		if (req->indirect_dma_addr) {
+			ib_dma_unmap_single(ibdev, req->indirect_dma_addr,
+					    target->indirect_size,
+					    DMA_TO_DEVICE);
+		}
+		kfree(req->indirect_desc);
+	}
+}
+
 static void srp_remove_work(struct work_struct *work)
 {
 	struct srp_target_port *target =
@@ -472,6 +488,7 @@
 	scsi_remove_host(target->scsi_host);
 	ib_destroy_cm_id(target->cm_id);
 	srp_free_target_ib(target);
+	srp_free_req_data(target);
 	scsi_host_put(target->scsi_host);
 }
 
@@ -535,18 +552,20 @@
 			   struct srp_target_port *target,
 			   struct srp_request *req)
 {
+	struct ib_device *ibdev = target->srp_host->srp_dev->dev;
+	struct ib_pool_fmr **pfmr;
+
 	if (!scsi_sglist(scmnd) ||
 	    (scmnd->sc_data_direction != DMA_TO_DEVICE &&
 	     scmnd->sc_data_direction != DMA_FROM_DEVICE))
 		return;
 
-	if (req->fmr) {
-		ib_fmr_pool_unmap(req->fmr);
-		req->fmr = NULL;
-	}
+	pfmr = req->fmr_list;
+	while (req->nfmr--)
+		ib_fmr_pool_unmap(*pfmr++);
 
-	ib_dma_unmap_sg(target->srp_host->srp_dev->dev, scsi_sglist(scmnd),
-			scsi_sg_count(scmnd), scmnd->sc_data_direction);
+	ib_dma_unmap_sg(ibdev, scsi_sglist(scmnd), scsi_sg_count(scmnd),
+			scmnd->sc_data_direction);
 }
 
 static void srp_remove_req(struct srp_target_port *target,
@@ -645,96 +664,151 @@
 	return ret;
 }
 
-static int srp_map_fmr(struct srp_target_port *target, struct scatterlist *scat,
-		       int sg_cnt, struct srp_request *req,
-		       struct srp_direct_buf *buf)
+static void srp_map_desc(struct srp_map_state *state, dma_addr_t dma_addr,
+			 unsigned int dma_len, u32 rkey)
 {
-	u64 io_addr = 0;
-	u64 *dma_pages;
-	u32 len;
-	int page_cnt;
-	int i, j;
-	int ret;
-	struct srp_device *dev = target->srp_host->srp_dev;
-	struct ib_device *ibdev = dev->dev;
-	struct scatterlist *sg;
+	struct srp_direct_buf *desc = state->desc;
 
-	if (!dev->fmr_pool)
-		return -ENODEV;
+	desc->va = cpu_to_be64(dma_addr);
+	desc->key = cpu_to_be32(rkey);
+	desc->len = cpu_to_be32(dma_len);
 
-	if (srp_target_is_mellanox(target) &&
-	    (ib_sg_dma_address(ibdev, &scat[0]) & ~dev->fmr_page_mask))
-		return -EINVAL;
+	state->total_len += dma_len;
+	state->desc++;
+	state->ndesc++;
+}
 
-	len = page_cnt = 0;
-	scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
-		unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
+static int srp_map_finish_fmr(struct srp_map_state *state,
+			      struct srp_target_port *target)
+{
+	struct srp_device *dev = target->srp_host->srp_dev;
+	struct ib_pool_fmr *fmr;
+	u64 io_addr = 0;
 
-		if (ib_sg_dma_address(ibdev, sg) & ~dev->fmr_page_mask) {
-			if (i > 0)
-				return -EINVAL;
-			else
-				++page_cnt;
-		}
-		if ((ib_sg_dma_address(ibdev, sg) + dma_len) &
-		    ~dev->fmr_page_mask) {
-			if (i < sg_cnt - 1)
-				return -EINVAL;
-			else
-				++page_cnt;
-		}
+	if (!state->npages)
+		return 0;
 
-		len += dma_len;
+	if (state->npages == 1) {
+		srp_map_desc(state, state->base_dma_addr, state->fmr_len,
+			     target->rkey);
+		state->npages = state->fmr_len = 0;
+		return 0;
 	}
 
-	page_cnt += len >> dev->fmr_page_shift;
-	if (page_cnt > SRP_FMR_SIZE)
-		return -ENOMEM;
+	fmr = ib_fmr_pool_map_phys(dev->fmr_pool, state->pages,
+				   state->npages, io_addr);
+	if (IS_ERR(fmr))
+		return PTR_ERR(fmr);
 
-	dma_pages = kmalloc(sizeof (u64) * page_cnt, GFP_ATOMIC);
-	if (!dma_pages)
-		return -ENOMEM;
+	*state->next_fmr++ = fmr;
+	state->nfmr++;
 
-	page_cnt = 0;
-	scsi_for_each_sg(req->scmnd, sg, sg_cnt, i) {
-		unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
+	srp_map_desc(state, 0, state->fmr_len, fmr->fmr->rkey);
+	state->npages = state->fmr_len = 0;
+	return 0;
+}
 
-		for (j = 0; j < dma_len; j += dev->fmr_page_size)
-			dma_pages[page_cnt++] =
-				(ib_sg_dma_address(ibdev, sg) &
-				 dev->fmr_page_mask) + j;
+static void srp_map_update_start(struct srp_map_state *state,
+				 struct scatterlist *sg, int sg_index,
+				 dma_addr_t dma_addr)
+{
+	state->unmapped_sg = sg;
+	state->unmapped_index = sg_index;
+	state->unmapped_addr = dma_addr;
+}
+
+static int srp_map_sg_entry(struct srp_map_state *state,
+			    struct srp_target_port *target,
+			    struct scatterlist *sg, int sg_index,
+			    int use_fmr)
+{
+	struct srp_device *dev = target->srp_host->srp_dev;
+	struct ib_device *ibdev = dev->dev;
+	dma_addr_t dma_addr = ib_sg_dma_address(ibdev, sg);
+	unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
+	unsigned int len;
+	int ret;
+
+	if (!dma_len)
+		return 0;
+
+	if (use_fmr == SRP_MAP_NO_FMR) {
+		/* Once we're in direct map mode for a request, we don't
+		 * go back to FMR mode, so no need to update anything
+		 * other than the descriptor.
+		 */
+		srp_map_desc(state, dma_addr, dma_len, target->rkey);
+		return 0;
 	}
 
-	req->fmr = ib_fmr_pool_map_phys(dev->fmr_pool,
-					dma_pages, page_cnt, io_addr);
-	if (IS_ERR(req->fmr)) {
-		ret = PTR_ERR(req->fmr);
-		req->fmr = NULL;
-		goto out;
+	/* If we start at an offset into the FMR page, don't merge into
+	 * the current FMR. Finish it out, and use the kernel's MR for this
+	 * sg entry. This is to avoid potential bugs on some SRP targets
+	 * that were never quite defined, but went away when the initiator
+	 * avoided using FMR on such page fragments.
+	 */
+	if (dma_addr & ~dev->fmr_page_mask || dma_len > dev->fmr_max_size) {
+		ret = srp_map_finish_fmr(state, target);
+		if (ret)
+			return ret;
+
+		srp_map_desc(state, dma_addr, dma_len, target->rkey);
+		srp_map_update_start(state, NULL, 0, 0);
+		return 0;
 	}
 
-	buf->va  = cpu_to_be64(ib_sg_dma_address(ibdev, &scat[0]) &
-			       ~dev->fmr_page_mask);
-	buf->key = cpu_to_be32(req->fmr->fmr->rkey);
-	buf->len = cpu_to_be32(len);
+	/* If this is the first sg to go into the FMR, save our position.
+	 * We need to know the first unmapped entry, its index, and the
+	 * first unmapped address within that entry to be able to restart
+	 * mapping after an error.
+	 */
+	if (!state->unmapped_sg)
+		srp_map_update_start(state, sg, sg_index, dma_addr);
 
-	ret = 0;
+	while (dma_len) {
+		if (state->npages == SRP_FMR_SIZE) {
+			ret = srp_map_finish_fmr(state, target);
+			if (ret)
+				return ret;
 
-out:
-	kfree(dma_pages);
+			srp_map_update_start(state, sg, sg_index, dma_addr);
+		}
 
+		len = min_t(unsigned int, dma_len, dev->fmr_page_size);
+
+		if (!state->npages)
+			state->base_dma_addr = dma_addr;
+		state->pages[state->npages++] = dma_addr;
+		state->fmr_len += len;
+		dma_addr += len;
+		dma_len -= len;
+	}
+
+	/* If the last entry of the FMR wasn't a full page, then we need to
+	 * close it out and start a new one -- we can only merge at page
+	 * boundries.
+	 */
+	ret = 0;
+	if (len != dev->fmr_page_size) {
+		ret = srp_map_finish_fmr(state, target);
+		if (!ret)
+			srp_map_update_start(state, NULL, 0, 0);
+	}
 	return ret;
 }
 
 static int srp_map_data(struct scsi_cmnd *scmnd, struct srp_target_port *target,
 			struct srp_request *req)
 {
-	struct scatterlist *scat;
+	struct scatterlist *scat, *sg;
 	struct srp_cmd *cmd = req->cmd->buf;
-	int len, nents, count;
-	u8 fmt = SRP_DATA_DESC_DIRECT;
+	int i, len, nents, count, use_fmr;
 	struct srp_device *dev;
 	struct ib_device *ibdev;
+	struct srp_map_state state;
+	struct srp_indirect_buf *indirect_hdr;
+	u32 table_len;
+	u8 fmt;
 
 	if (!scsi_sglist(scmnd) || scmnd->sc_data_direction == DMA_NONE)
 		return sizeof (struct srp_cmd);
@@ -754,6 +828,8 @@
 	ibdev = dev->dev;
 
 	count = ib_dma_map_sg(ibdev, scat, nents, scmnd->sc_data_direction);
+	if (unlikely(count == 0))
+		return -EIO;
 
 	fmt = SRP_DATA_DESC_DIRECT;
 	len = sizeof (struct srp_cmd) +	sizeof (struct srp_direct_buf);
@@ -770,49 +846,99 @@
 		buf->va  = cpu_to_be64(ib_sg_dma_address(ibdev, scat));
 		buf->key = cpu_to_be32(target->rkey);
 		buf->len = cpu_to_be32(ib_sg_dma_len(ibdev, scat));
-	} else if (srp_map_fmr(target, scat, count, req,
-			       (void *) cmd->add_data)) {
-		/*
-		 * FMR mapping failed, and the scatterlist has more
-		 * than one entry.  Generate an indirect memory
-		 * descriptor.
-		 */
-		struct srp_indirect_buf *buf = (void *) cmd->add_data;
-		struct scatterlist *sg;
-		u32 datalen = 0;
-		int i;
 
-		fmt = SRP_DATA_DESC_INDIRECT;
-		len = sizeof (struct srp_cmd) +
-			sizeof (struct srp_indirect_buf) +
-			count * sizeof (struct srp_direct_buf);
+		req->nfmr = 0;
+		goto map_complete;
+	}
 
-		scsi_for_each_sg(scmnd, sg, count, i) {
-			unsigned int dma_len = ib_sg_dma_len(ibdev, sg);
+	/* We have more than one scatter/gather entry, so build our indirect
+	 * descriptor table, trying to merge as many entries with FMR as we
+	 * can.
+	 */
+	indirect_hdr = (void *) cmd->add_data;
 
-			buf->desc_list[i].va  =
-				cpu_to_be64(ib_sg_dma_address(ibdev, sg));
-			buf->desc_list[i].key =
-				cpu_to_be32(target->rkey);
-			buf->desc_list[i].len = cpu_to_be32(dma_len);
-			datalen += dma_len;
+	ib_dma_sync_single_for_cpu(ibdev, req->indirect_dma_addr,
+				   target->indirect_size, DMA_TO_DEVICE);
+
+	memset(&state, 0, sizeof(state));
+	state.desc	= req->indirect_desc;
+	state.pages	= req->map_page;
+	state.next_fmr	= req->fmr_list;
+
+	use_fmr = dev->fmr_pool ? SRP_MAP_ALLOW_FMR : SRP_MAP_NO_FMR;
+
+	for_each_sg(scat, sg, count, i) {
+		if (srp_map_sg_entry(&state, target, sg, i, use_fmr)) {
+			/* FMR mapping failed, so backtrack to the first
+			 * unmapped entry and continue on without using FMR.
+			 */
+			dma_addr_t dma_addr;
+			unsigned int dma_len;
+
+backtrack:
+			sg = state.unmapped_sg;
+			i = state.unmapped_index;
+
+			dma_addr = ib_sg_dma_address(ibdev, sg);
+			dma_len = ib_sg_dma_len(ibdev, sg);
+			dma_len -= (state.unmapped_addr - dma_addr);
+			dma_addr = state.unmapped_addr;
+			use_fmr = SRP_MAP_NO_FMR;
+			srp_map_desc(&state, dma_addr, dma_len, target->rkey);
 		}
+	}
 
-		if (scmnd->sc_data_direction == DMA_TO_DEVICE)
-			cmd->data_out_desc_cnt = count;
-		else
-			cmd->data_in_desc_cnt = count;
+	if (use_fmr == SRP_MAP_ALLOW_FMR && srp_map_finish_fmr(&state, target))
+		goto backtrack;
 
-		buf->table_desc.va  =
-			cpu_to_be64(req->cmd->dma + sizeof *cmd + sizeof *buf);
-		buf->table_desc.key =
-			cpu_to_be32(target->rkey);
-		buf->table_desc.len =
-			cpu_to_be32(count * sizeof (struct srp_direct_buf));
+	/* We've mapped the request, now pull as much of the indirect
+	 * descriptor table as we can into the command buffer. If this
+	 * target is not using an external indirect table, we are
+	 * guaranteed to fit into the command, as the SCSI layer won't
+	 * give us more S/G entries than we allow.
+	 */
+	req->nfmr = state.nfmr;
+	if (state.ndesc == 1) {
+		/* FMR mapping was able to collapse this to one entry,
+		 * so use a direct descriptor.
+		 */
+		struct srp_direct_buf *buf = (void *) cmd->add_data;
 
-		buf->len = cpu_to_be32(datalen);
+		*buf = req->indirect_desc[0];
+		goto map_complete;
+	}
+
+	if (unlikely(target->cmd_sg_cnt < state.ndesc &&
+						!target->allow_ext_sg)) {
+		shost_printk(KERN_ERR, target->scsi_host,
+			     "Could not fit S/G list into SRP_CMD\n");
+		return -EIO;
 	}
 
+	count = min(state.ndesc, target->cmd_sg_cnt);
+	table_len = state.ndesc * sizeof (struct srp_direct_buf);
+
+	fmt = SRP_DATA_DESC_INDIRECT;
+	len = sizeof(struct srp_cmd) + sizeof (struct srp_indirect_buf);
+	len += count * sizeof (struct srp_direct_buf);
+
+	memcpy(indirect_hdr->desc_list, req->indirect_desc,
+	       count * sizeof (struct srp_direct_buf));
+
+	indirect_hdr->table_desc.va = cpu_to_be64(req->indirect_dma_addr);
+	indirect_hdr->table_desc.key = cpu_to_be32(target->rkey);
+	indirect_hdr->table_desc.len = cpu_to_be32(table_len);
+	indirect_hdr->len = cpu_to_be32(state.total_len);
+
+	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
+		cmd->data_out_desc_cnt = count;
+	else
+		cmd->data_in_desc_cnt = count;
+
+	ib_dma_sync_single_for_device(ibdev, req->indirect_dma_addr, table_len,
+				      DMA_TO_DEVICE);
+
+map_complete:
 	if (scmnd->sc_data_direction == DMA_TO_DEVICE)
 		cmd->buf_fmt = fmt << 4;
 	else
@@ -1140,7 +1266,7 @@
 	spin_unlock_irqrestore(&target->lock, flags);
 
 	dev = target->srp_host->srp_dev->dev;
-	ib_dma_sync_single_for_cpu(dev, iu->dma, srp_max_iu_len,
+	ib_dma_sync_single_for_cpu(dev, iu->dma, target->max_iu_len,
 				   DMA_TO_DEVICE);
 
 	scmnd->result        = 0;
@@ -1164,7 +1290,7 @@
 		goto err_iu;
 	}
 
-	ib_dma_sync_single_for_device(dev, iu->dma, srp_max_iu_len,
+	ib_dma_sync_single_for_device(dev, iu->dma, target->max_iu_len,
 				      DMA_TO_DEVICE);
 
 	if (srp_post_send(target, iu, len)) {
@@ -1204,7 +1330,7 @@
 
 	for (i = 0; i < SRP_SQ_SIZE; ++i) {
 		target->tx_ring[i] = srp_alloc_iu(target->srp_host,
-						  srp_max_iu_len,
+						  target->max_iu_len,
 						  GFP_KERNEL, DMA_TO_DEVICE);
 		if (!target->tx_ring[i])
 			goto err;
@@ -1228,6 +1354,78 @@
 	return -ENOMEM;
 }
 
+static void srp_cm_rep_handler(struct ib_cm_id *cm_id,
+			       struct srp_login_rsp *lrsp,
+			       struct srp_target_port *target)
+{
+	struct ib_qp_attr *qp_attr = NULL;
+	int attr_mask = 0;
+	int ret;
+	int i;
+
+	if (lrsp->opcode == SRP_LOGIN_RSP) {
+		target->max_ti_iu_len = be32_to_cpu(lrsp->max_ti_iu_len);
+		target->req_lim       = be32_to_cpu(lrsp->req_lim_delta);
+
+		/*
+		 * Reserve credits for task management so we don't
+		 * bounce requests back to the SCSI mid-layer.
+		 */
+		target->scsi_host->can_queue
+			= min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
+			      target->scsi_host->can_queue);
+	} else {
+		shost_printk(KERN_WARNING, target->scsi_host,
+			     PFX "Unhandled RSP opcode %#x\n", lrsp->opcode);
+		ret = -ECONNRESET;
+		goto error;
+	}
+
+	if (!target->rx_ring[0]) {
+		ret = srp_alloc_iu_bufs(target);
+		if (ret)
+			goto error;
+	}
+
+	ret = -ENOMEM;
+	qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
+	if (!qp_attr)
+		goto error;
+
+	qp_attr->qp_state = IB_QPS_RTR;
+	ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
+	if (ret)
+		goto error_free;
+
+	ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
+	if (ret)
+		goto error_free;
+
+	for (i = 0; i < SRP_RQ_SIZE; i++) {
+		struct srp_iu *iu = target->rx_ring[i];
+		ret = srp_post_recv(target, iu);
+		if (ret)
+			goto error_free;
+	}
+
+	qp_attr->qp_state = IB_QPS_RTS;
+	ret = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
+	if (ret)
+		goto error_free;
+
+	ret = ib_modify_qp(target->qp, qp_attr, attr_mask);
+	if (ret)
+		goto error_free;
+
+	ret = ib_send_cm_rtu(cm_id, NULL, 0);
+
+error_free:
+	kfree(qp_attr);
+
+error:
+	target->status = ret;
+}
+
 static void srp_cm_rej_handler(struct ib_cm_id *cm_id,
 			       struct ib_cm_event *event,
 			       struct srp_target_port *target)
@@ -1311,11 +1509,7 @@
 static int srp_cm_handler(struct ib_cm_id *cm_id, struct ib_cm_event *event)
 {
 	struct srp_target_port *target = cm_id->context;
-	struct ib_qp_attr *qp_attr = NULL;
-	int attr_mask = 0;
 	int comp = 0;
-	int opcode = 0;
-	int i;
 
 	switch (event->event) {
 	case IB_CM_REQ_ERROR:
@@ -1327,71 +1521,7 @@
 
 	case IB_CM_REP_RECEIVED:
 		comp = 1;
-		opcode = *(u8 *) event->private_data;
-
-		if (opcode == SRP_LOGIN_RSP) {
-			struct srp_login_rsp *rsp = event->private_data;
-
-			target->max_ti_iu_len = be32_to_cpu(rsp->max_ti_iu_len);
-			target->req_lim       = be32_to_cpu(rsp->req_lim_delta);
-
-			/*
-			 * Reserve credits for task management so we don't
-			 * bounce requests back to the SCSI mid-layer.
-			 */
-			target->scsi_host->can_queue
-				= min(target->req_lim - SRP_TSK_MGMT_SQ_SIZE,
-				      target->scsi_host->can_queue);
-		} else {
-			shost_printk(KERN_WARNING, target->scsi_host,
-				    PFX "Unhandled RSP opcode %#x\n", opcode);
-			target->status = -ECONNRESET;
-			break;
-		}
-
-		if (!target->rx_ring[0]) {
-			target->status = srp_alloc_iu_bufs(target);
-			if (target->status)
-				break;
-		}
-
-		qp_attr = kmalloc(sizeof *qp_attr, GFP_KERNEL);
-		if (!qp_attr) {
-			target->status = -ENOMEM;
-			break;
-		}
-
-		qp_attr->qp_state = IB_QPS_RTR;
-		target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
-		if (target->status)
-			break;
-
-		target->status = ib_modify_qp(target->qp, qp_attr, attr_mask);
-		if (target->status)
-			break;
-
-		for (i = 0; i < SRP_RQ_SIZE; i++) {
-			struct srp_iu *iu = target->rx_ring[i];
-			target->status = srp_post_recv(target, iu);
-			if (target->status)
-				break;
-		}
-		if (target->status)
-			break;
-
-		qp_attr->qp_state = IB_QPS_RTS;
-		target->status = ib_cm_init_qp_attr(cm_id, qp_attr, &attr_mask);
-		if (target->status)
-			break;
-
-		target->status = ib_modify_qp(target->qp, qp_attr, attr_mask);
-		if (target->status)
-			break;
-
-		target->status = ib_send_cm_rtu(cm_id, NULL, 0);
-		if (target->status)
-			break;
-
+		srp_cm_rep_handler(cm_id, event->private_data, target);
 		break;
 
 	case IB_CM_REJ_RECEIVED:
@@ -1431,8 +1561,6 @@
 	if (comp)
 		complete(&target->done);
 
-	kfree(qp_attr);
-
 	return 0;
 }
 
@@ -1658,6 +1786,22 @@
 	return sprintf(buf, "%s\n", target->srp_host->srp_dev->dev->name);
 }
 
+static ssize_t show_cmd_sg_entries(struct device *dev,
+				   struct device_attribute *attr, char *buf)
+{
+	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+	return sprintf(buf, "%u\n", target->cmd_sg_cnt);
+}
+
+static ssize_t show_allow_ext_sg(struct device *dev,
+				 struct device_attribute *attr, char *buf)
+{
+	struct srp_target_port *target = host_to_target(class_to_shost(dev));
+
+	return sprintf(buf, "%s\n", target->allow_ext_sg ? "true" : "false");
+}
+
 static DEVICE_ATTR(id_ext,	    S_IRUGO, show_id_ext,	   NULL);
 static DEVICE_ATTR(ioc_guid,	    S_IRUGO, show_ioc_guid,	   NULL);
 static DEVICE_ATTR(service_id,	    S_IRUGO, show_service_id,	   NULL);
@@ -1668,6 +1812,8 @@
 static DEVICE_ATTR(zero_req_lim,    S_IRUGO, show_zero_req_lim,	   NULL);
 static DEVICE_ATTR(local_ib_port,   S_IRUGO, show_local_ib_port,   NULL);
 static DEVICE_ATTR(local_ib_device, S_IRUGO, show_local_ib_device, NULL);
+static DEVICE_ATTR(cmd_sg_entries,  S_IRUGO, show_cmd_sg_entries,  NULL);
+static DEVICE_ATTR(allow_ext_sg,    S_IRUGO, show_allow_ext_sg,    NULL);
 
 static struct device_attribute *srp_host_attrs[] = {
 	&dev_attr_id_ext,
@@ -1680,6 +1826,8 @@
 	&dev_attr_zero_req_lim,
 	&dev_attr_local_ib_port,
 	&dev_attr_local_ib_device,
+	&dev_attr_cmd_sg_entries,
+	&dev_attr_allow_ext_sg,
 	NULL
 };
 
@@ -1692,6 +1840,7 @@
 	.eh_abort_handler		= srp_abort,
 	.eh_device_reset_handler	= srp_reset_device,
 	.eh_host_reset_handler		= srp_reset_host,
+	.sg_tablesize			= SRP_DEF_SG_TABLESIZE,
 	.can_queue			= SRP_CMD_SQ_SIZE,
 	.this_id			= -1,
 	.cmd_per_lun			= SRP_CMD_SQ_SIZE,
@@ -1763,6 +1912,9 @@
 	SRP_OPT_MAX_CMD_PER_LUN	= 1 << 6,
 	SRP_OPT_IO_CLASS	= 1 << 7,
 	SRP_OPT_INITIATOR_EXT	= 1 << 8,
+	SRP_OPT_CMD_SG_ENTRIES	= 1 << 9,
+	SRP_OPT_ALLOW_EXT_SG	= 1 << 10,
+	SRP_OPT_SG_TABLESIZE	= 1 << 11,
 	SRP_OPT_ALL		= (SRP_OPT_ID_EXT	|
 				   SRP_OPT_IOC_GUID	|
 				   SRP_OPT_DGID		|
@@ -1780,6 +1932,9 @@
 	{ SRP_OPT_MAX_CMD_PER_LUN,	"max_cmd_per_lun=%d" 	},
 	{ SRP_OPT_IO_CLASS,		"io_class=%x"		},
 	{ SRP_OPT_INITIATOR_EXT,	"initiator_ext=%s"	},
+	{ SRP_OPT_CMD_SG_ENTRIES,	"cmd_sg_entries=%u"	},
+	{ SRP_OPT_ALLOW_EXT_SG,		"allow_ext_sg=%u"	},
+	{ SRP_OPT_SG_TABLESIZE,		"sg_tablesize=%u"	},
 	{ SRP_OPT_ERR,			NULL 			}
 };
 
@@ -1907,6 +2062,31 @@
 			kfree(p);
 			break;
 
+		case SRP_OPT_CMD_SG_ENTRIES:
+			if (match_int(args, &token) || token < 1 || token > 255) {
+				printk(KERN_WARNING PFX "bad max cmd_sg_entries parameter '%s'\n", p);
+				goto out;
+			}
+			target->cmd_sg_cnt = token;
+			break;
+
+		case SRP_OPT_ALLOW_EXT_SG:
+			if (match_int(args, &token)) {
+				printk(KERN_WARNING PFX "bad allow_ext_sg parameter '%s'\n", p);
+				goto out;
+			}
+			target->allow_ext_sg = !!token;
+			break;
+
+		case SRP_OPT_SG_TABLESIZE:
+			if (match_int(args, &token) || token < 1 ||
+					token > SCSI_MAX_SG_CHAIN_SEGMENTS) {
+				printk(KERN_WARNING PFX "bad max sg_tablesize parameter '%s'\n", p);
+				goto out;
+			}
+			target->sg_tablesize = token;
+			break;
+
 		default:
 			printk(KERN_WARNING PFX "unknown parameter or missing value "
 			       "'%s' in target creation request\n", p);
@@ -1937,39 +2117,73 @@
 		container_of(dev, struct srp_host, dev);
 	struct Scsi_Host *target_host;
 	struct srp_target_port *target;
-	int ret;
-	int i;
+	struct ib_device *ibdev = host->srp_dev->dev;
+	dma_addr_t dma_addr;
+	int i, ret;
 
 	target_host = scsi_host_alloc(&srp_template,
 				      sizeof (struct srp_target_port));
 	if (!target_host)
 		return -ENOMEM;
 
-	target_host->transportt = ib_srp_transport_template;
+	target_host->transportt  = ib_srp_transport_template;
 	target_host->max_lun     = SRP_MAX_LUN;
 	target_host->max_cmd_len = sizeof ((struct srp_cmd *) (void *) 0L)->cdb;
 
 	target = host_to_target(target_host);
 
-	target->io_class   = SRP_REV16A_IB_IO_CLASS;
-	target->scsi_host  = target_host;
-	target->srp_host   = host;
-	target->lkey	   = host->srp_dev->mr->lkey;
-	target->rkey	   = host->srp_dev->mr->rkey;
+	target->io_class	= SRP_REV16A_IB_IO_CLASS;
+	target->scsi_host	= target_host;
+	target->srp_host	= host;
+	target->lkey		= host->srp_dev->mr->lkey;
+	target->rkey		= host->srp_dev->mr->rkey;
+	target->cmd_sg_cnt	= cmd_sg_entries;
+	target->sg_tablesize	= indirect_sg_entries ? : cmd_sg_entries;
+	target->allow_ext_sg	= allow_ext_sg;
+
+	ret = srp_parse_options(buf, target);
+	if (ret)
+		goto err;
+
+	if (!host->srp_dev->fmr_pool && !target->allow_ext_sg &&
+				target->cmd_sg_cnt < target->sg_tablesize) {
+		printk(KERN_WARNING PFX "No FMR pool and no external indirect descriptors, limiting sg_tablesize to cmd_sg_cnt\n");
+		target->sg_tablesize = target->cmd_sg_cnt;
+	}
+
+	target_host->sg_tablesize = target->sg_tablesize;
+	target->indirect_size = target->sg_tablesize *
+				sizeof (struct srp_direct_buf);
+	target->max_iu_len = sizeof (struct srp_cmd) +
+			     sizeof (struct srp_indirect_buf) +
+			     target->cmd_sg_cnt * sizeof (struct srp_direct_buf);
 
 	spin_lock_init(&target->lock);
 	INIT_LIST_HEAD(&target->free_tx);
 	INIT_LIST_HEAD(&target->free_reqs);
 	for (i = 0; i < SRP_CMD_SQ_SIZE; ++i) {
-		target->req_ring[i].index = i;
-		list_add_tail(&target->req_ring[i].list, &target->free_reqs);
-	}
+		struct srp_request *req = &target->req_ring[i];
 
-	ret = srp_parse_options(buf, target);
-	if (ret)
-		goto err;
+		req->fmr_list = kmalloc(target->cmd_sg_cnt * sizeof (void *),
+					GFP_KERNEL);
+		req->map_page = kmalloc(SRP_FMR_SIZE * sizeof (void *),
+					GFP_KERNEL);
+		req->indirect_desc = kmalloc(target->indirect_size, GFP_KERNEL);
+		if (!req->fmr_list || !req->map_page || !req->indirect_desc)
+			goto err_free_mem;
 
-	ib_query_gid(host->srp_dev->dev, host->port, 0, &target->path.sgid);
+		dma_addr = ib_dma_map_single(ibdev, req->indirect_desc,
+					     target->indirect_size,
+					     DMA_TO_DEVICE);
+		if (ib_dma_mapping_error(ibdev, dma_addr))
+			goto err_free_mem;
+
+		req->indirect_dma_addr = dma_addr;
+		req->index = i;
+		list_add_tail(&req->list, &target->free_reqs);
+	}
+
+	ib_query_gid(ibdev, host->port, 0, &target->path.sgid);
 
 	shost_printk(KERN_DEBUG, target->scsi_host, PFX
 		     "new target: id_ext %016llx ioc_guid %016llx pkey %04x "
@@ -1982,11 +2196,11 @@
 
 	ret = srp_create_target_ib(target);
 	if (ret)
-		goto err;
+		goto err_free_mem;
 
 	ret = srp_new_cm_id(target);
 	if (ret)
-		goto err_free;
+		goto err_free_ib;
 
 	target->qp_in_error = 0;
 	ret = srp_connect_target(target);
@@ -2008,9 +2222,12 @@
 err_cm_id:
 	ib_destroy_cm_id(target->cm_id);
 
-err_free:
+err_free_ib:
 	srp_free_target_ib(target);
 
+err_free_mem:
+	srp_free_req_data(target);
+
 err:
 	scsi_host_put(target_host);
 
@@ -2083,7 +2300,7 @@
 	struct ib_device_attr *dev_attr;
 	struct ib_fmr_pool_param fmr_param;
 	struct srp_host *host;
-	int s, e, p;
+	int max_pages_per_fmr, fmr_page_shift, s, e, p;
 
 	dev_attr = kmalloc(sizeof *dev_attr, GFP_KERNEL);
 	if (!dev_attr)
@@ -2101,12 +2318,13 @@
 
 	/*
 	 * Use the smallest page size supported by the HCA, down to a
-	 * minimum of 512 bytes (which is the smallest sector that a
-	 * SCSI command will ever carry).
+	 * minimum of 4096 bytes. We're unlikely to build large sglists
+	 * out of smaller entries.
 	 */
-	srp_dev->fmr_page_shift = max(9, ffs(dev_attr->page_size_cap) - 1);
-	srp_dev->fmr_page_size  = 1 << srp_dev->fmr_page_shift;
-	srp_dev->fmr_page_mask  = ~((u64) srp_dev->fmr_page_size - 1);
+	fmr_page_shift		= max(12, ffs(dev_attr->page_size_cap) - 1);
+	srp_dev->fmr_page_size	= 1 << fmr_page_shift;
+	srp_dev->fmr_page_mask	= ~((u64) srp_dev->fmr_page_size - 1);
+	srp_dev->fmr_max_size	= srp_dev->fmr_page_size * SRP_FMR_SIZE;
 
 	INIT_LIST_HEAD(&srp_dev->dev_list);
 
@@ -2122,17 +2340,24 @@
 	if (IS_ERR(srp_dev->mr))
 		goto err_pd;
 
-	memset(&fmr_param, 0, sizeof fmr_param);
-	fmr_param.pool_size	    = SRP_FMR_POOL_SIZE;
-	fmr_param.dirty_watermark   = SRP_FMR_DIRTY_SIZE;
-	fmr_param.cache		    = 1;
-	fmr_param.max_pages_per_fmr = SRP_FMR_SIZE;
-	fmr_param.page_shift	    = srp_dev->fmr_page_shift;
-	fmr_param.access	    = (IB_ACCESS_LOCAL_WRITE |
-				       IB_ACCESS_REMOTE_WRITE |
-				       IB_ACCESS_REMOTE_READ);
+	for (max_pages_per_fmr = SRP_FMR_SIZE;
+			max_pages_per_fmr >= SRP_FMR_MIN_SIZE;
+			max_pages_per_fmr /= 2, srp_dev->fmr_max_size /= 2) {
+		memset(&fmr_param, 0, sizeof fmr_param);
+		fmr_param.pool_size	    = SRP_FMR_POOL_SIZE;
+		fmr_param.dirty_watermark   = SRP_FMR_DIRTY_SIZE;
+		fmr_param.cache		    = 1;
+		fmr_param.max_pages_per_fmr = max_pages_per_fmr;
+		fmr_param.page_shift	    = fmr_page_shift;
+		fmr_param.access	    = (IB_ACCESS_LOCAL_WRITE |
+					       IB_ACCESS_REMOTE_WRITE |
+					       IB_ACCESS_REMOTE_READ);
+
+		srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param);
+		if (!IS_ERR(srp_dev->fmr_pool))
+			break;
+	}
 
-	srp_dev->fmr_pool = ib_create_fmr_pool(srp_dev->pd, &fmr_param);
 	if (IS_ERR(srp_dev->fmr_pool))
 		srp_dev->fmr_pool = NULL;
 
@@ -2207,6 +2432,7 @@
 			srp_disconnect_target(target);
 			ib_destroy_cm_id(target->cm_id);
 			srp_free_target_ib(target);
+			srp_free_req_data(target);
 			scsi_host_put(target->scsi_host);
 		}
 
@@ -2230,9 +2456,25 @@
 
 	BUILD_BUG_ON(FIELD_SIZEOF(struct ib_wc, wr_id) < sizeof(void *));
 
-	if (srp_sg_tablesize > 255) {
-		printk(KERN_WARNING PFX "Clamping srp_sg_tablesize to 255\n");
-		srp_sg_tablesize = 255;
+	if (srp_sg_tablesize) {
+		printk(KERN_WARNING PFX "srp_sg_tablesize is deprecated, please use cmd_sg_entries\n");
+		if (!cmd_sg_entries)
+			cmd_sg_entries = srp_sg_tablesize;
+	}
+
+	if (!cmd_sg_entries)
+		cmd_sg_entries = SRP_DEF_SG_TABLESIZE;
+
+	if (cmd_sg_entries > 255) {
+		printk(KERN_WARNING PFX "Clamping cmd_sg_entries to 255\n");
+		cmd_sg_entries = 255;
+	}
+
+	if (!indirect_sg_entries)
+		indirect_sg_entries = cmd_sg_entries;
+	else if (indirect_sg_entries < cmd_sg_entries) {
+		printk(KERN_WARNING PFX "Bumping up indirect_sg_entries to match cmd_sg_entries (%u)\n", cmd_sg_entries);
+		indirect_sg_entries = cmd_sg_entries;
 	}
 
 	ib_srp_transport_template =
@@ -2240,11 +2482,6 @@
 	if (!ib_srp_transport_template)
 		return -ENOMEM;
 
-	srp_template.sg_tablesize = srp_sg_tablesize;
-	srp_max_iu_len = (sizeof (struct srp_cmd) +
-			  sizeof (struct srp_indirect_buf) +
-			  srp_sg_tablesize * 16);
-
 	ret = class_register(&srp_class);
 	if (ret) {
 		printk(KERN_ERR PFX "couldn't register class infiniband_srp\n");
diff -druN linux-libre-2.6.38-gnu/drivers/infiniband/ulp/srp/ib_srp.h linux-libre-2.6.39-gnu/drivers/infiniband/ulp/srp/ib_srp.h
--- linux-libre-2.6.38-gnu/drivers/infiniband/ulp/srp/ib_srp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/infiniband/ulp/srp/ib_srp.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,9 +69,13 @@
 	SRP_TAG_NO_REQ		= ~0U,
 	SRP_TAG_TSK_MGMT	= 1U << 31,
 
-	SRP_FMR_SIZE		= 256,
+	SRP_FMR_SIZE		= 512,
+	SRP_FMR_MIN_SIZE	= 128,
 	SRP_FMR_POOL_SIZE	= 1024,
-	SRP_FMR_DIRTY_SIZE	= SRP_FMR_POOL_SIZE / 4
+	SRP_FMR_DIRTY_SIZE	= SRP_FMR_POOL_SIZE / 4,
+
+	SRP_MAP_ALLOW_FMR	= 0,
+	SRP_MAP_NO_FMR		= 1,
 };
 
 enum srp_target_state {
@@ -93,9 +97,9 @@
 	struct ib_pd	       *pd;
 	struct ib_mr	       *mr;
 	struct ib_fmr_pool     *fmr_pool;
-	int			fmr_page_shift;
-	int			fmr_page_size;
 	u64			fmr_page_mask;
+	int			fmr_page_size;
+	int			fmr_max_size;
 };
 
 struct srp_host {
@@ -112,7 +116,11 @@
 	struct list_head	list;
 	struct scsi_cmnd       *scmnd;
 	struct srp_iu	       *cmd;
-	struct ib_pool_fmr     *fmr;
+	struct ib_pool_fmr    **fmr_list;
+	u64		       *map_page;
+	struct srp_direct_buf  *indirect_desc;
+	dma_addr_t		indirect_dma_addr;
+	short			nfmr;
 	short			index;
 };
 
@@ -130,6 +138,10 @@
 	u32			lkey;
 	u32			rkey;
 	enum srp_target_state	state;
+	unsigned int		max_iu_len;
+	unsigned int		cmd_sg_cnt;
+	unsigned int		indirect_size;
+	bool			allow_ext_sg;
 
 	/* Everything above this point is used in the hot path of
 	 * command processing. Try to keep them packed into cachelines.
@@ -144,6 +156,7 @@
 	struct Scsi_Host       *scsi_host;
 	char			target_name[32];
 	unsigned int		scsi_id;
+	unsigned int		sg_tablesize;
 
 	struct ib_sa_path_rec	path;
 	__be16			orig_dgid[8];
@@ -179,4 +192,19 @@
 	enum dma_data_direction	direction;
 };
 
+struct srp_map_state {
+	struct ib_pool_fmr    **next_fmr;
+	struct srp_direct_buf  *desc;
+	u64		       *pages;
+	dma_addr_t		base_dma_addr;
+	u32			fmr_len;
+	u32			total_len;
+	unsigned int		npages;
+	unsigned int		nfmr;
+	unsigned int		ndesc;
+	struct scatterlist     *unmapped_sg;
+	int			unmapped_index;
+	dma_addr_t		unmapped_addr;
+};
+
 #endif /* IB_SRP_H */
diff -druN linux-libre-2.6.38-gnu/drivers/input/evdev.c linux-libre-2.6.39-gnu/drivers/input/evdev.c
--- linux-libre-2.6.38-gnu/drivers/input/evdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/evdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,13 +39,13 @@
 };
 
 struct evdev_client {
-	int head;
-	int tail;
+	unsigned int head;
+	unsigned int tail;
 	spinlock_t buffer_lock; /* protects access to buffer, head and tail */
 	struct fasync_struct *fasync;
 	struct evdev *evdev;
 	struct list_head node;
-	int bufsize;
+	unsigned int bufsize;
 	struct input_event buffer[];
 };
 
@@ -55,16 +55,25 @@
 static void evdev_pass_event(struct evdev_client *client,
 			     struct input_event *event)
 {
-	/*
-	 * Interrupts are disabled, just acquire the lock.
-	 * Make sure we don't leave with the client buffer
-	 * "empty" by having client->head == client->tail.
-	 */
+	/* Interrupts are disabled, just acquire the lock. */
 	spin_lock(&client->buffer_lock);
-	do {
-		client->buffer[client->head++] = *event;
-		client->head &= client->bufsize - 1;
-	} while (client->head == client->tail);
+
+	client->buffer[client->head++] = *event;
+	client->head &= client->bufsize - 1;
+
+	if (unlikely(client->head == client->tail)) {
+		/*
+		 * This effectively "drops" all unconsumed events, leaving
+		 * EV_SYN/SYN_DROPPED plus the newest event in the queue.
+		 */
+		client->tail = (client->head - 2) & (client->bufsize - 1);
+
+		client->buffer[client->tail].time = event->time;
+		client->buffer[client->tail].type = EV_SYN;
+		client->buffer[client->tail].code = SYN_DROPPED;
+		client->buffer[client->tail].value = 0;
+	}
+
 	spin_unlock(&client->buffer_lock);
 
 	if (event->type == EV_SYN)
@@ -321,6 +330,9 @@
 	struct input_event event;
 	int retval;
 
+	if (count < input_event_size())
+		return -EINVAL;
+
 	retval = mutex_lock_interruptible(&evdev->mutex);
 	if (retval)
 		return retval;
@@ -330,17 +342,16 @@
 		goto out;
 	}
 
-	while (retval < count) {
-
+	do {
 		if (input_event_from_user(buffer + retval, &event)) {
 			retval = -EFAULT;
 			goto out;
 		}
+		retval += input_event_size();
 
 		input_inject_event(&evdev->handle,
 				   event.type, event.code, event.value);
-		retval += input_event_size();
-	}
+	} while (retval + input_event_size() <= count);
 
  out:
 	mutex_unlock(&evdev->mutex);
diff -druN linux-libre-2.6.38-gnu/drivers/input/input.c linux-libre-2.6.39-gnu/drivers/input/input.c
--- linux-libre-2.6.38-gnu/drivers/input/input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/input.c	2011-05-19 00:06:34.000000000 -0400
@@ -791,22 +791,9 @@
 	int retval;
 
 	spin_lock_irqsave(&dev->event_lock, flags);
-
-	if (dev->getkeycode) {
-		/*
-		 * Support for legacy drivers, that don't implement the new
-		 * ioctls
-		 */
-		u32 scancode = ke->index;
-
-		memcpy(ke->scancode, &scancode, sizeof(scancode));
-		ke->len = sizeof(scancode);
-		retval = dev->getkeycode(dev, scancode, &ke->keycode);
-	} else {
-		retval = dev->getkeycode_new(dev, ke);
-	}
-
+	retval = dev->getkeycode(dev, ke);
 	spin_unlock_irqrestore(&dev->event_lock, flags);
+
 	return retval;
 }
 EXPORT_SYMBOL(input_get_keycode);
@@ -831,35 +818,7 @@
 
 	spin_lock_irqsave(&dev->event_lock, flags);
 
-	if (dev->setkeycode) {
-		/*
-		 * Support for legacy drivers, that don't implement the new
-		 * ioctls
-		 */
-		unsigned int scancode;
-
-		retval = input_scancode_to_scalar(ke, &scancode);
-		if (retval)
-			goto out;
-
-		/*
-		 * We need to know the old scancode, in order to generate a
-		 * keyup effect, if the set operation happens successfully
-		 */
-		if (!dev->getkeycode) {
-			retval = -EINVAL;
-			goto out;
-		}
-
-		retval = dev->getkeycode(dev, scancode, &old_keycode);
-		if (retval)
-			goto out;
-
-		retval = dev->setkeycode(dev, scancode, ke->keycode);
-	} else {
-		retval = dev->setkeycode_new(dev, ke, &old_keycode);
-	}
-
+	retval = dev->setkeycode(dev, ke, &old_keycode);
 	if (retval)
 		goto out;
 
@@ -1787,6 +1746,42 @@
 }
 EXPORT_SYMBOL(input_set_capability);
 
+static unsigned int input_estimate_events_per_packet(struct input_dev *dev)
+{
+	int mt_slots;
+	int i;
+	unsigned int events;
+
+	if (dev->mtsize) {
+		mt_slots = dev->mtsize;
+	} else if (test_bit(ABS_MT_TRACKING_ID, dev->absbit)) {
+		mt_slots = dev->absinfo[ABS_MT_TRACKING_ID].maximum -
+			   dev->absinfo[ABS_MT_TRACKING_ID].minimum + 1,
+		clamp(mt_slots, 2, 32);
+	} else if (test_bit(ABS_MT_POSITION_X, dev->absbit)) {
+		mt_slots = 2;
+	} else {
+		mt_slots = 0;
+	}
+
+	events = mt_slots + 1; /* count SYN_MT_REPORT and SYN_REPORT */
+
+	for (i = 0; i < ABS_CNT; i++) {
+		if (test_bit(i, dev->absbit)) {
+			if (input_is_mt_axis(i))
+				events += mt_slots;
+			else
+				events++;
+		}
+	}
+
+	for (i = 0; i < REL_CNT; i++)
+		if (test_bit(i, dev->relbit))
+			events++;
+
+	return events;
+}
+
 #define INPUT_CLEANSE_BITMASK(dev, type, bits)				\
 	do {								\
 		if (!test_bit(EV_##type, dev->evbit))			\
@@ -1834,6 +1829,10 @@
 	/* Make sure that bitmasks not mentioned in dev->evbit are clean. */
 	input_cleanse_bitmasks(dev);
 
+	if (!dev->hint_events_per_packet)
+		dev->hint_events_per_packet =
+				input_estimate_events_per_packet(dev);
+
 	/*
 	 * If delay and period are pre-set by the driver, then autorepeating
 	 * is handled by the driver itself and we don't do it in input.c.
@@ -1846,11 +1845,11 @@
 		dev->rep[REP_PERIOD] = 33;
 	}
 
-	if (!dev->getkeycode && !dev->getkeycode_new)
-		dev->getkeycode_new = input_default_getkeycode;
+	if (!dev->getkeycode)
+		dev->getkeycode = input_default_getkeycode;
 
-	if (!dev->setkeycode && !dev->setkeycode_new)
-		dev->setkeycode_new = input_default_setkeycode;
+	if (!dev->setkeycode)
+		dev->setkeycode = input_default_setkeycode;
 
 	dev_set_name(&dev->dev, "input%ld",
 		     (unsigned long) atomic_inc_return(&input_no) - 1);
diff -druN linux-libre-2.6.38-gnu/drivers/input/input-polldev.c linux-libre-2.6.39-gnu/drivers/input/input-polldev.c
--- linux-libre-2.6.38-gnu/drivers/input/input-polldev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/input-polldev.c	2011-05-19 00:06:34.000000000 -0400
@@ -192,7 +192,7 @@
 };
 
 /**
- * input_allocate_polled_device - allocated memory polled device
+ * input_allocate_polled_device - allocate memory for polled device
  *
  * The function allocates memory for a polled device and also
  * for an input device associated with this polled device.
@@ -239,7 +239,7 @@
  * with input layer. The device should be allocated with call to
  * input_allocate_polled_device(). Callers should also set up poll()
  * method and set up capabilities (id, name, phys, bits) of the
- * corresponing input_dev structure.
+ * corresponding input_dev structure.
  */
 int input_register_polled_device(struct input_polled_dev *dev)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/input/joydev.c linux-libre-2.6.39-gnu/drivers/input/joydev.c
--- linux-libre-2.6.38-gnu/drivers/input/joydev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/joydev.c	2011-05-19 00:06:34.000000000 -0400
@@ -758,7 +758,7 @@
 }
 
 /*
- * Mark device non-existant. This disables writes, ioctls and
+ * Mark device non-existent. This disables writes, ioctls and
  * prevents new users from opening the device. Already posted
  * blocking reads will stay, however new ones will fail.
  */
@@ -777,7 +777,7 @@
 	joydev_hangup(joydev);
 	joydev_remove_chrdev(joydev);
 
-	/* joydev is marked dead so noone else accesses joydev->open */
+	/* joydev is marked dead so no one else accesses joydev->open */
 	if (joydev->open)
 		input_close_device(handle);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/input/joystick/a3d.c linux-libre-2.6.39-gnu/drivers/input/joystick/a3d.c
--- linux-libre-2.6.38-gnu/drivers/input/joystick/a3d.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/joystick/a3d.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  */
 
 /*
- * FP-Gaming Assasin 3D joystick driver for Linux
+ * FP-Gaming Assassin 3D joystick driver for Linux
  */
 
 /*
@@ -34,7 +34,7 @@
 #include <linux/input.h>
 #include <linux/jiffies.h>
 
-#define DRIVER_DESC	"FP-Gaming Assasin 3D joystick driver"
+#define DRIVER_DESC	"FP-Gaming Assassin 3D joystick driver"
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
 MODULE_DESCRIPTION(DRIVER_DESC);
diff -druN linux-libre-2.6.38-gnu/drivers/input/Kconfig linux-libre-2.6.39-gnu/drivers/input/Kconfig
--- linux-libre-2.6.38-gnu/drivers/input/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -161,16 +161,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called apm-power.
 
-config XEN_KBDDEV_FRONTEND
-	tristate "Xen virtual keyboard and mouse support"
-	depends on XEN_FBDEV_FRONTEND
-	default y
-	select XEN_XENBUS_FRONTEND
-	help
-	  This driver implements the front-end of the Xen virtual
-	  keyboard and mouse device driver.  It communicates with a back-end
-	  in another domain.
-
 comment "Input Device Drivers"
 
 source "drivers/input/keyboard/Kconfig"
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/davinci_keyscan.c linux-libre-2.6.39-gnu/drivers/input/keyboard/davinci_keyscan.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/davinci_keyscan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/davinci_keyscan.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * Author: Miguel Aguilar <miguel.aguilar@ridgerun.com>
  *
- * Intial Code: Sandeep Paulraj <s-paulraj@ti.com>
+ * Initial Code: Sandeep Paulraj <s-paulraj@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
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/Kconfig linux-libre-2.6.39-gnu/drivers/input/keyboard/Kconfig
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -112,6 +112,16 @@
 	  right-hand column will be interpreted as the key shown in the
 	  left-hand column.
 
+config KEYBOARD_QT1070
+       tristate "Atmel AT42QT1070 Touch Sensor Chip"
+       depends on I2C
+       help
+         Say Y here if you want to use Atmel AT42QT1070 QTouch
+         Sensor chip as input device.
+
+         To compile this driver as a module, choose M here:
+         the module will be called qt1070
+
 config KEYBOARD_QT2160
 	tristate "Atmel AT42QT2160 Touch Sensor Chip"
 	depends on I2C && EXPERIMENTAL
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/lm8323.c linux-libre-2.6.39-gnu/drivers/input/keyboard/lm8323.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/lm8323.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/lm8323.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/leds.h>
+#include <linux/pm.h>
 #include <linux/i2c/lm8323.h>
 #include <linux/slab.h>
 
@@ -802,12 +803,13 @@
  * 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)
+static int lm8323_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 	int i;
 
-	set_irq_wake(client->irq, 0);
+	irq_set_irq_wake(client->irq, 0);
 	disable_irq(client->irq);
 
 	mutex_lock(&lm->lock);
@@ -821,8 +823,9 @@
 	return 0;
 }
 
-static int lm8323_resume(struct i2c_client *client)
+static int lm8323_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct lm8323_chip *lm = i2c_get_clientdata(client);
 	int i;
 
@@ -835,15 +838,14 @@
 			led_classdev_resume(&lm->pwm[i].cdev);
 
 	enable_irq(client->irq);
-	set_irq_wake(client->irq, 1);
+	irq_set_irq_wake(client->irq, 1);
 
 	return 0;
 }
-#else
-#define lm8323_suspend	NULL
-#define lm8323_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(lm8323_pm_ops, lm8323_suspend, lm8323_resume);
+
 static const struct i2c_device_id lm8323_id[] = {
 	{ "lm8323", 0 },
 	{ }
@@ -852,11 +854,10 @@
 static struct i2c_driver lm8323_i2c_driver = {
 	.driver = {
 		.name	= "lm8323",
+		.pm	= &lm8323_pm_ops,
 	},
 	.probe		= lm8323_probe,
 	.remove		= __devexit_p(lm8323_remove),
-	.suspend	= lm8323_suspend,
-	.resume		= lm8323_resume,
 	.id_table	= lm8323_id,
 };
 MODULE_DEVICE_TABLE(i2c, lm8323_id);
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/Makefile linux-libre-2.6.39-gnu/drivers/input/keyboard/Makefile
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 obj-$(CONFIG_KEYBOARD_OPENCORES)	+= opencores-kbd.o
 obj-$(CONFIG_KEYBOARD_PXA27x)		+= pxa27x_keypad.o
 obj-$(CONFIG_KEYBOARD_PXA930_ROTARY)	+= pxa930_rotary.o
+obj-$(CONFIG_KEYBOARD_QT1070)           += qt1070.o
 obj-$(CONFIG_KEYBOARD_QT2160)		+= qt2160.o
 obj-$(CONFIG_KEYBOARD_SAMSUNG)		+= samsung-keypad.o
 obj-$(CONFIG_KEYBOARD_SH_KEYSC)		+= sh_keysc.o
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/max7359_keypad.c linux-libre-2.6.39-gnu/drivers/input/keyboard/max7359_keypad.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/max7359_keypad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/max7359_keypad.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/input.h>
 #include <linux/input/matrix_keypad.h>
 
@@ -271,8 +272,10 @@
 }
 
 #ifdef CONFIG_PM
-static int max7359_suspend(struct i2c_client *client, pm_message_t mesg)
+static int max7359_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	max7359_fall_deepsleep(client);
 
 	if (device_may_wakeup(&client->dev))
@@ -281,8 +284,10 @@
 	return 0;
 }
 
-static int max7359_resume(struct i2c_client *client)
+static int max7359_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	if (device_may_wakeup(&client->dev))
 		disable_irq_wake(client->irq);
 
@@ -291,11 +296,10 @@
 
 	return 0;
 }
-#else
-#define max7359_suspend	NULL
-#define max7359_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(max7359_pm, max7359_suspend, max7359_resume);
+
 static const struct i2c_device_id max7359_ids[] = {
 	{ "max7359", 0 },
 	{ }
@@ -305,11 +309,10 @@
 static struct i2c_driver max7359_i2c_driver = {
 	.driver = {
 		.name = "max7359",
+		.pm   = &max7359_pm,
 	},
 	.probe		= max7359_probe,
 	.remove		= __devexit_p(max7359_remove),
-	.suspend	= max7359_suspend,
-	.resume		= max7359_resume,
 	.id_table	= max7359_ids,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/mcs_touchkey.c linux-libre-2.6.39-gnu/drivers/input/keyboard/mcs_touchkey.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/mcs_touchkey.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/mcs_touchkey.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * mcs_touchkey.c - Touchkey driver for MELFAS MCS5000/5080 controller
+ * Touchkey driver for MELFAS MCS5000/5080 controller
  *
  * Copyright (C) 2010 Samsung Electronics Co.Ltd
  * Author: HeungJun Kim <riverful.kim@samsung.com>
@@ -19,6 +19,7 @@
 #include <linux/input.h>
 #include <linux/irq.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 /* MCS5000 Touchkey */
 #define MCS5000_TOUCHKEY_STATUS		0x04
@@ -45,6 +46,8 @@
 };
 
 struct mcs_touchkey_data {
+	void (*poweron)(bool);
+
 	struct i2c_client *client;
 	struct input_dev *input_dev;
 	struct mcs_touchkey_chip chip;
@@ -169,6 +172,11 @@
 	if (pdata->cfg_pin)
 		pdata->cfg_pin();
 
+	if (pdata->poweron) {
+		data->poweron = pdata->poweron;
+		data->poweron(true);
+	}
+
 	error = request_threaded_irq(client->irq, NULL, mcs_touchkey_interrupt,
 			IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
 	if (error) {
@@ -196,12 +204,57 @@
 	struct mcs_touchkey_data *data = i2c_get_clientdata(client);
 
 	free_irq(client->irq, data);
+	if (data->poweron)
+		data->poweron(false);
 	input_unregister_device(data->input_dev);
 	kfree(data);
 
 	return 0;
 }
 
+static void mcs_touchkey_shutdown(struct i2c_client *client)
+{
+	struct mcs_touchkey_data *data = i2c_get_clientdata(client);
+
+	if (data->poweron)
+		data->poweron(false);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int mcs_touchkey_suspend(struct device *dev)
+{
+	struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	/* Disable the work */
+	disable_irq(client->irq);
+
+	/* Finally turn off the power */
+	if (data->poweron)
+		data->poweron(false);
+
+	return 0;
+}
+
+static int mcs_touchkey_resume(struct device *dev)
+{
+	struct mcs_touchkey_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+
+	/* Enable the device first */
+	if (data->poweron)
+		data->poweron(true);
+
+	/* Enable irq again */
+	enable_irq(client->irq);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(mcs_touchkey_pm_ops,
+			 mcs_touchkey_suspend, mcs_touchkey_resume);
+
 static const struct i2c_device_id mcs_touchkey_id[] = {
 	{ "mcs5000_touchkey", MCS5000_TOUCHKEY },
 	{ "mcs5080_touchkey", MCS5080_TOUCHKEY },
@@ -213,9 +266,11 @@
 	.driver = {
 		.name	= "mcs_touchkey",
 		.owner	= THIS_MODULE,
+		.pm	= &mcs_touchkey_pm_ops,
 	},
 	.probe		= mcs_touchkey_probe,
 	.remove		= __devexit_p(mcs_touchkey_remove),
+	.shutdown       = mcs_touchkey_shutdown,
 	.id_table	= mcs_touchkey_id,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/omap4-keypad.c linux-libre-2.6.39-gnu/drivers/input/keyboard/omap4-keypad.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/omap4-keypad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/omap4-keypad.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/io.h>
 #include <linux/input.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <plat/omap4-keypad.h>
 
@@ -80,20 +81,6 @@
 	unsigned short keymap[];
 };
 
-static void __devinit omap4_keypad_config(struct omap4_keypad *keypad_data)
-{
-	__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
-			keypad_data->base + OMAP4_KBD_CTRL);
-	__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
-			keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
-	__raw_writel(OMAP4_VAL_IRQDISABLE,
-			keypad_data->base + OMAP4_KBD_IRQSTATUS);
-	__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
-			keypad_data->base + OMAP4_KBD_IRQENABLE);
-	__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
-			keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
-}
-
 /* Interrupt handler */
 static irqreturn_t omap4_keypad_interrupt(int irq, void *dev_id)
 {
@@ -144,6 +131,49 @@
 	return IRQ_HANDLED;
 }
 
+static int omap4_keypad_open(struct input_dev *input)
+{
+	struct omap4_keypad *keypad_data = input_get_drvdata(input);
+
+	pm_runtime_get_sync(input->dev.parent);
+
+	disable_irq(keypad_data->irq);
+
+	__raw_writel(OMAP4_VAL_FUNCTIONALCFG,
+			keypad_data->base + OMAP4_KBD_CTRL);
+	__raw_writel(OMAP4_VAL_DEBOUNCINGTIME,
+			keypad_data->base + OMAP4_KBD_DEBOUNCINGTIME);
+	__raw_writel(OMAP4_VAL_IRQDISABLE,
+			keypad_data->base + OMAP4_KBD_IRQSTATUS);
+	__raw_writel(OMAP4_DEF_IRQENABLE_EVENTEN | OMAP4_DEF_IRQENABLE_LONGKEY,
+			keypad_data->base + OMAP4_KBD_IRQENABLE);
+	__raw_writel(OMAP4_DEF_WUP_EVENT_ENA | OMAP4_DEF_WUP_LONG_KEY_ENA,
+			keypad_data->base + OMAP4_KBD_WAKEUPENABLE);
+
+	enable_irq(keypad_data->irq);
+
+	return 0;
+}
+
+static void omap4_keypad_close(struct input_dev *input)
+{
+	struct omap4_keypad *keypad_data = input_get_drvdata(input);
+
+	disable_irq(keypad_data->irq);
+
+	/* Disable interrupts */
+	__raw_writel(OMAP4_VAL_IRQDISABLE,
+		     keypad_data->base + OMAP4_KBD_IRQENABLE);
+
+	/* clear pending interrupts */
+	__raw_writel(__raw_readl(keypad_data->base + OMAP4_KBD_IRQSTATUS),
+			keypad_data->base + OMAP4_KBD_IRQSTATUS);
+
+	enable_irq(keypad_data->irq);
+
+	pm_runtime_put_sync(input->dev.parent);
+}
+
 static int __devinit omap4_keypad_probe(struct platform_device *pdev)
 {
 	const struct omap4_keypad_platform_data *pdata;
@@ -225,6 +255,9 @@
 	input_dev->id.product = 0x0001;
 	input_dev->id.version = 0x0001;
 
+	input_dev->open = omap4_keypad_open;
+	input_dev->close = omap4_keypad_close;
+
 	input_dev->keycode	= keypad_data->keymap;
 	input_dev->keycodesize	= sizeof(keypad_data->keymap[0]);
 	input_dev->keycodemax	= max_keys;
@@ -239,8 +272,6 @@
 	matrix_keypad_build_keymap(pdata->keymap_data, row_shift,
 			input_dev->keycode, input_dev->keybit);
 
-	omap4_keypad_config(keypad_data);
-
 	error = request_irq(keypad_data->irq, omap4_keypad_interrupt,
 			     IRQF_TRIGGER_RISING,
 			     "omap4-keypad", keypad_data);
@@ -249,17 +280,19 @@
 		goto err_free_input;
 	}
 
+	pm_runtime_enable(&pdev->dev);
+
 	error = input_register_device(keypad_data->input);
 	if (error < 0) {
 		dev_err(&pdev->dev, "failed to register input device\n");
-		goto err_free_irq;
+		goto err_pm_disable;
 	}
 
-
 	platform_set_drvdata(pdev, keypad_data);
 	return 0;
 
-err_free_irq:
+err_pm_disable:
+	pm_runtime_disable(&pdev->dev);
 	free_irq(keypad_data->irq, keypad_data);
 err_free_input:
 	input_free_device(input_dev);
@@ -278,6 +311,9 @@
 	struct resource *res;
 
 	free_irq(keypad_data->irq, keypad_data);
+
+	pm_runtime_disable(&pdev->dev);
+
 	input_unregister_device(keypad_data->input);
 
 	iounmap(keypad_data->base);
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/qt1070.c linux-libre-2.6.39-gnu/drivers/input/keyboard/qt1070.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/qt1070.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/qt1070.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,276 @@
+/*
+ *  Atmel AT42QT1070 QTouch Sensor Controller
+ *
+ *  Copyright (C) 2011 Atmel
+ *
+ *  Authors: Bo Shen <voice.shen@atmel.com>
+ *
+ *  Base on AT42QT2160 driver by:
+ *  Raphael Derosso Pereira <raphaelpereira@gmail.com>
+ *  Copyright (C) 2009
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/i2c.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/jiffies.h>
+#include <linux/delay.h>
+
+/* Address for each register */
+#define CHIP_ID            0x00
+#define QT1070_CHIP_ID     0x2E
+
+#define FW_VERSION         0x01
+#define QT1070_FW_VERSION  0x15
+
+#define DET_STATUS         0x02
+
+#define KEY_STATUS         0x03
+
+/* Calibrate */
+#define CALIBRATE_CMD      0x38
+#define QT1070_CAL_TIME    200
+
+/* Reset */
+#define RESET              0x39
+#define QT1070_RESET_TIME  255
+
+/* AT42QT1070 support up to 7 keys */
+static const unsigned short qt1070_key2code[] = {
+	KEY_0, KEY_1, KEY_2, KEY_3,
+	KEY_4, KEY_5, KEY_6,
+};
+
+struct qt1070_data {
+	struct i2c_client *client;
+	struct input_dev *input;
+	unsigned int irq;
+	unsigned short keycodes[ARRAY_SIZE(qt1070_key2code)];
+	u8 last_keys;
+};
+
+static int qt1070_read(struct i2c_client *client, u8 reg)
+{
+	int ret;
+
+	ret = i2c_smbus_read_byte_data(client, reg);
+	if (ret < 0)
+		dev_err(&client->dev,
+			"can not read register, returned %d\n", ret);
+
+	return ret;
+}
+
+static int qt1070_write(struct i2c_client *client, u8 reg, u8 data)
+{
+	int ret;
+
+	ret = i2c_smbus_write_byte_data(client, reg, data);
+	if (ret < 0)
+		dev_err(&client->dev,
+			"can not write register, returned %d\n", ret);
+
+	return ret;
+}
+
+static bool __devinit qt1070_identify(struct i2c_client *client)
+{
+	int id, ver;
+
+	/* Read Chip ID */
+	id = qt1070_read(client, CHIP_ID);
+	if (id != QT1070_CHIP_ID) {
+		dev_err(&client->dev, "ID %d not supported\n", id);
+		return false;
+	}
+
+	/* Read firmware version */
+	ver = qt1070_read(client, FW_VERSION);
+	if (ver < 0) {
+		dev_err(&client->dev, "could not read the firmware version\n");
+		return false;
+	}
+
+	dev_info(&client->dev, "AT42QT1070 firmware version %x\n", ver);
+
+	return true;
+}
+
+static irqreturn_t qt1070_interrupt(int irq, void *dev_id)
+{
+	struct qt1070_data *data = dev_id;
+	struct i2c_client *client = data->client;
+	struct input_dev *input = data->input;
+	int i;
+	u8 new_keys, keyval, mask = 0x01;
+
+	/* Read the detected status register, thus clearing interrupt */
+	qt1070_read(client, DET_STATUS);
+
+	/* Read which key changed */
+	new_keys = qt1070_read(client, KEY_STATUS);
+
+	for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) {
+		keyval = new_keys & mask;
+		if ((data->last_keys & mask) != keyval)
+			input_report_key(input, data->keycodes[i], keyval);
+		mask <<= 1;
+	}
+	input_sync(input);
+
+	data->last_keys = new_keys;
+	return IRQ_HANDLED;
+}
+
+static int __devinit qt1070_probe(struct i2c_client *client,
+				const struct i2c_device_id *id)
+{
+	struct qt1070_data *data;
+	struct input_dev *input;
+	int i;
+	int err;
+
+	err = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE);
+	if (!err) {
+		dev_err(&client->dev, "%s adapter not supported\n",
+			dev_driver_string(&client->adapter->dev));
+		return -ENODEV;
+	}
+
+	if (!client->irq) {
+		dev_err(&client->dev, "please assign the irq to this device\n");
+		return -EINVAL;
+	}
+
+	/* Identify the qt1070 chip */
+	if (!qt1070_identify(client))
+		return -ENODEV;
+
+	data = kzalloc(sizeof(struct qt1070_data), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!data || !input) {
+		dev_err(&client->dev, "insufficient memory\n");
+		err = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	data->client = client;
+	data->input = input;
+	data->irq = client->irq;
+
+	input->name = "AT42QT1070 QTouch Sensor";
+	input->dev.parent = &client->dev;
+	input->id.bustype = BUS_I2C;
+
+	/* Add the keycode */
+	input->keycode = data->keycodes;
+	input->keycodesize = sizeof(data->keycodes[0]);
+	input->keycodemax = ARRAY_SIZE(qt1070_key2code);
+
+	__set_bit(EV_KEY, input->evbit);
+
+	for (i = 0; i < ARRAY_SIZE(qt1070_key2code); i++) {
+		data->keycodes[i] = qt1070_key2code[i];
+		__set_bit(qt1070_key2code[i], input->keybit);
+	}
+
+	/* Calibrate device */
+	qt1070_write(client, CALIBRATE_CMD, 1);
+	msleep(QT1070_CAL_TIME);
+
+	/* Soft reset */
+	qt1070_write(client, RESET, 1);
+	msleep(QT1070_RESET_TIME);
+
+	err = request_threaded_irq(client->irq, NULL, qt1070_interrupt,
+		IRQF_TRIGGER_NONE, client->dev.driver->name, data);
+	if (err) {
+		dev_err(&client->dev, "fail to request irq\n");
+		goto err_free_mem;
+	}
+
+	/* Register the input device */
+	err = input_register_device(data->input);
+	if (err) {
+		dev_err(&client->dev, "Failed to register input device\n");
+		goto err_free_irq;
+	}
+
+	i2c_set_clientdata(client, data);
+
+	/* Read to clear the chang line */
+	qt1070_read(client, DET_STATUS);
+
+	return 0;
+
+err_free_irq:
+	free_irq(client->irq, data);
+err_free_mem:
+	input_free_device(input);
+	kfree(data);
+	return err;
+}
+
+static int __devexit qt1070_remove(struct i2c_client *client)
+{
+	struct qt1070_data *data = i2c_get_clientdata(client);
+
+	/* Release IRQ */
+	free_irq(client->irq, data);
+
+	input_unregister_device(data->input);
+	kfree(data);
+
+	i2c_set_clientdata(client, NULL);
+
+	return 0;
+}
+
+static const struct i2c_device_id qt1070_id[] = {
+	{ "qt1070", 0 },
+	{ },
+};
+
+static struct i2c_driver qt1070_driver = {
+	.driver	= {
+		.name	= "qt1070",
+		.owner	= THIS_MODULE,
+	},
+	.id_table	= qt1070_id,
+	.probe		= qt1070_probe,
+	.remove		= __devexit_p(qt1070_remove),
+};
+
+static int __init qt1070_init(void)
+{
+	return i2c_add_driver(&qt1070_driver);
+}
+module_init(qt1070_init);
+
+static void __exit qt1070_exit(void)
+{
+	i2c_del_driver(&qt1070_driver);
+}
+module_exit(qt1070_exit);
+
+MODULE_AUTHOR("Bo Shen <voice.shen@atmel.com>");
+MODULE_DESCRIPTION("Driver for AT42QT1070 QTouch sensor");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/spear-keyboard.c linux-libre-2.6.39-gnu/drivers/input/keyboard/spear-keyboard.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/spear-keyboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/spear-keyboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,7 +69,7 @@
 	u8 sts, val;
 
 	sts = readb(kbd->io_base + STATUS_REG);
-	if (sts & DATA_AVAIL)
+	if (!(sts & DATA_AVAIL))
 		return IRQ_NONE;
 
 	if (kbd->last_key != KEY_RESERVED) {
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/tc3589x-keypad.c linux-libre-2.6.39-gnu/drivers/input/keyboard/tc3589x-keypad.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/tc3589x-keypad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/tc3589x-keypad.c	2011-05-19 00:06:34.000000000 -0400
@@ -402,7 +402,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int tc3589x_keypad_suspend(struct device *dev)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -439,19 +439,19 @@
 
 	return 0;
 }
-
-static const SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
-			       tc3589x_keypad_suspend, tc3589x_keypad_resume);
 #endif
 
+static SIMPLE_DEV_PM_OPS(tc3589x_keypad_dev_pm_ops,
+			 tc3589x_keypad_suspend, tc3589x_keypad_resume);
+
 static struct platform_driver tc3589x_keypad_driver = {
-	.driver.name  = "tc3589x-keypad",
-	.driver.owner = THIS_MODULE,
-#ifdef CONFIG_PM
-	.driver.pm = &tc3589x_keypad_dev_pm_ops,
-#endif
-	.probe = tc3589x_keypad_probe,
-	.remove = __devexit_p(tc3589x_keypad_remove),
+	.driver	= {
+		.name	= "tc3589x-keypad",
+		.owner	= THIS_MODULE,
+		.pm	= &tc3589x_keypad_dev_pm_ops,
+	},
+	.probe	= tc3589x_keypad_probe,
+	.remove	= __devexit_p(tc3589x_keypad_remove),
 };
 
 static int __init tc3589x_keypad_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/tca6416-keypad.c linux-libre-2.6.39-gnu/drivers/input/keyboard/tca6416-keypad.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/tca6416-keypad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/tca6416-keypad.c	2011-05-19 00:06:34.000000000 -0400
@@ -297,6 +297,7 @@
 	}
 
 	i2c_set_clientdata(client, chip);
+	device_init_wakeup(&client->dev, 1);
 
 	return 0;
 
@@ -326,10 +327,37 @@
 	return 0;
 }
 
+#ifdef CONFIG_PM_SLEEP
+static int tca6416_keypad_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(dev))
+		enable_irq_wake(chip->irqnum);
+
+	return 0;
+}
+
+static int tca6416_keypad_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tca6416_keypad_chip *chip = i2c_get_clientdata(client);
+
+	if (device_may_wakeup(dev))
+		disable_irq_wake(chip->irqnum);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tca6416_keypad_dev_pm_ops,
+			 tca6416_keypad_suspend, tca6416_keypad_resume);
 
 static struct i2c_driver tca6416_keypad_driver = {
 	.driver = {
 		.name	= "tca6416-keypad",
+		.pm	= &tca6416_keypad_dev_pm_ops,
 	},
 	.probe		= tca6416_keypad_probe,
 	.remove		= __devexit_p(tca6416_keypad_remove),
diff -druN linux-libre-2.6.38-gnu/drivers/input/keyboard/twl4030_keypad.c linux-libre-2.6.39-gnu/drivers/input/keyboard/twl4030_keypad.c
--- linux-libre-2.6.38-gnu/drivers/input/keyboard/twl4030_keypad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/keyboard/twl4030_keypad.c	2011-05-19 00:06:34.000000000 -0400
@@ -332,18 +332,20 @@
 static int __devinit twl4030_kp_probe(struct platform_device *pdev)
 {
 	struct twl4030_keypad_data *pdata = pdev->dev.platform_data;
-	const struct matrix_keymap_data *keymap_data = pdata->keymap_data;
+	const struct matrix_keymap_data *keymap_data;
 	struct twl4030_keypad *kp;
 	struct input_dev *input;
 	u8 reg;
 	int error;
 
-	if (!pdata || !pdata->rows || !pdata->cols ||
+	if (!pdata || !pdata->rows || !pdata->cols || !pdata->keymap_data ||
 	    pdata->rows > TWL4030_MAX_ROWS || pdata->cols > TWL4030_MAX_COLS) {
 		dev_err(&pdev->dev, "Invalid platform_data\n");
 		return -EINVAL;
 	}
 
+	keymap_data = pdata->keymap_data;
+
 	kp = kzalloc(sizeof(*kp), GFP_KERNEL);
 	input = input_allocate_device();
 	if (!kp || !input) {
diff -druN linux-libre-2.6.38-gnu/drivers/input/Makefile linux-libre-2.6.39-gnu/drivers/input/Makefile
--- linux-libre-2.6.38-gnu/drivers/input/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -24,5 +24,3 @@
 obj-$(CONFIG_INPUT_MISC)	+= misc/
 
 obj-$(CONFIG_INPUT_APMPOWER)	+= apm-power.o
-
-obj-$(CONFIG_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/88pm860x_onkey.c linux-libre-2.6.39-gnu/drivers/input/misc/88pm860x_onkey.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/88pm860x_onkey.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/88pm860x_onkey.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,7 +74,7 @@
 	info->chip = chip;
 	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
 	info->dev = &pdev->dev;
-	info->irq = irq + chip->irq_base;
+	info->irq = irq;
 
 	info->idev = input_allocate_device();
 	if (!info->idev) {
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/ad714x-i2c.c linux-libre-2.6.39-gnu/drivers/input/misc/ad714x-i2c.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/ad714x-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/ad714x-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,23 +10,23 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 #include "ad714x.h"
 
 #ifdef CONFIG_PM
-static int ad714x_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int ad714x_i2c_suspend(struct device *dev)
 {
-	return ad714x_disable(i2c_get_clientdata(client));
+	return ad714x_disable(i2c_get_clientdata(to_i2c_client(dev)));
 }
 
-static int ad714x_i2c_resume(struct i2c_client *client)
+static int ad714x_i2c_resume(struct device *dev)
 {
-	return ad714x_enable(i2c_get_clientdata(client));
+	return ad714x_enable(i2c_get_clientdata(to_i2c_client(dev)));
 }
-#else
-# define ad714x_i2c_suspend NULL
-# define ad714x_i2c_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad714x_i2c_pm, ad714x_i2c_suspend, ad714x_i2c_resume);
+
 static int ad714x_i2c_write(struct device *dev, unsigned short reg,
 				unsigned short data)
 {
@@ -114,11 +114,10 @@
 static struct i2c_driver ad714x_i2c_driver = {
 	.driver = {
 		.name = "ad714x_captouch",
+		.pm   = &ad714x_i2c_pm,
 	},
 	.probe    = ad714x_i2c_probe,
 	.remove   = __devexit_p(ad714x_i2c_remove),
-	.suspend  = ad714x_i2c_suspend,
-	.resume	  = ad714x_i2c_resume,
 	.id_table = ad714x_id,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/ad714x-spi.c linux-libre-2.6.39-gnu/drivers/input/misc/ad714x-spi.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/ad714x-spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/ad714x-spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
 #include <linux/input.h>	/* BUS_I2C */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include "ad714x.h"
 
@@ -16,20 +17,19 @@
 #define AD714x_SPI_READ            BIT(10)
 
 #ifdef CONFIG_PM
-static int ad714x_spi_suspend(struct spi_device *spi, pm_message_t message)
+static int ad714x_spi_suspend(struct device *dev)
 {
-	return ad714x_disable(spi_get_drvdata(spi));
+	return ad714x_disable(spi_get_drvdata(to_spi_device(dev)));
 }
 
-static int ad714x_spi_resume(struct spi_device *spi)
+static int ad714x_spi_resume(struct device *dev)
 {
-	return ad714x_enable(spi_get_drvdata(spi));
+	return ad714x_enable(spi_get_drvdata(to_spi_device(dev)));
 }
-#else
-# define ad714x_spi_suspend NULL
-# define ad714x_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad714x_spi_pm, ad714x_spi_suspend, ad714x_spi_resume);
+
 static int ad714x_spi_read(struct device *dev, unsigned short reg,
 		unsigned short *data)
 {
@@ -79,11 +79,10 @@
 	.driver = {
 		.name	= "ad714x_captouch",
 		.owner	= THIS_MODULE,
+		.pm	= &ad714x_spi_pm,
 	},
 	.probe		= ad714x_spi_probe,
 	.remove		= __devexit_p(ad714x_spi_remove),
-	.suspend	= ad714x_spi_suspend,
-	.resume		= ad714x_spi_resume,
 };
 
 static __init int ad714x_spi_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/adxl34x.c linux-libre-2.6.39-gnu/drivers/input/misc/adxl34x.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/adxl34x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/adxl34x.c	2011-05-19 00:06:34.000000000 -0400
@@ -716,7 +716,7 @@
 	pdata = dev->platform_data;
 	if (!pdata) {
 		dev_dbg(dev,
-			"No platfrom data: Using default initialization\n");
+			"No platform data: Using default initialization\n");
 		pdata = &adxl34x_default_init;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/adxl34x-i2c.c linux-libre-2.6.39-gnu/drivers/input/misc/adxl34x-i2c.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/adxl34x-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/adxl34x-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/i2c.h>
 #include <linux/module.h>
 #include <linux/types.h>
+#include <linux/pm.h>
 #include "adxl34x.h"
 
 static int adxl34x_smbus_read(struct device *dev, unsigned char reg)
@@ -105,8 +106,9 @@
 }
 
 #ifdef CONFIG_PM
-static int adxl34x_i2c_suspend(struct i2c_client *client, pm_message_t message)
+static int adxl34x_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct adxl34x *ac = i2c_get_clientdata(client);
 
 	adxl34x_suspend(ac);
@@ -114,19 +116,20 @@
 	return 0;
 }
 
-static int adxl34x_i2c_resume(struct i2c_client *client)
+static int adxl34x_i2c_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct adxl34x *ac = i2c_get_clientdata(client);
 
 	adxl34x_resume(ac);
 
 	return 0;
 }
-#else
-# define adxl34x_i2c_suspend NULL
-# define adxl34x_i2c_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adxl34x_i2c_pm, adxl34x_i2c_suspend,
+			 adxl34x_i2c_resume);
+
 static const struct i2c_device_id adxl34x_id[] = {
 	{ "adxl34x", 0 },
 	{ }
@@ -138,11 +141,10 @@
 	.driver = {
 		.name = "adxl34x",
 		.owner = THIS_MODULE,
+		.pm = &adxl34x_i2c_pm,
 	},
 	.probe    = adxl34x_i2c_probe,
 	.remove   = __devexit_p(adxl34x_i2c_remove),
-	.suspend  = adxl34x_i2c_suspend,
-	.resume   = adxl34x_i2c_resume,
 	.id_table = adxl34x_id,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/adxl34x-spi.c linux-libre-2.6.39-gnu/drivers/input/misc/adxl34x-spi.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/adxl34x-spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/adxl34x-spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -10,6 +10,7 @@
 #include <linux/input.h>	/* BUS_SPI */
 #include <linux/module.h>
 #include <linux/spi/spi.h>
+#include <linux/pm.h>
 #include <linux/types.h>
 #include "adxl34x.h"
 
@@ -57,7 +58,7 @@
 	return (status < 0) ? status : 0;
 }
 
-static const struct adxl34x_bus_ops adx134x_spi_bops = {
+static const struct adxl34x_bus_ops adxl34x_spi_bops = {
 	.bustype	= BUS_SPI,
 	.write		= adxl34x_spi_write,
 	.read		= adxl34x_spi_read,
@@ -76,7 +77,7 @@
 
 	ac = adxl34x_probe(&spi->dev, spi->irq,
 			   spi->max_speed_hz > MAX_FREQ_NO_FIFODELAY,
-			   &adx134x_spi_bops);
+			   &adxl34x_spi_bops);
 
 	if (IS_ERR(ac))
 		return PTR_ERR(ac);
@@ -94,8 +95,9 @@
 }
 
 #ifdef CONFIG_PM
-static int adxl34x_spi_suspend(struct spi_device *spi, pm_message_t message)
+static int adxl34x_spi_suspend(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
 	adxl34x_suspend(ac);
@@ -103,29 +105,29 @@
 	return 0;
 }
 
-static int adxl34x_spi_resume(struct spi_device *spi)
+static int adxl34x_spi_resume(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct adxl34x *ac = dev_get_drvdata(&spi->dev);
 
 	adxl34x_resume(ac);
 
 	return 0;
 }
-#else
-# define adxl34x_spi_suspend NULL
-# define adxl34x_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adxl34x_spi_pm, adxl34x_spi_suspend,
+			 adxl34x_spi_resume);
+
 static struct spi_driver adxl34x_driver = {
 	.driver = {
 		.name = "adxl34x",
 		.bus = &spi_bus_type,
 		.owner = THIS_MODULE,
+		.pm = &adxl34x_spi_pm,
 	},
 	.probe   = adxl34x_spi_probe,
 	.remove  = __devexit_p(adxl34x_spi_remove),
-	.suspend = adxl34x_spi_suspend,
-	.resume  = adxl34x_spi_resume,
 };
 
 static int __init adxl34x_spi_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/ati_remote2.c linux-libre-2.6.39-gnu/drivers/input/misc/ati_remote2.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/ati_remote2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/ati_remote2.c	2011-05-19 00:06:34.000000000 -0400
@@ -612,8 +612,8 @@
 	idev->open = ati_remote2_open;
 	idev->close = ati_remote2_close;
 
-	idev->getkeycode_new = ati_remote2_getkeycode;
-	idev->setkeycode_new = ati_remote2_setkeycode;
+	idev->getkeycode = ati_remote2_getkeycode;
+	idev->setkeycode = ati_remote2_setkeycode;
 
 	idev->name = ar2->name;
 	idev->phys = ar2->phys;
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/Kconfig linux-libre-2.6.39-gnu/drivers/input/misc/Kconfig
--- linux-libre-2.6.38-gnu/drivers/input/misc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -454,4 +454,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cma3000_d0x_i2c.
 
+config INPUT_XEN_KBDDEV_FRONTEND
+	tristate "Xen virtual keyboard and mouse support"
+	depends on XEN_FBDEV_FRONTEND
+	default y
+	select XEN_XENBUS_FRONTEND
+	help
+	  This driver implements the front-end of the Xen virtual
+	  keyboard and mouse device driver.  It communicates with a back-end
+	  in another domain.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called xen-kbdfront.
+
 endif
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/keyspan_remote.c linux-libre-2.6.39-gnu/drivers/input/misc/keyspan_remote.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/keyspan_remote.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/keyspan_remote.c	2011-05-19 00:06:34.000000000 -0400
@@ -312,7 +312,7 @@
 			remote->data.tester = remote->data.tester >> 5;
 			remote->data.bits_left -= 5;
 		} else {
-			err("Bad message recieved, no stop bit found.\n");
+			err("Bad message received, no stop bit found.\n");
 		}
 
 		dev_dbg(&remote->udev->dev,
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/Makefile linux-libre-2.6.39-gnu/drivers/input/misc/Makefile
--- linux-libre-2.6.38-gnu/drivers/input/misc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -42,5 +42,6 @@
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
 obj-$(CONFIG_INPUT_WISTRON_BTNS)	+= wistron_btns.o
 obj-$(CONFIG_INPUT_WM831X_ON)		+= wm831x-on.o
+obj-$(CONFIG_INPUT_XEN_KBDDEV_FRONTEND)	+= xen-kbdfront.o
 obj-$(CONFIG_INPUT_YEALINK)		+= yealink.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/sparcspkr.c linux-libre-2.6.39-gnu/drivers/input/misc/sparcspkr.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/sparcspkr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/sparcspkr.c	2011-05-19 00:06:34.000000000 -0400
@@ -173,18 +173,16 @@
 	return 0;
 }
 
-static int sparcspkr_shutdown(struct platform_device *dev)
+static void sparcspkr_shutdown(struct platform_device *dev)
 {
 	struct sparcspkr_state *state = dev_get_drvdata(&dev->dev);
 	struct input_dev *input_dev = state->input_dev;
 
 	/* turn off the speaker */
 	state->event(input_dev, EV_SND, SND_BELL, 0);
-
-	return 0;
 }
 
-static int __devinit bbc_beep_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bbc_beep_probe(struct platform_device *op)
 {
 	struct sparcspkr_state *state;
 	struct bbc_beep_info *info;
@@ -258,7 +256,7 @@
 	{},
 };
 
-static struct of_platform_driver bbc_beep_driver = {
+static struct platform_driver bbc_beep_driver = {
 	.driver = {
 		.name = "bbcbeep",
 		.owner = THIS_MODULE,
@@ -269,7 +267,7 @@
 	.shutdown	= sparcspkr_shutdown,
 };
 
-static int __devinit grover_beep_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit grover_beep_probe(struct platform_device *op)
 {
 	struct sparcspkr_state *state;
 	struct grover_beep_info *info;
@@ -340,7 +338,7 @@
 	{},
 };
 
-static struct of_platform_driver grover_beep_driver = {
+static struct platform_driver grover_beep_driver = {
 	.driver = {
 		.name = "groverbeep",
 		.owner = THIS_MODULE,
@@ -353,12 +351,12 @@
 
 static int __init sparcspkr_init(void)
 {
-	int err = of_register_platform_driver(&bbc_beep_driver);
+	int err = platform_driver_register(&bbc_beep_driver);
 
 	if (!err) {
-		err = of_register_platform_driver(&grover_beep_driver);
+		err = platform_driver_register(&grover_beep_driver);
 		if (err)
-			of_unregister_platform_driver(&bbc_beep_driver);
+			platform_driver_unregister(&bbc_beep_driver);
 	}
 
 	return err;
@@ -366,8 +364,8 @@
 
 static void __exit sparcspkr_exit(void)
 {
-	of_unregister_platform_driver(&bbc_beep_driver);
-	of_unregister_platform_driver(&grover_beep_driver);
+	platform_driver_unregister(&bbc_beep_driver);
+	platform_driver_unregister(&grover_beep_driver);
 }
 
 module_init(sparcspkr_init);
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/twl4030-vibra.c linux-libre-2.6.39-gnu/drivers/input/misc/twl4030-vibra.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/twl4030-vibra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/twl4030-vibra.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/workqueue.h>
 #include <linux/i2c/twl.h>
 #include <linux/mfd/twl4030-codec.h>
+#include <linux/mfd/core.h>
 #include <linux/input.h>
 #include <linux/slab.h>
 
@@ -196,7 +197,7 @@
 
 static int __devinit twl4030_vibra_probe(struct platform_device *pdev)
 {
-	struct twl4030_codec_vibra_data *pdata = pdev->dev.platform_data;
+	struct twl4030_codec_vibra_data *pdata = mfd_get_data(pdev);
 	struct vibra_info *info;
 	int ret;
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/uinput.c linux-libre-2.6.39-gnu/drivers/input/misc/uinput.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/uinput.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/uinput.c	2011-05-19 00:06:34.000000000 -0400
@@ -302,10 +302,14 @@
 	int retval = 0;
 
 	for (cnt = 0; cnt < ABS_CNT; cnt++) {
+		int min, max;
 		if (!test_bit(cnt, dev->absbit))
 			continue;
 
-		if (input_abs_get_max(dev, cnt) <= input_abs_get_min(dev, cnt)) {
+		min = input_abs_get_min(dev, cnt);
+		max = input_abs_get_max(dev, cnt);
+
+		if ((min != 0 || max != 0) && max <= min) {
 			printk(KERN_DEBUG
 				"%s: invalid abs[%02x] min:%d max:%d\n",
 				UINPUT_NAME, cnt,
@@ -347,8 +351,7 @@
 {
 	struct uinput_user_dev	*user_dev;
 	struct input_dev	*dev;
-	char			*name;
-	int			i, size;
+	int			i;
 	int			retval;
 
 	if (count != sizeof(struct uinput_user_dev))
@@ -362,30 +365,25 @@
 
 	dev = udev->dev;
 
-	user_dev = kmalloc(sizeof(struct uinput_user_dev), GFP_KERNEL);
-	if (!user_dev)
-		return -ENOMEM;
-
-	if (copy_from_user(user_dev, buffer, sizeof(struct uinput_user_dev))) {
-		retval = -EFAULT;
-		goto exit;
-	}
+	user_dev = memdup_user(buffer, sizeof(struct uinput_user_dev));
+	if (IS_ERR(user_dev))
+		return PTR_ERR(user_dev);
 
 	udev->ff_effects_max = user_dev->ff_effects_max;
 
-	size = strnlen(user_dev->name, UINPUT_MAX_NAME_SIZE) + 1;
-	if (!size) {
+	/* Ensure name is filled in */
+	if (!user_dev->name[0]) {
 		retval = -EINVAL;
 		goto exit;
 	}
 
 	kfree(dev->name);
-	dev->name = name = kmalloc(size, GFP_KERNEL);
-	if (!name) {
+	dev->name = kstrndup(user_dev->name, UINPUT_MAX_NAME_SIZE,
+			     GFP_KERNEL);
+	if (!dev->name) {
 		retval = -ENOMEM;
 		goto exit;
 	}
-	strlcpy(name, user_dev->name, size);
 
 	dev->id.bustype	= user_dev->id.bustype;
 	dev->id.vendor	= user_dev->id.vendor;
@@ -622,7 +620,6 @@
 	struct uinput_ff_upload ff_up;
 	struct uinput_ff_erase  ff_erase;
 	struct uinput_request   *req;
-	int                     length;
 	char			*phys;
 
 	retval = mutex_lock_interruptible(&udev->mutex);
@@ -689,24 +686,15 @@
 				retval = -EINVAL;
 				goto out;
 			}
-			length = strnlen_user(p, 1024);
-			if (length <= 0) {
-				retval = -EFAULT;
-				break;
+
+			phys = strndup_user(p, 1024);
+			if (IS_ERR(phys)) {
+				retval = PTR_ERR(phys);
+				goto out;
 			}
+
 			kfree(udev->dev->phys);
-			udev->dev->phys = phys = kmalloc(length, GFP_KERNEL);
-			if (!phys) {
-				retval = -ENOMEM;
-				break;
-			}
-			if (copy_from_user(phys, p, length)) {
-				udev->dev->phys = NULL;
-				kfree(phys);
-				retval = -EFAULT;
-				break;
-			}
-			phys[length - 1] = '\0';
+			udev->dev->phys = phys;
 			break;
 
 		case UI_BEGIN_FF_UPLOAD:
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/wistron_btns.c linux-libre-2.6.39-gnu/drivers/input/misc/wistron_btns.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/wistron_btns.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/misc/wistron_btns.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,7 +274,7 @@
 	{ KE_BLUETOOTH, 0x30 },                      /* Fn+F10 */
 	{ KE_KEY,       0x31, {KEY_MAIL} },          /* mail button */
 	{ KE_KEY,       0x36, {KEY_WWW} },           /* www button */
-	{ KE_WIFI,      0x78 },                      /* satelite dish button */
+	{ KE_WIFI,      0x78 },                      /* satellite dish button */
 	{ KE_END,       0 }
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/misc/xen-kbdfront.c linux-libre-2.6.39-gnu/drivers/input/misc/xen-kbdfront.c
--- linux-libre-2.6.38-gnu/drivers/input/misc/xen-kbdfront.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/input/misc/xen-kbdfront.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,396 @@
+/*
+ * Xen para-virtual input device
+ *
+ * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
+ * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
+ *
+ *  Based on linux/drivers/input/mouse/sermouse.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.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/slab.h>
+
+#include <asm/xen/hypervisor.h>
+
+#include <xen/xen.h>
+#include <xen/events.h>
+#include <xen/page.h>
+#include <xen/grant_table.h>
+#include <xen/interface/grant_table.h>
+#include <xen/interface/io/fbif.h>
+#include <xen/interface/io/kbdif.h>
+#include <xen/xenbus.h>
+
+struct xenkbd_info {
+	struct input_dev *kbd;
+	struct input_dev *ptr;
+	struct xenkbd_page *page;
+	int gref;
+	int irq;
+	struct xenbus_device *xbdev;
+	char phys[32];
+};
+
+static int xenkbd_remove(struct xenbus_device *);
+static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
+static void xenkbd_disconnect_backend(struct xenkbd_info *);
+
+/*
+ * Note: if you need to send out events, see xenfb_do_update() for how
+ * to do that.
+ */
+
+static irqreturn_t input_handler(int rq, void *dev_id)
+{
+	struct xenkbd_info *info = dev_id;
+	struct xenkbd_page *page = info->page;
+	__u32 cons, prod;
+
+	prod = page->in_prod;
+	if (prod == page->in_cons)
+		return IRQ_HANDLED;
+	rmb();			/* ensure we see ring contents up to prod */
+	for (cons = page->in_cons; cons != prod; cons++) {
+		union xenkbd_in_event *event;
+		struct input_dev *dev;
+		event = &XENKBD_IN_RING_REF(page, cons);
+
+		dev = info->ptr;
+		switch (event->type) {
+		case XENKBD_TYPE_MOTION:
+			input_report_rel(dev, REL_X, event->motion.rel_x);
+			input_report_rel(dev, REL_Y, event->motion.rel_y);
+			if (event->motion.rel_z)
+				input_report_rel(dev, REL_WHEEL,
+						 -event->motion.rel_z);
+			break;
+		case XENKBD_TYPE_KEY:
+			dev = NULL;
+			if (test_bit(event->key.keycode, info->kbd->keybit))
+				dev = info->kbd;
+			if (test_bit(event->key.keycode, info->ptr->keybit))
+				dev = info->ptr;
+			if (dev)
+				input_report_key(dev, event->key.keycode,
+						 event->key.pressed);
+			else
+				pr_warning("unhandled keycode 0x%x\n",
+					   event->key.keycode);
+			break;
+		case XENKBD_TYPE_POS:
+			input_report_abs(dev, ABS_X, event->pos.abs_x);
+			input_report_abs(dev, ABS_Y, event->pos.abs_y);
+			if (event->pos.rel_z)
+				input_report_rel(dev, REL_WHEEL,
+						 -event->pos.rel_z);
+			break;
+		}
+		if (dev)
+			input_sync(dev);
+	}
+	mb();			/* ensure we got ring contents */
+	page->in_cons = cons;
+	notify_remote_via_irq(info->irq);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit xenkbd_probe(struct xenbus_device *dev,
+				  const struct xenbus_device_id *id)
+{
+	int ret, i, abs;
+	struct xenkbd_info *info;
+	struct input_dev *kbd, *ptr;
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info) {
+		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
+		return -ENOMEM;
+	}
+	dev_set_drvdata(&dev->dev, info);
+	info->xbdev = dev;
+	info->irq = -1;
+	info->gref = -1;
+	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
+
+	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
+	if (!info->page)
+		goto error_nomem;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-abs-pointer", "%d", &abs) < 0)
+		abs = 0;
+	if (abs)
+		xenbus_printf(XBT_NIL, dev->nodename, "request-abs-pointer", "1");
+
+	/* keyboard */
+	kbd = input_allocate_device();
+	if (!kbd)
+		goto error_nomem;
+	kbd->name = "Xen Virtual Keyboard";
+	kbd->phys = info->phys;
+	kbd->id.bustype = BUS_PCI;
+	kbd->id.vendor = 0x5853;
+	kbd->id.product = 0xffff;
+
+	__set_bit(EV_KEY, kbd->evbit);
+	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
+		__set_bit(i, kbd->keybit);
+	for (i = KEY_OK; i < KEY_MAX; i++)
+		__set_bit(i, kbd->keybit);
+
+	ret = input_register_device(kbd);
+	if (ret) {
+		input_free_device(kbd);
+		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
+		goto error;
+	}
+	info->kbd = kbd;
+
+	/* pointing device */
+	ptr = input_allocate_device();
+	if (!ptr)
+		goto error_nomem;
+	ptr->name = "Xen Virtual Pointer";
+	ptr->phys = info->phys;
+	ptr->id.bustype = BUS_PCI;
+	ptr->id.vendor = 0x5853;
+	ptr->id.product = 0xfffe;
+
+	if (abs) {
+		__set_bit(EV_ABS, ptr->evbit);
+		input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
+		input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
+	} else {
+		input_set_capability(ptr, EV_REL, REL_X);
+		input_set_capability(ptr, EV_REL, REL_Y);
+	}
+	input_set_capability(ptr, EV_REL, REL_WHEEL);
+
+	__set_bit(EV_KEY, ptr->evbit);
+	for (i = BTN_LEFT; i <= BTN_TASK; i++)
+		__set_bit(i, ptr->keybit);
+
+	ret = input_register_device(ptr);
+	if (ret) {
+		input_free_device(ptr);
+		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
+		goto error;
+	}
+	info->ptr = ptr;
+
+	ret = xenkbd_connect_backend(dev, info);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+ error_nomem:
+	ret = -ENOMEM;
+	xenbus_dev_fatal(dev, ret, "allocating device memory");
+ error:
+	xenkbd_remove(dev);
+	return ret;
+}
+
+static int xenkbd_resume(struct xenbus_device *dev)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+	xenkbd_disconnect_backend(info);
+	memset(info->page, 0, PAGE_SIZE);
+	return xenkbd_connect_backend(dev, info);
+}
+
+static int xenkbd_remove(struct xenbus_device *dev)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+
+	xenkbd_disconnect_backend(info);
+	if (info->kbd)
+		input_unregister_device(info->kbd);
+	if (info->ptr)
+		input_unregister_device(info->ptr);
+	free_page((unsigned long)info->page);
+	kfree(info);
+	return 0;
+}
+
+static int xenkbd_connect_backend(struct xenbus_device *dev,
+				  struct xenkbd_info *info)
+{
+	int ret, evtchn;
+	struct xenbus_transaction xbt;
+
+	ret = gnttab_grant_foreign_access(dev->otherend_id,
+	                                  virt_to_mfn(info->page), 0);
+	if (ret < 0)
+		return ret;
+	info->gref = ret;
+
+	ret = xenbus_alloc_evtchn(dev, &evtchn);
+	if (ret)
+		goto error_grant;
+	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
+					0, dev->devicetype, info);
+	if (ret < 0) {
+		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
+		goto error_evtchan;
+	}
+	info->irq = ret;
+
+ again:
+	ret = xenbus_transaction_start(&xbt);
+	if (ret) {
+		xenbus_dev_fatal(dev, ret, "starting transaction");
+		goto error_irqh;
+	}
+	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
+			    virt_to_mfn(info->page));
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "page-gref", "%u", info->gref);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
+			    evtchn);
+	if (ret)
+		goto error_xenbus;
+	ret = xenbus_transaction_end(xbt, 0);
+	if (ret) {
+		if (ret == -EAGAIN)
+			goto again;
+		xenbus_dev_fatal(dev, ret, "completing transaction");
+		goto error_irqh;
+	}
+
+	xenbus_switch_state(dev, XenbusStateInitialised);
+	return 0;
+
+ error_xenbus:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, ret, "writing xenstore");
+ error_irqh:
+	unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+ error_evtchan:
+	xenbus_free_evtchn(dev, evtchn);
+ error_grant:
+	gnttab_end_foreign_access_ref(info->gref, 0);
+	info->gref = -1;
+	return ret;
+}
+
+static void xenkbd_disconnect_backend(struct xenkbd_info *info)
+{
+	if (info->irq >= 0)
+		unbind_from_irqhandler(info->irq, info);
+	info->irq = -1;
+	if (info->gref >= 0)
+		gnttab_end_foreign_access_ref(info->gref, 0);
+	info->gref = -1;
+}
+
+static void xenkbd_backend_changed(struct xenbus_device *dev,
+				   enum xenbus_state backend_state)
+{
+	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
+	int ret, val;
+
+	switch (backend_state) {
+	case XenbusStateInitialising:
+	case XenbusStateInitialised:
+	case XenbusStateReconfiguring:
+	case XenbusStateReconfigured:
+	case XenbusStateUnknown:
+	case XenbusStateClosed:
+		break;
+
+	case XenbusStateInitWait:
+InitWait:
+		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				   "feature-abs-pointer", "%d", &val);
+		if (ret < 0)
+			val = 0;
+		if (val) {
+			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
+					    "request-abs-pointer", "1");
+			if (ret)
+				pr_warning("xenkbd: can't request abs-pointer");
+		}
+
+		xenbus_switch_state(dev, XenbusStateConnected);
+		break;
+
+	case XenbusStateConnected:
+		/*
+		 * Work around xenbus race condition: If backend goes
+		 * through InitWait to Connected fast enough, we can
+		 * get Connected twice here.
+		 */
+		if (dev->state != XenbusStateConnected)
+			goto InitWait; /* no InitWait seen yet, fudge it */
+
+		/* Set input abs params to match backend screen res */
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "width", "%d", &val) > 0)
+			input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
+
+		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
+				 "height", "%d", &val) > 0)
+			input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
+
+		break;
+
+	case XenbusStateClosing:
+		xenbus_frontend_closed(dev);
+		break;
+	}
+}
+
+static const struct xenbus_device_id xenkbd_ids[] = {
+	{ "vkbd" },
+	{ "" }
+};
+
+static struct xenbus_driver xenkbd_driver = {
+	.name = "vkbd",
+	.owner = THIS_MODULE,
+	.ids = xenkbd_ids,
+	.probe = xenkbd_probe,
+	.remove = xenkbd_remove,
+	.resume = xenkbd_resume,
+	.otherend_changed = xenkbd_backend_changed,
+};
+
+static int __init xenkbd_init(void)
+{
+	if (!xen_pv_domain())
+		return -ENODEV;
+
+	/* Nothing to do if running in dom0. */
+	if (xen_initial_domain())
+		return -ENODEV;
+
+	return xenbus_register_frontend(&xenkbd_driver);
+}
+
+static void __exit xenkbd_cleanup(void)
+{
+	xenbus_unregister_driver(&xenkbd_driver);
+}
+
+module_init(xenkbd_init);
+module_exit(xenkbd_cleanup);
+
+MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("xen:vkbd");
diff -druN linux-libre-2.6.38-gnu/drivers/input/mouse/bcm5974.c linux-libre-2.6.39-gnu/drivers/input/mouse/bcm5974.c
--- linux-libre-2.6.38-gnu/drivers/input/mouse/bcm5974.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/mouse/bcm5974.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,6 +63,10 @@
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI	0x0242
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO	0x0243
 #define USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS	0x0244
+/* Macbook8 (unibody, March 2011) */
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI	0x0245
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_ISO	0x0246
+#define USB_DEVICE_ID_APPLE_WELLSPRING5_JIS	0x0247
 
 #define BCM5974_DEVICE(prod) {					\
 	.match_flags = (USB_DEVICE_ID_MATCH_DEVICE |		\
@@ -96,6 +100,10 @@
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ANSI),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_ISO),
 	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING4A_JIS),
+	/* MacbookPro8 */
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_ISO),
+	BCM5974_DEVICE(USB_DEVICE_ID_APPLE_WELLSPRING5_JIS),
 	/* Terminating entry */
 	{}
 };
@@ -274,6 +282,18 @@
 		{ DIM_X, DIM_X / SN_COORD, -4616, 5112 },
 		{ DIM_Y, DIM_Y / SN_COORD, -142, 5234 }
 	},
+	{
+		USB_DEVICE_ID_APPLE_WELLSPRING5_ANSI,
+		USB_DEVICE_ID_APPLE_WELLSPRING5_ISO,
+		USB_DEVICE_ID_APPLE_WELLSPRING5_JIS,
+		HAS_INTEGRATED_BUTTON,
+		0x84, sizeof(struct bt_data),
+		0x81, TYPE2, FINGER_TYPE2, FINGER_TYPE2 + SIZEOF_ALL_FINGERS,
+		{ DIM_PRESSURE, DIM_PRESSURE / SN_PRESSURE, 0, 300 },
+		{ DIM_WIDTH, DIM_WIDTH / SN_WIDTH, 0, 2048 },
+		{ DIM_X, DIM_X / SN_COORD, -4415, 5050 },
+		{ DIM_Y, DIM_Y / SN_COORD, -55, 6680 }
+	},
 	{}
 };
 
@@ -430,10 +450,6 @@
 		ptest = int2bound(&c->p, raw_p);
 		origin = raw2int(f->origin);
 
-		/* set the integrated button if applicable */
-		if (c->tp_type == TYPE2)
-			ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
-
 		/* while tracking finger still valid, count all fingers */
 		if (ptest > PRESSURE_LOW && origin) {
 			abs_p = ptest;
@@ -452,6 +468,10 @@
 		}
 	}
 
+	/* set the integrated button if applicable */
+	if (c->tp_type == TYPE2)
+		ibt = raw2int(dev->tp_data[BUTTON_TYPE2]);
+
 	if (dev->fingers < nmin)
 		dev->fingers = nmin;
 	if (dev->fingers > nmax)
@@ -619,7 +639,7 @@
  * device, resulting in trackpad malfunction under certain
  * circumstances. To get around this problem, there is at least one
  * example that utilizes the USB_QUIRK_RESET_RESUME quirk in order to
- * recieve a reset_resume request rather than the normal resume.
+ * receive a reset_resume request rather than the normal resume.
  * Since the implementation of reset_resume is equal to mode switch
  * plus start_traffic, it seems easier to always do the switch when
  * starting traffic on the device.
diff -druN linux-libre-2.6.38-gnu/drivers/input/mouse/synaptics.c linux-libre-2.6.39-gnu/drivers/input/mouse/synaptics.c
--- linux-libre-2.6.38-gnu/drivers/input/mouse/synaptics.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/mouse/synaptics.c	2011-05-19 00:06:34.000000000 -0400
@@ -836,8 +836,8 @@
 		},
 
 	},
-	{ }
 #endif
+	{ }
 };
 
 static bool broken_olpc_ec;
@@ -851,8 +851,8 @@
 			DMI_MATCH(DMI_PRODUCT_NAME, "XO"),
 		},
 	},
-	{ }
 #endif
+	{ }
 };
 
 void __init synaptics_module_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/mouse/synaptics_i2c.c linux-libre-2.6.39-gnu/drivers/input/mouse/synaptics_i2c.c
--- linux-libre-2.6.38-gnu/drivers/input/mouse/synaptics_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/mouse/synaptics_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 #define DRIVER_NAME		"synaptics_i2c"
 /* maximum product id is 15 characters */
@@ -461,7 +462,7 @@
 	 * 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.
+	 * necessarily 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.
 	 */
@@ -619,8 +620,9 @@
 }
 
 #ifdef CONFIG_PM
-static int synaptics_i2c_suspend(struct i2c_client *client, pm_message_t mesg)
+static int synaptics_i2c_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
 	cancel_delayed_work_sync(&touch->dwork);
@@ -631,9 +633,10 @@
 	return 0;
 }
 
-static int synaptics_i2c_resume(struct i2c_client *client)
+static int synaptics_i2c_resume(struct device *dev)
 {
 	int ret;
+	struct i2c_client *client = to_i2c_client(dev);
 	struct synaptics_i2c *touch = i2c_get_clientdata(client);
 
 	ret = synaptics_i2c_reset_config(client);
@@ -645,11 +648,11 @@
 
 	return 0;
 }
-#else
-#define synaptics_i2c_suspend	NULL
-#define synaptics_i2c_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(synaptics_i2c_pm, synaptics_i2c_suspend,
+			 synaptics_i2c_resume);
+
 static const struct i2c_device_id synaptics_i2c_id_table[] = {
 	{ "synaptics_i2c", 0 },
 	{ },
@@ -660,13 +663,12 @@
 	.driver = {
 		.name	= DRIVER_NAME,
 		.owner	= THIS_MODULE,
+		.pm	= &synaptics_i2c_pm,
 	},
 
 	.probe		= synaptics_i2c_probe,
 	.remove		= __devexit_p(synaptics_i2c_remove),
 
-	.suspend	= synaptics_i2c_suspend,
-	.resume		= synaptics_i2c_resume,
 	.id_table	= synaptics_i2c_id_table,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/mouse/vsxxxaa.c linux-libre-2.6.39-gnu/drivers/input/mouse/vsxxxaa.c
--- linux-libre-2.6.38-gnu/drivers/input/mouse/vsxxxaa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/mouse/vsxxxaa.c	2011-05-19 00:06:34.000000000 -0400
@@ -334,7 +334,7 @@
 	 * M: manufacturer location code
 	 * R: revision code
 	 * E: Error code. If it's in the range of 0x00..0x1f, only some
-	 *    minor problem occured. Errors >= 0x20 are considered bad
+	 *    minor problem occurred. Errors >= 0x20 are considered bad
 	 *    and the device may not work properly...
 	 * D: <0010> == mouse, <0100> == tablet
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/altera_ps2.c linux-libre-2.6.39-gnu/drivers/input/serio/altera_ps2.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/altera_ps2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/altera_ps2.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/of.h>
 
 #define DRV_NAME "altera_ps2"
 
@@ -173,6 +174,16 @@
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id altera_ps2_match[] = {
+	{ .compatible = "ALTR,ps2-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_ps2_match);
+#else /* CONFIG_OF */
+#define altera_ps2_match NULL
+#endif /* CONFIG_OF */
+
 /*
  * Our device driver structure
  */
@@ -182,6 +193,7 @@
 	.driver	= {
 		.name	= DRV_NAME,
 		.owner	= THIS_MODULE,
+		.of_match_table = altera_ps2_match,
 	},
 };
 
@@ -189,13 +201,12 @@
 {
 	return platform_driver_register(&altera_ps2_driver);
 }
+module_init(altera_ps2_init);
 
 static void __exit altera_ps2_exit(void)
 {
 	platform_driver_unregister(&altera_ps2_driver);
 }
-
-module_init(altera_ps2_init);
 module_exit(altera_ps2_exit);
 
 MODULE_DESCRIPTION("Altera University Program PS2 controller driver");
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/ambakmi.c linux-libre-2.6.39-gnu/drivers/input/serio/ambakmi.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/ambakmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/ambakmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,7 +107,8 @@
 	clk_disable(kmi->clk);
 }
 
-static int __devinit amba_kmi_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit amba_kmi_probe(struct amba_device *dev,
+	const struct amba_id *id)
 {
 	struct amba_kmi_port *kmi;
 	struct serio *io;
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/ams_delta_serio.c linux-libre-2.6.39-gnu/drivers/input/serio/ams_delta_serio.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/ams_delta_serio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/ams_delta_serio.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
 	 * at FIQ level, switch back from edge to simple interrupt handler
 	 * to avoid bad interaction.
 	 */
-	set_irq_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
+	irq_set_handler(gpio_to_irq(AMS_DELTA_GPIO_PIN_KEYBRD_CLK),
 			handle_simple_irq);
 
 	serio_register_port(ams_delta_serio);
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/hp_sdc.c linux-libre-2.6.39-gnu/drivers/input/serio/hp_sdc.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/hp_sdc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/hp_sdc.c	2011-05-19 00:06:34.000000000 -0400
@@ -955,7 +955,7 @@
 	INIT_DELAYED_WORK(&moduleloader_work, request_module_delayed);
 
 	ret = hp_sdc_init();
-	/* after successfull initialization give SDC some time to settle
+	/* after successful initialization give SDC some time to settle
 	 * and then load the hp_sdc_mlc upper layer driver */
 	if (!ret)
 		schedule_delayed_work(&moduleloader_work,
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/i8042.c linux-libre-2.6.39-gnu/drivers/input/serio/i8042.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/i8042.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/i8042.c	2011-05-19 00:06:34.000000000 -0400
@@ -869,15 +869,15 @@
 	do {
 
 		if (i8042_command(&param, I8042_CMD_CTL_TEST)) {
-			pr_err("i8042 controller self test timeout\n");
+			pr_err("i8042 controller selftest timeout\n");
 			return -ENODEV;
 		}
 
 		if (param == I8042_RET_CTL_TEST)
 			return 0;
 
-		pr_err("i8042 controller selftest failed. (%#x != %#x)\n",
-		       param, I8042_RET_CTL_TEST);
+		dbg("i8042 controller selftest: %#x != %#x\n",
+		    param, I8042_RET_CTL_TEST);
 		msleep(50);
 	} while (i++ < 5);
 
@@ -891,6 +891,7 @@
 	pr_info("giving up on controller selftest, continuing anyway...\n");
 	return 0;
 #else
+	pr_err("i8042 controller selftest failed\n");
 	return -EIO;
 #endif
 }
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/i8042.h linux-libre-2.6.39-gnu/drivers/input/serio/i8042.h
--- linux-libre-2.6.38-gnu/drivers/input/serio/i8042.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/i8042.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,8 @@
 #include "i8042-sparcio.h"
 #elif defined(CONFIG_X86) || defined(CONFIG_IA64)
 #include "i8042-x86ia64io.h"
+#elif defined(CONFIG_UNICORE32)
+#include "i8042-unicore32io.h"
 #else
 #include "i8042-io.h"
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/i8042-sparcio.h linux-libre-2.6.39-gnu/drivers/input/serio/i8042-sparcio.h
--- linux-libre-2.6.38-gnu/drivers/input/serio/i8042-sparcio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/i8042-sparcio.h	2011-05-19 00:06:34.000000000 -0400
@@ -49,7 +49,7 @@
 #define OBP_PS2MS_NAME1		"kdmouse"
 #define OBP_PS2MS_NAME2		"mouse"
 
-static int __devinit sparc_i8042_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit sparc_i8042_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -95,7 +95,7 @@
 };
 MODULE_DEVICE_TABLE(of, sparc_i8042_match);
 
-static struct of_platform_driver sparc_i8042_driver = {
+static struct platform_driver sparc_i8042_driver = {
 	.driver = {
 		.name = "i8042",
 		.owner = THIS_MODULE,
@@ -116,7 +116,7 @@
 		if (!kbd_iobase)
 			return -ENODEV;
 	} else {
-		int err = of_register_platform_driver(&sparc_i8042_driver);
+		int err = platform_driver_register(&sparc_i8042_driver);
 		if (err)
 			return err;
 
@@ -140,7 +140,7 @@
 	struct device_node *root = of_find_node_by_path("/");
 
 	if (strcmp(root->name, "SUNW,JavaStation-1"))
-		of_unregister_platform_driver(&sparc_i8042_driver);
+		platform_driver_unregister(&sparc_i8042_driver);
 }
 
 #else /* !CONFIG_PCI */
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/i8042-unicore32io.h linux-libre-2.6.39-gnu/drivers/input/serio/i8042-unicore32io.h
--- linux-libre-2.6.38-gnu/drivers/input/serio/i8042-unicore32io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/input/serio/i8042-unicore32io.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,73 @@
+/*
+ * Code specific to PKUnity SoC and UniCore ISA
+ *
+ *	Maintained by GUAN Xue-tao <gxt@mprc.pku.edu.cn>
+ *	Copyright (C) 2001-2011 Guan Xuetao
+ *
+ * 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 _I8042_UNICORE32_H
+#define _I8042_UNICORE32_H
+
+#include <mach/hardware.h>
+
+/*
+ * Names.
+ */
+#define I8042_KBD_PHYS_DESC "isa0060/serio0"
+#define I8042_AUX_PHYS_DESC "isa0060/serio1"
+#define I8042_MUX_PHYS_DESC "isa0060/serio%d"
+
+/*
+ * IRQs.
+ */
+#define I8042_KBD_IRQ           IRQ_PS2_KBD
+#define I8042_AUX_IRQ           IRQ_PS2_AUX
+
+/*
+ * Register numbers.
+ */
+#define I8042_COMMAND_REG	PS2_COMMAND
+#define I8042_STATUS_REG	PS2_STATUS
+#define I8042_DATA_REG		PS2_DATA
+
+#define I8042_REGION_START	(resource_size_t)(PS2_DATA)
+#define I8042_REGION_SIZE	(resource_size_t)(16)
+
+static inline int i8042_read_data(void)
+{
+	return readb(I8042_DATA_REG);
+}
+
+static inline int i8042_read_status(void)
+{
+	return readb(I8042_STATUS_REG);
+}
+
+static inline void i8042_write_data(int val)
+{
+	writeb(val, I8042_DATA_REG);
+}
+
+static inline void i8042_write_command(int val)
+{
+	writeb(val, I8042_COMMAND_REG);
+}
+
+static inline int i8042_platform_init(void)
+{
+	if (!request_mem_region(I8042_REGION_START, I8042_REGION_SIZE, "i8042"))
+		return -EBUSY;
+
+	i8042_reset = 1;
+	return 0;
+}
+
+static inline void i8042_platform_exit(void)
+{
+	release_mem_region(I8042_REGION_START, I8042_REGION_SIZE);
+}
+
+#endif /* _I8042_UNICORE32_H */
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/rpckbd.c linux-libre-2.6.39-gnu/drivers/input/serio/rpckbd.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/rpckbd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/rpckbd.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,7 +90,7 @@
 
 	if (request_irq(IRQ_KEYBOARDTX, rpckbd_tx, 0, "rpckbd", port) != 0) {
 		printk(KERN_ERR "rpckbd.c: Could not allocate keyboard transmit IRQ\n");
-		free_irq(IRQ_KEYBOARDRX, NULL);
+		free_irq(IRQ_KEYBOARDRX, port);
 		return -EBUSY;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/serio/xilinx_ps2.c linux-libre-2.6.39-gnu/drivers/input/serio/xilinx_ps2.c
--- linux-libre-2.6.38-gnu/drivers/input/serio/xilinx_ps2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/serio/xilinx_ps2.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,15 +225,14 @@
 /**
  * xps2_of_probe - probe method for the PS/2 device.
  * @of_dev:	pointer to OF device structure
- * @match:	pointer to the stucture used for matching a device
+ * @match:	pointer to the structure used for matching a device
  *
  * This function probes the PS/2 device in the device tree.
  * It initializes the driver data structure and the hardware.
  * It returns 0, if the driver is bound to the PS/2 device, or a negative
  * value if there is an error.
  */
-static int __devinit xps2_of_probe(struct platform_device *ofdev,
-				   const struct of_device_id *match)
+static int __devinit xps2_of_probe(struct platform_device *ofdev)
 {
 	struct resource r_irq; /* Interrupt resources */
 	struct resource r_mem; /* IO mem resources */
@@ -361,7 +360,7 @@
 };
 MODULE_DEVICE_TABLE(of, xps2_of_match);
 
-static struct of_platform_driver xps2_of_driver = {
+static struct platform_driver xps2_of_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -373,12 +372,12 @@
 
 static int __init xps2_init(void)
 {
-	return of_register_platform_driver(&xps2_of_driver);
+	return platform_driver_register(&xps2_of_driver);
 }
 
 static void __exit xps2_cleanup(void)
 {
-	of_unregister_platform_driver(&xps2_of_driver);
+	platform_driver_unregister(&xps2_of_driver);
 }
 
 module_init(xps2_init);
diff -druN linux-libre-2.6.38-gnu/drivers/input/sparse-keymap.c linux-libre-2.6.39-gnu/drivers/input/sparse-keymap.c
--- linux-libre-2.6.38-gnu/drivers/input/sparse-keymap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/sparse-keymap.c	2011-05-19 00:06:34.000000000 -0400
@@ -208,10 +208,16 @@
 		}
 	}
 
+	if (test_bit(EV_KEY, dev->evbit)) {
+		__set_bit(KEY_UNKNOWN, dev->keybit);
+		__set_bit(EV_MSC, dev->evbit);
+		__set_bit(MSC_SCAN, dev->mscbit);
+	}
+
 	dev->keycode = map;
 	dev->keycodemax = map_size;
-	dev->getkeycode_new = sparse_keymap_getkeycode;
-	dev->setkeycode_new = sparse_keymap_setkeycode;
+	dev->getkeycode = sparse_keymap_getkeycode;
+	dev->setkeycode = sparse_keymap_setkeycode;
 
 	return 0;
 
@@ -268,6 +274,7 @@
 {
 	switch (ke->type) {
 	case KE_KEY:
+		input_event(dev, EV_MSC, MSC_SCAN, ke->code);
 		input_report_key(dev, ke->keycode, value);
 		input_sync(dev);
 		if (value && autorelease) {
@@ -305,12 +312,19 @@
 {
 	const struct key_entry *ke =
 		sparse_keymap_entry_from_scancode(dev, code);
+	struct key_entry unknown_ke;
 
 	if (ke) {
 		sparse_keymap_report_entry(dev, ke, value, autorelease);
 		return true;
 	}
 
+	/* Report an unknown key event as a debugging aid */
+	unknown_ke.type = KE_KEY;
+	unknown_ke.code = code;
+	unknown_ke.keycode = KEY_UNKNOWN;
+	sparse_keymap_report_entry(dev, &unknown_ke, value, true);
+
 	return false;
 }
 EXPORT_SYMBOL(sparse_keymap_report_event);
diff -druN linux-libre-2.6.38-gnu/drivers/input/tablet/wacom_sys.c linux-libre-2.6.39-gnu/drivers/input/tablet/wacom_sys.c
--- linux-libre-2.6.38-gnu/drivers/input/tablet/wacom_sys.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/tablet/wacom_sys.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,16 +193,16 @@
 			case HID_USAGE_X:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						features->device_type = BTN_TOOL_DOUBLETAP;
+						features->device_type = BTN_TOOL_FINGER;
 						if (features->type == TABLETPC2FG) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 						}
 						if (features->type == BAMBOO_PT) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_BBTOUCH;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 							features->x_phy =
 								get_unaligned_le16(&report[i + 5]);
 							features->x_max =
@@ -241,11 +241,11 @@
 			case HID_USAGE_Y:
 				if (usage == WCM_DESKTOP) {
 					if (finger) {
-						features->device_type = BTN_TOOL_DOUBLETAP;
+						features->device_type = BTN_TOOL_FINGER;
 						if (features->type == TABLETPC2FG) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_TPC2FG;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 							features->y_max =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_phy =
@@ -254,7 +254,7 @@
 						} else if (features->type == BAMBOO_PT) {
 							/* need to reset back */
 							features->pktlen = WACOM_PKGLEN_BBTOUCH;
-							features->device_type = BTN_TOOL_TRIPLETAP;
+							features->device_type = BTN_TOOL_DOUBLETAP;
 							features->y_phy =
 								get_unaligned_le16(&report[i + 3]);
 							features->y_max =
diff -druN linux-libre-2.6.38-gnu/drivers/input/tablet/wacom_wac.c linux-libre-2.6.39-gnu/drivers/input/tablet/wacom_wac.c
--- linux-libre-2.6.38-gnu/drivers/input/tablet/wacom_wac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/tablet/wacom_wac.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,6 +16,14 @@
 #include "wacom.h"
 #include <linux/input/mt.h>
 
+/* resolution for penabled devices */
+#define WACOM_PL_RES		20
+#define WACOM_PENPRTN_RES	40
+#define WACOM_VOLITO_RES	50
+#define WACOM_GRAPHIRE_RES	80
+#define WACOM_INTUOS_RES	100
+#define WACOM_INTUOS3_RES	200
+
 static int wacom_penpartner_irq(struct wacom_wac *wacom)
 {
 	unsigned char *data = wacom->data;
@@ -675,169 +683,87 @@
 	return 1;
 }
 
-
-static void wacom_tpc_finger_in(struct wacom_wac *wacom, char *data, int idx)
+static int wacom_tpc_mt_touch(struct wacom_wac *wacom)
 {
 	struct input_dev *input = wacom->input;
-	int finger = idx + 1;
-	int x = le16_to_cpup((__le16 *)&data[finger * 2]) & 0x7fff;
-	int y = le16_to_cpup((__le16 *)&data[4 + finger * 2]) & 0x7fff;
+	unsigned char *data = wacom->data;
+	int contact_with_no_pen_down_count = 0;
+	int i;
 
-	/*
-	 * Work around input core suppressing "duplicate" events since
-	 * we are abusing ABS_X/ABS_Y to transmit multi-finger data.
-	 * This should go away once we switch to true multitouch
-	 * protocol.
-	 */
-	if (wacom->last_finger != finger) {
-		if (x == input_abs_get_val(input, ABS_X))
-			x++;
+	for (i = 0; i < 2; i++) {
+		int p = data[1] & (1 << i);
+		bool touch = p && !wacom->shared->stylus_in_proximity;
 
-		if (y == input_abs_get_val(input, ABS_Y))
-			y++;
-	}
+		input_mt_slot(input, i);
+		input_mt_report_slot_state(input, MT_TOOL_FINGER, touch);
+		if (touch) {
+			int x = le16_to_cpup((__le16 *)&data[i * 2 + 2]) & 0x7fff;
+			int y = le16_to_cpup((__le16 *)&data[i * 2 + 6]) & 0x7fff;
 
-	input_report_abs(input, ABS_X, x);
-	input_report_abs(input, ABS_Y, y);
-	input_report_abs(input, ABS_MISC, wacom->id[0]);
-	input_report_key(input, wacom->tool[finger], 1);
-	if (!idx)
-		input_report_key(input, BTN_TOUCH, 1);
-	input_event(input, EV_MSC, MSC_SERIAL, finger);
-	input_sync(input);
+			input_report_abs(input, ABS_MT_POSITION_X, x);
+			input_report_abs(input, ABS_MT_POSITION_Y, y);
+			contact_with_no_pen_down_count++;
+		}
+	}
 
-	wacom->last_finger = finger;
-}
+	/* keep touch state for pen event */
+	wacom->shared->touch_down = (contact_with_no_pen_down_count > 0);
 
-static void wacom_tpc_touch_out(struct wacom_wac *wacom, int idx)
-{
-	struct input_dev *input = wacom->input;
-	int finger = idx + 1;
+	input_mt_report_pointer_emulation(input, true);
 
-	input_report_abs(input, ABS_X, 0);
-	input_report_abs(input, ABS_Y, 0);
-	input_report_abs(input, ABS_MISC, 0);
-	input_report_key(input, wacom->tool[finger], 0);
-	if (!idx)
-		input_report_key(input, BTN_TOUCH, 0);
-	input_event(input, EV_MSC, MSC_SERIAL, finger);
-	input_sync(input);
+	return 1;
 }
 
-static void wacom_tpc_touch_in(struct wacom_wac *wacom, size_t len)
+static int wacom_tpc_single_touch(struct wacom_wac *wacom, size_t len)
 {
 	char *data = wacom->data;
 	struct input_dev *input = wacom->input;
+	bool prox;
+	int x = 0, y = 0;
 
-	wacom->tool[1] = BTN_TOOL_DOUBLETAP;
-	wacom->id[0] = TOUCH_DEVICE_ID;
-	wacom->tool[2] = BTN_TOOL_TRIPLETAP;
-
-	if (len != WACOM_PKGLEN_TPC1FG) {
-
-		switch (data[0]) {
+	if (!wacom->shared->stylus_in_proximity) {
+		if (len == WACOM_PKGLEN_TPC1FG) {
+			prox = data[0] & 0x01;
+			x = get_unaligned_le16(&data[1]);
+			y = get_unaligned_le16(&data[3]);
+		} else { /* with capacity */
+			prox = data[1] & 0x01;
+			x = le16_to_cpup((__le16 *)&data[2]);
+			y = le16_to_cpup((__le16 *)&data[4]);
+		}
+	} else
+		/* force touch out when pen is in prox */
+		prox = 0;
 
-		case WACOM_REPORT_TPC1FG:
-			input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
-			input_report_abs(input, ABS_Y, le16_to_cpup((__le16 *)&data[4]));
-			input_report_abs(input, ABS_PRESSURE, le16_to_cpup((__le16 *)&data[6]));
-			input_report_key(input, BTN_TOUCH, le16_to_cpup((__le16 *)&data[6]));
-			input_report_abs(input, ABS_MISC, wacom->id[0]);
-			input_report_key(input, wacom->tool[1], 1);
-			input_sync(input);
-			break;
+	if (prox) {
+		input_report_abs(input, ABS_X, x);
+		input_report_abs(input, ABS_Y, y);
+	}
+	input_report_key(input, BTN_TOUCH, prox);
 
-		case WACOM_REPORT_TPC2FG:
-			if (data[1] & 0x01)
-				wacom_tpc_finger_in(wacom, data, 0);
-			else if (wacom->id[1] & 0x01)
-				wacom_tpc_touch_out(wacom, 0);
+	/* keep touch state for pen events */
+	wacom->shared->touch_down = prox;
 
-			if (data[1] & 0x02)
-				wacom_tpc_finger_in(wacom, data, 1);
-			else if (wacom->id[1] & 0x02)
-				wacom_tpc_touch_out(wacom, 1);
-			break;
-		}
-	} else {
-		input_report_abs(input, ABS_X, get_unaligned_le16(&data[1]));
-		input_report_abs(input, ABS_Y, get_unaligned_le16(&data[3]));
-		input_report_key(input, BTN_TOUCH, 1);
-		input_report_abs(input, ABS_MISC, wacom->id[1]);
-		input_report_key(input, wacom->tool[1], 1);
-		input_sync(input);
-	}
+	return 1;
 }
 
-static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+static int wacom_tpc_pen(struct wacom_wac *wacom)
 {
 	struct wacom_features *features = &wacom->features;
 	char *data = wacom->data;
 	struct input_dev *input = wacom->input;
-	int prox = 0, pressure;
-	int retval = 0;
-
-	dbg("wacom_tpc_irq: received report #%d", data[0]);
-
-	if (len == WACOM_PKGLEN_TPC1FG ||		 /* single touch */
-	    data[0] == WACOM_REPORT_TPC1FG ||		 /* single touch */
-	    data[0] == WACOM_REPORT_TPC2FG) {		 /* 2FG touch */
-
-		if (wacom->shared->stylus_in_proximity) {
-			if (wacom->id[1] & 0x01)
-				wacom_tpc_touch_out(wacom, 0);
-
-			if (wacom->id[1] & 0x02)
-				wacom_tpc_touch_out(wacom, 1);
-
-			wacom->id[1] = 0;
-			return 0;
-		}
-
-		if (len == WACOM_PKGLEN_TPC1FG) {	/* with touch */
-			prox = data[0] & 0x01;
-		} else {  /* with capacity */
-			if (data[0] == WACOM_REPORT_TPC1FG)
-				/* single touch */
-				prox = data[1] & 0x01;
-			else
-				/* 2FG touch data */
-				prox = data[1] & 0x03;
-		}
-
-		if (prox) {
-			if (!wacom->id[1])
-				wacom->last_finger = 1;
-			wacom_tpc_touch_in(wacom, len);
-		} else {
-			if (data[0] == WACOM_REPORT_TPC2FG) {
-				/* 2FGT out-prox */
-				if (wacom->id[1] & 0x01)
-					wacom_tpc_touch_out(wacom, 0);
-
-				if (wacom->id[1] & 0x02)
-					wacom_tpc_touch_out(wacom, 1);
-			} else
-				/* one finger touch */
-				wacom_tpc_touch_out(wacom, 0);
+	int pressure;
+	bool prox = data[1] & 0x20;
 
-			wacom->id[0] = 0;
-		}
-		/* keep prox bit to send proper out-prox event */
-		wacom->id[1] = prox;
-	} else if (data[0] == WACOM_REPORT_PENABLED) { /* Penabled */
-		prox = data[1] & 0x20;
+	if (!wacom->shared->stylus_in_proximity) /* first in prox */
+		/* Going into proximity select tool */
+		wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
 
-		if (!wacom->shared->stylus_in_proximity) { /* first in prox */
-			/* Going into proximity select tool */
-			wacom->tool[0] = (data[1] & 0x0c) ? BTN_TOOL_RUBBER : BTN_TOOL_PEN;
-			if (wacom->tool[0] == BTN_TOOL_PEN)
-				wacom->id[0] = STYLUS_DEVICE_ID;
-			else
-				wacom->id[0] = ERASER_DEVICE_ID;
+	/* keep pen state for touch events */
+	wacom->shared->stylus_in_proximity = prox;
 
-			wacom->shared->stylus_in_proximity = true;
-		}
+	/* send pen events only when touch is up or forced out */
+	if (!wacom->shared->touch_down) {
 		input_report_key(input, BTN_STYLUS, data[1] & 0x02);
 		input_report_key(input, BTN_STYLUS2, data[1] & 0x10);
 		input_report_abs(input, ABS_X, le16_to_cpup((__le16 *)&data[2]));
@@ -847,15 +773,27 @@
 			pressure = features->pressure_max + pressure + 1;
 		input_report_abs(input, ABS_PRESSURE, pressure);
 		input_report_key(input, BTN_TOUCH, data[1] & 0x05);
-		if (!prox) { /* out-prox */
-			wacom->id[0] = 0;
-			wacom->shared->stylus_in_proximity = false;
-		}
 		input_report_key(input, wacom->tool[0], prox);
-		input_report_abs(input, ABS_MISC, wacom->id[0]);
-		retval = 1;
+		return 1;
 	}
-	return retval;
+
+	return 0;
+}
+
+static int wacom_tpc_irq(struct wacom_wac *wacom, size_t len)
+{
+	char *data = wacom->data;
+
+	dbg("wacom_tpc_irq: received report #%d", data[0]);
+
+	if (len == WACOM_PKGLEN_TPC1FG || data[0] == WACOM_REPORT_TPC1FG)
+		return wacom_tpc_single_touch(wacom, len);
+	else if (data[0] == WACOM_REPORT_TPC2FG)
+		return wacom_tpc_mt_touch(wacom);
+	else if (data[0] == WACOM_REPORT_PENABLED)
+		return wacom_tpc_pen(wacom);
+
+	return 0;
 }
 
 static int wacom_bpt_touch(struct wacom_wac *wacom)
@@ -1078,7 +1016,7 @@
 {
 
 	/* touch device found but size is not defined. use default */
-	if (features->device_type == BTN_TOOL_DOUBLETAP && !features->x_max) {
+	if (features->device_type == BTN_TOOL_FINGER && !features->x_max) {
 		features->x_max = 1023;
 		features->y_max = 1023;
 	}
@@ -1090,7 +1028,7 @@
 
 	/* quirks for bamboo touch */
 	if (features->type == BAMBOO_PT &&
-	    features->device_type == BTN_TOOL_TRIPLETAP) {
+	    features->device_type == BTN_TOOL_DOUBLETAP) {
 		features->x_max <<= 5;
 		features->y_max <<= 5;
 		features->x_fuzz <<= 5;
@@ -1125,6 +1063,19 @@
 	input_set_abs_params(input_dev, ABS_PRESSURE, 0, features->pressure_max,
 			     features->pressure_fuzz, 0);
 
+	if (features->device_type == BTN_TOOL_PEN) {
+		/* penabled devices have fixed resolution for each model */
+		input_abs_set_res(input_dev, ABS_X, features->x_resolution);
+		input_abs_set_res(input_dev, ABS_Y, features->y_resolution);
+	} else {
+		input_abs_set_res(input_dev, ABS_X,
+			wacom_calculate_touch_res(features->x_max,
+						features->x_phy));
+		input_abs_set_res(input_dev, ABS_Y,
+			wacom_calculate_touch_res(features->y_max,
+						features->y_phy));
+	}
+
 	__set_bit(ABS_MISC, input_dev->absbit);
 
 	switch (wacom_wac->features.type) {
@@ -1226,23 +1177,20 @@
 		break;
 
 	case TABLETPC2FG:
-		if (features->device_type == BTN_TOOL_TRIPLETAP) {
-			__set_bit(BTN_TOOL_TRIPLETAP, input_dev->keybit);
-			input_set_capability(input_dev, EV_MSC, MSC_SERIAL);
+		if (features->device_type == BTN_TOOL_DOUBLETAP) {
+
+			input_mt_init_slots(input_dev, 2);
+			input_set_abs_params(input_dev, ABS_MT_TOOL_TYPE,
+					0, MT_TOOL_MAX, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+					0, features->x_max, 0, 0);
+			input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+					0, features->y_max, 0, 0);
 		}
 		/* fall through */
 
 	case TABLETPC:
-		if (features->device_type == BTN_TOOL_DOUBLETAP ||
-		    features->device_type == BTN_TOOL_TRIPLETAP) {
-			input_abs_set_res(input_dev, ABS_X,
-				wacom_calculate_touch_res(features->x_max,
-							features->x_phy));
-			input_abs_set_res(input_dev, ABS_Y,
-				wacom_calculate_touch_res(features->y_max,
-							features->y_phy));
-			__set_bit(BTN_TOOL_DOUBLETAP, input_dev->keybit);
-		}
+		__clear_bit(ABS_MISC, input_dev->absbit);
 
 		if (features->device_type != BTN_TOOL_PEN)
 			break;  /* no need to process stylus stuff */
@@ -1264,7 +1212,7 @@
 	case BAMBOO_PT:
 		__clear_bit(ABS_MISC, input_dev->absbit);
 
-		if (features->device_type == BTN_TOOL_TRIPLETAP) {
+		if (features->device_type == BTN_TOOL_DOUBLETAP) {
 			__set_bit(BTN_LEFT, input_dev->keybit);
 			__set_bit(BTN_FORWARD, input_dev->keybit);
 			__set_bit(BTN_BACK, input_dev->keybit);
@@ -1283,12 +1231,6 @@
 			input_set_abs_params(input_dev, ABS_MT_PRESSURE,
 					     0, features->pressure_max,
 					     features->pressure_fuzz, 0);
-			input_abs_set_res(input_dev, ABS_X,
-				wacom_calculate_touch_res(features->x_max,
-							features->x_phy));
-			input_abs_set_res(input_dev, ABS_Y,
-				wacom_calculate_touch_res(features->y_max,
-							features->y_phy));
 		} else if (features->device_type == BTN_TOOL_PEN) {
 			__set_bit(BTN_TOOL_RUBBER, input_dev->keybit);
 			__set_bit(BTN_TOOL_PEN, input_dev->keybit);
@@ -1300,161 +1242,242 @@
 }
 
 static const struct wacom_features wacom_features_0x00 =
-	{ "Wacom Penpartner",     WACOM_PKGLEN_PENPRTN,    5040,  3780,  255,  0, PENPARTNER };
+	{ "Wacom Penpartner",     WACOM_PKGLEN_PENPRTN,    5040,  3780,  255,
+	  0, PENPARTNER, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
 static const struct wacom_features wacom_features_0x10 =
-	{ "Wacom Graphire",       WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE };
+	{ "Wacom Graphire",       WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511,
+	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x11 =
-	{ "Wacom Graphire2 4x5",  WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511, 63, GRAPHIRE };
+	{ "Wacom Graphire2 4x5",  WACOM_PKGLEN_GRAPHIRE,  10206,  7422,  511,
+	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x12 =
-	{ "Wacom Graphire2 5x7",  WACOM_PKGLEN_GRAPHIRE,  13918, 10206,  511, 63, GRAPHIRE };
+	{ "Wacom Graphire2 5x7",  WACOM_PKGLEN_GRAPHIRE,  13918, 10206,  511,
+	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x13 =
-	{ "Wacom Graphire3",      WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, GRAPHIRE };
+	{ "Wacom Graphire3",      WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511,
+	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x14 =
-	{ "Wacom Graphire3 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE };
+	{ "Wacom Graphire3 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511,
+	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x15 =
-	{ "Wacom Graphire4 4x5",  WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511, 63, WACOM_G4 };
+	{ "Wacom Graphire4 4x5",  WACOM_PKGLEN_GRAPHIRE,  10208,  7424,  511,
+	  63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x16 =
-	{ "Wacom Graphire4 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, WACOM_G4 };
+	{ "Wacom Graphire4 6x8",  WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511,
+	  63, WACOM_G4, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x17 =
-	{ "Wacom BambooFun 4x5",  WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO };
+	{ "Wacom BambooFun 4x5",  WACOM_PKGLEN_BBFUN,     14760,  9225,  511,
+	  63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x18 =
-	{ "Wacom BambooFun 6x8",  WACOM_PKGLEN_BBFUN,     21648, 13530,  511, 63, WACOM_MO };
+	{ "Wacom BambooFun 6x8",  WACOM_PKGLEN_BBFUN,     21648, 13530,  511,
+	  63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x19 =
-	{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511, 63, GRAPHIRE };
+	{ "Wacom Bamboo1 Medium", WACOM_PKGLEN_GRAPHIRE,  16704, 12064,  511,
+	  63, GRAPHIRE, WACOM_GRAPHIRE_RES, WACOM_GRAPHIRE_RES };
 static const struct wacom_features wacom_features_0x60 =
-	{ "Wacom Volito",         WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE };
+	{ "Wacom Volito",         WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
+	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
 static const struct wacom_features wacom_features_0x61 =
-	{ "Wacom PenStation2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  255, 63, GRAPHIRE };
+	{ "Wacom PenStation2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  255,
+	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
 static const struct wacom_features wacom_features_0x62 =
-	{ "Wacom Volito2 4x5",    WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE };
+	{ "Wacom Volito2 4x5",    WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
+	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
 static const struct wacom_features wacom_features_0x63 =
-	{ "Wacom Volito2 2x3",    WACOM_PKGLEN_GRAPHIRE,   3248,  2320,  511, 63, GRAPHIRE };
+	{ "Wacom Volito2 2x3",    WACOM_PKGLEN_GRAPHIRE,   3248,  2320,  511,
+	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
 static const struct wacom_features wacom_features_0x64 =
-	{ "Wacom PenPartner2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  511, 63, GRAPHIRE };
+	{ "Wacom PenPartner2",    WACOM_PKGLEN_GRAPHIRE,   3250,  2320,  511,
+	  63, GRAPHIRE, WACOM_VOLITO_RES, WACOM_VOLITO_RES };
 static const struct wacom_features wacom_features_0x65 =
-	{ "Wacom Bamboo",         WACOM_PKGLEN_BBFUN,     14760,  9225,  511, 63, WACOM_MO };
+	{ "Wacom Bamboo",         WACOM_PKGLEN_BBFUN,     14760,  9225,  511,
+	  63, WACOM_MO, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x69 =
-	{ "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511, 63, GRAPHIRE };
+	{ "Wacom Bamboo1",        WACOM_PKGLEN_GRAPHIRE,   5104,  3712,  511,
+	  63, GRAPHIRE, WACOM_PENPRTN_RES, WACOM_PENPRTN_RES };
 static const struct wacom_features wacom_features_0x20 =
-	{ "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS };
+	{ "Wacom Intuos 4x5",     WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x21 =
-	{ "Wacom Intuos 6x8",     WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS };
+	{ "Wacom Intuos 6x8",     WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x22 =
-	{ "Wacom Intuos 9x12",    WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS };
+	{ "Wacom Intuos 9x12",    WACOM_PKGLEN_INTUOS,    30480, 24060, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x23 =
-	{ "Wacom Intuos 12x12",   WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS };
+	{ "Wacom Intuos 12x12",   WACOM_PKGLEN_INTUOS,    30480, 31680, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x24 =
-	{ "Wacom Intuos 12x18",   WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS };
+	{ "Wacom Intuos 12x18",   WACOM_PKGLEN_INTUOS,    45720, 31680, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x30 =
-	{ "Wacom PL400",          WACOM_PKGLEN_GRAPHIRE,   5408,  4056,  255,  0, PL };
+	{ "Wacom PL400",          WACOM_PKGLEN_GRAPHIRE,   5408,  4056,  255,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x31 =
-	{ "Wacom PL500",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  255,  0, PL };
+	{ "Wacom PL500",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  255,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x32 =
-	{ "Wacom PL600",          WACOM_PKGLEN_GRAPHIRE,   6126,  4604,  255,  0, PL };
+	{ "Wacom PL600",          WACOM_PKGLEN_GRAPHIRE,   6126,  4604,  255,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x33 =
-	{ "Wacom PL600SX",        WACOM_PKGLEN_GRAPHIRE,   6260,  5016,  255,  0, PL };
+	{ "Wacom PL600SX",        WACOM_PKGLEN_GRAPHIRE,   6260,  5016,  255,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x34 =
-	{ "Wacom PL550",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  511,  0, PL };
+	{ "Wacom PL550",          WACOM_PKGLEN_GRAPHIRE,   6144,  4608,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x35 =
-	{ "Wacom PL800",          WACOM_PKGLEN_GRAPHIRE,   7220,  5780,  511,  0, PL };
+	{ "Wacom PL800",          WACOM_PKGLEN_GRAPHIRE,   7220,  5780,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x37 =
-	{ "Wacom PL700",          WACOM_PKGLEN_GRAPHIRE,   6758,  5406,  511,  0, PL };
+	{ "Wacom PL700",          WACOM_PKGLEN_GRAPHIRE,   6758,  5406,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x38 =
-	{ "Wacom PL510",          WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL };
+	{ "Wacom PL510",          WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x39 =
-	{ "Wacom DTU710",         WACOM_PKGLEN_GRAPHIRE,  34080, 27660,  511,  0, PL };
+	{ "Wacom DTU710",         WACOM_PKGLEN_GRAPHIRE,  34080, 27660,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0xC4 =
-	{ "Wacom DTF521",         WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,  0, PL };
+	{ "Wacom DTF521",         WACOM_PKGLEN_GRAPHIRE,   6282,  4762,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0xC0 =
-	{ "Wacom DTF720",         WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL };
+	{ "Wacom DTF720",         WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0xC2 =
-	{ "Wacom DTF720a",        WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,  0, PL };
+	{ "Wacom DTF720a",        WACOM_PKGLEN_GRAPHIRE,   6858,  5506,  511,
+	  0, PL, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x03 =
-	{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE,  20480, 15360,  511,  0, PTU };
+	{ "Wacom Cintiq Partner", WACOM_PKGLEN_GRAPHIRE,  20480, 15360,  511,
+	  0, PTU, WACOM_PL_RES, WACOM_PL_RES };
 static const struct wacom_features wacom_features_0x41 =
-	{ "Wacom Intuos2 4x5",    WACOM_PKGLEN_INTUOS,    12700, 10600, 1023, 31, INTUOS };
+	{ "Wacom Intuos2 4x5",    WACOM_PKGLEN_INTUOS,    12700, 10600, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x42 =
-	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS };
+	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x43 =
-	{ "Wacom Intuos2 9x12",   WACOM_PKGLEN_INTUOS,    30480, 24060, 1023, 31, INTUOS };
+	{ "Wacom Intuos2 9x12",   WACOM_PKGLEN_INTUOS,    30480, 24060, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x44 =
-	{ "Wacom Intuos2 12x12",  WACOM_PKGLEN_INTUOS,    30480, 31680, 1023, 31, INTUOS };
+	{ "Wacom Intuos2 12x12",  WACOM_PKGLEN_INTUOS,    30480, 31680, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x45 =
-	{ "Wacom Intuos2 12x18",  WACOM_PKGLEN_INTUOS,    45720, 31680, 1023, 31, INTUOS };
+	{ "Wacom Intuos2 12x18",  WACOM_PKGLEN_INTUOS,    45720, 31680, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xB0 =
-	{ "Wacom Intuos3 4x5",    WACOM_PKGLEN_INTUOS,    25400, 20320, 1023, 63, INTUOS3S };
+	{ "Wacom Intuos3 4x5",    WACOM_PKGLEN_INTUOS,    25400, 20320, 1023,
+	  63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB1 =
-	{ "Wacom Intuos3 6x8",    WACOM_PKGLEN_INTUOS,    40640, 30480, 1023, 63, INTUOS3 };
+	{ "Wacom Intuos3 6x8",    WACOM_PKGLEN_INTUOS,    40640, 30480, 1023,
+	  63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB2 =
-	{ "Wacom Intuos3 9x12",   WACOM_PKGLEN_INTUOS,    60960, 45720, 1023, 63, INTUOS3 };
+	{ "Wacom Intuos3 9x12",   WACOM_PKGLEN_INTUOS,    60960, 45720, 1023,
+	  63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB3 =
-	{ "Wacom Intuos3 12x12",  WACOM_PKGLEN_INTUOS,    60960, 60960, 1023, 63, INTUOS3L };
+	{ "Wacom Intuos3 12x12",  WACOM_PKGLEN_INTUOS,    60960, 60960, 1023,
+	  63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB4 =
-	{ "Wacom Intuos3 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 1023, 63, INTUOS3L };
+	{ "Wacom Intuos3 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 1023,
+	  63, INTUOS3L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB5 =
-	{ "Wacom Intuos3 6x11",   WACOM_PKGLEN_INTUOS,    54204, 31750, 1023, 63, INTUOS3 };
+	{ "Wacom Intuos3 6x11",   WACOM_PKGLEN_INTUOS,    54204, 31750, 1023,
+	  63, INTUOS3, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB7 =
-	{ "Wacom Intuos3 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 1023, 63, INTUOS3S };
+	{ "Wacom Intuos3 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 1023,
+	  63, INTUOS3S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB8 =
-	{ "Wacom Intuos4 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 2047, 63, INTUOS4S };
+	{ "Wacom Intuos4 4x6",    WACOM_PKGLEN_INTUOS,    31496, 19685, 2047,
+	  63, INTUOS4S, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xB9 =
-	{ "Wacom Intuos4 6x9",    WACOM_PKGLEN_INTUOS,    44704, 27940, 2047, 63, INTUOS4 };
+	{ "Wacom Intuos4 6x9",    WACOM_PKGLEN_INTUOS,    44704, 27940, 2047,
+	  63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xBA =
-	{ "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047, 63, INTUOS4L };
+	{ "Wacom Intuos4 8x13",   WACOM_PKGLEN_INTUOS,    65024, 40640, 2047,
+	  63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xBB =
-	{ "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047, 63, INTUOS4L };
+	{ "Wacom Intuos4 12x19",  WACOM_PKGLEN_INTUOS,    97536, 60960, 2047,
+	  63, INTUOS4L, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xBC =
-	{ "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40840, 25400, 2047, 63, INTUOS4 };
+	{ "Wacom Intuos4 WL",     WACOM_PKGLEN_INTUOS,    40840, 25400, 2047,
+	  63, INTUOS4, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x3F =
-	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023, 63, CINTIQ };
+	{ "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
+	  63, CINTIQ, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xC5 =
-	{ "Wacom Cintiq 20WSX",   WACOM_PKGLEN_INTUOS,    86680, 54180, 1023, 63, WACOM_BEE };
+	{ "Wacom Cintiq 20WSX",   WACOM_PKGLEN_INTUOS,    86680, 54180, 1023,
+	  63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xC6 =
-	{ "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023, 63, WACOM_BEE };
+	{ "Wacom Cintiq 12WX",    WACOM_PKGLEN_INTUOS,    53020, 33440, 1023,
+	  63, WACOM_BEE, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xC7 =
-	{ "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,  0, PL };
+	{ "Wacom DTU1931",        WACOM_PKGLEN_GRAPHIRE,  37832, 30305,  511,
+	  0, PL, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xCE =
-	{ "Wacom DTU2231",        WACOM_PKGLEN_GRAPHIRE,  47864, 27011,  511,  0, DTU };
+	{ "Wacom DTU2231",        WACOM_PKGLEN_GRAPHIRE,  47864, 27011,  511,
+	  0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xF0 =
-	{ "Wacom DTU1631",        WACOM_PKGLEN_GRAPHIRE,  34623, 19553,  511,  0, DTU };
+	{ "Wacom DTU1631",        WACOM_PKGLEN_GRAPHIRE,  34623, 19553,  511,
+	  0, DTU, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xCC =
-	{ "Wacom Cintiq 21UX2",   WACOM_PKGLEN_INTUOS,    87200, 65600, 2047, 63, WACOM_21UX2 };
+	{ "Wacom Cintiq 21UX2",   WACOM_PKGLEN_INTUOS,    87200, 65600, 2047,
+	  63, WACOM_21UX2, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x90 =
-	{ "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC };
+	{ "Wacom ISDv4 90",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
+	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x93 =
-	{ "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC };
+	{ "Wacom ISDv4 93",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
+	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x9A =
-	{ "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC };
+	{ "Wacom ISDv4 9A",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
+	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x9F =
-	{ "Wacom ISDv4 9F",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,  0, TABLETPC };
+	{ "Wacom ISDv4 9F",       WACOM_PKGLEN_GRAPHIRE,  26202, 16325,  255,
+	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xE2 =
-	{ "Wacom ISDv4 E2",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG };
+	{ "Wacom ISDv4 E2",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,
+	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xE3 =
-	{ "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,  0, TABLETPC2FG };
+	{ "Wacom ISDv4 E3",       WACOM_PKGLEN_TPC2FG,    26202, 16325,  255,
+	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xE6 =
+	{ "Wacom ISDv4 E6",       WACOM_PKGLEN_TPC2FG,    27760, 15694,  255,
+	  0, TABLETPC2FG, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x47 =
-	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023, 31, INTUOS };
-static struct wacom_features wacom_features_0xD0 =
-	{ "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xD1 =
-	{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xD2 =
-	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xD3 =
-	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023, 63, BAMBOO_PT };
+	{ "Wacom Intuos2 6x8",    WACOM_PKGLEN_INTUOS,    20320, 16240, 1023,
+	  31, INTUOS, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD0 =
+	{ "Wacom Bamboo 2FG",     WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD1 =
+	{ "Wacom Bamboo 2FG 4x5", WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD2 =
+	{ "Wacom Bamboo Craft",   WACOM_PKGLEN_BBFUN,     14720,  9200, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD3 =
+	{ "Wacom Bamboo 2FG 6x8", WACOM_PKGLEN_BBFUN,     21648, 13530, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0xD4 =
-	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xD6 =
-	{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xD7 =
-	{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720,  9200, 1023, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xD8 =
-	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023, 63, BAMBOO_PT };
-static struct wacom_features wacom_features_0xDA =
-	{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023, 63, BAMBOO_PT };
+	{ "Wacom Bamboo Pen",     WACOM_PKGLEN_BBFUN,     14720,  9200,  255,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD6 =
+	{ "Wacom BambooPT 2FG 4x5", WACOM_PKGLEN_BBFUN,   14720,  9200, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD7 =
+	{ "Wacom BambooPT 2FG Small", WACOM_PKGLEN_BBFUN, 14720,  9200, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xD8 =
+	{ "Wacom Bamboo Comic 2FG", WACOM_PKGLEN_BBFUN,   21648, 13530, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
+static const struct wacom_features wacom_features_0xDA =
+	{ "Wacom Bamboo 2FG 4x5 SE", WACOM_PKGLEN_BBFUN,  14720,  9200, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static struct wacom_features wacom_features_0xDB =
-	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13530, 1023, 63, BAMBOO_PT };
+	{ "Wacom Bamboo 2FG 6x8 SE", WACOM_PKGLEN_BBFUN,  21648, 13530, 1023,
+	  63, BAMBOO_PT, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 static const struct wacom_features wacom_features_0x6004 =
-	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800, 8000, 255, 0, TABLETPC };
+	{ "ISD-V4",               WACOM_PKGLEN_GRAPHIRE,  12800,  8000,  255,
+	  0, TABLETPC, WACOM_INTUOS_RES, WACOM_INTUOS_RES };
 
 #define USB_DEVICE_WACOM(prod)					\
 	USB_DEVICE(USB_VENDOR_ID_WACOM, prod),			\
@@ -1541,6 +1564,7 @@
 	{ USB_DEVICE_WACOM(0x9F) },
 	{ USB_DEVICE_WACOM(0xE2) },
 	{ USB_DEVICE_WACOM(0xE3) },
+	{ USB_DEVICE_WACOM(0xE6) },
 	{ USB_DEVICE_WACOM(0x47) },
 	{ USB_DEVICE_LENOVO(0x6004) },
 	{ }
diff -druN linux-libre-2.6.38-gnu/drivers/input/tablet/wacom_wac.h linux-libre-2.6.39-gnu/drivers/input/tablet/wacom_wac.h
--- linux-libre-2.6.38-gnu/drivers/input/tablet/wacom_wac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/tablet/wacom_wac.h	2011-05-19 00:06:34.000000000 -0400
@@ -74,6 +74,8 @@
 	int pressure_max;
 	int distance_max;
 	int type;
+	int x_resolution;
+	int y_resolution;
 	int device_type;
 	int x_phy;
 	int y_phy;
@@ -88,15 +90,15 @@
 
 struct wacom_shared {
 	bool stylus_in_proximity;
+	bool touch_down;
 };
 
 struct wacom_wac {
 	char name[64];
 	unsigned char *data;
-	int tool[3];
-	int id[3];
+	int tool[2];
+	int id[2];
 	__u32 serial[2];
-	int last_finger;
 	struct wacom_features features;
 	struct wacom_shared *shared;
 	struct input_dev *input;
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/ad7877.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/ad7877.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/ad7877.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/ad7877.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,6 +41,7 @@
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/interrupt.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ad7877.h>
@@ -826,39 +827,37 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int ad7877_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ad7877_suspend(struct device *dev)
 {
-	struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+	struct ad7877 *ts = dev_get_drvdata(dev);
 
 	ad7877_disable(ts);
 
 	return 0;
 }
 
-static int ad7877_resume(struct spi_device *spi)
+static int ad7877_resume(struct device *dev)
 {
-	struct ad7877 *ts = dev_get_drvdata(&spi->dev);
+	struct ad7877 *ts = dev_get_drvdata(dev);
 
 	ad7877_enable(ts);
 
 	return 0;
 }
-#else
-#define ad7877_suspend NULL
-#define ad7877_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad7877_pm, ad7877_suspend, ad7877_resume);
+
 static struct spi_driver ad7877_driver = {
 	.driver = {
 		.name	= "ad7877",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &ad7877_pm,
 	},
 	.probe		= ad7877_probe,
 	.remove		= __devexit_p(ad7877_remove),
-	.suspend	= ad7877_suspend,
-	.resume		= ad7877_resume,
 };
 
 static int __init ad7877_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/ad7879-spi.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/ad7879-spi.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/ad7879-spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/ad7879-spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,7 @@
  */
 
 #include <linux/input.h>	/* BUS_SPI */
+#include <linux/pm.h>
 #include <linux/spi/spi.h>
 
 #include "ad7879.h"
@@ -20,9 +21,10 @@
 #define AD7879_WRITECMD(reg) (AD7879_CMD(reg))
 #define AD7879_READCMD(reg)  (AD7879_CMD(reg) | AD7879_CMD_READ)
 
-#ifdef CONFIG_PM
-static int ad7879_spi_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ad7879_spi_suspend(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct ad7879 *ts = spi_get_drvdata(spi);
 
 	ad7879_suspend(ts);
@@ -30,19 +32,19 @@
 	return 0;
 }
 
-static int ad7879_spi_resume(struct spi_device *spi)
+static int ad7879_spi_resume(struct device *dev)
 {
+	struct spi_device *spi = to_spi_device(dev);
 	struct ad7879 *ts = spi_get_drvdata(spi);
 
 	ad7879_resume(ts);
 
 	return 0;
 }
-#else
-# define ad7879_spi_suspend NULL
-# define ad7879_spi_resume  NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(ad7879_spi_pm, ad7879_spi_suspend, ad7879_spi_resume);
+
 /*
  * ad7879_read/write are only used for initial setup and for sysfs controls.
  * The main traffic is done in ad7879_collect().
@@ -173,11 +175,10 @@
 		.name	= "ad7879",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &ad7879_spi_pm,
 	},
 	.probe		= ad7879_spi_probe,
 	.remove		= __devexit_p(ad7879_spi_remove),
-	.suspend	= ad7879_spi_suspend,
-	.resume		= ad7879_spi_resume,
 };
 
 static int __init ad7879_spi_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/ads7846.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/ads7846.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/ads7846.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/ads7846.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/input.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 #include <linux/gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/ads7846.h>
@@ -280,17 +281,24 @@
 	u8			command;
 	u8			ref_off;
 	u16			scratch;
-	__be16			sample;
 	struct spi_message	msg;
 	struct spi_transfer	xfer[6];
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	__be16 sample ____cacheline_aligned;
 };
 
 struct ads7845_ser_req {
 	u8			command[3];
-	u8			pwrdown[3];
-	u8			sample[3];
 	struct spi_message	msg;
 	struct spi_transfer	xfer[2];
+	/*
+	 * DMA (thus cache coherency maintenance) requires the
+	 * transfer buffers to live in their own cache lines.
+	 */
+	u8 sample[3] ____cacheline_aligned;
 };
 
 static int ads7846_read12_ser(struct device *dev, unsigned command)
@@ -892,9 +900,10 @@
 	return IRQ_HANDLED;
 }
 
-static int ads7846_suspend(struct spi_device *spi, pm_message_t message)
+#ifdef CONFIG_PM_SLEEP
+static int ads7846_suspend(struct device *dev)
 {
-	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
 
 	mutex_lock(&ts->lock);
 
@@ -914,9 +923,9 @@
 	return 0;
 }
 
-static int ads7846_resume(struct spi_device *spi)
+static int ads7846_resume(struct device *dev)
 {
-	struct ads7846 *ts = dev_get_drvdata(&spi->dev);
+	struct ads7846 *ts = dev_get_drvdata(dev);
 
 	mutex_lock(&ts->lock);
 
@@ -935,6 +944,9 @@
 
 	return 0;
 }
+#endif
+
+static SIMPLE_DEV_PM_OPS(ads7846_pm, ads7846_suspend, ads7846_resume);
 
 static int __devinit ads7846_setup_pendown(struct spi_device *spi, struct ads7846 *ts)
 {
@@ -1408,11 +1420,10 @@
 		.name	= "ads7846",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &ads7846_pm,
 	},
 	.probe		= ads7846_probe,
 	.remove		= __devexit_p(ads7846_remove),
-	.suspend	= ads7846_suspend,
-	.resume		= ads7846_resume,
 };
 
 static int __init ads7846_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/atmel_mxt_ts.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/atmel_mxt_ts.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/atmel_mxt_ts.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/atmel_mxt_ts.c	2012-03-24 03:36:03.000000000 -0400
@@ -0,0 +1,1211 @@
+/*
+ * Atmel maXTouch Touchscreen driver
+ *
+ * Copyright (C) 2010 Samsung Electronics Co.Ltd
+ * Author: Joonyoung Shim <jy0922.shim@samsung.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/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/i2c.h>
+#include <linux/i2c/atmel_mxt_ts.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+
+/* Version */
+#define MXT_VER_20		20
+#define MXT_VER_21		21
+#define MXT_VER_22		22
+
+/* Slave addresses */
+#define MXT_APP_LOW		0x4a
+#define MXT_APP_HIGH		0x4b
+#define MXT_BOOT_LOW		0x24
+#define MXT_BOOT_HIGH		0x25
+
+/* Firmware */
+#define MXT_FW_NAME		"/*(DEBLOBBED)*/"
+
+/* Registers */
+#define MXT_FAMILY_ID		0x00
+#define MXT_VARIANT_ID		0x01
+#define MXT_VERSION		0x02
+#define MXT_BUILD		0x03
+#define MXT_MATRIX_X_SIZE	0x04
+#define MXT_MATRIX_Y_SIZE	0x05
+#define MXT_OBJECT_NUM		0x06
+#define MXT_OBJECT_START	0x07
+
+#define MXT_OBJECT_SIZE		6
+
+/* Object types */
+#define MXT_DEBUG_DIAGNOSTIC	37
+#define MXT_GEN_MESSAGE		5
+#define MXT_GEN_COMMAND		6
+#define MXT_GEN_POWER		7
+#define MXT_GEN_ACQUIRE		8
+#define MXT_TOUCH_MULTI		9
+#define MXT_TOUCH_KEYARRAY	15
+#define MXT_TOUCH_PROXIMITY	23
+#define MXT_PROCI_GRIPFACE	20
+#define MXT_PROCG_NOISE		22
+#define MXT_PROCI_ONETOUCH	24
+#define MXT_PROCI_TWOTOUCH	27
+#define MXT_PROCI_GRIP		40
+#define MXT_PROCI_PALM		41
+#define MXT_SPT_COMMSCONFIG	18
+#define MXT_SPT_GPIOPWM		19
+#define MXT_SPT_SELFTEST	25
+#define MXT_SPT_CTECONFIG	28
+#define MXT_SPT_USERDATA	38
+#define MXT_SPT_DIGITIZER	43
+#define MXT_SPT_MESSAGECOUNT	44
+
+/* MXT_GEN_COMMAND field */
+#define MXT_COMMAND_RESET	0
+#define MXT_COMMAND_BACKUPNV	1
+#define MXT_COMMAND_CALIBRATE	2
+#define MXT_COMMAND_REPORTALL	3
+#define MXT_COMMAND_DIAGNOSTIC	5
+
+/* MXT_GEN_POWER field */
+#define MXT_POWER_IDLEACQINT	0
+#define MXT_POWER_ACTVACQINT	1
+#define MXT_POWER_ACTV2IDLETO	2
+
+/* MXT_GEN_ACQUIRE field */
+#define MXT_ACQUIRE_CHRGTIME	0
+#define MXT_ACQUIRE_TCHDRIFT	2
+#define MXT_ACQUIRE_DRIFTST	3
+#define MXT_ACQUIRE_TCHAUTOCAL	4
+#define MXT_ACQUIRE_SYNC	5
+#define MXT_ACQUIRE_ATCHCALST	6
+#define MXT_ACQUIRE_ATCHCALSTHR	7
+
+/* MXT_TOUCH_MULTI field */
+#define MXT_TOUCH_CTRL		0
+#define MXT_TOUCH_XORIGIN	1
+#define MXT_TOUCH_YORIGIN	2
+#define MXT_TOUCH_XSIZE		3
+#define MXT_TOUCH_YSIZE		4
+#define MXT_TOUCH_BLEN		6
+#define MXT_TOUCH_TCHTHR	7
+#define MXT_TOUCH_TCHDI		8
+#define MXT_TOUCH_ORIENT	9
+#define MXT_TOUCH_MOVHYSTI	11
+#define MXT_TOUCH_MOVHYSTN	12
+#define MXT_TOUCH_NUMTOUCH	14
+#define MXT_TOUCH_MRGHYST	15
+#define MXT_TOUCH_MRGTHR	16
+#define MXT_TOUCH_AMPHYST	17
+#define MXT_TOUCH_XRANGE_LSB	18
+#define MXT_TOUCH_XRANGE_MSB	19
+#define MXT_TOUCH_YRANGE_LSB	20
+#define MXT_TOUCH_YRANGE_MSB	21
+#define MXT_TOUCH_XLOCLIP	22
+#define MXT_TOUCH_XHICLIP	23
+#define MXT_TOUCH_YLOCLIP	24
+#define MXT_TOUCH_YHICLIP	25
+#define MXT_TOUCH_XEDGECTRL	26
+#define MXT_TOUCH_XEDGEDIST	27
+#define MXT_TOUCH_YEDGECTRL	28
+#define MXT_TOUCH_YEDGEDIST	29
+#define MXT_TOUCH_JUMPLIMIT	30
+
+/* MXT_PROCI_GRIPFACE field */
+#define MXT_GRIPFACE_CTRL	0
+#define MXT_GRIPFACE_XLOGRIP	1
+#define MXT_GRIPFACE_XHIGRIP	2
+#define MXT_GRIPFACE_YLOGRIP	3
+#define MXT_GRIPFACE_YHIGRIP	4
+#define MXT_GRIPFACE_MAXTCHS	5
+#define MXT_GRIPFACE_SZTHR1	7
+#define MXT_GRIPFACE_SZTHR2	8
+#define MXT_GRIPFACE_SHPTHR1	9
+#define MXT_GRIPFACE_SHPTHR2	10
+#define MXT_GRIPFACE_SUPEXTTO	11
+
+/* MXT_PROCI_NOISE field */
+#define MXT_NOISE_CTRL		0
+#define MXT_NOISE_OUTFLEN	1
+#define MXT_NOISE_GCAFUL_LSB	3
+#define MXT_NOISE_GCAFUL_MSB	4
+#define MXT_NOISE_GCAFLL_LSB	5
+#define MXT_NOISE_GCAFLL_MSB	6
+#define MXT_NOISE_ACTVGCAFVALID	7
+#define MXT_NOISE_NOISETHR	8
+#define MXT_NOISE_FREQHOPSCALE	10
+#define MXT_NOISE_FREQ0		11
+#define MXT_NOISE_FREQ1		12
+#define MXT_NOISE_FREQ2		13
+#define MXT_NOISE_FREQ3		14
+#define MXT_NOISE_FREQ4		15
+#define MXT_NOISE_IDLEGCAFVALID	16
+
+/* MXT_SPT_COMMSCONFIG */
+#define MXT_COMMS_CTRL		0
+#define MXT_COMMS_CMD		1
+
+/* MXT_SPT_CTECONFIG field */
+#define MXT_CTE_CTRL		0
+#define MXT_CTE_CMD		1
+#define MXT_CTE_MODE		2
+#define MXT_CTE_IDLEGCAFDEPTH	3
+#define MXT_CTE_ACTVGCAFDEPTH	4
+#define MXT_CTE_VOLTAGE		5
+
+#define MXT_VOLTAGE_DEFAULT	2700000
+#define MXT_VOLTAGE_STEP	10000
+
+/* Define for MXT_GEN_COMMAND */
+#define MXT_BOOT_VALUE		0xa5
+#define MXT_BACKUP_VALUE	0x55
+#define MXT_BACKUP_TIME		25	/* msec */
+#define MXT_RESET_TIME		65	/* msec */
+
+#define MXT_FWRESET_TIME	175	/* msec */
+
+/* Command to unlock bootloader */
+#define MXT_UNLOCK_CMD_MSB	0xaa
+#define MXT_UNLOCK_CMD_LSB	0xdc
+
+/* Bootloader mode status */
+#define MXT_WAITING_BOOTLOAD_CMD	0xc0	/* valid 7 6 bit only */
+#define MXT_WAITING_FRAME_DATA	0x80	/* valid 7 6 bit only */
+#define MXT_FRAME_CRC_CHECK	0x02
+#define MXT_FRAME_CRC_FAIL	0x03
+#define MXT_FRAME_CRC_PASS	0x04
+#define MXT_APP_CRC_FAIL	0x40	/* valid 7 8 bit only */
+#define MXT_BOOT_STATUS_MASK	0x3f
+
+/* Touch status */
+#define MXT_SUPPRESS		(1 << 1)
+#define MXT_AMP			(1 << 2)
+#define MXT_VECTOR		(1 << 3)
+#define MXT_MOVE		(1 << 4)
+#define MXT_RELEASE		(1 << 5)
+#define MXT_PRESS		(1 << 6)
+#define MXT_DETECT		(1 << 7)
+
+/* Touchscreen absolute values */
+#define MXT_MAX_XC		0x3ff
+#define MXT_MAX_YC		0x3ff
+#define MXT_MAX_AREA		0xff
+
+#define MXT_MAX_FINGER		10
+
+struct mxt_info {
+	u8 family_id;
+	u8 variant_id;
+	u8 version;
+	u8 build;
+	u8 matrix_xsize;
+	u8 matrix_ysize;
+	u8 object_num;
+};
+
+struct mxt_object {
+	u8 type;
+	u16 start_address;
+	u8 size;
+	u8 instances;
+	u8 num_report_ids;
+
+	/* to map object and message */
+	u8 max_reportid;
+};
+
+struct mxt_message {
+	u8 reportid;
+	u8 message[7];
+	u8 checksum;
+};
+
+struct mxt_finger {
+	int status;
+	int x;
+	int y;
+	int area;
+};
+
+/* Each client has this additional data */
+struct mxt_data {
+	struct i2c_client *client;
+	struct input_dev *input_dev;
+	const struct mxt_platform_data *pdata;
+	struct mxt_object *object_table;
+	struct mxt_info info;
+	struct mxt_finger finger[MXT_MAX_FINGER];
+	unsigned int irq;
+};
+
+static bool mxt_object_readable(unsigned int type)
+{
+	switch (type) {
+	case MXT_GEN_MESSAGE:
+	case MXT_GEN_COMMAND:
+	case MXT_GEN_POWER:
+	case MXT_GEN_ACQUIRE:
+	case MXT_TOUCH_MULTI:
+	case MXT_TOUCH_KEYARRAY:
+	case MXT_TOUCH_PROXIMITY:
+	case MXT_PROCI_GRIPFACE:
+	case MXT_PROCG_NOISE:
+	case MXT_PROCI_ONETOUCH:
+	case MXT_PROCI_TWOTOUCH:
+	case MXT_PROCI_GRIP:
+	case MXT_PROCI_PALM:
+	case MXT_SPT_COMMSCONFIG:
+	case MXT_SPT_GPIOPWM:
+	case MXT_SPT_SELFTEST:
+	case MXT_SPT_CTECONFIG:
+	case MXT_SPT_USERDATA:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool mxt_object_writable(unsigned int type)
+{
+	switch (type) {
+	case MXT_GEN_COMMAND:
+	case MXT_GEN_POWER:
+	case MXT_GEN_ACQUIRE:
+	case MXT_TOUCH_MULTI:
+	case MXT_TOUCH_KEYARRAY:
+	case MXT_TOUCH_PROXIMITY:
+	case MXT_PROCI_GRIPFACE:
+	case MXT_PROCG_NOISE:
+	case MXT_PROCI_ONETOUCH:
+	case MXT_PROCI_TWOTOUCH:
+	case MXT_PROCI_GRIP:
+	case MXT_PROCI_PALM:
+	case MXT_SPT_GPIOPWM:
+	case MXT_SPT_SELFTEST:
+	case MXT_SPT_CTECONFIG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void mxt_dump_message(struct device *dev,
+				  struct mxt_message *message)
+{
+	dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
+	dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
+	dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
+	dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
+	dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
+	dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
+	dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
+	dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
+	dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
+}
+
+static int mxt_check_bootloader(struct i2c_client *client,
+				     unsigned int state)
+{
+	u8 val;
+
+recheck:
+	if (i2c_master_recv(client, &val, 1) != 1) {
+		dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
+		return -EIO;
+	}
+
+	switch (state) {
+	case MXT_WAITING_BOOTLOAD_CMD:
+	case MXT_WAITING_FRAME_DATA:
+		val &= ~MXT_BOOT_STATUS_MASK;
+		break;
+	case MXT_FRAME_CRC_PASS:
+		if (val == MXT_FRAME_CRC_CHECK)
+			goto recheck;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	if (val != state) {
+		dev_err(&client->dev, "Unvalid bootloader mode state\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int mxt_unlock_bootloader(struct i2c_client *client)
+{
+	u8 buf[2];
+
+	buf[0] = MXT_UNLOCK_CMD_LSB;
+	buf[1] = MXT_UNLOCK_CMD_MSB;
+
+	if (i2c_master_send(client, buf, 2) != 2) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mxt_fw_write(struct i2c_client *client,
+			     const u8 *data, unsigned int frame_size)
+{
+	if (i2c_master_send(client, data, frame_size) != frame_size) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int __mxt_read_reg(struct i2c_client *client,
+			       u16 reg, u16 len, void *val)
+{
+	struct i2c_msg xfer[2];
+	u8 buf[2];
+
+	buf[0] = reg & 0xff;
+	buf[1] = (reg >> 8) & 0xff;
+
+	/* Write register */
+	xfer[0].addr = client->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 2;
+	xfer[0].buf = buf;
+
+	/* Read data */
+	xfer[1].addr = client->addr;
+	xfer[1].flags = I2C_M_RD;
+	xfer[1].len = len;
+	xfer[1].buf = val;
+
+	if (i2c_transfer(client->adapter, xfer, 2) != 2) {
+		dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mxt_read_reg(struct i2c_client *client, u16 reg, u8 *val)
+{
+	return __mxt_read_reg(client, reg, 1, val);
+}
+
+static int mxt_write_reg(struct i2c_client *client, u16 reg, u8 val)
+{
+	u8 buf[3];
+
+	buf[0] = reg & 0xff;
+	buf[1] = (reg >> 8) & 0xff;
+	buf[2] = val;
+
+	if (i2c_master_send(client, buf, 3) != 3) {
+		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mxt_read_object_table(struct i2c_client *client,
+				      u16 reg, u8 *object_buf)
+{
+	return __mxt_read_reg(client, reg, MXT_OBJECT_SIZE,
+				   object_buf);
+}
+
+static struct mxt_object *
+mxt_get_object(struct mxt_data *data, u8 type)
+{
+	struct mxt_object *object;
+	int i;
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+		if (object->type == type)
+			return object;
+	}
+
+	dev_err(&data->client->dev, "Invalid object type\n");
+	return NULL;
+}
+
+static int mxt_read_message(struct mxt_data *data,
+				 struct mxt_message *message)
+{
+	struct mxt_object *object;
+	u16 reg;
+
+	object = mxt_get_object(data, MXT_GEN_MESSAGE);
+	if (!object)
+		return -EINVAL;
+
+	reg = object->start_address;
+	return __mxt_read_reg(data->client, reg,
+			sizeof(struct mxt_message), message);
+}
+
+static int mxt_read_object(struct mxt_data *data,
+				u8 type, u8 offset, u8 *val)
+{
+	struct mxt_object *object;
+	u16 reg;
+
+	object = mxt_get_object(data, type);
+	if (!object)
+		return -EINVAL;
+
+	reg = object->start_address;
+	return __mxt_read_reg(data->client, reg + offset, 1, val);
+}
+
+static int mxt_write_object(struct mxt_data *data,
+				 u8 type, u8 offset, u8 val)
+{
+	struct mxt_object *object;
+	u16 reg;
+
+	object = mxt_get_object(data, type);
+	if (!object)
+		return -EINVAL;
+
+	reg = object->start_address;
+	return mxt_write_reg(data->client, reg + offset, val);
+}
+
+static void mxt_input_report(struct mxt_data *data, int single_id)
+{
+	struct mxt_finger *finger = data->finger;
+	struct input_dev *input_dev = data->input_dev;
+	int status = finger[single_id].status;
+	int finger_num = 0;
+	int id;
+
+	for (id = 0; id < MXT_MAX_FINGER; id++) {
+		if (!finger[id].status)
+			continue;
+
+		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
+				finger[id].status != MXT_RELEASE ?
+				finger[id].area : 0);
+		input_report_abs(input_dev, ABS_MT_POSITION_X,
+				finger[id].x);
+		input_report_abs(input_dev, ABS_MT_POSITION_Y,
+				finger[id].y);
+		input_mt_sync(input_dev);
+
+		if (finger[id].status == MXT_RELEASE)
+			finger[id].status = 0;
+		else
+			finger_num++;
+	}
+
+	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
+
+	if (status != MXT_RELEASE) {
+		input_report_abs(input_dev, ABS_X, finger[single_id].x);
+		input_report_abs(input_dev, ABS_Y, finger[single_id].y);
+	}
+
+	input_sync(input_dev);
+}
+
+static void mxt_input_touchevent(struct mxt_data *data,
+				      struct mxt_message *message, int id)
+{
+	struct mxt_finger *finger = data->finger;
+	struct device *dev = &data->client->dev;
+	u8 status = message->message[0];
+	int x;
+	int y;
+	int area;
+
+	/* Check the touch is present on the screen */
+	if (!(status & MXT_DETECT)) {
+		if (status & MXT_RELEASE) {
+			dev_dbg(dev, "[%d] released\n", id);
+
+			finger[id].status = MXT_RELEASE;
+			mxt_input_report(data, id);
+		}
+		return;
+	}
+
+	/* Check only AMP detection */
+	if (!(status & (MXT_PRESS | MXT_MOVE)))
+		return;
+
+	x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
+	y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
+	area = message->message[4];
+
+	dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
+		status & MXT_MOVE ? "moved" : "pressed",
+		x, y, area);
+
+	finger[id].status = status & MXT_MOVE ?
+				MXT_MOVE : MXT_PRESS;
+	finger[id].x = x;
+	finger[id].y = y;
+	finger[id].area = area;
+
+	mxt_input_report(data, id);
+}
+
+static irqreturn_t mxt_interrupt(int irq, void *dev_id)
+{
+	struct mxt_data *data = dev_id;
+	struct mxt_message message;
+	struct mxt_object *object;
+	struct device *dev = &data->client->dev;
+	int id;
+	u8 reportid;
+	u8 max_reportid;
+	u8 min_reportid;
+
+	do {
+		if (mxt_read_message(data, &message)) {
+			dev_err(dev, "Failed to read message\n");
+			goto end;
+		}
+
+		reportid = message.reportid;
+
+		/* whether reportid is thing of MXT_TOUCH_MULTI */
+		object = mxt_get_object(data, MXT_TOUCH_MULTI);
+		if (!object)
+			goto end;
+
+		max_reportid = object->max_reportid;
+		min_reportid = max_reportid - object->num_report_ids + 1;
+		id = reportid - min_reportid;
+
+		if (reportid >= min_reportid && reportid <= max_reportid)
+			mxt_input_touchevent(data, &message, id);
+		else
+			mxt_dump_message(dev, &message);
+	} while (reportid != 0xff);
+
+end:
+	return IRQ_HANDLED;
+}
+
+static int mxt_check_reg_init(struct mxt_data *data)
+{
+	const struct mxt_platform_data *pdata = data->pdata;
+	struct mxt_object *object;
+	struct device *dev = &data->client->dev;
+	int index = 0;
+	int i, j, config_offset;
+
+	if (!pdata->config) {
+		dev_dbg(dev, "No cfg data defined, skipping reg init\n");
+		return 0;
+	}
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+
+		if (!mxt_object_writable(object->type))
+			continue;
+
+		for (j = 0; j < object->size + 1; j++) {
+			config_offset = index + j;
+			if (config_offset > pdata->config_length) {
+				dev_err(dev, "Not enough config data!\n");
+				return -EINVAL;
+			}
+			mxt_write_object(data, object->type, j,
+					 pdata->config[config_offset]);
+		}
+		index += object->size + 1;
+	}
+
+	return 0;
+}
+
+static int mxt_make_highchg(struct mxt_data *data)
+{
+	struct device *dev = &data->client->dev;
+	struct mxt_message message;
+	int count = 10;
+	int error;
+
+	/* Read dummy message to make high CHG pin */
+	do {
+		error = mxt_read_message(data, &message);
+		if (error)
+			return error;
+	} while (message.reportid != 0xff && --count);
+
+	if (!count) {
+		dev_err(dev, "CHG pin isn't cleared\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+static void mxt_handle_pdata(struct mxt_data *data)
+{
+	const struct mxt_platform_data *pdata = data->pdata;
+	u8 voltage;
+
+	/* Set touchscreen lines */
+	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_XSIZE,
+			pdata->x_line);
+	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_YSIZE,
+			pdata->y_line);
+
+	/* Set touchscreen orient */
+	mxt_write_object(data, MXT_TOUCH_MULTI, MXT_TOUCH_ORIENT,
+			pdata->orient);
+
+	/* Set touchscreen burst length */
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_BLEN, pdata->blen);
+
+	/* Set touchscreen threshold */
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_TCHTHR, pdata->threshold);
+
+	/* Set touchscreen resolution */
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
+	mxt_write_object(data, MXT_TOUCH_MULTI,
+			MXT_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
+
+	/* Set touchscreen voltage */
+	if (pdata->voltage) {
+		if (pdata->voltage < MXT_VOLTAGE_DEFAULT) {
+			voltage = (MXT_VOLTAGE_DEFAULT - pdata->voltage) /
+				MXT_VOLTAGE_STEP;
+			voltage = 0xff - voltage + 1;
+		} else
+			voltage = (pdata->voltage - MXT_VOLTAGE_DEFAULT) /
+				MXT_VOLTAGE_STEP;
+
+		mxt_write_object(data, MXT_SPT_CTECONFIG,
+				MXT_CTE_VOLTAGE, voltage);
+	}
+}
+
+static int mxt_get_info(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct mxt_info *info = &data->info;
+	int error;
+	u8 val;
+
+	error = mxt_read_reg(client, MXT_FAMILY_ID, &val);
+	if (error)
+		return error;
+	info->family_id = val;
+
+	error = mxt_read_reg(client, MXT_VARIANT_ID, &val);
+	if (error)
+		return error;
+	info->variant_id = val;
+
+	error = mxt_read_reg(client, MXT_VERSION, &val);
+	if (error)
+		return error;
+	info->version = val;
+
+	error = mxt_read_reg(client, MXT_BUILD, &val);
+	if (error)
+		return error;
+	info->build = val;
+
+	error = mxt_read_reg(client, MXT_OBJECT_NUM, &val);
+	if (error)
+		return error;
+	info->object_num = val;
+
+	return 0;
+}
+
+static int mxt_get_object_table(struct mxt_data *data)
+{
+	int error;
+	int i;
+	u16 reg;
+	u8 reportid = 0;
+	u8 buf[MXT_OBJECT_SIZE];
+
+	for (i = 0; i < data->info.object_num; i++) {
+		struct mxt_object *object = data->object_table + i;
+
+		reg = MXT_OBJECT_START + MXT_OBJECT_SIZE * i;
+		error = mxt_read_object_table(data->client, reg, buf);
+		if (error)
+			return error;
+
+		object->type = buf[0];
+		object->start_address = (buf[2] << 8) | buf[1];
+		object->size = buf[3];
+		object->instances = buf[4];
+		object->num_report_ids = buf[5];
+
+		if (object->num_report_ids) {
+			reportid += object->num_report_ids *
+					(object->instances + 1);
+			object->max_reportid = reportid;
+		}
+	}
+
+	return 0;
+}
+
+static int mxt_initialize(struct mxt_data *data)
+{
+	struct i2c_client *client = data->client;
+	struct mxt_info *info = &data->info;
+	int error;
+	u8 val;
+
+	error = mxt_get_info(data);
+	if (error)
+		return error;
+
+	data->object_table = kcalloc(info->object_num,
+				     sizeof(struct mxt_object),
+				     GFP_KERNEL);
+	if (!data->object_table) {
+		dev_err(&client->dev, "Failed to allocate memory\n");
+		return -ENOMEM;
+	}
+
+	/* Get object table information */
+	error = mxt_get_object_table(data);
+	if (error)
+		return error;
+
+	/* Check register init values */
+	error = mxt_check_reg_init(data);
+	if (error)
+		return error;
+
+	error = mxt_make_highchg(data);
+	if (error)
+		return error;
+
+	mxt_handle_pdata(data);
+
+	/* Backup to memory */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_BACKUPNV,
+			MXT_BACKUP_VALUE);
+	msleep(MXT_BACKUP_TIME);
+
+	/* Soft reset */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_RESET, 1);
+	msleep(MXT_RESET_TIME);
+
+	/* Update matrix size at info struct */
+	error = mxt_read_reg(client, MXT_MATRIX_X_SIZE, &val);
+	if (error)
+		return error;
+	info->matrix_xsize = val;
+
+	error = mxt_read_reg(client, MXT_MATRIX_Y_SIZE, &val);
+	if (error)
+		return error;
+	info->matrix_ysize = val;
+
+	dev_info(&client->dev,
+			"Family ID: %d Variant ID: %d Version: %d Build: %d\n",
+			info->family_id, info->variant_id, info->version,
+			info->build);
+
+	dev_info(&client->dev,
+			"Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
+			info->matrix_xsize, info->matrix_ysize,
+			info->object_num);
+
+	return 0;
+}
+
+static ssize_t mxt_object_show(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct mxt_object *object;
+	int count = 0;
+	int i, j;
+	int error;
+	u8 val;
+
+	for (i = 0; i < data->info.object_num; i++) {
+		object = data->object_table + i;
+
+		count += sprintf(buf + count,
+				"Object Table Element %d(Type %d)\n",
+				i + 1, object->type);
+
+		if (!mxt_object_readable(object->type)) {
+			count += sprintf(buf + count, "\n");
+			continue;
+		}
+
+		for (j = 0; j < object->size + 1; j++) {
+			error = mxt_read_object(data,
+						object->type, j, &val);
+			if (error)
+				return error;
+
+			count += sprintf(buf + count,
+					"  Byte %d: 0x%x (%d)\n", j, val, val);
+		}
+
+		count += sprintf(buf + count, "\n");
+	}
+
+	return count;
+}
+
+static int mxt_load_fw(struct device *dev, const char *fn)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	struct i2c_client *client = data->client;
+	const struct firmware *fw = NULL;
+	unsigned int frame_size;
+	unsigned int pos = 0;
+	int ret;
+
+	ret = reject_firmware(&fw, fn, dev);
+	if (ret) {
+		dev_err(dev, "Unable to open firmware %s\n", fn);
+		return ret;
+	}
+
+	/* Change to the bootloader mode */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_RESET, MXT_BOOT_VALUE);
+	msleep(MXT_RESET_TIME);
+
+	/* Change to slave address of bootloader */
+	if (client->addr == MXT_APP_LOW)
+		client->addr = MXT_BOOT_LOW;
+	else
+		client->addr = MXT_BOOT_HIGH;
+
+	ret = mxt_check_bootloader(client, MXT_WAITING_BOOTLOAD_CMD);
+	if (ret)
+		goto out;
+
+	/* Unlock bootloader */
+	mxt_unlock_bootloader(client);
+
+	while (pos < fw->size) {
+		ret = mxt_check_bootloader(client,
+						MXT_WAITING_FRAME_DATA);
+		if (ret)
+			goto out;
+
+		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
+
+		/* We should add 2 at frame size as the the firmware data is not
+		 * included the CRC bytes.
+		 */
+		frame_size += 2;
+
+		/* Write one frame to device */
+		mxt_fw_write(client, fw->data + pos, frame_size);
+
+		ret = mxt_check_bootloader(client,
+						MXT_FRAME_CRC_PASS);
+		if (ret)
+			goto out;
+
+		pos += frame_size;
+
+		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
+	}
+
+out:
+	release_firmware(fw);
+
+	/* Change to slave address of application */
+	if (client->addr == MXT_BOOT_LOW)
+		client->addr = MXT_APP_LOW;
+	else
+		client->addr = MXT_APP_HIGH;
+
+	return ret;
+}
+
+static ssize_t mxt_update_fw_store(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct mxt_data *data = dev_get_drvdata(dev);
+	int error;
+
+	disable_irq(data->irq);
+
+	error = mxt_load_fw(dev, MXT_FW_NAME);
+	if (error) {
+		dev_err(dev, "The firmware update failed(%d)\n", error);
+		count = error;
+	} else {
+		dev_dbg(dev, "The firmware update succeeded\n");
+
+		/* Wait for reset */
+		msleep(MXT_FWRESET_TIME);
+
+		kfree(data->object_table);
+		data->object_table = NULL;
+
+		mxt_initialize(data);
+	}
+
+	enable_irq(data->irq);
+
+	return count;
+}
+
+static DEVICE_ATTR(object, 0444, mxt_object_show, NULL);
+static DEVICE_ATTR(update_fw, 0664, NULL, mxt_update_fw_store);
+
+static struct attribute *mxt_attrs[] = {
+	&dev_attr_object.attr,
+	&dev_attr_update_fw.attr,
+	NULL
+};
+
+static const struct attribute_group mxt_attr_group = {
+	.attrs = mxt_attrs,
+};
+
+static void mxt_start(struct mxt_data *data)
+{
+	/* Touch enable */
+	mxt_write_object(data,
+			MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0x83);
+}
+
+static void mxt_stop(struct mxt_data *data)
+{
+	/* Touch disable */
+	mxt_write_object(data,
+			MXT_TOUCH_MULTI, MXT_TOUCH_CTRL, 0);
+}
+
+static int mxt_input_open(struct input_dev *dev)
+{
+	struct mxt_data *data = input_get_drvdata(dev);
+
+	mxt_start(data);
+
+	return 0;
+}
+
+static void mxt_input_close(struct input_dev *dev)
+{
+	struct mxt_data *data = input_get_drvdata(dev);
+
+	mxt_stop(data);
+}
+
+static int __devinit mxt_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+	const struct mxt_platform_data *pdata = client->dev.platform_data;
+	struct mxt_data *data;
+	struct input_dev *input_dev;
+	int error;
+
+	if (!pdata)
+		return -EINVAL;
+
+	data = kzalloc(sizeof(struct mxt_data), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!data || !input_dev) {
+		dev_err(&client->dev, "Failed to allocate memory\n");
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	input_dev->name = "Atmel maXTouch Touchscreen";
+	input_dev->id.bustype = BUS_I2C;
+	input_dev->dev.parent = &client->dev;
+	input_dev->open = mxt_input_open;
+	input_dev->close = mxt_input_close;
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+
+	/* For single touch */
+	input_set_abs_params(input_dev, ABS_X,
+			     0, MXT_MAX_XC, 0, 0);
+	input_set_abs_params(input_dev, ABS_Y,
+			     0, MXT_MAX_YC, 0, 0);
+
+	/* For multi touch */
+	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
+			     0, MXT_MAX_AREA, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
+			     0, MXT_MAX_XC, 0, 0);
+	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
+			     0, MXT_MAX_YC, 0, 0);
+
+	input_set_drvdata(input_dev, data);
+
+	data->client = client;
+	data->input_dev = input_dev;
+	data->pdata = pdata;
+	data->irq = client->irq;
+
+	i2c_set_clientdata(client, data);
+
+	error = mxt_initialize(data);
+	if (error)
+		goto err_free_object;
+
+	error = request_threaded_irq(client->irq, NULL, mxt_interrupt,
+			pdata->irqflags, client->dev.driver->name, data);
+	if (error) {
+		dev_err(&client->dev, "Failed to register interrupt\n");
+		goto err_free_object;
+	}
+
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_free_irq;
+
+	error = sysfs_create_group(&client->dev.kobj, &mxt_attr_group);
+	if (error)
+		goto err_unregister_device;
+
+	return 0;
+
+err_unregister_device:
+	input_unregister_device(input_dev);
+	input_dev = NULL;
+err_free_irq:
+	free_irq(client->irq, data);
+err_free_object:
+	kfree(data->object_table);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(data);
+	return error;
+}
+
+static int __devexit mxt_remove(struct i2c_client *client)
+{
+	struct mxt_data *data = i2c_get_clientdata(client);
+
+	sysfs_remove_group(&client->dev.kobj, &mxt_attr_group);
+	free_irq(data->irq, data);
+	input_unregister_device(data->input_dev);
+	kfree(data->object_table);
+	kfree(data);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxt_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mxt_data *data = i2c_get_clientdata(client);
+	struct input_dev *input_dev = data->input_dev;
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		mxt_stop(data);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
+static int mxt_resume(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct mxt_data *data = i2c_get_clientdata(client);
+	struct input_dev *input_dev = data->input_dev;
+
+	/* Soft reset */
+	mxt_write_object(data, MXT_GEN_COMMAND,
+			MXT_COMMAND_RESET, 1);
+
+	msleep(MXT_RESET_TIME);
+
+	mutex_lock(&input_dev->mutex);
+
+	if (input_dev->users)
+		mxt_start(data);
+
+	mutex_unlock(&input_dev->mutex);
+
+	return 0;
+}
+
+static const struct dev_pm_ops mxt_pm_ops = {
+	.suspend	= mxt_suspend,
+	.resume		= mxt_resume,
+};
+#endif
+
+static const struct i2c_device_id mxt_id[] = {
+	{ "qt602240_ts", 0 },
+	{ "atmel_mxt_ts", 0 },
+	{ "mXT224", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, mxt_id);
+
+static struct i2c_driver mxt_driver = {
+	.driver = {
+		.name	= "atmel_mxt_ts",
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &mxt_pm_ops,
+#endif
+	},
+	.probe		= mxt_probe,
+	.remove		= __devexit_p(mxt_remove),
+	.id_table	= mxt_id,
+};
+
+static int __init mxt_init(void)
+{
+	return i2c_add_driver(&mxt_driver);
+}
+
+static void __exit mxt_exit(void)
+{
+	i2c_del_driver(&mxt_driver);
+}
+
+module_init(mxt_init);
+module_exit(mxt_exit);
+
+/* Module information */
+MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
+MODULE_DESCRIPTION("Atmel maXTouch Touchscreen driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/h3600_ts_input.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/h3600_ts_input.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/h3600_ts_input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/h3600_ts_input.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
         Programmer has no control over these numbers.
         TODO there are holes - specifically  1,7,0x0a
 */
-#define VERSION_ID              0       /* Get Version (request/respose) */
+#define VERSION_ID              0       /* Get Version (request/response) */
 #define KEYBD_ID                2       /* Keyboard (event) */
 #define TOUCHS_ID               3       /* Touch Screen (event)*/
 #define EEPROM_READ_ID          4       /* (request/response) */
@@ -399,31 +399,34 @@
 			IRQF_SHARED | IRQF_DISABLED, "h3600_action", &ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Action Button IRQ!\n");
 		err = -EBUSY;
-		goto fail2;
+		goto fail1;
 	}
 
 	if (request_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, npower_button_handler,
 			IRQF_SHARED | IRQF_DISABLED, "h3600_suspend", &ts->dev)) {
 		printk(KERN_ERR "h3600ts.c: Could not allocate Power Button IRQ!\n");
 		err = -EBUSY;
-		goto fail3;
+		goto fail2;
 	}
 
 	serio_set_drvdata(serio, ts);
 
 	err = serio_open(serio, drv);
 	if (err)
-		return err;
+		goto fail3;
 
 	//h3600_flite_control(1, 25);     /* default brightness */
-	input_register_device(ts->dev);
+	err = input_register_device(ts->dev);
+	if (err)
+		goto fail4;
 
 	return 0;
 
-fail3:	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
+fail4:	serio_close(serio);
+fail3:	serio_set_drvdata(serio, NULL);
+	free_irq(IRQ_GPIO_BITSY_NPOWER_BUTTON, ts->dev);
 fail2:	free_irq(IRQ_GPIO_BITSY_ACTION_BUTTON, ts->dev);
-fail1:	serio_set_drvdata(serio, NULL);
-	input_free_device(input_dev);
+fail1:	input_free_device(input_dev);
 	kfree(ts);
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/intel-mid-touch.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/intel-mid-touch.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/intel-mid-touch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/intel-mid-touch.c	2011-05-19 00:06:34.000000000 -0400
@@ -542,7 +542,7 @@
 	 * ADC power on, start, enable PENDET and set loop delay
 	 * ADC loop delay is set to 4.5 ms approximately
 	 * Loop delay more than this results in jitter in adc readings
-	 * Setting loop delay to 0 (continous loop) in MAXIM stops PENDET
+	 * Setting loop delay to 0 (continuous loop) in MAXIM stops PENDET
 	 * interrupt generation sometimes.
 	 */
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/Kconfig linux-libre-2.6.39-gnu/drivers/input/touchscreen/Kconfig
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -86,6 +86,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ad7879-spi.
 
+config TOUCHSCREEN_ATMEL_MXT
+	tristate "Atmel mXT I2C Touchscreen"
+	depends on I2C
+	help
+	  Say Y here if you have Atmel mXT series I2C touchscreen,
+	  such as AT42QT602240/ATMXT224, connected to your system.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called atmel_mxt_ts.
+
 config TOUCHSCREEN_BITSY
 	tristate "Compaq iPAQ H3600 (Bitsy) touchscreen"
 	depends on SA1100_BITSY
@@ -339,18 +351,6 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called penmount.
 
-config TOUCHSCREEN_QT602240
-	tristate "QT602240 I2C Touchscreen"
-	depends on I2C
-	help
-	  Say Y here if you have the AT42QT602240/ATMXT224 I2C touchscreen
-	  connected to your system.
-
-	  If unsure, say N.
-
-	  To compile this driver as a module, choose M here: the
-	  module will be called qt602240_ts.
-
 config TOUCHSCREEN_MIGOR
 	tristate "Renesas MIGO-R touchscreen"
 	depends on SH_MIGOR && I2C
@@ -423,6 +423,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_ts.
 
+config TOUCHSCREEN_WM831X
+	tristate "Support for WM831x touchscreen controllers"
+	depends on MFD_WM831X
+	help
+	  This enables support for the touchscreen controller on the WM831x
+	  series of PMICs.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called wm831x-ts.
+
 config TOUCHSCREEN_WM97XX
 	tristate "Support for WM97xx AC97 touchscreen controllers"
 	depends on AC97_BUS
@@ -629,6 +639,17 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called touchit213.
 
+config TOUCHSCREEN_TSC2005
+        tristate "TSC2005 based touchscreens"
+        depends on SPI_MASTER && GENERIC_HARDIRQS
+        help
+          Say Y here if you have a TSC2005 based touchscreen.
+
+	  If unsure, say N.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tsc2005.
+
 config TOUCHSCREEN_TSC2007
 	tristate "TSC2007 based touchscreens"
 	depends on I2C
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/mainstone-wm97xx.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/mainstone-wm97xx.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/mainstone-wm97xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/mainstone-wm97xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -219,7 +219,7 @@
 		}
 
 		wm->pen_irq = gpio_to_irq(irq);
-		set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
+		irq_set_irq_type(wm->pen_irq, IRQ_TYPE_EDGE_BOTH);
 	} else /* pen irq not supported */
 		pen_int = 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/Makefile linux-libre-2.6.39-gnu/drivers/input/touchscreen/Makefile
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 obj-$(CONFIG_TOUCHSCREEN_AD7879_I2C)	+= ad7879-i2c.o
 obj-$(CONFIG_TOUCHSCREEN_AD7879_SPI)	+= ad7879-spi.o
 obj-$(CONFIG_TOUCHSCREEN_ADS7846)	+= ads7846.o
+obj-$(CONFIG_TOUCHSCREEN_ATMEL_MXT)	+= atmel_mxt_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ATMEL_TSADCC)	+= atmel_tsadcc.o
 obj-$(CONFIG_TOUCHSCREEN_BITSY)		+= h3600_ts_input.o
 obj-$(CONFIG_TOUCHSCREEN_BU21013)       += bu21013_ts.o
@@ -37,7 +38,6 @@
 obj-$(CONFIG_TOUCHSCREEN_USB_COMPOSITE)	+= usbtouchscreen.o
 obj-$(CONFIG_TOUCHSCREEN_PCAP)		+= pcap_ts.o
 obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
-obj-$(CONFIG_TOUCHSCREEN_QT602240)	+= qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_ST1232)	+= st1232.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
@@ -45,9 +45,11 @@
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
+obj-$(CONFIG_TOUCHSCREEN_TSC2005)	+= tsc2005.o
 obj-$(CONFIG_TOUCHSCREEN_TSC2007)	+= tsc2007.o
 obj-$(CONFIG_TOUCHSCREEN_UCB1400)	+= ucb1400_ts.o
 obj-$(CONFIG_TOUCHSCREEN_WACOM_W8001)	+= wacom_w8001.o
+obj-$(CONFIG_TOUCHSCREEN_WM831X)	+= wm831x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_WM97XX)	+= wm97xx-ts.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9705)	+= wm9705.o
 wm97xx-ts-$(CONFIG_TOUCHSCREEN_WM9712)	+= wm9712.o
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/qt602240_ts.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/qt602240_ts.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/qt602240_ts.c	2012-03-24 01:17:13.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/qt602240_ts.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,1406 +0,0 @@
-/*
- * AT42QT602240/ATMXT224 Touchscreen driver
- *
- * Copyright (C) 2010 Samsung Electronics Co.Ltd
- * Author: Joonyoung Shim <jy0922.shim@samsung.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/module.h>
-#include <linux/init.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/i2c.h>
-#include <linux/i2c/qt602240_ts.h>
-#include <linux/input.h>
-#include <linux/interrupt.h>
-#include <linux/slab.h>
-
-/* Version */
-#define QT602240_VER_20			20
-#define QT602240_VER_21			21
-#define QT602240_VER_22			22
-
-/* Slave addresses */
-#define QT602240_APP_LOW		0x4a
-#define QT602240_APP_HIGH		0x4b
-#define QT602240_BOOT_LOW		0x24
-#define QT602240_BOOT_HIGH		0x25
-
-/* Firmware */
-#define QT602240_FW_NAME		"/*(DEBLOBBED)*/"
-
-/* Registers */
-#define QT602240_FAMILY_ID		0x00
-#define QT602240_VARIANT_ID		0x01
-#define QT602240_VERSION		0x02
-#define QT602240_BUILD			0x03
-#define QT602240_MATRIX_X_SIZE		0x04
-#define QT602240_MATRIX_Y_SIZE		0x05
-#define QT602240_OBJECT_NUM		0x06
-#define QT602240_OBJECT_START		0x07
-
-#define QT602240_OBJECT_SIZE		6
-
-/* Object types */
-#define QT602240_DEBUG_DIAGNOSTIC	37
-#define QT602240_GEN_MESSAGE		5
-#define QT602240_GEN_COMMAND		6
-#define QT602240_GEN_POWER		7
-#define QT602240_GEN_ACQUIRE		8
-#define QT602240_TOUCH_MULTI		9
-#define QT602240_TOUCH_KEYARRAY		15
-#define QT602240_TOUCH_PROXIMITY	23
-#define QT602240_PROCI_GRIPFACE		20
-#define QT602240_PROCG_NOISE		22
-#define QT602240_PROCI_ONETOUCH		24
-#define QT602240_PROCI_TWOTOUCH		27
-#define QT602240_SPT_COMMSCONFIG	18	/* firmware ver 21 over */
-#define QT602240_SPT_GPIOPWM		19
-#define QT602240_SPT_SELFTEST		25
-#define QT602240_SPT_CTECONFIG		28
-#define QT602240_SPT_USERDATA		38	/* firmware ver 21 over */
-
-/* QT602240_GEN_COMMAND field */
-#define QT602240_COMMAND_RESET		0
-#define QT602240_COMMAND_BACKUPNV	1
-#define QT602240_COMMAND_CALIBRATE	2
-#define QT602240_COMMAND_REPORTALL	3
-#define QT602240_COMMAND_DIAGNOSTIC	5
-
-/* QT602240_GEN_POWER field */
-#define QT602240_POWER_IDLEACQINT	0
-#define QT602240_POWER_ACTVACQINT	1
-#define QT602240_POWER_ACTV2IDLETO	2
-
-/* QT602240_GEN_ACQUIRE field */
-#define QT602240_ACQUIRE_CHRGTIME	0
-#define QT602240_ACQUIRE_TCHDRIFT	2
-#define QT602240_ACQUIRE_DRIFTST	3
-#define QT602240_ACQUIRE_TCHAUTOCAL	4
-#define QT602240_ACQUIRE_SYNC		5
-#define QT602240_ACQUIRE_ATCHCALST	6
-#define QT602240_ACQUIRE_ATCHCALSTHR	7
-
-/* QT602240_TOUCH_MULTI field */
-#define QT602240_TOUCH_CTRL		0
-#define QT602240_TOUCH_XORIGIN		1
-#define QT602240_TOUCH_YORIGIN		2
-#define QT602240_TOUCH_XSIZE		3
-#define QT602240_TOUCH_YSIZE		4
-#define QT602240_TOUCH_BLEN		6
-#define QT602240_TOUCH_TCHTHR		7
-#define QT602240_TOUCH_TCHDI		8
-#define QT602240_TOUCH_ORIENT		9
-#define QT602240_TOUCH_MOVHYSTI		11
-#define QT602240_TOUCH_MOVHYSTN		12
-#define QT602240_TOUCH_NUMTOUCH		14
-#define QT602240_TOUCH_MRGHYST		15
-#define QT602240_TOUCH_MRGTHR		16
-#define QT602240_TOUCH_AMPHYST		17
-#define QT602240_TOUCH_XRANGE_LSB	18
-#define QT602240_TOUCH_XRANGE_MSB	19
-#define QT602240_TOUCH_YRANGE_LSB	20
-#define QT602240_TOUCH_YRANGE_MSB	21
-#define QT602240_TOUCH_XLOCLIP		22
-#define QT602240_TOUCH_XHICLIP		23
-#define QT602240_TOUCH_YLOCLIP		24
-#define QT602240_TOUCH_YHICLIP		25
-#define QT602240_TOUCH_XEDGECTRL	26
-#define QT602240_TOUCH_XEDGEDIST	27
-#define QT602240_TOUCH_YEDGECTRL	28
-#define QT602240_TOUCH_YEDGEDIST	29
-#define QT602240_TOUCH_JUMPLIMIT	30	/* firmware ver 22 over */
-
-/* QT602240_PROCI_GRIPFACE field */
-#define QT602240_GRIPFACE_CTRL		0
-#define QT602240_GRIPFACE_XLOGRIP	1
-#define QT602240_GRIPFACE_XHIGRIP	2
-#define QT602240_GRIPFACE_YLOGRIP	3
-#define QT602240_GRIPFACE_YHIGRIP	4
-#define QT602240_GRIPFACE_MAXTCHS	5
-#define QT602240_GRIPFACE_SZTHR1	7
-#define QT602240_GRIPFACE_SZTHR2	8
-#define QT602240_GRIPFACE_SHPTHR1	9
-#define QT602240_GRIPFACE_SHPTHR2	10
-#define QT602240_GRIPFACE_SUPEXTTO	11
-
-/* QT602240_PROCI_NOISE field */
-#define QT602240_NOISE_CTRL		0
-#define QT602240_NOISE_OUTFLEN		1
-#define QT602240_NOISE_GCAFUL_LSB	3
-#define QT602240_NOISE_GCAFUL_MSB	4
-#define QT602240_NOISE_GCAFLL_LSB	5
-#define QT602240_NOISE_GCAFLL_MSB	6
-#define QT602240_NOISE_ACTVGCAFVALID	7
-#define QT602240_NOISE_NOISETHR		8
-#define QT602240_NOISE_FREQHOPSCALE	10
-#define QT602240_NOISE_FREQ0		11
-#define QT602240_NOISE_FREQ1		12
-#define QT602240_NOISE_FREQ2		13
-#define QT602240_NOISE_FREQ3		14
-#define QT602240_NOISE_FREQ4		15
-#define QT602240_NOISE_IDLEGCAFVALID	16
-
-/* QT602240_SPT_COMMSCONFIG */
-#define QT602240_COMMS_CTRL		0
-#define QT602240_COMMS_CMD		1
-
-/* QT602240_SPT_CTECONFIG field */
-#define QT602240_CTE_CTRL		0
-#define QT602240_CTE_CMD		1
-#define QT602240_CTE_MODE		2
-#define QT602240_CTE_IDLEGCAFDEPTH	3
-#define QT602240_CTE_ACTVGCAFDEPTH	4
-#define QT602240_CTE_VOLTAGE		5	/* firmware ver 21 over */
-
-#define QT602240_VOLTAGE_DEFAULT	2700000
-#define QT602240_VOLTAGE_STEP		10000
-
-/* Define for QT602240_GEN_COMMAND */
-#define QT602240_BOOT_VALUE		0xa5
-#define QT602240_BACKUP_VALUE		0x55
-#define QT602240_BACKUP_TIME		25	/* msec */
-#define QT602240_RESET_TIME		65	/* msec */
-
-#define QT602240_FWRESET_TIME		175	/* msec */
-
-/* Command to unlock bootloader */
-#define QT602240_UNLOCK_CMD_MSB		0xaa
-#define QT602240_UNLOCK_CMD_LSB		0xdc
-
-/* Bootloader mode status */
-#define QT602240_WAITING_BOOTLOAD_CMD	0xc0	/* valid 7 6 bit only */
-#define QT602240_WAITING_FRAME_DATA	0x80	/* valid 7 6 bit only */
-#define QT602240_FRAME_CRC_CHECK	0x02
-#define QT602240_FRAME_CRC_FAIL		0x03
-#define QT602240_FRAME_CRC_PASS		0x04
-#define QT602240_APP_CRC_FAIL		0x40	/* valid 7 8 bit only */
-#define QT602240_BOOT_STATUS_MASK	0x3f
-
-/* Touch status */
-#define QT602240_SUPPRESS		(1 << 1)
-#define QT602240_AMP			(1 << 2)
-#define QT602240_VECTOR			(1 << 3)
-#define QT602240_MOVE			(1 << 4)
-#define QT602240_RELEASE		(1 << 5)
-#define QT602240_PRESS			(1 << 6)
-#define QT602240_DETECT			(1 << 7)
-
-/* Touchscreen absolute values */
-#define QT602240_MAX_XC			0x3ff
-#define QT602240_MAX_YC			0x3ff
-#define QT602240_MAX_AREA		0xff
-
-#define QT602240_MAX_FINGER		10
-
-/* Initial register values recommended from chip vendor */
-static const u8 init_vals_ver_20[] = {
-	/* QT602240_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* QT602240_GEN_ACQUIRE(8) */
-	0x08, 0x05, 0x05, 0x00, 0x00, 0x00, 0x05, 0x14,
-	/* QT602240_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x88, 0x64,
-	/* QT602240_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00,
-	/* QT602240_PROCI_GRIPFACE(20) */
-	0x00, 0x64, 0x64, 0x64, 0x64, 0x00, 0x00, 0x1e, 0x14, 0x04,
-	0x1e, 0x00,
-	/* QT602240_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x19, 0x00, 0xe7, 0xff, 0x04, 0x32, 0x00,
-	0x01, 0x0a, 0x0f, 0x14, 0x00, 0x00, 0xe8,
-	/* QT602240_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00,
-	/* QT602240_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x00, 0x04, 0x08,
-};
-
-static const u8 init_vals_ver_21[] = {
-	/* QT602240_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* QT602240_GEN_ACQUIRE(8) */
-	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-	/* QT602240_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_GRIPFACE(20) */
-	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-	0x0f, 0x0a,
-	/* QT602240_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-	/* QT602240_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00,
-	/* QT602240_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
-};
-
-static const u8 init_vals_ver_22[] = {
-	/* QT602240_GEN_COMMAND(6) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_GEN_POWER(7) */
-	0x20, 0xff, 0x32,
-	/* QT602240_GEN_ACQUIRE(8) */
-	0x0a, 0x00, 0x05, 0x00, 0x00, 0x00, 0x09, 0x23,
-	/* QT602240_TOUCH_MULTI(9) */
-	0x00, 0x00, 0x00, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x02, 0x00,
-	0x00, 0x01, 0x01, 0x0e, 0x0a, 0x0a, 0x0a, 0x0a, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_TOUCH_KEYARRAY(15) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00,
-	/* QT602240_SPT_GPIOPWM(19) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_GRIPFACE(20) */
-	0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x28, 0x04,
-	0x0f, 0x0a,
-	/* QT602240_PROCG_NOISE(22) */
-	0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x23, 0x00,
-	0x00, 0x05, 0x0f, 0x19, 0x23, 0x2d, 0x03,
-	/* QT602240_TOUCH_PROXIMITY(23) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_ONETOUCH(24) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_SELFTEST(25) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00,
-	/* QT602240_PROCI_TWOTOUCH(27) */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	/* QT602240_SPT_CTECONFIG(28) */
-	0x00, 0x00, 0x00, 0x08, 0x10, 0x00,
-};
-
-struct qt602240_info {
-	u8 family_id;
-	u8 variant_id;
-	u8 version;
-	u8 build;
-	u8 matrix_xsize;
-	u8 matrix_ysize;
-	u8 object_num;
-};
-
-struct qt602240_object {
-	u8 type;
-	u16 start_address;
-	u8 size;
-	u8 instances;
-	u8 num_report_ids;
-
-	/* to map object and message */
-	u8 max_reportid;
-};
-
-struct qt602240_message {
-	u8 reportid;
-	u8 message[7];
-	u8 checksum;
-};
-
-struct qt602240_finger {
-	int status;
-	int x;
-	int y;
-	int area;
-};
-
-/* Each client has this additional data */
-struct qt602240_data {
-	struct i2c_client *client;
-	struct input_dev *input_dev;
-	const struct qt602240_platform_data *pdata;
-	struct qt602240_object *object_table;
-	struct qt602240_info info;
-	struct qt602240_finger finger[QT602240_MAX_FINGER];
-	unsigned int irq;
-};
-
-static bool qt602240_object_readable(unsigned int type)
-{
-	switch (type) {
-	case QT602240_GEN_MESSAGE:
-	case QT602240_GEN_COMMAND:
-	case QT602240_GEN_POWER:
-	case QT602240_GEN_ACQUIRE:
-	case QT602240_TOUCH_MULTI:
-	case QT602240_TOUCH_KEYARRAY:
-	case QT602240_TOUCH_PROXIMITY:
-	case QT602240_PROCI_GRIPFACE:
-	case QT602240_PROCG_NOISE:
-	case QT602240_PROCI_ONETOUCH:
-	case QT602240_PROCI_TWOTOUCH:
-	case QT602240_SPT_COMMSCONFIG:
-	case QT602240_SPT_GPIOPWM:
-	case QT602240_SPT_SELFTEST:
-	case QT602240_SPT_CTECONFIG:
-	case QT602240_SPT_USERDATA:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static bool qt602240_object_writable(unsigned int type)
-{
-	switch (type) {
-	case QT602240_GEN_COMMAND:
-	case QT602240_GEN_POWER:
-	case QT602240_GEN_ACQUIRE:
-	case QT602240_TOUCH_MULTI:
-	case QT602240_TOUCH_KEYARRAY:
-	case QT602240_TOUCH_PROXIMITY:
-	case QT602240_PROCI_GRIPFACE:
-	case QT602240_PROCG_NOISE:
-	case QT602240_PROCI_ONETOUCH:
-	case QT602240_PROCI_TWOTOUCH:
-	case QT602240_SPT_GPIOPWM:
-	case QT602240_SPT_SELFTEST:
-	case QT602240_SPT_CTECONFIG:
-		return true;
-	default:
-		return false;
-	}
-}
-
-static void qt602240_dump_message(struct device *dev,
-				  struct qt602240_message *message)
-{
-	dev_dbg(dev, "reportid:\t0x%x\n", message->reportid);
-	dev_dbg(dev, "message1:\t0x%x\n", message->message[0]);
-	dev_dbg(dev, "message2:\t0x%x\n", message->message[1]);
-	dev_dbg(dev, "message3:\t0x%x\n", message->message[2]);
-	dev_dbg(dev, "message4:\t0x%x\n", message->message[3]);
-	dev_dbg(dev, "message5:\t0x%x\n", message->message[4]);
-	dev_dbg(dev, "message6:\t0x%x\n", message->message[5]);
-	dev_dbg(dev, "message7:\t0x%x\n", message->message[6]);
-	dev_dbg(dev, "checksum:\t0x%x\n", message->checksum);
-}
-
-static int qt602240_check_bootloader(struct i2c_client *client,
-				     unsigned int state)
-{
-	u8 val;
-
-recheck:
-	if (i2c_master_recv(client, &val, 1) != 1) {
-		dev_err(&client->dev, "%s: i2c recv failed\n", __func__);
-		return -EIO;
-	}
-
-	switch (state) {
-	case QT602240_WAITING_BOOTLOAD_CMD:
-	case QT602240_WAITING_FRAME_DATA:
-		val &= ~QT602240_BOOT_STATUS_MASK;
-		break;
-	case QT602240_FRAME_CRC_PASS:
-		if (val == QT602240_FRAME_CRC_CHECK)
-			goto recheck;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	if (val != state) {
-		dev_err(&client->dev, "Unvalid bootloader mode state\n");
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
-static int qt602240_unlock_bootloader(struct i2c_client *client)
-{
-	u8 buf[2];
-
-	buf[0] = QT602240_UNLOCK_CMD_LSB;
-	buf[1] = QT602240_UNLOCK_CMD_MSB;
-
-	if (i2c_master_send(client, buf, 2) != 2) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int qt602240_fw_write(struct i2c_client *client,
-			     const u8 *data, unsigned int frame_size)
-{
-	if (i2c_master_send(client, data, frame_size) != frame_size) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int __qt602240_read_reg(struct i2c_client *client,
-			       u16 reg, u16 len, void *val)
-{
-	struct i2c_msg xfer[2];
-	u8 buf[2];
-
-	buf[0] = reg & 0xff;
-	buf[1] = (reg >> 8) & 0xff;
-
-	/* Write register */
-	xfer[0].addr = client->addr;
-	xfer[0].flags = 0;
-	xfer[0].len = 2;
-	xfer[0].buf = buf;
-
-	/* Read data */
-	xfer[1].addr = client->addr;
-	xfer[1].flags = I2C_M_RD;
-	xfer[1].len = len;
-	xfer[1].buf = val;
-
-	if (i2c_transfer(client->adapter, xfer, 2) != 2) {
-		dev_err(&client->dev, "%s: i2c transfer failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int qt602240_read_reg(struct i2c_client *client, u16 reg, u8 *val)
-{
-	return __qt602240_read_reg(client, reg, 1, val);
-}
-
-static int qt602240_write_reg(struct i2c_client *client, u16 reg, u8 val)
-{
-	u8 buf[3];
-
-	buf[0] = reg & 0xff;
-	buf[1] = (reg >> 8) & 0xff;
-	buf[2] = val;
-
-	if (i2c_master_send(client, buf, 3) != 3) {
-		dev_err(&client->dev, "%s: i2c send failed\n", __func__);
-		return -EIO;
-	}
-
-	return 0;
-}
-
-static int qt602240_read_object_table(struct i2c_client *client,
-				      u16 reg, u8 *object_buf)
-{
-	return __qt602240_read_reg(client, reg, QT602240_OBJECT_SIZE,
-				   object_buf);
-}
-
-static struct qt602240_object *
-qt602240_get_object(struct qt602240_data *data, u8 type)
-{
-	struct qt602240_object *object;
-	int i;
-
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
-		if (object->type == type)
-			return object;
-	}
-
-	dev_err(&data->client->dev, "Invalid object type\n");
-	return NULL;
-}
-
-static int qt602240_read_message(struct qt602240_data *data,
-				 struct qt602240_message *message)
-{
-	struct qt602240_object *object;
-	u16 reg;
-
-	object = qt602240_get_object(data, QT602240_GEN_MESSAGE);
-	if (!object)
-		return -EINVAL;
-
-	reg = object->start_address;
-	return __qt602240_read_reg(data->client, reg,
-			sizeof(struct qt602240_message), message);
-}
-
-static int qt602240_read_object(struct qt602240_data *data,
-				u8 type, u8 offset, u8 *val)
-{
-	struct qt602240_object *object;
-	u16 reg;
-
-	object = qt602240_get_object(data, type);
-	if (!object)
-		return -EINVAL;
-
-	reg = object->start_address;
-	return __qt602240_read_reg(data->client, reg + offset, 1, val);
-}
-
-static int qt602240_write_object(struct qt602240_data *data,
-				 u8 type, u8 offset, u8 val)
-{
-	struct qt602240_object *object;
-	u16 reg;
-
-	object = qt602240_get_object(data, type);
-	if (!object)
-		return -EINVAL;
-
-	reg = object->start_address;
-	return qt602240_write_reg(data->client, reg + offset, val);
-}
-
-static void qt602240_input_report(struct qt602240_data *data, int single_id)
-{
-	struct qt602240_finger *finger = data->finger;
-	struct input_dev *input_dev = data->input_dev;
-	int status = finger[single_id].status;
-	int finger_num = 0;
-	int id;
-
-	for (id = 0; id < QT602240_MAX_FINGER; id++) {
-		if (!finger[id].status)
-			continue;
-
-		input_report_abs(input_dev, ABS_MT_TOUCH_MAJOR,
-				finger[id].status != QT602240_RELEASE ?
-				finger[id].area : 0);
-		input_report_abs(input_dev, ABS_MT_POSITION_X,
-				finger[id].x);
-		input_report_abs(input_dev, ABS_MT_POSITION_Y,
-				finger[id].y);
-		input_mt_sync(input_dev);
-
-		if (finger[id].status == QT602240_RELEASE)
-			finger[id].status = 0;
-		else
-			finger_num++;
-	}
-
-	input_report_key(input_dev, BTN_TOUCH, finger_num > 0);
-
-	if (status != QT602240_RELEASE) {
-		input_report_abs(input_dev, ABS_X, finger[single_id].x);
-		input_report_abs(input_dev, ABS_Y, finger[single_id].y);
-	}
-
-	input_sync(input_dev);
-}
-
-static void qt602240_input_touchevent(struct qt602240_data *data,
-				      struct qt602240_message *message, int id)
-{
-	struct qt602240_finger *finger = data->finger;
-	struct device *dev = &data->client->dev;
-	u8 status = message->message[0];
-	int x;
-	int y;
-	int area;
-
-	/* Check the touch is present on the screen */
-	if (!(status & QT602240_DETECT)) {
-		if (status & QT602240_RELEASE) {
-			dev_dbg(dev, "[%d] released\n", id);
-
-			finger[id].status = QT602240_RELEASE;
-			qt602240_input_report(data, id);
-		}
-		return;
-	}
-
-	/* Check only AMP detection */
-	if (!(status & (QT602240_PRESS | QT602240_MOVE)))
-		return;
-
-	x = (message->message[1] << 2) | ((message->message[3] & ~0x3f) >> 6);
-	y = (message->message[2] << 2) | ((message->message[3] & ~0xf3) >> 2);
-	area = message->message[4];
-
-	dev_dbg(dev, "[%d] %s x: %d, y: %d, area: %d\n", id,
-		status & QT602240_MOVE ? "moved" : "pressed",
-		x, y, area);
-
-	finger[id].status = status & QT602240_MOVE ?
-				QT602240_MOVE : QT602240_PRESS;
-	finger[id].x = x;
-	finger[id].y = y;
-	finger[id].area = area;
-
-	qt602240_input_report(data, id);
-}
-
-static irqreturn_t qt602240_interrupt(int irq, void *dev_id)
-{
-	struct qt602240_data *data = dev_id;
-	struct qt602240_message message;
-	struct qt602240_object *object;
-	struct device *dev = &data->client->dev;
-	int id;
-	u8 reportid;
-	u8 max_reportid;
-	u8 min_reportid;
-
-	do {
-		if (qt602240_read_message(data, &message)) {
-			dev_err(dev, "Failed to read message\n");
-			goto end;
-		}
-
-		reportid = message.reportid;
-
-		/* whether reportid is thing of QT602240_TOUCH_MULTI */
-		object = qt602240_get_object(data, QT602240_TOUCH_MULTI);
-		if (!object)
-			goto end;
-
-		max_reportid = object->max_reportid;
-		min_reportid = max_reportid - object->num_report_ids + 1;
-		id = reportid - min_reportid;
-
-		if (reportid >= min_reportid && reportid <= max_reportid)
-			qt602240_input_touchevent(data, &message, id);
-		else
-			qt602240_dump_message(dev, &message);
-	} while (reportid != 0xff);
-
-end:
-	return IRQ_HANDLED;
-}
-
-static int qt602240_check_reg_init(struct qt602240_data *data)
-{
-	struct qt602240_object *object;
-	struct device *dev = &data->client->dev;
-	int index = 0;
-	int i, j;
-	u8 version = data->info.version;
-	u8 *init_vals;
-
-	switch (version) {
-	case QT602240_VER_20:
-		init_vals = (u8 *)init_vals_ver_20;
-		break;
-	case QT602240_VER_21:
-		init_vals = (u8 *)init_vals_ver_21;
-		break;
-	case QT602240_VER_22:
-		init_vals = (u8 *)init_vals_ver_22;
-		break;
-	default:
-		dev_err(dev, "Firmware version %d doesn't support\n", version);
-		return -EINVAL;
-	}
-
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
-
-		if (!qt602240_object_writable(object->type))
-			continue;
-
-		for (j = 0; j < object->size + 1; j++)
-			qt602240_write_object(data, object->type, j,
-					init_vals[index + j]);
-
-		index += object->size + 1;
-	}
-
-	return 0;
-}
-
-static int qt602240_check_matrix_size(struct qt602240_data *data)
-{
-	const struct qt602240_platform_data *pdata = data->pdata;
-	struct device *dev = &data->client->dev;
-	int mode = -1;
-	int error;
-	u8 val;
-
-	dev_dbg(dev, "Number of X lines: %d\n", pdata->x_line);
-	dev_dbg(dev, "Number of Y lines: %d\n", pdata->y_line);
-
-	switch (pdata->x_line) {
-	case 0 ... 15:
-		if (pdata->y_line <= 14)
-			mode = 0;
-		break;
-	case 16:
-		if (pdata->y_line <= 12)
-			mode = 1;
-		if (pdata->y_line == 13 || pdata->y_line == 14)
-			mode = 0;
-		break;
-	case 17:
-		if (pdata->y_line <= 11)
-			mode = 2;
-		if (pdata->y_line == 12 || pdata->y_line == 13)
-			mode = 1;
-		break;
-	case 18:
-		if (pdata->y_line <= 10)
-			mode = 3;
-		if (pdata->y_line == 11 || pdata->y_line == 12)
-			mode = 2;
-		break;
-	case 19:
-		if (pdata->y_line <= 9)
-			mode = 4;
-		if (pdata->y_line == 10 || pdata->y_line == 11)
-			mode = 3;
-		break;
-	case 20:
-		mode = 4;
-	}
-
-	if (mode < 0) {
-		dev_err(dev, "Invalid X/Y lines\n");
-		return -EINVAL;
-	}
-
-	error = qt602240_read_object(data, QT602240_SPT_CTECONFIG,
-				QT602240_CTE_MODE, &val);
-	if (error)
-		return error;
-
-	if (mode == val)
-		return 0;
-
-	/* Change the CTE configuration */
-	qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-			QT602240_CTE_CTRL, 1);
-	qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-			QT602240_CTE_MODE, mode);
-	qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-			QT602240_CTE_CTRL, 0);
-
-	return 0;
-}
-
-static int qt602240_make_highchg(struct qt602240_data *data)
-{
-	struct device *dev = &data->client->dev;
-	int count = 10;
-	int error;
-	u8 val;
-
-	/* Read dummy message to make high CHG pin */
-	do {
-		error = qt602240_read_object(data, QT602240_GEN_MESSAGE, 0, &val);
-		if (error)
-			return error;
-	} while ((val != 0xff) && --count);
-
-	if (!count) {
-		dev_err(dev, "CHG pin isn't cleared\n");
-		return -EBUSY;
-	}
-
-	return 0;
-}
-
-static void qt602240_handle_pdata(struct qt602240_data *data)
-{
-	const struct qt602240_platform_data *pdata = data->pdata;
-	u8 voltage;
-
-	/* Set touchscreen lines */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_XSIZE,
-			pdata->x_line);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_YSIZE,
-			pdata->y_line);
-
-	/* Set touchscreen orient */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI, QT602240_TOUCH_ORIENT,
-			pdata->orient);
-
-	/* Set touchscreen burst length */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_BLEN, pdata->blen);
-
-	/* Set touchscreen threshold */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_TCHTHR, pdata->threshold);
-
-	/* Set touchscreen resolution */
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_XRANGE_LSB, (pdata->x_size - 1) & 0xff);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_XRANGE_MSB, (pdata->x_size - 1) >> 8);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_YRANGE_LSB, (pdata->y_size - 1) & 0xff);
-	qt602240_write_object(data, QT602240_TOUCH_MULTI,
-			QT602240_TOUCH_YRANGE_MSB, (pdata->y_size - 1) >> 8);
-
-	/* Set touchscreen voltage */
-	if (data->info.version >= QT602240_VER_21 && pdata->voltage) {
-		if (pdata->voltage < QT602240_VOLTAGE_DEFAULT) {
-			voltage = (QT602240_VOLTAGE_DEFAULT - pdata->voltage) /
-				QT602240_VOLTAGE_STEP;
-			voltage = 0xff - voltage + 1;
-		} else
-			voltage = (pdata->voltage - QT602240_VOLTAGE_DEFAULT) /
-				QT602240_VOLTAGE_STEP;
-
-		qt602240_write_object(data, QT602240_SPT_CTECONFIG,
-				QT602240_CTE_VOLTAGE, voltage);
-	}
-}
-
-static int qt602240_get_info(struct qt602240_data *data)
-{
-	struct i2c_client *client = data->client;
-	struct qt602240_info *info = &data->info;
-	int error;
-	u8 val;
-
-	error = qt602240_read_reg(client, QT602240_FAMILY_ID, &val);
-	if (error)
-		return error;
-	info->family_id = val;
-
-	error = qt602240_read_reg(client, QT602240_VARIANT_ID, &val);
-	if (error)
-		return error;
-	info->variant_id = val;
-
-	error = qt602240_read_reg(client, QT602240_VERSION, &val);
-	if (error)
-		return error;
-	info->version = val;
-
-	error = qt602240_read_reg(client, QT602240_BUILD, &val);
-	if (error)
-		return error;
-	info->build = val;
-
-	error = qt602240_read_reg(client, QT602240_OBJECT_NUM, &val);
-	if (error)
-		return error;
-	info->object_num = val;
-
-	return 0;
-}
-
-static int qt602240_get_object_table(struct qt602240_data *data)
-{
-	int error;
-	int i;
-	u16 reg;
-	u8 reportid = 0;
-	u8 buf[QT602240_OBJECT_SIZE];
-
-	for (i = 0; i < data->info.object_num; i++) {
-		struct qt602240_object *object = data->object_table + i;
-
-		reg = QT602240_OBJECT_START + QT602240_OBJECT_SIZE * i;
-		error = qt602240_read_object_table(data->client, reg, buf);
-		if (error)
-			return error;
-
-		object->type = buf[0];
-		object->start_address = (buf[2] << 8) | buf[1];
-		object->size = buf[3];
-		object->instances = buf[4];
-		object->num_report_ids = buf[5];
-
-		if (object->num_report_ids) {
-			reportid += object->num_report_ids *
-					(object->instances + 1);
-			object->max_reportid = reportid;
-		}
-	}
-
-	return 0;
-}
-
-static int qt602240_initialize(struct qt602240_data *data)
-{
-	struct i2c_client *client = data->client;
-	struct qt602240_info *info = &data->info;
-	int error;
-	u8 val;
-
-	error = qt602240_get_info(data);
-	if (error)
-		return error;
-
-	data->object_table = kcalloc(info->object_num,
-				     sizeof(struct qt602240_object),
-				     GFP_KERNEL);
-	if (!data->object_table) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
-		return -ENOMEM;
-	}
-
-	/* Get object table information */
-	error = qt602240_get_object_table(data);
-	if (error)
-		return error;
-
-	/* Check register init values */
-	error = qt602240_check_reg_init(data);
-	if (error)
-		return error;
-
-	/* Check X/Y matrix size */
-	error = qt602240_check_matrix_size(data);
-	if (error)
-		return error;
-
-	error = qt602240_make_highchg(data);
-	if (error)
-		return error;
-
-	qt602240_handle_pdata(data);
-
-	/* Backup to memory */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_BACKUPNV,
-			QT602240_BACKUP_VALUE);
-	msleep(QT602240_BACKUP_TIME);
-
-	/* Soft reset */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_RESET, 1);
-	msleep(QT602240_RESET_TIME);
-
-	/* Update matrix size at info struct */
-	error = qt602240_read_reg(client, QT602240_MATRIX_X_SIZE, &val);
-	if (error)
-		return error;
-	info->matrix_xsize = val;
-
-	error = qt602240_read_reg(client, QT602240_MATRIX_Y_SIZE, &val);
-	if (error)
-		return error;
-	info->matrix_ysize = val;
-
-	dev_info(&client->dev,
-			"Family ID: %d Variant ID: %d Version: %d Build: %d\n",
-			info->family_id, info->variant_id, info->version,
-			info->build);
-
-	dev_info(&client->dev,
-			"Matrix X Size: %d Matrix Y Size: %d Object Num: %d\n",
-			info->matrix_xsize, info->matrix_ysize,
-			info->object_num);
-
-	return 0;
-}
-
-static ssize_t qt602240_object_show(struct device *dev,
-				    struct device_attribute *attr, char *buf)
-{
-	struct qt602240_data *data = dev_get_drvdata(dev);
-	struct qt602240_object *object;
-	int count = 0;
-	int i, j;
-	int error;
-	u8 val;
-
-	for (i = 0; i < data->info.object_num; i++) {
-		object = data->object_table + i;
-
-		count += sprintf(buf + count,
-				"Object Table Element %d(Type %d)\n",
-				i + 1, object->type);
-
-		if (!qt602240_object_readable(object->type)) {
-			count += sprintf(buf + count, "\n");
-			continue;
-		}
-
-		for (j = 0; j < object->size + 1; j++) {
-			error = qt602240_read_object(data,
-						object->type, j, &val);
-			if (error)
-				return error;
-
-			count += sprintf(buf + count,
-					"  Byte %d: 0x%x (%d)\n", j, val, val);
-		}
-
-		count += sprintf(buf + count, "\n");
-	}
-
-	return count;
-}
-
-static int qt602240_load_fw(struct device *dev, const char *fn)
-{
-	struct qt602240_data *data = dev_get_drvdata(dev);
-	struct i2c_client *client = data->client;
-	const struct firmware *fw = NULL;
-	unsigned int frame_size;
-	unsigned int pos = 0;
-	int ret;
-
-	ret = reject_firmware(&fw, fn, dev);
-	if (ret) {
-		dev_err(dev, "Unable to open firmware %s\n", fn);
-		return ret;
-	}
-
-	/* Change to the bootloader mode */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_RESET, QT602240_BOOT_VALUE);
-	msleep(QT602240_RESET_TIME);
-
-	/* Change to slave address of bootloader */
-	if (client->addr == QT602240_APP_LOW)
-		client->addr = QT602240_BOOT_LOW;
-	else
-		client->addr = QT602240_BOOT_HIGH;
-
-	ret = qt602240_check_bootloader(client, QT602240_WAITING_BOOTLOAD_CMD);
-	if (ret)
-		goto out;
-
-	/* Unlock bootloader */
-	qt602240_unlock_bootloader(client);
-
-	while (pos < fw->size) {
-		ret = qt602240_check_bootloader(client,
-						QT602240_WAITING_FRAME_DATA);
-		if (ret)
-			goto out;
-
-		frame_size = ((*(fw->data + pos) << 8) | *(fw->data + pos + 1));
-
-		/* We should add 2 at frame size as the the firmware data is not
-		 * included the CRC bytes.
-		 */
-		frame_size += 2;
-
-		/* Write one frame to device */
-		qt602240_fw_write(client, fw->data + pos, frame_size);
-
-		ret = qt602240_check_bootloader(client,
-						QT602240_FRAME_CRC_PASS);
-		if (ret)
-			goto out;
-
-		pos += frame_size;
-
-		dev_dbg(dev, "Updated %d bytes / %zd bytes\n", pos, fw->size);
-	}
-
-out:
-	release_firmware(fw);
-
-	/* Change to slave address of application */
-	if (client->addr == QT602240_BOOT_LOW)
-		client->addr = QT602240_APP_LOW;
-	else
-		client->addr = QT602240_APP_HIGH;
-
-	return ret;
-}
-
-static ssize_t qt602240_update_fw_store(struct device *dev,
-					struct device_attribute *attr,
-					const char *buf, size_t count)
-{
-	struct qt602240_data *data = dev_get_drvdata(dev);
-	unsigned int version;
-	int error;
-
-	if (sscanf(buf, "%u", &version) != 1) {
-		dev_err(dev, "Invalid values\n");
-		return -EINVAL;
-	}
-
-	if (data->info.version < QT602240_VER_21 || version < QT602240_VER_21) {
-		dev_err(dev, "FW update supported starting with version 21\n");
-		return -EINVAL;
-	}
-
-	disable_irq(data->irq);
-
-	error = qt602240_load_fw(dev, QT602240_FW_NAME);
-	if (error) {
-		dev_err(dev, "The firmware update failed(%d)\n", error);
-		count = error;
-	} else {
-		dev_dbg(dev, "The firmware update succeeded\n");
-
-		/* Wait for reset */
-		msleep(QT602240_FWRESET_TIME);
-
-		kfree(data->object_table);
-		data->object_table = NULL;
-
-		qt602240_initialize(data);
-	}
-
-	enable_irq(data->irq);
-
-	return count;
-}
-
-static DEVICE_ATTR(object, 0444, qt602240_object_show, NULL);
-static DEVICE_ATTR(update_fw, 0664, NULL, qt602240_update_fw_store);
-
-static struct attribute *qt602240_attrs[] = {
-	&dev_attr_object.attr,
-	&dev_attr_update_fw.attr,
-	NULL
-};
-
-static const struct attribute_group qt602240_attr_group = {
-	.attrs = qt602240_attrs,
-};
-
-static void qt602240_start(struct qt602240_data *data)
-{
-	/* Touch enable */
-	qt602240_write_object(data,
-			QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0x83);
-}
-
-static void qt602240_stop(struct qt602240_data *data)
-{
-	/* Touch disable */
-	qt602240_write_object(data,
-			QT602240_TOUCH_MULTI, QT602240_TOUCH_CTRL, 0);
-}
-
-static int qt602240_input_open(struct input_dev *dev)
-{
-	struct qt602240_data *data = input_get_drvdata(dev);
-
-	qt602240_start(data);
-
-	return 0;
-}
-
-static void qt602240_input_close(struct input_dev *dev)
-{
-	struct qt602240_data *data = input_get_drvdata(dev);
-
-	qt602240_stop(data);
-}
-
-static int __devinit qt602240_probe(struct i2c_client *client,
-		const struct i2c_device_id *id)
-{
-	struct qt602240_data *data;
-	struct input_dev *input_dev;
-	int error;
-
-	if (!client->dev.platform_data)
-		return -EINVAL;
-
-	data = kzalloc(sizeof(struct qt602240_data), GFP_KERNEL);
-	input_dev = input_allocate_device();
-	if (!data || !input_dev) {
-		dev_err(&client->dev, "Failed to allocate memory\n");
-		error = -ENOMEM;
-		goto err_free_mem;
-	}
-
-	input_dev->name = "AT42QT602240/ATMXT224 Touchscreen";
-	input_dev->id.bustype = BUS_I2C;
-	input_dev->dev.parent = &client->dev;
-	input_dev->open = qt602240_input_open;
-	input_dev->close = qt602240_input_close;
-
-	__set_bit(EV_ABS, input_dev->evbit);
-	__set_bit(EV_KEY, input_dev->evbit);
-	__set_bit(BTN_TOUCH, input_dev->keybit);
-
-	/* For single touch */
-	input_set_abs_params(input_dev, ABS_X,
-			     0, QT602240_MAX_XC, 0, 0);
-	input_set_abs_params(input_dev, ABS_Y,
-			     0, QT602240_MAX_YC, 0, 0);
-
-	/* For multi touch */
-	input_set_abs_params(input_dev, ABS_MT_TOUCH_MAJOR,
-			     0, QT602240_MAX_AREA, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_X,
-			     0, QT602240_MAX_XC, 0, 0);
-	input_set_abs_params(input_dev, ABS_MT_POSITION_Y,
-			     0, QT602240_MAX_YC, 0, 0);
-
-	input_set_drvdata(input_dev, data);
-
-	data->client = client;
-	data->input_dev = input_dev;
-	data->pdata = client->dev.platform_data;
-	data->irq = client->irq;
-
-	i2c_set_clientdata(client, data);
-
-	error = qt602240_initialize(data);
-	if (error)
-		goto err_free_object;
-
-	error = request_threaded_irq(client->irq, NULL, qt602240_interrupt,
-			IRQF_TRIGGER_FALLING, client->dev.driver->name, data);
-	if (error) {
-		dev_err(&client->dev, "Failed to register interrupt\n");
-		goto err_free_object;
-	}
-
-	error = input_register_device(input_dev);
-	if (error)
-		goto err_free_irq;
-
-	error = sysfs_create_group(&client->dev.kobj, &qt602240_attr_group);
-	if (error)
-		goto err_unregister_device;
-
-	return 0;
-
-err_unregister_device:
-	input_unregister_device(input_dev);
-	input_dev = NULL;
-err_free_irq:
-	free_irq(client->irq, data);
-err_free_object:
-	kfree(data->object_table);
-err_free_mem:
-	input_free_device(input_dev);
-	kfree(data);
-	return error;
-}
-
-static int __devexit qt602240_remove(struct i2c_client *client)
-{
-	struct qt602240_data *data = i2c_get_clientdata(client);
-
-	sysfs_remove_group(&client->dev.kobj, &qt602240_attr_group);
-	free_irq(data->irq, data);
-	input_unregister_device(data->input_dev);
-	kfree(data->object_table);
-	kfree(data);
-
-	return 0;
-}
-
-#ifdef CONFIG_PM
-static int qt602240_suspend(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct qt602240_data *data = i2c_get_clientdata(client);
-	struct input_dev *input_dev = data->input_dev;
-
-	mutex_lock(&input_dev->mutex);
-
-	if (input_dev->users)
-		qt602240_stop(data);
-
-	mutex_unlock(&input_dev->mutex);
-
-	return 0;
-}
-
-static int qt602240_resume(struct device *dev)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct qt602240_data *data = i2c_get_clientdata(client);
-	struct input_dev *input_dev = data->input_dev;
-
-	/* Soft reset */
-	qt602240_write_object(data, QT602240_GEN_COMMAND,
-			QT602240_COMMAND_RESET, 1);
-
-	msleep(QT602240_RESET_TIME);
-
-	mutex_lock(&input_dev->mutex);
-
-	if (input_dev->users)
-		qt602240_start(data);
-
-	mutex_unlock(&input_dev->mutex);
-
-	return 0;
-}
-
-static const struct dev_pm_ops qt602240_pm_ops = {
-	.suspend	= qt602240_suspend,
-	.resume		= qt602240_resume,
-};
-#endif
-
-static const struct i2c_device_id qt602240_id[] = {
-	{ "qt602240_ts", 0 },
-	{ }
-};
-MODULE_DEVICE_TABLE(i2c, qt602240_id);
-
-static struct i2c_driver qt602240_driver = {
-	.driver = {
-		.name	= "qt602240_ts",
-		.owner	= THIS_MODULE,
-#ifdef CONFIG_PM
-		.pm	= &qt602240_pm_ops,
-#endif
-	},
-	.probe		= qt602240_probe,
-	.remove		= __devexit_p(qt602240_remove),
-	.id_table	= qt602240_id,
-};
-
-static int __init qt602240_init(void)
-{
-	return i2c_add_driver(&qt602240_driver);
-}
-
-static void __exit qt602240_exit(void)
-{
-	i2c_del_driver(&qt602240_driver);
-}
-
-module_init(qt602240_init);
-module_exit(qt602240_exit);
-
-/* Module information */
-MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>");
-MODULE_DESCRIPTION("AT42QT602240/ATMXT224 Touchscreen driver");
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/tps6507x-ts.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/tps6507x-ts.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/tps6507x-ts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/tps6507x-ts.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,7 +43,6 @@
 	struct input_dev	*input_dev;
 	struct device		*dev;
 	char			phys[32];
-	struct workqueue_struct *wq;
 	struct delayed_work	work;
 	unsigned		polling;	/* polling is active */
 	struct ts_event		tc;
@@ -220,8 +219,8 @@
 	poll = 1;
 
 	if (poll) {
-		schd = queue_delayed_work(tsc->wq, &tsc->work,
-					  msecs_to_jiffies(tsc->poll_period));
+		schd = schedule_delayed_work(&tsc->work,
+					msecs_to_jiffies(tsc->poll_period));
 		if (schd)
 			tsc->polling = 1;
 		else {
@@ -303,7 +302,6 @@
 	tsc->input_dev = input_dev;
 
 	INIT_DELAYED_WORK(&tsc->work, tps6507x_ts_handler);
-	tsc->wq = create_workqueue("TPS6507x Touchscreen");
 
 	if (init_data) {
 		tsc->poll_period = init_data->poll_period;
@@ -325,8 +323,8 @@
 	if (error)
 		goto err2;
 
-	schd = queue_delayed_work(tsc->wq, &tsc->work,
-				  msecs_to_jiffies(tsc->poll_period));
+	schd = schedule_delayed_work(&tsc->work,
+				     msecs_to_jiffies(tsc->poll_period));
 
 	if (schd)
 		tsc->polling = 1;
@@ -341,7 +339,6 @@
 
 err2:
 	cancel_delayed_work_sync(&tsc->work);
-	destroy_workqueue(tsc->wq);
 	input_free_device(input_dev);
 err1:
 	kfree(tsc);
@@ -357,7 +354,6 @@
 	struct input_dev *input_dev = tsc->input_dev;
 
 	cancel_delayed_work_sync(&tsc->work);
-	destroy_workqueue(tsc->wq);
 
 	input_unregister_device(input_dev);
 
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/tsc2005.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/tsc2005.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/tsc2005.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/tsc2005.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,764 @@
+/*
+ * TSC2005 touchscreen driver
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ *
+ * Author: Lauri Leukkunen <lauri.leukkunen@nokia.com>
+ * based on TSC2301 driver by Klaus K. Pedersen <klaus.k.pedersen@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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/pm.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/tsc2005.h>
+
+/*
+ * The touchscreen interface operates as follows:
+ *
+ * 1) Pen is pressed against the touchscreen.
+ * 2) TSC2005 performs AD conversion.
+ * 3) After the conversion is done TSC2005 drives DAV line down.
+ * 4) GPIO IRQ is received and tsc2005_irq_thread() is scheduled.
+ * 5) tsc2005_irq_thread() queues up an spi transfer to fetch the x, y, z1, z2
+ *    values.
+ * 6) tsc2005_irq_thread() reports coordinates to input layer and sets up
+ *    tsc2005_penup_timer() to be called after TSC2005_PENUP_TIME_MS (40ms).
+ * 7) When the penup timer expires, there have not been touch or DAV interrupts
+ *    during the last 40ms which means the pen has been lifted.
+ *
+ * ESD recovery via a hardware reset is done if the TSC2005 doesn't respond
+ * after a configurable period (in ms) of activity. If esd_timeout is 0, the
+ * watchdog is disabled.
+ */
+
+/* control byte 1 */
+#define TSC2005_CMD			0x80
+#define TSC2005_CMD_NORMAL		0x00
+#define TSC2005_CMD_STOP		0x01
+#define TSC2005_CMD_12BIT		0x04
+
+/* control byte 0 */
+#define TSC2005_REG_READ		0x0001
+#define TSC2005_REG_PND0		0x0002
+#define TSC2005_REG_X			0x0000
+#define TSC2005_REG_Y			0x0008
+#define TSC2005_REG_Z1			0x0010
+#define TSC2005_REG_Z2			0x0018
+#define TSC2005_REG_TEMP_HIGH		0x0050
+#define TSC2005_REG_CFR0		0x0060
+#define TSC2005_REG_CFR1		0x0068
+#define TSC2005_REG_CFR2		0x0070
+
+/* configuration register 0 */
+#define TSC2005_CFR0_PRECHARGE_276US	0x0040
+#define TSC2005_CFR0_STABTIME_1MS	0x0300
+#define TSC2005_CFR0_CLOCK_1MHZ		0x1000
+#define TSC2005_CFR0_RESOLUTION12	0x2000
+#define TSC2005_CFR0_PENMODE		0x8000
+#define TSC2005_CFR0_INITVALUE		(TSC2005_CFR0_STABTIME_1MS    | \
+					 TSC2005_CFR0_CLOCK_1MHZ      | \
+					 TSC2005_CFR0_RESOLUTION12    | \
+					 TSC2005_CFR0_PRECHARGE_276US | \
+					 TSC2005_CFR0_PENMODE)
+
+/* bits common to both read and write of configuration register 0 */
+#define	TSC2005_CFR0_RW_MASK		0x3fff
+
+/* configuration register 1 */
+#define TSC2005_CFR1_BATCHDELAY_4MS	0x0003
+#define TSC2005_CFR1_INITVALUE		TSC2005_CFR1_BATCHDELAY_4MS
+
+/* configuration register 2 */
+#define TSC2005_CFR2_MAVE_Z		0x0004
+#define TSC2005_CFR2_MAVE_Y		0x0008
+#define TSC2005_CFR2_MAVE_X		0x0010
+#define TSC2005_CFR2_AVG_7		0x0800
+#define TSC2005_CFR2_MEDIUM_15		0x3000
+#define TSC2005_CFR2_INITVALUE		(TSC2005_CFR2_MAVE_X	| \
+					 TSC2005_CFR2_MAVE_Y	| \
+					 TSC2005_CFR2_MAVE_Z	| \
+					 TSC2005_CFR2_MEDIUM_15	| \
+					 TSC2005_CFR2_AVG_7)
+
+#define MAX_12BIT			0xfff
+#define TSC2005_SPI_MAX_SPEED_HZ	10000000
+#define TSC2005_PENUP_TIME_MS		40
+
+struct tsc2005_spi_rd {
+	struct spi_transfer	spi_xfer;
+	u32			spi_tx;
+	u32			spi_rx;
+};
+
+struct tsc2005 {
+	struct spi_device	*spi;
+
+	struct spi_message      spi_read_msg;
+	struct tsc2005_spi_rd	spi_x;
+	struct tsc2005_spi_rd	spi_y;
+	struct tsc2005_spi_rd	spi_z1;
+	struct tsc2005_spi_rd	spi_z2;
+
+	struct input_dev	*idev;
+	char			phys[32];
+
+	struct mutex		mutex;
+
+	/* raw copy of previous x,y,z */
+	int			in_x;
+	int			in_y;
+	int                     in_z1;
+	int			in_z2;
+
+	spinlock_t		lock;
+	struct timer_list	penup_timer;
+
+	unsigned int		esd_timeout;
+	struct delayed_work	esd_work;
+	unsigned long		last_valid_interrupt;
+
+	unsigned int		x_plate_ohm;
+
+	bool			opened;
+	bool			suspended;
+
+	bool			pen_down;
+
+	void			(*set_reset)(bool enable);
+};
+
+static int tsc2005_cmd(struct tsc2005 *ts, u8 cmd)
+{
+	u8 tx = TSC2005_CMD | TSC2005_CMD_12BIT | cmd;
+	struct spi_transfer xfer = {
+		.tx_buf		= &tx,
+		.len		= 1,
+		.bits_per_word	= 8,
+	};
+	struct spi_message msg;
+	int error;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	error = spi_sync(ts->spi, &msg);
+	if (error) {
+		dev_err(&ts->spi->dev, "%s: failed, command: %x, error: %d\n",
+			__func__, cmd, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static int tsc2005_write(struct tsc2005 *ts, u8 reg, u16 value)
+{
+	u32 tx = ((reg | TSC2005_REG_PND0) << 16) | value;
+	struct spi_transfer xfer = {
+		.tx_buf		= &tx,
+		.len		= 4,
+		.bits_per_word	= 24,
+	};
+	struct spi_message msg;
+	int error;
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&xfer, &msg);
+
+	error = spi_sync(ts->spi, &msg);
+	if (error) {
+		dev_err(&ts->spi->dev,
+			"%s: failed, register: %x, value: %x, error: %d\n",
+			__func__, reg, value, error);
+		return error;
+	}
+
+	return 0;
+}
+
+static void tsc2005_setup_read(struct tsc2005_spi_rd *rd, u8 reg, bool last)
+{
+	memset(rd, 0, sizeof(*rd));
+
+	rd->spi_tx		   = (reg | TSC2005_REG_READ) << 16;
+	rd->spi_xfer.tx_buf	   = &rd->spi_tx;
+	rd->spi_xfer.rx_buf	   = &rd->spi_rx;
+	rd->spi_xfer.len	   = 4;
+	rd->spi_xfer.bits_per_word = 24;
+	rd->spi_xfer.cs_change	   = !last;
+}
+
+static int tsc2005_read(struct tsc2005 *ts, u8 reg, u16 *value)
+{
+	struct tsc2005_spi_rd spi_rd;
+	struct spi_message msg;
+	int error;
+
+	tsc2005_setup_read(&spi_rd, reg, true);
+
+	spi_message_init(&msg);
+	spi_message_add_tail(&spi_rd.spi_xfer, &msg);
+
+	error = spi_sync(ts->spi, &msg);
+	if (error)
+		return error;
+
+	*value = spi_rd.spi_rx;
+	return 0;
+}
+
+static void tsc2005_update_pen_state(struct tsc2005 *ts,
+				     int x, int y, int pressure)
+{
+	if (pressure) {
+		input_report_abs(ts->idev, ABS_X, x);
+		input_report_abs(ts->idev, ABS_Y, y);
+		input_report_abs(ts->idev, ABS_PRESSURE, pressure);
+		if (!ts->pen_down) {
+			input_report_key(ts->idev, BTN_TOUCH, !!pressure);
+			ts->pen_down = true;
+		}
+	} else {
+		input_report_abs(ts->idev, ABS_PRESSURE, 0);
+		if (ts->pen_down) {
+			input_report_key(ts->idev, BTN_TOUCH, 0);
+			ts->pen_down = false;
+		}
+	}
+	input_sync(ts->idev);
+	dev_dbg(&ts->spi->dev, "point(%4d,%4d), pressure (%4d)\n", x, y,
+		pressure);
+}
+
+static irqreturn_t tsc2005_irq_thread(int irq, void *_ts)
+{
+	struct tsc2005 *ts = _ts;
+	unsigned long flags;
+	unsigned int pressure;
+	u32 x, y;
+	u32 z1, z2;
+	int error;
+
+	/* read the coordinates */
+	error = spi_sync(ts->spi, &ts->spi_read_msg);
+	if (unlikely(error))
+		goto out;
+
+	x = ts->spi_x.spi_rx;
+	y = ts->spi_y.spi_rx;
+	z1 = ts->spi_z1.spi_rx;
+	z2 = ts->spi_z2.spi_rx;
+
+	/* validate position */
+	if (unlikely(x > MAX_12BIT || y > MAX_12BIT))
+		goto out;
+
+	/* Skip reading if the pressure components are out of range */
+	if (unlikely(z1 == 0 || z2 > MAX_12BIT || z1 >= z2))
+		goto out;
+
+       /*
+	* Skip point if this is a pen down with the exact same values as
+	* the value before pen-up - that implies SPI fed us stale data
+	*/
+	if (!ts->pen_down &&
+	    ts->in_x == x && ts->in_y == y &&
+	    ts->in_z1 == z1 && ts->in_z2 == z2) {
+		goto out;
+	}
+
+	/*
+	 * At this point we are happy we have a valid and useful reading.
+	 * Remember it for later comparisons. We may now begin downsampling.
+	 */
+	ts->in_x = x;
+	ts->in_y = y;
+	ts->in_z1 = z1;
+	ts->in_z2 = z2;
+
+	/* Compute touch pressure resistance using equation #1 */
+	pressure = x * (z2 - z1) / z1;
+	pressure = pressure * ts->x_plate_ohm / 4096;
+	if (unlikely(pressure > MAX_12BIT))
+		goto out;
+
+	spin_lock_irqsave(&ts->lock, flags);
+
+	tsc2005_update_pen_state(ts, x, y, pressure);
+	mod_timer(&ts->penup_timer,
+		  jiffies + msecs_to_jiffies(TSC2005_PENUP_TIME_MS));
+
+	spin_unlock_irqrestore(&ts->lock, flags);
+
+	ts->last_valid_interrupt = jiffies;
+out:
+	return IRQ_HANDLED;
+}
+
+static void tsc2005_penup_timer(unsigned long data)
+{
+	struct tsc2005 *ts = (struct tsc2005 *)data;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ts->lock, flags);
+	tsc2005_update_pen_state(ts, 0, 0, 0);
+	spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static void tsc2005_start_scan(struct tsc2005 *ts)
+{
+	tsc2005_write(ts, TSC2005_REG_CFR0, TSC2005_CFR0_INITVALUE);
+	tsc2005_write(ts, TSC2005_REG_CFR1, TSC2005_CFR1_INITVALUE);
+	tsc2005_write(ts, TSC2005_REG_CFR2, TSC2005_CFR2_INITVALUE);
+	tsc2005_cmd(ts, TSC2005_CMD_NORMAL);
+}
+
+static void tsc2005_stop_scan(struct tsc2005 *ts)
+{
+	tsc2005_cmd(ts, TSC2005_CMD_STOP);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc2005_disable(struct tsc2005 *ts)
+{
+	tsc2005_stop_scan(ts);
+
+	disable_irq(ts->spi->irq);
+	del_timer_sync(&ts->penup_timer);
+
+	cancel_delayed_work_sync(&ts->esd_work);
+
+	enable_irq(ts->spi->irq);
+}
+
+/* must be called with ts->mutex held */
+static void __tsc2005_enable(struct tsc2005 *ts)
+{
+	tsc2005_start_scan(ts);
+
+	if (ts->esd_timeout && ts->set_reset) {
+		ts->last_valid_interrupt = jiffies;
+		schedule_delayed_work(&ts->esd_work,
+				round_jiffies_relative(
+					msecs_to_jiffies(ts->esd_timeout)));
+	}
+
+}
+
+static ssize_t tsc2005_selftest_show(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+	u16 temp_high;
+	u16 temp_high_orig;
+	u16 temp_high_test;
+	bool success = true;
+	int error;
+
+	mutex_lock(&ts->mutex);
+
+	/*
+	 * Test TSC2005 communications via temp high register.
+	 */
+	__tsc2005_disable(ts);
+
+	error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high_orig);
+	if (error) {
+		dev_warn(dev, "selftest failed: read error %d\n", error);
+		success = false;
+		goto out;
+	}
+
+	temp_high_test = (temp_high_orig - 1) & MAX_12BIT;
+
+	error = tsc2005_write(ts, TSC2005_REG_TEMP_HIGH, temp_high_test);
+	if (error) {
+		dev_warn(dev, "selftest failed: write error %d\n", error);
+		success = false;
+		goto out;
+	}
+
+	error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
+	if (error) {
+		dev_warn(dev, "selftest failed: read error %d after write\n",
+			 error);
+		success = false;
+		goto out;
+	}
+
+	if (temp_high != temp_high_test) {
+		dev_warn(dev, "selftest failed: %d != %d\n",
+			 temp_high, temp_high_test);
+		success = false;
+	}
+
+	/* hardware reset */
+	ts->set_reset(false);
+	usleep_range(100, 500); /* only 10us required */
+	ts->set_reset(true);
+
+	if (!success)
+		goto out;
+
+	/* test that the reset really happened */
+	error = tsc2005_read(ts, TSC2005_REG_TEMP_HIGH, &temp_high);
+	if (error) {
+		dev_warn(dev, "selftest failed: read error %d after reset\n",
+			 error);
+		success = false;
+		goto out;
+	}
+
+	if (temp_high != temp_high_orig) {
+		dev_warn(dev, "selftest failed after reset: %d != %d\n",
+			 temp_high, temp_high_orig);
+		success = false;
+	}
+
+out:
+	__tsc2005_enable(ts);
+	mutex_unlock(&ts->mutex);
+
+	return sprintf(buf, "%d\n", success);
+}
+
+static DEVICE_ATTR(selftest, S_IRUGO, tsc2005_selftest_show, NULL);
+
+static struct attribute *tsc2005_attrs[] = {
+	&dev_attr_selftest.attr,
+	NULL
+};
+
+static mode_t tsc2005_attr_is_visible(struct kobject *kobj,
+				      struct attribute *attr, int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+	mode_t mode = attr->mode;
+
+	if (attr == &dev_attr_selftest.attr) {
+		if (!ts->set_reset)
+			mode = 0;
+	}
+
+	return mode;
+}
+
+static const struct attribute_group tsc2005_attr_group = {
+	.is_visible	= tsc2005_attr_is_visible,
+	.attrs		= tsc2005_attrs,
+};
+
+static void tsc2005_esd_work(struct work_struct *work)
+{
+	struct tsc2005 *ts = container_of(work, struct tsc2005, esd_work.work);
+	int error;
+	u16 r;
+
+	if (!mutex_trylock(&ts->mutex)) {
+		/*
+		 * If the mutex is taken, it means that disable or enable is in
+		 * progress. In that case just reschedule the work. If the work
+		 * is not needed, it will be canceled by disable.
+		 */
+		goto reschedule;
+	}
+
+	if (time_is_after_jiffies(ts->last_valid_interrupt +
+				  msecs_to_jiffies(ts->esd_timeout)))
+		goto out;
+
+	/* We should be able to read register without disabling interrupts. */
+	error = tsc2005_read(ts, TSC2005_REG_CFR0, &r);
+	if (!error &&
+	    !((r ^ TSC2005_CFR0_INITVALUE) & TSC2005_CFR0_RW_MASK)) {
+		goto out;
+	}
+
+	/*
+	 * If we could not read our known value from configuration register 0
+	 * then we should reset the controller as if from power-up and start
+	 * scanning again.
+	 */
+	dev_info(&ts->spi->dev, "TSC2005 not responding - resetting\n");
+
+	disable_irq(ts->spi->irq);
+	del_timer_sync(&ts->penup_timer);
+
+	tsc2005_update_pen_state(ts, 0, 0, 0);
+
+	ts->set_reset(false);
+	usleep_range(100, 500); /* only 10us required */
+	ts->set_reset(true);
+
+	enable_irq(ts->spi->irq);
+	tsc2005_start_scan(ts);
+
+out:
+	mutex_unlock(&ts->mutex);
+reschedule:
+	/* re-arm the watchdog */
+	schedule_delayed_work(&ts->esd_work,
+			      round_jiffies_relative(
+					msecs_to_jiffies(ts->esd_timeout)));
+}
+
+static int tsc2005_open(struct input_dev *input)
+{
+	struct tsc2005 *ts = input_get_drvdata(input);
+
+	mutex_lock(&ts->mutex);
+
+	if (!ts->suspended)
+		__tsc2005_enable(ts);
+
+	ts->opened = true;
+
+	mutex_unlock(&ts->mutex);
+
+	return 0;
+}
+
+static void tsc2005_close(struct input_dev *input)
+{
+	struct tsc2005 *ts = input_get_drvdata(input);
+
+	mutex_lock(&ts->mutex);
+
+	if (!ts->suspended)
+		__tsc2005_disable(ts);
+
+	ts->opened = false;
+
+	mutex_unlock(&ts->mutex);
+}
+
+static void __devinit tsc2005_setup_spi_xfer(struct tsc2005 *ts)
+{
+	tsc2005_setup_read(&ts->spi_x, TSC2005_REG_X, false);
+	tsc2005_setup_read(&ts->spi_y, TSC2005_REG_Y, false);
+	tsc2005_setup_read(&ts->spi_z1, TSC2005_REG_Z1, false);
+	tsc2005_setup_read(&ts->spi_z2, TSC2005_REG_Z2, true);
+
+	spi_message_init(&ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_x.spi_xfer, &ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_y.spi_xfer, &ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_z1.spi_xfer, &ts->spi_read_msg);
+	spi_message_add_tail(&ts->spi_z2.spi_xfer, &ts->spi_read_msg);
+}
+
+static int __devinit tsc2005_probe(struct spi_device *spi)
+{
+	const struct tsc2005_platform_data *pdata = spi->dev.platform_data;
+	struct tsc2005 *ts;
+	struct input_dev *input_dev;
+	unsigned int max_x, max_y, max_p;
+	unsigned int fudge_x, fudge_y, fudge_p;
+	int error;
+
+	if (!pdata) {
+		dev_dbg(&spi->dev, "no platform data\n");
+		return -ENODEV;
+	}
+
+	fudge_x	= pdata->ts_x_fudge	   ? : 4;
+	fudge_y	= pdata->ts_y_fudge	   ? : 8;
+	fudge_p	= pdata->ts_pressure_fudge ? : 2;
+	max_x	= pdata->ts_x_max	   ? : MAX_12BIT;
+	max_y	= pdata->ts_y_max	   ? : MAX_12BIT;
+	max_p	= pdata->ts_pressure_max   ? : MAX_12BIT;
+
+	if (spi->irq <= 0) {
+		dev_dbg(&spi->dev, "no irq\n");
+		return -ENODEV;
+	}
+
+	spi->mode = SPI_MODE_0;
+	spi->bits_per_word = 8;
+	if (!spi->max_speed_hz)
+		spi->max_speed_hz = TSC2005_SPI_MAX_SPEED_HZ;
+
+	error = spi_setup(spi);
+	if (error)
+		return error;
+
+	ts = kzalloc(sizeof(*ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	ts->spi = spi;
+	ts->idev = input_dev;
+
+	ts->x_plate_ohm	= pdata->ts_x_plate_ohm	? : 280;
+	ts->esd_timeout	= pdata->esd_timeout_ms;
+	ts->set_reset	= pdata->set_reset;
+
+	mutex_init(&ts->mutex);
+
+	spin_lock_init(&ts->lock);
+	setup_timer(&ts->penup_timer, tsc2005_penup_timer, (unsigned long)ts);
+
+	INIT_DELAYED_WORK(&ts->esd_work, tsc2005_esd_work);
+
+	tsc2005_setup_spi_xfer(ts);
+
+	snprintf(ts->phys, sizeof(ts->phys),
+		 "%s/input-ts", dev_name(&spi->dev));
+
+	input_dev->name = "TSC2005 touchscreen";
+	input_dev->phys = ts->phys;
+	input_dev->id.bustype = BUS_SPI;
+	input_dev->dev.parent = &spi->dev;
+	input_dev->evbit[0] = BIT(EV_ABS) | BIT(EV_KEY);
+	input_dev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
+
+	input_set_abs_params(input_dev, ABS_X, 0, max_x, fudge_x, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, max_y, fudge_y, 0);
+	input_set_abs_params(input_dev, ABS_PRESSURE, 0, max_p, fudge_p, 0);
+
+	input_dev->open = tsc2005_open;
+	input_dev->close = tsc2005_close;
+
+	input_set_drvdata(input_dev, ts);
+
+	/* Ensure the touchscreen is off */
+	tsc2005_stop_scan(ts);
+
+	error = request_threaded_irq(spi->irq, NULL, tsc2005_irq_thread,
+				     IRQF_TRIGGER_RISING, "tsc2005", ts);
+	if (error) {
+		dev_err(&spi->dev, "Failed to request irq, err: %d\n", error);
+		goto err_free_mem;
+	}
+
+	spi_set_drvdata(spi, ts);
+	error = sysfs_create_group(&spi->dev.kobj, &tsc2005_attr_group);
+	if (error) {
+		dev_err(&spi->dev,
+			"Failed to create sysfs attributes, err: %d\n", error);
+		goto err_clear_drvdata;
+	}
+
+	error = input_register_device(ts->idev);
+	if (error) {
+		dev_err(&spi->dev,
+			"Failed to register input device, err: %d\n", error);
+		goto err_remove_sysfs;
+	}
+
+	irq_set_irq_wake(spi->irq, 1);
+	return 0;
+
+err_remove_sysfs:
+	sysfs_remove_group(&spi->dev.kobj, &tsc2005_attr_group);
+err_clear_drvdata:
+	spi_set_drvdata(spi, NULL);
+	free_irq(spi->irq, ts);
+err_free_mem:
+	input_free_device(input_dev);
+	kfree(ts);
+	return error;
+}
+
+static int __devexit tsc2005_remove(struct spi_device *spi)
+{
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+
+	sysfs_remove_group(&ts->spi->dev.kobj, &tsc2005_attr_group);
+
+	free_irq(ts->spi->irq, ts);
+	input_unregister_device(ts->idev);
+	kfree(ts);
+
+	spi_set_drvdata(spi, NULL);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tsc2005_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+
+	mutex_lock(&ts->mutex);
+
+	if (!ts->suspended && ts->opened)
+		__tsc2005_disable(ts);
+
+	ts->suspended = true;
+
+	mutex_unlock(&ts->mutex);
+
+	return 0;
+}
+
+static int tsc2005_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct tsc2005 *ts = spi_get_drvdata(spi);
+
+	mutex_lock(&ts->mutex);
+
+	if (ts->suspended && ts->opened)
+		__tsc2005_enable(ts);
+
+	ts->suspended = false;
+
+	mutex_unlock(&ts->mutex);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(tsc2005_pm_ops, tsc2005_suspend, tsc2005_resume);
+
+static struct spi_driver tsc2005_driver = {
+	.driver	= {
+		.name	= "tsc2005",
+		.owner	= THIS_MODULE,
+		.pm	= &tsc2005_pm_ops,
+	},
+	.probe	= tsc2005_probe,
+	.remove	= __devexit_p(tsc2005_remove),
+};
+
+static int __init tsc2005_init(void)
+{
+	return spi_register_driver(&tsc2005_driver);
+}
+module_init(tsc2005_init);
+
+static void __exit tsc2005_exit(void)
+{
+	spi_unregister_driver(&tsc2005_driver);
+}
+module_exit(tsc2005_exit);
+
+MODULE_AUTHOR("Lauri Leukkunen <lauri.leukkunen@nokia.com>");
+MODULE_DESCRIPTION("TSC2005 Touchscreen Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/ucb1400_ts.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/ucb1400_ts.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/ucb1400_ts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/ucb1400_ts.c	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  *  Copyright:	MontaVista Software, Inc.
  *
  * Spliting done by: Marek Vasut <marek.vasut@gmail.com>
- * If something doesnt work and it worked before spliting, e-mail me,
+ * If something doesn't work and it worked before spliting, e-mail me,
  * dont bother Nicolas please ;-)
  *
  * This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm831x-ts.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm831x-ts.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm831x-ts.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm831x-ts.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,421 @@
+/*
+ * Touchscreen driver for WM831x PMICs
+ *
+ * Copyright 2011 Wolfson Microelectronics plc.
+ * Author: 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 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/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/string.h>
+#include <linux/pm.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/mfd/wm831x/core.h>
+#include <linux/mfd/wm831x/irq.h>
+#include <linux/mfd/wm831x/pdata.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+/*
+ * R16424 (0x4028) - Touch Control 1
+ */
+#define WM831X_TCH_ENA                          0x8000  /* TCH_ENA */
+#define WM831X_TCH_CVT_ENA                      0x4000  /* TCH_CVT_ENA */
+#define WM831X_TCH_SLPENA                       0x1000  /* TCH_SLPENA */
+#define WM831X_TCH_Z_ENA                        0x0400  /* TCH_Z_ENA */
+#define WM831X_TCH_Y_ENA                        0x0200  /* TCH_Y_ENA */
+#define WM831X_TCH_X_ENA                        0x0100  /* TCH_X_ENA */
+#define WM831X_TCH_DELAY_MASK                   0x00E0  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_DELAY_SHIFT                       5  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_DELAY_WIDTH                       3  /* TCH_DELAY - [7:5] */
+#define WM831X_TCH_RATE_MASK                    0x001F  /* TCH_RATE - [4:0] */
+#define WM831X_TCH_RATE_SHIFT                        0  /* TCH_RATE - [4:0] */
+#define WM831X_TCH_RATE_WIDTH                        5  /* TCH_RATE - [4:0] */
+
+/*
+ * R16425 (0x4029) - Touch Control 2
+ */
+#define WM831X_TCH_PD_WK                        0x2000  /* TCH_PD_WK */
+#define WM831X_TCH_5WIRE                        0x1000  /* TCH_5WIRE */
+#define WM831X_TCH_PDONLY                       0x0800  /* TCH_PDONLY */
+#define WM831X_TCH_ISEL                         0x0100  /* TCH_ISEL */
+#define WM831X_TCH_RPU_MASK                     0x000F  /* TCH_RPU - [3:0] */
+#define WM831X_TCH_RPU_SHIFT                         0  /* TCH_RPU - [3:0] */
+#define WM831X_TCH_RPU_WIDTH                         4  /* TCH_RPU - [3:0] */
+
+/*
+ * R16426-8 (0x402A-C) - Touch Data X/Y/X
+ */
+#define WM831X_TCH_PD                           0x8000  /* TCH_PD1 */
+#define WM831X_TCH_DATA_MASK                    0x0FFF  /* TCH_DATA - [11:0] */
+#define WM831X_TCH_DATA_SHIFT                        0  /* TCH_DATA - [11:0] */
+#define WM831X_TCH_DATA_WIDTH                       12  /* TCH_DATA - [11:0] */
+
+struct wm831x_ts {
+	struct input_dev *input_dev;
+	struct wm831x *wm831x;
+	unsigned int data_irq;
+	unsigned int pd_irq;
+	bool pressure;
+	bool pen_down;
+	struct work_struct pd_data_work;
+};
+
+static void wm831x_pd_data_work(struct work_struct *work)
+{
+	struct wm831x_ts *wm831x_ts =
+		container_of(work, struct wm831x_ts, pd_data_work);
+
+	if (wm831x_ts->pen_down) {
+		enable_irq(wm831x_ts->data_irq);
+		dev_dbg(wm831x_ts->wm831x->dev, "IRQ PD->DATA done\n");
+	} else {
+		enable_irq(wm831x_ts->pd_irq);
+		dev_dbg(wm831x_ts->wm831x->dev, "IRQ DATA->PD done\n");
+	}
+}
+
+static irqreturn_t wm831x_ts_data_irq(int irq, void *irq_data)
+{
+	struct wm831x_ts *wm831x_ts = irq_data;
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+	static int data_types[] = { ABS_X, ABS_Y, ABS_PRESSURE };
+	u16 data[3];
+	int count;
+	int i, ret;
+
+	if (wm831x_ts->pressure)
+		count = 3;
+	else
+		count = 2;
+
+	wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+			WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
+
+	ret = wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count,
+			       data);
+	if (ret != 0) {
+		dev_err(wm831x->dev, "Failed to read touch data: %d\n",
+			ret);
+		return IRQ_NONE;
+	}
+
+	/*
+	 * We get a pen down reading on every reading, report pen up if any
+	 * individual reading does so.
+	 */
+	wm831x_ts->pen_down = true;
+	for (i = 0; i < count; i++) {
+		if (!(data[i] & WM831X_TCH_PD)) {
+			wm831x_ts->pen_down = false;
+			continue;
+		}
+		input_report_abs(wm831x_ts->input_dev, data_types[i],
+				 data[i] & WM831X_TCH_DATA_MASK);
+	}
+
+	if (!wm831x_ts->pen_down) {
+		/* Switch from data to pen down */
+		dev_dbg(wm831x->dev, "IRQ DATA->PD\n");
+
+		disable_irq_nosync(wm831x_ts->data_irq);
+
+		/* Don't need data any more */
+		wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+				WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+				WM831X_TCH_Z_ENA, 0);
+
+		/* Flush any final samples that arrived while reading */
+		wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+				WM831X_TCHDATA_EINT, WM831X_TCHDATA_EINT);
+
+		wm831x_bulk_read(wm831x, WM831X_TOUCH_DATA_X, count, data);
+
+		if (wm831x_ts->pressure)
+			input_report_abs(wm831x_ts->input_dev,
+					 ABS_PRESSURE, 0);
+
+		input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 0);
+
+		schedule_work(&wm831x_ts->pd_data_work);
+	} else {
+		input_report_key(wm831x_ts->input_dev, BTN_TOUCH, 1);
+	}
+
+	input_sync(wm831x_ts->input_dev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wm831x_ts_pen_down_irq(int irq, void *irq_data)
+{
+	struct wm831x_ts *wm831x_ts = irq_data;
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+	int ena = 0;
+
+	if (wm831x_ts->pen_down)
+		return IRQ_HANDLED;
+
+	disable_irq_nosync(wm831x_ts->pd_irq);
+
+	/* Start collecting data */
+	if (wm831x_ts->pressure)
+		ena |= WM831X_TCH_Z_ENA;
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA,
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA | ena);
+
+	wm831x_set_bits(wm831x, WM831X_INTERRUPT_STATUS_1,
+			WM831X_TCHPD_EINT, WM831X_TCHPD_EINT);
+
+	wm831x_ts->pen_down = true;
+
+	/* Switch from pen down to data */
+	dev_dbg(wm831x->dev, "IRQ PD->DATA\n");
+	schedule_work(&wm831x_ts->pd_data_work);
+
+	return IRQ_HANDLED;
+}
+
+static int wm831x_ts_input_open(struct input_dev *idev)
+{
+	struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_ENA | WM831X_TCH_CVT_ENA |
+			WM831X_TCH_X_ENA | WM831X_TCH_Y_ENA |
+			WM831X_TCH_Z_ENA, WM831X_TCH_ENA);
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_CVT_ENA, WM831X_TCH_CVT_ENA);
+
+	return 0;
+}
+
+static void wm831x_ts_input_close(struct input_dev *idev)
+{
+	struct wm831x_ts *wm831x_ts = input_get_drvdata(idev);
+	struct wm831x *wm831x = wm831x_ts->wm831x;
+
+	/* Shut the controller down, disabling all other functionality too */
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_ENA | WM831X_TCH_X_ENA |
+			WM831X_TCH_Y_ENA | WM831X_TCH_Z_ENA, 0);
+
+	/* Make sure any pending IRQs are done, the above will prevent
+	 * new ones firing.
+	 */
+	synchronize_irq(wm831x_ts->data_irq);
+	synchronize_irq(wm831x_ts->pd_irq);
+
+	/* Make sure the IRQ completion work is quiesced */
+	flush_work_sync(&wm831x_ts->pd_data_work);
+
+	/* If we ended up with the pen down then make sure we revert back
+	 * to pen detection state for the next time we start up.
+	 */
+	if (wm831x_ts->pen_down) {
+		disable_irq(wm831x_ts->data_irq);
+		enable_irq(wm831x_ts->pd_irq);
+		wm831x_ts->pen_down = false;
+	}
+}
+
+static __devinit int wm831x_ts_probe(struct platform_device *pdev)
+{
+	struct wm831x_ts *wm831x_ts;
+	struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
+	struct wm831x_pdata *core_pdata = dev_get_platdata(pdev->dev.parent);
+	struct wm831x_touch_pdata *pdata = NULL;
+	struct input_dev *input_dev;
+	int error, irqf;
+
+	if (core_pdata)
+		pdata = core_pdata->touch;
+
+	wm831x_ts = kzalloc(sizeof(struct wm831x_ts), GFP_KERNEL);
+	input_dev = input_allocate_device();
+	if (!wm831x_ts || !input_dev) {
+		error = -ENOMEM;
+		goto err_alloc;
+	}
+
+	wm831x_ts->wm831x = wm831x;
+	wm831x_ts->input_dev = input_dev;
+	INIT_WORK(&wm831x_ts->pd_data_work, wm831x_pd_data_work);
+
+	/*
+	 * If we have a direct IRQ use it, otherwise use the interrupt
+	 * from the WM831x IRQ controller.
+	 */
+	if (pdata && pdata->data_irq)
+		wm831x_ts->data_irq = pdata->data_irq;
+	else
+		wm831x_ts->data_irq = platform_get_irq_byname(pdev, "TCHDATA");
+
+	if (pdata && pdata->pd_irq)
+		wm831x_ts->pd_irq = pdata->pd_irq;
+	else
+		wm831x_ts->pd_irq = platform_get_irq_byname(pdev, "TCHPD");
+
+	if (pdata)
+		wm831x_ts->pressure = pdata->pressure;
+	else
+		wm831x_ts->pressure = true;
+
+	/* Five wire touchscreens can't report pressure */
+	if (pdata && pdata->fivewire) {
+		wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+				WM831X_TCH_5WIRE, WM831X_TCH_5WIRE);
+
+		/* Pressure measurements are not possible for five wire mode */
+		WARN_ON(pdata->pressure && pdata->fivewire);
+		wm831x_ts->pressure = false;
+	} else {
+		wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+				WM831X_TCH_5WIRE, 0);
+	}
+
+	if (pdata) {
+		switch (pdata->isel) {
+		default:
+			dev_err(&pdev->dev, "Unsupported ISEL setting: %d\n",
+				pdata->isel);
+			/* Fall through */
+		case 200:
+		case 0:
+			wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+					WM831X_TCH_ISEL, 0);
+			break;
+		case 400:
+			wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+					WM831X_TCH_ISEL, WM831X_TCH_ISEL);
+			break;
+		}
+	}
+
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_2,
+			WM831X_TCH_PDONLY, 0);
+
+	/* Default to 96 samples/sec */
+	wm831x_set_bits(wm831x, WM831X_TOUCH_CONTROL_1,
+			WM831X_TCH_RATE_MASK, 6);
+
+	if (pdata && pdata->data_irqf)
+		irqf = pdata->data_irqf;
+	else
+		irqf = IRQF_TRIGGER_HIGH;
+
+	error = request_threaded_irq(wm831x_ts->data_irq,
+				     NULL, wm831x_ts_data_irq,
+				     irqf | IRQF_ONESHOT,
+				     "Touchscreen data", wm831x_ts);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to request data IRQ %d: %d\n",
+			wm831x_ts->data_irq, error);
+		goto err_alloc;
+	}
+	disable_irq(wm831x_ts->data_irq);
+
+	if (pdata && pdata->pd_irqf)
+		irqf = pdata->pd_irqf;
+	else
+		irqf = IRQF_TRIGGER_HIGH;
+
+	error = request_threaded_irq(wm831x_ts->pd_irq,
+				     NULL, wm831x_ts_pen_down_irq,
+				     irqf | IRQF_ONESHOT,
+				     "Touchscreen pen down", wm831x_ts);
+	if (error) {
+		dev_err(&pdev->dev, "Failed to request pen down IRQ %d: %d\n",
+			wm831x_ts->pd_irq, error);
+		goto err_data_irq;
+	}
+
+	/* set up touch configuration */
+	input_dev->name = "WM831x touchscreen";
+	input_dev->phys = "wm831x";
+	input_dev->open = wm831x_ts_input_open;
+	input_dev->close = wm831x_ts_input_close;
+
+	__set_bit(EV_ABS, input_dev->evbit);
+	__set_bit(EV_KEY, input_dev->evbit);
+	__set_bit(BTN_TOUCH, input_dev->keybit);
+
+	input_set_abs_params(input_dev, ABS_X, 0, 4095, 5, 0);
+	input_set_abs_params(input_dev, ABS_Y, 0, 4095, 5, 0);
+	if (wm831x_ts->pressure)
+		input_set_abs_params(input_dev, ABS_PRESSURE, 0, 4095, 5, 0);
+
+	input_set_drvdata(input_dev, wm831x_ts);
+	input_dev->dev.parent = &pdev->dev;
+
+	error = input_register_device(input_dev);
+	if (error)
+		goto err_pd_irq;
+
+	platform_set_drvdata(pdev, wm831x_ts);
+	return 0;
+
+err_pd_irq:
+	free_irq(wm831x_ts->pd_irq, wm831x_ts);
+err_data_irq:
+	free_irq(wm831x_ts->data_irq, wm831x_ts);
+err_alloc:
+	input_free_device(input_dev);
+	kfree(wm831x_ts);
+
+	return error;
+}
+
+static __devexit int wm831x_ts_remove(struct platform_device *pdev)
+{
+	struct wm831x_ts *wm831x_ts = platform_get_drvdata(pdev);
+
+	free_irq(wm831x_ts->pd_irq, wm831x_ts);
+	free_irq(wm831x_ts->data_irq, wm831x_ts);
+	input_unregister_device(wm831x_ts->input_dev);
+	kfree(wm831x_ts);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver wm831x_ts_driver = {
+	.driver = {
+		.name = "wm831x-touch",
+		.owner = THIS_MODULE,
+	},
+	.probe = wm831x_ts_probe,
+	.remove = __devexit_p(wm831x_ts_remove),
+};
+
+static int __init wm831x_ts_init(void)
+{
+	return platform_driver_register(&wm831x_ts_driver);
+}
+module_init(wm831x_ts_init);
+
+static void __exit wm831x_ts_exit(void)
+{
+	platform_driver_unregister(&wm831x_ts_driver);
+}
+module_exit(wm831x_ts_exit);
+
+/* Module information */
+MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
+MODULE_DESCRIPTION("WM831x PMIC touchscreen driver");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:wm831x-touch");
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm9705.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm9705.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm9705.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm9705.c	2011-05-19 00:06:34.000000000 -0400
@@ -306,7 +306,7 @@
 	dig2 = wm->dig[2];
 
 	if (enable) {
-		/* continous mode */
+		/* continuous mode */
 		if (wm->mach_ops->acc_startup &&
 		    (ret = wm->mach_ops->acc_startup(wm)) < 0)
 			return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm9712.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm9712.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm9712.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm9712.c	2011-05-19 00:06:34.000000000 -0400
@@ -419,7 +419,7 @@
 	dig2 = wm->dig[2];
 
 	if (enable) {
-		/* continous mode */
+		/* continuous mode */
 		if (wm->mach_ops->acc_startup) {
 			ret = wm->mach_ops->acc_startup(wm);
 			if (ret < 0)
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm9713.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm9713.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm9713.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm9713.c	2011-05-19 00:06:34.000000000 -0400
@@ -431,7 +431,7 @@
 	dig3 = wm->dig[2];
 
 	if (enable) {
-		/* continous mode */
+		/* continuous mode */
 		if (wm->mach_ops->acc_startup &&
 			(ret = wm->mach_ops->acc_startup(wm)) < 0)
 			return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm97xx-core.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm97xx-core.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/wm97xx-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/wm97xx-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -335,7 +335,7 @@
 	 */
 	if (!wm->mach_ops->acc_enabled || wm->mach_ops->acc_pen_down) {
 		if (wm->pen_is_down && !pen_was_down) {
-			/* Data is not availiable immediately on pen down */
+			/* Data is not available immediately on pen down */
 			queue_delayed_work(wm->ts_workq, &wm->ts_reader, 1);
 		}
 
@@ -354,7 +354,7 @@
  * Codec PENDOWN irq handler
  *
  * We have to disable the codec interrupt in the handler because it
- * can take upto 1ms to clear the interrupt source. We schedule a task
+ * can take up to 1ms to clear the interrupt source. We schedule a task
  * in a work queue to do the actual interaction with the chip.  The
  * interrupt is then enabled again in the slow handler when the source
  * has been cleared.
diff -druN linux-libre-2.6.38-gnu/drivers/input/touchscreen/zylonite-wm97xx.c linux-libre-2.6.39-gnu/drivers/input/touchscreen/zylonite-wm97xx.c
--- linux-libre-2.6.38-gnu/drivers/input/touchscreen/zylonite-wm97xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/touchscreen/zylonite-wm97xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,7 +193,7 @@
 		gpio_touch_irq = mfp_to_gpio(MFP_PIN_GPIO26);
 
 	wm->pen_irq = IRQ_GPIO(gpio_touch_irq);
-	set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(IRQ_GPIO(gpio_touch_irq), IRQ_TYPE_EDGE_BOTH);
 
 	wm97xx_config_gpio(wm, WM97XX_GPIO_13, WM97XX_GPIO_IN,
 			   WM97XX_GPIO_POL_HIGH,
diff -druN linux-libre-2.6.38-gnu/drivers/input/xen-kbdfront.c linux-libre-2.6.39-gnu/drivers/input/xen-kbdfront.c
--- linux-libre-2.6.38-gnu/drivers/input/xen-kbdfront.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/input/xen-kbdfront.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,364 +0,0 @@
-/*
- * Xen para-virtual input device
- *
- * Copyright (C) 2005 Anthony Liguori <aliguori@us.ibm.com>
- * Copyright (C) 2006-2008 Red Hat, Inc., Markus Armbruster <armbru@redhat.com>
- *
- *  Based on linux/drivers/input/mouse/sermouse.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.
- */
-
-/*
- * TODO:
- *
- * Switch to grant tables together with xen-fbfront.c.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/module.h>
-#include <linux/input.h>
-#include <linux/slab.h>
-
-#include <asm/xen/hypervisor.h>
-
-#include <xen/xen.h>
-#include <xen/events.h>
-#include <xen/page.h>
-#include <xen/interface/io/fbif.h>
-#include <xen/interface/io/kbdif.h>
-#include <xen/xenbus.h>
-
-struct xenkbd_info {
-	struct input_dev *kbd;
-	struct input_dev *ptr;
-	struct xenkbd_page *page;
-	int irq;
-	struct xenbus_device *xbdev;
-	char phys[32];
-};
-
-static int xenkbd_remove(struct xenbus_device *);
-static int xenkbd_connect_backend(struct xenbus_device *, struct xenkbd_info *);
-static void xenkbd_disconnect_backend(struct xenkbd_info *);
-
-/*
- * Note: if you need to send out events, see xenfb_do_update() for how
- * to do that.
- */
-
-static irqreturn_t input_handler(int rq, void *dev_id)
-{
-	struct xenkbd_info *info = dev_id;
-	struct xenkbd_page *page = info->page;
-	__u32 cons, prod;
-
-	prod = page->in_prod;
-	if (prod == page->in_cons)
-		return IRQ_HANDLED;
-	rmb();			/* ensure we see ring contents up to prod */
-	for (cons = page->in_cons; cons != prod; cons++) {
-		union xenkbd_in_event *event;
-		struct input_dev *dev;
-		event = &XENKBD_IN_RING_REF(page, cons);
-
-		dev = info->ptr;
-		switch (event->type) {
-		case XENKBD_TYPE_MOTION:
-			input_report_rel(dev, REL_X, event->motion.rel_x);
-			input_report_rel(dev, REL_Y, event->motion.rel_y);
-			if (event->motion.rel_z)
-				input_report_rel(dev, REL_WHEEL,
-						 -event->motion.rel_z);
-			break;
-		case XENKBD_TYPE_KEY:
-			dev = NULL;
-			if (test_bit(event->key.keycode, info->kbd->keybit))
-				dev = info->kbd;
-			if (test_bit(event->key.keycode, info->ptr->keybit))
-				dev = info->ptr;
-			if (dev)
-				input_report_key(dev, event->key.keycode,
-						 event->key.pressed);
-			else
-				pr_warning("unhandled keycode 0x%x\n",
-					   event->key.keycode);
-			break;
-		case XENKBD_TYPE_POS:
-			input_report_abs(dev, ABS_X, event->pos.abs_x);
-			input_report_abs(dev, ABS_Y, event->pos.abs_y);
-			if (event->pos.rel_z)
-				input_report_rel(dev, REL_WHEEL,
-						 -event->pos.rel_z);
-			break;
-		}
-		if (dev)
-			input_sync(dev);
-	}
-	mb();			/* ensure we got ring contents */
-	page->in_cons = cons;
-	notify_remote_via_irq(info->irq);
-
-	return IRQ_HANDLED;
-}
-
-static int __devinit xenkbd_probe(struct xenbus_device *dev,
-				  const struct xenbus_device_id *id)
-{
-	int ret, i;
-	struct xenkbd_info *info;
-	struct input_dev *kbd, *ptr;
-
-	info = kzalloc(sizeof(*info), GFP_KERNEL);
-	if (!info) {
-		xenbus_dev_fatal(dev, -ENOMEM, "allocating info structure");
-		return -ENOMEM;
-	}
-	dev_set_drvdata(&dev->dev, info);
-	info->xbdev = dev;
-	info->irq = -1;
-	snprintf(info->phys, sizeof(info->phys), "xenbus/%s", dev->nodename);
-
-	info->page = (void *)__get_free_page(GFP_KERNEL | __GFP_ZERO);
-	if (!info->page)
-		goto error_nomem;
-
-	/* keyboard */
-	kbd = input_allocate_device();
-	if (!kbd)
-		goto error_nomem;
-	kbd->name = "Xen Virtual Keyboard";
-	kbd->phys = info->phys;
-	kbd->id.bustype = BUS_PCI;
-	kbd->id.vendor = 0x5853;
-	kbd->id.product = 0xffff;
-	kbd->evbit[0] = BIT(EV_KEY);
-	for (i = KEY_ESC; i < KEY_UNKNOWN; i++)
-		set_bit(i, kbd->keybit);
-	for (i = KEY_OK; i < KEY_MAX; i++)
-		set_bit(i, kbd->keybit);
-
-	ret = input_register_device(kbd);
-	if (ret) {
-		input_free_device(kbd);
-		xenbus_dev_fatal(dev, ret, "input_register_device(kbd)");
-		goto error;
-	}
-	info->kbd = kbd;
-
-	/* pointing device */
-	ptr = input_allocate_device();
-	if (!ptr)
-		goto error_nomem;
-	ptr->name = "Xen Virtual Pointer";
-	ptr->phys = info->phys;
-	ptr->id.bustype = BUS_PCI;
-	ptr->id.vendor = 0x5853;
-	ptr->id.product = 0xfffe;
-	ptr->evbit[0] = BIT(EV_KEY) | BIT(EV_REL) | BIT(EV_ABS);
-	for (i = BTN_LEFT; i <= BTN_TASK; i++)
-		set_bit(i, ptr->keybit);
-	ptr->relbit[0] = BIT(REL_X) | BIT(REL_Y) | BIT(REL_WHEEL);
-	input_set_abs_params(ptr, ABS_X, 0, XENFB_WIDTH, 0, 0);
-	input_set_abs_params(ptr, ABS_Y, 0, XENFB_HEIGHT, 0, 0);
-
-	ret = input_register_device(ptr);
-	if (ret) {
-		input_free_device(ptr);
-		xenbus_dev_fatal(dev, ret, "input_register_device(ptr)");
-		goto error;
-	}
-	info->ptr = ptr;
-
-	ret = xenkbd_connect_backend(dev, info);
-	if (ret < 0)
-		goto error;
-
-	return 0;
-
- error_nomem:
-	ret = -ENOMEM;
-	xenbus_dev_fatal(dev, ret, "allocating device memory");
- error:
-	xenkbd_remove(dev);
-	return ret;
-}
-
-static int xenkbd_resume(struct xenbus_device *dev)
-{
-	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-
-	xenkbd_disconnect_backend(info);
-	memset(info->page, 0, PAGE_SIZE);
-	return xenkbd_connect_backend(dev, info);
-}
-
-static int xenkbd_remove(struct xenbus_device *dev)
-{
-	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-
-	xenkbd_disconnect_backend(info);
-	if (info->kbd)
-		input_unregister_device(info->kbd);
-	if (info->ptr)
-		input_unregister_device(info->ptr);
-	free_page((unsigned long)info->page);
-	kfree(info);
-	return 0;
-}
-
-static int xenkbd_connect_backend(struct xenbus_device *dev,
-				  struct xenkbd_info *info)
-{
-	int ret, evtchn;
-	struct xenbus_transaction xbt;
-
-	ret = xenbus_alloc_evtchn(dev, &evtchn);
-	if (ret)
-		return ret;
-	ret = bind_evtchn_to_irqhandler(evtchn, input_handler,
-					0, dev->devicetype, info);
-	if (ret < 0) {
-		xenbus_free_evtchn(dev, evtchn);
-		xenbus_dev_fatal(dev, ret, "bind_evtchn_to_irqhandler");
-		return ret;
-	}
-	info->irq = ret;
-
- again:
-	ret = xenbus_transaction_start(&xbt);
-	if (ret) {
-		xenbus_dev_fatal(dev, ret, "starting transaction");
-		return ret;
-	}
-	ret = xenbus_printf(xbt, dev->nodename, "page-ref", "%lu",
-			    virt_to_mfn(info->page));
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_printf(xbt, dev->nodename, "event-channel", "%u",
-			    evtchn);
-	if (ret)
-		goto error_xenbus;
-	ret = xenbus_transaction_end(xbt, 0);
-	if (ret) {
-		if (ret == -EAGAIN)
-			goto again;
-		xenbus_dev_fatal(dev, ret, "completing transaction");
-		return ret;
-	}
-
-	xenbus_switch_state(dev, XenbusStateInitialised);
-	return 0;
-
- error_xenbus:
-	xenbus_transaction_end(xbt, 1);
-	xenbus_dev_fatal(dev, ret, "writing xenstore");
-	return ret;
-}
-
-static void xenkbd_disconnect_backend(struct xenkbd_info *info)
-{
-	if (info->irq >= 0)
-		unbind_from_irqhandler(info->irq, info);
-	info->irq = -1;
-}
-
-static void xenkbd_backend_changed(struct xenbus_device *dev,
-				   enum xenbus_state backend_state)
-{
-	struct xenkbd_info *info = dev_get_drvdata(&dev->dev);
-	int ret, val;
-
-	switch (backend_state) {
-	case XenbusStateInitialising:
-	case XenbusStateInitialised:
-	case XenbusStateReconfiguring:
-	case XenbusStateReconfigured:
-	case XenbusStateUnknown:
-	case XenbusStateClosed:
-		break;
-
-	case XenbusStateInitWait:
-InitWait:
-		ret = xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				   "feature-abs-pointer", "%d", &val);
-		if (ret < 0)
-			val = 0;
-		if (val) {
-			ret = xenbus_printf(XBT_NIL, info->xbdev->nodename,
-					    "request-abs-pointer", "1");
-			if (ret)
-				pr_warning("can't request abs-pointer\n");
-		}
-		xenbus_switch_state(dev, XenbusStateConnected);
-		break;
-
-	case XenbusStateConnected:
-		/*
-		 * Work around xenbus race condition: If backend goes
-		 * through InitWait to Connected fast enough, we can
-		 * get Connected twice here.
-		 */
-		if (dev->state != XenbusStateConnected)
-			goto InitWait; /* no InitWait seen yet, fudge it */
-
-		/* Set input abs params to match backend screen res */
-		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				 "width", "%d", &val) > 0)
-			input_set_abs_params(info->ptr, ABS_X, 0, val, 0, 0);
-
-		if (xenbus_scanf(XBT_NIL, info->xbdev->otherend,
-				 "height", "%d", &val) > 0)
-			input_set_abs_params(info->ptr, ABS_Y, 0, val, 0, 0);
-
-		break;
-
-	case XenbusStateClosing:
-		xenbus_frontend_closed(dev);
-		break;
-	}
-}
-
-static const struct xenbus_device_id xenkbd_ids[] = {
-	{ "vkbd" },
-	{ "" }
-};
-
-static struct xenbus_driver xenkbd_driver = {
-	.name = "vkbd",
-	.owner = THIS_MODULE,
-	.ids = xenkbd_ids,
-	.probe = xenkbd_probe,
-	.remove = xenkbd_remove,
-	.resume = xenkbd_resume,
-	.otherend_changed = xenkbd_backend_changed,
-};
-
-static int __init xenkbd_init(void)
-{
-	if (!xen_pv_domain())
-		return -ENODEV;
-
-	/* Nothing to do if running in dom0. */
-	if (xen_initial_domain())
-		return -ENODEV;
-
-	return xenbus_register_frontend(&xenkbd_driver);
-}
-
-static void __exit xenkbd_cleanup(void)
-{
-	xenbus_unregister_driver(&xenkbd_driver);
-}
-
-module_init(xenkbd_init);
-module_exit(xenkbd_cleanup);
-
-MODULE_DESCRIPTION("Xen virtual keyboard/pointer device frontend");
-MODULE_LICENSE("GPL");
-MODULE_ALIAS("xen:vkbd");
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/capi/capi.c linux-libre-2.6.39-gnu/drivers/isdn/capi/capi.c
--- linux-libre-2.6.38-gnu/drivers/isdn/capi/capi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/capi/capi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1219,16 +1219,10 @@
 	return mp->outbytes;
 }
 
-static int capinc_tty_ioctl(struct tty_struct *tty, struct file * file,
+static int capinc_tty_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
-	int error = 0;
-	switch (cmd) {
-	default:
-		error = n_tty_ioctl_helper(tty, file, cmd, arg);
-		break;
-	}
-	return error;
+	return -ENOIOCTLCMD;
 }
 
 static void capinc_tty_set_termios(struct tty_struct *tty, struct ktermios * old)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/gigaset/interface.c linux-libre-2.6.39-gnu/drivers/isdn/gigaset/interface.c
--- linux-libre-2.6.38-gnu/drivers/isdn/gigaset/interface.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/gigaset/interface.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,15 +115,15 @@
 
 static int  if_open(struct tty_struct *tty, struct file *filp);
 static void if_close(struct tty_struct *tty, struct file *filp);
-static int  if_ioctl(struct tty_struct *tty, struct file *file,
+static int  if_ioctl(struct tty_struct *tty,
 		     unsigned int cmd, unsigned long arg);
 static int  if_write_room(struct tty_struct *tty);
 static int  if_chars_in_buffer(struct tty_struct *tty);
 static void if_throttle(struct tty_struct *tty);
 static void if_unthrottle(struct tty_struct *tty);
 static void if_set_termios(struct tty_struct *tty, struct ktermios *old);
-static int  if_tiocmget(struct tty_struct *tty, struct file *file);
-static int  if_tiocmset(struct tty_struct *tty, struct file *file,
+static int  if_tiocmget(struct tty_struct *tty);
+static int  if_tiocmset(struct tty_struct *tty,
 			unsigned int set, unsigned int clear);
 static int  if_write(struct tty_struct *tty,
 		     const unsigned char *buf, int count);
@@ -205,7 +205,7 @@
 	module_put(cs->driver->owner);
 }
 
-static int if_ioctl(struct tty_struct *tty, struct file *file,
+static int if_ioctl(struct tty_struct *tty,
 		    unsigned int cmd, unsigned long arg)
 {
 	struct cardstate *cs;
@@ -280,7 +280,7 @@
 	return retval;
 }
 
-static int if_tiocmget(struct tty_struct *tty, struct file *file)
+static int if_tiocmget(struct tty_struct *tty)
 {
 	struct cardstate *cs;
 	int retval;
@@ -303,7 +303,7 @@
 	return retval;
 }
 
-static int if_tiocmset(struct tty_struct *tty, struct file *file,
+static int if_tiocmset(struct tty_struct *tty,
 		       unsigned int set, unsigned int clear)
 {
 	struct cardstate *cs;
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/gigaset/ser-gigaset.c linux-libre-2.6.39-gnu/drivers/isdn/gigaset/ser-gigaset.c
--- linux-libre-2.6.38-gnu/drivers/isdn/gigaset/ser-gigaset.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/gigaset/ser-gigaset.c	2011-05-19 00:06:34.000000000 -0400
@@ -440,7 +440,7 @@
 	if (!set && !clear)
 		return 0;
 	gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
-	return tty->ops->tiocmset(tty, NULL, set, clear);
+	return tty->ops->tiocmset(tty, set, clear);
 }
 
 static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/divacapi.h linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/divacapi.h
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/divacapi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/divacapi.h	2011-05-19 00:06:34.000000000 -0400
@@ -673,7 +673,7 @@
 
 
 /*------------------------------------------------------------------*/
-/* auxilliary states for supplementary services                     */
+/* auxiliary states for supplementary services                     */
 /*------------------------------------------------------------------*/
 
 #define IDLE                0
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/io.h linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/io.h
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
   -------------------------------------------------------------------------- */
 struct _ISDN_ADAPTER {
  void             (* DIRequest)(PISDN_ADAPTER, ENTITY *) ;
- int                 State ; /* from NT4 1.srv, a good idea, but  a poor achievment */
+ int                 State ; /* from NT4 1.srv, a good idea, but  a poor achievement */
  int                 Initialized ;
  int         RegisteredWithDidd ;
  int                 Unavailable ;  /* callback function possible? */
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/message.c linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/message.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/message.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/message.c	2011-05-19 00:06:34.000000000 -0400
@@ -2639,7 +2639,7 @@
     }
     else
     {
-      /* local reply if assign unsuccessfull
+      /* local reply if assign unsuccessful
          or B3 protocol allows only one layer 3 connection
            and already connected
              or B2 protocol not any LAPD
@@ -8189,7 +8189,7 @@
       dlc[ 0] = 15;
       if(b2_config->length >= 8) { /* PIAFS control abilities */
         dlc[ 7] = 10; 
-        dlc[16] = 2; /* Length of PIAFS extention */
+        dlc[16] = 2; /* Length of PIAFS extension */
         dlc[17] = PIAFS_UDATA_ABILITIES; /* control (UDATA) ability */
         dlc[18] = b2_config_parms[4].info[0]; /* value */
         dlc[ 0] = 18;
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/pc.h linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/pc.h
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/pc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/pc.h	2011-05-19 00:06:34.000000000 -0400
@@ -701,7 +701,7 @@
 #define PROTCAP_FREE12    0x1000  /* not used                            */
 #define PROTCAP_FREE13    0x2000  /* not used                            */
 #define PROTCAP_FREE14    0x4000  /* not used                            */
-#define PROTCAP_EXTENSION 0x8000  /* used for future extentions          */
+#define PROTCAP_EXTENSION 0x8000  /* used for future extensions          */
 /* -----------------------------------------------------------* */
 /* Onhook data transmission ETS30065901 */
 /* Message Type */
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/um_idi.c linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/um_idi.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/eicon/um_idi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/eicon/um_idi.c	2011-05-19 00:06:34.000000000 -0400
@@ -363,7 +363,7 @@
 
 		if ((ret = (*cp_fn) (os_handle, dst, data, length)) >= 0) {
 			/*
-			   Acknowledge only if read was successfull
+			   Acknowledge only if read was successful
 			 */
 			diva_data_q_ack_segment4read(q);
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c linux-libre-2.6.39-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/mISDN/hfcmulti.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,7 @@
  *	-> See hfc_multi.h for HFC_IO_MODE_* values
  *	By default, the IO mode is pci memory IO (MEMIO).
  *	Some cards require specific IO mode, so it cannot be changed.
- *	It may be usefull to set IO mode to register io (REGIO) to solve
+ *	It may be useful to set IO mode to register io (REGIO) to solve
  *	PCI bridge problems.
  *	If unsure, don't give this parameter.
  *
@@ -903,7 +903,7 @@
 /*
  * Speech Design resync feature
  * NOTE: This is called sometimes outside interrupt handler.
- * We must lock irqsave, so no other interrupt (other card) will occurr!
+ * We must lock irqsave, so no other interrupt (other card) will occur!
  * Also multiple interrupts may nest, so must lock each access (lists, card)!
  */
 static inline void
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hardware/mISDN/hfcpci.c linux-libre-2.6.39-gnu/drivers/isdn/hardware/mISDN/hfcpci.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hardware/mISDN/hfcpci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hardware/mISDN/hfcpci.c	2011-05-19 00:06:34.000000000 -0400
@@ -272,7 +272,7 @@
 	 * D- and monitor/CI channel are not enabled
 	 * STIO1 is used as output for data, B1+B2 from ST->IOM+HFC
 	 * STIO2 is used as data input, B1+B2 from IOM->ST
-	 * ST B-channel send disabled -> continous 1s
+	 * ST B-channel send disabled -> continuous 1s
 	 * The IOM slots are always enabled
 	 */
 	if (test_bit(HFC_CFG_PCM, &hc->cfg)) {
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/hfc_pci.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/hfc_pci.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/hfc_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/hfc_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -146,7 +146,7 @@
 	/* D- and monitor/CI channel are not enabled */
 	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
 	/* STIO2 is used as data input, B1+B2 from IOM->ST */
-	/* ST B-channel send disabled -> continous 1s */
+	/* ST B-channel send disabled -> continuous 1s */
 	/* The IOM slots are always enabled */
 	cs->hw.hfcpci.conn = 0x36;	/* set data flow directions */
 	Write_hfc(cs, HFCPCI_CONNECT, cs->hw.hfcpci.conn);
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/hfc_sx.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/hfc_sx.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/hfc_sx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/hfc_sx.c	2011-05-19 00:06:34.000000000 -0400
@@ -399,7 +399,7 @@
 	/* D- and monitor/CI channel are not enabled */
 	/* STIO1 is used as output for data, B1+B2 from ST->IOM+HFC */
 	/* STIO2 is used as data input, B1+B2 from IOM->ST */
-	/* ST B-channel send disabled -> continous 1s */
+	/* ST B-channel send disabled -> continuous 1s */
 	/* The IOM slots are always enabled */
 	cs->hw.hfcsx.conn = 0x36;	/* set data flow directions */
 	Write_hfc(cs, HFCSX_CONNECT, cs->hw.hfcsx.conn);
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/hfc_usb.h linux-libre-2.6.39-gnu/drivers/isdn/hisax/hfc_usb.h
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/hfc_usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/hfc_usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -126,7 +126,7 @@
 
 
 /*
- * device dependant information to support different
+ * device dependent information to support different
  * ISDN Ta's using the HFC-S USB chip
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/l3dss1.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/l3dss1.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/l3dss1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/l3dss1.c	2011-05-19 00:06:34.000000000 -0400
@@ -1595,7 +1595,7 @@
 	 * Bearer Capabilities
 	 */
 	p = skb->data;
-	/* only the first occurence 'll be detected ! */
+	/* only the first occurrence 'll be detected ! */
 	if ((p = findie(p, skb->len, 0x04, 0))) {
 		if ((p[1] < 2) || (p[1] > 11))
 			err = 1;
@@ -2161,7 +2161,7 @@
 
 /***********************************************/
 /* handle special commands for this protocol.  */
-/* Examples are call independant services like */
+/* Examples are call independent services like */
 /* remote operations with dummy  callref.      */
 /***********************************************/
 static int l3dss1_cmd_global(struct PStack *st, isdn_ctrl *ic)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/l3ni1.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/l3ni1.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/l3ni1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/l3ni1.c	2011-05-19 00:06:34.000000000 -0400
@@ -1449,7 +1449,7 @@
 	 * Bearer Capabilities
 	 */
 	p = skb->data;
-	/* only the first occurence 'll be detected ! */
+	/* only the first occurrence 'll be detected ! */
 	if ((p = findie(p, skb->len, 0x04, 0))) {
 		if ((p[1] < 2) || (p[1] > 11))
 			err = 1;
@@ -2017,7 +2017,7 @@
 
 /***********************************************/
 /* handle special commands for this protocol.  */
-/* Examples are call independant services like */
+/* Examples are call independent services like */
 /* remote operations with dummy  callref.      */
 /***********************************************/
 static int l3ni1_cmd_global(struct PStack *st, isdn_ctrl *ic)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/Makefile linux-libre-2.6.39-gnu/drivers/isdn/hisax/Makefile
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
 
 # Define maximum number of cards
 
-EXTRA_CFLAGS      += -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
+ccflags-y      := -DHISAX_MAX_CARDS=$(CONFIG_HISAX_MAX_CARDS)
 
 obj-$(CONFIG_ISDN_DRV_HISAX)		+= hisax.o
 obj-$(CONFIG_HISAX_SEDLBAUER_CS)	+= sedlbauer_cs.o
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/nj_s.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/nj_s.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/nj_s.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/nj_s.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 		return(0);
 	}
 	/* the TJ300 and TJ320 must be detected, the IRQ handling is different
-	 * unfortunatly the chips use the same device ID, but the TJ320 has
+	 * unfortunately the chips use the same device ID, but the TJ320 has
 	 * the bit20 in status PCI cfg register set
 	 */
 	pci_read_config_dword(dev_netjet, 0x04, &cfg);
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/st5481_b.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/st5481_b.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/st5481_b.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/st5481_b.c	2011-05-19 00:06:34.000000000 -0400
@@ -124,7 +124,7 @@
 }
 
 /*
- * Start transfering (flags or data) on the B channel, since
+ * Start transferring (flags or data) on the B channel, since
  * FIFO counters has been set to a non-zero value.
  */
 static void st5481B_start_xfer(void *context)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/st5481_usb.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/st5481_usb.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/st5481_usb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/st5481_usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -470,7 +470,7 @@
 
 /*
  * Decode frames received on the B/D channel.
- * Note that this function will be called continously
+ * Note that this function will be called continuously
  * with 64Kbit/s / 16Kbit/s of data and hence it will be 
  * called 50 times per second with 20 ISOC descriptors. 
  * Called at interrupt.
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hisax/teles_cs.c linux-libre-2.6.39-gnu/drivers/isdn/hisax/teles_cs.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hisax/teles_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hisax/teles_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
     Also inspired by ELSA PCMCIA driver 
     by Klaus Lichtenwalder <Lichtenwalder@ACM.org>
     
-    Extentions to new hisax_pcmcia by Karsten Keil
+    Extensions to new hisax_pcmcia by Karsten Keil
 
     minor changes to be compatible with kernel 2.4.x
     by Jan.Schubert@GMX.li
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/hysdn/hysdn_sched.c linux-libre-2.6.39-gnu/drivers/isdn/hysdn/hysdn_sched.c
--- linux-libre-2.6.38-gnu/drivers/isdn/hysdn/hysdn_sched.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/hysdn/hysdn_sched.c	2011-05-19 00:06:34.000000000 -0400
@@ -143,7 +143,7 @@
 /* send one config line to the card and return 0 if successful, otherwise a */
 /* negative error code.                                                      */
 /* The function works with timeouts perhaps not giving the greatest speed    */
-/* sending the line, but this should be meaningless beacuse only some lines  */
+/* sending the line, but this should be meaningless because only some lines  */
 /* are to be sent and this happens very seldom.                              */
 /*****************************************************************************/
 int
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/i4l/isdn_net.c linux-libre-2.6.39-gnu/drivers/isdn/i4l/isdn_net.c
--- linux-libre-2.6.38-gnu/drivers/isdn/i4l/isdn_net.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/i4l/isdn_net.c	2011-05-19 00:06:34.000000000 -0400
@@ -1530,7 +1530,7 @@
 		printk (KERN_WARNING
 				"UPDOWN: Line protocol on Interface %s,"
 				" changed state to down\n", lp->netdev->dev->name);
-		/* should stop routing higher-level data accross */
+		/* should stop routing higher-level data across */
 	} else if ((!lp->cisco_line_state) &&
 		(myseq_diff >= 0) && (myseq_diff <= 2)) {
 		/* line down -> up */
@@ -1538,7 +1538,7 @@
 		printk (KERN_WARNING
 				"UPDOWN: Line protocol on Interface %s,"
 				" changed state to up\n", lp->netdev->dev->name);
-		/* restart routing higher-level data accross */
+		/* restart routing higher-level data across */
 	}
 
 	if (lp->cisco_debserint)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/i4l/isdn_ppp.c linux-libre-2.6.39-gnu/drivers/isdn/i4l/isdn_ppp.c
--- linux-libre-2.6.38-gnu/drivers/isdn/i4l/isdn_ppp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/i4l/isdn_ppp.c	2011-05-19 00:06:34.000000000 -0400
@@ -1514,7 +1514,7 @@
 #define MP_LONGSEQ_MAXBIT	((MP_LONGSEQ_MASK+1)>>1)
 #define MP_SHORTSEQ_MAXBIT	((MP_SHORTSEQ_MASK+1)>>1)
 
-/* sequence-wrap safe comparisions (for long sequence)*/ 
+/* sequence-wrap safe comparisons (for long sequence)*/
 #define MP_LT(a,b)	((a-b)&MP_LONGSEQ_MAXBIT)
 #define MP_LE(a,b) 	!((b-a)&MP_LONGSEQ_MAXBIT)
 #define MP_GT(a,b) 	((b-a)&MP_LONGSEQ_MAXBIT)
@@ -1746,7 +1746,7 @@
 		 * then next fragment should be the start of new reassembly
 		 * if sequence is contiguous, but we haven't reassembled yet,
 		 * keep going.
-		 * if sequence is not contiguous, either clear everyting
+		 * if sequence is not contiguous, either clear everything
 		 * below low watermark and set start to the next frag or
 		 * clear start ptr.
 		 */ 
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/i4l/isdn_tty.c linux-libre-2.6.39-gnu/drivers/isdn/i4l/isdn_tty.c
--- linux-libre-2.6.38-gnu/drivers/isdn/i4l/isdn_tty.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/i4l/isdn_tty.c	2011-05-19 00:06:34.000000000 -0400
@@ -792,7 +792,7 @@
 }
 
 /* isdn_tty_resume() tries to resume a suspended call
- * setup of the lower levels before that. unfortunatly here is no
+ * setup of the lower levels before that. unfortunately here is no
  * checking for compatibility of used protocols implemented by Q931
  * It does the same things like isdn_tty_dial, the last command
  * is different, may be we can merge it.
@@ -1345,7 +1345,7 @@
 
 
 static int
-isdn_tty_tiocmget(struct tty_struct *tty, struct file *file)
+isdn_tty_tiocmget(struct tty_struct *tty)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
 	u_char control, status;
@@ -1372,7 +1372,7 @@
 }
 
 static int
-isdn_tty_tiocmset(struct tty_struct *tty, struct file *file,
+isdn_tty_tiocmset(struct tty_struct *tty,
 		unsigned int set, unsigned int clear)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
@@ -1413,8 +1413,7 @@
 }
 
 static int
-isdn_tty_ioctl(struct tty_struct *tty, struct file *file,
-	       uint cmd, ulong arg)
+isdn_tty_ioctl(struct tty_struct *tty, uint cmd, ulong arg)
 {
 	modem_info *info = (modem_info *) tty->driver_data;
 	int retval;
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/isdnloop/isdnloop.c linux-libre-2.6.39-gnu/drivers/isdn/isdnloop/isdnloop.c
--- linux-libre-2.6.38-gnu/drivers/isdn/isdnloop/isdnloop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/isdnloop/isdnloop.c	2011-05-19 00:06:34.000000000 -0400
@@ -954,7 +954,7 @@
 /*
  * Put command-strings into the of the 'card'. In reality, execute them
  * right in place by calling isdnloop_parse_cmd(). Also copy every
- * command to the read message ringbuffer, preceeding it with a '>'.
+ * command to the read message ringbuffer, preceding it with a '>'.
  * These mesagges can be read at /dev/isdnctrl.
  *
  * Parameter:
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_cmx.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_cmx.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_cmx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_cmx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1513,7 +1513,7 @@
 	/* -> if echo is NOT enabled */
 	if (!dsp->echo.software) {
 		/*
-		 * -> substract rx-data from conf-data,
+		 * -> subtract rx-data from conf-data,
 		 * if tx-data is available, mix
 		 */
 		while (r != rr && t != tt) {
@@ -1572,7 +1572,7 @@
 send_packet:
 	/*
 	 * send tx-data if enabled - don't filter,
-	 * becuase we want what we send, not what we filtered
+	 * because we want what we send, not what we filtered
 	 */
 	if (dsp->tx_data) {
 		if (tx_data_only) {
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_core.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_core.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,7 @@
  *
  * The CMX has special functions for conferences with one, two and more
  * members. It will allow different types of data flow. Receive and transmit
- * data to/form upper layer may be swithed on/off individually without loosing
+ * data to/form upper layer may be swithed on/off individually without losing
  * features of CMX, Tones and DTMF.
  *
  * Echo Cancellation: Sometimes we like to cancel echo from the interface.
@@ -127,9 +127,9 @@
  *
  * If all used features can be realized in hardware, and if transmit and/or
  * receive data ist disabled, the card may not send/receive any data at all.
- * Not receiving is usefull if only announcements are played. Not sending is
- * usefull if an answering machine records audio. Not sending and receiving is
- * usefull during most states of the call. If supported by hardware, tones
+ * Not receiving is useful if only announcements are played. Not sending is
+ * useful if an answering machine records audio. Not sending and receiving is
+ * useful during most states of the call. If supported by hardware, tones
  * will be played without cpu load. Small PBXs and NT-Mode applications will
  * not need expensive hardware when processing calls.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_dtmf.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_dtmf.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_dtmf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_dtmf.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
  * tested it allot. it even works with very short tones (40ms). the only
  * disadvantage is, that it doesn't work good with different volumes of both
  * tones. this will happen, if accoustically coupled dialers are used.
- * it sometimes detects tones during speach, which is normal for decoders.
+ * it sometimes detects tones during speech, which is normal for decoders.
  * use sequences to given commands during calls.
  *
  * dtmf - points to a structure of the current dtmf state
@@ -244,7 +244,7 @@
 		if (result[i] < tresh) {
 			lowgroup = -1;
 			highgroup = -1;
-			break;  /* noise inbetween */
+			break;  /* noise in between */
 		}
 		/* good level found. This is allowed only one time per group */
 		if (i < NCOEFF/2) {
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp.h linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp.h
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 /* options may be:
  *
  * bit 0 = use ulaw instead of alaw
- * bit 1 = enable hfc hardware accelleration for all channels
+ * bit 1 = enable hfc hardware acceleration for all channels
  *
  */
 #define DSP_OPT_ULAW		(1<<0)
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_tones.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_tones.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/dsp_tones.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/dsp_tones.c	2011-05-19 00:06:34.000000000 -0400
@@ -394,7 +394,7 @@
 	while (len) {
 		/* find sample to start with */
 		while (42) {
-			/* warp arround */
+			/* wrap around */
 			if (!pat->seq[index]) {
 				count = 0;
 				index = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/hwchannel.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/hwchannel.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/hwchannel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/hwchannel.c	2011-05-19 00:06:34.000000000 -0400
@@ -206,7 +206,7 @@
 	hh->id = id;
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
-			"fushing!\n", bch);
+			"flushing!\n", bch);
 		skb_queue_purge(&bch->rqueue);
 		bch->rcount = 0;
 		return;
@@ -231,7 +231,7 @@
 {
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
-			"fushing!\n", bch);
+			"flushing!\n", bch);
 		skb_queue_purge(&bch->rqueue);
 		bch->rcount = 0;
 	}
@@ -279,7 +279,7 @@
 
 	if (bch->rcount >= 64) {
 		printk(KERN_WARNING "B-channel %p receive queue overflow, "
-			"fushing!\n", bch);
+			"flushing!\n", bch);
 		skb_queue_purge(&bch->rqueue);
 		bch->rcount = 0;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/l1oip_core.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/l1oip_core.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/l1oip_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/l1oip_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,7 +179,7 @@
 - Time Base = Timestamp of first sample in frame
 The "Time Base" is used to rearange packets and to detect packet loss.
 The 16 bits are sent in network order (MSB first) and count 1/8000 th of a
-second. This causes a wrap arround each 8,192 seconds. There is no requirement
+second. This causes a wrap around each 8,192 seconds. There is no requirement
 for the initial "Time Base", but 0 should be used for the first packet.
 In case of HDLC data, this timestamp counts the packet or byte number.
 
@@ -205,7 +205,7 @@
 
 If the ondemand parameter is given, the remote IP is set to 0 on timeout.
 This will stop keepalive traffic to remote. If the remote is online again,
-traffic will continue to the remote address. This is usefull for road warriors.
+traffic will continue to the remote address. This is useful for road warriors.
 This feature only works with ID set, otherwhise it is highly unsecure.
 
 
@@ -590,7 +590,7 @@
 			return;
 		}
 	} else
-		mlen = len-2; /* single frame, substract timebase */
+		mlen = len-2; /* single frame, subtract timebase */
 
 	if (len < 2) {
 		printk(KERN_WARNING "%s: packet error - packet too short, time "
diff -druN linux-libre-2.6.38-gnu/drivers/isdn/mISDN/layer2.c linux-libre-2.6.39-gnu/drivers/isdn/mISDN/layer2.c
--- linux-libre-2.6.38-gnu/drivers/isdn/mISDN/layer2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/isdn/mISDN/layer2.c	2011-05-19 00:06:34.000000000 -0400
@@ -1864,7 +1864,7 @@
 		psapi >>= 2;
 		ptei >>= 1;
 		if (psapi != l2->sapi) {
-			/* not our bussiness */
+			/* not our business */
 			if (*debug & DEBUG_L2)
 				printk(KERN_DEBUG "%s: sapi %d/%d mismatch\n",
 					__func__, psapi, l2->sapi);
@@ -1872,7 +1872,7 @@
 			return 0;
 		}
 		if ((ptei != l2->tei) && (ptei != GROUP_TEI)) {
-			/* not our bussiness */
+			/* not our business */
 			if (*debug & DEBUG_L2)
 				printk(KERN_DEBUG "%s: tei %d/%d mismatch\n",
 					__func__, ptei, l2->tei);
diff -druN linux-libre-2.6.38-gnu/drivers/Kconfig linux-libre-2.6.39-gnu/drivers/Kconfig
--- linux-libre-2.6.38-gnu/drivers/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -117,4 +117,6 @@
 source "drivers/platform/Kconfig"
 
 source "drivers/clk/Kconfig"
+
+source "drivers/hwspinlock/Kconfig"
 endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/leds/Kconfig linux-libre-2.6.39-gnu/drivers/leds/Kconfig
--- linux-libre-2.6.38-gnu/drivers/leds/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,16 @@
 	  This option enables support for LEDs driven using outputs
 	  of the dedicated PWM controller found on newer Atmel SOCs.
 
+config LEDS_LM3530
+	tristate "LCD Backlight driver for LM3530"
+	depends on LEDS_CLASS
+	depends on I2C
+	help
+	  This option enables support for the LCD backlight using
+	  LM3530 ambient light sensor chip. This ALS chip can be
+	  controlled manually or using PWM input or using ambient
+	  light automatically.
+
 config LEDS_LOCOMO
 	tristate "LED Support for Locomo device"
 	depends on LEDS_CLASS
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-88pm860x.c linux-libre-2.6.39-gnu/drivers/leds/leds-88pm860x.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-88pm860x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-88pm860x.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/leds.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
 
 #define LED_PWM_SHIFT		(3)
@@ -118,7 +119,8 @@
 
 	struct pm860x_led *led;
 	struct pm860x_chip *chip;
-	int mask;
+	unsigned char buf[3];
+	int mask, ret;
 
 	led = container_of(work, struct pm860x_led, work);
 	chip = led->chip;
@@ -128,16 +130,27 @@
 			pm860x_set_bits(led->i2c, __led_off(led->port),
 					LED_CURRENT_MASK, led->iset);
 		}
+		pm860x_set_bits(led->i2c, __blink_off(led->port),
+				LED_BLINK_MASK, LED_ON_CONTINUOUS);
 		mask = __blink_ctl_mask(led->port);
 		pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, mask);
-	} else if (led->brightness == 0) {
-		pm860x_set_bits(led->i2c, __led_off(led->port),
-				LED_CURRENT_MASK, 0);
-		mask = __blink_ctl_mask(led->port);
-		pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
 	}
 	pm860x_set_bits(led->i2c, __led_off(led->port), LED_PWM_MASK,
 			led->brightness);
+
+	if (led->brightness == 0) {
+		pm860x_bulk_read(led->i2c, __led_off(led->port), 3, buf);
+		ret = buf[0] & LED_PWM_MASK;
+		ret |= buf[1] & LED_PWM_MASK;
+		ret |= buf[2] & LED_PWM_MASK;
+		if (ret == 0) {
+			/* unset current since no led is lighting */
+			pm860x_set_bits(led->i2c, __led_off(led->port),
+					LED_CURRENT_MASK, 0);
+			mask = __blink_ctl_mask(led->port);
+			pm860x_set_bits(led->i2c, PM8606_WLED3B, mask, 0);
+		}
+	}
 	led->current_brightness = led->brightness;
 	dev_dbg(chip->dev, "Update LED. (reg:%d, brightness:%d)\n",
 		__led_off(led->port), led->brightness);
@@ -153,31 +166,12 @@
 	schedule_work(&data->work);
 }
 
-static int __check_device(struct pm860x_led_pdata *pdata, char *name)
-{
-	struct pm860x_led_pdata *p = pdata;
-	int ret = -EINVAL;
-
-	while (p && p->id) {
-		if ((p->id != PM8606_ID_LED) || (p->flags < 0))
-			break;
-
-		if (!strncmp(name, pm860x_led_name[p->flags],
-			MFD_NAME_SIZE)) {
-			ret = (int)p->flags;
-			break;
-		}
-		p++;
-	}
-	return ret;
-}
-
 static int pm860x_led_probe(struct platform_device *pdev)
 {
 	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_platform_data *pm860x_pdata;
 	struct pm860x_led_pdata *pdata;
 	struct pm860x_led *data;
+	struct mfd_cell *cell;
 	struct resource *res;
 	int ret;
 
@@ -187,10 +181,11 @@
 		return -EINVAL;
 	}
 
-	if (pdev->dev.parent->platform_data) {
-		pm860x_pdata = pdev->dev.parent->platform_data;
-		pdata = pm860x_pdata->led;
-	} else {
+	cell = pdev->dev.platform_data;
+	if (cell == NULL)
+		return -ENODEV;
+	pdata = cell->mfd_data;
+	if (pdata == NULL) {
 		dev_err(&pdev->dev, "No platform data!\n");
 		return -EINVAL;
 	}
@@ -198,12 +193,12 @@
 	data = kzalloc(sizeof(struct pm860x_led), GFP_KERNEL);
 	if (data == NULL)
 		return -ENOMEM;
-	strncpy(data->name, res->name, MFD_NAME_SIZE);
+	strncpy(data->name, res->name, MFD_NAME_SIZE - 1);
 	dev_set_drvdata(&pdev->dev, data);
 	data->chip = chip;
 	data->i2c = (chip->id == CHIP_PM8606) ? chip->client : chip->companion;
 	data->iset = pdata->iset;
-	data->port = __check_device(pdata, data->name);
+	data->port = pdata->flags;
 	if (data->port < 0) {
 		dev_err(&pdev->dev, "check device failed\n");
 		kfree(data);
@@ -221,6 +216,7 @@
 		dev_err(&pdev->dev, "Failed to register LED: %d\n", ret);
 		goto out;
 	}
+	pm860x_led_set(&data->cdev, 0);
 	return 0;
 out:
 	kfree(data);
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-bd2802.c linux-libre-2.6.39-gnu/drivers/leds/leds-bd2802.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-bd2802.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-bd2802.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 #include <linux/leds.h>
 #include <linux/leds-bd2802.h>
 #include <linux/slab.h>
-
+#include <linux/pm.h>
 
 #define LED_CTL(rgb2en, rgb1en) ((rgb2en) << 4 | ((rgb1en) << 0))
 
@@ -319,20 +319,6 @@
 	bd2802_update_state(led, id, color, BD2802_OFF);
 }
 
-static void bd2802_restore_state(struct bd2802_led *led)
-{
-	int i;
-
-	for (i = 0; i < LED_NUM; i++) {
-		if (led->led[i].r)
-			bd2802_turn_on(led, i, RED, led->led[i].r);
-		if (led->led[i].g)
-			bd2802_turn_on(led, i, GREEN, led->led[i].g);
-		if (led->led[i].b)
-			bd2802_turn_on(led, i, BLUE, led->led[i].b);
-	}
-}
-
 #define BD2802_SET_REGISTER(reg_addr, reg_name)				\
 static ssize_t bd2802_store_reg##reg_addr(struct device *dev,		\
 	struct device_attribute *attr, const char *buf, size_t count)	\
@@ -761,8 +747,25 @@
 	return 0;
 }
 
-static int bd2802_suspend(struct i2c_client *client, pm_message_t mesg)
+#ifdef CONFIG_PM
+
+static void bd2802_restore_state(struct bd2802_led *led)
 {
+	int i;
+
+	for (i = 0; i < LED_NUM; i++) {
+		if (led->led[i].r)
+			bd2802_turn_on(led, i, RED, led->led[i].r);
+		if (led->led[i].g)
+			bd2802_turn_on(led, i, GREEN, led->led[i].g);
+		if (led->led[i].b)
+			bd2802_turn_on(led, i, BLUE, led->led[i].b);
+	}
+}
+
+static int bd2802_suspend(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
 	struct bd2802_led *led = i2c_get_clientdata(client);
 
 	gpio_set_value(led->pdata->reset_gpio, 0);
@@ -770,8 +773,9 @@
 	return 0;
 }
 
-static int bd2802_resume(struct i2c_client *client)
+static int bd2802_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct bd2802_led *led = i2c_get_clientdata(client);
 
 	if (!bd2802_is_all_off(led) || led->adf_on) {
@@ -782,6 +786,12 @@
 	return 0;
 }
 
+static SIMPLE_DEV_PM_OPS(bd2802_pm, bd2802_suspend, bd2802_resume);
+#define BD2802_PM (&bd2802_pm)
+#else		/* CONFIG_PM */
+#define BD2802_PM NULL
+#endif
+
 static const struct i2c_device_id bd2802_id[] = {
 	{ "BD2802", 0 },
 	{ }
@@ -791,11 +801,10 @@
 static struct i2c_driver bd2802_i2c_driver = {
 	.driver	= {
 		.name	= "BD2802",
+		.pm	= BD2802_PM,
 	},
 	.probe		= bd2802_probe,
 	.remove		= __exit_p(bd2802_remove),
-	.suspend	= bd2802_suspend,
-	.resume		= bd2802_resume,
 	.id_table	= bd2802_id,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-gpio.c linux-libre-2.6.39-gnu/drivers/leds/leds-gpio.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,8 @@
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/leds.h>
+#include <linux/of_platform.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/workqueue.h>
 
@@ -151,96 +153,34 @@
 	gpio_free(led->gpio);
 }
 
-#ifdef CONFIG_LEDS_GPIO_PLATFORM
-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;
-	int i, ret = 0;
-
-	if (!pdata)
-		return -EBUSY;
-
-	leds_data = kzalloc(sizeof(struct gpio_led_data) * pdata->num_leds,
-				GFP_KERNEL);
-	if (!leds_data)
-		return -ENOMEM;
-
-	for (i = 0; i < pdata->num_leds; i++) {
-		ret = create_gpio_led(&pdata->leds[i], &leds_data[i],
-				      &pdev->dev, pdata->gpio_blink_set);
-		if (ret < 0)
-			goto err;
-	}
-
-	platform_set_drvdata(pdev, leds_data);
-
-	return 0;
-
-err:
-	for (i = i - 1; i >= 0; i--)
-		delete_gpio_led(&leds_data[i]);
-
-	kfree(leds_data);
-
-	return ret;
-}
+struct gpio_leds_priv {
+	int num_leds;
+	struct gpio_led_data leds[];
+};
 
-static int __devexit gpio_led_remove(struct platform_device *pdev)
+static inline int sizeof_gpio_leds_priv(int num_leds)
 {
-	int i;
-	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
-	struct gpio_led_data *leds_data;
-
-	leds_data = platform_get_drvdata(pdev);
-
-	for (i = 0; i < pdata->num_leds; i++)
-		delete_gpio_led(&leds_data[i]);
-
-	kfree(leds_data);
-
-	return 0;
+	return sizeof(struct gpio_leds_priv) +
+		(sizeof(struct gpio_led_data) * num_leds);
 }
 
-static struct platform_driver gpio_led_driver = {
-	.probe		= gpio_led_probe,
-	.remove		= __devexit_p(gpio_led_remove),
-	.driver		= {
-		.name	= "leds-gpio",
-		.owner	= THIS_MODULE,
-	},
-};
-
-MODULE_ALIAS("platform:leds-gpio");
-#endif /* CONFIG_LEDS_GPIO_PLATFORM */
-
 /* Code to create from OpenFirmware platform devices */
 #ifdef CONFIG_LEDS_GPIO_OF
-#include <linux/of_platform.h>
-#include <linux/of_gpio.h>
-
-struct gpio_led_of_platform_data {
-	int num_leds;
-	struct gpio_led_data led_data[];
-};
-
-static int __devinit of_gpio_leds_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
 {
-	struct device_node *np = ofdev->dev.of_node, *child;
-	struct gpio_led_of_platform_data *pdata;
+	struct device_node *np = pdev->dev.of_node, *child;
+	struct gpio_leds_priv *priv;
 	int count = 0, ret;
 
-	/* count LEDs defined by this device, so we know how much to allocate */
+	/* count LEDs in this device, so we know how much to allocate */
 	for_each_child_of_node(np, child)
 		count++;
 	if (!count)
-		return 0; /* or ENODEV? */
+		return NULL;
 
-	pdata = kzalloc(sizeof(*pdata) + sizeof(struct gpio_led_data) * count,
-			GFP_KERNEL);
-	if (!pdata)
-		return -ENOMEM;
+	priv = kzalloc(sizeof_gpio_leds_priv(count), GFP_KERNEL);
+	if (!priv)
+		return NULL;
 
 	for_each_child_of_node(np, child) {
 		struct gpio_led led = {};
@@ -256,92 +196,112 @@
 		if (state) {
 			if (!strcmp(state, "keep"))
 				led.default_state = LEDS_GPIO_DEFSTATE_KEEP;
-			else if(!strcmp(state, "on"))
+			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);
+		ret = create_gpio_led(&led, &priv->leds[priv->num_leds++],
+				      &pdev->dev, NULL);
 		if (ret < 0) {
 			of_node_put(child);
 			goto err;
 		}
 	}
 
-	dev_set_drvdata(&ofdev->dev, pdata);
-
-	return 0;
+	return priv;
 
 err:
-	for (count = pdata->num_leds - 2; count >= 0; count--)
-		delete_gpio_led(&pdata->led_data[count]);
-
-	kfree(pdata);
+	for (count = priv->num_leds - 2; count >= 0; count--)
+		delete_gpio_led(&priv->leds[count]);
+	kfree(priv);
+	return NULL;
+}
 
-	return ret;
+static const struct of_device_id of_gpio_leds_match[] = {
+	{ .compatible = "gpio-leds", },
+	{},
+};
+#else
+static struct gpio_leds_priv * __devinit gpio_leds_create_of(struct platform_device *pdev)
+{
+	return NULL;
 }
+#define of_gpio_leds_match NULL
+#endif
 
-static int __devexit of_gpio_leds_remove(struct platform_device *ofdev)
+
+static int __devinit gpio_led_probe(struct platform_device *pdev)
 {
-	struct gpio_led_of_platform_data *pdata = dev_get_drvdata(&ofdev->dev);
-	int i;
+	struct gpio_led_platform_data *pdata = pdev->dev.platform_data;
+	struct gpio_leds_priv *priv;
+	int i, ret = 0;
 
-	for (i = 0; i < pdata->num_leds; i++)
-		delete_gpio_led(&pdata->led_data[i]);
+	if (pdata && pdata->num_leds) {
+		priv = kzalloc(sizeof_gpio_leds_priv(pdata->num_leds),
+				GFP_KERNEL);
+		if (!priv)
+			return -ENOMEM;
 
-	kfree(pdata);
+		priv->num_leds = pdata->num_leds;
+		for (i = 0; i < priv->num_leds; i++) {
+			ret = create_gpio_led(&pdata->leds[i],
+					      &priv->leds[i],
+					      &pdev->dev, pdata->gpio_blink_set);
+			if (ret < 0) {
+				/* On failure: unwind the led creations */
+				for (i = i - 1; i >= 0; i--)
+					delete_gpio_led(&priv->leds[i]);
+				kfree(priv);
+				return ret;
+			}
+		}
+	} else {
+		priv = gpio_leds_create_of(pdev);
+		if (!priv)
+			return -ENODEV;
+	}
 
-	dev_set_drvdata(&ofdev->dev, NULL);
+	platform_set_drvdata(pdev, priv);
 
 	return 0;
 }
 
-static const struct of_device_id of_gpio_leds_match[] = {
-	{ .compatible = "gpio-leds", },
-	{},
-};
+static int __devexit gpio_led_remove(struct platform_device *pdev)
+{
+	struct gpio_leds_priv *priv = dev_get_drvdata(&pdev->dev);
+	int i;
 
-static struct of_platform_driver of_gpio_leds_driver = {
-	.driver = {
-		.name = "of_gpio_leds",
-		.owner = THIS_MODULE,
+	for (i = 0; i < priv->num_leds; i++)
+		delete_gpio_led(&priv->leds[i]);
+
+	dev_set_drvdata(&pdev->dev, NULL);
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver gpio_led_driver = {
+	.probe		= gpio_led_probe,
+	.remove		= __devexit_p(gpio_led_remove),
+	.driver		= {
+		.name	= "leds-gpio",
+		.owner	= THIS_MODULE,
 		.of_match_table = of_gpio_leds_match,
 	},
-	.probe = of_gpio_leds_probe,
-	.remove = __devexit_p(of_gpio_leds_remove),
 };
-#endif
+
+MODULE_ALIAS("platform:leds-gpio");
 
 static int __init gpio_led_init(void)
 {
-	int ret = 0;
-
-#ifdef CONFIG_LEDS_GPIO_PLATFORM	
-	ret = platform_driver_register(&gpio_led_driver);
-	if (ret)
-		return ret;
-#endif
-#ifdef CONFIG_LEDS_GPIO_OF
-	ret = of_register_platform_driver(&of_gpio_leds_driver);
-#endif
-#ifdef CONFIG_LEDS_GPIO_PLATFORM	
-	if (ret)
-		platform_driver_unregister(&gpio_led_driver);
-#endif
-
-	return ret;
+	return platform_driver_register(&gpio_led_driver);
 }
 
 static void __exit gpio_led_exit(void)
 {
-#ifdef CONFIG_LEDS_GPIO_PLATFORM
 	platform_driver_unregister(&gpio_led_driver);
-#endif
-#ifdef CONFIG_LEDS_GPIO_OF
-	of_unregister_platform_driver(&of_gpio_leds_driver);
-#endif
 }
 
 module_init(gpio_led_init);
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-lm3530.c linux-libre-2.6.39-gnu/drivers/leds/leds-lm3530.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-lm3530.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-lm3530.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,379 @@
+/*
+ * Copyright (C) 2011 ST-Ericsson SA.
+ * Copyright (C) 2009 Motorola, Inc.
+ *
+ * License Terms: GNU General Public License v2
+ *
+ * Simple driver for National Semiconductor LM3530 Backlight driver chip
+ *
+ * Author: Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>
+ * based on leds-lm3530.c by Dan Murphy <D.Murphy@motorola.com>
+ */
+
+#include <linux/i2c.h>
+#include <linux/leds.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <linux/led-lm3530.h>
+#include <linux/types.h>
+
+#define LM3530_LED_DEV "lcd-backlight"
+#define LM3530_NAME "lm3530-led"
+
+#define LM3530_GEN_CONFIG		0x10
+#define LM3530_ALS_CONFIG		0x20
+#define LM3530_BRT_RAMP_RATE		0x30
+#define LM3530_ALS_ZONE_REG		0x40
+#define LM3530_ALS_IMP_SELECT		0x41
+#define LM3530_BRT_CTRL_REG		0xA0
+#define LM3530_ALS_ZB0_REG		0x60
+#define LM3530_ALS_ZB1_REG		0x61
+#define LM3530_ALS_ZB2_REG		0x62
+#define LM3530_ALS_ZB3_REG		0x63
+#define LM3530_ALS_Z0T_REG		0x70
+#define LM3530_ALS_Z1T_REG		0x71
+#define LM3530_ALS_Z2T_REG		0x72
+#define LM3530_ALS_Z3T_REG		0x73
+#define LM3530_ALS_Z4T_REG		0x74
+#define LM3530_REG_MAX			15
+
+/* General Control Register */
+#define LM3530_EN_I2C_SHIFT		(0)
+#define LM3530_RAMP_LAW_SHIFT		(1)
+#define LM3530_MAX_CURR_SHIFT		(2)
+#define LM3530_EN_PWM_SHIFT		(5)
+#define LM3530_PWM_POL_SHIFT		(6)
+#define LM3530_EN_PWM_SIMPLE_SHIFT	(7)
+
+#define LM3530_ENABLE_I2C		(1 << LM3530_EN_I2C_SHIFT)
+#define LM3530_ENABLE_PWM		(1 << LM3530_EN_PWM_SHIFT)
+#define LM3530_POL_LOW			(1 << LM3530_PWM_POL_SHIFT)
+#define LM3530_ENABLE_PWM_SIMPLE	(1 << LM3530_EN_PWM_SIMPLE_SHIFT)
+
+/* ALS Config Register Options */
+#define LM3530_ALS_AVG_TIME_SHIFT	(0)
+#define LM3530_EN_ALS_SHIFT		(3)
+#define LM3530_ALS_SEL_SHIFT		(5)
+
+#define LM3530_ENABLE_ALS		(3 << LM3530_EN_ALS_SHIFT)
+
+/* Brightness Ramp Rate Register */
+#define LM3530_BRT_RAMP_FALL_SHIFT	(0)
+#define LM3530_BRT_RAMP_RISE_SHIFT	(3)
+
+/* ALS Resistor Select */
+#define LM3530_ALS1_IMP_SHIFT		(0)
+#define LM3530_ALS2_IMP_SHIFT		(4)
+
+/* Zone Boundary Register defaults */
+#define LM3530_DEF_ZB_0			(0x33)
+#define LM3530_DEF_ZB_1			(0x66)
+#define LM3530_DEF_ZB_2			(0x99)
+#define LM3530_DEF_ZB_3			(0xCC)
+
+/* Zone Target Register defaults */
+#define LM3530_DEF_ZT_0			(0x19)
+#define LM3530_DEF_ZT_1			(0x33)
+#define LM3530_DEF_ZT_2			(0x4C)
+#define LM3530_DEF_ZT_3			(0x66)
+#define LM3530_DEF_ZT_4			(0x7F)
+
+struct lm3530_mode_map {
+	const char *mode;
+	enum lm3530_mode mode_val;
+};
+
+static struct lm3530_mode_map mode_map[] = {
+	{ "man", LM3530_BL_MODE_MANUAL },
+	{ "als", LM3530_BL_MODE_ALS },
+	{ "pwm", LM3530_BL_MODE_PWM },
+};
+
+/**
+ * struct lm3530_data
+ * @led_dev: led class device
+ * @client: i2c client
+ * @pdata: LM3530 platform data
+ * @mode: mode of operation - manual, ALS, PWM
+ */
+struct lm3530_data {
+	struct led_classdev led_dev;
+	struct i2c_client *client;
+	struct lm3530_platform_data *pdata;
+	enum lm3530_mode mode;
+};
+
+static const u8 lm3530_reg[LM3530_REG_MAX] = {
+	LM3530_GEN_CONFIG,
+	LM3530_ALS_CONFIG,
+	LM3530_BRT_RAMP_RATE,
+	LM3530_ALS_ZONE_REG,
+	LM3530_ALS_IMP_SELECT,
+	LM3530_BRT_CTRL_REG,
+	LM3530_ALS_ZB0_REG,
+	LM3530_ALS_ZB1_REG,
+	LM3530_ALS_ZB2_REG,
+	LM3530_ALS_ZB3_REG,
+	LM3530_ALS_Z0T_REG,
+	LM3530_ALS_Z1T_REG,
+	LM3530_ALS_Z2T_REG,
+	LM3530_ALS_Z3T_REG,
+	LM3530_ALS_Z4T_REG,
+};
+
+static int lm3530_get_mode_from_str(const char *str)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(mode_map); i++)
+		if (sysfs_streq(str, mode_map[i].mode))
+			return mode_map[i].mode_val;
+
+	return -1;
+}
+
+static int lm3530_init_registers(struct lm3530_data *drvdata)
+{
+	int ret = 0;
+	int i;
+	u8 gen_config;
+	u8 als_config = 0;
+	u8 brt_ramp;
+	u8 als_imp_sel = 0;
+	u8 brightness;
+	u8 reg_val[LM3530_REG_MAX];
+	struct lm3530_platform_data *pltfm = drvdata->pdata;
+	struct i2c_client *client = drvdata->client;
+
+	gen_config = (pltfm->brt_ramp_law << LM3530_RAMP_LAW_SHIFT) |
+			((pltfm->max_current & 7) << LM3530_MAX_CURR_SHIFT);
+
+	if (drvdata->mode == LM3530_BL_MODE_MANUAL ||
+	    drvdata->mode == LM3530_BL_MODE_ALS)
+		gen_config |= (LM3530_ENABLE_I2C);
+
+	if (drvdata->mode == LM3530_BL_MODE_ALS) {
+		als_config =
+			(pltfm->als_avrg_time << LM3530_ALS_AVG_TIME_SHIFT) |
+			(LM3530_ENABLE_ALS) |
+			(pltfm->als_input_mode << LM3530_ALS_SEL_SHIFT);
+
+		als_imp_sel =
+			(pltfm->als1_resistor_sel << LM3530_ALS1_IMP_SHIFT) |
+			(pltfm->als2_resistor_sel << LM3530_ALS2_IMP_SHIFT);
+	}
+
+	if (drvdata->mode == LM3530_BL_MODE_PWM)
+		gen_config |= (LM3530_ENABLE_PWM) |
+				(pltfm->pwm_pol_hi << LM3530_PWM_POL_SHIFT) |
+				(LM3530_ENABLE_PWM_SIMPLE);
+
+	brt_ramp = (pltfm->brt_ramp_fall << LM3530_BRT_RAMP_FALL_SHIFT) |
+			(pltfm->brt_ramp_rise << LM3530_BRT_RAMP_RISE_SHIFT);
+
+	brightness = pltfm->brt_val;
+
+	reg_val[0] = gen_config;	/* LM3530_GEN_CONFIG */
+	reg_val[1] = als_config;	/* LM3530_ALS_CONFIG */
+	reg_val[2] = brt_ramp;		/* LM3530_BRT_RAMP_RATE */
+	reg_val[3] = 0x00;		/* LM3530_ALS_ZONE_REG */
+	reg_val[4] = als_imp_sel;	/* LM3530_ALS_IMP_SELECT */
+	reg_val[5] = brightness;	/* LM3530_BRT_CTRL_REG */
+	reg_val[6] = LM3530_DEF_ZB_0;	/* LM3530_ALS_ZB0_REG */
+	reg_val[7] = LM3530_DEF_ZB_1;	/* LM3530_ALS_ZB1_REG */
+	reg_val[8] = LM3530_DEF_ZB_2;	/* LM3530_ALS_ZB2_REG */
+	reg_val[9] = LM3530_DEF_ZB_3;	/* LM3530_ALS_ZB3_REG */
+	reg_val[10] = LM3530_DEF_ZT_0;	/* LM3530_ALS_Z0T_REG */
+	reg_val[11] = LM3530_DEF_ZT_1;	/* LM3530_ALS_Z1T_REG */
+	reg_val[12] = LM3530_DEF_ZT_2;	/* LM3530_ALS_Z2T_REG */
+	reg_val[13] = LM3530_DEF_ZT_3;	/* LM3530_ALS_Z3T_REG */
+	reg_val[14] = LM3530_DEF_ZT_4;	/* LM3530_ALS_Z4T_REG */
+
+	for (i = 0; i < LM3530_REG_MAX; i++) {
+		ret = i2c_smbus_write_byte_data(client,
+				lm3530_reg[i], reg_val[i]);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+static void lm3530_brightness_set(struct led_classdev *led_cdev,
+				     enum led_brightness brt_val)
+{
+	int err;
+	struct lm3530_data *drvdata =
+	    container_of(led_cdev, struct lm3530_data, led_dev);
+
+	switch (drvdata->mode) {
+	case LM3530_BL_MODE_MANUAL:
+
+		/* set the brightness in brightness control register*/
+		err = i2c_smbus_write_byte_data(drvdata->client,
+				LM3530_BRT_CTRL_REG, brt_val / 2);
+		if (err)
+			dev_err(&drvdata->client->dev,
+				"Unable to set brightness: %d\n", err);
+		break;
+	case LM3530_BL_MODE_ALS:
+		break;
+	case LM3530_BL_MODE_PWM:
+		break;
+	default:
+		break;
+	}
+}
+
+
+static ssize_t lm3530_mode_set(struct device *dev, struct device_attribute
+				   *attr, const char *buf, size_t size)
+{
+	int err;
+	struct i2c_client *client = container_of(
+					dev->parent, struct i2c_client, dev);
+	struct lm3530_data *drvdata = i2c_get_clientdata(client);
+	int mode;
+
+	mode = lm3530_get_mode_from_str(buf);
+	if (mode < 0) {
+		dev_err(dev, "Invalid mode\n");
+		return -EINVAL;
+	}
+
+	if (mode == LM3530_BL_MODE_MANUAL)
+		drvdata->mode = LM3530_BL_MODE_MANUAL;
+	else if (mode == LM3530_BL_MODE_ALS)
+		drvdata->mode = LM3530_BL_MODE_ALS;
+	else if (mode == LM3530_BL_MODE_PWM) {
+		dev_err(dev, "PWM mode not supported\n");
+		return -EINVAL;
+	}
+
+	err = lm3530_init_registers(drvdata);
+	if (err) {
+		dev_err(dev, "Setting %s Mode failed :%d\n", buf, err);
+		return err;
+	}
+
+	return sizeof(drvdata->mode);
+}
+
+static DEVICE_ATTR(mode, 0644, NULL, lm3530_mode_set);
+
+static int __devinit lm3530_probe(struct i2c_client *client,
+			   const struct i2c_device_id *id)
+{
+	struct lm3530_platform_data *pdata = client->dev.platform_data;
+	struct lm3530_data *drvdata;
+	int err = 0;
+
+	if (pdata == NULL) {
+		dev_err(&client->dev, "platform data required\n");
+		err = -ENODEV;
+		goto err_out;
+	}
+
+	/* BL mode */
+	if (pdata->mode > LM3530_BL_MODE_PWM) {
+		dev_err(&client->dev, "Illegal Mode request\n");
+		err = -EINVAL;
+		goto err_out;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "I2C_FUNC_I2C not supported\n");
+		err = -EIO;
+		goto err_out;
+	}
+
+	drvdata = kzalloc(sizeof(struct lm3530_data), GFP_KERNEL);
+	if (drvdata == NULL) {
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	drvdata->mode = pdata->mode;
+	drvdata->client = client;
+	drvdata->pdata = pdata;
+	drvdata->led_dev.name = LM3530_LED_DEV;
+	drvdata->led_dev.brightness_set = lm3530_brightness_set;
+
+	i2c_set_clientdata(client, drvdata);
+
+	err = lm3530_init_registers(drvdata);
+	if (err < 0) {
+		dev_err(&client->dev, "Register Init failed: %d\n", err);
+		err = -ENODEV;
+		goto err_reg_init;
+	}
+
+	err = led_classdev_register((struct device *)
+				      &client->dev, &drvdata->led_dev);
+	if (err < 0) {
+		dev_err(&client->dev, "Register led class failed: %d\n", err);
+		err = -ENODEV;
+		goto err_class_register;
+	}
+
+	err = device_create_file(drvdata->led_dev.dev, &dev_attr_mode);
+	if (err < 0) {
+		dev_err(&client->dev, "File device creation failed: %d\n", err);
+		err = -ENODEV;
+		goto err_create_file;
+	}
+
+	return 0;
+
+err_create_file:
+	led_classdev_unregister(&drvdata->led_dev);
+err_class_register:
+err_reg_init:
+	kfree(drvdata);
+err_out:
+	return err;
+}
+
+static int __devexit lm3530_remove(struct i2c_client *client)
+{
+	struct lm3530_data *drvdata = i2c_get_clientdata(client);
+
+	device_remove_file(drvdata->led_dev.dev, &dev_attr_mode);
+	led_classdev_unregister(&drvdata->led_dev);
+	kfree(drvdata);
+	return 0;
+}
+
+static const struct i2c_device_id lm3530_id[] = {
+	{LM3530_NAME, 0},
+	{}
+};
+MODULE_DEVICE_TABLE(i2c, lm3530_id);
+
+static struct i2c_driver lm3530_i2c_driver = {
+	.probe = lm3530_probe,
+	.remove = lm3530_remove,
+	.id_table = lm3530_id,
+	.driver = {
+		.name = LM3530_NAME,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init lm3530_init(void)
+{
+	return i2c_add_driver(&lm3530_i2c_driver);
+}
+
+static void __exit lm3530_exit(void)
+{
+	i2c_del_driver(&lm3530_i2c_driver);
+}
+
+module_init(lm3530_init);
+module_exit(lm3530_exit);
+
+MODULE_DESCRIPTION("Back Light driver for LM3530");
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Shreshtha Kumar SAHU <shreshthakumar.sahu@stericsson.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-lp5521.c linux-libre-2.6.39-gnu/drivers/leds/leds-lp5521.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-lp5521.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-lp5521.c	2011-05-19 00:06:34.000000000 -0400
@@ -534,7 +534,7 @@
 }
 
 /* led class device attributes */
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
 
 static struct attribute *lp5521_led_attributes[] = {
@@ -548,15 +548,15 @@
 };
 
 /* device attributes */
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
 		   show_engine1_mode, store_engine1_mode);
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
 		   show_engine2_mode, store_engine2_mode);
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
 		   show_engine3_mode, store_engine3_mode);
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
 static DEVICE_ATTR(selftest, S_IRUGO, lp5521_selftest, NULL);
 
 static struct attribute *lp5521_attributes[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-lp5523.c linux-libre-2.6.39-gnu/drivers/leds/leds-lp5523.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-lp5523.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-lp5523.c	2011-05-19 00:06:34.000000000 -0400
@@ -713,7 +713,7 @@
 }
 
 /* led class device attributes */
-static DEVICE_ATTR(led_current, S_IRUGO | S_IWUGO, show_current, store_current);
+static DEVICE_ATTR(led_current, S_IRUGO | S_IWUSR, show_current, store_current);
 static DEVICE_ATTR(max_current, S_IRUGO , show_max_current, NULL);
 
 static struct attribute *lp5523_led_attributes[] = {
@@ -727,21 +727,21 @@
 };
 
 /* device attributes */
-static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_mode, S_IRUGO | S_IWUSR,
 		   show_engine1_mode, store_engine1_mode);
-static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_mode, S_IRUGO | S_IWUSR,
 		   show_engine2_mode, store_engine2_mode);
-static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_mode, S_IRUGO | S_IWUSR,
 		   show_engine3_mode, store_engine3_mode);
-static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine1_leds, S_IRUGO | S_IWUSR,
 		   show_engine1_leds, store_engine1_leds);
-static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine2_leds, S_IRUGO | S_IWUSR,
 		   show_engine2_leds, store_engine2_leds);
-static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUGO,
+static DEVICE_ATTR(engine3_leds, S_IRUGO | S_IWUSR,
 		   show_engine3_leds, store_engine3_leds);
-static DEVICE_ATTR(engine1_load, S_IWUGO, NULL, store_engine1_load);
-static DEVICE_ATTR(engine2_load, S_IWUGO, NULL, store_engine2_load);
-static DEVICE_ATTR(engine3_load, S_IWUGO, NULL, store_engine3_load);
+static DEVICE_ATTR(engine1_load, S_IWUSR, NULL, store_engine1_load);
+static DEVICE_ATTR(engine2_load, S_IWUSR, NULL, store_engine2_load);
+static DEVICE_ATTR(engine3_load, S_IWUSR, NULL, store_engine3_load);
 static DEVICE_ATTR(selftest, S_IRUGO, lp5523_selftest, NULL);
 
 static struct attribute *lp5523_attributes[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-mc13783.c linux-libre-2.6.39-gnu/drivers/leds/leds-mc13783.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-mc13783.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-mc13783.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #include <linux/leds.h>
 #include <linux/workqueue.h>
 #include <linux/mfd/mc13783.h>
+#include <linux/mfd/core.h>
 #include <linux/slab.h>
 
 struct mc13783_led {
@@ -183,7 +184,7 @@
 
 static int __devinit mc13783_leds_prepare(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
 	struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
 	int ret = 0;
 	int reg = 0;
@@ -264,7 +265,7 @@
 
 static int __devinit mc13783_led_probe(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
 	struct mc13783_led_platform_data *led_cur;
 	struct mc13783_led *led, *led_dat;
 	int ret, i;
@@ -351,7 +352,7 @@
 
 static int __devexit mc13783_led_remove(struct platform_device *pdev)
 {
-	struct mc13783_leds_platform_data *pdata = dev_get_platdata(&pdev->dev);
+	struct mc13783_leds_platform_data *pdata = mfd_get_data(pdev);
 	struct mc13783_led *led = platform_get_drvdata(pdev);
 	struct mc13783 *dev = dev_get_drvdata(pdev->dev.parent);
 	int i;
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-net5501.c linux-libre-2.6.39-gnu/drivers/leds/leds-net5501.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-net5501.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-net5501.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 
 #include <asm/geode.h>
 
-static struct gpio_led net5501_leds[] = {
+static const struct gpio_led net5501_leds[] = {
 	{
 		.name = "error",
 		.gpio = 6,
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-pca9532.c linux-libre-2.6.39-gnu/drivers/leds/leds-pca9532.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-pca9532.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-pca9532.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,7 +58,7 @@
 	.id_table = pca9532_id,
 };
 
-/* We have two pwm/blinkers, but 16 possible leds to drive. Additionaly,
+/* We have two pwm/blinkers, but 16 possible leds to drive. Additionally,
  * the clever Thecus people are using one pwm to drive the beeper. So,
  * as a compromise we average one pwm to the values requested by all
  * leds that are not ON/OFF.
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-regulator.c linux-libre-2.6.39-gnu/drivers/leds/leds-regulator.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-regulator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-regulator.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,6 +178,10 @@
 	led->cdev.flags |= LED_CORE_SUSPENDRESUME;
 	led->vcc = vcc;
 
+	/* to handle correctly an already enabled regulator */
+	if (regulator_is_enabled(led->vcc))
+		led->enabled = 1;
+
 	mutex_init(&led->mutex);
 	INIT_WORK(&led->work, led_work);
 
diff -druN linux-libre-2.6.38-gnu/drivers/leds/leds-wm8350.c linux-libre-2.6.39-gnu/drivers/leds/leds-wm8350.c
--- linux-libre-2.6.38-gnu/drivers/leds/leds-wm8350.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/leds-wm8350.c	2011-05-19 00:06:34.000000000 -0400
@@ -215,13 +215,13 @@
 
 	isink = regulator_get(&pdev->dev, "led_isink");
 	if (IS_ERR(isink)) {
-		printk(KERN_ERR "%s: cant get ISINK\n", __func__);
+		printk(KERN_ERR "%s: can't get ISINK\n", __func__);
 		return PTR_ERR(isink);
 	}
 
 	dcdc = regulator_get(&pdev->dev, "led_vcc");
 	if (IS_ERR(dcdc)) {
-		printk(KERN_ERR "%s: cant get DCDC\n", __func__);
+		printk(KERN_ERR "%s: can't get DCDC\n", __func__);
 		ret = PTR_ERR(dcdc);
 		goto err_isink;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/leds/led-triggers.c linux-libre-2.6.39-gnu/drivers/leds/led-triggers.c
--- linux-libre-2.6.38-gnu/drivers/leds/led-triggers.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/led-triggers.c	2011-05-19 00:06:34.000000000 -0400
@@ -231,6 +231,26 @@
 }
 EXPORT_SYMBOL_GPL(led_trigger_event);
 
+void led_trigger_blink(struct led_trigger *trigger,
+		       unsigned long *delay_on,
+		       unsigned long *delay_off)
+{
+	struct list_head *entry;
+
+	if (!trigger)
+		return;
+
+	read_lock(&trigger->leddev_list_lock);
+	list_for_each(entry, &trigger->led_cdevs) {
+		struct led_classdev *led_cdev;
+
+		led_cdev = list_entry(entry, struct led_classdev, trig_list);
+		led_blink_set(led_cdev, delay_on, delay_off);
+	}
+	read_unlock(&trigger->leddev_list_lock);
+}
+EXPORT_SYMBOL_GPL(led_trigger_blink);
+
 void led_trigger_register_simple(const char *name, struct led_trigger **tp)
 {
 	struct led_trigger *trigger;
diff -druN linux-libre-2.6.38-gnu/drivers/leds/Makefile linux-libre-2.6.39-gnu/drivers/leds/Makefile
--- linux-libre-2.6.38-gnu/drivers/leds/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/leds/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
 obj-$(CONFIG_LEDS_ATMEL_PWM)		+= leds-atmel-pwm.o
 obj-$(CONFIG_LEDS_BD2802)		+= leds-bd2802.o
 obj-$(CONFIG_LEDS_LOCOMO)		+= leds-locomo.o
+obj-$(CONFIG_LEDS_LM3530)		+= leds-lm3530.o
 obj-$(CONFIG_LEDS_MIKROTIK_RB532)	+= leds-rb532.o
 obj-$(CONFIG_LEDS_S3C24XX)		+= leds-s3c24xx.o
 obj-$(CONFIG_LEDS_AMS_DELTA)		+= leds-ams-delta.o
diff -druN linux-libre-2.6.38-gnu/drivers/lguest/lguest_user.c linux-libre-2.6.39-gnu/drivers/lguest/lguest_user.c
--- linux-libre-2.6.38-gnu/drivers/lguest/lguest_user.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/lguest/lguest_user.c	2011-05-19 00:06:34.000000000 -0400
@@ -130,7 +130,7 @@
 	rcu_assign_pointer(lg->eventfds, new);
 
 	/*
-	 * We're not in a big hurry.  Wait until noone's looking at old
+	 * We're not in a big hurry.  Wait until no one's looking at old
 	 * version, then free it.
 	 */
 	synchronize_rcu();
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/adbhid.c linux-libre-2.6.39-gnu/drivers/macintosh/adbhid.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/adbhid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/adbhid.c	2011-05-19 00:06:34.000000000 -0400
@@ -328,7 +328,7 @@
 	switch (keycode) {
 	case ADB_KEY_CAPSLOCK:
 		if (!restore_capslock_events) {
-			/* Generate down/up events for CapsLock everytime. */
+			/* Generate down/up events for CapsLock every time. */
 			input_report_key(ahid->input, KEY_CAPSLOCK, 1);
 			input_sync(ahid->input);
 			input_report_key(ahid->input, KEY_CAPSLOCK, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/macio-adb.c linux-libre-2.6.39-gnu/drivers/macintosh/macio-adb.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/macio-adb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/macio-adb.c	2011-05-19 00:06:34.000000000 -0400
@@ -147,7 +147,7 @@
 
 	/* Hrm... we may want to not lock interrupts for so
 	 * long ... oh well, who uses that chip anyway ? :)
-	 * That function will be seldomly used during boot
+	 * That function will be seldom used during boot
 	 * on rare machines, so...
 	 */
 	spin_lock_irqsave(&macio_lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/rack-meter.c linux-libre-2.6.39-gnu/drivers/macintosh/rack-meter.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/rack-meter.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/rack-meter.c	2011-05-19 00:06:34.000000000 -0400
@@ -283,7 +283,7 @@
 	}
 }
 
-static void __devexit rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
+static void rackmeter_stop_cpu_sniffer(struct rackmeter *rm)
 {
 	cancel_delayed_work_sync(&rm->cpu[0].sniffer);
 	cancel_delayed_work_sync(&rm->cpu[1].sniffer);
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/smu.c linux-libre-2.6.39-gnu/drivers/macintosh/smu.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/smu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/smu.c	2011-05-19 00:06:34.000000000 -0400
@@ -645,8 +645,7 @@
 
 static DECLARE_WORK(smu_expose_childs_work, smu_expose_childs);
 
-static int smu_platform_probe(struct platform_device* dev,
-			      const struct of_device_id *match)
+static int smu_platform_probe(struct platform_device* dev)
 {
 	if (!smu)
 		return -ENODEV;
@@ -669,7 +668,7 @@
 	{},
 };
 
-static struct of_platform_driver smu_of_platform_driver =
+static struct platform_driver smu_of_platform_driver =
 {
 	.driver = {
 		.name = "smu",
@@ -689,7 +688,7 @@
 	 * I'm a bit too far from figuring out how that works with those
 	 * new chipsets, but that will come back and bite us
 	 */
-	of_register_platform_driver(&smu_of_platform_driver);
+	platform_driver_register(&smu_of_platform_driver);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/therm_adt746x.c linux-libre-2.6.39-gnu/drivers/macintosh/therm_adt746x.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/therm_adt746x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/therm_adt746x.c	2011-05-19 00:06:34.000000000 -0400
@@ -662,7 +662,7 @@
 		err |= device_create_file(&of_dev->dev, &dev_attr_sensor2_fan_speed);
 	if (err)
 		printk(KERN_WARNING
-			"Failed to create tempertaure attribute file(s).\n");
+			"Failed to create temperature attribute file(s).\n");
 }
 
 static void thermostat_remove_files(void)
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/therm_pm72.c linux-libre-2.6.39-gnu/drivers/macintosh/therm_pm72.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/therm_pm72.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/therm_pm72.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
  *
  *  Mar. 10, 2005 : 1.2
  *	- Add basic support for Xserve G5
- *	- Retreive pumps min/max from EEPROM image in device-tree (broken)
+ *	- Retrieve pumps min/max from EEPROM image in device-tree (broken)
  *	- Use min/max macros here or there
  *	- Latest darwin updated U3H min fan speed to 20% PWM
  *
@@ -153,7 +153,7 @@
 static struct i2c_adapter *		u3_1;
 static struct i2c_adapter *		k2;
 static struct i2c_client *		fcu;
-static struct cpu_pid_state		cpu_state[2];
+static struct cpu_pid_state		processor_state[2];
 static struct basckside_pid_params	backside_params;
 static struct backside_pid_state	backside_state;
 static struct drives_pid_state		drives_state;
@@ -375,7 +375,7 @@
 		rc = i2c_master_send(state->monitor, buf, 2);
 		if (rc <= 0)
 			goto error;
-		/* Wait for convertion */
+		/* Wait for conversion */
 		msleep(1);
 		/* Switch to data register */
 		buf[0] = 4;
@@ -664,8 +664,8 @@
 
 static void fetch_cpu_pumps_minmax(void)
 {
-	struct cpu_pid_state *state0 = &cpu_state[0];
-	struct cpu_pid_state *state1 = &cpu_state[1];
+	struct cpu_pid_state *state0 = &processor_state[0];
+	struct cpu_pid_state *state1 = &processor_state[1];
 	u16 pump_min = 0, pump_max = 0xffff;
 	u16 tmp[4];
 
@@ -717,17 +717,17 @@
 	return sprintf(buf, "%d", data);			\
 }
 
-BUILD_SHOW_FUNC_FIX(cpu0_temperature, cpu_state[0].last_temp)
-BUILD_SHOW_FUNC_FIX(cpu0_voltage, cpu_state[0].voltage)
-BUILD_SHOW_FUNC_FIX(cpu0_current, cpu_state[0].current_a)
-BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, cpu_state[0].rpm)
-BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, cpu_state[0].intake_rpm)
+BUILD_SHOW_FUNC_FIX(cpu0_temperature, processor_state[0].last_temp)
+BUILD_SHOW_FUNC_FIX(cpu0_voltage, processor_state[0].voltage)
+BUILD_SHOW_FUNC_FIX(cpu0_current, processor_state[0].current_a)
+BUILD_SHOW_FUNC_INT(cpu0_exhaust_fan_rpm, processor_state[0].rpm)
+BUILD_SHOW_FUNC_INT(cpu0_intake_fan_rpm, processor_state[0].intake_rpm)
 
-BUILD_SHOW_FUNC_FIX(cpu1_temperature, cpu_state[1].last_temp)
-BUILD_SHOW_FUNC_FIX(cpu1_voltage, cpu_state[1].voltage)
-BUILD_SHOW_FUNC_FIX(cpu1_current, cpu_state[1].current_a)
-BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, cpu_state[1].rpm)
-BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, cpu_state[1].intake_rpm)
+BUILD_SHOW_FUNC_FIX(cpu1_temperature, processor_state[1].last_temp)
+BUILD_SHOW_FUNC_FIX(cpu1_voltage, processor_state[1].voltage)
+BUILD_SHOW_FUNC_FIX(cpu1_current, processor_state[1].current_a)
+BUILD_SHOW_FUNC_INT(cpu1_exhaust_fan_rpm, processor_state[1].rpm)
+BUILD_SHOW_FUNC_INT(cpu1_intake_fan_rpm, processor_state[1].intake_rpm)
 
 BUILD_SHOW_FUNC_FIX(backside_temperature, backside_state.last_temp)
 BUILD_SHOW_FUNC_INT(backside_fan_pwm, backside_state.pwm)
@@ -919,8 +919,8 @@
 
 static void do_monitor_cpu_combined(void)
 {
-	struct cpu_pid_state *state0 = &cpu_state[0];
-	struct cpu_pid_state *state1 = &cpu_state[1];
+	struct cpu_pid_state *state0 = &processor_state[0];
+	struct cpu_pid_state *state1 = &processor_state[1];
 	s32 temp0, power0, temp1, power1;
 	s32 temp_combi, power_combi;
 	int rc, intake, pump;
@@ -1150,7 +1150,7 @@
 /*
  * Initialize the state structure for one CPU control loop
  */
-static int init_cpu_state(struct cpu_pid_state *state, int index)
+static int init_processor_state(struct cpu_pid_state *state, int index)
 {
 	int err;
 
@@ -1192,7 +1192,7 @@
 		err |= device_create_file(&of_dev->dev, &dev_attr_cpu1_intake_fan_rpm);
 	}
 	if (err)
-		printk(KERN_WARNING "Failed to create some of the atribute"
+		printk(KERN_WARNING "Failed to create some of the attribute"
 			"files for CPU %d\n", index);
 
 	return 0;
@@ -1205,7 +1205,7 @@
 /*
  * Dispose of the state data for one CPU control loop
  */
-static void dispose_cpu_state(struct cpu_pid_state *state)
+static void dispose_processor_state(struct cpu_pid_state *state)
 {
 	if (state->monitor == NULL)
 		return;
@@ -1804,9 +1804,9 @@
 		set_pwm_fan(SLOTS_FAN_PWM_INDEX, SLOTS_FAN_DEFAULT_PWM);
 
 	/* Initialize ADCs */
-	initialize_adc(&cpu_state[0]);
-	if (cpu_state[1].monitor != NULL)
-		initialize_adc(&cpu_state[1]);
+	initialize_adc(&processor_state[0]);
+	if (processor_state[1].monitor != NULL)
+		initialize_adc(&processor_state[1]);
 
 	fcu_tickle_ticks = FCU_TICKLE_TICKS;
 
@@ -1833,14 +1833,14 @@
 		if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
 			do_monitor_cpu_combined();
 		else if (cpu_pid_type == CPU_PID_TYPE_RACKMAC) {
-			do_monitor_cpu_rack(&cpu_state[0]);
-			if (cpu_state[1].monitor != NULL)
-				do_monitor_cpu_rack(&cpu_state[1]);
+			do_monitor_cpu_rack(&processor_state[0]);
+			if (processor_state[1].monitor != NULL)
+				do_monitor_cpu_rack(&processor_state[1]);
 			// better deal with UP
 		} else {
-			do_monitor_cpu_split(&cpu_state[0]);
-			if (cpu_state[1].monitor != NULL)
-				do_monitor_cpu_split(&cpu_state[1]);
+			do_monitor_cpu_split(&processor_state[0]);
+			if (processor_state[1].monitor != NULL)
+				do_monitor_cpu_split(&processor_state[1]);
 			// better deal with UP
 		}
 		/* Then, the rest */
@@ -1885,8 +1885,8 @@
  */
 static void dispose_control_loops(void)
 {
-	dispose_cpu_state(&cpu_state[0]);
-	dispose_cpu_state(&cpu_state[1]);
+	dispose_processor_state(&processor_state[0]);
+	dispose_processor_state(&processor_state[1]);
 	dispose_backside_state(&backside_state);
 	dispose_drives_state(&drives_state);
 	dispose_slots_state(&slots_state);
@@ -1928,12 +1928,12 @@
 	/* Create control loops for everything. If any fail, everything
 	 * fails
 	 */
-	if (init_cpu_state(&cpu_state[0], 0))
+	if (init_processor_state(&processor_state[0], 0))
 		goto fail;
 	if (cpu_pid_type == CPU_PID_TYPE_COMBINED)
 		fetch_cpu_pumps_minmax();
 
-	if (cpu_count > 1 && init_cpu_state(&cpu_state[1], 1))
+	if (cpu_count > 1 && init_processor_state(&processor_state[1], 1))
 		goto fail;
 	if (init_backside_state(&backside_state))
 		goto fail;
@@ -2210,7 +2210,7 @@
 	}
 }
 
-static int fcu_of_probe(struct platform_device* dev, const struct of_device_id *match)
+static int fcu_of_probe(struct platform_device* dev)
 {
 	state = state_detached;
 	of_dev = dev;
@@ -2240,7 +2240,7 @@
 };
 MODULE_DEVICE_TABLE(of, fcu_match);
 
-static struct of_platform_driver fcu_of_platform_driver = 
+static struct platform_driver fcu_of_platform_driver = 
 {
 	.driver = {
 		.name = "temperature",
@@ -2263,12 +2263,12 @@
 	    !rackmac)
 	    	return -ENODEV;
 
-	return of_register_platform_driver(&fcu_of_platform_driver);
+	return platform_driver_register(&fcu_of_platform_driver);
 }
 
 static void __exit therm_pm72_exit(void)
 {
-	of_unregister_platform_driver(&fcu_of_platform_driver);
+	platform_driver_unregister(&fcu_of_platform_driver);
 }
 
 module_init(therm_pm72_init);
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/therm_windtunnel.c linux-libre-2.6.39-gnu/drivers/macintosh/therm_windtunnel.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/therm_windtunnel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/therm_windtunnel.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 #include <asm/sections.h>
 #include <asm/macio.h>
 
-#define LOG_TEMP		0			/* continously log temperature */
+#define LOG_TEMP		0			/* continuously log temperature */
 
 static struct {
 	volatile int		running;
@@ -443,8 +443,7 @@
 /*	initialization / cleanup					*/
 /************************************************************************/
 
-static int
-therm_of_probe( struct platform_device *dev, const struct of_device_id *match )
+static int therm_of_probe(struct platform_device *dev)
 {
 	return i2c_add_driver( &g4fan_driver );
 }
@@ -462,7 +461,7 @@
     }, {}
 };
 
-static struct of_platform_driver therm_of_driver = {
+static struct platform_driver therm_of_driver = {
 	.driver = {
 		.name = "temperature",
 		.owner = THIS_MODULE,
@@ -509,14 +508,14 @@
 		return -ENODEV;
 	}
 
-	of_register_platform_driver( &therm_of_driver );
+	platform_driver_register( &therm_of_driver );
 	return 0;
 }
 
 static void __exit
 g4fan_exit( void )
 {
-	of_unregister_platform_driver( &therm_of_driver );
+	platform_driver_unregister( &therm_of_driver );
 
 	if( x.of_dev )
 		of_device_unregister( x.of_dev );
diff -druN linux-libre-2.6.38-gnu/drivers/macintosh/via-pmu-backlight.c linux-libre-2.6.39-gnu/drivers/macintosh/via-pmu-backlight.c
--- linux-libre-2.6.38-gnu/drivers/macintosh/via-pmu-backlight.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/macintosh/via-pmu-backlight.c	2011-05-19 00:06:34.000000000 -0400
@@ -163,6 +163,7 @@
 	snprintf(name, sizeof(name), "pmubl");
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = FB_BACKLIGHT_LEVELS - 1;
 	bd = backlight_device_register(name, NULL, NULL, &pmu_backlight_data,
 				       &props);
diff -druN linux-libre-2.6.38-gnu/drivers/Makefile linux-libre-2.6.39-gnu/drivers/Makefile
--- linux-libre-2.6.38-gnu/drivers/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -117,3 +117,5 @@
 obj-y				+= ieee802154/
 #common clk code
 obj-y				+= clk/
+
+obj-$(CONFIG_HWSPINLOCK)	+= hwspinlock/
diff -druN linux-libre-2.6.38-gnu/drivers/md/bitmap.c linux-libre-2.6.39-gnu/drivers/md/bitmap.c
--- linux-libre-2.6.38-gnu/drivers/md/bitmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/bitmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -347,7 +347,7 @@
 			atomic_inc(&bitmap->pending_writes);
 			set_buffer_locked(bh);
 			set_buffer_mapped(bh);
-			submit_bh(WRITE | REQ_UNPLUG | REQ_SYNC, bh);
+			submit_bh(WRITE | REQ_SYNC, bh);
 			bh = bh->b_this_page;
 		}
 
@@ -854,7 +854,7 @@
 		if (bitmap->flags & BITMAP_HOSTENDIAN)
 			set_bit(bit, kaddr);
 		else
-			ext2_set_bit(bit, kaddr);
+			__test_and_set_bit_le(bit, kaddr);
 		kunmap_atomic(kaddr, KM_USER0);
 		PRINTK("set file bit %lu page %lu\n", bit, page->index);
 	}
@@ -1050,7 +1050,7 @@
 		if (bitmap->flags & BITMAP_HOSTENDIAN)
 			b = test_bit(bit, paddr);
 		else
-			b = ext2_test_bit(bit, paddr);
+			b = test_bit_le(bit, paddr);
 		kunmap_atomic(paddr, KM_USER0);
 		if (b) {
 			/* if the disk bit is set, set the memory bit */
@@ -1226,7 +1226,7 @@
 						clear_bit(file_page_offset(bitmap, j),
 							  paddr);
 					else
-						ext2_clear_bit(file_page_offset(bitmap, j),
+						__test_and_clear_bit_le(file_page_offset(bitmap, j),
 							       paddr);
 					kunmap_atomic(paddr, KM_USER0);
 				} else
@@ -1339,8 +1339,7 @@
 			prepare_to_wait(&bitmap->overflow_wait, &__wait,
 					TASK_UNINTERRUPTIBLE);
 			spin_unlock_irq(&bitmap->lock);
-			md_unplug(bitmap->mddev);
-			schedule();
+			io_schedule();
 			finish_wait(&bitmap->overflow_wait, &__wait);
 			continue;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/md/bitmap.h linux-libre-2.6.39-gnu/drivers/md/bitmap.h
--- linux-libre-2.6.38-gnu/drivers/md/bitmap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/bitmap.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
  *
  * The counter counts pending write requests, plus the on-disk bit.
  * When the counter is '1' and the resync bits are clear, the on-disk
- * bit can be cleared aswell, thus setting the counter to 0.
+ * bit can be cleared as well, thus setting the counter to 0.
  * When we set a bit, or in the counter (to start a write), if the fields is
  * 0, we first set the disk bit and set the counter to 1.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm.c linux-libre-2.6.39-gnu/drivers/md/dm.c
--- linux-libre-2.6.38-gnu/drivers/md/dm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm.c	2011-05-19 00:06:34.000000000 -0400
@@ -477,7 +477,8 @@
 	cpu = part_stat_lock();
 	part_round_stats(cpu, &dm_disk(md)->part0);
 	part_stat_unlock();
-	dm_disk(md)->part0.in_flight[rw] = atomic_inc_return(&md->pending[rw]);
+	atomic_set(&dm_disk(md)->part0.in_flight[rw],
+		atomic_inc_return(&md->pending[rw]));
 }
 
 static void end_io_acct(struct dm_io *io)
@@ -497,8 +498,8 @@
 	 * After this is decremented the bio must not be touched if it is
 	 * a flush.
 	 */
-	dm_disk(md)->part0.in_flight[rw] = pending =
-		atomic_dec_return(&md->pending[rw]);
+	pending = atomic_dec_return(&md->pending[rw]);
+	atomic_set(&dm_disk(md)->part0.in_flight[rw], pending);
 	pending += atomic_read(&md->pending[rw^0x1]);
 
 	/* nudge anyone waiting on suspend queue */
@@ -807,8 +808,6 @@
 	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);
 
@@ -1613,10 +1612,10 @@
 	 * number of in-flight I/Os after the queue is stopped in
 	 * dm_suspend().
 	 */
-	while (!blk_queue_plugged(q) && !blk_queue_stopped(q)) {
+	while (!blk_queue_stopped(q)) {
 		rq = blk_peek_request(q);
 		if (!rq)
-			goto plug_and_out;
+			goto delay_and_out;
 
 		/* always use block 0 to find the target for flushes for now */
 		pos = 0;
@@ -1627,7 +1626,7 @@
 		BUG_ON(!dm_target_is_valid(ti));
 
 		if (ti->type->busy && ti->type->busy(ti))
-			goto plug_and_out;
+			goto delay_and_out;
 
 		blk_start_request(rq);
 		clone = rq->special;
@@ -1647,11 +1646,8 @@
 	BUG_ON(!irqs_disabled());
 	spin_lock(q->queue_lock);
 
-plug_and_out:
-	if (!elv_queue_empty(q))
-		/* Some requests still remain, retry later */
-		blk_plug_device(q);
-
+delay_and_out:
+	blk_delay_queue(q, HZ / 10);
 out:
 	dm_table_put(map);
 
@@ -1680,20 +1676,6 @@
 	return r;
 }
 
-static void dm_unplug_all(struct request_queue *q)
-{
-	struct mapped_device *md = q->queuedata;
-	struct dm_table *map = dm_get_live_table(md);
-
-	if (map) {
-		if (dm_request_based(md))
-			generic_unplug_device(q);
-
-		dm_table_unplug_all(map);
-		dm_table_put(map);
-	}
-}
-
 static int dm_any_congested(void *congested_data, int bdi_bits)
 {
 	int r = bdi_bits;
@@ -1817,7 +1799,6 @@
 	md->queue->backing_dev_info.congested_data = md;
 	blk_queue_make_request(md->queue, dm_request);
 	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);
 	blk_queue_flush(md->queue, REQ_FLUSH | REQ_FUA);
 }
@@ -2263,8 +2244,6 @@
 	int r = 0;
 	DECLARE_WAITQUEUE(wait, current);
 
-	dm_unplug_all(md->queue);
-
 	add_wait_queue(&md->wait, &wait);
 
 	while (1) {
@@ -2539,7 +2518,6 @@
 
 	clear_bit(DMF_SUSPENDED, &md->flags);
 
-	dm_table_unplug_all(map);
 	r = 0;
 out:
 	dm_table_put(map);
@@ -2643,9 +2621,10 @@
 }
 EXPORT_SYMBOL_GPL(dm_noflush_suspending);
 
-struct dm_md_mempools *dm_alloc_md_mempools(unsigned type)
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity)
 {
 	struct dm_md_mempools *pools = kmalloc(sizeof(*pools), GFP_KERNEL);
+	unsigned int pool_size = (type == DM_TYPE_BIO_BASED) ? 16 : MIN_IOS;
 
 	if (!pools)
 		return NULL;
@@ -2662,13 +2641,18 @@
 	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);
+	pools->bs = bioset_create(pool_size, 0);
 	if (!pools->bs)
 		goto free_tio_pool_and_out;
 
+	if (integrity && bioset_integrity_create(pools->bs, pool_size))
+		goto free_bioset_and_out;
+
 	return pools;
 
+free_bioset_and_out:
+	bioset_free(pools->bs);
+
 free_tio_pool_and_out:
 	mempool_destroy(pools->tio_pool);
 
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-crypt.c linux-libre-2.6.39-gnu/drivers/md/dm-crypt.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-crypt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-crypt.c	2011-05-19 00:06:34.000000000 -0400
@@ -991,11 +991,6 @@
 	clone->bi_destructor = dm_crypt_bio_destructor;
 }
 
-static void kcryptd_unplug(struct crypt_config *cc)
-{
-	blk_unplug(bdev_get_queue(cc->dev->bdev));
-}
-
 static int kcryptd_io_read(struct dm_crypt_io *io, gfp_t gfp)
 {
 	struct crypt_config *cc = io->target->private;
@@ -1008,10 +1003,8 @@
 	 * one in order to decrypt the whole bio data *afterwards*.
 	 */
 	clone = bio_alloc_bioset(gfp, bio_segments(base_bio), cc->bs);
-	if (!clone) {
-		kcryptd_unplug(cc);
+	if (!clone)
 		return 1;
-	}
 
 	crypt_inc_pending(io);
 
@@ -1331,20 +1324,29 @@
 
 static int crypt_set_key(struct crypt_config *cc, char *key)
 {
+	int r = -EINVAL;
+	int key_string_len = strlen(key);
+
 	/* The key size may not be changed. */
-	if (cc->key_size != (strlen(key) >> 1))
-		return -EINVAL;
+	if (cc->key_size != (key_string_len >> 1))
+		goto out;
 
 	/* Hyphen (which gives a key_size of zero) means there is no key. */
 	if (!cc->key_size && strcmp(key, "-"))
-		return -EINVAL;
+		goto out;
 
 	if (cc->key_size && crypt_decode_key(cc->key, key, cc->key_size) < 0)
-		return -EINVAL;
+		goto out;
 
 	set_bit(DM_CRYPT_KEY_VALID, &cc->flags);
 
-	return crypt_setkey_allcpus(cc);
+	r = crypt_setkey_allcpus(cc);
+
+out:
+	/* Hex key string not needed after here, so wipe it. */
+	memset(key, '0', key_string_len);
+
+	return r;
 }
 
 static int crypt_wipe_key(struct crypt_config *cc)
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-flakey.c linux-libre-2.6.39-gnu/drivers/md/dm-flakey.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-flakey.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/md/dm-flakey.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,212 @@
+/*
+ * Copyright (C) 2003 Sistina Software (UK) Limited.
+ * Copyright (C) 2004, 2010 Red Hat, Inc. All rights reserved.
+ *
+ * This file is released under the GPL.
+ */
+
+#include <linux/device-mapper.h>
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/blkdev.h>
+#include <linux/bio.h>
+#include <linux/slab.h>
+
+#define DM_MSG_PREFIX "flakey"
+
+/*
+ * Flakey: Used for testing only, simulates intermittent,
+ * catastrophic device failure.
+ */
+struct flakey_c {
+	struct dm_dev *dev;
+	unsigned long start_time;
+	sector_t start;
+	unsigned up_interval;
+	unsigned down_interval;
+};
+
+/*
+ * Construct a flakey mapping: <dev_path> <offset> <up interval> <down interval>
+ */
+static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
+{
+	struct flakey_c *fc;
+	unsigned long long tmp;
+
+	if (argc != 4) {
+		ti->error = "dm-flakey: Invalid argument count";
+		return -EINVAL;
+	}
+
+	fc = kmalloc(sizeof(*fc), GFP_KERNEL);
+	if (!fc) {
+		ti->error = "dm-flakey: Cannot allocate linear context";
+		return -ENOMEM;
+	}
+	fc->start_time = jiffies;
+
+	if (sscanf(argv[1], "%llu", &tmp) != 1) {
+		ti->error = "dm-flakey: Invalid device sector";
+		goto bad;
+	}
+	fc->start = tmp;
+
+	if (sscanf(argv[2], "%u", &fc->up_interval) != 1) {
+		ti->error = "dm-flakey: Invalid up interval";
+		goto bad;
+	}
+
+	if (sscanf(argv[3], "%u", &fc->down_interval) != 1) {
+		ti->error = "dm-flakey: Invalid down interval";
+		goto bad;
+	}
+
+	if (!(fc->up_interval + fc->down_interval)) {
+		ti->error = "dm-flakey: Total (up + down) interval is zero";
+		goto bad;
+	}
+
+	if (fc->up_interval + fc->down_interval < fc->up_interval) {
+		ti->error = "dm-flakey: Interval overflow";
+		goto bad;
+	}
+
+	if (dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &fc->dev)) {
+		ti->error = "dm-flakey: Device lookup failed";
+		goto bad;
+	}
+
+	ti->num_flush_requests = 1;
+	ti->private = fc;
+	return 0;
+
+bad:
+	kfree(fc);
+	return -EINVAL;
+}
+
+static void flakey_dtr(struct dm_target *ti)
+{
+	struct flakey_c *fc = ti->private;
+
+	dm_put_device(ti, fc->dev);
+	kfree(fc);
+}
+
+static sector_t flakey_map_sector(struct dm_target *ti, sector_t bi_sector)
+{
+	struct flakey_c *fc = ti->private;
+
+	return fc->start + (bi_sector - ti->begin);
+}
+
+static void flakey_map_bio(struct dm_target *ti, struct bio *bio)
+{
+	struct flakey_c *fc = ti->private;
+
+	bio->bi_bdev = fc->dev->bdev;
+	if (bio_sectors(bio))
+		bio->bi_sector = flakey_map_sector(ti, bio->bi_sector);
+}
+
+static int flakey_map(struct dm_target *ti, struct bio *bio,
+		      union map_info *map_context)
+{
+	struct flakey_c *fc = ti->private;
+	unsigned elapsed;
+
+	/* Are we alive ? */
+	elapsed = (jiffies - fc->start_time) / HZ;
+	if (elapsed % (fc->up_interval + fc->down_interval) >= fc->up_interval)
+		return -EIO;
+
+	flakey_map_bio(ti, bio);
+
+	return DM_MAPIO_REMAPPED;
+}
+
+static int flakey_status(struct dm_target *ti, status_type_t type,
+			 char *result, unsigned int maxlen)
+{
+	struct flakey_c *fc = ti->private;
+
+	switch (type) {
+	case STATUSTYPE_INFO:
+		result[0] = '\0';
+		break;
+
+	case STATUSTYPE_TABLE:
+		snprintf(result, maxlen, "%s %llu %u %u", fc->dev->name,
+			 (unsigned long long)fc->start, fc->up_interval,
+			 fc->down_interval);
+		break;
+	}
+	return 0;
+}
+
+static int flakey_ioctl(struct dm_target *ti, unsigned int cmd, unsigned long arg)
+{
+	struct flakey_c *fc = ti->private;
+
+	return __blkdev_driver_ioctl(fc->dev->bdev, fc->dev->mode, cmd, arg);
+}
+
+static int flakey_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+			struct bio_vec *biovec, int max_size)
+{
+	struct flakey_c *fc = ti->private;
+	struct request_queue *q = bdev_get_queue(fc->dev->bdev);
+
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = fc->dev->bdev;
+	bvm->bi_sector = flakey_map_sector(ti, bvm->bi_sector);
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
+static int flakey_iterate_devices(struct dm_target *ti, iterate_devices_callout_fn fn, void *data)
+{
+	struct flakey_c *fc = ti->private;
+
+	return fn(ti, fc->dev, fc->start, ti->len, data);
+}
+
+static struct target_type flakey_target = {
+	.name   = "flakey",
+	.version = {1, 1, 0},
+	.module = THIS_MODULE,
+	.ctr    = flakey_ctr,
+	.dtr    = flakey_dtr,
+	.map    = flakey_map,
+	.status = flakey_status,
+	.ioctl	= flakey_ioctl,
+	.merge	= flakey_merge,
+	.iterate_devices = flakey_iterate_devices,
+};
+
+static int __init dm_flakey_init(void)
+{
+	int r = dm_register_target(&flakey_target);
+
+	if (r < 0)
+		DMERR("register failed %d", r);
+
+	return r;
+}
+
+static void __exit dm_flakey_exit(void)
+{
+	dm_unregister_target(&flakey_target);
+}
+
+/* Module hooks */
+module_init(dm_flakey_init);
+module_exit(dm_flakey_exit);
+
+MODULE_DESCRIPTION(DM_NAME " flakey target");
+MODULE_AUTHOR("Joe Thornber <dm-devel@redhat.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm.h linux-libre-2.6.39-gnu/drivers/md/dm.h
--- linux-libre-2.6.38-gnu/drivers/md/dm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm.h	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
 /*
  * Mempool operations
  */
-struct dm_md_mempools *dm_alloc_md_mempools(unsigned type);
+struct dm_md_mempools *dm_alloc_md_mempools(unsigned type, unsigned integrity);
 void dm_free_md_mempools(struct dm_md_mempools *pools);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-io.c linux-libre-2.6.39-gnu/drivers/md/dm-io.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-io.c	2011-05-19 00:06:34.000000000 -0400
@@ -352,7 +352,7 @@
 	BUG_ON(num_regions > DM_IO_MAX_REGIONS);
 
 	if (sync)
-		rw |= REQ_SYNC | REQ_UNPLUG;
+		rw |= REQ_SYNC;
 
 	/*
 	 * For multiple regions we need to be careful to rewind
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-ioctl.c linux-libre-2.6.39-gnu/drivers/md/dm-ioctl.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -1501,14 +1501,10 @@
 	return r;
 }
 
-static void free_params(struct dm_ioctl *param)
-{
-	vfree(param);
-}
-
 static int copy_params(struct dm_ioctl __user *user, struct dm_ioctl **param)
 {
 	struct dm_ioctl tmp, *dmi;
+	int secure_data;
 
 	if (copy_from_user(&tmp, user, sizeof(tmp) - sizeof(tmp.data)))
 		return -EFAULT;
@@ -1516,17 +1512,30 @@
 	if (tmp.data_size < (sizeof(tmp) - sizeof(tmp.data)))
 		return -EINVAL;
 
+	secure_data = tmp.flags & DM_SECURE_DATA_FLAG;
+
 	dmi = vmalloc(tmp.data_size);
-	if (!dmi)
+	if (!dmi) {
+		if (secure_data && clear_user(user, tmp.data_size))
+			return -EFAULT;
 		return -ENOMEM;
-
-	if (copy_from_user(dmi, user, tmp.data_size)) {
-		vfree(dmi);
-		return -EFAULT;
 	}
 
+	if (copy_from_user(dmi, user, tmp.data_size))
+		goto bad;
+
+	/* Wipe the user buffer so we do not return it to userspace */
+	if (secure_data && clear_user(user, tmp.data_size))
+		goto bad;
+
 	*param = dmi;
 	return 0;
+
+bad:
+	if (secure_data)
+		memset(dmi, 0, tmp.data_size);
+	vfree(dmi);
+	return -EFAULT;
 }
 
 static int validate_params(uint cmd, struct dm_ioctl *param)
@@ -1534,6 +1543,7 @@
 	/* Always clear this flag */
 	param->flags &= ~DM_BUFFER_FULL_FLAG;
 	param->flags &= ~DM_UEVENT_GENERATED_FLAG;
+	param->flags &= ~DM_SECURE_DATA_FLAG;
 
 	/* Ignores parameters */
 	if (cmd == DM_REMOVE_ALL_CMD ||
@@ -1561,10 +1571,11 @@
 static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
 {
 	int r = 0;
+	int wipe_buffer;
 	unsigned int cmd;
 	struct dm_ioctl *uninitialized_var(param);
 	ioctl_fn fn = NULL;
-	size_t param_size;
+	size_t input_param_size;
 
 	/* only root can play with this */
 	if (!capable(CAP_SYS_ADMIN))
@@ -1611,13 +1622,15 @@
 	if (r)
 		return r;
 
+	input_param_size = param->data_size;
+	wipe_buffer = param->flags & DM_SECURE_DATA_FLAG;
+
 	r = validate_params(cmd, param);
 	if (r)
 		goto out;
 
-	param_size = param->data_size;
 	param->data_size = sizeof(*param);
-	r = fn(param, param_size);
+	r = fn(param, input_param_size);
 
 	/*
 	 * Copy the results back to userland.
@@ -1625,8 +1638,11 @@
 	if (!r && copy_to_user(user, param, param->data_size))
 		r = -EFAULT;
 
- out:
-	free_params(param);
+out:
+	if (wipe_buffer)
+		memset(param, 0, input_param_size);
+
+	vfree(param);
 	return r;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-kcopyd.c linux-libre-2.6.39-gnu/drivers/md/dm-kcopyd.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-kcopyd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-kcopyd.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,13 +37,6 @@
 	unsigned int nr_pages;
 	unsigned int nr_free_pages;
 
-	/*
-	 * Block devices to unplug.
-	 * Non-NULL pointer means that a block device has some pending requests
-	 * and needs to be unplugged.
-	 */
-	struct block_device *unplug[2];
-
 	struct dm_io_client *io_client;
 
 	wait_queue_head_t destroyq;
@@ -315,31 +308,6 @@
 	return 0;
 }
 
-/*
- * Unplug the block device at the specified index.
- */
-static void unplug(struct dm_kcopyd_client *kc, int rw)
-{
-	if (kc->unplug[rw] != NULL) {
-		blk_unplug(bdev_get_queue(kc->unplug[rw]));
-		kc->unplug[rw] = NULL;
-	}
-}
-
-/*
- * Prepare block device unplug. If there's another device
- * to be unplugged at the same array index, we unplug that
- * device first.
- */
-static void prepare_unplug(struct dm_kcopyd_client *kc, int rw,
-			   struct block_device *bdev)
-{
-	if (likely(kc->unplug[rw] == bdev))
-		return;
-	unplug(kc, rw);
-	kc->unplug[rw] = bdev;
-}
-
 static void complete_io(unsigned long error, void *context)
 {
 	struct kcopyd_job *job = (struct kcopyd_job *) context;
@@ -386,16 +354,10 @@
 		.client = job->kc->io_client,
 	};
 
-	if (job->rw == READ) {
+	if (job->rw == READ)
 		r = dm_io(&io_req, 1, &job->source, NULL);
-		prepare_unplug(job->kc, READ, job->source.bdev);
-	} else {
-		if (job->num_dests > 1)
-			io_req.bi_rw |= REQ_UNPLUG;
+	else
 		r = dm_io(&io_req, job->num_dests, job->dests, NULL);
-		if (!(io_req.bi_rw & REQ_UNPLUG))
-			prepare_unplug(job->kc, WRITE, job->dests[0].bdev);
-	}
 
 	return r;
 }
@@ -466,6 +428,7 @@
 {
 	struct dm_kcopyd_client *kc = container_of(work,
 					struct dm_kcopyd_client, kcopyd_work);
+	struct blk_plug plug;
 
 	/*
 	 * The order that these are called is *very* important.
@@ -473,18 +436,12 @@
 	 * Pages jobs when successful will jump onto the io jobs
 	 * list.  io jobs call wake when they complete and it all
 	 * starts again.
-	 *
-	 * Note that io_jobs add block devices to the unplug array,
-	 * this array is cleared with "unplug" calls. It is thus
-	 * forbidden to run complete_jobs after io_jobs and before
-	 * unplug because the block device could be destroyed in
-	 * job completion callback.
 	 */
+	blk_start_plug(&plug);
 	process_jobs(&kc->complete_jobs, kc, run_complete_job);
 	process_jobs(&kc->pages_jobs, kc, run_pages_job);
 	process_jobs(&kc->io_jobs, kc, run_io_job);
-	unplug(kc, READ);
-	unplug(kc, WRITE);
+	blk_finish_plug(&plug);
 }
 
 /*
@@ -665,8 +622,6 @@
 	INIT_LIST_HEAD(&kc->io_jobs);
 	INIT_LIST_HEAD(&kc->pages_jobs);
 
-	memset(kc->unplug, 0, sizeof(kc->unplug));
-
 	kc->job_pool = mempool_create_slab_pool(MIN_JOBS, _job_cache);
 	if (!kc->job_pool)
 		goto bad_slab;
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-log.c linux-libre-2.6.39-gnu/drivers/md/dm-log.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-log.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-log.c	2011-05-19 00:06:34.000000000 -0400
@@ -251,20 +251,20 @@
  */
 static inline int log_test_bit(uint32_t *bs, unsigned bit)
 {
-	return ext2_test_bit(bit, (unsigned long *) bs) ? 1 : 0;
+	return test_bit_le(bit, (unsigned long *) bs) ? 1 : 0;
 }
 
 static inline void log_set_bit(struct log_c *l,
 			       uint32_t *bs, unsigned bit)
 {
-	ext2_set_bit(bit, (unsigned long *) bs);
+	__test_and_set_bit_le(bit, (unsigned long *) bs);
 	l->touched_cleaned = 1;
 }
 
 static inline void log_clear_bit(struct log_c *l,
 				 uint32_t *bs, unsigned bit)
 {
-	ext2_clear_bit(bit, (unsigned long *) bs);
+	__test_and_clear_bit_le(bit, (unsigned long *) bs);
 	l->touched_dirtied = 1;
 }
 
@@ -543,7 +543,7 @@
 		return -EINVAL;
 	}
 
-	r = dm_get_device(ti, argv[0], FMODE_READ | FMODE_WRITE, &dev);
+	r = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &dev);
 	if (r)
 		return r;
 
@@ -740,7 +740,7 @@
 		return 0;
 
 	do {
-		*region = ext2_find_next_zero_bit(
+		*region = find_next_zero_bit_le(
 					     (unsigned long *) lc->sync_bits,
 					     lc->region_count,
 					     lc->sync_search);
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-log-userspace-transfer.c linux-libre-2.6.39-gnu/drivers/md/dm-log-userspace-transfer.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-log-userspace-transfer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-log-userspace-transfer.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,7 +134,7 @@
 {
 	struct dm_ulog_request *tfr = (struct dm_ulog_request *)(msg + 1);
 
-	if (!cap_raised(nsp->eff_cap, CAP_SYS_ADMIN))
+	if (!cap_raised(current_cap(), CAP_SYS_ADMIN))
 		return;
 
 	spin_lock(&receiving_list_lock);
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-mpath.c linux-libre-2.6.39-gnu/drivers/md/dm-mpath.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-mpath.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-mpath.c	2011-05-19 00:06:34.000000000 -0400
@@ -844,8 +844,8 @@
 {
 	/* target parameters */
 	static struct param _params[] = {
-		{1, 1024, "invalid number of priority groups"},
-		{1, 1024, "invalid initial priority group number"},
+		{0, 1024, "invalid number of priority groups"},
+		{0, 1024, "invalid initial priority group number"},
 	};
 
 	int r;
@@ -879,6 +879,13 @@
 	if (r)
 		goto bad;
 
+	if ((!m->nr_priority_groups && next_pg_num) ||
+	    (m->nr_priority_groups && !next_pg_num)) {
+		ti->error = "invalid initial priority group";
+		r = -EINVAL;
+		goto bad;
+	}
+
 	/* parse the priority groups */
 	while (as.argc) {
 		struct priority_group *pg;
@@ -1065,7 +1072,7 @@
 static int action_dev(struct multipath *m, struct dm_dev *dev,
 		      action_fn action)
 {
-	int r = 0;
+	int r = -EINVAL;
 	struct pgpath *pgpath;
 	struct priority_group *pg;
 
@@ -1283,24 +1290,22 @@
 	if (!error && !clone->errors)
 		return 0;	/* I/O complete */
 
-	if (error == -EOPNOTSUPP)
-		return error;
-
-	if (clone->cmd_flags & REQ_DISCARD)
-		/*
-		 * Pass all discard request failures up.
-		 * FIXME: only fail_path if the discard failed due to a
-		 * transport problem.  This requires precise understanding
-		 * of the underlying failure (e.g. the SCSI sense).
-		 */
+	if (error == -EOPNOTSUPP || error == -EREMOTEIO)
 		return error;
 
 	if (mpio->pgpath)
 		fail_path(mpio->pgpath);
 
 	spin_lock_irqsave(&m->lock, flags);
-	if (!m->nr_valid_paths && !m->queue_if_no_path && !__must_push_back(m))
-		r = -EIO;
+	if (!m->nr_valid_paths) {
+		if (!m->queue_if_no_path) {
+			if (!__must_push_back(m))
+				r = -EIO;
+		} else {
+			if (error == -EBADE)
+				r = error;
+		}
+	}
 	spin_unlock_irqrestore(&m->lock, flags);
 
 	return r;
@@ -1417,7 +1422,7 @@
 	else if (m->current_pg)
 		pg_num = m->current_pg->pg_num;
 	else
-			pg_num = 1;
+		pg_num = (m->nr_priority_groups ? 1 : 0);
 
 	DMEMIT("%u ", pg_num);
 
@@ -1671,7 +1676,7 @@
  *---------------------------------------------------------------*/
 static struct target_type multipath_target = {
 	.name = "multipath",
-	.version = {1, 2, 0},
+	.version = {1, 3, 0},
 	.module = THIS_MODULE,
 	.ctr = multipath_ctr,
 	.dtr = multipath_dtr,
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-raid1.c linux-libre-2.6.39-gnu/drivers/md/dm-raid1.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-raid1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-raid1.c	2011-05-19 00:06:34.000000000 -0400
@@ -842,8 +842,6 @@
 	do_reads(ms, &reads);
 	do_writes(ms, &writes);
 	do_failures(ms, &failures);
-
-	dm_table_unplug_all(ms->ti->table);
 }
 
 /*-----------------------------------------------------------------
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-raid.c linux-libre-2.6.39-gnu/drivers/md/dm-raid.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-raid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-raid.c	2011-05-19 00:06:34.000000000 -0400
@@ -390,13 +390,6 @@
 	return md_raid5_congested(&rs->md, bits);
 }
 
-static void raid_unplug(struct dm_target_callbacks *cb)
-{
-	struct raid_set *rs = container_of(cb, struct raid_set, callbacks);
-
-	md_raid5_unplug_device(rs->md.private);
-}
-
 /*
  * Construct a RAID4/5/6 mapping:
  * Args:
@@ -487,7 +480,6 @@
 	}
 
 	rs->callbacks.congested_fn = raid_is_congested;
-	rs->callbacks.unplug_fn = raid_unplug;
 	dm_table_add_target_callbacks(ti->table, &rs->callbacks);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-region-hash.c linux-libre-2.6.39-gnu/drivers/md/dm-region-hash.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-region-hash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-region-hash.c	2011-05-19 00:06:34.000000000 -0400
@@ -419,7 +419,7 @@
 	/*
 	 * Possible cases:
 	 *   1) DM_RH_DIRTY
-	 *   2) DM_RH_NOSYNC: was dirty, other preceeding writes failed
+	 *   2) DM_RH_NOSYNC: was dirty, other preceding writes failed
 	 *   3) DM_RH_RECOVERING: flushing pending writes
 	 * Either case, the region should have not been connected to list.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-snap.c linux-libre-2.6.39-gnu/drivers/md/dm-snap.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-snap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-snap.c	2011-05-19 00:06:34.000000000 -0400
@@ -1080,7 +1080,7 @@
 	argv++;
 	argc--;
 
-	r = dm_get_device(ti, cow_path, FMODE_READ | FMODE_WRITE, &s->cow);
+	r = dm_get_device(ti, cow_path, dm_table_get_mode(ti->table), &s->cow);
 	if (r) {
 		ti->error = "Cannot get COW device";
 		goto bad_cow;
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-stripe.c linux-libre-2.6.39-gnu/drivers/md/dm-stripe.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-stripe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-stripe.c	2011-05-19 00:06:34.000000000 -0400
@@ -396,9 +396,29 @@
 	blk_limits_io_opt(limits, chunk_size * sc->stripes);
 }
 
+static int stripe_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
+			struct bio_vec *biovec, int max_size)
+{
+	struct stripe_c *sc = ti->private;
+	sector_t bvm_sector = bvm->bi_sector;
+	uint32_t stripe;
+	struct request_queue *q;
+
+	stripe_map_sector(sc, bvm_sector, &stripe, &bvm_sector);
+
+	q = bdev_get_queue(sc->stripe[stripe].dev->bdev);
+	if (!q->merge_bvec_fn)
+		return max_size;
+
+	bvm->bi_bdev = sc->stripe[stripe].dev->bdev;
+	bvm->bi_sector = sc->stripe[stripe].physical_start + bvm_sector;
+
+	return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
+}
+
 static struct target_type stripe_target = {
 	.name   = "striped",
-	.version = {1, 3, 1},
+	.version = {1, 4, 0},
 	.module = THIS_MODULE,
 	.ctr    = stripe_ctr,
 	.dtr    = stripe_dtr,
@@ -407,6 +427,7 @@
 	.status = stripe_status,
 	.iterate_devices = stripe_iterate_devices,
 	.io_hints = stripe_io_hints,
+	.merge  = stripe_merge,
 };
 
 int __init dm_stripe_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/md/dm-table.c linux-libre-2.6.39-gnu/drivers/md/dm-table.c
--- linux-libre-2.6.38-gnu/drivers/md/dm-table.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/dm-table.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,6 +55,7 @@
 	struct dm_target *targets;
 
 	unsigned discards_supported:1;
+	unsigned integrity_supported:1;
 
 	/*
 	 * Indicates the rw permissions for the new logical
@@ -859,7 +860,7 @@
 		return -EINVAL;
 	}
 
-	t->mempools = dm_alloc_md_mempools(type);
+	t->mempools = dm_alloc_md_mempools(type, t->integrity_supported);
 	if (!t->mempools)
 		return -ENOMEM;
 
@@ -926,18 +927,80 @@
 }
 
 /*
+ * Get a disk whose integrity profile reflects the table's profile.
+ * If %match_all is true, all devices' profiles must match.
+ * If %match_all is false, all devices must at least have an
+ * allocated integrity profile; but uninitialized is ok.
+ * Returns NULL if integrity support was inconsistent or unavailable.
+ */
+static struct gendisk * dm_table_get_integrity_disk(struct dm_table *t,
+						    bool match_all)
+{
+	struct list_head *devices = dm_table_get_devices(t);
+	struct dm_dev_internal *dd = NULL;
+	struct gendisk *prev_disk = NULL, *template_disk = NULL;
+
+	list_for_each_entry(dd, devices, list) {
+		template_disk = dd->dm_dev.bdev->bd_disk;
+		if (!blk_get_integrity(template_disk))
+			goto no_integrity;
+		if (!match_all && !blk_integrity_is_initialized(template_disk))
+			continue; /* skip uninitialized profiles */
+		else if (prev_disk &&
+			 blk_integrity_compare(prev_disk, template_disk) < 0)
+			goto no_integrity;
+		prev_disk = template_disk;
+	}
+
+	return template_disk;
+
+no_integrity:
+	if (prev_disk)
+		DMWARN("%s: integrity not set: %s and %s profile mismatch",
+		       dm_device_name(t->md),
+		       prev_disk->disk_name,
+		       template_disk->disk_name);
+	return NULL;
+}
+
+/*
  * Register the mapped device for blk_integrity support if
- * the underlying devices support it.
+ * the underlying devices have an integrity profile.  But all devices
+ * may not have matching profiles (checking all devices isn't reliable
+ * during table load because this table may use other DM device(s) which
+ * must be resumed before they will have an initialized integity profile).
+ * Stacked DM devices force a 2 stage integrity profile validation:
+ * 1 - during load, validate all initialized integrity profiles match
+ * 2 - during resume, validate all integrity profiles match
  */
 static int dm_table_prealloc_integrity(struct dm_table *t, struct mapped_device *md)
 {
-	struct list_head *devices = dm_table_get_devices(t);
-	struct dm_dev_internal *dd;
+	struct gendisk *template_disk = NULL;
 
-	list_for_each_entry(dd, devices, list)
-		if (bdev_get_integrity(dd->dm_dev.bdev))
-			return blk_integrity_register(dm_disk(md), NULL);
+	template_disk = dm_table_get_integrity_disk(t, false);
+	if (!template_disk)
+		return 0;
+
+	if (!blk_integrity_is_initialized(dm_disk(md))) {
+		t->integrity_supported = 1;
+		return blk_integrity_register(dm_disk(md), NULL);
+	}
 
+	/*
+	 * If DM device already has an initalized integrity
+	 * profile the new profile should not conflict.
+	 */
+	if (blk_integrity_is_initialized(template_disk) &&
+	    blk_integrity_compare(dm_disk(md), template_disk) < 0) {
+		DMWARN("%s: conflict with existing integrity profile: "
+		       "%s profile mismatch",
+		       dm_device_name(t->md),
+		       template_disk->disk_name);
+		return 1;
+	}
+
+	/* Preserve existing initialized integrity profile */
+	t->integrity_supported = 1;
 	return 0;
 }
 
@@ -1091,41 +1154,27 @@
 
 /*
  * Set the integrity profile for this device if all devices used have
- * matching profiles.
+ * matching profiles.  We're quite deep in the resume path but still
+ * don't know if all devices (particularly DM devices this device
+ * may be stacked on) have matching profiles.  Even if the profiles
+ * don't match we have no way to fail (to resume) at this point.
  */
 static void dm_table_set_integrity(struct dm_table *t)
 {
-	struct list_head *devices = dm_table_get_devices(t);
-	struct dm_dev_internal *prev = NULL, *dd = NULL;
+	struct gendisk *template_disk = NULL;
 
 	if (!blk_get_integrity(dm_disk(t->md)))
 		return;
 
-	list_for_each_entry(dd, devices, list) {
-		if (prev &&
-		    blk_integrity_compare(prev->dm_dev.bdev->bd_disk,
-					  dd->dm_dev.bdev->bd_disk) < 0) {
-			DMWARN("%s: integrity not set: %s and %s mismatch",
-			       dm_device_name(t->md),
-			       prev->dm_dev.bdev->bd_disk->disk_name,
-			       dd->dm_dev.bdev->bd_disk->disk_name);
-			goto no_integrity;
-		}
-		prev = dd;
+	template_disk = dm_table_get_integrity_disk(t, true);
+	if (!template_disk &&
+	    blk_integrity_is_initialized(dm_disk(t->md))) {
+		DMWARN("%s: device no longer has a valid integrity profile",
+		       dm_device_name(t->md));
+		return;
 	}
-
-	if (!prev || !bdev_get_integrity(prev->dm_dev.bdev))
-		goto no_integrity;
-
 	blk_integrity_register(dm_disk(t->md),
-			       bdev_get_integrity(prev->dm_dev.bdev));
-
-	return;
-
-no_integrity:
-	blk_integrity_register(dm_disk(t->md), NULL);
-
-	return;
+			       blk_get_integrity(template_disk));
 }
 
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
@@ -1275,29 +1324,6 @@
 	return 0;
 }
 
-void dm_table_unplug_all(struct dm_table *t)
-{
-	struct dm_dev_internal *dd;
-	struct list_head *devices = dm_table_get_devices(t);
-	struct dm_target_callbacks *cb;
-
-	list_for_each_entry(dd, devices, list) {
-		struct request_queue *q = bdev_get_queue(dd->dm_dev.bdev);
-		char b[BDEVNAME_SIZE];
-
-		if (likely(q))
-			blk_unplug(q);
-		else
-			DMWARN_LIMIT("%s: Cannot unplug nonexistent device %s",
-				     dm_device_name(t->md),
-				     bdevname(dd->dm_dev.bdev, b));
-	}
-
-	list_for_each_entry(cb, &t->target_callbacks, list)
-		if (cb->unplug_fn)
-			cb->unplug_fn(cb);
-}
-
 struct mapped_device *dm_table_get_md(struct dm_table *t)
 {
 	return t->md;
@@ -1345,4 +1371,3 @@
 EXPORT_SYMBOL(dm_table_get_md);
 EXPORT_SYMBOL(dm_table_put);
 EXPORT_SYMBOL(dm_table_get);
-EXPORT_SYMBOL(dm_table_unplug_all);
diff -druN linux-libre-2.6.38-gnu/drivers/md/faulty.c linux-libre-2.6.39-gnu/drivers/md/faulty.c
--- linux-libre-2.6.38-gnu/drivers/md/faulty.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/faulty.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
  *
  * Different modes can be active at a time, but only
  * one can be set at array creation.  Others can be added later.
- * A mode can be one-shot or recurrent with the recurrance being
+ * A mode can be one-shot or recurrent with the recurrence being
  * once in every N requests.
  * The bottom 5 bits of the "layout" indicate the mode.  The
  * remainder indicate a period, or 0 for one-shot.
diff -druN linux-libre-2.6.38-gnu/drivers/md/Kconfig linux-libre-2.6.39-gnu/drivers/md/Kconfig
--- linux-libre-2.6.38-gnu/drivers/md/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -327,4 +327,10 @@
 	---help---
 	Generate udev events for DM events.
 
+config DM_FLAKEY
+       tristate "Flakey target (EXPERIMENTAL)"
+       depends on BLK_DEV_DM && EXPERIMENTAL
+       ---help---
+         A target that intermittently fails I/O for debugging purposes.
+
 endif # MD
diff -druN linux-libre-2.6.38-gnu/drivers/md/linear.c linux-libre-2.6.39-gnu/drivers/md/linear.c
--- linux-libre-2.6.38-gnu/drivers/md/linear.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/linear.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,22 +87,6 @@
 	return maxsectors << 9;
 }
 
-static void linear_unplug(struct request_queue *q)
-{
-	mddev_t *mddev = q->queuedata;
-	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;
@@ -224,11 +208,9 @@
 	md_set_array_sectors(mddev, linear_size(mddev, 0, 0));
 
 	blk_queue_merge_bvec(mddev->queue, linear_mergeable_bvec);
-	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;
+	return md_integrity_register(mddev);
 }
 
 static void free_conf(struct rcu_head *head)
diff -druN linux-libre-2.6.38-gnu/drivers/md/Makefile linux-libre-2.6.39-gnu/drivers/md/Makefile
--- linux-libre-2.6.38-gnu/drivers/md/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 obj-$(CONFIG_BLK_DEV_DM)	+= dm-mod.o
 obj-$(CONFIG_DM_CRYPT)		+= dm-crypt.o
 obj-$(CONFIG_DM_DELAY)		+= dm-delay.o
+obj-$(CONFIG_DM_FLAKEY)		+= dm-flakey.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
diff -druN linux-libre-2.6.38-gnu/drivers/md/md.c linux-libre-2.6.39-gnu/drivers/md/md.c
--- linux-libre-2.6.38-gnu/drivers/md/md.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/md.c	2011-05-19 00:06:34.000000000 -0400
@@ -447,48 +447,59 @@
 
 /* Support for plugging.
  * This mirrors the plugging support in request_queue, but does not
- * require having a whole queue
+ * require having a whole queue or request structures.
+ * We allocate an md_plug_cb for each md device and each thread it gets
+ * plugged on.  This links tot the private plug_handle structure in the
+ * personality data where we keep a count of the number of outstanding
+ * plugs so other code can see if a plug is active.
  */
-static void plugger_work(struct work_struct *work)
-{
-	struct plug_handle *plug =
-		container_of(work, struct plug_handle, unplug_work);
-	plug->unplug_fn(plug);
-}
-static void plugger_timeout(unsigned long data)
-{
-	struct plug_handle *plug = (void *)data;
-	kblockd_schedule_work(NULL, &plug->unplug_work);
-}
-void plugger_init(struct plug_handle *plug,
-		  void (*unplug_fn)(struct plug_handle *))
-{
-	plug->unplug_flag = 0;
-	plug->unplug_fn = unplug_fn;
-	init_timer(&plug->unplug_timer);
-	plug->unplug_timer.function = plugger_timeout;
-	plug->unplug_timer.data = (unsigned long)plug;
-	INIT_WORK(&plug->unplug_work, plugger_work);
-}
-EXPORT_SYMBOL_GPL(plugger_init);
+struct md_plug_cb {
+	struct blk_plug_cb cb;
+	mddev_t *mddev;
+};
 
-void plugger_set_plug(struct plug_handle *plug)
+static void plugger_unplug(struct blk_plug_cb *cb)
 {
-	if (!test_and_set_bit(PLUGGED_FLAG, &plug->unplug_flag))
-		mod_timer(&plug->unplug_timer, jiffies + msecs_to_jiffies(3)+1);
+	struct md_plug_cb *mdcb = container_of(cb, struct md_plug_cb, cb);
+	if (atomic_dec_and_test(&mdcb->mddev->plug_cnt))
+		md_wakeup_thread(mdcb->mddev->thread);
+	kfree(mdcb);
 }
-EXPORT_SYMBOL_GPL(plugger_set_plug);
 
-int plugger_remove_plug(struct plug_handle *plug)
+/* Check that an unplug wakeup will come shortly.
+ * If not, wakeup the md thread immediately
+ */
+int mddev_check_plugged(mddev_t *mddev)
 {
-	if (test_and_clear_bit(PLUGGED_FLAG, &plug->unplug_flag)) {
-		del_timer(&plug->unplug_timer);
-		return 1;
-	} else
+	struct blk_plug *plug = current->plug;
+	struct md_plug_cb *mdcb;
+
+	if (!plug)
+		return 0;
+
+	list_for_each_entry(mdcb, &plug->cb_list, cb.list) {
+		if (mdcb->cb.callback == plugger_unplug &&
+		    mdcb->mddev == mddev) {
+			/* Already on the list, move to top */
+			if (mdcb != list_first_entry(&plug->cb_list,
+						    struct md_plug_cb,
+						    cb.list))
+				list_move(&mdcb->cb.list, &plug->cb_list);
+			return 1;
+		}
+	}
+	/* Not currently on the callback list */
+	mdcb = kmalloc(sizeof(*mdcb), GFP_ATOMIC);
+	if (!mdcb)
 		return 0;
-}
-EXPORT_SYMBOL_GPL(plugger_remove_plug);
 
+	mdcb->mddev = mddev;
+	mdcb->cb.callback = plugger_unplug;
+	atomic_inc(&mddev->plug_cnt);
+	list_add(&mdcb->cb.list, &plug->cb_list);
+	return 1;
+}
+EXPORT_SYMBOL_GPL(mddev_check_plugged);
 
 static inline mddev_t *mddev_get(mddev_t *mddev)
 {
@@ -538,6 +549,7 @@
 	atomic_set(&mddev->active, 1);
 	atomic_set(&mddev->openers, 0);
 	atomic_set(&mddev->active_io, 0);
+	atomic_set(&mddev->plug_cnt, 0);
 	spin_lock_init(&mddev->write_lock);
 	atomic_set(&mddev->flush_pending, 0);
 	init_waitqueue_head(&mddev->sb_wait);
@@ -780,8 +792,7 @@
 	bio->bi_end_io = super_written;
 
 	atomic_inc(&mddev->pending_writes);
-	submit_bio(REQ_WRITE | REQ_SYNC | REQ_UNPLUG | REQ_FLUSH | REQ_FUA,
-		   bio);
+	submit_bio(REQ_WRITE | REQ_SYNC | REQ_FLUSH | REQ_FUA, bio);
 }
 
 void md_super_wait(mddev_t *mddev)
@@ -809,7 +820,7 @@
 	struct completion event;
 	int ret;
 
-	rw |= REQ_SYNC | REQ_UNPLUG;
+	rw |= REQ_SYNC;
 
 	bio->bi_bdev = (metadata_op && rdev->meta_bdev) ?
 		rdev->meta_bdev : rdev->bdev;
@@ -1778,12 +1789,6 @@
 			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;
@@ -1794,6 +1799,8 @@
 				rdev->bdev->bd_disk) < 0)
 			return -EINVAL;
 	}
+	if (!reference || !bdev_get_integrity(reference->bdev))
+		return 0;
 	/*
 	 * All component devices are integrity capable and have matching
 	 * profiles, register the common profile for the md device.
@@ -1804,8 +1811,12 @@
 			mdname(mddev));
 		return -EINVAL;
 	}
-	printk(KERN_NOTICE "md: data integrity on %s enabled\n",
-		mdname(mddev));
+	printk(KERN_NOTICE "md: data integrity enabled on %s\n", mdname(mddev));
+	if (bioset_integrity_create(mddev->bio_set, BIO_POOL_SIZE)) {
+		printk(KERN_ERR "md: failed to create integrity pool for %s\n",
+		       mdname(mddev));
+		return -EINVAL;
+	}
 	return 0;
 }
 EXPORT_SYMBOL(md_integrity_register);
@@ -3159,6 +3170,7 @@
 	mddev->layout = mddev->new_layout;
 	mddev->chunk_sectors = mddev->new_chunk_sectors;
 	mddev->delta_disks = 0;
+	mddev->degraded = 0;
 	if (mddev->pers->sync_request == NULL) {
 		/* this is now an array without redundancy, so
 		 * it must always be in_sync
@@ -4724,7 +4736,6 @@
 	mddev->bitmap_info.chunksize = 0;
 	mddev->bitmap_info.daemon_sleep = 0;
 	mddev->bitmap_info.max_write_behind = 0;
-	mddev->plug = NULL;
 }
 
 static void __md_stop_writes(mddev_t *mddev)
@@ -4817,7 +4828,6 @@
 		__md_stop_writes(mddev);
 		md_stop(mddev);
 		mddev->queue->merge_bvec_fn = NULL;
-		mddev->queue->unplug_fn = NULL;
 		mddev->queue->backing_dev_info.congested_fn = NULL;
 
 		/* tell userspace to handle 'inactive' */
@@ -6268,7 +6278,7 @@
 	 * rt is a sector_t, so could be 32bit or 64bit.
 	 * So we divide before multiply in case it is 32bit and close
 	 * to the limit.
-	 * We scale the divisor (db) by 32 to avoid loosing precision
+	 * We scale the divisor (db) by 32 to avoid losing precision
 	 * near the end of resync when the number of remaining sectors
 	 * is close to 'db'.
 	 * We then divide rt by 32 after multiplying by db to compensate.
@@ -6690,14 +6700,6 @@
 }
 EXPORT_SYMBOL_GPL(md_allow_write);
 
-void md_unplug(mddev_t *mddev)
-{
-	if (mddev->queue)
-		blk_unplug(mddev->queue);
-	if (mddev->plug)
-		mddev->plug->unplug_fn(mddev->plug);
-}
-
 #define SYNC_MARKS	10
 #define	SYNC_MARK_STEP	(3*HZ)
 void md_do_sync(mddev_t *mddev)
@@ -6876,7 +6878,6 @@
 		     >= mddev->resync_max - mddev->curr_resync_completed
 			    )) {
 			/* time to update curr_resync_completed */
-			md_unplug(mddev);
 			wait_event(mddev->recovery_wait,
 				   atomic_read(&mddev->recovery_active) == 0);
 			mddev->curr_resync_completed = j;
@@ -6952,7 +6953,6 @@
 		 * about not overloading the IO subsystem. (things like an
 		 * e2fsck being done on the RAID array should execute fast)
 		 */
-		md_unplug(mddev);
 		cond_resched();
 
 		currspeed = ((unsigned long)(io_sectors-mddev->resync_mark_cnt))/2
@@ -6971,8 +6971,6 @@
 	 * this also signals 'finished resyncing' to md_stop
 	 */
  out:
-	md_unplug(mddev);
-
 	wait_event(mddev->recovery_wait, !atomic_read(&mddev->recovery_active));
 
 	/* tell personality that we are finished */
@@ -7361,7 +7359,7 @@
 {
 	int ret = -ENOMEM;
 
-	md_wq = alloc_workqueue("md", WQ_RESCUER, 0);
+	md_wq = alloc_workqueue("md", WQ_MEM_RECLAIM, 0);
 	if (!md_wq)
 		goto err_wq;
 
diff -druN linux-libre-2.6.38-gnu/drivers/md/md.h linux-libre-2.6.39-gnu/drivers/md/md.h
--- linux-libre-2.6.38-gnu/drivers/md/md.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/md.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,26 +29,6 @@
 typedef struct mddev_s mddev_t;
 typedef struct mdk_rdev_s mdk_rdev_t;
 
-/* generic plugging support - like that provided with request_queue,
- * but does not require a request_queue
- */
-struct plug_handle {
-	void			(*unplug_fn)(struct plug_handle *);
-	struct timer_list	unplug_timer;
-	struct work_struct	unplug_work;
-	unsigned long		unplug_flag;
-};
-#define	PLUGGED_FLAG 1
-void plugger_init(struct plug_handle *plug,
-		  void (*unplug_fn)(struct plug_handle *));
-void plugger_set_plug(struct plug_handle *plug);
-int plugger_remove_plug(struct plug_handle *plug);
-static inline void plugger_flush(struct plug_handle *plug)
-{
-	del_timer_sync(&plug->unplug_timer);
-	cancel_work_sync(&plug->unplug_work);
-}
-
 /*
  * MD's 'extended' device
  */
@@ -94,7 +74,7 @@
 #define	In_sync		2		/* device is in_sync with rest of array */
 #define	WriteMostly	4		/* Avoid reading if at all possible */
 #define	AutoDetected	7		/* added by auto-detect */
-#define Blocked		8		/* An error occured on an externally
+#define Blocked		8		/* An error occurred on an externally
 					 * managed array, don't allow writes
 					 * until it is cleared */
 	wait_queue_head_t blocked_wait;
@@ -199,6 +179,9 @@
 	int				delta_disks, new_level, new_layout;
 	int				new_chunk_sectors;
 
+	atomic_t			plug_cnt;	/* If device is expecting
+							 * more bios soon.
+							 */
 	struct mdk_thread_s		*thread;	/* management thread */
 	struct mdk_thread_s		*sync_thread;	/* doing resync or reconstruct */
 	sector_t			curr_resync;	/* last block scheduled */
@@ -336,7 +319,6 @@
 	struct list_head		all_mddevs;
 
 	struct attribute_group		*to_remove;
-	struct plug_handle		*plug; /* if used by personality */
 
 	struct bio_set			*bio_set;
 
@@ -516,7 +498,6 @@
 extern void md_integrity_add_rdev(mdk_rdev_t *rdev, mddev_t *mddev);
 extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
 extern void restore_bitmap_write_access(struct file *file);
-extern void md_unplug(mddev_t *mddev);
 
 extern void mddev_init(mddev_t *mddev);
 extern int md_run(mddev_t *mddev);
@@ -530,4 +511,5 @@
 				   mddev_t *mddev);
 extern struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
 				   mddev_t *mddev);
+extern int mddev_check_plugged(mddev_t *mddev);
 #endif /* _MD_MD_H */
diff -druN linux-libre-2.6.38-gnu/drivers/md/multipath.c linux-libre-2.6.39-gnu/drivers/md/multipath.c
--- linux-libre-2.6.38-gnu/drivers/md/multipath.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/multipath.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,36 +106,6 @@
 	rdev_dec_pending(rdev, conf->mddev);
 }
 
-static void unplug_slaves(mddev_t *mddev)
-{
-	multipath_conf_t *conf = mddev->private;
-	int i;
-
-	rcu_read_lock();
-	for (i=0; i<mddev->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->multipaths[i].rdev);
-		if (rdev && !test_bit(Faulty, &rdev->flags)
-		    && atomic_read(&rdev->nr_pending)) {
-			struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
-
-			atomic_inc(&rdev->nr_pending);
-			rcu_read_unlock();
-
-			blk_unplug(r_queue);
-
-			rdev_dec_pending(rdev, mddev);
-			rcu_read_lock();
-		}
-	}
-	rcu_read_unlock();
-}
-
-static void multipath_unplug(struct request_queue *q)
-{
-	unplug_slaves(q->queuedata);
-}
-
-
 static int multipath_make_request(mddev_t *mddev, struct bio * bio)
 {
 	multipath_conf_t *conf = mddev->private;
@@ -345,7 +315,7 @@
 			p->rdev = rdev;
 			goto abort;
 		}
-		md_integrity_register(mddev);
+		err = md_integrity_register(mddev);
 	}
 abort:
 
@@ -517,10 +487,12 @@
 	 */
 	md_set_array_sectors(mddev, multipath_size(mddev, 0, 0));
 
-	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);
+
+	if (md_integrity_register(mddev))
+		goto out_free_conf;
+
 	return 0;
 
 out_free_conf:
diff -druN linux-libre-2.6.38-gnu/drivers/md/raid0.c linux-libre-2.6.39-gnu/drivers/md/raid0.c
--- linux-libre-2.6.38-gnu/drivers/md/raid0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/raid0.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,21 +25,6 @@
 #include "raid0.h"
 #include "raid5.h"
 
-static void raid0_unplug(struct request_queue *q)
-{
-	mddev_t *mddev = q->queuedata;
-	raid0_conf_t *conf = mddev->private;
-	mdk_rdev_t **devlist = conf->devlist;
-	int raid_disks = conf->strip_zone[0].nb_dev;
-	int i;
-
-	for (i=0; i < raid_disks; i++) {
-		struct request_queue *r_queue = bdev_get_queue(devlist[i]->bdev);
-
-		blk_unplug(r_queue);
-	}
-}
-
 static int raid0_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
@@ -272,7 +257,6 @@
 		       mdname(mddev),
 		       (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;
 
@@ -395,8 +379,7 @@
 
 	blk_queue_merge_bvec(mddev->queue, raid0_mergeable_bvec);
 	dump_zones(mddev);
-	md_integrity_register(mddev);
-	return 0;
+	return md_integrity_register(mddev);
 }
 
 static int raid0_stop(mddev_t *mddev)
diff -druN linux-libre-2.6.38-gnu/drivers/md/raid10.c linux-libre-2.6.39-gnu/drivers/md/raid10.c
--- linux-libre-2.6.38-gnu/drivers/md/raid10.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/raid10.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
  *
  * RAID-10 support for md.
  *
- * Base on code in raid1.c.  See raid1.c for futher copyright information.
+ * Base on code in raid1.c.  See raid1.c for further copyright information.
  *
  *
  * This program is free software; you can redistribute it and/or modify
@@ -57,23 +57,16 @@
  */
 #define	NR_RAID10_BIOS 256
 
-static void unplug_slaves(mddev_t *mddev);
-
 static void allow_barrier(conf_t *conf);
 static void lower_barrier(conf_t *conf);
 
 static void * r10bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	conf_t *conf = data;
-	r10bio_t *r10_bio;
 	int size = offsetof(struct r10bio_s, devs[conf->copies]);
 
 	/* allocate a r10bio with room for raid_disks entries in the bios array */
-	r10_bio = kzalloc(size, gfp_flags);
-	if (!r10_bio && conf->mddev)
-		unplug_slaves(conf->mddev);
-
-	return r10_bio;
+	return kzalloc(size, gfp_flags);
 }
 
 static void r10bio_pool_free(void *r10_bio, void *data)
@@ -106,10 +99,8 @@
 	int nalloc;
 
 	r10_bio = r10bio_pool_alloc(gfp_flags, conf);
-	if (!r10_bio) {
-		unplug_slaves(conf->mddev);
+	if (!r10_bio)
 		return NULL;
-	}
 
 	if (test_bit(MD_RECOVERY_SYNC, &conf->mddev->recovery))
 		nalloc = conf->copies; /* resync */
@@ -349,14 +340,14 @@
 
 /*
  * RAID10 layout manager
- * Aswell as the chunksize and raid_disks count, there are two
+ * As well as the chunksize and raid_disks count, there are two
  * parameters: near_copies and far_copies.
  * near_copies * far_copies must be <= raid_disks.
  * Normally one of these will be 1.
  * If both are 1, we get raid0.
  * If near_copies == raid_disks, we get raid1.
  *
- * Chunks are layed out in raid0 style with near_copies copies of the
+ * Chunks are laid out in raid0 style with near_copies copies of the
  * first chunk, followed by near_copies copies of the next chunk and
  * so on.
  * If far_copies > 1, then after 1/far_copies of the array has been assigned
@@ -597,37 +588,6 @@
 	return disk;
 }
 
-static void unplug_slaves(mddev_t *mddev)
-{
-	conf_t *conf = mddev->private;
-	int i;
-
-	rcu_read_lock();
-	for (i=0; i < conf->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
-		if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
-			struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
-
-			atomic_inc(&rdev->nr_pending);
-			rcu_read_unlock();
-
-			blk_unplug(r_queue);
-
-			rdev_dec_pending(rdev, mddev);
-			rcu_read_lock();
-		}
-	}
-	rcu_read_unlock();
-}
-
-static void raid10_unplug(struct request_queue *q)
-{
-	mddev_t *mddev = q->queuedata;
-
-	unplug_slaves(q->queuedata);
-	md_wakeup_thread(mddev->thread);
-}
-
 static int raid10_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
@@ -649,23 +609,16 @@
 	return ret;
 }
 
-static int flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(conf_t *conf)
 {
 	/* Any writes that have been queued but are awaiting
 	 * bitmap updates get flushed here.
-	 * We return 1 if any requests were actually submitted.
 	 */
-	int rv = 0;
-
 	spin_lock_irq(&conf->device_lock);
 
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
-		/* Spinlock only taken to quiet a warning */
-		spin_lock(conf->mddev->queue->queue_lock);
-		blk_remove_plug(conf->mddev->queue);
-		spin_unlock(conf->mddev->queue->queue_lock);
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to disk
 		 * before proceeding w/ I/O */
@@ -677,11 +630,10 @@
 			generic_make_request(bio);
 			bio = next;
 		}
-		rv = 1;
 	} else
 		spin_unlock_irq(&conf->device_lock);
-	return rv;
 }
+
 /* Barriers....
  * Sometimes we need to suspend IO while we do something else,
  * either some resync/recovery, or reconfigure the array.
@@ -711,17 +663,15 @@
 
 	/* Wait until no block IO is waiting (unless 'force') */
 	wait_event_lock_irq(conf->wait_barrier, force || !conf->nr_waiting,
-			    conf->resync_lock,
-			    raid10_unplug(conf->mddev->queue));
+			    conf->resync_lock, );
 
 	/* block any new IO from starting */
 	conf->barrier++;
 
-	/* No wait for all pending IO to complete */
+	/* Now wait for all pending IO to complete */
 	wait_event_lock_irq(conf->wait_barrier,
 			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock,
-			    raid10_unplug(conf->mddev->queue));
+			    conf->resync_lock, );
 
 	spin_unlock_irq(&conf->resync_lock);
 }
@@ -742,7 +692,7 @@
 		conf->nr_waiting++;
 		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
 				    conf->resync_lock,
-				    raid10_unplug(conf->mddev->queue));
+				    );
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
@@ -778,8 +728,8 @@
 	wait_event_lock_irq(conf->wait_barrier,
 			    conf->nr_pending == conf->nr_queued+1,
 			    conf->resync_lock,
-			    ({ flush_pending_writes(conf);
-			       raid10_unplug(conf->mddev->queue); }));
+			    flush_pending_writes(conf));
+
 	spin_unlock_irq(&conf->resync_lock);
 }
 
@@ -806,6 +756,7 @@
 	const unsigned long do_fua = (bio->bi_rw & REQ_FUA);
 	unsigned long flags;
 	mdk_rdev_t *blocked_rdev;
+	int plugged;
 
 	if (unlikely(bio->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bio);
@@ -914,6 +865,8 @@
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
 	 */
+	plugged = mddev_check_plugged(mddev);
+
 	raid10_find_phys(conf, r10_bio);
  retry_write:
 	blocked_rdev = NULL;
@@ -974,7 +927,6 @@
 		atomic_inc(&r10_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
-		blk_plug_device_unlocked(mddev->queue);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 
@@ -991,9 +943,8 @@
 	/* In case raid10d snuck in to freeze_array */
 	wake_up(&conf->wait_barrier);
 
-	if (do_sync)
+	if (do_sync || !mddev->bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
-
 	return 0;
 }
 
@@ -1233,7 +1184,7 @@
 			p->rdev = rdev;
 			goto abort;
 		}
-		md_integrity_register(mddev);
+		err = md_integrity_register(mddev);
 	}
 abort:
 
@@ -1684,15 +1635,16 @@
 	unsigned long flags;
 	conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
-	int unplug=0;
 	mdk_rdev_t *rdev;
+	struct blk_plug plug;
 
 	md_check_recovery(mddev);
 
+	blk_start_plug(&plug);
 	for (;;) {
 		char b[BDEVNAME_SIZE];
 
-		unplug += flush_pending_writes(conf);
+		flush_pending_writes(conf);
 
 		spin_lock_irqsave(&conf->device_lock, flags);
 		if (list_empty(head)) {
@@ -1706,13 +1658,11 @@
 
 		mddev = r10_bio->mddev;
 		conf = mddev->private;
-		if (test_bit(R10BIO_IsSync, &r10_bio->state)) {
+		if (test_bit(R10BIO_IsSync, &r10_bio->state))
 			sync_request_write(mddev, r10_bio);
-			unplug = 1;
-		} else 	if (test_bit(R10BIO_IsRecover, &r10_bio->state)) {
+		else if (test_bit(R10BIO_IsRecover, &r10_bio->state))
 			recovery_request_write(mddev, r10_bio);
-			unplug = 1;
-		} else {
+		else {
 			int mirror;
 			/* we got a read error. Maybe the drive is bad.  Maybe just
 			 * the block and we can fix it.
@@ -1759,14 +1709,12 @@
 				bio->bi_rw = READ | do_sync;
 				bio->bi_private = r10_bio;
 				bio->bi_end_io = raid10_end_read_request;
-				unplug = 1;
 				generic_make_request(bio);
 			}
 		}
 		cond_resched();
 	}
-	if (unplug)
-		unplug_slaves(mddev);
+	blk_finish_plug(&plug);
 }
 
 
@@ -2377,7 +2325,6 @@
 	md_set_array_sectors(mddev, size);
 	mddev->resync_max_sectors = size;
 
-	mddev->queue->unplug_fn = raid10_unplug;
 	mddev->queue->backing_dev_info.congested_fn = raid10_congested;
 	mddev->queue->backing_dev_info.congested_data = mddev;
 
@@ -2395,7 +2342,10 @@
 
 	if (conf->near_copies < conf->raid_disks)
 		blk_queue_merge_bvec(mddev->queue, raid10_mergeable_bvec);
-	md_integrity_register(mddev);
+
+	if (md_integrity_register(mddev))
+		goto out_free_conf;
+
 	return 0;
 
 out_free_conf:
diff -druN linux-libre-2.6.38-gnu/drivers/md/raid10.h linux-libre-2.6.39-gnu/drivers/md/raid10.h
--- linux-libre-2.6.38-gnu/drivers/md/raid10.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/raid10.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,8 +17,8 @@
 	spinlock_t		device_lock;
 
 	/* geometry */
-	int			near_copies;  /* number of copies layed out raid0 style */
-	int 			far_copies;   /* number of copies layed out
+	int			near_copies;  /* number of copies laid out raid0 style */
+	int 			far_copies;   /* number of copies laid out
 					       * at large strides across drives
 					       */
 	int			far_offset;   /* far_copies are offset by 1 stripe
diff -druN linux-libre-2.6.38-gnu/drivers/md/raid1.c linux-libre-2.6.39-gnu/drivers/md/raid1.c
--- linux-libre-2.6.38-gnu/drivers/md/raid1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/raid1.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,23 +52,16 @@
 #define	NR_RAID1_BIOS 256
 
 
-static void unplug_slaves(mddev_t *mddev);
-
 static void allow_barrier(conf_t *conf);
 static void lower_barrier(conf_t *conf);
 
 static void * r1bio_pool_alloc(gfp_t gfp_flags, void *data)
 {
 	struct pool_info *pi = data;
-	r1bio_t *r1_bio;
 	int size = offsetof(r1bio_t, bios[pi->raid_disks]);
 
 	/* allocate a r1bio with room for raid_disks entries in the bios array */
-	r1_bio = kzalloc(size, gfp_flags);
-	if (!r1_bio && pi->mddev)
-		unplug_slaves(pi->mddev);
-
-	return r1_bio;
+	return kzalloc(size, gfp_flags);
 }
 
 static void r1bio_pool_free(void *r1_bio, void *data)
@@ -91,10 +84,8 @@
 	int i, j;
 
 	r1_bio = r1bio_pool_alloc(gfp_flags, pi);
-	if (!r1_bio) {
-		unplug_slaves(pi->mddev);
+	if (!r1_bio)
 		return NULL;
-	}
 
 	/*
 	 * Allocate bios : 1 for reading, n-1 for writing
@@ -520,37 +511,6 @@
 	return new_disk;
 }
 
-static void unplug_slaves(mddev_t *mddev)
-{
-	conf_t *conf = mddev->private;
-	int i;
-
-	rcu_read_lock();
-	for (i=0; i<mddev->raid_disks; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->mirrors[i].rdev);
-		if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
-			struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
-
-			atomic_inc(&rdev->nr_pending);
-			rcu_read_unlock();
-
-			blk_unplug(r_queue);
-
-			rdev_dec_pending(rdev, mddev);
-			rcu_read_lock();
-		}
-	}
-	rcu_read_unlock();
-}
-
-static void raid1_unplug(struct request_queue *q)
-{
-	mddev_t *mddev = q->queuedata;
-
-	unplug_slaves(mddev);
-	md_wakeup_thread(mddev->thread);
-}
-
 static int raid1_congested(void *data, int bits)
 {
 	mddev_t *mddev = data;
@@ -580,23 +540,16 @@
 }
 
 
-static int flush_pending_writes(conf_t *conf)
+static void flush_pending_writes(conf_t *conf)
 {
 	/* Any writes that have been queued but are awaiting
 	 * bitmap updates get flushed here.
-	 * We return 1 if any requests were actually submitted.
 	 */
-	int rv = 0;
-
 	spin_lock_irq(&conf->device_lock);
 
 	if (conf->pending_bio_list.head) {
 		struct bio *bio;
 		bio = bio_list_get(&conf->pending_bio_list);
-		/* Only take the spinlock to quiet a warning */
-		spin_lock(conf->mddev->queue->queue_lock);
-		blk_remove_plug(conf->mddev->queue);
-		spin_unlock(conf->mddev->queue->queue_lock);
 		spin_unlock_irq(&conf->device_lock);
 		/* flush any pending bitmap writes to
 		 * disk before proceeding w/ I/O */
@@ -608,10 +561,8 @@
 			generic_make_request(bio);
 			bio = next;
 		}
-		rv = 1;
 	} else
 		spin_unlock_irq(&conf->device_lock);
-	return rv;
 }
 
 /* Barriers....
@@ -643,8 +594,7 @@
 
 	/* Wait until no block IO is waiting */
 	wait_event_lock_irq(conf->wait_barrier, !conf->nr_waiting,
-			    conf->resync_lock,
-			    raid1_unplug(conf->mddev->queue));
+			    conf->resync_lock, );
 
 	/* block any new IO from starting */
 	conf->barrier++;
@@ -652,8 +602,7 @@
 	/* Now wait for all pending IO to complete */
 	wait_event_lock_irq(conf->wait_barrier,
 			    !conf->nr_pending && conf->barrier < RESYNC_DEPTH,
-			    conf->resync_lock,
-			    raid1_unplug(conf->mddev->queue));
+			    conf->resync_lock, );
 
 	spin_unlock_irq(&conf->resync_lock);
 }
@@ -675,7 +624,7 @@
 		conf->nr_waiting++;
 		wait_event_lock_irq(conf->wait_barrier, !conf->barrier,
 				    conf->resync_lock,
-				    raid1_unplug(conf->mddev->queue));
+				    );
 		conf->nr_waiting--;
 	}
 	conf->nr_pending++;
@@ -711,8 +660,7 @@
 	wait_event_lock_irq(conf->wait_barrier,
 			    conf->nr_pending == conf->nr_queued+1,
 			    conf->resync_lock,
-			    ({ flush_pending_writes(conf);
-			       raid1_unplug(conf->mddev->queue); }));
+			    flush_pending_writes(conf));
 	spin_unlock_irq(&conf->resync_lock);
 }
 static void unfreeze_array(conf_t *conf)
@@ -774,6 +722,7 @@
 	const unsigned long do_sync = (bio->bi_rw & REQ_SYNC);
 	const unsigned long do_flush_fua = (bio->bi_rw & (REQ_FLUSH | REQ_FUA));
 	mdk_rdev_t *blocked_rdev;
+	int plugged;
 
 	/*
 	 * Register the new request and wait if the reconstruction
@@ -865,6 +814,8 @@
 	 * inc refcount on their rdev.  Record them by setting
 	 * bios[x] to bio
 	 */
+	plugged = mddev_check_plugged(mddev);
+
 	disks = conf->raid_disks;
  retry_write:
 	blocked_rdev = NULL;
@@ -962,7 +913,6 @@
 		atomic_inc(&r1_bio->remaining);
 		spin_lock_irqsave(&conf->device_lock, flags);
 		bio_list_add(&conf->pending_bio_list, mbio);
-		blk_plug_device_unlocked(mddev->queue);
 		spin_unlock_irqrestore(&conf->device_lock, flags);
 	}
 	r1_bio_write_done(r1_bio, bio->bi_vcnt, behind_pages, behind_pages != NULL);
@@ -971,7 +921,7 @@
 	/* In case raid1d snuck in to freeze_array */
 	wake_up(&conf->wait_barrier);
 
-	if (do_sync)
+	if (do_sync || !bitmap || !plugged)
 		md_wakeup_thread(mddev->thread);
 
 	return 0;
@@ -1178,7 +1128,7 @@
 			p->rdev = rdev;
 			goto abort;
 		}
-		md_integrity_register(mddev);
+		err = md_integrity_register(mddev);
 	}
 abort:
 
@@ -1561,15 +1511,17 @@
 	unsigned long flags;
 	conf_t *conf = mddev->private;
 	struct list_head *head = &conf->retry_list;
-	int unplug=0;
 	mdk_rdev_t *rdev;
+	struct blk_plug plug;
 
 	md_check_recovery(mddev);
-	
+
+	blk_start_plug(&plug);
 	for (;;) {
 		char b[BDEVNAME_SIZE];
 
-		unplug += flush_pending_writes(conf);
+		if (atomic_read(&mddev->plug_cnt) == 0)
+			flush_pending_writes(conf);
 
 		spin_lock_irqsave(&conf->device_lock, flags);
 		if (list_empty(head)) {
@@ -1583,10 +1535,9 @@
 
 		mddev = r1_bio->mddev;
 		conf = mddev->private;
-		if (test_bit(R1BIO_IsSync, &r1_bio->state)) {
+		if (test_bit(R1BIO_IsSync, &r1_bio->state))
 			sync_request_write(mddev, r1_bio);
-			unplug = 1;
-		} else {
+		else {
 			int disk;
 
 			/* we got a read error. Maybe the drive is bad.  Maybe just
@@ -1636,14 +1587,12 @@
 				bio->bi_end_io = raid1_end_read_request;
 				bio->bi_rw = READ | do_sync;
 				bio->bi_private = r1_bio;
-				unplug = 1;
 				generic_make_request(bio);
 			}
 		}
 		cond_resched();
 	}
-	if (unplug)
-		unplug_slaves(mddev);
+	blk_finish_plug(&plug);
 }
 
 
@@ -2066,11 +2015,9 @@
 
 	md_set_array_sectors(mddev, raid1_size(mddev, 0, 0));
 
-	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;
+	return md_integrity_register(mddev);
 }
 
 static int stop(mddev_t *mddev)
@@ -2092,7 +2039,6 @@
 
 	md_unregister_thread(mddev->thread);
 	mddev->thread = NULL;
-	blk_sync_queue(mddev->queue); /* the unplug fn references 'conf'*/
 	if (conf->r1bio_pool)
 		mempool_destroy(conf->r1bio_pool);
 	kfree(conf->mirrors);
diff -druN linux-libre-2.6.38-gnu/drivers/md/raid5.c linux-libre-2.6.39-gnu/drivers/md/raid5.c
--- linux-libre-2.6.38-gnu/drivers/md/raid5.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/raid5.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,12 +27,12 @@
  *
  * We group bitmap updates into batches.  Each batch has a number.
  * We may write out several batches at once, but that isn't very important.
- * conf->bm_write is the number of the last batch successfully written.
- * conf->bm_flush is the number of the last batch that was closed to
+ * conf->seq_write is the number of the last batch successfully written.
+ * conf->seq_flush is the number of the last batch that was closed to
  *    new additions.
  * When we discover that we will need to write to any block in a stripe
  * (in add_stripe_bio) we update the in-memory bitmap and record in sh->bm_seq
- * the number of the batch it will be in. This is bm_flush+1.
+ * the number of the batch it will be in. This is seq_flush+1.
  * When we are ready to do a write, if that batch hasn't been written yet,
  *   we plug the array and queue the stripe for later.
  * When an unplug happens, we increment bm_flush, thus closing the current
@@ -199,14 +199,12 @@
 		BUG_ON(!list_empty(&sh->lru));
 		BUG_ON(atomic_read(&conf->active_stripes)==0);
 		if (test_bit(STRIPE_HANDLE, &sh->state)) {
-			if (test_bit(STRIPE_DELAYED, &sh->state)) {
+			if (test_bit(STRIPE_DELAYED, &sh->state))
 				list_add_tail(&sh->lru, &conf->delayed_list);
-				plugger_set_plug(&conf->plug);
-			} else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
-				   sh->bm_seq - conf->seq_write > 0) {
+			else if (test_bit(STRIPE_BIT_DELAY, &sh->state) &&
+				   sh->bm_seq - conf->seq_write > 0)
 				list_add_tail(&sh->lru, &conf->bitmap_list);
-				plugger_set_plug(&conf->plug);
-			} else {
+			else {
 				clear_bit(STRIPE_BIT_DELAY, &sh->state);
 				list_add_tail(&sh->lru, &conf->handle_list);
 			}
@@ -433,8 +431,6 @@
 	return 0;
 }
 
-static void unplug_slaves(mddev_t *mddev);
-
 static struct stripe_head *
 get_active_stripe(raid5_conf_t *conf, sector_t sector,
 		  int previous, int noblock, int noquiesce)
@@ -463,8 +459,7 @@
 						     < (conf->max_nr_stripes *3/4)
 						     || !conf->inactive_blocked),
 						    conf->device_lock,
-						    md_raid5_unplug_device(conf)
-					);
+						    );
 				conf->inactive_blocked = 0;
 			} else
 				init_stripe(sh, sector, previous);
@@ -1473,8 +1468,7 @@
 		wait_event_lock_irq(conf->wait_for_stripe,
 				    !list_empty(&conf->inactive_list),
 				    conf->device_lock,
-				    unplug_slaves(conf->mddev)
-			);
+				    );
 		osh = get_free_stripe(conf);
 		spin_unlock_irq(&conf->device_lock);
 		atomic_set(&nsh->count, 1);
@@ -3627,8 +3621,7 @@
 				atomic_inc(&conf->preread_active_stripes);
 			list_add_tail(&sh->lru, &conf->hold_list);
 		}
-	} else
-		plugger_set_plug(&conf->plug);
+	}
 }
 
 static void activate_bit_delay(raid5_conf_t *conf)
@@ -3645,60 +3638,6 @@
 	}
 }
 
-static void unplug_slaves(mddev_t *mddev)
-{
-	raid5_conf_t *conf = mddev->private;
-	int i;
-	int devs = max(conf->raid_disks, conf->previous_raid_disks);
-
-	rcu_read_lock();
-	for (i = 0; i < devs; i++) {
-		mdk_rdev_t *rdev = rcu_dereference(conf->disks[i].rdev);
-		if (rdev && !test_bit(Faulty, &rdev->flags) && atomic_read(&rdev->nr_pending)) {
-			struct request_queue *r_queue = bdev_get_queue(rdev->bdev);
-
-			atomic_inc(&rdev->nr_pending);
-			rcu_read_unlock();
-
-			blk_unplug(r_queue);
-
-			rdev_dec_pending(rdev, mddev);
-			rcu_read_lock();
-		}
-	}
-	rcu_read_unlock();
-}
-
-void md_raid5_unplug_device(raid5_conf_t *conf)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&conf->device_lock, flags);
-
-	if (plugger_remove_plug(&conf->plug)) {
-		conf->seq_flush++;
-		raid5_activate_delayed(conf);
-	}
-	md_wakeup_thread(conf->mddev->thread);
-
-	spin_unlock_irqrestore(&conf->device_lock, flags);
-
-	unplug_slaves(conf->mddev);
-}
-EXPORT_SYMBOL_GPL(md_raid5_unplug_device);
-
-static void raid5_unplug(struct plug_handle *plug)
-{
-	raid5_conf_t *conf = container_of(plug, raid5_conf_t, plug);
-	md_raid5_unplug_device(conf);
-}
-
-static void raid5_unplug_queue(struct request_queue *q)
-{
-	mddev_t *mddev = q->queuedata;
-	md_raid5_unplug_device(mddev->private);
-}
-
 int md_raid5_congested(mddev_t *mddev, int bits)
 {
 	raid5_conf_t *conf = mddev->private;
@@ -3988,6 +3927,7 @@
 	struct stripe_head *sh;
 	const int rw = bio_data_dir(bi);
 	int remaining;
+	int plugged;
 
 	if (unlikely(bi->bi_rw & REQ_FLUSH)) {
 		md_flush_request(mddev, bi);
@@ -4006,6 +3946,7 @@
 	bi->bi_next = NULL;
 	bi->bi_phys_segments = 1;	/* over-loaded to count active stripes */
 
+	plugged = mddev_check_plugged(mddev);
 	for (;logical_sector < last_sector; logical_sector += STRIPE_SECTORS) {
 		DEFINE_WAIT(w);
 		int disks, data_disks;
@@ -4100,7 +4041,7 @@
 				 * add failed due to overlap.  Flush everything
 				 * and wait a while
 				 */
-				md_raid5_unplug_device(conf);
+				md_wakeup_thread(mddev->thread);
 				release_stripe(sh);
 				schedule();
 				goto retry;
@@ -4120,6 +4061,9 @@
 		}
 			
 	}
+	if (!plugged)
+		md_wakeup_thread(mddev->thread);
+
 	spin_lock_irq(&conf->device_lock);
 	remaining = raid5_dec_bi_phys_segments(bi);
 	spin_unlock_irq(&conf->device_lock);
@@ -4365,7 +4309,6 @@
 
 	if (sector_nr >= max_sector) {
 		/* just being told to finish up .. nothing much to do */
-		unplug_slaves(mddev);
 
 		if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery)) {
 			end_reshape(conf);
@@ -4522,24 +4465,30 @@
 	struct stripe_head *sh;
 	raid5_conf_t *conf = mddev->private;
 	int handled;
+	struct blk_plug plug;
 
 	pr_debug("+++ raid5d active\n");
 
 	md_check_recovery(mddev);
 
+	blk_start_plug(&plug);
 	handled = 0;
 	spin_lock_irq(&conf->device_lock);
 	while (1) {
 		struct bio *bio;
 
-		if (conf->seq_flush != conf->seq_write) {
-			int seq = conf->seq_flush;
+		if (atomic_read(&mddev->plug_cnt) == 0 &&
+		    !list_empty(&conf->bitmap_list)) {
+			/* Now is a good time to flush some bitmap updates */
+			conf->seq_flush++;
 			spin_unlock_irq(&conf->device_lock);
 			bitmap_unplug(mddev->bitmap);
 			spin_lock_irq(&conf->device_lock);
-			conf->seq_write = seq;
+			conf->seq_write = conf->seq_flush;
 			activate_bit_delay(conf);
 		}
+		if (atomic_read(&mddev->plug_cnt) == 0)
+			raid5_activate_delayed(conf);
 
 		while ((bio = remove_bio_from_retry(conf))) {
 			int ok;
@@ -4569,7 +4518,7 @@
 	spin_unlock_irq(&conf->device_lock);
 
 	async_tx_issue_pending_all();
-	unplug_slaves(mddev);
+	blk_finish_plug(&plug);
 
 	pr_debug("--- raid5d inactive\n");
 }
@@ -5186,8 +5135,6 @@
 		       mdname(mddev));
 	md_set_array_sectors(mddev, raid5_size(mddev, 0, 0));
 
-	plugger_init(&conf->plug, raid5_unplug);
-	mddev->plug = &conf->plug;
 	if (mddev->queue) {
 		int chunk_size;
 		/* read-ahead size must cover two whole stripes, which
@@ -5204,7 +5151,6 @@
 
 		mddev->queue->backing_dev_info.congested_data = mddev;
 		mddev->queue->backing_dev_info.congested_fn = raid5_congested;
-		mddev->queue->unplug_fn = raid5_unplug_queue;
 
 		chunk_size = mddev->chunk_sectors << 9;
 		blk_queue_io_min(mddev->queue, chunk_size);
@@ -5237,7 +5183,6 @@
 	mddev->thread = NULL;
 	if (mddev->queue)
 		mddev->queue->backing_dev_info.congested_fn = NULL;
-	plugger_flush(&conf->plug); /* the unplug fn references 'conf'*/
 	free_conf(conf);
 	mddev->private = NULL;
 	mddev->to_remove = &raid5_attrs_group;
@@ -5733,6 +5678,7 @@
 static void *raid45_takeover_raid0(mddev_t *mddev, int level)
 {
 	struct raid0_private_data *raid0_priv = mddev->private;
+	sector_t sectors;
 
 	/* for raid0 takeover only one zone is supported */
 	if (raid0_priv->nr_strip_zones > 1) {
@@ -5741,6 +5687,9 @@
 		return ERR_PTR(-EINVAL);
 	}
 
+	sectors = raid0_priv->strip_zone[0].zone_end;
+	sector_div(sectors, raid0_priv->strip_zone[0].nb_dev);
+	mddev->dev_sectors = sectors;
 	mddev->new_level = level;
 	mddev->new_layout = ALGORITHM_PARITY_N;
 	mddev->new_chunk_sectors = mddev->chunk_sectors;
diff -druN linux-libre-2.6.38-gnu/drivers/md/raid5.h linux-libre-2.6.39-gnu/drivers/md/raid5.h
--- linux-libre-2.6.38-gnu/drivers/md/raid5.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/md/raid5.h	2011-05-19 00:06:34.000000000 -0400
@@ -400,8 +400,6 @@
 					    * Cleared when a sync completes.
 					    */
 
-	struct plug_handle	plug;
-
 	/* per cpu variables */
 	struct raid5_percpu {
 		struct page	*spare_page; /* Used when checking P/Q in raid6 */
@@ -503,6 +501,6 @@
 }
 
 extern int md_raid5_congested(mddev_t *mddev, int bits);
-extern void md_raid5_unplug_device(raid5_conf_t *conf);
+extern void md_raid5_kick_device(raid5_conf_t *conf);
 extern int raid5_set_cache_size(mddev_t *mddev, int size);
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/saa7146_i2c.c linux-libre-2.6.39-gnu/drivers/media/common/saa7146_i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/common/saa7146_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/saa7146_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -161,7 +161,7 @@
 		msleep(SAA7146_I2C_DELAY);
 	}
 
-	/* if any error is still present, a fatal error has occured ... */
+	/* if any error is still present, a fatal error has occurred ... */
 	status = saa7146_i2c_status(dev);
 	if ( dev->i2c_bitrate != status ) {
 		DEB_I2C(("fatal error. status:0x%08x\n",status));
@@ -326,9 +326,9 @@
 			if ( 0 != err) {
 				/* this one is unsatisfying: some i2c slaves on some
 				   dvb cards don't acknowledge correctly, so the saa7146
-				   thinks that an address error occured. in that case, the
+				   thinks that an address error occurred. in that case, the
 				   transaction should be retrying, even if an address error
-				   occured. analog saa7146 based cards extensively rely on
+				   occurred. analog saa7146 based cards extensively rely on
 				   i2c address probing, however, and address errors indicate that a
 				   device is really *not* there. retrying in that case
 				   increases the time the device needs to probe greatly, so
@@ -365,7 +365,7 @@
 	DEB_I2C(("transmission successful. (msg:%d).\n",err));
 out:
 	/* another bug in revision 0: the i2c-registers get uploaded randomly by other
-	   uploads, so we better clear them out before continueing */
+	   uploads, so we better clear them out before continuing */
 	if( 0 == dev->revision ) {
 		__le32 zero = 0;
 		saa7146_i2c_reset(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/mxl5005s.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/mxl5005s.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/mxl5005s.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/mxl5005s.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 /* MXL5005 Tuner Register Struct */
 struct TunerReg {
 	u16 Reg_Num;	/* Tuner Register Address */
-	u16 Reg_Val;	/* Current sw programmed value waiting to be writen */
+	u16 Reg_Val;	/* Current sw programmed value waiting to be written */
 };
 
 enum {
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271-common.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271-common.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -533,16 +533,7 @@
 	if (tda_fail(ret))
 		goto fail;
 
-	regs[R_MPD]   = (0x77 & pd);
-
-	switch (priv->mode) {
-	case TDA18271_ANALOG:
-		regs[R_MPD]  &= ~0x08;
-		break;
-	case TDA18271_DIGITAL:
-		regs[R_MPD]  |=  0x08;
-		break;
-	}
+	regs[R_MPD]   = (0x7f & pd);
 
 	div =  ((d * (freq / 1000)) << 7) / 125;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271-fe.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271-fe.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271-fe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271-fe.c	2011-05-19 00:06:34.000000000 -0400
@@ -579,8 +579,8 @@
 #define RF3 2
 	u32 rf_default[3];
 	u32 rf_freq[3];
-	u8 prog_cal[3];
-	u8 prog_tab[3];
+	s32 prog_cal[3];
+	s32 prog_tab[3];
 
 	i = tda18271_lookup_rf_band(fe, &freq, NULL);
 
@@ -602,32 +602,33 @@
 			return bcal;
 
 		tda18271_calc_rf_cal(fe, &rf_freq[rf]);
-		prog_tab[rf] = regs[R_EB14];
+		prog_tab[rf] = (s32)regs[R_EB14];
 
 		if (1 == bcal)
-			prog_cal[rf] = tda18271_calibrate_rf(fe, rf_freq[rf]);
+			prog_cal[rf] =
+				(s32)tda18271_calibrate_rf(fe, rf_freq[rf]);
 		else
 			prog_cal[rf] = prog_tab[rf];
 
 		switch (rf) {
 		case RF1:
 			map[i].rf_a1 = 0;
-			map[i].rf_b1 = (s32)(prog_cal[RF1] - prog_tab[RF1]);
+			map[i].rf_b1 = (prog_cal[RF1] - prog_tab[RF1]);
 			map[i].rf1   = rf_freq[RF1] / 1000;
 			break;
 		case RF2:
-			dividend = (s32)(prog_cal[RF2] - prog_tab[RF2]) -
-				   (s32)(prog_cal[RF1] + prog_tab[RF1]);
+			dividend = (prog_cal[RF2] - prog_tab[RF2] -
+				    prog_cal[RF1] + prog_tab[RF1]);
 			divisor = (s32)(rf_freq[RF2] - rf_freq[RF1]) / 1000;
 			map[i].rf_a1 = (dividend / divisor);
 			map[i].rf2   = rf_freq[RF2] / 1000;
 			break;
 		case RF3:
-			dividend = (s32)(prog_cal[RF3] - prog_tab[RF3]) -
-				   (s32)(prog_cal[RF2] + prog_tab[RF2]);
+			dividend = (prog_cal[RF3] - prog_tab[RF3] -
+				    prog_cal[RF2] + prog_tab[RF2]);
 			divisor = (s32)(rf_freq[RF3] - rf_freq[RF2]) / 1000;
 			map[i].rf_a2 = (dividend / divisor);
-			map[i].rf_b2 = (s32)(prog_cal[RF2] - prog_tab[RF2]);
+			map[i].rf_b2 = (prog_cal[RF2] - prog_tab[RF2]);
 			map[i].rf3   = rf_freq[RF3] / 1000;
 			break;
 		default:
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271.h linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271.h
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271.h	2011-05-19 00:06:34.000000000 -0400
@@ -98,7 +98,7 @@
 	/* output options that can be disabled */
 	enum tda18271_output_options output_opt;
 
-	/* some i2c providers cant write all 39 registers at once */
+	/* some i2c providers can't write all 39 registers at once */
 	enum tda18271_small_i2c small_i2c;
 
 	/* force rf tracking filter calibration on startup */
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271-maps.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271-maps.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda18271-maps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda18271-maps.c	2011-05-19 00:06:34.000000000 -0400
@@ -229,8 +229,7 @@
 static struct tda18271_map tda18271_rf_band[] = {
 	{ .rfmax =  47900, .val = 0x00 },
 	{ .rfmax =  61100, .val = 0x01 },
-/*	{ .rfmax = 152600, .val = 0x02 }, */
-	{ .rfmax = 121200, .val = 0x02 },
+	{ .rfmax = 152600, .val = 0x02 },
 	{ .rfmax = 164700, .val = 0x03 },
 	{ .rfmax = 203500, .val = 0x04 },
 	{ .rfmax = 457800, .val = 0x05 },
@@ -448,7 +447,7 @@
 	{ .rfmax = 150000, .val = 0xb0 },
 	{ .rfmax = 151000, .val = 0xb1 },
 	{ .rfmax = 152000, .val = 0xb7 },
-	{ .rfmax = 153000, .val = 0xbd },
+	{ .rfmax = 152600, .val = 0xbd },
 	{ .rfmax = 154000, .val = 0x20 },
 	{ .rfmax = 155000, .val = 0x22 },
 	{ .rfmax = 156000, .val = 0x24 },
@@ -459,7 +458,7 @@
 	{ .rfmax = 161000, .val = 0x2d },
 	{ .rfmax = 163000, .val = 0x2e },
 	{ .rfmax = 164000, .val = 0x2f },
-	{ .rfmax = 165000, .val = 0x30 },
+	{ .rfmax = 164700, .val = 0x30 },
 	{ .rfmax = 166000, .val = 0x11 },
 	{ .rfmax = 167000, .val = 0x12 },
 	{ .rfmax = 168000, .val = 0x13 },
@@ -510,7 +509,8 @@
 	{ .rfmax = 236000, .val = 0x1b },
 	{ .rfmax = 237000, .val = 0x1c },
 	{ .rfmax = 240000, .val = 0x1d },
-	{ .rfmax = 242000, .val = 0x1f },
+	{ .rfmax = 242000, .val = 0x1e },
+	{ .rfmax = 244000, .val = 0x1f },
 	{ .rfmax = 247000, .val = 0x20 },
 	{ .rfmax = 249000, .val = 0x21 },
 	{ .rfmax = 252000, .val = 0x22 },
@@ -624,7 +624,7 @@
 	{ .rfmax = 453000, .val = 0x93 },
 	{ .rfmax = 454000, .val = 0x94 },
 	{ .rfmax = 456000, .val = 0x96 },
-	{ .rfmax = 457000, .val = 0x98 },
+	{ .rfmax = 457800, .val = 0x98 },
 	{ .rfmax = 461000, .val = 0x11 },
 	{ .rfmax = 468000, .val = 0x12 },
 	{ .rfmax = 472000, .val = 0x13 },
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda9887.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda9887.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tda9887.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tda9887.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,8 @@
 	unsigned int       mode;
 	unsigned int       audmode;
 	v4l2_std_id        std;
+
+	bool               standby;
 };
 
 /* ---------------------------------------------------------------------- */
@@ -568,7 +570,7 @@
 	tda9887_do_config(fe);
 	tda9887_set_insmod(fe);
 
-	if (priv->mode == T_STANDBY)
+	if (priv->standby)
 		priv->data[1] |= cForcedMuteAudioON;
 
 	tuner_dbg("writing: b=0x%02x c=0x%02x e=0x%02x\n",
@@ -616,7 +618,7 @@
 {
 	struct tda9887_priv *priv = fe->analog_demod_priv;
 
-	priv->mode = T_STANDBY;
+	priv->standby = true;
 
 	tda9887_configure(fe);
 }
@@ -626,6 +628,7 @@
 {
 	struct tda9887_priv *priv = fe->analog_demod_priv;
 
+	priv->standby = false;
 	priv->mode    = params->mode;
 	priv->audmode = params->audmode;
 	priv->std     = params->std;
@@ -686,7 +689,7 @@
 		return NULL;
 	case 1:
 		fe->analog_demod_priv = priv;
-		priv->mode = T_STANDBY;
+		priv->standby = true;
 		tuner_info("tda988[5/6/7] found\n");
 		break;
 	default:
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tea5761.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tea5761.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tea5761.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tea5761.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 	struct tuner_i2c_props i2c_props;
 
 	u32 frequency;
+	bool standby;
 };
 
 /*****************************************************************************/
@@ -135,18 +136,19 @@
 }
 
 /* Freq should be specifyed at 62.5 Hz */
-static int set_radio_freq(struct dvb_frontend *fe,
-			  struct analog_parameters *params)
+static int __set_radio_freq(struct dvb_frontend *fe,
+			    unsigned int freq,
+			    bool mono)
 {
 	struct tea5761_priv *priv = fe->tuner_priv;
-	unsigned int frq = params->frequency;
+	unsigned int frq = freq;
 	unsigned char buffer[7] = {0, 0, 0, 0, 0, 0, 0 };
 	unsigned div;
 	int rc;
 
 	tuner_dbg("radio freq counter %d\n", frq);
 
-	if (params->mode == T_STANDBY) {
+	if (priv->standby) {
 		tuner_dbg("TEA5761 set to standby mode\n");
 		buffer[5] |= TEA5761_TNCTRL_MU;
 	} else {
@@ -154,7 +156,7 @@
 	}
 
 
-	if (params->audmode == V4L2_TUNER_MODE_MONO) {
+	if (mono) {
 		tuner_dbg("TEA5761 set to mono\n");
 		buffer[5] |= TEA5761_TNCTRL_MST;
 	} else {
@@ -176,6 +178,26 @@
 	return 0;
 }
 
+static int set_radio_freq(struct dvb_frontend *fe,
+			  struct analog_parameters *params)
+{
+	struct tea5761_priv *priv = fe->analog_demod_priv;
+
+	priv->standby = false;
+
+	return __set_radio_freq(fe, params->frequency,
+				params->audmode == V4L2_TUNER_MODE_MONO);
+}
+
+static int set_radio_sleep(struct dvb_frontend *fe)
+{
+	struct tea5761_priv *priv = fe->analog_demod_priv;
+
+	priv->standby = true;
+
+	return __set_radio_freq(fe, priv->frequency, false);
+}
+
 static int tea5761_read_status(struct dvb_frontend *fe, char *buffer)
 {
 	struct tea5761_priv *priv = fe->tuner_priv;
@@ -284,6 +306,7 @@
 		.name           = "tea5761", // Philips TEA5761HN FM Radio
 	},
 	.set_analog_params = set_radio_freq,
+	.sleep		   = set_radio_sleep,
 	.release           = tea5761_release,
 	.get_frequency     = tea5761_get_frequency,
 	.get_status        = tea5761_get_status,
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tuner-types.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tuner-types.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tuner-types.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tuner-types.c	2011-05-19 00:06:34.000000000 -0400
@@ -971,6 +971,22 @@
 	},
 };
 
+/* ------------ TUNER_TENA_TNF_5337 - Tena tnf5337MFD STD M/N ------------ */
+
+static struct tuner_range tuner_tena_tnf_5337_ntsc_ranges[] = {
+	{ 16 * 166.25 /*MHz*/, 0x86, 0x01, },
+	{ 16 * 466.25 /*MHz*/, 0x86, 0x02, },
+	{ 16 * 999.99        , 0x86, 0x08, },
+};
+
+static struct tuner_params tuner_tena_tnf_5337_params[] = {
+	{
+		.type   = TUNER_PARAM_TYPE_NTSC,
+		.ranges = tuner_tena_tnf_5337_ntsc_ranges,
+		.count  = ARRAY_SIZE(tuner_tena_tnf_5337_ntsc_ranges),
+	},
+};
+
 /* ------------ TUNER_PHILIPS_FMD1216ME(X)_MK3 - Philips PAL ------------ */
 
 static struct tuner_range tuner_philips_fmd1216me_mk3_pal_ranges[] = {
@@ -1842,6 +1858,11 @@
 		.params = tuner_philips_fq1236_mk5_params,
 		.count  = ARRAY_SIZE(tuner_philips_fq1236_mk5_params),
 	},
+	[TUNER_TENA_TNF_5337] = { /* Tena 5337 MFD */
+		.name   = "Tena TNF5337 MFD",
+		.params = tuner_tena_tnf_5337_params,
+		.count  = ARRAY_SIZE(tuner_tena_tnf_5337_params),
+	},
 };
 EXPORT_SYMBOL(tuners);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/tuner-xc2028.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/tuner-xc2028.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/tuner-xc2028.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/tuner-xc2028.c	2012-03-24 03:26:51.000000000 -0400
@@ -685,7 +685,7 @@
 {
 	struct xc2028_data         *priv = fe->tuner_priv;
 	struct firmware_properties new_fw;
-	int			   rc = 0, is_retry = 0;
+	int			   rc = 0, retry_count = 0;
 	u16			   version, hwmodel;
 	v4l2_std_id		   std0;
 
@@ -855,9 +855,9 @@
 
 fail:
 	memset(&priv->cur_fw, 0, sizeof(priv->cur_fw));
-	if (!is_retry) {
+	if (retry_count < 8) {
 		msleep(50);
-		is_retry = 1;
+		retry_count++;
 		tuner_dbg("Retrying firmware load\n");
 		goto retry;
 	}
@@ -907,7 +907,7 @@
 #define DIV 15625
 
 static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
-			    enum tuner_mode new_mode,
+			    enum v4l2_tuner_type new_type,
 			    unsigned int type,
 			    v4l2_std_id std,
 			    u16 int_freq)
@@ -933,7 +933,7 @@
 	 * that xc2028 will be in a safe state.
 	 * Maybe this might also be needed for DTV.
 	 */
-	if (new_mode == T_ANALOG_TV) {
+	if (new_type == V4L2_TUNER_ANALOG_TV) {
 		rc = send_seq(priv, {0x00, 0x00});
 
 		/* Analog modes require offset = 0 */
@@ -1054,7 +1054,7 @@
 		if (priv->ctrl.input1)
 			type |= INPUT1;
 		return generic_set_freq(fe, (625l * p->frequency) / 10,
-				T_RADIO, type, 0, 0);
+				V4L2_TUNER_RADIO, type, 0, 0);
 	}
 
 	/* if std is not defined, choose one */
@@ -1069,7 +1069,7 @@
 	p->std |= parse_audio_std_option();
 
 	return generic_set_freq(fe, 62500l * p->frequency,
-				T_ANALOG_TV, type, p->std, 0);
+				V4L2_TUNER_ANALOG_TV, type, p->std, 0);
 }
 
 static int xc2028_set_params(struct dvb_frontend *fe,
@@ -1174,7 +1174,7 @@
 	}
 
 	return generic_set_freq(fe, p->frequency,
-				T_DIGITAL_TV, type, 0, demod);
+				V4L2_TUNER_DIGITAL_TV, type, 0, demod);
 }
 
 static int xc2028_sleep(struct dvb_frontend *fe)
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/xc5000.c linux-libre-2.6.39-gnu/drivers/media/common/tuners/xc5000.c
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/xc5000.c	2012-03-24 01:01:04.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/xc5000.c	2012-03-24 03:26:54.000000000 -0400
@@ -65,7 +65,7 @@
 };
 
 /* Misc Defines */
-#define MAX_TV_STANDARD			23
+#define MAX_TV_STANDARD			24
 #define XC_MAX_I2C_WRITE_LENGTH		64
 
 /* Signal Types */
@@ -92,6 +92,8 @@
 #define XREG_IF_OUT       0x05
 #define XREG_SEEK_MODE    0x07
 #define XREG_POWER_DOWN   0x0A /* Obsolete */
+/* Set the output amplitude - SIF for analog, DTVP/DTVN for digital */
+#define XREG_OUTPUT_AMP   0x0B
 #define XREG_SIGNALSOURCE 0x0D /* 0=Air, 1=Cable */
 #define XREG_SMOOTHEDCVBS 0x0E
 #define XREG_XTALFREQ     0x0F
@@ -173,6 +175,7 @@
 #define DTV7			20
 #define FM_Radio_INPUT2 	21
 #define FM_Radio_INPUT1 	22
+#define FM_Radio_INPUT1_MONO	23
 
 static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
 	{"M/N-NTSC/PAL-BTSC", 0x0400, 0x8020},
@@ -197,7 +200,8 @@
 	{"DTV7/8",            0x00C0, 0x801B},
 	{"DTV7",              0x00C0, 0x8007},
 	{"FM Radio-INPUT2",   0x9802, 0x9002},
-	{"FM Radio-INPUT1",   0x0208, 0x9002}
+	{"FM Radio-INPUT1",   0x0208, 0x9002},
+	{"FM Radio-INPUT1_MONO", 0x0278, 0x9002}
 };
 
 static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
@@ -683,6 +687,24 @@
 			return -EINVAL;
 		}
 		priv->rf_mode = XC_RF_MODE_AIR;
+	} else if (fe->ops.info.type == FE_QAM) {
+		dprintk(1, "%s() QAM\n", __func__);
+		switch (params->u.qam.modulation) {
+		case QAM_16:
+		case QAM_32:
+		case QAM_64:
+		case QAM_128:
+		case QAM_256:
+		case QAM_AUTO:
+			dprintk(1, "%s() QAM modulation\n", __func__);
+			priv->bandwidth = BANDWIDTH_8_MHZ;
+			priv->video_standard = DTV7_8;
+			priv->freq_hz = params->frequency - 2750000;
+			priv->rf_mode = XC_RF_MODE_CABLE;
+			break;
+		default:
+			return -EINVAL;
+		}
 	} else {
 		printk(KERN_ERR "xc5000 modulation type not supported!\n");
 		return -EINVAL;
@@ -714,6 +736,8 @@
 		return -EIO;
 	}
 
+	xc_write_reg(priv, XREG_OUTPUT_AMP, 0x8a);
+
 	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_DIGITAL);
 
 	if (debug)
@@ -818,6 +842,8 @@
 		return -EREMOTEIO;
 	}
 
+	xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
+
 	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
 
 	if (debug)
@@ -845,6 +871,8 @@
 		radio_input = FM_Radio_INPUT1;
 	else if  (priv->radio_input == XC5000_RADIO_FM2)
 		radio_input = FM_Radio_INPUT2;
+	else if  (priv->radio_input == XC5000_RADIO_FM1_MONO)
+		radio_input = FM_Radio_INPUT1_MONO;
 	else {
 		dprintk(1, "%s() unknown radio input %d\n", __func__,
 			priv->radio_input);
@@ -871,6 +899,12 @@
 		return -EREMOTEIO;
 	}
 
+	if ((priv->radio_input == XC5000_RADIO_FM1) ||
+				(priv->radio_input == XC5000_RADIO_FM2))
+		xc_write_reg(priv, XREG_OUTPUT_AMP, 0x09);
+	else if  (priv->radio_input == XC5000_RADIO_FM1_MONO)
+		xc_write_reg(priv, XREG_OUTPUT_AMP, 0x06);
+
 	xc_tune_channel(priv, priv->freq_hz, XC_TUNE_ANALOG);
 
 	return 0;
@@ -1021,6 +1055,23 @@
 	return 0;
 }
 
+static int xc5000_set_config(struct dvb_frontend *fe, void *priv_cfg)
+{
+	struct xc5000_priv *priv = fe->tuner_priv;
+	struct xc5000_config *p = priv_cfg;
+
+	dprintk(1, "%s()\n", __func__);
+
+	if (p->if_khz)
+		priv->if_khz = p->if_khz;
+
+	if (p->radio_input)
+		priv->radio_input = p->radio_input;
+
+	return 0;
+}
+
+
 static const struct dvb_tuner_ops xc5000_tuner_ops = {
 	.info = {
 		.name           = "Xceive XC5000",
@@ -1033,6 +1084,7 @@
 	.init		   = xc5000_init,
 	.sleep		   = xc5000_sleep,
 
+	.set_config	   = xc5000_set_config,
 	.set_params	   = xc5000_set_params,
 	.set_analog_params = xc5000_set_analog_params,
 	.get_frequency	   = xc5000_get_frequency,
diff -druN linux-libre-2.6.38-gnu/drivers/media/common/tuners/xc5000.h linux-libre-2.6.39-gnu/drivers/media/common/tuners/xc5000.h
--- linux-libre-2.6.38-gnu/drivers/media/common/tuners/xc5000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/common/tuners/xc5000.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 #define XC5000_RADIO_NOT_CONFIGURED		0
 #define XC5000_RADIO_FM1			1
 #define XC5000_RADIO_FM2			2
+#define XC5000_RADIO_FM1_MONO			3
 
 /* For each bridge framework, when it attaches either analog or digital,
  * it has to store a reference back to its _core equivalent structure,
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/b2c2/flexcop-pci.c linux-libre-2.6.39-gnu/drivers/media/dvb/b2c2/flexcop-pci.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/b2c2/flexcop-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/b2c2/flexcop-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 	DEBSTATUS);
 
 #define DRIVER_VERSION "0.1"
-#define DRIVER_NAME "Technisat/B2C2 FlexCop II/IIb/III Digital TV PCI Driver"
+#define DRIVER_NAME "flexcop-pci"
 #define DRIVER_AUTHOR "Patrick Boettcher <patrick.boettcher@desy.de>"
 
 struct flexcop_pci {
@@ -58,7 +58,7 @@
 
 	int active_dma1_addr; /* 0 = addr0 of dma1; 1 = addr1 of dma1 */
 	u32 last_dma1_cur_pos;
-	/* position of the pointer last time the timer/packet irq occured */
+	/* position of the pointer last time the timer/packet irq occurred */
 	int count;
 	int count_prev;
 	int stream_problem;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/bt8xx/dvb-bt8xx.c linux-libre-2.6.39-gnu/drivers/media/dvb/bt8xx/dvb-bt8xx.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2012-03-24 01:01:09.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/bt8xx/dvb-bt8xx.c	2012-03-24 03:26:56.000000000 -0400
@@ -427,10 +427,10 @@
 	struct dvb_bt8xx_card *bt = fe->dvb->priv;
 
 	/* RESET DEVICE
-	 * reset is controled by GPIO-0
+	 * reset is controlled by GPIO-0
 	 * when set to 0 causes reset and when to 1 for normal op
 	 * must remain reset for 128 clock cycles on a 50Mhz clock
-	 * also PRM1 PRM2 & PRM4 are controled by GPIO-1,GPIO-2 & GPIO-4
+	 * also PRM1 PRM2 & PRM4 are controlled by GPIO-1,GPIO-2 & GPIO-4
 	 * We assume that the reset has be held low long enough or we
 	 * have been reset by a power on.  When the driver is unloaded
 	 * reset set to 0 so if reloaded we have been reset.
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-core/dvb_frontend.c	2011-05-19 00:06:34.000000000 -0400
@@ -1638,7 +1638,7 @@
 	case FE_READ_STATUS: {
 		fe_status_t* status = parg;
 
-		/* if retune was requested but hasn't occured yet, prevent
+		/* if retune was requested but hasn't occurred yet, prevent
 		 * that user get signal state from previous tuning */
 		if (fepriv->state == FESTATE_RETUNE ||
 		    fepriv->state == FESTATE_ERROR) {
@@ -1729,7 +1729,7 @@
 			 * Dish network legacy switches (as used by Dish500)
 			 * are controlled by sending 9-bit command words
 			 * spaced 8msec apart.
-			 * the actual command word is switch/port dependant
+			 * the actual command word is switch/port dependent
 			 * so it is up to the userspace application to send
 			 * the right command.
 			 * The command must always start with a '0' after
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-core/dvb_frontend.h	2011-05-19 00:06:34.000000000 -0400
@@ -239,7 +239,6 @@
 	void (*set_params)(struct dvb_frontend *fe,
 			   struct analog_parameters *params);
 	int  (*has_signal)(struct dvb_frontend *fe);
-	int  (*is_stereo)(struct dvb_frontend *fe);
 	int  (*get_afc)(struct dvb_frontend *fe);
 	void (*tuner_status)(struct dvb_frontend *fe);
 	void (*standby)(struct dvb_frontend *fe);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/a800.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/a800.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/a800.c	2012-03-24 01:01:13.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/a800.c	2012-03-24 03:26:59.000000000 -0400
@@ -38,8 +38,8 @@
 }
 
 static struct rc_map_table rc_map_a800_table[] = {
-	{ 0x0201, KEY_PROG1 },       /* SOURCE */
-	{ 0x0200, KEY_POWER },       /* POWER */
+	{ 0x0201, KEY_MODE },      /* SOURCE */
+	{ 0x0200, KEY_POWER2 },      /* POWER */
 	{ 0x0205, KEY_1 },           /* 1 */
 	{ 0x0206, KEY_2 },           /* 2 */
 	{ 0x0207, KEY_3 },           /* 3 */
@@ -52,8 +52,8 @@
 	{ 0x0212, KEY_LEFT },        /* L / DISPLAY */
 	{ 0x0211, KEY_0 },           /* 0 */
 	{ 0x0213, KEY_RIGHT },       /* R / CH RTN */
-	{ 0x0217, KEY_PROG2 },       /* SNAP SHOT */
-	{ 0x0210, KEY_PROG3 },       /* 16-CH PREV */
+	{ 0x0217, KEY_CAMERA },      /* SNAP SHOT */
+	{ 0x0210, KEY_LAST },        /* 16-CH PREV */
 	{ 0x021e, KEY_VOLUMEDOWN },  /* VOL DOWN */
 	{ 0x020c, KEY_ZOOM },        /* FULL SCREEN */
 	{ 0x021f, KEY_VOLUMEUP },    /* VOL UP */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c	2012-03-24 01:01:08.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/af9005-fe.c	2012-03-24 03:26:56.000000000 -0400
@@ -580,7 +580,7 @@
 		NS_coeff2_8k = 0x724925;
 		break;
 	default:
-		err("Invalid bandwith %d.", bw);
+		err("Invalid bandwidth %d.", bw);
 		return -EINVAL;
 	}
 
@@ -789,7 +789,7 @@
 		temp = 2;
 		break;
 	default:
-		err("Invalid bandwith %d.", bw);
+		err("Invalid bandwidth %d.", bw);
 		return -EINVAL;
 	}
 	return af9005_write_register_bits(d, xd_g_reg_bw, reg_bw_pos,
@@ -930,7 +930,7 @@
 	if (ret)
 		return ret;
 
-	/* init other parameters: program cfoe and select bandwith */
+	/* init other parameters: program cfoe and select bandwidth */
 	deb_info("program cfoe\n");
 	if ((ret = af9005_fe_program_cfoe(state->d, BANDWIDTH_6_MHZ)))
 		return ret;
@@ -1146,7 +1146,7 @@
 	if (ret)
 		return ret;
 
-	/* select bandwith */
+	/* select bandwidth */
 	deb_info("select bandwidth");
 	ret = af9005_fe_select_bw(state->d, fep->u.ofdm.bandwidth);
 	if (ret)
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/af9015.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/af9015.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/af9015.c	2012-03-24 01:01:23.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/af9015.c	2012-03-24 03:27:05.000000000 -0400
@@ -479,6 +479,7 @@
 		ret = af9015_set_reg_bit(d, 0xd50b, 0);
 	else
 		ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+
 error:
 	if (ret)
 		err("endpoint init failed:%d", ret);
@@ -611,6 +612,11 @@
 	int ret;
 	deb_info("%s:\n", __func__);
 
+	/* init RC canary */
+	ret = af9015_write_reg(d, 0x98e9, 0xff);
+	if (ret)
+		goto error;
+
 	ret = af9015_init_endpoint(d);
 	if (ret)
 		goto error;
@@ -659,9 +665,8 @@
 static int af9015_download_firmware(struct usb_device *udev,
 	const struct firmware *fw)
 {
-	int i, len, packets, remainder, ret;
+	int i, len, remaining, ret;
 	struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
-	u16 addr = 0x5100; /* firmware start address */
 	u16 checksum = 0;
 
 	deb_info("%s:\n", __func__);
@@ -673,24 +678,20 @@
 	af9015_config.firmware_size = fw->size;
 	af9015_config.firmware_checksum = checksum;
 
-	#define FW_PACKET_MAX_DATA  55
-
-	packets = fw->size / FW_PACKET_MAX_DATA;
-	remainder = fw->size % FW_PACKET_MAX_DATA;
-	len = FW_PACKET_MAX_DATA;
-	for (i = 0; i <= packets; i++) {
-		if (i == packets)  /* set size of the last packet */
-			len = remainder;
+	#define FW_ADDR 0x5100 /* firmware start address */
+	#define LEN_MAX 55 /* max packet size */
+	for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
+		len = remaining;
+		if (len > LEN_MAX)
+			len = LEN_MAX;
 
 		req.data_len = len;
-		req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
-		req.addr = addr;
-		addr += FW_PACKET_MAX_DATA;
+		req.data = (u8 *) &fw->data[fw->size - remaining];
+		req.addr = FW_ADDR + fw->size - remaining;
 
 		ret = af9015_rw_udev(udev, &req);
 		if (ret) {
-			err("firmware download failed at packet %d with " \
-				"code %d", i, ret);
+			err("firmware download failed:%d", ret);
 			goto error;
 		}
 	}
@@ -738,6 +739,8 @@
 };
 
 static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
+	{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_RC,
+		RC_MAP_TERRATEC_SLIM_2 },
 	{ (USB_VID_TERRATEC << 16) + USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
 		RC_MAP_TERRATEC_SLIM },
 	{ (USB_VID_VISIONPLUS << 16) + USB_PID_AZUREWAVE_AD_TU700,
@@ -1016,22 +1019,38 @@
 {
 	struct af9015_state *priv = d->priv;
 	int ret;
-	u8 buf[16];
+	u8 buf[17];
 
 	/* read registers needed to detect remote controller code */
 	ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf));
 	if (ret)
 		goto error;
 
-	if (buf[14] || buf[15]) {
+	/* If any of these are non-zero, assume invalid data */
+	if (buf[1] || buf[2] || buf[3])
+		return ret;
+
+	/* Check for repeat of previous code */
+	if ((priv->rc_repeat != buf[6] || buf[0]) &&
+					!memcmp(&buf[12], priv->rc_last, 4)) {
+		deb_rc("%s: key repeated\n", __func__);
+		rc_keydown(d->rc_dev, priv->rc_keycode, 0);
+		priv->rc_repeat = buf[6];
+		return ret;
+	}
+
+	/* Only process key if canary killed */
+	if (buf[16] != 0xff && buf[0] != 0x01) {
 		deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__,
 			buf[12], buf[13], buf[14], buf[15]);
 
-		/* clean IR code from mem */
-		ret = af9015_write_regs(d, 0x98e5, "\x00\x00\x00\x00", 4);
+		/* Reset the canary */
+		ret = af9015_write_reg(d, 0x98e9, 0xff);
 		if (ret)
 			goto error;
 
+		/* Remember this key */
+		memcpy(priv->rc_last, &buf[12], 4);
 		if (buf[14] == (u8) ~buf[15]) {
 			if (buf[12] == (u8) ~buf[13]) {
 				/* NEC */
@@ -1041,15 +1060,17 @@
 				priv->rc_keycode = buf[12] << 16 |
 					buf[13] << 8 | buf[14];
 			}
-			rc_keydown(d->rc_dev, priv->rc_keycode, 0);
 		} else {
-			priv->rc_keycode = 0; /* clear just for sure */
+			/* 32 bit NEC */
+			priv->rc_keycode = buf[12] << 24 | buf[13] << 16 |
+					buf[14] << 8 | buf[15];
 		}
-	} else if (priv->rc_repeat != buf[6] || buf[0]) {
-		deb_rc("%s: key repeated\n", __func__);
 		rc_keydown(d->rc_dev, priv->rc_keycode, 0);
 	} else {
 		deb_rc("%s: no key press\n", __func__);
+		/* Invalidate last keypress */
+		/* Not really needed, but helps with debug */
+		priv->rc_last[2] = priv->rc_last[3];
 	}
 
 	priv->rc_repeat = buf[6];
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/af9015.h linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/af9015.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/af9015.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/af9015.h	2011-05-19 00:06:34.000000000 -0400
@@ -102,6 +102,7 @@
 	struct i2c_adapter i2c_adap; /* I2C adapter for 2nd FE */
 	u8 rc_repeat;
 	u32 rc_keycode;
+	u8 rc_last[4];
 };
 
 struct af9015_config {
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dib0700_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -186,7 +186,7 @@
 						 msg[i].len,
 						 USB_CTRL_GET_TIMEOUT);
 			if (result < 0) {
-				err("i2c read error (status = %d)\n", result);
+				deb_info("i2c read error (status = %d)\n", result);
 				break;
 			}
 
@@ -215,7 +215,7 @@
 						 0, 0, buf, msg[i].len + 4,
 						 USB_CTRL_GET_TIMEOUT);
 			if (result < 0) {
-				err("i2c write error (status = %d)\n", result);
+				deb_info("i2c write error (status = %d)\n", result);
 				break;
 			}
 		}
@@ -328,6 +328,31 @@
 	return dib0700_ctrl_wr(d, b, 10);
 }
 
+int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz)
+{
+	u16 divider;
+	u8 b[8];
+
+	if (scl_kHz == 0)
+		return -EINVAL;
+
+	b[0] = REQUEST_SET_I2C_PARAM;
+	divider = (u16) (30000 / scl_kHz);
+	b[2] = (u8) (divider >> 8);
+	b[3] = (u8) (divider & 0xff);
+	divider = (u16) (72000 / scl_kHz);
+	b[4] = (u8) (divider >> 8);
+	b[5] = (u8) (divider & 0xff);
+	divider = (u16) (72000 / scl_kHz); /* clock: 72MHz */
+	b[6] = (u8) (divider >> 8);
+	b[7] = (u8) (divider & 0xff);
+
+	deb_info("setting I2C speed: %04x %04x %04x (%d kHz).",
+		(b[2] << 8) | (b[3]), (b[4] << 8) | b[5], (b[6] << 8) | b[7], scl_kHz);
+	return dib0700_ctrl_wr(d, b, 8);
+}
+
+
 int dib0700_ctrl_clock(struct dvb_usb_device *d, u32 clk_MHz, u8 clock_out_gp3)
 {
 	switch (clk_MHz) {
@@ -459,10 +484,20 @@
 
 	deb_info("modifying (%d) streaming state for %d\n", onoff, adap->id);
 
-	if (onoff)
-		st->channel_state |=   1 << adap->id;
-	else
-		st->channel_state &= ~(1 << adap->id);
+	st->channel_state &= ~0x3;
+	if ((adap->stream.props.endpoint != 2)
+			&& (adap->stream.props.endpoint != 3)) {
+		deb_info("the endpoint number (%i) is not correct, use the adapter id instead", adap->stream.props.endpoint);
+		if (onoff)
+			st->channel_state |=	1 << (adap->id);
+		else
+			st->channel_state |=	1 << ~(adap->id);
+	} else {
+		if (onoff)
+			st->channel_state |=	1 << (adap->stream.props.endpoint-2);
+		else
+			st->channel_state |=	1 << (3-adap->stream.props.endpoint);
+	}
 
 	b[2] |= st->channel_state;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c	2012-03-24 01:01:41.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dib0700_devices.c	2012-03-24 03:27:15.000000000 -0400
@@ -12,6 +12,7 @@
 #include "dib7000m.h"
 #include "dib7000p.h"
 #include "dib8000.h"
+#include "dib9000.h"
 #include "mt2060.h"
 #include "mt2266.h"
 #include "tuner-xc2028.h"
@@ -29,6 +30,7 @@
 
 struct dib0700_adapter_state {
 	int (*set_param_save) (struct dvb_frontend *, struct dvb_frontend_parameters *);
+	const struct firmware *frontend_firmware;
 };
 
 /* Hauppauge Nova-T 500 (aka Bristol)
@@ -1243,13 +1245,13 @@
 static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
 	u16 pid, int onoff)
 {
-    return dib8000_pid_filter(adapter->fe, index, pid, onoff);
+	return dib8000_pid_filter(adapter->fe, index, pid, onoff);
 }
 
 static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
-	int onoff)
+		int onoff)
 {
-    return dib8000_pid_filter_ctrl(adapter->fe, onoff);
+	return dib8000_pid_filter_ctrl(adapter->fe, onoff);
 }
 
 /* STK807x */
@@ -1321,11 +1323,11 @@
 
 /* STK8096GP */
 struct dibx000_agc_config dib8090_agc_config[2] = {
-    {
+	{
 	BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
-     * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-     * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
 	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
 	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
 
@@ -1362,12 +1364,12 @@
 	51,
 
 	0,
-    },
-    {
+	},
+	{
 	BAND_CBAND,
 	/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
-     * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
-     * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+	 * P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
+	 * P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
 	(0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
 	| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
 
@@ -1404,135 +1406,153 @@
 	51,
 
 	0,
-    }
+	}
 };
 
 static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
-    54000, 13500,
-    1, 18, 3, 1, 0,
-    0, 0, 1, 1, 2,
-    (3 << 14) | (1 << 12) | (599 << 0),
-    (0 << 25) | 0,
-    20199727,
-    12000000,
+	54000, 13500,
+	1, 18, 3, 1, 0,
+	0, 0, 1, 1, 2,
+	(3 << 14) | (1 << 12) | (599 << 0),
+	(0 << 25) | 0,
+	20199727,
+	12000000,
 };
 
 static int dib8090_get_adc_power(struct dvb_frontend *fe)
 {
-    return dib8000_get_adc_power(fe, 1);
+	return dib8000_get_adc_power(fe, 1);
 }
 
-static struct dib8000_config dib809x_dib8000_config = {
-    .output_mpeg2_in_188_bytes = 1,
+static struct dib8000_config dib809x_dib8000_config[2] = {
+	{
+	.output_mpeg2_in_188_bytes = 1,
 
-    .agc_config_count = 2,
-    .agc = dib8090_agc_config,
-    .agc_control = dib0090_dcc_freq,
-    .pll = &dib8090_pll_config_12mhz,
-    .tuner_is_baseband = 1,
+	.agc_config_count = 2,
+	.agc = dib8090_agc_config,
+	.agc_control = dib0090_dcc_freq,
+	.pll = &dib8090_pll_config_12mhz,
+	.tuner_is_baseband = 1,
 
-    .gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
-    .gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
-    .gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
+	.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
+	.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
+	.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
 
-    .hostbus_diversity = 1,
-    .div_cfg = 0x31,
-    .output_mode = OUTMODE_MPEG2_FIFO,
-    .drives = 0x2d98,
-    .diversity_delay = 144,
-    .refclksel = 3,
+	.hostbus_diversity = 1,
+	.div_cfg = 0x31,
+	.output_mode = OUTMODE_MPEG2_FIFO,
+	.drives = 0x2d98,
+	.diversity_delay = 48,
+	.refclksel = 3,
+	}, {
+	.output_mpeg2_in_188_bytes = 1,
+
+	.agc_config_count = 2,
+	.agc = dib8090_agc_config,
+	.agc_control = dib0090_dcc_freq,
+	.pll = &dib8090_pll_config_12mhz,
+	.tuner_is_baseband = 1,
+
+	.gpio_dir = DIB8000_GPIO_DEFAULT_DIRECTIONS,
+	.gpio_val = DIB8000_GPIO_DEFAULT_VALUES,
+	.gpio_pwm_pos = DIB8000_GPIO_DEFAULT_PWM_POS,
+
+	.hostbus_diversity = 1,
+	.div_cfg = 0x31,
+	.output_mode = OUTMODE_DIVERSITY,
+	.drives = 0x2d08,
+	.diversity_delay = 1,
+	.refclksel = 3,
+	}
+};
+
+static struct dib0090_wbd_slope dib8090_wbd_table[] = {
+	/* max freq ; cold slope ; cold offset ; warm slope ; warm offset ; wbd gain */
+	{ 120,     0, 500,  0,   500, 4 }, /* CBAND */
+	{ 170,     0, 450,  0,   450, 4 }, /* CBAND */
+	{ 380,    48, 373, 28,   259, 6 }, /* VHF */
+	{ 860,    34, 700, 36,   616, 6 }, /* high UHF */
+	{ 0xFFFF, 34, 700, 36,   616, 6 }, /* default */
 };
 
 static struct dib0090_config dib809x_dib0090_config = {
-    .io.pll_bypass = 1,
-    .io.pll_range = 1,
-    .io.pll_prediv = 1,
-    .io.pll_loopdiv = 20,
-    .io.adc_clock_ratio = 8,
-    .io.pll_int_loop_filt = 0,
-    .io.clock_khz = 12000,
-    .reset = dib80xx_tuner_reset,
-    .sleep = dib80xx_tuner_sleep,
-    .clkouttobamse = 1,
-    .analog_output = 1,
-    .i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
-    .wbd_vhf_offset = 100,
-    .wbd_cband_offset = 450,
-    .use_pwm_agc = 1,
-    .clkoutdrive = 1,
-    .get_adc_power = dib8090_get_adc_power,
-	.freq_offset_khz_uhf = 0,
+	.io.pll_bypass = 1,
+	.io.pll_range = 1,
+	.io.pll_prediv = 1,
+	.io.pll_loopdiv = 20,
+	.io.adc_clock_ratio = 8,
+	.io.pll_int_loop_filt = 0,
+	.io.clock_khz = 12000,
+	.reset = dib80xx_tuner_reset,
+	.sleep = dib80xx_tuner_sleep,
+	.clkouttobamse = 1,
+	.analog_output = 1,
+	.i2c_address = DEFAULT_DIB0090_I2C_ADDRESS,
+	.use_pwm_agc = 1,
+	.clkoutdrive = 1,
+	.get_adc_power = dib8090_get_adc_power,
+	.freq_offset_khz_uhf = -63,
 	.freq_offset_khz_vhf = -143,
+	.wbd = dib8090_wbd_table,
+	.fref_clock_ratio = 6,
 };
 
 static int dib8096_set_param_override(struct dvb_frontend *fe,
 		struct dvb_frontend_parameters *fep)
 {
-    struct dvb_usb_adapter *adap = fe->dvb->priv;
-    struct dib0700_adapter_state *state = adap->priv;
-    u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
-    u16 offset;
-    int ret = 0;
-    enum frontend_tune_state tune_state = CT_SHUTDOWN;
-    u16 ltgain, rf_gain_limit;
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+	u8 band = BAND_OF_FREQUENCY(fep->frequency/1000);
+	u16 target;
+	int ret = 0;
+	enum frontend_tune_state tune_state = CT_SHUTDOWN;
+	u16 ltgain, rf_gain_limit;
 
-    ret = state->set_param_save(fe, fep);
-    if (ret < 0)
-	return ret;
+	ret = state->set_param_save(fe, fep);
+	if (ret < 0)
+		return ret;
 
-    switch (band) {
-    case BAND_VHF:
-	    offset = 100;
-	    break;
-    case BAND_UHF:
-	    offset = 550;
-	    break;
-    default:
-	    offset = 0;
-	    break;
-    }
-    offset += (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
-    dib8000_set_wbd_ref(fe, offset);
+	target = (dib0090_get_wbd_offset(fe) * 8 * 18 / 33 + 1) / 2;
+	dib8000_set_wbd_ref(fe, target);
 
 
-    if (band == BAND_CBAND) {
-	deb_info("tuning in CBAND - soft-AGC startup\n");
-	/* TODO specific wbd target for dib0090 - needed for startup ? */
-	dib0090_set_tune_state(fe, CT_AGC_START);
-	do {
-		ret = dib0090_gain_control(fe);
-		msleep(ret);
-		tune_state = dib0090_get_tune_state(fe);
-		if (tune_state == CT_AGC_STEP_0)
-			dib8000_set_gpio(fe, 6, 0, 1);
-		else if (tune_state == CT_AGC_STEP_1) {
-			dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
-			if (rf_gain_limit == 0)
-				dib8000_set_gpio(fe, 6, 0, 0);
-		}
-	} while (tune_state < CT_AGC_STOP);
-	dib0090_pwm_gain_reset(fe);
-	dib8000_pwm_agc_reset(fe);
-	dib8000_set_tune_state(fe, CT_DEMOD_START);
-    } else {
-	deb_info("not tuning in CBAND - standard AGC startup\n");
-	dib0090_pwm_gain_reset(fe);
-    }
+	if (band == BAND_CBAND) {
+		deb_info("tuning in CBAND - soft-AGC startup\n");
+		dib0090_set_tune_state(fe, CT_AGC_START);
+		do {
+			ret = dib0090_gain_control(fe);
+			msleep(ret);
+			tune_state = dib0090_get_tune_state(fe);
+			if (tune_state == CT_AGC_STEP_0)
+				dib8000_set_gpio(fe, 6, 0, 1);
+			else if (tune_state == CT_AGC_STEP_1) {
+				dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
+				if (rf_gain_limit == 0)
+					dib8000_set_gpio(fe, 6, 0, 0);
+			}
+		} while (tune_state < CT_AGC_STOP);
+		dib0090_pwm_gain_reset(fe);
+		dib8000_pwm_agc_reset(fe);
+		dib8000_set_tune_state(fe, CT_DEMOD_START);
+	} else {
+		deb_info("not tuning in CBAND - standard AGC startup\n");
+		dib0090_pwm_gain_reset(fe);
+	}
 
-    return 0;
+	return 0;
 }
 
 static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
 {
-    struct dib0700_adapter_state *st = adap->priv;
-    struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	struct dib0700_adapter_state *st = adap->priv;
+	struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
 
-    if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
-	return -ENODEV;
+	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+		return -ENODEV;
 
-    st->set_param_save = adap->fe->ops.tuner_ops.set_params;
-    adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
-    return 0;
+	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+	adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+	return 0;
 }
 
 static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
@@ -1554,11 +1574,931 @@
 
 	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80);
 
-	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config);
+	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+
+	return adap->fe == NULL ?  -ENODEV : 0;
+}
+
+static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *st = adap->priv;
+	struct i2c_adapter *tun_i2c;
+	struct dvb_frontend *fe_slave  = dib8000_get_slave_frontend(adap->fe, 1);
+
+	if (fe_slave) {
+		tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
+		if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
+			return -ENODEV;
+		fe_slave->dvb = adap->fe->dvb;
+		fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
+	}
+	tun_i2c = dib8000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &dib809x_dib0090_config) == NULL)
+		return -ENODEV;
+
+	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+	adap->fe->ops.tuner_ops.set_params = dib8096_set_param_override;
+
+	return 0;
+}
+
+static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dvb_frontend *fe_slave;
+
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(1000);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	dib0700_ctrl_clock(adap->dev, 72, 1);
+
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80);
+
+	adap->fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+	if (adap->fe == NULL)
+		return -ENODEV;
+
+	fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
+	dib8000_set_slave_frontend(adap->fe, fe_slave);
+
+	return fe_slave == NULL ?  -ENODEV : 0;
+}
+
+/* STK9090M */
+static int dib90x0_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
+{
+	return dib9000_fw_pid_filter(adapter->fe, index, pid, onoff);
+}
+
+static int dib90x0_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
+{
+	return dib9000_fw_pid_filter_ctrl(adapter->fe, onoff);
+}
+
+static int dib90x0_tuner_reset(struct dvb_frontend *fe, int onoff)
+{
+	return dib9000_set_gpio(fe, 5, 0, !onoff);
+}
+
+static int dib90x0_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	return dib9000_set_gpio(fe, 0, 0, onoff);
+}
+
+static int dib01x0_pmu_update(struct i2c_adapter *i2c, u16 *data, u8 len)
+{
+	u8 wb[4] = { 0xc >> 8, 0xc & 0xff, 0, 0 };
+	u8 rb[2];
+	struct i2c_msg msg[2] = {
+		{.addr = 0x1e >> 1, .flags = 0, .buf = wb, .len = 2},
+		{.addr = 0x1e >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
+	};
+	u8 index_data;
+
+	dibx000_i2c_set_speed(i2c, 250);
+
+	if (i2c_transfer(i2c, msg, 2) != 2)
+		return -EIO;
+
+	switch (rb[0] << 8 | rb[1]) {
+	case 0:
+			deb_info("Found DiB0170 rev1: This version of DiB0170 is not supported any longer.\n");
+			return -EIO;
+	case 1:
+			deb_info("Found DiB0170 rev2");
+			break;
+	case 2:
+			deb_info("Found DiB0190 rev2");
+			break;
+	default:
+			deb_info("DiB01x0 not found");
+			return -EIO;
+	}
+
+	for (index_data = 0; index_data < len; index_data += 2) {
+		wb[2] = (data[index_data + 1] >> 8) & 0xff;
+		wb[3] = (data[index_data + 1]) & 0xff;
+
+		if (data[index_data] == 0) {
+			wb[0] = (data[index_data] >> 8) & 0xff;
+			wb[1] = (data[index_data]) & 0xff;
+			msg[0].len = 2;
+			if (i2c_transfer(i2c, msg, 2) != 2)
+				return -EIO;
+			wb[2] |= rb[0];
+			wb[3] |= rb[1] & ~(3 << 4);
+		}
+
+		wb[0] = (data[index_data] >> 8)&0xff;
+		wb[1] = (data[index_data])&0xff;
+		msg[0].len = 4;
+		if (i2c_transfer(i2c, &msg[0], 1) != 1)
+			return -EIO;
+	}
+	return 0;
+}
+
+static struct dib9000_config stk9090m_config = {
+	.output_mpeg2_in_188_bytes = 1,
+	.output_mode = OUTMODE_MPEG2_FIFO,
+	.vcxo_timer = 279620,
+	.timing_frequency = 20452225,
+	.demod_clock_khz = 60000,
+	.xtal_clock_khz = 30000,
+	.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
+	.subband = {
+		2,
+		{
+			{ 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0008 } }, /* GPIO 3 to 1 for VHF */
+			{ 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0008, 0x0000, 0x0000 } }, /* GPIO 3 to 0 for UHF */
+			{ 0 },
+		},
+	},
+	.gpio_function = {
+		{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 },
+		{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 },
+	},
+};
+
+static struct dib9000_config nim9090md_config[2] = {
+	{
+		.output_mpeg2_in_188_bytes = 1,
+		.output_mode = OUTMODE_MPEG2_FIFO,
+		.vcxo_timer = 279620,
+		.timing_frequency = 20452225,
+		.demod_clock_khz = 60000,
+		.xtal_clock_khz = 30000,
+		.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
+	}, {
+		.output_mpeg2_in_188_bytes = 1,
+		.output_mode = OUTMODE_DIVERSITY,
+		.vcxo_timer = 279620,
+		.timing_frequency = 20452225,
+		.demod_clock_khz = 60000,
+		.xtal_clock_khz = 30000,
+		.if_drives = (0 << 15) | (1 << 13) | (0 << 12) | (3 << 10) | (0 << 9) | (1 << 7) | (0 << 6) | (0 << 4) | (1 << 3) | (1 << 1) | (0),
+		.subband = {
+			2,
+			{
+				{ 240, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0006 } }, /* GPIO 1 and 2 to 1 for VHF */
+				{ 890, { BOARD_GPIO_COMPONENT_DEMOD, BOARD_GPIO_FUNCTION_SUBBAND_GPIO, 0x0006, 0x0000, 0x0000 } }, /* GPIO 1 and 2 to 0 for UHF */
+				{ 0 },
+			},
+		},
+		.gpio_function = {
+			{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_ON, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = (0x10 & ~0x1) | 0x20 },
+			{ .component = BOARD_GPIO_COMPONENT_DEMOD, .function = BOARD_GPIO_FUNCTION_COMPONENT_OFF, .mask = 0x10 | 0x21, .direction = 0 & ~0x21, .value = 0 | 0x21 },
+		},
+	}
+};
+
+static struct dib0090_config dib9090_dib0090_config = {
+	.io.pll_bypass = 0,
+	.io.pll_range = 1,
+	.io.pll_prediv = 1,
+	.io.pll_loopdiv = 8,
+	.io.adc_clock_ratio = 8,
+	.io.pll_int_loop_filt = 0,
+	.io.clock_khz = 30000,
+	.reset = dib90x0_tuner_reset,
+	.sleep = dib90x0_tuner_sleep,
+	.clkouttobamse = 0,
+	.analog_output = 0,
+	.use_pwm_agc = 0,
+	.clkoutdrive = 0,
+	.freq_offset_khz_uhf = 0,
+	.freq_offset_khz_vhf = 0,
+};
+
+static struct dib0090_config nim9090md_dib0090_config[2] = {
+	{
+		.io.pll_bypass = 0,
+		.io.pll_range = 1,
+		.io.pll_prediv = 1,
+		.io.pll_loopdiv = 8,
+		.io.adc_clock_ratio = 8,
+		.io.pll_int_loop_filt = 0,
+		.io.clock_khz = 30000,
+		.reset = dib90x0_tuner_reset,
+		.sleep = dib90x0_tuner_sleep,
+		.clkouttobamse = 1,
+		.analog_output = 0,
+		.use_pwm_agc = 0,
+		.clkoutdrive = 0,
+		.freq_offset_khz_uhf = 0,
+		.freq_offset_khz_vhf = 0,
+	}, {
+		.io.pll_bypass = 0,
+		.io.pll_range = 1,
+		.io.pll_prediv = 1,
+		.io.pll_loopdiv = 8,
+		.io.adc_clock_ratio = 8,
+		.io.pll_int_loop_filt = 0,
+		.io.clock_khz = 30000,
+		.reset = dib90x0_tuner_reset,
+		.sleep = dib90x0_tuner_sleep,
+		.clkouttobamse = 0,
+		.analog_output = 0,
+		.use_pwm_agc = 0,
+		.clkoutdrive = 0,
+		.freq_offset_khz_uhf = 0,
+		.freq_offset_khz_vhf = 0,
+	}
+};
+
+
+static int stk9090m_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *state = adap->priv;
+	struct dib0700_state *st = adap->dev->priv;
+	u32 fw_version;
+
+	/* Make use of the new i2c functions from FW 1.20 */
+	dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
+	if (fw_version >= 0x10200)
+		st->fw_use_new_i2c_api = 1;
+	dib0700_set_i2c_speed(adap->dev, 340);
+
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	dib0700_ctrl_clock(adap->dev, 72, 1);
+
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80);
+
+	if (reject_firmware(&state->frontend_firmware, "/*(DEBLOBBED)*/", &adap->dev->udev->dev)) {
+		deb_info("%s: Upload failed. (file not found?)\n", __func__);
+		return -ENODEV;
+	} else {
+		deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size);
+	}
+	stk9090m_config.microcode_B_fe_size = state->frontend_firmware->size;
+	stk9090m_config.microcode_B_fe_buffer = state->frontend_firmware->data;
+
+	adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &stk9090m_config);
 
 	return adap->fe == NULL ?  -ENODEV : 0;
 }
 
+static int dib9090_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *state = adap->priv;
+	struct i2c_adapter *i2c = dib9000_get_tuner_interface(adap->fe);
+	u16 data_dib190[10] = {
+		1, 0x1374,
+		2, 0x01a2,
+		7, 0x0020,
+		0, 0x00ef,
+		8, 0x0486,
+	};
+
+	if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &dib9090_dib0090_config) == NULL)
+		return -ENODEV;
+	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+	if (dib01x0_pmu_update(i2c, data_dib190, 10) != 0)
+		return -ENODEV;
+	dib0700_set_i2c_speed(adap->dev, 2000);
+	if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+		return -ENODEV;
+	release_firmware(state->frontend_firmware);
+	return 0;
+}
+
+static int nim9090md_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *state = adap->priv;
+	struct dib0700_state *st = adap->dev->priv;
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe_slave;
+	u32 fw_version;
+
+	/* Make use of the new i2c functions from FW 1.20 */
+	dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
+	if (fw_version >= 0x10200)
+		st->fw_use_new_i2c_api = 1;
+	dib0700_set_i2c_speed(adap->dev, 340);
+
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	dib0700_ctrl_clock(adap->dev, 72, 1);
+
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	if (reject_firmware(&state->frontend_firmware, "/*(DEBLOBBED)*/", &adap->dev->udev->dev)) {
+		deb_info("%s: Upload failed. (file not found?)\n", __func__);
+		return -EIO;
+	} else {
+		deb_info("%s: firmware read %Zu bytes.\n", __func__, state->frontend_firmware->size);
+	}
+	nim9090md_config[0].microcode_B_fe_size = state->frontend_firmware->size;
+	nim9090md_config[0].microcode_B_fe_buffer = state->frontend_firmware->data;
+	nim9090md_config[1].microcode_B_fe_size = state->frontend_firmware->size;
+	nim9090md_config[1].microcode_B_fe_buffer = state->frontend_firmware->data;
+
+	dib9000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, 0x80);
+	adap->fe = dvb_attach(dib9000_attach, &adap->dev->i2c_adap, 0x80, &nim9090md_config[0]);
+
+	if (adap->fe == NULL)
+		return -ENODEV;
+
+	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_3_4, 0);
+	dib9000_i2c_enumeration(i2c, 1, 0x12, 0x82);
+
+	fe_slave = dvb_attach(dib9000_attach, i2c, 0x82, &nim9090md_config[1]);
+	dib9000_set_slave_frontend(adap->fe, fe_slave);
+
+	return fe_slave == NULL ?  -ENODEV : 0;
+}
+
+static int nim9090md_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *state = adap->priv;
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe_slave;
+	u16 data_dib190[10] = {
+		1, 0x5374,
+		2, 0x01ae,
+		7, 0x0020,
+		0, 0x00ef,
+		8, 0x0406,
+	};
+	i2c = dib9000_get_tuner_interface(adap->fe);
+	if (dvb_attach(dib0090_fw_register, adap->fe, i2c, &nim9090md_dib0090_config[0]) == NULL)
+		return -ENODEV;
+	i2c = dib9000_get_i2c_master(adap->fe, DIBX000_I2C_INTERFACE_GPIO_1_2, 0);
+	if (dib01x0_pmu_update(i2c, data_dib190, 10) < 0)
+		return -ENODEV;
+	dib0700_set_i2c_speed(adap->dev, 2000);
+	if (dib9000_firmware_post_pll_init(adap->fe) < 0)
+		return -ENODEV;
+
+	fe_slave = dib9000_get_slave_frontend(adap->fe, 1);
+	if (fe_slave != NULL) {
+		i2c = dib9000_get_component_bus_interface(adap->fe);
+		dib9000_set_i2c_adapter(fe_slave, i2c);
+
+		i2c = dib9000_get_tuner_interface(fe_slave);
+		if (dvb_attach(dib0090_fw_register, fe_slave, i2c, &nim9090md_dib0090_config[1]) == NULL)
+			return -ENODEV;
+		fe_slave->dvb = adap->fe->dvb;
+		dib9000_fw_set_component_bus_speed(adap->fe, 2000);
+		if (dib9000_firmware_post_pll_init(fe_slave) < 0)
+			return -ENODEV;
+	}
+	release_firmware(state->frontend_firmware);
+
+	return 0;
+}
+
+/* NIM7090 */
+struct dib7090p_best_adc {
+	u32 timf;
+	u32 pll_loopdiv;
+	u32 pll_prediv;
+};
+
+static int dib7090p_get_best_sampling(struct dvb_frontend *fe , struct dib7090p_best_adc *adc)
+{
+	u8 spur = 0, prediv = 0, loopdiv = 0, min_prediv = 1, max_prediv = 1;
+
+	u16 xtal = 12000;
+	u32 fcp_min = 1900;  /* PLL Minimum Frequency comparator KHz */
+	u32 fcp_max = 20000; /* PLL Maximum Frequency comparator KHz */
+	u32 fdem_max = 76000;
+	u32 fdem_min = 69500;
+	u32 fcp = 0, fs = 0, fdem = 0;
+	u32 harmonic_id = 0;
+
+	adc->pll_loopdiv = loopdiv;
+	adc->pll_prediv = prediv;
+	adc->timf = 0;
+
+	deb_info("bandwidth = %d fdem_min =%d", fe->dtv_property_cache.bandwidth_hz, fdem_min);
+
+	/* Find Min and Max prediv */
+	while ((xtal/max_prediv) >= fcp_min)
+		max_prediv++;
+
+	max_prediv--;
+	min_prediv = max_prediv;
+	while ((xtal/min_prediv) <= fcp_max) {
+		min_prediv--;
+		if (min_prediv == 1)
+			break;
+	}
+	deb_info("MIN prediv = %d : MAX prediv = %d", min_prediv, max_prediv);
+
+	min_prediv = 2;
+
+	for (prediv = min_prediv ; prediv < max_prediv; prediv++) {
+		fcp = xtal / prediv;
+		if (fcp > fcp_min && fcp < fcp_max) {
+			for (loopdiv = 1 ; loopdiv < 64 ; loopdiv++) {
+				fdem = ((xtal/prediv) * loopdiv);
+				fs   = fdem / 4;
+				/* test min/max system restrictions */
+
+				if ((fdem >= fdem_min) && (fdem <= fdem_max) && (fs >= fe->dtv_property_cache.bandwidth_hz/1000)) {
+					spur = 0;
+					/* test fs harmonics positions */
+					for (harmonic_id = (fe->dtv_property_cache.frequency / (1000*fs)) ;  harmonic_id <= ((fe->dtv_property_cache.frequency / (1000*fs))+1) ; harmonic_id++) {
+						if (((fs*harmonic_id) >= ((fe->dtv_property_cache.frequency/1000) - (fe->dtv_property_cache.bandwidth_hz/2000))) &&  ((fs*harmonic_id) <= ((fe->dtv_property_cache.frequency/1000) + (fe->dtv_property_cache.bandwidth_hz/2000)))) {
+							spur = 1;
+							break;
+						}
+					}
+
+					if (!spur) {
+						adc->pll_loopdiv = loopdiv;
+						adc->pll_prediv = prediv;
+						adc->timf = 2396745143UL/fdem*(1 << 9);
+						adc->timf += ((2396745143UL%fdem) << 9)/fdem;
+						deb_info("loopdiv=%i prediv=%i timf=%i", loopdiv, prediv, adc->timf);
+						break;
+					}
+				}
+			}
+		}
+		if (!spur)
+			break;
+	}
+
+
+	if (adc->pll_loopdiv == 0 && adc->pll_prediv == 0)
+		return -EINVAL;
+	else
+		return 0;
+}
+
+static int dib7090_agc_startup(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+	struct dvb_usb_adapter *adap = fe->dvb->priv;
+	struct dib0700_adapter_state *state = adap->priv;
+	struct dibx000_bandwidth_config pll;
+	u16 target;
+	struct dib7090p_best_adc adc;
+	int ret;
+
+	ret = state->set_param_save(fe, fep);
+	if (ret < 0)
+		return ret;
+
+	memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
+	dib0090_pwm_gain_reset(fe);
+	target = (dib0090_get_wbd_offset(fe) * 8 + 1) / 2;
+	dib7000p_set_wbd_ref(fe, target);
+
+	if (dib7090p_get_best_sampling(fe, &adc) == 0) {
+		pll.pll_ratio  = adc.pll_loopdiv;
+		pll.pll_prediv = adc.pll_prediv;
+
+		dib7000p_update_pll(fe, &pll);
+		dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+	}
+	return 0;
+}
+
+static struct dib0090_wbd_slope dib7090_wbd_table[] = {
+	{ 380,   81, 850, 64, 540,  4},
+	{ 860,   51, 866, 21,  375, 4},
+	{1700,    0, 250, 0,   100, 6},
+	{2600,    0, 250, 0,   100, 6},
+	{ 0xFFFF, 0,   0, 0,   0,   0},
+};
+
+struct dibx000_agc_config dib7090_agc_config[2] = {
+	{
+		.band_caps      = BAND_UHF,
+		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+		.setup          = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+
+		.inv_gain       = 687,
+		.time_stabiliz  = 10,
+
+		.alpha_level    = 0,
+		.thlock         = 118,
+
+		.wbd_inv        = 0,
+		.wbd_ref        = 1200,
+		.wbd_sel        = 3,
+		.wbd_alpha      = 5,
+
+		.agc1_max       = 65535,
+		.agc1_min       = 0,
+
+		.agc2_max       = 65535,
+		.agc2_min       = 0,
+
+		.agc1_pt1       = 0,
+		.agc1_pt2       = 32,
+		.agc1_pt3       = 114,
+		.agc1_slope1    = 143,
+		.agc1_slope2    = 144,
+		.agc2_pt1       = 114,
+		.agc2_pt2       = 227,
+		.agc2_slope1    = 116,
+		.agc2_slope2    = 117,
+
+		.alpha_mant     = 18,
+		.alpha_exp      = 0,
+		.beta_mant      = 20,
+		.beta_exp       = 59,
+
+		.perform_agc_softsplit = 0,
+	} , {
+		.band_caps      = BAND_FM | BAND_VHF | BAND_CBAND,
+		/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1, P_agc_inv_pwm1=0, P_agc_inv_pwm2=0,
+		* P_agc_inh_dc_rv_est=0, P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
+		.setup          = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8) | (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
+
+		.inv_gain       = 732,
+		.time_stabiliz  = 10,
+
+		.alpha_level    = 0,
+		.thlock         = 118,
+
+		.wbd_inv        = 0,
+		.wbd_ref        = 1200,
+		.wbd_sel        = 3,
+		.wbd_alpha      = 5,
+
+		.agc1_max       = 65535,
+		.agc1_min       = 0,
+
+		.agc2_max       = 65535,
+		.agc2_min       = 0,
+
+		.agc1_pt1       = 0,
+		.agc1_pt2       = 0,
+		.agc1_pt3       = 98,
+		.agc1_slope1    = 0,
+		.agc1_slope2    = 167,
+		.agc2_pt1       = 98,
+		.agc2_pt2       = 255,
+		.agc2_slope1    = 104,
+		.agc2_slope2    = 0,
+
+		.alpha_mant     = 18,
+		.alpha_exp      = 0,
+		.beta_mant      = 20,
+		.beta_exp       = 59,
+
+		.perform_agc_softsplit = 0,
+	}
+};
+
+static struct dibx000_bandwidth_config dib7090_clock_config_12_mhz = {
+	60000, 15000,
+	1, 5, 0, 0, 0,
+	0, 0, 1, 1, 2,
+	(3 << 14) | (1 << 12) | (524 << 0),
+	(0 << 25) | 0,
+	20452225,
+	15000000,
+};
+
+static struct dib7000p_config nim7090_dib7000p_config = {
+	.output_mpeg2_in_188_bytes  = 1,
+	.hostbus_diversity			= 1,
+	.tuner_is_baseband			= 1,
+	.update_lna					= NULL,
+
+	.agc_config_count			= 2,
+	.agc						= dib7090_agc_config,
+
+	.bw							= &dib7090_clock_config_12_mhz,
+
+	.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+	.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
+	.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+	.pwm_freq_div				= 0,
+
+	.agc_control				= dib7090_agc_restart,
+
+	.spur_protect				= 0,
+	.disable_sample_and_hold	= 0,
+	.enable_current_mirror		= 0,
+	.diversity_delay			= 0,
+
+	.output_mode				= OUTMODE_MPEG2_FIFO,
+	.enMpegOutput				= 1,
+};
+
+static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
+	{
+		.output_mpeg2_in_188_bytes  = 1,
+		.hostbus_diversity			= 1,
+		.tuner_is_baseband			= 1,
+		.update_lna					= NULL,
+
+		.agc_config_count			= 2,
+		.agc						= dib7090_agc_config,
+
+		.bw							= &dib7090_clock_config_12_mhz,
+
+		.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+		.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
+		.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+		.pwm_freq_div				= 0,
+
+		.agc_control				= dib7090_agc_restart,
+
+		.spur_protect				= 0,
+		.disable_sample_and_hold	= 0,
+		.enable_current_mirror		= 0,
+		.diversity_delay			= 0,
+
+		.output_mode				= OUTMODE_MPEG2_PAR_GATED_CLK,
+		.default_i2c_addr			= 0x90,
+		.enMpegOutput				= 1,
+	}, {
+		.output_mpeg2_in_188_bytes  = 1,
+		.hostbus_diversity			= 1,
+		.tuner_is_baseband			= 1,
+		.update_lna					= NULL,
+
+		.agc_config_count			= 2,
+		.agc						= dib7090_agc_config,
+
+		.bw							= &dib7090_clock_config_12_mhz,
+
+		.gpio_dir					= DIB7000P_GPIO_DEFAULT_DIRECTIONS,
+		.gpio_val					= DIB7000P_GPIO_DEFAULT_VALUES,
+		.gpio_pwm_pos				= DIB7000P_GPIO_DEFAULT_PWM_POS,
+
+		.pwm_freq_div				= 0,
+
+		.agc_control				= dib7090_agc_restart,
+
+		.spur_protect				= 0,
+		.disable_sample_and_hold	= 0,
+		.enable_current_mirror		= 0,
+		.diversity_delay			= 0,
+
+		.output_mode				= OUTMODE_MPEG2_PAR_GATED_CLK,
+		.default_i2c_addr			= 0x92,
+		.enMpegOutput				= 0,
+	}
+};
+
+static const struct dib0090_config nim7090_dib0090_config = {
+	.io.clock_khz = 12000,
+	.io.pll_bypass = 0,
+	.io.pll_range = 0,
+	.io.pll_prediv = 3,
+	.io.pll_loopdiv = 6,
+	.io.adc_clock_ratio = 0,
+	.io.pll_int_loop_filt = 0,
+	.reset = dib7090_tuner_sleep,
+	.sleep = dib7090_tuner_sleep,
+
+	.freq_offset_khz_uhf = 0,
+	.freq_offset_khz_vhf = 0,
+
+	.get_adc_power = dib7090_get_adc_power,
+
+	.clkouttobamse = 1,
+	.analog_output = 0,
+
+	.wbd_vhf_offset = 0,
+	.wbd_cband_offset = 0,
+	.use_pwm_agc = 1,
+	.clkoutdrive = 0,
+
+	.fref_clock_ratio = 0,
+
+	.wbd = dib7090_wbd_table,
+
+	.ls_cfg_pad_drv = 0,
+	.data_tx_drv = 0,
+	.low_if = NULL,
+	.in_soc = 1,
+};
+
+static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
+	{
+		.io.clock_khz = 12000,
+		.io.pll_bypass = 0,
+		.io.pll_range = 0,
+		.io.pll_prediv = 3,
+		.io.pll_loopdiv = 6,
+		.io.adc_clock_ratio = 0,
+		.io.pll_int_loop_filt = 0,
+		.reset = dib7090_tuner_sleep,
+		.sleep = dib7090_tuner_sleep,
+
+		.freq_offset_khz_uhf = 50,
+		.freq_offset_khz_vhf = 70,
+
+		.get_adc_power = dib7090_get_adc_power,
+
+		.clkouttobamse = 1,
+		.analog_output = 0,
+
+		.wbd_vhf_offset = 0,
+		.wbd_cband_offset = 0,
+		.use_pwm_agc = 1,
+		.clkoutdrive = 0,
+
+		.fref_clock_ratio = 0,
+
+		.wbd = dib7090_wbd_table,
+
+		.ls_cfg_pad_drv = 0,
+		.data_tx_drv = 0,
+		.low_if = NULL,
+		.in_soc = 1,
+	}, {
+		.io.clock_khz = 12000,
+		.io.pll_bypass = 0,
+		.io.pll_range = 0,
+		.io.pll_prediv = 3,
+		.io.pll_loopdiv = 6,
+		.io.adc_clock_ratio = 0,
+		.io.pll_int_loop_filt = 0,
+		.reset = dib7090_tuner_sleep,
+		.sleep = dib7090_tuner_sleep,
+
+		.freq_offset_khz_uhf = -50,
+		.freq_offset_khz_vhf = -70,
+
+		.get_adc_power = dib7090_get_adc_power,
+
+		.clkouttobamse = 1,
+		.analog_output = 0,
+
+		.wbd_vhf_offset = 0,
+		.wbd_cband_offset = 0,
+		.use_pwm_agc = 1,
+		.clkoutdrive = 0,
+
+		.fref_clock_ratio = 0,
+
+		.wbd = dib7090_wbd_table,
+
+		.ls_cfg_pad_drv = 0,
+		.data_tx_drv = 0,
+		.low_if = NULL,
+		.in_soc = 1,
+	}
+};
+
+static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
+{
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+		return -ENODEV;
+	}
+	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+
+	return adap->fe == NULL ?  -ENODEV : 0;
+}
+
+static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *st = adap->priv;
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+
+	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &nim7090_dib0090_config) == NULL)
+		return -ENODEV;
+
+	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+
+	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+	adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+	return 0;
+}
+
+static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_state *st = adap->dev->priv;
+
+	/* The TFE7090 requires the dib0700 to not be in master mode */
+	st->disable_streaming_master_mode = 1;
+
+	dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO7, GPIO_OUT, 1);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
+
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
+	msleep(20);
+	dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
+
+	/* initialize IC 0 */
+	if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+		return -ENODEV;
+	}
+
+	dib0700_set_i2c_speed(adap->dev, 340);
+	adap->fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+
+	if (adap->fe == NULL)
+		return -ENODEV;
+
+	dib7090_slave_reset(adap->fe);
+
+	return 0;
+}
+
+static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
+{
+	struct i2c_adapter *i2c;
+
+	if (adap->dev->adapter[0].fe == NULL) {
+		err("the master dib7090 has to be initialized first");
+		return -ENODEV; /* the master device has not been initialized */
+	}
+
+	i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+	if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
+		err("%s: dib7000p_i2c_enumeration failed.  Cannot continue\n", __func__);
+		return -ENODEV;
+	}
+
+	adap->fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+	dib0700_set_i2c_speed(adap->dev, 200);
+
+	return adap->fe == NULL ? -ENODEV : 0;
+}
+
+static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *st = adap->priv;
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+
+	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
+		return -ENODEV;
+
+	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+
+	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+	adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+	return 0;
+}
+
+static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
+{
+	struct dib0700_adapter_state *st = adap->priv;
+	struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe);
+
+	if (dvb_attach(dib0090_register, adap->fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
+		return -ENODEV;
+
+	dib7000p_set_gpio(adap->fe, 8, 0, 1);
+
+	st->set_param_save = adap->fe->ops.tuner_ops.set_params;
+	adap->fe->ops.tuner_ops.set_params = dib7090_agc_startup;
+	return 0;
+}
+
 /* STK7070PD */
 static struct dib7000p_config stk7070pd_dib7000p_config[2] = {
 	{
@@ -1856,6 +2796,12 @@
 	{ USB_DEVICE(USB_VID_PINNACLE,	USB_PID_PINNACLE_PCTV282E) },
 	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_STK8096GP) },
 	{ USB_DEVICE(USB_VID_ELGATO,    USB_PID_ELGATO_EYETV_DIVERSITY) },
+	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM9090M) },
+/* 70 */{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM8096MD) },
+	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM9090MD) },
+	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_NIM7090) },
+	{ USB_DEVICE(USB_VID_DIBCOM,    USB_PID_DIBCOM_TFE7090PVR) },
+	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2) },
 	{ 0 }		/* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, dib0700_usb_id_table);
@@ -2465,7 +3411,7 @@
 			},
 		},
 
-		.num_device_descs = 2,
+		.num_device_descs = 3,
 		.devices = {
 			{   "DiBcom STK7770P reference design",
 				{ &dib0700_usb_id_table[59], NULL },
@@ -2477,6 +3423,10 @@
 					&dib0700_usb_id_table[60], NULL},
 				{ NULL },
 			},
+			{   "TechniSat AirStar TeleStick 2",
+				{ &dib0700_usb_id_table[74], NULL },
+				{ NULL },
+			},
 		},
 
 		.rc.core = {
@@ -2608,6 +3558,205 @@
 				{ NULL },
 			},
 		},
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
+		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter = dib90x0_pid_filter,
+				.pid_filter_ctrl = dib90x0_pid_filter_ctrl,
+				.frontend_attach  = stk9090m_frontend_attach,
+				.tuner_attach     = dib9090_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom STK9090M reference design",
+				{ &dib0700_usb_id_table[69], NULL },
+				{ NULL },
+			},
+		},
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
+		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter = stk80xx_pid_filter,
+				.pid_filter_ctrl = stk80xx_pid_filter_ctrl,
+				.frontend_attach  = nim8096md_frontend_attach,
+				.tuner_attach     = nim8096md_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom NIM8096MD reference design",
+				{ &dib0700_usb_id_table[70], NULL },
+				{ NULL },
+			},
+		},
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
+		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter = dib90x0_pid_filter,
+				.pid_filter_ctrl = dib90x0_pid_filter_ctrl,
+				.frontend_attach  = nim9090md_frontend_attach,
+				.tuner_attach     = nim9090md_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom NIM9090MD reference design",
+				{ &dib0700_usb_id_table[71], NULL },
+				{ NULL },
+			},
+		},
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
+		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.num_adapters = 1,
+		.adapter = {
+			{
+				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter = stk70x0p_pid_filter,
+				.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = nim7090_frontend_attach,
+				.tuner_attach     = nim7090_tuner_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom NIM7090 reference design",
+				{ &dib0700_usb_id_table[72], NULL },
+				{ NULL },
+			},
+		},
+
+		.rc.core = {
+			.rc_interval      = DEFAULT_RC_INTERVAL,
+			.rc_codes         = RC_MAP_DIB0700_RC5_TABLE,
+			.module_name	  = "dib0700",
+			.rc_query         = dib0700_rc_query_old_firmware,
+			.allowed_protos   = RC_TYPE_RC5 |
+					    RC_TYPE_RC6 |
+					    RC_TYPE_NEC,
+			.change_protocol  = dib0700_change_protocol,
+		},
+	}, { DIB0700_DEFAULT_DEVICE_PROPERTIES,
+		.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 = stk70x0p_pid_filter,
+				.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = tfe7090pvr_frontend0_attach,
+				.tuner_attach     = tfe7090pvr_tuner0_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x03),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+			{
+				.caps  = DVB_USB_ADAP_HAS_PID_FILTER |
+					DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+				.pid_filter_count = 32,
+				.pid_filter = stk70x0p_pid_filter,
+				.pid_filter_ctrl = stk70x0p_pid_filter_ctrl,
+				.frontend_attach  = tfe7090pvr_frontend1_attach,
+				.tuner_attach     = tfe7090pvr_tuner1_attach,
+
+				DIB0700_DEFAULT_STREAMING_CONFIG(0x02),
+
+				.size_of_priv =
+					sizeof(struct dib0700_adapter_state),
+			},
+		},
+
+		.num_device_descs = 1,
+		.devices = {
+			{   "DiBcom TFE7090PVR reference design",
+				{ &dib0700_usb_id_table[73], NULL },
+				{ NULL },
+			},
+		},
 
 		.rc.core = {
 			.rc_interval      = DEFAULT_RC_INTERVAL,
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dib0700.h linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dib0700.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dib0700.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dib0700.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 	// 1 Byte: 4MSB(1 = enable streaming, 0 = disable streaming) 4LSB(Video Mode: 0 = MPEG2 188Bytes, 1 = Analog)
 	// 2 Byte: MPEG2 mode:  4MSB(1 = Master Mode, 0 = Slave Mode) 4LSB(Channel 1 = bit0, Channel 2 = bit1)
 	// 2 Byte: Analog mode: 4MSB(0 = 625 lines, 1 = 525 lines)    4LSB(     "                "           )
+#define REQUEST_SET_I2C_PARAM       0x10
 #define REQUEST_SET_RC              0x11
 #define REQUEST_NEW_I2C_READ        0x12
 #define REQUEST_NEW_I2C_WRITE       0x13
@@ -61,6 +62,7 @@
 extern int dib0700_identify_state(struct usb_device *udev, struct dvb_usb_device_properties *props,
 			struct dvb_usb_device_description **desc, int *cold);
 extern int dib0700_change_protocol(struct rc_dev *dev, u64 rc_type);
+extern int dib0700_set_i2c_speed(struct dvb_usb_device *d, u16 scl_kHz);
 
 extern int dib0700_device_count;
 extern int dvb_usb_dib0700_ir_proto;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/digitv.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/digitv.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/digitv.c	2012-03-24 01:01:54.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/digitv.c	2012-03-24 03:27:23.000000000 -0400
@@ -176,7 +176,7 @@
 	{ 0xaf59, KEY_AUX },
 	{ 0x5f5a, KEY_DVD },
 	{ 0x6f5a, KEY_POWER },
-	{ 0x9f5a, KEY_MHP },     /* labelled 'Picture' */
+	{ 0x9f5a, KEY_CAMERA },     /* labelled 'Picture' */
 	{ 0xaf5a, KEY_AUDIO },
 	{ 0x5f65, KEY_INFO },
 	{ 0x6f65, KEY_F13 },     /* 16:9 */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dvb-usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -181,6 +181,7 @@
  * @rc_codes: name of rc codes table
  * @protocol: type of protocol(s) currently used by the driver
  * @allowed_protos: protocol(s) supported by the driver
+ * @driver_type: Used to point if a device supports raw mode
  * @change_protocol: callback to change protocol
  * @rc_query: called to query an event event.
  * @rc_interval: time in ms between two queries.
@@ -190,6 +191,7 @@
 	char *rc_codes;
 	u64 protocol;
 	u64 allowed_protos;
+	enum rc_driver_type driver_type;
 	int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
 	char *module_name;
 	int (*rc_query) (struct dvb_usb_device *d);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dvb-usb-ids.h	2011-05-19 00:06:34.000000000 -0400
@@ -106,8 +106,13 @@
 #define USB_PID_DIBCOM_STK807XP				0x1f90
 #define USB_PID_DIBCOM_STK807XPVR			0x1f98
 #define USB_PID_DIBCOM_STK8096GP                        0x1fa0
+#define USB_PID_DIBCOM_NIM8096MD                        0x1fa8
 #define USB_PID_DIBCOM_ANCHOR_2135_COLD			0x2131
 #define USB_PID_DIBCOM_STK7770P				0x1e80
+#define USB_PID_DIBCOM_NIM7090				0x1bb2
+#define USB_PID_DIBCOM_TFE7090PVR			0x1bb4
+#define USB_PID_DIBCOM_NIM9090M				0x2383
+#define USB_PID_DIBCOM_NIM9090MD			0x2384
 #define USB_PID_DPOSH_M9206_COLD			0x9206
 #define USB_PID_DPOSH_M9206_WARM			0xa090
 #define USB_PID_E3C_EC168				0x1689
@@ -312,4 +317,6 @@
 #define USB_PID_TERRATEC_DVBS2CI_V2			0x10ac
 #define USB_PID_TECHNISAT_USB2_HDCI_V1			0x0001
 #define USB_PID_TECHNISAT_USB2_HDCI_V2			0x0002
+#define USB_PID_TECHNISAT_AIRSTAR_TELESTICK_2		0x0004
+#define USB_PID_TECHNISAT_USB2_DVB_S2			0x0500
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dvb-usb-remote.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dvb-usb-remote.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dvb-usb-remote.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dvb-usb-remote.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,60 +8,71 @@
 #include "dvb-usb-common.h"
 #include <linux/usb/input.h>
 
-static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
-				unsigned int scancode, unsigned int *keycode)
+static unsigned int
+legacy_dvb_usb_get_keymap_index(const struct input_keymap_entry *ke,
+				struct rc_map_table *keymap,
+				unsigned int keymap_size)
 {
-	struct dvb_usb_device *d = input_get_drvdata(dev);
+	unsigned int index;
+	unsigned int scancode;
 
-	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	int i;
+	if (ke->flags & INPUT_KEYMAP_BY_INDEX) {
+		index = ke->index;
+	} else {
+		if (input_scancode_to_scalar(ke, &scancode))
+			return keymap_size;
 
-	/* See if we can match the raw key code. */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].scancode == scancode) {
-			*keycode = keymap[i].keycode;
-			return 0;
-		}
+		/* See if we can match the raw key code. */
+		for (index = 0; index < keymap_size; index++)
+			if (keymap[index].scancode == scancode)
+				break;
 
-	/*
-	 * If is there extra space, returns KEY_RESERVED,
-	 * otherwise, input core won't let legacy_dvb_usb_setkeycode
-	 * to work
-	 */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].keycode == KEY_RESERVED ||
-		    keymap[i].keycode == KEY_UNKNOWN) {
-			*keycode = KEY_RESERVED;
-			return 0;
+		/* See if there is an unused hole in the map */
+		if (index >= keymap_size) {
+			for (index = 0; index < keymap_size; index++) {
+				if (keymap[index].keycode == KEY_RESERVED ||
+				    keymap[index].keycode == KEY_UNKNOWN) {
+					break;
+				}
+			}
 		}
+	}
 
-	return -EINVAL;
+	return index;
 }
 
-static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
-				unsigned int scancode, unsigned int keycode)
+static int legacy_dvb_usb_getkeycode(struct input_dev *dev,
+				     struct input_keymap_entry *ke)
 {
 	struct dvb_usb_device *d = input_get_drvdata(dev);
-
 	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
-	int i;
+	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
+	unsigned int index;
 
-	/* Search if it is replacing an existing keycode */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].scancode == scancode) {
-			keymap[i].keycode = keycode;
-			return 0;
-		}
+	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
+	if (index >= keymap_size)
+		return -EINVAL;
 
-	/* Search if is there a clean entry. If so, use it */
-	for (i = 0; i < d->props.rc.legacy.rc_map_size; i++)
-		if (keymap[i].keycode == KEY_RESERVED ||
-		    keymap[i].keycode == KEY_UNKNOWN) {
-			keymap[i].scancode = scancode;
-			keymap[i].keycode = keycode;
-			return 0;
-		}
+	ke->keycode = keymap[index].keycode;
+	if (ke->keycode == KEY_UNKNOWN)
+		ke->keycode = KEY_RESERVED;
+	ke->len = sizeof(keymap[index].scancode);
+	memcpy(&ke->scancode, &keymap[index].scancode, ke->len);
+	ke->index = index;
+
+	return 0;
+}
 
+static int legacy_dvb_usb_setkeycode(struct input_dev *dev,
+				     const struct input_keymap_entry *ke,
+				     unsigned int *old_keycode)
+{
+	struct dvb_usb_device *d = input_get_drvdata(dev);
+	struct rc_map_table *keymap = d->props.rc.legacy.rc_map_table;
+	unsigned int keymap_size = d->props.rc.legacy.rc_map_size;
+	unsigned int index;
+
+	index = legacy_dvb_usb_get_keymap_index(ke, keymap, keymap_size);
 	/*
 	 * FIXME: Currently, it is not possible to increase the size of
 	 * scancode table. For it to happen, one possibility
@@ -69,8 +80,24 @@
 	 * copying data, appending the new key on it, and freeing
 	 * the old one - or maybe just allocating some spare space
 	 */
+	if (index >= keymap_size)
+		return -EINVAL;
 
-	return -EINVAL;
+	*old_keycode = keymap[index].keycode;
+	keymap->keycode = ke->keycode;
+	__set_bit(ke->keycode, dev->keybit);
+
+	if (*old_keycode != KEY_RESERVED) {
+		__clear_bit(*old_keycode, dev->keybit);
+		for (index = 0; index < keymap_size; index++) {
+			if (keymap[index].keycode == *old_keycode) {
+				__set_bit(*old_keycode, dev->keybit);
+				break;
+			}
+		}
+	}
+
+	return 0;
 }
 
 /* Remote-control poll function - called every dib->rc_query_interval ms to see
@@ -246,7 +273,7 @@
 	dev->map_name = d->props.rc.core.rc_codes;
 	dev->change_protocol = d->props.rc.core.change_protocol;
 	dev->allowed_protos = d->props.rc.core.allowed_protos;
-	dev->driver_type = RC_DRIVER_SCANCODE;
+	dev->driver_type = d->props.rc.core.driver_type;
 	usb_to_input_id(d->udev, &dev->input_id);
 	dev->input_name = "IR-receiver inside an USB DVB receiver";
 	dev->input_phys = d->rc_phys;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dw2102.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dw2102.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/dw2102.c	2012-03-24 01:02:03.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/dw2102.c	2012-03-24 03:27:28.000000000 -0400
@@ -1,15 +1,16 @@
 /* DVB USB framework compliant Linux driver for the
-*	DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
-*	TeVii S600, S630, S650,
-*	Prof 1100, 7500 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
-*	Free Software Foundation, version 2.
-*
-* see Documentation/dvb/README.dvb-usb for more information
-*/
+ *	DVBWorld DVB-S 2101, 2102, DVB-S2 2104, DVB-C 3101,
+ *	TeVii S600, S630, S650, S660, S480,
+ *	Prof 1100, 7500,
+ *	Geniatech SU3000 Cards
+ * Copyright (C) 2008-2011 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
+ *	Free Software Foundation, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
 #include "dw2102.h"
 #include "si21xx.h"
 #include "stv0299.h"
@@ -55,6 +56,14 @@
 #define USB_PID_TEVII_S660 0xd660
 #endif
 
+#ifndef USB_PID_TEVII_S480_1
+#define USB_PID_TEVII_S480_1 0xd481
+#endif
+
+#ifndef USB_PID_TEVII_S480_2
+#define USB_PID_TEVII_S480_2 0xd482
+#endif
+
 #ifndef USB_PID_PROF_1100
 #define USB_PID_PROF_1100 0xb012
 #endif
@@ -67,7 +76,9 @@
 #define REG_21_SYMBOLRATE_BYTE2 0x21
 /* on my own*/
 #define DW2102_VOLTAGE_CTRL (0x1800)
+#define SU3000_STREAM_CTRL (0x1900)
 #define DW2102_RC_QUERY (0x1a00)
+#define DW2102_LED_CTRL (0x1b00)
 
 #define	err_str "did not find the firmware file. (%s) " \
 		"Please see linux/Documentation/dvb/ for more details " \
@@ -78,6 +89,14 @@
 	int rc_keys_size;
 };
 
+struct su3000_state {
+	u8 initialized;
+};
+
+struct s6x0_state {
+	int (*old_set_voltage)(struct dvb_frontend *f, fe_sec_voltage_t v);
+};
+
 /* debug */
 static int dvb_usb_dw2102_debug;
 module_param_named(debug, dvb_usb_dw2102_debug, int, 0644);
@@ -87,7 +106,8 @@
 /* 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  ...");
+MODULE_PARM_DESC(keymap, "set keymap 0=default 1=dvbworld 2=tevii 3=tbs  ..."
+			" 256=none");
 
 /* demod probe */
 static int demod_probe = 1;
@@ -136,8 +156,7 @@
 		/* read stv0299 register */
 		value = msg[0].buf[0];/* register */
 		for (i = 0; i < msg[1].len; i++) {
-			value = value + i;
-			ret = dw210x_op_rw(d->udev, 0xb5, value, 0,
+			ret = dw210x_op_rw(d->udev, 0xb5, value + i, 0,
 					buf6, 2, DW210X_READ_MSG);
 			msg[1].buf[i] = buf6[0];
 		}
@@ -483,10 +502,10 @@
 	for (j = 0; j < num; j++) {
 		switch (msg[j].addr) {
 		case (DW2102_RC_QUERY): {
-			u8 ibuf[4];
+			u8 ibuf[5];
 			ret  = dw210x_op_rw(d->udev, 0xb8, 0, 0,
-					ibuf, 4, DW210X_READ_MSG);
-			memcpy(msg[j].buf, ibuf + 1, 2);
+					ibuf, 5, DW210X_READ_MSG);
+			memcpy(msg[j].buf, ibuf + 3, 2);
 			break;
 		}
 		case (DW2102_VOLTAGE_CTRL): {
@@ -502,6 +521,15 @@
 					obuf, 2, DW210X_WRITE_MSG);
 			break;
 		}
+		case (DW2102_LED_CTRL): {
+			u8 obuf[2];
+
+			obuf[0] = 5;
+			obuf[1] = msg[j].buf[0];
+			ret = dw210x_op_rw(d->udev, 0x8a, 0, 0,
+					obuf, 2, DW210X_WRITE_MSG);
+			break;
+		}
 		/*case 0x55: cx24116
 		case 0x6a: stv0903
 		case 0x68: ds3000, stv0903
@@ -535,14 +563,15 @@
 					i += 16;
 					len -= 16;
 				} while (len > 0);
-			} else if ((udev->descriptor.idProduct == 0x7500)
-					&& (j < (num - 1))) {
+			} else if (j < (num - 1)) {
 				/* write register addr before read */
 				u8 obuf[msg[j].len + 2];
 				obuf[0] = msg[j + 1].len;
 				obuf[1] = (msg[j].addr << 1);
 				memcpy(obuf + 2, msg[j].buf, msg[j].len);
-				ret = dw210x_op_rw(d->udev, 0x92, 0, 0,
+				ret = dw210x_op_rw(d->udev,
+						udev->descriptor.idProduct ==
+						0x7500 ? 0x92 : 0x90, 0, 0,
 						obuf, msg[j].len + 2,
 						DW210X_WRITE_MSG);
 				break;
@@ -552,8 +581,7 @@
 				obuf[0] = msg[j].len + 1;
 				obuf[1] = (msg[j].addr << 1);
 				memcpy(obuf + 2, msg[j].buf, msg[j].len);
-				ret = dw210x_op_rw(d->udev,
-						(num > 1 ? 0x90 : 0x80), 0, 0,
+				ret = dw210x_op_rw(d->udev, 0x80, 0, 0,
 						obuf, msg[j].len + 2,
 						DW210X_WRITE_MSG);
 				break;
@@ -561,14 +589,76 @@
 			break;
 		}
 		}
-
-		msleep(3);
 	}
 
 	mutex_unlock(&d->i2c_mutex);
 	return num;
 }
 
+static int su3000_i2c_transfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+								int num)
+{
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+	u8 obuf[0x40], ibuf[0x40];
+
+	if (!d)
+		return -ENODEV;
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	switch (num) {
+	case 1:
+		switch (msg[0].addr) {
+		case SU3000_STREAM_CTRL:
+			obuf[0] = msg[0].buf[0] + 0x36;
+			obuf[1] = 3;
+			obuf[2] = 0;
+			if (dvb_usb_generic_rw(d, obuf, 3, ibuf, 0, 0) < 0)
+				err("i2c transfer failed.");
+			break;
+		case DW2102_RC_QUERY:
+			obuf[0] = 0x10;
+			if (dvb_usb_generic_rw(d, obuf, 1, ibuf, 2, 0) < 0)
+				err("i2c transfer failed.");
+			msg[0].buf[1] = ibuf[0];
+			msg[0].buf[0] = ibuf[1];
+			break;
+		default:
+			/* always i2c write*/
+			obuf[0] = 0x08;
+			obuf[1] = msg[0].addr;
+			obuf[2] = msg[0].len;
+
+			memcpy(&obuf[3], msg[0].buf, msg[0].len);
+
+			if (dvb_usb_generic_rw(d, obuf, msg[0].len + 3,
+						ibuf, 1, 0) < 0)
+				err("i2c transfer failed.");
+
+		}
+		break;
+	case 2:
+		/* always i2c read */
+		obuf[0] = 0x09;
+		obuf[1] = msg[0].len;
+		obuf[2] = msg[1].len;
+		obuf[3] = msg[0].addr;
+		memcpy(&obuf[4], msg[0].buf, msg[0].len);
+
+		if (dvb_usb_generic_rw(d, obuf, msg[0].len + 4,
+					ibuf, msg[1].len + 1, 0) < 0)
+			err("i2c transfer failed.");
+
+		memcpy(msg[1].buf, &ibuf[1], msg[1].len);
+		break;
+	default:
+		warn("more than 2 i2c messages at a time is not handled yet.");
+		break;
+	}
+	mutex_unlock(&d->i2c_mutex);
+	return num;
+}
+
 static u32 dw210x_i2c_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_I2C;
@@ -604,6 +694,11 @@
 	.functionality = dw210x_i2c_func,
 };
 
+static struct i2c_algorithm su3000_i2c_algo = {
+	.master_xfer = su3000_i2c_transfer,
+	.functionality = dw210x_i2c_func,
+};
+
 static int dw210x_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
 {
 	int i;
@@ -668,6 +763,82 @@
 	return 0;
 };
 
+static int su3000_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+	static u8 command_start[] = {0x00};
+	static u8 command_stop[] = {0x01};
+	struct i2c_msg msg = {
+		.addr = SU3000_STREAM_CTRL,
+		.flags = 0,
+		.buf = onoff ? command_start : command_stop,
+		.len = 1
+	};
+
+	i2c_transfer(&adap->dev->i2c_adap, &msg, 1);
+
+	return 0;
+}
+
+static int su3000_power_ctrl(struct dvb_usb_device *d, int i)
+{
+	struct su3000_state *state = (struct su3000_state *)d->priv;
+	u8 obuf[] = {0xde, 0};
+
+	info("%s: %d, initialized %d\n", __func__, i, state->initialized);
+
+	if (i && !state->initialized) {
+		state->initialized = 1;
+		/* reset board */
+		dvb_usb_generic_rw(d, obuf, 2, NULL, 0, 0);
+	}
+
+	return 0;
+}
+
+static int su3000_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+{
+	int i;
+	u8 obuf[] = { 0x1f, 0xf0 };
+	u8 ibuf[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0x51,
+			.flags = 0,
+			.buf = obuf,
+			.len = 2,
+		}, {
+			.addr = 0x51,
+			.flags = I2C_M_RD,
+			.buf = ibuf,
+			.len = 1,
+
+		}
+	};
+
+	for (i = 0; i < 6; i++) {
+		obuf[1] = 0xf0 + i;
+		if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
+			break;
+		else
+			mac[i] = ibuf[0];
+
+		debug_dump(mac, 6, printk);
+	}
+
+	return 0;
+}
+
+static int su3000_identify_state(struct usb_device *udev,
+				 struct dvb_usb_device_properties *props,
+				 struct dvb_usb_device_description **desc,
+				 int *cold)
+{
+	info("%s\n", __func__);
+
+	*cold = 0;
+	return 0;
+}
+
 static int dw210x_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
 	static u8 command_13v[] = {0x00, 0x01};
@@ -692,6 +863,37 @@
 	return 0;
 }
 
+static int s660_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+	struct dvb_usb_adapter *d =
+		(struct dvb_usb_adapter *)(fe->dvb->priv);
+	struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
+
+	dw210x_set_voltage(fe, voltage);
+	if (st->old_set_voltage)
+		st->old_set_voltage(fe, voltage);
+
+	return 0;
+}
+
+static void dw210x_led_ctrl(struct dvb_frontend *fe, int offon)
+{
+	static u8 led_off[] = { 0 };
+	static u8 led_on[] = { 1 };
+	struct i2c_msg msg = {
+		.addr = DW2102_LED_CTRL,
+		.flags = 0,
+		.buf = led_off,
+		.len = 1
+	};
+	struct dvb_usb_adapter *udev_adap =
+		(struct dvb_usb_adapter *)(fe->dvb->priv);
+
+	if (offon)
+		msg.buf = led_on;
+	i2c_transfer(&udev_adap->dev->i2c_adap, &msg, 1);
+}
+
 static struct stv0299_config sharp_z0194a_config = {
 	.demod_address = 0x68,
 	.inittab = sharp_z0194a_inittab,
@@ -771,6 +973,12 @@
 	.tun1_adc = 0,/* 2 Vpp */
 	.path1_mode = 3,
 	.tun1_type = 3,
+	.set_lock_led = dw210x_led_ctrl,
+};
+
+static struct ds3000_config su3000_ds3000_config = {
+	.demod_address = 0x68,
+	.ci_mode = 1,
 };
 
 static int dw2104_frontend_attach(struct dvb_usb_adapter *d)
@@ -885,7 +1093,7 @@
 	return -EIO;
 }
 
-static int s6x0_frontend_attach(struct dvb_usb_adapter *d)
+static int zl100313_frontend_attach(struct dvb_usb_adapter *d)
 {
 	d->fe = dvb_attach(mt312_attach, &zl313_config,
 			&d->dev->i2c_adap);
@@ -898,41 +1106,108 @@
 		}
 	}
 
+	return -EIO;
+}
+
+static int stv0288_frontend_attach(struct dvb_usb_adapter *d)
+{
+	u8 obuf[] = {7, 1};
+
 	d->fe = dvb_attach(stv0288_attach, &earda_config,
 			&d->dev->i2c_adap);
-	if (d->fe != NULL) {
-		if (dvb_attach(stb6000_attach, d->fe, 0x61,
-				&d->dev->i2c_adap)) {
-			d->fe->ops.set_voltage = dw210x_set_voltage;
-			info("Attached stv0288+stb6000!\n");
-			return 0;
-		}
-	}
+
+	if (d->fe == NULL)
+		return -EIO;
+
+	if (NULL == dvb_attach(stb6000_attach, d->fe, 0x61, &d->dev->i2c_adap))
+		return -EIO;
+
+	d->fe->ops.set_voltage = dw210x_set_voltage;
+
+	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
+
+	info("Attached stv0288+stb6000!\n");
+
+	return 0;
+
+}
+
+static int ds3000_frontend_attach(struct dvb_usb_adapter *d)
+{
+	struct s6x0_state *st = (struct s6x0_state *)d->dev->priv;
+	u8 obuf[] = {7, 1};
 
 	d->fe = dvb_attach(ds3000_attach, &dw2104_ds3000_config,
 			&d->dev->i2c_adap);
-	if (d->fe != NULL) {
-		d->fe->ops.set_voltage = dw210x_set_voltage;
-		info("Attached ds3000+ds2020!\n");
-		return 0;
-	}
 
-	return -EIO;
+	if (d->fe == NULL)
+		return -EIO;
+
+	st->old_set_voltage = d->fe->ops.set_voltage;
+	d->fe->ops.set_voltage = s660_set_voltage;
+
+	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
+
+	info("Attached ds3000+ds2020!\n");
+
+	return 0;
 }
 
 static int prof_7500_frontend_attach(struct dvb_usb_adapter *d)
 {
+	u8 obuf[] = {7, 1};
+
 	d->fe = dvb_attach(stv0900_attach, &prof_7500_stv0900_config,
 					&d->dev->i2c_adap, 0);
 	if (d->fe == NULL)
 		return -EIO;
+
 	d->fe->ops.set_voltage = dw210x_set_voltage;
 
+	dw210x_op_rw(d->dev->udev, 0x8a, 0, 0, obuf, 2, DW210X_WRITE_MSG);
+
 	info("Attached STV0900+STB6100A!\n");
 
 	return 0;
 }
 
+static int su3000_frontend_attach(struct dvb_usb_adapter *d)
+{
+	u8 obuf[3] = { 0xe, 0x80, 0 };
+	u8 ibuf[] = { 0 };
+
+	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
+		err("command 0x0e transfer failed.");
+
+	obuf[0] = 0xe;
+	obuf[1] = 0x83;
+	obuf[2] = 0;
+
+	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
+		err("command 0x0e transfer failed.");
+
+	obuf[0] = 0xe;
+	obuf[1] = 0x83;
+	obuf[2] = 1;
+
+	if (dvb_usb_generic_rw(d->dev, obuf, 3, ibuf, 1, 0) < 0)
+		err("command 0x0e transfer failed.");
+
+	obuf[0] = 0x51;
+
+	if (dvb_usb_generic_rw(d->dev, obuf, 1, ibuf, 1, 0) < 0)
+		err("command 0x51 transfer failed.");
+
+	d->fe = dvb_attach(ds3000_attach, &su3000_ds3000_config,
+					&d->dev->i2c_adap);
+	if (d->fe == NULL)
+		return -EIO;
+
+	info("Attached DS3000!\n");
+
+	return 0;
+}
+
 static int dw2102_tuner_attach(struct dvb_usb_adapter *adap)
 {
 	dvb_attach(dvb_pll_attach, adap->fe, 0x60,
@@ -949,8 +1224,8 @@
 }
 
 static struct rc_map_table rc_map_dw210x_table[] = {
-	{ 0xf80a, KEY_Q },		/*power*/
-	{ 0xf80c, KEY_M },		/*mute*/
+	{ 0xf80a, KEY_POWER2 },		/*power*/
+	{ 0xf80c, KEY_MUTE },		/*mute*/
 	{ 0xf811, KEY_1 },
 	{ 0xf812, KEY_2 },
 	{ 0xf813, KEY_3 },
@@ -961,25 +1236,25 @@
 	{ 0xf818, KEY_8 },
 	{ 0xf819, KEY_9 },
 	{ 0xf810, KEY_0 },
-	{ 0xf81c, KEY_PAGEUP },	/*ch+*/
-	{ 0xf80f, KEY_PAGEDOWN },	/*ch-*/
-	{ 0xf81a, KEY_O },		/*vol+*/
-	{ 0xf80e, KEY_Z },		/*vol-*/
-	{ 0xf804, KEY_R },		/*rec*/
-	{ 0xf809, KEY_D },		/*fav*/
-	{ 0xf808, KEY_BACKSPACE },	/*rewind*/
-	{ 0xf807, KEY_A },		/*fast*/
-	{ 0xf80b, KEY_P },		/*pause*/
-	{ 0xf802, KEY_ESC },	/*cancel*/
-	{ 0xf803, KEY_G },		/*tab*/
+	{ 0xf81c, KEY_CHANNELUP },	/*ch+*/
+	{ 0xf80f, KEY_CHANNELDOWN },	/*ch-*/
+	{ 0xf81a, KEY_VOLUMEUP },	/*vol+*/
+	{ 0xf80e, KEY_VOLUMEDOWN },	/*vol-*/
+	{ 0xf804, KEY_RECORD },		/*rec*/
+	{ 0xf809, KEY_FAVORITES },	/*fav*/
+	{ 0xf808, KEY_REWIND },		/*rewind*/
+	{ 0xf807, KEY_FASTFORWARD },	/*fast*/
+	{ 0xf80b, KEY_PAUSE },		/*pause*/
+	{ 0xf802, KEY_ESC },		/*cancel*/
+	{ 0xf803, KEY_TAB },		/*tab*/
 	{ 0xf800, KEY_UP },		/*up*/
-	{ 0xf81f, KEY_ENTER },	/*ok*/
-	{ 0xf801, KEY_DOWN },	/*down*/
-	{ 0xf805, KEY_C },		/*cap*/
-	{ 0xf806, KEY_S },		/*stop*/
-	{ 0xf840, KEY_F },		/*full*/
-	{ 0xf81e, KEY_W },		/*tvmode*/
-	{ 0xf81b, KEY_B },		/*recall*/
+	{ 0xf81f, KEY_OK },		/*ok*/
+	{ 0xf801, KEY_DOWN },		/*down*/
+	{ 0xf805, KEY_CAMERA },		/*cap*/
+	{ 0xf806, KEY_STOP },		/*stop*/
+	{ 0xf840, KEY_ZOOM },		/*full*/
+	{ 0xf81e, KEY_TV },		/*tvmode*/
+	{ 0xf81b, KEY_LAST },		/*recall*/
 };
 
 static struct rc_map_table rc_map_tevii_table[] = {
@@ -1067,10 +1342,49 @@
 	{ 0xf89b, KEY_MODE }
 };
 
+static struct rc_map_table rc_map_su3000_table[] = {
+	{ 0x25, KEY_POWER },	/* right-bottom Red */
+	{ 0x0a, KEY_MUTE },	/* -/-- */
+	{ 0x01, KEY_1 },
+	{ 0x02, KEY_2 },
+	{ 0x03, KEY_3 },
+	{ 0x04, KEY_4 },
+	{ 0x05, KEY_5 },
+	{ 0x06, KEY_6 },
+	{ 0x07, KEY_7 },
+	{ 0x08, KEY_8 },
+	{ 0x09, KEY_9 },
+	{ 0x00, KEY_0 },
+	{ 0x20, KEY_UP },	/* CH+ */
+	{ 0x21, KEY_DOWN },	/* CH+ */
+	{ 0x12, KEY_VOLUMEUP },	/* Brightness Up */
+	{ 0x13, KEY_VOLUMEDOWN },/* Brightness Down */
+	{ 0x1f, KEY_RECORD },
+	{ 0x17, KEY_PLAY },
+	{ 0x16, KEY_PAUSE },
+	{ 0x0b, KEY_STOP },
+	{ 0x27, KEY_FASTFORWARD },/* >> */
+	{ 0x26, KEY_REWIND },	/* << */
+	{ 0x0d, KEY_OK },	/* Mute */
+	{ 0x11, KEY_LEFT },	/* VOL- */
+	{ 0x10, KEY_RIGHT },	/* VOL+ */
+	{ 0x29, KEY_BACK },	/* button under 9 */
+	{ 0x2c, KEY_MENU },	/* TTX */
+	{ 0x2b, KEY_EPG },	/* EPG */
+	{ 0x1e, KEY_RED },	/* OSD */
+	{ 0x0e, KEY_GREEN },	/* Window */
+	{ 0x2d, KEY_YELLOW },	/* button under << */
+	{ 0x0f, KEY_BLUE },	/* bottom yellow button */
+	{ 0x14, KEY_AUDIO },	/* Snapshot */
+	{ 0x38, KEY_TV },	/* TV/Radio */
+	{ 0x0c, KEY_ESC }	/* upper Red buttton */
+};
+
 static struct rc_map_dvb_usb_table_table keys_tables[] = {
 	{ rc_map_dw210x_table, ARRAY_SIZE(rc_map_dw210x_table) },
 	{ rc_map_tevii_table, ARRAY_SIZE(rc_map_tevii_table) },
 	{ rc_map_tbs_table, ARRAY_SIZE(rc_map_tbs_table) },
+	{ rc_map_su3000_table, ARRAY_SIZE(rc_map_su3000_table) },
 };
 
 static int dw2102_rc_query(struct dvb_usb_device *d, u32 *event, int *state)
@@ -1089,7 +1403,8 @@
 	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;
-	}
+	} else if (ir_keymap > ARRAY_SIZE(keys_tables))
+		return 0; /* none */
 
 	*state = REMOTE_NO_KEY_PRESSED;
 	if (d->props.i2c_algo->master_xfer(&d->i2c_adap, &msg, 1) == 1) {
@@ -1125,6 +1440,11 @@
 	{USB_DEVICE(0x3011, USB_PID_PROF_1100)},
 	{USB_DEVICE(0x9022, USB_PID_TEVII_S660)},
 	{USB_DEVICE(0x3034, 0x7500)},
+	{USB_DEVICE(0x1f4d, 0x3000)},
+	{USB_DEVICE(USB_VID_TERRATEC, 0x00a8)},
+	{USB_DEVICE(0x9022, USB_PID_TEVII_S480_1)},
+	{USB_DEVICE(0x9022, USB_PID_TEVII_S480_2)},
+	{USB_DEVICE(0x1f4d, 0x3100)},
 	{ }
 };
 
@@ -1184,11 +1504,6 @@
 		}
 		/* init registers */
 		switch (dev->descriptor.idProduct) {
-		case USB_PID_PROF_1100:
-			s6x0_properties.rc.legacy.rc_map_table = rc_map_tbs_table;
-			s6x0_properties.rc.legacy.rc_map_size =
-					ARRAY_SIZE(rc_map_tbs_table);
-			break;
 		case USB_PID_TEVII_S650:
 			dw2104_properties.rc.legacy.rc_map_table = rc_map_tevii_table;
 			dw2104_properties.rc.legacy.rc_map_size =
@@ -1271,8 +1586,6 @@
 	.adapter = {
 		{
 			.frontend_attach = dw2102_frontend_attach,
-			.streaming_ctrl = NULL,
-			.tuner_attach = NULL,
 			.stream = {
 				.type = USB_BULK,
 				.count = 8,
@@ -1324,8 +1637,6 @@
 	.adapter = {
 		{
 			.frontend_attach = dw2104_frontend_attach,
-			.streaming_ctrl = NULL,
-			/*.tuner_attach = dw2104_tuner_attach,*/
 			.stream = {
 				.type = USB_BULK,
 				.count = 8,
@@ -1373,7 +1684,6 @@
 	.adapter = {
 		{
 			.frontend_attach = dw3101_frontend_attach,
-			.streaming_ctrl = NULL,
 			.tuner_attach = dw3101_tuner_attach,
 			.stream = {
 				.type = USB_BULK,
@@ -1399,6 +1709,7 @@
 static struct dvb_usb_device_properties s6x0_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
 	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv = sizeof(struct s6x0_state),
 	.firmware = "/*(DEBLOBBED)*/",
 	.no_reconnect = 1,
 
@@ -1416,9 +1727,7 @@
 	.read_mac_address = s6x0_read_mac_address,
 	.adapter = {
 		{
-			.frontend_attach = s6x0_frontend_attach,
-			.streaming_ctrl = NULL,
-			.tuner_attach = NULL,
+			.frontend_attach = zl100313_frontend_attach,
 			.stream = {
 				.type = USB_BULK,
 				.count = 8,
@@ -1431,23 +1740,41 @@
 			},
 		}
 	},
-	.num_device_descs = 3,
+	.num_device_descs = 1,
 	.devices = {
 		{"TeVii S630 USB",
 			{&dw2102_table[6], NULL},
 			{NULL},
 		},
-		{"Prof 1100 USB ",
-			{&dw2102_table[7], NULL},
-			{NULL},
-		},
-		{"TeVii S660 USB",
-			{&dw2102_table[8], NULL},
-			{NULL},
-		},
 	}
 };
 
+struct dvb_usb_device_properties *p1100;
+static struct dvb_usb_device_description d1100 = {
+	"Prof 1100 USB ",
+	{&dw2102_table[7], NULL},
+	{NULL},
+};
+
+struct dvb_usb_device_properties *s660;
+static struct dvb_usb_device_description d660 = {
+	"TeVii S660 USB",
+	{&dw2102_table[8], NULL},
+	{NULL},
+};
+
+static struct dvb_usb_device_description d480_1 = {
+	"TeVii S480.1 USB",
+	{&dw2102_table[12], NULL},
+	{NULL},
+};
+
+static struct dvb_usb_device_description d480_2 = {
+	"TeVii S480.2 USB",
+	{&dw2102_table[13], NULL},
+	{NULL},
+};
+
 struct dvb_usb_device_properties *p7500;
 static struct dvb_usb_device_description d7500 = {
 	"Prof 7500 USB DVB-S2",
@@ -1455,17 +1782,97 @@
 	{NULL},
 };
 
+static struct dvb_usb_device_properties su3000_properties = {
+	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
+	.usb_ctrl = DEVICE_SPECIFIC,
+	.size_of_priv = sizeof(struct su3000_state),
+	.power_ctrl = su3000_power_ctrl,
+	.num_adapters = 1,
+	.identify_state	= su3000_identify_state,
+	.i2c_algo = &su3000_i2c_algo,
+
+	.rc.legacy = {
+		.rc_map_table = rc_map_su3000_table,
+		.rc_map_size = ARRAY_SIZE(rc_map_su3000_table),
+		.rc_interval = 150,
+		.rc_query = dw2102_rc_query,
+	},
+
+	.read_mac_address = su3000_read_mac_address,
+
+	.generic_bulk_ctrl_endpoint = 0x01,
+
+	.adapter = {
+		{
+			.streaming_ctrl   = su3000_streaming_ctrl,
+			.frontend_attach  = su3000_frontend_attach,
+			.stream = {
+				.type = USB_BULK,
+				.count = 8,
+				.endpoint = 0x82,
+				.u = {
+					.bulk = {
+						.buffersize = 4096,
+					}
+				}
+			}
+		}
+	},
+	.num_device_descs = 3,
+	.devices = {
+		{ "SU3000HD DVB-S USB2.0",
+			{ &dw2102_table[10], NULL },
+			{ NULL },
+		},
+		{ "Terratec Cinergy S2 USB HD",
+			{ &dw2102_table[11], NULL },
+			{ NULL },
+		},
+		{ "X3M TV SPC1400HD PCI",
+			{ &dw2102_table[14], NULL },
+			{ NULL },
+		},
+	}
+};
+
 static int dw2102_probe(struct usb_interface *intf,
 		const struct usb_device_id *id)
 {
+	p1100 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+	if (!p1100)
+		return -ENOMEM;
+	/* copy default structure */
+	memcpy(p1100, &s6x0_properties,
+			sizeof(struct dvb_usb_device_properties));
+	/* fill only different fields */
+	p1100->firmware = "/*(DEBLOBBED)*/";
+	p1100->devices[0] = d1100;
+	p1100->rc.legacy.rc_map_table = rc_map_tbs_table;
+	p1100->rc.legacy.rc_map_size = ARRAY_SIZE(rc_map_tbs_table);
+	p1100->adapter->frontend_attach = stv0288_frontend_attach;
+
+	s660 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
+	if (!s660) {
+		kfree(p1100);
+		return -ENOMEM;
+	}
+	memcpy(s660, &s6x0_properties,
+			sizeof(struct dvb_usb_device_properties));
+	s660->firmware = "/*(DEBLOBBED)*/";
+	s660->num_device_descs = 3;
+	s660->devices[0] = d660;
+	s660->devices[1] = d480_1;
+	s660->devices[2] = d480_2;
+	s660->adapter->frontend_attach = ds3000_frontend_attach;
 
 	p7500 = kzalloc(sizeof(struct dvb_usb_device_properties), GFP_KERNEL);
-	if (!p7500)
+	if (!p7500) {
+		kfree(p1100);
+		kfree(s660);
 		return -ENOMEM;
-	/* copy default structure */
+	}
 	memcpy(p7500, &s6x0_properties,
 			sizeof(struct dvb_usb_device_properties));
-	/* fill only different fields */
 	p7500->firmware = "/*(DEBLOBBED)*/";
 	p7500->devices[0] = d7500;
 	p7500->rc.legacy.rc_map_table = rc_map_tbs_table;
@@ -1480,8 +1887,14 @@
 			THIS_MODULE, NULL, adapter_nr) ||
 	    0 == dvb_usb_device_init(intf, &s6x0_properties,
 			THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, p1100,
+			THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, s660,
+			THIS_MODULE, NULL, adapter_nr) ||
 	    0 == dvb_usb_device_init(intf, p7500,
-			THIS_MODULE, NULL, adapter_nr))
+			THIS_MODULE, NULL, adapter_nr) ||
+	    0 == dvb_usb_device_init(intf, &su3000_properties,
+				     THIS_MODULE, NULL, adapter_nr))
 		return 0;
 
 	return -ENODEV;
@@ -1514,7 +1927,8 @@
 MODULE_AUTHOR("Igor M. Liplianin (c) liplianin@me.by");
 MODULE_DESCRIPTION("Driver for DVBWorld DVB-S 2101, 2102, DVB-S2 2104,"
 				" DVB-C 3101 USB2.0,"
-				" TeVii S600, S630, S650, S660 USB2.0,"
-				" Prof 1100, 7500 USB2.0 devices");
+				" TeVii S600, S630, S650, S660, S480,"
+				" Prof 1100, 7500 USB2.0,"
+				" Geniatech SU3000 devices");
 MODULE_VERSION("0.1");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/friio.h linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/friio.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/friio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/friio.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
  *         Frontend:                             comtech JDVBT-90502
  *             (tuner PLL:                       tua6034, I2C addr:(0xC0 >> 1))
  *             (OFDM demodulator:                TC90502, I2C addr:(0x30 >> 1))
- *         LED x3 (+LNB) controll:               PIC 16F676
+ *         LED x3 (+LNB) control:                PIC 16F676
  *         EEPROM:                               24C08
  *
  *        (USB smart card reader:                AU9522)
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/Kconfig linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -356,5 +356,15 @@
 	select DVB_TDA826X if !DVB_FE_CUSTOMISE
 	select DVB_STV0288 if !DVB_FE_CUSTOMISE
 	select DVB_IX2505V if !DVB_FE_CUSTOMISE
+	select DVB_STV0299 if !DVB_FE_CUSTOMISE
+	select DVB_PLL if !DVB_FE_CUSTOMISE
 	help
 	  Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
+
+config DVB_USB_TECHNISAT_USB2
+	tristate "Technisat DVB-S/S2 USB2.0 support"
+	depends on DVB_USB
+	select DVB_STV090x if !DVB_FE_CUSTOMISE
+	select DVB_STV6110x if !DVB_FE_CUSTOMISE
+	help
+	  Say Y here to support the Technisat USB2 DVB-S/S2 device
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/lmedm04.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/lmedm04.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/lmedm04.c	2012-03-24 01:02:17.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/lmedm04.c	2012-03-24 03:27:35.000000000 -0400
@@ -2,7 +2,9 @@
  *
  * DM04/QQBOX DVB-S USB BOX	LME2510C + SHARP:BS2F7HZ7395
  *				LME2510C + LG TDQY-P001F
+ *				LME2510C + BS2F7HZ0194
  *				LME2510 + LG TDQY-P001F
+ *				LME2510 + BS2F7HZ0194
  *
  * MVB7395 (LME2510C+SHARP:BS2F7HZ7395)
  * SHARP:BS2F7HZ7395 = (STV0288+Sharp IX2505V)
@@ -12,20 +14,22 @@
  *
  * MVB0001F (LME2510C+LGTDQT-P001F)
  *
+ * MV0194 (LME2510+SHARP:BS2F7HZ0194)
+ * SHARP:BS2F7HZ0194 = (STV0299+IX2410)
+ *
+ * MVB0194 (LME2510C+SHARP0194)
+ *
  * For firmware see Documentation/dvb/lmedm04.txt
  *
  * I2C addresses:
  * 0xd0 - STV0288	- Demodulator
  * 0xc0 - Sharp IX2505V	- Tuner
- * --or--
+ * --
  * 0x1c - TDA10086   - Demodulator
  * 0xc0 - TDA8263    - Tuner
- *
- * ***Please Note***
- *		There are other variants of the DM04
- *		***NOT SUPPORTED***
- *		MV0194 (LME2510+SHARP0194)
- *		MVB0194 (LME2510C+SHARP0194)
+ * --
+ * 0xd0 - STV0299	- Demodulator
+ * 0xc0 - IX2410	- Tuner
  *
  *
  * VID = 3344  PID LME2510=1122 LME2510C=1120
@@ -55,6 +59,9 @@
  *
  * QQbox suffers from noise on LNB voltage.
  *
+ *	LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
+ * with other tuners. After a cold reset streaming will not start.
+ *
  *	PID functions have been removed from this driver version due to
  * problems with different firmware and application versions.
  */
@@ -69,6 +76,9 @@
 #include "tda10086.h"
 #include "stv0288.h"
 #include "ix2505v.h"
+#include "stv0299.h"
+#include "dvb-pll.h"
+#include "z0194a.h"
 
 
 
@@ -96,8 +106,11 @@
 
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define TUNER_DEFAULT	0x0
 #define TUNER_LG	0x1
 #define TUNER_S7395	0x2
+#define TUNER_S0194	0x3
 
 struct lme2510_state {
 	u8 id;
@@ -191,7 +204,7 @@
 			rbuff, sizeof(rbuff));
 	return ret;
 }
-static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u16 keypress)
+static int lme2510_remote_keypress(struct dvb_usb_adapter *adap, u32 keypress)
 {
 	struct dvb_usb_device *d = adap->dev;
 
@@ -237,7 +250,8 @@
 		case 0xaa:
 			debug_data_snipet(1, "INT Remote data snipet in", ibuf);
 			lme2510_remote_keypress(adap,
-				(u16)(ibuf[4]<<8)+ibuf[5]);
+				(u32)(ibuf[2] << 24) + (ibuf[3] << 16) +
+				(ibuf[4] << 8) + ibuf[5]);
 			break;
 		case 0xbb:
 			switch (st->tuner_config) {
@@ -249,6 +263,7 @@
 				st->time_key = ibuf[7];
 				break;
 			case TUNER_S7395:
+			case TUNER_S0194:
 				/* Tweak for earlier firmware*/
 				if (ibuf[1] == 0x03) {
 					if (ibuf[2] > 1)
@@ -306,7 +321,7 @@
 	lme_int->lme_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	usb_submit_urb(lme_int->lme_urb, GFP_ATOMIC);
-	info("INT Interupt Service Started");
+	info("INT Interrupt Service Started");
 
 	return 0;
 }
@@ -364,6 +379,18 @@
 					msleep(5);
 			}
 			break;
+		case TUNER_S0194:
+			if (wbuf[2] == 0xd0) {
+				if (wbuf[3] == 0x1b) {
+					st->signal_lock = rbuf[1];
+					if ((st->stream_on & 1) &&
+						(st->signal_lock & 0x8)) {
+						lme2510_stream_restart(d);
+						st->i2c_talk_onoff = 0;
+					}
+				}
+			}
+			break;
 		default:
 			break;
 		}
@@ -423,11 +450,39 @@
 				break;
 			}
 			break;
+		case TUNER_S0194:
+			switch (wbuf[3]) {
+			case 0x18:
+				rbuf[0] = 0x55;
+				rbuf[1] = (st->signal_level & 0x80)
+						? 0 : (st->signal_level * 2);
+				break;
+			case 0x24:
+				rbuf[0] = 0x55;
+				rbuf[1] = st->signal_sn;
+				break;
+			case 0x1b:
+				rbuf[0] = 0x55;
+				rbuf[1] = st->signal_lock;
+				break;
+			case 0x19:
+			case 0x25:
+			case 0x1e:
+			case 0x1d:
+				rbuf[0] = 0x55;
+				rbuf[1] = 0x00;
+				break;
+			default:
+				lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
+				st->i2c_talk_onoff = 1;
+				break;
+			}
+			break;
 		default:
 			break;
 		}
 
-		deb_info(4, "I2C From Interupt Message out(%02x) in(%02x)",
+		deb_info(4, "I2C From Interrupt Message out(%02x) in(%02x)",
 				wbuf[3], rbuf[1]);
 
 	}
@@ -517,17 +572,14 @@
 		struct dvb_usb_device_description **desc,
 		int *cold)
 {
-	if (lme2510_return_status(udev) == 0x44)
-		*cold = 1;
-	else
-		*cold = 0;
+	*cold = 0;
 	return 0;
 }
 
 static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
 	struct lme2510_state *st = adap->dev->priv;
-	static u8 clear_reg_3[] =  LME_CLEAR_PID;
+	static u8 clear_reg_3[] = LME_CLEAR_PID;
 	static u8 rbuf[1];
 	int ret = 0, rlen = sizeof(rbuf);
 
@@ -580,11 +632,11 @@
 	}
 	d->rc_dev = rc;
 
-	/* Start the Interupt */
+	/* Start the Interrupt */
 	ret = lme2510_int_read(adap);
 	if (ret < 0) {
 		rc_unregister_device(rc);
-		info("INT Unable to start Interupt Service");
+		info("INT Unable to start Interrupt Service");
 		return -ENODEV;
 	}
 
@@ -658,9 +710,6 @@
 	return (ret < 0) ? -ENODEV : 0;
 }
 
-/* Default firmware for LME2510C */
-char lme_firmware[50] = "/*(DEBLOBBED)*/";
-
 static void lme_coldreset(struct usb_device *dev)
 {
 	int ret = 0, len_in;
@@ -678,49 +727,83 @@
 static int lme_firmware_switch(struct usb_device *udev, int cold)
 {
 	const struct firmware *fw = NULL;
-	char lme2510c_s7395[] = "/*(DEBLOBBED)*/";
-	char lme2510c_lg[] = "/*(DEBLOBBED)*/";
-	char *firm_msg[] = {"Loading", "Switching to"};
-	int ret;
+	const char fw_c_s7395[] = "/*(DEBLOBBED)*/";
+	const char fw_c_lg[] = "/*(DEBLOBBED)*/";
+	const char fw_c_s0194[] = "/*(DEBLOBBED)*/";
+	const char fw_lg[] = "/*(DEBLOBBED)*/";
+	const char fw_s0194[] = "/*(DEBLOBBED)*/";
+	const char *fw_lme;
+	int ret, cold_fw;
 
 	cold = (cold > 0) ? (cold & 1) : 0;
 
-	if (udev->descriptor.idProduct == 0x1122)
-		return 0;
+	cold_fw = !cold;
 
-	switch (dvb_usb_lme2510_firmware) {
-	case 0:
-	default:
-		memcpy(&lme_firmware, lme2510c_s7395, sizeof(lme2510c_s7395));
-		ret = reject_firmware(&fw, lme_firmware, &udev->dev);
-		if (ret == 0) {
-			info("FRM %s S7395 Firmware", firm_msg[cold]);
+	if (udev->descriptor.idProduct == 0x1122) {
+		switch (dvb_usb_lme2510_firmware) {
+		default:
+			dvb_usb_lme2510_firmware = TUNER_S0194;
+		case TUNER_S0194:
+			fw_lme = fw_s0194;
+			ret = reject_firmware(&fw, fw_lme, &udev->dev);
+			if (ret == 0) {
+				cold = 0;/*lme2510-s0194 cannot cold reset*/
+				break;
+			}
+			dvb_usb_lme2510_firmware = TUNER_LG;
+		case TUNER_LG:
+			fw_lme = fw_lg;
+			ret = reject_firmware(&fw, fw_lme, &udev->dev);
+			if (ret == 0)
+				break;
+			info("FRM No Firmware Found - please install");
+			dvb_usb_lme2510_firmware = TUNER_DEFAULT;
+			cold = 0;
+			cold_fw = 0;
 			break;
 		}
-		if (cold == 0)
-			dvb_usb_lme2510_firmware = 1;
-		else
+	} else {
+		switch (dvb_usb_lme2510_firmware) {
+		default:
+			dvb_usb_lme2510_firmware = TUNER_S7395;
+		case TUNER_S7395:
+			fw_lme = fw_c_s7395;
+			ret = reject_firmware(&fw, fw_lme, &udev->dev);
+			if (ret == 0)
+				break;
+			dvb_usb_lme2510_firmware = TUNER_LG;
+		case TUNER_LG:
+			fw_lme = fw_c_lg;
+			ret = reject_firmware(&fw, fw_lme, &udev->dev);
+			if (ret == 0)
+				break;
+			dvb_usb_lme2510_firmware = TUNER_S0194;
+		case TUNER_S0194:
+			fw_lme = fw_c_s0194;
+			ret = reject_firmware(&fw, fw_lme, &udev->dev);
+			if (ret == 0)
+				break;
+			info("FRM No Firmware Found - please install");
+			dvb_usb_lme2510_firmware = TUNER_DEFAULT;
 			cold = 0;
-	case 1:
-		memcpy(&lme_firmware, lme2510c_lg, sizeof(lme2510c_lg));
-		ret = reject_firmware(&fw, lme_firmware, &udev->dev);
-		if (ret == 0) {
-			info("FRM %s LG Firmware", firm_msg[cold]);
+			cold_fw = 0;
 			break;
 		}
-		info("FRM No Firmware Found - please install");
-		dvb_usb_lme2510_firmware = 0;
-		cold = 0;
-		break;
 	}
 
-	release_firmware(fw);
+	if (cold_fw) {
+		info("FRM Loading %s file", fw_lme);
+		ret = lme2510_download_firmware(udev, fw);
+	}
 
 	if (cold) {
+		info("FRM Changing to %s firmware", fw_lme);
 		lme_coldreset(udev);
 		return -ENODEV;
 	}
 
+	release_firmware(fw);
+
 	return ret;
 }
 
@@ -758,6 +841,18 @@
 	.tuner_chargepump = 0x3,
 };
 
+static struct stv0299_config sharp_z0194_config = {
+	.demod_address = 0xd0,
+	.inittab = sharp_z0194a_inittab,
+	.mclk = 88000000UL,
+	.invert = 0,
+	.skip_reinit = 0,
+	.lock_output = STV0299_LOCKOUTPUT_1,
+	.volt13_op0_op1 = STV0299_VOLT13_OP1,
+	.min_delay_ms = 100,
+	.set_symbol_rate = sharp_z0194a_set_symbol_rate,
+};
+
 static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
 					fe_sec_voltage_t voltage)
 {
@@ -793,7 +888,8 @@
 {
 	struct lme2510_state *st = adap->dev->priv;
 	const char *desc = adap->dev->desc->name;
-	char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395"};
+	char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
+				" SHARP:BS2F7HZ0194"};
 	char *name = adap->fe->ops.info.name;
 
 	strlcpy(name, desc, 128);
@@ -820,26 +916,40 @@
 		st->i2c_tuner_gate_r = 4;
 		st->i2c_tuner_addr = 0xc0;
 		st->tuner_config = TUNER_LG;
-		if (dvb_usb_lme2510_firmware != 1) {
-			dvb_usb_lme2510_firmware = 1;
+		if (dvb_usb_lme2510_firmware != TUNER_LG) {
+			dvb_usb_lme2510_firmware = TUNER_LG;
 			ret = lme_firmware_switch(adap->dev->udev, 1);
-		} else /*stops LG/Sharp multi tuner problems*/
-			dvb_usb_lme2510_firmware = 0;
+		}
+		goto end;
+	}
+
+	st->i2c_gate = 4;
+	adap->fe = dvb_attach(stv0299_attach, &sharp_z0194_config,
+			&adap->dev->i2c_adap);
+	if (adap->fe) {
+		info("FE Found Stv0299");
+		st->i2c_tuner_gate_w = 4;
+		st->i2c_tuner_gate_r = 5;
+		st->i2c_tuner_addr = 0xc0;
+		st->tuner_config = TUNER_S0194;
+		if (dvb_usb_lme2510_firmware != TUNER_S0194) {
+			dvb_usb_lme2510_firmware = TUNER_S0194;
+			ret = lme_firmware_switch(adap->dev->udev, 1);
+		}
 		goto end;
 	}
 
 	st->i2c_gate = 5;
 	adap->fe = dvb_attach(stv0288_attach, &lme_config,
 			&adap->dev->i2c_adap);
-
 	if (adap->fe) {
 		info("FE Found Stv0288");
 		st->i2c_tuner_gate_w = 4;
 		st->i2c_tuner_gate_r = 5;
 		st->i2c_tuner_addr = 0xc0;
 		st->tuner_config = TUNER_S7395;
-		if (dvb_usb_lme2510_firmware != 0) {
-			dvb_usb_lme2510_firmware = 0;
+		if (dvb_usb_lme2510_firmware != TUNER_S7395) {
+			dvb_usb_lme2510_firmware = TUNER_S7395;
 			ret = lme_firmware_switch(adap->dev->udev, 1);
 		}
 	} else {
@@ -847,6 +957,7 @@
 		return -ENODEV;
 	}
 
+
 end:	if (ret) {
 		kfree(adap->fe);
 		adap->fe = NULL;
@@ -855,14 +966,13 @@
 
 	adap->fe->ops.set_voltage = dm04_lme2510_set_voltage;
 	ret = lme_name(adap);
-
 	return ret;
 }
 
 static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
 {
 	struct lme2510_state *st = adap->dev->priv;
-	char *tun_msg[] = {"", "TDA8263", "IX2505V"};
+	char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA"};
 	int ret = 0;
 
 	switch (st->tuner_config) {
@@ -876,6 +986,11 @@
 			&adap->dev->i2c_adap))
 			ret = st->tuner_config;
 		break;
+	case TUNER_S0194:
+		if (dvb_attach(dvb_pll_attach , adap->fe, 0xc0,
+			&adap->dev->i2c_adap, DVB_PLL_OPERA1))
+			ret = st->tuner_config;
+		break;
 	default:
 		break;
 	}
@@ -888,7 +1003,7 @@
 		return -ENODEV;
 	}
 
-	/* Start the Interupt & Remote*/
+	/* Start the Interrupt & Remote*/
 	ret = lme2510_int_service(adap);
 
 	return ret;
@@ -936,7 +1051,10 @@
 		return -ENODEV;
 	}
 
-	lme_firmware_switch(udev, 0);
+	if (lme2510_return_status(udev) == 0x44) {
+		lme_firmware_switch(udev, 0);
+		return -ENODEV;
+	}
 
 	if (0 == dvb_usb_device_init(intf, &lme2510_properties,
 				     THIS_MODULE, NULL, adapter_nr)) {
@@ -964,10 +1082,6 @@
 
 static struct dvb_usb_device_properties lme2510_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.download_firmware = lme2510_download_firmware,
-	.firmware = "/*(DEBLOBBED)*/",
-
 	.size_of_priv = sizeof(struct lme2510_state),
 	.num_adapters = 1,
 	.adapter = {
@@ -1004,9 +1118,6 @@
 
 static struct dvb_usb_device_properties lme2510c_properties = {
 	.caps = DVB_USB_IS_AN_I2C_ADAPTER,
-	.usb_ctrl = DEVICE_SPECIFIC,
-	.download_firmware = lme2510_download_firmware,
-	.firmware = (const char *)&lme_firmware,
 	.size_of_priv = sizeof(struct lme2510_state),
 	.num_adapters = 1,
 	.adapter = {
@@ -1060,7 +1171,7 @@
 		usb_kill_urb(st->lme_urb);
 		usb_free_coherent(d->udev, 5000, st->buffer,
 				  st->lme_urb->transfer_dma);
-		info("Interupt Service Stopped");
+		info("Interrupt Service Stopped");
 		rc_unregister_device(d->rc_dev);
 		info("Remote Stopped");
 	}
@@ -1109,5 +1220,5 @@
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.75");
+MODULE_VERSION("1.80");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/Makefile linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -91,6 +91,9 @@
 dvb-usb-lmedm04-objs = lmedm04.o
 obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
 
+dvb-usb-technisat-usb2-objs = technisat-usb2.o
+obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
+
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
 # due to tuner-xc3028
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/opera1.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/opera1.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/opera1.c	2012-03-24 01:02:30.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/opera1.c	2012-03-24 03:27:46.000000000 -0400
@@ -342,23 +342,22 @@
 	{0x49b6, KEY_8},
 	{0x05fa, KEY_9},
 	{0x45ba, KEY_0},
-	{0x09f6, KEY_UP},	/*chanup */
-	{0x1be5, KEY_DOWN},	/*chandown */
-	{0x5da3, KEY_LEFT},	/*voldown */
-	{0x5fa1, KEY_RIGHT},	/*volup */
-	{0x07f8, KEY_SPACE},	/*tab */
-	{0x1fe1, KEY_ENTER},	/*play ok */
-	{0x1be4, KEY_Z},	/*zoom */
-	{0x59a6, KEY_M},	/*mute */
-	{0x5ba5, KEY_F},	/*tv/f */
-	{0x19e7, KEY_R},	/*rec */
-	{0x01fe, KEY_S},	/*Stop */
-	{0x03fd, KEY_P},	/*pause */
-	{0x03fc, KEY_W},	/*<- -> */
-	{0x07f9, KEY_C},	/*capture */
-	{0x47b9, KEY_Q},	/*exit */
-	{0x43bc, KEY_O},	/*power */
-
+	{0x09f6, KEY_CHANNELUP},	/*chanup */
+	{0x1be5, KEY_CHANNELDOWN},	/*chandown */
+	{0x5da3, KEY_VOLUMEDOWN},	/*voldown */
+	{0x5fa1, KEY_VOLUMEUP},		/*volup */
+	{0x07f8, KEY_SPACE},		/*tab */
+	{0x1fe1, KEY_OK},		/*play ok */
+	{0x1be4, KEY_ZOOM},		/*zoom */
+	{0x59a6, KEY_MUTE},		/*mute */
+	{0x5ba5, KEY_RADIO},		/*tv/f */
+	{0x19e7, KEY_RECORD},		/*rec */
+	{0x01fe, KEY_STOP},		/*Stop */
+	{0x03fd, KEY_PAUSE},		/*pause */
+	{0x03fc, KEY_SCREEN},		/*<- -> */
+	{0x07f9, KEY_CAMERA},		/*capture */
+	{0x47b9, KEY_ESC},		/*exit */
+	{0x43bc, KEY_POWER2},		/*power */
 };
 
 static int opera1_rc_query(struct dvb_usb_device *dev, u32 * event, int *state)
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/dvb-usb/technisat-usb2.c	2012-03-24 03:27:48.000000000 -0400
@@ -0,0 +1,807 @@
+/*
+ * Linux driver for Technisat DVB-S/S2 USB 2.0 device
+ *
+ * Copyright (C) 2010 Patrick Boettcher,
+ *                    Kernel Labs Inc. PO Box 745, St James, NY 11780
+ *
+ * Development was sponsored by Technisat Digital UK Limited, whose
+ * registered office is Witan Gate House 500 - 600 Witan Gate West,
+ * Milton Keynes, MK9 1SH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND
+ * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE.  NEITHER THE COPYRIGHT HOLDER
+ * NOR TECHNISAT DIGITAL UK LIMITED SHALL 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 PROGRAM. See the
+ * GNU General Public License for more details.
+ */
+
+#define DVB_USB_LOG_PREFIX "technisat-usb2"
+#include "dvb-usb.h"
+
+#include "stv6110x.h"
+#include "stv090x.h"
+
+/* module parameters */
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug,
+		"set debugging level (bit-mask: 1=info,2=eeprom,4=i2c,8=rc)." \
+		DVB_USB_DEBUG_STATUS);
+
+/* disables all LED control command and
+ * also does not start the signal polling thread */
+static int disable_led_control;
+module_param(disable_led_control, int, 0444);
+MODULE_PARM_DESC(disable_led_control,
+		"disable LED control of the device "
+		"(default: 0 - LED control is active).");
+
+/* device private data */
+struct technisat_usb2_state {
+	struct dvb_usb_device *dev;
+	struct delayed_work green_led_work;
+	u8 power_state;
+
+	u16 last_scan_code;
+};
+
+/* debug print helpers */
+#define deb_info(args...)    dprintk(debug, 0x01, args)
+#define deb_eeprom(args...)  dprintk(debug, 0x02, args)
+#define deb_i2c(args...)     dprintk(debug, 0x04, args)
+#define deb_rc(args...)      dprintk(debug, 0x08, args)
+
+/* vendor requests */
+#define SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST 0xB3
+#define SET_FRONT_END_RESET_VENDOR_REQUEST         0xB4
+#define GET_VERSION_INFO_VENDOR_REQUEST            0xB5
+#define SET_GREEN_LED_VENDOR_REQUEST               0xB6
+#define SET_RED_LED_VENDOR_REQUEST                 0xB7
+#define GET_IR_DATA_VENDOR_REQUEST                 0xB8
+#define SET_LED_TIMER_DIVIDER_VENDOR_REQUEST       0xB9
+#define SET_USB_REENUMERATION                      0xBA
+
+/* i2c-access methods */
+#define I2C_SPEED_100KHZ_BIT 0x40
+
+#define I2C_STATUS_NAK 7
+#define I2C_STATUS_OK 8
+
+static int technisat_usb2_i2c_access(struct usb_device *udev,
+		u8 device_addr, u8 *tx, u8 txlen, u8 *rx, u8 rxlen)
+{
+	u8 b[64];
+	int ret, actual_length;
+
+	deb_i2c("i2c-access: %02x, tx: ", device_addr);
+	debug_dump(tx, txlen, deb_i2c);
+	deb_i2c(" ");
+
+	if (txlen > 62) {
+		err("i2c TX buffer can't exceed 62 bytes (dev 0x%02x)",
+				device_addr);
+		txlen = 62;
+	}
+	if (rxlen > 62) {
+		err("i2c RX buffer can't exceed 62 bytes (dev 0x%02x)",
+				device_addr);
+		txlen = 62;
+	}
+
+	b[0] = I2C_SPEED_100KHZ_BIT;
+	b[1] = device_addr << 1;
+
+	if (rx != NULL) {
+		b[0] |= rxlen;
+		b[1] |= 1;
+	}
+
+	memcpy(&b[2], tx, txlen);
+	ret = usb_bulk_msg(udev,
+			usb_sndbulkpipe(udev, 0x01),
+			b, 2 + txlen,
+			NULL, 1000);
+
+	if (ret < 0) {
+		err("i2c-error: out failed %02x = %d", device_addr, ret);
+		return -ENODEV;
+	}
+
+	ret = usb_bulk_msg(udev,
+			usb_rcvbulkpipe(udev, 0x01),
+			b, 64, &actual_length, 1000);
+	if (ret < 0) {
+		err("i2c-error: in failed %02x = %d", device_addr, ret);
+		return -ENODEV;
+	}
+
+	if (b[0] != I2C_STATUS_OK) {
+		err("i2c-error: %02x = %d", device_addr, b[0]);
+		/* handle tuner-i2c-nak */
+		if (!(b[0] == I2C_STATUS_NAK &&
+				device_addr == 0x60
+				/* && device_is_technisat_usb2 */))
+			return -ENODEV;
+	}
+
+	deb_i2c("status: %d, ", b[0]);
+
+	if (rx != NULL) {
+		memcpy(rx, &b[2], rxlen);
+
+		deb_i2c("rx (%d): ", rxlen);
+		debug_dump(rx, rxlen, deb_i2c);
+	}
+
+	deb_i2c("\n");
+
+	return 0;
+}
+
+static int technisat_usb2_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msg,
+				int num)
+{
+	int ret = 0, i;
+	struct dvb_usb_device *d = i2c_get_adapdata(adap);
+
+	/* Ensure nobody else hits the i2c bus while we're sending our
+	   sequence of messages, (such as the remote control thread) */
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	for (i = 0; i < num; i++) {
+		if (i+1 < num && msg[i+1].flags & I2C_M_RD) {
+			ret = technisat_usb2_i2c_access(d->udev, msg[i+1].addr,
+						msg[i].buf, msg[i].len,
+						msg[i+1].buf, msg[i+1].len);
+			if (ret != 0)
+				break;
+			i++;
+		} else {
+			ret = technisat_usb2_i2c_access(d->udev, msg[i].addr,
+						msg[i].buf, msg[i].len,
+						NULL, 0);
+			if (ret != 0)
+				break;
+		}
+	}
+
+	if (ret == 0)
+		ret = i;
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+
+static u32 technisat_usb2_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm technisat_usb2_i2c_algo = {
+	.master_xfer   = technisat_usb2_i2c_xfer,
+	.functionality = technisat_usb2_i2c_func,
+};
+
+#if 0
+static void technisat_usb2_frontend_reset(struct usb_device *udev)
+{
+	usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+			SET_FRONT_END_RESET_VENDOR_REQUEST,
+			USB_TYPE_VENDOR | USB_DIR_OUT,
+			10, 0,
+			NULL, 0, 500);
+}
+#endif
+
+/* LED control */
+enum technisat_usb2_led_state {
+	LED_OFF,
+	LED_BLINK,
+	LED_ON,
+	LED_UNDEFINED
+};
+
+static int technisat_usb2_set_led(struct dvb_usb_device *d, int red, enum technisat_usb2_led_state state)
+{
+	int ret;
+
+	u8 led[8] = {
+		red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
+		0
+	};
+
+	if (disable_led_control && state != LED_OFF)
+		return 0;
+
+	switch (state) {
+	case LED_ON:
+		led[1] = 0x82;
+		break;
+	case LED_BLINK:
+		led[1] = 0x82;
+		if (red) {
+			led[2] = 0x02;
+			led[3] = 10;
+			led[4] = 10;
+		} else {
+			led[2] = 0xff;
+			led[3] = 50;
+			led[4] = 50;
+		}
+		led[5] = 1;
+		break;
+
+	default:
+	case LED_OFF:
+		led[1] = 0x80;
+		break;
+	}
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
+		red ? SET_RED_LED_VENDOR_REQUEST : SET_GREEN_LED_VENDOR_REQUEST,
+		USB_TYPE_VENDOR | USB_DIR_OUT,
+		0, 0,
+		led, sizeof(led), 500);
+
+	mutex_unlock(&d->i2c_mutex);
+	return ret;
+}
+
+static int technisat_usb2_set_led_timer(struct dvb_usb_device *d, u8 red, u8 green)
+{
+	int ret;
+	u8 b = 0;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+
+	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
+		SET_LED_TIMER_DIVIDER_VENDOR_REQUEST,
+		USB_TYPE_VENDOR | USB_DIR_OUT,
+		(red << 8) | green, 0,
+		&b, 1, 500);
+
+	mutex_unlock(&d->i2c_mutex);
+
+	return ret;
+}
+
+static void technisat_usb2_green_led_control(struct work_struct *work)
+{
+	struct technisat_usb2_state *state =
+		container_of(work, struct technisat_usb2_state, green_led_work.work);
+	struct dvb_frontend *fe = state->dev->adapter[0].fe;
+
+	if (state->power_state == 0)
+		goto schedule;
+
+	if (fe != NULL) {
+		enum fe_status status;
+
+		if (fe->ops.read_status(fe, &status) != 0)
+			goto schedule;
+
+		if (status & FE_HAS_LOCK) {
+			u32 ber;
+
+			if (fe->ops.read_ber(fe, &ber) != 0)
+				goto schedule;
+
+			if (ber > 1000)
+				technisat_usb2_set_led(state->dev, 0, LED_BLINK);
+			else
+				technisat_usb2_set_led(state->dev, 0, LED_ON);
+		} else
+			technisat_usb2_set_led(state->dev, 0, LED_OFF);
+	}
+
+schedule:
+	schedule_delayed_work(&state->green_led_work,
+			msecs_to_jiffies(500));
+}
+
+/* method to find out whether the firmware has to be downloaded or not */
+static int technisat_usb2_identify_state(struct usb_device *udev,
+		struct dvb_usb_device_properties *props,
+		struct dvb_usb_device_description **desc, int *cold)
+{
+	int ret;
+	u8 version[3];
+
+	/* first select the interface */
+	if (usb_set_interface(udev, 0, 1) != 0)
+		err("could not set alternate setting to 0");
+	else
+		info("set alternate setting");
+
+	*cold = 0; /* by default do not download a firmware - just in case something is wrong */
+
+	ret = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0),
+		GET_VERSION_INFO_VENDOR_REQUEST,
+		USB_TYPE_VENDOR | USB_DIR_IN,
+		0, 0,
+		version, sizeof(version), 500);
+
+	if (ret < 0)
+		*cold = 1;
+	else {
+		info("firmware version: %d.%d", version[1], version[2]);
+		*cold = 0;
+	}
+
+	return 0;
+}
+
+/* power control */
+static int technisat_usb2_power_ctrl(struct dvb_usb_device *d, int level)
+{
+	struct technisat_usb2_state *state = d->priv;
+
+	state->power_state = level;
+
+	if (disable_led_control)
+		return 0;
+
+	/* green led is turned off in any case - will be turned on when tuning */
+	technisat_usb2_set_led(d, 0, LED_OFF);
+	/* red led is turned on all the time */
+	technisat_usb2_set_led(d, 1, LED_ON);
+	return 0;
+}
+
+/* mac address reading - from the eeprom */
+#if 0
+static void technisat_usb2_eeprom_dump(struct dvb_usb_device *d)
+{
+	u8 reg;
+	u8 b[16];
+	int i, j;
+
+	/* full EEPROM dump */
+	for (j = 0; j < 256 * 4; j += 16) {
+		reg = j;
+		if (technisat_usb2_i2c_access(d->udev, 0x50 + j / 256, &reg, 1, b, 16) != 0)
+			break;
+
+		deb_eeprom("EEPROM: %01x%02x: ", j / 256, reg);
+		for (i = 0; i < 16; i++)
+			deb_eeprom("%02x ", b[i]);
+		deb_eeprom("\n");
+	}
+}
+#endif
+
+static u8 technisat_usb2_calc_lrc(const u8 *b, u16 length)
+{
+	u8 lrc = 0;
+	while (--length)
+		lrc ^= *b++;
+	return lrc;
+}
+
+static int technisat_usb2_eeprom_lrc_read(struct dvb_usb_device *d,
+	u16 offset, u8 *b, u16 length, u8 tries)
+{
+	u8 bo = offset & 0xff;
+	struct i2c_msg msg[] = {
+		{
+			.addr = 0x50 | ((offset >> 8) & 0x3),
+			.buf = &bo,
+			.len = 1
+		}, {
+			.addr = 0x50 | ((offset >> 8) & 0x3),
+			.flags	= I2C_M_RD,
+			.buf = b,
+			.len = length
+		}
+	};
+
+	while (tries--) {
+		int status;
+
+		if (i2c_transfer(&d->i2c_adap, msg, 2) != 2)
+			break;
+
+		status =
+			technisat_usb2_calc_lrc(b, length - 1) == b[length - 1];
+
+		if (status)
+			return 0;
+	}
+
+	return -EREMOTEIO;
+}
+
+#define EEPROM_MAC_START 0x3f8
+#define EEPROM_MAC_TOTAL 8
+static int technisat_usb2_read_mac_address(struct dvb_usb_device *d,
+		u8 mac[])
+{
+	u8 buf[EEPROM_MAC_TOTAL];
+
+	if (technisat_usb2_eeprom_lrc_read(d, EEPROM_MAC_START,
+				buf, EEPROM_MAC_TOTAL, 4) != 0)
+		return -ENODEV;
+
+	memcpy(mac, buf, 6);
+	return 0;
+}
+
+/* frontend attach */
+static int technisat_usb2_set_voltage(struct dvb_frontend *fe,
+		fe_sec_voltage_t voltage)
+{
+	int i;
+	u8 gpio[3] = { 0 }; /* 0 = 2, 1 = 3, 2 = 4 */
+
+	gpio[2] = 1; /* high - voltage ? */
+
+	switch (voltage) {
+	case SEC_VOLTAGE_13:
+		gpio[0] = 1;
+		break;
+	case SEC_VOLTAGE_18:
+		gpio[0] = 1;
+		gpio[1] = 1;
+		break;
+	default:
+	case SEC_VOLTAGE_OFF:
+		break;
+	}
+
+	for (i = 0; i < 3; i++)
+		if (stv090x_set_gpio(fe, i+2, 0, gpio[i], 0) != 0)
+			return -EREMOTEIO;
+	return 0;
+}
+
+static struct stv090x_config technisat_usb2_stv090x_config = {
+	.device         = STV0903,
+	.demod_mode     = STV090x_SINGLE,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 8000000,
+	.address        = 0x68,
+
+	.ts1_mode       = STV090x_TSMODE_DVBCI,
+	.ts1_clk        = 13400000,
+	.ts1_tei        = 1,
+
+	.repeater_level = STV090x_RPTLEVEL_64,
+
+	.tuner_bbgain   = 6,
+};
+
+static struct stv6110x_config technisat_usb2_stv6110x_config = {
+	.addr           = 0x60,
+	.refclk         = 16000000,
+	.clk_div        = 2,
+};
+
+static int technisat_usb2_frontend_attach(struct dvb_usb_adapter *a)
+{
+	struct usb_device *udev = a->dev->udev;
+	int ret;
+
+	a->fe = dvb_attach(stv090x_attach, &technisat_usb2_stv090x_config,
+			&a->dev->i2c_adap, STV090x_DEMODULATOR_0);
+
+	if (a->fe) {
+		struct stv6110x_devctl *ctl;
+
+		ctl = dvb_attach(stv6110x_attach,
+				a->fe,
+				&technisat_usb2_stv6110x_config,
+				&a->dev->i2c_adap);
+
+		if (ctl) {
+			technisat_usb2_stv090x_config.tuner_init          = ctl->tuner_init;
+			technisat_usb2_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
+			technisat_usb2_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
+			technisat_usb2_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
+			technisat_usb2_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
+			technisat_usb2_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+			technisat_usb2_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+			technisat_usb2_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
+			technisat_usb2_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
+			technisat_usb2_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
+			technisat_usb2_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
+
+			/* call the init function once to initialize
+			   tuner's clock output divider and demod's
+			   master clock */
+			if (a->fe->ops.init)
+				a->fe->ops.init(a->fe);
+
+			if (mutex_lock_interruptible(&a->dev->i2c_mutex) < 0)
+				return -EAGAIN;
+
+			ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+					SET_IFCLK_TO_EXTERNAL_TSCLK_VENDOR_REQUEST,
+					USB_TYPE_VENDOR | USB_DIR_OUT,
+					0, 0,
+					NULL, 0, 500);
+			mutex_unlock(&a->dev->i2c_mutex);
+
+			if (ret != 0)
+				err("could not set IF_CLK to external");
+
+			a->fe->ops.set_voltage = technisat_usb2_set_voltage;
+
+			/* if everything was successful assign a nice name to the frontend */
+			strlcpy(a->fe->ops.info.name, a->dev->desc->name,
+					sizeof(a->fe->ops.info.name));
+		} else {
+			dvb_frontend_detach(a->fe);
+			a->fe = NULL;
+		}
+	}
+
+	technisat_usb2_set_led_timer(a->dev, 1, 1);
+
+	return a->fe == NULL ? -ENODEV : 0;
+}
+
+/* Remote control */
+
+/* the device is giving providing raw IR-signals to the host mapping
+ * it only to one remote control is just the default implementation
+ */
+#define NOMINAL_IR_BIT_TRANSITION_TIME_US 889
+#define NOMINAL_IR_BIT_TIME_US (2 * NOMINAL_IR_BIT_TRANSITION_TIME_US)
+
+#define FIRMWARE_CLOCK_TICK 83333
+#define FIRMWARE_CLOCK_DIVISOR 256
+
+#define IR_PERCENT_TOLERANCE 15
+
+#define NOMINAL_IR_BIT_TRANSITION_TICKS ((NOMINAL_IR_BIT_TRANSITION_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
+#define NOMINAL_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICKS / FIRMWARE_CLOCK_DIVISOR)
+
+#define NOMINAL_IR_BIT_TIME_TICKS ((NOMINAL_IR_BIT_TIME_US * 1000 * 1000) / FIRMWARE_CLOCK_TICK)
+#define NOMINAL_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICKS / FIRMWARE_CLOCK_DIVISOR)
+
+#define MINIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT - ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
+#define MAXIMUM_IR_BIT_TRANSITION_TICK_COUNT (NOMINAL_IR_BIT_TRANSITION_TICK_COUNT + ((NOMINAL_IR_BIT_TRANSITION_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
+
+#define MINIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT - ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
+#define MAXIMUM_IR_BIT_TIME_TICK_COUNT (NOMINAL_IR_BIT_TIME_TICK_COUNT + ((NOMINAL_IR_BIT_TIME_TICK_COUNT * IR_PERCENT_TOLERANCE) / 100))
+
+static int technisat_usb2_get_ir(struct dvb_usb_device *d)
+{
+	u8 buf[62], *b;
+	int ret;
+	struct ir_raw_event ev;
+
+	buf[0] = GET_IR_DATA_VENDOR_REQUEST;
+	buf[1] = 0x08;
+	buf[2] = 0x8f;
+	buf[3] = MINIMUM_IR_BIT_TRANSITION_TICK_COUNT;
+	buf[4] = MAXIMUM_IR_BIT_TIME_TICK_COUNT;
+
+	if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+		return -EAGAIN;
+	ret = usb_control_msg(d->udev, usb_sndctrlpipe(d->udev, 0),
+			GET_IR_DATA_VENDOR_REQUEST,
+			USB_TYPE_VENDOR | USB_DIR_OUT,
+			0, 0,
+			buf, 5, 500);
+	if (ret < 0)
+		goto unlock;
+
+	buf[1] = 0;
+	buf[2] = 0;
+	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+			GET_IR_DATA_VENDOR_REQUEST,
+			USB_TYPE_VENDOR | USB_DIR_IN,
+			0x8080, 0,
+			buf, sizeof(buf), 500);
+
+unlock:
+	mutex_unlock(&d->i2c_mutex);
+
+	if (ret < 0)
+		return ret;
+
+	if (ret == 1)
+		return 0; /* no key pressed */
+
+	/* decoding */
+	b = buf+1;
+
+#if 0
+	deb_rc("RC: %d ", ret);
+	debug_dump(b, ret, deb_rc);
+#endif
+
+	ev.pulse = 0;
+	while (1) {
+		ev.pulse = !ev.pulse;
+		ev.duration = (*b * FIRMWARE_CLOCK_DIVISOR * FIRMWARE_CLOCK_TICK) / 1000;
+		ir_raw_event_store(d->rc_dev, &ev);
+
+		b++;
+		if (*b == 0xff) {
+			ev.pulse = 0;
+			ev.duration = 888888*2;
+			ir_raw_event_store(d->rc_dev, &ev);
+			break;
+		}
+	}
+
+	ir_raw_event_handle(d->rc_dev);
+
+	return 1;
+}
+
+static int technisat_usb2_rc_query(struct dvb_usb_device *d)
+{
+	int ret = technisat_usb2_get_ir(d);
+
+	if (ret < 0)
+		return ret;
+
+	if (ret == 0)
+		return 0;
+
+	if (!disable_led_control)
+		technisat_usb2_set_led(d, 1, LED_BLINK);
+
+	return 0;
+}
+
+/* DVB-USB and USB stuff follows */
+static struct usb_device_id technisat_usb2_id_table[] = {
+	{ USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
+	{ 0 }		/* Terminating entry */
+};
+
+/* device description */
+static struct dvb_usb_device_properties technisat_usb2_devices = {
+	.caps              = DVB_USB_IS_AN_I2C_ADAPTER,
+
+	.usb_ctrl          = CYPRESS_FX2,
+
+	.identify_state    = technisat_usb2_identify_state,
+	.firmware          = "/*(DEBLOBBED)*/",
+
+	.size_of_priv      = sizeof(struct technisat_usb2_state),
+
+	.i2c_algo          = &technisat_usb2_i2c_algo,
+
+	.power_ctrl        = technisat_usb2_power_ctrl,
+	.read_mac_address  = technisat_usb2_read_mac_address,
+
+	.num_adapters = 1,
+	.adapter = {
+		{
+			.frontend_attach  = technisat_usb2_frontend_attach,
+
+			.stream = {
+				.type = USB_ISOC,
+				.count = 8,
+				.endpoint = 0x2,
+				.u = {
+					.isoc = {
+						.framesperurb = 32,
+						.framesize = 2048,
+						.interval = 3,
+					}
+				}
+			},
+
+			.size_of_priv = 0,
+		},
+	},
+
+	.num_device_descs = 1,
+	.devices = {
+		{   "Technisat SkyStar USB HD (DVB-S/S2)",
+			{ &technisat_usb2_id_table[0], NULL },
+			{ NULL },
+		},
+	},
+
+	.rc.core = {
+		.rc_interval = 100,
+		.rc_codes    = RC_MAP_TECHNISAT_USB2,
+		.module_name = "technisat-usb2",
+		.rc_query    = technisat_usb2_rc_query,
+		.allowed_protos = RC_TYPE_ALL,
+		.driver_type    = RC_DRIVER_IR_RAW,
+	}
+};
+
+static int technisat_usb2_probe(struct usb_interface *intf,
+		const struct usb_device_id *id)
+{
+	struct dvb_usb_device *dev;
+
+	if (dvb_usb_device_init(intf, &technisat_usb2_devices, THIS_MODULE,
+				&dev, adapter_nr) != 0)
+		return -ENODEV;
+
+	if (dev) {
+		struct technisat_usb2_state *state = dev->priv;
+		state->dev = dev;
+
+		if (!disable_led_control) {
+			INIT_DELAYED_WORK(&state->green_led_work,
+					technisat_usb2_green_led_control);
+			schedule_delayed_work(&state->green_led_work,
+					msecs_to_jiffies(500));
+		}
+	}
+
+	return 0;
+}
+
+static void technisat_usb2_disconnect(struct usb_interface *intf)
+{
+	struct dvb_usb_device *dev = usb_get_intfdata(intf);
+
+	/* work and stuff was only created when the device is is hot-state */
+	if (dev != NULL) {
+		struct technisat_usb2_state *state = dev->priv;
+		if (state != NULL) {
+			cancel_delayed_work_sync(&state->green_led_work);
+			flush_scheduled_work();
+		}
+	}
+
+	dvb_usb_device_exit(intf);
+}
+
+static struct usb_driver technisat_usb2_driver = {
+	.name       = "dvb_usb_technisat_usb2",
+	.probe      = technisat_usb2_probe,
+	.disconnect = technisat_usb2_disconnect,
+	.id_table   = technisat_usb2_id_table,
+};
+
+/* module stuff */
+static int __init technisat_usb2_module_init(void)
+{
+	int result = usb_register(&technisat_usb2_driver);
+	if (result) {
+		err("usb_register failed. Code %d", result);
+		return result;
+	}
+
+	return 0;
+}
+
+static void __exit technisat_usb2_module_exit(void)
+{
+	usb_deregister(&technisat_usb2_driver);
+}
+
+module_init(technisat_usb2_module_init);
+module_exit(technisat_usb2_module_exit);
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>");
+MODULE_DESCRIPTION("Driver for Technisat DVB-S/S2 USB 2.0 device");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-1394.c linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-1394.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-1394.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-1394.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,300 +0,0 @@
-/*
- * FireDTV driver -- ieee1394 I/O backend
- *
- * Copyright (C) 2004 Andreas Monitzer <andy@monitzer.com>
- * Copyright (C) 2007-2008 Ben Backx <ben@bbackx.com>
- * Copyright (C) 2008 Henrik Kurelid <henrik@kurelid.se>
- *
- *	This program is free software; you can redistribute it and/or
- *	modify it under the terms of the 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/errno.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/slab.h>
-#include <linux/spinlock.h>
-#include <linux/types.h>
-
-#include <dma.h>
-#include <csr1212.h>
-#include <highlevel.h>
-#include <hosts.h>
-#include <ieee1394.h>
-#include <iso.h>
-#include <nodemgr.h>
-
-#include <dvb_demux.h>
-
-#include "firedtv.h"
-
-static LIST_HEAD(node_list);
-static DEFINE_SPINLOCK(node_list_lock);
-
-#define CIP_HEADER_SIZE			8
-#define MPEG2_TS_HEADER_SIZE		4
-#define MPEG2_TS_SOURCE_PACKET_SIZE	(4 + 188)
-
-static void rawiso_activity_cb(struct hpsb_iso *iso)
-{
-	struct firedtv *f, *fdtv = NULL;
-	unsigned int i, num, packet;
-	unsigned char *buf;
-	unsigned long flags;
-	int count;
-
-	spin_lock_irqsave(&node_list_lock, flags);
-	list_for_each_entry(f, &node_list, list)
-		if (f->backend_data == iso) {
-			fdtv = f;
-			break;
-		}
-	spin_unlock_irqrestore(&node_list_lock, flags);
-
-	packet = iso->first_packet;
-	num = hpsb_iso_n_ready(iso);
-
-	if (!fdtv) {
-		pr_err("received at unknown iso channel\n");
-		goto out;
-	}
-
-	for (i = 0; i < num; i++, packet = (packet + 1) % iso->buf_packets) {
-		buf = dma_region_i(&iso->data_buf, unsigned char,
-			iso->infos[packet].offset + CIP_HEADER_SIZE);
-		count = (iso->infos[packet].len - CIP_HEADER_SIZE) /
-			MPEG2_TS_SOURCE_PACKET_SIZE;
-
-		/* ignore empty packet */
-		if (iso->infos[packet].len <= CIP_HEADER_SIZE)
-			continue;
-
-		while (count--) {
-			if (buf[MPEG2_TS_HEADER_SIZE] == 0x47)
-				dvb_dmx_swfilter_packets(&fdtv->demux,
-						&buf[MPEG2_TS_HEADER_SIZE], 1);
-			else
-				dev_err(fdtv->device,
-					"skipping invalid packet\n");
-			buf += MPEG2_TS_SOURCE_PACKET_SIZE;
-		}
-	}
-out:
-	hpsb_iso_recv_release_packets(iso, num);
-}
-
-static inline struct node_entry *node_of(struct firedtv *fdtv)
-{
-	return container_of(fdtv->device, struct unit_directory, device)->ne;
-}
-
-static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
-{
-	quadlet_t *d = data;
-	int ret;
-
-	ret = hpsb_node_lock(node_of(fdtv), addr,
-			     EXTCODE_COMPARE_SWAP, &d[1], d[0]);
-	d[0] = d[1];
-
-	return ret;
-}
-
-static int node_read(struct firedtv *fdtv, u64 addr, void *data)
-{
-	return hpsb_node_read(node_of(fdtv), addr, data, 4);
-}
-
-static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
-{
-	return hpsb_node_write(node_of(fdtv), addr, data, len);
-}
-
-#define FDTV_ISO_BUFFER_PACKETS 256
-#define FDTV_ISO_BUFFER_SIZE (FDTV_ISO_BUFFER_PACKETS * 200)
-
-static int start_iso(struct firedtv *fdtv)
-{
-	struct hpsb_iso *iso_handle;
-	int ret;
-
-	iso_handle = hpsb_iso_recv_init(node_of(fdtv)->host,
-				FDTV_ISO_BUFFER_SIZE, FDTV_ISO_BUFFER_PACKETS,
-				fdtv->isochannel, HPSB_ISO_DMA_DEFAULT,
-				-1, /* stat.config.irq_interval */
-				rawiso_activity_cb);
-	if (iso_handle == NULL) {
-		dev_err(fdtv->device, "cannot initialize iso receive\n");
-		return -ENOMEM;
-	}
-	fdtv->backend_data = iso_handle;
-
-	ret = hpsb_iso_recv_start(iso_handle, -1, -1, 0);
-	if (ret != 0) {
-		dev_err(fdtv->device, "cannot start iso receive\n");
-		hpsb_iso_shutdown(iso_handle);
-		fdtv->backend_data = NULL;
-	}
-	return ret;
-}
-
-static void stop_iso(struct firedtv *fdtv)
-{
-	struct hpsb_iso *iso_handle = fdtv->backend_data;
-
-	if (iso_handle != NULL) {
-		hpsb_iso_stop(iso_handle);
-		hpsb_iso_shutdown(iso_handle);
-	}
-	fdtv->backend_data = NULL;
-}
-
-static const struct firedtv_backend fdtv_1394_backend = {
-	.lock		= node_lock,
-	.read		= node_read,
-	.write		= node_write,
-	.start_iso	= start_iso,
-	.stop_iso	= stop_iso,
-};
-
-static void fcp_request(struct hpsb_host *host, int nodeid, int direction,
-			int cts, u8 *data, size_t length)
-{
-	struct firedtv *f, *fdtv = NULL;
-	unsigned long flags;
-	int su;
-
-	if (length == 0 || (data[0] & 0xf0) != 0)
-		return;
-
-	su = data[1] & 0x7;
-
-	spin_lock_irqsave(&node_list_lock, flags);
-	list_for_each_entry(f, &node_list, list)
-		if (node_of(f)->host == host &&
-		    node_of(f)->nodeid == nodeid &&
-		    (f->subunit == su || (f->subunit == 0 && su == 0x7))) {
-			fdtv = f;
-			break;
-		}
-	spin_unlock_irqrestore(&node_list_lock, flags);
-
-	if (fdtv)
-		avc_recv(fdtv, data, length);
-}
-
-static int node_probe(struct device *dev)
-{
-	struct unit_directory *ud =
-			container_of(dev, struct unit_directory, device);
-	struct firedtv *fdtv;
-	int kv_len, err;
-	void *kv_str;
-
-	if (ud->model_name_kv) {
-		kv_len = (ud->model_name_kv->value.leaf.len - 2) * 4;
-		kv_str = CSR1212_TEXTUAL_DESCRIPTOR_LEAF_DATA(ud->model_name_kv);
-	} else {
-		kv_len = 0;
-		kv_str = NULL;
-	}
-	fdtv = fdtv_alloc(dev, &fdtv_1394_backend, kv_str, kv_len);
-	if (!fdtv)
-		return -ENOMEM;
-
-	/*
-	 * Work around a bug in udev's path_id script:  Use the fw-host's dev
-	 * instead of the unit directory's dev as parent of the input device.
-	 */
-	err = fdtv_register_rc(fdtv, dev->parent->parent);
-	if (err)
-		goto fail_free;
-
-	spin_lock_irq(&node_list_lock);
-	list_add_tail(&fdtv->list, &node_list);
-	spin_unlock_irq(&node_list_lock);
-
-	err = avc_identify_subunit(fdtv);
-	if (err)
-		goto fail;
-
-	err = fdtv_dvb_register(fdtv);
-	if (err)
-		goto fail;
-
-	avc_register_remote_control(fdtv);
-
-	return 0;
-fail:
-	spin_lock_irq(&node_list_lock);
-	list_del(&fdtv->list);
-	spin_unlock_irq(&node_list_lock);
-	fdtv_unregister_rc(fdtv);
-fail_free:
-	kfree(fdtv);
-
-	return err;
-}
-
-static int node_remove(struct device *dev)
-{
-	struct firedtv *fdtv = dev_get_drvdata(dev);
-
-	fdtv_dvb_unregister(fdtv);
-
-	spin_lock_irq(&node_list_lock);
-	list_del(&fdtv->list);
-	spin_unlock_irq(&node_list_lock);
-
-	fdtv_unregister_rc(fdtv);
-	kfree(fdtv);
-
-	return 0;
-}
-
-static int node_update(struct unit_directory *ud)
-{
-	struct firedtv *fdtv = dev_get_drvdata(&ud->device);
-
-	if (fdtv->isochannel >= 0)
-		cmp_establish_pp_connection(fdtv, fdtv->subunit,
-					    fdtv->isochannel);
-	return 0;
-}
-
-static struct hpsb_protocol_driver fdtv_driver = {
-	.name		= "firedtv",
-	.id_table	= fdtv_id_table,
-	.update		= node_update,
-	.driver         = {
-		.probe  = node_probe,
-		.remove = node_remove,
-	},
-};
-
-static struct hpsb_highlevel fdtv_highlevel = {
-	.name		= "firedtv",
-	.fcp_request	= fcp_request,
-};
-
-int __init fdtv_1394_init(void)
-{
-	int ret;
-
-	hpsb_register_highlevel(&fdtv_highlevel);
-	ret = hpsb_register_protocol(&fdtv_driver);
-	if (ret) {
-		printk(KERN_ERR "firedtv: failed to register protocol\n");
-		hpsb_unregister_highlevel(&fdtv_highlevel);
-	}
-	return ret;
-}
-
-void __exit fdtv_1394_exit(void)
-{
-	hpsb_unregister_protocol(&fdtv_driver);
-	hpsb_unregister_highlevel(&fdtv_highlevel);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-avc.c linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-avc.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-avc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-avc.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,8 +241,8 @@
 		if (unlikely(avc_debug))
 			debug_fcp(fdtv->avc_data, fdtv->avc_data_length);
 
-		err = fdtv->backend->write(fdtv, FCP_COMMAND_REGISTER,
-				fdtv->avc_data, fdtv->avc_data_length);
+		err = fdtv_write(fdtv, FCP_COMMAND_REGISTER,
+				 fdtv->avc_data, fdtv->avc_data_length);
 		if (err) {
 			dev_err(fdtv->device, "FCP command write failed\n");
 
@@ -1322,7 +1322,7 @@
 
 	mutex_lock(&fdtv->avc_mutex);
 
-	ret = fdtv->backend->read(fdtv, addr, data);
+	ret = fdtv_read(fdtv, addr, data);
 	if (ret < 0)
 		dev_err(fdtv->device, "CMP: read I/O error\n");
 
@@ -1340,7 +1340,7 @@
 	/* data[] is stack-allocated and should not be DMA-mapped. */
 	memcpy(fdtv->avc_data, data, 8);
 
-	ret = fdtv->backend->lock(fdtv, addr, fdtv->avc_data);
+	ret = fdtv_lock(fdtv, addr, fdtv->avc_data);
 	if (ret < 0)
 		dev_err(fdtv->device, "CMP: lock I/O error\n");
 	else
@@ -1405,10 +1405,7 @@
 		/* FIXME: this is for the worst case - optimize */
 		set_opcr_overhead_id(opcr, 0);
 
-		/*
-		 * FIXME: allocate isochronous channel and bandwidth at IRM
-		 * fdtv->backend->alloc_resources(fdtv, channels_mask, bw);
-		 */
+		/* FIXME: allocate isochronous channel and bandwidth at IRM */
 	}
 
 	set_opcr_p2p_connections(opcr, get_opcr_p2p_connections(*opcr) + 1);
@@ -1424,8 +1421,6 @@
 		/*
 		 * FIXME: if old_opcr.P2P_Connections > 0,
 		 * deallocate isochronous channel and bandwidth at IRM
-		 * if (...)
-		 *	fdtv->backend->dealloc_resources(fdtv, channel, bw);
 		 */
 
 		if (++attempts < 6) /* arbitrary limit */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-dvb.c linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-dvb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-dvb.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,14 +14,9 @@
 #include <linux/device.h>
 #include <linux/errno.h>
 #include <linux/kernel.h>
-#include <linux/mod_devicetable.h>
 #include <linux/module.h>
 #include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/string.h>
 #include <linux/types.h>
-#include <linux/wait.h>
-#include <linux/workqueue.h>
 
 #include <dmxdev.h>
 #include <dvb_demux.h>
@@ -166,11 +161,11 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-int fdtv_dvb_register(struct firedtv *fdtv)
+int fdtv_dvb_register(struct firedtv *fdtv, const char *name)
 {
 	int err;
 
-	err = dvb_register_adapter(&fdtv->adapter, fdtv_model_names[fdtv->type],
+	err = dvb_register_adapter(&fdtv->adapter, name,
 				   THIS_MODULE, fdtv->device, adapter_nr);
 	if (err < 0)
 		goto fail_log;
@@ -210,7 +205,7 @@
 
 	dvb_net_init(&fdtv->adapter, &fdtv->dvbnet, &fdtv->demux.dmx);
 
-	fdtv_frontend_init(fdtv);
+	fdtv_frontend_init(fdtv, name);
 	err = dvb_register_frontend(&fdtv->adapter, &fdtv->fe);
 	if (err)
 		goto fail_net_release;
@@ -248,127 +243,3 @@
 	dvb_dmx_release(&fdtv->demux);
 	dvb_unregister_adapter(&fdtv->adapter);
 }
-
-const char *fdtv_model_names[] = {
-	[FIREDTV_UNKNOWN] = "unknown type",
-	[FIREDTV_DVB_S]   = "FireDTV S/CI",
-	[FIREDTV_DVB_C]   = "FireDTV C/CI",
-	[FIREDTV_DVB_T]   = "FireDTV T/CI",
-	[FIREDTV_DVB_S2]  = "FireDTV S2  ",
-};
-
-struct firedtv *fdtv_alloc(struct device *dev,
-			   const struct firedtv_backend *backend,
-			   const char *name, size_t name_len)
-{
-	struct firedtv *fdtv;
-	int i;
-
-	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
-	if (!fdtv)
-		return NULL;
-
-	dev_set_drvdata(dev, fdtv);
-	fdtv->device		= dev;
-	fdtv->isochannel	= -1;
-	fdtv->voltage		= 0xff;
-	fdtv->tone		= 0xff;
-	fdtv->backend		= backend;
-
-	mutex_init(&fdtv->avc_mutex);
-	init_waitqueue_head(&fdtv->avc_wait);
-	mutex_init(&fdtv->demux_mutex);
-	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
-
-	for (i = ARRAY_SIZE(fdtv_model_names); --i; )
-		if (strlen(fdtv_model_names[i]) <= name_len &&
-		    strncmp(name, fdtv_model_names[i], name_len) == 0)
-			break;
-	fdtv->type = i;
-
-	return fdtv;
-}
-
-#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
-		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
-
-#define DIGITAL_EVERYWHERE_OUI	0x001287
-#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
-#define AVC_SW_VERSION_ENTRY	0x010001
-
-const struct ieee1394_device_id fdtv_id_table[] = {
-	{
-		/* FloppyDTV S/CI and FloppyDTV S2 */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000024,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FloppyDTV T/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000025,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FloppyDTV C/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000026,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FireDTV S/CI and FloppyDTV S2 */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000034,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FireDTV T/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000035,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {
-		/* FireDTV C/CI */
-		.match_flags	= MATCH_FLAGS,
-		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
-		.model_id	= 0x000036,
-		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
-		.version	= AVC_SW_VERSION_ENTRY,
-	}, {}
-};
-MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
-
-static int __init fdtv_init(void)
-{
-	int ret;
-
-	ret = fdtv_fw_init();
-	if (ret < 0)
-		return ret;
-
-	ret = fdtv_1394_init();
-	if (ret < 0)
-		fdtv_fw_exit();
-
-	return ret;
-}
-
-static void __exit fdtv_exit(void)
-{
-	fdtv_1394_exit();
-	fdtv_fw_exit();
-}
-
-module_init(fdtv_init);
-module_exit(fdtv_exit);
-
-MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
-MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
-MODULE_DESCRIPTION("FireDTV DVB Driver");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-fe.c linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-fe.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-fe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-fe.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,14 +36,14 @@
 		return err;
 	}
 
-	return fdtv->backend->start_iso(fdtv);
+	return fdtv_start_iso(fdtv);
 }
 
 static int fdtv_sleep(struct dvb_frontend *fe)
 {
 	struct firedtv *fdtv = fe->sec_priv;
 
-	fdtv->backend->stop_iso(fdtv);
+	fdtv_stop_iso(fdtv);
 	cmp_break_pp_connection(fdtv, fdtv->subunit, fdtv->isochannel);
 	fdtv->isochannel = -1;
 	return 0;
@@ -165,7 +165,7 @@
 	return 0;
 }
 
-void fdtv_frontend_init(struct firedtv *fdtv)
+void fdtv_frontend_init(struct firedtv *fdtv, const char *name)
 {
 	struct dvb_frontend_ops *ops = &fdtv->fe.ops;
 	struct dvb_frontend_info *fi = &ops->info;
@@ -266,7 +266,7 @@
 		dev_err(fdtv->device, "no frontend for model type %d\n",
 			fdtv->type);
 	}
-	strcpy(fi->name, fdtv_model_names[fdtv->type]);
+	strcpy(fi->name, name);
 
 	fdtv->fe.dvb = &fdtv->adapter;
 	fdtv->fe.sec_priv = fdtv;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-fw.c linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-fw.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv-fw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv-fw.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,11 +9,18 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <linux/mm.h>
+#include <linux/mod_devicetable.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/slab.h>
 #include <linux/spinlock.h>
+#include <linux/string.h>
 #include <linux/types.h>
+#include <linux/wait.h>
+#include <linux/workqueue.h>
 
 #include <asm/page.h>
+#include <asm/system.h>
 
 #include <dvb_demux.h>
 
@@ -41,17 +48,17 @@
 	return rcode != RCODE_COMPLETE ? -EIO : 0;
 }
 
-static int node_lock(struct firedtv *fdtv, u64 addr, void *data)
+int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data)
 {
 	return node_req(fdtv, addr, data, 8, TCODE_LOCK_COMPARE_SWAP);
 }
 
-static int node_read(struct firedtv *fdtv, u64 addr, void *data)
+int fdtv_read(struct firedtv *fdtv, u64 addr, void *data)
 {
 	return node_req(fdtv, addr, data, 4, TCODE_READ_QUADLET_REQUEST);
 }
 
-static int node_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
+int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len)
 {
 	return node_req(fdtv, addr, data, len, TCODE_WRITE_BLOCK_REQUEST);
 }
@@ -67,7 +74,7 @@
 #define N_PAGES			DIV_ROUND_UP(N_PACKETS, PACKETS_PER_PAGE)
 #define IRQ_INTERVAL		16
 
-struct firedtv_receive_context {
+struct fdtv_ir_context {
 	struct fw_iso_context *context;
 	struct fw_iso_buffer buffer;
 	int interrupt_packet;
@@ -75,7 +82,7 @@
 	char *pages[N_PAGES];
 };
 
-static int queue_iso(struct firedtv_receive_context *ctx, int index)
+static int queue_iso(struct fdtv_ir_context *ctx, int index)
 {
 	struct fw_iso_packet p;
 
@@ -92,7 +99,7 @@
 		       size_t header_length, void *header, void *data)
 {
 	struct firedtv *fdtv = data;
-	struct firedtv_receive_context *ctx = fdtv->backend_data;
+	struct fdtv_ir_context *ctx = fdtv->ir_context;
 	__be32 *h, *h_end;
 	int length, err, i = ctx->current_packet;
 	char *p, *p_end;
@@ -121,9 +128,9 @@
 	ctx->current_packet = i;
 }
 
-static int start_iso(struct firedtv *fdtv)
+int fdtv_start_iso(struct firedtv *fdtv)
 {
-	struct firedtv_receive_context *ctx;
+	struct fdtv_ir_context *ctx;
 	struct fw_device *device = device_of(fdtv);
 	int i, err;
 
@@ -161,7 +168,7 @@
 	if (err)
 		goto fail;
 
-	fdtv->backend_data = ctx;
+	fdtv->ir_context = ctx;
 
 	return 0;
 fail:
@@ -174,9 +181,9 @@
 	return err;
 }
 
-static void stop_iso(struct firedtv *fdtv)
+void fdtv_stop_iso(struct firedtv *fdtv)
 {
-	struct firedtv_receive_context *ctx = fdtv->backend_data;
+	struct fdtv_ir_context *ctx = fdtv->ir_context;
 
 	fw_iso_context_stop(ctx->context);
 	fw_iso_buffer_destroy(&ctx->buffer, device_of(fdtv)->card);
@@ -184,14 +191,6 @@
 	kfree(ctx);
 }
 
-static const struct firedtv_backend backend = {
-	.lock		= node_lock,
-	.read		= node_read,
-	.write		= node_write,
-	.start_iso	= start_iso,
-	.stop_iso	= stop_iso,
-};
-
 static void handle_fcp(struct fw_card *card, struct fw_request *request,
 		       int tcode, int destination, int source, int generation,
 		       unsigned long long offset, void *payload, size_t length,
@@ -238,6 +237,14 @@
 	.end	= CSR_REGISTER_BASE + CSR_FCP_END,
 };
 
+static const char * const model_names[] = {
+	[FIREDTV_UNKNOWN] = "unknown type",
+	[FIREDTV_DVB_S]   = "FireDTV S/CI",
+	[FIREDTV_DVB_C]   = "FireDTV C/CI",
+	[FIREDTV_DVB_T]   = "FireDTV T/CI",
+	[FIREDTV_DVB_S2]  = "FireDTV S2  ",
+};
+
 /* Adjust the template string if models with longer names appear. */
 #define MAX_MODEL_NAME_LEN sizeof("FireDTV ????")
 
@@ -245,15 +252,31 @@
 {
 	struct firedtv *fdtv;
 	char name[MAX_MODEL_NAME_LEN];
-	int name_len, err;
-
-	name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
-				 name, sizeof(name));
+	int name_len, i, err;
 
-	fdtv = fdtv_alloc(dev, &backend, name, name_len >= 0 ? name_len : 0);
+	fdtv = kzalloc(sizeof(*fdtv), GFP_KERNEL);
 	if (!fdtv)
 		return -ENOMEM;
 
+	dev_set_drvdata(dev, fdtv);
+	fdtv->device		= dev;
+	fdtv->isochannel	= -1;
+	fdtv->voltage		= 0xff;
+	fdtv->tone		= 0xff;
+
+	mutex_init(&fdtv->avc_mutex);
+	init_waitqueue_head(&fdtv->avc_wait);
+	mutex_init(&fdtv->demux_mutex);
+	INIT_WORK(&fdtv->remote_ctrl_work, avc_remote_ctrl_work);
+
+	name_len = fw_csr_string(fw_unit(dev)->directory, CSR_MODEL,
+				 name, sizeof(name));
+	for (i = ARRAY_SIZE(model_names); --i; )
+		if (strlen(model_names[i]) <= name_len &&
+		    strncmp(name, model_names[i], name_len) == 0)
+			break;
+	fdtv->type = i;
+
 	err = fdtv_register_rc(fdtv, dev);
 	if (err)
 		goto fail_free;
@@ -266,7 +289,7 @@
 	if (err)
 		goto fail;
 
-	err = fdtv_dvb_register(fdtv);
+	err = fdtv_dvb_register(fdtv, model_names[fdtv->type]);
 	if (err)
 		goto fail;
 
@@ -309,6 +332,60 @@
 					    fdtv->isochannel);
 }
 
+#define MATCH_FLAGS (IEEE1394_MATCH_VENDOR_ID | IEEE1394_MATCH_MODEL_ID | \
+		     IEEE1394_MATCH_SPECIFIER_ID | IEEE1394_MATCH_VERSION)
+
+#define DIGITAL_EVERYWHERE_OUI	0x001287
+#define AVC_UNIT_SPEC_ID_ENTRY	0x00a02d
+#define AVC_SW_VERSION_ENTRY	0x010001
+
+static const struct ieee1394_device_id fdtv_id_table[] = {
+	{
+		/* FloppyDTV S/CI and FloppyDTV S2 */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000024,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FloppyDTV T/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000025,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FloppyDTV C/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000026,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV S/CI and FloppyDTV S2 */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000034,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV T/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000035,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {
+		/* FireDTV C/CI */
+		.match_flags	= MATCH_FLAGS,
+		.vendor_id	= DIGITAL_EVERYWHERE_OUI,
+		.model_id	= 0x000036,
+		.specifier_id	= AVC_UNIT_SPEC_ID_ENTRY,
+		.version	= AVC_SW_VERSION_ENTRY,
+	}, {}
+};
+MODULE_DEVICE_TABLE(ieee1394, fdtv_id_table);
+
 static struct fw_driver fdtv_driver = {
 	.driver   = {
 		.owner  = THIS_MODULE,
@@ -321,7 +398,7 @@
 	.id_table = fdtv_id_table,
 };
 
-int __init fdtv_fw_init(void)
+static int __init fdtv_init(void)
 {
 	int ret;
 
@@ -329,11 +406,24 @@
 	if (ret < 0)
 		return ret;
 
-	return driver_register(&fdtv_driver.driver);
+	ret = driver_register(&fdtv_driver.driver);
+	if (ret < 0)
+		fw_core_remove_address_handler(&fcp_handler);
+
+	return ret;
 }
 
-void fdtv_fw_exit(void)
+static void __exit fdtv_exit(void)
 {
 	driver_unregister(&fdtv_driver.driver);
 	fw_core_remove_address_handler(&fcp_handler);
 }
+
+module_init(fdtv_init);
+module_exit(fdtv_exit);
+
+MODULE_AUTHOR("Andreas Monitzer <andy@monitzer.com>");
+MODULE_AUTHOR("Ben Backx <ben@bbackx.com>");
+MODULE_DESCRIPTION("FireDTV DVB Driver");
+MODULE_LICENSE("GPL");
+MODULE_SUPPORTED_DEVICE("FireDTV DVB");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv.h linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/firedtv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/firedtv.h	2011-05-19 00:06:34.000000000 -0400
@@ -70,15 +70,7 @@
 
 struct device;
 struct input_dev;
-struct firedtv;
-
-struct firedtv_backend {
-	int (*lock)(struct firedtv *fdtv, u64 addr, void *data);
-	int (*read)(struct firedtv *fdtv, u64 addr, void *data);
-	int (*write)(struct firedtv *fdtv, u64 addr, void *data, size_t len);
-	int (*start_iso)(struct firedtv *fdtv);
-	void (*stop_iso)(struct firedtv *fdtv);
-};
+struct fdtv_ir_context;
 
 struct firedtv {
 	struct device *device;
@@ -104,12 +96,11 @@
 	enum model_type		type;
 	char			subunit;
 	char			isochannel;
+	struct fdtv_ir_context	*ir_context;
+
 	fe_sec_voltage_t	voltage;
 	fe_sec_tone_mode_t	tone;
 
-	const struct firedtv_backend *backend;
-	void			*backend_data;
-
 	struct mutex		demux_mutex;
 	unsigned long		channel_active;
 	u16			channel_pid[16];
@@ -118,15 +109,6 @@
 	u8			avc_data[512];
 };
 
-/* firedtv-1394.c */
-#ifdef CONFIG_DVB_FIREDTV_IEEE1394
-int fdtv_1394_init(void);
-void fdtv_1394_exit(void);
-#else
-static inline int fdtv_1394_init(void) { return 0; }
-static inline void fdtv_1394_exit(void) {}
-#endif
-
 /* firedtv-avc.c */
 int avc_recv(struct firedtv *fdtv, void *data, size_t length);
 int avc_tuner_status(struct firedtv *fdtv, struct firedtv_tuner_status *stat);
@@ -158,25 +140,18 @@
 /* firedtv-dvb.c */
 int fdtv_start_feed(struct dvb_demux_feed *dvbdmxfeed);
 int fdtv_stop_feed(struct dvb_demux_feed *dvbdmxfeed);
-int fdtv_dvb_register(struct firedtv *fdtv);
+int fdtv_dvb_register(struct firedtv *fdtv, const char *name);
 void fdtv_dvb_unregister(struct firedtv *fdtv);
-struct firedtv *fdtv_alloc(struct device *dev,
-			   const struct firedtv_backend *backend,
-			   const char *name, size_t name_len);
-extern const char *fdtv_model_names[];
-extern const struct ieee1394_device_id fdtv_id_table[];
 
 /* firedtv-fe.c */
-void fdtv_frontend_init(struct firedtv *fdtv);
+void fdtv_frontend_init(struct firedtv *fdtv, const char *name);
 
 /* firedtv-fw.c */
-#ifdef CONFIG_DVB_FIREDTV_FIREWIRE
-int fdtv_fw_init(void);
-void fdtv_fw_exit(void);
-#else
-static inline int fdtv_fw_init(void) { return 0; }
-static inline void fdtv_fw_exit(void) {}
-#endif
+int fdtv_lock(struct firedtv *fdtv, u64 addr, void *data);
+int fdtv_read(struct firedtv *fdtv, u64 addr, void *data);
+int fdtv_write(struct firedtv *fdtv, u64 addr, void *data, size_t len);
+int fdtv_start_iso(struct firedtv *fdtv);
+void fdtv_stop_iso(struct firedtv *fdtv);
 
 /* firedtv-rc.c */
 #ifdef CONFIG_DVB_FIREDTV_INPUT
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/Kconfig linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 config DVB_FIREDTV
 	tristate "FireDTV and FloppyDTV"
-	depends on DVB_CORE && (FIREWIRE || IEEE1394)
+	depends on DVB_CORE && FIREWIRE
 	help
 	  Support for DVB receivers from Digital Everywhere
 	  which are connected via IEEE 1394 (FireWire).
@@ -13,12 +13,6 @@
 
 if DVB_FIREDTV
 
-config DVB_FIREDTV_FIREWIRE
-	def_bool FIREWIRE = y || (FIREWIRE = m && DVB_FIREDTV = m)
-
-config DVB_FIREDTV_IEEE1394
-	def_bool IEEE1394 = y || (IEEE1394 = m && DVB_FIREDTV = m)
-
 config DVB_FIREDTV_INPUT
 	def_bool INPUT = y || (INPUT = m && DVB_FIREDTV = m)
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/Makefile linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/dvb/firewire/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/firewire/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,9 +1,6 @@
 obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
 
-firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o
-firedtv-$(CONFIG_DVB_FIREDTV_FIREWIRE) += firedtv-fw.o
-firedtv-$(CONFIG_DVB_FIREDTV_IEEE1394) += firedtv-1394.o
+firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o
 firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
 
 ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-$(CONFIG_DVB_FIREDTV_IEEE1394) += -Idrivers/ieee1394
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/af9013.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/af9013.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/af9013.c	2012-03-24 01:02:47.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/af9013.c	2012-03-24 03:27:57.000000000 -0400
@@ -1323,13 +1323,11 @@
 
 static int af9013_download_firmware(struct af9013_state *state)
 {
-	int i, len, packets, remainder, ret;
+	int i, len, remaining, ret;
 	const struct firmware *fw;
-	u16 addr = 0x5100; /* firmware start address */
 	u16 checksum = 0;
 	u8 val;
 	u8 fw_params[4];
-	u8 *data;
 	u8 *fw_file = "/*(DEBLOBBED)*/";
 
 	msleep(100);
@@ -1373,21 +1371,18 @@
 	if (ret)
 		goto error_release;
 
-	#define FW_PACKET_MAX_DATA  16
-
-	packets = fw->size / FW_PACKET_MAX_DATA;
-	remainder = fw->size % FW_PACKET_MAX_DATA;
-	len = FW_PACKET_MAX_DATA;
-	for (i = 0; i <= packets; i++) {
-		if (i == packets)  /* set size of the last packet */
-			len = remainder;
-
-		data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
-		ret = af9013_write_ofsm_regs(state, addr, data, len);
-		addr += FW_PACKET_MAX_DATA;
+	#define FW_ADDR 0x5100 /* firmware start address */
+	#define LEN_MAX 16 /* max packet size */
+	for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
+		len = remaining;
+		if (len > LEN_MAX)
+			len = LEN_MAX;
 
+		ret = af9013_write_ofsm_regs(state,
+			FW_ADDR + fw->size - remaining,
+			(u8 *) &fw->data[fw->size - remaining], len);
 		if (ret) {
-			err("firmware download failed at %d with %d", i, ret);
+			err("firmware download failed:%d", ret);
 			goto error_release;
 		}
 	}
@@ -1466,20 +1461,6 @@
 	state->i2c = i2c;
 	memcpy(&state->config, config, sizeof(struct af9013_config));
 
-	/* chip version */
-	ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
-	if (ret)
-		goto error;
-
-	/* ROM version */
-	for (i = 0; i < 2; i++) {
-		ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
-		if (ret)
-			goto error;
-	}
-	deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
-		buf[2], buf[0], buf[1]);
-
 	/* download firmware */
 	if (state->config.output_mode != AF9013_OUTPUT_MODE_USB) {
 		ret = af9013_download_firmware(state);
@@ -1495,6 +1476,20 @@
 	}
 	info("firmware version:%d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
 
+	/* chip version */
+	ret = af9013_read_reg_bits(state, 0xd733, 4, 4, &buf[2]);
+	if (ret)
+		goto error;
+
+	/* ROM version */
+	for (i = 0; i < 2; i++) {
+		ret = af9013_read_reg(state, 0x116b + i, &buf[i]);
+		if (ret)
+			goto error;
+	}
+	deb_info("%s: chip version:%d ROM version:%d.%d\n", __func__,
+		buf[2], buf[0], buf[1]);
+
 	/* settings for mp2if */
 	if (state->config.output_mode == AF9013_OUTPUT_MODE_USB) {
 		/* AF9015 split PSB to 1.5k + 0.5k */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/atbm8830.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/atbm8830.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/atbm8830.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/atbm8830.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 	/* parallel or serial transport stream */
 	u8 serial_ts;
 
-	/* transport stream clock output only when receving valid stream */
+	/* transport stream clock output only when receiving valid stream */
 	u8 ts_clk_gated;
 
 	/* Decoder sample TS data at rising edge of clock */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/au8522_dig.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/au8522_dig.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/au8522_dig.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/au8522_dig.c	2011-05-19 00:06:34.000000000 -0400
@@ -635,7 +635,7 @@
 	struct au8522_led_config *led_config = state->config->led_cfg;
 	u8 val;
 
-	/* bail out if we cant control an LED */
+	/* bail out if we can't control an LED */
 	if (!led_config || !led_config->gpio_output ||
 	    !led_config->gpio_output_enable || !led_config->gpio_output_disable)
 		return 0;
@@ -665,7 +665,7 @@
 	struct au8522_led_config *led_config = state->config->led_cfg;
 	int i, ret = 0;
 
-	/* bail out if we cant control an LED */
+	/* bail out if we can't control an LED */
 	if (!led_config || !led_config->gpio_leds ||
 	    !led_config->num_led_states || !led_config->led_states)
 		return 0;
@@ -803,7 +803,7 @@
 	int led;
 	u16 strong;
 
-	/* bail out if we cant control an LED */
+	/* bail out if we can't control an LED */
 	if (!led_config)
 		return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/bcm3510.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/bcm3510.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/bcm3510.c	2012-03-24 01:02:47.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/bcm3510.c	2012-03-24 03:27:57.000000000 -0400
@@ -153,7 +153,7 @@
 	unsigned long t;
 
 /* Check if any previous HAB request still needs to be serviced by the
- * Aquisition Processor before sending new request */
+ * Acquisition Processor before sending new request */
 	if ((ret = bcm3510_readB(st,0xa8,&v)) < 0)
 		return ret;
 	if (v.HABSTAT_a8.HABR) {
@@ -359,7 +359,7 @@
 /* Set duration of the initial state of TUNCTL = 3.34 micro Sec */
 	c.TUNCTL_state = 0x40;
 
-/* PRESCALER DEVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
+/* PRESCALER DIVIDE RATIO | BC1_2_3_4; (band switch), 1stosc REFERENCE COUNTER REF_S12 and REF_S11 */
 	c.ctl_dat[0].ctrl.size = BITS_8;
 	c.ctl_dat[0].data      = 0x80 | bc;
 
@@ -395,7 +395,7 @@
 	c.ctl_dat[7].ctrl.cs0  = 1;
 	c.ctl_dat[7].data      = 0x40;
 
-/* PRESCALER DEVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
+/* PRESCALER DIVIDE RATIO, 2ndosc REFERENCE COUNTER REF_S12 and REF_S11 */
 	c.ctl_dat[8].ctrl.size = BITS_8;
 	c.ctl_dat[8].data      = 0x80;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx22700.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx22700.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx22700.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx22700.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,7 +179,7 @@
 	cx22700_writereg (state, 0x06, val);
 
 	cx22700_writereg (state, 0x08, 0x04 | 0x02);  /* use user tps parameters */
-	cx22700_writereg (state, 0x08, 0x04);         /* restart aquisition */
+	cx22700_writereg (state, 0x08, 0x04);         /* restart acquisition */
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx22702.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx22702.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx22702.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx22702.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,7 @@
 
 /* Register values to initialise the demod */
 static const u8 init_tab[] = {
-	0x00, 0x00, /* Stop aquisition */
+	0x00, 0x00, /* Stop acquisition */
 	0x0B, 0x06,
 	0x09, 0x01,
 	0x0D, 0x41,
@@ -310,7 +310,7 @@
 			& 0xfc);
 		cx22702_writereg(state, 0x0C,
 			(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
-		cx22702_writereg(state, 0x00, 0x01); /* Begin aquisition */
+		cx22702_writereg(state, 0x00, 0x01); /* Begin acquisition */
 		dprintk("%s: Autodetecting\n", __func__);
 		return 0;
 	}
@@ -424,7 +424,7 @@
 	cx22702_writereg(state, 0x0C,
 		(cx22702_readreg(state, 0x0C) & 0xBF) | 0x40);
 
-	/* Begin channel aquisition */
+	/* Begin channel acquisition */
 	cx22702_writereg(state, 0x00, 0x01);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx24110.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx24110.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx24110.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx24110.c	2011-05-19 00:06:34.000000000 -0400
@@ -544,7 +544,7 @@
 	cx24110_set_inversion (state, p->inversion);
 	cx24110_set_fec (state, p->u.qpsk.fec_inner);
 	cx24110_set_symbolrate (state, p->u.qpsk.symbol_rate);
-	cx24110_writereg(state,0x04,0x05); /* start aquisition */
+	cx24110_writereg(state,0x04,0x05); /* start acquisition */
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx24113.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx24113.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx24113.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx24113.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- *  Driver for Conexant CX24113/CX24128 Tuner (Satelite)
+ *  Driver for Conexant CX24113/CX24128 Tuner (Satellite)
  *
  *  Copyright (C) 2007-8 Patrick Boettcher <pb@linuxtv.org>
  *
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx24123.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx24123.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/cx24123.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/cx24123.c	2011-05-19 00:06:34.000000000 -0400
@@ -949,7 +949,7 @@
 	else
 		err("it seems I don't have a tuner...");
 
-	/* Enable automatic aquisition and reset cycle */
+	/* Enable automatic acquisition and reset cycle */
 	cx24123_writereg(state, 0x03, (cx24123_readreg(state, 0x03) | 0x07));
 	cx24123_writereg(state, 0x00, 0x10);
 	cx24123_writereg(state, 0x00, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib0090.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib0090.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib0090.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib0090.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 	} \
 } while (0)
 
+#define CONFIG_SYS_DVBT
 #define CONFIG_SYS_ISDBT
 #define CONFIG_BAND_CBAND
 #define CONFIG_BAND_VHF
@@ -76,6 +77,34 @@
 #define EN_SBD		 0x44E9
 #define EN_CAB		 0x88E9
 
+/* Calibration defines */
+#define      DC_CAL 0x1
+#define     WBD_CAL 0x2
+#define    TEMP_CAL 0x4
+#define CAPTRIM_CAL 0x8
+
+#define KROSUS_PLL_LOCKED   0x800
+#define KROSUS              0x2
+
+/* Use those defines to identify SOC version */
+#define SOC               0x02
+#define SOC_7090_P1G_11R1 0x82
+#define SOC_7090_P1G_21R1 0x8a
+#define SOC_8090_P1G_11R1 0x86
+#define SOC_8090_P1G_21R1 0x8e
+
+/* else use thos ones to check */
+#define P1A_B      0x0
+#define P1C	   0x1
+#define P1D_E_F    0x3
+#define P1G	   0x7
+#define P1G_21R2   0xf
+
+#define MP001 0x1		/* Single 9090/8096 */
+#define MP005 0x4		/* Single Sband */
+#define MP008 0x6		/* Dual diversity VHF-UHF-LBAND */
+#define MP009 0x7		/* Dual diversity 29098 CBAND-UHF-LBAND-SBAND */
+
 #define pgm_read_word(w) (*w)
 
 struct dc_calibration;
@@ -84,7 +113,7 @@
 	u32 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
 	u8 switch_trim;
 	u8 lna_tune;
-	u8 lna_bias;
+	u16 lna_bias;
 	u16 v2i;
 	u16 mix;
 	u16 load;
@@ -99,13 +128,19 @@
 	u8 topresc;
 };
 
+struct dib0090_identity {
+	u8 version;
+	u8 product;
+	u8 p1g;
+	u8 in_soc;
+};
+
 struct dib0090_state {
 	struct i2c_adapter *i2c;
 	struct dvb_frontend *fe;
 	const struct dib0090_config *config;
 
 	u8 current_band;
-	u16 revision;
 	enum frontend_tune_state tune_state;
 	u32 current_rf;
 
@@ -143,7 +178,26 @@
 	u8 tuner_is_tuned;
 	u8 agc_freeze;
 
-	u8 reset;
+	struct dib0090_identity identity;
+
+	u32 rf_request;
+	u8 current_standard;
+
+	u8 calibrate;
+	u32 rest;
+	u16 bias;
+	s16 temperature;
+
+	u8 wbd_calibration_gain;
+	const struct dib0090_wbd_slope *current_wbd_table;
+	u16 wbdmux;
+};
+
+struct dib0090_fw_state {
+	struct i2c_adapter *i2c;
+	struct dvb_frontend *fe;
+	struct dib0090_identity identity;
+	const struct dib0090_config *config;
 };
 
 static u16 dib0090_read_reg(struct dib0090_state *state, u8 reg)
@@ -171,6 +225,28 @@
 	return 0;
 }
 
+static u16 dib0090_fw_read_reg(struct dib0090_fw_state *state, u8 reg)
+{
+	u8 b[2];
+	struct i2c_msg msg = {.addr = reg, .flags = I2C_M_RD, .buf = b, .len = 2 };
+	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0090 I2C read failed\n");
+		return 0;
+	}
+	return (b[0] << 8) | b[1];
+}
+
+static int dib0090_fw_write_reg(struct dib0090_fw_state *state, u8 reg, u16 val)
+{
+	u8 b[2] = { val >> 8, val & 0xff };
+	struct i2c_msg msg = {.addr = reg, .flags = 0, .buf = b, .len = 2 };
+	if (i2c_transfer(state->i2c, &msg, 1) != 1) {
+		printk(KERN_WARNING "DiB0090 I2C write failed\n");
+		return -EREMOTEIO;
+	}
+	return 0;
+}
+
 #define HARD_RESET(state) do {  if (cfg->reset) {  if (cfg->sleep) cfg->sleep(fe, 0); msleep(10);  cfg->reset(fe, 1); msleep(10);  cfg->reset(fe, 0); msleep(10);  }  } while (0)
 #define ADC_TARGET -220
 #define GAIN_ALPHA 5
@@ -183,89 +259,327 @@
 	} while (--c);
 }
 
-static u16 dib0090_identify(struct dvb_frontend *fe)
+static int dib0090_identify(struct dvb_frontend *fe)
 {
 	struct dib0090_state *state = fe->tuner_priv;
 	u16 v;
+	struct dib0090_identity *identity = &state->identity;
 
 	v = dib0090_read_reg(state, 0x1a);
 
-#ifdef FIRMWARE_FIREFLY
-	/* pll is not locked locked */
-	if (!(v & 0x800))
-		dprintk("FE%d : Identification : pll is not yet locked", fe->id);
-#endif
+	identity->p1g = 0;
+	identity->in_soc = 0;
+
+	dprintk("Tuner identification (Version = 0x%04x)", v);
 
 	/* without PLL lock info */
-	v &= 0x3ff;
-	dprintk("P/V: %04x:", v);
+	v &= ~KROSUS_PLL_LOCKED;
 
-	if ((v >> 8) & 0xf)
-		dprintk("FE%d : Product ID = 0x%x : KROSUS", fe->id, (v >> 8) & 0xf);
-	else
-		return 0xff;
+	identity->version = v & 0xff;
+	identity->product = (v >> 8) & 0xf;
 
-	v &= 0xff;
-	if (((v >> 5) & 0x7) == 0x1)
-		dprintk("FE%d : MP001 : 9090/8096", fe->id);
-	else if (((v >> 5) & 0x7) == 0x4)
-		dprintk("FE%d : MP005 : Single Sband", fe->id);
-	else if (((v >> 5) & 0x7) == 0x6)
-		dprintk("FE%d : MP008 : diversity VHF-UHF-LBAND", fe->id);
-	else if (((v >> 5) & 0x7) == 0x7)
-		dprintk("FE%d : MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND", fe->id);
-	else
-		return 0xff;
+	if (identity->product != KROSUS)
+		goto identification_error;
 
-	/* revision only */
-	if ((v & 0x1f) == 0x3)
-		dprintk("FE%d : P1-D/E/F detected", fe->id);
-	else if ((v & 0x1f) == 0x1)
-		dprintk("FE%d : P1C detected", fe->id);
-	else if ((v & 0x1f) == 0x0) {
-#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
-		dprintk("FE%d : P1-A/B detected: using previous driver - support will be removed soon", fe->id);
-		dib0090_p1b_register(fe);
-#else
-		dprintk("FE%d : P1-A/B detected: driver is deactivated - not available", fe->id);
-		return 0xff;
-#endif
+	if ((identity->version & 0x3) == SOC) {
+		identity->in_soc = 1;
+		switch (identity->version) {
+		case SOC_8090_P1G_11R1:
+			dprintk("SOC 8090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_8090_P1G_21R1:
+			dprintk("SOC 8090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_11R1:
+			dprintk("SOC 7090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_21R1:
+			dprintk("SOC 7090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		default:
+			goto identification_error;
+		}
+	} else {
+		switch ((identity->version >> 5) & 0x7) {
+		case MP001:
+			dprintk("MP001 : 9090/8096");
+			break;
+		case MP005:
+			dprintk("MP005 : Single Sband");
+			break;
+		case MP008:
+			dprintk("MP008 : diversity VHF-UHF-LBAND");
+			break;
+		case MP009:
+			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
+			break;
+		default:
+			goto identification_error;
+		}
+
+		switch (identity->version & 0x1f) {
+		case P1G_21R2:
+			dprintk("P1G_21R2 detected");
+			identity->p1g = 1;
+			break;
+		case P1G:
+			dprintk("P1G detected");
+			identity->p1g = 1;
+			break;
+		case P1D_E_F:
+			dprintk("P1D/E/F detected");
+			break;
+		case P1C:
+			dprintk("P1C detected");
+			break;
+		case P1A_B:
+			dprintk("P1-A/B detected: driver is deactivated - not available");
+			goto identification_error;
+			break;
+		default:
+			goto identification_error;
+		}
 	}
 
-	return v;
+	return 0;
+
+identification_error:
+	return -EIO;
+}
+
+static int dib0090_fw_identify(struct dvb_frontend *fe)
+{
+	struct dib0090_fw_state *state = fe->tuner_priv;
+	struct dib0090_identity *identity = &state->identity;
+
+	u16 v = dib0090_fw_read_reg(state, 0x1a);
+	identity->p1g = 0;
+	identity->in_soc = 0;
+
+	dprintk("FE: Tuner identification (Version = 0x%04x)", v);
+
+	/* without PLL lock info */
+	v &= ~KROSUS_PLL_LOCKED;
+
+	identity->version = v & 0xff;
+	identity->product = (v >> 8) & 0xf;
+
+	if (identity->product != KROSUS)
+		goto identification_error;
+
+	if ((identity->version & 0x3) == SOC) {
+		identity->in_soc = 1;
+		switch (identity->version) {
+		case SOC_8090_P1G_11R1:
+			dprintk("SOC 8090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_8090_P1G_21R1:
+			dprintk("SOC 8090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_11R1:
+			dprintk("SOC 7090 P1-G11R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		case SOC_7090_P1G_21R1:
+			dprintk("SOC 7090 P1-G21R1 Has been detected");
+			identity->p1g = 1;
+			break;
+		default:
+			goto identification_error;
+		}
+	} else {
+		switch ((identity->version >> 5) & 0x7) {
+		case MP001:
+			dprintk("MP001 : 9090/8096");
+			break;
+		case MP005:
+			dprintk("MP005 : Single Sband");
+			break;
+		case MP008:
+			dprintk("MP008 : diversity VHF-UHF-LBAND");
+			break;
+		case MP009:
+			dprintk("MP009 : diversity 29098 CBAND-UHF-LBAND-SBAND");
+			break;
+		default:
+			goto identification_error;
+		}
+
+		switch (identity->version & 0x1f) {
+		case P1G_21R2:
+			dprintk("P1G_21R2 detected");
+			identity->p1g = 1;
+			break;
+		case P1G:
+			dprintk("P1G detected");
+			identity->p1g = 1;
+			break;
+		case P1D_E_F:
+			dprintk("P1D/E/F detected");
+			break;
+		case P1C:
+			dprintk("P1C detected");
+			break;
+		case P1A_B:
+			dprintk("P1-A/B detected: driver is deactivated - not available");
+			goto identification_error;
+			break;
+		default:
+			goto identification_error;
+		}
+	}
+
+	return 0;
+
+identification_error:
+	return -EIO;;
 }
 
 static void dib0090_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
 {
 	struct dib0090_state *state = fe->tuner_priv;
+	u16 PllCfg, i, v;
 
 	HARD_RESET(state);
 
-	dib0090_write_reg(state, 0x24, EN_PLL);
+	dib0090_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
 	dib0090_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
 
-	/* adcClkOutRatio=8->7, release reset */
-	dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
+	if (!cfg->in_soc) {
+		/* adcClkOutRatio=8->7, release reset */
+		dib0090_write_reg(state, 0x20, ((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (0 << 4) | 0);
+		if (cfg->clkoutdrive != 0)
+			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
+					  | (cfg->clkoutdrive << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
+		else
+			dib0090_write_reg(state, 0x23, (0 << 15) | ((!cfg->analog_output) << 14) | (2 << 10) | (1 << 9) | (0 << 8)
+					  | (7 << 5) | (cfg->clkouttobamse << 4) | (0 << 2) | (0));
+	}
+
+	/* Read Pll current config * */
+	PllCfg = dib0090_read_reg(state, 0x21);
+
+	/** Reconfigure PLL if current setting is different from default setting **/
+	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && (!cfg->in_soc)
+			&& !cfg->io.pll_bypass) {
+
+		/* Set Bypass mode */
+		PllCfg |= (1 << 15);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+		/* Set Reset Pll */
+		PllCfg &= ~(1 << 13);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+	/*** Set new Pll configuration in bypass and reset state ***/
+		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+		/* Remove Reset Pll */
+		PllCfg |= (1 << 13);
+		dib0090_write_reg(state, 0x21, PllCfg);
+
+	/*** Wait for PLL lock ***/
+		i = 100;
+		do {
+			v = !!(dib0090_read_reg(state, 0x1a) & 0x800);
+			if (v)
+				break;
+		} while (--i);
+
+		if (i == 0) {
+			dprintk("Pll: Unable to lock Pll");
+			return;
+		}
+
+		/* Finally Remove Bypass mode */
+		PllCfg &= ~(1 << 15);
+		dib0090_write_reg(state, 0x21, PllCfg);
+	}
+
+	if (cfg->io.pll_bypass) {
+		PllCfg |= (cfg->io.pll_bypass << 15);
+		dib0090_write_reg(state, 0x21, PllCfg);
+	}
+}
+
+static int dib0090_fw_reset_digital(struct dvb_frontend *fe, const struct dib0090_config *cfg)
+{
+	struct dib0090_fw_state *state = fe->tuner_priv;
+	u16 PllCfg;
+	u16 v;
+	int i;
+
+	dprintk("fw reset digital");
+	HARD_RESET(state);
+
+	dib0090_fw_write_reg(state, 0x24, EN_PLL | EN_CRYSTAL);
+	dib0090_fw_write_reg(state, 0x1b, EN_DIGCLK | EN_PLL | EN_CRYSTAL);	/* PLL, DIG_CLK and CRYSTAL remain */
+
+	dib0090_fw_write_reg(state, 0x20,
+			((cfg->io.adc_clock_ratio - 1) << 11) | (0 << 10) | (1 << 9) | (1 << 8) | (cfg->data_tx_drv << 4) | cfg->ls_cfg_pad_drv);
+
+	v = (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 9) | (0 << 8) | (cfg->clkouttobamse << 4) | (0 << 2) | (0);
 	if (cfg->clkoutdrive != 0)
-		dib0090_write_reg(state, 0x23,
-				  (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (cfg->clkoutdrive << 5) | (cfg->
-																	   clkouttobamse
-																	   << 4) | (0
-																		    <<
-																		    2)
-				  | (0));
+		v |= cfg->clkoutdrive << 5;
 	else
-		dib0090_write_reg(state, 0x23,
-				  (0 << 15) | ((!cfg->analog_output) << 14) | (1 << 10) | (1 << 9) | (0 << 8) | (7 << 5) | (cfg->
-															    clkouttobamse << 4) | (0
-																		   <<
-																		   2)
-				  | (0));
+		v |= 7 << 5;
 
-	/* enable pll, de-activate reset, ratio: 2/1 = 60MHz */
-	dib0090_write_reg(state, 0x21,
-			  (cfg->io.pll_bypass << 15) | (1 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv));
+	v |= 2 << 10;
+	dib0090_fw_write_reg(state, 0x23, v);
+
+	/* Read Pll current config * */
+	PllCfg = dib0090_fw_read_reg(state, 0x21);
 
+	/** Reconfigure PLL if current setting is different from default setting **/
+	if ((PllCfg & 0x1FFF) != ((cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv)) && !cfg->io.pll_bypass) {
+
+		/* Set Bypass mode */
+		PllCfg |= (1 << 15);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+		/* Set Reset Pll */
+		PllCfg &= ~(1 << 13);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+	/*** Set new Pll configuration in bypass and reset state ***/
+		PllCfg = (1 << 15) | (0 << 13) | (cfg->io.pll_range << 12) | (cfg->io.pll_loopdiv << 6) | (cfg->io.pll_prediv);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+		/* Remove Reset Pll */
+		PllCfg |= (1 << 13);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+
+	/*** Wait for PLL lock ***/
+		i = 100;
+		do {
+			v = !!(dib0090_fw_read_reg(state, 0x1a) & 0x800);
+			if (v)
+				break;
+		} while (--i);
+
+		if (i == 0) {
+			dprintk("Pll: Unable to lock Pll");
+			return -EIO;
+		}
+
+		/* Finally Remove Bypass mode */
+		PllCfg &= ~(1 << 15);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+	}
+
+	if (cfg->io.pll_bypass) {
+		PllCfg |= (cfg->io.pll_bypass << 15);
+		dib0090_fw_write_reg(state, 0x21, PllCfg);
+	}
+
+	return dib0090_fw_identify(fe);
 }
 
 static int dib0090_wakeup(struct dvb_frontend *fe)
@@ -273,6 +587,9 @@
 	struct dib0090_state *state = fe->tuner_priv;
 	if (state->config->sleep)
 		state->config->sleep(fe, 0);
+
+	/* enable dataTX in case we have been restarted in the wrong moment */
+	dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
 	return 0;
 }
 
@@ -292,8 +609,75 @@
 	else
 		dib0090_write_reg(state, 0x04, 1);
 }
+
 EXPORT_SYMBOL(dib0090_dcc_freq);
 
+static const u16 bb_ramp_pwm_normal_socs[] = {
+	550,			/* max BB gain in 10th of dB */
+	(1 << 9) | 8,		/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> BB_RAMP2 */
+	440,
+	(4 << 9) | 0,		/* BB_RAMP3 = 26dB */
+	(0 << 9) | 208,		/* BB_RAMP4 */
+	(4 << 9) | 208,		/* BB_RAMP5 = 29dB */
+	(0 << 9) | 440,		/* BB_RAMP6 */
+};
+
+static const u16 rf_ramp_pwm_cband_7090[] = {
+	280,			/* max RF gain in 10th of dB */
+	18,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	504,			/* ramp_max = maximum X used on the ramp */
+	(29 << 10) | 364,	/* RF_RAMP5, LNA 1 = 8dB */
+	(0 << 10) | 504,	/* RF_RAMP6, LNA 1 */
+	(60 << 10) | 228,	/* RF_RAMP7, LNA 2 = 7.7dB */
+	(0 << 10) | 364,	/* RF_RAMP8, LNA 2 */
+	(34 << 10) | 109,	/* GAIN_4_1, LNA 3 = 6.8dB */
+	(0 << 10) | 228,	/* GAIN_4_2, LNA 3 */
+	(37 << 10) | 0,		/* RF_RAMP3, LNA 4 = 6.2dB */
+	(0 << 10) | 109,	/* RF_RAMP4, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_cband_8090[] = {
+	345,			/* max RF gain in 10th of dB */
+	29,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1000,			/* ramp_max = maximum X used on the ramp */
+	(35 << 10) | 772,	/* RF_RAMP3, LNA 1 = 8dB */
+	(0 << 10) | 1000,	/* RF_RAMP4, LNA 1 */
+	(58 << 10) | 496,	/* RF_RAMP5, LNA 2 = 9.5dB */
+	(0 << 10) | 772,	/* RF_RAMP6, LNA 2 */
+	(27 << 10) | 200,	/* RF_RAMP7, LNA 3 = 10.5dB */
+	(0 << 10) | 496,	/* RF_RAMP8, LNA 3 */
+	(40 << 10) | 0,		/* GAIN_4_1, LNA 4 = 7dB */
+	(0 << 10) | 200,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_uhf_7090[] = {
+	407,			/* max RF gain in 10th of dB */
+	13,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	529,			/* ramp_max = maximum X used on the ramp */
+	(23 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
+	(0 << 10) | 176,	/* RF_RAMP4, LNA 1 */
+	(63 << 10) | 400,	/* RF_RAMP5, LNA 2 = 8dB */
+	(0 << 10) | 529,	/* RF_RAMP6, LNA 2 */
+	(48 << 10) | 316,	/* RF_RAMP7, LNA 3 = 6.8dB */
+	(0 << 10) | 400,	/* RF_RAMP8, LNA 3 */
+	(29 << 10) | 176,	/* GAIN_4_1, LNA 4 = 11.5dB */
+	(0 << 10) | 316,	/* GAIN_4_2, LNA 4 */
+};
+
+static const u16 rf_ramp_pwm_uhf_8090[] = {
+	388,			/* max RF gain in 10th of dB */
+	26,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> RF_RAMP2 */
+	1008,			/* ramp_max = maximum X used on the ramp */
+	(11 << 10) | 0,		/* RF_RAMP3, LNA 1 = 14.7dB */
+	(0 << 10) | 369,	/* RF_RAMP4, LNA 1 */
+	(41 << 10) | 809,	/* RF_RAMP5, LNA 2 = 8dB */
+	(0 << 10) | 1008,	/* RF_RAMP6, LNA 2 */
+	(27 << 10) | 659,	/* RF_RAMP7, LNA 3 = 6dB */
+	(0 << 10) | 809,	/* RF_RAMP8, LNA 3 */
+	(14 << 10) | 369,	/* GAIN_4_1, LNA 4 = 11.5dB */
+	(0 << 10) | 659,	/* GAIN_4_2, LNA 4 */
+};
+
 static const u16 rf_ramp_pwm_cband[] = {
 	0,			/* max RF gain in 10th of dB */
 	0,			/* ramp_slope = 1dB of gain -> clock_ticks_per_db = clk_khz / ramp_slope -> 0x2b */
@@ -326,6 +710,16 @@
 	0, 0, 127,		/* CBAND :  0.0 dB */
 };
 
+static const u16 rf_ramp_cband_broadmatching[] =	/* for p1G only */
+{
+	314,			/* Calibrated at 200MHz order has been changed g4-g3-g2-g1 */
+	84, 314, 127,		/* LNA1 */
+	80, 230, 255,		/* LNA2 */
+	80, 150, 127,		/* LNA3  It was measured 12dB, do not lock if 120 */
+	70, 70, 127,		/* LNA4 */
+	0, 0, 127,		/* CBAND */
+};
+
 static const u16 rf_ramp_cband[] = {
 	332,			/* max RF gain in 10th of dB */
 	132, 252, 127,		/* LNA1,  dB */
@@ -380,8 +774,8 @@
 };
 
 struct slope {
-	int16_t range;
-	int16_t slope;
+	s16 range;
+	s16 slope;
 };
 static u16 slopes_to_scale(const struct slope *slopes, u8 num, s16 val)
 {
@@ -597,19 +991,39 @@
 #endif
 #ifdef CONFIG_BAND_CBAND
 		if (state->current_band == BAND_CBAND) {
-			dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
-			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			if (state->identity.in_soc) {
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_8090);
+				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband_7090);
+			} else {
+				dib0090_set_rframp_pwm(state, rf_ramp_pwm_cband);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			}
 		} else
 #endif
 #ifdef CONFIG_BAND_VHF
 		if (state->current_band == BAND_VHF) {
-			dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
-			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			if (state->identity.in_soc) {
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+			} else {
+				dib0090_set_rframp_pwm(state, rf_ramp_pwm_vhf);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			}
 		} else
 #endif
 		{
-			dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
-			dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			if (state->identity.in_soc) {
+				if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_8090);
+				else if (state->identity.version == SOC_7090_P1G_11R1 || state->identity.version == SOC_7090_P1G_21R1)
+					dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf_7090);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal_socs);
+			} else {
+				dib0090_set_rframp_pwm(state, rf_ramp_pwm_uhf);
+				dib0090_set_bbramp_pwm(state, bb_ramp_pwm_normal);
+			}
 		}
 
 		if (state->rf_ramp[0] != 0)
@@ -617,11 +1031,21 @@
 		else
 			dib0090_write_reg(state, 0x32, (0 << 11));
 
+		dib0090_write_reg(state, 0x04, 0x01);
 		dib0090_write_reg(state, 0x39, (1 << 10));
 	}
 }
+
 EXPORT_SYMBOL(dib0090_pwm_gain_reset);
 
+static u32 dib0090_get_slow_adc_val(struct dib0090_state *state)
+{
+	u16 adc_val = dib0090_read_reg(state, 0x1d);
+	if (state->identity.in_soc)
+		adc_val >>= 2;
+	return adc_val;
+}
+
 int dib0090_gain_control(struct dvb_frontend *fe)
 {
 	struct dib0090_state *state = fe->tuner_priv;
@@ -643,18 +1067,21 @@
 		} else
 #endif
 #ifdef CONFIG_BAND_VHF
-		if (state->current_band == BAND_VHF) {
+		if (state->current_band == BAND_VHF && !state->identity.p1g) {
 			dib0090_set_rframp(state, rf_ramp_vhf);
 			dib0090_set_bbramp(state, bb_ramp_boost);
 		} else
 #endif
 #ifdef CONFIG_BAND_CBAND
-		if (state->current_band == BAND_CBAND) {
+		if (state->current_band == BAND_CBAND && !state->identity.p1g) {
 			dib0090_set_rframp(state, rf_ramp_cband);
 			dib0090_set_bbramp(state, bb_ramp_boost);
 		} else
 #endif
-		{
+		if ((state->current_band == BAND_CBAND || state->current_band == BAND_VHF) && state->identity.p1g) {
+			dib0090_set_rframp(state, rf_ramp_cband_broadmatching);
+			dib0090_set_bbramp(state, bb_ramp_boost);
+		} else {
 			dib0090_set_rframp(state, rf_ramp_uhf);
 			dib0090_set_bbramp(state, bb_ramp_boost);
 		}
@@ -669,17 +1096,25 @@
 
 		*tune_state = CT_AGC_STEP_0;
 	} else if (!state->agc_freeze) {
-		s16 wbd;
+		s16 wbd = 0, i, cnt;
 
 		int adc;
-		wbd_val = dib0090_read_reg(state, 0x1d);
+		wbd_val = dib0090_get_slow_adc_val(state);
 
-		/* read and calc the wbd power */
-		wbd = dib0090_wbd_to_db(state, wbd_val);
+		if (*tune_state == CT_AGC_STEP_0)
+			cnt = 5;
+		else
+			cnt = 1;
+
+		for (i = 0; i < cnt; i++) {
+			wbd_val = dib0090_get_slow_adc_val(state);
+			wbd += dib0090_wbd_to_db(state, wbd_val);
+		}
+		wbd /= cnt;
 		wbd_error = state->wbd_target - wbd;
 
 		if (*tune_state == CT_AGC_STEP_0) {
-			if (wbd_error < 0 && state->rf_gain_limit > 0) {
+			if (wbd_error < 0 && state->rf_gain_limit > 0 && !state->identity.p1g) {
 #ifdef CONFIG_BAND_CBAND
 				/* in case of CBAND tune reduce first the lt_gain2 before adjusting the RF gain */
 				u8 ltg2 = (state->rf_lt_def >> 10) & 0x7;
@@ -700,39 +1135,39 @@
 			adc_error = (s16) (((s32) ADC_TARGET) - adc);
 #ifdef CONFIG_STANDARD_DAB
 			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DAB)
-				adc_error += 130;
+				adc_error -= 10;
 #endif
 #ifdef CONFIG_STANDARD_DVBT
 			if (state->fe->dtv_property_cache.delivery_system == STANDARD_DVBT &&
-			    (state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
+					(state->fe->dtv_property_cache.modulation == QAM_64 || state->fe->dtv_property_cache.modulation == QAM_16))
 				adc_error += 60;
 #endif
 #ifdef CONFIG_SYS_ISDBT
 			if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT) && (((state->fe->dtv_property_cache.layer[0].segment_count >
-											       0)
-											      &&
-											      ((state->fe->dtv_property_cache.layer[0].modulation ==
-												QAM_64)
-											       || (state->fe->dtv_property_cache.layer[0].
-												   modulation == QAM_16)))
-											     ||
-											     ((state->fe->dtv_property_cache.layer[1].segment_count >
-											       0)
-											      &&
-											      ((state->fe->dtv_property_cache.layer[1].modulation ==
-												QAM_64)
-											       || (state->fe->dtv_property_cache.layer[1].
-												   modulation == QAM_16)))
-											     ||
-											     ((state->fe->dtv_property_cache.layer[2].segment_count >
-											       0)
-											      &&
-											      ((state->fe->dtv_property_cache.layer[2].modulation ==
-												QAM_64)
-											       || (state->fe->dtv_property_cache.layer[2].
-												   modulation == QAM_16)))
-			    )
-			    )
+								0)
+							&&
+							((state->fe->dtv_property_cache.layer[0].modulation ==
+							  QAM_64)
+							 || (state->fe->dtv_property_cache.
+								 layer[0].modulation == QAM_16)))
+						||
+						((state->fe->dtv_property_cache.layer[1].segment_count >
+						  0)
+						 &&
+						 ((state->fe->dtv_property_cache.layer[1].modulation ==
+						   QAM_64)
+						  || (state->fe->dtv_property_cache.
+							  layer[1].modulation == QAM_16)))
+						||
+						((state->fe->dtv_property_cache.layer[2].segment_count >
+						  0)
+						 &&
+						 ((state->fe->dtv_property_cache.layer[2].modulation ==
+						   QAM_64)
+						  || (state->fe->dtv_property_cache.
+							  layer[2].modulation == QAM_16)))
+						)
+				)
 				adc_error += 60;
 #endif
 
@@ -760,9 +1195,9 @@
 		}
 #ifdef DEBUG_AGC
 		dprintk
-		    ("FE: %d, tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
-		     (u32) fe->id, (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
-		     (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
+			("tune state %d, ADC = %3ddB (ADC err %3d) WBD %3ddB (WBD err %3d, WBD val SADC: %4d), RFGainLimit (TOP): %3d, signal: %3ddBm",
+			 (u32) *tune_state, (u32) adc, (u32) adc_error, (u32) wbd, (u32) wbd_error, (u32) wbd_val,
+			 (u32) state->rf_gain_limit >> WBD_ALPHA, (s32) 200 + adc - (state->current_gain >> GAIN_ALPHA));
 #endif
 	}
 
@@ -771,6 +1206,7 @@
 		dib0090_gain_apply(state, adc_error, wbd_error, apply_gain_immediatly);
 	return ret;
 }
+
 EXPORT_SYMBOL(dib0090_gain_control);
 
 void dib0090_get_current_gain(struct dvb_frontend *fe, u16 * rf, u16 * bb, u16 * rf_gain_limit, u16 * rflt)
@@ -785,13 +1221,47 @@
 	if (rflt)
 		*rflt = (state->rf_lt_def >> 10) & 0x7;
 }
+
 EXPORT_SYMBOL(dib0090_get_current_gain);
 
-u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner)
+u16 dib0090_get_wbd_offset(struct dvb_frontend *fe)
 {
-	struct dib0090_state *st = tuner->tuner_priv;
-	return st->wbd_offset;
+	struct dib0090_state *state = fe->tuner_priv;
+	u32 f_MHz = state->fe->dtv_property_cache.frequency / 1000000;
+	s32 current_temp = state->temperature;
+	s32 wbd_thot, wbd_tcold;
+	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
+
+	while (f_MHz > wbd->max_freq)
+		wbd++;
+
+	dprintk("using wbd-table-entry with max freq %d", wbd->max_freq);
+
+	if (current_temp < 0)
+		current_temp = 0;
+	if (current_temp > 128)
+		current_temp = 128;
+
+	state->wbdmux &= ~(7 << 13);
+	if (wbd->wbd_gain != 0)
+		state->wbdmux |= (wbd->wbd_gain << 13);
+	else
+		state->wbdmux |= (4 << 13);
+
+	dib0090_write_reg(state, 0x10, state->wbdmux);
+
+	wbd_thot = wbd->offset_hot - (((u32) wbd->slope_hot * f_MHz) >> 6);
+	wbd_tcold = wbd->offset_cold - (((u32) wbd->slope_cold * f_MHz) >> 6);
+
+	wbd_tcold += ((wbd_thot - wbd_tcold) * current_temp) >> 7;
+
+	state->wbd_target = dib0090_wbd_to_db(state, state->wbd_offset + wbd_tcold);
+	dprintk("wbd-target: %d dB", (u32) state->wbd_target);
+	dprintk("wbd offset applied is %d", wbd_tcold);
+
+	return state->wbd_offset + wbd_tcold;
 }
+
 EXPORT_SYMBOL(dib0090_get_wbd_offset);
 
 static const u16 dib0090_defaults[] = {
@@ -801,7 +1271,7 @@
 	0x99a0,
 	0x6008,
 	0x0000,
-	0x8acb,
+	0x8bcb,
 	0x0000,
 	0x0405,
 	0x0000,
@@ -829,8 +1299,6 @@
 	1, 0x39,
 	0x0000,
 
-	1, 0x1b,
-	EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL,
 	2, 0x1e,
 	0x07FF,
 	0x0007,
@@ -844,50 +1312,125 @@
 	0
 };
 
-static int dib0090_reset(struct dvb_frontend *fe)
-{
-	struct dib0090_state *state = fe->tuner_priv;
-	u16 l, r, *n;
+static const u16 dib0090_p1g_additionnal_defaults[] = {
+	1, 0x05,
+	0xabcd,
 
-	dib0090_reset_digital(fe, state->config);
-	state->revision = dib0090_identify(fe);
+	1, 0x11,
+	0x00b4,
 
-	/* Revision definition */
-	if (state->revision == 0xff)
-		return -EINVAL;
-#ifdef EFUSE
-	else if ((state->revision & 0x1f) >= 3)	/* Update the efuse : Only available for KROSUS > P1C */
-		dib0090_set_EFUSE(state);
-#endif
+	1, 0x1c,
+	0xfffd,
 
-#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
-	if (!(state->revision & 0x1))	/* it is P1B - reset is already done */
-		return 0;
-#endif
+	1, 0x40,
+	0x108,
+	0
+};
+
+static void dib0090_set_default_config(struct dib0090_state *state, const u16 * n)
+{
+	u16 l, r;
 
-	/* Upload the default values */
-	n = (u16 *) dib0090_defaults;
 	l = pgm_read_word(n++);
 	while (l) {
 		r = pgm_read_word(n++);
 		do {
-			/* DEBUG_TUNER */
-			/* dprintk("%d, %d, %d", l, r, pgm_read_word(n)); */
 			dib0090_write_reg(state, r, pgm_read_word(n++));
 			r++;
 		} while (--l);
 		l = pgm_read_word(n++);
 	}
+}
+
+#define CAP_VALUE_MIN (u8)  9
+#define CAP_VALUE_MAX (u8) 40
+#define HR_MIN	      (u8) 25
+#define HR_MAX	      (u8) 40
+#define POLY_MIN      (u8)  0
+#define POLY_MAX      (u8)  8
+
+void dib0090_set_EFUSE(struct dib0090_state *state)
+{
+	u8 c, h, n;
+	u16 e2, e4;
+	u16 cal;
+
+	e2 = dib0090_read_reg(state, 0x26);
+	e4 = dib0090_read_reg(state, 0x28);
+
+	if ((state->identity.version == P1D_E_F) ||
+			(state->identity.version == P1G) || (e2 == 0xffff)) {
+
+		dib0090_write_reg(state, 0x22, 0x10);
+		cal = (dib0090_read_reg(state, 0x22) >> 6) & 0x3ff;
+
+		if ((cal < 670) || (cal == 1023))
+			cal = 850;
+		n = 165 - ((cal * 10)>>6) ;
+		e2 = e4 = (3<<12) | (34<<6) | (n);
+	}
+
+	if (e2 != e4)
+		e2 &= e4; /* Remove the redundancy  */
+
+	if (e2 != 0xffff) {
+		c = e2 & 0x3f;
+		n = (e2 >> 12) & 0xf;
+		h = (e2 >> 6) & 0x3f;
+
+		if ((c >= CAP_VALUE_MAX) || (c <= CAP_VALUE_MIN))
+			c = 32;
+		if ((h >= HR_MAX) || (h <= HR_MIN))
+			h = 34;
+		if ((n >= POLY_MAX) || (n <= POLY_MIN))
+			n = 3;
+
+		dib0090_write_reg(state, 0x13, (h << 10)) ;
+		e2 = (n<<11) | ((h>>2)<<6) | (c);
+		dib0090_write_reg(state, 0x2, e2) ; /* Load the BB_2 */
+	}
+}
+
+static int dib0090_reset(struct dvb_frontend *fe)
+{
+	struct dib0090_state *state = fe->tuner_priv;
+
+	dib0090_reset_digital(fe, state->config);
+	if (dib0090_identify(fe) < 0)
+		return -EIO;
+
+#ifdef CONFIG_TUNER_DIB0090_P1B_SUPPORT
+	if (!(state->identity.version & 0x1))	/* it is P1B - reset is already done */
+		return 0;
+#endif
+
+	if (!state->identity.in_soc) {
+		if ((dib0090_read_reg(state, 0x1a) >> 5) & 0x2)
+			dib0090_write_reg(state, 0x1b, (EN_IQADC | EN_BB | EN_BIAS | EN_DIGCLK | EN_PLL | EN_CRYSTAL));
+		else
+			dib0090_write_reg(state, 0x1b, (EN_DIGCLK | EN_PLL | EN_CRYSTAL));
+	}
+
+	dib0090_set_default_config(state, dib0090_defaults);
+
+	if (state->identity.in_soc)
+		dib0090_write_reg(state, 0x18, 0x2910);  /* charge pump current = 0 */
+
+	if (state->identity.p1g)
+		dib0090_set_default_config(state, dib0090_p1g_additionnal_defaults);
+
+	/* Update the efuse : Only available for KROSUS > P1C  and SOC as well*/
+	if (((state->identity.version & 0x1f) >= P1D_E_F) || (state->identity.in_soc))
+		dib0090_set_EFUSE(state);
 
 	/* Congigure in function of the crystal */
 	if (state->config->io.clock_khz >= 24000)
-		l = 1;
+		dib0090_write_reg(state, 0x14, 1);
 	else
-		l = 2;
-	dib0090_write_reg(state, 0x14, l);
+		dib0090_write_reg(state, 0x14, 2);
 	dprintk("Pll lock : %d", (dib0090_read_reg(state, 0x1a) >> 11) & 0x1);
 
-	state->reset = 3;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
+	state->calibrate = DC_CAL | WBD_CAL | TEMP_CAL;	/* enable iq-offset-calibration and wbd-calibration when tuning next time */
 
 	return 0;
 }
@@ -927,11 +1470,11 @@
 }
 
 struct dc_calibration {
-	uint8_t addr;
-	uint8_t offset;
-	uint8_t pga:1;
-	uint16_t bb1;
-	uint8_t i:1;
+	u8 addr;
+	u8 offset;
+	u8 pga:1;
+	u16 bb1;
+	u8 i:1;
 };
 
 static const struct dc_calibration dc_table[] = {
@@ -944,6 +1487,17 @@
 	{0},
 };
 
+static const struct dc_calibration dc_p1g_table[] = {
+	/* Step1 BB gain1= 26 with boost 1, gain 2 = 0 */
+	/* addr ; trim reg offset ; pga ; CTRL_BB1 value ; i or q */
+	{0x06, 5, 1, (1 << 13) | (0 << 8) | (15 << 3), 1},
+	{0x07, 11, 1, (1 << 13) | (0 << 8) | (15 << 3), 0},
+	/* Step 2 BB gain 1 = 26 with boost = 1 & gain 2 = 29 */
+	{0x06, 0, 0, (1 << 13) | (29 << 8) | (15 << 3), 1},
+	{0x06, 10, 0, (1 << 13) | (29 << 8) | (15 << 3), 0},
+	{0},
+};
+
 static void dib0090_set_trim(struct dib0090_state *state)
 {
 	u16 *val;
@@ -962,41 +1516,45 @@
 static int dib0090_dc_offset_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
 {
 	int ret = 0;
+	u16 reg;
 
 	switch (*tune_state) {
-
 	case CT_TUNER_START:
-		/* init */
-		dprintk("Internal DC calibration");
-
-		/* the LNA is off */
-		dib0090_write_reg(state, 0x24, 0x02ed);
+		dprintk("Start DC offset calibration");
 
 		/* force vcm2 = 0.8V */
 		state->bb6 = 0;
 		state->bb7 = 0x040d;
 
+		/* the LNA AND LO are off */
+		reg = dib0090_read_reg(state, 0x24) & 0x0ffb;	/* shutdown lna and lo */
+		dib0090_write_reg(state, 0x24, reg);
+
+		state->wbdmux = dib0090_read_reg(state, 0x10);
+		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x7 << 3) | 0x3);
+		dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
+
 		state->dc = dc_table;
 
+		if (state->identity.p1g)
+			state->dc = dc_p1g_table;
 		*tune_state = CT_TUNER_STEP_0;
 
 		/* fall through */
 
 	case CT_TUNER_STEP_0:
+		dprintk("Sart/continue DC calibration for %s path", (state->dc->i == 1) ? "I" : "Q");
 		dib0090_write_reg(state, 0x01, state->dc->bb1);
 		dib0090_write_reg(state, 0x07, state->bb7 | (state->dc->i << 7));
 
 		state->step = 0;
-
 		state->min_adc_diff = 1023;
-
 		*tune_state = CT_TUNER_STEP_1;
 		ret = 50;
 		break;
 
 	case CT_TUNER_STEP_1:
 		dib0090_set_trim(state);
-
 		*tune_state = CT_TUNER_STEP_2;
 		break;
 
@@ -1007,7 +1565,13 @@
 		break;
 
 	case CT_TUNER_STEP_5:	/* found an offset */
-		dprintk("FE%d: IQC read=%d, current=%x", state->fe->id, (u32) state->adc_diff, state->step);
+		dprintk("adc_diff = %d, current step= %d", (u32) state->adc_diff, state->step);
+		if (state->step == 0 && state->adc_diff < 0) {
+			state->min_adc_diff = -1023;
+			dprintk("Change of sign of the minimum adc diff");
+		}
+
+		dprintk("adc_diff = %d, min_adc_diff = %d current_step = %d", state->adc_diff, state->min_adc_diff, state->step);
 
 		/* first turn for this frequency */
 		if (state->step == 0) {
@@ -1017,20 +1581,21 @@
 				state->step = 0x10;
 		}
 
-		state->adc_diff = ABS(state->adc_diff);
-
-		if (state->adc_diff < state->min_adc_diff && steps(state->step) < 15) {	/* stop search when the delta to 0 is increasing */
+		/* Look for a change of Sign in the Adc_diff.min_adc_diff is used to STORE the setp N-1 */
+		if ((state->adc_diff & 0x8000) == (state->min_adc_diff & 0x8000) && steps(state->step) < 15) {
+			/* stop search when the delta the sign is changing and Steps =15 and Step=0 is force for continuance */
 			state->step++;
 			state->min_adc_diff = state->adc_diff;
 			*tune_state = CT_TUNER_STEP_1;
 		} else {
-
 			/* the minimum was what we have seen in the step before */
-			state->step--;
-			dib0090_set_trim(state);
+			if (ABS(state->adc_diff) > ABS(state->min_adc_diff)) {
+				dprintk("Since adc_diff N = %d  > adc_diff step N-1 = %d, Come back one step", state->adc_diff, state->min_adc_diff);
+				state->step--;
+			}
 
-			dprintk("FE%d: BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->fe->id, state->dc->addr, state->adc_diff,
-				state->step);
+			dib0090_set_trim(state);
+			dprintk("BB Offset Cal, BBreg=%hd,Offset=%hd,Value Set=%hd", state->dc->addr, state->adc_diff, state->step);
 
 			state->dc++;
 			if (state->dc->addr == 0)	/* done */
@@ -1045,7 +1610,7 @@
 		dib0090_write_reg(state, 0x07, state->bb7 & ~0x0008);
 		dib0090_write_reg(state, 0x1f, 0x7);
 		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
-		state->reset &= ~0x1;
+		state->calibrate &= ~DC_CAL;
 	default:
 		break;
 	}
@@ -1054,21 +1619,43 @@
 
 static int dib0090_wbd_calibration(struct dib0090_state *state, enum frontend_tune_state *tune_state)
 {
+	u8 wbd_gain;
+	const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
+
 	switch (*tune_state) {
 	case CT_TUNER_START:
-		/* WBD-mode=log, Bias=2, Gain=6, Testmode=1, en=1, WBDMUX=1 */
-		dib0090_write_reg(state, 0x10, 0xdb09 | (1 << 10));
-		dib0090_write_reg(state, 0x24, EN_UHF & 0x0fff);
+		while (state->current_rf / 1000 > wbd->max_freq)
+			wbd++;
+		if (wbd->wbd_gain != 0)
+			wbd_gain = wbd->wbd_gain;
+		else {
+			wbd_gain = 4;
+#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
+			if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND))
+				wbd_gain = 2;
+#endif
+		}
 
+		if (wbd_gain == state->wbd_calibration_gain) {	/* the WBD calibration has already been done */
+			*tune_state = CT_TUNER_START;
+			state->calibrate &= ~WBD_CAL;
+			return 0;
+		}
+
+		dib0090_write_reg(state, 0x10, 0x1b81 | (1 << 10) | (wbd_gain << 13) | (1 << 3));
+
+		dib0090_write_reg(state, 0x24, ((EN_UHF & 0x0fff) | (1 << 1)));
 		*tune_state = CT_TUNER_STEP_0;
+		state->wbd_calibration_gain = wbd_gain;
 		return 90;	/* wait for the WBDMUX to switch and for the ADC to sample */
+
 	case CT_TUNER_STEP_0:
-		state->wbd_offset = dib0090_read_reg(state, 0x1d);
+		state->wbd_offset = dib0090_get_slow_adc_val(state);
 		dprintk("WBD calibration offset = %d", state->wbd_offset);
-
 		*tune_state = CT_TUNER_START;	/* reset done -> real tuning can now begin */
-		state->reset &= ~0x2;
+		state->calibrate &= ~WBD_CAL;
 		break;
+
 	default:
 		break;
 	}
@@ -1092,6 +1679,15 @@
 	state->bb_1_def |= tmp;
 
 	dib0090_write_reg(state, 0x01, state->bb_1_def);	/* be sure that we have the right bb-filter */
+
+	dib0090_write_reg(state, 0x03, 0x6008);	/* = 0x6008 : vcm3_trim = 1 ; filter2_gm1_trim = 8 ; filter2_cutoff_freq = 0 */
+	dib0090_write_reg(state, 0x04, 0x1);	/* 0 = 1KHz ; 1 = 50Hz ; 2 = 150Hz ; 3 = 50KHz ; 4 = servo fast */
+	if (state->identity.in_soc) {
+		dib0090_write_reg(state, 0x05, 0x9bcf); /* attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 1 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 15 */
+	} else {
+		dib0090_write_reg(state, 0x02, (5 << 11) | (8 << 6) | (22 & 0x3f));	/* 22 = cap_value */
+		dib0090_write_reg(state, 0x05, 0xabcd);	/* = 0xabcd : attenuator_ibias_tri = 2 ; input_stage_ibias_tr = 2 ; nc = 11 ; ext_gm_trim = 1 ; obuf_ibias_trim = 4 ; filter13_gm2_ibias_t = 13 */
+	}
 }
 
 static const struct dib0090_pll dib0090_pll_table[] = {
@@ -1180,6 +1776,255 @@
 #endif
 };
 
+static const struct dib0090_tuning dib0090_p1g_tuning_table[] = {
+#ifdef CONFIG_BAND_CBAND
+	{170000, 4, 1, 0x820f, 0x300, 0x2d22, 0x82cb, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{184000, 1, 1, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{227000, 1, 3, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+	{380000, 1, 7, 15, 0x300, 0x4d12, 0xb94e, EN_VHF},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{510000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{540000, 2, 1, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{600000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{630000, 2, 4, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{680000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{720000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_pll dib0090_p1g_pll_table[] = {
+#ifdef CONFIG_BAND_CBAND
+	{57000, 0, 11, 48, 6},
+	{70000, 1, 11, 48, 6},
+	{86000, 0, 10, 32, 4},
+	{105000, 1, 10, 32, 4},
+	{115000, 0, 9, 24, 6},
+	{140000, 1, 9, 24, 6},
+	{170000, 0, 8, 16, 4},
+#endif
+#ifdef CONFIG_BAND_VHF
+	{200000, 1, 8, 16, 4},
+	{230000, 0, 7, 12, 6},
+	{280000, 1, 7, 12, 6},
+	{340000, 0, 6, 8, 4},
+	{380000, 1, 6, 8, 4},
+	{455000, 0, 5, 6, 6},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{580000, 1, 5, 6, 6},
+	{680000, 0, 4, 4, 4},
+	{860000, 1, 4, 4, 4},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1800000, 1, 2, 2, 4},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2900000, 0, 1, 1, 6},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_p1g_tuning_table_fm_vhf_on_cband[] = {
+#ifdef CONFIG_BAND_CBAND
+	{184000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
+	{227000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
+	{380000, 4, 3, 0x4187, 0x2c0, 0x2d22, 0x81cb, EN_CAB},
+#endif
+#ifdef CONFIG_BAND_UHF
+	{520000, 2, 0, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{550000, 2, 2, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{650000, 2, 3, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{750000, 2, 5, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{850000, 2, 6, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+	{900000, 2, 7, 15, 0x300, 0x1d12, 0xb9ce, EN_UHF},
+#endif
+#ifdef CONFIG_BAND_LBAND
+	{1500000, 4, 0, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1600000, 4, 1, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+	{1800000, 4, 3, 20, 0x300, 0x1912, 0x82c9, EN_LBD},
+#endif
+#ifdef CONFIG_BAND_SBAND
+	{2300000, 1, 4, 20, 0x300, 0x2d2A, 0x82c7, EN_SBD},
+	{2900000, 1, 7, 20, 0x280, 0x2deb, 0x8347, EN_SBD},
+#endif
+};
+
+static const struct dib0090_tuning dib0090_tuning_table_cband_7090[] = {
+#ifdef CONFIG_BAND_CBAND
+	{300000, 4, 3, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+	{380000, 4, 10, 0x018F, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+	{570000, 4, 10, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+	{858000, 4, 5, 0x8190, 0x2c0, 0x2d22, 0xb9ce, EN_CAB},
+#endif
+};
+
+static int dib0090_captrim_search(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = 0;
+	u16 lo4 = 0xe900;
+
+	s16 adc_target;
+	u16 adc;
+	s8 step_sign;
+	u8 force_soft_search = 0;
+
+	if (state->identity.version == SOC_8090_P1G_11R1 || state->identity.version == SOC_8090_P1G_21R1)
+		force_soft_search = 1;
+
+	if (*tune_state == CT_TUNER_START) {
+		dprintk("Start Captrim search : %s", (force_soft_search == 1) ? "FORCE SOFT SEARCH" : "AUTO");
+		dib0090_write_reg(state, 0x10, 0x2B1);
+		dib0090_write_reg(state, 0x1e, 0x0032);
+
+		if (!state->tuner_is_tuned) {
+			/* prepare a complete captrim */
+			if (!state->identity.p1g || force_soft_search)
+				state->step = state->captrim = state->fcaptrim = 64;
+
+			state->current_rf = state->rf_request;
+		} else {	/* we are already tuned to this frequency - the configuration is correct  */
+			if (!state->identity.p1g || force_soft_search) {
+				/* do a minimal captrim even if the frequency has not changed */
+				state->step = 4;
+				state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
+			}
+		}
+		state->adc_diff = 3000;
+		*tune_state = CT_TUNER_STEP_0;
+
+	} else if (*tune_state == CT_TUNER_STEP_0) {
+		if (state->identity.p1g && !force_soft_search) {
+			u8 ratio = 31;
+
+			dib0090_write_reg(state, 0x40, (3 << 7) | (ratio << 2) | (1 << 1) | 1);
+			dib0090_read_reg(state, 0x40);
+			ret = 50;
+		} else {
+			state->step /= 2;
+			dib0090_write_reg(state, 0x18, lo4 | state->captrim);
+
+			if (state->identity.in_soc)
+				ret = 25;
+		}
+		*tune_state = CT_TUNER_STEP_1;
+
+	} else if (*tune_state == CT_TUNER_STEP_1) {
+		if (state->identity.p1g && !force_soft_search) {
+			dib0090_write_reg(state, 0x40, 0x18c | (0 << 1) | 0);
+			dib0090_read_reg(state, 0x40);
+
+			state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7F;
+			dprintk("***Final Captrim= 0x%x", state->fcaptrim);
+			*tune_state = CT_TUNER_STEP_3;
+
+		} else {
+			/* MERGE for all krosus before P1G */
+			adc = dib0090_get_slow_adc_val(state);
+			dprintk("CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) state->captrim, (u32) adc, (u32) (adc) * (u32) 1800 / (u32) 1024);
+
+			if (state->rest == 0 || state->identity.in_soc) {	/* Just for 8090P SOCS where auto captrim HW bug : TO CHECK IN ACI for SOCS !!! if 400 for 8090p SOC => tune issue !!! */
+				adc_target = 200;
+			} else
+				adc_target = 400;
+
+			if (adc >= adc_target) {
+				adc -= adc_target;
+				step_sign = -1;
+			} else {
+				adc = adc_target - adc;
+				step_sign = 1;
+			}
+
+			if (adc < state->adc_diff) {
+				dprintk("CAPTRIM=%d is closer to target (%d/%d)", (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
+				state->adc_diff = adc;
+				state->fcaptrim = state->captrim;
+			}
+
+			state->captrim += step_sign * state->step;
+			if (state->step >= 1)
+				*tune_state = CT_TUNER_STEP_0;
+			else
+				*tune_state = CT_TUNER_STEP_2;
+
+			ret = 25;
+		}
+	} else if (*tune_state == CT_TUNER_STEP_2) {	/* this step is only used by krosus < P1G */
+		/*write the final cptrim config */
+		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
+
+		*tune_state = CT_TUNER_STEP_3;
+
+	} else if (*tune_state == CT_TUNER_STEP_3) {
+		state->calibrate &= ~CAPTRIM_CAL;
+		*tune_state = CT_TUNER_STEP_0;
+	}
+
+	return ret;
+}
+
+static int dib0090_get_temperature(struct dib0090_state *state, enum frontend_tune_state *tune_state)
+{
+	int ret = 15;
+	s16 val;
+
+	switch (*tune_state) {
+	case CT_TUNER_START:
+		state->wbdmux = dib0090_read_reg(state, 0x10);
+		dib0090_write_reg(state, 0x10, (state->wbdmux & ~(0xff << 3)) | (0x8 << 3));
+
+		state->bias = dib0090_read_reg(state, 0x13);
+		dib0090_write_reg(state, 0x13, state->bias | (0x3 << 8));
+
+		*tune_state = CT_TUNER_STEP_0;
+		/* wait for the WBDMUX to switch and for the ADC to sample */
+		break;
+
+	case CT_TUNER_STEP_0:
+		state->adc_diff = dib0090_get_slow_adc_val(state);
+		dib0090_write_reg(state, 0x13, (state->bias & ~(0x3 << 8)) | (0x2 << 8));
+		*tune_state = CT_TUNER_STEP_1;
+		break;
+
+	case CT_TUNER_STEP_1:
+		val = dib0090_get_slow_adc_val(state);
+		state->temperature = ((s16) ((val - state->adc_diff) * 180) >> 8) + 55;
+
+		dprintk("temperature: %d C", state->temperature - 30);
+
+		*tune_state = CT_TUNER_STEP_2;
+		break;
+
+	case CT_TUNER_STEP_2:
+		dib0090_write_reg(state, 0x13, state->bias);
+		dib0090_write_reg(state, 0x10, state->wbdmux);	/* write back original WBDMUX */
+
+		*tune_state = CT_TUNER_START;
+		state->calibrate &= ~TEMP_CAL;
+		if (state->config->analog_output == 0)
+			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
+
+		break;
+
+	default:
+		ret = 0;
+		break;
+	}
+	return ret;
+}
+
 #define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
 static int dib0090_tune(struct dvb_frontend *fe)
 {
@@ -1188,87 +2033,131 @@
 	const struct dib0090_pll *pll = state->current_pll_table_index;
 	enum frontend_tune_state *tune_state = &state->tune_state;
 
-	u32 rf;
-	u16 lo4 = 0xe900, lo5, lo6, Den;
+	u16 lo5, lo6, Den, tmp;
 	u32 FBDiv, Rest, FREF, VCOF_kHz = 0;
-	u16 tmp, adc;
-	int8_t step_sign;
 	int ret = 10;		/* 1ms is the default delay most of the time */
 	u8 c, i;
 
-	state->current_band = (u8) BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000);
-	rf = fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
-							BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->freq_offset_khz_vhf);
-	/* in any case we first need to do a reset if needed */
-	if (state->reset & 0x1)
-		return dib0090_dc_offset_calibration(state, tune_state);
-	else if (state->reset & 0x2)
-		return dib0090_wbd_calibration(state, tune_state);
-
-    /************************* VCO ***************************/
+	/************************* VCO ***************************/
 	/* Default values for FG                                 */
 	/* from these are needed :                               */
 	/* Cp,HFdiv,VCOband,SD,Num,Den,FB and REFDiv             */
 
-#ifdef CONFIG_SYS_ISDBT
-	if (state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1)
-		rf += 850;
-#endif
+	/* in any case we first need to do a calibration if needed */
+	if (*tune_state == CT_TUNER_START) {
+		/* deactivate DataTX before some calibrations */
+		if (state->calibrate & (DC_CAL | TEMP_CAL | WBD_CAL))
+			dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) & ~(1 << 14));
+		else
+			/* Activate DataTX in case a calibration has been done before */
+			if (state->config->analog_output == 0)
+				dib0090_write_reg(state, 0x23, dib0090_read_reg(state, 0x23) | (1 << 14));
+	}
 
-	if (state->current_rf != rf) {
-		state->tuner_is_tuned = 0;
+	if (state->calibrate & DC_CAL)
+		return dib0090_dc_offset_calibration(state, tune_state);
+	else if (state->calibrate & WBD_CAL) {
+		if (state->current_rf == 0)
+			state->current_rf = state->fe->dtv_property_cache.frequency / 1000;
+		return dib0090_wbd_calibration(state, tune_state);
+	} else if (state->calibrate & TEMP_CAL)
+		return dib0090_get_temperature(state, tune_state);
+	else if (state->calibrate & CAPTRIM_CAL)
+		return dib0090_captrim_search(state, tune_state);
 
-		tune = dib0090_tuning_table;
+	if (*tune_state == CT_TUNER_START) {
+		/* if soc and AGC pwm control, disengage mux to be able to R/W access to 0x01 register to set the right filter (cutoff_freq_select) during the tune sequence, otherwise, SOC SERPAR error when accessing to 0x01 */
+		if (state->config->use_pwm_agc && state->identity.in_soc) {
+			tmp = dib0090_read_reg(state, 0x39);
+			if ((tmp >> 10) & 0x1)
+				dib0090_write_reg(state, 0x39, tmp & ~(1 << 10));
+		}
 
-		tmp = (state->revision >> 5) & 0x7;
-		if (tmp == 0x4 || tmp == 0x7) {
-			/* CBAND tuner version for VHF */
-			if (state->current_band == BAND_FM || state->current_band == BAND_VHF) {
-				/* Force CBAND */
-				state->current_band = BAND_CBAND;
-				tune = dib0090_tuning_table_fm_vhf_on_cband;
+		state->current_band = (u8) BAND_OF_FREQUENCY(state->fe->dtv_property_cache.frequency / 1000);
+		state->rf_request =
+			state->fe->dtv_property_cache.frequency / 1000 + (state->current_band ==
+					BAND_UHF ? state->config->freq_offset_khz_uhf : state->config->
+					freq_offset_khz_vhf);
+
+		/* in ISDB-T 1seg we shift tuning frequency */
+		if ((state->fe->dtv_property_cache.delivery_system == SYS_ISDBT && state->fe->dtv_property_cache.isdbt_sb_mode == 1
+					&& state->fe->dtv_property_cache.isdbt_partial_reception == 0)) {
+			const struct dib0090_low_if_offset_table *LUT_offset = state->config->low_if;
+			u8 found_offset = 0;
+			u32 margin_khz = 100;
+
+			if (LUT_offset != NULL) {
+				while (LUT_offset->RF_freq != 0xffff) {
+					if (((state->rf_request > (LUT_offset->RF_freq - margin_khz))
+								&& (state->rf_request < (LUT_offset->RF_freq + margin_khz)))
+							&& LUT_offset->std == state->fe->dtv_property_cache.delivery_system) {
+						state->rf_request += LUT_offset->offset_khz;
+						found_offset = 1;
+						break;
+					}
+					LUT_offset++;
+				}
 			}
+
+			if (found_offset == 0)
+				state->rf_request += 400;
 		}
+		if (state->current_rf != state->rf_request || (state->current_standard != state->fe->dtv_property_cache.delivery_system)) {
+			state->tuner_is_tuned = 0;
+			state->current_rf = 0;
+			state->current_standard = 0;
 
-		pll = dib0090_pll_table;
-		/* Look for the interval */
-		while (rf > tune->max_freq)
-			tune++;
-		while (rf > pll->max_freq)
-			pll++;
-		state->current_tune_table_index = tune;
-		state->current_pll_table_index = pll;
-	}
+			tune = dib0090_tuning_table;
+			if (state->identity.p1g)
+				tune = dib0090_p1g_tuning_table;
 
-	if (*tune_state == CT_TUNER_START) {
+			tmp = (state->identity.version >> 5) & 0x7;
 
-		if (state->tuner_is_tuned == 0)
-			state->current_rf = 0;
+			if (state->identity.in_soc) {
+				if (state->config->force_cband_input) {	/* Use the CBAND input for all band */
+					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF
+							|| state->current_band & BAND_UHF) {
+						state->current_band = BAND_CBAND;
+						tune = dib0090_tuning_table_cband_7090;
+					}
+				} else {	/* Use the CBAND input for all band under UHF */
+					if (state->current_band & BAND_CBAND || state->current_band & BAND_FM || state->current_band & BAND_VHF) {
+						state->current_band = BAND_CBAND;
+						tune = dib0090_tuning_table_cband_7090;
+					}
+				}
+			} else
+			 if (tmp == 0x4 || tmp == 0x7) {
+				/* CBAND tuner version for VHF */
+				if (state->current_band == BAND_FM || state->current_band == BAND_CBAND || state->current_band == BAND_VHF) {
+					state->current_band = BAND_CBAND;	/* Force CBAND */
 
-		if (state->current_rf != rf) {
+					tune = dib0090_tuning_table_fm_vhf_on_cband;
+					if (state->identity.p1g)
+						tune = dib0090_p1g_tuning_table_fm_vhf_on_cband;
+				}
+			}
 
-			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
+			pll = dib0090_pll_table;
+			if (state->identity.p1g)
+				pll = dib0090_p1g_pll_table;
 
-			/* external loop filter, otherwise:
-			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
-			 * lo6 = 0x0e34 */
-			if (pll->vco_band)
-				lo5 = 0x049e;
-			else if (state->config->analog_output)
-				lo5 = 0x041d;
-			else
-				lo5 = 0x041c;
+			/* Look for the interval */
+			while (state->rf_request > tune->max_freq)
+				tune++;
+			while (state->rf_request > pll->max_freq)
+				pll++;
 
-			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
+			state->current_tune_table_index = tune;
+			state->current_pll_table_index = pll;
 
-			if (!state->config->io.pll_int_loop_filt)
-				lo6 = 0xff28;
-			else
-				lo6 = (state->config->io.pll_int_loop_filt << 3);
+			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->switch_trim));
 
-			VCOF_kHz = (pll->hfdiv * rf) * 2;
+			VCOF_kHz = (pll->hfdiv * state->rf_request) * 2;
 
 			FREF = state->config->io.clock_khz;
+			if (state->config->fref_clock_ratio != 0)
+				FREF /= state->config->fref_clock_ratio;
 
 			FBDiv = (VCOF_kHz / pll->topresc / FREF);
 			Rest = (VCOF_kHz / pll->topresc) - FBDiv * FREF;
@@ -1283,144 +2172,132 @@
 			} else if (Rest > (FREF - 2 * LPF))
 				Rest = FREF - 2 * LPF;
 			Rest = (Rest * 6528) / (FREF / 10);
+			state->rest = Rest;
 
-			Den = 1;
+			/* external loop filter, otherwise:
+			 * lo5 = (0 << 15) | (0 << 12) | (0 << 11) | (3 << 9) | (4 << 6) | (3 << 4) | 4;
+			 * lo6 = 0x0e34 */
 
-			dprintk(" *****  ******* Rest value = %d", Rest);
+			if (Rest == 0) {
+				if (pll->vco_band)
+					lo5 = 0x049f;
+				else
+					lo5 = 0x041f;
+			} else {
+				if (pll->vco_band)
+					lo5 = 0x049e;
+				else if (state->config->analog_output)
+					lo5 = 0x041d;
+				else
+					lo5 = 0x041c;
+			}
+
+			if (state->identity.p1g) {	/* Bias is done automatically in P1G */
+				if (state->identity.in_soc) {
+					if (state->identity.version == SOC_8090_P1G_11R1)
+						lo5 = 0x46f;
+					else
+						lo5 = 0x42f;
+				} else
+					lo5 = 0x42c;
+			}
+
+			lo5 |= (pll->hfdiv_code << 11) | (pll->vco_band << 7);	/* bit 15 is the split to the slave, we do not do it here */
+
+			if (!state->config->io.pll_int_loop_filt) {
+				if (state->identity.in_soc)
+					lo6 = 0xff98;
+				else if (state->identity.p1g || (Rest == 0))
+					lo6 = 0xfff8;
+				else
+					lo6 = 0xff28;
+			} else
+				lo6 = (state->config->io.pll_int_loop_filt << 3);
+
+			Den = 1;
 
 			if (Rest > 0) {
 				if (state->config->analog_output)
 					lo6 |= (1 << 2) | 2;
-				else
-					lo6 |= (1 << 2) | 1;
+				else {
+					if (state->identity.in_soc)
+						lo6 |= (1 << 2) | 2;
+					else
+						lo6 |= (1 << 2) | 2;
+				}
 				Den = 255;
 			}
-#ifdef CONFIG_BAND_SBAND
-			if (state->current_band == BAND_SBAND)
-				lo6 &= 0xfffb;
-#endif
-
 			dib0090_write_reg(state, 0x15, (u16) FBDiv);
-
-			dib0090_write_reg(state, 0x16, (Den << 8) | 1);
-
+			if (state->config->fref_clock_ratio != 0)
+				dib0090_write_reg(state, 0x16, (Den << 8) | state->config->fref_clock_ratio);
+			else
+				dib0090_write_reg(state, 0x16, (Den << 8) | 1);
 			dib0090_write_reg(state, 0x17, (u16) Rest);
-
 			dib0090_write_reg(state, 0x19, lo5);
-
 			dib0090_write_reg(state, 0x1c, lo6);
 
 			lo6 = tune->tuner_enable;
 			if (state->config->analog_output)
 				lo6 = (lo6 & 0xff9f) | 0x2;
 
-			dib0090_write_reg(state, 0x24, lo6 | EN_LO
-#ifdef CONFIG_DIB0090_USE_PWM_AGC
-					  | state->config->use_pwm_agc * EN_CRYSTAL
-#endif
-			    );
-
-			state->current_rf = rf;
-
-			/* prepare a complete captrim */
-			state->step = state->captrim = state->fcaptrim = 64;
-
-		} else {	/* we are already tuned to this frequency - the configuration is correct  */
+			dib0090_write_reg(state, 0x24, lo6 | EN_LO | state->config->use_pwm_agc * EN_CRYSTAL);
 
-			/* do a minimal captrim even if the frequency has not changed */
-			state->step = 4;
-			state->captrim = state->fcaptrim = dib0090_read_reg(state, 0x18) & 0x7f;
 		}
-		state->adc_diff = 3000;
 
-		dib0090_write_reg(state, 0x10, 0x2B1);
-
-		dib0090_write_reg(state, 0x1e, 0x0032);
+		state->current_rf = state->rf_request;
+		state->current_standard = state->fe->dtv_property_cache.delivery_system;
 
 		ret = 20;
-		*tune_state = CT_TUNER_STEP_1;
-	} else if (*tune_state == CT_TUNER_STEP_0) {
-		/* nothing */
-	} else if (*tune_state == CT_TUNER_STEP_1) {
-		state->step /= 2;
-		dib0090_write_reg(state, 0x18, lo4 | state->captrim);
-		*tune_state = CT_TUNER_STEP_2;
-	} else if (*tune_state == CT_TUNER_STEP_2) {
-
-		adc = dib0090_read_reg(state, 0x1d);
-		dprintk("FE %d CAPTRIM=%d; ADC = %d (ADC) & %dmV", (u32) fe->id, (u32) state->captrim, (u32) adc,
-			(u32) (adc) * (u32) 1800 / (u32) 1024);
-
-		if (adc >= 400) {
-			adc -= 400;
-			step_sign = -1;
-		} else {
-			adc = 400 - adc;
-			step_sign = 1;
-		}
+		state->calibrate = CAPTRIM_CAL;	/* captrim serach now */
+	}
 
-		if (adc < state->adc_diff) {
-			dprintk("FE %d CAPTRIM=%d is closer to target (%d/%d)", (u32) fe->id, (u32) state->captrim, (u32) adc, (u32) state->adc_diff);
-			state->adc_diff = adc;
-			state->fcaptrim = state->captrim;
+	else if (*tune_state == CT_TUNER_STEP_0) {	/* Warning : because of captrim cal, if you change this step, change it also in _cal.c file because it is the step following captrim cal state machine */
+		const struct dib0090_wbd_slope *wbd = state->current_wbd_table;
 
-		}
+		while (state->current_rf / 1000 > wbd->max_freq)
+			wbd++;
 
-		state->captrim += step_sign * state->step;
-		if (state->step >= 1)
-			*tune_state = CT_TUNER_STEP_1;
-		else
-			*tune_state = CT_TUNER_STEP_3;
+		dib0090_write_reg(state, 0x1e, 0x07ff);
+		dprintk("Final Captrim: %d", (u32) state->fcaptrim);
+		dprintk("HFDIV code: %d", (u32) pll->hfdiv_code);
+		dprintk("VCO = %d", (u32) pll->vco_band);
+		dprintk("VCOF in kHz: %d ((%d*%d) << 1))", (u32) ((pll->hfdiv * state->rf_request) * 2), (u32) pll->hfdiv, (u32) state->rf_request);
+		dprintk("REFDIV: %d, FREF: %d", (u32) 1, (u32) state->config->io.clock_khz);
+		dprintk("FBDIV: %d, Rest: %d", (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
+		dprintk("Num: %d, Den: %d, SD: %d", (u32) dib0090_read_reg(state, 0x17), (u32) (dib0090_read_reg(state, 0x16) >> 8),
+			(u32) dib0090_read_reg(state, 0x1c) & 0x3);
 
-		ret = 15;
-	} else if (*tune_state == CT_TUNER_STEP_3) {
-		/*write the final cptrim config */
-		dib0090_write_reg(state, 0x18, lo4 | state->fcaptrim);
+#define WBD     0x781		/* 1 1 1 1 0000 0 0 1 */
+		c = 4;
+		i = 3;
 
-#ifdef CONFIG_TUNER_DIB0090_CAPTRIM_MEMORY
-		state->memory[state->memory_index].cap = state->fcaptrim;
-#endif
+		if (wbd->wbd_gain != 0)
+			c = wbd->wbd_gain;
 
-		*tune_state = CT_TUNER_STEP_4;
-	} else if (*tune_state == CT_TUNER_STEP_4) {
-		dib0090_write_reg(state, 0x1e, 0x07ff);
+		state->wbdmux = (c << 13) | (i << 11) | (WBD | (state->config->use_pwm_agc << 1));
+		dib0090_write_reg(state, 0x10, state->wbdmux);
 
-		dprintk("FE %d Final Captrim: %d", (u32) fe->id, (u32) state->fcaptrim);
-		dprintk("FE %d HFDIV code: %d", (u32) fe->id, (u32) pll->hfdiv_code);
-		dprintk("FE %d VCO = %d", (u32) fe->id, (u32) pll->vco_band);
-		dprintk("FE %d VCOF in kHz: %d ((%d*%d) << 1))", (u32) fe->id, (u32) ((pll->hfdiv * rf) * 2), (u32) pll->hfdiv, (u32) rf);
-		dprintk("FE %d REFDIV: %d, FREF: %d", (u32) fe->id, (u32) 1, (u32) state->config->io.clock_khz);
-		dprintk("FE %d FBDIV: %d, Rest: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x15), (u32) dib0090_read_reg(state, 0x17));
-		dprintk("FE %d Num: %d, Den: %d, SD: %d", (u32) fe->id, (u32) dib0090_read_reg(state, 0x17),
-			(u32) (dib0090_read_reg(state, 0x16) >> 8), (u32) dib0090_read_reg(state, 0x1c) & 0x3);
+		if ((tune->tuner_enable == EN_CAB) && state->identity.p1g) {
+			dprintk("P1G : The cable band is selected and lna_tune = %d", tune->lna_tune);
+			dib0090_write_reg(state, 0x09, tune->lna_bias);
+			dib0090_write_reg(state, 0x0b, 0xb800 | (tune->lna_tune << 6) | (tune->switch_trim));
+		} else
+			dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | tune->lna_bias);
 
-		c = 4;
-		i = 3;
-#if defined(CONFIG_BAND_LBAND) || defined(CONFIG_BAND_SBAND)
-		if ((state->current_band == BAND_LBAND) || (state->current_band == BAND_SBAND)) {
-			c = 2;
-			i = 2;
-		}
-#endif
-		dib0090_write_reg(state, 0x10, (c << 13) | (i << 11) | (WBD
-#ifdef CONFIG_DIB0090_USE_PWM_AGC
-									| (state->config->use_pwm_agc << 1)
-#endif
-				  ));
-		dib0090_write_reg(state, 0x09, (tune->lna_tune << 5) | (tune->lna_bias << 0));
 		dib0090_write_reg(state, 0x0c, tune->v2i);
 		dib0090_write_reg(state, 0x0d, tune->mix);
 		dib0090_write_reg(state, 0x0e, tune->load);
+		*tune_state = CT_TUNER_STEP_1;
 
-		*tune_state = CT_TUNER_STEP_5;
-	} else if (*tune_state == CT_TUNER_STEP_5) {
-
+	} else if (*tune_state == CT_TUNER_STEP_1) {
 		/* initialize the lt gain register */
 		state->rf_lt_def = 0x7c00;
-		dib0090_write_reg(state, 0x0f, state->rf_lt_def);
 
 		dib0090_set_bandwidth(state);
 		state->tuner_is_tuned = 1;
+
+		state->calibrate |= WBD_CAL;
+		state->calibrate |= TEMP_CAL;
 		*tune_state = CT_TUNER_STOP;
 	} else
 		ret = FE_CALLBACK_TIME_NEVER;
@@ -1440,6 +2317,7 @@
 
 	return state->tune_state;
 }
+
 EXPORT_SYMBOL(dib0090_get_tune_state);
 
 int dib0090_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
@@ -1449,6 +2327,7 @@
 	state->tune_state = tune_state;
 	return 0;
 }
+
 EXPORT_SYMBOL(dib0090_set_tune_state);
 
 static int dib0090_get_frequency(struct dvb_frontend *fe, u32 * frequency)
@@ -1462,7 +2341,7 @@
 static int dib0090_set_params(struct dvb_frontend *fe, struct dvb_frontend_parameters *p)
 {
 	struct dib0090_state *state = fe->tuner_priv;
-	uint32_t ret;
+	u32 ret;
 
 	state->tune_state = CT_TUNER_START;
 
@@ -1492,6 +2371,29 @@
 	.get_frequency = dib0090_get_frequency,
 };
 
+static const struct dvb_tuner_ops dib0090_fw_ops = {
+	.info = {
+		 .name = "DiBcom DiB0090",
+		 .frequency_min = 45000000,
+		 .frequency_max = 860000000,
+		 .frequency_step = 1000,
+		 },
+	.release = dib0090_release,
+
+	.init = NULL,
+	.sleep = NULL,
+	.set_params = NULL,
+	.get_frequency = NULL,
+};
+
+static const struct dib0090_wbd_slope dib0090_wbd_table_default[] = {
+	{470, 0, 250, 0, 100, 4},
+	{860, 51, 866, 21, 375, 4},
+	{1700, 0, 800, 0, 850, 4},
+	{2900, 0, 250, 0, 100, 6},
+	{0xFFFF, 0, 0, 0, 0, 0},
+};
+
 struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
 {
 	struct dib0090_state *st = kzalloc(sizeof(struct dib0090_state), GFP_KERNEL);
@@ -1503,6 +2405,11 @@
 	st->fe = fe;
 	fe->tuner_priv = st;
 
+	if (config->wbd == NULL)
+		st->current_wbd_table = dib0090_wbd_table_default;
+	else
+		st->current_wbd_table = config->wbd;
+
 	if (dib0090_reset(fe) != 0)
 		goto free_mem;
 
@@ -1515,8 +2422,34 @@
 	fe->tuner_priv = NULL;
 	return NULL;
 }
+
 EXPORT_SYMBOL(dib0090_register);
 
+struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config)
+{
+	struct dib0090_fw_state *st = kzalloc(sizeof(struct dib0090_fw_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+
+	st->config = config;
+	st->i2c = i2c;
+	st->fe = fe;
+	fe->tuner_priv = st;
+
+	if (dib0090_fw_reset_digital(fe, st->config) != 0)
+		goto free_mem;
+
+	dprintk("DiB0090 FW: successfully identified");
+	memcpy(&fe->ops.tuner_ops, &dib0090_fw_ops, sizeof(struct dvb_tuner_ops));
+
+	return fe;
+free_mem:
+	kfree(st);
+	fe->tuner_priv = NULL;
+	return NULL;
+}
+EXPORT_SYMBOL(dib0090_fw_register);
+
 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
 MODULE_AUTHOR("Olivier Grenie <olivier.grenie@dibcom.fr>");
 MODULE_DESCRIPTION("Driver for the DiBcom 0090 base-band RF Tuner");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib0090.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib0090.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib0090.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib0090.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,21 @@
 	u16 pll_int_loop_filt;
 };
 
+struct dib0090_wbd_slope {
+	u16 max_freq;		/* for every frequency less than or equal to that field: this information is correct */
+	u16 slope_cold;
+	u16 offset_cold;
+	u16 slope_hot;
+	u16 offset_hot;
+	u8 wbd_gain;
+};
+
+struct dib0090_low_if_offset_table {
+	int std;
+	u32 RF_freq;
+	s32 offset_khz;
+};
+
 struct dib0090_config {
 	struct dib0090_io_config io;
 	int (*reset) (struct dvb_frontend *, int);
@@ -47,10 +62,20 @@
 	u16 wbd_cband_offset;
 	u8 use_pwm_agc;
 	u8 clkoutdrive;
+
+	u8 ls_cfg_pad_drv;
+	u8 data_tx_drv;
+
+	u8 in_soc;
+	const struct dib0090_low_if_offset_table *low_if;
+	u8 fref_clock_ratio;
+	u16 force_cband_input;
+	struct dib0090_wbd_slope *wbd;
 };
 
 #if defined(CONFIG_DVB_TUNER_DIB0090) || (defined(CONFIG_DVB_TUNER_DIB0090_MODULE) && defined(MODULE))
 extern struct dvb_frontend *dib0090_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
+extern struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, const struct dib0090_config *config);
 extern void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast);
 extern void dib0090_pwm_gain_reset(struct dvb_frontend *fe);
 extern u16 dib0090_get_wbd_offset(struct dvb_frontend *tuner);
@@ -63,6 +88,12 @@
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
+}
+
+static inline struct dvb_frontend *dib0090_fw_register(struct dvb_frontend *fe, struct i2c_adapter *i2c, struct dib0090_config *config)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
 }
 
 static inline void dib0090_dcc_freq(struct dvb_frontend *fe, u8 fast)
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib7000p.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib7000p.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib7000p.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib7000p.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,24 +26,29 @@
 
 #define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB7000P: "); printk(args); printk("\n"); } } while (0)
 
+struct i2c_device {
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+};
+
 struct dib7000p_state {
 	struct dvb_frontend demod;
-    struct dib7000p_config cfg;
+	struct dib7000p_config cfg;
 
 	u8 i2c_addr;
-	struct i2c_adapter   *i2c_adap;
+	struct i2c_adapter *i2c_adap;
 
 	struct dibx000_i2c_master i2c_master;
 
 	u16 wbd_ref;
 
-	u8  current_band;
+	u8 current_band;
 	u32 current_bandwidth;
 	struct dibx000_agc_config *current_agc;
 	u32 timf;
 
-	u8 div_force_off : 1;
-	u8 div_state : 1;
+	u8 div_force_off:1;
+	u8 div_state:1;
 	u16 div_sync_wait;
 
 	u8 agc_state;
@@ -51,7 +56,13 @@
 	u16 gpio_dir;
 	u16 gpio_val;
 
-	u8 sfn_workaround_active :1;
+	u8 sfn_workaround_active:1;
+
+#define SOC7090 0x7090
+	u16 version;
+
+	u16 tuner_enable;
+	struct i2c_adapter dib7090_tuner_adap;
 };
 
 enum dib7000p_power_mode {
@@ -60,17 +71,20 @@
 	DIB7000P_POWER_INTERFACE_ONLY,
 };
 
+static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode);
+static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff);
+
 static u16 dib7000p_read_word(struct dib7000p_state *state, u16 reg)
 {
 	u8 wb[2] = { reg >> 8, reg & 0xff };
 	u8 rb[2];
 	struct i2c_msg msg[2] = {
-		{ .addr = state->i2c_addr >> 1, .flags = 0,        .buf = wb, .len = 2 },
-		{ .addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2 },
+		{.addr = state->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
+		{.addr = state->i2c_addr >> 1, .flags = I2C_M_RD, .buf = rb, .len = 2},
 	};
 
 	if (i2c_transfer(state->i2c_adap, msg, 2) != 2)
-		dprintk("i2c read error on %d",reg);
+		dprintk("i2c read error on %d", reg);
 
 	return (rb[0] << 8) | rb[1];
 }
@@ -86,7 +100,8 @@
 	};
 	return i2c_transfer(state->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
 }
-static void dib7000p_write_tab(struct dib7000p_state *state, u16 *buf)
+
+static void dib7000p_write_tab(struct dib7000p_state *state, u16 * buf)
 {
 	u16 l = 0, r, *n;
 	n = buf;
@@ -104,54 +119,54 @@
 
 static int dib7000p_set_output_mode(struct dib7000p_state *state, int mode)
 {
-	int    ret = 0;
+	int ret = 0;
 	u16 outreg, fifo_threshold, smo_mode;
 
 	outreg = 0;
 	fifo_threshold = 1792;
 	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
 
-	dprintk( "setting output mode for demod %p to %d",
-			&state->demod, mode);
+	dprintk("setting output mode for demod %p to %d", &state->demod, mode);
 
 	switch (mode) {
-		case OUTMODE_MPEG2_PAR_GATED_CLK:   // STBs with parallel gated clock
-			outreg = (1 << 10);  /* 0x0400 */
-			break;
-		case OUTMODE_MPEG2_PAR_CONT_CLK:    // STBs with parallel continues clock
-			outreg = (1 << 10) | (1 << 6); /* 0x0440 */
-			break;
-		case OUTMODE_MPEG2_SERIAL:          // STBs with serial input
-			outreg = (1 << 10) | (2 << 6) | (0 << 1); /* 0x0480 */
-			break;
-		case OUTMODE_DIVERSITY:
-			if (state->cfg.hostbus_diversity)
-				outreg = (1 << 10) | (4 << 6); /* 0x0500 */
-			else
-				outreg = (1 << 11);
-			break;
-		case OUTMODE_MPEG2_FIFO:            // e.g. USB feeding
-			smo_mode |= (3 << 1);
-			fifo_threshold = 512;
-			outreg = (1 << 10) | (5 << 6);
-			break;
-		case OUTMODE_ANALOG_ADC:
-			outreg = (1 << 10) | (3 << 6);
-			break;
-		case OUTMODE_HIGH_Z:  // disable
-			outreg = 0;
-			break;
-		default:
-			dprintk( "Unhandled output_mode passed to be set for demod %p",&state->demod);
-			break;
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		outreg = (1 << 10);	/* 0x0400 */
+		break;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
+		break;
+	case OUTMODE_MPEG2_SERIAL:
+		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0480 */
+		break;
+	case OUTMODE_DIVERSITY:
+		if (state->cfg.hostbus_diversity)
+			outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
+		else
+			outreg = (1 << 11);
+		break;
+	case OUTMODE_MPEG2_FIFO:
+		smo_mode |= (3 << 1);
+		fifo_threshold = 512;
+		outreg = (1 << 10) | (5 << 6);
+		break;
+	case OUTMODE_ANALOG_ADC:
+		outreg = (1 << 10) | (3 << 6);
+		break;
+	case OUTMODE_HIGH_Z:
+		outreg = 0;
+		break;
+	default:
+		dprintk("Unhandled output_mode passed to be set for demod %p", &state->demod);
+		break;
 	}
 
 	if (state->cfg.output_mpeg2_in_188_bytes)
-		smo_mode |= (1 << 5) ;
+		smo_mode |= (1 << 5);
 
-	ret |= dib7000p_write_word(state,  235, smo_mode);
-	ret |= dib7000p_write_word(state,  236, fifo_threshold); /* synchronous fread */
-	ret |= dib7000p_write_word(state, 1286, outreg);         /* P_Div_active */
+	ret |= dib7000p_write_word(state, 235, smo_mode);
+	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
+	if (state->version != SOC7090)
+		ret |= dib7000p_write_word(state, 1286, outreg);	/* P_Div_active */
 
 	return ret;
 }
@@ -161,13 +176,13 @@
 	struct dib7000p_state *state = demod->demodulator_priv;
 
 	if (state->div_force_off) {
-		dprintk( "diversity combination deactivated - forced by COFDM parameters");
+		dprintk("diversity combination deactivated - forced by COFDM parameters");
 		onoff = 0;
 		dib7000p_write_word(state, 207, 0);
 	} else
 		dib7000p_write_word(state, 207, (state->div_sync_wait << 4) | (1 << 2) | (2 << 0));
 
-	state->div_state = (u8)onoff;
+	state->div_state = (u8) onoff;
 
 	if (onoff) {
 		dib7000p_write_word(state, 204, 6);
@@ -184,37 +199,48 @@
 static int dib7000p_set_power_mode(struct dib7000p_state *state, enum dib7000p_power_mode mode)
 {
 	/* by default everything is powered off */
-	u16 reg_774 = 0xffff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899  = 0x0003,
-		reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
+	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0x0007, reg_899 = 0x0003, reg_1280 = (0xfe00) | (dib7000p_read_word(state, 1280) & 0x01ff);
 
 	/* now, depending on the requested mode, we power on */
 	switch (mode) {
 		/* power up everything in the demod */
-		case DIB7000P_POWER_ALL:
-			reg_774 = 0x0000; reg_775 = 0x0000; reg_776 = 0x0; reg_899 = 0x0; reg_1280 &= 0x01ff;
-			break;
+	case DIB7000P_POWER_ALL:
+		reg_774 = 0x0000;
+		reg_775 = 0x0000;
+		reg_776 = 0x0;
+		reg_899 = 0x0;
+		if (state->version == SOC7090)
+			reg_1280 &= 0x001f;
+		else
+			reg_1280 &= 0x01ff;
+		break;
 
-		case DIB7000P_POWER_ANALOG_ADC:
-			/* dem, cfg, iqc, sad, agc */
-			reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
-			/* nud */
-			reg_776 &= ~((1 << 0));
-			/* Dout */
+	case DIB7000P_POWER_ANALOG_ADC:
+		/* dem, cfg, iqc, sad, agc */
+		reg_774 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10) | (1 << 9));
+		/* nud */
+		reg_776 &= ~((1 << 0));
+		/* Dout */
+		if (state->version != SOC7090)
 			reg_1280 &= ~((1 << 11));
-			/* fall through wanted to enable the interfaces */
+		reg_1280 &= ~(1 << 6);
+		/* fall through wanted to enable the interfaces */
 
 		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO) */
-		case DIB7000P_POWER_INTERFACE_ONLY: /* TODO power up either SDIO or I2C */
+	case DIB7000P_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C */
+		if (state->version == SOC7090)
+			reg_1280 &= ~((1 << 7) | (1 << 5));
+		else
 			reg_1280 &= ~((1 << 14) | (1 << 13) | (1 << 12) | (1 << 10));
-			break;
+		break;
 
 /* TODO following stuff is just converted from the dib7000-driver - check when is used what */
 	}
 
-	dib7000p_write_word(state,  774,  reg_774);
-	dib7000p_write_word(state,  775,  reg_775);
-	dib7000p_write_word(state,  776,  reg_776);
-	dib7000p_write_word(state,  899,  reg_899);
+	dib7000p_write_word(state, 774, reg_774);
+	dib7000p_write_word(state, 775, reg_775);
+	dib7000p_write_word(state, 776, reg_776);
+	dib7000p_write_word(state, 899, reg_899);
 	dib7000p_write_word(state, 1280, reg_1280);
 
 	return 0;
@@ -222,40 +248,57 @@
 
 static void dib7000p_set_adc_state(struct dib7000p_state *state, enum dibx000_adc_states no)
 {
-	u16 reg_908 = dib7000p_read_word(state, 908),
-	       reg_909 = dib7000p_read_word(state, 909);
+	u16 reg_908 = dib7000p_read_word(state, 908), reg_909 = dib7000p_read_word(state, 909);
+	u16 reg;
 
 	switch (no) {
-		case DIBX000_SLOW_ADC_ON:
+	case DIBX000_SLOW_ADC_ON:
+		if (state->version == SOC7090) {
+			reg = dib7000p_read_word(state, 1925);
+
+			dib7000p_write_word(state, 1925, reg | (1 << 4) | (1 << 2));	/* en_slowAdc = 1 & reset_sladc = 1 */
+
+			reg = dib7000p_read_word(state, 1925);	/* read acces to make it works... strange ... */
+			msleep(200);
+			dib7000p_write_word(state, 1925, reg & ~(1 << 4));	/* en_slowAdc = 1 & reset_sladc = 0 */
+
+			reg = dib7000p_read_word(state, 72) & ~((0x3 << 14) | (0x3 << 12));
+			dib7000p_write_word(state, 72, reg | (1 << 14) | (3 << 12) | 524);	/* ref = Vin1 => Vbg ; sel = Vin0 or Vin3 ; (Vin2 = Vcm) */
+		} else {
 			reg_909 |= (1 << 1) | (1 << 0);
 			dib7000p_write_word(state, 909, reg_909);
 			reg_909 &= ~(1 << 1);
-			break;
+		}
+		break;
 
-		case DIBX000_SLOW_ADC_OFF:
-			reg_909 |=  (1 << 1) | (1 << 0);
-			break;
+	case DIBX000_SLOW_ADC_OFF:
+		if (state->version == SOC7090) {
+			reg = dib7000p_read_word(state, 1925);
+			dib7000p_write_word(state, 1925, (reg & ~(1 << 2)) | (1 << 4));	/* reset_sladc = 1 en_slowAdc = 0 */
+		} else
+			reg_909 |= (1 << 1) | (1 << 0);
+		break;
 
-		case DIBX000_ADC_ON:
-			reg_908 &= 0x0fff;
-			reg_909 &= 0x0003;
-			break;
+	case DIBX000_ADC_ON:
+		reg_908 &= 0x0fff;
+		reg_909 &= 0x0003;
+		break;
 
-		case DIBX000_ADC_OFF: // leave the VBG voltage on
-			reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
-			reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
-			break;
+	case DIBX000_ADC_OFF:
+		reg_908 |= (1 << 14) | (1 << 13) | (1 << 12);
+		reg_909 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+		break;
 
-		case DIBX000_VBG_ENABLE:
-			reg_908 &= ~(1 << 15);
-			break;
+	case DIBX000_VBG_ENABLE:
+		reg_908 &= ~(1 << 15);
+		break;
 
-		case DIBX000_VBG_DISABLE:
-			reg_908 |= (1 << 15);
-			break;
+	case DIBX000_VBG_DISABLE:
+		reg_908 |= (1 << 15);
+		break;
 
-		default:
-			break;
+	default:
+		break;
 	}
 
 //	dprintk( "908: %x, 909: %x\n", reg_908, reg_909);
@@ -275,17 +318,17 @@
 	state->current_bandwidth = bw;
 
 	if (state->timf == 0) {
-		dprintk( "using default timf");
+		dprintk("using default timf");
 		timf = state->cfg.bw->timf;
 	} else {
-		dprintk( "using updated timf");
+		dprintk("using updated timf");
 		timf = state->timf;
 	}
 
 	timf = timf * (bw / 50) / 160;
 
 	dib7000p_write_word(state, 23, (u16) ((timf >> 16) & 0xffff));
-	dib7000p_write_word(state, 24, (u16) ((timf      ) & 0xffff));
+	dib7000p_write_word(state, 24, (u16) ((timf) & 0xffff));
 
 	return 0;
 }
@@ -293,9 +336,12 @@
 static int dib7000p_sad_calib(struct dib7000p_state *state)
 {
 /* internal */
-//	dib7000p_write_word(state, 72, (3 << 14) | (1 << 12) | (524 << 0)); // sampling clock of the SAD is writting in set_bandwidth
 	dib7000p_write_word(state, 73, (0 << 1) | (0 << 0));
-	dib7000p_write_word(state, 74, 776); // 0.625*3.3 / 4096
+
+	if (state->version == SOC7090)
+		dib7000p_write_word(state, 74, 2048);
+	else
+		dib7000p_write_word(state, 74, 776);
 
 	/* do the calibration */
 	dib7000p_write_word(state, 73, (1 << 0));
@@ -314,37 +360,91 @@
 	state->wbd_ref = value;
 	return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
 }
-
 EXPORT_SYMBOL(dib7000p_set_wbd_ref);
+
 static void dib7000p_reset_pll(struct dib7000p_state *state)
 {
 	struct dibx000_bandwidth_config *bw = &state->cfg.bw[0];
 	u16 clk_cfg0;
 
-	/* force PLL bypass */
-	clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
-		(bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) |
-		(bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
+	if (state->version == SOC7090) {
+		dib7000p_write_word(state, 1856, (!bw->pll_reset << 13) | (bw->pll_range << 12) | (bw->pll_ratio << 6) | (bw->pll_prediv));
 
-	dib7000p_write_word(state, 900, clk_cfg0);
+		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
+			;
 
-	/* P_pll_cfg */
-	dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
-	clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
-	dib7000p_write_word(state, 900, clk_cfg0);
+		dib7000p_write_word(state, 1857, dib7000p_read_word(state, 1857) | (!bw->pll_bypass << 15));
+	} else {
+		/* force PLL bypass */
+		clk_cfg0 = (1 << 15) | ((bw->pll_ratio & 0x3f) << 9) |
+			(bw->modulo << 7) | (bw->ADClkSrc << 6) | (bw->IO_CLK_en_core << 5) | (bw->bypclk_div << 2) | (bw->enable_refdiv << 1) | (0 << 0);
 
-	dib7000p_write_word(state, 18, (u16) (((bw->internal*1000) >> 16) & 0xffff));
-	dib7000p_write_word(state, 19, (u16) ( (bw->internal*1000       ) & 0xffff));
-	dib7000p_write_word(state, 21, (u16) ( (bw->ifreq          >> 16) & 0xffff));
-	dib7000p_write_word(state, 22, (u16) ( (bw->ifreq               ) & 0xffff));
+		dib7000p_write_word(state, 900, clk_cfg0);
+
+		/* P_pll_cfg */
+		dib7000p_write_word(state, 903, (bw->pll_prediv << 5) | (((bw->pll_ratio >> 6) & 0x3) << 3) | (bw->pll_range << 1) | bw->pll_reset);
+		clk_cfg0 = (bw->pll_bypass << 15) | (clk_cfg0 & 0x7fff);
+		dib7000p_write_word(state, 900, clk_cfg0);
+	}
+
+	dib7000p_write_word(state, 18, (u16) (((bw->internal * 1000) >> 16) & 0xffff));
+	dib7000p_write_word(state, 19, (u16) ((bw->internal * 1000) & 0xffff));
+	dib7000p_write_word(state, 21, (u16) ((bw->ifreq >> 16) & 0xffff));
+	dib7000p_write_word(state, 22, (u16) ((bw->ifreq) & 0xffff));
 
 	dib7000p_write_word(state, 72, bw->sad_cfg);
 }
 
+static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
+{
+	u32 internal = (u32) dib7000p_read_word(state, 18) << 16;
+	internal |= (u32) dib7000p_read_word(state, 19);
+	internal /= 1000;
+
+	return internal;
+}
+
+int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
+	u8 loopdiv, prediv;
+	u32 internal, xtal;
+
+	/* get back old values */
+	prediv = reg_1856 & 0x3f;
+	loopdiv = (reg_1856 >> 6) & 0x3f;
+
+	if ((bw != NULL) && (bw->pll_prediv != prediv || bw->pll_ratio != loopdiv)) {
+		dprintk("Updating pll (prediv: old =  %d new = %d ; loopdiv : old = %d new = %d)", prediv, bw->pll_prediv, loopdiv, bw->pll_ratio);
+		reg_1856 &= 0xf000;
+		reg_1857 = dib7000p_read_word(state, 1857);
+		dib7000p_write_word(state, 1857, reg_1857 & ~(1 << 15));
+
+		dib7000p_write_word(state, 1856, reg_1856 | ((bw->pll_ratio & 0x3f) << 6) | (bw->pll_prediv & 0x3f));
+
+		/* write new system clk into P_sec_len */
+		internal = dib7000p_get_internal_freq(state);
+		xtal = (internal / loopdiv) * prediv;
+		internal = 1000 * (xtal / bw->pll_prediv) * bw->pll_ratio;	/* new internal */
+		dib7000p_write_word(state, 18, (u16) ((internal >> 16) & 0xffff));
+		dib7000p_write_word(state, 19, (u16) (internal & 0xffff));
+
+		dib7000p_write_word(state, 1857, reg_1857 | (1 << 15));
+
+		while (((dib7000p_read_word(state, 1856) >> 15) & 0x1) != 1)
+			dprintk("Waiting for PLL to lock");
+
+		return 0;
+	}
+	return -EIO;
+}
+EXPORT_SYMBOL(dib7000p_update_pll);
+
 static int dib7000p_reset_gpio(struct dib7000p_state *st)
 {
 	/* reset the GPIOs */
-	dprintk( "gpio dir: %x: val: %x, pwm_pos: %x",st->gpio_dir, st->gpio_val,st->cfg.gpio_pwm_pos);
+	dprintk("gpio dir: %x: val: %x, pwm_pos: %x", st->gpio_dir, st->gpio_val, st->cfg.gpio_pwm_pos);
 
 	dib7000p_write_word(st, 1029, st->gpio_dir);
 	dib7000p_write_word(st, 1030, st->gpio_val);
@@ -360,13 +460,13 @@
 static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
 {
 	st->gpio_dir = dib7000p_read_word(st, 1029);
-	st->gpio_dir &= ~(1 << num);         /* reset the direction bit */
-	st->gpio_dir |=  (dir & 0x1) << num; /* set the new direction */
+	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
 	dib7000p_write_word(st, 1029, st->gpio_dir);
 
 	st->gpio_val = dib7000p_read_word(st, 1030);
-	st->gpio_val &= ~(1 << num);          /* reset the direction bit */
-	st->gpio_val |=  (val & 0x01) << num; /* set the new value */
+	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
 	dib7000p_write_word(st, 1030, st->gpio_val);
 
 	return 0;
@@ -377,96 +477,94 @@
 	struct dib7000p_state *state = demod->demodulator_priv;
 	return dib7000p_cfg_gpio(state, num, dir, val);
 }
-
 EXPORT_SYMBOL(dib7000p_set_gpio);
-static u16 dib7000p_defaults[] =
 
-{
+static u16 dib7000p_defaults[] = {
 	// auto search configuration
 	3, 2,
-		0x0004,
-		0x1000,
-		0x0814, /* Equal Lock */
+	0x0004,
+	0x1000,
+	0x0814,			/* Equal Lock */
 
 	12, 6,
-		0x001b,
-		0x7740,
-		0x005b,
-		0x8d80,
-		0x01c9,
-		0xc380,
-		0x0000,
-		0x0080,
-		0x0000,
-		0x0090,
-		0x0001,
-		0xd4c0,
+	0x001b,
+	0x7740,
+	0x005b,
+	0x8d80,
+	0x01c9,
+	0xc380,
+	0x0000,
+	0x0080,
+	0x0000,
+	0x0090,
+	0x0001,
+	0xd4c0,
 
 	1, 26,
-		0x6680, // P_timf_alpha=6, P_corm_alpha=6, P_corm_thres=128 default: 6,4,26
+	0x6680,
 
 	/* set ADC level to -16 */
 	11, 79,
-		(1 << 13) - 825 - 117,
-		(1 << 13) - 837 - 117,
-		(1 << 13) - 811 - 117,
-		(1 << 13) - 766 - 117,
-		(1 << 13) - 737 - 117,
-		(1 << 13) - 693 - 117,
-		(1 << 13) - 648 - 117,
-		(1 << 13) - 619 - 117,
-		(1 << 13) - 575 - 117,
-		(1 << 13) - 531 - 117,
-		(1 << 13) - 501 - 117,
+	(1 << 13) - 825 - 117,
+	(1 << 13) - 837 - 117,
+	(1 << 13) - 811 - 117,
+	(1 << 13) - 766 - 117,
+	(1 << 13) - 737 - 117,
+	(1 << 13) - 693 - 117,
+	(1 << 13) - 648 - 117,
+	(1 << 13) - 619 - 117,
+	(1 << 13) - 575 - 117,
+	(1 << 13) - 531 - 117,
+	(1 << 13) - 501 - 117,
 
 	1, 142,
-		0x0410, // P_palf_filter_on=1, P_palf_filter_freeze=0, P_palf_alpha_regul=16
+	0x0410,
 
 	/* disable power smoothing */
 	8, 145,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
-		0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
 
 	1, 154,
-		1 << 13, // P_fft_freq_dir=1, P_fft_nb_to_cut=0
+	1 << 13,
 
 	1, 168,
-		0x0ccd, // P_pha3_thres, default 0x3000
-
-//	1, 169,
-//		0x0010, // P_cti_use_cpe=0, P_cti_use_prog=0, P_cti_win_len=16, default: 0x0010
+	0x0ccd,
 
 	1, 183,
-		0x200f, // P_cspu_regul=512, P_cspu_win_cut=15, default: 0x2005
+	0x200f,
+
+	1, 212,
+		0x169,
 
 	5, 187,
-		0x023d, // P_adp_regul_cnt=573, default: 410
-		0x00a4, // P_adp_noise_cnt=
-		0x00a4, // P_adp_regul_ext
-		0x7ff0, // P_adp_noise_ext
-		0x3ccc, // P_adp_fil
+	0x023d,
+	0x00a4,
+	0x00a4,
+	0x7ff0,
+	0x3ccc,
 
 	1, 198,
-		0x800, // P_equal_thres_wgn
+	0x800,
 
 	1, 222,
-		0x0010, // P_fec_ber_rs_len=2
+	0x0010,
 
 	1, 235,
-		0x0062, // P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+	0x0062,
 
 	2, 901,
-		0x0006, // P_clk_cfg1
-		(3 << 10) | (1 << 6), // P_divclksel=3 P_divbitsel=1
+	0x0006,
+	(3 << 10) | (1 << 6),
 
 	1, 905,
-		0x2c8e, // Tuner IO bank: max drive (14mA) + divout pads max drive
+	0x2c8e,
 
 	0,
 };
@@ -475,51 +573,64 @@
 {
 	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
 
+	if (state->version == SOC7090)
+		dibx000_reset_i2c_master(&state->i2c_master);
+
 	dib7000p_set_adc_state(state, DIBX000_VBG_ENABLE);
 
 	/* restart all parts */
-	dib7000p_write_word(state,  770, 0xffff);
-	dib7000p_write_word(state,  771, 0xffff);
-	dib7000p_write_word(state,  772, 0x001f);
-	dib7000p_write_word(state,  898, 0x0003);
-	/* except i2c, sdio, gpio - control interfaces */
-	dib7000p_write_word(state, 1280, 0x01fc - ((1 << 7) | (1 << 6) | (1 << 5)) );
+	dib7000p_write_word(state, 770, 0xffff);
+	dib7000p_write_word(state, 771, 0xffff);
+	dib7000p_write_word(state, 772, 0x001f);
+	dib7000p_write_word(state, 898, 0x0003);
+	dib7000p_write_word(state, 1280, 0x001f - ((1 << 4) | (1 << 3)));
 
-	dib7000p_write_word(state,  770, 0);
-	dib7000p_write_word(state,  771, 0);
-	dib7000p_write_word(state,  772, 0);
-	dib7000p_write_word(state,  898, 0);
+	dib7000p_write_word(state, 770, 0);
+	dib7000p_write_word(state, 771, 0);
+	dib7000p_write_word(state, 772, 0);
+	dib7000p_write_word(state, 898, 0);
 	dib7000p_write_word(state, 1280, 0);
 
 	/* default */
 	dib7000p_reset_pll(state);
 
 	if (dib7000p_reset_gpio(state) != 0)
-		dprintk( "GPIO reset was not successful.");
-
-	if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
-		dprintk( "OUTPUT_MODE could not be reset.");
+		dprintk("GPIO reset was not successful.");
 
-	/* unforce divstr regardless whether i2c enumeration was done or not */
-	dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1) );
+	if (state->version == SOC7090) {
+		dib7000p_write_word(state, 899, 0);
 
-	dib7000p_set_bandwidth(state, 8000);
+		/* impulse noise */
+		dib7000p_write_word(state, 42, (1<<5) | 3); /* P_iqc_thsat_ipc = 1 ; P_iqc_win2 = 3 */
+		dib7000p_write_word(state, 43, 0x2d4); /*-300 fag P_iqc_dect_min = -280 */
+		dib7000p_write_word(state, 44, 300); /* 300 fag P_iqc_dect_min = +280 */
+		dib7000p_write_word(state, 273, (1<<6) | 30);
+	}
+	if (dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+		dprintk("OUTPUT_MODE could not be reset.");
 
 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
 	dib7000p_sad_calib(state);
 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_OFF);
 
-	// P_iqc_alpha_pha, P_iqc_alpha_amp_dcc_alpha, ...
-	if(state->cfg.tuner_is_baseband)
-		dib7000p_write_word(state, 36,0x0755);
-	else
-		dib7000p_write_word(state, 36,0x1f55);
+	/* unforce divstr regardless whether i2c enumeration was done or not */
+	dib7000p_write_word(state, 1285, dib7000p_read_word(state, 1285) & ~(1 << 1));
+
+	dib7000p_set_bandwidth(state, 8000);
+
+	if (state->version == SOC7090) {
+		dib7000p_write_word(state, 36, 0x5755);/* P_iqc_impnc_on =1 & P_iqc_corr_inh = 1 for impulsive noise */
+	} else {
+		if (state->cfg.tuner_is_baseband)
+			dib7000p_write_word(state, 36, 0x0755);
+		else
+			dib7000p_write_word(state, 36, 0x1f55);
+	}
 
 	dib7000p_write_tab(state, dib7000p_defaults);
 
 	dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
 
-
 	return 0;
 }
 
@@ -527,9 +638,9 @@
 {
 	u16 tmp = 0;
 	tmp = dib7000p_read_word(state, 903);
-	dib7000p_write_word(state, 903, (tmp | 0x1));   //pwr-up pll
+	dib7000p_write_word(state, 903, (tmp | 0x1));
 	tmp = dib7000p_read_word(state, 900);
-	dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));     //use High freq clock
+	dib7000p_write_word(state, 900, (tmp & 0x7fff) | (1 << 6));
 }
 
 static void dib7000p_restart_agc(struct dib7000p_state *state)
@@ -543,11 +654,9 @@
 {
 	u16 dyn_gain;
 
-	// when there is no LNA to program return immediatly
 	if (state->cfg.update_lna) {
-		// read dyn_gain here (because it is demod-dependent and not fe)
 		dyn_gain = dib7000p_read_word(state, 394);
-		if (state->cfg.update_lna(&state->demod,dyn_gain)) { // LNA has changed
+		if (state->cfg.update_lna(&state->demod, dyn_gain)) {
 			dib7000p_restart_agc(state);
 			return 1;
 		}
@@ -571,24 +680,24 @@
 		}
 
 	if (agc == NULL) {
-		dprintk( "no valid AGC configuration found for band 0x%02x",band);
+		dprintk("no valid AGC configuration found for band 0x%02x", band);
 		return -EINVAL;
 	}
 
 	state->current_agc = agc;
 
 	/* AGC */
-	dib7000p_write_word(state, 75 ,  agc->setup );
-	dib7000p_write_word(state, 76 ,  agc->inv_gain );
-	dib7000p_write_word(state, 77 ,  agc->time_stabiliz );
+	dib7000p_write_word(state, 75, agc->setup);
+	dib7000p_write_word(state, 76, agc->inv_gain);
+	dib7000p_write_word(state, 77, agc->time_stabiliz);
 	dib7000p_write_word(state, 100, (agc->alpha_level << 12) | agc->thlock);
 
 	// Demod AGC loop configuration
 	dib7000p_write_word(state, 101, (agc->alpha_mant << 5) | agc->alpha_exp);
-	dib7000p_write_word(state, 102, (agc->beta_mant << 6)  | agc->beta_exp);
+	dib7000p_write_word(state, 102, (agc->beta_mant << 6) | agc->beta_exp);
 
 	/* AGC continued */
-	dprintk( "WBD: ref: %d, sel: %d, active: %d, alpha: %d",
+	dprintk("WBD: ref: %d, sel: %d, active: %d, alpha: %d",
 		state->wbd_ref != 0 ? state->wbd_ref : agc->wbd_ref, agc->wbd_sel, !agc->perform_agc_softsplit, agc->wbd_sel);
 
 	if (state->wbd_ref != 0)
@@ -598,101 +707,135 @@
 
 	dib7000p_write_word(state, 106, (agc->wbd_sel << 13) | (agc->wbd_alpha << 9) | (agc->perform_agc_softsplit << 8));
 
-	dib7000p_write_word(state, 107,  agc->agc1_max);
-	dib7000p_write_word(state, 108,  agc->agc1_min);
-	dib7000p_write_word(state, 109,  agc->agc2_max);
-	dib7000p_write_word(state, 110,  agc->agc2_min);
-	dib7000p_write_word(state, 111, (agc->agc1_pt1    << 8) | agc->agc1_pt2);
-	dib7000p_write_word(state, 112,  agc->agc1_pt3);
+	dib7000p_write_word(state, 107, agc->agc1_max);
+	dib7000p_write_word(state, 108, agc->agc1_min);
+	dib7000p_write_word(state, 109, agc->agc2_max);
+	dib7000p_write_word(state, 110, agc->agc2_min);
+	dib7000p_write_word(state, 111, (agc->agc1_pt1 << 8) | agc->agc1_pt2);
+	dib7000p_write_word(state, 112, agc->agc1_pt3);
 	dib7000p_write_word(state, 113, (agc->agc1_slope1 << 8) | agc->agc1_slope2);
-	dib7000p_write_word(state, 114, (agc->agc2_pt1    << 8) | agc->agc2_pt2);
+	dib7000p_write_word(state, 114, (agc->agc2_pt1 << 8) | agc->agc2_pt2);
 	dib7000p_write_word(state, 115, (agc->agc2_slope1 << 8) | agc->agc2_slope2);
 	return 0;
 }
 
+static void dib7000p_set_dds(struct dib7000p_state *state, s32 offset_khz)
+{
+	u32 internal = dib7000p_get_internal_freq(state);
+	s32 unit_khz_dds_val = 67108864 / (internal);	/* 2**26 / Fsampling is the unit 1KHz offset */
+	u32 abs_offset_khz = ABS(offset_khz);
+	u32 dds = state->cfg.bw->ifreq & 0x1ffffff;
+	u8 invert = !!(state->cfg.bw->ifreq & (1 << 25));
+
+	dprintk("setting a frequency offset of %dkHz internal freq = %d invert = %d", offset_khz, internal, invert);
+
+	if (offset_khz < 0)
+		unit_khz_dds_val *= -1;
+
+	/* IF tuner */
+	if (invert)
+		dds -= (abs_offset_khz * unit_khz_dds_val);	/* /100 because of /100 on the unit_khz_dds_val line calc for better accuracy */
+	else
+		dds += (abs_offset_khz * unit_khz_dds_val);
+
+	if (abs_offset_khz <= (internal / 2)) {	/* Max dds offset is the half of the demod freq */
+		dib7000p_write_word(state, 21, (u16) (((dds >> 16) & 0x1ff) | (0 << 10) | (invert << 9)));
+		dib7000p_write_word(state, 22, (u16) (dds & 0xffff));
+	}
+}
+
 static int dib7000p_agc_startup(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
 {
 	struct dib7000p_state *state = demod->demodulator_priv;
 	int ret = -1;
 	u8 *agc_state = &state->agc_state;
 	u8 agc_split;
+	u16 reg;
+	u32 upd_demod_gain_period = 0x1000;
 
 	switch (state->agc_state) {
-		case 0:
-			// set power-up level: interf+analog+AGC
-			dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+	case 0:
+		dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
+		if (state->version == SOC7090) {
+			reg = dib7000p_read_word(state, 0x79b) & 0xff00;
+			dib7000p_write_word(state, 0x79a, upd_demod_gain_period & 0xFFFF);	/* lsb */
+			dib7000p_write_word(state, 0x79b, reg | (1 << 14) | ((upd_demod_gain_period >> 16) & 0xFF));
+
+			/* enable adc i & q */
+			reg = dib7000p_read_word(state, 0x780);
+			dib7000p_write_word(state, 0x780, (reg | (0x3)) & (~(1 << 7)));
+		} else {
 			dib7000p_set_adc_state(state, DIBX000_ADC_ON);
 			dib7000p_pll_clk_cfg(state);
+		}
 
-			if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency/1000)) != 0)
-				return -1;
-
-			ret = 7;
-			(*agc_state)++;
-			break;
-
-		case 1:
-			// AGC initialization
-			if (state->cfg.agc_control)
-				state->cfg.agc_control(&state->demod, 1);
+		if (dib7000p_set_agc_config(state, BAND_OF_FREQUENCY(ch->frequency / 1000)) != 0)
+			return -1;
 
-			dib7000p_write_word(state, 78, 32768);
-			if (!state->current_agc->perform_agc_softsplit) {
-				/* we are using the wbd - so slow AGC startup */
-				/* force 0 split on WBD and restart AGC */
-				dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
-				(*agc_state)++;
-				ret = 5;
-			} else {
-				/* default AGC startup */
-				(*agc_state) = 4;
-				/* wait AGC rough lock time */
-				ret = 7;
-			}
+		dib7000p_set_dds(state, 0);
+		ret = 7;
+		(*agc_state)++;
+		break;
 
-			dib7000p_restart_agc(state);
-			break;
+	case 1:
+		if (state->cfg.agc_control)
+			state->cfg.agc_control(&state->demod, 1);
 
-		case 2: /* fast split search path after 5sec */
-			dib7000p_write_word(state,  75, state->current_agc->setup | (1 << 4)); /* freeze AGC loop */
-			dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8)); /* fast split search 0.25kHz */
+		dib7000p_write_word(state, 78, 32768);
+		if (!state->current_agc->perform_agc_softsplit) {
+			/* we are using the wbd - so slow AGC startup */
+			/* force 0 split on WBD and restart AGC */
+			dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | (1 << 8));
 			(*agc_state)++;
-			ret = 14;
-			break;
+			ret = 5;
+		} else {
+			/* default AGC startup */
+			(*agc_state) = 4;
+			/* wait AGC rough lock time */
+			ret = 7;
+		}
 
-	case 3: /* split search ended */
-			agc_split = (u8)dib7000p_read_word(state, 396); /* store the split value for the next time */
-			dib7000p_write_word(state, 78, dib7000p_read_word(state, 394)); /* set AGC gain start value */
+		dib7000p_restart_agc(state);
+		break;
 
-			dib7000p_write_word(state, 75,  state->current_agc->setup);   /* std AGC loop */
-			dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split); /* standard split search */
+	case 2:		/* fast split search path after 5sec */
+		dib7000p_write_word(state, 75, state->current_agc->setup | (1 << 4));	/* freeze AGC loop */
+		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (2 << 9) | (0 << 8));	/* fast split search 0.25kHz */
+		(*agc_state)++;
+		ret = 14;
+		break;
 
-			dib7000p_restart_agc(state);
+	case 3:		/* split search ended */
+		agc_split = (u8) dib7000p_read_word(state, 396);	/* store the split value for the next time */
+		dib7000p_write_word(state, 78, dib7000p_read_word(state, 394));	/* set AGC gain start value */
 
-			dprintk( "SPLIT %p: %hd", demod, agc_split);
+		dib7000p_write_word(state, 75, state->current_agc->setup);	/* std AGC loop */
+		dib7000p_write_word(state, 106, (state->current_agc->wbd_sel << 13) | (state->current_agc->wbd_alpha << 9) | agc_split);	/* standard split search */
 
-			(*agc_state)++;
-			ret = 5;
-			break;
+		dib7000p_restart_agc(state);
 
-		case 4: /* LNA startup */
-			// wait AGC accurate lock time
-			ret = 7;
+		dprintk("SPLIT %p: %hd", demod, agc_split);
 
-			if (dib7000p_update_lna(state))
-				// wait only AGC rough lock time
-				ret = 5;
-			else // nothing was done, go to the next state
-				(*agc_state)++;
-			break;
+		(*agc_state)++;
+		ret = 5;
+		break;
 
-		case 5:
-			if (state->cfg.agc_control)
-				state->cfg.agc_control(&state->demod, 0);
+	case 4:		/* LNA startup */
+		ret = 7;
+
+		if (dib7000p_update_lna(state))
+			ret = 5;
+		else
 			(*agc_state)++;
-			break;
-		default:
-			break;
+		break;
+
+	case 5:
+		if (state->cfg.agc_control)
+			state->cfg.agc_control(&state->demod, 0);
+		(*agc_state)++;
+		break;
+	default:
+		break;
 	}
 	return ret;
 }
@@ -703,45 +846,89 @@
 	state->timf = timf * 160 / (state->current_bandwidth / 50);
 	dib7000p_write_word(state, 23, (u16) (timf >> 16));
 	dib7000p_write_word(state, 24, (u16) (timf & 0xffff));
-	dprintk( "updated timf_frequency: %d (default: %d)",state->timf, state->cfg.bw->timf);
+	dprintk("updated timf_frequency: %d (default: %d)", state->timf, state->cfg.bw->timf);
+
+}
 
+u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	switch (op) {
+	case DEMOD_TIMF_SET:
+		state->timf = timf;
+		break;
+	case DEMOD_TIMF_UPDATE:
+		dib7000p_update_timf(state);
+		break;
+	case DEMOD_TIMF_GET:
+		break;
+	}
+	dib7000p_set_bandwidth(state, state->current_bandwidth);
+	return state->timf;
 }
+EXPORT_SYMBOL(dib7000p_ctrl_timf);
 
 static void dib7000p_set_channel(struct dib7000p_state *state, struct dvb_frontend_parameters *ch, u8 seq)
 {
 	u16 value, est[4];
 
-    dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
 
 	/* nfft, guard, qam, alpha */
 	value = 0;
 	switch (ch->u.ofdm.transmission_mode) {
-		case TRANSMISSION_MODE_2K: value |= (0 << 7); break;
-		case TRANSMISSION_MODE_4K: value |= (2 << 7); break;
-		default:
-		case TRANSMISSION_MODE_8K: value |= (1 << 7); break;
+	case TRANSMISSION_MODE_2K:
+		value |= (0 << 7);
+		break;
+	case TRANSMISSION_MODE_4K:
+		value |= (2 << 7);
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		value |= (1 << 7);
+		break;
 	}
 	switch (ch->u.ofdm.guard_interval) {
-		case GUARD_INTERVAL_1_32: value |= (0 << 5); break;
-		case GUARD_INTERVAL_1_16: value |= (1 << 5); break;
-		case GUARD_INTERVAL_1_4:  value |= (3 << 5); break;
-		default:
-		case GUARD_INTERVAL_1_8:  value |= (2 << 5); break;
+	case GUARD_INTERVAL_1_32:
+		value |= (0 << 5);
+		break;
+	case GUARD_INTERVAL_1_16:
+		value |= (1 << 5);
+		break;
+	case GUARD_INTERVAL_1_4:
+		value |= (3 << 5);
+		break;
+	default:
+	case GUARD_INTERVAL_1_8:
+		value |= (2 << 5);
+		break;
 	}
 	switch (ch->u.ofdm.constellation) {
-		case QPSK:  value |= (0 << 3); break;
-		case QAM_16: value |= (1 << 3); break;
-		default:
-		case QAM_64: value |= (2 << 3); break;
+	case QPSK:
+		value |= (0 << 3);
+		break;
+	case QAM_16:
+		value |= (1 << 3);
+		break;
+	default:
+	case QAM_64:
+		value |= (2 << 3);
+		break;
 	}
 	switch (HIERARCHY_1) {
-		case HIERARCHY_2: value |= 2; break;
-		case HIERARCHY_4: value |= 4; break;
-		default:
-		case HIERARCHY_1: value |= 1; break;
+	case HIERARCHY_2:
+		value |= 2;
+		break;
+	case HIERARCHY_4:
+		value |= 4;
+		break;
+	default:
+	case HIERARCHY_1:
+		value |= 1;
+		break;
 	}
 	dib7000p_write_word(state, 0, value);
-	dib7000p_write_word(state, 5, (seq << 4) | 1); /* do not force tps, search list 0 */
+	dib7000p_write_word(state, 5, (seq << 4) | 1);	/* do not force tps, search list 0 */
 
 	/* P_dintl_native, P_dintlv_inv, P_hrch, P_code_rate, P_select_hp */
 	value = 0;
@@ -752,39 +939,63 @@
 	if (1 == 1)
 		value |= 1;
 	switch ((ch->u.ofdm.hierarchy_information == 0 || 1 == 1) ? ch->u.ofdm.code_rate_HP : ch->u.ofdm.code_rate_LP) {
-		case FEC_2_3: value |= (2 << 1); break;
-		case FEC_3_4: value |= (3 << 1); break;
-		case FEC_5_6: value |= (5 << 1); break;
-		case FEC_7_8: value |= (7 << 1); break;
-		default:
-		case FEC_1_2: value |= (1 << 1); break;
+	case FEC_2_3:
+		value |= (2 << 1);
+		break;
+	case FEC_3_4:
+		value |= (3 << 1);
+		break;
+	case FEC_5_6:
+		value |= (5 << 1);
+		break;
+	case FEC_7_8:
+		value |= (7 << 1);
+		break;
+	default:
+	case FEC_1_2:
+		value |= (1 << 1);
+		break;
 	}
 	dib7000p_write_word(state, 208, value);
 
 	/* offset loop parameters */
-	dib7000p_write_word(state, 26, 0x6680); // timf(6xxx)
-	dib7000p_write_word(state, 32, 0x0003); // pha_off_max(xxx3)
-	dib7000p_write_word(state, 29, 0x1273); // isi
-	dib7000p_write_word(state, 33, 0x0005); // sfreq(xxx5)
+	dib7000p_write_word(state, 26, 0x6680);
+	dib7000p_write_word(state, 32, 0x0003);
+	dib7000p_write_word(state, 29, 0x1273);
+	dib7000p_write_word(state, 33, 0x0005);
 
 	/* P_dvsy_sync_wait */
 	switch (ch->u.ofdm.transmission_mode) {
-		case TRANSMISSION_MODE_8K: value = 256; break;
-		case TRANSMISSION_MODE_4K: value = 128; break;
-		case TRANSMISSION_MODE_2K:
-		default: value = 64; break;
+	case TRANSMISSION_MODE_8K:
+		value = 256;
+		break;
+	case TRANSMISSION_MODE_4K:
+		value = 128;
+		break;
+	case TRANSMISSION_MODE_2K:
+	default:
+		value = 64;
+		break;
 	}
 	switch (ch->u.ofdm.guard_interval) {
-		case GUARD_INTERVAL_1_16: value *= 2; break;
-		case GUARD_INTERVAL_1_8:  value *= 4; break;
-		case GUARD_INTERVAL_1_4:  value *= 8; break;
-		default:
-		case GUARD_INTERVAL_1_32: value *= 1; break;
+	case GUARD_INTERVAL_1_16:
+		value *= 2;
+		break;
+	case GUARD_INTERVAL_1_8:
+		value *= 4;
+		break;
+	case GUARD_INTERVAL_1_4:
+		value *= 8;
+		break;
+	default:
+	case GUARD_INTERVAL_1_32:
+		value *= 1;
+		break;
 	}
 	if (state->cfg.diversity_delay == 0)
-		state->div_sync_wait = (value * 3) / 2 + 48; // add 50% SFN margin + compensate for one DVSY-fifo
+		state->div_sync_wait = (value * 3) / 2 + 48;
 	else
-		state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay; // add 50% SFN margin + compensate for one DVSY-fifo
+		state->div_sync_wait = (value * 3) / 2 + state->cfg.diversity_delay;
 
 	/* deactive the possibility of diversity reception if extended interleaver */
 	state->div_force_off = !1 && ch->u.ofdm.transmission_mode != TRANSMISSION_MODE_8K;
@@ -792,24 +1003,24 @@
 
 	/* channel estimation fine configuration */
 	switch (ch->u.ofdm.constellation) {
-		case QAM_64:
-			est[0] = 0x0148;       /* P_adp_regul_cnt 0.04 */
-			est[1] = 0xfff0;       /* P_adp_noise_cnt -0.002 */
-			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
-			est[3] = 0xfff8;       /* P_adp_noise_ext -0.001 */
-			break;
-		case QAM_16:
-			est[0] = 0x023d;       /* P_adp_regul_cnt 0.07 */
-			est[1] = 0xffdf;       /* P_adp_noise_cnt -0.004 */
-			est[2] = 0x00a4;       /* P_adp_regul_ext 0.02 */
-			est[3] = 0xfff0;       /* P_adp_noise_ext -0.002 */
-			break;
-		default:
-			est[0] = 0x099a;       /* P_adp_regul_cnt 0.3 */
-			est[1] = 0xffae;       /* P_adp_noise_cnt -0.01 */
-			est[2] = 0x0333;       /* P_adp_regul_ext 0.1 */
-			est[3] = 0xfff8;       /* P_adp_noise_ext -0.002 */
-			break;
+	case QAM_64:
+		est[0] = 0x0148;	/* P_adp_regul_cnt 0.04 */
+		est[1] = 0xfff0;	/* P_adp_noise_cnt -0.002 */
+		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
+		est[3] = 0xfff8;	/* P_adp_noise_ext -0.001 */
+		break;
+	case QAM_16:
+		est[0] = 0x023d;	/* P_adp_regul_cnt 0.07 */
+		est[1] = 0xffdf;	/* P_adp_noise_cnt -0.004 */
+		est[2] = 0x00a4;	/* P_adp_regul_ext 0.02 */
+		est[3] = 0xfff0;	/* P_adp_noise_ext -0.002 */
+		break;
+	default:
+		est[0] = 0x099a;	/* P_adp_regul_cnt 0.3 */
+		est[1] = 0xffae;	/* P_adp_noise_cnt -0.01 */
+		est[2] = 0x0333;	/* P_adp_regul_ext 0.1 */
+		est[3] = 0xfff8;	/* P_adp_noise_ext -0.002 */
+		break;
 	}
 	for (value = 0; value < 4; value++)
 		dib7000p_write_word(state, 187 + value, est[value]);
@@ -820,14 +1031,15 @@
 	struct dib7000p_state *state = demod->demodulator_priv;
 	struct dvb_frontend_parameters schan;
 	u32 value, factor;
+	u32 internal = dib7000p_get_internal_freq(state);
 
 	schan = *ch;
 	schan.u.ofdm.constellation = QAM_64;
-	schan.u.ofdm.guard_interval         = GUARD_INTERVAL_1_32;
-	schan.u.ofdm.transmission_mode          = TRANSMISSION_MODE_8K;
-	schan.u.ofdm.code_rate_HP  = FEC_2_3;
-	schan.u.ofdm.code_rate_LP  = FEC_3_4;
-	schan.u.ofdm.hierarchy_information          = 0;
+	schan.u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+	schan.u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+	schan.u.ofdm.code_rate_HP = FEC_2_3;
+	schan.u.ofdm.code_rate_LP = FEC_3_4;
+	schan.u.ofdm.hierarchy_information = 0;
 
 	dib7000p_set_channel(state, &schan, 7);
 
@@ -837,16 +1049,15 @@
 	else
 		factor = 6;
 
-	// always use the setting for 8MHz here lock_time for 7,6 MHz are longer
-	value = 30 * state->cfg.bw->internal * factor;
-	dib7000p_write_word(state, 6,  (u16) ((value >> 16) & 0xffff)); // lock0 wait time
-	dib7000p_write_word(state, 7,  (u16)  (value        & 0xffff)); // lock0 wait time
-	value = 100 * state->cfg.bw->internal * factor;
-	dib7000p_write_word(state, 8,  (u16) ((value >> 16) & 0xffff)); // lock1 wait time
-	dib7000p_write_word(state, 9,  (u16)  (value        & 0xffff)); // lock1 wait time
-	value = 500 * state->cfg.bw->internal * factor;
-	dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff)); // lock2 wait time
-	dib7000p_write_word(state, 11, (u16)  (value        & 0xffff)); // lock2 wait time
+	value = 30 * internal * factor;
+	dib7000p_write_word(state, 6, (u16) ((value >> 16) & 0xffff));
+	dib7000p_write_word(state, 7, (u16) (value & 0xffff));
+	value = 100 * internal * factor;
+	dib7000p_write_word(state, 8, (u16) ((value >> 16) & 0xffff));
+	dib7000p_write_word(state, 9, (u16) (value & 0xffff));
+	value = 500 * internal * factor;
+	dib7000p_write_word(state, 10, (u16) ((value >> 16) & 0xffff));
+	dib7000p_write_word(state, 11, (u16) (value & 0xffff));
 
 	value = dib7000p_read_word(state, 0);
 	dib7000p_write_word(state, 0, (u16) ((1 << 9) | value));
@@ -861,101 +1072,101 @@
 	struct dib7000p_state *state = demod->demodulator_priv;
 	u16 irq_pending = dib7000p_read_word(state, 1284);
 
-	if (irq_pending & 0x1) // failed
+	if (irq_pending & 0x1)
 		return 1;
 
-	if (irq_pending & 0x2) // succeeded
+	if (irq_pending & 0x2)
 		return 2;
 
-	return 0; // still pending
+	return 0;
 }
 
 static void dib7000p_spur_protect(struct dib7000p_state *state, u32 rf_khz, u32 bw)
 {
-	static s16 notch[]={16143, 14402, 12238, 9713, 6902, 3888, 759, -2392};
-	static u8 sine [] ={0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
-	24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
-	53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
-	82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
-	107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
-	128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
-	147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
-	166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
-	183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
-	199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
-	213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
-	225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
-	235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
-	244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
-	250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
-	254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
-	255, 255, 255, 255, 255, 255};
+	static s16 notch[] = { 16143, 14402, 12238, 9713, 6902, 3888, 759, -2392 };
+	static u8 sine[] = { 0, 2, 3, 5, 6, 8, 9, 11, 13, 14, 16, 17, 19, 20, 22,
+		24, 25, 27, 28, 30, 31, 33, 34, 36, 38, 39, 41, 42, 44, 45, 47, 48, 50, 51,
+		53, 55, 56, 58, 59, 61, 62, 64, 65, 67, 68, 70, 71, 73, 74, 76, 77, 79, 80,
+		82, 83, 85, 86, 88, 89, 91, 92, 94, 95, 97, 98, 99, 101, 102, 104, 105,
+		107, 108, 109, 111, 112, 114, 115, 117, 118, 119, 121, 122, 123, 125, 126,
+		128, 129, 130, 132, 133, 134, 136, 137, 138, 140, 141, 142, 144, 145, 146,
+		147, 149, 150, 151, 152, 154, 155, 156, 157, 159, 160, 161, 162, 164, 165,
+		166, 167, 168, 170, 171, 172, 173, 174, 175, 177, 178, 179, 180, 181, 182,
+		183, 184, 185, 186, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198,
+		199, 200, 201, 202, 203, 204, 205, 206, 207, 207, 208, 209, 210, 211, 212,
+		213, 214, 215, 215, 216, 217, 218, 219, 220, 220, 221, 222, 223, 224, 224,
+		225, 226, 227, 227, 228, 229, 229, 230, 231, 231, 232, 233, 233, 234, 235,
+		235, 236, 237, 237, 238, 238, 239, 239, 240, 241, 241, 242, 242, 243, 243,
+		244, 244, 245, 245, 245, 246, 246, 247, 247, 248, 248, 248, 249, 249, 249,
+		250, 250, 250, 251, 251, 251, 252, 252, 252, 252, 253, 253, 253, 253, 254,
+		254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+		255, 255, 255, 255, 255, 255
+	};
 
 	u32 xtal = state->cfg.bw->xtal_hz / 1000;
 	int f_rel = DIV_ROUND_CLOSEST(rf_khz, xtal) * xtal - rf_khz;
 	int k;
-	int coef_re[8],coef_im[8];
+	int coef_re[8], coef_im[8];
 	int bw_khz = bw;
 	u32 pha;
 
-	dprintk( "relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
-
+	dprintk("relative position of the Spur: %dk (RF: %dk, XTAL: %dk)", f_rel, rf_khz, xtal);
 
-	if (f_rel < -bw_khz/2 || f_rel > bw_khz/2)
+	if (f_rel < -bw_khz / 2 || f_rel > bw_khz / 2)
 		return;
 
 	bw_khz /= 100;
 
-	dib7000p_write_word(state, 142 ,0x0610);
+	dib7000p_write_word(state, 142, 0x0610);
 
 	for (k = 0; k < 8; k++) {
-		pha = ((f_rel * (k+1) * 112 * 80/bw_khz) /1000) & 0x3ff;
+		pha = ((f_rel * (k + 1) * 112 * 80 / bw_khz) / 1000) & 0x3ff;
 
-		if (pha==0) {
+		if (pha == 0) {
 			coef_re[k] = 256;
 			coef_im[k] = 0;
-		} else if(pha < 256) {
-			coef_re[k] = sine[256-(pha&0xff)];
-			coef_im[k] = sine[pha&0xff];
+		} else if (pha < 256) {
+			coef_re[k] = sine[256 - (pha & 0xff)];
+			coef_im[k] = sine[pha & 0xff];
 		} else if (pha == 256) {
 			coef_re[k] = 0;
 			coef_im[k] = 256;
 		} else if (pha < 512) {
-			coef_re[k] = -sine[pha&0xff];
-			coef_im[k] = sine[256 - (pha&0xff)];
+			coef_re[k] = -sine[pha & 0xff];
+			coef_im[k] = sine[256 - (pha & 0xff)];
 		} else if (pha == 512) {
 			coef_re[k] = -256;
 			coef_im[k] = 0;
 		} else if (pha < 768) {
-			coef_re[k] = -sine[256-(pha&0xff)];
-			coef_im[k] = -sine[pha&0xff];
+			coef_re[k] = -sine[256 - (pha & 0xff)];
+			coef_im[k] = -sine[pha & 0xff];
 		} else if (pha == 768) {
 			coef_re[k] = 0;
 			coef_im[k] = -256;
 		} else {
-			coef_re[k] = sine[pha&0xff];
-			coef_im[k] = -sine[256 - (pha&0xff)];
+			coef_re[k] = sine[pha & 0xff];
+			coef_im[k] = -sine[256 - (pha & 0xff)];
 		}
 
 		coef_re[k] *= notch[k];
-		coef_re[k] += (1<<14);
-		if (coef_re[k] >= (1<<24))
-			coef_re[k]  = (1<<24) - 1;
-		coef_re[k] /= (1<<15);
+		coef_re[k] += (1 << 14);
+		if (coef_re[k] >= (1 << 24))
+			coef_re[k] = (1 << 24) - 1;
+		coef_re[k] /= (1 << 15);
 
 		coef_im[k] *= notch[k];
-		coef_im[k] += (1<<14);
-		if (coef_im[k] >= (1<<24))
-			coef_im[k]  = (1<<24)-1;
-		coef_im[k] /= (1<<15);
+		coef_im[k] += (1 << 14);
+		if (coef_im[k] >= (1 << 24))
+			coef_im[k] = (1 << 24) - 1;
+		coef_im[k] /= (1 << 15);
 
-		dprintk( "PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
+		dprintk("PALF COEF: %d re: %d im: %d", k, coef_re[k], coef_im[k]);
 
 		dib7000p_write_word(state, 143, (0 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
 		dib7000p_write_word(state, 144, coef_im[k] & 0x3ff);
 		dib7000p_write_word(state, 143, (1 << 14) | (k << 10) | (coef_re[k] & 0x3ff));
 	}
-	dib7000p_write_word(state,143 ,0);
+	dib7000p_write_word(state, 143, 0);
 }
 
 static int dib7000p_tune(struct dvb_frontend *demod, struct dvb_frontend_parameters *ch)
@@ -976,11 +1187,11 @@
 	/* P_ctrl_inh_cor=0, P_ctrl_alpha_cor=4, P_ctrl_inh_isi=0, P_ctrl_alpha_isi=3, P_ctrl_inh_cor4=1, P_ctrl_alpha_cor4=3 */
 	tmp = (0 << 14) | (4 << 10) | (0 << 9) | (3 << 5) | (1 << 4) | (0x3);
 	if (state->sfn_workaround_active) {
-		dprintk( "SFN workaround is active");
+		dprintk("SFN workaround is active");
 		tmp |= (1 << 9);
-		dib7000p_write_word(state, 166, 0x4000); // P_pha3_force_pha_shift
+		dib7000p_write_word(state, 166, 0x4000);
 	} else {
-		dib7000p_write_word(state, 166, 0x0000); // P_pha3_force_pha_shift
+		dib7000p_write_word(state, 166, 0x0000);
 	}
 	dib7000p_write_word(state, 29, tmp);
 
@@ -993,51 +1204,72 @@
 	/* P_timf_alpha, P_corm_alpha=6, P_corm_thres=0x80 */
 	tmp = (6 << 8) | 0x80;
 	switch (ch->u.ofdm.transmission_mode) {
-		case TRANSMISSION_MODE_2K: tmp |= (7 << 12); break;
-		case TRANSMISSION_MODE_4K: tmp |= (8 << 12); break;
-		default:
-		case TRANSMISSION_MODE_8K: tmp |= (9 << 12); break;
+	case TRANSMISSION_MODE_2K:
+		tmp |= (2 << 12);
+		break;
+	case TRANSMISSION_MODE_4K:
+		tmp |= (3 << 12);
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		tmp |= (4 << 12);
+		break;
 	}
-	dib7000p_write_word(state, 26, tmp);  /* timf_a(6xxx) */
+	dib7000p_write_word(state, 26, tmp);	/* timf_a(6xxx) */
 
 	/* P_ctrl_freeze_pha_shift=0, P_ctrl_pha_off_max */
 	tmp = (0 << 4);
 	switch (ch->u.ofdm.transmission_mode) {
-		case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
-		case TRANSMISSION_MODE_4K: tmp |= 0x7; break;
-		default:
-		case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
+	case TRANSMISSION_MODE_2K:
+		tmp |= 0x6;
+		break;
+	case TRANSMISSION_MODE_4K:
+		tmp |= 0x7;
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		tmp |= 0x8;
+		break;
 	}
-	dib7000p_write_word(state, 32,  tmp);
+	dib7000p_write_word(state, 32, tmp);
 
 	/* P_ctrl_sfreq_inh=0, P_ctrl_sfreq_step */
 	tmp = (0 << 4);
 	switch (ch->u.ofdm.transmission_mode) {
-		case TRANSMISSION_MODE_2K: tmp |= 0x6; break;
-		case TRANSMISSION_MODE_4K: tmp |= 0x7; break;
-		default:
-		case TRANSMISSION_MODE_8K: tmp |= 0x8; break;
+	case TRANSMISSION_MODE_2K:
+		tmp |= 0x6;
+		break;
+	case TRANSMISSION_MODE_4K:
+		tmp |= 0x7;
+		break;
+	default:
+	case TRANSMISSION_MODE_8K:
+		tmp |= 0x8;
+		break;
 	}
-	dib7000p_write_word(state, 33,  tmp);
+	dib7000p_write_word(state, 33, tmp);
 
-	tmp = dib7000p_read_word(state,509);
+	tmp = dib7000p_read_word(state, 509);
 	if (!((tmp >> 6) & 0x1)) {
 		/* restart the fec */
-		tmp = dib7000p_read_word(state,771);
+		tmp = dib7000p_read_word(state, 771);
 		dib7000p_write_word(state, 771, tmp | (1 << 1));
 		dib7000p_write_word(state, 771, tmp);
-		msleep(10);
-		tmp = dib7000p_read_word(state,509);
+		msleep(40);
+		tmp = dib7000p_read_word(state, 509);
 	}
-
 	// we achieved a lock - it's time to update the osc freq
-	if ((tmp >> 6) & 0x1)
+	if ((tmp >> 6) & 0x1) {
 		dib7000p_update_timf(state);
+		/* P_timf_alpha += 2 */
+		tmp = dib7000p_read_word(state, 26);
+		dib7000p_write_word(state, 26, (tmp & ~(0xf << 12)) | ((((tmp >> 12) & 0xf) + 5) << 12));
+	}
 
 	if (state->cfg.spur_protect)
-		dib7000p_spur_protect(state, ch->frequency/1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+		dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
 
-    dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
+	dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->u.ofdm.bandwidth));
 	return 0;
 }
 
@@ -1046,63 +1278,82 @@
 	struct dib7000p_state *state = demod->demodulator_priv;
 	dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
 	dib7000p_set_adc_state(state, DIBX000_SLOW_ADC_ON);
+	if (state->version == SOC7090)
+		dib7000p_sad_calib(state);
 	return 0;
 }
 
 static int dib7000p_sleep(struct dvb_frontend *demod)
 {
 	struct dib7000p_state *state = demod->demodulator_priv;
+	if (state->version == SOC7090)
+		return dib7090_set_output_mode(demod, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
 	return dib7000p_set_output_mode(state, OUTMODE_HIGH_Z) | dib7000p_set_power_mode(state, DIB7000P_POWER_INTERFACE_ONLY);
 }
 
 static int dib7000p_identify(struct dib7000p_state *st)
 {
 	u16 value;
-	dprintk( "checking demod on I2C address: %d (%x)",
-		st->i2c_addr, st->i2c_addr);
+	dprintk("checking demod on I2C address: %d (%x)", st->i2c_addr, st->i2c_addr);
 
 	if ((value = dib7000p_read_word(st, 768)) != 0x01b3) {
-		dprintk( "wrong Vendor ID (read=0x%x)",value);
+		dprintk("wrong Vendor ID (read=0x%x)", value);
 		return -EREMOTEIO;
 	}
 
 	if ((value = dib7000p_read_word(st, 769)) != 0x4000) {
-		dprintk( "wrong Device ID (%x)",value);
+		dprintk("wrong Device ID (%x)", value);
 		return -EREMOTEIO;
 	}
 
 	return 0;
 }
 
-
-static int dib7000p_get_frontend(struct dvb_frontend* fe,
-				struct dvb_frontend_parameters *fep)
+static int dib7000p_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
-	u16 tps = dib7000p_read_word(state,463);
+	u16 tps = dib7000p_read_word(state, 463);
 
 	fep->inversion = INVERSION_AUTO;
 
 	fep->u.ofdm.bandwidth = BANDWIDTH_TO_INDEX(state->current_bandwidth);
 
 	switch ((tps >> 8) & 0x3) {
-		case 0: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K; break;
-		case 1: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K; break;
-		/* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
+	case 0:
+		fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 1:
+		fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	/* case 2: fep->u.ofdm.transmission_mode = TRANSMISSION_MODE_4K; break; */
 	}
 
 	switch (tps & 0x3) {
-		case 0: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32; break;
-		case 1: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16; break;
-		case 2: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8; break;
-		case 3: fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4; break;
+	case 0:
+		fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		fep->u.ofdm.guard_interval = GUARD_INTERVAL_1_4;
+		break;
 	}
 
 	switch ((tps >> 14) & 0x3) {
-		case 0: fep->u.ofdm.constellation = QPSK; break;
-		case 1: fep->u.ofdm.constellation = QAM_16; break;
-		case 2:
-		default: fep->u.ofdm.constellation = QAM_64; break;
+	case 0:
+		fep->u.ofdm.constellation = QPSK;
+		break;
+	case 1:
+		fep->u.ofdm.constellation = QAM_16;
+		break;
+	case 2:
+	default:
+		fep->u.ofdm.constellation = QAM_64;
+		break;
 	}
 
 	/* as long as the frontend_param structure is fixed for hierarchical transmission I refuse to use it */
@@ -1110,22 +1361,42 @@
 
 	fep->u.ofdm.hierarchy_information = HIERARCHY_NONE;
 	switch ((tps >> 5) & 0x7) {
-		case 1: fep->u.ofdm.code_rate_HP = FEC_1_2; break;
-		case 2: fep->u.ofdm.code_rate_HP = FEC_2_3; break;
-		case 3: fep->u.ofdm.code_rate_HP = FEC_3_4; break;
-		case 5: fep->u.ofdm.code_rate_HP = FEC_5_6; break;
-		case 7:
-		default: fep->u.ofdm.code_rate_HP = FEC_7_8; break;
+	case 1:
+		fep->u.ofdm.code_rate_HP = FEC_1_2;
+		break;
+	case 2:
+		fep->u.ofdm.code_rate_HP = FEC_2_3;
+		break;
+	case 3:
+		fep->u.ofdm.code_rate_HP = FEC_3_4;
+		break;
+	case 5:
+		fep->u.ofdm.code_rate_HP = FEC_5_6;
+		break;
+	case 7:
+	default:
+		fep->u.ofdm.code_rate_HP = FEC_7_8;
+		break;
 
 	}
 
 	switch ((tps >> 2) & 0x7) {
-		case 1: fep->u.ofdm.code_rate_LP = FEC_1_2; break;
-		case 2: fep->u.ofdm.code_rate_LP = FEC_2_3; break;
-		case 3: fep->u.ofdm.code_rate_LP = FEC_3_4; break;
-		case 5: fep->u.ofdm.code_rate_LP = FEC_5_6; break;
-		case 7:
-		default: fep->u.ofdm.code_rate_LP = FEC_7_8; break;
+	case 1:
+		fep->u.ofdm.code_rate_LP = FEC_1_2;
+		break;
+	case 2:
+		fep->u.ofdm.code_rate_LP = FEC_2_3;
+		break;
+	case 3:
+		fep->u.ofdm.code_rate_LP = FEC_3_4;
+		break;
+	case 5:
+		fep->u.ofdm.code_rate_LP = FEC_5_6;
+		break;
+	case 7:
+	default:
+		fep->u.ofdm.code_rate_LP = FEC_7_8;
+		break;
 	}
 
 	/* native interleaver: (dib7000p_read_word(state, 464) >>  5) & 0x1 */
@@ -1133,15 +1404,18 @@
 	return 0;
 }
 
-static int dib7000p_set_frontend(struct dvb_frontend* fe,
-				struct dvb_frontend_parameters *fep)
+static int dib7000p_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	int time, ret;
 
-	dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
+	if (state->version == SOC7090) {
+		dib7090_set_diversity_in(fe, 0);
+		dib7090_set_output_mode(fe, OUTMODE_HIGH_Z);
+	} else
+		dib7000p_set_output_mode(state, OUTMODE_HIGH_Z);
 
-    /* maybe the parameter has been changed */
+	/* maybe the parameter has been changed */
 	state->sfn_workaround_active = buggy_sfn_workaround;
 
 	if (fe->ops.tuner_ops.set_params)
@@ -1156,9 +1430,7 @@
 	} while (time != -1);
 
 	if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
-		fep->u.ofdm.guard_interval    == GUARD_INTERVAL_AUTO ||
-		fep->u.ofdm.constellation     == QAM_AUTO ||
-		fep->u.ofdm.code_rate_HP      == FEC_AUTO) {
+		fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
 		int i = 800, found;
 
 		dib7000p_autosearch_start(fe, fep);
@@ -1167,9 +1439,9 @@
 			found = dib7000p_autosearch_is_irq(fe);
 		} while (found == 0 && i--);
 
-		dprintk("autosearch returns: %d",found);
+		dprintk("autosearch returns: %d", found);
 		if (found == 0 || found == 1)
-			return 0; // no channel found
+			return 0;
 
 		dib7000p_get_frontend(fe, fep);
 	}
@@ -1177,11 +1449,15 @@
 	ret = dib7000p_tune(fe, fep);
 
 	/* make this a config parameter */
-	dib7000p_set_output_mode(state, state->cfg.output_mode);
-    return ret;
+	if (state->version == SOC7090)
+		dib7090_set_output_mode(fe, state->cfg.output_mode);
+	else
+		dib7000p_set_output_mode(state, state->cfg.output_mode);
+
+	return ret;
 }
 
-static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t *stat)
+static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 lock = dib7000p_read_word(state, 509);
@@ -1196,27 +1472,27 @@
 		*stat |= FE_HAS_VITERBI;
 	if (lock & 0x0010)
 		*stat |= FE_HAS_SYNC;
-    if ((lock & 0x0038) == 0x38)
+	if ((lock & 0x0038) == 0x38)
 		*stat |= FE_HAS_LOCK;
 
 	return 0;
 }
 
-static int dib7000p_read_ber(struct dvb_frontend *fe, u32 *ber)
+static int dib7000p_read_ber(struct dvb_frontend *fe, u32 * ber)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	*ber = (dib7000p_read_word(state, 500) << 16) | dib7000p_read_word(state, 501);
 	return 0;
 }
 
-static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 *unc)
+static int dib7000p_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	*unc = dib7000p_read_word(state, 506);
 	return 0;
 }
 
-static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
+static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 val = dib7000p_read_word(state, 394);
@@ -1224,7 +1500,7 @@
 	return 0;
 }
 
-static int dib7000p_read_snr(struct dvb_frontend* fe, u16 *snr)
+static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
 {
 	struct dib7000p_state *state = fe->demodulator_priv;
 	u16 val;
@@ -1240,19 +1516,17 @@
 		noise_exp -= 0x40;
 
 	signal_mant = (val >> 6) & 0xFF;
-	signal_exp  = (val & 0x3F);
+	signal_exp = (val & 0x3F);
 	if ((signal_exp & 0x20) != 0)
 		signal_exp -= 0x40;
 
 	if (signal_mant != 0)
-		result = intlog10(2) * 10 * signal_exp + 10 *
-			intlog10(signal_mant);
+		result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
 	else
 		result = intlog10(2) * 10 * signal_exp - 100;
 
 	if (noise_mant != 0)
-		result -= intlog10(2) * 10 * noise_exp + 10 *
-			intlog10(noise_mant);
+		result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
 	else
 		result -= intlog10(2) * 10 * noise_exp - 100;
 
@@ -1260,7 +1534,7 @@
 	return 0;
 }
 
-static int dib7000p_fe_get_tune_settings(struct dvb_frontend* fe, struct dvb_frontend_tune_settings *tune)
+static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
 {
 	tune->min_delay_ms = 1000;
 	return 0;
@@ -1270,6 +1544,7 @@
 {
 	struct dib7000p_state *st = demod->demodulator_priv;
 	dibx000_exit_i2c_master(&st->i2c_master);
+	i2c_del_adapter(&st->dib7090_tuner_adap);
 	kfree(st);
 }
 
@@ -1277,8 +1552,8 @@
 {
 	u8 tx[2], rx[2];
 	struct i2c_msg msg[2] = {
-		{ .addr = 18 >> 1, .flags = 0,        .buf = tx, .len = 2 },
-		{ .addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2 },
+		{.addr = 18 >> 1, .flags = 0, .buf = tx, .len = 2},
+		{.addr = 18 >> 1, .flags = I2C_M_RD, .buf = rx, .len = 2},
 	};
 
 	tx[0] = 0x03;
@@ -1303,7 +1578,7 @@
 }
 EXPORT_SYMBOL(dib7000pc_detection);
 
-struct i2c_adapter * dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
 {
 	struct dib7000p_state *st = demod->demodulator_priv;
 	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
@@ -1312,19 +1587,19 @@
 
 int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
 {
-    struct dib7000p_state *state = fe->demodulator_priv;
-    u16 val = dib7000p_read_word(state, 235) & 0xffef;
-    val |= (onoff & 0x1) << 4;
-    dprintk("PID filter enabled %d", onoff);
-    return dib7000p_write_word(state, 235, val);
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 val = dib7000p_read_word(state, 235) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+	dprintk("PID filter enabled %d", onoff);
+	return dib7000p_write_word(state, 235, val);
 }
 EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
 
 int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
-    struct dib7000p_state *state = fe->demodulator_priv;
-    dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
-    return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
+	struct dib7000p_state *state = fe->demodulator_priv;
+	dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
 }
 EXPORT_SYMBOL(dib7000p_pid_filter);
 
@@ -1340,16 +1615,19 @@
 
 	dpst->i2c_adap = i2c;
 
-	for (k = no_of_demods-1; k >= 0; k--) {
+	for (k = no_of_demods - 1; k >= 0; k--) {
 		dpst->cfg = cfg[k];
 
 		/* designated i2c address */
-		new_addr          = (0x40 + k) << 1;
+		if (cfg[k].default_i2c_addr != 0)
+			new_addr = cfg[k].default_i2c_addr + (k << 1);
+		else
+			new_addr = (0x40 + k) << 1;
 		dpst->i2c_addr = new_addr;
-		dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
+		dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
 		if (dib7000p_identify(dpst) != 0) {
 			dpst->i2c_addr = default_addr;
-			dib7000p_write_word(dpst, 1287, 0x0003); /* sram lead in, rdy */
+			dib7000p_write_word(dpst, 1287, 0x0003);	/* sram lead in, rdy */
 			if (dib7000p_identify(dpst) != 0) {
 				dprintk("DiB7000P #%d: not identified\n", k);
 				kfree(dpst);
@@ -1368,7 +1646,10 @@
 
 	for (k = 0; k < no_of_demods; k++) {
 		dpst->cfg = cfg[k];
-		dpst->i2c_addr = (0x40 + k) << 1;
+		if (cfg[k].default_i2c_addr != 0)
+			dpst->i2c_addr = (cfg[k].default_i2c_addr + k) << 1;
+		else
+			dpst->i2c_addr = (0x40 + k) << 1;
 
 		// unforce divstr
 		dib7000p_write_word(dpst, 1285, dpst->i2c_addr << 2);
@@ -1382,8 +1663,613 @@
 }
 EXPORT_SYMBOL(dib7000p_i2c_enumeration);
 
+static const s32 lut_1000ln_mant[] = {
+	6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
+};
+
+static s32 dib7000p_get_adc_power(struct dvb_frontend *fe)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u32 tmp_val = 0, exp = 0, mant = 0;
+	s32 pow_i;
+	u16 buf[2];
+	u8 ix = 0;
+
+	buf[0] = dib7000p_read_word(state, 0x184);
+	buf[1] = dib7000p_read_word(state, 0x185);
+	pow_i = (buf[0] << 16) | buf[1];
+	dprintk("raw pow_i = %d", pow_i);
+
+	tmp_val = pow_i;
+	while (tmp_val >>= 1)
+		exp++;
+
+	mant = (pow_i * 1000 / (1 << exp));
+	dprintk(" mant = %d exp = %d", mant / 1000, exp);
+
+	ix = (u8) ((mant - 1000) / 100);	/* index of the LUT */
+	dprintk(" ix = %d", ix);
+
+	pow_i = (lut_1000ln_mant[ix] + 693 * (exp - 20) - 6908);
+	pow_i = (pow_i << 8) / 1000;
+	dprintk(" pow_i = %d", pow_i);
+
+	return pow_i;
+}
+
+static int map_addr_to_serpar_number(struct i2c_msg *msg)
+{
+	if ((msg->buf[0] <= 15))
+		msg->buf[0] -= 1;
+	else if (msg->buf[0] == 17)
+		msg->buf[0] = 15;
+	else if (msg->buf[0] == 16)
+		msg->buf[0] = 17;
+	else if (msg->buf[0] == 19)
+		msg->buf[0] = 16;
+	else if (msg->buf[0] >= 21 && msg->buf[0] <= 25)
+		msg->buf[0] -= 3;
+	else if (msg->buf[0] == 28)
+		msg->buf[0] = 23;
+	else
+		return -EINVAL;
+	return 0;
+}
+
+static int w7090p_tuner_write_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+	u8 n_overflow = 1;
+	u16 i = 1000;
+	u16 serpar_num = msg[0].buf[0];
+
+	while (n_overflow == 1 && i) {
+		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("Tuner ITF: write busy (overflow)");
+	}
+	dib7000p_write_word(state, 1985, (1 << 6) | (serpar_num & 0x3f));
+	dib7000p_write_word(state, 1986, (msg[0].buf[1] << 8) | msg[0].buf[2]);
+
+	return num;
+}
+
+static int w7090p_tuner_read_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+	u8 n_overflow = 1, n_empty = 1;
+	u16 i = 1000;
+	u16 serpar_num = msg[0].buf[0];
+	u16 read_word;
+
+	while (n_overflow == 1 && i) {
+		n_overflow = (dib7000p_read_word(state, 1984) >> 1) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("TunerITF: read busy (overflow)");
+	}
+	dib7000p_write_word(state, 1985, (0 << 6) | (serpar_num & 0x3f));
+
+	i = 1000;
+	while (n_empty == 1 && i) {
+		n_empty = dib7000p_read_word(state, 1984) & 0x1;
+		i--;
+		if (i == 0)
+			dprintk("TunerITF: read busy (empty)");
+	}
+	read_word = dib7000p_read_word(state, 1987);
+	msg[1].buf[0] = (read_word >> 8) & 0xff;
+	msg[1].buf[1] = (read_word) & 0xff;
+
+	return num;
+}
+
+static int w7090p_tuner_rw_serpar(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	if (map_addr_to_serpar_number(&msg[0]) == 0) {	/* else = Tuner regs to ignore : DIG_CFG, CTRL_RF_LT, PLL_CFG, PWM1_REG, ADCCLK, DIG_CFG_3; SLEEP_EN... */
+		if (num == 1) {	/* write */
+			return w7090p_tuner_write_serpar(i2c_adap, msg, 1);
+		} else {	/* read */
+			return w7090p_tuner_read_serpar(i2c_adap, msg, 2);
+		}
+	}
+	return num;
+}
+
+int dib7090p_rw_on_apb(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num, u16 apb_address)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+	u16 word;
+
+	if (num == 1) {		/* write */
+		dib7000p_write_word(state, apb_address, ((msg[0].buf[1] << 8) | (msg[0].buf[2])));
+	} else {
+		word = dib7000p_read_word(state, apb_address);
+		msg[1].buf[0] = (word >> 8) & 0xff;
+		msg[1].buf[1] = (word) & 0xff;
+	}
+
+	return num;
+}
+
+static int dib7090_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib7000p_state *state = i2c_get_adapdata(i2c_adap);
+
+	u16 apb_address = 0, word;
+	int i = 0;
+	switch (msg[0].buf[0]) {
+	case 0x12:
+		apb_address = 1920;
+		break;
+	case 0x14:
+		apb_address = 1921;
+		break;
+	case 0x24:
+		apb_address = 1922;
+		break;
+	case 0x1a:
+		apb_address = 1923;
+		break;
+	case 0x22:
+		apb_address = 1924;
+		break;
+	case 0x33:
+		apb_address = 1926;
+		break;
+	case 0x34:
+		apb_address = 1927;
+		break;
+	case 0x35:
+		apb_address = 1928;
+		break;
+	case 0x36:
+		apb_address = 1929;
+		break;
+	case 0x37:
+		apb_address = 1930;
+		break;
+	case 0x38:
+		apb_address = 1931;
+		break;
+	case 0x39:
+		apb_address = 1932;
+		break;
+	case 0x2a:
+		apb_address = 1935;
+		break;
+	case 0x2b:
+		apb_address = 1936;
+		break;
+	case 0x2c:
+		apb_address = 1937;
+		break;
+	case 0x2d:
+		apb_address = 1938;
+		break;
+	case 0x2e:
+		apb_address = 1939;
+		break;
+	case 0x2f:
+		apb_address = 1940;
+		break;
+	case 0x30:
+		apb_address = 1941;
+		break;
+	case 0x31:
+		apb_address = 1942;
+		break;
+	case 0x32:
+		apb_address = 1943;
+		break;
+	case 0x3e:
+		apb_address = 1944;
+		break;
+	case 0x3f:
+		apb_address = 1945;
+		break;
+	case 0x40:
+		apb_address = 1948;
+		break;
+	case 0x25:
+		apb_address = 914;
+		break;
+	case 0x26:
+		apb_address = 915;
+		break;
+	case 0x27:
+		apb_address = 916;
+		break;
+	case 0x28:
+		apb_address = 917;
+		break;
+	case 0x1d:
+		i = ((dib7000p_read_word(state, 72) >> 12) & 0x3);
+		word = dib7000p_read_word(state, 384 + i);
+		msg[1].buf[0] = (word >> 8) & 0xff;
+		msg[1].buf[1] = (word) & 0xff;
+		return num;
+	case 0x1f:
+		if (num == 1) {	/* write */
+			word = (u16) ((msg[0].buf[1] << 8) | msg[0].buf[2]);
+			word &= 0x3;
+			word = (dib7000p_read_word(state, 72) & ~(3 << 12)) | (word << 12);
+			dib7000p_write_word(state, 72, word);	/* Set the proper input */
+			return num;
+		}
+	}
+
+	if (apb_address != 0)	/* R/W acces via APB */
+		return dib7090p_rw_on_apb(i2c_adap, msg, num, apb_address);
+	else			/* R/W access via SERPAR  */
+		return w7090p_tuner_rw_serpar(i2c_adap, msg, num);
+
+	return 0;
+}
+
+static u32 dib7000p_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib7090_tuner_xfer_algo = {
+	.master_xfer = dib7090_tuner_xfer,
+	.functionality = dib7000p_i2c_func,
+};
+
+struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+{
+	struct dib7000p_state *st = fe->demodulator_priv;
+	return &st->dib7090_tuner_adap;
+}
+EXPORT_SYMBOL(dib7090_get_i2c_tuner);
+
+static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
+{
+	u16 reg;
+
+	/* drive host bus 2, 3, 4 */
+	reg = dib7000p_read_word(state, 1798) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive << 12) | (drive << 6) | drive;
+	dib7000p_write_word(state, 1798, reg);
+
+	/* drive host bus 5,6 */
+	reg = dib7000p_read_word(state, 1799) & ~((0x7 << 2) | (0x7 << 8));
+	reg |= (drive << 8) | (drive << 2);
+	dib7000p_write_word(state, 1799, reg);
+
+	/* drive host bus 7, 8, 9 */
+	reg = dib7000p_read_word(state, 1800) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive << 12) | (drive << 6) | drive;
+	dib7000p_write_word(state, 1800, reg);
+
+	/* drive host bus 10, 11 */
+	reg = dib7000p_read_word(state, 1801) & ~((0x7 << 2) | (0x7 << 8));
+	reg |= (drive << 8) | (drive << 2);
+	dib7000p_write_word(state, 1801, reg);
+
+	/* drive host bus 12, 13, 14 */
+	reg = dib7000p_read_word(state, 1802) & ~((0x7) | (0x7 << 6) | (0x7 << 12));
+	reg |= (drive << 12) | (drive << 6) | drive;
+	dib7000p_write_word(state, 1802, reg);
+
+	return 0;
+}
+
+static u32 dib7090_calcSyncFreq(u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 syncSize)
+{
+	u32 quantif = 3;
+	u32 nom = (insertExtSynchro * P_Kin + syncSize);
+	u32 denom = P_Kout;
+	u32 syncFreq = ((nom << quantif) / denom);
+
+	if ((syncFreq & ((1 << quantif) - 1)) != 0)
+		syncFreq = (syncFreq >> quantif) + 1;
+	else
+		syncFreq = (syncFreq >> quantif);
+
+	if (syncFreq != 0)
+		syncFreq = syncFreq - 1;
+
+	return syncFreq;
+}
+
+static int dib7090_cfg_DibTx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 insertExtSynchro, u32 synchroMode, u32 syncWord, u32 syncSize)
+{
+	u8 index_buf;
+	u16 rx_copy_buf[22];
+
+	dprintk("Configure DibStream Tx");
+	for (index_buf = 0; index_buf < 22; index_buf++)
+		rx_copy_buf[index_buf] = dib7000p_read_word(state, 1536+index_buf);
+
+	dib7000p_write_word(state, 1615, 1);
+	dib7000p_write_word(state, 1603, P_Kin);
+	dib7000p_write_word(state, 1605, P_Kout);
+	dib7000p_write_word(state, 1606, insertExtSynchro);
+	dib7000p_write_word(state, 1608, synchroMode);
+	dib7000p_write_word(state, 1609, (syncWord >> 16) & 0xffff);
+	dib7000p_write_word(state, 1610, syncWord & 0xffff);
+	dib7000p_write_word(state, 1612, syncSize);
+	dib7000p_write_word(state, 1615, 0);
+
+	for (index_buf = 0; index_buf < 22; index_buf++)
+		dib7000p_write_word(state, 1536+index_buf, rx_copy_buf[index_buf]);
+
+	return 0;
+}
+
+static int dib7090_cfg_DibRx(struct dib7000p_state *state, u32 P_Kin, u32 P_Kout, u32 synchroMode, u32 insertExtSynchro, u32 syncWord, u32 syncSize,
+		u32 dataOutRate)
+{
+	u32 syncFreq;
+
+	dprintk("Configure DibStream Rx");
+	if ((P_Kin != 0) && (P_Kout != 0)) {
+		syncFreq = dib7090_calcSyncFreq(P_Kin, P_Kout, insertExtSynchro, syncSize);
+		dib7000p_write_word(state, 1542, syncFreq);
+	}
+	dib7000p_write_word(state, 1554, 1);
+	dib7000p_write_word(state, 1536, P_Kin);
+	dib7000p_write_word(state, 1537, P_Kout);
+	dib7000p_write_word(state, 1539, synchroMode);
+	dib7000p_write_word(state, 1540, (syncWord >> 16) & 0xffff);
+	dib7000p_write_word(state, 1541, syncWord & 0xffff);
+	dib7000p_write_word(state, 1543, syncSize);
+	dib7000p_write_word(state, 1544, dataOutRate);
+	dib7000p_write_word(state, 1554, 0);
+
+	return 0;
+}
+
+static int dib7090_enDivOnHostBus(struct dib7000p_state *state)
+{
+	u16 reg;
+
+	dprintk("Enable Diversity on host bus");
+	reg = (1 << 8) | (1 << 5);
+	dib7000p_write_word(state, 1288, reg);
+
+	return dib7090_cfg_DibTx(state, 5, 5, 0, 0, 0, 0);
+}
+
+static int dib7090_enAdcOnHostBus(struct dib7000p_state *state)
+{
+	u16 reg;
+
+	dprintk("Enable ADC on host bus");
+	reg = (1 << 7) | (1 << 5);
+	dib7000p_write_word(state, 1288, reg);
+
+	return dib7090_cfg_DibTx(state, 20, 5, 10, 0, 0, 0);
+}
+
+static int dib7090_enMpegOnHostBus(struct dib7000p_state *state)
+{
+	u16 reg;
+
+	dprintk("Enable Mpeg on host bus");
+	reg = (1 << 9) | (1 << 5);
+	dib7000p_write_word(state, 1288, reg);
+
+	return dib7090_cfg_DibTx(state, 8, 5, 0, 0, 0, 0);
+}
+
+static int dib7090_enMpegInput(struct dib7000p_state *state)
+{
+	dprintk("Enable Mpeg input");
+	return dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0);	/*outputRate = 8 */
+}
+
+static int dib7090_enMpegMux(struct dib7000p_state *state, u16 pulseWidth, u16 enSerialMode, u16 enSerialClkDiv2)
+{
+	u16 reg = (1 << 7) | ((pulseWidth & 0x1f) << 2) | ((enSerialMode & 0x1) << 1) | (enSerialClkDiv2 & 0x1);
+
+	dprintk("Enable Mpeg mux");
+	dib7000p_write_word(state, 1287, reg);
+
+	reg &= ~(1 << 7);
+	dib7000p_write_word(state, 1287, reg);
+
+	reg = (1 << 4);
+	dib7000p_write_word(state, 1288, reg);
+
+	return 0;
+}
+
+static int dib7090_disableMpegMux(struct dib7000p_state *state)
+{
+	u16 reg;
+
+	dprintk("Disable Mpeg mux");
+	dib7000p_write_word(state, 1288, 0);
+
+	reg = dib7000p_read_word(state, 1287);
+	reg &= ~(1 << 7);
+	dib7000p_write_word(state, 1287, reg);
+
+	return 0;
+}
+
+static int dib7090_set_input_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+
+	switch (mode) {
+	case INPUT_MODE_DIVERSITY:
+			dprintk("Enable diversity INPUT");
+			dib7090_cfg_DibRx(state, 5, 5, 0, 0, 0, 0, 0);
+			break;
+	case INPUT_MODE_MPEG:
+			dprintk("Enable Mpeg INPUT");
+			dib7090_cfg_DibRx(state, 8, 5, 0, 0, 0, 8, 0); /*outputRate = 8 */
+			break;
+	case INPUT_MODE_OFF:
+	default:
+			dprintk("Disable INPUT");
+			dib7090_cfg_DibRx(state, 0, 0, 0, 0, 0, 0, 0);
+			break;
+	}
+	return 0;
+}
+
+static int dib7090_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+	switch (onoff) {
+	case 0:		/* only use the internal way - not the diversity input */
+		dib7090_set_input_mode(fe, INPUT_MODE_MPEG);
+		break;
+	case 1:		/* both ways */
+	case 2:		/* only the diversity input */
+		dib7090_set_input_mode(fe, INPUT_MODE_DIVERSITY);
+		break;
+	}
+
+	return 0;
+}
+
+static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+
+	u16 outreg, smo_mode, fifo_threshold;
+	u8 prefer_mpeg_mux_use = 1;
+	int ret = 0;
+
+	dib7090_host_bus_drive(state, 1);
+
+	fifo_threshold = 1792;
+	smo_mode = (dib7000p_read_word(state, 235) & 0x0050) | (1 << 1);
+	outreg = dib7000p_read_word(state, 1286) & ~((1 << 10) | (0x7 << 6) | (1 << 1));
+
+	switch (mode) {
+	case OUTMODE_HIGH_Z:
+		outreg = 0;
+		break;
+
+	case OUTMODE_MPEG2_SERIAL:
+		if (prefer_mpeg_mux_use) {
+			dprintk("Sip 7090P setting output mode TS_SERIAL using Mpeg Mux");
+			dib7090_enMpegOnHostBus(state);
+			dib7090_enMpegInput(state);
+			if (state->cfg.enMpegOutput == 1)
+				dib7090_enMpegMux(state, 3, 1, 1);
+
+		} else {	/* Use Smooth block */
+			dprintk("Sip 7090P setting output mode TS_SERIAL using Smooth bloc");
+			dib7090_disableMpegMux(state);
+			dib7000p_write_word(state, 1288, (1 << 6));
+			outreg |= (2 << 6) | (0 << 1);
+		}
+		break;
+
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		if (prefer_mpeg_mux_use) {
+			dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Mpeg Mux");
+			dib7090_enMpegOnHostBus(state);
+			dib7090_enMpegInput(state);
+			if (state->cfg.enMpegOutput == 1)
+				dib7090_enMpegMux(state, 2, 0, 0);
+		} else {	/* Use Smooth block */
+			dprintk("Sip 7090P setting output mode TS_PARALLEL_GATED using Smooth block");
+			dib7090_disableMpegMux(state);
+			dib7000p_write_word(state, 1288, (1 << 6));
+			outreg |= (0 << 6);
+		}
+		break;
+
+	case OUTMODE_MPEG2_PAR_CONT_CLK:	/* Using Smooth block only */
+		dprintk("Sip 7090P setting output mode TS_PARALLEL_CONT using Smooth block");
+		dib7090_disableMpegMux(state);
+		dib7000p_write_word(state, 1288, (1 << 6));
+		outreg |= (1 << 6);
+		break;
+
+	case OUTMODE_MPEG2_FIFO:	/* Using Smooth block because not supported by new Mpeg Mux bloc */
+		dprintk("Sip 7090P setting output mode TS_FIFO using Smooth block");
+		dib7090_disableMpegMux(state);
+		dib7000p_write_word(state, 1288, (1 << 6));
+		outreg |= (5 << 6);
+		smo_mode |= (3 << 1);
+		fifo_threshold = 512;
+		break;
+
+	case OUTMODE_DIVERSITY:
+		dprintk("Sip 7090P setting output mode MODE_DIVERSITY");
+		dib7090_disableMpegMux(state);
+		dib7090_enDivOnHostBus(state);
+		break;
+
+	case OUTMODE_ANALOG_ADC:
+		dprintk("Sip 7090P setting output mode MODE_ANALOG_ADC");
+		dib7090_enAdcOnHostBus(state);
+		break;
+	}
+
+	if (state->cfg.output_mpeg2_in_188_bytes)
+		smo_mode |= (1 << 5);
+
+	ret |= dib7000p_write_word(state, 235, smo_mode);
+	ret |= dib7000p_write_word(state, 236, fifo_threshold);	/* synchronous fread */
+	ret |= dib7000p_write_word(state, 1286, outreg | (1 << 10));	/* allways set Dout active = 1 !!! */
+
+	return ret;
+}
+
+int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 en_cur_state;
+
+	dprintk("sleep dib7090: %d", onoff);
+
+	en_cur_state = dib7000p_read_word(state, 1922);
+
+	if (en_cur_state > 0xff)
+		state->tuner_enable = en_cur_state;
+
+	if (onoff)
+		en_cur_state &= 0x00ff;
+	else {
+		if (state->tuner_enable != 0)
+			en_cur_state = state->tuner_enable;
+	}
+
+	dib7000p_write_word(state, 1922, en_cur_state);
+
+	return 0;
+}
+EXPORT_SYMBOL(dib7090_tuner_sleep);
+
+int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
+{
+	dprintk("AGC restart callback: %d", restart);
+	return 0;
+}
+EXPORT_SYMBOL(dib7090_agc_restart);
+
+int dib7090_get_adc_power(struct dvb_frontend *fe)
+{
+	return dib7000p_get_adc_power(fe);
+}
+EXPORT_SYMBOL(dib7090_get_adc_power);
+
+int dib7090_slave_reset(struct dvb_frontend *fe)
+{
+	struct dib7000p_state *state = fe->demodulator_priv;
+	u16 reg;
+
+	reg = dib7000p_read_word(state, 1794);
+	dib7000p_write_word(state, 1794, reg | (4 << 12));
+
+	dib7000p_write_word(state, 1032, 0xffff);
+	return 0;
+}
+EXPORT_SYMBOL(dib7090_slave_reset);
+
 static struct dvb_frontend_ops dib7000p_ops;
-struct dvb_frontend * dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
 {
 	struct dvb_frontend *demod;
 	struct dib7000p_state *st;
@@ -1400,28 +2286,41 @@
 	/* Ensure the output mode remains at the previous default if it's
 	 * not specifically set by the caller.
 	 */
-	if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) &&
-	    (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
+	if ((st->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
 		st->cfg.output_mode = OUTMODE_MPEG2_FIFO;
 
-	demod                   = &st->demod;
+	demod = &st->demod;
 	demod->demodulator_priv = st;
 	memcpy(&st->demod.ops, &dib7000p_ops, sizeof(struct dvb_frontend_ops));
 
-    dib7000p_write_word(st, 1287, 0x0003); /* sram lead in, rdy */
+	dib7000p_write_word(st, 1287, 0x0003);	/* sram lead in, rdy */
 
 	if (dib7000p_identify(st) != 0)
 		goto error;
 
+	st->version = dib7000p_read_word(st, 897);
+
 	/* FIXME: make sure the dev.parent field is initialized, or else
-	request_firmware() will hit an OOPS (this should be moved somewhere
-	more common) */
-	st->i2c_master.gated_tuner_i2c_adap.dev.parent = i2c_adap->dev.parent;
+		request_firmware() will hit an OOPS (this should be moved somewhere
+		more common) */
 
 	dibx000_init_i2c_master(&st->i2c_master, DIB7000P, st->i2c_adap, st->i2c_addr);
 
+	/* init 7090 tuner adapter */
+	strncpy(st->dib7090_tuner_adap.name, "DiB7090 tuner interface", sizeof(st->dib7090_tuner_adap.name));
+	st->dib7090_tuner_adap.algo = &dib7090_tuner_xfer_algo;
+	st->dib7090_tuner_adap.algo_data = NULL;
+	st->dib7090_tuner_adap.dev.parent = st->i2c_adap->dev.parent;
+	i2c_set_adapdata(&st->dib7090_tuner_adap, st);
+	i2c_add_adapter(&st->dib7090_tuner_adap);
+
 	dib7000p_demod_reset(st);
 
+	if (st->version == SOC7090) {
+		dib7090_set_output_mode(demod, st->cfg.output_mode);
+		dib7090_set_diversity_in(demod, 0);
+	}
+
 	return demod;
 
 error:
@@ -1432,37 +2331,35 @@
 
 static struct dvb_frontend_ops dib7000p_ops = {
 	.info = {
-		.name = "DiBcom 7000PC",
-		.type = FE_OFDM,
-		.frequency_min      = 44250000,
-		.frequency_max      = 867250000,
-		.frequency_stepsize = 62500,
-		.caps = FE_CAN_INVERSION_AUTO |
-			FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
-			FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
-			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
-			FE_CAN_TRANSMISSION_MODE_AUTO |
-			FE_CAN_GUARD_INTERVAL_AUTO |
-			FE_CAN_RECOVER |
-			FE_CAN_HIERARCHY_AUTO,
-	},
+		 .name = "DiBcom 7000PC",
+		 .type = FE_OFDM,
+		 .frequency_min = 44250000,
+		 .frequency_max = 867250000,
+		 .frequency_stepsize = 62500,
+		 .caps = FE_CAN_INVERSION_AUTO |
+		 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+		 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
+		 },
 
-	.release              = dib7000p_release,
+	.release = dib7000p_release,
 
-	.init                 = dib7000p_wakeup,
-	.sleep                = dib7000p_sleep,
+	.init = dib7000p_wakeup,
+	.sleep = dib7000p_sleep,
 
-	.set_frontend         = dib7000p_set_frontend,
-	.get_tune_settings    = dib7000p_fe_get_tune_settings,
-	.get_frontend         = dib7000p_get_frontend,
+	.set_frontend = dib7000p_set_frontend,
+	.get_tune_settings = dib7000p_fe_get_tune_settings,
+	.get_frontend = dib7000p_get_frontend,
 
-	.read_status          = dib7000p_read_status,
-	.read_ber             = dib7000p_read_ber,
+	.read_status = dib7000p_read_status,
+	.read_ber = dib7000p_read_ber,
 	.read_signal_strength = dib7000p_read_signal_strength,
-	.read_snr             = dib7000p_read_snr,
-	.read_ucblocks        = dib7000p_read_unc_blocks,
+	.read_snr = dib7000p_read_snr,
+	.read_ucblocks = dib7000p_read_unc_blocks,
 };
 
+MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
 MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
 MODULE_DESCRIPTION("Driver for the DiBcom 7000PC COFDM demodulator");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib7000p.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib7000p.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib7000p.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib7000p.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,59 +33,54 @@
 	int (*agc_control) (struct dvb_frontend *, u8 before);
 
 	u8 output_mode;
-	u8 disable_sample_and_hold : 1;
+	u8 disable_sample_and_hold:1;
 
-	u8 enable_current_mirror : 1;
-	u8 diversity_delay;
+	u8 enable_current_mirror:1;
+	u16 diversity_delay;
 
+	u8 default_i2c_addr;
+	u8 enMpegOutput:1;
 };
 
 #define DEFAULT_DIB7000P_I2C_ADDRESS 18
 
 #if defined(CONFIG_DVB_DIB7000P) || (defined(CONFIG_DVB_DIB7000P_MODULE) && \
-				     defined(MODULE))
-extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap,
-					    u8 i2c_addr,
-					    struct dib7000p_config *cfg);
-extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *,
-						   enum dibx000_i2c_interface,
-						   int);
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
-				    int no_of_demods, u8 default_addr,
-				    struct dib7000p_config cfg[]);
+					defined(MODULE))
+extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
+extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
 extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
 extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
 extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
 extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
 extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
+extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
+extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
+extern int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart);
+extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
+extern int dib7090_get_adc_power(struct dvb_frontend *fe);
+extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
+extern int dib7090_slave_reset(struct dvb_frontend *fe);
 #else
-static inline
-struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
-				     struct dib7000p_config *cfg)
+static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
 
-static inline
-struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe,
-					    enum dibx000_i2c_interface i,
-					    int x)
+static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
 
-static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c,
-					   int no_of_demods, u8 default_addr,
-					   struct dib7000p_config cfg[])
+static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
 
-static inline int dib7000p_set_gpio(struct dvb_frontend *fe,
-				    u8 num, u8 dir, u8 val)
+static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
 {
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
@@ -102,16 +97,59 @@
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return -ENODEV;
 }
+
 static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
-    printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-    return -ENODEV;
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
 }
 
 static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
 {
-    printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-    return -ENODEV;
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib7090_slave_reset(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
 }
 #endif
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib8000.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib8000.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib8000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib8000.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,7 @@
 #define LAYER_C   3
 
 #define FE_CALLBACK_TIME_NEVER 0xffffffff
+#define MAX_NUMBER_OF_FRONTENDS 6
 
 static int debug;
 module_param(debug, int, 0644);
@@ -37,7 +38,6 @@
 };
 
 struct dib8000_state {
-	struct dvb_frontend fe;
 	struct dib8000_config cfg;
 
 	struct i2c_device i2c;
@@ -68,6 +68,8 @@
 	u8 isdbt_cfg_loaded;
 	enum frontend_tune_state tune_state;
 	u32 status;
+
+	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
 };
 
 enum dib8000_power_mode {
@@ -122,111 +124,111 @@
 	return dib8000_i2c_write16(&state->i2c, reg, val);
 }
 
-static const int16_t coeff_2k_sb_1seg_dqpsk[8] = {
+static const s16 coeff_2k_sb_1seg_dqpsk[8] = {
 	(769 << 5) | 0x0a, (745 << 5) | 0x03, (595 << 5) | 0x0d, (769 << 5) | 0x0a, (920 << 5) | 0x09, (784 << 5) | 0x02, (519 << 5) | 0x0c,
-	    (920 << 5) | 0x09
+		(920 << 5) | 0x09
 };
 
-static const int16_t coeff_2k_sb_1seg[8] = {
+static const s16 coeff_2k_sb_1seg[8] = {
 	(692 << 5) | 0x0b, (683 << 5) | 0x01, (519 << 5) | 0x09, (692 << 5) | 0x0b, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f, 0 | 0x1f
 };
 
-static const int16_t coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
+static const s16 coeff_2k_sb_3seg_0dqpsk_1dqpsk[8] = {
 	(832 << 5) | 0x10, (912 << 5) | 0x05, (900 << 5) | 0x12, (832 << 5) | 0x10, (-931 << 5) | 0x0f, (912 << 5) | 0x04, (807 << 5) | 0x11,
-	    (-931 << 5) | 0x0f
+		(-931 << 5) | 0x0f
 };
 
-static const int16_t coeff_2k_sb_3seg_0dqpsk[8] = {
+static const s16 coeff_2k_sb_3seg_0dqpsk[8] = {
 	(622 << 5) | 0x0c, (941 << 5) | 0x04, (796 << 5) | 0x10, (622 << 5) | 0x0c, (982 << 5) | 0x0c, (519 << 5) | 0x02, (572 << 5) | 0x0e,
-	    (982 << 5) | 0x0c
+		(982 << 5) | 0x0c
 };
 
-static const int16_t coeff_2k_sb_3seg_1dqpsk[8] = {
+static const s16 coeff_2k_sb_3seg_1dqpsk[8] = {
 	(699 << 5) | 0x14, (607 << 5) | 0x04, (944 << 5) | 0x13, (699 << 5) | 0x14, (-720 << 5) | 0x0d, (640 << 5) | 0x03, (866 << 5) | 0x12,
-	    (-720 << 5) | 0x0d
+		(-720 << 5) | 0x0d
 };
 
-static const int16_t coeff_2k_sb_3seg[8] = {
+static const s16 coeff_2k_sb_3seg[8] = {
 	(664 << 5) | 0x0c, (925 << 5) | 0x03, (937 << 5) | 0x10, (664 << 5) | 0x0c, (-610 << 5) | 0x0a, (697 << 5) | 0x01, (836 << 5) | 0x0e,
-	    (-610 << 5) | 0x0a
+		(-610 << 5) | 0x0a
 };
 
-static const int16_t coeff_4k_sb_1seg_dqpsk[8] = {
+static const s16 coeff_4k_sb_1seg_dqpsk[8] = {
 	(-955 << 5) | 0x0e, (687 << 5) | 0x04, (818 << 5) | 0x10, (-955 << 5) | 0x0e, (-922 << 5) | 0x0d, (750 << 5) | 0x03, (665 << 5) | 0x0f,
-	    (-922 << 5) | 0x0d
+		(-922 << 5) | 0x0d
 };
 
-static const int16_t coeff_4k_sb_1seg[8] = {
+static const s16 coeff_4k_sb_1seg[8] = {
 	(638 << 5) | 0x0d, (683 << 5) | 0x02, (638 << 5) | 0x0d, (638 << 5) | 0x0d, (-655 << 5) | 0x0a, (517 << 5) | 0x00, (698 << 5) | 0x0d,
-	    (-655 << 5) | 0x0a
+		(-655 << 5) | 0x0a
 };
 
-static const int16_t coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
+static const s16 coeff_4k_sb_3seg_0dqpsk_1dqpsk[8] = {
 	(-707 << 5) | 0x14, (910 << 5) | 0x06, (889 << 5) | 0x16, (-707 << 5) | 0x14, (-958 << 5) | 0x13, (993 << 5) | 0x05, (523 << 5) | 0x14,
-	    (-958 << 5) | 0x13
+		(-958 << 5) | 0x13
 };
 
-static const int16_t coeff_4k_sb_3seg_0dqpsk[8] = {
+static const s16 coeff_4k_sb_3seg_0dqpsk[8] = {
 	(-723 << 5) | 0x13, (910 << 5) | 0x05, (777 << 5) | 0x14, (-723 << 5) | 0x13, (-568 << 5) | 0x0f, (547 << 5) | 0x03, (696 << 5) | 0x12,
-	    (-568 << 5) | 0x0f
+		(-568 << 5) | 0x0f
 };
 
-static const int16_t coeff_4k_sb_3seg_1dqpsk[8] = {
+static const s16 coeff_4k_sb_3seg_1dqpsk[8] = {
 	(-940 << 5) | 0x15, (607 << 5) | 0x05, (915 << 5) | 0x16, (-940 << 5) | 0x15, (-848 << 5) | 0x13, (683 << 5) | 0x04, (543 << 5) | 0x14,
-	    (-848 << 5) | 0x13
+		(-848 << 5) | 0x13
 };
 
-static const int16_t coeff_4k_sb_3seg[8] = {
+static const s16 coeff_4k_sb_3seg[8] = {
 	(612 << 5) | 0x12, (910 << 5) | 0x04, (864 << 5) | 0x14, (612 << 5) | 0x12, (-869 << 5) | 0x13, (683 << 5) | 0x02, (869 << 5) | 0x12,
-	    (-869 << 5) | 0x13
+		(-869 << 5) | 0x13
 };
 
-static const int16_t coeff_8k_sb_1seg_dqpsk[8] = {
+static const s16 coeff_8k_sb_1seg_dqpsk[8] = {
 	(-835 << 5) | 0x12, (684 << 5) | 0x05, (735 << 5) | 0x14, (-835 << 5) | 0x12, (-598 << 5) | 0x10, (781 << 5) | 0x04, (739 << 5) | 0x13,
-	    (-598 << 5) | 0x10
+		(-598 << 5) | 0x10
 };
 
-static const int16_t coeff_8k_sb_1seg[8] = {
+static const s16 coeff_8k_sb_1seg[8] = {
 	(673 << 5) | 0x0f, (683 << 5) | 0x03, (808 << 5) | 0x12, (673 << 5) | 0x0f, (585 << 5) | 0x0f, (512 << 5) | 0x01, (780 << 5) | 0x0f,
-	    (585 << 5) | 0x0f
+		(585 << 5) | 0x0f
 };
 
-static const int16_t coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
+static const s16 coeff_8k_sb_3seg_0dqpsk_1dqpsk[8] = {
 	(863 << 5) | 0x17, (930 << 5) | 0x07, (878 << 5) | 0x19, (863 << 5) | 0x17, (0 << 5) | 0x14, (521 << 5) | 0x05, (980 << 5) | 0x18,
-	    (0 << 5) | 0x14
+		(0 << 5) | 0x14
 };
 
-static const int16_t coeff_8k_sb_3seg_0dqpsk[8] = {
+static const s16 coeff_8k_sb_3seg_0dqpsk[8] = {
 	(-924 << 5) | 0x17, (910 << 5) | 0x06, (774 << 5) | 0x17, (-924 << 5) | 0x17, (-877 << 5) | 0x15, (565 << 5) | 0x04, (553 << 5) | 0x15,
-	    (-877 << 5) | 0x15
+		(-877 << 5) | 0x15
 };
 
-static const int16_t coeff_8k_sb_3seg_1dqpsk[8] = {
+static const s16 coeff_8k_sb_3seg_1dqpsk[8] = {
 	(-921 << 5) | 0x19, (607 << 5) | 0x06, (881 << 5) | 0x19, (-921 << 5) | 0x19, (-921 << 5) | 0x14, (713 << 5) | 0x05, (1018 << 5) | 0x18,
-	    (-921 << 5) | 0x14
+		(-921 << 5) | 0x14
 };
 
-static const int16_t coeff_8k_sb_3seg[8] = {
+static const s16 coeff_8k_sb_3seg[8] = {
 	(514 << 5) | 0x14, (910 << 5) | 0x05, (861 << 5) | 0x17, (514 << 5) | 0x14, (690 << 5) | 0x14, (683 << 5) | 0x03, (662 << 5) | 0x15,
-	    (690 << 5) | 0x14
+		(690 << 5) | 0x14
 };
 
-static const int16_t ana_fe_coeff_3seg[24] = {
+static const s16 ana_fe_coeff_3seg[24] = {
 	81, 80, 78, 74, 68, 61, 54, 45, 37, 28, 19, 11, 4, 1022, 1017, 1013, 1010, 1008, 1008, 1008, 1008, 1010, 1014, 1017
 };
 
-static const int16_t ana_fe_coeff_1seg[24] = {
+static const s16 ana_fe_coeff_1seg[24] = {
 	249, 226, 164, 82, 5, 981, 970, 988, 1018, 20, 31, 26, 8, 1012, 1000, 1018, 1012, 8, 15, 14, 9, 3, 1017, 1003
 };
 
-static const int16_t ana_fe_coeff_13seg[24] = {
+static const s16 ana_fe_coeff_13seg[24] = {
 	396, 305, 105, -51, -77, -12, 41, 31, -11, -30, -11, 14, 15, -2, -13, -7, 5, 8, 1, -6, -7, -3, 0, 1
 };
 
 static u16 fft_to_mode(struct dib8000_state *state)
 {
 	u16 mode;
-	switch (state->fe.dtv_property_cache.transmission_mode) {
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
 	case TRANSMISSION_MODE_2K:
 		mode = 1;
 		break;
@@ -249,16 +251,18 @@
 	dprintk("acquisition mode activated");
 	dib8000_write_word(state, 298, nud);
 }
-
-static int dib8000_set_output_mode(struct dib8000_state *state, int mode)
+static int dib8000_set_output_mode(struct dvb_frontend *fe, int mode)
 {
+	struct dib8000_state *state = fe->demodulator_priv;
+
 	u16 outreg, fifo_threshold, smo_mode, sram = 0x0205;	/* by default SDRAM deintlv is enabled */
 
 	outreg = 0;
 	fifo_threshold = 1792;
 	smo_mode = (dib8000_read_word(state, 299) & 0x0050) | (1 << 1);
 
-	dprintk("-I-  Setting output mode for demod %p to %d", &state->fe, mode);
+	dprintk("-I-	Setting output mode for demod %p to %d",
+			&state->fe[0], mode);
 
 	switch (mode) {
 	case OUTMODE_MPEG2_PAR_GATED_CLK:	// STBs with parallel gated clock
@@ -292,7 +296,8 @@
 		break;
 
 	default:
-		dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe);
+		dprintk("Unhandled output_mode passed to be set for demod %p",
+				&state->fe[0]);
 		return -EINVAL;
 	}
 
@@ -342,7 +347,8 @@
 {
 	/* by default everything is going to be powered off */
 	u16 reg_774 = 0x3fff, reg_775 = 0xffff, reg_776 = 0xffff,
-	    reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3, reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
+		reg_900 = (dib8000_read_word(state, 900) & 0xfffc) | 0x3,
+		reg_1280 = (dib8000_read_word(state, 1280) & 0x00ff) | 0xff00;
 
 	/* now, depending on the requested mode, we power on */
 	switch (mode) {
@@ -411,8 +417,9 @@
 	return ret;
 }
 
-static int dib8000_set_bandwidth(struct dib8000_state *state, u32 bw)
+static int dib8000_set_bandwidth(struct dvb_frontend *fe, u32 bw)
 {
+	struct dib8000_state *state = fe->demodulator_priv;
 	u32 timf;
 
 	if (bw == 0)
@@ -478,7 +485,8 @@
 
 	// clk_cfg1
 	clk_cfg1 = (1 << 10) | (0 << 9) | (pll->IO_CLK_en_core << 8) |
-	    (pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) | (pll->pll_range << 1) | (pll->pll_reset << 0);
+		(pll->bypclk_div << 5) | (pll->enable_refdiv << 4) | (1 << 3) |
+		(pll->pll_range << 1) | (pll->pll_reset << 0);
 
 	dib8000_write_word(state, 902, clk_cfg1);
 	clk_cfg1 = (clk_cfg1 & 0xfff7) | (pll->pll_bypass << 3);
@@ -488,11 +496,12 @@
 
 	/* smpl_cfg: P_refclksel=2, P_ensmplsel=1 nodivsmpl=1 */
 	if (state->cfg.pll->ADClkSrc == 0)
-		dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
+		dib8000_write_word(state, 904, (0 << 15) | (0 << 12) | (0 << 10) |
+				(pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
 	else if (state->cfg.refclksel != 0)
-		dib8000_write_word(state, 904,
-				   (0 << 15) | (1 << 12) | ((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) | (pll->
-															ADClkSrc << 7) | (0 << 1));
+		dib8000_write_word(state, 904, (0 << 15) | (1 << 12) |
+				((state->cfg.refclksel & 0x3) << 10) | (pll->modulo << 8) |
+				(pll->ADClkSrc << 7) | (0 << 1));
 	else
 		dib8000_write_word(state, 904, (0 << 15) | (1 << 12) | (3 << 10) | (pll->modulo << 8) | (pll->ADClkSrc << 7) | (0 << 1));
 
@@ -560,7 +569,7 @@
 	0xd4c0,
 
 	/*1, 32,
-	   0x6680 // P_corm_thres Lock algorithms configuration */
+		0x6680 // P_corm_thres Lock algorithms configuration */
 
 	11, 80,			/* set ADC level to -16 */
 	(1 << 13) - 825 - 117,
@@ -623,14 +632,14 @@
 	1, 285,
 	0x0020,			//p_fec_
 	1, 299,
-	0x0062,			// P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard
+	0x0062,			/* P_smo_mode, P_smo_rs_discard, P_smo_fifo_flush, P_smo_pid_parse, P_smo_error_discard */
 
 	1, 338,
 	(1 << 12) |		// P_ctrl_corm_thres4pre_freq_inh=1
-	    (1 << 10) |		// P_ctrl_pre_freq_mode_sat=1
-	    (0 << 9) |		// P_ctrl_pre_freq_inh=0
-	    (3 << 5) |		// P_ctrl_pre_freq_step=3
-	    (1 << 0),		// P_pre_freq_win_len=1
+		(1 << 10) |
+		(0 << 9) |		/* P_ctrl_pre_freq_inh=0 */
+		(3 << 5) |		/* P_ctrl_pre_freq_step=3 */
+		(1 << 0),		/* P_pre_freq_win_len=1 */
 
 	1, 903,
 	(0 << 4) | 2,		// P_divclksel=0 P_divbitsel=2 (was clk=3,bit=1 for MPW)
@@ -717,7 +726,7 @@
 	if (dib8000_reset_gpio(state) != 0)
 		dprintk("GPIO reset was not successful.");
 
-	if (dib8000_set_output_mode(state, OUTMODE_HIGH_Z) != 0)
+	if (dib8000_set_output_mode(fe, OUTMODE_HIGH_Z) != 0)
 		dprintk("OUTPUT_MODE could not be resetted.");
 
 	state->current_agc = NULL;
@@ -752,7 +761,7 @@
 	/* unforce divstr regardless whether i2c enumeration was done or not */
 	dib8000_write_word(state, 1285, dib8000_read_word(state, 1285) & ~(1 << 1));
 
-	dib8000_set_bandwidth(state, 6000);
+	dib8000_set_bandwidth(fe, 6000);
 
 	dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON);
 	dib8000_sad_calib(state);
@@ -778,7 +787,7 @@
 		// read dyn_gain here (because it is demod-dependent and not tuner)
 		dyn_gain = dib8000_read_word(state, 390);
 
-		if (state->cfg.update_lna(&state->fe, dyn_gain)) {	// LNA has changed
+		if (state->cfg.update_lna(state->fe[0], dyn_gain)) {
 			dib8000_restart_agc(state);
 			return 1;
 		}
@@ -865,7 +874,8 @@
 		split_offset = state->current_agc->split.max;
 	else
 		split_offset = state->current_agc->split.max *
-		    (agc - state->current_agc->split.min_thres) / (state->current_agc->split.max_thres - state->current_agc->split.min_thres);
+			(agc - state->current_agc->split.min_thres) /
+			(state->current_agc->split.max_thres - state->current_agc->split.min_thres);
 
 	dprintk("AGC split_offset: %d", split_offset);
 
@@ -900,7 +910,7 @@
 	case CT_AGC_STEP_0:
 		//AGC initialization
 		if (state->cfg.agc_control)
-			state->cfg.agc_control(&state->fe, 1);
+			state->cfg.agc_control(fe, 1);
 
 		dib8000_restart_agc(state);
 
@@ -924,7 +934,7 @@
 		dib8000_agc_soft_split(state);
 
 		if (state->cfg.agc_control)
-			state->cfg.agc_control(&state->fe, 0);
+			state->cfg.agc_control(fe, 0);
 
 		*tune_state = CT_AGC_STOP;
 		break;
@@ -936,29 +946,28 @@
 
 }
 
-static const int32_t lut_1000ln_mant[] =
+static const s32 lut_1000ln_mant[] =
 {
 	908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
 };
 
-int32_t dib8000_get_adc_power(struct dvb_frontend *fe, uint8_t mode)
+s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
 {
-    struct dib8000_state *state = fe->demodulator_priv;
-    uint32_t ix = 0, tmp_val = 0, exp = 0, mant = 0;
-    int32_t val;
+	struct dib8000_state *state = fe->demodulator_priv;
+	u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
+	s32 val;
 
-    val = dib8000_read32(state, 384);
-    /* mode = 1 : ln_agcpower calc using mant-exp conversion and mantis look up table */
-    if (mode) {
-	tmp_val = val;
-	while (tmp_val >>= 1)
-		exp++;
-	mant = (val * 1000 / (1<<exp));
-	ix = (uint8_t)((mant-1000)/100); /* index of the LUT */
-	val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908); /* 1000 * ln(adcpower_real) ; 693 = 1000ln(2) ; 6908 = 1000*ln(1000) ; 20 comes from adc_real = adc_pow_int / 2**20 */
-	val = (val*256)/1000;
-    }
-    return val;
+	val = dib8000_read32(state, 384);
+	if (mode) {
+		tmp_val = val;
+		while (tmp_val >>= 1)
+			exp++;
+		mant = (val * 1000 / (1<<exp));
+		ix = (u8)((mant-1000)/100); /* index of the LUT */
+		val = (lut_1000ln_mant[ix] + 693*(exp-20) - 6908);
+		val = (val*256)/1000;
+	}
+	return val;
 }
 EXPORT_SYMBOL(dib8000_get_adc_power);
 
@@ -1002,22 +1011,23 @@
 		dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
 
 	i = dib8000_read_word(state, 26) & 1;	// P_dds_invspec
-	dib8000_write_word(state, 26, state->fe.dtv_property_cache.inversion ^ i);
+	dib8000_write_word(state, 26, state->fe[0]->dtv_property_cache.inversion^i);
 
-	if (state->fe.dtv_property_cache.isdbt_sb_mode) {
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
 		//compute new dds_freq for the seg and adjust prbs
 		int seg_offset =
-		    state->fe.dtv_property_cache.isdbt_sb_segment_idx - (state->fe.dtv_property_cache.isdbt_sb_segment_count / 2) -
-		    (state->fe.dtv_property_cache.isdbt_sb_segment_count % 2);
+			state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx -
+			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) -
+			(state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2);
 		int clk = state->cfg.pll->internal;
 		u32 segtodds = ((u32) (430 << 23) / clk) << 3;	// segtodds = SegBW / Fclk * pow(2,26)
 		int dds_offset = seg_offset * segtodds;
 		int new_dds, sub_channel;
-		if ((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) == 0)	// if even
+		if ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
 			dds_offset -= (int)(segtodds / 2);
 
 		if (state->cfg.pll->ifreq == 0) {
-			if ((state->fe.dtv_property_cache.inversion ^ i) == 0) {
+			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0) {
 				dib8000_write_word(state, 26, dib8000_read_word(state, 26) | 1);
 				new_dds = dds_offset;
 			} else
@@ -1027,35 +1037,35 @@
 			//  - the segment of center frequency with an odd total number of segments
 			//  - the segment to the left of center frequency with an even total number of segments
 			//  - the segment to the right of center frequency with an even total number of segments
-			if ((state->fe.dtv_property_cache.delivery_system == SYS_ISDBT) && (state->fe.dtv_property_cache.isdbt_sb_mode == 1)
-			    &&
-			    (((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2)
-			      && (state->fe.dtv_property_cache.isdbt_sb_segment_idx ==
-				  ((state->fe.dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-			     || (((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-				 && (state->fe.dtv_property_cache.isdbt_sb_segment_idx == (state->fe.dtv_property_cache.isdbt_sb_segment_count / 2)))
-			     || (((state->fe.dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
-				 && (state->fe.dtv_property_cache.isdbt_sb_segment_idx ==
-				     ((state->fe.dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
-			    )) {
+			if ((state->fe[0]->dtv_property_cache.delivery_system == SYS_ISDBT)
+				&& (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
+					&& (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
+					  && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
+				  ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx == (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2)))
+					 || (((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2) == 0)
+						 && (state->fe[0]->dtv_property_cache.isdbt_sb_segment_idx ==
+							 ((state->fe[0]->dtv_property_cache.isdbt_sb_segment_count / 2) + 1)))
+					)) {
 				new_dds -= ((u32) (850 << 22) / clk) << 4;	// new_dds = 850 (freq shift in KHz) / Fclk * pow(2,26)
 			}
 		} else {
-			if ((state->fe.dtv_property_cache.inversion ^ i) == 0)
+			if ((state->fe[0]->dtv_property_cache.inversion ^ i) == 0)
 				new_dds = state->cfg.pll->ifreq - dds_offset;
 			else
 				new_dds = state->cfg.pll->ifreq + dds_offset;
 		}
 		dib8000_write_word(state, 27, (u16) ((new_dds >> 16) & 0x01ff));
 		dib8000_write_word(state, 28, (u16) (new_dds & 0xffff));
-		if (state->fe.dtv_property_cache.isdbt_sb_segment_count % 2)	// if odd
-			sub_channel = ((state->fe.dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3;
-		else		// if even
-			sub_channel = ((state->fe.dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3;
+		if (state->fe[0]->dtv_property_cache.isdbt_sb_segment_count % 2)
+			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset) + 1) % 41) / 3;
+		else
+			sub_channel = ((state->fe[0]->dtv_property_cache.isdbt_sb_subchannel + (3 * seg_offset)) % 41) / 3;
 		sub_channel -= 6;
 
-		if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K
-		    || state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) {
+		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K
+				|| state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_4K) {
 			dib8000_write_word(state, 219, dib8000_read_word(state, 219) | 0x1);	//adp_pass =1
 			dib8000_write_word(state, 190, dib8000_read_word(state, 190) | (0x1 << 14));	//pha3_force_pha_shift = 1
 		} else {
@@ -1063,7 +1073,7 @@
 			dib8000_write_word(state, 190, dib8000_read_word(state, 190) & 0xbfff);	//pha3_force_pha_shift = 0
 		}
 
-		switch (state->fe.dtv_property_cache.transmission_mode) {
+		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
 		case TRANSMISSION_MODE_2K:
 			switch (sub_channel) {
 			case -6:
@@ -1209,7 +1219,7 @@
 			}
 			break;
 		}
-	} else {		// if not state->fe.dtv_property_cache.isdbt_sb_mode
+	} else {
 		dib8000_write_word(state, 27, (u16) ((state->cfg.pll->ifreq >> 16) & 0x01ff));
 		dib8000_write_word(state, 28, (u16) (state->cfg.pll->ifreq & 0xffff));
 		dib8000_write_word(state, 26, (u16) ((state->cfg.pll->ifreq >> 25) & 0x0003));
@@ -1218,7 +1228,7 @@
 	dib8000_write_word(state, 10, (seq << 4));
 	//  dib8000_write_word(state, 287, (dib8000_read_word(state, 287) & 0xe000) | 0x1000);
 
-	switch (state->fe.dtv_property_cache.guard_interval) {
+	switch (state->fe[0]->dtv_property_cache.guard_interval) {
 	case GUARD_INTERVAL_1_32:
 		guard = 0;
 		break;
@@ -1238,7 +1248,7 @@
 
 	max_constellation = DQPSK;
 	for (i = 0; i < 3; i++) {
-		switch (state->fe.dtv_property_cache.layer[i].modulation) {
+		switch (state->fe[0]->dtv_property_cache.layer[i].modulation) {
 		case DQPSK:
 			constellation = 0;
 			break;
@@ -1254,7 +1264,7 @@
 			break;
 		}
 
-		switch (state->fe.dtv_property_cache.layer[i].fec) {
+		switch (state->fe[0]->dtv_property_cache.layer[i].fec) {
 		case FEC_1_2:
 			crate = 1;
 			break;
@@ -1273,26 +1283,26 @@
 			break;
 		}
 
-		if ((state->fe.dtv_property_cache.layer[i].interleaving > 0) &&
-		    ((state->fe.dtv_property_cache.layer[i].interleaving <= 3) ||
-		     (state->fe.dtv_property_cache.layer[i].interleaving == 4 && state->fe.dtv_property_cache.isdbt_sb_mode == 1))
-		    )
-			timeI = state->fe.dtv_property_cache.layer[i].interleaving;
+		if ((state->fe[0]->dtv_property_cache.layer[i].interleaving > 0) &&
+				((state->fe[0]->dtv_property_cache.layer[i].interleaving <= 3) ||
+				 (state->fe[0]->dtv_property_cache.layer[i].interleaving == 4 && state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1))
+			)
+			timeI = state->fe[0]->dtv_property_cache.layer[i].interleaving;
 		else
 			timeI = 0;
-		dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe.dtv_property_cache.layer[i].segment_count & 0xf) << 6) |
-				   (crate << 3) | timeI);
-		if (state->fe.dtv_property_cache.layer[i].segment_count > 0) {
+		dib8000_write_word(state, 2 + i, (constellation << 10) | ((state->fe[0]->dtv_property_cache.layer[i].segment_count & 0xf) << 6) |
+					(crate << 3) | timeI);
+		if (state->fe[0]->dtv_property_cache.layer[i].segment_count > 0) {
 			switch (max_constellation) {
 			case DQPSK:
 			case QPSK:
-				if (state->fe.dtv_property_cache.layer[i].modulation == QAM_16 ||
-				    state->fe.dtv_property_cache.layer[i].modulation == QAM_64)
-					max_constellation = state->fe.dtv_property_cache.layer[i].modulation;
+				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_16 ||
+					state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
+					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
 				break;
 			case QAM_16:
-				if (state->fe.dtv_property_cache.layer[i].modulation == QAM_64)
-					max_constellation = state->fe.dtv_property_cache.layer[i].modulation;
+				if (state->fe[0]->dtv_property_cache.layer[i].modulation == QAM_64)
+					max_constellation = state->fe[0]->dtv_property_cache.layer[i].modulation;
 				break;
 			}
 		}
@@ -1303,34 +1313,34 @@
 	//dib8000_write_word(state, 5, 13); /*p_last_seg = 13*/
 
 	dib8000_write_word(state, 274, (dib8000_read_word(state, 274) & 0xffcf) |
-			   ((state->fe.dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe.dtv_property_cache.
+				((state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 5) | ((state->fe[0]->dtv_property_cache.
 												 isdbt_sb_mode & 1) << 4));
 
-	dprintk("mode = %d ; guard = %d", mode, state->fe.dtv_property_cache.guard_interval);
+	dprintk("mode = %d ; guard = %d", mode, state->fe[0]->dtv_property_cache.guard_interval);
 
 	/* signal optimization parameter */
 
-	if (state->fe.dtv_property_cache.isdbt_partial_reception) {
-		seg_diff_mask = (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0];
+	if (state->fe[0]->dtv_property_cache.isdbt_partial_reception) {
+		seg_diff_mask = (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) << permu_seg[0];
 		for (i = 1; i < 3; i++)
 			nbseg_diff +=
-			    (state->fe.dtv_property_cache.layer[i].modulation == DQPSK) * state->fe.dtv_property_cache.layer[i].segment_count;
+				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
 		for (i = 0; i < nbseg_diff; i++)
 			seg_diff_mask |= 1 << permu_seg[i + 1];
 	} else {
 		for (i = 0; i < 3; i++)
 			nbseg_diff +=
-			    (state->fe.dtv_property_cache.layer[i].modulation == DQPSK) * state->fe.dtv_property_cache.layer[i].segment_count;
+				(state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * state->fe[0]->dtv_property_cache.layer[i].segment_count;
 		for (i = 0; i < nbseg_diff; i++)
 			seg_diff_mask |= 1 << permu_seg[i];
 	}
 	dprintk("nbseg_diff = %X (%d)", seg_diff_mask, seg_diff_mask);
 
 	state->differential_constellation = (seg_diff_mask != 0);
-	dib8000_set_diversity_in(&state->fe, state->diversity_onoff);
+	dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
 
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {	// ISDB-Tsb
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 1)	// 3-segments
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
 			seg_mask13 = 0x00E0;
 		else		// 1-segment
 			seg_mask13 = 0x0040;
@@ -1340,7 +1350,7 @@
 	// WRITE: Mode & Diff mask
 	dib8000_write_word(state, 0, (mode << 13) | seg_diff_mask);
 
-	if ((seg_diff_mask) || (state->fe.dtv_property_cache.isdbt_sb_mode))
+	if ((seg_diff_mask) || (state->fe[0]->dtv_property_cache.isdbt_sb_mode))
 		dib8000_write_word(state, 268, (dib8000_read_word(state, 268) & 0xF9FF) | 0x0200);
 	else
 		dib8000_write_word(state, 268, (2 << 9) | 39);	//init value
@@ -1351,26 +1361,25 @@
 
 	dib8000_write_word(state, 353, seg_mask13);	// ADDR 353
 
-/*     // P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */
-	// dib8000_write_word(state, 351, (state->fe.dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5 );
+/*	// P_small_narrow_band=0, P_small_last_seg=13, P_small_offset_num_car=5 */
 
 	// ---- SMALL ----
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {
-		switch (state->fe.dtv_property_cache.transmission_mode) {
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		switch (state->fe[0]->dtv_property_cache.transmission_mode) {
 		case TRANSMISSION_MODE_2K:
-			if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) {	// 1-seg
-				if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK)	// DQPSK
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
 					ncoeff = coeff_2k_sb_1seg_dqpsk;
 				else	// QPSK or QAM
 					ncoeff = coeff_2k_sb_1seg;
 			} else {	// 3-segments
-				if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) {	// DQPSK on central segment
-					if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK)	// DQPSK on external segments
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
 						ncoeff = coeff_2k_sb_3seg_0dqpsk_1dqpsk;
 					else	// QPSK or QAM on external segments
 						ncoeff = coeff_2k_sb_3seg_0dqpsk;
 				} else {	// QPSK or QAM on central segment
-					if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK)	// DQPSK on external segments
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK)
 						ncoeff = coeff_2k_sb_3seg_1dqpsk;
 					else	// QPSK or QAM on external segments
 						ncoeff = coeff_2k_sb_3seg;
@@ -1379,20 +1388,20 @@
 			break;
 
 		case TRANSMISSION_MODE_4K:
-			if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) {	// 1-seg
-				if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK)	// DQPSK
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
 					ncoeff = coeff_4k_sb_1seg_dqpsk;
 				else	// QPSK or QAM
 					ncoeff = coeff_4k_sb_1seg;
 			} else {	// 3-segments
-				if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) {	// DQPSK on central segment
-					if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) {	// DQPSK on external segments
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
 						ncoeff = coeff_4k_sb_3seg_0dqpsk_1dqpsk;
 					} else {	// QPSK or QAM on external segments
 						ncoeff = coeff_4k_sb_3seg_0dqpsk;
 					}
 				} else {	// QPSK or QAM on central segment
-					if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) {	// DQPSK on external segments
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
 						ncoeff = coeff_4k_sb_3seg_1dqpsk;
 					} else	// QPSK or QAM on external segments
 						ncoeff = coeff_4k_sb_3seg;
@@ -1403,20 +1412,20 @@
 		case TRANSMISSION_MODE_AUTO:
 		case TRANSMISSION_MODE_8K:
 		default:
-			if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) {	// 1-seg
-				if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK)	// DQPSK
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK)
 					ncoeff = coeff_8k_sb_1seg_dqpsk;
 				else	// QPSK or QAM
 					ncoeff = coeff_8k_sb_1seg;
 			} else {	// 3-segments
-				if (state->fe.dtv_property_cache.layer[0].modulation == DQPSK) {	// DQPSK on central segment
-					if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) {	// DQPSK on external segments
+				if (state->fe[0]->dtv_property_cache.layer[0].modulation == DQPSK) {
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
 						ncoeff = coeff_8k_sb_3seg_0dqpsk_1dqpsk;
 					} else {	// QPSK or QAM on external segments
 						ncoeff = coeff_8k_sb_3seg_0dqpsk;
 					}
 				} else {	// QPSK or QAM on central segment
-					if (state->fe.dtv_property_cache.layer[1].modulation == DQPSK) {	// DQPSK on external segments
+					if (state->fe[0]->dtv_property_cache.layer[1].modulation == DQPSK) {
 						ncoeff = coeff_8k_sb_3seg_1dqpsk;
 					} else	// QPSK or QAM on external segments
 						ncoeff = coeff_8k_sb_3seg;
@@ -1430,22 +1439,22 @@
 
 	// P_small_coef_ext_enable=ISDB-Tsb, P_small_narrow_band=ISDB-Tsb, P_small_last_seg=13, P_small_offset_num_car=5
 	dib8000_write_word(state, 351,
-			   (state->fe.dtv_property_cache.isdbt_sb_mode << 9) | (state->fe.dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5);
+				(state->fe[0]->dtv_property_cache.isdbt_sb_mode << 9) | (state->fe[0]->dtv_property_cache.isdbt_sb_mode << 8) | (13 << 4) | 5);
 
 	// ---- COFF ----
 	// Carloff, the most robust
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {	// Sound Broadcasting mode - use both TMCC and AC pilots
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
 
 		// P_coff_cpil_alpha=4, P_coff_inh=0, P_coff_cpil_winlen=64
 		// P_coff_narrow_band=1, P_coff_square_val=1, P_coff_one_seg=~partial_rcpt, P_coff_use_tmcc=1, P_coff_use_ac=1
 		dib8000_write_word(state, 187,
-				   (4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe.dtv_property_cache.isdbt_partial_reception & 1) << 2)
-				   | 0x3);
+					(4 << 12) | (0 << 11) | (63 << 5) | (0x3 << 3) | ((~state->fe[0]->dtv_property_cache.isdbt_partial_reception & 1) << 2)
+					| 0x3);
 
-/*             // P_small_coef_ext_enable = 1 */
-/*             dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */
+/*		// P_small_coef_ext_enable = 1 */
+/*		dib8000_write_word(state, 351, dib8000_read_word(state, 351) | 0x200); */
 
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) {	// Sound Broadcasting mode 1 seg
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
 
 			// P_coff_winlen=63, P_coff_thres_lock=15, P_coff_one_seg_width= (P_mode == 3) , P_coff_one_seg_sym= (P_mode-1)
 			if (mode == 3)
@@ -1469,10 +1478,10 @@
 			dib8000_write_word(state, 186, 80);
 		} else {	// Sound Broadcasting mode 3 seg
 			// P_coff_one_seg_sym= 1, P_coff_one_seg_width= 1, P_coff_winlen=63, P_coff_thres_lock=15
-			/*                 if (mode == 3) */
-			/*                     dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */
-			/*                 else */
-			/*                     dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */
+			/*	if (mode == 3) */
+			/*		dib8000_write_word(state, 180, 0x2fca | ((0) << 14)); */
+			/*	else */
+			/*		dib8000_write_word(state, 180, 0x2fca | ((1) << 14)); */
 			dib8000_write_word(state, 180, 0x1fcf | (1 << 14));
 
 			// P_ctrl_corm_thres4pre_freq_inh = 1, P_ctrl_pre_freq_mode_sat=1,
@@ -1509,7 +1518,7 @@
 		dib8000_write_word(state, 341, (4 << 3) | (1 << 2) | (1 << 1) | (1 << 0));
 	}
 	// ---- FFT ----
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1 && state->fe.dtv_property_cache.isdbt_partial_reception == 0)	// 1-seg
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 && state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
 		dib8000_write_word(state, 178, 64);	// P_fft_powrange=64
 	else
 		dib8000_write_word(state, 178, 32);	// P_fft_powrange=32
@@ -1518,12 +1527,12 @@
 	 * 6bits; p_coff_thres_lock 6bits (for coff lock if needed)
 	 */
 	/* if ( ( nbseg_diff>0)&&(nbseg_diff<13))
-	   dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */
+		dib8000_write_word(state, 187, (dib8000_read_word(state, 187) & 0xfffb) | (1 << 3)); */
 
 	dib8000_write_word(state, 189, ~seg_mask13 | seg_diff_mask);	/* P_lmod4_seg_inh       */
 	dib8000_write_word(state, 192, ~seg_mask13 | seg_diff_mask);	/* P_pha3_seg_inh        */
 	dib8000_write_word(state, 225, ~seg_mask13 | seg_diff_mask);	/* P_tac_seg_inh         */
-	if ((!state->fe.dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0))
+	if ((!state->fe[0]->dtv_property_cache.isdbt_sb_mode) && (state->cfg.pll->ifreq == 0))
 		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask | 0x40);	/* P_equal_noise_seg_inh */
 	else
 		dib8000_write_word(state, 266, ~seg_mask13 | seg_diff_mask);	/* P_equal_noise_seg_inh */
@@ -1538,8 +1547,8 @@
 	dib8000_write_word(state, 211, seg_mask13 & (~seg_diff_mask));	/* P_des_seg_enabled     */
 
 	/* offset loop parameters */
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 0)	// Sound Broadcasting mode 1 seg
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
 			/* P_timf_alpha = (11-P_mode), P_corm_alpha=6, P_corm_thres=0x80 */
 			dib8000_write_word(state, 32, ((11 - mode) << 12) | (6 << 8) | 0x40);
 
@@ -1551,8 +1560,8 @@
 		/* P_timf_alpha = (9-P_mode, P_corm_alpha=6, P_corm_thres=0x80 */
 		dib8000_write_word(state, 32, ((9 - mode) << 12) | (6 << 8) | 0x80);
 
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 0)	// Sound Broadcasting mode 1 seg
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
 			/* P_ctrl_pha_off_max=3   P_ctrl_sfreq_inh =0  P_ctrl_sfreq_step = (11-P_mode)  */
 			dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (10 - mode));
 
@@ -1564,7 +1573,7 @@
 		dib8000_write_word(state, 37, (3 << 5) | (0 << 4) | (8 - mode));
 
 	/* P_dvsy_sync_wait - reuse mode */
-	switch (state->fe.dtv_property_cache.transmission_mode) {
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
 	case TRANSMISSION_MODE_8K:
 		mode = 256;
 		break;
@@ -1624,15 +1633,15 @@
 	}
 
 	// ---- ANA_FE ----
-	if (state->fe.dtv_property_cache.isdbt_sb_mode) {
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 1)	// 3-segments
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 1)
 			ana_fe = ana_fe_coeff_3seg;
 		else		// 1-segment
 			ana_fe = ana_fe_coeff_1seg;
 	} else
 		ana_fe = ana_fe_coeff_13seg;
 
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0)
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1 || state->isdbt_cfg_loaded == 0)
 		for (mode = 0; mode < 24; mode++)
 			dib8000_write_word(state, 117 + mode, ana_fe[mode]);
 
@@ -1648,11 +1657,11 @@
 	// "P_cspu_left_edge"  not used => do not care
 	// "P_cspu_right_edge" not used => do not care
 
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {	// ISDB-Tsb
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
 		dib8000_write_word(state, 228, 1);	// P_2d_mode_byp=1
 		dib8000_write_word(state, 205, dib8000_read_word(state, 205) & 0xfff0);	// P_cspu_win_cut = 0
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 0	// 1-segment
-		    && state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0
+			&& state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_2K) {
 			//dib8000_write_word(state, 219, dib8000_read_word(state, 219) & 0xfffe); // P_adp_pass = 0
 			dib8000_write_word(state, 265, 15);	// P_equal_noise_sel = 15
 		}
@@ -1664,7 +1673,7 @@
 	// ---- TMCC ----
 	for (i = 0; i < 3; i++)
 		tmcc_pow +=
-		    (((state->fe.dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe.dtv_property_cache.layer[i].segment_count);
+			(((state->fe[0]->dtv_property_cache.layer[i].modulation == DQPSK) * 4 + 1) * state->fe[0]->dtv_property_cache.layer[i].segment_count);
 	// Quantif of "P_tmcc_dec_thres_?k" is (0, 5+mode, 9);
 	// Threshold is set at 1/4 of max power.
 	tmcc_pow *= (1 << (9 - 2));
@@ -1678,7 +1687,7 @@
 	if (state->isdbt_cfg_loaded == 0)
 		dib8000_write_word(state, 250, 3285);	/*p_2d_hspeed_thr0 */
 
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1)
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1)
 		state->isdbt_cfg_loaded = 0;
 	else
 		state->isdbt_cfg_loaded = 1;
@@ -1693,38 +1702,38 @@
 
 	int slist = 0;
 
-	state->fe.dtv_property_cache.inversion = 0;
-	if (!state->fe.dtv_property_cache.isdbt_sb_mode)
-		state->fe.dtv_property_cache.layer[0].segment_count = 13;
-	state->fe.dtv_property_cache.layer[0].modulation = QAM_64;
-	state->fe.dtv_property_cache.layer[0].fec = FEC_2_3;
-	state->fe.dtv_property_cache.layer[0].interleaving = 0;
+	state->fe[0]->dtv_property_cache.inversion = 0;
+	if (!state->fe[0]->dtv_property_cache.isdbt_sb_mode)
+		state->fe[0]->dtv_property_cache.layer[0].segment_count = 13;
+	state->fe[0]->dtv_property_cache.layer[0].modulation = QAM_64;
+	state->fe[0]->dtv_property_cache.layer[0].fec = FEC_2_3;
+	state->fe[0]->dtv_property_cache.layer[0].interleaving = 0;
 
 	//choose the right list, in sb, always do everything
-	if (state->fe.dtv_property_cache.isdbt_sb_mode) {
-		state->fe.dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		state->fe.dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode) {
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
 		slist = 7;
 		dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));
 	} else {
-		if (state->fe.dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
-			if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
+		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) {
+			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
 				slist = 7;
 				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1 to have autosearch start ok with mode2
 			} else
 				slist = 3;
 		} else {
-			if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
+			if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) {
 				slist = 2;
 				dib8000_write_word(state, 0, (dib8000_read_word(state, 0) & 0x9fff) | (1 << 13));	// P_mode = 1
 			} else
 				slist = 0;
 		}
 
-		if (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO)
-			state->fe.dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
-		if (state->fe.dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO)
-			state->fe.dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+		if (state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO)
+			state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		if (state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO)
+			state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
 
 		dprintk("using list for autosearch : %d", slist);
 		dib8000_set_channel(state, (unsigned char)slist, 1);
@@ -1786,7 +1795,7 @@
 	if (state == NULL)
 		return -EINVAL;
 
-	dib8000_set_bandwidth(state, state->fe.dtv_property_cache.bandwidth_hz / 1000);
+	dib8000_set_bandwidth(fe, state->fe[0]->dtv_property_cache.bandwidth_hz / 1000);
 	dib8000_set_channel(state, 0, 0);
 
 	// restart demod
@@ -1799,17 +1808,16 @@
 
 	// never achieved a lock before - wait for timfreq to update
 	if (state->timf == 0) {
-		if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {
-			if (state->fe.dtv_property_cache.isdbt_partial_reception == 0)	// Sound Broadcasting mode 1 seg
+		if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+			if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0)
 				msleep(300);
 			else	// Sound Broadcasting mode 3 seg
 				msleep(500);
 		} else		// 13 seg
 			msleep(200);
 	}
-	//dump_reg(state);
-	if (state->fe.dtv_property_cache.isdbt_sb_mode == 1) {
-		if (state->fe.dtv_property_cache.isdbt_partial_reception == 0) {	// Sound Broadcasting mode 1 seg
+	if (state->fe[0]->dtv_property_cache.isdbt_sb_mode == 1) {
+		if (state->fe[0]->dtv_property_cache.isdbt_partial_reception == 0) {
 
 			/* P_timf_alpha = (13-P_mode) , P_corm_alpha=6, P_corm_thres=0x40  alpha to check on board */
 			dib8000_write_word(state, 32, ((13 - mode) << 12) | (6 << 8) | 0x40);
@@ -1854,26 +1862,38 @@
 static int dib8000_wakeup(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	int ret;
 
 	dib8000_set_power_mode(state, DIB8000M_POWER_ALL);
 	dib8000_set_adc_state(state, DIBX000_ADC_ON);
 	if (dib8000_set_adc_state(state, DIBX000_SLOW_ADC_ON) != 0)
 		dprintk("could not start Slow ADC");
 
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		ret = state->fe[index_frontend]->ops.init(state->fe[index_frontend]);
+		if (ret < 0)
+			return ret;
+	}
+
 	return 0;
 }
 
 static int dib8000_sleep(struct dvb_frontend *fe)
 {
-	struct dib8000_state *st = fe->demodulator_priv;
-	if (1) {
-		dib8000_set_output_mode(st, OUTMODE_HIGH_Z);
-		dib8000_set_power_mode(st, DIB8000M_POWER_INTERFACE_ONLY);
-		return dib8000_set_adc_state(st, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(st, DIBX000_ADC_OFF);
-	} else {
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	int ret;
 
-		return 0;
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
+		if (ret < 0)
+			return ret;
 	}
+
+	dib8000_set_output_mode(fe, OUTMODE_HIGH_Z);
+	dib8000_set_power_mode(state, DIB8000M_POWER_INTERFACE_ONLY);
+	return dib8000_set_adc_state(state, DIBX000_SLOW_ADC_OFF) | dib8000_set_adc_state(state, DIBX000_ADC_OFF);
 }
 
 enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
@@ -1891,16 +1911,40 @@
 }
 EXPORT_SYMBOL(dib8000_set_tune_state);
 
-
-
-
 static int dib8000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
 	u16 i, val = 0;
+	fe_status_t stat;
+	u8 index_frontend, sub_index_frontend;
 
 	fe->dtv_property_cache.bandwidth_hz = 6000000;
 
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
+		if (stat&FE_HAS_SYNC) {
+			dprintk("TMCC lock on the slave%i", index_frontend);
+			/* synchronize the cache with the other frontends */
+			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
+			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL); sub_index_frontend++) {
+				if (sub_index_frontend != index_frontend) {
+					state->fe[sub_index_frontend]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
+					state->fe[sub_index_frontend]->dtv_property_cache.inversion = state->fe[index_frontend]->dtv_property_cache.inversion;
+					state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode = state->fe[index_frontend]->dtv_property_cache.transmission_mode;
+					state->fe[sub_index_frontend]->dtv_property_cache.guard_interval = state->fe[index_frontend]->dtv_property_cache.guard_interval;
+					state->fe[sub_index_frontend]->dtv_property_cache.isdbt_partial_reception = state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception;
+					for (i = 0; i < 3; i++) {
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].segment_count = state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count;
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].interleaving = state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving;
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].fec = state->fe[index_frontend]->dtv_property_cache.layer[i].fec;
+						state->fe[sub_index_frontend]->dtv_property_cache.layer[i].modulation = state->fe[index_frontend]->dtv_property_cache.layer[i].modulation;
+					}
+				}
+			}
+			return 0;
+		}
+	}
+
 	fe->dtv_property_cache.isdbt_sb_mode = dib8000_read_word(state, 508) & 0x1;
 
 	val = dib8000_read_word(state, 570);
@@ -1992,112 +2036,200 @@
 			break;
 		}
 	}
+
+	/* synchronize the cache with the other frontends */
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode = fe->dtv_property_cache.isdbt_sb_mode;
+		state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
+		state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
+		state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
+		state->fe[index_frontend]->dtv_property_cache.isdbt_partial_reception = fe->dtv_property_cache.isdbt_partial_reception;
+		for (i = 0; i < 3; i++) {
+			state->fe[index_frontend]->dtv_property_cache.layer[i].segment_count = fe->dtv_property_cache.layer[i].segment_count;
+			state->fe[index_frontend]->dtv_property_cache.layer[i].interleaving = fe->dtv_property_cache.layer[i].interleaving;
+			state->fe[index_frontend]->dtv_property_cache.layer[i].fec = fe->dtv_property_cache.layer[i].fec;
+			state->fe[index_frontend]->dtv_property_cache.layer[i].modulation = fe->dtv_property_cache.layer[i].modulation;
+		}
+	}
 	return 0;
 }
 
 static int dib8000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
+	u8 nbr_pending, exit_condition, index_frontend;
+	s8 index_frontend_success = -1;
 	int time, ret;
+	int  time_slave = FE_CALLBACK_TIME_NEVER;
 
-	fe->dtv_property_cache.delivery_system = SYS_ISDBT;
+	if (state->fe[0]->dtv_property_cache.frequency == 0) {
+		dprintk("dib8000: must at least specify frequency ");
+		return 0;
+	}
 
-	dib8000_set_output_mode(state, OUTMODE_HIGH_Z);
+	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
+		dprintk("dib8000: no bandwidth specified, set to default ");
+		state->fe[0]->dtv_property_cache.bandwidth_hz = 6000000;
+	}
 
-	if (fe->ops.tuner_ops.set_params)
-		fe->ops.tuner_ops.set_params(fe, fep);
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		/* synchronization of the cache */
+		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_ISDBT;
+		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
+
+		dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
+		if (state->fe[index_frontend]->ops.tuner_ops.set_params)
+			state->fe[index_frontend]->ops.tuner_ops.set_params(state->fe[index_frontend], fep);
+
+		dib8000_set_tune_state(state->fe[index_frontend], CT_AGC_START);
+	}
 
 	/* start up the AGC */
-	state->tune_state = CT_AGC_START;
 	do {
-		time = dib8000_agc_startup(fe);
+		time = dib8000_agc_startup(state->fe[0]);
+		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			time_slave = dib8000_agc_startup(state->fe[index_frontend]);
+			if (time == FE_CALLBACK_TIME_NEVER)
+				time = time_slave;
+			else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
+				time = time_slave;
+		}
 		if (time != FE_CALLBACK_TIME_NEVER)
 			msleep(time / 10);
 		else
 			break;
-	} while (state->tune_state != CT_AGC_STOP);
-
-	if (state->fe.dtv_property_cache.frequency == 0) {
-		dprintk("dib8000: must at least specify frequency ");
-		return 0;
-	}
+		exit_condition = 1;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
+				exit_condition = 0;
+				break;
+			}
+		}
+	} while (exit_condition == 0);
 
-	if (state->fe.dtv_property_cache.bandwidth_hz == 0) {
-		dprintk("dib8000: no bandwidth specified, set to default ");
-		state->fe.dtv_property_cache.bandwidth_hz = 6000000;
-	}
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		dib8000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
 
-	state->tune_state = CT_DEMOD_START;
+	if ((state->fe[0]->dtv_property_cache.delivery_system != SYS_ISDBT) ||
+			(state->fe[0]->dtv_property_cache.inversion == INVERSION_AUTO) ||
+			(state->fe[0]->dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
+			(state->fe[0]->dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
+			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
+			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0xff) &&
+			 (state->fe[0]->dtv_property_cache.layer[0].segment_count != 0) &&
+			 ((state->fe[0]->dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
+			  (state->fe[0]->dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
+			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
+			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0xff) &&
+			 (state->fe[0]->dtv_property_cache.layer[1].segment_count != 0) &&
+			 ((state->fe[0]->dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
+			  (state->fe[0]->dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
+			(((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
+			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0xff) &&
+			 (state->fe[0]->dtv_property_cache.layer[2].segment_count != 0) &&
+			 ((state->fe[0]->dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
+			  (state->fe[0]->dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
+			(((state->fe[0]->dtv_property_cache.layer[0].segment_count == 0) ||
+			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
+			 ((state->fe[0]->dtv_property_cache.layer[1].segment_count == 0) ||
+			  ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
+			 ((state->fe[0]->dtv_property_cache.layer[2].segment_count == 0) || ((state->fe[0]->dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
+		int i = 80000;
+		u8 found = 0;
+		u8 tune_failed = 0;
 
-	if ((state->fe.dtv_property_cache.delivery_system != SYS_ISDBT) ||
-	    (state->fe.dtv_property_cache.inversion == INVERSION_AUTO) ||
-	    (state->fe.dtv_property_cache.transmission_mode == TRANSMISSION_MODE_AUTO) ||
-	    (state->fe.dtv_property_cache.guard_interval == GUARD_INTERVAL_AUTO) ||
-	    (((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 0)) != 0) &&
-	     (state->fe.dtv_property_cache.layer[0].segment_count != 0xff) &&
-	     (state->fe.dtv_property_cache.layer[0].segment_count != 0) &&
-	     ((state->fe.dtv_property_cache.layer[0].modulation == QAM_AUTO) ||
-	      (state->fe.dtv_property_cache.layer[0].fec == FEC_AUTO))) ||
-	    (((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 1)) != 0) &&
-	     (state->fe.dtv_property_cache.layer[1].segment_count != 0xff) &&
-	     (state->fe.dtv_property_cache.layer[1].segment_count != 0) &&
-	     ((state->fe.dtv_property_cache.layer[1].modulation == QAM_AUTO) ||
-	      (state->fe.dtv_property_cache.layer[1].fec == FEC_AUTO))) ||
-	    (((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 2)) != 0) &&
-	     (state->fe.dtv_property_cache.layer[2].segment_count != 0xff) &&
-	     (state->fe.dtv_property_cache.layer[2].segment_count != 0) &&
-	     ((state->fe.dtv_property_cache.layer[2].modulation == QAM_AUTO) ||
-	      (state->fe.dtv_property_cache.layer[2].fec == FEC_AUTO))) ||
-	    (((state->fe.dtv_property_cache.layer[0].segment_count == 0) ||
-	      ((state->fe.dtv_property_cache.isdbt_layer_enabled & (1 << 0)) == 0)) &&
-	     ((state->fe.dtv_property_cache.layer[1].segment_count == 0) ||
-	      ((state->fe.dtv_property_cache.isdbt_layer_enabled & (2 << 0)) == 0)) &&
-	     ((state->fe.dtv_property_cache.layer[2].segment_count == 0) || ((state->fe.dtv_property_cache.isdbt_layer_enabled & (3 << 0)) == 0)))) {
-		int i = 800, found;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			dib8000_set_bandwidth(state->fe[index_frontend], fe->dtv_property_cache.bandwidth_hz / 1000);
+			dib8000_autosearch_start(state->fe[index_frontend]);
+		}
 
-		dib8000_set_bandwidth(state, fe->dtv_property_cache.bandwidth_hz / 1000);
-		dib8000_autosearch_start(fe);
 		do {
-			msleep(10);
-			found = dib8000_autosearch_irq(fe);
-		} while (found == 0 && i--);
+			msleep(20);
+			nbr_pending = 0;
+			exit_condition = 0; /* 0: tune pending; 1: tune failed; 2:tune success */
+			for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+				if (((tune_failed >> index_frontend) & 0x1) == 0) {
+					found = dib8000_autosearch_irq(state->fe[index_frontend]);
+					switch (found) {
+					case 0: /* tune pending */
+						 nbr_pending++;
+						 break;
+					case 2:
+						 dprintk("autosearch succeed on the frontend%i", index_frontend);
+						 exit_condition = 2;
+						 index_frontend_success = index_frontend;
+						 break;
+					default:
+						 dprintk("unhandled autosearch result");
+					case 1:
+						 dprintk("autosearch failed for the frontend%i", index_frontend);
+						 break;
+					}
+				}
+			}
 
-		dprintk("Frequency %d Hz, autosearch returns: %d", fep->frequency, found);
+			/* if all tune are done and no success, exit: tune failed */
+			if ((nbr_pending == 0) && (exit_condition == 0))
+				exit_condition = 1;
+		} while ((exit_condition == 0) && i--);
 
-		if (found == 0 || found == 1)
-			return 0;	// no channel found
+		if (exit_condition == 1) { /* tune failed */
+			dprintk("tune failed");
+			return 0;
+		}
+
+		dprintk("tune success on frontend%i", index_frontend_success);
 
 		dib8000_get_frontend(fe, fep);
 	}
 
-	ret = dib8000_tune(fe);
+	for (index_frontend = 0, ret = 0; (ret >= 0) && (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		ret = dib8000_tune(state->fe[index_frontend]);
 
-	/* make this a config parameter */
-	dib8000_set_output_mode(state, state->cfg.output_mode);
+	/* set output mode and diversity input */
+	dib8000_set_output_mode(state->fe[0], state->cfg.output_mode);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		dib8000_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
+		dib8000_set_diversity_in(state->fe[index_frontend-1], 1);
+	}
+
+	/* turn off the diversity of the last chip */
+	dib8000_set_diversity_in(state->fe[index_frontend-1], 0);
 
 	return ret;
 }
 
+static u16 dib8000_read_lock(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	return dib8000_read_word(state, 568);
+}
+
 static int dib8000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
-	u16 lock = dib8000_read_word(state, 568);
+	u16 lock_slave = 0, lock = dib8000_read_word(state, 568);
+	u8 index_frontend;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		lock_slave |= dib8000_read_lock(state->fe[index_frontend]);
 
 	*stat = 0;
 
-	if ((lock >> 13) & 1)
+	if (((lock >> 13) & 1) || ((lock_slave >> 13) & 1))
 		*stat |= FE_HAS_SIGNAL;
 
-	if ((lock >> 8) & 1) /* Equal */
+	if (((lock >> 8) & 1) || ((lock_slave >> 8) & 1)) /* Equal */
 		*stat |= FE_HAS_CARRIER;
 
-	if (((lock >> 1) & 0xf) == 0xf) /* TMCC_SYNC */
+	if ((((lock >> 1) & 0xf) == 0xf) || (((lock_slave >> 1) & 0xf) == 0xf)) /* TMCC_SYNC */
 		*stat |= FE_HAS_SYNC;
 
-	if (((lock >> 12) & 1) && ((lock >> 5) & 7)) /* FEC MPEG */
+	if ((((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) && ((lock >> 5) & 7)) /* FEC MPEG */
 		*stat |= FE_HAS_LOCK;
 
-	if ((lock >> 12) & 1) {
+	if (((lock >> 12) & 1) || ((lock_slave >> 12) & 1)) {
 		lock = dib8000_read_word(state, 554); /* Viterbi Layer A */
 		if (lock & 0x01)
 			*stat |= FE_HAS_VITERBI;
@@ -2131,44 +2263,120 @@
 static int dib8000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
-	u16 val = dib8000_read_word(state, 390);
-	*strength = 65535 - val;
+	u8 index_frontend;
+	u16 val;
+
+	*strength = 0;
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
+		if (val > 65535 - *strength)
+			*strength = 65535;
+		else
+			*strength += val;
+	}
+
+	val = 65535 - dib8000_read_word(state, 390);
+	if (val > 65535 - *strength)
+		*strength = 65535;
+	else
+		*strength += val;
 	return 0;
 }
 
-static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
+static u32 dib8000_get_snr(struct dvb_frontend *fe)
 {
 	struct dib8000_state *state = fe->demodulator_priv;
+	u32 n, s, exp;
 	u16 val;
-	s32 signal_mant, signal_exp, noise_mant, noise_exp;
-	u32 result = 0;
 
 	val = dib8000_read_word(state, 542);
-	noise_mant = (val >> 6) & 0xff;
-	noise_exp = (val & 0x3f);
+	n = (val >> 6) & 0xff;
+	exp = (val & 0x3f);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	n <<= exp+16;
 
 	val = dib8000_read_word(state, 543);
-	signal_mant = (val >> 6) & 0xff;
-	signal_exp = (val & 0x3f);
+	s = (val >> 6) & 0xff;
+	exp = (val & 0x3f);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	s <<= exp+16;
 
-	if ((noise_exp & 0x20) != 0)
-		noise_exp -= 0x40;
-	if ((signal_exp & 0x20) != 0)
-		signal_exp -= 0x40;
+	if (n > 0) {
+		u32 t = (s/n) << 16;
+		return t + ((s << 16) - n*t) / n;
+	}
+	return 0xffffffff;
+}
 
-	if (signal_mant != 0)
-		result = intlog10(2) * 10 * signal_exp + 10 * intlog10(signal_mant);
-	else
-		result = intlog10(2) * 10 * signal_exp - 100;
-	if (noise_mant != 0)
-		result -= intlog10(2) * 10 * noise_exp + 10 * intlog10(noise_mant);
+static int dib8000_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u32 snr_master;
+
+	snr_master = dib8000_get_snr(fe);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		snr_master += dib8000_get_snr(state->fe[index_frontend]);
+
+	if (snr_master != 0) {
+		snr_master = 10*intlog10(snr_master>>16);
+		*snr = snr_master / ((1 << 24) / 10);
+	}
 	else
-		result -= intlog10(2) * 10 * noise_exp - 100;
+		*snr = 0;
 
-	*snr = result / ((1 << 24) / 10);
 	return 0;
 }
 
+int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
+		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
+		state->fe[index_frontend] = fe_slave;
+		return 0;
+	}
+
+	dprintk("too many slave frontend");
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(dib8000_set_slave_frontend);
+
+int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend != 1) {
+		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend-1], index_frontend-1);
+		state->fe[index_frontend] = NULL;
+		return 0;
+	}
+
+	dprintk("no frontend to be removed");
+	return -ENODEV;
+}
+EXPORT_SYMBOL(dib8000_remove_slave_frontend);
+
+struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	struct dib8000_state *state = fe->demodulator_priv;
+
+	if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
+		return NULL;
+	return state->fe[slave_index];
+}
+EXPORT_SYMBOL(dib8000_get_slave_frontend);
+
+
 int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
 {
 	int k = 0;
@@ -2227,7 +2435,13 @@
 static void dib8000_release(struct dvb_frontend *fe)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
+	u8 index_frontend;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
+		dvb_frontend_detach(st->fe[index_frontend]);
+
 	dibx000_exit_i2c_master(&st->i2c_master);
+	kfree(st->fe[0]);
 	kfree(st);
 }
 
@@ -2242,19 +2456,19 @@
 int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
-    u16 val = dib8000_read_word(st, 299) & 0xffef;
-    val |= (onoff & 0x1) << 4;
+	u16 val = dib8000_read_word(st, 299) & 0xffef;
+	val |= (onoff & 0x1) << 4;
 
-    dprintk("pid filter enabled %d", onoff);
-    return dib8000_write_word(st, 299, val);
+	dprintk("pid filter enabled %d", onoff);
+	return dib8000_write_word(st, 299, val);
 }
 EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
 
 int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
 {
 	struct dib8000_state *st = fe->demodulator_priv;
-    dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
-    return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
+	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
 }
 EXPORT_SYMBOL(dib8000_pid_filter);
 
@@ -2298,6 +2512,9 @@
 	state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
 	if (state == NULL)
 		return NULL;
+	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
+	if (fe == NULL)
+		goto error;
 
 	memcpy(&state->cfg, cfg, sizeof(struct dib8000_config));
 	state->i2c.adap = i2c_adap;
@@ -2311,9 +2528,9 @@
 	if ((state->cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (state->cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
 		state->cfg.output_mode = OUTMODE_MPEG2_FIFO;
 
-	fe = &state->fe;
+	state->fe[0] = fe;
 	fe->demodulator_priv = state;
-	memcpy(&state->fe.ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
+	memcpy(&state->fe[0]->ops, &dib8000_ops, sizeof(struct dvb_frontend_ops));
 
 	state->timf_default = cfg->pll->timf;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib8000.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib8000.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib8000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib8000.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,6 +50,9 @@
 extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
 extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
 extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
+extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
+extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
 #else
 static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
 {
@@ -111,6 +114,23 @@
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return 0;
 }
+static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
 #endif
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib9000.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib9000.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib9000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib9000.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2351 @@
+/*
+ * Linux-DVB Driver for DiBcom's DiB9000 and demodulator-family.
+ *
+ * Copyright (C) 2005-10 DiBcom (http://www.dibcom.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 Free Software Foundation, version 2.
+ */
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+#include "dvb_math.h"
+#include "dvb_frontend.h"
+
+#include "dib9000.h"
+#include "dibx000_common.h"
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "turn on debugging (default: 0)");
+
+#define dprintk(args...) do { if (debug) { printk(KERN_DEBUG "DiB9000: "); printk(args); printk("\n"); } } while (0)
+#define MAX_NUMBER_OF_FRONTENDS 6
+
+struct i2c_device {
+	struct i2c_adapter *i2c_adap;
+	u8 i2c_addr;
+};
+
+/* lock */
+#define DIB_LOCK struct mutex
+#define DibAcquireLock(lock) do { if (mutex_lock_interruptible(lock) < 0) dprintk("could not get the lock"); } while (0)
+#define DibReleaseLock(lock) mutex_unlock(lock)
+#define DibInitLock(lock) mutex_init(lock)
+#define DibFreeLock(lock)
+
+struct dib9000_state {
+	struct i2c_device i2c;
+
+	struct dibx000_i2c_master i2c_master;
+	struct i2c_adapter tuner_adap;
+	struct i2c_adapter component_bus;
+
+	u16 revision;
+	u8 reg_offs;
+
+	enum frontend_tune_state tune_state;
+	u32 status;
+	struct dvb_frontend_parametersContext channel_status;
+
+	u8 fe_id;
+
+#define DIB9000_GPIO_DEFAULT_DIRECTIONS 0xffff
+	u16 gpio_dir;
+#define DIB9000_GPIO_DEFAULT_VALUES     0x0000
+	u16 gpio_val;
+#define DIB9000_GPIO_DEFAULT_PWM_POS    0xffff
+	u16 gpio_pwm_pos;
+
+	union {			/* common for all chips */
+		struct {
+			u8 mobile_mode:1;
+		} host;
+
+		struct {
+			struct dib9000_fe_memory_map {
+				u16 addr;
+				u16 size;
+			} fe_mm[18];
+			u8 memcmd;
+
+			DIB_LOCK mbx_if_lock;	/* to protect read/write operations */
+			DIB_LOCK mbx_lock;	/* to protect the whole mailbox handling */
+
+			DIB_LOCK mem_lock;	/* to protect the memory accesses */
+			DIB_LOCK mem_mbx_lock;	/* to protect the memory-based mailbox */
+
+#define MBX_MAX_WORDS (256 - 200 - 2)
+#define DIB9000_MSG_CACHE_SIZE 2
+			u16 message_cache[DIB9000_MSG_CACHE_SIZE][MBX_MAX_WORDS];
+			u8 fw_is_running;
+		} risc;
+	} platform;
+
+	union {			/* common for all platforms */
+		struct {
+			struct dib9000_config cfg;
+		} d9;
+	} chip;
+
+	struct dvb_frontend *fe[MAX_NUMBER_OF_FRONTENDS];
+	u16 component_bus_speed;
+};
+
+u32 fe_info[44] = { 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, 0, 0
+};
+
+enum dib9000_power_mode {
+	DIB9000_POWER_ALL = 0,
+
+	DIB9000_POWER_NO,
+	DIB9000_POWER_INTERF_ANALOG_AGC,
+	DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD,
+	DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD,
+	DIB9000_POWER_INTERFACE_ONLY,
+};
+
+enum dib9000_out_messages {
+	OUT_MSG_HBM_ACK,
+	OUT_MSG_HOST_BUF_FAIL,
+	OUT_MSG_REQ_VERSION,
+	OUT_MSG_BRIDGE_I2C_W,
+	OUT_MSG_BRIDGE_I2C_R,
+	OUT_MSG_BRIDGE_APB_W,
+	OUT_MSG_BRIDGE_APB_R,
+	OUT_MSG_SCAN_CHANNEL,
+	OUT_MSG_MONIT_DEMOD,
+	OUT_MSG_CONF_GPIO,
+	OUT_MSG_DEBUG_HELP,
+	OUT_MSG_SUBBAND_SEL,
+	OUT_MSG_ENABLE_TIME_SLICE,
+	OUT_MSG_FE_FW_DL,
+	OUT_MSG_FE_CHANNEL_SEARCH,
+	OUT_MSG_FE_CHANNEL_TUNE,
+	OUT_MSG_FE_SLEEP,
+	OUT_MSG_FE_SYNC,
+	OUT_MSG_CTL_MONIT,
+
+	OUT_MSG_CONF_SVC,
+	OUT_MSG_SET_HBM,
+	OUT_MSG_INIT_DEMOD,
+	OUT_MSG_ENABLE_DIVERSITY,
+	OUT_MSG_SET_OUTPUT_MODE,
+	OUT_MSG_SET_PRIORITARY_CHANNEL,
+	OUT_MSG_ACK_FRG,
+	OUT_MSG_INIT_PMU,
+};
+
+enum dib9000_in_messages {
+	IN_MSG_DATA,
+	IN_MSG_FRAME_INFO,
+	IN_MSG_CTL_MONIT,
+	IN_MSG_ACK_FREE_ITEM,
+	IN_MSG_DEBUG_BUF,
+	IN_MSG_MPE_MONITOR,
+	IN_MSG_RAWTS_MONITOR,
+	IN_MSG_END_BRIDGE_I2C_RW,
+	IN_MSG_END_BRIDGE_APB_RW,
+	IN_MSG_VERSION,
+	IN_MSG_END_OF_SCAN,
+	IN_MSG_MONIT_DEMOD,
+	IN_MSG_ERROR,
+	IN_MSG_FE_FW_DL_DONE,
+	IN_MSG_EVENT,
+	IN_MSG_ACK_CHANGE_SVC,
+	IN_MSG_HBM_PROF,
+};
+
+/* memory_access requests */
+#define FE_MM_W_CHANNEL                   0
+#define FE_MM_W_FE_INFO                   1
+#define FE_MM_RW_SYNC                     2
+
+#define FE_SYNC_CHANNEL          1
+#define FE_SYNC_W_GENERIC_MONIT	 2
+#define FE_SYNC_COMPONENT_ACCESS 3
+
+#define FE_MM_R_CHANNEL_SEARCH_STATE      3
+#define FE_MM_R_CHANNEL_UNION_CONTEXT     4
+#define FE_MM_R_FE_INFO                   5
+#define FE_MM_R_FE_MONITOR                6
+
+#define FE_MM_W_CHANNEL_HEAD              7
+#define FE_MM_W_CHANNEL_UNION             8
+#define FE_MM_W_CHANNEL_CONTEXT           9
+#define FE_MM_R_CHANNEL_UNION            10
+#define FE_MM_R_CHANNEL_CONTEXT          11
+#define FE_MM_R_CHANNEL_TUNE_STATE       12
+
+#define FE_MM_R_GENERIC_MONITORING_SIZE	 13
+#define FE_MM_W_GENERIC_MONITORING	     14
+#define FE_MM_R_GENERIC_MONITORING	     15
+
+#define FE_MM_W_COMPONENT_ACCESS         16
+#define FE_MM_RW_COMPONENT_ACCESS_BUFFER 17
+static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len);
+static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len);
+
+static u16 to_fw_output_mode(u16 mode)
+{
+	switch (mode) {
+	case OUTMODE_HIGH_Z:
+		return 0;
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		return 4;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+		return 8;
+	case OUTMODE_MPEG2_SERIAL:
+		return 16;
+	case OUTMODE_DIVERSITY:
+		return 128;
+	case OUTMODE_MPEG2_FIFO:
+		return 2;
+	case OUTMODE_ANALOG_ADC:
+		return 1;
+	default:
+		return 0;
+	}
+}
+
+static u16 dib9000_read16_attr(struct dib9000_state *state, u16 reg, u8 * b, u32 len, u16 attribute)
+{
+	u32 chunk_size = 126;
+	u32 l;
+	int ret;
+	u8 wb[2] = { reg >> 8, reg & 0xff };
+	struct i2c_msg msg[2] = {
+		{.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
+		{.addr = state->i2c.i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = len},
+	};
+
+	if (state->platform.risc.fw_is_running && (reg < 1024))
+		return dib9000_risc_apb_access_read(state, reg, attribute, NULL, 0, b, len);
+
+	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+		wb[0] |= (1 << 5);
+	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+		wb[0] |= (1 << 4);
+
+	do {
+		l = len < chunk_size ? len : chunk_size;
+		msg[1].len = l;
+		msg[1].buf = b;
+		ret = i2c_transfer(state->i2c.i2c_adap, msg, 2) != 2 ? -EREMOTEIO : 0;
+		if (ret != 0) {
+			dprintk("i2c read error on %d", reg);
+			return -EREMOTEIO;
+		}
+
+		b += l;
+		len -= l;
+
+		if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
+			reg += l / 2;
+	} while ((ret == 0) && len);
+
+	return 0;
+}
+
+static u16 dib9000_i2c_read16(struct i2c_device *i2c, u16 reg)
+{
+	u8 b[2];
+	u8 wb[2] = { reg >> 8, reg & 0xff };
+	struct i2c_msg msg[2] = {
+		{.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = wb, .len = 2},
+		{.addr = i2c->i2c_addr >> 1, .flags = I2C_M_RD, .buf = b, .len = 2},
+	};
+
+	if (i2c_transfer(i2c->i2c_adap, msg, 2) != 2) {
+		dprintk("read register %x error", reg);
+		return 0;
+	}
+
+	return (b[0] << 8) | b[1];
+}
+
+static inline u16 dib9000_read_word(struct dib9000_state *state, u16 reg)
+{
+	u8 b[2];
+	if (dib9000_read16_attr(state, reg, b, 2, 0) != 0)
+		return 0;
+	return (b[0] << 8 | b[1]);
+}
+
+static inline u16 dib9000_read_word_attr(struct dib9000_state *state, u16 reg, u16 attribute)
+{
+	u8 b[2];
+	if (dib9000_read16_attr(state, reg, b, 2, attribute) != 0)
+		return 0;
+	return (b[0] << 8 | b[1]);
+}
+
+#define dib9000_read16_noinc_attr(state, reg, b, len, attribute) dib9000_read16_attr(state, reg, b, len, (attribute) | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+
+static u16 dib9000_write16_attr(struct dib9000_state *state, u16 reg, const u8 * buf, u32 len, u16 attribute)
+{
+	u8 b[255];
+	u32 chunk_size = 126;
+	u32 l;
+	int ret;
+
+	struct i2c_msg msg = {
+		.addr = state->i2c.i2c_addr >> 1, .flags = 0, .buf = b, .len = len + 2
+	};
+
+	if (state->platform.risc.fw_is_running && (reg < 1024)) {
+		if (dib9000_risc_apb_access_write
+		    (state, reg, DATA_BUS_ACCESS_MODE_16BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | attribute, buf, len) != 0)
+			return -EINVAL;
+		return 0;
+	}
+
+	b[0] = (reg >> 8) & 0xff;
+	b[1] = (reg) & 0xff;
+
+	if (attribute & DATA_BUS_ACCESS_MODE_8BIT)
+		b[0] |= (1 << 5);
+	if (attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+		b[0] |= (1 << 4);
+
+	do {
+		l = len < chunk_size ? len : chunk_size;
+		msg.len = l + 2;
+		memcpy(&b[2], buf, l);
+
+		ret = i2c_transfer(state->i2c.i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+
+		buf += l;
+		len -= l;
+
+		if (!(attribute & DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT))
+			reg += l / 2;
+	} while ((ret == 0) && len);
+
+	return ret;
+}
+
+static int dib9000_i2c_write16(struct i2c_device *i2c, u16 reg, u16 val)
+{
+	u8 b[4] = { (reg >> 8) & 0xff, reg & 0xff, (val >> 8) & 0xff, val & 0xff };
+	struct i2c_msg msg = {
+		.addr = i2c->i2c_addr >> 1, .flags = 0, .buf = b, .len = 4
+	};
+
+	return i2c_transfer(i2c->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
+}
+
+static inline int dib9000_write_word(struct dib9000_state *state, u16 reg, u16 val)
+{
+	u8 b[2] = { val >> 8, val & 0xff };
+	return dib9000_write16_attr(state, reg, b, 2, 0);
+}
+
+static inline int dib9000_write_word_attr(struct dib9000_state *state, u16 reg, u16 val, u16 attribute)
+{
+	u8 b[2] = { val >> 8, val & 0xff };
+	return dib9000_write16_attr(state, reg, b, 2, attribute);
+}
+
+#define dib9000_write(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, 0)
+#define dib9000_write16_noinc(state, reg, buf, len) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+#define dib9000_write16_noinc_attr(state, reg, buf, len, attribute) dib9000_write16_attr(state, reg, buf, len, DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT | (attribute))
+
+#define dib9000_mbx_send(state, id, data, len) dib9000_mbx_send_attr(state, id, data, len, 0)
+#define dib9000_mbx_get_message(state, id, msg, len) dib9000_mbx_get_message_attr(state, id, msg, len, 0)
+
+#define MAC_IRQ      (1 << 1)
+#define IRQ_POL_MSK  (1 << 4)
+
+#define dib9000_risc_mem_read_chunks(state, b, len) dib9000_read16_attr(state, 1063, b, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+#define dib9000_risc_mem_write_chunks(state, buf, len) dib9000_write16_attr(state, 1063, buf, len, DATA_BUS_ACCESS_MODE_8BIT | DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT)
+
+static void dib9000_risc_mem_setup_cmd(struct dib9000_state *state, u32 addr, u32 len, u8 reading)
+{
+	u8 b[14] = { 0 };
+
+/*      dprintk("%d memcmd: %d %d %d\n", state->fe_id, addr, addr+len, len); */
+/*      b[0] = 0 << 7; */
+	b[1] = 1;
+
+/*      b[2] = 0; */
+/*      b[3] = 0; */
+	b[4] = (u8) (addr >> 8);
+	b[5] = (u8) (addr & 0xff);
+
+/*      b[10] = 0; */
+/*      b[11] = 0; */
+	b[12] = (u8) (addr >> 8);
+	b[13] = (u8) (addr & 0xff);
+
+	addr += len;
+/*      b[6] = 0; */
+/*      b[7] = 0; */
+	b[8] = (u8) (addr >> 8);
+	b[9] = (u8) (addr & 0xff);
+
+	dib9000_write(state, 1056, b, 14);
+	if (reading)
+		dib9000_write_word(state, 1056, (1 << 15) | 1);
+	state->platform.risc.memcmd = -1;	/* if it was called directly reset it - to force a future setup-call to set it */
+}
+
+static void dib9000_risc_mem_setup(struct dib9000_state *state, u8 cmd)
+{
+	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd & 0x7f];
+	/* decide whether we need to "refresh" the memory controller */
+	if (state->platform.risc.memcmd == cmd &&	/* same command */
+	    !(cmd & 0x80 && m->size < 67))	/* and we do not want to read something with less than 67 bytes looping - working around a bug in the memory controller */
+		return;
+	dib9000_risc_mem_setup_cmd(state, m->addr, m->size, cmd & 0x80);
+	state->platform.risc.memcmd = cmd;
+}
+
+static int dib9000_risc_mem_read(struct dib9000_state *state, u8 cmd, u8 * b, u16 len)
+{
+	if (!state->platform.risc.fw_is_running)
+		return -EIO;
+
+	DibAcquireLock(&state->platform.risc.mem_lock);
+	dib9000_risc_mem_setup(state, cmd | 0x80);
+	dib9000_risc_mem_read_chunks(state, b, len);
+	DibReleaseLock(&state->platform.risc.mem_lock);
+	return 0;
+}
+
+static int dib9000_risc_mem_write(struct dib9000_state *state, u8 cmd, const u8 * b)
+{
+	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[cmd];
+	if (!state->platform.risc.fw_is_running)
+		return -EIO;
+
+	DibAcquireLock(&state->platform.risc.mem_lock);
+	dib9000_risc_mem_setup(state, cmd);
+	dib9000_risc_mem_write_chunks(state, b, m->size);
+	DibReleaseLock(&state->platform.risc.mem_lock);
+	return 0;
+}
+
+static int dib9000_firmware_download(struct dib9000_state *state, u8 risc_id, u16 key, const u8 * code, u32 len)
+{
+	u16 offs;
+
+	if (risc_id == 1)
+		offs = 16;
+	else
+		offs = 0;
+
+	/* config crtl reg */
+	dib9000_write_word(state, 1024 + offs, 0x000f);
+	dib9000_write_word(state, 1025 + offs, 0);
+	dib9000_write_word(state, 1031 + offs, key);
+
+	dprintk("going to download %dB of microcode", len);
+	if (dib9000_write16_noinc(state, 1026 + offs, (u8 *) code, (u16) len) != 0) {
+		dprintk("error while downloading microcode for RISC %c", 'A' + risc_id);
+		return -EIO;
+	}
+
+	dprintk("Microcode for RISC %c loaded", 'A' + risc_id);
+
+	return 0;
+}
+
+static int dib9000_mbx_host_init(struct dib9000_state *state, u8 risc_id)
+{
+	u16 mbox_offs;
+	u16 reset_reg;
+	u16 tries = 1000;
+
+	if (risc_id == 1)
+		mbox_offs = 16;
+	else
+		mbox_offs = 0;
+
+	/* Reset mailbox  */
+	dib9000_write_word(state, 1027 + mbox_offs, 0x8000);
+
+	/* Read reset status */
+	do {
+		reset_reg = dib9000_read_word(state, 1027 + mbox_offs);
+		msleep(100);
+	} while ((reset_reg & 0x8000) && --tries);
+
+	if (reset_reg & 0x8000) {
+		dprintk("MBX: init ERROR, no response from RISC %c", 'A' + risc_id);
+		return -EIO;
+	}
+	dprintk("MBX: initialized");
+	return 0;
+}
+
+#define MAX_MAILBOX_TRY 100
+static int dib9000_mbx_send_attr(struct dib9000_state *state, u8 id, u16 * data, u8 len, u16 attr)
+{
+	u8 *d, b[2];
+	u16 tmp;
+	u16 size;
+	u32 i;
+	int ret = 0;
+
+	if (!state->platform.risc.fw_is_running)
+		return -EINVAL;
+
+	DibAcquireLock(&state->platform.risc.mbx_if_lock);
+	tmp = MAX_MAILBOX_TRY;
+	do {
+		size = dib9000_read_word_attr(state, 1043, attr) & 0xff;
+		if ((size + len + 1) > MBX_MAX_WORDS && --tmp) {
+			dprintk("MBX: RISC mbx full, retrying");
+			msleep(100);
+		} else
+			break;
+	} while (1);
+
+	/*dprintk( "MBX: size: %d", size); */
+
+	if (tmp == 0) {
+		ret = -EINVAL;
+		goto out;
+	}
+#ifdef DUMP_MSG
+	dprintk("--> %02x %d ", id, len + 1);
+	for (i = 0; i < len; i++)
+		dprintk("%04x ", data[i]);
+	dprintk("\n");
+#endif
+
+	/* byte-order conversion - works on big (where it is not necessary) or little endian */
+	d = (u8 *) data;
+	for (i = 0; i < len; i++) {
+		tmp = data[i];
+		*d++ = tmp >> 8;
+		*d++ = tmp & 0xff;
+	}
+
+	/* write msg */
+	b[0] = id;
+	b[1] = len + 1;
+	if (dib9000_write16_noinc_attr(state, 1045, b, 2, attr) != 0 || dib9000_write16_noinc_attr(state, 1045, (u8 *) data, len * 2, attr) != 0) {
+		ret = -EIO;
+		goto out;
+	}
+
+	/* update register nb_mes_in_RX */
+	ret = (u8) dib9000_write_word_attr(state, 1043, 1 << 14, attr);
+
+out:
+	DibReleaseLock(&state->platform.risc.mbx_if_lock);
+
+	return ret;
+}
+
+static u8 dib9000_mbx_read(struct dib9000_state *state, u16 * data, u8 risc_id, u16 attr)
+{
+#ifdef DUMP_MSG
+	u16 *d = data;
+#endif
+
+	u16 tmp, i;
+	u8 size;
+	u8 mc_base;
+
+	if (!state->platform.risc.fw_is_running)
+		return 0;
+
+	DibAcquireLock(&state->platform.risc.mbx_if_lock);
+	if (risc_id == 1)
+		mc_base = 16;
+	else
+		mc_base = 0;
+
+	/* Length and type in the first word */
+	*data = dib9000_read_word_attr(state, 1029 + mc_base, attr);
+
+	size = *data & 0xff;
+	if (size <= MBX_MAX_WORDS) {
+		data++;
+		size--;		/* Initial word already read */
+
+		dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, size * 2, attr);
+
+		/* to word conversion */
+		for (i = 0; i < size; i++) {
+			tmp = *data;
+			*data = (tmp >> 8) | (tmp << 8);
+			data++;
+		}
+
+#ifdef DUMP_MSG
+		dprintk("<-- ");
+		for (i = 0; i < size + 1; i++)
+			dprintk("%04x ", d[i]);
+		dprintk("\n");
+#endif
+	} else {
+		dprintk("MBX: message is too big for message cache (%d), flushing message", size);
+		size--;		/* Initial word already read */
+		while (size--)
+			dib9000_read16_noinc_attr(state, 1029 + mc_base, (u8 *) data, 2, attr);
+	}
+	/* Update register nb_mes_in_TX */
+	dib9000_write_word_attr(state, 1028 + mc_base, 1 << 14, attr);
+
+	DibReleaseLock(&state->platform.risc.mbx_if_lock);
+
+	return size + 1;
+}
+
+static int dib9000_risc_debug_buf(struct dib9000_state *state, u16 * data, u8 size)
+{
+	u32 ts = data[1] << 16 | data[0];
+	char *b = (char *)&data[2];
+
+	b[2 * (size - 2) - 1] = '\0';	/* Bullet proof the buffer */
+	if (*b == '~') {
+		b++;
+		dprintk(b);
+	} else
+		dprintk("RISC%d: %d.%04d %s", state->fe_id, ts / 10000, ts % 10000, *b ? b : "<emtpy>");
+	return 1;
+}
+
+static int dib9000_mbx_fetch_to_cache(struct dib9000_state *state, u16 attr)
+{
+	int i;
+	u8 size;
+	u16 *block;
+	/* find a free slot */
+	for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
+		block = state->platform.risc.message_cache[i];
+		if (*block == 0) {
+			size = dib9000_mbx_read(state, block, 1, attr);
+
+/*                      dprintk( "MBX: fetched %04x message to cache", *block); */
+
+			switch (*block >> 8) {
+			case IN_MSG_DEBUG_BUF:
+				dib9000_risc_debug_buf(state, block + 1, size);	/* debug-messages are going to be printed right away */
+				*block = 0;	/* free the block */
+				break;
+#if 0
+			case IN_MSG_DATA:	/* FE-TRACE */
+				dib9000_risc_data_process(state, block + 1, size);
+				*block = 0;
+				break;
+#endif
+			default:
+				break;
+			}
+
+			return 1;
+		}
+	}
+	dprintk("MBX: no free cache-slot found for new message...");
+	return -1;
+}
+
+static u8 dib9000_mbx_count(struct dib9000_state *state, u8 risc_id, u16 attr)
+{
+	if (risc_id == 0)
+		return (u8) (dib9000_read_word_attr(state, 1028, attr) >> 10) & 0x1f;	/* 5 bit field */
+	else
+		return (u8) (dib9000_read_word_attr(state, 1044, attr) >> 8) & 0x7f;	/* 7 bit field */
+}
+
+static int dib9000_mbx_process(struct dib9000_state *state, u16 attr)
+{
+	int ret = 0;
+	u16 tmp;
+
+	if (!state->platform.risc.fw_is_running)
+		return -1;
+
+	DibAcquireLock(&state->platform.risc.mbx_lock);
+
+	if (dib9000_mbx_count(state, 1, attr))	/* 1=RiscB */
+		ret = dib9000_mbx_fetch_to_cache(state, attr);
+
+	tmp = dib9000_read_word_attr(state, 1229, attr);	/* Clear the IRQ */
+/*      if (tmp) */
+/*              dprintk( "cleared IRQ: %x", tmp); */
+	DibReleaseLock(&state->platform.risc.mbx_lock);
+
+	return ret;
+}
+
+static int dib9000_mbx_get_message_attr(struct dib9000_state *state, u16 id, u16 * msg, u8 * size, u16 attr)
+{
+	u8 i;
+	u16 *block;
+	u16 timeout = 30;
+
+	*msg = 0;
+	do {
+		/* dib9000_mbx_get_from_cache(); */
+		for (i = 0; i < DIB9000_MSG_CACHE_SIZE; i++) {
+			block = state->platform.risc.message_cache[i];
+			if ((*block >> 8) == id) {
+				*size = (*block & 0xff) - 1;
+				memcpy(msg, block + 1, (*size) * 2);
+				*block = 0;	/* free the block */
+				i = 0;	/* signal that we found a message */
+				break;
+			}
+		}
+
+		if (i == 0)
+			break;
+
+		if (dib9000_mbx_process(state, attr) == -1)	/* try to fetch one message - if any */
+			return -1;
+
+	} while (--timeout);
+
+	if (timeout == 0) {
+		dprintk("waiting for message %d timed out", id);
+		return -1;
+	}
+
+	return i == 0;
+}
+
+static int dib9000_risc_check_version(struct dib9000_state *state)
+{
+	u8 r[4];
+	u8 size;
+	u16 fw_version = 0;
+
+	if (dib9000_mbx_send(state, OUT_MSG_REQ_VERSION, &fw_version, 1) != 0)
+		return -EIO;
+
+	if (dib9000_mbx_get_message(state, IN_MSG_VERSION, (u16 *) r, &size) < 0)
+		return -EIO;
+
+	fw_version = (r[0] << 8) | r[1];
+	dprintk("RISC: ver: %d.%02d (IC: %d)", fw_version >> 10, fw_version & 0x3ff, (r[2] << 8) | r[3]);
+
+	if ((fw_version >> 10) != 7)
+		return -EINVAL;
+
+	switch (fw_version & 0x3ff) {
+	case 11:
+	case 12:
+	case 14:
+	case 15:
+	case 16:
+	case 17:
+		break;
+	default:
+		dprintk("RISC: invalid firmware version");
+		return -EINVAL;
+	}
+
+	dprintk("RISC: valid firmware version");
+	return 0;
+}
+
+static int dib9000_fw_boot(struct dib9000_state *state, const u8 * codeA, u32 lenA, const u8 * codeB, u32 lenB)
+{
+	/* Reconfig pool mac ram */
+	dib9000_write_word(state, 1225, 0x02);	/* A: 8k C, 4 k D - B: 32k C 6 k D - IRAM 96k */
+	dib9000_write_word(state, 1226, 0x05);
+
+	/* Toggles IP crypto to Host APB interface. */
+	dib9000_write_word(state, 1542, 1);
+
+	/* Set jump and no jump in the dma box */
+	dib9000_write_word(state, 1074, 0);
+	dib9000_write_word(state, 1075, 0);
+
+	/* Set MAC as APB Master. */
+	dib9000_write_word(state, 1237, 0);
+
+	/* Reset the RISCs */
+	if (codeA != NULL)
+		dib9000_write_word(state, 1024, 2);
+	else
+		dib9000_write_word(state, 1024, 15);
+	if (codeB != NULL)
+		dib9000_write_word(state, 1040, 2);
+
+	if (codeA != NULL)
+		dib9000_firmware_download(state, 0, 0x1234, codeA, lenA);
+	if (codeB != NULL)
+		dib9000_firmware_download(state, 1, 0x1234, codeB, lenB);
+
+	/* Run the RISCs */
+	if (codeA != NULL)
+		dib9000_write_word(state, 1024, 0);
+	if (codeB != NULL)
+		dib9000_write_word(state, 1040, 0);
+
+	if (codeA != NULL)
+		if (dib9000_mbx_host_init(state, 0) != 0)
+			return -EIO;
+	if (codeB != NULL)
+		if (dib9000_mbx_host_init(state, 1) != 0)
+			return -EIO;
+
+	msleep(100);
+	state->platform.risc.fw_is_running = 1;
+
+	if (dib9000_risc_check_version(state) != 0)
+		return -EINVAL;
+
+	state->platform.risc.memcmd = 0xff;
+	return 0;
+}
+
+static u16 dib9000_identify(struct i2c_device *client)
+{
+	u16 value;
+
+	value = dib9000_i2c_read16(client, 896);
+	if (value != 0x01b3) {
+		dprintk("wrong Vendor ID (0x%x)", value);
+		return 0;
+	}
+
+	value = dib9000_i2c_read16(client, 897);
+	if (value != 0x4000 && value != 0x4001 && value != 0x4002 && value != 0x4003 && value != 0x4004 && value != 0x4005) {
+		dprintk("wrong Device ID (0x%x)", value);
+		return 0;
+	}
+
+	/* protect this driver to be used with 7000PC */
+	if (value == 0x4000 && dib9000_i2c_read16(client, 769) == 0x4000) {
+		dprintk("this driver does not work with DiB7000PC");
+		return 0;
+	}
+
+	switch (value) {
+	case 0x4000:
+		dprintk("found DiB7000MA/PA/MB/PB");
+		break;
+	case 0x4001:
+		dprintk("found DiB7000HC");
+		break;
+	case 0x4002:
+		dprintk("found DiB7000MC");
+		break;
+	case 0x4003:
+		dprintk("found DiB9000A");
+		break;
+	case 0x4004:
+		dprintk("found DiB9000H");
+		break;
+	case 0x4005:
+		dprintk("found DiB9000M");
+		break;
+	}
+
+	return value;
+}
+
+static void dib9000_set_power_mode(struct dib9000_state *state, enum dib9000_power_mode mode)
+{
+	/* by default everything is going to be powered off */
+	u16 reg_903 = 0x3fff, reg_904 = 0xffff, reg_905 = 0xffff, reg_906;
+	u8 offset;
+
+	if (state->revision == 0x4003 || state->revision == 0x4004 || state->revision == 0x4005)
+		offset = 1;
+	else
+		offset = 0;
+
+	reg_906 = dib9000_read_word(state, 906 + offset) | 0x3;	/* keep settings for RISC */
+
+	/* now, depending on the requested mode, we power on */
+	switch (mode) {
+		/* power up everything in the demod */
+	case DIB9000_POWER_ALL:
+		reg_903 = 0x0000;
+		reg_904 = 0x0000;
+		reg_905 = 0x0000;
+		reg_906 = 0x0000;
+		break;
+
+		/* just leave power on the control-interfaces: GPIO and (I2C or SDIO or SRAM) */
+	case DIB9000_POWER_INTERFACE_ONLY:	/* TODO power up either SDIO or I2C or SRAM */
+		reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 2));
+		break;
+
+	case DIB9000_POWER_INTERF_ANALOG_AGC:
+		reg_903 &= ~((1 << 15) | (1 << 14) | (1 << 11) | (1 << 10));
+		reg_905 &= ~((1 << 7) | (1 << 6) | (1 << 5) | (1 << 4) | (1 << 2));
+		reg_906 &= ~((1 << 0));
+		break;
+
+	case DIB9000_POWER_COR4_DINTLV_ICIRM_EQUAL_CFROD:
+		reg_903 = 0x0000;
+		reg_904 = 0x801f;
+		reg_905 = 0x0000;
+		reg_906 &= ~((1 << 0));
+		break;
+
+	case DIB9000_POWER_COR4_CRY_ESRAM_MOUT_NUD:
+		reg_903 = 0x0000;
+		reg_904 = 0x8000;
+		reg_905 = 0x010b;
+		reg_906 &= ~((1 << 0));
+		break;
+	default:
+	case DIB9000_POWER_NO:
+		break;
+	}
+
+	/* always power down unused parts */
+	if (!state->platform.host.mobile_mode)
+		reg_904 |= (1 << 7) | (1 << 6) | (1 << 4) | (1 << 2) | (1 << 1);
+
+	/* P_sdio_select_clk = 0 on MC and after */
+	if (state->revision != 0x4000)
+		reg_906 <<= 1;
+
+	dib9000_write_word(state, 903 + offset, reg_903);
+	dib9000_write_word(state, 904 + offset, reg_904);
+	dib9000_write_word(state, 905 + offset, reg_905);
+	dib9000_write_word(state, 906 + offset, reg_906);
+}
+
+static int dib9000_fw_reset(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	dib9000_write_word(state, 1817, 0x0003);
+
+	dib9000_write_word(state, 1227, 1);
+	dib9000_write_word(state, 1227, 0);
+
+	switch ((state->revision = dib9000_identify(&state->i2c))) {
+	case 0x4003:
+	case 0x4004:
+	case 0x4005:
+		state->reg_offs = 1;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* reset the i2c-master to use the host interface */
+	dibx000_reset_i2c_master(&state->i2c_master);
+
+	dib9000_set_power_mode(state, DIB9000_POWER_ALL);
+
+	/* unforce divstr regardless whether i2c enumeration was done or not */
+	dib9000_write_word(state, 1794, dib9000_read_word(state, 1794) & ~(1 << 1));
+	dib9000_write_word(state, 1796, 0);
+	dib9000_write_word(state, 1805, 0x805);
+
+	/* restart all parts */
+	dib9000_write_word(state, 898, 0xffff);
+	dib9000_write_word(state, 899, 0xffff);
+	dib9000_write_word(state, 900, 0x0001);
+	dib9000_write_word(state, 901, 0xff19);
+	dib9000_write_word(state, 902, 0x003c);
+
+	dib9000_write_word(state, 898, 0);
+	dib9000_write_word(state, 899, 0);
+	dib9000_write_word(state, 900, 0);
+	dib9000_write_word(state, 901, 0);
+	dib9000_write_word(state, 902, 0);
+
+	dib9000_write_word(state, 911, state->chip.d9.cfg.if_drives);
+
+	dib9000_set_power_mode(state, DIB9000_POWER_INTERFACE_ONLY);
+
+	return 0;
+}
+
+static int dib9000_risc_apb_access_read(struct dib9000_state *state, u32 address, u16 attribute, const u8 * tx, u32 txlen, u8 * b, u32 len)
+{
+	u16 mb[10];
+	u8 i, s;
+
+	if (address >= 1024 || !state->platform.risc.fw_is_running)
+		return -EINVAL;
+
+	/* dprintk( "APB access thru rd fw %d %x", address, attribute); */
+
+	mb[0] = (u16) address;
+	mb[1] = len / 2;
+	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_R, mb, 2, attribute);
+	switch (dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute)) {
+	case 1:
+		s--;
+		for (i = 0; i < s; i++) {
+			b[i * 2] = (mb[i + 1] >> 8) & 0xff;
+			b[i * 2 + 1] = (mb[i + 1]) & 0xff;
+		}
+		return 0;
+	default:
+		return -EIO;
+	}
+	return -EIO;
+}
+
+static int dib9000_risc_apb_access_write(struct dib9000_state *state, u32 address, u16 attribute, const u8 * b, u32 len)
+{
+	u16 mb[10];
+	u8 s, i;
+
+	if (address >= 1024 || !state->platform.risc.fw_is_running)
+		return -EINVAL;
+
+	/* dprintk( "APB access thru wr fw %d %x", address, attribute); */
+
+	mb[0] = (unsigned short)address;
+	for (i = 0; i < len && i < 20; i += 2)
+		mb[1 + (i / 2)] = (b[i] << 8 | b[i + 1]);
+
+	dib9000_mbx_send_attr(state, OUT_MSG_BRIDGE_APB_W, mb, 1 + len / 2, attribute);
+	return dib9000_mbx_get_message_attr(state, IN_MSG_END_BRIDGE_APB_RW, mb, &s, attribute) == 1 ? 0 : -EINVAL;
+}
+
+static int dib9000_fw_memmbx_sync(struct dib9000_state *state, u8 i)
+{
+	u8 index_loop = 10;
+
+	if (!state->platform.risc.fw_is_running)
+		return 0;
+	dib9000_risc_mem_write(state, FE_MM_RW_SYNC, &i);
+	do {
+		dib9000_risc_mem_read(state, FE_MM_RW_SYNC, &i, 1);
+	} while (i && index_loop--);
+
+	if (index_loop > 0)
+		return 0;
+	return -EIO;
+}
+
+static int dib9000_fw_init(struct dib9000_state *state)
+{
+	struct dibGPIOFunction *f;
+	u16 b[40] = { 0 };
+	u8 i;
+	u8 size;
+
+	if (dib9000_fw_boot(state, NULL, 0, state->chip.d9.cfg.microcode_B_fe_buffer, state->chip.d9.cfg.microcode_B_fe_size) != 0)
+		return -EIO;
+
+	/* initialize the firmware */
+	for (i = 0; i < ARRAY_SIZE(state->chip.d9.cfg.gpio_function); i++) {
+		f = &state->chip.d9.cfg.gpio_function[i];
+		if (f->mask) {
+			switch (f->function) {
+			case BOARD_GPIO_FUNCTION_COMPONENT_ON:
+				b[0] = (u16) f->mask;
+				b[1] = (u16) f->direction;
+				b[2] = (u16) f->value;
+				break;
+			case BOARD_GPIO_FUNCTION_COMPONENT_OFF:
+				b[3] = (u16) f->mask;
+				b[4] = (u16) f->direction;
+				b[5] = (u16) f->value;
+				break;
+			}
+		}
+	}
+	if (dib9000_mbx_send(state, OUT_MSG_CONF_GPIO, b, 15) != 0)
+		return -EIO;
+
+	/* subband */
+	b[0] = state->chip.d9.cfg.subband.size;	/* type == 0 -> GPIO - PWM not yet supported */
+	for (i = 0; i < state->chip.d9.cfg.subband.size; i++) {
+		b[1 + i * 4] = state->chip.d9.cfg.subband.subband[i].f_mhz;
+		b[2 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.mask;
+		b[3 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.direction;
+		b[4 + i * 4] = (u16) state->chip.d9.cfg.subband.subband[i].gpio.value;
+	}
+	b[1 + i * 4] = 0;	/* fe_id */
+	if (dib9000_mbx_send(state, OUT_MSG_SUBBAND_SEL, b, 2 + 4 * i) != 0)
+		return -EIO;
+
+	/* 0 - id, 1 - no_of_frontends */
+	b[0] = (0 << 8) | 1;
+	/* 0 = i2c-address demod, 0 = tuner */
+	b[1] = (0 << 8) | (0);
+	b[2] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000) >> 16) & 0xffff);
+	b[3] = (u16) (((state->chip.d9.cfg.xtal_clock_khz * 1000)) & 0xffff);
+	b[4] = (u16) ((state->chip.d9.cfg.vcxo_timer >> 16) & 0xffff);
+	b[5] = (u16) ((state->chip.d9.cfg.vcxo_timer) & 0xffff);
+	b[6] = (u16) ((state->chip.d9.cfg.timing_frequency >> 16) & 0xffff);
+	b[7] = (u16) ((state->chip.d9.cfg.timing_frequency) & 0xffff);
+	b[29] = state->chip.d9.cfg.if_drives;
+	if (dib9000_mbx_send(state, OUT_MSG_INIT_DEMOD, b, ARRAY_SIZE(b)) != 0)
+		return -EIO;
+
+	if (dib9000_mbx_send(state, OUT_MSG_FE_FW_DL, NULL, 0) != 0)
+		return -EIO;
+
+	if (dib9000_mbx_get_message(state, IN_MSG_FE_FW_DL_DONE, b, &size) < 0)
+		return -EIO;
+
+	if (size > ARRAY_SIZE(b)) {
+		dprintk("error : firmware returned %dbytes needed but the used buffer has only %dbytes\n Firmware init ABORTED", size,
+			(int)ARRAY_SIZE(b));
+		return -EINVAL;
+	}
+
+	for (i = 0; i < size; i += 2) {
+		state->platform.risc.fe_mm[i / 2].addr = b[i + 0];
+		state->platform.risc.fe_mm[i / 2].size = b[i + 1];
+	}
+
+	return 0;
+}
+
+static void dib9000_fw_set_channel_head(struct dib9000_state *state, struct dvb_frontend_parameters *ch)
+{
+	u8 b[9];
+	u32 freq = state->fe[0]->dtv_property_cache.frequency / 1000;
+	if (state->fe_id % 2)
+		freq += 101;
+
+	b[0] = (u8) ((freq >> 0) & 0xff);
+	b[1] = (u8) ((freq >> 8) & 0xff);
+	b[2] = (u8) ((freq >> 16) & 0xff);
+	b[3] = (u8) ((freq >> 24) & 0xff);
+	b[4] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 0) & 0xff);
+	b[5] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 8) & 0xff);
+	b[6] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 16) & 0xff);
+	b[7] = (u8) ((state->fe[0]->dtv_property_cache.bandwidth_hz / 1000 >> 24) & 0xff);
+	b[8] = 0x80;		/* do not wait for CELL ID when doing autosearch */
+	if (state->fe[0]->dtv_property_cache.delivery_system == SYS_DVBT)
+		b[8] |= 1;
+	dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_HEAD, b);
+}
+
+static int dib9000_fw_get_channel(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	struct dibDVBTChannel {
+		s8 spectrum_inversion;
+
+		s8 nfft;
+		s8 guard;
+		s8 constellation;
+
+		s8 hrch;
+		s8 alpha;
+		s8 code_rate_hp;
+		s8 code_rate_lp;
+		s8 select_hp;
+
+		s8 intlv_native;
+	};
+	struct dibDVBTChannel ch;
+	int ret = 0;
+
+	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0) {
+		goto error;
+		ret = -EIO;
+	}
+
+	dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_UNION, (u8 *) &ch, sizeof(struct dibDVBTChannel));
+
+	switch (ch.spectrum_inversion & 0x7) {
+	case 1:
+		state->fe[0]->dtv_property_cache.inversion = INVERSION_ON;
+		break;
+	case 0:
+		state->fe[0]->dtv_property_cache.inversion = INVERSION_OFF;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.inversion = INVERSION_AUTO;
+		break;
+	}
+	switch (ch.nfft) {
+	case 0:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_AUTO;
+		break;
+	}
+	switch (ch.guard) {
+	case 0:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
+		break;
+	case 3:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.guard_interval = GUARD_INTERVAL_AUTO;
+		break;
+	}
+	switch (ch.constellation) {
+	case 2:
+		state->fe[0]->dtv_property_cache.modulation = QAM_64;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.modulation = QAM_16;
+		break;
+	case 0:
+		state->fe[0]->dtv_property_cache.modulation = QPSK;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.modulation = QAM_AUTO;
+		break;
+	}
+	switch (ch.hrch) {
+	case 0:
+		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_NONE;
+		break;
+	case 1:
+		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_1;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.hierarchy = HIERARCHY_AUTO;
+		break;
+	}
+	switch (ch.code_rate_hp) {
+	case 1:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_1_2;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_2_3;
+		break;
+	case 3:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_3_4;
+		break;
+	case 5:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_5_6;
+		break;
+	case 7:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_7_8;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.code_rate_HP = FEC_AUTO;
+		break;
+	}
+	switch (ch.code_rate_lp) {
+	case 1:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_1_2;
+		break;
+	case 2:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_2_3;
+		break;
+	case 3:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_3_4;
+		break;
+	case 5:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_5_6;
+		break;
+	case 7:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_7_8;
+		break;
+	default:
+	case -1:
+		state->fe[0]->dtv_property_cache.code_rate_LP = FEC_AUTO;
+		break;
+	}
+
+error:
+	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+	return ret;
+}
+
+static int dib9000_fw_set_channel_union(struct dvb_frontend *fe, struct dvb_frontend_parameters *channel)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	struct dibDVBTChannel {
+		s8 spectrum_inversion;
+
+		s8 nfft;
+		s8 guard;
+		s8 constellation;
+
+		s8 hrch;
+		s8 alpha;
+		s8 code_rate_hp;
+		s8 code_rate_lp;
+		s8 select_hp;
+
+		s8 intlv_native;
+	};
+	struct dibDVBTChannel ch;
+
+	switch (state->fe[0]->dtv_property_cache.inversion) {
+	case INVERSION_ON:
+		ch.spectrum_inversion = 1;
+		break;
+	case INVERSION_OFF:
+		ch.spectrum_inversion = 0;
+		break;
+	default:
+	case INVERSION_AUTO:
+		ch.spectrum_inversion = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.transmission_mode) {
+	case TRANSMISSION_MODE_2K:
+		ch.nfft = 0;
+		break;
+	case TRANSMISSION_MODE_4K:
+		ch.nfft = 2;
+		break;
+	case TRANSMISSION_MODE_8K:
+		ch.nfft = 1;
+		break;
+	default:
+	case TRANSMISSION_MODE_AUTO:
+		ch.nfft = 1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.guard_interval) {
+	case GUARD_INTERVAL_1_32:
+		ch.guard = 0;
+		break;
+	case GUARD_INTERVAL_1_16:
+		ch.guard = 1;
+		break;
+	case GUARD_INTERVAL_1_8:
+		ch.guard = 2;
+		break;
+	case GUARD_INTERVAL_1_4:
+		ch.guard = 3;
+		break;
+	default:
+	case GUARD_INTERVAL_AUTO:
+		ch.guard = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.modulation) {
+	case QAM_64:
+		ch.constellation = 2;
+		break;
+	case QAM_16:
+		ch.constellation = 1;
+		break;
+	case QPSK:
+		ch.constellation = 0;
+		break;
+	default:
+	case QAM_AUTO:
+		ch.constellation = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.hierarchy) {
+	case HIERARCHY_NONE:
+		ch.hrch = 0;
+		break;
+	case HIERARCHY_1:
+	case HIERARCHY_2:
+	case HIERARCHY_4:
+		ch.hrch = 1;
+		break;
+	default:
+	case HIERARCHY_AUTO:
+		ch.hrch = -1;
+		break;
+	}
+	ch.alpha = 1;
+	switch (state->fe[0]->dtv_property_cache.code_rate_HP) {
+	case FEC_1_2:
+		ch.code_rate_hp = 1;
+		break;
+	case FEC_2_3:
+		ch.code_rate_hp = 2;
+		break;
+	case FEC_3_4:
+		ch.code_rate_hp = 3;
+		break;
+	case FEC_5_6:
+		ch.code_rate_hp = 5;
+		break;
+	case FEC_7_8:
+		ch.code_rate_hp = 7;
+		break;
+	default:
+	case FEC_AUTO:
+		ch.code_rate_hp = -1;
+		break;
+	}
+	switch (state->fe[0]->dtv_property_cache.code_rate_LP) {
+	case FEC_1_2:
+		ch.code_rate_lp = 1;
+		break;
+	case FEC_2_3:
+		ch.code_rate_lp = 2;
+		break;
+	case FEC_3_4:
+		ch.code_rate_lp = 3;
+		break;
+	case FEC_5_6:
+		ch.code_rate_lp = 5;
+		break;
+	case FEC_7_8:
+		ch.code_rate_lp = 7;
+		break;
+	default:
+	case FEC_AUTO:
+		ch.code_rate_lp = -1;
+		break;
+	}
+	ch.select_hp = 1;
+	ch.intlv_native = 1;
+
+	dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_UNION, (u8 *) &ch);
+
+	return 0;
+}
+
+static int dib9000_fw_tune(struct dvb_frontend *fe, struct dvb_frontend_parameters *ch)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	int ret = 10, search = state->channel_status.status == CHANNEL_STATUS_PARAMETERS_UNKNOWN;
+	s8 i;
+
+	switch (state->tune_state) {
+	case CT_DEMOD_START:
+		dib9000_fw_set_channel_head(state, ch);
+
+		/* write the channel context - a channel is initialized to 0, so it is OK */
+		dib9000_risc_mem_write(state, FE_MM_W_CHANNEL_CONTEXT, (u8 *) fe_info);
+		dib9000_risc_mem_write(state, FE_MM_W_FE_INFO, (u8 *) fe_info);
+
+		if (search)
+			dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_SEARCH, NULL, 0);
+		else {
+			dib9000_fw_set_channel_union(fe, ch);
+			dib9000_mbx_send(state, OUT_MSG_FE_CHANNEL_TUNE, NULL, 0);
+		}
+		state->tune_state = CT_DEMOD_STEP_1;
+		break;
+	case CT_DEMOD_STEP_1:
+		if (search)
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_SEARCH_STATE, (u8 *) &i, 1);
+		else
+			dib9000_risc_mem_read(state, FE_MM_R_CHANNEL_TUNE_STATE, (u8 *) &i, 1);
+		switch (i) {	/* something happened */
+		case 0:
+			break;
+		case -2:	/* tps locks are "slower" than MPEG locks -> even in autosearch data is OK here */
+			if (search)
+				state->status = FE_STATUS_DEMOD_SUCCESS;
+			else {
+				state->tune_state = CT_DEMOD_STOP;
+				state->status = FE_STATUS_LOCKED;
+			}
+			break;
+		default:
+			state->status = FE_STATUS_TUNE_FAILED;
+			state->tune_state = CT_DEMOD_STOP;
+			break;
+		}
+		break;
+	default:
+		ret = FE_CALLBACK_TIME_NEVER;
+		break;
+	}
+
+	return ret;
+}
+
+static int dib9000_fw_set_diversity_in(struct dvb_frontend *fe, int onoff)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 mode = (u16) onoff;
+	return dib9000_mbx_send(state, OUT_MSG_ENABLE_DIVERSITY, &mode, 1);
+}
+
+static int dib9000_fw_set_output_mode(struct dvb_frontend *fe, int mode)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 outreg, smo_mode;
+
+	dprintk("setting output mode for demod %p to %d", fe, mode);
+
+	switch (mode) {
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+		outreg = (1 << 10);	/* 0x0400 */
+		break;
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+		outreg = (1 << 10) | (1 << 6);	/* 0x0440 */
+		break;
+	case OUTMODE_MPEG2_SERIAL:
+		outreg = (1 << 10) | (2 << 6) | (0 << 1);	/* 0x0482 */
+		break;
+	case OUTMODE_DIVERSITY:
+		outreg = (1 << 10) | (4 << 6);	/* 0x0500 */
+		break;
+	case OUTMODE_MPEG2_FIFO:
+		outreg = (1 << 10) | (5 << 6);
+		break;
+	case OUTMODE_HIGH_Z:
+		outreg = 0;
+		break;
+	default:
+		dprintk("Unhandled output_mode passed to be set for demod %p", &state->fe[0]);
+		return -EINVAL;
+	}
+
+	dib9000_write_word(state, 1795, outreg);
+
+	switch (mode) {
+	case OUTMODE_MPEG2_PAR_GATED_CLK:
+	case OUTMODE_MPEG2_PAR_CONT_CLK:
+	case OUTMODE_MPEG2_SERIAL:
+	case OUTMODE_MPEG2_FIFO:
+		smo_mode = (dib9000_read_word(state, 295) & 0x0010) | (1 << 1);
+		if (state->chip.d9.cfg.output_mpeg2_in_188_bytes)
+			smo_mode |= (1 << 5);
+		dib9000_write_word(state, 295, smo_mode);
+		break;
+	}
+
+	outreg = to_fw_output_mode(mode);
+	return dib9000_mbx_send(state, OUT_MSG_SET_OUTPUT_MODE, &outreg, 1);
+}
+
+static int dib9000_tuner_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
+	u16 i, len, t, index_msg;
+
+	for (index_msg = 0; index_msg < num; index_msg++) {
+		if (msg[index_msg].flags & I2C_M_RD) {	/* read */
+			len = msg[index_msg].len;
+			if (len > 16)
+				len = 16;
+
+			if (dib9000_read_word(state, 790) != 0)
+				dprintk("TunerITF: read busy");
+
+			dib9000_write_word(state, 784, (u16) (msg[index_msg].addr));
+			dib9000_write_word(state, 787, (len / 2) - 1);
+			dib9000_write_word(state, 786, 1);	/* start read */
+
+			i = 1000;
+			while (dib9000_read_word(state, 790) != (len / 2) && i)
+				i--;
+
+			if (i == 0)
+				dprintk("TunerITF: read failed");
+
+			for (i = 0; i < len; i += 2) {
+				t = dib9000_read_word(state, 785);
+				msg[index_msg].buf[i] = (t >> 8) & 0xff;
+				msg[index_msg].buf[i + 1] = (t) & 0xff;
+			}
+			if (dib9000_read_word(state, 790) != 0)
+				dprintk("TunerITF: read more data than expected");
+		} else {
+			i = 1000;
+			while (dib9000_read_word(state, 789) && i)
+				i--;
+			if (i == 0)
+				dprintk("TunerITF: write busy");
+
+			len = msg[index_msg].len;
+			if (len > 16)
+				len = 16;
+
+			for (i = 0; i < len; i += 2)
+				dib9000_write_word(state, 785, (msg[index_msg].buf[i] << 8) | msg[index_msg].buf[i + 1]);
+			dib9000_write_word(state, 784, (u16) msg[index_msg].addr);
+			dib9000_write_word(state, 787, (len / 2) - 1);
+			dib9000_write_word(state, 786, 0);	/* start write */
+
+			i = 1000;
+			while (dib9000_read_word(state, 791) > 0 && i)
+				i--;
+			if (i == 0)
+				dprintk("TunerITF: write failed");
+		}
+	}
+	return num;
+}
+
+int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	state->component_bus_speed = speed;
+	return 0;
+}
+EXPORT_SYMBOL(dib9000_fw_set_component_bus_speed);
+
+static int dib9000_fw_component_bus_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dib9000_state *state = i2c_get_adapdata(i2c_adap);
+	u8 type = 0;		/* I2C */
+	u8 port = DIBX000_I2C_INTERFACE_GPIO_3_4;
+	u16 scl = state->component_bus_speed;	/* SCL frequency */
+	struct dib9000_fe_memory_map *m = &state->platform.risc.fe_mm[FE_MM_RW_COMPONENT_ACCESS_BUFFER];
+	u8 p[13] = { 0 };
+
+	p[0] = type;
+	p[1] = port;
+	p[2] = msg[0].addr << 1;
+
+	p[3] = (u8) scl & 0xff;	/* scl */
+	p[4] = (u8) (scl >> 8);
+
+	p[7] = 0;
+	p[8] = 0;
+
+	p[9] = (u8) (msg[0].len);
+	p[10] = (u8) (msg[0].len >> 8);
+	if ((num > 1) && (msg[1].flags & I2C_M_RD)) {
+		p[11] = (u8) (msg[1].len);
+		p[12] = (u8) (msg[1].len >> 8);
+	} else {
+		p[11] = 0;
+		p[12] = 0;
+	}
+
+	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+
+	dib9000_risc_mem_write(state, FE_MM_W_COMPONENT_ACCESS, p);
+
+	{			/* write-part */
+		dib9000_risc_mem_setup_cmd(state, m->addr, msg[0].len, 0);
+		dib9000_risc_mem_write_chunks(state, msg[0].buf, msg[0].len);
+	}
+
+	/* do the transaction */
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_COMPONENT_ACCESS) < 0) {
+		DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+		return 0;
+	}
+
+	/* read back any possible result */
+	if ((num > 1) && (msg[1].flags & I2C_M_RD))
+		dib9000_risc_mem_read(state, FE_MM_RW_COMPONENT_ACCESS_BUFFER, msg[1].buf, msg[1].len);
+
+	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+	return num;
+}
+
+static u32 dib9000_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm dib9000_tuner_algo = {
+	.master_xfer = dib9000_tuner_xfer,
+	.functionality = dib9000_i2c_func,
+};
+
+static struct i2c_algorithm dib9000_component_bus_algo = {
+	.master_xfer = dib9000_fw_component_bus_xfer,
+	.functionality = dib9000_i2c_func,
+};
+
+struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+	return &st->tuner_adap;
+}
+EXPORT_SYMBOL(dib9000_get_tuner_interface);
+
+struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+	return &st->component_bus;
+}
+EXPORT_SYMBOL(dib9000_get_component_bus_interface);
+
+struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+	return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
+}
+EXPORT_SYMBOL(dib9000_get_i2c_master);
+
+int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
+{
+	struct dib9000_state *st = fe->demodulator_priv;
+
+	st->i2c.i2c_adap = i2c;
+	return 0;
+}
+EXPORT_SYMBOL(dib9000_set_i2c_adapter);
+
+static int dib9000_cfg_gpio(struct dib9000_state *st, u8 num, u8 dir, u8 val)
+{
+	st->gpio_dir = dib9000_read_word(st, 773);
+	st->gpio_dir &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_dir |= (dir & 0x1) << num;	/* set the new direction */
+	dib9000_write_word(st, 773, st->gpio_dir);
+
+	st->gpio_val = dib9000_read_word(st, 774);
+	st->gpio_val &= ~(1 << num);	/* reset the direction bit */
+	st->gpio_val |= (val & 0x01) << num;	/* set the new value */
+	dib9000_write_word(st, 774, st->gpio_val);
+
+	dprintk("gpio dir: %04x: gpio val: %04x", st->gpio_dir, st->gpio_val);
+
+	return 0;
+}
+
+int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	return dib9000_cfg_gpio(state, num, dir, val);
+}
+EXPORT_SYMBOL(dib9000_set_gpio);
+
+int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 val = dib9000_read_word(state, 294 + 1) & 0xffef;
+	val |= (onoff & 0x1) << 4;
+
+	dprintk("PID filter enabled %d", onoff);
+	return dib9000_write_word(state, 294 + 1, val);
+}
+EXPORT_SYMBOL(dib9000_fw_pid_filter_ctrl);
+
+int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
+	return dib9000_write_word(state, 300 + 1 + id, onoff ? (1 << 13) | pid : 0);
+}
+EXPORT_SYMBOL(dib9000_fw_pid_filter);
+
+int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	return dib9000_fw_init(state);
+}
+EXPORT_SYMBOL(dib9000_firmware_post_pll_init);
+
+static void dib9000_release(struct dvb_frontend *demod)
+{
+	struct dib9000_state *st = demod->demodulator_priv;
+	u8 index_frontend;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (st->fe[index_frontend] != NULL); index_frontend++)
+		dvb_frontend_detach(st->fe[index_frontend]);
+
+	DibFreeLock(&state->platform.risc.mbx_if_lock);
+	DibFreeLock(&state->platform.risc.mbx_lock);
+	DibFreeLock(&state->platform.risc.mem_lock);
+	DibFreeLock(&state->platform.risc.mem_mbx_lock);
+	dibx000_exit_i2c_master(&st->i2c_master);
+
+	i2c_del_adapter(&st->tuner_adap);
+	i2c_del_adapter(&st->component_bus);
+	kfree(st->fe[0]);
+	kfree(st);
+}
+
+static int dib9000_wakeup(struct dvb_frontend *fe)
+{
+	return 0;
+}
+
+static int dib9000_sleep(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	int ret;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		ret = state->fe[index_frontend]->ops.sleep(state->fe[index_frontend]);
+		if (ret < 0)
+			return ret;
+	}
+	return dib9000_mbx_send(state, OUT_MSG_FE_SLEEP, NULL, 0);
+}
+
+static int dib9000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
+{
+	tune->min_delay_ms = 1000;
+	return 0;
+}
+
+static int dib9000_get_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend, sub_index_frontend;
+	fe_status_t stat;
+	int ret;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
+		if (stat & FE_HAS_SYNC) {
+			dprintk("TPS lock on the slave%i", index_frontend);
+
+			/* synchronize the cache with the other frontends */
+			state->fe[index_frontend]->ops.get_frontend(state->fe[index_frontend], fep);
+			for (sub_index_frontend = 0; (sub_index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[sub_index_frontend] != NULL);
+			     sub_index_frontend++) {
+				if (sub_index_frontend != index_frontend) {
+					state->fe[sub_index_frontend]->dtv_property_cache.modulation =
+					    state->fe[index_frontend]->dtv_property_cache.modulation;
+					state->fe[sub_index_frontend]->dtv_property_cache.inversion =
+					    state->fe[index_frontend]->dtv_property_cache.inversion;
+					state->fe[sub_index_frontend]->dtv_property_cache.transmission_mode =
+					    state->fe[index_frontend]->dtv_property_cache.transmission_mode;
+					state->fe[sub_index_frontend]->dtv_property_cache.guard_interval =
+					    state->fe[index_frontend]->dtv_property_cache.guard_interval;
+					state->fe[sub_index_frontend]->dtv_property_cache.hierarchy =
+					    state->fe[index_frontend]->dtv_property_cache.hierarchy;
+					state->fe[sub_index_frontend]->dtv_property_cache.code_rate_HP =
+					    state->fe[index_frontend]->dtv_property_cache.code_rate_HP;
+					state->fe[sub_index_frontend]->dtv_property_cache.code_rate_LP =
+					    state->fe[index_frontend]->dtv_property_cache.code_rate_LP;
+					state->fe[sub_index_frontend]->dtv_property_cache.rolloff =
+					    state->fe[index_frontend]->dtv_property_cache.rolloff;
+				}
+			}
+			return 0;
+		}
+	}
+
+	/* get the channel from master chip */
+	ret = dib9000_fw_get_channel(fe, fep);
+	if (ret != 0)
+		return ret;
+
+	/* synchronize the cache with the other frontends */
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->dtv_property_cache.inversion = fe->dtv_property_cache.inversion;
+		state->fe[index_frontend]->dtv_property_cache.transmission_mode = fe->dtv_property_cache.transmission_mode;
+		state->fe[index_frontend]->dtv_property_cache.guard_interval = fe->dtv_property_cache.guard_interval;
+		state->fe[index_frontend]->dtv_property_cache.modulation = fe->dtv_property_cache.modulation;
+		state->fe[index_frontend]->dtv_property_cache.hierarchy = fe->dtv_property_cache.hierarchy;
+		state->fe[index_frontend]->dtv_property_cache.code_rate_HP = fe->dtv_property_cache.code_rate_HP;
+		state->fe[index_frontend]->dtv_property_cache.code_rate_LP = fe->dtv_property_cache.code_rate_LP;
+		state->fe[index_frontend]->dtv_property_cache.rolloff = fe->dtv_property_cache.rolloff;
+	}
+
+	return 0;
+}
+
+static int dib9000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	state->tune_state = tune_state;
+	if (tune_state == CT_DEMOD_START)
+		state->status = FE_STATUS_TUNE_PENDING;
+
+	return 0;
+}
+
+static u32 dib9000_get_status(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	return state->status;
+}
+
+static int dib9000_set_channel_status(struct dvb_frontend *fe, struct dvb_frontend_parametersContext *channel_status)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	memcpy(&state->channel_status, channel_status, sizeof(struct dvb_frontend_parametersContext));
+	return 0;
+}
+
+static int dib9000_set_frontend(struct dvb_frontend *fe, struct dvb_frontend_parameters *fep)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	int sleep_time, sleep_time_slave;
+	u32 frontend_status;
+	u8 nbr_pending, exit_condition, index_frontend, index_frontend_success;
+	struct dvb_frontend_parametersContext channel_status;
+
+	/* check that the correct parameters are set */
+	if (state->fe[0]->dtv_property_cache.frequency == 0) {
+		dprintk("dib9000: must specify frequency ");
+		return 0;
+	}
+
+	if (state->fe[0]->dtv_property_cache.bandwidth_hz == 0) {
+		dprintk("dib9000: must specify bandwidth ");
+		return 0;
+	}
+	fe->dtv_property_cache.delivery_system = SYS_DVBT;
+
+	/* set the master status */
+	if (fep->u.ofdm.transmission_mode == TRANSMISSION_MODE_AUTO ||
+	    fep->u.ofdm.guard_interval == GUARD_INTERVAL_AUTO || fep->u.ofdm.constellation == QAM_AUTO || fep->u.ofdm.code_rate_HP == FEC_AUTO) {
+		/* no channel specified, autosearch the channel */
+		state->channel_status.status = CHANNEL_STATUS_PARAMETERS_UNKNOWN;
+	} else
+		state->channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
+
+	/* set mode and status for the different frontends */
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		dib9000_fw_set_diversity_in(state->fe[index_frontend], 1);
+
+		/* synchronization of the cache */
+		memcpy(&state->fe[index_frontend]->dtv_property_cache, &fe->dtv_property_cache, sizeof(struct dtv_frontend_properties));
+
+		state->fe[index_frontend]->dtv_property_cache.delivery_system = SYS_DVBT;
+		dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_HIGH_Z);
+
+		dib9000_set_channel_status(state->fe[index_frontend], &state->channel_status);
+		dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
+	}
+
+	/* actual tune */
+	exit_condition = 0;	/* 0: tune pending; 1: tune failed; 2:tune success */
+	index_frontend_success = 0;
+	do {
+		sleep_time = dib9000_fw_tune(state->fe[0], NULL);
+		for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
+			if (sleep_time == FE_CALLBACK_TIME_NEVER)
+				sleep_time = sleep_time_slave;
+			else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
+				sleep_time = sleep_time_slave;
+		}
+		if (sleep_time != FE_CALLBACK_TIME_NEVER)
+			msleep(sleep_time / 10);
+		else
+			break;
+
+		nbr_pending = 0;
+		exit_condition = 0;
+		index_frontend_success = 0;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			frontend_status = -dib9000_get_status(state->fe[index_frontend]);
+			if (frontend_status > -FE_STATUS_TUNE_PENDING) {
+				exit_condition = 2;	/* tune success */
+				index_frontend_success = index_frontend;
+				break;
+			}
+			if (frontend_status == -FE_STATUS_TUNE_PENDING)
+				nbr_pending++;	/* some frontends are still tuning */
+		}
+		if ((exit_condition != 2) && (nbr_pending == 0))
+			exit_condition = 1;	/* if all tune are done and no success, exit: tune failed */
+
+	} while (exit_condition == 0);
+
+	/* check the tune result */
+	if (exit_condition == 1) {	/* tune failed */
+		dprintk("tune failed");
+		return 0;
+	}
+
+	dprintk("tune success on frontend%i", index_frontend_success);
+
+	/* synchronize all the channel cache */
+	dib9000_get_frontend(state->fe[0], fep);
+
+	/* retune the other frontends with the found channel */
+	channel_status.status = CHANNEL_STATUS_PARAMETERS_SET;
+	for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		/* only retune the frontends which was not tuned success */
+		if (index_frontend != index_frontend_success) {
+			dib9000_set_channel_status(state->fe[index_frontend], &channel_status);
+			dib9000_set_tune_state(state->fe[index_frontend], CT_DEMOD_START);
+		}
+	}
+	do {
+		sleep_time = FE_CALLBACK_TIME_NEVER;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			if (index_frontend != index_frontend_success) {
+				sleep_time_slave = dib9000_fw_tune(state->fe[index_frontend], NULL);
+				if (sleep_time == FE_CALLBACK_TIME_NEVER)
+					sleep_time = sleep_time_slave;
+				else if ((sleep_time_slave != FE_CALLBACK_TIME_NEVER) && (sleep_time_slave > sleep_time))
+					sleep_time = sleep_time_slave;
+			}
+		}
+		if (sleep_time != FE_CALLBACK_TIME_NEVER)
+			msleep(sleep_time / 10);
+		else
+			break;
+
+		nbr_pending = 0;
+		for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+			if (index_frontend != index_frontend_success) {
+				frontend_status = -dib9000_get_status(state->fe[index_frontend]);
+				if ((index_frontend != index_frontend_success) && (frontend_status == -FE_STATUS_TUNE_PENDING))
+					nbr_pending++;	/* some frontends are still tuning */
+			}
+		}
+	} while (nbr_pending != 0);
+
+	/* set the output mode */
+	dib9000_fw_set_output_mode(state->fe[0], state->chip.d9.cfg.output_mode);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		dib9000_fw_set_output_mode(state->fe[index_frontend], OUTMODE_DIVERSITY);
+
+	/* turn off the diversity for the last frontend */
+	dib9000_fw_set_diversity_in(state->fe[index_frontend - 1], 0);
+
+	return 0;
+}
+
+static u16 dib9000_read_lock(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	return dib9000_read_word(state, 535);
+}
+
+static int dib9000_read_status(struct dvb_frontend *fe, fe_status_t * stat)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u16 lock = 0, lock_slave = 0;
+
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		lock_slave |= dib9000_read_lock(state->fe[index_frontend]);
+
+	lock = dib9000_read_word(state, 535);
+
+	*stat = 0;
+
+	if ((lock & 0x8000) || (lock_slave & 0x8000))
+		*stat |= FE_HAS_SIGNAL;
+	if ((lock & 0x3000) || (lock_slave & 0x3000))
+		*stat |= FE_HAS_CARRIER;
+	if ((lock & 0x0100) || (lock_slave & 0x0100))
+		*stat |= FE_HAS_VITERBI;
+	if (((lock & 0x0038) == 0x38) || ((lock_slave & 0x0038) == 0x38))
+		*stat |= FE_HAS_SYNC;
+	if ((lock & 0x0008) || (lock_slave & 0x0008))
+		*stat |= FE_HAS_LOCK;
+
+	return 0;
+}
+
+static int dib9000_read_ber(struct dvb_frontend *fe, u32 * ber)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 c[16];
+
+	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+		return -EIO;
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+	*ber = c[10] << 16 | c[11];
+	return 0;
+}
+
+static int dib9000_read_signal_strength(struct dvb_frontend *fe, u16 * strength)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u16 c[16];
+	u16 val;
+
+	*strength = 0;
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
+		state->fe[index_frontend]->ops.read_signal_strength(state->fe[index_frontend], &val);
+		if (val > 65535 - *strength)
+			*strength = 65535;
+		else
+			*strength += val;
+	}
+
+	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+		return -EIO;
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+	val = 65535 - c[4];
+	if (val > 65535 - *strength)
+		*strength = 65535;
+	else
+		*strength += val;
+	return 0;
+}
+
+static u32 dib9000_get_snr(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 c[16];
+	u32 n, s, exp;
+	u16 val;
+
+	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+		return -EIO;
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+	val = c[7];
+	n = (val >> 4) & 0xff;
+	exp = ((val & 0xf) << 2);
+	val = c[8];
+	exp += ((val >> 14) & 0x3);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	n <<= exp + 16;
+
+	s = (val >> 6) & 0xFF;
+	exp = (val & 0x3F);
+	if ((exp & 0x20) != 0)
+		exp -= 0x40;
+	s <<= exp + 16;
+
+	if (n > 0) {
+		u32 t = (s / n) << 16;
+		return t + ((s << 16) - n * t) / n;
+	}
+	return 0xffffffff;
+}
+
+static int dib9000_read_snr(struct dvb_frontend *fe, u16 * snr)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend;
+	u32 snr_master;
+
+	snr_master = dib9000_get_snr(fe);
+	for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++)
+		snr_master += dib9000_get_snr(state->fe[index_frontend]);
+
+	if ((snr_master >> 16) != 0) {
+		snr_master = 10 * intlog10(snr_master >> 16);
+		*snr = snr_master / ((1 << 24) / 10);
+	} else
+		*snr = 0;
+
+	return 0;
+}
+
+static int dib9000_read_unc_blocks(struct dvb_frontend *fe, u32 * unc)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u16 c[16];
+
+	DibAcquireLock(&state->platform.risc.mem_mbx_lock);
+	if (dib9000_fw_memmbx_sync(state, FE_SYNC_CHANNEL) < 0)
+		return -EIO;
+	dib9000_risc_mem_read(state, FE_MM_R_FE_MONITOR, (u8 *) c, sizeof(c));
+	DibReleaseLock(&state->platform.risc.mem_mbx_lock);
+
+	*unc = c[12];
+	return 0;
+}
+
+int dib9000_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, u8 first_addr)
+{
+	int k = 0;
+	u8 new_addr = 0;
+	struct i2c_device client = {.i2c_adap = i2c };
+
+	client.i2c_addr = default_addr + 16;
+	dib9000_i2c_write16(&client, 1796, 0x0);
+
+	for (k = no_of_demods - 1; k >= 0; k--) {
+		/* designated i2c address */
+		new_addr = first_addr + (k << 1);
+		client.i2c_addr = default_addr;
+
+		dib9000_i2c_write16(&client, 1817, 3);
+		dib9000_i2c_write16(&client, 1796, 0);
+		dib9000_i2c_write16(&client, 1227, 1);
+		dib9000_i2c_write16(&client, 1227, 0);
+
+		client.i2c_addr = new_addr;
+		dib9000_i2c_write16(&client, 1817, 3);
+		dib9000_i2c_write16(&client, 1796, 0);
+		dib9000_i2c_write16(&client, 1227, 1);
+		dib9000_i2c_write16(&client, 1227, 0);
+
+		if (dib9000_identify(&client) == 0) {
+			client.i2c_addr = default_addr;
+			if (dib9000_identify(&client) == 0) {
+				dprintk("DiB9000 #%d: not identified", k);
+				return -EIO;
+			}
+		}
+
+		dib9000_i2c_write16(&client, 1795, (1 << 10) | (4 << 6));
+		dib9000_i2c_write16(&client, 1794, (new_addr << 2) | 2);
+
+		dprintk("IC %d initialized (to i2c_address 0x%x)", k, new_addr);
+	}
+
+	for (k = 0; k < no_of_demods; k++) {
+		new_addr = first_addr | (k << 1);
+		client.i2c_addr = new_addr;
+
+		dib9000_i2c_write16(&client, 1794, (new_addr << 2));
+		dib9000_i2c_write16(&client, 1795, 0);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(dib9000_i2c_enumeration);
+
+int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend < MAX_NUMBER_OF_FRONTENDS) {
+		dprintk("set slave fe %p to index %i", fe_slave, index_frontend);
+		state->fe[index_frontend] = fe_slave;
+		return 0;
+	}
+
+	dprintk("too many slave frontend");
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(dib9000_set_slave_frontend);
+
+int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+	u8 index_frontend = 1;
+
+	while ((index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL))
+		index_frontend++;
+	if (index_frontend != 1) {
+		dprintk("remove slave fe %p (index %i)", state->fe[index_frontend - 1], index_frontend - 1);
+		state->fe[index_frontend] = NULL;
+		return 0;
+	}
+
+	dprintk("no frontend to be removed");
+	return -ENODEV;
+}
+EXPORT_SYMBOL(dib9000_remove_slave_frontend);
+
+struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	struct dib9000_state *state = fe->demodulator_priv;
+
+	if (slave_index >= MAX_NUMBER_OF_FRONTENDS)
+		return NULL;
+	return state->fe[slave_index];
+}
+EXPORT_SYMBOL(dib9000_get_slave_frontend);
+
+static struct dvb_frontend_ops dib9000_ops;
+struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg)
+{
+	struct dvb_frontend *fe;
+	struct dib9000_state *st;
+	st = kzalloc(sizeof(struct dib9000_state), GFP_KERNEL);
+	if (st == NULL)
+		return NULL;
+	fe = kzalloc(sizeof(struct dvb_frontend), GFP_KERNEL);
+	if (fe == NULL)
+		return NULL;
+
+	memcpy(&st->chip.d9.cfg, cfg, sizeof(struct dib9000_config));
+	st->i2c.i2c_adap = i2c_adap;
+	st->i2c.i2c_addr = i2c_addr;
+
+	st->gpio_dir = DIB9000_GPIO_DEFAULT_DIRECTIONS;
+	st->gpio_val = DIB9000_GPIO_DEFAULT_VALUES;
+	st->gpio_pwm_pos = DIB9000_GPIO_DEFAULT_PWM_POS;
+
+	DibInitLock(&st->platform.risc.mbx_if_lock);
+	DibInitLock(&st->platform.risc.mbx_lock);
+	DibInitLock(&st->platform.risc.mem_lock);
+	DibInitLock(&st->platform.risc.mem_mbx_lock);
+
+	st->fe[0] = fe;
+	fe->demodulator_priv = st;
+	memcpy(&st->fe[0]->ops, &dib9000_ops, sizeof(struct dvb_frontend_ops));
+
+	/* Ensure the output mode remains at the previous default if it's
+	 * not specifically set by the caller.
+	 */
+	if ((st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_SERIAL) && (st->chip.d9.cfg.output_mode != OUTMODE_MPEG2_PAR_GATED_CLK))
+		st->chip.d9.cfg.output_mode = OUTMODE_MPEG2_FIFO;
+
+	if (dib9000_identify(&st->i2c) == 0)
+		goto error;
+
+	dibx000_init_i2c_master(&st->i2c_master, DIB7000MC, st->i2c.i2c_adap, st->i2c.i2c_addr);
+
+	st->tuner_adap.dev.parent = i2c_adap->dev.parent;
+	strncpy(st->tuner_adap.name, "DIB9000_FW TUNER ACCESS", sizeof(st->tuner_adap.name));
+	st->tuner_adap.algo = &dib9000_tuner_algo;
+	st->tuner_adap.algo_data = NULL;
+	i2c_set_adapdata(&st->tuner_adap, st);
+	if (i2c_add_adapter(&st->tuner_adap) < 0)
+		goto error;
+
+	st->component_bus.dev.parent = i2c_adap->dev.parent;
+	strncpy(st->component_bus.name, "DIB9000_FW COMPONENT BUS ACCESS", sizeof(st->component_bus.name));
+	st->component_bus.algo = &dib9000_component_bus_algo;
+	st->component_bus.algo_data = NULL;
+	st->component_bus_speed = 340;
+	i2c_set_adapdata(&st->component_bus, st);
+	if (i2c_add_adapter(&st->component_bus) < 0)
+		goto component_bus_add_error;
+
+	dib9000_fw_reset(fe);
+
+	return fe;
+
+component_bus_add_error:
+	i2c_del_adapter(&st->tuner_adap);
+error:
+	kfree(st);
+	return NULL;
+}
+EXPORT_SYMBOL(dib9000_attach);
+
+static struct dvb_frontend_ops dib9000_ops = {
+	.info = {
+		 .name = "DiBcom 9000",
+		 .type = FE_OFDM,
+		 .frequency_min = 44250000,
+		 .frequency_max = 867250000,
+		 .frequency_stepsize = 62500,
+		 .caps = FE_CAN_INVERSION_AUTO |
+		 FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 | FE_CAN_FEC_3_4 |
+		 FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 | FE_CAN_FEC_AUTO |
+		 FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 | FE_CAN_QAM_AUTO |
+		 FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_RECOVER | FE_CAN_HIERARCHY_AUTO,
+		 },
+
+	.release = dib9000_release,
+
+	.init = dib9000_wakeup,
+	.sleep = dib9000_sleep,
+
+	.set_frontend = dib9000_set_frontend,
+	.get_tune_settings = dib9000_fe_get_tune_settings,
+	.get_frontend = dib9000_get_frontend,
+
+	.read_status = dib9000_read_status,
+	.read_ber = dib9000_read_ber,
+	.read_signal_strength = dib9000_read_signal_strength,
+	.read_snr = dib9000_read_snr,
+	.read_ucblocks = dib9000_read_unc_blocks,
+};
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@dibcom.fr>");
+MODULE_AUTHOR("Olivier Grenie <ogrenie@dibcom.fr>");
+MODULE_DESCRIPTION("Driver for the DiBcom 9000 COFDM demodulator");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib9000.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib9000.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dib9000.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dib9000.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,131 @@
+#ifndef DIB9000_H
+#define DIB9000_H
+
+#include "dibx000_common.h"
+
+struct dib9000_config {
+	u8 dvbt_mode;
+	u8 output_mpeg2_in_188_bytes;
+	u8 hostbus_diversity;
+	struct dibx000_bandwidth_config *bw;
+
+	u16 if_drives;
+
+	u32 timing_frequency;
+	u32 xtal_clock_khz;
+	u32 vcxo_timer;
+	u32 demod_clock_khz;
+
+	const u8 *microcode_B_fe_buffer;
+	u32 microcode_B_fe_size;
+
+	struct dibGPIOFunction gpio_function[2];
+	struct dibSubbandSelection subband;
+
+	u8 output_mode;
+};
+
+#define DEFAULT_DIB9000_I2C_ADDRESS 18
+
+#if defined(CONFIG_DVB_DIB9000) || (defined(CONFIG_DVB_DIB9000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, const struct dib9000_config *cfg);
+extern int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr);
+extern struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe);
+extern struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
+extern int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
+extern int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
+extern int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+extern int dib9000_firmware_post_pll_init(struct dvb_frontend *fe);
+extern int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+extern int dib9000_remove_slave_frontend(struct dvb_frontend *fe);
+extern struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
+extern struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe);
+extern int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c);
+extern int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed);
+#else
+static inline struct dvb_frontend *dib9000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib9000_config *cfg)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *dib9000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib9000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods, u8 default_addr, u8 first_addr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct i2c_adapter *dib9000_get_tuner_interface(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib9000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_fw_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_fw_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_firmware_post_pll_init(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+int dib9000_remove_slave_frontend(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline struct dvb_frontend *dib9000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline struct i2c_adapter *dib9000_get_component_bus_interface(struct dvb_frontend *fe)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+
+static inline int dib9000_set_i2c_adapter(struct dvb_frontend *fe, struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+
+static inline int dib9000_fw_set_component_bus_speed(struct dvb_frontend *fe, u16 speed)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dibx000_common.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dibx000_common.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dibx000_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dibx000_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,9 +17,145 @@
 	struct i2c_msg msg = {
 		.addr = mst->i2c_addr,.flags = 0,.buf = b,.len = 4
 	};
+
 	return i2c_transfer(mst->i2c_adap, &msg, 1) != 1 ? -EREMOTEIO : 0;
 }
 
+static u16 dibx000_read_word(struct dibx000_i2c_master *mst, u16 reg)
+{
+	u8 wb[2] = { reg >> 8, reg & 0xff };
+	u8 rb[2];
+	struct i2c_msg msg[2] = {
+		{.addr = mst->i2c_addr, .flags = 0, .buf = wb, .len = 2},
+		{.addr = mst->i2c_addr, .flags = I2C_M_RD, .buf = rb, .len = 2},
+	};
+
+	if (i2c_transfer(mst->i2c_adap, msg, 2) != 2)
+		dprintk("i2c read error on %d", reg);
+
+	return (rb[0] << 8) | rb[1];
+}
+
+static int dibx000_is_i2c_done(struct dibx000_i2c_master *mst)
+{
+	int i = 100;
+	u16 status;
+
+	while (((status = dibx000_read_word(mst, mst->base_reg + 2)) & 0x0100) == 0 && --i > 0)
+		;
+
+	/* i2c timed out */
+	if (i == 0)
+		return -EREMOTEIO;
+
+	/* no acknowledge */
+	if ((status & 0x0080) == 0)
+		return -EREMOTEIO;
+
+	return 0;
+}
+
+static int dibx000_master_i2c_write(struct dibx000_i2c_master *mst, struct i2c_msg *msg, u8 stop)
+{
+	u16 data;
+	u16 da;
+	u16 i;
+	u16 txlen = msg->len, len;
+	const u8 *b = msg->buf;
+
+	while (txlen) {
+		dibx000_read_word(mst, mst->base_reg + 2);
+
+		len = txlen > 8 ? 8 : txlen;
+		for (i = 0; i < len; i += 2) {
+			data = *b++ << 8;
+			if (i+1 < len)
+				data |= *b++;
+			dibx000_write_word(mst, mst->base_reg, data);
+		}
+		da = (((u8) (msg->addr))  << 9) |
+			(1           << 8) |
+			(1           << 7) |
+			(0           << 6) |
+			(0           << 5) |
+			((len & 0x7) << 2) |
+			(0           << 1) |
+			(0           << 0);
+
+		if (txlen == msg->len)
+			da |= 1 << 5; /* start */
+
+		if (txlen-len == 0 && stop)
+			da |= 1 << 6; /* stop */
+
+		dibx000_write_word(mst, mst->base_reg+1, da);
+
+		if (dibx000_is_i2c_done(mst) != 0)
+			return -EREMOTEIO;
+		txlen -= len;
+	}
+
+	return 0;
+}
+
+static int dibx000_master_i2c_read(struct dibx000_i2c_master *mst, struct i2c_msg *msg)
+{
+	u16 da;
+	u8 *b = msg->buf;
+	u16 rxlen = msg->len, len;
+
+	while (rxlen) {
+		len = rxlen > 8 ? 8 : rxlen;
+		da = (((u8) (msg->addr)) << 9) |
+			(1           << 8) |
+			(1           << 7) |
+			(0           << 6) |
+			(0           << 5) |
+			((len & 0x7) << 2) |
+			(1           << 1) |
+			(0           << 0);
+
+		if (rxlen == msg->len)
+			da |= 1 << 5; /* start */
+
+		if (rxlen-len == 0)
+			da |= 1 << 6; /* stop */
+		dibx000_write_word(mst, mst->base_reg+1, da);
+
+		if (dibx000_is_i2c_done(mst) != 0)
+			return -EREMOTEIO;
+
+		rxlen -= len;
+
+		while (len) {
+			da = dibx000_read_word(mst, mst->base_reg);
+			*b++ = (da >> 8) & 0xff;
+			len--;
+			if (len >= 1) {
+				*b++ =  da   & 0xff;
+				len--;
+			}
+		}
+	}
+
+	return 0;
+}
+
+int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+
+	if (mst->device_rev < DIB7000MC && speed < 235)
+		speed = 235;
+	return dibx000_write_word(mst, mst->base_reg + 3, (u16)(60000 / speed));
+
+}
+EXPORT_SYMBOL(dibx000_i2c_set_speed);
+
+static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_I2C;
+}
 
 static int dibx000_i2c_select_interface(struct dibx000_i2c_master *mst,
 					enum dibx000_i2c_interface intf)
@@ -32,6 +168,60 @@
 	return 0;
 }
 
+static int dibx000_i2c_master_xfer_gpio12(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int msg_index;
+	int ret = 0;
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_1_2);
+	for (msg_index = 0; msg_index < num; msg_index++) {
+		if (msg[msg_index].flags & I2C_M_RD) {
+			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
+			if (ret != 0)
+				return 0;
+		} else {
+			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
+			if (ret != 0)
+				return 0;
+		}
+	}
+
+	return num;
+}
+
+static int dibx000_i2c_master_xfer_gpio34(struct i2c_adapter *i2c_adap, struct i2c_msg msg[], int num)
+{
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	int msg_index;
+	int ret = 0;
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_3_4);
+	for (msg_index = 0; msg_index < num; msg_index++) {
+		if (msg[msg_index].flags & I2C_M_RD) {
+			ret = dibx000_master_i2c_read(mst, &msg[msg_index]);
+			if (ret != 0)
+				return 0;
+		} else {
+			ret = dibx000_master_i2c_write(mst, &msg[msg_index], 1);
+			if (ret != 0)
+				return 0;
+		}
+	}
+
+	return num;
+}
+
+static struct i2c_algorithm dibx000_i2c_master_gpio12_xfer_algo = {
+	.master_xfer = dibx000_i2c_master_xfer_gpio12,
+	.functionality = dibx000_i2c_func,
+};
+
+static struct i2c_algorithm dibx000_i2c_master_gpio34_xfer_algo = {
+	.master_xfer = dibx000_i2c_master_xfer_gpio34,
+	.functionality = dibx000_i2c_func,
+};
+
 static int dibx000_i2c_gate_ctrl(struct dibx000_i2c_master *mst, u8 tx[4],
 				 u8 addr, int onoff)
 {
@@ -54,11 +244,37 @@
 	return 0;
 }
 
-static u32 dibx000_i2c_func(struct i2c_adapter *adapter)
+static int dibx000_i2c_gated_gpio67_xfer(struct i2c_adapter *i2c_adap,
+					struct i2c_msg msg[], int num)
 {
-	return I2C_FUNC_I2C;
+	struct dibx000_i2c_master *mst = i2c_get_adapdata(i2c_adap);
+	struct i2c_msg m[2 + num];
+	u8 tx_open[4], tx_close[4];
+
+	memset(m, 0, sizeof(struct i2c_msg) * (2 + num));
+
+	dibx000_i2c_select_interface(mst, DIBX000_I2C_INTERFACE_GPIO_6_7);
+
+	dibx000_i2c_gate_ctrl(mst, tx_open, msg[0].addr, 1);
+	m[0].addr = mst->i2c_addr;
+	m[0].buf = tx_open;
+	m[0].len = 4;
+
+	memcpy(&m[1], msg, sizeof(struct i2c_msg) * num);
+
+	dibx000_i2c_gate_ctrl(mst, tx_close, 0, 0);
+	m[num + 1].addr = mst->i2c_addr;
+	m[num + 1].buf = tx_close;
+	m[num + 1].len = 4;
+
+	return i2c_transfer(mst->i2c_adap, m, 2 + num) == 2 + num ? num : -EIO;
 }
 
+static struct i2c_algorithm dibx000_i2c_gated_gpio67_algo = {
+	.master_xfer = dibx000_i2c_gated_gpio67_xfer,
+	.functionality = dibx000_i2c_func,
+};
+
 static int dibx000_i2c_gated_tuner_xfer(struct i2c_adapter *i2c_adap,
 					struct i2c_msg msg[], int num)
 {
@@ -91,8 +307,8 @@
 };
 
 struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master *mst,
-					    enum dibx000_i2c_interface intf,
-					    int gating)
+						enum dibx000_i2c_interface intf,
+						int gating)
 {
 	struct i2c_adapter *i2c = NULL;
 
@@ -101,6 +317,18 @@
 		if (gating)
 			i2c = &mst->gated_tuner_i2c_adap;
 		break;
+	case DIBX000_I2C_INTERFACE_GPIO_1_2:
+		if (!gating)
+			i2c = &mst->master_i2c_adap_gpio12;
+		break;
+	case DIBX000_I2C_INTERFACE_GPIO_3_4:
+		if (!gating)
+			i2c = &mst->master_i2c_adap_gpio34;
+		break;
+	case DIBX000_I2C_INTERFACE_GPIO_6_7:
+		if (gating)
+			i2c = &mst->master_i2c_adap_gpio67;
+		break;
 	default:
 		printk(KERN_ERR "DiBX000: incorrect I2C interface selected\n");
 		break;
@@ -126,8 +354,8 @@
 EXPORT_SYMBOL(dibx000_reset_i2c_master);
 
 static int i2c_adapter_init(struct i2c_adapter *i2c_adap,
-			    struct i2c_algorithm *algo, const char *name,
-			    struct dibx000_i2c_master *mst)
+				struct i2c_algorithm *algo, const char *name,
+				struct dibx000_i2c_master *mst)
 {
 	strncpy(i2c_adap->name, name, sizeof(i2c_adap->name));
 	i2c_adap->algo = algo;
@@ -139,7 +367,7 @@
 }
 
 int dibx000_init_i2c_master(struct dibx000_i2c_master *mst, u16 device_rev,
-			    struct i2c_adapter *i2c_adap, u8 i2c_addr)
+				struct i2c_adapter *i2c_adap, u8 i2c_addr)
 {
 	u8 tx[4];
 	struct i2c_msg m = {.addr = i2c_addr >> 1,.buf = tx,.len = 4 };
@@ -153,11 +381,33 @@
 	else
 		mst->base_reg = 768;
 
+	mst->gated_tuner_i2c_adap.dev.parent = mst->i2c_adap->dev.parent;
 	if (i2c_adapter_init
-	    (&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
-	     "DiBX000 tuner I2C bus", mst) != 0)
+			(&mst->gated_tuner_i2c_adap, &dibx000_i2c_gated_tuner_algo,
+			 "DiBX000 tuner I2C bus", mst) != 0)
 		printk(KERN_ERR
-		       "DiBX000: could not initialize the tuner i2c_adapter\n");
+				"DiBX000: could not initialize the tuner i2c_adapter\n");
+
+	mst->master_i2c_adap_gpio12.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->master_i2c_adap_gpio12, &dibx000_i2c_master_gpio12_xfer_algo,
+			 "DiBX000 master GPIO12 I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the master i2c_adapter\n");
+
+	mst->master_i2c_adap_gpio34.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->master_i2c_adap_gpio34, &dibx000_i2c_master_gpio34_xfer_algo,
+			 "DiBX000 master GPIO34 I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the master i2c_adapter\n");
+
+	mst->master_i2c_adap_gpio67.dev.parent = mst->i2c_adap->dev.parent;
+	if (i2c_adapter_init
+			(&mst->master_i2c_adap_gpio67, &dibx000_i2c_gated_gpio67_algo,
+			 "DiBX000 master GPIO67 I2C bus", mst) != 0)
+		printk(KERN_ERR
+				"DiBX000: could not initialize the master i2c_adapter\n");
 
 	/* initialize the i2c-master by closing the gate */
 	dibx000_i2c_gate_ctrl(mst, tx, 0, 0);
@@ -170,16 +420,19 @@
 void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst)
 {
 	i2c_del_adapter(&mst->gated_tuner_i2c_adap);
+	i2c_del_adapter(&mst->master_i2c_adap_gpio12);
+	i2c_del_adapter(&mst->master_i2c_adap_gpio34);
+	i2c_del_adapter(&mst->master_i2c_adap_gpio67);
 }
 EXPORT_SYMBOL(dibx000_exit_i2c_master);
 
 
 u32 systime(void)
 {
-    struct timespec t;
+	struct timespec t;
 
-    t = current_kernel_time();
-    return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
+	t = current_kernel_time();
+	return (t.tv_sec * 10000) + (t.tv_nsec / 100000);
 }
 EXPORT_SYMBOL(systime);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dibx000_common.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dibx000_common.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dibx000_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dibx000_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,8 @@
 enum dibx000_i2c_interface {
 	DIBX000_I2C_INTERFACE_TUNER = 0,
 	DIBX000_I2C_INTERFACE_GPIO_1_2 = 1,
-	DIBX000_I2C_INTERFACE_GPIO_3_4 = 2
+	DIBX000_I2C_INTERFACE_GPIO_3_4 = 2,
+	DIBX000_I2C_INTERFACE_GPIO_6_7 = 3
 };
 
 struct dibx000_i2c_master {
@@ -17,8 +18,11 @@
 
 	enum dibx000_i2c_interface selected_interface;
 
-//      struct i2c_adapter  tuner_i2c_adap;
+/*	struct i2c_adapter  tuner_i2c_adap; */
 	struct i2c_adapter gated_tuner_i2c_adap;
+	struct i2c_adapter master_i2c_adap_gpio12;
+	struct i2c_adapter master_i2c_adap_gpio34;
+	struct i2c_adapter master_i2c_adap_gpio67;
 
 	struct i2c_adapter *i2c_adap;
 	u8 i2c_addr;
@@ -27,14 +31,15 @@
 };
 
 extern int dibx000_init_i2c_master(struct dibx000_i2c_master *mst,
-				   u16 device_rev, struct i2c_adapter *i2c_adap,
-				   u8 i2c_addr);
+					u16 device_rev, struct i2c_adapter *i2c_adap,
+					u8 i2c_addr);
 extern struct i2c_adapter *dibx000_get_i2c_adapter(struct dibx000_i2c_master
-						   *mst,
-						   enum dibx000_i2c_interface
-						   intf, int gating);
+							*mst,
+							enum dibx000_i2c_interface
+							intf, int gating);
 extern void dibx000_exit_i2c_master(struct dibx000_i2c_master *mst);
 extern void dibx000_reset_i2c_master(struct dibx000_i2c_master *mst);
+extern int dibx000_i2c_set_speed(struct i2c_adapter *i2c_adap, u16 speed);
 
 extern u32 systime(void);
 
@@ -42,7 +47,7 @@
 #define BAND_UHF   0x02
 #define BAND_VHF   0x04
 #define BAND_SBAND 0x08
-#define BAND_FM    0x10
+#define BAND_FM	   0x10
 #define BAND_CBAND 0x20
 
 #define BAND_OF_FREQUENCY(freq_kHz) ((freq_kHz) <= 170000 ? BAND_CBAND : \
@@ -135,9 +140,9 @@
 	DIBX000_VBG_DISABLE,
 };
 
-#define BANDWIDTH_TO_KHZ(v) ( (v) == BANDWIDTH_8_MHZ  ? 8000 : \
-			     (v) == BANDWIDTH_7_MHZ  ? 7000 : \
-			     (v) == BANDWIDTH_6_MHZ  ? 6000 : 8000 )
+#define BANDWIDTH_TO_KHZ(v) ((v) == BANDWIDTH_8_MHZ  ? 8000 : \
+				(v) == BANDWIDTH_7_MHZ  ? 7000 : \
+				(v) == BANDWIDTH_6_MHZ  ? 6000 : 8000)
 
 #define BANDWIDTH_TO_INDEX(v) ( \
 	(v) == 8000 ? BANDWIDTH_8_MHZ : \
@@ -153,53 +158,57 @@
 #define OUTMODE_MPEG2_FIFO          5
 #define OUTMODE_ANALOG_ADC          6
 
+#define INPUT_MODE_OFF                0x11
+#define INPUT_MODE_DIVERSITY          0x12
+#define INPUT_MODE_MPEG               0x13
+
 enum frontend_tune_state {
-    CT_TUNER_START = 10,
-    CT_TUNER_STEP_0,
-    CT_TUNER_STEP_1,
-    CT_TUNER_STEP_2,
-    CT_TUNER_STEP_3,
-    CT_TUNER_STEP_4,
-    CT_TUNER_STEP_5,
-    CT_TUNER_STEP_6,
-    CT_TUNER_STEP_7,
-    CT_TUNER_STOP,
+	CT_TUNER_START = 10,
+	CT_TUNER_STEP_0,
+	CT_TUNER_STEP_1,
+	CT_TUNER_STEP_2,
+	CT_TUNER_STEP_3,
+	CT_TUNER_STEP_4,
+	CT_TUNER_STEP_5,
+	CT_TUNER_STEP_6,
+	CT_TUNER_STEP_7,
+	CT_TUNER_STOP,
 
-    CT_AGC_START = 20,
-    CT_AGC_STEP_0,
-    CT_AGC_STEP_1,
-    CT_AGC_STEP_2,
-    CT_AGC_STEP_3,
-    CT_AGC_STEP_4,
-    CT_AGC_STOP,
+	CT_AGC_START = 20,
+	CT_AGC_STEP_0,
+	CT_AGC_STEP_1,
+	CT_AGC_STEP_2,
+	CT_AGC_STEP_3,
+	CT_AGC_STEP_4,
+	CT_AGC_STOP,
 
 	CT_DEMOD_START = 30,
-    CT_DEMOD_STEP_1,
-    CT_DEMOD_STEP_2,
-    CT_DEMOD_STEP_3,
-    CT_DEMOD_STEP_4,
-    CT_DEMOD_STEP_5,
-    CT_DEMOD_STEP_6,
-    CT_DEMOD_STEP_7,
-    CT_DEMOD_STEP_8,
-    CT_DEMOD_STEP_9,
-    CT_DEMOD_STEP_10,
-    CT_DEMOD_SEARCH_NEXT = 41,
-    CT_DEMOD_STEP_LOCKED,
-    CT_DEMOD_STOP,
+	CT_DEMOD_STEP_1,
+	CT_DEMOD_STEP_2,
+	CT_DEMOD_STEP_3,
+	CT_DEMOD_STEP_4,
+	CT_DEMOD_STEP_5,
+	CT_DEMOD_STEP_6,
+	CT_DEMOD_STEP_7,
+	CT_DEMOD_STEP_8,
+	CT_DEMOD_STEP_9,
+	CT_DEMOD_STEP_10,
+	CT_DEMOD_SEARCH_NEXT = 41,
+	CT_DEMOD_STEP_LOCKED,
+	CT_DEMOD_STOP,
 
-    CT_DONE = 100,
-    CT_SHUTDOWN,
+	CT_DONE = 100,
+	CT_SHUTDOWN,
 
 };
 
 struct dvb_frontend_parametersContext {
 #define CHANNEL_STATUS_PARAMETERS_UNKNOWN   0x01
 #define CHANNEL_STATUS_PARAMETERS_SET       0x02
-    u8 status;
-    u32 tune_time_estimation[2];
-    s32 tps_available;
-    u16 tps[9];
+	u8 status;
+	u32 tune_time_estimation[2];
+	s32 tps_available;
+	u16 tps[9];
 };
 
 #define FE_STATUS_TUNE_FAILED          0
@@ -216,4 +225,49 @@
 
 #define ABS(x) ((x < 0) ? (-x) : (x))
 
+#define DATA_BUS_ACCESS_MODE_8BIT                 0x01
+#define DATA_BUS_ACCESS_MODE_16BIT                0x02
+#define DATA_BUS_ACCESS_MODE_NO_ADDRESS_INCREMENT 0x10
+
+struct dibGPIOFunction {
+#define BOARD_GPIO_COMPONENT_BUS_ADAPTER 1
+#define BOARD_GPIO_COMPONENT_DEMOD       2
+	u8 component;
+
+#define BOARD_GPIO_FUNCTION_BOARD_ON      1
+#define BOARD_GPIO_FUNCTION_BOARD_OFF     2
+#define BOARD_GPIO_FUNCTION_COMPONENT_ON  3
+#define BOARD_GPIO_FUNCTION_COMPONENT_OFF 4
+#define BOARD_GPIO_FUNCTION_SUBBAND_PWM   5
+#define BOARD_GPIO_FUNCTION_SUBBAND_GPIO   6
+	u8 function;
+
+/* mask, direction and value are used specify which GPIO to change GPIO0
+ * is LSB and possible GPIO31 is MSB.  The same bit-position as in the
+ * mask is used for the direction and the value. Direction == 1 is OUT,
+ * 0 == IN. For direction "OUT" value is either 1 or 0, for direction IN
+ * value has no meaning.
+ *
+ * In case of BOARD_GPIO_FUNCTION_PWM mask is giving the GPIO to be
+ * used to do the PWM. Direction gives the PWModulator to be used.
+ * Value gives the PWM value in device-dependent scale.
+ */
+	u32 mask;
+	u32 direction;
+	u32 value;
+};
+
+#define MAX_NB_SUBBANDS   8
+struct dibSubbandSelection {
+	u8  size; /* Actual number of subbands. */
+	struct {
+		u16 f_mhz;
+		struct dibGPIOFunction gpio;
+	} subband[MAX_NB_SUBBANDS];
+};
+
+#define DEMOD_TIMF_SET    0x00
+#define DEMOD_TIMF_GET    0x01
+#define DEMOD_TIMF_UPDATE 0x02
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/drx397xD.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/drx397xD.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/drx397xD.c	2012-03-24 01:03:31.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/drx397xD.c	2012-03-24 03:28:23.000000000 -0400
@@ -1097,7 +1097,7 @@
 	s->config.ifagc.w0A = 0x3ff;
 	s->config.ifagc.w0C = 0x388;
 
-	/* for signal strenght calculations */
+	/* for signal strength calculations */
 	s->config.ss76 = 820;
 	s->config.ss78 = 2200;
 	s->config.ss7A = 150;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/ds3000.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/ds3000.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/ds3000.c	2012-03-24 01:02:52.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/ds3000.c	2012-03-24 03:28:00.000000000 -0400
@@ -227,31 +227,11 @@
 	0xb8, 0x00,
 };
 
-/* DS3000 doesn't need some parameters as input and auto-detects them */
-/* save input from the application of those parameters */
-struct ds3000_tuning {
-	u32 frequency;
-	u32 symbol_rate;
-	fe_spectral_inversion_t inversion;
-	enum fe_code_rate fec;
-
-	/* input values */
-	u8 inversion_val;
-	fe_modulation_t delivery;
-	u8 rolloff;
-};
-
 struct ds3000_state {
 	struct i2c_adapter *i2c;
 	const struct ds3000_config *config;
-
 	struct dvb_frontend frontend;
-
-	struct ds3000_tuning dcur;
-	struct ds3000_tuning dnxt;
-
 	u8 skip_fw_load;
-
 	/* previous uncorrected block counter for DVB-S2 */
 	u16 prevUCBS2;
 };
@@ -303,7 +283,7 @@
 	struct i2c_msg msg;
 	u8 *buf;
 
-	buf = kmalloc(3, GFP_KERNEL);
+	buf = kmalloc(33, GFP_KERNEL);
 	if (buf == NULL) {
 		printk(KERN_ERR "Unable to kmalloc\n");
 		ret = -ENOMEM;
@@ -315,10 +295,10 @@
 	msg.addr = state->config->demod_address;
 	msg.flags = 0;
 	msg.buf = buf;
-	msg.len = 3;
+	msg.len = 33;
 
-	for (i = 0; i < len; i += 2) {
-		memcpy(buf + 1, data + i, 2);
+	for (i = 0; i < len; i += 32) {
+		memcpy(buf + 1, data + i, 32);
 
 		dprintk("%s: write reg 0x%02x, len = %d\n", __func__, reg, len);
 
@@ -399,45 +379,6 @@
 	return b1[0];
 }
 
-static int ds3000_set_inversion(struct ds3000_state *state,
-					fe_spectral_inversion_t inversion)
-{
-	dprintk("%s(%d)\n", __func__, inversion);
-
-	switch (inversion) {
-	case INVERSION_OFF:
-	case INVERSION_ON:
-	case INVERSION_AUTO:
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	state->dnxt.inversion = inversion;
-
-	return 0;
-}
-
-static int ds3000_set_symbolrate(struct ds3000_state *state, u32 rate)
-{
-	int ret = 0;
-
-	dprintk("%s()\n", __func__);
-
-	dprintk("%s() symbol_rate = %d\n", __func__, state->dnxt.symbol_rate);
-
-	/*  check if symbol rate is within limits */
-	if ((state->dnxt.symbol_rate >
-				state->frontend.ops.info.symbol_rate_max) ||
-	    (state->dnxt.symbol_rate <
-				state->frontend.ops.info.symbol_rate_min))
-		ret = -EOPNOTSUPP;
-
-	state->dnxt.symbol_rate = rate;
-
-	return ret;
-}
-
 static int ds3000_load_firmware(struct dvb_frontend *fe,
 					const struct firmware *fw);
 
@@ -507,23 +448,31 @@
 	return 0;
 }
 
-static void ds3000_dump_registers(struct dvb_frontend *fe)
+static int ds3000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
 {
 	struct ds3000_state *state = fe->demodulator_priv;
-	int x, y, reg = 0, val;
+	u8 data;
 
-	for (y = 0; y < 16; y++) {
-		dprintk("%s: %02x: ", __func__, y);
-		for (x = 0; x < 16; x++) {
-			reg = (y << 4) + x;
-			val = ds3000_readreg(state, reg);
-			if (x != 15)
-				dprintk("%02x ",  val);
-			else
-				dprintk("%02x\n", val);
-		}
+	dprintk("%s(%d)\n", __func__, voltage);
+
+	data = ds3000_readreg(state, 0xa2);
+	data |= 0x03; /* bit0 V/H, bit1 off/on */
+
+	switch (voltage) {
+	case SEC_VOLTAGE_18:
+		data &= ~0x03;
+		break;
+	case SEC_VOLTAGE_13:
+		data &= ~0x03;
+		data |= 0x01;
+		break;
+	case SEC_VOLTAGE_OFF:
+		break;
 	}
-	dprintk("%s: -- DS3000 DUMP DONE --\n", __func__);
+
+	ds3000_writereg(state, 0xa2, data);
+
+	return 0;
 }
 
 static int ds3000_read_status(struct dvb_frontend *fe, fe_status_t* status)
@@ -560,16 +509,6 @@
 	return 0;
 }
 
-#define FE_IS_TUNED (FE_HAS_SIGNAL + FE_HAS_LOCK)
-static int ds3000_is_tuned(struct dvb_frontend *fe)
-{
-	fe_status_t tunerstat;
-
-	ds3000_read_status(fe, &tunerstat);
-
-	return ((tunerstat & FE_IS_TUNED) == FE_IS_TUNED);
-}
-
 /* read DS3000 BER value */
 static int ds3000_read_ber(struct dvb_frontend *fe, u32* ber)
 {
@@ -790,13 +729,6 @@
 	return 0;
 }
 
-/* Overwrite the current tuning params, we are about to tune */
-static void ds3000_clone_params(struct dvb_frontend *fe)
-{
-	struct ds3000_state *state = fe->demodulator_priv;
-	memcpy(&state->dcur, &state->dnxt, sizeof(state->dcur));
-}
-
 static int ds3000_set_tone(struct dvb_frontend *fe, fe_sec_tone_mode_t tone)
 {
 	struct ds3000_state *state = fe->demodulator_priv;
@@ -1014,287 +946,298 @@
 	return 0;
 }
 
-static int ds3000_tune(struct dvb_frontend *fe,
+static int ds3000_set_carrier_offset(struct dvb_frontend *fe,
+					s32 carrier_offset_khz)
+{
+	struct ds3000_state *state = fe->demodulator_priv;
+	s32 tmp;
+
+	tmp = carrier_offset_khz;
+	tmp *= 65536;
+	tmp = (2 * tmp + DS3000_SAMPLE_RATE) / (2 * DS3000_SAMPLE_RATE);
+
+	if (tmp < 0)
+		tmp += 65536;
+
+	ds3000_writereg(state, 0x5f, tmp >> 8);
+	ds3000_writereg(state, 0x5e, tmp & 0xff);
+
+	return 0;
+}
+
+static int ds3000_set_frontend(struct dvb_frontend *fe,
 				struct dvb_frontend_parameters *p)
 {
 	struct ds3000_state *state = fe->demodulator_priv;
 	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
 
-	int ret = 0, retune, i;
-	u8 status, mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf;
+	int i;
+	fe_status_t status;
+	u8 mlpf, mlpf_new, mlpf_max, mlpf_min, nlpf, div4;
+	s32 offset_khz;
 	u16 value, ndiv;
 	u32 f3db;
 
 	dprintk("%s() ", __func__);
 
-	/* Load the firmware if required */
-	ret = ds3000_firmware_ondemand(fe);
-	if (ret != 0) {
-		printk(KERN_ERR "%s: Unable initialise the firmware\n",
-								__func__);
-		return ret;
+	if (state->config->set_ts_params)
+		state->config->set_ts_params(fe, 0);
+	/* Tune */
+	/* unknown */
+	ds3000_tuner_writereg(state, 0x07, 0x02);
+	ds3000_tuner_writereg(state, 0x10, 0x00);
+	ds3000_tuner_writereg(state, 0x60, 0x79);
+	ds3000_tuner_writereg(state, 0x08, 0x01);
+	ds3000_tuner_writereg(state, 0x00, 0x01);
+	div4 = 0;
+
+	/* calculate and set freq divider */
+	if (p->frequency < 1146000) {
+		ds3000_tuner_writereg(state, 0x10, 0x11);
+		div4 = 1;
+		ndiv = ((p->frequency * (6 + 8) * 4) +
+				(DS3000_XTAL_FREQ / 2)) /
+				DS3000_XTAL_FREQ - 1024;
+	} else {
+		ds3000_tuner_writereg(state, 0x10, 0x01);
+		ndiv = ((p->frequency * (6 + 8) * 2) +
+				(DS3000_XTAL_FREQ / 2)) /
+				DS3000_XTAL_FREQ - 1024;
 	}
 
-	state->dnxt.delivery = c->modulation;
-	state->dnxt.frequency = c->frequency;
-	state->dnxt.rolloff = 2; /* fixme */
-	state->dnxt.fec = c->fec_inner;
+	ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8);
+	ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff);
 
-	ret = ds3000_set_inversion(state, p->inversion);
-	if (ret !=  0)
-		return ret;
+	/* set pll */
+	ds3000_tuner_writereg(state, 0x03, 0x06);
+	ds3000_tuner_writereg(state, 0x51, 0x0f);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x10);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
 
-	ret = ds3000_set_symbolrate(state, c->symbol_rate);
-	if (ret !=  0)
-		return ret;
+	/* unknown */
+	ds3000_tuner_writereg(state, 0x51, 0x17);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x08);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
 
-	/* discard the 'current' tuning parameters and prepare to tune */
-	ds3000_clone_params(fe);
+	value = ds3000_tuner_readreg(state, 0x3d);
+	value &= 0x0f;
+	if ((value > 4) && (value < 15)) {
+		value -= 3;
+		if (value < 4)
+			value = 4;
+		value = ((value << 3) | 0x01) & 0x79;
+	}
 
-	retune = 1;	/* try 1 times */
-	dprintk("%s:   retune = %d\n", __func__, retune);
-	dprintk("%s:   frequency   = %d\n", __func__, state->dcur.frequency);
-	dprintk("%s:   symbol_rate = %d\n", __func__, state->dcur.symbol_rate);
-	dprintk("%s:   FEC	 = %d \n", __func__,
-		state->dcur.fec);
-	dprintk("%s:   Inversion   = %d\n", __func__, state->dcur.inversion);
+	ds3000_tuner_writereg(state, 0x60, value);
+	ds3000_tuner_writereg(state, 0x51, 0x17);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x08);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
 
-	do {
-		/* Reset status register */
-		status = 0;
-		/* Tune */
-		/* TS2020 init */
-		ds3000_tuner_writereg(state, 0x42, 0x73);
-		ds3000_tuner_writereg(state, 0x05, 0x01);
-		ds3000_tuner_writereg(state, 0x62, 0xf5);
-		/* unknown */
-		ds3000_tuner_writereg(state, 0x07, 0x02);
-		ds3000_tuner_writereg(state, 0x10, 0x00);
-		ds3000_tuner_writereg(state, 0x60, 0x79);
-		ds3000_tuner_writereg(state, 0x08, 0x01);
-		ds3000_tuner_writereg(state, 0x00, 0x01);
-		/* calculate and set freq divider */
-		if (state->dcur.frequency < 1146000) {
-			ds3000_tuner_writereg(state, 0x10, 0x11);
-			ndiv = ((state->dcur.frequency * (6 + 8) * 4) +
-					(DS3000_XTAL_FREQ / 2)) /
-					DS3000_XTAL_FREQ - 1024;
-		} else {
-			ds3000_tuner_writereg(state, 0x10, 0x01);
-			ndiv = ((state->dcur.frequency * (6 + 8) * 2) +
-					(DS3000_XTAL_FREQ / 2)) /
-					DS3000_XTAL_FREQ - 1024;
-		}
+	/* set low-pass filter period */
+	ds3000_tuner_writereg(state, 0x04, 0x2e);
+	ds3000_tuner_writereg(state, 0x51, 0x1b);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x04);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
 
-		ds3000_tuner_writereg(state, 0x01, (ndiv & 0x0f00) >> 8);
-		ds3000_tuner_writereg(state, 0x02, ndiv & 0x00ff);
+	f3db = ((c->symbol_rate / 1000) << 2) / 5 + 2000;
+	if ((c->symbol_rate / 1000) < 5000)
+		f3db += 3000;
+	if (f3db < 7000)
+		f3db = 7000;
+	if (f3db > 40000)
+		f3db = 40000;
 
-		/* set pll */
-		ds3000_tuner_writereg(state, 0x03, 0x06);
-		ds3000_tuner_writereg(state, 0x51, 0x0f);
-		ds3000_tuner_writereg(state, 0x51, 0x1f);
-		ds3000_tuner_writereg(state, 0x50, 0x10);
-		ds3000_tuner_writereg(state, 0x50, 0x00);
-		msleep(5);
+	/* set low-pass filter baseband */
+	value = ds3000_tuner_readreg(state, 0x26);
+	mlpf = 0x2e * 207 / ((value << 1) + 151);
+	mlpf_max = mlpf * 135 / 100;
+	mlpf_min = mlpf * 78 / 100;
+	if (mlpf_max > 63)
+		mlpf_max = 63;
 
-		/* unknown */
-		ds3000_tuner_writereg(state, 0x51, 0x17);
-		ds3000_tuner_writereg(state, 0x51, 0x1f);
-		ds3000_tuner_writereg(state, 0x50, 0x08);
-		ds3000_tuner_writereg(state, 0x50, 0x00);
-		msleep(5);
+	/* rounded to the closest integer */
+	nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2))
+			/ (2766 * DS3000_XTAL_FREQ);
+	if (nlpf > 23)
+		nlpf = 23;
+	if (nlpf < 1)
+		nlpf = 1;
 
-		value = ds3000_tuner_readreg(state, 0x3d);
-		value &= 0x0f;
-		if ((value > 4) && (value < 15)) {
-			value -= 3;
-			if (value < 4)
-				value = 4;
-			value = ((value << 3) | 0x01) & 0x79;
-		}
+	/* rounded to the closest integer */
+	mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
+			(1000 * f3db / 2)) / (1000 * f3db);
 
-		ds3000_tuner_writereg(state, 0x60, value);
-		ds3000_tuner_writereg(state, 0x51, 0x17);
-		ds3000_tuner_writereg(state, 0x51, 0x1f);
-		ds3000_tuner_writereg(state, 0x50, 0x08);
-		ds3000_tuner_writereg(state, 0x50, 0x00);
+	if (mlpf_new < mlpf_min) {
+		nlpf++;
+		mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
+				(1000 * f3db / 2)) / (1000 * f3db);
+	}
 
-		/* set low-pass filter period */
-		ds3000_tuner_writereg(state, 0x04, 0x2e);
-		ds3000_tuner_writereg(state, 0x51, 0x1b);
-		ds3000_tuner_writereg(state, 0x51, 0x1f);
-		ds3000_tuner_writereg(state, 0x50, 0x04);
-		ds3000_tuner_writereg(state, 0x50, 0x00);
-		msleep(5);
+	if (mlpf_new > mlpf_max)
+		mlpf_new = mlpf_max;
 
-		f3db = ((state->dcur.symbol_rate / 1000) << 2) / 5 + 2000;
-		if ((state->dcur.symbol_rate / 1000) < 5000)
-			f3db += 3000;
-		if (f3db < 7000)
-			f3db = 7000;
-		if (f3db > 40000)
-			f3db = 40000;
+	ds3000_tuner_writereg(state, 0x04, mlpf_new);
+	ds3000_tuner_writereg(state, 0x06, nlpf);
+	ds3000_tuner_writereg(state, 0x51, 0x1b);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x04);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(5);
 
-		/* set low-pass filter baseband */
-		value = ds3000_tuner_readreg(state, 0x26);
-		mlpf = 0x2e * 207 / ((value << 1) + 151);
-		mlpf_max = mlpf * 135 / 100;
-		mlpf_min = mlpf * 78 / 100;
-		if (mlpf_max > 63)
-			mlpf_max = 63;
+	/* unknown */
+	ds3000_tuner_writereg(state, 0x51, 0x1e);
+	ds3000_tuner_writereg(state, 0x51, 0x1f);
+	ds3000_tuner_writereg(state, 0x50, 0x01);
+	ds3000_tuner_writereg(state, 0x50, 0x00);
+	msleep(60);
 
-		/* rounded to the closest integer */
-		nlpf = ((mlpf * f3db * 1000) + (2766 * DS3000_XTAL_FREQ / 2))
-				/ (2766 * DS3000_XTAL_FREQ);
-		if (nlpf > 23)
-			nlpf = 23;
-		if (nlpf < 1)
-			nlpf = 1;
+	offset_khz = (ndiv - ndiv % 2 + 1024) * DS3000_XTAL_FREQ
+		/ (6 + 8) / (div4 + 1) / 2 - p->frequency;
 
-		/* rounded to the closest integer */
-		mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
-				(1000 * f3db / 2)) / (1000 * f3db);
+	/* ds3000 global reset */
+	ds3000_writereg(state, 0x07, 0x80);
+	ds3000_writereg(state, 0x07, 0x00);
+	/* ds3000 build-in uC reset */
+	ds3000_writereg(state, 0xb2, 0x01);
+	/* ds3000 software reset */
+	ds3000_writereg(state, 0x00, 0x01);
 
-		if (mlpf_new < mlpf_min) {
-			nlpf++;
-			mlpf_new = ((DS3000_XTAL_FREQ * nlpf * 2766) +
-					(1000 * f3db / 2)) / (1000 * f3db);
-		}
+	switch (c->delivery_system) {
+	case SYS_DVBS:
+		/* initialise the demod in DVB-S mode */
+		for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2)
+			ds3000_writereg(state,
+				ds3000_dvbs_init_tab[i],
+				ds3000_dvbs_init_tab[i + 1]);
+		value = ds3000_readreg(state, 0xfe);
+		value &= 0xc0;
+		value |= 0x1b;
+		ds3000_writereg(state, 0xfe, value);
+		break;
+	case SYS_DVBS2:
+		/* initialise the demod in DVB-S2 mode */
+		for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2)
+			ds3000_writereg(state,
+				ds3000_dvbs2_init_tab[i],
+				ds3000_dvbs2_init_tab[i + 1]);
+		ds3000_writereg(state, 0xfe, 0x98);
+		break;
+	default:
+		return 1;
+	}
 
-		if (mlpf_new > mlpf_max)
-			mlpf_new = mlpf_max;
+	/* enable 27MHz clock output */
+	ds3000_writereg(state, 0x29, 0x80);
+	/* enable ac coupling */
+	ds3000_writereg(state, 0x25, 0x8a);
 
-		ds3000_tuner_writereg(state, 0x04, mlpf_new);
-		ds3000_tuner_writereg(state, 0x06, nlpf);
-		ds3000_tuner_writereg(state, 0x51, 0x1b);
-		ds3000_tuner_writereg(state, 0x51, 0x1f);
-		ds3000_tuner_writereg(state, 0x50, 0x04);
-		ds3000_tuner_writereg(state, 0x50, 0x00);
-		msleep(5);
+	/* enhance symbol rate performance */
+	if ((c->symbol_rate / 1000) <= 5000) {
+		value = 29777 / (c->symbol_rate / 1000) + 1;
+		if (value % 2 != 0)
+			value++;
+		ds3000_writereg(state, 0xc3, 0x0d);
+		ds3000_writereg(state, 0xc8, value);
+		ds3000_writereg(state, 0xc4, 0x10);
+		ds3000_writereg(state, 0xc7, 0x0e);
+	} else if ((c->symbol_rate / 1000) <= 10000) {
+		value = 92166 / (c->symbol_rate / 1000) + 1;
+		if (value % 2 != 0)
+			value++;
+		ds3000_writereg(state, 0xc3, 0x07);
+		ds3000_writereg(state, 0xc8, value);
+		ds3000_writereg(state, 0xc4, 0x09);
+		ds3000_writereg(state, 0xc7, 0x12);
+	} else if ((c->symbol_rate / 1000) <= 20000) {
+		value = 64516 / (c->symbol_rate / 1000) + 1;
+		ds3000_writereg(state, 0xc3, value);
+		ds3000_writereg(state, 0xc8, 0x0e);
+		ds3000_writereg(state, 0xc4, 0x07);
+		ds3000_writereg(state, 0xc7, 0x18);
+	} else {
+		value = 129032 / (c->symbol_rate / 1000) + 1;
+		ds3000_writereg(state, 0xc3, value);
+		ds3000_writereg(state, 0xc8, 0x0a);
+		ds3000_writereg(state, 0xc4, 0x05);
+		ds3000_writereg(state, 0xc7, 0x24);
+	}
 
-		/* unknown */
-		ds3000_tuner_writereg(state, 0x51, 0x1e);
-		ds3000_tuner_writereg(state, 0x51, 0x1f);
-		ds3000_tuner_writereg(state, 0x50, 0x01);
-		ds3000_tuner_writereg(state, 0x50, 0x00);
-		msleep(60);
+	/* normalized symbol rate rounded to the closest integer */
+	value = (((c->symbol_rate / 1000) << 16) +
+			(DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE;
+	ds3000_writereg(state, 0x61, value & 0x00ff);
+	ds3000_writereg(state, 0x62, (value & 0xff00) >> 8);
 
-		/* ds3000 global reset */
-		ds3000_writereg(state, 0x07, 0x80);
-		ds3000_writereg(state, 0x07, 0x00);
-		/* ds3000 build-in uC reset */
-		ds3000_writereg(state, 0xb2, 0x01);
-		/* ds3000 software reset */
-		ds3000_writereg(state, 0x00, 0x01);
+	/* co-channel interference cancellation disabled */
+	ds3000_writereg(state, 0x56, 0x00);
 
+	/* equalizer disabled */
+	ds3000_writereg(state, 0x76, 0x00);
+
+	/*ds3000_writereg(state, 0x08, 0x03);
+	ds3000_writereg(state, 0xfd, 0x22);
+	ds3000_writereg(state, 0x08, 0x07);
+	ds3000_writereg(state, 0xfd, 0x42);
+	ds3000_writereg(state, 0x08, 0x07);*/
+
+	if (state->config->ci_mode) {
 		switch (c->delivery_system) {
 		case SYS_DVBS:
-			/* initialise the demod in DVB-S mode */
-			for (i = 0; i < sizeof(ds3000_dvbs_init_tab); i += 2)
-				ds3000_writereg(state,
-					ds3000_dvbs_init_tab[i],
-					ds3000_dvbs_init_tab[i + 1]);
-			value = ds3000_readreg(state, 0xfe);
-			value &= 0xc0;
-			value |= 0x1b;
-			ds3000_writereg(state, 0xfe, value);
-			break;
+		default:
+			ds3000_writereg(state, 0xfd, 0x80);
+		break;
 		case SYS_DVBS2:
-			/* initialise the demod in DVB-S2 mode */
-			for (i = 0; i < sizeof(ds3000_dvbs2_init_tab); i += 2)
-				ds3000_writereg(state,
-					ds3000_dvbs2_init_tab[i],
-					ds3000_dvbs2_init_tab[i + 1]);
-			ds3000_writereg(state, 0xfe, 0x54);
+			ds3000_writereg(state, 0xfd, 0x01);
 			break;
-		default:
-			return 1;
-		}
-
-		/* enable 27MHz clock output */
-		ds3000_writereg(state, 0x29, 0x80);
-		/* enable ac coupling */
-		ds3000_writereg(state, 0x25, 0x8a);
-
-		/* enhance symbol rate performance */
-		if ((state->dcur.symbol_rate / 1000) <= 5000) {
-			value = 29777 / (state->dcur.symbol_rate / 1000) + 1;
-			if (value % 2 != 0)
-				value++;
-			ds3000_writereg(state, 0xc3, 0x0d);
-			ds3000_writereg(state, 0xc8, value);
-			ds3000_writereg(state, 0xc4, 0x10);
-			ds3000_writereg(state, 0xc7, 0x0e);
-		} else if ((state->dcur.symbol_rate / 1000) <= 10000) {
-			value = 92166 / (state->dcur.symbol_rate / 1000) + 1;
-			if (value % 2 != 0)
-				value++;
-			ds3000_writereg(state, 0xc3, 0x07);
-			ds3000_writereg(state, 0xc8, value);
-			ds3000_writereg(state, 0xc4, 0x09);
-			ds3000_writereg(state, 0xc7, 0x12);
-		} else if ((state->dcur.symbol_rate / 1000) <= 20000) {
-			value = 64516 / (state->dcur.symbol_rate / 1000) + 1;
-			ds3000_writereg(state, 0xc3, value);
-			ds3000_writereg(state, 0xc8, 0x0e);
-			ds3000_writereg(state, 0xc4, 0x07);
-			ds3000_writereg(state, 0xc7, 0x18);
-		} else {
-			value = 129032 / (state->dcur.symbol_rate / 1000) + 1;
-			ds3000_writereg(state, 0xc3, value);
-			ds3000_writereg(state, 0xc8, 0x0a);
-			ds3000_writereg(state, 0xc4, 0x05);
-			ds3000_writereg(state, 0xc7, 0x24);
 		}
+	}
 
-		/* normalized symbol rate rounded to the closest integer */
-		value = (((state->dcur.symbol_rate / 1000) << 16) +
-				(DS3000_SAMPLE_RATE / 2)) / DS3000_SAMPLE_RATE;
-		ds3000_writereg(state, 0x61, value & 0x00ff);
-		ds3000_writereg(state, 0x62, (value & 0xff00) >> 8);
-
-		/* co-channel interference cancellation disabled */
-		ds3000_writereg(state, 0x56, 0x00);
-
-		/* equalizer disabled */
-		ds3000_writereg(state, 0x76, 0x00);
+	/* ds3000 out of software reset */
+	ds3000_writereg(state, 0x00, 0x00);
+	/* start ds3000 build-in uC */
+	ds3000_writereg(state, 0xb2, 0x00);
 
-		/*ds3000_writereg(state, 0x08, 0x03);
-		ds3000_writereg(state, 0xfd, 0x22);
-		ds3000_writereg(state, 0x08, 0x07);
-		ds3000_writereg(state, 0xfd, 0x42);
-		ds3000_writereg(state, 0x08, 0x07);*/
+	ds3000_set_carrier_offset(fe, offset_khz);
 
-		/* ds3000 out of software reset */
-		ds3000_writereg(state, 0x00, 0x00);
-		/* start ds3000 build-in uC */
-		ds3000_writereg(state, 0xb2, 0x00);
+	for (i = 0; i < 30 ; i++) {
+		ds3000_read_status(fe, &status);
+		if (status && FE_HAS_LOCK)
+			break;
 
-		/* TODO: calculate and set carrier offset */
+		msleep(10);
+	}
 
-		/* wait before retrying */
-		for (i = 0; i < 30 ; i++) {
-			if (ds3000_is_tuned(fe)) {
-				dprintk("%s: Tuned\n", __func__);
-				ds3000_dump_registers(fe);
-				goto tuned;
-			}
-			msleep(1);
-		}
+	return 0;
+}
 
-		dprintk("%s: Not tuned\n", __func__);
-		ds3000_dump_registers(fe);
+static int ds3000_tune(struct dvb_frontend *fe,
+			struct dvb_frontend_parameters *p,
+			unsigned int mode_flags,
+			unsigned int *delay,
+			fe_status_t *status)
+{
+	if (p) {
+		int ret = ds3000_set_frontend(fe, p);
+		if (ret)
+			return ret;
+	}
 
-	} while (--retune);
+	*delay = HZ / 5;
 
-tuned:
-	return ret;
+	return ds3000_read_status(fe, status);
 }
 
 static enum dvbfe_algo ds3000_get_algo(struct dvb_frontend *fe)
 {
 	dprintk("%s()\n", __func__);
-	return DVBFE_ALGO_SW;
+	return DVBFE_ALGO_HW;
 }
 
 /*
@@ -1304,7 +1247,25 @@
  */
 static int ds3000_initfe(struct dvb_frontend *fe)
 {
+	struct ds3000_state *state = fe->demodulator_priv;
+	int ret;
+
 	dprintk("%s()\n", __func__);
+	/* hard reset */
+	ds3000_writereg(state, 0x08, 0x01 | ds3000_readreg(state, 0x08));
+	msleep(1);
+
+	/* TS2020 init */
+	ds3000_tuner_writereg(state, 0x42, 0x73);
+	ds3000_tuner_writereg(state, 0x05, 0x01);
+	ds3000_tuner_writereg(state, 0x62, 0xf5);
+	/* Load the firmware if required */
+	ret = ds3000_firmware_ondemand(fe);
+	if (ret != 0) {
+		printk(KERN_ERR "%s: Unable initialize firmware\n", __func__);
+		return ret;
+	}
+
 	return 0;
 }
 
@@ -1343,6 +1304,7 @@
 	.read_signal_strength = ds3000_read_signal_strength,
 	.read_snr = ds3000_read_snr,
 	.read_ucblocks = ds3000_read_ucblocks,
+	.set_voltage = ds3000_set_voltage,
 	.set_tone = ds3000_set_tone,
 	.diseqc_send_master_cmd = ds3000_send_diseqc_msg,
 	.diseqc_send_burst = ds3000_diseqc_send_burst,
@@ -1350,7 +1312,8 @@
 
 	.set_property = ds3000_set_property,
 	.get_property = ds3000_get_property,
-	.set_frontend = ds3000_tune,
+	.set_frontend = ds3000_set_frontend,
+	.tune = ds3000_tune,
 };
 
 module_param(debug, int, 0644);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/ds3000.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/ds3000.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/ds3000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/ds3000.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,9 @@
 struct ds3000_config {
 	/* the demodulator's i2c address */
 	u8 demod_address;
+	u8 ci_mode;
+	/* Set device param to start dma */
+	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
 };
 
 #if defined(CONFIG_DVB_DS3000) || \
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dvb-pll.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dvb-pll.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/dvb-pll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/dvb-pll.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,6 +64,7 @@
 	void (*set)(struct dvb_frontend *fe, u8 *buf,
 		    const struct dvb_frontend_parameters *params);
 	u8   *initdata;
+	u8   *initdata2;
 	u8   *sleepdata;
 	int  count;
 	struct {
@@ -321,26 +322,73 @@
 static void opera1_bw(struct dvb_frontend *fe, u8 *buf,
 		      const struct dvb_frontend_parameters *params)
 {
-	if (params->u.ofdm.bandwidth == BANDWIDTH_8_MHZ)
-		buf[2] |= 0x08;
+	struct dvb_pll_priv *priv = fe->tuner_priv;
+	u32 b_w  = (params->u.qpsk.symbol_rate * 27) / 32000;
+	struct i2c_msg msg = {
+		.addr = priv->pll_i2c_address,
+		.flags = 0,
+		.buf = buf,
+		.len = 4
+	};
+	int result;
+	u8 lpf;
+
+	if (fe->ops.i2c_gate_ctrl)
+		fe->ops.i2c_gate_ctrl(fe, 1);
+
+	result = i2c_transfer(priv->i2c, &msg, 1);
+	if (result != 1)
+		printk(KERN_ERR "%s: i2c_transfer failed:%d",
+			__func__, result);
+
+	if (b_w <= 10000)
+		lpf = 0xc;
+	else if (b_w <= 12000)
+		lpf = 0x2;
+	else if (b_w <= 14000)
+		lpf = 0xa;
+	else if (b_w <= 16000)
+		lpf = 0x6;
+	else if (b_w <= 18000)
+		lpf = 0xe;
+	else if (b_w <= 20000)
+		lpf = 0x1;
+	else if (b_w <= 22000)
+		lpf = 0x9;
+	else if (b_w <= 24000)
+		lpf = 0x5;
+	else if (b_w <= 26000)
+		lpf = 0xd;
+	else if (b_w <= 28000)
+		lpf = 0x3;
+		else
+		lpf = 0xb;
+	buf[2] ^= 0x1c; /* Flip bits 3-5 */
+	/* Set lpf */
+	buf[2] |= ((lpf >> 2) & 0x3) << 3;
+	buf[3] |= (lpf & 0x3) << 2;
+
+	return;
 }
 
 static struct dvb_pll_desc dvb_pll_opera1 = {
 	.name  = "Opera Tuner",
 	.min   =  900000,
 	.max   = 2250000,
+	.initdata = (u8[]){ 4, 0x08, 0xe5, 0xe1, 0x00 },
+	.initdata2 = (u8[]){ 4, 0x08, 0xe5, 0xe5, 0x00 },
 	.iffreq= 0,
 	.set   = opera1_bw,
 	.count = 8,
 	.entries = {
-		{ 1064000, 500, 0xe5, 0xc6 },
-		{ 1169000, 500, 0xe5, 0xe6 },
-		{ 1299000, 500, 0xe5, 0x24 },
-		{ 1444000, 500, 0xe5, 0x44 },
-		{ 1606000, 500, 0xe5, 0x64 },
-		{ 1777000, 500, 0xe5, 0x84 },
-		{ 1941000, 500, 0xe5, 0xa4 },
-		{ 2250000, 500, 0xe5, 0xc4 },
+		{ 1064000, 500, 0xf9, 0xc2 },
+		{ 1169000, 500, 0xf9, 0xe2 },
+		{ 1299000, 500, 0xf9, 0x20 },
+		{ 1444000, 500, 0xf9, 0x40 },
+		{ 1606000, 500, 0xf9, 0x60 },
+		{ 1777000, 500, 0xf9, 0x80 },
+		{ 1941000, 500, 0xf9, 0xa0 },
+		{ 2250000, 500, 0xf9, 0xc0 },
 	}
 };
 
@@ -648,8 +696,17 @@
 		int result;
 		if (fe->ops.i2c_gate_ctrl)
 			fe->ops.i2c_gate_ctrl(fe, 1);
-		if ((result = i2c_transfer(priv->i2c, &msg, 1)) != 1) {
+		result = i2c_transfer(priv->i2c, &msg, 1);
+		if (result != 1)
 			return result;
+		if (priv->pll_desc->initdata2) {
+			msg.buf = priv->pll_desc->initdata2 + 1;
+			msg.len = priv->pll_desc->initdata2[0];
+			if (fe->ops.i2c_gate_ctrl)
+				fe->ops.i2c_gate_ctrl(fe, 1);
+			result = i2c_transfer(priv->i2c, &msg, 1);
+			if (result != 1)
+				return result;
 		}
 		return 0;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/Kconfig linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -349,6 +349,14 @@
 	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
 	  to support this frontend.
 
+config DVB_DIB9000
+	tristate "DiBcom 9000"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-T tuner module. Designed for mobile usage. Say Y when you want
+	  to support this frontend.
+
 config DVB_TDA10048
 	tristate "Philips TDA10048HN based"
 	depends on DVB_CORE && I2C
@@ -370,6 +378,13 @@
 	help
 	  Say Y when you want to support this frontend.
 
+config DVB_STV0367
+	tristate "ST STV0367 based"
+	depends on DVB_CORE && I2C
+	default m if DVB_FE_CUSTOMISE
+	help
+	  A DVB-T/C tuner module. Say Y when you want to support this frontend.
+
 comment "DVB-C (cable) frontends"
 	depends on DVB_CORE
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/Makefile linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 obj-$(CONFIG_DVB_DIB7000M) += dib7000m.o dibx000_common.o
 obj-$(CONFIG_DVB_DIB7000P) += dib7000p.o dibx000_common.o
 obj-$(CONFIG_DVB_DIB8000) += dib8000.o dibx000_common.o
+obj-$(CONFIG_DVB_DIB9000) += dib9000.o dibx000_common.o
 obj-$(CONFIG_DVB_MT312) += mt312.o
 obj-$(CONFIG_DVB_VES1820) += ves1820.o
 obj-$(CONFIG_DVB_VES1X93) += ves1x93.o
@@ -83,3 +84,4 @@
 obj-$(CONFIG_DVB_MB86A16) += mb86a16.o
 obj-$(CONFIG_DVB_MB86A20S) += mb86a20s.o
 obj-$(CONFIG_DVB_IX2505V) += ix2505v.o
+obj-$(CONFIG_DVB_STV0367) += stv0367.o
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/mb86a16.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/mb86a16.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/mb86a16.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/mb86a16.c	2011-05-19 00:06:34.000000000 -0400
@@ -1630,7 +1630,7 @@
 	state->srate = p->u.qpsk.symbol_rate / 1000;
 
 	if (!mb86a16_set_fe(state)) {
-		dprintk(verbose, MB86A16_ERROR, 1, "Succesfully acquired LOCK");
+		dprintk(verbose, MB86A16_ERROR, 1, "Successfully acquired LOCK");
 		return DVBFE_ALGO_SEARCH_SUCCESS;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/mb86a20s.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/mb86a20s.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/mb86a20s.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/mb86a20s.c	2011-05-19 00:06:34.000000000 -0400
@@ -406,7 +406,7 @@
 		printk(KERN_INFO "mb86a20s: Init failed. Will try again later\n");
 	} else {
 		state->need_init = false;
-		dprintk("Initialization succeded.\n");
+		dprintk("Initialization succeeded.\n");
 	}
 	return rc;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/mt312.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/mt312.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/mt312.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/mt312.c	2011-05-19 00:06:34.000000000 -0400
@@ -670,7 +670,7 @@
 		if (ret < 0)
 			goto error;
 
-		/* preserve this bit to not accidently shutdown ADC */
+		/* preserve this bit to not accidentally shutdown ADC */
 		val &= 0x80;
 		break;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/s5h1420.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/s5h1420.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/s5h1420.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/s5h1420.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,7 +225,7 @@
 	unsigned long timeout;
 	int result = 0;
 
-	/* setup for DISEQC recieve */
+	/* setup for DISEQC receive */
 	val = s5h1420_readreg(state, 0x3b);
 	s5h1420_writereg(state, 0x3b, 0x82); /* FIXME: guess - do we need to set DIS_RDY(0x08) in receive mode? */
 	msleep(15);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stb6100.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stb6100.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stb6100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stb6100.c	2011-05-19 00:06:34.000000000 -0400
@@ -360,7 +360,7 @@
 	else
 		odiv = 0;
 
-	/* VCO enabled, seach clock off as per LL3.7, 3.4.1 */
+	/* VCO enabled, search clock off as per LL3.7, 3.4.1 */
 	regs[STB6100_VCO] = 0xe0 | (odiv << STB6100_VCO_ODIV_SHIFT);
 
 	/* OSM	*/
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0288.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0288.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0288.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0288.c	2011-05-19 00:06:34.000000000 -0400
@@ -367,8 +367,11 @@
 	dprintk("%s : FE_READ_STATUS : VSTATUS: 0x%02x\n", __func__, sync);
 
 	*status = 0;
-
-	if ((sync & 0x08) == 0x08) {
+	if (sync & 0x80)
+		*status |= FE_HAS_CARRIER | FE_HAS_SIGNAL;
+	if (sync & 0x10)
+		*status |= FE_HAS_VITERBI;
+	if (sync & 0x08) {
 		*status |= FE_HAS_LOCK;
 		dprintk("stv0288 has locked\n");
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0297.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0297.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0297.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0297.c	2011-05-19 00:06:34.000000000 -0400
@@ -435,7 +435,7 @@
 		return -EINVAL;
 	}
 
-	// determine inversion dependant parameters
+	// determine inversion dependent parameters
 	inversion = p->inversion;
 	if (state->config->invert)
 		inversion = (inversion == INVERSION_ON) ? INVERSION_OFF : INVERSION_ON;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3459 @@
+/*
+ * stv0367.c
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/string.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+
+#include "stv0367.h"
+#include "stv0367_regs.h"
+#include "stv0367_priv.h"
+
+static int stvdebug;
+module_param_named(debug, stvdebug, int, 0644);
+
+static int i2cdebug;
+module_param_named(i2c_debug, i2cdebug, int, 0644);
+
+#define dprintk(args...) \
+	do { \
+		if (stvdebug) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+	/* DVB-C */
+
+struct stv0367cab_state {
+	enum stv0367_cab_signal_type	state;
+	u32	mclk;
+	u32	adc_clk;
+	s32	search_range;
+	s32	derot_offset;
+	/* results */
+	int locked;			/* channel found		*/
+	u32 freq_khz;			/* found frequency (in kHz)	*/
+	u32 symbol_rate;		/* found symbol rate (in Bds)	*/
+	enum stv0367cab_mod modulation;	/* modulation			*/
+	fe_spectral_inversion_t	spect_inv; /* Spectrum Inversion	*/
+};
+
+struct stv0367ter_state {
+	/* DVB-T */
+	enum stv0367_ter_signal_type state;
+	enum stv0367_ter_if_iq_mode if_iq_mode;
+	enum stv0367_ter_mode mode;/* mode 2K or 8K */
+	fe_guard_interval_t guard;
+	enum stv0367_ter_hierarchy hierarchy;
+	u32 frequency;
+	fe_spectral_inversion_t  sense; /*  current search spectrum */
+	u8  force; /* force mode/guard */
+	u8  bw; /* channel width 6, 7 or 8 in MHz */
+	u8  pBW; /* channel width used during previous lock */
+	u32 pBER;
+	u32 pPER;
+	u32 ucblocks;
+	s8  echo_pos; /* echo position */
+	u8  first_lock;
+	u8  unlock_counter;
+	u32 agc_val;
+};
+
+struct stv0367_state {
+	struct dvb_frontend fe;
+	struct i2c_adapter *i2c;
+	/* config settings */
+	const struct stv0367_config *config;
+	u8 chip_id;
+	/* DVB-C */
+	struct stv0367cab_state *cab_state;
+	/* DVB-T */
+	struct stv0367ter_state *ter_state;
+};
+
+struct st_register {
+	u16	addr;
+	u8	value;
+};
+
+/* values for STV4100 XTAL=30M int clk=53.125M*/
+static struct st_register def0367ter[STV0367TER_NBREGS] = {
+	{R367TER_ID,		0x60},
+	{R367TER_I2CRPT,	0xa0},
+	/* {R367TER_I2CRPT,	0x22},*/
+	{R367TER_TOPCTRL,	0x00},/* for xc5000; was 0x02 */
+	{R367TER_IOCFG0,	0x40},
+	{R367TER_DAC0R,		0x00},
+	{R367TER_IOCFG1,	0x00},
+	{R367TER_DAC1R,		0x00},
+	{R367TER_IOCFG2,	0x62},
+	{R367TER_SDFR,		0x00},
+	{R367TER_STATUS,	0xf8},
+	{R367TER_AUX_CLK,	0x0a},
+	{R367TER_FREESYS1,	0x00},
+	{R367TER_FREESYS2,	0x00},
+	{R367TER_FREESYS3,	0x00},
+	{R367TER_GPIO_CFG,	0x55},
+	{R367TER_GPIO_CMD,	0x00},
+	{R367TER_AGC2MAX,	0xff},
+	{R367TER_AGC2MIN,	0x00},
+	{R367TER_AGC1MAX,	0xff},
+	{R367TER_AGC1MIN,	0x00},
+	{R367TER_AGCR,		0xbc},
+	{R367TER_AGC2TH,	0x00},
+	{R367TER_AGC12C,	0x00},
+	{R367TER_AGCCTRL1,	0x85},
+	{R367TER_AGCCTRL2,	0x1f},
+	{R367TER_AGC1VAL1,	0x00},
+	{R367TER_AGC1VAL2,	0x00},
+	{R367TER_AGC2VAL1,	0x6f},
+	{R367TER_AGC2VAL2,	0x05},
+	{R367TER_AGC2PGA,	0x00},
+	{R367TER_OVF_RATE1,	0x00},
+	{R367TER_OVF_RATE2,	0x00},
+	{R367TER_GAIN_SRC1,	0xaa},/* for xc5000; was 0x2b */
+	{R367TER_GAIN_SRC2,	0xd6},/* for xc5000; was 0x04 */
+	{R367TER_INC_DEROT1,	0x55},
+	{R367TER_INC_DEROT2,	0x55},
+	{R367TER_PPM_CPAMP_DIR,	0x2c},
+	{R367TER_PPM_CPAMP_INV,	0x00},
+	{R367TER_FREESTFE_1,	0x00},
+	{R367TER_FREESTFE_2,	0x1c},
+	{R367TER_DCOFFSET,	0x00},
+	{R367TER_EN_PROCESS,	0x05},
+	{R367TER_SDI_SMOOTHER,	0x80},
+	{R367TER_FE_LOOP_OPEN,	0x1c},
+	{R367TER_FREQOFF1,	0x00},
+	{R367TER_FREQOFF2,	0x00},
+	{R367TER_FREQOFF3,	0x00},
+	{R367TER_TIMOFF1,	0x00},
+	{R367TER_TIMOFF2,	0x00},
+	{R367TER_EPQ,		0x02},
+	{R367TER_EPQAUTO,	0x01},
+	{R367TER_SYR_UPDATE,	0xf5},
+	{R367TER_CHPFREE,	0x00},
+	{R367TER_PPM_STATE_MAC,	0x23},
+	{R367TER_INR_THRESHOLD,	0xff},
+	{R367TER_EPQ_TPS_ID_CELL, 0xf9},
+	{R367TER_EPQ_CFG,	0x00},
+	{R367TER_EPQ_STATUS,	0x01},
+	{R367TER_AUTORELOCK,	0x81},
+	{R367TER_BER_THR_VMSB,	0x00},
+	{R367TER_BER_THR_MSB,	0x00},
+	{R367TER_BER_THR_LSB,	0x00},
+	{R367TER_CCD,		0x83},
+	{R367TER_SPECTR_CFG,	0x00},
+	{R367TER_CHC_DUMMY,	0x18},
+	{R367TER_INC_CTL,	0x88},
+	{R367TER_INCTHRES_COR1,	0xb4},
+	{R367TER_INCTHRES_COR2,	0x96},
+	{R367TER_INCTHRES_DET1,	0x0e},
+	{R367TER_INCTHRES_DET2,	0x11},
+	{R367TER_IIR_CELLNB,	0x8d},
+	{R367TER_IIRCX_COEFF1_MSB, 0x00},
+	{R367TER_IIRCX_COEFF1_LSB, 0x00},
+	{R367TER_IIRCX_COEFF2_MSB, 0x09},
+	{R367TER_IIRCX_COEFF2_LSB, 0x18},
+	{R367TER_IIRCX_COEFF3_MSB, 0x14},
+	{R367TER_IIRCX_COEFF3_LSB, 0x9c},
+	{R367TER_IIRCX_COEFF4_MSB, 0x00},
+	{R367TER_IIRCX_COEFF4_LSB, 0x00},
+	{R367TER_IIRCX_COEFF5_MSB, 0x36},
+	{R367TER_IIRCX_COEFF5_LSB, 0x42},
+	{R367TER_FEPATH_CFG,	0x00},
+	{R367TER_PMC1_FUNC,	0x65},
+	{R367TER_PMC1_FOR,	0x00},
+	{R367TER_PMC2_FUNC,	0x00},
+	{R367TER_STATUS_ERR_DA,	0xe0},
+	{R367TER_DIG_AGC_R,	0xfe},
+	{R367TER_COMAGC_TARMSB,	0x0b},
+	{R367TER_COM_AGC_TAR_ENMODE, 0x41},
+	{R367TER_COM_AGC_CFG,	0x3e},
+	{R367TER_COM_AGC_GAIN1, 0x39},
+	{R367TER_AUT_AGC_TARGETMSB, 0x0b},
+	{R367TER_LOCK_DET_MSB,	0x01},
+	{R367TER_AGCTAR_LOCK_LSBS, 0x40},
+	{R367TER_AUT_GAIN_EN,	0xf4},
+	{R367TER_AUT_CFG,	0xf0},
+	{R367TER_LOCKN,		0x23},
+	{R367TER_INT_X_3,	0x00},
+	{R367TER_INT_X_2,	0x03},
+	{R367TER_INT_X_1,	0x8d},
+	{R367TER_INT_X_0,	0xa0},
+	{R367TER_MIN_ERRX_MSB,	0x00},
+	{R367TER_COR_CTL,	0x23},
+	{R367TER_COR_STAT,	0xf6},
+	{R367TER_COR_INTEN,	0x00},
+	{R367TER_COR_INTSTAT,	0x3f},
+	{R367TER_COR_MODEGUARD,	0x03},
+	{R367TER_AGC_CTL,	0x08},
+	{R367TER_AGC_MANUAL1,	0x00},
+	{R367TER_AGC_MANUAL2,	0x00},
+	{R367TER_AGC_TARG,	0x16},
+	{R367TER_AGC_GAIN1,	0x53},
+	{R367TER_AGC_GAIN2,	0x1d},
+	{R367TER_RESERVED_1,	0x00},
+	{R367TER_RESERVED_2,	0x00},
+	{R367TER_RESERVED_3,	0x00},
+	{R367TER_CAS_CTL,	0x44},
+	{R367TER_CAS_FREQ,	0xb3},
+	{R367TER_CAS_DAGCGAIN,	0x12},
+	{R367TER_SYR_CTL,	0x04},
+	{R367TER_SYR_STAT,	0x10},
+	{R367TER_SYR_NCO1,	0x00},
+	{R367TER_SYR_NCO2,	0x00},
+	{R367TER_SYR_OFFSET1,	0x00},
+	{R367TER_SYR_OFFSET2,	0x00},
+	{R367TER_FFT_CTL,	0x00},
+	{R367TER_SCR_CTL,	0x70},
+	{R367TER_PPM_CTL1,	0xf8},
+	{R367TER_TRL_CTL,	0x14},/* for xc5000; was 0xac */
+	{R367TER_TRL_NOMRATE1,	0xae},/* for xc5000; was 0x1e */
+	{R367TER_TRL_NOMRATE2,	0x56},/* for xc5000; was 0x58 */
+	{R367TER_TRL_TIME1,	0x1d},
+	{R367TER_TRL_TIME2,	0xfc},
+	{R367TER_CRL_CTL,	0x24},
+	{R367TER_CRL_FREQ1,	0xad},
+	{R367TER_CRL_FREQ2,	0x9d},
+	{R367TER_CRL_FREQ3,	0xff},
+	{R367TER_CHC_CTL,	0x01},
+	{R367TER_CHC_SNR,	0xf0},
+	{R367TER_BDI_CTL,	0x00},
+	{R367TER_DMP_CTL,	0x00},
+	{R367TER_TPS_RCVD1,	0x30},
+	{R367TER_TPS_RCVD2,	0x02},
+	{R367TER_TPS_RCVD3,	0x01},
+	{R367TER_TPS_RCVD4,	0x00},
+	{R367TER_TPS_ID_CELL1,	0x00},
+	{R367TER_TPS_ID_CELL2,	0x00},
+	{R367TER_TPS_RCVD5_SET1, 0x02},
+	{R367TER_TPS_SET2,	0x02},
+	{R367TER_TPS_SET3,	0x01},
+	{R367TER_TPS_CTL,	0x00},
+	{R367TER_CTL_FFTOSNUM,	0x34},
+	{R367TER_TESTSELECT,	0x09},
+	{R367TER_MSC_REV,	0x0a},
+	{R367TER_PIR_CTL,	0x00},
+	{R367TER_SNR_CARRIER1,	0xa1},
+	{R367TER_SNR_CARRIER2,	0x9a},
+	{R367TER_PPM_CPAMP,	0x2c},
+	{R367TER_TSM_AP0,	0x00},
+	{R367TER_TSM_AP1,	0x00},
+	{R367TER_TSM_AP2 ,	0x00},
+	{R367TER_TSM_AP3,	0x00},
+	{R367TER_TSM_AP4,	0x00},
+	{R367TER_TSM_AP5,	0x00},
+	{R367TER_TSM_AP6,	0x00},
+	{R367TER_TSM_AP7,	0x00},
+	{R367TER_TSTRES,	0x00},
+	{R367TER_ANACTRL,	0x0D},/* PLL stoped, restart at init!!! */
+	{R367TER_TSTBUS,	0x00},
+	{R367TER_TSTRATE,	0x00},
+	{R367TER_CONSTMODE,	0x01},
+	{R367TER_CONSTCARR1,	0x00},
+	{R367TER_CONSTCARR2,	0x00},
+	{R367TER_ICONSTEL,	0x0a},
+	{R367TER_QCONSTEL,	0x15},
+	{R367TER_TSTBISTRES0,	0x00},
+	{R367TER_TSTBISTRES1,	0x00},
+	{R367TER_TSTBISTRES2,	0x28},
+	{R367TER_TSTBISTRES3,	0x00},
+	{R367TER_RF_AGC1,	0xff},
+	{R367TER_RF_AGC2,	0x83},
+	{R367TER_ANADIGCTRL,	0x19},
+	{R367TER_PLLMDIV,	0x01},/* for xc5000; was 0x0c */
+	{R367TER_PLLNDIV,	0x06},/* for xc5000; was 0x55 */
+	{R367TER_PLLSETUP,	0x18},
+	{R367TER_DUAL_AD12,	0x0C},/* for xc5000 AGC voltage 1.6V */
+	{R367TER_TSTBIST,	0x00},
+	{R367TER_PAD_COMP_CTRL,	0x00},
+	{R367TER_PAD_COMP_WR,	0x00},
+	{R367TER_PAD_COMP_RD,	0xe0},
+	{R367TER_SYR_TARGET_FFTADJT_MSB, 0x00},
+	{R367TER_SYR_TARGET_FFTADJT_LSB, 0x00},
+	{R367TER_SYR_TARGET_CHCADJT_MSB, 0x00},
+	{R367TER_SYR_TARGET_CHCADJT_LSB, 0x00},
+	{R367TER_SYR_FLAG,	0x00},
+	{R367TER_CRL_TARGET1,	0x00},
+	{R367TER_CRL_TARGET2,	0x00},
+	{R367TER_CRL_TARGET3,	0x00},
+	{R367TER_CRL_TARGET4,	0x00},
+	{R367TER_CRL_FLAG,	0x00},
+	{R367TER_TRL_TARGET1,	0x00},
+	{R367TER_TRL_TARGET2,	0x00},
+	{R367TER_TRL_CHC,	0x00},
+	{R367TER_CHC_SNR_TARG,	0x00},
+	{R367TER_TOP_TRACK,	0x00},
+	{R367TER_TRACKER_FREE1,	0x00},
+	{R367TER_ERROR_CRL1,	0x00},
+	{R367TER_ERROR_CRL2,	0x00},
+	{R367TER_ERROR_CRL3,	0x00},
+	{R367TER_ERROR_CRL4,	0x00},
+	{R367TER_DEC_NCO1,	0x2c},
+	{R367TER_DEC_NCO2,	0x0f},
+	{R367TER_DEC_NCO3,	0x20},
+	{R367TER_SNR,		0xf1},
+	{R367TER_SYR_FFTADJ1,	0x00},
+	{R367TER_SYR_FFTADJ2,	0x00},
+	{R367TER_SYR_CHCADJ1,	0x00},
+	{R367TER_SYR_CHCADJ2,	0x00},
+	{R367TER_SYR_OFF,	0x00},
+	{R367TER_PPM_OFFSET1,	0x00},
+	{R367TER_PPM_OFFSET2,	0x03},
+	{R367TER_TRACKER_FREE2,	0x00},
+	{R367TER_DEBG_LT10,	0x00},
+	{R367TER_DEBG_LT11,	0x00},
+	{R367TER_DEBG_LT12,	0x00},
+	{R367TER_DEBG_LT13,	0x00},
+	{R367TER_DEBG_LT14,	0x00},
+	{R367TER_DEBG_LT15,	0x00},
+	{R367TER_DEBG_LT16,	0x00},
+	{R367TER_DEBG_LT17,	0x00},
+	{R367TER_DEBG_LT18,	0x00},
+	{R367TER_DEBG_LT19,	0x00},
+	{R367TER_DEBG_LT1A,	0x00},
+	{R367TER_DEBG_LT1B,	0x00},
+	{R367TER_DEBG_LT1C,	0x00},
+	{R367TER_DEBG_LT1D,	0x00},
+	{R367TER_DEBG_LT1E,	0x00},
+	{R367TER_DEBG_LT1F,	0x00},
+	{R367TER_RCCFGH,	0x00},
+	{R367TER_RCCFGM,	0x00},
+	{R367TER_RCCFGL,	0x00},
+	{R367TER_RCINSDELH,	0x00},
+	{R367TER_RCINSDELM,	0x00},
+	{R367TER_RCINSDELL,	0x00},
+	{R367TER_RCSTATUS,	0x00},
+	{R367TER_RCSPEED,	0x6f},
+	{R367TER_RCDEBUGM,	0xe7},
+	{R367TER_RCDEBUGL,	0x9b},
+	{R367TER_RCOBSCFG,	0x00},
+	{R367TER_RCOBSM,	0x00},
+	{R367TER_RCOBSL,	0x00},
+	{R367TER_RCFECSPY,	0x00},
+	{R367TER_RCFSPYCFG,	0x00},
+	{R367TER_RCFSPYDATA,	0x00},
+	{R367TER_RCFSPYOUT,	0x00},
+	{R367TER_RCFSTATUS,	0x00},
+	{R367TER_RCFGOODPACK,	0x00},
+	{R367TER_RCFPACKCNT,	0x00},
+	{R367TER_RCFSPYMISC,	0x00},
+	{R367TER_RCFBERCPT4,	0x00},
+	{R367TER_RCFBERCPT3,	0x00},
+	{R367TER_RCFBERCPT2,	0x00},
+	{R367TER_RCFBERCPT1,	0x00},
+	{R367TER_RCFBERCPT0,	0x00},
+	{R367TER_RCFBERERR2,	0x00},
+	{R367TER_RCFBERERR1,	0x00},
+	{R367TER_RCFBERERR0,	0x00},
+	{R367TER_RCFSTATESM,	0x00},
+	{R367TER_RCFSTATESL,	0x00},
+	{R367TER_RCFSPYBER,	0x00},
+	{R367TER_RCFSPYDISTM,	0x00},
+	{R367TER_RCFSPYDISTL,	0x00},
+	{R367TER_RCFSPYOBS7,	0x00},
+	{R367TER_RCFSPYOBS6,	0x00},
+	{R367TER_RCFSPYOBS5,	0x00},
+	{R367TER_RCFSPYOBS4,	0x00},
+	{R367TER_RCFSPYOBS3,	0x00},
+	{R367TER_RCFSPYOBS2,	0x00},
+	{R367TER_RCFSPYOBS1,	0x00},
+	{R367TER_RCFSPYOBS0,	0x00},
+	{R367TER_TSGENERAL,	0x00},
+	{R367TER_RC1SPEED,	0x6f},
+	{R367TER_TSGSTATUS,	0x18},
+	{R367TER_FECM,		0x01},
+	{R367TER_VTH12,		0xff},
+	{R367TER_VTH23,		0xa1},
+	{R367TER_VTH34,		0x64},
+	{R367TER_VTH56,		0x40},
+	{R367TER_VTH67,		0x00},
+	{R367TER_VTH78,		0x2c},
+	{R367TER_VITCURPUN,	0x12},
+	{R367TER_VERROR,	0x01},
+	{R367TER_PRVIT,		0x3f},
+	{R367TER_VAVSRVIT,	0x00},
+	{R367TER_VSTATUSVIT,	0xbd},
+	{R367TER_VTHINUSE,	0xa1},
+	{R367TER_KDIV12,	0x20},
+	{R367TER_KDIV23,	0x40},
+	{R367TER_KDIV34,	0x20},
+	{R367TER_KDIV56,	0x30},
+	{R367TER_KDIV67,	0x00},
+	{R367TER_KDIV78,	0x30},
+	{R367TER_SIGPOWER,	0x54},
+	{R367TER_DEMAPVIT,	0x40},
+	{R367TER_VITSCALE,	0x00},
+	{R367TER_FFEC1PRG,	0x00},
+	{R367TER_FVITCURPUN,	0x12},
+	{R367TER_FVERROR,	0x01},
+	{R367TER_FVSTATUSVIT,	0xbd},
+	{R367TER_DEBUG_LT1,	0x00},
+	{R367TER_DEBUG_LT2,	0x00},
+	{R367TER_DEBUG_LT3,	0x00},
+	{R367TER_TSTSFMET,	0x00},
+	{R367TER_SELOUT,	0x00},
+	{R367TER_TSYNC,		0x00},
+	{R367TER_TSTERR,	0x00},
+	{R367TER_TSFSYNC,	0x00},
+	{R367TER_TSTSFERR,	0x00},
+	{R367TER_TSTTSSF1,	0x01},
+	{R367TER_TSTTSSF2,	0x1f},
+	{R367TER_TSTTSSF3,	0x00},
+	{R367TER_TSTTS1,	0x00},
+	{R367TER_TSTTS2,	0x1f},
+	{R367TER_TSTTS3,	0x01},
+	{R367TER_TSTTS4,	0x00},
+	{R367TER_TSTTSRC,	0x00},
+	{R367TER_TSTTSRS,	0x00},
+	{R367TER_TSSTATEM,	0xb0},
+	{R367TER_TSSTATEL,	0x40},
+	{R367TER_TSCFGH,	0xC0},
+	{R367TER_TSCFGM,	0xc0},/* for xc5000; was 0x00 */
+	{R367TER_TSCFGL,	0x20},
+	{R367TER_TSSYNC,	0x00},
+	{R367TER_TSINSDELH,	0x00},
+	{R367TER_TSINSDELM,	0x00},
+	{R367TER_TSINSDELL,	0x00},
+	{R367TER_TSDIVN,	0x03},
+	{R367TER_TSDIVPM,	0x00},
+	{R367TER_TSDIVPL,	0x00},
+	{R367TER_TSDIVQM,	0x00},
+	{R367TER_TSDIVQL,	0x00},
+	{R367TER_TSDILSTKM,	0x00},
+	{R367TER_TSDILSTKL,	0x00},
+	{R367TER_TSSPEED,	0x40},/* for xc5000; was 0x6f */
+	{R367TER_TSSTATUS,	0x81},
+	{R367TER_TSSTATUS2,	0x6a},
+	{R367TER_TSBITRATEM,	0x0f},
+	{R367TER_TSBITRATEL,	0xc6},
+	{R367TER_TSPACKLENM,	0x00},
+	{R367TER_TSPACKLENL,	0xfc},
+	{R367TER_TSBLOCLENM,	0x0a},
+	{R367TER_TSBLOCLENL,	0x80},
+	{R367TER_TSDLYH,	0x90},
+	{R367TER_TSDLYM,	0x68},
+	{R367TER_TSDLYL,	0x01},
+	{R367TER_TSNPDAV,	0x00},
+	{R367TER_TSBUFSTATH,	0x00},
+	{R367TER_TSBUFSTATM,	0x00},
+	{R367TER_TSBUFSTATL,	0x00},
+	{R367TER_TSDEBUGM,	0xcf},
+	{R367TER_TSDEBUGL,	0x1e},
+	{R367TER_TSDLYSETH,	0x00},
+	{R367TER_TSDLYSETM,	0x68},
+	{R367TER_TSDLYSETL,	0x00},
+	{R367TER_TSOBSCFG,	0x00},
+	{R367TER_TSOBSM,	0x47},
+	{R367TER_TSOBSL,	0x1f},
+	{R367TER_ERRCTRL1,	0x95},
+	{R367TER_ERRCNT1H,	0x80},
+	{R367TER_ERRCNT1M,	0x00},
+	{R367TER_ERRCNT1L,	0x00},
+	{R367TER_ERRCTRL2,	0x95},
+	{R367TER_ERRCNT2H,	0x00},
+	{R367TER_ERRCNT2M,	0x00},
+	{R367TER_ERRCNT2L,	0x00},
+	{R367TER_FECSPY,	0x88},
+	{R367TER_FSPYCFG,	0x2c},
+	{R367TER_FSPYDATA,	0x3a},
+	{R367TER_FSPYOUT,	0x06},
+	{R367TER_FSTATUS,	0x61},
+	{R367TER_FGOODPACK,	0xff},
+	{R367TER_FPACKCNT,	0xff},
+	{R367TER_FSPYMISC,	0x66},
+	{R367TER_FBERCPT4,	0x00},
+	{R367TER_FBERCPT3,	0x00},
+	{R367TER_FBERCPT2,	0x36},
+	{R367TER_FBERCPT1,	0x36},
+	{R367TER_FBERCPT0,	0x14},
+	{R367TER_FBERERR2,	0x00},
+	{R367TER_FBERERR1,	0x03},
+	{R367TER_FBERERR0,	0x28},
+	{R367TER_FSTATESM,	0x00},
+	{R367TER_FSTATESL,	0x02},
+	{R367TER_FSPYBER,	0x00},
+	{R367TER_FSPYDISTM,	0x01},
+	{R367TER_FSPYDISTL,	0x9f},
+	{R367TER_FSPYOBS7,	0xc9},
+	{R367TER_FSPYOBS6,	0x99},
+	{R367TER_FSPYOBS5,	0x08},
+	{R367TER_FSPYOBS4,	0xec},
+	{R367TER_FSPYOBS3,	0x01},
+	{R367TER_FSPYOBS2,	0x0f},
+	{R367TER_FSPYOBS1,	0xf5},
+	{R367TER_FSPYOBS0,	0x08},
+	{R367TER_SFDEMAP,	0x40},
+	{R367TER_SFERROR,	0x00},
+	{R367TER_SFAVSR,	0x30},
+	{R367TER_SFECSTATUS,	0xcc},
+	{R367TER_SFKDIV12,	0x20},
+	{R367TER_SFKDIV23,	0x40},
+	{R367TER_SFKDIV34,	0x20},
+	{R367TER_SFKDIV56,	0x20},
+	{R367TER_SFKDIV67,	0x00},
+	{R367TER_SFKDIV78,	0x20},
+	{R367TER_SFDILSTKM,	0x00},
+	{R367TER_SFDILSTKL,	0x00},
+	{R367TER_SFSTATUS,	0xb5},
+	{R367TER_SFDLYH,	0x90},
+	{R367TER_SFDLYM,	0x60},
+	{R367TER_SFDLYL,	0x01},
+	{R367TER_SFDLYSETH,	0xc0},
+	{R367TER_SFDLYSETM,	0x60},
+	{R367TER_SFDLYSETL,	0x00},
+	{R367TER_SFOBSCFG,	0x00},
+	{R367TER_SFOBSM,	0x47},
+	{R367TER_SFOBSL,	0x05},
+	{R367TER_SFECINFO,	0x40},
+	{R367TER_SFERRCTRL,	0x74},
+	{R367TER_SFERRCNTH,	0x80},
+	{R367TER_SFERRCNTM ,	0x00},
+	{R367TER_SFERRCNTL,	0x00},
+	{R367TER_SYMBRATEM,	0x2f},
+	{R367TER_SYMBRATEL,	0x50},
+	{R367TER_SYMBSTATUS,	0x7f},
+	{R367TER_SYMBCFG,	0x00},
+	{R367TER_SYMBFIFOM,	0xf4},
+	{R367TER_SYMBFIFOL,	0x0d},
+	{R367TER_SYMBOFFSM,	0xf0},
+	{R367TER_SYMBOFFSL,	0x2d},
+	{R367TER_DEBUG_LT4,	0x00},
+	{R367TER_DEBUG_LT5,	0x00},
+	{R367TER_DEBUG_LT6,	0x00},
+	{R367TER_DEBUG_LT7,	0x00},
+	{R367TER_DEBUG_LT8,	0x00},
+	{R367TER_DEBUG_LT9,	0x00},
+};
+
+#define RF_LOOKUP_TABLE_SIZE  31
+#define RF_LOOKUP_TABLE2_SIZE 16
+/* RF Level (for RF AGC->AGC1) Lookup Table, depends on the board and tuner.*/
+s32 stv0367cab_RF_LookUp1[RF_LOOKUP_TABLE_SIZE][RF_LOOKUP_TABLE_SIZE] = {
+	{/*AGC1*/
+		48, 50, 51, 53, 54, 56, 57, 58, 60, 61, 62, 63,
+		64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75,
+		76, 77, 78, 80, 83, 85, 88,
+	}, {/*RF(dbm)*/
+		22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
+		34, 35, 36, 37, 38, 39, 41, 42, 43, 44, 46, 47,
+		49, 50, 52, 53, 54, 55, 56,
+	}
+};
+/* RF Level (for IF AGC->AGC2) Lookup Table, depends on the board and tuner.*/
+s32 stv0367cab_RF_LookUp2[RF_LOOKUP_TABLE2_SIZE][RF_LOOKUP_TABLE2_SIZE] = {
+	{/*AGC2*/
+		28, 29, 31, 32, 34, 35, 36, 37,
+		38, 39, 40, 41, 42, 43, 44, 45,
+	}, {/*RF(dbm)*/
+		57, 58, 59, 60, 61, 62, 63, 64,
+		65, 66, 67, 68, 69, 70, 71, 72,
+	}
+};
+
+static struct st_register def0367cab[STV0367CAB_NBREGS] = {
+	{R367CAB_ID,		0x60},
+	{R367CAB_I2CRPT,	0xa0},
+	/*{R367CAB_I2CRPT,	0x22},*/
+	{R367CAB_TOPCTRL,	0x10},
+	{R367CAB_IOCFG0,	0x80},
+	{R367CAB_DAC0R,		0x00},
+	{R367CAB_IOCFG1,	0x00},
+	{R367CAB_DAC1R,		0x00},
+	{R367CAB_IOCFG2,	0x00},
+	{R367CAB_SDFR,		0x00},
+	{R367CAB_AUX_CLK,	0x00},
+	{R367CAB_FREESYS1,	0x00},
+	{R367CAB_FREESYS2,	0x00},
+	{R367CAB_FREESYS3,	0x00},
+	{R367CAB_GPIO_CFG,	0x55},
+	{R367CAB_GPIO_CMD,	0x01},
+	{R367CAB_TSTRES,	0x00},
+	{R367CAB_ANACTRL,	0x0d},/* was 0x00 need to check - I.M.L.*/
+	{R367CAB_TSTBUS,	0x00},
+	{R367CAB_RF_AGC1,	0xea},
+	{R367CAB_RF_AGC2,	0x82},
+	{R367CAB_ANADIGCTRL,	0x0b},
+	{R367CAB_PLLMDIV,	0x01},
+	{R367CAB_PLLNDIV,	0x08},
+	{R367CAB_PLLSETUP,	0x18},
+	{R367CAB_DUAL_AD12,	0x0C}, /* for xc5000 AGC voltage 1.6V */
+	{R367CAB_TSTBIST,	0x00},
+	{R367CAB_CTRL_1,	0x00},
+	{R367CAB_CTRL_2,	0x03},
+	{R367CAB_IT_STATUS1,	0x2b},
+	{R367CAB_IT_STATUS2,	0x08},
+	{R367CAB_IT_EN1,	0x00},
+	{R367CAB_IT_EN2,	0x00},
+	{R367CAB_CTRL_STATUS,	0x04},
+	{R367CAB_TEST_CTL,	0x00},
+	{R367CAB_AGC_CTL,	0x73},
+	{R367CAB_AGC_IF_CFG,	0x50},
+	{R367CAB_AGC_RF_CFG,	0x00},
+	{R367CAB_AGC_PWM_CFG,	0x03},
+	{R367CAB_AGC_PWR_REF_L,	0x5a},
+	{R367CAB_AGC_PWR_REF_H,	0x00},
+	{R367CAB_AGC_RF_TH_L,	0xff},
+	{R367CAB_AGC_RF_TH_H,	0x07},
+	{R367CAB_AGC_IF_LTH_L,	0x00},
+	{R367CAB_AGC_IF_LTH_H,	0x08},
+	{R367CAB_AGC_IF_HTH_L,	0xff},
+	{R367CAB_AGC_IF_HTH_H,	0x07},
+	{R367CAB_AGC_PWR_RD_L,	0xa0},
+	{R367CAB_AGC_PWR_RD_M,	0xe9},
+	{R367CAB_AGC_PWR_RD_H,	0x03},
+	{R367CAB_AGC_PWM_IFCMD_L,	0xe4},
+	{R367CAB_AGC_PWM_IFCMD_H,	0x00},
+	{R367CAB_AGC_PWM_RFCMD_L,	0xff},
+	{R367CAB_AGC_PWM_RFCMD_H,	0x07},
+	{R367CAB_IQDEM_CFG,	0x01},
+	{R367CAB_MIX_NCO_LL,	0x22},
+	{R367CAB_MIX_NCO_HL,	0x96},
+	{R367CAB_MIX_NCO_HH,	0x55},
+	{R367CAB_SRC_NCO_LL,	0xff},
+	{R367CAB_SRC_NCO_LH,	0x0c},
+	{R367CAB_SRC_NCO_HL,	0xf5},
+	{R367CAB_SRC_NCO_HH,	0x20},
+	{R367CAB_IQDEM_GAIN_SRC_L,	0x06},
+	{R367CAB_IQDEM_GAIN_SRC_H,	0x01},
+	{R367CAB_IQDEM_DCRM_CFG_LL,	0xfe},
+	{R367CAB_IQDEM_DCRM_CFG_LH,	0xff},
+	{R367CAB_IQDEM_DCRM_CFG_HL,	0x0f},
+	{R367CAB_IQDEM_DCRM_CFG_HH,	0x00},
+	{R367CAB_IQDEM_ADJ_COEFF0,	0x34},
+	{R367CAB_IQDEM_ADJ_COEFF1,	0xae},
+	{R367CAB_IQDEM_ADJ_COEFF2,	0x46},
+	{R367CAB_IQDEM_ADJ_COEFF3,	0x77},
+	{R367CAB_IQDEM_ADJ_COEFF4,	0x96},
+	{R367CAB_IQDEM_ADJ_COEFF5,	0x69},
+	{R367CAB_IQDEM_ADJ_COEFF6,	0xc7},
+	{R367CAB_IQDEM_ADJ_COEFF7,	0x01},
+	{R367CAB_IQDEM_ADJ_EN,	0x04},
+	{R367CAB_IQDEM_ADJ_AGC_REF,	0x94},
+	{R367CAB_ALLPASSFILT1,	0xc9},
+	{R367CAB_ALLPASSFILT2,	0x2d},
+	{R367CAB_ALLPASSFILT3,	0xa3},
+	{R367CAB_ALLPASSFILT4,	0xfb},
+	{R367CAB_ALLPASSFILT5,	0xf6},
+	{R367CAB_ALLPASSFILT6,	0x45},
+	{R367CAB_ALLPASSFILT7,	0x6f},
+	{R367CAB_ALLPASSFILT8,	0x7e},
+	{R367CAB_ALLPASSFILT9,	0x05},
+	{R367CAB_ALLPASSFILT10,	0x0a},
+	{R367CAB_ALLPASSFILT11,	0x51},
+	{R367CAB_TRL_AGC_CFG,	0x20},
+	{R367CAB_TRL_LPF_CFG,	0x28},
+	{R367CAB_TRL_LPF_ACQ_GAIN,	0x44},
+	{R367CAB_TRL_LPF_TRK_GAIN,	0x22},
+	{R367CAB_TRL_LPF_OUT_GAIN,	0x03},
+	{R367CAB_TRL_LOCKDET_LTH,	0x04},
+	{R367CAB_TRL_LOCKDET_HTH,	0x11},
+	{R367CAB_TRL_LOCKDET_TRGVAL,	0x20},
+	{R367CAB_IQ_QAM,	0x01},
+	{R367CAB_FSM_STATE,	0xa0},
+	{R367CAB_FSM_CTL,	0x08},
+	{R367CAB_FSM_STS,	0x0c},
+	{R367CAB_FSM_SNR0_HTH,	0x00},
+	{R367CAB_FSM_SNR1_HTH,	0x00},
+	{R367CAB_FSM_SNR2_HTH,	0x23},/* 0x00 */
+	{R367CAB_FSM_SNR0_LTH,	0x00},
+	{R367CAB_FSM_SNR1_LTH,	0x00},
+	{R367CAB_FSM_EQA1_HTH,	0x00},
+	{R367CAB_FSM_TEMPO,	0x32},
+	{R367CAB_FSM_CONFIG,	0x03},
+	{R367CAB_EQU_I_TESTTAP_L,	0x11},
+	{R367CAB_EQU_I_TESTTAP_M,	0x00},
+	{R367CAB_EQU_I_TESTTAP_H,	0x00},
+	{R367CAB_EQU_TESTAP_CFG,	0x00},
+	{R367CAB_EQU_Q_TESTTAP_L,	0xff},
+	{R367CAB_EQU_Q_TESTTAP_M,	0x00},
+	{R367CAB_EQU_Q_TESTTAP_H,	0x00},
+	{R367CAB_EQU_TAP_CTRL,	0x00},
+	{R367CAB_EQU_CTR_CRL_CONTROL_L,	0x11},
+	{R367CAB_EQU_CTR_CRL_CONTROL_H,	0x05},
+	{R367CAB_EQU_CTR_HIPOW_L,	0x00},
+	{R367CAB_EQU_CTR_HIPOW_H,	0x00},
+	{R367CAB_EQU_I_EQU_LO,	0xef},
+	{R367CAB_EQU_I_EQU_HI,	0x00},
+	{R367CAB_EQU_Q_EQU_LO,	0xee},
+	{R367CAB_EQU_Q_EQU_HI,	0x00},
+	{R367CAB_EQU_MAPPER,	0xc5},
+	{R367CAB_EQU_SWEEP_RATE,	0x80},
+	{R367CAB_EQU_SNR_LO,	0x64},
+	{R367CAB_EQU_SNR_HI,	0x03},
+	{R367CAB_EQU_GAMMA_LO,	0x00},
+	{R367CAB_EQU_GAMMA_HI,	0x00},
+	{R367CAB_EQU_ERR_GAIN,	0x36},
+	{R367CAB_EQU_RADIUS,	0xaa},
+	{R367CAB_EQU_FFE_MAINTAP,	0x00},
+	{R367CAB_EQU_FFE_LEAKAGE,	0x63},
+	{R367CAB_EQU_FFE_MAINTAP_POS,	0xdf},
+	{R367CAB_EQU_GAIN_WIDE,	0x88},
+	{R367CAB_EQU_GAIN_NARROW,	0x41},
+	{R367CAB_EQU_CTR_LPF_GAIN,	0xd1},
+	{R367CAB_EQU_CRL_LPF_GAIN,	0xa7},
+	{R367CAB_EQU_GLOBAL_GAIN,	0x06},
+	{R367CAB_EQU_CRL_LD_SEN,	0x85},
+	{R367CAB_EQU_CRL_LD_VAL,	0xe2},
+	{R367CAB_EQU_CRL_TFR,	0x20},
+	{R367CAB_EQU_CRL_BISTH_LO,	0x00},
+	{R367CAB_EQU_CRL_BISTH_HI,	0x00},
+	{R367CAB_EQU_SWEEP_RANGE_LO,	0x00},
+	{R367CAB_EQU_SWEEP_RANGE_HI,	0x00},
+	{R367CAB_EQU_CRL_LIMITER,	0x40},
+	{R367CAB_EQU_MODULUS_MAP,	0x90},
+	{R367CAB_EQU_PNT_GAIN,	0xa7},
+	{R367CAB_FEC_AC_CTR_0,	0x16},
+	{R367CAB_FEC_AC_CTR_1,	0x0b},
+	{R367CAB_FEC_AC_CTR_2,	0x88},
+	{R367CAB_FEC_AC_CTR_3,	0x02},
+	{R367CAB_FEC_STATUS,	0x12},
+	{R367CAB_RS_COUNTER_0,	0x7d},
+	{R367CAB_RS_COUNTER_1,	0xd0},
+	{R367CAB_RS_COUNTER_2,	0x19},
+	{R367CAB_RS_COUNTER_3,	0x0b},
+	{R367CAB_RS_COUNTER_4,	0xa3},
+	{R367CAB_RS_COUNTER_5,	0x00},
+	{R367CAB_BERT_0,	0x01},
+	{R367CAB_BERT_1,	0x25},
+	{R367CAB_BERT_2,	0x41},
+	{R367CAB_BERT_3,	0x39},
+	{R367CAB_OUTFORMAT_0,	0xc2},
+	{R367CAB_OUTFORMAT_1,	0x22},
+	{R367CAB_SMOOTHER_2,	0x28},
+	{R367CAB_TSMF_CTRL_0,	0x01},
+	{R367CAB_TSMF_CTRL_1,	0xc6},
+	{R367CAB_TSMF_CTRL_3,	0x43},
+	{R367CAB_TS_ON_ID_0,	0x00},
+	{R367CAB_TS_ON_ID_1,	0x00},
+	{R367CAB_TS_ON_ID_2,	0x00},
+	{R367CAB_TS_ON_ID_3,	0x00},
+	{R367CAB_RE_STATUS_0,	0x00},
+	{R367CAB_RE_STATUS_1,	0x00},
+	{R367CAB_RE_STATUS_2,	0x00},
+	{R367CAB_RE_STATUS_3,	0x00},
+	{R367CAB_TS_STATUS_0,	0x00},
+	{R367CAB_TS_STATUS_1,	0x00},
+	{R367CAB_TS_STATUS_2,	0xa0},
+	{R367CAB_TS_STATUS_3,	0x00},
+	{R367CAB_T_O_ID_0,	0x00},
+	{R367CAB_T_O_ID_1,	0x00},
+	{R367CAB_T_O_ID_2,	0x00},
+	{R367CAB_T_O_ID_3,	0x00},
+};
+
+static
+int stv0367_writeregs(struct stv0367_state *state, u16 reg, u8 *data, int len)
+{
+	u8 buf[len + 2];
+	struct i2c_msg msg = {
+		.addr = state->config->demod_address,
+		.flags = 0,
+		.buf = buf,
+		.len = len + 2
+	};
+	int ret;
+
+	buf[0] = MSB(reg);
+	buf[1] = LSB(reg);
+	memcpy(buf + 2, data, len);
+
+	if (i2cdebug)
+		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, buf[2]);
+
+	ret = i2c_transfer(state->i2c, &msg, 1);
+	if (ret != 1)
+		printk(KERN_ERR "%s: i2c write error!\n", __func__);
+
+	return (ret != 1) ? -EREMOTEIO : 0;
+}
+
+static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
+{
+	return stv0367_writeregs(state, reg, &data, 1);
+}
+
+static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
+{
+	u8 b0[] = { 0, 0 };
+	u8 b1[] = { 0 };
+	struct i2c_msg msg[] = {
+		{
+			.addr = state->config->demod_address,
+			.flags = 0,
+			.buf = b0,
+			.len = 2
+		}, {
+			.addr = state->config->demod_address,
+			.flags = I2C_M_RD,
+			.buf = b1,
+			.len = 1
+		}
+	};
+	int ret;
+
+	b0[0] = MSB(reg);
+	b0[1] = LSB(reg);
+
+	ret = i2c_transfer(state->i2c, msg, 2);
+	if (ret != 2)
+		printk(KERN_ERR "%s: i2c read error\n", __func__);
+
+	if (i2cdebug)
+		printk(KERN_DEBUG "%s: %02x: %02x\n", __func__, reg, b1[0]);
+
+	return b1[0];
+}
+
+static void extract_mask_pos(u32 label, u8 *mask, u8 *pos)
+{
+	u8 position = 0, i = 0;
+
+	(*mask) = label & 0xff;
+
+	while ((position == 0) && (i < 8)) {
+		position = ((*mask) >> i) & 0x01;
+		i++;
+	}
+
+	(*pos) = (i - 1);
+}
+
+static void stv0367_writebits(struct stv0367_state *state, u32 label, u8 val)
+{
+	u8 reg, mask, pos;
+
+	reg = stv0367_readreg(state, (label >> 16) & 0xffff);
+	extract_mask_pos(label, &mask, &pos);
+
+	val = mask & (val << pos);
+
+	reg = (reg & (~mask)) | val;
+	stv0367_writereg(state, (label >> 16) & 0xffff, reg);
+
+}
+
+static void stv0367_setbits(u8 *reg, u32 label, u8 val)
+{
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	val = mask & (val << pos);
+
+	(*reg) = ((*reg) & (~mask)) | val;
+}
+
+static u8 stv0367_readbits(struct stv0367_state *state, u32 label)
+{
+	u8 val = 0xff;
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	val = stv0367_readreg(state, label >> 16);
+	val = (val & mask) >> pos;
+
+	return val;
+}
+
+u8 stv0367_getbits(u8 reg, u32 label)
+{
+	u8 mask, pos;
+
+	extract_mask_pos(label, &mask, &pos);
+
+	return (reg & mask) >> pos;
+}
+
+static int stv0367ter_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u8 tmp = stv0367_readreg(state, R367TER_I2CRPT);
+
+	dprintk("%s:\n", __func__);
+
+	if (enable) {
+		stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 0);
+		stv0367_setbits(&tmp, F367TER_I2CT_ON, 1);
+	} else {
+		stv0367_setbits(&tmp, F367TER_STOP_ENABLE, 1);
+		stv0367_setbits(&tmp, F367TER_I2CT_ON, 0);
+	}
+
+	stv0367_writereg(state, R367TER_I2CRPT, tmp);
+
+	return 0;
+}
+
+static u32 stv0367_get_tuner_freq(struct dvb_frontend *fe)
+{
+	struct dvb_frontend_ops	*frontend_ops = NULL;
+	struct dvb_tuner_ops	*tuner_ops = NULL;
+	u32 freq = 0;
+	int err = 0;
+
+	dprintk("%s:\n", __func__);
+
+
+	if (&fe->ops)
+		frontend_ops = &fe->ops;
+	if (&frontend_ops->tuner_ops)
+		tuner_ops = &frontend_ops->tuner_ops;
+	if (tuner_ops->get_frequency) {
+		err = tuner_ops->get_frequency(fe, &freq);
+		if (err < 0) {
+			printk(KERN_ERR "%s: Invalid parameter\n", __func__);
+			return err;
+		}
+
+		dprintk("%s: frequency=%d\n", __func__, freq);
+
+	} else
+		return -1;
+
+	return freq;
+}
+
+static u16 CellsCoeffs_8MHz_367cofdm[3][6][5] = {
+	{
+		{0x10EF, 0xE205, 0x10EF, 0xCE49, 0x6DA7}, /* CELL 1 COEFFS 27M*/
+		{0x2151, 0xc557, 0x2151, 0xc705, 0x6f93}, /* CELL 2 COEFFS */
+		{0x2503, 0xc000, 0x2503, 0xc375, 0x7194}, /* CELL 3 COEFFS */
+		{0x20E9, 0xca94, 0x20e9, 0xc153, 0x7194}, /* CELL 4 COEFFS */
+		{0x06EF, 0xF852, 0x06EF, 0xC057, 0x7207}, /* CELL 5 COEFFS */
+		{0x0000, 0x0ECC, 0x0ECC, 0x0000, 0x3647} /* CELL 6 COEFFS */
+	}, {
+		{0x10A0, 0xE2AF, 0x10A1, 0xCE76, 0x6D6D}, /* CELL 1 COEFFS 25M*/
+		{0x20DC, 0xC676, 0x20D9, 0xC80A, 0x6F29},
+		{0x2532, 0xC000, 0x251D, 0xC391, 0x706F},
+		{0x1F7A, 0xCD2B, 0x2032, 0xC15E, 0x711F},
+		{0x0698, 0xFA5E, 0x0568, 0xC059, 0x7193},
+		{0x0000, 0x0918, 0x149C, 0x0000, 0x3642} /* CELL 6 COEFFS */
+	}, {
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
+	}
+};
+
+static u16 CellsCoeffs_7MHz_367cofdm[3][6][5] = {
+	{
+		{0x12CA, 0xDDAF, 0x12CA, 0xCCEB, 0x6FB1}, /* CELL 1 COEFFS 27M*/
+		{0x2329, 0xC000, 0x2329, 0xC6B0, 0x725F}, /* CELL 2 COEFFS */
+		{0x2394, 0xC000, 0x2394, 0xC2C7, 0x7410}, /* CELL 3 COEFFS */
+		{0x251C, 0xC000, 0x251C, 0xC103, 0x74D9}, /* CELL 4 COEFFS */
+		{0x0804, 0xF546, 0x0804, 0xC040, 0x7544}, /* CELL 5 COEFFS */
+		{0x0000, 0x0CD9, 0x0CD9, 0x0000, 0x370A} /* CELL 6 COEFFS */
+	}, {
+		{0x1285, 0xDE47, 0x1285, 0xCD17, 0x6F76}, /*25M*/
+		{0x234C, 0xC000, 0x2348, 0xC6DA, 0x7206},
+		{0x23B4, 0xC000, 0x23AC, 0xC2DB, 0x73B3},
+		{0x253D, 0xC000, 0x25B6, 0xC10B, 0x747F},
+		{0x0721, 0xF79C, 0x065F, 0xC041, 0x74EB},
+		{0x0000, 0x08FA, 0x1162, 0x0000, 0x36FF}
+	}, {
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
+	}
+};
+
+static u16 CellsCoeffs_6MHz_367cofdm[3][6][5] = {
+	{
+		{0x1699, 0xD5B8, 0x1699, 0xCBC3, 0x713B}, /* CELL 1 COEFFS 27M*/
+		{0x2245, 0xC000, 0x2245, 0xC568, 0x74D5}, /* CELL 2 COEFFS */
+		{0x227F, 0xC000, 0x227F, 0xC1FC, 0x76C6}, /* CELL 3 COEFFS */
+		{0x235E, 0xC000, 0x235E, 0xC0A7, 0x778A}, /* CELL 4 COEFFS */
+		{0x0ECB, 0xEA0B, 0x0ECB, 0xC027, 0x77DD}, /* CELL 5 COEFFS */
+		{0x0000, 0x0B68, 0x0B68, 0x0000, 0xC89A}, /* CELL 6 COEFFS */
+	}, {
+		{0x1655, 0xD64E, 0x1658, 0xCBEF, 0x70FE}, /*25M*/
+		{0x225E, 0xC000, 0x2256, 0xC589, 0x7489},
+		{0x2293, 0xC000, 0x2295, 0xC209, 0x767E},
+		{0x2377, 0xC000, 0x23AA, 0xC0AB, 0x7746},
+		{0x0DC7, 0xEBC8, 0x0D07, 0xC027, 0x7799},
+		{0x0000, 0x0888, 0x0E9C, 0x0000, 0x3757}
+
+	}, {
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}, /* 30M */
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000},
+		{0x0000, 0x0000, 0x0000, 0x0000, 0x0000}
+	}
+};
+
+static u32 stv0367ter_get_mclk(struct stv0367_state *state, u32 ExtClk_Hz)
+{
+	u32 mclk_Hz = 0; /* master clock frequency (Hz) */
+	u32 m, n, p;
+
+	dprintk("%s:\n", __func__);
+
+	if (stv0367_readbits(state, F367TER_BYPASS_PLLXN) == 0) {
+		n = (u32)stv0367_readbits(state, F367TER_PLL_NDIV);
+		if (n == 0)
+			n = n + 1;
+
+		m = (u32)stv0367_readbits(state, F367TER_PLL_MDIV);
+		if (m == 0)
+			m = m + 1;
+
+		p = (u32)stv0367_readbits(state, F367TER_PLL_PDIV);
+		if (p > 5)
+			p = 5;
+
+		mclk_Hz = ((ExtClk_Hz / 2) * n) / (m * (1 << p));
+
+		dprintk("N=%d M=%d P=%d mclk_Hz=%d ExtClk_Hz=%d\n",
+				n, m, p, mclk_Hz, ExtClk_Hz);
+	} else
+		mclk_Hz = ExtClk_Hz;
+
+	dprintk("%s: mclk_Hz=%d\n", __func__, mclk_Hz);
+
+	return mclk_Hz;
+}
+
+static int stv0367ter_filt_coeff_init(struct stv0367_state *state,
+				u16 CellsCoeffs[3][6][5], u32 DemodXtal)
+{
+	int i, j, k, freq;
+
+	dprintk("%s:\n", __func__);
+
+	freq = stv0367ter_get_mclk(state, DemodXtal);
+
+	if (freq == 53125000)
+		k = 1; /* equivalent to Xtal 25M on 362*/
+	else if (freq == 54000000)
+		k = 0; /* equivalent to Xtal 27M on 362*/
+	else if (freq == 52500000)
+		k = 2; /* equivalent to Xtal 30M on 362*/
+	else
+		return 0;
+
+	for (i = 1; i <= 6; i++) {
+		stv0367_writebits(state, F367TER_IIR_CELL_NB, i - 1);
+
+		for (j = 1; j <= 5; j++) {
+			stv0367_writereg(state,
+				(R367TER_IIRCX_COEFF1_MSB + 2 * (j - 1)),
+				MSB(CellsCoeffs[k][i-1][j-1]));
+			stv0367_writereg(state,
+				(R367TER_IIRCX_COEFF1_LSB + 2 * (j - 1)),
+				LSB(CellsCoeffs[k][i-1][j-1]));
+		}
+	}
+
+	return 1;
+
+}
+
+static void stv0367ter_agc_iir_lock_detect_set(struct stv0367_state *state)
+{
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367TER_LOCK_DETECT_LSB, 0x00);
+
+	/* Lock detect 1 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x00);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04);
+
+	/* Lock detect 2 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x01);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x06);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x04);
+
+	/* Lock detect 3 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x02);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00);
+
+	/* Lock detect 4 */
+	stv0367_writebits(state, F367TER_LOCK_DETECT_CHOICE, 0x03);
+	stv0367_writebits(state, F367TER_LOCK_DETECT_MSB, 0x01);
+	stv0367_writebits(state, F367TER_AUT_AGC_TARGET_LSB, 0x00);
+
+}
+
+static int stv0367_iir_filt_init(struct stv0367_state *state, u8 Bandwidth,
+							u32 DemodXtalValue)
+{
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367TER_NRST_IIR, 0);
+
+	switch (Bandwidth) {
+	case 6:
+		if (!stv0367ter_filt_coeff_init(state,
+				CellsCoeffs_6MHz_367cofdm,
+				DemodXtalValue))
+			return 0;
+		break;
+	case 7:
+		if (!stv0367ter_filt_coeff_init(state,
+				CellsCoeffs_7MHz_367cofdm,
+				DemodXtalValue))
+			return 0;
+		break;
+	case 8:
+		if (!stv0367ter_filt_coeff_init(state,
+				CellsCoeffs_8MHz_367cofdm,
+				DemodXtalValue))
+			return 0;
+		break;
+	default:
+		return 0;
+	}
+
+	stv0367_writebits(state, F367TER_NRST_IIR, 1);
+
+	return 1;
+}
+
+static void stv0367ter_agc_iir_rst(struct stv0367_state *state)
+{
+
+	u8 com_n;
+
+	dprintk("%s:\n", __func__);
+
+	com_n = stv0367_readbits(state, F367TER_COM_N);
+
+	stv0367_writebits(state, F367TER_COM_N, 0x07);
+
+	stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x00);
+	stv0367_writebits(state, F367TER_COM_AGC_ON, 0x00);
+
+	stv0367_writebits(state, F367TER_COM_SOFT_RSTN, 0x01);
+	stv0367_writebits(state, F367TER_COM_AGC_ON, 0x01);
+
+	stv0367_writebits(state, F367TER_COM_N, com_n);
+
+}
+
+static int stv0367ter_duration(s32 mode, int tempo1, int tempo2, int tempo3)
+{
+	int local_tempo = 0;
+	switch (mode) {
+	case 0:
+		local_tempo = tempo1;
+		break;
+	case 1:
+		local_tempo = tempo2;
+		break ;
+
+	case 2:
+		local_tempo = tempo3;
+		break;
+
+	default:
+		break;
+	}
+	/*	msleep(local_tempo);  */
+	return local_tempo;
+}
+
+static enum
+stv0367_ter_signal_type stv0367ter_check_syr(struct stv0367_state *state)
+{
+	int wd = 100;
+	unsigned short int SYR_var;
+	s32 SYRStatus;
+
+	dprintk("%s:\n", __func__);
+
+	SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK);
+
+	while ((!SYR_var) && (wd > 0)) {
+		usleep_range(2000, 3000);
+		wd -= 2;
+		SYR_var = stv0367_readbits(state, F367TER_SYR_LOCK);
+	}
+
+	if (!SYR_var)
+		SYRStatus = FE_TER_NOSYMBOL;
+	else
+		SYRStatus =  FE_TER_SYMBOLOK;
+
+	dprintk("stv0367ter_check_syr SYRStatus %s\n",
+				SYR_var == 0 ? "No Symbol" : "OK");
+
+	return SYRStatus;
+}
+
+static enum
+stv0367_ter_signal_type stv0367ter_check_cpamp(struct stv0367_state *state,
+								s32 FFTmode)
+{
+
+	s32  CPAMPvalue = 0, CPAMPStatus, CPAMPMin;
+	int wd = 0;
+
+	dprintk("%s:\n", __func__);
+
+	switch (FFTmode) {
+	case 0: /*2k mode*/
+		CPAMPMin = 20;
+		wd = 10;
+		break;
+	case 1: /*8k mode*/
+		CPAMPMin = 80;
+		wd = 55;
+		break;
+	case 2: /*4k mode*/
+		CPAMPMin = 40;
+		wd = 30;
+		break;
+	default:
+		CPAMPMin = 0xffff;  /*drives to NOCPAMP	*/
+		break;
+	}
+
+	dprintk("%s: CPAMPMin=%d wd=%d\n", __func__, CPAMPMin, wd);
+
+	CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT);
+	while ((CPAMPvalue < CPAMPMin) && (wd > 0)) {
+		usleep_range(1000, 2000);
+		wd -= 1;
+		CPAMPvalue = stv0367_readbits(state, F367TER_PPM_CPAMP_DIRECT);
+		/*dprintk("CPAMPvalue= %d at wd=%d\n",CPAMPvalue,wd); */
+	}
+	dprintk("******last CPAMPvalue= %d at wd=%d\n", CPAMPvalue, wd);
+	if (CPAMPvalue < CPAMPMin) {
+		CPAMPStatus = FE_TER_NOCPAMP;
+		printk(KERN_ERR "CPAMP failed\n");
+	} else {
+		printk(KERN_ERR "CPAMP OK !\n");
+		CPAMPStatus = FE_TER_CPAMPOK;
+	}
+
+	return CPAMPStatus;
+}
+
+enum
+stv0367_ter_signal_type stv0367ter_lock_algo(struct stv0367_state *state)
+{
+	enum stv0367_ter_signal_type ret_flag;
+	short int wd, tempo;
+	u8 try, u_var1 = 0, u_var2 = 0, u_var3 = 0, u_var4 = 0, mode, guard;
+	u8 tmp, tmp2;
+
+	dprintk("%s:\n", __func__);
+
+	if (state == NULL)
+		return FE_TER_SWNOK;
+
+	try = 0;
+	do {
+		ret_flag = FE_TER_LOCKOK;
+
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+
+		if (state->config->if_iq_mode != 0)
+			stv0367_writebits(state, F367TER_COM_N, 0x07);
+
+		stv0367_writebits(state, F367TER_GUARD, 3);/* suggest 2k 1/4 */
+		stv0367_writebits(state, F367TER_MODE, 0);
+		stv0367_writebits(state, F367TER_SYR_TR_DIS, 0);
+		usleep_range(5000, 10000);
+
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+
+
+		if (stv0367ter_check_syr(state) == FE_TER_NOSYMBOL)
+			return FE_TER_NOSYMBOL;
+		else { /*
+			if chip locked on wrong mode first try,
+			it must lock correctly second try */
+			mode = stv0367_readbits(state, F367TER_SYR_MODE);
+			if (stv0367ter_check_cpamp(state, mode) ==
+							FE_TER_NOCPAMP) {
+				if (try == 0)
+					ret_flag = FE_TER_NOCPAMP;
+
+			}
+		}
+
+		try++;
+	} while ((try < 10) && (ret_flag != FE_TER_LOCKOK));
+
+	tmp  = stv0367_readreg(state, R367TER_SYR_STAT);
+	tmp2 = stv0367_readreg(state, R367TER_STATUS);
+	dprintk("state=%p\n", state);
+	dprintk("LOCK OK! mode=%d SYR_STAT=0x%x R367TER_STATUS=0x%x\n",
+							mode, tmp, tmp2);
+
+	tmp  = stv0367_readreg(state, R367TER_PRVIT);
+	tmp2 = stv0367_readreg(state, R367TER_I2CRPT);
+	dprintk("PRVIT=0x%x I2CRPT=0x%x\n", tmp, tmp2);
+
+	tmp  = stv0367_readreg(state, R367TER_GAIN_SRC1);
+	dprintk("GAIN_SRC1=0x%x\n", tmp);
+
+	if ((mode != 0) && (mode != 1) && (mode != 2))
+		return FE_TER_SWNOK;
+
+	/*guard=stv0367_readbits(state,F367TER_SYR_GUARD); */
+
+	/*suppress EPQ auto for SYR_GARD 1/16 or 1/32
+	and set channel predictor in automatic */
+#if 0
+	switch (guard) {
+
+	case 0:
+	case 1:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 0);
+		stv0367_writereg(state, R367TER_CHC_CTL, 0x01);
+		break;
+	case 2:
+	case 3:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 1);
+		stv0367_writereg(state, R367TER_CHC_CTL, 0x11);
+		break;
+
+	default:
+		return FE_TER_SWNOK;
+	}
+#endif
+
+	/*reset fec an reedsolo FOR 367 only*/
+	stv0367_writebits(state, F367TER_RST_SFEC, 1);
+	stv0367_writebits(state, F367TER_RST_REEDSOLO, 1);
+	usleep_range(1000, 2000);
+	stv0367_writebits(state, F367TER_RST_SFEC, 0);
+	stv0367_writebits(state, F367TER_RST_REEDSOLO, 0);
+
+	u_var1 = stv0367_readbits(state, F367TER_LK);
+	u_var2 = stv0367_readbits(state, F367TER_PRF);
+	u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK);
+	/*	u_var4=stv0367_readbits(state,F367TER_TSFIFO_LINEOK); */
+
+	wd = stv0367ter_duration(mode, 125, 500, 250);
+	tempo = stv0367ter_duration(mode, 4, 16, 8);
+
+	/*while ( ((!u_var1)||(!u_var2)||(!u_var3)||(!u_var4))  && (wd>=0)) */
+	while (((!u_var1) || (!u_var2) || (!u_var3)) && (wd >= 0)) {
+		usleep_range(1000 * tempo, 1000 * (tempo + 1));
+		wd -= tempo;
+		u_var1 = stv0367_readbits(state, F367TER_LK);
+		u_var2 = stv0367_readbits(state, F367TER_PRF);
+		u_var3 = stv0367_readbits(state, F367TER_TPS_LOCK);
+		/*u_var4=stv0367_readbits(state, F367TER_TSFIFO_LINEOK); */
+	}
+
+	if (!u_var1)
+		return FE_TER_NOLOCK;
+
+
+	if (!u_var2)
+		return FE_TER_NOPRFOUND;
+
+	if (!u_var3)
+		return FE_TER_NOTPS;
+
+	guard = stv0367_readbits(state, F367TER_SYR_GUARD);
+	stv0367_writereg(state, R367TER_CHC_CTL, 0x11);
+	switch (guard) {
+	case 0:
+	case 1:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 0);
+		/*stv0367_writereg(state,R367TER_CHC_CTL, 0x1);*/
+		stv0367_writebits(state, F367TER_SYR_FILTER, 0);
+		break;
+	case 2:
+	case 3:
+		stv0367_writebits(state, F367TER_AUTO_LE_EN, 1);
+		/*stv0367_writereg(state,R367TER_CHC_CTL, 0x11);*/
+		stv0367_writebits(state, F367TER_SYR_FILTER, 1);
+		break;
+
+	default:
+		return FE_TER_SWNOK;
+	}
+
+	/* apply Sfec workaround if 8K 64QAM CR!=1/2*/
+	if ((stv0367_readbits(state, F367TER_TPS_CONST) == 2) &&
+			(mode == 1) &&
+			(stv0367_readbits(state, F367TER_TPS_HPCODE) != 0)) {
+		stv0367_writereg(state, R367TER_SFDLYSETH, 0xc0);
+		stv0367_writereg(state, R367TER_SFDLYSETM, 0x60);
+		stv0367_writereg(state, R367TER_SFDLYSETL, 0x0);
+	} else
+		stv0367_writereg(state, R367TER_SFDLYSETH, 0x0);
+
+	wd = stv0367ter_duration(mode, 125, 500, 250);
+	u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK);
+
+	while ((!u_var4) && (wd >= 0)) {
+		usleep_range(1000 * tempo, 1000 * (tempo + 1));
+		wd -= tempo;
+		u_var4 = stv0367_readbits(state, F367TER_TSFIFO_LINEOK);
+	}
+
+	if (!u_var4)
+		return FE_TER_NOLOCK;
+
+	/* for 367 leave COM_N at 0x7 for IQ_mode*/
+	/*if(ter_state->if_iq_mode!=FE_TER_NORMAL_IF_TUNER) {
+		tempo=0;
+		while ((stv0367_readbits(state,F367TER_COM_USEGAINTRK)!=1) &&
+		(stv0367_readbits(state,F367TER_COM_AGCLOCK)!=1)&&(tempo<100)) {
+			ChipWaitOrAbort(state,1);
+			tempo+=1;
+		}
+
+		stv0367_writebits(state,F367TER_COM_N,0x17);
+	} */
+
+	stv0367_writebits(state, F367TER_SYR_TR_DIS, 1);
+
+	dprintk("FE_TER_LOCKOK !!!\n");
+
+	return	FE_TER_LOCKOK;
+
+}
+
+static void stv0367ter_set_ts_mode(struct stv0367_state *state,
+					enum stv0367_ts_mode PathTS)
+{
+
+	dprintk("%s:\n", __func__);
+
+	if (state == NULL)
+		return;
+
+	stv0367_writebits(state, F367TER_TS_DIS, 0);
+	switch (PathTS) {
+	default:
+		/*for removing warning :default we can assume in parallel mode*/
+	case STV0367_PARALLEL_PUNCT_CLOCK:
+		stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 0);
+		stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 0);
+		break;
+	case STV0367_SERIAL_PUNCT_CLOCK:
+		stv0367_writebits(state, F367TER_TSFIFO_SERIAL, 1);
+		stv0367_writebits(state, F367TER_TSFIFO_DVBCI, 1);
+		break;
+	}
+}
+
+static void stv0367ter_set_clk_pol(struct stv0367_state *state,
+					enum stv0367_clk_pol clock)
+{
+
+	dprintk("%s:\n", __func__);
+
+	if (state == NULL)
+		return;
+
+	switch (clock) {
+	case STV0367_RISINGEDGE_CLOCK:
+		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 1);
+		break;
+	case STV0367_FALLINGEDGE_CLOCK:
+		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0);
+		break;
+		/*case FE_TER_CLOCK_POLARITY_DEFAULT:*/
+	default:
+		stv0367_writebits(state, F367TER_TS_BYTE_CLK_INV, 0);
+		break;
+	}
+}
+
+#if 0
+static void stv0367ter_core_sw(struct stv0367_state *state)
+{
+
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+	stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+	msleep(350);
+}
+#endif
+static int stv0367ter_standby(struct dvb_frontend *fe, u8 standby_on)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	if (standby_on) {
+		stv0367_writebits(state, F367TER_STDBY, 1);
+		stv0367_writebits(state, F367TER_STDBY_FEC, 1);
+		stv0367_writebits(state, F367TER_STDBY_CORE, 1);
+	} else {
+		stv0367_writebits(state, F367TER_STDBY, 0);
+		stv0367_writebits(state, F367TER_STDBY_FEC, 0);
+		stv0367_writebits(state, F367TER_STDBY_CORE, 0);
+	}
+
+	return 0;
+}
+
+static int stv0367ter_sleep(struct dvb_frontend *fe)
+{
+	return stv0367ter_standby(fe, 1);
+}
+
+int stv0367ter_init(struct dvb_frontend *fe)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	int i;
+
+	dprintk("%s:\n", __func__);
+
+	ter_state->pBER = 0;
+
+	for (i = 0; i < STV0367TER_NBREGS; i++)
+		stv0367_writereg(state, def0367ter[i].addr,
+					def0367ter[i].value);
+
+	switch (state->config->xtal) {
+		/*set internal freq to 53.125MHz */
+	case 25000000:
+		stv0367_writereg(state, R367TER_PLLMDIV, 0xa);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
+	default:
+	case 27000000:
+		dprintk("FE_STV0367TER_SetCLKgen for 27Mhz\n");
+		stv0367_writereg(state, R367TER_PLLMDIV, 0x1);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x8);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
+	case 30000000:
+		stv0367_writereg(state, R367TER_PLLMDIV, 0xc);
+		stv0367_writereg(state, R367TER_PLLNDIV, 0x55);
+		stv0367_writereg(state, R367TER_PLLSETUP, 0x18);
+		break;
+	}
+
+	stv0367_writereg(state, R367TER_I2CRPT, 0xa0);
+	stv0367_writereg(state, R367TER_ANACTRL, 0x00);
+
+	/*Set TS1 and TS2 to serial or parallel mode */
+	stv0367ter_set_ts_mode(state, state->config->ts_mode);
+	stv0367ter_set_clk_pol(state, state->config->clk_pol);
+
+	state->chip_id = stv0367_readreg(state, R367TER_ID);
+	ter_state->first_lock = 0;
+	ter_state->unlock_counter = 2;
+
+	return 0;
+}
+
+static int stv0367ter_algo(struct dvb_frontend *fe,
+				struct dvb_frontend_parameters *param)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	int offset = 0, tempo = 0;
+	u8 u_var;
+	u8 /*constell,*/ counter, tps_rcvd[2];
+	s8 step;
+	s32 timing_offset = 0;
+	u32 trl_nomrate = 0, InternalFreq = 0, temp = 0;
+
+	dprintk("%s:\n", __func__);
+
+	ter_state->frequency = param->frequency;
+	ter_state->force = FE_TER_FORCENONE
+			+ stv0367_readbits(state, F367TER_FORCE) * 2;
+	ter_state->if_iq_mode = state->config->if_iq_mode;
+	switch (state->config->if_iq_mode) {
+	case FE_TER_NORMAL_IF_TUNER:  /* Normal IF mode */
+		dprintk("ALGO: FE_TER_NORMAL_IF_TUNER selected\n");
+		stv0367_writebits(state, F367TER_TUNER_BB, 0);
+		stv0367_writebits(state, F367TER_LONGPATH_IF, 0);
+		stv0367_writebits(state, F367TER_DEMUX_SWAP, 0);
+		break;
+	case FE_TER_LONGPATH_IF_TUNER:  /* Long IF mode */
+		dprintk("ALGO: FE_TER_LONGPATH_IF_TUNER selected\n");
+		stv0367_writebits(state, F367TER_TUNER_BB, 0);
+		stv0367_writebits(state, F367TER_LONGPATH_IF, 1);
+		stv0367_writebits(state, F367TER_DEMUX_SWAP, 1);
+		break;
+	case FE_TER_IQ_TUNER:  /* IQ mode */
+		dprintk("ALGO: FE_TER_IQ_TUNER selected\n");
+		stv0367_writebits(state, F367TER_TUNER_BB, 1);
+		stv0367_writebits(state, F367TER_PPM_INVSEL, 0);
+		break;
+	default:
+		printk(KERN_ERR "ALGO: wrong TUNER type selected\n");
+		return -EINVAL;
+	}
+
+	usleep_range(5000, 7000);
+
+	switch (param->inversion) {
+	case INVERSION_AUTO:
+	default:
+		dprintk("%s: inversion AUTO\n", __func__);
+		if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
+			stv0367_writebits(state, F367TER_IQ_INVERT,
+						ter_state->sense);
+		else
+			stv0367_writebits(state, F367TER_INV_SPECTR,
+						ter_state->sense);
+
+		break;
+	case INVERSION_ON:
+	case INVERSION_OFF:
+		if (ter_state->if_iq_mode == FE_TER_IQ_TUNER)
+			stv0367_writebits(state, F367TER_IQ_INVERT,
+						param->inversion);
+		else
+			stv0367_writebits(state, F367TER_INV_SPECTR,
+						param->inversion);
+
+		break;
+	}
+
+	if ((ter_state->if_iq_mode != FE_TER_NORMAL_IF_TUNER) &&
+				(ter_state->pBW != ter_state->bw)) {
+		stv0367ter_agc_iir_lock_detect_set(state);
+
+		/*set fine agc target to 180 for LPIF or IQ mode*/
+		/* set Q_AGCTarget */
+		stv0367_writebits(state, F367TER_SEL_IQNTAR, 1);
+		stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB);
+		/*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */
+
+		/* set Q_AGCTarget */
+		stv0367_writebits(state, F367TER_SEL_IQNTAR, 0);
+		stv0367_writebits(state, F367TER_AUT_AGC_TARGET_MSB, 0xB);
+		/*stv0367_writebits(state,AUT_AGC_TARGET_LSB,0x04); */
+
+		if (!stv0367_iir_filt_init(state, ter_state->bw,
+						state->config->xtal))
+			return -EINVAL;
+		/*set IIR filter once for 6,7 or 8MHz BW*/
+		ter_state->pBW = ter_state->bw;
+
+		stv0367ter_agc_iir_rst(state);
+	}
+
+	if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO)
+		stv0367_writebits(state, F367TER_BDI_LPSEL, 0x01);
+	else
+		stv0367_writebits(state, F367TER_BDI_LPSEL, 0x00);
+
+	InternalFreq = stv0367ter_get_mclk(state, state->config->xtal) / 1000;
+	temp = (int)
+		((((ter_state->bw * 64 * (1 << 15) * 100)
+						/ (InternalFreq)) * 10) / 7);
+
+	stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB, temp % 2);
+	temp = temp / 2;
+	stv0367_writebits(state, F367TER_TRL_NOMRATE_HI, temp / 256);
+	stv0367_writebits(state, F367TER_TRL_NOMRATE_LO, temp % 256);
+
+	temp = stv0367_readbits(state, F367TER_TRL_NOMRATE_HI) * 512 +
+			stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2 +
+			stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB);
+	temp = (int)(((1 << 17) * ter_state->bw * 1000) / (7 * (InternalFreq)));
+	stv0367_writebits(state, F367TER_GAIN_SRC_HI, temp / 256);
+	stv0367_writebits(state, F367TER_GAIN_SRC_LO, temp % 256);
+	temp = stv0367_readbits(state, F367TER_GAIN_SRC_HI) * 256 +
+			stv0367_readbits(state, F367TER_GAIN_SRC_LO);
+
+	temp = (int)
+		((InternalFreq - state->config->if_khz) * (1 << 16)
+							/ (InternalFreq));
+
+	dprintk("DEROT temp=0x%x\n", temp);
+	stv0367_writebits(state, F367TER_INC_DEROT_HI, temp / 256);
+	stv0367_writebits(state, F367TER_INC_DEROT_LO, temp % 256);
+
+	ter_state->echo_pos = 0;
+	ter_state->ucblocks = 0; /* liplianin */
+	ter_state->pBER = 0; /* liplianin */
+	stv0367_writebits(state, F367TER_LONG_ECHO, ter_state->echo_pos);
+
+	if (stv0367ter_lock_algo(state) != FE_TER_LOCKOK)
+		return 0;
+
+	ter_state->state = FE_TER_LOCKOK;
+	/* update results */
+	tps_rcvd[0] = stv0367_readreg(state, R367TER_TPS_RCVD2);
+	tps_rcvd[1] = stv0367_readreg(state, R367TER_TPS_RCVD3);
+
+	ter_state->mode = stv0367_readbits(state, F367TER_SYR_MODE);
+	ter_state->guard = stv0367_readbits(state, F367TER_SYR_GUARD);
+
+	ter_state->first_lock = 1; /* we know sense now :) */
+
+	ter_state->agc_val =
+			(stv0367_readbits(state, F367TER_AGC1_VAL_LO) << 16) +
+			(stv0367_readbits(state, F367TER_AGC1_VAL_HI) << 24) +
+			stv0367_readbits(state, F367TER_AGC2_VAL_LO) +
+			(stv0367_readbits(state, F367TER_AGC2_VAL_HI) << 8);
+
+	/* Carrier offset calculation */
+	stv0367_writebits(state, F367TER_FREEZE, 1);
+	offset = (stv0367_readbits(state, F367TER_CRL_FOFFSET_VHI) << 16) ;
+	offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_HI) << 8);
+	offset += (stv0367_readbits(state, F367TER_CRL_FOFFSET_LO));
+	stv0367_writebits(state, F367TER_FREEZE, 0);
+	if (offset > 8388607)
+		offset -= 16777216;
+
+	offset = offset * 2 / 16384;
+
+	if (ter_state->mode == FE_TER_MODE_2K)
+		offset = (offset * 4464) / 1000;/*** 1 FFT BIN=4.464khz***/
+	else if (ter_state->mode == FE_TER_MODE_4K)
+		offset = (offset * 223) / 100;/*** 1 FFT BIN=2.23khz***/
+	else  if (ter_state->mode == FE_TER_MODE_8K)
+		offset = (offset * 111) / 100;/*** 1 FFT BIN=1.1khz***/
+
+	if (stv0367_readbits(state, F367TER_PPM_INVSEL) == 1) {
+		if ((stv0367_readbits(state, F367TER_INV_SPECTR) ==
+				(stv0367_readbits(state,
+					F367TER_STATUS_INV_SPECRUM) == 1)))
+			offset = offset * -1;
+	}
+
+	if (ter_state->bw == 6)
+		offset = (offset * 6) / 8;
+	else if (ter_state->bw == 7)
+		offset = (offset * 7) / 8;
+
+	ter_state->frequency += offset;
+
+	tempo = 10;  /* exit even if timing_offset stays null */
+	while ((timing_offset == 0) && (tempo > 0)) {
+		usleep_range(10000, 20000);	/*was 20ms  */
+		/* fine tuning of timing offset if required */
+		timing_offset = stv0367_readbits(state, F367TER_TRL_TOFFSET_LO)
+				+ 256 * stv0367_readbits(state,
+							F367TER_TRL_TOFFSET_HI);
+		if (timing_offset >= 32768)
+			timing_offset -= 65536;
+		trl_nomrate = (512 * stv0367_readbits(state,
+							F367TER_TRL_NOMRATE_HI)
+			+ stv0367_readbits(state, F367TER_TRL_NOMRATE_LO) * 2
+			+ stv0367_readbits(state, F367TER_TRL_NOMRATE_LSB));
+
+		timing_offset = ((signed)(1000000 / trl_nomrate) *
+							timing_offset) / 2048;
+		tempo--;
+	}
+
+	if (timing_offset <= 0) {
+		timing_offset = (timing_offset - 11) / 22;
+		step = -1;
+	} else {
+		timing_offset = (timing_offset + 11) / 22;
+		step = 1;
+	}
+
+	for (counter = 0; counter < abs(timing_offset); counter++) {
+		trl_nomrate += step;
+		stv0367_writebits(state, F367TER_TRL_NOMRATE_LSB,
+						trl_nomrate % 2);
+		stv0367_writebits(state, F367TER_TRL_NOMRATE_LO,
+						trl_nomrate / 2);
+		usleep_range(1000, 2000);
+	}
+
+	usleep_range(5000, 6000);
+	/* unlocks could happen in case of trl centring big step,
+	then a core off/on restarts demod */
+	u_var = stv0367_readbits(state, F367TER_LK);
+
+	if (!u_var) {
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+		msleep(20);
+		stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+	}
+
+	return 0;
+}
+
+static int stv0367ter_set_frontend(struct dvb_frontend *fe,
+				struct dvb_frontend_parameters *param)
+{
+	struct dvb_ofdm_parameters *op = &param->u.ofdm;
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+
+	/*u8 trials[2]; */
+	s8 num_trials, index;
+	u8 SenseTrials[] = { INVERSION_ON, INVERSION_OFF };
+
+	stv0367ter_init(fe);
+
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	switch (op->transmission_mode) {
+	default:
+	case TRANSMISSION_MODE_AUTO:
+	case TRANSMISSION_MODE_2K:
+		ter_state->mode = FE_TER_MODE_2K;
+		break;
+/*	case TRANSMISSION_MODE_4K:
+		pLook.mode = FE_TER_MODE_4K;
+		break;*/
+	case TRANSMISSION_MODE_8K:
+		ter_state->mode = FE_TER_MODE_8K;
+		break;
+	}
+
+	switch (op->guard_interval) {
+	default:
+	case GUARD_INTERVAL_1_32:
+	case GUARD_INTERVAL_1_16:
+	case GUARD_INTERVAL_1_8:
+	case GUARD_INTERVAL_1_4:
+		ter_state->guard = op->guard_interval;
+		break;
+	case GUARD_INTERVAL_AUTO:
+		ter_state->guard = GUARD_INTERVAL_1_32;
+		break;
+	}
+
+	switch (op->bandwidth) {
+	case BANDWIDTH_6_MHZ:
+		ter_state->bw = FE_TER_CHAN_BW_6M;
+		break;
+	case BANDWIDTH_7_MHZ:
+		ter_state->bw = FE_TER_CHAN_BW_7M;
+		break;
+	case BANDWIDTH_8_MHZ:
+	default:
+		ter_state->bw = FE_TER_CHAN_BW_8M;
+	}
+
+	ter_state->hierarchy = FE_TER_HIER_NONE;
+
+	switch (param->inversion) {
+	case INVERSION_OFF:
+	case INVERSION_ON:
+		num_trials = 1;
+		break;
+	default:
+		num_trials = 2;
+		if (ter_state->first_lock)
+			num_trials = 1;
+		break;
+	}
+
+	ter_state->state = FE_TER_NOLOCK;
+	index = 0;
+
+	while (((index) < num_trials) && (ter_state->state != FE_TER_LOCKOK)) {
+		if (!ter_state->first_lock) {
+			if (param->inversion == INVERSION_AUTO)
+				ter_state->sense = SenseTrials[index];
+
+		}
+		stv0367ter_algo(fe,/* &pLook, result,*/ param);
+
+		if ((ter_state->state == FE_TER_LOCKOK) &&
+				(param->inversion == INVERSION_AUTO) &&
+								(index == 1)) {
+			/* invert spectrum sense */
+			SenseTrials[index] = SenseTrials[0];
+			SenseTrials[(index + 1) % 2] = (SenseTrials[1] + 1) % 2;
+		}
+
+		index++;
+	}
+
+	return 0;
+}
+
+static int stv0367ter_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	u32 errs = 0;
+
+	/*wait for counting completion*/
+	if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0) {
+		errs =
+			((u32)stv0367_readbits(state, F367TER_ERR_CNT1)
+			* (1 << 16))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI)
+			* (1 << 8))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO));
+		ter_state->ucblocks = errs;
+	}
+
+	(*ucblocks) = ter_state->ucblocks;
+
+	return 0;
+}
+
+static int stv0367ter_get_frontend(struct dvb_frontend *fe,
+				  struct dvb_frontend_parameters *param)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	struct dvb_ofdm_parameters *op = &param->u.ofdm;
+	struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+
+	int error = 0;
+	enum stv0367_ter_mode mode;
+	int constell = 0,/* snr = 0,*/ Data = 0;
+
+	param->frequency = stv0367_get_tuner_freq(fe);
+	if ((int)param->frequency < 0)
+		param->frequency = c->frequency;
+
+	constell = stv0367_readbits(state, F367TER_TPS_CONST);
+	if (constell == 0)
+		op->constellation = QPSK;
+	else if (constell == 1)
+		op->constellation = QAM_16;
+	else
+		op->constellation = QAM_64;
+
+	param->inversion = stv0367_readbits(state, F367TER_INV_SPECTR);
+
+	/* Get the Hierarchical mode */
+	Data = stv0367_readbits(state, F367TER_TPS_HIERMODE);
+
+	switch (Data) {
+	case 0:
+		op->hierarchy_information = HIERARCHY_NONE;
+		break;
+	case 1:
+		op->hierarchy_information = HIERARCHY_1;
+		break;
+	case 2:
+		op->hierarchy_information = HIERARCHY_2;
+		break;
+	case 3:
+		op->hierarchy_information = HIERARCHY_4;
+		break;
+	default:
+		op->hierarchy_information = HIERARCHY_AUTO;
+		break; /* error */
+	}
+
+	/* Get the FEC Rate */
+	if (ter_state->hierarchy == FE_TER_HIER_LOW_PRIO)
+		Data = stv0367_readbits(state, F367TER_TPS_LPCODE);
+	else
+		Data = stv0367_readbits(state, F367TER_TPS_HPCODE);
+
+	switch (Data) {
+	case 0:
+		op->code_rate_HP = FEC_1_2;
+		break;
+	case 1:
+		op->code_rate_HP = FEC_2_3;
+		break;
+	case 2:
+		op->code_rate_HP = FEC_3_4;
+		break;
+	case 3:
+		op->code_rate_HP = FEC_5_6;
+		break;
+	case 4:
+		op->code_rate_HP = FEC_7_8;
+		break;
+	default:
+		op->code_rate_HP = FEC_AUTO;
+		break; /* error */
+	}
+
+	mode = stv0367_readbits(state, F367TER_SYR_MODE);
+
+	switch (mode) {
+	case FE_TER_MODE_2K:
+		op->transmission_mode = TRANSMISSION_MODE_2K;
+		break;
+/*	case FE_TER_MODE_4K:
+		op->transmission_mode = TRANSMISSION_MODE_4K;
+		break;*/
+	case FE_TER_MODE_8K:
+		op->transmission_mode = TRANSMISSION_MODE_8K;
+		break;
+	default:
+		op->transmission_mode = TRANSMISSION_MODE_AUTO;
+	}
+
+	op->guard_interval = stv0367_readbits(state, F367TER_SYR_GUARD);
+
+	return error;
+}
+
+static int stv0367ter_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u32 snru32 = 0;
+	int cpt = 0;
+	u8 cut = stv0367_readbits(state, F367TER_IDENTIFICATIONREG);
+
+	while (cpt < 10) {
+		usleep_range(2000, 3000);
+		if (cut == 0x50) /*cut 1.0 cut 1.1*/
+			snru32 += stv0367_readbits(state, F367TER_CHCSNR) / 4;
+		else /*cu2.0*/
+			snru32 += 125 * stv0367_readbits(state, F367TER_CHCSNR);
+
+		cpt++;
+	}
+
+	snru32 /= 10;/*average on 10 values*/
+
+	*snr = snru32 / 1000;
+
+	return 0;
+}
+
+#if 0
+static int stv0367ter_status(struct dvb_frontend *fe)
+{
+
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	int locked = FALSE;
+
+	locked = (stv0367_readbits(state, F367TER_LK));
+	if (!locked)
+		ter_state->unlock_counter += 1;
+	else
+		ter_state->unlock_counter = 0;
+
+	if (ter_state->unlock_counter > 2) {
+		if (!stv0367_readbits(state, F367TER_TPS_LOCK) ||
+				(!stv0367_readbits(state, F367TER_LK))) {
+			stv0367_writebits(state, F367TER_CORE_ACTIVE, 0);
+			usleep_range(2000, 3000);
+			stv0367_writebits(state, F367TER_CORE_ACTIVE, 1);
+			msleep(350);
+			locked = (stv0367_readbits(state, F367TER_TPS_LOCK)) &&
+					(stv0367_readbits(state, F367TER_LK));
+		}
+
+	}
+
+	return locked;
+}
+#endif
+static int stv0367ter_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	*status = 0;
+
+	if (stv0367_readbits(state, F367TER_LK)) {
+		*status |= FE_HAS_LOCK;
+		dprintk("%s: stv0367 has locked\n", __func__);
+	}
+
+	return 0;
+}
+
+static int stv0367ter_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367ter_state *ter_state = state->ter_state;
+	u32 Errors = 0, tber = 0, temporary = 0;
+	int abc = 0, def = 0;
+
+
+	/*wait for counting completion*/
+	if (stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 0)
+		Errors = ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT)
+			* (1 << 16))
+			+ ((u32)stv0367_readbits(state, F367TER_SFEC_ERR_CNT_HI)
+			* (1 << 8))
+			+ ((u32)stv0367_readbits(state,
+						F367TER_SFEC_ERR_CNT_LO));
+	/*measurement not completed, load previous value*/
+	else {
+		tber = ter_state->pBER;
+		return 0;
+	}
+
+	abc = stv0367_readbits(state, F367TER_SFEC_ERR_SOURCE);
+	def = stv0367_readbits(state, F367TER_SFEC_NUM_EVENT);
+
+	if (Errors == 0) {
+		tber = 0;
+	} else if (abc == 0x7) {
+		if (Errors <= 4) {
+			temporary = (Errors * 1000000000) / (8 * (1 << 14));
+			temporary =  temporary;
+		} else if (Errors <= 42) {
+			temporary = (Errors * 100000000) / (8 * (1 << 14));
+			temporary = temporary * 10;
+		} else if (Errors <= 429) {
+			temporary = (Errors * 10000000) / (8 * (1 << 14));
+			temporary = temporary * 100;
+		} else if (Errors <= 4294) {
+			temporary = (Errors * 1000000) / (8 * (1 << 14));
+			temporary = temporary * 1000;
+		} else if (Errors <= 42949) {
+			temporary = (Errors * 100000) / (8 * (1 << 14));
+			temporary = temporary * 10000;
+		} else if (Errors <= 429496) {
+			temporary = (Errors * 10000) / (8 * (1 << 14));
+			temporary = temporary * 100000;
+		} else { /*if (Errors<4294967) 2^22 max error*/
+			temporary = (Errors * 1000) / (8 * (1 << 14));
+			temporary = temporary * 100000;	/* still to *10 */
+		}
+
+		/* Byte error*/
+		if (def == 2)
+			/*tber=Errors/(8*(1 <<14));*/
+			tber = temporary;
+		else if (def == 3)
+			/*tber=Errors/(8*(1 <<16));*/
+			tber = temporary / 4;
+		else if (def == 4)
+			/*tber=Errors/(8*(1 <<18));*/
+			tber = temporary / 16;
+		else if (def == 5)
+			/*tber=Errors/(8*(1 <<20));*/
+			tber = temporary / 64;
+		else if (def == 6)
+			/*tber=Errors/(8*(1 <<22));*/
+			tber = temporary / 256;
+		else
+			/* should not pass here*/
+			tber = 0;
+
+		if ((Errors < 4294967) && (Errors > 429496))
+			tber *= 10;
+
+	}
+
+	/* save actual value */
+	ter_state->pBER = tber;
+
+	(*ber) = tber;
+
+	return 0;
+}
+#if 0
+static u32 stv0367ter_get_per(struct stv0367_state *state)
+{
+	struct stv0367ter_state *ter_state = state->ter_state;
+	u32 Errors = 0, Per = 0, temporary = 0;
+	int abc = 0, def = 0, cpt = 0;
+
+	while (((stv0367_readbits(state, F367TER_SFERRC_OLDVALUE) == 1) &&
+			(cpt < 400)) || ((Errors == 0) && (cpt < 400))) {
+		usleep_range(1000, 2000);
+		Errors = ((u32)stv0367_readbits(state, F367TER_ERR_CNT1)
+			* (1 << 16))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_HI)
+			* (1 << 8))
+			+ ((u32)stv0367_readbits(state, F367TER_ERR_CNT1_LO));
+		cpt++;
+	}
+	abc = stv0367_readbits(state, F367TER_ERR_SRC1);
+	def = stv0367_readbits(state, F367TER_NUM_EVT1);
+
+	if (Errors == 0)
+		Per = 0;
+	else if (abc == 0x9) {
+		if (Errors <= 4) {
+			temporary = (Errors * 1000000000) / (8 * (1 << 8));
+			temporary =  temporary;
+		} else if (Errors <= 42) {
+			temporary = (Errors * 100000000) / (8 * (1 << 8));
+			temporary = temporary * 10;
+		} else if (Errors <= 429) {
+			temporary = (Errors * 10000000) / (8 * (1 << 8));
+			temporary = temporary * 100;
+		} else if (Errors <= 4294) {
+			temporary = (Errors * 1000000) / (8 * (1 << 8));
+			temporary = temporary * 1000;
+		} else if (Errors <= 42949) {
+			temporary = (Errors * 100000) / (8 * (1 << 8));
+			temporary = temporary * 10000;
+		} else { /*if(Errors<=429496)  2^16 errors max*/
+			temporary = (Errors * 10000) / (8 * (1 << 8));
+			temporary = temporary * 100000;
+		}
+
+		/* pkt error*/
+		if (def == 2)
+			/*Per=Errors/(1 << 8);*/
+			Per = temporary;
+		else if (def == 3)
+			/*Per=Errors/(1 << 10);*/
+			Per = temporary / 4;
+		else if (def == 4)
+			/*Per=Errors/(1 << 12);*/
+			Per = temporary / 16;
+		else if (def == 5)
+			/*Per=Errors/(1 << 14);*/
+			Per = temporary / 64;
+		else if (def == 6)
+			/*Per=Errors/(1 << 16);*/
+			Per = temporary / 256;
+		else
+			Per = 0;
+
+	}
+	/* save actual value */
+	ter_state->pPER = Per;
+
+	return Per;
+}
+#endif
+static int stv0367_get_tune_settings(struct dvb_frontend *fe,
+					struct dvb_frontend_tune_settings
+					*fe_tune_settings)
+{
+	fe_tune_settings->min_delay_ms = 1000;
+	fe_tune_settings->step_size = 0;
+	fe_tune_settings->max_drift = 0;
+
+	return 0;
+}
+
+static void stv0367_release(struct dvb_frontend *fe)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	kfree(state->ter_state);
+	kfree(state->cab_state);
+	kfree(state);
+}
+
+static struct dvb_frontend_ops stv0367ter_ops = {
+	.info = {
+		.name			= "ST STV0367 DVB-T",
+		.type			= FE_OFDM,
+		.frequency_min		= 47000000,
+		.frequency_max		= 862000000,
+		.frequency_stepsize	= 15625,
+		.frequency_tolerance	= 0,
+		.caps = FE_CAN_FEC_1_2 | FE_CAN_FEC_2_3 |
+			FE_CAN_FEC_3_4 | FE_CAN_FEC_5_6 | FE_CAN_FEC_7_8 |
+			FE_CAN_FEC_AUTO |
+			FE_CAN_QPSK | FE_CAN_QAM_16 | FE_CAN_QAM_64 |
+			FE_CAN_QAM_128 | FE_CAN_QAM_256 | FE_CAN_QAM_AUTO |
+			FE_CAN_TRANSMISSION_MODE_AUTO | FE_CAN_RECOVER |
+			FE_CAN_INVERSION_AUTO |
+			FE_CAN_MUTE_TS
+	},
+	.release = stv0367_release,
+	.init = stv0367ter_init,
+	.sleep = stv0367ter_sleep,
+	.i2c_gate_ctrl = stv0367ter_gate_ctrl,
+	.set_frontend = stv0367ter_set_frontend,
+	.get_frontend = stv0367ter_get_frontend,
+	.get_tune_settings = stv0367_get_tune_settings,
+	.read_status = stv0367ter_read_status,
+	.read_ber = stv0367ter_read_ber,/* too slow */
+/*	.read_signal_strength = stv0367_read_signal_strength,*/
+	.read_snr = stv0367ter_read_snr,
+	.read_ucblocks = stv0367ter_read_ucblocks,
+};
+
+struct dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct stv0367_state *state = NULL;
+	struct stv0367ter_state *ter_state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+	ter_state = kzalloc(sizeof(struct stv0367ter_state), GFP_KERNEL);
+	if (ter_state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	state->config = config;
+	state->ter_state = ter_state;
+	state->fe.ops = stv0367ter_ops;
+	state->fe.demodulator_priv = state;
+	state->chip_id = stv0367_readreg(state, 0xf000);
+
+	dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id);
+
+	/* check if the demod is there */
+	if ((state->chip_id != 0x50) && (state->chip_id != 0x60))
+		goto error;
+
+	return &state->fe;
+
+error:
+	kfree(ter_state);
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv0367ter_attach);
+
+static int stv0367cab_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	stv0367_writebits(state, F367CAB_I2CT_ON, (enable > 0) ? 1 : 0);
+
+	return 0;
+}
+
+static u32 stv0367cab_get_mclk(struct dvb_frontend *fe, u32 ExtClk_Hz)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u32 mclk_Hz = 0;/* master clock frequency (Hz) */
+	u32 M, N, P;
+
+
+	if (stv0367_readbits(state, F367CAB_BYPASS_PLLXN) == 0) {
+		N = (u32)stv0367_readbits(state, F367CAB_PLL_NDIV);
+		if (N == 0)
+			N = N + 1;
+
+		M = (u32)stv0367_readbits(state, F367CAB_PLL_MDIV);
+		if (M == 0)
+			M = M + 1;
+
+		P = (u32)stv0367_readbits(state, F367CAB_PLL_PDIV);
+
+		if (P > 5)
+			P = 5;
+
+		mclk_Hz = ((ExtClk_Hz / 2) * N) / (M * (1 << P));
+		dprintk("stv0367cab_get_mclk BYPASS_PLLXN mclk_Hz=%d\n",
+								mclk_Hz);
+	} else
+		mclk_Hz = ExtClk_Hz;
+
+	dprintk("stv0367cab_get_mclk final mclk_Hz=%d\n", mclk_Hz);
+
+	return mclk_Hz;
+}
+
+static u32 stv0367cab_get_adc_freq(struct dvb_frontend *fe, u32 ExtClk_Hz)
+{
+	u32 ADCClk_Hz = ExtClk_Hz;
+
+	ADCClk_Hz = stv0367cab_get_mclk(fe, ExtClk_Hz);
+
+	return ADCClk_Hz;
+}
+
+enum stv0367cab_mod stv0367cab_SetQamSize(struct stv0367_state *state,
+					u32 SymbolRate,
+					enum stv0367cab_mod QAMSize)
+{
+	/* Set QAM size */
+	stv0367_writebits(state, F367CAB_QAM_MODE, QAMSize);
+
+	/* Set Registers settings specific to the QAM size */
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM4:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		break;
+	case FE_CAB_MOD_QAM16:
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x64);
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0x90);
+		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x8a);
+		break;
+	case FE_CAB_MOD_QAM32:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x6e);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0);
+		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xb7);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x9d);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
+		break;
+	case FE_CAB_MOD_QAM64:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x82);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a);
+		if (SymbolRate > 45000000) {
+			stv0367_writereg(state, R367CAB_FSM_STATE, 0xb0);
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa5);
+		} else if (SymbolRate > 25000000) {
+			stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6);
+		} else {
+			stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1);
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		}
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x95);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0x99);
+		break;
+	case FE_CAB_MOD_QAM128:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x76);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0x90);
+		stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xb1);
+		if (SymbolRate > 45000000)
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		else if (SymbolRate > 25000000)
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa6);
+		else
+			stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0x97);
+
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x8e);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x7f);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
+		break;
+	case FE_CAB_MOD_QAM256:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x94);
+		stv0367_writereg(state, R367CAB_AGC_PWR_REF_L, 0x5a);
+		stv0367_writereg(state, R367CAB_FSM_STATE, 0xa0);
+		if (SymbolRate > 45000000)
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		else if (SymbolRate > 25000000)
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xc1);
+		else
+			stv0367_writereg(state, R367CAB_EQU_CTR_LPF_GAIN, 0xd1);
+
+		stv0367_writereg(state, R367CAB_EQU_CRL_LPF_GAIN, 0xa7);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LD_SEN, 0x85);
+		stv0367_writereg(state, R367CAB_EQU_CRL_LIMITER, 0x40);
+		stv0367_writereg(state, R367CAB_EQU_PNT_GAIN, 0xa7);
+		break;
+	case FE_CAB_MOD_QAM512:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		break;
+	case FE_CAB_MOD_QAM1024:
+		stv0367_writereg(state, R367CAB_IQDEM_ADJ_AGC_REF, 0x00);
+		break;
+	default:
+		break;
+	}
+
+	return QAMSize;
+}
+
+static u32 stv0367cab_set_derot_freq(struct stv0367_state *state,
+					u32 adc_hz, s32 derot_hz)
+{
+	u32 sampled_if = 0;
+	u32 adc_khz;
+
+	adc_khz = adc_hz / 1000;
+
+	dprintk("%s: adc_hz=%d derot_hz=%d\n", __func__, adc_hz, derot_hz);
+
+	if (adc_khz != 0) {
+		if (derot_hz < 1000000)
+			derot_hz = adc_hz / 4; /* ZIF operation */
+		if (derot_hz > adc_hz)
+			derot_hz = derot_hz - adc_hz;
+		sampled_if = (u32)derot_hz / 1000;
+		sampled_if *= 32768;
+		sampled_if /= adc_khz;
+		sampled_if *= 256;
+	}
+
+	if (sampled_if > 8388607)
+		sampled_if = 8388607;
+
+	dprintk("%s: sampled_if=0x%x\n", __func__, sampled_if);
+
+	stv0367_writereg(state, R367CAB_MIX_NCO_LL, sampled_if);
+	stv0367_writereg(state, R367CAB_MIX_NCO_HL, (sampled_if >> 8));
+	stv0367_writebits(state, F367CAB_MIX_NCO_INC_HH, (sampled_if >> 16));
+
+	return derot_hz;
+}
+
+static u32 stv0367cab_get_derot_freq(struct stv0367_state *state, u32 adc_hz)
+{
+	u32 sampled_if;
+
+	sampled_if = stv0367_readbits(state, F367CAB_MIX_NCO_INC_LL) +
+			(stv0367_readbits(state, F367CAB_MIX_NCO_INC_HL) << 8) +
+			(stv0367_readbits(state, F367CAB_MIX_NCO_INC_HH) << 16);
+
+	sampled_if /= 256;
+	sampled_if *= (adc_hz / 1000);
+	sampled_if += 1;
+	sampled_if /= 32768;
+
+	return sampled_if;
+}
+
+static u32 stv0367cab_set_srate(struct stv0367_state *state, u32 adc_hz,
+			u32 mclk_hz, u32 SymbolRate,
+			enum stv0367cab_mod QAMSize)
+{
+	u32 QamSizeCorr = 0;
+	u32 u32_tmp = 0, u32_tmp1 = 0;
+	u32 adp_khz;
+
+	dprintk("%s:\n", __func__);
+
+	/* Set Correction factor of SRC gain */
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM4:
+		QamSizeCorr = 1110;
+		break;
+	case FE_CAB_MOD_QAM16:
+		QamSizeCorr = 1032;
+		break;
+	case FE_CAB_MOD_QAM32:
+		QamSizeCorr =  954;
+		break;
+	case FE_CAB_MOD_QAM64:
+		QamSizeCorr =  983;
+		break;
+	case FE_CAB_MOD_QAM128:
+		QamSizeCorr =  957;
+		break;
+	case FE_CAB_MOD_QAM256:
+		QamSizeCorr =  948;
+		break;
+	case FE_CAB_MOD_QAM512:
+		QamSizeCorr =    0;
+		break;
+	case FE_CAB_MOD_QAM1024:
+		QamSizeCorr =  944;
+		break;
+	default:
+		break;
+	}
+
+	/* Transfer ratio calculation */
+	if (adc_hz != 0) {
+		u32_tmp = 256 * SymbolRate;
+		u32_tmp = u32_tmp / adc_hz;
+	}
+	stv0367_writereg(state, R367CAB_EQU_CRL_TFR, (u8)u32_tmp);
+
+	/* Symbol rate and SRC gain calculation */
+	adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */
+	if (adp_khz != 0) {
+		u32_tmp = SymbolRate;
+		u32_tmp1 = SymbolRate;
+
+		if (u32_tmp < 2097152) { /* 2097152 = 2^21 */
+			/* Symbol rate calculation */
+			u32_tmp *= 2048; /* 2048 = 2^11 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2^14 */
+			u32_tmp /= 125 ; /* 125 = 1000/2^3 */
+			u32_tmp = u32_tmp * 8; /* 8 = 2^3 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 2048; /* *2*2^10 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 10000000;
+
+		} else if (u32_tmp < 4194304) { /* 4194304 = 2**22 */
+			/* Symbol rate calculation */
+			u32_tmp *= 1024 ; /* 1024 = 2**10 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */
+			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
+			u32_tmp = u32_tmp * 16; /* 16 = 2**4 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 1024; /* *2*2^9 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz)*/
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 5000000;
+		} else if (u32_tmp < 8388607) { /* 8388607 = 2**23 */
+			/* Symbol rate calculation */
+			u32_tmp *= 512 ; /* 512 = 2**9 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2**14 */
+			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
+			u32_tmp = u32_tmp * 32; /* 32 = 2**5 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 512; /* *2*2^8 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 2500000;
+		} else {
+			/* Symbol rate calculation */
+			u32_tmp *= 256 ; /* 256 = 2**8 */
+			u32_tmp = u32_tmp / adp_khz;
+			u32_tmp = u32_tmp * 16384; /* 16384 = 2**13 */
+			u32_tmp /= 125 ; /* 125 = 1000/2**3 */
+			u32_tmp = u32_tmp * 64; /* 64 = 2**6 */
+
+			/* SRC Gain Calculation */
+			u32_tmp1 *= 256; /* 2*2^7 */
+			u32_tmp1 /= 439; /* *2/878 */
+			u32_tmp1 *= 256; /* *2^8 */
+			u32_tmp1 = u32_tmp1 / adp_khz; /* /(AdpClk in kHz) */
+			u32_tmp1 *= QamSizeCorr * 9; /* *1000*corr factor */
+			u32_tmp1 = u32_tmp1 / 1250000;
+		}
+	}
+#if 0
+	/* Filters' coefficients are calculated and written
+	into registers only if the filters are enabled */
+	if (stv0367_readbits(state, F367CAB_ADJ_EN)) {
+		stv0367cab_SetIirAdjacentcoefficient(state, mclk_hz,
+								SymbolRate);
+		/* AllPass filter must be enabled
+		when the adjacents filter is used */
+		stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 1);
+		stv0367cab_SetAllPasscoefficient(state, mclk_hz, SymbolRate);
+	} else
+		/* AllPass filter must be disabled
+		when the adjacents filter is not used */
+#endif
+	stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
+
+	stv0367_writereg(state, R367CAB_SRC_NCO_LL, u32_tmp);
+	stv0367_writereg(state, R367CAB_SRC_NCO_LH, (u32_tmp >> 8));
+	stv0367_writereg(state, R367CAB_SRC_NCO_HL, (u32_tmp >> 16));
+	stv0367_writereg(state, R367CAB_SRC_NCO_HH, (u32_tmp >> 24));
+
+	stv0367_writereg(state, R367CAB_IQDEM_GAIN_SRC_L, u32_tmp1 & 0x00ff);
+	stv0367_writebits(state, F367CAB_GAIN_SRC_HI, (u32_tmp1 >> 8) & 0x00ff);
+
+	return SymbolRate ;
+}
+
+static u32 stv0367cab_GetSymbolRate(struct stv0367_state *state, u32 mclk_hz)
+{
+	u32 regsym;
+	u32 adp_khz;
+
+	regsym = stv0367_readreg(state, R367CAB_SRC_NCO_LL) +
+		(stv0367_readreg(state, R367CAB_SRC_NCO_LH) << 8) +
+		(stv0367_readreg(state, R367CAB_SRC_NCO_HL) << 16) +
+		(stv0367_readreg(state, R367CAB_SRC_NCO_HH) << 24);
+
+	adp_khz = (mclk_hz >> 1) / 1000;/* TRL works at half the system clock */
+
+	if (regsym < 134217728) {		/* 134217728L = 2**27*/
+		regsym = regsym * 32;		/* 32 = 2**5 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3 */
+		regsym /= 2048 ;		/* 2048 = 2**11	*/
+	} else if (regsym < 268435456) {	/* 268435456L = 2**28 */
+		regsym = regsym * 16;		/* 16 = 2**4 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3*/
+		regsym /= 1024 ;		/* 256 = 2**10*/
+	} else if (regsym < 536870912) {	/* 536870912L = 2**29*/
+		regsym = regsym * 8;		/* 8 = 2**3 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3 */
+		regsym /= 512 ;			/* 128 = 2**9 */
+	} else {
+		regsym = regsym * 4;		/* 4 = 2**2 */
+		regsym = regsym / 32768;	/* 32768L = 2**15 */
+		regsym = adp_khz * regsym;	/* AdpClk in kHz */
+		regsym = regsym / 128;		/* 128 = 2**7 */
+		regsym *= 125 ;			/* 125 = 1000/2**3 */
+		regsym /= 256 ;			/* 64 = 2**8 */
+	}
+
+	return regsym;
+}
+
+static int stv0367cab_read_status(struct dvb_frontend *fe, fe_status_t *status)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	*status = 0;
+
+	if (stv0367_readbits(state, F367CAB_QAMFEC_LOCK)) {
+		*status |= FE_HAS_LOCK;
+		dprintk("%s: stv0367 has locked\n", __func__);
+	}
+
+	return 0;
+}
+
+static int stv0367cab_standby(struct dvb_frontend *fe, u8 standby_on)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	dprintk("%s:\n", __func__);
+
+	if (standby_on) {
+		stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x03);
+		stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x01);
+		stv0367_writebits(state, F367CAB_STDBY, 1);
+		stv0367_writebits(state, F367CAB_STDBY_CORE, 1);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_I, 0);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 0);
+		stv0367_writebits(state, F367CAB_POFFQ, 1);
+		stv0367_writebits(state, F367CAB_POFFI, 1);
+	} else {
+		stv0367_writebits(state, F367CAB_STDBY_PLLXN, 0x00);
+		stv0367_writebits(state, F367CAB_BYPASS_PLLXN, 0x00);
+		stv0367_writebits(state, F367CAB_STDBY, 0);
+		stv0367_writebits(state, F367CAB_STDBY_CORE, 0);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_I, 1);
+		stv0367_writebits(state, F367CAB_EN_BUFFER_Q, 1);
+		stv0367_writebits(state, F367CAB_POFFQ, 0);
+		stv0367_writebits(state, F367CAB_POFFI, 0);
+	}
+
+	return 0;
+}
+
+static int stv0367cab_sleep(struct dvb_frontend *fe)
+{
+	return stv0367cab_standby(fe, 1);
+}
+
+int stv0367cab_init(struct dvb_frontend *fe)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367cab_state *cab_state = state->cab_state;
+	int i;
+
+	dprintk("%s:\n", __func__);
+
+	for (i = 0; i < STV0367CAB_NBREGS; i++)
+		stv0367_writereg(state, def0367cab[i].addr,
+						def0367cab[i].value);
+
+	switch (state->config->ts_mode) {
+	case STV0367_DVBCI_CLOCK:
+		dprintk("Setting TSMode = STV0367_DVBCI_CLOCK\n");
+		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x03);
+		break;
+	case STV0367_SERIAL_PUNCT_CLOCK:
+	case STV0367_SERIAL_CONT_CLOCK:
+		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x01);
+		break;
+	case STV0367_PARALLEL_PUNCT_CLOCK:
+	case STV0367_OUTPUTMODE_DEFAULT:
+		stv0367_writebits(state, F367CAB_OUTFORMAT, 0x00);
+		break;
+	}
+
+	switch (state->config->clk_pol) {
+	case STV0367_RISINGEDGE_CLOCK:
+		stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x00);
+		break;
+	case STV0367_FALLINGEDGE_CLOCK:
+	case STV0367_CLOCKPOLARITY_DEFAULT:
+		stv0367_writebits(state, F367CAB_CLK_POLARITY, 0x01);
+		break;
+	}
+
+	stv0367_writebits(state, F367CAB_SYNC_STRIP, 0x00);
+
+	stv0367_writebits(state, F367CAB_CT_NBST, 0x01);
+
+	stv0367_writebits(state, F367CAB_TS_SWAP, 0x01);
+
+	stv0367_writebits(state, F367CAB_FIFO_BYPASS, 0x00);
+
+	stv0367_writereg(state, R367CAB_ANACTRL, 0x00);/*PLL enabled and used */
+
+	cab_state->mclk = stv0367cab_get_mclk(fe, state->config->xtal);
+	cab_state->adc_clk = stv0367cab_get_adc_freq(fe, state->config->xtal);
+
+	return 0;
+}
+static
+enum stv0367_cab_signal_type stv0367cab_algo(struct stv0367_state *state,
+				struct dvb_frontend_parameters *param)
+{
+	struct dvb_qam_parameters *op = &param->u.qam;
+	struct stv0367cab_state *cab_state = state->cab_state;
+	enum stv0367_cab_signal_type signalType = FE_CAB_NOAGC;
+	u32	QAMFEC_Lock, QAM_Lock, u32_tmp,
+		LockTime, TRLTimeOut, AGCTimeOut, CRLSymbols,
+		CRLTimeOut, EQLTimeOut, DemodTimeOut, FECTimeOut;
+	u8	TrackAGCAccum;
+	s32	tmp;
+
+	dprintk("%s:\n", __func__);
+
+	/* Timeouts calculation */
+	/* A max lock time of 25 ms is allowed for delayed AGC */
+	AGCTimeOut = 25;
+	/* 100000 symbols needed by the TRL as a maximum value */
+	TRLTimeOut = 100000000 / op->symbol_rate;
+	/* CRLSymbols is the needed number of symbols to achieve a lock
+	   within [-4%, +4%] of the symbol rate.
+	   CRL timeout is calculated
+	   for a lock within [-search_range, +search_range].
+	   EQL timeout can be changed depending on
+	   the micro-reflections we want to handle.
+	   A characterization must be performed
+	   with these echoes to get new timeout values.
+	*/
+	switch (op->modulation) {
+	case QAM_16:
+		CRLSymbols = 150000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_32:
+		CRLSymbols = 250000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_64:
+		CRLSymbols = 200000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_128:
+		CRLSymbols = 250000;
+		EQLTimeOut = 100;
+		break;
+	case QAM_256:
+		CRLSymbols = 250000;
+		EQLTimeOut = 100;
+		break;
+	default:
+		CRLSymbols = 200000;
+		EQLTimeOut = 100;
+		break;
+	}
+#if 0
+	if (pIntParams->search_range < 0) {
+		CRLTimeOut = (25 * CRLSymbols *
+				(-pIntParams->search_range / 1000)) /
+					(pIntParams->symbol_rate / 1000);
+	} else
+#endif
+	CRLTimeOut = (25 * CRLSymbols * (cab_state->search_range / 1000)) /
+					(op->symbol_rate / 1000);
+
+	CRLTimeOut = (1000 * CRLTimeOut) / op->symbol_rate;
+	/* Timeouts below 50ms are coerced */
+	if (CRLTimeOut < 50)
+		CRLTimeOut = 50;
+	/* A maximum of 100 TS packets is needed to get FEC lock even in case
+	the spectrum inversion needs to be changed.
+	   This is equal to 20 ms in case of the lowest symbol rate of 0.87Msps
+	*/
+	FECTimeOut = 20;
+	DemodTimeOut = AGCTimeOut + TRLTimeOut + CRLTimeOut + EQLTimeOut;
+
+	dprintk("%s: DemodTimeOut=%d\n", __func__, DemodTimeOut);
+
+	/* Reset the TRL to ensure nothing starts until the
+	   AGC is stable which ensures a better lock time
+	*/
+	stv0367_writereg(state, R367CAB_CTRL_1, 0x04);
+	/* Set AGC accumulation time to minimum and lock threshold to maximum
+	in order to speed up the AGC lock */
+	TrackAGCAccum = stv0367_readbits(state, F367CAB_AGC_ACCUMRSTSEL);
+	stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, 0x0);
+	/* Modulus Mapper is disabled */
+	stv0367_writebits(state, F367CAB_MODULUSMAP_EN, 0);
+	/* Disable the sweep function */
+	stv0367_writebits(state, F367CAB_SWEEP_EN, 0);
+	/* The sweep function is never used, Sweep rate must be set to 0 */
+	/* Set the derotator frequency in Hz */
+	stv0367cab_set_derot_freq(state, cab_state->adc_clk,
+		(1000 * (s32)state->config->if_khz + cab_state->derot_offset));
+	/* Disable the Allpass Filter when the symbol rate is out of range */
+	if ((op->symbol_rate > 10800000) | (op->symbol_rate < 1800000)) {
+		stv0367_writebits(state, F367CAB_ADJ_EN, 0);
+		stv0367_writebits(state, F367CAB_ALLPASSFILT_EN, 0);
+	}
+#if 0
+	/* Check if the tuner is locked */
+	tuner_lock = stv0367cab_tuner_get_status(fe);
+	if (tuner_lock == 0)
+		return FE_367CAB_NOTUNER;
+#endif
+	/* Relase the TRL to start demodulator acquisition */
+	/* Wait for QAM lock */
+	LockTime = 0;
+	stv0367_writereg(state, R367CAB_CTRL_1, 0x00);
+	do {
+		QAM_Lock = stv0367_readbits(state, F367CAB_FSM_STATUS);
+		if ((LockTime >= (DemodTimeOut - EQLTimeOut)) &&
+							(QAM_Lock == 0x04))
+			/*
+			 * We don't wait longer, the frequency/phase offset
+			 * must be too big
+			 */
+			LockTime = DemodTimeOut;
+		else if ((LockTime >= (AGCTimeOut + TRLTimeOut)) &&
+							(QAM_Lock == 0x02))
+			/*
+			 * We don't wait longer, either there is no signal or
+			 * it is not the right symbol rate or it is an analog
+			 * carrier
+			 */
+		{
+			LockTime = DemodTimeOut;
+			u32_tmp = stv0367_readbits(state,
+						F367CAB_AGC_PWR_WORD_LO) +
+					(stv0367_readbits(state,
+						F367CAB_AGC_PWR_WORD_ME) << 8) +
+					(stv0367_readbits(state,
+						F367CAB_AGC_PWR_WORD_HI) << 16);
+			if (u32_tmp >= 131072)
+				u32_tmp = 262144 - u32_tmp;
+			u32_tmp = u32_tmp / (1 << (11 - stv0367_readbits(state,
+							F367CAB_AGC_IF_BWSEL)));
+
+			if (u32_tmp < stv0367_readbits(state,
+						F367CAB_AGC_PWRREF_LO) +
+					256 * stv0367_readbits(state,
+						F367CAB_AGC_PWRREF_HI) - 10)
+				QAM_Lock = 0x0f;
+		} else {
+			usleep_range(10000, 20000);
+			LockTime += 10;
+		}
+		dprintk("QAM_Lock=0x%x LockTime=%d\n", QAM_Lock, LockTime);
+		tmp = stv0367_readreg(state, R367CAB_IT_STATUS1);
+
+		dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp);
+
+	} while (((QAM_Lock != 0x0c) && (QAM_Lock != 0x0b)) &&
+						(LockTime < DemodTimeOut));
+
+	dprintk("QAM_Lock=0x%x\n", QAM_Lock);
+
+	tmp = stv0367_readreg(state, R367CAB_IT_STATUS1);
+	dprintk("R367CAB_IT_STATUS1=0x%x\n", tmp);
+	tmp = stv0367_readreg(state, R367CAB_IT_STATUS2);
+	dprintk("R367CAB_IT_STATUS2=0x%x\n", tmp);
+
+	tmp  = stv0367cab_get_derot_freq(state, cab_state->adc_clk);
+	dprintk("stv0367cab_get_derot_freq=0x%x\n", tmp);
+
+	if ((QAM_Lock == 0x0c) || (QAM_Lock == 0x0b)) {
+		/* Wait for FEC lock */
+		LockTime = 0;
+		do {
+			usleep_range(5000, 7000);
+			LockTime += 5;
+			QAMFEC_Lock = stv0367_readbits(state,
+							F367CAB_QAMFEC_LOCK);
+		} while (!QAMFEC_Lock && (LockTime < FECTimeOut));
+	} else
+		QAMFEC_Lock = 0;
+
+	if (QAMFEC_Lock) {
+		signalType = FE_CAB_DATAOK;
+		cab_state->modulation = op->modulation;
+		cab_state->spect_inv = stv0367_readbits(state,
+							F367CAB_QUAD_INV);
+#if 0
+/* not clear for me */
+		if (state->config->if_khz != 0) {
+			if (state->config->if_khz > cab_state->adc_clk / 1000) {
+				cab_state->freq_khz =
+					FE_Cab_TunerGetFrequency(pIntParams->hTuner)
+				- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
+				- cab_state->adc_clk / 1000 + state->config->if_khz;
+			} else {
+				cab_state->freq_khz =
+						FE_Cab_TunerGetFrequency(pIntParams->hTuner)
+						- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
+										+ state->config->if_khz;
+			}
+		} else {
+			cab_state->freq_khz =
+				FE_Cab_TunerGetFrequency(pIntParams->hTuner) +
+				stv0367cab_get_derot_freq(state,
+							cab_state->adc_clk) -
+				cab_state->adc_clk / 4000;
+		}
+#endif
+		cab_state->symbol_rate = stv0367cab_GetSymbolRate(state,
+							cab_state->mclk);
+		cab_state->locked = 1;
+
+		/* stv0367_setbits(state, F367CAB_AGC_ACCUMRSTSEL,7);*/
+	} else {
+		switch (QAM_Lock) {
+		case 1:
+			signalType = FE_CAB_NOAGC;
+			break;
+		case 2:
+			signalType = FE_CAB_NOTIMING;
+			break;
+		case 3:
+			signalType = FE_CAB_TIMINGOK;
+			break;
+		case 4:
+			signalType = FE_CAB_NOCARRIER;
+			break;
+		case 5:
+			signalType = FE_CAB_CARRIEROK;
+			break;
+		case 7:
+			signalType = FE_CAB_NOBLIND;
+			break;
+		case 8:
+			signalType = FE_CAB_BLINDOK;
+			break;
+		case 10:
+			signalType = FE_CAB_NODEMOD;
+			break;
+		case 11:
+			signalType = FE_CAB_DEMODOK;
+			break;
+		case 12:
+			signalType = FE_CAB_DEMODOK;
+			break;
+		case 13:
+			signalType = FE_CAB_NODEMOD;
+			break;
+		case 14:
+			signalType = FE_CAB_NOBLIND;
+			break;
+		case 15:
+			signalType = FE_CAB_NOSIGNAL;
+			break;
+		default:
+			break;
+		}
+
+	}
+
+	/* Set the AGC control values to tracking values */
+	stv0367_writebits(state, F367CAB_AGC_ACCUMRSTSEL, TrackAGCAccum);
+	return signalType;
+}
+
+static int stv0367cab_set_frontend(struct dvb_frontend *fe,
+				struct dvb_frontend_parameters *param)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367cab_state *cab_state = state->cab_state;
+	struct dvb_qam_parameters *op = &param->u.qam;
+	enum stv0367cab_mod QAMSize = 0;
+
+	dprintk("%s: freq = %d, srate = %d\n", __func__,
+					param->frequency, op->symbol_rate);
+
+	cab_state->derot_offset = 0;
+
+	switch (op->modulation) {
+	case QAM_16:
+		QAMSize = FE_CAB_MOD_QAM16;
+		break;
+	case QAM_32:
+		QAMSize = FE_CAB_MOD_QAM32;
+		break;
+	case QAM_64:
+		QAMSize = FE_CAB_MOD_QAM64;
+		break;
+	case QAM_128:
+		QAMSize = FE_CAB_MOD_QAM128;
+		break;
+	case QAM_256:
+		QAMSize = FE_CAB_MOD_QAM256;
+		break;
+	default:
+		break;
+	}
+
+	stv0367cab_init(fe);
+
+	/* Tuner Frequency Setting */
+	if (fe->ops.tuner_ops.set_params) {
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 1);
+		fe->ops.tuner_ops.set_params(fe, param);
+		if (fe->ops.i2c_gate_ctrl)
+			fe->ops.i2c_gate_ctrl(fe, 0);
+	}
+
+	stv0367cab_SetQamSize(
+			state,
+			op->symbol_rate,
+			QAMSize);
+
+	stv0367cab_set_srate(state,
+			cab_state->adc_clk,
+			cab_state->mclk,
+			op->symbol_rate,
+			QAMSize);
+	/* Search algorithm launch, [-1.1*RangeOffset, +1.1*RangeOffset] scan */
+	cab_state->state = stv0367cab_algo(state, param);
+	return 0;
+}
+
+static int stv0367cab_get_frontend(struct dvb_frontend *fe,
+				  struct dvb_frontend_parameters *param)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	struct stv0367cab_state *cab_state = state->cab_state;
+	struct dvb_qam_parameters *op = &param->u.qam;
+
+	enum stv0367cab_mod QAMSize;
+
+	dprintk("%s:\n", __func__);
+
+	op->symbol_rate = stv0367cab_GetSymbolRate(state, cab_state->mclk);
+
+	QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM16:
+		op->modulation = QAM_16;
+		break;
+	case FE_CAB_MOD_QAM32:
+		op->modulation = QAM_32;
+		break;
+	case FE_CAB_MOD_QAM64:
+		op->modulation = QAM_64;
+		break;
+	case FE_CAB_MOD_QAM128:
+		op->modulation = QAM_128;
+		break;
+	case QAM_256:
+		op->modulation = QAM_256;
+		break;
+	default:
+		break;
+	}
+
+	param->frequency = stv0367_get_tuner_freq(fe);
+
+	dprintk("%s: tuner frequency = %d\n", __func__, param->frequency);
+
+	if (state->config->if_khz == 0) {
+		param->frequency +=
+			(stv0367cab_get_derot_freq(state, cab_state->adc_clk) -
+			cab_state->adc_clk / 4000);
+		return 0;
+	}
+
+	if (state->config->if_khz > cab_state->adc_clk / 1000)
+		param->frequency += (state->config->if_khz
+			- stv0367cab_get_derot_freq(state, cab_state->adc_clk)
+			- cab_state->adc_clk / 1000);
+	else
+		param->frequency += (state->config->if_khz
+			- stv0367cab_get_derot_freq(state, cab_state->adc_clk));
+
+	return 0;
+}
+
+#if 0
+void stv0367cab_GetErrorCount(state, enum stv0367cab_mod QAMSize,
+			u32 symbol_rate, FE_367qam_Monitor *Monitor_results)
+{
+	stv0367cab_OptimiseNByteAndGetBER(state, QAMSize, symbol_rate, Monitor_results);
+	stv0367cab_GetPacketsCount(state, Monitor_results);
+
+	return;
+}
+
+static int stv0367cab_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	return 0;
+}
+#endif
+static s32 stv0367cab_get_rf_lvl(struct stv0367_state *state)
+{
+	s32 rfLevel = 0;
+	s32 RfAgcPwm = 0, IfAgcPwm = 0;
+	u8 i;
+
+	stv0367_writebits(state, F367CAB_STDBY_ADCGP, 0x0);
+
+	RfAgcPwm =
+		(stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_LO) & 0x03) +
+		(stv0367_readbits(state, F367CAB_RF_AGC1_LEVEL_HI) << 2);
+	RfAgcPwm = 100 * RfAgcPwm / 1023;
+
+	IfAgcPwm =
+		stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_LO) +
+		(stv0367_readbits(state, F367CAB_AGC_IF_PWMCMD_HI) << 8);
+	if (IfAgcPwm >= 2048)
+		IfAgcPwm -= 2048;
+	else
+		IfAgcPwm += 2048;
+
+	IfAgcPwm = 100 * IfAgcPwm / 4095;
+
+	/* For DTT75467 on NIM */
+	if (RfAgcPwm < 90  && IfAgcPwm < 28) {
+		for (i = 0; i < RF_LOOKUP_TABLE_SIZE; i++) {
+			if (RfAgcPwm <= stv0367cab_RF_LookUp1[0][i]) {
+				rfLevel = (-1) * stv0367cab_RF_LookUp1[1][i];
+				break;
+			}
+		}
+		if (i == RF_LOOKUP_TABLE_SIZE)
+			rfLevel = -56;
+	} else { /*if IF AGC>10*/
+		for (i = 0; i < RF_LOOKUP_TABLE2_SIZE; i++) {
+			if (IfAgcPwm <= stv0367cab_RF_LookUp2[0][i]) {
+				rfLevel = (-1) * stv0367cab_RF_LookUp2[1][i];
+				break;
+			}
+		}
+		if (i == RF_LOOKUP_TABLE2_SIZE)
+			rfLevel = -72;
+	}
+	return rfLevel;
+}
+
+static int stv0367cab_read_strength(struct dvb_frontend *fe, u16 *strength)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+
+	s32 signal =  stv0367cab_get_rf_lvl(state);
+
+	dprintk("%s: signal=%d dBm\n", __func__, signal);
+
+	if (signal <= -72)
+		*strength = 65535;
+	else
+		*strength = (22 + signal) * (-1311);
+
+	dprintk("%s: strength=%d\n", __func__, (*strength));
+
+	return 0;
+}
+
+static int stv0367cab_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	u32 noisepercentage;
+	enum stv0367cab_mod QAMSize;
+	u32 regval = 0, temp = 0;
+	int power, i;
+
+	QAMSize = stv0367_readbits(state, F367CAB_QAM_MODE);
+	switch (QAMSize) {
+	case FE_CAB_MOD_QAM4:
+		power = 21904;
+		break;
+	case FE_CAB_MOD_QAM16:
+		power = 20480;
+		break;
+	case FE_CAB_MOD_QAM32:
+		power = 23040;
+		break;
+	case FE_CAB_MOD_QAM64:
+		power = 21504;
+		break;
+	case FE_CAB_MOD_QAM128:
+		power = 23616;
+		break;
+	case FE_CAB_MOD_QAM256:
+		power = 21760;
+		break;
+	case FE_CAB_MOD_QAM512:
+		power = 1;
+		break;
+	case FE_CAB_MOD_QAM1024:
+		power = 21280;
+		break;
+	default:
+		power = 1;
+		break;
+	}
+
+	for (i = 0; i < 10; i++) {
+		regval += (stv0367_readbits(state, F367CAB_SNR_LO)
+			+ 256 * stv0367_readbits(state, F367CAB_SNR_HI));
+	}
+
+	regval /= 10; /*for average over 10 times in for loop above*/
+	if (regval != 0) {
+		temp = power
+			* (1 << (3 + stv0367_readbits(state, F367CAB_SNR_PER)));
+		temp /= regval;
+	}
+
+	/* table values, not needed to calculate logarithms */
+	if (temp >= 5012)
+		noisepercentage = 100;
+	else if (temp >= 3981)
+		noisepercentage = 93;
+	else if (temp >= 3162)
+		noisepercentage = 86;
+	else if (temp >= 2512)
+		noisepercentage = 79;
+	else if (temp >= 1995)
+		noisepercentage = 72;
+	else if (temp >= 1585)
+		noisepercentage = 65;
+	else if (temp >= 1259)
+		noisepercentage = 58;
+	else if (temp >= 1000)
+		noisepercentage = 50;
+	else if (temp >= 794)
+		noisepercentage = 43;
+	else if (temp >= 501)
+		noisepercentage = 36;
+	else if (temp >= 316)
+		noisepercentage = 29;
+	else if (temp >= 200)
+		noisepercentage = 22;
+	else if (temp >= 158)
+		noisepercentage = 14;
+	else if (temp >= 126)
+		noisepercentage = 7;
+	else
+		noisepercentage = 0;
+
+	dprintk("%s: noisepercentage=%d\n", __func__, noisepercentage);
+
+	*snr = (noisepercentage * 65535) / 100;
+
+	return 0;
+}
+
+static int stv0367cab_read_ucblcks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+	struct stv0367_state *state = fe->demodulator_priv;
+	int corrected, tscount;
+
+	*ucblocks = (stv0367_readreg(state, R367CAB_RS_COUNTER_5) << 8)
+			| stv0367_readreg(state, R367CAB_RS_COUNTER_4);
+	corrected = (stv0367_readreg(state, R367CAB_RS_COUNTER_3) << 8)
+			| stv0367_readreg(state, R367CAB_RS_COUNTER_2);
+	tscount = (stv0367_readreg(state, R367CAB_RS_COUNTER_2) << 8)
+			| stv0367_readreg(state, R367CAB_RS_COUNTER_1);
+
+	dprintk("%s: uncorrected blocks=%d corrected blocks=%d tscount=%d\n",
+				__func__, *ucblocks, corrected, tscount);
+
+	return 0;
+};
+
+static struct dvb_frontend_ops stv0367cab_ops = {
+	.info = {
+		.name = "ST STV0367 DVB-C",
+		.type = FE_QAM,
+		.frequency_min = 47000000,
+		.frequency_max = 862000000,
+		.frequency_stepsize = 62500,
+		.symbol_rate_min = 870000,
+		.symbol_rate_max = 11700000,
+		.caps = 0x400 |/* FE_CAN_QAM_4 */
+			FE_CAN_QAM_16 | FE_CAN_QAM_32  |
+			FE_CAN_QAM_64 | FE_CAN_QAM_128 |
+			FE_CAN_QAM_256 | FE_CAN_FEC_AUTO
+	},
+	.release				= stv0367_release,
+	.init					= stv0367cab_init,
+	.sleep					= stv0367cab_sleep,
+	.i2c_gate_ctrl				= stv0367cab_gate_ctrl,
+	.set_frontend				= stv0367cab_set_frontend,
+	.get_frontend				= stv0367cab_get_frontend,
+	.read_status				= stv0367cab_read_status,
+/*	.read_ber				= stv0367cab_read_ber, */
+	.read_signal_strength			= stv0367cab_read_strength,
+	.read_snr				= stv0367cab_read_snr,
+	.read_ucblocks				= stv0367cab_read_ucblcks,
+	.get_tune_settings			= stv0367_get_tune_settings,
+};
+
+struct dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
+				   struct i2c_adapter *i2c)
+{
+	struct stv0367_state *state = NULL;
+	struct stv0367cab_state *cab_state = NULL;
+
+	/* allocate memory for the internal state */
+	state = kzalloc(sizeof(struct stv0367_state), GFP_KERNEL);
+	if (state == NULL)
+		goto error;
+	cab_state = kzalloc(sizeof(struct stv0367cab_state), GFP_KERNEL);
+	if (cab_state == NULL)
+		goto error;
+
+	/* setup the state */
+	state->i2c = i2c;
+	state->config = config;
+	cab_state->search_range = 280000;
+	state->cab_state = cab_state;
+	state->fe.ops = stv0367cab_ops;
+	state->fe.demodulator_priv = state;
+	state->chip_id = stv0367_readreg(state, 0xf000);
+
+	dprintk("%s: chip_id = 0x%x\n", __func__, state->chip_id);
+
+	/* check if the demod is there */
+	if ((state->chip_id != 0x50) && (state->chip_id != 0x60))
+		goto error;
+
+	return &state->fe;
+
+error:
+	kfree(cab_state);
+	kfree(state);
+	return NULL;
+}
+EXPORT_SYMBOL(stv0367cab_attach);
+
+MODULE_PARM_DESC(debug, "Set debug");
+MODULE_PARM_DESC(i2c_debug, "Set i2c debug");
+
+MODULE_AUTHOR("Igor M. Liplianin");
+MODULE_DESCRIPTION("ST STV0367 DVB-C/T demodulator driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,66 @@
+/*
+ * stv0367.h
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 STV0367_H
+#define STV0367_H
+
+#include <linux/dvb/frontend.h>
+#include "dvb_frontend.h"
+
+struct stv0367_config {
+	u8 demod_address;
+	u32 xtal;
+	u32 if_khz;/*4500*/
+	int if_iq_mode;
+	int ts_mode;
+	int clk_pol;
+};
+
+#if defined(CONFIG_DVB_STV0367) || (defined(CONFIG_DVB_STV0367_MODULE) \
+							&& defined(MODULE))
+extern struct
+dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c);
+extern struct
+dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c);
+#else
+static inline struct
+dvb_frontend *stv0367ter_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+static inline struct
+dvb_frontend *stv0367cab_attach(const struct stv0367_config *config,
+					struct i2c_adapter *i2c)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return NULL;
+}
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367_priv.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367_priv.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367_priv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367_priv.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,212 @@
+/*
+ * stv0367_priv.h
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ */
+/* Common driver error constants */
+
+#ifndef STV0367_PRIV_H
+#define STV0367_PRIV_H
+
+#ifndef TRUE
+    #define TRUE (1 == 1)
+#endif
+#ifndef FALSE
+    #define FALSE (!TRUE)
+#endif
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* MACRO definitions */
+#define ABS(X) ((X) < 0 ? (-1 * (X)) : (X))
+#define MAX(X, Y) ((X) >= (Y) ? (X) : (Y))
+#define MIN(X, Y) ((X) <= (Y) ? (X) : (Y))
+#define INRANGE(X, Y, Z) \
+	((((X) <= (Y)) && ((Y) <= (Z))) || \
+	(((Z) <= (Y)) && ((Y) <= (X))) ? 1 : 0)
+
+#ifndef MAKEWORD
+#define MAKEWORD(X, Y) (((X) << 8) + (Y))
+#endif
+
+#define LSB(X) (((X) & 0xff))
+#define MSB(Y) (((Y) >> 8) & 0xff)
+#define MMSB(Y)(((Y) >> 16) & 0xff)
+
+enum stv0367_ter_signal_type {
+	FE_TER_NOAGC = 0,
+	FE_TER_AGCOK = 5,
+	FE_TER_NOTPS = 6,
+	FE_TER_TPSOK = 7,
+	FE_TER_NOSYMBOL = 8,
+	FE_TER_BAD_CPQ = 9,
+	FE_TER_PRFOUNDOK = 10,
+	FE_TER_NOPRFOUND = 11,
+	FE_TER_LOCKOK = 12,
+	FE_TER_NOLOCK = 13,
+	FE_TER_SYMBOLOK = 15,
+	FE_TER_CPAMPOK = 16,
+	FE_TER_NOCPAMP = 17,
+	FE_TER_SWNOK = 18
+};
+
+enum stv0367_ts_mode {
+	STV0367_OUTPUTMODE_DEFAULT,
+	STV0367_SERIAL_PUNCT_CLOCK,
+	STV0367_SERIAL_CONT_CLOCK,
+	STV0367_PARALLEL_PUNCT_CLOCK,
+	STV0367_DVBCI_CLOCK
+};
+
+enum stv0367_clk_pol {
+	STV0367_CLOCKPOLARITY_DEFAULT,
+	STV0367_RISINGEDGE_CLOCK,
+	STV0367_FALLINGEDGE_CLOCK
+};
+
+enum stv0367_ter_bw {
+	FE_TER_CHAN_BW_6M = 6,
+	FE_TER_CHAN_BW_7M = 7,
+	FE_TER_CHAN_BW_8M = 8
+};
+
+#if 0
+enum FE_TER_Rate_TPS {
+	FE_TER_TPS_1_2 = 0,
+	FE_TER_TPS_2_3 = 1,
+	FE_TER_TPS_3_4 = 2,
+	FE_TER_TPS_5_6 = 3,
+	FE_TER_TPS_7_8 = 4
+};
+#endif
+
+enum stv0367_ter_mode {
+	FE_TER_MODE_2K,
+	FE_TER_MODE_8K,
+	FE_TER_MODE_4K
+};
+#if 0
+enum FE_TER_Hierarchy_Alpha {
+	FE_TER_HIER_ALPHA_NONE,	/* Regular modulation */
+	FE_TER_HIER_ALPHA_1,	/* Hierarchical modulation a = 1*/
+	FE_TER_HIER_ALPHA_2,	/* Hierarchical modulation a = 2*/
+	FE_TER_HIER_ALPHA_4	/* Hierarchical modulation a = 4*/
+};
+#endif
+enum stv0367_ter_hierarchy {
+	FE_TER_HIER_NONE,	/*Hierarchy None*/
+	FE_TER_HIER_LOW_PRIO,	/*Hierarchy : Low Priority*/
+	FE_TER_HIER_HIGH_PRIO,	/*Hierarchy : High Priority*/
+	FE_TER_HIER_PRIO_ANY	/*Hierarchy  :Any*/
+};
+
+#if 0
+enum fe_stv0367_ter_spec {
+	FE_TER_INVERSION_NONE = 0,
+	FE_TER_INVERSION = 1,
+	FE_TER_INVERSION_AUTO = 2,
+	FE_TER_INVERSION_UNK  = 4
+};
+#endif
+
+enum stv0367_ter_if_iq_mode {
+	FE_TER_NORMAL_IF_TUNER = 0,
+	FE_TER_LONGPATH_IF_TUNER = 1,
+	FE_TER_IQ_TUNER = 2
+
+};
+
+#if 0
+enum FE_TER_FECRate {
+	FE_TER_FEC_NONE = 0x00,	/* no FEC rate specified */
+	FE_TER_FEC_ALL = 0xFF,	 /* Logical OR of all FECs */
+	FE_TER_FEC_1_2 = 1,
+	FE_TER_FEC_2_3 = (1 << 1),
+	FE_TER_FEC_3_4 = (1 << 2),
+	FE_TER_FEC_4_5 = (1 << 3),
+	FE_TER_FEC_5_6 = (1 << 4),
+	FE_TER_FEC_6_7 = (1 << 5),
+	FE_TER_FEC_7_8 = (1 << 6),
+	FE_TER_FEC_8_9 = (1 << 7)
+};
+
+enum FE_TER_Rate {
+	FE_TER_FE_1_2 = 0,
+	FE_TER_FE_2_3 = 1,
+	FE_TER_FE_3_4 = 2,
+	FE_TER_FE_5_6 = 3,
+	FE_TER_FE_6_7 = 4,
+	FE_TER_FE_7_8 = 5
+};
+#endif
+
+enum stv0367_ter_force {
+	FE_TER_FORCENONE = 0,
+	FE_TER_FORCE_M_G = 1
+};
+
+enum  stv0367cab_mod {
+	FE_CAB_MOD_QAM4,
+	FE_CAB_MOD_QAM16,
+	FE_CAB_MOD_QAM32,
+	FE_CAB_MOD_QAM64,
+	FE_CAB_MOD_QAM128,
+	FE_CAB_MOD_QAM256,
+	FE_CAB_MOD_QAM512,
+	FE_CAB_MOD_QAM1024
+};
+#if 0
+enum {
+	FE_CAB_FEC_A = 1,	/* J83 Annex A */
+	FE_CAB_FEC_B = (1 << 1),/* J83 Annex B */
+	FE_CAB_FEC_C = (1 << 2)	/* J83 Annex C */
+} FE_CAB_FECType_t;
+#endif
+struct stv0367_cab_signal_info {
+	int locked;
+	u32 frequency; /* kHz */
+	u32 symbol_rate; /* Mbds */
+	enum stv0367cab_mod modulation;
+	fe_spectral_inversion_t spect_inv;
+	s32 Power_dBmx10;	/* Power of the RF signal (dBm x 10) */
+	u32	CN_dBx10;	/* Carrier to noise ratio (dB x 10) */
+	u32	BER;		/* Bit error rate (x 10000000)	*/
+};
+
+enum stv0367_cab_signal_type {
+	FE_CAB_NOTUNER,
+	FE_CAB_NOAGC,
+	FE_CAB_NOSIGNAL,
+	FE_CAB_NOTIMING,
+	FE_CAB_TIMINGOK,
+	FE_CAB_NOCARRIER,
+	FE_CAB_CARRIEROK,
+	FE_CAB_NOBLIND,
+	FE_CAB_BLINDOK,
+	FE_CAB_NODEMOD,
+	FE_CAB_DEMODOK,
+	FE_CAB_DATAOK
+};
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367_regs.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367_regs.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0367_regs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0367_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3614 @@
+/*
+ * stv0367_regs.h
+ *
+ * Driver for ST STV0367 DVB-T & DVB-C demodulator IC.
+ *
+ * Copyright (C) ST Microelectronics.
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 STV0367_REGS_H
+#define STV0367_REGS_H
+
+/* ID */
+#define	R367TER_ID	0xf000
+#define	F367TER_IDENTIFICATIONREG	0xf00000ff
+
+/* I2CRPT */
+#define	R367TER_I2CRPT	0xf001
+#define	F367TER_I2CT_ON	0xf0010080
+#define	F367TER_ENARPT_LEVEL	0xf0010070
+#define	F367TER_SCLT_DELAY	0xf0010008
+#define	F367TER_SCLT_NOD	0xf0010004
+#define	F367TER_STOP_ENABLE	0xf0010002
+#define	F367TER_SDAT_NOD	0xf0010001
+
+/* TOPCTRL */
+#define	R367TER_TOPCTRL	0xf002
+#define	F367TER_STDBY	0xf0020080
+#define	F367TER_STDBY_FEC	0xf0020040
+#define	F367TER_STDBY_CORE	0xf0020020
+#define	F367TER_QAM_COFDM	0xf0020010
+#define	F367TER_TS_DIS	0xf0020008
+#define	F367TER_DIR_CLK_216	0xf0020004
+#define	F367TER_TUNER_BB	0xf0020002
+#define	F367TER_DVBT_H	0xf0020001
+
+/* IOCFG0 */
+#define	R367TER_IOCFG0	0xf003
+#define	F367TER_OP0_SD	0xf0030080
+#define	F367TER_OP0_VAL	0xf0030040
+#define	F367TER_OP0_OD	0xf0030020
+#define	F367TER_OP0_INV	0xf0030010
+#define	F367TER_OP0_DACVALUE_HI	0xf003000f
+
+/* DAc0R */
+#define	R367TER_DAC0R	0xf004
+#define	F367TER_OP0_DACVALUE_LO	0xf00400ff
+
+/* IOCFG1 */
+#define	R367TER_IOCFG1	0xf005
+#define	F367TER_IP0	0xf0050040
+#define	F367TER_OP1_OD	0xf0050020
+#define	F367TER_OP1_INV	0xf0050010
+#define	F367TER_OP1_DACVALUE_HI	0xf005000f
+
+/* DAC1R */
+#define	R367TER_DAC1R	0xf006
+#define	F367TER_OP1_DACVALUE_LO	0xf00600ff
+
+/* IOCFG2 */
+#define	R367TER_IOCFG2	0xf007
+#define	F367TER_OP2_LOCK_CONF	0xf00700e0
+#define	F367TER_OP2_OD	0xf0070010
+#define	F367TER_OP2_VAL	0xf0070008
+#define	F367TER_OP1_LOCK_CONF	0xf0070007
+
+/* SDFR */
+#define	R367TER_SDFR	0xf008
+#define	F367TER_OP0_FREQ	0xf00800f0
+#define	F367TER_OP1_FREQ	0xf008000f
+
+/* STATUS */
+#define	R367TER_STATUS	0xf009
+#define	F367TER_TPS_LOCK	0xf0090080
+#define	F367TER_SYR_LOCK	0xf0090040
+#define	F367TER_AGC_LOCK	0xf0090020
+#define	F367TER_PRF	0xf0090010
+#define	F367TER_LK	0xf0090008
+#define	F367TER_PR	0xf0090007
+
+/* AUX_CLK */
+#define	R367TER_AUX_CLK	0xf00a
+#define	F367TER_AUXFEC_CTL	0xf00a00c0
+#define	F367TER_DIS_CKX4	0xf00a0020
+#define	F367TER_CKSEL	0xf00a0018
+#define	F367TER_CKDIV_PROG	0xf00a0006
+#define	F367TER_AUXCLK_ENA	0xf00a0001
+
+/* FREESYS1 */
+#define	R367TER_FREESYS1	0xf00b
+#define	F367TER_FREE_SYS1	0xf00b00ff
+
+/* FREESYS2 */
+#define	R367TER_FREESYS2	0xf00c
+#define	F367TER_FREE_SYS2	0xf00c00ff
+
+/* FREESYS3 */
+#define	R367TER_FREESYS3	0xf00d
+#define	F367TER_FREE_SYS3	0xf00d00ff
+
+/* GPIO_CFG */
+#define	R367TER_GPIO_CFG	0xf00e
+#define	F367TER_GPIO7_NOD	0xf00e0080
+#define	F367TER_GPIO7_CFG	0xf00e0040
+#define	F367TER_GPIO6_NOD	0xf00e0020
+#define	F367TER_GPIO6_CFG	0xf00e0010
+#define	F367TER_GPIO5_NOD	0xf00e0008
+#define	F367TER_GPIO5_CFG	0xf00e0004
+#define	F367TER_GPIO4_NOD	0xf00e0002
+#define	F367TER_GPIO4_CFG	0xf00e0001
+
+/* GPIO_CMD */
+#define	R367TER_GPIO_CMD	0xf00f
+#define	F367TER_GPIO7_VAL	0xf00f0008
+#define	F367TER_GPIO6_VAL	0xf00f0004
+#define	F367TER_GPIO5_VAL	0xf00f0002
+#define	F367TER_GPIO4_VAL	0xf00f0001
+
+/* AGC2MAX */
+#define	R367TER_AGC2MAX	0xf010
+#define	F367TER_AGC2_MAX	0xf01000ff
+
+/* AGC2MIN */
+#define	R367TER_AGC2MIN	0xf011
+#define	F367TER_AGC2_MIN	0xf01100ff
+
+/* AGC1MAX */
+#define	R367TER_AGC1MAX	0xf012
+#define	F367TER_AGC1_MAX	0xf01200ff
+
+/* AGC1MIN */
+#define	R367TER_AGC1MIN	0xf013
+#define	F367TER_AGC1_MIN	0xf01300ff
+
+/* AGCR */
+#define	R367TER_AGCR	0xf014
+#define	F367TER_RATIO_A	0xf01400e0
+#define	F367TER_RATIO_B	0xf0140018
+#define	F367TER_RATIO_C	0xf0140007
+
+/* AGC2TH */
+#define	R367TER_AGC2TH	0xf015
+#define	F367TER_AGC2_THRES	0xf01500ff
+
+/* AGC12c */
+#define	R367TER_AGC12C	0xf016
+#define	F367TER_AGC1_IV	0xf0160080
+#define	F367TER_AGC1_OD	0xf0160040
+#define	F367TER_AGC1_LOAD	0xf0160020
+#define	F367TER_AGC2_IV	0xf0160010
+#define	F367TER_AGC2_OD	0xf0160008
+#define	F367TER_AGC2_LOAD	0xf0160004
+#define	F367TER_AGC12_MODE	0xf0160003
+
+/* AGCCTRL1 */
+#define	R367TER_AGCCTRL1	0xf017
+#define	F367TER_DAGC_ON	0xf0170080
+#define	F367TER_INVERT_AGC12	0xf0170040
+#define	F367TER_AGC1_MODE	0xf0170008
+#define	F367TER_AGC2_MODE	0xf0170007
+
+/* AGCCTRL2 */
+#define	R367TER_AGCCTRL2	0xf018
+#define	F367TER_FRZ2_CTRL	0xf0180060
+#define	F367TER_FRZ1_CTRL	0xf0180018
+#define	F367TER_TIME_CST	0xf0180007
+
+/* AGC1VAL1 */
+#define	R367TER_AGC1VAL1	0xf019
+#define	F367TER_AGC1_VAL_LO	0xf01900ff
+
+/* AGC1VAL2 */
+#define	R367TER_AGC1VAL2	0xf01a
+#define	F367TER_AGC1_VAL_HI	0xf01a000f
+
+/* AGC2VAL1 */
+#define	R367TER_AGC2VAL1	0xf01b
+#define	F367TER_AGC2_VAL_LO	0xf01b00ff
+
+/* AGC2VAL2 */
+#define	R367TER_AGC2VAL2	0xf01c
+#define	F367TER_AGC2_VAL_HI	0xf01c000f
+
+/* AGC2PGA */
+#define	R367TER_AGC2PGA	0xf01d
+#define	F367TER_AGC2_PGA	0xf01d00ff
+
+/* OVF_RATE1 */
+#define	R367TER_OVF_RATE1	0xf01e
+#define	F367TER_OVF_RATE_HI	0xf01e000f
+
+/* OVF_RATE2 */
+#define	R367TER_OVF_RATE2	0xf01f
+#define	F367TER_OVF_RATE_LO	0xf01f00ff
+
+/* GAIN_SRC1 */
+#define	R367TER_GAIN_SRC1	0xf020
+#define	F367TER_INV_SPECTR	0xf0200080
+#define	F367TER_IQ_INVERT	0xf0200040
+#define	F367TER_INR_BYPASS	0xf0200020
+#define	F367TER_STATUS_INV_SPECRUM	0xf0200010
+#define	F367TER_GAIN_SRC_HI	0xf020000f
+
+/* GAIN_SRC2 */
+#define	R367TER_GAIN_SRC2	0xf021
+#define	F367TER_GAIN_SRC_LO	0xf02100ff
+
+/* INC_DEROT1 */
+#define	R367TER_INC_DEROT1	0xf022
+#define	F367TER_INC_DEROT_HI	0xf02200ff
+
+/* INC_DEROT2 */
+#define	R367TER_INC_DEROT2	0xf023
+#define	F367TER_INC_DEROT_LO	0xf02300ff
+
+/* PPM_CPAMP_DIR */
+#define	R367TER_PPM_CPAMP_DIR	0xf024
+#define	F367TER_PPM_CPAMP_DIRECT	0xf02400ff
+
+/* PPM_CPAMP_INV */
+#define	R367TER_PPM_CPAMP_INV	0xf025
+#define	F367TER_PPM_CPAMP_INVER	0xf02500ff
+
+/* FREESTFE_1 */
+#define	R367TER_FREESTFE_1	0xf026
+#define	F367TER_SYMBOL_NUMBER_INC	0xf02600c0
+#define	F367TER_SEL_LSB	0xf0260004
+#define	F367TER_AVERAGE_ON	0xf0260002
+#define	F367TER_DC_ADJ	0xf0260001
+
+/* FREESTFE_2 */
+#define	R367TER_FREESTFE_2	0xf027
+#define	F367TER_SEL_SRCOUT	0xf02700c0
+#define	F367TER_SEL_SYRTHR	0xf027001f
+
+/* DCOFFSET */
+#define	R367TER_DCOFFSET	0xf028
+#define	F367TER_SELECT_I_Q	0xf0280080
+#define	F367TER_DC_OFFSET	0xf028007f
+
+/* EN_PROCESS */
+#define	R367TER_EN_PROCESS	0xf029
+#define	F367TER_FREE	0xf02900f0
+#define	F367TER_ENAB_MANUAL	0xf0290001
+
+/* SDI_SMOOTHER */
+#define	R367TER_SDI_SMOOTHER	0xf02a
+#define	F367TER_DIS_SMOOTH	0xf02a0080
+#define	F367TER_SDI_INC_SMOOTHER	0xf02a007f
+
+/* FE_LOOP_OPEN */
+#define	R367TER_FE_LOOP_OPEN	0xf02b
+#define	F367TER_TRL_LOOP_OP	0xf02b0002
+#define	F367TER_CRL_LOOP_OP	0xf02b0001
+
+/* FREQOFF1 */
+#define	R367TER_FREQOFF1	0xf02c
+#define	F367TER_FREQ_OFFSET_LOOP_OPEN_VHI	0xf02c00ff
+
+/* FREQOFF2 */
+#define	R367TER_FREQOFF2	0xf02d
+#define	F367TER_FREQ_OFFSET_LOOP_OPEN_HI	0xf02d00ff
+
+/* FREQOFF3 */
+#define	R367TER_FREQOFF3	0xf02e
+#define	F367TER_FREQ_OFFSET_LOOP_OPEN_LO	0xf02e00ff
+
+/* TIMOFF1 */
+#define	R367TER_TIMOFF1	0xf02f
+#define	F367TER_TIM_OFFSET_LOOP_OPEN_HI	0xf02f00ff
+
+/* TIMOFF2 */
+#define	R367TER_TIMOFF2	0xf030
+#define	F367TER_TIM_OFFSET_LOOP_OPEN_LO	0xf03000ff
+
+/* EPQ */
+#define	R367TER_EPQ	0xf031
+#define	F367TER_EPQ1	0xf03100ff
+
+/* EPQAUTO */
+#define	R367TER_EPQAUTO	0xf032
+#define	F367TER_EPQ2	0xf03200ff
+
+/* SYR_UPDATE */
+#define	R367TER_SYR_UPDATE	0xf033
+#define	F367TER_SYR_PROTV	0xf0330080
+#define	F367TER_SYR_PROTV_GAIN	0xf0330060
+#define	F367TER_SYR_FILTER	0xf0330010
+#define	F367TER_SYR_TRACK_THRES	0xf033000c
+
+/* CHPFREE */
+#define	R367TER_CHPFREE	0xf034
+#define	F367TER_CHP_FREE	0xf03400ff
+
+/* PPM_STATE_MAC */
+#define	R367TER_PPM_STATE_MAC	0xf035
+#define	F367TER_PPM_STATE_MACHINE_DECODER	0xf035003f
+
+/* INR_THRESHOLD */
+#define	R367TER_INR_THRESHOLD	0xf036
+#define	F367TER_INR_THRESH	0xf03600ff
+
+/* EPQ_TPS_ID_CELL */
+#define	R367TER_EPQ_TPS_ID_CELL	0xf037
+#define	F367TER_ENABLE_LGTH_TO_CF	0xf0370080
+#define	F367TER_DIS_TPS_RSVD	0xf0370040
+#define	F367TER_DIS_BCH	0xf0370020
+#define	F367TER_DIS_ID_CEL	0xf0370010
+#define	F367TER_TPS_ADJUST_SYM	0xf037000f
+
+/* EPQ_CFG */
+#define	R367TER_EPQ_CFG	0xf038
+#define	F367TER_EPQ_RANGE	0xf0380002
+#define	F367TER_EPQ_SOFT	0xf0380001
+
+/* EPQ_STATUS */
+#define	R367TER_EPQ_STATUS	0xf039
+#define	F367TER_SLOPE_INC	0xf03900fc
+#define	F367TER_TPS_FIELD	0xf0390003
+
+/* AUTORELOCK */
+#define	R367TER_AUTORELOCK	0xf03a
+#define	F367TER_BYPASS_BER_TEMPO	0xf03a0080
+#define	F367TER_BER_TEMPO	0xf03a0070
+#define	F367TER_BYPASS_COFDM_TEMPO	0xf03a0008
+#define	F367TER_COFDM_TEMPO	0xf03a0007
+
+/* BER_THR_VMSB */
+#define	R367TER_BER_THR_VMSB	0xf03b
+#define	F367TER_BER_THRESHOLD_HI	0xf03b00ff
+
+/* BER_THR_MSB */
+#define	R367TER_BER_THR_MSB	0xf03c
+#define	F367TER_BER_THRESHOLD_MID	0xf03c00ff
+
+/* BER_THR_LSB */
+#define	R367TER_BER_THR_LSB	0xf03d
+#define	F367TER_BER_THRESHOLD_LO	0xf03d00ff
+
+/* CCD */
+#define	R367TER_CCD	0xf03e
+#define	F367TER_CCD_DETECTED	0xf03e0080
+#define	F367TER_CCD_RESET	0xf03e0040
+#define	F367TER_CCD_THRESHOLD	0xf03e000f
+
+/* SPECTR_CFG */
+#define	R367TER_SPECTR_CFG	0xf03f
+#define	F367TER_SPECT_CFG	0xf03f0003
+
+/* CONSTMU_MSB */
+#define	R367TER_CONSTMU_MSB	0xf040
+#define	F367TER_CONSTMU_FREEZE	0xf0400080
+#define	F367TER_CONSTNU_FORCE_EN	0xf0400040
+#define	F367TER_CONST_MU_MSB	0xf040003f
+
+/* CONSTMU_LSB */
+#define	R367TER_CONSTMU_LSB	0xf041
+#define	F367TER_CONST_MU_LSB	0xf04100ff
+
+/* CONSTMU_MAX_MSB */
+#define	R367TER_CONSTMU_MAX_MSB	0xf042
+#define	F367TER_CONST_MU_MAX_MSB	0xf042003f
+
+/* CONSTMU_MAX_LSB */
+#define	R367TER_CONSTMU_MAX_LSB	0xf043
+#define	F367TER_CONST_MU_MAX_LSB	0xf04300ff
+
+/* ALPHANOISE */
+#define	R367TER_ALPHANOISE	0xf044
+#define	F367TER_USE_ALLFILTER	0xf0440080
+#define	F367TER_INTER_ON	0xf0440040
+#define	F367TER_ALPHA_NOISE	0xf044001f
+
+/* MAXGP_MSB */
+#define	R367TER_MAXGP_MSB	0xf045
+#define	F367TER_MUFILTER_LENGTH	0xf04500f0
+#define	F367TER_MAX_GP_MSB	0xf045000f
+
+/* MAXGP_LSB */
+#define	R367TER_MAXGP_LSB	0xf046
+#define	F367TER_MAX_GP_LSB	0xf04600ff
+
+/* ALPHAMSB */
+#define	R367TER_ALPHAMSB	0xf047
+#define	F367TER_CHC_DATARATE	0xf04700c0
+#define	F367TER_ALPHA_MSB	0xf047003f
+
+/* ALPHALSB */
+#define	R367TER_ALPHALSB	0xf048
+#define	F367TER_ALPHA_LSB	0xf04800ff
+
+/* PILOT_ACCU */
+#define	R367TER_PILOT_ACCU	0xf049
+#define	F367TER_USE_SCAT4ADDAPT	0xf0490080
+#define	F367TER_PILOT_ACC	0xf049001f
+
+/* PILOTMU_ACCU */
+#define	R367TER_PILOTMU_ACCU	0xf04a
+#define	F367TER_DISCARD_BAD_SP	0xf04a0080
+#define	F367TER_DISCARD_BAD_CP	0xf04a0040
+#define	F367TER_PILOT_MU_ACCU	0xf04a001f
+
+/* FILT_CHANNEL_EST */
+#define	R367TER_FILT_CHANNEL_EST	0xf04b
+#define	F367TER_USE_FILT_PILOT	0xf04b0080
+#define	F367TER_FILT_CHANNEL	0xf04b007f
+
+/* ALPHA_NOPISE_FREQ */
+#define	R367TER_ALPHA_NOPISE_FREQ	0xf04c
+#define	F367TER_NOISE_FREQ_FILT	0xf04c0040
+#define	F367TER_ALPHA_NOISE_FREQ	0xf04c003f
+
+/* RATIO_PILOT */
+#define	R367TER_RATIO_PILOT	0xf04d
+#define	F367TER_RATIO_MEAN_SP	0xf04d00f0
+#define	F367TER_RATIO_MEAN_CP	0xf04d000f
+
+/* CHC_CTL */
+#define	R367TER_CHC_CTL	0xf04e
+#define	F367TER_TRACK_EN	0xf04e0080
+#define	F367TER_NOISE_NORM_EN	0xf04e0040
+#define	F367TER_FORCE_CHC_RESET	0xf04e0020
+#define	F367TER_SHORT_TIME	0xf04e0010
+#define	F367TER_FORCE_STATE_EN	0xf04e0008
+#define	F367TER_FORCE_STATE	0xf04e0007
+
+/* EPQ_ADJUST */
+#define	R367TER_EPQ_ADJUST	0xf04f
+#define	F367TER_ADJUST_SCAT_IND	0xf04f00c0
+#define	F367TER_ONE_SYMBOL	0xf04f0010
+#define	F367TER_EPQ_DECAY	0xf04f000e
+#define	F367TER_HOLD_SLOPE	0xf04f0001
+
+/* EPQ_THRES */
+#define	R367TER_EPQ_THRES	0xf050
+#define	F367TER_EPQ_THR	0xf05000ff
+
+/* OMEGA_CTL */
+#define	R367TER_OMEGA_CTL	0xf051
+#define	F367TER_OMEGA_RST	0xf0510080
+#define	F367TER_FREEZE_OMEGA	0xf0510040
+#define	F367TER_OMEGA_SEL	0xf051003f
+
+/* GP_CTL */
+#define	R367TER_GP_CTL	0xf052
+#define	F367TER_CHC_STATE	0xf05200e0
+#define	F367TER_FREEZE_GP	0xf0520010
+#define	F367TER_GP_SEL	0xf052000f
+
+/* MUMSB */
+#define	R367TER_MUMSB	0xf053
+#define	F367TER_MU_MSB	0xf053007f
+
+/* MULSB */
+#define	R367TER_MULSB	0xf054
+#define	F367TER_MU_LSB	0xf05400ff
+
+/* GPMSB */
+#define	R367TER_GPMSB	0xf055
+#define	F367TER_CSI_THRESHOLD	0xf05500e0
+#define	F367TER_GP_MSB	0xf055000f
+
+/* GPLSB */
+#define	R367TER_GPLSB	0xf056
+#define	F367TER_GP_LSB	0xf05600ff
+
+/* OMEGAMSB */
+#define	R367TER_OMEGAMSB	0xf057
+#define	F367TER_OMEGA_MSB	0xf057007f
+
+/* OMEGALSB */
+#define	R367TER_OMEGALSB	0xf058
+#define	F367TER_OMEGA_LSB	0xf05800ff
+
+/* SCAT_NB */
+#define	R367TER_SCAT_NB	0xf059
+#define	F367TER_CHC_TEST	0xf05900f8
+#define	F367TER_SCAT_NUMB	0xf0590003
+
+/* CHC_DUMMY */
+#define	R367TER_CHC_DUMMY	0xf05a
+#define	F367TER_CHC_DUM	0xf05a00ff
+
+/* INC_CTL */
+#define	R367TER_INC_CTL	0xf05b
+#define	F367TER_INC_BYPASS	0xf05b0080
+#define	F367TER_INC_NDEPTH	0xf05b000c
+#define	F367TER_INC_MADEPTH	0xf05b0003
+
+/* INCTHRES_COR1 */
+#define	R367TER_INCTHRES_COR1	0xf05c
+#define	F367TER_INC_THRES_COR1	0xf05c00ff
+
+/* INCTHRES_COR2 */
+#define	R367TER_INCTHRES_COR2	0xf05d
+#define	F367TER_INC_THRES_COR2	0xf05d00ff
+
+/* INCTHRES_DET1 */
+#define	R367TER_INCTHRES_DET1	0xf05e
+#define	F367TER_INC_THRES_DET1	0xf05e003f
+
+/* INCTHRES_DET2 */
+#define	R367TER_INCTHRES_DET2	0xf05f
+#define	F367TER_INC_THRES_DET2	0xf05f003f
+
+/* IIR_CELLNB */
+#define	R367TER_IIR_CELLNB	0xf060
+#define	F367TER_NRST_IIR	0xf0600080
+#define	F367TER_IIR_CELL_NB	0xf0600007
+
+/* IIRCX_COEFF1_MSB */
+#define	R367TER_IIRCX_COEFF1_MSB	0xf061
+#define	F367TER_IIR_CX_COEFF1_MSB	0xf06100ff
+
+/* IIRCX_COEFF1_LSB */
+#define	R367TER_IIRCX_COEFF1_LSB	0xf062
+#define	F367TER_IIR_CX_COEFF1_LSB	0xf06200ff
+
+/* IIRCX_COEFF2_MSB */
+#define	R367TER_IIRCX_COEFF2_MSB	0xf063
+#define	F367TER_IIR_CX_COEFF2_MSB	0xf06300ff
+
+/* IIRCX_COEFF2_LSB */
+#define	R367TER_IIRCX_COEFF2_LSB	0xf064
+#define	F367TER_IIR_CX_COEFF2_LSB	0xf06400ff
+
+/* IIRCX_COEFF3_MSB */
+#define	R367TER_IIRCX_COEFF3_MSB	0xf065
+#define	F367TER_IIR_CX_COEFF3_MSB	0xf06500ff
+
+/* IIRCX_COEFF3_LSB */
+#define	R367TER_IIRCX_COEFF3_LSB	0xf066
+#define	F367TER_IIR_CX_COEFF3_LSB	0xf06600ff
+
+/* IIRCX_COEFF4_MSB */
+#define	R367TER_IIRCX_COEFF4_MSB	0xf067
+#define	F367TER_IIR_CX_COEFF4_MSB	0xf06700ff
+
+/* IIRCX_COEFF4_LSB */
+#define	R367TER_IIRCX_COEFF4_LSB	0xf068
+#define	F367TER_IIR_CX_COEFF4_LSB	0xf06800ff
+
+/* IIRCX_COEFF5_MSB */
+#define	R367TER_IIRCX_COEFF5_MSB	0xf069
+#define	F367TER_IIR_CX_COEFF5_MSB	0xf06900ff
+
+/* IIRCX_COEFF5_LSB */
+#define	R367TER_IIRCX_COEFF5_LSB	0xf06a
+#define	F367TER_IIR_CX_COEFF5_LSB	0xf06a00ff
+
+/* FEPATH_CFG */
+#define	R367TER_FEPATH_CFG	0xf06b
+#define	F367TER_DEMUX_SWAP	0xf06b0004
+#define	F367TER_DIGAGC_SWAP	0xf06b0002
+#define	F367TER_LONGPATH_IF	0xf06b0001
+
+/* PMC1_FUNC */
+#define	R367TER_PMC1_FUNC	0xf06c
+#define	F367TER_SOFT_RSTN	0xf06c0080
+#define	F367TER_PMC1_AVERAGE_TIME	0xf06c0078
+#define	F367TER_PMC1_WAIT_TIME	0xf06c0006
+#define	F367TER_PMC1_2N_SEL	0xf06c0001
+
+/* PMC1_FOR */
+#define	R367TER_PMC1_FOR	0xf06d
+#define	F367TER_PMC1_FORCE	0xf06d0080
+#define	F367TER_PMC1_FORCE_VALUE	0xf06d007c
+
+/* PMC2_FUNC */
+#define	R367TER_PMC2_FUNC	0xf06e
+#define	F367TER_PMC2_SOFT_STN	0xf06e0080
+#define	F367TER_PMC2_ACCU_TIME	0xf06e0070
+#define	F367TER_PMC2_CMDP_MN	0xf06e0008
+#define	F367TER_PMC2_SWAP	0xf06e0004
+
+/* STATUS_ERR_DA */
+#define	R367TER_STATUS_ERR_DA	0xf06f
+#define	F367TER_COM_USEGAINTRK	0xf06f0080
+#define	F367TER_COM_AGCLOCK	0xf06f0040
+#define	F367TER_AUT_AGCLOCK	0xf06f0020
+#define	F367TER_MIN_ERR_X_LSB	0xf06f000f
+
+/* DIG_AGC_R */
+#define	R367TER_DIG_AGC_R	0xf070
+#define	F367TER_COM_SOFT_RSTN	0xf0700080
+#define	F367TER_COM_AGC_ON	0xf0700040
+#define	F367TER_COM_EARLY	0xf0700020
+#define	F367TER_AUT_SOFT_RESETN	0xf0700010
+#define	F367TER_AUT_AGC_ON	0xf0700008
+#define	F367TER_AUT_EARLY	0xf0700004
+#define	F367TER_AUT_ROT_EN	0xf0700002
+#define	F367TER_LOCK_SOFT_RESETN	0xf0700001
+
+/* COMAGC_TARMSB */
+#define	R367TER_COMAGC_TARMSB	0xf071
+#define	F367TER_COM_AGC_TARGET_MSB	0xf07100ff
+
+/* COM_AGC_TAR_ENMODE */
+#define	R367TER_COM_AGC_TAR_ENMODE	0xf072
+#define	F367TER_COM_AGC_TARGET_LSB	0xf07200f0
+#define	F367TER_COM_ENMODE	0xf072000f
+
+/* COM_AGC_CFG */
+#define	R367TER_COM_AGC_CFG	0xf073
+#define	F367TER_COM_N	0xf07300f8
+#define	F367TER_COM_STABMODE	0xf0730006
+#define	F367TER_ERR_SEL	0xf0730001
+
+/* COM_AGC_GAIN1 */
+#define	R367TER_COM_AGC_GAIN1	0xf074
+#define	F367TER_COM_GAIN1aCK	0xf07400f0
+#define	F367TER_COM_GAIN1TRK	0xf074000f
+
+/* AUT_AGC_TARGETMSB */
+#define	R367TER_AUT_AGC_TARGETMSB	0xf075
+#define	F367TER_AUT_AGC_TARGET_MSB	0xf07500ff
+
+/* LOCK_DET_MSB */
+#define	R367TER_LOCK_DET_MSB	0xf076
+#define	F367TER_LOCK_DETECT_MSB	0xf07600ff
+
+/* AGCTAR_LOCK_LSBS */
+#define	R367TER_AGCTAR_LOCK_LSBS	0xf077
+#define	F367TER_AUT_AGC_TARGET_LSB	0xf07700f0
+#define	F367TER_LOCK_DETECT_LSB	0xf077000f
+
+/* AUT_GAIN_EN */
+#define	R367TER_AUT_GAIN_EN	0xf078
+#define	F367TER_AUT_ENMODE	0xf07800f0
+#define	F367TER_AUT_GAIN2	0xf078000f
+
+/* AUT_CFG */
+#define	R367TER_AUT_CFG	0xf079
+#define	F367TER_AUT_N	0xf07900f8
+#define	F367TER_INT_CHOICE	0xf0790006
+#define	F367TER_INT_LOAD	0xf0790001
+
+/* LOCKN */
+#define	R367TER_LOCKN	0xf07a
+#define	F367TER_LOCK_N	0xf07a00f8
+#define	F367TER_SEL_IQNTAR	0xf07a0004
+#define	F367TER_LOCK_DETECT_CHOICE	0xf07a0003
+
+/* INT_X_3 */
+#define	R367TER_INT_X_3	0xf07b
+#define	F367TER_INT_X3	0xf07b00ff
+
+/* INT_X_2 */
+#define	R367TER_INT_X_2	0xf07c
+#define	F367TER_INT_X2	0xf07c00ff
+
+/* INT_X_1 */
+#define	R367TER_INT_X_1	0xf07d
+#define	F367TER_INT_X1	0xf07d00ff
+
+/* INT_X_0 */
+#define	R367TER_INT_X_0	0xf07e
+#define	F367TER_INT_X0	0xf07e00ff
+
+/* MIN_ERRX_MSB */
+#define	R367TER_MIN_ERRX_MSB	0xf07f
+#define	F367TER_MIN_ERR_X_MSB	0xf07f00ff
+
+/* COR_CTL */
+#define	R367TER_COR_CTL	0xf080
+#define	F367TER_CORE_ACTIVE	0xf0800020
+#define	F367TER_HOLD	0xf0800010
+#define	F367TER_CORE_STATE_CTL	0xf080000f
+
+/* COR_STAT */
+#define	R367TER_COR_STAT	0xf081
+#define	F367TER_SCATT_LOCKED	0xf0810080
+#define	F367TER_TPS_LOCKED	0xf0810040
+#define	F367TER_SYR_LOCKED_COR	0xf0810020
+#define	F367TER_AGC_LOCKED_STAT	0xf0810010
+#define	F367TER_CORE_STATE_STAT	0xf081000f
+
+/* COR_INTEN */
+#define	R367TER_COR_INTEN	0xf082
+#define	F367TER_INTEN	0xf0820080
+#define	F367TER_INTEN_SYR	0xf0820020
+#define	F367TER_INTEN_FFT	0xf0820010
+#define	F367TER_INTEN_AGC	0xf0820008
+#define	F367TER_INTEN_TPS1	0xf0820004
+#define	F367TER_INTEN_TPS2	0xf0820002
+#define	F367TER_INTEN_TPS3	0xf0820001
+
+/* COR_INTSTAT */
+#define	R367TER_COR_INTSTAT	0xf083
+#define	F367TER_INTSTAT_SYR	0xf0830020
+#define	F367TER_INTSTAT_FFT	0xf0830010
+#define	F367TER_INTSAT_AGC	0xf0830008
+#define	F367TER_INTSTAT_TPS1	0xf0830004
+#define	F367TER_INTSTAT_TPS2	0xf0830002
+#define	F367TER_INTSTAT_TPS3	0xf0830001
+
+/* COR_MODEGUARD */
+#define	R367TER_COR_MODEGUARD	0xf084
+#define	F367TER_FORCE	0xf0840010
+#define	F367TER_MODE	0xf084000c
+#define	F367TER_GUARD	0xf0840003
+
+/* AGC_CTL */
+#define	R367TER_AGC_CTL	0xf085
+#define	F367TER_AGC_TIMING_FACTOR	0xf08500e0
+#define	F367TER_AGC_LAST	0xf0850010
+#define	F367TER_AGC_GAIN	0xf085000c
+#define	F367TER_AGC_NEG	0xf0850002
+#define	F367TER_AGC_SET	0xf0850001
+
+/* AGC_MANUAL1 */
+#define	R367TER_AGC_MANUAL1	0xf086
+#define	F367TER_AGC_VAL_LO	0xf08600ff
+
+/* AGC_MANUAL2 */
+#define	R367TER_AGC_MANUAL2	0xf087
+#define	F367TER_AGC_VAL_HI	0xf087000f
+
+/* AGC_TARG */
+#define	R367TER_AGC_TARG	0xf088
+#define	F367TER_AGC_TARGET	0xf08800ff
+
+/* AGC_GAIN1 */
+#define	R367TER_AGC_GAIN1	0xf089
+#define	F367TER_AGC_GAIN_LO	0xf08900ff
+
+/* AGC_GAIN2 */
+#define	R367TER_AGC_GAIN2	0xf08a
+#define	F367TER_AGC_LOCKED_GAIN2	0xf08a0010
+#define	F367TER_AGC_GAIN_HI	0xf08a000f
+
+/* RESERVED_1 */
+#define	R367TER_RESERVED_1	0xf08b
+#define	F367TER_RESERVED1	0xf08b00ff
+
+/* RESERVED_2 */
+#define	R367TER_RESERVED_2	0xf08c
+#define	F367TER_RESERVED2	0xf08c00ff
+
+/* RESERVED_3 */
+#define	R367TER_RESERVED_3	0xf08d
+#define	F367TER_RESERVED3	0xf08d00ff
+
+/* CAS_CTL */
+#define	R367TER_CAS_CTL	0xf08e
+#define	F367TER_CCS_ENABLE	0xf08e0080
+#define	F367TER_ACS_DISABLE	0xf08e0040
+#define	F367TER_DAGC_DIS	0xf08e0020
+#define	F367TER_DAGC_GAIN	0xf08e0018
+#define	F367TER_CCSMU	0xf08e0007
+
+/* CAS_FREQ */
+#define	R367TER_CAS_FREQ	0xf08f
+#define	F367TER_CCS_FREQ	0xf08f00ff
+
+/* CAS_DAGCGAIN */
+#define	R367TER_CAS_DAGCGAIN	0xf090
+#define	F367TER_CAS_DAGC_GAIN	0xf09000ff
+
+/* SYR_CTL */
+#define	R367TER_SYR_CTL	0xf091
+#define	F367TER_SICTH_ENABLE	0xf0910080
+#define	F367TER_LONG_ECHO	0xf0910078
+#define	F367TER_AUTO_LE_EN	0xf0910004
+#define	F367TER_SYR_BYPASS	0xf0910002
+#define	F367TER_SYR_TR_DIS	0xf0910001
+
+/* SYR_STAT */
+#define	R367TER_SYR_STAT	0xf092
+#define	F367TER_SYR_LOCKED_STAT	0xf0920010
+#define	F367TER_SYR_MODE	0xf092000c
+#define	F367TER_SYR_GUARD	0xf0920003
+
+/* SYR_NCO1 */
+#define	R367TER_SYR_NCO1	0xf093
+#define	F367TER_SYR_NCO_LO	0xf09300ff
+
+/* SYR_NCO2 */
+#define	R367TER_SYR_NCO2	0xf094
+#define	F367TER_SYR_NCO_HI	0xf094003f
+
+/* SYR_OFFSET1 */
+#define	R367TER_SYR_OFFSET1	0xf095
+#define	F367TER_SYR_OFFSET_LO	0xf09500ff
+
+/* SYR_OFFSET2 */
+#define	R367TER_SYR_OFFSET2	0xf096
+#define	F367TER_SYR_OFFSET_HI	0xf096003f
+
+/* FFT_CTL */
+#define	R367TER_FFT_CTL	0xf097
+#define	F367TER_SHIFT_FFT_TRIG	0xf0970018
+#define	F367TER_FFT_TRIGGER	0xf0970004
+#define	F367TER_FFT_MANUAL	0xf0970002
+#define	F367TER_IFFT_MODE	0xf0970001
+
+/* SCR_CTL */
+#define	R367TER_SCR_CTL	0xf098
+#define	F367TER_SYRADJDECAY	0xf0980070
+#define	F367TER_SCR_CPEDIS	0xf0980002
+#define	F367TER_SCR_DIS	0xf0980001
+
+/* PPM_CTL1 */
+#define	R367TER_PPM_CTL1	0xf099
+#define	F367TER_PPM_MAXFREQ	0xf0990030
+#define	F367TER_PPM_MAXTIM	0xf0990008
+#define	F367TER_PPM_INVSEL	0xf0990004
+#define	F367TER_PPM_SCATDIS	0xf0990002
+#define	F367TER_PPM_BYP	0xf0990001
+
+/* TRL_CTL */
+#define	R367TER_TRL_CTL	0xf09a
+#define	F367TER_TRL_NOMRATE_LSB	0xf09a0080
+#define	F367TER_TRL_GAIN_FACTOR	0xf09a0078
+#define	F367TER_TRL_LOOPGAIN	0xf09a0007
+
+/* TRL_NOMRATE1 */
+#define	R367TER_TRL_NOMRATE1	0xf09b
+#define	F367TER_TRL_NOMRATE_LO	0xf09b00ff
+
+/* TRL_NOMRATE2 */
+#define	R367TER_TRL_NOMRATE2	0xf09c
+#define	F367TER_TRL_NOMRATE_HI	0xf09c00ff
+
+/* TRL_TIME1 */
+#define	R367TER_TRL_TIME1	0xf09d
+#define	F367TER_TRL_TOFFSET_LO	0xf09d00ff
+
+/* TRL_TIME2 */
+#define	R367TER_TRL_TIME2	0xf09e
+#define	F367TER_TRL_TOFFSET_HI	0xf09e00ff
+
+/* CRL_CTL */
+#define	R367TER_CRL_CTL	0xf09f
+#define	F367TER_CRL_DIS	0xf09f0080
+#define	F367TER_CRL_GAIN_FACTOR	0xf09f0078
+#define	F367TER_CRL_LOOPGAIN	0xf09f0007
+
+/* CRL_FREQ1 */
+#define	R367TER_CRL_FREQ1	0xf0a0
+#define	F367TER_CRL_FOFFSET_LO	0xf0a000ff
+
+/* CRL_FREQ2 */
+#define	R367TER_CRL_FREQ2	0xf0a1
+#define	F367TER_CRL_FOFFSET_HI	0xf0a100ff
+
+/* CRL_FREQ3 */
+#define	R367TER_CRL_FREQ3	0xf0a2
+#define	F367TER_CRL_FOFFSET_VHI	0xf0a200ff
+
+/* TPS_SFRAME_CTL */
+#define	R367TER_TPS_SFRAME_CTL	0xf0a3
+#define	F367TER_TPS_SFRAME_SYNC	0xf0a30001
+
+/* CHC_SNR */
+#define	R367TER_CHC_SNR	0xf0a4
+#define	F367TER_CHCSNR	0xf0a400ff
+
+/* BDI_CTL */
+#define	R367TER_BDI_CTL	0xf0a5
+#define	F367TER_BDI_LPSEL	0xf0a50002
+#define	F367TER_BDI_SERIAL	0xf0a50001
+
+/* DMP_CTL */
+#define	R367TER_DMP_CTL	0xf0a6
+#define	F367TER_DMP_SCALING_FACTOR	0xf0a6001e
+#define	F367TER_DMP_SDDIS	0xf0a60001
+
+/* TPS_RCVD1 */
+#define	R367TER_TPS_RCVD1	0xf0a7
+#define	F367TER_TPS_CHANGE	0xf0a70040
+#define	F367TER_BCH_OK	0xf0a70020
+#define	F367TER_TPS_SYNC	0xf0a70010
+#define	F367TER_TPS_FRAME	0xf0a70003
+
+/* TPS_RCVD2 */
+#define	R367TER_TPS_RCVD2	0xf0a8
+#define	F367TER_TPS_HIERMODE	0xf0a80070
+#define	F367TER_TPS_CONST	0xf0a80003
+
+/* TPS_RCVD3 */
+#define	R367TER_TPS_RCVD3	0xf0a9
+#define	F367TER_TPS_LPCODE	0xf0a90070
+#define	F367TER_TPS_HPCODE	0xf0a90007
+
+/* TPS_RCVD4 */
+#define	R367TER_TPS_RCVD4	0xf0aa
+#define	F367TER_TPS_GUARD	0xf0aa0030
+#define	F367TER_TPS_MODE	0xf0aa0003
+
+/* TPS_ID_CELL1 */
+#define	R367TER_TPS_ID_CELL1	0xf0ab
+#define	F367TER_TPS_ID_CELL_LO	0xf0ab00ff
+
+/* TPS_ID_CELL2 */
+#define	R367TER_TPS_ID_CELL2	0xf0ac
+#define	F367TER_TPS_ID_CELL_HI	0xf0ac00ff
+
+/* TPS_RCVD5_SET1 */
+#define	R367TER_TPS_RCVD5_SET1	0xf0ad
+#define	F367TER_TPS_NA	0xf0ad00fC
+#define	F367TER_TPS_SETFRAME	0xf0ad0003
+
+/* TPS_SET2 */
+#define	R367TER_TPS_SET2	0xf0ae
+#define	F367TER_TPS_SETHIERMODE	0xf0ae0070
+#define	F367TER_TPS_SETCONST	0xf0ae0003
+
+/* TPS_SET3 */
+#define	R367TER_TPS_SET3	0xf0af
+#define	F367TER_TPS_SETLPCODE	0xf0af0070
+#define	F367TER_TPS_SETHPCODE	0xf0af0007
+
+/* TPS_CTL */
+#define	R367TER_TPS_CTL	0xf0b0
+#define	F367TER_TPS_IMM	0xf0b00004
+#define	F367TER_TPS_BCHDIS	0xf0b00002
+#define	F367TER_TPS_UPDDIS	0xf0b00001
+
+/* CTL_FFTOSNUM */
+#define	R367TER_CTL_FFTOSNUM	0xf0b1
+#define	F367TER_SYMBOL_NUMBER	0xf0b1007f
+
+/* TESTSELECT */
+#define	R367TER_TESTSELECT	0xf0b2
+#define	F367TER_TEST_SELECT	0xf0b2001f
+
+/* MSC_REV */
+#define	R367TER_MSC_REV	0xf0b3
+#define	F367TER_REV_NUMBER	0xf0b300ff
+
+/* PIR_CTL */
+#define	R367TER_PIR_CTL	0xf0b4
+#define	F367TER_FREEZE	0xf0b40001
+
+/* SNR_CARRIER1 */
+#define	R367TER_SNR_CARRIER1	0xf0b5
+#define	F367TER_SNR_CARRIER_LO	0xf0b500ff
+
+/* SNR_CARRIER2 */
+#define	R367TER_SNR_CARRIER2	0xf0b6
+#define	F367TER_MEAN	0xf0b600c0
+#define	F367TER_SNR_CARRIER_HI	0xf0b6001f
+
+/* PPM_CPAMP */
+#define	R367TER_PPM_CPAMP	0xf0b7
+#define	F367TER_PPM_CPC	0xf0b700ff
+
+/* TSM_AP0 */
+#define	R367TER_TSM_AP0	0xf0b8
+#define	F367TER_ADDRESS_BYTE_0	0xf0b800ff
+
+/* TSM_AP1 */
+#define	R367TER_TSM_AP1	0xf0b9
+#define	F367TER_ADDRESS_BYTE_1	0xf0b900ff
+
+/* TSM_AP2 */
+#define	R367TER_TSM_AP2	0xf0bA
+#define	F367TER_DATA_BYTE_0	0xf0ba00ff
+
+/* TSM_AP3 */
+#define	R367TER_TSM_AP3	0xf0bB
+#define	F367TER_DATA_BYTE_1	0xf0bb00ff
+
+/* TSM_AP4 */
+#define	R367TER_TSM_AP4	0xf0bC
+#define	F367TER_DATA_BYTE_2	0xf0bc00ff
+
+/* TSM_AP5 */
+#define	R367TER_TSM_AP5	0xf0bD
+#define	F367TER_DATA_BYTE_3	0xf0bd00ff
+
+/* TSM_AP6 */
+#define	R367TER_TSM_AP6	0xf0bE
+#define	F367TER_TSM_AP_6	0xf0be00ff
+
+/* TSM_AP7 */
+#define	R367TER_TSM_AP7	0xf0bF
+#define	F367TER_MEM_SELECT_BYTE	0xf0bf00ff
+
+/* TSTRES */
+#define	R367TER_TSTRES	0xf0c0
+#define	F367TER_FRES_DISPLAY	0xf0c00080
+#define	F367TER_FRES_FIFO_AD	0xf0c00020
+#define	F367TER_FRESRS	0xf0c00010
+#define	F367TER_FRESACS	0xf0c00008
+#define	F367TER_FRESFEC	0xf0c00004
+#define	F367TER_FRES_PRIF	0xf0c00002
+#define	F367TER_FRESCORE	0xf0c00001
+
+/* ANACTRL */
+#define	R367TER_ANACTRL	0xf0c1
+#define	F367TER_BYPASS_XTAL	0xf0c10040
+#define	F367TER_BYPASS_PLLXN	0xf0c1000c
+#define	F367TER_DIS_PAD_OSC	0xf0c10002
+#define	F367TER_STDBY_PLLXN	0xf0c10001
+
+/* TSTBUS */
+#define	R367TER_TSTBUS	0xf0c2
+#define	F367TER_TS_BYTE_CLK_INV	0xf0c20080
+#define	F367TER_CFG_IP	0xf0c20070
+#define	F367TER_CFG_TST	0xf0c2000f
+
+/* TSTRATE */
+#define	R367TER_TSTRATE	0xf0c6
+#define	F367TER_FORCEPHA	0xf0c60080
+#define	F367TER_FNEWPHA	0xf0c60010
+#define	F367TER_FROT90	0xf0c60008
+#define	F367TER_FR	0xf0c60007
+
+/* CONSTMODE */
+#define	R367TER_CONSTMODE	0xf0cb
+#define	F367TER_TST_PRIF	0xf0cb00e0
+#define	F367TER_CAR_TYPE	0xf0cb0018
+#define	F367TER_CONST_MODE	0xf0cb0003
+
+/* CONSTCARR1 */
+#define	R367TER_CONSTCARR1	0xf0cc
+#define	F367TER_CONST_CARR_LO	0xf0cc00ff
+
+/* CONSTCARR2 */
+#define	R367TER_CONSTCARR2	0xf0cd
+#define	F367TER_CONST_CARR_HI	0xf0cd001f
+
+/* ICONSTEL */
+#define	R367TER_ICONSTEL	0xf0ce
+#define	F367TER_PICONSTEL	0xf0ce00ff
+
+/* QCONSTEL */
+#define	R367TER_QCONSTEL	0xf0cf
+#define	F367TER_PQCONSTEL	0xf0cf00ff
+
+/* TSTBISTRES0 */
+#define	R367TER_TSTBISTRES0	0xf0d0
+#define	F367TER_BEND_PPM	0xf0d00080
+#define	F367TER_BBAD_PPM	0xf0d00040
+#define	F367TER_BEND_FFTW	0xf0d00020
+#define	F367TER_BBAD_FFTW	0xf0d00010
+#define	F367TER_BEND_FFT_BUF	0xf0d00008
+#define	F367TER_BBAD_FFT_BUF	0xf0d00004
+#define	F367TER_BEND_SYR	0xf0d00002
+#define	F367TER_BBAD_SYR	0xf0d00001
+
+/* TSTBISTRES1 */
+#define	R367TER_TSTBISTRES1	0xf0d1
+#define	F367TER_BEND_CHC_CP	0xf0d10080
+#define	F367TER_BBAD_CHC_CP	0xf0d10040
+#define	F367TER_BEND_CHCI	0xf0d10020
+#define	F367TER_BBAD_CHCI	0xf0d10010
+#define	F367TER_BEND_BDI	0xf0d10008
+#define	F367TER_BBAD_BDI	0xf0d10004
+#define	F367TER_BEND_SDI	0xf0d10002
+#define	F367TER_BBAD_SDI	0xf0d10001
+
+/* TSTBISTRES2 */
+#define	R367TER_TSTBISTRES2	0xf0d2
+#define	F367TER_BEND_CHC_INC	0xf0d20080
+#define	F367TER_BBAD_CHC_INC	0xf0d20040
+#define	F367TER_BEND_CHC_SPP	0xf0d20020
+#define	F367TER_BBAD_CHC_SPP	0xf0d20010
+#define	F367TER_BEND_CHC_CPP	0xf0d20008
+#define	F367TER_BBAD_CHC_CPP	0xf0d20004
+#define	F367TER_BEND_CHC_SP	0xf0d20002
+#define	F367TER_BBAD_CHC_SP	0xf0d20001
+
+/* TSTBISTRES3 */
+#define	R367TER_TSTBISTRES3	0xf0d3
+#define	F367TER_BEND_QAM	0xf0d30080
+#define	F367TER_BBAD_QAM	0xf0d30040
+#define	F367TER_BEND_SFEC_VIT	0xf0d30020
+#define	F367TER_BBAD_SFEC_VIT	0xf0d30010
+#define	F367TER_BEND_SFEC_DLINE	0xf0d30008
+#define	F367TER_BBAD_SFEC_DLINE	0xf0d30004
+#define	F367TER_BEND_SFEC_HW	0xf0d30002
+#define	F367TER_BBAD_SFEC_HW	0xf0d30001
+
+/* RF_AGC1 */
+#define	R367TER_RF_AGC1	0xf0d4
+#define	F367TER_RF_AGC1_LEVEL_HI	0xf0d400ff
+
+/* RF_AGC2 */
+#define	R367TER_RF_AGC2	0xf0d5
+#define	F367TER_REF_ADGP	0xf0d50080
+#define	F367TER_STDBY_ADCGP	0xf0d50020
+#define	F367TER_CHANNEL_SEL	0xf0d5001c
+#define	F367TER_RF_AGC1_LEVEL_LO	0xf0d50003
+
+/* ANADIGCTRL */
+#define	R367TER_ANADIGCTRL	0xf0d7
+#define	F367TER_SEL_CLKDEM	0xf0d70020
+#define	F367TER_EN_BUFFER_Q	0xf0d70010
+#define	F367TER_EN_BUFFER_I	0xf0d70008
+#define	F367TER_ADC_RIS_EGDE	0xf0d70004
+#define	F367TER_SGN_ADC	0xf0d70002
+#define	F367TER_SEL_AD12_SYNC	0xf0d70001
+
+/* PLLMDIV */
+#define	R367TER_PLLMDIV	0xf0d8
+#define	F367TER_PLL_MDIV	0xf0d800ff
+
+/* PLLNDIV */
+#define	R367TER_PLLNDIV	0xf0d9
+#define	F367TER_PLL_NDIV	0xf0d900ff
+
+/* PLLSETUP */
+#define	R367TER_PLLSETUP	0xf0dA
+#define	F367TER_PLL_PDIV	0xf0da0070
+#define	F367TER_PLL_KDIV	0xf0da000f
+
+/* DUAL_AD12 */
+#define	R367TER_DUAL_AD12	0xf0dB
+#define	F367TER_FS20M	0xf0db0020
+#define	F367TER_FS50M	0xf0db0010
+#define	F367TER_INMODe0	0xf0db0008
+#define	F367TER_POFFQ	0xf0db0004
+#define	F367TER_POFFI	0xf0db0002
+#define	F367TER_INMODE1	0xf0db0001
+
+/* TSTBIST */
+#define	R367TER_TSTBIST	0xf0dC
+#define	F367TER_TST_BYP_CLK	0xf0dc0080
+#define	F367TER_TST_GCLKENA_STD	0xf0dc0040
+#define	F367TER_TST_GCLKENA	0xf0dc0020
+#define	F367TER_TST_MEMBIST	0xf0dc001f
+
+/* PAD_COMP_CTRL */
+#define	R367TER_PAD_COMP_CTRL	0xf0dD
+#define	F367TER_COMPTQ	0xf0dd0010
+#define	F367TER_COMPEN	0xf0dd0008
+#define	F367TER_FREEZE2	0xf0dd0004
+#define	F367TER_SLEEP_INHBT	0xf0dd0002
+#define	F367TER_CHIP_SLEEP	0xf0dd0001
+
+/* PAD_COMP_WR */
+#define	R367TER_PAD_COMP_WR	0xf0de
+#define	F367TER_WR_ASRC	0xf0de007f
+
+/* PAD_COMP_RD */
+#define	R367TER_PAD_COMP_RD	0xf0df
+#define	F367TER_COMPOK	0xf0df0080
+#define	F367TER_RD_ASRC	0xf0df007f
+
+/* SYR_TARGET_FFTADJT_MSB */
+#define	R367TER_SYR_TARGET_FFTADJT_MSB	0xf100
+#define	F367TER_SYR_START	0xf1000080
+#define	F367TER_SYR_TARGET_FFTADJ_HI	0xf100000f
+
+/* SYR_TARGET_FFTADJT_LSB */
+#define	R367TER_SYR_TARGET_FFTADJT_LSB	0xf101
+#define	F367TER_SYR_TARGET_FFTADJ_LO	0xf10100ff
+
+/* SYR_TARGET_CHCADJT_MSB */
+#define	R367TER_SYR_TARGET_CHCADJT_MSB	0xf102
+#define	F367TER_SYR_TARGET_CHCADJ_HI	0xf102000f
+
+/* SYR_TARGET_CHCADJT_LSB */
+#define	R367TER_SYR_TARGET_CHCADJT_LSB	0xf103
+#define	F367TER_SYR_TARGET_CHCADJ_LO	0xf10300ff
+
+/* SYR_FLAG */
+#define	R367TER_SYR_FLAG	0xf104
+#define	F367TER_TRIG_FLG1	0xf1040080
+#define	F367TER_TRIG_FLG0	0xf1040040
+#define	F367TER_FFT_FLG1	0xf1040008
+#define	F367TER_FFT_FLG0	0xf1040004
+#define	F367TER_CHC_FLG1	0xf1040002
+#define	F367TER_CHC_FLG0	0xf1040001
+
+/* CRL_TARGET1 */
+#define	R367TER_CRL_TARGET1	0xf105
+#define	F367TER_CRL_START	0xf1050080
+#define	F367TER_CRL_TARGET_VHI	0xf105000f
+
+/* CRL_TARGET2 */
+#define	R367TER_CRL_TARGET2	0xf106
+#define	F367TER_CRL_TARGET_HI	0xf10600ff
+
+/* CRL_TARGET3 */
+#define	R367TER_CRL_TARGET3	0xf107
+#define	F367TER_CRL_TARGET_LO	0xf10700ff
+
+/* CRL_TARGET4 */
+#define	R367TER_CRL_TARGET4	0xf108
+#define	F367TER_CRL_TARGET_VLO	0xf10800ff
+
+/* CRL_FLAG */
+#define	R367TER_CRL_FLAG	0xf109
+#define	F367TER_CRL_FLAG1	0xf1090002
+#define	F367TER_CRL_FLAG0	0xf1090001
+
+/* TRL_TARGET1 */
+#define	R367TER_TRL_TARGET1	0xf10a
+#define	F367TER_TRL_TARGET_HI	0xf10a00ff
+
+/* TRL_TARGET2 */
+#define	R367TER_TRL_TARGET2	0xf10b
+#define	F367TER_TRL_TARGET_LO	0xf10b00ff
+
+/* TRL_CHC */
+#define	R367TER_TRL_CHC	0xf10c
+#define	F367TER_TRL_START	0xf10c0080
+#define	F367TER_CHC_START	0xf10c0040
+#define	F367TER_TRL_FLAG1	0xf10c0002
+#define	F367TER_TRL_FLAG0	0xf10c0001
+
+/* CHC_SNR_TARG */
+#define	R367TER_CHC_SNR_TARG	0xf10d
+#define	F367TER_CHC_SNR_TARGET	0xf10d00ff
+
+/* TOP_TRACK */
+#define	R367TER_TOP_TRACK	0xf10e
+#define	F367TER_TOP_START	0xf10e0080
+#define	F367TER_FIRST_FLAG	0xf10e0070
+#define	F367TER_TOP_FLAG1	0xf10e0008
+#define	F367TER_TOP_FLAG0	0xf10e0004
+#define	F367TER_CHC_FLAG1	0xf10e0002
+#define	F367TER_CHC_FLAG0	0xf10e0001
+
+/* TRACKER_FREE1 */
+#define	R367TER_TRACKER_FREE1	0xf10f
+#define	F367TER_TRACKER_FREE_1	0xf10f00ff
+
+/* ERROR_CRL1 */
+#define	R367TER_ERROR_CRL1	0xf110
+#define	F367TER_ERROR_CRL_VHI	0xf11000ff
+
+/* ERROR_CRL2 */
+#define	R367TER_ERROR_CRL2	0xf111
+#define	F367TER_ERROR_CRL_HI	0xf11100ff
+
+/* ERROR_CRL3 */
+#define	R367TER_ERROR_CRL3	0xf112
+#define	F367TER_ERROR_CRL_LOI	0xf11200ff
+
+/* ERROR_CRL4 */
+#define	R367TER_ERROR_CRL4	0xf113
+#define	F367TER_ERROR_CRL_VLO	0xf11300ff
+
+/* DEC_NCO1 */
+#define	R367TER_DEC_NCO1	0xf114
+#define	F367TER_DEC_NCO_VHI	0xf11400ff
+
+/* DEC_NCO2 */
+#define	R367TER_DEC_NCO2	0xf115
+#define	F367TER_DEC_NCO_HI	0xf11500ff
+
+/* DEC_NCO3 */
+#define	R367TER_DEC_NCO3	0xf116
+#define	F367TER_DEC_NCO_LO	0xf11600ff
+
+/* SNR */
+#define	R367TER_SNR	0xf117
+#define	F367TER_SNRATIO	0xf11700ff
+
+/* SYR_FFTADJ1 */
+#define	R367TER_SYR_FFTADJ1	0xf118
+#define	F367TER_SYR_FFTADJ_HI	0xf11800ff
+
+/* SYR_FFTADJ2 */
+#define	R367TER_SYR_FFTADJ2	0xf119
+#define	F367TER_SYR_FFTADJ_LO	0xf11900ff
+
+/* SYR_CHCADJ1 */
+#define	R367TER_SYR_CHCADJ1	0xf11a
+#define	F367TER_SYR_CHCADJ_HI	0xf11a00ff
+
+/* SYR_CHCADJ2 */
+#define	R367TER_SYR_CHCADJ2	0xf11b
+#define	F367TER_SYR_CHCADJ_LO	0xf11b00ff
+
+/* SYR_OFF */
+#define	R367TER_SYR_OFF	0xf11c
+#define	F367TER_SYR_OFFSET	0xf11c00ff
+
+/* PPM_OFFSET1 */
+#define	R367TER_PPM_OFFSET1	0xf11d
+#define	F367TER_PPM_OFFSET_HI	0xf11d00ff
+
+/* PPM_OFFSET2 */
+#define	R367TER_PPM_OFFSET2	0xf11e
+#define	F367TER_PPM_OFFSET_LO	0xf11e00ff
+
+/* TRACKER_FREE2 */
+#define	R367TER_TRACKER_FREE2	0xf11f
+#define	F367TER_TRACKER_FREE_2	0xf11f00ff
+
+/* DEBG_LT10 */
+#define	R367TER_DEBG_LT10	0xf120
+#define	F367TER_DEBUG_LT10	0xf12000ff
+
+/* DEBG_LT11 */
+#define	R367TER_DEBG_LT11	0xf121
+#define	F367TER_DEBUG_LT11	0xf12100ff
+
+/* DEBG_LT12 */
+#define	R367TER_DEBG_LT12	0xf122
+#define	F367TER_DEBUG_LT12	0xf12200ff
+
+/* DEBG_LT13 */
+#define	R367TER_DEBG_LT13	0xf123
+#define	F367TER_DEBUG_LT13	0xf12300ff
+
+/* DEBG_LT14 */
+#define	R367TER_DEBG_LT14	0xf124
+#define	F367TER_DEBUG_LT14	0xf12400ff
+
+/* DEBG_LT15 */
+#define	R367TER_DEBG_LT15	0xf125
+#define	F367TER_DEBUG_LT15	0xf12500ff
+
+/* DEBG_LT16 */
+#define	R367TER_DEBG_LT16	0xf126
+#define	F367TER_DEBUG_LT16	0xf12600ff
+
+/* DEBG_LT17 */
+#define	R367TER_DEBG_LT17	0xf127
+#define	F367TER_DEBUG_LT17	0xf12700ff
+
+/* DEBG_LT18 */
+#define	R367TER_DEBG_LT18	0xf128
+#define	F367TER_DEBUG_LT18	0xf12800ff
+
+/* DEBG_LT19 */
+#define	R367TER_DEBG_LT19	0xf129
+#define	F367TER_DEBUG_LT19	0xf12900ff
+
+/* DEBG_LT1a */
+#define	R367TER_DEBG_LT1A	0xf12a
+#define	F367TER_DEBUG_LT1A	0xf12a00ff
+
+/* DEBG_LT1b */
+#define	R367TER_DEBG_LT1B	0xf12b
+#define	F367TER_DEBUG_LT1B	0xf12b00ff
+
+/* DEBG_LT1c */
+#define	R367TER_DEBG_LT1C	0xf12c
+#define	F367TER_DEBUG_LT1C	0xf12c00ff
+
+/* DEBG_LT1D */
+#define	R367TER_DEBG_LT1D	0xf12d
+#define	F367TER_DEBUG_LT1D	0xf12d00ff
+
+/* DEBG_LT1E */
+#define	R367TER_DEBG_LT1E	0xf12e
+#define	F367TER_DEBUG_LT1E	0xf12e00ff
+
+/* DEBG_LT1F */
+#define	R367TER_DEBG_LT1F	0xf12f
+#define	F367TER_DEBUG_LT1F	0xf12f00ff
+
+/* RCCFGH */
+#define	R367TER_RCCFGH	0xf200
+#define	F367TER_TSRCFIFO_DVBCI	0xf2000080
+#define	F367TER_TSRCFIFO_SERIAL	0xf2000040
+#define	F367TER_TSRCFIFO_DISABLE	0xf2000020
+#define	F367TER_TSFIFO_2TORC	0xf2000010
+#define	F367TER_TSRCFIFO_HSGNLOUT	0xf2000008
+#define	F367TER_TSRCFIFO_ERRMODE	0xf2000006
+#define	F367TER_RCCFGH_0	0xf2000001
+
+/* RCCFGM */
+#define	R367TER_RCCFGM	0xf201
+#define	F367TER_TSRCFIFO_MANSPEED	0xf20100c0
+#define	F367TER_TSRCFIFO_PERMDATA	0xf2010020
+#define	F367TER_TSRCFIFO_NONEWSGNL	0xf2010010
+#define	F367TER_RCBYTE_OVERSAMPLING	0xf201000e
+#define	F367TER_TSRCFIFO_INVDATA	0xf2010001
+
+/* RCCFGL */
+#define	R367TER_RCCFGL	0xf202
+#define	F367TER_TSRCFIFO_BCLKDEL1cK	0xf20200c0
+#define	F367TER_RCCFGL_5	0xf2020020
+#define	F367TER_TSRCFIFO_DUTY50	0xf2020010
+#define	F367TER_TSRCFIFO_NSGNL2dATA	0xf2020008
+#define	F367TER_TSRCFIFO_DISSERMUX	0xf2020004
+#define	F367TER_RCCFGL_1	0xf2020002
+#define	F367TER_TSRCFIFO_STOPCKDIS	0xf2020001
+
+/* RCINSDELH */
+#define	R367TER_RCINSDELH	0xf203
+#define	F367TER_TSRCDEL_SYNCBYTE	0xf2030080
+#define	F367TER_TSRCDEL_XXHEADER	0xf2030040
+#define	F367TER_TSRCDEL_BBHEADER	0xf2030020
+#define	F367TER_TSRCDEL_DATAFIELD	0xf2030010
+#define	F367TER_TSRCINSDEL_ISCR	0xf2030008
+#define	F367TER_TSRCINSDEL_NPD	0xf2030004
+#define	F367TER_TSRCINSDEL_RSPARITY	0xf2030002
+#define	F367TER_TSRCINSDEL_CRC8	0xf2030001
+
+/* RCINSDELM */
+#define	R367TER_RCINSDELM	0xf204
+#define	F367TER_TSRCINS_BBPADDING	0xf2040080
+#define	F367TER_TSRCINS_BCHFEC	0xf2040040
+#define	F367TER_TSRCINS_LDPCFEC	0xf2040020
+#define	F367TER_TSRCINS_EMODCOD	0xf2040010
+#define	F367TER_TSRCINS_TOKEN	0xf2040008
+#define	F367TER_TSRCINS_XXXERR	0xf2040004
+#define	F367TER_TSRCINS_MATYPE	0xf2040002
+#define	F367TER_TSRCINS_UPL	0xf2040001
+
+/* RCINSDELL */
+#define	R367TER_RCINSDELL	0xf205
+#define	F367TER_TSRCINS_DFL	0xf2050080
+#define	F367TER_TSRCINS_SYNCD	0xf2050040
+#define	F367TER_TSRCINS_BLOCLEN	0xf2050020
+#define	F367TER_TSRCINS_SIGPCOUNT	0xf2050010
+#define	F367TER_TSRCINS_FIFO	0xf2050008
+#define	F367TER_TSRCINS_REALPACK	0xf2050004
+#define	F367TER_TSRCINS_TSCONFIG	0xf2050002
+#define	F367TER_TSRCINS_LATENCY	0xf2050001
+
+/* RCSTATUS */
+#define	R367TER_RCSTATUS	0xf206
+#define	F367TER_TSRCFIFO_LINEOK	0xf2060080
+#define	F367TER_TSRCFIFO_ERROR	0xf2060040
+#define	F367TER_TSRCFIFO_DATA7	0xf2060020
+#define	F367TER_RCSTATUS_4	0xf2060010
+#define	F367TER_TSRCFIFO_DEMODSEL	0xf2060008
+#define	F367TER_TSRC1FIFOSPEED_STORE	0xf2060004
+#define	F367TER_RCSTATUS_1	0xf2060002
+#define	F367TER_TSRCSERIAL_IMPOSSIBLE	0xf2060001
+
+/* RCSPEED */
+#define	R367TER_RCSPEED	0xf207
+#define	F367TER_TSRCFIFO_OUTSPEED	0xf20700ff
+
+/* RCDEBUGM */
+#define	R367TER_RCDEBUGM	0xf208
+#define	F367TER_SD_UNSYNC	0xf2080080
+#define	F367TER_ULFLOCK_DETECTM	0xf2080040
+#define	F367TER_SUL_SELECTOS	0xf2080020
+#define	F367TER_DILUL_NOSCRBLE	0xf2080010
+#define	F367TER_NUL_SCRB	0xf2080008
+#define	F367TER_UL_SCRB	0xf2080004
+#define	F367TER_SCRAULBAD	0xf2080002
+#define	F367TER_SCRAUL_UNSYNC	0xf2080001
+
+/* RCDEBUGL */
+#define	R367TER_RCDEBUGL	0xf209
+#define	F367TER_RS_ERR	0xf2090080
+#define	F367TER_LLFLOCK_DETECTM	0xf2090040
+#define	F367TER_NOT_SUL_SELECTOS	0xf2090020
+#define	F367TER_DILLL_NOSCRBLE	0xf2090010
+#define	F367TER_NLL_SCRB	0xf2090008
+#define	F367TER_LL_SCRB	0xf2090004
+#define	F367TER_SCRALLBAD	0xf2090002
+#define	F367TER_SCRALL_UNSYNC	0xf2090001
+
+/* RCOBSCFG */
+#define	R367TER_RCOBSCFG	0xf20a
+#define	F367TER_TSRCFIFO_OBSCFG	0xf20a00ff
+
+/* RCOBSM */
+#define	R367TER_RCOBSM	0xf20b
+#define	F367TER_TSRCFIFO_OBSDATA_HI	0xf20b00ff
+
+/* RCOBSL */
+#define	R367TER_RCOBSL	0xf20c
+#define	F367TER_TSRCFIFO_OBSDATA_LO	0xf20c00ff
+
+/* RCFECSPY */
+#define	R367TER_RCFECSPY	0xf210
+#define	F367TER_SPYRC_ENABLE	0xf2100080
+#define	F367TER_RCNO_SYNCBYTE	0xf2100040
+#define	F367TER_RCSERIAL_MODE	0xf2100020
+#define	F367TER_RCUNUSUAL_PACKET	0xf2100010
+#define	F367TER_BERRCMETER_DATAMODE	0xf210000c
+#define	F367TER_BERRCMETER_LMODE	0xf2100002
+#define	F367TER_BERRCMETER_RESET	0xf2100001
+
+/* RCFSPYCFG */
+#define	R367TER_RCFSPYCFG	0xf211
+#define	F367TER_FECSPYRC_INPUT	0xf21100c0
+#define	F367TER_RCRST_ON_ERROR	0xf2110020
+#define	F367TER_RCONE_SHOT	0xf2110010
+#define	F367TER_RCI2C_MODE	0xf211000c
+#define	F367TER_SPYRC_HSTERESIS	0xf2110003
+
+/* RCFSPYDATA */
+#define	R367TER_RCFSPYDATA	0xf212
+#define	F367TER_SPYRC_STUFFING	0xf2120080
+#define	F367TER_RCNOERR_PKTJITTER	0xf2120040
+#define	F367TER_SPYRC_CNULLPKT	0xf2120020
+#define	F367TER_SPYRC_OUTDATA_MODE	0xf212001f
+
+/* RCFSPYOUT */
+#define	R367TER_RCFSPYOUT	0xf213
+#define	F367TER_FSPYRC_DIRECT	0xf2130080
+#define	F367TER_RCFSPYOUT_6	0xf2130040
+#define	F367TER_SPYRC_OUTDATA_BUS	0xf2130038
+#define	F367TER_RCSTUFF_MODE	0xf2130007
+
+/* RCFSTATUS */
+#define	R367TER_RCFSTATUS	0xf214
+#define	F367TER_SPYRC_ENDSIM	0xf2140080
+#define	F367TER_RCVALID_SIM	0xf2140040
+#define	F367TER_RCFOUND_SIGNAL	0xf2140020
+#define	F367TER_RCDSS_SYNCBYTE	0xf2140010
+#define	F367TER_RCRESULT_STATE	0xf214000f
+
+/* RCFGOODPACK */
+#define	R367TER_RCFGOODPACK	0xf215
+#define	F367TER_RCGOOD_PACKET	0xf21500ff
+
+/* RCFPACKCNT */
+#define	R367TER_RCFPACKCNT	0xf216
+#define	F367TER_RCPACKET_COUNTER	0xf21600ff
+
+/* RCFSPYMISC */
+#define	R367TER_RCFSPYMISC	0xf217
+#define	F367TER_RCLABEL_COUNTER	0xf21700ff
+
+/* RCFBERCPT4 */
+#define	R367TER_RCFBERCPT4	0xf218
+#define	F367TER_FBERRCMETER_CPT_MMMMSB	0xf21800ff
+
+/* RCFBERCPT3 */
+#define	R367TER_RCFBERCPT3	0xf219
+#define	F367TER_FBERRCMETER_CPT_MMMSB	0xf21900ff
+
+/* RCFBERCPT2 */
+#define	R367TER_RCFBERCPT2	0xf21a
+#define	F367TER_FBERRCMETER_CPT_MMSB	0xf21a00ff
+
+/* RCFBERCPT1 */
+#define	R367TER_RCFBERCPT1	0xf21b
+#define	F367TER_FBERRCMETER_CPT_MSB	0xf21b00ff
+
+/* RCFBERCPT0 */
+#define	R367TER_RCFBERCPT0	0xf21c
+#define	F367TER_FBERRCMETER_CPT_LSB	0xf21c00ff
+
+/* RCFBERERR2 */
+#define	R367TER_RCFBERERR2	0xf21d
+#define	F367TER_FBERRCMETER_ERR_HI	0xf21d00ff
+
+/* RCFBERERR1 */
+#define	R367TER_RCFBERERR1	0xf21e
+#define	F367TER_FBERRCMETER_ERR	0xf21e00ff
+
+/* RCFBERERR0 */
+#define	R367TER_RCFBERERR0	0xf21f
+#define	F367TER_FBERRCMETER_ERR_LO	0xf21f00ff
+
+/* RCFSTATESM */
+#define	R367TER_RCFSTATESM	0xf220
+#define	F367TER_RCRSTATE_F	0xf2200080
+#define	F367TER_RCRSTATE_E	0xf2200040
+#define	F367TER_RCRSTATE_D	0xf2200020
+#define	F367TER_RCRSTATE_C	0xf2200010
+#define	F367TER_RCRSTATE_B	0xf2200008
+#define	F367TER_RCRSTATE_A	0xf2200004
+#define	F367TER_RCRSTATE_9	0xf2200002
+#define	F367TER_RCRSTATE_8	0xf2200001
+
+/* RCFSTATESL */
+#define	R367TER_RCFSTATESL	0xf221
+#define	F367TER_RCRSTATE_7	0xf2210080
+#define	F367TER_RCRSTATE_6	0xf2210040
+#define	F367TER_RCRSTATE_5	0xf2210020
+#define	F367TER_RCRSTATE_4	0xf2210010
+#define	F367TER_RCRSTATE_3	0xf2210008
+#define	F367TER_RCRSTATE_2	0xf2210004
+#define	F367TER_RCRSTATE_1	0xf2210002
+#define	F367TER_RCRSTATE_0	0xf2210001
+
+/* RCFSPYBER */
+#define	R367TER_RCFSPYBER	0xf222
+#define	F367TER_RCFSPYBER_7	0xf2220080
+#define	F367TER_SPYRCOBS_XORREAD	0xf2220040
+#define	F367TER_FSPYRCBER_OBSMODE	0xf2220020
+#define	F367TER_FSPYRCBER_SYNCBYT	0xf2220010
+#define	F367TER_FSPYRCBER_UNSYNC	0xf2220008
+#define	F367TER_FSPYRCBER_CTIME	0xf2220007
+
+/* RCFSPYDISTM */
+#define	R367TER_RCFSPYDISTM	0xf223
+#define	F367TER_RCPKTTIME_DISTANCE_HI	0xf22300ff
+
+/* RCFSPYDISTL */
+#define	R367TER_RCFSPYDISTL	0xf224
+#define	F367TER_RCPKTTIME_DISTANCE_LO	0xf22400ff
+
+/* RCFSPYOBS7 */
+#define	R367TER_RCFSPYOBS7	0xf228
+#define	F367TER_RCSPYOBS_SPYFAIL	0xf2280080
+#define	F367TER_RCSPYOBS_SPYFAIL1	0xf2280040
+#define	F367TER_RCSPYOBS_ERROR	0xf2280020
+#define	F367TER_RCSPYOBS_STROUT	0xf2280010
+#define	F367TER_RCSPYOBS_RESULTSTATE1	0xf228000f
+
+/* RCFSPYOBS6 */
+#define	R367TER_RCFSPYOBS6	0xf229
+#define	F367TER_RCSPYOBS_RESULTSTATe0	0xf22900f0
+#define	F367TER_RCSPYOBS_RESULTSTATEM1	0xf229000f
+
+/* RCFSPYOBS5 */
+#define	R367TER_RCFSPYOBS5	0xf22a
+#define	F367TER_RCSPYOBS_BYTEOFPACKET1	0xf22a00ff
+
+/* RCFSPYOBS4 */
+#define	R367TER_RCFSPYOBS4	0xf22b
+#define	F367TER_RCSPYOBS_BYTEVALUE1	0xf22b00ff
+
+/* RCFSPYOBS3 */
+#define	R367TER_RCFSPYOBS3	0xf22c
+#define	F367TER_RCSPYOBS_DATA1	0xf22c00ff
+
+/* RCFSPYOBS2 */
+#define	R367TER_RCFSPYOBS2	0xf22d
+#define	F367TER_RCSPYOBS_DATa0	0xf22d00ff
+
+/* RCFSPYOBS1 */
+#define	R367TER_RCFSPYOBS1	0xf22e
+#define	F367TER_RCSPYOBS_DATAM1	0xf22e00ff
+
+/* RCFSPYOBS0 */
+#define	R367TER_RCFSPYOBS0	0xf22f
+#define	F367TER_RCSPYOBS_DATAM2	0xf22f00ff
+
+/* TSGENERAL */
+#define	R367TER_TSGENERAL	0xf230
+#define	F367TER_TSGENERAL_7	0xf2300080
+#define	F367TER_TSGENERAL_6	0xf2300040
+#define	F367TER_TSFIFO_BCLK1aLL	0xf2300020
+#define	F367TER_TSGENERAL_4	0xf2300010
+#define	F367TER_MUXSTREAM_OUTMODE	0xf2300008
+#define	F367TER_TSFIFO_PERMPARAL	0xf2300006
+#define	F367TER_RST_REEDSOLO	0xf2300001
+
+/* RC1SPEED */
+#define	R367TER_RC1SPEED	0xf231
+#define	F367TER_TSRCFIFO1_OUTSPEED	0xf23100ff
+
+/* TSGSTATUS */
+#define	R367TER_TSGSTATUS	0xf232
+#define	F367TER_TSGSTATUS_7	0xf2320080
+#define	F367TER_TSGSTATUS_6	0xf2320040
+#define	F367TER_RSMEM_FULL	0xf2320020
+#define	F367TER_RS_MULTCALC	0xf2320010
+#define	F367TER_RSIN_OVERTIME	0xf2320008
+#define	F367TER_TSFIFO3_DEMODSEL	0xf2320004
+#define	F367TER_TSFIFO2_DEMODSEL	0xf2320002
+#define	F367TER_TSFIFO1_DEMODSEL	0xf2320001
+
+
+/* FECM */
+#define	R367TER_FECM	0xf233
+#define	F367TER_DSS_DVB	0xf2330080
+#define	F367TER_DEMOD_BYPASS	0xf2330040
+#define	F367TER_CMP_SLOWMODE	0xf2330020
+#define	F367TER_DSS_SRCH	0xf2330010
+#define	F367TER_FECM_3	0xf2330008
+#define	F367TER_DIFF_MODEVIT	0xf2330004
+#define	F367TER_SYNCVIT	0xf2330002
+#define	F367TER_I2CSYM	0xf2330001
+
+/* VTH12 */
+#define	R367TER_VTH12	0xf234
+#define	F367TER_VTH_12	0xf23400ff
+
+/* VTH23 */
+#define	R367TER_VTH23	0xf235
+#define	F367TER_VTH_23	0xf23500ff
+
+/* VTH34 */
+#define	R367TER_VTH34	0xf236
+#define	F367TER_VTH_34	0xf23600ff
+
+/* VTH56 */
+#define	R367TER_VTH56	0xf237
+#define	F367TER_VTH_56	0xf23700ff
+
+/* VTH67 */
+#define	R367TER_VTH67	0xf238
+#define	F367TER_VTH_67	0xf23800ff
+
+/* VTH78 */
+#define	R367TER_VTH78	0xf239
+#define	F367TER_VTH_78	0xf23900ff
+
+/* VITCURPUN */
+#define	R367TER_VITCURPUN	0xf23a
+#define	F367TER_VIT_MAPPING	0xf23a00e0
+#define	F367TER_VIT_CURPUN	0xf23a001f
+
+/* VERROR */
+#define	R367TER_VERROR	0xf23b
+#define	F367TER_REGERR_VIT	0xf23b00ff
+
+/* PRVIT */
+#define	R367TER_PRVIT	0xf23c
+#define	F367TER_PRVIT_7	0xf23c0080
+#define	F367TER_DIS_VTHLOCK	0xf23c0040
+#define	F367TER_E7_8VIT	0xf23c0020
+#define	F367TER_E6_7VIT	0xf23c0010
+#define	F367TER_E5_6VIT	0xf23c0008
+#define	F367TER_E3_4VIT	0xf23c0004
+#define	F367TER_E2_3VIT	0xf23c0002
+#define	F367TER_E1_2VIT	0xf23c0001
+
+/* VAVSRVIT */
+#define	R367TER_VAVSRVIT	0xf23d
+#define	F367TER_AMVIT	0xf23d0080
+#define	F367TER_FROZENVIT	0xf23d0040
+#define	F367TER_SNVIT	0xf23d0030
+#define	F367TER_TOVVIT	0xf23d000c
+#define	F367TER_HYPVIT	0xf23d0003
+
+/* VSTATUSVIT */
+#define	R367TER_VSTATUSVIT	0xf23e
+#define	F367TER_VITERBI_ON	0xf23e0080
+#define	F367TER_END_LOOPVIT	0xf23e0040
+#define	F367TER_VITERBI_DEPRF	0xf23e0020
+#define	F367TER_PRFVIT	0xf23e0010
+#define	F367TER_LOCKEDVIT	0xf23e0008
+#define	F367TER_VITERBI_DELOCK	0xf23e0004
+#define	F367TER_VIT_DEMODSEL	0xf23e0002
+#define	F367TER_VITERBI_COMPOUT	0xf23e0001
+
+/* VTHINUSE */
+#define	R367TER_VTHINUSE	0xf23f
+#define	F367TER_VIT_INUSE	0xf23f00ff
+
+/* KDIV12 */
+#define	R367TER_KDIV12	0xf240
+#define	F367TER_KDIV12_MANUAL	0xf2400080
+#define	F367TER_K_DIVIDER_12	0xf240007f
+
+/* KDIV23 */
+#define	R367TER_KDIV23	0xf241
+#define	F367TER_KDIV23_MANUAL	0xf2410080
+#define	F367TER_K_DIVIDER_23	0xf241007f
+
+/* KDIV34 */
+#define	R367TER_KDIV34	0xf242
+#define	F367TER_KDIV34_MANUAL	0xf2420080
+#define	F367TER_K_DIVIDER_34	0xf242007f
+
+/* KDIV56 */
+#define	R367TER_KDIV56	0xf243
+#define	F367TER_KDIV56_MANUAL	0xf2430080
+#define	F367TER_K_DIVIDER_56	0xf243007f
+
+/* KDIV67 */
+#define	R367TER_KDIV67	0xf244
+#define	F367TER_KDIV67_MANUAL	0xf2440080
+#define	F367TER_K_DIVIDER_67	0xf244007f
+
+/* KDIV78 */
+#define	R367TER_KDIV78	0xf245
+#define	F367TER_KDIV78_MANUAL	0xf2450080
+#define	F367TER_K_DIVIDER_78	0xf245007f
+
+/* SIGPOWER */
+#define	R367TER_SIGPOWER	0xf246
+#define	F367TER_SIGPOWER_MANUAL	0xf2460080
+#define	F367TER_SIG_POWER	0xf246007f
+
+/* DEMAPVIT */
+#define	R367TER_DEMAPVIT	0xf247
+#define	F367TER_DEMAPVIT_7	0xf2470080
+#define	F367TER_K_DIVIDER_VIT	0xf247007f
+
+/* VITSCALE */
+#define	R367TER_VITSCALE	0xf248
+#define	F367TER_NVTH_NOSRANGE	0xf2480080
+#define	F367TER_VERROR_MAXMODE	0xf2480040
+#define	F367TER_KDIV_MODE	0xf2480030
+#define	F367TER_NSLOWSN_LOCKED	0xf2480008
+#define	F367TER_DELOCK_PRFLOSS	0xf2480004
+#define	F367TER_DIS_RSFLOCK	0xf2480002
+#define	F367TER_VITSCALE_0	0xf2480001
+
+/* FFEC1PRG */
+#define	R367TER_FFEC1PRG	0xf249
+#define	F367TER_FDSS_DVB	0xf2490080
+#define	F367TER_FDSS_SRCH	0xf2490040
+#define	F367TER_FFECPROG_5	0xf2490020
+#define	F367TER_FFECPROG_4	0xf2490010
+#define	F367TER_FFECPROG_3	0xf2490008
+#define	F367TER_FFECPROG_2	0xf2490004
+#define	F367TER_FTS1_DISABLE	0xf2490002
+#define	F367TER_FTS2_DISABLE	0xf2490001
+
+/* FVITCURPUN */
+#define	R367TER_FVITCURPUN	0xf24a
+#define	F367TER_FVIT_MAPPING	0xf24a00e0
+#define	F367TER_FVIT_CURPUN	0xf24a001f
+
+/* FVERROR */
+#define	R367TER_FVERROR	0xf24b
+#define	F367TER_FREGERR_VIT	0xf24b00ff
+
+/* FVSTATUSVIT */
+#define	R367TER_FVSTATUSVIT	0xf24c
+#define	F367TER_FVITERBI_ON	0xf24c0080
+#define	F367TER_F1END_LOOPVIT	0xf24c0040
+#define	F367TER_FVITERBI_DEPRF	0xf24c0020
+#define	F367TER_FPRFVIT	0xf24c0010
+#define	F367TER_FLOCKEDVIT	0xf24c0008
+#define	F367TER_FVITERBI_DELOCK	0xf24c0004
+#define	F367TER_FVIT_DEMODSEL	0xf24c0002
+#define	F367TER_FVITERBI_COMPOUT	0xf24c0001
+
+/* DEBUG_LT1 */
+#define	R367TER_DEBUG_LT1	0xf24d
+#define	F367TER_DBG_LT1	0xf24d00ff
+
+/* DEBUG_LT2 */
+#define	R367TER_DEBUG_LT2	0xf24e
+#define	F367TER_DBG_LT2	0xf24e00ff
+
+/* DEBUG_LT3 */
+#define	R367TER_DEBUG_LT3	0xf24f
+#define	F367TER_DBG_LT3	0xf24f00ff
+
+/*	TSTSFMET */
+#define	R367TER_TSTSFMET	0xf250
+#define F367TER_TSTSFEC_METRIQUES	0xf25000ff
+
+/*	SELOUT */
+#define	R367TER_SELOUT	0xf252
+#define	F367TER_EN_SYNC	0xf2520080
+#define	F367TER_EN_TBUSDEMAP	0xf2520040
+#define	F367TER_SELOUT_5	0xf2520020
+#define	F367TER_SELOUT_4	0xf2520010
+#define	F367TER_TSTSYNCHRO_MODE	0xf2520002
+
+/*	TSYNC */
+#define R367TER_TSYNC	0xf253
+#define F367TER_CURPUN_INCMODE	0xf2530080
+#define F367TER_CERR_TSTMODE	0xf2530040
+#define F367TER_SHIFTSOF_MODE	0xf2530030
+#define F367TER_SLOWPHA_MODE	0xf2530008
+#define F367TER_PXX_BYPALL	0xf2530004
+#define F367TER_FROTA45_FIRST	0xf2530002
+#define F367TER_TST_BCHERROR	0xf2530001
+
+/*	TSTERR */
+#define R367TER_TSTERR	0xf254
+#define F367TER_TST_LONGPKT	0xf2540080
+#define F367TER_TST_ISSYION	0xf2540040
+#define F367TER_TST_NPDON	0xf2540020
+#define F367TER_TSTERR_4	0xf2540010
+#define F367TER_TRACEBACK_MODE	0xf2540008
+#define F367TER_TST_RSPARITY	0xf2540004
+#define F367TER_METRIQUE_MODE	0xf2540003
+
+/*	TSFSYNC */
+#define R367TER_TSFSYNC	0xf255
+#define F367TER_EN_SFECSYNC	0xf2550080
+#define F367TER_EN_SFECDEMAP	0xf2550040
+#define F367TER_SFCERR_TSTMODE	0xf2550020
+#define F367TER_SFECPXX_BYPALL	0xf2550010
+#define F367TER_SFECTSTSYNCHRO_MODE 0xf255000f
+
+/*	TSTSFERR */
+#define R367TER_TSTSFERR	0xf256
+#define F367TER_TSTSTERR_7	0xf2560080
+#define F367TER_TSTSTERR_6	0xf2560040
+#define F367TER_TSTSTERR_5	0xf2560020
+#define F367TER_TSTSTERR_4	0xf2560010
+#define F367TER_SFECTRACEBACK_MODE	0xf2560008
+#define F367TER_SFEC_NCONVPROG	0xf2560004
+#define F367TER_SFECMETRIQUE_MODE	0xf2560003
+
+/*	TSTTSSF1 */
+#define R367TER_TSTTSSF1	0xf258
+#define F367TER_TSTERSSF	0xf2580080
+#define F367TER_TSTTSSFEN	0xf2580040
+#define F367TER_SFEC_OUTMODE	0xf2580030
+#define F367TER_XLSF_NOFTHRESHOLD  0xf2580008
+#define F367TER_TSTTSSF_STACKSEL	0xf2580007
+
+/*	TSTTSSF2 */
+#define R367TER_TSTTSSF2	0xf259
+#define F367TER_DILSF_DBBHEADER	0xf2590080
+#define F367TER_TSTTSSF_DISBUG	0xf2590040
+#define F367TER_TSTTSSF_NOBADSTART	0xf2590020
+#define F367TER_TSTTSSF_SELECT	0xf259001f
+
+/*	TSTTSSF3 */
+#define R367TER_TSTTSSF3	0xf25a
+#define F367TER_TSTTSSF3_7	0xf25a0080
+#define F367TER_TSTTSSF3_6	0xf25a0040
+#define F367TER_TSTTSSF3_5	0xf25a0020
+#define F367TER_TSTTSSF3_4	0xf25a0010
+#define F367TER_TSTTSSF3_3	0xf25a0008
+#define F367TER_TSTTSSF3_2	0xf25a0004
+#define F367TER_TSTTSSF3_1	0xf25a0002
+#define F367TER_DISSF_CLKENABLE	0xf25a0001
+
+/*	TSTTS1 */
+#define R367TER_TSTTS1	0xf25c
+#define F367TER_TSTERS	0xf25c0080
+#define F367TER_TSFIFO_DSSSYNCB	0xf25c0040
+#define F367TER_TSTTS_FSPYBEFRS	0xf25c0020
+#define F367TER_NFORCE_SYNCBYTE	0xf25c0010
+#define F367TER_XL_NOFTHRESHOLD	0xf25c0008
+#define F367TER_TSTTS_FRFORCEPKT	0xf25c0004
+#define F367TER_DESCR_NOTAUTO	0xf25c0002
+#define F367TER_TSTTSEN	0xf25c0001
+
+/*	TSTTS2 */
+#define R367TER_TSTTS2	0xf25d
+#define F367TER_DIL_DBBHEADER	0xf25d0080
+#define F367TER_TSTTS_NOBADXXX	0xf25d0040
+#define F367TER_TSFIFO_DELSPEEDUP	0xf25d0020
+#define F367TER_TSTTS_SELECT	0xf25d001f
+
+/*	TSTTS3 */
+#define R367TER_TSTTS3	0xf25e
+#define F367TER_TSTTS_NOPKTGAIN	0xf25e0080
+#define F367TER_TSTTS_NOPKTENE	0xf25e0040
+#define F367TER_TSTTS_ISOLATION	0xf25e0020
+#define F367TER_TSTTS_DISBUG	0xf25e0010
+#define F367TER_TSTTS_NOBADSTART	0xf25e0008
+#define F367TER_TSTTS_STACKSEL	0xf25e0007
+
+/*	TSTTS4 */
+#define R367TER_TSTTS4	0xf25f
+#define F367TER_TSTTS4_7	0xf25f0080
+#define F367TER_TSTTS4_6	0xf25f0040
+#define F367TER_TSTTS4_5	0xf25f0020
+#define F367TER_TSTTS_DISDSTATE	0xf25f0010
+#define F367TER_TSTTS_FASTNOSYNC	0xf25f0008
+#define F367TER_EXT_FECSPYIN	0xf25f0004
+#define F367TER_TSTTS_NODPZERO	0xf25f0002
+#define F367TER_TSTTS_NODIV3	0xf25f0001
+
+/*	TSTTSRC */
+#define R367TER_TSTTSRC	0xf26c
+#define F367TER_TSTTSRC_7	0xf26c0080
+#define F367TER_TSRCFIFO_DSSSYNCB	0xf26c0040
+#define F367TER_TSRCFIFO_DPUNACTIVE	0xf26c0020
+#define F367TER_TSRCFIFO_DELSPEEDUP	0xf26c0010
+#define F367TER_TSTTSRC_NODIV3	0xf26c0008
+#define F367TER_TSTTSRC_FRFORCEPKT	0xf26c0004
+#define F367TER_SAT25_SDDORIGINE	0xf26c0002
+#define F367TER_TSTTSRC_INACTIVE	0xf26c0001
+
+/*	TSTTSRS */
+#define R367TER_TSTTSRS	0xf26d
+#define F367TER_TSTTSRS_7	0xf26d0080
+#define F367TER_TSTTSRS_6	0xf26d0040
+#define F367TER_TSTTSRS_5	0xf26d0020
+#define F367TER_TSTTSRS_4	0xf26d0010
+#define F367TER_TSTTSRS_3	0xf26d0008
+#define F367TER_TSTTSRS_2	0xf26d0004
+#define F367TER_TSTRS_DISRS2	0xf26d0002
+#define F367TER_TSTRS_DISRS1	0xf26d0001
+
+/* TSSTATEM */
+#define	R367TER_TSSTATEM	0xf270
+#define	F367TER_TSDIL_ON	0xf2700080
+#define	F367TER_TSSKIPRS_ON	0xf2700040
+#define	F367TER_TSRS_ON	0xf2700020
+#define	F367TER_TSDESCRAMB_ON	0xf2700010
+#define	F367TER_TSFRAME_MODE	0xf2700008
+#define	F367TER_TS_DISABLE	0xf2700004
+#define	F367TER_TSACM_MODE	0xf2700002
+#define	F367TER_TSOUT_NOSYNC	0xf2700001
+
+/* TSSTATEL */
+#define	R367TER_TSSTATEL	0xf271
+#define	F367TER_TSNOSYNCBYTE	0xf2710080
+#define	F367TER_TSPARITY_ON	0xf2710040
+#define	F367TER_TSSYNCOUTRS_ON	0xf2710020
+#define	F367TER_TSDVBS2_MODE	0xf2710010
+#define	F367TER_TSISSYI_ON	0xf2710008
+#define	F367TER_TSNPD_ON	0xf2710004
+#define	F367TER_TSCRC8_ON	0xf2710002
+#define	F367TER_TSDSS_PACKET	0xf2710001
+
+/* TSCFGH */
+#define	R367TER_TSCFGH	0xf272
+#define	F367TER_TSFIFO_DVBCI	0xf2720080
+#define	F367TER_TSFIFO_SERIAL	0xf2720040
+#define	F367TER_TSFIFO_TEIUPDATE	0xf2720020
+#define	F367TER_TSFIFO_DUTY50	0xf2720010
+#define	F367TER_TSFIFO_HSGNLOUT	0xf2720008
+#define	F367TER_TSFIFO_ERRMODE	0xf2720006
+#define	F367TER_RST_HWARE	0xf2720001
+
+/* TSCFGM */
+#define	R367TER_TSCFGM	0xf273
+#define	F367TER_TSFIFO_MANSPEED	0xf27300c0
+#define	F367TER_TSFIFO_PERMDATA	0xf2730020
+#define	F367TER_TSFIFO_NONEWSGNL	0xf2730010
+#define	F367TER_TSFIFO_BITSPEED	0xf2730008
+#define	F367TER_NPD_SPECDVBS2	0xf2730004
+#define	F367TER_TSFIFO_STOPCKDIS	0xf2730002
+#define	F367TER_TSFIFO_INVDATA	0xf2730001
+
+/* TSCFGL */
+#define	R367TER_TSCFGL	0xf274
+#define	F367TER_TSFIFO_BCLKDEL1cK	0xf27400c0
+#define	F367TER_BCHERROR_MODE	0xf2740030
+#define	F367TER_TSFIFO_NSGNL2dATA	0xf2740008
+#define	F367TER_TSFIFO_EMBINDVB	0xf2740004
+#define	F367TER_TSFIFO_DPUNACT	0xf2740002
+#define	F367TER_TSFIFO_NPDOFF	0xf2740001
+
+/* TSSYNC */
+#define	R367TER_TSSYNC	0xf275
+#define	F367TER_TSFIFO_PERMUTE	0xf2750080
+#define	F367TER_TSFIFO_FISCR3B	0xf2750060
+#define	F367TER_TSFIFO_SYNCMODE	0xf2750018
+#define	F367TER_TSFIFO_SYNCSEL	0xf2750007
+
+/* TSINSDELH */
+#define	R367TER_TSINSDELH	0xf276
+#define	F367TER_TSDEL_SYNCBYTE	0xf2760080
+#define	F367TER_TSDEL_XXHEADER	0xf2760040
+#define	F367TER_TSDEL_BBHEADER	0xf2760020
+#define	F367TER_TSDEL_DATAFIELD	0xf2760010
+#define	F367TER_TSINSDEL_ISCR	0xf2760008
+#define	F367TER_TSINSDEL_NPD	0xf2760004
+#define	F367TER_TSINSDEL_RSPARITY	0xf2760002
+#define	F367TER_TSINSDEL_CRC8	0xf2760001
+
+/* TSINSDELM */
+#define	R367TER_TSINSDELM	0xf277
+#define	F367TER_TSINS_BBPADDING	0xf2770080
+#define	F367TER_TSINS_BCHFEC	0xf2770040
+#define	F367TER_TSINS_LDPCFEC	0xf2770020
+#define	F367TER_TSINS_EMODCOD	0xf2770010
+#define	F367TER_TSINS_TOKEN	0xf2770008
+#define	F367TER_TSINS_XXXERR	0xf2770004
+#define	F367TER_TSINS_MATYPE	0xf2770002
+#define	F367TER_TSINS_UPL	0xf2770001
+
+/* TSINSDELL */
+#define	R367TER_TSINSDELL	0xf278
+#define	F367TER_TSINS_DFL	0xf2780080
+#define	F367TER_TSINS_SYNCD	0xf2780040
+#define	F367TER_TSINS_BLOCLEN	0xf2780020
+#define	F367TER_TSINS_SIGPCOUNT	0xf2780010
+#define	F367TER_TSINS_FIFO	0xf2780008
+#define	F367TER_TSINS_REALPACK	0xf2780004
+#define	F367TER_TSINS_TSCONFIG	0xf2780002
+#define	F367TER_TSINS_LATENCY	0xf2780001
+
+/* TSDIVN */
+#define	R367TER_TSDIVN	0xf279
+#define	F367TER_TSFIFO_LOWSPEED	0xf2790080
+#define	F367TER_BYTE_OVERSAMPLING	0xf2790070
+#define	F367TER_TSMANUAL_PACKETNBR	0xf279000f
+
+/* TSDIVPM */
+#define	R367TER_TSDIVPM	0xf27a
+#define	F367TER_TSMANUAL_P_HI	0xf27a00ff
+
+/* TSDIVPL */
+#define	R367TER_TSDIVPL	0xf27b
+#define	F367TER_TSMANUAL_P_LO	0xf27b00ff
+
+/* TSDIVQM */
+#define	R367TER_TSDIVQM	0xf27c
+#define	F367TER_TSMANUAL_Q_HI	0xf27c00ff
+
+/* TSDIVQL */
+#define	R367TER_TSDIVQL	0xf27d
+#define	F367TER_TSMANUAL_Q_LO	0xf27d00ff
+
+/* TSDILSTKM */
+#define	R367TER_TSDILSTKM	0xf27e
+#define	F367TER_TSFIFO_DILSTK_HI	0xf27e00ff
+
+/* TSDILSTKL */
+#define	R367TER_TSDILSTKL	0xf27f
+#define	F367TER_TSFIFO_DILSTK_LO	0xf27f00ff
+
+/* TSSPEED */
+#define	R367TER_TSSPEED	0xf280
+#define	F367TER_TSFIFO_OUTSPEED	0xf28000ff
+
+/* TSSTATUS */
+#define	R367TER_TSSTATUS	0xf281
+#define	F367TER_TSFIFO_LINEOK	0xf2810080
+#define	F367TER_TSFIFO_ERROR	0xf2810040
+#define	F367TER_TSFIFO_DATA7	0xf2810020
+#define	F367TER_TSFIFO_NOSYNC	0xf2810010
+#define	F367TER_ISCR_INITIALIZED	0xf2810008
+#define	F367TER_ISCR_UPDATED	0xf2810004
+#define	F367TER_SOFFIFO_UNREGUL	0xf2810002
+#define	F367TER_DIL_READY	0xf2810001
+
+/* TSSTATUS2 */
+#define	R367TER_TSSTATUS2	0xf282
+#define	F367TER_TSFIFO_DEMODSEL	0xf2820080
+#define	F367TER_TSFIFOSPEED_STORE	0xf2820040
+#define	F367TER_DILXX_RESET	0xf2820020
+#define	F367TER_TSSERIAL_IMPOSSIBLE	0xf2820010
+#define	F367TER_TSFIFO_UNDERSPEED	0xf2820008
+#define	F367TER_BITSPEED_EVENT	0xf2820004
+#define	F367TER_UL_SCRAMBDETECT	0xf2820002
+#define	F367TER_ULDTV67_FALSELOCK	0xf2820001
+
+/* TSBITRATEM */
+#define	R367TER_TSBITRATEM	0xf283
+#define	F367TER_TSFIFO_BITRATE_HI	0xf28300ff
+
+/* TSBITRATEL */
+#define	R367TER_TSBITRATEL	0xf284
+#define	F367TER_TSFIFO_BITRATE_LO	0xf28400ff
+
+/* TSPACKLENM */
+#define	R367TER_TSPACKLENM	0xf285
+#define	F367TER_TSFIFO_PACKCPT	0xf28500e0
+#define	F367TER_DIL_RPLEN_HI	0xf285001f
+
+/* TSPACKLENL */
+#define	R367TER_TSPACKLENL	0xf286
+#define	F367TER_DIL_RPLEN_LO	0xf28600ff
+
+/* TSBLOCLENM */
+#define	R367TER_TSBLOCLENM	0xf287
+#define	F367TER_TSFIFO_PFLEN_HI	0xf28700ff
+
+/* TSBLOCLENL */
+#define	R367TER_TSBLOCLENL	0xf288
+#define	F367TER_TSFIFO_PFLEN_LO	0xf28800ff
+
+/* TSDLYH */
+#define	R367TER_TSDLYH	0xf289
+#define	F367TER_SOFFIFO_TSTIMEVALID	0xf2890080
+#define	F367TER_SOFFIFO_SPEEDUP	0xf2890040
+#define	F367TER_SOFFIFO_STOP	0xf2890020
+#define	F367TER_SOFFIFO_REGULATED	0xf2890010
+#define	F367TER_SOFFIFO_REALSBOFF_HI	0xf289000f
+
+/* TSDLYM */
+#define	R367TER_TSDLYM	0xf28a
+#define	F367TER_SOFFIFO_REALSBOFF_MED	0xf28a00ff
+
+/* TSDLYL */
+#define	R367TER_TSDLYL	0xf28b
+#define	F367TER_SOFFIFO_REALSBOFF_LO	0xf28b00ff
+
+/* TSNPDAV */
+#define	R367TER_TSNPDAV	0xf28c
+#define	F367TER_TSNPD_AVERAGE	0xf28c00ff
+
+/* TSBUFSTATH */
+#define	R367TER_TSBUFSTATH	0xf28d
+#define	F367TER_TSISCR_3BYTES	0xf28d0080
+#define	F367TER_TSISCR_NEWDATA	0xf28d0040
+#define	F367TER_TSISCR_BUFSTAT_HI	0xf28d003f
+
+/* TSBUFSTATM */
+#define	R367TER_TSBUFSTATM	0xf28e
+#define	F367TER_TSISCR_BUFSTAT_MED	0xf28e00ff
+
+/* TSBUFSTATL */
+#define	R367TER_TSBUFSTATL	0xf28f
+#define	F367TER_TSISCR_BUFSTAT_LO	0xf28f00ff
+
+/* TSDEBUGM */
+#define	R367TER_TSDEBUGM	0xf290
+#define	F367TER_TSFIFO_ILLPACKET	0xf2900080
+#define	F367TER_DIL_NOSYNC	0xf2900040
+#define	F367TER_DIL_ISCR	0xf2900020
+#define	F367TER_DILOUT_BSYNCB	0xf2900010
+#define	F367TER_TSFIFO_EMPTYPKT	0xf2900008
+#define	F367TER_TSFIFO_EMPTYRD	0xf2900004
+#define	F367TER_SOFFIFO_STOPM	0xf2900002
+#define	F367TER_SOFFIFO_SPEEDUPM	0xf2900001
+
+/* TSDEBUGL */
+#define	R367TER_TSDEBUGL	0xf291
+#define	F367TER_TSFIFO_PACKLENFAIL	0xf2910080
+#define	F367TER_TSFIFO_SYNCBFAIL	0xf2910040
+#define	F367TER_TSFIFO_VITLIBRE	0xf2910020
+#define	F367TER_TSFIFO_BOOSTSPEEDM	0xf2910010
+#define	F367TER_TSFIFO_UNDERSPEEDM	0xf2910008
+#define	F367TER_TSFIFO_ERROR_EVNT	0xf2910004
+#define	F367TER_TSFIFO_FULL	0xf2910002
+#define	F367TER_TSFIFO_OVERFLOWM	0xf2910001
+
+/* TSDLYSETH */
+#define	R367TER_TSDLYSETH	0xf292
+#define	F367TER_SOFFIFO_OFFSET	0xf29200e0
+#define	F367TER_SOFFIFO_SYMBOFFSET_HI	0xf292001f
+
+/* TSDLYSETM */
+#define	R367TER_TSDLYSETM	0xf293
+#define	F367TER_SOFFIFO_SYMBOFFSET_MED	0xf29300ff
+
+/* TSDLYSETL */
+#define	R367TER_TSDLYSETL	0xf294
+#define	F367TER_SOFFIFO_SYMBOFFSET_LO	0xf29400ff
+
+/* TSOBSCFG */
+#define	R367TER_TSOBSCFG	0xf295
+#define	F367TER_TSFIFO_OBSCFG	0xf29500ff
+
+/* TSOBSM */
+#define	R367TER_TSOBSM	0xf296
+#define	F367TER_TSFIFO_OBSDATA_HI	0xf29600ff
+
+/* TSOBSL */
+#define	R367TER_TSOBSL	0xf297
+#define	F367TER_TSFIFO_OBSDATA_LO	0xf29700ff
+
+/* ERRCTRL1 */
+#define	R367TER_ERRCTRL1	0xf298
+#define	F367TER_ERR_SRC1	0xf29800f0
+#define	F367TER_ERRCTRL1_3	0xf2980008
+#define	F367TER_NUM_EVT1	0xf2980007
+
+/* ERRCNT1H */
+#define	R367TER_ERRCNT1H	0xf299
+#define	F367TER_ERRCNT1_OLDVALUE	0xf2990080
+#define	F367TER_ERR_CNT1	0xf299007f
+
+/* ERRCNT1M */
+#define	R367TER_ERRCNT1M	0xf29a
+#define	F367TER_ERR_CNT1_HI	0xf29a00ff
+
+/* ERRCNT1L */
+#define	R367TER_ERRCNT1L	0xf29b
+#define	F367TER_ERR_CNT1_LO	0xf29b00ff
+
+/* ERRCTRL2 */
+#define	R367TER_ERRCTRL2	0xf29c
+#define	F367TER_ERR_SRC2	0xf29c00f0
+#define	F367TER_ERRCTRL2_3	0xf29c0008
+#define	F367TER_NUM_EVT2	0xf29c0007
+
+/* ERRCNT2H */
+#define	R367TER_ERRCNT2H	0xf29d
+#define	F367TER_ERRCNT2_OLDVALUE	0xf29d0080
+#define	F367TER_ERR_CNT2_HI	0xf29d007f
+
+/* ERRCNT2M */
+#define	R367TER_ERRCNT2M	0xf29e
+#define	F367TER_ERR_CNT2_MED	0xf29e00ff
+
+/* ERRCNT2L */
+#define	R367TER_ERRCNT2L	0xf29f
+#define	F367TER_ERR_CNT2_LO	0xf29f00ff
+
+/* FECSPY */
+#define	R367TER_FECSPY	0xf2a0
+#define	F367TER_SPY_ENABLE	0xf2a00080
+#define	F367TER_NO_SYNCBYTE	0xf2a00040
+#define	F367TER_SERIAL_MODE	0xf2a00020
+#define	F367TER_UNUSUAL_PACKET	0xf2a00010
+#define	F367TER_BERMETER_DATAMODE	0xf2a0000c
+#define	F367TER_BERMETER_LMODE	0xf2a00002
+#define	F367TER_BERMETER_RESET	0xf2a00001
+
+/* FSPYCFG */
+#define	R367TER_FSPYCFG	0xf2a1
+#define	F367TER_FECSPY_INPUT	0xf2a100c0
+#define	F367TER_RST_ON_ERROR	0xf2a10020
+#define	F367TER_ONE_SHOT	0xf2a10010
+#define	F367TER_I2C_MOD	0xf2a1000c
+#define	F367TER_SPY_HYSTERESIS	0xf2a10003
+
+/* FSPYDATA */
+#define	R367TER_FSPYDATA	0xf2a2
+#define	F367TER_SPY_STUFFING	0xf2a20080
+#define	F367TER_NOERROR_PKTJITTER	0xf2a20040
+#define	F367TER_SPY_CNULLPKT	0xf2a20020
+#define	F367TER_SPY_OUTDATA_MODE	0xf2a2001f
+
+/* FSPYOUT */
+#define	R367TER_FSPYOUT	0xf2a3
+#define	F367TER_FSPY_DIRECT	0xf2a30080
+#define	F367TER_FSPYOUT_6	0xf2a30040
+#define	F367TER_SPY_OUTDATA_BUS	0xf2a30038
+#define	F367TER_STUFF_MODE	0xf2a30007
+
+/* FSTATUS */
+#define	R367TER_FSTATUS	0xf2a4
+#define	F367TER_SPY_ENDSIM	0xf2a40080
+#define	F367TER_VALID_SIM	0xf2a40040
+#define	F367TER_FOUND_SIGNAL	0xf2a40020
+#define	F367TER_DSS_SYNCBYTE	0xf2a40010
+#define	F367TER_RESULT_STATE	0xf2a4000f
+
+/* FGOODPACK */
+#define	R367TER_FGOODPACK	0xf2a5
+#define	F367TER_FGOOD_PACKET	0xf2a500ff
+
+/* FPACKCNT */
+#define	R367TER_FPACKCNT	0xf2a6
+#define	F367TER_FPACKET_COUNTER	0xf2a600ff
+
+/* FSPYMISC */
+#define	R367TER_FSPYMISC	0xf2a7
+#define	F367TER_FLABEL_COUNTER	0xf2a700ff
+
+/* FBERCPT4 */
+#define	R367TER_FBERCPT4	0xf2a8
+#define	F367TER_FBERMETER_CPT5	0xf2a800ff
+
+/* FBERCPT3 */
+#define	R367TER_FBERCPT3	0xf2a9
+#define	F367TER_FBERMETER_CPT4	0xf2a900ff
+
+/* FBERCPT2 */
+#define	R367TER_FBERCPT2	0xf2aa
+#define	F367TER_FBERMETER_CPT3	0xf2aa00ff
+
+/* FBERCPT1 */
+#define	R367TER_FBERCPT1	0xf2ab
+#define	F367TER_FBERMETER_CPT2	0xf2ab00ff
+
+/* FBERCPT0 */
+#define	R367TER_FBERCPT0	0xf2ac
+#define	F367TER_FBERMETER_CPT1	0xf2ac00ff
+
+/* FBERERR2 */
+#define	R367TER_FBERERR2	0xf2ad
+#define	F367TER_FBERMETER_ERR_HI	0xf2ad00ff
+
+/* FBERERR1 */
+#define	R367TER_FBERERR1	0xf2ae
+#define	F367TER_FBERMETER_ERR_MED	0xf2ae00ff
+
+/* FBERERR0 */
+#define	R367TER_FBERERR0	0xf2af
+#define	F367TER_FBERMETER_ERR_LO	0xf2af00ff
+
+/* FSTATESM */
+#define	R367TER_FSTATESM	0xf2b0
+#define	F367TER_RSTATE_F	0xf2b00080
+#define	F367TER_RSTATE_E	0xf2b00040
+#define	F367TER_RSTATE_D	0xf2b00020
+#define	F367TER_RSTATE_C	0xf2b00010
+#define	F367TER_RSTATE_B	0xf2b00008
+#define	F367TER_RSTATE_A	0xf2b00004
+#define	F367TER_RSTATE_9	0xf2b00002
+#define	F367TER_RSTATE_8	0xf2b00001
+
+/* FSTATESL */
+#define	R367TER_FSTATESL	0xf2b1
+#define	F367TER_RSTATE_7	0xf2b10080
+#define	F367TER_RSTATE_6	0xf2b10040
+#define	F367TER_RSTATE_5	0xf2b10020
+#define	F367TER_RSTATE_4	0xf2b10010
+#define	F367TER_RSTATE_3	0xf2b10008
+#define	F367TER_RSTATE_2	0xf2b10004
+#define	F367TER_RSTATE_1	0xf2b10002
+#define	F367TER_RSTATE_0	0xf2b10001
+
+/* FSPYBER */
+#define	R367TER_FSPYBER	0xf2b2
+#define	F367TER_FSPYBER_7	0xf2b20080
+#define	F367TER_FSPYOBS_XORREAD	0xf2b20040
+#define	F367TER_FSPYBER_OBSMODE	0xf2b20020
+#define	F367TER_FSPYBER_SYNCBYTE	0xf2b20010
+#define	F367TER_FSPYBER_UNSYNC	0xf2b20008
+#define	F367TER_FSPYBER_CTIME	0xf2b20007
+
+/* FSPYDISTM */
+#define	R367TER_FSPYDISTM	0xf2b3
+#define	F367TER_PKTTIME_DISTANCE_HI	0xf2b300ff
+
+/* FSPYDISTL */
+#define	R367TER_FSPYDISTL	0xf2b4
+#define	F367TER_PKTTIME_DISTANCE_LO	0xf2b400ff
+
+/* FSPYOBS7 */
+#define	R367TER_FSPYOBS7	0xf2b8
+#define	F367TER_FSPYOBS_SPYFAIL	0xf2b80080
+#define	F367TER_FSPYOBS_SPYFAIL1	0xf2b80040
+#define	F367TER_FSPYOBS_ERROR	0xf2b80020
+#define	F367TER_FSPYOBS_STROUT	0xf2b80010
+#define	F367TER_FSPYOBS_RESULTSTATE1	0xf2b8000f
+
+/* FSPYOBS6 */
+#define	R367TER_FSPYOBS6	0xf2b9
+#define	F367TER_FSPYOBS_RESULTSTATe0	0xf2b900f0
+#define	F367TER_FSPYOBS_RESULTSTATEM1	0xf2b9000f
+
+/* FSPYOBS5 */
+#define	R367TER_FSPYOBS5	0xf2ba
+#define	F367TER_FSPYOBS_BYTEOFPACKET1	0xf2ba00ff
+
+/* FSPYOBS4 */
+#define	R367TER_FSPYOBS4	0xf2bb
+#define	F367TER_FSPYOBS_BYTEVALUE1	0xf2bb00ff
+
+/* FSPYOBS3 */
+#define	R367TER_FSPYOBS3	0xf2bc
+#define	F367TER_FSPYOBS_DATA1	0xf2bc00ff
+
+/* FSPYOBS2 */
+#define	R367TER_FSPYOBS2	0xf2bd
+#define	F367TER_FSPYOBS_DATa0	0xf2bd00ff
+
+/* FSPYOBS1 */
+#define	R367TER_FSPYOBS1	0xf2be
+#define	F367TER_FSPYOBS_DATAM1	0xf2be00ff
+
+/* FSPYOBS0 */
+#define	R367TER_FSPYOBS0	0xf2bf
+#define	F367TER_FSPYOBS_DATAM2	0xf2bf00ff
+
+/* SFDEMAP */
+#define	R367TER_SFDEMAP	0xf2c0
+#define	F367TER_SFDEMAP_7	0xf2c00080
+#define	F367TER_SFEC_K_DIVIDER_VIT	0xf2c0007f
+
+/* SFERROR */
+#define	R367TER_SFERROR	0xf2c1
+#define	F367TER_SFEC_REGERR_VIT	0xf2c100ff
+
+/* SFAVSR */
+#define	R367TER_SFAVSR	0xf2c2
+#define	F367TER_SFEC_SUMERRORS	0xf2c20080
+#define	F367TER_SERROR_MAXMODE	0xf2c20040
+#define	F367TER_SN_SFEC	0xf2c20030
+#define	F367TER_KDIV_MODE_SFEC	0xf2c2000c
+#define	F367TER_SFAVSR_1	0xf2c20002
+#define	F367TER_SFAVSR_0	0xf2c20001
+
+/* SFECSTATUS */
+#define	R367TER_SFECSTATUS	0xf2c3
+#define	F367TER_SFEC_ON	0xf2c30080
+#define	F367TER_SFSTATUS_6	0xf2c30040
+#define	F367TER_SFSTATUS_5	0xf2c30020
+#define	F367TER_SFSTATUS_4	0xf2c30010
+#define	F367TER_LOCKEDSFEC	0xf2c30008
+#define	F367TER_SFEC_DELOCK	0xf2c30004
+#define	F367TER_SFEC_DEMODSEL1	0xf2c30002
+#define	F367TER_SFEC_OVFON	0xf2c30001
+
+/* SFKDIV12 */
+#define	R367TER_SFKDIV12	0xf2c4
+#define	F367TER_SFECKDIV12_MAN	0xf2c40080
+#define	F367TER_SFEC_K_DIVIDER_12	0xf2c4007f
+
+/* SFKDIV23 */
+#define	R367TER_SFKDIV23	0xf2c5
+#define	F367TER_SFECKDIV23_MAN	0xf2c50080
+#define	F367TER_SFEC_K_DIVIDER_23	0xf2c5007f
+
+/* SFKDIV34 */
+#define	R367TER_SFKDIV34	0xf2c6
+#define	F367TER_SFECKDIV34_MAN	0xf2c60080
+#define	F367TER_SFEC_K_DIVIDER_34	0xf2c6007f
+
+/* SFKDIV56 */
+#define	R367TER_SFKDIV56	0xf2c7
+#define	F367TER_SFECKDIV56_MAN	0xf2c70080
+#define	F367TER_SFEC_K_DIVIDER_56	0xf2c7007f
+
+/* SFKDIV67 */
+#define	R367TER_SFKDIV67	0xf2c8
+#define	F367TER_SFECKDIV67_MAN	0xf2c80080
+#define	F367TER_SFEC_K_DIVIDER_67	0xf2c8007f
+
+/* SFKDIV78 */
+#define	R367TER_SFKDIV78	0xf2c9
+#define	F367TER_SFECKDIV78_MAN	0xf2c90080
+#define	F367TER_SFEC_K_DIVIDER_78	0xf2c9007f
+
+/* SFDILSTKM */
+#define	R367TER_SFDILSTKM	0xf2ca
+#define	F367TER_SFEC_PACKCPT	0xf2ca00e0
+#define	F367TER_SFEC_DILSTK_HI	0xf2ca001f
+
+/* SFDILSTKL */
+#define	R367TER_SFDILSTKL	0xf2cb
+#define	F367TER_SFEC_DILSTK_LO	0xf2cb00ff
+
+/* SFSTATUS */
+#define	R367TER_SFSTATUS	0xf2cc
+#define	F367TER_SFEC_LINEOK	0xf2cc0080
+#define	F367TER_SFEC_ERROR	0xf2cc0040
+#define	F367TER_SFEC_DATA7	0xf2cc0020
+#define	F367TER_SFEC_OVERFLOW	0xf2cc0010
+#define	F367TER_SFEC_DEMODSEL2	0xf2cc0008
+#define	F367TER_SFEC_NOSYNC	0xf2cc0004
+#define	F367TER_SFEC_UNREGULA	0xf2cc0002
+#define	F367TER_SFEC_READY	0xf2cc0001
+
+/* SFDLYH */
+#define	R367TER_SFDLYH	0xf2cd
+#define	F367TER_SFEC_TSTIMEVALID	0xf2cd0080
+#define	F367TER_SFEC_SPEEDUP	0xf2cd0040
+#define	F367TER_SFEC_STOP	0xf2cd0020
+#define	F367TER_SFEC_REGULATED	0xf2cd0010
+#define	F367TER_SFEC_REALSYMBOFFSET	0xf2cd000f
+
+/* SFDLYM */
+#define	R367TER_SFDLYM	0xf2ce
+#define	F367TER_SFEC_REALSYMBOFFSET_HI	0xf2ce00ff
+
+/* SFDLYL */
+#define	R367TER_SFDLYL	0xf2cf
+#define	F367TER_SFEC_REALSYMBOFFSET_LO	0xf2cf00ff
+
+/* SFDLYSETH */
+#define	R367TER_SFDLYSETH	0xf2d0
+#define	F367TER_SFEC_OFFSET	0xf2d000e0
+#define	F367TER_SFECDLYSETH_4	0xf2d00010
+#define	F367TER_RST_SFEC	0xf2d00008
+#define	F367TER_SFECDLYSETH_2	0xf2d00004
+#define	F367TER_SFEC_DISABLE	0xf2d00002
+#define	F367TER_SFEC_UNREGUL	0xf2d00001
+
+/* SFDLYSETM */
+#define	R367TER_SFDLYSETM	0xf2d1
+#define	F367TER_SFECDLYSETM_7	0xf2d10080
+#define	F367TER_SFEC_SYMBOFFSET_HI	0xf2d1007f
+
+/* SFDLYSETL */
+#define	R367TER_SFDLYSETL	0xf2d2
+#define	F367TER_SFEC_SYMBOFFSET_LO	0xf2d200ff
+
+/* SFOBSCFG */
+#define	R367TER_SFOBSCFG	0xf2d3
+#define	F367TER_SFEC_OBSCFG	0xf2d300ff
+
+/* SFOBSM */
+#define	R367TER_SFOBSM	0xf2d4
+#define	F367TER_SFEC_OBSDATA_HI	0xf2d400ff
+
+/* SFOBSL */
+#define	R367TER_SFOBSL	0xf2d5
+#define	F367TER_SFEC_OBSDATA_LO	0xf2d500ff
+
+/* SFECINFO */
+#define	R367TER_SFECINFO	0xf2d6
+#define	F367TER_SFECINFO_7	0xf2d60080
+#define	F367TER_SFEC_SYNCDLSB	0xf2d60070
+#define	F367TER_SFCE_S1cPHASE	0xf2d6000f
+
+/* SFERRCTRL */
+#define	R367TER_SFERRCTRL	0xf2d8
+#define	F367TER_SFEC_ERR_SOURCE	0xf2d800f0
+#define	F367TER_SFERRCTRL_3	0xf2d80008
+#define	F367TER_SFEC_NUM_EVENT	0xf2d80007
+
+/* SFERRCNTH */
+#define	R367TER_SFERRCNTH	0xf2d9
+#define	F367TER_SFERRC_OLDVALUE	0xf2d90080
+#define	F367TER_SFEC_ERR_CNT	0xf2d9007f
+
+/* SFERRCNTM */
+#define	R367TER_SFERRCNTM	0xf2da
+#define	F367TER_SFEC_ERR_CNT_HI	0xf2da00ff
+
+/* SFERRCNTL */
+#define	R367TER_SFERRCNTL	0xf2db
+#define	F367TER_SFEC_ERR_CNT_LO	0xf2db00ff
+
+/* SYMBRATEM */
+#define	R367TER_SYMBRATEM	0xf2e0
+#define	F367TER_DEFGEN_SYMBRATE_HI	0xf2e000ff
+
+/* SYMBRATEL */
+#define	R367TER_SYMBRATEL	0xf2e1
+#define	F367TER_DEFGEN_SYMBRATE_LO	0xf2e100ff
+
+/* SYMBSTATUS */
+#define	R367TER_SYMBSTATUS	0xf2e2
+#define	F367TER_SYMBDLINE2_OFF	0xf2e20080
+#define	F367TER_SDDL_REINIT1	0xf2e20040
+#define	F367TER_SDD_REINIT1	0xf2e20020
+#define	F367TER_TOKENID_ERROR	0xf2e20010
+#define	F367TER_SYMBRATE_OVERFLOW	0xf2e20008
+#define	F367TER_SYMBRATE_UNDERFLOW	0xf2e20004
+#define	F367TER_TOKENID_RSTEVENT	0xf2e20002
+#define	F367TER_TOKENID_RESET1	0xf2e20001
+
+/* SYMBCFG */
+#define	R367TER_SYMBCFG	0xf2e3
+#define	F367TER_SYMBCFG_7	0xf2e30080
+#define	F367TER_SYMBCFG_6	0xf2e30040
+#define	F367TER_SYMBCFG_5	0xf2e30020
+#define	F367TER_SYMBCFG_4	0xf2e30010
+#define	F367TER_SYMRATE_FSPEED	0xf2e3000c
+#define	F367TER_SYMRATE_SSPEED	0xf2e30003
+
+/* SYMBFIFOM */
+#define	R367TER_SYMBFIFOM	0xf2e4
+#define	F367TER_SYMBFIFOM_7	0xf2e40080
+#define	F367TER_SYMBFIFOM_6	0xf2e40040
+#define	F367TER_DEFGEN_SYMFIFO_HI	0xf2e4003f
+
+/* SYMBFIFOL */
+#define	R367TER_SYMBFIFOL	0xf2e5
+#define	F367TER_DEFGEN_SYMFIFO_LO	0xf2e500ff
+
+/* SYMBOFFSM */
+#define	R367TER_SYMBOFFSM	0xf2e6
+#define	F367TER_TOKENID_RESET2	0xf2e60080
+#define	F367TER_SDDL_REINIT2	0xf2e60040
+#define	F367TER_SDD_REINIT2	0xf2e60020
+#define	F367TER_SYMBOFFSM_4	0xf2e60010
+#define	F367TER_SYMBOFFSM_3	0xf2e60008
+#define	F367TER_DEFGEN_SYMBOFFSET_HI	0xf2e60007
+
+/* SYMBOFFSL */
+#define	R367TER_SYMBOFFSL	0xf2e7
+#define	F367TER_DEFGEN_SYMBOFFSET_LO	0xf2e700ff
+
+/* DEBUG_LT4 */
+#define	R367TER_DEBUG_LT4	0xf400
+#define	F367TER_F_DEBUG_LT4	0xf40000ff
+
+/* DEBUG_LT5 */
+#define	R367TER_DEBUG_LT5	0xf401
+#define	F367TER_F_DEBUG_LT5	0xf40100ff
+
+/* DEBUG_LT6 */
+#define	R367TER_DEBUG_LT6	0xf402
+#define	F367TER_F_DEBUG_LT6	0xf40200ff
+
+/* DEBUG_LT7 */
+#define	R367TER_DEBUG_LT7	0xf403
+#define	F367TER_F_DEBUG_LT7	0xf40300ff
+
+/* DEBUG_LT8 */
+#define	R367TER_DEBUG_LT8	0xf404
+#define	F367TER_F_DEBUG_LT8	0xf40400ff
+
+/* DEBUG_LT9 */
+#define	R367TER_DEBUG_LT9	0xf405
+#define	F367TER_F_DEBUG_LT9	0xf40500ff
+
+#define STV0367TER_NBREGS	445
+
+/* ID */
+#define	R367CAB_ID	0xf000
+#define	F367CAB_IDENTIFICATIONREGISTER	0xf00000ff
+
+/* I2CRPT */
+#define	R367CAB_I2CRPT	0xf001
+#define	F367CAB_I2CT_ON	0xf0010080
+#define	F367CAB_ENARPT_LEVEL	0xf0010070
+#define	F367CAB_SCLT_DELAY	0xf0010008
+#define	F367CAB_SCLT_NOD	0xf0010004
+#define	F367CAB_STOP_ENABLE	0xf0010002
+#define	F367CAB_SDAT_NOD	0xf0010001
+
+/* TOPCTRL */
+#define	R367CAB_TOPCTRL	0xf002
+#define	F367CAB_STDBY	0xf0020080
+#define	F367CAB_STDBY_CORE	0xf0020020
+#define	F367CAB_QAM_COFDM	0xf0020010
+#define	F367CAB_TS_DIS	0xf0020008
+#define	F367CAB_DIR_CLK_216	0xf0020004
+
+/* IOCFG0 */
+#define	R367CAB_IOCFG0	0xf003
+#define	F367CAB_OP0_SD	0xf0030080
+#define	F367CAB_OP0_VAL	0xf0030040
+#define	F367CAB_OP0_OD	0xf0030020
+#define	F367CAB_OP0_INV	0xf0030010
+#define	F367CAB_OP0_DACVALUE_HI	0xf003000f
+
+/* DAc0R */
+#define	R367CAB_DAC0R	0xf004
+#define	F367CAB_OP0_DACVALUE_LO	0xf00400ff
+
+/* IOCFG1 */
+#define	R367CAB_IOCFG1	0xf005
+#define	F367CAB_IP0	0xf0050040
+#define	F367CAB_OP1_OD	0xf0050020
+#define	F367CAB_OP1_INV	0xf0050010
+#define	F367CAB_OP1_DACVALUE_HI	0xf005000f
+
+/* DAC1R */
+#define	R367CAB_DAC1R	0xf006
+#define	F367CAB_OP1_DACVALUE_LO	0xf00600ff
+
+/* IOCFG2 */
+#define	R367CAB_IOCFG2	0xf007
+#define	F367CAB_OP2_LOCK_CONF	0xf00700e0
+#define	F367CAB_OP2_OD	0xf0070010
+#define	F367CAB_OP2_VAL	0xf0070008
+#define	F367CAB_OP1_LOCK_CONF	0xf0070007
+
+/* SDFR */
+#define	R367CAB_SDFR	0xf008
+#define	F367CAB_OP0_FREQ	0xf00800f0
+#define	F367CAB_OP1_FREQ	0xf008000f
+
+/* AUX_CLK */
+#define	R367CAB_AUX_CLK	0xf00a
+#define	F367CAB_AUXFEC_CTL	0xf00a00c0
+#define	F367CAB_DIS_CKX4	0xf00a0020
+#define	F367CAB_CKSEL	0xf00a0018
+#define	F367CAB_CKDIV_PROG	0xf00a0006
+#define	F367CAB_AUXCLK_ENA	0xf00a0001
+
+/* FREESYS1 */
+#define	R367CAB_FREESYS1	0xf00b
+#define	F367CAB_FREESYS_1	0xf00b00ff
+
+/* FREESYS2 */
+#define	R367CAB_FREESYS2	0xf00c
+#define	F367CAB_FREESYS_2	0xf00c00ff
+
+/* FREESYS3 */
+#define	R367CAB_FREESYS3	0xf00d
+#define	F367CAB_FREESYS_3	0xf00d00ff
+
+/* GPIO_CFG */
+#define	R367CAB_GPIO_CFG	0xf00e
+#define	F367CAB_GPIO7_OD	0xf00e0080
+#define	F367CAB_GPIO7_CFG	0xf00e0040
+#define	F367CAB_GPIO6_OD	0xf00e0020
+#define	F367CAB_GPIO6_CFG	0xf00e0010
+#define	F367CAB_GPIO5_OD	0xf00e0008
+#define	F367CAB_GPIO5_CFG	0xf00e0004
+#define	F367CAB_GPIO4_OD	0xf00e0002
+#define	F367CAB_GPIO4_CFG	0xf00e0001
+
+/* GPIO_CMD */
+#define	R367CAB_GPIO_CMD	0xf00f
+#define	F367CAB_GPIO7_VAL	0xf00f0008
+#define	F367CAB_GPIO6_VAL	0xf00f0004
+#define	F367CAB_GPIO5_VAL	0xf00f0002
+#define	F367CAB_GPIO4_VAL	0xf00f0001
+
+/* TSTRES */
+#define	R367CAB_TSTRES	0xf0c0
+#define	F367CAB_FRES_DISPLAY	0xf0c00080
+#define	F367CAB_FRES_FIFO_AD	0xf0c00020
+#define	F367CAB_FRESRS	0xf0c00010
+#define	F367CAB_FRESACS	0xf0c00008
+#define	F367CAB_FRESFEC	0xf0c00004
+#define	F367CAB_FRES_PRIF	0xf0c00002
+#define	F367CAB_FRESCORE	0xf0c00001
+
+/* ANACTRL */
+#define	R367CAB_ANACTRL	0xf0c1
+#define	F367CAB_BYPASS_XTAL	0xf0c10040
+#define	F367CAB_BYPASS_PLLXN	0xf0c1000c
+#define	F367CAB_DIS_PAD_OSC	0xf0c10002
+#define	F367CAB_STDBY_PLLXN	0xf0c10001
+
+/* TSTBUS */
+#define	R367CAB_TSTBUS	0xf0c2
+#define	F367CAB_TS_BYTE_CLK_INV	0xf0c20080
+#define	F367CAB_CFG_IP	0xf0c20070
+#define	F367CAB_CFG_TST	0xf0c2000f
+
+/* RF_AGC1 */
+#define	R367CAB_RF_AGC1	0xf0d4
+#define	F367CAB_RF_AGC1_LEVEL_HI	0xf0d400ff
+
+/* RF_AGC2 */
+#define	R367CAB_RF_AGC2	0xf0d5
+#define	F367CAB_REF_ADGP	0xf0d50080
+#define	F367CAB_STDBY_ADCGP	0xf0d50020
+#define	F367CAB_RF_AGC1_LEVEL_LO	0xf0d50003
+
+/* ANADIGCTRL */
+#define	R367CAB_ANADIGCTRL	0xf0d7
+#define	F367CAB_SEL_CLKDEM	0xf0d70020
+#define	F367CAB_EN_BUFFER_Q	0xf0d70010
+#define	F367CAB_EN_BUFFER_I	0xf0d70008
+#define	F367CAB_ADC_RIS_EGDE	0xf0d70004
+#define	F367CAB_SGN_ADC	0xf0d70002
+#define	F367CAB_SEL_AD12_SYNC	0xf0d70001
+
+/* PLLMDIV */
+#define	R367CAB_PLLMDIV	0xf0d8
+#define	F367CAB_PLL_MDIV	0xf0d800ff
+
+/* PLLNDIV */
+#define	R367CAB_PLLNDIV	0xf0d9
+#define	F367CAB_PLL_NDIV	0xf0d900ff
+
+/* PLLSETUP */
+#define	R367CAB_PLLSETUP	0xf0da
+#define	F367CAB_PLL_PDIV	0xf0da0070
+#define	F367CAB_PLL_KDIV	0xf0da000f
+
+/* DUAL_AD12 */
+#define	R367CAB_DUAL_AD12	0xf0db
+#define	F367CAB_FS20M	0xf0db0020
+#define	F367CAB_FS50M	0xf0db0010
+#define	F367CAB_INMODe0	0xf0db0008
+#define	F367CAB_POFFQ	0xf0db0004
+#define	F367CAB_POFFI	0xf0db0002
+#define	F367CAB_INMODE1	0xf0db0001
+
+/* TSTBIST */
+#define	R367CAB_TSTBIST	0xf0dc
+#define	F367CAB_TST_BYP_CLK	0xf0dc0080
+#define	F367CAB_TST_GCLKENA_STD	0xf0dc0040
+#define	F367CAB_TST_GCLKENA	0xf0dc0020
+#define	F367CAB_TST_MEMBIST	0xf0dc001f
+
+/* CTRL_1 */
+#define	R367CAB_CTRL_1	0xf402
+#define	F367CAB_SOFT_RST	0xf4020080
+#define	F367CAB_EQU_RST	0xf4020008
+#define	F367CAB_CRL_RST	0xf4020004
+#define	F367CAB_TRL_RST	0xf4020002
+#define	F367CAB_AGC_RST	0xf4020001
+
+/* CTRL_2 */
+#define	R367CAB_CTRL_2	0xf403
+#define	F367CAB_DEINT_RST	0xf4030008
+#define	F367CAB_RS_RST	0xf4030004
+
+/* IT_STATUS1 */
+#define	R367CAB_IT_STATUS1	0xf408
+#define	F367CAB_SWEEP_OUT	0xf4080080
+#define	F367CAB_FSM_CRL	0xf4080040
+#define	F367CAB_CRL_LOCK	0xf4080020
+#define	F367CAB_MFSM	0xf4080010
+#define	F367CAB_TRL_LOCK	0xf4080008
+#define	F367CAB_TRL_AGC_LIMIT	0xf4080004
+#define	F367CAB_ADJ_AGC_LOCK	0xf4080002
+#define	F367CAB_AGC_QAM_LOCK	0xf4080001
+
+/* IT_STATUS2 */
+#define	R367CAB_IT_STATUS2	0xf409
+#define	F367CAB_TSMF_CNT	0xf4090080
+#define	F367CAB_TSMF_EOF	0xf4090040
+#define	F367CAB_TSMF_RDY	0xf4090020
+#define	F367CAB_FEC_NOCORR	0xf4090010
+#define	F367CAB_SYNCSTATE	0xf4090008
+#define	F367CAB_DEINT_LOCK	0xf4090004
+#define	F367CAB_FADDING_FRZ	0xf4090002
+#define	F367CAB_TAPMON_ALARM	0xf4090001
+
+/* IT_EN1 */
+#define	R367CAB_IT_EN1	0xf40a
+#define	F367CAB_SWEEP_OUTE	0xf40a0080
+#define	F367CAB_FSM_CRLE	0xf40a0040
+#define	F367CAB_CRL_LOCKE	0xf40a0020
+#define	F367CAB_MFSME	0xf40a0010
+#define	F367CAB_TRL_LOCKE	0xf40a0008
+#define	F367CAB_TRL_AGC_LIMITE	0xf40a0004
+#define	F367CAB_ADJ_AGC_LOCKE	0xf40a0002
+#define	F367CAB_AGC_LOCKE	0xf40a0001
+
+/* IT_EN2 */
+#define	R367CAB_IT_EN2	0xf40b
+#define	F367CAB_TSMF_CNTE	0xf40b0080
+#define	F367CAB_TSMF_EOFE	0xf40b0040
+#define	F367CAB_TSMF_RDYE	0xf40b0020
+#define	F367CAB_FEC_NOCORRE	0xf40b0010
+#define	F367CAB_SYNCSTATEE	0xf40b0008
+#define	F367CAB_DEINT_LOCKE	0xf40b0004
+#define	F367CAB_FADDING_FRZE	0xf40b0002
+#define	F367CAB_TAPMON_ALARME	0xf40b0001
+
+/* CTRL_STATUS */
+#define	R367CAB_CTRL_STATUS	0xf40c
+#define	F367CAB_QAMFEC_LOCK	0xf40c0004
+#define	F367CAB_TSMF_LOCK	0xf40c0002
+#define	F367CAB_TSMF_ERROR	0xf40c0001
+
+/* TEST_CTL */
+#define	R367CAB_TEST_CTL	0xf40f
+#define	F367CAB_TST_BLK_SEL	0xf40f0060
+#define	F367CAB_TST_BUS_SEL	0xf40f001f
+
+/* AGC_CTL */
+#define	R367CAB_AGC_CTL	0xf410
+#define	F367CAB_AGC_LCK_TH	0xf41000f0
+#define	F367CAB_AGC_ACCUMRSTSEL	0xf4100007
+
+/* AGC_IF_CFG */
+#define	R367CAB_AGC_IF_CFG	0xf411
+#define	F367CAB_AGC_IF_BWSEL	0xf41100f0
+#define	F367CAB_AGC_IF_FREEZE	0xf4110002
+
+/* AGC_RF_CFG */
+#define	R367CAB_AGC_RF_CFG	0xf412
+#define	F367CAB_AGC_RF_BWSEL	0xf4120070
+#define	F367CAB_AGC_RF_FREEZE	0xf4120002
+
+/* AGC_PWM_CFG */
+#define	R367CAB_AGC_PWM_CFG	0xf413
+#define	F367CAB_AGC_RF_PWM_TST	0xf4130080
+#define	F367CAB_AGC_RF_PWM_INV	0xf4130040
+#define	F367CAB_AGC_IF_PWM_TST	0xf4130008
+#define	F367CAB_AGC_IF_PWM_INV	0xf4130004
+#define	F367CAB_AGC_PWM_CLKDIV	0xf4130003
+
+/* AGC_PWR_REF_L */
+#define	R367CAB_AGC_PWR_REF_L	0xf414
+#define	F367CAB_AGC_PWRREF_LO	0xf41400ff
+
+/* AGC_PWR_REF_H */
+#define	R367CAB_AGC_PWR_REF_H	0xf415
+#define	F367CAB_AGC_PWRREF_HI	0xf4150003
+
+/* AGC_RF_TH_L */
+#define	R367CAB_AGC_RF_TH_L	0xf416
+#define	F367CAB_AGC_RF_TH_LO	0xf41600ff
+
+/* AGC_RF_TH_H */
+#define	R367CAB_AGC_RF_TH_H	0xf417
+#define	F367CAB_AGC_RF_TH_HI	0xf417000f
+
+/* AGC_IF_LTH_L */
+#define	R367CAB_AGC_IF_LTH_L	0xf418
+#define	F367CAB_AGC_IF_THLO_LO	0xf41800ff
+
+/* AGC_IF_LTH_H */
+#define	R367CAB_AGC_IF_LTH_H	0xf419
+#define	F367CAB_AGC_IF_THLO_HI	0xf419000f
+
+/* AGC_IF_HTH_L */
+#define	R367CAB_AGC_IF_HTH_L	0xf41a
+#define	F367CAB_AGC_IF_THHI_LO	0xf41a00ff
+
+/* AGC_IF_HTH_H */
+#define	R367CAB_AGC_IF_HTH_H	0xf41b
+#define	F367CAB_AGC_IF_THHI_HI	0xf41b000f
+
+/* AGC_PWR_RD_L */
+#define	R367CAB_AGC_PWR_RD_L	0xf41c
+#define	F367CAB_AGC_PWR_WORD_LO	0xf41c00ff
+
+/* AGC_PWR_RD_M */
+#define	R367CAB_AGC_PWR_RD_M	0xf41d
+#define	F367CAB_AGC_PWR_WORD_ME	0xf41d00ff
+
+/* AGC_PWR_RD_H */
+#define	R367CAB_AGC_PWR_RD_H	0xf41e
+#define	F367CAB_AGC_PWR_WORD_HI	0xf41e0003
+
+/* AGC_PWM_IFCMD_L */
+#define	R367CAB_AGC_PWM_IFCMD_L	0xf420
+#define	F367CAB_AGC_IF_PWMCMD_LO	0xf42000ff
+
+/* AGC_PWM_IFCMD_H */
+#define	R367CAB_AGC_PWM_IFCMD_H	0xf421
+#define	F367CAB_AGC_IF_PWMCMD_HI	0xf421000f
+
+/* AGC_PWM_RFCMD_L */
+#define	R367CAB_AGC_PWM_RFCMD_L	0xf422
+#define	F367CAB_AGC_RF_PWMCMD_LO	0xf42200ff
+
+/* AGC_PWM_RFCMD_H */
+#define	R367CAB_AGC_PWM_RFCMD_H	0xf423
+#define	F367CAB_AGC_RF_PWMCMD_HI	0xf423000f
+
+/* IQDEM_CFG */
+#define	R367CAB_IQDEM_CFG	0xf424
+#define	F367CAB_IQDEM_CLK_SEL	0xf4240004
+#define	F367CAB_IQDEM_INVIQ	0xf4240002
+#define	F367CAB_IQDEM_A2dTYPE	0xf4240001
+
+/* MIX_NCO_LL */
+#define	R367CAB_MIX_NCO_LL	0xf425
+#define	F367CAB_MIX_NCO_INC_LL	0xf42500ff
+
+/* MIX_NCO_HL */
+#define	R367CAB_MIX_NCO_HL	0xf426
+#define	F367CAB_MIX_NCO_INC_HL	0xf42600ff
+
+/* MIX_NCO_HH */
+#define	R367CAB_MIX_NCO_HH	0xf427
+#define	F367CAB_MIX_NCO_INVCNST	0xf4270080
+#define	F367CAB_MIX_NCO_INC_HH	0xf427007f
+
+/* SRC_NCO_LL */
+#define	R367CAB_SRC_NCO_LL	0xf428
+#define	F367CAB_SRC_NCO_INC_LL	0xf42800ff
+
+/* SRC_NCO_LH */
+#define	R367CAB_SRC_NCO_LH	0xf429
+#define	F367CAB_SRC_NCO_INC_LH	0xf42900ff
+
+/* SRC_NCO_HL */
+#define	R367CAB_SRC_NCO_HL	0xf42a
+#define	F367CAB_SRC_NCO_INC_HL	0xf42a00ff
+
+/* SRC_NCO_HH */
+#define	R367CAB_SRC_NCO_HH	0xf42b
+#define	F367CAB_SRC_NCO_INC_HH	0xf42b007f
+
+/* IQDEM_GAIN_SRC_L */
+#define	R367CAB_IQDEM_GAIN_SRC_L	0xf42c
+#define	F367CAB_GAIN_SRC_LO	0xf42c00ff
+
+/* IQDEM_GAIN_SRC_H */
+#define	R367CAB_IQDEM_GAIN_SRC_H	0xf42d
+#define	F367CAB_GAIN_SRC_HI	0xf42d0003
+
+/* IQDEM_DCRM_CFG_LL */
+#define	R367CAB_IQDEM_DCRM_CFG_LL	0xf430
+#define	F367CAB_DCRM0_DCIN_L	0xf43000ff
+
+/* IQDEM_DCRM_CFG_LH */
+#define	R367CAB_IQDEM_DCRM_CFG_LH	0xf431
+#define	F367CAB_DCRM1_I_DCIN_L	0xf43100fc
+#define	F367CAB_DCRM0_DCIN_H	0xf4310003
+
+/* IQDEM_DCRM_CFG_HL */
+#define	R367CAB_IQDEM_DCRM_CFG_HL	0xf432
+#define	F367CAB_DCRM1_Q_DCIN_L	0xf43200f0
+#define	F367CAB_DCRM1_I_DCIN_H	0xf432000f
+
+/* IQDEM_DCRM_CFG_HH */
+#define	R367CAB_IQDEM_DCRM_CFG_HH	0xf433
+#define	F367CAB_DCRM1_FRZ	0xf4330080
+#define	F367CAB_DCRM0_FRZ	0xf4330040
+#define	F367CAB_DCRM1_Q_DCIN_H	0xf433003f
+
+/* IQDEM_ADJ_COEFf0 */
+#define	R367CAB_IQDEM_ADJ_COEFF0	0xf434
+#define	F367CAB_ADJIIR_COEFF10_L	0xf43400ff
+
+/* IQDEM_ADJ_COEFF1 */
+#define	R367CAB_IQDEM_ADJ_COEFF1	0xf435
+#define	F367CAB_ADJIIR_COEFF11_L	0xf43500fc
+#define	F367CAB_ADJIIR_COEFF10_H	0xf4350003
+
+/* IQDEM_ADJ_COEFF2 */
+#define	R367CAB_IQDEM_ADJ_COEFF2	0xf436
+#define	F367CAB_ADJIIR_COEFF12_L	0xf43600f0
+#define	F367CAB_ADJIIR_COEFF11_H	0xf436000f
+
+/* IQDEM_ADJ_COEFF3 */
+#define	R367CAB_IQDEM_ADJ_COEFF3	0xf437
+#define	F367CAB_ADJIIR_COEFF20_L	0xf43700c0
+#define	F367CAB_ADJIIR_COEFF12_H	0xf437003f
+
+/* IQDEM_ADJ_COEFF4 */
+#define	R367CAB_IQDEM_ADJ_COEFF4	0xf438
+#define	F367CAB_ADJIIR_COEFF20_H	0xf43800ff
+
+/* IQDEM_ADJ_COEFF5 */
+#define	R367CAB_IQDEM_ADJ_COEFF5	0xf439
+#define	F367CAB_ADJIIR_COEFF21_L	0xf43900ff
+
+/* IQDEM_ADJ_COEFF6 */
+#define	R367CAB_IQDEM_ADJ_COEFF6	0xf43a
+#define	F367CAB_ADJIIR_COEFF22_L	0xf43a00fc
+#define	F367CAB_ADJIIR_COEFF21_H	0xf43a0003
+
+/* IQDEM_ADJ_COEFF7 */
+#define	R367CAB_IQDEM_ADJ_COEFF7	0xf43b
+#define	F367CAB_ADJIIR_COEFF22_H	0xf43b000f
+
+/* IQDEM_ADJ_EN */
+#define	R367CAB_IQDEM_ADJ_EN	0xf43c
+#define	F367CAB_ALLPASSFILT_EN	0xf43c0008
+#define	F367CAB_ADJ_AGC_EN	0xf43c0004
+#define	F367CAB_ADJ_COEFF_FRZ	0xf43c0002
+#define	F367CAB_ADJ_EN	0xf43c0001
+
+/* IQDEM_ADJ_AGC_REF */
+#define	R367CAB_IQDEM_ADJ_AGC_REF	0xf43d
+#define	F367CAB_ADJ_AGC_REF	0xf43d00ff
+
+/* ALLPASSFILT1 */
+#define	R367CAB_ALLPASSFILT1	0xf440
+#define	F367CAB_ALLPASSFILT_COEFF1_LO	0xf44000ff
+
+/* ALLPASSFILT2 */
+#define	R367CAB_ALLPASSFILT2	0xf441
+#define	F367CAB_ALLPASSFILT_COEFF1_ME	0xf44100ff
+
+/* ALLPASSFILT3 */
+#define	R367CAB_ALLPASSFILT3	0xf442
+#define	F367CAB_ALLPASSFILT_COEFF2_LO	0xf44200c0
+#define	F367CAB_ALLPASSFILT_COEFF1_HI	0xf442003f
+
+/* ALLPASSFILT4 */
+#define	R367CAB_ALLPASSFILT4	0xf443
+#define	F367CAB_ALLPASSFILT_COEFF2_MEL	0xf44300ff
+
+/* ALLPASSFILT5 */
+#define	R367CAB_ALLPASSFILT5	0xf444
+#define	F367CAB_ALLPASSFILT_COEFF2_MEH	0xf44400ff
+
+/* ALLPASSFILT6 */
+#define	R367CAB_ALLPASSFILT6	0xf445
+#define	F367CAB_ALLPASSFILT_COEFF3_LO	0xf44500f0
+#define	F367CAB_ALLPASSFILT_COEFF2_HI	0xf445000f
+
+/* ALLPASSFILT7 */
+#define	R367CAB_ALLPASSFILT7	0xf446
+#define	F367CAB_ALLPASSFILT_COEFF3_MEL	0xf44600ff
+
+/* ALLPASSFILT8 */
+#define	R367CAB_ALLPASSFILT8	0xf447
+#define	F367CAB_ALLPASSFILT_COEFF3_MEH	0xf44700ff
+
+/* ALLPASSFILT9 */
+#define	R367CAB_ALLPASSFILT9	0xf448
+#define	F367CAB_ALLPASSFILT_COEFF4_LO	0xf44800fc
+#define	F367CAB_ALLPASSFILT_COEFF3_HI	0xf4480003
+
+/* ALLPASSFILT10 */
+#define	R367CAB_ALLPASSFILT10	0xf449
+#define	F367CAB_ALLPASSFILT_COEFF4_ME	0xf44900ff
+
+/* ALLPASSFILT11 */
+#define	R367CAB_ALLPASSFILT11	0xf44a
+#define	F367CAB_ALLPASSFILT_COEFF4_HI	0xf44a00ff
+
+/* TRL_AGC_CFG */
+#define	R367CAB_TRL_AGC_CFG	0xf450
+#define	F367CAB_TRL_AGC_FREEZE	0xf4500080
+#define	F367CAB_TRL_AGC_REF	0xf450007f
+
+/* TRL_LPF_CFG */
+#define	R367CAB_TRL_LPF_CFG	0xf454
+#define	F367CAB_NYQPOINT_INV	0xf4540040
+#define	F367CAB_TRL_SHIFT	0xf4540030
+#define	F367CAB_NYQ_COEFF_SEL	0xf454000c
+#define	F367CAB_TRL_LPF_FREEZE	0xf4540002
+#define	F367CAB_TRL_LPF_CRT	0xf4540001
+
+/* TRL_LPF_ACQ_GAIN */
+#define	R367CAB_TRL_LPF_ACQ_GAIN	0xf455
+#define	F367CAB_TRL_GDIR_ACQ	0xf4550070
+#define	F367CAB_TRL_GINT_ACQ	0xf4550007
+
+/* TRL_LPF_TRK_GAIN */
+#define	R367CAB_TRL_LPF_TRK_GAIN	0xf456
+#define	F367CAB_TRL_GDIR_TRK	0xf4560070
+#define	F367CAB_TRL_GINT_TRK	0xf4560007
+
+/* TRL_LPF_OUT_GAIN */
+#define	R367CAB_TRL_LPF_OUT_GAIN	0xf457
+#define	F367CAB_TRL_GAIN_OUT	0xf4570007
+
+/* TRL_LOCKDET_LTH */
+#define	R367CAB_TRL_LOCKDET_LTH	0xf458
+#define	F367CAB_TRL_LCK_THLO	0xf4580007
+
+/* TRL_LOCKDET_HTH */
+#define	R367CAB_TRL_LOCKDET_HTH	0xf459
+#define	F367CAB_TRL_LCK_THHI	0xf45900ff
+
+/* TRL_LOCKDET_TRGVAL */
+#define	R367CAB_TRL_LOCKDET_TRGVAL	0xf45a
+#define	F367CAB_TRL_LCK_TRG	0xf45a00ff
+
+/* IQ_QAM */
+#define	R367CAB_IQ_QAM	0xf45c
+#define	F367CAB_IQ_INPUT	0xf45c0008
+#define	F367CAB_DETECT_MODE	0xf45c0007
+
+/* FSM_STATE */
+#define	R367CAB_FSM_STATE	0xf460
+#define	F367CAB_CRL_DFE	0xf4600080
+#define	F367CAB_DFE_START	0xf4600040
+#define	F367CAB_CTRLG_START	0xf4600030
+#define	F367CAB_FSM_FORCESTATE	0xf460000f
+
+/* FSM_CTL */
+#define	R367CAB_FSM_CTL	0xf461
+#define	F367CAB_FEC2_EN	0xf4610040
+#define	F367CAB_SIT_EN	0xf4610020
+#define	F367CAB_TRL_AHEAD	0xf4610010
+#define	F367CAB_TRL2_EN	0xf4610008
+#define	F367CAB_FSM_EQA1_EN	0xf4610004
+#define	F367CAB_FSM_BKP_DIS	0xf4610002
+#define	F367CAB_FSM_FORCE_EN	0xf4610001
+
+/* FSM_STS */
+#define	R367CAB_FSM_STS	0xf462
+#define	F367CAB_FSM_STATUS	0xf462000f
+
+/* FSM_SNR0_HTH */
+#define	R367CAB_FSM_SNR0_HTH	0xf463
+#define	F367CAB_SNR0_HTH	0xf46300ff
+
+/* FSM_SNR1_HTH */
+#define	R367CAB_FSM_SNR1_HTH	0xf464
+#define	F367CAB_SNR1_HTH	0xf46400ff
+
+/* FSM_SNR2_HTH */
+#define	R367CAB_FSM_SNR2_HTH	0xf465
+#define	F367CAB_SNR2_HTH	0xf46500ff
+
+/* FSM_SNR0_LTH */
+#define	R367CAB_FSM_SNR0_LTH	0xf466
+#define	F367CAB_SNR0_LTH	0xf46600ff
+
+/* FSM_SNR1_LTH */
+#define	R367CAB_FSM_SNR1_LTH	0xf467
+#define	F367CAB_SNR1_LTH	0xf46700ff
+
+/* FSM_EQA1_HTH */
+#define	R367CAB_FSM_EQA1_HTH	0xf468
+#define	F367CAB_SNR3_HTH_LO	0xf46800f0
+#define	F367CAB_EQA1_HTH	0xf468000f
+
+/* FSM_TEMPO */
+#define	R367CAB_FSM_TEMPO	0xf469
+#define	F367CAB_SIT	0xf46900c0
+#define	F367CAB_WST	0xf4690038
+#define	F367CAB_ELT	0xf4690006
+#define	F367CAB_SNR3_HTH_HI	0xf4690001
+
+/* FSM_CONFIG */
+#define	R367CAB_FSM_CONFIG	0xf46a
+#define	F367CAB_FEC2_DFEOFF	0xf46a0004
+#define	F367CAB_PRIT_STATE	0xf46a0002
+#define	F367CAB_MODMAP_STATE	0xf46a0001
+
+/* EQU_I_TESTTAP_L */
+#define	R367CAB_EQU_I_TESTTAP_L	0xf474
+#define	F367CAB_I_TEST_TAP_L	0xf47400ff
+
+/* EQU_I_TESTTAP_M */
+#define	R367CAB_EQU_I_TESTTAP_M	0xf475
+#define	F367CAB_I_TEST_TAP_M	0xf47500ff
+
+/* EQU_I_TESTTAP_H */
+#define	R367CAB_EQU_I_TESTTAP_H	0xf476
+#define	F367CAB_I_TEST_TAP_H	0xf476001f
+
+/* EQU_TESTAP_CFG */
+#define	R367CAB_EQU_TESTAP_CFG	0xf477
+#define	F367CAB_TEST_FFE_DFE_SEL	0xf4770040
+#define	F367CAB_TEST_TAP_SELECT	0xf477003f
+
+/* EQU_Q_TESTTAP_L */
+#define	R367CAB_EQU_Q_TESTTAP_L	0xf478
+#define	F367CAB_Q_TEST_TAP_L	0xf47800ff
+
+/* EQU_Q_TESTTAP_M */
+#define	R367CAB_EQU_Q_TESTTAP_M	0xf479
+#define	F367CAB_Q_TEST_TAP_M	0xf47900ff
+
+/* EQU_Q_TESTTAP_H */
+#define	R367CAB_EQU_Q_TESTTAP_H	0xf47a
+#define	F367CAB_Q_TEST_TAP_H	0xf47a001f
+
+/* EQU_TAP_CTRL */
+#define	R367CAB_EQU_TAP_CTRL	0xf47b
+#define	F367CAB_MTAP_FRZ	0xf47b0010
+#define	F367CAB_PRE_FREEZE	0xf47b0008
+#define	F367CAB_DFE_TAPMON_EN	0xf47b0004
+#define	F367CAB_FFE_TAPMON_EN	0xf47b0002
+#define	F367CAB_MTAP_ONLY	0xf47b0001
+
+/* EQU_CTR_CRL_CONTROL_L */
+#define	R367CAB_EQU_CTR_CRL_CONTROL_L	0xf47c
+#define	F367CAB_EQU_CTR_CRL_CONTROL_LO	0xf47c00ff
+
+/* EQU_CTR_CRL_CONTROL_H */
+#define	R367CAB_EQU_CTR_CRL_CONTROL_H	0xf47d
+#define	F367CAB_EQU_CTR_CRL_CONTROL_HI	0xf47d00ff
+
+/* EQU_CTR_HIPOW_L */
+#define	R367CAB_EQU_CTR_HIPOW_L	0xf47e
+#define	F367CAB_CTR_HIPOW_L	0xf47e00ff
+
+/* EQU_CTR_HIPOW_H */
+#define	R367CAB_EQU_CTR_HIPOW_H	0xf47f
+#define	F367CAB_CTR_HIPOW_H	0xf47f00ff
+
+/* EQU_I_EQU_LO */
+#define	R367CAB_EQU_I_EQU_LO	0xf480
+#define	F367CAB_EQU_I_EQU_L	0xf48000ff
+
+/* EQU_I_EQU_HI */
+#define	R367CAB_EQU_I_EQU_HI	0xf481
+#define	F367CAB_EQU_I_EQU_H	0xf4810003
+
+/* EQU_Q_EQU_LO */
+#define	R367CAB_EQU_Q_EQU_LO	0xf482
+#define	F367CAB_EQU_Q_EQU_L	0xf48200ff
+
+/* EQU_Q_EQU_HI */
+#define	R367CAB_EQU_Q_EQU_HI	0xf483
+#define	F367CAB_EQU_Q_EQU_H	0xf4830003
+
+/* EQU_MAPPER */
+#define	R367CAB_EQU_MAPPER	0xf484
+#define	F367CAB_QUAD_AUTO	0xf4840080
+#define	F367CAB_QUAD_INV	0xf4840040
+#define	F367CAB_QAM_MODE	0xf4840007
+
+/* EQU_SWEEP_RATE */
+#define	R367CAB_EQU_SWEEP_RATE	0xf485
+#define	F367CAB_SNR_PER	0xf48500c0
+#define	F367CAB_SWEEP_RATE	0xf485003f
+
+/* EQU_SNR_LO */
+#define	R367CAB_EQU_SNR_LO	0xf486
+#define	F367CAB_SNR_LO	0xf48600ff
+
+/* EQU_SNR_HI */
+#define	R367CAB_EQU_SNR_HI	0xf487
+#define	F367CAB_SNR_HI	0xf48700ff
+
+/* EQU_GAMMA_LO */
+#define	R367CAB_EQU_GAMMA_LO	0xf488
+#define	F367CAB_GAMMA_LO	0xf48800ff
+
+/* EQU_GAMMA_HI */
+#define	R367CAB_EQU_GAMMA_HI	0xf489
+#define	F367CAB_GAMMA_ME	0xf48900ff
+
+/* EQU_ERR_GAIN */
+#define	R367CAB_EQU_ERR_GAIN	0xf48a
+#define	F367CAB_EQA1MU	0xf48a0070
+#define	F367CAB_CRL2MU	0xf48a000e
+#define	F367CAB_GAMMA_HI	0xf48a0001
+
+/* EQU_RADIUS */
+#define	R367CAB_EQU_RADIUS	0xf48b
+#define	F367CAB_RADIUS	0xf48b00ff
+
+/* EQU_FFE_MAINTAP */
+#define	R367CAB_EQU_FFE_MAINTAP	0xf48c
+#define	F367CAB_FFE_MAINTAP_INIT	0xf48c00ff
+
+/* EQU_FFE_LEAKAGE */
+#define	R367CAB_EQU_FFE_LEAKAGE	0xf48e
+#define	F367CAB_LEAK_PER	0xf48e00f0
+#define	F367CAB_EQU_OUTSEL	0xf48e0002
+#define	F367CAB_PNT2dFE	0xf48e0001
+
+/* EQU_FFE_MAINTAP_POS */
+#define	R367CAB_EQU_FFE_MAINTAP_POS	0xf48f
+#define	F367CAB_FFE_LEAK_EN	0xf48f0080
+#define	F367CAB_DFE_LEAK_EN	0xf48f0040
+#define	F367CAB_FFE_MAINTAP_POS	0xf48f003f
+
+/* EQU_GAIN_WIDE */
+#define	R367CAB_EQU_GAIN_WIDE	0xf490
+#define	F367CAB_DFE_GAIN_WIDE	0xf49000f0
+#define	F367CAB_FFE_GAIN_WIDE	0xf490000f
+
+/* EQU_GAIN_NARROW */
+#define	R367CAB_EQU_GAIN_NARROW	0xf491
+#define	F367CAB_DFE_GAIN_NARROW	0xf49100f0
+#define	F367CAB_FFE_GAIN_NARROW	0xf491000f
+
+/* EQU_CTR_LPF_GAIN */
+#define	R367CAB_EQU_CTR_LPF_GAIN	0xf492
+#define	F367CAB_CTR_GTO	0xf4920080
+#define	F367CAB_CTR_GDIR	0xf4920070
+#define	F367CAB_SWEEP_EN	0xf4920008
+#define	F367CAB_CTR_GINT	0xf4920007
+
+/* EQU_CRL_LPF_GAIN */
+#define	R367CAB_EQU_CRL_LPF_GAIN	0xf493
+#define	F367CAB_CRL_GTO	0xf4930080
+#define	F367CAB_CRL_GDIR	0xf4930070
+#define	F367CAB_SWEEP_DIR	0xf4930008
+#define	F367CAB_CRL_GINT	0xf4930007
+
+/* EQU_GLOBAL_GAIN */
+#define	R367CAB_EQU_GLOBAL_GAIN	0xf494
+#define	F367CAB_CRL_GAIN	0xf49400f8
+#define	F367CAB_CTR_INC_GAIN	0xf4940004
+#define	F367CAB_CTR_FRAC	0xf4940003
+
+/* EQU_CRL_LD_SEN */
+#define	R367CAB_EQU_CRL_LD_SEN	0xf495
+#define	F367CAB_CTR_BADPOINT_EN	0xf4950080
+#define	F367CAB_CTR_GAIN	0xf4950070
+#define	F367CAB_LIMANEN	0xf4950008
+#define	F367CAB_CRL_LD_SEN	0xf4950007
+
+/* EQU_CRL_LD_VAL */
+#define	R367CAB_EQU_CRL_LD_VAL	0xf496
+#define	F367CAB_CRL_BISTH_LIMIT	0xf4960080
+#define	F367CAB_CARE_EN	0xf4960040
+#define	F367CAB_CRL_LD_PER	0xf4960030
+#define	F367CAB_CRL_LD_WST	0xf496000c
+#define	F367CAB_CRL_LD_TFS	0xf4960003
+
+/* EQU_CRL_TFR */
+#define	R367CAB_EQU_CRL_TFR	0xf497
+#define	F367CAB_CRL_LD_TFR	0xf49700ff
+
+/* EQU_CRL_BISTH_LO */
+#define	R367CAB_EQU_CRL_BISTH_LO	0xf498
+#define	F367CAB_CRL_BISTH_LO	0xf49800ff
+
+/* EQU_CRL_BISTH_HI */
+#define	R367CAB_EQU_CRL_BISTH_HI	0xf499
+#define	F367CAB_CRL_BISTH_HI	0xf49900ff
+
+/* EQU_SWEEP_RANGE_LO */
+#define	R367CAB_EQU_SWEEP_RANGE_LO	0xf49a
+#define	F367CAB_SWEEP_RANGE_LO	0xf49a00ff
+
+/* EQU_SWEEP_RANGE_HI */
+#define	R367CAB_EQU_SWEEP_RANGE_HI	0xf49b
+#define	F367CAB_SWEEP_RANGE_HI	0xf49b00ff
+
+/* EQU_CRL_LIMITER */
+#define	R367CAB_EQU_CRL_LIMITER	0xf49c
+#define	F367CAB_BISECTOR_EN	0xf49c0080
+#define	F367CAB_PHEST128_EN	0xf49c0040
+#define	F367CAB_CRL_LIM	0xf49c003f
+
+/* EQU_MODULUS_MAP */
+#define	R367CAB_EQU_MODULUS_MAP	0xf49d
+#define	F367CAB_PNT_DEPTH	0xf49d00e0
+#define	F367CAB_MODULUS_CMP	0xf49d001f
+
+/* EQU_PNT_GAIN */
+#define	R367CAB_EQU_PNT_GAIN	0xf49e
+#define	F367CAB_PNT_EN	0xf49e0080
+#define	F367CAB_MODULUSMAP_EN	0xf49e0040
+#define	F367CAB_PNT_GAIN	0xf49e003f
+
+/* FEC_AC_CTR_0 */
+#define	R367CAB_FEC_AC_CTR_0	0xf4a8
+#define	F367CAB_BE_BYPASS	0xf4a80020
+#define	F367CAB_REFRESH47	0xf4a80010
+#define	F367CAB_CT_NBST	0xf4a80008
+#define	F367CAB_TEI_ENA	0xf4a80004
+#define	F367CAB_DS_ENA	0xf4a80002
+#define	F367CAB_TSMF_EN	0xf4a80001
+
+/* FEC_AC_CTR_1 */
+#define	R367CAB_FEC_AC_CTR_1	0xf4a9
+#define	F367CAB_DEINT_DEPTH	0xf4a900ff
+
+/* FEC_AC_CTR_2 */
+#define	R367CAB_FEC_AC_CTR_2	0xf4aa
+#define	F367CAB_DEINT_M	0xf4aa00f8
+#define	F367CAB_DIS_UNLOCK	0xf4aa0004
+#define	F367CAB_DESCR_MODE	0xf4aa0003
+
+/* FEC_AC_CTR_3 */
+#define	R367CAB_FEC_AC_CTR_3	0xf4ab
+#define	F367CAB_DI_UNLOCK	0xf4ab0080
+#define	F367CAB_DI_FREEZE	0xf4ab0040
+#define	F367CAB_MISMATCH	0xf4ab0030
+#define	F367CAB_ACQ_MODE	0xf4ab000c
+#define	F367CAB_TRK_MODE	0xf4ab0003
+
+/* FEC_STATUS */
+#define	R367CAB_FEC_STATUS	0xf4ac
+#define	F367CAB_DEINT_SMCNTR	0xf4ac00e0
+#define	F367CAB_DEINT_SYNCSTATE	0xf4ac0018
+#define	F367CAB_DEINT_SYNLOST	0xf4ac0004
+#define	F367CAB_DESCR_SYNCSTATE	0xf4ac0002
+
+/* RS_COUNTER_0 */
+#define	R367CAB_RS_COUNTER_0	0xf4ae
+#define	F367CAB_BK_CT_L	0xf4ae00ff
+
+/* RS_COUNTER_1 */
+#define	R367CAB_RS_COUNTER_1	0xf4af
+#define	F367CAB_BK_CT_H	0xf4af00ff
+
+/* RS_COUNTER_2 */
+#define	R367CAB_RS_COUNTER_2	0xf4b0
+#define	F367CAB_CORR_CT_L	0xf4b000ff
+
+/* RS_COUNTER_3 */
+#define	R367CAB_RS_COUNTER_3	0xf4b1
+#define	F367CAB_CORR_CT_H	0xf4b100ff
+
+/* RS_COUNTER_4 */
+#define	R367CAB_RS_COUNTER_4	0xf4b2
+#define	F367CAB_UNCORR_CT_L	0xf4b200ff
+
+/* RS_COUNTER_5 */
+#define	R367CAB_RS_COUNTER_5	0xf4b3
+#define	F367CAB_UNCORR_CT_H	0xf4b300ff
+
+/* BERT_0 */
+#define	R367CAB_BERT_0	0xf4b4
+#define	F367CAB_RS_NOCORR	0xf4b40004
+#define	F367CAB_CT_HOLD	0xf4b40002
+#define	F367CAB_CT_CLEAR	0xf4b40001
+
+/* BERT_1 */
+#define	R367CAB_BERT_1	0xf4b5
+#define	F367CAB_BERT_ON	0xf4b50020
+#define	F367CAB_BERT_ERR_SRC	0xf4b50010
+#define	F367CAB_BERT_ERR_MODE	0xf4b50008
+#define	F367CAB_BERT_NBYTE	0xf4b50007
+
+/* BERT_2 */
+#define	R367CAB_BERT_2	0xf4b6
+#define	F367CAB_BERT_ERRCOUNT_L	0xf4b600ff
+
+/* BERT_3 */
+#define	R367CAB_BERT_3	0xf4b7
+#define	F367CAB_BERT_ERRCOUNT_H	0xf4b700ff
+
+/* OUTFORMAT_0 */
+#define	R367CAB_OUTFORMAT_0	0xf4b8
+#define	F367CAB_CLK_POLARITY	0xf4b80080
+#define	F367CAB_FEC_TYPE	0xf4b80040
+#define	F367CAB_SYNC_STRIP	0xf4b80008
+#define	F367CAB_TS_SWAP	0xf4b80004
+#define	F367CAB_OUTFORMAT	0xf4b80003
+
+/* OUTFORMAT_1 */
+#define	R367CAB_OUTFORMAT_1	0xf4b9
+#define	F367CAB_CI_DIVRANGE	0xf4b900ff
+
+/* SMOOTHER_2 */
+#define	R367CAB_SMOOTHER_2	0xf4be
+#define	F367CAB_FIFO_BYPASS	0xf4be0020
+
+/* TSMF_CTRL_0 */
+#define	R367CAB_TSMF_CTRL_0	0xf4c0
+#define	F367CAB_TS_NUMBER	0xf4c0001e
+#define	F367CAB_SEL_MODE	0xf4c00001
+
+/* TSMF_CTRL_1 */
+#define	R367CAB_TSMF_CTRL_1	0xf4c1
+#define	F367CAB_CHECK_ERROR_BIT	0xf4c10080
+#define	F367CAB_CHCK_F_SYNC	0xf4c10040
+#define	F367CAB_H_MODE	0xf4c10008
+#define	F367CAB_D_V_MODE	0xf4c10004
+#define	F367CAB_MODE	0xf4c10003
+
+/* TSMF_CTRL_3 */
+#define	R367CAB_TSMF_CTRL_3	0xf4c3
+#define	F367CAB_SYNC_IN_COUNT	0xf4c300f0
+#define	F367CAB_SYNC_OUT_COUNT	0xf4c3000f
+
+/* TS_ON_ID_0 */
+#define	R367CAB_TS_ON_ID_0	0xf4c4
+#define	F367CAB_TS_ID_L	0xf4c400ff
+
+/* TS_ON_ID_1 */
+#define	R367CAB_TS_ON_ID_1	0xf4c5
+#define	F367CAB_TS_ID_H	0xf4c500ff
+
+/* TS_ON_ID_2 */
+#define	R367CAB_TS_ON_ID_2	0xf4c6
+#define	F367CAB_ON_ID_L	0xf4c600ff
+
+/* TS_ON_ID_3 */
+#define	R367CAB_TS_ON_ID_3	0xf4c7
+#define	F367CAB_ON_ID_H	0xf4c700ff
+
+/* RE_STATUS_0 */
+#define	R367CAB_RE_STATUS_0	0xf4c8
+#define	F367CAB_RECEIVE_STATUS_L	0xf4c800ff
+
+/* RE_STATUS_1 */
+#define	R367CAB_RE_STATUS_1	0xf4c9
+#define	F367CAB_RECEIVE_STATUS_LH	0xf4c900ff
+
+/* RE_STATUS_2 */
+#define	R367CAB_RE_STATUS_2	0xf4ca
+#define	F367CAB_RECEIVE_STATUS_HL	0xf4ca00ff
+
+/* RE_STATUS_3 */
+#define	R367CAB_RE_STATUS_3	0xf4cb
+#define	F367CAB_RECEIVE_STATUS_HH	0xf4cb003f
+
+/* TS_STATUS_0 */
+#define	R367CAB_TS_STATUS_0	0xf4cc
+#define	F367CAB_TS_STATUS_L	0xf4cc00ff
+
+/* TS_STATUS_1 */
+#define	R367CAB_TS_STATUS_1	0xf4cd
+#define	F367CAB_TS_STATUS_H	0xf4cd007f
+
+/* TS_STATUS_2 */
+#define	R367CAB_TS_STATUS_2	0xf4ce
+#define	F367CAB_ERROR	0xf4ce0080
+#define	F367CAB_EMERGENCY	0xf4ce0040
+#define	F367CAB_CRE_TS	0xf4ce0030
+#define	F367CAB_VER	0xf4ce000e
+#define	F367CAB_M_LOCK	0xf4ce0001
+
+/* TS_STATUS_3 */
+#define	R367CAB_TS_STATUS_3	0xf4cf
+#define	F367CAB_UPDATE_READY	0xf4cf0080
+#define	F367CAB_END_FRAME_HEADER	0xf4cf0040
+#define	F367CAB_CONTCNT	0xf4cf0020
+#define	F367CAB_TS_IDENTIFIER_SEL	0xf4cf000f
+
+/* T_O_ID_0 */
+#define	R367CAB_T_O_ID_0	0xf4d0
+#define	F367CAB_ON_ID_I_L	0xf4d000ff
+
+/* T_O_ID_1 */
+#define	R367CAB_T_O_ID_1	0xf4d1
+#define	F367CAB_ON_ID_I_H	0xf4d100ff
+
+/* T_O_ID_2 */
+#define	R367CAB_T_O_ID_2	0xf4d2
+#define	F367CAB_TS_ID_I_L	0xf4d200ff
+
+/* T_O_ID_3 */
+#define	R367CAB_T_O_ID_3	0xf4d3
+#define	F367CAB_TS_ID_I_H	0xf4d300ff
+
+#define STV0367CAB_NBREGS	187
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0900_core.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0900_core.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0900_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0900_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1604,6 +1604,9 @@
 	p_search.standard = STV0900_AUTO_SEARCH;
 	p_search.iq_inversion = STV0900_IQ_AUTO;
 	p_search.search_algo = STV0900_BLIND_SEARCH;
+	/* Speeds up DVB-S searching */
+	if (c->delivery_system == SYS_DVBS)
+		p_search.standard = STV0900_SEARCH_DVBS1;
 
 	intp->srch_standard[demod] = p_search.standard;
 	intp->symbol_rate[demod] = p_search.symbol_rate;
@@ -1660,8 +1663,14 @@
 			| FE_HAS_VITERBI
 			| FE_HAS_SYNC
 			| FE_HAS_LOCK;
-	} else
+		if (state->config->set_lock_led)
+			state->config->set_lock_led(fe, 1);
+	} else {
+		*status = 0;
+		if (state->config->set_lock_led)
+			state->config->set_lock_led(fe, 0);
 		dprintk("DEMOD LOCK FAIL\n");
+	}
 
 	return 0;
 }
@@ -1831,6 +1840,9 @@
 
 	dprintk("%s\n", __func__);
 
+	if (state->config->set_lock_led)
+		state->config->set_lock_led(fe, 0);
+
 	if ((--(state->internal->dmds_used)) <= 0) {
 
 		dprintk("%s: Actually removing\n", __func__);
@@ -1842,6 +1854,18 @@
 	kfree(state);
 }
 
+static int stv0900_sleep(struct dvb_frontend *fe)
+{
+	struct stv0900_state *state = fe->demodulator_priv;
+
+	dprintk("%s\n", __func__);
+
+	if (state->config->set_lock_led)
+		state->config->set_lock_led(fe, 0);
+
+	return 0;
+}
+
 static int stv0900_get_frontend(struct dvb_frontend *fe,
 				struct dvb_frontend_parameters *p)
 {
@@ -1876,6 +1900,7 @@
 	.release			= stv0900_release,
 	.init				= stv0900_init,
 	.get_frontend                   = stv0900_get_frontend,
+	.sleep				= stv0900_sleep,
 	.get_frontend_algo		= stv0900_frontend_algo,
 	.i2c_gate_ctrl			= stv0900_i2c_gate_ctrl,
 	.diseqc_send_master_cmd		= stv0900_send_master_cmd,
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0900.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0900.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0900.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0900.h	2011-05-19 00:06:34.000000000 -0400
@@ -53,6 +53,8 @@
 	u8 tun2_type;
 	/* Set device param to start dma */
 	int (*set_ts_params)(struct dvb_frontend *fe, int is_punctured);
+	/* Hook for Lock LED */
+	void (*set_lock_led)(struct dvb_frontend *fe, int offon);
 };
 
 #if defined(CONFIG_DVB_STV0900) || (defined(CONFIG_DVB_STV0900_MODULE) \
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0900_priv.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0900_priv.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv0900_priv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv0900_priv.h	2011-05-19 00:06:34.000000000 -0400
@@ -238,7 +238,7 @@
 };
 
 struct stv0900_init_params{
-	u32	dmd_ref_clk;/* Refrence,Input clock for the demod in Hz */
+	u32	dmd_ref_clk;/* Reference,Input clock for the demod in Hz */
 
 	/* Demodulator Type (single demod or dual demod) */
 	enum fe_stv0900_demod_mode	demod_mode;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv090x.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv090x.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv090x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv090x.c	2011-05-19 00:06:34.000000000 -0400
@@ -767,8 +767,12 @@
 	 * In case of any error, the lock is unlocked and exit within the
 	 * relevant operations themselves.
 	 */
-	if (enable)
-		mutex_lock(&state->internal->tuner_lock);
+	if (enable) {
+		if (state->config->tuner_i2c_lock)
+			state->config->tuner_i2c_lock(&state->frontend, 1);
+		else
+			mutex_lock(&state->internal->tuner_lock);
+	}
 
 	reg = STV090x_READ_DEMOD(state, I2CRPT);
 	if (enable) {
@@ -784,13 +788,20 @@
 			goto err;
 	}
 
-	if (!enable)
-		mutex_unlock(&state->internal->tuner_lock);
+	if (!enable) {
+		if (state->config->tuner_i2c_lock)
+			state->config->tuner_i2c_lock(&state->frontend, 0);
+		else
+			mutex_unlock(&state->internal->tuner_lock);
+	}
 
 	return 0;
 err:
 	dprintk(FE_ERROR, 1, "I/O error");
-	mutex_unlock(&state->internal->tuner_lock);
+	if (state->config->tuner_i2c_lock)
+		state->config->tuner_i2c_lock(&state->frontend, 0);
+	else
+		mutex_unlock(&state->internal->tuner_lock);
 	return -1;
 }
 
@@ -1413,7 +1424,7 @@
 			if (STV090x_WRITE_DEMOD(state, CFRLOW0, 0x00) < 0)
 				goto err;
 
-			/*enlarge the timing bandwith for Low SR*/
+			/*enlarge the timing bandwidth for Low SR*/
 			if (STV090x_WRITE_DEMOD(state, RTCS2, 0x68) < 0)
 				goto err;
 		} else {
@@ -1421,17 +1432,17 @@
 			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*/
+			/*reduce the timing bandwidth 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 */
+			/* enlarge the timing bandwidth for Low SR */
 			STV090x_WRITE_DEMOD(state, RTCS2, 0x68);
 		} else {
-			/* reduce timing bandwith for high SR */
+			/* reduce timing bandwidth for high SR */
 			STV090x_WRITE_DEMOD(state, RTCS2, 0x44);
 		}
 
@@ -2471,7 +2482,7 @@
 					dvbs2_fly_wheel = STV090x_GETFIELD_Px(reg, FLYWHEEL_CPT_FIELD);
 				}
 				if (dvbs2_fly_wheel < 0xd) {
-					/*FALSE lock, The demod is loosing lock */
+					/*FALSE lock, The demod is losing lock */
 					lock = 0;
 					if (trials < 2) {
 						if (state->internal->dev_ver >= 0x20) {
@@ -2883,10 +2894,12 @@
 		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->internal->dev_ver >= 0x30) {
+			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);
@@ -3189,7 +3202,7 @@
 			goto err;
 		if (STV090x_WRITE_DEMOD(state, CORRELMANT, 0x70) < 0)
 			goto err;
-		if (stv090x_set_srate(state, 1000000) < 0) /* inital srate = 1Msps */
+		if (stv090x_set_srate(state, 1000000) < 0) /* initial srate = 1Msps */
 			goto err;
 	} else {
 		/* known srate */
@@ -3846,6 +3859,7 @@
 {
 	struct stv090x_state *state = fe->demodulator_priv;
 	u32 reg;
+	u8 full_standby = 0;
 
 	if (stv090x_i2c_gate_ctrl(state, 1) < 0)
 		goto err;
@@ -3858,24 +3872,119 @@
 	if (stv090x_i2c_gate_ctrl(state, 0) < 0)
 		goto err;
 
-	dprintk(FE_DEBUG, 1, "Set %s to sleep",
-		state->device == STV0900 ? "STV0900" : "STV0903");
+	dprintk(FE_DEBUG, 1, "Set %s(%d) to sleep",
+		state->device == STV0900 ? "STV0900" : "STV0903",
+		state->demod);
 
-	reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
-	STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
-	if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
-		goto err;
+	mutex_lock(&state->internal->demod_lock);
 
-	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;
+	switch (state->demod) {
+	case STV090x_DEMODULATOR_0:
+		/* power off ADC 1 */
+		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;
+		/* power off DiSEqC 1 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
+		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
+			goto err;
+
+		/* check whether path 2 is already sleeping, that is when
+		   ADC2 is off */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+		if (STV090x_GETFIELD(reg, ADC2_PON_FIELD) == 0)
+			full_standby = 1;
+
+		/* stop clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 1);
+		/* ADC 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 1);
+		/* FEC clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 1);
+		/* viterbi 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 1);
+		/* TS clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
 
+	case STV090x_DEMODULATOR_1:
+		/* power off ADC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
+			goto err;
+		/* power off DiSEqC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
+		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
+			goto err;
+
+		/* check whether path 1 is already sleeping, that is when
+		   ADC1 is off */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR1);
+		if (STV090x_GETFIELD(reg, ADC1_PON_FIELD) == 0)
+			full_standby = 1;
+
+		/* stop clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 1);
+		/* ADC 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 1);
+		/* FEC clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 1);
+		/* viterbi 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 1);
+		/* TS clock is shared between the two paths, only stop it
+		   when full standby is possible */
+		if (full_standby)
+			STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		dprintk(FE_ERROR, 1, "Wrong demodulator!");
+		break;
+	}
+
+	if (full_standby) {
+		/* general power off */
+		reg = stv090x_read_reg(state, STV090x_SYNTCTRL);
+		STV090x_SETFIELD(reg, STANDBY_FIELD, 0x01);
+		if (stv090x_write_reg(state, STV090x_SYNTCTRL, reg) < 0)
+			goto err;
+	}
+
+	mutex_unlock(&state->internal->demod_lock);
 	return 0;
 
 err_gateoff:
 	stv090x_i2c_gate_ctrl(state, 0);
 err:
+	mutex_unlock(&state->internal->demod_lock);
 	dprintk(FE_ERROR, 1, "I/O error");
 	return -1;
 }
@@ -3885,21 +3994,94 @@
 	struct stv090x_state *state = fe->demodulator_priv;
 	u32 reg;
 
-	dprintk(FE_DEBUG, 1, "Wake %s from standby",
-		state->device == STV0900 ? "STV0900" : "STV0903");
+	dprintk(FE_DEBUG, 1, "Wake %s(%d) from standby",
+		state->device == STV0900 ? "STV0900" : "STV0903",
+		state->demod);
 
+	mutex_lock(&state->internal->demod_lock);
+
+	/* general power on */
 	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;
+	switch (state->demod) {
+	case STV090x_DEMODULATOR_0:
+		/* power on ADC 1 */
+		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;
+		/* power on DiSEqC 1 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR2);
+		STV090x_SETFIELD(reg, DISEQC1_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR2, reg) < 0)
+			goto err;
 
+		/* activate clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT1_FIELD, 0);
+		/* ADC 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI1_FIELD, 0);
+		/* FEC clock */
+		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP1_FIELD, 0);
+		/* viterbi 1 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT1_FIELD, 0);
+		/* TS clock */
+		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	case STV090x_DEMODULATOR_1:
+		/* power on ADC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR3);
+		STV090x_SETFIELD(reg, ADC2_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR3, reg) < 0)
+			goto err;
+		/* power on DiSEqC 2 */
+		reg = stv090x_read_reg(state, STV090x_TSTTNR4);
+		STV090x_SETFIELD(reg, DISEQC2_PON_FIELD, 1);
+		if (stv090x_write_reg(state, STV090x_TSTTNR4, reg) < 0)
+			goto err;
+
+		/* activate clocks */
+		reg = stv090x_read_reg(state, STV090x_STOPCLK1);
+		/* packet delineator 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKPKDT2_FIELD, 0);
+		/* ADC 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKADCI2_FIELD, 0);
+		/* FEC clock */
+		STV090x_SETFIELD(reg, STOP_CLKFEC_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK1, reg) < 0)
+			goto err;
+		reg = stv090x_read_reg(state, STV090x_STOPCLK2);
+		/* sampling 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKSAMP2_FIELD, 0);
+		/* viterbi 2 clock */
+		STV090x_SETFIELD(reg, STOP_CLKVIT2_FIELD, 0);
+		/* TS clock */
+		STV090x_SETFIELD(reg, STOP_CLKTS_FIELD, 0);
+		if (stv090x_write_reg(state, STV090x_STOPCLK2, reg) < 0)
+			goto err;
+		break;
+
+	default:
+		dprintk(FE_ERROR, 1, "Wrong demodulator!");
+		break;
+	}
+
+	mutex_unlock(&state->internal->demod_lock);
 	return 0;
 err:
+	mutex_unlock(&state->internal->demod_lock);
 	dprintk(FE_ERROR, 1, "I/O error");
 	return -1;
 }
@@ -4169,6 +4351,7 @@
 	switch (state->config->ts1_mode) {
 	case STV090x_TSMODE_PARALLEL_PUNCTURED:
 		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
 		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)
@@ -4177,6 +4360,7 @@
 
 	case STV090x_TSMODE_DVBCI:
 		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
 		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)
@@ -4185,6 +4369,7 @@
 
 	case STV090x_TSMODE_SERIAL_PUNCTURED:
 		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
 		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)
@@ -4193,6 +4378,7 @@
 
 	case STV090x_TSMODE_SERIAL_CONTINUOUS:
 		reg = stv090x_read_reg(state, STV090x_P1_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts1_tei);
 		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)
@@ -4206,6 +4392,7 @@
 	switch (state->config->ts2_mode) {
 	case STV090x_TSMODE_PARALLEL_PUNCTURED:
 		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
 		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)
@@ -4214,6 +4401,7 @@
 
 	case STV090x_TSMODE_DVBCI:
 		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
 		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)
@@ -4222,6 +4410,7 @@
 
 	case STV090x_TSMODE_SERIAL_PUNCTURED:
 		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
 		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)
@@ -4230,6 +4419,7 @@
 
 	case STV090x_TSMODE_SERIAL_CONTINUOUS:
 		reg = stv090x_read_reg(state, STV090x_P2_TSCFGH);
+		STV090x_SETFIELD_Px(reg, TSFIFO_TEIUPDATE_FIELD, state->config->ts2_tei);
 		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)
@@ -4506,16 +4696,26 @@
 	if (stv090x_write_reg(state, STV090x_TSTRES0, 0x00) < 0)
 		goto err;
 
-	/* workaround for stuck DiSEqC output */
-	if (config->diseqc_envelope_mode)
-		stv090x_send_diseqc_burst(fe, SEC_MINI_A);
-
 	return 0;
 err:
 	dprintk(FE_ERROR, 1, "I/O error");
 	return -1;
 }
 
+int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio, u8 dir, u8 value,
+		u8 xor_value)
+{
+	struct stv090x_state *state = fe->demodulator_priv;
+	u8 reg = 0;
+
+	STV090x_SETFIELD(reg, GPIOx_OPD_FIELD, dir);
+	STV090x_SETFIELD(reg, GPIOx_CONFIG_FIELD, value);
+	STV090x_SETFIELD(reg, GPIOx_XOR_FIELD, xor_value);
+
+	return stv090x_write_reg(state, STV090x_GPIOxCFG(gpio), reg);
+}
+EXPORT_SYMBOL(stv090x_set_gpio);
+
 static struct dvb_frontend_ops stv090x_ops = {
 
 	.info = {
@@ -4580,39 +4780,35 @@
 		state->internal = temp_int->internal;
 		state->internal->num_used++;
 		dprintk(FE_INFO, 1, "Found Internal Structure!");
-		dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
-			state->device == STV0900 ? "STV0900" : "STV0903",
-			demod,
-			state->internal->dev_ver);
-		return &state->frontend;
 	} else {
 		state->internal = kmalloc(sizeof(struct stv090x_internal),
 					  GFP_KERNEL);
+		if (!state->internal)
+			goto error;
 		temp_int = append_internal(state->internal);
+		if (!temp_int) {
+			kfree(state->internal);
+			goto error;
+		}
 		state->internal->num_used = 1;
 		state->internal->mclk = 0;
 		state->internal->dev_ver = 0;
 		state->internal->i2c_adap = state->i2c;
 		state->internal->i2c_addr = state->config->address;
 		dprintk(FE_INFO, 1, "Create New Internal Structure!");
-	}
 
-	mutex_init(&state->internal->demod_lock);
-	mutex_init(&state->internal->tuner_lock);
+		mutex_init(&state->internal->demod_lock);
+		mutex_init(&state->internal->tuner_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 err_remove;
+		}
 	}
 
-	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;
-	}
+	/* workaround for stuck DiSEqC output */
+	if (config->diseqc_envelope_mode)
+		stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
 
 	dprintk(FE_ERROR, 1, "Attaching %s demodulator(%d) Cut=0x%02x",
 	       state->device == STV0900 ? "STV0900" : "STV0903",
@@ -4621,6 +4817,9 @@
 
 	return &state->frontend;
 
+err_remove:
+	remove_dev(state->internal);
+	kfree(state->internal);
 error:
 	kfree(state);
 	return NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv090x.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv090x.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv090x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv090x.h	2011-05-19 00:06:34.000000000 -0400
@@ -78,6 +78,9 @@
 	u32 ts1_clk;
 	u32 ts2_clk;
 
+	u8 ts1_tei : 1;
+	u8 ts2_tei : 1;
+
 	enum stv090x_i2crpt	repeater_level;
 
 	u8			tuner_bbgain; /* default: 10db */
@@ -97,6 +100,7 @@
 	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);
+	void (*tuner_i2c_lock) (struct dvb_frontend *fe, int lock);
 };
 
 #if defined(CONFIG_DVB_STV090x) || (defined(CONFIG_DVB_STV090x_MODULE) && defined(MODULE))
@@ -104,6 +108,11 @@
 extern struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
 					   struct i2c_adapter *i2c,
 					   enum stv090x_demodulator demod);
+
+/* dir = 0 -> output, dir = 1 -> input/open-drain */
+extern int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+		u8 dir, u8 value, u8 xor_value);
+
 #else
 
 static inline struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
@@ -113,6 +122,13 @@
 	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
 	return NULL;
 }
+
+static inline int stv090x_set_gpio(struct dvb_frontend *fe, u8 gpio,
+		u8 opd, u8 value, u8 xor_value)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return -ENODEV;
+}
 #endif /* CONFIG_DVB_STV090x */
 
 #endif /* __STV090x_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv090x_reg.h linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv090x_reg.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/stv090x_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/stv090x_reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -1327,10 +1327,10 @@
 #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_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
 
@@ -1406,7 +1406,7 @@
 
 #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_P2_BCLC2S28			STV090x_Px_BCLC2S28(2)
 #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
@@ -1414,7 +1414,7 @@
 
 #define STV090x_Px_BCLC2S216A(__x)		(0xf49e - (__x - 1) * 0x200)
 #define STV090x_P1_BCLC2S216A			STV090x_Px_BCLC2S216A(1)
-#define STV090x_P2_BCLC2S216A			STV090x_Px_BCLC2S216A(1)
+#define STV090x_P2_BCLC2S216A			STV090x_Px_BCLC2S216A(2)
 #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
@@ -1422,7 +1422,7 @@
 
 #define STV090x_Px_BCLC2S232A(__x)		(0xf49f - (__x - 1) * 0x200)
 #define STV090x_P1_BCLC2S232A			STV090x_Px_BCLC2S232A(1)
-#define STV090x_P2_BCLC2S232A			STV090x_Px_BCLC2S232A(1)
+#define STV090x_P2_BCLC2S232A			STV090x_Px_BCLC2S232A(2)
 #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
@@ -1602,7 +1602,7 @@
 
 #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_P2_CCIACC			STV090x_Px_CCIACC(2)
 #define STV090x_OFFST_Px_CCI_VALUE_FIELD	0
 #define STV090x_WIDTH_Px_CCI_VALUE_FIELD	8
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/zl10036.c linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/zl10036.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/frontends/zl10036.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/frontends/zl10036.c	2011-05-19 00:06:34.000000000 -0400
@@ -463,16 +463,16 @@
 				    const struct zl10036_config *config,
 				    struct i2c_adapter *i2c)
 {
-	struct zl10036_state *state = NULL;
+	struct zl10036_state *state;
 	int ret;
 
-	if (NULL == config) {
+	if (!config) {
 		printk(KERN_ERR "%s: no config specified", __func__);
-		goto error;
+		return NULL;
 	}
 
 	state = kzalloc(sizeof(struct zl10036_state), GFP_KERNEL);
-	if (NULL == state)
+	if (!state)
 		return NULL;
 
 	state->config = config;
@@ -507,7 +507,7 @@
 	return fe;
 
 error:
-	zl10036_release(fe);
+	kfree(state);
 	return NULL;
 }
 EXPORT_SYMBOL(zl10036_attach);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/Kconfig linux-libre-2.6.39-gnu/drivers/media/dvb/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/dvb/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
 source "drivers/media/dvb/dm1105/Kconfig"
 
 comment "Supported FireWire (IEEE 1394) Adapters"
-	depends on DVB_CORE && IEEE1394
+	depends on DVB_CORE && FIREWIRE
 source "drivers/media/dvb/firewire/Kconfig"
 
 comment "Supported Earthsoft PT1 Adapters"
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/mantis/mantis_uart.c linux-libre-2.6.39-gnu/drivers/media/dvb/mantis/mantis_uart.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/mantis/mantis_uart.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/mantis/mantis_uart.c	2011-05-19 00:06:34.000000000 -0400
@@ -172,7 +172,7 @@
 	mmwrite(mmread(MANTIS_UART_CTL) | MANTIS_UART_RXINT, MANTIS_UART_CTL);
 
 	schedule_work(&mantis->uart_work);
-	dprintk(MANTIS_DEBUG, 1, "UART succesfully initialized");
+	dprintk(MANTIS_DEBUG, 1, "UART successfully initialized");
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/Makefile linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,3 +9,6 @@
 EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core/
 EXTRA_CFLAGS += -Idrivers/media/dvb/frontends/
 EXTRA_CFLAGS += -Idrivers/media/common/tuners/
+
+# For the staging CI driver cxd2099
+EXTRA_CFLAGS += -Idrivers/staging/cxd2099/
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene-cards.c linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene-cards.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene-cards.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,20 +48,27 @@
 
 static int tuner_attach_stv6110(struct ngene_channel *chan)
 {
+	struct i2c_adapter *i2c;
 	struct stv090x_config *feconf = (struct stv090x_config *)
 		chan->dev->card_info->fe_config[chan->number];
 	struct stv6110x_config *tunerconf = (struct stv6110x_config *)
 		chan->dev->card_info->tuner_config[chan->number];
 	struct stv6110x_devctl *ctl;
 
-	ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf,
-			 &chan->i2c_adapter);
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	ctl = dvb_attach(stv6110x_attach, chan->fe, tunerconf, i2c);
 	if (ctl == NULL) {
 		printk(KERN_ERR	DEVICE_NAME ": No STV6110X found!\n");
 		return -ENODEV;
 	}
 
 	feconf->tuner_init          = ctl->tuner_init;
+	feconf->tuner_sleep         = ctl->tuner_sleep;
 	feconf->tuner_set_mode      = ctl->tuner_set_mode;
 	feconf->tuner_set_frequency = ctl->tuner_set_frequency;
 	feconf->tuner_get_frequency = ctl->tuner_get_frequency;
@@ -78,29 +85,106 @@
 
 static int demod_attach_stv0900(struct ngene_channel *chan)
 {
+	struct i2c_adapter *i2c;
 	struct stv090x_config *feconf = (struct stv090x_config *)
 		chan->dev->card_info->fe_config[chan->number];
 
-	chan->fe = dvb_attach(stv090x_attach,
-			feconf,
-			&chan->i2c_adapter,
-			chan->number == 0 ? STV090x_DEMODULATOR_0 :
-					    STV090x_DEMODULATOR_1);
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	/* Note: Both adapters share the same i2c bus, but the demod     */
+	/*       driver requires that each demod has its own i2c adapter */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	chan->fe = dvb_attach(stv090x_attach, feconf, i2c,
+			(chan->number & 1) == 0 ? STV090x_DEMODULATOR_0
+						: STV090x_DEMODULATOR_1);
 	if (chan->fe == NULL) {
 		printk(KERN_ERR	DEVICE_NAME ": No STV0900 found!\n");
 		return -ENODEV;
 	}
 
-	if (!dvb_attach(lnbh24_attach, chan->fe, &chan->i2c_adapter, 0,
+	/* store channel info */
+	if (feconf->tuner_i2c_lock)
+		chan->fe->analog_demod_priv = chan;
+
+	if (!dvb_attach(lnbh24_attach, chan->fe, i2c, 0,
 			0, chan->dev->card_info->lnb[chan->number])) {
 		printk(KERN_ERR DEVICE_NAME ": No LNBH24 found!\n");
 		dvb_frontend_detach(chan->fe);
+		chan->fe = NULL;
 		return -ENODEV;
 	}
 
 	return 0;
 }
 
+static void cineS2_tuner_i2c_lock(struct dvb_frontend *fe, int lock)
+{
+	struct ngene_channel *chan = fe->analog_demod_priv;
+
+	if (lock)
+		down(&chan->dev->pll_mutex);
+	else
+		up(&chan->dev->pll_mutex);
+}
+
+static int cineS2_probe(struct ngene_channel *chan)
+{
+	struct i2c_adapter *i2c;
+	struct stv090x_config *fe_conf;
+	u8 buf[3];
+	struct i2c_msg i2c_msg = { .flags = 0, .buf = buf };
+	int rc;
+
+	/* tuner 1+2: i2c adapter #0, tuner 3+4: i2c adapter #1 */
+	if (chan->number < 2)
+		i2c = &chan->dev->channel[0].i2c_adapter;
+	else
+		i2c = &chan->dev->channel[1].i2c_adapter;
+
+	fe_conf = chan->dev->card_info->fe_config[chan->number];
+	i2c_msg.addr = fe_conf->address;
+
+	/* probe demod */
+	i2c_msg.len = 2;
+	buf[0] = 0xf1;
+	buf[1] = 0x00;
+	rc = i2c_transfer(i2c, &i2c_msg, 1);
+	if (rc != 1)
+		return -ENODEV;
+
+	/* demod found, attach it */
+	rc = demod_attach_stv0900(chan);
+	if (rc < 0 || chan->number < 2)
+		return rc;
+
+	/* demod #2: reprogram outputs DPN1 & DPN2 */
+	i2c_msg.len = 3;
+	buf[0] = 0xf1;
+	switch (chan->number) {
+	case 2:
+		buf[1] = 0x5c;
+		buf[2] = 0xc2;
+		break;
+	case 3:
+		buf[1] = 0x61;
+		buf[2] = 0xcc;
+		break;
+	default:
+		return -ENODEV;
+	}
+	rc = i2c_transfer(i2c, &i2c_msg, 1);
+	if (rc != 1) {
+		printk(KERN_ERR DEVICE_NAME ": could not setup DPNx\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+
 static struct lgdt330x_config aver_m780 = {
 	.demod_address = 0xb2 >> 1,
 	.demod_chip    = LGDT3303,
@@ -151,6 +235,29 @@
 	.adc2_range	= STV090x_ADC_1Vpp,
 
 	.diseqc_envelope_mode = true,
+
+	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
+};
+
+static struct stv090x_config fe_cineS2_2 = {
+	.device         = STV0900,
+	.demod_mode     = STV090x_DUAL,
+	.clk_mode       = STV090x_CLK_EXT,
+
+	.xtal           = 27000000,
+	.address        = 0x69,
+
+	.ts1_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+	.ts2_mode       = STV090x_TSMODE_SERIAL_PUNCTURED,
+
+	.repeater_level = STV090x_RPTLEVEL_16,
+
+	.adc1_range	= STV090x_ADC_1Vpp,
+	.adc2_range	= STV090x_ADC_1Vpp,
+
+	.diseqc_envelope_mode = true,
+
+	.tuner_i2c_lock = cineS2_tuner_i2c_lock,
 };
 
 static struct stv6110x_config tuner_cineS2_0 = {
@@ -175,7 +282,8 @@
 	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
 	.lnb		= {0x0b, 0x08},
 	.tsf		= {3, 3},
-	.fw_version	= 15,
+	.fw_version	= 18,
+	.msi_supported	= true,
 };
 
 static struct ngene_info ngene_info_satixS2 = {
@@ -188,46 +296,54 @@
 	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
 	.lnb		= {0x0b, 0x08},
 	.tsf		= {3, 3},
-	.fw_version	= 15,
+	.fw_version	= 18,
+	.msi_supported	= true,
 };
 
 static struct ngene_info ngene_info_satixS2v2 = {
 	.type		= NGENE_SIDEWINDER,
 	.name		= "Mystique SaTiX-S2 Dual (v2)",
-	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
-	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
-	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
-	.fe_config	= {&fe_cineS2, &fe_cineS2},
-	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb		= {0x0a, 0x08},
+	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSOUT},
+	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
+	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
+	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
 	.tsf		= {3, 3},
-	.fw_version	= 15,
+	.fw_version	= 18,
+	.msi_supported	= true,
 };
 
 static struct ngene_info ngene_info_cineS2v5 = {
 	.type		= NGENE_SIDEWINDER,
 	.name		= "Linux4Media cineS2 DVB-S2 Twin Tuner (v5)",
-	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN},
-	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900},
-	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110},
-	.fe_config	= {&fe_cineS2, &fe_cineS2},
-	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb		= {0x0a, 0x08},
+	.io_type	= {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSOUT},
+	.demod_attach	= {demod_attach_stv0900, demod_attach_stv0900, cineS2_probe, cineS2_probe},
+	.tuner_attach	= {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+	.fe_config	= {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
+	.tuner_config	= {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb		= {0x0a, 0x08, 0x0b, 0x09},
 	.tsf		= {3, 3},
-	.fw_version	= 15,
+	.fw_version	= 18,
+	.msi_supported	= true,
 };
 
+
 static struct ngene_info ngene_info_duoFlexS2 = {
 	.type           = NGENE_SIDEWINDER,
 	.name           = "Digital Devices DuoFlex S2 miniPCIe",
-	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
-	.demod_attach   = {demod_attach_stv0900, demod_attach_stv0900},
-	.tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110},
-	.fe_config      = {&fe_cineS2, &fe_cineS2},
-	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1},
-	.lnb            = {0x0a, 0x08},
+	.io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN, NGENE_IO_TSIN,
+			   NGENE_IO_TSOUT},
+	.demod_attach   = {cineS2_probe, cineS2_probe, cineS2_probe, cineS2_probe},
+	.tuner_attach   = {tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110, tuner_attach_stv6110},
+	.fe_config      = {&fe_cineS2, &fe_cineS2, &fe_cineS2_2, &fe_cineS2_2},
+	.tuner_config   = {&tuner_cineS2_0, &tuner_cineS2_1, &tuner_cineS2_0, &tuner_cineS2_1},
+	.lnb            = {0x0a, 0x08, 0x0b, 0x09},
 	.tsf            = {3, 3},
-	.fw_version     = 15,
+	.fw_version     = 18,
+	.msi_supported	= true,
 };
 
 static struct ngene_info ngene_info_m780 = {
@@ -321,6 +437,7 @@
 	.probe       = ngene_probe,
 	.remove      = __devexit_p(ngene_remove),
 	.err_handler = &ngene_errors,
+	.shutdown    = ngene_shutdown,
 };
 
 static __init int module_init_ngene(void)
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene-core.c linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene-core.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene-core.c	2012-03-24 01:03:39.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene-core.c	2012-03-24 03:28:27.000000000 -0400
@@ -45,6 +45,9 @@
 module_param(one_adapter, int, 0444);
 MODULE_PARM_DESC(one_adapter, "Use only one adapter.");
 
+static int shutdown_workaround;
+module_param(shutdown_workaround, int, 0644);
+MODULE_PARM_DESC(shutdown_workaround, "Activate workaround for shutdown problem with some chipsets.");
 
 static int debug;
 module_param(debug, int, 0444);
@@ -119,7 +122,7 @@
 						Cur->ngeneBuffer.SR.Flags &=
 							~0x40;
 						break;
-						/* Stop proccessing stream */
+						/* Stop processing stream */
 					}
 				} else {
 					/* We got a valid buffer,
@@ -130,7 +133,7 @@
 				printk(KERN_ERR DEVICE_NAME ": OOPS\n");
 				if (chan->HWState == HWSTATE_RUN) {
 					Cur->ngeneBuffer.SR.Flags &= ~0x40;
-					break;	/* Stop proccessing stream */
+					break;	/* Stop processing stream */
 				}
 			}
 			if (chan->AudioDTOUpdated) {
@@ -143,7 +146,7 @@
 			}
 		} else {
 			if (chan->HWState == HWSTATE_RUN) {
-				u32 Flags = 0;
+				u32 Flags = chan->DataFormatFlags;
 				IBufferExchange *exch1 = chan->pBufferExchange;
 				IBufferExchange *exch2 = chan->pBufferExchange2;
 				if (Cur->ngeneBuffer.SR.Flags & 0x01)
@@ -474,9 +477,9 @@
 
 /* Set NGENE I2S Config to transport stream compatible mode */
 
-static u8 TS_I2SConfiguration[4] = { 0x3E, 0x1A, 0x00, 0x00 }; /*3e 18 00 00 ?*/
+static u8 TS_I2SConfiguration[4] = { 0x3E, 0x18, 0x00, 0x00 };
 
-static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x20, 0x00, 0x00 };
+static u8 TS_I2SOutConfiguration[4] = { 0x80, 0x04, 0x00, 0x00 };
 
 static u8 ITUDecoderSetup[4][16] = {
 	{0x1c, 0x13, 0x01, 0x68, 0x3d, 0x90, 0x14, 0x20,  /* SDTV */
@@ -749,13 +752,11 @@
 		if (chan->mode & NGENE_IO_TSOUT) {
 			chan->pBufferExchange = tsout_exchange;
 			/* 0x66666666 = 50MHz *2^33 /250MHz */
-			chan->AudioDTOValue = 0x66666666;
-			/* set_dto(chan, 38810700+1000); */
-			/* set_dto(chan, 19392658); */
+			chan->AudioDTOValue = 0x80000000;
+			chan->AudioDTOUpdated = 1;
 		}
 		if (chan->mode & NGENE_IO_TSIN)
 			chan->pBufferExchange = tsin_exchange;
-		/* ngwritel(0, 0x9310); */
 		spin_unlock_irq(&chan->state_lock);
 	} else
 		;/* printk(KERN_INFO DEVICE_NAME ": lock=%08x\n",
@@ -1168,6 +1169,7 @@
 		iounmap(dev->iomem);
 	free_common_buffers(dev);
 	vfree(dev->tsout_buf);
+	vfree(dev->tsin_buf);
 	vfree(dev->ain_buf);
 	vfree(dev->vin_buf);
 	vfree(dev);
@@ -1184,6 +1186,13 @@
 		dvb_ringbuffer_init(&dev->tsout_rbuf,
 				    dev->tsout_buf, TSOUT_BUF_SIZE);
 	}
+	if (dev->card_info->io_type[2]&NGENE_IO_TSIN) {
+		dev->tsin_buf = vmalloc(TSIN_BUF_SIZE);
+		if (!dev->tsin_buf)
+			return -ENOMEM;
+		dvb_ringbuffer_init(&dev->tsin_rbuf,
+				    dev->tsin_buf, TSIN_BUF_SIZE);
+	}
 	if (dev->card_info->io_type[2] & NGENE_IO_AIN) {
 		dev->ain_buf = vmalloc(AIN_BUF_SIZE);
 		if (!dev->ain_buf)
@@ -1257,6 +1266,10 @@
 		fw_name = "/*(DEBLOBBED)*/";
 		dev->cmd_timeout_workaround = true;
 		break;
+	case 18:
+		size = 0;
+		fw_name = "/*(DEBLOBBED)*/";
+		break;
 	}
 
 	if (reject_firmware(&fw, fw_name, &dev->pci_dev->dev) < 0) {
@@ -1266,6 +1279,8 @@
 			": Copy %s to your hotplug directory!\n", fw_name);
 		return -1;
 	}
+	if (size == 0)
+		size = fw->size;
 	if (size != fw->size) {
 		printk(KERN_ERR DEVICE_NAME
 			": Firmware %s has invalid size!", fw_name);
@@ -1301,6 +1316,35 @@
 #endif
 }
 
+static int ngene_buffer_config(struct ngene *dev)
+{
+	int stat;
+
+	if (dev->card_info->fw_version >= 17) {
+		u8 tsin12_config[6]   = { 0x60, 0x60, 0x00, 0x00, 0x00, 0x00 };
+		u8 tsin1234_config[6] = { 0x30, 0x30, 0x00, 0x30, 0x30, 0x00 };
+		u8 tsio1235_config[6] = { 0x30, 0x30, 0x00, 0x28, 0x00, 0x38 };
+		u8 *bconf = tsin12_config;
+
+		if (dev->card_info->io_type[2]&NGENE_IO_TSIN &&
+		    dev->card_info->io_type[3]&NGENE_IO_TSIN) {
+			bconf = tsin1234_config;
+			if (dev->card_info->io_type[4]&NGENE_IO_TSOUT &&
+			    dev->ci.en)
+				bconf = tsio1235_config;
+		}
+		stat = ngene_command_config_free_buf(dev, bconf);
+	} else {
+		int bconf = BUFFER_CONFIG_4422;
+
+		if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
+			bconf = BUFFER_CONFIG_3333;
+		stat = ngene_command_config_buf(dev, bconf);
+	}
+	return stat;
+}
+
+
 static int ngene_start(struct ngene *dev)
 {
 	int stat;
@@ -1365,23 +1409,6 @@
 	if (stat < 0)
 		goto fail;
 
-	if (dev->card_info->fw_version == 17) {
-		u8 tsin4_config[6] = {
-			3072 / 64, 3072 / 64, 0, 3072 / 64, 3072 / 64, 0};
-		u8 default_config[6] = {
-			4096 / 64, 4096 / 64, 0, 2048 / 64, 2048 / 64, 0};
-		u8 *bconf = default_config;
-
-		if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
-			bconf = tsin4_config;
-		dprintk(KERN_DEBUG DEVICE_NAME ": FW 17 buffer config\n");
-		stat = ngene_command_config_free_buf(dev, bconf);
-	} else {
-		int bconf = BUFFER_CONFIG_4422;
-		if (dev->card_info->io_type[3] == NGENE_IO_TSIN)
-			bconf = BUFFER_CONFIG_3333;
-		stat = ngene_command_config_buf(dev, bconf);
-	}
 	if (!stat)
 		return stat;
 
@@ -1397,9 +1424,6 @@
 	return stat;
 }
 
-
-
-
 /****************************************************************************/
 /****************************************************************************/
 /****************************************************************************/
@@ -1408,20 +1432,25 @@
 {
 	struct dvb_demux *dvbdemux = &chan->demux;
 	struct ngene *dev = chan->dev;
-	struct ngene_info *ni = dev->card_info;
-	int io = ni->io_type[chan->number];
 
-	if (chan->dev->cmd_timeout_workaround && chan->running)
+	if (chan->running)
 		set_transfer(chan, 0);
 
 	tasklet_kill(&chan->demux_tasklet);
 
-	if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
-		if (chan->fe) {
-			dvb_unregister_frontend(chan->fe);
-			dvb_frontend_detach(chan->fe);
-			chan->fe = NULL;
-		}
+	if (chan->ci_dev) {
+		dvb_unregister_device(chan->ci_dev);
+		chan->ci_dev = NULL;
+	}
+
+	if (chan->fe) {
+		dvb_unregister_frontend(chan->fe);
+		dvb_frontend_detach(chan->fe);
+		chan->fe = NULL;
+	}
+
+	if (chan->has_demux) {
+		dvb_net_release(&chan->dvbnet);
 		dvbdemux->dmx.close(&dvbdemux->dmx);
 		dvbdemux->dmx.remove_frontend(&dvbdemux->dmx,
 					      &chan->hw_frontend);
@@ -1429,9 +1458,12 @@
 					      &chan->mem_frontend);
 		dvb_dmxdev_release(&chan->dmxdev);
 		dvb_dmx_release(&chan->demux);
+		chan->has_demux = false;
+	}
 
-		if (chan->number == 0 || !one_adapter)
-			dvb_unregister_adapter(&dev->adapter[chan->number]);
+	if (chan->has_adapter) {
+		dvb_unregister_adapter(&dev->adapter[chan->number]);
+		chan->has_adapter = false;
 	}
 }
 
@@ -1449,9 +1481,27 @@
 	chan->type = io;
 	chan->mode = chan->type;	/* for now only one mode */
 
+	if (io & NGENE_IO_TSIN) {
+		chan->fe = NULL;
+		if (ni->demod_attach[nr]) {
+			ret = ni->demod_attach[nr](chan);
+			if (ret < 0)
+				goto err;
+		}
+		if (chan->fe && ni->tuner_attach[nr]) {
+			ret = ni->tuner_attach[nr](chan);
+			if (ret < 0)
+				goto err;
+		}
+	}
+
+	if (!dev->ci.en && (io & NGENE_IO_TSOUT))
+		return 0;
+
 	if (io & (NGENE_IO_TSIN | NGENE_IO_TSOUT)) {
 		if (nr >= STREAM_AUDIOIN1)
 			chan->DataFormatFlags = DF_SWAP32;
+
 		if (nr == 0 || !one_adapter || dev->first_adapter == NULL) {
 			adapter = &dev->adapter[nr];
 			ret = dvb_register_adapter(adapter, "nGene",
@@ -1459,40 +1509,51 @@
 						   &chan->dev->pci_dev->dev,
 						   adapter_nr);
 			if (ret < 0)
-				return ret;
+				goto err;
 			if (dev->first_adapter == NULL)
 				dev->first_adapter = adapter;
-		} else {
+			chan->has_adapter = true;
+		} else
 			adapter = dev->first_adapter;
-		}
+	}
+
+	if (dev->ci.en && (io & NGENE_IO_TSOUT)) {
+		dvb_ca_en50221_init(adapter, dev->ci.en, 0, 1);
+		set_transfer(chan, 1);
+		chan->dev->channel[2].DataFormatFlags = DF_SWAP32;
+		set_transfer(&chan->dev->channel[2], 1);
+		dvb_register_device(adapter, &chan->ci_dev,
+				    &ngene_dvbdev_ci, (void *) chan,
+				    DVB_DEVICE_SEC);
+		if (!chan->ci_dev)
+			goto err;
+	}
+
+	if (chan->fe) {
+		if (dvb_register_frontend(adapter, chan->fe) < 0)
+			goto err;
+		chan->has_demux = true;
+	}
 
+	if (chan->has_demux) {
 		ret = my_dvb_dmx_ts_card_init(dvbdemux, "SW demux",
 					      ngene_start_feed,
 					      ngene_stop_feed, chan);
 		ret = my_dvb_dmxdev_ts_card_init(&chan->dmxdev, &chan->demux,
 						 &chan->hw_frontend,
 						 &chan->mem_frontend, adapter);
+		ret = dvb_net_init(adapter, &chan->dvbnet, &chan->demux.dmx);
 	}
 
-	if (io & NGENE_IO_TSIN) {
+	return ret;
+
+err:
+	if (chan->fe) {
+		dvb_frontend_detach(chan->fe);
 		chan->fe = NULL;
-		if (ni->demod_attach[nr])
-			ni->demod_attach[nr](chan);
-		if (chan->fe) {
-			if (dvb_register_frontend(adapter, chan->fe) < 0) {
-				if (chan->fe->ops.release)
-					chan->fe->ops.release(chan->fe);
-				chan->fe = NULL;
-			}
-		}
-		if (chan->fe && ni->tuner_attach[nr])
-			if (ni->tuner_attach[nr] (chan) < 0) {
-				printk(KERN_ERR DEVICE_NAME
-				       ": Tuner attach failed on channel %d!\n",
-				       nr);
-			}
 	}
-	return ret;
+	release_channel(chan);
+	return 0;
 }
 
 static int init_channels(struct ngene *dev)
@@ -1510,6 +1571,57 @@
 	return 0;
 }
 
+static void cxd_attach(struct ngene *dev)
+{
+	struct ngene_ci *ci = &dev->ci;
+
+	ci->en = cxd2099_attach(0x40, dev, &dev->channel[0].i2c_adapter);
+	ci->dev = dev;
+	return;
+}
+
+static void cxd_detach(struct ngene *dev)
+{
+	struct ngene_ci *ci = &dev->ci;
+
+	dvb_ca_en50221_release(ci->en);
+	kfree(ci->en);
+	ci->en = 0;
+}
+
+/***********************************/
+/* workaround for shutdown failure */
+/***********************************/
+
+static void ngene_unlink(struct ngene *dev)
+{
+	struct ngene_command com;
+
+	com.cmd.hdr.Opcode = CMD_MEM_WRITE;
+	com.cmd.hdr.Length = 3;
+	com.cmd.MemoryWrite.address = 0x910c;
+	com.cmd.MemoryWrite.data = 0xff;
+	com.in_len = 3;
+	com.out_len = 1;
+
+	down(&dev->cmd_mutex);
+	ngwritel(0, NGENE_INT_ENABLE);
+	ngene_command_mutex(dev, &com);
+	up(&dev->cmd_mutex);
+}
+
+void ngene_shutdown(struct pci_dev *pdev)
+{
+	struct ngene *dev = (struct ngene *)pci_get_drvdata(pdev);
+
+	if (!dev || !shutdown_workaround)
+		return;
+
+	printk(KERN_INFO DEVICE_NAME ": shutdown workaround...\n");
+	ngene_unlink(dev);
+	pci_disable_device(pdev);
+}
+
 /****************************************************************************/
 /* device probe/remove calls ************************************************/
 /****************************************************************************/
@@ -1522,6 +1634,8 @@
 	tasklet_kill(&dev->event_tasklet);
 	for (i = MAX_STREAM - 1; i >= 0; i--)
 		release_channel(&dev->channel[i]);
+	if (dev->ci.en)
+		cxd_detach(dev);
 	ngene_stop(dev);
 	ngene_release_buffers(dev);
 	pci_set_drvdata(pdev, NULL);
@@ -1557,6 +1671,13 @@
 	if (stat < 0)
 		goto fail1;
 
+	cxd_attach(dev);
+
+	stat = ngene_buffer_config(dev);
+	if (stat < 0)
+		goto fail1;
+
+
 	dev->i2c_current_bus = -1;
 
 	/* Register DVB adapters and devices for both channels */
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene-dvb.c linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene-dvb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene-dvb.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,6 +47,64 @@
 /* COMMAND API interface ****************************************************/
 /****************************************************************************/
 
+static ssize_t ts_write(struct file *file, const char *buf,
+			size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+
+	if (wait_event_interruptible(dev->tsout_rbuf.queue,
+				     dvb_ringbuffer_free
+				     (&dev->tsout_rbuf) >= count) < 0)
+		return 0;
+
+	dvb_ringbuffer_write(&dev->tsout_rbuf, buf, count);
+
+	return count;
+}
+
+static ssize_t ts_read(struct file *file, char *buf,
+		       size_t count, loff_t *ppos)
+{
+	struct dvb_device *dvbdev = file->private_data;
+	struct ngene_channel *chan = dvbdev->priv;
+	struct ngene *dev = chan->dev;
+	int left, avail;
+
+	left = count;
+	while (left) {
+		if (wait_event_interruptible(
+			    dev->tsin_rbuf.queue,
+			    dvb_ringbuffer_avail(&dev->tsin_rbuf) > 0) < 0)
+			return -EAGAIN;
+		avail = dvb_ringbuffer_avail(&dev->tsin_rbuf);
+		if (avail > left)
+			avail = left;
+		dvb_ringbuffer_read_user(&dev->tsin_rbuf, buf, avail);
+		left -= avail;
+		buf += avail;
+	}
+	return count;
+}
+
+static const struct file_operations ci_fops = {
+	.owner   = THIS_MODULE,
+	.read    = ts_read,
+	.write   = ts_write,
+	.open    = dvb_generic_open,
+	.release = dvb_generic_release,
+};
+
+struct dvb_device ngene_dvbdev_ci = {
+	.priv    = 0,
+	.readers = -1,
+	.writers = -1,
+	.users   = -1,
+	.fops    = &ci_fops,
+};
+
+
 /****************************************************************************/
 /* DVB functions and API interface ******************************************/
 /****************************************************************************/
@@ -63,10 +121,21 @@
 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags)
 {
 	struct ngene_channel *chan = priv;
+	struct ngene *dev = chan->dev;
 
 
-	if (chan->users > 0)
+	if (flags & DF_SWAP32)
+		swap_buffer(buf, len);
+	if (dev->ci.en && chan->number == 2) {
+		if (dvb_ringbuffer_free(&dev->tsin_rbuf) > len) {
+			dvb_ringbuffer_write(&dev->tsin_rbuf, buf, len);
+			wake_up_interruptible(&dev->tsin_rbuf.queue);
+		}
+		return 0;
+	}
+	if (chan->users > 0) {
 		dvb_dmx_swfilter(&chan->demux, buf, len);
+	}
 	return NULL;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene.h linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene.h
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ngene/ngene.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ngene/ngene.h	2011-05-19 00:06:34.000000000 -0400
@@ -36,8 +36,11 @@
 #include "dmxdev.h"
 #include "dvbdev.h"
 #include "dvb_demux.h"
+#include "dvb_ca_en50221.h"
 #include "dvb_frontend.h"
 #include "dvb_ringbuffer.h"
+#include "dvb_net.h"
+#include "cxd2099.h"
 
 #define DEVICE_NAME "ngene"
 
@@ -636,14 +639,18 @@
 	int                   number;
 	int                   type;
 	int                   mode;
+	bool                  has_adapter;
+	bool                  has_demux;
 
 	struct dvb_frontend  *fe;
 	struct dmxdev         dmxdev;
 	struct dvb_demux      demux;
+	struct dvb_net        dvbnet;
 	struct dmx_frontend   hw_frontend;
 	struct dmx_frontend   mem_frontend;
 	int                   users;
 	struct video_device  *v4l_dev;
+	struct dvb_device    *ci_dev;
 	struct tasklet_struct demux_tasklet;
 
 	struct SBufferHeader *nextBuffer;
@@ -710,6 +717,15 @@
 	int running;
 };
 
+
+struct ngene_ci {
+	struct device         device;
+	struct i2c_adapter    i2c_adapter;
+
+	struct ngene         *dev;
+	struct dvb_ca_en50221 *en;
+};
+
 struct ngene;
 
 typedef void (rx_cb_t)(struct ngene *, u32, u8);
@@ -774,6 +790,10 @@
 #define TSOUT_BUF_SIZE (512*188*8)
 	struct dvb_ringbuffer tsout_rbuf;
 
+	u8                   *tsin_buf;
+#define TSIN_BUF_SIZE (512*188*8)
+	struct dvb_ringbuffer tsin_rbuf;
+
 	u8                   *ain_buf;
 #define AIN_BUF_SIZE (128*1024)
 	struct dvb_ringbuffer ain_rbuf;
@@ -785,6 +805,8 @@
 
 	unsigned long         exp_val;
 	int prev_cmd;
+
+	struct ngene_ci       ci;
 };
 
 struct ngene_info {
@@ -863,6 +885,7 @@
 int __devinit ngene_probe(struct pci_dev *pci_dev,
 			  const struct pci_device_id *id);
 void __devexit ngene_remove(struct pci_dev *pdev);
+void ngene_shutdown(struct pci_dev *pdev);
 int ngene_command(struct ngene *dev, struct ngene_command *com);
 int ngene_command_gpio_set(struct ngene *dev, u8 select, u8 level);
 void set_transfer(struct ngene_channel *chan, int state);
@@ -872,6 +895,7 @@
 int ngene_i2c_init(struct ngene *dev, int dev_nr);
 
 /* Provided by ngene-dvb.c */
+extern struct dvb_device ngene_dvbdev_ci;
 void *tsout_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags);
 void *tsin_exchange(void *priv, void *buf, u32 len, u32 clock, u32 flags);
 int ngene_start_feed(struct dvb_demux_feed *dvbdmxfeed);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/pluto2/pluto2.c linux-libre-2.6.39-gnu/drivers/media/dvb/pluto2/pluto2.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/pluto2/pluto2.c	2012-03-24 01:03:39.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/pluto2/pluto2.c	2012-03-24 03:28:27.000000000 -0400
@@ -294,13 +294,13 @@
 
 	/* Workaround for broken hardware:
 	 * [1] On startup NBPACKETS seems to contain an uninitialized value,
-	 *     but no packets have been transfered.
+	 *     but no packets have been transferred.
 	 * [2] Sometimes (actually very often) NBPACKETS stays at zero
-	 *     although one packet has been transfered.
+	 *     although one packet has been transferred.
 	 * [3] Sometimes (actually rarely), the card gets into an erroneous
 	 *     mode where it continuously generates interrupts, claiming it
-	 *     has recieved nbpackets>TS_DMA_PACKETS packets, but no packet
-	 *     has been transfered. Only a reset seems to solve this
+	 *     has received nbpackets>TS_DMA_PACKETS packets, but no packet
+	 *     has been transferred. Only a reset seems to solve this
 	 */
 	if ((nbpackets == 0) || (nbpackets > TS_DMA_PACKETS)) {
 		unsigned int i = 0;
@@ -332,7 +332,7 @@
 	struct pluto *pluto = dev_id;
 	u32 tscr;
 
-	/* check whether an interrupt occured on this device */
+	/* check whether an interrupt occurred on this device */
 	tscr = pluto_readreg(pluto, REG_TSCR);
 	if (!(tscr & (TSCR_DE | TSCR_OVR)))
 		return IRQ_NONE;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/siano/sms-cards.c linux-libre-2.6.39-gnu/drivers/media/dvb/siano/sms-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/siano/sms-cards.c	2012-03-24 01:03:47.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/siano/sms-cards.c	2012-03-24 03:28:32.000000000 -0400
@@ -64,7 +64,7 @@
 		.type	= SMS_NOVA_B0,
 		.fw[DEVICE_MODE_ISDBT_BDA] = "/*(DEBLOBBED)*/",
 		.fw[DEVICE_MODE_DVBT_BDA] = "/*(DEBLOBBED)*/",
-		.rc_codes = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.rc_codes = RC_MAP_HAUPPAUGE,
 		.board_cfg.leds_power = 26,
 		.board_cfg.led0 = 27,
 		.board_cfg.led1 = 28,
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/siano/smsdvb.c linux-libre-2.6.39-gnu/drivers/media/dvb/siano/smsdvb.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/siano/smsdvb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/siano/smsdvb.c	2011-05-19 00:06:34.000000000 -0400
@@ -650,7 +650,7 @@
 		if (status & FE_HAS_LOCK)
 			return ret;
 
-		/* previous tune didnt lock - enable LNA and tune again */
+		/* previous tune didn't lock - enable LNA and tune again */
 		sms_board_lna_control(client->coredev, 1);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ttpci/av7110.c linux-libre-2.6.39-gnu/drivers/media/dvb/ttpci/av7110.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ttpci/av7110.c	2012-03-24 01:03:31.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ttpci/av7110.c	2012-03-24 03:28:21.000000000 -0400
@@ -2332,7 +2332,7 @@
  * increment. That's how the 7146 is programmed to do event
  * counting in this budget-patch.c
  * I *think* HPS setting has something to do with the phase
- * of HS but I cant be 100% sure in that.
+ * of HS but I can't be 100% sure in that.
  *
  * hardware debug note: a working budget card (including budget patch)
  * with vpeirq() interrupt setup in mode "0x90" (every 64K) will
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ttpci/budget-ci.c linux-libre-2.6.39-gnu/drivers/media/dvb/ttpci/budget-ci.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ttpci/budget-ci.c	2012-03-24 01:03:31.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ttpci/budget-ci.c	2012-03-24 03:28:23.000000000 -0400
@@ -26,7 +26,7 @@
  * Or, point your browser to http://www.gnu.org/copyleft/gpl.html
  *
  *
- * the project's page is at http://www.linuxtv.org/ 
+ * the project's page is at http://www.linuxtv.org/
  */
 
 #include <linux/module.h>
@@ -102,6 +102,7 @@
 	int rc5_device;
 	u32 ir_key;
 	bool have_command;
+	bool full_rc5;		/* Outputs a full RC5 code */
 };
 
 struct budget_ci {
@@ -154,11 +155,18 @@
 		return;
 	budget_ci->ir.have_command = false;
 
-	/* FIXME: We should generate complete scancodes with device info */
 	if (budget_ci->ir.rc5_device != IR_DEVICE_ANY &&
 	    budget_ci->ir.rc5_device != (command & 0x1f))
 		return;
 
+	if (budget_ci->ir.full_rc5) {
+		rc_keydown(dev,
+			   budget_ci->ir.rc5_device <<8 | budget_ci->ir.ir_key,
+			   (command & 0x20) ? 1 : 0);
+		return;
+	}
+
+	/* FIXME: We should generate complete scancodes for all devices */
 	rc_keydown(dev, budget_ci->ir.ir_key, (command & 0x20) ? 1 : 0);
 }
 
@@ -206,7 +214,8 @@
 	case 0x1011:
 	case 0x1012:
 		/* The hauppauge keymap is a superset of these remotes */
-		dev->map_name = RC_MAP_HAUPPAUGE_NEW;
+		dev->map_name = RC_MAP_HAUPPAUGE;
+		budget_ci->ir.full_rc5 = true;
 
 		if (rc5_device < 0)
 			budget_ci->ir.rc5_device = 0x1f;
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ttpci/budget-patch.c linux-libre-2.6.39-gnu/drivers/media/dvb/ttpci/budget-patch.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ttpci/budget-patch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ttpci/budget-patch.c	2011-05-19 00:06:34.000000000 -0400
@@ -539,7 +539,7 @@
 **      increment. That's how the 7146 is programmed to do event
 **      counting in this budget-patch.c
 **      I *think* HPS setting has something to do with the phase
-**      of HS but I cant be 100% sure in that.
+**      of HS but I can't be 100% sure in that.
 
 **      hardware debug note: a working budget card (including budget patch)
 **      with vpeirq() interrupt setup in mode "0x90" (every 64K) will
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c linux-libre-2.6.39-gnu/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	2012-03-24 01:03:55.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c	2012-03-24 03:28:37.000000000 -0400
@@ -334,6 +334,7 @@
 	err = ttusb_cmd(ttusb, b, 4, 0);
 
       done:
+	release_firmware(fw);
 	if (err) {
 		dprintk("%s: usb_bulk_msg() failed, return value %i!\n",
 			__func__, err);
diff -druN linux-libre-2.6.38-gnu/drivers/media/dvb/ttusb-dec/ttusb_dec.c linux-libre-2.6.39-gnu/drivers/media/dvb/ttusb-dec/ttusb_dec.c
--- linux-libre-2.6.38-gnu/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2012-03-24 01:04:00.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/dvb/ttusb-dec/ttusb_dec.c	2012-03-24 03:28:40.000000000 -0400
@@ -234,7 +234,7 @@
 		 * (with buffer[3] == 0x40) in an intervall of ~100ms.
 		 * But to handle this correctly we had to imlemenent some
 		 * kind of timer which signals a 'key up' event if no
-		 * keyrepeat signal is recieved for lets say 200ms.
+		 * keyrepeat signal is received for lets say 200ms.
 		 * this should/could be added later ...
 		 * for now lets report each signal as a key down and up*/
 		dprintk("%s:rc signal:%d\n", __func__, buffer[4]);
diff -druN linux-libre-2.6.38-gnu/drivers/media/Kconfig linux-libre-2.6.39-gnu/drivers/media/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,19 @@
 comment "Multimedia core support"
 
 #
+# Media controller
+#
+
+config MEDIA_CONTROLLER
+	bool "Media Controller API (EXPERIMENTAL)"
+	depends on EXPERIMENTAL
+	---help---
+	  Enable the media controller API used to query media devices internal
+	  topology and configure it dynamically.
+
+	  This API is mostly used by camera interfaces in embedded platforms.
+
+#
 # V4L core and enabled API's
 #
 
@@ -40,6 +53,15 @@
 	depends on (I2C || I2C=n) && VIDEO_DEV
 	default (I2C || I2C=n) && VIDEO_DEV
 
+config VIDEO_V4L2_SUBDEV_API
+	bool "V4L2 sub-device userspace API (EXPERIMENTAL)"
+	depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL
+	---help---
+	  Enables the V4L2 sub-device pad-level userspace API used to configure
+	  video format, size and frame rate between hardware blocks.
+
+	  This API is mostly used by camera interfaces in embedded platforms.
+
 #
 # DVB Core
 #
diff -druN linux-libre-2.6.38-gnu/drivers/media/Makefile linux-libre-2.6.39-gnu/drivers/media/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,12 @@
 # Makefile for the kernel multimedia device drivers.
 #
 
+media-objs	:= media-device.o media-devnode.o media-entity.o
+
+ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
+  obj-$(CONFIG_MEDIA_SUPPORT) += media.o
+endif
+
 obj-y += common/ rc/ video/
 
 obj-$(CONFIG_VIDEO_DEV) += radio/
diff -druN linux-libre-2.6.38-gnu/drivers/media/media-device.c linux-libre-2.6.39-gnu/drivers/media/media-device.c
--- linux-libre-2.6.38-gnu/drivers/media/media-device.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/media-device.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,382 @@
+/*
+ * Media device
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/types.h>
+#include <linux/ioctl.h>
+#include <linux/media.h>
+
+#include <media/media-device.h>
+#include <media/media-devnode.h>
+#include <media/media-entity.h>
+
+/* -----------------------------------------------------------------------------
+ * Userspace API
+ */
+
+static int media_device_open(struct file *filp)
+{
+	return 0;
+}
+
+static int media_device_close(struct file *filp)
+{
+	return 0;
+}
+
+static int media_device_get_info(struct media_device *dev,
+				 struct media_device_info __user *__info)
+{
+	struct media_device_info info;
+
+	memset(&info, 0, sizeof(info));
+
+	strlcpy(info.driver, dev->dev->driver->name, sizeof(info.driver));
+	strlcpy(info.model, dev->model, sizeof(info.model));
+	strlcpy(info.serial, dev->serial, sizeof(info.serial));
+	strlcpy(info.bus_info, dev->bus_info, sizeof(info.bus_info));
+
+	info.media_version = MEDIA_API_VERSION;
+	info.hw_revision = dev->hw_revision;
+	info.driver_version = dev->driver_version;
+
+	return copy_to_user(__info, &info, sizeof(*__info));
+}
+
+static struct media_entity *find_entity(struct media_device *mdev, u32 id)
+{
+	struct media_entity *entity;
+	int next = id & MEDIA_ENT_ID_FLAG_NEXT;
+
+	id &= ~MEDIA_ENT_ID_FLAG_NEXT;
+
+	spin_lock(&mdev->lock);
+
+	media_device_for_each_entity(entity, mdev) {
+		if ((entity->id == id && !next) ||
+		    (entity->id > id && next)) {
+			spin_unlock(&mdev->lock);
+			return entity;
+		}
+	}
+
+	spin_unlock(&mdev->lock);
+
+	return NULL;
+}
+
+static long media_device_enum_entities(struct media_device *mdev,
+				       struct media_entity_desc __user *uent)
+{
+	struct media_entity *ent;
+	struct media_entity_desc u_ent;
+
+	if (copy_from_user(&u_ent.id, &uent->id, sizeof(u_ent.id)))
+		return -EFAULT;
+
+	ent = find_entity(mdev, u_ent.id);
+
+	if (ent == NULL)
+		return -EINVAL;
+
+	u_ent.id = ent->id;
+	u_ent.name[0] = '\0';
+	if (ent->name)
+		strlcpy(u_ent.name, ent->name, sizeof(u_ent.name));
+	u_ent.type = ent->type;
+	u_ent.revision = ent->revision;
+	u_ent.flags = ent->flags;
+	u_ent.group_id = ent->group_id;
+	u_ent.pads = ent->num_pads;
+	u_ent.links = ent->num_links - ent->num_backlinks;
+	u_ent.v4l.major = ent->v4l.major;
+	u_ent.v4l.minor = ent->v4l.minor;
+	if (copy_to_user(uent, &u_ent, sizeof(u_ent)))
+		return -EFAULT;
+	return 0;
+}
+
+static void media_device_kpad_to_upad(const struct media_pad *kpad,
+				      struct media_pad_desc *upad)
+{
+	upad->entity = kpad->entity->id;
+	upad->index = kpad->index;
+	upad->flags = kpad->flags;
+}
+
+static long media_device_enum_links(struct media_device *mdev,
+				    struct media_links_enum __user *ulinks)
+{
+	struct media_entity *entity;
+	struct media_links_enum links;
+
+	if (copy_from_user(&links, ulinks, sizeof(links)))
+		return -EFAULT;
+
+	entity = find_entity(mdev, links.entity);
+	if (entity == NULL)
+		return -EINVAL;
+
+	if (links.pads) {
+		unsigned int p;
+
+		for (p = 0; p < entity->num_pads; p++) {
+			struct media_pad_desc pad;
+			media_device_kpad_to_upad(&entity->pads[p], &pad);
+			if (copy_to_user(&links.pads[p], &pad, sizeof(pad)))
+				return -EFAULT;
+		}
+	}
+
+	if (links.links) {
+		struct media_link_desc __user *ulink;
+		unsigned int l;
+
+		for (l = 0, ulink = links.links; l < entity->num_links; l++) {
+			struct media_link_desc link;
+
+			/* Ignore backlinks. */
+			if (entity->links[l].source->entity != entity)
+				continue;
+
+			media_device_kpad_to_upad(entity->links[l].source,
+						  &link.source);
+			media_device_kpad_to_upad(entity->links[l].sink,
+						  &link.sink);
+			link.flags = entity->links[l].flags;
+			if (copy_to_user(ulink, &link, sizeof(*ulink)))
+				return -EFAULT;
+			ulink++;
+		}
+	}
+	if (copy_to_user(ulinks, &links, sizeof(*ulinks)))
+		return -EFAULT;
+	return 0;
+}
+
+static long media_device_setup_link(struct media_device *mdev,
+				    struct media_link_desc __user *_ulink)
+{
+	struct media_link *link = NULL;
+	struct media_link_desc ulink;
+	struct media_entity *source;
+	struct media_entity *sink;
+	int ret;
+
+	if (copy_from_user(&ulink, _ulink, sizeof(ulink)))
+		return -EFAULT;
+
+	/* Find the source and sink entities and link.
+	 */
+	source = find_entity(mdev, ulink.source.entity);
+	sink = find_entity(mdev, ulink.sink.entity);
+
+	if (source == NULL || sink == NULL)
+		return -EINVAL;
+
+	if (ulink.source.index >= source->num_pads ||
+	    ulink.sink.index >= sink->num_pads)
+		return -EINVAL;
+
+	link = media_entity_find_link(&source->pads[ulink.source.index],
+				      &sink->pads[ulink.sink.index]);
+	if (link == NULL)
+		return -EINVAL;
+
+	/* Setup the link on both entities. */
+	ret = __media_entity_setup_link(link, ulink.flags);
+
+	if (copy_to_user(_ulink, &ulink, sizeof(ulink)))
+		return -EFAULT;
+
+	return ret;
+}
+
+static long media_device_ioctl(struct file *filp, unsigned int cmd,
+			       unsigned long arg)
+{
+	struct media_devnode *devnode = media_devnode_data(filp);
+	struct media_device *dev = to_media_device(devnode);
+	long ret;
+
+	switch (cmd) {
+	case MEDIA_IOC_DEVICE_INFO:
+		ret = media_device_get_info(dev,
+				(struct media_device_info __user *)arg);
+		break;
+
+	case MEDIA_IOC_ENUM_ENTITIES:
+		ret = media_device_enum_entities(dev,
+				(struct media_entity_desc __user *)arg);
+		break;
+
+	case MEDIA_IOC_ENUM_LINKS:
+		mutex_lock(&dev->graph_mutex);
+		ret = media_device_enum_links(dev,
+				(struct media_links_enum __user *)arg);
+		mutex_unlock(&dev->graph_mutex);
+		break;
+
+	case MEDIA_IOC_SETUP_LINK:
+		mutex_lock(&dev->graph_mutex);
+		ret = media_device_setup_link(dev,
+				(struct media_link_desc __user *)arg);
+		mutex_unlock(&dev->graph_mutex);
+		break;
+
+	default:
+		ret = -ENOIOCTLCMD;
+	}
+
+	return ret;
+}
+
+static const struct media_file_operations media_device_fops = {
+	.owner = THIS_MODULE,
+	.open = media_device_open,
+	.ioctl = media_device_ioctl,
+	.release = media_device_close,
+};
+
+/* -----------------------------------------------------------------------------
+ * sysfs
+ */
+
+static ssize_t show_model(struct device *cd,
+			  struct device_attribute *attr, char *buf)
+{
+	struct media_device *mdev = to_media_device(to_media_devnode(cd));
+
+	return sprintf(buf, "%.*s\n", (int)sizeof(mdev->model), mdev->model);
+}
+
+static DEVICE_ATTR(model, S_IRUGO, show_model, NULL);
+
+/* -----------------------------------------------------------------------------
+ * Registration/unregistration
+ */
+
+static void media_device_release(struct media_devnode *mdev)
+{
+}
+
+/**
+ * media_device_register - register a media device
+ * @mdev:	The media device
+ *
+ * The caller is responsible for initializing the media device before
+ * registration. The following fields must be set:
+ *
+ * - dev must point to the parent device
+ * - model must be filled with the device model name
+ */
+int __must_check media_device_register(struct media_device *mdev)
+{
+	int ret;
+
+	if (WARN_ON(mdev->dev == NULL || mdev->model[0] == 0))
+		return -EINVAL;
+
+	mdev->entity_id = 1;
+	INIT_LIST_HEAD(&mdev->entities);
+	spin_lock_init(&mdev->lock);
+	mutex_init(&mdev->graph_mutex);
+
+	/* Register the device node. */
+	mdev->devnode.fops = &media_device_fops;
+	mdev->devnode.parent = mdev->dev;
+	mdev->devnode.release = media_device_release;
+	ret = media_devnode_register(&mdev->devnode);
+	if (ret < 0)
+		return ret;
+
+	ret = device_create_file(&mdev->devnode.dev, &dev_attr_model);
+	if (ret < 0) {
+		media_devnode_unregister(&mdev->devnode);
+		return ret;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_device_register);
+
+/**
+ * media_device_unregister - unregister a media device
+ * @mdev:	The media device
+ *
+ */
+void media_device_unregister(struct media_device *mdev)
+{
+	struct media_entity *entity;
+	struct media_entity *next;
+
+	list_for_each_entry_safe(entity, next, &mdev->entities, list)
+		media_device_unregister_entity(entity);
+
+	device_remove_file(&mdev->devnode.dev, &dev_attr_model);
+	media_devnode_unregister(&mdev->devnode);
+}
+EXPORT_SYMBOL_GPL(media_device_unregister);
+
+/**
+ * media_device_register_entity - Register an entity with a media device
+ * @mdev:	The media device
+ * @entity:	The entity
+ */
+int __must_check media_device_register_entity(struct media_device *mdev,
+					      struct media_entity *entity)
+{
+	/* Warn if we apparently re-register an entity */
+	WARN_ON(entity->parent != NULL);
+	entity->parent = mdev;
+
+	spin_lock(&mdev->lock);
+	if (entity->id == 0)
+		entity->id = mdev->entity_id++;
+	else
+		mdev->entity_id = max(entity->id + 1, mdev->entity_id);
+	list_add_tail(&entity->list, &mdev->entities);
+	spin_unlock(&mdev->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_device_register_entity);
+
+/**
+ * media_device_unregister_entity - Unregister an entity
+ * @entity:	The entity
+ *
+ * If the entity has never been registered this function will return
+ * immediately.
+ */
+void media_device_unregister_entity(struct media_entity *entity)
+{
+	struct media_device *mdev = entity->parent;
+
+	if (mdev == NULL)
+		return;
+
+	spin_lock(&mdev->lock);
+	list_del(&entity->list);
+	spin_unlock(&mdev->lock);
+	entity->parent = NULL;
+}
+EXPORT_SYMBOL_GPL(media_device_unregister_entity);
diff -druN linux-libre-2.6.38-gnu/drivers/media/media-devnode.c linux-libre-2.6.39-gnu/drivers/media/media-devnode.c
--- linux-libre-2.6.38-gnu/drivers/media/media-devnode.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/media-devnode.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,320 @@
+/*
+ * Media device node
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Based on drivers/media/video/v4l2_dev.c code authored by
+ *	Mauro Carvalho Chehab <mchehab@infradead.org> (version 2)
+ *	Alan Cox, <alan@lxorguk.ukuu.org.uk> (version 1)
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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
+ *
+ * --
+ *
+ * Generic media device node infrastructure to register and unregister
+ * character devices using a dynamic major number and proper reference
+ * counting.
+ */
+
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/kmod.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/uaccess.h>
+#include <asm/system.h>
+
+#include <media/media-devnode.h>
+
+#define MEDIA_NUM_DEVICES	256
+#define MEDIA_NAME		"media"
+
+static dev_t media_dev_t;
+
+/*
+ *	Active devices
+ */
+static DEFINE_MUTEX(media_devnode_lock);
+static DECLARE_BITMAP(media_devnode_nums, MEDIA_NUM_DEVICES);
+
+/* Called when the last user of the media device exits. */
+static void media_devnode_release(struct device *cd)
+{
+	struct media_devnode *mdev = to_media_devnode(cd);
+
+	mutex_lock(&media_devnode_lock);
+
+	/* Delete the cdev on this minor as well */
+	cdev_del(&mdev->cdev);
+
+	/* Mark device node number as free */
+	clear_bit(mdev->minor, media_devnode_nums);
+
+	mutex_unlock(&media_devnode_lock);
+
+	/* Release media_devnode and perform other cleanups as needed. */
+	if (mdev->release)
+		mdev->release(mdev);
+}
+
+static struct bus_type media_bus_type = {
+	.name = MEDIA_NAME,
+};
+
+static ssize_t media_read(struct file *filp, char __user *buf,
+		size_t sz, loff_t *off)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+
+	if (!mdev->fops->read)
+		return -EINVAL;
+	if (!media_devnode_is_registered(mdev))
+		return -EIO;
+	return mdev->fops->read(filp, buf, sz, off);
+}
+
+static ssize_t media_write(struct file *filp, const char __user *buf,
+		size_t sz, loff_t *off)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+
+	if (!mdev->fops->write)
+		return -EINVAL;
+	if (!media_devnode_is_registered(mdev))
+		return -EIO;
+	return mdev->fops->write(filp, buf, sz, off);
+}
+
+static unsigned int media_poll(struct file *filp,
+			       struct poll_table_struct *poll)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+
+	if (!media_devnode_is_registered(mdev))
+		return POLLERR | POLLHUP;
+	if (!mdev->fops->poll)
+		return DEFAULT_POLLMASK;
+	return mdev->fops->poll(filp, poll);
+}
+
+static long media_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+
+	if (!mdev->fops->ioctl)
+		return -ENOTTY;
+
+	if (!media_devnode_is_registered(mdev))
+		return -EIO;
+
+	return mdev->fops->ioctl(filp, cmd, arg);
+}
+
+/* Override for the open function */
+static int media_open(struct inode *inode, struct file *filp)
+{
+	struct media_devnode *mdev;
+	int ret;
+
+	/* Check if the media device is available. This needs to be done with
+	 * the media_devnode_lock held to prevent an open/unregister race:
+	 * without the lock, the device could be unregistered and freed between
+	 * the media_devnode_is_registered() and get_device() calls, leading to
+	 * a crash.
+	 */
+	mutex_lock(&media_devnode_lock);
+	mdev = container_of(inode->i_cdev, struct media_devnode, cdev);
+	/* return ENXIO if the media device has been removed
+	   already or if it is not registered anymore. */
+	if (!media_devnode_is_registered(mdev)) {
+		mutex_unlock(&media_devnode_lock);
+		return -ENXIO;
+	}
+	/* and increase the device refcount */
+	get_device(&mdev->dev);
+	mutex_unlock(&media_devnode_lock);
+
+	filp->private_data = mdev;
+
+	if (mdev->fops->open) {
+		ret = mdev->fops->open(filp);
+		if (ret) {
+			put_device(&mdev->dev);
+			return ret;
+		}
+	}
+
+	return 0;
+}
+
+/* Override for the release function */
+static int media_release(struct inode *inode, struct file *filp)
+{
+	struct media_devnode *mdev = media_devnode_data(filp);
+	int ret = 0;
+
+	if (mdev->fops->release)
+		mdev->fops->release(filp);
+
+	/* decrease the refcount unconditionally since the release()
+	   return value is ignored. */
+	put_device(&mdev->dev);
+	filp->private_data = NULL;
+	return ret;
+}
+
+static const struct file_operations media_devnode_fops = {
+	.owner = THIS_MODULE,
+	.read = media_read,
+	.write = media_write,
+	.open = media_open,
+	.unlocked_ioctl = media_ioctl,
+	.release = media_release,
+	.poll = media_poll,
+	.llseek = no_llseek,
+};
+
+/**
+ * media_devnode_register - register a media device node
+ * @mdev: media device node structure we want to register
+ *
+ * The registration code assigns minor numbers and registers the new device node
+ * with the kernel. An error is returned if no free minor number can be found,
+ * or if the registration of the device node fails.
+ *
+ * Zero is returned on success.
+ *
+ * Note that if the media_devnode_register call fails, the release() callback of
+ * the media_devnode structure is *not* called, so the caller is responsible for
+ * freeing any data.
+ */
+int __must_check media_devnode_register(struct media_devnode *mdev)
+{
+	int minor;
+	int ret;
+
+	/* Part 1: Find a free minor number */
+	mutex_lock(&media_devnode_lock);
+	minor = find_next_zero_bit(media_devnode_nums, 0, MEDIA_NUM_DEVICES);
+	if (minor == MEDIA_NUM_DEVICES) {
+		mutex_unlock(&media_devnode_lock);
+		printk(KERN_ERR "could not get a free minor\n");
+		return -ENFILE;
+	}
+
+	set_bit(mdev->minor, media_devnode_nums);
+	mutex_unlock(&media_devnode_lock);
+
+	mdev->minor = minor;
+
+	/* Part 2: Initialize and register the character device */
+	cdev_init(&mdev->cdev, &media_devnode_fops);
+	mdev->cdev.owner = mdev->fops->owner;
+
+	ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: cdev_add failed\n", __func__);
+		goto error;
+	}
+
+	/* Part 3: Register the media device */
+	mdev->dev.bus = &media_bus_type;
+	mdev->dev.devt = MKDEV(MAJOR(media_dev_t), mdev->minor);
+	mdev->dev.release = media_devnode_release;
+	if (mdev->parent)
+		mdev->dev.parent = mdev->parent;
+	dev_set_name(&mdev->dev, "media%d", mdev->minor);
+	ret = device_register(&mdev->dev);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: device_register failed\n", __func__);
+		goto error;
+	}
+
+	/* Part 4: Activate this minor. The char device can now be used. */
+	set_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+
+	return 0;
+
+error:
+	cdev_del(&mdev->cdev);
+	clear_bit(mdev->minor, media_devnode_nums);
+	return ret;
+}
+
+/**
+ * media_devnode_unregister - unregister a media device node
+ * @mdev: the device node to unregister
+ *
+ * This unregisters the passed device. Future open calls will be met with
+ * errors.
+ *
+ * This function can safely be called if the device node has never been
+ * registered or has already been unregistered.
+ */
+void media_devnode_unregister(struct media_devnode *mdev)
+{
+	/* Check if mdev was ever registered at all */
+	if (!media_devnode_is_registered(mdev))
+		return;
+
+	mutex_lock(&media_devnode_lock);
+	clear_bit(MEDIA_FLAG_REGISTERED, &mdev->flags);
+	mutex_unlock(&media_devnode_lock);
+	device_unregister(&mdev->dev);
+}
+
+/*
+ *	Initialise media for linux
+ */
+static int __init media_devnode_init(void)
+{
+	int ret;
+
+	printk(KERN_INFO "Linux media interface: v0.10\n");
+	ret = alloc_chrdev_region(&media_dev_t, 0, MEDIA_NUM_DEVICES,
+				  MEDIA_NAME);
+	if (ret < 0) {
+		printk(KERN_WARNING "media: unable to allocate major\n");
+		return ret;
+	}
+
+	ret = bus_register(&media_bus_type);
+	if (ret < 0) {
+		unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
+		printk(KERN_WARNING "media: bus_register failed\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static void __exit media_devnode_exit(void)
+{
+	bus_unregister(&media_bus_type);
+	unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
+}
+
+module_init(media_devnode_init)
+module_exit(media_devnode_exit)
+
+MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
+MODULE_DESCRIPTION("Device node registration for media drivers");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/media-entity.c linux-libre-2.6.39-gnu/drivers/media/media-entity.c
--- linux-libre-2.6.38-gnu/drivers/media/media-entity.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/media-entity.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,540 @@
+/*
+ * Media entity
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/slab.h>
+#include <media/media-entity.h>
+#include <media/media-device.h>
+
+/**
+ * media_entity_init - Initialize a media entity
+ *
+ * @num_pads: Total number of sink and source pads.
+ * @extra_links: Initial estimate of the number of extra links.
+ * @pads: Array of 'num_pads' pads.
+ *
+ * The total number of pads is an intrinsic property of entities known by the
+ * entity driver, while the total number of links depends on hardware design
+ * and is an extrinsic property unknown to the entity driver. However, in most
+ * use cases the entity driver can guess the number of links which can safely
+ * be assumed to be equal to or larger than the number of pads.
+ *
+ * For those reasons the links array can be preallocated based on the entity
+ * driver guess and will be reallocated later if extra links need to be
+ * created.
+ *
+ * This function allocates a links array with enough space to hold at least
+ * 'num_pads' + 'extra_links' elements. The media_entity::max_links field will
+ * be set to the number of allocated elements.
+ *
+ * The pads array is managed by the entity driver and passed to
+ * media_entity_init() where its pointer will be stored in the entity structure.
+ */
+int
+media_entity_init(struct media_entity *entity, u16 num_pads,
+		  struct media_pad *pads, u16 extra_links)
+{
+	struct media_link *links;
+	unsigned int max_links = num_pads + extra_links;
+	unsigned int i;
+
+	links = kzalloc(max_links * sizeof(links[0]), GFP_KERNEL);
+	if (links == NULL)
+		return -ENOMEM;
+
+	entity->group_id = 0;
+	entity->max_links = max_links;
+	entity->num_links = 0;
+	entity->num_backlinks = 0;
+	entity->num_pads = num_pads;
+	entity->pads = pads;
+	entity->links = links;
+
+	for (i = 0; i < num_pads; i++) {
+		pads[i].entity = entity;
+		pads[i].index = i;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_entity_init);
+
+void
+media_entity_cleanup(struct media_entity *entity)
+{
+	kfree(entity->links);
+}
+EXPORT_SYMBOL_GPL(media_entity_cleanup);
+
+/* -----------------------------------------------------------------------------
+ * Graph traversal
+ */
+
+static struct media_entity *
+media_entity_other(struct media_entity *entity, struct media_link *link)
+{
+	if (link->source->entity == entity)
+		return link->sink->entity;
+	else
+		return link->source->entity;
+}
+
+/* push an entity to traversal stack */
+static void stack_push(struct media_entity_graph *graph,
+		       struct media_entity *entity)
+{
+	if (graph->top == MEDIA_ENTITY_ENUM_MAX_DEPTH - 1) {
+		WARN_ON(1);
+		return;
+	}
+	graph->top++;
+	graph->stack[graph->top].link = 0;
+	graph->stack[graph->top].entity = entity;
+}
+
+static struct media_entity *stack_pop(struct media_entity_graph *graph)
+{
+	struct media_entity *entity;
+
+	entity = graph->stack[graph->top].entity;
+	graph->top--;
+
+	return entity;
+}
+
+#define stack_peek(en)	((en)->stack[(en)->top - 1].entity)
+#define link_top(en)	((en)->stack[(en)->top].link)
+#define stack_top(en)	((en)->stack[(en)->top].entity)
+
+/**
+ * media_entity_graph_walk_start - Start walking the media graph at a given entity
+ * @graph: Media graph structure that will be used to walk the graph
+ * @entity: Starting entity
+ *
+ * This function initializes the graph traversal structure to walk the entities
+ * graph starting at the given entity. The traversal structure must not be
+ * modified by the caller during graph traversal. When done the structure can
+ * safely be freed.
+ */
+void media_entity_graph_walk_start(struct media_entity_graph *graph,
+				   struct media_entity *entity)
+{
+	graph->top = 0;
+	graph->stack[graph->top].entity = NULL;
+	stack_push(graph, entity);
+}
+EXPORT_SYMBOL_GPL(media_entity_graph_walk_start);
+
+/**
+ * media_entity_graph_walk_next - Get the next entity in the graph
+ * @graph: Media graph structure
+ *
+ * Perform a depth-first traversal of the given media entities graph.
+ *
+ * The graph structure must have been previously initialized with a call to
+ * media_entity_graph_walk_start().
+ *
+ * Return the next entity in the graph or NULL if the whole graph have been
+ * traversed.
+ */
+struct media_entity *
+media_entity_graph_walk_next(struct media_entity_graph *graph)
+{
+	if (stack_top(graph) == NULL)
+		return NULL;
+
+	/*
+	 * Depth first search. Push entity to stack and continue from
+	 * top of the stack until no more entities on the level can be
+	 * found.
+	 */
+	while (link_top(graph) < stack_top(graph)->num_links) {
+		struct media_entity *entity = stack_top(graph);
+		struct media_link *link = &entity->links[link_top(graph)];
+		struct media_entity *next;
+
+		/* The link is not enabled so we do not follow. */
+		if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
+			link_top(graph)++;
+			continue;
+		}
+
+		/* Get the entity in the other end of the link . */
+		next = media_entity_other(entity, link);
+
+		/* Was it the entity we came here from? */
+		if (next == stack_peek(graph)) {
+			link_top(graph)++;
+			continue;
+		}
+
+		/* Push the new entity to stack and start over. */
+		link_top(graph)++;
+		stack_push(graph, next);
+	}
+
+	return stack_pop(graph);
+}
+EXPORT_SYMBOL_GPL(media_entity_graph_walk_next);
+
+/* -----------------------------------------------------------------------------
+ * Pipeline management
+ */
+
+/**
+ * media_entity_pipeline_start - Mark a pipeline as streaming
+ * @entity: Starting entity
+ * @pipe: Media pipeline to be assigned to all entities in the pipeline.
+ *
+ * Mark all entities connected to a given entity through enabled links, either
+ * directly or indirectly, as streaming. The given pipeline object is assigned to
+ * every entity in the pipeline and stored in the media_entity pipe field.
+ *
+ * Calls to this function can be nested, in which case the same number of
+ * media_entity_pipeline_stop() calls will be required to stop streaming. The
+ * pipeline pointer must be identical for all nested calls to
+ * media_entity_pipeline_start().
+ */
+void media_entity_pipeline_start(struct media_entity *entity,
+				 struct media_pipeline *pipe)
+{
+	struct media_device *mdev = entity->parent;
+	struct media_entity_graph graph;
+
+	mutex_lock(&mdev->graph_mutex);
+
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+		entity->stream_count++;
+		WARN_ON(entity->pipe && entity->pipe != pipe);
+		entity->pipe = pipe;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+}
+EXPORT_SYMBOL_GPL(media_entity_pipeline_start);
+
+/**
+ * media_entity_pipeline_stop - Mark a pipeline as not streaming
+ * @entity: Starting entity
+ *
+ * Mark all entities connected to a given entity through enabled links, either
+ * directly or indirectly, as not streaming. The media_entity pipe field is
+ * reset to NULL.
+ *
+ * If multiple calls to media_entity_pipeline_start() have been made, the same
+ * number of calls to this function are required to mark the pipeline as not
+ * streaming.
+ */
+void media_entity_pipeline_stop(struct media_entity *entity)
+{
+	struct media_device *mdev = entity->parent;
+	struct media_entity_graph graph;
+
+	mutex_lock(&mdev->graph_mutex);
+
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+		entity->stream_count--;
+		if (entity->stream_count == 0)
+			entity->pipe = NULL;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+}
+EXPORT_SYMBOL_GPL(media_entity_pipeline_stop);
+
+/* -----------------------------------------------------------------------------
+ * Module use count
+ */
+
+/*
+ * media_entity_get - Get a reference to the parent module
+ * @entity: The entity
+ *
+ * Get a reference to the parent media device module.
+ *
+ * The function will return immediately if @entity is NULL.
+ *
+ * Return a pointer to the entity on success or NULL on failure.
+ */
+struct media_entity *media_entity_get(struct media_entity *entity)
+{
+	if (entity == NULL)
+		return NULL;
+
+	if (entity->parent->dev &&
+	    !try_module_get(entity->parent->dev->driver->owner))
+		return NULL;
+
+	return entity;
+}
+EXPORT_SYMBOL_GPL(media_entity_get);
+
+/*
+ * media_entity_put - Release the reference to the parent module
+ * @entity: The entity
+ *
+ * Release the reference count acquired by media_entity_get().
+ *
+ * The function will return immediately if @entity is NULL.
+ */
+void media_entity_put(struct media_entity *entity)
+{
+	if (entity == NULL)
+		return;
+
+	if (entity->parent->dev)
+		module_put(entity->parent->dev->driver->owner);
+}
+EXPORT_SYMBOL_GPL(media_entity_put);
+
+/* -----------------------------------------------------------------------------
+ * Links management
+ */
+
+static struct media_link *media_entity_add_link(struct media_entity *entity)
+{
+	if (entity->num_links >= entity->max_links) {
+		struct media_link *links = entity->links;
+		unsigned int max_links = entity->max_links + 2;
+		unsigned int i;
+
+		links = krealloc(links, max_links * sizeof(*links), GFP_KERNEL);
+		if (links == NULL)
+			return NULL;
+
+		for (i = 0; i < entity->num_links; i++)
+			links[i].reverse->reverse = &links[i];
+
+		entity->max_links = max_links;
+		entity->links = links;
+	}
+
+	return &entity->links[entity->num_links++];
+}
+
+int
+media_entity_create_link(struct media_entity *source, u16 source_pad,
+			 struct media_entity *sink, u16 sink_pad, u32 flags)
+{
+	struct media_link *link;
+	struct media_link *backlink;
+
+	BUG_ON(source == NULL || sink == NULL);
+	BUG_ON(source_pad >= source->num_pads);
+	BUG_ON(sink_pad >= sink->num_pads);
+
+	link = media_entity_add_link(source);
+	if (link == NULL)
+		return -ENOMEM;
+
+	link->source = &source->pads[source_pad];
+	link->sink = &sink->pads[sink_pad];
+	link->flags = flags;
+
+	/* Create the backlink. Backlinks are used to help graph traversal and
+	 * are not reported to userspace.
+	 */
+	backlink = media_entity_add_link(sink);
+	if (backlink == NULL) {
+		source->num_links--;
+		return -ENOMEM;
+	}
+
+	backlink->source = &source->pads[source_pad];
+	backlink->sink = &sink->pads[sink_pad];
+	backlink->flags = flags;
+
+	link->reverse = backlink;
+	backlink->reverse = link;
+
+	sink->num_backlinks++;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(media_entity_create_link);
+
+static int __media_entity_setup_link_notify(struct media_link *link, u32 flags)
+{
+	int ret;
+
+	/* Notify both entities. */
+	ret = media_entity_call(link->source->entity, link_setup,
+				link->source, link->sink, flags);
+	if (ret < 0 && ret != -ENOIOCTLCMD)
+		return ret;
+
+	ret = media_entity_call(link->sink->entity, link_setup,
+				link->sink, link->source, flags);
+	if (ret < 0 && ret != -ENOIOCTLCMD) {
+		media_entity_call(link->source->entity, link_setup,
+				  link->source, link->sink, link->flags);
+		return ret;
+	}
+
+	link->flags = flags;
+	link->reverse->flags = link->flags;
+
+	return 0;
+}
+
+/**
+ * __media_entity_setup_link - Configure a media link
+ * @link: The link being configured
+ * @flags: Link configuration flags
+ *
+ * The bulk of link setup is handled by the two entities connected through the
+ * link. This function notifies both entities of the link configuration change.
+ *
+ * If the link is immutable or if the current and new configuration are
+ * identical, return immediately.
+ *
+ * The user is expected to hold link->source->parent->mutex. If not,
+ * media_entity_setup_link() should be used instead.
+ */
+int __media_entity_setup_link(struct media_link *link, u32 flags)
+{
+	const u32 mask = MEDIA_LNK_FL_ENABLED;
+	struct media_device *mdev;
+	struct media_entity *source, *sink;
+	int ret = -EBUSY;
+
+	if (link == NULL)
+		return -EINVAL;
+
+	/* The non-modifiable link flags must not be modified. */
+	if ((link->flags & ~mask) != (flags & ~mask))
+		return -EINVAL;
+
+	if (link->flags & MEDIA_LNK_FL_IMMUTABLE)
+		return link->flags == flags ? 0 : -EINVAL;
+
+	if (link->flags == flags)
+		return 0;
+
+	source = link->source->entity;
+	sink = link->sink->entity;
+
+	if (!(link->flags & MEDIA_LNK_FL_DYNAMIC) &&
+	    (source->stream_count || sink->stream_count))
+		return -EBUSY;
+
+	mdev = source->parent;
+
+	if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify) {
+		ret = mdev->link_notify(link->source, link->sink,
+					MEDIA_LNK_FL_ENABLED);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = __media_entity_setup_link_notify(link, flags);
+	if (ret < 0)
+		goto err;
+
+	if (!(flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
+		mdev->link_notify(link->source, link->sink, 0);
+
+	return 0;
+
+err:
+	if ((flags & MEDIA_LNK_FL_ENABLED) && mdev->link_notify)
+		mdev->link_notify(link->source, link->sink, 0);
+
+	return ret;
+}
+
+int media_entity_setup_link(struct media_link *link, u32 flags)
+{
+	int ret;
+
+	mutex_lock(&link->source->entity->parent->graph_mutex);
+	ret = __media_entity_setup_link(link, flags);
+	mutex_unlock(&link->source->entity->parent->graph_mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(media_entity_setup_link);
+
+/**
+ * media_entity_find_link - Find a link between two pads
+ * @source: Source pad
+ * @sink: Sink pad
+ *
+ * Return a pointer to the link between the two entities. If no such link
+ * exists, return NULL.
+ */
+struct media_link *
+media_entity_find_link(struct media_pad *source, struct media_pad *sink)
+{
+	struct media_link *link;
+	unsigned int i;
+
+	for (i = 0; i < source->entity->num_links; ++i) {
+		link = &source->entity->links[i];
+
+		if (link->source->entity == source->entity &&
+		    link->source->index == source->index &&
+		    link->sink->entity == sink->entity &&
+		    link->sink->index == sink->index)
+			return link;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL_GPL(media_entity_find_link);
+
+/**
+ * media_entity_remote_source - Find the source pad at the remote end of a link
+ * @pad: Sink pad at the local end of the link
+ *
+ * Search for a remote source pad connected to the given sink pad by iterating
+ * over all links originating or terminating at that pad until an enabled link
+ * is found.
+ *
+ * Return a pointer to the pad at the remote end of the first found enabled
+ * link, or NULL if no enabled link has been found.
+ */
+struct media_pad *media_entity_remote_source(struct media_pad *pad)
+{
+	unsigned int i;
+
+	for (i = 0; i < pad->entity->num_links; i++) {
+		struct media_link *link = &pad->entity->links[i];
+
+		if (!(link->flags & MEDIA_LNK_FL_ENABLED))
+			continue;
+
+		if (link->source == pad)
+			return link->sink;
+
+		if (link->sink == pad)
+			return link->source;
+	}
+
+	return NULL;
+
+}
+EXPORT_SYMBOL_GPL(media_entity_remote_source);
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/dsbr100.c linux-libre-2.6.39-gnu/drivers/media/radio/dsbr100.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/dsbr100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/dsbr100.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,7 +129,7 @@
 #define STARTED	0
 #define STOPPED	1
 
-#define videodev_to_radio(d) container_of(d, struct dsbr100_device, videodev)
+#define v4l2_dev_to_radio(d) container_of(d, struct dsbr100_device, v4l2_dev)
 
 static int usb_dsbr100_probe(struct usb_interface *intf,
 			     const struct usb_device_id *id);
@@ -148,10 +148,9 @@
 	struct v4l2_device v4l2_dev;
 
 	u8 *transfer_buffer;
-	struct mutex lock;	/* buffer locking */
+	struct mutex v4l2_lock;
 	int curfreq;
 	int stereo;
-	int removed;
 	int status;
 };
 
@@ -182,8 +181,6 @@
 	int retval;
 	int request;
 
-	mutex_lock(&radio->lock);
-
 	retval = usb_control_msg(radio->usbdev,
 		usb_rcvctrlpipe(radio->usbdev, 0),
 		USB_REQ_GET_STATUS,
@@ -207,11 +204,9 @@
 	}
 
 	radio->status = STARTED;
-	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
 
 usb_control_msg_failed:
-	mutex_unlock(&radio->lock);
 	dev_err(&radio->usbdev->dev,
 		"%s - usb_control_msg returned %i, request %i\n",
 			__func__, retval, request);
@@ -225,8 +220,6 @@
 	int retval;
 	int request;
 
-	mutex_lock(&radio->lock);
-
 	retval = usb_control_msg(radio->usbdev,
 		usb_rcvctrlpipe(radio->usbdev, 0),
 		USB_REQ_GET_STATUS,
@@ -250,11 +243,9 @@
 	}
 
 	radio->status = STOPPED;
-	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
 
 usb_control_msg_failed:
-	mutex_unlock(&radio->lock);
 	dev_err(&radio->usbdev->dev,
 		"%s - usb_control_msg returned %i, request %i\n",
 			__func__, retval, request);
@@ -269,8 +260,6 @@
 	int request;
 	int freq = (radio->curfreq / 16 * 80) / 1000 + 856;
 
-	mutex_lock(&radio->lock);
-
 	retval = usb_control_msg(radio->usbdev,
 		usb_rcvctrlpipe(radio->usbdev, 0),
 		DSB100_TUNE,
@@ -306,12 +295,10 @@
 	}
 
 	radio->stereo = !((radio->transfer_buffer)[0] & 0x01);
-	mutex_unlock(&radio->lock);
 	return (radio->transfer_buffer)[0];
 
 usb_control_msg_failed:
 	radio->stereo = -1;
-	mutex_unlock(&radio->lock);
 	dev_err(&radio->usbdev->dev,
 		"%s - usb_control_msg returned %i, request %i\n",
 			__func__, retval, request);
@@ -324,8 +311,6 @@
 {
 	int retval;
 
-	mutex_lock(&radio->lock);
-
 	retval = usb_control_msg(radio->usbdev,
 		usb_rcvctrlpipe(radio->usbdev, 0),
 		USB_REQ_GET_STATUS,
@@ -340,33 +325,8 @@
 	} else {
 		radio->stereo = !(radio->transfer_buffer[0] & 0x01);
 	}
-
-	mutex_unlock(&radio->lock);
-}
-
-/* USB subsystem interface begins here */
-
-/*
- * Handle unplugging of the device.
- * We call video_unregister_device in any case.
- * The last function called in this procedure is
- * usb_dsbr100_video_device_release
- */
-static void usb_dsbr100_disconnect(struct usb_interface *intf)
-{
-	struct dsbr100_device *radio = usb_get_intfdata(intf);
-
-	usb_set_intfdata (intf, NULL);
-
-	mutex_lock(&radio->lock);
-	radio->removed = 1;
-	mutex_unlock(&radio->lock);
-
-	video_unregister_device(&radio->videodev);
-	v4l2_device_disconnect(&radio->v4l2_dev);
 }
 
-
 static int vidioc_querycap(struct file *file, void *priv,
 					struct v4l2_capability *v)
 {
@@ -385,10 +345,6 @@
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
-	/* safety check */
-	if (radio->removed)
-		return -EIO;
-
 	if (v->index > 0)
 		return -EINVAL;
 
@@ -410,16 +366,7 @@
 static int vidioc_s_tuner(struct file *file, void *priv,
 				struct v4l2_tuner *v)
 {
-	struct dsbr100_device *radio = video_drvdata(file);
-
-	/* safety check */
-	if (radio->removed)
-		return -EIO;
-
-	if (v->index > 0)
-		return -EINVAL;
-
-	return 0;
+	return v->index ? -EINVAL : 0;
 }
 
 static int vidioc_s_frequency(struct file *file, void *priv,
@@ -428,13 +375,7 @@
 	struct dsbr100_device *radio = video_drvdata(file);
 	int retval;
 
-	/* safety check */
-	if (radio->removed)
-		return -EIO;
-
-	mutex_lock(&radio->lock);
 	radio->curfreq = f->frequency;
-	mutex_unlock(&radio->lock);
 
 	retval = dsbr100_setfreq(radio);
 	if (retval < 0)
@@ -447,10 +388,6 @@
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
-	/* safety check */
-	if (radio->removed)
-		return -EIO;
-
 	f->type = V4L2_TUNER_RADIO;
 	f->frequency = radio->curfreq;
 	return 0;
@@ -472,10 +409,6 @@
 {
 	struct dsbr100_device *radio = video_drvdata(file);
 
-	/* safety check */
-	if (radio->removed)
-		return -EIO;
-
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		ctrl->value = radio->status;
@@ -490,10 +423,6 @@
 	struct dsbr100_device *radio = video_drvdata(file);
 	int retval;
 
-	/* safety check */
-	if (radio->removed)
-		return -EIO;
-
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
 		if (ctrl->value) {
@@ -535,25 +464,44 @@
 
 static int vidioc_s_input(struct file *filp, void *priv, unsigned int i)
 {
-	if (i != 0)
-		return -EINVAL;
-	return 0;
+	return i ? -EINVAL : 0;
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
 					struct v4l2_audio *a)
 {
-	if (a->index != 0)
-		return -EINVAL;
-	return 0;
+	return a->index ? -EINVAL : 0;
+}
+
+/* USB subsystem interface begins here */
+
+/*
+ * Handle unplugging of the device.
+ * We call video_unregister_device in any case.
+ * The last function called in this procedure is
+ * usb_dsbr100_video_device_release
+ */
+static void usb_dsbr100_disconnect(struct usb_interface *intf)
+{
+	struct dsbr100_device *radio = usb_get_intfdata(intf);
+
+	v4l2_device_get(&radio->v4l2_dev);
+	mutex_lock(&radio->v4l2_lock);
+	usb_set_intfdata(intf, NULL);
+	video_unregister_device(&radio->videodev);
+	v4l2_device_disconnect(&radio->v4l2_dev);
+	mutex_unlock(&radio->v4l2_lock);
+	v4l2_device_put(&radio->v4l2_dev);
 }
 
+
 /* 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;
 
+	mutex_lock(&radio->v4l2_lock);
 	if (radio->status == STARTED) {
 		retval = dsbr100_stop(radio);
 		if (retval < 0)
@@ -564,11 +512,9 @@
 		 * 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);
 	}
+	mutex_unlock(&radio->v4l2_lock);
 
 	dev_info(&intf->dev, "going into suspend..\n");
 
@@ -581,11 +527,13 @@
 	struct dsbr100_device *radio = usb_get_intfdata(intf);
 	int retval;
 
+	mutex_lock(&radio->v4l2_lock);
 	if (radio->status == STARTED) {
 		retval = dsbr100_start(radio);
 		if (retval < 0)
 			dev_warn(&intf->dev, "dsbr100_start failed\n");
 	}
+	mutex_unlock(&radio->v4l2_lock);
 
 	dev_info(&intf->dev, "coming out of suspend..\n");
 
@@ -593,9 +541,9 @@
 }
 
 /* free data structures */
-static void usb_dsbr100_video_device_release(struct video_device *videodev)
+static void usb_dsbr100_release(struct v4l2_device *v4l2_dev)
 {
-	struct dsbr100_device *radio = videodev_to_radio(videodev);
+	struct dsbr100_device *radio = v4l2_dev_to_radio(v4l2_dev);
 
 	v4l2_device_unregister(&radio->v4l2_dev);
 	kfree(radio->transfer_buffer);
@@ -605,7 +553,7 @@
 /* File system interface */
 static const struct v4l2_file_operations usb_dsbr100_fops = {
 	.owner		= THIS_MODULE,
-	.ioctl		= video_ioctl2,
+	.unlocked_ioctl	= video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops usb_dsbr100_ioctl_ops = {
@@ -644,6 +592,7 @@
 	}
 
 	v4l2_dev = &radio->v4l2_dev;
+	v4l2_dev->release = usb_dsbr100_release;
 
 	retval = v4l2_device_register(&intf->dev, v4l2_dev);
 	if (retval < 0) {
@@ -653,15 +602,14 @@
 		return retval;
 	}
 
+	mutex_init(&radio->v4l2_lock);
 	strlcpy(radio->videodev.name, v4l2_dev->name, sizeof(radio->videodev.name));
 	radio->videodev.v4l2_dev = v4l2_dev;
 	radio->videodev.fops = &usb_dsbr100_fops;
 	radio->videodev.ioctl_ops = &usb_dsbr100_ioctl_ops;
-	radio->videodev.release = usb_dsbr100_video_device_release;
-
-	mutex_init(&radio->lock);
+	radio->videodev.release = video_device_release_empty;
+	radio->videodev.lock = &radio->v4l2_lock;
 
-	radio->removed = 0;
 	radio->usbdev = interface_to_usbdev(intf);
 	radio->curfreq = FREQ_MIN * FREQ_MUL;
 	radio->status = STOPPED;
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/Kconfig linux-libre-2.6.39-gnu/drivers/media/radio/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/radio/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -441,6 +441,7 @@
 config RADIO_WL1273
 	tristate "Texas Instruments WL1273 I2C FM Radio"
 	depends on I2C && VIDEO_V4L2
+	select MFD_CORE
 	select MFD_WL1273_CORE
 	select FW_LOADER
 	---help---
@@ -454,4 +455,7 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called radio-wl1273.
 
+# TI's ST based wl128x FM radio
+source "drivers/media/radio/wl128x/Kconfig"
+
 endif # RADIO_ADAPTERS
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/Makefile linux-libre-2.6.39-gnu/drivers/media/radio/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/radio/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -26,5 +26,6 @@
 obj-$(CONFIG_RADIO_TEF6862) += tef6862.o
 obj-$(CONFIG_RADIO_TIMBERDALE) += radio-timb.o
 obj-$(CONFIG_RADIO_WL1273) += radio-wl1273.o
+obj-$(CONFIG_RADIO_WL128X) += wl128x/
 
 EXTRA_CFLAGS += -Isound
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/radio-mr800.c linux-libre-2.6.39-gnu/drivers/media/radio/radio-mr800.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/radio-mr800.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/radio-mr800.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 
 /*
  * Commands that device should understand
- * List isnt full and will be updated with implementation of new functions
+ * List isn't full and will be updated with implementation of new functions
  */
 #define AMRADIO_SET_FREQ	0xa4
 #define AMRADIO_SET_MUTE	0xab
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/radio-sf16fmr2.c linux-libre-2.6.39-gnu/drivers/media/radio/radio-sf16fmr2.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/radio-sf16fmr2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/radio-sf16fmr2.c	2011-05-19 00:06:34.000000000 -0400
@@ -170,7 +170,7 @@
 	return 0;
 }
 
-/* !!! not tested, in my card this does't work !!! */
+/* !!! not tested, in my card this doesn't work !!! */
 static int fmr2_setvolume(struct fmr2 *dev)
 {
 	int vol[16] = { 0x021, 0x084, 0x090, 0x104,
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/radio-si4713.c linux-libre-2.6.39-gnu/drivers/media/radio/radio-si4713.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/radio-si4713.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/radio-si4713.c	2011-05-19 00:06:34.000000000 -0400
@@ -224,7 +224,8 @@
 							s_frequency, vf);
 }
 
-static long radio_si4713_default(struct file *file, void *p, int cmd, void *arg)
+static long radio_si4713_default(struct file *file, void *p,
+				bool valid_prio, int cmd, void *arg)
 {
 	return v4l2_device_call_until_err(get_v4l2_dev(file), 0, core,
 							ioctl, cmd, arg);
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/radio-timb.c linux-libre-2.6.39-gnu/drivers/media/radio/radio-timb.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/radio-timb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/radio-timb.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/i2c.h>
@@ -148,7 +149,7 @@
 
 static int __devinit timbradio_probe(struct platform_device *pdev)
 {
-	struct timb_radio_platform_data *pdata = pdev->dev.platform_data;
+	struct timb_radio_platform_data *pdata = mfd_get_data(pdev);
 	struct timbradio *tr;
 	int err;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/radio-wl1273.c linux-libre-2.6.39-gnu/drivers/media/radio/radio-wl1273.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/radio-wl1273.c	2012-03-24 01:06:04.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/radio-wl1273.c	2012-03-24 03:29:43.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Driver for the Texas Instruments WL1273 FM radio.
  *
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
  * Author: Matti J. Aaltonen <matti.j.aaltonen@nokia.com>
  *
  * This program is free software; you can redistribute it and/or
@@ -67,7 +67,6 @@
 
 	/* RDS */
 	unsigned int rds_on;
-	struct delayed_work work;
 
 	wait_queue_head_t read_queue;
 	struct mutex lock; /* for serializing fm radio operations */
@@ -104,58 +103,6 @@
 module_param(rds_buf, uint, 0);
 MODULE_PARM_DESC(rds_buf, "Number of RDS buffer entries. Default = 100");
 
-static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
-{
-	struct i2c_client *client = core->client;
-	u8 b[2];
-	int r;
-
-	r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
-	if (r != 2) {
-		dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
-		return -EREMOTEIO;
-	}
-
-	*value = (u16)b[0] << 8 | b[1];
-
-	return 0;
-}
-
-static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
-{
-	struct i2c_client *client = core->client;
-	u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
-	int r;
-
-	r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
-	if (r) {
-		dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
-		return r;
-	}
-
-	return 0;
-}
-
-static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
-{
-	struct i2c_client *client = core->client;
-	struct i2c_msg msg;
-	int r;
-
-	msg.addr = client->addr;
-	msg.flags = 0;
-	msg.buf = data;
-	msg.len = len;
-
-	r = i2c_transfer(client->adapter, &msg, 1);
-	if (r != 1) {
-		dev_err(&client->dev, "%s: write error.\n", __func__);
-		return -EREMOTEIO;
-	}
-
-	return 0;
-}
-
 static int wl1273_fm_write_fw(struct wl1273_core *core,
 			      __u8 *fw, int len)
 {
@@ -188,94 +135,6 @@
 	return r;
 }
 
-/**
- * wl1273_fm_set_audio() -	Set audio mode.
- * @core:			A pointer to the device struct.
- * @new_mode:			The new audio mode.
- *
- * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
- */
-static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
-{
-	int r = 0;
-
-	if (core->mode == WL1273_MODE_OFF ||
-	    core->mode == WL1273_MODE_SUSPENDED)
-		return -EPERM;
-
-	if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
-		r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
-					WL1273_PCM_DEF_MODE);
-		if (r)
-			goto out;
-
-		r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
-					core->i2s_mode);
-		if (r)
-			goto out;
-
-		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
-					WL1273_AUDIO_ENABLE_I2S);
-		if (r)
-			goto out;
-
-	} else if (core->mode == WL1273_MODE_RX &&
-		   new_mode == WL1273_AUDIO_ANALOG) {
-		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
-					WL1273_AUDIO_ENABLE_ANALOG);
-		if (r)
-			goto out;
-
-	} else if (core->mode == WL1273_MODE_TX &&
-		   new_mode == WL1273_AUDIO_DIGITAL) {
-		r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
-					core->i2s_mode);
-		if (r)
-			goto out;
-
-		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
-					WL1273_AUDIO_IO_SET_I2S);
-		if (r)
-			goto out;
-
-	} else if (core->mode == WL1273_MODE_TX &&
-		   new_mode == WL1273_AUDIO_ANALOG) {
-		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
-					WL1273_AUDIO_IO_SET_ANALOG);
-		if (r)
-			goto out;
-	}
-
-	core->audio_mode = new_mode;
-out:
-	return r;
-}
-
-/**
- * wl1273_fm_set_volume() -	Set volume.
- * @core:			A pointer to the device struct.
- * @volume:			The new volume value.
- */
-static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
-{
-	u16 val;
-	int r;
-
-	if (volume > WL1273_MAX_VOLUME)
-		return -EINVAL;
-
-	if (core->volume == volume)
-		return 0;
-
-	val = volume;
-	r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val);
-	if (r)
-		return r;
-
-	core->volume = volume;
-	return 0;
-}
-
 #define WL1273_FIFO_HAS_DATA(status)	(1 << 5 & status)
 #define WL1273_RDS_CORRECTABLE_ERROR	(1 << 3)
 #define WL1273_RDS_UNCORRECTABLE_ERROR	(1 << 4)
@@ -306,7 +165,7 @@
 	if (core->mode != WL1273_MODE_RX)
 		return 0;
 
-	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 	if (r)
 		return r;
 
@@ -374,7 +233,7 @@
 	u16 flags;
 	int r;
 
-	r = wl1273_fm_read_reg(core, WL1273_FLAG_GET, &flags);
+	r = core->read(core, WL1273_FLAG_GET, &flags);
 	if (r)
 		goto out;
 
@@ -398,7 +257,7 @@
 	if (flags & WL1273_LEV_EVENT) {
 		u16 level;
 
-		r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &level);
+		r = core->read(core, WL1273_RSSI_LVL_GET, &level);
 		if (r)
 			goto out;
 
@@ -439,8 +298,8 @@
 		dev_dbg(radio->dev, "IRQ: FR:\n");
 
 		if (core->mode == WL1273_MODE_RX) {
-			r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
-						TUNER_MODE_STOP_SEARCH);
+			r = core->write(core, WL1273_TUNER_MODE_SET,
+					TUNER_MODE_STOP_SEARCH);
 			if (r) {
 				dev_err(radio->dev,
 					"%s: TUNER_MODE_SET fails: %d\n",
@@ -448,7 +307,7 @@
 				goto out;
 			}
 
-			r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &freq);
+			r = core->read(core, WL1273_FREQ_SET, &freq);
 			if (r)
 				goto out;
 
@@ -467,7 +326,7 @@
 			dev_dbg(radio->dev, "%dkHz\n", radio->rx_frequency);
 
 		} else {
-			r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &freq);
+			r = core->read(core, WL1273_CHANL_SET, &freq);
 			if (r)
 				goto out;
 
@@ -477,8 +336,7 @@
 	}
 
 out:
-	wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
-			    radio->irq_flags);
+	core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 	complete(&radio->busy);
 
 	return IRQ_HANDLED;
@@ -512,7 +370,7 @@
 	dev_dbg(radio->dev, "%s: freq: %d kHz\n", __func__, freq);
 
 	/* Set the current tx channel */
-	r = wl1273_fm_write_cmd(core, WL1273_CHANL_SET, freq / 10);
+	r = core->write(core, WL1273_CHANL_SET, freq / 10);
 	if (r)
 		return r;
 
@@ -526,7 +384,7 @@
 	dev_dbg(radio->dev, "WL1273_CHANL_SET: %d\n", r);
 
 	/* Enable the output power */
-	r = wl1273_fm_write_cmd(core, WL1273_POWER_ENB_SET, 1);
+	r = core->write(core, WL1273_POWER_ENB_SET, 1);
 	if (r)
 		return r;
 
@@ -566,20 +424,20 @@
 
 	dev_dbg(radio->dev, "%s: %dkHz\n", __func__, freq);
 
-	wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 
 	if (radio->band == WL1273_BAND_JAPAN)
 		f = (freq - WL1273_BAND_JAPAN_LOW) / 50;
 	else
 		f = (freq - WL1273_BAND_OTHER_LOW) / 50;
 
-	r = wl1273_fm_write_cmd(core, WL1273_FREQ_SET, f);
+	r = core->write(core, WL1273_FREQ_SET, f);
 	if (r) {
 		dev_err(radio->dev, "FREQ_SET fails\n");
 		goto err;
 	}
 
-	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET);
+	r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_PRESET);
 	if (r) {
 		dev_err(radio->dev, "TUNER_MODE_SET fails\n");
 		goto err;
@@ -609,7 +467,7 @@
 	int r;
 
 	if (core->mode == WL1273_MODE_RX) {
-		r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &f);
+		r = core->read(core, WL1273_FREQ_SET, &f);
 		if (r)
 			return r;
 
@@ -619,7 +477,7 @@
 		else
 			freq = WL1273_BAND_OTHER_LOW + 50 * f;
 	} else {
-		r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &f);
+		r = core->read(core, WL1273_CHANL_SET, &f);
 		if (r)
 			return r;
 
@@ -670,7 +528,7 @@
 	}
 
 	/* ignore possible error here */
-	wl1273_fm_write_cmd(core, WL1273_RESET, 0);
+	core->write(core, WL1273_RESET, 0);
 
 	dev_dbg(dev, "%s - download OK, r: %d\n", __func__, r);
 out:
@@ -683,14 +541,14 @@
 	struct wl1273_core *core = radio->core;
 
 	if (core->mode == WL1273_MODE_RX) {
-		int r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+		int r = core->write(core, WL1273_POWER_SET,
 				    WL1273_POWER_SET_OFF);
 		if (r)
 			dev_err(radio->dev, "%s: POWER_SET fails: %d\n",
 				__func__, r);
 	} else if (core->mode == WL1273_MODE_TX) {
-		int r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
-					    WL1273_PUPD_SET_OFF);
+		int r = core->write(core, WL1273_PUPD_SET,
+				    WL1273_PUPD_SET_OFF);
 		if (r)
 			dev_err(radio->dev,
 				"%s: PUPD_SET fails: %d\n", __func__, r);
@@ -725,11 +583,11 @@
 			val |= WL1273_POWER_SET_RDS;
 
 		/* If this fails try again */
-		r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+		r = core->write(core, WL1273_POWER_SET, val);
 		if (r) {
 			msleep(100);
 
-			r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+			r = core->write(core, WL1273_POWER_SET, val);
 			if (r) {
 				dev_err(dev, "%s: POWER_SET fails\n", __func__);
 				goto fail;
@@ -742,11 +600,10 @@
 
 	} else if (new_mode == WL1273_MODE_TX) {
 		/* If this fails try again once */
-		r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
-					WL1273_PUPD_SET_ON);
+		r = core->write(core, WL1273_PUPD_SET, WL1273_PUPD_SET_ON);
 		if (r) {
 			msleep(100);
-			r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+			r = core->write(core, WL1273_PUPD_SET,
 					WL1273_PUPD_SET_ON);
 			if (r) {
 				dev_err(dev, "%s: PUPD_SET fails\n", __func__);
@@ -755,9 +612,9 @@
 		}
 
 		if (radio->rds_on)
-			r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1);
+			r = core->write(core, WL1273_RDS_DATA_ENB, 1);
 		else
-			r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0);
+			r = core->write(core, WL1273_RDS_DATA_ENB, 0);
 	} else {
 		dev_warn(dev, "%s: Illegal mode.\n", __func__);
 	}
@@ -777,14 +634,14 @@
 			if (radio->rds_on)
 				val |= WL1273_POWER_SET_RDS;
 
-			r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, val);
+			r = core->write(core, WL1273_POWER_SET, val);
 			if (r) {
 				dev_err(dev, "%s: POWER_SET fails\n", __func__);
 				goto fail;
 			}
 		} else if (new_mode == WL1273_MODE_TX) {
-			r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
-						WL1273_PUPD_SET_ON);
+			r = core->write(core, WL1273_PUPD_SET,
+					WL1273_PUPD_SET_ON);
 			if (r) {
 				dev_err(dev, "%s: PUPD_SET fails\n", __func__);
 				goto fail;
@@ -808,10 +665,10 @@
 
 	/* Cannot go from OFF to SUSPENDED */
 	if (core->mode == WL1273_MODE_RX)
-		r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+		r = core->write(core, WL1273_POWER_SET,
 				WL1273_POWER_SET_RETENTION);
 	else if (core->mode == WL1273_MODE_TX)
-		r = wl1273_fm_write_cmd(core, WL1273_PUPD_SET,
+		r = core->write(core, WL1273_PUPD_SET,
 				WL1273_PUPD_SET_RETENTION);
 	else
 		r = -EINVAL;
@@ -852,8 +709,7 @@
 		}
 
 		core->mode = mode;
-		r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
-					radio->irq_flags);
+		r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 		if (r) {
 			dev_err(dev, "INT_MASK_SET fails.\n");
 			goto out;
@@ -951,22 +807,21 @@
 	INIT_COMPLETION(radio->busy);
 	dev_dbg(radio->dev, "%s: BUSY\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 	if (r)
 		goto out;
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_SEARCH_LVL_SET, level);
+	r = core->write(core, WL1273_SEARCH_LVL_SET, level);
 	if (r)
 		goto out;
 
-	r = wl1273_fm_write_cmd(core, WL1273_SEARCH_DIR_SET, dir);
+	r = core->write(core, WL1273_SEARCH_DIR_SET, dir);
 	if (r)
 		goto out;
 
-	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
-				TUNER_MODE_AUTO_SEEK);
+	r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK);
 	if (r)
 		goto out;
 
@@ -994,8 +849,7 @@
 	INIT_COMPLETION(radio->busy);
 	dev_dbg(radio->dev, "%s: BUSY\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_TUNER_MODE_SET,
-				TUNER_MODE_AUTO_SEEK);
+	r = core->write(core, WL1273_TUNER_MODE_SET, TUNER_MODE_AUTO_SEEK);
 	if (r)
 		goto out;
 
@@ -1020,7 +874,7 @@
 	    core->mode == WL1273_MODE_SUSPENDED)
 		return -EPERM;
 
-	r = wl1273_fm_read_reg(core, WL1273_READ_FMANT_TUNE_VALUE, &val);
+	r = core->read(core, WL1273_READ_FMANT_TUNE_VALUE, &val);
 	if (r) {
 		dev_err(dev, "%s: read error: %d\n", __func__, r);
 		goto out;
@@ -1066,7 +920,7 @@
 		goto out;
 	}
 
-	r = wl1273_fm_write_cmd(core, WL1273_PREMPH_SET, em);
+	r = core->write(core, WL1273_PREMPH_SET, em);
 	if (r)
 		goto out;
 
@@ -1086,7 +940,7 @@
 	if (radio->rds_on)
 		return 0;
 
-	r = wl1273_fm_write_cmd(core, WL1273_POWER_SET,
+	r = core->write(core, WL1273_POWER_SET,
 			WL1273_POWER_SET_FM | WL1273_POWER_SET_RDS);
 	if (r)
 		goto out;
@@ -1108,19 +962,16 @@
 
 	radio->irq_flags &= ~WL1273_RDS_EVENT;
 
-	r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET, radio->irq_flags);
+	r = core->write(core, WL1273_INT_MASK_SET, radio->irq_flags);
 	if (r)
 		goto out;
 
-	/* stop rds reception */
-	cancel_delayed_work(&radio->work);
-
 	/* Service pending read */
 	wake_up_interruptible(&radio->read_queue);
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	r = wl1273_fm_write_cmd(core, WL1273_POWER_SET, WL1273_POWER_SET_FM);
+	r = core->write(core, WL1273_POWER_SET, WL1273_POWER_SET_FM);
 	if (r)
 		goto out;
 
@@ -1143,14 +994,14 @@
 		return -EPERM;
 
 	if (new_mode == WL1273_RDS_RESET) {
-		r = wl1273_fm_write_cmd(core, WL1273_RDS_CNTRL_SET, 1);
+		r = core->write(core, WL1273_RDS_CNTRL_SET, 1);
 		return r;
 	}
 
 	if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_OFF) {
-		r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 0);
+		r = core->write(core, WL1273_RDS_DATA_ENB, 0);
 	} else if (core->mode == WL1273_MODE_TX && new_mode == WL1273_RDS_ON) {
-		r = wl1273_fm_write_cmd(core, WL1273_RDS_DATA_ENB, 1);
+		r = core->write(core, WL1273_RDS_DATA_ENB, 1);
 	} else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_OFF) {
 		r = wl1273_fm_rds_off(radio);
 	} else if (core->mode == WL1273_MODE_RX && new_mode == WL1273_RDS_ON) {
@@ -1171,12 +1022,13 @@
 				    size_t count, loff_t *ppos)
 {
 	struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
+	struct wl1273_core *core = radio->core;
 	u16 val;
 	int r;
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	if (radio->core->mode != WL1273_MODE_TX)
+	if (core->mode != WL1273_MODE_TX)
 		return count;
 
 	if (radio->rds_users == 0) {
@@ -1184,7 +1036,7 @@
 		return 0;
 	}
 
-	if (mutex_lock_interruptible(&radio->core->lock))
+	if (mutex_lock_interruptible(&core->lock))
 		return -EINTR;
 	/*
 	 * Multiple processes can open the device, but only
@@ -1202,7 +1054,7 @@
 	else
 		val = count;
 
-	wl1273_fm_write_cmd(radio->core, WL1273_RDS_CONFIG_DATA_SET, val);
+	core->write(core, WL1273_RDS_CONFIG_DATA_SET, val);
 
 	if (copy_from_user(radio->write_buf + 1, buf, val)) {
 		r = -EFAULT;
@@ -1213,11 +1065,11 @@
 	dev_dbg(radio->dev, "From user: \"%s\"\n", radio->write_buf);
 
 	radio->write_buf[0] = WL1273_RDS_DATA_SET;
-	wl1273_fm_write_data(radio->core, radio->write_buf, val + 1);
+	core->write_data(core, radio->write_buf, val + 1);
 
 	r = val;
 out:
-	mutex_unlock(&radio->core->lock);
+	mutex_unlock(&core->lock);
 
 	return r;
 }
@@ -1263,8 +1115,8 @@
 
 		radio->irq_flags |= WL1273_RDS_EVENT;
 
-		r = wl1273_fm_write_cmd(core, WL1273_INT_MASK_SET,
-					radio->irq_flags);
+		r = core->write(core, WL1273_INT_MASK_SET,
+				radio->irq_flags);
 		if (r) {
 			mutex_unlock(&core->lock);
 			goto out;
@@ -1295,9 +1147,9 @@
 			radio->irq_flags &= ~WL1273_RDS_EVENT;
 
 			if (core->mode == WL1273_MODE_RX) {
-				r = wl1273_fm_write_cmd(core,
-							WL1273_INT_MASK_SET,
-							radio->irq_flags);
+				r = core->write(core,
+						WL1273_INT_MASK_SET,
+						radio->irq_flags);
 				if (r) {
 					mutex_unlock(&core->lock);
 					goto out;
@@ -1324,7 +1176,7 @@
 
 	dev_dbg(radio->dev, "%s\n", __func__);
 
-	if (radio->core->mode != WL1273_MODE_RX)
+	if (core->mode != WL1273_MODE_RX)
 		return 0;
 
 	if (radio->rds_users == 0) {
@@ -1345,7 +1197,7 @@
 	}
 	radio->owner = file;
 
-	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 	if (r) {
 		dev_err(radio->dev, "%s: Get RDS_SYNC fails.\n", __func__);
 		goto out;
@@ -1466,23 +1318,24 @@
  */
 static int wl1273_fm_set_tx_power(struct wl1273_device *radio, u16 power)
 {
+	struct wl1273_core *core = radio->core;
 	int r;
 
-	if (radio->core->mode == WL1273_MODE_OFF ||
-	    radio->core->mode == WL1273_MODE_SUSPENDED)
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
 		return -EPERM;
 
-	mutex_lock(&radio->core->lock);
+	mutex_lock(&core->lock);
 
 	/* Convert the dBuV value to chip presentation */
-	r = wl1273_fm_write_cmd(radio->core, WL1273_POWER_LEV_SET, 122 - power);
+	r = core->write(core, WL1273_POWER_LEV_SET, 122 - power);
 	if (r)
 		goto out;
 
 	radio->tx_power = power;
 
 out:
-	mutex_unlock(&radio->core->lock);
+	mutex_unlock(&core->lock);
 	return r;
 }
 
@@ -1493,23 +1346,24 @@
 static int wl1273_fm_tx_set_spacing(struct wl1273_device *radio,
 				    unsigned int spacing)
 {
+	struct wl1273_core *core = radio->core;
 	int r;
 
 	if (spacing == 0) {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_100kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_100kHz);
 		radio->spacing = 100;
 	} else if (spacing - 50000 < 25000) {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_50kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_50kHz);
 		radio->spacing = 50;
 	} else if (spacing - 100000 < 50000) {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_100kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_100kHz);
 		radio->spacing = 100;
 	} else {
-		r = wl1273_fm_write_cmd(radio->core, WL1273_SCAN_SPACING_SET,
-					WL1273_SPACING_200kHz);
+		r = core->write(core, WL1273_SCAN_SPACING_SET,
+				WL1273_SPACING_200kHz);
 		radio->spacing = 200;
 	}
 
@@ -1567,17 +1421,17 @@
 			return -EINTR;
 
 		if (core->mode == WL1273_MODE_RX && ctrl->val)
-			r = wl1273_fm_write_cmd(core,
-						WL1273_MUTE_STATUS_SET,
-						WL1273_MUTE_HARD_LEFT |
-						WL1273_MUTE_HARD_RIGHT);
+			r = core->write(core,
+					WL1273_MUTE_STATUS_SET,
+					WL1273_MUTE_HARD_LEFT |
+					WL1273_MUTE_HARD_RIGHT);
 		else if (core->mode == WL1273_MODE_RX)
-			r = wl1273_fm_write_cmd(core,
-						WL1273_MUTE_STATUS_SET, 0x0);
+			r = core->write(core,
+					WL1273_MUTE_STATUS_SET, 0x0);
 		else if (core->mode == WL1273_MODE_TX && ctrl->val)
-			r = wl1273_fm_write_cmd(core, WL1273_MUTE, 1);
+			r = core->write(core, WL1273_MUTE, 1);
 		else if (core->mode == WL1273_MODE_TX)
-			r = wl1273_fm_write_cmd(core, WL1273_MUTE, 0);
+			r = core->write(core, WL1273_MUTE, 0);
 
 		mutex_unlock(&core->lock);
 		break;
@@ -1672,7 +1526,7 @@
 	if (mutex_lock_interruptible(&core->lock))
 		return -EINTR;
 
-	r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val);
+	r = core->read(core, WL1273_STEREO_GET, &val);
 	if (r)
 		goto out;
 
@@ -1681,7 +1535,7 @@
 	else
 		tuner->rxsubchans = V4L2_TUNER_SUB_MONO;
 
-	r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val);
+	r = core->read(core, WL1273_RSSI_LVL_GET, &val);
 	if (r)
 		goto out;
 
@@ -1690,7 +1544,7 @@
 
 	tuner->afc = 0;
 
-	r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+	r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 	if (r)
 		goto out;
 
@@ -1736,8 +1590,7 @@
 		dev_warn(radio->dev, "%s: RDS fails: %d\n", __func__, r);
 
 	if (tuner->audmode == V4L2_TUNER_MODE_MONO) {
-		r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
-					WL1273_RX_MONO);
+		r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_MONO);
 		if (r < 0) {
 			dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
 				 __func__, r);
@@ -1745,8 +1598,7 @@
 		}
 		radio->stereo = false;
 	} else if (tuner->audmode == V4L2_TUNER_MODE_STEREO) {
-		r = wl1273_fm_write_cmd(core, WL1273_MOST_MODE_SET,
-					WL1273_RX_STEREO);
+		r = core->write(core, WL1273_MOST_MODE_SET, WL1273_RX_STEREO);
 		if (r < 0) {
 			dev_warn(radio->dev, "%s: MOST_MODE fails: %d\n",
 				 __func__, r);
@@ -1885,10 +1737,10 @@
 		r = wl1273_fm_set_rds(radio, WL1273_RDS_OFF);
 
 	if (modulator->txsubchans & V4L2_TUNER_SUB_MONO)
-		r = wl1273_fm_write_cmd(core, WL1273_MONO_SET, WL1273_TX_MONO);
+		r = core->write(core, WL1273_MONO_SET, WL1273_TX_MONO);
 	else
-		r = wl1273_fm_write_cmd(core, WL1273_MONO_SET,
-					WL1273_RX_STEREO);
+		r = core->write(core, WL1273_MONO_SET,
+				WL1273_RX_STEREO);
 	if (r < 0)
 		dev_warn(radio->dev, WL1273_FM_DRIVER_NAME
 			 "MONO_SET fails: %d\n", r);
@@ -1923,7 +1775,7 @@
 	if (mutex_lock_interruptible(&core->lock))
 		return -EINTR;
 
-	r = wl1273_fm_read_reg(core, WL1273_MONO_SET, &val);
+	r = core->read(core, WL1273_MONO_SET, &val);
 	if (r)
 		goto out;
 
@@ -1960,38 +1812,38 @@
 		return 0;
 	}
 
-	r = wl1273_fm_read_reg(core, WL1273_ASIC_ID_GET, &val);
+	r = core->read(core, WL1273_ASIC_ID_GET, &val);
 	if (r)
 		dev_err(dev, "%s: Get ASIC_ID fails.\n", __func__);
 	else
 		dev_info(dev, "ASIC_ID: 0x%04x\n", val);
 
-	r = wl1273_fm_read_reg(core, WL1273_ASIC_VER_GET, &val);
+	r = core->read(core, WL1273_ASIC_VER_GET, &val);
 	if (r)
 		dev_err(dev, "%s: Get ASIC_VER fails.\n", __func__);
 	else
 		dev_info(dev, "ASIC Version: 0x%04x\n", val);
 
-	r = wl1273_fm_read_reg(core, WL1273_FIRM_VER_GET, &val);
+	r = core->read(core, WL1273_FIRM_VER_GET, &val);
 	if (r)
 		dev_err(dev, "%s: Get FIRM_VER fails.\n", __func__);
 	else
 		dev_info(dev, "FW version: %d(0x%04x)\n", val, val);
 
-	r = wl1273_fm_read_reg(core, WL1273_BAND_SET, &val);
+	r = core->read(core, WL1273_BAND_SET, &val);
 	if (r)
 		dev_err(dev, "%s: Get BAND fails.\n", __func__);
 	else
 		dev_info(dev, "BAND: %d\n", val);
 
 	if (core->mode == WL1273_MODE_TX) {
-		r = wl1273_fm_read_reg(core, WL1273_PUPD_SET, &val);
+		r = core->read(core, WL1273_PUPD_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get PUPD fails.\n", __func__);
 		else
 			dev_info(dev, "PUPD: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_CHANL_SET, &val);
+		r = core->read(core, WL1273_CHANL_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get CHANL fails.\n", __func__);
 		else
@@ -1999,13 +1851,13 @@
 	} else if (core->mode == WL1273_MODE_RX) {
 		int bf = radio->rangelow;
 
-		r = wl1273_fm_read_reg(core, WL1273_FREQ_SET, &val);
+		r = core->read(core, WL1273_FREQ_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get FREQ fails.\n", __func__);
 		else
 			dev_info(dev, "RX Frequency: %dkHz\n", bf + val*50);
 
-		r = wl1273_fm_read_reg(core, WL1273_MOST_MODE_SET, &val);
+		r = core->read(core, WL1273_MOST_MODE_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get MOST_MODE fails.\n",
 				__func__);
@@ -2016,7 +1868,7 @@
 		else
 			dev_info(dev, "MOST_MODE: Unexpected value: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_MOST_BLEND_SET, &val);
+		r = core->read(core, WL1273_MOST_BLEND_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get MOST_BLEND fails.\n", __func__);
 		else if (val == 0)
@@ -2027,7 +1879,7 @@
 		else
 			dev_info(dev, "MOST_BLEND: Unexpected val: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_STEREO_GET, &val);
+		r = core->read(core, WL1273_STEREO_GET, &val);
 		if (r)
 			dev_err(dev, "%s: Get STEREO fails.\n", __func__);
 		else if (val == 0)
@@ -2037,25 +1889,25 @@
 		else
 			dev_info(dev, "STEREO: Unexpected value: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_RSSI_LVL_GET, &val);
+		r = core->read(core, WL1273_RSSI_LVL_GET, &val);
 		if (r)
 			dev_err(dev, "%s: Get RSSI_LVL fails.\n", __func__);
 		else
 			dev_info(dev, "RX signal strength: %d\n", (s16) val);
 
-		r = wl1273_fm_read_reg(core, WL1273_POWER_SET, &val);
+		r = core->read(core, WL1273_POWER_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get POWER fails.\n", __func__);
 		else
 			dev_info(dev, "POWER: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_INT_MASK_SET, &val);
+		r = core->read(core, WL1273_INT_MASK_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get INT_MASK fails.\n", __func__);
 		else
 			dev_info(dev, "INT_MASK: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_RDS_SYNC_GET, &val);
+		r = core->read(core, WL1273_RDS_SYNC_GET, &val);
 		if (r)
 			dev_err(dev, "%s: Get RDS_SYNC fails.\n",
 				__func__);
@@ -2067,14 +1919,14 @@
 		else
 			dev_info(dev, "RDS_SYNC: Unexpected value: %d\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_I2S_MODE_CONFIG_SET, &val);
+		r = core->read(core, WL1273_I2S_MODE_CONFIG_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get I2S_MODE_CONFIG fails.\n",
 				__func__);
 		else
 			dev_info(dev, "I2S_MODE_CONFIG: 0x%04x\n", val);
 
-		r = wl1273_fm_read_reg(core, WL1273_VOLUME_SET, &val);
+		r = core->read(core, WL1273_VOLUME_SET, &val);
 		if (r)
 			dev_err(dev, "%s: Get VOLUME fails.\n", __func__);
 		else
@@ -2138,7 +1990,7 @@
 
 static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
 {
-	struct wl1273_core **core = pdev->dev.platform_data;
+	struct wl1273_core **core = mfd_get_data(pdev);
 	struct wl1273_device *radio;
 	struct v4l2_ctrl *ctrl;
 	int r = 0;
@@ -2184,10 +2036,6 @@
 	radio->stereo = true;
 	radio->bus_type = "I2C";
 
-	radio->core->write = wl1273_fm_write_cmd;
-	radio->core->set_audio = wl1273_fm_set_audio;
-	radio->core->set_volume = wl1273_fm_set_volume;
-
 	if (radio->core->pdata->request_resources) {
 		r = radio->core->pdata->request_resources(radio->core->client);
 		if (r) {
@@ -2319,7 +2167,6 @@
 
 static void __exit wl1273_fm_module_exit(void)
 {
-	flush_scheduled_work();
 	platform_driver_unregister(&wl1273_fm_radio_driver);
 	pr_info(DRIVER_DESC ", Exiting.\n");
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/saa7706h.c linux-libre-2.6.39-gnu/drivers/media/radio/saa7706h.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/saa7706h.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/saa7706h.c	2011-05-19 00:06:34.000000000 -0400
@@ -376,7 +376,7 @@
 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct saa7706h_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	sd = &state->sd;
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/si470x/radio-si470x-common.c linux-libre-2.6.39-gnu/drivers/media/radio/si470x/radio-si470x-common.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/si470x/radio-si470x-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/si470x/radio-si470x-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -460,7 +460,6 @@
 	count /= 3;
 
 	/* copy RDS block out of internal buffer and to user buffer */
-	mutex_lock(&radio->lock);
 	while (block_count < count) {
 		if (radio->rd_index == radio->wr_index)
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/si4713-i2c.c linux-libre-2.6.39-gnu/drivers/media/radio/si4713-i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/si4713-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/si4713-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -481,7 +481,7 @@
 }
 
 /*
- * si4713_wait_stc - Waits STC interrupt and clears status bits. Usefull
+ * si4713_wait_stc - Waits STC interrupt and clears status bits. Useful
  *		     for TX_TUNE_POWER, TX_TUNE_FREQ and TX_TUNE_MEAS
  * @sdev: si4713_device structure for the device we are communicating
  * @usecs: timeout to wait for STC interrupt signal
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/tef6862.c linux-libre-2.6.39-gnu/drivers/media/radio/tef6862.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/tef6862.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/radio/tef6862.c	2011-05-19 00:06:34.000000000 -0400
@@ -176,7 +176,7 @@
 	v4l_info(client, "chip found @ 0x%02x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct tef6862_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct tef6862_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	state->freq = TEF6862_LO_FREQ;
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_common.c linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_common.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_common.c	2012-03-24 03:29:48.000000000 -0400
@@ -0,0 +1,1687 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *
+ *  This sub-module of FM driver is common for FM RX and TX
+ *  functionality. This module is responsible for:
+ *  1) Forming group of Channel-8 commands to perform particular
+ *     functionality (eg., frequency set require more than
+ *     one Channel-8 command to be sent to the chip).
+ *  2) Sending each Channel-8 command to the chip and reading
+ *     response back over Shared Transport.
+ *  3) Managing TX and RX Queues and Tasklets.
+ *  4) Handling FM Interrupt packet and taking appropriate action.
+ *  5) Loading FM firmware to the chip (common, FM TX, and FM RX
+ *     firmware files based on mode selection)
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *  Author: Raja Mani <raja_mani@ti.com>
+ *  Author: Manjunatha Halli <manjunatha_halli@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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/firmware.h>
+#include <linux/delay.h>
+#include "fmdrv.h"
+#include "fmdrv_v4l2.h"
+#include "fmdrv_common.h"
+#include <linux/ti_wilink_st.h>
+#include "fmdrv_rx.h"
+#include "fmdrv_tx.h"
+
+/* Region info */
+static struct region_info region_configs[] = {
+	/* Europe/US */
+	{
+	 .chanl_space = FM_CHANNEL_SPACING_200KHZ * FM_FREQ_MUL,
+	 .bot_freq = 87500,	/* 87.5 MHz */
+	 .top_freq = 108000,	/* 108 MHz */
+	 .fm_band = 0,
+	 },
+	/* Japan */
+	{
+	 .chanl_space = FM_CHANNEL_SPACING_200KHZ * FM_FREQ_MUL,
+	 .bot_freq = 76000,	/* 76 MHz */
+	 .top_freq = 90000,	/* 90 MHz */
+	 .fm_band = 1,
+	 },
+};
+
+/* Band selection */
+static u8 default_radio_region;	/* Europe/US */
+module_param(default_radio_region, byte, 0);
+MODULE_PARM_DESC(default_radio_region, "Region: 0=Europe/US, 1=Japan");
+
+/* RDS buffer blocks */
+static u32 default_rds_buf = 300;
+module_param(default_rds_buf, uint, 0444);
+MODULE_PARM_DESC(rds_buf, "RDS buffer entries");
+
+/* Radio Nr */
+static u32 radio_nr = -1;
+module_param(radio_nr, int, 0444);
+MODULE_PARM_DESC(radio_nr, "Radio Nr");
+
+/* FM irq handlers forward declaration */
+static void fm_irq_send_flag_getcmd(struct fmdev *);
+static void fm_irq_handle_flag_getcmd_resp(struct fmdev *);
+static void fm_irq_handle_hw_malfunction(struct fmdev *);
+static void fm_irq_handle_rds_start(struct fmdev *);
+static void fm_irq_send_rdsdata_getcmd(struct fmdev *);
+static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *);
+static void fm_irq_handle_rds_finish(struct fmdev *);
+static void fm_irq_handle_tune_op_ended(struct fmdev *);
+static void fm_irq_handle_power_enb(struct fmdev *);
+static void fm_irq_handle_low_rssi_start(struct fmdev *);
+static void fm_irq_afjump_set_pi(struct fmdev *);
+static void fm_irq_handle_set_pi_resp(struct fmdev *);
+static void fm_irq_afjump_set_pimask(struct fmdev *);
+static void fm_irq_handle_set_pimask_resp(struct fmdev *);
+static void fm_irq_afjump_setfreq(struct fmdev *);
+static void fm_irq_handle_setfreq_resp(struct fmdev *);
+static void fm_irq_afjump_enableint(struct fmdev *);
+static void fm_irq_afjump_enableint_resp(struct fmdev *);
+static void fm_irq_start_afjump(struct fmdev *);
+static void fm_irq_handle_start_afjump_resp(struct fmdev *);
+static void fm_irq_afjump_rd_freq(struct fmdev *);
+static void fm_irq_afjump_rd_freq_resp(struct fmdev *);
+static void fm_irq_handle_low_rssi_finish(struct fmdev *);
+static void fm_irq_send_intmsk_cmd(struct fmdev *);
+static void fm_irq_handle_intmsk_cmd_resp(struct fmdev *);
+
+/*
+ * When FM common module receives interrupt packet, following handlers
+ * will be executed one after another to service the interrupt(s)
+ */
+enum fmc_irq_handler_index {
+	FM_SEND_FLAG_GETCMD_IDX,
+	FM_HANDLE_FLAG_GETCMD_RESP_IDX,
+
+	/* HW malfunction irq handler */
+	FM_HW_MAL_FUNC_IDX,
+
+	/* RDS threshold reached irq handler */
+	FM_RDS_START_IDX,
+	FM_RDS_SEND_RDS_GETCMD_IDX,
+	FM_RDS_HANDLE_RDS_GETCMD_RESP_IDX,
+	FM_RDS_FINISH_IDX,
+
+	/* Tune operation ended irq handler */
+	FM_HW_TUNE_OP_ENDED_IDX,
+
+	/* TX power enable irq handler */
+	FM_HW_POWER_ENB_IDX,
+
+	/* Low RSSI irq handler */
+	FM_LOW_RSSI_START_IDX,
+	FM_AF_JUMP_SETPI_IDX,
+	FM_AF_JUMP_HANDLE_SETPI_RESP_IDX,
+	FM_AF_JUMP_SETPI_MASK_IDX,
+	FM_AF_JUMP_HANDLE_SETPI_MASK_RESP_IDX,
+	FM_AF_JUMP_SET_AF_FREQ_IDX,
+	FM_AF_JUMP_HANDLE_SET_AFFREQ_RESP_IDX,
+	FM_AF_JUMP_ENABLE_INT_IDX,
+	FM_AF_JUMP_ENABLE_INT_RESP_IDX,
+	FM_AF_JUMP_START_AFJUMP_IDX,
+	FM_AF_JUMP_HANDLE_START_AFJUMP_RESP_IDX,
+	FM_AF_JUMP_RD_FREQ_IDX,
+	FM_AF_JUMP_RD_FREQ_RESP_IDX,
+	FM_LOW_RSSI_FINISH_IDX,
+
+	/* Interrupt process post action */
+	FM_SEND_INTMSK_CMD_IDX,
+	FM_HANDLE_INTMSK_CMD_RESP_IDX,
+};
+
+/* FM interrupt handler table */
+static int_handler_prototype int_handler_table[] = {
+	fm_irq_send_flag_getcmd,
+	fm_irq_handle_flag_getcmd_resp,
+	fm_irq_handle_hw_malfunction,
+	fm_irq_handle_rds_start, /* RDS threshold reached irq handler */
+	fm_irq_send_rdsdata_getcmd,
+	fm_irq_handle_rdsdata_getcmd_resp,
+	fm_irq_handle_rds_finish,
+	fm_irq_handle_tune_op_ended,
+	fm_irq_handle_power_enb, /* TX power enable irq handler */
+	fm_irq_handle_low_rssi_start,
+	fm_irq_afjump_set_pi,
+	fm_irq_handle_set_pi_resp,
+	fm_irq_afjump_set_pimask,
+	fm_irq_handle_set_pimask_resp,
+	fm_irq_afjump_setfreq,
+	fm_irq_handle_setfreq_resp,
+	fm_irq_afjump_enableint,
+	fm_irq_afjump_enableint_resp,
+	fm_irq_start_afjump,
+	fm_irq_handle_start_afjump_resp,
+	fm_irq_afjump_rd_freq,
+	fm_irq_afjump_rd_freq_resp,
+	fm_irq_handle_low_rssi_finish,
+	fm_irq_send_intmsk_cmd, /* Interrupt process post action */
+	fm_irq_handle_intmsk_cmd_resp
+};
+
+long (*g_st_write) (struct sk_buff *skb);
+static struct completion wait_for_fmdrv_reg_comp;
+
+static inline void fm_irq_call(struct fmdev *fmdev)
+{
+	fmdev->irq_info.handlers[fmdev->irq_info.stage](fmdev);
+}
+
+/* Continue next function in interrupt handler table */
+static inline void fm_irq_call_stage(struct fmdev *fmdev, u8 stage)
+{
+	fmdev->irq_info.stage = stage;
+	fm_irq_call(fmdev);
+}
+
+static inline void fm_irq_timeout_stage(struct fmdev *fmdev, u8 stage)
+{
+	fmdev->irq_info.stage = stage;
+	mod_timer(&fmdev->irq_info.timer, jiffies + FM_DRV_TX_TIMEOUT);
+}
+
+#ifdef FM_DUMP_TXRX_PKT
+ /* To dump outgoing FM Channel-8 packets */
+inline void dump_tx_skb_data(struct sk_buff *skb)
+{
+	int len, len_org;
+	u8 index;
+	struct fm_cmd_msg_hdr *cmd_hdr;
+
+	cmd_hdr = (struct fm_cmd_msg_hdr *)skb->data;
+	printk(KERN_INFO "<<%shdr:%02x len:%02x opcode:%02x type:%s dlen:%02x",
+	       fm_cb(skb)->completion ? " " : "*", cmd_hdr->hdr,
+	       cmd_hdr->len, cmd_hdr->op,
+	       cmd_hdr->rd_wr ? "RD" : "WR", cmd_hdr->dlen);
+
+	len_org = skb->len - FM_CMD_MSG_HDR_SIZE;
+	if (len_org > 0) {
+		printk("\n   data(%d): ", cmd_hdr->dlen);
+		len = min(len_org, 14);
+		for (index = 0; index < len; index++)
+			printk("%x ",
+			       skb->data[FM_CMD_MSG_HDR_SIZE + index]);
+		printk("%s", (len_org > 14) ? ".." : "");
+	}
+	printk("\n");
+}
+
+ /* To dump incoming FM Channel-8 packets */
+inline void dump_rx_skb_data(struct sk_buff *skb)
+{
+	int len, len_org;
+	u8 index;
+	struct fm_event_msg_hdr *evt_hdr;
+
+	evt_hdr = (struct fm_event_msg_hdr *)skb->data;
+	printk(KERN_INFO ">> hdr:%02x len:%02x sts:%02x numhci:%02x "
+	    "opcode:%02x type:%s dlen:%02x", evt_hdr->hdr, evt_hdr->len,
+	    evt_hdr->status, evt_hdr->num_fm_hci_cmds, evt_hdr->op,
+	    (evt_hdr->rd_wr) ? "RD" : "WR", evt_hdr->dlen);
+
+	len_org = skb->len - FM_EVT_MSG_HDR_SIZE;
+	if (len_org > 0) {
+		printk("\n   data(%d): ", evt_hdr->dlen);
+		len = min(len_org, 14);
+		for (index = 0; index < len; index++)
+			printk("%x ",
+			       skb->data[FM_EVT_MSG_HDR_SIZE + index]);
+		printk("%s", (len_org > 14) ? ".." : "");
+	}
+	printk("\n");
+}
+#endif
+
+void fmc_update_region_info(struct fmdev *fmdev, u8 region_to_set)
+{
+	fmdev->rx.region = region_configs[region_to_set];
+}
+
+/*
+ * FM common sub-module will schedule this tasklet whenever it receives
+ * FM packet from ST driver.
+ */
+static void recv_tasklet(unsigned long arg)
+{
+	struct fmdev *fmdev;
+	struct fm_irq *irq_info;
+	struct fm_event_msg_hdr *evt_hdr;
+	struct sk_buff *skb;
+	u8 num_fm_hci_cmds;
+	unsigned long flags;
+
+	fmdev = (struct fmdev *)arg;
+	irq_info = &fmdev->irq_info;
+	/* Process all packets in the RX queue */
+	while ((skb = skb_dequeue(&fmdev->rx_q))) {
+		if (skb->len < sizeof(struct fm_event_msg_hdr)) {
+			fmerr("skb(%p) has only %d bytes, "
+				"at least need %zu bytes to decode\n", skb,
+				skb->len, sizeof(struct fm_event_msg_hdr));
+			kfree_skb(skb);
+			continue;
+		}
+
+		evt_hdr = (void *)skb->data;
+		num_fm_hci_cmds = evt_hdr->num_fm_hci_cmds;
+
+		/* FM interrupt packet? */
+		if (evt_hdr->op == FM_INTERRUPT) {
+			/* FM interrupt handler started already? */
+			if (!test_bit(FM_INTTASK_RUNNING, &fmdev->flag)) {
+				set_bit(FM_INTTASK_RUNNING, &fmdev->flag);
+				if (irq_info->stage != 0) {
+					fmerr("Inval stage resetting to zero\n");
+					irq_info->stage = 0;
+				}
+
+				/*
+				 * Execute first function in interrupt handler
+				 * table.
+				 */
+				irq_info->handlers[irq_info->stage](fmdev);
+			} else {
+				set_bit(FM_INTTASK_SCHEDULE_PENDING, &fmdev->flag);
+			}
+			kfree_skb(skb);
+		}
+		/* Anyone waiting for this with completion handler? */
+		else if (evt_hdr->op == fmdev->pre_op && fmdev->resp_comp != NULL) {
+
+			spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
+			fmdev->resp_skb = skb;
+			spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
+			complete(fmdev->resp_comp);
+
+			fmdev->resp_comp = NULL;
+			atomic_set(&fmdev->tx_cnt, 1);
+		}
+		/* Is this for interrupt handler? */
+		else if (evt_hdr->op == fmdev->pre_op && fmdev->resp_comp == NULL) {
+			if (fmdev->resp_skb != NULL)
+				fmerr("Response SKB ptr not NULL\n");
+
+			spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
+			fmdev->resp_skb = skb;
+			spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
+
+			/* Execute interrupt handler where state index points */
+			irq_info->handlers[irq_info->stage](fmdev);
+
+			kfree_skb(skb);
+			atomic_set(&fmdev->tx_cnt, 1);
+		} else {
+			fmerr("Nobody claimed SKB(%p),purging\n", skb);
+		}
+
+		/*
+		 * Check flow control field. If Num_FM_HCI_Commands field is
+		 * not zero, schedule FM TX tasklet.
+		 */
+		if (num_fm_hci_cmds && atomic_read(&fmdev->tx_cnt))
+			if (!skb_queue_empty(&fmdev->tx_q))
+				tasklet_schedule(&fmdev->tx_task);
+	}
+}
+
+/* FM send tasklet: is scheduled when FM packet has to be sent to chip */
+static void send_tasklet(unsigned long arg)
+{
+	struct fmdev *fmdev;
+	struct sk_buff *skb;
+	int len;
+
+	fmdev = (struct fmdev *)arg;
+
+	if (!atomic_read(&fmdev->tx_cnt))
+		return;
+
+	/* Check, is there any timeout happened to last transmitted packet */
+	if ((jiffies - fmdev->last_tx_jiffies) > FM_DRV_TX_TIMEOUT) {
+		fmerr("TX timeout occurred\n");
+		atomic_set(&fmdev->tx_cnt, 1);
+	}
+
+	/* Send queued FM TX packets */
+	skb = skb_dequeue(&fmdev->tx_q);
+	if (!skb)
+		return;
+
+	atomic_dec(&fmdev->tx_cnt);
+	fmdev->pre_op = fm_cb(skb)->fm_op;
+
+	if (fmdev->resp_comp != NULL)
+		fmerr("Response completion handler is not NULL\n");
+
+	fmdev->resp_comp = fm_cb(skb)->completion;
+
+	/* Write FM packet to ST driver */
+	len = g_st_write(skb);
+	if (len < 0) {
+		kfree_skb(skb);
+		fmdev->resp_comp = NULL;
+		fmerr("TX tasklet failed to send skb(%p)\n", skb);
+		atomic_set(&fmdev->tx_cnt, 1);
+	} else {
+		fmdev->last_tx_jiffies = jiffies;
+	}
+}
+
+/*
+ * Queues FM Channel-8 packet to FM TX queue and schedules FM TX tasklet for
+ * transmission
+ */
+static u32 fm_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type,	void *payload,
+		int payload_len, struct completion *wait_completion)
+{
+	struct sk_buff *skb;
+	struct fm_cmd_msg_hdr *hdr;
+	int size;
+
+	if (fm_op >= FM_INTERRUPT) {
+		fmerr("Invalid fm opcode - %d\n", fm_op);
+		return -EINVAL;
+	}
+	if (test_bit(FM_FW_DW_INPROGRESS, &fmdev->flag) && payload == NULL) {
+		fmerr("Payload data is NULL during fw download\n");
+		return -EINVAL;
+	}
+	if (!test_bit(FM_FW_DW_INPROGRESS, &fmdev->flag))
+		size =
+		    FM_CMD_MSG_HDR_SIZE + ((payload == NULL) ? 0 : payload_len);
+	else
+		size = payload_len;
+
+	skb = alloc_skb(size, GFP_ATOMIC);
+	if (!skb) {
+		fmerr("No memory to create new SKB\n");
+		return -ENOMEM;
+	}
+	/*
+	 * Don't fill FM header info for the commands which come from
+	 * FM firmware file.
+	 */
+	if (!test_bit(FM_FW_DW_INPROGRESS, &fmdev->flag) ||
+			test_bit(FM_INTTASK_RUNNING, &fmdev->flag)) {
+		/* Fill command header info */
+		hdr = (struct fm_cmd_msg_hdr *)skb_put(skb, FM_CMD_MSG_HDR_SIZE);
+		hdr->hdr = FM_PKT_LOGICAL_CHAN_NUMBER;	/* 0x08 */
+
+		/* 3 (fm_opcode,rd_wr,dlen) + payload len) */
+		hdr->len = ((payload == NULL) ? 0 : payload_len) + 3;
+
+		/* FM opcode */
+		hdr->op = fm_op;
+
+		/* read/write type */
+		hdr->rd_wr = type;
+		hdr->dlen = payload_len;
+		fm_cb(skb)->fm_op = fm_op;
+
+		/*
+		 * If firmware download has finished and the command is
+		 * not a read command then payload is != NULL - a write
+		 * command with u16 payload - convert to be16
+		 */
+		if (payload != NULL)
+			*(u16 *)payload = cpu_to_be16(*(u16 *)payload);
+
+	} else if (payload != NULL) {
+		fm_cb(skb)->fm_op = *((u8 *)payload + 2);
+	}
+	if (payload != NULL)
+		memcpy(skb_put(skb, payload_len), payload, payload_len);
+
+	fm_cb(skb)->completion = wait_completion;
+	skb_queue_tail(&fmdev->tx_q, skb);
+	tasklet_schedule(&fmdev->tx_task);
+
+	return 0;
+}
+
+/* Sends FM Channel-8 command to the chip and waits for the response */
+u32 fmc_send_cmd(struct fmdev *fmdev, u8 fm_op, u16 type, void *payload,
+		unsigned int payload_len, void *response, int *response_len)
+{
+	struct sk_buff *skb;
+	struct fm_event_msg_hdr *evt_hdr;
+	unsigned long flags;
+	u32 ret;
+
+	init_completion(&fmdev->maintask_comp);
+	ret = fm_send_cmd(fmdev, fm_op, type, payload, payload_len,
+			    &fmdev->maintask_comp);
+	if (ret)
+		return ret;
+
+	ret = wait_for_completion_timeout(&fmdev->maintask_comp, FM_DRV_TX_TIMEOUT);
+	if (!ret) {
+		fmerr("Timeout(%d sec),didn't get reg"
+			   "completion signal from RX tasklet\n",
+			   jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
+		return -ETIMEDOUT;
+	}
+	if (!fmdev->resp_skb) {
+		fmerr("Response SKB is missing\n");
+		return -EFAULT;
+	}
+	spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
+	skb = fmdev->resp_skb;
+	fmdev->resp_skb = NULL;
+	spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
+
+	evt_hdr = (void *)skb->data;
+	if (evt_hdr->status != 0) {
+		fmerr("Received event pkt status(%d) is not zero\n",
+			   evt_hdr->status);
+		kfree_skb(skb);
+		return -EIO;
+	}
+	/* Send response data to caller */
+	if (response != NULL && response_len != NULL && evt_hdr->dlen) {
+		/* Skip header info and copy only response data */
+		skb_pull(skb, sizeof(struct fm_event_msg_hdr));
+		memcpy(response, skb->data, evt_hdr->dlen);
+		*response_len = evt_hdr->dlen;
+	} else if (response_len != NULL && evt_hdr->dlen == 0) {
+		*response_len = 0;
+	}
+	kfree_skb(skb);
+
+	return 0;
+}
+
+/* --- Helper functions used in FM interrupt handlers ---*/
+static inline u32 check_cmdresp_status(struct fmdev *fmdev,
+		struct sk_buff **skb)
+{
+	struct fm_event_msg_hdr *fm_evt_hdr;
+	unsigned long flags;
+
+	del_timer(&fmdev->irq_info.timer);
+
+	spin_lock_irqsave(&fmdev->resp_skb_lock, flags);
+	*skb = fmdev->resp_skb;
+	fmdev->resp_skb = NULL;
+	spin_unlock_irqrestore(&fmdev->resp_skb_lock, flags);
+
+	fm_evt_hdr = (void *)(*skb)->data;
+	if (fm_evt_hdr->status != 0) {
+		fmerr("irq: opcode %x response status is not zero "
+				"Initiating irq recovery process\n",
+				fm_evt_hdr->op);
+
+		mod_timer(&fmdev->irq_info.timer, jiffies + FM_DRV_TX_TIMEOUT);
+		return -1;
+	}
+
+	return 0;
+}
+
+static inline void fm_irq_common_cmd_resp_helper(struct fmdev *fmdev, u8 stage)
+{
+	struct sk_buff *skb;
+
+	if (!check_cmdresp_status(fmdev, &skb))
+		fm_irq_call_stage(fmdev, stage);
+}
+
+/*
+ * Interrupt process timeout handler.
+ * One of the irq handler did not get proper response from the chip. So take
+ * recovery action here. FM interrupts are disabled in the beginning of
+ * interrupt process. Therefore reset stage index to re-enable default
+ * interrupts. So that next interrupt will be processed as usual.
+ */
+static void int_timeout_handler(unsigned long data)
+{
+	struct fmdev *fmdev;
+	struct fm_irq *fmirq;
+
+	fmdbg("irq: timeout,trying to re-enable fm interrupts\n");
+	fmdev = (struct fmdev *)data;
+	fmirq = &fmdev->irq_info;
+	fmirq->retry++;
+
+	if (fmirq->retry > FM_IRQ_TIMEOUT_RETRY_MAX) {
+		/* Stop recovery action (interrupt reenable process) and
+		 * reset stage index & retry count values */
+		fmirq->stage = 0;
+		fmirq->retry = 0;
+		fmerr("Recovery action failed during"
+				"irq processing, max retry reached\n");
+		return;
+	}
+	fm_irq_call_stage(fmdev, FM_SEND_INTMSK_CMD_IDX);
+}
+
+/* --------- FM interrupt handlers ------------*/
+static void fm_irq_send_flag_getcmd(struct fmdev *fmdev)
+{
+	u16 flag;
+
+	/* Send FLAG_GET command , to know the source of interrupt */
+	if (!fm_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, sizeof(flag), NULL))
+		fm_irq_timeout_stage(fmdev, FM_HANDLE_FLAG_GETCMD_RESP_IDX);
+}
+
+static void fm_irq_handle_flag_getcmd_resp(struct fmdev *fmdev)
+{
+	struct sk_buff *skb;
+	struct fm_event_msg_hdr *fm_evt_hdr;
+
+	if (check_cmdresp_status(fmdev, &skb))
+		return;
+
+	fm_evt_hdr = (void *)skb->data;
+
+	/* Skip header info and copy only response data */
+	skb_pull(skb, sizeof(struct fm_event_msg_hdr));
+	memcpy(&fmdev->irq_info.flag, skb->data, fm_evt_hdr->dlen);
+
+	fmdev->irq_info.flag = be16_to_cpu(fmdev->irq_info.flag);
+	fmdbg("irq: flag register(0x%x)\n", fmdev->irq_info.flag);
+
+	/* Continue next function in interrupt handler table */
+	fm_irq_call_stage(fmdev, FM_HW_MAL_FUNC_IDX);
+}
+
+static void fm_irq_handle_hw_malfunction(struct fmdev *fmdev)
+{
+	if (fmdev->irq_info.flag & FM_MAL_EVENT & fmdev->irq_info.mask)
+		fmerr("irq: HW MAL int received - do nothing\n");
+
+	/* Continue next function in interrupt handler table */
+	fm_irq_call_stage(fmdev, FM_RDS_START_IDX);
+}
+
+static void fm_irq_handle_rds_start(struct fmdev *fmdev)
+{
+	if (fmdev->irq_info.flag & FM_RDS_EVENT & fmdev->irq_info.mask) {
+		fmdbg("irq: rds threshold reached\n");
+		fmdev->irq_info.stage = FM_RDS_SEND_RDS_GETCMD_IDX;
+	} else {
+		/* Continue next function in interrupt handler table */
+		fmdev->irq_info.stage = FM_HW_TUNE_OP_ENDED_IDX;
+	}
+
+	fm_irq_call(fmdev);
+}
+
+static void fm_irq_send_rdsdata_getcmd(struct fmdev *fmdev)
+{
+	/* Send the command to read RDS data from the chip */
+	if (!fm_send_cmd(fmdev, RDS_DATA_GET, REG_RD, NULL,
+			    (FM_RX_RDS_FIFO_THRESHOLD * 3), NULL))
+		fm_irq_timeout_stage(fmdev, FM_RDS_HANDLE_RDS_GETCMD_RESP_IDX);
+}
+
+/* Keeps track of current RX channel AF (Alternate Frequency) */
+static void fm_rx_update_af_cache(struct fmdev *fmdev, u8 af)
+{
+	struct tuned_station_info *stat_info = &fmdev->rx.stat_info;
+	u8 reg_idx = fmdev->rx.region.fm_band;
+	u8 index;
+	u32 freq;
+
+	/* First AF indicates the number of AF follows. Reset the list */
+	if ((af >= FM_RDS_1_AF_FOLLOWS) && (af <= FM_RDS_25_AF_FOLLOWS)) {
+		fmdev->rx.stat_info.af_list_max = (af - FM_RDS_1_AF_FOLLOWS + 1);
+		fmdev->rx.stat_info.afcache_size = 0;
+		fmdbg("No of expected AF : %d\n", fmdev->rx.stat_info.af_list_max);
+		return;
+	}
+
+	if (af < FM_RDS_MIN_AF)
+		return;
+	if (reg_idx == FM_BAND_EUROPE_US && af > FM_RDS_MAX_AF)
+		return;
+	if (reg_idx == FM_BAND_JAPAN && af > FM_RDS_MAX_AF_JAPAN)
+		return;
+
+	freq = fmdev->rx.region.bot_freq + (af * 100);
+	if (freq == fmdev->rx.freq) {
+		fmdbg("Current freq(%d) is matching with received AF(%d)\n",
+				fmdev->rx.freq, freq);
+		return;
+	}
+	/* Do check in AF cache */
+	for (index = 0; index < stat_info->afcache_size; index++) {
+		if (stat_info->af_cache[index] == freq)
+			break;
+	}
+	/* Reached the limit of the list - ignore the next AF */
+	if (index == stat_info->af_list_max) {
+		fmdbg("AF cache is full\n");
+		return;
+	}
+	/*
+	 * If we reached the end of the list then this AF is not
+	 * in the list - add it.
+	 */
+	if (index == stat_info->afcache_size) {
+		fmdbg("Storing AF %d to cache index %d\n", freq, index);
+		stat_info->af_cache[index] = freq;
+		stat_info->afcache_size++;
+	}
+}
+
+/*
+ * Converts RDS buffer data from big endian format
+ * to little endian format.
+ */
+static void fm_rdsparse_swapbytes(struct fmdev *fmdev,
+		struct fm_rdsdata_format *rds_format)
+{
+	u8 byte1;
+	u8 index = 0;
+	u8 *rds_buff;
+
+	/*
+	 * Since in Orca the 2 RDS Data bytes are in little endian and
+	 * in Dolphin they are in big endian, the parsing of the RDS data
+	 * is chip dependent
+	 */
+	if (fmdev->asci_id != 0x6350) {
+		rds_buff = &rds_format->data.groupdatabuff.buff[0];
+		while (index + 1 < FM_RX_RDS_INFO_FIELD_MAX) {
+			byte1 = rds_buff[index];
+			rds_buff[index] = rds_buff[index + 1];
+			rds_buff[index + 1] = byte1;
+			index += 2;
+		}
+	}
+}
+
+static void fm_irq_handle_rdsdata_getcmd_resp(struct fmdev *fmdev)
+{
+	struct sk_buff *skb;
+	struct fm_rdsdata_format rds_fmt;
+	struct fm_rds *rds = &fmdev->rx.rds;
+	unsigned long group_idx, flags;
+	u8 *rds_data, meta_data, tmpbuf[3];
+	u8 type, blk_idx;
+	u16 cur_picode;
+	u32 rds_len;
+
+	if (check_cmdresp_status(fmdev, &skb))
+		return;
+
+	/* Skip header info */
+	skb_pull(skb, sizeof(struct fm_event_msg_hdr));
+	rds_data = skb->data;
+	rds_len = skb->len;
+
+	/* Parse the RDS data */
+	while (rds_len >= FM_RDS_BLK_SIZE) {
+		meta_data = rds_data[2];
+		/* Get the type: 0=A, 1=B, 2=C, 3=C', 4=D, 5=E */
+		type = (meta_data & 0x07);
+
+		/* Transform the blk type into index sequence (0, 1, 2, 3, 4) */
+		blk_idx = (type <= FM_RDS_BLOCK_C ? type : (type - 1));
+		fmdbg("Block index:%d(%s)\n", blk_idx,
+			   (meta_data & FM_RDS_STATUS_ERR_MASK) ? "Bad" : "Ok");
+
+		if ((meta_data & FM_RDS_STATUS_ERR_MASK) != 0)
+			break;
+
+		if (blk_idx < FM_RDS_BLK_IDX_A || blk_idx > FM_RDS_BLK_IDX_D) {
+			fmdbg("Block sequence mismatch\n");
+			rds->last_blk_idx = -1;
+			break;
+		}
+
+		/* Skip checkword (control) byte and copy only data byte */
+		memcpy(&rds_fmt.data.groupdatabuff.
+				buff[blk_idx * (FM_RDS_BLK_SIZE - 1)],
+				rds_data, (FM_RDS_BLK_SIZE - 1));
+
+		rds->last_blk_idx = blk_idx;
+
+		/* If completed a whole group then handle it */
+		if (blk_idx == FM_RDS_BLK_IDX_D) {
+			fmdbg("Good block received\n");
+			fm_rdsparse_swapbytes(fmdev, &rds_fmt);
+
+			/*
+			 * Extract PI code and store in local cache.
+			 * We need this during AF switch processing.
+			 */
+			cur_picode = be16_to_cpu(rds_fmt.data.groupgeneral.pidata);
+			if (fmdev->rx.stat_info.picode != cur_picode)
+				fmdev->rx.stat_info.picode = cur_picode;
+
+			fmdbg("picode:%d\n", cur_picode);
+
+			group_idx = (rds_fmt.data.groupgeneral.blk_b[0] >> 3);
+			fmdbg("(fmdrv):Group:%ld%s\n", group_idx/2,
+					(group_idx % 2) ? "B" : "A");
+
+			group_idx = 1 << (rds_fmt.data.groupgeneral.blk_b[0] >> 3);
+			if (group_idx == FM_RDS_GROUP_TYPE_MASK_0A) {
+				fm_rx_update_af_cache(fmdev, rds_fmt.data.group0A.af[0]);
+				fm_rx_update_af_cache(fmdev, rds_fmt.data.group0A.af[1]);
+			}
+		}
+		rds_len -= FM_RDS_BLK_SIZE;
+		rds_data += FM_RDS_BLK_SIZE;
+	}
+
+	/* Copy raw rds data to internal rds buffer */
+	rds_data = skb->data;
+	rds_len = skb->len;
+
+	spin_lock_irqsave(&fmdev->rds_buff_lock, flags);
+	while (rds_len > 0) {
+		/*
+		 * Fill RDS buffer as per V4L2 specification.
+		 * Store control byte
+		 */
+		type = (rds_data[2] & 0x07);
+		blk_idx = (type <= FM_RDS_BLOCK_C ? type : (type - 1));
+		tmpbuf[2] = blk_idx;	/* Offset name */
+		tmpbuf[2] |= blk_idx << 3;	/* Received offset */
+
+		/* Store data byte */
+		tmpbuf[0] = rds_data[0];
+		tmpbuf[1] = rds_data[1];
+
+		memcpy(&rds->buff[rds->wr_idx], &tmpbuf, FM_RDS_BLK_SIZE);
+		rds->wr_idx = (rds->wr_idx + FM_RDS_BLK_SIZE) % rds->buf_size;
+
+		/* Check for overflow & start over */
+		if (rds->wr_idx == rds->rd_idx) {
+			fmdbg("RDS buffer overflow\n");
+			rds->wr_idx = 0;
+			rds->rd_idx = 0;
+			break;
+		}
+		rds_len -= FM_RDS_BLK_SIZE;
+		rds_data += FM_RDS_BLK_SIZE;
+	}
+	spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags);
+
+	/* Wakeup read queue */
+	if (rds->wr_idx != rds->rd_idx)
+		wake_up_interruptible(&rds->read_queue);
+
+	fm_irq_call_stage(fmdev, FM_RDS_FINISH_IDX);
+}
+
+static void fm_irq_handle_rds_finish(struct fmdev *fmdev)
+{
+	fm_irq_call_stage(fmdev, FM_HW_TUNE_OP_ENDED_IDX);
+}
+
+static void fm_irq_handle_tune_op_ended(struct fmdev *fmdev)
+{
+	if (fmdev->irq_info.flag & (FM_FR_EVENT | FM_BL_EVENT) & fmdev->
+	    irq_info.mask) {
+		fmdbg("irq: tune ended/bandlimit reached\n");
+		if (test_and_clear_bit(FM_AF_SWITCH_INPROGRESS, &fmdev->flag)) {
+			fmdev->irq_info.stage = FM_AF_JUMP_RD_FREQ_IDX;
+		} else {
+			complete(&fmdev->maintask_comp);
+			fmdev->irq_info.stage = FM_HW_POWER_ENB_IDX;
+		}
+	} else
+		fmdev->irq_info.stage = FM_HW_POWER_ENB_IDX;
+
+	fm_irq_call(fmdev);
+}
+
+static void fm_irq_handle_power_enb(struct fmdev *fmdev)
+{
+	if (fmdev->irq_info.flag & FM_POW_ENB_EVENT) {
+		fmdbg("irq: Power Enabled/Disabled\n");
+		complete(&fmdev->maintask_comp);
+	}
+
+	fm_irq_call_stage(fmdev, FM_LOW_RSSI_START_IDX);
+}
+
+static void fm_irq_handle_low_rssi_start(struct fmdev *fmdev)
+{
+	if ((fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON) &&
+	    (fmdev->irq_info.flag & FM_LEV_EVENT & fmdev->irq_info.mask) &&
+	    (fmdev->rx.freq != FM_UNDEFINED_FREQ) &&
+	    (fmdev->rx.stat_info.afcache_size != 0)) {
+		fmdbg("irq: rssi level has fallen below threshold level\n");
+
+		/* Disable further low RSSI interrupts */
+		fmdev->irq_info.mask &= ~FM_LEV_EVENT;
+
+		fmdev->rx.afjump_idx = 0;
+		fmdev->rx.freq_before_jump = fmdev->rx.freq;
+		fmdev->irq_info.stage = FM_AF_JUMP_SETPI_IDX;
+	} else {
+		/* Continue next function in interrupt handler table */
+		fmdev->irq_info.stage = FM_SEND_INTMSK_CMD_IDX;
+	}
+
+	fm_irq_call(fmdev);
+}
+
+static void fm_irq_afjump_set_pi(struct fmdev *fmdev)
+{
+	u16 payload;
+
+	/* Set PI code - must be updated if the AF list is not empty */
+	payload = fmdev->rx.stat_info.picode;
+	if (!fm_send_cmd(fmdev, RDS_PI_SET, REG_WR, &payload, sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_SETPI_RESP_IDX);
+}
+
+static void fm_irq_handle_set_pi_resp(struct fmdev *fmdev)
+{
+	fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_SETPI_MASK_IDX);
+}
+
+/*
+ * Set PI mask.
+ * 0xFFFF = Enable PI code matching
+ * 0x0000 = Disable PI code matching
+ */
+static void fm_irq_afjump_set_pimask(struct fmdev *fmdev)
+{
+	u16 payload;
+
+	payload = 0x0000;
+	if (!fm_send_cmd(fmdev, RDS_PI_MASK_SET, REG_WR, &payload, sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_SETPI_MASK_RESP_IDX);
+}
+
+static void fm_irq_handle_set_pimask_resp(struct fmdev *fmdev)
+{
+	fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_SET_AF_FREQ_IDX);
+}
+
+static void fm_irq_afjump_setfreq(struct fmdev *fmdev)
+{
+	u16 frq_index;
+	u16 payload;
+
+	fmdbg("Swtich to %d KHz\n", fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx]);
+	frq_index = (fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx] -
+	     fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
+
+	payload = frq_index;
+	if (!fm_send_cmd(fmdev, AF_FREQ_SET, REG_WR, &payload, sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_SET_AFFREQ_RESP_IDX);
+}
+
+static void fm_irq_handle_setfreq_resp(struct fmdev *fmdev)
+{
+	fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_ENABLE_INT_IDX);
+}
+
+static void fm_irq_afjump_enableint(struct fmdev *fmdev)
+{
+	u16 payload;
+
+	/* Enable FR (tuning operation ended) interrupt */
+	payload = FM_FR_EVENT;
+	if (!fm_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload, sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_AF_JUMP_ENABLE_INT_RESP_IDX);
+}
+
+static void fm_irq_afjump_enableint_resp(struct fmdev *fmdev)
+{
+	fm_irq_common_cmd_resp_helper(fmdev, FM_AF_JUMP_START_AFJUMP_IDX);
+}
+
+static void fm_irq_start_afjump(struct fmdev *fmdev)
+{
+	u16 payload;
+
+	payload = FM_TUNER_AF_JUMP_MODE;
+	if (!fm_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
+			sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_AF_JUMP_HANDLE_START_AFJUMP_RESP_IDX);
+}
+
+static void fm_irq_handle_start_afjump_resp(struct fmdev *fmdev)
+{
+	struct sk_buff *skb;
+
+	if (check_cmdresp_status(fmdev, &skb))
+		return;
+
+	fmdev->irq_info.stage = FM_SEND_FLAG_GETCMD_IDX;
+	set_bit(FM_AF_SWITCH_INPROGRESS, &fmdev->flag);
+	clear_bit(FM_INTTASK_RUNNING, &fmdev->flag);
+}
+
+static void fm_irq_afjump_rd_freq(struct fmdev *fmdev)
+{
+	u16 payload;
+
+	if (!fm_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_AF_JUMP_RD_FREQ_RESP_IDX);
+}
+
+static void fm_irq_afjump_rd_freq_resp(struct fmdev *fmdev)
+{
+	struct sk_buff *skb;
+	u16 read_freq;
+	u32 curr_freq, jumped_freq;
+
+	if (check_cmdresp_status(fmdev, &skb))
+		return;
+
+	/* Skip header info and copy only response data */
+	skb_pull(skb, sizeof(struct fm_event_msg_hdr));
+	memcpy(&read_freq, skb->data, sizeof(read_freq));
+	read_freq = be16_to_cpu(read_freq);
+	curr_freq = fmdev->rx.region.bot_freq + ((u32)read_freq * FM_FREQ_MUL);
+
+	jumped_freq = fmdev->rx.stat_info.af_cache[fmdev->rx.afjump_idx];
+
+	/* If the frequency was changed the jump succeeded */
+	if ((curr_freq != fmdev->rx.freq_before_jump) && (curr_freq == jumped_freq)) {
+		fmdbg("Successfully switched to alternate freq %d\n", curr_freq);
+		fmdev->rx.freq = curr_freq;
+		fm_rx_reset_rds_cache(fmdev);
+
+		/* AF feature is on, enable low level RSSI interrupt */
+		if (fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
+			fmdev->irq_info.mask |= FM_LEV_EVENT;
+
+		fmdev->irq_info.stage = FM_LOW_RSSI_FINISH_IDX;
+	} else {		/* jump to the next freq in the AF list */
+		fmdev->rx.afjump_idx++;
+
+		/* If we reached the end of the list - stop searching */
+		if (fmdev->rx.afjump_idx >= fmdev->rx.stat_info.afcache_size) {
+			fmdbg("AF switch processing failed\n");
+			fmdev->irq_info.stage = FM_LOW_RSSI_FINISH_IDX;
+		} else {	/* AF List is not over - try next one */
+
+			fmdbg("Trying next freq in AF cache\n");
+			fmdev->irq_info.stage = FM_AF_JUMP_SETPI_IDX;
+		}
+	}
+	fm_irq_call(fmdev);
+}
+
+static void fm_irq_handle_low_rssi_finish(struct fmdev *fmdev)
+{
+	fm_irq_call_stage(fmdev, FM_SEND_INTMSK_CMD_IDX);
+}
+
+static void fm_irq_send_intmsk_cmd(struct fmdev *fmdev)
+{
+	u16 payload;
+
+	/* Re-enable FM interrupts */
+	payload = fmdev->irq_info.mask;
+
+	if (!fm_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL))
+		fm_irq_timeout_stage(fmdev, FM_HANDLE_INTMSK_CMD_RESP_IDX);
+}
+
+static void fm_irq_handle_intmsk_cmd_resp(struct fmdev *fmdev)
+{
+	struct sk_buff *skb;
+
+	if (check_cmdresp_status(fmdev, &skb))
+		return;
+	/*
+	 * This is last function in interrupt table to be executed.
+	 * So, reset stage index to 0.
+	 */
+	fmdev->irq_info.stage = FM_SEND_FLAG_GETCMD_IDX;
+
+	/* Start processing any pending interrupt */
+	if (test_and_clear_bit(FM_INTTASK_SCHEDULE_PENDING, &fmdev->flag))
+		fmdev->irq_info.handlers[fmdev->irq_info.stage](fmdev);
+	else
+		clear_bit(FM_INTTASK_RUNNING, &fmdev->flag);
+}
+
+/* Returns availability of RDS data in internel buffer */
+u32 fmc_is_rds_data_available(struct fmdev *fmdev, struct file *file,
+				struct poll_table_struct *pts)
+{
+	poll_wait(file, &fmdev->rx.rds.read_queue, pts);
+	if (fmdev->rx.rds.rd_idx != fmdev->rx.rds.wr_idx)
+		return 0;
+
+	return -EAGAIN;
+}
+
+/* Copies RDS data from internal buffer to user buffer */
+u32 fmc_transfer_rds_from_internal_buff(struct fmdev *fmdev, struct file *file,
+		u8 __user *buf, size_t count)
+{
+	u32 block_count;
+	unsigned long flags;
+	int ret;
+
+	if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx) {
+		if (file->f_flags & O_NONBLOCK)
+			return -EWOULDBLOCK;
+
+		ret = wait_event_interruptible(fmdev->rx.rds.read_queue,
+				(fmdev->rx.rds.wr_idx != fmdev->rx.rds.rd_idx));
+		if (ret)
+			return -EINTR;
+	}
+
+	/* Calculate block count from byte count */
+	count /= 3;
+	block_count = 0;
+	ret = 0;
+
+	spin_lock_irqsave(&fmdev->rds_buff_lock, flags);
+
+	while (block_count < count) {
+		if (fmdev->rx.rds.wr_idx == fmdev->rx.rds.rd_idx)
+			break;
+
+		if (copy_to_user(buf, &fmdev->rx.rds.buff[fmdev->rx.rds.rd_idx],
+					FM_RDS_BLK_SIZE))
+			break;
+
+		fmdev->rx.rds.rd_idx += FM_RDS_BLK_SIZE;
+		if (fmdev->rx.rds.rd_idx >= fmdev->rx.rds.buf_size)
+			fmdev->rx.rds.rd_idx = 0;
+
+		block_count++;
+		buf += FM_RDS_BLK_SIZE;
+		ret += FM_RDS_BLK_SIZE;
+	}
+	spin_unlock_irqrestore(&fmdev->rds_buff_lock, flags);
+	return ret;
+}
+
+u32 fmc_set_freq(struct fmdev *fmdev, u32 freq_to_set)
+{
+	switch (fmdev->curr_fmmode) {
+	case FM_MODE_RX:
+		return fm_rx_set_freq(fmdev, freq_to_set);
+
+	case FM_MODE_TX:
+		return fm_tx_set_freq(fmdev, freq_to_set);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+u32 fmc_get_freq(struct fmdev *fmdev, u32 *cur_tuned_frq)
+{
+	if (fmdev->rx.freq == FM_UNDEFINED_FREQ) {
+		fmerr("RX frequency is not set\n");
+		return -EPERM;
+	}
+	if (cur_tuned_frq == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	switch (fmdev->curr_fmmode) {
+	case FM_MODE_RX:
+		*cur_tuned_frq = fmdev->rx.freq;
+		return 0;
+
+	case FM_MODE_TX:
+		*cur_tuned_frq = 0;	/* TODO : Change this later */
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+
+}
+
+u32 fmc_set_region(struct fmdev *fmdev, u8 region_to_set)
+{
+	switch (fmdev->curr_fmmode) {
+	case FM_MODE_RX:
+		return fm_rx_set_region(fmdev, region_to_set);
+
+	case FM_MODE_TX:
+		return fm_tx_set_region(fmdev, region_to_set);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+u32 fmc_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+{
+	switch (fmdev->curr_fmmode) {
+	case FM_MODE_RX:
+		return fm_rx_set_mute_mode(fmdev, mute_mode_toset);
+
+	case FM_MODE_TX:
+		return fm_tx_set_mute_mode(fmdev, mute_mode_toset);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+u32 fmc_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+{
+	switch (fmdev->curr_fmmode) {
+	case FM_MODE_RX:
+		return fm_rx_set_stereo_mono(fmdev, mode);
+
+	case FM_MODE_TX:
+		return fm_tx_set_stereo_mono(fmdev, mode);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+u32 fmc_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+{
+	switch (fmdev->curr_fmmode) {
+	case FM_MODE_RX:
+		return fm_rx_set_rds_mode(fmdev, rds_en_dis);
+
+	case FM_MODE_TX:
+		return fm_tx_set_rds_mode(fmdev, rds_en_dis);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+/* Sends power off command to the chip */
+static u32 fm_power_down(struct fmdev *fmdev)
+{
+	u16 payload;
+	u32 ret;
+
+	if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
+		fmerr("FM core is not ready\n");
+		return -EPERM;
+	}
+	if (fmdev->curr_fmmode == FM_MODE_OFF) {
+		fmdbg("FM chip is already in OFF state\n");
+		return 0;
+	}
+
+	payload = 0x0;
+	ret = fmc_send_cmd(fmdev, FM_POWER_MODE, REG_WR, &payload,
+		sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return fmc_release(fmdev);
+}
+
+/* Reads init command from FM firmware file and loads to the chip */
+static u32 fm_download_firmware(struct fmdev *fmdev, const u8 *fw_name)
+{
+	const struct firmware *fw_entry;
+	struct bts_header *fw_header;
+	struct bts_action *action;
+	struct bts_action_delay *delay;
+	u8 *fw_data;
+	int ret, fw_len, cmd_cnt;
+
+	cmd_cnt = 0;
+	set_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);
+
+	ret = reject_firmware(&fw_entry, fw_name,
+				&fmdev->radio_dev->dev);
+	if (ret < 0) {
+		fmerr("Unable to read firmware(%s) content\n", fw_name);
+		return ret;
+	}
+	fmdbg("Firmware(%s) length : %d bytes\n", fw_name, fw_entry->size);
+
+	fw_data = (void *)fw_entry->data;
+	fw_len = fw_entry->size;
+
+	fw_header = (struct bts_header *)fw_data;
+	if (fw_header->magic != FM_FW_FILE_HEADER_MAGIC) {
+		fmerr("%s not a legal TI firmware file\n", fw_name);
+		ret = -EINVAL;
+		goto rel_fw;
+	}
+	fmdbg("FW(%s) magic number : 0x%x\n", fw_name, fw_header->magic);
+
+	/* Skip file header info , we already verified it */
+	fw_data += sizeof(struct bts_header);
+	fw_len -= sizeof(struct bts_header);
+
+	while (fw_data && fw_len > 0) {
+		action = (struct bts_action *)fw_data;
+
+		switch (action->type) {
+		case ACTION_SEND_COMMAND:	/* Send */
+			if (fmc_send_cmd(fmdev, 0, 0, action->data,
+						action->size, NULL, NULL))
+				goto rel_fw;
+
+			cmd_cnt++;
+			break;
+
+		case ACTION_DELAY:	/* Delay */
+			delay = (struct bts_action_delay *)action->data;
+			mdelay(delay->msec);
+			break;
+		}
+
+		fw_data += (sizeof(struct bts_action) + (action->size));
+		fw_len -= (sizeof(struct bts_action) + (action->size));
+	}
+	fmdbg("Firmware commands(%d) loaded to chip\n", cmd_cnt);
+rel_fw:
+	release_firmware(fw_entry);
+	clear_bit(FM_FW_DW_INPROGRESS, &fmdev->flag);
+
+	return ret;
+}
+
+/* Loads default RX configuration to the chip */
+static u32 load_default_rx_configuration(struct fmdev *fmdev)
+{
+	int ret;
+
+	ret = fm_rx_set_volume(fmdev, FM_DEFAULT_RX_VOLUME);
+	if (ret < 0)
+		return ret;
+
+	return fm_rx_set_rssi_threshold(fmdev, FM_DEFAULT_RSSI_THRESHOLD);
+}
+
+/* Does FM power on sequence */
+static u32 fm_power_up(struct fmdev *fmdev, u8 mode)
+{
+	u16 payload, asic_id, asic_ver;
+	int resp_len, ret;
+	u8 fw_name[50];
+
+	if (mode >= FM_MODE_ENTRY_MAX) {
+		fmerr("Invalid firmware download option\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Initialize FM common module. FM GPIO toggling is
+	 * taken care in Shared Transport driver.
+	 */
+	ret = fmc_prepare(fmdev);
+	if (ret < 0) {
+		fmerr("Unable to prepare FM Common\n");
+		return ret;
+	}
+
+	payload = FM_ENABLE;
+	if (fmc_send_cmd(fmdev, FM_POWER_MODE, REG_WR, &payload,
+			sizeof(payload), NULL, NULL))
+		goto rel;
+
+	/* Allow the chip to settle down in Channel-8 mode */
+	msleep(20);
+
+	if (fmc_send_cmd(fmdev, ASIC_ID_GET, REG_RD, NULL,
+			sizeof(asic_id), &asic_id, &resp_len))
+		goto rel;
+
+	if (fmc_send_cmd(fmdev, ASIC_VER_GET, REG_RD, NULL,
+			sizeof(asic_ver), &asic_ver, &resp_len))
+		goto rel;
+
+	fmdbg("ASIC ID: 0x%x , ASIC Version: %d\n",
+		be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
+
+	sprintf(fw_name, "/*(DEBLOBBED)*/", FM_FMC_FW_FILE_START,
+		be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
+
+	ret = fm_download_firmware(fmdev, fw_name);
+	if (ret < 0) {
+		fmdbg("Failed to download firmware file %s\n", fw_name);
+		goto rel;
+	}
+	sprintf(fw_name, "/*(DEBLOBBED)*/", (mode == FM_MODE_RX) ?
+			FM_RX_FW_FILE_START : FM_TX_FW_FILE_START,
+			be16_to_cpu(asic_id), be16_to_cpu(asic_ver));
+
+	ret = fm_download_firmware(fmdev, fw_name);
+	if (ret < 0) {
+		fmdbg("Failed to download firmware file %s\n", fw_name);
+		goto rel;
+	} else
+		return ret;
+rel:
+	return fmc_release(fmdev);
+}
+
+/* Set FM Modes(TX, RX, OFF) */
+u32 fmc_set_mode(struct fmdev *fmdev, u8 fm_mode)
+{
+	int ret = 0;
+
+	if (fm_mode >= FM_MODE_ENTRY_MAX) {
+		fmerr("Invalid FM mode\n");
+		return -EINVAL;
+	}
+	if (fmdev->curr_fmmode == fm_mode) {
+		fmdbg("Already fm is in mode(%d)\n", fm_mode);
+		return ret;
+	}
+
+	switch (fm_mode) {
+	case FM_MODE_OFF:	/* OFF Mode */
+		ret = fm_power_down(fmdev);
+		if (ret < 0) {
+			fmerr("Failed to set OFF mode\n");
+			return ret;
+		}
+		break;
+
+	case FM_MODE_TX:	/* TX Mode */
+	case FM_MODE_RX:	/* RX Mode */
+		/* Power down before switching to TX or RX mode */
+		if (fmdev->curr_fmmode != FM_MODE_OFF) {
+			ret = fm_power_down(fmdev);
+			if (ret < 0) {
+				fmerr("Failed to set OFF mode\n");
+				return ret;
+			}
+			msleep(30);
+		}
+		ret = fm_power_up(fmdev, fm_mode);
+		if (ret < 0) {
+			fmerr("Failed to load firmware\n");
+			return ret;
+		}
+	}
+	fmdev->curr_fmmode = fm_mode;
+
+	/* Set default configuration */
+	if (fmdev->curr_fmmode == FM_MODE_RX) {
+		fmdbg("Loading default rx configuration..\n");
+		ret = load_default_rx_configuration(fmdev);
+		if (ret < 0)
+			fmerr("Failed to load default values\n");
+	}
+
+	return ret;
+}
+
+/* Returns current FM mode (TX, RX, OFF) */
+u32 fmc_get_mode(struct fmdev *fmdev, u8 *fmmode)
+{
+	if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
+		fmerr("FM core is not ready\n");
+		return -EPERM;
+	}
+	if (fmmode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*fmmode = fmdev->curr_fmmode;
+	return 0;
+}
+
+/* Called by ST layer when FM packet is available */
+static long fm_st_receive(void *arg, struct sk_buff *skb)
+{
+	struct fmdev *fmdev;
+
+	fmdev = (struct fmdev *)arg;
+
+	if (skb == NULL) {
+		fmerr("Invalid SKB received from ST\n");
+		return -EFAULT;
+	}
+
+	if (skb->cb[0] != FM_PKT_LOGICAL_CHAN_NUMBER) {
+		fmerr("Received SKB (%p) is not FM Channel 8 pkt\n", skb);
+		return -EINVAL;
+	}
+
+	memcpy(skb_push(skb, 1), &skb->cb[0], 1);
+	skb_queue_tail(&fmdev->rx_q, skb);
+	tasklet_schedule(&fmdev->rx_task);
+
+	return 0;
+}
+
+/*
+ * Called by ST layer to indicate protocol registration completion
+ * status.
+ */
+static void fm_st_reg_comp_cb(void *arg, char data)
+{
+	struct fmdev *fmdev;
+
+	fmdev = (struct fmdev *)arg;
+	fmdev->streg_cbdata = data;
+	complete(&wait_for_fmdrv_reg_comp);
+}
+
+/*
+ * This function will be called from FM V4L2 open function.
+ * Register with ST driver and initialize driver data.
+ */
+u32 fmc_prepare(struct fmdev *fmdev)
+{
+	static struct st_proto_s fm_st_proto;
+	u32 ret;
+
+	if (test_bit(FM_CORE_READY, &fmdev->flag)) {
+		fmdbg("FM Core is already up\n");
+		return 0;
+	}
+
+	memset(&fm_st_proto, 0, sizeof(fm_st_proto));
+	fm_st_proto.recv = fm_st_receive;
+	fm_st_proto.match_packet = NULL;
+	fm_st_proto.reg_complete_cb = fm_st_reg_comp_cb;
+	fm_st_proto.write = NULL; /* TI ST driver will fill write pointer */
+	fm_st_proto.priv_data = fmdev;
+	fm_st_proto.chnl_id = 0x08;
+	fm_st_proto.max_frame_size = 0xff;
+	fm_st_proto.hdr_len = 1;
+	fm_st_proto.offset_len_in_hdr = 0;
+	fm_st_proto.len_size = 1;
+	fm_st_proto.reserve = 1;
+
+	ret = st_register(&fm_st_proto);
+	if (ret == -EINPROGRESS) {
+		init_completion(&wait_for_fmdrv_reg_comp);
+		fmdev->streg_cbdata = -EINPROGRESS;
+		fmdbg("%s waiting for ST reg completion signal\n", __func__);
+
+		ret = wait_for_completion_timeout(&wait_for_fmdrv_reg_comp,
+				FM_ST_REG_TIMEOUT);
+
+		if (!ret) {
+			fmerr("Timeout(%d sec), didn't get reg "
+					"completion signal from ST\n",
+					jiffies_to_msecs(FM_ST_REG_TIMEOUT) / 1000);
+			return -ETIMEDOUT;
+		}
+		if (fmdev->streg_cbdata != 0) {
+			fmerr("ST reg comp CB called with error "
+					"status %d\n", fmdev->streg_cbdata);
+			return -EAGAIN;
+		}
+
+		ret = 0;
+	} else if (ret == -1) {
+		fmerr("st_register failed %d\n", ret);
+		return -EAGAIN;
+	}
+
+	if (fm_st_proto.write != NULL) {
+		g_st_write = fm_st_proto.write;
+	} else {
+		fmerr("Failed to get ST write func pointer\n");
+		ret = st_unregister(&fm_st_proto);
+		if (ret < 0)
+			fmerr("st_unregister failed %d\n", ret);
+		return -EAGAIN;
+	}
+
+	spin_lock_init(&fmdev->rds_buff_lock);
+	spin_lock_init(&fmdev->resp_skb_lock);
+
+	/* Initialize TX queue and TX tasklet */
+	skb_queue_head_init(&fmdev->tx_q);
+	tasklet_init(&fmdev->tx_task, send_tasklet, (unsigned long)fmdev);
+
+	/* Initialize RX Queue and RX tasklet */
+	skb_queue_head_init(&fmdev->rx_q);
+	tasklet_init(&fmdev->rx_task, recv_tasklet, (unsigned long)fmdev);
+
+	fmdev->irq_info.stage = 0;
+	atomic_set(&fmdev->tx_cnt, 1);
+	fmdev->resp_comp = NULL;
+
+	init_timer(&fmdev->irq_info.timer);
+	fmdev->irq_info.timer.function = &int_timeout_handler;
+	fmdev->irq_info.timer.data = (unsigned long)fmdev;
+	/*TODO: add FM_STIC_EVENT later */
+	fmdev->irq_info.mask = FM_MAL_EVENT;
+
+	/* Region info */
+	memcpy(&fmdev->rx.region, &region_configs[default_radio_region],
+			sizeof(struct region_info));
+
+	fmdev->rx.mute_mode = FM_MUTE_OFF;
+	fmdev->rx.rf_depend_mute = FM_RX_RF_DEPENDENT_MUTE_OFF;
+	fmdev->rx.rds.flag = FM_RDS_DISABLE;
+	fmdev->rx.freq = FM_UNDEFINED_FREQ;
+	fmdev->rx.rds_mode = FM_RDS_SYSTEM_RDS;
+	fmdev->rx.af_mode = FM_RX_RDS_AF_SWITCH_MODE_OFF;
+	fmdev->irq_info.retry = 0;
+
+	fm_rx_reset_rds_cache(fmdev);
+	init_waitqueue_head(&fmdev->rx.rds.read_queue);
+
+	fm_rx_reset_station_info(fmdev);
+	set_bit(FM_CORE_READY, &fmdev->flag);
+
+	return ret;
+}
+
+/*
+ * This function will be called from FM V4L2 release function.
+ * Unregister from ST driver.
+ */
+u32 fmc_release(struct fmdev *fmdev)
+{
+	static struct st_proto_s fm_st_proto;
+	u32 ret;
+
+	if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
+		fmdbg("FM Core is already down\n");
+		return 0;
+	}
+	/* Service pending read */
+	wake_up_interruptible(&fmdev->rx.rds.read_queue);
+
+	tasklet_kill(&fmdev->tx_task);
+	tasklet_kill(&fmdev->rx_task);
+
+	skb_queue_purge(&fmdev->tx_q);
+	skb_queue_purge(&fmdev->rx_q);
+
+	fmdev->resp_comp = NULL;
+	fmdev->rx.freq = 0;
+
+	memset(&fm_st_proto, 0, sizeof(fm_st_proto));
+	fm_st_proto.chnl_id = 0x08;
+
+	ret = st_unregister(&fm_st_proto);
+
+	if (ret < 0)
+		fmerr("Failed to de-register FM from ST %d\n", ret);
+	else
+		fmdbg("Successfully unregistered from ST\n");
+
+	clear_bit(FM_CORE_READY, &fmdev->flag);
+	return ret;
+}
+
+/*
+ * Module init function. Ask FM V4L module to register video device.
+ * Allocate memory for FM driver context and RX RDS buffer.
+ */
+static int __init fm_drv_init(void)
+{
+	struct fmdev *fmdev = NULL;
+	u32 ret = -ENOMEM;
+
+	fmdbg("FM driver version %s\n", FM_DRV_VERSION);
+
+	fmdev = kzalloc(sizeof(struct fmdev), GFP_KERNEL);
+	if (NULL == fmdev) {
+		fmerr("Can't allocate operation structure memory\n");
+		return ret;
+	}
+	fmdev->rx.rds.buf_size = default_rds_buf * FM_RDS_BLK_SIZE;
+	fmdev->rx.rds.buff = kzalloc(fmdev->rx.rds.buf_size, GFP_KERNEL);
+	if (NULL == fmdev->rx.rds.buff) {
+		fmerr("Can't allocate rds ring buffer\n");
+		goto rel_dev;
+	}
+
+	ret = fm_v4l2_init_video_device(fmdev, radio_nr);
+	if (ret < 0)
+		goto rel_rdsbuf;
+
+	fmdev->irq_info.handlers = int_handler_table;
+	fmdev->curr_fmmode = FM_MODE_OFF;
+	fmdev->tx_data.pwr_lvl = FM_PWR_LVL_DEF;
+	fmdev->tx_data.preemph = FM_TX_PREEMPH_50US;
+	return ret;
+
+rel_rdsbuf:
+	kfree(fmdev->rx.rds.buff);
+rel_dev:
+	kfree(fmdev);
+
+	return ret;
+}
+
+/* Module exit function. Ask FM V4L module to unregister video device */
+static void __exit fm_drv_exit(void)
+{
+	struct fmdev *fmdev = NULL;
+
+	fmdev = fm_v4l2_deinit_video_device();
+	if (fmdev != NULL) {
+		kfree(fmdev->rx.rds.buff);
+		kfree(fmdev);
+	}
+}
+
+module_init(fm_drv_init);
+module_exit(fm_drv_exit);
+
+/* ------------- Module Info ------------- */
+MODULE_AUTHOR("Manjunatha Halli <manjunatha_halli@ti.com>");
+MODULE_DESCRIPTION("FM Driver for TI's Connectivity chip. " FM_DRV_VERSION);
+MODULE_VERSION(FM_DRV_VERSION);
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_common.h linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_common.h
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_common.h	2012-03-24 03:29:45.000000000 -0400
@@ -0,0 +1,402 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *  FM Common module header file
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *
+ *  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 _FMDRV_COMMON_H
+#define _FMDRV_COMMON_H
+
+#define FM_ST_REG_TIMEOUT   msecs_to_jiffies(6000)	/* 6 sec */
+#define FM_PKT_LOGICAL_CHAN_NUMBER  0x08   /* Logical channel 8 */
+
+#define REG_RD       0x1
+#define REG_WR      0x0
+
+struct fm_reg_table {
+	u8 opcode;
+	u8 type;
+	u8 *name;
+};
+
+#define STEREO_GET               0
+#define RSSI_LVL_GET             1
+#define IF_COUNT_GET             2
+#define FLAG_GET                 3
+#define RDS_SYNC_GET             4
+#define RDS_DATA_GET             5
+#define FREQ_SET                 10
+#define AF_FREQ_SET              11
+#define MOST_MODE_SET            12
+#define MOST_BLEND_SET           13
+#define DEMPH_MODE_SET           14
+#define SEARCH_LVL_SET           15
+#define BAND_SET                 16
+#define MUTE_STATUS_SET          17
+#define RDS_PAUSE_LVL_SET        18
+#define RDS_PAUSE_DUR_SET        19
+#define RDS_MEM_SET              20
+#define RDS_BLK_B_SET            21
+#define RDS_MSK_B_SET            22
+#define RDS_PI_MASK_SET          23
+#define RDS_PI_SET               24
+#define RDS_SYSTEM_SET           25
+#define INT_MASK_SET             26
+#define SEARCH_DIR_SET           27
+#define VOLUME_SET               28
+#define AUDIO_ENABLE_SET         29
+#define PCM_MODE_SET             30
+#define I2S_MODE_CONFIG_SET      31
+#define POWER_SET                32
+#define INTX_CONFIG_SET          33
+#define PULL_EN_SET              34
+#define HILO_SET                 35
+#define SWITCH2FREF              36
+#define FREQ_DRIFT_REPORT        37
+
+#define PCE_GET                  40
+#define FIRM_VER_GET             41
+#define ASIC_VER_GET             42
+#define ASIC_ID_GET              43
+#define MAN_ID_GET               44
+#define TUNER_MODE_SET           45
+#define STOP_SEARCH              46
+#define RDS_CNTRL_SET            47
+
+#define WRITE_HARDWARE_REG       100
+#define CODE_DOWNLOAD            101
+#define RESET                    102
+
+#define FM_POWER_MODE            254
+#define FM_INTERRUPT             255
+
+/* Transmitter API */
+
+#define CHANL_SET                55
+#define CHANL_BW_SET		56
+#define REF_SET                  57
+#define POWER_ENB_SET            90
+#define POWER_ATT_SET            58
+#define POWER_LEV_SET            59
+#define AUDIO_DEV_SET            60
+#define PILOT_DEV_SET            61
+#define RDS_DEV_SET              62
+#define TX_BAND_SET              65
+#define PUPD_SET                 91
+#define AUDIO_IO_SET             63
+#define PREMPH_SET               64
+#define MONO_SET                 66
+#define MUTE                     92
+#define MPX_LMT_ENABLE           67
+#define PI_SET                   93
+#define ECC_SET                  69
+#define PTY                      70
+#define AF                       71
+#define DISPLAY_MODE             74
+#define RDS_REP_SET              77
+#define RDS_CONFIG_DATA_SET      98
+#define RDS_DATA_SET             99
+#define RDS_DATA_ENB             94
+#define TA_SET                   78
+#define TP_SET                   79
+#define DI_SET                   80
+#define MS_SET                   81
+#define PS_SCROLL_SPEED          82
+#define TX_AUDIO_LEVEL_TEST      96
+#define TX_AUDIO_LEVEL_TEST_THRESHOLD    73
+#define TX_AUDIO_INPUT_LEVEL_RANGE_SET   54
+#define RX_ANTENNA_SELECT        87
+#define I2C_DEV_ADDR_SET         86
+#define REF_ERR_CALIB_PARAM_SET          88
+#define REF_ERR_CALIB_PERIODICITY_SET    89
+#define SOC_INT_TRIGGER                  52
+#define SOC_AUDIO_PATH_SET               83
+#define SOC_PCMI_OVERRIDE                84
+#define SOC_I2S_OVERRIDE         85
+#define RSSI_BLOCK_SCAN_FREQ_SET 95
+#define RSSI_BLOCK_SCAN_START    97
+#define RSSI_BLOCK_SCAN_DATA_GET  5
+#define READ_FMANT_TUNE_VALUE            104
+
+/* SKB helpers */
+struct fm_skb_cb {
+	__u8 fm_op;
+	struct completion *completion;
+};
+
+#define fm_cb(skb) ((struct fm_skb_cb *)(skb->cb))
+
+/* FM Channel-8 command message format */
+struct fm_cmd_msg_hdr {
+	__u8 hdr;		/* Logical Channel-8 */
+	__u8 len;		/* Number of bytes follows */
+	__u8 op;		/* FM Opcode */
+	__u8 rd_wr;		/* Read/Write command */
+	__u8 dlen;		/* Length of payload */
+} __attribute__ ((packed));
+
+#define FM_CMD_MSG_HDR_SIZE    5	/* sizeof(struct fm_cmd_msg_hdr) */
+
+/* FM Channel-8 event messgage format */
+struct fm_event_msg_hdr {
+	__u8 header;		/* Logical Channel-8 */
+	__u8 len;		/* Number of bytes follows */
+	__u8 status;		/* Event status */
+	__u8 num_fm_hci_cmds;	/* Number of pkts the host allowed to send */
+	__u8 op;		/* FM Opcode */
+	__u8 rd_wr;		/* Read/Write command */
+	__u8 dlen;		/* Length of payload */
+} __attribute__ ((packed));
+
+#define FM_EVT_MSG_HDR_SIZE     7	/* sizeof(struct fm_event_msg_hdr) */
+
+/* TI's magic number in firmware file */
+#define FM_FW_FILE_HEADER_MAGIC	     0x42535442
+
+#define FM_ENABLE   1
+#define FM_DISABLE  0
+
+/* FLAG_GET register bits */
+#define FM_FR_EVENT		(1 << 0)
+#define FM_BL_EVENT		(1 << 1)
+#define FM_RDS_EVENT		(1 << 2)
+#define FM_BBLK_EVENT		(1 << 3)
+#define FM_LSYNC_EVENT		(1 << 4)
+#define FM_LEV_EVENT		(1 << 5)
+#define FM_IFFR_EVENT		(1 << 6)
+#define FM_PI_EVENT		(1 << 7)
+#define FM_PD_EVENT		(1 << 8)
+#define FM_STIC_EVENT		(1 << 9)
+#define FM_MAL_EVENT		(1 << 10)
+#define FM_POW_ENB_EVENT	(1 << 11)
+
+/*
+ * Firmware files of FM. ASIC ID and ASIC version will be appened to this,
+ * later.
+ */
+#define FM_FMC_FW_FILE_START      ("/*(DEBLOBBED)*/")
+#define FM_RX_FW_FILE_START       ("/*(DEBLOBBED)*/")
+#define FM_TX_FW_FILE_START       ("/*(DEBLOBBED)*/")
+
+#define FM_UNDEFINED_FREQ		   0xFFFFFFFF
+
+/* Band types */
+#define FM_BAND_EUROPE_US	0
+#define FM_BAND_JAPAN		1
+
+/* Seek directions */
+#define FM_SEARCH_DIRECTION_DOWN	0
+#define FM_SEARCH_DIRECTION_UP		1
+
+/* Tunner modes */
+#define FM_TUNER_STOP_SEARCH_MODE	0
+#define FM_TUNER_PRESET_MODE		1
+#define FM_TUNER_AUTONOMOUS_SEARCH_MODE	2
+#define FM_TUNER_AF_JUMP_MODE		3
+
+/* Min and Max volume */
+#define FM_RX_VOLUME_MIN	0
+#define FM_RX_VOLUME_MAX	70
+
+/* Volume gain step */
+#define FM_RX_VOLUME_GAIN_STEP	0x370
+
+/* Mute modes */
+#define	FM_MUTE_ON		0
+#define FM_MUTE_OFF		1
+#define	FM_MUTE_ATTENUATE	2
+
+#define FM_RX_UNMUTE_MODE		0x00
+#define FM_RX_RF_DEP_MODE		0x01
+#define FM_RX_AC_MUTE_MODE		0x02
+#define FM_RX_HARD_MUTE_LEFT_MODE	0x04
+#define FM_RX_HARD_MUTE_RIGHT_MODE	0x08
+#define FM_RX_SOFT_MUTE_FORCE_MODE	0x10
+
+/* RF dependent mute mode */
+#define FM_RX_RF_DEPENDENT_MUTE_ON	1
+#define FM_RX_RF_DEPENDENT_MUTE_OFF	0
+
+/* RSSI threshold min and max */
+#define FM_RX_RSSI_THRESHOLD_MIN	-128
+#define FM_RX_RSSI_THRESHOLD_MAX	127
+
+/* Stereo/Mono mode */
+#define FM_STEREO_MODE		0
+#define FM_MONO_MODE		1
+#define FM_STEREO_SOFT_BLEND	1
+
+/* FM RX De-emphasis filter modes */
+#define FM_RX_EMPHASIS_FILTER_50_USEC	0
+#define FM_RX_EMPHASIS_FILTER_75_USEC	1
+
+/* FM RDS modes */
+#define FM_RDS_DISABLE	0
+#define FM_RDS_ENABLE	1
+
+#define FM_NO_PI_CODE	0
+
+/* FM and RX RDS block enable/disable  */
+#define FM_RX_PWR_SET_FM_ON_RDS_OFF		0x1
+#define FM_RX_PWR_SET_FM_AND_RDS_BLK_ON		0x3
+#define FM_RX_PWR_SET_FM_AND_RDS_BLK_OFF	0x0
+
+/* RX RDS */
+#define FM_RX_RDS_FLUSH_FIFO		0x1
+#define FM_RX_RDS_FIFO_THRESHOLD	64	/* tuples */
+#define FM_RDS_BLK_SIZE		3	/* 3 bytes */
+
+/* RDS block types */
+#define FM_RDS_BLOCK_A		0
+#define FM_RDS_BLOCK_B		1
+#define FM_RDS_BLOCK_C		2
+#define FM_RDS_BLOCK_Ctag	3
+#define FM_RDS_BLOCK_D		4
+#define FM_RDS_BLOCK_E		5
+
+#define FM_RDS_BLK_IDX_A		0
+#define FM_RDS_BLK_IDX_B		1
+#define FM_RDS_BLK_IDX_C		2
+#define FM_RDS_BLK_IDX_D		3
+#define FM_RDS_BLK_IDX_UNKNOWN	0xF0
+
+#define FM_RDS_STATUS_ERR_MASK	0x18
+
+/*
+ * Represents an RDS group type & version.
+ * There are 15 groups, each group has 2 versions: A and B.
+ */
+#define FM_RDS_GROUP_TYPE_MASK_0A	    ((unsigned long)1<<0)
+#define FM_RDS_GROUP_TYPE_MASK_0B	    ((unsigned long)1<<1)
+#define FM_RDS_GROUP_TYPE_MASK_1A	    ((unsigned long)1<<2)
+#define FM_RDS_GROUP_TYPE_MASK_1B	    ((unsigned long)1<<3)
+#define FM_RDS_GROUP_TYPE_MASK_2A	    ((unsigned long)1<<4)
+#define FM_RDS_GROUP_TYPE_MASK_2B	    ((unsigned long)1<<5)
+#define FM_RDS_GROUP_TYPE_MASK_3A	    ((unsigned long)1<<6)
+#define FM_RDS_GROUP_TYPE_MASK_3B           ((unsigned long)1<<7)
+#define FM_RDS_GROUP_TYPE_MASK_4A	    ((unsigned long)1<<8)
+#define FM_RDS_GROUP_TYPE_MASK_4B	    ((unsigned long)1<<9)
+#define FM_RDS_GROUP_TYPE_MASK_5A	    ((unsigned long)1<<10)
+#define FM_RDS_GROUP_TYPE_MASK_5B	    ((unsigned long)1<<11)
+#define FM_RDS_GROUP_TYPE_MASK_6A	    ((unsigned long)1<<12)
+#define FM_RDS_GROUP_TYPE_MASK_6B	    ((unsigned long)1<<13)
+#define FM_RDS_GROUP_TYPE_MASK_7A	    ((unsigned long)1<<14)
+#define FM_RDS_GROUP_TYPE_MASK_7B	    ((unsigned long)1<<15)
+#define FM_RDS_GROUP_TYPE_MASK_8A           ((unsigned long)1<<16)
+#define FM_RDS_GROUP_TYPE_MASK_8B	    ((unsigned long)1<<17)
+#define FM_RDS_GROUP_TYPE_MASK_9A	    ((unsigned long)1<<18)
+#define FM_RDS_GROUP_TYPE_MASK_9B	    ((unsigned long)1<<19)
+#define FM_RDS_GROUP_TYPE_MASK_10A	    ((unsigned long)1<<20)
+#define FM_RDS_GROUP_TYPE_MASK_10B	    ((unsigned long)1<<21)
+#define FM_RDS_GROUP_TYPE_MASK_11A	    ((unsigned long)1<<22)
+#define FM_RDS_GROUP_TYPE_MASK_11B	    ((unsigned long)1<<23)
+#define FM_RDS_GROUP_TYPE_MASK_12A	    ((unsigned long)1<<24)
+#define FM_RDS_GROUP_TYPE_MASK_12B	    ((unsigned long)1<<25)
+#define FM_RDS_GROUP_TYPE_MASK_13A	    ((unsigned long)1<<26)
+#define FM_RDS_GROUP_TYPE_MASK_13B	    ((unsigned long)1<<27)
+#define FM_RDS_GROUP_TYPE_MASK_14A	    ((unsigned long)1<<28)
+#define FM_RDS_GROUP_TYPE_MASK_14B	    ((unsigned long)1<<29)
+#define FM_RDS_GROUP_TYPE_MASK_15A	    ((unsigned long)1<<30)
+#define FM_RDS_GROUP_TYPE_MASK_15B	    ((unsigned long)1<<31)
+
+/* RX Alternate Frequency info */
+#define FM_RDS_MIN_AF		          1
+#define FM_RDS_MAX_AF		        204
+#define FM_RDS_MAX_AF_JAPAN	        140
+#define FM_RDS_1_AF_FOLLOWS	        225
+#define FM_RDS_25_AF_FOLLOWS	        249
+
+/* RDS system type (RDS/RBDS) */
+#define FM_RDS_SYSTEM_RDS		0
+#define FM_RDS_SYSTEM_RBDS		1
+
+/* AF on/off */
+#define FM_RX_RDS_AF_SWITCH_MODE_ON	1
+#define FM_RX_RDS_AF_SWITCH_MODE_OFF	0
+
+/* Retry count when interrupt process goes wrong */
+#define FM_IRQ_TIMEOUT_RETRY_MAX	5	/* 5 times */
+
+/* Audio IO set values */
+#define FM_RX_AUDIO_ENABLE_I2S	0x01
+#define FM_RX_AUDIO_ENABLE_ANALOG	0x02
+#define FM_RX_AUDIO_ENABLE_I2S_AND_ANALOG	0x03
+#define FM_RX_AUDIO_ENABLE_DISABLE	0x00
+
+/* HI/LO set values */
+#define FM_RX_IFFREQ_TO_HI_SIDE		0x0
+#define FM_RX_IFFREQ_TO_LO_SIDE		0x1
+#define FM_RX_IFFREQ_HILO_AUTOMATIC	0x2
+
+/*
+ * Default RX mode configuration. Chip will be configured
+ * with this default values after loading RX firmware.
+ */
+#define FM_DEFAULT_RX_VOLUME		10
+#define FM_DEFAULT_RSSI_THRESHOLD	3
+
+/* Range for TX power level in units for dB/uV */
+#define FM_PWR_LVL_LOW			91
+#define FM_PWR_LVL_HIGH			122
+
+/* Chip specific default TX power level value */
+#define FM_PWR_LVL_DEF			4
+
+/* FM TX Pre-emphasis filter values */
+#define FM_TX_PREEMPH_OFF		1
+#define FM_TX_PREEMPH_50US		0
+#define FM_TX_PREEMPH_75US		2
+
+/* FM TX antenna impedance values */
+#define FM_TX_ANT_IMP_50		0
+#define FM_TX_ANT_IMP_200		1
+#define FM_TX_ANT_IMP_500		2
+
+/* Functions exported by FM common sub-module */
+u32 fmc_prepare(struct fmdev *);
+u32 fmc_release(struct fmdev *);
+
+void fmc_update_region_info(struct fmdev *, u8);
+u32 fmc_send_cmd(struct fmdev *, u8, u16,
+				void *, unsigned int, void *, int *);
+u32 fmc_is_rds_data_available(struct fmdev *, struct file *,
+				struct poll_table_struct *);
+u32 fmc_transfer_rds_from_internal_buff(struct fmdev *, struct file *,
+					u8 __user *, size_t);
+
+u32 fmc_set_freq(struct fmdev *, u32);
+u32 fmc_set_mode(struct fmdev *, u8);
+u32 fmc_set_region(struct fmdev *, u8);
+u32 fmc_set_mute_mode(struct fmdev *, u8);
+u32 fmc_set_stereo_mono(struct fmdev *, u16);
+u32 fmc_set_rds_mode(struct fmdev *, u8);
+
+u32 fmc_get_freq(struct fmdev *, u32 *);
+u32 fmc_get_region(struct fmdev *, u8 *);
+u32 fmc_get_mode(struct fmdev *, u8 *);
+
+/*
+ * channel spacing
+ */
+#define FM_CHANNEL_SPACING_50KHZ 1
+#define FM_CHANNEL_SPACING_100KHZ 2
+#define FM_CHANNEL_SPACING_200KHZ 4
+#define FM_FREQ_MUL 50
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv.h linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv.h
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,244 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *
+ *  Common header for all FM driver sub-modules.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *
+ *  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 _FM_DRV_H
+#define _FM_DRV_H
+
+#include <linux/skbuff.h>
+#include <linux/interrupt.h>
+#include <sound/core.h>
+#include <sound/initval.h>
+#include <linux/timer.h>
+#include <linux/version.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+
+#define FM_DRV_VERSION            "0.10"
+/* Should match with FM_DRV_VERSION */
+#define FM_DRV_RADIO_VERSION      KERNEL_VERSION(0, 0, 1)
+#define FM_DRV_NAME               "ti_fmdrv"
+#define FM_DRV_CARD_SHORT_NAME    "TI FM Radio"
+#define FM_DRV_CARD_LONG_NAME     "Texas Instruments FM Radio"
+
+/* Flag info */
+#define FM_INTTASK_RUNNING            0
+#define FM_INTTASK_SCHEDULE_PENDING   1
+#define FM_FW_DW_INPROGRESS     2
+#define FM_CORE_READY                 3
+#define FM_CORE_TRANSPORT_READY       4
+#define FM_AF_SWITCH_INPROGRESS	      5
+#define FM_CORE_TX_XMITING	      6
+
+#define FM_TUNE_COMPLETE	      0x1
+#define FM_BAND_LIMIT		      0x2
+
+#define FM_DRV_TX_TIMEOUT      (5*HZ)	/* 5 seconds */
+#define FM_DRV_RX_SEEK_TIMEOUT (20*HZ)	/* 20 seconds */
+
+#define NO_OF_ENTRIES_IN_ARRAY(array) (sizeof(array) / sizeof(array[0]))
+
+#define fmerr(format, ...) \
+	printk(KERN_ERR "fmdrv: " format, ## __VA_ARGS__)
+#define fmwarn(format, ...) \
+	printk(KERN_WARNING "fmdrv: " format, ##__VA_ARGS__)
+#ifdef DEBUG
+#define fmdbg(format, ...) \
+	printk(KERN_DEBUG "fmdrv: " format, ## __VA_ARGS__)
+#else /* DEBUG */
+#define fmdbg(format, ...)
+#endif
+enum {
+	FM_MODE_OFF,
+	FM_MODE_TX,
+	FM_MODE_RX,
+	FM_MODE_ENTRY_MAX
+};
+
+#define FM_RX_RDS_INFO_FIELD_MAX	8	/* 4 Group * 2 Bytes */
+
+/* RX RDS data format */
+struct fm_rdsdata_format {
+	union {
+		struct {
+			u8 buff[FM_RX_RDS_INFO_FIELD_MAX];
+		} groupdatabuff;
+		struct {
+			u16 pidata;
+			u8 blk_b[2];
+			u8 blk_c[2];
+			u8 blk_d[2];
+		} groupgeneral;
+		struct {
+			u16 pidata;
+			u8 blk_b[2];
+			u8 af[2];
+			u8 ps[2];
+		} group0A;
+		struct {
+			u16 pi[2];
+			u8 blk_b[2];
+			u8 ps[2];
+		} group0B;
+	} data;
+};
+
+/* FM region (Europe/US, Japan) info */
+struct region_info {
+	u32 chanl_space;
+	u32 bot_freq;
+	u32 top_freq;
+	u8 fm_band;
+};
+struct fmdev;
+typedef void (*int_handler_prototype) (struct fmdev *);
+
+/* FM Interrupt processing related info */
+struct fm_irq {
+	u8 stage;
+	u16 flag;	/* FM interrupt flag */
+	u16 mask;	/* FM interrupt mask */
+	/* Interrupt process timeout handler */
+	struct timer_list timer;
+	u8 retry;
+	int_handler_prototype *handlers;
+};
+
+/* RDS info */
+struct fm_rds {
+	u8 flag;	/* RX RDS on/off status */
+	u8 last_blk_idx;	/* Last received RDS block */
+
+	/* RDS buffer */
+	wait_queue_head_t read_queue;
+	u32 buf_size;	/* Size is always multiple of 3 */
+	u32 wr_idx;
+	u32 rd_idx;
+	u8 *buff;
+};
+
+#define FM_RDS_MAX_AF_LIST		25
+
+/*
+ * Current RX channel Alternate Frequency cache.
+ * This info is used to switch to other freq (AF)
+ * when current channel signal strengh is below RSSI threshold.
+ */
+struct tuned_station_info {
+	u16 picode;
+	u32 af_cache[FM_RDS_MAX_AF_LIST];
+	u8 afcache_size;
+	u8 af_list_max;
+};
+
+/* FM RX mode info */
+struct fm_rx {
+	struct region_info region;	/* Current selected band */
+	u32 freq;	/* Current RX frquency */
+	u8 mute_mode;	/* Current mute mode */
+	u8 deemphasis_mode; /* Current deemphasis mode */
+	/* RF dependent soft mute mode */
+	u8 rf_depend_mute;
+	u16 volume;	/* Current volume level */
+	u16 rssi_threshold;	/* Current RSSI threshold level */
+	/* Holds the index of the current AF jump */
+	u8 afjump_idx;
+	/* Will hold the frequency before the jump */
+	u32 freq_before_jump;
+	u8 rds_mode;	/* RDS operation mode (RDS/RDBS) */
+	u8 af_mode;	/* Alternate frequency on/off */
+	struct tuned_station_info stat_info;
+	struct fm_rds rds;
+};
+
+#define FMTX_RDS_TXT_STR_SIZE	25
+/*
+ * FM TX RDS data
+ *
+ * @ text_type: is the text following PS or RT
+ * @ text: radio text string which could either be PS or RT
+ * @ af_freq: alternate frequency for Tx
+ * TODO: to be declared in application
+ */
+struct tx_rds {
+	u8 text_type;
+	u8 text[FMTX_RDS_TXT_STR_SIZE];
+	u8 flag;
+	u32 af_freq;
+};
+/*
+ * FM TX global data
+ *
+ * @ pwr_lvl: Power Level of the Transmission from mixer control
+ * @ xmit_state: Transmission state = Updated locally upon Start/Stop
+ * @ audio_io: i2S/Analog
+ * @ tx_frq: Transmission frequency
+ */
+struct fmtx_data {
+	u8 pwr_lvl;
+	u8 xmit_state;
+	u8 audio_io;
+	u8 region;
+	u16 aud_mode;
+	u32 preemph;
+	u32 tx_frq;
+	struct tx_rds rds;
+};
+
+/* FM driver operation structure */
+struct fmdev {
+	struct video_device *radio_dev;	/* V4L2 video device pointer */
+	struct snd_card *card;	/* Card which holds FM mixer controls */
+	u16 asci_id;
+	spinlock_t rds_buff_lock; /* To protect access to RDS buffer */
+	spinlock_t resp_skb_lock; /* To protect access to received SKB */
+
+	long flag;		/*  FM driver state machine info */
+	u8 streg_cbdata; /* status of ST registration */
+
+	struct sk_buff_head rx_q;	/* RX queue */
+	struct tasklet_struct rx_task;	/* RX Tasklet */
+
+	struct sk_buff_head tx_q;	/* TX queue */
+	struct tasklet_struct tx_task;	/* TX Tasklet */
+	unsigned long last_tx_jiffies;	/* Timestamp of last pkt sent */
+	atomic_t tx_cnt;	/* Number of packets can send at a time */
+
+	struct sk_buff *resp_skb;	/* Response from the chip */
+	/* Main task completion handler */
+	struct completion maintask_comp;
+	/* Opcode of last command sent to the chip */
+	u8 pre_op;
+	/* Handler used for wakeup when response packet is received */
+	struct completion *resp_comp;
+	struct fm_irq irq_info;
+	u8 curr_fmmode; /* Current FM chip mode (TX, RX, OFF) */
+	struct fm_rx rx;	/* FM receiver info */
+	struct fmtx_data tx_data;
+
+	/* V4L2 ctrl framwork handler*/
+	struct v4l2_ctrl_handler ctrl_handler;
+
+	/* For core assisted locking */
+	struct mutex mutex;
+};
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_rx.c linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_rx.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_rx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,847 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *  This sub-module of FM driver implements FM RX functionality.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *  Author: Raja Mani <raja_mani@ti.com>
+ *  Author: Manjunatha Halli <manjunatha_halli@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "fmdrv.h"
+#include "fmdrv_common.h"
+#include "fmdrv_rx.h"
+
+void fm_rx_reset_rds_cache(struct fmdev *fmdev)
+{
+	fmdev->rx.rds.flag = FM_RDS_DISABLE;
+	fmdev->rx.rds.last_blk_idx = 0;
+	fmdev->rx.rds.wr_idx = 0;
+	fmdev->rx.rds.rd_idx = 0;
+
+	if (fmdev->rx.af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
+		fmdev->irq_info.mask |= FM_LEV_EVENT;
+}
+
+void fm_rx_reset_station_info(struct fmdev *fmdev)
+{
+	fmdev->rx.stat_info.picode = FM_NO_PI_CODE;
+	fmdev->rx.stat_info.afcache_size = 0;
+	fmdev->rx.stat_info.af_list_max = 0;
+}
+
+u32 fm_rx_set_freq(struct fmdev *fmdev, u32 freq)
+{
+	unsigned long timeleft;
+	u16 payload, curr_frq, intr_flag;
+	u32 curr_frq_in_khz;
+	u32 ret, resp_len;
+
+	if (freq < fmdev->rx.region.bot_freq || freq > fmdev->rx.region.top_freq) {
+		fmerr("Invalid frequency %d\n", freq);
+		return -EINVAL;
+	}
+
+	/* Set audio enable */
+	payload = FM_RX_AUDIO_ENABLE_I2S_AND_ANALOG;
+
+	ret = fmc_send_cmd(fmdev, AUDIO_ENABLE_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Set hilo to automatic selection */
+	payload = FM_RX_IFFREQ_HILO_AUTOMATIC;
+	ret = fmc_send_cmd(fmdev, HILO_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Calculate frequency index and set*/
+	payload = (freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
+
+	ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Read flags - just to clear any pending interrupts if we had */
+	ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Enable FR, BL interrupts */
+	intr_flag = fmdev->irq_info.mask;
+	fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT);
+	payload = fmdev->irq_info.mask;
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Start tune */
+	payload = FM_TUNER_PRESET_MODE;
+	ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		goto exit;
+
+	/* Wait for tune ended interrupt */
+	init_completion(&fmdev->maintask_comp);
+	timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
+			FM_DRV_TX_TIMEOUT);
+	if (!timeleft) {
+		fmerr("Timeout(%d sec),didn't get tune ended int\n",
+			   jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
+		ret = -ETIMEDOUT;
+		goto exit;
+	}
+
+	/* Read freq back to confirm */
+	ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2, &curr_frq, &resp_len);
+	if (ret < 0)
+		goto exit;
+
+	curr_frq = be16_to_cpu(curr_frq);
+	curr_frq_in_khz = (fmdev->rx.region.bot_freq + ((u32)curr_frq * FM_FREQ_MUL));
+
+	if (curr_frq_in_khz != freq) {
+		pr_info("Frequency is set to (%d) but "
+			   "requested freq is (%d)\n", curr_frq_in_khz, freq);
+	}
+
+	/* Update local cache  */
+	fmdev->rx.freq = curr_frq_in_khz;
+exit:
+	/* Re-enable default FM interrupts */
+	fmdev->irq_info.mask = intr_flag;
+	payload = fmdev->irq_info.mask;
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Reset RDS cache and current station pointers */
+	fm_rx_reset_rds_cache(fmdev);
+	fm_rx_reset_station_info(fmdev);
+
+	return ret;
+}
+
+static u32 fm_rx_set_channel_spacing(struct fmdev *fmdev, u32 spacing)
+{
+	u16 payload;
+	u32 ret;
+
+	if (spacing > 0 && spacing <= 50000)
+		spacing = FM_CHANNEL_SPACING_50KHZ;
+	else if (spacing > 50000 && spacing <= 100000)
+		spacing = FM_CHANNEL_SPACING_100KHZ;
+	else
+		spacing = FM_CHANNEL_SPACING_200KHZ;
+
+	/* set channel spacing */
+	payload = spacing;
+	ret = fmc_send_cmd(fmdev, CHANL_BW_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->rx.region.chanl_space = spacing * FM_FREQ_MUL;
+
+	return ret;
+}
+
+u32 fm_rx_seek(struct fmdev *fmdev, u32 seek_upward,
+		u32 wrap_around, u32 spacing)
+{
+	u32 resp_len;
+	u16 curr_frq, next_frq, last_frq;
+	u16 payload, int_reason, intr_flag;
+	u16 offset, space_idx;
+	unsigned long timeleft;
+	u32 ret;
+
+	/* Set channel spacing */
+	ret = fm_rx_set_channel_spacing(fmdev, spacing);
+	if (ret < 0) {
+		fmerr("Failed to set channel spacing\n");
+		return ret;
+	}
+
+	/* Read the current frequency from chip */
+	ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL,
+			sizeof(curr_frq), &curr_frq, &resp_len);
+	if (ret < 0)
+		return ret;
+
+	curr_frq = be16_to_cpu(curr_frq);
+	last_frq = (fmdev->rx.region.top_freq - fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
+
+	/* Check the offset in order to be aligned to the channel spacing*/
+	space_idx = fmdev->rx.region.chanl_space / FM_FREQ_MUL;
+	offset = curr_frq % space_idx;
+
+	next_frq = seek_upward ? curr_frq + space_idx /* Seek Up */ :
+				curr_frq - space_idx /* Seek Down */ ;
+
+	/*
+	 * Add or subtract offset in order to stay aligned to the channel
+	 * spacing.
+	 */
+	if ((short)next_frq < 0)
+		next_frq = last_frq - offset;
+	else if (next_frq > last_frq)
+		next_frq = 0 + offset;
+
+again:
+	/* Set calculated next frequency to perform seek */
+	payload = next_frq;
+	ret = fmc_send_cmd(fmdev, FREQ_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Set search direction (0:Seek Down, 1:Seek Up) */
+	payload = (seek_upward ? FM_SEARCH_DIRECTION_UP : FM_SEARCH_DIRECTION_DOWN);
+	ret = fmc_send_cmd(fmdev, SEARCH_DIR_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Read flags - just to clear any pending interrupts if we had */
+	ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2, NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Enable FR, BL interrupts */
+	intr_flag = fmdev->irq_info.mask;
+	fmdev->irq_info.mask = (FM_FR_EVENT | FM_BL_EVENT);
+	payload = fmdev->irq_info.mask;
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Start seek */
+	payload = FM_TUNER_AUTONOMOUS_SEARCH_MODE;
+	ret = fmc_send_cmd(fmdev, TUNER_MODE_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Wait for tune ended/band limit reached interrupt */
+	init_completion(&fmdev->maintask_comp);
+	timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
+			FM_DRV_RX_SEEK_TIMEOUT);
+	if (!timeleft) {
+		fmerr("Timeout(%d sec),didn't get tune ended int\n",
+			   jiffies_to_msecs(FM_DRV_RX_SEEK_TIMEOUT) / 1000);
+		return -ETIMEDOUT;
+	}
+
+	int_reason = fmdev->irq_info.flag & (FM_TUNE_COMPLETE | FM_BAND_LIMIT);
+
+	/* Re-enable default FM interrupts */
+	fmdev->irq_info.mask = intr_flag;
+	payload = fmdev->irq_info.mask;
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	if (int_reason & FM_BL_EVENT) {
+		if (wrap_around == 0) {
+			fmdev->rx.freq = seek_upward ?
+				fmdev->rx.region.top_freq :
+				fmdev->rx.region.bot_freq;
+		} else {
+			fmdev->rx.freq = seek_upward ?
+				fmdev->rx.region.bot_freq :
+				fmdev->rx.region.top_freq;
+			/* Calculate frequency index to write */
+			next_frq = (fmdev->rx.freq -
+					fmdev->rx.region.bot_freq) / FM_FREQ_MUL;
+			goto again;
+		}
+	} else {
+		/* Read freq to know where operation tune operation stopped */
+		ret = fmc_send_cmd(fmdev, FREQ_SET, REG_RD, NULL, 2,
+				&curr_frq, &resp_len);
+		if (ret < 0)
+			return ret;
+
+		curr_frq = be16_to_cpu(curr_frq);
+		fmdev->rx.freq = (fmdev->rx.region.bot_freq +
+				((u32)curr_frq * FM_FREQ_MUL));
+
+	}
+	/* Reset RDS cache and current station pointers */
+	fm_rx_reset_rds_cache(fmdev);
+	fm_rx_reset_station_info(fmdev);
+
+	return ret;
+}
+
+u32 fm_rx_set_volume(struct fmdev *fmdev, u16 vol_to_set)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (vol_to_set < FM_RX_VOLUME_MIN || vol_to_set > FM_RX_VOLUME_MAX) {
+		fmerr("Volume is not within(%d-%d) range\n",
+			   FM_RX_VOLUME_MIN, FM_RX_VOLUME_MAX);
+		return -EINVAL;
+	}
+	vol_to_set *= FM_RX_VOLUME_GAIN_STEP;
+
+	payload = vol_to_set;
+	ret = fmc_send_cmd(fmdev, VOLUME_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->rx.volume = vol_to_set;
+	return ret;
+}
+
+/* Get volume */
+u32 fm_rx_get_volume(struct fmdev *fmdev, u16 *curr_vol)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (curr_vol == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*curr_vol = fmdev->rx.volume / FM_RX_VOLUME_GAIN_STEP;
+
+	return 0;
+}
+
+/* To get current band's bottom and top frequency */
+u32 fm_rx_get_band_freq_range(struct fmdev *fmdev, u32 *bot_freq, u32 *top_freq)
+{
+	if (bot_freq != NULL)
+		*bot_freq = fmdev->rx.region.bot_freq;
+
+	if (top_freq != NULL)
+		*top_freq = fmdev->rx.region.top_freq;
+
+	return 0;
+}
+
+/* Returns current band index (0-Europe/US; 1-Japan) */
+void fm_rx_get_region(struct fmdev *fmdev, u8 *region)
+{
+	*region = fmdev->rx.region.fm_band;
+}
+
+/* Sets band (0-Europe/US; 1-Japan) */
+u32 fm_rx_set_region(struct fmdev *fmdev, u8 region_to_set)
+{
+	u16 payload;
+	u32 new_frq = 0;
+	u32 ret;
+
+	if (region_to_set != FM_BAND_EUROPE_US &&
+	    region_to_set != FM_BAND_JAPAN) {
+		fmerr("Invalid band\n");
+		return -EINVAL;
+	}
+
+	if (fmdev->rx.region.fm_band == region_to_set) {
+		fmerr("Requested band is already configured\n");
+		return 0;
+	}
+
+	/* Send cmd to set the band  */
+	payload = (u16)region_to_set;
+	ret = fmc_send_cmd(fmdev, BAND_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmc_update_region_info(fmdev, region_to_set);
+
+	/* Check whether current RX frequency is within band boundary */
+	if (fmdev->rx.freq < fmdev->rx.region.bot_freq)
+		new_frq = fmdev->rx.region.bot_freq;
+	else if (fmdev->rx.freq > fmdev->rx.region.top_freq)
+		new_frq = fmdev->rx.region.top_freq;
+
+	if (new_frq) {
+		fmdbg("Current freq is not within band limit boundary,"
+				"switching to %d KHz\n", new_frq);
+		 /* Current RX frequency is not in range. So, update it */
+		ret = fm_rx_set_freq(fmdev, new_frq);
+	}
+
+	return ret;
+}
+
+/* Reads current mute mode (Mute Off/On/Attenuate)*/
+u32 fm_rx_get_mute_mode(struct fmdev *fmdev, u8 *curr_mute_mode)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (curr_mute_mode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*curr_mute_mode = fmdev->rx.mute_mode;
+
+	return 0;
+}
+
+static u32 fm_config_rx_mute_reg(struct fmdev *fmdev)
+{
+	u16 payload, muteval;
+	u32 ret;
+
+	muteval = 0;
+	switch (fmdev->rx.mute_mode) {
+	case FM_MUTE_ON:
+		muteval = FM_RX_AC_MUTE_MODE;
+		break;
+
+	case FM_MUTE_OFF:
+		muteval = FM_RX_UNMUTE_MODE;
+		break;
+
+	case FM_MUTE_ATTENUATE:
+		muteval = FM_RX_SOFT_MUTE_FORCE_MODE;
+		break;
+	}
+	if (fmdev->rx.rf_depend_mute == FM_RX_RF_DEPENDENT_MUTE_ON)
+		muteval |= FM_RX_RF_DEP_MODE;
+	else
+		muteval &= ~FM_RX_RF_DEP_MODE;
+
+	payload = muteval;
+	ret = fmc_send_cmd(fmdev, MUTE_STATUS_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* Configures mute mode (Mute Off/On/Attenuate) */
+u32 fm_rx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+{
+	u8 org_state;
+	u32 ret;
+
+	if (fmdev->rx.mute_mode == mute_mode_toset)
+		return 0;
+
+	org_state = fmdev->rx.mute_mode;
+	fmdev->rx.mute_mode = mute_mode_toset;
+
+	ret = fm_config_rx_mute_reg(fmdev);
+	if (ret < 0) {
+		fmdev->rx.mute_mode = org_state;
+		return ret;
+	}
+
+	return 0;
+}
+
+/* Gets RF dependent soft mute mode enable/disable status */
+u32 fm_rx_get_rfdepend_softmute(struct fmdev *fmdev, u8 *curr_mute_mode)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (curr_mute_mode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*curr_mute_mode = fmdev->rx.rf_depend_mute;
+
+	return 0;
+}
+
+/* Sets RF dependent soft mute mode */
+u32 fm_rx_set_rfdepend_softmute(struct fmdev *fmdev, u8 rfdepend_mute)
+{
+	u8 org_state;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_ON &&
+	    rfdepend_mute != FM_RX_RF_DEPENDENT_MUTE_OFF) {
+		fmerr("Invalid RF dependent soft mute\n");
+		return -EINVAL;
+	}
+	if (fmdev->rx.rf_depend_mute == rfdepend_mute)
+		return 0;
+
+	org_state = fmdev->rx.rf_depend_mute;
+	fmdev->rx.rf_depend_mute = rfdepend_mute;
+
+	ret = fm_config_rx_mute_reg(fmdev);
+	if (ret < 0) {
+		fmdev->rx.rf_depend_mute = org_state;
+		return ret;
+	}
+
+	return 0;
+}
+
+/* Returns the signal strength level of current channel */
+u32 fm_rx_get_rssi_level(struct fmdev *fmdev, u16 *rssilvl)
+{
+	u16 curr_rssi_lel;
+	u32 resp_len;
+	u32 ret;
+
+	if (rssilvl == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+	/* Read current RSSI level */
+	ret = fmc_send_cmd(fmdev, RSSI_LVL_GET, REG_RD, NULL, 2,
+			&curr_rssi_lel, &resp_len);
+	if (ret < 0)
+		return ret;
+
+	*rssilvl = be16_to_cpu(curr_rssi_lel);
+
+	return 0;
+}
+
+/*
+ * Sets the signal strength level that once reached
+ * will stop the auto search process
+ */
+u32 fm_rx_set_rssi_threshold(struct fmdev *fmdev, short rssi_lvl_toset)
+{
+	u16 payload;
+	u32 ret;
+
+	if (rssi_lvl_toset < FM_RX_RSSI_THRESHOLD_MIN ||
+			rssi_lvl_toset > FM_RX_RSSI_THRESHOLD_MAX) {
+		fmerr("Invalid RSSI threshold level\n");
+		return -EINVAL;
+	}
+	payload = (u16)rssi_lvl_toset;
+	ret = fmc_send_cmd(fmdev, SEARCH_LVL_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->rx.rssi_threshold = rssi_lvl_toset;
+
+	return 0;
+}
+
+/* Returns current RX RSSI threshold value */
+u32 fm_rx_get_rssi_threshold(struct fmdev *fmdev, short *curr_rssi_lvl)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (curr_rssi_lvl == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*curr_rssi_lvl = fmdev->rx.rssi_threshold;
+
+	return 0;
+}
+
+/* Sets RX stereo/mono modes */
+u32 fm_rx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+{
+	u16 payload;
+	u32 ret;
+
+	if (mode != FM_STEREO_MODE && mode != FM_MONO_MODE) {
+		fmerr("Invalid mode\n");
+		return -EINVAL;
+	}
+
+	/* Set stereo/mono mode */
+	payload = (u16)mode;
+	ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Set stereo blending mode */
+	payload = FM_STEREO_SOFT_BLEND;
+	ret = fmc_send_cmd(fmdev, MOST_BLEND_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* Gets current RX stereo/mono mode */
+u32 fm_rx_get_stereo_mono(struct fmdev *fmdev, u16 *mode)
+{
+	u16 curr_mode;
+	u32 ret, resp_len;
+
+	if (mode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	ret = fmc_send_cmd(fmdev, MOST_MODE_SET, REG_RD, NULL, 2,
+			&curr_mode, &resp_len);
+	if (ret < 0)
+		return ret;
+
+	*mode = be16_to_cpu(curr_mode);
+
+	return 0;
+}
+
+/* Choose RX de-emphasis filter mode (50us/75us) */
+u32 fm_rx_set_deemphasis_mode(struct fmdev *fmdev, u16 mode)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (mode != FM_RX_EMPHASIS_FILTER_50_USEC &&
+			mode != FM_RX_EMPHASIS_FILTER_75_USEC) {
+		fmerr("Invalid rx de-emphasis mode (%d)\n", mode);
+		return -EINVAL;
+	}
+
+	payload = mode;
+	ret = fmc_send_cmd(fmdev, DEMPH_MODE_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->rx.deemphasis_mode = mode;
+
+	return 0;
+}
+
+/* Gets current RX de-emphasis filter mode */
+u32 fm_rx_get_deemph_mode(struct fmdev *fmdev, u16 *curr_deemphasis_mode)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (curr_deemphasis_mode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*curr_deemphasis_mode = fmdev->rx.deemphasis_mode;
+
+	return 0;
+}
+
+/* Enable/Disable RX RDS */
+u32 fm_rx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+{
+	u16 payload;
+	u32 ret;
+
+	if (rds_en_dis != FM_RDS_ENABLE && rds_en_dis != FM_RDS_DISABLE) {
+		fmerr("Invalid rds option\n");
+		return -EINVAL;
+	}
+
+	if (rds_en_dis == FM_RDS_ENABLE
+	    && fmdev->rx.rds.flag == FM_RDS_DISABLE) {
+		/* Turn on RX RDS and RDS circuit */
+		payload = FM_RX_PWR_SET_FM_AND_RDS_BLK_ON;
+		ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload,
+				sizeof(payload), NULL, NULL);
+		if (ret < 0)
+			return ret;
+
+		/* Clear and reset RDS FIFO */
+		payload = FM_RX_RDS_FLUSH_FIFO;
+		ret = fmc_send_cmd(fmdev, RDS_CNTRL_SET, REG_WR, &payload,
+		sizeof(payload), NULL, NULL);
+		if (ret < 0)
+			return ret;
+
+		/* Read flags - just to clear any pending interrupts. */
+		ret = fmc_send_cmd(fmdev, FLAG_GET, REG_RD, NULL, 2,
+				NULL, NULL);
+		if (ret < 0)
+			return ret;
+
+		/* Set RDS FIFO threshold value */
+		payload = FM_RX_RDS_FIFO_THRESHOLD;
+		ret = fmc_send_cmd(fmdev, RDS_MEM_SET, REG_WR, &payload,
+		sizeof(payload), NULL, NULL);
+		if (ret < 0)
+			return ret;
+
+		/* Enable RDS interrupt */
+		fmdev->irq_info.mask |= FM_RDS_EVENT;
+		payload = fmdev->irq_info.mask;
+		ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+				sizeof(payload), NULL, NULL);
+		if (ret < 0) {
+			fmdev->irq_info.mask &= ~FM_RDS_EVENT;
+			return ret;
+		}
+
+		/* Update our local flag */
+		fmdev->rx.rds.flag = FM_RDS_ENABLE;
+	} else if (rds_en_dis == FM_RDS_DISABLE
+		   && fmdev->rx.rds.flag == FM_RDS_ENABLE) {
+		/* Turn off RX RDS */
+		payload = FM_RX_PWR_SET_FM_ON_RDS_OFF;
+		ret = fmc_send_cmd(fmdev, POWER_SET, REG_WR, &payload,
+				sizeof(payload), NULL, NULL);
+		if (ret < 0)
+			return ret;
+
+		/* Reset RDS pointers */
+		fmdev->rx.rds.last_blk_idx = 0;
+		fmdev->rx.rds.wr_idx = 0;
+		fmdev->rx.rds.rd_idx = 0;
+		fm_rx_reset_station_info(fmdev);
+
+		/* Update RDS local cache */
+		fmdev->irq_info.mask &= ~(FM_RDS_EVENT);
+		fmdev->rx.rds.flag = FM_RDS_DISABLE;
+	}
+
+	return 0;
+}
+
+/* Returns current RX RDS enable/disable status */
+u32 fm_rx_get_rds_mode(struct fmdev *fmdev, u8 *curr_rds_en_dis)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (curr_rds_en_dis == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*curr_rds_en_dis = fmdev->rx.rds.flag;
+
+	return 0;
+}
+
+/* Sets RDS operation mode (RDS/RDBS) */
+u32 fm_rx_set_rds_system(struct fmdev *fmdev, u8 rds_mode)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (rds_mode != FM_RDS_SYSTEM_RDS && rds_mode != FM_RDS_SYSTEM_RBDS) {
+		fmerr("Invalid rds mode\n");
+		return -EINVAL;
+	}
+	/* Set RDS operation mode */
+	payload = (u16)rds_mode;
+	ret = fmc_send_cmd(fmdev, RDS_SYSTEM_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->rx.rds_mode = rds_mode;
+
+	return 0;
+}
+
+/* Returns current RDS operation mode */
+u32 fm_rx_get_rds_system(struct fmdev *fmdev, u8 *rds_mode)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (rds_mode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*rds_mode = fmdev->rx.rds_mode;
+
+	return 0;
+}
+
+/* Configures Alternate Frequency switch mode */
+u32 fm_rx_set_af_switch(struct fmdev *fmdev, u8 af_mode)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (af_mode != FM_RX_RDS_AF_SWITCH_MODE_ON &&
+	    af_mode != FM_RX_RDS_AF_SWITCH_MODE_OFF) {
+		fmerr("Invalid af mode\n");
+		return -EINVAL;
+	}
+	/* Enable/disable low RSSI interrupt based on af_mode */
+	if (af_mode == FM_RX_RDS_AF_SWITCH_MODE_ON)
+		fmdev->irq_info.mask |= FM_LEV_EVENT;
+	else
+		fmdev->irq_info.mask &= ~FM_LEV_EVENT;
+
+	payload = fmdev->irq_info.mask;
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->rx.af_mode = af_mode;
+
+	return 0;
+}
+
+/* Returns Alternate Frequency switch status */
+u32 fm_rx_get_af_switch(struct fmdev *fmdev, u8 *af_mode)
+{
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	if (af_mode == NULL) {
+		fmerr("Invalid memory\n");
+		return -ENOMEM;
+	}
+
+	*af_mode = fmdev->rx.af_mode;
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_rx.h linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_rx.h
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_rx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_rx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,59 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *  FM RX module header.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *
+ *  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 _FMDRV_RX_H
+#define _FMDRV_RX_H
+
+u32 fm_rx_set_freq(struct fmdev *, u32);
+u32 fm_rx_set_mute_mode(struct fmdev *, u8);
+u32 fm_rx_set_stereo_mono(struct fmdev *, u16);
+u32 fm_rx_set_rds_mode(struct fmdev *, u8);
+u32 fm_rx_set_rds_system(struct fmdev *, u8);
+u32 fm_rx_set_volume(struct fmdev *, u16);
+u32 fm_rx_set_rssi_threshold(struct fmdev *, short);
+u32 fm_rx_set_region(struct fmdev *, u8);
+u32 fm_rx_set_rfdepend_softmute(struct fmdev *, u8);
+u32 fm_rx_set_deemphasis_mode(struct fmdev *, u16);
+u32 fm_rx_set_af_switch(struct fmdev *, u8);
+
+void fm_rx_reset_rds_cache(struct fmdev *);
+void fm_rx_reset_station_info(struct fmdev *);
+
+u32 fm_rx_seek(struct fmdev *, u32, u32, u32);
+
+u32 fm_rx_get_rds_mode(struct fmdev *, u8 *);
+u32 fm_rx_get_rds_system(struct fmdev *, u8 *);
+u32 fm_rx_get_mute_mode(struct fmdev *, u8 *);
+u32 fm_rx_get_volume(struct fmdev *, u16 *);
+u32 fm_rx_get_band_freq_range(struct fmdev *,
+					u32 *, u32 *);
+u32 fm_rx_get_stereo_mono(struct fmdev *, u16 *);
+u32 fm_rx_get_rssi_level(struct fmdev *, u16 *);
+u32 fm_rx_get_rssi_threshold(struct fmdev *, short *);
+u32 fm_rx_get_rfdepend_softmute(struct fmdev *, u8 *);
+u32 fm_rx_get_deemph_mode(struct fmdev *, u16 *);
+u32 fm_rx_get_af_switch(struct fmdev *, u8 *);
+void fm_rx_get_region(struct fmdev *, u8 *);
+
+u32 fm_rx_set_chanl_spacing(struct fmdev *, u8);
+u32 fm_rx_get_chanl_spacing(struct fmdev *, u8 *);
+#endif
+
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_tx.c linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_tx.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_tx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,425 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *  This sub-module of FM driver implements FM TX functionality.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *
+ *  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/delay.h>
+#include "fmdrv.h"
+#include "fmdrv_common.h"
+#include "fmdrv_tx.h"
+
+u32 fm_tx_set_stereo_mono(struct fmdev *fmdev, u16 mode)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->tx_data.aud_mode == mode)
+		return 0;
+
+	fmdbg("stereo mode: %d\n", mode);
+
+	/* Set Stereo/Mono mode */
+	payload = (1 - mode);
+	ret = fmc_send_cmd(fmdev, MONO_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fmdev->tx_data.aud_mode = mode;
+
+	return ret;
+}
+
+static u32 set_rds_text(struct fmdev *fmdev, u8 *rds_text)
+{
+	u16 payload;
+	u32 ret;
+
+	ret = fmc_send_cmd(fmdev, RDS_DATA_SET, REG_WR, rds_text,
+			strlen(rds_text), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Scroll mode */
+	payload = (u16)0x1;
+	ret = fmc_send_cmd(fmdev, DISPLAY_MODE, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static u32 set_rds_data_mode(struct fmdev *fmdev, u8 mode)
+{
+	u16 payload;
+	u32 ret;
+
+	/* Setting unique PI TODO: how unique? */
+	payload = (u16)0xcafe;
+	ret = fmc_send_cmd(fmdev, PI_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Set decoder id */
+	payload = (u16)0xa;
+	ret = fmc_send_cmd(fmdev, DI_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* TODO: RDS_MODE_GET? */
+	return 0;
+}
+
+static u32 set_rds_len(struct fmdev *fmdev, u8 type, u16 len)
+{
+	u16 payload;
+	u32 ret;
+
+	len |= type << 8;
+	payload = len;
+	ret = fmc_send_cmd(fmdev, RDS_CONFIG_DATA_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* TODO: LENGTH_GET? */
+	return 0;
+}
+
+u32 fm_tx_set_rds_mode(struct fmdev *fmdev, u8 rds_en_dis)
+{
+	u16 payload;
+	u32 ret;
+	u8 rds_text[] = "Zoom2\n";
+
+	fmdbg("rds_en_dis:%d(E:%d, D:%d)\n", rds_en_dis,
+		   FM_RDS_ENABLE, FM_RDS_DISABLE);
+
+	if (rds_en_dis == FM_RDS_ENABLE) {
+		/* Set RDS length */
+		set_rds_len(fmdev, 0, strlen(rds_text));
+
+		/* Set RDS text */
+		set_rds_text(fmdev, rds_text);
+
+		/* Set RDS mode */
+		set_rds_data_mode(fmdev, 0x0);
+	}
+
+	/* Send command to enable RDS */
+	if (rds_en_dis == FM_RDS_ENABLE)
+		payload = 0x01;
+	else
+		payload = 0x00;
+
+	ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	if (rds_en_dis == FM_RDS_ENABLE) {
+		/* Set RDS length */
+		set_rds_len(fmdev, 0, strlen(rds_text));
+
+		/* Set RDS text */
+		set_rds_text(fmdev, rds_text);
+	}
+	fmdev->tx_data.rds.flag = rds_en_dis;
+
+	return 0;
+}
+
+u32 fm_tx_set_radio_text(struct fmdev *fmdev, u8 *rds_text, u8 rds_type)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX)
+		return -EPERM;
+
+	fm_tx_set_rds_mode(fmdev, 0);
+
+	/* Set RDS length */
+	set_rds_len(fmdev, rds_type, strlen(rds_text));
+
+	/* Set RDS text */
+	set_rds_text(fmdev, rds_text);
+
+	/* Set RDS mode */
+	set_rds_data_mode(fmdev, 0x0);
+
+	payload = 1;
+	ret = fmc_send_cmd(fmdev, RDS_DATA_ENB, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+u32 fm_tx_set_af(struct fmdev *fmdev, u32 af)
+{
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX)
+		return -EPERM;
+
+	fmdbg("AF: %d\n", af);
+
+	af = (af - 87500) / 100;
+	payload = (u16)af;
+	ret = fmc_send_cmd(fmdev, TA_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+u32 fm_tx_set_region(struct fmdev *fmdev, u8 region)
+{
+	u16 payload;
+	u32 ret;
+
+	if (region != FM_BAND_EUROPE_US && region != FM_BAND_JAPAN) {
+		fmerr("Invalid band\n");
+		return -EINVAL;
+	}
+
+	/* Send command to set the band */
+	payload = (u16)region;
+	ret = fmc_send_cmd(fmdev, TX_BAND_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+u32 fm_tx_set_mute_mode(struct fmdev *fmdev, u8 mute_mode_toset)
+{
+	u16 payload;
+	u32 ret;
+
+	fmdbg("tx: mute mode %d\n", mute_mode_toset);
+
+	payload = mute_mode_toset;
+	ret = fmc_send_cmd(fmdev, MUTE, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/* Set TX Audio I/O */
+static u32 set_audio_io(struct fmdev *fmdev)
+{
+	struct fmtx_data *tx = &fmdev->tx_data;
+	u16 payload;
+	u32 ret;
+
+	/* Set Audio I/O Enable */
+	payload = tx->audio_io;
+	ret = fmc_send_cmd(fmdev, AUDIO_IO_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* TODO: is audio set? */
+	return 0;
+}
+
+/* Start TX Transmission */
+static u32 enable_xmit(struct fmdev *fmdev, u8 new_xmit_state)
+{
+	struct fmtx_data *tx = &fmdev->tx_data;
+	unsigned long timeleft;
+	u16 payload;
+	u32 ret;
+
+	/* Enable POWER_ENB interrupts */
+	payload = FM_POW_ENB_EVENT;
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Set Power Enable */
+	payload = new_xmit_state;
+	ret = fmc_send_cmd(fmdev, POWER_ENB_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* Wait for Power Enabled */
+	init_completion(&fmdev->maintask_comp);
+	timeleft = wait_for_completion_timeout(&fmdev->maintask_comp,
+			FM_DRV_TX_TIMEOUT);
+	if (!timeleft) {
+		fmerr("Timeout(%d sec),didn't get tune ended interrupt\n",
+			   jiffies_to_msecs(FM_DRV_TX_TIMEOUT) / 1000);
+		return -ETIMEDOUT;
+	}
+
+	set_bit(FM_CORE_TX_XMITING, &fmdev->flag);
+	tx->xmit_state = new_xmit_state;
+
+	return 0;
+}
+
+/* Set TX power level */
+u32 fm_tx_set_pwr_lvl(struct fmdev *fmdev, u8 new_pwr_lvl)
+{
+	u16 payload;
+	struct fmtx_data *tx = &fmdev->tx_data;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX)
+		return -EPERM;
+	fmdbg("tx: pwr_level_to_set %ld\n", (long int)new_pwr_lvl);
+
+	/* If the core isn't ready update global variable */
+	if (!test_bit(FM_CORE_READY, &fmdev->flag)) {
+		tx->pwr_lvl = new_pwr_lvl;
+		return 0;
+	}
+
+	/* Set power level: Application will specify power level value in
+	 * units of dB/uV, whereas range and step are specific to FM chip.
+	 * For TI's WL chips, convert application specified power level value
+	 * to chip specific value by subtracting 122 from it. Refer to TI FM
+	 * data sheet for details.
+	 * */
+
+	payload = (FM_PWR_LVL_HIGH - new_pwr_lvl);
+	ret = fmc_send_cmd(fmdev, POWER_LEV_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	/* TODO: is the power level set? */
+	tx->pwr_lvl = new_pwr_lvl;
+
+	return 0;
+}
+
+/*
+ * Sets FM TX pre-emphasis filter value (OFF, 50us, or 75us)
+ * Convert V4L2 specified filter values to chip specific filter values.
+ */
+u32 fm_tx_set_preemph_filter(struct fmdev *fmdev, u32 preemphasis)
+{
+	struct fmtx_data *tx = &fmdev->tx_data;
+	u16 payload;
+	u32 ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX)
+		return -EPERM;
+
+	switch (preemphasis) {
+	case V4L2_PREEMPHASIS_DISABLED:
+		payload = FM_TX_PREEMPH_OFF;
+		break;
+	case V4L2_PREEMPHASIS_50_uS:
+		payload = FM_TX_PREEMPH_50US;
+		break;
+	case V4L2_PREEMPHASIS_75_uS:
+		payload = FM_TX_PREEMPH_75US;
+		break;
+	}
+
+	ret = fmc_send_cmd(fmdev, PREMPH_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	tx->preemph = payload;
+
+	return ret;
+}
+
+/* Get the TX tuning capacitor value.*/
+u32 fm_tx_get_tune_cap_val(struct fmdev *fmdev)
+{
+	u16 curr_val;
+	u32 ret, resp_len;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX)
+		return -EPERM;
+
+	ret = fmc_send_cmd(fmdev, READ_FMANT_TUNE_VALUE, REG_RD,
+			NULL, sizeof(curr_val), &curr_val, &resp_len);
+	if (ret < 0)
+		return ret;
+
+	curr_val = be16_to_cpu(curr_val);
+
+	return curr_val;
+}
+
+/* Set TX Frequency */
+u32 fm_tx_set_freq(struct fmdev *fmdev, u32 freq_to_set)
+{
+	struct fmtx_data *tx = &fmdev->tx_data;
+	u16 payload, chanl_index;
+	u32 ret;
+
+	if (test_bit(FM_CORE_TX_XMITING, &fmdev->flag)) {
+		enable_xmit(fmdev, 0);
+		clear_bit(FM_CORE_TX_XMITING, &fmdev->flag);
+	}
+
+	/* Enable FR, BL interrupts */
+	payload = (FM_FR_EVENT | FM_BL_EVENT);
+	ret = fmc_send_cmd(fmdev, INT_MASK_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	tx->tx_frq = (unsigned long)freq_to_set;
+	fmdbg("tx: freq_to_set %ld\n", (long int)tx->tx_frq);
+
+	chanl_index = freq_to_set / 10;
+
+	/* Set current tuner channel */
+	payload = chanl_index;
+	ret = fmc_send_cmd(fmdev, CHANL_SET, REG_WR, &payload,
+			sizeof(payload), NULL, NULL);
+	if (ret < 0)
+		return ret;
+
+	fm_tx_set_pwr_lvl(fmdev, tx->pwr_lvl);
+	fm_tx_set_preemph_filter(fmdev, tx->preemph);
+
+	tx->audio_io = 0x01;	/* I2S */
+	set_audio_io(fmdev);
+
+	enable_xmit(fmdev, 0x01);	/* Enable transmission */
+
+	tx->aud_mode = FM_STEREO_MODE;
+	tx->rds.flag = FM_RDS_DISABLE;
+
+	return 0;
+}
+
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_tx.h linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_tx.h
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_tx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_tx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,37 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *  FM TX module header.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *
+ *  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 _FMDRV_TX_H
+#define _FMDRV_TX_H
+
+u32 fm_tx_set_freq(struct fmdev *, u32);
+u32 fm_tx_set_pwr_lvl(struct fmdev *, u8);
+u32 fm_tx_set_region(struct fmdev *, u8);
+u32 fm_tx_set_mute_mode(struct fmdev *, u8);
+u32 fm_tx_set_stereo_mono(struct fmdev *, u16);
+u32 fm_tx_set_rds_mode(struct fmdev *, u8);
+u32 fm_tx_set_radio_text(struct fmdev *, u8 *, u8);
+u32 fm_tx_set_af(struct fmdev *, u32);
+u32 fm_tx_set_preemph_filter(struct fmdev *, u32);
+u32 fm_tx_get_tune_cap_val(struct fmdev *);
+
+#endif
+
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,580 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *  This file provides interfaces to V4L2 subsystem.
+ *
+ *  This module registers with V4L2 subsystem as Radio
+ *  data system interface (/dev/radio). During the registration,
+ *  it will expose two set of function pointers.
+ *
+ *    1) File operation related API (open, close, read, write, poll...etc).
+ *    2) Set of V4L2 IOCTL complaint API.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *  Author: Raja Mani <raja_mani@ti.com>
+ *  Author: Manjunatha Halli <manjunatha_halli@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.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 "fmdrv.h"
+#include "fmdrv_v4l2.h"
+#include "fmdrv_common.h"
+#include "fmdrv_rx.h"
+#include "fmdrv_tx.h"
+
+static struct video_device *gradio_dev;
+static u8 radio_disconnected;
+
+/* -- V4L2 RADIO (/dev/radioX) device file operation interfaces --- */
+
+/* Read RX RDS data */
+static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
+					size_t count, loff_t *ppos)
+{
+	u8 rds_mode;
+	int ret;
+	struct fmdev *fmdev;
+
+	fmdev = video_drvdata(file);
+
+	if (!radio_disconnected) {
+		fmerr("FM device is already disconnected\n");
+		return -EIO;
+	}
+
+	/* Turn on RDS mode , if it is disabled */
+	ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
+	if (ret < 0) {
+		fmerr("Unable to read current rds mode\n");
+		return ret;
+	}
+
+	if (rds_mode == FM_RDS_DISABLE) {
+		ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
+		if (ret < 0) {
+			fmerr("Failed to enable rds mode\n");
+			return ret;
+		}
+	}
+
+	/* Copy RDS data from internal buffer to user buffer */
+	return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
+}
+
+/* Write TX RDS data */
+static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
+		size_t count, loff_t *ppos)
+{
+	struct tx_rds rds;
+	int ret;
+	struct fmdev *fmdev;
+
+	ret = copy_from_user(&rds, buf, sizeof(rds));
+	fmdbg("(%d)type: %d, text %s, af %d\n",
+		   ret, rds.text_type, rds.text, rds.af_freq);
+
+	fmdev = video_drvdata(file);
+	fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
+	fm_tx_set_af(fmdev, rds.af_freq);
+
+	return 0;
+}
+
+static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
+{
+	int ret;
+	struct fmdev *fmdev;
+
+	fmdev = video_drvdata(file);
+	ret = fmc_is_rds_data_available(fmdev, file, pts);
+	if (ret < 0)
+		return POLLIN | POLLRDNORM;
+
+	return 0;
+}
+
+/*
+ * Handle open request for "/dev/radioX" device.
+ * Start with FM RX mode as default.
+ */
+static int fm_v4l2_fops_open(struct file *file)
+{
+	int ret;
+	struct fmdev *fmdev = NULL;
+
+	/* Don't allow multiple open */
+	if (radio_disconnected) {
+		fmerr("FM device is already opened\n");
+		return -EBUSY;
+	}
+
+	fmdev = video_drvdata(file);
+
+	ret = fmc_prepare(fmdev);
+	if (ret < 0) {
+		fmerr("Unable to prepare FM CORE\n");
+		return ret;
+	}
+
+	fmdbg("Load FM RX firmware..\n");
+
+	ret = fmc_set_mode(fmdev, FM_MODE_RX);
+	if (ret < 0) {
+		fmerr("Unable to load FM RX firmware\n");
+		return ret;
+	}
+	radio_disconnected = 1;
+
+	return ret;
+}
+
+static int fm_v4l2_fops_release(struct file *file)
+{
+	int ret;
+	struct fmdev *fmdev;
+
+	fmdev = video_drvdata(file);
+	if (!radio_disconnected) {
+		fmdbg("FM device is already closed\n");
+		return 0;
+	}
+
+	ret = fmc_set_mode(fmdev, FM_MODE_OFF);
+	if (ret < 0) {
+		fmerr("Unable to turn off the chip\n");
+		return ret;
+	}
+
+	ret = fmc_release(fmdev);
+	if (ret < 0) {
+		fmerr("FM CORE release failed\n");
+		return ret;
+	}
+	radio_disconnected = 0;
+
+	return ret;
+}
+
+/* V4L2 RADIO (/dev/radioX) device IOCTL interfaces */
+static int fm_v4l2_vidioc_querycap(struct file *file, void *priv,
+		struct v4l2_capability *capability)
+{
+	strlcpy(capability->driver, FM_DRV_NAME, sizeof(capability->driver));
+	strlcpy(capability->card, FM_DRV_CARD_SHORT_NAME,
+			sizeof(capability->card));
+	sprintf(capability->bus_info, "UART");
+	capability->version = FM_DRV_RADIO_VERSION;
+	capability->capabilities = V4L2_CAP_HW_FREQ_SEEK | V4L2_CAP_TUNER |
+		V4L2_CAP_RADIO | V4L2_CAP_MODULATOR |
+		V4L2_CAP_AUDIO | V4L2_CAP_READWRITE |
+		V4L2_CAP_RDS_CAPTURE;
+
+	return 0;
+}
+
+static int fm_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct fmdev *fmdev = container_of(ctrl->handler,
+			struct fmdev, ctrl_handler);
+
+	switch (ctrl->id) {
+	case  V4L2_CID_TUNE_ANTENNA_CAPACITOR:
+		ctrl->val = fm_tx_get_tune_cap_val(fmdev);
+		break;
+	default:
+		fmwarn("%s: Unknown IOCTL: %d\n", __func__, ctrl->id);
+		break;
+	}
+
+	return 0;
+}
+
+static int fm_v4l2_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct fmdev *fmdev = container_of(ctrl->handler,
+			struct fmdev, ctrl_handler);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_VOLUME:	/* set volume */
+		return fm_rx_set_volume(fmdev, (u16)ctrl->val);
+
+	case V4L2_CID_AUDIO_MUTE:	/* set mute */
+		return fmc_set_mute_mode(fmdev, (u8)ctrl->val);
+
+	case V4L2_CID_TUNE_POWER_LEVEL:
+		/* set TX power level - ext control */
+		return fm_tx_set_pwr_lvl(fmdev, (u8)ctrl->val);
+
+	case V4L2_CID_TUNE_PREEMPHASIS:
+		return fm_tx_set_preemph_filter(fmdev, (u8) ctrl->val);
+
+	default:
+		return -EINVAL;
+	}
+}
+
+static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv,
+		struct v4l2_audio *audio)
+{
+	memset(audio, 0, sizeof(*audio));
+	strcpy(audio->name, "Radio");
+	audio->capability = V4L2_AUDCAP_STEREO;
+
+	return 0;
+}
+
+static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv,
+		struct v4l2_audio *audio)
+{
+	if (audio->index != 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/* Get tuner attributes. If current mode is NOT RX, return error */
+static int fm_v4l2_vidioc_g_tuner(struct file *file, void *priv,
+		struct v4l2_tuner *tuner)
+{
+	struct fmdev *fmdev = video_drvdata(file);
+	u32 bottom_freq;
+	u32 top_freq;
+	u16 stereo_mono_mode;
+	u16 rssilvl;
+	int ret;
+
+	if (tuner->index != 0)
+		return -EINVAL;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX)
+		return -EPERM;
+
+	ret = fm_rx_get_band_freq_range(fmdev, &bottom_freq, &top_freq);
+	if (ret != 0)
+		return ret;
+
+	ret = fm_rx_get_stereo_mono(fmdev, &stereo_mono_mode);
+	if (ret != 0)
+		return ret;
+
+	ret = fm_rx_get_rssi_level(fmdev, &rssilvl);
+	if (ret != 0)
+		return ret;
+
+	strcpy(tuner->name, "FM");
+	tuner->type = V4L2_TUNER_RADIO;
+	/* Store rangelow and rangehigh freq in unit of 62.5 Hz */
+	tuner->rangelow = bottom_freq * 16;
+	tuner->rangehigh = top_freq * 16;
+	tuner->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO |
+	((fmdev->rx.rds.flag == FM_RDS_ENABLE) ? V4L2_TUNER_SUB_RDS : 0);
+	tuner->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
+			    V4L2_TUNER_CAP_LOW;
+	tuner->audmode = (stereo_mono_mode ?
+			  V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO);
+
+	/*
+	 * Actual rssi value lies in between -128 to +127.
+	 * Convert this range from 0 to 255 by adding +128
+	 */
+	rssilvl += 128;
+
+	/*
+	 * Return signal strength value should be within 0 to 65535.
+	 * Find out correct signal radio by multiplying (65535/255) = 257
+	 */
+	tuner->signal = rssilvl * 257;
+	tuner->afc = 0;
+
+	return ret;
+}
+
+/*
+ * Set tuner attributes. If current mode is NOT RX, set to RX.
+ * Currently, we set only audio mode (mono/stereo) and RDS state (on/off).
+ * Should we set other tuner attributes, too?
+ */
+static int fm_v4l2_vidioc_s_tuner(struct file *file, void *priv,
+		struct v4l2_tuner *tuner)
+{
+	struct fmdev *fmdev = video_drvdata(file);
+	u16 aud_mode;
+	u8 rds_mode;
+	int ret;
+
+	if (tuner->index != 0)
+		return -EINVAL;
+
+	aud_mode = (tuner->audmode == V4L2_TUNER_MODE_STEREO) ?
+			FM_STEREO_MODE : FM_MONO_MODE;
+	rds_mode = (tuner->rxsubchans & V4L2_TUNER_SUB_RDS) ?
+			FM_RDS_ENABLE : FM_RDS_DISABLE;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX) {
+		ret = fmc_set_mode(fmdev, FM_MODE_RX);
+		if (ret < 0) {
+			fmerr("Failed to set RX mode\n");
+			return ret;
+		}
+	}
+
+	ret = fmc_set_stereo_mono(fmdev, aud_mode);
+	if (ret < 0) {
+		fmerr("Failed to set RX stereo/mono mode\n");
+		return ret;
+	}
+
+	ret = fmc_set_rds_mode(fmdev, rds_mode);
+	if (ret < 0)
+		fmerr("Failed to set RX RDS mode\n");
+
+	return ret;
+}
+
+/* Get tuner or modulator radio frequency */
+static int fm_v4l2_vidioc_g_freq(struct file *file, void *priv,
+		struct v4l2_frequency *freq)
+{
+	struct fmdev *fmdev = video_drvdata(file);
+	int ret;
+
+	ret = fmc_get_freq(fmdev, &freq->frequency);
+	if (ret < 0) {
+		fmerr("Failed to get frequency\n");
+		return ret;
+	}
+
+	/* Frequency unit of 62.5 Hz*/
+	freq->frequency = (u32) freq->frequency * 16;
+
+	return 0;
+}
+
+/* Set tuner or modulator radio frequency */
+static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
+		struct v4l2_frequency *freq)
+{
+	struct fmdev *fmdev = video_drvdata(file);
+
+	/*
+	 * As V4L2_TUNER_CAP_LOW is set 1 user sends the frequency
+	 * in units of 62.5 Hz.
+	 */
+	freq->frequency = (u32)(freq->frequency / 16);
+
+	return fmc_set_freq(fmdev, freq->frequency);
+}
+
+/* Set hardware frequency seek. If current mode is NOT RX, set it RX. */
+static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
+		struct v4l2_hw_freq_seek *seek)
+{
+	struct fmdev *fmdev = video_drvdata(file);
+	int ret;
+
+	if (fmdev->curr_fmmode != FM_MODE_RX) {
+		ret = fmc_set_mode(fmdev, FM_MODE_RX);
+		if (ret != 0) {
+			fmerr("Failed to set RX mode\n");
+			return ret;
+		}
+	}
+
+	ret = fm_rx_seek(fmdev, seek->seek_upward, seek->wrap_around,
+			seek->spacing);
+	if (ret < 0)
+		fmerr("RX seek failed - %d\n", ret);
+
+	return ret;
+}
+/* Get modulator attributes. If mode is not TX, return no attributes. */
+static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
+		struct v4l2_modulator *mod)
+{
+	struct fmdev *fmdev = video_drvdata(file);;
+
+	if (mod->index != 0)
+		return -EINVAL;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX)
+		return -EPERM;
+
+	mod->txsubchans = ((fmdev->tx_data.aud_mode == FM_STEREO_MODE) ?
+				V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO) |
+				((fmdev->tx_data.rds.flag == FM_RDS_ENABLE) ?
+				V4L2_TUNER_SUB_RDS : 0);
+
+	mod->capability = V4L2_TUNER_CAP_STEREO | V4L2_TUNER_CAP_RDS |
+				V4L2_TUNER_CAP_LOW;
+
+	return 0;
+}
+
+/* Set modulator attributes. If mode is not TX, set to TX. */
+static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv,
+		struct v4l2_modulator *mod)
+{
+	struct fmdev *fmdev = video_drvdata(file);
+	u8 rds_mode;
+	u16 aud_mode;
+	int ret;
+
+	if (mod->index != 0)
+		return -EINVAL;
+
+	if (fmdev->curr_fmmode != FM_MODE_TX) {
+		ret = fmc_set_mode(fmdev, FM_MODE_TX);
+		if (ret != 0) {
+			fmerr("Failed to set TX mode\n");
+			return ret;
+		}
+	}
+
+	aud_mode = (mod->txsubchans & V4L2_TUNER_SUB_STEREO) ?
+			FM_STEREO_MODE : FM_MONO_MODE;
+	rds_mode = (mod->txsubchans & V4L2_TUNER_SUB_RDS) ?
+			FM_RDS_ENABLE : FM_RDS_DISABLE;
+	ret = fm_tx_set_stereo_mono(fmdev, aud_mode);
+	if (ret < 0) {
+		fmerr("Failed to set mono/stereo mode for TX\n");
+		return ret;
+	}
+	ret = fm_tx_set_rds_mode(fmdev, rds_mode);
+	if (ret < 0)
+		fmerr("Failed to set rds mode for TX\n");
+
+	return ret;
+}
+
+static const struct v4l2_file_operations fm_drv_fops = {
+	.owner = THIS_MODULE,
+	.read = fm_v4l2_fops_read,
+	.write = fm_v4l2_fops_write,
+	.poll = fm_v4l2_fops_poll,
+	.unlocked_ioctl = video_ioctl2,
+	.open = fm_v4l2_fops_open,
+	.release = fm_v4l2_fops_release,
+};
+
+static const struct v4l2_ctrl_ops fm_ctrl_ops = {
+	.s_ctrl = fm_v4l2_s_ctrl,
+	.g_volatile_ctrl = fm_g_volatile_ctrl,
+};
+static const struct v4l2_ioctl_ops fm_drv_ioctl_ops = {
+	.vidioc_querycap = fm_v4l2_vidioc_querycap,
+	.vidioc_g_audio = fm_v4l2_vidioc_g_audio,
+	.vidioc_s_audio = fm_v4l2_vidioc_s_audio,
+	.vidioc_g_tuner = fm_v4l2_vidioc_g_tuner,
+	.vidioc_s_tuner = fm_v4l2_vidioc_s_tuner,
+	.vidioc_g_frequency = fm_v4l2_vidioc_g_freq,
+	.vidioc_s_frequency = fm_v4l2_vidioc_s_freq,
+	.vidioc_s_hw_freq_seek = fm_v4l2_vidioc_s_hw_freq_seek,
+	.vidioc_g_modulator = fm_v4l2_vidioc_g_modulator,
+	.vidioc_s_modulator = fm_v4l2_vidioc_s_modulator
+};
+
+/* V4L2 RADIO device parent structure */
+static struct video_device fm_viddev_template = {
+	.fops = &fm_drv_fops,
+	.ioctl_ops = &fm_drv_ioctl_ops,
+	.name = FM_DRV_NAME,
+	.release = video_device_release,
+};
+
+int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
+{
+	struct v4l2_ctrl *ctrl;
+	int ret;
+
+	/* Init mutex for core locking */
+	mutex_init(&fmdev->mutex);
+
+	/* Allocate new video device */
+	gradio_dev = video_device_alloc();
+	if (NULL == gradio_dev) {
+		fmerr("Can't allocate video device\n");
+		return -ENOMEM;
+	}
+
+	/* Setup FM driver's V4L2 properties */
+	memcpy(gradio_dev, &fm_viddev_template, sizeof(fm_viddev_template));
+
+	video_set_drvdata(gradio_dev, fmdev);
+
+	gradio_dev->lock = &fmdev->mutex;
+
+	/* Register with V4L2 subsystem as RADIO device */
+	if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
+		video_device_release(gradio_dev);
+		fmerr("Could not register video device\n");
+		return -ENOMEM;
+	}
+
+	fmdev->radio_dev = gradio_dev;
+
+	/* Register to v4l2 ctrl handler framework */
+	fmdev->radio_dev->ctrl_handler = &fmdev->ctrl_handler;
+
+	ret = v4l2_ctrl_handler_init(&fmdev->ctrl_handler, 5);
+	if (ret < 0) {
+		fmerr("(fmdev): Can't init ctrl handler\n");
+		v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
+		return -EBUSY;
+	}
+
+	/*
+	 * Following controls are handled by V4L2 control framework.
+	 * Added in ascending ID order.
+	 */
+	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, FM_RX_VOLUME_MIN,
+			FM_RX_VOLUME_MAX, 1, FM_RX_VOLUME_MAX);
+
+	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 1);
+
+	v4l2_ctrl_new_std_menu(&fmdev->ctrl_handler, &fm_ctrl_ops,
+			V4L2_CID_TUNE_PREEMPHASIS, V4L2_PREEMPHASIS_75_uS,
+			0, V4L2_PREEMPHASIS_75_uS);
+
+	v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
+			V4L2_CID_TUNE_POWER_LEVEL, FM_PWR_LVL_LOW,
+			FM_PWR_LVL_HIGH, 1, FM_PWR_LVL_HIGH);
+
+	ctrl = v4l2_ctrl_new_std(&fmdev->ctrl_handler, &fm_ctrl_ops,
+			V4L2_CID_TUNE_ANTENNA_CAPACITOR, 0,
+			255, 1, 255);
+
+	if (ctrl)
+		ctrl->is_volatile = 1;
+
+	return 0;
+}
+
+void *fm_v4l2_deinit_video_device(void)
+{
+	struct fmdev *fmdev;
+
+
+	fmdev = video_get_drvdata(gradio_dev);
+
+	/* Unregister to v4l2 ctrl handler framework*/
+	v4l2_ctrl_handler_free(&fmdev->ctrl_handler);
+
+	/* Unregister RADIO device from V4L2 subsystem */
+	video_unregister_device(gradio_dev);
+
+	return fmdev;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.h linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.h
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/fmdrv_v4l2.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ *  FM Driver for Connectivity chip of Texas Instruments.
+ *
+ *  FM V4L2 module header.
+ *
+ *  Copyright (C) 2011 Texas Instruments
+ *
+ *  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 _FMDRV_V4L2_H
+#define _FMDRV_V4L2_H
+
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+
+int fm_v4l2_init_video_device(struct fmdev *, int);
+void *fm_v4l2_deinit_video_device(void);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/Kconfig linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,17 @@
+#
+# TI's wl128x FM driver based on TI's ST driver.
+#
+menu "Texas Instruments WL128x FM driver (ST based)"
+config RADIO_WL128X
+	tristate "Texas Instruments WL128x FM Radio"
+	depends on VIDEO_V4L2 && RFKILL
+	select TI_ST
+	help
+	Choose Y here if you have this FM radio chip.
+
+	In order to control your radio card, you will need to use programs
+	that are compatible with the Video For Linux 2 API.  Information on
+	this API and pointers to "v4l2" programs may be found at
+	<file:Documentation/video4linux/API.html>.
+
+endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/Makefile linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/radio/wl128x/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/radio/wl128x/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,6 @@
+#
+# Makefile for TI's shared transport driver based wl128x
+# FM radio.
+#
+obj-$(CONFIG_RADIO_WL128X)	+= fm_drv.o
+fm_drv-objs		:= fmdrv_common.o fmdrv_rx.o fmdrv_tx.o fmdrv_v4l2.o
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/ene_ir.c linux-libre-2.6.39-gnu/drivers/media/rc/ene_ir.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/ene_ir.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/ene_ir.c	2011-05-19 00:06:34.000000000 -0400
@@ -520,7 +520,7 @@
 	dev->rx_enabled = false;
 }
 
-/* This resets the receiver. Usefull to stop stream of spaces at end of
+/* This resets the receiver. Useful to stop stream of spaces at end of
  * transmission
  */
 static void ene_rx_reset(struct ene_device *dev)
@@ -1089,7 +1089,7 @@
 	if (error < 0)
 		goto error;
 
-	ene_notice("driver has been succesfully loaded");
+	ene_notice("driver has been successfully loaded");
 	return 0;
 error:
 	if (dev && dev->irq >= 0)
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/imon.c linux-libre-2.6.39-gnu/drivers/media/rc/imon.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/imon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/imon.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
 #define MOD_AUTHOR	"Jarod Wilson <jarod@wilsonet.com>"
 #define MOD_DESC	"Driver for SoundGraph iMON MultiMedia IR/Display"
 #define MOD_NAME	"imon"
-#define MOD_VERSION	"0.9.2"
+#define MOD_VERSION	"0.9.3"
 
 #define DISPLAY_MINOR_BASE	144
 #define DEVICE_NAME	"lcd%d"
@@ -277,12 +277,21 @@
 	u64 hw_code;
 	u32 keycode;
 } imon_panel_key_table[] = {
-	{ 0x000000000f00ffeell, KEY_PROG1 }, /* Go */
+	{ 0x000000000f00ffeell, KEY_MEDIA }, /* Go */
+	{ 0x000000001200ffeell, KEY_UP },
+	{ 0x000000001300ffeell, KEY_DOWN },
+	{ 0x000000001400ffeell, KEY_LEFT },
+	{ 0x000000001500ffeell, KEY_RIGHT },
+	{ 0x000000001600ffeell, KEY_ENTER },
+	{ 0x000000001700ffeell, KEY_ESC },
 	{ 0x000000001f00ffeell, KEY_AUDIO },
 	{ 0x000000002000ffeell, KEY_VIDEO },
 	{ 0x000000002100ffeell, KEY_CAMERA },
 	{ 0x000000002700ffeell, KEY_DVD },
 	{ 0x000000002300ffeell, KEY_TV },
+	{ 0x000000002b00ffeell, KEY_EXIT },
+	{ 0x000000002c00ffeell, KEY_SELECT },
+	{ 0x000000002d00ffeell, KEY_MENU },
 	{ 0x000000000500ffeell, KEY_PREVIOUS },
 	{ 0x000000000700ffeell, KEY_REWIND },
 	{ 0x000000000400ffeell, KEY_STOP },
@@ -451,8 +460,9 @@
 }
 
 /**
- * Sends a packet to the device -- this function must be called
- * with ictx->lock held.
+ * Sends a packet to the device -- this function must be called with
+ * ictx->lock held, or its unlock/lock sequence while waiting for tx
+ * to complete can/will lead to a deadlock.
  */
 static int send_packet(struct imon_context *ictx)
 {
@@ -982,12 +992,21 @@
  * the iMON remotes, and those used by the Windows MCE remotes (which is
  * really just RC-6), but only one or the other at a time, as the signals
  * are decoded onboard the receiver.
+ *
+ * This function gets called two different ways, one way is from
+ * rc_register_device, for initial protocol selection/setup, and the other is
+ * via a userspace-initiated protocol change request, either by direct sysfs
+ * prodding or by something like ir-keytable. In the rc_register_device case,
+ * the imon context lock is already held, but when initiated from userspace,
+ * it is not, so we must acquire it prior to calling send_packet, which
+ * requires that the lock is held.
  */
 static int imon_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 {
 	int retval;
 	struct imon_context *ictx = rc->priv;
 	struct device *dev = ictx->dev;
+	bool unlock = false;
 	unsigned char ir_proto_packet[] = {
 		0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86 };
 
@@ -1020,6 +1039,11 @@
 
 	memcpy(ictx->usb_tx_buf, &ir_proto_packet, sizeof(ir_proto_packet));
 
+	if (!mutex_is_locked(&ictx->lock)) {
+		unlock = true;
+		mutex_lock(&ictx->lock);
+	}
+
 	retval = send_packet(ictx);
 	if (retval)
 		goto out;
@@ -1028,6 +1052,9 @@
 	ictx->pad_mouse = false;
 
 out:
+	if (unlock)
+		mutex_unlock(&ictx->lock);
+
 	return retval;
 }
 
@@ -1284,7 +1311,7 @@
 	 * contain a position coordinate (x,y), with each component ranging
 	 * from -14 to 14. We want to down-sample this to only 4 discrete values
 	 * for up/down/left/right arrow keys. Also, when you get too close to
-	 * diagonals, it has a tendancy to jump back and forth, so lets try to
+	 * diagonals, it has a tendency to jump back and forth, so lets try to
 	 * ignore when they get too close.
 	 */
 	if (ictx->product != 0xffdc) {
@@ -2125,6 +2152,7 @@
 		goto rdev_setup_failed;
 	}
 
+	mutex_unlock(&ictx->lock);
 	return ictx;
 
 rdev_setup_failed:
@@ -2196,6 +2224,7 @@
 		goto urb_submit_failed;
 	}
 
+	mutex_unlock(&ictx->lock);
 	return ictx;
 
 urb_submit_failed:
@@ -2290,6 +2319,8 @@
 	usb_set_intfdata(interface, ictx);
 
 	if (ifnum == 0) {
+		mutex_lock(&ictx->lock);
+
 		if (product == 0xffdc && ictx->rf_device) {
 			sysfs_err = sysfs_create_group(&interface->dev.kobj,
 						       &imon_rf_attr_group);
@@ -2300,13 +2331,14 @@
 
 		if (ictx->display_supported)
 			imon_init_display(ictx, interface);
+
+		mutex_unlock(&ictx->lock);
 	}
 
 	dev_info(dev, "iMON device (%04x:%04x, intf%d) on "
 		 "usb<%d:%d> initialized\n", vendor, product, ifnum,
 		 usbdev->bus->busnum, usbdev->devnum);
 
-	mutex_unlock(&ictx->lock);
 	mutex_unlock(&driver_lock);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/ir-nec-decoder.c linux-libre-2.6.39-gnu/drivers/media/rc/ir-nec-decoder.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/ir-nec-decoder.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/ir-nec-decoder.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,6 +49,7 @@
 	struct nec_dec *data = &dev->raw->nec;
 	u32 scancode;
 	u8 address, not_address, command, not_command;
+	bool send_32bits = false;
 
 	if (!(dev->raw->enabled_protocols & RC_TYPE_NEC))
 		return 0;
@@ -164,10 +165,15 @@
 		if ((command ^ not_command) != 0xff) {
 			IR_dprintk(1, "NEC checksum error: received 0x%08x\n",
 				   data->bits);
-			break;
+			send_32bits = true;
 		}
 
-		if ((address ^ not_address) != 0xff) {
+		if (send_32bits) {
+			/* NEC transport, but modified protocol, used by at
+			 * least Apple and TiVo remotes */
+			scancode = data->bits;
+			IR_dprintk(1, "NEC (modified) scancode 0x%08x\n", scancode);
+		} else if ((address ^ not_address) != 0xff) {
 			/* Extended NEC */
 			scancode = address     << 16 |
 				   not_address <<  8 |
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/ir-raw.c linux-libre-2.6.39-gnu/drivers/media/rc/ir-raw.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/ir-raw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/ir-raw.c	2011-05-19 00:06:34.000000000 -0400
@@ -153,7 +153,7 @@
  * @type:	the type of the event that has occurred
  *
  * This routine (which may be called from an interrupt context) works
- * in similiar manner to ir_raw_event_store_edge.
+ * in similar manner to ir_raw_event_store_edge.
  * This routine is intended for devices with limited internal buffer
  * It automerges samples of same type, and handles timeouts
  */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/ite-cir.c linux-libre-2.6.39-gnu/drivers/media/rc/ite-cir.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/ite-cir.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/rc/ite-cir.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1738 @@
+/*
+ * Driver for ITE Tech Inc. IT8712F/IT8512 CIR
+ *
+ * Copyright (C) 2010 Juan JesÃºs GarcÃ­a de Soria <skandalfo@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ *
+ * Inspired by the original lirc_it87 and lirc_ite8709 drivers, on top of the
+ * skeleton provided by the nuvoton-cir driver.
+ *
+ * The lirc_it87 driver was originally written by Hans-Gunter Lutke Uphues
+ * <hg_lu@web.de> in 2001, with enhancements by Christoph Bartelmus
+ * <lirc@bartelmus.de>, Andrew Calkin <r_tay@hotmail.com> and James Edwards
+ * <jimbo-lirc@edwardsclan.net>.
+ *
+ * The lirc_ite8709 driver was written by GrÃ©gory LardiÃ¨re
+ * <spmf2004-lirc@yahoo.fr> in 2008.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/pnp.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/bitops.h>
+#include <media/rc-core.h>
+#include <linux/pci_ids.h>
+#include <linux/delay.h>
+
+#include "ite-cir.h"
+
+/* module parameters */
+
+/* debug level */
+static int debug;
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Enable debugging output");
+
+/* low limit for RX carrier freq, Hz, 0 for no RX demodulation */
+static int rx_low_carrier_freq;
+module_param(rx_low_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rx_low_carrier_freq, "Override low RX carrier frequency, Hz, "
+		 "0 for no RX demodulation");
+
+/* high limit for RX carrier freq, Hz, 0 for no RX demodulation */
+static int rx_high_carrier_freq;
+module_param(rx_high_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(rx_high_carrier_freq, "Override high RX carrier frequency, "
+		 "Hz, 0 for no RX demodulation");
+
+/* override tx carrier frequency */
+static int tx_carrier_freq;
+module_param(tx_carrier_freq, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_carrier_freq, "Override TX carrier frequency, Hz");
+
+/* override tx duty cycle */
+static int tx_duty_cycle;
+module_param(tx_duty_cycle, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(tx_duty_cycle, "Override TX duty cycle, 1-100");
+
+/* override default sample period */
+static long sample_period;
+module_param(sample_period, long, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(sample_period, "Override carrier sample period, us");
+
+/* override detected model id */
+static int model_number = -1;
+module_param(model_number, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(model_number, "Use this model number, don't autodetect");
+
+
+/* HW-independent code functions */
+
+/* check whether carrier frequency is high frequency */
+static inline bool ite_is_high_carrier_freq(unsigned int freq)
+{
+	return freq >= ITE_HCF_MIN_CARRIER_FREQ;
+}
+
+/* get the bits required to program the carrier frequency in CFQ bits,
+ * unshifted */
+static u8 ite_get_carrier_freq_bits(unsigned int freq)
+{
+	if (ite_is_high_carrier_freq(freq)) {
+		if (freq < 425000)
+			return ITE_CFQ_400;
+
+		else if (freq < 465000)
+			return ITE_CFQ_450;
+
+		else if (freq < 490000)
+			return ITE_CFQ_480;
+
+		else
+			return ITE_CFQ_500;
+	} else {
+			/* trim to limits */
+		if (freq < ITE_LCF_MIN_CARRIER_FREQ)
+			freq = ITE_LCF_MIN_CARRIER_FREQ;
+		if (freq > ITE_LCF_MAX_CARRIER_FREQ)
+			freq = ITE_LCF_MAX_CARRIER_FREQ;
+
+		/* convert to kHz and subtract the base freq */
+		freq =
+		    DIV_ROUND_CLOSEST(freq - ITE_LCF_MIN_CARRIER_FREQ,
+				      1000);
+
+		return (u8) freq;
+	}
+}
+
+/* get the bits required to program the pulse with in TXMPW */
+static u8 ite_get_pulse_width_bits(unsigned int freq, int duty_cycle)
+{
+	unsigned long period_ns, on_ns;
+
+	/* sanitize freq into range */
+	if (freq < ITE_LCF_MIN_CARRIER_FREQ)
+		freq = ITE_LCF_MIN_CARRIER_FREQ;
+	if (freq > ITE_HCF_MAX_CARRIER_FREQ)
+		freq = ITE_HCF_MAX_CARRIER_FREQ;
+
+	period_ns = 1000000000UL / freq;
+	on_ns = period_ns * duty_cycle / 100;
+
+	if (ite_is_high_carrier_freq(freq)) {
+		if (on_ns < 750)
+			return ITE_TXMPW_A;
+
+		else if (on_ns < 850)
+			return ITE_TXMPW_B;
+
+		else if (on_ns < 950)
+			return ITE_TXMPW_C;
+
+		else if (on_ns < 1080)
+			return ITE_TXMPW_D;
+
+		else
+			return ITE_TXMPW_E;
+	} else {
+		if (on_ns < 6500)
+			return ITE_TXMPW_A;
+
+		else if (on_ns < 7850)
+			return ITE_TXMPW_B;
+
+		else if (on_ns < 9650)
+			return ITE_TXMPW_C;
+
+		else if (on_ns < 11950)
+			return ITE_TXMPW_D;
+
+		else
+			return ITE_TXMPW_E;
+	}
+}
+
+/* decode raw bytes as received by the hardware, and push them to the ir-core
+ * layer */
+static void ite_decode_bytes(struct ite_dev *dev, const u8 * data, int
+			     length)
+{
+	u32 sample_period;
+	unsigned long *ldata;
+	unsigned int next_one, next_zero, size;
+	DEFINE_IR_RAW_EVENT(ev);
+
+	if (length == 0)
+		return;
+
+	sample_period = dev->params.sample_period;
+	ldata = (unsigned long *)data;
+	size = length << 3;
+	next_one = find_next_bit_le(ldata, size, 0);
+	if (next_one > 0) {
+		ev.pulse = true;
+		ev.duration =
+		    ITE_BITS_TO_NS(next_one, sample_period);
+		ir_raw_event_store_with_filter(dev->rdev, &ev);
+	}
+
+	while (next_one < size) {
+		next_zero = find_next_zero_bit_le(ldata, size, next_one + 1);
+		ev.pulse = false;
+		ev.duration = ITE_BITS_TO_NS(next_zero - next_one, sample_period);
+		ir_raw_event_store_with_filter(dev->rdev, &ev);
+
+		if (next_zero < size) {
+			next_one =
+			    find_next_bit_le(ldata,
+						     size,
+						     next_zero + 1);
+			ev.pulse = true;
+			ev.duration =
+			    ITE_BITS_TO_NS(next_one - next_zero,
+					   sample_period);
+			ir_raw_event_store_with_filter
+			    (dev->rdev, &ev);
+		} else
+			next_one = size;
+	}
+
+	ir_raw_event_handle(dev->rdev);
+
+	ite_dbg_verbose("decoded %d bytes.", length);
+}
+
+/* set all the rx/tx carrier parameters; this must be called with the device
+ * spinlock held */
+static void ite_set_carrier_params(struct ite_dev *dev)
+{
+	unsigned int freq, low_freq, high_freq;
+	int allowance;
+	bool use_demodulator;
+	bool for_tx = dev->transmitting;
+
+	ite_dbg("%s called", __func__);
+
+	if (for_tx) {
+		/* we don't need no stinking calculations */
+		freq = dev->params.tx_carrier_freq;
+		allowance = ITE_RXDCR_DEFAULT;
+		use_demodulator = false;
+	} else {
+		low_freq = dev->params.rx_low_carrier_freq;
+		high_freq = dev->params.rx_high_carrier_freq;
+
+		if (low_freq == 0) {
+			/* don't demodulate */
+			freq =
+			ITE_DEFAULT_CARRIER_FREQ;
+			allowance = ITE_RXDCR_DEFAULT;
+			use_demodulator = false;
+		} else {
+			/* calculate the middle freq */
+			freq = (low_freq + high_freq) / 2;
+
+			/* calculate the allowance */
+			allowance =
+			    DIV_ROUND_CLOSEST(10000 * (high_freq - low_freq),
+					      ITE_RXDCR_PER_10000_STEP
+					      * (high_freq + low_freq));
+
+			if (allowance < 1)
+				allowance = 1;
+
+			if (allowance > ITE_RXDCR_MAX)
+				allowance = ITE_RXDCR_MAX;
+		}
+	}
+
+	/* set the carrier parameters in a device-dependent way */
+	dev->params.set_carrier_params(dev, ite_is_high_carrier_freq(freq),
+		 use_demodulator, ite_get_carrier_freq_bits(freq), allowance,
+		 ite_get_pulse_width_bits(freq, dev->params.tx_duty_cycle));
+}
+
+/* interrupt service routine for incoming and outgoing CIR data */
+static irqreturn_t ite_cir_isr(int irq, void *data)
+{
+	struct ite_dev *dev = data;
+	unsigned long flags;
+	irqreturn_t ret = IRQ_RETVAL(IRQ_NONE);
+	u8 rx_buf[ITE_RX_FIFO_LEN];
+	int rx_bytes;
+	int iflags;
+
+	ite_dbg_verbose("%s firing", __func__);
+
+	/* grab the spinlock */
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* read the interrupt flags */
+	iflags = dev->params.get_irq_causes(dev);
+
+	/* check for the receive interrupt */
+	if (iflags & (ITE_IRQ_RX_FIFO | ITE_IRQ_RX_FIFO_OVERRUN)) {
+		/* read the FIFO bytes */
+		rx_bytes =
+			dev->params.get_rx_bytes(dev, rx_buf,
+					     ITE_RX_FIFO_LEN);
+
+		if (rx_bytes > 0) {
+			/* drop the spinlock, since the ir-core layer
+			 * may call us back again through
+			 * ite_s_idle() */
+			spin_unlock_irqrestore(&dev->
+									 lock,
+									 flags);
+
+			/* decode the data we've just received */
+			ite_decode_bytes(dev, rx_buf,
+								   rx_bytes);
+
+			/* reacquire the spinlock */
+			spin_lock_irqsave(&dev->lock,
+								    flags);
+
+			/* mark the interrupt as serviced */
+			ret = IRQ_RETVAL(IRQ_HANDLED);
+		}
+	} else if (iflags & ITE_IRQ_TX_FIFO) {
+		/* FIFO space available interrupt */
+		ite_dbg_verbose("got interrupt for TX FIFO");
+
+		/* wake any sleeping transmitter */
+		wake_up_interruptible(&dev->tx_queue);
+
+		/* mark the interrupt as serviced */
+		ret = IRQ_RETVAL(IRQ_HANDLED);
+	}
+
+	/* drop the spinlock */
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	ite_dbg_verbose("%s done returning %d", __func__, (int)ret);
+
+	return ret;
+}
+
+/* set the rx carrier freq range, guess it's in Hz... */
+static int ite_set_rx_carrier_range(struct rc_dev *rcdev, u32 carrier_low, u32
+				    carrier_high)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->params.rx_low_carrier_freq = carrier_low;
+	dev->params.rx_high_carrier_freq = carrier_high;
+	ite_set_carrier_params(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* set the tx carrier freq, guess it's in Hz... */
+static int ite_set_tx_carrier(struct rc_dev *rcdev, u32 carrier)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->params.tx_carrier_freq = carrier;
+	ite_set_carrier_params(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* set the tx duty cycle by controlling the pulse width */
+static int ite_set_tx_duty_cycle(struct rc_dev *rcdev, u32 duty_cycle)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->params.tx_duty_cycle = duty_cycle;
+	ite_set_carrier_params(dev);
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* transmit out IR pulses; what you get here is a batch of alternating
+ * pulse/space/pulse/space lengths that we should write out completely through
+ * the FIFO, blocking on a full FIFO */
+static int ite_tx_ir(struct rc_dev *rcdev, int *txbuf, u32 n)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+	bool is_pulse = false;
+	int remaining_us, fifo_avail, fifo_remaining, last_idx = 0;
+	int max_rle_us, next_rle_us;
+	int ret = n;
+	u8 last_sent[ITE_TX_FIFO_LEN];
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	/* clear the array just in case */
+	memset(last_sent, 0, ARRAY_SIZE(last_sent));
+
+	/* n comes in bytes; convert to ints */
+	n /= sizeof(int);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* let everybody know we're now transmitting */
+	dev->transmitting = true;
+
+	/* and set the carrier values for transmission */
+	ite_set_carrier_params(dev);
+
+	/* calculate how much time we can send in one byte */
+	max_rle_us =
+	    (ITE_BAUDRATE_DIVISOR * dev->params.sample_period *
+	     ITE_TX_MAX_RLE) / 1000;
+
+	/* disable the receiver */
+	dev->params.disable_rx(dev);
+
+	/* this is where we'll begin filling in the FIFO, until it's full.
+	 * then we'll just activate the interrupt, wait for it to wake us up
+	 * again, disable it, continue filling the FIFO... until everything
+	 * has been pushed out */
+	fifo_avail =
+	    ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);
+
+	while (n > 0 && dev->in_use) {
+		/* transmit the next sample */
+		is_pulse = !is_pulse;
+		remaining_us = *(txbuf++);
+		n--;
+
+		ite_dbg("%s: %ld",
+				      ((is_pulse) ? "pulse" : "space"),
+				      (long int)
+				      remaining_us);
+
+		/* repeat while the pulse is non-zero length */
+		while (remaining_us > 0 && dev->in_use) {
+			if (remaining_us > max_rle_us)
+				next_rle_us = max_rle_us;
+
+			else
+				next_rle_us = remaining_us;
+
+			remaining_us -= next_rle_us;
+
+			/* check what's the length we have to pump out */
+			val = (ITE_TX_MAX_RLE * next_rle_us) / max_rle_us;
+
+			/* put it into the sent buffer */
+			last_sent[last_idx++] = val;
+			last_idx &= (ITE_TX_FIFO_LEN);
+
+			/* encode it for 7 bits */
+			val = (val - 1) & ITE_TX_RLE_MASK;
+
+			/* take into account pulse/space prefix */
+			if (is_pulse)
+				val |= ITE_TX_PULSE;
+
+			else
+				val |= ITE_TX_SPACE;
+
+			/*
+			 * if we get to 0 available, read again, just in case
+			 * some other slot got freed
+			 */
+			if (fifo_avail <= 0)
+				fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev);
+
+			/* if it's still full */
+			if (fifo_avail <= 0) {
+				/* enable the tx interrupt */
+				dev->params.
+				enable_tx_interrupt(dev);
+
+				/* drop the spinlock */
+				spin_unlock_irqrestore(&dev->lock, flags);
+
+				/* wait for the FIFO to empty enough */
+				wait_event_interruptible(dev->tx_queue, (fifo_avail = ITE_TX_FIFO_LEN - dev->params.get_tx_used_slots(dev)) >= 8);
+
+				/* get the spinlock again */
+				spin_lock_irqsave(&dev->lock, flags);
+
+				/* disable the tx interrupt again. */
+				dev->params.
+				disable_tx_interrupt(dev);
+			}
+
+			/* now send the byte through the FIFO */
+			dev->params.put_tx_byte(dev, val);
+			fifo_avail--;
+		}
+	}
+
+	/* wait and don't return until the whole FIFO has been sent out;
+	 * otherwise we could configure the RX carrier params instead of the
+	 * TX ones while the transmission is still being performed! */
+	fifo_remaining = dev->params.get_tx_used_slots(dev);
+	remaining_us = 0;
+	while (fifo_remaining > 0) {
+		fifo_remaining--;
+		last_idx--;
+		last_idx &= (ITE_TX_FIFO_LEN - 1);
+		remaining_us += last_sent[last_idx];
+	}
+	remaining_us = (remaining_us * max_rle_us) / (ITE_TX_MAX_RLE);
+
+	/* drop the spinlock while we sleep */
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* sleep remaining_us microseconds */
+	mdelay(DIV_ROUND_UP(remaining_us, 1000));
+
+	/* reacquire the spinlock */
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* now we're not transmitting anymore */
+	dev->transmitting = false;
+
+	/* and set the carrier values for reception */
+	ite_set_carrier_params(dev);
+
+	/* reenable the receiver */
+	if (dev->in_use)
+		dev->params.enable_rx(dev);
+
+	/* notify transmission end */
+	wake_up_interruptible(&dev->tx_ended);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return ret;
+}
+
+/* idle the receiver if needed */
+static void ite_s_idle(struct rc_dev *rcdev, bool enable)
+{
+	unsigned long flags;
+	struct ite_dev *dev = rcdev->priv;
+
+	ite_dbg("%s called", __func__);
+
+	if (enable) {
+		spin_lock_irqsave(&dev->lock, flags);
+		dev->params.idle_rx(dev);
+		spin_unlock_irqrestore(&dev->lock, flags);
+	}
+}
+
+
+/* IT8712F HW-specific functions */
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it87_get_irq_causes(struct ite_dev *dev)
+{
+	u8 iflags;
+	int ret = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read the interrupt flags */
+	iflags = inb(dev->cir_addr + IT87_IIR) & IT87_II;
+
+	switch (iflags) {
+	case IT87_II_RXDS:
+		ret = ITE_IRQ_RX_FIFO;
+		break;
+	case IT87_II_RXFO:
+		ret = ITE_IRQ_RX_FIFO_OVERRUN;
+		break;
+	case IT87_II_TXLDL:
+		ret = ITE_IRQ_TX_FIFO;
+		break;
+	}
+
+	return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it87_set_carrier_params(struct ite_dev *dev, bool high_freq,
+				    bool use_demodulator,
+				    u8 carrier_freq_bits, u8 allowance_bits,
+				    u8 pulse_width_bits)
+{
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	/* program the RCR register */
+	val = inb(dev->cir_addr + IT87_RCR)
+		& ~(IT87_HCFS | IT87_RXEND | IT87_RXDCR);
+
+	if (high_freq)
+		val |= IT87_HCFS;
+
+	if (use_demodulator)
+		val |= IT87_RXEND;
+
+	val |= allowance_bits;
+
+	outb(val, dev->cir_addr + IT87_RCR);
+
+	/* program the TCR2 register */
+	outb((carrier_freq_bits << IT87_CFQ_SHIFT) | pulse_width_bits,
+		dev->cir_addr + IT87_TCR2);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it87_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+	int fifo, read = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read how many bytes are still in the FIFO */
+	fifo = inb(dev->cir_addr + IT87_RSR) & IT87_RXFBC;
+
+	while (fifo > 0 && buf_size > 0) {
+		*(buf++) = inb(dev->cir_addr + IT87_DR);
+		fifo--;
+		read++;
+		buf_size--;
+	}
+
+	return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it87_get_tx_used_slots(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	return inb(dev->cir_addr + IT87_TSR) & IT87_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it87_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+	outb(value, dev->cir_addr + IT87_DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+  pulse is detected; this must be called with the device spinlock held */
+static void it87_idle_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable streaming by clearing RXACT writing it as 1 */
+	outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXACT,
+		dev->cir_addr + IT87_RCR);
+
+	/* clear the FIFO */
+	outb(inb(dev->cir_addr + IT87_TCR1) | IT87_FIFOCLR,
+		dev->cir_addr + IT87_TCR1);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it87_disable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the receiver interrupts */
+	outb(inb(dev->cir_addr + IT87_IER) & ~(IT87_RDAIE | IT87_RFOIE),
+		dev->cir_addr + IT87_IER);
+
+	/* disable the receiver */
+	outb(inb(dev->cir_addr + IT87_RCR) & ~IT87_RXEN,
+		dev->cir_addr + IT87_RCR);
+
+	/* clear the FIFO and RXACT (actually RXACT should have been cleared
+	* in the previous outb() call) */
+	it87_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it87_enable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the receiver by setting RXEN */
+	outb(inb(dev->cir_addr + IT87_RCR) | IT87_RXEN,
+		dev->cir_addr + IT87_RCR);
+
+	/* just prepare it to idle for the next reception */
+	it87_idle_rx(dev);
+
+	/* enable the receiver interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT87_IER) | IT87_RDAIE | IT87_RFOIE | IT87_IEC,
+		dev->cir_addr + IT87_IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it87_disable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the transmitter interrupts */
+	outb(inb(dev->cir_addr + IT87_IER) & ~IT87_TLDLIE,
+		dev->cir_addr + IT87_IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it87_enable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the transmitter interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT87_IER) | IT87_TLDLIE | IT87_IEC,
+		dev->cir_addr + IT87_IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it87_disable(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* clear out all interrupt enable flags */
+	outb(inb(dev->cir_addr + IT87_IER) &
+		~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE),
+		dev->cir_addr + IT87_IER);
+
+	/* disable the receiver */
+	it87_disable_rx(dev);
+
+	/* erase the FIFO */
+	outb(IT87_FIFOCLR | inb(dev->cir_addr + IT87_TCR1),
+		dev->cir_addr + IT87_TCR1);
+}
+
+/* initialize the hardware */
+static void it87_init_hardware(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable just the baud rate divisor register,
+	disabling all the interrupts at the same time */
+	outb((inb(dev->cir_addr + IT87_IER) &
+		~(IT87_IEC | IT87_RFOIE | IT87_RDAIE | IT87_TLDLIE)) | IT87_BR,
+		dev->cir_addr + IT87_IER);
+
+	/* write out the baud rate divisor */
+	outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT87_BDLR);
+	outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff, dev->cir_addr + IT87_BDHR);
+
+	/* disable the baud rate divisor register again */
+	outb(inb(dev->cir_addr + IT87_IER) & ~IT87_BR,
+		dev->cir_addr + IT87_IER);
+
+	/* program the RCR register defaults */
+	outb(ITE_RXDCR_DEFAULT, dev->cir_addr + IT87_RCR);
+
+	/* program the TCR1 register */
+	outb(IT87_TXMPM_DEFAULT | IT87_TXENDF | IT87_TXRLE
+		| IT87_FIFOTL_DEFAULT | IT87_FIFOCLR,
+		dev->cir_addr + IT87_TCR1);
+
+	/* program the carrier parameters */
+	ite_set_carrier_params(dev);
+}
+
+/* IT8512F on ITE8708 HW-specific functions */
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it8708_get_irq_causes(struct ite_dev *dev)
+{
+	u8 iflags;
+	int ret = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read the interrupt flags */
+	iflags = inb(dev->cir_addr + IT8708_C0IIR);
+
+	if (iflags & IT85_TLDLI)
+		ret |= ITE_IRQ_TX_FIFO;
+	if (iflags & IT85_RDAI)
+		ret |= ITE_IRQ_RX_FIFO;
+	if (iflags & IT85_RFOI)
+		ret |= ITE_IRQ_RX_FIFO_OVERRUN;
+
+	return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it8708_set_carrier_params(struct ite_dev *dev, bool high_freq,
+				      bool use_demodulator,
+				      u8 carrier_freq_bits, u8 allowance_bits,
+				      u8 pulse_width_bits)
+{
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	/* program the C0CFR register, with HRAE=1 */
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE,
+		dev->cir_addr + IT8708_BANKSEL);
+
+	val = (inb(dev->cir_addr + IT8708_C0CFR)
+		& ~(IT85_HCFS | IT85_CFQ)) | carrier_freq_bits;
+
+	if (high_freq)
+		val |= IT85_HCFS;
+
+	outb(val, dev->cir_addr + IT8708_C0CFR);
+
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE,
+		   dev->cir_addr + IT8708_BANKSEL);
+
+	/* program the C0RCR register */
+	val = inb(dev->cir_addr + IT8708_C0RCR)
+		& ~(IT85_RXEND | IT85_RXDCR);
+
+	if (use_demodulator)
+		val |= IT85_RXEND;
+
+	val |= allowance_bits;
+
+	outb(val, dev->cir_addr + IT8708_C0RCR);
+
+	/* program the C0TCR register */
+	val = inb(dev->cir_addr + IT8708_C0TCR) & ~IT85_TXMPW;
+	val |= pulse_width_bits;
+	outb(val, dev->cir_addr + IT8708_C0TCR);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it8708_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+	int fifo, read = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read how many bytes are still in the FIFO */
+	fifo = inb(dev->cir_addr + IT8708_C0RFSR) & IT85_RXFBC;
+
+	while (fifo > 0 && buf_size > 0) {
+		*(buf++) = inb(dev->cir_addr + IT8708_C0DR);
+		fifo--;
+		read++;
+		buf_size--;
+	}
+
+	return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it8708_get_tx_used_slots(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	return inb(dev->cir_addr + IT8708_C0TFSR) & IT85_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it8708_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+	outb(value, dev->cir_addr + IT8708_C0DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+  pulse is detected; this must be called with the device spinlock held */
+static void it8708_idle_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable streaming by clearing RXACT writing it as 1 */
+	outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXACT,
+		dev->cir_addr + IT8708_C0RCR);
+
+	/* clear the FIFO */
+	outb(inb(dev->cir_addr + IT8708_C0MSTCR) | IT85_FIFOCLR,
+		dev->cir_addr + IT8708_C0MSTCR);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it8708_disable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the receiver interrupts */
+	outb(inb(dev->cir_addr + IT8708_C0IER) &
+		~(IT85_RDAIE | IT85_RFOIE),
+		dev->cir_addr + IT8708_C0IER);
+
+	/* disable the receiver */
+	outb(inb(dev->cir_addr + IT8708_C0RCR) & ~IT85_RXEN,
+		dev->cir_addr + IT8708_C0RCR);
+
+	/* clear the FIFO and RXACT (actually RXACT should have been cleared
+	 * in the previous outb() call) */
+	it8708_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it8708_enable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the receiver by setting RXEN */
+	outb(inb(dev->cir_addr + IT8708_C0RCR) | IT85_RXEN,
+		dev->cir_addr + IT8708_C0RCR);
+
+	/* just prepare it to idle for the next reception */
+	it8708_idle_rx(dev);
+
+	/* enable the receiver interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT8708_C0IER)
+		|IT85_RDAIE | IT85_RFOIE | IT85_IEC,
+		dev->cir_addr + IT8708_C0IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8708_disable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the transmitter interrupts */
+	outb(inb(dev->cir_addr + IT8708_C0IER) & ~IT85_TLDLIE,
+		dev->cir_addr + IT8708_C0IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8708_enable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the transmitter interrupts and master enable flag */
+	outb(inb(dev->cir_addr + IT8708_C0IER)
+		|IT85_TLDLIE | IT85_IEC,
+		dev->cir_addr + IT8708_C0IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it8708_disable(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* clear out all interrupt enable flags */
+	outb(inb(dev->cir_addr + IT8708_C0IER) &
+		~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE),
+		dev->cir_addr + IT8708_C0IER);
+
+	/* disable the receiver */
+	it8708_disable_rx(dev);
+
+	/* erase the FIFO */
+	outb(IT85_FIFOCLR | inb(dev->cir_addr + IT8708_C0MSTCR),
+		dev->cir_addr + IT8708_C0MSTCR);
+}
+
+/* initialize the hardware */
+static void it8708_init_hardware(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable all the interrupts */
+	outb(inb(dev->cir_addr + IT8708_C0IER) &
+		~(IT85_IEC | IT85_RFOIE | IT85_RDAIE | IT85_TLDLIE),
+		dev->cir_addr + IT8708_C0IER);
+
+	/* program the baud rate divisor */
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) | IT8708_HRAE,
+		dev->cir_addr + IT8708_BANKSEL);
+
+	outb(ITE_BAUDRATE_DIVISOR & 0xff, dev->cir_addr + IT8708_C0BDLR);
+	outb((ITE_BAUDRATE_DIVISOR >> 8) & 0xff,
+		   dev->cir_addr + IT8708_C0BDHR);
+
+	outb(inb(dev->cir_addr + IT8708_BANKSEL) & ~IT8708_HRAE,
+		   dev->cir_addr + IT8708_BANKSEL);
+
+	/* program the C0MSTCR register defaults */
+	outb((inb(dev->cir_addr + IT8708_C0MSTCR) &
+			~(IT85_ILSEL | IT85_ILE | IT85_FIFOTL |
+			  IT85_FIFOCLR | IT85_RESET)) |
+		       IT85_FIFOTL_DEFAULT,
+		       dev->cir_addr + IT8708_C0MSTCR);
+
+	/* program the C0RCR register defaults */
+	outb((inb(dev->cir_addr + IT8708_C0RCR) &
+			~(IT85_RXEN | IT85_RDWOS | IT85_RXEND |
+			  IT85_RXACT | IT85_RXDCR)) |
+		       ITE_RXDCR_DEFAULT,
+		       dev->cir_addr + IT8708_C0RCR);
+
+	/* program the C0TCR register defaults */
+	outb((inb(dev->cir_addr + IT8708_C0TCR) &
+			~(IT85_TXMPM | IT85_TXMPW))
+		       |IT85_TXRLE | IT85_TXENDF |
+		       IT85_TXMPM_DEFAULT | IT85_TXMPW_DEFAULT,
+		       dev->cir_addr + IT8708_C0TCR);
+
+	/* program the carrier parameters */
+	ite_set_carrier_params(dev);
+}
+
+/* IT8512F on ITE8709 HW-specific functions */
+
+/* read a byte from the SRAM module */
+static inline u8 it8709_rm(struct ite_dev *dev, int index)
+{
+	outb(index, dev->cir_addr + IT8709_RAM_IDX);
+	return inb(dev->cir_addr + IT8709_RAM_VAL);
+}
+
+/* write a byte to the SRAM module */
+static inline void it8709_wm(struct ite_dev *dev, u8 val, int index)
+{
+	outb(index, dev->cir_addr + IT8709_RAM_IDX);
+	outb(val, dev->cir_addr + IT8709_RAM_VAL);
+}
+
+static void it8709_wait(struct ite_dev *dev)
+{
+	int i = 0;
+	/*
+	 * loop until device tells it's ready to continue
+	 * iterations count is usually ~750 but can sometimes achieve 13000
+	 */
+	for (i = 0; i < 15000; i++) {
+		udelay(2);
+		if (it8709_rm(dev, IT8709_MODE) == IT8709_IDLE)
+			break;
+	}
+}
+
+/* read the value of a CIR register */
+static u8 it8709_rr(struct ite_dev *dev, int index)
+{
+	/* just wait in case the previous access was a write */
+	it8709_wait(dev);
+	it8709_wm(dev, index, IT8709_REG_IDX);
+	it8709_wm(dev, IT8709_READ, IT8709_MODE);
+
+	/* wait for the read data to be available */
+	it8709_wait(dev);
+
+	/* return the read value */
+	return it8709_rm(dev, IT8709_REG_VAL);
+}
+
+/* write the value of a CIR register */
+static void it8709_wr(struct ite_dev *dev, u8 val, int index)
+{
+	/* we wait before writing, and not afterwards, since this allows us to
+	 * pipeline the host CPU with the microcontroller */
+	it8709_wait(dev);
+	it8709_wm(dev, val, IT8709_REG_VAL);
+	it8709_wm(dev, index, IT8709_REG_IDX);
+	it8709_wm(dev, IT8709_WRITE, IT8709_MODE);
+}
+
+/* retrieve a bitmask of the current causes for a pending interrupt; this may
+ * be composed of ITE_IRQ_TX_FIFO, ITE_IRQ_RX_FIFO and ITE_IRQ_RX_FIFO_OVERRUN
+ * */
+static int it8709_get_irq_causes(struct ite_dev *dev)
+{
+	u8 iflags;
+	int ret = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read the interrupt flags */
+	iflags = it8709_rm(dev, IT8709_IIR);
+
+	if (iflags & IT85_TLDLI)
+		ret |= ITE_IRQ_TX_FIFO;
+	if (iflags & IT85_RDAI)
+		ret |= ITE_IRQ_RX_FIFO;
+	if (iflags & IT85_RFOI)
+		ret |= ITE_IRQ_RX_FIFO_OVERRUN;
+
+	return ret;
+}
+
+/* set the carrier parameters; to be called with the spinlock held */
+static void it8709_set_carrier_params(struct ite_dev *dev, bool high_freq,
+				      bool use_demodulator,
+				      u8 carrier_freq_bits, u8 allowance_bits,
+				      u8 pulse_width_bits)
+{
+	u8 val;
+
+	ite_dbg("%s called", __func__);
+
+	val = (it8709_rr(dev, IT85_C0CFR)
+		     &~(IT85_HCFS | IT85_CFQ)) |
+	    carrier_freq_bits;
+
+	if (high_freq)
+		val |= IT85_HCFS;
+
+	it8709_wr(dev, val, IT85_C0CFR);
+
+	/* program the C0RCR register */
+	val = it8709_rr(dev, IT85_C0RCR)
+		& ~(IT85_RXEND | IT85_RXDCR);
+
+	if (use_demodulator)
+		val |= IT85_RXEND;
+
+	val |= allowance_bits;
+
+	it8709_wr(dev, val, IT85_C0RCR);
+
+	/* program the C0TCR register */
+	val = it8709_rr(dev, IT85_C0TCR) & ~IT85_TXMPW;
+	val |= pulse_width_bits;
+	it8709_wr(dev, val, IT85_C0TCR);
+}
+
+/* read up to buf_size bytes from the RX FIFO; to be called with the spinlock
+ * held */
+static int it8709_get_rx_bytes(struct ite_dev *dev, u8 * buf, int buf_size)
+{
+	int fifo, read = 0;
+
+	ite_dbg("%s called", __func__);
+
+	/* read how many bytes are still in the FIFO */
+	fifo = it8709_rm(dev, IT8709_RFSR) & IT85_RXFBC;
+
+	while (fifo > 0 && buf_size > 0) {
+		*(buf++) = it8709_rm(dev, IT8709_FIFO + read);
+		fifo--;
+		read++;
+		buf_size--;
+	}
+
+	/* 'clear' the FIFO by setting the writing index to 0; this is
+	 * completely bound to be racy, but we can't help it, since it's a
+	 * limitation of the protocol */
+	it8709_wm(dev, 0, IT8709_RFSR);
+
+	return read;
+}
+
+/* return how many bytes are still in the FIFO; this will be called
+ * with the device spinlock NOT HELD while waiting for the TX FIFO to get
+ * empty; let's expect this won't be a problem */
+static int it8709_get_tx_used_slots(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	return it8709_rr(dev, IT85_C0TFSR) & IT85_TXFBC;
+}
+
+/* put a byte to the TX fifo; this should be called with the spinlock held */
+static void it8709_put_tx_byte(struct ite_dev *dev, u8 value)
+{
+	it8709_wr(dev, value, IT85_C0DR);
+}
+
+/* idle the receiver so that we won't receive samples until another
+  pulse is detected; this must be called with the device spinlock held */
+static void it8709_idle_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable streaming by clearing RXACT writing it as 1 */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXACT,
+			    IT85_C0RCR);
+
+	/* clear the FIFO */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0MSTCR) | IT85_FIFOCLR,
+			    IT85_C0MSTCR);
+}
+
+/* disable the receiver; this must be called with the device spinlock held */
+static void it8709_disable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the receiver interrupts */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER) &
+			    ~(IT85_RDAIE | IT85_RFOIE),
+			    IT85_C0IER);
+
+	/* disable the receiver */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) & ~IT85_RXEN,
+			    IT85_C0RCR);
+
+	/* clear the FIFO and RXACT (actually RXACT should have been cleared
+	 * in the previous it8709_wr(dev, ) call) */
+	it8709_idle_rx(dev);
+}
+
+/* enable the receiver; this must be called with the device spinlock held */
+static void it8709_enable_rx(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the receiver by setting RXEN */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0RCR) | IT85_RXEN,
+			    IT85_C0RCR);
+
+	/* just prepare it to idle for the next reception */
+	it8709_idle_rx(dev);
+
+	/* enable the receiver interrupts and master enable flag */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER)
+			    |IT85_RDAIE | IT85_RFOIE | IT85_IEC,
+			    IT85_C0IER);
+}
+
+/* disable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8709_disable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable the transmitter interrupts */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER) & ~IT85_TLDLIE,
+			    IT85_C0IER);
+}
+
+/* enable the transmitter interrupt; this must be called with the device
+ * spinlock held */
+static void it8709_enable_tx_interrupt(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* enable the transmitter interrupts and master enable flag */
+	it8709_wr(dev, it8709_rr(dev, IT85_C0IER)
+			    |IT85_TLDLIE | IT85_IEC,
+			    IT85_C0IER);
+}
+
+/* disable the device; this must be called with the device spinlock held */
+static void it8709_disable(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* clear out all interrupt enable flags */
+	it8709_wr(dev,
+			    it8709_rr(dev,
+				      IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE |
+						      IT85_RDAIE |
+						      IT85_TLDLIE), IT85_C0IER);
+
+	/* disable the receiver */
+	it8709_disable_rx(dev);
+
+	/* erase the FIFO */
+	it8709_wr(dev, IT85_FIFOCLR | it8709_rr(dev, IT85_C0MSTCR),
+			    IT85_C0MSTCR);
+}
+
+/* initialize the hardware */
+static void it8709_init_hardware(struct ite_dev *dev)
+{
+	ite_dbg("%s called", __func__);
+
+	/* disable all the interrupts */
+	it8709_wr(dev,
+			    it8709_rr(dev,
+				      IT85_C0IER) & ~(IT85_IEC | IT85_RFOIE |
+						      IT85_RDAIE |
+						      IT85_TLDLIE), IT85_C0IER);
+
+	/* program the baud rate divisor */
+	it8709_wr(dev, ITE_BAUDRATE_DIVISOR & 0xff, IT85_C0BDLR);
+	it8709_wr(dev, (ITE_BAUDRATE_DIVISOR >> 8) & 0xff,
+			IT85_C0BDHR);
+
+	/* program the C0MSTCR register defaults */
+	it8709_wr(dev, (it8709_rr(dev, IT85_C0MSTCR) & ~(IT85_ILSEL |
+								   IT85_ILE
+								   | IT85_FIFOTL
+								   |
+								   IT85_FIFOCLR
+								   |
+								   IT85_RESET))
+			    | IT85_FIFOTL_DEFAULT, IT85_C0MSTCR);
+
+	/* program the C0RCR register defaults */
+	it8709_wr(dev,
+			    (it8709_rr(dev, IT85_C0RCR) &
+			     ~(IT85_RXEN | IT85_RDWOS | IT85_RXEND
+			       | IT85_RXACT | IT85_RXDCR)) |
+			    ITE_RXDCR_DEFAULT, IT85_C0RCR);
+
+	/* program the C0TCR register defaults */
+	it8709_wr(dev, (it8709_rr(dev, IT85_C0TCR)
+				  &~(IT85_TXMPM | IT85_TXMPW))
+			    |IT85_TXRLE | IT85_TXENDF |
+			    IT85_TXMPM_DEFAULT |
+			    IT85_TXMPW_DEFAULT, IT85_C0TCR);
+
+	/* program the carrier parameters */
+	ite_set_carrier_params(dev);
+}
+
+
+/* generic hardware setup/teardown code */
+
+/* activate the device for use */
+static int ite_open(struct rc_dev *rcdev)
+{
+	struct ite_dev *dev = rcdev->priv;
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->in_use = true;
+
+	/* enable the receiver */
+	dev->params.enable_rx(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+/* deactivate the device for use */
+static void ite_close(struct rc_dev *rcdev)
+{
+	struct ite_dev *dev = rcdev->priv;
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+	dev->in_use = false;
+
+	/* wait for any transmission to end */
+	spin_unlock_irqrestore(&dev->lock, flags);
+	wait_event_interruptible(dev->tx_ended, !dev->transmitting);
+	spin_lock_irqsave(&dev->lock, flags);
+
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+/* supported models and their parameters */
+static const struct ite_dev_params ite_dev_descs[] = {
+	{	/* 0: ITE8704 */
+	       .model = "ITE8704 CIR transceiver",
+	       .io_region_size = IT87_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it87_get_irq_causes,
+	       .enable_rx = it87_enable_rx,
+	       .idle_rx = it87_idle_rx,
+	       .disable_rx = it87_idle_rx,
+	       .get_rx_bytes = it87_get_rx_bytes,
+	       .enable_tx_interrupt = it87_enable_tx_interrupt,
+	       .disable_tx_interrupt = it87_disable_tx_interrupt,
+	       .get_tx_used_slots = it87_get_tx_used_slots,
+	       .put_tx_byte = it87_put_tx_byte,
+	       .disable = it87_disable,
+	       .init_hardware = it87_init_hardware,
+	       .set_carrier_params = it87_set_carrier_params,
+	       },
+	{	/* 1: ITE8713 */
+	       .model = "ITE8713 CIR transceiver",
+	       .io_region_size = IT87_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it87_get_irq_causes,
+	       .enable_rx = it87_enable_rx,
+	       .idle_rx = it87_idle_rx,
+	       .disable_rx = it87_idle_rx,
+	       .get_rx_bytes = it87_get_rx_bytes,
+	       .enable_tx_interrupt = it87_enable_tx_interrupt,
+	       .disable_tx_interrupt = it87_disable_tx_interrupt,
+	       .get_tx_used_slots = it87_get_tx_used_slots,
+	       .put_tx_byte = it87_put_tx_byte,
+	       .disable = it87_disable,
+	       .init_hardware = it87_init_hardware,
+	       .set_carrier_params = it87_set_carrier_params,
+	       },
+	{	/* 2: ITE8708 */
+	       .model = "ITE8708 CIR transceiver",
+	       .io_region_size = IT8708_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it8708_get_irq_causes,
+	       .enable_rx = it8708_enable_rx,
+	       .idle_rx = it8708_idle_rx,
+	       .disable_rx = it8708_idle_rx,
+	       .get_rx_bytes = it8708_get_rx_bytes,
+	       .enable_tx_interrupt = it8708_enable_tx_interrupt,
+	       .disable_tx_interrupt =
+	       it8708_disable_tx_interrupt,
+	       .get_tx_used_slots = it8708_get_tx_used_slots,
+	       .put_tx_byte = it8708_put_tx_byte,
+	       .disable = it8708_disable,
+	       .init_hardware = it8708_init_hardware,
+	       .set_carrier_params = it8708_set_carrier_params,
+	       },
+	{	/* 3: ITE8709 */
+	       .model = "ITE8709 CIR transceiver",
+	       .io_region_size = IT8709_IOREG_LENGTH,
+	       .hw_tx_capable = true,
+	       .sample_period = (u32) (1000000000ULL / 115200),
+	       .tx_carrier_freq = 38000,
+	       .tx_duty_cycle = 33,
+	       .rx_low_carrier_freq = 0,
+	       .rx_high_carrier_freq = 0,
+
+		/* operations */
+	       .get_irq_causes = it8709_get_irq_causes,
+	       .enable_rx = it8709_enable_rx,
+	       .idle_rx = it8709_idle_rx,
+	       .disable_rx = it8709_idle_rx,
+	       .get_rx_bytes = it8709_get_rx_bytes,
+	       .enable_tx_interrupt = it8709_enable_tx_interrupt,
+	       .disable_tx_interrupt =
+	       it8709_disable_tx_interrupt,
+	       .get_tx_used_slots = it8709_get_tx_used_slots,
+	       .put_tx_byte = it8709_put_tx_byte,
+	       .disable = it8709_disable,
+	       .init_hardware = it8709_init_hardware,
+	       .set_carrier_params = it8709_set_carrier_params,
+	       },
+};
+
+static const struct pnp_device_id ite_ids[] = {
+	{"ITE8704", 0},		/* Default model */
+	{"ITE8713", 1},		/* CIR found in EEEBox 1501U */
+	{"ITE8708", 2},		/* Bridged IT8512 */
+	{"ITE8709", 3},		/* SRAM-Bridged IT8512 */
+	{"", 0},
+};
+
+/* allocate memory, probe hardware, and initialize everything */
+static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
+		     *dev_id)
+{
+	const struct ite_dev_params *dev_desc = NULL;
+	struct ite_dev *itdev = NULL;
+	struct rc_dev *rdev = NULL;
+	int ret = -ENOMEM;
+	int model_no;
+
+	ite_dbg("%s called", __func__);
+
+	itdev = kzalloc(sizeof(struct ite_dev), GFP_KERNEL);
+	if (!itdev)
+		return ret;
+
+	/* input device for IR remote (and tx) */
+	rdev = rc_allocate_device();
+	if (!rdev)
+		goto failure;
+
+	ret = -ENODEV;
+
+	/* get the model number */
+	model_no = (int)dev_id->driver_data;
+	ite_pr(KERN_NOTICE, "Auto-detected model: %s\n",
+		ite_dev_descs[model_no].model);
+
+	if (model_number >= 0 && model_number < ARRAY_SIZE(ite_dev_descs)) {
+		model_no = model_number;
+		ite_pr(KERN_NOTICE, "The model has been fixed by a module "
+			"parameter.");
+	}
+
+	ite_pr(KERN_NOTICE, "Using model: %s\n", ite_dev_descs[model_no].model);
+
+	/* get the description for the device */
+	dev_desc = &ite_dev_descs[model_no];
+
+	/* validate pnp resources */
+	if (!pnp_port_valid(pdev, 0) ||
+	    pnp_port_len(pdev, 0) != dev_desc->io_region_size) {
+		dev_err(&pdev->dev, "IR PNP Port not valid!\n");
+		goto failure;
+	}
+
+	if (!pnp_irq_valid(pdev, 0)) {
+		dev_err(&pdev->dev, "PNP IRQ not valid!\n");
+		goto failure;
+	}
+
+	/* store resource values */
+	itdev->cir_addr = pnp_port_start(pdev, 0);
+	itdev->cir_irq = pnp_irq(pdev, 0);
+
+	/* initialize spinlocks */
+	spin_lock_init(&itdev->lock);
+
+	/* initialize raw event */
+	init_ir_raw_event(&itdev->rawir);
+
+	ret = -EBUSY;
+	/* now claim resources */
+	if (!request_region(itdev->cir_addr,
+				dev_desc->io_region_size, ITE_DRIVER_NAME))
+		goto failure;
+
+	if (request_irq(itdev->cir_irq, ite_cir_isr, IRQF_SHARED,
+			ITE_DRIVER_NAME, (void *)itdev))
+		goto failure;
+
+	/* set driver data into the pnp device */
+	pnp_set_drvdata(pdev, itdev);
+	itdev->pdev = pdev;
+
+	/* initialize waitqueues for transmission */
+	init_waitqueue_head(&itdev->tx_queue);
+	init_waitqueue_head(&itdev->tx_ended);
+
+	/* copy model-specific parameters */
+	itdev->params = *dev_desc;
+
+	/* apply any overrides */
+	if (sample_period > 0)
+		itdev->params.sample_period = sample_period;
+
+	if (tx_carrier_freq > 0)
+		itdev->params.tx_carrier_freq = tx_carrier_freq;
+
+	if (tx_duty_cycle > 0 && tx_duty_cycle <= 100)
+		itdev->params.tx_duty_cycle = tx_duty_cycle;
+
+	if (rx_low_carrier_freq > 0)
+		itdev->params.rx_low_carrier_freq = rx_low_carrier_freq;
+
+	if (rx_high_carrier_freq > 0)
+		itdev->params.rx_high_carrier_freq = rx_high_carrier_freq;
+
+	/* print out parameters */
+	ite_pr(KERN_NOTICE, "TX-capable: %d\n", (int)
+			 itdev->params.hw_tx_capable);
+	ite_pr(KERN_NOTICE, "Sample period (ns): %ld\n", (long)
+		     itdev->params.sample_period);
+	ite_pr(KERN_NOTICE, "TX carrier frequency (Hz): %d\n", (int)
+		     itdev->params.tx_carrier_freq);
+	ite_pr(KERN_NOTICE, "TX duty cycle (%%): %d\n", (int)
+		     itdev->params.tx_duty_cycle);
+	ite_pr(KERN_NOTICE, "RX low carrier frequency (Hz): %d\n", (int)
+		     itdev->params.rx_low_carrier_freq);
+	ite_pr(KERN_NOTICE, "RX high carrier frequency (Hz): %d\n", (int)
+		     itdev->params.rx_high_carrier_freq);
+
+	/* set up hardware initial state */
+	itdev->params.init_hardware(itdev);
+
+	/* set up ir-core props */
+	rdev->priv = itdev;
+	rdev->driver_type = RC_DRIVER_IR_RAW;
+	rdev->allowed_protos = RC_TYPE_ALL;
+	rdev->open = ite_open;
+	rdev->close = ite_close;
+	rdev->s_idle = ite_s_idle;
+	rdev->s_rx_carrier_range = ite_set_rx_carrier_range;
+	rdev->min_timeout = ITE_MIN_IDLE_TIMEOUT;
+	rdev->max_timeout = ITE_MAX_IDLE_TIMEOUT;
+	rdev->timeout = ITE_IDLE_TIMEOUT;
+	rdev->rx_resolution = ITE_BAUDRATE_DIVISOR *
+				itdev->params.sample_period;
+	rdev->tx_resolution = ITE_BAUDRATE_DIVISOR *
+				itdev->params.sample_period;
+
+	/* set up transmitter related values if needed */
+	if (itdev->params.hw_tx_capable) {
+		rdev->tx_ir = ite_tx_ir;
+		rdev->s_tx_carrier = ite_set_tx_carrier;
+		rdev->s_tx_duty_cycle = ite_set_tx_duty_cycle;
+	}
+
+	rdev->input_name = dev_desc->model;
+	rdev->input_id.bustype = BUS_HOST;
+	rdev->input_id.vendor = PCI_VENDOR_ID_ITE;
+	rdev->input_id.product = 0;
+	rdev->input_id.version = 0;
+	rdev->driver_name = ITE_DRIVER_NAME;
+	rdev->map_name = RC_MAP_RC6_MCE;
+
+	ret = rc_register_device(rdev);
+	if (ret)
+		goto failure;
+
+	itdev->rdev = rdev;
+	ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
+
+	return 0;
+
+failure:
+	if (itdev->cir_irq)
+		free_irq(itdev->cir_irq, itdev);
+
+	if (itdev->cir_addr)
+		release_region(itdev->cir_addr, itdev->params.io_region_size);
+
+	rc_free_device(rdev);
+	kfree(itdev);
+
+	return ret;
+}
+
+static void __devexit ite_remove(struct pnp_dev *pdev)
+{
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* disable hardware */
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	/* free resources */
+	free_irq(dev->cir_irq, dev);
+	release_region(dev->cir_addr, dev->params.io_region_size);
+
+	rc_unregister_device(dev->rdev);
+
+	kfree(dev);
+}
+
+static int ite_suspend(struct pnp_dev *pdev, pm_message_t state)
+{
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* disable all interrupts */
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return 0;
+}
+
+static int ite_resume(struct pnp_dev *pdev)
+{
+	int ret = 0;
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	if (dev->transmitting) {
+		/* wake up the transmitter */
+		wake_up_interruptible(&dev->tx_queue);
+	} else {
+		/* enable the receiver */
+		dev->params.enable_rx(dev);
+	}
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+
+	return ret;
+}
+
+static void ite_shutdown(struct pnp_dev *pdev)
+{
+	struct ite_dev *dev = pnp_get_drvdata(pdev);
+	unsigned long flags;
+
+	ite_dbg("%s called", __func__);
+
+	spin_lock_irqsave(&dev->lock, flags);
+
+	/* disable all interrupts */
+	dev->params.disable(dev);
+
+	spin_unlock_irqrestore(&dev->lock, flags);
+}
+
+static struct pnp_driver ite_driver = {
+	.name		= ITE_DRIVER_NAME,
+	.id_table	= ite_ids,
+	.probe		= ite_probe,
+	.remove		= __devexit_p(ite_remove),
+	.suspend	= ite_suspend,
+	.resume		= ite_resume,
+	.shutdown	= ite_shutdown,
+};
+
+int ite_init(void)
+{
+	return pnp_register_driver(&ite_driver);
+}
+
+void ite_exit(void)
+{
+	pnp_unregister_driver(&ite_driver);
+}
+
+MODULE_DEVICE_TABLE(pnp, ite_ids);
+MODULE_DESCRIPTION("ITE Tech Inc. IT8712F/ITE8512F CIR driver");
+
+MODULE_AUTHOR("Juan J. Garcia de Soria <skandalfo@gmail.com>");
+MODULE_LICENSE("GPL");
+
+module_init(ite_init);
+module_exit(ite_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/ite-cir.h linux-libre-2.6.39-gnu/drivers/media/rc/ite-cir.h
--- linux-libre-2.6.38-gnu/drivers/media/rc/ite-cir.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/rc/ite-cir.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,481 @@
+/*
+ * Driver for ITE Tech Inc. IT8712F/IT8512F CIR
+ *
+ * Copyright (C) 2010 Juan JesÃºs GarcÃ­a de Soria <skandalfo@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., 59 Temple Place, Suite 330, Boston, MA 02111-1307
+ * USA.
+ */
+
+/* platform driver name to register */
+#define ITE_DRIVER_NAME "ite-cir"
+
+/* logging macros */
+#define ite_pr(level, text, ...) \
+	printk(level KBUILD_MODNAME ": " text, ## __VA_ARGS__)
+#define ite_dbg(text, ...) do { \
+	if (debug) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \
+} while (0)
+
+#define ite_dbg_verbose(text, ...) do {\
+	if (debug > 1) \
+		printk(KERN_DEBUG \
+			KBUILD_MODNAME ": " text "\n" , ## __VA_ARGS__); \
+} while (0)
+
+/* FIFO sizes */
+#define ITE_TX_FIFO_LEN 32
+#define ITE_RX_FIFO_LEN 32
+
+/* interrupt types */
+#define ITE_IRQ_TX_FIFO        1
+#define ITE_IRQ_RX_FIFO        2
+#define ITE_IRQ_RX_FIFO_OVERRUN    4
+
+/* forward declaration */
+struct ite_dev;
+
+/* struct for storing the parameters of different recognized devices */
+struct ite_dev_params {
+	/* model of the device */
+	const char *model;
+
+	/* size of the I/O region */
+	int io_region_size;
+
+	/* true if the hardware supports transmission */
+	bool hw_tx_capable;
+
+	/* base sampling period, in ns */
+	u32 sample_period;
+
+	/* rx low carrier frequency, in Hz, 0 means no demodulation */
+	unsigned int rx_low_carrier_freq;
+
+	/* tx high carrier frequency, in Hz, 0 means no demodulation */
+	unsigned int rx_high_carrier_freq;
+
+	/* tx carrier frequency, in Hz */
+	unsigned int tx_carrier_freq;
+
+	/* duty cycle, 0-100 */
+	int tx_duty_cycle;
+
+	/* hw-specific operation function pointers; most of these must be
+	 * called while holding the spin lock, except for the TX FIFO length
+	 * one */
+	/* get pending interrupt causes */
+	int (*get_irq_causes) (struct ite_dev *dev);
+
+	/* enable rx */
+	void (*enable_rx) (struct ite_dev *dev);
+
+	/* make rx enter the idle state; keep listening for a pulse, but stop
+	 * streaming space bytes */
+	void (*idle_rx) (struct ite_dev *dev);
+
+	/* disable rx completely */
+	void (*disable_rx) (struct ite_dev *dev);
+
+	/* read bytes from RX FIFO; return read count */
+	int (*get_rx_bytes) (struct ite_dev *dev, u8 *buf, int buf_size);
+
+	/* enable tx FIFO space available interrupt */
+	void (*enable_tx_interrupt) (struct ite_dev *dev);
+
+	/* disable tx FIFO space available interrupt */
+	void (*disable_tx_interrupt) (struct ite_dev *dev);
+
+	/* get number of full TX FIFO slots */
+	int (*get_tx_used_slots) (struct ite_dev *dev);
+
+	/* put a byte to the TX FIFO */
+	void (*put_tx_byte) (struct ite_dev *dev, u8 value);
+
+	/* disable hardware completely */
+	void (*disable) (struct ite_dev *dev);
+
+	/* initialize the hardware */
+	void (*init_hardware) (struct ite_dev *dev);
+
+	/* set the carrier parameters */
+	void (*set_carrier_params) (struct ite_dev *dev, bool high_freq,
+				    bool use_demodulator, u8 carrier_freq_bits,
+				    u8 allowance_bits, u8 pulse_width_bits);
+};
+
+/* ITE CIR device structure */
+struct ite_dev {
+	struct pnp_dev *pdev;
+	struct rc_dev *rdev;
+	struct ir_raw_event rawir;
+
+	/* sync data */
+	spinlock_t lock;
+	bool in_use, transmitting;
+
+	/* transmit support */
+	int tx_fifo_allowance;
+	wait_queue_head_t tx_queue, tx_ended;
+
+	/* hardware I/O settings */
+	unsigned long cir_addr;
+	int cir_irq;
+
+	/* overridable copy of model parameters */
+	struct ite_dev_params params;
+};
+
+/* common values for all kinds of hardware */
+
+/* baud rate divisor default */
+#define ITE_BAUDRATE_DIVISOR		1
+
+/* low-speed carrier frequency limits (Hz) */
+#define ITE_LCF_MIN_CARRIER_FREQ	27000
+#define ITE_LCF_MAX_CARRIER_FREQ	58000
+
+/* high-speed carrier frequency limits (Hz) */
+#define ITE_HCF_MIN_CARRIER_FREQ	400000
+#define ITE_HCF_MAX_CARRIER_FREQ	500000
+
+/* default carrier freq for when demodulator is off (Hz) */
+#define ITE_DEFAULT_CARRIER_FREQ	38000
+
+/* default idling timeout in ns (0.2 seconds) */
+#define ITE_IDLE_TIMEOUT		200000000UL
+
+/* limit timeout values */
+#define ITE_MIN_IDLE_TIMEOUT		100000000UL
+#define ITE_MAX_IDLE_TIMEOUT		1000000000UL
+
+/* convert bits to us */
+#define ITE_BITS_TO_NS(bits, sample_period) \
+((u32) ((bits) * ITE_BAUDRATE_DIVISOR * sample_period))
+
+/*
+ * n in RDCR produces a tolerance of +/- n * 6.25% around the center
+ * carrier frequency...
+ *
+ * From two limit frequencies, L (low) and H (high), we can get both the
+ * center frequency F = (L + H) / 2 and the variation from the center
+ * frequency A = (H - L) / (H + L). We can use this in order to honor the
+ * s_rx_carrier_range() call in ir-core. We'll suppose that any request
+ * setting L=0 means we must shut down the demodulator.
+ */
+#define ITE_RXDCR_PER_10000_STEP 625
+
+/* high speed carrier freq values */
+#define ITE_CFQ_400		0x03
+#define ITE_CFQ_450		0x08
+#define ITE_CFQ_480		0x0b
+#define ITE_CFQ_500		0x0d
+
+/* values for pulse widths */
+#define ITE_TXMPW_A		0x02
+#define ITE_TXMPW_B		0x03
+#define ITE_TXMPW_C		0x04
+#define ITE_TXMPW_D		0x05
+#define ITE_TXMPW_E		0x06
+
+/* values for demodulator carrier range allowance */
+#define ITE_RXDCR_DEFAULT	0x01	/* default carrier range */
+#define ITE_RXDCR_MAX		0x07	/* default carrier range */
+
+/* DR TX bits */
+#define ITE_TX_PULSE		0x00
+#define ITE_TX_SPACE		0x80
+#define ITE_TX_MAX_RLE		0x80
+#define ITE_TX_RLE_MASK		0x7f
+
+/*
+ * IT8712F
+ *
+ * hardware data obtained from:
+ *
+ * IT8712F
+ * Environment Control â€“ Low Pin Count Input / Output
+ * (EC - LPC I/O)
+ * Preliminary Specification V0. 81
+ */
+
+/* register offsets */
+#define IT87_DR		0x00	/* data register */
+#define IT87_IER	0x01	/* interrupt enable register */
+#define IT87_RCR	0x02	/* receiver control register */
+#define IT87_TCR1	0x03	/* transmitter control register 1 */
+#define IT87_TCR2	0x04	/* transmitter control register 2 */
+#define IT87_TSR	0x05	/* transmitter status register */
+#define IT87_RSR	0x06	/* receiver status register */
+#define IT87_BDLR	0x05	/* baud rate divisor low byte register */
+#define IT87_BDHR	0x06	/* baud rate divisor high byte register */
+#define IT87_IIR	0x07	/* interrupt identification register */
+
+#define IT87_IOREG_LENGTH 0x08	/* length of register file */
+
+/* IER bits */
+#define IT87_TLDLIE	0x01	/* transmitter low data interrupt enable */
+#define IT87_RDAIE	0x02	/* receiver data available interrupt enable */
+#define IT87_RFOIE	0x04	/* receiver FIFO overrun interrupt enable */
+#define IT87_IEC	0x08	/* interrupt enable control */
+#define IT87_BR		0x10	/* baud rate register enable */
+#define IT87_RESET	0x20	/* reset */
+
+/* RCR bits */
+#define IT87_RXDCR	0x07	/* receiver demodulation carrier range mask */
+#define IT87_RXACT	0x08	/* receiver active */
+#define IT87_RXEND	0x10	/* receiver demodulation enable */
+#define IT87_RXEN	0x20	/* receiver enable */
+#define IT87_HCFS	0x40	/* high-speed carrier frequency select */
+#define IT87_RDWOS	0x80	/* receiver data without sync */
+
+/* TCR1 bits */
+#define IT87_TXMPM	0x03	/* transmitter modulation pulse mode mask */
+#define IT87_TXMPM_DEFAULT 0x00	/* modulation pulse mode default */
+#define IT87_TXENDF	0x04	/* transmitter deferral */
+#define IT87_TXRLE	0x08	/* transmitter run length enable */
+#define IT87_FIFOTL	0x30	/* FIFO level threshold mask */
+#define IT87_FIFOTL_DEFAULT 0x20	/* FIFO level threshold default
+					 * 0x00 -> 1, 0x10 -> 7, 0x20 -> 17,
+					 * 0x30 -> 25 */
+#define IT87_ILE	0x40	/* internal loopback enable */
+#define IT87_FIFOCLR	0x80	/* FIFO clear bit */
+
+/* TCR2 bits */
+#define IT87_TXMPW	0x07	/* transmitter modulation pulse width mask */
+#define IT87_TXMPW_DEFAULT 0x04	/* default modulation pulse width */
+#define IT87_CFQ	0xf8	/* carrier frequency mask */
+#define IT87_CFQ_SHIFT	3	/* carrier frequency bit shift */
+
+/* TSR bits */
+#define IT87_TXFBC	0x3f	/* transmitter FIFO byte count mask */
+
+/* RSR bits */
+#define IT87_RXFBC	0x3f	/* receiver FIFO byte count mask */
+#define IT87_RXFTO	0x80	/* receiver FIFO time-out */
+
+/* IIR bits */
+#define IT87_IP		0x01	/* interrupt pending */
+#define IT87_II		0x06	/* interrupt identification mask */
+#define IT87_II_NOINT	0x00	/* no interrupt */
+#define IT87_II_TXLDL	0x02	/* transmitter low data level */
+#define IT87_II_RXDS	0x04	/* receiver data stored */
+#define IT87_II_RXFO	0x06	/* receiver FIFO overrun */
+
+/*
+ * IT8512E/F
+ *
+ * Hardware data obtained from:
+ *
+ * IT8512E/F
+ * Embedded Controller
+ * Preliminary Specification V0.4.1
+ *
+ * Note that the CIR registers are not directly available to the host, because
+ * they only are accessible to the integrated microcontroller. Thus, in order
+ * use it, some kind of bridging is required. As the bridging may depend on
+ * the controller firmware in use, we are going to use the PNP ID in order to
+ * determine the strategy and ports available. See after these generic
+ * IT8512E/F register definitions for register definitions for those
+ * strategies.
+ */
+
+/* register offsets */
+#define IT85_C0DR	0x00	/* data register */
+#define IT85_C0MSTCR	0x01	/* master control register */
+#define IT85_C0IER	0x02	/* interrupt enable register */
+#define IT85_C0IIR	0x03	/* interrupt identification register */
+#define IT85_C0CFR	0x04	/* carrier frequency register */
+#define IT85_C0RCR	0x05	/* receiver control register */
+#define IT85_C0TCR	0x06	/* transmitter control register */
+#define IT85_C0SCK	0x07	/* slow clock control register */
+#define IT85_C0BDLR	0x08	/* baud rate divisor low byte register */
+#define IT85_C0BDHR	0x09	/* baud rate divisor high byte register */
+#define IT85_C0TFSR	0x0a	/* transmitter FIFO status register */
+#define IT85_C0RFSR	0x0b	/* receiver FIFO status register */
+#define IT85_C0WCL	0x0d	/* wakeup code length register */
+#define IT85_C0WCR	0x0e	/* wakeup code read/write register */
+#define IT85_C0WPS	0x0f	/* wakeup power control/status register */
+
+#define IT85_IOREG_LENGTH 0x10	/* length of register file */
+
+/* C0MSTCR bits */
+#define IT85_RESET	0x01	/* reset */
+#define IT85_FIFOCLR	0x02	/* FIFO clear bit */
+#define IT85_FIFOTL	0x0c	/* FIFO level threshold mask */
+#define IT85_FIFOTL_DEFAULT 0x08	/* FIFO level threshold default
+					 * 0x00 -> 1, 0x04 -> 7, 0x08 -> 17,
+					 * 0x0c -> 25 */
+#define IT85_ILE	0x10	/* internal loopback enable */
+#define IT85_ILSEL	0x20	/* internal loopback select */
+
+/* C0IER bits */
+#define IT85_TLDLIE	0x01	/* TX low data level interrupt enable */
+#define IT85_RDAIE	0x02	/* RX data available interrupt enable */
+#define IT85_RFOIE	0x04	/* RX FIFO overrun interrupt enable */
+#define IT85_IEC	0x80	/* interrupt enable function control */
+
+/* C0IIR bits */
+#define IT85_TLDLI	0x01	/* transmitter low data level interrupt */
+#define IT85_RDAI	0x02	/* receiver data available interrupt */
+#define IT85_RFOI	0x04	/* receiver FIFO overrun interrupt */
+#define IT85_NIP	0x80	/* no interrupt pending */
+
+/* C0CFR bits */
+#define IT85_CFQ	0x1f	/* carrier frequency mask */
+#define IT85_HCFS	0x20	/* high speed carrier frequency select */
+
+/* C0RCR bits */
+#define IT85_RXDCR	0x07	/* receiver demodulation carrier range mask */
+#define IT85_RXACT	0x08	/* receiver active */
+#define IT85_RXEND	0x10	/* receiver demodulation enable */
+#define IT85_RDWOS	0x20	/* receiver data without sync */
+#define IT85_RXEN	0x80	/* receiver enable */
+
+/* C0TCR bits */
+#define IT85_TXMPW	0x07	/* transmitter modulation pulse width mask */
+#define IT85_TXMPW_DEFAULT 0x04	/* default modulation pulse width */
+#define IT85_TXMPM	0x18	/* transmitter modulation pulse mode mask */
+#define IT85_TXMPM_DEFAULT 0x00	/* modulation pulse mode default */
+#define IT85_TXENDF	0x20	/* transmitter deferral */
+#define IT85_TXRLE	0x40	/* transmitter run length enable */
+
+/* C0SCK bits */
+#define IT85_SCKS	0x01	/* slow clock select */
+#define IT85_TXDCKG	0x02	/* TXD clock gating */
+#define IT85_DLL1P8E	0x04	/* DLL 1.8432M enable */
+#define IT85_DLLTE	0x08	/* DLL test enable */
+#define IT85_BRCM	0x70	/* baud rate count mode */
+#define IT85_DLLOCK	0x80	/* DLL lock */
+
+/* C0TFSR bits */
+#define IT85_TXFBC	0x3f	/* transmitter FIFO count mask */
+
+/* C0RFSR bits */
+#define IT85_RXFBC	0x3f	/* receiver FIFO count mask */
+#define IT85_RXFTO	0x80	/* receiver FIFO time-out */
+
+/* C0WCL bits */
+#define IT85_WCL	0x3f	/* wakeup code length mask */
+
+/* C0WPS bits */
+#define IT85_CIRPOSIE	0x01	/* power on/off status interrupt enable */
+#define IT85_CIRPOIS	0x02	/* power on/off interrupt status */
+#define IT85_CIRPOII	0x04	/* power on/off interrupt identification */
+#define IT85_RCRST	0x10	/* wakeup code reading counter reset bit */
+#define IT85_WCRST	0x20	/* wakeup code writing counter reset bit */
+
+/*
+ * ITE8708
+ *
+ * Hardware data obtained from hacked driver for IT8512 in this forum post:
+ *
+ *  http://ubuntuforums.org/showthread.php?t=1028640
+ *
+ * Although there's no official documentation for that driver, analysis would
+ * suggest that it maps the 16 registers of IT8512 onto two 8-register banks,
+ * selectable by a single bank-select bit that's mapped onto both banks. The
+ * IT8512 registers are mapped in a different order, so that the first bank
+ * maps the ones that are used more often, and two registers that share a
+ * reserved high-order bit are placed at the same offset in both banks in
+ * order to reuse the reserved bit as the bank select bit.
+ */
+
+/* register offsets */
+
+/* mapped onto both banks */
+#define IT8708_BANKSEL	0x07	/* bank select register */
+#define IT8708_HRAE	0x80	/* high registers access enable */
+
+/* mapped onto the low bank */
+#define IT8708_C0DR	0x00	/* data register */
+#define IT8708_C0MSTCR	0x01	/* master control register */
+#define IT8708_C0IER	0x02	/* interrupt enable register */
+#define IT8708_C0IIR	0x03	/* interrupt identification register */
+#define IT8708_C0RFSR	0x04	/* receiver FIFO status register */
+#define IT8708_C0RCR	0x05	/* receiver control register */
+#define IT8708_C0TFSR	0x06	/* transmitter FIFO status register */
+#define IT8708_C0TCR	0x07	/* transmitter control register */
+
+/* mapped onto the high bank */
+#define IT8708_C0BDLR	0x01	/* baud rate divisor low byte register */
+#define IT8708_C0BDHR	0x02	/* baud rate divisor high byte register */
+#define IT8708_C0CFR	0x04	/* carrier frequency register */
+
+/* registers whose bank mapping we don't know, since they weren't being used
+ * in the hacked driver... most probably they belong to the high bank too,
+ * since they fit in the holes the other registers leave */
+#define IT8708_C0SCK	0x03	/* slow clock control register */
+#define IT8708_C0WCL	0x05	/* wakeup code length register */
+#define IT8708_C0WCR	0x06	/* wakeup code read/write register */
+#define IT8708_C0WPS	0x07	/* wakeup power control/status register */
+
+#define IT8708_IOREG_LENGTH 0x08	/* length of register file */
+
+/* two more registers that are defined in the hacked driver, but can't be
+ * found in the data sheets; no idea what they are or how they are accessed,
+ * since the hacked driver doesn't seem to use them */
+#define IT8708_CSCRR	0x00
+#define IT8708_CGPINTR	0x01
+
+/* CSCRR bits */
+#define IT8708_CSCRR_SCRB 0x3f
+#define IT8708_CSCRR_PM	0x80
+
+/* CGPINTR bits */
+#define IT8708_CGPINT	0x01
+
+/*
+ * ITE8709
+ *
+ * Hardware interfacing data obtained from the original lirc_ite8709 driver.
+ * Verbatim from its sources:
+ *
+ * The ITE8709 device seems to be the combination of IT8512 superIO chip and
+ * a specific firmware running on the IT8512's embedded micro-controller.
+ * In addition of the embedded micro-controller, the IT8512 chip contains a
+ * CIR module and several other modules. A few modules are directly accessible
+ * by the host CPU, but most of them are only accessible by the
+ * micro-controller. The CIR module is only accessible by the
+ * micro-controller.
+ *
+ * The battery-backed SRAM module is accessible by the host CPU and the
+ * micro-controller. So one of the MC's firmware role is to act as a bridge
+ * between the host CPU and the CIR module. The firmware implements a kind of
+ * communication protocol using the SRAM module as a shared memory. The IT8512
+ * specification is publicly available on ITE's web site, but the
+ * communication protocol is not, so it was reverse-engineered.
+ */
+
+/* register offsets */
+#define IT8709_RAM_IDX	0x00	/* index into the SRAM module bytes */
+#define IT8709_RAM_VAL	0x01	/* read/write data to the indexed byte */
+
+#define IT8709_IOREG_LENGTH 0x02	/* length of register file */
+
+/* register offsets inside the SRAM module */
+#define IT8709_MODE	0x1a	/* request/ack byte */
+#define IT8709_REG_IDX	0x1b	/* index of the CIR register to access */
+#define IT8709_REG_VAL	0x1c	/* value read/to be written */
+#define IT8709_IIR	0x1e	/* interrupt identification register */
+#define IT8709_RFSR	0x1f	/* receiver FIFO status register */
+#define IT8709_FIFO	0x20	/* start of in RAM RX FIFO copy */
+
+/* MODE values */
+#define IT8709_IDLE	0x00
+#define IT8709_WRITE	0x01
+#define IT8709_READ	0x02
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/Kconfig linux-libre-2.6.39-gnu/drivers/media/rc/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/rc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -135,6 +135,19 @@
 	   To compile this driver as a module, choose M here: the
 	   module will be called mceusb.
 
+config IR_ITE_CIR
+	tristate "ITE Tech Inc. IT8712/IT8512 Consumer Infrared Transceiver"
+	depends on PNP
+	depends on RC_CORE
+	---help---
+	   Say Y here to enable support for integrated infrared receivers
+	   /transceivers made by ITE Tech Inc. These are found in
+	   several ASUS devices, like the ASUS Digimatrix or the ASUS
+	   EEEBox 1501U.
+
+	   To compile this driver as a module, choose M here: the
+	   module will be called ite-cir.
+
 config IR_NUVOTON
 	tristate "Nuvoton w836x7hg Consumer Infrared Transceiver"
 	depends on PNP
@@ -161,20 +174,20 @@
 	   module will be called streamzap.
 
 config IR_WINBOND_CIR
-        tristate "Winbond IR remote control"
-        depends on X86 && PNP
+	tristate "Winbond IR remote control"
+	depends on X86 && PNP
 	depends on RC_CORE
-        select NEW_LEDS
-        select LEDS_CLASS
-        select LEDS_TRIGGERS
-        select BITREVERSE
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_TRIGGERS
+	select BITREVERSE
 	---help---
-           Say Y here if you want to use the IR remote functionality found
-           in some Winbond SuperI/O chips. Currently only the WPCD376I
-           chip is supported (included in some Intel Media series
+	   Say Y here if you want to use the IR remote functionality found
+	   in some Winbond SuperI/O chips. Currently only the WPCD376I
+	   chip is supported (included in some Intel Media series
 	   motherboards).
 
-           To compile this driver as a module, choose M here: the module will
+	   To compile this driver as a module, choose M here: the module will
 	   be called winbond_cir.
 
 config RC_LOOPBACK
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/Makefile linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,6 @@
 			rc-gadmei-rm008z.o \
 			rc-genius-tvgo-a11mce.o \
 			rc-gotview7135.o \
-			rc-hauppauge-new.o \
 			rc-imon-mce.o \
 			rc-imon-pad.o \
 			rc-iodata-bctv7e.o \
@@ -68,14 +67,15 @@
 			rc-proteus-2309.o \
 			rc-purpletv.o \
 			rc-pv951.o \
-			rc-rc5-hauppauge-new.o \
-			rc-rc5-tv.o \
+			rc-hauppauge.o \
 			rc-rc6-mce.o \
 			rc-real-audio-220-32-keys.o \
 			rc-streamzap.o \
 			rc-tbs-nec.o \
+			rc-technisat-usb2.o \
 			rc-terratec-cinergy-xs.o \
 			rc-terratec-slim.o \
+			rc-terratec-slim-2.o \
 			rc-tevii-nec.o \
 			rc-total-media-in-hand.o \
 			rc-trekstor.o \
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-adstech-dvb-t-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,9 +50,9 @@
 	{ 0x13, KEY_TUNER },		/* Live */
 	{ 0x0a, KEY_A },
 	{ 0x12, KEY_B },
-	{ 0x03, KEY_PROG1 },		/* 1 */
-	{ 0x01, KEY_PROG2 },		/* 2 */
-	{ 0x00, KEY_PROG3 },		/* 3 */
+	{ 0x03, KEY_RED },		/* 1 */
+	{ 0x01, KEY_GREEN },		/* 2 */
+	{ 0x00, KEY_YELLOW },		/* 3 */
 	{ 0x06, KEY_DVD },
 	{ 0x48, KEY_AUX },		/* Photo */
 	{ 0x40, KEY_VIDEO },
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-dvbt.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,12 +26,12 @@
 	{ 0x16, KEY_8 },		/* '8' / 'down arrow' */
 	{ 0x36, KEY_9 },		/* '9' */
 
-	{ 0x20, KEY_LIST },		/* 'source' */
+	{ 0x20, KEY_VIDEO },		/* 'source' */
 	{ 0x10, KEY_TEXT },		/* 'teletext' */
 	{ 0x00, KEY_POWER },		/* 'power' */
 	{ 0x04, KEY_AUDIO },		/* 'audio' */
 	{ 0x06, KEY_ZOOM },		/* 'full screen' */
-	{ 0x18, KEY_VIDEO },		/* 'display' */
+	{ 0x18, KEY_SWITCHVIDEOMODE },	/* 'display' */
 	{ 0x38, KEY_SEARCH },		/* 'loop' */
 	{ 0x08, KEY_INFO },		/* 'preview' */
 	{ 0x2a, KEY_REWIND },		/* 'backward <<' */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-m135a.c	2011-05-19 00:06:34.000000000 -0400
@@ -108,7 +108,7 @@
 	{ 0x0414, KEY_TEXT },
 	{ 0x0415, KEY_EPG },
 	{ 0x041a, KEY_TV2 },      /* PIP */
-	{ 0x041b, KEY_MHP },      /* Snapshot */
+	{ 0x041b, KEY_CAMERA },      /* Snapshot */
 
 	{ 0x0417, KEY_RECORD },
 	{ 0x0416, KEY_PLAYPAUSE },
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-m733a-rm-k6.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
 	{ 0x0414, KEY_TEXT },
 	{ 0x0415, KEY_EPG },
 	{ 0x041a, KEY_TV2 },      /* PIP */
-	{ 0x041b, KEY_MHP },      /* Snapshot */
+	{ 0x041b, KEY_CAMERA },      /* Snapshot */
 
 	{ 0x0417, KEY_RECORD },
 	{ 0x0416, KEY_PLAYPAUSE },
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-avermedia-rm-ks.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 	{ 0x0505, KEY_VOLUMEDOWN },
 	{ 0x0506, KEY_MUTE },
 	{ 0x0507, KEY_RIGHT },
-	{ 0x0508, KEY_PROG1 },
+	{ 0x0508, KEY_RED },
 	{ 0x0509, KEY_1 },
 	{ 0x050a, KEY_2 },
 	{ 0x050b, KEY_3 },
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-behold.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-behold.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-behold.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-behold.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 	{ 0x6b861a, KEY_STOP },
 	{ 0x6b860e, KEY_TEXT },
 	{ 0x6b861f, KEY_RED },	/*XXX KEY_AUDIO	*/
-	{ 0x6b861e, KEY_YELLOW },	/*XXX KEY_SOURCE	*/
+	{ 0x6b861e, KEY_VIDEO },
 
 	/*  0x1d   0x13     0x19  *
 	 * SLEEP  PREVIEW   DVB   *
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-behold-columbus.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,7 @@
 	 *                             */
 
 	{ 0x13, KEY_MUTE },
-	{ 0x11, KEY_PROPS },
+	{ 0x11, KEY_VIDEO },
 	{ 0x1C, KEY_TUNER },	/* KEY_TV/KEY_RADIO	*/
 	{ 0x12, KEY_POWER },
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-budget-ci-old.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,8 @@
 
 #include <media/rc-map.h>
 
-/* From reading the following remotes:
+/*
+ * From reading the following remotes:
  * Zenith Universal 7 / TV Mode 807 / VCR Mode 837
  * Hauppauge (from NOVA-CI-s box product)
  * This is a "middle of the road" approach, differences are noted
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-cinergy.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-cinergy.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-cinergy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-cinergy.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,7 +25,7 @@
 	{ 0x09, KEY_9 },
 
 	{ 0x0a, KEY_POWER },
-	{ 0x0b, KEY_PROG1 },		/* app */
+	{ 0x0b, KEY_MEDIA },		/* app */
 	{ 0x0c, KEY_ZOOM },		/* zoom/fullscreen */
 	{ 0x0d, KEY_CHANNELUP },	/* channel */
 	{ 0x0e, KEY_CHANNELDOWN },	/* channel- */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-dntv-live-dvb-t.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 	{ 0x0c, KEY_SEARCH },		/* scan */
 	{ 0x0d, KEY_STOP },
 	{ 0x0e, KEY_PAUSE },
-	{ 0x0f, KEY_LIST },		/* source */
+	{ 0x0f, KEY_VIDEO },		/* source */
 
 	{ 0x10, KEY_MUTE },
 	{ 0x11, KEY_REWIND },		/* backward << */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-encore-enltv2.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 	{ 0x64, KEY_LAST },		/* +100 */
 	{ 0x4e, KEY_AGAIN },		/* Recall */
 
-	{ 0x6c, KEY_SWITCHVIDEOMODE },	/* Video Source */
+	{ 0x6c, KEY_VIDEO },		/* Video Source */
 	{ 0x5e, KEY_MENU },
 	{ 0x56, KEY_SCREEN },
 	{ 0x7a, KEY_SETUP },
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-encore-enltv.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 	{ 0x1e, KEY_TV },
 	{ 0x00, KEY_VIDEO },
 	{ 0x01, KEY_AUDIO },		/* music */
-	{ 0x02, KEY_MHP },		/* picture */
+	{ 0x02, KEY_CAMERA },		/* picture */
 
 	{ 0x1f, KEY_1 },
 	{ 0x03, KEY_2 },
@@ -77,7 +77,7 @@
 	{ 0x50, KEY_SLEEP },		/* shutdown */
 	{ 0x51, KEY_MODE },		/* stereo > main */
 	{ 0x52, KEY_SELECT },		/* stereo > sap */
-	{ 0x53, KEY_PROG1 },		/* teletext */
+	{ 0x53, KEY_TEXT },		/* teletext */
 
 
 	{ 0x59, KEY_RED },		/* AP1 */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-flydvb.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-flydvb.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-flydvb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-flydvb.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,8 +37,8 @@
 	{ 0x13, KEY_CHANNELDOWN },	/* CH- */
 	{ 0x1d, KEY_ENTER },		/* Enter */
 
-	{ 0x1a, KEY_MODE },		/* PIP */
-	{ 0x18, KEY_TUNER },		/* Source */
+	{ 0x1a, KEY_TV2 },		/* PIP */
+	{ 0x18, KEY_VIDEO },		/* Source */
 
 	{ 0x1e, KEY_RECORD },		/* Record/Pause */
 	{ 0x15, KEY_ANGLE },		/* Swap (no label on key) */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-hauppauge.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-hauppauge.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-hauppauge.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-hauppauge.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,241 @@
+/* rc-hauppauge.c - Keytable for Hauppauge Remote Controllers
+ *
+ * keymap imported from ir-keymaps.c
+ *
+ * This map currently contains the code for four different RCs:
+ *	- New Hauppauge Gray;
+ *	- Old Hauppauge Gray (with a golden screen for media keys);
+ *	- Hauppauge Black;
+ *	- DSR-0112 remote bundled with Haupauge MiniStick.
+ *
+ * Copyright (c) 2010-2011 by Mauro Carvalho Chehab <mchehab@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 <media/rc-map.h>
+
+/*
+ * Hauppauge:the newer, gray remotes (seems there are multiple
+ * slightly different versions), shipped with cx88+ivtv cards.
+ *
+ * This table contains the complete RC5 code, instead of just the data part
+ */
+
+static struct rc_map_table rc5_hauppauge_new[] = {
+	/*
+	 * Remote Controller Hauppauge Gray found on modern devices
+	 * Keycodes start with address = 0x1e
+	 */
+
+	{ 0x1e3b, KEY_SELECT },		/* GO / house symbol */
+	{ 0x1e3d, KEY_POWER2 },		/* system power (green button) */
+
+	{ 0x1e1c, KEY_TV },
+	{ 0x1e18, KEY_VIDEO },		/* Videos */
+	{ 0x1e19, KEY_AUDIO },		/* Music */
+	{ 0x1e1a, KEY_CAMERA },		/* Pictures */
+
+	{ 0x1e1b, KEY_EPG },		/* Guide */
+	{ 0x1e0c, KEY_RADIO },
+
+	{ 0x1e14, KEY_UP },
+	{ 0x1e15, KEY_DOWN },
+	{ 0x1e16, KEY_LEFT },
+	{ 0x1e17, KEY_RIGHT },
+	{ 0x1e25, KEY_OK },		/* OK */
+
+	{ 0x1e1f, KEY_EXIT },		/* back/exit */
+	{ 0x1e0d, KEY_MENU },
+
+	{ 0x1e10, KEY_VOLUMEUP },
+	{ 0x1e11, KEY_VOLUMEDOWN },
+
+	{ 0x1e12, KEY_PREVIOUS },	/* previous channel */
+	{ 0x1e0f, KEY_MUTE },
+
+	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
+
+	{ 0x1e37, KEY_RECORD },		/* recording */
+	{ 0x1e36, KEY_STOP },
+
+	{ 0x1e32, KEY_REWIND },		/* backward << */
+	{ 0x1e35, KEY_PLAY },
+	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
+
+	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x1e30, KEY_PAUSE },		/* pause */
+	{ 0x1e1e, KEY_NEXTSONG },	/* skip >| */
+
+	{ 0x1e01, KEY_1 },
+	{ 0x1e02, KEY_2 },
+	{ 0x1e03, KEY_3 },
+
+	{ 0x1e04, KEY_4 },
+	{ 0x1e05, KEY_5 },
+	{ 0x1e06, KEY_6 },
+
+	{ 0x1e07, KEY_7 },
+	{ 0x1e08, KEY_8 },
+	{ 0x1e09, KEY_9 },
+
+	{ 0x1e0a, KEY_TEXT },		/* keypad asterisk as well */
+	{ 0x1e00, KEY_0 },
+	{ 0x1e0e, KEY_SUBTITLE },	/* also the Pound key (#) */
+
+	{ 0x1e0b, KEY_RED },		/* red button */
+	{ 0x1e2e, KEY_GREEN },		/* green button */
+	{ 0x1e38, KEY_YELLOW },		/* yellow key */
+	{ 0x1e29, KEY_BLUE },		/* blue key */
+
+	/*
+	 * Old Remote Controller Hauppauge Gray with a golden screen
+	 * Keycodes start with address = 0x1f
+	 */
+	{ 0x1f3d, KEY_POWER2 },		/* system power (green button) */
+	{ 0x1f3b, KEY_SELECT },		/* GO */
+
+	/* Keys 0 to 9 */
+	{ 0x1f00, KEY_0 },
+	{ 0x1f01, KEY_1 },
+	{ 0x1f02, KEY_2 },
+	{ 0x1f03, KEY_3 },
+	{ 0x1f04, KEY_4 },
+	{ 0x1f05, KEY_5 },
+	{ 0x1f06, KEY_6 },
+	{ 0x1f07, KEY_7 },
+	{ 0x1f08, KEY_8 },
+	{ 0x1f09, KEY_9 },
+
+	{ 0x1f1f, KEY_EXIT },		/* back/exit */
+	{ 0x1f0d, KEY_MENU },
+
+	{ 0x1f10, KEY_VOLUMEUP },
+	{ 0x1f11, KEY_VOLUMEDOWN },
+	{ 0x1f20, KEY_CHANNELUP },	/* channel / program + */
+	{ 0x1f21, KEY_CHANNELDOWN },	/* channel / program - */
+	{ 0x1f25, KEY_ENTER },		/* OK */
+
+	{ 0x1f0b, KEY_RED },		/* red button */
+	{ 0x1f2e, KEY_GREEN },		/* green button */
+	{ 0x1f38, KEY_YELLOW },		/* yellow key */
+	{ 0x1f29, KEY_BLUE },		/* blue key */
+
+	{ 0x1f0f, KEY_MUTE },
+	{ 0x1f0c, KEY_RADIO },		/* There's no indicator on this key */
+	{ 0x1f3c, KEY_ZOOM },		/* full */
+
+	{ 0x1f32, KEY_REWIND },		/* backward << */
+	{ 0x1f35, KEY_PLAY },
+	{ 0x1f34, KEY_FASTFORWARD },	/* forward >> */
+
+	{ 0x1f37, KEY_RECORD },		/* recording */
+	{ 0x1f36, KEY_STOP },
+	{ 0x1f30, KEY_PAUSE },		/* pause */
+
+	{ 0x1f24, KEY_PREVIOUSSONG },	/* replay |< */
+	{ 0x1f1e, KEY_NEXTSONG },	/* skip >| */
+
+	/*
+	 * Keycodes for DSR-0112 remote bundled with Haupauge MiniStick
+	 * Keycodes start with address = 0x1d
+	 */
+	{ 0x1d00, KEY_0 },
+	{ 0x1d01, KEY_1 },
+	{ 0x1d02, KEY_2 },
+	{ 0x1d03, KEY_3 },
+	{ 0x1d04, KEY_4 },
+	{ 0x1d05, KEY_5 },
+	{ 0x1d06, KEY_6 },
+	{ 0x1d07, KEY_7 },
+	{ 0x1d08, KEY_8 },
+	{ 0x1d09, KEY_9 },
+	{ 0x1d0a, KEY_TEXT },
+	{ 0x1d0d, KEY_MENU },
+	{ 0x1d0f, KEY_MUTE },
+	{ 0x1d10, KEY_VOLUMEUP },
+	{ 0x1d11, KEY_VOLUMEDOWN },
+	{ 0x1d12, KEY_PREVIOUS },        /* Prev.Ch .. ??? */
+	{ 0x1d14, KEY_UP },
+	{ 0x1d15, KEY_DOWN },
+	{ 0x1d16, KEY_LEFT },
+	{ 0x1d17, KEY_RIGHT },
+	{ 0x1d1c, KEY_TV },
+	{ 0x1d1e, KEY_NEXT },           /* >|             */
+	{ 0x1d1f, KEY_EXIT },
+	{ 0x1d20, KEY_CHANNELUP },
+	{ 0x1d21, KEY_CHANNELDOWN },
+	{ 0x1d24, KEY_LAST },           /* <|             */
+	{ 0x1d25, KEY_OK },
+	{ 0x1d30, KEY_PAUSE },
+	{ 0x1d32, KEY_REWIND },
+	{ 0x1d34, KEY_FASTFORWARD },
+	{ 0x1d35, KEY_PLAY },
+	{ 0x1d36, KEY_STOP },
+	{ 0x1d37, KEY_RECORD },
+	{ 0x1d3b, KEY_GOTO },
+	{ 0x1d3d, KEY_POWER },
+	{ 0x1d3f, KEY_HOME },
+
+	/*
+	 * Keycodes for the old Black Remote Controller
+	 * This one also uses RC-5 protocol
+	 * Keycodes start with address = 0x00
+	 */
+	{ 0x001f, KEY_TV },
+	{ 0x0020, KEY_CHANNELUP },
+	{ 0x000c, KEY_RADIO },
+
+	{ 0x0011, KEY_VOLUMEDOWN },
+	{ 0x002e, KEY_ZOOM },		/* full screen */
+	{ 0x0010, KEY_VOLUMEUP },
+
+	{ 0x000d, KEY_MUTE },
+	{ 0x0021, KEY_CHANNELDOWN },
+	{ 0x0022, KEY_VIDEO },		/* source */
+
+	{ 0x0001, KEY_1 },
+	{ 0x0002, KEY_2 },
+	{ 0x0003, KEY_3 },
+
+	{ 0x0004, KEY_4 },
+	{ 0x0005, KEY_5 },
+	{ 0x0006, KEY_6 },
+
+	{ 0x0007, KEY_7 },
+	{ 0x0008, KEY_8 },
+	{ 0x0009, KEY_9 },
+
+	{ 0x001e, KEY_RED },	/* Reserved */
+	{ 0x0000, KEY_0 },
+	{ 0x0026, KEY_SLEEP },	/* Minimize */
+};
+
+static struct rc_map_list rc5_hauppauge_new_map = {
+	.map = {
+		.scan    = rc5_hauppauge_new,
+		.size    = ARRAY_SIZE(rc5_hauppauge_new),
+		.rc_type = RC_TYPE_RC5,
+		.name    = RC_MAP_HAUPPAUGE,
+	}
+};
+
+static int __init init_rc_map_rc5_hauppauge_new(void)
+{
+	return rc_map_register(&rc5_hauppauge_new_map);
+}
+
+static void __exit exit_rc_map_rc5_hauppauge_new(void)
+{
+	rc_map_unregister(&rc5_hauppauge_new_map);
+}
+
+module_init(init_rc_map_rc5_hauppauge_new)
+module_exit(exit_rc_map_rc5_hauppauge_new)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-hauppauge-new.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-hauppauge-new.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-hauppauge-new.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-hauppauge-new.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,100 +0,0 @@
-/* hauppauge-new.h - Keytable for hauppauge_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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 <media/rc-map.h>
-
-/* Hauppauge: the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- * almost rc5 coding, but some non-standard keys */
-
-static struct rc_map_table hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0a, KEY_TEXT },		/* keypad asterisk as well */
-	{ 0x0b, KEY_RED },		/* red button */
-	{ 0x0c, KEY_RADIO },
-	{ 0x0d, KEY_MENU },
-	{ 0x0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x0f, KEY_MUTE },
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x14, KEY_UP },
-	{ 0x15, KEY_DOWN },
-	{ 0x16, KEY_LEFT },
-	{ 0x17, KEY_RIGHT },
-	{ 0x18, KEY_VIDEO },		/* Videos */
-	{ 0x19, KEY_AUDIO },		/* Music */
-	/* 0x1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1a, KEY_MHP },
-
-	{ 0x1b, KEY_EPG },		/* Guide */
-	{ 0x1c, KEY_TV },
-	{ 0x1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1f, KEY_EXIT },		/* back/exit */
-	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x25, KEY_ENTER },		/* OK */
-	{ 0x26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x29, KEY_BLUE },		/* blue key */
-	{ 0x2e, KEY_GREEN },		/* green button */
-	{ 0x30, KEY_PAUSE },		/* pause */
-	{ 0x32, KEY_REWIND },		/* backward << */
-	{ 0x34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },		/* recording */
-	{ 0x38, KEY_YELLOW },		/* yellow key */
-	{ 0x3b, KEY_SELECT },		/* top right button */
-	{ 0x3c, KEY_ZOOM },		/* full */
-	{ 0x3d, KEY_POWER },		/* system power (green button) */
-};
-
-static struct rc_map_list hauppauge_new_map = {
-	.map = {
-		.scan    = hauppauge_new,
-		.size    = ARRAY_SIZE(hauppauge_new),
-		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_HAUPPAUGE_NEW,
-	}
-};
-
-static int __init init_rc_map_hauppauge_new(void)
-{
-	return rc_map_register(&hauppauge_new_map);
-}
-
-static void __exit exit_rc_map_hauppauge_new(void)
-{
-	rc_map_unregister(&hauppauge_new_map);
-}
-
-module_init(init_rc_map_hauppauge_new)
-module_exit(exit_rc_map_hauppauge_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-imon-mce.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-imon-mce.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-imon-mce.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-imon-mce.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,7 +111,7 @@
 	{ 0x800ff44d, KEY_TITLE },
 
 	{ 0x800ff40c, KEY_POWER },
-	{ 0x800ff40d, KEY_PROG1 }, /* Windows MCE button */
+	{ 0x800ff40d, KEY_LEFTMETA }, /* Windows MCE button */
 
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-imon-pad.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-imon-pad.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-imon-pad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-imon-pad.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,7 +125,7 @@
 	{ 0x2b8195b7, KEY_CONTEXT_MENU }, /* Left Menu*/
 	{ 0x02000065, KEY_COMPOSE }, /* RightMenu */
 	{ 0x28b715b7, KEY_COMPOSE }, /* RightMenu */
-	{ 0x2ab195b7, KEY_PROG1 }, /* Go or MultiMon */
+	{ 0x2ab195b7, KEY_LEFTMETA }, /* Go or MultiMon */
 	{ 0x29b715b7, KEY_DASHBOARD }, /* AppLauncher */
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-kworld-315u.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
 
 static struct rc_map_table kworld_315u[] = {
 	{ 0x6143, KEY_POWER },
-	{ 0x6101, KEY_TUNER },		/* source */
+	{ 0x6101, KEY_VIDEO },		/* source */
 	{ 0x610b, KEY_ZOOM },
 	{ 0x6103, KEY_POWER2 },		/* shutdown */
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-kworld-plus-tv-analog.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
  */
 
 static struct rc_map_table kworld_plus_tv_analog[] = {
-	{ 0x0c, KEY_PROG1 },		/* Kworld key */
+	{ 0x0c, KEY_LEFTMETA },		/* Kworld key */
 	{ 0x16, KEY_CLOSECD },		/* -> ) */
 	{ 0x1d, KEY_POWER2 },
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-lme2510.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-lme2510.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-lme2510.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-lme2510.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,33 +13,75 @@
 
 
 static struct rc_map_table lme2510_rc[] = {
-	{ 0xba45, KEY_0 },
-	{ 0xa05f, KEY_1 },
-	{ 0xaf50, KEY_2 },
-	{ 0xa25d, KEY_3 },
-	{ 0xbe41, KEY_4 },
-	{ 0xf50a, KEY_5 },
-	{ 0xbd42, KEY_6 },
-	{ 0xb847, KEY_7 },
-	{ 0xb649, KEY_8 },
-	{ 0xfa05, KEY_9 },
-	{ 0xbc43, KEY_POWER },
-	{ 0xb946, KEY_SUBTITLE },
-	{ 0xf906, KEY_PAUSE },
-	{ 0xfc03, KEY_MEDIA_REPEAT},
-	{ 0xfd02, KEY_PAUSE },
-	{ 0xa15e, KEY_VOLUMEUP },
-	{ 0xa35c, KEY_VOLUMEDOWN },
-	{ 0xf609, KEY_CHANNELUP },
-	{ 0xe51a, KEY_CHANNELDOWN },
-	{ 0xe11e, KEY_PLAY },
-	{ 0xe41b, KEY_ZOOM },
-	{ 0xa659, KEY_MUTE },
-	{ 0xa55a, KEY_TV },
-	{ 0xe718, KEY_RECORD },
-	{ 0xf807, KEY_EPG },
-	{ 0xfe01, KEY_STOP },
-
+	/* Type 1 - 26 buttons */
+	{ 0xef12ba45, KEY_0 },
+	{ 0xef12a05f, KEY_1 },
+	{ 0xef12af50, KEY_2 },
+	{ 0xef12a25d, KEY_3 },
+	{ 0xef12be41, KEY_4 },
+	{ 0xef12f50a, KEY_5 },
+	{ 0xef12bd42, KEY_6 },
+	{ 0xef12b847, KEY_7 },
+	{ 0xef12b649, KEY_8 },
+	{ 0xef12fa05, KEY_9 },
+	{ 0xef12bc43, KEY_POWER },
+	{ 0xef12b946, KEY_SUBTITLE },
+	{ 0xef12f906, KEY_PAUSE },
+	{ 0xef12fc03, KEY_MEDIA_REPEAT},
+	{ 0xef12fd02, KEY_PAUSE },
+	{ 0xef12a15e, KEY_VOLUMEUP },
+	{ 0xef12a35c, KEY_VOLUMEDOWN },
+	{ 0xef12f609, KEY_CHANNELUP },
+	{ 0xef12e51a, KEY_CHANNELDOWN },
+	{ 0xef12e11e, KEY_PLAY },
+	{ 0xef12e41b, KEY_ZOOM },
+	{ 0xef12a659, KEY_MUTE },
+	{ 0xef12a55a, KEY_TV },
+	{ 0xef12e718, KEY_RECORD },
+	{ 0xef12f807, KEY_EPG },
+	{ 0xef12fe01, KEY_STOP },
+	/* Type 2 - 20 buttons */
+	{ 0xff40ea15, KEY_0 },
+	{ 0xff40f708, KEY_1 },
+	{ 0xff40f609, KEY_2 },
+	{ 0xff40f50a, KEY_3 },
+	{ 0xff40f30c, KEY_4 },
+	{ 0xff40f20d, KEY_5 },
+	{ 0xff40f10e, KEY_6 },
+	{ 0xff40ef10, KEY_7 },
+	{ 0xff40ee11, KEY_8 },
+	{ 0xff40ed12, KEY_9 },
+	{ 0xff40ff00, KEY_POWER },
+	{ 0xff40fb04, KEY_MEDIA_REPEAT}, /* Recall */
+	{ 0xff40e51a, KEY_PAUSE }, /* Timeshift */
+	{ 0xff40fd02, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
+	{ 0xff40f906, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
+	{ 0xff40fe01, KEY_CHANNELUP },
+	{ 0xff40fa05, KEY_CHANNELDOWN },
+	{ 0xff40eb14, KEY_ZOOM },
+	{ 0xff40e718, KEY_RECORD },
+	{ 0xff40e916, KEY_STOP },
+	/* Type 3 - 20 buttons */
+	{ 0xff00e31c, KEY_0 },
+	{ 0xff00f807, KEY_1 },
+	{ 0xff00ea15, KEY_2 },
+	{ 0xff00f609, KEY_3 },
+	{ 0xff00e916, KEY_4 },
+	{ 0xff00e619, KEY_5 },
+	{ 0xff00f20d, KEY_6 },
+	{ 0xff00f30c, KEY_7 },
+	{ 0xff00e718, KEY_8 },
+	{ 0xff00a15e, KEY_9 },
+	{ 0xff00ba45, KEY_POWER },
+	{ 0xff00bb44, KEY_MEDIA_REPEAT}, /* Recall */
+	{ 0xff00b54a, KEY_PAUSE }, /* Timeshift */
+	{ 0xff00b847, KEY_VOLUMEUP }, /* 2 x -/+ Keys not marked */
+	{ 0xff00bc43, KEY_VOLUMEDOWN }, /* Volume defined as right hand*/
+	{ 0xff00b946, KEY_CHANNELUP },
+	{ 0xff00bf40, KEY_CHANNELDOWN },
+	{ 0xff00f708, KEY_ZOOM },
+	{ 0xff00bd42, KEY_RECORD },
+	{ 0xff00a55a, KEY_STOP },
 };
 
 static struct rc_map_list lme2510_map = {
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 
 	{ 0x0c, KEY_MUTE },
 	{ 0x0f, KEY_SCREEN },		/* Full Screen */
-	{ 0x10, KEY_FN },		/* Funtion */
+	{ 0x10, KEY_FN },		/* Function */
 	{ 0x11, KEY_TIME },		/* Time shift */
 	{ 0x12, KEY_POWER },
 	{ 0x13, KEY_MEDIA },		/* MTS */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-msi-tvanywhere-plus.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 	{ 0x13, KEY_AGAIN },		/* Recall */
 
 	{ 0x1e, KEY_POWER },		/* Power */
-	{ 0x07, KEY_TUNER },		/* Source */
+	{ 0x07, KEY_VIDEO },		/* Source */
 	{ 0x1c, KEY_SEARCH },		/* Scan */
 	{ 0x18, KEY_MUTE },		/* Mute */
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-nebula.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-nebula.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-nebula.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-nebula.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 	{ 0x0b, KEY_AUX },
 	{ 0x0c, KEY_DVD },
 	{ 0x0d, KEY_POWER },
-	{ 0x0e, KEY_MHP },	/* labelled 'Picture' */
+	{ 0x0e, KEY_CAMERA },	/* labelled 'Picture' */
 	{ 0x0f, KEY_AUDIO },
 	{ 0x10, KEY_INFO },
 	{ 0x11, KEY_F13 },	/* 16:9 */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-norwood.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-norwood.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-norwood.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-norwood.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 	{ 0x28, KEY_8 },
 	{ 0x29, KEY_9 },
 
-	{ 0x78, KEY_TUNER },		/* Video Source        */
+	{ 0x78, KEY_VIDEO },		/* Video Source        */
 	{ 0x2c, KEY_EXIT },		/* Open/Close software */
 	{ 0x2a, KEY_SELECT },		/* 2 Digit Select      */
 	{ 0x69, KEY_AGAIN },		/* Recall              */
@@ -49,7 +49,7 @@
 	{ 0x37, KEY_PLAY },		/* Play                */
 	{ 0x36, KEY_PAUSE },		/* Pause               */
 	{ 0x2b, KEY_STOP },		/* Stop                */
-	{ 0x67, KEY_FASTFORWARD },	/* Foward              */
+	{ 0x67, KEY_FASTFORWARD },	/* Forward              */
 	{ 0x66, KEY_REWIND },		/* Rewind              */
 	{ 0x3e, KEY_SEARCH },		/* Auto Scan           */
 	{ 0x2e, KEY_CAMERA },		/* Capture Video       */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pctv-sedna.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 	{ 0x0e, KEY_STOP },
 	{ 0x0f, KEY_PREVIOUSSONG },
 	{ 0x10, KEY_ZOOM },
-	{ 0x11, KEY_TUNER },	/* Source */
+	{ 0x11, KEY_VIDEO },	/* Source */
 	{ 0x12, KEY_POWER },
 	{ 0x13, KEY_MUTE },
 	{ 0x15, KEY_CHANNELDOWN },
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pixelview.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pixelview.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pixelview.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pixelview.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
 static struct rc_map_table pixelview[] = {
 
 	{ 0x1e, KEY_POWER },	/* power */
-	{ 0x07, KEY_MEDIA },	/* source */
+	{ 0x07, KEY_VIDEO },	/* source */
 	{ 0x1c, KEY_SEARCH },	/* scan */
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pixelview-mk12.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 	{ 0x866b13, KEY_AGAIN },	/* loop */
 	{ 0x866b10, KEY_DIGITS },	/* +100 */
 
-	{ 0x866b00, KEY_MEDIA },	/* source */
+	{ 0x866b00, KEY_VIDEO },		/* source */
 	{ 0x866b18, KEY_MUTE },		/* mute */
 	{ 0x866b19, KEY_CAMERA },	/* snapshot */
 	{ 0x866b1a, KEY_SEARCH },	/* scan */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pixelview-new.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 	{ 0x3e, KEY_0 },
 
 	{ 0x1c, KEY_AGAIN },		/* LOOP	*/
-	{ 0x3f, KEY_MEDIA },		/* Source */
+	{ 0x3f, KEY_VIDEO },		/* Source */
 	{ 0x1f, KEY_LAST },		/* +100 */
 	{ 0x1b, KEY_MUTE },
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pv951.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pv951.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-pv951.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-pv951.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,10 +46,10 @@
 	{ 0x0c, KEY_SEARCH },		/* AUTOSCAN */
 
 	/* Not sure what to do with these ones! */
-	{ 0x0f, KEY_SELECT },		/* SOURCE */
+	{ 0x0f, KEY_VIDEO },		/* SOURCE */
 	{ 0x0a, KEY_KPPLUS },		/* +100 */
 	{ 0x14, KEY_EQUAL },		/* SYNC */
-	{ 0x1c, KEY_MEDIA },		/* PC/TV */
+	{ 0x1c, KEY_TV },		/* PC/TV */
 };
 
 static struct rc_map_list pv951_map = {
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-rc5-hauppauge-new.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,141 +0,0 @@
-/* rc5-hauppauge-new.h - Keytable for rc5_hauppauge_new Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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 <media/rc-map.h>
-
-/*
- * Hauppauge:the newer, gray remotes (seems there are multiple
- * slightly different versions), shipped with cx88+ivtv cards.
- *
- * This table contains the complete RC5 code, instead of just the data part
- */
-
-static struct rc_map_table rc5_hauppauge_new[] = {
-	/* Keys 0 to 9 */
-	{ 0x1e00, KEY_0 },
-	{ 0x1e01, KEY_1 },
-	{ 0x1e02, KEY_2 },
-	{ 0x1e03, KEY_3 },
-	{ 0x1e04, KEY_4 },
-	{ 0x1e05, KEY_5 },
-	{ 0x1e06, KEY_6 },
-	{ 0x1e07, KEY_7 },
-	{ 0x1e08, KEY_8 },
-	{ 0x1e09, KEY_9 },
-
-	{ 0x1e0a, KEY_TEXT },		/* keypad asterisk as well */
-	{ 0x1e0b, KEY_RED },		/* red button */
-	{ 0x1e0c, KEY_RADIO },
-	{ 0x1e0d, KEY_MENU },
-	{ 0x1e0e, KEY_SUBTITLE },		/* also the # key */
-	{ 0x1e0f, KEY_MUTE },
-	{ 0x1e10, KEY_VOLUMEUP },
-	{ 0x1e11, KEY_VOLUMEDOWN },
-	{ 0x1e12, KEY_PREVIOUS },		/* previous channel */
-	{ 0x1e14, KEY_UP },
-	{ 0x1e15, KEY_DOWN },
-	{ 0x1e16, KEY_LEFT },
-	{ 0x1e17, KEY_RIGHT },
-	{ 0x1e18, KEY_VIDEO },		/* Videos */
-	{ 0x1e19, KEY_AUDIO },		/* Music */
-	/* 0x1e1a: Pictures - presume this means
-	   "Multimedia Home Platform" -
-	   no "PICTURES" key in input.h
-	 */
-	{ 0x1e1a, KEY_MHP },
-
-	{ 0x1e1b, KEY_EPG },		/* Guide */
-	{ 0x1e1c, KEY_TV },
-	{ 0x1e1e, KEY_NEXTSONG },		/* skip >| */
-	{ 0x1e1f, KEY_EXIT },		/* back/exit */
-	{ 0x1e20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x1e21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x1e22, KEY_CHANNEL },		/* source (old black remote) */
-	{ 0x1e24, KEY_PREVIOUSSONG },	/* replay |< */
-	{ 0x1e25, KEY_ENTER },		/* OK */
-	{ 0x1e26, KEY_SLEEP },		/* minimize (old black remote) */
-	{ 0x1e29, KEY_BLUE },		/* blue key */
-	{ 0x1e2e, KEY_GREEN },		/* green button */
-	{ 0x1e30, KEY_PAUSE },		/* pause */
-	{ 0x1e32, KEY_REWIND },		/* backward << */
-	{ 0x1e34, KEY_FASTFORWARD },	/* forward >> */
-	{ 0x1e35, KEY_PLAY },
-	{ 0x1e36, KEY_STOP },
-	{ 0x1e37, KEY_RECORD },		/* recording */
-	{ 0x1e38, KEY_YELLOW },		/* yellow key */
-	{ 0x1e3b, KEY_SELECT },		/* top right button */
-	{ 0x1e3c, KEY_ZOOM },		/* full */
-	{ 0x1e3d, KEY_POWER },		/* system power (green button) */
-
-	/* Keycodes for DSR-0112 remote bundled with Haupauge MiniStick */
-	{ 0x1d00, KEY_0 },
-	{ 0x1d01, KEY_1 },
-	{ 0x1d02, KEY_2 },
-	{ 0x1d03, KEY_3 },
-	{ 0x1d04, KEY_4 },
-	{ 0x1d05, KEY_5 },
-	{ 0x1d06, KEY_6 },
-	{ 0x1d07, KEY_7 },
-	{ 0x1d08, KEY_8 },
-	{ 0x1d09, KEY_9 },
-	{ 0x1d0a, KEY_TEXT },
-	{ 0x1d0d, KEY_MENU },
-	{ 0x1d0f, KEY_MUTE },
-	{ 0x1d10, KEY_VOLUMEUP },
-	{ 0x1d11, KEY_VOLUMEDOWN },
-	{ 0x1d12, KEY_PREVIOUS },        /* Prev.Ch .. ??? */
-	{ 0x1d14, KEY_UP },
-	{ 0x1d15, KEY_DOWN },
-	{ 0x1d16, KEY_LEFT },
-	{ 0x1d17, KEY_RIGHT },
-	{ 0x1d1c, KEY_TV },
-	{ 0x1d1e, KEY_NEXT },           /* >|             */
-	{ 0x1d1f, KEY_EXIT },
-	{ 0x1d20, KEY_CHANNELUP },
-	{ 0x1d21, KEY_CHANNELDOWN },
-	{ 0x1d24, KEY_LAST },           /* <|             */
-	{ 0x1d25, KEY_OK },
-	{ 0x1d30, KEY_PAUSE },
-	{ 0x1d32, KEY_REWIND },
-	{ 0x1d34, KEY_FASTFORWARD },
-	{ 0x1d35, KEY_PLAY },
-	{ 0x1d36, KEY_STOP },
-	{ 0x1d37, KEY_RECORD },
-	{ 0x1d3b, KEY_GOTO },
-	{ 0x1d3d, KEY_POWER },
-	{ 0x1d3f, KEY_HOME },
-};
-
-static struct rc_map_list rc5_hauppauge_new_map = {
-	.map = {
-		.scan    = rc5_hauppauge_new,
-		.size    = ARRAY_SIZE(rc5_hauppauge_new),
-		.rc_type = RC_TYPE_RC5,
-		.name    = RC_MAP_RC5_HAUPPAUGE_NEW,
-	}
-};
-
-static int __init init_rc_map_rc5_hauppauge_new(void)
-{
-	return rc_map_register(&rc5_hauppauge_new_map);
-}
-
-static void __exit exit_rc_map_rc5_hauppauge_new(void)
-{
-	rc_map_unregister(&rc5_hauppauge_new_map);
-}
-
-module_init(init_rc_map_rc5_hauppauge_new)
-module_exit(exit_rc_map_rc5_hauppauge_new)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-rc5-tv.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-rc5-tv.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-rc5-tv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-rc5-tv.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,81 +0,0 @@
-/* rc5-tv.h - Keytable for rc5_tv Remote Controller
- *
- * keymap imported from ir-keymaps.c
- *
- * Copyright (c) 2010 by Mauro Carvalho Chehab <mchehab@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 <media/rc-map.h>
-
-/* generic RC5 keytable                                          */
-/* see http://users.pandora.be/nenya/electronics/rc5/codes00.htm */
-/* used by old (black) Hauppauge remotes                         */
-
-static struct rc_map_table rc5_tv[] = {
-	/* Keys 0 to 9 */
-	{ 0x00, KEY_0 },
-	{ 0x01, KEY_1 },
-	{ 0x02, KEY_2 },
-	{ 0x03, KEY_3 },
-	{ 0x04, KEY_4 },
-	{ 0x05, KEY_5 },
-	{ 0x06, KEY_6 },
-	{ 0x07, KEY_7 },
-	{ 0x08, KEY_8 },
-	{ 0x09, KEY_9 },
-
-	{ 0x0b, KEY_CHANNEL },		/* channel / program (japan: 11) */
-	{ 0x0c, KEY_POWER },		/* standby */
-	{ 0x0d, KEY_MUTE },		/* mute / demute */
-	{ 0x0f, KEY_TV },		/* display */
-	{ 0x10, KEY_VOLUMEUP },
-	{ 0x11, KEY_VOLUMEDOWN },
-	{ 0x12, KEY_BRIGHTNESSUP },
-	{ 0x13, KEY_BRIGHTNESSDOWN },
-	{ 0x1e, KEY_SEARCH },		/* search + */
-	{ 0x20, KEY_CHANNELUP },	/* channel / program + */
-	{ 0x21, KEY_CHANNELDOWN },	/* channel / program - */
-	{ 0x22, KEY_CHANNEL },		/* alt / channel */
-	{ 0x23, KEY_LANGUAGE },		/* 1st / 2nd language */
-	{ 0x26, KEY_SLEEP },		/* sleeptimer */
-	{ 0x2e, KEY_MENU },		/* 2nd controls (USA: menu) */
-	{ 0x30, KEY_PAUSE },
-	{ 0x32, KEY_REWIND },
-	{ 0x33, KEY_GOTO },
-	{ 0x35, KEY_PLAY },
-	{ 0x36, KEY_STOP },
-	{ 0x37, KEY_RECORD },		/* recording */
-	{ 0x3c, KEY_TEXT },		/* teletext submode (Japan: 12) */
-	{ 0x3d, KEY_SUSPEND },		/* system standby */
-
-};
-
-static struct rc_map_list rc5_tv_map = {
-	.map = {
-		.scan    = rc5_tv,
-		.size    = ARRAY_SIZE(rc5_tv),
-		.rc_type = RC_TYPE_UNKNOWN,	/* Legacy IR type */
-		.name    = RC_MAP_RC5_TV,
-	}
-};
-
-static int __init init_rc_map_rc5_tv(void)
-{
-	return rc_map_register(&rc5_tv_map);
-}
-
-static void __exit exit_rc_map_rc5_tv(void)
-{
-	rc_map_unregister(&rc5_tv_map);
-}
-
-module_init(init_rc_map_rc5_tv)
-module_exit(exit_rc_map_rc5_tv)
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-rc6-mce.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 	{ 0x800f040a, KEY_DELETE },
 	{ 0x800f040b, KEY_ENTER },
 	{ 0x800f040c, KEY_POWER },		/* PC Power */
-	{ 0x800f040d, KEY_PROG1 },		/* Windows MCE button */
+	{ 0x800f040d, KEY_LEFTMETA },		/* Windows MCE button */
 	{ 0x800f040e, KEY_MUTE },
 	{ 0x800f040f, KEY_INFO },
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-real-audio-220-32-keys.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 	{ 0x15, KEY_CHANNELDOWN},
 	{ 0x16, KEY_ENTER},
 
-	{ 0x11, KEY_LIST},		/* Source */
+	{ 0x11, KEY_VIDEO},		/* Source */
 	{ 0x0d, KEY_AUDIO},		/* stereo */
 
 	{ 0x0f, KEY_PREVIOUS},		/* Prev */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-technisat-usb2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,93 @@
+/* rc-technisat-usb2.c - Keytable for SkyStar HD USB
+ *
+ * Copyright (C) 2010 Patrick Boettcher,
+ *                    Kernel Labs Inc. PO Box 745, St James, NY 11780
+ *
+ * Development was sponsored by Technisat Digital UK Limited, whose
+ * registered office is Witan Gate House 500 - 600 Witan Gate West,
+ * Milton Keynes, MK9 1SH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * THIS PROGRAM IS PROVIDED "AS IS" AND BOTH THE COPYRIGHT HOLDER AND
+ * TECHNISAT DIGITAL UK LTD DISCLAIM ALL WARRANTIES WITH REGARD TO
+ * THIS PROGRAM INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY OR
+ * FITNESS FOR A PARTICULAR PURPOSE.  NEITHER THE COPYRIGHT HOLDER
+ * NOR TECHNISAT DIGITAL UK LIMITED SHALL 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 PROGRAM. See the
+ * GNU General Public License for more details.
+ */
+
+#include <media/rc-map.h>
+
+static struct rc_map_table technisat_usb2[] = {
+	{0x0a0c, KEY_POWER},
+	{0x0a01, KEY_1},
+	{0x0a02, KEY_2},
+	{0x0a03, KEY_3},
+	{0x0a0d, KEY_MUTE},
+	{0x0a04, KEY_4},
+	{0x0a05, KEY_5},
+	{0x0a06, KEY_6},
+	{0x0a38, KEY_VIDEO}, /* EXT */
+	{0x0a07, KEY_7},
+	{0x0a08, KEY_8},
+	{0x0a09, KEY_9},
+	{0x0a00, KEY_0},
+	{0x0a4f, KEY_INFO},
+	{0x0a20, KEY_CHANNELUP},
+	{0x0a52, KEY_MENU},
+	{0x0a11, KEY_VOLUMEUP},
+	{0x0a57, KEY_OK},
+	{0x0a10, KEY_VOLUMEDOWN},
+	{0x0a2f, KEY_EPG},
+	{0x0a21, KEY_CHANNELDOWN},
+	{0x0a22, KEY_REFRESH},
+	{0x0a3c, KEY_TEXT},
+	{0x0a76, KEY_ENTER}, /* HOOK */
+	{0x0a0f, KEY_HELP},
+	{0x0a6b, KEY_RED},
+	{0x0a6c, KEY_GREEN},
+	{0x0a6d, KEY_YELLOW},
+	{0x0a6e, KEY_BLUE},
+	{0x0a29, KEY_STOP},
+	{0x0a23, KEY_LANGUAGE},
+	{0x0a53, KEY_TV},
+	{0x0a0a, KEY_PROGRAM},
+};
+
+static struct rc_map_list technisat_usb2_map = {
+	.map = {
+		.scan    = technisat_usb2,
+		.size    = ARRAY_SIZE(technisat_usb2),
+		.rc_type = RC_TYPE_RC5,
+		.name    = RC_MAP_TECHNISAT_USB2,
+	}
+};
+
+static int __init init_rc_map(void)
+{
+	return rc_map_register(&technisat_usb2_map);
+}
+
+static void __exit exit_rc_map(void)
+{
+	rc_map_unregister(&technisat_usb2_map);
+}
+
+module_init(init_rc_map)
+module_exit(exit_rc_map)
+
+MODULE_AUTHOR("Patrick Boettcher <pboettcher@kernellabs.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-terratec-slim-2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,72 @@
+/*
+ * TerraTec remote controller keytable
+ *
+ * Copyright (C) 2011 Martin Groszhauser <mgroszhauser@gmail.com>
+ * Copyright (C) 2011 Antti Palosaari <crope@iki.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
+ *    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 <media/rc-map.h>
+
+/*
+ * TerraTec slim remote, 6 rows, 3 columns.
+ * Keytable from Martin Groszhauser <mgroszhauser@gmail.com>
+ */
+static struct rc_map_table terratec_slim_2[] = {
+	{ 0x8001, KEY_MUTE },            /* MUTE */
+	{ 0x8002, KEY_VOLUMEDOWN },
+	{ 0x8003, KEY_CHANNELDOWN },
+	{ 0x8004, KEY_1 },
+	{ 0x8005, KEY_2 },
+	{ 0x8006, KEY_3 },
+	{ 0x8007, KEY_4 },
+	{ 0x8008, KEY_5 },
+	{ 0x8009, KEY_6 },
+	{ 0x800a, KEY_7 },
+	{ 0x800c, KEY_ZOOM },            /* [fullscreen] */
+	{ 0x800d, KEY_0 },
+	{ 0x800e, KEY_AGAIN },           /* [two arrows forming a circle] */
+	{ 0x8012, KEY_POWER2 },          /* [red power button] */
+	{ 0x801a, KEY_VOLUMEUP },
+	{ 0x801b, KEY_8 },
+	{ 0x801e, KEY_CHANNELUP },
+	{ 0x801f, KEY_9 },
+};
+
+static struct rc_map_list terratec_slim_2_map = {
+	.map = {
+		.scan    = terratec_slim_2,
+		.size    = ARRAY_SIZE(terratec_slim_2),
+		.rc_type = RC_TYPE_NEC,
+		.name    = RC_MAP_TERRATEC_SLIM_2,
+	}
+};
+
+static int __init init_rc_map_terratec_slim_2(void)
+{
+	return rc_map_register(&terratec_slim_2_map);
+}
+
+static void __exit exit_rc_map_terratec_slim_2(void)
+{
+	rc_map_unregister(&terratec_slim_2_map);
+}
+
+module_init(init_rc_map_terratec_slim_2)
+module_exit(exit_rc_map_terratec_slim_2)
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-winfast.c linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-winfast.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/keymaps/rc-winfast.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/keymaps/rc-winfast.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,15 +27,15 @@
 	{ 0x0e, KEY_8 },
 	{ 0x0f, KEY_9 },
 
-	{ 0x00, KEY_POWER },
+	{ 0x00, KEY_POWER2 },
 	{ 0x1b, KEY_AUDIO },		/* Audio Source */
 	{ 0x02, KEY_TUNER },		/* TV/FM, not on Y0400052 */
 	{ 0x1e, KEY_VIDEO },		/* Video Source */
 	{ 0x16, KEY_INFO },		/* Display information */
-	{ 0x04, KEY_VOLUMEUP },
-	{ 0x08, KEY_VOLUMEDOWN },
-	{ 0x0c, KEY_CHANNELUP },
-	{ 0x10, KEY_CHANNELDOWN },
+	{ 0x04, KEY_LEFT },
+	{ 0x08, KEY_RIGHT },
+	{ 0x0c, KEY_UP },
+	{ 0x10, KEY_DOWN },
 	{ 0x03, KEY_ZOOM },		/* fullscreen */
 	{ 0x1f, KEY_TEXT },		/* closed caption/teletext */
 	{ 0x20, KEY_SLEEP },
@@ -47,7 +47,7 @@
 	{ 0x2e, KEY_BLUE },
 	{ 0x18, KEY_KPPLUS },		/* fine tune + , not on Y040052 */
 	{ 0x19, KEY_KPMINUS },		/* fine tune - , not on Y040052 */
-	{ 0x2a, KEY_MEDIA },		/* PIP (Picture in picture */
+	{ 0x2a, KEY_TV2 },		/* PIP (Picture in picture */
 	{ 0x21, KEY_DOT },
 	{ 0x13, KEY_ENTER },
 	{ 0x11, KEY_LAST },		/* Recall (last channel */
@@ -57,7 +57,7 @@
 	{ 0x25, KEY_TIME },		/* Time Shifting */
 	{ 0x26, KEY_STOP },
 	{ 0x27, KEY_RECORD },
-	{ 0x28, KEY_SAVE },		/* Screenshot */
+	{ 0x28, KEY_CAMERA },		/* Screenshot */
 	{ 0x2f, KEY_MENU },
 	{ 0x30, KEY_CANCEL },
 	{ 0x31, KEY_CHANNEL },		/* Channel Surf */
@@ -70,10 +70,10 @@
 	{ 0x38, KEY_DVD },
 
 	{ 0x1a, KEY_MODE},		/* change to MCE mode on Y04G0051 */
-	{ 0x3e, KEY_F21 },		/* MCE +VOL, on Y04G0033 */
-	{ 0x3a, KEY_F22 },		/* MCE -VOL, on Y04G0033 */
-	{ 0x3b, KEY_F23 },		/* MCE +CH,  on Y04G0033 */
-	{ 0x3f, KEY_F24 }		/* MCE -CH,  on Y04G0033 */
+	{ 0x3e, KEY_VOLUMEUP },		/* MCE +VOL, on Y04G0033 */
+	{ 0x3a, KEY_VOLUMEDOWN },	/* MCE -VOL, on Y04G0033 */
+	{ 0x3b, KEY_CHANNELUP },	/* MCE +CH,  on Y04G0033 */
+	{ 0x3f, KEY_CHANNELDOWN }	/* MCE -CH,  on Y04G0033 */
 };
 
 static struct rc_map_list winfast_map = {
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/Makefile linux-libre-2.6.39-gnu/drivers/media/rc/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/rc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
 
 # stand-alone IR receivers/transmitters
 obj-$(CONFIG_IR_IMON) += imon.o
+obj-$(CONFIG_IR_ITE_CIR) += ite-cir.o
 obj-$(CONFIG_IR_MCEUSB) += mceusb.o
 obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
 obj-$(CONFIG_IR_ENE) += ene_ir.o
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/mceusb.c linux-libre-2.6.39-gnu/drivers/media/rc/mceusb.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/mceusb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/mceusb.c	2011-05-19 00:06:34.000000000 -0400
@@ -186,7 +186,7 @@
 		 * remotes, but we should have something handy,
 		 * to allow testing it
 		 */
-		.rc_map = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.rc_map = RC_MAP_HAUPPAUGE,
 		.name = "Conexant Hybrid TV (cx231xx) MCE IR",
 	},
 	[CX_HYBRID_TV] = {
@@ -220,6 +220,8 @@
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x206c) },
 	/* Philips/Spinel plus IR transceiver for ASUS */
 	{ USB_DEVICE(VENDOR_PHILIPS, 0x2088) },
+	/* Philips IR transceiver (Dell branded) */
+	{ USB_DEVICE(VENDOR_PHILIPS, 0x2093) },
 	/* Realtek MCE IR Receiver and card reader */
 	{ USB_DEVICE(VENDOR_REALTEK, 0x0161),
 	  .driver_info = MULTIFUNCTION },
@@ -261,7 +263,7 @@
 	  .driver_info = MCE_GEN2_TX_INV },
 	/* Topseed eHome Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_TOPSEED, 0x0011),
-	  .driver_info = MCE_GEN2_TX_INV },
+	  .driver_info = MCE_GEN3 },
 	/* Ricavision internal Infrared Transceiver */
 	{ USB_DEVICE(VENDOR_RICAVISION, 0x0010) },
 	/* Itron ione Libra Q-11 */
diff -druN linux-libre-2.6.38-gnu/drivers/media/rc/rc-main.c linux-libre-2.6.39-gnu/drivers/media/rc/rc-main.c
--- linux-libre-2.6.38-gnu/drivers/media/rc/rc-main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/rc/rc-main.c	2011-05-19 00:06:34.000000000 -0400
@@ -255,7 +255,7 @@
  * @rc_map:	scancode table to be searched
  * @scancode:	the desired scancode
  * @resize:	controls whether we allowed to resize the table to
- *		accomodate not yet present scancodes
+ *		accommodate not yet present scancodes
  * @return:	index of the mapping containing scancode in question
  *		or -1U in case of failure.
  *
@@ -707,7 +707,8 @@
 {
 	struct rc_dev *rdev = input_get_drvdata(idev);
 
-	rdev->close(rdev);
+	 if (rdev)
+		rdev->close(rdev);
 }
 
 /* class for /sys/class/rc */
@@ -733,6 +734,7 @@
 	{ RC_TYPE_SONY,		"sony"		},
 	{ RC_TYPE_RC5_SZ,	"rc-5-sz"	},
 	{ RC_TYPE_LIRC,		"lirc"		},
+	{ RC_TYPE_OTHER,	"other"		},
 };
 
 #define PROTO_NONE	"none"
@@ -966,8 +968,8 @@
 		return NULL;
 	}
 
-	dev->input_dev->getkeycode_new = ir_getkeycode;
-	dev->input_dev->setkeycode_new = ir_setkeycode;
+	dev->input_dev->getkeycode = ir_getkeycode;
+	dev->input_dev->setkeycode = ir_setkeycode;
 	input_set_drvdata(dev->input_dev, dev);
 
 	spin_lock_init(&dev->rc_map.lock);
@@ -1037,7 +1039,7 @@
 		goto out_table;
 
 	/*
-	 * Default delay of 250ms is too short for some protocols, expecially
+	 * Default delay of 250ms is too short for some protocols, especially
 	 * since the timeout is currently set to 250ms. Increase it to 500ms,
 	 * to avoid wrong repetition of the keycodes. Note that this must be
 	 * set after the call to input_register_device().
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/adv7343.c linux-libre-2.6.39-gnu/drivers/media/video/adv7343.c
--- linux-libre-2.6.38-gnu/drivers/media/video/adv7343.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/adv7343.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <media/adv7343.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 #include "adv7343_regs.h"
 
@@ -41,15 +42,13 @@
 
 struct adv7343_state {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	u8 reg00;
 	u8 reg01;
 	u8 reg02;
 	u8 reg35;
 	u8 reg80;
 	u8 reg82;
-	int bright;
-	int hue;
-	int gain;
 	u32 output;
 	v4l2_std_id std;
 };
@@ -59,6 +58,11 @@
 	return container_of(sd, struct adv7343_state, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct adv7343_state, hdl)->sd;
+}
+
 static inline int adv7343_write(struct v4l2_subdev *sd, u8 reg, u8 value)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -268,111 +272,22 @@
 	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)
+static int adv7343_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct adv7343_state *state = to_state(sd);
+	struct v4l2_subdev *sd = to_sd(ctrl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = state->bright;
-		break;
+		return adv7343_write(sd, ADV7343_SD_BRIGHTNESS_WSS,
+					ctrl->val);
 
 	case V4L2_CID_HUE:
-		ctrl->value = state->hue;
-		break;
+		return adv7343_write(sd, ADV7343_SD_HUE_REG, ctrl->val);
 
 	case V4L2_CID_GAIN:
-		ctrl->value = state->gain;
-		break;
-
-	default:
-		return -EINVAL;
+		return adv7343_write(sd, ADV7343_DAC2_OUTPUT_LEVEL, ctrl->val);
 	}
-
-	return 0;
+	return -EINVAL;
 }
 
 static int adv7343_g_chip_ident(struct v4l2_subdev *sd,
@@ -383,12 +298,20 @@
 	return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7343, 0);
 }
 
+static const struct v4l2_ctrl_ops adv7343_ctrl_ops = {
+	.s_ctrl = adv7343_s_ctrl,
+};
+
 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,
+	.log_status = adv7343_log_status,
+	.g_chip_ident = adv7343_g_chip_ident,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 };
 
 static int adv7343_s_std_output(struct v4l2_subdev *sd, v4l2_std_id std)
@@ -468,6 +391,7 @@
 				const struct i2c_device_id *id)
 {
 	struct adv7343_state *state;
+	int err;
 
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		return -ENODEV;
@@ -490,15 +414,46 @@
 	state->std = V4L2_STD_NTSC;
 
 	v4l2_i2c_subdev_init(&state->sd, client, &adv7343_ops);
-	return adv7343_initialize(&state->sd);
+
+	v4l2_ctrl_handler_init(&state->hdl, 2);
+	v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, ADV7343_BRIGHTNESS_MIN,
+					     ADV7343_BRIGHTNESS_MAX, 1,
+					     ADV7343_BRIGHTNESS_DEF);
+	v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
+			V4L2_CID_HUE, ADV7343_HUE_MIN,
+				      ADV7343_HUE_MAX, 1,
+				      ADV7343_HUE_DEF);
+	v4l2_ctrl_new_std(&state->hdl, &adv7343_ctrl_ops,
+			V4L2_CID_GAIN, ADV7343_GAIN_MIN,
+				       ADV7343_GAIN_MAX, 1,
+				       ADV7343_GAIN_DEF);
+	state->sd.ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&state->hdl);
+
+	err = adv7343_initialize(&state->sd);
+	if (err) {
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+	}
+	return err;
 }
 
 static int adv7343_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct adv7343_state *state = to_state(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_state(sd));
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/adv7343_regs.h linux-libre-2.6.39-gnu/drivers/media/video/adv7343_regs.h
--- linux-libre-2.6.38-gnu/drivers/media/video/adv7343_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/adv7343_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -102,10 +102,6 @@
 
 /* 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)
@@ -178,8 +174,8 @@
 #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_MAX	(64)
+#define ADV7343_GAIN_MIN	(-64)
 #define ADV7343_GAIN_DEF	(0)
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/au0828/au0828-cards.c linux-libre-2.6.39-gnu/drivers/media/video/au0828/au0828-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/au0828/au0828-cards.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/au0828/au0828-cards.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,8 +185,7 @@
 	static u8 eeprom[256];
 	struct tuner_setup tun_setup;
 	struct v4l2_subdev *sd;
-	unsigned int mode_mask = T_ANALOG_TV |
-				 T_DIGITAL_TV;
+	unsigned int mode_mask = T_ANALOG_TV;
 
 	dprintk(1, "%s()\n", __func__);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/au0828/au0828-dvb.c linux-libre-2.6.39-gnu/drivers/media/video/au0828/au0828-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/au0828/au0828-dvb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/au0828/au0828-dvb.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,6 @@
 /*-------------------------------------------------------------------*/
 static void urb_completion(struct urb *purb)
 {
-	u8 *ptr;
 	struct au0828_dev *dev = purb->context;
 	int ptype = usb_pipetype(purb->pipe);
 
@@ -114,8 +113,6 @@
 		return;
 	}
 
-	ptr = (u8 *)purb->transfer_buffer;
-
 	/* Feed the transport payload into the kernel demux */
 	dvb_dmx_swfilter_packets(&dev->dvb.demux,
 		purb->transfer_buffer, purb->actual_length / 188);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/au0828/au0828-video.c linux-libre-2.6.39-gnu/drivers/media/video/au0828/au0828-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/au0828/au0828-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/au0828/au0828-video.c	2011-05-19 00:06:34.000000000 -0400
@@ -502,7 +502,7 @@
 
 	/* Get the next buffer */
 	*buf = list_entry(dma_q->active.next, struct au0828_buffer, vb.queue);
-	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
 	outp = videobuf_to_vmalloc(&(*buf)->vb);
 	memset(outp, 0x00, (*buf)->vb.size);
 
@@ -1177,10 +1177,6 @@
 	int ret;
 	int width = format->fmt.pix.width;
 	int height = format->fmt.pix.height;
-	unsigned int maxwidth, maxheight;
-
-	maxwidth = 720;
-	maxheight = 480;
 
 	if (format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/bt819.c linux-libre-2.6.39-gnu/drivers/media/video/bt819.c
--- linux-libre-2.6.38-gnu/drivers/media/video/bt819.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/bt819.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,6 +37,7 @@
 #include <linux/slab.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 #include <media/bt819.h>
 
 MODULE_DESCRIPTION("Brooktree-819 video decoder driver");
@@ -52,16 +53,13 @@
 
 struct bt819 {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	unsigned char reg[32];
 
 	v4l2_std_id norm;
 	int ident;
 	int input;
 	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
 static inline struct bt819 *to_bt819(struct v4l2_subdev *sd)
@@ -69,6 +67,11 @@
 	return container_of(sd, struct bt819, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct bt819, hdl)->sd;
+}
+
 struct timing {
 	int hactive;
 	int hdelay;
@@ -333,71 +336,35 @@
 	return 0;
 }
 
-static int bt819_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-		break;
-
-	case V4L2_CID_CONTRAST:
-		v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
-		break;
-
-	case V4L2_CID_SATURATION:
-		v4l2_ctrl_query_fill(qc, 0, 511, 1, 256);
-		break;
-
-	case V4L2_CID_HUE:
-		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int bt819_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int bt819_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct v4l2_subdev *sd = to_sd(ctrl);
 	struct bt819 *decoder = to_bt819(sd);
 	int temp;
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		if (decoder->bright == ctrl->value)
-			break;
-		decoder->bright = ctrl->value;
-		bt819_write(decoder, 0x0a, decoder->bright);
+		bt819_write(decoder, 0x0a, ctrl->val);
 		break;
 
 	case V4L2_CID_CONTRAST:
-		if (decoder->contrast == ctrl->value)
-			break;
-		decoder->contrast = ctrl->value;
-		bt819_write(decoder, 0x0c, decoder->contrast & 0xff);
-		bt819_setbit(decoder, 0x0b, 2, ((decoder->contrast >> 8) & 0x01));
+		bt819_write(decoder, 0x0c, ctrl->val & 0xff);
+		bt819_setbit(decoder, 0x0b, 2, ((ctrl->val >> 8) & 0x01));
 		break;
 
 	case V4L2_CID_SATURATION:
-		if (decoder->sat == ctrl->value)
-			break;
-		decoder->sat = ctrl->value;
-		bt819_write(decoder, 0x0d, (decoder->sat >> 7) & 0xff);
-		bt819_setbit(decoder, 0x0b, 1, ((decoder->sat >> 15) & 0x01));
+		bt819_write(decoder, 0x0d, (ctrl->val >> 7) & 0xff);
+		bt819_setbit(decoder, 0x0b, 1, ((ctrl->val >> 15) & 0x01));
 
 		/* Ratio between U gain and V gain must stay the same as
 		   the ratio between the default U and V gain values. */
-		temp = (decoder->sat * 180) / 254;
+		temp = (ctrl->val * 180) / 254;
 		bt819_write(decoder, 0x0e, (temp >> 7) & 0xff);
 		bt819_setbit(decoder, 0x0b, 0, (temp >> 15) & 0x01);
 		break;
 
 	case V4L2_CID_HUE:
-		if (decoder->hue == ctrl->value)
-			break;
-		decoder->hue = ctrl->value;
-		bt819_write(decoder, 0x0f, decoder->hue);
+		bt819_write(decoder, 0x0f, ctrl->val);
 		break;
 
 	default:
@@ -406,29 +373,6 @@
 	return 0;
 }
 
-static int bt819_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct bt819 *decoder = to_bt819(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = decoder->bright;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = decoder->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = decoder->sat;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = decoder->hue;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
 static int bt819_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
 {
 	struct bt819 *decoder = to_bt819(sd);
@@ -439,11 +383,19 @@
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops bt819_ctrl_ops = {
+	.s_ctrl = bt819_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops bt819_core_ops = {
 	.g_chip_ident = bt819_g_chip_ident,
-	.g_ctrl = bt819_g_ctrl,
-	.s_ctrl = bt819_s_ctrl,
-	.queryctrl = bt819_queryctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 	.s_std = bt819_s_std,
 };
 
@@ -505,23 +457,40 @@
 	decoder->norm = V4L2_STD_NTSC;
 	decoder->input = 0;
 	decoder->enable = 1;
-	decoder->bright = 0;
-	decoder->contrast = 0xd8;	/* 100% of original signal */
-	decoder->hue = 0;
-	decoder->sat = 0xfe;		/* 100% of original signal */
 
 	i = bt819_init(sd);
 	if (i < 0)
 		v4l2_dbg(1, debug, sd, "init status %d\n", i);
+
+	v4l2_ctrl_handler_init(&decoder->hdl, 4);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 511, 1, 0xd8);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 511, 1, 0xfe);
+	v4l2_ctrl_new_std(&decoder->hdl, &bt819_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
 	return 0;
 }
 
 static int bt819_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct bt819 *decoder = to_bt819(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_bt819(sd));
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/bt8xx/bttv-cards.c linux-libre-2.6.39-gnu/drivers/media/video/bt8xx/bttv-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/bt8xx/bttv-cards.c	2012-03-24 01:04:11.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/bt8xx/bttv-cards.c	2012-03-24 03:28:46.000000000 -0400
@@ -2244,8 +2244,8 @@
 	},
 	[BTTV_BOARD_PICOLO_TETRA_CHIP] = {
 		/*Eric DEBIEF <debief@telemsa.com>*/
-		/*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controled*/
-		/* adds picolo_tetra_muxsel(), picolo_tetra_init(), the folowing declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/
+		/*EURESYS Picolo Tetra : 4 Conexant Fusion 878A, no audio, video input set with analog multiplexers GPIO controlled*/
+		/* adds picolo_tetra_muxsel(), picolo_tetra_init(), the following declaration strucure, and #define BTTV_BOARD_PICOLO_TETRA_CHIP*/
 		/*0x79 in bttv.h*/
 		.name           = "Euresys Picolo Tetra",
 		.video_inputs   = 4,
@@ -3616,7 +3616,7 @@
 				&btv->c.i2c_adap, "tuner",
 				0, v4l2_i2c_tuner_addrs(ADDRS_TV_WITH_DEMOD));
 
-		tun_setup.mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
+		tun_setup.mode_mask = T_ANALOG_TV;
 		tun_setup.type = btv->tuner_type;
 		tun_setup.addr = addr;
 
@@ -4564,7 +4564,7 @@
  * at one input while the monitor is looking at another.
  *
  * Since I've couldn't be bothered figuring out how to add an
- * independant muxsel for the monitor bus, I've just set it to
+ * independent muxsel for the monitor bus, I've just set it to
  * whatever the card is looking at.
  *
  *  OUT0 of the TDA8540's is connected to MUX0         (0x03)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/bt8xx/bttv-gpio.c linux-libre-2.6.39-gnu/drivers/media/video/bt8xx/bttv-gpio.c
--- linux-libre-2.6.38-gnu/drivers/media/video/bt8xx/bttv-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/bt8xx/bttv-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
     bttv-gpio.c  --  gpio sub drivers
 
     sysfs-based sub driver interface for bttv
-    mainly intented for gpio access
+    mainly intended for gpio access
 
 
     Copyright (C) 1996,97,98 Ralph  Metzler (rjkm@thp.uni-koeln.de)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/bt8xx/bttv-input.c linux-libre-2.6.39-gnu/drivers/media/video/bt8xx/bttv-input.c
--- linux-libre-2.6.38-gnu/drivers/media/video/bt8xx/bttv-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/bt8xx/bttv-input.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,12 +193,10 @@
 {
 	struct bttv_ir *ir = (struct bttv_ir *)data;
 	struct timeval tv;
-	unsigned long current_jiffies;
 	u32 gap;
 	u32 rc5 = 0;
 
 	/* get time */
-	current_jiffies = jiffies;
 	do_gettimeofday(&tv);
 
 	/* avoid overflow with gap >1s */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cafe_ccic.c linux-libre-2.6.39-gnu/drivers/media/video/cafe_ccic.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cafe_ccic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cafe_ccic.c	2011-05-19 00:06:34.000000000 -0400
@@ -383,7 +383,7 @@
 	 * causes the device to die.
 	 * Use a busy-wait because we often send a large quantity of small
 	 * commands at-once; using msleep() would cause a lot of context
-	 * switches which take longer than 2ms, resulting in a noticable
+	 * switches which take longer than 2ms, resulting in a noticeable
 	 * boot-time and capture-start delays.
 	 */
 	mdelay(2);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cpia2/cpia2_core.c linux-libre-2.6.39-gnu/drivers/media/video/cpia2/cpia2_core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cpia2/cpia2_core.c	2012-03-24 01:04:24.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cpia2/cpia2_core.c	2012-03-24 03:28:54.000000000 -0400
@@ -519,22 +519,16 @@
  *  cpia2_send_command
  *
  *****************************************************************************/
+
+#define DIR(cmd) ((cmd->direction == TRANSFER_WRITE) ? "Write" : "Read")
+#define BINDEX(cmd) (cmd->req_mode & 0x03)
+
 int cpia2_send_command(struct camera_data *cam, struct cpia2_command *cmd)
 {
 	u8 count;
 	u8 start;
-	u8 block_index;
 	u8 *buffer;
 	int retval;
-	const char* dir;
-
-	if (cmd->direction == TRANSFER_WRITE) {
-		dir = "Write";
-	} else {
-		dir = "Read";
-	}
-
-	block_index = cmd->req_mode & 0x03;
 
 	switch (cmd->req_mode & 0x0c) {
 	case CAMERAACCESS_TYPE_RANDOM:
@@ -542,32 +536,32 @@
 		start = 0;
 		buffer = (u8 *) & cmd->buffer;
 		if (debugs_on & DEBUG_REG)
-			DBG("%s Random: Register block %s\n", dir,
-			    block_name[block_index]);
+			DBG("%s Random: Register block %s\n", DIR(cmd),
+			    block_name[BINDEX(cmd)]);
 		break;
 	case CAMERAACCESS_TYPE_BLOCK:
 		count = cmd->reg_count;
 		start = cmd->start;
 		buffer = cmd->buffer.block_data;
 		if (debugs_on & DEBUG_REG)
-			DBG("%s Block: Register block %s\n", dir,
-			    block_name[block_index]);
+			DBG("%s Block: Register block %s\n", DIR(cmd),
+			    block_name[BINDEX(cmd)]);
 		break;
 	case CAMERAACCESS_TYPE_MASK:
 		count = cmd->reg_count * sizeof(struct cpia2_reg_mask);
 		start = 0;
 		buffer = (u8 *) & cmd->buffer;
 		if (debugs_on & DEBUG_REG)
-			DBG("%s Mask: Register block %s\n", dir,
-			    block_name[block_index]);
+			DBG("%s Mask: Register block %s\n", DIR(cmd),
+			    block_name[BINDEX(cmd)]);
 		break;
 	case CAMERAACCESS_TYPE_REPEAT:	/* For patch blocks only */
 		count = cmd->reg_count;
 		start = cmd->start;
 		buffer = cmd->buffer.block_data;
 		if (debugs_on & DEBUG_REG)
-			DBG("%s Repeat: Register block %s\n", dir,
-			    block_name[block_index]);
+			DBG("%s Repeat: Register block %s\n", DIR(cmd),
+			    block_name[BINDEX(cmd)]);
 		break;
 	default:
 		LOG("%s: invalid request mode\n",__func__);
@@ -584,10 +578,10 @@
 		for (i = 0; i < cmd->reg_count; i++) {
 			if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_BLOCK)
 				KINFO("%s Block: [0x%02X] = 0x%02X\n",
-				    dir, start + i, buffer[i]);
+				    DIR(cmd), start + i, buffer[i]);
 			if((cmd->req_mode & 0x0c) == CAMERAACCESS_TYPE_RANDOM)
 				KINFO("%s Random: [0x%02X] = 0x%02X\n",
-				    dir, cmd->buffer.registers[i].index,
+				    DIR(cmd), cmd->buffer.registers[i].index,
 				    cmd->buffer.registers[i].value);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cpia2/cpia2_v4l.c linux-libre-2.6.39-gnu/drivers/media/video/cpia2/cpia2_v4l.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cpia2/cpia2_v4l.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cpia2/cpia2_v4l.c	2011-05-19 00:06:34.000000000 -0400
@@ -395,10 +395,15 @@
  *
  *****************************************************************************/
 
-static int ioctl_set_gpio(void *arg, struct camera_data *cam)
+static long cpia2_default(struct file *file, void *fh, bool valid_prio,
+			  int cmd, void *arg)
 {
+	struct camera_data *cam = video_drvdata(file);
 	__u32 gpio_val;
 
+	if (cmd != CPIA2_CID_GPIO)
+		return -EINVAL;
+
 	gpio_val = *(__u32*) arg;
 
 	if (gpio_val &~ 0xFFU)
@@ -415,11 +420,10 @@
  *
  *****************************************************************************/
 
-static int ioctl_querycap(void *arg, struct camera_data *cam)
+static int cpia2_querycap(struct file *file, void *fh, struct v4l2_capability *vc)
 {
-	struct v4l2_capability *vc = arg;
+	struct camera_data *cam = video_drvdata(file);
 
-	memset(vc, 0, sizeof(*vc));
 	strcpy(vc->driver, "cpia2");
 
 	if (cam->params.pnp_id.product == 0x151)
@@ -479,22 +483,26 @@
  *
  *****************************************************************************/
 
-static int ioctl_input(unsigned int ioclt_nr,void *arg,struct camera_data *cam)
+static int cpia2_enum_input(struct file *file, void *fh, struct v4l2_input *i)
 {
-	struct v4l2_input *i = arg;
-
-	if(ioclt_nr  != VIDIOC_G_INPUT) {
-		if (i->index != 0)
-		       return -EINVAL;
-	}
-
-	memset(i, 0, sizeof(*i));
+	if (i->index)
+		return -EINVAL;
 	strcpy(i->name, "Camera");
 	i->type = V4L2_INPUT_TYPE_CAMERA;
+	return 0;
+}
 
+static int cpia2_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	*i = 0;
 	return 0;
 }
 
+static int cpia2_s_input(struct file *file, void *fh, unsigned int i)
+{
+	return i ? -EINVAL : 0;
+}
+
 /******************************************************************************
  *
  *  ioctl_enum_fmt
@@ -503,9 +511,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_enum_fmt(void *arg,struct camera_data *cam)
+static int cpia2_enum_fmt_vid_cap(struct file *file, void *fh,
+					    struct v4l2_fmtdesc *f)
 {
-	struct v4l2_fmtdesc *f = arg;
 	int index = f->index;
 
 	if (index < 0 || index > 1)
@@ -539,12 +547,10 @@
  *
  *****************************************************************************/
 
-static int ioctl_try_fmt(void *arg,struct camera_data *cam)
+static int cpia2_try_fmt_vid_cap(struct file *file, void *fh,
+					  struct v4l2_format *f)
 {
-	struct v4l2_format *f = arg;
-
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-	       return -EINVAL;
+	struct camera_data *cam = video_drvdata(file);
 
 	if (f->fmt.pix.pixelformat != V4L2_PIX_FMT_MJPEG &&
 	    f->fmt.pix.pixelformat != V4L2_PIX_FMT_JPEG)
@@ -603,12 +609,17 @@
  *
  *****************************************************************************/
 
-static int ioctl_set_fmt(void *arg,struct camera_data *cam, struct cpia2_fh *fh)
+static int cpia2_s_fmt_vid_cap(struct file *file, void *_fh,
+					struct v4l2_format *f)
 {
-	struct v4l2_format *f = arg;
+	struct camera_data *cam = video_drvdata(file);
+	struct cpia2_fh *fh = _fh;
 	int err, frame;
 
-	err = ioctl_try_fmt(arg, cam);
+	err = v4l2_prio_check(&cam->prio, fh->prio);
+	if (err)
+		return err;
+	err = cpia2_try_fmt_vid_cap(file, _fh, f);
 	if(err != 0)
 		return err;
 
@@ -658,12 +669,10 @@
  *
  *****************************************************************************/
 
-static int ioctl_get_fmt(void *arg,struct camera_data *cam)
+static int cpia2_g_fmt_vid_cap(struct file *file, void *fh,
+					struct v4l2_format *f)
 {
-	struct v4l2_format *f = arg;
-
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-	       return -EINVAL;
+	struct camera_data *cam = video_drvdata(file);
 
 	f->fmt.pix.width = cam->width;
 	f->fmt.pix.height = cam->height;
@@ -686,9 +695,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_cropcap(void *arg,struct camera_data *cam)
+static int cpia2_cropcap(struct file *file, void *fh, struct v4l2_cropcap *c)
 {
-	struct v4l2_cropcap *c = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	if (c->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 	       return -EINVAL;
@@ -715,9 +724,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_queryctrl(void *arg,struct camera_data *cam)
+static int cpia2_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
 {
-	struct v4l2_queryctrl *c = arg;
+	struct camera_data *cam = video_drvdata(file);
 	int i;
 
 	for(i=0; i<NUM_CONTROLS; ++i) {
@@ -783,12 +792,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_querymenu(void *arg,struct camera_data *cam)
+static int cpia2_querymenu(struct file *file, void *fh, struct v4l2_querymenu *m)
 {
-	struct v4l2_querymenu *m = arg;
-
-	memset(m->name, 0, sizeof(m->name));
-	m->reserved = 0;
+	struct camera_data *cam = video_drvdata(file);
 
 	switch(m->id) {
 	case CPIA2_CID_FLICKER_MODE:
@@ -837,9 +843,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_g_ctrl(void *arg,struct camera_data *cam)
+static int cpia2_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
 {
-	struct v4l2_control *c = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	switch(c->id) {
 	case V4L2_CID_BRIGHTNESS:
@@ -955,9 +961,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_s_ctrl(void *arg,struct camera_data *cam)
+static int cpia2_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
 {
-	struct v4l2_control *c = arg;
+	struct camera_data *cam = video_drvdata(file);
 	int i;
 	int retval = 0;
 
@@ -1031,9 +1037,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_g_jpegcomp(void *arg,struct camera_data *cam)
+static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
 {
-	struct v4l2_jpegcompression *parms = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	memset(parms, 0, sizeof(*parms));
 
@@ -1072,9 +1078,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_s_jpegcomp(void *arg,struct camera_data *cam)
+static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
 {
-	struct v4l2_jpegcompression *parms = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	DBG("S_JPEGCOMP APP_len:%d COM_len:%d\n",
 	    parms->APP_len, parms->COM_len);
@@ -1121,9 +1127,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_reqbufs(void *arg,struct camera_data *cam)
+static int cpia2_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *req)
 {
-	struct v4l2_requestbuffers *req = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	if(req->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
 	   req->memory != V4L2_MEMORY_MMAP)
@@ -1144,9 +1150,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_querybuf(void *arg,struct camera_data *cam)
+static int cpia2_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-	struct v4l2_buffer *buf = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
 	   buf->index > cam->num_frames)
@@ -1192,9 +1198,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_qbuf(void *arg,struct camera_data *cam)
+static int cpia2_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-	struct v4l2_buffer *buf = arg;
+	struct camera_data *cam = video_drvdata(file);
 
 	if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
 	   buf->memory != V4L2_MEMORY_MMAP ||
@@ -1248,9 +1254,9 @@
  *
  *****************************************************************************/
 
-static int ioctl_dqbuf(void *arg,struct camera_data *cam, struct file *file)
+static int cpia2_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
 {
-	struct v4l2_buffer *buf = arg;
+	struct camera_data *cam = video_drvdata(file);
 	int frame;
 
 	if(buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
@@ -1296,210 +1302,56 @@
 	return 0;
 }
 
-/******************************************************************************
- *
- *  cpia2_ioctl
- *
- *****************************************************************************/
-static long cpia2_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int cpia2_g_priority(struct file *file, void *_fh, enum v4l2_priority *p)
 {
-	struct camera_data *cam = video_drvdata(file);
-	long retval = 0;
-
-	if (!cam)
-		return -ENOTTY;
-
-	if (!cam->present)
-		return -ENODEV;
-
-	/* Priority check */
-	switch (cmd) {
-	case VIDIOC_S_FMT:
-	{
-		struct cpia2_fh *fh = file->private_data;
-		retval = v4l2_prio_check(&cam->prio, fh->prio);
-		if (retval)
-			return retval;
-		break;
-	}
-	default:
-		break;
-	}
-
-	switch (cmd) {
-	/* CPIA2 extension to Video4Linux API */
-	case CPIA2_IOC_SET_GPIO:
-		retval = ioctl_set_gpio(arg, cam);
-		break;
-	case VIDIOC_QUERYCAP:
-		retval = ioctl_querycap(arg,cam);
-		break;
-
-	case VIDIOC_ENUMINPUT:
-	case VIDIOC_G_INPUT:
-	case VIDIOC_S_INPUT:
-		retval = ioctl_input(cmd, arg, cam);
-		break;
-
-	case VIDIOC_ENUM_FMT:
-		retval = ioctl_enum_fmt(arg,cam);
-		break;
-	case VIDIOC_TRY_FMT:
-		retval = ioctl_try_fmt(arg,cam);
-		break;
-	case VIDIOC_G_FMT:
-		retval = ioctl_get_fmt(arg,cam);
-		break;
-	case VIDIOC_S_FMT:
-		retval = ioctl_set_fmt(arg,cam,file->private_data);
-		break;
-
-	case VIDIOC_CROPCAP:
-		retval = ioctl_cropcap(arg,cam);
-		break;
-	case VIDIOC_G_CROP:
-	case VIDIOC_S_CROP:
-		// TODO: I think cropping can be implemented - SJB
-		retval = -EINVAL;
-		break;
-
-	case VIDIOC_QUERYCTRL:
-		retval = ioctl_queryctrl(arg,cam);
-		break;
-	case VIDIOC_QUERYMENU:
-		retval = ioctl_querymenu(arg,cam);
-		break;
-	case VIDIOC_G_CTRL:
-		retval = ioctl_g_ctrl(arg,cam);
-		break;
-	case VIDIOC_S_CTRL:
-		retval = ioctl_s_ctrl(arg,cam);
-		break;
-
-	case VIDIOC_G_JPEGCOMP:
-		retval = ioctl_g_jpegcomp(arg,cam);
-		break;
-	case VIDIOC_S_JPEGCOMP:
-		retval = ioctl_s_jpegcomp(arg,cam);
-		break;
-
-	case VIDIOC_G_PRIORITY:
-	{
-		struct cpia2_fh *fh = file->private_data;
-		*(enum v4l2_priority*)arg = fh->prio;
-		break;
-	}
-	case VIDIOC_S_PRIORITY:
-	{
-		struct cpia2_fh *fh = file->private_data;
-		enum v4l2_priority prio;
-		prio = *(enum v4l2_priority*)arg;
-		if(cam->streaming &&
-		   prio != fh->prio &&
-		   fh->prio == V4L2_PRIORITY_RECORD) {
-			/* Can't drop record priority while streaming */
-			retval = -EBUSY;
-		} else if(prio == V4L2_PRIORITY_RECORD &&
-		   prio != fh->prio &&
-		   v4l2_prio_max(&cam->prio) == V4L2_PRIORITY_RECORD) {
-			/* Only one program can record at a time */
-			retval = -EBUSY;
-		} else {
-			retval = v4l2_prio_change(&cam->prio, &fh->prio, prio);
-		}
-		break;
-	}
-
-	case VIDIOC_REQBUFS:
-		retval = ioctl_reqbufs(arg,cam);
-		break;
-	case VIDIOC_QUERYBUF:
-		retval = ioctl_querybuf(arg,cam);
-		break;
-	case VIDIOC_QBUF:
-		retval = ioctl_qbuf(arg,cam);
-		break;
-	case VIDIOC_DQBUF:
-		retval = ioctl_dqbuf(arg,cam,file);
-		break;
-	case VIDIOC_STREAMON:
-	{
-		int type;
-		DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming);
-		type = *(int*)arg;
-		if(!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			retval = -EINVAL;
-
-		if(!cam->streaming) {
-			retval = cpia2_usb_stream_start(cam,
-					  cam->params.camera_state.stream_mode);
-		} else {
-			retval = -EINVAL;
-		}
-
-		break;
-	}
-	case VIDIOC_STREAMOFF:
-	{
-		int type;
-		DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming);
-		type = *(int*)arg;
-		if(!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			retval = -EINVAL;
-
-		if(cam->streaming) {
-			retval = cpia2_usb_stream_stop(cam);
-		} else {
-			retval = -EINVAL;
-		}
-
-		break;
-	}
-
-	case VIDIOC_ENUMOUTPUT:
-	case VIDIOC_G_OUTPUT:
-	case VIDIOC_S_OUTPUT:
-	case VIDIOC_G_MODULATOR:
-	case VIDIOC_S_MODULATOR:
+	struct cpia2_fh *fh = _fh;
 
-	case VIDIOC_ENUMAUDIO:
-	case VIDIOC_G_AUDIO:
-	case VIDIOC_S_AUDIO:
+	*p = fh->prio;
+	return 0;
+}
 
-	case VIDIOC_ENUMAUDOUT:
-	case VIDIOC_G_AUDOUT:
-	case VIDIOC_S_AUDOUT:
+static int cpia2_s_priority(struct file *file, void *_fh, enum v4l2_priority prio)
+{
+	struct camera_data *cam = video_drvdata(file);
+	struct cpia2_fh *fh = fh;
 
-	case VIDIOC_ENUMSTD:
-	case VIDIOC_QUERYSTD:
-	case VIDIOC_G_STD:
-	case VIDIOC_S_STD:
+	if (cam->streaming && prio != fh->prio &&
+			fh->prio == V4L2_PRIORITY_RECORD)
+		/* Can't drop record priority while streaming */
+		return -EBUSY;
 
-	case VIDIOC_G_TUNER:
-	case VIDIOC_S_TUNER:
-	case VIDIOC_G_FREQUENCY:
-	case VIDIOC_S_FREQUENCY:
+	if (prio == V4L2_PRIORITY_RECORD && prio != fh->prio &&
+			v4l2_prio_max(&cam->prio) == V4L2_PRIORITY_RECORD)
+		/* Only one program can record at a time */
+		return -EBUSY;
+	return v4l2_prio_change(&cam->prio, &fh->prio, prio);
+}
 
-	case VIDIOC_OVERLAY:
-	case VIDIOC_G_FBUF:
-	case VIDIOC_S_FBUF:
+static int cpia2_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+	struct camera_data *cam = video_drvdata(file);
 
-	case VIDIOC_G_PARM:
-	case VIDIOC_S_PARM:
-		retval = -EINVAL;
-		break;
-	default:
-		retval = -ENOIOCTLCMD;
-		break;
-	}
+	DBG("VIDIOC_STREAMON, streaming=%d\n", cam->streaming);
+	if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
 
-	return retval;
+	if (!cam->streaming)
+		return cpia2_usb_stream_start(cam,
+				cam->params.camera_state.stream_mode);
+	return -EINVAL;
 }
 
-static long cpia2_ioctl(struct file *file,
-		       unsigned int cmd, unsigned long arg)
+static int cpia2_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
 {
-	return video_usercopy(file, cmd, arg, cpia2_do_ioctl);
+	struct camera_data *cam = video_drvdata(file);
+
+	DBG("VIDIOC_STREAMOFF, streaming=%d\n", cam->streaming);
+	if (!cam->mmapped || type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
+	if (cam->streaming)
+		return cpia2_usb_stream_stop(cam);
+	return -EINVAL;
 }
 
 /******************************************************************************
@@ -1550,6 +1402,33 @@
 	v4l2_prio_init(&cam->prio);
 }
 
+static const struct v4l2_ioctl_ops cpia2_ioctl_ops = {
+	.vidioc_querycap		    = cpia2_querycap,
+	.vidioc_enum_input		    = cpia2_enum_input,
+	.vidioc_g_input			    = cpia2_g_input,
+	.vidioc_s_input			    = cpia2_s_input,
+	.vidioc_enum_fmt_vid_cap	    = cpia2_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		    = cpia2_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		    = cpia2_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		    = cpia2_try_fmt_vid_cap,
+	.vidioc_queryctrl		    = cpia2_queryctrl,
+	.vidioc_querymenu		    = cpia2_querymenu,
+	.vidioc_g_ctrl			    = cpia2_g_ctrl,
+	.vidioc_s_ctrl			    = cpia2_s_ctrl,
+	.vidioc_g_jpegcomp		    = cpia2_g_jpegcomp,
+	.vidioc_s_jpegcomp		    = cpia2_s_jpegcomp,
+	.vidioc_cropcap			    = cpia2_cropcap,
+	.vidioc_reqbufs			    = cpia2_reqbufs,
+	.vidioc_querybuf		    = cpia2_querybuf,
+	.vidioc_qbuf			    = cpia2_qbuf,
+	.vidioc_dqbuf			    = cpia2_dqbuf,
+	.vidioc_streamon		    = cpia2_streamon,
+	.vidioc_streamoff		    = cpia2_streamoff,
+	.vidioc_g_priority		    = cpia2_g_priority,
+	.vidioc_s_priority		    = cpia2_s_priority,
+	.vidioc_default			    = cpia2_default,
+};
+
 /***
  * The v4l video device structure initialized for this device
  ***/
@@ -1559,7 +1438,7 @@
 	.release	= cpia2_close,
 	.read		= cpia2_v4l_read,
 	.poll		= cpia2_v4l_poll,
-	.unlocked_ioctl	= cpia2_ioctl,
+	.unlocked_ioctl	= video_ioctl2,
 	.mmap		= cpia2_mmap,
 };
 
@@ -1567,6 +1446,7 @@
 	/* I could not find any place for the old .initialize initializer?? */
 	.name =		"CPiA2 Camera",
 	.fops =		&cpia2_fops,
+	.ioctl_ops =	&cpia2_ioctl_ops,
 	.release =	video_device_release,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cs5345.c linux-libre-2.6.39-gnu/drivers/media/video/cs5345.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cs5345.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cs5345.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/slab.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 MODULE_DESCRIPTION("i2c device driver for cs5345 Audio ADC");
 MODULE_AUTHOR("Hans Verkuil");
@@ -36,6 +37,20 @@
 
 MODULE_PARM_DESC(debug, "Debugging messages, 0=Off (default), 1=On");
 
+struct cs5345_state {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+};
+
+static inline struct cs5345_state *to_state(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct cs5345_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct cs5345_state, hdl)->sd;
+}
 
 /* ----------------------------------------------------------------------- */
 
@@ -65,33 +80,20 @@
 	return 0;
 }
 
-static int cs5345_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int cs5345_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
-		ctrl->value = (cs5345_read(sd, 0x04) & 0x08) != 0;
-		return 0;
-	}
-	if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
-		return -EINVAL;
-	ctrl->value = cs5345_read(sd, 0x07) & 0x3f;
-	if (ctrl->value >= 32)
-		ctrl->value = ctrl->value - 64;
-	return 0;
-}
+	struct v4l2_subdev *sd = to_sd(ctrl);
 
-static int cs5345_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	if (ctrl->id == V4L2_CID_AUDIO_MUTE) {
-		cs5345_write(sd, 0x04, ctrl->value ? 0x80 : 0);
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		cs5345_write(sd, 0x04, ctrl->val ? 0x80 : 0);
+		return 0;
+	case V4L2_CID_AUDIO_VOLUME:
+		cs5345_write(sd, 0x07, ((u8)ctrl->val) & 0x3f);
+		cs5345_write(sd, 0x08, ((u8)ctrl->val) & 0x3f);
 		return 0;
 	}
-	if (ctrl->id != V4L2_CID_AUDIO_VOLUME)
-		return -EINVAL;
-	if (ctrl->value > 24 || ctrl->value < -24)
-		return -EINVAL;
-	cs5345_write(sd, 0x07, ((u8)ctrl->value) & 0x3f);
-	cs5345_write(sd, 0x08, ((u8)ctrl->value) & 0x3f);
-	return 0;
+	return -EINVAL;
 }
 
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -144,11 +146,20 @@
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops cs5345_ctrl_ops = {
+	.s_ctrl = cs5345_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops cs5345_core_ops = {
 	.log_status = cs5345_log_status,
 	.g_chip_ident = cs5345_g_chip_ident,
-	.g_ctrl = cs5345_g_ctrl,
-	.s_ctrl = cs5345_s_ctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = cs5345_g_register,
 	.s_register = cs5345_s_register,
@@ -169,6 +180,7 @@
 static int cs5345_probe(struct i2c_client *client,
 			const struct i2c_device_id *id)
 {
+	struct cs5345_state *state;
 	struct v4l2_subdev *sd;
 
 	/* Check if the adapter supports the needed features */
@@ -178,11 +190,28 @@
 	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)
+	state = kzalloc(sizeof(struct cs5345_state), GFP_KERNEL);
+	if (state == NULL)
 		return -ENOMEM;
+	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &cs5345_ops);
 
+	v4l2_ctrl_handler_init(&state->hdl, 2);
+	v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &cs5345_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, -24, 24, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	/* set volume/mute */
+	v4l2_ctrl_handler_setup(&state->hdl);
+
 	cs5345_write(sd, 0x02, 0x00);
 	cs5345_write(sd, 0x04, 0x01);
 	cs5345_write(sd, 0x09, 0x01);
@@ -194,9 +223,11 @@
 static int cs5345_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct cs5345_state *state = to_state(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(sd);
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-av-audio.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-av-audio.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-av-audio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-av-audio.c	2011-05-19 00:06:34.000000000 -0400
@@ -342,17 +342,6 @@
 	}
 }
 
-static int get_volume(struct cx18 *cx)
-{
-	/* Volume runs +18dB to -96dB in 1/2dB steps
-	 * change to fit the msp3400 -114dB to +12dB range */
-
-	/* check PATH1_VOLUME */
-	int vol = 228 - cx18_av_read(cx, 0x8d4);
-	vol = (vol / 2) + 23;
-	return vol << 9;
-}
-
 static void set_volume(struct cx18 *cx, int volume)
 {
 	/* First convert the volume to msp3400 values (0-127) */
@@ -369,52 +358,18 @@
 	cx18_av_write(cx, 0x8d4, 228 - (vol * 2));
 }
 
-static int get_bass(struct cx18 *cx)
-{
-	/* bass is 49 steps +12dB to -12dB */
-
-	/* check PATH1_EQ_BASS_VOL */
-	int bass = cx18_av_read(cx, 0x8d9) & 0x3f;
-	bass = (((48 - bass) * 0xffff) + 47) / 48;
-	return bass;
-}
-
 static void set_bass(struct cx18 *cx, int bass)
 {
 	/* PATH1_EQ_BASS_VOL */
 	cx18_av_and_or(cx, 0x8d9, ~0x3f, 48 - (bass * 48 / 0xffff));
 }
 
-static int get_treble(struct cx18 *cx)
-{
-	/* treble is 49 steps +12dB to -12dB */
-
-	/* check PATH1_EQ_TREBLE_VOL */
-	int treble = cx18_av_read(cx, 0x8db) & 0x3f;
-	treble = (((48 - treble) * 0xffff) + 47) / 48;
-	return treble;
-}
-
 static void set_treble(struct cx18 *cx, int treble)
 {
 	/* PATH1_EQ_TREBLE_VOL */
 	cx18_av_and_or(cx, 0x8db, ~0x3f, 48 - (treble * 48 / 0xffff));
 }
 
-static int get_balance(struct cx18 *cx)
-{
-	/* balance is 7 bit, 0 to -96dB */
-
-	/* check PATH1_BAL_LEVEL */
-	int balance = cx18_av_read(cx, 0x8d5) & 0x7f;
-	/* check PATH1_BAL_LEFT */
-	if ((cx18_av_read(cx, 0x8d5) & 0x80) == 0)
-		balance = 0x80 - balance;
-	else
-		balance = 0x80 + balance;
-	return balance << 8;
-}
-
 static void set_balance(struct cx18 *cx, int balance)
 {
 	int bal = balance >> 8;
@@ -431,12 +386,6 @@
 	}
 }
 
-static int get_mute(struct cx18 *cx)
-{
-	/* check SRC1_MUTE_EN */
-	return cx18_av_read(cx, 0x8d3) & 0x2 ? 1 : 0;
-}
-
 static void set_mute(struct cx18 *cx, int mute)
 {
 	struct cx18_av_state *state = &cx->av_state;
@@ -490,50 +439,33 @@
 	return retval;
 }
 
-int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
+static int cx18_av_audio_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		ctrl->value = get_volume(cx);
-		break;
-	case V4L2_CID_AUDIO_BASS:
-		ctrl->value = get_bass(cx);
-		break;
-	case V4L2_CID_AUDIO_TREBLE:
-		ctrl->value = get_treble(cx);
-		break;
-	case V4L2_CID_AUDIO_BALANCE:
-		ctrl->value = get_balance(cx);
-		break;
-	case V4L2_CID_AUDIO_MUTE:
-		ctrl->value = get_mute(cx);
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
+	struct v4l2_subdev *sd = to_sd(ctrl);
+	struct cx18 *cx = v4l2_get_subdevdata(sd);
 
-int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl)
-{
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_VOLUME:
-		set_volume(cx, ctrl->value);
+		set_volume(cx, ctrl->val);
 		break;
 	case V4L2_CID_AUDIO_BASS:
-		set_bass(cx, ctrl->value);
+		set_bass(cx, ctrl->val);
 		break;
 	case V4L2_CID_AUDIO_TREBLE:
-		set_treble(cx, ctrl->value);
+		set_treble(cx, ctrl->val);
 		break;
 	case V4L2_CID_AUDIO_BALANCE:
-		set_balance(cx, ctrl->value);
+		set_balance(cx, ctrl->val);
 		break;
 	case V4L2_CID_AUDIO_MUTE:
-		set_mute(cx, ctrl->value);
+		set_mute(cx, ctrl->val);
 		break;
 	default:
 		return -EINVAL;
 	}
 	return 0;
 }
+
+const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops = {
+	.s_ctrl = cx18_av_audio_s_ctrl,
+};
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-av-core.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-av-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-av-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-av-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,6 +129,7 @@
 {
 	struct cx18_av_state *state = to_cx18_av_state(sd);
 	struct cx18 *cx = v4l2_get_subdevdata(sd);
+	int default_volume;
 	u32 v;
 
 	cx18_av_loadfw(cx);
@@ -247,8 +248,23 @@
 /*      	CxDevWrReg(CXADEC_SRC_COMB_CFG, 0x6628021F); */
 /*    } */
 	cx18_av_write4(cx, CXADEC_SRC_COMB_CFG, 0x6628021F);
-	state->default_volume = 228 - cx18_av_read(cx, 0x8d4);
-	state->default_volume = ((state->default_volume / 2) + 23) << 9;
+	default_volume = cx18_av_read(cx, 0x8d4);
+	/*
+	 * Enforce the legacy volume scale mapping limits to avoid
+	 * -ERANGE errors when initializing the volume control
+	 */
+	if (default_volume > 228) {
+		/* Bottom out at -96 dB, v4l2 vol range 0x2e00-0x2fff */
+		default_volume = 228;
+		cx18_av_write(cx, 0x8d4, 228);
+	} else if (default_volume < 20) {
+		/* Top out at + 8 dB, v4l2 vol range 0xfe00-0xffff */
+		default_volume = 20;
+		cx18_av_write(cx, 0x8d4, 20);
+	}
+	default_volume = (((228 - default_volume) >> 1) + 23) << 9;
+	state->volume->cur.val = state->volume->default_value = default_volume;
+	v4l2_ctrl_handler_setup(&state->hdl);
 }
 
 static int cx18_av_reset(struct v4l2_subdev *sd, u32 val)
@@ -901,126 +917,35 @@
 	return 0;
 }
 
-static int cx18_av_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int cx18_av_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct v4l2_subdev *sd = to_sd(ctrl);
 	struct cx18 *cx = v4l2_get_subdevdata(sd);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		if (ctrl->value < 0 || ctrl->value > 255) {
-			CX18_ERR_DEV(sd, "invalid brightness setting %d\n",
-				     ctrl->value);
-			return -ERANGE;
-		}
-
-		cx18_av_write(cx, 0x414, ctrl->value - 128);
+		cx18_av_write(cx, 0x414, ctrl->val - 128);
 		break;
 
 	case V4L2_CID_CONTRAST:
-		if (ctrl->value < 0 || ctrl->value > 127) {
-			CX18_ERR_DEV(sd, "invalid contrast setting %d\n",
-				     ctrl->value);
-			return -ERANGE;
-		}
-
-		cx18_av_write(cx, 0x415, ctrl->value << 1);
+		cx18_av_write(cx, 0x415, ctrl->val << 1);
 		break;
 
 	case V4L2_CID_SATURATION:
-		if (ctrl->value < 0 || ctrl->value > 127) {
-			CX18_ERR_DEV(sd, "invalid saturation setting %d\n",
-				     ctrl->value);
-			return -ERANGE;
-		}
-
-		cx18_av_write(cx, 0x420, ctrl->value << 1);
-		cx18_av_write(cx, 0x421, ctrl->value << 1);
+		cx18_av_write(cx, 0x420, ctrl->val << 1);
+		cx18_av_write(cx, 0x421, ctrl->val << 1);
 		break;
 
 	case V4L2_CID_HUE:
-		if (ctrl->value < -128 || ctrl->value > 127) {
-			CX18_ERR_DEV(sd, "invalid hue setting %d\n",
-				     ctrl->value);
-			return -ERANGE;
-		}
-
-		cx18_av_write(cx, 0x422, ctrl->value);
+		cx18_av_write(cx, 0x422, ctrl->val);
 		break;
 
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_MUTE:
-		return cx18_av_audio_s_ctrl(cx, ctrl);
-
 	default:
 		return -EINVAL;
 	}
 	return 0;
 }
 
-static int cx18_av_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct cx18 *cx = v4l2_get_subdevdata(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = (s8)cx18_av_read(cx, 0x414) + 128;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = cx18_av_read(cx, 0x415) >> 1;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = cx18_av_read(cx, 0x420) >> 1;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = (s8)cx18_av_read(cx, 0x422);
-		break;
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_MUTE:
-		return cx18_av_audio_g_ctrl(cx, ctrl);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int cx18_av_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	struct cx18_av_state *state = to_cx18_av_state(sd);
-
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-	default:
-		break;
-	}
-
-	switch (qc->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qc, 0, 65535,
-			65535 / 100, state->default_volume);
-	case V4L2_CID_AUDIO_MUTE:
-		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-		return v4l2_ctrl_query_fill(qc, 0, 65535, 65535 / 100, 32768);
-	default:
-		return -EINVAL;
-	}
-	return -EINVAL;
-}
-
 static int cx18_av_s_mbus_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *fmt)
 {
 	struct cx18_av_state *state = to_cx18_av_state(sd);
@@ -1356,14 +1281,22 @@
 }
 #endif
 
+static const struct v4l2_ctrl_ops cx18_av_ctrl_ops = {
+	.s_ctrl = cx18_av_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops cx18_av_general_ops = {
 	.g_chip_ident = cx18_av_g_chip_ident,
 	.log_status = cx18_av_log_status,
 	.load_fw = cx18_av_load_fw,
 	.reset = cx18_av_reset,
-	.queryctrl = cx18_av_queryctrl,
-	.g_ctrl = cx18_av_g_ctrl,
-	.s_ctrl = cx18_av_s_ctrl,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 	.s_std = cx18_av_s_std,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = cx18_av_g_register,
@@ -1427,8 +1360,42 @@
 	snprintf(sd->name, sizeof(sd->name),
 		 "%s %03x", cx->v4l2_dev.name, (state->rev >> 4));
 	sd->grp_id = CX18_HW_418_AV;
+	v4l2_ctrl_handler_init(&state->hdl, 9);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+
+	state->volume = v4l2_ctrl_new_std(&state->hdl,
+			&cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_VOLUME,
+			0, 65535, 65535 / 100, 0);
+	v4l2_ctrl_new_std(&state->hdl,
+			&cx18_av_audio_ctrl_ops, V4L2_CID_AUDIO_MUTE,
+			0, 1, 1, 0);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE,
+			0, 65535, 65535 / 100, 32768);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+			V4L2_CID_AUDIO_BASS,
+			0, 65535, 65535 / 100, 32768);
+	v4l2_ctrl_new_std(&state->hdl, &cx18_av_audio_ctrl_ops,
+			V4L2_CID_AUDIO_TREBLE,
+			0, 65535, 65535 / 100, 32768);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		return err;
+	}
 	err = v4l2_device_register_subdev(&cx->v4l2_dev, sd);
-	if (!err)
+	if (err)
+		v4l2_ctrl_handler_free(&state->hdl);
+	else
 		cx18_av_init(cx);
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-av-core.h linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-av-core.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-av-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-av-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #define _CX18_AV_CORE_H_
 
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 
 struct cx18;
 
@@ -95,19 +96,20 @@
 
 struct cx18_av_state {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	struct v4l2_ctrl *volume;
 	int radio;
 	v4l2_std_id std;
 	enum cx18_av_video_input vid_input;
 	enum cx18_av_audio_input aud_input;
 	u32 audclk_freq;
 	int audmode;
-	int default_volume;
 	u32 id;
 	u32 rev;
 	int is_initialized;
 
 	/*
-	 * The VBI slicer starts operating and counting lines, begining at
+	 * The VBI slicer starts operating and counting lines, beginning at
 	 * slicer line count of 1, at D lines after the deassertion of VRESET.
 	 * This staring field line, S, is 6 (& 319) or 10 (& 273) for 625 or 525
 	 * line systems respectively.  Sliced ancillary data captured on VBI
@@ -347,6 +349,11 @@
 	return container_of(sd, struct cx18_av_state, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct cx18_av_state, hdl)->sd;
+}
+
 /* ----------------------------------------------------------------------- */
 /* cx18_av-core.c 							   */
 int cx18_av_write(struct cx18 *cx, u16 addr, u8 value);
@@ -369,10 +376,9 @@
 
 /* ----------------------------------------------------------------------- */
 /* cx18_av-audio.c                                                         */
-int cx18_av_audio_g_ctrl(struct cx18 *cx, struct v4l2_control *ctrl);
-int cx18_av_audio_s_ctrl(struct cx18 *cx, struct v4l2_control *ctrl);
 int cx18_av_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
 void cx18_av_audio_set_path(struct cx18 *cx);
+extern const struct v4l2_ctrl_ops cx18_av_audio_ctrl_ops;
 
 /* ----------------------------------------------------------------------- */
 /* cx18_av-vbi.c                                                           */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-controls.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-controls.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-controls.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-controls.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,152 +30,11 @@
 #include "cx18-mailbox.h"
 #include "cx18-controls.h"
 
-/* Must be sorted from low to high control ID! */
-static const u32 user_ctrls[] = {
-	V4L2_CID_USER_CLASS,
-	V4L2_CID_BRIGHTNESS,
-	V4L2_CID_CONTRAST,
-	V4L2_CID_SATURATION,
-	V4L2_CID_HUE,
-	V4L2_CID_AUDIO_VOLUME,
-	V4L2_CID_AUDIO_BALANCE,
-	V4L2_CID_AUDIO_BASS,
-	V4L2_CID_AUDIO_TREBLE,
-	V4L2_CID_AUDIO_MUTE,
-	V4L2_CID_AUDIO_LOUDNESS,
-	0
-};
-
-static const u32 *ctrl_classes[] = {
-	user_ctrls,
-	cx2341x_mpeg_ctrls,
-	NULL
-};
-
-int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qctrl)
-{
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
-	const char *name;
-
-	qctrl->id = v4l2_ctrl_next(ctrl_classes, qctrl->id);
-	if (qctrl->id == 0)
-		return -EINVAL;
-
-	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:
-	case V4L2_CID_CONTRAST:
-		if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl))
-			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
-		return 0;
-
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_LOUDNESS:
-		if (v4l2_subdev_call(cx->sd_av, core, queryctrl, qctrl))
-			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
-		return 0;
-
-	default:
-		if (cx2341x_ctrl_query(&cx->params, qctrl))
-			qctrl->flags |= V4L2_CTRL_FLAG_DISABLED;
-		return 0;
-	}
-	strncpy(qctrl->name, name, sizeof(qctrl->name) - 1);
-	qctrl->name[sizeof(qctrl->name) - 1] = 0;
-	return 0;
-}
-
-int cx18_querymenu(struct file *file, void *fh, struct v4l2_querymenu *qmenu)
-{
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
-	struct v4l2_queryctrl qctrl;
-
-	qctrl.id = qmenu->id;
-	cx18_queryctrl(file, fh, &qctrl);
-	return v4l2_ctrl_query_menu(qmenu, &qctrl,
-			cx2341x_ctrl_get_menu(&cx->params, qmenu->id));
-}
-
-static int cx18_try_ctrl(struct file *file, void *fh,
-					struct v4l2_ext_control *vctrl)
-{
-	struct v4l2_queryctrl qctrl;
-	const char * const *menu_items = NULL;
-	int err;
-
-	qctrl.id = vctrl->id;
-	err = cx18_queryctrl(file, fh, &qctrl);
-	if (err)
-		return err;
-	if (qctrl.type == V4L2_CTRL_TYPE_MENU)
-		menu_items = v4l2_ctrl_get_menu(qctrl.id);
-	return v4l2_ctrl_check(vctrl, &qctrl, menu_items);
-}
-
-static int cx18_s_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
-{
-	switch (vctrl->id) {
-		/* Standard V4L2 controls */
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_HUE:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_CONTRAST:
-		return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl);
-
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_LOUDNESS:
-		return v4l2_subdev_call(cx->sd_av, core, s_ctrl, vctrl);
-
-	default:
-		CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int cx18_g_ctrl(struct cx18 *cx, struct v4l2_control *vctrl)
+static int cx18_s_stream_vbi_fmt(struct cx2341x_handler *cxhdl, u32 fmt)
 {
-	switch (vctrl->id) {
-		/* Standard V4L2 controls */
-	case V4L2_CID_BRIGHTNESS:
-	case V4L2_CID_HUE:
-	case V4L2_CID_SATURATION:
-	case V4L2_CID_CONTRAST:
-		return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl);
-
-	case V4L2_CID_AUDIO_VOLUME:
-	case V4L2_CID_AUDIO_MUTE:
-	case V4L2_CID_AUDIO_BALANCE:
-	case V4L2_CID_AUDIO_BASS:
-	case V4L2_CID_AUDIO_TREBLE:
-	case V4L2_CID_AUDIO_LOUDNESS:
-		return v4l2_subdev_call(cx->sd_av, core, g_ctrl, vctrl);
-
-	default:
-		CX18_DEBUG_IOCTL("invalid control 0x%x\n", vctrl->id);
-		return -EINVAL;
-	}
-	return 0;
-}
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+	int type = cxhdl->stream_type->val;
 
-static int cx18_setup_vbi_fmt(struct cx18 *cx,
-			      enum v4l2_mpeg_stream_vbi_fmt fmt,
-			      enum v4l2_mpeg_stream_type type)
-{
-	if (!(cx->v4l2_cap & V4L2_CAP_SLICED_VBI_CAPTURE))
-		return -EINVAL;
 	if (atomic_read(&cx->ana_capturing) > 0)
 		return -EBUSY;
 
@@ -230,121 +89,43 @@
 	return 0;
 }
 
-int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
+static int cx18_s_video_encoding(struct cx2341x_handler *cxhdl, u32 val)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
-	struct v4l2_control ctrl;
-
-	if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
-		int i;
-		int err = 0;
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
+	int is_mpeg1 = val == V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
+	struct v4l2_mbus_framefmt fmt;
 
-		for (i = 0; i < c->count; i++) {
-			ctrl.id = c->controls[i].id;
-			ctrl.value = c->controls[i].value;
-			err = cx18_g_ctrl(cx, &ctrl);
-			c->controls[i].value = ctrl.value;
-			if (err) {
-				c->error_idx = i;
-				break;
-			}
-		}
-		return err;
-	}
-	if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
-		return cx2341x_ext_ctrls(&cx->params, 0, c, VIDIOC_G_EXT_CTRLS);
-	return -EINVAL;
+	/* fix videodecoder resolution */
+	fmt.width = cxhdl->width / (is_mpeg1 ? 2 : 1);
+	fmt.height = cxhdl->height;
+	fmt.code = V4L2_MBUS_FMT_FIXED;
+	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
+	return 0;
 }
 
-int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
+static int cx18_s_audio_sampling_freq(struct cx2341x_handler *cxhdl, u32 idx)
 {
-	struct cx18_open_id *id = fh;
-	struct cx18 *cx = id->cx;
-	int ret;
-	struct v4l2_control ctrl;
-
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
-
-	if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
-		int i;
-		int err = 0;
-
-		for (i = 0; i < c->count; i++) {
-			ctrl.id = c->controls[i].id;
-			ctrl.value = c->controls[i].value;
-			err = cx18_s_ctrl(cx, &ctrl);
-			c->controls[i].value = ctrl.value;
-			if (err) {
-				c->error_idx = i;
-				break;
-			}
-		}
-		return err;
-	}
-	if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG) {
-		static u32 freqs[3] = { 44100, 48000, 32000 };
-		struct cx18_api_func_private priv;
-		struct cx2341x_mpeg_params p = cx->params;
-		int err = cx2341x_ext_ctrls(&p, atomic_read(&cx->ana_capturing),
-						c, VIDIOC_S_EXT_CTRLS);
-		unsigned int idx;
-
-		if (err)
-			return err;
-
-		if (p.video_encoding != cx->params.video_encoding) {
-			int is_mpeg1 = p.video_encoding ==
-						V4L2_MPEG_VIDEO_ENCODING_MPEG_1;
-			struct v4l2_mbus_framefmt fmt;
+	static const u32 freqs[3] = { 44100, 48000, 32000 };
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
 
-			/* fix videodecoder resolution */
-			fmt.width = cx->params.width / (is_mpeg1 ? 2 : 1);
-			fmt.height = cx->params.height;
-			fmt.code = V4L2_MBUS_FMT_FIXED;
-			v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &fmt);
-		}
-		priv.cx = cx;
-		priv.s = &cx->streams[id->type];
-		err = cx2341x_update(&priv, cx18_api_func, &cx->params, &p);
-		if (!err &&
-		    (cx->params.stream_vbi_fmt != p.stream_vbi_fmt ||
-		     cx->params.stream_type != p.stream_type))
-			err = cx18_setup_vbi_fmt(cx, p.stream_vbi_fmt,
-						 p.stream_type);
-		cx->params = p;
-		cx->dualwatch_stereo_mode = p.audio_properties & 0x0300;
-		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 < ARRAY_SIZE(freqs))
-			cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
-		return err;
-	}
-	return -EINVAL;
+	/* The audio clock of the digitizer must match the codec sample
+	   rate otherwise you get some very strange effects. */
+	if (idx < ARRAY_SIZE(freqs))
+		cx18_call_all(cx, audio, s_clock_freq, freqs[idx]);
+	return 0;
 }
 
-int cx18_try_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *c)
+static int cx18_s_audio_mode(struct cx2341x_handler *cxhdl, u32 val)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
-
-	if (c->ctrl_class == V4L2_CTRL_CLASS_USER) {
-		int i;
-		int err = 0;
+	struct cx18 *cx = container_of(cxhdl, struct cx18, cxhdl);
 
-		for (i = 0; i < c->count; i++) {
-			err = cx18_try_ctrl(file, fh, &c->controls[i]);
-			if (err) {
-				c->error_idx = i;
-				break;
-			}
-		}
-		return err;
-	}
-	if (c->ctrl_class == V4L2_CTRL_CLASS_MPEG)
-		return cx2341x_ext_ctrls(&cx->params,
-						atomic_read(&cx->ana_capturing),
-						c, VIDIOC_TRY_EXT_CTRLS);
-	return -EINVAL;
+	cx->dualwatch_stereo_mode = val;
+	return 0;
 }
+
+struct cx2341x_handler_ops cx18_cxhdl_ops = {
+	.s_audio_mode = cx18_s_audio_mode,
+	.s_audio_sampling_freq = cx18_s_audio_sampling_freq,
+	.s_video_encoding = cx18_s_video_encoding,
+	.s_stream_vbi_fmt = cx18_s_stream_vbi_fmt,
+};
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-controls.h linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-controls.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-controls.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-controls.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,9 +21,4 @@
  *  02111-1307  USA
  */
 
-int cx18_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *a);
-int cx18_g_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
-int cx18_s_ext_ctrls(struct file *file, void *fh, struct v4l2_ext_controls *a);
-int cx18_try_ext_ctrls(struct file *file, void *fh,
-			struct v4l2_ext_controls *a);
-int cx18_querymenu(struct file *file, void *fh, struct v4l2_querymenu *a);
+extern struct cx2341x_handler_ops cx18_cxhdl_ops;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-driver.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-driver.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-driver.c	2012-03-24 01:00:57.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-driver.c	2012-03-24 03:26:51.000000000 -0400
@@ -36,6 +36,7 @@
 #include "cx18-scb.h"
 #include "cx18-mailbox.h"
 #include "cx18-ioctl.h"
+#include "cx18-controls.h"
 #include "tuner-xc2028.h"
 
 #include <media/tveeprom.h>
@@ -729,15 +730,22 @@
 	cx->open_id = 1;
 
 	/* Initial settings */
-	cx2341x_fill_defaults(&cx->params);
-	cx->temporal_strength = cx->params.video_temporal_filter;
-	cx->spatial_strength = cx->params.video_spatial_filter;
-	cx->filter_mode = cx->params.video_spatial_filter_mode |
-		(cx->params.video_temporal_filter_mode << 1) |
-		(cx->params.video_median_filter_type << 2);
-	cx->params.port = CX2341X_PORT_MEMORY;
-	cx->params.capabilities =
-				CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI;
+	cx->cxhdl.port = CX2341X_PORT_MEMORY;
+	cx->cxhdl.capabilities = CX2341X_CAP_HAS_TS | CX2341X_CAP_HAS_SLICED_VBI;
+	cx->cxhdl.ops = &cx18_cxhdl_ops;
+	cx->cxhdl.func = cx18_api_func;
+	cx->cxhdl.priv = &cx->streams[CX18_ENC_STREAM_TYPE_MPG];
+	ret = cx2341x_handler_init(&cx->cxhdl, 50);
+	if (ret)
+		return ret;
+	cx->v4l2_dev.ctrl_handler = &cx->cxhdl.hdl;
+
+	cx->temporal_strength = cx->cxhdl.video_temporal_filter->cur.val;
+	cx->spatial_strength = cx->cxhdl.video_spatial_filter->cur.val;
+	cx->filter_mode = cx->cxhdl.video_spatial_filter_mode->cur.val |
+		(cx->cxhdl.video_temporal_filter_mode->cur.val << 1) |
+		(cx->cxhdl.video_median_filter_type->cur.val << 2);
+
 	init_waitqueue_head(&cx->cap_w);
 	init_waitqueue_head(&cx->mb_apu_waitq);
 	init_waitqueue_head(&cx->mb_cpu_waitq);
@@ -1049,7 +1057,7 @@
 	else
 		cx->is_50hz = 1;
 
-	cx->params.video_gop_size = cx->is_60hz ? 15 : 12;
+	cx2341x_handler_set_50hz(&cx->cxhdl, !cx->is_60hz);
 
 	if (cx->options.radio > 0)
 		cx->v4l2_cap |= V4L2_CAP_RADIO;
@@ -1095,7 +1103,6 @@
 
 	/* Load cx18 submodules (cx18-alsa) */
 	request_modules(cx);
-
 	return 0;
 
 free_streams:
@@ -1278,6 +1285,8 @@
 		for (i = 0; i < CX18_VBI_FRAMES; i++)
 			kfree(cx->vbi.sliced_mpeg_data[i]);
 
+	v4l2_ctrl_handler_free(&cx->av_state.hdl);
+
 	CX18_INFO("Removed %s\n", cx->card_name);
 
 	v4l2_device_unregister(v4l2_dev);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-driver.h linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-driver.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-driver.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-driver.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,6 +50,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-fh.h>
 #include <media/tuner.h>
 #include <media/ir-kbd-i2c.h>
 #include "cx18-mailbox.h"
@@ -405,12 +406,22 @@
 };
 
 struct cx18_open_id {
+	struct v4l2_fh fh;
 	u32 open_id;
 	int type;
-	enum v4l2_priority prio;
 	struct cx18 *cx;
 };
 
+static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
+{
+	return container_of(fh, struct cx18_open_id, fh);
+}
+
+static inline struct cx18_open_id *file2id(struct file *file)
+{
+	return fh2id(file->private_data);
+}
+
 /* forward declaration of struct defined in cx18-cards.h */
 struct cx18_card;
 
@@ -565,7 +576,7 @@
 	struct cx18_av_state av_state;
 
 	/* codec settings */
-	struct cx2341x_mpeg_params params;
+	struct cx2341x_handler cxhdl;
 	u32 filter_mode;
 	u32 temporal_strength;
 	u32 spatial_strength;
@@ -593,7 +604,6 @@
 				   uninitialized value in the stream->id. */
 
 	u32 base_addr;
-	struct v4l2_prio_state prio;
 
 	u8 card_rev;
 	void __iomem *enc_mem, *reg_mem;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-fileops.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-fileops.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-fileops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-fileops.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,13 +160,10 @@
 static void cx18_dualwatch(struct cx18 *cx)
 {
 	struct v4l2_tuner vt;
-	u32 new_bitmap;
 	u32 new_stereo_mode;
-	const u32 stereo_mask = 0x0300;
 	const u32 dual = 0x0200;
-	u32 h;
 
-	new_stereo_mode = cx->params.audio_properties & stereo_mask;
+	new_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
 	memset(&vt, 0, sizeof(vt));
 	cx18_call_all(cx, tuner, g_tuner, &vt);
 	if (vt.audmode == V4L2_TUNER_MODE_LANG1_LANG2 &&
@@ -176,25 +173,10 @@
 	if (new_stereo_mode == cx->dualwatch_stereo_mode)
 		return;
 
-	new_bitmap = new_stereo_mode
-			| (cx->params.audio_properties & ~stereo_mask);
-
-	CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x. "
-			"new audio_bitmask=0x%ux\n",
-			cx->dualwatch_stereo_mode, new_stereo_mode, new_bitmap);
-
-	h = cx18_find_handle(cx);
-	if (h == CX18_INVALID_TASK_HANDLE) {
-		CX18_DEBUG_INFO("dualwatch: can't find valid task handle\n");
-		return;
-	}
-
-	if (cx18_vapi(cx,
-		      CX18_CPU_SET_AUDIO_PARAMETERS, 2, h, new_bitmap) == 0) {
-		cx->dualwatch_stereo_mode = new_stereo_mode;
-		return;
-	}
-	CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
+	CX18_DEBUG_INFO("dualwatch: change stereo flag from 0x%x to 0x%x.\n",
+			   cx->dualwatch_stereo_mode, new_stereo_mode);
+	if (v4l2_ctrl_s_ctrl(cx->cxhdl.audio_mode, new_stereo_mode))
+		CX18_DEBUG_INFO("dualwatch: changing stereo flag failed\n");
 }
 
 
@@ -603,7 +585,7 @@
 ssize_t cx18_v4l2_read(struct file *filp, char __user *buf, size_t count,
 		loff_t *pos)
 {
-	struct cx18_open_id *id = filp->private_data;
+	struct cx18_open_id *id = file2id(filp);
 	struct cx18 *cx = id->cx;
 	struct cx18_stream *s = &cx->streams[id->type];
 	int rc;
@@ -620,7 +602,7 @@
 
 unsigned int cx18_v4l2_enc_poll(struct file *filp, poll_table *wait)
 {
-	struct cx18_open_id *id = filp->private_data;
+	struct cx18_open_id *id = file2id(filp);
 	struct cx18 *cx = id->cx;
 	struct cx18_stream *s = &cx->streams[id->type];
 	int eof = test_bit(CX18_F_S_STREAMOFF, &s->s_flags);
@@ -694,13 +676,15 @@
 
 int cx18_v4l2_close(struct file *filp)
 {
-	struct cx18_open_id *id = filp->private_data;
+	struct v4l2_fh *fh = filp->private_data;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	struct cx18_stream *s = &cx->streams[id->type];
 
 	CX18_DEBUG_IOCTL("close() of %s\n", s->name);
 
-	v4l2_prio_close(&cx->prio, id->prio);
+	v4l2_fh_del(fh);
+	v4l2_fh_exit(fh);
 
 	/* Easy case first: this stream was never claimed by us */
 	if (s->id != id->open_id) {
@@ -724,8 +708,8 @@
 		if (atomic_read(&cx->ana_capturing) > 0) {
 			/* Undo video mute */
 			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
-				cx->params.video_mute |
-					(cx->params.video_mute_yuv << 8));
+			    (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute) |
+			    (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8)));
 		}
 		/* Done! Unmute and continue. */
 		cx18_unmute(cx);
@@ -746,22 +730,24 @@
 	CX18_DEBUG_FILE("open %s\n", s->name);
 
 	/* Allocate memory */
-	item = kmalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
+	item = kzalloc(sizeof(struct cx18_open_id), GFP_KERNEL);
 	if (NULL == item) {
 		CX18_DEBUG_WARN("nomem on v4l2 open\n");
 		return -ENOMEM;
 	}
+	v4l2_fh_init(&item->fh, s->video_dev);
+
 	item->cx = cx;
 	item->type = s->type;
-	v4l2_prio_open(&cx->prio, &item->prio);
 
 	item->open_id = cx->open_id++;
-	filp->private_data = item;
+	filp->private_data = &item->fh;
 
 	if (item->type == CX18_ENC_STREAM_TYPE_RAD) {
 		/* Try to claim this stream */
 		if (cx18_claim_stream(item, item->type)) {
 			/* No, it's already in use */
+			v4l2_fh_exit(&item->fh);
 			kfree(item);
 			return -EBUSY;
 		}
@@ -771,6 +757,7 @@
 				/* switching to radio while capture is
 				   in progress is not polite */
 				cx18_release_stream(s);
+				v4l2_fh_exit(&item->fh);
 				kfree(item);
 				return -EBUSY;
 			}
@@ -787,6 +774,7 @@
 		/* Done! Unmute and continue. */
 		cx18_unmute(cx);
 	}
+	v4l2_fh_add(&item->fh);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-i2c.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 	/* Our default information for ir-kbd-i2c.c to use */
 	switch (hw) {
 	case CX18_HW_Z8F0811_IR_RX_HAUP:
-		init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 		init_data->type = RC_TYPE_RC5;
 		init_data->name = cx->card_name;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-ioctl.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-ioctl.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -148,12 +148,12 @@
 static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
 				struct v4l2_format *fmt)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
 
-	pixfmt->width = cx->params.width;
-	pixfmt->height = cx->params.height;
+	pixfmt->width = cx->cxhdl.width;
+	pixfmt->height = cx->cxhdl.height;
 	pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
 	pixfmt->field = V4L2_FIELD_INTERLACED;
 	pixfmt->priv = 0;
@@ -173,7 +173,7 @@
 static int cx18_g_fmt_vbi_cap(struct file *file, void *fh,
 				struct v4l2_format *fmt)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
 
 	vbifmt->sampling_rate = 27000000;
@@ -192,7 +192,7 @@
 static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_format *fmt)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
 
 	/* sane, V4L2 spec compliant, defaults */
@@ -221,7 +221,7 @@
 static int cx18_try_fmt_vid_cap(struct file *file, void *fh,
 				struct v4l2_format *fmt)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	int w = fmt->fmt.pix.width;
 	int h = fmt->fmt.pix.height;
@@ -252,7 +252,7 @@
 static int cx18_try_fmt_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_format *fmt)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
 
 	vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
@@ -271,30 +271,26 @@
 static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
 				struct v4l2_format *fmt)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	struct v4l2_mbus_framefmt mbus_fmt;
 	int ret;
 	int w, h;
 
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
-
 	ret = cx18_try_fmt_vid_cap(file, fh, fmt);
 	if (ret)
 		return ret;
 	w = fmt->fmt.pix.width;
 	h = fmt->fmt.pix.height;
 
-	if (cx->params.width == w && cx->params.height == h)
+	if (cx->cxhdl.width == w && cx->cxhdl.height == h)
 		return 0;
 
 	if (atomic_read(&cx->ana_capturing) > 0)
 		return -EBUSY;
 
-	mbus_fmt.width = cx->params.width = w;
-	mbus_fmt.height = cx->params.height = h;
+	mbus_fmt.width = cx->cxhdl.width = w;
+	mbus_fmt.height = cx->cxhdl.height = h;
 	mbus_fmt.code = V4L2_MBUS_FMT_FIXED;
 	v4l2_subdev_call(cx->sd_av, video, s_mbus_fmt, &mbus_fmt);
 	return cx18_g_fmt_vid_cap(file, fh, fmt);
@@ -303,14 +299,10 @@
 static int cx18_s_fmt_vbi_cap(struct file *file, void *fh,
 				struct v4l2_format *fmt)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	int ret;
 
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
-
 	/*
 	 * Changing the Encoder's Raw VBI parameters won't have any effect
 	 * if any analog capture is ongoing
@@ -320,7 +312,7 @@
 
 	/*
 	 * Set the digitizer registers for raw active VBI.
-	 * Note cx18_av_vbi_wipes out alot of the passed in fmt under valid
+	 * Note cx18_av_vbi_wipes out a lot of the passed in fmt under valid
 	 * calling conditions
 	 */
 	ret = v4l2_subdev_call(cx->sd_av, vbi, s_raw_fmt, &fmt->fmt.vbi);
@@ -337,15 +329,11 @@
 static int cx18_s_fmt_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_format *fmt)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	int ret;
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
 
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
-
 	cx18_try_fmt_sliced_vbi_cap(file, fh, fmt);
 
 	/*
@@ -372,7 +360,7 @@
 static int cx18_g_chip_ident(struct file *file, void *fh,
 				struct v4l2_dbg_chip_ident *chip)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	int err = 0;
 
 	chip->ident = V4L2_IDENT_NONE;
@@ -442,7 +430,7 @@
 static int cx18_g_register(struct file *file, void *fh,
 				struct v4l2_dbg_register *reg)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (v4l2_chip_match_host(&reg->match))
 		return cx18_cxc(cx, VIDIOC_DBG_G_REGISTER, reg);
@@ -454,7 +442,7 @@
 static int cx18_s_register(struct file *file, void *fh,
 				struct v4l2_dbg_register *reg)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (v4l2_chip_match_host(&reg->match))
 		return cx18_cxc(cx, VIDIOC_DBG_S_REGISTER, reg);
@@ -464,26 +452,10 @@
 }
 #endif
 
-static int cx18_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
-{
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
-
-	*p = v4l2_prio_max(&cx->prio);
-	return 0;
-}
-
-static int cx18_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
-{
-	struct cx18_open_id *id = fh;
-	struct cx18 *cx = id->cx;
-
-	return v4l2_prio_change(&cx->prio, &id->prio, prio);
-}
-
 static int cx18_querycap(struct file *file, void *fh,
 				struct v4l2_capability *vcap)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
@@ -496,14 +468,14 @@
 
 static int cx18_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	return cx18_get_audio_input(cx, vin->index, vin);
 }
 
 static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	vin->index = cx->audio_input;
 	return cx18_get_audio_input(cx, vin->index, vin);
@@ -511,7 +483,7 @@
 
 static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (vout->index >= cx->nof_audio_inputs)
 		return -EINVAL;
@@ -522,7 +494,7 @@
 
 static int cx18_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	/* set it to defaults from our table */
 	return cx18_get_input(cx, vin->index, vin);
@@ -531,7 +503,7 @@
 static int cx18_cropcap(struct file *file, void *fh,
 			struct v4l2_cropcap *cropcap)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (cropcap->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
@@ -546,13 +518,8 @@
 
 static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
-	int ret;
-
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
 
 	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
@@ -562,7 +529,7 @@
 
 static int cx18_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
 		return -EINVAL;
@@ -590,7 +557,7 @@
 
 static int cx18_g_input(struct file *file, void *fh, unsigned int *i)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	*i = cx->active_input;
 	return 0;
@@ -598,13 +565,8 @@
 
 int cx18_s_input(struct file *file, void *fh, unsigned int inp)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
-	int ret;
-
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
 
 	if (inp >= cx->nof_inputs)
 		return -EINVAL;
@@ -633,7 +595,7 @@
 static int cx18_g_frequency(struct file *file, void *fh,
 				struct v4l2_frequency *vf)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (vf->tuner != 0)
 		return -EINVAL;
@@ -644,13 +606,8 @@
 
 int cx18_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
-	int ret;
-
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
 
 	if (vf->tuner != 0)
 		return -EINVAL;
@@ -664,7 +621,7 @@
 
 static int cx18_g_std(struct file *file, void *fh, v4l2_std_id *std)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	*std = cx->std;
 	return 0;
@@ -672,13 +629,8 @@
 
 int cx18_s_std(struct file *file, void *fh, v4l2_std_id *std)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
-	int ret;
-
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
 
 	if ((*std & V4L2_STD_ALL) == 0)
 		return -EINVAL;
@@ -696,9 +648,10 @@
 
 	cx->std = *std;
 	cx->is_60hz = (*std & V4L2_STD_525_60) ? 1 : 0;
-	cx->params.is_50hz = cx->is_50hz = !cx->is_60hz;
-	cx->params.width = 720;
-	cx->params.height = cx->is_50hz ? 576 : 480;
+	cx->is_50hz = !cx->is_60hz;
+	cx2341x_handler_set_50hz(&cx->cxhdl, cx->is_50hz);
+	cx->cxhdl.width = 720;
+	cx->cxhdl.height = cx->is_50hz ? 576 : 480;
 	cx->vbi.count = cx->is_50hz ? 18 : 12;
 	cx->vbi.start[0] = cx->is_50hz ? 6 : 10;
 	cx->vbi.start[1] = cx->is_50hz ? 318 : 273;
@@ -712,13 +665,8 @@
 
 static int cx18_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
-	int ret;
-
-	ret = v4l2_prio_check(&cx->prio, id->prio);
-	if (ret)
-		return ret;
 
 	if (vt->index != 0)
 		return -EINVAL;
@@ -729,7 +677,7 @@
 
 static int cx18_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	if (vt->index != 0)
 		return -EINVAL;
@@ -750,7 +698,7 @@
 static int cx18_g_sliced_vbi_cap(struct file *file, void *fh,
 					struct v4l2_sliced_vbi_cap *cap)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	int set = cx->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
 	int f, l;
 
@@ -871,7 +819,7 @@
 static int cx18_g_enc_index(struct file *file, void *fh,
 				struct v4l2_enc_idx *idx)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	struct cx18_stream *s = &cx->streams[CX18_ENC_STREAM_TYPE_IDX];
 	s32 tmp;
 	struct cx18_mdl *mdl;
@@ -918,7 +866,7 @@
 static int cx18_encoder_cmd(struct file *file, void *fh,
 				struct v4l2_encoder_cmd *enc)
 {
-	struct cx18_open_id *id = fh;
+	struct cx18_open_id *id = fh2id(fh);
 	struct cx18 *cx = id->cx;
 	u32 h;
 
@@ -979,7 +927,7 @@
 static int cx18_try_encoder_cmd(struct file *file, void *fh,
 				struct v4l2_encoder_cmd *enc)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	switch (enc->cmd) {
 	case V4L2_ENC_CMD_START:
@@ -1011,7 +959,7 @@
 
 static int cx18_log_status(struct file *file, void *fh)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 	struct v4l2_input vidin;
 	struct v4l2_audio audin;
 	int i;
@@ -1035,7 +983,7 @@
 	mutex_unlock(&cx->gpio_lock);
 	CX18_INFO("Tuner: %s\n",
 		test_bit(CX18_F_I_RADIO_USER, &cx->i_flags) ?  "Radio" : "TV");
-	cx2341x_log_status(&cx->params, cx->v4l2_dev.name);
+	v4l2_ctrl_handler_log_status(&cx->cxhdl.hdl, cx->v4l2_dev.name);
 	CX18_INFO("Status flags: 0x%08lx\n", cx->i_flags);
 	for (i = 0; i < CX18_MAX_STREAMS; i++) {
 		struct cx18_stream *s = &cx->streams[i];
@@ -1056,9 +1004,10 @@
 	return 0;
 }
 
-static long cx18_default(struct file *file, void *fh, int cmd, void *arg)
+static long cx18_default(struct file *file, void *fh, bool valid_prio,
+							int cmd, void *arg)
 {
-	struct cx18 *cx = ((struct cx18_open_id *)fh)->cx;
+	struct cx18 *cx = fh2id(fh)->cx;
 
 	switch (cmd) {
 	case VIDIOC_INT_RESET: {
@@ -1080,14 +1029,12 @@
 		    unsigned long arg)
 {
 	struct video_device *vfd = video_devdata(filp);
-	struct cx18_open_id *id = filp->private_data;
+	struct cx18_open_id *id = file2id(filp);
 	struct cx18 *cx = id->cx;
 	long res;
 
 	mutex_lock(&cx->serialize_lock);
 
-	/* FIXME - consolidate v4l2_prio_check()'s here */
-
 	if (cx18_debug & CX18_DBGFLG_IOCTL)
 		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
 	res = video_ioctl2(filp, cmd, arg);
@@ -1098,8 +1045,6 @@
 
 static const struct v4l2_ioctl_ops cx18_ioctl_ops = {
 	.vidioc_querycap                = cx18_querycap,
-	.vidioc_g_priority              = cx18_g_priority,
-	.vidioc_s_priority              = cx18_s_priority,
 	.vidioc_s_audio                 = cx18_s_audio,
 	.vidioc_g_audio                 = cx18_g_audio,
 	.vidioc_enumaudio               = cx18_enumaudio,
@@ -1136,11 +1081,6 @@
 	.vidioc_s_register              = cx18_s_register,
 #endif
 	.vidioc_default                 = cx18_default,
-	.vidioc_queryctrl               = cx18_queryctrl,
-	.vidioc_querymenu               = cx18_querymenu,
-	.vidioc_g_ext_ctrls             = cx18_g_ext_ctrls,
-	.vidioc_s_ext_ctrls             = cx18_s_ext_ctrls,
-	.vidioc_try_ext_ctrls           = cx18_try_ext_ctrls,
 };
 
 void cx18_set_funcs(struct video_device *vdev)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-mailbox.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-mailbox.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-mailbox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-mailbox.c	2011-05-19 00:06:34.000000000 -0400
@@ -716,9 +716,8 @@
 int cx18_api_func(void *priv, u32 cmd, int in, int out,
 		u32 data[CX2341X_MBOX_MAX_DATA])
 {
-	struct cx18_api_func_private *api_priv = priv;
-	struct cx18 *cx = api_priv->cx;
-	struct cx18_stream *s = api_priv->s;
+	struct cx18_stream *s = priv;
+	struct cx18 *cx = s->cx;
 
 	switch (cmd) {
 	case CX2341X_ENC_SET_OUTPUT_PORT:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-mailbox.h linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-mailbox.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-mailbox.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-mailbox.h	2011-05-19 00:06:34.000000000 -0400
@@ -81,11 +81,6 @@
 
 struct cx18_stream;
 
-struct cx18_api_func_private {
-	struct cx18 *cx;
-	struct cx18_stream *s;
-};
-
 int cx18_api(struct cx18 *cx, u32 cmd, int args, u32 data[]);
 int cx18_vapi_result(struct cx18 *cx, u32 data[MAX_MB_ARGUMENTS], u32 cmd,
 		int args, ...);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-streams.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-streams.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-streams.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-streams.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,6 +207,7 @@
 	s->video_dev->fops = &cx18_v4l2_enc_fops;
 	s->video_dev->release = video_device_release;
 	s->video_dev->tvnorms = V4L2_STD_ALL;
+	set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
 	cx18_set_funcs(s->video_dev);
 	return 0;
 }
@@ -349,9 +350,17 @@
 
 		/* No struct video_device, but can have buffers allocated */
 		if (type == CX18_ENC_STREAM_TYPE_IDX) {
+			/* If the module params didn't inhibit IDX ... */
 			if (cx->stream_buffers[type] != 0) {
 				cx->stream_buffers[type] = 0;
-				cx18_stream_free(&cx->streams[type]);
+				/*
+				 * Before calling cx18_stream_free(),
+				 * check if the IDX stream was actually set up.
+				 * Needed, since the cx18_probe() error path
+				 * exits through here as well as normal clean up
+				 */
+				if (cx->streams[type].buffers != 0)
+					cx18_stream_free(&cx->streams[type]);
 			}
 			continue;
 		}
@@ -572,7 +581,7 @@
 		 * Set the MDL size to the exact size needed for one frame.
 		 * Use enough buffers per MDL to cover the MDL size
 		 */
-		s->mdl_size = 720 * s->cx->params.height * 3 / 2;
+		s->mdl_size = 720 * s->cx->cxhdl.height * 3 / 2;
 		s->bufs_per_mdl = s->mdl_size / s->buf_size;
 		if (s->mdl_size % s->buf_size)
 			s->bufs_per_mdl++;
@@ -607,7 +616,6 @@
 	u32 data[MAX_MB_ARGUMENTS];
 	struct cx18 *cx = s->cx;
 	int captype = 0;
-	struct cx18_api_func_private priv;
 	struct cx18_stream *s_idx;
 
 	if (!cx18_stream_enabled(s))
@@ -620,7 +628,7 @@
 		captype = CAPTURE_CHANNEL_TYPE_MPEG;
 		cx->mpg_data_received = cx->vbi_data_inserted = 0;
 		cx->dualwatch_jiffies = jiffies;
-		cx->dualwatch_stereo_mode = cx->params.audio_properties & 0x300;
+		cx->dualwatch_stereo_mode = v4l2_ctrl_g_ctrl(cx->cxhdl.audio_mode);
 		cx->search_pack_header = 0;
 		break;
 
@@ -710,21 +718,21 @@
 				 s->handle, cx18_stream_enabled(s_idx) ? 7 : 0);
 
 		/* Call out to the common CX2341x API setup for user controls */
-		priv.cx = cx;
-		priv.s = s;
-		cx2341x_update(&priv, cx18_api_func, NULL, &cx->params);
+		cx->cxhdl.priv = s;
+		cx2341x_handler_setup(&cx->cxhdl);
 
 		/*
 		 * When starting a capture and we're set for radio,
 		 * ensure the video is muted, despite the user control.
 		 */
-		if (!cx->params.video_mute &&
+		if (!cx->cxhdl.video_mute &&
 		    test_bit(CX18_F_I_RADIO_USER, &cx->i_flags))
 			cx18_vapi(cx, CX18_CPU_SET_VIDEO_MUTE, 2, s->handle,
-				  (cx->params.video_mute_yuv << 8) | 1);
+			  (v4l2_ctrl_g_ctrl(cx->cxhdl.video_mute_yuv) << 8) | 1);
 	}
 
 	if (atomic_read(&cx->tot_capturing) == 0) {
+		cx2341x_handler_set_busy(&cx->cxhdl, 1);
 		clear_bit(CX18_F_I_EOS, &cx->i_flags);
 		cx18_write_reg(cx, 7, CX18_DSP0_INTERRUPT_MASK);
 	}
@@ -826,6 +834,7 @@
 	if (atomic_read(&cx->tot_capturing) > 0)
 		return 0;
 
+	cx2341x_handler_set_busy(&cx->cxhdl, 0);
 	cx18_write_reg(cx, 5, CX18_DSP0_INTERRUPT_MASK);
 	wake_up(&s->waitq);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-vbi.c linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-vbi.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx18-vbi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx18-vbi.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 /*
  * Raster Reference/Protection (RP) bytes, used in Start/End Active
  * Video codes emitted from the digitzer in VIP 1.x mode, that flag the start
- * of VBI sample or VBI ancilliary data regions in the digitial ratser line.
+ * of VBI sample or VBI ancillary data regions in the digitial ratser line.
  *
  * Task FieldEven VerticalBlank HorizontalBlank 0 0 0 0
  */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx23418.h linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx23418.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx18/cx23418.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx18/cx23418.h	2011-05-19 00:06:34.000000000 -0400
@@ -477,7 +477,7 @@
 /* The are no buffers ready. Try again soon! */
 #define CXERR_NODATA_AGAIN      0x00001E
 
-/* The stream is stopping. Function not alllowed now! */
+/* The stream is stopping. Function not allowed now! */
 #define CXERR_STOPPING_STATUS   0x00001F
 
 /* Trying to access hardware when the power is turned OFF */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-417.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-417.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-417.c	2012-03-24 01:04:41.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-417.c	2012-03-24 03:29:03.000000000 -0400
@@ -942,13 +942,13 @@
 
 	p_current_fw = vmalloc(1884180 * 4);
 	p_fw = p_current_fw;
-	if (p_current_fw == 0) {
+	if (p_current_fw == NULL) {
 		dprintk(2, "FAIL!!!\n");
 		return -1;
 	}
 
 	p_buffer = vmalloc(4096);
-	if (p_buffer == 0) {
+	if (p_buffer == NULL) {
 		dprintk(2, "FAIL!!!\n");
 		return -1;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-avcore.c	2011-05-19 00:06:34.000000000 -0400
@@ -759,11 +759,8 @@
 	case CX231XX_VMUX_TELEVISION:
 	case CX231XX_VMUX_CABLE:
 	default:
-		switch (dev->model) {
-		case CX231XX_BOARD_CNXT_CARRAERA:
-		case CX231XX_BOARD_CNXT_RDE_250:
-		case CX231XX_BOARD_CNXT_SHELBY:
-		case CX231XX_BOARD_CNXT_RDU_250:
+		/* TODO: Test if this is also needed for xc2028/xc3028 */
+		if (dev->board.tuner_type == TUNER_XC5000) {
 			/* Disable the use of  DIF   */
 
 			status = vid_blk_read_word(dev, AFE_CTRL, &value);
@@ -820,8 +817,7 @@
 				MODE_CTRL, FLD_INPUT_MODE,
 				cx231xx_set_field(FLD_INPUT_MODE,
 						INPUT_MODE_CVBS_0));
-			break;
-		default:
+		} else {
 			/* Enable the DIF for the tuner */
 
 			/* Reinitialize the DIF */
@@ -1275,6 +1271,8 @@
 	int status = 0;
 	bool current_is_port_3;
 
+	if (dev->board.dont_use_port_3)
+		is_port_3 = false;
 	status = cx231xx_read_ctrl_reg(dev, VRT_GET_REGISTER,
 				       PWR_CTL_EN, value, 4);
 	if (status < 0)
@@ -2550,7 +2548,7 @@
 		case 4:	/* ts1 */
 			cx231xx_info("%s: set ts1 registers", __func__);
 
-		if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
+		if (dev->board.has_417) {
 			cx231xx_info(" MPEG\n");
 			value &= 0xFFFFFFFC;
 			value |= 0x3;
@@ -2579,7 +2577,7 @@
 			break;
 
 		case 6:	/* ts1 parallel mode */
-			cx231xx_info("%s: set ts1 parrallel mode registers\n",
+			cx231xx_info("%s: set ts1 parallel mode registers\n",
 				     __func__);
 			status = cx231xx_mode_register(dev, TS_MODE_REG, 0x100);
 			status = cx231xx_mode_register(dev, TS1_CFG_REG, 0x400);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-cards.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-cards.c	2012-03-24 01:01:03.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-cards.c	2012-03-24 03:26:54.000000000 -0400
@@ -261,6 +261,9 @@
 		.agc_analog_digital_select_gpio = 0x1c,
 		.gpio_pin_status_mask = 0x4001000,
 		.norm = V4L2_STD_PAL,
+		.no_alt_vanc = 1,
+		.external_av = 1,
+		.has_417 = 1,
 
 		.input = {{
 				.type = CX231XX_VMUX_COMPOSITE1,
@@ -357,19 +360,19 @@
 			.type = CX231XX_VMUX_TELEVISION,
 			.vmux = CX231XX_VIN_3_1,
 			.amux = CX231XX_AMUX_VIDEO,
-			.gpio = 0,
+			.gpio = NULL,
 		}, {
 			.type = CX231XX_VMUX_COMPOSITE1,
 			.vmux = CX231XX_VIN_2_1,
 			.amux = CX231XX_AMUX_LINE_IN,
-			.gpio = 0,
+			.gpio = NULL,
 		}, {
 			.type = CX231XX_VMUX_SVIDEO,
 			.vmux = CX231XX_VIN_1_1 |
 				(CX231XX_VIN_1_2 << 8) |
 				CX25840_SVIDEO_ON,
 			.amux = CX231XX_AMUX_LINE_IN,
-			.gpio = 0,
+			.gpio = NULL,
 		} },
 	},
 	[CX231XX_BOARD_HAUPPAUGE_USBLIVE2] = {
@@ -382,18 +385,20 @@
 		.agc_analog_digital_select_gpio = 0x0c,
 		.gpio_pin_status_mask = 0x4001000,
 		.norm = V4L2_STD_NTSC,
+		.no_alt_vanc = 1,
+		.external_av = 1,
 		.input = {{
 			.type = CX231XX_VMUX_COMPOSITE1,
 			.vmux = CX231XX_VIN_2_1,
 			.amux = CX231XX_AMUX_LINE_IN,
-			.gpio = 0,
+			.gpio = NULL,
 		}, {
 			.type = CX231XX_VMUX_SVIDEO,
 			.vmux = CX231XX_VIN_1_1 |
 				(CX231XX_VIN_1_2 << 8) |
 				CX25840_SVIDEO_ON,
 			.amux = CX231XX_AMUX_LINE_IN,
-			.gpio = 0,
+			.gpio = NULL,
 		} },
 	},
 	[CX231XX_BOARD_PV_PLAYTV_USB_HYBRID] = {
@@ -420,21 +425,50 @@
 			.type = CX231XX_VMUX_TELEVISION,
 			.vmux = CX231XX_VIN_3_1,
 			.amux = CX231XX_AMUX_VIDEO,
-			.gpio = 0,
+			.gpio = NULL,
 		}, {
 			.type = CX231XX_VMUX_COMPOSITE1,
 			.vmux = CX231XX_VIN_2_1,
 			.amux = CX231XX_AMUX_LINE_IN,
-			.gpio = 0,
+			.gpio = NULL,
 		}, {
 			.type = CX231XX_VMUX_SVIDEO,
 			.vmux = CX231XX_VIN_1_1 |
 				(CX231XX_VIN_1_2 << 8) |
 				CX25840_SVIDEO_ON,
 			.amux = CX231XX_AMUX_LINE_IN,
-			.gpio = 0,
+			.gpio = NULL,
 		} },
 	},
+	[CX231XX_BOARD_PV_XCAPTURE_USB] = {
+		.name = "Pixelview Xcapture USB",
+		.tuner_type = TUNER_ABSENT,
+		.decoder = CX231XX_AVDECODER,
+		.output_mode = OUT_MODE_VIP11,
+		.demod_xfer_mode = 0,
+		.ctl_pin_status_mask = 0xFFFFFFC4,
+		.agc_analog_digital_select_gpio = 0x0c,
+		.gpio_pin_status_mask = 0x4001000,
+		.norm = V4L2_STD_NTSC,
+		.no_alt_vanc = 1,
+		.external_av = 1,
+		.dont_use_port_3 = 1,
+
+		.input = {{
+				.type = CX231XX_VMUX_COMPOSITE1,
+				.vmux = CX231XX_VIN_2_1,
+				.amux = CX231XX_AMUX_LINE_IN,
+				.gpio = NULL,
+			}, {
+				.type = CX231XX_VMUX_SVIDEO,
+				.vmux = CX231XX_VIN_1_1 |
+					(CX231XX_VIN_1_2 << 8) |
+					CX25840_SVIDEO_ON,
+				.amux = CX231XX_AMUX_LINE_IN,
+				.gpio = NULL,
+			}
+		},
+	},
 };
 const unsigned int cx231xx_bcount = ARRAY_SIZE(cx231xx_boards);
 
@@ -464,6 +498,8 @@
 	 .driver_info = CX231XX_BOARD_HAUPPAUGE_USBLIVE2},
 	{USB_DEVICE_VER(USB_VID_PIXELVIEW, USB_PID_PIXELVIEW_SBTVD, 0x4000, 0x4001),
 	 .driver_info = CX231XX_BOARD_PV_PLAYTV_USB_HYBRID},
+	{USB_DEVICE(USB_VID_PIXELVIEW, 0x5014),
+	 .driver_info = CX231XX_BOARD_PV_XCAPTURE_USB},
 	{},
 };
 
@@ -772,7 +808,7 @@
 	/* Reset other chips required if they are tied up with GPIO pins */
 	cx231xx_add_into_devlist(dev);
 
-	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER) {
+	if (dev->board.has_417) {
 		printk(KERN_INFO "attach 417 %d\n", dev->model);
 		if (cx231xx_417_register(dev) < 0) {
 			printk(KERN_ERR
@@ -844,110 +880,110 @@
 	udev = usb_get_dev(interface_to_usbdev(interface));
 	ifnum = interface->altsetting[0].desc.bInterfaceNumber;
 
-	if (ifnum == 1) {
-		/*
-		 * Interface number 0 - IR interface
-		 */
-		/* Check to see next free device and mark as used */
-		nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
-		cx231xx_devused |= 1 << nr;
+	/*
+	 * Interface number 0 - IR interface (handled by mceusb driver)
+	 * Interface number 1 - AV interface (handled by this driver)
+	 */
+	if (ifnum != 1)
+		return -ENODEV;
 
-		if (nr >= CX231XX_MAXBOARDS) {
-			cx231xx_err(DRIVER_NAME
+	/* Check to see next free device and mark as used */
+	nr = find_first_zero_bit(&cx231xx_devused, CX231XX_MAXBOARDS);
+	cx231xx_devused |= 1 << nr;
+
+	if (nr >= CX231XX_MAXBOARDS) {
+		cx231xx_err(DRIVER_NAME
 		 ": Supports only %i cx231xx boards.\n", CX231XX_MAXBOARDS);
-			cx231xx_devused &= ~(1 << nr);
-			return -ENOMEM;
-		}
+		cx231xx_devused &= ~(1 << nr);
+		return -ENOMEM;
+	}
 
-		/* allocate memory for our device state and initialize it */
-		dev = kzalloc(sizeof(*dev), GFP_KERNEL);
-		if (dev == NULL) {
-			cx231xx_err(DRIVER_NAME ": out of memory!\n");
-			cx231xx_devused &= ~(1 << nr);
-			return -ENOMEM;
-		}
+	/* allocate memory for our device state and initialize it */
+	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+	if (dev == NULL) {
+		cx231xx_err(DRIVER_NAME ": out of memory!\n");
+		cx231xx_devused &= ~(1 << nr);
+		return -ENOMEM;
+	}
 
-		snprintf(dev->name, 29, "cx231xx #%d", nr);
-		dev->devno = nr;
-		dev->model = id->driver_info;
-		dev->video_mode.alt = -1;
-		dev->interface_count++;
+	snprintf(dev->name, 29, "cx231xx #%d", nr);
+	dev->devno = nr;
+	dev->model = id->driver_info;
+	dev->video_mode.alt = -1;
 
-		/* reset gpio dir and value */
-		dev->gpio_dir = 0;
-		dev->gpio_val = 0;
-		dev->xc_fw_load_done = 0;
-		dev->has_alsa_audio = 1;
-		dev->power_mode = -1;
-		atomic_set(&dev->devlist_count, 0);
+	dev->interface_count++;
+	/* reset gpio dir and value */
+	dev->gpio_dir = 0;
+	dev->gpio_val = 0;
+	dev->xc_fw_load_done = 0;
+	dev->has_alsa_audio = 1;
+	dev->power_mode = -1;
+	atomic_set(&dev->devlist_count, 0);
 
-		/* 0 - vbi ; 1 -sliced cc mode */
-		dev->vbi_or_sliced_cc_mode = 0;
+	/* 0 - vbi ; 1 -sliced cc mode */
+	dev->vbi_or_sliced_cc_mode = 0;
 
-		/* get maximum no.of IAD interfaces */
-		assoc_desc = udev->actconfig->intf_assoc[0];
-		dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
+	/* get maximum no.of IAD interfaces */
+	assoc_desc = udev->actconfig->intf_assoc[0];
+	dev->max_iad_interface_count = assoc_desc->bInterfaceCount;
 
-		/* init CIR module TBD */
+	/* init CIR module TBD */
 
-		/* store the current interface */
-		lif = interface;
+	/* store the current interface */
+	lif = interface;
 
-		/*mode_tv: digital=1 or analog=0*/
-		dev->mode_tv = 0;
+	/*mode_tv: digital=1 or analog=0*/
+	dev->mode_tv = 0;
 
-		dev->USE_ISO = transfer_mode;
+	dev->USE_ISO = transfer_mode;
 
-		switch (udev->speed) {
-		case USB_SPEED_LOW:
-			speed = "1.5";
-			break;
-		case USB_SPEED_UNKNOWN:
-		case USB_SPEED_FULL:
-			speed = "12";
-			break;
-		case USB_SPEED_HIGH:
-			speed = "480";
-			break;
-		default:
-			speed = "unknown";
-		}
+	switch (udev->speed) {
+	case USB_SPEED_LOW:
+		speed = "1.5";
+		break;
+	case USB_SPEED_UNKNOWN:
+	case USB_SPEED_FULL:
+		speed = "12";
+		break;
+	case USB_SPEED_HIGH:
+		speed = "480";
+		break;
+	default:
+		speed = "unknown";
+	}
 
-		if (udev->manufacturer)
-			strlcpy(descr, udev->manufacturer, sizeof(descr));
+	if (udev->manufacturer)
+		strlcpy(descr, udev->manufacturer, sizeof(descr));
 
-		if (udev->product) {
-			if (*descr)
-				strlcat(descr, " ", sizeof(descr));
-			strlcat(descr, udev->product, sizeof(descr));
-		}
+	if (udev->product) {
 		if (*descr)
 			strlcat(descr, " ", sizeof(descr));
+		strlcat(descr, udev->product, sizeof(descr));
+	}
+	if (*descr)
+		strlcat(descr, " ", sizeof(descr));
 
-		cx231xx_info("New device %s@ %s Mbps "
-		     "(%04x:%04x) with %d interfaces\n",
-		     descr,
-		     speed,
-		     le16_to_cpu(udev->descriptor.idVendor),
-		     le16_to_cpu(udev->descriptor.idProduct),
-		     dev->max_iad_interface_count);
+	cx231xx_info("New device %s@ %s Mbps "
+	     "(%04x:%04x) with %d interfaces\n",
+	     descr,
+	     speed,
+	     le16_to_cpu(udev->descriptor.idVendor),
+	     le16_to_cpu(udev->descriptor.idProduct),
+	     dev->max_iad_interface_count);
 
-		/* store the interface 0 back */
-		lif = udev->actconfig->interface[0];
+	/* store the interface 0 back */
+	lif = udev->actconfig->interface[0];
 
-		/* increment interface count */
-		dev->interface_count++;
+	/* increment interface count */
+	dev->interface_count++;
 
-		/* get device number */
-		nr = dev->devno;
+	/* get device number */
+	nr = dev->devno;
 
-		assoc_desc = udev->actconfig->intf_assoc[0];
-		if (assoc_desc->bFirstInterface != ifnum) {
-			cx231xx_err(DRIVER_NAME ": Not found "
-				    "matching IAD interface\n");
-			return -ENODEV;
-		}
-	} else {
+	assoc_desc = udev->actconfig->intf_assoc[0];
+	if (assoc_desc->bFirstInterface != ifnum) {
+		cx231xx_err(DRIVER_NAME ": Not found "
+			    "matching IAD interface\n");
 		return -ENODEV;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-core.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -571,6 +571,8 @@
 							     alt];
 		break;
 	case INDEX_VANC:
+		if (dev->board.no_alt_vanc)
+			return 0;
 		usb_interface_index =
 		    dev->current_pcb_config.hs_config_info[0].interface_info.
 		    vanc_index + 1;
@@ -600,8 +602,7 @@
 		usb_interface_index, alt);
 		/*To workaround error number=-71 on EP0 for videograbber,
 		 need add following codes.*/
-		if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER &&
-		    dev->model != CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
+		if (dev->board.no_alt_vanc)
 			return -1;
 	}
 
@@ -1301,8 +1302,7 @@
 	/* init hardware */
 	/* Note : with out calling set power mode function,
 	afe can not be set up correctly */
-	if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
-	    dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2) {
+	if (dev->board.external_av) {
 		errCode = cx231xx_set_power_mode(dev,
 				 POLARIS_AVMODE_ENXTERNAL_AV);
 		if (errCode < 0) {
@@ -1322,11 +1322,9 @@
 		}
 	}
 
-	/* reset the Tuner */
-	if ((dev->model == CX231XX_BOARD_CNXT_CARRAERA) ||
-		(dev->model == CX231XX_BOARD_CNXT_RDE_250) ||
-		(dev->model == CX231XX_BOARD_CNXT_SHELBY) ||
-		(dev->model == CX231XX_BOARD_CNXT_RDU_250))
+	/* reset the Tuner, if it is a Xceive tuner */
+	if ((dev->board.tuner_type == TUNER_XC5000) ||
+	    (dev->board.tuner_type == TUNER_XC2028))
 			cx231xx_gpio_set(dev, dev->board.tuner_gpio);
 
 	/* initialize Colibri block */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx.h linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -64,6 +64,7 @@
 #define CX231XX_BOARD_HAUPPAUGE_EXETER  8
 #define CX231XX_BOARD_HAUPPAUGE_USBLIVE2 9
 #define CX231XX_BOARD_PV_PLAYTV_USB_HYBRID 10
+#define CX231XX_BOARD_PV_XCAPTURE_USB 11
 
 /* Limits minimum and default number of buffers */
 #define CX231XX_MIN_BUF                 4
@@ -353,7 +354,11 @@
 
 	unsigned int max_range_640_480:1;
 	unsigned int has_dvb:1;
+	unsigned int has_417:1;
 	unsigned int valid:1;
+	unsigned int no_alt_vanc:1;
+	unsigned int external_av:1;
+	unsigned int dont_use_port_3:1;
 
 	unsigned char xclk, i2c_speed;
 
@@ -464,7 +469,7 @@
 #define I2C_STOP                0x0
 /* 1-- do not transmit STOP at end of transaction */
 #define I2C_NOSTOP              0x1
-/* 1--alllow slave to insert clock wait states */
+/* 1--allow slave to insert clock wait states */
 #define I2C_SYNC                0x1
 
 struct cx231xx_i2c {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,6 +54,21 @@
       } 						\
 } while (0)
 
+static inline bool is_tuner(struct cx231xx *dev, struct cx231xx_i2c *bus,
+			const struct i2c_msg *msg, int tuner_type)
+{
+	if (bus->nr != dev->board.tuner_i2c_master)
+		return false;
+
+	if (msg->addr != dev->board.tuner_addr)
+		return false;
+
+	if (dev->tuner_type != tuner_type)
+		return false;
+
+	return true;
+}
+
 /*
  * cx231xx_i2c_send_bytes()
  */
@@ -71,9 +86,7 @@
 	u16 saddr = 0;
 	u8 need_gpio = 0;
 
-	if ((bus->nr == 1) && (msg->addr == 0x61)
-	    && (dev->tuner_type == TUNER_XC5000)) {
-
+	if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
 		size = msg->len;
 
 		if (size == 2) {	/* register write sub addr */
@@ -180,9 +193,7 @@
 	u16 saddr = 0;
 	u8 need_gpio = 0;
 
-	if ((bus->nr == 1) && (msg->addr == 0x61)
-	    && dev->tuner_type == TUNER_XC5000) {
-
+	if (is_tuner(dev, bus, msg, TUNER_XC5000)) {
 		if (msg->len == 2)
 			saddr = msg->buf[0] << 8 | msg->buf[1];
 		else if (msg->len == 1)
@@ -274,9 +285,7 @@
 	else if (msg1->len == 1)
 		saddr = msg1->buf[0];
 
-	if ((bus->nr == 1) && (msg2->addr == 0x61)
-	    && dev->tuner_type == TUNER_XC5000) {
-
+	if (is_tuner(dev, bus, msg2, TUNER_XC5000)) {
 		if ((msg2->len < 16)) {
 
 			dprintk1(1,
@@ -454,8 +463,8 @@
 	[0x32 >> 1] = "GeminiIII",
 	[0x02 >> 1] = "Aquarius",
 	[0xa0 >> 1] = "eeprom",
-	[0xc0 >> 1] = "tuner/XC3028",
-	[0xc2 >> 1] = "tuner/XC5000",
+	[0xc0 >> 1] = "tuner",
+	[0xc2 >> 1] = "tuner",
 };
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-vbi.c	2011-05-19 00:06:34.000000000 -0400
@@ -631,7 +631,7 @@
 	/* Get the next buffer */
 	*buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
 
-	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
 	outp = videobuf_to_vmalloc(&(*buf)->vb);
 	memset(outp, 0, (*buf)->vb.size);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-video.c linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx231xx/cx231xx-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx231xx/cx231xx-video.c	2011-05-19 00:06:34.000000000 -0400
@@ -309,7 +309,7 @@
 	/* Get the next buffer */
 	*buf = list_entry(dma_q->active.next, struct cx231xx_buffer, vb.queue);
 
-	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
 	outp = videobuf_to_vmalloc(&(*buf)->vb);
 	memset(outp, 0, (*buf)->vb.size);
 
@@ -2190,8 +2190,7 @@
 		dev->height = norm_maxh(dev);
 
 		/* Power up in Analog TV mode */
-		if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER ||
-		    dev->model == CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
+		if (dev->board.external_av)
 			cx231xx_set_power_mode(dev,
 				 POLARIS_AVMODE_ENXTERNAL_AV);
 		else
@@ -2231,9 +2230,7 @@
 	if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 		/* Set the required alternate setting  VBI interface works in
 		   Bulk mode only */
-		if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER &&
-		    dev->model != CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
-			cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
+		cx231xx_set_alt_setting(dev, INDEX_VANC, 0);
 
 		videobuf_queue_vmalloc_init(&fh->vb_vidq, &cx231xx_vbi_qops,
 					    NULL, &dev->vbi_mode.slock,
@@ -2275,7 +2272,7 @@
 		cx231xx_info("V4L2 device %s deregistered\n",
 			     video_device_node_name(dev->vdev));
 
-		if (dev->model == CX231XX_BOARD_CNXT_VIDEO_GRABBER)
+		if (dev->board.has_417)
 			cx231xx_417_unregister(dev);
 
 		if (video_is_registered(dev->vdev))
@@ -2302,10 +2299,13 @@
 	if (res_check(fh))
 		res_free(fh);
 
-	/*To workaround error number=-71 on EP0 for VideoGrabber,
-		 need exclude following.*/
-	if (dev->model != CX231XX_BOARD_CNXT_VIDEO_GRABBER &&
-	    dev->model != CX231XX_BOARD_HAUPPAUGE_USBLIVE2)
+	/*
+	 * To workaround error number=-71 on EP0 for VideoGrabber,
+	 *	 need exclude following.
+	 * FIXME: It is probably safe to remove most of these, as we're
+	 * now avoiding the alternate setting for INDEX_VANC
+	 */
+	if (!dev->board.no_alt_vanc)
 		if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
 			videobuf_stop(&fh->vb_vidq);
 			videobuf_mmap_free(&fh->vb_vidq);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/altera-ci.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/altera-ci.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/altera-ci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/altera-ci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,838 @@
+/*
+ * altera-ci.c
+ *
+ *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
+ *
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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.
+ */
+
+/*
+ * currently cx23885 GPIO's used.
+ * GPIO-0 ~INT in
+ * GPIO-1 TMS out
+ * GPIO-2 ~reset chips out
+ * GPIO-3 to GPIO-10 data/addr for CA in/out
+ * GPIO-11 ~CS out
+ * GPIO-12 AD_RG out
+ * GPIO-13 ~WR out
+ * GPIO-14 ~RD out
+ * GPIO-15 ~RDY in
+ * GPIO-16 TCK out
+ * GPIO-17 TDO in
+ * GPIO-18 TDI out
+ */
+/*
+ *  Bit definitions for MC417_RWD and MC417_OEN registers
+ * bits 31-16
+ * +-----------+
+ * | Reserved  |
+ * +-----------+
+ *   bit 15  bit 14  bit 13 bit 12  bit 11  bit 10  bit 9   bit 8
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |  TDI  |  TDO  |  TCK  |  RDY# |  #RD  |  #WR  | AD_RG |  #CS  |
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ *  bit 7   bit 6   bit 5   bit 4   bit 3   bit 2   bit 1   bit 0
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ * |  DATA7|  DATA6|  DATA5|  DATA4|  DATA3|  DATA2|  DATA1|  DATA0|
+ * +-------+-------+-------+-------+-------+-------+-------+-------+
+ */
+#include <linux/version.h>
+#include <media/videobuf-dma-sg.h>
+#include <media/videobuf-dvb.h>
+#include "altera-ci.h"
+#include "dvb_ca_en50221.h"
+
+/* FPGA regs */
+#define NETUP_CI_INT_CTRL	0x00
+#define NETUP_CI_BUSCTRL2	0x01
+#define NETUP_CI_ADDR0		0x04
+#define NETUP_CI_ADDR1		0x05
+#define NETUP_CI_DATA		0x06
+#define NETUP_CI_BUSCTRL	0x07
+#define NETUP_CI_PID_ADDR0	0x08
+#define NETUP_CI_PID_ADDR1	0x09
+#define NETUP_CI_PID_DATA	0x0a
+#define NETUP_CI_TSA_DIV	0x0c
+#define NETUP_CI_TSB_DIV	0x0d
+#define NETUP_CI_REVISION	0x0f
+
+/* const for ci op */
+#define NETUP_CI_FLG_CTL	1
+#define NETUP_CI_FLG_RD		1
+#define NETUP_CI_FLG_AD		1
+
+static unsigned int ci_dbg;
+module_param(ci_dbg, int, 0644);
+MODULE_PARM_DESC(ci_dbg, "Enable CI debugging");
+
+static unsigned int pid_dbg;
+module_param(pid_dbg, int, 0644);
+MODULE_PARM_DESC(pid_dbg, "Enable PID filtering debugging");
+
+MODULE_DESCRIPTION("altera FPGA CI module");
+MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");
+MODULE_LICENSE("GPL");
+
+#define ci_dbg_print(args...) \
+	do { \
+		if (ci_dbg) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+#define pid_dbg_print(args...) \
+	do { \
+		if (pid_dbg) \
+			printk(KERN_DEBUG args); \
+	} while (0)
+
+struct altera_ci_state;
+struct netup_hw_pid_filter;
+
+struct fpga_internal {
+	void *dev;
+	struct mutex fpga_mutex;/* two CI's on the same fpga */
+	struct netup_hw_pid_filter *pid_filt[2];
+	struct altera_ci_state *state[2];
+	struct work_struct work;
+	int (*fpga_rw) (void *dev, int flag, int data, int rw);
+	int cis_used;
+	int filts_used;
+	int strt_wrk;
+};
+
+/* stores all private variables for communication with CI */
+struct altera_ci_state {
+	struct fpga_internal *internal;
+	struct dvb_ca_en50221 ca;
+	int status;
+	int nr;
+};
+
+/* stores all private variables for hardware pid filtering */
+struct netup_hw_pid_filter {
+	struct fpga_internal *internal;
+	struct dvb_demux *demux;
+	/* save old functions */
+	int (*start_feed)(struct dvb_demux_feed *feed);
+	int (*stop_feed)(struct dvb_demux_feed *feed);
+
+	int status;
+	int nr;
+};
+
+/* internal params node */
+struct fpga_inode {
+	/* pointer for internal params, one for each pair of CI's */
+	struct fpga_internal		*internal;
+	struct fpga_inode		*next_inode;
+};
+
+/* first internal params */
+static struct fpga_inode *fpga_first_inode;
+
+/* find chip by dev */
+static struct fpga_inode *find_inode(void *dev)
+{
+	struct fpga_inode *temp_chip = fpga_first_inode;
+
+	if (temp_chip == NULL)
+		return temp_chip;
+
+	/*
+	 Search for the last fpga CI chip or
+	 find it by dev */
+	while ((temp_chip != NULL) &&
+				(temp_chip->internal->dev != dev))
+		temp_chip = temp_chip->next_inode;
+
+	return temp_chip;
+}
+/* check demux */
+static struct fpga_internal *check_filter(struct fpga_internal *temp_int,
+						void *demux_dev, int filt_nr)
+{
+	if (temp_int == NULL)
+		return NULL;
+
+	if ((temp_int->pid_filt[filt_nr]) == NULL)
+		return NULL;
+
+	if (temp_int->pid_filt[filt_nr]->demux == demux_dev)
+		return temp_int;
+
+	return NULL;
+}
+
+/* find chip by demux */
+static struct fpga_inode *find_dinode(void *demux_dev)
+{
+	struct fpga_inode *temp_chip = fpga_first_inode;
+	struct fpga_internal *temp_int;
+
+	/*
+	 * Search of the last fpga CI chip or
+	 * find it by demux
+	 */
+	while (temp_chip != NULL) {
+		if (temp_chip->internal != NULL) {
+			temp_int = temp_chip->internal;
+			if (check_filter(temp_int, demux_dev, 0))
+				break;
+			if (check_filter(temp_int, demux_dev, 1))
+				break;
+		}
+
+		temp_chip = temp_chip->next_inode;
+	}
+
+	return temp_chip;
+}
+
+/* deallocating chip */
+static void remove_inode(struct fpga_internal *internal)
+{
+	struct fpga_inode *prev_node = fpga_first_inode;
+	struct fpga_inode *del_node = find_inode(internal->dev);
+
+	if (del_node != NULL) {
+		if (del_node == fpga_first_inode) {
+			fpga_first_inode = del_node->next_inode;
+		} else {
+			while (prev_node->next_inode != del_node)
+				prev_node = prev_node->next_inode;
+
+			if (del_node->next_inode == NULL)
+				prev_node->next_inode = NULL;
+			else
+				prev_node->next_inode =
+					prev_node->next_inode->next_inode;
+		}
+
+		kfree(del_node);
+	}
+}
+
+/* allocating new chip */
+static struct fpga_inode *append_internal(struct fpga_internal *internal)
+{
+	struct fpga_inode *new_node = fpga_first_inode;
+
+	if (new_node == NULL) {
+		new_node = kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
+		fpga_first_inode = new_node;
+	} else {
+		while (new_node->next_inode != NULL)
+			new_node = new_node->next_inode;
+
+		new_node->next_inode =
+				kmalloc(sizeof(struct fpga_inode), GFP_KERNEL);
+		if (new_node->next_inode != NULL)
+			new_node = new_node->next_inode;
+		else
+			new_node = NULL;
+	}
+
+	if (new_node != NULL) {
+		new_node->internal = internal;
+		new_node->next_inode = NULL;
+	}
+
+	return new_node;
+}
+
+static int netup_fpga_op_rw(struct fpga_internal *inter, int addr,
+							u8 val, u8 read)
+{
+	inter->fpga_rw(inter->dev, NETUP_CI_FLG_AD, addr, 0);
+	return inter->fpga_rw(inter->dev, 0, val, read);
+}
+
+/* flag - mem/io, read - read/write */
+int altera_ci_op_cam(struct dvb_ca_en50221 *en50221, int slot,
+				u8 flag, u8 read, int addr, u8 val)
+{
+
+	struct altera_ci_state *state = en50221->data;
+	struct fpga_internal *inter = state->internal;
+
+	u8 store;
+	int mem = 0;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	netup_fpga_op_rw(inter, NETUP_CI_ADDR0, ((addr << 1) & 0xfe), 0);
+	netup_fpga_op_rw(inter, NETUP_CI_ADDR1, ((addr >> 7) & 0x7f), 0);
+	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+
+	store &= 0x0f;
+	store |= ((state->nr << 7) | (flag << 6));
+
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, store, 0);
+	mem = netup_fpga_op_rw(inter, NETUP_CI_DATA, val, read);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	ci_dbg_print("%s: %s: addr=[0x%02x], %s=%x\n", __func__,
+			(read) ? "read" : "write", addr,
+			(flag == NETUP_CI_FLG_CTL) ? "ctl" : "mem",
+			(read) ? mem : val);
+
+	return mem;
+}
+
+int altera_ci_read_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr)
+{
+	return altera_ci_op_cam(en50221, slot, 0, NETUP_CI_FLG_RD, addr, 0);
+}
+
+int altera_ci_write_attribute_mem(struct dvb_ca_en50221 *en50221,
+						int slot, int addr, u8 data)
+{
+	return altera_ci_op_cam(en50221, slot, 0, 0, addr, data);
+}
+
+int altera_ci_read_cam_ctl(struct dvb_ca_en50221 *en50221, int slot, u8 addr)
+{
+	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL,
+						NETUP_CI_FLG_RD, addr, 0);
+}
+
+int altera_ci_write_cam_ctl(struct dvb_ca_en50221 *en50221, int slot,
+						u8 addr, u8 data)
+{
+	return altera_ci_op_cam(en50221, slot, NETUP_CI_FLG_CTL, 0, addr, data);
+}
+
+int altera_ci_slot_reset(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct altera_ci_state *state = en50221->data;
+	struct fpga_internal *inter = state->internal;
+	/* reasonable timeout for CI reset is 10 seconds */
+	unsigned long t_out = jiffies + msecs_to_jiffies(9999);
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+				(ret & 0xcf) | (1 << (5 - state->nr)), 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	for (;;) {
+		mdelay(50);
+
+		mutex_lock(&inter->fpga_mutex);
+
+		ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+						0, NETUP_CI_FLG_RD);
+		mutex_unlock(&inter->fpga_mutex);
+
+		if ((ret & (1 << (5 - state->nr))) == 0)
+			break;
+		if (time_after(jiffies, t_out))
+			break;
+	}
+
+
+	ci_dbg_print("%s: %d msecs\n", __func__,
+		jiffies_to_msecs(jiffies + msecs_to_jiffies(9999) - t_out));
+
+	return 0;
+}
+
+int altera_ci_slot_shutdown(struct dvb_ca_en50221 *en50221, int slot)
+{
+	/* not implemented */
+	return 0;
+}
+
+int altera_ci_slot_ts_ctl(struct dvb_ca_en50221 *en50221, int slot)
+{
+	struct altera_ci_state *state = en50221->data;
+	struct fpga_internal *inter = state->internal;
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (0 != slot)
+		return -EINVAL;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL,
+				(ret & 0x0f) | (1 << (3 - state->nr)), 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	return 0;
+}
+
+/* work handler */
+static void netup_read_ci_status(struct work_struct *work)
+{
+	struct fpga_internal *inter =
+			container_of(work, struct fpga_internal, work);
+	int ret;
+
+	ci_dbg_print("%s\n", __func__);
+
+	mutex_lock(&inter->fpga_mutex);
+	/* ack' irq */
+	ret = netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0, NETUP_CI_FLG_RD);
+	ret = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL, 0, NETUP_CI_FLG_RD);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	if (inter->state[1] != NULL) {
+		inter->state[1]->status =
+				((ret & 1) == 0 ?
+				DVB_CA_EN50221_POLL_CAM_PRESENT |
+				DVB_CA_EN50221_POLL_CAM_READY : 0);
+		ci_dbg_print("%s: setting CI[1] status = 0x%x\n",
+				__func__, inter->state[1]->status);
+	};
+
+	if (inter->state[0] != NULL) {
+		inter->state[0]->status =
+				((ret & 2) == 0 ?
+				DVB_CA_EN50221_POLL_CAM_PRESENT |
+				DVB_CA_EN50221_POLL_CAM_READY : 0);
+		ci_dbg_print("%s: setting CI[0] status = 0x%x\n",
+				__func__, inter->state[0]->status);
+	};
+}
+
+/* CI irq handler */
+int altera_ci_irq(void *dev)
+{
+	struct fpga_inode *temp_int = NULL;
+	struct fpga_internal *inter = NULL;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (dev != NULL) {
+		temp_int = find_inode(dev);
+		if (temp_int != NULL) {
+			inter = temp_int->internal;
+			schedule_work(&inter->work);
+		}
+	}
+
+	return 1;
+}
+EXPORT_SYMBOL(altera_ci_irq);
+
+int altera_poll_ci_slot_status(struct dvb_ca_en50221 *en50221, int slot,
+								int open)
+{
+	struct altera_ci_state *state = en50221->data;
+
+	if (0 != slot)
+		return -EINVAL;
+
+	return state->status;
+}
+
+void altera_hw_filt_release(void *main_dev, int filt_nr)
+{
+	struct fpga_inode *temp_int = find_inode(main_dev);
+	struct netup_hw_pid_filter *pid_filt = NULL;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (temp_int != NULL) {
+		pid_filt = temp_int->internal->pid_filt[filt_nr - 1];
+		/* stored old feed controls */
+		pid_filt->demux->start_feed = pid_filt->start_feed;
+		pid_filt->demux->stop_feed = pid_filt->stop_feed;
+
+		if (((--(temp_int->internal->filts_used)) <= 0) &&
+			 ((temp_int->internal->cis_used) <= 0)) {
+
+			ci_dbg_print("%s: Actually removing\n", __func__);
+
+			remove_inode(temp_int->internal);
+			kfree(pid_filt->internal);
+		}
+
+		kfree(pid_filt);
+
+	}
+
+}
+EXPORT_SYMBOL(altera_hw_filt_release);
+
+void altera_ci_release(void *dev, int ci_nr)
+{
+	struct fpga_inode *temp_int = find_inode(dev);
+	struct altera_ci_state *state = NULL;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (temp_int != NULL) {
+		state = temp_int->internal->state[ci_nr - 1];
+		altera_hw_filt_release(dev, ci_nr);
+
+
+		if (((temp_int->internal->filts_used) <= 0) &&
+				((--(temp_int->internal->cis_used)) <= 0)) {
+
+			ci_dbg_print("%s: Actually removing\n", __func__);
+
+			remove_inode(temp_int->internal);
+			kfree(state->internal);
+		}
+
+		if (state != NULL) {
+			if (state->ca.data != NULL)
+				dvb_ca_en50221_release(&state->ca);
+
+			kfree(state);
+		}
+	}
+
+}
+EXPORT_SYMBOL(altera_ci_release);
+
+static void altera_pid_control(struct netup_hw_pid_filter *pid_filt,
+		u16 pid, int onoff)
+{
+	struct fpga_internal *inter = pid_filt->internal;
+	u8 store = 0;
+
+	/* pid 0-0x1f always enabled, don't touch them */
+	if ((pid == 0x2000) || (pid < 0x20))
+		return;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, (pid >> 3) & 0xff, 0);
+	netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
+			((pid >> 11) & 0x03) | (pid_filt->nr << 2), 0);
+
+	store = netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, 0, NETUP_CI_FLG_RD);
+
+	if (onoff)/* 0 - on, 1 - off */
+		store |= (1 << (pid & 7));
+	else
+		store &= ~(1 << (pid & 7));
+
+	netup_fpga_op_rw(inter, NETUP_CI_PID_DATA, store, 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	pid_dbg_print("%s: (%d) set pid: %5d 0x%04x '%s'\n", __func__,
+		pid_filt->nr, pid, pid, onoff ? "off" : "on");
+}
+
+static void altera_toggle_fullts_streaming(struct netup_hw_pid_filter *pid_filt,
+					int filt_nr, int onoff)
+{
+	struct fpga_internal *inter = pid_filt->internal;
+	u8 store = 0;
+	int i;
+
+	pid_dbg_print("%s: pid_filt->nr[%d]  now %s\n", __func__, pid_filt->nr,
+			onoff ? "off" : "on");
+
+	if (onoff)/* 0 - on, 1 - off */
+		store = 0xff;/* ignore pid */
+	else
+		store = 0;/* enable pid */
+
+	mutex_lock(&inter->fpga_mutex);
+
+	for (i = 0; i < 1024; i++) {
+		netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR0, i & 0xff, 0);
+
+		netup_fpga_op_rw(inter, NETUP_CI_PID_ADDR1,
+				((i >> 8) & 0x03) | (pid_filt->nr << 2), 0);
+		/* pid 0-0x1f always enabled */
+		netup_fpga_op_rw(inter, NETUP_CI_PID_DATA,
+				(i > 3 ? store : 0), 0);
+	}
+
+	mutex_unlock(&inter->fpga_mutex);
+}
+
+int altera_pid_feed_control(void *demux_dev, int filt_nr,
+		struct dvb_demux_feed *feed, int onoff)
+{
+	struct fpga_inode *temp_int = find_dinode(demux_dev);
+	struct fpga_internal *inter = temp_int->internal;
+	struct netup_hw_pid_filter *pid_filt = inter->pid_filt[filt_nr - 1];
+
+	altera_pid_control(pid_filt, feed->pid, onoff ? 0 : 1);
+	/* call old feed proc's */
+	if (onoff)
+		pid_filt->start_feed(feed);
+	else
+		pid_filt->stop_feed(feed);
+
+	if (feed->pid == 0x2000)
+		altera_toggle_fullts_streaming(pid_filt, filt_nr,
+						onoff ? 0 : 1);
+
+	return 0;
+}
+EXPORT_SYMBOL(altera_pid_feed_control);
+
+int altera_ci_start_feed(struct dvb_demux_feed *feed, int num)
+{
+	altera_pid_feed_control(feed->demux, num, feed, 1);
+
+	return 0;
+}
+
+int altera_ci_stop_feed(struct dvb_demux_feed *feed, int num)
+{
+	altera_pid_feed_control(feed->demux, num, feed, 0);
+
+	return 0;
+}
+
+int altera_ci_start_feed_1(struct dvb_demux_feed *feed)
+{
+	return altera_ci_start_feed(feed, 1);
+}
+
+int altera_ci_stop_feed_1(struct dvb_demux_feed *feed)
+{
+	return altera_ci_stop_feed(feed, 1);
+}
+
+int altera_ci_start_feed_2(struct dvb_demux_feed *feed)
+{
+	return altera_ci_start_feed(feed, 2);
+}
+
+int altera_ci_stop_feed_2(struct dvb_demux_feed *feed)
+{
+	return altera_ci_stop_feed(feed, 2);
+}
+
+int altera_hw_filt_init(struct altera_ci_config *config, int hw_filt_nr)
+{
+	struct netup_hw_pid_filter *pid_filt = NULL;
+	struct fpga_inode *temp_int = find_inode(config->dev);
+	struct fpga_internal *inter = NULL;
+	int ret = 0;
+
+	pid_filt = kzalloc(sizeof(struct netup_hw_pid_filter), GFP_KERNEL);
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (!pid_filt) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (temp_int != NULL) {
+		inter = temp_int->internal;
+		(inter->filts_used)++;
+		ci_dbg_print("%s: Find Internal Structure!\n", __func__);
+	} else {
+		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
+		if (!inter) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		temp_int = append_internal(inter);
+		inter->filts_used = 1;
+		inter->dev = config->dev;
+		inter->fpga_rw = config->fpga_rw;
+		mutex_init(&inter->fpga_mutex);
+		inter->strt_wrk = 1;
+		ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
+	}
+
+	ci_dbg_print("%s: setting hw pid filter = %p for ci = %d\n", __func__,
+						pid_filt, hw_filt_nr - 1);
+	inter->pid_filt[hw_filt_nr - 1] = pid_filt;
+	pid_filt->demux = config->demux;
+	pid_filt->internal = inter;
+	pid_filt->nr = hw_filt_nr - 1;
+	/* store old feed controls */
+	pid_filt->start_feed = config->demux->start_feed;
+	pid_filt->stop_feed = config->demux->stop_feed;
+	/* replace with new feed controls */
+	if (hw_filt_nr == 1) {
+		pid_filt->demux->start_feed = altera_ci_start_feed_1;
+		pid_filt->demux->stop_feed = altera_ci_stop_feed_1;
+	} else if (hw_filt_nr == 2) {
+		pid_filt->demux->start_feed = altera_ci_start_feed_2;
+		pid_filt->demux->stop_feed = altera_ci_stop_feed_2;
+	}
+
+	altera_toggle_fullts_streaming(pid_filt, 0, 1);
+
+	return 0;
+err:
+	ci_dbg_print("%s: Can't init hardware filter: Error %d\n",
+		     __func__, ret);
+
+	kfree(pid_filt);
+
+	return ret;
+}
+EXPORT_SYMBOL(altera_hw_filt_init);
+
+int altera_ci_init(struct altera_ci_config *config, int ci_nr)
+{
+	struct altera_ci_state *state;
+	struct fpga_inode *temp_int = find_inode(config->dev);
+	struct fpga_internal *inter = NULL;
+	int ret = 0;
+	u8 store = 0;
+
+	state = kzalloc(sizeof(struct altera_ci_state), GFP_KERNEL);
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (!state) {
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	if (temp_int != NULL) {
+		inter = temp_int->internal;
+		(inter->cis_used)++;
+		ci_dbg_print("%s: Find Internal Structure!\n", __func__);
+	} else {
+		inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
+		if (!inter) {
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		temp_int = append_internal(inter);
+		inter->cis_used = 1;
+		inter->dev = config->dev;
+		inter->fpga_rw = config->fpga_rw;
+		mutex_init(&inter->fpga_mutex);
+		inter->strt_wrk = 1;
+		ci_dbg_print("%s: Create New Internal Structure!\n", __func__);
+	}
+
+	ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__,
+						state, ci_nr - 1);
+	inter->state[ci_nr - 1] = state;
+	state->internal = inter;
+	state->nr = ci_nr - 1;
+
+	state->ca.owner = THIS_MODULE;
+	state->ca.read_attribute_mem = altera_ci_read_attribute_mem;
+	state->ca.write_attribute_mem = altera_ci_write_attribute_mem;
+	state->ca.read_cam_control = altera_ci_read_cam_ctl;
+	state->ca.write_cam_control = altera_ci_write_cam_ctl;
+	state->ca.slot_reset = altera_ci_slot_reset;
+	state->ca.slot_shutdown = altera_ci_slot_shutdown;
+	state->ca.slot_ts_enable = altera_ci_slot_ts_ctl;
+	state->ca.poll_slot_status = altera_poll_ci_slot_status;
+	state->ca.data = state;
+
+	ret = dvb_ca_en50221_init(config->adapter,
+				   &state->ca,
+				   /* flags */ 0,
+				   /* n_slots */ 1);
+	if (0 != ret)
+		goto err;
+
+	altera_hw_filt_init(config, ci_nr);
+
+	if (inter->strt_wrk) {
+		INIT_WORK(&inter->work, netup_read_ci_status);
+		inter->strt_wrk = 0;
+	}
+
+	ci_dbg_print("%s: CI initialized!\n", __func__);
+
+	mutex_lock(&inter->fpga_mutex);
+
+	/* Enable div */
+	netup_fpga_op_rw(inter, NETUP_CI_TSA_DIV, 0x0, 0);
+	netup_fpga_op_rw(inter, NETUP_CI_TSB_DIV, 0x0, 0);
+
+	/* enable TS out */
+	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
+	store |= (3 << 4);
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+
+	ret = netup_fpga_op_rw(inter, NETUP_CI_REVISION, 0, NETUP_CI_FLG_RD);
+	/* enable irq */
+	netup_fpga_op_rw(inter, NETUP_CI_INT_CTRL, 0x44, 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	ci_dbg_print("%s: NetUP CI Revision = 0x%x\n", __func__, ret);
+
+	schedule_work(&inter->work);
+
+	return 0;
+err:
+	ci_dbg_print("%s: Cannot initialize CI: Error %d.\n", __func__, ret);
+
+	kfree(state);
+
+	return ret;
+}
+EXPORT_SYMBOL(altera_ci_init);
+
+int altera_ci_tuner_reset(void *dev, int ci_nr)
+{
+	struct fpga_inode *temp_int = find_inode(dev);
+	struct fpga_internal *inter = NULL;
+	u8 store;
+
+	ci_dbg_print("%s\n", __func__);
+
+	if (temp_int == NULL)
+		return -1;
+
+	if (temp_int->internal == NULL)
+		return -1;
+
+	inter = temp_int->internal;
+
+	mutex_lock(&inter->fpga_mutex);
+
+	store = netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, 0, NETUP_CI_FLG_RD);
+	store &= ~(4 << (2 - ci_nr));
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+	msleep(100);
+	store |= (4 << (2 - ci_nr));
+	netup_fpga_op_rw(inter, NETUP_CI_BUSCTRL2, store, 0);
+
+	mutex_unlock(&inter->fpga_mutex);
+
+	return 0;
+}
+EXPORT_SYMBOL(altera_ci_tuner_reset);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/altera-ci.h linux-libre-2.6.39-gnu/drivers/media/video/cx23885/altera-ci.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/altera-ci.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/altera-ci.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * altera-ci.c
+ *
+ *  CI driver in conjunction with NetUp Dual DVB-T/C RF CI card
+ *
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 __ALTERA_CI_H
+#define __ALTERA_CI_H
+
+#define ALT_DATA	0x000000ff
+#define ALT_TDI		0x00008000
+#define ALT_TDO		0x00004000
+#define ALT_TCK		0x00002000
+#define ALT_RDY		0x00001000
+#define ALT_RD		0x00000800
+#define ALT_WR		0x00000400
+#define ALT_AD_RG	0x00000200
+#define ALT_CS		0x00000100
+
+struct altera_ci_config {
+	void *dev;/* main dev, for example cx23885_dev */
+	void *adapter;/* for CI to connect to */
+	struct dvb_demux *demux;/* for hardware PID filter to connect to */
+	int (*fpga_rw) (void *dev, int ad_rg, int val, int rw);
+};
+
+#if defined(CONFIG_MEDIA_ALTERA_CI) || (defined(CONFIG_MEDIA_ALTERA_CI_MODULE) \
+							&& defined(MODULE))
+
+extern int altera_ci_init(struct altera_ci_config *config, int ci_nr);
+extern void altera_ci_release(void *dev, int ci_nr);
+extern int altera_ci_irq(void *dev);
+extern int altera_ci_tuner_reset(void *dev, int ci_nr);
+
+#else
+
+static inline int altera_ci_init(struct altera_ci_config *config, int ci_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline void altera_ci_release(void *dev, int ci_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int altera_ci_irq(void *dev)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline int altera_ci_tuner_reset(void *dev, int ci_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+#endif
+#if 0
+static inline int altera_hw_filt_init(struct altera_ci_config *config,
+							int hw_filt_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+static inline void altera_hw_filt_release(void *dev, int filt_nr)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+}
+
+static inline int altera_pid_feed_control(void *dev, int filt_nr,
+		struct dvb_demux_feed *dvbdmxfeed, int onoff)
+{
+	printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+	return 0;
+}
+
+#endif /* CONFIG_MEDIA_ALTERA_CI */
+
+#endif /* __ALTERA_CI_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cimax2.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cimax2.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cimax2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cimax2.c	2011-05-19 00:06:34.000000000 -0400
@@ -449,7 +449,7 @@
 		0x04, /* ack active low */
 		0x00, /* LOCK = 0 */
 		0x33, /* serial mode, rising in, rising out, MSB first*/
-		0x31, /* syncronization */
+		0x31, /* synchronization */
 	};
 	int ret;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-cards.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-cards.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-cards.c	2012-03-24 03:29:09.000000000 -0400
@@ -24,10 +24,14 @@
 #include <linux/pci.h>
 #include <linux/delay.h>
 #include <media/cx25840.h>
+#include <linux/firmware.h>
+#include <staging/altera.h>
 
 #include "cx23885.h"
 #include "tuner-xc2028.h"
 #include "netup-init.h"
+#include "altera-ci.h"
+#include "xc5000.h"
 #include "cx23888-ir.h"
 
 static unsigned int enable_885_ir;
@@ -90,6 +94,7 @@
 		.portc		= CX23885_MPEG_DVB,
 		.tuner_type	= TUNER_PHILIPS_TDA8290,
 		.tuner_addr	= 0x42, /* 0x84 >> 1 */
+		.tuner_bus	= 1,
 		.input          = {{
 			.type   = CX23885_VMUX_TELEVISION,
 			.vmux   =	CX25840_VIN7_CH3 |
@@ -187,7 +192,7 @@
 		.portb		= CX23885_MPEG_DVB,
 	},
 	[CX23885_BOARD_NETUP_DUAL_DVBS2_CI] = {
-		.cimax		= 1,
+		.ci_type	= 1,
 		.name		= "NetUP Dual DVB-S2 CI",
 		.portb		= CX23885_MPEG_DVB,
 		.portc		= CX23885_MPEG_DVB,
@@ -212,6 +217,7 @@
 		.name		= "Mygica X8506 DMB-TH",
 		.tuner_type = TUNER_XC5000,
 		.tuner_addr = 0x61,
+		.tuner_bus	= 1,
 		.porta		= CX23885_ANALOG_VIDEO,
 		.portb		= CX23885_MPEG_DVB,
 		.input		= {
@@ -241,6 +247,7 @@
 		.name		= "Magic-Pro ProHDTV Extreme 2",
 		.tuner_type = TUNER_XC5000,
 		.tuner_addr = 0x61,
+		.tuner_bus	= 1,
 		.porta		= CX23885_ANALOG_VIDEO,
 		.portb		= CX23885_MPEG_DVB,
 		.input		= {
@@ -289,6 +296,7 @@
 		.porta          = CX23885_ANALOG_VIDEO,
 		.tuner_type     = TUNER_XC2028,
 		.tuner_addr     = 0x61,
+		.tuner_bus	= 1,
 		.input          = {{
 			.type   = CX23885_VMUX_TELEVISION,
 			.vmux   = CX25840_VIN2_CH1 |
@@ -313,6 +321,7 @@
 		.name		= "GoTView X5 3D Hybrid",
 		.tuner_type	= TUNER_XC5000,
 		.tuner_addr	= 0x64,
+		.tuner_bus	= 1,
 		.porta		= CX23885_ANALOG_VIDEO,
 		.portb		= CX23885_MPEG_DVB,
 		.input          = {{
@@ -329,6 +338,21 @@
 				  CX25840_SVIDEO_CHROMA4,
 		} },
 	},
+	[CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF] = {
+		.ci_type	= 2,
+		.name		= "NetUP Dual DVB-T/C-CI RF",
+		.porta		= CX23885_ANALOG_VIDEO,
+		.portb		= CX23885_MPEG_DVB,
+		.portc		= CX23885_MPEG_DVB,
+		.num_fds_portb	= 2,
+		.num_fds_portc	= 2,
+		.tuner_type	= TUNER_XC5000,
+		.tuner_addr	= 0x64,
+		.input          = { {
+				.type   = CX23885_VMUX_TELEVISION,
+				.vmux   = CX25840_COMPOSITE1,
+		} },
+	},
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
 
@@ -520,6 +544,10 @@
 		.subvendor = 0x5654,
 		.subdevice = 0x2390,
 		.card      = CX23885_BOARD_GOTVIEW_X5_3D_HYBRID,
+	}, {
+		.subvendor = 0x1b55,
+		.subdevice = 0xe2e4,
+		.card      = CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF,
 	},
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -740,6 +768,9 @@
 		/* Tuner Reset Command */
 		bitmask = 0x02;
 		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		altera_ci_tuner_reset(dev, port->nr);
+		break;
 	}
 
 	if (bitmask) {
@@ -998,6 +1029,33 @@
 	case CX23885_BOARD_GOTVIEW_X5_3D_HYBRID:
 		cx_set(GP0_IO, 0x00010001); /* Bring the part out of reset */
 		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		/* GPIO-0 ~INT in
+		   GPIO-1 TMS out
+		   GPIO-2 ~reset chips out
+		   GPIO-3 to GPIO-10 data/addr for CA in/out
+		   GPIO-11 ~CS out
+		   GPIO-12 ADDR out
+		   GPIO-13 ~WR out
+		   GPIO-14 ~RD out
+		   GPIO-15 ~RDY in
+		   GPIO-16 TCK out
+		   GPIO-17 TDO in
+		   GPIO-18 TDI out
+		 */
+		cx_set(GP0_IO, 0x00060000); /* GPIO-1,2 as out */
+		/* GPIO-0 as INT, reset & TMS low */
+		cx_clear(GP0_IO, 0x00010006);
+		mdelay(100);/* reset delay */
+		cx_set(GP0_IO, 0x00000004); /* reset high */
+		cx_write(MC417_CTL, 0x00000037);/* enable GPIO-3..18 pins */
+		/* GPIO-17 is TDO in, GPIO-15 is ~RDY in, rest is out */
+		cx_write(MC417_OEN, 0x00005000);
+		/* ~RD, ~WR high; ADDR low; ~CS high */
+		cx_write(MC417_RWD, 0x00000d00);
+		/* enable irq */
+		cx_write(GPIO_ISM, 0x00000000);/* INTERRUPTS active low*/
+		break;
 	}
 }
 
@@ -1113,6 +1171,31 @@
 	}
 }
 
+int netup_jtag_io(void *device, int tms, int tdi, int read_tdo)
+{
+	int data;
+	int tdo = 0;
+	struct cx23885_dev *dev = (struct cx23885_dev *)device;
+	/*TMS*/
+	data = ((cx_read(GP0_IO)) & (~0x00000002));
+	data |= (tms ? 0x00020002 : 0x00020000);
+	cx_write(GP0_IO, data);
+
+	/*TDI*/
+	data = ((cx_read(MC417_RWD)) & (~0x0000a000));
+	data |= (tdi ? 0x00008000 : 0);
+	cx_write(MC417_RWD, data);
+	if (read_tdo)
+		tdo = (data & 0x00004000) ? 1 : 0; /*TDO*/
+
+	cx_write(MC417_RWD, data | 0x00002000);
+	udelay(1);
+	/*TCK*/
+	cx_write(MC417_RWD, data);
+
+	return tdo;
+}
+
 void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
 {
 	switch (dev->board) {
@@ -1212,6 +1295,7 @@
 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
 		break;
 	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
 		ts1->gen_ctrl_val  = 0xc; /* Serial bus + punctured clock */
 		ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
 		ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
@@ -1271,6 +1355,7 @@
 	case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E650F:
 	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
 	case CX23885_BOARD_COMPRO_VIDEOMATE_E800:
 	case CX23885_BOARD_HAUPPAUGE_HVR1850:
 	case CX23885_BOARD_MYGICA_X8506:
@@ -1293,6 +1378,29 @@
 	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
 		netup_initialize(dev);
 		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+		int ret;
+		const struct firmware *fw;
+		const char *filename = "/*(DEBLOBBED)*/";
+		char *action = "configure";
+		struct altera_config netup_config = {
+			.dev = dev,
+			.action = action,
+			.jtag_io = netup_jtag_io,
+		};
+
+		netup_initialize(dev);
+
+		ret = reject_firmware(&fw, filename, &dev->pci->dev);
+		if (ret != 0)
+			printk(KERN_ERR "did not find the firmware file. (%s) "
+			"Please see linux/Documentation/dvb/ for more details "
+			"on firmware-problems.", filename);
+		else
+			altera_init(&netup_config, fw);
+
+		break;
+	}
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-core.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,9 +29,11 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <asm/div64.h>
+#include <linux/firmware.h>
 
 #include "cx23885.h"
 #include "cimax2.h"
+#include "altera-ci.h"
 #include "cx23888-ir.h"
 #include "cx23885-ir.h"
 #include "cx23885-av.h"
@@ -902,8 +904,6 @@
 	dev->pci_bus  = dev->pci->bus->number;
 	dev->pci_slot = PCI_SLOT(dev->pci->devfn);
 	cx23885_irq_add(dev, 0x001f00);
-	if (cx23885_boards[dev->board].cimax > 0)
-		cx23885_irq_add(dev, 0x01800000); /* for CiMaxes */
 
 	/* External Master 1 Bus */
 	dev->i2c_bus[0].nr = 0;
@@ -970,11 +970,12 @@
 	/* Assume some sensible defaults */
 	dev->tuner_type = cx23885_boards[dev->board].tuner_type;
 	dev->tuner_addr = cx23885_boards[dev->board].tuner_addr;
+	dev->tuner_bus = cx23885_boards[dev->board].tuner_bus;
 	dev->radio_type = cx23885_boards[dev->board].radio_type;
 	dev->radio_addr = cx23885_boards[dev->board].radio_addr;
 
-	dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x\n",
-		__func__, dev->tuner_type, dev->tuner_addr);
+	dprintk(1, "%s() tuner_type = 0x%x tuner_addr = 0x%x tuner_bus = %d\n",
+		__func__, dev->tuner_type, dev->tuner_addr, dev->tuner_bus);
 	dprintk(1, "%s() radio_type = 0x%x radio_addr = 0x%x\n",
 		__func__, dev->radio_type, dev->radio_addr);
 
@@ -1004,6 +1005,9 @@
 	}
 
 	if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB) {
+		if (cx23885_boards[dev->board].num_fds_portb)
+			dev->ts1.num_frontends =
+				cx23885_boards[dev->board].num_fds_portb;
 		if (cx23885_dvb_register(&dev->ts1) < 0) {
 			printk(KERN_ERR "%s() Failed to register dvb adapters on VID_B\n",
 			       __func__);
@@ -1018,6 +1022,9 @@
 	}
 
 	if (cx23885_boards[dev->board].portc == CX23885_MPEG_DVB) {
+		if (cx23885_boards[dev->board].num_fds_portc)
+			dev->ts2.num_frontends =
+				cx23885_boards[dev->board].num_fds_portc;
 		if (cx23885_dvb_register(&dev->ts2) < 0) {
 			printk(KERN_ERR
 				"%s() Failed to register dvb on VID_C\n",
@@ -1034,6 +1041,10 @@
 
 	cx23885_dev_checkrevision(dev);
 
+	/* disable MSI for NetUP cards, otherwise CI is not working */
+	if (cx23885_boards[dev->board].ci_type > 0)
+		cx_clear(RDR_RDRCTL1, 1 << 8);
+
 	return 0;
 }
 
@@ -1822,14 +1833,13 @@
 				PCI_MSK_IR);
 	}
 
-	if (cx23885_boards[dev->board].cimax > 0 &&
-		((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 (cx23885_boards[dev->board].ci_type == 1 &&
+			(pci_status & (PCI_MSK_GPIO1 | PCI_MSK_GPIO0)))
+		handled += netup_ci_slot_status(dev, pci_status);
 
-	}
+	if (cx23885_boards[dev->board].ci_type == 2 &&
+			(pci_status & PCI_MSK_GPIO0))
+		handled += altera_ci_irq(dev);
 
 	if (ts1_status) {
 		if (cx23885_boards[dev->board].portb == CX23885_MPEG_DVB)
@@ -2064,7 +2074,10 @@
 
 	switch (dev->board) {
 	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
-		cx23885_irq_add_enable(dev, 0x01800000); /* for NetUP */
+		cx23885_irq_add_enable(dev, PCI_MSK_GPIO1 | PCI_MSK_GPIO0);
+		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		cx23885_irq_add_enable(dev, PCI_MSK_GPIO0);
 		break;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-dvb.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-dvb.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-dvb.c	2012-03-24 03:26:51.000000000 -0400
@@ -58,6 +58,8 @@
 #include "atbm8830.h"
 #include "ds3000.h"
 #include "cx23885-f300.h"
+#include "altera-ci.h"
+#include "stv0367.h"
 
 static unsigned int debug;
 
@@ -108,6 +110,22 @@
 	cx23885_free_buffer(q, (struct cx23885_buffer *)vb);
 }
 
+static void cx23885_dvb_gate_ctrl(struct cx23885_tsport  *port, int open)
+{
+	struct videobuf_dvb_frontends *f;
+	struct videobuf_dvb_frontend *fe;
+
+	f = &port->frontends;
+
+	if (f->gate <= 1) /* undefined or fe0 */
+		fe = videobuf_dvb_get_frontend(f, 1);
+	else
+		fe = videobuf_dvb_get_frontend(f, f->gate);
+
+	if (fe && fe->dvb.frontend && fe->dvb.frontend->ops.i2c_gate_ctrl)
+		fe->dvb.frontend->ops.i2c_gate_ctrl(fe->dvb.frontend, open);
+}
+
 static struct videobuf_queue_ops dvb_qops = {
 	.buf_setup    = dvb_buf_setup,
 	.buf_prepare  = dvb_buf_prepare,
@@ -570,12 +588,84 @@
 	.i2c_address = 0x60,
 	.osc_clk = 20
 };
+static struct stv0367_config netup_stv0367_config[] = {
+	{
+		.demod_address = 0x1c,
+		.xtal = 27000000,
+		.if_khz = 4500,
+		.if_iq_mode = 0,
+		.ts_mode = 1,
+		.clk_pol = 0,
+	}, {
+		.demod_address = 0x1d,
+		.xtal = 27000000,
+		.if_khz = 4500,
+		.if_iq_mode = 0,
+		.ts_mode = 1,
+		.clk_pol = 0,
+	},
+};
+
+static struct xc5000_config netup_xc5000_config[] = {
+	{
+		.i2c_address = 0x61,
+		.if_khz = 4500,
+	}, {
+		.i2c_address = 0x64,
+		.if_khz = 4500,
+	},
+};
+
+int netup_altera_fpga_rw(void *device, int flag, int data, int read)
+{
+	struct cx23885_dev *dev = (struct cx23885_dev *)device;
+	unsigned long timeout = jiffies + msecs_to_jiffies(1);
+	uint32_t mem = 0;
+
+	mem = cx_read(MC417_RWD);
+	if (read)
+		cx_set(MC417_OEN, ALT_DATA);
+	else {
+		cx_clear(MC417_OEN, ALT_DATA);/* D0-D7 out */
+		mem &= ~ALT_DATA;
+		mem |= (data & ALT_DATA);
+	}
+
+	if (flag)
+		mem |= ALT_AD_RG;
+	else
+		mem &= ~ALT_AD_RG;
+
+	mem &= ~ALT_CS;
+	if (read)
+		mem = (mem & ~ALT_RD) | ALT_WR;
+	else
+		mem = (mem & ~ALT_WR) | ALT_RD;
+
+	cx_write(MC417_RWD, mem);  /* start RW cycle */
+
+	for (;;) {
+		mem = cx_read(MC417_RWD);
+		if ((mem & ALT_RDY) == 0)
+			break;
+		if (time_after(jiffies, timeout))
+			break;
+		udelay(1);
+	}
+
+	cx_set(MC417_RWD, ALT_RD | ALT_WR | ALT_CS);
+	if (read)
+		return mem & ALT_DATA;
+
+	return 0;
+};
 
 static int dvb_register(struct cx23885_tsport *port)
 {
 	struct cx23885_dev *dev = port->dev;
 	struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
-	struct videobuf_dvb_frontend *fe0;
+	struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
+	int mfe_shared = 0; /* bus not shared by default */
 	int ret;
 
 	/* Get the first frontend */
@@ -586,6 +676,12 @@
 	/* init struct videobuf_dvb */
 	fe0->dvb.name = dev->name;
 
+	/* multi-frontend gate control is undefined or defaults to fe0 */
+	port->frontends.gate = 0;
+
+	/* Sets the gate control callback to be used by i2c command calls */
+	port->gate_ctrl = cx23885_dvb_gate_ctrl;
+
 	/* init frontend */
 	switch (dev->board) {
 	case CX23885_BOARD_HAUPPAUGE_HVR1250:
@@ -966,20 +1062,64 @@
 			break;
 		}
 		break;
-
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		i2c_bus = &dev->i2c_bus[0];
+		mfe_shared = 1;/* MFE */
+		port->frontends.gate = 0;/* not clear for me yet */
+		/* ports B, C */
+		/* MFE frontend 1 DVB-T */
+		fe0->dvb.frontend = dvb_attach(stv0367ter_attach,
+					&netup_stv0367_config[port->nr - 1],
+					&i2c_bus->i2c_adap);
+		if (fe0->dvb.frontend != NULL) {
+			if (NULL == dvb_attach(xc5000_attach,
+					fe0->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&netup_xc5000_config[port->nr - 1]))
+				goto frontend_detach;
+			/* load xc5000 firmware */
+			fe0->dvb.frontend->ops.tuner_ops.init(fe0->dvb.frontend);
+		}
+		/* MFE frontend 2 */
+		fe1 = videobuf_dvb_get_frontend(&port->frontends, 2);
+		if (fe1 == NULL)
+			goto frontend_detach;
+		/* DVB-C init */
+		fe1->dvb.frontend = dvb_attach(stv0367cab_attach,
+					&netup_stv0367_config[port->nr - 1],
+					&i2c_bus->i2c_adap);
+		if (fe1->dvb.frontend != NULL) {
+			fe1->dvb.frontend->id = 1;
+			if (NULL == dvb_attach(xc5000_attach,
+					fe1->dvb.frontend,
+					&i2c_bus->i2c_adap,
+					&netup_xc5000_config[port->nr - 1]))
+				goto frontend_detach;
+		}
+		break;
 	default:
 		printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
 			" isn't supported yet\n",
 		       dev->name);
 		break;
 	}
-	if (NULL == fe0->dvb.frontend) {
+
+	if ((NULL == fe0->dvb.frontend) || (fe1 && NULL == fe1->dvb.frontend)) {
 		printk(KERN_ERR "%s: frontend initialization failed\n",
-			dev->name);
-		return -1;
+		       dev->name);
+		goto frontend_detach;
 	}
+
 	/* define general-purpose callback pointer */
 	fe0->dvb.frontend->callback = cx23885_tuner_callback;
+	if (fe1)
+		fe1->dvb.frontend->callback = cx23885_tuner_callback;
+#if 0
+	/* Ensure all frontends negotiate bus access */
+	fe0->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
+	if (fe1)
+		fe1->dvb.frontend->ops.ts_bus_ctrl = cx23885_dvb_bus_ctrl;
+#endif
 
 	/* Put the analog decoder in standby to keep it quiet */
 	call_all(dev, core, s_power, 0);
@@ -989,10 +1129,10 @@
 
 	/* register everything */
 	ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
-					&dev->pci->dev, adapter_nr, 0,
+					&dev->pci->dev, adapter_nr, mfe_shared,
 					cx23885_dvb_fe_ioctl_override);
 	if (ret)
-		return ret;
+		goto frontend_detach;
 
 	/* init CI & MAC */
 	switch (dev->board) {
@@ -1008,6 +1148,17 @@
 		netup_ci_init(port);
 		break;
 		}
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF: {
+		struct altera_ci_config netup_ci_cfg = {
+			.dev = dev,/* magic number to identify*/
+			.adapter = &port->frontends.adapter,/* for CI */
+			.demux = &fe0->dvb.demux,/* for hw pid filter */
+			.fpga_rw = netup_altera_fpga_rw,
+		};
+
+		altera_ci_init(&netup_ci_cfg, port->nr);
+		break;
+		}
 	case CX23885_BOARD_TEVII_S470: {
 		u8 eeprom[256]; /* 24C02 i2c eeprom */
 
@@ -1024,6 +1175,11 @@
 	}
 
 	return ret;
+
+frontend_detach:
+	port->gate_ctrl = NULL;
+	videobuf_dvb_dealloc_frontends(&port->frontends);
+	return -EINVAL;
 }
 
 int cx23885_dvb_register(struct cx23885_tsport *port)
@@ -1100,8 +1256,13 @@
 	case CX23885_BOARD_NETUP_DUAL_DVBS2_CI:
 		netup_ci_exit(port);
 		break;
+	case CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF:
+		altera_ci_release(port->dev, port->nr);
+		break;
 	}
 
+	port->gate_ctrl = NULL;
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885.h linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885.h	2011-05-19 00:06:34.000000000 -0400
@@ -85,6 +85,7 @@
 #define CX23885_BOARD_MYGICA_X8558PRO          27
 #define CX23885_BOARD_LEADTEK_WINFAST_PXTV1200 28
 #define CX23885_BOARD_GOTVIEW_X5_3D_HYBRID     29
+#define CX23885_BOARD_NETUP_DUAL_DVB_T_C_CI_RF 30
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
@@ -204,14 +205,16 @@
 struct cx23885_board {
 	char                    *name;
 	port_t			porta, portb, portc;
+	int		num_fds_portb, num_fds_portc;
 	unsigned int		tuner_type;
 	unsigned int		radio_type;
 	unsigned char		tuner_addr;
 	unsigned char		radio_addr;
+	unsigned int		tuner_bus;
 
 	/* Vendors can and do run the PCIe bridge at different
 	 * clock rates, driven physically by crystals on the PCBs.
-	 * The core has to accomodate this. This allows the user
+	 * The core has to accommodate this. This allows the user
 	 * to add new boards with new frequencys. The value is
 	 * expressed in Hz.
 	 *
@@ -220,7 +223,7 @@
 	 */
 	u32			clk_freq;
 	struct cx23885_input    input[MAX_CX23885_INPUT];
-	int			cimax; /* for NetUP */
+	int			ci_type; /* for NetUP */
 };
 
 struct cx23885_subid {
@@ -303,6 +306,7 @@
 
 	/* Allow a single tsport to have multiple frontends */
 	u32                        num_frontends;
+	void                (*gate_ctrl)(struct cx23885_tsport *port, int open);
 	void                       *port_priv;
 };
 
@@ -362,6 +366,7 @@
 	v4l2_std_id                tvnorm;
 	unsigned int               tuner_type;
 	unsigned char              tuner_addr;
+	unsigned int               tuner_bus;
 	unsigned int               radio_type;
 	unsigned char              radio_addr;
 	unsigned int               has_radio;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-input.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-input.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-input.c	2011-05-19 00:06:34.000000000 -0400
@@ -264,7 +264,7 @@
 		driver_type = RC_DRIVER_IR_RAW;
 		allowed_protos = RC_TYPE_ALL;
 		/* The grey Hauppauge RC-5 remote */
-		rc_map = RC_MAP_RC5_HAUPPAUGE_NEW;
+		rc_map = RC_MAP_HAUPPAUGE;
 		break;
 	case CX23885_BOARD_TEVII_S470:
 		/* Integrated CX23885 IR controller */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-reg.h linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-reg.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -292,6 +292,7 @@
 #define RDR_CFG0	0x00050000
 #define RDR_CFG1	0x00050004
 #define RDR_CFG2	0x00050008
+#define RDR_RDRCTL1	0x0005030c
 #define RDR_TLCTL0	0x00050318
 
 /* APB DMAC Current Buffer Pointer */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-video.c linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/cx23885-video.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/cx23885-video.c	2012-03-24 03:26:51.000000000 -0400
@@ -1468,16 +1468,17 @@
 
 	cx23885_irq_add_enable(dev, 0x01);
 
-	if (TUNER_ABSENT != dev->tuner_type) {
+	if ((TUNER_ABSENT != dev->tuner_type) &&
+			((dev->tuner_bus == 0) || (dev->tuner_bus == 1))) {
 		struct v4l2_subdev *sd = NULL;
 
 		if (dev->tuner_addr)
 			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-				&dev->i2c_bus[1].i2c_adap,
+				&dev->i2c_bus[dev->tuner_bus].i2c_adap,
 				"tuner", dev->tuner_addr, NULL);
 		else
 			sd = v4l2_i2c_new_subdev(&dev->v4l2_dev,
-				&dev->i2c_bus[1].i2c_adap,
+				&dev->i2c_bus[dev->tuner_bus].i2c_adap,
 				"tuner", 0, v4l2_i2c_tuner_addrs(ADDRS_TV));
 		if (sd) {
 			struct tuner_setup tun_setup;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/Kconfig linux-libre-2.6.39-gnu/drivers/media/video/cx23885/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,7 @@
 config VIDEO_CX23885
 	tristate "Conexant cx23885 (2388x successor) support"
-	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT
+	depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
+	select SND_PCM
 	select I2C_ALGOBIT
 	select VIDEO_BTCX
 	select VIDEO_TUNER
@@ -21,6 +22,7 @@
 	select DVB_CX24116 if !DVB_FE_CUSTOMISE
 	select DVB_STV0900 if !DVB_FE_CUSTOMISE
 	select DVB_DS3000 if !DVB_FE_CUSTOMISE
+	select DVB_STV0367 if !DVB_FE_CUSTOMISE
 	select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
 	select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
@@ -33,3 +35,12 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called cx23885
 
+config MEDIA_ALTERA_CI
+	tristate "Altera FPGA based CI module"
+	depends on VIDEO_CX23885 && DVB_CORE
+	select STAPL_ALTERA
+	---help---
+	  An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called altera-ci
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx23885/Makefile linux-libre-2.6.39-gnu/drivers/media/video/cx23885/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/video/cx23885/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx23885/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,7 @@
 		    cx23885-f300.o
 
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
+obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
 
 EXTRA_CFLAGS += -Idrivers/media/video
 EXTRA_CFLAGS += -Idrivers/media/common/tuners
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx25840/cx25840-core.c linux-libre-2.6.39-gnu/drivers/media/video/cx25840/cx25840-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx25840/cx25840-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx25840/cx25840-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  *
  * Copyright (C) 2004 Ulf Eklund
  *
- * Based on the saa7115 driver and on the first verison of Chris Kennedy's
+ * Based on the saa7115 driver and on the first version of Chris Kennedy's
  * cx25840 driver.
  *
  * Changes by Tyler Trafford <tatrafford@comcast.net>
@@ -445,7 +445,7 @@
 	cx25840_write(client, 0x918, 0xa0);
 	cx25840_write(client, 0x919, 0x01);
 
-	/* stereo prefered */
+	/* stereo preferred */
 	cx25840_write(client, 0x809, 0x04);
 	/* AC97 shift */
 	cx25840_write(client, 0x8cf, 0x0f);
@@ -546,7 +546,7 @@
 	 * Aux PLL
 	 * Initial setup for audio sample clock:
 	 * 48 ksps, 16 bits/sample, x160 multiplier = 122.88 MHz
-	 * Intial I2S output/master clock(?):
+	 * Initial I2S output/master clock(?):
 	 * 48 ksps, 16 bits/sample, x16 multiplier = 12.288 MHz
 	 */
 	switch (state->id) {
@@ -903,7 +903,7 @@
 	} else if (std & V4L2_STD_PAL) {
 		/* Autodetect audio standard and audio system */
 		cx25840_write(client, 0x808, 0xff);
-		/* Since system PAL-L is pretty much non-existant and
+		/* Since system PAL-L is pretty much non-existent and
 		   not used by any public broadcast network, force
 		   6.5 MHz carrier to be interpreted as System DK,
 		   this avoids DK audio detection instability */
@@ -1851,7 +1851,7 @@
 			ret = V4L2_IDENT_CX23885_AV;
 		} else {
 			/* CX23887 has a broken DIF, but the registers
-			 * appear valid (but unsed), good enough to detect. */
+			 * appear valid (but unused), good enough to detect. */
 			ret = V4L2_IDENT_CX23887_AV;
 		}
 	} else if (cx25840_read4(client, 0x300) & 0x0fffffff) {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-alsa.c linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-alsa.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-alsa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-alsa.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 #include <sound/control.h>
 #include <sound/initval.h>
 #include <sound/tlv.h>
+#include <media/wm8775.h>
 
 #include "cx88.h"
 #include "cx88-reg.h"
@@ -577,6 +578,35 @@
 	return 0;
 }
 
+static void snd_cx88_wm8775_volume_put(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	struct v4l2_control client_ctl;
+	int left = value->value.integer.value[0];
+	int right = value->value.integer.value[1];
+	int v, b;
+
+	memset(&client_ctl, 0, sizeof(client_ctl));
+
+	/* Pass volume & balance onto any WM8775 */
+	if (left >= right) {
+		v = left << 10;
+		b = left ? (0x8000 * right) / left : 0x8000;
+	} else {
+		v = right << 10;
+		b = right ? 0xffff - (0x8000 * left) / right : 0x8000;
+	}
+	client_ctl.value = v;
+	client_ctl.id = V4L2_CID_AUDIO_VOLUME;
+	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+
+	client_ctl.value = b;
+	client_ctl.id = V4L2_CID_AUDIO_BALANCE;
+	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+}
+
 /* OK - TODO: test it */
 static int snd_cx88_volume_put(struct snd_kcontrol *kcontrol,
 			       struct snd_ctl_elem_value *value)
@@ -587,25 +617,28 @@
 	int changed = 0;
 	u32 old;
 
+	if (core->board.audio_chip == V4L2_IDENT_WM8775)
+		snd_cx88_wm8775_volume_put(kcontrol, value);
+
 	left = value->value.integer.value[0] & 0x3f;
 	right = value->value.integer.value[1] & 0x3f;
 	b = right - left;
 	if (b < 0) {
-	    v = 0x3f - left;
-	    b = (-b) | 0x40;
+		v = 0x3f - left;
+		b = (-b) | 0x40;
 	} else {
-	    v = 0x3f - right;
+		v = 0x3f - right;
 	}
 	/* Do we really know this will always be called with IRQs on? */
 	spin_lock_irq(&chip->reg_lock);
 	old = cx_read(AUD_VOL_CTL);
 	if (v != (old & 0x3f)) {
-	    cx_write(AUD_VOL_CTL, (old & ~0x3f) | v);
-	    changed = 1;
+		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, (old & ~0x3f) | v);
+		changed = 1;
 	}
-	if (cx_read(AUD_BAL_CTL) != b) {
-	    cx_write(AUD_BAL_CTL, b);
-	    changed = 1;
+	if ((cx_read(AUD_BAL_CTL) & 0x7f) != b) {
+		cx_write(AUD_BAL_CTL, b);
+		changed = 1;
 	}
 	spin_unlock_irq(&chip->reg_lock);
 
@@ -618,7 +651,7 @@
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
 	.access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
 		  SNDRV_CTL_ELEM_ACCESS_TLV_READ,
-	.name = "Playback Volume",
+	.name = "Analog-TV Volume",
 	.info = snd_cx88_volume_info,
 	.get = snd_cx88_volume_get,
 	.put = snd_cx88_volume_put,
@@ -649,7 +682,17 @@
 	vol = cx_read(AUD_VOL_CTL);
 	if (value->value.integer.value[0] != !(vol & bit)) {
 		vol ^= bit;
-		cx_write(AUD_VOL_CTL, vol);
+		cx_swrite(SHADOW_AUD_VOL_CTL, AUD_VOL_CTL, vol);
+		/* Pass mute onto any WM8775 */
+		if ((core->board.audio_chip == V4L2_IDENT_WM8775) &&
+		    ((1<<6) == bit)) {
+			struct v4l2_control client_ctl;
+
+			memset(&client_ctl, 0, sizeof(client_ctl));
+			client_ctl.value = 0 != (vol & bit);
+			client_ctl.id = V4L2_CID_AUDIO_MUTE;
+			call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+		}
 		ret = 1;
 	}
 	spin_unlock_irq(&chip->reg_lock);
@@ -658,7 +701,7 @@
 
 static const struct snd_kcontrol_new snd_cx88_dac_switch = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Playback Switch",
+	.name = "Audio-Out Switch",
 	.info = snd_ctl_boolean_mono_info,
 	.get = snd_cx88_switch_get,
 	.put = snd_cx88_switch_put,
@@ -667,13 +710,51 @@
 
 static const struct snd_kcontrol_new snd_cx88_source_switch = {
 	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
-	.name = "Capture Switch",
+	.name = "Analog-TV Switch",
 	.info = snd_ctl_boolean_mono_info,
 	.get = snd_cx88_switch_get,
 	.put = snd_cx88_switch_put,
 	.private_value = (1<<6),
 };
 
+static int snd_cx88_alc_get(struct snd_kcontrol *kcontrol,
+			       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	struct v4l2_control client_ctl;
+
+	memset(&client_ctl, 0, sizeof(client_ctl));
+	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
+	call_hw(core, WM8775_GID, core, g_ctrl, &client_ctl);
+	value->value.integer.value[0] = client_ctl.value ? 1 : 0;
+
+	return 0;
+}
+
+static int snd_cx88_alc_put(struct snd_kcontrol *kcontrol,
+				       struct snd_ctl_elem_value *value)
+{
+	snd_cx88_card_t *chip = snd_kcontrol_chip(kcontrol);
+	struct cx88_core *core = chip->core;
+	struct v4l2_control client_ctl;
+
+	memset(&client_ctl, 0, sizeof(client_ctl));
+	client_ctl.value = 0 != value->value.integer.value[0];
+	client_ctl.id = V4L2_CID_AUDIO_LOUDNESS;
+	call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+
+	return 0;
+}
+
+static struct snd_kcontrol_new snd_cx88_alc_switch = {
+	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+	.name = "Line-In ALC Switch",
+	.info = snd_ctl_boolean_mono_info,
+	.get = snd_cx88_alc_get,
+	.put = snd_cx88_alc_put,
+};
+
 /****************************************************************************
 			Basic Flow for Sound Devices
  ****************************************************************************/
@@ -724,7 +805,8 @@
 static int devno;
 static int __devinit snd_cx88_create(struct snd_card *card,
 				     struct pci_dev *pci,
-				     snd_cx88_card_t **rchip)
+				     snd_cx88_card_t **rchip,
+				     struct cx88_core **core_ptr)
 {
 	snd_cx88_card_t   *chip;
 	struct cx88_core  *core;
@@ -750,7 +832,7 @@
 	if (!pci_dma_supported(pci,DMA_BIT_MASK(32))) {
 		dprintk(0, "%s/1: Oops: no 32bit PCI DMA ???\n",core->name);
 		err = -EIO;
-		cx88_core_put(core,pci);
+		cx88_core_put(core, pci);
 		return err;
 	}
 
@@ -786,6 +868,7 @@
 	snd_card_set_dev(card, &pci->dev);
 
 	*rchip = chip;
+	*core_ptr = core;
 
 	return 0;
 }
@@ -795,6 +878,7 @@
 {
 	struct snd_card  *card;
 	snd_cx88_card_t  *chip;
+	struct cx88_core *core = NULL;
 	int              err;
 
 	if (devno >= SNDRV_CARDS)
@@ -812,7 +896,7 @@
 
 	card->private_free = snd_cx88_dev_free;
 
-	err = snd_cx88_create(card, pci, &chip);
+	err = snd_cx88_create(card, pci, &chip, &core);
 	if (err < 0)
 		goto error;
 
@@ -830,6 +914,10 @@
 	if (err < 0)
 		goto error;
 
+	/* If there's a wm8775 then add a Line-In ALC switch */
+	if (core->board.audio_chip == V4L2_IDENT_WM8775)
+		snd_ctl_add(card, snd_ctl_new1(&snd_cx88_alc_switch, chip));
+
 	strcpy (card->driver, "CX88x");
 	sprintf(card->shortname, "Conexant CX%x", pci->device);
 	sprintf(card->longname, "%s at %#llx",
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-cards.c linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-cards.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-cards.c	2012-03-24 03:26:51.000000000 -0400
@@ -970,7 +970,8 @@
 		.radio_type	= UNSET,
 		.tuner_addr	= ADDR_UNSET,
 		.radio_addr	= ADDR_UNSET,
-		.audio_chip = V4L2_IDENT_WM8775,
+		.audio_chip	= V4L2_IDENT_WM8775,
+		.i2sinputcntl   = 2,
 		.input		= {{
 			.type	= CX88_VMUX_DVB,
 			.vmux	= 0,
@@ -1952,6 +1953,18 @@
 		} },
 		.mpeg           = CX88_MPEG_DVB,
 	},
+	[CX88_BOARD_TEVII_S464] = {
+		.name           = "TeVii S464 DVB-S/S2",
+		.tuner_type     = UNSET,
+		.radio_type     = UNSET,
+		.tuner_addr     = ADDR_UNSET,
+		.radio_addr     = ADDR_UNSET,
+		.input          = {{
+			.type   = CX88_VMUX_DVB,
+			.vmux   = 0,
+		} },
+		.mpeg           = CX88_MPEG_DVB,
+	},
 	[CX88_BOARD_OMICOM_SS4_PCI] = {
 		.name           = "Omicom SS4 DVB-S/S2 PCI",
 		.tuner_type     = UNSET,
@@ -2528,6 +2541,10 @@
 		.subdevice = 0x9022,
 		.card      = CX88_BOARD_TEVII_S460,
 	}, {
+		.subvendor = 0xd464,
+		.subdevice = 0x9022,
+		.card      = CX88_BOARD_TEVII_S464,
+	}, {
 		.subvendor = 0xA044,
 		.subdevice = 0x2011,
 		.card      = CX88_BOARD_OMICOM_SS4_PCI,
@@ -3165,9 +3182,7 @@
 {
 	static u8 eeprom[256];
 	struct tuner_setup tun_setup;
-	unsigned int mode_mask = T_RADIO     |
-				 T_ANALOG_TV |
-				 T_DIGITAL_TV;
+	unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
 
 	memset(&tun_setup, 0, sizeof(tun_setup));
 
@@ -3287,6 +3302,7 @@
 	}
 	case  CX88_BOARD_TEVII_S420:
 	case  CX88_BOARD_TEVII_S460:
+	case  CX88_BOARD_TEVII_S464:
 	case  CX88_BOARD_OMICOM_SS4_PCI:
 	case  CX88_BOARD_TBS_8910:
 	case  CX88_BOARD_TBS_8920:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-dvb.c linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-dvb.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-dvb.c	2012-03-24 03:26:51.000000000 -0400
@@ -57,6 +57,7 @@
 #include "stb6100.h"
 #include "stb6100_proc.h"
 #include "mb86a16.h"
+#include "ds3000.h"
 
 MODULE_DESCRIPTION("driver for cx2388x based DVB cards");
 MODULE_AUTHOR("Chris Pascoe <c.pascoe@itee.uq.edu.au>");
@@ -648,6 +649,20 @@
 	.reset_device  = cx24116_reset_device,
 };
 
+static int ds3000_set_ts_param(struct dvb_frontend *fe,
+	int is_punctured)
+{
+	struct cx8802_dev *dev = fe->dvb->priv;
+	dev->ts_gen_cntrl = 4;
+
+	return 0;
+}
+
+static struct ds3000_config tevii_ds3000_config = {
+	.demod_address = 0x68,
+	.set_ts_params = ds3000_set_ts_param,
+};
+
 static const struct stv0900_config prof_7301_stv0900_config = {
 	.demod_address = 0x6a,
 /*	demod_mode = 0,*/
@@ -1381,6 +1396,14 @@
 		if (fe0->dvb.frontend != NULL)
 			fe0->dvb.frontend->ops.set_voltage = tevii_dvbs_set_voltage;
 		break;
+	case CX88_BOARD_TEVII_S464:
+		fe0->dvb.frontend = dvb_attach(ds3000_attach,
+						&tevii_ds3000_config,
+						&core->i2c_adap);
+		if (fe0->dvb.frontend != NULL)
+			fe0->dvb.frontend->ops.set_voltage =
+							tevii_dvbs_set_voltage;
+		break;
 	case CX88_BOARD_OMICOM_SS4_PCI:
 	case CX88_BOARD_TBS_8920:
 	case CX88_BOARD_PROF_7300:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88.h linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88.h
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,7 @@
 #include <media/cx2341x.h>
 #include <media/videobuf-dvb.h>
 #include <media/ir-kbd-i2c.h>
+#include <media/wm8775.h>
 
 #include "btcx-risc.h"
 #include "cx88-reg.h"
@@ -240,6 +241,7 @@
 #define CX88_BOARD_PROF_7301               83
 #define CX88_BOARD_SAMSUNG_SMT_7020        84
 #define CX88_BOARD_TWINHAN_VP1027_DVBS     85
+#define CX88_BOARD_TEVII_S464              86
 
 enum cx88_itype {
 	CX88_VMUX_COMPOSITE1 = 1,
@@ -273,6 +275,9 @@
 	enum cx88_board_type    mpeg;
 	unsigned int            audio_chip;
 	int			num_frontends;
+
+	/* Used for I2S devices */
+	int			i2sinputcntl;
 };
 
 struct cx88_subid {
@@ -379,6 +384,7 @@
 
 	/* I2C remote data */
 	struct IR_i2c_init_data    init_data;
+	struct wm8775_platform_data wm8775_data;
 
 	struct mutex               lock;
 	/* various v4l controls */
@@ -398,17 +404,21 @@
 	return container_of(v4l2_dev, struct cx88_core, v4l2_dev);
 }
 
-#define call_all(core, o, f, args...) 				\
+#define WM8775_GID	(1 << 0)
+
+#define call_hw(core, grpid, o, f, args...) \
 	do {							\
 		if (!core->i2c_rc) {				\
 			if (core->gate_ctrl)			\
 				core->gate_ctrl(core, 1);	\
-			v4l2_device_call_all(&core->v4l2_dev, 0, o, f, ##args); \
+			v4l2_device_call_all(&core->v4l2_dev, grpid, o, f, ##args); \
 			if (core->gate_ctrl)			\
 				core->gate_ctrl(core, 0);	\
 		}						\
 	} while (0)
 
+#define call_all(core, o, f, args...) call_hw(core, 0, o, f, ##args)
+
 struct cx8800_dev;
 struct cx8802_dev;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-input.c linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-input.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-input.c	2011-05-19 00:06:34.000000000 -0400
@@ -283,7 +283,7 @@
 	case CX88_BOARD_PCHDTV_HD3000:
 	case CX88_BOARD_PCHDTV_HD5500:
 	case CX88_BOARD_HAUPPAUGE_IRONLY:
-		ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		ir_codes = RC_MAP_HAUPPAUGE;
 		ir->sampling = 1;
 		break;
 	case CX88_BOARD_WINFAST_DTV2000H:
@@ -373,6 +373,7 @@
 		ir_codes = RC_MAP_TBS_NEC;
 		ir->sampling = 0xff00; /* address */
 		break;
+	case CX88_BOARD_TEVII_S464:
 	case CX88_BOARD_TEVII_S460:
 	case CX88_BOARD_TEVII_S420:
 		ir_codes = RC_MAP_TEVII_NEC;
@@ -523,7 +524,7 @@
 	for (todo = 32; todo > 0; todo -= bits) {
 		ev.pulse = samples & 0x80000000 ? false : true;
 		bits = min(todo, 32U - fls(ev.pulse ? samples : ~samples));
-		ev.duration = (bits * NSEC_PER_SEC) / (1000 * ir_samplerate);
+		ev.duration = (bits * (NSEC_PER_SEC / 1000)) / ir_samplerate;
 		ir_raw_event_store_with_filter(ir->dev, &ev);
 		samples <<= bits;
 	}
@@ -603,7 +604,7 @@
 		if (*addrp == 0x71) {
 			/* Hauppauge XVR */
 			core->init_data.name = "cx88 Hauppauge XVR remote";
-			core->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW;
+			core->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 			core->init_data.type = RC_TYPE_RC5;
 			core->init_data.internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-tvaudio.c linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-tvaudio.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-tvaudio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-tvaudio.c	2011-05-19 00:06:34.000000000 -0400
@@ -786,8 +786,12 @@
 		break;
 	case WW_I2SADC:
 		set_audio_start(core, 0x01);
-		/* Slave/Philips/Autobaud */
-		cx_write(AUD_I2SINPUTCNTL, 0);
+		/*
+		 * Slave/Philips/Autobaud
+		 * NB on Nova-S bit1 NPhilipsSony appears to be inverted:
+		 *	0= Sony, 1=Philips
+		 */
+		cx_write(AUD_I2SINPUTCNTL, core->board.i2sinputcntl);
 		/* Switch to "I2S ADC mode" */
 		cx_write(AUD_I2SCNTL, 0x1);
 		set_audio_finish(core, EN_I2SIN_ENABLE);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-video.c linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/cx88/cx88-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/cx88/cx88-video.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 #include "cx88.h"
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
+#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("v4l2 driver module for cx2388x based TV cards");
 MODULE_AUTHOR("Gerd Knorr <kraxel@bytesex.org> [SuSE Labs]");
@@ -989,6 +990,32 @@
 		ctl->value = c->v.minimum;
 	if (ctl->value > c->v.maximum)
 		ctl->value = c->v.maximum;
+
+	/* Pass changes onto any WM8775 */
+	if (core->board.audio_chip == V4L2_IDENT_WM8775) {
+		struct v4l2_control client_ctl;
+		memset(&client_ctl, 0, sizeof(client_ctl));
+		client_ctl.id = ctl->id;
+
+		switch (ctl->id) {
+		case V4L2_CID_AUDIO_MUTE:
+			client_ctl.value = ctl->value;
+			break;
+		case V4L2_CID_AUDIO_VOLUME:
+			client_ctl.value = (ctl->value) ?
+				(0x90 + ctl->value) << 8 : 0;
+			break;
+		case V4L2_CID_AUDIO_BALANCE:
+			client_ctl.value = ctl->value << 9;
+			break;
+		default:
+			client_ctl.id = 0;
+			break;
+		}
+		if (client_ctl.id)
+			call_hw(core, WM8775_GID, core, s_ctrl, &client_ctl);
+	}
+
 	mask=c->mask;
 	switch (ctl->id) {
 	case V4L2_CID_AUDIO_BALANCE:
@@ -1526,7 +1553,9 @@
 	if (c->id <  V4L2_CID_BASE ||
 		c->id >= V4L2_CID_LASTP1)
 		return -EINVAL;
-	if (c->id == V4L2_CID_AUDIO_MUTE) {
+	if (c->id == V4L2_CID_AUDIO_MUTE ||
+		c->id == V4L2_CID_AUDIO_VOLUME ||
+		c->id == V4L2_CID_AUDIO_BALANCE) {
 		for (i = 0; i < CX8800_CTLS; i++) {
 			if (cx8800_ctls[i].v.id == c->id)
 				break;
@@ -1672,7 +1701,7 @@
 	.read	       = video_read,
 	.poll          = video_poll,
 	.mmap	       = video_mmap,
-	.ioctl	       = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1722,7 +1751,7 @@
 	.owner         = THIS_MODULE,
 	.open          = video_open,
 	.release       = video_release,
-	.ioctl         = video_ioctl2,
+	.unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops radio_ioctl_ops = {
@@ -1856,9 +1885,24 @@
 
 	/* load and configure helper modules */
 
-	if (core->board.audio_chip == V4L2_IDENT_WM8775)
-		v4l2_i2c_new_subdev(&core->v4l2_dev, &core->i2c_adap,
-				"wm8775", 0x36 >> 1, NULL);
+	if (core->board.audio_chip == V4L2_IDENT_WM8775) {
+		struct i2c_board_info wm8775_info = {
+			.type = "wm8775",
+			.addr = 0x36 >> 1,
+			.platform_data = &core->wm8775_data,
+		};
+		struct v4l2_subdev *sd;
+
+		if (core->boardnr == CX88_BOARD_HAUPPAUGE_NOVASPLUS_S1)
+			core->wm8775_data.is_nova_s = true;
+		else
+			core->wm8775_data.is_nova_s = false;
+
+		sd = v4l2_i2c_new_subdev_board(&core->v4l2_dev, &core->i2c_adap,
+				&wm8775_info, NULL);
+		if (sd != NULL)
+			sd->grp_id = WM8775_GID;
+	}
 
 	if (core->board.audio_chip == V4L2_IDENT_TVAUDIO) {
 		/* This probes for a tda9874 as is used on some
@@ -1882,6 +1926,15 @@
 		request_module("ir-kbd-i2c");
 	}
 
+	/* Sets device info at pci_dev */
+	pci_set_drvdata(pci_dev, dev);
+
+	/* initial device configuration */
+	mutex_lock(&core->lock);
+	cx88_set_tvnorm(core, core->tvnorm);
+	init_controls(core);
+	cx88_video_mux(core, 0);
+
 	/* register v4l devices */
 	dev->video_dev = cx88_vdev_init(core,dev->pci,
 					&cx8800_video_template,"video");
@@ -1923,16 +1976,6 @@
 		       core->name, video_device_node_name(dev->radio_dev));
 	}
 
-	/* everything worked */
-	pci_set_drvdata(pci_dev,dev);
-
-	/* initial device configuration */
-	mutex_lock(&core->lock);
-	cx88_set_tvnorm(core,core->tvnorm);
-	init_controls(core);
-	cx88_video_mux(core,0);
-	mutex_unlock(&core->lock);
-
 	/* start tvaudio thread */
 	if (core->board.tuner_type != TUNER_ABSENT) {
 		core->kthread = kthread_run(cx88_audio_thread, core, "cx88 tvaudio");
@@ -1942,11 +1985,14 @@
 			       core->name, err);
 		}
 	}
+	mutex_unlock(&core->lock);
+
 	return 0;
 
 fail_unreg:
 	cx8800_unregister_video(dev);
 	free_irq(pci_dev->irq, dev);
+	mutex_unlock(&core->lock);
 fail_core:
 	cx88_core_put(core,dev->pci);
 fail_free:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/davinci/dm644x_ccdc.c linux-libre-2.6.39-gnu/drivers/media/video/davinci/dm644x_ccdc.c
--- linux-libre-2.6.38-gnu/drivers/media/video/davinci/dm644x_ccdc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/davinci/dm644x_ccdc.c	2011-05-19 00:06:34.000000000 -0400
@@ -258,7 +258,7 @@
 	/*
 	 * Allocate memory for FPC table if current
 	 * FPC table buffer is not big enough to
-	 * accomodate FPC Number requested
+	 * accommodate FPC Number requested
 	 */
 	if (raw_params->fault_pxl.fp_num != config_params->fault_pxl.fp_num) {
 		if (fpc_physaddr != NULL) {
@@ -436,7 +436,7 @@
 
 	/*
 	 * configure the horizontal line offset. This should be a
-	 * on 32 byte bondary. So clear LSB 5 bits
+	 * on 32 byte boundary. So clear LSB 5 bits
 	 */
 	regw(((params->win.width * 2  + 31) & ~0x1f), CCDC_HSIZE_OFF);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/davinci/vpfe_capture.c linux-libre-2.6.39-gnu/drivers/media/video/davinci/vpfe_capture.c
--- linux-libre-2.6.38-gnu/drivers/media/video/davinci/vpfe_capture.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/davinci/vpfe_capture.c	2011-05-19 00:06:34.000000000 -0400
@@ -1691,7 +1691,7 @@
 		goto unlock_out;
 	}
 
-	/* adjust the width to 16 pixel boundry */
+	/* adjust the width to 16 pixel boundary */
 	crop->c.width = ((crop->c.width + 15) & ~0xf);
 
 	/* make sure parameters are valid */
@@ -1719,7 +1719,7 @@
 
 
 static long vpfe_param_handler(struct file *file, void *priv,
-		int cmd, void *param)
+		bool valid_prio, int cmd, void *param)
 {
 	struct vpfe_device *vpfe_dev = video_drvdata(file);
 	int ret = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/em28xx/em28xx-cards.c linux-libre-2.6.39-gnu/drivers/media/video/em28xx/em28xx-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-03-24 01:00:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/em28xx/em28xx-cards.c	2012-03-24 03:26:51.000000000 -0400
@@ -834,7 +834,7 @@
 		.mts_firmware = 1,
 		.has_dvb      = 1,
 		.dvb_gpio     = hauppauge_wintv_hvr_900_digital,
-		.ir_codes     = RC_MAP_HAUPPAUGE_NEW,
+		.ir_codes     = RC_MAP_HAUPPAUGE,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -859,7 +859,7 @@
 		.tuner_type   = TUNER_XC2028,
 		.tuner_gpio   = default_tuner_gpio,
 		.mts_firmware = 1,
-		.ir_codes     = RC_MAP_HAUPPAUGE_NEW,
+		.ir_codes     = RC_MAP_HAUPPAUGE,
 		.decoder      = EM28XX_TVP5150,
 		.input        = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -885,7 +885,7 @@
 		.mts_firmware   = 1,
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-		.ir_codes       = RC_MAP_HAUPPAUGE_NEW,
+		.ir_codes       = RC_MAP_HAUPPAUGE,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -911,7 +911,7 @@
 		.mts_firmware   = 1,
 		.has_dvb        = 1,
 		.dvb_gpio       = hauppauge_wintv_hvr_900_digital,
-		.ir_codes       = RC_MAP_RC5_HAUPPAUGE_NEW,
+		.ir_codes       = RC_MAP_HAUPPAUGE,
 		.decoder        = EM28XX_TVP5150,
 		.input          = { {
 			.type     = EM28XX_VMUX_TELEVISION,
@@ -2430,7 +2430,7 @@
 		dev->init_data.name = "i2c IR (EM28XX Pinnacle PCTV)";
 		break;
 	case EM2820_BOARD_HAUPPAUGE_WINTV_USB_2:
-		dev->init_data.ir_codes = RC_MAP_RC5_HAUPPAUGE_NEW;
+		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 		dev->init_data.get_key = em28xx_get_key_em_haup;
 		dev->init_data.name = "i2c IR (EM2840 Hauppauge)";
 		break;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/em28xx/em28xx-video.c linux-libre-2.6.39-gnu/drivers/media/video/em28xx/em28xx-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/em28xx/em28xx-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/em28xx/em28xx-video.c	2011-05-19 00:06:34.000000000 -0400
@@ -377,7 +377,7 @@
 	/* Get the next buffer */
 	*buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
 
-	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
 	outp = videobuf_to_vmalloc(&(*buf)->vb);
 	memset(outp, 0, (*buf)->vb.size);
 
@@ -404,7 +404,7 @@
 
 	/* Get the next buffer */
 	*buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
-	/* Cleans up buffer - Usefull for testing for frame/URB loss */
+	/* Cleans up buffer - Useful for testing for frame/URB loss */
 	outp = videobuf_to_vmalloc(&(*buf)->vb);
 	memset(outp, 0x00, (*buf)->vb.size);
 
@@ -1387,6 +1387,27 @@
 		return -EINVAL;
 }
 
+/*
+ * FIXME: This is an indirect way to check if a control exists at a
+ * subdev. Instead of that hack, maybe the better would be to change all
+ * subdevs to return -ENOIOCTLCMD, if an ioctl is not supported.
+ */
+static int check_subdev_ctrl(struct em28xx *dev, int id)
+{
+	struct v4l2_queryctrl qc;
+
+	memset(&qc, 0, sizeof(qc));
+	qc.id = id;
+
+	/* enumerate V4L2 device controls */
+	v4l2_device_call_all(&dev->v4l2_dev, 0, core, queryctrl, &qc);
+
+	if (qc.type)
+		return 0;
+	else
+		return -EINVAL;
+}
+
 static int vidioc_g_ctrl(struct file *file, void *priv,
 				struct v4l2_control *ctrl)
 {
@@ -1399,7 +1420,6 @@
 		return rc;
 	rc = 0;
 
-
 	/* Set an AC97 control */
 	if (dev->audio_mode.ac97 != EM28XX_NO_AC97)
 		rc = ac97_get_ctrl(dev, ctrl);
@@ -1408,6 +1428,9 @@
 
 	/* It were not an AC97 control. Sends it to the v4l2 dev interface */
 	if (rc == 1) {
+		if (check_subdev_ctrl(dev, ctrl->id))
+			return -EINVAL;
+
 		v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_ctrl, ctrl);
 		rc = 0;
 	}
@@ -1434,8 +1457,10 @@
 
 	/* It isn't an AC97 control. Sends it to the v4l2 dev interface */
 	if (rc == 1) {
-		rc = v4l2_device_call_until_err(&dev->v4l2_dev, 0, core, s_ctrl, ctrl);
-
+		rc = check_subdev_ctrl(dev, ctrl->id);
+		if (!rc)
+			v4l2_device_call_all(&dev->v4l2_dev, 0,
+					     core, s_ctrl, ctrl);
 		/*
 		 * In the case of non-AC97 volume controls, we still need
 		 * to do some setups at em28xx, in order to mute/unmute
@@ -1452,7 +1477,7 @@
 			rc = em28xx_audio_analog_set(dev);
 		}
 	}
-	return rc;
+	return (rc < 0) ? rc : 0;
 }
 
 static int vidioc_g_tuner(struct file *file, void *priv,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/fsl-viu.c linux-libre-2.6.39-gnu/drivers/media/video/fsl-viu.c
--- linux-libre-2.6.38-gnu/drivers/media/video/fsl-viu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/fsl-viu.c	2011-05-19 00:06:34.000000000 -0400
@@ -1445,8 +1445,7 @@
 	.current_norm   = V4L2_STD_NTSC_M,
 };
 
-static int __devinit viu_of_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit viu_of_probe(struct platform_device *op)
 {
 	struct viu_dev *viu_dev;
 	struct video_device *vdev;
@@ -1627,7 +1626,7 @@
 };
 MODULE_DEVICE_TABLE(of, mpc512x_viu_of_match);
 
-static struct of_platform_driver viu_of_platform_driver = {
+static struct platform_driver viu_of_platform_driver = {
 	.probe = viu_of_probe,
 	.remove = __devexit_p(viu_of_remove),
 #ifdef CONFIG_PM
@@ -1643,12 +1642,12 @@
 
 static int __init viu_init(void)
 {
-	return of_register_platform_driver(&viu_of_platform_driver);
+	return platform_driver_register(&viu_of_platform_driver);
 }
 
 static void __exit viu_exit(void)
 {
-	of_unregister_platform_driver(&viu_of_platform_driver);
+	platform_driver_unregister(&viu_of_platform_driver);
 }
 
 module_init(viu_init);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/autogain_functions.h linux-libre-2.6.39-gnu/drivers/media/video/gspca/autogain_functions.h
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/autogain_functions.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/autogain_functions.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,179 @@
+/*
+ * Functions for auto gain.
+ *
+ * Copyright (C) 2010-2011 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
+ * 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
+ */
+
+/* auto gain and exposure algorithm based on the knee algorithm described here:
+   http://ytse.tricolour.net/docs/LowLightOptimization.html
+
+   Returns 0 if no changes were made, 1 if the gain and or exposure settings
+   where changed. */
+static inline int auto_gain_n_exposure(
+			struct gspca_dev *gspca_dev,
+			int avg_lum,
+			int desired_avg_lum,
+			int deadzone,
+			int gain_knee,
+			int exposure_knee)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int i, steps, gain, orig_gain, exposure, orig_exposure;
+	int retval = 0;
+
+	orig_gain = gain = sd->ctrls[GAIN].val;
+	orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
+
+	/* If we are of a multiple of deadzone, do multiple steps to reach the
+	   desired lumination fast (with the risc of a slight overshoot) */
+	steps = abs(desired_avg_lum - avg_lum) / deadzone;
+
+	PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
+		avg_lum, desired_avg_lum, steps);
+
+	for (i = 0; i < steps; i++) {
+		if (avg_lum > desired_avg_lum) {
+			if (gain > gain_knee)
+				gain--;
+			else if (exposure > exposure_knee)
+				exposure--;
+			else if (gain > sd->ctrls[GAIN].def)
+				gain--;
+			else if (exposure > sd->ctrls[EXPOSURE].min)
+				exposure--;
+			else if (gain > sd->ctrls[GAIN].min)
+				gain--;
+			else
+				break;
+		} else {
+			if (gain < sd->ctrls[GAIN].def)
+				gain++;
+			else if (exposure < exposure_knee)
+				exposure++;
+			else if (gain < gain_knee)
+				gain++;
+			else if (exposure < sd->ctrls[EXPOSURE].max)
+				exposure++;
+			else if (gain < sd->ctrls[GAIN].max)
+				gain++;
+			else
+				break;
+		}
+	}
+
+	if (gain != orig_gain) {
+		sd->ctrls[GAIN].val = gain;
+		setgain(gspca_dev);
+		retval = 1;
+	}
+	if (exposure != orig_exposure) {
+		sd->ctrls[EXPOSURE].val = exposure;
+		setexposure(gspca_dev);
+		retval = 1;
+	}
+
+	if (retval)
+		PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
+			gain, exposure);
+	return retval;
+}
+
+/* Autogain + exposure algorithm for cameras with a coarse exposure control
+   (usually this means we can only control the clockdiv to change exposure)
+   As changing the clockdiv so that the fps drops from 30 to 15 fps for
+   example, will lead to a huge exposure change (it effectively doubles),
+   this algorithm normally tries to only adjust the gain (between 40 and
+   80 %) and if that does not help, only then changes exposure. This leads
+   to a much more stable image then using the knee algorithm which at
+   certain points of the knee graph will only try to adjust exposure,
+   which leads to oscilating as one exposure step is huge.
+
+   Note this assumes that the sd struct for the cam in question has
+   exp_too_high_cnt and exp_too_high_cnt int members for use by this function.
+
+   Returns 0 if no changes were made, 1 if the gain and or exposure settings
+   where changed. */
+static inline int coarse_grained_expo_autogain(
+			struct gspca_dev *gspca_dev,
+			int avg_lum,
+			int desired_avg_lum,
+			int deadzone)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int steps, gain, orig_gain, exposure, orig_exposure;
+	int gain_low, gain_high;
+	int retval = 0;
+
+	orig_gain = gain = sd->ctrls[GAIN].val;
+	orig_exposure = exposure = sd->ctrls[EXPOSURE].val;
+
+	gain_low = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 2;
+	gain_low += sd->ctrls[GAIN].min;
+	gain_high = (sd->ctrls[GAIN].max - sd->ctrls[GAIN].min) / 5 * 4;
+	gain_high += sd->ctrls[GAIN].min;
+
+	/* If we are of a multiple of deadzone, do multiple steps to reach the
+	   desired lumination fast (with the risc of a slight overshoot) */
+	steps = (desired_avg_lum - avg_lum) / deadzone;
+
+	PDEBUG(D_FRAM, "autogain: lum: %d, desired: %d, steps: %d",
+		avg_lum, desired_avg_lum, steps);
+
+	if ((gain + steps) > gain_high &&
+	    exposure < sd->ctrls[EXPOSURE].max) {
+		gain = gain_high;
+		sd->exp_too_low_cnt++;
+		sd->exp_too_high_cnt = 0;
+	} else if ((gain + steps) < gain_low &&
+		   exposure > sd->ctrls[EXPOSURE].min) {
+		gain = gain_low;
+		sd->exp_too_high_cnt++;
+		sd->exp_too_low_cnt = 0;
+	} else {
+		gain += steps;
+		if (gain > sd->ctrls[GAIN].max)
+			gain = sd->ctrls[GAIN].max;
+		else if (gain < sd->ctrls[GAIN].min)
+			gain = sd->ctrls[GAIN].min;
+		sd->exp_too_high_cnt = 0;
+		sd->exp_too_low_cnt = 0;
+	}
+
+	if (sd->exp_too_high_cnt > 3) {
+		exposure--;
+		sd->exp_too_high_cnt = 0;
+	} else if (sd->exp_too_low_cnt > 3) {
+		exposure++;
+		sd->exp_too_low_cnt = 0;
+	}
+
+	if (gain != orig_gain) {
+		sd->ctrls[GAIN].val = gain;
+		setgain(gspca_dev);
+		retval = 1;
+	}
+	if (exposure != orig_exposure) {
+		sd->ctrls[EXPOSURE].val = exposure;
+		setexposure(gspca_dev);
+		retval = 1;
+	}
+
+	if (retval)
+		PDEBUG(D_FRAM, "autogain: changed gain: %d, expo: %d",
+			gain, exposure);
+	return retval;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/cpia1.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/cpia1.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/cpia1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/cpia1.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * cpia CPiA (1) gspca driver
  *
- * Copyright (C) 2010 Hans de Goede <hdegoede@redhat.com>
+ * Copyright (C) 2010-2011 Hans de Goede <hdegoede@redhat.com>
  *
  * This module is adapted from the in kernel v4l1 cpia driver which is :
  *
@@ -28,6 +28,7 @@
 
 #define MODULE_NAME "cpia1"
 
+#include <linux/input.h>
 #include "gspca.h"
 
 MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
@@ -653,10 +654,15 @@
 		break;
 
 	case CPIA_COMMAND_ReadMCPorts:
-		if (!sd->params.qx3.qx3_detected)
-			break;
 		/* test button press */
-		sd->params.qx3.button = ((gspca_dev->usb_buf[1] & 0x02) == 0);
+		a = ((gspca_dev->usb_buf[1] & 0x02) == 0);
+		if (a != sd->params.qx3.button) {
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+			input_report_key(gspca_dev->input_dev, KEY_CAMERA, a);
+			input_sync(gspca_dev->input_dev);
+#endif
+	        	sd->params.qx3.button = a;
+		}
 		if (sd->params.qx3.button) {
 			/* button pressed - unlock the latch */
 			do_command(gspca_dev, CPIA_COMMAND_WriteMCPort,
@@ -1400,7 +1406,7 @@
 		if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
 		     sd->exposure_status == EXPOSURE_DARK) &&
 		    sd->exposure_count >= DARK_TIME * framerate &&
-		    sd->params.sensorFps.divisor < 3) {
+		    sd->params.sensorFps.divisor < 2) {
 
 			/* dark for too long */
 			++sd->params.sensorFps.divisor;
@@ -1456,7 +1462,7 @@
 		if ((sd->exposure_status == EXPOSURE_VERY_DARK ||
 		     sd->exposure_status == EXPOSURE_DARK) &&
 		    sd->exposure_count >= DARK_TIME * framerate &&
-		    sd->params.sensorFps.divisor < 3) {
+		    sd->params.sensorFps.divisor < 2) {
 
 			/* dark for too long */
 			++sd->params.sensorFps.divisor;
@@ -1738,6 +1744,8 @@
 
 static void sd_stopN(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
+
 	command_pause(gspca_dev);
 
 	/* save camera state for later open (developers guide ch 3.5.3) */
@@ -1748,6 +1756,17 @@
 
 	/* Update the camera status */
 	do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+	/* If the last button state is pressed, release it now! */
+	if (sd->params.qx3.button) {
+		/* The camera latch will hold the pressed state until we reset
+		   the latch, so we do not reset sd->params.qx3.button now, to
+		   avoid a false keypress being reported the next sd_start */
+		input_report_key(gspca_dev->input_dev, KEY_CAMERA, 0);
+		input_sync(gspca_dev->input_dev);
+	}
+#endif
 }
 
 /* this function is called at probe and resume time */
@@ -1852,8 +1871,7 @@
 
 	/* Update our knowledge of the camera state */
 	do_command(gspca_dev, CPIA_COMMAND_GetExposure, 0, 0, 0, 0);
-	if (sd->params.qx3.qx3_detected)
-		do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
+	do_command(gspca_dev, CPIA_COMMAND_ReadMCPorts, 0, 0, 0, 0);
 }
 
 static int sd_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
@@ -2085,6 +2103,9 @@
 	.dq_callback = sd_dq_callback,
 	.pkt_scan = sd_pkt_scan,
 	.querymenu = sd_querymenu,
+#if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
+	.other_input = 1,
+#endif
 };
 
 /* -- module initialisation -- */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/gl860/gl860-mi1320.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/gl860/gl860-mi1320.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/gl860/gl860-mi1320.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/gl860/gl860-mi1320.c	2011-05-19 00:06:34.000000000 -0400
@@ -201,7 +201,7 @@
 	sd->vmax.backlight  =  2;
 	sd->vmax.brightness =  8;
 	sd->vmax.sharpness  =  7;
-	sd->vmax.contrast   =  0; /* 10 but not working with tihs driver */
+	sd->vmax.contrast   =  0; /* 10 but not working with this driver */
 	sd->vmax.gamma      = 40;
 	sd->vmax.hue        =  5 + 1;
 	sd->vmax.saturation =  8;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/gspca.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/gspca.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/gspca.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/gspca.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Main USB camera driver
  *
- * Copyright (C) 2008-2010 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2008-2011 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
  *
  * Camera button input handling by MÃ¡rton NÃ©meth
  * Copyright (C) 2009-2010 MÃ¡rton NÃ©meth <nm127@freemail.hu>
@@ -414,7 +414,6 @@
  *	- 0 or many INTER_PACKETs
  *	- one LAST_PACKET
  * DISCARD_PACKET invalidates the whole frame.
- * On LAST_PACKET, a new frame is returned.
  */
 void gspca_frame_add(struct gspca_dev *gspca_dev,
 			enum gspca_packet_type packet_type,
@@ -631,7 +630,8 @@
 		ep = &alt->endpoint[i];
 		attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
 		if (attr == xfer
-		    && ep->desc.wMaxPacketSize != 0)
+		    && ep->desc.wMaxPacketSize != 0
+		    && usb_endpoint_dir_in(&ep->desc))
 			return ep;
 	}
 	return NULL;
@@ -857,7 +857,7 @@
 		}
 
 		/* the bandwidth is not wide enough
-		 * negociate or try a lower alternate setting */
+		 * negotiate or try a lower alternate setting */
 		PDEBUG(D_ERR|D_STREAM,
 			"bandwidth not wide enough - trying again");
 		msleep(20);	/* wait for kill complete */
@@ -1525,10 +1525,12 @@
 		gspca_dev->usb_err = 0;
 		gspca_stream_off(gspca_dev);
 		mutex_unlock(&gspca_dev->usb_lock);
+
+		/* Don't restart the stream when switching from read
+		 * to mmap mode */
+		if (gspca_dev->memory == GSPCA_MEMORY_READ)
+			streaming = 0;
 	}
-	/* Don't restart the stream when switching from read to mmap mode */
-	if (gspca_dev->memory == GSPCA_MEMORY_READ)
-		streaming = 0;
 
 	/* free the previous allocated buffers, if any */
 	if (gspca_dev->nframes != 0)
@@ -2152,7 +2154,7 @@
 	.vidioc_g_chip_ident	= vidioc_g_chip_ident,
 };
 
-static struct video_device gspca_template = {
+static const struct video_device gspca_template = {
 	.name = "gspca main driver",
 	.fops = &dev_fops,
 	.ioctl_ops = &dev_ioctl_ops,
@@ -2344,7 +2346,7 @@
 	usb_set_intfdata(intf, NULL);
 
 	/* release the device */
-	/* (this will call gspca_release() immediatly or on last close) */
+	/* (this will call gspca_release() immediately or on last close) */
 	video_unregister_device(&gspca_dev->vdev);
 
 /*	PDEBUG(D_PROBE, "disconnect complete"); */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/jeilinj.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/jeilinj.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/jeilinj.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/jeilinj.c	2011-05-19 00:06:34.000000000 -0400
@@ -183,7 +183,6 @@
 	struct sd *dev = container_of(work, struct sd, work_struct);
 	struct gspca_dev *gspca_dev = &dev->gspca_dev;
 	int blocks_left; /* 0x200-sized blocks remaining in current frame. */
-	int size_in_blocks;
 	int act_len;
 	int packet_type;
 	int ret;
@@ -209,7 +208,6 @@
 			act_len, JEILINJ_MAX_TRANSFER);
 		if (ret < 0 || act_len < FRAME_HEADER_LEN)
 			goto quit_stream;
-		size_in_blocks = buffer[0x0a];
 		blocks_left = buffer[0x0a] - 1;
 		PDEBUG(D_STREAM, "blocks_left = 0x%x", blocks_left);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/Kconfig linux-libre-2.6.39-gnu/drivers/media/video/gspca/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -104,6 +104,15 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_mr97310a.
 
+config USB_GSPCA_NW80X
+	tristate "Divio based (NW80x) USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for cameras based on the NW80x chips.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_nw80x.
+
 config USB_GSPCA_OV519
 	tristate "OV51x / OVFX2 / W996xCF USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
@@ -346,6 +355,16 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called gspca_vc032x.
 
+config USB_GSPCA_VICAM
+	tristate "ViCam USB Camera Driver"
+	depends on VIDEO_V4L2 && USB_GSPCA
+	help
+	  Say Y here if you want support for the 3com homeconnect camera
+	  (vicam).
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called gspca_vicam.
+
 config USB_GSPCA_XIRLINK_CIT
 	tristate "Xirlink C-It USB Camera Driver"
 	depends on VIDEO_V4L2 && USB_GSPCA
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/Makefile linux-libre-2.6.39-gnu/drivers/media/video/gspca/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,7 @@
 obj-$(CONFIG_USB_GSPCA_KONICA)   += gspca_konica.o
 obj-$(CONFIG_USB_GSPCA_MARS)     += gspca_mars.o
 obj-$(CONFIG_USB_GSPCA_MR97310A) += gspca_mr97310a.o
+obj-$(CONFIG_USB_GSPCA_NW80X)    += gspca_nw80x.o
 obj-$(CONFIG_USB_GSPCA_OV519)    += gspca_ov519.o
 obj-$(CONFIG_USB_GSPCA_OV534)    += gspca_ov534.o
 obj-$(CONFIG_USB_GSPCA_OV534_9)  += gspca_ov534_9.o
@@ -34,6 +35,7 @@
 obj-$(CONFIG_USB_GSPCA_T613)     += gspca_t613.o
 obj-$(CONFIG_USB_GSPCA_TV8532)   += gspca_tv8532.o
 obj-$(CONFIG_USB_GSPCA_VC032X)   += gspca_vc032x.o
+obj-$(CONFIG_USB_GSPCA_VICAM)    += gspca_vicam.o
 obj-$(CONFIG_USB_GSPCA_XIRLINK_CIT) += gspca_xirlink_cit.o
 obj-$(CONFIG_USB_GSPCA_ZC3XX)    += gspca_zc3xx.o
 
@@ -47,6 +49,7 @@
 gspca_konica-objs   := konica.o
 gspca_mars-objs     := mars.o
 gspca_mr97310a-objs := mr97310a.o
+gspca_nw80x-objs    := nw80x.o
 gspca_ov519-objs    := ov519.o
 gspca_ov534-objs    := ov534.o
 gspca_ov534_9-objs  := ov534_9.o
@@ -73,6 +76,7 @@
 gspca_t613-objs     := t613.o
 gspca_tv8532-objs   := tv8532.o
 gspca_vc032x-objs   := vc032x.o
+gspca_vicam-objs    := vicam.o
 gspca_xirlink_cit-objs := xirlink_cit.o
 gspca_zc3xx-objs    := zc3xx.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/mars.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/mars.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/mars.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/mars.c	2011-05-19 00:06:34.000000000 -0400
@@ -361,7 +361,7 @@
 		mi_w(gspca_dev, i + 1, mi_data[i]);
 
 	data[0] = 0x00;
-	data[1] = 0x4d;		/* ISOC transfering enable... */
+	data[1] = 0x4d;		/* ISOC transferring enable... */
 	reg_w(gspca_dev, 2);
 
 	gspca_dev->ctrl_inac = 0; /* activate the illuminator controls */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/mr97310a.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/mr97310a.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/mr97310a.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/mr97310a.c	2011-05-19 00:06:34.000000000 -0400
@@ -469,7 +469,7 @@
 static int isoc_enable(struct gspca_dev *gspca_dev)
 {
 	gspca_dev->usb_buf[0] = 0x00;
-	gspca_dev->usb_buf[1] = 0x4d;  /* ISOC transfering enable... */
+	gspca_dev->usb_buf[1] = 0x4d;  /* ISOC transferring enable... */
 	return mr_write(gspca_dev, 2);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/nw80x.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/nw80x.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/nw80x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/nw80x.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2145 @@
+/*
+ * DivIO nw80x subdriver
+ *
+ * Copyright (C) 2011 Jean-FranÃ§ois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2003 Sylvain Munaut <tnt@246tNt.com>
+ *			Kjell Claesson <keyson@users.sourceforge.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
+ * 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 MODULE_NAME "nw80x"
+
+#include "gspca.h"
+
+MODULE_AUTHOR("Jean-Francois Moine <http://moinejf.free.fr>");
+MODULE_DESCRIPTION("NW80x USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+static int webcam;
+
+/* controls */
+enum e_ctrl {
+	GAIN,
+	EXPOSURE,
+	AUTOGAIN,
+	NCTRLS		/* number of controls */
+};
+
+#define AUTOGAIN_DEF 1
+
+/* specific webcam descriptor */
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+
+	struct gspca_ctrl ctrls[NCTRLS];
+
+	u32 ae_res;
+	s8 ag_cnt;
+#define AG_CNT_START 13
+	u8 exp_too_low_cnt;
+	u8 exp_too_high_cnt;
+
+	u8 bridge;
+	u8 webcam;
+};
+
+enum bridges {
+	BRIDGE_NW800,	/* and et31x110 */
+	BRIDGE_NW801,
+	BRIDGE_NW802,
+};
+enum webcams {
+	Generic800,
+	SpaceCam,	/* Trust 120 SpaceCam */
+	SpaceCam2,	/* other Trust 120 SpaceCam */
+	Cvideopro,	/* Conceptronic Video Pro */
+	Dlink350c,
+	DS3303u,
+	Kr651us,
+	Kritter,
+	Mustek300,
+	Proscope,
+	Twinkle,
+	DvcV6,
+	P35u,
+	Generic802,
+	NWEBCAMS	/* number of webcams */
+};
+
+static const u8 webcam_chip[NWEBCAMS] = {
+	[Generic800]	= BRIDGE_NW800,	/* 06a5:0000
+					 * Typhoon Webcam 100 USB */
+
+	[SpaceCam]	= BRIDGE_NW800,	/* 06a5:d800
+				* Trust SpaceCam120 or SpaceCam100 PORTABLE */
+
+	[SpaceCam2]	= BRIDGE_NW800,	/* 06a5:d800 - pas106
+			* other Trust SpaceCam120 or SpaceCam100 PORTABLE */
+
+	[Cvideopro]	= BRIDGE_NW802,	/* 06a5:d001
+			* Conceptronic Video Pro 'CVIDEOPRO USB Webcam CCD' */
+
+	[Dlink350c]	= BRIDGE_NW802,	/* 06a5:d001
+					 * D-Link NetQam Pro 250plus */
+
+	[DS3303u]	= BRIDGE_NW801,	/* 06a5:d001
+				* Plustek Opticam 500U or ProLink DS3303u */
+
+	[Kr651us]	= BRIDGE_NW802,	/* 06a5:d001
+					 * Panasonic GP-KR651US */
+
+	[Kritter]	= BRIDGE_NW802,	/* 06a5:d001
+					 * iRez Kritter cam */
+
+	[Mustek300]	= BRIDGE_NW802,	/* 055f:d001
+					 * Mustek Wcam 300 mini */
+
+	[Proscope]	= BRIDGE_NW802,	/* 06a5:d001
+					 * Scalar USB Microscope (ProScope) */
+
+	[Twinkle]	= BRIDGE_NW800,	/* 06a5:d800 - hv7121b? (seems pas106)
+					 * Divio Chicony TwinkleCam
+					 * DSB-C110 */
+
+	[DvcV6]		= BRIDGE_NW802,	/* 0502:d001
+					 * DVC V6 */
+
+	[P35u]		= BRIDGE_NW801,	/* 052b:d001, 06a5:d001 and 06be:d001
+					 * EZCam Pro p35u */
+
+	[Generic802]	= BRIDGE_NW802,
+};
+/*
+ * other webcams:
+ *	- nw801 046d:d001
+ *		Logitech QuickCam Pro (dark focus ring)
+ *	- nw801 0728:d001
+ *		AVerMedia Camguard
+ *	- nw??? 06a5:d001
+ *		D-Link NetQam Pro 250plus
+ *	- nw800 065a:d800
+ *		Showcam NGS webcam
+ *	- nw??? ????:????
+ *		Sceptre svc300
+ */
+
+/*
+ * registers
+ *    nw800/et31x110	  nw801		  nw802
+ *	0000..009e	0000..00a1	0000..009e
+ *	0200..0211	   id		   id
+ *	0300..0302	   id		   id
+ *	0400..0406	  (inex)	0400..0406
+ *	0500..0505	0500..0506	  (inex)
+ *	0600..061a	0600..0601	0600..0601
+ *	0800..0814	   id		   id
+ *	1000..109c	1000..10a1	1000..109a
+ */
+
+/* resolutions
+ *	nw800: 320x240, 352x288
+ *	nw801/802: 320x240, 640x480
+ */
+static const struct v4l2_pix_format cif_mode[] = {
+	{320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 4 / 8,
+		.colorspace = V4L2_COLORSPACE_JPEG},
+	{352, 288, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+		.bytesperline = 352,
+		.sizeimage = 352 * 288 * 4 / 8,
+		.colorspace = V4L2_COLORSPACE_JPEG}
+};
+static const struct v4l2_pix_format vga_mode[] = {
+	{320, 240, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 4 / 8,
+		.colorspace = V4L2_COLORSPACE_JPEG},
+	{640, 480, V4L2_PIX_FMT_JPGL, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 3 / 8,
+		.colorspace = V4L2_COLORSPACE_JPEG},
+};
+
+/*
+ * The sequences below contain:
+ *	- 1st and 2nd bytes: either
+ *		- register number (BE)
+ *		- I2C0 + i2c address
+ *	- 3rd byte: data length (=0 for end of sequence)
+ *	- n bytes: data
+ */
+#define I2C0 0xff
+
+static const u8 nw800_init[] = {
+	0x04, 0x05, 0x01, 0x61,
+	0x04, 0x04, 0x01, 0x01,
+	0x04, 0x06, 0x01, 0x04,
+	0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
+	0x05, 0x05, 0x01, 0x00,
+	0, 0, 0
+};
+static const u8 nw800_start[] = {
+	0x04, 0x06, 0x01, 0xc0,
+	0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
+			  0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
+			  0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
+			  0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+			  0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
+	0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
+	0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
+			  0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+			  0x01, 0x60, 0x01, 0x00, 0x00,
+
+	0x04, 0x04, 0x01, 0xff,
+	0x04, 0x06, 0x01, 0xc4,
+
+	0x04, 0x06, 0x01, 0xc0,
+	0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
+			  0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
+			  0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
+			  0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+			  0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0xc0,
+	0x05, 0x00, 0x06, 0xe8, 0x00, 0x00, 0x00, 0x20, 0x20,
+	0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
+			  0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+			  0x01, 0x60, 0x01, 0x00, 0x00,
+
+	0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+			  0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+			  0x40,
+	0x00, 0x80, 0x01, 0xa0,
+	0x10, 0x1a, 0x01, 0x00,
+	0x00, 0x91, 0x02, 0x6c, 0x01,
+	0x00, 0x03, 0x02, 0xc8, 0x01,
+	0x10, 0x1a, 0x01, 0x00,
+	0x10, 0x00, 0x01, 0x83,
+	0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+			  0x20, 0x01, 0x60, 0x01,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x10, 0x1b, 0x02, 0x69, 0x00,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x05, 0x02, 0x01, 0x02,
+	0x06, 0x00, 0x02, 0x04, 0xd9,
+	0x05, 0x05, 0x01, 0x20,
+	0x05, 0x05, 0x01, 0x21,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
+			  0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
+			  0xea,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x13, 0x13,
+	0x10, 0x03, 0x01, 0x14,
+	0x10, 0x41, 0x11, 0x00, 0x08, 0x21, 0x3d, 0x52, 0x63, 0x75, 0x83,
+			  0x91, 0x9e, 0xaa, 0xb6, 0xc1, 0xcc, 0xd6, 0xe0,
+			  0xea,
+	0x10, 0x0b, 0x01, 0x14,
+	0x10, 0x0d, 0x01, 0x20,
+	0x10, 0x0c, 0x01, 0x34,
+	0x04, 0x06, 0x01, 0xc3,
+	0x04, 0x04, 0x01, 0x00,
+	0x05, 0x02, 0x01, 0x02,
+	0x06, 0x00, 0x02, 0x00, 0x48,
+	0x05, 0x05, 0x01, 0x20,
+	0x05, 0x05, 0x01, 0x21,
+	0, 0, 0
+};
+
+/* 06a5:d001 - nw801 - Panasonic
+ *		P35u */
+static const u8 nw801_start_1[] = {
+	0x05, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x0e, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
+			  0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+			  0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x69, 0xa8, 0x1f, 0x00,
+			  0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
+			  0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
+			  0x36, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x00, 0x00, 0x00,
+	0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x22, 0x02, 0x80, 0x00, 0x1e, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x0a, 0x15, 0x08, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x01, 0x35, 0xfd, 0x07, 0x3d, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x14, 0x02,
+			  0x00, 0x01, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00,
+			  0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x10, 0x06,
+			  0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
+	0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
+			  0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99, 0xa4,
+			  0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc, 0xcf,
+			  0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
+			  0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
+			  0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+	0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x82, 0x02,
+			  0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
+			  0xf0, 0x00,
+	0, 0, 0,
+};
+static const u8 nw801_start_qvga[] = {
+	0x02, 0x00, 0x10, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x18, 0x0b, 0x06, 0xa2, 0x86, 0x78,
+	0x02, 0x0f, 0x01, 0x6b,
+	0x10, 0x1a, 0x01, 0x15,
+	0x00, 0x00, 0x01, 0x1e,
+	0x10, 0x00, 0x01, 0x2f,
+	0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
+							/* AE window */
+	0, 0, 0,
+};
+static const u8 nw801_start_vga[] = {
+	0x02, 0x00, 0x10, 0x78, 0xa0, 0x97, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xf0,
+	0x02, 0x0f, 0x01, 0xd5,
+	0x10, 0x1a, 0x01, 0x15,
+	0x00, 0x00, 0x01, 0x0e,
+	0x10, 0x00, 0x01, 0x22,
+	0x10, 0x8c, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+	0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
+	0, 0, 0,
+};
+static const u8 nw801_start_2[] = {
+	0x10, 0x04, 0x01, 0x1a,
+	0x10, 0x19, 0x01, 0x09,				/* clock */
+	0x10, 0x24, 0x06, 0xc0, 0x00, 0x3f, 0x02, 0x00, 0x01,
+							 /* .. gain .. */
+	0x00, 0x03, 0x02, 0x92, 0x03,
+	0x00, 0x1d, 0x04, 0xf2, 0x00, 0x24, 0x07,
+	0x00, 0x7b, 0x01, 0xcf,
+	0x10, 0x94, 0x01, 0x07,
+	0x05, 0x05, 0x01, 0x01,
+	0x05, 0x04, 0x01, 0x01,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
+			  0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
+			  0xf0,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x0c, 0x0c,
+	0x10, 0x03, 0x01, 0x08,
+	0x10, 0x48, 0x11, 0x00, 0x37, 0x55, 0x6b, 0x7d, 0x8d, 0x9b, 0xa8,
+			  0xb4, 0xbf, 0xca, 0xd4, 0xdd, 0xe6, 0xef, 0xf0,
+			  0xf0,
+	0x10, 0x0b, 0x01, 0x0b,
+	0x10, 0x0d, 0x01, 0x0b,
+	0x10, 0x0c, 0x01, 0x1f,
+	0x05, 0x06, 0x01, 0x03,
+	0, 0, 0
+};
+
+/* nw802 (sharp IR3Y38M?) */
+static const u8 nw802_start[] = {
+	0x04, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x4d,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+			  0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x08, 0x00, 0x18, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x1d, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0xff, 0x01, 0xc0, 0x00, 0x14,
+			  0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x05, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x00,
+	0x10, 0x00, 0x01, 0xad,
+	0x00, 0x00, 0x01, 0x08,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
+	0x10, 0x1d, 0x08, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0, 0x00, 0xa0,
+	0x10, 0x0e, 0x01, 0x27,
+	0x10, 0x41, 0x11, 0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
+			  0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
+			  0xd8,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x14, 0x14,
+	0x10, 0x03, 0x01, 0x0c,
+	0x10, 0x41, 0x11, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64, 0x74,
+			  0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2, 0xf1,
+			  0xff,
+/*			  0x00, 0x0e, 0x35, 0x4f, 0x62, 0x71, 0x7f, 0x8b,
+ *			  0x96, 0xa0, 0xa9, 0xb2, 0xbb, 0xc3, 0xca, 0xd2,
+ *			  0xd8,	*/
+	0x10, 0x0b, 0x01, 0x10,
+	0x10, 0x0d, 0x01, 0x11,
+	0x10, 0x0c, 0x01, 0x1c,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+/* et31x110 - Trust 120 SpaceCam */
+static const u8 spacecam_init[] = {
+	0x04, 0x05, 0x01, 0x01,
+	0x04, 0x04, 0x01, 0x01,
+	0x04, 0x06, 0x01, 0x04,
+	0x04, 0x04, 0x03, 0x00, 0x00, 0x00,
+	0x05, 0x05, 0x01, 0x00,
+	0, 0, 0
+};
+static const u8 spacecam_start[] = {
+	0x04, 0x06, 0x01, 0x44,
+	0x00, 0x00, 0x40, 0x10, 0x43, 0x00, 0xb4, 0x01, 0x10, 0x00, 0x4f,
+			  0xef, 0x0e, 0x00, 0x74, 0x01, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x3e, 0x00, 0x24,
+			  0x03, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xa0, 0x48, 0xc3, 0x02, 0x88, 0x0c, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x06, 0x00, 0x08,
+			  0x00, 0x32, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+			  0x00, 0x4b, 0x00, 0x7c, 0x00, 0x80, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x83, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x2d, 0x00, 0x62,
+			  0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+			  0x01, 0x60, 0x01, 0x00, 0x00,
+	0x04, 0x06, 0x01, 0xc0,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+			  0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+			  0x40,
+	0x00, 0x80, 0x01, 0xa0,
+	0x10, 0x1a, 0x01, 0x00,
+	0x00, 0x91, 0x02, 0x32, 0x01,
+	0x00, 0x03, 0x02, 0x08, 0x02,
+	0x10, 0x00, 0x01, 0x83,
+	0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+			  0x20, 0x01, 0x60, 0x01,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
+			  0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+			  0xf9,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x13, 0x13,
+	0x10, 0x03, 0x01, 0x06,
+	0x10, 0x41, 0x11, 0x00, 0x64, 0x99, 0xc0, 0xe2, 0xf9, 0xf9, 0xf9,
+			  0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+			  0xf9,
+	0x10, 0x0b, 0x01, 0x08,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x1f,
+	0x04, 0x06, 0x01, 0xc3,
+	0x04, 0x05, 0x01, 0x40,
+	0x04, 0x04, 0x01, 0x40,
+	0, 0, 0
+};
+/* et31x110 - pas106 - other Trust SpaceCam120 */
+static const u8 spacecam2_start[] = {
+	0x04, 0x06, 0x01, 0x44,
+	0x04, 0x06, 0x01, 0x00,
+	0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
+			  0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
+			  0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
+			  0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+			  0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
+	0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x13, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
+			  0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+			  0x01, 0x60, 0x01, 0x00, 0x00,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x04, 0x04, 0x01, 0x40,
+	0x04, 0x04, 0x01, 0x00,
+	I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x05,
+			  0x00, 0x00, 0x05, 0x05,
+	I2C0, 0x40, 0x02, 0x11, 0x06,
+	I2C0, 0x40, 0x02, 0x14, 0x00,
+	I2C0, 0x40, 0x02, 0x13, 0x01,		/* i2c end */
+	0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+			  0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+			  0x40,
+	I2C0, 0x40, 0x02, 0x02, 0x0c,		/* pixel clock */
+	I2C0, 0x40, 0x02, 0x0f, 0x00,
+	I2C0, 0x40, 0x02, 0x13, 0x01,		/* i2c end */
+	0x10, 0x00, 0x01, 0x01,
+	0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+			  0x20, 0x01, 0x60, 0x01,
+	I2C0, 0x40, 0x02, 0x05, 0x0f,		/* exposure */
+	I2C0, 0x40, 0x02, 0x13, 0x01,		/* i2c end */
+	I2C0, 0x40, 0x07, 0x09, 0x0b, 0x0f, 0x05, 0x05, 0x0f, 0x00,
+						/* gains */
+	I2C0, 0x40, 0x03, 0x12, 0x04, 0x01,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+			  0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+			  0xf9,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x13, 0x13,
+	0x10, 0x03, 0x01, 0x06,
+	0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+			  0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+			  0xf9,
+	0x10, 0x0b, 0x01, 0x11,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x14,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x05, 0x01, 0x61,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* nw802 - Conceptronic Video Pro */
+static const u8 cvideopro_start[] = {
+	0x04, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
+			  0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+			  0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+			  0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
+	0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+			  0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+			  0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x03,
+	0x10, 0x00, 0x01, 0xac,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x3b, 0x01,
+	0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+	0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+	0x10, 0x1d, 0x02, 0x40, 0x06,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
+			  0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
+			  0xdc,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x12, 0x12,
+	0x10, 0x03, 0x01, 0x0c,
+	0x10, 0x41, 0x11, 0x00, 0x0f, 0x46, 0x62, 0x76, 0x86, 0x94, 0xa0,
+			  0xab, 0xb6, 0xbf, 0xc8, 0xcf, 0xd7, 0xdc, 0xdc,
+			  0xdc,
+	0x10, 0x0b, 0x01, 0x09,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x2f,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* nw802 - D-link dru-350c cam */
+static const u8 dlink_start[] = {
+	0x04, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+			  0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
+			  0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x01, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x00,
+	0x10, 0x00, 0x01, 0xad,
+	0x00, 0x00, 0x01, 0x08,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x51, 0x00, 0xf0, 0x00, 0x3d, 0x00, 0xb4, 0x00,
+	0x10, 0x1d, 0x08, 0x40, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+	0x10, 0x0e, 0x01, 0x20,
+	0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
+			  0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
+			  0xea,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x11, 0x11,
+	0x10, 0x03, 0x01, 0x10,
+	0x10, 0x41, 0x11, 0x00, 0x07, 0x1e, 0x38, 0x4d, 0x60, 0x70, 0x7f,
+			  0x8e, 0x9b, 0xa8, 0xb4, 0xbf, 0xca, 0xd5, 0xdf,
+			  0xea,
+	0x10, 0x0b, 0x01, 0x19,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x1e,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* 06a5:d001 - nw801 - Sony
+ *		Plustek Opticam 500U or ProLink DS3303u (Hitachi HD49322BF) */
+/*fixme: 320x240 only*/
+static const u8 ds3303_start[] = {
+	0x05, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x16, 0x00, 0x00, 0xf9, 0x02, 0x11, 0x00, 0x0e,
+			  0x01, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+			  0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x22, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x08, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa9, 0xa8, 0x1f, 0x00,
+			  0x0d, 0x02, 0x07, 0x00, 0x01, 0x00, 0x19, 0x00,
+			  0xf2, 0x00, 0x18, 0x06, 0x10, 0x06, 0x10, 0x00,
+			  0x36, 0x00,
+	0x02, 0x00, 0x12, 0x03, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0x50,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x05, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x2f, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
+			  0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
+			  0x00, 0x01, 0x15, 0xfd, 0x07, 0x3d, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x8c, 0x04, 0x01, 0x20,
+			  0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00, 0x00,
+			  0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08, 0x03,
+			  0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06, 0xf7,
+	0x10, 0x40, 0x40, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80, 0x80,
+			  0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f, 0x88,
+			  0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4, 0xcb,
+			  0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54, 0x64,
+			  0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2, 0xe2,
+			  0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+	0x10, 0x80, 0x22, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f, 0x01,
+			  0x00, 0x00, 0xef, 0x00, 0x02, 0x0a, 0x82, 0x02,
+			  0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40, 0x01,
+			  0xf0, 0x00,
+
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x3f, 0x00, 0xf2, 0x8f, 0x81,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x15,
+	0x10, 0x00, 0x01, 0x2f,
+	0x10, 0x8c, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+	0x10, 0x26, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+	0x10, 0x24, 0x02, 0x40, 0x06,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
+			  0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+			  0xf9,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x16, 0x16,
+	0x10, 0x03, 0x01, 0x0c,
+	0x10, 0x48, 0x11, 0x00, 0x15, 0x40, 0x67, 0x84, 0x9d, 0xb2, 0xc6,
+			  0xd6, 0xe7, 0xf6, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+			  0xf9,
+	0x10, 0x0b, 0x01, 0x26,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x1c,
+	0x05, 0x06, 0x01, 0x03,
+	0x05, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* 06a5:d001 - nw802 - Panasonic
+ *		GP-KR651US (Philips TDA8786) */
+static const u8 kr651_start_1[] = {
+	0x04, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x48,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
+			  0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+			  0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+			  0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
+	0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+			  0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+			  0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0, 0, 0
+};
+static const u8 kr651_start_qvga[] = {
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x03,
+	0x10, 0x00, 0x01, 0xac,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x29, 0x00, 0x18, 0x01, 0x1f, 0x00, 0xd2, 0x00,
+	0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
+	0x10, 0x1d, 0x02, 0x28, 0x01,
+	0, 0, 0
+};
+static const u8 kr651_start_vga[] = {
+	0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x30, 0x03, 0x01, 0x82, 0x82, 0x98,
+			  0x80,
+	0x10, 0x1a, 0x01, 0x03,
+	0x10, 0x00, 0x01, 0xa0,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x51, 0x00, 0x30, 0x02, 0x3d, 0x00, 0xa4, 0x01,
+	0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
+	0x10, 0x1d, 0x02, 0x68, 0x00,
+};
+static const u8 kr651_start_2[] = {
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
+			  0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+			  0xdc,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x0c, 0x0c,
+	0x10, 0x03, 0x01, 0x0c,
+	0x10, 0x41, 0x11, 0x00, 0x11, 0x3c, 0x5c, 0x74, 0x88, 0x99, 0xa8,
+			  0xb7, 0xc4, 0xd0, 0xdc, 0xdc, 0xdc, 0xdc, 0xdc,
+			  0xdc,
+	0x10, 0x0b, 0x01, 0x10,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x2d,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* nw802 - iRez Kritter cam */
+static const u8 kritter_start[] = {
+	0x04, 0x06, 0x01, 0x06,
+	0x00, 0x00, 0x40, 0x44, 0x96, 0x98, 0x94, 0x03, 0x18, 0x00, 0x48,
+			  0x0f, 0x1e, 0x00, 0x0c, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x0b, 0x00, 0x1b, 0x00, 0x0a, 0x01, 0x28,
+			  0x07, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+			  0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+			  0x00, 0x5d, 0x00, 0x0e, 0x00, 0x7e, 0x00, 0x30,
+	0x00, 0x80, 0x1f, 0x18, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+			  0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0b, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x02, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+			  0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x8c, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x03,
+	0x10, 0x00, 0x01, 0xaf,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x3b, 0x01,
+	0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+	0x10, 0x1d, 0x06, 0xe0, 0x00, 0x0c, 0x00, 0x52, 0x00,
+	0x10, 0x1d, 0x02, 0x00, 0x00,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
+			  0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
+			  0xcb,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x0d, 0x0d,
+	0x10, 0x03, 0x01, 0x02,
+	0x10, 0x41, 0x11, 0x00, 0x0d, 0x36, 0x4e, 0x60, 0x6f, 0x7b, 0x86,
+			  0x90, 0x98, 0xa1, 0xa9, 0xb1, 0xb7, 0xbe, 0xc4,
+			  0xcb,
+	0x10, 0x0b, 0x01, 0x17,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x1e,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* nw802 - Mustek Wcam 300 mini */
+static const u8 mustek_start[] = {
+	0x04, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x10, 0x00, 0x00, 0x92, 0x03, 0x10, 0x00, 0x4d,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0xce, 0x00, 0xf4,
+			  0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x3f, 0x0f, 0x88, 0x20, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x01, 0x00, 0x16, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0xfc, 0x05, 0x0c, 0x06,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa1, 0x02, 0x80, 0x00, 0x13, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0xc0, 0x00, 0x14,
+			  0x02, 0x00, 0x01, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x00,
+	0x10, 0x00, 0x01, 0xad,
+	0x00, 0x00, 0x01, 0x08,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1d, 0x08, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20, 0x00, 0x20,
+	0x10, 0x0e, 0x01, 0x0f,
+	0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
+			  0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
+			  0xff,
+	0x10, 0x0f, 0x02, 0x11, 0x11,
+	0x10, 0x03, 0x01, 0x0c,
+	0x10, 0x41, 0x11, 0x00, 0x0f, 0x29, 0x4a, 0x64, 0x7a, 0x8c, 0x9e,
+			  0xad, 0xba, 0xc7, 0xd3, 0xde, 0xe8, 0xf1, 0xf9,
+			  0xff,
+	0x10, 0x0b, 0x01, 0x1c,
+	0x10, 0x0d, 0x01, 0x1a,
+	0x10, 0x0c, 0x01, 0x34,
+	0x04, 0x05, 0x01, 0x61,
+	0x04, 0x04, 0x01, 0x40,
+	0x04, 0x06, 0x01, 0x03,
+	0, 0, 0
+};
+
+/* nw802 - Scope USB Microscope M2 (ProScope) (Hitachi HD49322BF) */
+static const u8 proscope_init[] = {
+	0x04, 0x05, 0x01, 0x21,
+	0x04, 0x04, 0x01, 0x01,
+	0, 0, 0
+};
+static const u8 proscope_start_1[] = {
+	0x04, 0x06, 0x01, 0x04,
+	0x00, 0x00, 0x40, 0x10, 0x01, 0x00, 0xf9, 0x02, 0x10, 0x00, 0x04,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x08, 0x00, 0x17, 0x00, 0xce, 0x00, 0xf4,
+			  0x05, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0xce, 0x00, 0xf8, 0x03, 0x3e, 0x00, 0x86,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0xb6,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xf6, 0x03, 0x34, 0x04, 0xf6, 0x03, 0x34,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xe8,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xb4, 0x6f, 0x1f, 0x0f, 0x08, 0x20, 0xa8, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x01, 0x00, 0x19, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x10, 0x00, 0x36, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x21, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xad, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x1f, 0x10, 0x08, 0x0a,
+			  0x0a, 0x51, 0x00, 0xf1, 0x00, 0x3c, 0x00, 0xb4,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0x8c, 0x04, 0x01,
+			  0x20, 0x02, 0x00, 0x03, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x2d, 0x46, 0x58, 0x67, 0x74, 0x7f,
+			  0x88, 0x94, 0x9d, 0xa6, 0xae, 0xb5, 0xbd, 0xc4,
+			  0xcb, 0xd1, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x3f,
+			  0x01, 0x00, 0x00, 0xef, 0x00, 0x09, 0x05, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0, 0, 0
+};
+static const u8 proscope_start_qvga[] = {
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x9e, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x10, 0x02, 0xf2, 0x8f, 0x78,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x06,
+	0x00, 0x03, 0x02, 0xf9, 0x02,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+	0x10, 0x0e, 0x01, 0x10,
+	0, 0, 0
+};
+static const u8 proscope_start_vga[] = {
+	0x00, 0x03, 0x02, 0xf9, 0x02,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+	0x02, 0x00, 0x11, 0x78, 0xa0, 0x8c, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x16, 0x00, 0x00, 0x82, 0x84, 0x00,
+			  0x80,
+	0x10, 0x1a, 0x01, 0x06,
+	0x10, 0x00, 0x01, 0xa1,
+	0x10, 0x1b, 0x02, 0x00, 0x00,
+	0x10, 0x1d, 0x08, 0xc0, 0x0d, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x7f, 0x02, 0x00, 0x00, 0xdf, 0x01,
+	0x10, 0x0e, 0x01, 0x10,
+	0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
+			  0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
+			  0xf9,
+	0x10, 0x03, 0x01, 0x00,
+	0, 0, 0
+};
+static const u8 proscope_start_2[] = {
+	0x10, 0x0f, 0x02, 0x0c, 0x0c,
+	0x10, 0x03, 0x01, 0x0c,
+	0x10, 0x41, 0x11, 0x00, 0x10, 0x51, 0x6e, 0x83, 0x93, 0xa1, 0xae,
+			  0xb9, 0xc3, 0xcc, 0xd4, 0xdd, 0xe4, 0xeb, 0xf2,
+			  0xf9,
+	0x10, 0x0b, 0x01, 0x0b,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x1b,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x05, 0x01, 0x21,
+	0x04, 0x04, 0x01, 0x00,
+	0, 0, 0
+};
+
+/* nw800 - hv7121b? (seems pas106) - Divio Chicony TwinkleCam */
+static const u8 twinkle_start[] = {
+	0x04, 0x06, 0x01, 0x44,
+	0x04, 0x06, 0x01, 0x00,
+	0x00, 0x00, 0x40, 0x14, 0x83, 0x00, 0xba, 0x01, 0x10, 0x00, 0x4f,
+			  0xef, 0x00, 0x00, 0x60, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x06, 0x00, 0xfc,
+			  0x01, 0x3e, 0x00, 0x86, 0x00, 0x3e, 0x00, 0x86,
+			  0x00, 0x3e, 0x00, 0x86, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x56, 0x00, 0x9e,
+			  0x00, 0x56, 0x00, 0x9e, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x6e, 0x00, 0xb6, 0x00, 0x6e, 0x00, 0x78,
+			  0x04, 0x6e, 0x00, 0xb6, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xca, 0x03, 0x46, 0x04, 0xca, 0x03, 0x46,
+			  0x04, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x3e, 0x00, 0xf0,
+			  0x00, 0x3e, 0x00, 0xaa, 0x00, 0x88, 0x00, 0x2e,
+	0x00, 0x80, 0x1f, 0xb8, 0x48, 0x0f, 0x04, 0x88, 0x14, 0x68, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0xa8, 0x01, 0x00, 0x03,
+			  0x00, 0x24, 0x01, 0x01, 0x00, 0x16, 0x00, 0x04,
+			  0x00, 0x4b, 0x00, 0x76, 0x00, 0x86, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0x61, 0x00,
+	0x05, 0x00, 0x06, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x06, 0x00, 0x1b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0x80, 0x02, 0x20, 0x00, 0x11, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x08,
+			  0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x10, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x00, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1d, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x62,
+			  0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01, 0x20,
+			  0x01, 0x60, 0x01, 0x00, 0x00,
+
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	0x04, 0x04, 0x01, 0x10,
+	0x04, 0x04, 0x01, 0x00,
+	0x04, 0x05, 0x01, 0x61,
+	0x04, 0x04, 0x01, 0x01,
+	I2C0, 0x40, 0x0c, 0x02, 0x0c, 0x12, 0x07, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x0a,
+	I2C0, 0x40, 0x02, 0x11, 0x06,
+	I2C0, 0x40, 0x02, 0x14, 0x00,
+	I2C0, 0x40, 0x02, 0x13, 0x01,		/* i2c end */
+	I2C0, 0x40, 0x02, 0x07, 0x01,
+	0x02, 0x00, 0x11, 0x48, 0x58, 0x9e, 0x48, 0x58, 0x00, 0x00, 0x00,
+			  0x00, 0x84, 0x36, 0x05, 0x01, 0xf2, 0x86, 0x65,
+			  0x40,
+	I2C0, 0x40, 0x02, 0x02, 0x0c,
+	I2C0, 0x40, 0x02, 0x13, 0x01,
+	0x10, 0x00, 0x01, 0x01,
+	0x10, 0x8f, 0x0c, 0x62, 0x01, 0x24, 0x01, 0x62, 0x01, 0x24, 0x01,
+			  0x20, 0x01, 0x60, 0x01,
+	I2C0, 0x40, 0x02, 0x05, 0x0f,
+	I2C0, 0x40, 0x02, 0x13, 0x01,
+	I2C0, 0x40, 0x08, 0x08, 0x04, 0x0b, 0x01, 0x01, 0x02, 0x00, 0x17,
+	I2C0, 0x40, 0x03, 0x12, 0x00, 0x01,
+	0x10, 0x11, 0x08, 0x00, 0x00, 0x5f, 0x01, 0x00, 0x00, 0x1f, 0x01,
+	I2C0, 0x40, 0x02, 0x12, 0x00,
+	I2C0, 0x40, 0x02, 0x0e, 0x00,
+	I2C0, 0x40, 0x02, 0x11, 0x06,
+	0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+			  0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+			  0xf9,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x0c, 0x0c,
+	0x10, 0x03, 0x01, 0x06,
+	0x10, 0x41, 0x11, 0x00, 0x17, 0x3f, 0x69, 0x7b, 0x8c, 0x9a, 0xa7,
+			  0xb3, 0xbf, 0xc9, 0xd3, 0xdd, 0xe6, 0xef, 0xf7,
+			  0xf9,
+	0x10, 0x0b, 0x01, 0x19,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x0d,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x05, 0x01, 0x61,
+	0x04, 0x04, 0x01, 0x41,
+	0, 0, 0
+};
+
+/* nw802 dvc-v6 */
+static const u8 dvcv6_start[] = {
+	0x04, 0x06, 0x01, 0x06,
+	0x00, 0x00, 0x40, 0x54, 0x96, 0x98, 0xf9, 0x02, 0x18, 0x00, 0x4c,
+			  0x0f, 0x1f, 0x00, 0x0d, 0x02, 0x01, 0x00, 0x19,
+			  0x00, 0x01, 0x00, 0x19, 0x00, 0x01, 0x00, 0x19,
+			  0x00, 0x0b, 0x00, 0x1b, 0x00, 0xc8, 0x00, 0xf4,
+			  0x05, 0xb4, 0x00, 0xcc, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa2, 0x00, 0xc6, 0x00, 0x60, 0x00, 0xc6,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+	0x00, 0x40, 0x40, 0x00, 0xae, 0x00, 0xd2, 0x00, 0xae, 0x00, 0xd2,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0xa8, 0x00, 0xc0, 0x00, 0x66, 0x00, 0xc0,
+			  0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01,
+			  0x00, 0x0a, 0x00, 0x54, 0x00, 0x0a, 0x00, 0x54,
+			  0x00, 0x10, 0x00, 0x36, 0x00, 0xd2, 0x00, 0xee,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf6,
+			  0x00, 0x5d, 0x00, 0xc7, 0x00, 0x7e, 0x00, 0x30,
+	0x00, 0x80, 0x1f, 0x98, 0x43, 0x3f, 0x0d, 0x88, 0x20, 0x80, 0x3f,
+			  0x47, 0xaf, 0x00, 0x00, 0xa8, 0x08, 0x00, 0x11,
+			  0x00, 0x0c, 0x02, 0x0c, 0x00, 0x1c, 0x00, 0x94,
+			  0x00, 0x10, 0x06, 0x24, 0x00, 0x4a, 0x00,
+	0x02, 0x00, 0x12, 0x78, 0xa0, 0x9e, 0x78, 0xa0, 0x00, 0x00, 0x00,
+			  0x00, 0xf0, 0x18, 0x0b, 0x06, 0x62, 0x82, 0xa0,
+			  0x40, 0x20,
+	0x03, 0x00, 0x03, 0x03, 0x00, 0x00,
+	0x04, 0x00, 0x07, 0x01, 0x10, 0x00, 0x00, 0x00, 0xff, 0x00,
+	0x06, 0x00, 0x02, 0x09, 0x99,
+	0x08, 0x00, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x40, 0xa0, 0x02, 0x80, 0x00, 0x12, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x10, 0x10, 0x10, 0x08, 0x0a,
+			  0x0a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+			  0x00, 0x49, 0x13, 0x00, 0x00, 0xe0, 0x00, 0x0c,
+			  0x00, 0x52, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00,
+			  0x00, 0x20, 0x00, 0x00, 0x00, 0x20, 0x10, 0x08,
+			  0x03, 0x00, 0x00, 0x00, 0x00, 0x20, 0x10, 0x06,
+			  0xf7, 0xee, 0x1c, 0x1c, 0xe9, 0xfc, 0x10, 0x80,
+	0x10, 0x40, 0x40, 0x80, 0x00, 0x05, 0x35, 0x5e, 0x78, 0x8b, 0x99,
+			  0xa4, 0xae, 0xb5, 0xbc, 0xc1, 0xc6, 0xc9, 0xcc,
+			  0xcf, 0xd0, 0x00, 0x11, 0x22, 0x32, 0x43, 0x54,
+			  0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3, 0xd2,
+			  0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32, 0x43,
+			  0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3, 0xc3,
+			  0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x11, 0x22, 0x32,
+			  0x43, 0x54, 0x64, 0x74, 0x84, 0x94, 0xa4, 0xb3,
+	0x10, 0x80, 0x1b, 0xc3, 0xd2, 0xe2, 0xf1, 0xff, 0x00, 0x00, 0x00,
+			  0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x05, 0x82,
+			  0x02, 0xe4, 0x01, 0x40, 0x01, 0xf0, 0x00, 0x40,
+			  0x01, 0xf0, 0x00,
+	0x00, 0x03, 0x02, 0x94, 0x03,
+	0x00, 0x1d, 0x04, 0x0a, 0x01, 0x28, 0x07,
+	0x00, 0x7b, 0x02, 0xe0, 0x00,
+	0x10, 0x8d, 0x01, 0x00,
+	0x00, 0x09, 0x04, 0x1e, 0x00, 0x0c, 0x02,
+	0x00, 0x91, 0x02, 0x0b, 0x02,
+	0x10, 0x00, 0x01, 0xaf,
+	0x02, 0x00, 0x11, 0x3c, 0x50, 0x8f, 0x3c, 0x50, 0x00, 0x00, 0x00,
+			  0x00, 0x78, 0x3f, 0x3f, 0x06, 0xf2, 0x8f, 0xf0,
+			  0x40,
+	0x10, 0x1a, 0x01, 0x02,
+	0x10, 0x00, 0x01, 0xaf,
+	0x10, 0x85, 0x08, 0x00, 0x00, 0x3f, 0x01, 0x00, 0x00, 0xef, 0x00,
+	0x10, 0x1b, 0x02, 0x07, 0x01,
+	0x10, 0x11, 0x08, 0x61, 0x00, 0xe0, 0x00, 0x49, 0x00, 0xa8, 0x00,
+	0x10, 0x1f, 0x06, 0x01, 0x20, 0x02, 0xe8, 0x03, 0x00,
+	0x10, 0x1d, 0x02, 0x40, 0x06,
+	0x10, 0x0e, 0x01, 0x08,
+	0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
+			  0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
+			  0xdc,
+	0x10, 0x03, 0x01, 0x00,
+	0x10, 0x0f, 0x02, 0x12, 0x12,
+	0x10, 0x03, 0x01, 0x11,
+	0x10, 0x41, 0x11, 0x00, 0x0f, 0x54, 0x6f, 0x82, 0x91, 0x9f, 0xaa,
+			  0xb4, 0xbd, 0xc5, 0xcd, 0xd5, 0xdb, 0xdc, 0xdc,
+			  0xdc,
+	0x10, 0x0b, 0x01, 0x16,
+	0x10, 0x0d, 0x01, 0x10,
+	0x10, 0x0c, 0x01, 0x1a,
+	0x04, 0x06, 0x01, 0x03,
+	0x04, 0x04, 0x01, 0x00,
+};
+
+static const u8 *webcam_start[] = {
+	[Generic800] = nw800_start,
+	[SpaceCam] = spacecam_start,
+	[SpaceCam2] = spacecam2_start,
+	[Cvideopro] = cvideopro_start,
+	[Dlink350c] = dlink_start,
+	[DS3303u] = ds3303_start,
+	[Kr651us] = kr651_start_1,
+	[Kritter] = kritter_start,
+	[Mustek300] = mustek_start,
+	[Proscope] = proscope_start_1,
+	[Twinkle] = twinkle_start,
+	[DvcV6] = dvcv6_start,
+	[P35u] = nw801_start_1,
+	[Generic802] = nw802_start,
+};
+
+/* -- write a register -- */
+static void reg_w(struct gspca_dev *gspca_dev,
+			u16 index,
+			const u8 *data,
+			int len)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	if (len == 1)
+		PDEBUG(D_USBO, "SET 00 0000 %04x %02x", index, *data);
+	else
+		PDEBUG(D_USBO, "SET 00 0000 %04x %02x %02x ...",
+				index, *data, data[1]);
+	memcpy(gspca_dev->usb_buf, data, len);
+	ret = usb_control_msg(dev, usb_sndctrlpipe(dev, 0),
+			0x00,
+			USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0x00,		/* value */
+			index,
+			gspca_dev->usb_buf,
+			len,
+			500);
+	if (ret < 0) {
+		err("reg_w err %d", ret);
+		gspca_dev->usb_err = ret;
+	}
+}
+
+/* -- read registers in usb_buf -- */
+static void reg_r(struct gspca_dev *gspca_dev,
+			u16 index,
+			int len)
+{
+	struct usb_device *dev = gspca_dev->dev;
+	int ret;
+
+	if (gspca_dev->usb_err < 0)
+		return;
+	ret = usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+			0x00,
+			USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			0x00, index,
+			gspca_dev->usb_buf, len, 500);
+	if (ret < 0) {
+		err("reg_r err %d", ret);
+		gspca_dev->usb_err = ret;
+		return;
+	}
+	if (len == 1)
+		PDEBUG(D_USBI, "GET 00 0000 %04x %02x",
+				index, gspca_dev->usb_buf[0]);
+	else
+		PDEBUG(D_USBI, "GET 00 0000 %04x %02x %02x ..",
+				index, gspca_dev->usb_buf[0],
+				gspca_dev->usb_buf[1]);
+}
+
+static void i2c_w(struct gspca_dev *gspca_dev,
+			u8 i2c_addr,
+			const u8 *data,
+			int len)
+{
+	u8 val[2];
+	int i;
+
+	reg_w(gspca_dev, 0x0600, data + 1, len - 1);
+	reg_w(gspca_dev, 0x0600, data, len);
+	val[0] = len;
+	val[1] = i2c_addr;
+	reg_w(gspca_dev, 0x0502, val, 2);
+	val[0] = 0x01;
+	reg_w(gspca_dev, 0x0501, val, 1);
+	for (i = 5; --i >= 0; ) {
+		msleep(4);
+		reg_r(gspca_dev, 0x0505, 1);
+		if (gspca_dev->usb_err < 0)
+			return;
+		if (gspca_dev->usb_buf[0] == 0)
+			return;
+	}
+	gspca_dev->usb_err = -ETIME;
+}
+
+static void reg_w_buf(struct gspca_dev *gspca_dev,
+			const u8 *cmd)
+{
+	u16 reg;
+	int len;
+
+	for (;;) {
+		reg = *cmd++ << 8;
+		reg += *cmd++;
+		len = *cmd++;
+		if (len == 0)
+			break;
+		if (cmd[-3] != I2C0)
+			reg_w(gspca_dev, reg, cmd, len);
+		else
+			i2c_w(gspca_dev, reg, cmd, len);
+		cmd += len;
+	}
+}
+
+static int swap_bits(int v)
+{
+	int r, i;
+
+	r = 0;
+	for (i = 0; i < 8; i++) {
+		r <<= 1;
+		if (v & 1)
+			r++;
+		v >>= 1;
+	}
+	return r;
+}
+
+static void setgain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val, v[2];
+
+	val = sd->ctrls[GAIN].val;
+	switch (sd->webcam) {
+	case P35u:
+		/* Note the control goes from 0-255 not 0-127, but anything
+		   above 127 just means amplifying noise */
+		val >>= 1;			/* 0 - 255 -> 0 - 127 */
+		reg_w(gspca_dev, 0x1026, &val, 1);
+		break;
+	case Kr651us:
+		/* 0 - 253 */
+		val = swap_bits(val);
+		v[0] = val << 3;
+		v[1] = val >> 5;
+		reg_w(gspca_dev, 0x101d, v, 2);	/* SIF reg0/1 (AGC) */
+		break;
+	}
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	s16 val;
+	u8 v[2];
+
+	val = sd->ctrls[EXPOSURE].val;
+	switch (sd->webcam) {
+	case P35u:
+		v[0] = ((9 - val) << 3) | 0x01;
+		reg_w(gspca_dev, 0x1019, v, 1);
+		break;
+	case Cvideopro:
+	case DvcV6:
+	case Kritter:
+	case Kr651us:
+		v[0] = val;
+		v[1] = val >> 8;
+		reg_w(gspca_dev, 0x101b, v, 2);
+		break;
+	}
+}
+
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int w, h;
+
+	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN))
+		return;
+	if (!sd->ctrls[AUTOGAIN].val) {
+		sd->ag_cnt = -1;
+		return;
+	}
+	sd->ag_cnt = AG_CNT_START;
+
+	reg_r(gspca_dev, 0x1004, 1);
+	if (gspca_dev->usb_buf[0] & 0x04) {	/* if AE_FULL_FRM */
+		sd->ae_res = gspca_dev->width * gspca_dev->height;
+	} else {				/* get the AE window size */
+		reg_r(gspca_dev, 0x1011, 8);
+		w = (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0]
+		  - (gspca_dev->usb_buf[3] << 8) - gspca_dev->usb_buf[2];
+		h = (gspca_dev->usb_buf[5] << 8) + gspca_dev->usb_buf[4]
+		  - (gspca_dev->usb_buf[7] << 8) - gspca_dev->usb_buf[6];
+		sd->ae_res = h * w;
+		if (sd->ae_res == 0)
+			sd->ae_res = gspca_dev->width * gspca_dev->height;
+	}
+}
+
+static int nw802_test_reg(struct gspca_dev *gspca_dev,
+			u16 index,
+			u8 value)
+{
+	/* write the value */
+	reg_w(gspca_dev, index, &value, 1);
+
+	/* read it */
+	reg_r(gspca_dev, index, 1);
+
+	return gspca_dev->usb_buf[0] == value;
+}
+
+/* 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;
+
+	if ((unsigned) webcam >= NWEBCAMS)
+		webcam = 0;
+	sd->webcam = webcam;
+	gspca_dev->cam.reverse_alts = 1;
+	gspca_dev->cam.ctrls = sd->ctrls;
+	sd->ag_cnt = -1;
+
+	/*
+	 * Autodetect sequence inspired from some log.
+	 * We try to detect what registers exist or not.
+	 * If 0x0500 does not exist => NW802
+	 * If it does, test 0x109b. If it doesn't exist,
+	 * then it's a NW801. Else, a NW800
+	 * If a et31x110 (nw800 and 06a5:d800)
+	 *	get the sensor ID
+	 */
+	if (!nw802_test_reg(gspca_dev, 0x0500, 0x55)) {
+		sd->bridge = BRIDGE_NW802;
+		if (sd->webcam == Generic800)
+			sd->webcam = Generic802;
+	} else if (!nw802_test_reg(gspca_dev, 0x109b, 0xaa)) {
+		sd->bridge = BRIDGE_NW801;
+		if (sd->webcam == Generic800)
+			sd->webcam = P35u;
+	} else if (id->idVendor == 0x06a5 && id->idProduct == 0xd800) {
+		reg_r(gspca_dev, 0x0403, 1);		/* GPIO */
+		PDEBUG(D_PROBE, "et31x110 sensor type %02x",
+				gspca_dev->usb_buf[0]);
+		switch (gspca_dev->usb_buf[0] >> 1) {
+		case 0x00:				/* ?? */
+			if (sd->webcam == Generic800)
+				sd->webcam = SpaceCam;
+			break;
+		case 0x01:				/* Hynix? */
+			if (sd->webcam == Generic800)
+				sd->webcam = Twinkle;
+			break;
+		case 0x0a:				/* Pixart */
+			if (sd->webcam == Generic800)
+				sd->webcam = SpaceCam2;
+			break;
+		}
+	}
+	if (webcam_chip[sd->webcam] != sd->bridge) {
+		err("Bad webcam type %d for NW80%d", sd->webcam, sd->bridge);
+		gspca_dev->usb_err = -ENODEV;
+		return gspca_dev->usb_err;
+	}
+	PDEBUG(D_PROBE, "Bridge nw80%d - type: %d", sd->bridge, sd->webcam);
+
+	if (sd->bridge == BRIDGE_NW800) {
+		switch (sd->webcam) {
+		case DS3303u:
+			gspca_dev->cam.cam_mode = cif_mode;	/* qvga */
+			break;
+		default:
+			gspca_dev->cam.cam_mode = &cif_mode[1];	/* cif */
+			break;
+		}
+		gspca_dev->cam.nmodes = 1;
+	} else {
+		gspca_dev->cam.cam_mode = vga_mode;
+		switch (sd->webcam) {
+		case Kr651us:
+		case Proscope:
+		case P35u:
+			gspca_dev->cam.nmodes = ARRAY_SIZE(vga_mode);
+			break;
+		default:
+			gspca_dev->cam.nmodes = 1;	/* qvga only */
+			break;
+		}
+	}
+	switch (sd->webcam) {
+	case P35u:
+/*		sd->ctrls[EXPOSURE].max = 9;
+ *		sd->ctrls[EXPOSURE].def = 9; */
+		/* coarse expo auto gain function gain minimum, to avoid
+		 * a large settings jump the first auto adjustment */
+		sd->ctrls[GAIN].def = 255 / 5 * 2;
+		break;
+	case Cvideopro:
+	case DvcV6:
+	case Kritter:
+		gspca_dev->ctrl_dis = (1 << GAIN) | (1 << AUTOGAIN);
+		/* fall thru */
+	case Kr651us:
+		sd->ctrls[EXPOSURE].max = 315;
+		sd->ctrls[EXPOSURE].def = 150;
+		break;
+	default:
+		gspca_dev->ctrl_dis = (1 << GAIN) | (1 << EXPOSURE)
+					 | (1 << AUTOGAIN);
+		break;
+	}
+
+#if AUTOGAIN_DEF
+	if (!(gspca_dev->ctrl_dis & (1 << AUTOGAIN)))
+		gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
+#endif
+	return gspca_dev->usb_err;
+}
+
+/* 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;
+
+	switch (sd->bridge) {
+	case BRIDGE_NW800:
+		switch (sd->webcam) {
+		case SpaceCam:
+			reg_w_buf(gspca_dev, spacecam_init);
+			break;
+		default:
+			reg_w_buf(gspca_dev, nw800_init);
+			break;
+		}
+		break;
+	default:
+		switch (sd->webcam) {
+		case Mustek300:
+		case P35u:
+		case Proscope:
+			reg_w_buf(gspca_dev, proscope_init);
+			break;
+		}
+		break;
+	}
+	return gspca_dev->usb_err;
+}
+
+/* -- start the camera -- */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	const u8 *cmd;
+
+	cmd = webcam_start[sd->webcam];
+	reg_w_buf(gspca_dev, cmd);
+	switch (sd->webcam) {
+	case P35u:
+		if (gspca_dev->width == 320)
+			reg_w_buf(gspca_dev, nw801_start_qvga);
+		else
+			reg_w_buf(gspca_dev, nw801_start_vga);
+		reg_w_buf(gspca_dev, nw801_start_2);
+		break;
+	case Kr651us:
+		if (gspca_dev->width == 320)
+			reg_w_buf(gspca_dev, kr651_start_qvga);
+		else
+			reg_w_buf(gspca_dev, kr651_start_vga);
+		reg_w_buf(gspca_dev, kr651_start_2);
+		break;
+	case Proscope:
+		if (gspca_dev->width == 320)
+			reg_w_buf(gspca_dev, proscope_start_qvga);
+		else
+			reg_w_buf(gspca_dev, proscope_start_vga);
+		reg_w_buf(gspca_dev, proscope_start_2);
+		break;
+	}
+
+	setgain(gspca_dev);
+	setexposure(gspca_dev);
+	setautogain(gspca_dev);
+	sd->exp_too_high_cnt = 0;
+	sd->exp_too_low_cnt = 0;
+	return gspca_dev->usb_err;
+}
+
+static void sd_stopN(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	u8 value;
+
+	/* 'go' off */
+	if (sd->bridge != BRIDGE_NW801) {
+		value = 0x02;
+		reg_w(gspca_dev, 0x0406, &value, 1);
+	}
+
+	/* LED off */
+	switch (sd->webcam) {
+	case Cvideopro:
+	case Kr651us:
+	case DvcV6:
+	case Kritter:
+		value = 0xff;
+		break;
+	case Dlink350c:
+		value = 0x21;
+		break;
+	case SpaceCam:
+	case SpaceCam2:
+	case Proscope:
+	case Twinkle:
+		value = 0x01;
+		break;
+	default:
+		return;
+	}
+	reg_w(gspca_dev, 0x0404, &value, 1);
+}
+
+static void sd_pkt_scan(struct gspca_dev *gspca_dev,
+			u8 *data,			/* isoc packet */
+			int len)			/* iso packet length */
+{
+	/*
+	 * frame header = '00 00 hh ww ss xx ff ff'
+	 * with:
+	 *	- 'hh': height / 4
+	 *	- 'ww': width / 4
+	 *	- 'ss': frame sequence number c0..dd
+	 */
+	if (data[0] == 0x00 && data[1] == 0x00
+	 && data[6] == 0xff && data[7] == 0xff) {
+		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+		gspca_frame_add(gspca_dev, FIRST_PACKET, data + 8, len - 8);
+	} else {
+		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+	}
+}
+
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->ctrls[AUTOGAIN].val = val;
+	if (val)
+		gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
+	else
+		gspca_dev->ctrl_inac = 0;
+	if (gspca_dev->streaming)
+		setautogain(gspca_dev);
+	return gspca_dev->usb_err;
+}
+
+#include "autogain_functions.h"
+
+static void do_autogain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int luma;
+
+	if (sd->ag_cnt < 0)
+		return;
+	if (--sd->ag_cnt >= 0)
+		return;
+	sd->ag_cnt = AG_CNT_START;
+
+	/* get the average luma */
+	reg_r(gspca_dev, sd->bridge == BRIDGE_NW801 ? 0x080d : 0x080c, 4);
+	luma = (gspca_dev->usb_buf[3] << 24) + (gspca_dev->usb_buf[2] << 16)
+		+ (gspca_dev->usb_buf[1] << 8) + gspca_dev->usb_buf[0];
+	luma /= sd->ae_res;
+
+	switch (sd->webcam) {
+	case P35u:
+		coarse_grained_expo_autogain(gspca_dev, luma, 100, 5);
+		break;
+	default:
+		auto_gain_n_exposure(gspca_dev, luma, 100, 5, 230, 0);
+		break;
+	}
+}
+
+/* V4L2 controls supported by the driver */
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[GAIN] = {
+	    {
+		.id      = V4L2_CID_GAIN,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gain",
+		.minimum = 0,
+		.maximum = 253,
+		.step    = 1,
+		.default_value = 128
+	    },
+	    .set_control = setgain
+	},
+[EXPOSURE] = {
+	    {
+		.id      = V4L2_CID_EXPOSURE,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Exposure",
+		.minimum = 0,
+		.maximum = 9,
+		.step    = 1,
+		.default_value = 9
+	    },
+	    .set_control = setexposure
+	},
+[AUTOGAIN] = {
+	    {
+		.id      = V4L2_CID_AUTOGAIN,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Auto Gain",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = AUTOGAIN_DEF,
+		.flags   = V4L2_CTRL_FLAG_UPDATE
+	    },
+	    .set = sd_setautogain
+	},
+};
+
+/* 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,
+	.pkt_scan = sd_pkt_scan,
+	.dq_callback = do_autogain,
+};
+
+/* -- module initialisation -- */
+static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x046d, 0xd001)},
+	{USB_DEVICE(0x0502, 0xd001)},
+	{USB_DEVICE(0x052b, 0xd001)},
+	{USB_DEVICE(0x055f, 0xd001)},
+	{USB_DEVICE(0x06a5, 0x0000)},
+	{USB_DEVICE(0x06a5, 0xd001)},
+	{USB_DEVICE(0x06a5, 0xd800)},
+	{USB_DEVICE(0x06be, 0xd001)},
+	{USB_DEVICE(0x0728, 0xd001)},
+	{}
+};
+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 struct usb_driver sd_driver = {
+	.name = MODULE_NAME,
+	.id_table = device_table,
+	.probe = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	return usb_register(&sd_driver);
+}
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
+
+module_param(webcam, int, 0644);
+MODULE_PARM_DESC(webcam,
+	"Webcam type\n"
+	"0: generic\n"
+	"1: Trust 120 SpaceCam\n"
+	"2: other Trust 120 SpaceCam\n"
+	"3: Conceptronic Video Pro\n"
+	"4: D-link dru-350c\n"
+	"5: Plustek Opticam 500U\n"
+	"6: Panasonic GP-KR651US\n"
+	"7: iRez Kritter\n"
+	"8: Mustek Wcam 300 mini\n"
+	"9: Scalar USB Microscope M2 (Proscope)\n"
+	"10: Divio Chicony TwinkleCam\n"
+	"11: DVC-V6\n");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/ov519.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/ov519.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/ov519.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/ov519.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /**
  * OV519 driver
  *
- * Copyright (C) 2008 Jean-Francois Moine (http://moinejf.free.fr)
+ * Copyright (C) 2008-2011 Jean-FranÃ§ois Moine <moinejf@free.fr>
  * Copyright (C) 2009 Hans de Goede <hdegoede@redhat.com>
  *
  * This module is adapted from the ov51x-jpeg package, which itself
@@ -61,10 +61,12 @@
 enum e_ctrl {
 	BRIGHTNESS,
 	CONTRAST,
+	EXPOSURE,
 	COLORS,
 	HFLIP,
 	VFLIP,
 	AUTOBRIGHT,
+	AUTOGAIN,
 	FREQ,
 	NCTRL		/* number of controls */
 };
@@ -118,6 +120,7 @@
 };
 enum sensors {
 	SEN_OV2610,
+	SEN_OV2610AE,
 	SEN_OV3610,
 	SEN_OV6620,
 	SEN_OV6630,
@@ -141,9 +144,11 @@
 /* V4L2 controls supported by the driver */
 static void setbrightness(struct gspca_dev *gspca_dev);
 static void setcontrast(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
 static void setcolors(struct gspca_dev *gspca_dev);
 static void sethvflip(struct gspca_dev *gspca_dev);
 static void setautobright(struct gspca_dev *gspca_dev);
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static void setfreq(struct gspca_dev *gspca_dev);
 static void setfreq_i(struct sd *sd);
 
@@ -172,6 +177,18 @@
 	    },
 	    .set_control = setcontrast,
 	},
+[EXPOSURE] = {
+	    {
+		.id      = V4L2_CID_EXPOSURE,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Exposure",
+		.minimum = 0,
+		.maximum = 255,
+		.step    = 1,
+		.default_value = 127,
+	    },
+	    .set_control = setexposure,
+	},
 [COLORS] = {
 	    {
 		.id      = V4L2_CID_SATURATION,
@@ -221,6 +238,19 @@
 	    },
 	    .set_control = setautobright,
 	},
+[AUTOGAIN] = {
+	    {
+		.id      = V4L2_CID_AUTOGAIN,
+		.type    = V4L2_CTRL_TYPE_BOOLEAN,
+		.name    = "Auto Gain",
+		.minimum = 0,
+		.maximum = 1,
+		.step    = 1,
+		.default_value = 1,
+		.flags	 = V4L2_CTRL_FLAG_UPDATE
+	    },
+	    .set = sd_setautogain,
+	},
 [FREQ] = {
 	    {
 		.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
@@ -237,48 +267,78 @@
 
 /* table of the disabled controls */
 static const unsigned ctrl_dis[] = {
-[SEN_OV2610] =		(1 << NCTRL) - 1,	/* no control */
+[SEN_OV2610] =		((1 << NCTRL) - 1)	/* no control */
+			^ ((1 << EXPOSURE)	/* but exposure */
+			 | (1 << AUTOGAIN)),	/* and autogain */
+
+[SEN_OV2610AE] =	((1 << NCTRL) - 1)	/* no control */
+			^ ((1 << EXPOSURE)	/* but exposure */
+			 | (1 << AUTOGAIN)),	/* and autogain */
 
 [SEN_OV3610] =		(1 << NCTRL) - 1,	/* no control */
 
 [SEN_OV6620] =		(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV6630] =		(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV66308AF] =	(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV7610] =		(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV7620] =		(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV7620AE] =	(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV7640] =		(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << AUTOBRIGHT) |
-			(1 << CONTRAST),
+			(1 << CONTRAST) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV7648] =		(1 << HFLIP) |
 			(1 << VFLIP) |
 			(1 << AUTOBRIGHT) |
-			(1 << CONTRAST),
+			(1 << CONTRAST) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
-[SEN_OV7660] =		(1 << AUTOBRIGHT),
+[SEN_OV7660] =		(1 << AUTOBRIGHT) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV7670] =		(1 << COLORS) |
-			(1 << AUTOBRIGHT),
+			(1 << AUTOBRIGHT) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV76BE] =		(1 << HFLIP) |
-			(1 << VFLIP),
+			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN),
 
 [SEN_OV8610] =		(1 << HFLIP) |
 			(1 << VFLIP) |
+			(1 << EXPOSURE) |
+			(1 << AUTOGAIN) |
 			(1 << FREQ),
 };
 
@@ -321,7 +381,7 @@
    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
+   transferred 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,
@@ -428,6 +488,11 @@
 		.priv = 0},
 };
 static const struct v4l2_pix_format ovfx2_ov2610_mode[] = {
+	{800, 600, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
+		.bytesperline = 800,
+		.sizeimage = 800 * 600,
+		.colorspace = V4L2_COLORSPACE_SRGB,
+		.priv = 1},
 	{1600, 1200, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
 		.bytesperline = 1600,
 		.sizeimage = 1600 * 1200,
@@ -544,6 +609,7 @@
  * buffers, there are some pretty strict real time constraints for
  * isochronous transfer for larger frame sizes).
  */
+/*jfm: this value works well for 1600x1200, but not 800x600 - see isoc_init */
 #define OVFX2_BULK_SIZE (13 * 4096)
 
 /* I2C registers */
@@ -656,6 +722,24 @@
 	{ 0x12, 0x80 },	/* reset */
 };
 
+static const struct ov_i2c_regvals norm_2610ae[] = {
+	{0x12, 0x80},	/* reset */
+	{0x13, 0xcd},
+	{0x09, 0x01},
+	{0x0d, 0x00},
+	{0x11, 0x80},
+	{0x12, 0x20},	/* 1600x1200 */
+	{0x33, 0x0c},
+	{0x35, 0x90},
+	{0x36, 0x37},
+/* ms-win traces */
+	{0x11, 0x83},	/* clock / 3 ? */
+	{0x2d, 0x00},	/* 60 Hz filter */
+	{0x24, 0xb0},	/* normal colors */
+	{0x25, 0x90},
+	{0x10, 0x43},
+};
+
 static const struct ov_i2c_regvals norm_3620b[] = {
 	/*
 	 * From the datasheet: "Note that after writing to register COMH
@@ -2621,6 +2705,9 @@
 	if (high == 0x96 && low == 0x40) {
 		PDEBUG(D_PROBE, "Sensor is an OV2610");
 		sd->sensor = SEN_OV2610;
+	} else if (high == 0x96 && low == 0x41) {
+		PDEBUG(D_PROBE, "Sensor is an OV2610AE");
+		sd->sensor = SEN_OV2610AE;
 	} else if (high == 0x36 && (low & 0x0f) == 0x00) {
 		PDEBUG(D_PROBE, "Sensor is an OV3610");
 		sd->sensor = SEN_OV3610;
@@ -3171,6 +3258,13 @@
 	ov518_i2c_w(sd, OV7670_R11_CLKRC, clock);
 }
 
+static void setautogain(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	i2c_w_mask(sd, 0x13, sd->ctrls[AUTOGAIN].val ? 0x05 : 0x00, 0x05);
+}
+
 /* this function is called at probe time */
 static int sd_config(struct gspca_dev *gspca_dev,
 			const struct usb_device_id *id)
@@ -3295,15 +3389,22 @@
 		}
 		break;
 	case BRIDGE_OVFX2:
-		if (sd->sensor == SEN_OV2610) {
+		switch (sd->sensor) {
+		case SEN_OV2610:
+		case SEN_OV2610AE:
 			cam->cam_mode = ovfx2_ov2610_mode;
 			cam->nmodes = ARRAY_SIZE(ovfx2_ov2610_mode);
-		} else if (sd->sensor == SEN_OV3610) {
+			break;
+		case SEN_OV3610:
 			cam->cam_mode = ovfx2_ov3610_mode;
 			cam->nmodes = ARRAY_SIZE(ovfx2_ov3610_mode);
-		} else if (sd->sif) {
-			cam->cam_mode = ov519_sif_mode;
-			cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
+			break;
+		default:
+			if (sd->sif) {
+				cam->cam_mode = ov519_sif_mode;
+				cam->nmodes = ARRAY_SIZE(ov519_sif_mode);
+			}
+			break;
 		}
 		break;
 	case BRIDGE_W9968CF:
@@ -3325,6 +3426,12 @@
 		/* Enable autogain, autoexpo, awb, bandfilter */
 		i2c_w_mask(sd, 0x13, 0x27, 0x27);
 		break;
+	case SEN_OV2610AE:
+		write_i2c_regvals(sd, norm_2610ae, ARRAY_SIZE(norm_2610ae));
+
+		/* enable autoexpo */
+		i2c_w_mask(sd, 0x13, 0x05, 0x05);
+		break;
 	case SEN_OV3610:
 		write_i2c_regvals(sd, norm_3620b, ARRAY_SIZE(norm_3620b));
 
@@ -3397,6 +3504,22 @@
 	return -EINVAL;
 }
 
+/* function called at start time before URB creation */
+static int sd_isoc_init(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	switch (sd->bridge) {
+	case BRIDGE_OVFX2:
+		if (gspca_dev->width == 1600)
+			gspca_dev->cam.bulk_size = OVFX2_BULK_SIZE;
+		else
+			gspca_dev->cam.bulk_size = 7 * 4096;
+		break;
+	}
+	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)
@@ -3827,6 +3950,25 @@
 		i2c_w_mask(sd, 0x67, qvga ? 0xf0 : 0x90, 0xf0);
 		i2c_w_mask(sd, 0x74, qvga ? 0x20 : 0x00, 0x20);
 		return;
+	case SEN_OV2610AE: {
+		u8 v;
+
+		/* frame rates:
+		 *	10fps / 5 fps for 1600x1200
+		 *	40fps / 20fps for 800x600
+		 */
+		v = 80;
+		if (qvga) {
+			if (sd->frame_rate < 25)
+				v = 0x81;
+		} else {
+			if (sd->frame_rate < 10)
+				v = 0x81;
+		}
+		i2c_w(sd, 0x11, v);
+		i2c_w(sd, 0x12, qvga ? 0x60 : 0x20);
+		return;
+	    }
 	case SEN_OV3610:
 		if (qvga) {
 			xstart = (1040 - gspca_dev->width) / 2 + (0x1f << 4);
@@ -3975,6 +4117,7 @@
 	/* mode setup is fully handled in mode_init_ov_sensor_regs for these */
 	switch (sd->sensor) {
 	case SEN_OV2610:
+	case SEN_OV2610AE:
 	case SEN_OV3610:
 	case SEN_OV7670:
 		mode_init_ov_sensor_regs(sd);
@@ -4110,12 +4253,16 @@
 		setcontrast(gspca_dev);
 	if (!(sd->gspca_dev.ctrl_dis & (1 << BRIGHTNESS)))
 		setbrightness(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << EXPOSURE)))
+		setexposure(gspca_dev);
 	if (!(sd->gspca_dev.ctrl_dis & (1 << COLORS)))
 		setcolors(gspca_dev);
 	if (!(sd->gspca_dev.ctrl_dis & ((1 << HFLIP) | (1 << VFLIP))))
 		sethvflip(gspca_dev);
 	if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOBRIGHT)))
 		setautobright(gspca_dev);
+	if (!(sd->gspca_dev.ctrl_dis & (1 << AUTOGAIN)))
+		setautogain(gspca_dev);
 	if (!(sd->gspca_dev.ctrl_dis & (1 << FREQ)))
 		setfreq_i(sd);
 
@@ -4221,7 +4368,7 @@
 				gspca_dev->last_packet_type = DISCARD_PACKET;
 				return;
 			}
-			/* Add 11 byte footer to frame, might be usefull */
+			/* Add 11 byte footer to frame, might be useful */
 			gspca_frame_add(gspca_dev, LAST_PACKET, in, 11);
 			return;
 		} else {
@@ -4529,6 +4676,14 @@
 	}
 }
 
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (!sd->ctrls[AUTOGAIN].val)
+		i2c_w(sd, 0x10, sd->ctrls[EXPOSURE].val);
+}
+
 static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -4587,6 +4742,22 @@
 	i2c_w_mask(sd, 0x2d, sd->ctrls[AUTOBRIGHT].val ? 0x10 : 0x00, 0x10);
 }
 
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->ctrls[AUTOGAIN].val = val;
+	if (val) {
+		gspca_dev->ctrl_inac |= (1 << EXPOSURE);
+	} else {
+		gspca_dev->ctrl_inac &= ~(1 << EXPOSURE);
+		sd->ctrls[EXPOSURE].val = i2c_r(sd, 0x10);
+	}
+	if (gspca_dev->streaming)
+		setautogain(gspca_dev);
+	return gspca_dev->usb_err;
+}
+
 static void setfreq_i(struct sd *sd)
 {
 	if (sd->sensor == SEN_OV7660
@@ -4731,6 +4902,7 @@
 	.nctrls = ARRAY_SIZE(sd_ctrls),
 	.config = sd_config,
 	.init = sd_init,
+	.isoc_init = sd_isoc_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
 	.stop0 = sd_stop0,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/ov534.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/ov534.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/ov534.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/ov534.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * ov534-ov772x gspca driver
+ * ov534-ov7xxx gspca driver
  *
  * Copyright (C) 2008 Antonio Ospite <ospite@studenti.unina.it>
  * Copyright (C) 2008 Jim Paris <jim@jtan.com>
@@ -49,54 +49,59 @@
 MODULE_DESCRIPTION("GSPCA/OV534 USB Camera Driver");
 MODULE_LICENSE("GPL");
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	CONTRAST,
+	GAIN,
+	EXPOSURE,
+	AGC,
+	AWB,
+	AEC,
+	SHARPNESS,
+	HFLIP,
+	VFLIP,
+	COLORS,
+	LIGHTFREQ,
+	NCTRLS		/* number of controls */
+};
+
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
+
+	struct gspca_ctrl ctrls[NCTRLS];
+
 	__u32 last_pts;
 	u16 last_fid;
 	u8 frame_rate;
 
-	u8 brightness;
-	u8 contrast;
-	u8 gain;
-	u8 exposure;
-	u8 agc;
-	u8 awb;
-	u8 aec;
-	s8 sharpness;
-	u8 hflip;
-	u8 vflip;
-	u8 freqfltr;
+	u8 sensor;
+};
+enum sensors {
+	SENSOR_OV767x,
+	SENSOR_OV772x,
+	NSENSORS
 };
 
 /* V4L2 controls supported by the driver */
-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 void setbrightness(struct gspca_dev *gspca_dev);
+static void setcontrast(struct gspca_dev *gspca_dev);
+static void setgain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
 static int sd_setagc(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getagc(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getsharpness(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_setvflip(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getvflip(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_setaec(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getaec(struct gspca_dev *gspca_dev, __s32 *val);
-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_setfreqfltr(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getfreqfltr(struct gspca_dev *gspca_dev, __s32 *val);
-static int sd_querymenu(struct gspca_dev *gspca_dev,
-		struct v4l2_querymenu *menu);
+static void setawb(struct gspca_dev *gspca_dev);
+static void setaec(struct gspca_dev *gspca_dev);
+static void setsharpness(struct gspca_dev *gspca_dev);
+static void sethvflip(struct gspca_dev *gspca_dev);
+static void setcolors(struct gspca_dev *gspca_dev);
+static void setlightfreq(struct gspca_dev *gspca_dev);
+
+static int sd_start(struct gspca_dev *gspca_dev);
+static void sd_stopN(struct gspca_dev *gspca_dev);
 
 static const struct ctrl sd_ctrls[] = {
-	{	/* 0 */
+[BRIGHTNESS] = {
 		{
 			.id      = V4L2_CID_BRIGHTNESS,
 			.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -104,13 +109,11 @@
 			.minimum = 0,
 			.maximum = 255,
 			.step    = 1,
-#define BRIGHTNESS_DEF 0
-			.default_value = BRIGHTNESS_DEF,
+			.default_value = 0,
 		},
-		.set = sd_setbrightness,
-		.get = sd_getbrightness,
+		.set_control = setbrightness
 	},
-	{	/* 1 */
+[CONTRAST] = {
 		{
 			.id      = V4L2_CID_CONTRAST,
 			.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -118,13 +121,11 @@
 			.minimum = 0,
 			.maximum = 255,
 			.step    = 1,
-#define CONTRAST_DEF 32
-			.default_value = CONTRAST_DEF,
+			.default_value = 32,
 		},
-		.set = sd_setcontrast,
-		.get = sd_getcontrast,
+		.set_control = setcontrast
 	},
-	{	/* 2 */
+[GAIN] = {
 		{
 			.id      = V4L2_CID_GAIN,
 			.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -132,13 +133,11 @@
 			.minimum = 0,
 			.maximum = 63,
 			.step    = 1,
-#define GAIN_DEF 20
-			.default_value = GAIN_DEF,
+			.default_value = 20,
 		},
-		.set = sd_setgain,
-		.get = sd_getgain,
+		.set_control = setgain
 	},
-	{	/* 3 */
+[EXPOSURE] = {
 		{
 			.id      = V4L2_CID_EXPOSURE,
 			.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -146,13 +145,11 @@
 			.minimum = 0,
 			.maximum = 255,
 			.step    = 1,
-#define EXPO_DEF 120
-			.default_value = EXPO_DEF,
+			.default_value = 120,
 		},
-		.set = sd_setexposure,
-		.get = sd_getexposure,
+		.set_control = setexposure
 	},
-	{	/* 4 */
+[AGC] = {
 		{
 			.id      = V4L2_CID_AUTOGAIN,
 			.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -160,14 +157,11 @@
 			.minimum = 0,
 			.maximum = 1,
 			.step    = 1,
-#define AGC_DEF 1
-			.default_value = AGC_DEF,
+			.default_value = 1,
 		},
-		.set = sd_setagc,
-		.get = sd_getagc,
+		.set = sd_setagc
 	},
-#define AWB_IDX 5
-	{	/* 5 */
+[AWB] = {
 		{
 			.id      = V4L2_CID_AUTO_WHITE_BALANCE,
 			.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -175,13 +169,11 @@
 			.minimum = 0,
 			.maximum = 1,
 			.step    = 1,
-#define AWB_DEF 1
-			.default_value = AWB_DEF,
+			.default_value = 1,
 		},
-		.set = sd_setawb,
-		.get = sd_getawb,
+		.set_control = setawb
 	},
-	{	/* 6 */
+[AEC] = {
 		{
 			.id      = V4L2_CID_EXPOSURE_AUTO,
 			.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -189,13 +181,11 @@
 			.minimum = 0,
 			.maximum = 1,
 			.step    = 1,
-#define AEC_DEF 1
-			.default_value = AEC_DEF,
+			.default_value = 1,
 		},
-		.set = sd_setaec,
-		.get = sd_getaec,
+		.set_control = setaec
 	},
-	{	/* 7 */
+[SHARPNESS] = {
 		{
 			.id      = V4L2_CID_SHARPNESS,
 			.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -203,13 +193,11 @@
 			.minimum = 0,
 			.maximum = 63,
 			.step    = 1,
-#define SHARPNESS_DEF 0
-			.default_value = SHARPNESS_DEF,
+			.default_value = 0,
 		},
-		.set = sd_setsharpness,
-		.get = sd_getsharpness,
+		.set_control = setsharpness
 	},
-	{	/* 8 */
+[HFLIP] = {
 		{
 			.id      = V4L2_CID_HFLIP,
 			.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -217,13 +205,11 @@
 			.minimum = 0,
 			.maximum = 1,
 			.step    = 1,
-#define HFLIP_DEF 0
-			.default_value = HFLIP_DEF,
+			.default_value = 0,
 		},
-		.set = sd_sethflip,
-		.get = sd_gethflip,
+		.set_control = sethvflip
 	},
-	{	/* 9 */
+[VFLIP] = {
 		{
 			.id      = V4L2_CID_VFLIP,
 			.type    = V4L2_CTRL_TYPE_BOOLEAN,
@@ -231,13 +217,23 @@
 			.minimum = 0,
 			.maximum = 1,
 			.step    = 1,
-#define VFLIP_DEF 0
-			.default_value = VFLIP_DEF,
+			.default_value = 0,
 		},
-		.set = sd_setvflip,
-		.get = sd_getvflip,
+		.set_control = sethvflip
 	},
-	{	/* 10 */
+[COLORS] = {
+		{
+			.id      = V4L2_CID_SATURATION,
+			.type    = V4L2_CTRL_TYPE_INTEGER,
+			.name    = "Saturation",
+			.minimum = 0,
+			.maximum = 6,
+			.step    = 1,
+			.default_value = 3,
+		},
+		.set_control = setcolors
+	},
+[LIGHTFREQ] = {
 		{
 			.id      = V4L2_CID_POWER_LINE_FREQUENCY,
 			.type    = V4L2_CTRL_TYPE_MENU,
@@ -245,11 +241,9 @@
 			.minimum = 0,
 			.maximum = 1,
 			.step    = 1,
-#define FREQFLTR_DEF 0
-			.default_value = FREQFLTR_DEF,
+			.default_value = 0,
 		},
-		.set = sd_setfreqfltr,
-		.get = sd_getfreqfltr,
+		.set_control = setlightfreq
 	},
 };
 
@@ -265,6 +259,16 @@
 	 .colorspace = V4L2_COLORSPACE_SRGB,
 	 .priv = 0},
 };
+static const struct v4l2_pix_format ov767x_mode[] = {
+	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 320,
+		.sizeimage = 320 * 240 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG},
+	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
+		.bytesperline = 640,
+		.sizeimage = 640 * 480 * 3 / 8 + 590,
+		.colorspace = V4L2_COLORSPACE_JPEG},
+};
 
 static const u8 qvga_rates[] = {125, 100, 75, 60, 50, 40, 30};
 static const u8 vga_rates[] = {60, 50, 40, 30, 15};
@@ -280,7 +284,288 @@
 	},
 };
 
-static const u8 bridge_init[][2] = {
+struct reg_array {
+	const u8 (*val)[2];
+	int len;
+};
+
+static const u8 bridge_init_767x[][2] = {
+/* comments from the ms-win file apollo7670.set */
+/* str1 */
+	{0xf1, 0x42},
+	{0x88, 0xf8},
+	{0x89, 0xff},
+	{0x76, 0x03},
+	{0x92, 0x03},
+	{0x95, 0x10},
+	{0xe2, 0x00},
+	{0xe7, 0x3e},
+	{0x8d, 0x1c},
+	{0x8e, 0x00},
+	{0x8f, 0x00},
+	{0x1f, 0x00},
+	{0xc3, 0xf9},
+	{0x89, 0xff},
+	{0x88, 0xf8},
+	{0x76, 0x03},
+	{0x92, 0x01},
+	{0x93, 0x18},
+	{0x1c, 0x00},
+	{0x1d, 0x48},
+	{0x1d, 0x00},
+	{0x1d, 0xff},
+	{0x1d, 0x02},
+	{0x1d, 0x58},
+	{0x1d, 0x00},
+	{0x1c, 0x0a},
+	{0x1d, 0x0a},
+	{0x1d, 0x0e},
+	{0xc0, 0x50},	/* HSize 640 */
+	{0xc1, 0x3c},	/* VSize 480 */
+	{0x34, 0x05},	/* enable Audio Suspend mode */
+	{0xc2, 0x0c},	/* Input YUV */
+	{0xc3, 0xf9},	/* enable PRE */
+	{0x34, 0x05},	/* enable Audio Suspend mode */
+	{0xe7, 0x2e},	/* this solves failure of "SuspendResumeTest" */
+	{0x31, 0xf9},	/* enable 1.8V Suspend */
+	{0x35, 0x02},	/* turn on JPEG */
+	{0xd9, 0x10},
+	{0x25, 0x42},	/* GPIO[8]:Input */
+	{0x94, 0x11},	/* If the default setting is loaded when
+			 * system boots up, this flag is closed here */
+};
+static const u8 sensor_init_767x[][2] = {
+	{0x12, 0x80},
+	{0x11, 0x03},
+	{0x3a, 0x04},
+	{0x12, 0x00},
+	{0x17, 0x13},
+	{0x18, 0x01},
+	{0x32, 0xb6},
+	{0x19, 0x02},
+	{0x1a, 0x7a},
+	{0x03, 0x0a},
+	{0x0c, 0x00},
+	{0x3e, 0x00},
+	{0x70, 0x3a},
+	{0x71, 0x35},
+	{0x72, 0x11},
+	{0x73, 0xf0},
+	{0xa2, 0x02},
+	{0x7a, 0x2a},	/* set Gamma=1.6 below */
+	{0x7b, 0x12},
+	{0x7c, 0x1d},
+	{0x7d, 0x2d},
+	{0x7e, 0x45},
+	{0x7f, 0x50},
+	{0x80, 0x59},
+	{0x81, 0x62},
+	{0x82, 0x6b},
+	{0x83, 0x73},
+	{0x84, 0x7b},
+	{0x85, 0x8a},
+	{0x86, 0x98},
+	{0x87, 0xb2},
+	{0x88, 0xca},
+	{0x89, 0xe0},
+	{0x13, 0xe0},
+	{0x00, 0x00},
+	{0x10, 0x00},
+	{0x0d, 0x40},
+	{0x14, 0x38},	/* gain max 16x */
+	{0xa5, 0x05},
+	{0xab, 0x07},
+	{0x24, 0x95},
+	{0x25, 0x33},
+	{0x26, 0xe3},
+	{0x9f, 0x78},
+	{0xa0, 0x68},
+	{0xa1, 0x03},
+	{0xa6, 0xd8},
+	{0xa7, 0xd8},
+	{0xa8, 0xf0},
+	{0xa9, 0x90},
+	{0xaa, 0x94},
+	{0x13, 0xe5},
+	{0x0e, 0x61},
+	{0x0f, 0x4b},
+	{0x16, 0x02},
+	{0x21, 0x02},
+	{0x22, 0x91},
+	{0x29, 0x07},
+	{0x33, 0x0b},
+	{0x35, 0x0b},
+	{0x37, 0x1d},
+	{0x38, 0x71},
+	{0x39, 0x2a},
+	{0x3c, 0x78},
+	{0x4d, 0x40},
+	{0x4e, 0x20},
+	{0x69, 0x00},
+	{0x6b, 0x4a},
+	{0x74, 0x10},
+	{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, 0x34},
+	{0x46, 0x58},
+	{0x47, 0x28},
+	{0x48, 0x3a},
+	{0x59, 0x88},
+	{0x5a, 0x88},
+	{0x5b, 0x44},
+	{0x5c, 0x67},
+	{0x5d, 0x49},
+	{0x5e, 0x0e},
+	{0x6c, 0x0a},
+	{0x6d, 0x55},
+	{0x6e, 0x11},
+	{0x6f, 0x9f},
+	{0x6a, 0x40},
+	{0x01, 0x40},
+	{0x02, 0x40},
+	{0x13, 0xe7},
+	{0x4f, 0x80},
+	{0x50, 0x80},
+	{0x51, 0x00},
+	{0x52, 0x22},
+	{0x53, 0x5e},
+	{0x54, 0x80},
+	{0x58, 0x9e},
+	{0x41, 0x08},
+	{0x3f, 0x00},
+	{0x75, 0x04},
+	{0x76, 0xe1},
+	{0x4c, 0x00},
+	{0x77, 0x01},
+	{0x3d, 0xc2},
+	{0x4b, 0x09},
+	{0xc9, 0x60},
+	{0x41, 0x38},	/* jfm: auto sharpness + auto de-noise  */
+	{0x56, 0x40},
+	{0x34, 0x11},
+	{0x3b, 0xc2},
+	{0xa4, 0x8a},	/* Night mode trigger point */
+	{0x96, 0x00},
+	{0x97, 0x30},
+	{0x98, 0x20},
+	{0x99, 0x20},
+	{0x9a, 0x84},
+	{0x9b, 0x29},
+	{0x9c, 0x03},
+	{0x9d, 0x4c},
+	{0x9e, 0x3f},
+	{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, 0x20},
+	{0x79, 0x26},
+};
+static const u8 bridge_start_vga_767x[][2] = {
+/* str59 JPG */
+	{0x94, 0xaa},
+	{0xf1, 0x42},
+	{0xe5, 0x04},
+	{0xc0, 0x50},
+	{0xc1, 0x3c},
+	{0xc2, 0x0c},
+	{0x35, 0x02},	/* turn on JPEG */
+	{0xd9, 0x10},
+	{0xda, 0x00},	/* for higher clock rate(30fps) */
+	{0x34, 0x05},	/* enable Audio Suspend mode */
+	{0xc3, 0xf9},	/* enable PRE */
+	{0x8c, 0x00},	/* CIF VSize LSB[2:0] */
+	{0x8d, 0x1c},	/* output YUV */
+/*	{0x34, 0x05},	 * enable Audio Suspend mode (?) */
+	{0x50, 0x00},	/* H/V divider=0 */
+	{0x51, 0xa0},	/* input H=640/4 */
+	{0x52, 0x3c},	/* input V=480/4 */
+	{0x53, 0x00},	/* offset X=0 */
+	{0x54, 0x00},	/* offset Y=0 */
+	{0x55, 0x00},	/* H/V size[8]=0 */
+	{0x57, 0x00},	/* H-size[9]=0 */
+	{0x5c, 0x00},	/* output size[9:8]=0 */
+	{0x5a, 0xa0},	/* output H=640/4 */
+	{0x5b, 0x78},	/* output V=480/4 */
+	{0x1c, 0x0a},
+	{0x1d, 0x0a},
+	{0x94, 0x11},
+};
+static const u8 sensor_start_vga_767x[][2] = {
+	{0x11, 0x01},
+	{0x1e, 0x04},
+	{0x19, 0x02},
+	{0x1a, 0x7a},
+};
+static const u8 bridge_start_qvga_767x[][2] = {
+/* str86 JPG */
+	{0x94, 0xaa},
+	{0xf1, 0x42},
+	{0xe5, 0x04},
+	{0xc0, 0x80},
+	{0xc1, 0x60},
+	{0xc2, 0x0c},
+	{0x35, 0x02},	/* turn on JPEG */
+	{0xd9, 0x10},
+	{0xc0, 0x50},	/* CIF HSize 640 */
+	{0xc1, 0x3c},	/* CIF VSize 480 */
+	{0x8c, 0x00},	/* CIF VSize LSB[2:0] */
+	{0x8d, 0x1c},	/* output YUV */
+	{0x34, 0x05},	/* enable Audio Suspend mode */
+	{0xc2, 0x4c},	/* output YUV and Enable DCW */
+	{0xc3, 0xf9},	/* enable PRE */
+	{0x1c, 0x00},	/* indirect addressing */
+	{0x1d, 0x48},	/* output YUV422 */
+	{0x50, 0x89},	/* H/V divider=/2; plus DCW AVG */
+	{0x51, 0xa0},	/* DCW input H=640/4 */
+	{0x52, 0x78},	/* DCW input V=480/4 */
+	{0x53, 0x00},	/* offset X=0 */
+	{0x54, 0x00},	/* offset Y=0 */
+	{0x55, 0x00},	/* H/V size[8]=0 */
+	{0x57, 0x00},	/* H-size[9]=0 */
+	{0x5c, 0x00},	/* DCW output size[9:8]=0 */
+	{0x5a, 0x50},	/* DCW output H=320/4 */
+	{0x5b, 0x3c},	/* DCW output V=240/4 */
+	{0x1c, 0x0a},
+	{0x1d, 0x0a},
+	{0x94, 0x11},
+};
+static const u8 sensor_start_qvga_767x[][2] = {
+	{0x11, 0x01},
+	{0x1e, 0x04},
+	{0x19, 0x02},
+	{0x1a, 0x7a},
+};
+
+static const u8 bridge_init_772x[][2] = {
 	{ 0xc2, 0x0c },
 	{ 0x88, 0xf8 },
 	{ 0xc3, 0x69 },
@@ -338,7 +623,7 @@
 	{ 0xc1, 0x3c },
 	{ 0xc2, 0x0c },
 };
-static const u8 sensor_init[][2] = {
+static const u8 sensor_init_772x[][2] = {
 	{ 0x12, 0x80 },
 	{ 0x11, 0x01 },
 /*fixme: better have a delay?*/
@@ -431,7 +716,7 @@
 	{ 0x8e, 0x00 },		/* De-noise threshold */
 	{ 0x0c, 0xd0 }
 };
-static const u8 bridge_start_vga[][2] = {
+static const u8 bridge_start_vga_772x[][2] = {
 	{0x1c, 0x00},
 	{0x1d, 0x40},
 	{0x1d, 0x02},
@@ -442,7 +727,7 @@
 	{0xc0, 0x50},
 	{0xc1, 0x3c},
 };
-static const u8 sensor_start_vga[][2] = {
+static const u8 sensor_start_vga_772x[][2] = {
 	{0x12, 0x00},
 	{0x17, 0x26},
 	{0x18, 0xa0},
@@ -452,7 +737,7 @@
 	{0x2c, 0xf0},
 	{0x65, 0x20},
 };
-static const u8 bridge_start_qvga[][2] = {
+static const u8 bridge_start_qvga_772x[][2] = {
 	{0x1c, 0x00},
 	{0x1d, 0x40},
 	{0x1d, 0x02},
@@ -463,7 +748,7 @@
 	{0xc0, 0x28},
 	{0xc1, 0x1e},
 };
-static const u8 sensor_start_qvga[][2] = {
+static const u8 sensor_start_qvga_772x[][2] = {
 	{0x12, 0x40},
 	{0x17, 0x3f},
 	{0x18, 0x50},
@@ -646,6 +931,8 @@
 		{30, 0x04, 0x41, 0x04},
 	};
 
+	if (sd->sensor != SENSOR_OV772x)
+		return;
 	if (gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv == 0) {
 		r = rate_0;
 		i = ARRAY_SIZE(rate_0);
@@ -669,15 +956,28 @@
 static void setbrightness(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	int val;
 
-	sccb_reg_write(gspca_dev, 0x9b, sd->brightness);
+	val = sd->ctrls[BRIGHTNESS].val;
+	if (sd->sensor == SENSOR_OV767x) {
+		if (val < 0)
+			val = 0x80 - val;
+		sccb_reg_write(gspca_dev, 0x55, val);	/* bright */
+	} else {
+		sccb_reg_write(gspca_dev, 0x9b, val);
+	}
 }
 
 static void setcontrast(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val;
 
-	sccb_reg_write(gspca_dev, 0x9c, sd->contrast);
+	val = sd->ctrls[CONTRAST].val;
+	if (sd->sensor == SENSOR_OV767x)
+		sccb_reg_write(gspca_dev, 0x56, val);	/* contras */
+	else
+		sccb_reg_write(gspca_dev, 0x9c, val);
 }
 
 static void setgain(struct gspca_dev *gspca_dev)
@@ -685,10 +985,10 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
-	if (sd->agc)
+	if (sd->ctrls[AGC].val)
 		return;
 
-	val = sd->gain;
+	val = sd->ctrls[GAIN].val;
 	switch (val & 0x30) {
 	case 0x00:
 		val &= 0x0f;
@@ -715,25 +1015,32 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
-	if (sd->aec)
+	if (sd->ctrls[AEC].val)
 		return;
 
-	/* 'val' is one byte and represents half of the exposure value we are
-	 * going to set into registers, a two bytes value:
-	 *
-	 *    MSB: ((u16) val << 1) >> 8   == val >> 7
-	 *    LSB: ((u16) val << 1) & 0xff == val << 1
-	 */
-	val = sd->exposure;
-	sccb_reg_write(gspca_dev, 0x08, val >> 7);
-	sccb_reg_write(gspca_dev, 0x10, val << 1);
+	val = sd->ctrls[EXPOSURE].val;
+	if (sd->sensor == SENSOR_OV767x) {
+
+		/* set only aec[9:2] */
+		sccb_reg_write(gspca_dev, 0x10, val);	/* aech */
+	} else {
+
+		/* 'val' is one byte and represents half of the exposure value
+		 * we are going to set into registers, a two bytes value:
+		 *
+		 *    MSB: ((u16) val << 1) >> 8   == val >> 7
+		 *    LSB: ((u16) val << 1) & 0xff == val << 1
+		 */
+		sccb_reg_write(gspca_dev, 0x08, val >> 7);
+		sccb_reg_write(gspca_dev, 0x10, val << 1);
+	}
 }
 
 static void setagc(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (sd->agc) {
+	if (sd->ctrls[AGC].val) {
 		sccb_reg_write(gspca_dev, 0x13,
 				sccb_reg_read(gspca_dev, 0x13) | 0x04);
 		sccb_reg_write(gspca_dev, 0x64,
@@ -752,15 +1059,17 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	if (sd->awb) {
+	if (sd->ctrls[AWB].val) {
 		sccb_reg_write(gspca_dev, 0x13,
 				sccb_reg_read(gspca_dev, 0x13) | 0x02);
-		sccb_reg_write(gspca_dev, 0x63,
+		if (sd->sensor == SENSOR_OV772x)
+			sccb_reg_write(gspca_dev, 0x63,
 				sccb_reg_read(gspca_dev, 0x63) | 0xc0);
 	} else {
 		sccb_reg_write(gspca_dev, 0x13,
 				sccb_reg_read(gspca_dev, 0x13) & ~0x02);
-		sccb_reg_write(gspca_dev, 0x63,
+		if (sd->sensor == SENSOR_OV772x)
+			sccb_reg_write(gspca_dev, 0x63,
 				sccb_reg_read(gspca_dev, 0x63) & ~0xc0);
 	}
 }
@@ -768,14 +1077,22 @@
 static void setaec(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	u8 data;
 
-	if (sd->aec)
+	data = sd->sensor == SENSOR_OV767x ?
+			0x05 :		/* agc + aec */
+			0x01;		/* agc */
+	if (sd->ctrls[AEC].val)
 		sccb_reg_write(gspca_dev, 0x13,
-				sccb_reg_read(gspca_dev, 0x13) | 0x01);
+				sccb_reg_read(gspca_dev, 0x13) | data);
 	else {
 		sccb_reg_write(gspca_dev, 0x13,
-				sccb_reg_read(gspca_dev, 0x13) & ~0x01);
-		setexposure(gspca_dev);
+				sccb_reg_read(gspca_dev, 0x13) & ~data);
+		if (sd->sensor == SENSOR_OV767x)
+			sd->ctrls[EXPOSURE].val =
+				sccb_reg_read(gspca_dev, 10);	/* aech */
+		else
+			setexposure(gspca_dev);
 	}
 }
 
@@ -784,43 +1101,67 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	u8 val;
 
-	val = sd->sharpness;
+	val = sd->ctrls[SHARPNESS].val;
 	sccb_reg_write(gspca_dev, 0x91, val);	/* Auto de-noise threshold */
 	sccb_reg_write(gspca_dev, 0x8e, val);	/* De-noise threshold */
 }
 
-static void sethflip(struct gspca_dev *gspca_dev)
+static void sethvflip(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val;
 
-	if (sd->hflip == 0)
-		sccb_reg_write(gspca_dev, 0x0c,
-				sccb_reg_read(gspca_dev, 0x0c) | 0x40);
-	else
-		sccb_reg_write(gspca_dev, 0x0c,
-				sccb_reg_read(gspca_dev, 0x0c) & ~0x40);
+	if (sd->sensor == SENSOR_OV767x) {
+		val = sccb_reg_read(gspca_dev, 0x1e);	/* mvfp */
+		val &= ~0x30;
+		if (sd->ctrls[HFLIP].val)
+			val |= 0x20;
+		if (sd->ctrls[VFLIP].val)
+			val |= 0x10;
+		sccb_reg_write(gspca_dev, 0x1e, val);
+	} else {
+		val = sccb_reg_read(gspca_dev, 0x0c);
+		val &= ~0xc0;
+		if (sd->ctrls[HFLIP].val == 0)
+			val |= 0x40;
+		if (sd->ctrls[VFLIP].val == 0)
+			val |= 0x80;
+		sccb_reg_write(gspca_dev, 0x0c, val);
+	}
 }
 
-static void setvflip(struct gspca_dev *gspca_dev)
+static void setcolors(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val;
+	int i;
+	static u8 color_tb[][6] = {
+		{0x42, 0x42, 0x00, 0x11, 0x30, 0x41},
+		{0x52, 0x52, 0x00, 0x16, 0x3c, 0x52},
+		{0x66, 0x66, 0x00, 0x1b, 0x4b, 0x66},
+		{0x80, 0x80, 0x00, 0x22, 0x5e, 0x80},
+		{0x9a, 0x9a, 0x00, 0x29, 0x71, 0x9a},
+		{0xb8, 0xb8, 0x00, 0x31, 0x87, 0xb8},
+		{0xdd, 0xdd, 0x00, 0x3b, 0xa2, 0xdd},
+	};
 
-	if (sd->vflip == 0)
-		sccb_reg_write(gspca_dev, 0x0c,
-				sccb_reg_read(gspca_dev, 0x0c) | 0x80);
-	else
-		sccb_reg_write(gspca_dev, 0x0c,
-				sccb_reg_read(gspca_dev, 0x0c) & ~0x80);
+	val = sd->ctrls[COLORS].val;
+	for (i = 0; i < ARRAY_SIZE(color_tb[0]); i++)
+		sccb_reg_write(gspca_dev, 0x4f + i, color_tb[val][i]);
 }
 
-static void setfreqfltr(struct gspca_dev *gspca_dev)
+static void setlightfreq(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
+	u8 val;
 
-	if (sd->freqfltr == 0)
-		sccb_reg_write(gspca_dev, 0x2b, 0x00);
-	else
-		sccb_reg_write(gspca_dev, 0x2b, 0x9e);
+	val = sd->ctrls[LIGHTFREQ].val ? 0x9e : 0x00;
+	if (sd->sensor == SENSOR_OV767x) {
+		sccb_reg_write(gspca_dev, 0x2a, 0x00);
+		if (val)
+			val = 0x9d;	/* insert dummy to 25fps for 50Hz */
+	}
+	sccb_reg_write(gspca_dev, 0x2b, val);
 }
 
 
@@ -833,39 +1174,33 @@
 
 	cam = &gspca_dev->cam;
 
+	cam->ctrls = sd->ctrls;
+
+	/* the auto white balance control works only when auto gain is set */
+	if (sd_ctrls[AGC].qctrl.default_value == 0)
+		gspca_dev->ctrl_inac |= (1 << AWB);
+
 	cam->cam_mode = ov772x_mode;
 	cam->nmodes = ARRAY_SIZE(ov772x_mode);
-	cam->mode_framerates = ov772x_framerates;
-
-	cam->bulk = 1;
-	cam->bulk_size = 16384;
-	cam->bulk_nurbs = 2;
 
 	sd->frame_rate = 30;
 
-	sd->brightness = BRIGHTNESS_DEF;
-	sd->contrast = CONTRAST_DEF;
-	sd->gain = GAIN_DEF;
-	sd->exposure = EXPO_DEF;
-#if AGC_DEF != 0
-	sd->agc = AGC_DEF;
-#else
-	gspca_dev->ctrl_inac |= (1 << AWB_IDX);
-#endif
-	sd->awb = AWB_DEF;
-	sd->aec = AEC_DEF;
-	sd->sharpness = SHARPNESS_DEF;
-	sd->hflip = HFLIP_DEF;
-	sd->vflip = VFLIP_DEF;
-	sd->freqfltr = FREQFLTR_DEF;
-
 	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;
 	u16 sensor_id;
+	static const struct reg_array bridge_init[NSENSORS] = {
+	[SENSOR_OV767x] = {bridge_init_767x, ARRAY_SIZE(bridge_init_767x)},
+	[SENSOR_OV772x] = {bridge_init_772x, ARRAY_SIZE(bridge_init_772x)},
+	};
+	static const struct reg_array sensor_init[NSENSORS] = {
+	[SENSOR_OV767x] = {sensor_init_767x, ARRAY_SIZE(sensor_init_767x)},
+	[SENSOR_OV772x] = {sensor_init_772x, ARRAY_SIZE(sensor_init_772x)},
+	};
 
 	/* reset bridge */
 	ov534_reg_write(gspca_dev, 0xe7, 0x3a);
@@ -886,48 +1221,100 @@
 	sensor_id |= sccb_reg_read(gspca_dev, 0x0b);
 	PDEBUG(D_PROBE, "Sensor ID: %04x", sensor_id);
 
+	if ((sensor_id & 0xfff0) == 0x7670) {
+		sd->sensor = SENSOR_OV767x;
+		gspca_dev->ctrl_dis = (1 << GAIN) |
+					(1 << AGC) |
+					(1 << SHARPNESS);	/* auto */
+		sd->ctrls[BRIGHTNESS].min = -127;
+		sd->ctrls[BRIGHTNESS].max = 127;
+		sd->ctrls[BRIGHTNESS].def = 0;
+		sd->ctrls[CONTRAST].max = 0x80;
+		sd->ctrls[CONTRAST].def = 0x40;
+		sd->ctrls[EXPOSURE].min = 0x08;
+		sd->ctrls[EXPOSURE].max = 0x60;
+		sd->ctrls[EXPOSURE].def = 0x13;
+		sd->ctrls[SHARPNESS].max = 9;
+		sd->ctrls[SHARPNESS].def = 4;
+		sd->ctrls[HFLIP].def = 1;
+		gspca_dev->cam.cam_mode = ov767x_mode;
+		gspca_dev->cam.nmodes = ARRAY_SIZE(ov767x_mode);
+	} else {
+		sd->sensor = SENSOR_OV772x;
+		gspca_dev->ctrl_dis = (1 << COLORS);
+		gspca_dev->cam.bulk = 1;
+		gspca_dev->cam.bulk_size = 16384;
+		gspca_dev->cam.bulk_nurbs = 2;
+		gspca_dev->cam.mode_framerates = ov772x_framerates;
+	}
+
 	/* initialize */
-	reg_w_array(gspca_dev, bridge_init,
-			ARRAY_SIZE(bridge_init));
+	reg_w_array(gspca_dev, bridge_init[sd->sensor].val,
+			bridge_init[sd->sensor].len);
 	ov534_set_led(gspca_dev, 1);
-	sccb_w_array(gspca_dev, sensor_init,
-			ARRAY_SIZE(sensor_init));
-	ov534_reg_write(gspca_dev, 0xe0, 0x09);
-	ov534_set_led(gspca_dev, 0);
-	set_frame_rate(gspca_dev);
+	sccb_w_array(gspca_dev, sensor_init[sd->sensor].val,
+			sensor_init[sd->sensor].len);
+	if (sd->sensor == SENSOR_OV767x)
+		sd_start(gspca_dev);
+	sd_stopN(gspca_dev);
+/*	set_frame_rate(gspca_dev);	*/
 
 	return gspca_dev->usb_err;
 }
 
 static int sd_start(struct gspca_dev *gspca_dev)
 {
+	struct sd *sd = (struct sd *) gspca_dev;
 	int mode;
+	static const struct reg_array bridge_start[NSENSORS][2] = {
+	[SENSOR_OV767x] = {{bridge_start_qvga_767x,
+					ARRAY_SIZE(bridge_start_qvga_767x)},
+			{bridge_start_vga_767x,
+					ARRAY_SIZE(bridge_start_vga_767x)}},
+	[SENSOR_OV772x] = {{bridge_start_qvga_772x,
+					ARRAY_SIZE(bridge_start_qvga_772x)},
+			{bridge_start_vga_772x,
+					ARRAY_SIZE(bridge_start_vga_772x)}},
+	};
+	static const struct reg_array sensor_start[NSENSORS][2] = {
+	[SENSOR_OV767x] = {{sensor_start_qvga_767x,
+					ARRAY_SIZE(sensor_start_qvga_767x)},
+			{sensor_start_vga_767x,
+					ARRAY_SIZE(sensor_start_vga_767x)}},
+	[SENSOR_OV772x] = {{sensor_start_qvga_772x,
+					ARRAY_SIZE(sensor_start_qvga_772x)},
+			{sensor_start_vga_772x,
+					ARRAY_SIZE(sensor_start_vga_772x)}},
+	};
+
+	/* (from ms-win trace) */
+	if (sd->sensor == SENSOR_OV767x)
+		sccb_reg_write(gspca_dev, 0x1e, 0x04);
+					/* black sun enable ? */
+
+	mode = gspca_dev->curr_mode;	/* 0: 320x240, 1: 640x480 */
+	reg_w_array(gspca_dev, bridge_start[sd->sensor][mode].val,
+				bridge_start[sd->sensor][mode].len);
+	sccb_w_array(gspca_dev, sensor_start[sd->sensor][mode].val,
+				sensor_start[sd->sensor][mode].len);
 
-	mode = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].priv;
-	if (mode != 0) {	/* 320x240 */
-		reg_w_array(gspca_dev, bridge_start_qvga,
-				ARRAY_SIZE(bridge_start_qvga));
-		sccb_w_array(gspca_dev, sensor_start_qvga,
-				ARRAY_SIZE(sensor_start_qvga));
-	} else {		/* 640x480 */
-		reg_w_array(gspca_dev, bridge_start_vga,
-				ARRAY_SIZE(bridge_start_vga));
-		sccb_w_array(gspca_dev, sensor_start_vga,
-				ARRAY_SIZE(sensor_start_vga));
-	}
 	set_frame_rate(gspca_dev);
 
-	setagc(gspca_dev);
+	if (!(gspca_dev->ctrl_dis & (1 << AGC)))
+		setagc(gspca_dev);
 	setawb(gspca_dev);
 	setaec(gspca_dev);
-	setgain(gspca_dev);
+	if (!(gspca_dev->ctrl_dis & (1 << GAIN)))
+		setgain(gspca_dev);
 	setexposure(gspca_dev);
 	setbrightness(gspca_dev);
 	setcontrast(gspca_dev);
-	setsharpness(gspca_dev);
-	setvflip(gspca_dev);
-	sethflip(gspca_dev);
-	setfreqfltr(gspca_dev);
+	if (!(gspca_dev->ctrl_dis & (1 << SHARPNESS)))
+		setsharpness(gspca_dev);
+	sethvflip(gspca_dev);
+	if (!(gspca_dev->ctrl_dis & (1 << COLORS)))
+		setcolors(gspca_dev);
+	setlightfreq(gspca_dev);
 
 	ov534_set_led(gspca_dev, 1);
 	ov534_reg_write(gspca_dev, 0xe0, 0x00);
@@ -957,9 +1344,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, 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
@@ -999,8 +1388,9 @@
 		/* If this packet is marked as EOF, end the frame */
 		} else if (data[1] & UVC_STREAM_EOF) {
 			sd->last_pts = 0;
-			if (gspca_dev->image_len + len - 12 !=
-			    gspca_dev->width * gspca_dev->height * 2) {
+			if (gspca_dev->pixfmt == V4L2_PIX_FMT_YUYV
+			 && gspca_dev->image_len + len - 12 !=
+				   gspca_dev->width * gspca_dev->height * 2) {
 				PDEBUG(D_PACK, "wrong sized frame");
 				goto discard;
 			}
@@ -1026,212 +1416,27 @@
 	} while (remaining_len > 0);
 }
 
-/* controls */
-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)
-		setgain(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_setexposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->exposure = val;
-	if (gspca_dev->streaming)
-		setexposure(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_setbrightness(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->brightness = val;
-	if (gspca_dev->streaming)
-		setbrightness(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)
-		setcontrast(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_setagc(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	sd->agc = val;
-
-	if (gspca_dev->streaming) {
+	sd->ctrls[AGC].val = val;
 
-		/* the auto white balance control works only
-		 * when auto gain is set */
-		if (val)
-			gspca_dev->ctrl_inac &= ~(1 << AWB_IDX);
-		else
-			gspca_dev->ctrl_inac |= (1 << AWB_IDX);
-		setagc(gspca_dev);
+	/* the auto white balance control works only
+	 * when auto gain is set */
+	if (val) {
+		gspca_dev->ctrl_inac &= ~(1 << AWB);
+	} else {
+		gspca_dev->ctrl_inac |= (1 << AWB);
+		if (sd->ctrls[AWB].val) {
+			sd->ctrls[AWB].val = 0;
+			if (gspca_dev->streaming)
+				setawb(gspca_dev);
+		}
 	}
-	return 0;
-}
-
-static int sd_getagc(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->agc;
-	return 0;
-}
-
-static int sd_setawb(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->awb = val;
-	if (gspca_dev->streaming)
-		setawb(gspca_dev);
-	return 0;
-}
-
-static int sd_getawb(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->awb;
-	return 0;
-}
-
-static int sd_setaec(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->aec = val;
-	if (gspca_dev->streaming)
-		setaec(gspca_dev);
-	return 0;
-}
-
-static int sd_getaec(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->aec;
-	return 0;
-}
-
-static int sd_setsharpness(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->sharpness = val;
-	if (gspca_dev->streaming)
-		setsharpness(gspca_dev);
-	return 0;
-}
-
-static int sd_getsharpness(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->sharpness;
-	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)
-		sethflip(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)
-		setvflip(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_setfreqfltr(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->freqfltr = val;
-	if (gspca_dev->streaming)
-		setfreqfltr(gspca_dev);
-	return 0;
-}
-
-static int sd_getfreqfltr(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->freqfltr;
-	return 0;
+		setagc(gspca_dev);
+	return gspca_dev->usb_err;
 }
 
 static int sd_querymenu(struct gspca_dev *gspca_dev,
@@ -1302,6 +1507,7 @@
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x1415, 0x2000)},
+	{USB_DEVICE(0x06f8, 0x3002)},
 	{}
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/sn9c20x.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/sn9c20x.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/sn9c20x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/sn9c20x.c	2011-05-19 00:06:34.000000000 -0400
@@ -152,6 +152,13 @@
 		}
 	},
 	{
+		.ident = "MSI MS-1633X",
+		.matches = {
+			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+			DMI_MATCH(DMI_BOARD_NAME, "MS-1633X")
+		}
+	},
+	{
 		.ident = "MSI MS-1635X",
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
@@ -369,7 +376,7 @@
 		.priv = SCALE_160x120},
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
-		.sizeimage = 320 * 240 * 3 / 8 + 590,
+		.sizeimage = 320 * 240 * 4 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = SCALE_320x240 | MODE_JPEG},
 	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
@@ -384,7 +391,7 @@
 		.priv = SCALE_320x240},
 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 640,
-		.sizeimage = 640 * 480 * 3 / 8 + 590,
+		.sizeimage = 640 * 480 * 4 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = SCALE_640x480 | MODE_JPEG},
 	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
@@ -417,7 +424,7 @@
 		.priv = SCALE_160x120},
 	{320, 240, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 320,
-		.sizeimage = 320 * 240 * 3 / 8 + 590,
+		.sizeimage = 320 * 240 * 4 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = SCALE_320x240 | MODE_JPEG},
 	{320, 240, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
@@ -432,7 +439,7 @@
 		.priv = SCALE_320x240},
 	{640, 480, V4L2_PIX_FMT_JPEG, V4L2_FIELD_NONE,
 		.bytesperline = 640,
-		.sizeimage = 640 * 480 * 3 / 8 + 590,
+		.sizeimage = 640 * 480 * 4 / 8 + 590,
 		.colorspace = V4L2_COLORSPACE_JPEG,
 		.priv = SCALE_640x480 | MODE_JPEG},
 	{640, 480, V4L2_PIX_FMT_SBGGR8, V4L2_FIELD_NONE,
@@ -884,6 +891,9 @@
 	{0x0e, 0x80}, {0x0d, 0x08}, {0x0f, 0xc3},
 	{0x04, 0xc3}, {0x10, 0x40}, {0x11, 0x40},
 	{0x12, 0x05}, {0x13, 0xba}, {0x14, 0x2a},
+	/* HDG Set hstart and hstop, datasheet default 0x11, 0x61, using
+	   0x10, 0x61 and sd->hstart, vstart = 3, fixes ugly colored borders */
+	{0x17, 0x10}, {0x18, 0x61},
 	{0x37, 0x0f}, {0x38, 0x02}, {0x39, 0x43},
 	{0x3a, 0x00}, {0x69, 0x90}, {0x2d, 0xf6},
 	{0x2e, 0x0b}, {0x01, 0x78}, {0x02, 0x50},
@@ -1332,10 +1342,8 @@
 			return -ENODEV;
 		}
 	}
-	/* disable hflip and vflip */
-	gspca_dev->ctrl_dis = (1 << HFLIP_IDX) | (1 << VFLIP_IDX);
-	sd->hstart = 1;
-	sd->vstart = 1;
+	sd->hstart = 3;
+	sd->vstart = 3;
 	return 0;
 }
 
@@ -1608,6 +1616,18 @@
 	}
 
 	switch (sd->sensor) {
+	case SENSOR_OV7660:
+		value = 0x01;
+		if (hflip)
+			value |= 0x20;
+		if (vflip) {
+			value |= 0x10;
+			sd->vstart = 2;
+		} else
+			sd->vstart = 3;
+		reg_w1(gspca_dev, 0x1182, sd->vstart);
+		i2c_w1(gspca_dev, 0x1e, value);
+		break;
 	case SENSOR_OV9650:
 		i2c_r1(gspca_dev, 0x1e, &value);
 		value &= ~0x30;
@@ -2482,7 +2502,7 @@
 	{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, 0x627b), SN9C20X(OV7660, 0x21, FLIP_DETECT)},
 	{USB_DEVICE(0x0c45, 0x627c), SN9C20X(HV7131R, 0x11, 0)},
 	{USB_DEVICE(0x0c45, 0x627f), SN9C20X(OV9650, 0x30, 0)},
 	{USB_DEVICE(0x0c45, 0x6280), SN9C20X(MT9M001, 0x5d, 0)},
@@ -2494,7 +2514,7 @@
 	{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, 0x62bb), SN9C20X(OV7660, 0x21, LED_REVERSE)},
 	{USB_DEVICE(0x0c45, 0x62bc), SN9C20X(HV7131R, 0x11, 0)},
 	{USB_DEVICE(0x045e, 0x00f4), SN9C20X(OV9650, 0x30, 0)},
 	{USB_DEVICE(0x145f, 0x013d), SN9C20X(OV7660, 0x21, 0)},
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/sonixb.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/sonixb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/sonixb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/sonixb.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,9 +1,9 @@
 /*
  *		sonix sn9c102 (bayer) library
- *		Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
- * Add Pas106 Stefano Mozzi (C) 2004
  *
- * V4L2 by Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009-2011 Jean-FranÃ§ois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2003 2004 Michel Xhaard mxhaard@magic.fr
+ * Add Pas106 Stefano Mozzi (C) 2004
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -52,13 +52,26 @@
 #include <linux/input.h>
 #include "gspca.h"
 
-MODULE_AUTHOR("Michel Xhaard <mxhaard@users.sourceforge.net>");
+MODULE_AUTHOR("Jean-FranÃ§ois Moine <http://moinejf.free.fr>");
 MODULE_DESCRIPTION("GSPCA/SN9C102 USB Camera Driver");
 MODULE_LICENSE("GPL");
 
+/* controls */
+enum e_ctrl {
+	BRIGHTNESS,
+	GAIN,
+	EXPOSURE,
+	AUTOGAIN,
+	FREQ,
+	NCTRLS		/* number of controls */
+};
+
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
+
+	struct gspca_ctrl ctrls[NCTRLS];
+
 	atomic_t avg_lum;
 	int prev_avg_lum;
 	int exp_too_low_cnt;
@@ -66,13 +79,8 @@
 	int header_read;
 	u8 header[12]; /* Header without sof marker */
 
-	unsigned short exposure;
-	unsigned char gain;
-	unsigned char brightness;
-	unsigned char autogain;
 	unsigned char autogain_ignore_frames;
 	unsigned char frames_to_drop;
-	unsigned char freq;		/* light freq filter setting */
 
 	__u8 bridge;			/* Type of bridge */
 #define BRIDGE_101 0
@@ -113,10 +121,9 @@
 #define MODE_REDUCED_SIF 0x20	/* vga mode (320x240 / 160x120) on sif cam */
 
 /* ctrl_dis helper macros */
-#define NO_EXPO ((1 << EXPOSURE_IDX) | (1 << COARSE_EXPOSURE_IDX) | \
-		 (1 << AUTOGAIN_IDX))
-#define NO_FREQ (1 << FREQ_IDX)
-#define NO_BRIGHTNESS (1 << BRIGHTNESS_IDX)
+#define NO_EXPO ((1 << EXPOSURE) | (1 << AUTOGAIN))
+#define NO_FREQ (1 << FREQ)
+#define NO_BRIGHTNESS (1 << BRIGHTNESS)
 
 #define COMP 0xc7		/* 0x87 //0x07 */
 #define COMP1 0xc9		/* 0x89 //0x09 */
@@ -141,20 +148,14 @@
 #define AUTOGAIN_IGNORE_FRAMES 1
 
 /* V4L2 controls supported by the driver */
-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_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 void setbrightness(struct gspca_dev *gspca_dev);
+static void setgain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
 static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
-static int sd_getautogain(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 setfreq(struct gspca_dev *gspca_dev);
 
-static const struct ctrl sd_ctrls[] = {
-#define BRIGHTNESS_IDX 0
-	{
+static const struct ctrl sd_ctrls[NCTRLS] = {
+[BRIGHTNESS] = {
 	    {
 		.id      = V4L2_CID_BRIGHTNESS,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -162,14 +163,11 @@
 		.minimum = 0,
 		.maximum = 255,
 		.step    = 1,
-#define BRIGHTNESS_DEF 127
-		.default_value = BRIGHTNESS_DEF,
+		.default_value = 127,
 	    },
-	    .set = sd_setbrightness,
-	    .get = sd_getbrightness,
+	    .set_control = setbrightness
 	},
-#define GAIN_IDX 1
-	{
+[GAIN] = {
 	    {
 		.id      = V4L2_CID_GAIN,
 		.type    = V4L2_CTRL_TYPE_INTEGER,
@@ -177,48 +175,31 @@
 		.minimum = 0,
 		.maximum = 255,
 		.step    = 1,
-#define GAIN_DEF 127
 #define GAIN_KNEE 230
-		.default_value = GAIN_DEF,
+		.default_value = 127,
 	    },
-	    .set = sd_setgain,
-	    .get = sd_getgain,
+	    .set_control = setgain
 	},
-#define EXPOSURE_IDX 2
-	{
+[EXPOSURE] = {
 		{
 			.id = V4L2_CID_EXPOSURE,
 			.type = V4L2_CTRL_TYPE_INTEGER,
 			.name = "Exposure",
-#define EXPOSURE_DEF  66 /*  33 ms / 30 fps (except on PASXXX) */
-#define EXPOSURE_KNEE 200 /* 100 ms / 10 fps (except on PASXXX) */
 			.minimum = 0,
 			.maximum = 1023,
 			.step = 1,
-			.default_value = EXPOSURE_DEF,
+			.default_value = 66,
+				/*  33 ms / 30 fps (except on PASXXX) */
+#define EXPOSURE_KNEE 200	/* 100 ms / 10 fps (except on PASXXX) */
 			.flags = 0,
 		},
-		.set = sd_setexposure,
-		.get = sd_getexposure,
+		.set_control = setexposure
 	},
-#define COARSE_EXPOSURE_IDX 3
-	{
-		{
-			.id = V4L2_CID_EXPOSURE,
-			.type = V4L2_CTRL_TYPE_INTEGER,
-			.name = "Exposure",
+/* for coarse exposure */
+#define COARSE_EXPOSURE_MIN 2
+#define COARSE_EXPOSURE_MAX 15
 #define COARSE_EXPOSURE_DEF  2 /* 30 fps */
-			.minimum = 2,
-			.maximum = 15,
-			.step = 1,
-			.default_value = COARSE_EXPOSURE_DEF,
-			.flags = 0,
-		},
-		.set = sd_setexposure,
-		.get = sd_getexposure,
-	},
-#define AUTOGAIN_IDX 4
-	{
+[AUTOGAIN] = {
 		{
 			.id = V4L2_CID_AUTOGAIN,
 			.type = V4L2_CTRL_TYPE_BOOLEAN,
@@ -228,13 +209,11 @@
 			.step = 1,
 #define AUTOGAIN_DEF 1
 			.default_value = AUTOGAIN_DEF,
-			.flags = 0,
+			.flags = V4L2_CTRL_FLAG_UPDATE
 		},
 		.set = sd_setautogain,
-		.get = sd_getautogain,
 	},
-#define FREQ_IDX 5
-	{
+[FREQ] = {
 		{
 			.id	 = V4L2_CID_POWER_LINE_FREQUENCY,
 			.type    = V4L2_CTRL_TYPE_MENU,
@@ -245,8 +224,7 @@
 #define FREQ_DEF 0
 			.default_value = FREQ_DEF,
 		},
-		.set = sd_setfreq,
-		.get = sd_getfreq,
+		.set_control = setfreq
 	},
 };
 
@@ -553,7 +531,7 @@
 	{0x30, 0x11, 0x02, 0x20, 0x70, 0x00, 0x00, 0x10},
 };
 
-static struct sensor_data sensor_data[] = {
+static const struct sensor_data sensor_data[] = {
 SENS(initHv7131d, hv7131d_sensor_init, F_GAIN, NO_BRIGHTNESS|NO_FREQ, 0),
 SENS(initHv7131r, hv7131r_sensor_init, 0, NO_BRIGHTNESS|NO_EXPO|NO_FREQ, 0),
 SENS(initOv6650, ov6650_sensor_init, F_GAIN|F_SIF, 0, 0x60),
@@ -646,7 +624,7 @@
 
 		/* change reg 0x06 */
 		i2cOV[1] = sensor_data[sd->sensor].sensor_addr;
-		i2cOV[3] = sd->brightness;
+		i2cOV[3] = sd->ctrls[BRIGHTNESS].val;
 		if (i2c_w(gspca_dev, i2cOV) < 0)
 			goto err;
 		break;
@@ -664,13 +642,13 @@
 			i2cpdoit[2] = 0x13;
 		}
 
-		if (sd->brightness < 127) {
+		if (sd->ctrls[BRIGHTNESS].val < 127) {
 			/* change reg 0x0b, signreg */
 			i2cpbright[3] = 0x01;
 			/* set reg 0x0c, offset */
-			i2cpbright[4] = 127 - sd->brightness;
+			i2cpbright[4] = 127 - sd->ctrls[BRIGHTNESS].val;
 		} else
-			i2cpbright[4] = sd->brightness - 127;
+			i2cpbright[4] = sd->ctrls[BRIGHTNESS].val - 127;
 
 		if (i2c_w(gspca_dev, i2cpbright) < 0)
 			goto err;
@@ -687,16 +665,16 @@
 static void setsensorgain(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	unsigned char gain = sd->gain;
+	u8 gain = sd->ctrls[GAIN].val;
 
 	switch (sd->sensor) {
 	case SENSOR_HV7131D: {
 		__u8 i2c[] =
 			{0xc0, 0x11, 0x31, 0x00, 0x00, 0x00, 0x00, 0x17};
 
-		i2c[3] = 0x3f - (sd->gain / 4);
-		i2c[4] = 0x3f - (sd->gain / 4);
-		i2c[5] = 0x3f - (sd->gain / 4);
+		i2c[3] = 0x3f - (gain / 4);
+		i2c[4] = 0x3f - (gain / 4);
+		i2c[5] = 0x3f - (gain / 4);
 
 		if (i2c_w(gspca_dev, i2c) < 0)
 			goto err;
@@ -759,11 +737,11 @@
 			i2cpdoit[2] = 0x13;
 		}
 
-		i2cpgain[3] = sd->gain >> 3;
-		i2cpcolorgain[3] = sd->gain >> 4;
-		i2cpcolorgain[4] = sd->gain >> 4;
-		i2cpcolorgain[5] = sd->gain >> 4;
-		i2cpcolorgain[6] = sd->gain >> 4;
+		i2cpgain[3] = gain >> 3;
+		i2cpcolorgain[3] = gain >> 4;
+		i2cpcolorgain[4] = gain >> 4;
+		i2cpcolorgain[5] = gain >> 4;
+		i2cpcolorgain[6] = gain >> 4;
 
 		if (i2c_w(gspca_dev, i2cpgain) < 0)
 			goto err;
@@ -792,13 +770,13 @@
 	}
 
 	if (sd->bridge == BRIDGE_103) {
-		gain = sd->gain >> 1;
+		gain = sd->ctrls[GAIN].val >> 1;
 		buf[0] = gain; /* Red */
 		buf[1] = gain; /* Green */
 		buf[2] = gain; /* Blue */
 		reg_w(gspca_dev, 0x05, buf, 3);
 	} else {
-		gain = sd->gain >> 4;
+		gain = sd->ctrls[GAIN].val >> 4;
 		buf[0] = gain << 4 | gain; /* Red and blue */
 		buf[1] = gain; /* Green */
 		reg_w(gspca_dev, 0x10, buf, 2);
@@ -820,7 +798,8 @@
 		      where the framerate starts dropping
 		   2) At 6138 the framerate has already dropped to 2 fps,
 		      going any lower makes little sense */
-		__u16 reg = sd->exposure * 6;
+		u16 reg = sd->ctrls[EXPOSURE].val * 6;
+
 		i2c[3] = reg >> 8;
 		i2c[4] = reg & 0xff;
 		if (i2c_w(gspca_dev, i2c) != 0)
@@ -832,7 +811,8 @@
 		/* register 19's high nibble contains the sn9c10x clock divider
 		   The high nibble configures the no fps according to the
 		   formula: 60 / high_nibble. With a maximum of 30 fps */
-		__u8 reg = sd->exposure;
+		u8 reg = sd->ctrls[EXPOSURE].val;
+
 		reg = (reg << 4) | 0x0b;
 		reg_w(gspca_dev, 0x19, &reg, 1);
 		break;
@@ -847,7 +827,7 @@
 		   possible to use less exposure then what the fps maximum
 		   allows by setting register 10. register 10 configures the
 		   actual exposure as quotient of the full exposure, with 0
-		   being no exposure at all (not very usefull) and reg10_max
+		   being no exposure at all (not very useful) and reg10_max
 		   being max exposure possible at that framerate.
 
 		   The code maps our 0 - 510 ms exposure ctrl to these 2
@@ -868,7 +848,7 @@
 		} else
 			reg10_max = 0x41;
 
-		reg11 = (15 * sd->exposure + 999) / 1000;
+		reg11 = (15 * sd->ctrls[EXPOSURE].val + 999) / 1000;
 		if (reg11 < 1)
 			reg11 = 1;
 		else if (reg11 > 16)
@@ -881,14 +861,16 @@
 			reg11 = 4;
 
 		/* frame exposure time in ms = 1000 * reg11 / 30    ->
-		reg10 = (sd->exposure / 2) * reg10_max / (1000 * reg11 / 30) */
-		reg10 = (sd->exposure * 15 * reg10_max) / (1000 * reg11);
+		reg10 = (sd->ctrls[EXPOSURE].val / 2) * reg10_max
+				/ (1000 * reg11 / 30) */
+		reg10 = (sd->ctrls[EXPOSURE].val * 15 * reg10_max)
+				/ (1000 * reg11);
 
 		/* Don't allow this to get below 10 when using autogain, the
 		   steps become very large (relatively) when below 10 causing
 		   the image to oscilate from much too dark, to much too bright
 		   and back again. */
-		if (sd->autogain && reg10 < 10)
+		if (sd->ctrls[AUTOGAIN].val && reg10 < 10)
 			reg10 = 10;
 		else if (reg10 > reg10_max)
 			reg10 = reg10_max;
@@ -927,15 +909,16 @@
 		   frame exposure times (like we are doing with the ov chips),
 		   as that sometimes leads to jumps in the exposure control,
 		   which are bad for auto exposure. */
-		if (sd->exposure < 200) {
-			i2cpexpo[3] = 255 - (sd->exposure * 255) / 200;
+		if (sd->ctrls[EXPOSURE].val < 200) {
+			i2cpexpo[3] = 255 - (sd->ctrls[EXPOSURE].val * 255)
+						/ 200;
 			framerate_ctrl = 500;
 		} else {
 			/* The PAS202's exposure control goes from 0 - 4095,
 			   but anything below 500 causes vsync issues, so scale
 			   our 200-1023 to 500-4095 */
-			framerate_ctrl = (sd->exposure - 200) * 1000 / 229 +
-					 500;
+			framerate_ctrl = (sd->ctrls[EXPOSURE].val - 200)
+							* 1000 / 229 +  500;
 		}
 
 		i2cpframerate[3] = framerate_ctrl >> 6;
@@ -959,15 +942,15 @@
 
 		/* For values below 150 use partial frame exposure, above
 		   that use framerate ctrl */
-		if (sd->exposure < 150) {
-			i2cpexpo[3] = 150 - sd->exposure;
+		if (sd->ctrls[EXPOSURE].val < 150) {
+			i2cpexpo[3] = 150 - sd->ctrls[EXPOSURE].val;
 			framerate_ctrl = 300;
 		} else {
 			/* The PAS106's exposure control goes from 0 - 4095,
 			   but anything below 300 causes vsync issues, so scale
 			   our 150-1023 to 300-4095 */
-			framerate_ctrl = (sd->exposure - 150) * 1000 / 230 +
-					 300;
+			framerate_ctrl = (sd->ctrls[EXPOSURE].val - 150)
+						* 1000 / 230 + 300;
 		}
 
 		i2cpframerate[3] = framerate_ctrl >> 4;
@@ -998,7 +981,7 @@
 		   0x2b register, see ov6630 datasheet.
 		   0x4f / 0x8a -> (30 fps -> 25 fps), 0x00 -> no adjustment */
 		__u8 i2c[] = {0xa0, 0x00, 0x2b, 0x00, 0x00, 0x00, 0x00, 0x10};
-		switch (sd->freq) {
+		switch (sd->ctrls[FREQ].val) {
 		default:
 /*		case 0:			 * no filter*/
 /*		case 2:			 * 60 hz */
@@ -1017,7 +1000,7 @@
 	}
 }
 
-#include "coarse_expo_autogain.h"
+#include "autogain_functions.h"
 
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
@@ -1025,7 +1008,8 @@
 	struct sd *sd = (struct sd *) gspca_dev;
 	int avg_lum = atomic_read(&sd->avg_lum);
 
-	if (avg_lum == -1 || !sd->autogain)
+	if ((gspca_dev->ctrl_dis & (1 << AUTOGAIN)) ||
+	    avg_lum == -1 || !sd->ctrls[AUTOGAIN].val)
 		return;
 
 	if (sd->autogain_ignore_frames > 0) {
@@ -1045,17 +1029,20 @@
 	}
 
 	if (sensor_data[sd->sensor].flags & F_COARSE_EXPO)
-		result = gspca_coarse_grained_expo_autogain(gspca_dev, avg_lum,
-				sd->brightness * desired_avg_lum / 127,
+		result = coarse_grained_expo_autogain(gspca_dev, avg_lum,
+				sd->ctrls[BRIGHTNESS].val
+						* desired_avg_lum / 127,
 				deadzone);
 	else
-		result = gspca_auto_gain_n_exposure(gspca_dev, avg_lum,
-				sd->brightness * desired_avg_lum / 127,
+		result = auto_gain_n_exposure(gspca_dev, avg_lum,
+				sd->ctrls[BRIGHTNESS].val
+						* desired_avg_lum / 127,
 				deadzone, GAIN_KNEE, EXPOSURE_KNEE);
 
 	if (result) {
 		PDEBUG(D_FRAM, "autogain: gain changed: gain: %d expo: %d",
-			(int)sd->gain, (int)sd->exposure);
+			(int) sd->ctrls[GAIN].val,
+			(int) sd->ctrls[EXPOSURE].val);
 		sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
 	}
 }
@@ -1074,9 +1061,15 @@
 	/* copy the webcam info from the device id */
 	sd->sensor = id->driver_info >> 8;
 	sd->bridge = id->driver_info & 0xff;
+
 	gspca_dev->ctrl_dis = sensor_data[sd->sensor].ctrl_dis;
+#if AUTOGAIN_DEF
+	if (!(gspca_dev->ctrl_dis & (1 << AUTOGAIN)))
+		gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
+#endif
 
 	cam = &gspca_dev->cam;
+	cam->ctrls = sd->ctrls;
 	if (!(sensor_data[sd->sensor].flags & F_SIF)) {
 		cam->cam_mode = vga_mode;
 		cam->nmodes = ARRAY_SIZE(vga_mode);
@@ -1086,20 +1079,11 @@
 	}
 	cam->npkt = 36;			/* 36 packets per ISOC message */
 
-	sd->brightness = BRIGHTNESS_DEF;
-	sd->gain = GAIN_DEF;
 	if (sensor_data[sd->sensor].flags & F_COARSE_EXPO) {
-		sd->exposure = COARSE_EXPOSURE_DEF;
-		gspca_dev->ctrl_dis |= (1 << EXPOSURE_IDX);
-	} else {
-		sd->exposure = EXPOSURE_DEF;
-		gspca_dev->ctrl_dis |= (1 << COARSE_EXPOSURE_IDX);
+		sd->ctrls[EXPOSURE].min = COARSE_EXPOSURE_MIN;
+		sd->ctrls[EXPOSURE].max = COARSE_EXPOSURE_MAX;
+		sd->ctrls[EXPOSURE].def = COARSE_EXPOSURE_DEF;
 	}
-	if (gspca_dev->ctrl_dis & (1 << AUTOGAIN_IDX))
-		sd->autogain = 0; /* Disable do_autogain callback */
-	else
-		sd->autogain = AUTOGAIN_DEF;
-	sd->freq = FREQ_DEF;
 
 	return 0;
 }
@@ -1398,65 +1382,11 @@
 	}
 }
 
-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)
-		setbrightness(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_setgain(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->gain = val;
-	if (gspca_dev->streaming)
-		setgain(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_setexposure(struct gspca_dev *gspca_dev, __s32 val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	sd->exposure = val;
-	if (gspca_dev->streaming)
-		setexposure(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_setautogain(struct gspca_dev *gspca_dev, __s32 val)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 
-	sd->autogain = val;
+	sd->ctrls[AUTOGAIN].val = val;
 	sd->exp_too_high_cnt = 0;
 	sd->exp_too_low_cnt = 0;
 
@@ -1464,9 +1394,10 @@
 	   we are on a valid point of the autogain gain /
 	   exposure knee graph, and give this change time to
 	   take effect before doing autogain. */
-	if (sd->autogain && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
-		sd->exposure = EXPOSURE_DEF;
-		sd->gain = GAIN_DEF;
+	if (sd->ctrls[AUTOGAIN].val
+	 && !(sensor_data[sd->sensor].flags & F_COARSE_EXPO)) {
+		sd->ctrls[EXPOSURE].val = sd->ctrls[EXPOSURE].def;
+		sd->ctrls[GAIN].val = sd->ctrls[GAIN].def;
 		if (gspca_dev->streaming) {
 			sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
 			setexposure(gspca_dev);
@@ -1474,32 +1405,11 @@
 		}
 	}
 
-	return 0;
-}
-
-static int sd_getautogain(struct gspca_dev *gspca_dev, __s32 *val)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
-
-	*val = sd->autogain;
-	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;
+	if (sd->ctrls[AUTOGAIN].val)
+		gspca_dev->ctrl_inac = (1 << GAIN) | (1 << EXPOSURE);
+	else
+		gspca_dev->ctrl_inac = 0;
 
-	*val = sd->freq;
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/sonixj.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/sonixj.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/sonixj.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/sonixj.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,8 +29,6 @@
 MODULE_DESCRIPTION("GSPCA/SONIX JPEG USB Camera Driver");
 MODULE_LICENSE("GPL");
 
-static int starcam;
-
 /* controls */
 enum e_ctrl {
 	BRIGHTNESS,
@@ -57,11 +55,18 @@
 	atomic_t avg_lum;
 	u32 exposure;
 
+	struct work_struct work;
+	struct workqueue_struct *work_thread;
+
+	u32 pktsz;			/* (used by pkt_scan) */
+	u16 npkt;
+	u8 nchg;
+	s8 short_mark;
+
 	u8 quality;			/* image quality */
-#define QUALITY_MIN 60
-#define QUALITY_MAX 95
-#define QUALITY_DEF 80
-	u8 jpegqual;			/* webcam quality */
+#define QUALITY_MIN 25
+#define QUALITY_MAX 90
+#define QUALITY_DEF 70
 
 	u8 reg01;
 	u8 reg17;
@@ -99,6 +104,8 @@
 	SENSOR_SP80708,
 };
 
+static void qual_upd(struct work_struct *work);
+
 /* device flags */
 #define F_PDN_INV	0x01	/* inverse pin S_PWR_DN / sn_xxx tables */
 #define F_ILLUM		0x02	/* presence of illuminator */
@@ -401,7 +408,7 @@
 
 static const u8 sn_mi0360[0x1c] = {
 /*	reg0	reg1	reg2	reg3	reg4	reg5	reg6	reg7 */
-	0x00,	0x61,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
+	0x00,	0x63,	0x40,	0x00,	0x1a,	0x20,	0x20,	0x20,
 /*	reg8	reg9	rega	regb	regc	regd	rege	regf */
 	0x81,	0x5d,	0x00,	0x00,	0x00,	0x00,	0x00,	0x00,
 /*	reg10	reg11	reg12	reg13	reg14	reg15	reg16	reg17 */
@@ -847,18 +854,8 @@
 	{0xb1, 0x5c, 0x01, 0x00, 0x01, 0x00, 0x00, 0x10}, /* IFP select */
 	{0xb1, 0x5c, 0x08, 0x04, 0x80, 0x00, 0x00, 0x10}, /* output fmt ctrl */
 	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10}, /* op mode ctrl */
-	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x03, 0x01, 0xe1, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x04, 0x02, 0x81, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10},
 	{0xb1, 0x5c, 0x01, 0x00, 0x04, 0x00, 0x00, 0x10}, /* sensor select */
-	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x03, 0x01, 0xe6, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x04, 0x02, 0x86, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x05, 0x00, 0x04, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x06, 0x00, 0x00, 0x00, 0x00, 0x10},
 	{0xb1, 0x5c, 0x08, 0x00, 0x08, 0x00, 0x00, 0x10}, /* row start */
-	{0xb1, 0x5c, 0x0e, 0x00, 0x08, 0x00, 0x00, 0x10},
 	{0xb1, 0x5c, 0x02, 0x00, 0x16, 0x00, 0x00, 0x10}, /* col start */
 	{0xb1, 0x5c, 0x03, 0x01, 0xe7, 0x00, 0x00, 0x10}, /* window height */
 	{0xb1, 0x5c, 0x04, 0x02, 0x87, 0x00, 0x00, 0x10}, /* window width */
@@ -872,15 +869,10 @@
 	{}
 };
 static const u8 mt9v111_sensor_param1[][8] = {
-	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x20, 0x00, 0x00, 0x00, 0x00, 0x10},
-	{0xb1, 0x5c, 0x09, 0x01, 0x2c, 0x00, 0x00, 0x10},
-	{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xa0, 0x10}, /* green1 gain */
-	{0xd1, 0x5c, 0x2d, 0x00, 0xa0, 0x00, 0x33, 0x10}, /* red gain */
-	/*******/
-	{0xb1, 0x5c, 0x06, 0x00, 0x1e, 0x00, 0x00, 0x10}, /* vert blanking */
-	{0xb1, 0x5c, 0x05, 0x00, 0x0a, 0x00, 0x00, 0x10}, /* horiz blanking */
-	{0xd1, 0x5c, 0x2c, 0x00, 0xad, 0x00, 0xad, 0x10}, /* blue gain */
+	{0xd1, 0x5c, 0x2b, 0x00, 0x33, 0x00, 0xad, 0x10}, /* G1 and B gains */
+	{0xd1, 0x5c, 0x2d, 0x00, 0xad, 0x00, 0x33, 0x10}, /* R and G2 gains */
+	{0xb1, 0x5c, 0x06, 0x00, 0x40, 0x00, 0x00, 0x10}, /* vert blanking */
+	{0xb1, 0x5c, 0x05, 0x00, 0x09, 0x00, 0x00, 0x10}, /* horiz blanking */
 	{0xb1, 0x5c, 0x35, 0x01, 0xc0, 0x00, 0x00, 0x10}, /* global gain */
 	{}
 };
@@ -1784,7 +1776,12 @@
 
 	sd->ag_cnt = -1;
 	sd->quality = QUALITY_DEF;
-	sd->jpegqual = 80;
+
+	/* if USB 1.1, let some bandwidth for the audio device */
+	if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
+		gspca_dev->nbalt--;
+
+	INIT_WORK(&sd->work, qual_upd);
 
 	return 0;
 }
@@ -1794,7 +1791,7 @@
 {
 	struct sd *sd = (struct sd *) gspca_dev;
 	const u8 *sn9c1xx;
-	u8 regGpio[] = { 0x29, 0x74 };		/* with audio */
+	u8 regGpio[] = { 0x29, 0x70 };		/* no audio */
 	u8 regF1;
 
 	/* setup a selector by bridge */
@@ -1806,6 +1803,8 @@
 	if (gspca_dev->usb_err < 0)
 		return gspca_dev->usb_err;
 	PDEBUG(D_PROBE, "Sonix chip id: %02x", regF1);
+	if (gspca_dev->audio)
+		regGpio[1] |= 0x04;		/* with audio */
 	switch (sd->bridge) {
 	case BRIDGE_SN9C102P:
 	case BRIDGE_SN9C105:
@@ -1838,14 +1837,7 @@
 	case BRIDGE_SN9C102P:
 		reg_w1(gspca_dev, 0x02, regGpio[1]);
 		break;
-	case BRIDGE_SN9C105:
-		reg_w(gspca_dev, 0x01, regGpio, 2);
-		break;
-	case BRIDGE_SN9C110:
-		reg_w1(gspca_dev, 0x02, 0x62);
-		break;
-	case BRIDGE_SN9C120:
-		regGpio[1] = 0x70;		/* no audio */
+	default:
 		reg_w(gspca_dev, 0x01, regGpio, 2);
 		break;
 	}
@@ -1944,10 +1936,10 @@
 		u8 expo_c1[] =
 			{ 0xb1, 0x5c, 0x09, 0x00, 0x00, 0x00, 0x00, 0x10 };
 
-		if (expo > 0x0280)
-			expo = 0x0280;
-		else if (expo < 0x0040)
-			expo = 0x0040;
+		if (expo > 0x0390)
+			expo = 0x0390;
+		else if (expo < 0x0060)
+			expo = 0x0060;
 		expo_c1[3] = expo >> 8;
 		expo_c1[4] = expo;
 		i2c_w8(gspca_dev, expo_c1);
@@ -2004,10 +1996,13 @@
 		sd->exposure = setexposure(gspca_dev, expo);
 		break;
 	case SENSOR_GC0307:
-	case SENSOR_MT9V111:
 		expo = brightness;
 		sd->exposure = setexposure(gspca_dev, expo);
 		return;			/* don't set the Y offset */
+	case SENSOR_MT9V111:
+		expo = brightness << 2;
+		sd->exposure = setexposure(gspca_dev, expo);
+		return;			/* don't set the Y offset */
 	case SENSOR_OM6802:
 		expo = brightness << 2;
 		sd->exposure = setexposure(gspca_dev, expo);
@@ -2199,14 +2194,11 @@
 			sd->ctrls[ILLUM].val ? 0x64 : 0x60);
 		break;
 	case SENSOR_MT9V111:
-		if (starcam)
-			reg_w1(gspca_dev, 0x02,
-				sd->ctrls[ILLUM].val ?
-						0x55 : 0x54);	/* 370i */
-		else
-			reg_w1(gspca_dev, 0x02,
-				sd->ctrls[ILLUM].val ?
-						0x66 : 0x64);	/* Clip */
+		reg_w1(gspca_dev, 0x02,
+			sd->ctrls[ILLUM].val ? 0x77 : 0x74);
+/* should have been: */
+/*						0x55 : 0x54);	* 370i */
+/*						0x66 : 0x64);	* Clip */
 		break;
 	}
 }
@@ -2271,18 +2263,12 @@
 static void setjpegqual(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int i, sc;
 
-	if (sd->jpegqual < 50)
-		sc = 5000 / sd->jpegqual;
-	else
-		sc = 200 - sd->jpegqual * 2;
+	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 #if USB_BUF_SZ < 64
 #error "No room enough in usb_buf for quantization table"
 #endif
-	for (i = 0; i < 64; i++)
-		gspca_dev->usb_buf[i] =
-			(jpeg_head[JPEG_QT0_OFFSET + i] * sc + 50) / 100;
+	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT0_OFFSET], 64);
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
 			0x08,
@@ -2290,9 +2276,7 @@
 			0x0100, 0,
 			gspca_dev->usb_buf, 64,
 			500);
-	for (i = 0; i < 64; i++)
-		gspca_dev->usb_buf[i] =
-			(jpeg_head[JPEG_QT1_OFFSET + i] * sc + 50) / 100;
+	memcpy(gspca_dev->usb_buf, &sd->jpeg_hdr[JPEG_QT1_OFFSET], 64);
 	usb_control_msg(gspca_dev->dev,
 			usb_sndctrlpipe(gspca_dev->dev, 0),
 			0x08,
@@ -2305,6 +2289,19 @@
 	reg_w1(gspca_dev, 0x18, sd->reg18);
 }
 
+/* JPEG quality update */
+/* This function is executed from a work queue. */
+static void qual_upd(struct work_struct *work)
+{
+	struct sd *sd = container_of(work, struct sd, work);
+	struct gspca_dev *gspca_dev = &sd->gspca_dev;
+
+	mutex_lock(&gspca_dev->usb_lock);
+	PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
+	setjpegqual(gspca_dev);
+	mutex_unlock(&gspca_dev->usb_lock);
+}
+
 /* -- start the camera -- */
 static int sd_start(struct gspca_dev *gspca_dev)
 {
@@ -2338,7 +2335,6 @@
 	/* create the JPEG header */
 	jpeg_define(sd->jpeg_hdr, gspca_dev->height, gspca_dev->width,
 			0x21);		/* JPEG 422 */
-	jpeg_set_qual(sd->jpeg_hdr, sd->quality);
 
 	/* initialize the bridge */
 	sn9c1xx = sn_tb[sd->sensor];
@@ -2619,6 +2615,11 @@
 	setcolors(gspca_dev);
 	setautogain(gspca_dev);
 	setfreq(gspca_dev);
+
+	sd->pktsz = sd->npkt = 0;
+	sd->nchg = sd->short_mark = 0;
+	sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+
 	return gspca_dev->usb_err;
 }
 
@@ -2695,6 +2696,20 @@
 	/* reg_w1(gspca_dev, 0xf1, 0x01); */
 }
 
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	if (sd->work_thread != NULL) {
+		mutex_unlock(&gspca_dev->usb_lock);
+		destroy_workqueue(sd->work_thread);
+		mutex_lock(&gspca_dev->usb_lock);
+		sd->work_thread = NULL;
+	}
+}
+
 static void do_autogain(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -2732,6 +2747,7 @@
 					(unsigned int) (expotimes << 8));
 			break;
 		case SENSOR_OM6802:
+		case SENSOR_MT9V111:
 			expotimes = sd->exposure;
 			expotimes += (luma_mean - delta) >> 2;
 			if (expotimes < 0)
@@ -2744,7 +2760,6 @@
 /*		case SENSOR_MO4000: */
 /*		case SENSOR_MI0360: */
 /*		case SENSOR_MI0360B: */
-/*		case SENSOR_MT9V111: */
 			expotimes = sd->exposure;
 			expotimes += (luma_mean - delta) >> 6;
 			if (expotimes < 0)
@@ -2757,6 +2772,29 @@
 	}
 }
 
+/* set the average luminosity from an isoc marker */
+static void set_lum(struct sd *sd,
+		    u8 *data)
+{
+	int avg_lum;
+
+	/*	w0 w1 w2
+	 *	w3 w4 w5
+	 *	w6 w7 w8
+	 */
+	avg_lum = (data[27] << 8) + data[28]		/* w3 */
+
+		+ (data[31] << 8) + data[32]		/* w5 */
+
+		+ (data[23] << 8) + data[24]		/* w1 */
+
+		+ (data[35] << 8) + data[36]		/* w7 */
+
+		+ (data[29] << 10) + (data[30] << 2);	/* w4 * 4 */
+	avg_lum >>= 10;
+	atomic_set(&sd->avg_lum, avg_lum);
+}
+
 /* scan the URB packets */
 /* This function is run at interrupt level. */
 static void sd_pkt_scan(struct gspca_dev *gspca_dev,
@@ -2764,70 +2802,141 @@
 			int len)			/* iso packet length */
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	int sof, avg_lum;
+	int i, new_qual;
 
-	/* the image ends on a 64 bytes block starting with
-	 *	ff d9 ff ff 00 c4 c4 96
-	 * and followed by various information including luminosity */
-	/* this block may be splitted between two packets */
-	/* a new image always starts in a new packet */
-	switch (gspca_dev->last_packet_type) {
-	case DISCARD_PACKET:		/* restart image building */
-		sof = len - 64;
-		if (sof >= 0 && data[sof] == 0xff && data[sof + 1] == 0xd9)
-			gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-		return;
-	case LAST_PACKET:		/* put the JPEG 422 header */
+	/*
+	 * A frame ends on the marker
+	 *		ff ff 00 c4 c4 96 ..
+	 * which is 62 bytes long and is followed by various information
+	 * including statuses and luminosity.
+	 *
+	 * A marker may be splitted on two packets.
+	 *
+	 * The 6th byte of a marker contains the bits:
+	 *	0x08: USB full
+	 *	0xc0: frame sequence
+	 * When the bit 'USB full' is set, the frame must be discarded;
+	 * this is also the case when the 2 bytes before the marker are
+	 * not the JPEG end of frame ('ff d9').
+	 */
+
+/*fixme: assumption about the following code:
+ *	- there can be only one marker in a packet
+ */
+
+	/* skip the remaining bytes of a short marker */
+	i = sd->short_mark;
+	if (i != 0) {
+		sd->short_mark = 0;
+		if (i < 0	/* if 'ff' at end of previous packet */
+		 && data[0] == 0xff
+		 && data[1] == 0x00)
+			goto marker_found;
+		if (data[0] == 0xff && data[1] == 0xff) {
+			i = 0;
+			goto marker_found;
+		}
+		len -= i;
+		if (len <= 0)
+			return;
+		data += i;
+	}
+
+	/* count the packets and their size */
+	sd->npkt++;
+	sd->pktsz += len;
+
+	/* search backwards if there is a marker in the packet */
+	for (i = len - 1; --i >= 0; ) {
+		if (data[i] != 0xff) {
+			i--;
+			continue;
+		}
+		if (data[i + 1] == 0xff) {
+
+			/* (there may be 'ff ff' inside a marker) */
+			if (i + 2 >= len || data[i + 2] == 0x00)
+				goto marker_found;
+		}
+	}
+
+	/* no marker found */
+	/* add the JPEG header if first fragment */
+	if (data[len - 1] == 0xff)
+		sd->short_mark = -1;
+	if (gspca_dev->last_packet_type == LAST_PACKET)
 		gspca_frame_add(gspca_dev, FIRST_PACKET,
 				sd->jpeg_hdr, JPEG_HDR_SZ);
-		break;
-	}
 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+	return;
 
-	data = gspca_dev->image;
-	if (data == NULL)
-		return;
-	sof = gspca_dev->image_len - 64;
-	if (data[sof] != 0xff
-	 || data[sof + 1] != 0xd9)
-		return;
+	/* marker found */
+	/* if some error, discard the frame and decrease the quality */
+marker_found:
+	new_qual = 0;
+	if (i > 2) {
+		if (data[i - 2] != 0xff || data[i - 1] != 0xd9) {
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+			new_qual = -3;
+		}
+	} else if (i + 6 < len) {
+		if (data[i + 6] & 0x08) {
+			gspca_dev->last_packet_type = DISCARD_PACKET;
+			new_qual = -5;
+		}
+	}
 
-	/* end of image found - remove the trailing data */
-	gspca_dev->image_len = sof + 2;
-	gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
-	if (sd->ag_cnt < 0)
-		return;
-/* w1 w2 w3 */
-/* w4 w5 w6 */
-/* w7 w8 */
-/* w4 */
-	avg_lum = ((data[sof + 29] << 8) | data[sof + 30]) >> 6;
-/* w6 */
-	avg_lum += ((data[sof + 33] << 8) | data[sof + 34]) >> 6;
-/* w2 */
-	avg_lum += ((data[sof + 25] << 8) | data[sof + 26]) >> 6;
-/* w8 */
-	avg_lum += ((data[sof + 37] << 8) | data[sof + 38]) >> 6;
-/* w5 */
-	avg_lum += ((data[sof + 31] << 8) | data[sof + 32]) >> 4;
-	avg_lum >>= 4;
-	atomic_set(&sd->avg_lum, avg_lum);
-}
+	gspca_frame_add(gspca_dev, LAST_PACKET, data, i);
 
-static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-			struct v4l2_jpegcompression *jcomp)
-{
-	struct sd *sd = (struct sd *) gspca_dev;
+	/* compute the filling rate and a new JPEG quality */
+	if (new_qual == 0) {
+		int r;
 
-	if (jcomp->quality < QUALITY_MIN)
-		sd->quality = QUALITY_MIN;
-	else if (jcomp->quality > QUALITY_MAX)
-		sd->quality = QUALITY_MAX;
-	else
-		sd->quality = jcomp->quality;
-	if (gspca_dev->streaming)
-		jpeg_set_qual(sd->jpeg_hdr, sd->quality);
-	return 0;
+		r = (sd->pktsz * 100) /
+			(sd->npkt *
+				gspca_dev->urb[0]->iso_frame_desc[0].length);
+		if (r >= 85)
+			new_qual = -3;
+		else if (r < 75)
+			new_qual = 2;
+	}
+	if (new_qual != 0) {
+		sd->nchg += new_qual;
+		if (sd->nchg < -6 || sd->nchg >= 12) {
+			sd->nchg = 0;
+			new_qual += sd->quality;
+			if (new_qual < QUALITY_MIN)
+				new_qual = QUALITY_MIN;
+			else if (new_qual > QUALITY_MAX)
+				new_qual = QUALITY_MAX;
+			if (new_qual != sd->quality) {
+				sd->quality = new_qual;
+				queue_work(sd->work_thread, &sd->work);
+			}
+		}
+	} else {
+		sd->nchg = 0;
+	}
+	sd->pktsz = sd->npkt = 0;
+
+	/* if the marker is smaller than 62 bytes,
+	 * memorize the number of bytes to skip in the next packet */
+	if (i + 62 > len) {			/* no more usable data */
+		sd->short_mark = i + 62 - len;
+		return;
+	}
+	if (sd->ag_cnt >= 0)
+		set_lum(sd, data + i);
+
+	/* if more data, start a new frame */
+	i += 62;
+	if (i < len) {
+		data += i;
+		len -= i;
+		gspca_frame_add(gspca_dev, FIRST_PACKET,
+				sd->jpeg_hdr, JPEG_HDR_SZ);
+		gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
+	}
 }
 
 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
@@ -2891,10 +3000,10 @@
 	.init = sd_init,
 	.start = sd_start,
 	.stopN = sd_stopN,
+	.stop0 = sd_stop0,
 	.pkt_scan = sd_pkt_scan,
 	.dq_callback = do_autogain,
 	.get_jcomp = sd_get_jcomp,
-	.set_jcomp = sd_set_jcomp,
 	.querymenu = sd_querymenu,
 #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE)
 	.int_pkt_scan = sd_int_pkt_scan,
@@ -3004,7 +3113,3 @@
 
 module_init(sd_mod_init);
 module_exit(sd_mod_exit);
-
-module_param(starcam, int, 0644);
-MODULE_PARM_DESC(starcam,
-	"StarCam model. 0: Clip, 1: 370i");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/spca500.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/spca500.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/spca500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/spca500.c	2011-05-19 00:06:34.000000000 -0400
@@ -607,7 +607,7 @@
 	reg_w(gspca_dev, 0x00, 0x8880, 2);
 	/* family cam Quicksmart stuff */
 	reg_w(gspca_dev, 0x00, 0x800a, 0x00);
-	/* Set agc transfer: synced inbetween frames */
+	/* Set agc transfer: synced between frames */
 	reg_w(gspca_dev, 0x00, 0x820f, 0x01);
 	/* Init SDRAM - needed for SDRAM access */
 	reg_w(gspca_dev, 0x00, 0x870a, 0x04);
@@ -831,7 +831,7 @@
 
 		/* familycam Quicksmart pocketDV stuff */
 		reg_w(gspca_dev, 0x00, 0x800a, 0x00);
-		/* Set agc transfer: synced inbetween frames */
+		/* Set agc transfer: synced between frames */
 		reg_w(gspca_dev, 0x00, 0x820f, 0x01);
 		/* Init SDRAM - needed for SDRAM access */
 		reg_w(gspca_dev, 0x00, 0x870a, 0x04);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/spca508.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/spca508.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/spca508.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/spca508.c	2011-05-19 00:06:34.000000000 -0400
@@ -592,7 +592,7 @@
 /* This line seems to setup the frame/canvas */
 	{0x000f, 0x8402},
 
-/* Theese 6 lines are needed to startup the webcam */
+/* These 6 lines are needed to startup the webcam */
 	{0x0090, 0x8110},
 	{0x0001, 0x8114},
 	{0x0001, 0x8114},
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/sq905.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/sq905.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/sq905.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/sq905.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
  * History and Acknowledgments
  *
  * The original Linux driver for SQ905 based cameras was written by
- * Marcell Lengyel and furter developed by many other contributers
+ * Marcell Lengyel and furter developed by many other contributors
  * and is available from http://sourceforge.net/projects/sqcam/
  *
  * This driver takes advantage of the reverse engineering work done for
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/stv06xx/stv06xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -525,11 +525,9 @@
 			  const struct usb_device_id *id)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
-	struct cam *cam;
 
 	PDEBUG(D_PROBE, "Configuring camera");
 
-	cam = &gspca_dev->cam;
 	sd->desc = sd_desc;
 	sd->bridge = id->driver_info;
 	gspca_dev->sd_desc = &sd->desc;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c	2011-05-19 00:06:34.000000000 -0400
@@ -569,7 +569,7 @@
 	if (err < 0)
 		return err;
 
-	/* Enable continous frame capture, bit 2: stop when frame complete */
+	/* Enable continuous frame capture, bit 2: stop when frame complete */
 	err = stv06xx_write_sensor(sd, HDCS_REG_CONFIG(sd), BIT(3));
 	if (err < 0)
 		return err;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/vicam.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/vicam.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/vicam.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/vicam.c	2012-03-24 03:29:40.000000000 -0400
@@ -0,0 +1,381 @@
+/*
+ * gspca ViCam subdriver
+ *
+ * Copyright (C) 2011 Hans de Goede <hdegoede@redhat.com>
+ *
+ * Based on the usbvideo vicam driver, which is:
+ *
+ * Copyright (c) 2002 Joe Burks (jburks@wavicle.org),
+ *                    Christopher L Cheney (ccheney@cheney.cx),
+ *                    Pavel Machek (pavel@ucw.cz),
+ *                    John Tyner (jtyner@cs.ucr.edu),
+ *                    Monroe Williams (monroe@pobox.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
+ */
+
+#define MODULE_NAME "vicam"
+#define HEADER_SIZE 64
+
+#include <linux/workqueue.h>
+#include <linux/slab.h>
+#include <linux/firmware.h>
+#include <linux/ihex.h>
+#include "gspca.h"
+
+MODULE_AUTHOR("Hans de Goede <hdegoede@redhat.com>");
+MODULE_DESCRIPTION("GSPCA ViCam USB Camera Driver");
+MODULE_LICENSE("GPL");
+
+enum e_ctrl {
+	GAIN,
+	EXPOSURE,
+	NCTRL		/* number of controls */
+};
+
+struct sd {
+	struct gspca_dev gspca_dev;	/* !! must be the first item */
+	struct work_struct work_struct;
+	struct workqueue_struct *work_thread;
+	struct gspca_ctrl ctrls[NCTRL];
+};
+
+/* The vicam sensor has a resolution of 512 x 244, with I believe square
+   pixels, but this is forced to a 4:3 ratio by optics. So it has
+   non square pixels :( */
+static struct v4l2_pix_format vicam_mode[] = {
+	{ 256, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+		.bytesperline = 256,
+		.sizeimage = 256 * 122,
+		.colorspace = V4L2_COLORSPACE_SRGB,},
+	/* 2 modes with somewhat more square pixels */
+	{ 256, 200, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+		.bytesperline = 256,
+		.sizeimage = 256 * 200,
+		.colorspace = V4L2_COLORSPACE_SRGB,},
+	{ 256, 240, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+		.bytesperline = 256,
+		.sizeimage = 256 * 240,
+		.colorspace = V4L2_COLORSPACE_SRGB,},
+#if 0   /* This mode has extremely non square pixels, testing use only */
+	{ 512, 122, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+		.bytesperline = 512,
+		.sizeimage = 512 * 122,
+		.colorspace = V4L2_COLORSPACE_SRGB,},
+#endif
+	{ 512, 244, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
+		.bytesperline = 512,
+		.sizeimage = 512 * 244,
+		.colorspace = V4L2_COLORSPACE_SRGB,},
+};
+
+static const struct ctrl sd_ctrls[] = {
+[GAIN] = {
+	    {
+		.id      = V4L2_CID_GAIN,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Gain",
+		.minimum = 0,
+		.maximum = 255,
+		.step    = 1,
+		.default_value = 200,
+	    },
+	},
+[EXPOSURE] = {
+	    {
+		.id      = V4L2_CID_EXPOSURE,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Exposure",
+		.minimum = 0,
+		.maximum = 2047,
+		.step    = 1,
+		.default_value = 256,
+	    },
+	},
+};
+
+static int vicam_control_msg(struct gspca_dev *gspca_dev, u8 request,
+	u16 value, u16 index, u8 *data, u16 len)
+{
+	int ret;
+
+	ret = usb_control_msg(gspca_dev->dev,
+			      usb_sndctrlpipe(gspca_dev->dev, 0),
+			      request,
+			      USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			      value, index, data, len, 1000);
+	if (ret < 0)
+		err("control msg req %02X error %d", request, ret);
+
+	return ret;
+}
+
+static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
+{
+	int ret;
+
+	ret = vicam_control_msg(gspca_dev, 0x50, state, 0, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	if (state)
+		ret = vicam_control_msg(gspca_dev, 0x55, 1, 0, NULL, 0);
+
+	return ret;
+}
+
+/*
+ *  request and read a block of data - see warning on vicam_command.
+ */
+static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
+{
+	struct sd *sd = (struct sd *)gspca_dev;
+	int ret, unscaled_height, act_len = 0;
+	u8 *req_data = gspca_dev->usb_buf;
+
+	memset(req_data, 0, 16);
+	req_data[0] = sd->ctrls[GAIN].val;
+	if (gspca_dev->width == 256)
+		req_data[1] |= 0x01; /* low nibble x-scale */
+	if (gspca_dev->height <= 122) {
+		req_data[1] |= 0x10; /* high nibble y-scale */
+		unscaled_height = gspca_dev->height * 2;
+	} else
+		unscaled_height = gspca_dev->height;
+	req_data[2] = 0x90; /* unknown, does not seem to do anything */
+	if (unscaled_height <= 200)
+		req_data[3] = 0x06; /* vend? */
+	else if (unscaled_height <= 242) /* Yes 242 not 240 */
+		req_data[3] = 0x07; /* vend? */
+	else /* Up to 244 lines with req_data[3] == 0x08 */
+		req_data[3] = 0x08; /* vend? */
+
+	if (sd->ctrls[EXPOSURE].val < 256) {
+		/* Frame rate maxed out, use partial frame expo time */
+		req_data[4] = 255 - sd->ctrls[EXPOSURE].val;
+		req_data[5] = 0x00;
+		req_data[6] = 0x00;
+		req_data[7] = 0x01;
+	} else {
+		/* Modify frame rate */
+		req_data[4] = 0x00;
+		req_data[5] = 0x00;
+		req_data[6] = sd->ctrls[EXPOSURE].val & 0xFF;
+		req_data[7] = sd->ctrls[EXPOSURE].val >> 8;
+	}
+	req_data[8] = ((244 - unscaled_height) / 2) & ~0x01; /* vstart */
+	/* bytes 9-15 do not seem to affect exposure or image quality */
+
+	mutex_lock(&gspca_dev->usb_lock);
+	ret = vicam_control_msg(gspca_dev, 0x51, 0x80, 0, req_data, 16);
+	mutex_unlock(&gspca_dev->usb_lock);
+	if (ret < 0)
+		return ret;
+
+	ret = usb_bulk_msg(gspca_dev->dev,
+			   usb_rcvbulkpipe(gspca_dev->dev, 0x81),
+			   data, size, &act_len, 10000);
+	/* successful, it returns 0, otherwise  negative */
+	if (ret < 0 || act_len != size) {
+		err("bulk read fail (%d) len %d/%d",
+			ret, act_len, size);
+		return -EIO;
+	}
+	return 0;
+}
+
+/* This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use the camera's USB interface we take the gspca
+ * usb_lock when performing USB operations. In practice the only thing we need
+ * to protect against is the usb_set_interface call that gspca makes during
+ * stream_off as the camera doesn't provide any controls that the user could try
+ * to change.
+ */
+static void vicam_dostream(struct work_struct *work)
+{
+	struct sd *sd = container_of(work, struct sd, work_struct);
+	struct gspca_dev *gspca_dev = &sd->gspca_dev;
+	int ret, frame_sz;
+	u8 *buffer;
+
+	frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage +
+		   HEADER_SIZE;
+	buffer = kmalloc(frame_sz, GFP_KERNEL | GFP_DMA);
+	if (!buffer) {
+		err("Couldn't allocate USB buffer");
+		goto exit;
+	}
+
+	while (gspca_dev->present && gspca_dev->streaming) {
+		ret = vicam_read_frame(gspca_dev, buffer, frame_sz);
+		if (ret < 0)
+			break;
+
+		/* Note the frame header contents seem to be completely
+		   constant, they do not change with either image, or
+		   settings. So we simply discard it. The frames have
+		   a very similar 64 byte footer, which we don't even
+		   bother reading from the cam */
+		gspca_frame_add(gspca_dev, FIRST_PACKET,
+				buffer + HEADER_SIZE,
+				frame_sz - HEADER_SIZE);
+		gspca_frame_add(gspca_dev, LAST_PACKET, NULL, 0);
+	}
+exit:
+	kfree(buffer);
+}
+
+/* This function is called at probe time just before sd_init */
+static int sd_config(struct gspca_dev *gspca_dev,
+		const struct usb_device_id *id)
+{
+	struct cam *cam = &gspca_dev->cam;
+	struct sd *sd = (struct sd *)gspca_dev;
+
+	/* We don't use the buffer gspca allocates so make it small. */
+	cam->bulk = 1;
+	cam->bulk_size = 64;
+	cam->cam_mode = vicam_mode;
+	cam->nmodes = ARRAY_SIZE(vicam_mode);
+	cam->ctrls = sd->ctrls;
+
+	INIT_WORK(&sd->work_struct, vicam_dostream);
+
+	return 0;
+}
+
+/* this function is called at probe and resume time */
+static int sd_init(struct gspca_dev *gspca_dev)
+{
+	int ret;
+	const struct ihex_binrec *rec;
+	const struct firmware *uninitialized_var(fw);
+	u8 *firmware_buf;
+
+	ret = reject_firmware(&fw, "/*(DEBLOBBED)*/",
+				    &gspca_dev->dev->dev);
+	if (ret) {
+		err("Failed to load \"/*(DEBLOBBED)*/\": %d\n", ret);
+		return ret;
+	}
+
+	firmware_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!firmware_buf) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+	for (rec = (void *)fw->data; rec; rec = ihex_next_binrec(rec)) {
+		memcpy(firmware_buf, rec->data, be16_to_cpu(rec->len));
+		ret = vicam_control_msg(gspca_dev, 0xff, 0, 0, firmware_buf,
+					be16_to_cpu(rec->len));
+		if (ret < 0)
+			break;
+	}
+
+	kfree(firmware_buf);
+exit:
+	release_firmware(fw);
+	return ret;
+}
+
+/* Set up for getting frames. */
+static int sd_start(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *)gspca_dev;
+	int ret;
+
+	ret = vicam_set_camera_power(gspca_dev, 1);
+	if (ret < 0)
+		return ret;
+
+	/* Start the workqueue function to do the streaming */
+	sd->work_thread = create_singlethread_workqueue(MODULE_NAME);
+	queue_work(sd->work_thread, &sd->work_struct);
+
+	return 0;
+}
+
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
+static void sd_stop0(struct gspca_dev *gspca_dev)
+{
+	struct sd *dev = (struct sd *)gspca_dev;
+
+	/* wait for the work queue to terminate */
+	mutex_unlock(&gspca_dev->usb_lock);
+	/* This waits for vicam_dostream to finish */
+	destroy_workqueue(dev->work_thread);
+	dev->work_thread = NULL;
+	mutex_lock(&gspca_dev->usb_lock);
+
+	vicam_set_camera_power(gspca_dev, 0);
+}
+
+/* Table of supported USB devices */
+static const struct usb_device_id device_table[] = {
+	{USB_DEVICE(0x04c1, 0x009d)},
+	{USB_DEVICE(0x0602, 0x1001)},
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, device_table);
+
+/* 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,
+	.stop0  = sd_stop0,
+};
+
+/* -- 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 struct usb_driver sd_driver = {
+	.name       = MODULE_NAME,
+	.id_table   = device_table,
+	.probe      = sd_probe,
+	.disconnect = gspca_disconnect,
+#ifdef CONFIG_PM
+	.suspend = gspca_suspend,
+	.resume  = gspca_resume,
+#endif
+};
+
+/* -- module insert / remove -- */
+static int __init sd_mod_init(void)
+{
+	return usb_register(&sd_driver);
+}
+
+static void __exit sd_mod_exit(void)
+{
+	usb_deregister(&sd_driver);
+}
+
+module_init(sd_mod_init);
+module_exit(sd_mod_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/zc3xx.c linux-libre-2.6.39-gnu/drivers/media/video/gspca/zc3xx.c
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/zc3xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/zc3xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * Z-Star/Vimicro zc301/zc302p/vc30x library
  *
- * Copyright (C) 2009-2010 Jean-Francois Moine <http://moinejf.free.fr>
+ * Copyright (C) 2009-2011 Jean-Francois Moine <http://moinejf.free.fr>
  * Copyright (C) 2004 2005 2006 Michel Xhaard mxhaard@magic.fr
  *
  * This program is free software; you can redistribute it and/or modify
@@ -39,6 +39,7 @@
 enum e_ctrl {
 	BRIGHTNESS,
 	CONTRAST,
+	EXPOSURE,
 	GAMMA,
 	AUTOGAIN,
 	LIGHTFREQ,
@@ -46,6 +47,8 @@
 	NCTRLS		/* number of controls */
 };
 
+#define AUTOGAIN_DEF 1
+
 /* specific webcam descriptor */
 struct sd {
 	struct gspca_dev gspca_dev;	/* !! must be the first item */
@@ -73,7 +76,7 @@
 	SENSOR_CS2102K,
 	SENSOR_GC0303,
 	SENSOR_GC0305,
-	SENSOR_HDCS2020b,
+	SENSOR_HDCS2020,
 	SENSOR_HV7131B,
 	SENSOR_HV7131R,
 	SENSOR_ICM105A,
@@ -92,7 +95,8 @@
 
 /* V4L2 controls supported by the driver */
 static void setcontrast(struct gspca_dev *gspca_dev);
-static void setautogain(struct gspca_dev *gspca_dev);
+static void setexposure(struct gspca_dev *gspca_dev);
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val);
 static void setlightfreq(struct gspca_dev *gspca_dev);
 static void setsharpness(struct gspca_dev *gspca_dev);
 
@@ -121,6 +125,18 @@
 	    },
 	    .set_control = setcontrast
 	},
+[EXPOSURE] = {
+	    {
+		.id      = V4L2_CID_EXPOSURE,
+		.type    = V4L2_CTRL_TYPE_INTEGER,
+		.name    = "Exposure",
+		.minimum = 0x30d,
+		.maximum	= 0x493e,
+		.step		= 1,
+		.default_value  = 0x927
+	    },
+	    .set_control = setexposure
+	},
 [GAMMA] = {
 	    {
 		.id      = V4L2_CID_GAMMA,
@@ -141,9 +157,10 @@
 		.minimum = 0,
 		.maximum = 1,
 		.step    = 1,
-		.default_value = 1,
+		.default_value = AUTOGAIN_DEF,
+		.flags   = V4L2_CTRL_FLAG_UPDATE
 	    },
-	    .set_control = setautogain
+	    .set = sd_setautogain
 	},
 [LIGHTFREQ] = {
 	    {
@@ -1498,7 +1515,7 @@
 	{}
 };
 
-static const struct usb_action hdcs2020b_InitialScale[] = {
+static const struct usb_action hdcs2020_InitialScale[] = {
 	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
 	{0xa0, 0x11, ZC3XX_R002_CLOCKSELECT},
 	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},	/* qtable 0x05 */
@@ -1630,7 +1647,7 @@
 	{0xa0, 0x40, ZC3XX_R118_BGAIN},
 	{}
 };
-static const struct usb_action hdcs2020b_Initial[] = {
+static const struct usb_action hdcs2020_Initial[] = {
 	{0xa0, 0x01, ZC3XX_R000_SYSTEMCONTROL},
 	{0xa0, 0x00, ZC3XX_R002_CLOCKSELECT},
 	{0xa0, 0x03, ZC3XX_R008_CLOCKSETTING},
@@ -1758,7 +1775,7 @@
 	{0xa0, 0x40, ZC3XX_R118_BGAIN},
 	{}
 };
-static const struct usb_action hdcs2020b_50HZ[] = {
+static const struct usb_action hdcs2020_50HZ[] = {
 	{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
 	{0xaa, 0x13, 0x0018},			/* 00,13,18,aa */
 	{0xaa, 0x14, 0x0001},			/* 00,14,01,aa */
@@ -1779,7 +1796,7 @@
 	{0xa0, 0x2f, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2f,cc */
 	{}
 };
-static const struct usb_action hdcs2020b_60HZ[] = {
+static const struct usb_action hdcs2020_60HZ[] = {
 	{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
 	{0xaa, 0x13, 0x0031},			/* 00,13,31,aa */
 	{0xaa, 0x14, 0x0001},			/* 00,14,01,aa */
@@ -1800,7 +1817,7 @@
 	{0xa0, 0x2c, ZC3XX_R01F_HSYNC_2}, /* 00,1f,2c,cc */
 	{}
 };
-static const struct usb_action hdcs2020b_NoFliker[] = {
+static const struct usb_action hdcs2020_NoFliker[] = {
 	{0xa0, 0x00, ZC3XX_R019_AUTOADJUSTFPS}, /* 00,19,00,cc */
 	{0xaa, 0x13, 0x0010},			/* 00,13,10,aa */
 	{0xaa, 0x14, 0x0001},			/* 00,14,01,aa */
@@ -2126,7 +2143,6 @@
 	{0xa0, 0x80, ZC3XX_R004_FRAMEWIDTHLOW},
 	{0xa0, 0x01, ZC3XX_R005_FRAMEHEIGHTHIGH},
 	{0xa0, 0xe0, ZC3XX_R006_FRAMEHEIGHTLOW},
-
 	{0xa0, 0x00, ZC3XX_R098_WINYSTARTLOW},
 	{0xa0, 0x00, ZC3XX_R09A_WINXSTARTLOW},
 	{0xa0, 0x01, ZC3XX_R09B_WINHEIGHTHIGH},
@@ -2878,7 +2894,7 @@
 	{0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
 	{0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
 	{0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
-	{0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */
+	{0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
 	{0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
 	{0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
 	{0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
@@ -2998,7 +3014,7 @@
 	{0xaa, 0x11, 0x0001}, /* 00,11,01,aa */
 	{0xaa, 0x30, 0x0000}, /* 00,30,00,aa */
 	{0xaa, 0x60, 0x0000}, /* 00,60,00,aa */
-	{0xaa, 0xa0, ZC3XX_R01A_LASTFRAMESTATE}, /* 00,a0,1a,aa */
+	{0xaa, 0xa0, 0x001a}, /* 00,a0,1a,aa */
 	{0xaa, 0xa1, 0x0000}, /* 00,a1,00,aa */
 	{0xaa, 0xa2, 0x003f}, /* 00,a2,3f,aa */
 	{0xaa, 0xa3, 0x0028}, /* 00,a3,28,aa */
@@ -3310,7 +3326,7 @@
 	{0xaa, 0x10, 0x0082},				/* 00,10,82,aa */
 	{0xaa, 0x76, 0x0003},				/* 00,76,03,aa */
 /*	{0xa0, 0x40, ZC3XX_R002_CLOCKSELECT},		 * 00,02,40,cc
-							 if mode0 (640x480) */
+							 * if mode0 (640x480) */
 	{}
 };
 static const struct usb_action ov7620_60HZ[] = {
@@ -5828,7 +5844,7 @@
 		[SENSOR_CS2102K] =	NULL,
 		[SENSOR_GC0303] =	gc0303_matrix,
 		[SENSOR_GC0305] =	gc0305_matrix,
-		[SENSOR_HDCS2020b] =	NULL,
+		[SENSOR_HDCS2020] =	NULL,
 		[SENSOR_HV7131B] =	NULL,
 		[SENSOR_HV7131R] =	po2030_matrix,
 		[SENSOR_ICM105A] =	po2030_matrix,
@@ -5927,6 +5943,26 @@
 		reg_w(gspca_dev, gr[i], 0x0130 + i);	/* gradient */
 }
 
+static void getexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->ctrls[EXPOSURE].val = (i2c_read(gspca_dev, 0x25) << 9)
+		| (i2c_read(gspca_dev, 0x26) << 1)
+		| (i2c_read(gspca_dev, 0x27) >> 7);
+}
+
+static void setexposure(struct gspca_dev *gspca_dev)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+	int val;
+
+	val = sd->ctrls[EXPOSURE].val;
+	i2c_write(gspca_dev, 0x25, val >> 9, 0x00);
+	i2c_write(gspca_dev, 0x26, val >> 1, 0x00);
+	i2c_write(gspca_dev, 0x27, val << 7, 0x00);
+}
+
 static void setquality(struct gspca_dev *gspca_dev)
 {
 	struct sd *sd = (struct sd *) gspca_dev;
@@ -5990,10 +6026,10 @@
 		{gc0305_NoFliker, gc0305_NoFliker,
 		 gc0305_50HZ, gc0305_50HZ,
 		 gc0305_60HZ, gc0305_60HZ},
-	[SENSOR_HDCS2020b] =
-		{hdcs2020b_NoFliker, hdcs2020b_NoFliker,
-		 hdcs2020b_50HZ, hdcs2020b_50HZ,
-		 hdcs2020b_60HZ, hdcs2020b_60HZ},
+	[SENSOR_HDCS2020] =
+		{hdcs2020_NoFliker, hdcs2020_NoFliker,
+		 hdcs2020_50HZ, hdcs2020_50HZ,
+		 hdcs2020_60HZ, hdcs2020_60HZ},
 	[SENSOR_HV7131B] =
 		{hv7131b_NoFliker, hv7131b_NoFlikerScale,
 		 hv7131b_50HZ, hv7131b_50HZScale,
@@ -6091,7 +6127,7 @@
 
 static void send_unknown(struct gspca_dev *gspca_dev, int sensor)
 {
-	reg_w(gspca_dev, 0x01, 0x0000);		/* led off */
+	reg_w(gspca_dev, 0x01, 0x0000);		/* bridge reset */
 	switch (sensor) {
 	case SENSOR_PAS106:
 		reg_w(gspca_dev, 0x03, 0x003a);
@@ -6310,6 +6346,7 @@
 		return 0x0a;			/* PB0330 */
 	}
 
+	/* probe gc0303 / gc0305 */
 	reg_w(gspca_dev, 0x01, 0x0000);
 	reg_w(gspca_dev, 0x01, 0x0001);
 	reg_w(gspca_dev, 0x98, 0x008b);
@@ -6414,6 +6451,10 @@
 	gspca_dev->cam.ctrls = sd->ctrls;
 	sd->quality = QUALITY_DEF;
 
+	/* if USB 1.1, let some bandwidth for the audio device */
+	if (gspca_dev->audio && gspca_dev->dev->speed < USB_SPEED_HIGH)
+		gspca_dev->nbalt--;
+
 	return 0;
 }
 
@@ -6429,7 +6470,7 @@
 		[SENSOR_CS2102K] =	5,
 		[SENSOR_GC0303] =	3,
 		[SENSOR_GC0305] =	4,
-		[SENSOR_HDCS2020b] =	4,
+		[SENSOR_HDCS2020] =	4,
 		[SENSOR_HV7131B] =	4,
 		[SENSOR_HV7131R] =	4,
 		[SENSOR_ICM105A] =	4,
@@ -6450,7 +6491,7 @@
 		[SENSOR_CS2102K] =	1,
 		[SENSOR_GC0303] =	1,
 		[SENSOR_GC0305] =	1,
-		[SENSOR_HDCS2020b] =	1,
+		[SENSOR_HDCS2020] =	1,
 		[SENSOR_HV7131B] =	1,
 		[SENSOR_HV7131R] =	1,
 		[SENSOR_ICM105A] =	1,
@@ -6513,8 +6554,8 @@
 			sd->sensor = SENSOR_CS2102;
 			break;
 		case 0x08:
-			PDEBUG(D_PROBE, "Find Sensor HDCS2020(b)");
-			sd->sensor = SENSOR_HDCS2020b;
+			PDEBUG(D_PROBE, "Find Sensor HDCS2020");
+			sd->sensor = SENSOR_HDCS2020;
 			break;
 		case 0x0a:
 			PDEBUG(D_PROBE,
@@ -6619,10 +6660,19 @@
 	sd->ctrls[GAMMA].def = gamma[sd->sensor];
 
 	switch (sd->sensor) {
+	case SENSOR_HV7131R:
+		break;
 	case SENSOR_OV7630C:
-		gspca_dev->ctrl_dis = (1 << LIGHTFREQ);
+		gspca_dev->ctrl_dis = (1 << LIGHTFREQ) | (1 << EXPOSURE);
+		break;
+	default:
+		gspca_dev->ctrl_dis = (1 << EXPOSURE);
 		break;
 	}
+#if AUTOGAIN_DEF
+	if (sd->ctrls[AUTOGAIN].val)
+		gspca_dev->ctrl_inac = (1 << EXPOSURE);
+#endif
 
 	/* switch off the led */
 	reg_w(gspca_dev, 0x01, 0x0000);
@@ -6644,8 +6694,8 @@
 		{gc0303_Initial, gc0303_InitialScale},
 	[SENSOR_GC0305] =
 			{gc0305_Initial, gc0305_InitialScale},
-	[SENSOR_HDCS2020b] =
-			{hdcs2020b_Initial, hdcs2020b_InitialScale},
+	[SENSOR_HDCS2020] =
+			{hdcs2020_Initial, hdcs2020_InitialScale},
 	[SENSOR_HV7131B] =
 			{hv7131b_Initial, hv7131b_InitialScale},
 	[SENSOR_HV7131R] =
@@ -6739,7 +6789,7 @@
 	/* set the gamma tables when not set */
 	switch (sd->sensor) {
 	case SENSOR_CS2102K:		/* gamma set in xxx_Initial */
-	case SENSOR_HDCS2020b:
+	case SENSOR_HDCS2020:
 	case SENSOR_OV7630C:
 		break;
 	default:
@@ -6768,9 +6818,8 @@
 		reg_w(gspca_dev, 0x40, 0x0117);
 		break;
 	case SENSOR_HV7131R:
-		i2c_write(gspca_dev, 0x25, 0x04, 0x00);	/* exposure */
-		i2c_write(gspca_dev, 0x26, 0x93, 0x00);
-		i2c_write(gspca_dev, 0x27, 0xe0, 0x00);
+		if (!sd->ctrls[AUTOGAIN].val)
+			setexposure(gspca_dev);
 		reg_w(gspca_dev, 0x00, ZC3XX_R1A7_CALCGLOBALMEAN);
 		break;
 	case SENSOR_GC0305:
@@ -6848,6 +6897,23 @@
 	gspca_frame_add(gspca_dev, INTER_PACKET, data, len);
 }
 
+static int sd_setautogain(struct gspca_dev *gspca_dev, __s32 val)
+{
+	struct sd *sd = (struct sd *) gspca_dev;
+
+	sd->ctrls[AUTOGAIN].val = val;
+	if (val) {
+		gspca_dev->ctrl_inac |= (1 << EXPOSURE);
+	} else {
+		gspca_dev->ctrl_inac &= ~(1 << EXPOSURE);
+		if (gspca_dev->streaming)
+			getexposure(gspca_dev);
+	}
+	if (gspca_dev->streaming)
+		setautogain(gspca_dev);
+	return gspca_dev->usb_err;
+}
+
 static int sd_querymenu(struct gspca_dev *gspca_dev,
 			struct v4l2_querymenu *menu)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/gspca/zc3xx-reg.h linux-libre-2.6.39-gnu/drivers/media/video/gspca/zc3xx-reg.h
--- linux-libre-2.6.38-gnu/drivers/media/video/gspca/zc3xx-reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/gspca/zc3xx-reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -160,8 +160,6 @@
 #define ZC3XX_R1A6_YMEANAFTERAE        0x01a6
 #define ZC3XX_R1A7_CALCGLOBALMEAN      0x01a7
 
-#define ZC3XX_R1A2_BLUEMEANAFTERAGC    0x01a2
-
 /* Matrixes */
 
 /* Color matrix is like :
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c linux-libre-2.6.39-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/hdpvr/hdpvr-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,25 +52,36 @@
 	};
 
 	/* Our default information for ir-kbd-i2c.c to use */
-	init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+	init_data->ir_codes = RC_MAP_HAUPPAUGE;
 	init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 	init_data->type = RC_TYPE_RC5;
 	init_data->name = "HD-PVR";
+	init_data->polling_interval = 405; /* ms, duplicated from Windows */
 	hdpvr_ir_rx_i2c_board_info.platform_data = init_data;
 
 	return i2c_new_device(&dev->i2c_adapter, &hdpvr_ir_rx_i2c_board_info);
 }
 
 static int hdpvr_i2c_read(struct hdpvr_device *dev, int bus,
-			  unsigned char addr, char *data, int len)
+			  unsigned char addr, char *wdata, int wlen,
+			  char *data, int len)
 {
 	int ret;
 
-	if (len > sizeof(dev->i2c_buf))
+	if ((len > sizeof(dev->i2c_buf)) || (wlen > sizeof(dev->i2c_buf)))
 		return -EINVAL;
 
-	ret = usb_control_msg(dev->udev,
-			      usb_rcvctrlpipe(dev->udev, 0),
+	if (wlen) {
+		memcpy(&dev->i2c_buf, wdata, wlen);
+		ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
+				      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
+				      (bus << 8) | addr, 0, &dev->i2c_buf,
+				      wlen, 1000);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_READ, CTRL_READ_REQUEST,
 			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
 
@@ -92,16 +103,14 @@
 		return -EINVAL;
 
 	memcpy(&dev->i2c_buf, data, len);
-	ret = usb_control_msg(dev->udev,
-			      usb_sndctrlpipe(dev->udev, 0),
+	ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_WRITE, CTRL_WRITE_REQUEST,
 			      (bus << 8) | addr, 0, &dev->i2c_buf, len, 1000);
 
 	if (ret < 0)
 		return ret;
 
-	ret = usb_control_msg(dev->udev,
-			      usb_rcvctrlpipe(dev->udev, 0),
+	ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
 			      REQTYPE_I2C_WRITE_STATT, CTRL_READ_REQUEST,
 			      0, 0, &dev->i2c_buf, 2, 1000);
 
@@ -117,24 +126,49 @@
 			  int num)
 {
 	struct hdpvr_device *dev = i2c_get_adapdata(i2c_adapter);
-	int retval = 0, i, addr;
+	int retval = 0, addr;
 
 	if (num <= 0)
 		return 0;
 
 	mutex_lock(&dev->i2c_mutex);
 
-	for (i = 0; i < num && !retval; i++) {
-		addr = msgs[i].addr << 1;
+	addr = msgs[0].addr << 1;
 
-		if (msgs[i].flags & I2C_M_RD)
-			retval = hdpvr_i2c_read(dev, 1, addr, msgs[i].buf,
-						msgs[i].len);
+	if (num == 1) {
+		if (msgs[0].flags & I2C_M_RD)
+			retval = hdpvr_i2c_read(dev, 1, addr, NULL, 0,
+						msgs[0].buf, msgs[0].len);
 		else
-			retval = hdpvr_i2c_write(dev, 1, addr, msgs[i].buf,
-						 msgs[i].len);
+			retval = hdpvr_i2c_write(dev, 1, addr, msgs[0].buf,
+						 msgs[0].len);
+	} else if (num == 2) {
+		if (msgs[0].addr != msgs[1].addr) {
+			v4l2_warn(&dev->v4l2_dev, "refusing 2-phase i2c xfer "
+				  "with conflicting target addresses\n");
+			retval = -EINVAL;
+			goto out;
+		}
+
+		if ((msgs[0].flags & I2C_M_RD) || !(msgs[1].flags & I2C_M_RD)) {
+			v4l2_warn(&dev->v4l2_dev, "refusing complex xfer with "
+				  "r0=%d, r1=%d\n", msgs[0].flags & I2C_M_RD,
+				  msgs[1].flags & I2C_M_RD);
+			retval = -EINVAL;
+			goto out;
+		}
+
+		/*
+		 * Write followed by atomic read is the only complex xfer that
+		 * we actually support here.
+		 */
+		retval = hdpvr_i2c_read(dev, 1, addr, msgs[0].buf, msgs[0].len,
+					msgs[1].buf, msgs[1].len);
+	} else {
+		v4l2_warn(&dev->v4l2_dev, "refusing %d-phase i2c xfer\n", num);
 	}
 
+out:
 	mutex_unlock(&dev->i2c_mutex);
 
 	return retval ? retval : num;
@@ -158,11 +192,11 @@
 
 static int hdpvr_activate_ir(struct hdpvr_device *dev)
 {
-	char buffer[8];
+	char buffer[2];
 
 	mutex_lock(&dev->i2c_mutex);
 
-	hdpvr_i2c_read(dev, 0, 0x54, buffer, 1);
+	hdpvr_i2c_read(dev, 0, 0x54, NULL, 0, buffer, 1);
 
 	buffer[0] = 0;
 	buffer[1] = 0x8;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/hexium_gemini.c linux-libre-2.6.39-gnu/drivers/media/video/hexium_gemini.c
--- linux-libre-2.6.38-gnu/drivers/media/video/hexium_gemini.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/hexium_gemini.c	2011-05-19 00:06:34.000000000 -0400
@@ -261,7 +261,7 @@
 
 /* the saa7146 provides some controls (brightness, contrast, saturation)
    which gets registered *after* this function. because of this we have
-   to return with a value != 0 even if the function succeded.. */
+   to return with a value != 0 even if the function succeeded.. */
 static int vidioc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *qc)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/imx074.c linux-libre-2.6.39-gnu/drivers/media/video/imx074.c
--- linux-libre-2.6.38-gnu/drivers/media/video/imx074.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/imx074.c	2011-05-19 00:06:34.000000000 -0400
@@ -298,7 +298,7 @@
 static int imx074_set_bus_param(struct soc_camera_device *icd,
 				 unsigned long flags)
 {
-	return -1;
+	return -EINVAL;
 }
 
 static struct soc_camera_ops imx074_ops = {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ir-kbd-i2c.c linux-libre-2.6.39-gnu/drivers/media/video/ir-kbd-i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ir-kbd-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ir-kbd-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,10 +55,6 @@
 static int debug;
 module_param(debug, int, 0644);    /* debug level (0,1,2) */
 
-static int hauppauge;
-module_param(hauppauge, int, 0644);    /* Choose Hauppauge remote */
-MODULE_PARM_DESC(hauppauge, "Specify Hauppauge remote: 0=black, 1=grey (defaults to 0)");
-
 
 #define MODULE_NAME "ir-kbd-i2c"
 #define dprintk(level, fmt, arg...)	if (debug >= level) \
@@ -105,10 +101,6 @@
 		/* invalid key press */
 		return 0;
 
-	if (dev!=0x1e && dev!=0x1f)
-		/* not a hauppauge remote */
-		return 0;
-
 	if (!range)
 		code += 64;
 
@@ -116,7 +108,7 @@
 		start, range, toggle, dev, code);
 
 	/* return key */
-	*ir_key = code;
+	*ir_key = (dev << 8) | code;
 	*ir_raw = ircode;
 	return 1;
 }
@@ -312,11 +304,7 @@
 		name        = "Hauppauge";
 		ir->get_key = get_key_haup;
 		rc_type     = RC_TYPE_RC5;
-		if (hauppauge == 1) {
-			ir_codes    = RC_MAP_HAUPPAUGE_NEW;
-		} else {
-			ir_codes    = RC_MAP_RC5_TV;
-		}
+		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	case 0x30:
 		name        = "KNC One";
@@ -340,7 +328,7 @@
 		name        = "Hauppauge/Zilog Z8";
 		ir->get_key = get_key_haup_xvr;
 		rc_type     = RC_TYPE_RC5;
-		ir_codes    = hauppauge ? RC_MAP_HAUPPAUGE_NEW : RC_MAP_RC5_TV;
+		ir_codes    = RC_MAP_HAUPPAUGE;
 		break;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-driver.h linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-driver.h
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-driver.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-driver.h	2011-05-19 00:06:34.000000000 -0400
@@ -383,7 +383,6 @@
 	u32 open_id;                    /* unique ID for this file descriptor */
 	int type;                       /* stream type */
 	int yuv_frames;                 /* 1: started OUT_UDMA_YUV output mode */
-	enum v4l2_priority prio;        /* priority */
 	struct ivtv *itv;
 };
 
@@ -710,7 +709,6 @@
 
 	/* Miscellaneous */
 	u32 open_id;			/* incremented each time an open occurs, is >= 1 */
-	struct v4l2_prio_state prio;    /* priority state */
 	int search_pack_header;         /* 1 if ivtv_copy_buf_to_user() is scanning for a pack header (0xba) */
 	int speed;                      /* current playback speed setting */
 	u8 speed_mute_audio;            /* 1 if audio should be muted when fast forward */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtvfb.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtvfb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtvfb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtvfb.c	2011-05-19 00:06:34.000000000 -0400
@@ -1080,7 +1080,7 @@
 		kmalloc(sizeof(u32) * 16, GFP_KERNEL|__GFP_NOWARN);
 
 	if (!oi->ivtvfb_info.pseudo_palette) {
-		IVTVFB_ERR("abort, unable to alloc pseudo pallete\n");
+		IVTVFB_ERR("abort, unable to alloc pseudo palette\n");
 		return -ENOMEM;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-fileops.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-fileops.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-fileops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-fileops.c	2011-05-19 00:06:34.000000000 -0400
@@ -856,7 +856,6 @@
 
 	IVTV_DEBUG_FILE("close %s\n", s->name);
 
-	v4l2_prio_close(&itv->prio, id->prio);
 	v4l2_fh_del(fh);
 	v4l2_fh_exit(fh);
 
@@ -973,7 +972,6 @@
 	}
 	item->itv = itv;
 	item->type = s->type;
-	v4l2_prio_open(&itv->prio, &item->prio);
 
 	item->open_id = itv->open_id++;
 	filp->private_data = &item->fh;
@@ -982,6 +980,7 @@
 		/* Try to claim this stream */
 		if (ivtv_claim_stream(item, item->type)) {
 			/* No, it's already in use */
+			v4l2_fh_exit(&item->fh);
 			kfree(item);
 			return -EBUSY;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-firmware.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-firmware.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-firmware.c	2012-03-24 01:04:54.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-firmware.c	2012-03-24 03:29:13.000000000 -0400
@@ -179,7 +179,7 @@
 {
 	int i;
 
-	/* mailbox is preceeded by a 16 byte 'magic cookie' starting at a 256-byte
+	/* mailbox is preceded by a 16 byte 'magic cookie' starting at a 256-byte
 	   address boundary */
 	for (i = 0; i < size; i += 0x100) {
 		if (readl(mem + i)      == 0x12345678 &&
@@ -377,7 +377,7 @@
 			  "Reloading\n", where);
 		res = ivtv_firmware_restart(itv);
 		/*
-		 * Even if restarted ok, still signal a problem had occured.
+		 * Even if restarted ok, still signal a problem had occurred.
 		 * The caller can come through this function again to check
 		 * if things are really ok after the restart.
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-i2c.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-i2c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -205,15 +205,14 @@
 		break;
 	case IVTV_HW_I2C_IR_RX_HAUP_EXT:
 	case IVTV_HW_I2C_IR_RX_HAUP_INT:
-		/* Default to old black remote */
-		init_data->ir_codes = RC_MAP_RC5_TV;
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
 		init_data->type = RC_TYPE_RC5;
 		init_data->name = itv->card_name;
 		break;
 	case IVTV_HW_Z8F0811_IR_RX_HAUP:
 		/* Default to grey remote */
-		init_data->ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 		init_data->type = RC_TYPE_RC5;
 		init_data->name = itv->card_name;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-ioctl.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-ioctl.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -313,7 +313,7 @@
 
 static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
 
 	vbifmt->reserved[0] = 0;
@@ -334,7 +334,7 @@
 
 static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
 
@@ -358,7 +358,7 @@
 
 static int ivtv_g_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	struct v4l2_vbi_format *vbifmt = &fmt->fmt.vbi;
 
 	vbifmt->sampling_rate = 27000000;
@@ -377,7 +377,7 @@
 static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 
 	vbifmt->reserved[0] = 0;
@@ -398,7 +398,7 @@
 
 static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
 
@@ -439,7 +439,7 @@
 
 static int ivtv_g_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	struct v4l2_window *winfmt = &fmt->fmt.win;
 
 	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
@@ -463,7 +463,7 @@
 
 static int ivtv_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	int w = fmt->fmt.pix.width;
 	int h = fmt->fmt.pix.height;
@@ -492,7 +492,7 @@
 static int ivtv_try_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 
 	if (id->type == IVTV_DEC_STREAM_TYPE_VBI)
@@ -512,7 +512,7 @@
 
 static int ivtv_try_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	s32 w = fmt->fmt.pix.width;
 	s32 h = fmt->fmt.pix.height;
 	int field = fmt->fmt.pix.field;
@@ -546,7 +546,7 @@
 
 static int ivtv_try_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	u32 chromakey = fmt->fmt.win.chromakey;
 	u8 global_alpha = fmt->fmt.win.global_alpha;
 
@@ -565,7 +565,7 @@
 
 static int ivtv_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct v4l2_mbus_framefmt mbus_fmt;
 	int ret = ivtv_try_fmt_vid_cap(file, fh, fmt);
@@ -594,7 +594,7 @@
 
 static int ivtv_s_fmt_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (!ivtv_raw_vbi(itv) && atomic_read(&itv->capturing) > 0)
 		return -EBUSY;
@@ -607,7 +607,7 @@
 static int ivtv_s_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_format *fmt)
 {
 	struct v4l2_sliced_vbi_format *vbifmt = &fmt->fmt.sliced;
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	int ret = ivtv_try_fmt_sliced_vbi_cap(file, fh, fmt);
 
@@ -625,7 +625,7 @@
 
 static int ivtv_s_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct yuv_playback_info *yi = &itv->yuv_info;
 	int ret = ivtv_try_fmt_vid_out(file, fh, fmt);
@@ -670,7 +670,7 @@
 
 static int ivtv_s_fmt_vid_out_overlay(struct file *file, void *fh, struct v4l2_format *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	int ret = ivtv_try_fmt_vid_out_overlay(file, fh, fmt);
 
 	if (ret == 0) {
@@ -683,7 +683,7 @@
 
 static int ivtv_g_chip_ident(struct file *file, void *fh, struct v4l2_dbg_chip_ident *chip)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	chip->ident = V4L2_IDENT_NONE;
 	chip->revision = 0;
@@ -727,7 +727,7 @@
 
 static int ivtv_g_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (v4l2_chip_match_host(&reg->match))
 		return ivtv_itvc(itv, VIDIOC_DBG_G_REGISTER, reg);
@@ -739,7 +739,7 @@
 
 static int ivtv_s_register(struct file *file, void *fh, struct v4l2_dbg_register *reg)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (v4l2_chip_match_host(&reg->match))
 		return ivtv_itvc(itv, VIDIOC_DBG_S_REGISTER, reg);
@@ -750,26 +750,9 @@
 }
 #endif
 
-static int ivtv_g_priority(struct file *file, void *fh, enum v4l2_priority *p)
-{
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
-
-	*p = v4l2_prio_max(&itv->prio);
-
-	return 0;
-}
-
-static int ivtv_s_priority(struct file *file, void *fh, enum v4l2_priority prio)
-{
-	struct ivtv_open_id *id = fh;
-	struct ivtv *itv = id->itv;
-
-	return v4l2_prio_change(&itv->prio, &id->prio, prio);
-}
-
 static int ivtv_querycap(struct file *file, void *fh, struct v4l2_capability *vcap)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	strlcpy(vcap->driver, IVTV_DRIVER_NAME, sizeof(vcap->driver));
 	strlcpy(vcap->card, itv->card_name, sizeof(vcap->card));
@@ -781,14 +764,14 @@
 
 static int ivtv_enumaudio(struct file *file, void *fh, struct v4l2_audio *vin)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	return ivtv_get_audio_input(itv, vin->index, vin);
 }
 
 static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	vin->index = itv->audio_input;
 	return ivtv_get_audio_input(itv, vin->index, vin);
@@ -796,7 +779,7 @@
 
 static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (vout->index >= itv->nof_audio_inputs)
 		return -EINVAL;
@@ -809,7 +792,7 @@
 
 static int ivtv_enumaudout(struct file *file, void *fh, struct v4l2_audioout *vin)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	/* set it to defaults from our table */
 	return ivtv_get_audio_output(itv, vin->index, vin);
@@ -817,7 +800,7 @@
 
 static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	vin->index = 0;
 	return ivtv_get_audio_output(itv, vin->index, vin);
@@ -825,14 +808,14 @@
 
 static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	return ivtv_get_audio_output(itv, vout->index, vout);
 }
 
 static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	/* set it to defaults from our table */
 	return ivtv_get_input(itv, vin->index, vin);
@@ -840,14 +823,14 @@
 
 static int ivtv_enum_output(struct file *file, void *fh, struct v4l2_output *vout)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	return ivtv_get_output(itv, vout->index, vout);
 }
 
 static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct yuv_playback_info *yi = &itv->yuv_info;
 	int streamtype;
@@ -884,7 +867,7 @@
 
 static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct yuv_playback_info *yi = &itv->yuv_info;
 	int streamtype;
@@ -910,7 +893,7 @@
 
 static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct yuv_playback_info *yi = &itv->yuv_info;
 	int streamtype;
@@ -952,7 +935,7 @@
 
 static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	static struct v4l2_fmtdesc formats[] = {
 		{ 0, 0, 0,
@@ -980,7 +963,7 @@
 
 static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	*i = itv->active_input;
 
@@ -989,7 +972,7 @@
 
 int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (inp < 0 || inp >= itv->nof_inputs)
 		return -EINVAL;
@@ -1023,7 +1006,7 @@
 
 static int ivtv_g_output(struct file *file, void *fh, unsigned int *i)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
 		return -EINVAL;
@@ -1035,7 +1018,7 @@
 
 static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (outp >= itv->card->nof_outputs)
 		return -EINVAL;
@@ -1057,7 +1040,7 @@
 
 static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (vf->tuner != 0)
 		return -EINVAL;
@@ -1068,7 +1051,7 @@
 
 int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (vf->tuner != 0)
 		return -EINVAL;
@@ -1082,7 +1065,7 @@
 
 static int ivtv_g_std(struct file *file, void *fh, v4l2_std_id *std)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	*std = itv->std;
 	return 0;
@@ -1091,7 +1074,7 @@
 int ivtv_s_std(struct file *file, void *fh, v4l2_std_id *std)
 {
 	DEFINE_WAIT(wait);
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	struct yuv_playback_info *yi = &itv->yuv_info;
 	int f;
 
@@ -1170,7 +1153,7 @@
 
 static int ivtv_s_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 
 	if (vt->index != 0)
@@ -1183,7 +1166,7 @@
 
 static int ivtv_g_tuner(struct file *file, void *fh, struct v4l2_tuner *vt)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	if (vt->index != 0)
 		return -EINVAL;
@@ -1203,7 +1186,7 @@
 
 static int ivtv_g_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_sliced_vbi_cap *cap)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	int set = itv->is_50hz ? V4L2_SLICED_VBI_625 : V4L2_SLICED_VBI_525;
 	int f, l;
 
@@ -1233,7 +1216,7 @@
 
 static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *idx)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	struct v4l2_enc_idx_entry *e = idx->entry;
 	int entries;
 	int i;
@@ -1256,7 +1239,7 @@
 
 static int ivtv_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 
 
@@ -1308,7 +1291,7 @@
 
 static int ivtv_try_encoder_cmd(struct file *file, void *fh, struct v4l2_encoder_cmd *enc)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 
 	switch (enc->cmd) {
 	case V4L2_ENC_CMD_START:
@@ -1338,7 +1321,7 @@
 
 static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	u32 data[CX2341X_MBOX_MAX_DATA];
 	struct yuv_playback_info *yi = &itv->yuv_info;
 
@@ -1425,7 +1408,7 @@
 
 static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 	struct yuv_playback_info *yi = &itv->yuv_info;
 
@@ -1445,7 +1428,7 @@
 
 static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
 {
-	struct ivtv_open_id *id = fh;
+	struct ivtv_open_id *id = fh2id(fh);
 	struct ivtv *itv = id->itv;
 
 	if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT_OVERLAY))
@@ -1470,7 +1453,7 @@
 
 static int ivtv_log_status(struct file *file, void *fh)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
 	u32 data[CX2341X_MBOX_MAX_DATA];
 
 	int has_output = itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT;
@@ -1795,9 +1778,25 @@
 	return 0;
 }
 
-static long ivtv_default(struct file *file, void *fh, int cmd, void *arg)
+static long ivtv_default(struct file *file, void *fh, bool valid_prio,
+			 int cmd, void *arg)
 {
-	struct ivtv *itv = ((struct ivtv_open_id *)fh)->itv;
+	struct ivtv *itv = fh2id(fh)->itv;
+
+	if (!valid_prio) {
+		switch (cmd) {
+		case VIDEO_PLAY:
+		case VIDEO_STOP:
+		case VIDEO_FREEZE:
+		case VIDEO_CONTINUE:
+		case VIDEO_COMMAND:
+		case VIDEO_SELECT_SOURCE:
+		case AUDIO_SET_MUTE:
+		case AUDIO_CHANNEL_SELECT:
+		case AUDIO_BILINGUAL_CHANNEL_SELECT:
+			return -EBUSY;
+		}
+	}
 
 	switch (cmd) {
 	case VIDIOC_INT_RESET: {
@@ -1836,30 +1835,8 @@
 		unsigned int cmd, unsigned long arg)
 {
 	struct video_device *vfd = video_devdata(filp);
-	struct ivtv_open_id *id = fh2id(filp->private_data);
 	long ret;
 
-	/* check priority */
-	switch (cmd) {
-	case VIDIOC_S_CTRL:
-	case VIDIOC_S_STD:
-	case VIDIOC_S_INPUT:
-	case VIDIOC_S_OUTPUT:
-	case VIDIOC_S_TUNER:
-	case VIDIOC_S_FREQUENCY:
-	case VIDIOC_S_FMT:
-	case VIDIOC_S_CROP:
-	case VIDIOC_S_AUDIO:
-	case VIDIOC_S_AUDOUT:
-	case VIDIOC_S_EXT_CTRLS:
-	case VIDIOC_S_FBUF:
-	case VIDIOC_S_PRIORITY:
-	case VIDIOC_OVERLAY:
-		ret = v4l2_prio_check(&itv->prio, id->prio);
-		if (ret)
-			return ret;
-	}
-
 	if (ivtv_debug & IVTV_DBGFLG_IOCTL)
 		vfd->debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
 	ret = video_ioctl2(filp, cmd, arg);
@@ -1884,8 +1861,6 @@
 
 static const struct v4l2_ioctl_ops ivtv_ioctl_ops = {
 	.vidioc_querycap    		    = ivtv_querycap,
-	.vidioc_g_priority  		    = ivtv_g_priority,
-	.vidioc_s_priority  		    = ivtv_s_priority,
 	.vidioc_s_audio     		    = ivtv_s_audio,
 	.vidioc_g_audio     		    = ivtv_g_audio,
 	.vidioc_enumaudio   		    = ivtv_enumaudio,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-streams.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-streams.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-streams.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-streams.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,6 +214,7 @@
 	s->vdev->fops = ivtv_stream_info[type].fops;
 	s->vdev->release = video_device_release;
 	s->vdev->tvnorms = V4L2_STD_ALL;
+	set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
 	ivtv_set_funcs(s->vdev);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-udma.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-udma.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-udma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-udma.c	2011-05-19 00:06:34.000000000 -0400
@@ -132,7 +132,12 @@
 	if (user_dma.page_count != err) {
 		IVTV_DEBUG_WARN("failed to map user pages, returned %d instead of %d\n",
 			   err, user_dma.page_count);
-		return -EINVAL;
+		if (err >= 0) {
+			for (i = 0; i < err; i++)
+				put_page(dma->map[i]);
+			return -EINVAL;
+		}
+		return err;
 	}
 
 	dma->page_count = user_dma.page_count;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-vbi.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-vbi.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-vbi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-vbi.c	2011-05-19 00:06:34.000000000 -0400
@@ -174,7 +174,7 @@
 			ret = -EFAULT;
 			break;
 		}
-		ivtv_write_vbi_line(itv, sliced + i, &cc, &found_cc);
+		ivtv_write_vbi_line(itv, &d, &cc, &found_cc);
 	}
 
 	if (found_cc)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-yuv.c linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-yuv.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ivtv/ivtv-yuv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ivtv/ivtv-yuv.c	2011-05-19 00:06:34.000000000 -0400
@@ -77,23 +77,51 @@
 	/* Get user pages for DMA Xfer */
 	down_read(&current->mm->mmap_sem);
 	y_pages = get_user_pages(current, current->mm, y_dma.uaddr, y_dma.page_count, 0, 1, &dma->map[0], NULL);
-	uv_pages = get_user_pages(current, current->mm, uv_dma.uaddr, uv_dma.page_count, 0, 1, &dma->map[y_pages], NULL);
+	uv_pages = 0; /* silence gcc. value is set and consumed only if: */
+	if (y_pages == y_dma.page_count) {
+		uv_pages = get_user_pages(current, current->mm,
+					  uv_dma.uaddr, uv_dma.page_count, 0, 1,
+					  &dma->map[y_pages], NULL);
+	}
 	up_read(&current->mm->mmap_sem);
 
-	dma->page_count = y_dma.page_count + uv_dma.page_count;
+	if (y_pages != y_dma.page_count || uv_pages != uv_dma.page_count) {
+		int rc = -EFAULT;
 
-	if (y_pages + uv_pages != dma->page_count) {
-		IVTV_DEBUG_WARN
-		    ("failed to map user pages, returned %d instead of %d\n",
-		     y_pages + uv_pages, dma->page_count);
+		if (y_pages == y_dma.page_count) {
+			IVTV_DEBUG_WARN
+				("failed to map uv user pages, returned %d "
+				 "expecting %d\n", uv_pages, uv_dma.page_count);
 
-		for (i = 0; i < dma->page_count; i++) {
-			put_page(dma->map[i]);
+			if (uv_pages >= 0) {
+				for (i = 0; i < uv_pages; i++)
+					put_page(dma->map[y_pages + i]);
+				rc = -EFAULT;
+			} else {
+				rc = uv_pages;
+			}
+		} else {
+			IVTV_DEBUG_WARN
+				("failed to map y user pages, returned %d "
+				 "expecting %d\n", y_pages, y_dma.page_count);
 		}
-		dma->page_count = 0;
-		return -EINVAL;
+		if (y_pages >= 0) {
+			for (i = 0; i < y_pages; i++)
+				put_page(dma->map[i]);
+			/*
+			 * Inherit the -EFAULT from rc's
+			 * initialization, but allow it to be
+			 * overriden by uv_pages above if it was an
+			 * actual errno.
+			 */
+		} else {
+			rc = y_pages;
+		}
+		return rc;
 	}
 
+	dma->page_count = y_pages + uv_pages;
+
 	/* Fill & map SG List */
 	if (ivtv_udma_fill_sg_list (dma, &uv_dma, ivtv_udma_fill_sg_list (dma, &y_dma, 0)) < 0) {
 		IVTV_DEBUG_WARN("could not allocate bounce buffers for highmem userspace buffers\n");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/Kconfig linux-libre-2.6.39-gnu/drivers/media/video/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/video/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -42,8 +42,30 @@
 
 config V4L2_MEM2MEM_DEV
 	tristate
-	depends on VIDEOBUF_GEN
+	depends on VIDEOBUF2_CORE
+
+config VIDEOBUF2_CORE
+	tristate
+
+config VIDEOBUF2_MEMOPS
+	tristate
+
+config VIDEOBUF2_DMA_CONTIG
+	select VIDEOBUF2_CORE
+	select VIDEOBUF2_MEMOPS
+	tristate
+
+config VIDEOBUF2_VMALLOC
+	select VIDEOBUF2_CORE
+	select VIDEOBUF2_MEMOPS
+	tristate
+
 
+config VIDEOBUF2_DMA_SG
+	#depends on HAS_DMA
+	select VIDEOBUF2_CORE
+	select VIDEOBUF2_MEMOPS
+	tristate
 #
 # Multimedia Video device configuration
 #
@@ -527,7 +549,7 @@
 	depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
 	depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
 	select FONT_8x16
-	select VIDEOBUF_VMALLOC
+	select VIDEOBUF2_VMALLOC
 	default n
 	---help---
 	  Enables a virtual video driver. This device shows a color bar
@@ -718,10 +740,30 @@
 	   Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
 	   with ov7670 sensors.
 
+config VIDEO_NOON010PC30
+	tristate "NOON010PC30 CIF camera sensor support"
+	depends on I2C && VIDEO_V4L2
+	---help---
+	  This driver supports NOON010PC30 CIF camera from Siliconfile
+
+config VIDEO_OMAP3
+	tristate "OMAP 3 Camera support (EXPERIMENTAL)"
+	select OMAP_IOMMU
+	depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
+	---help---
+	  Driver for an OMAP 3 camera controller.
+
+config VIDEO_OMAP3_DEBUG
+	bool "OMAP 3 Camera debug messages"
+	depends on VIDEO_OMAP3
+	---help---
+	  Enable debug messages on OMAP 3 camera controller driver.
+
 config SOC_CAMERA
 	tristate "SoC camera support"
 	depends on VIDEO_V4L2 && HAS_DMA && I2C
 	select VIDEOBUF_GEN
+	select VIDEOBUF2_CORE
 	help
 	  SoC Camera is a common API to several cameras, not connecting
 	  over a bus like PCI or USB. For example some i2c camera connected
@@ -809,6 +851,12 @@
 	help
 	  This is a ov9640 camera driver
 
+config SOC_CAMERA_OV9740
+	tristate "ov9740 camera support"
+	depends on SOC_CAMERA && I2C
+	help
+	  This is a ov9740 camera driver
+
 config MX1_VIDEO
 	bool
 
@@ -827,7 +875,7 @@
 config VIDEO_MX3
 	tristate "i.MX3x Camera Sensor Interface driver"
 	depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
-	select VIDEOBUF_DMA_CONTIG
+	select VIDEOBUF2_DMA_CONTIG
 	select MX3_VIDEO
 	---help---
 	  This is a v4l2 driver for the i.MX3x Camera Sensor Interface
@@ -848,7 +896,7 @@
 config VIDEO_SH_MOBILE_CEU
 	tristate "SuperH Mobile CEU Interface driver"
 	depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
-	select VIDEOBUF_DMA_CONTIG
+	select VIDEOBUF2_DMA_CONTIG
 	---help---
 	  This is a v4l2 driver for the SuperH Mobile CEU Interface
 
@@ -967,7 +1015,7 @@
 config VIDEO_MEM2MEM_TESTDEV
 	tristate "Virtual test device for mem2mem framework"
 	depends on VIDEO_DEV && VIDEO_V4L2
-	select VIDEOBUF_VMALLOC
+	select VIDEOBUF2_VMALLOC
 	select V4L2_MEM2MEM_DEV
 	default n
 	---help---
@@ -977,7 +1025,7 @@
 config  VIDEO_SAMSUNG_S5P_FIMC
 	tristate "Samsung S5P FIMC (video postprocessor) driver"
 	depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
-	select VIDEOBUF_DMA_CONTIG
+	select VIDEOBUF2_DMA_CONTIG
 	select V4L2_MEM2MEM_DEV
 	help
 	  This is a v4l2 driver for the S5P camera interface
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/m52790.c linux-libre-2.6.39-gnu/drivers/media/video/m52790.c
--- linux-libre-2.6.38-gnu/drivers/media/video/m52790.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/m52790.c	2011-05-19 00:06:34.000000000 -0400
@@ -174,7 +174,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct m52790_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct m52790_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/Makefile linux-libre-2.6.39-gnu/drivers/media/video/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/video/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 omap2cam-objs	:=	omap24xxcam.o omap24xxcam-dma.o
 
 videodev-objs	:=	v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
-			v4l2-event.o v4l2-ctrls.o
+			v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
 
 # V4L2 core modules
 
@@ -67,6 +67,7 @@
 obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
 obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
 obj-$(CONFIG_VIDEO_SR030PC30)	+= sr030pc30.o
+obj-$(CONFIG_VIDEO_NOON010PC30)	+= noon010pc30.o
 
 obj-$(CONFIG_SOC_CAMERA_IMX074)		+= imx074.o
 obj-$(CONFIG_SOC_CAMERA_MT9M001)	+= mt9m001.o
@@ -78,6 +79,7 @@
 obj-$(CONFIG_SOC_CAMERA_OV6650)		+= ov6650.o
 obj-$(CONFIG_SOC_CAMERA_OV772X)		+= ov772x.o
 obj-$(CONFIG_SOC_CAMERA_OV9640)		+= ov9640.o
+obj-$(CONFIG_SOC_CAMERA_OV9740)		+= ov9740.o
 obj-$(CONFIG_SOC_CAMERA_RJ54N1)		+= rj54n1cb0c.o
 obj-$(CONFIG_SOC_CAMERA_TW9910)		+= tw9910.o
 
@@ -111,6 +113,12 @@
 obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
 obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
 
+obj-$(CONFIG_VIDEOBUF2_CORE)		+= videobuf2-core.o
+obj-$(CONFIG_VIDEOBUF2_MEMOPS)		+= videobuf2-memops.o
+obj-$(CONFIG_VIDEOBUF2_VMALLOC)		+= videobuf2-vmalloc.o
+obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG)	+= videobuf2-dma-contig.o
+obj-$(CONFIG_VIDEOBUF2_DMA_SG)		+= videobuf2-dma-sg.o
+
 obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
 
 obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
@@ -121,6 +129,8 @@
 
 obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
 
+obj-$(CONFIG_VIDEO_OMAP3)	+= omap3isp/
+
 obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
 obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/mem2mem_testdev.c linux-libre-2.6.39-gnu/drivers/media/video/mem2mem_testdev.c
--- linux-libre-2.6.38-gnu/drivers/media/video/mem2mem_testdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/mem2mem_testdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
  * operation (via the mem2mem framework).
  *
  * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * Pawel Osciak, <p.osciak@samsung.com>
+ * Pawel Osciak, <pawel@osciak.com>
  * Marek Szyprowski, <m.szyprowski@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -28,12 +28,12 @@
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf-vmalloc.h>
+#include <media/videobuf2-vmalloc.h>
 
 #define MEM2MEM_TEST_MODULE_NAME "mem2mem-testdev"
 
 MODULE_DESCRIPTION("Virtual device for mem2mem framework testing");
-MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>");
+MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
 MODULE_LICENSE("GPL");
 
 
@@ -201,11 +201,6 @@
 	struct v4l2_m2m_ctx	*m2m_ctx;
 };
 
-struct m2mtest_buffer {
-	/* vb must be first! */
-	struct videobuf_buffer	vb;
-};
-
 static struct v4l2_queryctrl *get_ctrl(int id)
 {
 	int i;
@@ -219,37 +214,41 @@
 }
 
 static int device_process(struct m2mtest_ctx *ctx,
-			  struct m2mtest_buffer *in_buf,
-			  struct m2mtest_buffer *out_buf)
+			  struct vb2_buffer *in_vb,
+			  struct vb2_buffer *out_vb)
 {
 	struct m2mtest_dev *dev = ctx->dev;
+	struct m2mtest_q_data *q_data;
 	u8 *p_in, *p_out;
 	int x, y, t, w;
 	int tile_w, bytes_left;
-	struct videobuf_queue *src_q;
-	struct videobuf_queue *dst_q;
+	int width, height, bytesperline;
 
-	src_q = v4l2_m2m_get_src_vq(ctx->m2m_ctx);
-	dst_q = v4l2_m2m_get_dst_vq(ctx->m2m_ctx);
-	p_in = videobuf_queue_to_vaddr(src_q, &in_buf->vb);
-	p_out = videobuf_queue_to_vaddr(dst_q, &out_buf->vb);
+	q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
+
+	width	= q_data->width;
+	height	= q_data->height;
+	bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
+
+	p_in = vb2_plane_vaddr(in_vb, 0);
+	p_out = vb2_plane_vaddr(out_vb, 0);
 	if (!p_in || !p_out) {
 		v4l2_err(&dev->v4l2_dev,
 			 "Acquiring kernel pointers to buffers failed\n");
 		return -EFAULT;
 	}
 
-	if (in_buf->vb.size > out_buf->vb.size) {
+	if (vb2_plane_size(in_vb, 0) > vb2_plane_size(out_vb, 0)) {
 		v4l2_err(&dev->v4l2_dev, "Output buffer is too small\n");
 		return -EINVAL;
 	}
 
-	tile_w = (in_buf->vb.width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
+	tile_w = (width * (q_data[V4L2_M2M_DST].fmt->depth >> 3))
 		/ MEM2MEM_NUM_TILES;
-	bytes_left = in_buf->vb.bytesperline - tile_w * MEM2MEM_NUM_TILES;
+	bytes_left = bytesperline - tile_w * MEM2MEM_NUM_TILES;
 	w = 0;
 
-	for (y = 0; y < in_buf->vb.height; ++y) {
+	for (y = 0; y < height; ++y) {
 		for (t = 0; t < MEM2MEM_NUM_TILES; ++t) {
 			if (w & 0x1) {
 				for (x = 0; x < tile_w; ++x)
@@ -301,6 +300,21 @@
 	ctx->aborting = 1;
 }
 
+static void m2mtest_lock(void *priv)
+{
+	struct m2mtest_ctx *ctx = priv;
+	struct m2mtest_dev *dev = ctx->dev;
+	mutex_lock(&dev->dev_mutex);
+}
+
+static void m2mtest_unlock(void *priv)
+{
+	struct m2mtest_ctx *ctx = priv;
+	struct m2mtest_dev *dev = ctx->dev;
+	mutex_unlock(&dev->dev_mutex);
+}
+
+
 /* device_run() - prepares and starts the device
  *
  * This simulates all the immediate preparations required before starting
@@ -311,7 +325,7 @@
 {
 	struct m2mtest_ctx *ctx = priv;
 	struct m2mtest_dev *dev = ctx->dev;
-	struct m2mtest_buffer *src_buf, *dst_buf;
+	struct vb2_buffer *src_buf, *dst_buf;
 
 	src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
 	dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
@@ -322,12 +336,11 @@
 	schedule_irq(dev, ctx->transtime);
 }
 
-
 static void device_isr(unsigned long priv)
 {
 	struct m2mtest_dev *m2mtest_dev = (struct m2mtest_dev *)priv;
 	struct m2mtest_ctx *curr_ctx;
-	struct m2mtest_buffer *src_buf, *dst_buf;
+	struct vb2_buffer *src_vb, *dst_vb;
 	unsigned long flags;
 
 	curr_ctx = v4l2_m2m_get_curr_priv(m2mtest_dev->m2m_dev);
@@ -338,31 +351,26 @@
 		return;
 	}
 
-	src_buf = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
-	dst_buf = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+	src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
+	dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+
 	curr_ctx->num_processed++;
 
+	spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
+	v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+	v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+	spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
+
 	if (curr_ctx->num_processed == curr_ctx->translen
 	    || curr_ctx->aborting) {
 		dprintk(curr_ctx->dev, "Finishing transaction\n");
 		curr_ctx->num_processed = 0;
-		spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
-		src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
-		wake_up(&src_buf->vb.done);
-		wake_up(&dst_buf->vb.done);
-		spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
 		v4l2_m2m_job_finish(m2mtest_dev->m2m_dev, curr_ctx->m2m_ctx);
 	} else {
-		spin_lock_irqsave(&m2mtest_dev->irqlock, flags);
-		src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
-		wake_up(&src_buf->vb.done);
-		wake_up(&dst_buf->vb.done);
-		spin_unlock_irqrestore(&m2mtest_dev->irqlock, flags);
 		device_run(curr_ctx);
 	}
 }
 
-
 /*
  * video ioctls
  */
@@ -423,7 +431,7 @@
 
 static int vidioc_g_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
 {
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 	struct m2mtest_q_data *q_data;
 
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
@@ -434,7 +442,7 @@
 
 	f->fmt.pix.width	= q_data->width;
 	f->fmt.pix.height	= q_data->height;
-	f->fmt.pix.field	= vq->field;
+	f->fmt.pix.field	= V4L2_FIELD_NONE;
 	f->fmt.pix.pixelformat	= q_data->fmt->fourcc;
 	f->fmt.pix.bytesperline	= (q_data->width * q_data->fmt->depth) >> 3;
 	f->fmt.pix.sizeimage	= q_data->sizeimage;
@@ -523,7 +531,7 @@
 static int vidioc_s_fmt(struct m2mtest_ctx *ctx, struct v4l2_format *f)
 {
 	struct m2mtest_q_data *q_data;
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 	if (!vq)
@@ -533,7 +541,7 @@
 	if (!q_data)
 		return -EINVAL;
 
-	if (videobuf_queue_is_busy(vq)) {
+	if (vb2_is_busy(vq)) {
 		v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
 		return -EBUSY;
 	}
@@ -543,7 +551,6 @@
 	q_data->height		= f->fmt.pix.height;
 	q_data->sizeimage	= q_data->width * q_data->height
 				* q_data->fmt->depth >> 3;
-	vq->field		= f->fmt.pix.field;
 
 	dprintk(ctx->dev,
 		"Setting format for type %d, wxh: %dx%d, fmt: %d\n",
@@ -733,120 +740,94 @@
  * Queue operations
  */
 
-static void m2mtest_buf_release(struct videobuf_queue *vq,
-				struct videobuf_buffer *vb)
-{
-	struct m2mtest_ctx *ctx = vq->priv_data;
-
-	dprintk(ctx->dev, "type: %d, index: %d, state: %d\n",
-		vq->type, vb->i, vb->state);
-
-	videobuf_vmalloc_free(vb);
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int m2mtest_buf_setup(struct videobuf_queue *vq, unsigned int *count,
-			  unsigned int *size)
+static int m2mtest_queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+				unsigned int *nplanes, unsigned long sizes[],
+				void *alloc_ctxs[])
 {
-	struct m2mtest_ctx *ctx = vq->priv_data;
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vq);
 	struct m2mtest_q_data *q_data;
+	unsigned int size, count = *nbuffers;
 
 	q_data = get_q_data(vq->type);
 
-	*size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
-	dprintk(ctx->dev, "size:%d, w/h %d/%d, depth: %d\n",
-		*size, q_data->width, q_data->height, q_data->fmt->depth);
+	size = q_data->width * q_data->height * q_data->fmt->depth >> 3;
 
-	if (0 == *count)
-		*count = MEM2MEM_DEF_NUM_BUFS;
+	while (size * count > MEM2MEM_VID_MEM_LIMIT)
+		(count)--;
 
-	while (*size * *count > MEM2MEM_VID_MEM_LIMIT)
-		(*count)--;
+	*nplanes = 1;
+	*nbuffers = count;
+	sizes[0] = size;
 
-	v4l2_info(&ctx->dev->v4l2_dev,
-		  "%d buffers of size %d set up.\n", *count, *size);
+	/*
+	 * videobuf2-vmalloc allocator is context-less so no need to set
+	 * alloc_ctxs array.
+	 */
+
+	dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
 
 	return 0;
 }
 
-static int m2mtest_buf_prepare(struct videobuf_queue *vq,
-			       struct videobuf_buffer *vb,
-			       enum v4l2_field field)
+static int m2mtest_buf_prepare(struct vb2_buffer *vb)
 {
-	struct m2mtest_ctx *ctx = vq->priv_data;
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct m2mtest_q_data *q_data;
-	int ret;
 
-	dprintk(ctx->dev, "type: %d, index: %d, state: %d\n",
-		vq->type, vb->i, vb->state);
+	dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
 
-	q_data = get_q_data(vq->type);
+	q_data = get_q_data(vb->vb2_queue->type);
 
-	if (vb->baddr) {
-		/* User-provided buffer */
-		if (vb->bsize < q_data->sizeimage) {
-			/* Buffer too small to fit a frame */
-			v4l2_err(&ctx->dev->v4l2_dev,
-				 "User-provided buffer too small\n");
-			return -EINVAL;
-		}
-	} else if (vb->state != VIDEOBUF_NEEDS_INIT
-			&& vb->bsize < q_data->sizeimage) {
-		/* We provide the buffer, but it's already been initialized
-		 * and is too small */
+	if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+		dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
+				__func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
 		return -EINVAL;
 	}
 
-	vb->width	= q_data->width;
-	vb->height	= q_data->height;
-	vb->bytesperline = (q_data->width * q_data->fmt->depth) >> 3;
-	vb->size	= q_data->sizeimage;
-	vb->field	= field;
-
-	if (VIDEOBUF_NEEDS_INIT == vb->state) {
-		ret = videobuf_iolock(vq, vb, NULL);
-		if (ret) {
-			v4l2_err(&ctx->dev->v4l2_dev,
-				 "Iolock failed\n");
-			goto fail;
-		}
-	}
-
-	vb->state = VIDEOBUF_PREPARED;
+	vb2_set_plane_payload(vb, 0, q_data->sizeimage);
 
 	return 0;
-fail:
-	m2mtest_buf_release(vq, vb);
-	return ret;
 }
 
-static void m2mtest_buf_queue(struct videobuf_queue *vq,
-			   struct videobuf_buffer *vb)
+static void m2mtest_buf_queue(struct vb2_buffer *vb)
 {
-	struct m2mtest_ctx *ctx = vq->priv_data;
-
-	v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
+	struct m2mtest_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
 }
 
-static struct videobuf_queue_ops m2mtest_qops = {
-	.buf_setup	= m2mtest_buf_setup,
-	.buf_prepare	= m2mtest_buf_prepare,
-	.buf_queue	= m2mtest_buf_queue,
-	.buf_release	= m2mtest_buf_release,
+static struct vb2_ops m2mtest_qops = {
+	.queue_setup	 = m2mtest_queue_setup,
+	.buf_prepare	 = m2mtest_buf_prepare,
+	.buf_queue	 = m2mtest_buf_queue,
 };
 
-static void queue_init(void *priv, struct videobuf_queue *vq,
-		       enum v4l2_buf_type type)
+static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq)
 {
 	struct m2mtest_ctx *ctx = priv;
-	struct m2mtest_dev *dev = ctx->dev;
+	int ret;
 
-	videobuf_queue_vmalloc_init(vq, &m2mtest_qops, dev->v4l2_dev.dev,
-				    &dev->irqlock, type, V4L2_FIELD_NONE,
-				    sizeof(struct m2mtest_buffer), priv,
-				    &dev->dev_mutex);
-}
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	src_vq->io_modes = VB2_MMAP;
+	src_vq->drv_priv = ctx;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	src_vq->ops = &m2mtest_qops;
+	src_vq->mem_ops = &vb2_vmalloc_memops;
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	dst_vq->io_modes = VB2_MMAP;
+	dst_vq->drv_priv = ctx;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+	dst_vq->ops = &m2mtest_qops;
+	dst_vq->mem_ops = &vb2_vmalloc_memops;
 
+	return vb2_queue_init(dst_vq);
+}
 
 /*
  * File operations
@@ -866,7 +847,8 @@
 	ctx->transtime = MEM2MEM_DEF_TRANSTIME;
 	ctx->num_processed = 0;
 
-	ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, dev->m2m_dev, queue_init);
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
+
 	if (IS_ERR(ctx->m2m_ctx)) {
 		int ret = PTR_ERR(ctx->m2m_ctx);
 
@@ -932,6 +914,8 @@
 	.device_run	= device_run,
 	.job_ready	= job_ready,
 	.job_abort	= job_abort,
+	.lock		= m2mtest_lock,
+	.unlock		= m2mtest_unlock,
 };
 
 static int m2mtest_probe(struct platform_device *pdev)
@@ -990,6 +974,7 @@
 
 	return 0;
 
+	v4l2_m2m_release(dev->m2m_dev);
 err_m2m:
 	video_unregister_device(dev->vfd);
 rel_vdev:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/meye.c linux-libre-2.6.39-gnu/drivers/media/video/meye.c
--- linux-libre-2.6.38-gnu/drivers/media/video/meye.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/meye.c	2011-05-19 00:06:34.000000000 -0400
@@ -1547,7 +1547,8 @@
 	return 0;
 }
 
-static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+static long vidioc_default(struct file *file, void *fh, bool valid_prio,
+						int cmd, void *arg)
 {
 	switch (cmd) {
 	case MEYEIOC_G_PARAMS:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/msp3400-driver.c linux-libre-2.6.39-gnu/drivers/media/video/msp3400-driver.c
--- linux-libre-2.6.38-gnu/drivers/media/video/msp3400-driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/msp3400-driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,7 +69,7 @@
 /* module parameters */
 static int opmode   = OPMODE_AUTO;
 int msp_debug;		 /* msp_debug output */
-int msp_once;		 /* no continous stereo monitoring */
+int msp_once;		 /* no continuous stereo monitoring */
 int msp_amsound;	 /* hard-wire AM sound at 6.5 Hz (france),
 			    the autoscan seems work well only with FM... */
 int msp_standard = 1;    /* Override auto detect of audio msp_standard,
@@ -551,7 +551,7 @@
 	switch (state->mode) {
 		case MSP_MODE_AM_DETECT: p = "AM (for carrier detect)"; break;
 		case MSP_MODE_FM_RADIO: p = "FM Radio"; break;
-		case MSP_MODE_FM_TERRA: p = "Terrestial FM-mono/stereo"; break;
+		case MSP_MODE_FM_TERRA: p = "Terrestrial FM-mono/stereo"; break;
 		case MSP_MODE_FM_SAT: p = "Satellite FM-mono"; break;
 		case MSP_MODE_FM_NICAM1: p = "NICAM/FM (B/G, D/K)"; break;
 		case MSP_MODE_FM_NICAM2: p = "NICAM/FM (I)"; break;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/msp3400-kthreads.c linux-libre-2.6.39-gnu/drivers/media/video/msp3400-kthreads.c
--- linux-libre-2.6.38-gnu/drivers/media/video/msp3400-kthreads.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/msp3400-kthreads.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,7 +87,7 @@
 		{-8, -8, 4, 6, 78, 107},
 		MSP_CARRIER(10.7), MSP_CARRIER(10.7),
 		0x00d0, 0x0480, 0x0020, 0x3000
-	}, {	/* Terrestial FM-mono + FM-stereo */
+	}, {	/* Terrestrial FM-mono + FM-stereo */
 		{3, 18, 27, 48, 66, 72},
 		{3, 18, 27, 48, 66, 72},
 		MSP_CARRIER(5.5), MSP_CARRIER(5.5),
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/mt9m001.c linux-libre-2.6.39-gnu/drivers/media/video/mt9m001.c
--- linux-libre-2.6.38-gnu/drivers/media/video/mt9m001.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/mt9m001.c	2011-05-19 00:06:34.000000000 -0400
@@ -79,7 +79,7 @@
 static const struct mt9m001_datafmt mt9m001_monochrome_fmts[] = {
 	/* Order important - see above */
 	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
-	{V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
 struct mt9m001 {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/mt9v022.c linux-libre-2.6.39-gnu/drivers/media/video/mt9v022.c
--- linux-libre-2.6.38-gnu/drivers/media/video/mt9v022.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/mt9v022.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
 	/* Order important - see above */
 	{V4L2_MBUS_FMT_Y10_1X10, V4L2_COLORSPACE_JPEG},
-	{V4L2_MBUS_FMT_GREY8_1X8, V4L2_COLORSPACE_JPEG},
+	{V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
 struct mt9v022 {
@@ -392,7 +392,7 @@
 	 * icd->try_fmt(), datawidth is from our supported format list
 	 */
 	switch (mf->code) {
-	case V4L2_MBUS_FMT_GREY8_1X8:
+	case V4L2_MBUS_FMT_Y8_1X8:
 	case V4L2_MBUS_FMT_Y10_1X10:
 		if (mt9v022->model != V4L2_IDENT_MT9V022IX7ATM)
 			return -EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/mx3_camera.c linux-libre-2.6.39-gnu/drivers/media/video/mx3_camera.c
--- linux-libre-2.6.38-gnu/drivers/media/video/mx3_camera.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/mx3_camera.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-dev.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
 #include <media/soc_camera.h>
 #include <media/soc_mediabus.h>
 
@@ -62,10 +62,16 @@
 
 #define MAX_VIDEO_MEM 16
 
+enum csi_buffer_state {
+	CSI_BUF_NEEDS_INIT,
+	CSI_BUF_PREPARED,
+};
+
 struct mx3_camera_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer			vb;
-	enum v4l2_mbus_pixelcode		code;
+	struct vb2_buffer			vb;
+	enum csi_buffer_state			state;
+	struct list_head			queue;
 
 	/* One descriptot per scatterlist (per frame) */
 	struct dma_async_tx_descriptor		*txd;
@@ -108,6 +114,9 @@
 	struct list_head	capture;
 	spinlock_t		lock;		/* Protects video buffer lists */
 	struct mx3_camera_buffer *active;
+	struct vb2_alloc_ctx	*alloc_ctx;
+	enum v4l2_field		field;
+	int			sequence;
 
 	/* IDMAC / dmaengine interface */
 	struct idmac_channel	*idmac_channel[1];	/* We need one channel */
@@ -130,6 +139,11 @@
 	__raw_writel(value, mx3->base + reg);
 }
 
+static struct mx3_camera_buffer *to_mx3_vb(struct vb2_buffer *vb)
+{
+	return container_of(vb, struct mx3_camera_buffer, vb);
+}
+
 /* Called from the IPU IDMAC ISR */
 static void mx3_cam_dma_done(void *arg)
 {
@@ -137,20 +151,20 @@
 	struct dma_chan *chan = desc->txd.chan;
 	struct idmac_channel *ichannel = to_idmac_chan(chan);
 	struct mx3_camera_dev *mx3_cam = ichannel->client;
-	struct videobuf_buffer *vb;
 
 	dev_dbg(chan->device->dev, "callback cookie %d, active DMA 0x%08x\n",
 		desc->txd.cookie, mx3_cam->active ? sg_dma_address(&mx3_cam->active->sg) : 0);
 
 	spin_lock(&mx3_cam->lock);
 	if (mx3_cam->active) {
-		vb = &mx3_cam->active->vb;
+		struct vb2_buffer *vb = &mx3_cam->active->vb;
+		struct mx3_camera_buffer *buf = to_mx3_vb(vb);
 
-		list_del_init(&vb->queue);
-		vb->state = VIDEOBUF_DONE;
-		do_gettimeofday(&vb->ts);
-		vb->field_count++;
-		wake_up(&vb->done);
+		list_del_init(&buf->queue);
+		do_gettimeofday(&vb->v4l2_buf.timestamp);
+		vb->v4l2_buf.field = mx3_cam->field;
+		vb->v4l2_buf.sequence = mx3_cam->sequence++;
+		vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
 	}
 
 	if (list_empty(&mx3_cam->capture)) {
@@ -165,50 +179,22 @@
 	}
 
 	mx3_cam->active = list_entry(mx3_cam->capture.next,
-				     struct mx3_camera_buffer, vb.queue);
-	mx3_cam->active->vb.state = VIDEOBUF_ACTIVE;
+				     struct mx3_camera_buffer, queue);
 	spin_unlock(&mx3_cam->lock);
 }
 
-static void free_buffer(struct videobuf_queue *vq, struct mx3_camera_buffer *buf)
-{
-	struct soc_camera_device *icd = vq->priv_data;
-	struct videobuf_buffer *vb = &buf->vb;
-	struct dma_async_tx_descriptor *txd = buf->txd;
-	struct idmac_channel *ichan;
-
-	BUG_ON(in_interrupt());
-
-	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
-		vb, vb->baddr, vb->bsize);
-
-	/*
-	 * This waits until this buffer is out of danger, i.e., until it is no
-	 * longer in STATE_QUEUED or STATE_ACTIVE
-	 */
-	videobuf_waiton(vq, vb, 0, 0);
-	if (txd) {
-		ichan = to_idmac_chan(txd->chan);
-		async_tx_ack(txd);
-	}
-	videobuf_dma_contig_free(vq, vb);
-	buf->txd = NULL;
-
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
 /*
  * Videobuf operations
  */
 
 /*
  * Calculate the __buffer__ (not data) size and number of buffers.
- * Called with .vb_lock held
  */
-static int mx3_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
-			      unsigned int *size)
+static int mx3_videobuf_setup(struct vb2_queue *vq,
+			unsigned int *count, unsigned int *num_planes,
+			unsigned long sizes[], void *alloc_ctxs[])
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = soc_camera_from_vb2q(vq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
 	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
@@ -220,162 +206,133 @@
 	if (!mx3_cam->idmac_channel[0])
 		return -EINVAL;
 
-	*size = bytes_per_line * icd->user_height;
+	*num_planes = 1;
+
+	mx3_cam->sequence = 0;
+	sizes[0] = bytes_per_line * icd->user_height;
+	alloc_ctxs[0] = mx3_cam->alloc_ctx;
 
 	if (!*count)
 		*count = 32;
 
-	if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
-		*count = MAX_VIDEO_MEM * 1024 * 1024 / *size;
+	if (sizes[0] * *count > MAX_VIDEO_MEM * 1024 * 1024)
+		*count = MAX_VIDEO_MEM * 1024 * 1024 / sizes[0];
 
 	return 0;
 }
 
-/* Called with .vb_lock held */
-static int mx3_videobuf_prepare(struct videobuf_queue *vq,
-		struct videobuf_buffer *vb, enum v4l2_field field)
+static int mx3_videobuf_prepare(struct vb2_buffer *vb)
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	struct mx3_camera_buffer *buf =
-		container_of(vb, struct mx3_camera_buffer, vb);
+	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
+	struct scatterlist *sg;
+	struct mx3_camera_buffer *buf;
 	size_t new_size;
-	int ret;
 	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
 						icd->current_fmt->host_fmt);
 
 	if (bytes_per_line < 0)
 		return bytes_per_line;
 
-	new_size = bytes_per_line * icd->user_height;
-
-	/*
-	 * I think, in buf_prepare you only have to protect global data,
-	 * the actual buffer is yours
-	 */
+	buf = to_mx3_vb(vb);
+	sg = &buf->sg;
 
-	if (buf->code	!= icd->current_fmt->code ||
-	    vb->width	!= icd->user_width ||
-	    vb->height	!= icd->user_height ||
-	    vb->field	!= field) {
-		buf->code	= icd->current_fmt->code;
-		vb->width	= icd->user_width;
-		vb->height	= icd->user_height;
-		vb->field	= field;
-		if (vb->state != VIDEOBUF_NEEDS_INIT)
-			free_buffer(vq, buf);
-	}
+	new_size = bytes_per_line * icd->user_height;
 
-	if (vb->baddr && vb->bsize < new_size) {
-		/* User provided buffer, but it is too small */
-		ret = -ENOMEM;
-		goto out;
+	if (vb2_plane_size(vb, 0) < new_size) {
+		dev_err(icd->dev.parent, "Buffer too small (%lu < %zu)\n",
+			vb2_plane_size(vb, 0), new_size);
+		return -ENOBUFS;
 	}
 
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-		struct scatterlist *sg = &buf->sg;
-
-		/*
-		 * The total size of video-buffers that will be allocated / mapped.
-		 * *size that we calculated in videobuf_setup gets assigned to
-		 * vb->bsize, and now we use the same calculation to get vb->size.
-		 */
-		vb->size = new_size;
-
-		/* This actually (allocates and) maps buffers */
-		ret = videobuf_iolock(vq, vb, NULL);
-		if (ret)
-			goto fail;
-
-		/*
-		 * We will have to configure the IDMAC channel. It has two slots
-		 * for DMA buffers, we shall enter the first two buffers there,
-		 * and then submit new buffers in DMA-ready interrupts
-		 */
-		sg_init_table(sg, 1);
-		sg_dma_address(sg)	= videobuf_to_dma_contig(vb);
-		sg_dma_len(sg)		= vb->size;
+	if (buf->state == CSI_BUF_NEEDS_INIT) {
+		sg_dma_address(sg)	= vb2_dma_contig_plane_paddr(vb, 0);
+		sg_dma_len(sg)		= new_size;
 
 		buf->txd = ichan->dma_chan.device->device_prep_slave_sg(
 			&ichan->dma_chan, sg, 1, DMA_FROM_DEVICE,
 			DMA_PREP_INTERRUPT);
-		if (!buf->txd) {
-			ret = -EIO;
-			goto fail;
-		}
+		if (!buf->txd)
+			return -EIO;
 
 		buf->txd->callback_param	= buf->txd;
 		buf->txd->callback		= mx3_cam_dma_done;
 
-		vb->state = VIDEOBUF_PREPARED;
+		buf->state = CSI_BUF_PREPARED;
 	}
 
-	return 0;
+	vb2_set_plane_payload(vb, 0, new_size);
 
-fail:
-	free_buffer(vq, buf);
-out:
-	return ret;
+	return 0;
 }
 
 static enum pixel_fmt fourcc_to_ipu_pix(__u32 fourcc)
 {
 	/* Add more formats as need arises and test possibilities appear... */
 	switch (fourcc) {
-	case V4L2_PIX_FMT_RGB565:
-		return IPU_PIX_FMT_RGB565;
 	case V4L2_PIX_FMT_RGB24:
 		return IPU_PIX_FMT_RGB24;
-	case V4L2_PIX_FMT_RGB332:
-		return IPU_PIX_FMT_RGB332;
-	case V4L2_PIX_FMT_YUV422P:
-		return IPU_PIX_FMT_YVU422P;
+	case V4L2_PIX_FMT_UYVY:
+	case V4L2_PIX_FMT_RGB565:
 	default:
 		return IPU_PIX_FMT_GENERIC;
 	}
 }
 
-/*
- * 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)
+static void mx3_videobuf_queue(struct vb2_buffer *vb)
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	struct mx3_camera_buffer *buf =
-		container_of(vb, struct mx3_camera_buffer, vb);
+	struct mx3_camera_buffer *buf = to_mx3_vb(vb);
 	struct dma_async_tx_descriptor *txd = buf->txd;
 	struct idmac_channel *ichan = to_idmac_chan(txd->chan);
 	struct idmac_video_param *video = &ichan->params.video;
 	dma_cookie_t cookie;
 	u32 fourcc = icd->current_fmt->host_fmt->fourcc;
-
-	BUG_ON(!irqs_disabled());
+	unsigned long flags;
 
 	/* This is the configuration of one sg-element */
 	video->out_pixel_fmt	= fourcc_to_ipu_pix(fourcc);
-	video->out_width	= icd->user_width;
-	video->out_height	= icd->user_height;
-	video->out_stride	= icd->user_width;
+
+	if (video->out_pixel_fmt == IPU_PIX_FMT_GENERIC) {
+		/*
+		 * If the IPU DMA channel is configured to transport
+		 * generic 8-bit data, we have to set up correctly the
+		 * geometry parameters upon the current pixel format.
+		 * So, since the DMA horizontal parameters are expressed
+		 * in bytes not pixels, convert these in the right unit.
+		 */
+		int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
+						icd->current_fmt->host_fmt);
+		BUG_ON(bytes_per_line <= 0);
+
+		video->out_width	= bytes_per_line;
+		video->out_height	= icd->user_height;
+		video->out_stride	= bytes_per_line;
+	} else {
+		/*
+		 * For IPU known formats the pixel unit will be managed
+		 * successfully by the IPU code
+		 */
+		video->out_width	= icd->user_width;
+		video->out_height	= icd->user_height;
+		video->out_stride	= icd->user_width;
+	}
 
 #ifdef DEBUG
 	/* helps to see what DMA actually has written */
-	memset((void *)vb->baddr, 0xaa, vb->bsize);
+	if (vb2_plane_vaddr(vb, 0))
+		memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
-	list_add_tail(&vb->queue, &mx3_cam->capture);
+	spin_lock_irqsave(&mx3_cam->lock, flags);
+	list_add_tail(&buf->queue, &mx3_cam->capture);
 
-	if (!mx3_cam->active) {
+	if (!mx3_cam->active)
 		mx3_cam->active = buf;
-		vb->state = VIDEOBUF_ACTIVE;
-	} else {
-		vb->state = VIDEOBUF_QUEUED;
-	}
 
 	spin_unlock_irq(&mx3_cam->lock);
 
@@ -383,67 +340,87 @@
 	dev_dbg(icd->dev.parent, "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_irq(&mx3_cam->lock);
 
-	list_del_init(&vb->queue);
+	/* Submit error */
+	list_del_init(&buf->queue);
 
 	if (mx3_cam->active == buf)
 		mx3_cam->active = NULL;
+
+	spin_unlock_irqrestore(&mx3_cam->lock, flags);
+	vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
 }
 
-/* Called with .vb_lock held */
-static void mx3_videobuf_release(struct videobuf_queue *vq,
-				 struct videobuf_buffer *vb)
+static void mx3_videobuf_release(struct vb2_buffer *vb)
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = soc_camera_from_vb2q(vb->vb2_queue);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct mx3_camera_dev *mx3_cam = ici->priv;
-	struct mx3_camera_buffer *buf =
-		container_of(vb, struct mx3_camera_buffer, vb);
+	struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+	struct dma_async_tx_descriptor *txd = buf->txd;
 	unsigned long flags;
 
 	dev_dbg(icd->dev.parent,
-		"Release%s DMA 0x%08x (state %d), queue %sempty\n",
+		"Release%s DMA 0x%08x, queue %sempty\n",
 		mx3_cam->active == buf ? " active" : "", sg_dma_address(&buf->sg),
-		vb->state, list_empty(&vb->queue) ? "" : "not ");
+		list_empty(&buf->queue) ? "" : "not ");
+
 	spin_lock_irqsave(&mx3_cam->lock, flags);
-	if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
-	    !list_empty(&vb->queue)) {
-		vb->state = VIDEOBUF_ERROR;
 
-		list_del_init(&vb->queue);
-		if (mx3_cam->active == buf)
-			mx3_cam->active = NULL;
+	if (mx3_cam->active == buf)
+		mx3_cam->active = NULL;
+
+	/* Doesn't hurt also if the list is empty */
+	list_del_init(&buf->queue);
+	buf->state = CSI_BUF_NEEDS_INIT;
+
+	if (txd) {
+		buf->txd = NULL;
+		if (mx3_cam->idmac_channel[0])
+			async_tx_ack(txd);
 	}
+
 	spin_unlock_irqrestore(&mx3_cam->lock, flags);
-	free_buffer(vq, buf);
 }
 
-static struct videobuf_queue_ops mx3_videobuf_ops = {
-	.buf_setup      = mx3_videobuf_setup,
-	.buf_prepare    = mx3_videobuf_prepare,
-	.buf_queue      = mx3_videobuf_queue,
-	.buf_release    = mx3_videobuf_release,
+static int mx3_videobuf_init(struct vb2_buffer *vb)
+{
+	struct mx3_camera_buffer *buf = to_mx3_vb(vb);
+	/* This is for locking debugging only */
+	INIT_LIST_HEAD(&buf->queue);
+	sg_init_table(&buf->sg, 1);
+
+	buf->state = CSI_BUF_NEEDS_INIT;
+	buf->txd = NULL;
+
+	return 0;
+}
+
+static struct vb2_ops mx3_videobuf_ops = {
+	.queue_setup	= mx3_videobuf_setup,
+	.buf_prepare	= mx3_videobuf_prepare,
+	.buf_queue	= mx3_videobuf_queue,
+	.buf_cleanup	= mx3_videobuf_release,
+	.buf_init	= mx3_videobuf_init,
+	.wait_prepare	= soc_camera_unlock,
+	.wait_finish	= soc_camera_lock,
 };
 
-static void mx3_camera_init_videobuf(struct videobuf_queue *q,
+static int mx3_camera_init_videobuf(struct vb2_queue *q,
 				     struct soc_camera_device *icd)
 {
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	struct mx3_camera_dev *mx3_cam = ici->priv;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = icd;
+	q->ops = &mx3_videobuf_ops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct mx3_camera_buffer);
 
-	videobuf_queue_dma_contig_init(q, &mx3_videobuf_ops, icd->dev.parent,
-				       &mx3_cam->lock,
-				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				       V4L2_FIELD_NONE,
-				       sizeof(struct mx3_camera_buffer), icd,
-				       &icd->video_lock);
+	return vb2_queue_init(q);
 }
 
 /* First part of ipu_csi_init_interface() */
@@ -538,18 +515,6 @@
 		 icd->devnum);
 }
 
-static bool channel_change_requested(struct soc_camera_device *icd,
-				     struct v4l2_rect *rect)
-{
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	struct mx3_camera_dev *mx3_cam = ici->priv;
-	struct idmac_channel *ichan = mx3_cam->idmac_channel[0];
-
-	/* Do buffers have to be re-allocated or channel re-configured? */
-	return ichan && rect->width * rect->height >
-		icd->user_width * icd->user_height;
-}
-
 static int test_platform_param(struct mx3_camera_dev *mx3_cam,
 			       unsigned char buswidth, unsigned long *flags)
 {
@@ -734,18 +699,36 @@
 	if (xlate) {
 		xlate->host_fmt	= fmt;
 		xlate->code	= code;
+		dev_dbg(dev, "Providing format %c%c%c%c in pass-through mode\n",
+			(fmt->fourcc >> (0*8)) & 0xFF,
+			(fmt->fourcc >> (1*8)) & 0xFF,
+			(fmt->fourcc >> (2*8)) & 0xFF,
+			(fmt->fourcc >> (3*8)) & 0xFF);
 		xlate++;
-		dev_dbg(dev, "Providing format %x in pass-through mode\n",
-			xlate->host_fmt->fourcc);
 	}
 
 	return formats;
 }
 
 static void configure_geometry(struct mx3_camera_dev *mx3_cam,
-			       unsigned int width, unsigned int height)
+			       unsigned int width, unsigned int height,
+			       enum v4l2_mbus_pixelcode code)
 {
 	u32 ctrl, width_field, height_field;
+	const struct soc_mbus_pixelfmt *fmt;
+
+	fmt = soc_mbus_get_fmtdesc(code);
+	BUG_ON(!fmt);
+
+	if (fourcc_to_ipu_pix(fmt->fourcc) == IPU_PIX_FMT_GENERIC) {
+		/*
+		 * As the CSI will be configured to output BAYER, here
+		 * the width parameter count the number of samples to
+		 * capture to complete the whole image width.
+		 */
+		width *= soc_mbus_samples_per_pixel(fmt);
+		BUG_ON(width < 0);
+	}
 
 	/* Setup frame size - this cannot be changed on-the-fly... */
 	width_field = width - 1;
@@ -772,18 +755,6 @@
 	struct dma_chan_request rq = {.mx3_cam = mx3_cam,
 				      .id = IDMAC_IC_7};
 
-	if (*ichan) {
-		struct videobuf_buffer *vb, *_vb;
-		dma_release_channel(&(*ichan)->dma_chan);
-		*ichan = NULL;
-		mx3_cam->active = NULL;
-		list_for_each_entry_safe(vb, _vb, &mx3_cam->capture, queue) {
-			list_del_init(&vb->queue);
-			vb->state = VIDEOBUF_ERROR;
-			wake_up(&vb->done);
-		}
-	}
-
 	dma_cap_zero(mask);
 	dma_cap_set(DMA_SLAVE, mask);
 	dma_cap_set(DMA_PRIVATE, mask);
@@ -843,19 +814,8 @@
 			return ret;
 	}
 
-	if (mf.width != icd->user_width || mf.height != icd->user_height) {
-		/*
-		 * We now know pixel formats and can decide upon DMA-channel(s)
-		 * So far only direct camera-to-memory is supported
-		 */
-		if (channel_change_requested(icd, rect)) {
-			ret = acquire_dma_channel(mx3_cam);
-			if (ret < 0)
-				return ret;
-		}
-
-		configure_geometry(mx3_cam, mf.width, mf.height);
-	}
+	if (mf.width != icd->user_width || mf.height != icd->user_height)
+		configure_geometry(mx3_cam, mf.width, mf.height, mf.code);
 
 	dev_dbg(icd->dev.parent, "Sensor cropped %dx%d\n",
 		mf.width, mf.height);
@@ -887,17 +847,13 @@
 	stride_align(&pix->width);
 	dev_dbg(icd->dev.parent, "Set format %dx%d\n", pix->width, pix->height);
 
-	ret = acquire_dma_channel(mx3_cam);
-	if (ret < 0)
-		return ret;
-
 	/*
 	 * Might have to perform a complete interface initialisation like in
 	 * ipu_csi_init_interface() in mxc_v4l2_s_param(). Also consider
 	 * mxc_v4l2_s_fmt()
 	 */
 
-	configure_geometry(mx3_cam, pix->width, pix->height);
+	configure_geometry(mx3_cam, pix->width, pix->height, xlate->code);
 
 	mf.width	= pix->width;
 	mf.height	= pix->height;
@@ -912,12 +868,25 @@
 	if (mf.code != xlate->code)
 		return -EINVAL;
 
+	if (!mx3_cam->idmac_channel[0]) {
+		ret = acquire_dma_channel(mx3_cam);
+		if (ret < 0)
+			return ret;
+	}
+
 	pix->width		= mf.width;
 	pix->height		= mf.height;
 	pix->field		= mf.field;
+	mx3_cam->field		= mf.field;
 	pix->colorspace		= mf.colorspace;
 	icd->current_fmt	= xlate;
 
+	pix->bytesperline = soc_mbus_bytes_per_line(pix->width,
+						    xlate->host_fmt);
+	if (pix->bytesperline < 0)
+		return pix->bytesperline;
+	pix->sizeimage = pix->height * pix->bytesperline;
+
 	dev_dbg(icd->dev.parent, "Sensor set %dx%d\n", pix->width, pix->height);
 
 	return ret;
@@ -991,7 +960,7 @@
 {
 	struct soc_camera_device *icd = file->private_data;
 
-	return videobuf_poll_stream(file, &icd->vb_vidq, pt);
+	return vb2_poll(&icd->vb2_vidq, file, pt);
 }
 
 static int mx3_camera_querycap(struct soc_camera_host *ici,
@@ -1165,7 +1134,7 @@
 	.set_fmt	= mx3_camera_set_fmt,
 	.try_fmt	= mx3_camera_try_fmt,
 	.get_formats	= mx3_camera_get_formats,
-	.init_videobuf	= mx3_camera_init_videobuf,
+	.init_videobuf2	= mx3_camera_init_videobuf,
 	.reqbufs	= mx3_camera_reqbufs,
 	.poll		= mx3_camera_poll,
 	.querycap	= mx3_camera_querycap,
@@ -1241,6 +1210,12 @@
 	soc_host->v4l2_dev.dev	= &pdev->dev;
 	soc_host->nr		= pdev->id;
 
+	mx3_cam->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR(mx3_cam->alloc_ctx)) {
+		err = PTR_ERR(mx3_cam->alloc_ctx);
+		goto eallocctx;
+	}
+
 	err = soc_camera_host_register(soc_host);
 	if (err)
 		goto ecamhostreg;
@@ -1251,6 +1226,8 @@
 	return 0;
 
 ecamhostreg:
+	vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
+eallocctx:
 	iounmap(base);
 eioremap:
 	clk_put(mx3_cam->clk);
@@ -1280,6 +1257,8 @@
 	if (WARN_ON(mx3_cam->idmac_channel[0]))
 		dma_release_channel(&mx3_cam->idmac_channel[0]->dma_chan);
 
+	vb2_dma_contig_cleanup_ctx(mx3_cam->alloc_ctx);
+
 	vfree(mx3_cam);
 
 	dmaengine_put();
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/mxb.c linux-libre-2.6.39-gnu/drivers/media/video/mxb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/mxb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/mxb.c	2011-05-19 00:06:34.000000000 -0400
@@ -643,7 +643,8 @@
 }
 #endif
 
-static long vidioc_default(struct file *file, void *fh, int cmd, void *arg)
+static long vidioc_default(struct file *file, void *fh, bool valid_prio,
+							int cmd, void *arg)
 {
 	struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
 	struct mxb *mxb = (struct mxb *)dev->ext_priv;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/noon010pc30.c linux-libre-2.6.39-gnu/drivers/media/video/noon010pc30.c
--- linux-libre-2.6.38-gnu/drivers/media/video/noon010pc30.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/noon010pc30.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,792 @@
+/*
+ * Driver for SiliconFile NOON010PC30 CIF (1/11") Image Sensor with ISP
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ * Contact: Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ *
+ * Initial register configuration based on a driver authored by
+ * HeungJun Kim <riverful.kim@samsung.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 vergsion.
+ */
+
+#include <linux/delay.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <media/noon010pc30.h>
+#include <media/v4l2-chip-ident.h>
+#include <linux/videodev2.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable module debug trace. Set to 1 to enable.");
+
+#define MODULE_NAME		"NOON010PC30"
+
+/*
+ * Register offsets within a page
+ * b15..b8 - page id, b7..b0 - register address
+ */
+#define POWER_CTRL_REG		0x0001
+#define PAGEMODE_REG		0x03
+#define DEVICE_ID_REG		0x0004
+#define NOON010PC30_ID		0x86
+#define VDO_CTL_REG(n)		(0x0010 + (n))
+#define SYNC_CTL_REG		0x0012
+/* Window size and position */
+#define WIN_ROWH_REG		0x0013
+#define WIN_ROWL_REG		0x0014
+#define WIN_COLH_REG		0x0015
+#define WIN_COLL_REG		0x0016
+#define WIN_HEIGHTH_REG		0x0017
+#define WIN_HEIGHTL_REG		0x0018
+#define WIN_WIDTHH_REG		0x0019
+#define WIN_WIDTHL_REG		0x001A
+#define HBLANKH_REG		0x001B
+#define HBLANKL_REG		0x001C
+#define VSYNCH_REG		0x001D
+#define VSYNCL_REG		0x001E
+/* VSYNC control */
+#define VS_CTL_REG(n)		(0x00A1 + (n))
+/* page 1 */
+#define ISP_CTL_REG(n)		(0x0110 + (n))
+#define YOFS_REG		0x0119
+#define DARK_YOFS_REG		0x011A
+#define SAT_CTL_REG		0x0120
+#define BSAT_REG		0x0121
+#define RSAT_REG		0x0122
+/* Color correction */
+#define CMC_CTL_REG		0x0130
+#define CMC_OFSGH_REG		0x0133
+#define CMC_OFSGL_REG		0x0135
+#define CMC_SIGN_REG		0x0136
+#define CMC_GOFS_REG		0x0137
+#define CMC_COEF_REG(n)		(0x0138 + (n))
+#define CMC_OFS_REG(n)		(0x0141 + (n))
+/* Gamma correction */
+#define GMA_CTL_REG		0x0160
+#define GMA_COEF_REG(n)		(0x0161 + (n))
+/* Lens Shading */
+#define LENS_CTRL_REG		0x01D0
+#define LENS_XCEN_REG		0x01D1
+#define LENS_YCEN_REG		0x01D2
+#define LENS_RC_REG		0x01D3
+#define LENS_GC_REG		0x01D4
+#define LENS_BC_REG		0x01D5
+#define L_AGON_REG		0x01D6
+#define L_AGOFF_REG		0x01D7
+/* Page 3 - Auto Exposure */
+#define AE_CTL_REG(n)		(0x0310 + (n))
+#define AE_CTL9_REG		0x032C
+#define AE_CTL10_REG		0x032D
+#define AE_YLVL_REG		0x031C
+#define AE_YTH_REG(n)		(0x031D + (n))
+#define AE_WGT_REG		0x0326
+#define EXP_TIMEH_REG		0x0333
+#define EXP_TIMEM_REG		0x0334
+#define EXP_TIMEL_REG		0x0335
+#define EXP_MMINH_REG		0x0336
+#define EXP_MMINL_REG		0x0337
+#define EXP_MMAXH_REG		0x0338
+#define EXP_MMAXM_REG		0x0339
+#define EXP_MMAXL_REG		0x033A
+/* Page 4 - Auto White Balance */
+#define AWB_CTL_REG(n)		(0x0410 + (n))
+#define AWB_ENABE		0x80
+#define AWB_WGHT_REG		0x0419
+#define BGAIN_PAR_REG(n)	(0x044F + (n))
+/* Manual white balance, when AWB_CTL2[0]=1 */
+#define MWB_RGAIN_REG		0x0466
+#define MWB_BGAIN_REG		0x0467
+
+/* The token to mark an array end */
+#define REG_TERM		0xFFFF
+
+struct noon010_format {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_colorspace colorspace;
+	u16 ispctl1_reg;
+};
+
+struct noon010_frmsize {
+	u16 width;
+	u16 height;
+	int vid_ctl1;
+};
+
+static const char * const noon010_supply_name[] = {
+	"vdd_core", "vddio", "vdda"
+};
+
+#define NOON010_NUM_SUPPLIES ARRAY_SIZE(noon010_supply_name)
+
+struct noon010_info {
+	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
+	const struct noon010pc30_platform_data *pdata;
+	const struct noon010_format *curr_fmt;
+	const struct noon010_frmsize *curr_win;
+	unsigned int hflip:1;
+	unsigned int vflip:1;
+	unsigned int power:1;
+	u8 i2c_reg_page;
+	struct regulator_bulk_data supply[NOON010_NUM_SUPPLIES];
+	u32 gpio_nreset;
+	u32 gpio_nstby;
+};
+
+struct i2c_regval {
+	u16 addr;
+	u16 val;
+};
+
+/* Supported resolutions. */
+static const struct noon010_frmsize noon010_sizes[] = {
+	{
+		.width		= 352,
+		.height		= 288,
+		.vid_ctl1	= 0,
+	}, {
+		.width		= 176,
+		.height		= 144,
+		.vid_ctl1	= 0x10,
+	}, {
+		.width		= 88,
+		.height		= 72,
+		.vid_ctl1	= 0x20,
+	},
+};
+
+/* Supported pixel formats. */
+static const struct noon010_format noon010_formats[] = {
+	{
+		.code		= V4L2_MBUS_FMT_YUYV8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x03,
+	}, {
+		.code		= V4L2_MBUS_FMT_YVYU8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x02,
+	}, {
+		.code		= V4L2_MBUS_FMT_VYUY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0,
+	}, {
+		.code		= V4L2_MBUS_FMT_UYVY8_2X8,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x01,
+	}, {
+		.code		= V4L2_MBUS_FMT_RGB565_2X8_BE,
+		.colorspace	= V4L2_COLORSPACE_JPEG,
+		.ispctl1_reg	= 0x40,
+	},
+};
+
+static const struct i2c_regval noon010_base_regs[] = {
+	{ WIN_COLL_REG,		0x06 },	{ HBLANKL_REG,		0x7C },
+	/* Color corection and saturation */
+	{ ISP_CTL_REG(0),	0x30 }, { ISP_CTL_REG(2),	0x30 },
+	{ YOFS_REG,		0x80 }, { DARK_YOFS_REG,	0x04 },
+	{ SAT_CTL_REG,		0x1F }, { BSAT_REG,		0x90 },
+	{ CMC_CTL_REG,		0x0F }, { CMC_OFSGH_REG,	0x3C },
+	{ CMC_OFSGL_REG,	0x2C }, { CMC_SIGN_REG,		0x3F },
+	{ CMC_COEF_REG(0),	0x79 }, { CMC_OFS_REG(0),	0x00 },
+	{ CMC_COEF_REG(1),	0x39 }, { CMC_OFS_REG(1),	0x00 },
+	{ CMC_COEF_REG(2),	0x00 }, { CMC_OFS_REG(2),	0x00 },
+	{ CMC_COEF_REG(3),	0x11 }, { CMC_OFS_REG(3),	0x8B },
+	{ CMC_COEF_REG(4),	0x65 }, { CMC_OFS_REG(4),	0x07 },
+	{ CMC_COEF_REG(5),	0x14 }, { CMC_OFS_REG(5),	0x04 },
+	{ CMC_COEF_REG(6),	0x01 }, { CMC_OFS_REG(6),	0x9C },
+	{ CMC_COEF_REG(7),	0x33 }, { CMC_OFS_REG(7),	0x89 },
+	{ CMC_COEF_REG(8),	0x74 }, { CMC_OFS_REG(8),	0x25 },
+	/* Automatic white balance */
+	{ AWB_CTL_REG(0),	0x78 }, { AWB_CTL_REG(1),	0x2E },
+	{ AWB_CTL_REG(2),	0x20 }, { AWB_CTL_REG(3),	0x85 },
+	/* Auto exposure */
+	{ AE_CTL_REG(0),	0xDC }, { AE_CTL_REG(1),	0x81 },
+	{ AE_CTL_REG(2),	0x30 }, { AE_CTL_REG(3),	0xA5 },
+	{ AE_CTL_REG(4),	0x40 }, { AE_CTL_REG(5),	0x51 },
+	{ AE_CTL_REG(6),	0x33 }, { AE_CTL_REG(7),	0x7E },
+	{ AE_CTL9_REG,		0x00 }, { AE_CTL10_REG,		0x02 },
+	{ AE_YLVL_REG,		0x44 },	{ AE_YTH_REG(0),	0x34 },
+	{ AE_YTH_REG(1),	0x30 },	{ AE_WGT_REG,		0xD5 },
+	/* Lens shading compensation */
+	{ LENS_CTRL_REG,	0x01 }, { LENS_XCEN_REG,	0x80 },
+	{ LENS_YCEN_REG,	0x70 }, { LENS_RC_REG,		0x53 },
+	{ LENS_GC_REG,		0x40 }, { LENS_BC_REG,		0x3E },
+	{ REG_TERM,		0 },
+};
+
+static inline struct noon010_info *to_noon010(struct v4l2_subdev *sd)
+{
+	return container_of(sd, struct noon010_info, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct noon010_info, hdl)->sd;
+}
+
+static inline int set_i2c_page(struct noon010_info *info,
+			       struct i2c_client *client, unsigned int reg)
+{
+	u32 page = reg >> 8 & 0xFF;
+	int ret = 0;
+
+	if (info->i2c_reg_page != page && (reg & 0xFF) != 0x03) {
+		ret = i2c_smbus_write_byte_data(client, PAGEMODE_REG, page);
+		if (!ret)
+			info->i2c_reg_page = page;
+	}
+	return ret;
+}
+
+static int cam_i2c_read(struct v4l2_subdev *sd, u32 reg_addr)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = set_i2c_page(info, client, reg_addr);
+
+	if (ret)
+		return ret;
+	return i2c_smbus_read_byte_data(client, reg_addr & 0xFF);
+}
+
+static int cam_i2c_write(struct v4l2_subdev *sd, u32 reg_addr, u32 val)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct noon010_info *info = to_noon010(sd);
+	int ret = set_i2c_page(info, client, reg_addr);
+
+	if (ret)
+		return ret;
+	return i2c_smbus_write_byte_data(client, reg_addr & 0xFF, val);
+}
+
+static inline int noon010_bulk_write_reg(struct v4l2_subdev *sd,
+					 const struct i2c_regval *msg)
+{
+	while (msg->addr != REG_TERM) {
+		int ret = cam_i2c_write(sd, msg->addr, msg->val);
+
+		if (ret)
+			return ret;
+		msg++;
+	}
+	return 0;
+}
+
+/* Device reset and sleep mode control */
+static int noon010_power_ctrl(struct v4l2_subdev *sd, bool reset, bool sleep)
+{
+	struct noon010_info *info = to_noon010(sd);
+	u8 reg = sleep ? 0xF1 : 0xF0;
+	int ret = 0;
+
+	if (reset)
+		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg | 0x02);
+	if (!ret) {
+		ret = cam_i2c_write(sd, POWER_CTRL_REG, reg);
+		if (reset && !ret)
+			info->i2c_reg_page = -1;
+	}
+	return ret;
+}
+
+/* Automatic white balance control */
+static int noon010_enable_autowhitebalance(struct v4l2_subdev *sd, int on)
+{
+	int ret;
+
+	ret = cam_i2c_write(sd, AWB_CTL_REG(1), on ? 0x2E : 0x2F);
+	if (!ret)
+		ret = cam_i2c_write(sd, AWB_CTL_REG(0), on ? 0xFB : 0x7B);
+	return ret;
+}
+
+static int noon010_set_flip(struct v4l2_subdev *sd, int hflip, int vflip)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int reg, ret;
+
+	reg = cam_i2c_read(sd, VDO_CTL_REG(1));
+	if (reg < 0)
+		return reg;
+
+	reg &= 0x7C;
+	if (hflip)
+		reg |= 0x01;
+	if (vflip)
+		reg |= 0x02;
+
+	ret = cam_i2c_write(sd, VDO_CTL_REG(1), reg | 0x80);
+	if (!ret) {
+		info->hflip = hflip;
+		info->vflip = vflip;
+	}
+	return ret;
+}
+
+/* Configure resolution and color format */
+static int noon010_set_params(struct v4l2_subdev *sd)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int ret;
+
+	if (!info->curr_win)
+		return -EINVAL;
+
+	ret = cam_i2c_write(sd, VDO_CTL_REG(0), info->curr_win->vid_ctl1);
+
+	if (!ret && info->curr_fmt)
+		ret = cam_i2c_write(sd, ISP_CTL_REG(0),
+				info->curr_fmt->ispctl1_reg);
+	return ret;
+}
+
+/* Find nearest matching image pixel size. */
+static int noon010_try_frame_size(struct v4l2_mbus_framefmt *mf)
+{
+	unsigned int min_err = ~0;
+	int i = ARRAY_SIZE(noon010_sizes);
+	const struct noon010_frmsize *fsize = &noon010_sizes[0],
+		*match = NULL;
+
+	while (i--) {
+		int err = abs(fsize->width - mf->width)
+				+ abs(fsize->height - mf->height);
+
+		if (err < min_err) {
+			min_err = err;
+			match = fsize;
+		}
+		fsize++;
+	}
+	if (match) {
+		mf->width  = match->width;
+		mf->height = match->height;
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int power_enable(struct noon010_info *info)
+{
+	int ret;
+
+	if (info->power) {
+		v4l2_info(&info->sd, "%s: sensor is already on\n", __func__);
+		return 0;
+	}
+
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_set_value(info->gpio_nstby, 0);
+
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_set_value(info->gpio_nreset, 0);
+
+	ret = regulator_bulk_enable(NOON010_NUM_SUPPLIES, info->supply);
+	if (ret)
+		return ret;
+
+	if (gpio_is_valid(info->gpio_nreset)) {
+		msleep(50);
+		gpio_set_value(info->gpio_nreset, 1);
+	}
+	if (gpio_is_valid(info->gpio_nstby)) {
+		udelay(1000);
+		gpio_set_value(info->gpio_nstby, 1);
+	}
+	if (gpio_is_valid(info->gpio_nreset)) {
+		udelay(1000);
+		gpio_set_value(info->gpio_nreset, 0);
+		msleep(100);
+		gpio_set_value(info->gpio_nreset, 1);
+		msleep(20);
+	}
+	info->power = 1;
+
+	v4l2_dbg(1, debug, &info->sd,  "%s: sensor is on\n", __func__);
+	return 0;
+}
+
+static int power_disable(struct noon010_info *info)
+{
+	int ret;
+
+	if (!info->power) {
+		v4l2_info(&info->sd, "%s: sensor is already off\n", __func__);
+		return 0;
+	}
+
+	ret = regulator_bulk_disable(NOON010_NUM_SUPPLIES, info->supply);
+	if (ret)
+		return ret;
+
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_set_value(info->gpio_nstby, 0);
+
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_set_value(info->gpio_nreset, 0);
+
+	info->power = 0;
+
+	v4l2_dbg(1, debug, &info->sd,  "%s: sensor is off\n", __func__);
+
+	return 0;
+}
+
+static int noon010_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct v4l2_subdev *sd = to_sd(ctrl);
+
+	v4l2_dbg(1, debug, sd, "%s: ctrl_id: %d, value: %d\n",
+		 __func__, ctrl->id, ctrl->val);
+
+	switch (ctrl->id) {
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		return noon010_enable_autowhitebalance(sd, ctrl->val);
+	case V4L2_CID_BLUE_BALANCE:
+		return cam_i2c_write(sd, MWB_BGAIN_REG, ctrl->val);
+	case V4L2_CID_RED_BALANCE:
+		return cam_i2c_write(sd, MWB_RGAIN_REG, ctrl->val);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int noon010_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			    enum v4l2_mbus_pixelcode *code)
+{
+	if (!code || index >= ARRAY_SIZE(noon010_formats))
+		return -EINVAL;
+
+	*code = noon010_formats[index].code;
+	return 0;
+}
+
+static int noon010_g_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int ret;
+
+	if (!mf)
+		return -EINVAL;
+
+	if (!info->curr_win || !info->curr_fmt) {
+		ret = noon010_set_params(sd);
+		if (ret)
+			return ret;
+	}
+
+	mf->width	= info->curr_win->width;
+	mf->height	= info->curr_win->height;
+	mf->code	= info->curr_fmt->code;
+	mf->colorspace	= info->curr_fmt->colorspace;
+	mf->field	= V4L2_FIELD_NONE;
+
+	return 0;
+}
+
+/* Return nearest media bus frame format. */
+static const struct noon010_format *try_fmt(struct v4l2_subdev *sd,
+					    struct v4l2_mbus_framefmt *mf)
+{
+	int i = ARRAY_SIZE(noon010_formats);
+
+	noon010_try_frame_size(mf);
+
+	while (i--)
+		if (mf->code == noon010_formats[i].code)
+			break;
+
+	mf->code = noon010_formats[i].code;
+
+	return &noon010_formats[i];
+}
+
+static int noon010_try_fmt(struct v4l2_subdev *sd,
+			   struct v4l2_mbus_framefmt *mf)
+{
+	if (!sd || !mf)
+		return -EINVAL;
+
+	try_fmt(sd, mf);
+	return 0;
+}
+
+static int noon010_s_fmt(struct v4l2_subdev *sd,
+			 struct v4l2_mbus_framefmt *mf)
+{
+	struct noon010_info *info = to_noon010(sd);
+
+	if (!sd || !mf)
+		return -EINVAL;
+
+	info->curr_fmt = try_fmt(sd, mf);
+
+	return noon010_set_params(sd);
+}
+
+static int noon010_base_config(struct v4l2_subdev *sd)
+{
+	struct noon010_info *info = to_noon010(sd);
+	int ret;
+
+	ret = noon010_bulk_write_reg(sd, noon010_base_regs);
+	if (!ret) {
+		info->curr_fmt = &noon010_formats[0];
+		info->curr_win = &noon010_sizes[0];
+		ret = noon010_set_params(sd);
+	}
+	if (!ret)
+		ret = noon010_set_flip(sd, 1, 0);
+	if (!ret)
+		ret = noon010_power_ctrl(sd, false, false);
+
+	/* sync the handler and the registers state */
+	v4l2_ctrl_handler_setup(&to_noon010(sd)->hdl);
+	return ret;
+}
+
+static int noon010_s_power(struct v4l2_subdev *sd, int on)
+{
+	struct noon010_info *info = to_noon010(sd);
+	const struct noon010pc30_platform_data *pdata = info->pdata;
+	int ret = 0;
+
+	if (WARN(pdata == NULL, "No platform data!\n"))
+		return -ENOMEM;
+
+	if (on) {
+		ret = power_enable(info);
+		if (ret)
+			return ret;
+		ret = noon010_base_config(sd);
+	} else {
+		noon010_power_ctrl(sd, false, true);
+		ret = power_disable(info);
+		info->curr_win = NULL;
+		info->curr_fmt = NULL;
+	}
+
+	return ret;
+}
+
+static int noon010_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_NOON010PC30, 0);
+}
+
+static int noon010_log_status(struct v4l2_subdev *sd)
+{
+	struct noon010_info *info = to_noon010(sd);
+
+	v4l2_ctrl_handler_log_status(&info->hdl, sd->name);
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops noon010_ctrl_ops = {
+	.s_ctrl = noon010_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops noon010_core_ops = {
+	.g_chip_ident	= noon010_g_chip_ident,
+	.s_power	= noon010_s_power,
+	.g_ctrl		= v4l2_subdev_g_ctrl,
+	.s_ctrl		= v4l2_subdev_s_ctrl,
+	.queryctrl	= v4l2_subdev_queryctrl,
+	.querymenu	= v4l2_subdev_querymenu,
+	.g_ext_ctrls	= v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls	= v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls	= v4l2_subdev_s_ext_ctrls,
+	.log_status	= noon010_log_status,
+};
+
+static const struct v4l2_subdev_video_ops noon010_video_ops = {
+	.g_mbus_fmt	= noon010_g_fmt,
+	.s_mbus_fmt	= noon010_s_fmt,
+	.try_mbus_fmt	= noon010_try_fmt,
+	.enum_mbus_fmt	= noon010_enum_fmt,
+};
+
+static const struct v4l2_subdev_ops noon010_ops = {
+	.core	= &noon010_core_ops,
+	.video	= &noon010_video_ops,
+};
+
+/* Return 0 if NOON010PC30L sensor type was detected or -ENODEV otherwise. */
+static int noon010_detect(struct i2c_client *client, struct noon010_info *info)
+{
+	int ret;
+
+	ret = power_enable(info);
+	if (ret)
+		return ret;
+
+	ret = i2c_smbus_read_byte_data(client, DEVICE_ID_REG);
+	if (ret < 0)
+		dev_err(&client->dev, "I2C read failed: 0x%X\n", ret);
+
+	power_disable(info);
+
+	return ret == NOON010PC30_ID ? 0 : -ENODEV;
+}
+
+static int noon010_probe(struct i2c_client *client,
+			 const struct i2c_device_id *id)
+{
+	struct noon010_info *info;
+	struct v4l2_subdev *sd;
+	const struct noon010pc30_platform_data *pdata
+		= client->dev.platform_data;
+	int ret;
+	int i;
+
+	if (!pdata) {
+		dev_err(&client->dev, "No platform data!\n");
+		return -EIO;
+	}
+
+	info = kzalloc(sizeof(*info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	sd = &info->sd;
+	strlcpy(sd->name, MODULE_NAME, sizeof(sd->name));
+	v4l2_i2c_subdev_init(sd, client, &noon010_ops);
+
+	v4l2_ctrl_handler_init(&info->hdl, 3);
+
+	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
+			  V4L2_CID_AUTO_WHITE_BALANCE, 0, 1, 1, 1);
+	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
+			  V4L2_CID_RED_BALANCE, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&info->hdl, &noon010_ctrl_ops,
+			  V4L2_CID_BLUE_BALANCE, 0, 127, 1, 64);
+
+	sd->ctrl_handler = &info->hdl;
+
+	ret = info->hdl.error;
+	if (ret)
+		goto np_err;
+
+	info->pdata		= client->dev.platform_data;
+	info->i2c_reg_page	= -1;
+	info->gpio_nreset	= -EINVAL;
+	info->gpio_nstby	= -EINVAL;
+
+	if (gpio_is_valid(pdata->gpio_nreset)) {
+		ret = gpio_request(pdata->gpio_nreset, "NOON010PC30 NRST");
+		if (ret) {
+			dev_err(&client->dev, "GPIO request error: %d\n", ret);
+			goto np_err;
+		}
+		info->gpio_nreset = pdata->gpio_nreset;
+		gpio_direction_output(info->gpio_nreset, 0);
+		gpio_export(info->gpio_nreset, 0);
+	}
+
+	if (gpio_is_valid(pdata->gpio_nstby)) {
+		ret = gpio_request(pdata->gpio_nstby, "NOON010PC30 NSTBY");
+		if (ret) {
+			dev_err(&client->dev, "GPIO request error: %d\n", ret);
+			goto np_gpio_err;
+		}
+		info->gpio_nstby = pdata->gpio_nstby;
+		gpio_direction_output(info->gpio_nstby, 0);
+		gpio_export(info->gpio_nstby, 0);
+	}
+
+	for (i = 0; i < NOON010_NUM_SUPPLIES; i++)
+		info->supply[i].supply = noon010_supply_name[i];
+
+	ret = regulator_bulk_get(&client->dev, NOON010_NUM_SUPPLIES,
+				 info->supply);
+	if (ret)
+		goto np_reg_err;
+
+	ret = noon010_detect(client, info);
+	if (!ret)
+		return 0;
+
+	/* the sensor detection failed */
+	regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
+np_reg_err:
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_free(info->gpio_nstby);
+np_gpio_err:
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_free(info->gpio_nreset);
+np_err:
+	v4l2_ctrl_handler_free(&info->hdl);
+	v4l2_device_unregister_subdev(sd);
+	kfree(info);
+	return ret;
+}
+
+static int noon010_remove(struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct noon010_info *info = to_noon010(sd);
+
+	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&info->hdl);
+
+	regulator_bulk_free(NOON010_NUM_SUPPLIES, info->supply);
+
+	if (gpio_is_valid(info->gpio_nreset))
+		gpio_free(info->gpio_nreset);
+
+	if (gpio_is_valid(info->gpio_nstby))
+		gpio_free(info->gpio_nstby);
+
+	kfree(info);
+	return 0;
+}
+
+static const struct i2c_device_id noon010_id[] = {
+	{ MODULE_NAME, 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(i2c, noon010_id);
+
+
+static struct i2c_driver noon010_i2c_driver = {
+	.driver = {
+		.name = MODULE_NAME
+	},
+	.probe		= noon010_probe,
+	.remove		= noon010_remove,
+	.id_table	= noon010_id,
+};
+
+static int __init noon010_init(void)
+{
+	return i2c_add_driver(&noon010_i2c_driver);
+}
+
+static void __exit noon010_exit(void)
+{
+	i2c_del_driver(&noon010_i2c_driver);
+}
+
+module_init(noon010_init);
+module_exit(noon010_exit);
+
+MODULE_DESCRIPTION("Siliconfile NOON010PC30 camera driver");
+MODULE_AUTHOR("Sylwester Nawrocki <s.nawrocki@samsung.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap/omap_vout.c linux-libre-2.6.39-gnu/drivers/media/video/omap/omap_vout.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap/omap_vout.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap/omap_vout.c	2011-05-19 00:06:34.000000000 -0400
@@ -473,7 +473,7 @@
 /*
  * Convert V4L2 rotation to DSS rotation
  *	V4L2 understand 0, 90, 180, 270.
- *	Convert to 0, 1, 2 and 3 repsectively for DSS
+ *	Convert to 0, 1, 2 and 3 respectively for DSS
  */
 static int v4l2_rot_to_dss_rot(int v4l2_rotation,
 			enum dss_rotation *rotation, bool mirror)
@@ -1142,7 +1142,7 @@
 }
 
 /*
- * Buffer queue funtion will be called from the videobuf layer when _QBUF
+ * Buffer queue function will be called from the videobuf layer when _QBUF
  * ioctl is called. It is used to enqueue buffer, which is ready to be
  * displayed.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap/omap_voutlib.c linux-libre-2.6.39-gnu/drivers/media/video/omap/omap_voutlib.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap/omap_voutlib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap/omap_voutlib.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 /* Given a new render window in new_win, adjust the window to the
  * nearest supported configuration.  The adjusted window parameters are
  * returned in new_win.
- * Returns zero if succesful, or -EINVAL if the requested window is
+ * Returns zero if successful, or -EINVAL if the requested window is
  * impossible and cannot reasonably be adjusted.
  */
 int omap_vout_try_window(struct v4l2_framebuffer *fbuf,
@@ -101,7 +101,7 @@
  * will also be adjusted if necessary.  Preference is given to keeping the
  * the window as close to the requested configuration as possible.  If
  * successful, new_win, vout->win, and crop are updated.
- * Returns zero if succesful, or -EINVAL if the requested preview window is
+ * Returns zero if successful, or -EINVAL if the requested preview window is
  * impossible and cannot reasonably be adjusted.
  */
 int omap_vout_new_window(struct v4l2_rect *crop,
@@ -155,7 +155,7 @@
  * window would fall outside the display boundaries, the cropping rectangle
  * will also be adjusted to maintain the rescaling ratios.  If successful, crop
  * and win are updated.
- * Returns zero if succesful, or -EINVAL if the requested cropping rectangle is
+ * Returns zero if successful, or -EINVAL if the requested cropping rectangle is
  * impossible and cannot reasonably be adjusted.
  */
 int omap_vout_new_crop(struct v4l2_pix_format *pix,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap1_camera.c linux-libre-2.6.39-gnu/drivers/media/video/omap1_camera.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap1_camera.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap1_camera.c	2011-05-19 00:06:34.000000000 -0400
@@ -687,7 +687,7 @@
 		 * In CONTIG mode, the current buffer parameters had already
 		 * been entered into the DMA programming register set while the
 		 * buffer was fetched with prepare_next_vb(), they may have also
-		 * been transfered into the runtime set and already active if
+		 * been transferred into the runtime set and already active if
 		 * the DMA still running.
 		 */
 	} else {
@@ -811,8 +811,8 @@
 	spin_lock_irqsave(&pcdev->lock, flags);
 
 	if (WARN_ON(!buf)) {
-		dev_warn(dev, "%s: unhandled camera interrupt, status == "
-				"%#x\n", __func__, it_status);
+		dev_warn(dev, "%s: unhandled camera interrupt, status == %#x\n",
+			 __func__, it_status);
 		suspend_capture(pcdev);
 		disable_capture(pcdev);
 		goto out;
@@ -835,7 +835,7 @@
 				/*
 				 * If exactly 2 sgbufs from the next sglist have
 				 * been programmed into the DMA engine (the
-				 * frist one already transfered into the DMA
+				 * first one already transferred into the DMA
 				 * runtime register set, the second one still
 				 * in the programming set), then we are in sync.
 				 */
@@ -1088,15 +1088,15 @@
 			xlate->host_fmt	= &omap1_cam_formats[code];
 			xlate->code	= code;
 			xlate++;
-			dev_dbg(dev, "%s: providing format %s "
-					"as byte swapped code #%d\n", __func__,
-					omap1_cam_formats[code].name, code);
+			dev_dbg(dev,
+				"%s: providing format %s as byte swapped code #%d\n",
+				__func__, omap1_cam_formats[code].name, code);
 		}
 	default:
 		if (xlate)
-			dev_dbg(dev, "%s: providing format %s "
-					"in pass-through mode\n", __func__,
-					fmt->name);
+			dev_dbg(dev,
+				"%s: providing format %s in pass-through mode\n",
+				__func__, fmt->name);
 	}
 	formats++;
 	if (xlate) {
@@ -1139,29 +1139,29 @@
 	return 1;
 }
 
-#define subdev_call_with_sense(pcdev, dev, icd, sd, function, args...)	   \
-({									   \
-	struct soc_camera_sense sense = {				   \
-		.master_clock		= pcdev->camexclk,		   \
-		.pixel_clock_max	= 0,				   \
-	};								   \
-	int __ret;							   \
-									   \
-	if (pcdev->pdata)						   \
-		sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000; \
-	icd->sense = &sense;						   \
-	__ret = v4l2_subdev_call(sd, video, function, ##args);		   \
-	icd->sense = NULL;						   \
-									   \
-	if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {			   \
-		if (sense.pixel_clock > sense.pixel_clock_max) {	   \
-			dev_err(dev, "%s: pixel clock %lu "		   \
-					"set by the camera too high!\n",   \
-					__func__, sense.pixel_clock);	   \
-			__ret = -EINVAL;				   \
-		}							   \
-	}								   \
-	__ret;								   \
+#define subdev_call_with_sense(pcdev, dev, icd, sd, function, args...)		     \
+({										     \
+	struct soc_camera_sense sense = {					     \
+		.master_clock		= pcdev->camexclk,			     \
+		.pixel_clock_max	= 0,					     \
+	};									     \
+	int __ret;								     \
+										     \
+	if (pcdev->pdata)							     \
+		sense.pixel_clock_max = pcdev->pdata->lclk_khz_max * 1000;	     \
+	icd->sense = &sense;							     \
+	__ret = v4l2_subdev_call(sd, video, function, ##args);			     \
+	icd->sense = NULL;							     \
+										     \
+	if (sense.flags & SOCAM_SENSE_PCLK_CHANGED) {				     \
+		if (sense.pixel_clock > sense.pixel_clock_max) {		     \
+			dev_err(dev,						     \
+				"%s: pixel clock %lu set by the camera too high!\n", \
+				__func__, sense.pixel_clock);			     \
+			__ret = -EINVAL;					     \
+		}								     \
+	}									     \
+	__ret;									     \
 })
 
 static int set_mbus_format(struct omap1_cam_dev *pcdev, struct device *dev,
@@ -1664,10 +1664,10 @@
 	res = pcdev->res;
 	release_mem_region(res->start, resource_size(res));
 
-	kfree(pcdev);
-
 	clk_put(pcdev->clk);
 
+	kfree(pcdev);
+
 	dev_info(&pdev->dev, "OMAP1 Camera Interface driver unloaded\n");
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap24xxcam.c linux-libre-2.6.39-gnu/drivers/media/video/omap24xxcam.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap24xxcam.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap24xxcam.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 
 #include <media/v4l2-common.h>
 #include <media/v4l2-ioctl.h>
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/cfa_coef_table.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/cfa_coef_table.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/cfa_coef_table.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/cfa_coef_table.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * cfa_coef_table.h
+ *
+ * TI OMAP3 ISP - CFA coefficients table
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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
+ */
+
+244,   0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
+248,   0,   0,   0,   0,  40,   0,   0, 244,  12, 250,   4,   0,  27,   0, 250,
+247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248,
+244,   0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
+248,   0,   0,   0,   0,  40,   0,   0, 244,  12, 250,   4,   0,  27,   0, 250,
+247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248,
+244,   0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
+248,   0,   0,   0,   0,  40,   0,   0, 244,  12, 250,   4,   0,  27,   0, 250,
+247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248,
+  0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
+  0,   0,   0, 248,   0,   0,  40,   0,   4, 250,  12, 244, 250,   0,  27,   0,
+ 12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0,
+  0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
+  0,   0,   0, 248,   0,   0,  40,   0,   4, 250,  12, 244, 250,   0,  27,   0,
+ 12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0,
+  0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
+  0,   0,   0, 248,   0,   0,  40,   0,   4, 250,  12, 244, 250,   0,  27,   0,
+ 12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0,
+  4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
+  0,   0,   0, 248,   0,   0,  40,   0,   0, 247,   0, 244, 247,  36,  27,  12,
+  0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0,
+  4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
+  0,   0,   0, 248,   0,   0,  40,   0,   0, 247,   0, 244, 247,  36,  27,  12,
+  0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0,
+  4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
+  0,   0,   0, 248,   0,   0,  40,   0,   0, 247,   0, 244, 247,  36,  27,  12,
+  0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0,
+244,  12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
+248,   0,   0,   0,   0,  40,   0,   0, 244,   0, 247,   0,  12,  27,  36, 247,
+250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248,
+244,  12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
+248,   0,   0,   0,   0,  40,   0,   0, 244,   0, 247,   0,  12,  27,  36, 247,
+250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248,
+244,  12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
+248,   0,   0,   0,   0,  40,   0,   0, 244,   0, 247,   0,  12,  27,  36, 247,
+250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/gamma_table.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/gamma_table.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/gamma_table.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/gamma_table.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,90 @@
+/*
+ * gamma_table.h
+ *
+ * TI OMAP3 ISP - Default gamma table for all components
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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
+ */
+
+  0,   0,   1,   2,   3,   3,   4,   5,   6,   8,  10,  12,  14,  16,  18,  20,
+ 22,  23,  25,  26,  28,  29,  31,  32,  34,  35,  36,  37,  39,  40,  41,  42,
+ 43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  52,  53,  54,  55,  56,  57,
+ 58,  59,  60,  61,  62,  63,  63,  64,  65,  66,  66,  67,  68,  69,  69,  70,
+ 71,  72,  72,  73,  74,  75,  75,  76,  77,  78,  78,  79,  80,  81,  81,  82,
+ 83,  84,  84,  85,  86,  87,  88,  88,  89,  90,  91,  91,  92,  93,  94,  94,
+ 95,  96,  97,  97,  98,  98,  99,  99, 100, 100, 101, 101, 102, 103, 104, 104,
+105, 106, 107, 108, 108, 109, 110, 111, 111, 112, 113, 114, 114, 115, 116, 117,
+117, 118, 119, 119, 120, 120, 121, 121, 122, 122, 123, 123, 124, 124, 125, 125,
+126, 126, 127, 127, 128, 128, 129, 129, 130, 130, 131, 131, 132, 132, 133, 133,
+134, 134, 135, 135, 136, 136, 137, 137, 138, 138, 139, 139, 140, 140, 141, 141,
+142, 142, 143, 143, 144, 144, 145, 145, 146, 146, 147, 147, 148, 148, 149, 149,
+150, 150, 151, 151, 152, 152, 153, 153, 153, 153, 154, 154, 154, 154, 155, 155,
+156, 156, 157, 157, 158, 158, 158, 159, 159, 159, 160, 160, 160, 161, 161, 162,
+162, 163, 163, 164, 164, 164, 164, 165, 165, 165, 165, 166, 166, 167, 167, 168,
+168, 169, 169, 170, 170, 170, 170, 171, 171, 171, 171, 172, 172, 173, 173, 174,
+174, 175, 175, 176, 176, 176, 176, 177, 177, 177, 177, 178, 178, 178, 178, 179,
+179, 179, 179, 180, 180, 180, 180, 181, 181, 181, 181, 182, 182, 182, 182, 183,
+183, 183, 183, 184, 184, 184, 184, 185, 185, 185, 185, 186, 186, 186, 186, 187,
+187, 187, 187, 188, 188, 188, 188, 189, 189, 189, 189, 190, 190, 190, 190, 191,
+191, 191, 191, 192, 192, 192, 192, 193, 193, 193, 193, 194, 194, 194, 194, 195,
+195, 195, 195, 196, 196, 196, 196, 197, 197, 197, 197, 198, 198, 198, 198, 199,
+199, 199, 199, 200, 200, 200, 200, 201, 201, 201, 201, 202, 202, 202, 203, 203,
+203, 203, 204, 204, 204, 204, 205, 205, 205, 205, 206, 206, 206, 206, 207, 207,
+207, 207, 208, 208, 208, 208, 209, 209, 209, 209, 210, 210, 210, 210, 210, 210,
+210, 210, 210, 210, 210, 210, 211, 211, 211, 211, 211, 211, 211, 211, 211, 211,
+211, 212, 212, 212, 212, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213, 213,
+213, 214, 214, 214, 214, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215, 215,
+216, 216, 216, 216, 217, 217, 217, 217, 218, 218, 218, 218, 219, 219, 219, 219,
+219, 219, 219, 219, 219, 219, 219, 219, 220, 220, 220, 220, 221, 221, 221, 221,
+221, 221, 221, 221, 221, 221, 221, 222, 222, 222, 222, 223, 223, 223, 223, 223,
+223, 223, 223, 223, 223, 223, 223, 224, 224, 224, 224, 225, 225, 225, 225, 225,
+225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 225, 226, 226,
+226, 226, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 227, 228, 228,
+228, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 229, 230, 230, 230,
+230, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 231, 232, 232, 232,
+232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232, 232,
+233, 233, 233, 233, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 234, 235,
+235, 235, 235, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236, 236,
+236, 236, 236, 236, 236, 236, 237, 237, 237, 237, 238, 238, 238, 238, 238, 238,
+238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238, 238,
+238, 238, 238, 238, 238, 239, 239, 239, 239, 240, 240, 240, 240, 240, 240, 240,
+240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240, 240,
+240, 240, 240, 240, 241, 241, 241, 241, 242, 242, 242, 242, 242, 242, 242, 242,
+242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242, 242,
+242, 242, 243, 243, 243, 243, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
+244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244, 244,
+244, 245, 245, 245, 245, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246,
+246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246, 246,
+246, 246, 246, 246, 246, 246, 246, 247, 247, 247, 247, 248, 248, 248, 248, 248,
+248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248, 248,
+248, 248, 248, 248, 248, 248, 249, 249, 249, 249, 250, 250, 250, 250, 250, 250,
+250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
+250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250, 250,
+250, 250, 250, 250, 251, 251, 251, 251, 252, 252, 252, 252, 252, 252, 252, 252,
+252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252, 252,
+252, 252, 252, 252, 252, 252, 252, 252, 253, 253, 253, 253, 253, 253, 253, 253,
+253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253, 253,
+253, 254, 254, 254, 254, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
+255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isp.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isp.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2236 @@
+/*
+ * isp.c
+ *
+ * TI OMAP3 ISP - Core
+ *
+ * Copyright (C) 2006-2010 Nokia Corporation
+ * Copyright (C) 2007-2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * Contributors:
+ *	Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	Sakari Ailus <sakari.ailus@iki.fi>
+ *	David Cohen <dacohen@gmail.com>
+ *	Stanimir Varbanov <svarbanov@mm-sol.com>
+ *	Vimarsh Zutshi <vimarsh.zutshi@gmail.com>
+ *	Tuukka Toivonen <tuukkat76@gmail.com>
+ *	Sergio Aguirre <saaguirre@ti.com>
+ *	Antti Koskipaa <akoskipa@gmail.com>
+ *	Ivan T. Ivanov <iivanov@mm-sol.com>
+ *	RaniSuneela <r-m@ti.com>
+ *	Atanas Filipov <afilipov@mm-sol.com>
+ *	Gjorgji Rosikopulos <grosikopulos@mm-sol.com>
+ *	Hiroshi DOYU <hiroshi.doyu@nokia.com>
+ *	Nayden Kanchev <nkanchev@mm-sol.com>
+ *	Phil Carmody <ext-phil.2.carmody@nokia.com>
+ *	Artem Bityutskiy <artem.bityutskiy@nokia.com>
+ *	Dominic Curran <dcurran@ti.com>
+ *	Ilkka Myllyperkio <ilkka.myllyperkio@sofica.fi>
+ *	Pallavi Kulkarni <p-kulkarni@ti.com>
+ *	Vaibhav Hiremath <hvaibhav@ti.com>
+ *	Mohit Jalori <mjalori@ti.com>
+ *	Sameer Venkatraman <sameerv@ti.com>
+ *	Senthilvadivu Guruswamy <svadivu@ti.com>
+ *	Thara Gopinath <thara@ti.com>
+ *	Toni Leinonen <toni.leinonen@nokia.com>
+ *	Troy Laramy <t-laramy@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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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 <asm/cacheflush.h>
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/i2c.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-device.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispccdc.h"
+#include "isppreview.h"
+#include "ispresizer.h"
+#include "ispcsi2.h"
+#include "ispccp2.h"
+#include "isph3a.h"
+#include "isphist.h"
+
+static unsigned int autoidle;
+module_param(autoidle, int, 0444);
+MODULE_PARM_DESC(autoidle, "Enable OMAP3ISP AUTOIDLE support");
+
+static void isp_save_ctx(struct isp_device *isp);
+
+static void isp_restore_ctx(struct isp_device *isp);
+
+static const struct isp_res_mapping isp_res_maps[] = {
+	{
+		.isp_rev = ISP_REVISION_2_0,
+		.map = 1 << OMAP3_ISP_IOMEM_MAIN |
+		       1 << OMAP3_ISP_IOMEM_CCP2 |
+		       1 << OMAP3_ISP_IOMEM_CCDC |
+		       1 << OMAP3_ISP_IOMEM_HIST |
+		       1 << OMAP3_ISP_IOMEM_H3A |
+		       1 << OMAP3_ISP_IOMEM_PREV |
+		       1 << OMAP3_ISP_IOMEM_RESZ |
+		       1 << OMAP3_ISP_IOMEM_SBL |
+		       1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
+		       1 << OMAP3_ISP_IOMEM_CSIPHY2,
+	},
+	{
+		.isp_rev = ISP_REVISION_15_0,
+		.map = 1 << OMAP3_ISP_IOMEM_MAIN |
+		       1 << OMAP3_ISP_IOMEM_CCP2 |
+		       1 << OMAP3_ISP_IOMEM_CCDC |
+		       1 << OMAP3_ISP_IOMEM_HIST |
+		       1 << OMAP3_ISP_IOMEM_H3A |
+		       1 << OMAP3_ISP_IOMEM_PREV |
+		       1 << OMAP3_ISP_IOMEM_RESZ |
+		       1 << OMAP3_ISP_IOMEM_SBL |
+		       1 << OMAP3_ISP_IOMEM_CSI2A_REGS1 |
+		       1 << OMAP3_ISP_IOMEM_CSIPHY2 |
+		       1 << OMAP3_ISP_IOMEM_CSI2A_REGS2 |
+		       1 << OMAP3_ISP_IOMEM_CSI2C_REGS1 |
+		       1 << OMAP3_ISP_IOMEM_CSIPHY1 |
+		       1 << OMAP3_ISP_IOMEM_CSI2C_REGS2,
+	},
+};
+
+/* Structure for saving/restoring ISP module registers */
+static struct isp_reg isp_reg_list[] = {
+	{OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, 0},
+	{OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL, 0},
+	{0, ISP_TOK_TERM, 0}
+};
+
+/*
+ * omap3isp_flush - Post pending L3 bus writes by doing a register readback
+ * @isp: OMAP3 ISP device
+ *
+ * In order to force posting of pending writes, we need to write and
+ * readback the same register, in this case the revision register.
+ *
+ * See this link for reference:
+ *   http://www.mail-archive.com/linux-omap@vger.kernel.org/msg08149.html
+ */
+void omap3isp_flush(struct isp_device *isp)
+{
+	isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
+	isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
+}
+
+/*
+ * isp_enable_interrupts - Enable ISP interrupts.
+ * @isp: OMAP3 ISP device
+ */
+static void isp_enable_interrupts(struct isp_device *isp)
+{
+	static const u32 irq = IRQ0ENABLE_CSIA_IRQ
+			     | IRQ0ENABLE_CSIB_IRQ
+			     | IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ
+			     | IRQ0ENABLE_CCDC_LSC_DONE_IRQ
+			     | IRQ0ENABLE_CCDC_VD0_IRQ
+			     | IRQ0ENABLE_CCDC_VD1_IRQ
+			     | IRQ0ENABLE_HS_VS_IRQ
+			     | IRQ0ENABLE_HIST_DONE_IRQ
+			     | IRQ0ENABLE_H3A_AWB_DONE_IRQ
+			     | IRQ0ENABLE_H3A_AF_DONE_IRQ
+			     | IRQ0ENABLE_PRV_DONE_IRQ
+			     | IRQ0ENABLE_RSZ_DONE_IRQ;
+
+	isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+	isp_reg_writel(isp, irq, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
+}
+
+/*
+ * isp_disable_interrupts - Disable ISP interrupts.
+ * @isp: OMAP3 ISP device
+ */
+static void isp_disable_interrupts(struct isp_device *isp)
+{
+	isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0ENABLE);
+}
+
+/**
+ * isp_set_xclk - Configures the specified cam_xclk to the desired frequency.
+ * @isp: OMAP3 ISP device
+ * @xclk: Desired frequency of the clock in Hz. 0 = stable low, 1 is stable high
+ * @xclksel: XCLK to configure (0 = A, 1 = B).
+ *
+ * Configures the specified MCLK divisor in the ISP timing control register
+ * (TCTRL_CTRL) to generate the desired xclk clock value.
+ *
+ * Divisor = cam_mclk_hz / xclk
+ *
+ * Returns the final frequency that is actually being generated
+ **/
+static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
+{
+	u32 divisor;
+	u32 currentxclk;
+	unsigned long mclk_hz;
+
+	if (!omap3isp_get(isp))
+		return 0;
+
+	mclk_hz = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
+
+	if (xclk >= mclk_hz) {
+		divisor = ISPTCTRL_CTRL_DIV_BYPASS;
+		currentxclk = mclk_hz;
+	} else if (xclk >= 2) {
+		divisor = mclk_hz / xclk;
+		if (divisor >= ISPTCTRL_CTRL_DIV_BYPASS)
+			divisor = ISPTCTRL_CTRL_DIV_BYPASS - 1;
+		currentxclk = mclk_hz / divisor;
+	} else {
+		divisor = xclk;
+		currentxclk = 0;
+	}
+
+	switch (xclksel) {
+	case ISP_XCLK_A:
+		isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
+				ISPTCTRL_CTRL_DIVA_MASK,
+				divisor << ISPTCTRL_CTRL_DIVA_SHIFT);
+		dev_dbg(isp->dev, "isp_set_xclk(): cam_xclka set to %d Hz\n",
+			currentxclk);
+		break;
+	case ISP_XCLK_B:
+		isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_TCTRL_CTRL,
+				ISPTCTRL_CTRL_DIVB_MASK,
+				divisor << ISPTCTRL_CTRL_DIVB_SHIFT);
+		dev_dbg(isp->dev, "isp_set_xclk(): cam_xclkb set to %d Hz\n",
+			currentxclk);
+		break;
+	case ISP_XCLK_NONE:
+	default:
+		omap3isp_put(isp);
+		dev_dbg(isp->dev, "ISP_ERR: isp_set_xclk(): Invalid requested "
+			"xclk. Must be 0 (A) or 1 (B).\n");
+		return -EINVAL;
+	}
+
+	/* Do we go from stable whatever to clock? */
+	if (divisor >= 2 && isp->xclk_divisor[xclksel - 1] < 2)
+		omap3isp_get(isp);
+	/* Stopping the clock. */
+	else if (divisor < 2 && isp->xclk_divisor[xclksel - 1] >= 2)
+		omap3isp_put(isp);
+
+	isp->xclk_divisor[xclksel - 1] = divisor;
+
+	omap3isp_put(isp);
+
+	return currentxclk;
+}
+
+/*
+ * isp_power_settings - Sysconfig settings, for Power Management.
+ * @isp: OMAP3 ISP device
+ * @idle: Consider idle state.
+ *
+ * Sets the power settings for the ISP, and SBL bus.
+ */
+static void isp_power_settings(struct isp_device *isp, int idle)
+{
+	isp_reg_writel(isp,
+		       ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY :
+				ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY) <<
+			ISP_SYSCONFIG_MIDLEMODE_SHIFT) |
+			((isp->revision == ISP_REVISION_15_0) ?
+			  ISP_SYSCONFIG_AUTOIDLE : 0),
+		       OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
+
+	if (isp->autoidle)
+		isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
+			       ISP_CTRL);
+}
+
+/*
+ * Configure the bridge and lane shifter. Valid inputs are
+ *
+ * CCDC_INPUT_PARALLEL: Parallel interface
+ * CCDC_INPUT_CSI2A: CSI2a receiver
+ * CCDC_INPUT_CCP2B: CCP2b receiver
+ * CCDC_INPUT_CSI2C: CSI2c receiver
+ *
+ * The bridge and lane shifter are configured according to the selected input
+ * and the ISP platform data.
+ */
+void omap3isp_configure_bridge(struct isp_device *isp,
+			       enum ccdc_input_entity input,
+			       const struct isp_parallel_platform_data *pdata,
+			       unsigned int shift)
+{
+	u32 ispctrl_val;
+
+	ispctrl_val  = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
+	ispctrl_val &= ~ISPCTRL_SHIFT_MASK;
+	ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
+	ispctrl_val &= ~ISPCTRL_PAR_SER_CLK_SEL_MASK;
+	ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_MASK;
+
+	switch (input) {
+	case CCDC_INPUT_PARALLEL:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
+		ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
+		ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
+		shift += pdata->data_lane_shift * 2;
+		break;
+
+	case CCDC_INPUT_CSI2A:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIA;
+		break;
+
+	case CCDC_INPUT_CCP2B:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIB;
+		break;
+
+	case CCDC_INPUT_CSI2C:
+		ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_CSIC;
+		break;
+
+	default:
+		return;
+	}
+
+	ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
+
+	ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
+	ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
+
+	isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
+}
+
+/**
+ * isp_set_pixel_clock - Configures the ISP pixel clock
+ * @isp: OMAP3 ISP device
+ * @pixelclk: Average pixel clock in Hz
+ *
+ * Set the average pixel clock required by the sensor. The ISP will use the
+ * lowest possible memory bandwidth settings compatible with the clock.
+ **/
+static void isp_set_pixel_clock(struct isp_device *isp, unsigned int pixelclk)
+{
+	isp->isp_ccdc.vpcfg.pixelclk = pixelclk;
+}
+
+void omap3isp_hist_dma_done(struct isp_device *isp)
+{
+	if (omap3isp_ccdc_busy(&isp->isp_ccdc) ||
+	    omap3isp_stat_pcr_busy(&isp->isp_hist)) {
+		/* Histogram cannot be enabled in this frame anymore */
+		atomic_set(&isp->isp_hist.buf_err, 1);
+		dev_dbg(isp->dev, "hist: Out of synchronization with "
+				  "CCDC. Ignoring next buffer.\n");
+	}
+}
+
+static inline void isp_isr_dbg(struct isp_device *isp, u32 irqstatus)
+{
+	static const char *name[] = {
+		"CSIA_IRQ",
+		"res1",
+		"res2",
+		"CSIB_LCM_IRQ",
+		"CSIB_IRQ",
+		"res5",
+		"res6",
+		"res7",
+		"CCDC_VD0_IRQ",
+		"CCDC_VD1_IRQ",
+		"CCDC_VD2_IRQ",
+		"CCDC_ERR_IRQ",
+		"H3A_AF_DONE_IRQ",
+		"H3A_AWB_DONE_IRQ",
+		"res14",
+		"res15",
+		"HIST_DONE_IRQ",
+		"CCDC_LSC_DONE",
+		"CCDC_LSC_PREFETCH_COMPLETED",
+		"CCDC_LSC_PREFETCH_ERROR",
+		"PRV_DONE_IRQ",
+		"CBUFF_IRQ",
+		"res22",
+		"res23",
+		"RSZ_DONE_IRQ",
+		"OVF_IRQ",
+		"res26",
+		"res27",
+		"MMU_ERR_IRQ",
+		"OCP_ERR_IRQ",
+		"SEC_ERR_IRQ",
+		"HS_VS_IRQ",
+	};
+	int i;
+
+	dev_dbg(isp->dev, "");
+
+	for (i = 0; i < ARRAY_SIZE(name); i++) {
+		if ((1 << i) & irqstatus)
+			printk(KERN_CONT "%s ", name[i]);
+	}
+	printk(KERN_CONT "\n");
+}
+
+static void isp_isr_sbl(struct isp_device *isp)
+{
+	struct device *dev = isp->dev;
+	u32 sbl_pcr;
+
+	/*
+	 * Handle shared buffer logic overflows for video buffers.
+	 * ISPSBL_PCR_CCDCPRV_2_RSZ_OVF can be safely ignored.
+	 */
+	sbl_pcr = isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
+	isp_reg_writel(isp, sbl_pcr, OMAP3_ISP_IOMEM_SBL, ISPSBL_PCR);
+	sbl_pcr &= ~ISPSBL_PCR_CCDCPRV_2_RSZ_OVF;
+
+	if (sbl_pcr)
+		dev_dbg(dev, "SBL overflow (PCR = 0x%08x)\n", sbl_pcr);
+
+	if (sbl_pcr & (ISPSBL_PCR_CCDC_WBL_OVF | ISPSBL_PCR_CSIA_WBL_OVF
+		     | ISPSBL_PCR_CSIB_WBL_OVF)) {
+		isp->isp_ccdc.error = 1;
+		if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
+			isp->isp_prev.error = 1;
+		if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
+			isp->isp_res.error = 1;
+	}
+
+	if (sbl_pcr & ISPSBL_PCR_PRV_WBL_OVF) {
+		isp->isp_prev.error = 1;
+		if (isp->isp_res.input == RESIZER_INPUT_VP &&
+		    !(isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER))
+			isp->isp_res.error = 1;
+	}
+
+	if (sbl_pcr & (ISPSBL_PCR_RSZ1_WBL_OVF
+		       | ISPSBL_PCR_RSZ2_WBL_OVF
+		       | ISPSBL_PCR_RSZ3_WBL_OVF
+		       | ISPSBL_PCR_RSZ4_WBL_OVF))
+		isp->isp_res.error = 1;
+
+	if (sbl_pcr & ISPSBL_PCR_H3A_AF_WBL_OVF)
+		omap3isp_stat_sbl_overflow(&isp->isp_af);
+
+	if (sbl_pcr & ISPSBL_PCR_H3A_AEAWB_WBL_OVF)
+		omap3isp_stat_sbl_overflow(&isp->isp_aewb);
+}
+
+/*
+ * isp_isr - Interrupt Service Routine for Camera ISP module.
+ * @irq: Not used currently.
+ * @_isp: Pointer to the OMAP3 ISP device
+ *
+ * Handles the corresponding callback if plugged in.
+ *
+ * Returns IRQ_HANDLED when IRQ was correctly handled, or IRQ_NONE when the
+ * IRQ wasn't handled.
+ */
+static irqreturn_t isp_isr(int irq, void *_isp)
+{
+	static const u32 ccdc_events = IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ |
+				       IRQ0STATUS_CCDC_LSC_DONE_IRQ |
+				       IRQ0STATUS_CCDC_VD0_IRQ |
+				       IRQ0STATUS_CCDC_VD1_IRQ |
+				       IRQ0STATUS_HS_VS_IRQ;
+	struct isp_device *isp = _isp;
+	u32 irqstatus;
+	int ret;
+
+	irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+	isp_reg_writel(isp, irqstatus, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+
+	isp_isr_sbl(isp);
+
+	if (irqstatus & IRQ0STATUS_CSIA_IRQ) {
+		ret = omap3isp_csi2_isr(&isp->isp_csi2a);
+		if (ret)
+			isp->isp_ccdc.error = 1;
+	}
+
+	if (irqstatus & IRQ0STATUS_CSIB_IRQ) {
+		ret = omap3isp_ccp2_isr(&isp->isp_ccp2);
+		if (ret)
+			isp->isp_ccdc.error = 1;
+	}
+
+	if (irqstatus & IRQ0STATUS_CCDC_VD0_IRQ) {
+		if (isp->isp_ccdc.output & CCDC_OUTPUT_PREVIEW)
+			omap3isp_preview_isr_frame_sync(&isp->isp_prev);
+		if (isp->isp_ccdc.output & CCDC_OUTPUT_RESIZER)
+			omap3isp_resizer_isr_frame_sync(&isp->isp_res);
+		omap3isp_stat_isr_frame_sync(&isp->isp_aewb);
+		omap3isp_stat_isr_frame_sync(&isp->isp_af);
+		omap3isp_stat_isr_frame_sync(&isp->isp_hist);
+	}
+
+	if (irqstatus & ccdc_events)
+		omap3isp_ccdc_isr(&isp->isp_ccdc, irqstatus & ccdc_events);
+
+	if (irqstatus & IRQ0STATUS_PRV_DONE_IRQ) {
+		if (isp->isp_prev.output & PREVIEW_OUTPUT_RESIZER)
+			omap3isp_resizer_isr_frame_sync(&isp->isp_res);
+		omap3isp_preview_isr(&isp->isp_prev);
+	}
+
+	if (irqstatus & IRQ0STATUS_RSZ_DONE_IRQ)
+		omap3isp_resizer_isr(&isp->isp_res);
+
+	if (irqstatus & IRQ0STATUS_H3A_AWB_DONE_IRQ)
+		omap3isp_stat_isr(&isp->isp_aewb);
+
+	if (irqstatus & IRQ0STATUS_H3A_AF_DONE_IRQ)
+		omap3isp_stat_isr(&isp->isp_af);
+
+	if (irqstatus & IRQ0STATUS_HIST_DONE_IRQ)
+		omap3isp_stat_isr(&isp->isp_hist);
+
+	omap3isp_flush(isp);
+
+#if defined(DEBUG) && defined(ISP_ISR_DEBUG)
+	isp_isr_dbg(isp, irqstatus);
+#endif
+
+	return IRQ_HANDLED;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipeline power management
+ *
+ * Entities must be powered up when part of a pipeline that contains at least
+ * one open video device node.
+ *
+ * To achieve this use the entity use_count field to track the number of users.
+ * For entities corresponding to video device nodes the use_count field stores
+ * the users count of the node. For entities corresponding to subdevs the
+ * use_count field stores the total number of users of all video device nodes
+ * in the pipeline.
+ *
+ * The omap3isp_pipeline_pm_use() function must be called in the open() and
+ * close() handlers of video device nodes. It increments or decrements the use
+ * count of all subdev entities in the pipeline.
+ *
+ * To react to link management on powered pipelines, the link setup notification
+ * callback updates the use count of all entities in the source and sink sides
+ * of the link.
+ */
+
+/*
+ * isp_pipeline_pm_use_count - Count the number of users of a pipeline
+ * @entity: The entity
+ *
+ * Return the total number of users of all video device nodes in the pipeline.
+ */
+static int isp_pipeline_pm_use_count(struct media_entity *entity)
+{
+	struct media_entity_graph graph;
+	int use = 0;
+
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+		if (media_entity_type(entity) == MEDIA_ENT_T_DEVNODE)
+			use += entity->use_count;
+	}
+
+	return use;
+}
+
+/*
+ * isp_pipeline_pm_power_one - Apply power change to an entity
+ * @entity: The entity
+ * @change: Use count change
+ *
+ * Change the entity use count by @change. If the entity is a subdev update its
+ * power state by calling the core::s_power operation when the use count goes
+ * from 0 to != 0 or from != 0 to 0.
+ *
+ * Return 0 on success or a negative error code on failure.
+ */
+static int isp_pipeline_pm_power_one(struct media_entity *entity, int change)
+{
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	subdev = media_entity_type(entity) == MEDIA_ENT_T_V4L2_SUBDEV
+	       ? media_entity_to_v4l2_subdev(entity) : NULL;
+
+	if (entity->use_count == 0 && change > 0 && subdev != NULL) {
+		ret = v4l2_subdev_call(subdev, core, s_power, 1);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			return ret;
+	}
+
+	entity->use_count += change;
+	WARN_ON(entity->use_count < 0);
+
+	if (entity->use_count == 0 && change < 0 && subdev != NULL)
+		v4l2_subdev_call(subdev, core, s_power, 0);
+
+	return 0;
+}
+
+/*
+ * isp_pipeline_pm_power - Apply power change to all entities in a pipeline
+ * @entity: The entity
+ * @change: Use count change
+ *
+ * Walk the pipeline to update the use count and the power state of all non-node
+ * entities.
+ *
+ * Return 0 on success or a negative error code on failure.
+ */
+static int isp_pipeline_pm_power(struct media_entity *entity, int change)
+{
+	struct media_entity_graph graph;
+	struct media_entity *first = entity;
+	int ret = 0;
+
+	if (!change)
+		return 0;
+
+	media_entity_graph_walk_start(&graph, entity);
+
+	while (!ret && (entity = media_entity_graph_walk_next(&graph)))
+		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+			ret = isp_pipeline_pm_power_one(entity, change);
+
+	if (!ret)
+		return 0;
+
+	media_entity_graph_walk_start(&graph, first);
+
+	while ((first = media_entity_graph_walk_next(&graph))
+	       && first != entity)
+		if (media_entity_type(first) != MEDIA_ENT_T_DEVNODE)
+			isp_pipeline_pm_power_one(first, -change);
+
+	return ret;
+}
+
+/*
+ * omap3isp_pipeline_pm_use - Update the use count of an entity
+ * @entity: The entity
+ * @use: Use (1) or stop using (0) the entity
+ *
+ * Update the use count of all entities in the pipeline and power entities on or
+ * off accordingly.
+ *
+ * Return 0 on success or a negative error code on failure. Powering entities
+ * off is assumed to never fail. No failure can occur when the use parameter is
+ * set to 0.
+ */
+int omap3isp_pipeline_pm_use(struct media_entity *entity, int use)
+{
+	int change = use ? 1 : -1;
+	int ret;
+
+	mutex_lock(&entity->parent->graph_mutex);
+
+	/* Apply use count to node. */
+	entity->use_count += change;
+	WARN_ON(entity->use_count < 0);
+
+	/* Apply power change to connected non-nodes. */
+	ret = isp_pipeline_pm_power(entity, change);
+	if (ret < 0)
+		entity->use_count -= change;
+
+	mutex_unlock(&entity->parent->graph_mutex);
+
+	return ret;
+}
+
+/*
+ * isp_pipeline_link_notify - Link management notification callback
+ * @source: Pad at the start of the link
+ * @sink: Pad at the end of the link
+ * @flags: New link flags that will be applied
+ *
+ * React to link management on powered pipelines by updating the use count of
+ * all entities in the source and sink sides of the link. Entities are powered
+ * on or off accordingly.
+ *
+ * Return 0 on success or a negative error code on failure. Powering entities
+ * off is assumed to never fail. This function will not fail for disconnection
+ * events.
+ */
+static int isp_pipeline_link_notify(struct media_pad *source,
+				    struct media_pad *sink, u32 flags)
+{
+	int source_use = isp_pipeline_pm_use_count(source->entity);
+	int sink_use = isp_pipeline_pm_use_count(sink->entity);
+	int ret;
+
+	if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+		/* Powering off entities is assumed to never fail. */
+		isp_pipeline_pm_power(source->entity, -sink_use);
+		isp_pipeline_pm_power(sink->entity, -source_use);
+		return 0;
+	}
+
+	ret = isp_pipeline_pm_power(source->entity, sink_use);
+	if (ret < 0)
+		return ret;
+
+	ret = isp_pipeline_pm_power(sink->entity, source_use);
+	if (ret < 0)
+		isp_pipeline_pm_power(source->entity, -sink_use);
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * Pipeline stream management
+ */
+
+/*
+ * isp_pipeline_enable - Enable streaming on a pipeline
+ * @pipe: ISP pipeline
+ * @mode: Stream mode (single shot or continuous)
+ *
+ * Walk the entities chain starting at the pipeline output video node and start
+ * all modules in the chain in the given mode.
+ *
+ * Return 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise.
+ */
+static int isp_pipeline_enable(struct isp_pipeline *pipe,
+			       enum isp_pipeline_stream_state mode)
+{
+	struct isp_device *isp = pipe->output->isp;
+	struct media_entity *entity;
+	struct media_pad *pad;
+	struct v4l2_subdev *subdev;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&pipe->lock, flags);
+	pipe->state &= ~(ISP_PIPELINE_IDLE_INPUT | ISP_PIPELINE_IDLE_OUTPUT);
+	spin_unlock_irqrestore(&pipe->lock, flags);
+
+	pipe->do_propagation = false;
+
+	entity = &pipe->output->video.entity;
+	while (1) {
+		pad = &entity->pads[0];
+		if (!(pad->flags & MEDIA_PAD_FL_SINK))
+			break;
+
+		pad = media_entity_remote_source(pad);
+		if (pad == NULL ||
+		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		entity = pad->entity;
+		subdev = media_entity_to_v4l2_subdev(entity);
+
+		ret = v4l2_subdev_call(subdev, video, s_stream, mode);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			break;
+
+		if (subdev == &isp->isp_ccdc.subdev) {
+			v4l2_subdev_call(&isp->isp_aewb.subdev, video,
+					s_stream, mode);
+			v4l2_subdev_call(&isp->isp_af.subdev, video,
+					s_stream, mode);
+			v4l2_subdev_call(&isp->isp_hist.subdev, video,
+					s_stream, mode);
+			pipe->do_propagation = true;
+		}
+	}
+
+	/* Frame number propagation. In continuous streaming mode the number
+	 * is incremented in the frame start ISR. In mem-to-mem mode
+	 * singleshot is used and frame start IRQs are not available.
+	 * Thus we have to increment the number here.
+	 */
+	if (pipe->do_propagation && mode == ISP_PIPELINE_STREAM_SINGLESHOT)
+		atomic_inc(&pipe->frame_number);
+
+	return ret;
+}
+
+static int isp_pipeline_wait_resizer(struct isp_device *isp)
+{
+	return omap3isp_resizer_busy(&isp->isp_res);
+}
+
+static int isp_pipeline_wait_preview(struct isp_device *isp)
+{
+	return omap3isp_preview_busy(&isp->isp_prev);
+}
+
+static int isp_pipeline_wait_ccdc(struct isp_device *isp)
+{
+	return omap3isp_stat_busy(&isp->isp_af)
+	    || omap3isp_stat_busy(&isp->isp_aewb)
+	    || omap3isp_stat_busy(&isp->isp_hist)
+	    || omap3isp_ccdc_busy(&isp->isp_ccdc);
+}
+
+#define ISP_STOP_TIMEOUT	msecs_to_jiffies(1000)
+
+static int isp_pipeline_wait(struct isp_device *isp,
+			     int(*busy)(struct isp_device *isp))
+{
+	unsigned long timeout = jiffies + ISP_STOP_TIMEOUT;
+
+	while (!time_after(jiffies, timeout)) {
+		if (!busy(isp))
+			return 0;
+	}
+
+	return 1;
+}
+
+/*
+ * isp_pipeline_disable - Disable streaming on a pipeline
+ * @pipe: ISP pipeline
+ *
+ * Walk the entities chain starting at the pipeline output video node and stop
+ * all modules in the chain. Wait synchronously for the modules to be stopped if
+ * necessary.
+ *
+ * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module
+ * can't be stopped (in which case a software reset of the ISP is probably
+ * necessary).
+ */
+static int isp_pipeline_disable(struct isp_pipeline *pipe)
+{
+	struct isp_device *isp = pipe->output->isp;
+	struct media_entity *entity;
+	struct media_pad *pad;
+	struct v4l2_subdev *subdev;
+	int failure = 0;
+	int ret;
+
+	/*
+	 * We need to stop all the modules after CCDC first or they'll
+	 * never stop since they may not get a full frame from CCDC.
+	 */
+	entity = &pipe->output->video.entity;
+	while (1) {
+		pad = &entity->pads[0];
+		if (!(pad->flags & MEDIA_PAD_FL_SINK))
+			break;
+
+		pad = media_entity_remote_source(pad);
+		if (pad == NULL ||
+		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		entity = pad->entity;
+		subdev = media_entity_to_v4l2_subdev(entity);
+
+		if (subdev == &isp->isp_ccdc.subdev) {
+			v4l2_subdev_call(&isp->isp_aewb.subdev,
+					 video, s_stream, 0);
+			v4l2_subdev_call(&isp->isp_af.subdev,
+					 video, s_stream, 0);
+			v4l2_subdev_call(&isp->isp_hist.subdev,
+					 video, s_stream, 0);
+		}
+
+		v4l2_subdev_call(subdev, video, s_stream, 0);
+
+		if (subdev == &isp->isp_res.subdev)
+			ret = isp_pipeline_wait(isp, isp_pipeline_wait_resizer);
+		else if (subdev == &isp->isp_prev.subdev)
+			ret = isp_pipeline_wait(isp, isp_pipeline_wait_preview);
+		else if (subdev == &isp->isp_ccdc.subdev)
+			ret = isp_pipeline_wait(isp, isp_pipeline_wait_ccdc);
+		else
+			ret = 0;
+
+		if (ret) {
+			dev_info(isp->dev, "Unable to stop %s\n", subdev->name);
+			failure = -ETIMEDOUT;
+		}
+	}
+
+	if (failure < 0)
+		isp->needs_reset = true;
+
+	return failure;
+}
+
+/*
+ * omap3isp_pipeline_set_stream - Enable/disable streaming on a pipeline
+ * @pipe: ISP pipeline
+ * @state: Stream state (stopped, single shot or continuous)
+ *
+ * Set the pipeline to the given stream state. Pipelines can be started in
+ * single-shot or continuous mode.
+ *
+ * Return 0 if successful, or the return value of the failed video::s_stream
+ * operation otherwise. The pipeline state is not updated when the operation
+ * fails, except when stopping the pipeline.
+ */
+int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
+				 enum isp_pipeline_stream_state state)
+{
+	int ret;
+
+	if (state == ISP_PIPELINE_STREAM_STOPPED)
+		ret = isp_pipeline_disable(pipe);
+	else
+		ret = isp_pipeline_enable(pipe, state);
+
+	if (ret == 0 || state == ISP_PIPELINE_STREAM_STOPPED)
+		pipe->stream_state = state;
+
+	return ret;
+}
+
+/*
+ * isp_pipeline_resume - Resume streaming on a pipeline
+ * @pipe: ISP pipeline
+ *
+ * Resume video output and input and re-enable pipeline.
+ */
+static void isp_pipeline_resume(struct isp_pipeline *pipe)
+{
+	int singleshot = pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT;
+
+	omap3isp_video_resume(pipe->output, !singleshot);
+	if (singleshot)
+		omap3isp_video_resume(pipe->input, 0);
+	isp_pipeline_enable(pipe, pipe->stream_state);
+}
+
+/*
+ * isp_pipeline_suspend - Suspend streaming on a pipeline
+ * @pipe: ISP pipeline
+ *
+ * Suspend pipeline.
+ */
+static void isp_pipeline_suspend(struct isp_pipeline *pipe)
+{
+	isp_pipeline_disable(pipe);
+}
+
+/*
+ * isp_pipeline_is_last - Verify if entity has an enabled link to the output
+ * 			  video node
+ * @me: ISP module's media entity
+ *
+ * Returns 1 if the entity has an enabled link to the output video node or 0
+ * otherwise. It's true only while pipeline can have no more than one output
+ * node.
+ */
+static int isp_pipeline_is_last(struct media_entity *me)
+{
+	struct isp_pipeline *pipe;
+	struct media_pad *pad;
+
+	if (!me->pipe)
+		return 0;
+	pipe = to_isp_pipeline(me);
+	if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED)
+		return 0;
+	pad = media_entity_remote_source(&pipe->output->pad);
+	return pad->entity == me;
+}
+
+/*
+ * isp_suspend_module_pipeline - Suspend pipeline to which belongs the module
+ * @me: ISP module's media entity
+ *
+ * Suspend the whole pipeline if module's entity has an enabled link to the
+ * output video node. It works only while pipeline can have no more than one
+ * output node.
+ */
+static void isp_suspend_module_pipeline(struct media_entity *me)
+{
+	if (isp_pipeline_is_last(me))
+		isp_pipeline_suspend(to_isp_pipeline(me));
+}
+
+/*
+ * isp_resume_module_pipeline - Resume pipeline to which belongs the module
+ * @me: ISP module's media entity
+ *
+ * Resume the whole pipeline if module's entity has an enabled link to the
+ * output video node. It works only while pipeline can have no more than one
+ * output node.
+ */
+static void isp_resume_module_pipeline(struct media_entity *me)
+{
+	if (isp_pipeline_is_last(me))
+		isp_pipeline_resume(to_isp_pipeline(me));
+}
+
+/*
+ * isp_suspend_modules - Suspend ISP submodules.
+ * @isp: OMAP3 ISP device
+ *
+ * Returns 0 if suspend left in idle state all the submodules properly,
+ * or returns 1 if a general Reset is required to suspend the submodules.
+ */
+static int isp_suspend_modules(struct isp_device *isp)
+{
+	unsigned long timeout;
+
+	omap3isp_stat_suspend(&isp->isp_aewb);
+	omap3isp_stat_suspend(&isp->isp_af);
+	omap3isp_stat_suspend(&isp->isp_hist);
+	isp_suspend_module_pipeline(&isp->isp_res.subdev.entity);
+	isp_suspend_module_pipeline(&isp->isp_prev.subdev.entity);
+	isp_suspend_module_pipeline(&isp->isp_ccdc.subdev.entity);
+	isp_suspend_module_pipeline(&isp->isp_csi2a.subdev.entity);
+	isp_suspend_module_pipeline(&isp->isp_ccp2.subdev.entity);
+
+	timeout = jiffies + ISP_STOP_TIMEOUT;
+	while (omap3isp_stat_busy(&isp->isp_af)
+	    || omap3isp_stat_busy(&isp->isp_aewb)
+	    || omap3isp_stat_busy(&isp->isp_hist)
+	    || omap3isp_preview_busy(&isp->isp_prev)
+	    || omap3isp_resizer_busy(&isp->isp_res)
+	    || omap3isp_ccdc_busy(&isp->isp_ccdc)) {
+		if (time_after(jiffies, timeout)) {
+			dev_info(isp->dev, "can't stop modules.\n");
+			return 1;
+		}
+		msleep(1);
+	}
+
+	return 0;
+}
+
+/*
+ * isp_resume_modules - Resume ISP submodules.
+ * @isp: OMAP3 ISP device
+ */
+static void isp_resume_modules(struct isp_device *isp)
+{
+	omap3isp_stat_resume(&isp->isp_aewb);
+	omap3isp_stat_resume(&isp->isp_af);
+	omap3isp_stat_resume(&isp->isp_hist);
+	isp_resume_module_pipeline(&isp->isp_res.subdev.entity);
+	isp_resume_module_pipeline(&isp->isp_prev.subdev.entity);
+	isp_resume_module_pipeline(&isp->isp_ccdc.subdev.entity);
+	isp_resume_module_pipeline(&isp->isp_csi2a.subdev.entity);
+	isp_resume_module_pipeline(&isp->isp_ccp2.subdev.entity);
+}
+
+/*
+ * isp_reset - Reset ISP with a timeout wait for idle.
+ * @isp: OMAP3 ISP device
+ */
+static int isp_reset(struct isp_device *isp)
+{
+	unsigned long timeout = 0;
+
+	isp_reg_writel(isp,
+		       isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG)
+		       | ISP_SYSCONFIG_SOFTRESET,
+		       OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
+	while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN,
+			       ISP_SYSSTATUS) & 0x1)) {
+		if (timeout++ > 10000) {
+			dev_alert(isp->dev, "cannot reset ISP\n");
+			return -ETIMEDOUT;
+		}
+		udelay(1);
+	}
+
+	return 0;
+}
+
+/*
+ * isp_save_context - Saves the values of the ISP module registers.
+ * @isp: OMAP3 ISP device
+ * @reg_list: Structure containing pairs of register address and value to
+ *            modify on OMAP.
+ */
+static void
+isp_save_context(struct isp_device *isp, struct isp_reg *reg_list)
+{
+	struct isp_reg *next = reg_list;
+
+	for (; next->reg != ISP_TOK_TERM; next++)
+		next->val = isp_reg_readl(isp, next->mmio_range, next->reg);
+}
+
+/*
+ * isp_restore_context - Restores the values of the ISP module registers.
+ * @isp: OMAP3 ISP device
+ * @reg_list: Structure containing pairs of register address and value to
+ *            modify on OMAP.
+ */
+static void
+isp_restore_context(struct isp_device *isp, struct isp_reg *reg_list)
+{
+	struct isp_reg *next = reg_list;
+
+	for (; next->reg != ISP_TOK_TERM; next++)
+		isp_reg_writel(isp, next->val, next->mmio_range, next->reg);
+}
+
+/*
+ * isp_save_ctx - Saves ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
+ * @isp: OMAP3 ISP device
+ *
+ * Routine for saving the context of each module in the ISP.
+ * CCDC, HIST, H3A, PREV, RESZ and MMU.
+ */
+static void isp_save_ctx(struct isp_device *isp)
+{
+	isp_save_context(isp, isp_reg_list);
+	if (isp->iommu)
+		iommu_save_ctx(isp->iommu);
+}
+
+/*
+ * isp_restore_ctx - Restores ISP, CCDC, HIST, H3A, PREV, RESZ & MMU context.
+ * @isp: OMAP3 ISP device
+ *
+ * Routine for restoring the context of each module in the ISP.
+ * CCDC, HIST, H3A, PREV, RESZ and MMU.
+ */
+static void isp_restore_ctx(struct isp_device *isp)
+{
+	isp_restore_context(isp, isp_reg_list);
+	if (isp->iommu)
+		iommu_restore_ctx(isp->iommu);
+	omap3isp_ccdc_restore_context(isp);
+	omap3isp_preview_restore_context(isp);
+}
+
+/* -----------------------------------------------------------------------------
+ * SBL resources management
+ */
+#define OMAP3_ISP_SBL_READ	(OMAP3_ISP_SBL_CSI1_READ | \
+				 OMAP3_ISP_SBL_CCDC_LSC_READ | \
+				 OMAP3_ISP_SBL_PREVIEW_READ | \
+				 OMAP3_ISP_SBL_RESIZER_READ)
+#define OMAP3_ISP_SBL_WRITE	(OMAP3_ISP_SBL_CSI1_WRITE | \
+				 OMAP3_ISP_SBL_CSI2A_WRITE | \
+				 OMAP3_ISP_SBL_CSI2C_WRITE | \
+				 OMAP3_ISP_SBL_CCDC_WRITE | \
+				 OMAP3_ISP_SBL_PREVIEW_WRITE)
+
+void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res)
+{
+	u32 sbl = 0;
+
+	isp->sbl_resources |= res;
+
+	if (isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ)
+		sbl |= ISPCTRL_SBL_SHARED_RPORTA;
+
+	if (isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ)
+		sbl |= ISPCTRL_SBL_SHARED_RPORTB;
+
+	if (isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE)
+		sbl |= ISPCTRL_SBL_SHARED_WPORTC;
+
+	if (isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE)
+		sbl |= ISPCTRL_SBL_WR0_RAM_EN;
+
+	if (isp->sbl_resources & OMAP3_ISP_SBL_WRITE)
+		sbl |= ISPCTRL_SBL_WR1_RAM_EN;
+
+	if (isp->sbl_resources & OMAP3_ISP_SBL_READ)
+		sbl |= ISPCTRL_SBL_RD_RAM_EN;
+
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
+}
+
+void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res)
+{
+	u32 sbl = 0;
+
+	isp->sbl_resources &= ~res;
+
+	if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI1_READ))
+		sbl |= ISPCTRL_SBL_SHARED_RPORTA;
+
+	if (!(isp->sbl_resources & OMAP3_ISP_SBL_CCDC_LSC_READ))
+		sbl |= ISPCTRL_SBL_SHARED_RPORTB;
+
+	if (!(isp->sbl_resources & OMAP3_ISP_SBL_CSI2C_WRITE))
+		sbl |= ISPCTRL_SBL_SHARED_WPORTC;
+
+	if (!(isp->sbl_resources & OMAP3_ISP_SBL_RESIZER_WRITE))
+		sbl |= ISPCTRL_SBL_WR0_RAM_EN;
+
+	if (!(isp->sbl_resources & OMAP3_ISP_SBL_WRITE))
+		sbl |= ISPCTRL_SBL_WR1_RAM_EN;
+
+	if (!(isp->sbl_resources & OMAP3_ISP_SBL_READ))
+		sbl |= ISPCTRL_SBL_RD_RAM_EN;
+
+	isp_reg_clr(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL, sbl);
+}
+
+/*
+ * isp_module_sync_idle - Helper to sync module with its idle state
+ * @me: ISP submodule's media entity
+ * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
+ * @stopping: flag which tells module wants to stop
+ *
+ * This function checks if ISP submodule needs to wait for next interrupt. If
+ * yes, makes the caller to sleep while waiting for such event.
+ */
+int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
+			      atomic_t *stopping)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(me);
+
+	if (pipe->stream_state == ISP_PIPELINE_STREAM_STOPPED ||
+	    (pipe->stream_state == ISP_PIPELINE_STREAM_SINGLESHOT &&
+	     !isp_pipeline_ready(pipe)))
+		return 0;
+
+	/*
+	 * atomic_set() doesn't include memory barrier on ARM platform for SMP
+	 * scenario. We'll call it here to avoid race conditions.
+	 */
+	atomic_set(stopping, 1);
+	smp_mb();
+
+	/*
+	 * If module is the last one, it's writing to memory. In this case,
+	 * it's necessary to check if the module is already paused due to
+	 * DMA queue underrun or if it has to wait for next interrupt to be
+	 * idle.
+	 * If it isn't the last one, the function won't sleep but *stopping
+	 * will still be set to warn next submodule caller's interrupt the
+	 * module wants to be idle.
+	 */
+	if (isp_pipeline_is_last(me)) {
+		struct isp_video *video = pipe->output;
+		unsigned long flags;
+		spin_lock_irqsave(&video->queue->irqlock, flags);
+		if (video->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
+			spin_unlock_irqrestore(&video->queue->irqlock, flags);
+			atomic_set(stopping, 0);
+			smp_mb();
+			return 0;
+		}
+		spin_unlock_irqrestore(&video->queue->irqlock, flags);
+		if (!wait_event_timeout(*wait, !atomic_read(stopping),
+					msecs_to_jiffies(1000))) {
+			atomic_set(stopping, 0);
+			smp_mb();
+			return -ETIMEDOUT;
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * omap3isp_module_sync_is_stopped - Helper to verify if module was stopping
+ * @wait: ISP submodule's wait queue for streamoff/interrupt synchronization
+ * @stopping: flag which tells module wants to stop
+ *
+ * This function checks if ISP submodule was stopping. In case of yes, it
+ * notices the caller by setting stopping to 0 and waking up the wait queue.
+ * Returns 1 if it was stopping or 0 otherwise.
+ */
+int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
+				     atomic_t *stopping)
+{
+	if (atomic_cmpxchg(stopping, 1, 0)) {
+		wake_up(wait);
+		return 1;
+	}
+
+	return 0;
+}
+
+/* --------------------------------------------------------------------------
+ * Clock management
+ */
+
+#define ISPCTRL_CLKS_MASK	(ISPCTRL_H3A_CLK_EN | \
+				 ISPCTRL_HIST_CLK_EN | \
+				 ISPCTRL_RSZ_CLK_EN | \
+				 (ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN) | \
+				 (ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN))
+
+static void __isp_subclk_update(struct isp_device *isp)
+{
+	u32 clk = 0;
+
+	if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A)
+		clk |= ISPCTRL_H3A_CLK_EN;
+
+	if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
+		clk |= ISPCTRL_HIST_CLK_EN;
+
+	if (isp->subclk_resources & OMAP3_ISP_SUBCLK_RESIZER)
+		clk |= ISPCTRL_RSZ_CLK_EN;
+
+	/* NOTE: For CCDC & Preview submodules, we need to affect internal
+	 *       RAM as well.
+	 */
+	if (isp->subclk_resources & OMAP3_ISP_SUBCLK_CCDC)
+		clk |= ISPCTRL_CCDC_CLK_EN | ISPCTRL_CCDC_RAM_EN;
+
+	if (isp->subclk_resources & OMAP3_ISP_SUBCLK_PREVIEW)
+		clk |= ISPCTRL_PREV_CLK_EN | ISPCTRL_PREV_RAM_EN;
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+			ISPCTRL_CLKS_MASK, clk);
+}
+
+void omap3isp_subclk_enable(struct isp_device *isp,
+			    enum isp_subclk_resource res)
+{
+	isp->subclk_resources |= res;
+
+	__isp_subclk_update(isp);
+}
+
+void omap3isp_subclk_disable(struct isp_device *isp,
+			     enum isp_subclk_resource res)
+{
+	isp->subclk_resources &= ~res;
+
+	__isp_subclk_update(isp);
+}
+
+/*
+ * isp_enable_clocks - Enable ISP clocks
+ * @isp: OMAP3 ISP device
+ *
+ * Return 0 if successful, or clk_enable return value if any of tthem fails.
+ */
+static int isp_enable_clocks(struct isp_device *isp)
+{
+	int r;
+	unsigned long rate;
+	int divisor;
+
+	/*
+	 * cam_mclk clock chain:
+	 *   dpll4 -> dpll4_m5 -> dpll4_m5x2 -> cam_mclk
+	 *
+	 * In OMAP3630 dpll4_m5x2 != 2 x dpll4_m5 but both are
+	 * set to the same value. Hence the rate set for dpll4_m5
+	 * has to be twice of what is set on OMAP3430 to get
+	 * the required value for cam_mclk
+	 */
+	if (cpu_is_omap3630())
+		divisor = 1;
+	else
+		divisor = 2;
+
+	r = clk_enable(isp->clock[ISP_CLK_CAM_ICK]);
+	if (r) {
+		dev_err(isp->dev, "clk_enable cam_ick failed\n");
+		goto out_clk_enable_ick;
+	}
+	r = clk_set_rate(isp->clock[ISP_CLK_DPLL4_M5_CK],
+			 CM_CAM_MCLK_HZ/divisor);
+	if (r) {
+		dev_err(isp->dev, "clk_set_rate for dpll4_m5_ck failed\n");
+		goto out_clk_enable_mclk;
+	}
+	r = clk_enable(isp->clock[ISP_CLK_CAM_MCLK]);
+	if (r) {
+		dev_err(isp->dev, "clk_enable cam_mclk failed\n");
+		goto out_clk_enable_mclk;
+	}
+	rate = clk_get_rate(isp->clock[ISP_CLK_CAM_MCLK]);
+	if (rate != CM_CAM_MCLK_HZ)
+		dev_warn(isp->dev, "unexpected cam_mclk rate:\n"
+				   " expected : %d\n"
+				   " actual   : %ld\n", CM_CAM_MCLK_HZ, rate);
+	r = clk_enable(isp->clock[ISP_CLK_CSI2_FCK]);
+	if (r) {
+		dev_err(isp->dev, "clk_enable csi2_fck failed\n");
+		goto out_clk_enable_csi2_fclk;
+	}
+	return 0;
+
+out_clk_enable_csi2_fclk:
+	clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
+out_clk_enable_mclk:
+	clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
+out_clk_enable_ick:
+	return r;
+}
+
+/*
+ * isp_disable_clocks - Disable ISP clocks
+ * @isp: OMAP3 ISP device
+ */
+static void isp_disable_clocks(struct isp_device *isp)
+{
+	clk_disable(isp->clock[ISP_CLK_CAM_ICK]);
+	clk_disable(isp->clock[ISP_CLK_CAM_MCLK]);
+	clk_disable(isp->clock[ISP_CLK_CSI2_FCK]);
+}
+
+static const char *isp_clocks[] = {
+	"cam_ick",
+	"cam_mclk",
+	"dpll4_m5_ck",
+	"csi2_96m_fck",
+	"l3_ick",
+};
+
+static void isp_put_clocks(struct isp_device *isp)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
+		if (isp->clock[i]) {
+			clk_put(isp->clock[i]);
+			isp->clock[i] = NULL;
+		}
+	}
+}
+
+static int isp_get_clocks(struct isp_device *isp)
+{
+	struct clk *clk;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(isp_clocks); ++i) {
+		clk = clk_get(isp->dev, isp_clocks[i]);
+		if (IS_ERR(clk)) {
+			dev_err(isp->dev, "clk_get %s failed\n", isp_clocks[i]);
+			isp_put_clocks(isp);
+			return PTR_ERR(clk);
+		}
+
+		isp->clock[i] = clk;
+	}
+
+	return 0;
+}
+
+/*
+ * omap3isp_get - Acquire the ISP resource.
+ *
+ * Initializes the clocks for the first acquire.
+ *
+ * Increment the reference count on the ISP. If the first reference is taken,
+ * enable clocks and power-up all submodules.
+ *
+ * Return a pointer to the ISP device structure, or NULL if an error occurred.
+ */
+struct isp_device *omap3isp_get(struct isp_device *isp)
+{
+	struct isp_device *__isp = isp;
+
+	if (isp == NULL)
+		return NULL;
+
+	mutex_lock(&isp->isp_mutex);
+	if (isp->ref_count > 0)
+		goto out;
+
+	if (isp_enable_clocks(isp) < 0) {
+		__isp = NULL;
+		goto out;
+	}
+
+	/* We don't want to restore context before saving it! */
+	if (isp->has_context)
+		isp_restore_ctx(isp);
+	else
+		isp->has_context = 1;
+
+	isp_enable_interrupts(isp);
+
+out:
+	if (__isp != NULL)
+		isp->ref_count++;
+	mutex_unlock(&isp->isp_mutex);
+
+	return __isp;
+}
+
+/*
+ * omap3isp_put - Release the ISP
+ *
+ * Decrement the reference count on the ISP. If the last reference is released,
+ * power-down all submodules, disable clocks and free temporary buffers.
+ */
+void omap3isp_put(struct isp_device *isp)
+{
+	if (isp == NULL)
+		return;
+
+	mutex_lock(&isp->isp_mutex);
+	BUG_ON(isp->ref_count == 0);
+	if (--isp->ref_count == 0) {
+		isp_disable_interrupts(isp);
+		isp_save_ctx(isp);
+		if (isp->needs_reset) {
+			isp_reset(isp);
+			isp->needs_reset = false;
+		}
+		isp_disable_clocks(isp);
+	}
+	mutex_unlock(&isp->isp_mutex);
+}
+
+/* --------------------------------------------------------------------------
+ * Platform device driver
+ */
+
+/*
+ * omap3isp_print_status - Prints the values of the ISP Control Module registers
+ * @isp: OMAP3 ISP device
+ */
+#define ISP_PRINT_REGISTER(isp, name)\
+	dev_dbg(isp->dev, "###ISP " #name "=0x%08x\n", \
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_##name))
+#define SBL_PRINT_REGISTER(isp, name)\
+	dev_dbg(isp->dev, "###SBL " #name "=0x%08x\n", \
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_##name))
+
+void omap3isp_print_status(struct isp_device *isp)
+{
+	dev_dbg(isp->dev, "-------------ISP Register dump--------------\n");
+
+	ISP_PRINT_REGISTER(isp, SYSCONFIG);
+	ISP_PRINT_REGISTER(isp, SYSSTATUS);
+	ISP_PRINT_REGISTER(isp, IRQ0ENABLE);
+	ISP_PRINT_REGISTER(isp, IRQ0STATUS);
+	ISP_PRINT_REGISTER(isp, TCTRL_GRESET_LENGTH);
+	ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_REPLAY);
+	ISP_PRINT_REGISTER(isp, CTRL);
+	ISP_PRINT_REGISTER(isp, TCTRL_CTRL);
+	ISP_PRINT_REGISTER(isp, TCTRL_FRAME);
+	ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_DELAY);
+	ISP_PRINT_REGISTER(isp, TCTRL_STRB_DELAY);
+	ISP_PRINT_REGISTER(isp, TCTRL_SHUT_DELAY);
+	ISP_PRINT_REGISTER(isp, TCTRL_PSTRB_LENGTH);
+	ISP_PRINT_REGISTER(isp, TCTRL_STRB_LENGTH);
+	ISP_PRINT_REGISTER(isp, TCTRL_SHUT_LENGTH);
+
+	SBL_PRINT_REGISTER(isp, PCR);
+	SBL_PRINT_REGISTER(isp, SDR_REQ_EXP);
+
+	dev_dbg(isp->dev, "--------------------------------------------\n");
+}
+
+#ifdef CONFIG_PM
+
+/*
+ * Power management support.
+ *
+ * As the ISP can't properly handle an input video stream interruption on a non
+ * frame boundary, the ISP pipelines need to be stopped before sensors get
+ * suspended. However, as suspending the sensors can require a running clock,
+ * which can be provided by the ISP, the ISP can't be completely suspended
+ * before the sensor.
+ *
+ * To solve this problem power management support is split into prepare/complete
+ * and suspend/resume operations. The pipelines are stopped in prepare() and the
+ * ISP clocks get disabled in suspend(). Similarly, the clocks are reenabled in
+ * resume(), and the the pipelines are restarted in complete().
+ *
+ * TODO: PM dependencies between the ISP and sensors are not modeled explicitly
+ * yet.
+ */
+static int isp_pm_prepare(struct device *dev)
+{
+	struct isp_device *isp = dev_get_drvdata(dev);
+	int reset;
+
+	WARN_ON(mutex_is_locked(&isp->isp_mutex));
+
+	if (isp->ref_count == 0)
+		return 0;
+
+	reset = isp_suspend_modules(isp);
+	isp_disable_interrupts(isp);
+	isp_save_ctx(isp);
+	if (reset)
+		isp_reset(isp);
+
+	return 0;
+}
+
+static int isp_pm_suspend(struct device *dev)
+{
+	struct isp_device *isp = dev_get_drvdata(dev);
+
+	WARN_ON(mutex_is_locked(&isp->isp_mutex));
+
+	if (isp->ref_count)
+		isp_disable_clocks(isp);
+
+	return 0;
+}
+
+static int isp_pm_resume(struct device *dev)
+{
+	struct isp_device *isp = dev_get_drvdata(dev);
+
+	if (isp->ref_count == 0)
+		return 0;
+
+	return isp_enable_clocks(isp);
+}
+
+static void isp_pm_complete(struct device *dev)
+{
+	struct isp_device *isp = dev_get_drvdata(dev);
+
+	if (isp->ref_count == 0)
+		return;
+
+	isp_restore_ctx(isp);
+	isp_enable_interrupts(isp);
+	isp_resume_modules(isp);
+}
+
+#else
+
+#define isp_pm_prepare	NULL
+#define isp_pm_suspend	NULL
+#define isp_pm_resume	NULL
+#define isp_pm_complete	NULL
+
+#endif /* CONFIG_PM */
+
+static void isp_unregister_entities(struct isp_device *isp)
+{
+	omap3isp_csi2_unregister_entities(&isp->isp_csi2a);
+	omap3isp_ccp2_unregister_entities(&isp->isp_ccp2);
+	omap3isp_ccdc_unregister_entities(&isp->isp_ccdc);
+	omap3isp_preview_unregister_entities(&isp->isp_prev);
+	omap3isp_resizer_unregister_entities(&isp->isp_res);
+	omap3isp_stat_unregister_entities(&isp->isp_aewb);
+	omap3isp_stat_unregister_entities(&isp->isp_af);
+	omap3isp_stat_unregister_entities(&isp->isp_hist);
+
+	v4l2_device_unregister(&isp->v4l2_dev);
+	media_device_unregister(&isp->media_dev);
+}
+
+/*
+ * isp_register_subdev_group - Register a group of subdevices
+ * @isp: OMAP3 ISP device
+ * @board_info: I2C subdevs board information array
+ *
+ * Register all I2C subdevices in the board_info array. The array must be
+ * terminated by a NULL entry, and the first entry must be the sensor.
+ *
+ * Return a pointer to the sensor media entity if it has been successfully
+ * registered, or NULL otherwise.
+ */
+static struct v4l2_subdev *
+isp_register_subdev_group(struct isp_device *isp,
+		     struct isp_subdev_i2c_board_info *board_info)
+{
+	struct v4l2_subdev *sensor = NULL;
+	unsigned int first;
+
+	if (board_info->board_info == NULL)
+		return NULL;
+
+	for (first = 1; board_info->board_info; ++board_info, first = 0) {
+		struct v4l2_subdev *subdev;
+		struct i2c_adapter *adapter;
+
+		adapter = i2c_get_adapter(board_info->i2c_adapter_id);
+		if (adapter == NULL) {
+			printk(KERN_ERR "%s: Unable to get I2C adapter %d for "
+				"device %s\n", __func__,
+				board_info->i2c_adapter_id,
+				board_info->board_info->type);
+			continue;
+		}
+
+		subdev = v4l2_i2c_new_subdev_board(&isp->v4l2_dev, adapter,
+				board_info->board_info, NULL);
+		if (subdev == NULL) {
+			printk(KERN_ERR "%s: Unable to register subdev %s\n",
+				__func__, board_info->board_info->type);
+			continue;
+		}
+
+		if (first)
+			sensor = subdev;
+	}
+
+	return sensor;
+}
+
+static int isp_register_entities(struct isp_device *isp)
+{
+	struct isp_platform_data *pdata = isp->pdata;
+	struct isp_v4l2_subdevs_group *subdevs;
+	int ret;
+
+	isp->media_dev.dev = isp->dev;
+	strlcpy(isp->media_dev.model, "TI OMAP3 ISP",
+		sizeof(isp->media_dev.model));
+	isp->media_dev.link_notify = isp_pipeline_link_notify;
+	ret = media_device_register(&isp->media_dev);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: Media device registration failed (%d)\n",
+			__func__, ret);
+		return ret;
+	}
+
+	isp->v4l2_dev.mdev = &isp->media_dev;
+	ret = v4l2_device_register(isp->dev, &isp->v4l2_dev);
+	if (ret < 0) {
+		printk(KERN_ERR "%s: V4L2 device registration failed (%d)\n",
+			__func__, ret);
+		goto done;
+	}
+
+	/* Register internal entities */
+	ret = omap3isp_ccp2_register_entities(&isp->isp_ccp2, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_csi2_register_entities(&isp->isp_csi2a, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_ccdc_register_entities(&isp->isp_ccdc, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_preview_register_entities(&isp->isp_prev,
+						 &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_resizer_register_entities(&isp->isp_res, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_stat_register_entities(&isp->isp_aewb, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_stat_register_entities(&isp->isp_af, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	ret = omap3isp_stat_register_entities(&isp->isp_hist, &isp->v4l2_dev);
+	if (ret < 0)
+		goto done;
+
+	/* Register external entities */
+	for (subdevs = pdata->subdevs; subdevs->subdevs; ++subdevs) {
+		struct v4l2_subdev *sensor;
+		struct media_entity *input;
+		unsigned int flags;
+		unsigned int pad;
+
+		sensor = isp_register_subdev_group(isp, subdevs->subdevs);
+		if (sensor == NULL)
+			continue;
+
+		sensor->host_priv = subdevs;
+
+		/* Connect the sensor to the correct interface module. Parallel
+		 * sensors are connected directly to the CCDC, while serial
+		 * sensors are connected to the CSI2a, CCP2b or CSI2c receiver
+		 * through CSIPHY1 or CSIPHY2.
+		 */
+		switch (subdevs->interface) {
+		case ISP_INTERFACE_PARALLEL:
+			input = &isp->isp_ccdc.subdev.entity;
+			pad = CCDC_PAD_SINK;
+			flags = 0;
+			break;
+
+		case ISP_INTERFACE_CSI2A_PHY2:
+			input = &isp->isp_csi2a.subdev.entity;
+			pad = CSI2_PAD_SINK;
+			flags = MEDIA_LNK_FL_IMMUTABLE
+			      | MEDIA_LNK_FL_ENABLED;
+			break;
+
+		case ISP_INTERFACE_CCP2B_PHY1:
+		case ISP_INTERFACE_CCP2B_PHY2:
+			input = &isp->isp_ccp2.subdev.entity;
+			pad = CCP2_PAD_SINK;
+			flags = 0;
+			break;
+
+		case ISP_INTERFACE_CSI2C_PHY1:
+			input = &isp->isp_csi2c.subdev.entity;
+			pad = CSI2_PAD_SINK;
+			flags = MEDIA_LNK_FL_IMMUTABLE
+			      | MEDIA_LNK_FL_ENABLED;
+			break;
+
+		default:
+			printk(KERN_ERR "%s: invalid interface type %u\n",
+			       __func__, subdevs->interface);
+			ret = -EINVAL;
+			goto done;
+		}
+
+		ret = media_entity_create_link(&sensor->entity, 0, input, pad,
+					       flags);
+		if (ret < 0)
+			goto done;
+	}
+
+	ret = v4l2_device_register_subdev_nodes(&isp->v4l2_dev);
+
+done:
+	if (ret < 0)
+		isp_unregister_entities(isp);
+
+	return ret;
+}
+
+static void isp_cleanup_modules(struct isp_device *isp)
+{
+	omap3isp_h3a_aewb_cleanup(isp);
+	omap3isp_h3a_af_cleanup(isp);
+	omap3isp_hist_cleanup(isp);
+	omap3isp_resizer_cleanup(isp);
+	omap3isp_preview_cleanup(isp);
+	omap3isp_ccdc_cleanup(isp);
+	omap3isp_ccp2_cleanup(isp);
+	omap3isp_csi2_cleanup(isp);
+}
+
+static int isp_initialize_modules(struct isp_device *isp)
+{
+	int ret;
+
+	ret = omap3isp_csiphy_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CSI PHY initialization failed\n");
+		goto error_csiphy;
+	}
+
+	ret = omap3isp_csi2_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CSI2 initialization failed\n");
+		goto error_csi2;
+	}
+
+	ret = omap3isp_ccp2_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCP2 initialization failed\n");
+		goto error_ccp2;
+	}
+
+	ret = omap3isp_ccdc_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "CCDC initialization failed\n");
+		goto error_ccdc;
+	}
+
+	ret = omap3isp_preview_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Preview initialization failed\n");
+		goto error_preview;
+	}
+
+	ret = omap3isp_resizer_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Resizer initialization failed\n");
+		goto error_resizer;
+	}
+
+	ret = omap3isp_hist_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "Histogram initialization failed\n");
+		goto error_hist;
+	}
+
+	ret = omap3isp_h3a_aewb_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "H3A AEWB initialization failed\n");
+		goto error_h3a_aewb;
+	}
+
+	ret = omap3isp_h3a_af_init(isp);
+	if (ret < 0) {
+		dev_err(isp->dev, "H3A AF initialization failed\n");
+		goto error_h3a_af;
+	}
+
+	/* Connect the submodules. */
+	ret = media_entity_create_link(
+			&isp->isp_csi2a.subdev.entity, CSI2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_ccp2.subdev.entity, CCP2_PAD_SOURCE,
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SINK, 0);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_prev.subdev.entity, PREV_PAD_SINK, 0);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_OF,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_prev.subdev.entity, PREV_PAD_SOURCE,
+			&isp->isp_res.subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_aewb.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_af.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		goto error_link;
+
+	ret = media_entity_create_link(
+			&isp->isp_ccdc.subdev.entity, CCDC_PAD_SOURCE_VP,
+			&isp->isp_hist.subdev.entity, 0,
+			MEDIA_LNK_FL_ENABLED | MEDIA_LNK_FL_IMMUTABLE);
+	if (ret < 0)
+		goto error_link;
+
+	return 0;
+
+error_link:
+	omap3isp_h3a_af_cleanup(isp);
+error_h3a_af:
+	omap3isp_h3a_aewb_cleanup(isp);
+error_h3a_aewb:
+	omap3isp_hist_cleanup(isp);
+error_hist:
+	omap3isp_resizer_cleanup(isp);
+error_resizer:
+	omap3isp_preview_cleanup(isp);
+error_preview:
+	omap3isp_ccdc_cleanup(isp);
+error_ccdc:
+	omap3isp_ccp2_cleanup(isp);
+error_ccp2:
+	omap3isp_csi2_cleanup(isp);
+error_csi2:
+error_csiphy:
+	return ret;
+}
+
+/*
+ * isp_remove - Remove ISP platform device
+ * @pdev: Pointer to ISP platform device
+ *
+ * Always returns 0.
+ */
+static int isp_remove(struct platform_device *pdev)
+{
+	struct isp_device *isp = platform_get_drvdata(pdev);
+	int i;
+
+	isp_unregister_entities(isp);
+	isp_cleanup_modules(isp);
+
+	omap3isp_get(isp);
+	iommu_put(isp->iommu);
+	omap3isp_put(isp);
+
+	free_irq(isp->irq_num, isp);
+	isp_put_clocks(isp);
+
+	for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
+		if (isp->mmio_base[i]) {
+			iounmap(isp->mmio_base[i]);
+			isp->mmio_base[i] = NULL;
+		}
+
+		if (isp->mmio_base_phys[i]) {
+			release_mem_region(isp->mmio_base_phys[i],
+					   isp->mmio_size[i]);
+			isp->mmio_base_phys[i] = 0;
+		}
+	}
+
+	regulator_put(isp->isp_csiphy1.vdd);
+	regulator_put(isp->isp_csiphy2.vdd);
+	kfree(isp);
+
+	return 0;
+}
+
+static int isp_map_mem_resource(struct platform_device *pdev,
+				struct isp_device *isp,
+				enum isp_mem_resources res)
+{
+	struct resource *mem;
+
+	/* request the mem region for the camera registers */
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
+	if (!mem) {
+		dev_err(isp->dev, "no mem resource?\n");
+		return -ENODEV;
+	}
+
+	if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
+		dev_err(isp->dev,
+			"cannot reserve camera register I/O region\n");
+		return -ENODEV;
+	}
+	isp->mmio_base_phys[res] = mem->start;
+	isp->mmio_size[res] = resource_size(mem);
+
+	/* map the region */
+	isp->mmio_base[res] = ioremap_nocache(isp->mmio_base_phys[res],
+					      isp->mmio_size[res]);
+	if (!isp->mmio_base[res]) {
+		dev_err(isp->dev, "cannot map camera register I/O region\n");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+/*
+ * isp_probe - Probe ISP platform device
+ * @pdev: Pointer to ISP platform device
+ *
+ * Returns 0 if successful,
+ *   -ENOMEM if no memory available,
+ *   -ENODEV if no platform device resources found
+ *     or no space for remapping registers,
+ *   -EINVAL if couldn't install ISR,
+ *   or clk_get return error value.
+ */
+static int isp_probe(struct platform_device *pdev)
+{
+	struct isp_platform_data *pdata = pdev->dev.platform_data;
+	struct isp_device *isp;
+	int ret;
+	int i, m;
+
+	if (pdata == NULL)
+		return -EINVAL;
+
+	isp = kzalloc(sizeof(*isp), GFP_KERNEL);
+	if (!isp) {
+		dev_err(&pdev->dev, "could not allocate memory\n");
+		return -ENOMEM;
+	}
+
+	isp->autoidle = autoidle;
+	isp->platform_cb.set_xclk = isp_set_xclk;
+	isp->platform_cb.set_pixel_clock = isp_set_pixel_clock;
+
+	mutex_init(&isp->isp_mutex);
+	spin_lock_init(&isp->stat_lock);
+
+	isp->dev = &pdev->dev;
+	isp->pdata = pdata;
+	isp->ref_count = 0;
+
+	isp->raw_dmamask = DMA_BIT_MASK(32);
+	isp->dev->dma_mask = &isp->raw_dmamask;
+	isp->dev->coherent_dma_mask = DMA_BIT_MASK(32);
+
+	platform_set_drvdata(pdev, isp);
+
+	/* Regulators */
+	isp->isp_csiphy1.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY1");
+	isp->isp_csiphy2.vdd = regulator_get(&pdev->dev, "VDD_CSIPHY2");
+
+	/* Clocks */
+	ret = isp_map_mem_resource(pdev, isp, OMAP3_ISP_IOMEM_MAIN);
+	if (ret < 0)
+		goto error;
+
+	ret = isp_get_clocks(isp);
+	if (ret < 0)
+		goto error;
+
+	if (omap3isp_get(isp) == NULL)
+		goto error;
+
+	ret = isp_reset(isp);
+	if (ret < 0)
+		goto error_isp;
+
+	/* Memory resources */
+	isp->revision = isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_REVISION);
+	dev_info(isp->dev, "Revision %d.%d found\n",
+		 (isp->revision & 0xf0) >> 4, isp->revision & 0x0f);
+
+	for (m = 0; m < ARRAY_SIZE(isp_res_maps); m++)
+		if (isp->revision == isp_res_maps[m].isp_rev)
+			break;
+
+	if (m == ARRAY_SIZE(isp_res_maps)) {
+		dev_err(isp->dev, "No resource map found for ISP rev %d.%d\n",
+			(isp->revision & 0xf0) >> 4, isp->revision & 0xf);
+		ret = -ENODEV;
+		goto error_isp;
+	}
+
+	for (i = 1; i < OMAP3_ISP_IOMEM_LAST; i++) {
+		if (isp_res_maps[m].map & 1 << i) {
+			ret = isp_map_mem_resource(pdev, isp, i);
+			if (ret)
+				goto error_isp;
+		}
+	}
+
+	/* IOMMU */
+	isp->iommu = iommu_get("isp");
+	if (IS_ERR_OR_NULL(isp->iommu)) {
+		isp->iommu = NULL;
+		ret = -ENODEV;
+		goto error_isp;
+	}
+
+	/* Interrupt */
+	isp->irq_num = platform_get_irq(pdev, 0);
+	if (isp->irq_num <= 0) {
+		dev_err(isp->dev, "No IRQ resource\n");
+		ret = -ENODEV;
+		goto error_isp;
+	}
+
+	if (request_irq(isp->irq_num, isp_isr, IRQF_SHARED, "OMAP3 ISP", isp)) {
+		dev_err(isp->dev, "Unable to request IRQ\n");
+		ret = -EINVAL;
+		goto error_isp;
+	}
+
+	/* Entities */
+	ret = isp_initialize_modules(isp);
+	if (ret < 0)
+		goto error_irq;
+
+	ret = isp_register_entities(isp);
+	if (ret < 0)
+		goto error_modules;
+
+	isp_power_settings(isp, 1);
+	omap3isp_put(isp);
+
+	return 0;
+
+error_modules:
+	isp_cleanup_modules(isp);
+error_irq:
+	free_irq(isp->irq_num, isp);
+error_isp:
+	iommu_put(isp->iommu);
+	omap3isp_put(isp);
+error:
+	isp_put_clocks(isp);
+
+	for (i = 0; i < OMAP3_ISP_IOMEM_LAST; i++) {
+		if (isp->mmio_base[i]) {
+			iounmap(isp->mmio_base[i]);
+			isp->mmio_base[i] = NULL;
+		}
+
+		if (isp->mmio_base_phys[i]) {
+			release_mem_region(isp->mmio_base_phys[i],
+					   isp->mmio_size[i]);
+			isp->mmio_base_phys[i] = 0;
+		}
+	}
+	regulator_put(isp->isp_csiphy2.vdd);
+	regulator_put(isp->isp_csiphy1.vdd);
+	platform_set_drvdata(pdev, NULL);
+	kfree(isp);
+
+	return ret;
+}
+
+static const struct dev_pm_ops omap3isp_pm_ops = {
+	.prepare = isp_pm_prepare,
+	.suspend = isp_pm_suspend,
+	.resume = isp_pm_resume,
+	.complete = isp_pm_complete,
+};
+
+static struct platform_device_id omap3isp_id_table[] = {
+	{ "omap3isp", 0 },
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, omap3isp_id_table);
+
+static struct platform_driver omap3isp_driver = {
+	.probe = isp_probe,
+	.remove = isp_remove,
+	.id_table = omap3isp_id_table,
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "omap3isp",
+		.pm	= &omap3isp_pm_ops,
+	},
+};
+
+/*
+ * isp_init - ISP module initialization.
+ */
+static int __init isp_init(void)
+{
+	return platform_driver_register(&omap3isp_driver);
+}
+
+/*
+ * isp_cleanup - ISP module cleanup.
+ */
+static void __exit isp_cleanup(void)
+{
+	platform_driver_unregister(&omap3isp_driver);
+}
+
+module_init(isp_init);
+module_exit(isp_cleanup);
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("TI OMAP3 ISP driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccdc.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccdc.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccdc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccdc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2291 @@
+/*
+ * ispccdc.c
+ *
+ * TI OMAP3 ISP - CCDC module
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/module.h>
+#include <linux/uaccess.h>
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <media/v4l2-event.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispccdc.h"
+
+static struct v4l2_mbus_framefmt *
+__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+		  unsigned int pad, enum v4l2_subdev_format_whence which);
+
+static const unsigned int ccdc_fmts[] = {
+	V4L2_MBUS_FMT_Y8_1X8,
+	V4L2_MBUS_FMT_Y10_1X10,
+	V4L2_MBUS_FMT_Y12_1X12,
+	V4L2_MBUS_FMT_SGRBG8_1X8,
+	V4L2_MBUS_FMT_SRGGB8_1X8,
+	V4L2_MBUS_FMT_SBGGR8_1X8,
+	V4L2_MBUS_FMT_SGBRG8_1X8,
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SRGGB10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_SGBRG10_1X10,
+	V4L2_MBUS_FMT_SGRBG12_1X12,
+	V4L2_MBUS_FMT_SRGGB12_1X12,
+	V4L2_MBUS_FMT_SBGGR12_1X12,
+	V4L2_MBUS_FMT_SGBRG12_1X12,
+};
+
+/*
+ * ccdc_print_status - Print current CCDC Module register values.
+ * @ccdc: Pointer to ISP CCDC device.
+ *
+ * Also prints other debug information stored in the CCDC module.
+ */
+#define CCDC_PRINT_REGISTER(isp, name)\
+	dev_dbg(isp->dev, "###CCDC " #name "=0x%08x\n", \
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_##name))
+
+static void ccdc_print_status(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	dev_dbg(isp->dev, "-------------CCDC Register dump-------------\n");
+
+	CCDC_PRINT_REGISTER(isp, PCR);
+	CCDC_PRINT_REGISTER(isp, SYN_MODE);
+	CCDC_PRINT_REGISTER(isp, HD_VD_WID);
+	CCDC_PRINT_REGISTER(isp, PIX_LINES);
+	CCDC_PRINT_REGISTER(isp, HORZ_INFO);
+	CCDC_PRINT_REGISTER(isp, VERT_START);
+	CCDC_PRINT_REGISTER(isp, VERT_LINES);
+	CCDC_PRINT_REGISTER(isp, CULLING);
+	CCDC_PRINT_REGISTER(isp, HSIZE_OFF);
+	CCDC_PRINT_REGISTER(isp, SDOFST);
+	CCDC_PRINT_REGISTER(isp, SDR_ADDR);
+	CCDC_PRINT_REGISTER(isp, CLAMP);
+	CCDC_PRINT_REGISTER(isp, DCSUB);
+	CCDC_PRINT_REGISTER(isp, COLPTN);
+	CCDC_PRINT_REGISTER(isp, BLKCMP);
+	CCDC_PRINT_REGISTER(isp, FPC);
+	CCDC_PRINT_REGISTER(isp, FPC_ADDR);
+	CCDC_PRINT_REGISTER(isp, VDINT);
+	CCDC_PRINT_REGISTER(isp, ALAW);
+	CCDC_PRINT_REGISTER(isp, REC656IF);
+	CCDC_PRINT_REGISTER(isp, CFG);
+	CCDC_PRINT_REGISTER(isp, FMTCFG);
+	CCDC_PRINT_REGISTER(isp, FMT_HORZ);
+	CCDC_PRINT_REGISTER(isp, FMT_VERT);
+	CCDC_PRINT_REGISTER(isp, PRGEVEN0);
+	CCDC_PRINT_REGISTER(isp, PRGEVEN1);
+	CCDC_PRINT_REGISTER(isp, PRGODD0);
+	CCDC_PRINT_REGISTER(isp, PRGODD1);
+	CCDC_PRINT_REGISTER(isp, VP_OUT);
+	CCDC_PRINT_REGISTER(isp, LSC_CONFIG);
+	CCDC_PRINT_REGISTER(isp, LSC_INITIAL);
+	CCDC_PRINT_REGISTER(isp, LSC_TABLE_BASE);
+	CCDC_PRINT_REGISTER(isp, LSC_TABLE_OFFSET);
+
+	dev_dbg(isp->dev, "--------------------------------------------\n");
+}
+
+/*
+ * omap3isp_ccdc_busy - Get busy state of the CCDC.
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+int omap3isp_ccdc_busy(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR) &
+		ISPCCDC_PCR_BUSY;
+}
+
+/* -----------------------------------------------------------------------------
+ * Lens Shading Compensation
+ */
+
+/*
+ * ccdc_lsc_validate_config - Check that LSC configuration is valid.
+ * @ccdc: Pointer to ISP CCDC device.
+ * @lsc_cfg: the LSC configuration to check.
+ *
+ * Returns 0 if the LSC configuration is valid, or -EINVAL if invalid.
+ */
+static int ccdc_lsc_validate_config(struct isp_ccdc_device *ccdc,
+				    struct omap3isp_ccdc_lsc_config *lsc_cfg)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	struct v4l2_mbus_framefmt *format;
+	unsigned int paxel_width, paxel_height;
+	unsigned int paxel_shift_x, paxel_shift_y;
+	unsigned int min_width, min_height, min_size;
+	unsigned int input_width, input_height;
+
+	paxel_shift_x = lsc_cfg->gain_mode_m;
+	paxel_shift_y = lsc_cfg->gain_mode_n;
+
+	if ((paxel_shift_x < 2) || (paxel_shift_x > 6) ||
+	    (paxel_shift_y < 2) || (paxel_shift_y > 6)) {
+		dev_dbg(isp->dev, "CCDC: LSC: Invalid paxel size\n");
+		return -EINVAL;
+	}
+
+	if (lsc_cfg->offset & 3) {
+		dev_dbg(isp->dev, "CCDC: LSC: Offset must be a multiple of "
+			"4\n");
+		return -EINVAL;
+	}
+
+	if ((lsc_cfg->initial_x & 1) || (lsc_cfg->initial_y & 1)) {
+		dev_dbg(isp->dev, "CCDC: LSC: initial_x and y must be even\n");
+		return -EINVAL;
+	}
+
+	format = __ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
+				   V4L2_SUBDEV_FORMAT_ACTIVE);
+	input_width = format->width;
+	input_height = format->height;
+
+	/* Calculate minimum bytesize for validation */
+	paxel_width = 1 << paxel_shift_x;
+	min_width = ((input_width + lsc_cfg->initial_x + paxel_width - 1)
+		     >> paxel_shift_x) + 1;
+
+	paxel_height = 1 << paxel_shift_y;
+	min_height = ((input_height + lsc_cfg->initial_y + paxel_height - 1)
+		     >> paxel_shift_y) + 1;
+
+	min_size = 4 * min_width * min_height;
+	if (min_size > lsc_cfg->size) {
+		dev_dbg(isp->dev, "CCDC: LSC: too small table\n");
+		return -EINVAL;
+	}
+	if (lsc_cfg->offset < (min_width * 4)) {
+		dev_dbg(isp->dev, "CCDC: LSC: Offset is too small\n");
+		return -EINVAL;
+	}
+	if ((lsc_cfg->size / lsc_cfg->offset) < min_height) {
+		dev_dbg(isp->dev, "CCDC: LSC: Wrong size/offset combination\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+
+/*
+ * ccdc_lsc_program_table - Program Lens Shading Compensation table address.
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_lsc_program_table(struct isp_ccdc_device *ccdc, u32 addr)
+{
+	isp_reg_writel(to_isp_device(ccdc), addr,
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_TABLE_BASE);
+}
+
+/*
+ * ccdc_lsc_setup_regs - Configures the lens shading compensation module
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_lsc_setup_regs(struct isp_ccdc_device *ccdc,
+				struct omap3isp_ccdc_lsc_config *cfg)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	int reg;
+
+	isp_reg_writel(isp, cfg->offset, OMAP3_ISP_IOMEM_CCDC,
+		       ISPCCDC_LSC_TABLE_OFFSET);
+
+	reg = 0;
+	reg |= cfg->gain_mode_n << ISPCCDC_LSC_GAIN_MODE_N_SHIFT;
+	reg |= cfg->gain_mode_m << ISPCCDC_LSC_GAIN_MODE_M_SHIFT;
+	reg |= cfg->gain_format << ISPCCDC_LSC_GAIN_FORMAT_SHIFT;
+	isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG);
+
+	reg = 0;
+	reg &= ~ISPCCDC_LSC_INITIAL_X_MASK;
+	reg |= cfg->initial_x << ISPCCDC_LSC_INITIAL_X_SHIFT;
+	reg &= ~ISPCCDC_LSC_INITIAL_Y_MASK;
+	reg |= cfg->initial_y << ISPCCDC_LSC_INITIAL_Y_SHIFT;
+	isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_CCDC,
+		       ISPCCDC_LSC_INITIAL);
+}
+
+static int ccdc_lsc_wait_prefetch(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	unsigned int wait;
+
+	isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
+		       OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+
+	/* timeout 1 ms */
+	for (wait = 0; wait < 1000; wait++) {
+		if (isp_reg_readl(isp, OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS) &
+				  IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ) {
+			isp_reg_writel(isp, IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ,
+				       OMAP3_ISP_IOMEM_MAIN, ISP_IRQ0STATUS);
+			return 0;
+		}
+
+		rmb();
+		udelay(1);
+	}
+
+	return -ETIMEDOUT;
+}
+
+/*
+ * __ccdc_lsc_enable - Enables/Disables the Lens Shading Compensation module.
+ * @ccdc: Pointer to ISP CCDC device.
+ * @enable: 0 Disables LSC, 1 Enables LSC.
+ */
+static int __ccdc_lsc_enable(struct isp_ccdc_device *ccdc, int enable)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	const struct v4l2_mbus_framefmt *format =
+		__ccdc_get_format(ccdc, NULL, CCDC_PAD_SINK,
+				  V4L2_SUBDEV_FORMAT_ACTIVE);
+
+	if ((format->code != V4L2_MBUS_FMT_SGRBG10_1X10) &&
+	    (format->code != V4L2_MBUS_FMT_SRGGB10_1X10) &&
+	    (format->code != V4L2_MBUS_FMT_SBGGR10_1X10) &&
+	    (format->code != V4L2_MBUS_FMT_SGBRG10_1X10))
+		return -EINVAL;
+
+	if (enable)
+		omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_LSC_READ);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
+			ISPCCDC_LSC_ENABLE, enable ? ISPCCDC_LSC_ENABLE : 0);
+
+	if (enable) {
+		if (ccdc_lsc_wait_prefetch(ccdc) < 0) {
+			isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC,
+				    ISPCCDC_LSC_CONFIG, ISPCCDC_LSC_ENABLE);
+			ccdc->lsc.state = LSC_STATE_STOPPED;
+			dev_warn(to_device(ccdc), "LSC prefecth timeout\n");
+			return -ETIMEDOUT;
+		}
+		ccdc->lsc.state = LSC_STATE_RUNNING;
+	} else {
+		ccdc->lsc.state = LSC_STATE_STOPPING;
+	}
+
+	return 0;
+}
+
+static int ccdc_lsc_busy(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	return isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG) &
+			     ISPCCDC_LSC_BUSY;
+}
+
+/* __ccdc_lsc_configure - Apply a new configuration to the LSC engine
+ * @ccdc: Pointer to ISP CCDC device
+ * @req: New configuration request
+ *
+ * context: in_interrupt()
+ */
+static int __ccdc_lsc_configure(struct isp_ccdc_device *ccdc,
+				struct ispccdc_lsc_config_req *req)
+{
+	if (!req->enable)
+		return -EINVAL;
+
+	if (ccdc_lsc_validate_config(ccdc, &req->config) < 0) {
+		dev_dbg(to_device(ccdc), "Discard LSC configuration\n");
+		return -EINVAL;
+	}
+
+	if (ccdc_lsc_busy(ccdc))
+		return -EBUSY;
+
+	ccdc_lsc_setup_regs(ccdc, &req->config);
+	ccdc_lsc_program_table(ccdc, req->table);
+	return 0;
+}
+
+/*
+ * ccdc_lsc_error_handler - Handle LSC prefetch error scenario.
+ * @ccdc: Pointer to ISP CCDC device.
+ *
+ * Disables LSC, and defers enablement to shadow registers update time.
+ */
+static void ccdc_lsc_error_handler(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	/*
+	 * From OMAP3 TRM: When this event is pending, the module
+	 * goes into transparent mode (output =input). Normal
+	 * operation can be resumed at the start of the next frame
+	 * after:
+	 *  1) Clearing this event
+	 *  2) Disabling the LSC module
+	 *  3) Enabling it
+	 */
+	isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_LSC_CONFIG,
+		    ISPCCDC_LSC_ENABLE);
+	ccdc->lsc.state = LSC_STATE_STOPPED;
+}
+
+static void ccdc_lsc_free_request(struct isp_ccdc_device *ccdc,
+				  struct ispccdc_lsc_config_req *req)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	if (req == NULL)
+		return;
+
+	if (req->iovm)
+		dma_unmap_sg(isp->dev, req->iovm->sgt->sgl,
+			     req->iovm->sgt->nents, DMA_TO_DEVICE);
+	if (req->table)
+		iommu_vfree(isp->iommu, req->table);
+	kfree(req);
+}
+
+static void ccdc_lsc_free_queue(struct isp_ccdc_device *ccdc,
+				struct list_head *queue)
+{
+	struct ispccdc_lsc_config_req *req, *n;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+	list_for_each_entry_safe(req, n, queue, list) {
+		list_del(&req->list);
+		spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+		ccdc_lsc_free_request(ccdc, req);
+		spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+	}
+	spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+}
+
+static void ccdc_lsc_free_table_work(struct work_struct *work)
+{
+	struct isp_ccdc_device *ccdc;
+	struct ispccdc_lsc *lsc;
+
+	lsc = container_of(work, struct ispccdc_lsc, table_work);
+	ccdc = container_of(lsc, struct isp_ccdc_device, lsc);
+
+	ccdc_lsc_free_queue(ccdc, &lsc->free_queue);
+}
+
+/*
+ * ccdc_lsc_config - Configure the LSC module from a userspace request
+ *
+ * Store the request LSC configuration in the LSC engine request pointer. The
+ * configuration will be applied to the hardware when the CCDC will be enabled,
+ * or at the next LSC interrupt if the CCDC is already running.
+ */
+static int ccdc_lsc_config(struct isp_ccdc_device *ccdc,
+			   struct omap3isp_ccdc_update_config *config)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	struct ispccdc_lsc_config_req *req;
+	unsigned long flags;
+	void *table;
+	u16 update;
+	int ret;
+
+	update = config->update &
+		 (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC);
+	if (!update)
+		return 0;
+
+	if (update != (OMAP3ISP_CCDC_CONFIG_LSC | OMAP3ISP_CCDC_TBL_LSC)) {
+		dev_dbg(to_device(ccdc), "%s: Both LSC configuration and table "
+			"need to be supplied\n", __func__);
+		return -EINVAL;
+	}
+
+	req = kzalloc(sizeof(*req), GFP_KERNEL);
+	if (req == NULL)
+		return -ENOMEM;
+
+	if (config->flag & OMAP3ISP_CCDC_CONFIG_LSC) {
+		if (copy_from_user(&req->config, config->lsc_cfg,
+				   sizeof(req->config))) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		req->enable = 1;
+
+		req->table = iommu_vmalloc(isp->iommu, 0, req->config.size,
+					   IOMMU_FLAG);
+		if (IS_ERR_VALUE(req->table)) {
+			req->table = 0;
+			ret = -ENOMEM;
+			goto done;
+		}
+
+		req->iovm = find_iovm_area(isp->iommu, req->table);
+		if (req->iovm == NULL) {
+			ret = -ENOMEM;
+			goto done;
+		}
+
+		if (!dma_map_sg(isp->dev, req->iovm->sgt->sgl,
+				req->iovm->sgt->nents, DMA_TO_DEVICE)) {
+			ret = -ENOMEM;
+			req->iovm = NULL;
+			goto done;
+		}
+
+		dma_sync_sg_for_cpu(isp->dev, req->iovm->sgt->sgl,
+				    req->iovm->sgt->nents, DMA_TO_DEVICE);
+
+		table = da_to_va(isp->iommu, req->table);
+		if (copy_from_user(table, config->lsc, req->config.size)) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		dma_sync_sg_for_device(isp->dev, req->iovm->sgt->sgl,
+				       req->iovm->sgt->nents, DMA_TO_DEVICE);
+	}
+
+	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+	if (ccdc->lsc.request) {
+		list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
+		schedule_work(&ccdc->lsc.table_work);
+	}
+	ccdc->lsc.request = req;
+	spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+
+	ret = 0;
+
+done:
+	if (ret < 0)
+		ccdc_lsc_free_request(ccdc, req);
+
+	return ret;
+}
+
+static inline int ccdc_lsc_is_configured(struct isp_ccdc_device *ccdc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+	if (ccdc->lsc.active) {
+		spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+		return 1;
+	}
+	spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+	return 0;
+}
+
+static int ccdc_lsc_enable(struct isp_ccdc_device *ccdc)
+{
+	struct ispccdc_lsc *lsc = &ccdc->lsc;
+
+	if (lsc->state != LSC_STATE_STOPPED)
+		return -EINVAL;
+
+	if (lsc->active) {
+		list_add_tail(&lsc->active->list, &lsc->free_queue);
+		lsc->active = NULL;
+	}
+
+	if (__ccdc_lsc_configure(ccdc, lsc->request) < 0) {
+		omap3isp_sbl_disable(to_isp_device(ccdc),
+				OMAP3_ISP_SBL_CCDC_LSC_READ);
+		list_add_tail(&lsc->request->list, &lsc->free_queue);
+		lsc->request = NULL;
+		goto done;
+	}
+
+	lsc->active = lsc->request;
+	lsc->request = NULL;
+	__ccdc_lsc_enable(ccdc, 1);
+
+done:
+	if (!list_empty(&lsc->free_queue))
+		schedule_work(&lsc->table_work);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * Parameters configuration
+ */
+
+/*
+ * ccdc_configure_clamp - Configure optical-black or digital clamping
+ * @ccdc: Pointer to ISP CCDC device.
+ *
+ * The CCDC performs either optical-black or digital clamp. Configure and enable
+ * the selected clamp method.
+ */
+static void ccdc_configure_clamp(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	u32 clamp;
+
+	if (ccdc->obclamp) {
+		clamp  = ccdc->clamp.obgain << ISPCCDC_CLAMP_OBGAIN_SHIFT;
+		clamp |= ccdc->clamp.oblen << ISPCCDC_CLAMP_OBSLEN_SHIFT;
+		clamp |= ccdc->clamp.oblines << ISPCCDC_CLAMP_OBSLN_SHIFT;
+		clamp |= ccdc->clamp.obstpixel << ISPCCDC_CLAMP_OBST_SHIFT;
+		isp_reg_writel(isp, clamp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP);
+	} else {
+		isp_reg_writel(isp, ccdc->clamp.dcsubval,
+			       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_DCSUB);
+	}
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CLAMP,
+			ISPCCDC_CLAMP_CLAMPEN,
+			ccdc->obclamp ? ISPCCDC_CLAMP_CLAMPEN : 0);
+}
+
+/*
+ * ccdc_configure_fpc - Configure Faulty Pixel Correction
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_configure_fpc(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC, ISPCCDC_FPC_FPCEN);
+
+	if (!ccdc->fpc_en)
+		return;
+
+	isp_reg_writel(isp, ccdc->fpc.fpcaddr, OMAP3_ISP_IOMEM_CCDC,
+		       ISPCCDC_FPC_ADDR);
+	/* The FPNUM field must be set before enabling FPC. */
+	isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT),
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
+	isp_reg_writel(isp, (ccdc->fpc.fpnum << ISPCCDC_FPC_FPNUM_SHIFT) |
+		       ISPCCDC_FPC_FPCEN, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FPC);
+}
+
+/*
+ * ccdc_configure_black_comp - Configure Black Level Compensation.
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_configure_black_comp(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	u32 blcomp;
+
+	blcomp  = ccdc->blcomp.b_mg << ISPCCDC_BLKCMP_B_MG_SHIFT;
+	blcomp |= ccdc->blcomp.gb_g << ISPCCDC_BLKCMP_GB_G_SHIFT;
+	blcomp |= ccdc->blcomp.gr_cy << ISPCCDC_BLKCMP_GR_CY_SHIFT;
+	blcomp |= ccdc->blcomp.r_ye << ISPCCDC_BLKCMP_R_YE_SHIFT;
+
+	isp_reg_writel(isp, blcomp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_BLKCMP);
+}
+
+/*
+ * ccdc_configure_lpf - Configure Low-Pass Filter (LPF).
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE,
+			ISPCCDC_SYN_MODE_LPF,
+			ccdc->lpf ? ISPCCDC_SYN_MODE_LPF : 0);
+}
+
+/*
+ * ccdc_configure_alaw - Configure A-law compression.
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	u32 alaw = 0;
+
+	switch (ccdc->syncif.datsz) {
+	case 8:
+		return;
+
+	case 10:
+		alaw = ISPCCDC_ALAW_GWDI_9_0;
+		break;
+	case 11:
+		alaw = ISPCCDC_ALAW_GWDI_10_1;
+		break;
+	case 12:
+		alaw = ISPCCDC_ALAW_GWDI_11_2;
+		break;
+	case 13:
+		alaw = ISPCCDC_ALAW_GWDI_12_3;
+		break;
+	}
+
+	if (ccdc->alaw)
+		alaw |= ISPCCDC_ALAW_CCDTBL;
+
+	isp_reg_writel(isp, alaw, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_ALAW);
+}
+
+/*
+ * ccdc_config_imgattr - Configure sensor image specific attributes.
+ * @ccdc: Pointer to ISP CCDC device.
+ * @colptn: Color pattern of the sensor.
+ */
+static void ccdc_config_imgattr(struct isp_ccdc_device *ccdc, u32 colptn)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_writel(isp, colptn, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_COLPTN);
+}
+
+/*
+ * ccdc_config - Set CCDC configuration from userspace
+ * @ccdc: Pointer to ISP CCDC device.
+ * @userspace_add: Structure containing CCDC configuration sent from userspace.
+ *
+ * Returns 0 if successful, -EINVAL if the pointer to the configuration
+ * structure is null, or the copy_from_user function fails to copy user space
+ * memory to kernel space memory.
+ */
+static int ccdc_config(struct isp_ccdc_device *ccdc,
+		       struct omap3isp_ccdc_update_config *ccdc_struct)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&ccdc->lock, flags);
+	ccdc->shadow_update = 1;
+	spin_unlock_irqrestore(&ccdc->lock, flags);
+
+	if (OMAP3ISP_CCDC_ALAW & ccdc_struct->update) {
+		ccdc->alaw = !!(OMAP3ISP_CCDC_ALAW & ccdc_struct->flag);
+		ccdc->update |= OMAP3ISP_CCDC_ALAW;
+	}
+
+	if (OMAP3ISP_CCDC_LPF & ccdc_struct->update) {
+		ccdc->lpf = !!(OMAP3ISP_CCDC_LPF & ccdc_struct->flag);
+		ccdc->update |= OMAP3ISP_CCDC_LPF;
+	}
+
+	if (OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->update) {
+		if (copy_from_user(&ccdc->clamp, ccdc_struct->bclamp,
+				   sizeof(ccdc->clamp))) {
+			ccdc->shadow_update = 0;
+			return -EFAULT;
+		}
+
+		ccdc->obclamp = !!(OMAP3ISP_CCDC_BLCLAMP & ccdc_struct->flag);
+		ccdc->update |= OMAP3ISP_CCDC_BLCLAMP;
+	}
+
+	if (OMAP3ISP_CCDC_BCOMP & ccdc_struct->update) {
+		if (copy_from_user(&ccdc->blcomp, ccdc_struct->blcomp,
+				   sizeof(ccdc->blcomp))) {
+			ccdc->shadow_update = 0;
+			return -EFAULT;
+		}
+
+		ccdc->update |= OMAP3ISP_CCDC_BCOMP;
+	}
+
+	ccdc->shadow_update = 0;
+
+	if (OMAP3ISP_CCDC_FPC & ccdc_struct->update) {
+		u32 table_old = 0;
+		u32 table_new;
+		u32 size;
+
+		if (ccdc->state != ISP_PIPELINE_STREAM_STOPPED)
+			return -EBUSY;
+
+		ccdc->fpc_en = !!(OMAP3ISP_CCDC_FPC & ccdc_struct->flag);
+
+		if (ccdc->fpc_en) {
+			if (copy_from_user(&ccdc->fpc, ccdc_struct->fpc,
+					   sizeof(ccdc->fpc)))
+				return -EFAULT;
+
+			/*
+			 * table_new must be 64-bytes aligned, but it's
+			 * already done by iommu_vmalloc().
+			 */
+			size = ccdc->fpc.fpnum * 4;
+			table_new = iommu_vmalloc(isp->iommu, 0, size,
+						  IOMMU_FLAG);
+			if (IS_ERR_VALUE(table_new))
+				return -ENOMEM;
+
+			if (copy_from_user(da_to_va(isp->iommu, table_new),
+					   (__force void __user *)
+					   ccdc->fpc.fpcaddr, size)) {
+				iommu_vfree(isp->iommu, table_new);
+				return -EFAULT;
+			}
+
+			table_old = ccdc->fpc.fpcaddr;
+			ccdc->fpc.fpcaddr = table_new;
+		}
+
+		ccdc_configure_fpc(ccdc);
+		if (table_old != 0)
+			iommu_vfree(isp->iommu, table_old);
+	}
+
+	return ccdc_lsc_config(ccdc, ccdc_struct);
+}
+
+static void ccdc_apply_controls(struct isp_ccdc_device *ccdc)
+{
+	if (ccdc->update & OMAP3ISP_CCDC_ALAW) {
+		ccdc_configure_alaw(ccdc);
+		ccdc->update &= ~OMAP3ISP_CCDC_ALAW;
+	}
+
+	if (ccdc->update & OMAP3ISP_CCDC_LPF) {
+		ccdc_configure_lpf(ccdc);
+		ccdc->update &= ~OMAP3ISP_CCDC_LPF;
+	}
+
+	if (ccdc->update & OMAP3ISP_CCDC_BLCLAMP) {
+		ccdc_configure_clamp(ccdc);
+		ccdc->update &= ~OMAP3ISP_CCDC_BLCLAMP;
+	}
+
+	if (ccdc->update & OMAP3ISP_CCDC_BCOMP) {
+		ccdc_configure_black_comp(ccdc);
+		ccdc->update &= ~OMAP3ISP_CCDC_BCOMP;
+	}
+}
+
+/*
+ * omap3isp_ccdc_restore_context - Restore values of the CCDC module registers
+ * @dev: Pointer to ISP device
+ */
+void omap3isp_ccdc_restore_context(struct isp_device *isp)
+{
+	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG, ISPCCDC_CFG_VDLC);
+
+	ccdc->update = OMAP3ISP_CCDC_ALAW | OMAP3ISP_CCDC_LPF
+		     | OMAP3ISP_CCDC_BLCLAMP | OMAP3ISP_CCDC_BCOMP;
+	ccdc_apply_controls(ccdc);
+	ccdc_configure_fpc(ccdc);
+}
+
+/* -----------------------------------------------------------------------------
+ * Format- and pipeline-related configuration helpers
+ */
+
+/*
+ * ccdc_config_vp - Configure the Video Port.
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+	struct isp_device *isp = to_isp_device(ccdc);
+	unsigned long l3_ick = pipe->l3_ick;
+	unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
+	unsigned int div = 0;
+	u32 fmtcfg_vp;
+
+	fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
+		  & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
+
+	switch (ccdc->syncif.datsz) {
+	case 8:
+	case 10:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
+		break;
+	case 11:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_10_1;
+		break;
+	case 12:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_11_2;
+		break;
+	case 13:
+		fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
+		break;
+	};
+
+	if (pipe->input)
+		div = DIV_ROUND_UP(l3_ick, pipe->max_rate);
+	else if (ccdc->vpcfg.pixelclk)
+		div = l3_ick / ccdc->vpcfg.pixelclk;
+
+	div = clamp(div, 2U, max_div);
+	fmtcfg_vp |= (div - 2) << ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT;
+
+	isp_reg_writel(isp, fmtcfg_vp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG);
+}
+
+/*
+ * ccdc_enable_vp - Enable Video Port.
+ * @ccdc: Pointer to ISP CCDC device.
+ * @enable: 0 Disables VP, 1 Enables VP
+ *
+ * This is needed for outputting image to Preview, H3A and HIST ISP submodules.
+ */
+static void ccdc_enable_vp(struct isp_ccdc_device *ccdc, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG,
+			ISPCCDC_FMTCFG_VPEN, enable ? ISPCCDC_FMTCFG_VPEN : 0);
+}
+
+/*
+ * ccdc_config_outlineoffset - Configure memory saving output line offset
+ * @ccdc: Pointer to ISP CCDC device.
+ * @offset: Address offset to start a new line. Must be twice the
+ *          Output width and aligned on 32 byte boundary
+ * @oddeven: Specifies the odd/even line pattern to be chosen to store the
+ *           output.
+ * @numlines: Set the value 0-3 for +1-4lines, 4-7 for -1-4lines.
+ *
+ * - Configures the output line offset when stored in memory
+ * - Sets the odd/even line pattern to store the output
+ *    (EVENEVEN (1), ODDEVEN (2), EVENODD (3), ODDODD (4))
+ * - Configures the number of even and odd line fields in case of rearranging
+ * the lines.
+ */
+static void ccdc_config_outlineoffset(struct isp_ccdc_device *ccdc,
+					u32 offset, u8 oddeven, u8 numlines)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_writel(isp, offset & 0xffff,
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HSIZE_OFF);
+
+	isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+		    ISPCCDC_SDOFST_FINV);
+
+	isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+		    ISPCCDC_SDOFST_FOFST_4L);
+
+	switch (oddeven) {
+	case EVENEVEN:
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			    (numlines & 0x7) << ISPCCDC_SDOFST_LOFST0_SHIFT);
+		break;
+	case ODDEVEN:
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			    (numlines & 0x7) << ISPCCDC_SDOFST_LOFST1_SHIFT);
+		break;
+	case EVENODD:
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			    (numlines & 0x7) << ISPCCDC_SDOFST_LOFST2_SHIFT);
+		break;
+	case ODDODD:
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDOFST,
+			    (numlines & 0x7) << ISPCCDC_SDOFST_LOFST3_SHIFT);
+		break;
+	default:
+		break;
+	}
+}
+
+/*
+ * ccdc_set_outaddr - Set memory address to save output image
+ * @ccdc: Pointer to ISP CCDC device.
+ * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
+ *
+ * Sets the memory address where the output will be saved.
+ */
+static void ccdc_set_outaddr(struct isp_ccdc_device *ccdc, u32 addr)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SDR_ADDR);
+}
+
+/*
+ * omap3isp_ccdc_max_rate - Calculate maximum input data rate based on the input
+ * @ccdc: Pointer to ISP CCDC device.
+ * @max_rate: Maximum calculated data rate.
+ *
+ * Returns in *max_rate less value between calculated and passed
+ */
+void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
+			    unsigned int *max_rate)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+	unsigned int rate;
+
+	if (pipe == NULL)
+		return;
+
+	/*
+	 * TRM says that for parallel sensors the maximum data rate
+	 * should be 90% form L3/2 clock, otherwise just L3/2.
+	 */
+	if (ccdc->input == CCDC_INPUT_PARALLEL)
+		rate = pipe->l3_ick / 2 * 9 / 10;
+	else
+		rate = pipe->l3_ick / 2;
+
+	*max_rate = min(*max_rate, rate);
+}
+
+/*
+ * ccdc_config_sync_if - Set CCDC sync interface configuration
+ * @ccdc: Pointer to ISP CCDC device.
+ * @syncif: Structure containing the sync parameters like field state, CCDC in
+ *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
+ *          signals.
+ */
+static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
+				struct ispccdc_syncif *syncif)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	u32 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC,
+				     ISPCCDC_SYN_MODE);
+
+	syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
+
+	if (syncif->fldstat)
+		syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
+
+	syn_mode &= ~ISPCCDC_SYN_MODE_DATSIZ_MASK;
+	switch (syncif->datsz) {
+	case 8:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
+		break;
+	case 10:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_10;
+		break;
+	case 11:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_11;
+		break;
+	case 12:
+		syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
+		break;
+	};
+
+	if (syncif->fldmode)
+		syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
+
+	if (syncif->datapol)
+		syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
+
+	if (syncif->fldpol)
+		syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
+
+	if (syncif->hdpol)
+		syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
+
+	if (syncif->vdpol)
+		syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
+
+	if (syncif->ccdc_mastermode) {
+		syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
+		isp_reg_writel(isp,
+			       syncif->hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
+			     | syncif->vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
+			       OMAP3_ISP_IOMEM_CCDC,
+			       ISPCCDC_HD_VD_WID);
+
+		isp_reg_writel(isp,
+			       syncif->ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
+			     | syncif->hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
+			       OMAP3_ISP_IOMEM_CCDC,
+			       ISPCCDC_PIX_LINES);
+	} else
+		syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
+			      ISPCCDC_SYN_MODE_VDHDOUT);
+
+	isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	if (!syncif->bt_r656_en)
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
+			    ISPCCDC_REC656IF_R656ON);
+}
+
+/* CCDC formats descriptions */
+static const u32 ccdc_sgrbg_pattern =
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
+
+static const u32 ccdc_srggb_pattern =
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
+
+static const u32 ccdc_sbggr_pattern =
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
+
+static const u32 ccdc_sgbrg_pattern =
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC0_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP0PLC2_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP0PLC3_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC1_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP1PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP1PLC3_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC0_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC1_SHIFT |
+	ISPCCDC_COLPTN_Gb_G  << ISPCCDC_COLPTN_CP2PLC2_SHIFT |
+	ISPCCDC_COLPTN_B_Mg  << ISPCCDC_COLPTN_CP2PLC3_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC0_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC1_SHIFT |
+	ISPCCDC_COLPTN_R_Ye  << ISPCCDC_COLPTN_CP3PLC2_SHIFT |
+	ISPCCDC_COLPTN_Gr_Cy << ISPCCDC_COLPTN_CP3PLC3_SHIFT;
+
+static void ccdc_configure(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+	struct isp_parallel_platform_data *pdata = NULL;
+	struct v4l2_subdev *sensor;
+	struct v4l2_mbus_framefmt *format;
+	const struct isp_format_info *fmt_info;
+	struct v4l2_subdev_format fmt_src;
+	unsigned int depth_out;
+	unsigned int depth_in = 0;
+	struct media_pad *pad;
+	unsigned long flags;
+	unsigned int shift;
+	u32 syn_mode;
+	u32 ccdc_pattern;
+
+	pad = media_entity_remote_source(&ccdc->pads[CCDC_PAD_SINK]);
+	sensor = media_entity_to_v4l2_subdev(pad->entity);
+	if (ccdc->input == CCDC_INPUT_PARALLEL)
+		pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
+			->bus.parallel;
+
+	/* Compute shift value for lane shifter to configure the bridge. */
+	fmt_src.pad = pad->index;
+	fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
+		fmt_info = omap3isp_video_format_info(fmt_src.format.code);
+		depth_in = fmt_info->bpp;
+	}
+
+	fmt_info = omap3isp_video_format_info
+		(isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
+	depth_out = fmt_info->bpp;
+
+	shift = depth_in - depth_out;
+	omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
+
+	ccdc->syncif.datsz = depth_out;
+	ccdc_config_sync_if(ccdc, &ccdc->syncif);
+
+	/* CCDC_PAD_SINK */
+	format = &ccdc->formats[CCDC_PAD_SINK];
+
+	syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	/* Use the raw, unprocessed data when writing to memory. The H3A and
+	 * histogram modules are still fed with lens shading corrected data.
+	 */
+	syn_mode &= ~ISPCCDC_SYN_MODE_VP2SDR;
+
+	if (ccdc->output & CCDC_OUTPUT_MEMORY)
+		syn_mode |= ISPCCDC_SYN_MODE_WEN;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_WEN;
+
+	if (ccdc->output & CCDC_OUTPUT_RESIZER)
+		syn_mode |= ISPCCDC_SYN_MODE_SDR2RSZ;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
+
+	/* Use PACK8 mode for 1byte per pixel formats. */
+	if (omap3isp_video_format_info(format->code)->bpp <= 8)
+		syn_mode |= ISPCCDC_SYN_MODE_PACK8;
+	else
+		syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
+
+	isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
+	/* Mosaic filter */
+	switch (format->code) {
+	case V4L2_MBUS_FMT_SRGGB10_1X10:
+	case V4L2_MBUS_FMT_SRGGB12_1X12:
+		ccdc_pattern = ccdc_srggb_pattern;
+		break;
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SBGGR12_1X12:
+		ccdc_pattern = ccdc_sbggr_pattern;
+		break;
+	case V4L2_MBUS_FMT_SGBRG10_1X10:
+	case V4L2_MBUS_FMT_SGBRG12_1X12:
+		ccdc_pattern = ccdc_sgbrg_pattern;
+		break;
+	default:
+		/* Use GRBG */
+		ccdc_pattern = ccdc_sgrbg_pattern;
+		break;
+	}
+	ccdc_config_imgattr(ccdc, ccdc_pattern);
+
+	/* Generate VD0 on the last line of the image and VD1 on the
+	 * 2/3 height line.
+	 */
+	isp_reg_writel(isp, ((format->height - 2) << ISPCCDC_VDINT_0_SHIFT) |
+		       ((format->height * 2 / 3) << ISPCCDC_VDINT_1_SHIFT),
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT);
+
+	/* CCDC_PAD_SOURCE_OF */
+	format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
+
+	isp_reg_writel(isp, (0 << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
+		       ((format->width - 1) << ISPCCDC_HORZ_INFO_NPH_SHIFT),
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_HORZ_INFO);
+	isp_reg_writel(isp, 0 << ISPCCDC_VERT_START_SLV0_SHIFT,
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_START);
+	isp_reg_writel(isp, (format->height - 1)
+			<< ISPCCDC_VERT_LINES_NLV_SHIFT,
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VERT_LINES);
+
+	ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
+
+	/* CCDC_PAD_SOURCE_VP */
+	format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
+
+	isp_reg_writel(isp, (0 << ISPCCDC_FMT_HORZ_FMTSPH_SHIFT) |
+		       (format->width << ISPCCDC_FMT_HORZ_FMTLNH_SHIFT),
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_HORZ);
+	isp_reg_writel(isp, (0 << ISPCCDC_FMT_VERT_FMTSLV_SHIFT) |
+		       ((format->height + 1) << ISPCCDC_FMT_VERT_FMTLNV_SHIFT),
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMT_VERT);
+
+	isp_reg_writel(isp, (format->width << ISPCCDC_VP_OUT_HORZ_NUM_SHIFT) |
+		       (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
+		       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
+
+	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+	if (ccdc->lsc.request == NULL)
+		goto unlock;
+
+	WARN_ON(ccdc->lsc.active);
+
+	/* Get last good LSC configuration. If it is not supported for
+	 * the current active resolution discard it.
+	 */
+	if (ccdc->lsc.active == NULL &&
+	    __ccdc_lsc_configure(ccdc, ccdc->lsc.request) == 0) {
+		ccdc->lsc.active = ccdc->lsc.request;
+	} else {
+		list_add_tail(&ccdc->lsc.request->list, &ccdc->lsc.free_queue);
+		schedule_work(&ccdc->lsc.table_work);
+	}
+
+	ccdc->lsc.request = NULL;
+
+unlock:
+	spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+
+	ccdc_apply_controls(ccdc);
+}
+
+static void __ccdc_enable(struct isp_ccdc_device *ccdc, int enable)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_PCR,
+			ISPCCDC_PCR_EN, enable ? ISPCCDC_PCR_EN : 0);
+}
+
+static int ccdc_disable(struct isp_ccdc_device *ccdc)
+{
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&ccdc->lock, flags);
+	if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS)
+		ccdc->stopping = CCDC_STOP_REQUEST;
+	spin_unlock_irqrestore(&ccdc->lock, flags);
+
+	ret = wait_event_timeout(ccdc->wait,
+				 ccdc->stopping == CCDC_STOP_FINISHED,
+				 msecs_to_jiffies(2000));
+	if (ret == 0) {
+		ret = -ETIMEDOUT;
+		dev_warn(to_device(ccdc), "CCDC stop timeout!\n");
+	}
+
+	omap3isp_sbl_disable(to_isp_device(ccdc), OMAP3_ISP_SBL_CCDC_LSC_READ);
+
+	mutex_lock(&ccdc->ioctl_lock);
+	ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
+	ccdc->lsc.request = ccdc->lsc.active;
+	ccdc->lsc.active = NULL;
+	cancel_work_sync(&ccdc->lsc.table_work);
+	ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
+	mutex_unlock(&ccdc->ioctl_lock);
+
+	ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
+
+	return ret > 0 ? 0 : ret;
+}
+
+static void ccdc_enable(struct isp_ccdc_device *ccdc)
+{
+	if (ccdc_lsc_is_configured(ccdc))
+		__ccdc_lsc_enable(ccdc, 1);
+	__ccdc_enable(ccdc, 1);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+/*
+ * ccdc_sbl_busy - Poll idle state of CCDC and related SBL memory write bits
+ * @ccdc: Pointer to ISP CCDC device.
+ *
+ * Returns zero if the CCDC is idle and the image has been written to
+ * memory, too.
+ */
+static int ccdc_sbl_busy(struct isp_ccdc_device *ccdc)
+{
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	return omap3isp_ccdc_busy(ccdc)
+		| (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_0) &
+		   ISPSBL_CCDC_WR_0_DATA_READY)
+		| (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_1) &
+		   ISPSBL_CCDC_WR_0_DATA_READY)
+		| (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_2) &
+		   ISPSBL_CCDC_WR_0_DATA_READY)
+		| (isp_reg_readl(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_CCDC_WR_3) &
+		   ISPSBL_CCDC_WR_0_DATA_READY);
+}
+
+/*
+ * ccdc_sbl_wait_idle - Wait until the CCDC and related SBL are idle
+ * @ccdc: Pointer to ISP CCDC device.
+ * @max_wait: Max retry count in us for wait for idle/busy transition.
+ */
+static int ccdc_sbl_wait_idle(struct isp_ccdc_device *ccdc,
+			      unsigned int max_wait)
+{
+	unsigned int wait = 0;
+
+	if (max_wait == 0)
+		max_wait = 10000; /* 10 ms */
+
+	for (wait = 0; wait <= max_wait; wait++) {
+		if (!ccdc_sbl_busy(ccdc))
+			return 0;
+
+		rmb();
+		udelay(1);
+	}
+
+	return -EBUSY;
+}
+
+/* __ccdc_handle_stopping - Handle CCDC and/or LSC stopping sequence
+ * @ccdc: Pointer to ISP CCDC device.
+ * @event: Pointing which event trigger handler
+ *
+ * Return 1 when the event and stopping request combination is satisfied,
+ * zero otherwise.
+ */
+static int __ccdc_handle_stopping(struct isp_ccdc_device *ccdc, u32 event)
+{
+	int rval = 0;
+
+	switch ((ccdc->stopping & 3) | event) {
+	case CCDC_STOP_REQUEST | CCDC_EVENT_VD1:
+		if (ccdc->lsc.state != LSC_STATE_STOPPED)
+			__ccdc_lsc_enable(ccdc, 0);
+		__ccdc_enable(ccdc, 0);
+		ccdc->stopping = CCDC_STOP_EXECUTED;
+		return 1;
+
+	case CCDC_STOP_EXECUTED | CCDC_EVENT_VD0:
+		ccdc->stopping |= CCDC_STOP_CCDC_FINISHED;
+		if (ccdc->lsc.state == LSC_STATE_STOPPED)
+			ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
+		rval = 1;
+		break;
+
+	case CCDC_STOP_EXECUTED | CCDC_EVENT_LSC_DONE:
+		ccdc->stopping |= CCDC_STOP_LSC_FINISHED;
+		rval = 1;
+		break;
+
+	case CCDC_STOP_EXECUTED | CCDC_EVENT_VD1:
+		return 1;
+	}
+
+	if (ccdc->stopping == CCDC_STOP_FINISHED) {
+		wake_up(&ccdc->wait);
+		rval = 1;
+	}
+
+	return rval;
+}
+
+static void ccdc_hs_vs_isr(struct isp_ccdc_device *ccdc)
+{
+	struct video_device *vdev = &ccdc->subdev.devnode;
+	struct v4l2_event event;
+
+	memset(&event, 0, sizeof(event));
+	event.type = V4L2_EVENT_OMAP3ISP_HS_VS;
+
+	v4l2_event_queue(vdev, &event);
+}
+
+/*
+ * ccdc_lsc_isr - Handle LSC events
+ * @ccdc: Pointer to ISP CCDC device.
+ * @events: LSC events
+ */
+static void ccdc_lsc_isr(struct isp_ccdc_device *ccdc, u32 events)
+{
+	unsigned long flags;
+
+	if (events & IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ) {
+		ccdc_lsc_error_handler(ccdc);
+		ccdc->error = 1;
+		dev_dbg(to_device(ccdc), "lsc prefetch error\n");
+	}
+
+	if (!(events & IRQ0STATUS_CCDC_LSC_DONE_IRQ))
+		return;
+
+	/* LSC_DONE interrupt occur, there are two cases
+	 * 1. stopping for reconfiguration
+	 * 2. stopping because of STREAM OFF command
+	 */
+	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+
+	if (ccdc->lsc.state == LSC_STATE_STOPPING)
+		ccdc->lsc.state = LSC_STATE_STOPPED;
+
+	if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_LSC_DONE))
+		goto done;
+
+	if (ccdc->lsc.state != LSC_STATE_RECONFIG)
+		goto done;
+
+	/* LSC is in STOPPING state, change to the new state */
+	ccdc->lsc.state = LSC_STATE_STOPPED;
+
+	/* This is an exception. Start of frame and LSC_DONE interrupt
+	 * have been received on the same time. Skip this event and wait
+	 * for better times.
+	 */
+	if (events & IRQ0STATUS_HS_VS_IRQ)
+		goto done;
+
+	/* The LSC engine is stopped at this point. Enable it if there's a
+	 * pending request.
+	 */
+	if (ccdc->lsc.request == NULL)
+		goto done;
+
+	ccdc_lsc_enable(ccdc);
+
+done:
+	spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+}
+
+static int ccdc_isr_buffer(struct isp_ccdc_device *ccdc)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
+	struct isp_device *isp = to_isp_device(ccdc);
+	struct isp_buffer *buffer;
+	int restart = 0;
+
+	/* The CCDC generates VD0 interrupts even when disabled (the datasheet
+	 * doesn't explicitly state if that's supposed to happen or not, so it
+	 * can be considered as a hardware bug or as a feature, but we have to
+	 * deal with it anyway). Disabling the CCDC when no buffer is available
+	 * would thus not be enough, we need to handle the situation explicitly.
+	 */
+	if (list_empty(&ccdc->video_out.dmaqueue))
+		goto done;
+
+	/* We're in continuous mode, and memory writes were disabled due to a
+	 * buffer underrun. Reenable them now that we have a buffer. The buffer
+	 * address has been set in ccdc_video_queue.
+	 */
+	if (ccdc->state == ISP_PIPELINE_STREAM_CONTINUOUS && ccdc->underrun) {
+		restart = 1;
+		ccdc->underrun = 0;
+		goto done;
+	}
+
+	if (ccdc_sbl_wait_idle(ccdc, 1000)) {
+		dev_info(isp->dev, "CCDC won't become idle!\n");
+		goto done;
+	}
+
+	buffer = omap3isp_video_buffer_next(&ccdc->video_out, ccdc->error);
+	if (buffer != NULL) {
+		ccdc_set_outaddr(ccdc, buffer->isp_addr);
+		restart = 1;
+	}
+
+	pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
+
+	if (ccdc->state == ISP_PIPELINE_STREAM_SINGLESHOT &&
+	    isp_pipeline_ready(pipe))
+		omap3isp_pipeline_set_stream(pipe,
+					ISP_PIPELINE_STREAM_SINGLESHOT);
+
+done:
+	ccdc->error = 0;
+	return restart;
+}
+
+/*
+ * ccdc_vd0_isr - Handle VD0 event
+ * @ccdc: Pointer to ISP CCDC device.
+ *
+ * Executes LSC deferred enablement before next frame starts.
+ */
+static void ccdc_vd0_isr(struct isp_ccdc_device *ccdc)
+{
+	unsigned long flags;
+	int restart = 0;
+
+	if (ccdc->output & CCDC_OUTPUT_MEMORY)
+		restart = ccdc_isr_buffer(ccdc);
+
+	spin_lock_irqsave(&ccdc->lock, flags);
+	if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD0)) {
+		spin_unlock_irqrestore(&ccdc->lock, flags);
+		return;
+	}
+
+	if (!ccdc->shadow_update)
+		ccdc_apply_controls(ccdc);
+	spin_unlock_irqrestore(&ccdc->lock, flags);
+
+	if (restart)
+		ccdc_enable(ccdc);
+}
+
+/*
+ * ccdc_vd1_isr - Handle VD1 event
+ * @ccdc: Pointer to ISP CCDC device.
+ */
+static void ccdc_vd1_isr(struct isp_ccdc_device *ccdc)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
+
+	/*
+	 * Depending on the CCDC pipeline state, CCDC stopping should be
+	 * handled differently. In SINGLESHOT we emulate an internal CCDC
+	 * stopping because the CCDC hw works only in continuous mode.
+	 * When CONTINUOUS pipeline state is used and the CCDC writes it's
+	 * data to memory the CCDC and LSC are stopped immediately but
+	 * without change the CCDC stopping state machine. The CCDC
+	 * stopping state machine should be used only when user request
+	 * for stopping is received (SINGLESHOT is an exeption).
+	 */
+	switch (ccdc->state) {
+	case ISP_PIPELINE_STREAM_SINGLESHOT:
+		ccdc->stopping = CCDC_STOP_REQUEST;
+		break;
+
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		if (ccdc->output & CCDC_OUTPUT_MEMORY) {
+			if (ccdc->lsc.state != LSC_STATE_STOPPED)
+				__ccdc_lsc_enable(ccdc, 0);
+			__ccdc_enable(ccdc, 0);
+		}
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+		break;
+	}
+
+	if (__ccdc_handle_stopping(ccdc, CCDC_EVENT_VD1))
+		goto done;
+
+	if (ccdc->lsc.request == NULL)
+		goto done;
+
+	/*
+	 * LSC need to be reconfigured. Stop it here and on next LSC_DONE IRQ
+	 * do the appropriate changes in registers
+	 */
+	if (ccdc->lsc.state == LSC_STATE_RUNNING) {
+		__ccdc_lsc_enable(ccdc, 0);
+		ccdc->lsc.state = LSC_STATE_RECONFIG;
+		goto done;
+	}
+
+	/* LSC has been in STOPPED state, enable it */
+	if (ccdc->lsc.state == LSC_STATE_STOPPED)
+		ccdc_lsc_enable(ccdc);
+
+done:
+	spin_unlock_irqrestore(&ccdc->lsc.req_lock, flags);
+}
+
+/*
+ * omap3isp_ccdc_isr - Configure CCDC during interframe time.
+ * @ccdc: Pointer to ISP CCDC device.
+ * @events: CCDC events
+ */
+int omap3isp_ccdc_isr(struct isp_ccdc_device *ccdc, u32 events)
+{
+	if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED)
+		return 0;
+
+	if (events & IRQ0STATUS_CCDC_VD1_IRQ)
+		ccdc_vd1_isr(ccdc);
+
+	ccdc_lsc_isr(ccdc, events);
+
+	if (events & IRQ0STATUS_CCDC_VD0_IRQ)
+		ccdc_vd0_isr(ccdc);
+
+	if (events & IRQ0STATUS_HS_VS_IRQ)
+		ccdc_hs_vs_isr(ccdc);
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP video operations
+ */
+
+static int ccdc_video_queue(struct isp_video *video, struct isp_buffer *buffer)
+{
+	struct isp_ccdc_device *ccdc = &video->isp->isp_ccdc;
+
+	if (!(ccdc->output & CCDC_OUTPUT_MEMORY))
+		return -ENODEV;
+
+	ccdc_set_outaddr(ccdc, buffer->isp_addr);
+
+	/* We now have a buffer queued on the output, restart the pipeline
+	 * on the next CCDC interrupt if running in continuous mode (or when
+	 * starting the stream).
+	 */
+	ccdc->underrun = 1;
+
+	return 0;
+}
+
+static const struct isp_video_operations ccdc_video_ops = {
+	.queue = ccdc_video_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+/*
+ * ccdc_ioctl - CCDC module private ioctl's
+ * @sd: ISP CCDC V4L2 subdevice
+ * @cmd: ioctl command
+ * @arg: ioctl argument
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	int ret;
+
+	switch (cmd) {
+	case VIDIOC_OMAP3ISP_CCDC_CFG:
+		mutex_lock(&ccdc->ioctl_lock);
+		ret = ccdc_config(ccdc, arg);
+		mutex_unlock(&ccdc->ioctl_lock);
+		break;
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+
+	return ret;
+}
+
+static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				struct v4l2_event_subscription *sub)
+{
+	if (sub->type != V4L2_EVENT_OMAP3ISP_HS_VS)
+		return -EINVAL;
+
+	return v4l2_event_subscribe(fh, sub);
+}
+
+static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
+				  struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
+/*
+ * ccdc_set_stream - Enable/Disable streaming on the CCDC module
+ * @sd: ISP CCDC V4L2 subdevice
+ * @enable: Enable/disable stream
+ *
+ * When writing to memory, the CCDC hardware can't be enabled without a memory
+ * buffer to write to. As the s_stream operation is called in response to a
+ * STREAMON call without any buffer queued yet, just update the enabled field
+ * and return immediately. The CCDC will be enabled in ccdc_isr_buffer().
+ *
+ * When not writing to memory enable the CCDC immediately.
+ */
+static int ccdc_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct isp_device *isp = to_isp_device(ccdc);
+	int ret = 0;
+
+	if (ccdc->state == ISP_PIPELINE_STREAM_STOPPED) {
+		if (enable == ISP_PIPELINE_STREAM_STOPPED)
+			return 0;
+
+		omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_CCDC);
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+			    ISPCCDC_CFG_VDLC);
+
+		ccdc_configure(ccdc);
+
+		/* TODO: Don't configure the video port if all of its output
+		 * links are inactive.
+		 */
+		ccdc_config_vp(ccdc);
+		ccdc_enable_vp(ccdc, 1);
+		ccdc->error = 0;
+		ccdc_print_status(ccdc);
+	}
+
+	switch (enable) {
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		if (ccdc->output & CCDC_OUTPUT_MEMORY)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
+
+		if (ccdc->underrun || !(ccdc->output & CCDC_OUTPUT_MEMORY))
+			ccdc_enable(ccdc);
+
+		ccdc->underrun = 0;
+		break;
+
+	case ISP_PIPELINE_STREAM_SINGLESHOT:
+		if (ccdc->output & CCDC_OUTPUT_MEMORY &&
+		    ccdc->state != ISP_PIPELINE_STREAM_SINGLESHOT)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
+
+		ccdc_enable(ccdc);
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+		ret = ccdc_disable(ccdc);
+		if (ccdc->output & CCDC_OUTPUT_MEMORY)
+			omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CCDC_WRITE);
+		omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_CCDC);
+		ccdc->underrun = 0;
+		break;
+	}
+
+	ccdc->state = enable;
+	return ret;
+}
+
+static struct v4l2_mbus_framefmt *
+__ccdc_get_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+		  unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_format(fh, pad);
+	else
+		return &ccdc->formats[pad];
+}
+
+/*
+ * ccdc_try_format - Try video format on a pad
+ * @ccdc: ISP CCDC device
+ * @fh : V4L2 subdev file handle
+ * @pad: Pad number
+ * @fmt: Format
+ */
+static void
+ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
+		unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+		enum v4l2_subdev_format_whence which)
+{
+	struct v4l2_mbus_framefmt *format;
+	const struct isp_format_info *info;
+	unsigned int width = fmt->width;
+	unsigned int height = fmt->height;
+	unsigned int i;
+
+	switch (pad) {
+	case CCDC_PAD_SINK:
+		/* TODO: If the CCDC output formatter pad is connected directly
+		 * to the resizer, only YUV formats can be used.
+		 */
+		for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) {
+			if (fmt->code == ccdc_fmts[i])
+				break;
+		}
+
+		/* If not found, use SGRBG10 as default */
+		if (i >= ARRAY_SIZE(ccdc_fmts))
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+		/* Clamp the input size. */
+		fmt->width = clamp_t(u32, width, 32, 4096);
+		fmt->height = clamp_t(u32, height, 32, 4096);
+		break;
+
+	case CCDC_PAD_SOURCE_OF:
+		format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
+		memcpy(fmt, format, sizeof(*fmt));
+
+		/* The data formatter truncates the number of horizontal output
+		 * pixels to a multiple of 16. To avoid clipping data, allow
+		 * callers to request an output size bigger than the input size
+		 * up to the nearest multiple of 16.
+		 */
+		fmt->width = clamp_t(u32, width, 32, (fmt->width + 15) & ~15);
+		fmt->width &= ~15;
+		fmt->height = clamp_t(u32, height, 32, fmt->height);
+		break;
+
+	case CCDC_PAD_SOURCE_VP:
+		format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
+		memcpy(fmt, format, sizeof(*fmt));
+
+		/* The video port interface truncates the data to 10 bits. */
+		info = omap3isp_video_format_info(fmt->code);
+		fmt->code = info->truncated;
+
+		/* The number of lines that can be clocked out from the video
+		 * port output must be at least one line less than the number
+		 * of input lines.
+		 */
+		fmt->width = clamp_t(u32, width, 32, fmt->width);
+		fmt->height = clamp_t(u32, height, 32, fmt->height - 1);
+		break;
+	}
+
+	/* Data is written to memory unpacked, each 10-bit or 12-bit pixel is
+	 * stored on 2 bytes.
+	 */
+	fmt->colorspace = V4L2_COLORSPACE_SRGB;
+	fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * ccdc_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_fh *fh,
+			       struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	switch (code->pad) {
+	case CCDC_PAD_SINK:
+		if (code->index >= ARRAY_SIZE(ccdc_fmts))
+			return -EINVAL;
+
+		code->code = ccdc_fmts[code->index];
+		break;
+
+	case CCDC_PAD_SOURCE_OF:
+	case CCDC_PAD_SOURCE_VP:
+		/* No format conversion inside CCDC */
+		if (code->index != 0)
+			return -EINVAL;
+
+		format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK,
+					   V4L2_SUBDEV_FORMAT_TRY);
+
+		code->code = format->code;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int ccdc_enum_frame_size(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt format;
+
+	if (fse->index != 0)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = 1;
+	format.height = 1;
+	ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->min_width = format.width;
+	fse->min_height = format.height;
+
+	if (format.code != fse->code)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = -1;
+	format.height = -1;
+	ccdc_try_format(ccdc, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->max_width = format.width;
+	fse->max_height = format.height;
+
+	return 0;
+}
+
+/*
+ * ccdc_get_format - Retrieve the video format on a pad
+ * @sd : ISP CCDC V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ccdc_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+/*
+ * ccdc_set_format - Set the video format on a pad
+ * @sd : ISP CCDC V4L2 subdevice
+ * @fh : V4L2 subdev file handle
+ * @fmt: Format
+ *
+ * Return 0 on success or -EINVAL if the pad is invalid or doesn't correspond
+ * to the format type.
+ */
+static int ccdc_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __ccdc_get_format(ccdc, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	ccdc_try_format(ccdc, fh, fmt->pad, &fmt->format, fmt->which);
+	*format = fmt->format;
+
+	/* Propagate the format from sink to source */
+	if (fmt->pad == CCDC_PAD_SINK) {
+		format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_OF,
+					   fmt->which);
+		*format = fmt->format;
+		ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_OF, format,
+				fmt->which);
+
+		format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SOURCE_VP,
+					   fmt->which);
+		*format = fmt->format;
+		ccdc_try_format(ccdc, fh, CCDC_PAD_SOURCE_VP, format,
+				fmt->which);
+	}
+
+	return 0;
+}
+
+/*
+ * ccdc_init_formats - Initialize formats on all pads
+ * @sd: ISP CCDC V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int ccdc_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_subdev_format format;
+
+	memset(&format, 0, sizeof(format));
+	format.pad = CCDC_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format.format.width = 4096;
+	format.format.height = 4096;
+	ccdc_set_format(sd, fh, &format);
+
+	return 0;
+}
+
+/* V4L2 subdev core operations */
+static const struct v4l2_subdev_core_ops ccdc_v4l2_core_ops = {
+	.ioctl = ccdc_ioctl,
+	.subscribe_event = ccdc_subscribe_event,
+	.unsubscribe_event = ccdc_unsubscribe_event,
+};
+
+/* V4L2 subdev video operations */
+static const struct v4l2_subdev_video_ops ccdc_v4l2_video_ops = {
+	.s_stream = ccdc_set_stream,
+};
+
+/* V4L2 subdev pad operations */
+static const struct v4l2_subdev_pad_ops ccdc_v4l2_pad_ops = {
+	.enum_mbus_code = ccdc_enum_mbus_code,
+	.enum_frame_size = ccdc_enum_frame_size,
+	.get_fmt = ccdc_get_format,
+	.set_fmt = ccdc_set_format,
+};
+
+/* V4L2 subdev operations */
+static const struct v4l2_subdev_ops ccdc_v4l2_ops = {
+	.core = &ccdc_v4l2_core_ops,
+	.video = &ccdc_v4l2_video_ops,
+	.pad = &ccdc_v4l2_pad_ops,
+};
+
+/* V4L2 subdev internal operations */
+static const struct v4l2_subdev_internal_ops ccdc_v4l2_internal_ops = {
+	.open = ccdc_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * ccdc_link_setup - Setup CCDC connections
+ * @entity: CCDC media entity
+ * @local: Pad at the local end of the link
+ * @remote: Pad at the remote end of the link
+ * @flags: Link flags
+ *
+ * return -EINVAL or zero on success
+ */
+static int ccdc_link_setup(struct media_entity *entity,
+			   const struct media_pad *local,
+			   const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct isp_ccdc_device *ccdc = v4l2_get_subdevdata(sd);
+	struct isp_device *isp = to_isp_device(ccdc);
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case CCDC_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* Read from the sensor (parallel interface), CCP2, CSI2a or
+		 * CSI2c.
+		 */
+		if (!(flags & MEDIA_LNK_FL_ENABLED)) {
+			ccdc->input = CCDC_INPUT_NONE;
+			break;
+		}
+
+		if (ccdc->input != CCDC_INPUT_NONE)
+			return -EBUSY;
+
+		if (remote->entity == &isp->isp_ccp2.subdev.entity)
+			ccdc->input = CCDC_INPUT_CCP2B;
+		else if (remote->entity == &isp->isp_csi2a.subdev.entity)
+			ccdc->input = CCDC_INPUT_CSI2A;
+		else if (remote->entity == &isp->isp_csi2c.subdev.entity)
+			ccdc->input = CCDC_INPUT_CSI2C;
+		else
+			ccdc->input = CCDC_INPUT_PARALLEL;
+
+		break;
+
+	/*
+	 * The ISP core doesn't support pipelines with multiple video outputs.
+	 * Revisit this when it will be implemented, and return -EBUSY for now.
+	 */
+
+	case CCDC_PAD_SOURCE_VP | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* Write to preview engine, histogram and H3A. When none of
+		 * those links are active, the video port can be disabled.
+		 */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (ccdc->output & ~CCDC_OUTPUT_PREVIEW)
+				return -EBUSY;
+			ccdc->output |= CCDC_OUTPUT_PREVIEW;
+		} else {
+			ccdc->output &= ~CCDC_OUTPUT_PREVIEW;
+		}
+		break;
+
+	case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_DEVNODE:
+		/* Write to memory */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (ccdc->output & ~CCDC_OUTPUT_MEMORY)
+				return -EBUSY;
+			ccdc->output |= CCDC_OUTPUT_MEMORY;
+		} else {
+			ccdc->output &= ~CCDC_OUTPUT_MEMORY;
+		}
+		break;
+
+	case CCDC_PAD_SOURCE_OF | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* Write to resizer */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (ccdc->output & ~CCDC_OUTPUT_RESIZER)
+				return -EBUSY;
+			ccdc->output |= CCDC_OUTPUT_RESIZER;
+		} else {
+			ccdc->output &= ~CCDC_OUTPUT_RESIZER;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations ccdc_media_ops = {
+	.link_setup = ccdc_link_setup,
+};
+
+/*
+ * ccdc_init_entities - Initialize V4L2 subdev and media entity
+ * @ccdc: ISP CCDC module
+ *
+ * Return 0 on success and a negative error code on failure.
+ */
+static int ccdc_init_entities(struct isp_ccdc_device *ccdc)
+{
+	struct v4l2_subdev *sd = &ccdc->subdev;
+	struct media_pad *pads = ccdc->pads;
+	struct media_entity *me = &sd->entity;
+	int ret;
+
+	ccdc->input = CCDC_INPUT_NONE;
+
+	v4l2_subdev_init(sd, &ccdc_v4l2_ops);
+	sd->internal_ops = &ccdc_v4l2_internal_ops;
+	strlcpy(sd->name, "OMAP3 ISP CCDC", sizeof(sd->name));
+	sd->grp_id = 1 << 16;	/* group ID for isp subdevs */
+	v4l2_set_subdevdata(sd, ccdc);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sd->nevents = OMAP3ISP_CCDC_NEVENTS;
+
+	pads[CCDC_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	pads[CCDC_PAD_SOURCE_VP].flags = MEDIA_PAD_FL_SOURCE;
+	pads[CCDC_PAD_SOURCE_OF].flags = MEDIA_PAD_FL_SOURCE;
+
+	me->ops = &ccdc_media_ops;
+	ret = media_entity_init(me, CCDC_PADS_NUM, pads, 0);
+	if (ret < 0)
+		return ret;
+
+	ccdc_init_formats(sd, NULL);
+
+	ccdc->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	ccdc->video_out.ops = &ccdc_video_ops;
+	ccdc->video_out.isp = to_isp_device(ccdc);
+	ccdc->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
+	ccdc->video_out.bpl_alignment = 32;
+
+	ret = omap3isp_video_init(&ccdc->video_out, "CCDC");
+	if (ret < 0)
+		return ret;
+
+	/* Connect the CCDC subdev to the video node. */
+	ret = media_entity_create_link(&ccdc->subdev.entity, CCDC_PAD_SOURCE_OF,
+			&ccdc->video_out.video.entity, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc)
+{
+	media_entity_cleanup(&ccdc->subdev.entity);
+
+	v4l2_device_unregister_subdev(&ccdc->subdev);
+	omap3isp_video_unregister(&ccdc->video_out);
+}
+
+int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
+	struct v4l2_device *vdev)
+{
+	int ret;
+
+	/* Register the subdev and video node. */
+	ret = v4l2_device_register_subdev(vdev, &ccdc->subdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&ccdc->video_out, vdev);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+error:
+	omap3isp_ccdc_unregister_entities(ccdc);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP CCDC initialisation and cleanup
+ */
+
+/*
+ * omap3isp_ccdc_init - CCDC module initialization.
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ *
+ * TODO: Get the initialisation values from platform data.
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+int omap3isp_ccdc_init(struct isp_device *isp)
+{
+	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+
+	spin_lock_init(&ccdc->lock);
+	init_waitqueue_head(&ccdc->wait);
+	mutex_init(&ccdc->ioctl_lock);
+
+	ccdc->stopping = CCDC_STOP_NOT_REQUESTED;
+
+	INIT_WORK(&ccdc->lsc.table_work, ccdc_lsc_free_table_work);
+	ccdc->lsc.state = LSC_STATE_STOPPED;
+	INIT_LIST_HEAD(&ccdc->lsc.free_queue);
+	spin_lock_init(&ccdc->lsc.req_lock);
+
+	ccdc->syncif.ccdc_mastermode = 0;
+	ccdc->syncif.datapol = 0;
+	ccdc->syncif.datsz = 0;
+	ccdc->syncif.fldmode = 0;
+	ccdc->syncif.fldout = 0;
+	ccdc->syncif.fldpol = 0;
+	ccdc->syncif.fldstat = 0;
+	ccdc->syncif.hdpol = 0;
+	ccdc->syncif.vdpol = 0;
+
+	ccdc->clamp.oblen = 0;
+	ccdc->clamp.dcsubval = 0;
+
+	ccdc->vpcfg.pixelclk = 0;
+
+	ccdc->update = OMAP3ISP_CCDC_BLCLAMP;
+	ccdc_apply_controls(ccdc);
+
+	return ccdc_init_entities(ccdc);
+}
+
+/*
+ * omap3isp_ccdc_cleanup - CCDC module cleanup.
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ */
+void omap3isp_ccdc_cleanup(struct isp_device *isp)
+{
+	struct isp_ccdc_device *ccdc = &isp->isp_ccdc;
+
+	/* Free LSC requests. As the CCDC is stopped there's no active request,
+	 * so only the pending request and the free queue need to be handled.
+	 */
+	ccdc_lsc_free_request(ccdc, ccdc->lsc.request);
+	cancel_work_sync(&ccdc->lsc.table_work);
+	ccdc_lsc_free_queue(ccdc, &ccdc->lsc.free_queue);
+
+	if (ccdc->fpc.fpcaddr != 0)
+		iommu_vfree(isp->iommu, ccdc->fpc.fpcaddr);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccdc.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccdc.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccdc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccdc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,219 @@
+/*
+ * ispccdc.h
+ *
+ * TI OMAP3 ISP - CCDC module
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_CCDC_H
+#define OMAP3_ISP_CCDC_H
+
+#include <linux/omap3isp.h>
+#include <linux/workqueue.h>
+
+#include "ispvideo.h"
+
+enum ccdc_input_entity {
+	CCDC_INPUT_NONE,
+	CCDC_INPUT_PARALLEL,
+	CCDC_INPUT_CSI2A,
+	CCDC_INPUT_CCP2B,
+	CCDC_INPUT_CSI2C
+};
+
+#define CCDC_OUTPUT_MEMORY	(1 << 0)
+#define CCDC_OUTPUT_PREVIEW	(1 << 1)
+#define CCDC_OUTPUT_RESIZER	(1 << 2)
+
+#define	OMAP3ISP_CCDC_NEVENTS	16
+
+/*
+ * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
+ * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
+ * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
+ * @datsz: Data size.
+ * @fldmode: 0 - Progressive, 1 - Interlaced.
+ * @datapol: 0 - Positive, 1 - Negative.
+ * @fldpol: 0 - Positive, 1 - Negative.
+ * @hdpol: 0 - Positive, 1 - Negative.
+ * @vdpol: 0 - Positive, 1 - Negative.
+ * @fldout: 0 - Input, 1 - Output.
+ * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
+ * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
+ * @ppln: Number of pixels per line, used for HS/VS Output.
+ * @hlprf: Number of half lines per frame, used for HS/VS Output.
+ * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
+ */
+struct ispccdc_syncif {
+	u8 ccdc_mastermode;
+	u8 fldstat;
+	u8 datsz;
+	u8 fldmode;
+	u8 datapol;
+	u8 fldpol;
+	u8 hdpol;
+	u8 vdpol;
+	u8 fldout;
+	u8 hs_width;
+	u8 vs_width;
+	u8 ppln;
+	u8 hlprf;
+	u8 bt_r656_en;
+};
+
+/*
+ * struct ispccdc_vp - Structure for Video Port parameters
+ * @pixelclk: Input pixel clock in Hz
+ */
+struct ispccdc_vp {
+	unsigned int pixelclk;
+};
+
+enum ispccdc_lsc_state {
+	LSC_STATE_STOPPED = 0,
+	LSC_STATE_STOPPING = 1,
+	LSC_STATE_RUNNING = 2,
+	LSC_STATE_RECONFIG = 3,
+};
+
+struct ispccdc_lsc_config_req {
+	struct list_head list;
+	struct omap3isp_ccdc_lsc_config config;
+	unsigned char enable;
+	u32 table;
+	struct iovm_struct *iovm;
+};
+
+/*
+ * ispccdc_lsc - CCDC LSC parameters
+ * @update_config: Set when user changes config
+ * @request_enable: Whether LSC is requested to be enabled
+ * @config: LSC config set by user
+ * @update_table: Set when user provides a new LSC table to table_new
+ * @table_new: LSC table set by user, ISP address
+ * @table_inuse: LSC table currently in use, ISP address
+ */
+struct ispccdc_lsc {
+	enum ispccdc_lsc_state state;
+	struct work_struct table_work;
+
+	/* LSC queue of configurations */
+	spinlock_t req_lock;
+	struct ispccdc_lsc_config_req *request;	/* requested configuration */
+	struct ispccdc_lsc_config_req *active;	/* active configuration */
+	struct list_head free_queue;	/* configurations for freeing */
+};
+
+#define CCDC_STOP_NOT_REQUESTED		0x00
+#define CCDC_STOP_REQUEST		0x01
+#define CCDC_STOP_EXECUTED		(0x02 | CCDC_STOP_REQUEST)
+#define CCDC_STOP_CCDC_FINISHED		0x04
+#define CCDC_STOP_LSC_FINISHED		0x08
+#define CCDC_STOP_FINISHED		\
+	(CCDC_STOP_EXECUTED | CCDC_STOP_CCDC_FINISHED | CCDC_STOP_LSC_FINISHED)
+
+#define CCDC_EVENT_VD1			0x10
+#define CCDC_EVENT_VD0			0x20
+#define CCDC_EVENT_LSC_DONE		0x40
+
+/* Sink and source CCDC pads */
+#define CCDC_PAD_SINK			0
+#define CCDC_PAD_SOURCE_OF		1
+#define CCDC_PAD_SOURCE_VP		2
+#define CCDC_PADS_NUM			3
+
+/*
+ * struct isp_ccdc_device - Structure for the CCDC module to store its own
+ *			    information
+ * @subdev: V4L2 subdevice
+ * @pads: Sink and source media entity pads
+ * @formats: Active video formats
+ * @input: Active input
+ * @output: Active outputs
+ * @video_out: Output video node
+ * @error: A hardware error occurred during capture
+ * @alaw: A-law compression enabled (1) or disabled (0)
+ * @lpf: Low pass filter enabled (1) or disabled (0)
+ * @obclamp: Optical-black clamp enabled (1) or disabled (0)
+ * @fpc_en: Faulty pixels correction enabled (1) or disabled (0)
+ * @blcomp: Black level compensation configuration
+ * @clamp: Optical-black or digital clamp configuration
+ * @fpc: Faulty pixels correction configuration
+ * @lsc: Lens shading compensation configuration
+ * @update: Bitmask of controls to update during the next interrupt
+ * @shadow_update: Controls update in progress by userspace
+ * @syncif: Interface synchronization configuration
+ * @vpcfg: Video port configuration
+ * @underrun: A buffer underrun occurred and a new buffer has been queued
+ * @state: Streaming state
+ * @lock: Serializes shadow_update with interrupt handler
+ * @wait: Wait queue used to stop the module
+ * @stopping: Stopping state
+ * @ioctl_lock: Serializes ioctl calls and LSC requests freeing
+ */
+struct isp_ccdc_device {
+	struct v4l2_subdev subdev;
+	struct media_pad pads[CCDC_PADS_NUM];
+	struct v4l2_mbus_framefmt formats[CCDC_PADS_NUM];
+
+	enum ccdc_input_entity input;
+	unsigned int output;
+	struct isp_video video_out;
+	unsigned int error;
+
+	unsigned int alaw:1,
+		     lpf:1,
+		     obclamp:1,
+		     fpc_en:1;
+	struct omap3isp_ccdc_blcomp blcomp;
+	struct omap3isp_ccdc_bclamp clamp;
+	struct omap3isp_ccdc_fpc fpc;
+	struct ispccdc_lsc lsc;
+	unsigned int update;
+	unsigned int shadow_update;
+
+	struct ispccdc_syncif syncif;
+	struct ispccdc_vp vpcfg;
+
+	unsigned int underrun:1;
+	enum isp_pipeline_stream_state state;
+	spinlock_t lock;
+	wait_queue_head_t wait;
+	unsigned int stopping;
+	struct mutex ioctl_lock;
+};
+
+struct isp_device;
+
+int omap3isp_ccdc_init(struct isp_device *isp);
+void omap3isp_ccdc_cleanup(struct isp_device *isp);
+int omap3isp_ccdc_register_entities(struct isp_ccdc_device *ccdc,
+	struct v4l2_device *vdev);
+void omap3isp_ccdc_unregister_entities(struct isp_ccdc_device *ccdc);
+
+int omap3isp_ccdc_busy(struct isp_ccdc_device *isp_ccdc);
+int omap3isp_ccdc_isr(struct isp_ccdc_device *isp_ccdc, u32 events);
+void omap3isp_ccdc_restore_context(struct isp_device *isp);
+void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
+	unsigned int *max_rate);
+
+#endif	/* OMAP3_ISP_CCDC_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccp2.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccp2.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccp2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccp2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1173 @@
+/*
+ * ispccp2.c
+ *
+ * TI OMAP3 ISP - CCP2 module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispccp2.h"
+
+/* Number of LCX channels */
+#define CCP2_LCx_CHANS_NUM			3
+/* Max/Min size for CCP2 video port */
+#define ISPCCP2_DAT_START_MIN			0
+#define ISPCCP2_DAT_START_MAX			4095
+#define ISPCCP2_DAT_SIZE_MIN			0
+#define ISPCCP2_DAT_SIZE_MAX			4095
+#define ISPCCP2_VPCLK_FRACDIV			65536
+#define ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP	0x12
+#define ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP	0x16
+/* Max/Min size for CCP2 memory channel */
+#define ISPCCP2_LCM_HSIZE_COUNT_MIN		16
+#define ISPCCP2_LCM_HSIZE_COUNT_MAX		8191
+#define ISPCCP2_LCM_HSIZE_SKIP_MIN		0
+#define ISPCCP2_LCM_HSIZE_SKIP_MAX		8191
+#define ISPCCP2_LCM_VSIZE_MIN			1
+#define ISPCCP2_LCM_VSIZE_MAX			8191
+#define ISPCCP2_LCM_HWORDS_MIN			1
+#define ISPCCP2_LCM_HWORDS_MAX			4095
+#define ISPCCP2_LCM_CTRL_BURST_SIZE_32X		5
+#define ISPCCP2_LCM_CTRL_READ_THROTTLE_FULL	0
+#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10	2
+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8	2
+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10	3
+#define ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10	3
+#define ISPCCP2_LCM_CTRL_DST_PORT_VP		0
+#define ISPCCP2_LCM_CTRL_DST_PORT_MEM		1
+
+/* Set only the required bits */
+#define BIT_SET(var, shift, mask, val)			\
+	do {						\
+		var = ((var) & ~((mask) << (shift)))	\
+			| ((val) << (shift));		\
+	} while (0)
+
+/*
+ * ccp2_print_status - Print current CCP2 module register values.
+ */
+#define CCP2_PRINT_REGISTER(isp, name)\
+	dev_dbg(isp->dev, "###CCP2 " #name "=0x%08x\n", \
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_##name))
+
+static void ccp2_print_status(struct isp_ccp2_device *ccp2)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+
+	dev_dbg(isp->dev, "-------------CCP2 Register dump-------------\n");
+
+	CCP2_PRINT_REGISTER(isp, SYSCONFIG);
+	CCP2_PRINT_REGISTER(isp, SYSSTATUS);
+	CCP2_PRINT_REGISTER(isp, LC01_IRQENABLE);
+	CCP2_PRINT_REGISTER(isp, LC01_IRQSTATUS);
+	CCP2_PRINT_REGISTER(isp, LC23_IRQENABLE);
+	CCP2_PRINT_REGISTER(isp, LC23_IRQSTATUS);
+	CCP2_PRINT_REGISTER(isp, LCM_IRQENABLE);
+	CCP2_PRINT_REGISTER(isp, LCM_IRQSTATUS);
+	CCP2_PRINT_REGISTER(isp, CTRL);
+	CCP2_PRINT_REGISTER(isp, LCx_CTRL(0));
+	CCP2_PRINT_REGISTER(isp, LCx_CODE(0));
+	CCP2_PRINT_REGISTER(isp, LCx_STAT_START(0));
+	CCP2_PRINT_REGISTER(isp, LCx_STAT_SIZE(0));
+	CCP2_PRINT_REGISTER(isp, LCx_SOF_ADDR(0));
+	CCP2_PRINT_REGISTER(isp, LCx_EOF_ADDR(0));
+	CCP2_PRINT_REGISTER(isp, LCx_DAT_START(0));
+	CCP2_PRINT_REGISTER(isp, LCx_DAT_SIZE(0));
+	CCP2_PRINT_REGISTER(isp, LCx_DAT_PING_ADDR(0));
+	CCP2_PRINT_REGISTER(isp, LCx_DAT_PONG_ADDR(0));
+	CCP2_PRINT_REGISTER(isp, LCx_DAT_OFST(0));
+	CCP2_PRINT_REGISTER(isp, LCM_CTRL);
+	CCP2_PRINT_REGISTER(isp, LCM_VSIZE);
+	CCP2_PRINT_REGISTER(isp, LCM_HSIZE);
+	CCP2_PRINT_REGISTER(isp, LCM_PREFETCH);
+	CCP2_PRINT_REGISTER(isp, LCM_SRC_ADDR);
+	CCP2_PRINT_REGISTER(isp, LCM_SRC_OFST);
+	CCP2_PRINT_REGISTER(isp, LCM_DST_ADDR);
+	CCP2_PRINT_REGISTER(isp, LCM_DST_OFST);
+
+	dev_dbg(isp->dev, "--------------------------------------------\n");
+}
+
+/*
+ * ccp2_reset - Reset the CCP2
+ * @ccp2: pointer to ISP CCP2 device
+ */
+static void ccp2_reset(struct isp_ccp2_device *ccp2)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	int i = 0;
+
+	/* Reset the CSI1/CCP2B and wait for reset to complete */
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG,
+		    ISPCCP2_SYSCONFIG_SOFT_RESET);
+	while (!(isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSSTATUS) &
+		 ISPCCP2_SYSSTATUS_RESET_DONE)) {
+		udelay(10);
+		if (i++ > 10) {  /* try read 10 times */
+			dev_warn(isp->dev,
+				"omap3_isp: timeout waiting for ccp2 reset\n");
+			break;
+		}
+	}
+}
+
+/*
+ * ccp2_pwr_cfg - Configure the power mode settings
+ * @ccp2: pointer to ISP CCP2 device
+ */
+static void ccp2_pwr_cfg(struct isp_ccp2_device *ccp2)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+
+	isp_reg_writel(isp, ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART |
+			((isp->revision == ISP_REVISION_15_0 && isp->autoidle) ?
+			  ISPCCP2_SYSCONFIG_AUTO_IDLE : 0),
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_SYSCONFIG);
+}
+
+/*
+ * ccp2_if_enable - Enable CCP2 interface.
+ * @ccp2: pointer to ISP CCP2 device
+ * @enable: enable/disable flag
+ */
+static void ccp2_if_enable(struct isp_ccp2_device *ccp2, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
+	int i;
+
+	/* Enable/Disable all the LCx channels */
+	for (i = 0; i < CCP2_LCx_CHANS_NUM; i++)
+		isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(i),
+				ISPCCP2_LCx_CTRL_CHAN_EN,
+				enable ? ISPCCP2_LCx_CTRL_CHAN_EN : 0);
+
+	/* Enable/Disable ccp2 interface in ccp2 mode */
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
+			ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN,
+			enable ? (ISPCCP2_CTRL_MODE | ISPCCP2_CTRL_IF_EN) : 0);
+
+	/* For frame count propagation */
+	if (pipe->do_propagation) {
+		/* We may want the Frame Start IRQ from LC0 */
+		if (enable)
+			isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2,
+				    ISPCCP2_LC01_IRQENABLE,
+				    ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
+		else
+			isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCP2,
+				    ISPCCP2_LC01_IRQENABLE,
+				    ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ);
+	}
+}
+
+/*
+ * ccp2_mem_enable - Enable CCP2 memory interface.
+ * @ccp2: pointer to ISP CCP2 device
+ * @enable: enable/disable flag
+ */
+static void ccp2_mem_enable(struct isp_ccp2_device *ccp2, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+
+	if (enable)
+		ccp2_if_enable(ccp2, 0);
+
+	/* Enable/Disable ccp2 interface in ccp2 mode */
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
+			ISPCCP2_CTRL_MODE, enable ? ISPCCP2_CTRL_MODE : 0);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL,
+			ISPCCP2_LCM_CTRL_CHAN_EN,
+			enable ? ISPCCP2_LCM_CTRL_CHAN_EN : 0);
+}
+
+/*
+ * ccp2_phyif_config - Initialize CCP2 phy interface config
+ * @ccp2: Pointer to ISP CCP2 device
+ * @config: CCP2 platform data
+ *
+ * Configure the CCP2 physical interface module from platform data.
+ *
+ * Returns -EIO if strobe is chosen in CSI1 mode, or 0 on success.
+ */
+static int ccp2_phyif_config(struct isp_ccp2_device *ccp2,
+			     const struct isp_ccp2_platform_data *pdata)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	u32 val;
+
+	/* CCP2B mode */
+	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL) |
+			    ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE;
+	/* Data/strobe physical layer */
+	BIT_SET(val, ISPCCP2_CTRL_PHY_SEL_SHIFT, ISPCCP2_CTRL_PHY_SEL_MASK,
+		pdata->phy_layer);
+	BIT_SET(val, ISPCCP2_CTRL_INV_SHIFT, ISPCCP2_CTRL_INV_MASK,
+		pdata->strobe_clk_pol);
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
+
+	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
+	if (!(val & ISPCCP2_CTRL_MODE)) {
+		if (pdata->ccp2_mode)
+			dev_warn(isp->dev, "OMAP3 CCP2 bus not available\n");
+		if (pdata->phy_layer == ISPCCP2_CTRL_PHY_SEL_STROBE)
+			/* Strobe mode requires CCP2 */
+			return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * ccp2_vp_config - Initialize CCP2 video port interface.
+ * @ccp2: Pointer to ISP CCP2 device
+ * @vpclk_div: Video port divisor
+ *
+ * Configure the CCP2 video port with the given clock divisor. The valid divisor
+ * values depend on the ISP revision:
+ *
+ * - revision 1.0 and 2.0	1 to 4
+ * - revision 15.0		1 to 65536
+ *
+ * The exact divisor value used might differ from the requested value, as ISP
+ * revision 15.0 represent the divisor by 65536 divided by an integer.
+ */
+static void ccp2_vp_config(struct isp_ccp2_device *ccp2,
+			   unsigned int vpclk_div)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	u32 val;
+
+	/* ISPCCP2_CTRL Video port */
+	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
+	val |= ISPCCP2_CTRL_VP_ONLY_EN;	/* Disable the memory write port */
+
+	if (isp->revision == ISP_REVISION_15_0) {
+		vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 65536);
+		vpclk_div = min(ISPCCP2_VPCLK_FRACDIV / vpclk_div, 65535U);
+		BIT_SET(val, ISPCCP2_CTRL_VPCLK_DIV_SHIFT,
+			ISPCCP2_CTRL_VPCLK_DIV_MASK, vpclk_div);
+	} else {
+		vpclk_div = clamp_t(unsigned int, vpclk_div, 1, 4);
+		BIT_SET(val, ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT,
+			ISPCCP2_CTRL_VP_OUT_CTRL_MASK, vpclk_div - 1);
+	}
+
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL);
+}
+
+/*
+ * ccp2_lcx_config - Initialize CCP2 logical channel interface.
+ * @ccp2: Pointer to ISP CCP2 device
+ * @config: Pointer to ISP LCx config structure.
+ *
+ * This will analyze the parameters passed by the interface config
+ * and configure CSI1/CCP2 logical channel
+ *
+ */
+static void ccp2_lcx_config(struct isp_ccp2_device *ccp2,
+			    struct isp_interface_lcx_config *config)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	u32 val, format;
+
+	switch (config->format) {
+	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+		format = ISPCCP2_LCx_CTRL_FORMAT_RAW8_DPCM10_VP;
+		break;
+	case V4L2_MBUS_FMT_SGRBG10_1X10:
+	default:
+		format = ISPCCP2_LCx_CTRL_FORMAT_RAW10_VP;	/* RAW10+VP */
+		break;
+	}
+	/* ISPCCP2_LCx_CTRL logical channel #0 */
+	val = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0))
+			    | (ISPCCP2_LCx_CTRL_REGION_EN); /* Region */
+
+	if (isp->revision == ISP_REVISION_15_0) {
+		/* CRC */
+		BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0,
+			ISPCCP2_LCx_CTRL_CRC_MASK,
+			config->crc);
+		/* Format = RAW10+VP or RAW8+DPCM10+VP*/
+		BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0,
+			ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0, format);
+	} else {
+		BIT_SET(val, ISPCCP2_LCx_CTRL_CRC_SHIFT,
+			ISPCCP2_LCx_CTRL_CRC_MASK,
+			config->crc);
+
+		BIT_SET(val, ISPCCP2_LCx_CTRL_FORMAT_SHIFT,
+			ISPCCP2_LCx_CTRL_FORMAT_MASK, format);
+	}
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_CTRL(0));
+
+	/* ISPCCP2_DAT_START for logical channel #0 */
+	isp_reg_writel(isp, config->data_start << ISPCCP2_LCx_DAT_SHIFT,
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_START(0));
+
+	/* ISPCCP2_DAT_SIZE for logical channel #0 */
+	isp_reg_writel(isp, config->data_size << ISPCCP2_LCx_DAT_SHIFT,
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCx_DAT_SIZE(0));
+
+	/* Enable error IRQs for logical channel #0 */
+	val = ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
+	      ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
+	      ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
+	      ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
+	      ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ |
+	      ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
+	      ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
+
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQSTATUS);
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LC01_IRQENABLE, val);
+}
+
+/*
+ * ccp2_if_configure - Configure ccp2 with data from sensor
+ * @ccp2: Pointer to ISP CCP2 device
+ *
+ * Return 0 on success or a negative error code
+ */
+static int ccp2_if_configure(struct isp_ccp2_device *ccp2)
+{
+	const struct isp_v4l2_subdevs_group *pdata;
+	struct v4l2_mbus_framefmt *format;
+	struct media_pad *pad;
+	struct v4l2_subdev *sensor;
+	u32 lines = 0;
+	int ret;
+
+	ccp2_pwr_cfg(ccp2);
+
+	pad = media_entity_remote_source(&ccp2->pads[CCP2_PAD_SINK]);
+	sensor = media_entity_to_v4l2_subdev(pad->entity);
+	pdata = sensor->host_priv;
+
+	ret = ccp2_phyif_config(ccp2, &pdata->bus.ccp2);
+	if (ret < 0)
+		return ret;
+
+	ccp2_vp_config(ccp2, pdata->bus.ccp2.vpclk_div + 1);
+
+	v4l2_subdev_call(sensor, sensor, g_skip_top_lines, &lines);
+
+	format = &ccp2->formats[CCP2_PAD_SINK];
+
+	ccp2->if_cfg.data_start = lines;
+	ccp2->if_cfg.crc = pdata->bus.ccp2.crc;
+	ccp2->if_cfg.format = format->code;
+	ccp2->if_cfg.data_size = format->height;
+
+	ccp2_lcx_config(ccp2, &ccp2->if_cfg);
+
+	return 0;
+}
+
+static int ccp2_adjust_bandwidth(struct isp_ccp2_device *ccp2)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
+	struct isp_device *isp = to_isp_device(ccp2);
+	const struct v4l2_mbus_framefmt *ofmt = &ccp2->formats[CCP2_PAD_SOURCE];
+	unsigned long l3_ick = pipe->l3_ick;
+	struct v4l2_fract *timeperframe;
+	unsigned int vpclk_div = 2;
+	unsigned int value;
+	u64 bound;
+	u64 area;
+
+	/* Compute the minimum clock divisor, based on the pipeline maximum
+	 * data rate. This is an absolute lower bound if we don't want SBL
+	 * overflows, so round the value up.
+	 */
+	vpclk_div = max_t(unsigned int, DIV_ROUND_UP(l3_ick, pipe->max_rate),
+			  vpclk_div);
+
+	/* Compute the maximum clock divisor, based on the requested frame rate.
+	 * This is a soft lower bound to achieve a frame rate equal or higher
+	 * than the requested value, so round the value down.
+	 */
+	timeperframe = &pipe->max_timeperframe;
+
+	if (timeperframe->numerator) {
+		area = ofmt->width * ofmt->height;
+		bound = div_u64(area * timeperframe->denominator,
+				timeperframe->numerator);
+		value = min_t(u64, bound, l3_ick);
+		vpclk_div = max_t(unsigned int, l3_ick / value, vpclk_div);
+	}
+
+	dev_dbg(isp->dev, "%s: minimum clock divisor = %u\n", __func__,
+		vpclk_div);
+
+	return vpclk_div;
+}
+
+/*
+ * ccp2_mem_configure - Initialize CCP2 memory input/output interface
+ * @ccp2: Pointer to ISP CCP2 device
+ * @config: Pointer to ISP mem interface config structure
+ *
+ * This will analyze the parameters passed by the interface config
+ * structure, and configure the respective registers for proper
+ * CSI1/CCP2 memory input.
+ */
+static void ccp2_mem_configure(struct isp_ccp2_device *ccp2,
+			       struct isp_interface_mem_config *config)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	u32 sink_pixcode = ccp2->formats[CCP2_PAD_SINK].code;
+	u32 source_pixcode = ccp2->formats[CCP2_PAD_SOURCE].code;
+	unsigned int dpcm_decompress = 0;
+	u32 val, hwords;
+
+	if (sink_pixcode != source_pixcode &&
+	    sink_pixcode == V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
+		dpcm_decompress = 1;
+
+	ccp2_pwr_cfg(ccp2);
+
+	/* Hsize, Skip */
+	isp_reg_writel(isp, ISPCCP2_LCM_HSIZE_SKIP_MIN |
+		       (config->hsize_count << ISPCCP2_LCM_HSIZE_SHIFT),
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_HSIZE);
+
+	/* Vsize, no. of lines */
+	isp_reg_writel(isp, config->vsize_count << ISPCCP2_LCM_VSIZE_SHIFT,
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_VSIZE);
+
+	if (ccp2->video_in.bpl_padding == 0)
+		config->src_ofst = 0;
+	else
+		config->src_ofst = ccp2->video_in.bpl_value;
+
+	isp_reg_writel(isp, config->src_ofst, OMAP3_ISP_IOMEM_CCP2,
+		       ISPCCP2_LCM_SRC_OFST);
+
+	/* Source and Destination formats */
+	val = ISPCCP2_LCM_CTRL_DST_FORMAT_RAW10 <<
+	      ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT;
+
+	if (dpcm_decompress) {
+		/* source format is RAW8 */
+		val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW8 <<
+		       ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
+
+		/* RAW8 + DPCM10 - simple predictor */
+		val |= ISPCCP2_LCM_CTRL_SRC_DPCM_PRED;
+
+		/* enable source DPCM decompression */
+		val |= ISPCCP2_LCM_CTRL_SRC_DECOMPR_DPCM10 <<
+		       ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT;
+	} else {
+		/* source format is RAW10 */
+		val |= ISPCCP2_LCM_CTRL_SRC_FORMAT_RAW10 <<
+		       ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT;
+	}
+
+	/* Burst size to 32x64 */
+	val |= ISPCCP2_LCM_CTRL_BURST_SIZE_32X <<
+	       ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT;
+
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_CTRL);
+
+	/* Prefetch setup */
+	if (dpcm_decompress)
+		hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
+			  config->hsize_count) >> 3;
+	else
+		hwords = (ISPCCP2_LCM_HSIZE_SKIP_MIN +
+			  config->hsize_count) >> 2;
+
+	isp_reg_writel(isp, hwords << ISPCCP2_LCM_PREFETCH_SHIFT,
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_PREFETCH);
+
+	/* Video port */
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_CTRL,
+		    ISPCCP2_CTRL_IO_OUT_SEL | ISPCCP2_CTRL_MODE);
+	ccp2_vp_config(ccp2, ccp2_adjust_bandwidth(ccp2));
+
+	/* Clear LCM interrupts */
+	isp_reg_writel(isp, ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ |
+		       ISPCCP2_LCM_IRQSTATUS_EOF_IRQ,
+		       OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQSTATUS);
+
+	/* Enable LCM interupts */
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_IRQENABLE,
+		    ISPCCP2_LCM_IRQSTATUS_EOF_IRQ |
+		    ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ);
+}
+
+/*
+ * ccp2_set_inaddr - Sets memory address of input frame.
+ * @ccp2: Pointer to ISP CCP2 device
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ *
+ * Configures the memory address from which the input frame is to be read.
+ */
+static void ccp2_set_inaddr(struct isp_ccp2_device *ccp2, u32 addr)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+
+	isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_CCP2, ISPCCP2_LCM_SRC_ADDR);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+static void ccp2_isr_buffer(struct isp_ccp2_device *ccp2)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&ccp2->subdev.entity);
+	struct isp_buffer *buffer;
+
+	buffer = omap3isp_video_buffer_next(&ccp2->video_in, ccp2->error);
+	if (buffer != NULL)
+		ccp2_set_inaddr(ccp2, buffer->isp_addr);
+
+	pipe->state |= ISP_PIPELINE_IDLE_INPUT;
+
+	if (ccp2->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
+		if (isp_pipeline_ready(pipe))
+			omap3isp_pipeline_set_stream(pipe,
+						ISP_PIPELINE_STREAM_SINGLESHOT);
+	}
+
+	ccp2->error = 0;
+}
+
+/*
+ * omap3isp_ccp2_isr - Handle ISP CCP2 interrupts
+ * @ccp2: Pointer to ISP CCP2 device
+ *
+ * This will handle the CCP2 interrupts
+ *
+ * Returns -EIO in case of error, or 0 on success.
+ */
+int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2)
+{
+	struct isp_device *isp = to_isp_device(ccp2);
+	int ret = 0;
+	static const u32 ISPCCP2_LC01_ERROR =
+		ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ |
+		ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ |
+		ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ |
+		ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ |
+		ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ |
+		ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ;
+	u32 lcx_irqstatus, lcm_irqstatus;
+
+	/* First clear the interrupts */
+	lcx_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
+				      ISPCCP2_LC01_IRQSTATUS);
+	isp_reg_writel(isp, lcx_irqstatus, OMAP3_ISP_IOMEM_CCP2,
+		       ISPCCP2_LC01_IRQSTATUS);
+
+	lcm_irqstatus = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCP2,
+				      ISPCCP2_LCM_IRQSTATUS);
+	isp_reg_writel(isp, lcm_irqstatus, OMAP3_ISP_IOMEM_CCP2,
+		       ISPCCP2_LCM_IRQSTATUS);
+	/* Errors */
+	if (lcx_irqstatus & ISPCCP2_LC01_ERROR) {
+		ccp2->error = 1;
+		dev_dbg(isp->dev, "CCP2 err:%x\n", lcx_irqstatus);
+		return -EIO;
+	}
+
+	if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ) {
+		ccp2->error = 1;
+		dev_dbg(isp->dev, "CCP2 OCP err:%x\n", lcm_irqstatus);
+		ret = -EIO;
+	}
+
+	if (omap3isp_module_sync_is_stopping(&ccp2->wait, &ccp2->stopping))
+		return 0;
+
+	/* Frame number propagation */
+	if (lcx_irqstatus & ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ) {
+		struct isp_pipeline *pipe =
+			to_isp_pipeline(&ccp2->subdev.entity);
+		if (pipe->do_propagation)
+			atomic_inc(&pipe->frame_number);
+	}
+
+	/* Handle queued buffers on frame end interrupts */
+	if (lcm_irqstatus & ISPCCP2_LCM_IRQSTATUS_EOF_IRQ)
+		ccp2_isr_buffer(ccp2);
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static const unsigned int ccp2_fmts[] = {
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+};
+
+/*
+ * __ccp2_get_format - helper function for getting ccp2 format
+ * @ccp2  : Pointer to ISP CCP2 device
+ * @fh    : V4L2 subdev file handle
+ * @pad   : pad number
+ * @which : wanted subdev format
+ * return format structure or NULL on error
+ */
+static struct v4l2_mbus_framefmt *
+__ccp2_get_format(struct isp_ccp2_device *ccp2, struct v4l2_subdev_fh *fh,
+		     unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_format(fh, pad);
+	else
+		return &ccp2->formats[pad];
+}
+
+/*
+ * ccp2_try_format - Handle try format by pad subdev method
+ * @ccp2  : Pointer to ISP CCP2 device
+ * @fh    : V4L2 subdev file handle
+ * @pad   : pad num
+ * @fmt   : pointer to v4l2 mbus format structure
+ * @which : wanted subdev format
+ */
+static void ccp2_try_format(struct isp_ccp2_device *ccp2,
+			       struct v4l2_subdev_fh *fh, unsigned int pad,
+			       struct v4l2_mbus_framefmt *fmt,
+			       enum v4l2_subdev_format_whence which)
+{
+	struct v4l2_mbus_framefmt *format;
+
+	switch (pad) {
+	case CCP2_PAD_SINK:
+		if (fmt->code != V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8)
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+		if (ccp2->input == CCP2_INPUT_SENSOR) {
+			fmt->width = clamp_t(u32, fmt->width,
+					     ISPCCP2_DAT_START_MIN,
+					     ISPCCP2_DAT_START_MAX);
+			fmt->height = clamp_t(u32, fmt->height,
+					      ISPCCP2_DAT_SIZE_MIN,
+					      ISPCCP2_DAT_SIZE_MAX);
+		} else if (ccp2->input == CCP2_INPUT_MEMORY) {
+			fmt->width = clamp_t(u32, fmt->width,
+					     ISPCCP2_LCM_HSIZE_COUNT_MIN,
+					     ISPCCP2_LCM_HSIZE_COUNT_MAX);
+			fmt->height = clamp_t(u32, fmt->height,
+					      ISPCCP2_LCM_VSIZE_MIN,
+					      ISPCCP2_LCM_VSIZE_MAX);
+		}
+		break;
+
+	case CCP2_PAD_SOURCE:
+		/* Source format - copy sink format and change pixel code
+		 * to SGRBG10_1X10 as we don't support CCP2 write to memory.
+		 * When CCP2 write to memory feature will be added this
+		 * should be changed properly.
+		 */
+		format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK, which);
+		memcpy(fmt, format, sizeof(*fmt));
+		fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+		break;
+	}
+
+	fmt->field = V4L2_FIELD_NONE;
+	fmt->colorspace = V4L2_COLORSPACE_SRGB;
+}
+
+/*
+ * ccp2_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh     : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int ccp2_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	if (code->pad == CCP2_PAD_SINK) {
+		if (code->index >= ARRAY_SIZE(ccp2_fmts))
+			return -EINVAL;
+
+		code->code = ccp2_fmts[code->index];
+	} else {
+		if (code->index != 0)
+			return -EINVAL;
+
+		format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SINK,
+					      V4L2_SUBDEV_FORMAT_TRY);
+		code->code = format->code;
+	}
+
+	return 0;
+}
+
+static int ccp2_enum_frame_size(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt format;
+
+	if (fse->index != 0)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = 1;
+	format.height = 1;
+	ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->min_width = format.width;
+	fse->min_height = format.height;
+
+	if (format.code != fse->code)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = -1;
+	format.height = -1;
+	ccp2_try_format(ccp2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->max_width = format.width;
+	fse->max_height = format.height;
+
+	return 0;
+}
+
+/*
+ * ccp2_get_format - Handle get format by pads subdev method
+ * @sd    : pointer to v4l2 subdev structure
+ * @fh    : V4L2 subdev file handle
+ * @fmt   : pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int ccp2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+/*
+ * ccp2_set_format - Handle set format by pads subdev method
+ * @sd    : pointer to v4l2 subdev structure
+ * @fh    : V4L2 subdev file handle
+ * @fmt   : pointer to v4l2 subdev format structure
+ * returns zero
+ */
+static int ccp2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __ccp2_get_format(ccp2, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	ccp2_try_format(ccp2, fh, fmt->pad, &fmt->format, fmt->which);
+	*format = fmt->format;
+
+	/* Propagate the format from sink to source */
+	if (fmt->pad == CCP2_PAD_SINK) {
+		format = __ccp2_get_format(ccp2, fh, CCP2_PAD_SOURCE,
+					   fmt->which);
+		*format = fmt->format;
+		ccp2_try_format(ccp2, fh, CCP2_PAD_SOURCE, format, fmt->which);
+	}
+
+	return 0;
+}
+
+/*
+ * ccp2_init_formats - Initialize formats on all pads
+ * @sd: ISP CCP2 V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int ccp2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_subdev_format format;
+
+	memset(&format, 0, sizeof(format));
+	format.pad = CCP2_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format.format.width = 4096;
+	format.format.height = 4096;
+	ccp2_set_format(sd, fh, &format);
+
+	return 0;
+}
+
+/*
+ * ccp2_s_stream - Enable/Disable streaming on ccp2 subdev
+ * @sd    : pointer to v4l2 subdev structure
+ * @enable: 1 == Enable, 0 == Disable
+ * return zero
+ */
+static int ccp2_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
+	struct isp_device *isp = to_isp_device(ccp2);
+	struct device *dev = to_device(ccp2);
+	int ret;
+
+	if (ccp2->state == ISP_PIPELINE_STREAM_STOPPED) {
+		if (enable == ISP_PIPELINE_STREAM_STOPPED)
+			return 0;
+		atomic_set(&ccp2->stopping, 0);
+		ccp2->error = 0;
+	}
+
+	switch (enable) {
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		if (ccp2->phy) {
+			ret = omap3isp_csiphy_acquire(ccp2->phy);
+			if (ret < 0)
+				return ret;
+		}
+
+		ccp2_if_configure(ccp2);
+		ccp2_print_status(ccp2);
+
+		/* Enable CSI1/CCP2 interface */
+		ccp2_if_enable(ccp2, 1);
+		break;
+
+	case ISP_PIPELINE_STREAM_SINGLESHOT:
+		if (ccp2->state != ISP_PIPELINE_STREAM_SINGLESHOT) {
+			struct v4l2_mbus_framefmt *format;
+
+			format = &ccp2->formats[CCP2_PAD_SINK];
+
+			ccp2->mem_cfg.hsize_count = format->width;
+			ccp2->mem_cfg.vsize_count = format->height;
+			ccp2->mem_cfg.src_ofst = 0;
+
+			ccp2_mem_configure(ccp2, &ccp2->mem_cfg);
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI1_READ);
+			ccp2_print_status(ccp2);
+		}
+		ccp2_mem_enable(ccp2, 1);
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+		if (omap3isp_module_sync_idle(&sd->entity, &ccp2->wait,
+					      &ccp2->stopping))
+			dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
+		if (ccp2->input == CCP2_INPUT_MEMORY) {
+			ccp2_mem_enable(ccp2, 0);
+			omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI1_READ);
+		} else if (ccp2->input == CCP2_INPUT_SENSOR) {
+			/* Disable CSI1/CCP2 interface */
+			ccp2_if_enable(ccp2, 0);
+			if (ccp2->phy)
+				omap3isp_csiphy_release(ccp2->phy);
+		}
+		break;
+	}
+
+	ccp2->state = enable;
+	return 0;
+}
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops ccp2_sd_video_ops = {
+	.s_stream = ccp2_s_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops ccp2_sd_pad_ops = {
+	.enum_mbus_code = ccp2_enum_mbus_code,
+	.enum_frame_size = ccp2_enum_frame_size,
+	.get_fmt = ccp2_get_format,
+	.set_fmt = ccp2_set_format,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops ccp2_sd_ops = {
+	.video = &ccp2_sd_video_ops,
+	.pad = &ccp2_sd_pad_ops,
+};
+
+/* subdev internal operations */
+static const struct v4l2_subdev_internal_ops ccp2_sd_internal_ops = {
+	.open = ccp2_init_formats,
+};
+
+/* --------------------------------------------------------------------------
+ * ISP ccp2 video device node
+ */
+
+/*
+ * ccp2_video_queue - Queue video buffer.
+ * @video : Pointer to isp video structure
+ * @buffer: Pointer to isp_buffer structure
+ * return -EIO or zero on success
+ */
+static int ccp2_video_queue(struct isp_video *video, struct isp_buffer *buffer)
+{
+	struct isp_ccp2_device *ccp2 = &video->isp->isp_ccp2;
+
+	ccp2_set_inaddr(ccp2, buffer->isp_addr);
+	return 0;
+}
+
+static const struct isp_video_operations ccp2_video_ops = {
+	.queue = ccp2_video_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * ccp2_link_setup - Setup ccp2 connections.
+ * @entity : Pointer to media entity structure
+ * @local  : Pointer to local pad array
+ * @remote : Pointer to remote pad array
+ * @flags  : Link flags
+ * return -EINVAL on error or zero on success
+ */
+static int ccp2_link_setup(struct media_entity *entity,
+			   const struct media_pad *local,
+			   const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct isp_ccp2_device *ccp2 = v4l2_get_subdevdata(sd);
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case CCP2_PAD_SINK | MEDIA_ENT_T_DEVNODE:
+		/* read from memory */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (ccp2->input == CCP2_INPUT_SENSOR)
+				return -EBUSY;
+			ccp2->input = CCP2_INPUT_MEMORY;
+		} else {
+			if (ccp2->input == CCP2_INPUT_MEMORY)
+				ccp2->input = CCP2_INPUT_NONE;
+		}
+		break;
+
+	case CCP2_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* read from sensor/phy */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (ccp2->input == CCP2_INPUT_MEMORY)
+				return -EBUSY;
+			ccp2->input = CCP2_INPUT_SENSOR;
+		} else {
+			if (ccp2->input == CCP2_INPUT_SENSOR)
+				ccp2->input = CCP2_INPUT_NONE;
+		} break;
+
+	case CCP2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* write to video port/ccdc */
+		if (flags & MEDIA_LNK_FL_ENABLED)
+			ccp2->output = CCP2_OUTPUT_CCDC;
+		else
+			ccp2->output = CCP2_OUTPUT_NONE;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations ccp2_media_ops = {
+	.link_setup = ccp2_link_setup,
+};
+
+/*
+ * ccp2_init_entities - Initialize ccp2 subdev and media entity.
+ * @ccp2: Pointer to ISP CCP2 device
+ * return negative error code or zero on success
+ */
+static int ccp2_init_entities(struct isp_ccp2_device *ccp2)
+{
+	struct v4l2_subdev *sd = &ccp2->subdev;
+	struct media_pad *pads = ccp2->pads;
+	struct media_entity *me = &sd->entity;
+	int ret;
+
+	ccp2->input = CCP2_INPUT_NONE;
+	ccp2->output = CCP2_OUTPUT_NONE;
+
+	v4l2_subdev_init(sd, &ccp2_sd_ops);
+	sd->internal_ops = &ccp2_sd_internal_ops;
+	strlcpy(sd->name, "OMAP3 ISP CCP2", sizeof(sd->name));
+	sd->grp_id = 1 << 16;   /* group ID for isp subdevs */
+	v4l2_set_subdevdata(sd, ccp2);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	pads[CCP2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	pads[CCP2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	me->ops = &ccp2_media_ops;
+	ret = media_entity_init(me, CCP2_PADS_NUM, pads, 0);
+	if (ret < 0)
+		return ret;
+
+	ccp2_init_formats(sd, NULL);
+
+	/*
+	 * The CCP2 has weird line alignment requirements, possibly caused by
+	 * DPCM8 decompression. Line length for data read from memory must be a
+	 * multiple of 128 bits (16 bytes) in continuous mode (when no padding
+	 * is present at end of lines). Additionally, if padding is used, the
+	 * padded line length must be a multiple of 32 bytes. To simplify the
+	 * implementation we use a fixed 32 bytes alignment regardless of the
+	 * input format and width. If strict 128 bits alignment support is
+	 * required ispvideo will need to be made aware of this special dual
+	 * alignement requirements.
+	 */
+	ccp2->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	ccp2->video_in.bpl_alignment = 32;
+	ccp2->video_in.bpl_max = 0xffffffe0;
+	ccp2->video_in.isp = to_isp_device(ccp2);
+	ccp2->video_in.ops = &ccp2_video_ops;
+	ccp2->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
+
+	ret = omap3isp_video_init(&ccp2->video_in, "CCP2");
+	if (ret < 0)
+		return ret;
+
+	/* Connect the video node to the ccp2 subdev. */
+	ret = media_entity_create_link(&ccp2->video_in.video.entity, 0,
+				       &ccp2->subdev.entity, CCP2_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+/*
+ * omap3isp_ccp2_unregister_entities - Unregister media entities: subdev
+ * @ccp2: Pointer to ISP CCP2 device
+ */
+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2)
+{
+	media_entity_cleanup(&ccp2->subdev.entity);
+
+	v4l2_device_unregister_subdev(&ccp2->subdev);
+	omap3isp_video_unregister(&ccp2->video_in);
+}
+
+/*
+ * omap3isp_ccp2_register_entities - Register the subdev media entity
+ * @ccp2: Pointer to ISP CCP2 device
+ * @vdev: Pointer to v4l device
+ * return negative error code or zero on success
+ */
+
+int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
+				    struct v4l2_device *vdev)
+{
+	int ret;
+
+	/* Register the subdev and video nodes. */
+	ret = v4l2_device_register_subdev(vdev, &ccp2->subdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&ccp2->video_in, vdev);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+error:
+	omap3isp_ccp2_unregister_entities(ccp2);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP ccp2 initialisation and cleanup
+ */
+
+/*
+ * omap3isp_ccp2_cleanup - CCP2 un-initialization
+ * @isp : Pointer to ISP device
+ */
+void omap3isp_ccp2_cleanup(struct isp_device *isp)
+{
+}
+
+/*
+ * omap3isp_ccp2_init - CCP2 initialization.
+ * @isp : Pointer to ISP device
+ * return negative error code or zero on success
+ */
+int omap3isp_ccp2_init(struct isp_device *isp)
+{
+	struct isp_ccp2_device *ccp2 = &isp->isp_ccp2;
+	int ret;
+
+	init_waitqueue_head(&ccp2->wait);
+
+	/* On the OMAP36xx, the CCP2 uses the CSI PHY1 or PHY2, shared with
+	 * the CSI2c or CSI2a receivers. The PHY then needs to be explicitly
+	 * configured.
+	 *
+	 * TODO: Don't hardcode the usage of PHY1 (shared with CSI2c).
+	 */
+	if (isp->revision == ISP_REVISION_15_0)
+		ccp2->phy = &isp->isp_csiphy1;
+
+	ret = ccp2_init_entities(ccp2);
+	if (ret < 0)
+		goto out;
+
+	ccp2_reset(ccp2);
+out:
+	if (ret)
+		omap3isp_ccp2_cleanup(isp);
+
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccp2.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccp2.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispccp2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispccp2.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * ispccp2.h
+ *
+ * TI OMAP3 ISP - CCP2 module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2010 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_CCP2_H
+#define OMAP3_ISP_CCP2_H
+
+#include <linux/videodev2.h>
+
+struct isp_device;
+struct isp_csiphy;
+
+/* Sink and source ccp2 pads */
+#define CCP2_PAD_SINK			0
+#define CCP2_PAD_SOURCE			1
+#define CCP2_PADS_NUM			2
+
+/* CCP2 input media entity */
+enum ccp2_input_entity {
+	CCP2_INPUT_NONE,
+	CCP2_INPUT_SENSOR,
+	CCP2_INPUT_MEMORY,
+};
+
+/* CCP2 output media entity */
+enum ccp2_output_entity {
+	CCP2_OUTPUT_NONE,
+	CCP2_OUTPUT_CCDC,
+	CCP2_OUTPUT_MEMORY,
+};
+
+
+/* Logical channel configuration */
+struct isp_interface_lcx_config {
+	int crc;
+	u32 data_start;
+	u32 data_size;
+	u32 format;
+};
+
+/* Memory channel configuration */
+struct isp_interface_mem_config {
+	u32 dst_port;
+	u32 vsize_count;
+	u32 hsize_count;
+	u32 src_ofst;
+	u32 dst_ofst;
+};
+
+/* CCP2 device */
+struct isp_ccp2_device {
+	struct v4l2_subdev subdev;
+	struct v4l2_mbus_framefmt formats[CCP2_PADS_NUM];
+	struct media_pad pads[CCP2_PADS_NUM];
+
+	enum ccp2_input_entity input;
+	enum ccp2_output_entity output;
+	struct isp_interface_lcx_config if_cfg;
+	struct isp_interface_mem_config mem_cfg;
+	struct isp_video video_in;
+	struct isp_csiphy *phy;
+	unsigned int error;
+	enum isp_pipeline_stream_state state;
+	wait_queue_head_t wait;
+	atomic_t stopping;
+};
+
+/* Function declarations */
+int omap3isp_ccp2_init(struct isp_device *isp);
+void omap3isp_ccp2_cleanup(struct isp_device *isp);
+int omap3isp_ccp2_register_entities(struct isp_ccp2_device *ccp2,
+			struct v4l2_device *vdev);
+void omap3isp_ccp2_unregister_entities(struct isp_ccp2_device *ccp2);
+int omap3isp_ccp2_isr(struct isp_ccp2_device *ccp2);
+
+#endif	/* OMAP3_ISP_CCP2_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsi2.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsi2.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsi2.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsi2.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1317 @@
+/*
+ * ispcsi2.c
+ *
+ * TI OMAP3 ISP - CSI2 module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/delay.h>
+#include <media/v4l2-common.h>
+#include <linux/v4l2-mediabus.h>
+#include <linux/mm.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispcsi2.h"
+
+/*
+ * csi2_if_enable - Enable CSI2 Receiver interface.
+ * @enable: enable flag
+ *
+ */
+static void csi2_if_enable(struct isp_device *isp,
+			   struct isp_csi2_device *csi2, u8 enable)
+{
+	struct isp_csi2_ctrl_cfg *currctrl = &csi2->ctrl;
+
+	isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_CTRL, ISPCSI2_CTRL_IF_EN,
+			enable ? ISPCSI2_CTRL_IF_EN : 0);
+
+	currctrl->if_enable = enable;
+}
+
+/*
+ * csi2_recv_config - CSI2 receiver module configuration.
+ * @currctrl: isp_csi2_ctrl_cfg structure
+ *
+ */
+static void csi2_recv_config(struct isp_device *isp,
+			     struct isp_csi2_device *csi2,
+			     struct isp_csi2_ctrl_cfg *currctrl)
+{
+	u32 reg;
+
+	reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTRL);
+
+	if (currctrl->frame_mode)
+		reg |= ISPCSI2_CTRL_FRAME;
+	else
+		reg &= ~ISPCSI2_CTRL_FRAME;
+
+	if (currctrl->vp_clk_enable)
+		reg |= ISPCSI2_CTRL_VP_CLK_EN;
+	else
+		reg &= ~ISPCSI2_CTRL_VP_CLK_EN;
+
+	if (currctrl->vp_only_enable)
+		reg |= ISPCSI2_CTRL_VP_ONLY_EN;
+	else
+		reg &= ~ISPCSI2_CTRL_VP_ONLY_EN;
+
+	reg &= ~ISPCSI2_CTRL_VP_OUT_CTRL_MASK;
+	reg |= currctrl->vp_out_ctrl << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT;
+
+	if (currctrl->ecc_enable)
+		reg |= ISPCSI2_CTRL_ECC_EN;
+	else
+		reg &= ~ISPCSI2_CTRL_ECC_EN;
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTRL);
+}
+
+static const unsigned int csi2_input_fmts[] = {
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SRGGB10_1X10,
+	V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
+	V4L2_MBUS_FMT_SGBRG10_1X10,
+	V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+};
+
+/* To set the format on the CSI2 requires a mapping function that takes
+ * the following inputs:
+ * - 2 different formats (at this time)
+ * - 2 destinations (mem, vp+mem) (vp only handled separately)
+ * - 2 decompression options (on, off)
+ * - 2 isp revisions (certain format must be handled differently on OMAP3630)
+ * Output should be CSI2 frame format code
+ * Array indices as follows: [format][dest][decompr][is_3630]
+ * Not all combinations are valid. 0 means invalid.
+ */
+static const u16 __csi2_fmt_map[2][2][2][2] = {
+	/* RAW10 formats */
+	{
+		/* Output to memory */
+		{
+			/* No DPCM decompression */
+			{ CSI2_PIX_FMT_RAW10_EXP16, CSI2_PIX_FMT_RAW10_EXP16 },
+			/* DPCM decompression */
+			{ 0, 0 },
+		},
+		/* Output to both */
+		{
+			/* No DPCM decompression */
+			{ CSI2_PIX_FMT_RAW10_EXP16_VP,
+			  CSI2_PIX_FMT_RAW10_EXP16_VP },
+			/* DPCM decompression */
+			{ 0, 0 },
+		},
+	},
+	/* RAW10 DPCM8 formats */
+	{
+		/* Output to memory */
+		{
+			/* No DPCM decompression */
+			{ CSI2_PIX_FMT_RAW8, CSI2_USERDEF_8BIT_DATA1 },
+			/* DPCM decompression */
+			{ CSI2_PIX_FMT_RAW8_DPCM10_EXP16,
+			  CSI2_USERDEF_8BIT_DATA1_DPCM10 },
+		},
+		/* Output to both */
+		{
+			/* No DPCM decompression */
+			{ CSI2_PIX_FMT_RAW8_VP,
+			  CSI2_PIX_FMT_RAW8_VP },
+			/* DPCM decompression */
+			{ CSI2_PIX_FMT_RAW8_DPCM10_VP,
+			  CSI2_USERDEF_8BIT_DATA1_DPCM10_VP },
+		},
+	},
+};
+
+/*
+ * csi2_ctx_map_format - Map CSI2 sink media bus format to CSI2 format ID
+ * @csi2: ISP CSI2 device
+ *
+ * Returns CSI2 physical format id
+ */
+static u16 csi2_ctx_map_format(struct isp_csi2_device *csi2)
+{
+	const struct v4l2_mbus_framefmt *fmt = &csi2->formats[CSI2_PAD_SINK];
+	int fmtidx, destidx, is_3630;
+
+	switch (fmt->code) {
+	case V4L2_MBUS_FMT_SGRBG10_1X10:
+	case V4L2_MBUS_FMT_SRGGB10_1X10:
+	case V4L2_MBUS_FMT_SBGGR10_1X10:
+	case V4L2_MBUS_FMT_SGBRG10_1X10:
+		fmtidx = 0;
+		break;
+	case V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8:
+	case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
+		fmtidx = 1;
+		break;
+	default:
+		WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
+		     fmt->code);
+		return 0;
+	}
+
+	if (!(csi2->output & CSI2_OUTPUT_CCDC) &&
+	    !(csi2->output & CSI2_OUTPUT_MEMORY)) {
+		/* Neither output enabled is a valid combination */
+		return CSI2_PIX_FMT_OTHERS;
+	}
+
+	/* If we need to skip frames at the beginning of the stream disable the
+	 * video port to avoid sending the skipped frames to the CCDC.
+	 */
+	destidx = csi2->frame_skip ? 0 : !!(csi2->output & CSI2_OUTPUT_CCDC);
+	is_3630 = csi2->isp->revision == ISP_REVISION_15_0;
+
+	return __csi2_fmt_map[fmtidx][destidx][csi2->dpcm_decompress][is_3630];
+}
+
+/*
+ * csi2_set_outaddr - Set memory address to save output image
+ * @csi2: Pointer to ISP CSI2a device.
+ * @addr: ISP MMU Mapped 32-bit memory address aligned on 32 byte boundary.
+ *
+ * Sets the memory address where the output will be saved.
+ *
+ * Returns 0 if successful, or -EINVAL if the address is not in the 32 byte
+ * boundary.
+ */
+static void csi2_set_outaddr(struct isp_csi2_device *csi2, u32 addr)
+{
+	struct isp_device *isp = csi2->isp;
+	struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[0];
+
+	ctx->ping_addr = addr;
+	ctx->pong_addr = addr;
+	isp_reg_writel(isp, ctx->ping_addr,
+		       csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
+	isp_reg_writel(isp, ctx->pong_addr,
+		       csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
+}
+
+/*
+ * is_usr_def_mapping - Checks whether USER_DEF_MAPPING should
+ *			be enabled by CSI2.
+ * @format_id: mapped format id
+ *
+ */
+static inline int is_usr_def_mapping(u32 format_id)
+{
+	return (format_id & 0x40) ? 1 : 0;
+}
+
+/*
+ * csi2_ctx_enable - Enable specified CSI2 context
+ * @ctxnum: Context number, valid between 0 and 7 values.
+ * @enable: enable
+ *
+ */
+static void csi2_ctx_enable(struct isp_device *isp,
+			    struct isp_csi2_device *csi2, u8 ctxnum, u8 enable)
+{
+	struct isp_csi2_ctx_cfg *ctx = &csi2->contexts[ctxnum];
+	unsigned int skip = 0;
+	u32 reg;
+
+	reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
+
+	if (enable) {
+		if (csi2->frame_skip)
+			skip = csi2->frame_skip;
+		else if (csi2->output & CSI2_OUTPUT_MEMORY)
+			skip = 1;
+
+		reg &= ~ISPCSI2_CTX_CTRL1_COUNT_MASK;
+		reg |= ISPCSI2_CTX_CTRL1_COUNT_UNLOCK
+		    |  (skip << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
+		    |  ISPCSI2_CTX_CTRL1_CTX_EN;
+	} else {
+		reg &= ~ISPCSI2_CTX_CTRL1_CTX_EN;
+	}
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctxnum));
+	ctx->enabled = enable;
+}
+
+/*
+ * csi2_ctx_config - CSI2 context configuration.
+ * @ctx: context configuration
+ *
+ */
+static void csi2_ctx_config(struct isp_device *isp,
+			    struct isp_csi2_device *csi2,
+			    struct isp_csi2_ctx_cfg *ctx)
+{
+	u32 reg;
+
+	/* Set up CSI2_CTx_CTRL1 */
+	reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
+
+	if (ctx->eof_enabled)
+		reg |= ISPCSI2_CTX_CTRL1_EOF_EN;
+	else
+		reg &= ~ISPCSI2_CTX_CTRL1_EOF_EN;
+
+	if (ctx->eol_enabled)
+		reg |= ISPCSI2_CTX_CTRL1_EOL_EN;
+	else
+		reg &= ~ISPCSI2_CTX_CTRL1_EOL_EN;
+
+	if (ctx->checksum_enabled)
+		reg |= ISPCSI2_CTX_CTRL1_CS_EN;
+	else
+		reg &= ~ISPCSI2_CTX_CTRL1_CS_EN;
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL1(ctx->ctxnum));
+
+	/* Set up CSI2_CTx_CTRL2 */
+	reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
+
+	reg &= ~(ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK);
+	reg |= ctx->virtual_id << ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT;
+
+	reg &= ~(ISPCSI2_CTX_CTRL2_FORMAT_MASK);
+	reg |= ctx->format_id << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT;
+
+	if (ctx->dpcm_decompress) {
+		if (ctx->dpcm_predictor)
+			reg |= ISPCSI2_CTX_CTRL2_DPCM_PRED;
+		else
+			reg &= ~ISPCSI2_CTX_CTRL2_DPCM_PRED;
+	}
+
+	if (is_usr_def_mapping(ctx->format_id)) {
+		reg &= ~ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK;
+		reg |= 2 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT;
+	}
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL2(ctx->ctxnum));
+
+	/* Set up CSI2_CTx_CTRL3 */
+	reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
+	reg &= ~(ISPCSI2_CTX_CTRL3_ALPHA_MASK);
+	reg |= (ctx->alpha << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT);
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_CTX_CTRL3(ctx->ctxnum));
+
+	/* Set up CSI2_CTx_DAT_OFST */
+	reg = isp_reg_readl(isp, csi2->regs1,
+			    ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
+	reg &= ~ISPCSI2_CTX_DAT_OFST_OFST_MASK;
+	reg |= ctx->data_offset << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT;
+	isp_reg_writel(isp, reg, csi2->regs1,
+		       ISPCSI2_CTX_DAT_OFST(ctx->ctxnum));
+
+	isp_reg_writel(isp, ctx->ping_addr,
+		       csi2->regs1, ISPCSI2_CTX_DAT_PING_ADDR(ctx->ctxnum));
+
+	isp_reg_writel(isp, ctx->pong_addr,
+		       csi2->regs1, ISPCSI2_CTX_DAT_PONG_ADDR(ctx->ctxnum));
+}
+
+/*
+ * csi2_timing_config - CSI2 timing configuration.
+ * @timing: csi2_timing_cfg structure
+ */
+static void csi2_timing_config(struct isp_device *isp,
+			       struct isp_csi2_device *csi2,
+			       struct isp_csi2_timing_cfg *timing)
+{
+	u32 reg;
+
+	reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_TIMING);
+
+	if (timing->force_rx_mode)
+		reg |= ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
+	else
+		reg &= ~ISPCSI2_TIMING_FORCE_RX_MODE_IO(timing->ionum);
+
+	if (timing->stop_state_16x)
+		reg |= ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
+	else
+		reg &= ~ISPCSI2_TIMING_STOP_STATE_X16_IO(timing->ionum);
+
+	if (timing->stop_state_4x)
+		reg |= ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
+	else
+		reg &= ~ISPCSI2_TIMING_STOP_STATE_X4_IO(timing->ionum);
+
+	reg &= ~ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(timing->ionum);
+	reg |= timing->stop_state_counter <<
+	       ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(timing->ionum);
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_TIMING);
+}
+
+/*
+ * csi2_irq_ctx_set - Enables CSI2 Context IRQs.
+ * @enable: Enable/disable CSI2 Context interrupts
+ */
+static void csi2_irq_ctx_set(struct isp_device *isp,
+			     struct isp_csi2_device *csi2, int enable)
+{
+	u32 reg = ISPCSI2_CTX_IRQSTATUS_FE_IRQ;
+	int i;
+
+	if (csi2->use_fs_irq)
+		reg |= ISPCSI2_CTX_IRQSTATUS_FS_IRQ;
+
+	for (i = 0; i < 8; i++) {
+		isp_reg_writel(isp, reg, csi2->regs1,
+			       ISPCSI2_CTX_IRQSTATUS(i));
+		if (enable)
+			isp_reg_set(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
+				    reg);
+		else
+			isp_reg_clr(isp, csi2->regs1, ISPCSI2_CTX_IRQENABLE(i),
+				    reg);
+	}
+}
+
+/*
+ * csi2_irq_complexio1_set - Enables CSI2 ComplexIO IRQs.
+ * @enable: Enable/disable CSI2 ComplexIO #1 interrupts
+ */
+static void csi2_irq_complexio1_set(struct isp_device *isp,
+				    struct isp_csi2_device *csi2, int enable)
+{
+	u32 reg;
+	reg = ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT |
+		ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER |
+		ISPCSI2_PHY_IRQENABLE_STATEULPM5 |
+		ISPCSI2_PHY_IRQENABLE_ERRCONTROL5 |
+		ISPCSI2_PHY_IRQENABLE_ERRESC5 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTHS5 |
+		ISPCSI2_PHY_IRQENABLE_STATEULPM4 |
+		ISPCSI2_PHY_IRQENABLE_ERRCONTROL4 |
+		ISPCSI2_PHY_IRQENABLE_ERRESC4 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTHS4 |
+		ISPCSI2_PHY_IRQENABLE_STATEULPM3 |
+		ISPCSI2_PHY_IRQENABLE_ERRCONTROL3 |
+		ISPCSI2_PHY_IRQENABLE_ERRESC3 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTHS3 |
+		ISPCSI2_PHY_IRQENABLE_STATEULPM2 |
+		ISPCSI2_PHY_IRQENABLE_ERRCONTROL2 |
+		ISPCSI2_PHY_IRQENABLE_ERRESC2 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTHS2 |
+		ISPCSI2_PHY_IRQENABLE_STATEULPM1 |
+		ISPCSI2_PHY_IRQENABLE_ERRCONTROL1 |
+		ISPCSI2_PHY_IRQENABLE_ERRESC1 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1 |
+		ISPCSI2_PHY_IRQENABLE_ERRSOTHS1;
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
+	if (enable)
+		reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
+	else
+		reg = 0;
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_PHY_IRQENABLE);
+}
+
+/*
+ * csi2_irq_status_set - Enables CSI2 Status IRQs.
+ * @enable: Enable/disable CSI2 Status interrupts
+ */
+static void csi2_irq_status_set(struct isp_device *isp,
+				struct isp_csi2_device *csi2, int enable)
+{
+	u32 reg;
+	reg = ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
+		ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
+		ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ |
+		ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
+		ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
+		ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ |
+		ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ |
+		ISPCSI2_IRQSTATUS_CONTEXT(0);
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQSTATUS);
+	if (enable)
+		reg |= isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQENABLE);
+	else
+		reg = 0;
+
+	isp_reg_writel(isp, reg, csi2->regs1, ISPCSI2_IRQENABLE);
+}
+
+/*
+ * omap3isp_csi2_reset - Resets the CSI2 module.
+ *
+ * Must be called with the phy lock held.
+ *
+ * Returns 0 if successful, or -EBUSY if power command didn't respond.
+ */
+int omap3isp_csi2_reset(struct isp_csi2_device *csi2)
+{
+	struct isp_device *isp = csi2->isp;
+	u8 soft_reset_retries = 0;
+	u32 reg;
+	int i;
+
+	if (!csi2->available)
+		return -ENODEV;
+
+	if (csi2->phy->phy_in_use)
+		return -EBUSY;
+
+	isp_reg_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
+		    ISPCSI2_SYSCONFIG_SOFT_RESET);
+
+	do {
+		reg = isp_reg_readl(isp, csi2->regs1, ISPCSI2_SYSSTATUS) &
+				    ISPCSI2_SYSSTATUS_RESET_DONE;
+		if (reg == ISPCSI2_SYSSTATUS_RESET_DONE)
+			break;
+		soft_reset_retries++;
+		if (soft_reset_retries < 5)
+			udelay(100);
+	} while (soft_reset_retries < 5);
+
+	if (soft_reset_retries == 5) {
+		printk(KERN_ERR "CSI2: Soft reset try count exceeded!\n");
+		return -EBUSY;
+	}
+
+	if (isp->revision == ISP_REVISION_15_0)
+		isp_reg_set(isp, csi2->regs1, ISPCSI2_PHY_CFG,
+			    ISPCSI2_PHY_CFG_RESET_CTRL);
+
+	i = 100;
+	do {
+		reg = isp_reg_readl(isp, csi2->phy->phy_regs, ISPCSIPHY_REG1)
+		    & ISPCSIPHY_REG1_RESET_DONE_CTRLCLK;
+		if (reg == ISPCSIPHY_REG1_RESET_DONE_CTRLCLK)
+			break;
+		udelay(100);
+	} while (--i > 0);
+
+	if (i == 0) {
+		printk(KERN_ERR
+		       "CSI2: Reset for CSI2_96M_FCLK domain Failed!\n");
+		return -EBUSY;
+	}
+
+	if (isp->autoidle)
+		isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
+				ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
+				ISPCSI2_SYSCONFIG_AUTO_IDLE,
+				ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART |
+				((isp->revision == ISP_REVISION_15_0) ?
+				 ISPCSI2_SYSCONFIG_AUTO_IDLE : 0));
+	else
+		isp_reg_clr_set(isp, csi2->regs1, ISPCSI2_SYSCONFIG,
+				ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK |
+				ISPCSI2_SYSCONFIG_AUTO_IDLE,
+				ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO);
+
+	return 0;
+}
+
+static int csi2_configure(struct isp_csi2_device *csi2)
+{
+	const struct isp_v4l2_subdevs_group *pdata;
+	struct isp_device *isp = csi2->isp;
+	struct isp_csi2_timing_cfg *timing = &csi2->timing[0];
+	struct v4l2_subdev *sensor;
+	struct media_pad *pad;
+
+	/*
+	 * CSI2 fields that can be updated while the context has
+	 * been enabled or the interface has been enabled are not
+	 * updated dynamically currently. So we do not allow to
+	 * reconfigure if either has been enabled
+	 */
+	if (csi2->contexts[0].enabled || csi2->ctrl.if_enable)
+		return -EBUSY;
+
+	pad = media_entity_remote_source(&csi2->pads[CSI2_PAD_SINK]);
+	sensor = media_entity_to_v4l2_subdev(pad->entity);
+	pdata = sensor->host_priv;
+
+	csi2->frame_skip = 0;
+	v4l2_subdev_call(sensor, sensor, g_skip_frames, &csi2->frame_skip);
+
+	csi2->ctrl.vp_out_ctrl = pdata->bus.csi2.vpclk_div;
+	csi2->ctrl.frame_mode = ISP_CSI2_FRAME_IMMEDIATE;
+	csi2->ctrl.ecc_enable = pdata->bus.csi2.crc;
+
+	timing->ionum = 1;
+	timing->force_rx_mode = 1;
+	timing->stop_state_16x = 1;
+	timing->stop_state_4x = 1;
+	timing->stop_state_counter = 0x1FF;
+
+	/*
+	 * The CSI2 receiver can't do any format conversion except DPCM
+	 * decompression, so every set_format call configures both pads
+	 * and enables DPCM decompression as a special case:
+	 */
+	if (csi2->formats[CSI2_PAD_SINK].code !=
+	    csi2->formats[CSI2_PAD_SOURCE].code)
+		csi2->dpcm_decompress = true;
+	else
+		csi2->dpcm_decompress = false;
+
+	csi2->contexts[0].format_id = csi2_ctx_map_format(csi2);
+
+	if (csi2->video_out.bpl_padding == 0)
+		csi2->contexts[0].data_offset = 0;
+	else
+		csi2->contexts[0].data_offset = csi2->video_out.bpl_value;
+
+	/*
+	 * Enable end of frame and end of line signals generation for
+	 * context 0. These signals are generated from CSI2 receiver to
+	 * qualify the last pixel of a frame and the last pixel of a line.
+	 * Without enabling the signals CSI2 receiver writes data to memory
+	 * beyond buffer size and/or data line offset is not handled correctly.
+	 */
+	csi2->contexts[0].eof_enabled = 1;
+	csi2->contexts[0].eol_enabled = 1;
+
+	csi2_irq_complexio1_set(isp, csi2, 1);
+	csi2_irq_ctx_set(isp, csi2, 1);
+	csi2_irq_status_set(isp, csi2, 1);
+
+	/* Set configuration (timings, format and links) */
+	csi2_timing_config(isp, csi2, timing);
+	csi2_recv_config(isp, csi2, &csi2->ctrl);
+	csi2_ctx_config(isp, csi2, &csi2->contexts[0]);
+
+	return 0;
+}
+
+/*
+ * csi2_print_status - Prints CSI2 debug information.
+ */
+#define CSI2_PRINT_REGISTER(isp, regs, name)\
+	dev_dbg(isp->dev, "###CSI2 " #name "=0x%08x\n", \
+		isp_reg_readl(isp, regs, ISPCSI2_##name))
+
+static void csi2_print_status(struct isp_csi2_device *csi2)
+{
+	struct isp_device *isp = csi2->isp;
+
+	if (!csi2->available)
+		return;
+
+	dev_dbg(isp->dev, "-------------CSI2 Register dump-------------\n");
+
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSCONFIG);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, SYSSTATUS);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQENABLE);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, IRQSTATUS);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTRL);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_H);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, GNQ);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_CFG);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQSTATUS);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, SHORT_PACKET);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, PHY_IRQENABLE);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, DBG_P);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, TIMING);
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL1(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL2(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_OFST(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PING_ADDR(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_DAT_PONG_ADDR(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQENABLE(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_IRQSTATUS(0));
+	CSI2_PRINT_REGISTER(isp, csi2->regs1, CTX_CTRL3(0));
+
+	dev_dbg(isp->dev, "--------------------------------------------\n");
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+/*
+ * csi2_isr_buffer - Does buffer handling at end-of-frame
+ * when writing to memory.
+ */
+static void csi2_isr_buffer(struct isp_csi2_device *csi2)
+{
+	struct isp_device *isp = csi2->isp;
+	struct isp_buffer *buffer;
+
+	csi2_ctx_enable(isp, csi2, 0, 0);
+
+	buffer = omap3isp_video_buffer_next(&csi2->video_out, 0);
+
+	/*
+	 * Let video queue operation restart engine if there is an underrun
+	 * condition.
+	 */
+	if (buffer == NULL)
+		return;
+
+	csi2_set_outaddr(csi2, buffer->isp_addr);
+	csi2_ctx_enable(isp, csi2, 0, 1);
+}
+
+static void csi2_isr_ctx(struct isp_csi2_device *csi2,
+			 struct isp_csi2_ctx_cfg *ctx)
+{
+	struct isp_device *isp = csi2->isp;
+	unsigned int n = ctx->ctxnum;
+	u32 status;
+
+	status = isp_reg_readl(isp, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
+	isp_reg_writel(isp, status, csi2->regs1, ISPCSI2_CTX_IRQSTATUS(n));
+
+	/* Propagate frame number */
+	if (status & ISPCSI2_CTX_IRQSTATUS_FS_IRQ) {
+		struct isp_pipeline *pipe =
+				     to_isp_pipeline(&csi2->subdev.entity);
+		if (pipe->do_propagation)
+			atomic_inc(&pipe->frame_number);
+	}
+
+	if (!(status & ISPCSI2_CTX_IRQSTATUS_FE_IRQ))
+		return;
+
+	/* Skip interrupts until we reach the frame skip count. The CSI2 will be
+	 * automatically disabled, as the frame skip count has been programmed
+	 * in the CSI2_CTx_CTRL1::COUNT field, so reenable it.
+	 *
+	 * It would have been nice to rely on the FRAME_NUMBER interrupt instead
+	 * but it turned out that the interrupt is only generated when the CSI2
+	 * writes to memory (the CSI2_CTx_CTRL1::COUNT field is decreased
+	 * correctly and reaches 0 when data is forwarded to the video port only
+	 * but no interrupt arrives). Maybe a CSI2 hardware bug.
+	 */
+	if (csi2->frame_skip) {
+		csi2->frame_skip--;
+		if (csi2->frame_skip == 0) {
+			ctx->format_id = csi2_ctx_map_format(csi2);
+			csi2_ctx_config(isp, csi2, ctx);
+			csi2_ctx_enable(isp, csi2, n, 1);
+		}
+		return;
+	}
+
+	if (csi2->output & CSI2_OUTPUT_MEMORY)
+		csi2_isr_buffer(csi2);
+}
+
+/*
+ * omap3isp_csi2_isr - CSI2 interrupt handling.
+ *
+ * Return -EIO on Transmission error
+ */
+int omap3isp_csi2_isr(struct isp_csi2_device *csi2)
+{
+	u32 csi2_irqstatus, cpxio1_irqstatus;
+	struct isp_device *isp = csi2->isp;
+	int retval = 0;
+
+	if (!csi2->available)
+		return -ENODEV;
+
+	csi2_irqstatus = isp_reg_readl(isp, csi2->regs1, ISPCSI2_IRQSTATUS);
+	isp_reg_writel(isp, csi2_irqstatus, csi2->regs1, ISPCSI2_IRQSTATUS);
+
+	/* Failure Cases */
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ) {
+		cpxio1_irqstatus = isp_reg_readl(isp, csi2->regs1,
+						 ISPCSI2_PHY_IRQSTATUS);
+		isp_reg_writel(isp, cpxio1_irqstatus,
+			       csi2->regs1, ISPCSI2_PHY_IRQSTATUS);
+		dev_dbg(isp->dev, "CSI2: ComplexIO Error IRQ "
+			"%x\n", cpxio1_irqstatus);
+		retval = -EIO;
+	}
+
+	if (csi2_irqstatus & (ISPCSI2_IRQSTATUS_OCP_ERR_IRQ |
+			      ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ |
+			      ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ |
+			      ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ |
+			      ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ)) {
+		dev_dbg(isp->dev, "CSI2 Err:"
+			" OCP:%d,"
+			" Short_pack:%d,"
+			" ECC:%d,"
+			" CPXIO2:%d,"
+			" FIFO_OVF:%d,"
+			"\n",
+			(csi2_irqstatus &
+			 ISPCSI2_IRQSTATUS_OCP_ERR_IRQ) ? 1 : 0,
+			(csi2_irqstatus &
+			 ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ) ? 1 : 0,
+			(csi2_irqstatus &
+			 ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ) ? 1 : 0,
+			(csi2_irqstatus &
+			 ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ) ? 1 : 0,
+			(csi2_irqstatus &
+			 ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ) ? 1 : 0);
+		retval = -EIO;
+	}
+
+	if (omap3isp_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
+		return 0;
+
+	/* Successful cases */
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_CONTEXT(0))
+		csi2_isr_ctx(csi2, &csi2->contexts[0]);
+
+	if (csi2_irqstatus & ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ)
+		dev_dbg(isp->dev, "CSI2: ECC correction done\n");
+
+	return retval;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP video operations
+ */
+
+/*
+ * csi2_queue - Queues the first buffer when using memory output
+ * @video: The video node
+ * @buffer: buffer to queue
+ */
+static int csi2_queue(struct isp_video *video, struct isp_buffer *buffer)
+{
+	struct isp_device *isp = video->isp;
+	struct isp_csi2_device *csi2 = &isp->isp_csi2a;
+
+	csi2_set_outaddr(csi2, buffer->isp_addr);
+
+	/*
+	 * If streaming was enabled before there was a buffer queued
+	 * or underrun happened in the ISR, the hardware was not enabled
+	 * and DMA queue flag ISP_VIDEO_DMAQUEUE_UNDERRUN is still set.
+	 * Enable it now.
+	 */
+	if (csi2->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_UNDERRUN) {
+		/* Enable / disable context 0 and IRQs */
+		csi2_if_enable(isp, csi2, 1);
+		csi2_ctx_enable(isp, csi2, 0, 1);
+		isp_video_dmaqueue_flags_clr(&csi2->video_out);
+	}
+
+	return 0;
+}
+
+static const struct isp_video_operations csi2_ispvideo_ops = {
+	.queue = csi2_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+static struct v4l2_mbus_framefmt *
+__csi2_get_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+		  unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_format(fh, pad);
+	else
+		return &csi2->formats[pad];
+}
+
+static void
+csi2_try_format(struct isp_csi2_device *csi2, struct v4l2_subdev_fh *fh,
+		unsigned int pad, struct v4l2_mbus_framefmt *fmt,
+		enum v4l2_subdev_format_whence which)
+{
+	enum v4l2_mbus_pixelcode pixelcode;
+	struct v4l2_mbus_framefmt *format;
+	const struct isp_format_info *info;
+	unsigned int i;
+
+	switch (pad) {
+	case CSI2_PAD_SINK:
+		/* Clamp the width and height to valid range (1-8191). */
+		for (i = 0; i < ARRAY_SIZE(csi2_input_fmts); i++) {
+			if (fmt->code == csi2_input_fmts[i])
+				break;
+		}
+
+		/* If not found, use SGRBG10 as default */
+		if (i >= ARRAY_SIZE(csi2_input_fmts))
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+
+		fmt->width = clamp_t(u32, fmt->width, 1, 8191);
+		fmt->height = clamp_t(u32, fmt->height, 1, 8191);
+		break;
+
+	case CSI2_PAD_SOURCE:
+		/* Source format same as sink format, except for DPCM
+		 * compression.
+		 */
+		pixelcode = fmt->code;
+		format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK, which);
+		memcpy(fmt, format, sizeof(*fmt));
+
+		/*
+		 * Only Allow DPCM decompression, and check that the
+		 * pattern is preserved
+		 */
+		info = omap3isp_video_format_info(fmt->code);
+		if (info->uncompressed == pixelcode)
+			fmt->code = pixelcode;
+		break;
+	}
+
+	/* RGB, non-interlaced */
+	fmt->colorspace = V4L2_COLORSPACE_SRGB;
+	fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * csi2_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh     : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int csi2_enum_mbus_code(struct v4l2_subdev *sd,
+			       struct v4l2_subdev_fh *fh,
+			       struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+	const struct isp_format_info *info;
+
+	if (code->pad == CSI2_PAD_SINK) {
+		if (code->index >= ARRAY_SIZE(csi2_input_fmts))
+			return -EINVAL;
+
+		code->code = csi2_input_fmts[code->index];
+	} else {
+		format = __csi2_get_format(csi2, fh, CSI2_PAD_SINK,
+					   V4L2_SUBDEV_FORMAT_TRY);
+		switch (code->index) {
+		case 0:
+			/* Passthrough sink pad code */
+			code->code = format->code;
+			break;
+		case 1:
+			/* Uncompressed code */
+			info = omap3isp_video_format_info(format->code);
+			if (info->uncompressed == format->code)
+				return -EINVAL;
+
+			code->code = info->uncompressed;
+			break;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return 0;
+}
+
+static int csi2_enum_frame_size(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh,
+				struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt format;
+
+	if (fse->index != 0)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = 1;
+	format.height = 1;
+	csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->min_width = format.width;
+	fse->min_height = format.height;
+
+	if (format.code != fse->code)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = -1;
+	format.height = -1;
+	csi2_try_format(csi2, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->max_width = format.width;
+	fse->max_height = format.height;
+
+	return 0;
+}
+
+/*
+ * csi2_get_format - Handle get format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int csi2_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+/*
+ * csi2_set_format - Handle set format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int csi2_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			   struct v4l2_subdev_format *fmt)
+{
+	struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __csi2_get_format(csi2, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	csi2_try_format(csi2, fh, fmt->pad, &fmt->format, fmt->which);
+	*format = fmt->format;
+
+	/* Propagate the format from sink to source */
+	if (fmt->pad == CSI2_PAD_SINK) {
+		format = __csi2_get_format(csi2, fh, CSI2_PAD_SOURCE,
+					   fmt->which);
+		*format = fmt->format;
+		csi2_try_format(csi2, fh, CSI2_PAD_SOURCE, format, fmt->which);
+	}
+
+	return 0;
+}
+
+/*
+ * csi2_init_formats - Initialize formats on all pads
+ * @sd: ISP CSI2 V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int csi2_init_formats(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_subdev_format format;
+
+	memset(&format, 0, sizeof(format));
+	format.pad = CSI2_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format.format.width = 4096;
+	format.format.height = 4096;
+	csi2_set_format(sd, fh, &format);
+
+	return 0;
+}
+
+/*
+ * csi2_set_stream - Enable/Disable streaming on the CSI2 module
+ * @sd: ISP CSI2 V4L2 subdevice
+ * @enable: ISP pipeline stream state
+ *
+ * Return 0 on success or a negative error code otherwise.
+ */
+static int csi2_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+	struct isp_device *isp = csi2->isp;
+	struct isp_pipeline *pipe = to_isp_pipeline(&csi2->subdev.entity);
+	struct isp_video *video_out = &csi2->video_out;
+
+	switch (enable) {
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		if (omap3isp_csiphy_acquire(csi2->phy) < 0)
+			return -ENODEV;
+		csi2->use_fs_irq = pipe->do_propagation;
+		if (csi2->output & CSI2_OUTPUT_MEMORY)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
+		csi2_configure(csi2);
+		csi2_print_status(csi2);
+
+		/*
+		 * When outputting to memory with no buffer available, let the
+		 * buffer queue handler start the hardware. A DMA queue flag
+		 * ISP_VIDEO_DMAQUEUE_QUEUED will be set as soon as there is
+		 * a buffer available.
+		 */
+		if (csi2->output & CSI2_OUTPUT_MEMORY &&
+		    !(video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED))
+			break;
+		/* Enable context 0 and IRQs */
+		atomic_set(&csi2->stopping, 0);
+		csi2_ctx_enable(isp, csi2, 0, 1);
+		csi2_if_enable(isp, csi2, 1);
+		isp_video_dmaqueue_flags_clr(video_out);
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+		if (csi2->state == ISP_PIPELINE_STREAM_STOPPED)
+			return 0;
+		if (omap3isp_module_sync_idle(&sd->entity, &csi2->wait,
+					      &csi2->stopping))
+			dev_dbg(isp->dev, "%s: module stop timeout.\n",
+				sd->name);
+		csi2_ctx_enable(isp, csi2, 0, 0);
+		csi2_if_enable(isp, csi2, 0);
+		csi2_irq_ctx_set(isp, csi2, 0);
+		omap3isp_csiphy_release(csi2->phy);
+		isp_video_dmaqueue_flags_clr(video_out);
+		omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_CSI2A_WRITE);
+		break;
+	}
+
+	csi2->state = enable;
+	return 0;
+}
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops csi2_video_ops = {
+	.s_stream = csi2_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops csi2_pad_ops = {
+	.enum_mbus_code = csi2_enum_mbus_code,
+	.enum_frame_size = csi2_enum_frame_size,
+	.get_fmt = csi2_get_format,
+	.set_fmt = csi2_set_format,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops csi2_ops = {
+	.video = &csi2_video_ops,
+	.pad = &csi2_pad_ops,
+};
+
+/* subdev internal operations */
+static const struct v4l2_subdev_internal_ops csi2_internal_ops = {
+	.open = csi2_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * csi2_link_setup - Setup CSI2 connections.
+ * @entity : Pointer to media entity structure
+ * @local  : Pointer to local pad array
+ * @remote : Pointer to remote pad array
+ * @flags  : Link flags
+ * return -EINVAL or zero on success
+ */
+static int csi2_link_setup(struct media_entity *entity,
+			   const struct media_pad *local,
+			   const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct isp_csi2_device *csi2 = v4l2_get_subdevdata(sd);
+	struct isp_csi2_ctrl_cfg *ctrl = &csi2->ctrl;
+
+	/*
+	 * The ISP core doesn't support pipelines with multiple video outputs.
+	 * Revisit this when it will be implemented, and return -EBUSY for now.
+	 */
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case CSI2_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (csi2->output & ~CSI2_OUTPUT_MEMORY)
+				return -EBUSY;
+			csi2->output |= CSI2_OUTPUT_MEMORY;
+		} else {
+			csi2->output &= ~CSI2_OUTPUT_MEMORY;
+		}
+		break;
+
+	case CSI2_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (csi2->output & ~CSI2_OUTPUT_CCDC)
+				return -EBUSY;
+			csi2->output |= CSI2_OUTPUT_CCDC;
+		} else {
+			csi2->output &= ~CSI2_OUTPUT_CCDC;
+		}
+		break;
+
+	default:
+		/* Link from camera to CSI2 is fixed... */
+		return -EINVAL;
+	}
+
+	ctrl->vp_only_enable =
+		(csi2->output & CSI2_OUTPUT_MEMORY) ? false : true;
+	ctrl->vp_clk_enable = !!(csi2->output & CSI2_OUTPUT_CCDC);
+
+	return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations csi2_media_ops = {
+	.link_setup = csi2_link_setup,
+};
+
+/*
+ * csi2_init_entities - Initialize subdev and media entity.
+ * @csi2: Pointer to csi2 structure.
+ * return -ENOMEM or zero on success
+ */
+static int csi2_init_entities(struct isp_csi2_device *csi2)
+{
+	struct v4l2_subdev *sd = &csi2->subdev;
+	struct media_pad *pads = csi2->pads;
+	struct media_entity *me = &sd->entity;
+	int ret;
+
+	v4l2_subdev_init(sd, &csi2_ops);
+	sd->internal_ops = &csi2_internal_ops;
+	strlcpy(sd->name, "OMAP3 ISP CSI2a", sizeof(sd->name));
+
+	sd->grp_id = 1 << 16;	/* group ID for isp subdevs */
+	v4l2_set_subdevdata(sd, csi2);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	pads[CSI2_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+	pads[CSI2_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+
+	me->ops = &csi2_media_ops;
+	ret = media_entity_init(me, CSI2_PADS_NUM, pads, 0);
+	if (ret < 0)
+		return ret;
+
+	csi2_init_formats(sd, NULL);
+
+	/* Video device node */
+	csi2->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	csi2->video_out.ops = &csi2_ispvideo_ops;
+	csi2->video_out.bpl_alignment = 32;
+	csi2->video_out.bpl_zero_padding = 1;
+	csi2->video_out.bpl_max = 0x1ffe0;
+	csi2->video_out.isp = csi2->isp;
+	csi2->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 3;
+
+	ret = omap3isp_video_init(&csi2->video_out, "CSI2a");
+	if (ret < 0)
+		return ret;
+
+	/* Connect the CSI2 subdev to the video node. */
+	ret = media_entity_create_link(&csi2->subdev.entity, CSI2_PAD_SOURCE,
+				       &csi2->video_out.video.entity, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2)
+{
+	media_entity_cleanup(&csi2->subdev.entity);
+
+	v4l2_device_unregister_subdev(&csi2->subdev);
+	omap3isp_video_unregister(&csi2->video_out);
+}
+
+int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
+				    struct v4l2_device *vdev)
+{
+	int ret;
+
+	/* Register the subdev and video nodes. */
+	ret = v4l2_device_register_subdev(vdev, &csi2->subdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&csi2->video_out, vdev);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+error:
+	omap3isp_csi2_unregister_entities(csi2);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP CSI2 initialisation and cleanup
+ */
+
+/*
+ * omap3isp_csi2_cleanup - Routine for module driver cleanup
+ */
+void omap3isp_csi2_cleanup(struct isp_device *isp)
+{
+}
+
+/*
+ * omap3isp_csi2_init - Routine for module driver init
+ */
+int omap3isp_csi2_init(struct isp_device *isp)
+{
+	struct isp_csi2_device *csi2a = &isp->isp_csi2a;
+	struct isp_csi2_device *csi2c = &isp->isp_csi2c;
+	int ret;
+
+	csi2a->isp = isp;
+	csi2a->available = 1;
+	csi2a->regs1 = OMAP3_ISP_IOMEM_CSI2A_REGS1;
+	csi2a->regs2 = OMAP3_ISP_IOMEM_CSI2A_REGS2;
+	csi2a->phy = &isp->isp_csiphy2;
+	csi2a->state = ISP_PIPELINE_STREAM_STOPPED;
+	init_waitqueue_head(&csi2a->wait);
+
+	ret = csi2_init_entities(csi2a);
+	if (ret < 0)
+		goto fail;
+
+	if (isp->revision == ISP_REVISION_15_0) {
+		csi2c->isp = isp;
+		csi2c->available = 1;
+		csi2c->regs1 = OMAP3_ISP_IOMEM_CSI2C_REGS1;
+		csi2c->regs2 = OMAP3_ISP_IOMEM_CSI2C_REGS2;
+		csi2c->phy = &isp->isp_csiphy1;
+		csi2c->state = ISP_PIPELINE_STREAM_STOPPED;
+		init_waitqueue_head(&csi2c->wait);
+	}
+
+	return 0;
+fail:
+	omap3isp_csi2_cleanup(isp);
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsi2.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsi2.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsi2.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsi2.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,166 @@
+/*
+ * ispcsi2.h
+ *
+ * TI OMAP3 ISP - CSI2 module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_CSI2_H
+#define OMAP3_ISP_CSI2_H
+
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+struct isp_csiphy;
+
+/* This is not an exhaustive list */
+enum isp_csi2_pix_formats {
+	CSI2_PIX_FMT_OTHERS = 0,
+	CSI2_PIX_FMT_YUV422_8BIT = 0x1e,
+	CSI2_PIX_FMT_YUV422_8BIT_VP = 0x9e,
+	CSI2_PIX_FMT_RAW10_EXP16 = 0xab,
+	CSI2_PIX_FMT_RAW10_EXP16_VP = 0x12f,
+	CSI2_PIX_FMT_RAW8 = 0x2a,
+	CSI2_PIX_FMT_RAW8_DPCM10_EXP16 = 0x2aa,
+	CSI2_PIX_FMT_RAW8_DPCM10_VP = 0x32a,
+	CSI2_PIX_FMT_RAW8_VP = 0x12a,
+	CSI2_USERDEF_8BIT_DATA1_DPCM10_VP = 0x340,
+	CSI2_USERDEF_8BIT_DATA1_DPCM10 = 0x2c0,
+	CSI2_USERDEF_8BIT_DATA1 = 0x40,
+};
+
+enum isp_csi2_irqevents {
+	OCP_ERR_IRQ = 0x4000,
+	SHORT_PACKET_IRQ = 0x2000,
+	ECC_CORRECTION_IRQ = 0x1000,
+	ECC_NO_CORRECTION_IRQ = 0x800,
+	COMPLEXIO2_ERR_IRQ = 0x400,
+	COMPLEXIO1_ERR_IRQ = 0x200,
+	FIFO_OVF_IRQ = 0x100,
+	CONTEXT7 = 0x80,
+	CONTEXT6 = 0x40,
+	CONTEXT5 = 0x20,
+	CONTEXT4 = 0x10,
+	CONTEXT3 = 0x8,
+	CONTEXT2 = 0x4,
+	CONTEXT1 = 0x2,
+	CONTEXT0 = 0x1,
+};
+
+enum isp_csi2_ctx_irqevents {
+	CTX_ECC_CORRECTION = 0x100,
+	CTX_LINE_NUMBER = 0x80,
+	CTX_FRAME_NUMBER = 0x40,
+	CTX_CS = 0x20,
+	CTX_LE = 0x8,
+	CTX_LS = 0x4,
+	CTX_FE = 0x2,
+	CTX_FS = 0x1,
+};
+
+enum isp_csi2_frame_mode {
+	ISP_CSI2_FRAME_IMMEDIATE,
+	ISP_CSI2_FRAME_AFTERFEC,
+};
+
+#define ISP_CSI2_MAX_CTX_NUM	7
+
+struct isp_csi2_ctx_cfg {
+	u8 ctxnum;		/* context number 0 - 7 */
+	u8 dpcm_decompress;
+
+	/* Fields in CSI2_CTx_CTRL2 - locked by CSI2_CTx_CTRL1.CTX_EN */
+	u8 virtual_id;
+	u16 format_id;		/* as in CSI2_CTx_CTRL2[9:0] */
+	u8 dpcm_predictor;	/* 1: simple, 0: advanced */
+
+	/* Fields in CSI2_CTx_CTRL1/3 - Shadowed */
+	u16 alpha;
+	u16 data_offset;
+	u32 ping_addr;
+	u32 pong_addr;
+	u8 eof_enabled;
+	u8 eol_enabled;
+	u8 checksum_enabled;
+	u8 enabled;
+};
+
+struct isp_csi2_timing_cfg {
+	u8 ionum;			/* IO1 or IO2 as in CSI2_TIMING */
+	unsigned force_rx_mode:1;
+	unsigned stop_state_16x:1;
+	unsigned stop_state_4x:1;
+	u16 stop_state_counter;
+};
+
+struct isp_csi2_ctrl_cfg {
+	bool vp_clk_enable;
+	bool vp_only_enable;
+	u8 vp_out_ctrl;
+	enum isp_csi2_frame_mode frame_mode;
+	bool ecc_enable;
+	bool if_enable;
+};
+
+#define CSI2_PAD_SINK		0
+#define CSI2_PAD_SOURCE		1
+#define CSI2_PADS_NUM		2
+
+#define CSI2_OUTPUT_CCDC	(1 << 0)
+#define CSI2_OUTPUT_MEMORY	(1 << 1)
+
+struct isp_csi2_device {
+	struct v4l2_subdev subdev;
+	struct media_pad pads[CSI2_PADS_NUM];
+	struct v4l2_mbus_framefmt formats[CSI2_PADS_NUM];
+
+	struct isp_video video_out;
+	struct isp_device *isp;
+
+	u8 available;		/* Is the IP present on the silicon? */
+
+	/* mem resources - enums as defined in enum isp_mem_resources */
+	u8 regs1;
+	u8 regs2;
+
+	u32 output; /* output to CCDC, memory or both? */
+	bool dpcm_decompress;
+	unsigned int frame_skip;
+	bool use_fs_irq;
+
+	struct isp_csiphy *phy;
+	struct isp_csi2_ctx_cfg contexts[ISP_CSI2_MAX_CTX_NUM + 1];
+	struct isp_csi2_timing_cfg timing[2];
+	struct isp_csi2_ctrl_cfg ctrl;
+	enum isp_pipeline_stream_state state;
+	wait_queue_head_t wait;
+	atomic_t stopping;
+};
+
+int omap3isp_csi2_isr(struct isp_csi2_device *csi2);
+int omap3isp_csi2_reset(struct isp_csi2_device *csi2);
+int omap3isp_csi2_init(struct isp_device *isp);
+void omap3isp_csi2_cleanup(struct isp_device *isp);
+void omap3isp_csi2_unregister_entities(struct isp_csi2_device *csi2);
+int omap3isp_csi2_register_entities(struct isp_csi2_device *csi2,
+				    struct v4l2_device *vdev);
+#endif	/* OMAP3_ISP_CSI2_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsiphy.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsiphy.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsiphy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsiphy.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,247 @@
+/*
+ * ispcsiphy.c
+ *
+ * TI OMAP3 ISP - CSI PHY module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/delay.h>
+#include <linux/device.h>
+#include <linux/regulator/consumer.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispcsiphy.h"
+
+/*
+ * csiphy_lanes_config - Configuration of CSIPHY lanes.
+ *
+ * Updates HW configuration.
+ * Called with phy->mutex taken.
+ */
+static void csiphy_lanes_config(struct isp_csiphy *phy)
+{
+	unsigned int i;
+	u32 reg;
+
+	reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG);
+
+	for (i = 0; i < phy->num_data_lanes; i++) {
+		reg &= ~(ISPCSI2_PHY_CFG_DATA_POL_MASK(i + 1) |
+			 ISPCSI2_PHY_CFG_DATA_POSITION_MASK(i + 1));
+		reg |= (phy->lanes.data[i].pol <<
+			ISPCSI2_PHY_CFG_DATA_POL_SHIFT(i + 1));
+		reg |= (phy->lanes.data[i].pos <<
+			ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(i + 1));
+	}
+
+	reg &= ~(ISPCSI2_PHY_CFG_CLOCK_POL_MASK |
+		 ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK);
+	reg |= phy->lanes.clk.pol << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT;
+	reg |= phy->lanes.clk.pos << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT;
+
+	isp_reg_writel(phy->isp, reg, phy->cfg_regs, ISPCSI2_PHY_CFG);
+}
+
+/*
+ * csiphy_power_autoswitch_enable
+ * @enable: Sets or clears the autoswitch function enable flag.
+ */
+static void csiphy_power_autoswitch_enable(struct isp_csiphy *phy, bool enable)
+{
+	isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
+			ISPCSI2_PHY_CFG_PWR_AUTO,
+			enable ? ISPCSI2_PHY_CFG_PWR_AUTO : 0);
+}
+
+/*
+ * csiphy_set_power
+ * @power: Power state to be set.
+ *
+ * Returns 0 if successful, or -EBUSY if the retry count is exceeded.
+ */
+static int csiphy_set_power(struct isp_csiphy *phy, u32 power)
+{
+	u32 reg;
+	u8 retry_count;
+
+	isp_reg_clr_set(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG,
+			ISPCSI2_PHY_CFG_PWR_CMD_MASK, power);
+
+	retry_count = 0;
+	do {
+		udelay(50);
+		reg = isp_reg_readl(phy->isp, phy->cfg_regs, ISPCSI2_PHY_CFG) &
+				    ISPCSI2_PHY_CFG_PWR_STATUS_MASK;
+
+		if (reg != power >> 2)
+			retry_count++;
+
+	} while ((reg != power >> 2) && (retry_count < 100));
+
+	if (retry_count == 100) {
+		printk(KERN_ERR "CSI2 CIO set power failed!\n");
+		return -EBUSY;
+	}
+
+	return 0;
+}
+
+/*
+ * csiphy_dphy_config - Configure CSI2 D-PHY parameters.
+ *
+ * Called with phy->mutex taken.
+ */
+static void csiphy_dphy_config(struct isp_csiphy *phy)
+{
+	u32 reg;
+
+	/* Set up ISPCSIPHY_REG0 */
+	reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG0);
+
+	reg &= ~(ISPCSIPHY_REG0_THS_TERM_MASK |
+		 ISPCSIPHY_REG0_THS_SETTLE_MASK);
+	reg |= phy->dphy.ths_term << ISPCSIPHY_REG0_THS_TERM_SHIFT;
+	reg |= phy->dphy.ths_settle << ISPCSIPHY_REG0_THS_SETTLE_SHIFT;
+
+	isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG0);
+
+	/* Set up ISPCSIPHY_REG1 */
+	reg = isp_reg_readl(phy->isp, phy->phy_regs, ISPCSIPHY_REG1);
+
+	reg &= ~(ISPCSIPHY_REG1_TCLK_TERM_MASK |
+		 ISPCSIPHY_REG1_TCLK_MISS_MASK |
+		 ISPCSIPHY_REG1_TCLK_SETTLE_MASK);
+	reg |= phy->dphy.tclk_term << ISPCSIPHY_REG1_TCLK_TERM_SHIFT;
+	reg |= phy->dphy.tclk_miss << ISPCSIPHY_REG1_TCLK_MISS_SHIFT;
+	reg |= phy->dphy.tclk_settle << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT;
+
+	isp_reg_writel(phy->isp, reg, phy->phy_regs, ISPCSIPHY_REG1);
+}
+
+static int csiphy_config(struct isp_csiphy *phy,
+			 struct isp_csiphy_dphy_cfg *dphy,
+			 struct isp_csiphy_lanes_cfg *lanes)
+{
+	unsigned int used_lanes = 0;
+	unsigned int i;
+
+	/* Clock and data lanes verification */
+	for (i = 0; i < phy->num_data_lanes; i++) {
+		if (lanes->data[i].pol > 1 || lanes->data[i].pos > 3)
+			return -EINVAL;
+
+		if (used_lanes & (1 << lanes->data[i].pos))
+			return -EINVAL;
+
+		used_lanes |= 1 << lanes->data[i].pos;
+	}
+
+	if (lanes->clk.pol > 1 || lanes->clk.pos > 3)
+		return -EINVAL;
+
+	if (lanes->clk.pos == 0 || used_lanes & (1 << lanes->clk.pos))
+		return -EINVAL;
+
+	mutex_lock(&phy->mutex);
+	phy->dphy = *dphy;
+	phy->lanes = *lanes;
+	mutex_unlock(&phy->mutex);
+
+	return 0;
+}
+
+int omap3isp_csiphy_acquire(struct isp_csiphy *phy)
+{
+	int rval;
+
+	if (phy->vdd == NULL) {
+		dev_err(phy->isp->dev, "Power regulator for CSI PHY not "
+			"available\n");
+		return -ENODEV;
+	}
+
+	mutex_lock(&phy->mutex);
+
+	rval = regulator_enable(phy->vdd);
+	if (rval < 0)
+		goto done;
+
+	omap3isp_csi2_reset(phy->csi2);
+
+	csiphy_dphy_config(phy);
+	csiphy_lanes_config(phy);
+
+	rval = csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_ON);
+	if (rval) {
+		regulator_disable(phy->vdd);
+		goto done;
+	}
+
+	csiphy_power_autoswitch_enable(phy, true);
+	phy->phy_in_use = 1;
+
+done:
+	mutex_unlock(&phy->mutex);
+	return rval;
+}
+
+void omap3isp_csiphy_release(struct isp_csiphy *phy)
+{
+	mutex_lock(&phy->mutex);
+	if (phy->phy_in_use) {
+		csiphy_power_autoswitch_enable(phy, false);
+		csiphy_set_power(phy, ISPCSI2_PHY_CFG_PWR_CMD_OFF);
+		regulator_disable(phy->vdd);
+		phy->phy_in_use = 0;
+	}
+	mutex_unlock(&phy->mutex);
+}
+
+/*
+ * omap3isp_csiphy_init - Initialize the CSI PHY frontends
+ */
+int omap3isp_csiphy_init(struct isp_device *isp)
+{
+	struct isp_csiphy *phy1 = &isp->isp_csiphy1;
+	struct isp_csiphy *phy2 = &isp->isp_csiphy2;
+
+	isp->platform_cb.csiphy_config = csiphy_config;
+
+	phy2->isp = isp;
+	phy2->csi2 = &isp->isp_csi2a;
+	phy2->num_data_lanes = ISP_CSIPHY2_NUM_DATA_LANES;
+	phy2->cfg_regs = OMAP3_ISP_IOMEM_CSI2A_REGS1;
+	phy2->phy_regs = OMAP3_ISP_IOMEM_CSIPHY2;
+	mutex_init(&phy2->mutex);
+
+	if (isp->revision == ISP_REVISION_15_0) {
+		phy1->isp = isp;
+		phy1->csi2 = &isp->isp_csi2c;
+		phy1->num_data_lanes = ISP_CSIPHY1_NUM_DATA_LANES;
+		phy1->cfg_regs = OMAP3_ISP_IOMEM_CSI2C_REGS1;
+		phy1->phy_regs = OMAP3_ISP_IOMEM_CSIPHY1;
+		mutex_init(&phy1->mutex);
+	}
+
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsiphy.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsiphy.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispcsiphy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispcsiphy.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,74 @@
+/*
+ * ispcsiphy.h
+ *
+ * TI OMAP3 ISP - CSI PHY module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_CSI_PHY_H
+#define OMAP3_ISP_CSI_PHY_H
+
+struct isp_csi2_device;
+struct regulator;
+
+struct csiphy_lane {
+	u8 pos;
+	u8 pol;
+};
+
+#define ISP_CSIPHY2_NUM_DATA_LANES	2
+#define ISP_CSIPHY1_NUM_DATA_LANES	1
+
+struct isp_csiphy_lanes_cfg {
+	struct csiphy_lane data[ISP_CSIPHY2_NUM_DATA_LANES];
+	struct csiphy_lane clk;
+};
+
+struct isp_csiphy_dphy_cfg {
+	u8 ths_term;
+	u8 ths_settle;
+	u8 tclk_term;
+	unsigned tclk_miss:1;
+	u8 tclk_settle;
+};
+
+struct isp_csiphy {
+	struct isp_device *isp;
+	struct mutex mutex;	/* serialize csiphy configuration */
+	u8 phy_in_use;
+	struct isp_csi2_device *csi2;
+	struct regulator *vdd;
+
+	/* mem resources - enums as defined in enum isp_mem_resources */
+	unsigned int cfg_regs;
+	unsigned int phy_regs;
+
+	u8 num_data_lanes;	/* number of CSI2 Data Lanes supported */
+	struct isp_csiphy_lanes_cfg lanes;
+	struct isp_csiphy_dphy_cfg dphy;
+};
+
+int omap3isp_csiphy_acquire(struct isp_csiphy *phy);
+void omap3isp_csiphy_release(struct isp_csiphy *phy);
+int omap3isp_csiphy_init(struct isp_device *isp);
+
+#endif	/* OMAP3_ISP_CSI_PHY_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isp.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isp.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isp.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isp.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,431 @@
+/*
+ * isp.h
+ *
+ * TI OMAP3 ISP - Core
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_CORE_H
+#define OMAP3_ISP_CORE_H
+
+#include <media/v4l2-device.h>
+#include <linux/device.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/wait.h>
+#include <plat/iommu.h>
+#include <plat/iovmm.h>
+
+#include "ispstat.h"
+#include "ispccdc.h"
+#include "ispreg.h"
+#include "ispresizer.h"
+#include "isppreview.h"
+#include "ispcsiphy.h"
+#include "ispcsi2.h"
+#include "ispccp2.h"
+
+#define IOMMU_FLAG (IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
+
+#define ISP_TOK_TERM		0xFFFFFFFF	/*
+						 * terminating token for ISP
+						 * modules reg list
+						 */
+#define to_isp_device(ptr_module)				\
+	container_of(ptr_module, struct isp_device, isp_##ptr_module)
+#define to_device(ptr_module)						\
+	(to_isp_device(ptr_module)->dev)
+
+enum isp_mem_resources {
+	OMAP3_ISP_IOMEM_MAIN,
+	OMAP3_ISP_IOMEM_CCP2,
+	OMAP3_ISP_IOMEM_CCDC,
+	OMAP3_ISP_IOMEM_HIST,
+	OMAP3_ISP_IOMEM_H3A,
+	OMAP3_ISP_IOMEM_PREV,
+	OMAP3_ISP_IOMEM_RESZ,
+	OMAP3_ISP_IOMEM_SBL,
+	OMAP3_ISP_IOMEM_CSI2A_REGS1,
+	OMAP3_ISP_IOMEM_CSIPHY2,
+	OMAP3_ISP_IOMEM_CSI2A_REGS2,
+	OMAP3_ISP_IOMEM_CSI2C_REGS1,
+	OMAP3_ISP_IOMEM_CSIPHY1,
+	OMAP3_ISP_IOMEM_CSI2C_REGS2,
+	OMAP3_ISP_IOMEM_LAST
+};
+
+enum isp_sbl_resource {
+	OMAP3_ISP_SBL_CSI1_READ		= 0x1,
+	OMAP3_ISP_SBL_CSI1_WRITE	= 0x2,
+	OMAP3_ISP_SBL_CSI2A_WRITE	= 0x4,
+	OMAP3_ISP_SBL_CSI2C_WRITE	= 0x8,
+	OMAP3_ISP_SBL_CCDC_LSC_READ	= 0x10,
+	OMAP3_ISP_SBL_CCDC_WRITE	= 0x20,
+	OMAP3_ISP_SBL_PREVIEW_READ	= 0x40,
+	OMAP3_ISP_SBL_PREVIEW_WRITE	= 0x80,
+	OMAP3_ISP_SBL_RESIZER_READ	= 0x100,
+	OMAP3_ISP_SBL_RESIZER_WRITE	= 0x200,
+};
+
+enum isp_subclk_resource {
+	OMAP3_ISP_SUBCLK_CCDC		= (1 << 0),
+	OMAP3_ISP_SUBCLK_H3A		= (1 << 1),
+	OMAP3_ISP_SUBCLK_HIST		= (1 << 2),
+	OMAP3_ISP_SUBCLK_PREVIEW	= (1 << 3),
+	OMAP3_ISP_SUBCLK_RESIZER	= (1 << 4),
+};
+
+enum isp_interface_type {
+	ISP_INTERFACE_PARALLEL,
+	ISP_INTERFACE_CSI2A_PHY2,
+	ISP_INTERFACE_CCP2B_PHY1,
+	ISP_INTERFACE_CCP2B_PHY2,
+	ISP_INTERFACE_CSI2C_PHY1,
+};
+
+/* ISP: OMAP 34xx ES 1.0 */
+#define ISP_REVISION_1_0		0x10
+/* ISP2: OMAP 34xx ES 2.0, 2.1 and 3.0 */
+#define ISP_REVISION_2_0		0x20
+/* ISP2P: OMAP 36xx */
+#define ISP_REVISION_15_0		0xF0
+
+/*
+ * struct isp_res_mapping - Map ISP io resources to ISP revision.
+ * @isp_rev: ISP_REVISION_x_x
+ * @map: bitmap for enum isp_mem_resources
+ */
+struct isp_res_mapping {
+	u32 isp_rev;
+	u32 map;
+};
+
+/*
+ * struct isp_reg - Structure for ISP register values.
+ * @reg: 32-bit Register address.
+ * @val: 32-bit Register value.
+ */
+struct isp_reg {
+	enum isp_mem_resources mmio_range;
+	u32 reg;
+	u32 val;
+};
+
+/**
+ * struct isp_parallel_platform_data - Parallel interface platform data
+ * @data_lane_shift: Data lane shifter
+ *		0 - CAMEXT[13:0] -> CAM[13:0]
+ *		1 - CAMEXT[13:2] -> CAM[11:0]
+ *		2 - CAMEXT[13:4] -> CAM[9:0]
+ *		3 - CAMEXT[13:6] -> CAM[7:0]
+ * @clk_pol: Pixel clock polarity
+ *		0 - Non Inverted, 1 - Inverted
+ * @bridge: CCDC Bridge input control
+ *		ISPCTRL_PAR_BRIDGE_DISABLE - Disable
+ *		ISPCTRL_PAR_BRIDGE_LENDIAN - Little endian
+ *		ISPCTRL_PAR_BRIDGE_BENDIAN - Big endian
+ */
+struct isp_parallel_platform_data {
+	unsigned int data_lane_shift:2;
+	unsigned int clk_pol:1;
+	unsigned int bridge:4;
+};
+
+/**
+ * struct isp_ccp2_platform_data - CCP2 interface platform data
+ * @strobe_clk_pol: Strobe/clock polarity
+ *		0 - Non Inverted, 1 - Inverted
+ * @crc: Enable the cyclic redundancy check
+ * @ccp2_mode: Enable CCP2 compatibility mode
+ *		0 - MIPI-CSI1 mode, 1 - CCP2 mode
+ * @phy_layer: Physical layer selection
+ *		ISPCCP2_CTRL_PHY_SEL_CLOCK - Data/clock physical layer
+ *		ISPCCP2_CTRL_PHY_SEL_STROBE - Data/strobe physical layer
+ * @vpclk_div: Video port output clock control
+ */
+struct isp_ccp2_platform_data {
+	unsigned int strobe_clk_pol:1;
+	unsigned int crc:1;
+	unsigned int ccp2_mode:1;
+	unsigned int phy_layer:1;
+	unsigned int vpclk_div:2;
+};
+
+/**
+ * struct isp_csi2_platform_data - CSI2 interface platform data
+ * @crc: Enable the cyclic redundancy check
+ * @vpclk_div: Video port output clock control
+ */
+struct isp_csi2_platform_data {
+	unsigned crc:1;
+	unsigned vpclk_div:2;
+};
+
+struct isp_subdev_i2c_board_info {
+	struct i2c_board_info *board_info;
+	int i2c_adapter_id;
+};
+
+struct isp_v4l2_subdevs_group {
+	struct isp_subdev_i2c_board_info *subdevs;
+	enum isp_interface_type interface;
+	union {
+		struct isp_parallel_platform_data parallel;
+		struct isp_ccp2_platform_data ccp2;
+		struct isp_csi2_platform_data csi2;
+	} bus; /* gcc < 4.6.0 chokes on anonymous union initializers */
+};
+
+struct isp_platform_data {
+	struct isp_v4l2_subdevs_group *subdevs;
+	void (*set_constraints)(struct isp_device *isp, bool enable);
+};
+
+struct isp_platform_callback {
+	u32 (*set_xclk)(struct isp_device *isp, u32 xclk, u8 xclksel);
+	int (*csiphy_config)(struct isp_csiphy *phy,
+			     struct isp_csiphy_dphy_cfg *dphy,
+			     struct isp_csiphy_lanes_cfg *lanes);
+	void (*set_pixel_clock)(struct isp_device *isp, unsigned int pixelclk);
+};
+
+/*
+ * struct isp_device - ISP device structure.
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @revision: Stores current ISP module revision.
+ * @irq_num: Currently used IRQ number.
+ * @mmio_base: Array with kernel base addresses for ioremapped ISP register
+ *             regions.
+ * @mmio_base_phys: Array with physical L4 bus addresses for ISP register
+ *                  regions.
+ * @mmio_size: Array with ISP register regions size in bytes.
+ * @raw_dmamask: Raw DMA mask
+ * @stat_lock: Spinlock for handling statistics
+ * @isp_mutex: Mutex for serializing requests to ISP.
+ * @has_context: Context has been saved at least once and can be restored.
+ * @ref_count: Reference count for handling multiple ISP requests.
+ * @cam_ick: Pointer to camera interface clock structure.
+ * @cam_mclk: Pointer to camera functional clock structure.
+ * @dpll4_m5_ck: Pointer to DPLL4 M5 clock structure.
+ * @csi2_fck: Pointer to camera CSI2 complexIO clock structure.
+ * @l3_ick: Pointer to OMAP3 L3 bus interface clock.
+ * @irq: Currently attached ISP ISR callbacks information structure.
+ * @isp_af: Pointer to current settings for ISP AutoFocus SCM.
+ * @isp_hist: Pointer to current settings for ISP Histogram SCM.
+ * @isp_h3a: Pointer to current settings for ISP Auto Exposure and
+ *           White Balance SCM.
+ * @isp_res: Pointer to current settings for ISP Resizer.
+ * @isp_prev: Pointer to current settings for ISP Preview.
+ * @isp_ccdc: Pointer to current settings for ISP CCDC.
+ * @iommu: Pointer to requested IOMMU instance for ISP.
+ * @platform_cb: ISP driver callback function pointers for platform code
+ *
+ * This structure is used to store the OMAP ISP Information.
+ */
+struct isp_device {
+	struct v4l2_device v4l2_dev;
+	struct media_device media_dev;
+	struct device *dev;
+	u32 revision;
+
+	/* platform HW resources */
+	struct isp_platform_data *pdata;
+	unsigned int irq_num;
+
+	void __iomem *mmio_base[OMAP3_ISP_IOMEM_LAST];
+	unsigned long mmio_base_phys[OMAP3_ISP_IOMEM_LAST];
+	resource_size_t mmio_size[OMAP3_ISP_IOMEM_LAST];
+
+	u64 raw_dmamask;
+
+	/* ISP Obj */
+	spinlock_t stat_lock;	/* common lock for statistic drivers */
+	struct mutex isp_mutex;	/* For handling ref_count field */
+	bool needs_reset;
+	int has_context;
+	int ref_count;
+	unsigned int autoidle;
+	u32 xclk_divisor[2];	/* Two clocks, a and b. */
+#define ISP_CLK_CAM_ICK		0
+#define ISP_CLK_CAM_MCLK	1
+#define ISP_CLK_DPLL4_M5_CK	2
+#define ISP_CLK_CSI2_FCK	3
+#define ISP_CLK_L3_ICK		4
+	struct clk *clock[5];
+
+	/* ISP modules */
+	struct ispstat isp_af;
+	struct ispstat isp_aewb;
+	struct ispstat isp_hist;
+	struct isp_res_device isp_res;
+	struct isp_prev_device isp_prev;
+	struct isp_ccdc_device isp_ccdc;
+	struct isp_csi2_device isp_csi2a;
+	struct isp_csi2_device isp_csi2c;
+	struct isp_ccp2_device isp_ccp2;
+	struct isp_csiphy isp_csiphy1;
+	struct isp_csiphy isp_csiphy2;
+
+	unsigned int sbl_resources;
+	unsigned int subclk_resources;
+
+	struct iommu *iommu;
+
+	struct isp_platform_callback platform_cb;
+};
+
+#define v4l2_dev_to_isp_device(dev) \
+	container_of(dev, struct isp_device, v4l2_dev)
+
+void omap3isp_hist_dma_done(struct isp_device *isp);
+
+void omap3isp_flush(struct isp_device *isp);
+
+int omap3isp_module_sync_idle(struct media_entity *me, wait_queue_head_t *wait,
+			      atomic_t *stopping);
+
+int omap3isp_module_sync_is_stopping(wait_queue_head_t *wait,
+				     atomic_t *stopping);
+
+int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
+				 enum isp_pipeline_stream_state state);
+void omap3isp_configure_bridge(struct isp_device *isp,
+			       enum ccdc_input_entity input,
+			       const struct isp_parallel_platform_data *pdata,
+			       unsigned int shift);
+
+#define ISP_XCLK_NONE			0
+#define ISP_XCLK_A			1
+#define ISP_XCLK_B			2
+
+struct isp_device *omap3isp_get(struct isp_device *isp);
+void omap3isp_put(struct isp_device *isp);
+
+void omap3isp_print_status(struct isp_device *isp);
+
+void omap3isp_sbl_enable(struct isp_device *isp, enum isp_sbl_resource res);
+void omap3isp_sbl_disable(struct isp_device *isp, enum isp_sbl_resource res);
+
+void omap3isp_subclk_enable(struct isp_device *isp,
+			    enum isp_subclk_resource res);
+void omap3isp_subclk_disable(struct isp_device *isp,
+			     enum isp_subclk_resource res);
+
+int omap3isp_pipeline_pm_use(struct media_entity *entity, int use);
+
+int omap3isp_register_entities(struct platform_device *pdev,
+			       struct v4l2_device *v4l2_dev);
+void omap3isp_unregister_entities(struct platform_device *pdev);
+
+/*
+ * isp_reg_readl - Read value of an OMAP3 ISP register
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @isp_mmio_range: Range to which the register offset refers to.
+ * @reg_offset: Register offset to read from.
+ *
+ * Returns an unsigned 32 bit value with the required register contents.
+ */
+static inline
+u32 isp_reg_readl(struct isp_device *isp, enum isp_mem_resources isp_mmio_range,
+		  u32 reg_offset)
+{
+	return __raw_readl(isp->mmio_base[isp_mmio_range] + reg_offset);
+}
+
+/*
+ * isp_reg_writel - Write value to an OMAP3 ISP register
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @reg_value: 32 bit value to write to the register.
+ * @isp_mmio_range: Range to which the register offset refers to.
+ * @reg_offset: Register offset to write into.
+ */
+static inline
+void isp_reg_writel(struct isp_device *isp, u32 reg_value,
+		    enum isp_mem_resources isp_mmio_range, u32 reg_offset)
+{
+	__raw_writel(reg_value, isp->mmio_base[isp_mmio_range] + reg_offset);
+}
+
+/*
+ * isp_reg_and - Clear individual bits in an OMAP3 ISP register
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @mmio_range: Range to which the register offset refers to.
+ * @reg: Register offset to work on.
+ * @clr_bits: 32 bit value which would be cleared in the register.
+ */
+static inline
+void isp_reg_clr(struct isp_device *isp, enum isp_mem_resources mmio_range,
+		 u32 reg, u32 clr_bits)
+{
+	u32 v = isp_reg_readl(isp, mmio_range, reg);
+
+	isp_reg_writel(isp, v & ~clr_bits, mmio_range, reg);
+}
+
+/*
+ * isp_reg_set - Set individual bits in an OMAP3 ISP register
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @mmio_range: Range to which the register offset refers to.
+ * @reg: Register offset to work on.
+ * @set_bits: 32 bit value which would be set in the register.
+ */
+static inline
+void isp_reg_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
+		 u32 reg, u32 set_bits)
+{
+	u32 v = isp_reg_readl(isp, mmio_range, reg);
+
+	isp_reg_writel(isp, v | set_bits, mmio_range, reg);
+}
+
+/*
+ * isp_reg_clr_set - Clear and set invidial bits in an OMAP3 ISP register
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @mmio_range: Range to which the register offset refers to.
+ * @reg: Register offset to work on.
+ * @clr_bits: 32 bit value which would be cleared in the register.
+ * @set_bits: 32 bit value which would be set in the register.
+ *
+ * The clear operation is done first, and then the set operation.
+ */
+static inline
+void isp_reg_clr_set(struct isp_device *isp, enum isp_mem_resources mmio_range,
+		     u32 reg, u32 clr_bits, u32 set_bits)
+{
+	u32 v = isp_reg_readl(isp, mmio_range, reg);
+
+	isp_reg_writel(isp, (v & ~clr_bits) | set_bits, mmio_range, reg);
+}
+
+static inline enum v4l2_buf_type
+isp_pad_buffer_type(const struct v4l2_subdev *subdev, int pad)
+{
+	if (pad >= subdev->entity.num_pads)
+		return 0;
+
+	if (subdev->entity.pads[pad].flags & MEDIA_PAD_FL_SINK)
+		return V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	else
+		return V4L2_BUF_TYPE_VIDEO_CAPTURE;
+}
+
+#endif	/* OMAP3_ISP_CORE_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isph3a_aewb.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isph3a_aewb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isph3a_aewb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isph3a_aewb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,374 @@
+/*
+ * isph3a.c
+ *
+ * TI OMAP3 ISP - H3A module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/slab.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+#include "isph3a.h"
+#include "ispstat.h"
+
+/*
+ * h3a_aewb_update_regs - Helper function to update h3a registers.
+ */
+static void h3a_aewb_setup_regs(struct ispstat *aewb, void *priv)
+{
+	struct omap3isp_h3a_aewb_config *conf = priv;
+	u32 pcr;
+	u32 win1;
+	u32 start;
+	u32 blk;
+	u32 subwin;
+
+	if (aewb->state == ISPSTAT_DISABLED)
+		return;
+
+	isp_reg_writel(aewb->isp, aewb->active_buf->iommu_addr,
+		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWBUFST);
+
+	if (!aewb->update)
+		return;
+
+	/* Converting config metadata into reg values */
+	pcr = conf->saturation_limit << ISPH3A_PCR_AEW_AVE2LMT_SHIFT;
+	pcr |= !!conf->alaw_enable << ISPH3A_PCR_AEW_ALAW_EN_SHIFT;
+
+	win1 = ((conf->win_height >> 1) - 1) << ISPH3A_AEWWIN1_WINH_SHIFT;
+	win1 |= ((conf->win_width >> 1) - 1) << ISPH3A_AEWWIN1_WINW_SHIFT;
+	win1 |= (conf->ver_win_count - 1) << ISPH3A_AEWWIN1_WINVC_SHIFT;
+	win1 |= (conf->hor_win_count - 1) << ISPH3A_AEWWIN1_WINHC_SHIFT;
+
+	start = conf->hor_win_start << ISPH3A_AEWINSTART_WINSH_SHIFT;
+	start |= conf->ver_win_start << ISPH3A_AEWINSTART_WINSV_SHIFT;
+
+	blk = conf->blk_ver_win_start << ISPH3A_AEWINBLK_WINSV_SHIFT;
+	blk |= ((conf->blk_win_height >> 1) - 1) << ISPH3A_AEWINBLK_WINH_SHIFT;
+
+	subwin = ((conf->subsample_ver_inc >> 1) - 1) <<
+		 ISPH3A_AEWSUBWIN_AEWINCV_SHIFT;
+	subwin |= ((conf->subsample_hor_inc >> 1) - 1) <<
+		  ISPH3A_AEWSUBWIN_AEWINCH_SHIFT;
+
+	isp_reg_writel(aewb->isp, win1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWWIN1);
+	isp_reg_writel(aewb->isp, start, OMAP3_ISP_IOMEM_H3A,
+		       ISPH3A_AEWINSTART);
+	isp_reg_writel(aewb->isp, blk, OMAP3_ISP_IOMEM_H3A, ISPH3A_AEWINBLK);
+	isp_reg_writel(aewb->isp, subwin, OMAP3_ISP_IOMEM_H3A,
+		       ISPH3A_AEWSUBWIN);
+	isp_reg_clr_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
+			ISPH3A_PCR_AEW_MASK, pcr);
+
+	aewb->update = 0;
+	aewb->config_counter += aewb->inc_config;
+	aewb->inc_config = 0;
+	aewb->buf_size = conf->buf_size;
+}
+
+static void h3a_aewb_enable(struct ispstat *aewb, int enable)
+{
+	if (enable) {
+		isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
+			    ISPH3A_PCR_AEW_EN);
+		/* This bit is already set if AF is enabled */
+		if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
+			isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+				    ISPCTRL_H3A_CLK_EN);
+	} else {
+		isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
+			    ISPH3A_PCR_AEW_EN);
+		/* This bit can't be cleared if AF is enabled */
+		if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
+			isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+				    ISPCTRL_H3A_CLK_EN);
+	}
+}
+
+static int h3a_aewb_busy(struct ispstat *aewb)
+{
+	return isp_reg_readl(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
+						& ISPH3A_PCR_BUSYAEAWB;
+}
+
+static u32 h3a_aewb_get_buf_size(struct omap3isp_h3a_aewb_config *conf)
+{
+	/* Number of configured windows + extra row for black data */
+	u32 win_count = (conf->ver_win_count + 1) * conf->hor_win_count;
+
+	/*
+	 * Unsaturated block counts for each 8 windows.
+	 * 1 extra for the last (win_count % 8) windows if win_count is not
+	 * divisible by 8.
+	 */
+	win_count += (win_count + 7) / 8;
+
+	return win_count * AEWB_PACKET_SIZE;
+}
+
+static int h3a_aewb_validate_params(struct ispstat *aewb, void *new_conf)
+{
+	struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
+	u32 buf_size;
+
+	if (unlikely(user_cfg->saturation_limit >
+		     OMAP3ISP_AEWB_MAX_SATURATION_LIM))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
+		     user_cfg->win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
+		     user_cfg->win_height & 0x01))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->win_width < OMAP3ISP_AEWB_MIN_WIN_W ||
+		     user_cfg->win_width > OMAP3ISP_AEWB_MAX_WIN_W ||
+		     user_cfg->win_width & 0x01))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->ver_win_count < OMAP3ISP_AEWB_MIN_WINVC ||
+		     user_cfg->ver_win_count > OMAP3ISP_AEWB_MAX_WINVC))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->hor_win_count < OMAP3ISP_AEWB_MIN_WINHC ||
+		     user_cfg->hor_win_count > OMAP3ISP_AEWB_MAX_WINHC))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->hor_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->blk_ver_win_start > OMAP3ISP_AEWB_MAX_WINSTART))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->blk_win_height < OMAP3ISP_AEWB_MIN_WIN_H ||
+		     user_cfg->blk_win_height > OMAP3ISP_AEWB_MAX_WIN_H ||
+		     user_cfg->blk_win_height & 0x01))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->subsample_ver_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
+		     user_cfg->subsample_ver_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
+		     user_cfg->subsample_ver_inc & 0x01))
+		return -EINVAL;
+
+	if (unlikely(user_cfg->subsample_hor_inc < OMAP3ISP_AEWB_MIN_SUB_INC ||
+		     user_cfg->subsample_hor_inc > OMAP3ISP_AEWB_MAX_SUB_INC ||
+		     user_cfg->subsample_hor_inc & 0x01))
+		return -EINVAL;
+
+	buf_size = h3a_aewb_get_buf_size(user_cfg);
+	if (buf_size > user_cfg->buf_size)
+		user_cfg->buf_size = buf_size;
+	else if (user_cfg->buf_size > OMAP3ISP_AEWB_MAX_BUF_SIZE)
+		user_cfg->buf_size = OMAP3ISP_AEWB_MAX_BUF_SIZE;
+
+	return 0;
+}
+
+/*
+ * h3a_aewb_set_params - Helper function to check & store user given params.
+ * @new_conf: Pointer to AE and AWB parameters struct.
+ *
+ * As most of them are busy-lock registers, need to wait until AEW_BUSY = 0 to
+ * program them during ISR.
+ */
+static void h3a_aewb_set_params(struct ispstat *aewb, void *new_conf)
+{
+	struct omap3isp_h3a_aewb_config *user_cfg = new_conf;
+	struct omap3isp_h3a_aewb_config *cur_cfg = aewb->priv;
+	int update = 0;
+
+	if (cur_cfg->saturation_limit != user_cfg->saturation_limit) {
+		cur_cfg->saturation_limit = user_cfg->saturation_limit;
+		update = 1;
+	}
+	if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
+		cur_cfg->alaw_enable = user_cfg->alaw_enable;
+		update = 1;
+	}
+	if (cur_cfg->win_height != user_cfg->win_height) {
+		cur_cfg->win_height = user_cfg->win_height;
+		update = 1;
+	}
+	if (cur_cfg->win_width != user_cfg->win_width) {
+		cur_cfg->win_width = user_cfg->win_width;
+		update = 1;
+	}
+	if (cur_cfg->ver_win_count != user_cfg->ver_win_count) {
+		cur_cfg->ver_win_count = user_cfg->ver_win_count;
+		update = 1;
+	}
+	if (cur_cfg->hor_win_count != user_cfg->hor_win_count) {
+		cur_cfg->hor_win_count = user_cfg->hor_win_count;
+		update = 1;
+	}
+	if (cur_cfg->ver_win_start != user_cfg->ver_win_start) {
+		cur_cfg->ver_win_start = user_cfg->ver_win_start;
+		update = 1;
+	}
+	if (cur_cfg->hor_win_start != user_cfg->hor_win_start) {
+		cur_cfg->hor_win_start = user_cfg->hor_win_start;
+		update = 1;
+	}
+	if (cur_cfg->blk_ver_win_start != user_cfg->blk_ver_win_start) {
+		cur_cfg->blk_ver_win_start = user_cfg->blk_ver_win_start;
+		update = 1;
+	}
+	if (cur_cfg->blk_win_height != user_cfg->blk_win_height) {
+		cur_cfg->blk_win_height = user_cfg->blk_win_height;
+		update = 1;
+	}
+	if (cur_cfg->subsample_ver_inc != user_cfg->subsample_ver_inc) {
+		cur_cfg->subsample_ver_inc = user_cfg->subsample_ver_inc;
+		update = 1;
+	}
+	if (cur_cfg->subsample_hor_inc != user_cfg->subsample_hor_inc) {
+		cur_cfg->subsample_hor_inc = user_cfg->subsample_hor_inc;
+		update = 1;
+	}
+
+	if (update || !aewb->configured) {
+		aewb->inc_config++;
+		aewb->update = 1;
+		cur_cfg->buf_size = h3a_aewb_get_buf_size(cur_cfg);
+	}
+}
+
+static long h3a_aewb_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct ispstat *stat = v4l2_get_subdevdata(sd);
+
+	switch (cmd) {
+	case VIDIOC_OMAP3ISP_AEWB_CFG:
+		return omap3isp_stat_config(stat, arg);
+	case VIDIOC_OMAP3ISP_STAT_REQ:
+		return omap3isp_stat_request_statistics(stat, arg);
+	case VIDIOC_OMAP3ISP_STAT_EN: {
+		unsigned long *en = arg;
+		return omap3isp_stat_enable(stat, !!*en);
+	}
+	}
+
+	return -ENOIOCTLCMD;
+}
+
+static const struct ispstat_ops h3a_aewb_ops = {
+	.validate_params	= h3a_aewb_validate_params,
+	.set_params		= h3a_aewb_set_params,
+	.setup_regs		= h3a_aewb_setup_regs,
+	.enable			= h3a_aewb_enable,
+	.busy			= h3a_aewb_busy,
+};
+
+static const struct v4l2_subdev_core_ops h3a_aewb_subdev_core_ops = {
+	.ioctl = h3a_aewb_ioctl,
+	.subscribe_event = omap3isp_stat_subscribe_event,
+	.unsubscribe_event = omap3isp_stat_unsubscribe_event,
+};
+
+static const struct v4l2_subdev_video_ops h3a_aewb_subdev_video_ops = {
+	.s_stream = omap3isp_stat_s_stream,
+};
+
+static const struct v4l2_subdev_ops h3a_aewb_subdev_ops = {
+	.core = &h3a_aewb_subdev_core_ops,
+	.video = &h3a_aewb_subdev_video_ops,
+};
+
+/*
+ * omap3isp_h3a_aewb_init - Module Initialisation.
+ */
+int omap3isp_h3a_aewb_init(struct isp_device *isp)
+{
+	struct ispstat *aewb = &isp->isp_aewb;
+	struct omap3isp_h3a_aewb_config *aewb_cfg;
+	struct omap3isp_h3a_aewb_config *aewb_recover_cfg;
+	int ret;
+
+	aewb_cfg = kzalloc(sizeof(*aewb_cfg), GFP_KERNEL);
+	if (!aewb_cfg)
+		return -ENOMEM;
+
+	memset(aewb, 0, sizeof(*aewb));
+	aewb->ops = &h3a_aewb_ops;
+	aewb->priv = aewb_cfg;
+	aewb->dma_ch = -1;
+	aewb->event_type = V4L2_EVENT_OMAP3ISP_AEWB;
+	aewb->isp = isp;
+
+	/* Set recover state configuration */
+	aewb_recover_cfg = kzalloc(sizeof(*aewb_recover_cfg), GFP_KERNEL);
+	if (!aewb_recover_cfg) {
+		dev_err(aewb->isp->dev, "AEWB: cannot allocate memory for "
+					"recover configuration.\n");
+		ret = -ENOMEM;
+		goto err_recover_alloc;
+	}
+
+	aewb_recover_cfg->saturation_limit = OMAP3ISP_AEWB_MAX_SATURATION_LIM;
+	aewb_recover_cfg->win_height = OMAP3ISP_AEWB_MIN_WIN_H;
+	aewb_recover_cfg->win_width = OMAP3ISP_AEWB_MIN_WIN_W;
+	aewb_recover_cfg->ver_win_count = OMAP3ISP_AEWB_MIN_WINVC;
+	aewb_recover_cfg->hor_win_count = OMAP3ISP_AEWB_MIN_WINHC;
+	aewb_recover_cfg->blk_ver_win_start = aewb_recover_cfg->ver_win_start +
+		aewb_recover_cfg->win_height * aewb_recover_cfg->ver_win_count;
+	aewb_recover_cfg->blk_win_height = OMAP3ISP_AEWB_MIN_WIN_H;
+	aewb_recover_cfg->subsample_ver_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
+	aewb_recover_cfg->subsample_hor_inc = OMAP3ISP_AEWB_MIN_SUB_INC;
+
+	if (h3a_aewb_validate_params(aewb, aewb_recover_cfg)) {
+		dev_err(aewb->isp->dev, "AEWB: recover configuration is "
+					"invalid.\n");
+		ret = -EINVAL;
+		goto err_conf;
+	}
+
+	aewb_recover_cfg->buf_size = h3a_aewb_get_buf_size(aewb_recover_cfg);
+	aewb->recover_priv = aewb_recover_cfg;
+
+	ret = omap3isp_stat_init(aewb, "AEWB", &h3a_aewb_subdev_ops);
+	if (ret)
+		goto err_conf;
+
+	return 0;
+
+err_conf:
+	kfree(aewb_recover_cfg);
+err_recover_alloc:
+	kfree(aewb_cfg);
+
+	return ret;
+}
+
+/*
+ * omap3isp_h3a_aewb_cleanup - Module exit.
+ */
+void omap3isp_h3a_aewb_cleanup(struct isp_device *isp)
+{
+	kfree(isp->isp_aewb.priv);
+	kfree(isp->isp_aewb.recover_priv);
+	omap3isp_stat_free(&isp->isp_aewb);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isph3a_af.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isph3a_af.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isph3a_af.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isph3a_af.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,429 @@
+/*
+ * isph3a_af.c
+ *
+ * TI OMAP3 ISP - H3A AF module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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
+ */
+
+/* Linux specific include files */
+#include <linux/device.h>
+#include <linux/slab.h>
+
+#include "isp.h"
+#include "isph3a.h"
+#include "ispstat.h"
+
+#define IS_OUT_OF_BOUNDS(value, min, max)		\
+	(((value) < (min)) || ((value) > (max)))
+
+static void h3a_af_setup_regs(struct ispstat *af, void *priv)
+{
+	struct omap3isp_h3a_af_config *conf = priv;
+	u32 pcr;
+	u32 pax1;
+	u32 pax2;
+	u32 paxstart;
+	u32 coef;
+	u32 base_coef_set0;
+	u32 base_coef_set1;
+	int index;
+
+	if (af->state == ISPSTAT_DISABLED)
+		return;
+
+	isp_reg_writel(af->isp, af->active_buf->iommu_addr, OMAP3_ISP_IOMEM_H3A,
+		       ISPH3A_AFBUFST);
+
+	if (!af->update)
+		return;
+
+	/* Configure Hardware Registers */
+	pax1 = ((conf->paxel.width >> 1) - 1) << AF_PAXW_SHIFT;
+	/* Set height in AFPAX1 */
+	pax1 |= (conf->paxel.height >> 1) - 1;
+	isp_reg_writel(af->isp, pax1, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX1);
+
+	/* Configure AFPAX2 Register */
+	/* Set Line Increment in AFPAX2 Register */
+	pax2 = ((conf->paxel.line_inc >> 1) - 1) << AF_LINE_INCR_SHIFT;
+	/* Set Vertical Count */
+	pax2 |= (conf->paxel.v_cnt - 1) << AF_VT_COUNT_SHIFT;
+	/* Set Horizontal Count */
+	pax2 |= (conf->paxel.h_cnt - 1);
+	isp_reg_writel(af->isp, pax2, OMAP3_ISP_IOMEM_H3A, ISPH3A_AFPAX2);
+
+	/* Configure PAXSTART Register */
+	/*Configure Horizontal Start */
+	paxstart = conf->paxel.h_start << AF_HZ_START_SHIFT;
+	/* Configure Vertical Start */
+	paxstart |= conf->paxel.v_start;
+	isp_reg_writel(af->isp, paxstart, OMAP3_ISP_IOMEM_H3A,
+		       ISPH3A_AFPAXSTART);
+
+	/*SetIIRSH Register */
+	isp_reg_writel(af->isp, conf->iir.h_start,
+		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AFIIRSH);
+
+	base_coef_set0 = ISPH3A_AFCOEF010;
+	base_coef_set1 = ISPH3A_AFCOEF110;
+	for (index = 0; index <= 8; index += 2) {
+		/*Set IIR Filter0 Coefficients */
+		coef = 0;
+		coef |= conf->iir.coeff_set0[index];
+		coef |= conf->iir.coeff_set0[index + 1] <<
+			AF_COEF_SHIFT;
+		isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
+			       base_coef_set0);
+		base_coef_set0 += AFCOEF_OFFSET;
+
+		/*Set IIR Filter1 Coefficients */
+		coef = 0;
+		coef |= conf->iir.coeff_set1[index];
+		coef |= conf->iir.coeff_set1[index + 1] <<
+			AF_COEF_SHIFT;
+		isp_reg_writel(af->isp, coef, OMAP3_ISP_IOMEM_H3A,
+			       base_coef_set1);
+		base_coef_set1 += AFCOEF_OFFSET;
+	}
+	/* set AFCOEF0010 Register */
+	isp_reg_writel(af->isp, conf->iir.coeff_set0[10],
+		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF0010);
+	/* set AFCOEF1010 Register */
+	isp_reg_writel(af->isp, conf->iir.coeff_set1[10],
+		       OMAP3_ISP_IOMEM_H3A, ISPH3A_AFCOEF1010);
+
+	/* PCR Register */
+	/* Set RGB Position */
+	pcr = conf->rgb_pos << AF_RGBPOS_SHIFT;
+	/* Set Accumulator Mode */
+	if (conf->fvmode == OMAP3ISP_AF_MODE_PEAK)
+		pcr |= AF_FVMODE;
+	/* Set A-law */
+	if (conf->alaw_enable)
+		pcr |= AF_ALAW_EN;
+	/* HMF Configurations */
+	if (conf->hmf.enable) {
+		/* Enable HMF */
+		pcr |= AF_MED_EN;
+		/* Set Median Threshold */
+		pcr |= conf->hmf.threshold << AF_MED_TH_SHIFT;
+	}
+	/* Set PCR Register */
+	isp_reg_clr_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
+			AF_PCR_MASK, pcr);
+
+	af->update = 0;
+	af->config_counter += af->inc_config;
+	af->inc_config = 0;
+	af->buf_size = conf->buf_size;
+}
+
+static void h3a_af_enable(struct ispstat *af, int enable)
+{
+	if (enable) {
+		isp_reg_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
+			    ISPH3A_PCR_AF_EN);
+		/* This bit is already set if AEWB is enabled */
+		if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
+			isp_reg_set(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+				    ISPCTRL_H3A_CLK_EN);
+	} else {
+		isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
+			    ISPH3A_PCR_AF_EN);
+		/* This bit can't be cleared if AEWB is enabled */
+		if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
+			isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+				    ISPCTRL_H3A_CLK_EN);
+	}
+}
+
+static int h3a_af_busy(struct ispstat *af)
+{
+	return isp_reg_readl(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR)
+						& ISPH3A_PCR_BUSYAF;
+}
+
+static u32 h3a_af_get_buf_size(struct omap3isp_h3a_af_config *conf)
+{
+	return conf->paxel.h_cnt * conf->paxel.v_cnt * OMAP3ISP_AF_PAXEL_SIZE;
+}
+
+/* Function to check paxel parameters */
+static int h3a_af_validate_params(struct ispstat *af, void *new_conf)
+{
+	struct omap3isp_h3a_af_config *user_cfg = new_conf;
+	struct omap3isp_h3a_af_paxel *paxel_cfg = &user_cfg->paxel;
+	struct omap3isp_h3a_af_iir *iir_cfg = &user_cfg->iir;
+	int index;
+	u32 buf_size;
+
+	/* Check horizontal Count */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->h_cnt,
+			     OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN,
+			     OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MAX))
+		return -EINVAL;
+
+	/* Check Vertical Count */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->v_cnt,
+			     OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN,
+			     OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MAX))
+		return -EINVAL;
+
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->height, OMAP3ISP_AF_PAXEL_HEIGHT_MIN,
+			     OMAP3ISP_AF_PAXEL_HEIGHT_MAX) ||
+	    paxel_cfg->height % 2)
+		return -EINVAL;
+
+	/* Check width */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->width, OMAP3ISP_AF_PAXEL_WIDTH_MIN,
+			     OMAP3ISP_AF_PAXEL_WIDTH_MAX) ||
+	    paxel_cfg->width % 2)
+		return -EINVAL;
+
+	/* Check Line Increment */
+	if (IS_OUT_OF_BOUNDS(paxel_cfg->line_inc,
+			     OMAP3ISP_AF_PAXEL_INCREMENT_MIN,
+			     OMAP3ISP_AF_PAXEL_INCREMENT_MAX) ||
+	    paxel_cfg->line_inc % 2)
+		return -EINVAL;
+
+	/* Check Horizontal Start */
+	if ((paxel_cfg->h_start < iir_cfg->h_start) ||
+	    IS_OUT_OF_BOUNDS(paxel_cfg->h_start,
+			     OMAP3ISP_AF_PAXEL_HZSTART_MIN,
+			     OMAP3ISP_AF_PAXEL_HZSTART_MAX))
+		return -EINVAL;
+
+	/* Check IIR */
+	for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
+		if ((iir_cfg->coeff_set0[index]) > OMAP3ISP_AF_COEF_MAX)
+			return -EINVAL;
+
+		if ((iir_cfg->coeff_set1[index]) > OMAP3ISP_AF_COEF_MAX)
+			return -EINVAL;
+	}
+
+	if (IS_OUT_OF_BOUNDS(iir_cfg->h_start, OMAP3ISP_AF_IIRSH_MIN,
+			     OMAP3ISP_AF_IIRSH_MAX))
+		return -EINVAL;
+
+	/* Hack: If paxel size is 12, the 10th AF window may be corrupted */
+	if ((paxel_cfg->h_cnt * paxel_cfg->v_cnt > 9) &&
+	    (paxel_cfg->width * paxel_cfg->height == 12))
+		return -EINVAL;
+
+	buf_size = h3a_af_get_buf_size(user_cfg);
+	if (buf_size > user_cfg->buf_size)
+		/* User buf_size request wasn't enough */
+		user_cfg->buf_size = buf_size;
+	else if (user_cfg->buf_size > OMAP3ISP_AF_MAX_BUF_SIZE)
+		user_cfg->buf_size = OMAP3ISP_AF_MAX_BUF_SIZE;
+
+	return 0;
+}
+
+/* Update local parameters */
+static void h3a_af_set_params(struct ispstat *af, void *new_conf)
+{
+	struct omap3isp_h3a_af_config *user_cfg = new_conf;
+	struct omap3isp_h3a_af_config *cur_cfg = af->priv;
+	int update = 0;
+	int index;
+
+	/* alaw */
+	if (cur_cfg->alaw_enable != user_cfg->alaw_enable) {
+		update = 1;
+		goto out;
+	}
+
+	/* hmf */
+	if (cur_cfg->hmf.enable != user_cfg->hmf.enable) {
+		update = 1;
+		goto out;
+	}
+	if (cur_cfg->hmf.threshold != user_cfg->hmf.threshold) {
+		update = 1;
+		goto out;
+	}
+
+	/* rgbpos */
+	if (cur_cfg->rgb_pos != user_cfg->rgb_pos) {
+		update = 1;
+		goto out;
+	}
+
+	/* iir */
+	if (cur_cfg->iir.h_start != user_cfg->iir.h_start) {
+		update = 1;
+		goto out;
+	}
+	for (index = 0; index < OMAP3ISP_AF_NUM_COEF; index++) {
+		if (cur_cfg->iir.coeff_set0[index] !=
+				user_cfg->iir.coeff_set0[index]) {
+			update = 1;
+			goto out;
+		}
+		if (cur_cfg->iir.coeff_set1[index] !=
+				user_cfg->iir.coeff_set1[index]) {
+			update = 1;
+			goto out;
+		}
+	}
+
+	/* paxel */
+	if ((cur_cfg->paxel.width != user_cfg->paxel.width) ||
+	    (cur_cfg->paxel.height != user_cfg->paxel.height) ||
+	    (cur_cfg->paxel.h_start != user_cfg->paxel.h_start) ||
+	    (cur_cfg->paxel.v_start != user_cfg->paxel.v_start) ||
+	    (cur_cfg->paxel.h_cnt != user_cfg->paxel.h_cnt) ||
+	    (cur_cfg->paxel.v_cnt != user_cfg->paxel.v_cnt) ||
+	    (cur_cfg->paxel.line_inc != user_cfg->paxel.line_inc)) {
+		update = 1;
+		goto out;
+	}
+
+	/* af_mode */
+	if (cur_cfg->fvmode != user_cfg->fvmode)
+		update = 1;
+
+out:
+	if (update || !af->configured) {
+		memcpy(cur_cfg, user_cfg, sizeof(*cur_cfg));
+		af->inc_config++;
+		af->update = 1;
+		/*
+		 * User might be asked for a bigger buffer than necessary for
+		 * this configuration. In order to return the right amount of
+		 * data during buffer request, let's calculate the size here
+		 * instead of stick with user_cfg->buf_size.
+		 */
+		cur_cfg->buf_size = h3a_af_get_buf_size(cur_cfg);
+	}
+}
+
+static long h3a_af_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct ispstat *stat = v4l2_get_subdevdata(sd);
+
+	switch (cmd) {
+	case VIDIOC_OMAP3ISP_AF_CFG:
+		return omap3isp_stat_config(stat, arg);
+	case VIDIOC_OMAP3ISP_STAT_REQ:
+		return omap3isp_stat_request_statistics(stat, arg);
+	case VIDIOC_OMAP3ISP_STAT_EN: {
+		int *en = arg;
+		return omap3isp_stat_enable(stat, !!*en);
+	}
+	}
+
+	return -ENOIOCTLCMD;
+
+}
+
+static const struct ispstat_ops h3a_af_ops = {
+	.validate_params	= h3a_af_validate_params,
+	.set_params		= h3a_af_set_params,
+	.setup_regs		= h3a_af_setup_regs,
+	.enable			= h3a_af_enable,
+	.busy			= h3a_af_busy,
+};
+
+static const struct v4l2_subdev_core_ops h3a_af_subdev_core_ops = {
+	.ioctl = h3a_af_ioctl,
+	.subscribe_event = omap3isp_stat_subscribe_event,
+	.unsubscribe_event = omap3isp_stat_unsubscribe_event,
+};
+
+static const struct v4l2_subdev_video_ops h3a_af_subdev_video_ops = {
+	.s_stream = omap3isp_stat_s_stream,
+};
+
+static const struct v4l2_subdev_ops h3a_af_subdev_ops = {
+	.core = &h3a_af_subdev_core_ops,
+	.video = &h3a_af_subdev_video_ops,
+};
+
+/* Function to register the AF character device driver. */
+int omap3isp_h3a_af_init(struct isp_device *isp)
+{
+	struct ispstat *af = &isp->isp_af;
+	struct omap3isp_h3a_af_config *af_cfg;
+	struct omap3isp_h3a_af_config *af_recover_cfg;
+	int ret;
+
+	af_cfg = kzalloc(sizeof(*af_cfg), GFP_KERNEL);
+	if (af_cfg == NULL)
+		return -ENOMEM;
+
+	memset(af, 0, sizeof(*af));
+	af->ops = &h3a_af_ops;
+	af->priv = af_cfg;
+	af->dma_ch = -1;
+	af->event_type = V4L2_EVENT_OMAP3ISP_AF;
+	af->isp = isp;
+
+	/* Set recover state configuration */
+	af_recover_cfg = kzalloc(sizeof(*af_recover_cfg), GFP_KERNEL);
+	if (!af_recover_cfg) {
+		dev_err(af->isp->dev, "AF: cannot allocate memory for recover "
+				      "configuration.\n");
+		ret = -ENOMEM;
+		goto err_recover_alloc;
+	}
+
+	af_recover_cfg->paxel.h_start = OMAP3ISP_AF_PAXEL_HZSTART_MIN;
+	af_recover_cfg->paxel.width = OMAP3ISP_AF_PAXEL_WIDTH_MIN;
+	af_recover_cfg->paxel.height = OMAP3ISP_AF_PAXEL_HEIGHT_MIN;
+	af_recover_cfg->paxel.h_cnt = OMAP3ISP_AF_PAXEL_HORIZONTAL_COUNT_MIN;
+	af_recover_cfg->paxel.v_cnt = OMAP3ISP_AF_PAXEL_VERTICAL_COUNT_MIN;
+	af_recover_cfg->paxel.line_inc = OMAP3ISP_AF_PAXEL_INCREMENT_MIN;
+	if (h3a_af_validate_params(af, af_recover_cfg)) {
+		dev_err(af->isp->dev, "AF: recover configuration is "
+				      "invalid.\n");
+		ret = -EINVAL;
+		goto err_conf;
+	}
+
+	af_recover_cfg->buf_size = h3a_af_get_buf_size(af_recover_cfg);
+	af->recover_priv = af_recover_cfg;
+
+	ret = omap3isp_stat_init(af, "AF", &h3a_af_subdev_ops);
+	if (ret)
+		goto err_conf;
+
+	return 0;
+
+err_conf:
+	kfree(af_recover_cfg);
+err_recover_alloc:
+	kfree(af_cfg);
+
+	return ret;
+}
+
+void omap3isp_h3a_af_cleanup(struct isp_device *isp)
+{
+	kfree(isp->isp_af.priv);
+	kfree(isp->isp_af.recover_priv);
+	omap3isp_stat_free(&isp->isp_af);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isph3a.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isph3a.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isph3a.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isph3a.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,117 @@
+/*
+ * isph3a.h
+ *
+ * TI OMAP3 ISP - H3A AF module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_H3A_H
+#define OMAP3_ISP_H3A_H
+
+#include <linux/omap3isp.h>
+
+/*
+ * ----------
+ * -H3A AEWB-
+ * ----------
+ */
+
+#define AEWB_PACKET_SIZE	16
+#define AEWB_SATURATION_LIMIT	0x3ff
+
+/* Flags for changed registers */
+#define PCR_CHNG		(1 << 0)
+#define AEWWIN1_CHNG		(1 << 1)
+#define AEWINSTART_CHNG		(1 << 2)
+#define AEWINBLK_CHNG		(1 << 3)
+#define AEWSUBWIN_CHNG		(1 << 4)
+#define PRV_WBDGAIN_CHNG	(1 << 5)
+#define PRV_WBGAIN_CHNG		(1 << 6)
+
+/* ISPH3A REGISTERS bits */
+#define ISPH3A_PCR_AF_EN	(1 << 0)
+#define ISPH3A_PCR_AF_ALAW_EN	(1 << 1)
+#define ISPH3A_PCR_AF_MED_EN	(1 << 2)
+#define ISPH3A_PCR_AF_BUSY	(1 << 15)
+#define ISPH3A_PCR_AEW_EN	(1 << 16)
+#define ISPH3A_PCR_AEW_ALAW_EN	(1 << 17)
+#define ISPH3A_PCR_AEW_BUSY	(1 << 18)
+#define ISPH3A_PCR_AEW_MASK	(ISPH3A_PCR_AEW_ALAW_EN | \
+				 ISPH3A_PCR_AEW_AVE2LMT_MASK)
+
+/*
+ * --------
+ * -H3A AF-
+ * --------
+ */
+
+/* Peripheral Revision */
+#define AFPID				0x0
+
+#define AFCOEF_OFFSET			0x00000004	/* COEF base address */
+
+/* PCR fields */
+#define AF_BUSYAF			(1 << 15)
+#define AF_FVMODE			(1 << 14)
+#define AF_RGBPOS			(0x7 << 11)
+#define AF_MED_TH			(0xFF << 3)
+#define AF_MED_EN			(1 << 2)
+#define AF_ALAW_EN			(1 << 1)
+#define AF_EN				(1 << 0)
+#define AF_PCR_MASK			(AF_FVMODE | AF_RGBPOS | AF_MED_TH | \
+					 AF_MED_EN | AF_ALAW_EN)
+
+/* AFPAX1 fields */
+#define AF_PAXW				(0x7F << 16)
+#define AF_PAXH				0x7F
+
+/* AFPAX2 fields */
+#define AF_AFINCV			(0xF << 13)
+#define AF_PAXVC			(0x7F << 6)
+#define AF_PAXHC			0x3F
+
+/* AFPAXSTART fields */
+#define AF_PAXSH			(0xFFF<<16)
+#define AF_PAXSV			0xFFF
+
+/* COEFFICIENT MASK */
+#define AF_COEF_MASK0			0xFFF
+#define AF_COEF_MASK1			(0xFFF<<16)
+
+/* BIT SHIFTS */
+#define AF_RGBPOS_SHIFT			11
+#define AF_MED_TH_SHIFT			3
+#define AF_PAXW_SHIFT			16
+#define AF_LINE_INCR_SHIFT		13
+#define AF_VT_COUNT_SHIFT		6
+#define AF_HZ_START_SHIFT		16
+#define AF_COEF_SHIFT			16
+
+/* Init and cleanup functions */
+int omap3isp_h3a_aewb_init(struct isp_device *isp);
+int omap3isp_h3a_af_init(struct isp_device *isp);
+
+void omap3isp_h3a_aewb_cleanup(struct isp_device *isp);
+void omap3isp_h3a_af_cleanup(struct isp_device *isp);
+
+#endif /* OMAP3_ISP_H3A_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isphist.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isphist.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isphist.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isphist.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,520 @@
+/*
+ * isphist.c
+ *
+ * TI OMAP3 ISP - Histogram module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/delay.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+#include <linux/device.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "isphist.h"
+
+#define HIST_CONFIG_DMA	1
+
+#define HIST_USING_DMA(hist) ((hist)->dma_ch >= 0)
+
+/*
+ * hist_reset_mem - clear Histogram memory before start stats engine.
+ */
+static void hist_reset_mem(struct ispstat *hist)
+{
+	struct isp_device *isp = hist->isp;
+	struct omap3isp_hist_config *conf = hist->priv;
+	unsigned int i;
+
+	isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
+
+	/*
+	 * By setting it, the histogram internal buffer is being cleared at the
+	 * same time it's being read. This bit must be cleared afterwards.
+	 */
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
+
+	/*
+	 * We'll clear 4 words at each iteration for optimization. It avoids
+	 * 3/4 of the jumps. We also know HIST_MEM_SIZE is divisible by 4.
+	 */
+	for (i = OMAP3ISP_HIST_MEM_SIZE / 4; i > 0; i--) {
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+	}
+	isp_reg_clr(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
+
+	hist->wait_acc_frames = conf->num_acc_frames;
+}
+
+static void hist_dma_config(struct ispstat *hist)
+{
+	hist->dma_config.data_type = OMAP_DMA_DATA_TYPE_S32;
+	hist->dma_config.sync_mode = OMAP_DMA_SYNC_ELEMENT;
+	hist->dma_config.frame_count = 1;
+	hist->dma_config.src_amode = OMAP_DMA_AMODE_CONSTANT;
+	hist->dma_config.src_start = OMAP3ISP_HIST_REG_BASE + ISPHIST_DATA;
+	hist->dma_config.dst_amode = OMAP_DMA_AMODE_POST_INC;
+	hist->dma_config.src_or_dst_synch = OMAP_DMA_SRC_SYNC;
+}
+
+/*
+ * hist_setup_regs - Helper function to update Histogram registers.
+ */
+static void hist_setup_regs(struct ispstat *hist, void *priv)
+{
+	struct isp_device *isp = hist->isp;
+	struct omap3isp_hist_config *conf = priv;
+	int c;
+	u32 cnt;
+	u32 wb_gain;
+	u32 reg_hor[OMAP3ISP_HIST_MAX_REGIONS];
+	u32 reg_ver[OMAP3ISP_HIST_MAX_REGIONS];
+
+	if (!hist->update || hist->state == ISPSTAT_DISABLED ||
+	    hist->state == ISPSTAT_DISABLING)
+		return;
+
+	cnt = conf->cfa << ISPHIST_CNT_CFA_SHIFT;
+
+	wb_gain = conf->wg[0] << ISPHIST_WB_GAIN_WG00_SHIFT;
+	wb_gain |= conf->wg[1] << ISPHIST_WB_GAIN_WG01_SHIFT;
+	wb_gain |= conf->wg[2] << ISPHIST_WB_GAIN_WG02_SHIFT;
+	if (conf->cfa == OMAP3ISP_HIST_CFA_BAYER)
+		wb_gain |= conf->wg[3] << ISPHIST_WB_GAIN_WG03_SHIFT;
+
+	/* Regions size and position */
+	for (c = 0; c < OMAP3ISP_HIST_MAX_REGIONS; c++) {
+		if (c < conf->num_regions) {
+			reg_hor[c] = conf->region[c].h_start <<
+				     ISPHIST_REG_START_SHIFT;
+			reg_hor[c] = conf->region[c].h_end <<
+				     ISPHIST_REG_END_SHIFT;
+			reg_ver[c] = conf->region[c].v_start <<
+				     ISPHIST_REG_START_SHIFT;
+			reg_ver[c] = conf->region[c].v_end <<
+				     ISPHIST_REG_END_SHIFT;
+		} else {
+			reg_hor[c] = 0;
+			reg_ver[c] = 0;
+		}
+	}
+
+	cnt |= conf->hist_bins << ISPHIST_CNT_BINS_SHIFT;
+	switch (conf->hist_bins) {
+	case OMAP3ISP_HIST_BINS_256:
+		cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 8) <<
+			ISPHIST_CNT_SHIFT_SHIFT;
+		break;
+	case OMAP3ISP_HIST_BINS_128:
+		cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 7) <<
+			ISPHIST_CNT_SHIFT_SHIFT;
+		break;
+	case OMAP3ISP_HIST_BINS_64:
+		cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 6) <<
+			ISPHIST_CNT_SHIFT_SHIFT;
+		break;
+	default: /* OMAP3ISP_HIST_BINS_32 */
+		cnt |= (ISPHIST_IN_BIT_WIDTH_CCDC - 5) <<
+			ISPHIST_CNT_SHIFT_SHIFT;
+		break;
+	}
+
+	hist_reset_mem(hist);
+
+	isp_reg_writel(isp, cnt, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT);
+	isp_reg_writel(isp, wb_gain,  OMAP3_ISP_IOMEM_HIST, ISPHIST_WB_GAIN);
+	isp_reg_writel(isp, reg_hor[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_HORZ);
+	isp_reg_writel(isp, reg_ver[0], OMAP3_ISP_IOMEM_HIST, ISPHIST_R0_VERT);
+	isp_reg_writel(isp, reg_hor[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_HORZ);
+	isp_reg_writel(isp, reg_ver[1], OMAP3_ISP_IOMEM_HIST, ISPHIST_R1_VERT);
+	isp_reg_writel(isp, reg_hor[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_HORZ);
+	isp_reg_writel(isp, reg_ver[2], OMAP3_ISP_IOMEM_HIST, ISPHIST_R2_VERT);
+	isp_reg_writel(isp, reg_hor[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_HORZ);
+	isp_reg_writel(isp, reg_ver[3], OMAP3_ISP_IOMEM_HIST, ISPHIST_R3_VERT);
+
+	hist->update = 0;
+	hist->config_counter += hist->inc_config;
+	hist->inc_config = 0;
+	hist->buf_size = conf->buf_size;
+}
+
+static void hist_enable(struct ispstat *hist, int enable)
+{
+	if (enable) {
+		isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
+			    ISPHIST_PCR_ENABLE);
+		isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+			    ISPCTRL_HIST_CLK_EN);
+	} else {
+		isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
+			    ISPHIST_PCR_ENABLE);
+		isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
+			    ISPCTRL_HIST_CLK_EN);
+	}
+}
+
+static int hist_busy(struct ispstat *hist)
+{
+	return isp_reg_readl(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR)
+						& ISPHIST_PCR_BUSY;
+}
+
+static void hist_dma_cb(int lch, u16 ch_status, void *data)
+{
+	struct ispstat *hist = data;
+
+	if (ch_status & ~OMAP_DMA_BLOCK_IRQ) {
+		dev_dbg(hist->isp->dev, "hist: DMA error. status = 0x%04x\n",
+			ch_status);
+		omap_stop_dma(lch);
+		hist_reset_mem(hist);
+		atomic_set(&hist->buf_err, 1);
+	}
+	isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
+		    ISPHIST_CNT_CLEAR);
+
+	omap3isp_stat_dma_isr(hist);
+	if (hist->state != ISPSTAT_DISABLED)
+		omap3isp_hist_dma_done(hist->isp);
+}
+
+static int hist_buf_dma(struct ispstat *hist)
+{
+	dma_addr_t dma_addr = hist->active_buf->dma_addr;
+
+	if (unlikely(!dma_addr)) {
+		dev_dbg(hist->isp->dev, "hist: invalid DMA buffer address\n");
+		hist_reset_mem(hist);
+		return STAT_NO_BUF;
+	}
+
+	isp_reg_writel(hist->isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
+	isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
+		    ISPHIST_CNT_CLEAR);
+	omap3isp_flush(hist->isp);
+	hist->dma_config.dst_start = dma_addr;
+	hist->dma_config.elem_count = hist->buf_size / sizeof(u32);
+	omap_set_dma_params(hist->dma_ch, &hist->dma_config);
+
+	omap_start_dma(hist->dma_ch);
+
+	return STAT_BUF_WAITING_DMA;
+}
+
+static int hist_buf_pio(struct ispstat *hist)
+{
+	struct isp_device *isp = hist->isp;
+	u32 *buf = hist->active_buf->virt_addr;
+	unsigned int i;
+
+	if (!buf) {
+		dev_dbg(isp->dev, "hist: invalid PIO buffer address\n");
+		hist_reset_mem(hist);
+		return STAT_NO_BUF;
+	}
+
+	isp_reg_writel(isp, 0, OMAP3_ISP_IOMEM_HIST, ISPHIST_ADDR);
+
+	/*
+	 * By setting it, the histogram internal buffer is being cleared at the
+	 * same time it's being read. This bit must be cleared just after all
+	 * data is acquired.
+	 */
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT, ISPHIST_CNT_CLEAR);
+
+	/*
+	 * We'll read 4 times a 4-bytes-word at each iteration for
+	 * optimization. It avoids 3/4 of the jumps. We also know buf_size is
+	 * divisible by 16.
+	 */
+	for (i = hist->buf_size / 16; i > 0; i--) {
+		*buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		*buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		*buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+		*buf++ = isp_reg_readl(isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_DATA);
+	}
+	isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_CNT,
+		    ISPHIST_CNT_CLEAR);
+
+	return STAT_BUF_DONE;
+}
+
+/*
+ * hist_buf_process - Callback from ISP driver for HIST interrupt.
+ */
+static int hist_buf_process(struct ispstat *hist)
+{
+	struct omap3isp_hist_config *user_cfg = hist->priv;
+	int ret;
+
+	if (atomic_read(&hist->buf_err) || hist->state != ISPSTAT_ENABLED) {
+		hist_reset_mem(hist);
+		return STAT_NO_BUF;
+	}
+
+	if (--(hist->wait_acc_frames))
+		return STAT_NO_BUF;
+
+	if (HIST_USING_DMA(hist))
+		ret = hist_buf_dma(hist);
+	else
+		ret = hist_buf_pio(hist);
+
+	hist->wait_acc_frames = user_cfg->num_acc_frames;
+
+	return ret;
+}
+
+static u32 hist_get_buf_size(struct omap3isp_hist_config *conf)
+{
+	return OMAP3ISP_HIST_MEM_SIZE_BINS(conf->hist_bins) * conf->num_regions;
+}
+
+/*
+ * hist_validate_params - Helper function to check user given params.
+ * @user_cfg: Pointer to user configuration structure.
+ *
+ * Returns 0 on success configuration.
+ */
+static int hist_validate_params(struct ispstat *hist, void *new_conf)
+{
+	struct omap3isp_hist_config *user_cfg = new_conf;
+	int c;
+	u32 buf_size;
+
+	if (user_cfg->cfa > OMAP3ISP_HIST_CFA_FOVEONX3)
+		return -EINVAL;
+
+	/* Regions size and position */
+
+	if ((user_cfg->num_regions < OMAP3ISP_HIST_MIN_REGIONS) ||
+	    (user_cfg->num_regions > OMAP3ISP_HIST_MAX_REGIONS))
+		return -EINVAL;
+
+	/* Regions */
+	for (c = 0; c < user_cfg->num_regions; c++) {
+		if (user_cfg->region[c].h_start & ~ISPHIST_REG_START_END_MASK)
+			return -EINVAL;
+		if (user_cfg->region[c].h_end & ~ISPHIST_REG_START_END_MASK)
+			return -EINVAL;
+		if (user_cfg->region[c].v_start & ~ISPHIST_REG_START_END_MASK)
+			return -EINVAL;
+		if (user_cfg->region[c].v_end & ~ISPHIST_REG_START_END_MASK)
+			return -EINVAL;
+		if (user_cfg->region[c].h_start > user_cfg->region[c].h_end)
+			return -EINVAL;
+		if (user_cfg->region[c].v_start > user_cfg->region[c].v_end)
+			return -EINVAL;
+	}
+
+	switch (user_cfg->num_regions) {
+	case 1:
+		if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_256)
+			return -EINVAL;
+		break;
+	case 2:
+		if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_128)
+			return -EINVAL;
+		break;
+	default: /* 3 or 4 */
+		if (user_cfg->hist_bins > OMAP3ISP_HIST_BINS_64)
+			return -EINVAL;
+		break;
+	}
+
+	buf_size = hist_get_buf_size(user_cfg);
+	if (buf_size > user_cfg->buf_size)
+		/* User's buf_size request wasn't enoght */
+		user_cfg->buf_size = buf_size;
+	else if (user_cfg->buf_size > OMAP3ISP_HIST_MAX_BUF_SIZE)
+		user_cfg->buf_size = OMAP3ISP_HIST_MAX_BUF_SIZE;
+
+	return 0;
+}
+
+static int hist_comp_params(struct ispstat *hist,
+			    struct omap3isp_hist_config *user_cfg)
+{
+	struct omap3isp_hist_config *cur_cfg = hist->priv;
+	int c;
+
+	if (cur_cfg->cfa != user_cfg->cfa)
+		return 1;
+
+	if (cur_cfg->num_acc_frames != user_cfg->num_acc_frames)
+		return 1;
+
+	if (cur_cfg->hist_bins != user_cfg->hist_bins)
+		return 1;
+
+	for (c = 0; c < OMAP3ISP_HIST_MAX_WG; c++) {
+		if (c == 3 && user_cfg->cfa == OMAP3ISP_HIST_CFA_FOVEONX3)
+			break;
+		else if (cur_cfg->wg[c] != user_cfg->wg[c])
+			return 1;
+	}
+
+	if (cur_cfg->num_regions != user_cfg->num_regions)
+		return 1;
+
+	/* Regions */
+	for (c = 0; c < user_cfg->num_regions; c++) {
+		if (cur_cfg->region[c].h_start != user_cfg->region[c].h_start)
+			return 1;
+		if (cur_cfg->region[c].h_end != user_cfg->region[c].h_end)
+			return 1;
+		if (cur_cfg->region[c].v_start != user_cfg->region[c].v_start)
+			return 1;
+		if (cur_cfg->region[c].v_end != user_cfg->region[c].v_end)
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * hist_update_params - Helper function to check and store user given params.
+ * @new_conf: Pointer to user configuration structure.
+ */
+static void hist_set_params(struct ispstat *hist, void *new_conf)
+{
+	struct omap3isp_hist_config *user_cfg = new_conf;
+	struct omap3isp_hist_config *cur_cfg = hist->priv;
+
+	if (!hist->configured || hist_comp_params(hist, user_cfg)) {
+		memcpy(cur_cfg, user_cfg, sizeof(*user_cfg));
+		if (user_cfg->num_acc_frames == 0)
+			user_cfg->num_acc_frames = 1;
+		hist->inc_config++;
+		hist->update = 1;
+		/*
+		 * User might be asked for a bigger buffer than necessary for
+		 * this configuration. In order to return the right amount of
+		 * data during buffer request, let's calculate the size here
+		 * instead of stick with user_cfg->buf_size.
+		 */
+		cur_cfg->buf_size = hist_get_buf_size(cur_cfg);
+
+	}
+}
+
+static long hist_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct ispstat *stat = v4l2_get_subdevdata(sd);
+
+	switch (cmd) {
+	case VIDIOC_OMAP3ISP_HIST_CFG:
+		return omap3isp_stat_config(stat, arg);
+	case VIDIOC_OMAP3ISP_STAT_REQ:
+		return omap3isp_stat_request_statistics(stat, arg);
+	case VIDIOC_OMAP3ISP_STAT_EN: {
+		int *en = arg;
+		return omap3isp_stat_enable(stat, !!*en);
+	}
+	}
+
+	return -ENOIOCTLCMD;
+
+}
+
+static const struct ispstat_ops hist_ops = {
+	.validate_params	= hist_validate_params,
+	.set_params		= hist_set_params,
+	.setup_regs		= hist_setup_regs,
+	.enable			= hist_enable,
+	.busy			= hist_busy,
+	.buf_process		= hist_buf_process,
+};
+
+static const struct v4l2_subdev_core_ops hist_subdev_core_ops = {
+	.ioctl = hist_ioctl,
+	.subscribe_event = omap3isp_stat_subscribe_event,
+	.unsubscribe_event = omap3isp_stat_unsubscribe_event,
+};
+
+static const struct v4l2_subdev_video_ops hist_subdev_video_ops = {
+	.s_stream = omap3isp_stat_s_stream,
+};
+
+static const struct v4l2_subdev_ops hist_subdev_ops = {
+	.core = &hist_subdev_core_ops,
+	.video = &hist_subdev_video_ops,
+};
+
+/*
+ * omap3isp_hist_init - Module Initialization.
+ */
+int omap3isp_hist_init(struct isp_device *isp)
+{
+	struct ispstat *hist = &isp->isp_hist;
+	struct omap3isp_hist_config *hist_cfg;
+	int ret = -1;
+
+	hist_cfg = kzalloc(sizeof(*hist_cfg), GFP_KERNEL);
+	if (hist_cfg == NULL)
+		return -ENOMEM;
+
+	memset(hist, 0, sizeof(*hist));
+	if (HIST_CONFIG_DMA)
+		ret = omap_request_dma(OMAP24XX_DMA_NO_DEVICE, "DMA_ISP_HIST",
+				       hist_dma_cb, hist, &hist->dma_ch);
+	if (ret) {
+		if (HIST_CONFIG_DMA)
+			dev_warn(isp->dev, "hist: DMA request channel failed. "
+					   "Using PIO only.\n");
+		hist->dma_ch = -1;
+	} else {
+		dev_dbg(isp->dev, "hist: DMA channel = %d\n", hist->dma_ch);
+		hist_dma_config(hist);
+		omap_enable_dma_irq(hist->dma_ch, OMAP_DMA_BLOCK_IRQ);
+	}
+
+	hist->ops = &hist_ops;
+	hist->priv = hist_cfg;
+	hist->event_type = V4L2_EVENT_OMAP3ISP_HIST;
+	hist->isp = isp;
+
+	ret = omap3isp_stat_init(hist, "histogram", &hist_subdev_ops);
+	if (ret) {
+		kfree(hist_cfg);
+		if (HIST_USING_DMA(hist))
+			omap_free_dma(hist->dma_ch);
+	}
+
+	return ret;
+}
+
+/*
+ * omap3isp_hist_cleanup - Module cleanup.
+ */
+void omap3isp_hist_cleanup(struct isp_device *isp)
+{
+	if (HIST_USING_DMA(&isp->isp_hist))
+		omap_free_dma(isp->isp_hist.dma_ch);
+	kfree(isp->isp_hist.priv);
+	omap3isp_stat_free(&isp->isp_hist);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isphist.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isphist.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isphist.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isphist.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,40 @@
+/*
+ * isphist.h
+ *
+ * TI OMAP3 ISP - Histogram module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_HIST_H
+#define OMAP3_ISP_HIST_H
+
+#include <linux/omap3isp.h>
+
+#define ISPHIST_IN_BIT_WIDTH_CCDC	10
+
+struct isp_device;
+
+int omap3isp_hist_init(struct isp_device *isp);
+void omap3isp_hist_cleanup(struct isp_device *isp);
+
+#endif /* OMAP3_ISP_HIST */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isppreview.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isppreview.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isppreview.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isppreview.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2113 @@
+/*
+ * isppreview.c
+ *
+ * TI OMAP3 ISP driver - Preview module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/device.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+#include <linux/mutex.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "isppreview.h"
+
+/* Default values in Office Fluorescent Light for RGBtoRGB Blending */
+static struct omap3isp_prev_rgbtorgb flr_rgb2rgb = {
+	{	/* RGB-RGB Matrix */
+		{0x01E2, 0x0F30, 0x0FEE},
+		{0x0F9B, 0x01AC, 0x0FB9},
+		{0x0FE0, 0x0EC0, 0x0260}
+	},	/* RGB Offset */
+	{0x0000, 0x0000, 0x0000}
+};
+
+/* Default values in Office Fluorescent Light for RGB to YUV Conversion*/
+static struct omap3isp_prev_csc flr_prev_csc = {
+	{	/* CSC Coef Matrix */
+		{66, 129, 25},
+		{-38, -75, 112},
+		{112, -94 , -18}
+	},	/* CSC Offset */
+	{0x0, 0x0, 0x0}
+};
+
+/* Default values in Office Fluorescent Light for CFA Gradient*/
+#define FLR_CFA_GRADTHRS_HORZ	0x28
+#define FLR_CFA_GRADTHRS_VERT	0x28
+
+/* Default values in Office Fluorescent Light for Chroma Suppression*/
+#define FLR_CSUP_GAIN		0x0D
+#define FLR_CSUP_THRES		0xEB
+
+/* Default values in Office Fluorescent Light for Noise Filter*/
+#define FLR_NF_STRGTH		0x03
+
+/* Default values for White Balance */
+#define FLR_WBAL_DGAIN		0x100
+#define FLR_WBAL_COEF		0x20
+
+/* Default values in Office Fluorescent Light for Black Adjustment*/
+#define FLR_BLKADJ_BLUE		0x0
+#define FLR_BLKADJ_GREEN	0x0
+#define FLR_BLKADJ_RED		0x0
+
+#define DEF_DETECT_CORRECT_VAL	0xe
+
+#define PREV_MIN_WIDTH		64
+#define PREV_MIN_HEIGHT		8
+#define PREV_MAX_HEIGHT		16384
+
+/*
+ * Coeficient Tables for the submodules in Preview.
+ * Array is initialised with the values from.the tables text file.
+ */
+
+/*
+ * CFA Filter Coefficient Table
+ *
+ */
+static u32 cfa_coef_table[] = {
+#include "cfa_coef_table.h"
+};
+
+/*
+ * Default Gamma Correction Table - All components
+ */
+static u32 gamma_table[] = {
+#include "gamma_table.h"
+};
+
+/*
+ * Noise Filter Threshold table
+ */
+static u32 noise_filter_table[] = {
+#include "noise_filter_table.h"
+};
+
+/*
+ * Luminance Enhancement Table
+ */
+static u32 luma_enhance_table[] = {
+#include "luma_enhance_table.h"
+};
+
+/*
+ * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
+ * @enable: 1 - Reverse the A-Law done in CCDC.
+ */
+static void
+preview_enable_invalaw(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
+}
+
+/*
+ * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture.
+ * @prev -
+ * @enable: 1 - Enable, 0 - Disable
+ *
+ * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also
+ * The process is applied for each captured frame.
+ */
+static void
+preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_DRKFCAP);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_DRKFCAP);
+}
+
+/*
+ * preview_enable_drkframe - Enable/Disable of the darkframe subtract.
+ * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
+ *          subtracted with the pixels in the current frame.
+ *
+ * The process is applied for each captured frame.
+ */
+static void
+preview_enable_drkframe(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_DRKFEN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_DRKFEN);
+}
+
+/*
+ * preview_config_drkf_shadcomp - Configures shift value in shading comp.
+ * @scomp_shtval: 3bit value of shift used in shading compensation.
+ */
+static void
+preview_config_drkf_shadcomp(struct isp_prev_device *prev,
+			     const void *scomp_shtval)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const u32 *shtval = scomp_shtval;
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			ISPPRV_PCR_SCOMP_SFT_MASK,
+			*shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT);
+}
+
+/*
+ * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
+ * @enable: 1 - Enables Horizontal Median Filter.
+ */
+static void
+preview_enable_hmed(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_HMEDEN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_HMEDEN);
+}
+
+/*
+ * preview_config_hmed - Configures the Horizontal Median Filter.
+ * @prev_hmed: Structure containing the odd and even distance between the
+ *             pixels in the image along with the filter threshold.
+ */
+static void
+preview_config_hmed(struct isp_prev_device *prev, const void *prev_hmed)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_hmed *hmed = prev_hmed;
+
+	isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
+		       (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
+		       (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
+}
+
+/*
+ * preview_config_noisefilter - Configures the Noise Filter.
+ * @prev_nf: Structure containing the noisefilter table, strength to be used
+ *           for the noise filter and the defect correction enable flag.
+ */
+static void
+preview_config_noisefilter(struct isp_prev_device *prev, const void *prev_nf)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_nf *nf = prev_nf;
+	unsigned int i;
+
+	isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
+	isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
+		isp_reg_writel(isp, nf->table[i],
+			       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+}
+
+/*
+ * preview_config_dcor - Configures the defect correction
+ * @prev_dcor: Structure containing the defect correct thresholds
+ */
+static void
+preview_config_dcor(struct isp_prev_device *prev, const void *prev_dcor)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_dcor *dcor = prev_dcor;
+
+	isp_reg_writel(isp, dcor->detect_correct[0],
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
+	isp_reg_writel(isp, dcor->detect_correct[1],
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
+	isp_reg_writel(isp, dcor->detect_correct[2],
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
+	isp_reg_writel(isp, dcor->detect_correct[3],
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			ISPPRV_PCR_DCCOUP,
+			dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
+}
+
+/*
+ * preview_config_cfa - Configures the CFA Interpolation parameters.
+ * @prev_cfa: Structure containing the CFA interpolation table, CFA format
+ *            in the image, vertical and horizontal gradient threshold.
+ */
+static void
+preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_cfa *cfa = prev_cfa;
+	unsigned int i;
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			ISPPRV_PCR_CFAFMT_MASK,
+			cfa->format << ISPPRV_PCR_CFAFMT_SHIFT);
+
+	isp_reg_writel(isp,
+		(cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
+		(cfa->gradthrs_horz << ISPPRV_CFA_GRADTH_HOR_SHIFT),
+		OMAP3_ISP_IOMEM_PREV, ISPPRV_CFA);
+
+	isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+
+	for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) {
+		isp_reg_writel(isp, cfa->table[i],
+			       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+}
+
+/*
+ * preview_config_gammacorrn - Configures the Gamma Correction table values
+ * @gtable: Structure containing the table for red, blue, green gamma table.
+ */
+static void
+preview_config_gammacorrn(struct isp_prev_device *prev, const void *gtable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_gtables *gt = gtable;
+	unsigned int i;
+
+	isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
+		isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
+			       ISPPRV_SET_TBL_DATA);
+
+	isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
+		isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
+			       ISPPRV_SET_TBL_DATA);
+
+	isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
+		isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
+			       ISPPRV_SET_TBL_DATA);
+}
+
+/*
+ * preview_config_luma_enhancement - Sets the Luminance Enhancement table.
+ * @ytable: Structure containing the table for Luminance Enhancement table.
+ */
+static void
+preview_config_luma_enhancement(struct isp_prev_device *prev,
+				const void *ytable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_luma *yt = ytable;
+	unsigned int i;
+
+	isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+	for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
+		isp_reg_writel(isp, yt->table[i],
+			       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+	}
+}
+
+/*
+ * preview_config_chroma_suppression - Configures the Chroma Suppression.
+ * @csup: Structure containing the threshold value for suppression
+ *        and the hypass filter enable flag.
+ */
+static void
+preview_config_chroma_suppression(struct isp_prev_device *prev,
+				  const void *csup)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_csup *cs = csup;
+
+	isp_reg_writel(isp,
+		       cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
+		       (cs->hypf_en << ISPPRV_CSUP_HPYF_SHIFT),
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_CSUP);
+}
+
+/*
+ * preview_enable_noisefilter - Enables/Disables the Noise Filter.
+ * @enable: 1 - Enables the Noise Filter.
+ */
+static void
+preview_enable_noisefilter(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_NFEN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_NFEN);
+}
+
+/*
+ * preview_enable_dcor - Enables/Disables the defect correction.
+ * @enable: 1 - Enables the defect correction.
+ */
+static void
+preview_enable_dcor(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_DCOREN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_DCOREN);
+}
+
+/*
+ * preview_enable_cfa - Enable/Disable the CFA Interpolation.
+ * @enable: 1 - Enables the CFA.
+ */
+static void
+preview_enable_cfa(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_CFAEN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_CFAEN);
+}
+
+/*
+ * preview_enable_gammabypass - Enables/Disables the GammaByPass
+ * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
+ *          0 - Goes through Gamma Correction. input and output is 10bit.
+ */
+static void
+preview_enable_gammabypass(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_GAMMA_BYPASS);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_GAMMA_BYPASS);
+}
+
+/*
+ * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
+ * @enable: 1 - Enable the Luminance Enhancement.
+ */
+static void
+preview_enable_luma_enhancement(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_YNENHEN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_YNENHEN);
+}
+
+/*
+ * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
+ * @enable: 1 - Enable the Chrominance Suppression.
+ */
+static void
+preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	if (enable)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_SUPEN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_SUPEN);
+}
+
+/*
+ * preview_config_whitebalance - Configures the White Balance parameters.
+ * @prev_wbal: Structure containing the digital gain and white balance
+ *             coefficient.
+ *
+ * Coefficient matrix always with default values.
+ */
+static void
+preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_wbal *wbal = prev_wbal;
+	u32 val;
+
+	isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
+
+	val = wbal->coef0 << ISPPRV_WBGAIN_COEF0_SHIFT;
+	val |= wbal->coef1 << ISPPRV_WBGAIN_COEF1_SHIFT;
+	val |= wbal->coef2 << ISPPRV_WBGAIN_COEF2_SHIFT;
+	val |= wbal->coef3 << ISPPRV_WBGAIN_COEF3_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_WBGAIN);
+
+	isp_reg_writel(isp,
+		       ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_0_SHIFT |
+		       ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_1_SHIFT |
+		       ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N0_2_SHIFT |
+		       ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N0_3_SHIFT |
+		       ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_0_SHIFT |
+		       ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_1_SHIFT |
+		       ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N1_2_SHIFT |
+		       ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N1_3_SHIFT |
+		       ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_0_SHIFT |
+		       ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_1_SHIFT |
+		       ISPPRV_WBSEL_COEF0 << ISPPRV_WBSEL_N2_2_SHIFT |
+		       ISPPRV_WBSEL_COEF1 << ISPPRV_WBSEL_N2_3_SHIFT |
+		       ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_0_SHIFT |
+		       ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_1_SHIFT |
+		       ISPPRV_WBSEL_COEF2 << ISPPRV_WBSEL_N3_2_SHIFT |
+		       ISPPRV_WBSEL_COEF3 << ISPPRV_WBSEL_N3_3_SHIFT,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_WBSEL);
+}
+
+/*
+ * preview_config_blkadj - Configures the Black Adjustment parameters.
+ * @prev_blkadj: Structure containing the black adjustment towards red, green,
+ *               blue.
+ */
+static void
+preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_blkadj *blkadj = prev_blkadj;
+
+	isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
+		       (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
+		       (blkadj->red << ISPPRV_BLKADJOFF_R_SHIFT),
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_BLKADJOFF);
+}
+
+/*
+ * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
+ * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
+ *           offset.
+ */
+static void
+preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_rgbtorgb *rgbrgb = rgb2rgb;
+	u32 val;
+
+	val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
+	val |= (rgbrgb->matrix[0][1] & 0xfff) << ISPPRV_RGB_MAT1_MTX_GR_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT1);
+
+	val = (rgbrgb->matrix[0][2] & 0xfff) << ISPPRV_RGB_MAT2_MTX_BR_SHIFT;
+	val |= (rgbrgb->matrix[1][0] & 0xfff) << ISPPRV_RGB_MAT2_MTX_RG_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT2);
+
+	val = (rgbrgb->matrix[1][1] & 0xfff) << ISPPRV_RGB_MAT3_MTX_GG_SHIFT;
+	val |= (rgbrgb->matrix[1][2] & 0xfff) << ISPPRV_RGB_MAT3_MTX_BG_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT3);
+
+	val = (rgbrgb->matrix[2][0] & 0xfff) << ISPPRV_RGB_MAT4_MTX_RB_SHIFT;
+	val |= (rgbrgb->matrix[2][1] & 0xfff) << ISPPRV_RGB_MAT4_MTX_GB_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT4);
+
+	val = (rgbrgb->matrix[2][2] & 0xfff) << ISPPRV_RGB_MAT5_MTX_BB_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_MAT5);
+
+	val = (rgbrgb->offset[0] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT;
+	val |= (rgbrgb->offset[1] & 0x3ff) << ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF1);
+
+	val = (rgbrgb->offset[2] & 0x3ff) << ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_RGB_OFF2);
+}
+
+/*
+ * Configures the RGB-YCbYCr conversion matrix
+ * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
+ *            YCbCr offset.
+ */
+static void
+preview_config_rgb_to_ycbcr(struct isp_prev_device *prev, const void *prev_csc)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_csc *csc = prev_csc;
+	u32 val;
+
+	val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
+	val |= (csc->matrix[0][1] & 0x3ff) << ISPPRV_CSC0_GY_SHIFT;
+	val |= (csc->matrix[0][2] & 0x3ff) << ISPPRV_CSC0_BY_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC0);
+
+	val = (csc->matrix[1][0] & 0x3ff) << ISPPRV_CSC1_RCB_SHIFT;
+	val |= (csc->matrix[1][1] & 0x3ff) << ISPPRV_CSC1_GCB_SHIFT;
+	val |= (csc->matrix[1][2] & 0x3ff) << ISPPRV_CSC1_BCB_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC1);
+
+	val = (csc->matrix[2][0] & 0x3ff) << ISPPRV_CSC2_RCR_SHIFT;
+	val |= (csc->matrix[2][1] & 0x3ff) << ISPPRV_CSC2_GCR_SHIFT;
+	val |= (csc->matrix[2][2] & 0x3ff) << ISPPRV_CSC2_BCR_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC2);
+
+	val = (csc->offset[0] & 0xff) << ISPPRV_CSC_OFFSET_Y_SHIFT;
+	val |= (csc->offset[1] & 0xff) << ISPPRV_CSC_OFFSET_CB_SHIFT;
+	val |= (csc->offset[2] & 0xff) << ISPPRV_CSC_OFFSET_CR_SHIFT;
+	isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
+}
+
+/*
+ * preview_update_contrast - Updates the contrast.
+ * @contrast: Pointer to hold the current programmed contrast value.
+ *
+ * Value should be programmed before enabling the module.
+ */
+static void
+preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
+{
+	struct prev_params *params = &prev->params;
+
+	if (params->contrast != (contrast * ISPPRV_CONTRAST_UNITS)) {
+		params->contrast = contrast * ISPPRV_CONTRAST_UNITS;
+		prev->update |= PREV_CONTRAST;
+	}
+}
+
+/*
+ * preview_config_contrast - Configures the Contrast.
+ * @params: Contrast value (u8 pointer, U8Q0 format).
+ *
+ * Value should be programmed before enabling the module.
+ */
+static void
+preview_config_contrast(struct isp_prev_device *prev, const void *params)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
+			0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
+			*(u8 *)params << ISPPRV_CNT_BRT_CNT_SHIFT);
+}
+
+/*
+ * preview_update_brightness - Updates the brightness in preview module.
+ * @brightness: Pointer to hold the current programmed brightness value.
+ *
+ */
+static void
+preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
+{
+	struct prev_params *params = &prev->params;
+
+	if (params->brightness != (brightness * ISPPRV_BRIGHT_UNITS)) {
+		params->brightness = brightness * ISPPRV_BRIGHT_UNITS;
+		prev->update |= PREV_BRIGHTNESS;
+	}
+}
+
+/*
+ * preview_config_brightness - Configures the brightness.
+ * @params: Brightness value (u8 pointer, U8Q0 format).
+ */
+static void
+preview_config_brightness(struct isp_prev_device *prev, const void *params)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
+			0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
+			*(u8 *)params << ISPPRV_CNT_BRT_BRT_SHIFT);
+}
+
+/*
+ * preview_config_yc_range - Configures the max and min Y and C values.
+ * @yclimit: Structure containing the range of Y and C values.
+ */
+static void
+preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	const struct omap3isp_prev_yclimit *yc = yclimit;
+
+	isp_reg_writel(isp,
+		       yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
+		       yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
+		       yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
+		       yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
+}
+
+/* preview parameters update structure */
+struct preview_update {
+	int cfg_bit;
+	int feature_bit;
+	void (*config)(struct isp_prev_device *, const void *);
+	void (*enable)(struct isp_prev_device *, u8);
+};
+
+static struct preview_update update_attrs[] = {
+	{OMAP3ISP_PREV_LUMAENH, PREV_LUMA_ENHANCE,
+		preview_config_luma_enhancement,
+		preview_enable_luma_enhancement},
+	{OMAP3ISP_PREV_INVALAW, PREV_INVERSE_ALAW,
+		NULL,
+		preview_enable_invalaw},
+	{OMAP3ISP_PREV_HRZ_MED, PREV_HORZ_MEDIAN_FILTER,
+		preview_config_hmed,
+		preview_enable_hmed},
+	{OMAP3ISP_PREV_CFA, PREV_CFA,
+		preview_config_cfa,
+		preview_enable_cfa},
+	{OMAP3ISP_PREV_CHROMA_SUPP, PREV_CHROMA_SUPPRESS,
+		preview_config_chroma_suppression,
+		preview_enable_chroma_suppression},
+	{OMAP3ISP_PREV_WB, PREV_WB,
+		preview_config_whitebalance,
+		NULL},
+	{OMAP3ISP_PREV_BLKADJ, PREV_BLKADJ,
+		preview_config_blkadj,
+		NULL},
+	{OMAP3ISP_PREV_RGB2RGB, PREV_RGB2RGB,
+		preview_config_rgb_blending,
+		NULL},
+	{OMAP3ISP_PREV_COLOR_CONV, PREV_COLOR_CONV,
+		preview_config_rgb_to_ycbcr,
+		NULL},
+	{OMAP3ISP_PREV_YC_LIMIT, PREV_YCLIMITS,
+		preview_config_yc_range,
+		NULL},
+	{OMAP3ISP_PREV_DEFECT_COR, PREV_DEFECT_COR,
+		preview_config_dcor,
+		preview_enable_dcor},
+	{OMAP3ISP_PREV_GAMMABYPASS, PREV_GAMMA_BYPASS,
+		NULL,
+		preview_enable_gammabypass},
+	{OMAP3ISP_PREV_DRK_FRM_CAPTURE, PREV_DARK_FRAME_CAPTURE,
+		NULL,
+		preview_enable_drkframe_capture},
+	{OMAP3ISP_PREV_DRK_FRM_SUBTRACT, PREV_DARK_FRAME_SUBTRACT,
+		NULL,
+		preview_enable_drkframe},
+	{OMAP3ISP_PREV_LENS_SHADING, PREV_LENS_SHADING,
+		preview_config_drkf_shadcomp,
+		preview_enable_drkframe},
+	{OMAP3ISP_PREV_NF, PREV_NOISE_FILTER,
+		preview_config_noisefilter,
+		preview_enable_noisefilter},
+	{OMAP3ISP_PREV_GAMMA, PREV_GAMMA,
+		preview_config_gammacorrn,
+		NULL},
+	{-1, PREV_CONTRAST,
+		preview_config_contrast,
+		NULL},
+	{-1, PREV_BRIGHTNESS,
+		preview_config_brightness,
+		NULL},
+};
+
+/*
+ * __preview_get_ptrs - helper function which return pointers to members
+ *                         of params and config structures.
+ * @params - pointer to preview_params structure.
+ * @param - return pointer to appropriate structure field.
+ * @configs - pointer to update config structure.
+ * @config - return pointer to appropriate structure field.
+ * @bit - for which feature to return pointers.
+ * Return size of corresponding prev_params member
+ */
+static u32
+__preview_get_ptrs(struct prev_params *params, void **param,
+		   struct omap3isp_prev_update_config *configs,
+		   void __user **config, u32 bit)
+{
+#define CHKARG(cfgs, cfg, field)				\
+	if (cfgs && cfg) {					\
+		*(cfg) = (cfgs)->field;				\
+	}
+
+	switch (bit) {
+	case PREV_HORZ_MEDIAN_FILTER:
+		*param = &params->hmed;
+		CHKARG(configs, config, hmed)
+		return sizeof(params->hmed);
+	case PREV_NOISE_FILTER:
+		*param = &params->nf;
+		CHKARG(configs, config, nf)
+		return sizeof(params->nf);
+		break;
+	case PREV_CFA:
+		*param = &params->cfa;
+		CHKARG(configs, config, cfa)
+		return sizeof(params->cfa);
+	case PREV_LUMA_ENHANCE:
+		*param = &params->luma;
+		CHKARG(configs, config, luma)
+		return sizeof(params->luma);
+	case PREV_CHROMA_SUPPRESS:
+		*param = &params->csup;
+		CHKARG(configs, config, csup)
+		return sizeof(params->csup);
+	case PREV_DEFECT_COR:
+		*param = &params->dcor;
+		CHKARG(configs, config, dcor)
+		return sizeof(params->dcor);
+	case PREV_BLKADJ:
+		*param = &params->blk_adj;
+		CHKARG(configs, config, blkadj)
+		return sizeof(params->blk_adj);
+	case PREV_YCLIMITS:
+		*param = &params->yclimit;
+		CHKARG(configs, config, yclimit)
+		return sizeof(params->yclimit);
+	case PREV_RGB2RGB:
+		*param = &params->rgb2rgb;
+		CHKARG(configs, config, rgb2rgb)
+		return sizeof(params->rgb2rgb);
+	case PREV_COLOR_CONV:
+		*param = &params->rgb2ycbcr;
+		CHKARG(configs, config, csc)
+		return sizeof(params->rgb2ycbcr);
+	case PREV_WB:
+		*param = &params->wbal;
+		CHKARG(configs, config, wbal)
+		return sizeof(params->wbal);
+	case PREV_GAMMA:
+		*param = &params->gamma;
+		CHKARG(configs, config, gamma)
+		return sizeof(params->gamma);
+	case PREV_CONTRAST:
+		*param = &params->contrast;
+		return 0;
+	case PREV_BRIGHTNESS:
+		*param = &params->brightness;
+		return 0;
+	default:
+		*param = NULL;
+		*config = NULL;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * preview_config - Copy and update local structure with userspace preview
+ *                  configuration.
+ * @prev: ISP preview engine
+ * @cfg: Configuration
+ *
+ * Return zero if success or -EFAULT if the configuration can't be copied from
+ * userspace.
+ */
+static int preview_config(struct isp_prev_device *prev,
+			  struct omap3isp_prev_update_config *cfg)
+{
+	struct prev_params *params;
+	struct preview_update *attr;
+	int i, bit, rval = 0;
+
+	params = &prev->params;
+
+	if (prev->state != ISP_PIPELINE_STREAM_STOPPED) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&prev->lock, flags);
+		prev->shadow_update = 1;
+		spin_unlock_irqrestore(&prev->lock, flags);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
+		attr = &update_attrs[i];
+		bit = 0;
+
+		if (!(cfg->update & attr->cfg_bit))
+			continue;
+
+		bit = cfg->flag & attr->cfg_bit;
+		if (bit) {
+			void *to = NULL, __user *from = NULL;
+			unsigned long sz = 0;
+
+			sz = __preview_get_ptrs(params, &to, cfg, &from,
+						   bit);
+			if (to && from && sz) {
+				if (copy_from_user(to, from, sz)) {
+					rval = -EFAULT;
+					break;
+				}
+			}
+			params->features |= attr->feature_bit;
+		} else {
+			params->features &= ~attr->feature_bit;
+		}
+
+		prev->update |= attr->feature_bit;
+	}
+
+	prev->shadow_update = 0;
+	return rval;
+}
+
+/*
+ * preview_setup_hw - Setup preview registers and/or internal memory
+ * @prev: pointer to preview private structure
+ * Note: can be called from interrupt context
+ * Return none
+ */
+static void preview_setup_hw(struct isp_prev_device *prev)
+{
+	struct prev_params *params = &prev->params;
+	struct preview_update *attr;
+	int i, bit;
+	void *param_ptr;
+
+	for (i = 0; i < ARRAY_SIZE(update_attrs); i++) {
+		attr = &update_attrs[i];
+
+		if (!(prev->update & attr->feature_bit))
+			continue;
+		bit = params->features & attr->feature_bit;
+		if (bit) {
+			if (attr->config) {
+				__preview_get_ptrs(params, &param_ptr, NULL,
+						      NULL, bit);
+				attr->config(prev, param_ptr);
+			}
+			if (attr->enable)
+				attr->enable(prev, 1);
+		} else
+			if (attr->enable)
+				attr->enable(prev, 0);
+
+		prev->update &= ~attr->feature_bit;
+	}
+}
+
+/*
+ * preview_config_ycpos - Configure byte layout of YUV image.
+ * @mode: Indicates the required byte layout.
+ */
+static void
+preview_config_ycpos(struct isp_prev_device *prev,
+		     enum v4l2_mbus_pixelcode pixelcode)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	enum preview_ycpos_mode mode;
+
+	switch (pixelcode) {
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+		mode = YCPOS_CrYCbY;
+		break;
+	case V4L2_MBUS_FMT_UYVY8_1X16:
+		mode = YCPOS_YCrYCb;
+		break;
+	default:
+		return;
+	}
+
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			ISPPRV_PCR_YCPOS_CrYCbY,
+			mode << ISPPRV_PCR_YCPOS_SHIFT);
+}
+
+/*
+ * preview_config_averager - Enable / disable / configure averager
+ * @average: Average value to be configured.
+ */
+static void preview_config_averager(struct isp_prev_device *prev, u8 average)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	int reg = 0;
+
+	if (prev->params.cfa.format == OMAP3ISP_CFAFMT_BAYER)
+		reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
+		      ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
+		      average;
+	else if (prev->params.cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON)
+		reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT |
+		      ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT |
+		      average;
+	isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
+}
+
+/*
+ * preview_config_input_size - Configure the input frame size
+ *
+ * The preview engine crops several rows and columns internally depending on
+ * which processing blocks are enabled. The driver assumes all those blocks are
+ * enabled when reporting source pad formats to userspace. If this assumption is
+ * not true, rows and columns must be manually cropped at the preview engine
+ * input to avoid overflows at the end of lines and frames.
+ */
+static void preview_config_input_size(struct isp_prev_device *prev)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	struct prev_params *params = &prev->params;
+	struct v4l2_mbus_framefmt *format = &prev->formats[PREV_PAD_SINK];
+	unsigned int sph = 0;
+	unsigned int eph = format->width - 1;
+	unsigned int slv = 0;
+	unsigned int elv = format->height - 1;
+
+	if (prev->input == PREVIEW_INPUT_CCDC) {
+		sph += 2;
+		eph -= 2;
+	}
+
+	/*
+	 * Median filter	4 pixels
+	 * Noise filter		4 pixels, 4 lines
+	 * or faulty pixels correction
+	 * CFA filter		4 pixels, 4 lines in Bayer mode
+	 *				  2 lines in other modes
+	 * Color suppression	2 pixels
+	 * or luma enhancement
+	 * -------------------------------------------------------------
+	 * Maximum total	14 pixels, 8 lines
+	 */
+
+	if (!(params->features & PREV_CFA)) {
+		sph += 2;
+		eph -= 2;
+		slv += 2;
+		elv -= 2;
+	}
+	if (!(params->features & (PREV_DEFECT_COR | PREV_NOISE_FILTER))) {
+		sph += 2;
+		eph -= 2;
+		slv += 2;
+		elv -= 2;
+	}
+	if (!(params->features & PREV_HORZ_MEDIAN_FILTER)) {
+		sph += 2;
+		eph -= 2;
+	}
+	if (!(params->features & (PREV_CHROMA_SUPPRESS | PREV_LUMA_ENHANCE)))
+		sph += 2;
+
+	isp_reg_writel(isp, (sph << ISPPRV_HORZ_INFO_SPH_SHIFT) | eph,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_HORZ_INFO);
+	isp_reg_writel(isp, (slv << ISPPRV_VERT_INFO_SLV_SHIFT) | elv,
+		       OMAP3_ISP_IOMEM_PREV, ISPPRV_VERT_INFO);
+}
+
+/*
+ * preview_config_inlineoffset - Configures the Read address line offset.
+ * @prev: Preview module
+ * @offset: Line offset
+ *
+ * According to the TRM, the line offset must be aligned on a 32 bytes boundary.
+ * However, a hardware bug requires the memory start address to be aligned on a
+ * 64 bytes boundary, so the offset probably should be aligned on 64 bytes as
+ * well.
+ */
+static void
+preview_config_inlineoffset(struct isp_prev_device *prev, u32 offset)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
+		       ISPPRV_RADR_OFFSET);
+}
+
+/*
+ * preview_set_inaddr - Sets memory address of input frame.
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ *
+ * Configures the memory address from which the input frame is to be read.
+ */
+static void preview_set_inaddr(struct isp_prev_device *prev, u32 addr)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_RSDR_ADDR);
+}
+
+/*
+ * preview_config_outlineoffset - Configures the Write address line offset.
+ * @offset: Line Offset for the preview output.
+ *
+ * The offset must be a multiple of 32 bytes.
+ */
+static void preview_config_outlineoffset(struct isp_prev_device *prev,
+				    u32 offset)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	isp_reg_writel(isp, offset & 0xffff, OMAP3_ISP_IOMEM_PREV,
+		       ISPPRV_WADD_OFFSET);
+}
+
+/*
+ * preview_set_outaddr - Sets the memory address to store output frame
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ *
+ * Configures the memory address to which the output frame is written.
+ */
+static void preview_set_outaddr(struct isp_prev_device *prev, u32 addr)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_PREV, ISPPRV_WSDR_ADDR);
+}
+
+static void preview_adjust_bandwidth(struct isp_prev_device *prev)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
+	struct isp_device *isp = to_isp_device(prev);
+	const struct v4l2_mbus_framefmt *ifmt = &prev->formats[PREV_PAD_SINK];
+	unsigned long l3_ick = pipe->l3_ick;
+	struct v4l2_fract *timeperframe;
+	unsigned int cycles_per_frame;
+	unsigned int requests_per_frame;
+	unsigned int cycles_per_request;
+	unsigned int minimum;
+	unsigned int maximum;
+	unsigned int value;
+
+	if (prev->input != PREVIEW_INPUT_MEMORY) {
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
+			    ISPSBL_SDR_REQ_PRV_EXP_MASK);
+		return;
+	}
+
+	/* Compute the minimum number of cycles per request, based on the
+	 * pipeline maximum data rate. This is an absolute lower bound if we
+	 * don't want SBL overflows, so round the value up.
+	 */
+	cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
+				     pipe->max_rate);
+	minimum = DIV_ROUND_UP(cycles_per_request, 32);
+
+	/* Compute the maximum number of cycles per request, based on the
+	 * requested frame rate. This is a soft upper bound to achieve a frame
+	 * rate equal or higher than the requested value, so round the value
+	 * down.
+	 */
+	timeperframe = &pipe->max_timeperframe;
+
+	requests_per_frame = DIV_ROUND_UP(ifmt->width * 2, 256) * ifmt->height;
+	cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
+				   timeperframe->denominator);
+	cycles_per_request = cycles_per_frame / requests_per_frame;
+
+	maximum = cycles_per_request / 32;
+
+	value = max(minimum, maximum);
+
+	dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
+			ISPSBL_SDR_REQ_PRV_EXP_MASK,
+			value << ISPSBL_SDR_REQ_PRV_EXP_SHIFT);
+}
+
+/*
+ * omap3isp_preview_busy - Gets busy state of preview module.
+ */
+int omap3isp_preview_busy(struct isp_prev_device *prev)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	return isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR)
+		& ISPPRV_PCR_BUSY;
+}
+
+/*
+ * omap3isp_preview_restore_context - Restores the values of preview registers
+ */
+void omap3isp_preview_restore_context(struct isp_device *isp)
+{
+	isp->isp_prev.update = PREV_FEATURES_END - 1;
+	preview_setup_hw(&isp->isp_prev);
+}
+
+/*
+ * preview_print_status - Dump preview module registers to the kernel log
+ */
+#define PREV_PRINT_REGISTER(isp, name)\
+	dev_dbg(isp->dev, "###PRV " #name "=0x%08x\n", \
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_##name))
+
+static void preview_print_status(struct isp_prev_device *prev)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	dev_dbg(isp->dev, "-------------Preview Register dump----------\n");
+
+	PREV_PRINT_REGISTER(isp, PCR);
+	PREV_PRINT_REGISTER(isp, HORZ_INFO);
+	PREV_PRINT_REGISTER(isp, VERT_INFO);
+	PREV_PRINT_REGISTER(isp, RSDR_ADDR);
+	PREV_PRINT_REGISTER(isp, RADR_OFFSET);
+	PREV_PRINT_REGISTER(isp, DSDR_ADDR);
+	PREV_PRINT_REGISTER(isp, DRKF_OFFSET);
+	PREV_PRINT_REGISTER(isp, WSDR_ADDR);
+	PREV_PRINT_REGISTER(isp, WADD_OFFSET);
+	PREV_PRINT_REGISTER(isp, AVE);
+	PREV_PRINT_REGISTER(isp, HMED);
+	PREV_PRINT_REGISTER(isp, NF);
+	PREV_PRINT_REGISTER(isp, WB_DGAIN);
+	PREV_PRINT_REGISTER(isp, WBGAIN);
+	PREV_PRINT_REGISTER(isp, WBSEL);
+	PREV_PRINT_REGISTER(isp, CFA);
+	PREV_PRINT_REGISTER(isp, BLKADJOFF);
+	PREV_PRINT_REGISTER(isp, RGB_MAT1);
+	PREV_PRINT_REGISTER(isp, RGB_MAT2);
+	PREV_PRINT_REGISTER(isp, RGB_MAT3);
+	PREV_PRINT_REGISTER(isp, RGB_MAT4);
+	PREV_PRINT_REGISTER(isp, RGB_MAT5);
+	PREV_PRINT_REGISTER(isp, RGB_OFF1);
+	PREV_PRINT_REGISTER(isp, RGB_OFF2);
+	PREV_PRINT_REGISTER(isp, CSC0);
+	PREV_PRINT_REGISTER(isp, CSC1);
+	PREV_PRINT_REGISTER(isp, CSC2);
+	PREV_PRINT_REGISTER(isp, CSC_OFFSET);
+	PREV_PRINT_REGISTER(isp, CNT_BRT);
+	PREV_PRINT_REGISTER(isp, CSUP);
+	PREV_PRINT_REGISTER(isp, SETUP_YC);
+	PREV_PRINT_REGISTER(isp, SET_TBL_ADDR);
+	PREV_PRINT_REGISTER(isp, CDC_THR0);
+	PREV_PRINT_REGISTER(isp, CDC_THR1);
+	PREV_PRINT_REGISTER(isp, CDC_THR2);
+	PREV_PRINT_REGISTER(isp, CDC_THR3);
+
+	dev_dbg(isp->dev, "--------------------------------------------\n");
+}
+
+/*
+ * preview_init_params - init image processing parameters.
+ * @prev: pointer to previewer private structure
+ * return none
+ */
+static void preview_init_params(struct isp_prev_device *prev)
+{
+	struct prev_params *params = &prev->params;
+	int i = 0;
+
+	/* Init values */
+	params->contrast = ISPPRV_CONTRAST_DEF * ISPPRV_CONTRAST_UNITS;
+	params->brightness = ISPPRV_BRIGHT_DEF * ISPPRV_BRIGHT_UNITS;
+	params->average = NO_AVE;
+	params->cfa.format = OMAP3ISP_CFAFMT_BAYER;
+	memcpy(params->cfa.table, cfa_coef_table,
+	       sizeof(params->cfa.table));
+	params->cfa.gradthrs_horz = FLR_CFA_GRADTHRS_HORZ;
+	params->cfa.gradthrs_vert = FLR_CFA_GRADTHRS_VERT;
+	params->csup.gain = FLR_CSUP_GAIN;
+	params->csup.thres = FLR_CSUP_THRES;
+	params->csup.hypf_en = 0;
+	memcpy(params->luma.table, luma_enhance_table,
+	       sizeof(params->luma.table));
+	params->nf.spread = FLR_NF_STRGTH;
+	memcpy(params->nf.table, noise_filter_table, sizeof(params->nf.table));
+	params->dcor.couplet_mode_en = 1;
+	for (i = 0; i < OMAP3ISP_PREV_DETECT_CORRECT_CHANNELS; i++)
+		params->dcor.detect_correct[i] = DEF_DETECT_CORRECT_VAL;
+	memcpy(params->gamma.blue, gamma_table, sizeof(params->gamma.blue));
+	memcpy(params->gamma.green, gamma_table, sizeof(params->gamma.green));
+	memcpy(params->gamma.red, gamma_table, sizeof(params->gamma.red));
+	params->wbal.dgain = FLR_WBAL_DGAIN;
+	params->wbal.coef0 = FLR_WBAL_COEF;
+	params->wbal.coef1 = FLR_WBAL_COEF;
+	params->wbal.coef2 = FLR_WBAL_COEF;
+	params->wbal.coef3 = FLR_WBAL_COEF;
+	params->blk_adj.red = FLR_BLKADJ_RED;
+	params->blk_adj.green = FLR_BLKADJ_GREEN;
+	params->blk_adj.blue = FLR_BLKADJ_BLUE;
+	params->rgb2rgb = flr_rgb2rgb;
+	params->rgb2ycbcr = flr_prev_csc;
+	params->yclimit.minC = ISPPRV_YC_MIN;
+	params->yclimit.maxC = ISPPRV_YC_MAX;
+	params->yclimit.minY = ISPPRV_YC_MIN;
+	params->yclimit.maxY = ISPPRV_YC_MAX;
+
+	params->features = PREV_CFA | PREV_DEFECT_COR | PREV_NOISE_FILTER
+			 | PREV_GAMMA | PREV_BLKADJ | PREV_YCLIMITS
+			 | PREV_RGB2RGB | PREV_COLOR_CONV | PREV_WB
+			 | PREV_BRIGHTNESS | PREV_CONTRAST;
+
+	prev->update = PREV_FEATURES_END - 1;
+}
+
+/*
+ * preview_max_out_width - Handle previewer hardware ouput limitations
+ * @isp_revision : ISP revision
+ * returns maximum width output for current isp revision
+ */
+static unsigned int preview_max_out_width(struct isp_prev_device *prev)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	switch (isp->revision) {
+	case ISP_REVISION_1_0:
+		return ISPPRV_MAXOUTPUT_WIDTH;
+
+	case ISP_REVISION_2_0:
+	default:
+		return ISPPRV_MAXOUTPUT_WIDTH_ES2;
+
+	case ISP_REVISION_15_0:
+		return ISPPRV_MAXOUTPUT_WIDTH_3630;
+	}
+}
+
+static void preview_configure(struct isp_prev_device *prev)
+{
+	struct isp_device *isp = to_isp_device(prev);
+	struct v4l2_mbus_framefmt *format;
+	unsigned int max_out_width;
+	unsigned int format_avg;
+
+	preview_setup_hw(prev);
+
+	if (prev->output & PREVIEW_OUTPUT_MEMORY)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_SDRPORT);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_SDRPORT);
+
+	if (prev->output & PREVIEW_OUTPUT_RESIZER)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_RSZPORT);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_RSZPORT);
+
+	/* PREV_PAD_SINK */
+	format = &prev->formats[PREV_PAD_SINK];
+
+	preview_adjust_bandwidth(prev);
+
+	preview_config_input_size(prev);
+
+	if (prev->input == PREVIEW_INPUT_CCDC)
+		preview_config_inlineoffset(prev, 0);
+	else
+		preview_config_inlineoffset(prev,
+				ALIGN(format->width, 0x20) * 2);
+
+	/* PREV_PAD_SOURCE */
+	format = &prev->formats[PREV_PAD_SOURCE];
+
+	if (prev->output & PREVIEW_OUTPUT_MEMORY)
+		preview_config_outlineoffset(prev,
+				ALIGN(format->width, 0x10) * 2);
+
+	max_out_width = preview_max_out_width(prev);
+
+	format_avg = fls(DIV_ROUND_UP(format->width, max_out_width) - 1);
+	preview_config_averager(prev, format_avg);
+	preview_config_ycpos(prev, format->code);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+static void preview_enable_oneshot(struct isp_prev_device *prev)
+{
+	struct isp_device *isp = to_isp_device(prev);
+
+	/* The PCR.SOURCE bit is automatically reset to 0 when the PCR.ENABLE
+	 * bit is set. As the preview engine is used in single-shot mode, we
+	 * need to set PCR.SOURCE before enabling the preview engine.
+	 */
+	if (prev->input == PREVIEW_INPUT_MEMORY)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+			    ISPPRV_PCR_SOURCE);
+
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+		    ISPPRV_PCR_EN | ISPPRV_PCR_ONESHOT);
+}
+
+void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev)
+{
+	/*
+	 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
+	 * condition, the module was paused and now we have a buffer queued
+	 * on the output again. Restart the pipeline if running in continuous
+	 * mode.
+	 */
+	if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
+	    prev->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
+		preview_enable_oneshot(prev);
+		isp_video_dmaqueue_flags_clr(&prev->video_out);
+	}
+}
+
+static void preview_isr_buffer(struct isp_prev_device *prev)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&prev->subdev.entity);
+	struct isp_buffer *buffer;
+	int restart = 0;
+
+	if (prev->input == PREVIEW_INPUT_MEMORY) {
+		buffer = omap3isp_video_buffer_next(&prev->video_in,
+						    prev->error);
+		if (buffer != NULL)
+			preview_set_inaddr(prev, buffer->isp_addr);
+		pipe->state |= ISP_PIPELINE_IDLE_INPUT;
+	}
+
+	if (prev->output & PREVIEW_OUTPUT_MEMORY) {
+		buffer = omap3isp_video_buffer_next(&prev->video_out,
+						    prev->error);
+		if (buffer != NULL) {
+			preview_set_outaddr(prev, buffer->isp_addr);
+			restart = 1;
+		}
+		pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
+	}
+
+	switch (prev->state) {
+	case ISP_PIPELINE_STREAM_SINGLESHOT:
+		if (isp_pipeline_ready(pipe))
+			omap3isp_pipeline_set_stream(pipe,
+						ISP_PIPELINE_STREAM_SINGLESHOT);
+		break;
+
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		/* If an underrun occurs, the video queue operation handler will
+		 * restart the preview engine. Otherwise restart it immediately.
+		 */
+		if (restart)
+			preview_enable_oneshot(prev);
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+	default:
+		return;
+	}
+
+	prev->error = 0;
+}
+
+/*
+ * omap3isp_preview_isr - ISP preview engine interrupt handler
+ *
+ * Manage the preview engine video buffers and configure shadowed registers.
+ */
+void omap3isp_preview_isr(struct isp_prev_device *prev)
+{
+	unsigned long flags;
+
+	if (omap3isp_module_sync_is_stopping(&prev->wait, &prev->stopping))
+		return;
+
+	spin_lock_irqsave(&prev->lock, flags);
+	if (prev->shadow_update)
+		goto done;
+
+	preview_setup_hw(prev);
+	preview_config_input_size(prev);
+
+done:
+	spin_unlock_irqrestore(&prev->lock, flags);
+
+	if (prev->input == PREVIEW_INPUT_MEMORY ||
+	    prev->output & PREVIEW_OUTPUT_MEMORY)
+		preview_isr_buffer(prev);
+	else if (prev->state == ISP_PIPELINE_STREAM_CONTINUOUS)
+		preview_enable_oneshot(prev);
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP video operations
+ */
+
+static int preview_video_queue(struct isp_video *video,
+			       struct isp_buffer *buffer)
+{
+	struct isp_prev_device *prev = &video->isp->isp_prev;
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		preview_set_inaddr(prev, buffer->isp_addr);
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		preview_set_outaddr(prev, buffer->isp_addr);
+
+	return 0;
+}
+
+static const struct isp_video_operations preview_video_ops = {
+	.queue = preview_video_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+/*
+ * preview_s_ctrl - Handle set control subdev method
+ * @ctrl: pointer to v4l2 control structure
+ */
+static int preview_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+	struct isp_prev_device *prev =
+		container_of(ctrl->handler, struct isp_prev_device, ctrls);
+
+	switch (ctrl->id) {
+	case V4L2_CID_BRIGHTNESS:
+		preview_update_brightness(prev, ctrl->val);
+		break;
+	case V4L2_CID_CONTRAST:
+		preview_update_contrast(prev, ctrl->val);
+		break;
+	}
+
+	return 0;
+}
+
+static const struct v4l2_ctrl_ops preview_ctrl_ops = {
+	.s_ctrl = preview_s_ctrl,
+};
+
+/*
+ * preview_ioctl - Handle preview module private ioctl's
+ * @prev: pointer to preview context structure
+ * @cmd: configuration command
+ * @arg: configuration argument
+ * return -EINVAL or zero on success
+ */
+static long preview_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+
+	switch (cmd) {
+	case VIDIOC_OMAP3ISP_PRV_CFG:
+		return preview_config(prev, arg);
+
+	default:
+		return -ENOIOCTLCMD;
+	}
+}
+
+/*
+ * preview_set_stream - Enable/Disable streaming on preview subdev
+ * @sd    : pointer to v4l2 subdev structure
+ * @enable: 1 == Enable, 0 == Disable
+ * return -EINVAL or zero on success
+ */
+static int preview_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+	struct isp_video *video_out = &prev->video_out;
+	struct isp_device *isp = to_isp_device(prev);
+	struct device *dev = to_device(prev);
+	unsigned long flags;
+
+	if (prev->state == ISP_PIPELINE_STREAM_STOPPED) {
+		if (enable == ISP_PIPELINE_STREAM_STOPPED)
+			return 0;
+
+		omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
+		preview_configure(prev);
+		atomic_set(&prev->stopping, 0);
+		prev->error = 0;
+		preview_print_status(prev);
+	}
+
+	switch (enable) {
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		if (prev->output & PREVIEW_OUTPUT_MEMORY)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
+
+		if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED ||
+		    !(prev->output & PREVIEW_OUTPUT_MEMORY))
+			preview_enable_oneshot(prev);
+
+		isp_video_dmaqueue_flags_clr(video_out);
+		break;
+
+	case ISP_PIPELINE_STREAM_SINGLESHOT:
+		if (prev->input == PREVIEW_INPUT_MEMORY)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
+		if (prev->output & PREVIEW_OUTPUT_MEMORY)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
+
+		preview_enable_oneshot(prev);
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+		if (omap3isp_module_sync_idle(&sd->entity, &prev->wait,
+					      &prev->stopping))
+			dev_dbg(dev, "%s: stop timeout.\n", sd->name);
+		spin_lock_irqsave(&prev->lock, flags);
+		omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_READ);
+		omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_PREVIEW_WRITE);
+		omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_PREVIEW);
+		spin_unlock_irqrestore(&prev->lock, flags);
+		isp_video_dmaqueue_flags_clr(video_out);
+		break;
+	}
+
+	prev->state = enable;
+	return 0;
+}
+
+static struct v4l2_mbus_framefmt *
+__preview_get_format(struct isp_prev_device *prev, struct v4l2_subdev_fh *fh,
+		     unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_format(fh, pad);
+	else
+		return &prev->formats[pad];
+}
+
+/* previewer format descriptions */
+static const unsigned int preview_input_fmts[] = {
+	V4L2_MBUS_FMT_SGRBG10_1X10,
+	V4L2_MBUS_FMT_SRGGB10_1X10,
+	V4L2_MBUS_FMT_SBGGR10_1X10,
+	V4L2_MBUS_FMT_SGBRG10_1X10,
+};
+
+static const unsigned int preview_output_fmts[] = {
+	V4L2_MBUS_FMT_UYVY8_1X16,
+	V4L2_MBUS_FMT_YUYV8_1X16,
+};
+
+/*
+ * preview_try_format - Handle try format by pad subdev method
+ * @prev: ISP preview device
+ * @fh : V4L2 subdev file handle
+ * @pad: pad num
+ * @fmt: pointer to v4l2 format structure
+ */
+static void preview_try_format(struct isp_prev_device *prev,
+			       struct v4l2_subdev_fh *fh, unsigned int pad,
+			       struct v4l2_mbus_framefmt *fmt,
+			       enum v4l2_subdev_format_whence which)
+{
+	struct v4l2_mbus_framefmt *format;
+	unsigned int max_out_width;
+	enum v4l2_mbus_pixelcode pixelcode;
+	unsigned int i;
+
+	max_out_width = preview_max_out_width(prev);
+
+	switch (pad) {
+	case PREV_PAD_SINK:
+		/* When reading data from the CCDC, the input size has already
+		 * been mangled by the CCDC output pad so it can be accepted
+		 * as-is.
+		 *
+		 * When reading data from memory, clamp the requested width and
+		 * height. The TRM doesn't specify a minimum input height, make
+		 * sure we got enough lines to enable the noise filter and color
+		 * filter array interpolation.
+		 */
+		if (prev->input == PREVIEW_INPUT_MEMORY) {
+			fmt->width = clamp_t(u32, fmt->width, PREV_MIN_WIDTH,
+					     max_out_width * 8);
+			fmt->height = clamp_t(u32, fmt->height, PREV_MIN_HEIGHT,
+					      PREV_MAX_HEIGHT);
+		}
+
+		fmt->colorspace = V4L2_COLORSPACE_SRGB;
+
+		for (i = 0; i < ARRAY_SIZE(preview_input_fmts); i++) {
+			if (fmt->code == preview_input_fmts[i])
+				break;
+		}
+
+		/* If not found, use SGRBG10 as default */
+		if (i >= ARRAY_SIZE(preview_input_fmts))
+			fmt->code = V4L2_MBUS_FMT_SGRBG10_1X10;
+		break;
+
+	case PREV_PAD_SOURCE:
+		pixelcode = fmt->code;
+		format = __preview_get_format(prev, fh, PREV_PAD_SINK, which);
+		memcpy(fmt, format, sizeof(*fmt));
+
+		/* The preview module output size is configurable through the
+		 * input interface (horizontal and vertical cropping) and the
+		 * averager (horizontal scaling by 1/1, 1/2, 1/4 or 1/8). In
+		 * spite of this, hardcode the output size to the biggest
+		 * possible value for simplicity reasons.
+		 */
+		switch (pixelcode) {
+		case V4L2_MBUS_FMT_YUYV8_1X16:
+		case V4L2_MBUS_FMT_UYVY8_1X16:
+			fmt->code = pixelcode;
+			break;
+
+		default:
+			fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+			break;
+		}
+
+		/* The TRM states (12.1.4.7.1.2) that 2 pixels must be cropped
+		 * from the left and right sides when the input source is the
+		 * CCDC. This seems not to be needed in practice, investigation
+		 * is required.
+		 */
+		if (prev->input == PREVIEW_INPUT_CCDC)
+			fmt->width -= 4;
+
+		/* The preview module can output a maximum of 3312 pixels
+		 * horizontally due to fixed memory-line sizes. Compute the
+		 * horizontal averaging factor accordingly. Note that the limit
+		 * applies to the noise filter and CFA interpolation blocks, so
+		 * it doesn't take cropping by further blocks into account.
+		 *
+		 * ES 1.0 hardware revision is limited to 1280 pixels
+		 * horizontally.
+		 */
+		fmt->width >>= fls(DIV_ROUND_UP(fmt->width, max_out_width) - 1);
+
+		/* Assume that all blocks are enabled and crop pixels and lines
+		 * accordingly. See preview_config_input_size() for more
+		 * information.
+		 */
+		fmt->width -= 14;
+		fmt->height -= 8;
+
+		fmt->colorspace = V4L2_COLORSPACE_JPEG;
+		break;
+	}
+
+	fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * preview_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh     : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int preview_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	switch (code->pad) {
+	case PREV_PAD_SINK:
+		if (code->index >= ARRAY_SIZE(preview_input_fmts))
+			return -EINVAL;
+
+		code->code = preview_input_fmts[code->index];
+		break;
+	case PREV_PAD_SOURCE:
+		if (code->index >= ARRAY_SIZE(preview_output_fmts))
+			return -EINVAL;
+
+		code->code = preview_output_fmts[code->index];
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int preview_enum_frame_size(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt format;
+
+	if (fse->index != 0)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = 1;
+	format.height = 1;
+	preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->min_width = format.width;
+	fse->min_height = format.height;
+
+	if (format.code != fse->code)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = -1;
+	format.height = -1;
+	preview_try_format(prev, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->max_width = format.width;
+	fse->max_height = format.height;
+
+	return 0;
+}
+
+/*
+ * preview_get_format - Handle get format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int preview_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+/*
+ * preview_set_format - Handle set format by pads subdev method
+ * @sd : pointer to v4l2 subdev structure
+ * @fh : V4L2 subdev file handle
+ * @fmt: pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int preview_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __preview_get_format(prev, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	preview_try_format(prev, fh, fmt->pad, &fmt->format, fmt->which);
+	*format = fmt->format;
+
+	/* Propagate the format from sink to source */
+	if (fmt->pad == PREV_PAD_SINK) {
+		format = __preview_get_format(prev, fh, PREV_PAD_SOURCE,
+					      fmt->which);
+		*format = fmt->format;
+		preview_try_format(prev, fh, PREV_PAD_SOURCE, format,
+				   fmt->which);
+	}
+
+	return 0;
+}
+
+/*
+ * preview_init_formats - Initialize formats on all pads
+ * @sd: ISP preview V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int preview_init_formats(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_subdev_format format;
+
+	memset(&format, 0, sizeof(format));
+	format.pad = PREV_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_SGRBG10_1X10;
+	format.format.width = 4096;
+	format.format.height = 4096;
+	preview_set_format(sd, fh, &format);
+
+	return 0;
+}
+
+/* subdev core operations */
+static const struct v4l2_subdev_core_ops preview_v4l2_core_ops = {
+	.ioctl = preview_ioctl,
+};
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops preview_v4l2_video_ops = {
+	.s_stream = preview_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops preview_v4l2_pad_ops = {
+	.enum_mbus_code = preview_enum_mbus_code,
+	.enum_frame_size = preview_enum_frame_size,
+	.get_fmt = preview_get_format,
+	.set_fmt = preview_set_format,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops preview_v4l2_ops = {
+	.core = &preview_v4l2_core_ops,
+	.video = &preview_v4l2_video_ops,
+	.pad = &preview_v4l2_pad_ops,
+};
+
+/* subdev internal operations */
+static const struct v4l2_subdev_internal_ops preview_v4l2_internal_ops = {
+	.open = preview_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * preview_link_setup - Setup previewer connections.
+ * @entity : Pointer to media entity structure
+ * @local  : Pointer to local pad array
+ * @remote : Pointer to remote pad array
+ * @flags  : Link flags
+ * return -EINVAL or zero on success
+ */
+static int preview_link_setup(struct media_entity *entity,
+			      const struct media_pad *local,
+			      const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct isp_prev_device *prev = v4l2_get_subdevdata(sd);
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case PREV_PAD_SINK | MEDIA_ENT_T_DEVNODE:
+		/* read from memory */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (prev->input == PREVIEW_INPUT_CCDC)
+				return -EBUSY;
+			prev->input = PREVIEW_INPUT_MEMORY;
+		} else {
+			if (prev->input == PREVIEW_INPUT_MEMORY)
+				prev->input = PREVIEW_INPUT_NONE;
+		}
+		break;
+
+	case PREV_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* read from ccdc */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (prev->input == PREVIEW_INPUT_MEMORY)
+				return -EBUSY;
+			prev->input = PREVIEW_INPUT_CCDC;
+		} else {
+			if (prev->input == PREVIEW_INPUT_CCDC)
+				prev->input = PREVIEW_INPUT_NONE;
+		}
+		break;
+
+	/*
+	 * The ISP core doesn't support pipelines with multiple video outputs.
+	 * Revisit this when it will be implemented, and return -EBUSY for now.
+	 */
+
+	case PREV_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+		/* write to memory */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (prev->output & ~PREVIEW_OUTPUT_MEMORY)
+				return -EBUSY;
+			prev->output |= PREVIEW_OUTPUT_MEMORY;
+		} else {
+			prev->output &= ~PREVIEW_OUTPUT_MEMORY;
+		}
+		break;
+
+	case PREV_PAD_SOURCE | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* write to resizer */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (prev->output & ~PREVIEW_OUTPUT_RESIZER)
+				return -EBUSY;
+			prev->output |= PREVIEW_OUTPUT_RESIZER;
+		} else {
+			prev->output &= ~PREVIEW_OUTPUT_RESIZER;
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations preview_media_ops = {
+	.link_setup = preview_link_setup,
+};
+
+/*
+ * review_init_entities - Initialize subdev and media entity.
+ * @prev : Pointer to preview structure
+ * return -ENOMEM or zero on success
+ */
+static int preview_init_entities(struct isp_prev_device *prev)
+{
+	struct v4l2_subdev *sd = &prev->subdev;
+	struct media_pad *pads = prev->pads;
+	struct media_entity *me = &sd->entity;
+	int ret;
+
+	prev->input = PREVIEW_INPUT_NONE;
+
+	v4l2_subdev_init(sd, &preview_v4l2_ops);
+	sd->internal_ops = &preview_v4l2_internal_ops;
+	strlcpy(sd->name, "OMAP3 ISP preview", sizeof(sd->name));
+	sd->grp_id = 1 << 16;	/* group ID for isp subdevs */
+	v4l2_set_subdevdata(sd, prev);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	v4l2_ctrl_handler_init(&prev->ctrls, 2);
+	v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_BRIGHTNESS,
+			  ISPPRV_BRIGHT_LOW, ISPPRV_BRIGHT_HIGH,
+			  ISPPRV_BRIGHT_STEP, ISPPRV_BRIGHT_DEF);
+	v4l2_ctrl_new_std(&prev->ctrls, &preview_ctrl_ops, V4L2_CID_CONTRAST,
+			  ISPPRV_CONTRAST_LOW, ISPPRV_CONTRAST_HIGH,
+			  ISPPRV_CONTRAST_STEP, ISPPRV_CONTRAST_DEF);
+	v4l2_ctrl_handler_setup(&prev->ctrls);
+	sd->ctrl_handler = &prev->ctrls;
+
+	pads[PREV_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	pads[PREV_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	me->ops = &preview_media_ops;
+	ret = media_entity_init(me, PREV_PADS_NUM, pads, 0);
+	if (ret < 0)
+		return ret;
+
+	preview_init_formats(sd, NULL);
+
+	/* According to the OMAP34xx TRM, video buffers need to be aligned on a
+	 * 32 bytes boundary. However, an undocumented hardware bug requires a
+	 * 64 bytes boundary at the preview engine input.
+	 */
+	prev->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	prev->video_in.ops = &preview_video_ops;
+	prev->video_in.isp = to_isp_device(prev);
+	prev->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
+	prev->video_in.bpl_alignment = 64;
+	prev->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	prev->video_out.ops = &preview_video_ops;
+	prev->video_out.isp = to_isp_device(prev);
+	prev->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
+	prev->video_out.bpl_alignment = 32;
+
+	ret = omap3isp_video_init(&prev->video_in, "preview");
+	if (ret < 0)
+		return ret;
+
+	ret = omap3isp_video_init(&prev->video_out, "preview");
+	if (ret < 0)
+		return ret;
+
+	/* Connect the video nodes to the previewer subdev. */
+	ret = media_entity_create_link(&prev->video_in.video.entity, 0,
+			&prev->subdev.entity, PREV_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_entity_create_link(&prev->subdev.entity, PREV_PAD_SOURCE,
+			&prev->video_out.video.entity, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void omap3isp_preview_unregister_entities(struct isp_prev_device *prev)
+{
+	media_entity_cleanup(&prev->subdev.entity);
+
+	v4l2_device_unregister_subdev(&prev->subdev);
+	v4l2_ctrl_handler_free(&prev->ctrls);
+	omap3isp_video_unregister(&prev->video_in);
+	omap3isp_video_unregister(&prev->video_out);
+}
+
+int omap3isp_preview_register_entities(struct isp_prev_device *prev,
+	struct v4l2_device *vdev)
+{
+	int ret;
+
+	/* Register the subdev and video nodes. */
+	ret = v4l2_device_register_subdev(vdev, &prev->subdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&prev->video_in, vdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&prev->video_out, vdev);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+error:
+	omap3isp_preview_unregister_entities(prev);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP previewer initialisation and cleanup
+ */
+
+void omap3isp_preview_cleanup(struct isp_device *isp)
+{
+}
+
+/*
+ * isp_preview_init - Previewer initialization.
+ * @dev : Pointer to ISP device
+ * return -ENOMEM or zero on success
+ */
+int omap3isp_preview_init(struct isp_device *isp)
+{
+	struct isp_prev_device *prev = &isp->isp_prev;
+	int ret;
+
+	spin_lock_init(&prev->lock);
+	init_waitqueue_head(&prev->wait);
+	preview_init_params(prev);
+
+	ret = preview_init_entities(prev);
+	if (ret < 0)
+		goto out;
+
+out:
+	if (ret)
+		omap3isp_preview_cleanup(isp);
+
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isppreview.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isppreview.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/isppreview.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/isppreview.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,214 @@
+/*
+ * isppreview.h
+ *
+ * TI OMAP3 ISP - Preview module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_PREVIEW_H
+#define OMAP3_ISP_PREVIEW_H
+
+#include <linux/omap3isp.h>
+#include <linux/types.h>
+#include <media/v4l2-ctrls.h>
+
+#include "ispvideo.h"
+
+#define ISPPRV_BRIGHT_STEP		0x1
+#define ISPPRV_BRIGHT_DEF		0x0
+#define ISPPRV_BRIGHT_LOW		0x0
+#define ISPPRV_BRIGHT_HIGH		0xFF
+#define ISPPRV_BRIGHT_UNITS		0x1
+
+#define ISPPRV_CONTRAST_STEP		0x1
+#define ISPPRV_CONTRAST_DEF		0x10
+#define ISPPRV_CONTRAST_LOW		0x0
+#define ISPPRV_CONTRAST_HIGH		0xFF
+#define ISPPRV_CONTRAST_UNITS		0x1
+
+#define NO_AVE				0x0
+#define AVE_2_PIX			0x1
+#define AVE_4_PIX			0x2
+#define AVE_8_PIX			0x3
+
+/* Features list */
+#define PREV_LUMA_ENHANCE		OMAP3ISP_PREV_LUMAENH
+#define PREV_INVERSE_ALAW		OMAP3ISP_PREV_INVALAW
+#define PREV_HORZ_MEDIAN_FILTER		OMAP3ISP_PREV_HRZ_MED
+#define PREV_CFA			OMAP3ISP_PREV_CFA
+#define PREV_CHROMA_SUPPRESS		OMAP3ISP_PREV_CHROMA_SUPP
+#define PREV_WB				OMAP3ISP_PREV_WB
+#define PREV_BLKADJ			OMAP3ISP_PREV_BLKADJ
+#define PREV_RGB2RGB			OMAP3ISP_PREV_RGB2RGB
+#define PREV_COLOR_CONV			OMAP3ISP_PREV_COLOR_CONV
+#define PREV_YCLIMITS			OMAP3ISP_PREV_YC_LIMIT
+#define PREV_DEFECT_COR			OMAP3ISP_PREV_DEFECT_COR
+#define PREV_GAMMA_BYPASS		OMAP3ISP_PREV_GAMMABYPASS
+#define PREV_DARK_FRAME_CAPTURE		OMAP3ISP_PREV_DRK_FRM_CAPTURE
+#define PREV_DARK_FRAME_SUBTRACT	OMAP3ISP_PREV_DRK_FRM_SUBTRACT
+#define PREV_LENS_SHADING		OMAP3ISP_PREV_LENS_SHADING
+#define PREV_NOISE_FILTER		OMAP3ISP_PREV_NF
+#define PREV_GAMMA			OMAP3ISP_PREV_GAMMA
+
+#define PREV_CONTRAST			(1 << 17)
+#define PREV_BRIGHTNESS			(1 << 18)
+#define PREV_AVERAGER			(1 << 19)
+#define PREV_FEATURES_END		(1 << 20)
+
+enum preview_input_entity {
+	PREVIEW_INPUT_NONE,
+	PREVIEW_INPUT_CCDC,
+	PREVIEW_INPUT_MEMORY,
+};
+
+#define PREVIEW_OUTPUT_RESIZER		(1 << 1)
+#define PREVIEW_OUTPUT_MEMORY		(1 << 2)
+
+/* Configure byte layout of YUV image */
+enum preview_ycpos_mode {
+	YCPOS_YCrYCb = 0,
+	YCPOS_YCbYCr = 1,
+	YCPOS_CbYCrY = 2,
+	YCPOS_CrYCbY = 3
+};
+
+/*
+ * struct prev_params - Structure for all configuration
+ * @features: Set of features enabled.
+ * @cfa: CFA coefficients.
+ * @csup: Chroma suppression coefficients.
+ * @luma: Luma enhancement coefficients.
+ * @nf: Noise filter coefficients.
+ * @dcor: Noise filter coefficients.
+ * @gamma: Gamma coefficients.
+ * @wbal: White Balance parameters.
+ * @blk_adj: Black adjustment parameters.
+ * @rgb2rgb: RGB blending parameters.
+ * @rgb2ycbcr: RGB to ycbcr parameters.
+ * @hmed: Horizontal median filter.
+ * @yclimit: YC limits parameters.
+ * @average: Downsampling rate for averager.
+ * @contrast: Contrast.
+ * @brightness: Brightness.
+ */
+struct prev_params {
+	u32 features;
+	struct omap3isp_prev_cfa cfa;
+	struct omap3isp_prev_csup csup;
+	struct omap3isp_prev_luma luma;
+	struct omap3isp_prev_nf nf;
+	struct omap3isp_prev_dcor dcor;
+	struct omap3isp_prev_gtables gamma;
+	struct omap3isp_prev_wbal wbal;
+	struct omap3isp_prev_blkadj blk_adj;
+	struct omap3isp_prev_rgbtorgb rgb2rgb;
+	struct omap3isp_prev_csc rgb2ycbcr;
+	struct omap3isp_prev_hmed hmed;
+	struct omap3isp_prev_yclimit yclimit;
+	u8 average;
+	u8 contrast;
+	u8 brightness;
+};
+
+/*
+ * struct isptables_update - Structure for Table Configuration.
+ * @update: Specifies which tables should be updated.
+ * @flag: Specifies which tables should be enabled.
+ * @nf: Pointer to structure for Noise Filter
+ * @lsc: Pointer to LSC gain table. (currently not used)
+ * @gamma: Pointer to gamma correction tables.
+ * @cfa: Pointer to color filter array configuration.
+ * @wbal: Pointer to colour and digital gain configuration.
+ */
+struct isptables_update {
+	u32 update;
+	u32 flag;
+	struct omap3isp_prev_nf *nf;
+	u32 *lsc;
+	struct omap3isp_prev_gtables *gamma;
+	struct omap3isp_prev_cfa *cfa;
+	struct omap3isp_prev_wbal *wbal;
+};
+
+/* Sink and source previewer pads */
+#define PREV_PAD_SINK			0
+#define PREV_PAD_SOURCE			1
+#define PREV_PADS_NUM			2
+
+/*
+ * struct isp_prev_device - Structure for storing ISP Preview module information
+ * @subdev: V4L2 subdevice
+ * @pads: Media entity pads
+ * @formats: Active formats at the subdev pad
+ * @input: Module currently connected to the input pad
+ * @output: Bitmask of the active output
+ * @video_in: Input video entity
+ * @video_out: Output video entity
+ * @error: A hardware error occurred during capture
+ * @params: Module configuration data
+ * @shadow_update: If set, update the hardware configured in the next interrupt
+ * @underrun: Whether the preview entity has queued buffers on the output
+ * @state: Current preview pipeline state
+ * @lock: Shadow update lock
+ * @update: Bitmask of the parameters to be updated
+ *
+ * This structure is used to store the OMAP ISP Preview module Information.
+ */
+struct isp_prev_device {
+	struct v4l2_subdev subdev;
+	struct media_pad pads[PREV_PADS_NUM];
+	struct v4l2_mbus_framefmt formats[PREV_PADS_NUM];
+
+	struct v4l2_ctrl_handler ctrls;
+
+	enum preview_input_entity input;
+	unsigned int output;
+	struct isp_video video_in;
+	struct isp_video video_out;
+	unsigned int error;
+
+	struct prev_params params;
+	unsigned int shadow_update:1;
+	enum isp_pipeline_stream_state state;
+	wait_queue_head_t wait;
+	atomic_t stopping;
+	spinlock_t lock;
+	u32 update;
+};
+
+struct isp_device;
+
+int omap3isp_preview_init(struct isp_device *isp);
+void omap3isp_preview_cleanup(struct isp_device *isp);
+
+int omap3isp_preview_register_entities(struct isp_prev_device *prv,
+				       struct v4l2_device *vdev);
+void omap3isp_preview_unregister_entities(struct isp_prev_device *prv);
+
+void omap3isp_preview_isr_frame_sync(struct isp_prev_device *prev);
+void omap3isp_preview_isr(struct isp_prev_device *prev);
+
+int omap3isp_preview_busy(struct isp_prev_device *isp_prev);
+
+void omap3isp_preview_restore_context(struct isp_device *isp);
+
+#endif	/* OMAP3_ISP_PREVIEW_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispqueue.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispqueue.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispqueue.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispqueue.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1153 @@
+/*
+ * ispqueue.c
+ *
+ * TI OMAP3 ISP - Video buffers queue handling
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 <asm/cacheflush.h>
+#include <linux/dma-mapping.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/poll.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include "ispqueue.h"
+
+/* -----------------------------------------------------------------------------
+ * Video buffers management
+ */
+
+/*
+ * isp_video_buffer_cache_sync - Keep the buffers coherent between CPU and ISP
+ *
+ * The typical operation required here is Cache Invalidation across
+ * the (user space) buffer address range. And this _must_ be done
+ * at QBUF stage (and *only* at QBUF).
+ *
+ * We try to use optimal cache invalidation function:
+ * - dmac_map_area:
+ *    - used when the number of pages are _low_.
+ *    - it becomes quite slow as the number of pages increase.
+ *       - for 648x492 viewfinder (150 pages) it takes 1.3 ms.
+ *       - for 5 Mpix buffer (2491 pages) it takes between 25-50 ms.
+ *
+ * - flush_cache_all:
+ *    - used when the number of pages are _high_.
+ *    - time taken in the range of 500-900 us.
+ *    - has a higher penalty but, as whole dcache + icache is invalidated
+ */
+/*
+ * FIXME: dmac_inv_range crashes randomly on the user space buffer
+ *        address. Fall back to flush_cache_all for now.
+ */
+#define ISP_CACHE_FLUSH_PAGES_MAX       0
+
+static void isp_video_buffer_cache_sync(struct isp_video_buffer *buf)
+{
+	if (buf->skip_cache)
+		return;
+
+	if (buf->vbuf.m.userptr == 0 || buf->npages == 0 ||
+	    buf->npages > ISP_CACHE_FLUSH_PAGES_MAX)
+		flush_cache_all();
+	else {
+		dmac_map_area((void *)buf->vbuf.m.userptr, buf->vbuf.length,
+			      DMA_FROM_DEVICE);
+		outer_inv_range(buf->vbuf.m.userptr,
+				buf->vbuf.m.userptr + buf->vbuf.length);
+	}
+}
+
+/*
+ * isp_video_buffer_lock_vma - Prevent VMAs from being unmapped
+ *
+ * Lock the VMAs underlying the given buffer into memory. This avoids the
+ * userspace buffer mapping from being swapped out, making VIPT cache handling
+ * easier.
+ *
+ * Note that the pages will not be freed as the buffers have been locked to
+ * memory using by a call to get_user_pages(), but the userspace mapping could
+ * still disappear if the VMAs are not locked. This is caused by the memory
+ * management code trying to be as lock-less as possible, which results in the
+ * userspace mapping manager not finding out that the pages are locked under
+ * some conditions.
+ */
+static int isp_video_buffer_lock_vma(struct isp_video_buffer *buf, int lock)
+{
+	struct vm_area_struct *vma;
+	unsigned long start;
+	unsigned long end;
+	int ret = 0;
+
+	if (buf->vbuf.memory == V4L2_MEMORY_MMAP)
+		return 0;
+
+	/* We can be called from workqueue context if the current task dies to
+	 * unlock the VMAs. In that case there's no current memory management
+	 * context so unlocking can't be performed, but the VMAs have been or
+	 * are getting destroyed anyway so it doesn't really matter.
+	 */
+	if (!current || !current->mm)
+		return lock ? -EINVAL : 0;
+
+	start = buf->vbuf.m.userptr;
+	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
+
+	down_write(&current->mm->mmap_sem);
+	spin_lock(&current->mm->page_table_lock);
+
+	do {
+		vma = find_vma(current->mm, start);
+		if (vma == NULL) {
+			ret = -EFAULT;
+			goto out;
+		}
+
+		if (lock)
+			vma->vm_flags |= VM_LOCKED;
+		else
+			vma->vm_flags &= ~VM_LOCKED;
+
+		start = vma->vm_end + 1;
+	} while (vma->vm_end < end);
+
+	if (lock)
+		buf->vm_flags |= VM_LOCKED;
+	else
+		buf->vm_flags &= ~VM_LOCKED;
+
+out:
+	spin_unlock(&current->mm->page_table_lock);
+	up_write(&current->mm->mmap_sem);
+	return ret;
+}
+
+/*
+ * isp_video_buffer_sglist_kernel - Build a scatter list for a vmalloc'ed buffer
+ *
+ * Iterate over the vmalloc'ed area and create a scatter list entry for every
+ * page.
+ */
+static int isp_video_buffer_sglist_kernel(struct isp_video_buffer *buf)
+{
+	struct scatterlist *sglist;
+	unsigned int npages;
+	unsigned int i;
+	void *addr;
+
+	addr = buf->vaddr;
+	npages = PAGE_ALIGN(buf->vbuf.length) >> PAGE_SHIFT;
+
+	sglist = vmalloc(npages * sizeof(*sglist));
+	if (sglist == NULL)
+		return -ENOMEM;
+
+	sg_init_table(sglist, npages);
+
+	for (i = 0; i < npages; ++i, addr += PAGE_SIZE) {
+		struct page *page = vmalloc_to_page(addr);
+
+		if (page == NULL || PageHighMem(page)) {
+			vfree(sglist);
+			return -EINVAL;
+		}
+
+		sg_set_page(&sglist[i], page, PAGE_SIZE, 0);
+	}
+
+	buf->sglen = npages;
+	buf->sglist = sglist;
+
+	return 0;
+}
+
+/*
+ * isp_video_buffer_sglist_user - Build a scatter list for a userspace buffer
+ *
+ * Walk the buffer pages list and create a 1:1 mapping to a scatter list.
+ */
+static int isp_video_buffer_sglist_user(struct isp_video_buffer *buf)
+{
+	struct scatterlist *sglist;
+	unsigned int offset = buf->offset;
+	unsigned int i;
+
+	sglist = vmalloc(buf->npages * sizeof(*sglist));
+	if (sglist == NULL)
+		return -ENOMEM;
+
+	sg_init_table(sglist, buf->npages);
+
+	for (i = 0; i < buf->npages; ++i) {
+		if (PageHighMem(buf->pages[i])) {
+			vfree(sglist);
+			return -EINVAL;
+		}
+
+		sg_set_page(&sglist[i], buf->pages[i], PAGE_SIZE - offset,
+			    offset);
+		offset = 0;
+	}
+
+	buf->sglen = buf->npages;
+	buf->sglist = sglist;
+
+	return 0;
+}
+
+/*
+ * isp_video_buffer_sglist_pfnmap - Build a scatter list for a VM_PFNMAP buffer
+ *
+ * Create a scatter list of physically contiguous pages starting at the buffer
+ * memory physical address.
+ */
+static int isp_video_buffer_sglist_pfnmap(struct isp_video_buffer *buf)
+{
+	struct scatterlist *sglist;
+	unsigned int offset = buf->offset;
+	unsigned long pfn = buf->paddr >> PAGE_SHIFT;
+	unsigned int i;
+
+	sglist = vmalloc(buf->npages * sizeof(*sglist));
+	if (sglist == NULL)
+		return -ENOMEM;
+
+	sg_init_table(sglist, buf->npages);
+
+	for (i = 0; i < buf->npages; ++i, ++pfn) {
+		sg_set_page(&sglist[i], pfn_to_page(pfn), PAGE_SIZE - offset,
+			    offset);
+		/* PFNMAP buffers will not get DMA-mapped, set the DMA address
+		 * manually.
+		 */
+		sg_dma_address(&sglist[i]) = (pfn << PAGE_SHIFT) + offset;
+		offset = 0;
+	}
+
+	buf->sglen = buf->npages;
+	buf->sglist = sglist;
+
+	return 0;
+}
+
+/*
+ * isp_video_buffer_cleanup - Release pages for a userspace VMA.
+ *
+ * Release pages locked by a call isp_video_buffer_prepare_user and free the
+ * pages table.
+ */
+static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
+{
+	enum dma_data_direction direction;
+	unsigned int i;
+
+	if (buf->queue->ops->buffer_cleanup)
+		buf->queue->ops->buffer_cleanup(buf);
+
+	if (!(buf->vm_flags & VM_PFNMAP)) {
+		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+		dma_unmap_sg(buf->queue->dev, buf->sglist, buf->sglen,
+			     direction);
+	}
+
+	vfree(buf->sglist);
+	buf->sglist = NULL;
+	buf->sglen = 0;
+
+	if (buf->pages != NULL) {
+		isp_video_buffer_lock_vma(buf, 0);
+
+		for (i = 0; i < buf->npages; ++i)
+			page_cache_release(buf->pages[i]);
+
+		vfree(buf->pages);
+		buf->pages = NULL;
+	}
+
+	buf->npages = 0;
+	buf->skip_cache = false;
+}
+
+/*
+ * isp_video_buffer_prepare_user - Pin userspace VMA pages to memory.
+ *
+ * This function creates a list of pages for a userspace VMA. The number of
+ * pages is first computed based on the buffer size, and pages are then
+ * retrieved by a call to get_user_pages.
+ *
+ * Pages are pinned to memory by get_user_pages, making them available for DMA
+ * transfers. However, due to memory management optimization, it seems the
+ * get_user_pages doesn't guarantee that the pinned pages will not be written
+ * to swap and removed from the userspace mapping(s). When this happens, a page
+ * fault can be generated when accessing those unmapped pages.
+ *
+ * If the fault is triggered by a page table walk caused by VIPT cache
+ * management operations, the page fault handler might oops if the MM semaphore
+ * is held, as it can't handle kernel page faults in that case. To fix that, a
+ * fixup entry needs to be added to the cache management code, or the userspace
+ * VMA must be locked to avoid removing pages from the userspace mapping in the
+ * first place.
+ *
+ * If the number of pages retrieved is smaller than the number required by the
+ * buffer size, the function returns -EFAULT.
+ */
+static int isp_video_buffer_prepare_user(struct isp_video_buffer *buf)
+{
+	unsigned long data;
+	unsigned int first;
+	unsigned int last;
+	int ret;
+
+	data = buf->vbuf.m.userptr;
+	first = (data & PAGE_MASK) >> PAGE_SHIFT;
+	last = ((data + buf->vbuf.length - 1) & PAGE_MASK) >> PAGE_SHIFT;
+
+	buf->offset = data & ~PAGE_MASK;
+	buf->npages = last - first + 1;
+	buf->pages = vmalloc(buf->npages * sizeof(buf->pages[0]));
+	if (buf->pages == NULL)
+		return -ENOMEM;
+
+	down_read(&current->mm->mmap_sem);
+	ret = get_user_pages(current, current->mm, data & PAGE_MASK,
+			     buf->npages,
+			     buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+			     buf->pages, NULL);
+	up_read(&current->mm->mmap_sem);
+
+	if (ret != buf->npages) {
+		buf->npages = ret < 0 ? 0 : ret;
+		isp_video_buffer_cleanup(buf);
+		return -EFAULT;
+	}
+
+	ret = isp_video_buffer_lock_vma(buf, 1);
+	if (ret < 0)
+		isp_video_buffer_cleanup(buf);
+
+	return ret;
+}
+
+/*
+ * isp_video_buffer_prepare_pfnmap - Validate a VM_PFNMAP userspace buffer
+ *
+ * Userspace VM_PFNMAP buffers are supported only if they are contiguous in
+ * memory and if they span a single VMA.
+ *
+ * Return 0 if the buffer is valid, or -EFAULT otherwise.
+ */
+static int isp_video_buffer_prepare_pfnmap(struct isp_video_buffer *buf)
+{
+	struct vm_area_struct *vma;
+	unsigned long prev_pfn;
+	unsigned long this_pfn;
+	unsigned long start;
+	unsigned long end;
+	dma_addr_t pa;
+	int ret = -EFAULT;
+
+	start = buf->vbuf.m.userptr;
+	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
+
+	buf->offset = start & ~PAGE_MASK;
+	buf->npages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
+	buf->pages = NULL;
+
+	down_read(&current->mm->mmap_sem);
+	vma = find_vma(current->mm, start);
+	if (vma == NULL || vma->vm_end < end)
+		goto done;
+
+	for (prev_pfn = 0; start <= end; start += PAGE_SIZE) {
+		ret = follow_pfn(vma, start, &this_pfn);
+		if (ret)
+			goto done;
+
+		if (prev_pfn == 0)
+			pa = this_pfn << PAGE_SHIFT;
+		else if (this_pfn != prev_pfn + 1) {
+			ret = -EFAULT;
+			goto done;
+		}
+
+		prev_pfn = this_pfn;
+	}
+
+	buf->paddr = pa + buf->offset;
+	ret = 0;
+
+done:
+	up_read(&current->mm->mmap_sem);
+	return ret;
+}
+
+/*
+ * isp_video_buffer_prepare_vm_flags - Get VMA flags for a userspace address
+ *
+ * This function locates the VMAs for the buffer's userspace address and checks
+ * that their flags match. The only flag that we need to care for at the moment
+ * is VM_PFNMAP.
+ *
+ * The buffer vm_flags field is set to the first VMA flags.
+ *
+ * Return -EFAULT if no VMA can be found for part of the buffer, or if the VMAs
+ * have incompatible flags.
+ */
+static int isp_video_buffer_prepare_vm_flags(struct isp_video_buffer *buf)
+{
+	struct vm_area_struct *vma;
+	pgprot_t vm_page_prot;
+	unsigned long start;
+	unsigned long end;
+	int ret = -EFAULT;
+
+	start = buf->vbuf.m.userptr;
+	end = buf->vbuf.m.userptr + buf->vbuf.length - 1;
+
+	down_read(&current->mm->mmap_sem);
+
+	do {
+		vma = find_vma(current->mm, start);
+		if (vma == NULL)
+			goto done;
+
+		if (start == buf->vbuf.m.userptr) {
+			buf->vm_flags = vma->vm_flags;
+			vm_page_prot = vma->vm_page_prot;
+		}
+
+		if ((buf->vm_flags ^ vma->vm_flags) & VM_PFNMAP)
+			goto done;
+
+		if (vm_page_prot != vma->vm_page_prot)
+			goto done;
+
+		start = vma->vm_end + 1;
+	} while (vma->vm_end < end);
+
+	/* Skip cache management to enhance performances for non-cached or
+	 * write-combining buffers.
+	 */
+	if (vm_page_prot == pgprot_noncached(vm_page_prot) ||
+	    vm_page_prot == pgprot_writecombine(vm_page_prot))
+		buf->skip_cache = true;
+
+	ret = 0;
+
+done:
+	up_read(&current->mm->mmap_sem);
+	return ret;
+}
+
+/*
+ * isp_video_buffer_prepare - Make a buffer ready for operation
+ *
+ * Preparing a buffer involves:
+ *
+ * - validating VMAs (userspace buffers only)
+ * - locking pages and VMAs into memory (userspace buffers only)
+ * - building page and scatter-gather lists
+ * - mapping buffers for DMA operation
+ * - performing driver-specific preparation
+ *
+ * The function must be called in userspace context with a valid mm context
+ * (this excludes cleanup paths such as sys_close when the userspace process
+ * segfaults).
+ */
+static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
+{
+	enum dma_data_direction direction;
+	int ret;
+
+	switch (buf->vbuf.memory) {
+	case V4L2_MEMORY_MMAP:
+		ret = isp_video_buffer_sglist_kernel(buf);
+		break;
+
+	case V4L2_MEMORY_USERPTR:
+		ret = isp_video_buffer_prepare_vm_flags(buf);
+		if (ret < 0)
+			return ret;
+
+		if (buf->vm_flags & VM_PFNMAP) {
+			ret = isp_video_buffer_prepare_pfnmap(buf);
+			if (ret < 0)
+				return ret;
+
+			ret = isp_video_buffer_sglist_pfnmap(buf);
+		} else {
+			ret = isp_video_buffer_prepare_user(buf);
+			if (ret < 0)
+				return ret;
+
+			ret = isp_video_buffer_sglist_user(buf);
+		}
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	if (ret < 0)
+		goto done;
+
+	if (!(buf->vm_flags & VM_PFNMAP)) {
+		direction = buf->vbuf.type == V4L2_BUF_TYPE_VIDEO_CAPTURE
+			  ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+		ret = dma_map_sg(buf->queue->dev, buf->sglist, buf->sglen,
+				 direction);
+		if (ret != buf->sglen) {
+			ret = -EFAULT;
+			goto done;
+		}
+	}
+
+	if (buf->queue->ops->buffer_prepare)
+		ret = buf->queue->ops->buffer_prepare(buf);
+
+done:
+	if (ret < 0) {
+		isp_video_buffer_cleanup(buf);
+		return ret;
+	}
+
+	return ret;
+}
+
+/*
+ * isp_video_queue_query - Query the status of a given buffer
+ *
+ * Locking: must be called with the queue lock held.
+ */
+static void isp_video_buffer_query(struct isp_video_buffer *buf,
+				   struct v4l2_buffer *vbuf)
+{
+	memcpy(vbuf, &buf->vbuf, sizeof(*vbuf));
+
+	if (buf->vma_use_count)
+		vbuf->flags |= V4L2_BUF_FLAG_MAPPED;
+
+	switch (buf->state) {
+	case ISP_BUF_STATE_ERROR:
+		vbuf->flags |= V4L2_BUF_FLAG_ERROR;
+	case ISP_BUF_STATE_DONE:
+		vbuf->flags |= V4L2_BUF_FLAG_DONE;
+	case ISP_BUF_STATE_QUEUED:
+	case ISP_BUF_STATE_ACTIVE:
+		vbuf->flags |= V4L2_BUF_FLAG_QUEUED;
+		break;
+	case ISP_BUF_STATE_IDLE:
+	default:
+		break;
+	}
+}
+
+/*
+ * isp_video_buffer_wait - Wait for a buffer to be ready
+ *
+ * In non-blocking mode, return immediately with 0 if the buffer is ready or
+ * -EAGAIN if the buffer is in the QUEUED or ACTIVE state.
+ *
+ * In blocking mode, wait (interruptibly but with no timeout) on the buffer wait
+ * queue using the same condition.
+ */
+static int isp_video_buffer_wait(struct isp_video_buffer *buf, int nonblocking)
+{
+	if (nonblocking) {
+		return (buf->state != ISP_BUF_STATE_QUEUED &&
+			buf->state != ISP_BUF_STATE_ACTIVE)
+			? 0 : -EAGAIN;
+	}
+
+	return wait_event_interruptible(buf->wait,
+		buf->state != ISP_BUF_STATE_QUEUED &&
+		buf->state != ISP_BUF_STATE_ACTIVE);
+}
+
+/* -----------------------------------------------------------------------------
+ * Queue management
+ */
+
+/*
+ * isp_video_queue_free - Free video buffers memory
+ *
+ * Buffers can only be freed if the queue isn't streaming and if no buffer is
+ * mapped to userspace. Return -EBUSY if those conditions aren't statisfied.
+ *
+ * This function must be called with the queue lock held.
+ */
+static int isp_video_queue_free(struct isp_video_queue *queue)
+{
+	unsigned int i;
+
+	if (queue->streaming)
+		return -EBUSY;
+
+	for (i = 0; i < queue->count; ++i) {
+		if (queue->buffers[i]->vma_use_count != 0)
+			return -EBUSY;
+	}
+
+	for (i = 0; i < queue->count; ++i) {
+		struct isp_video_buffer *buf = queue->buffers[i];
+
+		isp_video_buffer_cleanup(buf);
+
+		vfree(buf->vaddr);
+		buf->vaddr = NULL;
+
+		kfree(buf);
+		queue->buffers[i] = NULL;
+	}
+
+	INIT_LIST_HEAD(&queue->queue);
+	queue->count = 0;
+	return 0;
+}
+
+/*
+ * isp_video_queue_alloc - Allocate video buffers memory
+ *
+ * This function must be called with the queue lock held.
+ */
+static int isp_video_queue_alloc(struct isp_video_queue *queue,
+				 unsigned int nbuffers,
+				 unsigned int size, enum v4l2_memory memory)
+{
+	struct isp_video_buffer *buf;
+	unsigned int i;
+	void *mem;
+	int ret;
+
+	/* Start by freeing the buffers. */
+	ret = isp_video_queue_free(queue);
+	if (ret < 0)
+		return ret;
+
+	/* Bail out of no buffers should be allocated. */
+	if (nbuffers == 0)
+		return 0;
+
+	/* Initialize the allocated buffers. */
+	for (i = 0; i < nbuffers; ++i) {
+		buf = kzalloc(queue->bufsize, GFP_KERNEL);
+		if (buf == NULL)
+			break;
+
+		if (memory == V4L2_MEMORY_MMAP) {
+			/* Allocate video buffers memory for mmap mode. Align
+			 * the size to the page size.
+			 */
+			mem = vmalloc_32_user(PAGE_ALIGN(size));
+			if (mem == NULL) {
+				kfree(buf);
+				break;
+			}
+
+			buf->vbuf.m.offset = i * PAGE_ALIGN(size);
+			buf->vaddr = mem;
+		}
+
+		buf->vbuf.index = i;
+		buf->vbuf.length = size;
+		buf->vbuf.type = queue->type;
+		buf->vbuf.field = V4L2_FIELD_NONE;
+		buf->vbuf.memory = memory;
+
+		buf->queue = queue;
+		init_waitqueue_head(&buf->wait);
+
+		queue->buffers[i] = buf;
+	}
+
+	if (i == 0)
+		return -ENOMEM;
+
+	queue->count = i;
+	return nbuffers;
+}
+
+/**
+ * omap3isp_video_queue_cleanup - Clean up the video buffers queue
+ * @queue: Video buffers queue
+ *
+ * Free all allocated resources and clean up the video buffers queue. The queue
+ * must not be busy (no ongoing video stream) and buffers must have been
+ * unmapped.
+ *
+ * Return 0 on success or -EBUSY if the queue is busy or buffers haven't been
+ * unmapped.
+ */
+int omap3isp_video_queue_cleanup(struct isp_video_queue *queue)
+{
+	return isp_video_queue_free(queue);
+}
+
+/**
+ * omap3isp_video_queue_init - Initialize the video buffers queue
+ * @queue: Video buffers queue
+ * @type: V4L2 buffer type (capture or output)
+ * @ops: Driver-specific queue operations
+ * @dev: Device used for DMA operations
+ * @bufsize: Size of the driver-specific buffer structure
+ *
+ * Initialize the video buffers queue with the supplied parameters.
+ *
+ * The queue type must be one of V4L2_BUF_TYPE_VIDEO_CAPTURE or
+ * V4L2_BUF_TYPE_VIDEO_OUTPUT. Other buffer types are not supported yet.
+ *
+ * Buffer objects will be allocated using the given buffer size to allow room
+ * for driver-specific fields. Driver-specific buffer structures must start
+ * with a struct isp_video_buffer field. Drivers with no driver-specific buffer
+ * structure must pass the size of the isp_video_buffer structure in the bufsize
+ * parameter.
+ *
+ * Return 0 on success.
+ */
+int omap3isp_video_queue_init(struct isp_video_queue *queue,
+			      enum v4l2_buf_type type,
+			      const struct isp_video_queue_operations *ops,
+			      struct device *dev, unsigned int bufsize)
+{
+	INIT_LIST_HEAD(&queue->queue);
+	mutex_init(&queue->lock);
+	spin_lock_init(&queue->irqlock);
+
+	queue->type = type;
+	queue->ops = ops;
+	queue->dev = dev;
+	queue->bufsize = bufsize;
+
+	return 0;
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 operations
+ */
+
+/**
+ * omap3isp_video_queue_reqbufs - Allocate video buffers memory
+ *
+ * This function is intended to be used as a VIDIOC_REQBUFS ioctl handler. It
+ * allocated video buffer objects and, for MMAP buffers, buffer memory.
+ *
+ * If the number of buffers is 0, all buffers are freed and the function returns
+ * without performing any allocation.
+ *
+ * If the number of buffers is not 0, currently allocated buffers (if any) are
+ * freed and the requested number of buffers are allocated. Depending on
+ * driver-specific requirements and on memory availability, a number of buffer
+ * smaller or bigger than requested can be allocated. This isn't considered as
+ * an error.
+ *
+ * Return 0 on success or one of the following error codes:
+ *
+ * -EINVAL if the buffer type or index are invalid
+ * -EBUSY if the queue is busy (streaming or buffers mapped)
+ * -ENOMEM if the buffers can't be allocated due to an out-of-memory condition
+ */
+int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
+				 struct v4l2_requestbuffers *rb)
+{
+	unsigned int nbuffers = rb->count;
+	unsigned int size;
+	int ret;
+
+	if (rb->type != queue->type)
+		return -EINVAL;
+
+	queue->ops->queue_prepare(queue, &nbuffers, &size);
+	if (size == 0)
+		return -EINVAL;
+
+	nbuffers = min_t(unsigned int, nbuffers, ISP_VIDEO_MAX_BUFFERS);
+
+	mutex_lock(&queue->lock);
+
+	ret = isp_video_queue_alloc(queue, nbuffers, size, rb->memory);
+	if (ret < 0)
+		goto done;
+
+	rb->count = ret;
+	ret = 0;
+
+done:
+	mutex_unlock(&queue->lock);
+	return ret;
+}
+
+/**
+ * omap3isp_video_queue_querybuf - Query the status of a buffer in a queue
+ *
+ * This function is intended to be used as a VIDIOC_QUERYBUF ioctl handler. It
+ * returns the status of a given video buffer.
+ *
+ * Return 0 on success or -EINVAL if the buffer type or index are invalid.
+ */
+int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
+				  struct v4l2_buffer *vbuf)
+{
+	struct isp_video_buffer *buf;
+	int ret = 0;
+
+	if (vbuf->type != queue->type)
+		return -EINVAL;
+
+	mutex_lock(&queue->lock);
+
+	if (vbuf->index >= queue->count) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	buf = queue->buffers[vbuf->index];
+	isp_video_buffer_query(buf, vbuf);
+
+done:
+	mutex_unlock(&queue->lock);
+	return ret;
+}
+
+/**
+ * omap3isp_video_queue_qbuf - Queue a buffer
+ *
+ * This function is intended to be used as a VIDIOC_QBUF ioctl handler.
+ *
+ * The v4l2_buffer structure passed from userspace is first sanity tested. If
+ * sane, the buffer is then processed and added to the main queue and, if the
+ * queue is streaming, to the IRQ queue.
+ *
+ * Before being enqueued, USERPTR buffers are checked for address changes. If
+ * the buffer has a different userspace address, the old memory area is unlocked
+ * and the new memory area is locked.
+ */
+int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
+			      struct v4l2_buffer *vbuf)
+{
+	struct isp_video_buffer *buf;
+	unsigned long flags;
+	int ret = -EINVAL;
+
+	if (vbuf->type != queue->type)
+		goto done;
+
+	mutex_lock(&queue->lock);
+
+	if (vbuf->index >= queue->count)
+		goto done;
+
+	buf = queue->buffers[vbuf->index];
+
+	if (vbuf->memory != buf->vbuf.memory)
+		goto done;
+
+	if (buf->state != ISP_BUF_STATE_IDLE)
+		goto done;
+
+	if (vbuf->memory == V4L2_MEMORY_USERPTR &&
+	    vbuf->m.userptr != buf->vbuf.m.userptr) {
+		isp_video_buffer_cleanup(buf);
+		buf->vbuf.m.userptr = vbuf->m.userptr;
+		buf->prepared = 0;
+	}
+
+	if (!buf->prepared) {
+		ret = isp_video_buffer_prepare(buf);
+		if (ret < 0)
+			goto done;
+		buf->prepared = 1;
+	}
+
+	isp_video_buffer_cache_sync(buf);
+
+	buf->state = ISP_BUF_STATE_QUEUED;
+	list_add_tail(&buf->stream, &queue->queue);
+
+	if (queue->streaming) {
+		spin_lock_irqsave(&queue->irqlock, flags);
+		queue->ops->buffer_queue(buf);
+		spin_unlock_irqrestore(&queue->irqlock, flags);
+	}
+
+	ret = 0;
+
+done:
+	mutex_unlock(&queue->lock);
+	return ret;
+}
+
+/**
+ * omap3isp_video_queue_dqbuf - Dequeue a buffer
+ *
+ * This function is intended to be used as a VIDIOC_DQBUF ioctl handler.
+ *
+ * The v4l2_buffer structure passed from userspace is first sanity tested. If
+ * sane, the buffer is then processed and added to the main queue and, if the
+ * queue is streaming, to the IRQ queue.
+ *
+ * Before being enqueued, USERPTR buffers are checked for address changes. If
+ * the buffer has a different userspace address, the old memory area is unlocked
+ * and the new memory area is locked.
+ */
+int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
+			       struct v4l2_buffer *vbuf, int nonblocking)
+{
+	struct isp_video_buffer *buf;
+	int ret;
+
+	if (vbuf->type != queue->type)
+		return -EINVAL;
+
+	mutex_lock(&queue->lock);
+
+	if (list_empty(&queue->queue)) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
+	ret = isp_video_buffer_wait(buf, nonblocking);
+	if (ret < 0)
+		goto done;
+
+	list_del(&buf->stream);
+
+	isp_video_buffer_query(buf, vbuf);
+	buf->state = ISP_BUF_STATE_IDLE;
+	vbuf->flags &= ~V4L2_BUF_FLAG_QUEUED;
+
+done:
+	mutex_unlock(&queue->lock);
+	return ret;
+}
+
+/**
+ * omap3isp_video_queue_streamon - Start streaming
+ *
+ * This function is intended to be used as a VIDIOC_STREAMON ioctl handler. It
+ * starts streaming on the queue and calls the buffer_queue operation for all
+ * queued buffers.
+ *
+ * Return 0 on success.
+ */
+int omap3isp_video_queue_streamon(struct isp_video_queue *queue)
+{
+	struct isp_video_buffer *buf;
+	unsigned long flags;
+
+	mutex_lock(&queue->lock);
+
+	if (queue->streaming)
+		goto done;
+
+	queue->streaming = 1;
+
+	spin_lock_irqsave(&queue->irqlock, flags);
+	list_for_each_entry(buf, &queue->queue, stream)
+		queue->ops->buffer_queue(buf);
+	spin_unlock_irqrestore(&queue->irqlock, flags);
+
+done:
+	mutex_unlock(&queue->lock);
+	return 0;
+}
+
+/**
+ * omap3isp_video_queue_streamoff - Stop streaming
+ *
+ * This function is intended to be used as a VIDIOC_STREAMOFF ioctl handler. It
+ * stops streaming on the queue and wakes up all the buffers.
+ *
+ * Drivers must stop the hardware and synchronize with interrupt handlers and/or
+ * delayed works before calling this function to make sure no buffer will be
+ * touched by the driver and/or hardware.
+ */
+void omap3isp_video_queue_streamoff(struct isp_video_queue *queue)
+{
+	struct isp_video_buffer *buf;
+	unsigned long flags;
+	unsigned int i;
+
+	mutex_lock(&queue->lock);
+
+	if (!queue->streaming)
+		goto done;
+
+	queue->streaming = 0;
+
+	spin_lock_irqsave(&queue->irqlock, flags);
+	for (i = 0; i < queue->count; ++i) {
+		buf = queue->buffers[i];
+
+		if (buf->state == ISP_BUF_STATE_ACTIVE)
+			wake_up(&buf->wait);
+
+		buf->state = ISP_BUF_STATE_IDLE;
+	}
+	spin_unlock_irqrestore(&queue->irqlock, flags);
+
+	INIT_LIST_HEAD(&queue->queue);
+
+done:
+	mutex_unlock(&queue->lock);
+}
+
+/**
+ * omap3isp_video_queue_discard_done - Discard all buffers marked as DONE
+ *
+ * This function is intended to be used with suspend/resume operations. It
+ * discards all 'done' buffers as they would be too old to be requested after
+ * resume.
+ *
+ * Drivers must stop the hardware and synchronize with interrupt handlers and/or
+ * delayed works before calling this function to make sure no buffer will be
+ * touched by the driver and/or hardware.
+ */
+void omap3isp_video_queue_discard_done(struct isp_video_queue *queue)
+{
+	struct isp_video_buffer *buf;
+	unsigned int i;
+
+	mutex_lock(&queue->lock);
+
+	if (!queue->streaming)
+		goto done;
+
+	for (i = 0; i < queue->count; ++i) {
+		buf = queue->buffers[i];
+
+		if (buf->state == ISP_BUF_STATE_DONE)
+			buf->state = ISP_BUF_STATE_ERROR;
+	}
+
+done:
+	mutex_unlock(&queue->lock);
+}
+
+static void isp_video_queue_vm_open(struct vm_area_struct *vma)
+{
+	struct isp_video_buffer *buf = vma->vm_private_data;
+
+	buf->vma_use_count++;
+}
+
+static void isp_video_queue_vm_close(struct vm_area_struct *vma)
+{
+	struct isp_video_buffer *buf = vma->vm_private_data;
+
+	buf->vma_use_count--;
+}
+
+static const struct vm_operations_struct isp_video_queue_vm_ops = {
+	.open = isp_video_queue_vm_open,
+	.close = isp_video_queue_vm_close,
+};
+
+/**
+ * omap3isp_video_queue_mmap - Map buffers to userspace
+ *
+ * This function is intended to be used as an mmap() file operation handler. It
+ * maps a buffer to userspace based on the VMA offset.
+ *
+ * Only buffers of memory type MMAP are supported.
+ */
+int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
+			 struct vm_area_struct *vma)
+{
+	struct isp_video_buffer *uninitialized_var(buf);
+	unsigned long size;
+	unsigned int i;
+	int ret = 0;
+
+	mutex_lock(&queue->lock);
+
+	for (i = 0; i < queue->count; ++i) {
+		buf = queue->buffers[i];
+		if ((buf->vbuf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
+			break;
+	}
+
+	if (i == queue->count) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	size = vma->vm_end - vma->vm_start;
+
+	if (buf->vbuf.memory != V4L2_MEMORY_MMAP ||
+	    size != PAGE_ALIGN(buf->vbuf.length)) {
+		ret = -EINVAL;
+		goto done;
+	}
+
+	ret = remap_vmalloc_range(vma, buf->vaddr, 0);
+	if (ret < 0)
+		goto done;
+
+	vma->vm_ops = &isp_video_queue_vm_ops;
+	vma->vm_private_data = buf;
+	isp_video_queue_vm_open(vma);
+
+done:
+	mutex_unlock(&queue->lock);
+	return ret;
+}
+
+/**
+ * omap3isp_video_queue_poll - Poll video queue state
+ *
+ * This function is intended to be used as a poll() file operation handler. It
+ * polls the state of the video buffer at the front of the queue and returns an
+ * events mask.
+ *
+ * If no buffer is present at the front of the queue, POLLERR is returned.
+ */
+unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
+				       struct file *file, poll_table *wait)
+{
+	struct isp_video_buffer *buf;
+	unsigned int mask = 0;
+
+	mutex_lock(&queue->lock);
+	if (list_empty(&queue->queue)) {
+		mask |= POLLERR;
+		goto done;
+	}
+	buf = list_first_entry(&queue->queue, struct isp_video_buffer, stream);
+
+	poll_wait(file, &buf->wait, wait);
+	if (buf->state == ISP_BUF_STATE_DONE ||
+	    buf->state == ISP_BUF_STATE_ERROR) {
+		if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			mask |= POLLIN | POLLRDNORM;
+		else
+			mask |= POLLOUT | POLLWRNORM;
+	}
+
+done:
+	mutex_unlock(&queue->lock);
+	return mask;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispqueue.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispqueue.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispqueue.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispqueue.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,187 @@
+/*
+ * ispqueue.h
+ *
+ * TI OMAP3 ISP - Video buffers queue handling
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_QUEUE_H
+#define OMAP3_ISP_QUEUE_H
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/mutex.h>
+#include <linux/videodev2.h>
+#include <linux/wait.h>
+
+struct isp_video_queue;
+struct page;
+struct scatterlist;
+
+#define ISP_VIDEO_MAX_BUFFERS		16
+
+/**
+ * enum isp_video_buffer_state - ISP video buffer state
+ * @ISP_BUF_STATE_IDLE:	The buffer is under userspace control (dequeued
+ *	or not queued yet).
+ * @ISP_BUF_STATE_QUEUED: The buffer has been queued but isn't used by the
+ *	device yet.
+ * @ISP_BUF_STATE_ACTIVE: The buffer is in use for an active video transfer.
+ * @ISP_BUF_STATE_ERROR: The device is done with the buffer and an error
+ *	occurred. For capture device the buffer likely contains corrupted data or
+ *	no data at all.
+ * @ISP_BUF_STATE_DONE: The device is done with the buffer and no error occurred.
+ *	For capture devices the buffer contains valid data.
+ */
+enum isp_video_buffer_state {
+	ISP_BUF_STATE_IDLE,
+	ISP_BUF_STATE_QUEUED,
+	ISP_BUF_STATE_ACTIVE,
+	ISP_BUF_STATE_ERROR,
+	ISP_BUF_STATE_DONE,
+};
+
+/**
+ * struct isp_video_buffer - ISP video buffer
+ * @vma_use_count: Number of times the buffer is mmap'ed to userspace
+ * @stream: List head for insertion into main queue
+ * @queue: ISP buffers queue this buffer belongs to
+ * @prepared: Whether the buffer has been prepared
+ * @skip_cache: Whether to skip cache management operations for this buffer
+ * @vaddr: Memory virtual address (for kernel buffers)
+ * @vm_flags: Buffer VMA flags (for userspace buffers)
+ * @offset: Offset inside the first page (for userspace buffers)
+ * @npages: Number of pages (for userspace buffers)
+ * @pages: Pages table (for userspace non-VM_PFNMAP buffers)
+ * @paddr: Memory physical address (for userspace VM_PFNMAP buffers)
+ * @sglen: Number of elements in the scatter list (for non-VM_PFNMAP buffers)
+ * @sglist: Scatter list (for non-VM_PFNMAP buffers)
+ * @vbuf: V4L2 buffer
+ * @irqlist: List head for insertion into IRQ queue
+ * @state: Current buffer state
+ * @wait: Wait queue to signal buffer completion
+ */
+struct isp_video_buffer {
+	unsigned long vma_use_count;
+	struct list_head stream;
+	struct isp_video_queue *queue;
+	unsigned int prepared:1;
+	bool skip_cache;
+
+	/* For kernel buffers. */
+	void *vaddr;
+
+	/* For userspace buffers. */
+	unsigned long vm_flags;
+	unsigned long offset;
+	unsigned int npages;
+	struct page **pages;
+	dma_addr_t paddr;
+
+	/* For all buffers except VM_PFNMAP. */
+	unsigned int sglen;
+	struct scatterlist *sglist;
+
+	/* Touched by the interrupt handler. */
+	struct v4l2_buffer vbuf;
+	struct list_head irqlist;
+	enum isp_video_buffer_state state;
+	wait_queue_head_t wait;
+};
+
+#define to_isp_video_buffer(vb)	container_of(vb, struct isp_video_buffer, vb)
+
+/**
+ * struct isp_video_queue_operations - Driver-specific operations
+ * @queue_prepare: Called before allocating buffers. Drivers should clamp the
+ *	number of buffers according to their requirements, and must return the
+ *	buffer size in bytes.
+ * @buffer_prepare: Called the first time a buffer is queued, or after changing
+ *	the userspace memory address for a USERPTR buffer, with the queue lock
+ *	held. Drivers should perform device-specific buffer preparation (such as
+ *	mapping the buffer memory in an IOMMU). This operation is optional.
+ * @buffer_queue: Called when a buffer is being added to the queue with the
+ *	queue irqlock spinlock held.
+ * @buffer_cleanup: Called before freeing buffers, or before changing the
+ *	userspace memory address for a USERPTR buffer, with the queue lock held.
+ *	Drivers must perform cleanup operations required to undo the
+ *	buffer_prepare call. This operation is optional.
+ */
+struct isp_video_queue_operations {
+	void (*queue_prepare)(struct isp_video_queue *queue,
+			      unsigned int *nbuffers, unsigned int *size);
+	int  (*buffer_prepare)(struct isp_video_buffer *buf);
+	void (*buffer_queue)(struct isp_video_buffer *buf);
+	void (*buffer_cleanup)(struct isp_video_buffer *buf);
+};
+
+/**
+ * struct isp_video_queue - ISP video buffers queue
+ * @type: Type of video buffers handled by this queue
+ * @ops: Queue operations
+ * @dev: Device used for DMA operations
+ * @bufsize: Size of a driver-specific buffer object
+ * @count: Number of currently allocated buffers
+ * @buffers: ISP video buffers
+ * @lock: Mutex to protect access to the buffers, main queue and state
+ * @irqlock: Spinlock to protect access to the IRQ queue
+ * @streaming: Queue state, indicates whether the queue is streaming
+ * @queue: List of all queued buffers
+ */
+struct isp_video_queue {
+	enum v4l2_buf_type type;
+	const struct isp_video_queue_operations *ops;
+	struct device *dev;
+	unsigned int bufsize;
+
+	unsigned int count;
+	struct isp_video_buffer *buffers[ISP_VIDEO_MAX_BUFFERS];
+	struct mutex lock;
+	spinlock_t irqlock;
+
+	unsigned int streaming:1;
+
+	struct list_head queue;
+};
+
+int omap3isp_video_queue_cleanup(struct isp_video_queue *queue);
+int omap3isp_video_queue_init(struct isp_video_queue *queue,
+			      enum v4l2_buf_type type,
+			      const struct isp_video_queue_operations *ops,
+			      struct device *dev, unsigned int bufsize);
+
+int omap3isp_video_queue_reqbufs(struct isp_video_queue *queue,
+				 struct v4l2_requestbuffers *rb);
+int omap3isp_video_queue_querybuf(struct isp_video_queue *queue,
+				  struct v4l2_buffer *vbuf);
+int omap3isp_video_queue_qbuf(struct isp_video_queue *queue,
+			      struct v4l2_buffer *vbuf);
+int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
+			       struct v4l2_buffer *vbuf, int nonblocking);
+int omap3isp_video_queue_streamon(struct isp_video_queue *queue);
+void omap3isp_video_queue_streamoff(struct isp_video_queue *queue);
+void omap3isp_video_queue_discard_done(struct isp_video_queue *queue);
+int omap3isp_video_queue_mmap(struct isp_video_queue *queue,
+			      struct vm_area_struct *vma);
+unsigned int omap3isp_video_queue_poll(struct isp_video_queue *queue,
+				       struct file *file, poll_table *wait);
+
+#endif /* OMAP3_ISP_QUEUE_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispreg.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispreg.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispreg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispreg.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1589 @@
+/*
+ * ispreg.h
+ *
+ * TI OMAP3 ISP - Registers definitions
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_REG_H
+#define OMAP3_ISP_REG_H
+
+#include <plat/omap34xx.h>
+
+
+#define CM_CAM_MCLK_HZ			172800000	/* Hz */
+
+/* ISP Submodules offset */
+
+#define OMAP3ISP_REG_BASE		OMAP3430_ISP_BASE
+#define OMAP3ISP_REG(offset)		(OMAP3ISP_REG_BASE + (offset))
+
+#define OMAP3ISP_CCP2_REG_OFFSET	0x0400
+#define OMAP3ISP_CCP2_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_CCP2_REG_OFFSET)
+#define OMAP3ISP_CCP2_REG(offset)	(OMAP3ISP_CCP2_REG_BASE + (offset))
+
+#define OMAP3ISP_CCDC_REG_OFFSET	0x0600
+#define OMAP3ISP_CCDC_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_CCDC_REG_OFFSET)
+#define OMAP3ISP_CCDC_REG(offset)	(OMAP3ISP_CCDC_REG_BASE + (offset))
+
+#define OMAP3ISP_HIST_REG_OFFSET	0x0A00
+#define OMAP3ISP_HIST_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_HIST_REG_OFFSET)
+#define OMAP3ISP_HIST_REG(offset)	(OMAP3ISP_HIST_REG_BASE + (offset))
+
+#define OMAP3ISP_H3A_REG_OFFSET		0x0C00
+#define OMAP3ISP_H3A_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_H3A_REG_OFFSET)
+#define OMAP3ISP_H3A_REG(offset)	(OMAP3ISP_H3A_REG_BASE + (offset))
+
+#define OMAP3ISP_PREV_REG_OFFSET	0x0E00
+#define OMAP3ISP_PREV_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_PREV_REG_OFFSET)
+#define OMAP3ISP_PREV_REG(offset)	(OMAP3ISP_PREV_REG_BASE + (offset))
+
+#define OMAP3ISP_RESZ_REG_OFFSET	0x1000
+#define OMAP3ISP_RESZ_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_RESZ_REG_OFFSET)
+#define OMAP3ISP_RESZ_REG(offset)	(OMAP3ISP_RESZ_REG_BASE + (offset))
+
+#define OMAP3ISP_SBL_REG_OFFSET		0x1200
+#define OMAP3ISP_SBL_REG_BASE		(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_SBL_REG_OFFSET)
+#define OMAP3ISP_SBL_REG(offset)	(OMAP3ISP_SBL_REG_BASE + (offset))
+
+#define OMAP3ISP_CSI2A_REGS1_REG_OFFSET	0x1800
+#define OMAP3ISP_CSI2A_REGS1_REG_BASE	(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_CSI2A_REGS1_REG_OFFSET)
+#define OMAP3ISP_CSI2A_REGS1_REG(offset)				\
+				(OMAP3ISP_CSI2A_REGS1_REG_BASE + (offset))
+
+#define OMAP3ISP_CSIPHY2_REG_OFFSET	0x1970
+#define OMAP3ISP_CSIPHY2_REG_BASE	(OMAP3ISP_REG_BASE +	\
+					 OMAP3ISP_CSIPHY2_REG_OFFSET)
+#define OMAP3ISP_CSIPHY2_REG(offset)	(OMAP3ISP_CSIPHY2_REG_BASE + (offset))
+
+#define OMAP3ISP_CSI2A_REGS2_REG_OFFSET	0x19C0
+#define OMAP3ISP_CSI2A_REGS2_REG_BASE	(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_CSI2A_REGS2_REG_OFFSET)
+#define OMAP3ISP_CSI2A_REGS2_REG(offset)				\
+				(OMAP3ISP_CSI2A_REGS2_REG_BASE + (offset))
+
+#define OMAP3ISP_CSI2C_REGS1_REG_OFFSET	0x1C00
+#define OMAP3ISP_CSI2C_REGS1_REG_BASE	(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_CSI2C_REGS1_REG_OFFSET)
+#define OMAP3ISP_CSI2C_REGS1_REG(offset)				\
+				(OMAP3ISP_CSI2C_REGS1_REG_BASE + (offset))
+
+#define OMAP3ISP_CSIPHY1_REG_OFFSET	0x1D70
+#define OMAP3ISP_CSIPHY1_REG_BASE	(OMAP3ISP_REG_BASE +	\
+					 OMAP3ISP_CSIPHY1_REG_OFFSET)
+#define OMAP3ISP_CSIPHY1_REG(offset)	(OMAP3ISP_CSIPHY1_REG_BASE + (offset))
+
+#define OMAP3ISP_CSI2C_REGS2_REG_OFFSET	0x1DC0
+#define OMAP3ISP_CSI2C_REGS2_REG_BASE	(OMAP3ISP_REG_BASE +		\
+					 OMAP3ISP_CSI2C_REGS2_REG_OFFSET)
+#define OMAP3ISP_CSI2C_REGS2_REG(offset)				\
+				(OMAP3ISP_CSI2C_REGS2_REG_BASE + (offset))
+
+/* ISP module register offset */
+
+#define ISP_REVISION			(0x000)
+#define ISP_SYSCONFIG			(0x004)
+#define ISP_SYSSTATUS			(0x008)
+#define ISP_IRQ0ENABLE			(0x00C)
+#define ISP_IRQ0STATUS			(0x010)
+#define ISP_IRQ1ENABLE			(0x014)
+#define ISP_IRQ1STATUS			(0x018)
+#define ISP_TCTRL_GRESET_LENGTH		(0x030)
+#define ISP_TCTRL_PSTRB_REPLAY		(0x034)
+#define ISP_CTRL			(0x040)
+#define ISP_SECURE			(0x044)
+#define ISP_TCTRL_CTRL			(0x050)
+#define ISP_TCTRL_FRAME			(0x054)
+#define ISP_TCTRL_PSTRB_DELAY		(0x058)
+#define ISP_TCTRL_STRB_DELAY		(0x05C)
+#define ISP_TCTRL_SHUT_DELAY		(0x060)
+#define ISP_TCTRL_PSTRB_LENGTH		(0x064)
+#define ISP_TCTRL_STRB_LENGTH		(0x068)
+#define ISP_TCTRL_SHUT_LENGTH		(0x06C)
+#define ISP_PING_PONG_ADDR		(0x070)
+#define ISP_PING_PONG_MEM_RANGE		(0x074)
+#define ISP_PING_PONG_BUF_SIZE		(0x078)
+
+/* CCP2 receiver registers */
+
+#define ISPCCP2_REVISION		(0x000)
+#define ISPCCP2_SYSCONFIG		(0x004)
+#define ISPCCP2_SYSCONFIG_SOFT_RESET	(1 << 1)
+#define ISPCCP2_SYSCONFIG_AUTO_IDLE		0x1
+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT	12
+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_FORCE	\
+	(0x0 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_NO	\
+	(0x1 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SMART	\
+	(0x2 << ISPCCP2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCCP2_SYSSTATUS		(0x008)
+#define ISPCCP2_SYSSTATUS_RESET_DONE	(1 << 0)
+#define ISPCCP2_LC01_IRQENABLE		(0x00C)
+#define ISPCCP2_LC01_IRQSTATUS		(0x010)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_FS_IRQ	(1 << 11)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_LE_IRQ	(1 << 10)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_LS_IRQ	(1 << 9)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_FE_IRQ	(1 << 8)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_COUNT_IRQ	(1 << 7)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_FIFO_OVF_IRQ	(1 << 5)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_CRC_IRQ	(1 << 4)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_FSP_IRQ	(1 << 3)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_FW_IRQ	(1 << 2)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_FSC_IRQ	(1 << 1)
+#define ISPCCP2_LC01_IRQSTATUS_LC0_SSC_IRQ	(1 << 0)
+
+#define ISPCCP2_LC23_IRQENABLE		(0x014)
+#define ISPCCP2_LC23_IRQSTATUS		(0x018)
+#define ISPCCP2_LCM_IRQENABLE		(0x02C)
+#define ISPCCP2_LCM_IRQSTATUS_EOF_IRQ		(1 << 0)
+#define ISPCCP2_LCM_IRQSTATUS_OCPERROR_IRQ	(1 << 1)
+#define ISPCCP2_LCM_IRQSTATUS		(0x030)
+#define ISPCCP2_CTRL			(0x040)
+#define ISPCCP2_CTRL_IF_EN		(1 << 0)
+#define ISPCCP2_CTRL_PHY_SEL		(1 << 1)
+#define ISPCCP2_CTRL_PHY_SEL_CLOCK	(0 << 1)
+#define ISPCCP2_CTRL_PHY_SEL_STROBE	(1 << 1)
+#define ISPCCP2_CTRL_PHY_SEL_MASK	0x1
+#define ISPCCP2_CTRL_PHY_SEL_SHIFT	1
+#define ISPCCP2_CTRL_IO_OUT_SEL		(1 << 2)
+#define ISPCCP2_CTRL_MODE		(1 << 4)
+#define ISPCCP2_CTRL_VP_CLK_FORCE_ON	(1 << 9)
+#define ISPCCP2_CTRL_INV		(1 << 10)
+#define ISPCCP2_CTRL_INV_MASK		0x1
+#define ISPCCP2_CTRL_INV_SHIFT		10
+#define ISPCCP2_CTRL_VP_ONLY_EN		(1 << 11)
+#define ISPCCP2_CTRL_VP_CLK_POL		(1 << 12)
+#define ISPCCP2_CTRL_VPCLK_DIV_SHIFT	15
+#define ISPCCP2_CTRL_VPCLK_DIV_MASK	0x1ffff /* [31:15] */
+#define ISPCCP2_CTRL_VP_OUT_CTRL_SHIFT	8 /* 3430 bits */
+#define ISPCCP2_CTRL_VP_OUT_CTRL_MASK	0x3 /* 3430 bits */
+#define ISPCCP2_DBG			(0x044)
+#define ISPCCP2_GNQ			(0x048)
+#define ISPCCP2_LCx_CTRL(x)			((0x050)+0x30*(x))
+#define ISPCCP2_LCx_CTRL_CHAN_EN		(1 << 0)
+#define ISPCCP2_LCx_CTRL_CRC_EN			(1 << 19)
+#define ISPCCP2_LCx_CTRL_CRC_MASK		0x1
+#define ISPCCP2_LCx_CTRL_CRC_SHIFT		2
+#define ISPCCP2_LCx_CTRL_CRC_SHIFT_15_0		19
+#define ISPCCP2_LCx_CTRL_REGION_EN		(1 << 1)
+#define ISPCCP2_LCx_CTRL_REGION_MASK		0x1
+#define ISPCCP2_LCx_CTRL_REGION_SHIFT		1
+#define ISPCCP2_LCx_CTRL_FORMAT_MASK_15_0	0x3f
+#define ISPCCP2_LCx_CTRL_FORMAT_SHIFT_15_0	0x2
+#define ISPCCP2_LCx_CTRL_FORMAT_MASK		0x1f
+#define ISPCCP2_LCx_CTRL_FORMAT_SHIFT		0x3
+#define ISPCCP2_LCx_CODE(x)		((0x054)+0x30*(x))
+#define ISPCCP2_LCx_STAT_START(x)	((0x058)+0x30*(x))
+#define ISPCCP2_LCx_STAT_SIZE(x)	((0x05C)+0x30*(x))
+#define ISPCCP2_LCx_SOF_ADDR(x)		((0x060)+0x30*(x))
+#define ISPCCP2_LCx_EOF_ADDR(x)		((0x064)+0x30*(x))
+#define ISPCCP2_LCx_DAT_START(x)	((0x068)+0x30*(x))
+#define ISPCCP2_LCx_DAT_SIZE(x)		((0x06C)+0x30*(x))
+#define ISPCCP2_LCx_DAT_MASK		0xFFF
+#define ISPCCP2_LCx_DAT_SHIFT		16
+#define ISPCCP2_LCx_DAT_PING_ADDR(x)	((0x070)+0x30*(x))
+#define ISPCCP2_LCx_DAT_PONG_ADDR(x)	((0x074)+0x30*(x))
+#define ISPCCP2_LCx_DAT_OFST(x)		((0x078)+0x30*(x))
+#define ISPCCP2_LCM_CTRL		(0x1D0)
+#define ISPCCP2_LCM_CTRL_CHAN_EN               (1 << 0)
+#define ISPCCP2_LCM_CTRL_DST_PORT              (1 << 2)
+#define ISPCCP2_LCM_CTRL_DST_PORT_SHIFT		2
+#define ISPCCP2_LCM_CTRL_READ_THROTTLE_SHIFT	3
+#define ISPCCP2_LCM_CTRL_READ_THROTTLE_MASK	0x11
+#define ISPCCP2_LCM_CTRL_BURST_SIZE_SHIFT	5
+#define ISPCCP2_LCM_CTRL_BURST_SIZE_MASK	0x7
+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_SHIFT	16
+#define ISPCCP2_LCM_CTRL_SRC_FORMAT_MASK	0x7
+#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_SHIFT	20
+#define ISPCCP2_LCM_CTRL_SRC_DECOMPR_MASK	0x3
+#define ISPCCP2_LCM_CTRL_SRC_DPCM_PRED		(1 << 22)
+#define ISPCCP2_LCM_CTRL_SRC_PACK		(1 << 23)
+#define ISPCCP2_LCM_CTRL_DST_FORMAT_SHIFT	24
+#define ISPCCP2_LCM_CTRL_DST_FORMAT_MASK	0x7
+#define ISPCCP2_LCM_VSIZE		(0x1D4)
+#define ISPCCP2_LCM_VSIZE_SHIFT		16
+#define ISPCCP2_LCM_HSIZE		(0x1D8)
+#define ISPCCP2_LCM_HSIZE_SHIFT		16
+#define ISPCCP2_LCM_PREFETCH		(0x1DC)
+#define ISPCCP2_LCM_PREFETCH_SHIFT	3
+#define ISPCCP2_LCM_SRC_ADDR		(0x1E0)
+#define ISPCCP2_LCM_SRC_OFST		(0x1E4)
+#define ISPCCP2_LCM_DST_ADDR		(0x1E8)
+#define ISPCCP2_LCM_DST_OFST		(0x1EC)
+
+/* CCDC module register offset */
+
+#define ISPCCDC_PID			(0x000)
+#define ISPCCDC_PCR			(0x004)
+#define ISPCCDC_SYN_MODE		(0x008)
+#define ISPCCDC_HD_VD_WID		(0x00C)
+#define ISPCCDC_PIX_LINES		(0x010)
+#define ISPCCDC_HORZ_INFO		(0x014)
+#define ISPCCDC_VERT_START		(0x018)
+#define ISPCCDC_VERT_LINES		(0x01C)
+#define ISPCCDC_CULLING			(0x020)
+#define ISPCCDC_HSIZE_OFF		(0x024)
+#define ISPCCDC_SDOFST			(0x028)
+#define ISPCCDC_SDR_ADDR		(0x02C)
+#define ISPCCDC_CLAMP			(0x030)
+#define ISPCCDC_DCSUB			(0x034)
+#define ISPCCDC_COLPTN			(0x038)
+#define ISPCCDC_BLKCMP			(0x03C)
+#define ISPCCDC_FPC			(0x040)
+#define ISPCCDC_FPC_ADDR		(0x044)
+#define ISPCCDC_VDINT			(0x048)
+#define ISPCCDC_ALAW			(0x04C)
+#define ISPCCDC_REC656IF		(0x050)
+#define ISPCCDC_CFG			(0x054)
+#define ISPCCDC_FMTCFG			(0x058)
+#define ISPCCDC_FMT_HORZ		(0x05C)
+#define ISPCCDC_FMT_VERT		(0x060)
+#define ISPCCDC_FMT_ADDR0		(0x064)
+#define ISPCCDC_FMT_ADDR1		(0x068)
+#define ISPCCDC_FMT_ADDR2		(0x06C)
+#define ISPCCDC_FMT_ADDR3		(0x070)
+#define ISPCCDC_FMT_ADDR4		(0x074)
+#define ISPCCDC_FMT_ADDR5		(0x078)
+#define ISPCCDC_FMT_ADDR6		(0x07C)
+#define ISPCCDC_FMT_ADDR7		(0x080)
+#define ISPCCDC_PRGEVEN0		(0x084)
+#define ISPCCDC_PRGEVEN1		(0x088)
+#define ISPCCDC_PRGODD0			(0x08C)
+#define ISPCCDC_PRGODD1			(0x090)
+#define ISPCCDC_VP_OUT			(0x094)
+
+#define ISPCCDC_LSC_CONFIG		(0x098)
+#define ISPCCDC_LSC_INITIAL		(0x09C)
+#define ISPCCDC_LSC_TABLE_BASE		(0x0A0)
+#define ISPCCDC_LSC_TABLE_OFFSET	(0x0A4)
+
+/* SBL */
+#define ISPSBL_PCR			0x4
+#define ISPSBL_PCR_H3A_AEAWB_WBL_OVF	(1 << 16)
+#define ISPSBL_PCR_H3A_AF_WBL_OVF	(1 << 17)
+#define ISPSBL_PCR_RSZ4_WBL_OVF		(1 << 18)
+#define ISPSBL_PCR_RSZ3_WBL_OVF		(1 << 19)
+#define ISPSBL_PCR_RSZ2_WBL_OVF		(1 << 20)
+#define ISPSBL_PCR_RSZ1_WBL_OVF		(1 << 21)
+#define ISPSBL_PCR_PRV_WBL_OVF		(1 << 22)
+#define ISPSBL_PCR_CCDC_WBL_OVF		(1 << 23)
+#define ISPSBL_PCR_CCDCPRV_2_RSZ_OVF	(1 << 24)
+#define ISPSBL_PCR_CSIA_WBL_OVF		(1 << 25)
+#define ISPSBL_PCR_CSIB_WBL_OVF		(1 << 26)
+#define ISPSBL_CCDC_WR_0		(0x028)
+#define ISPSBL_CCDC_WR_0_DATA_READY	(1 << 21)
+#define ISPSBL_CCDC_WR_1		(0x02C)
+#define ISPSBL_CCDC_WR_2		(0x030)
+#define ISPSBL_CCDC_WR_3		(0x034)
+
+#define ISPSBL_SDR_REQ_EXP		0xF8
+#define ISPSBL_SDR_REQ_HIST_EXP_SHIFT	0
+#define ISPSBL_SDR_REQ_HIST_EXP_MASK	(0x3FF)
+#define ISPSBL_SDR_REQ_RSZ_EXP_SHIFT	10
+#define ISPSBL_SDR_REQ_RSZ_EXP_MASK	(0x3FF << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT)
+#define ISPSBL_SDR_REQ_PRV_EXP_SHIFT	20
+#define ISPSBL_SDR_REQ_PRV_EXP_MASK	(0x3FF << ISPSBL_SDR_REQ_PRV_EXP_SHIFT)
+
+/* Histogram registers */
+#define ISPHIST_PID			(0x000)
+#define ISPHIST_PCR			(0x004)
+#define ISPHIST_CNT			(0x008)
+#define ISPHIST_WB_GAIN			(0x00C)
+#define ISPHIST_R0_HORZ			(0x010)
+#define ISPHIST_R0_VERT			(0x014)
+#define ISPHIST_R1_HORZ			(0x018)
+#define ISPHIST_R1_VERT			(0x01C)
+#define ISPHIST_R2_HORZ			(0x020)
+#define ISPHIST_R2_VERT			(0x024)
+#define ISPHIST_R3_HORZ			(0x028)
+#define ISPHIST_R3_VERT			(0x02C)
+#define ISPHIST_ADDR			(0x030)
+#define ISPHIST_DATA			(0x034)
+#define ISPHIST_RADD			(0x038)
+#define ISPHIST_RADD_OFF		(0x03C)
+#define ISPHIST_H_V_INFO		(0x040)
+
+/* H3A module registers */
+#define ISPH3A_PID			(0x000)
+#define ISPH3A_PCR			(0x004)
+#define ISPH3A_AEWWIN1			(0x04C)
+#define ISPH3A_AEWINSTART		(0x050)
+#define ISPH3A_AEWINBLK			(0x054)
+#define ISPH3A_AEWSUBWIN		(0x058)
+#define ISPH3A_AEWBUFST			(0x05C)
+#define ISPH3A_AFPAX1			(0x008)
+#define ISPH3A_AFPAX2			(0x00C)
+#define ISPH3A_AFPAXSTART		(0x010)
+#define ISPH3A_AFIIRSH			(0x014)
+#define ISPH3A_AFBUFST			(0x018)
+#define ISPH3A_AFCOEF010		(0x01C)
+#define ISPH3A_AFCOEF032		(0x020)
+#define ISPH3A_AFCOEF054		(0x024)
+#define ISPH3A_AFCOEF076		(0x028)
+#define ISPH3A_AFCOEF098		(0x02C)
+#define ISPH3A_AFCOEF0010		(0x030)
+#define ISPH3A_AFCOEF110		(0x034)
+#define ISPH3A_AFCOEF132		(0x038)
+#define ISPH3A_AFCOEF154		(0x03C)
+#define ISPH3A_AFCOEF176		(0x040)
+#define ISPH3A_AFCOEF198		(0x044)
+#define ISPH3A_AFCOEF1010		(0x048)
+
+#define ISPPRV_PCR			(0x004)
+#define ISPPRV_HORZ_INFO		(0x008)
+#define ISPPRV_VERT_INFO		(0x00C)
+#define ISPPRV_RSDR_ADDR		(0x010)
+#define ISPPRV_RADR_OFFSET		(0x014)
+#define ISPPRV_DSDR_ADDR		(0x018)
+#define ISPPRV_DRKF_OFFSET		(0x01C)
+#define ISPPRV_WSDR_ADDR		(0x020)
+#define ISPPRV_WADD_OFFSET		(0x024)
+#define ISPPRV_AVE			(0x028)
+#define ISPPRV_HMED			(0x02C)
+#define ISPPRV_NF			(0x030)
+#define ISPPRV_WB_DGAIN			(0x034)
+#define ISPPRV_WBGAIN			(0x038)
+#define ISPPRV_WBSEL			(0x03C)
+#define ISPPRV_CFA			(0x040)
+#define ISPPRV_BLKADJOFF		(0x044)
+#define ISPPRV_RGB_MAT1			(0x048)
+#define ISPPRV_RGB_MAT2			(0x04C)
+#define ISPPRV_RGB_MAT3			(0x050)
+#define ISPPRV_RGB_MAT4			(0x054)
+#define ISPPRV_RGB_MAT5			(0x058)
+#define ISPPRV_RGB_OFF1			(0x05C)
+#define ISPPRV_RGB_OFF2			(0x060)
+#define ISPPRV_CSC0			(0x064)
+#define ISPPRV_CSC1			(0x068)
+#define ISPPRV_CSC2			(0x06C)
+#define ISPPRV_CSC_OFFSET		(0x070)
+#define ISPPRV_CNT_BRT			(0x074)
+#define ISPPRV_CSUP			(0x078)
+#define ISPPRV_SETUP_YC			(0x07C)
+#define ISPPRV_SET_TBL_ADDR		(0x080)
+#define ISPPRV_SET_TBL_DATA		(0x084)
+#define ISPPRV_CDC_THR0			(0x090)
+#define ISPPRV_CDC_THR1			(ISPPRV_CDC_THR0 + (0x4))
+#define ISPPRV_CDC_THR2			(ISPPRV_CDC_THR0 + (0x4) * 2)
+#define ISPPRV_CDC_THR3			(ISPPRV_CDC_THR0 + (0x4) * 3)
+
+#define ISPPRV_REDGAMMA_TABLE_ADDR	0x0000
+#define ISPPRV_GREENGAMMA_TABLE_ADDR	0x0400
+#define ISPPRV_BLUEGAMMA_TABLE_ADDR	0x0800
+#define ISPPRV_NF_TABLE_ADDR		0x0C00
+#define ISPPRV_YENH_TABLE_ADDR		0x1000
+#define ISPPRV_CFA_TABLE_ADDR		0x1400
+
+#define ISPPRV_MAXOUTPUT_WIDTH		1280
+#define ISPPRV_MAXOUTPUT_WIDTH_ES2	3300
+#define ISPPRV_MAXOUTPUT_WIDTH_3630	4096
+#define ISPRSZ_MIN_OUTPUT		64
+#define ISPRSZ_MAX_OUTPUT		3312
+
+/* Resizer module register offset */
+#define ISPRSZ_PID			(0x000)
+#define ISPRSZ_PCR			(0x004)
+#define ISPRSZ_CNT			(0x008)
+#define ISPRSZ_OUT_SIZE			(0x00C)
+#define ISPRSZ_IN_START			(0x010)
+#define ISPRSZ_IN_SIZE			(0x014)
+#define ISPRSZ_SDR_INADD		(0x018)
+#define ISPRSZ_SDR_INOFF		(0x01C)
+#define ISPRSZ_SDR_OUTADD		(0x020)
+#define ISPRSZ_SDR_OUTOFF		(0x024)
+#define ISPRSZ_HFILT10			(0x028)
+#define ISPRSZ_HFILT32			(0x02C)
+#define ISPRSZ_HFILT54			(0x030)
+#define ISPRSZ_HFILT76			(0x034)
+#define ISPRSZ_HFILT98			(0x038)
+#define ISPRSZ_HFILT1110		(0x03C)
+#define ISPRSZ_HFILT1312		(0x040)
+#define ISPRSZ_HFILT1514		(0x044)
+#define ISPRSZ_HFILT1716		(0x048)
+#define ISPRSZ_HFILT1918		(0x04C)
+#define ISPRSZ_HFILT2120		(0x050)
+#define ISPRSZ_HFILT2322		(0x054)
+#define ISPRSZ_HFILT2524		(0x058)
+#define ISPRSZ_HFILT2726		(0x05C)
+#define ISPRSZ_HFILT2928		(0x060)
+#define ISPRSZ_HFILT3130		(0x064)
+#define ISPRSZ_VFILT10			(0x068)
+#define ISPRSZ_VFILT32			(0x06C)
+#define ISPRSZ_VFILT54			(0x070)
+#define ISPRSZ_VFILT76			(0x074)
+#define ISPRSZ_VFILT98			(0x078)
+#define ISPRSZ_VFILT1110		(0x07C)
+#define ISPRSZ_VFILT1312		(0x080)
+#define ISPRSZ_VFILT1514		(0x084)
+#define ISPRSZ_VFILT1716		(0x088)
+#define ISPRSZ_VFILT1918		(0x08C)
+#define ISPRSZ_VFILT2120		(0x090)
+#define ISPRSZ_VFILT2322		(0x094)
+#define ISPRSZ_VFILT2524		(0x098)
+#define ISPRSZ_VFILT2726		(0x09C)
+#define ISPRSZ_VFILT2928		(0x0A0)
+#define ISPRSZ_VFILT3130		(0x0A4)
+#define ISPRSZ_YENH			(0x0A8)
+
+#define ISP_INT_CLR			0xFF113F11
+#define ISPPRV_PCR_EN			1
+#define ISPPRV_PCR_BUSY			(1 << 1)
+#define ISPPRV_PCR_SOURCE		(1 << 2)
+#define ISPPRV_PCR_ONESHOT		(1 << 3)
+#define ISPPRV_PCR_WIDTH		(1 << 4)
+#define ISPPRV_PCR_INVALAW		(1 << 5)
+#define ISPPRV_PCR_DRKFEN		(1 << 6)
+#define ISPPRV_PCR_DRKFCAP		(1 << 7)
+#define ISPPRV_PCR_HMEDEN		(1 << 8)
+#define ISPPRV_PCR_NFEN			(1 << 9)
+#define ISPPRV_PCR_CFAEN		(1 << 10)
+#define ISPPRV_PCR_CFAFMT_SHIFT		11
+#define ISPPRV_PCR_CFAFMT_MASK		0x7800
+#define ISPPRV_PCR_CFAFMT_BAYER		(0 << 11)
+#define ISPPRV_PCR_CFAFMT_SONYVGA	(1 << 11)
+#define ISPPRV_PCR_CFAFMT_RGBFOVEON	(2 << 11)
+#define ISPPRV_PCR_CFAFMT_DNSPL		(3 << 11)
+#define ISPPRV_PCR_CFAFMT_HONEYCOMB	(4 << 11)
+#define ISPPRV_PCR_CFAFMT_RRGGBBFOVEON	(5 << 11)
+#define ISPPRV_PCR_YNENHEN		(1 << 15)
+#define ISPPRV_PCR_SUPEN		(1 << 16)
+#define ISPPRV_PCR_YCPOS_SHIFT		17
+#define ISPPRV_PCR_YCPOS_YCrYCb		(0 << 17)
+#define ISPPRV_PCR_YCPOS_YCbYCr		(1 << 17)
+#define ISPPRV_PCR_YCPOS_CbYCrY		(2 << 17)
+#define ISPPRV_PCR_YCPOS_CrYCbY		(3 << 17)
+#define ISPPRV_PCR_RSZPORT		(1 << 19)
+#define ISPPRV_PCR_SDRPORT		(1 << 20)
+#define ISPPRV_PCR_SCOMP_EN		(1 << 21)
+#define ISPPRV_PCR_SCOMP_SFT_SHIFT	(22)
+#define ISPPRV_PCR_SCOMP_SFT_MASK	(7 << 22)
+#define ISPPRV_PCR_GAMMA_BYPASS		(1 << 26)
+#define ISPPRV_PCR_DCOREN		(1 << 27)
+#define ISPPRV_PCR_DCCOUP		(1 << 28)
+#define ISPPRV_PCR_DRK_FAIL		(1 << 31)
+
+#define ISPPRV_HORZ_INFO_EPH_SHIFT	0
+#define ISPPRV_HORZ_INFO_EPH_MASK	0x3fff
+#define ISPPRV_HORZ_INFO_SPH_SHIFT	16
+#define ISPPRV_HORZ_INFO_SPH_MASK	0x3fff0
+
+#define ISPPRV_VERT_INFO_ELV_SHIFT	0
+#define ISPPRV_VERT_INFO_ELV_MASK	0x3fff
+#define ISPPRV_VERT_INFO_SLV_SHIFT	16
+#define ISPPRV_VERT_INFO_SLV_MASK	0x3fff0
+
+#define ISPPRV_AVE_EVENDIST_SHIFT	2
+#define ISPPRV_AVE_EVENDIST_1		0x0
+#define ISPPRV_AVE_EVENDIST_2		0x1
+#define ISPPRV_AVE_EVENDIST_3		0x2
+#define ISPPRV_AVE_EVENDIST_4		0x3
+#define ISPPRV_AVE_ODDDIST_SHIFT	4
+#define ISPPRV_AVE_ODDDIST_1		0x0
+#define ISPPRV_AVE_ODDDIST_2		0x1
+#define ISPPRV_AVE_ODDDIST_3		0x2
+#define ISPPRV_AVE_ODDDIST_4		0x3
+
+#define ISPPRV_HMED_THRESHOLD_SHIFT	0
+#define ISPPRV_HMED_EVENDIST		(1 << 8)
+#define ISPPRV_HMED_ODDDIST		(1 << 9)
+
+#define ISPPRV_WBGAIN_COEF0_SHIFT	0
+#define ISPPRV_WBGAIN_COEF1_SHIFT	8
+#define ISPPRV_WBGAIN_COEF2_SHIFT	16
+#define ISPPRV_WBGAIN_COEF3_SHIFT	24
+
+#define ISPPRV_WBSEL_COEF0		0x0
+#define ISPPRV_WBSEL_COEF1		0x1
+#define ISPPRV_WBSEL_COEF2		0x2
+#define ISPPRV_WBSEL_COEF3		0x3
+
+#define ISPPRV_WBSEL_N0_0_SHIFT		0
+#define ISPPRV_WBSEL_N0_1_SHIFT		2
+#define ISPPRV_WBSEL_N0_2_SHIFT		4
+#define ISPPRV_WBSEL_N0_3_SHIFT		6
+#define ISPPRV_WBSEL_N1_0_SHIFT		8
+#define ISPPRV_WBSEL_N1_1_SHIFT		10
+#define ISPPRV_WBSEL_N1_2_SHIFT		12
+#define ISPPRV_WBSEL_N1_3_SHIFT		14
+#define ISPPRV_WBSEL_N2_0_SHIFT		16
+#define ISPPRV_WBSEL_N2_1_SHIFT		18
+#define ISPPRV_WBSEL_N2_2_SHIFT		20
+#define ISPPRV_WBSEL_N2_3_SHIFT		22
+#define ISPPRV_WBSEL_N3_0_SHIFT		24
+#define ISPPRV_WBSEL_N3_1_SHIFT		26
+#define ISPPRV_WBSEL_N3_2_SHIFT		28
+#define ISPPRV_WBSEL_N3_3_SHIFT		30
+
+#define ISPPRV_CFA_GRADTH_HOR_SHIFT	0
+#define ISPPRV_CFA_GRADTH_VER_SHIFT	8
+
+#define ISPPRV_BLKADJOFF_B_SHIFT	0
+#define ISPPRV_BLKADJOFF_G_SHIFT	8
+#define ISPPRV_BLKADJOFF_R_SHIFT	16
+
+#define ISPPRV_RGB_MAT1_MTX_RR_SHIFT	0
+#define ISPPRV_RGB_MAT1_MTX_GR_SHIFT	16
+
+#define ISPPRV_RGB_MAT2_MTX_BR_SHIFT	0
+#define ISPPRV_RGB_MAT2_MTX_RG_SHIFT	16
+
+#define ISPPRV_RGB_MAT3_MTX_GG_SHIFT	0
+#define ISPPRV_RGB_MAT3_MTX_BG_SHIFT	16
+
+#define ISPPRV_RGB_MAT4_MTX_RB_SHIFT	0
+#define ISPPRV_RGB_MAT4_MTX_GB_SHIFT	16
+
+#define ISPPRV_RGB_MAT5_MTX_BB_SHIFT	0
+
+#define ISPPRV_RGB_OFF1_MTX_OFFG_SHIFT	0
+#define ISPPRV_RGB_OFF1_MTX_OFFR_SHIFT	16
+
+#define ISPPRV_RGB_OFF2_MTX_OFFB_SHIFT	0
+
+#define ISPPRV_CSC0_RY_SHIFT		0
+#define ISPPRV_CSC0_GY_SHIFT		10
+#define ISPPRV_CSC0_BY_SHIFT		20
+
+#define ISPPRV_CSC1_RCB_SHIFT		0
+#define ISPPRV_CSC1_GCB_SHIFT		10
+#define ISPPRV_CSC1_BCB_SHIFT		20
+
+#define ISPPRV_CSC2_RCR_SHIFT		0
+#define ISPPRV_CSC2_GCR_SHIFT		10
+#define ISPPRV_CSC2_BCR_SHIFT		20
+
+#define ISPPRV_CSC_OFFSET_CR_SHIFT	0
+#define ISPPRV_CSC_OFFSET_CB_SHIFT	8
+#define ISPPRV_CSC_OFFSET_Y_SHIFT	16
+
+#define ISPPRV_CNT_BRT_BRT_SHIFT	0
+#define ISPPRV_CNT_BRT_CNT_SHIFT	8
+
+#define ISPPRV_CONTRAST_MAX		0x10
+#define ISPPRV_CONTRAST_MIN		0xFF
+#define ISPPRV_BRIGHT_MIN		0x00
+#define ISPPRV_BRIGHT_MAX		0xFF
+
+#define ISPPRV_CSUP_CSUPG_SHIFT		0
+#define ISPPRV_CSUP_THRES_SHIFT		8
+#define ISPPRV_CSUP_HPYF_SHIFT		16
+
+#define ISPPRV_SETUP_YC_MINC_SHIFT	0
+#define ISPPRV_SETUP_YC_MAXC_SHIFT	8
+#define ISPPRV_SETUP_YC_MINY_SHIFT	16
+#define ISPPRV_SETUP_YC_MAXY_SHIFT	24
+#define ISPPRV_YC_MAX			0xFF
+#define ISPPRV_YC_MIN			0x0
+
+/* Define bit fields within selected registers */
+#define ISP_REVISION_SHIFT			0
+
+#define ISP_SYSCONFIG_AUTOIDLE			(1 << 0)
+#define ISP_SYSCONFIG_SOFTRESET			(1 << 1)
+#define ISP_SYSCONFIG_MIDLEMODE_SHIFT		12
+#define ISP_SYSCONFIG_MIDLEMODE_FORCESTANDBY	0x0
+#define ISP_SYSCONFIG_MIDLEMODE_NOSTANBY	0x1
+#define ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY	0x2
+
+#define ISP_SYSSTATUS_RESETDONE			0
+
+#define IRQ0ENABLE_CSIA_IRQ			(1 << 0)
+#define IRQ0ENABLE_CSIC_IRQ			(1 << 1)
+#define IRQ0ENABLE_CCP2_LCM_IRQ			(1 << 3)
+#define IRQ0ENABLE_CCP2_LC0_IRQ			(1 << 4)
+#define IRQ0ENABLE_CCP2_LC1_IRQ			(1 << 5)
+#define IRQ0ENABLE_CCP2_LC2_IRQ			(1 << 6)
+#define IRQ0ENABLE_CCP2_LC3_IRQ			(1 << 7)
+#define IRQ0ENABLE_CSIB_IRQ			(IRQ0ENABLE_CCP2_LCM_IRQ | \
+						IRQ0ENABLE_CCP2_LC0_IRQ | \
+						IRQ0ENABLE_CCP2_LC1_IRQ | \
+						IRQ0ENABLE_CCP2_LC2_IRQ | \
+						IRQ0ENABLE_CCP2_LC3_IRQ)
+
+#define IRQ0ENABLE_CCDC_VD0_IRQ			(1 << 8)
+#define IRQ0ENABLE_CCDC_VD1_IRQ			(1 << 9)
+#define IRQ0ENABLE_CCDC_VD2_IRQ			(1 << 10)
+#define IRQ0ENABLE_CCDC_ERR_IRQ			(1 << 11)
+#define IRQ0ENABLE_H3A_AF_DONE_IRQ		(1 << 12)
+#define IRQ0ENABLE_H3A_AWB_DONE_IRQ		(1 << 13)
+#define IRQ0ENABLE_HIST_DONE_IRQ		(1 << 16)
+#define IRQ0ENABLE_CCDC_LSC_DONE_IRQ		(1 << 17)
+#define IRQ0ENABLE_CCDC_LSC_PREF_COMP_IRQ	(1 << 18)
+#define IRQ0ENABLE_CCDC_LSC_PREF_ERR_IRQ	(1 << 19)
+#define IRQ0ENABLE_PRV_DONE_IRQ			(1 << 20)
+#define IRQ0ENABLE_RSZ_DONE_IRQ			(1 << 24)
+#define IRQ0ENABLE_OVF_IRQ			(1 << 25)
+#define IRQ0ENABLE_PING_IRQ			(1 << 26)
+#define IRQ0ENABLE_PONG_IRQ			(1 << 27)
+#define IRQ0ENABLE_MMU_ERR_IRQ			(1 << 28)
+#define IRQ0ENABLE_OCP_ERR_IRQ			(1 << 29)
+#define IRQ0ENABLE_SEC_ERR_IRQ			(1 << 30)
+#define IRQ0ENABLE_HS_VS_IRQ			(1 << 31)
+
+#define IRQ0STATUS_CSIA_IRQ			(1 << 0)
+#define IRQ0STATUS_CSI2C_IRQ			(1 << 1)
+#define IRQ0STATUS_CCP2_LCM_IRQ			(1 << 3)
+#define IRQ0STATUS_CCP2_LC0_IRQ			(1 << 4)
+#define IRQ0STATUS_CSIB_IRQ			(IRQ0STATUS_CCP2_LCM_IRQ | \
+						IRQ0STATUS_CCP2_LC0_IRQ)
+
+#define IRQ0STATUS_CSIB_LC1_IRQ			(1 << 5)
+#define IRQ0STATUS_CSIB_LC2_IRQ			(1 << 6)
+#define IRQ0STATUS_CSIB_LC3_IRQ			(1 << 7)
+#define IRQ0STATUS_CCDC_VD0_IRQ			(1 << 8)
+#define IRQ0STATUS_CCDC_VD1_IRQ			(1 << 9)
+#define IRQ0STATUS_CCDC_VD2_IRQ			(1 << 10)
+#define IRQ0STATUS_CCDC_ERR_IRQ			(1 << 11)
+#define IRQ0STATUS_H3A_AF_DONE_IRQ		(1 << 12)
+#define IRQ0STATUS_H3A_AWB_DONE_IRQ		(1 << 13)
+#define IRQ0STATUS_HIST_DONE_IRQ		(1 << 16)
+#define IRQ0STATUS_CCDC_LSC_DONE_IRQ		(1 << 17)
+#define IRQ0STATUS_CCDC_LSC_PREF_COMP_IRQ	(1 << 18)
+#define IRQ0STATUS_CCDC_LSC_PREF_ERR_IRQ	(1 << 19)
+#define IRQ0STATUS_PRV_DONE_IRQ			(1 << 20)
+#define IRQ0STATUS_RSZ_DONE_IRQ			(1 << 24)
+#define IRQ0STATUS_OVF_IRQ			(1 << 25)
+#define IRQ0STATUS_PING_IRQ			(1 << 26)
+#define IRQ0STATUS_PONG_IRQ			(1 << 27)
+#define IRQ0STATUS_MMU_ERR_IRQ			(1 << 28)
+#define IRQ0STATUS_OCP_ERR_IRQ			(1 << 29)
+#define IRQ0STATUS_SEC_ERR_IRQ			(1 << 30)
+#define IRQ0STATUS_HS_VS_IRQ			(1 << 31)
+
+#define TCTRL_GRESET_LEN			0
+
+#define TCTRL_PSTRB_REPLAY_DELAY		0
+#define TCTRL_PSTRB_REPLAY_COUNTER_SHIFT	25
+
+#define ISPCTRL_PAR_SER_CLK_SEL_PARALLEL	0x0
+#define ISPCTRL_PAR_SER_CLK_SEL_CSIA		0x1
+#define ISPCTRL_PAR_SER_CLK_SEL_CSIB		0x2
+#define ISPCTRL_PAR_SER_CLK_SEL_CSIC		0x3
+#define ISPCTRL_PAR_SER_CLK_SEL_MASK		0x3
+
+#define ISPCTRL_PAR_BRIDGE_SHIFT		2
+#define ISPCTRL_PAR_BRIDGE_DISABLE		(0x0 << 2)
+#define ISPCTRL_PAR_BRIDGE_LENDIAN		(0x2 << 2)
+#define ISPCTRL_PAR_BRIDGE_BENDIAN		(0x3 << 2)
+#define ISPCTRL_PAR_BRIDGE_MASK			(0x3 << 2)
+
+#define ISPCTRL_PAR_CLK_POL_SHIFT		4
+#define ISPCTRL_PAR_CLK_POL_INV			(1 << 4)
+#define ISPCTRL_PING_PONG_EN			(1 << 5)
+#define ISPCTRL_SHIFT_SHIFT			6
+#define ISPCTRL_SHIFT_0				(0x0 << 6)
+#define ISPCTRL_SHIFT_2				(0x1 << 6)
+#define ISPCTRL_SHIFT_4				(0x2 << 6)
+#define ISPCTRL_SHIFT_MASK			(0x3 << 6)
+
+#define ISPCTRL_CCDC_CLK_EN			(1 << 8)
+#define ISPCTRL_SCMP_CLK_EN			(1 << 9)
+#define ISPCTRL_H3A_CLK_EN			(1 << 10)
+#define ISPCTRL_HIST_CLK_EN			(1 << 11)
+#define ISPCTRL_PREV_CLK_EN			(1 << 12)
+#define ISPCTRL_RSZ_CLK_EN			(1 << 13)
+#define ISPCTRL_SYNC_DETECT_SHIFT		14
+#define ISPCTRL_SYNC_DETECT_HSFALL	(0x0 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_HSRISE	(0x1 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_VSFALL	(0x2 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_VSRISE	(0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
+#define ISPCTRL_SYNC_DETECT_MASK	(0x3 << ISPCTRL_SYNC_DETECT_SHIFT)
+
+#define ISPCTRL_CCDC_RAM_EN		(1 << 16)
+#define ISPCTRL_PREV_RAM_EN		(1 << 17)
+#define ISPCTRL_SBL_RD_RAM_EN		(1 << 18)
+#define ISPCTRL_SBL_WR1_RAM_EN		(1 << 19)
+#define ISPCTRL_SBL_WR0_RAM_EN		(1 << 20)
+#define ISPCTRL_SBL_AUTOIDLE		(1 << 21)
+#define ISPCTRL_SBL_SHARED_WPORTC	(1 << 26)
+#define ISPCTRL_SBL_SHARED_RPORTA	(1 << 27)
+#define ISPCTRL_SBL_SHARED_RPORTB	(1 << 28)
+#define ISPCTRL_JPEG_FLUSH		(1 << 30)
+#define ISPCTRL_CCDC_FLUSH		(1 << 31)
+
+#define ISPSECURE_SECUREMODE		0
+
+#define ISPTCTRL_CTRL_DIV_LOW		0x0
+#define ISPTCTRL_CTRL_DIV_HIGH		0x1
+#define ISPTCTRL_CTRL_DIV_BYPASS	0x1F
+
+#define ISPTCTRL_CTRL_DIVA_SHIFT	0
+#define ISPTCTRL_CTRL_DIVA_MASK		(0x1F << ISPTCTRL_CTRL_DIVA_SHIFT)
+
+#define ISPTCTRL_CTRL_DIVB_SHIFT	5
+#define ISPTCTRL_CTRL_DIVB_MASK		(0x1F << ISPTCTRL_CTRL_DIVB_SHIFT)
+
+#define ISPTCTRL_CTRL_DIVC_SHIFT	10
+#define ISPTCTRL_CTRL_DIVC_NOCLOCK	(0x0 << 10)
+
+#define ISPTCTRL_CTRL_SHUTEN		(1 << 21)
+#define ISPTCTRL_CTRL_PSTRBEN		(1 << 22)
+#define ISPTCTRL_CTRL_STRBEN		(1 << 23)
+#define ISPTCTRL_CTRL_SHUTPOL		(1 << 24)
+#define ISPTCTRL_CTRL_STRBPSTRBPOL	(1 << 26)
+
+#define ISPTCTRL_CTRL_INSEL_SHIFT	27
+#define ISPTCTRL_CTRL_INSEL_PARALLEL	(0x0 << 27)
+#define ISPTCTRL_CTRL_INSEL_CSIA	(0x1 << 27)
+#define ISPTCTRL_CTRL_INSEL_CSIB	(0x2 << 27)
+
+#define ISPTCTRL_CTRL_GRESETEn		(1 << 29)
+#define ISPTCTRL_CTRL_GRESETPOL		(1 << 30)
+#define ISPTCTRL_CTRL_GRESETDIR		(1 << 31)
+
+#define ISPTCTRL_FRAME_SHUT_SHIFT		0
+#define ISPTCTRL_FRAME_PSTRB_SHIFT		6
+#define ISPTCTRL_FRAME_STRB_SHIFT		12
+
+#define ISPCCDC_PID_PREV_SHIFT			0
+#define ISPCCDC_PID_CID_SHIFT			8
+#define ISPCCDC_PID_TID_SHIFT			16
+
+#define ISPCCDC_PCR_EN				1
+#define ISPCCDC_PCR_BUSY			(1 << 1)
+
+#define ISPCCDC_SYN_MODE_VDHDOUT		0x1
+#define ISPCCDC_SYN_MODE_FLDOUT			(1 << 1)
+#define ISPCCDC_SYN_MODE_VDPOL			(1 << 2)
+#define ISPCCDC_SYN_MODE_HDPOL			(1 << 3)
+#define ISPCCDC_SYN_MODE_FLDPOL			(1 << 4)
+#define ISPCCDC_SYN_MODE_EXWEN			(1 << 5)
+#define ISPCCDC_SYN_MODE_DATAPOL		(1 << 6)
+#define ISPCCDC_SYN_MODE_FLDMODE		(1 << 7)
+#define ISPCCDC_SYN_MODE_DATSIZ_MASK		(0x7 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_8_16		(0x0 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_12		(0x4 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_11		(0x5 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_10		(0x6 << 8)
+#define ISPCCDC_SYN_MODE_DATSIZ_8		(0x7 << 8)
+#define ISPCCDC_SYN_MODE_PACK8			(1 << 11)
+#define ISPCCDC_SYN_MODE_INPMOD_MASK		(3 << 12)
+#define ISPCCDC_SYN_MODE_INPMOD_RAW		(0 << 12)
+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR16		(1 << 12)
+#define ISPCCDC_SYN_MODE_INPMOD_YCBCR8		(2 << 12)
+#define ISPCCDC_SYN_MODE_LPF			(1 << 14)
+#define ISPCCDC_SYN_MODE_FLDSTAT		(1 << 15)
+#define ISPCCDC_SYN_MODE_VDHDEN			(1 << 16)
+#define ISPCCDC_SYN_MODE_WEN			(1 << 17)
+#define ISPCCDC_SYN_MODE_VP2SDR			(1 << 18)
+#define ISPCCDC_SYN_MODE_SDR2RSZ		(1 << 19)
+
+#define ISPCCDC_HD_VD_WID_VDW_SHIFT		0
+#define ISPCCDC_HD_VD_WID_HDW_SHIFT		16
+
+#define ISPCCDC_PIX_LINES_HLPRF_SHIFT		0
+#define ISPCCDC_PIX_LINES_PPLN_SHIFT		16
+
+#define ISPCCDC_HORZ_INFO_NPH_SHIFT		0
+#define ISPCCDC_HORZ_INFO_NPH_MASK		0x00007fff
+#define ISPCCDC_HORZ_INFO_SPH_SHIFT		16
+#define ISPCCDC_HORZ_INFO_SPH_MASK		0x7fff0000
+
+#define ISPCCDC_VERT_START_SLV1_SHIFT		0
+#define ISPCCDC_VERT_START_SLV0_SHIFT		16
+#define ISPCCDC_VERT_START_SLV0_MASK		0x7fff0000
+
+#define ISPCCDC_VERT_LINES_NLV_SHIFT		0
+#define ISPCCDC_VERT_LINES_NLV_MASK		0x00007fff
+
+#define ISPCCDC_CULLING_CULV_SHIFT		0
+#define ISPCCDC_CULLING_CULHODD_SHIFT		16
+#define ISPCCDC_CULLING_CULHEVN_SHIFT		24
+
+#define ISPCCDC_HSIZE_OFF_SHIFT			0
+
+#define ISPCCDC_SDOFST_FINV			(1 << 14)
+#define ISPCCDC_SDOFST_FOFST_1L			0
+#define ISPCCDC_SDOFST_FOFST_4L			(3 << 12)
+#define ISPCCDC_SDOFST_LOFST3_SHIFT		0
+#define ISPCCDC_SDOFST_LOFST2_SHIFT		3
+#define ISPCCDC_SDOFST_LOFST1_SHIFT		6
+#define ISPCCDC_SDOFST_LOFST0_SHIFT		9
+#define EVENEVEN				1
+#define ODDEVEN					2
+#define EVENODD					3
+#define ODDODD					4
+
+#define ISPCCDC_CLAMP_OBGAIN_SHIFT		0
+#define ISPCCDC_CLAMP_OBST_SHIFT		10
+#define ISPCCDC_CLAMP_OBSLN_SHIFT		25
+#define ISPCCDC_CLAMP_OBSLEN_SHIFT		28
+#define ISPCCDC_CLAMP_CLAMPEN			(1 << 31)
+
+#define ISPCCDC_COLPTN_R_Ye			0x0
+#define ISPCCDC_COLPTN_Gr_Cy			0x1
+#define ISPCCDC_COLPTN_Gb_G			0x2
+#define ISPCCDC_COLPTN_B_Mg			0x3
+#define ISPCCDC_COLPTN_CP0PLC0_SHIFT		0
+#define ISPCCDC_COLPTN_CP0PLC1_SHIFT		2
+#define ISPCCDC_COLPTN_CP0PLC2_SHIFT		4
+#define ISPCCDC_COLPTN_CP0PLC3_SHIFT		6
+#define ISPCCDC_COLPTN_CP1PLC0_SHIFT		8
+#define ISPCCDC_COLPTN_CP1PLC1_SHIFT		10
+#define ISPCCDC_COLPTN_CP1PLC2_SHIFT		12
+#define ISPCCDC_COLPTN_CP1PLC3_SHIFT		14
+#define ISPCCDC_COLPTN_CP2PLC0_SHIFT		16
+#define ISPCCDC_COLPTN_CP2PLC1_SHIFT		18
+#define ISPCCDC_COLPTN_CP2PLC2_SHIFT		20
+#define ISPCCDC_COLPTN_CP2PLC3_SHIFT		22
+#define ISPCCDC_COLPTN_CP3PLC0_SHIFT		24
+#define ISPCCDC_COLPTN_CP3PLC1_SHIFT		26
+#define ISPCCDC_COLPTN_CP3PLC2_SHIFT		28
+#define ISPCCDC_COLPTN_CP3PLC3_SHIFT		30
+
+#define ISPCCDC_BLKCMP_B_MG_SHIFT		0
+#define ISPCCDC_BLKCMP_GB_G_SHIFT		8
+#define ISPCCDC_BLKCMP_GR_CY_SHIFT		16
+#define ISPCCDC_BLKCMP_R_YE_SHIFT		24
+
+#define ISPCCDC_FPC_FPNUM_SHIFT			0
+#define ISPCCDC_FPC_FPCEN			(1 << 15)
+#define ISPCCDC_FPC_FPERR			(1 << 16)
+
+#define ISPCCDC_VDINT_1_SHIFT			0
+#define ISPCCDC_VDINT_1_MASK			0x00007fff
+#define ISPCCDC_VDINT_0_SHIFT			16
+#define ISPCCDC_VDINT_0_MASK			0x7fff0000
+
+#define ISPCCDC_ALAW_GWDI_12_3			(0x3 << 0)
+#define ISPCCDC_ALAW_GWDI_11_2			(0x4 << 0)
+#define ISPCCDC_ALAW_GWDI_10_1			(0x5 << 0)
+#define ISPCCDC_ALAW_GWDI_9_0			(0x6 << 0)
+#define ISPCCDC_ALAW_CCDTBL			(1 << 3)
+
+#define ISPCCDC_REC656IF_R656ON			1
+#define ISPCCDC_REC656IF_ECCFVH			(1 << 1)
+
+#define ISPCCDC_CFG_BW656			(1 << 5)
+#define ISPCCDC_CFG_FIDMD_SHIFT			6
+#define ISPCCDC_CFG_WENLOG			(1 << 8)
+#define ISPCCDC_CFG_WENLOG_AND			(0 << 8)
+#define ISPCCDC_CFG_WENLOG_OR			(1 << 8)
+#define ISPCCDC_CFG_Y8POS			(1 << 11)
+#define ISPCCDC_CFG_BSWD			(1 << 12)
+#define ISPCCDC_CFG_MSBINVI			(1 << 13)
+#define ISPCCDC_CFG_VDLC			(1 << 15)
+
+#define ISPCCDC_FMTCFG_FMTEN			0x1
+#define ISPCCDC_FMTCFG_LNALT			(1 << 1)
+#define ISPCCDC_FMTCFG_LNUM_SHIFT		2
+#define ISPCCDC_FMTCFG_PLEN_ODD_SHIFT		4
+#define ISPCCDC_FMTCFG_PLEN_EVEN_SHIFT		8
+#define ISPCCDC_FMTCFG_VPIN_MASK		0x00007000
+#define ISPCCDC_FMTCFG_VPIN_12_3		(0x3 << 12)
+#define ISPCCDC_FMTCFG_VPIN_11_2		(0x4 << 12)
+#define ISPCCDC_FMTCFG_VPIN_10_1		(0x5 << 12)
+#define ISPCCDC_FMTCFG_VPIN_9_0			(0x6 << 12)
+#define ISPCCDC_FMTCFG_VPEN			(1 << 15)
+
+#define ISPCCDC_FMTCFG_VPIF_FRQ_MASK		0x003f0000
+#define ISPCCDC_FMTCFG_VPIF_FRQ_SHIFT		16
+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY2		(0x0 << 16)
+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY3		(0x1 << 16)
+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY4		(0x2 << 16)
+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY5		(0x3 << 16)
+#define ISPCCDC_FMTCFG_VPIF_FRQ_BY6		(0x4 << 16)
+
+#define ISPCCDC_FMT_HORZ_FMTLNH_SHIFT		0
+#define ISPCCDC_FMT_HORZ_FMTSPH_SHIFT		16
+
+#define ISPCCDC_FMT_VERT_FMTLNV_SHIFT		0
+#define ISPCCDC_FMT_VERT_FMTSLV_SHIFT		16
+
+#define ISPCCDC_FMT_HORZ_FMTSPH_MASK		0x1fff0000
+#define ISPCCDC_FMT_HORZ_FMTLNH_MASK		0x00001fff
+
+#define ISPCCDC_FMT_VERT_FMTSLV_MASK		0x1fff0000
+#define ISPCCDC_FMT_VERT_FMTLNV_MASK		0x00001fff
+
+#define ISPCCDC_VP_OUT_HORZ_ST_SHIFT		0
+#define ISPCCDC_VP_OUT_HORZ_NUM_SHIFT		4
+#define ISPCCDC_VP_OUT_VERT_NUM_SHIFT		17
+
+#define ISPRSZ_PID_PREV_SHIFT			0
+#define ISPRSZ_PID_CID_SHIFT			8
+#define ISPRSZ_PID_TID_SHIFT			16
+
+#define ISPRSZ_PCR_ENABLE			(1 << 0)
+#define ISPRSZ_PCR_BUSY				(1 << 1)
+#define ISPRSZ_PCR_ONESHOT			(1 << 2)
+
+#define ISPRSZ_CNT_HRSZ_SHIFT			0
+#define ISPRSZ_CNT_HRSZ_MASK			\
+	(0x3FF << ISPRSZ_CNT_HRSZ_SHIFT)
+#define ISPRSZ_CNT_VRSZ_SHIFT			10
+#define ISPRSZ_CNT_VRSZ_MASK			\
+	(0x3FF << ISPRSZ_CNT_VRSZ_SHIFT)
+#define ISPRSZ_CNT_HSTPH_SHIFT			20
+#define ISPRSZ_CNT_HSTPH_MASK			(0x7 << ISPRSZ_CNT_HSTPH_SHIFT)
+#define ISPRSZ_CNT_VSTPH_SHIFT			23
+#define ISPRSZ_CNT_VSTPH_MASK			(0x7 << ISPRSZ_CNT_VSTPH_SHIFT)
+#define ISPRSZ_CNT_YCPOS			(1 << 26)
+#define ISPRSZ_CNT_INPTYP			(1 << 27)
+#define ISPRSZ_CNT_INPSRC			(1 << 28)
+#define ISPRSZ_CNT_CBILIN			(1 << 29)
+
+#define ISPRSZ_OUT_SIZE_HORZ_SHIFT		0
+#define ISPRSZ_OUT_SIZE_HORZ_MASK		\
+	(0xFFF << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
+#define ISPRSZ_OUT_SIZE_VERT_SHIFT		16
+#define ISPRSZ_OUT_SIZE_VERT_MASK		\
+	(0xFFF << ISPRSZ_OUT_SIZE_VERT_SHIFT)
+
+#define ISPRSZ_IN_START_HORZ_ST_SHIFT		0
+#define ISPRSZ_IN_START_HORZ_ST_MASK		\
+	(0x1FFF << ISPRSZ_IN_START_HORZ_ST_SHIFT)
+#define ISPRSZ_IN_START_VERT_ST_SHIFT		16
+#define ISPRSZ_IN_START_VERT_ST_MASK		\
+	(0x1FFF << ISPRSZ_IN_START_VERT_ST_SHIFT)
+
+#define ISPRSZ_IN_SIZE_HORZ_SHIFT		0
+#define ISPRSZ_IN_SIZE_HORZ_MASK		\
+	(0x1FFF << ISPRSZ_IN_SIZE_HORZ_SHIFT)
+#define ISPRSZ_IN_SIZE_VERT_SHIFT		16
+#define ISPRSZ_IN_SIZE_VERT_MASK		\
+	(0x1FFF << ISPRSZ_IN_SIZE_VERT_SHIFT)
+
+#define ISPRSZ_SDR_INADD_ADDR_SHIFT		0
+#define ISPRSZ_SDR_INADD_ADDR_MASK		0xFFFFFFFF
+
+#define ISPRSZ_SDR_INOFF_OFFSET_SHIFT		0
+#define ISPRSZ_SDR_INOFF_OFFSET_MASK		\
+	(0xFFFF << ISPRSZ_SDR_INOFF_OFFSET_SHIFT)
+
+#define ISPRSZ_SDR_OUTADD_ADDR_SHIFT		0
+#define ISPRSZ_SDR_OUTADD_ADDR_MASK		0xFFFFFFFF
+
+
+#define ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT		0
+#define ISPRSZ_SDR_OUTOFF_OFFSET_MASK		\
+	(0xFFFF << ISPRSZ_SDR_OUTOFF_OFFSET_SHIFT)
+
+#define ISPRSZ_HFILT_COEF0_SHIFT		0
+#define ISPRSZ_HFILT_COEF0_MASK			\
+	(0x3FF << ISPRSZ_HFILT_COEF0_SHIFT)
+#define ISPRSZ_HFILT_COEF1_SHIFT		16
+#define ISPRSZ_HFILT_COEF1_MASK			\
+	(0x3FF << ISPRSZ_HFILT_COEF1_SHIFT)
+
+#define ISPRSZ_HFILT32_COEF2_SHIFT		0
+#define ISPRSZ_HFILT32_COEF2_MASK		0x3FF
+#define ISPRSZ_HFILT32_COEF3_SHIFT		16
+#define ISPRSZ_HFILT32_COEF3_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT54_COEF4_SHIFT		0
+#define ISPRSZ_HFILT54_COEF4_MASK		0x3FF
+#define ISPRSZ_HFILT54_COEF5_SHIFT		16
+#define ISPRSZ_HFILT54_COEF5_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT76_COEFF6_SHIFT		0
+#define ISPRSZ_HFILT76_COEFF6_MASK		0x3FF
+#define ISPRSZ_HFILT76_COEFF7_SHIFT		16
+#define ISPRSZ_HFILT76_COEFF7_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT98_COEFF8_SHIFT		0
+#define ISPRSZ_HFILT98_COEFF8_MASK		0x3FF
+#define ISPRSZ_HFILT98_COEFF9_SHIFT		16
+#define ISPRSZ_HFILT98_COEFF9_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1110_COEF10_SHIFT		0
+#define ISPRSZ_HFILT1110_COEF10_MASK		0x3FF
+#define ISPRSZ_HFILT1110_COEF11_SHIFT		16
+#define ISPRSZ_HFILT1110_COEF11_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1312_COEFF12_SHIFT		0
+#define ISPRSZ_HFILT1312_COEFF12_MASK		0x3FF
+#define ISPRSZ_HFILT1312_COEFF13_SHIFT		16
+#define ISPRSZ_HFILT1312_COEFF13_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1514_COEFF14_SHIFT		0
+#define ISPRSZ_HFILT1514_COEFF14_MASK		0x3FF
+#define ISPRSZ_HFILT1514_COEFF15_SHIFT		16
+#define ISPRSZ_HFILT1514_COEFF15_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1716_COEF16_SHIFT		0
+#define ISPRSZ_HFILT1716_COEF16_MASK		0x3FF
+#define ISPRSZ_HFILT1716_COEF17_SHIFT		16
+#define ISPRSZ_HFILT1716_COEF17_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT1918_COEF18_SHIFT		0
+#define ISPRSZ_HFILT1918_COEF18_MASK		0x3FF
+#define ISPRSZ_HFILT1918_COEF19_SHIFT		16
+#define ISPRSZ_HFILT1918_COEF19_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2120_COEF20_SHIFT		0
+#define ISPRSZ_HFILT2120_COEF20_MASK		0x3FF
+#define ISPRSZ_HFILT2120_COEF21_SHIFT		16
+#define ISPRSZ_HFILT2120_COEF21_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2322_COEF22_SHIFT		0
+#define ISPRSZ_HFILT2322_COEF22_MASK		0x3FF
+#define ISPRSZ_HFILT2322_COEF23_SHIFT		16
+#define ISPRSZ_HFILT2322_COEF23_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2524_COEF24_SHIFT		0
+#define ISPRSZ_HFILT2524_COEF24_MASK		0x3FF
+#define ISPRSZ_HFILT2524_COEF25_SHIFT		16
+#define ISPRSZ_HFILT2524_COEF25_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2726_COEF26_SHIFT		0
+#define ISPRSZ_HFILT2726_COEF26_MASK		0x3FF
+#define ISPRSZ_HFILT2726_COEF27_SHIFT		16
+#define ISPRSZ_HFILT2726_COEF27_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT2928_COEF28_SHIFT		0
+#define ISPRSZ_HFILT2928_COEF28_MASK		0x3FF
+#define ISPRSZ_HFILT2928_COEF29_SHIFT		16
+#define ISPRSZ_HFILT2928_COEF29_MASK		0x3FF0000
+
+#define ISPRSZ_HFILT3130_COEF30_SHIFT		0
+#define ISPRSZ_HFILT3130_COEF30_MASK		0x3FF
+#define ISPRSZ_HFILT3130_COEF31_SHIFT		16
+#define ISPRSZ_HFILT3130_COEF31_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT_COEF0_SHIFT		0
+#define ISPRSZ_VFILT_COEF0_MASK			\
+	(0x3FF << ISPRSZ_VFILT_COEF0_SHIFT)
+#define ISPRSZ_VFILT_COEF1_SHIFT		16
+#define ISPRSZ_VFILT_COEF1_MASK			\
+	(0x3FF << ISPRSZ_VFILT_COEF1_SHIFT)
+
+#define ISPRSZ_VFILT10_COEF0_SHIFT		0
+#define ISPRSZ_VFILT10_COEF0_MASK		0x3FF
+#define ISPRSZ_VFILT10_COEF1_SHIFT		16
+#define ISPRSZ_VFILT10_COEF1_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT32_COEF2_SHIFT		0
+#define ISPRSZ_VFILT32_COEF2_MASK		0x3FF
+#define ISPRSZ_VFILT32_COEF3_SHIFT		16
+#define ISPRSZ_VFILT32_COEF3_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT54_COEF4_SHIFT		0
+#define ISPRSZ_VFILT54_COEF4_MASK		0x3FF
+#define ISPRSZ_VFILT54_COEF5_SHIFT		16
+#define ISPRSZ_VFILT54_COEF5_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT76_COEFF6_SHIFT		0
+#define ISPRSZ_VFILT76_COEFF6_MASK		0x3FF
+#define ISPRSZ_VFILT76_COEFF7_SHIFT		16
+#define ISPRSZ_VFILT76_COEFF7_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT98_COEFF8_SHIFT		0
+#define ISPRSZ_VFILT98_COEFF8_MASK		0x3FF
+#define ISPRSZ_VFILT98_COEFF9_SHIFT		16
+#define ISPRSZ_VFILT98_COEFF9_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1110_COEF10_SHIFT		0
+#define ISPRSZ_VFILT1110_COEF10_MASK		0x3FF
+#define ISPRSZ_VFILT1110_COEF11_SHIFT		16
+#define ISPRSZ_VFILT1110_COEF11_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1312_COEFF12_SHIFT		0
+#define ISPRSZ_VFILT1312_COEFF12_MASK		0x3FF
+#define ISPRSZ_VFILT1312_COEFF13_SHIFT		16
+#define ISPRSZ_VFILT1312_COEFF13_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1514_COEFF14_SHIFT		0
+#define ISPRSZ_VFILT1514_COEFF14_MASK		0x3FF
+#define ISPRSZ_VFILT1514_COEFF15_SHIFT		16
+#define ISPRSZ_VFILT1514_COEFF15_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1716_COEF16_SHIFT		0
+#define ISPRSZ_VFILT1716_COEF16_MASK		0x3FF
+#define ISPRSZ_VFILT1716_COEF17_SHIFT		16
+#define ISPRSZ_VFILT1716_COEF17_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT1918_COEF18_SHIFT		0
+#define ISPRSZ_VFILT1918_COEF18_MASK		0x3FF
+#define ISPRSZ_VFILT1918_COEF19_SHIFT		16
+#define ISPRSZ_VFILT1918_COEF19_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2120_COEF20_SHIFT		0
+#define ISPRSZ_VFILT2120_COEF20_MASK		0x3FF
+#define ISPRSZ_VFILT2120_COEF21_SHIFT		16
+#define ISPRSZ_VFILT2120_COEF21_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2322_COEF22_SHIFT		0
+#define ISPRSZ_VFILT2322_COEF22_MASK		0x3FF
+#define ISPRSZ_VFILT2322_COEF23_SHIFT		16
+#define ISPRSZ_VFILT2322_COEF23_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2524_COEF24_SHIFT		0
+#define ISPRSZ_VFILT2524_COEF24_MASK		0x3FF
+#define ISPRSZ_VFILT2524_COEF25_SHIFT		16
+#define ISPRSZ_VFILT2524_COEF25_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2726_COEF26_SHIFT		0
+#define ISPRSZ_VFILT2726_COEF26_MASK		0x3FF
+#define ISPRSZ_VFILT2726_COEF27_SHIFT		16
+#define ISPRSZ_VFILT2726_COEF27_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT2928_COEF28_SHIFT		0
+#define ISPRSZ_VFILT2928_COEF28_MASK		0x3FF
+#define ISPRSZ_VFILT2928_COEF29_SHIFT		16
+#define ISPRSZ_VFILT2928_COEF29_MASK		0x3FF0000
+
+#define ISPRSZ_VFILT3130_COEF30_SHIFT		0
+#define ISPRSZ_VFILT3130_COEF30_MASK		0x3FF
+#define ISPRSZ_VFILT3130_COEF31_SHIFT		16
+#define ISPRSZ_VFILT3130_COEF31_MASK		0x3FF0000
+
+#define ISPRSZ_YENH_CORE_SHIFT			0
+#define ISPRSZ_YENH_CORE_MASK			\
+	(0xFF << ISPRSZ_YENH_CORE_SHIFT)
+#define ISPRSZ_YENH_SLOP_SHIFT			8
+#define ISPRSZ_YENH_SLOP_MASK			\
+	(0xF << ISPRSZ_YENH_SLOP_SHIFT)
+#define ISPRSZ_YENH_GAIN_SHIFT			12
+#define ISPRSZ_YENH_GAIN_MASK			\
+	(0xF << ISPRSZ_YENH_GAIN_SHIFT)
+#define ISPRSZ_YENH_ALGO_SHIFT			16
+#define ISPRSZ_YENH_ALGO_MASK			\
+	(0x3 << ISPRSZ_YENH_ALGO_SHIFT)
+
+#define ISPH3A_PCR_AEW_ALAW_EN_SHIFT		1
+#define ISPH3A_PCR_AF_MED_TH_SHIFT		3
+#define ISPH3A_PCR_AF_RGBPOS_SHIFT		11
+#define ISPH3A_PCR_AEW_AVE2LMT_SHIFT		22
+#define ISPH3A_PCR_AEW_AVE2LMT_MASK		0xFFC00000
+#define ISPH3A_PCR_BUSYAF			(1 << 15)
+#define ISPH3A_PCR_BUSYAEAWB			(1 << 18)
+
+#define ISPH3A_AEWWIN1_WINHC_SHIFT		0
+#define ISPH3A_AEWWIN1_WINHC_MASK		0x3F
+#define ISPH3A_AEWWIN1_WINVC_SHIFT		6
+#define ISPH3A_AEWWIN1_WINVC_MASK		0x1FC0
+#define ISPH3A_AEWWIN1_WINW_SHIFT		13
+#define ISPH3A_AEWWIN1_WINW_MASK		0xFE000
+#define ISPH3A_AEWWIN1_WINH_SHIFT		24
+#define ISPH3A_AEWWIN1_WINH_MASK		0x7F000000
+
+#define ISPH3A_AEWINSTART_WINSH_SHIFT		0
+#define ISPH3A_AEWINSTART_WINSH_MASK		0x0FFF
+#define ISPH3A_AEWINSTART_WINSV_SHIFT		16
+#define ISPH3A_AEWINSTART_WINSV_MASK		0x0FFF0000
+
+#define ISPH3A_AEWINBLK_WINH_SHIFT		0
+#define ISPH3A_AEWINBLK_WINH_MASK		0x7F
+#define ISPH3A_AEWINBLK_WINSV_SHIFT		16
+#define ISPH3A_AEWINBLK_WINSV_MASK		0x0FFF0000
+
+#define ISPH3A_AEWSUBWIN_AEWINCH_SHIFT		0
+#define ISPH3A_AEWSUBWIN_AEWINCH_MASK		0x0F
+#define ISPH3A_AEWSUBWIN_AEWINCV_SHIFT		8
+#define ISPH3A_AEWSUBWIN_AEWINCV_MASK		0x0F00
+
+#define ISPHIST_PCR_ENABLE_SHIFT	0
+#define ISPHIST_PCR_ENABLE_MASK		0x01
+#define ISPHIST_PCR_ENABLE		(1 << ISPHIST_PCR_ENABLE_SHIFT)
+#define ISPHIST_PCR_BUSY		0x02
+
+#define ISPHIST_CNT_DATASIZE_SHIFT	8
+#define ISPHIST_CNT_DATASIZE_MASK	0x0100
+#define ISPHIST_CNT_CLEAR_SHIFT		7
+#define ISPHIST_CNT_CLEAR_MASK		0x080
+#define ISPHIST_CNT_CLEAR		(1 << ISPHIST_CNT_CLEAR_SHIFT)
+#define ISPHIST_CNT_CFA_SHIFT		6
+#define ISPHIST_CNT_CFA_MASK		0x040
+#define ISPHIST_CNT_BINS_SHIFT		4
+#define ISPHIST_CNT_BINS_MASK		0x030
+#define ISPHIST_CNT_SOURCE_SHIFT	3
+#define ISPHIST_CNT_SOURCE_MASK		0x08
+#define ISPHIST_CNT_SHIFT_SHIFT		0
+#define ISPHIST_CNT_SHIFT_MASK		0x07
+
+#define ISPHIST_WB_GAIN_WG00_SHIFT	24
+#define ISPHIST_WB_GAIN_WG00_MASK	0xFF000000
+#define ISPHIST_WB_GAIN_WG01_SHIFT	16
+#define ISPHIST_WB_GAIN_WG01_MASK	0xFF0000
+#define ISPHIST_WB_GAIN_WG02_SHIFT	8
+#define ISPHIST_WB_GAIN_WG02_MASK	0xFF00
+#define ISPHIST_WB_GAIN_WG03_SHIFT	0
+#define ISPHIST_WB_GAIN_WG03_MASK	0xFF
+
+#define ISPHIST_REG_START_END_MASK		0x3FFF
+#define ISPHIST_REG_START_SHIFT			16
+#define ISPHIST_REG_END_SHIFT			0
+#define ISPHIST_REG_START_MASK			(ISPHIST_REG_START_END_MASK << \
+						 ISPHIST_REG_START_SHIFT)
+#define ISPHIST_REG_END_MASK			(ISPHIST_REG_START_END_MASK << \
+						 ISPHIST_REG_END_SHIFT)
+
+#define ISPHIST_REG_MASK			(ISPHIST_REG_START_MASK | \
+						 ISPHIST_REG_END_MASK)
+
+#define ISPHIST_ADDR_SHIFT			0
+#define ISPHIST_ADDR_MASK			0x3FF
+
+#define ISPHIST_DATA_SHIFT			0
+#define ISPHIST_DATA_MASK			0xFFFFF
+
+#define ISPHIST_RADD_SHIFT			0
+#define ISPHIST_RADD_MASK			0xFFFFFFFF
+
+#define ISPHIST_RADD_OFF_SHIFT			0
+#define ISPHIST_RADD_OFF_MASK			0xFFFF
+
+#define ISPHIST_HV_INFO_HSIZE_SHIFT		16
+#define ISPHIST_HV_INFO_HSIZE_MASK		0x3FFF0000
+#define ISPHIST_HV_INFO_VSIZE_SHIFT		0
+#define ISPHIST_HV_INFO_VSIZE_MASK		0x3FFF
+
+#define ISPHIST_HV_INFO_MASK			0x3FFF3FFF
+
+#define ISPCCDC_LSC_ENABLE			1
+#define ISPCCDC_LSC_BUSY			(1 << 7)
+#define ISPCCDC_LSC_GAIN_MODE_N_MASK		0x700
+#define ISPCCDC_LSC_GAIN_MODE_N_SHIFT		8
+#define ISPCCDC_LSC_GAIN_MODE_M_MASK		0x3800
+#define ISPCCDC_LSC_GAIN_MODE_M_SHIFT		12
+#define ISPCCDC_LSC_GAIN_FORMAT_MASK		0xE
+#define ISPCCDC_LSC_GAIN_FORMAT_SHIFT		1
+#define ISPCCDC_LSC_AFTER_REFORMATTER_MASK	(1<<6)
+
+#define ISPCCDC_LSC_INITIAL_X_MASK		0x3F
+#define ISPCCDC_LSC_INITIAL_X_SHIFT		0
+#define ISPCCDC_LSC_INITIAL_Y_MASK		0x3F0000
+#define ISPCCDC_LSC_INITIAL_Y_SHIFT		16
+
+/* -----------------------------------------------------------------------------
+ * CSI2 receiver registers (ES2.0)
+ */
+
+#define ISPCSI2_REVISION			(0x000)
+#define ISPCSI2_SYSCONFIG			(0x010)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT	12
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_MASK	\
+	(0x3 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_FORCE	\
+	(0x0 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_NO	\
+	(0x1 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SMART	\
+	(0x2 << ISPCSI2_SYSCONFIG_MSTANDBY_MODE_SHIFT)
+#define ISPCSI2_SYSCONFIG_SOFT_RESET		(1 << 1)
+#define ISPCSI2_SYSCONFIG_AUTO_IDLE		(1 << 0)
+
+#define ISPCSI2_SYSSTATUS			(0x014)
+#define ISPCSI2_SYSSTATUS_RESET_DONE		(1 << 0)
+
+#define ISPCSI2_IRQSTATUS			(0x018)
+#define ISPCSI2_IRQSTATUS_OCP_ERR_IRQ		(1 << 14)
+#define ISPCSI2_IRQSTATUS_SHORT_PACKET_IRQ	(1 << 13)
+#define ISPCSI2_IRQSTATUS_ECC_CORRECTION_IRQ	(1 << 12)
+#define ISPCSI2_IRQSTATUS_ECC_NO_CORRECTION_IRQ	(1 << 11)
+#define ISPCSI2_IRQSTATUS_COMPLEXIO2_ERR_IRQ	(1 << 10)
+#define ISPCSI2_IRQSTATUS_COMPLEXIO1_ERR_IRQ	(1 << 9)
+#define ISPCSI2_IRQSTATUS_FIFO_OVF_IRQ		(1 << 8)
+#define ISPCSI2_IRQSTATUS_CONTEXT(n)		(1 << (n))
+
+#define ISPCSI2_IRQENABLE			(0x01c)
+#define ISPCSI2_CTRL				(0x040)
+#define ISPCSI2_CTRL_VP_CLK_EN			(1 << 15)
+#define ISPCSI2_CTRL_VP_ONLY_EN			(1 << 11)
+#define ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT		8
+#define ISPCSI2_CTRL_VP_OUT_CTRL_MASK		\
+	(3 << ISPCSI2_CTRL_VP_OUT_CTRL_SHIFT)
+#define ISPCSI2_CTRL_DBG_EN			(1 << 7)
+#define ISPCSI2_CTRL_BURST_SIZE_SHIFT		5
+#define ISPCSI2_CTRL_BURST_SIZE_MASK		\
+	(3 << ISPCSI2_CTRL_BURST_SIZE_SHIFT)
+#define ISPCSI2_CTRL_FRAME			(1 << 3)
+#define ISPCSI2_CTRL_ECC_EN			(1 << 2)
+#define ISPCSI2_CTRL_SECURE			(1 << 1)
+#define ISPCSI2_CTRL_IF_EN			(1 << 0)
+
+#define ISPCSI2_DBG_H				(0x044)
+#define ISPCSI2_GNQ				(0x048)
+#define ISPCSI2_PHY_CFG				(0x050)
+#define ISPCSI2_PHY_CFG_RESET_CTRL		(1 << 30)
+#define ISPCSI2_PHY_CFG_RESET_DONE		(1 << 29)
+#define ISPCSI2_PHY_CFG_PWR_CMD_SHIFT		27
+#define ISPCSI2_PHY_CFG_PWR_CMD_MASK		\
+	(0x3 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_CMD_OFF		\
+	(0x0 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_CMD_ON		\
+	(0x1 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_CMD_ULPW		\
+	(0x2 << ISPCSI2_PHY_CFG_PWR_CMD_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT	25
+#define ISPCSI2_PHY_CFG_PWR_STATUS_MASK		\
+	(0x3 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_STATUS_OFF		\
+	(0x0 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_STATUS_ON		\
+	(0x1 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_STATUS_ULPW		\
+	(0x2 << ISPCSI2_PHY_CFG_PWR_STATUS_SHIFT)
+#define ISPCSI2_PHY_CFG_PWR_AUTO		(1 << 24)
+
+#define ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n)	(3 + ((n) * 4))
+#define ISPCSI2_PHY_CFG_DATA_POL_MASK(n)	\
+	(0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POL_PN(n)		\
+	(0x0 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POL_NP(n)		\
+	(0x1 << ISPCSI2_PHY_CFG_DATA_POL_SHIFT(n))
+
+#define ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n)	((n) * 4)
+#define ISPCSI2_PHY_CFG_DATA_POSITION_MASK(n)	\
+	(0x7 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POSITION_NC(n)	\
+	(0x0 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POSITION_1(n)	\
+	(0x1 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POSITION_2(n)	\
+	(0x2 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POSITION_3(n)	\
+	(0x3 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POSITION_4(n)	\
+	(0x4 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+#define ISPCSI2_PHY_CFG_DATA_POSITION_5(n)	\
+	(0x5 << ISPCSI2_PHY_CFG_DATA_POSITION_SHIFT(n))
+
+#define ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT		3
+#define ISPCSI2_PHY_CFG_CLOCK_POL_MASK		\
+	(0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POL_PN		\
+	(0x0 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POL_NP		\
+	(0x1 << ISPCSI2_PHY_CFG_CLOCK_POL_SHIFT)
+
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT	0
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_MASK	\
+	(0x7 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_1	\
+	(0x1 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_2	\
+	(0x2 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_3	\
+	(0x3 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_4	\
+	(0x4 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
+#define ISPCSI2_PHY_CFG_CLOCK_POSITION_5	\
+	(0x5 << ISPCSI2_PHY_CFG_CLOCK_POSITION_SHIFT)
+
+#define ISPCSI2_PHY_IRQSTATUS			(0x054)
+#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMEXIT	(1 << 26)
+#define ISPCSI2_PHY_IRQSTATUS_STATEALLULPMENTER	(1 << 25)
+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM5	(1 << 24)
+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM4	(1 << 23)
+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM3	(1 << 22)
+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM2	(1 << 21)
+#define ISPCSI2_PHY_IRQSTATUS_STATEULPM1	(1 << 20)
+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL5	(1 << 19)
+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL4	(1 << 18)
+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL3	(1 << 17)
+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL2	(1 << 16)
+#define ISPCSI2_PHY_IRQSTATUS_ERRCONTROL1	(1 << 15)
+#define ISPCSI2_PHY_IRQSTATUS_ERRESC5		(1 << 14)
+#define ISPCSI2_PHY_IRQSTATUS_ERRESC4		(1 << 13)
+#define ISPCSI2_PHY_IRQSTATUS_ERRESC3		(1 << 12)
+#define ISPCSI2_PHY_IRQSTATUS_ERRESC2		(1 << 11)
+#define ISPCSI2_PHY_IRQSTATUS_ERRESC1		(1 << 10)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS5	(1 << 9)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS4	(1 << 8)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS3	(1 << 7)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS2	(1 << 6)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTSYNCHS1	(1 << 5)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS5		(1 << 4)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS4		(1 << 3)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS3		(1 << 2)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS2		(1 << 1)
+#define ISPCSI2_PHY_IRQSTATUS_ERRSOTHS1		1
+
+#define ISPCSI2_SHORT_PACKET			(0x05c)
+#define ISPCSI2_PHY_IRQENABLE			(0x060)
+#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMEXIT	(1 << 26)
+#define ISPCSI2_PHY_IRQENABLE_STATEALLULPMENTER	(1 << 25)
+#define ISPCSI2_PHY_IRQENABLE_STATEULPM5	(1 << 24)
+#define ISPCSI2_PHY_IRQENABLE_STATEULPM4	(1 << 23)
+#define ISPCSI2_PHY_IRQENABLE_STATEULPM3	(1 << 22)
+#define ISPCSI2_PHY_IRQENABLE_STATEULPM2	(1 << 21)
+#define ISPCSI2_PHY_IRQENABLE_STATEULPM1	(1 << 20)
+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL5	(1 << 19)
+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL4	(1 << 18)
+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL3	(1 << 17)
+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL2	(1 << 16)
+#define ISPCSI2_PHY_IRQENABLE_ERRCONTROL1	(1 << 15)
+#define ISPCSI2_PHY_IRQENABLE_ERRESC5		(1 << 14)
+#define ISPCSI2_PHY_IRQENABLE_ERRESC4		(1 << 13)
+#define ISPCSI2_PHY_IRQENABLE_ERRESC3		(1 << 12)
+#define ISPCSI2_PHY_IRQENABLE_ERRESC2		(1 << 11)
+#define ISPCSI2_PHY_IRQENABLE_ERRESC1		(1 << 10)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS5	(1 << 9)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS4	(1 << 8)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS3	(1 << 7)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS2	(1 << 6)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTSYNCHS1	(1 << 5)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS5		(1 << 4)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS4		(1 << 3)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS3		(1 << 2)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS2		(1 << 1)
+#define ISPCSI2_PHY_IRQENABLE_ERRSOTHS1		(1 << 0)
+
+#define ISPCSI2_DBG_P				(0x068)
+#define ISPCSI2_TIMING				(0x06c)
+#define ISPCSI2_TIMING_FORCE_RX_MODE_IO(n)	(1 << ((16 * ((n) - 1)) + 15))
+#define ISPCSI2_TIMING_STOP_STATE_X16_IO(n)	(1 << ((16 * ((n) - 1)) + 14))
+#define ISPCSI2_TIMING_STOP_STATE_X4_IO(n)	(1 << ((16 * ((n) - 1)) + 13))
+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n)	(16 * ((n) - 1))
+#define ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_MASK(n)	\
+	(0x1fff << ISPCSI2_TIMING_STOP_STATE_COUNTER_IO_SHIFT(n))
+
+#define ISPCSI2_CTX_CTRL1(n)			((0x070) + 0x20 * (n))
+#define ISPCSI2_CTX_CTRL1_COUNT_SHIFT		8
+#define ISPCSI2_CTX_CTRL1_COUNT_MASK		\
+	(0xff << ISPCSI2_CTX_CTRL1_COUNT_SHIFT)
+#define ISPCSI2_CTX_CTRL1_EOF_EN		(1 << 7)
+#define ISPCSI2_CTX_CTRL1_EOL_EN		(1 << 6)
+#define ISPCSI2_CTX_CTRL1_CS_EN			(1 << 5)
+#define ISPCSI2_CTX_CTRL1_COUNT_UNLOCK		(1 << 4)
+#define ISPCSI2_CTX_CTRL1_PING_PONG		(1 << 3)
+#define ISPCSI2_CTX_CTRL1_CTX_EN		(1 << 0)
+
+#define ISPCSI2_CTX_CTRL2(n)			((0x074) + 0x20 * (n))
+#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT	13
+#define ISPCSI2_CTX_CTRL2_USER_DEF_MAP_MASK	\
+	(0x3 << ISPCSI2_CTX_CTRL2_USER_DEF_MAP_SHIFT)
+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT	11
+#define ISPCSI2_CTX_CTRL2_VIRTUAL_ID_MASK	\
+	(0x3 <<	ISPCSI2_CTX_CTRL2_VIRTUAL_ID_SHIFT)
+#define ISPCSI2_CTX_CTRL2_DPCM_PRED		(1 << 10)
+#define ISPCSI2_CTX_CTRL2_FORMAT_SHIFT		0
+#define ISPCSI2_CTX_CTRL2_FORMAT_MASK		\
+	(0x3ff << ISPCSI2_CTX_CTRL2_FORMAT_SHIFT)
+#define ISPCSI2_CTX_CTRL2_FRAME_SHIFT		16
+#define ISPCSI2_CTX_CTRL2_FRAME_MASK		\
+	(0xffff << ISPCSI2_CTX_CTRL2_FRAME_SHIFT)
+
+#define ISPCSI2_CTX_DAT_OFST(n)			((0x078) + 0x20 * (n))
+#define ISPCSI2_CTX_DAT_OFST_OFST_SHIFT		0
+#define ISPCSI2_CTX_DAT_OFST_OFST_MASK		\
+	(0x1ffe0 << ISPCSI2_CTX_DAT_OFST_OFST_SHIFT)
+
+#define ISPCSI2_CTX_DAT_PING_ADDR(n)		((0x07c) + 0x20 * (n))
+#define ISPCSI2_CTX_DAT_PONG_ADDR(n)		((0x080) + 0x20 * (n))
+#define ISPCSI2_CTX_IRQENABLE(n)		((0x084) + 0x20 * (n))
+#define ISPCSI2_CTX_IRQENABLE_ECC_CORRECTION_IRQ	(1 << 8)
+#define ISPCSI2_CTX_IRQENABLE_LINE_NUMBER_IRQ	(1 << 7)
+#define ISPCSI2_CTX_IRQENABLE_FRAME_NUMBER_IRQ	(1 << 6)
+#define ISPCSI2_CTX_IRQENABLE_CS_IRQ		(1 << 5)
+#define ISPCSI2_CTX_IRQENABLE_LE_IRQ		(1 << 3)
+#define ISPCSI2_CTX_IRQENABLE_LS_IRQ		(1 << 2)
+#define ISPCSI2_CTX_IRQENABLE_FE_IRQ		(1 << 1)
+#define ISPCSI2_CTX_IRQENABLE_FS_IRQ		(1 << 0)
+
+#define ISPCSI2_CTX_IRQSTATUS(n)		((0x088) + 0x20 * (n))
+#define ISPCSI2_CTX_IRQSTATUS_ECC_CORRECTION_IRQ	(1 << 8)
+#define ISPCSI2_CTX_IRQSTATUS_LINE_NUMBER_IRQ	(1 << 7)
+#define ISPCSI2_CTX_IRQSTATUS_FRAME_NUMBER_IRQ	(1 << 6)
+#define ISPCSI2_CTX_IRQSTATUS_CS_IRQ		(1 << 5)
+#define ISPCSI2_CTX_IRQSTATUS_LE_IRQ		(1 << 3)
+#define ISPCSI2_CTX_IRQSTATUS_LS_IRQ		(1 << 2)
+#define ISPCSI2_CTX_IRQSTATUS_FE_IRQ		(1 << 1)
+#define ISPCSI2_CTX_IRQSTATUS_FS_IRQ		(1 << 0)
+
+#define ISPCSI2_CTX_CTRL3(n)			((0x08c) + 0x20 * (n))
+#define ISPCSI2_CTX_CTRL3_ALPHA_SHIFT		5
+#define ISPCSI2_CTX_CTRL3_ALPHA_MASK		\
+	(0x3fff << ISPCSI2_CTX_CTRL3_ALPHA_SHIFT)
+
+/* This instance is for OMAP3630 only */
+#define ISPCSI2_CTX_TRANSCODEH(n)		(0x000 + 0x8 * (n))
+#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT	16
+#define ISPCSI2_CTX_TRANSCODEH_HCOUNT_MASK	\
+	(0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
+#define ISPCSI2_CTX_TRANSCODEH_HSKIP_SHIFT	0
+#define ISPCSI2_CTX_TRANSCODEH_HSKIP_MASK	\
+	(0x1fff << ISPCSI2_CTX_TRANSCODEH_HCOUNT_SHIFT)
+#define ISPCSI2_CTX_TRANSCODEV(n)		(0x004 + 0x8 * (n))
+#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT	16
+#define ISPCSI2_CTX_TRANSCODEV_VCOUNT_MASK	\
+	(0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
+#define ISPCSI2_CTX_TRANSCODEV_VSKIP_SHIFT	0
+#define ISPCSI2_CTX_TRANSCODEV_VSKIP_MASK	\
+	(0x1fff << ISPCSI2_CTX_TRANSCODEV_VCOUNT_SHIFT)
+
+/* -----------------------------------------------------------------------------
+ * CSI PHY registers
+ */
+
+#define ISPCSIPHY_REG0				(0x000)
+#define ISPCSIPHY_REG0_THS_TERM_SHIFT		8
+#define ISPCSIPHY_REG0_THS_TERM_MASK		\
+	(0xff << ISPCSIPHY_REG0_THS_TERM_SHIFT)
+#define ISPCSIPHY_REG0_THS_SETTLE_SHIFT		0
+#define ISPCSIPHY_REG0_THS_SETTLE_MASK		\
+	(0xff << ISPCSIPHY_REG0_THS_SETTLE_SHIFT)
+
+#define ISPCSIPHY_REG1					(0x004)
+#define ISPCSIPHY_REG1_RESET_DONE_CTRLCLK		(1 << 29)
+/* This field is for OMAP3630 only */
+#define ISPCSIPHY_REG1_CLOCK_MISS_DETECTOR_STATUS	(1 << 25)
+#define ISPCSIPHY_REG1_TCLK_TERM_SHIFT			18
+#define ISPCSIPHY_REG1_TCLK_TERM_MASK			\
+	(0x7f << ISPCSIPHY_REG1_TCLK_TERM_SHIFT)
+#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_SHIFT	10
+#define ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN_MASK	\
+	(0xff << ISPCSIPHY_REG1_DPHY_HS_SYNC_PATTERN)
+/* This field is for OMAP3430 only */
+#define ISPCSIPHY_REG1_TCLK_MISS_SHIFT			8
+#define ISPCSIPHY_REG1_TCLK_MISS_MASK			\
+	(0x3 << ISPCSIPHY_REG1_TCLK_MISS_SHIFT)
+/* This field is for OMAP3630 only */
+#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT		8
+#define ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_MASK		\
+	(0x3 << ISPCSIPHY_REG1_CTRLCLK_DIV_FACTOR_SHIFT)
+#define ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT		0
+#define ISPCSIPHY_REG1_TCLK_SETTLE_MASK			\
+	(0xff << ISPCSIPHY_REG1_TCLK_SETTLE_SHIFT)
+
+/* This register is for OMAP3630 only */
+#define ISPCSIPHY_REG2					(0x008)
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT	30
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_MASK	\
+	(0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC0_SHIFT)
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT	28
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_MASK	\
+	(0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC1_SHIFT)
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT	26
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_MASK	\
+	(0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC2_SHIFT)
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT	24
+#define ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_MASK	\
+	(0x3 << ISPCSIPHY_REG2_TRIGGER_CMD_RXTRIGESC3_SHIFT)
+#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT		0
+#define ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_MASK		\
+	(0x7fffff << ISPCSIPHY_REG2_CCP2_SYNC_PATTERN_SHIFT)
+
+#endif	/* OMAP3_ISP_REG_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispresizer.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispresizer.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispresizer.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispresizer.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1738 @@
+/*
+ * ispresizer.c
+ *
+ * TI OMAP3 ISP - Resizer module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/device.h>
+#include <linux/mm.h>
+#include <linux/module.h>
+
+#include "isp.h"
+#include "ispreg.h"
+#include "ispresizer.h"
+
+/*
+ * Resizer Constants
+ */
+#define MIN_RESIZE_VALUE		64
+#define MID_RESIZE_VALUE		512
+#define MAX_RESIZE_VALUE		1024
+
+#define MIN_IN_WIDTH			32
+#define MIN_IN_HEIGHT			32
+#define MAX_IN_WIDTH_MEMORY_MODE	4095
+#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES1	1280
+#define MAX_IN_WIDTH_ONTHEFLY_MODE_ES2	4095
+#define MAX_IN_HEIGHT			4095
+
+#define MIN_OUT_WIDTH			16
+#define MIN_OUT_HEIGHT			2
+#define MAX_OUT_HEIGHT			4095
+
+/*
+ * Resizer Use Constraints
+ * "TRM ES3.1, table 12-46"
+ */
+#define MAX_4TAP_OUT_WIDTH_ES1		1280
+#define MAX_7TAP_OUT_WIDTH_ES1		640
+#define MAX_4TAP_OUT_WIDTH_ES2		3312
+#define MAX_7TAP_OUT_WIDTH_ES2		1650
+#define MAX_4TAP_OUT_WIDTH_3630		4096
+#define MAX_7TAP_OUT_WIDTH_3630		2048
+
+/*
+ * Constants for ratio calculation
+ */
+#define RESIZE_DIVISOR			256
+#define DEFAULT_PHASE			1
+
+/*
+ * Default (and only) configuration of filter coefficients.
+ * 7-tap mode is for scale factors 0.25x to 0.5x.
+ * 4-tap mode is for scale factors 0.5x to 4.0x.
+ * There shouldn't be any reason to recalculate these, EVER.
+ */
+static const struct isprsz_coef filter_coefs = {
+	/* For 8-phase 4-tap horizontal filter: */
+	{
+		0x0000, 0x0100, 0x0000, 0x0000,
+		0x03FA, 0x00F6, 0x0010, 0x0000,
+		0x03F9, 0x00DB, 0x002C, 0x0000,
+		0x03FB, 0x00B3, 0x0053, 0x03FF,
+		0x03FD, 0x0082, 0x0084, 0x03FD,
+		0x03FF, 0x0053, 0x00B3, 0x03FB,
+		0x0000, 0x002C, 0x00DB, 0x03F9,
+		0x0000, 0x0010, 0x00F6, 0x03FA
+	},
+	/* For 8-phase 4-tap vertical filter: */
+	{
+		0x0000, 0x0100, 0x0000, 0x0000,
+		0x03FA, 0x00F6, 0x0010, 0x0000,
+		0x03F9, 0x00DB, 0x002C, 0x0000,
+		0x03FB, 0x00B3, 0x0053, 0x03FF,
+		0x03FD, 0x0082, 0x0084, 0x03FD,
+		0x03FF, 0x0053, 0x00B3, 0x03FB,
+		0x0000, 0x002C, 0x00DB, 0x03F9,
+		0x0000, 0x0010, 0x00F6, 0x03FA
+	},
+	/* For 4-phase 7-tap horizontal filter: */
+	#define DUMMY 0
+	{
+		0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000, DUMMY,
+		0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000, DUMMY,
+		0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
+		0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
+	},
+	/* For 4-phase 7-tap vertical filter: */
+	{
+		0x0004, 0x0023, 0x005A, 0x0058, 0x0023, 0x0004, 0x0000, DUMMY,
+		0x0002, 0x0018, 0x004d, 0x0060, 0x0031, 0x0008, 0x0000, DUMMY,
+		0x0001, 0x000f, 0x003f, 0x0062, 0x003f, 0x000f, 0x0001, DUMMY,
+		0x0000, 0x0008, 0x0031, 0x0060, 0x004d, 0x0018, 0x0002, DUMMY
+	}
+	/*
+	 * The dummy padding is required in 7-tap mode because of how the
+	 * registers are arranged physically.
+	 */
+	#undef DUMMY
+};
+
+/*
+ * __resizer_get_format - helper function for getting resizer format
+ * @res   : pointer to resizer private structure
+ * @pad   : pad number
+ * @fh    : V4L2 subdev file handle
+ * @which : wanted subdev format
+ * return zero
+ */
+static struct v4l2_mbus_framefmt *
+__resizer_get_format(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
+		     unsigned int pad, enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_format(fh, pad);
+	else
+		return &res->formats[pad];
+}
+
+/*
+ * __resizer_get_crop - helper function for getting resizer crop rectangle
+ * @res   : pointer to resizer private structure
+ * @fh    : V4L2 subdev file handle
+ * @which : wanted subdev crop rectangle
+ */
+static struct v4l2_rect *
+__resizer_get_crop(struct isp_res_device *res, struct v4l2_subdev_fh *fh,
+		   enum v4l2_subdev_format_whence which)
+{
+	if (which == V4L2_SUBDEV_FORMAT_TRY)
+		return v4l2_subdev_get_try_crop(fh, RESZ_PAD_SINK);
+	else
+		return &res->crop.request;
+}
+
+/*
+ * resizer_set_filters - Set resizer filters
+ * @res: Device context.
+ * @h_coeff: horizontal coefficient
+ * @v_coeff: vertical coefficient
+ * Return none
+ */
+static void resizer_set_filters(struct isp_res_device *res, const u16 *h_coeff,
+				const u16 *v_coeff)
+{
+	struct isp_device *isp = to_isp_device(res);
+	u32 startaddr_h, startaddr_v, tmp_h, tmp_v;
+	int i;
+
+	startaddr_h = ISPRSZ_HFILT10;
+	startaddr_v = ISPRSZ_VFILT10;
+
+	for (i = 0; i < COEFF_CNT; i += 2) {
+		tmp_h = h_coeff[i] |
+			(h_coeff[i + 1] << ISPRSZ_HFILT_COEF1_SHIFT);
+		tmp_v = v_coeff[i] |
+			(v_coeff[i + 1] << ISPRSZ_VFILT_COEF1_SHIFT);
+		isp_reg_writel(isp, tmp_h, OMAP3_ISP_IOMEM_RESZ, startaddr_h);
+		isp_reg_writel(isp, tmp_v, OMAP3_ISP_IOMEM_RESZ, startaddr_v);
+		startaddr_h += 4;
+		startaddr_v += 4;
+	}
+}
+
+/*
+ * resizer_set_bilinear - Chrominance horizontal algorithm select
+ * @res: Device context.
+ * @type: Filtering interpolation type.
+ *
+ * Filtering that is same as luminance processing is
+ * intended only for downsampling, and bilinear interpolation
+ * is intended only for upsampling.
+ */
+static void resizer_set_bilinear(struct isp_res_device *res,
+				 enum resizer_chroma_algo type)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	if (type == RSZ_BILINEAR)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_CBILIN);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_CBILIN);
+}
+
+/*
+ * resizer_set_ycpos - Luminance and chrominance order
+ * @res: Device context.
+ * @order: order type.
+ */
+static void resizer_set_ycpos(struct isp_res_device *res,
+			      enum v4l2_mbus_pixelcode pixelcode)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	switch (pixelcode) {
+	case V4L2_MBUS_FMT_YUYV8_1X16:
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_YCPOS);
+		break;
+	case V4L2_MBUS_FMT_UYVY8_1X16:
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_YCPOS);
+		break;
+	default:
+		return;
+	}
+}
+
+/*
+ * resizer_set_phase - Setup horizontal and vertical starting phase
+ * @res: Device context.
+ * @h_phase: horizontal phase parameters.
+ * @v_phase: vertical phase parameters.
+ *
+ * Horizontal and vertical phase range is 0 to 7
+ */
+static void resizer_set_phase(struct isp_res_device *res, u32 h_phase,
+			      u32 v_phase)
+{
+	struct isp_device *isp = to_isp_device(res);
+	u32 rgval = 0;
+
+	rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
+	      ~(ISPRSZ_CNT_HSTPH_MASK | ISPRSZ_CNT_VSTPH_MASK);
+	rgval |= (h_phase << ISPRSZ_CNT_HSTPH_SHIFT) & ISPRSZ_CNT_HSTPH_MASK;
+	rgval |= (v_phase << ISPRSZ_CNT_VSTPH_SHIFT) & ISPRSZ_CNT_VSTPH_MASK;
+
+	isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT);
+}
+
+/*
+ * resizer_set_luma - Setup luminance enhancer parameters
+ * @res: Device context.
+ * @luma: Structure for luminance enhancer parameters.
+ *
+ * Algorithm select:
+ *  0x0: Disable
+ *  0x1: [-1  2 -1]/2 high-pass filter
+ *  0x2: [-1 -2  6 -2 -1]/4 high-pass filter
+ *
+ * Maximum gain:
+ *  The data is coded in U4Q4 representation.
+ *
+ * Slope:
+ *  The data is coded in U4Q4 representation.
+ *
+ * Coring offset:
+ *  The data is coded in U8Q0 representation.
+ *
+ * The new luminance value is computed as:
+ *  Y += HPF(Y) x max(GAIN, (HPF(Y) - CORE) x SLOP + 8) >> 4.
+ */
+static void resizer_set_luma(struct isp_res_device *res,
+			     struct resizer_luma_yenh *luma)
+{
+	struct isp_device *isp = to_isp_device(res);
+	u32 rgval = 0;
+
+	rgval  = (luma->algo << ISPRSZ_YENH_ALGO_SHIFT)
+		  & ISPRSZ_YENH_ALGO_MASK;
+	rgval |= (luma->gain << ISPRSZ_YENH_GAIN_SHIFT)
+		  & ISPRSZ_YENH_GAIN_MASK;
+	rgval |= (luma->slope << ISPRSZ_YENH_SLOP_SHIFT)
+		  & ISPRSZ_YENH_SLOP_MASK;
+	rgval |= (luma->core << ISPRSZ_YENH_CORE_SHIFT)
+		  & ISPRSZ_YENH_CORE_MASK;
+
+	isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_YENH);
+}
+
+/*
+ * resizer_set_source - Input source select
+ * @res: Device context.
+ * @source: Input source type
+ *
+ * If this field is set to RESIZER_INPUT_VP, the resizer input is fed from
+ * Preview/CCDC engine, otherwise from memory.
+ */
+static void resizer_set_source(struct isp_res_device *res,
+			       enum resizer_input_entity source)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	if (source == RESIZER_INPUT_MEMORY)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_INPSRC);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_INPSRC);
+}
+
+/*
+ * resizer_set_ratio - Setup horizontal and vertical resizing value
+ * @res: Device context.
+ * @ratio: Structure for ratio parameters.
+ *
+ * Resizing range from 64 to 1024
+ */
+static void resizer_set_ratio(struct isp_res_device *res,
+			      const struct resizer_ratio *ratio)
+{
+	struct isp_device *isp = to_isp_device(res);
+	const u16 *h_filter, *v_filter;
+	u32 rgval = 0;
+
+	rgval = isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT) &
+			      ~(ISPRSZ_CNT_HRSZ_MASK | ISPRSZ_CNT_VRSZ_MASK);
+	rgval |= ((ratio->horz - 1) << ISPRSZ_CNT_HRSZ_SHIFT)
+		  & ISPRSZ_CNT_HRSZ_MASK;
+	rgval |= ((ratio->vert - 1) << ISPRSZ_CNT_VRSZ_SHIFT)
+		  & ISPRSZ_CNT_VRSZ_MASK;
+	isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT);
+
+	/* prepare horizontal filter coefficients */
+	if (ratio->horz > MID_RESIZE_VALUE)
+		h_filter = &filter_coefs.h_filter_coef_7tap[0];
+	else
+		h_filter = &filter_coefs.h_filter_coef_4tap[0];
+
+	/* prepare vertical filter coefficients */
+	if (ratio->vert > MID_RESIZE_VALUE)
+		v_filter = &filter_coefs.v_filter_coef_7tap[0];
+	else
+		v_filter = &filter_coefs.v_filter_coef_4tap[0];
+
+	resizer_set_filters(res, h_filter, v_filter);
+}
+
+/*
+ * resizer_set_dst_size - Setup the output height and width
+ * @res: Device context.
+ * @width: Output width.
+ * @height: Output height.
+ *
+ * Width :
+ *  The value must be EVEN.
+ *
+ * Height:
+ *  The number of bytes written to SDRAM must be
+ *  a multiple of 16-bytes if the vertical resizing factor
+ *  is greater than 1x (upsizing)
+ */
+static void resizer_set_output_size(struct isp_res_device *res,
+				    u32 width, u32 height)
+{
+	struct isp_device *isp = to_isp_device(res);
+	u32 rgval = 0;
+
+	dev_dbg(isp->dev, "Output size[w/h]: %dx%d\n", width, height);
+	rgval  = (width << ISPRSZ_OUT_SIZE_HORZ_SHIFT)
+		 & ISPRSZ_OUT_SIZE_HORZ_MASK;
+	rgval |= (height << ISPRSZ_OUT_SIZE_VERT_SHIFT)
+		 & ISPRSZ_OUT_SIZE_VERT_MASK;
+	isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_OUT_SIZE);
+}
+
+/*
+ * resizer_set_output_offset - Setup memory offset for the output lines.
+ * @res: Device context.
+ * @offset: Memory offset.
+ *
+ * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte
+ * boundary; the 5 LSBs are read-only. For optimal use of SDRAM bandwidth,
+ * the SDRAM line offset must be set on a 256-byte boundary
+ */
+static void resizer_set_output_offset(struct isp_res_device *res, u32 offset)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTOFF);
+}
+
+/*
+ * resizer_set_start - Setup vertical and horizontal start position
+ * @res: Device context.
+ * @left: Horizontal start position.
+ * @top: Vertical start position.
+ *
+ * Vertical start line:
+ *  This field makes sense only when the resizer obtains its input
+ *  from the preview engine/CCDC
+ *
+ * Horizontal start pixel:
+ *  Pixels are coded on 16 bits for YUV and 8 bits for color separate data.
+ *  When the resizer gets its input from SDRAM, this field must be set
+ *  to <= 15 for YUV 16-bit data and <= 31 for 8-bit color separate data
+ */
+static void resizer_set_start(struct isp_res_device *res, u32 left, u32 top)
+{
+	struct isp_device *isp = to_isp_device(res);
+	u32 rgval = 0;
+
+	rgval = (left << ISPRSZ_IN_START_HORZ_ST_SHIFT)
+		& ISPRSZ_IN_START_HORZ_ST_MASK;
+	rgval |= (top << ISPRSZ_IN_START_VERT_ST_SHIFT)
+		 & ISPRSZ_IN_START_VERT_ST_MASK;
+
+	isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_START);
+}
+
+/*
+ * resizer_set_input_size - Setup the input size
+ * @res: Device context.
+ * @width: The range is 0 to 4095 pixels
+ * @height: The range is 0 to 4095 lines
+ */
+static void resizer_set_input_size(struct isp_res_device *res,
+				   u32 width, u32 height)
+{
+	struct isp_device *isp = to_isp_device(res);
+	u32 rgval = 0;
+
+	dev_dbg(isp->dev, "Input size[w/h]: %dx%d\n", width, height);
+
+	rgval = (width << ISPRSZ_IN_SIZE_HORZ_SHIFT)
+		& ISPRSZ_IN_SIZE_HORZ_MASK;
+	rgval |= (height << ISPRSZ_IN_SIZE_VERT_SHIFT)
+		 & ISPRSZ_IN_SIZE_VERT_MASK;
+
+	isp_reg_writel(isp, rgval, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_IN_SIZE);
+}
+
+/*
+ * resizer_set_src_offs - Setup the memory offset for the input lines
+ * @res: Device context.
+ * @offset: Memory offset.
+ *
+ * The 5 LSBs are forced to be zeros by the hardware to align on a 32-byte
+ * boundary; the 5 LSBs are read-only. This field must be programmed to be
+ * 0x0 if the resizer input is from preview engine/CCDC.
+ */
+static void resizer_set_input_offset(struct isp_res_device *res, u32 offset)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	isp_reg_writel(isp, offset, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INOFF);
+}
+
+/*
+ * resizer_set_intype - Input type select
+ * @res: Device context.
+ * @type: Pixel format type.
+ */
+static void resizer_set_intype(struct isp_res_device *res,
+			       enum resizer_colors_type type)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	if (type == RSZ_COLOR8)
+		isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_INPTYP);
+	else
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_CNT,
+			    ISPRSZ_CNT_INPTYP);
+}
+
+/*
+ * __resizer_set_inaddr - Helper function for set input address
+ * @res : pointer to resizer private data structure
+ * @addr: input address
+ * return none
+ */
+static void __resizer_set_inaddr(struct isp_res_device *res, u32 addr)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	isp_reg_writel(isp, addr, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_INADD);
+}
+
+/*
+ * The data rate at the horizontal resizer output must not exceed half the
+ * functional clock or 100 MP/s, whichever is lower. According to the TRM
+ * there's no similar requirement for the vertical resizer output. However
+ * experience showed that vertical upscaling by 4 leads to SBL overflows (with
+ * data rates at the resizer output exceeding 300 MP/s). Limiting the resizer
+ * output data rate to the functional clock or 200 MP/s, whichever is lower,
+ * seems to get rid of SBL overflows.
+ *
+ * The maximum data rate at the output of the horizontal resizer can thus be
+ * computed with
+ *
+ * max intermediate rate <= L3 clock * input height / output height
+ * max intermediate rate <= L3 clock / 2
+ *
+ * The maximum data rate at the resizer input is then
+ *
+ * max input rate <= max intermediate rate * input width / output width
+ *
+ * where the input width and height are the resizer input crop rectangle size.
+ * The TRM doesn't clearly explain if that's a maximum instant data rate or a
+ * maximum average data rate.
+ */
+void omap3isp_resizer_max_rate(struct isp_res_device *res,
+			       unsigned int *max_rate)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
+	const struct v4l2_mbus_framefmt *ofmt = &res->formats[RESZ_PAD_SOURCE];
+	unsigned long limit = min(pipe->l3_ick, 200000000UL);
+	unsigned long clock;
+
+	clock = div_u64((u64)limit * res->crop.active.height, ofmt->height);
+	clock = min(clock, limit / 2);
+	*max_rate = div_u64((u64)clock * res->crop.active.width, ofmt->width);
+}
+
+/*
+ * When the resizer processes images from memory, the driver must slow down read
+ * requests on the input to at least comply with the internal data rate
+ * requirements. If the application real-time requirements can cope with slower
+ * processing, the resizer can be slowed down even more to put less pressure on
+ * the overall system.
+ *
+ * When the resizer processes images on the fly (either from the CCDC or the
+ * preview module), the same data rate requirements apply but they can't be
+ * enforced at the resizer level. The image input module (sensor, CCP2 or
+ * preview module) must not provide image data faster than the resizer can
+ * process.
+ *
+ * For live image pipelines, the data rate is set by the frame format, size and
+ * rate. The sensor output frame rate must not exceed the maximum resizer data
+ * rate.
+ *
+ * The resizer slows down read requests by inserting wait cycles in the SBL
+ * requests. The maximum number of 256-byte requests per second can be computed
+ * as (the data rate is multiplied by 2 to convert from pixels per second to
+ * bytes per second)
+ *
+ * request per second = data rate * 2 / 256
+ * cycles per request = cycles per second / requests per second
+ *
+ * The number of cycles per second is controlled by the L3 clock, leading to
+ *
+ * cycles per request = L3 frequency / 2 * 256 / data rate
+ */
+static void resizer_adjust_bandwidth(struct isp_res_device *res)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
+	struct isp_device *isp = to_isp_device(res);
+	unsigned long l3_ick = pipe->l3_ick;
+	struct v4l2_fract *timeperframe;
+	unsigned int cycles_per_frame;
+	unsigned int requests_per_frame;
+	unsigned int cycles_per_request;
+	unsigned int granularity;
+	unsigned int minimum;
+	unsigned int maximum;
+	unsigned int value;
+
+	if (res->input != RESIZER_INPUT_MEMORY) {
+		isp_reg_clr(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
+			    ISPSBL_SDR_REQ_RSZ_EXP_MASK);
+		return;
+	}
+
+	switch (isp->revision) {
+	case ISP_REVISION_1_0:
+	case ISP_REVISION_2_0:
+	default:
+		granularity = 1024;
+		break;
+
+	case ISP_REVISION_15_0:
+		granularity = 32;
+		break;
+	}
+
+	/* Compute the minimum number of cycles per request, based on the
+	 * pipeline maximum data rate. This is an absolute lower bound if we
+	 * don't want SBL overflows, so round the value up.
+	 */
+	cycles_per_request = div_u64((u64)l3_ick / 2 * 256 + pipe->max_rate - 1,
+				     pipe->max_rate);
+	minimum = DIV_ROUND_UP(cycles_per_request, granularity);
+
+	/* Compute the maximum number of cycles per request, based on the
+	 * requested frame rate. This is a soft upper bound to achieve a frame
+	 * rate equal or higher than the requested value, so round the value
+	 * down.
+	 */
+	timeperframe = &pipe->max_timeperframe;
+
+	requests_per_frame = DIV_ROUND_UP(res->crop.active.width * 2, 256)
+			   * res->crop.active.height;
+	cycles_per_frame = div_u64((u64)l3_ick * timeperframe->numerator,
+				   timeperframe->denominator);
+	cycles_per_request = cycles_per_frame / requests_per_frame;
+
+	maximum = cycles_per_request / granularity;
+
+	value = max(minimum, maximum);
+
+	dev_dbg(isp->dev, "%s: cycles per request = %u\n", __func__, value);
+	isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_SBL, ISPSBL_SDR_REQ_EXP,
+			ISPSBL_SDR_REQ_RSZ_EXP_MASK,
+			value << ISPSBL_SDR_REQ_RSZ_EXP_SHIFT);
+}
+
+/*
+ * omap3isp_resizer_busy - Checks if ISP resizer is busy.
+ *
+ * Returns busy field from ISPRSZ_PCR register.
+ */
+int omap3isp_resizer_busy(struct isp_res_device *res)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	return isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR) &
+			     ISPRSZ_PCR_BUSY;
+}
+
+/*
+ * resizer_set_inaddr - Sets the memory address of the input frame.
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ */
+static void resizer_set_inaddr(struct isp_res_device *res, u32 addr)
+{
+	res->addr_base = addr;
+
+	/* This will handle crop settings in stream off state */
+	if (res->crop_offset)
+		addr += res->crop_offset & ~0x1f;
+
+	__resizer_set_inaddr(res, addr);
+}
+
+/*
+ * Configures the memory address to which the output frame is written.
+ * @addr: 32bit memory address aligned on 32byte boundary.
+ * Note: For SBL efficiency reasons the address should be on a 256-byte
+ * boundary.
+ */
+static void resizer_set_outaddr(struct isp_res_device *res, u32 addr)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	/*
+	 * Set output address. This needs to be in its own function
+	 * because it changes often.
+	 */
+	isp_reg_writel(isp, addr << ISPRSZ_SDR_OUTADD_ADDR_SHIFT,
+		       OMAP3_ISP_IOMEM_RESZ, ISPRSZ_SDR_OUTADD);
+}
+
+/*
+ * resizer_print_status - Prints the values of the resizer module registers.
+ */
+#define RSZ_PRINT_REGISTER(isp, name)\
+	dev_dbg(isp->dev, "###RSZ " #name "=0x%08x\n", \
+		isp_reg_readl(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_##name))
+
+static void resizer_print_status(struct isp_res_device *res)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	dev_dbg(isp->dev, "-------------Resizer Register dump----------\n");
+
+	RSZ_PRINT_REGISTER(isp, PCR);
+	RSZ_PRINT_REGISTER(isp, CNT);
+	RSZ_PRINT_REGISTER(isp, OUT_SIZE);
+	RSZ_PRINT_REGISTER(isp, IN_START);
+	RSZ_PRINT_REGISTER(isp, IN_SIZE);
+	RSZ_PRINT_REGISTER(isp, SDR_INADD);
+	RSZ_PRINT_REGISTER(isp, SDR_INOFF);
+	RSZ_PRINT_REGISTER(isp, SDR_OUTADD);
+	RSZ_PRINT_REGISTER(isp, SDR_OUTOFF);
+	RSZ_PRINT_REGISTER(isp, YENH);
+
+	dev_dbg(isp->dev, "--------------------------------------------\n");
+}
+
+/*
+ * resizer_calc_ratios - Helper function for calculate resizer ratios
+ * @res: pointer to resizer private data structure
+ * @input: input frame size
+ * @output: output frame size
+ * @ratio : return calculated ratios
+ * return none
+ *
+ * The resizer uses a polyphase sample rate converter. The upsampling filter
+ * has a fixed number of phases that depend on the resizing ratio. As the ratio
+ * computation depends on the number of phases, we need to compute a first
+ * approximation and then refine it.
+ *
+ * The input/output/ratio relationship is given by the OMAP34xx TRM:
+ *
+ * - 8-phase, 4-tap mode (RSZ = 64 ~ 512)
+ *	iw = (32 * sph + (ow - 1) * hrsz + 16) >> 8 + 7
+ *	ih = (32 * spv + (oh - 1) * vrsz + 16) >> 8 + 4
+ * - 4-phase, 7-tap mode (RSZ = 513 ~ 1024)
+ *	iw = (64 * sph + (ow - 1) * hrsz + 32) >> 8 + 7
+ *	ih = (64 * spv + (oh - 1) * vrsz + 32) >> 8 + 7
+ *
+ * iw and ih are the input width and height after cropping. Those equations need
+ * to be satisfied exactly for the resizer to work correctly.
+ *
+ * The equations can't be easily reverted, as the >> 8 operation is not linear.
+ * In addition, not all input sizes can be achieved for a given output size. To
+ * get the highest input size lower than or equal to the requested input size,
+ * we need to compute the highest resizing ratio that satisfies the following
+ * inequality (taking the 4-tap mode width equation as an example)
+ *
+ *	iw >= (32 * sph + (ow - 1) * hrsz + 16) >> 8 - 7
+ *
+ * (where iw is the requested input width) which can be rewritten as
+ *
+ *	  iw - 7            >= (32 * sph + (ow - 1) * hrsz + 16) >> 8
+ *	 (iw - 7) << 8      >=  32 * sph + (ow - 1) * hrsz + 16 - b
+ *	((iw - 7) << 8) + b >=  32 * sph + (ow - 1) * hrsz + 16
+ *
+ * where b is the value of the 8 least significant bits of the right hand side
+ * expression of the last inequality. The highest resizing ratio value will be
+ * achieved when b is equal to its maximum value of 255. That resizing ratio
+ * value will still satisfy the original inequality, as b will disappear when
+ * the expression will be shifted right by 8.
+ *
+ * The reverted the equations thus become
+ *
+ * - 8-phase, 4-tap mode
+ *	hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
+ *	vrsz = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / (oh - 1)
+ * - 4-phase, 7-tap mode
+ *	hrsz = ((iw - 7) * 256 + 255 - 32 - 64 * sph) / (ow - 1)
+ *	vrsz = ((ih - 7) * 256 + 255 - 32 - 64 * spv) / (oh - 1)
+ *
+ * The ratios are integer values, and are rounded down to ensure that the
+ * cropped input size is not bigger than the uncropped input size.
+ *
+ * As the number of phases/taps, used to select the correct equations to compute
+ * the ratio, depends on the ratio, we start with the 4-tap mode equations to
+ * compute an approximation of the ratio, and switch to the 7-tap mode equations
+ * if the approximation is higher than the ratio threshold.
+ *
+ * As the 7-tap mode equations will return a ratio smaller than or equal to the
+ * 4-tap mode equations, the resulting ratio could become lower than or equal to
+ * the ratio threshold. This 'equations loop' isn't an issue as long as the
+ * correct equations are used to compute the final input size. Starting with the
+ * 4-tap mode equations ensure that, in case of values resulting in a 'ratio
+ * loop', the smallest of the ratio values will be used, never exceeding the
+ * requested input size.
+ *
+ * We first clamp the output size according to the hardware capabilitie to avoid
+ * auto-cropping the input more than required to satisfy the TRM equations. The
+ * minimum output size is achieved with a scaling factor of 1024. It is thus
+ * computed using the 7-tap equations.
+ *
+ *	min ow = ((iw - 7) * 256 - 32 - 64 * sph) / 1024 + 1
+ *	min oh = ((ih - 7) * 256 - 32 - 64 * spv) / 1024 + 1
+ *
+ * Similarly, the maximum output size is achieved with a scaling factor of 64
+ * and computed using the 4-tap equations.
+ *
+ *	max ow = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / 64 + 1
+ *	max oh = ((ih - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1
+ *
+ * The additional +255 term compensates for the round down operation performed
+ * by the TRM equations when shifting the value right by 8 bits.
+ *
+ * We then compute and clamp the ratios (x1/4 ~ x4). Clamping the output size to
+ * the maximum value guarantees that the ratio value will never be smaller than
+ * the minimum, but it could still slightly exceed the maximum. Clamping the
+ * ratio will thus result in a resizing factor slightly larger than the
+ * requested value.
+ *
+ * To accommodate that, and make sure the TRM equations are satisfied exactly, we
+ * compute the input crop rectangle as the last step.
+ *
+ * As if the situation wasn't complex enough, the maximum output width depends
+ * on the vertical resizing ratio.  Fortunately, the output height doesn't
+ * depend on the horizontal resizing ratio. We can then start by computing the
+ * output height and the vertical ratio, and then move to computing the output
+ * width and the horizontal ratio.
+ */
+static void resizer_calc_ratios(struct isp_res_device *res,
+				struct v4l2_rect *input,
+				struct v4l2_mbus_framefmt *output,
+				struct resizer_ratio *ratio)
+{
+	struct isp_device *isp = to_isp_device(res);
+	const unsigned int spv = DEFAULT_PHASE;
+	const unsigned int sph = DEFAULT_PHASE;
+	unsigned int upscaled_width;
+	unsigned int upscaled_height;
+	unsigned int min_width;
+	unsigned int min_height;
+	unsigned int max_width;
+	unsigned int max_height;
+	unsigned int width_alignment;
+	unsigned int width;
+	unsigned int height;
+
+	/*
+	 * Clamp the output height based on the hardware capabilities and
+	 * compute the vertical resizing ratio.
+	 */
+	min_height = ((input->height - 7) * 256 - 32 - 64 * spv) / 1024 + 1;
+	min_height = max_t(unsigned int, min_height, MIN_OUT_HEIGHT);
+	max_height = ((input->height - 4) * 256 + 255 - 16 - 32 * spv) / 64 + 1;
+	max_height = min_t(unsigned int, max_height, MAX_OUT_HEIGHT);
+	output->height = clamp(output->height, min_height, max_height);
+
+	ratio->vert = ((input->height - 4) * 256 + 255 - 16 - 32 * spv)
+		    / (output->height - 1);
+	if (ratio->vert > MID_RESIZE_VALUE)
+		ratio->vert = ((input->height - 7) * 256 + 255 - 32 - 64 * spv)
+			    / (output->height - 1);
+	ratio->vert = clamp_t(unsigned int, ratio->vert,
+			      MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
+
+	if (ratio->vert <= MID_RESIZE_VALUE) {
+		upscaled_height = (output->height - 1) * ratio->vert
+				+ 32 * spv + 16;
+		height = (upscaled_height >> 8) + 4;
+	} else {
+		upscaled_height = (output->height - 1) * ratio->vert
+				+ 64 * spv + 32;
+		height = (upscaled_height >> 8) + 7;
+	}
+
+	/*
+	 * Compute the minimum and maximum output widths based on the hardware
+	 * capabilities. The maximum depends on the vertical resizing ratio.
+	 */
+	min_width = ((input->width - 7) * 256 - 32 - 64 * sph) / 1024 + 1;
+	min_width = max_t(unsigned int, min_width, MIN_OUT_WIDTH);
+
+	if (ratio->vert <= MID_RESIZE_VALUE) {
+		switch (isp->revision) {
+		case ISP_REVISION_1_0:
+			max_width = MAX_4TAP_OUT_WIDTH_ES1;
+			break;
+
+		case ISP_REVISION_2_0:
+		default:
+			max_width = MAX_4TAP_OUT_WIDTH_ES2;
+			break;
+
+		case ISP_REVISION_15_0:
+			max_width = MAX_4TAP_OUT_WIDTH_3630;
+			break;
+		}
+	} else {
+		switch (isp->revision) {
+		case ISP_REVISION_1_0:
+			max_width = MAX_7TAP_OUT_WIDTH_ES1;
+			break;
+
+		case ISP_REVISION_2_0:
+		default:
+			max_width = MAX_7TAP_OUT_WIDTH_ES2;
+			break;
+
+		case ISP_REVISION_15_0:
+			max_width = MAX_7TAP_OUT_WIDTH_3630;
+			break;
+		}
+	}
+	max_width = min(((input->width - 7) * 256 + 255 - 16 - 32 * sph) / 64
+			+ 1, max_width);
+
+	/*
+	 * The output width must be even, and must be a multiple of 16 bytes
+	 * when upscaling vertically. Clamp the output width to the valid range.
+	 * Take the alignment into account (the maximum width in 7-tap mode on
+	 * ES2 isn't a multiple of 8) and align the result up to make sure it
+	 * won't be smaller than the minimum.
+	 */
+	width_alignment = ratio->vert < 256 ? 8 : 2;
+	output->width = clamp(output->width, min_width,
+			      max_width & ~(width_alignment - 1));
+	output->width = ALIGN(output->width, width_alignment);
+
+	ratio->horz = ((input->width - 7) * 256 + 255 - 16 - 32 * sph)
+		    / (output->width - 1);
+	if (ratio->horz > MID_RESIZE_VALUE)
+		ratio->horz = ((input->width - 7) * 256 + 255 - 32 - 64 * sph)
+			    / (output->width - 1);
+	ratio->horz = clamp_t(unsigned int, ratio->horz,
+			      MIN_RESIZE_VALUE, MAX_RESIZE_VALUE);
+
+	if (ratio->horz <= MID_RESIZE_VALUE) {
+		upscaled_width = (output->width - 1) * ratio->horz
+			       + 32 * sph + 16;
+		width = (upscaled_width >> 8) + 7;
+	} else {
+		upscaled_width = (output->width - 1) * ratio->horz
+			       + 64 * sph + 32;
+		width = (upscaled_width >> 8) + 7;
+	}
+
+	/* Center the new crop rectangle. */
+	input->left += (input->width - width) / 2;
+	input->top += (input->height - height) / 2;
+	input->width = width;
+	input->height = height;
+}
+
+/*
+ * resizer_set_crop_params - Setup hardware with cropping parameters
+ * @res : resizer private structure
+ * @crop_rect : current crop rectangle
+ * @ratio : resizer ratios
+ * return none
+ */
+static void resizer_set_crop_params(struct isp_res_device *res,
+				    const struct v4l2_mbus_framefmt *input,
+				    const struct v4l2_mbus_framefmt *output)
+{
+	resizer_set_ratio(res, &res->ratio);
+
+	/* Set chrominance horizontal algorithm */
+	if (res->ratio.horz >= RESIZE_DIVISOR)
+		resizer_set_bilinear(res, RSZ_THE_SAME);
+	else
+		resizer_set_bilinear(res, RSZ_BILINEAR);
+
+	resizer_adjust_bandwidth(res);
+
+	if (res->input == RESIZER_INPUT_MEMORY) {
+		/* Calculate additional offset for crop */
+		res->crop_offset = (res->crop.active.top * input->width +
+				    res->crop.active.left) * 2;
+		/*
+		 * Write lowest 4 bits of horizontal pixel offset (in pixels),
+		 * vertical start must be 0.
+		 */
+		resizer_set_start(res, (res->crop_offset / 2) & 0xf, 0);
+
+		/*
+		 * Set start (read) address for cropping, in bytes.
+		 * Lowest 5 bits must be zero.
+		 */
+		__resizer_set_inaddr(res,
+				res->addr_base + (res->crop_offset & ~0x1f));
+	} else {
+		/*
+		 * Set vertical start line and horizontal starting pixel.
+		 * If the input is from CCDC/PREV, horizontal start field is
+		 * in bytes (twice number of pixels).
+		 */
+		resizer_set_start(res, res->crop.active.left * 2,
+				  res->crop.active.top);
+		/* Input address and offset must be 0 for preview/ccdc input */
+		__resizer_set_inaddr(res, 0);
+		resizer_set_input_offset(res, 0);
+	}
+
+	/* Set the input size */
+	resizer_set_input_size(res, res->crop.active.width,
+			       res->crop.active.height);
+}
+
+static void resizer_configure(struct isp_res_device *res)
+{
+	struct v4l2_mbus_framefmt *informat, *outformat;
+	struct resizer_luma_yenh luma = {0, 0, 0, 0};
+
+	resizer_set_source(res, res->input);
+
+	informat = &res->formats[RESZ_PAD_SINK];
+	outformat = &res->formats[RESZ_PAD_SOURCE];
+
+	/* RESZ_PAD_SINK */
+	if (res->input == RESIZER_INPUT_VP)
+		resizer_set_input_offset(res, 0);
+	else
+		resizer_set_input_offset(res, ALIGN(informat->width, 0x10) * 2);
+
+	/* YUV422 interleaved, default phase, no luma enhancement */
+	resizer_set_intype(res, RSZ_YUV422);
+	resizer_set_ycpos(res, informat->code);
+	resizer_set_phase(res, DEFAULT_PHASE, DEFAULT_PHASE);
+	resizer_set_luma(res, &luma);
+
+	/* RESZ_PAD_SOURCE */
+	resizer_set_output_offset(res, ALIGN(outformat->width * 2, 32));
+	resizer_set_output_size(res, outformat->width, outformat->height);
+
+	resizer_set_crop_params(res, informat, outformat);
+}
+
+/* -----------------------------------------------------------------------------
+ * Interrupt handling
+ */
+
+static void resizer_enable_oneshot(struct isp_res_device *res)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	isp_reg_set(isp, OMAP3_ISP_IOMEM_RESZ, ISPRSZ_PCR,
+		    ISPRSZ_PCR_ENABLE | ISPRSZ_PCR_ONESHOT);
+}
+
+void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res)
+{
+	/*
+	 * If ISP_VIDEO_DMAQUEUE_QUEUED is set, DMA queue had an underrun
+	 * condition, the module was paused and now we have a buffer queued
+	 * on the output again. Restart the pipeline if running in continuous
+	 * mode.
+	 */
+	if (res->state == ISP_PIPELINE_STREAM_CONTINUOUS &&
+	    res->video_out.dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
+		resizer_enable_oneshot(res);
+		isp_video_dmaqueue_flags_clr(&res->video_out);
+	}
+}
+
+static void resizer_isr_buffer(struct isp_res_device *res)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&res->subdev.entity);
+	struct isp_buffer *buffer;
+	int restart = 0;
+
+	if (res->state == ISP_PIPELINE_STREAM_STOPPED)
+		return;
+
+	/* Complete the output buffer and, if reading from memory, the input
+	 * buffer.
+	 */
+	buffer = omap3isp_video_buffer_next(&res->video_out, res->error);
+	if (buffer != NULL) {
+		resizer_set_outaddr(res, buffer->isp_addr);
+		restart = 1;
+	}
+
+	pipe->state |= ISP_PIPELINE_IDLE_OUTPUT;
+
+	if (res->input == RESIZER_INPUT_MEMORY) {
+		buffer = omap3isp_video_buffer_next(&res->video_in, 0);
+		if (buffer != NULL)
+			resizer_set_inaddr(res, buffer->isp_addr);
+		pipe->state |= ISP_PIPELINE_IDLE_INPUT;
+	}
+
+	if (res->state == ISP_PIPELINE_STREAM_SINGLESHOT) {
+		if (isp_pipeline_ready(pipe))
+			omap3isp_pipeline_set_stream(pipe,
+						ISP_PIPELINE_STREAM_SINGLESHOT);
+	} else {
+		/* If an underrun occurs, the video queue operation handler will
+		 * restart the resizer. Otherwise restart it immediately.
+		 */
+		if (restart)
+			resizer_enable_oneshot(res);
+	}
+
+	res->error = 0;
+}
+
+/*
+ * omap3isp_resizer_isr - ISP resizer interrupt handler
+ *
+ * Manage the resizer video buffers and configure shadowed and busy-locked
+ * registers.
+ */
+void omap3isp_resizer_isr(struct isp_res_device *res)
+{
+	struct v4l2_mbus_framefmt *informat, *outformat;
+
+	if (omap3isp_module_sync_is_stopping(&res->wait, &res->stopping))
+		return;
+
+	if (res->applycrop) {
+		outformat = __resizer_get_format(res, NULL, RESZ_PAD_SOURCE,
+					      V4L2_SUBDEV_FORMAT_ACTIVE);
+		informat = __resizer_get_format(res, NULL, RESZ_PAD_SINK,
+					      V4L2_SUBDEV_FORMAT_ACTIVE);
+		resizer_set_crop_params(res, informat, outformat);
+		res->applycrop = 0;
+	}
+
+	resizer_isr_buffer(res);
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP video operations
+ */
+
+static int resizer_video_queue(struct isp_video *video,
+			       struct isp_buffer *buffer)
+{
+	struct isp_res_device *res = &video->isp->isp_res;
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		resizer_set_inaddr(res, buffer->isp_addr);
+
+	/*
+	 * We now have a buffer queued on the output. Despite what the
+	 * TRM says, the resizer can't be restarted immediately.
+	 * Enabling it in one shot mode in the middle of a frame (or at
+	 * least asynchronously to the frame) results in the output
+	 * being shifted randomly left/right and up/down, as if the
+	 * hardware didn't synchronize itself to the beginning of the
+	 * frame correctly.
+	 *
+	 * Restart the resizer on the next sync interrupt if running in
+	 * continuous mode or when starting the stream.
+	 */
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		resizer_set_outaddr(res, buffer->isp_addr);
+
+	return 0;
+}
+
+static const struct isp_video_operations resizer_video_ops = {
+	.queue = resizer_video_queue,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 subdev operations
+ */
+
+/*
+ * resizer_set_stream - Enable/Disable streaming on resizer subdev
+ * @sd: ISP resizer V4L2 subdev
+ * @enable: 1 == Enable, 0 == Disable
+ *
+ * The resizer hardware can't be enabled without a memory buffer to write to.
+ * As the s_stream operation is called in response to a STREAMON call without
+ * any buffer queued yet, just update the state field and return immediately.
+ * The resizer will be enabled in resizer_video_queue().
+ */
+static int resizer_set_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct isp_video *video_out = &res->video_out;
+	struct isp_device *isp = to_isp_device(res);
+	struct device *dev = to_device(res);
+
+	if (res->state == ISP_PIPELINE_STREAM_STOPPED) {
+		if (enable == ISP_PIPELINE_STREAM_STOPPED)
+			return 0;
+
+		omap3isp_subclk_enable(isp, OMAP3_ISP_SUBCLK_RESIZER);
+		resizer_configure(res);
+		res->error = 0;
+		resizer_print_status(res);
+	}
+
+	switch (enable) {
+	case ISP_PIPELINE_STREAM_CONTINUOUS:
+		omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
+		if (video_out->dmaqueue_flags & ISP_VIDEO_DMAQUEUE_QUEUED) {
+			resizer_enable_oneshot(res);
+			isp_video_dmaqueue_flags_clr(video_out);
+		}
+		break;
+
+	case ISP_PIPELINE_STREAM_SINGLESHOT:
+		if (res->input == RESIZER_INPUT_MEMORY)
+			omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_READ);
+		omap3isp_sbl_enable(isp, OMAP3_ISP_SBL_RESIZER_WRITE);
+
+		resizer_enable_oneshot(res);
+		break;
+
+	case ISP_PIPELINE_STREAM_STOPPED:
+		if (omap3isp_module_sync_idle(&sd->entity, &res->wait,
+					      &res->stopping))
+			dev_dbg(dev, "%s: module stop timeout.\n", sd->name);
+		omap3isp_sbl_disable(isp, OMAP3_ISP_SBL_RESIZER_READ |
+				OMAP3_ISP_SBL_RESIZER_WRITE);
+		omap3isp_subclk_disable(isp, OMAP3_ISP_SUBCLK_RESIZER);
+		isp_video_dmaqueue_flags_clr(video_out);
+		break;
+	}
+
+	res->state = enable;
+	return 0;
+}
+
+/*
+ * resizer_g_crop - handle get crop subdev operation
+ * @sd : pointer to v4l2 subdev structure
+ * @pad : subdev pad
+ * @crop : pointer to crop structure
+ * @which : active or try format
+ * return zero
+ */
+static int resizer_g_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_crop *crop)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+	struct resizer_ratio ratio;
+
+	/* Only sink pad has crop capability */
+	if (crop->pad != RESZ_PAD_SINK)
+		return -EINVAL;
+
+	format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE, crop->which);
+	crop->rect = *__resizer_get_crop(res, fh, crop->which);
+	resizer_calc_ratios(res, &crop->rect, format, &ratio);
+
+	return 0;
+}
+
+/*
+ * resizer_try_crop - mangles crop parameters.
+ */
+static void resizer_try_crop(const struct v4l2_mbus_framefmt *sink,
+			     const struct v4l2_mbus_framefmt *source,
+			     struct v4l2_rect *crop)
+{
+	const unsigned int spv = DEFAULT_PHASE;
+	const unsigned int sph = DEFAULT_PHASE;
+
+	/* Crop rectangle is constrained to the output size so that zoom ratio
+	 * cannot exceed +/-4.0.
+	 */
+	unsigned int min_width =
+		((32 * sph + (source->width - 1) * 64 + 16) >> 8) + 7;
+	unsigned int min_height =
+		((32 * spv + (source->height - 1) * 64 + 16) >> 8) + 4;
+	unsigned int max_width =
+		((64 * sph + (source->width - 1) * 1024 + 32) >> 8) + 7;
+	unsigned int max_height =
+		((64 * spv + (source->height - 1) * 1024 + 32) >> 8) + 7;
+
+	crop->width = clamp_t(u32, crop->width, min_width, max_width);
+	crop->height = clamp_t(u32, crop->height, min_height, max_height);
+
+	/* Crop can not go beyond of the input rectangle */
+	crop->left = clamp_t(u32, crop->left, 0, sink->width - MIN_IN_WIDTH);
+	crop->width = clamp_t(u32, crop->width, MIN_IN_WIDTH,
+			      sink->width - crop->left);
+	crop->top = clamp_t(u32, crop->top, 0, sink->height - MIN_IN_HEIGHT);
+	crop->height = clamp_t(u32, crop->height, MIN_IN_HEIGHT,
+			       sink->height - crop->top);
+}
+
+/*
+ * resizer_s_crop - handle set crop subdev operation
+ * @sd : pointer to v4l2 subdev structure
+ * @pad : subdev pad
+ * @crop : pointer to crop structure
+ * @which : active or try format
+ * return -EINVAL or zero when succeed
+ */
+static int resizer_s_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			  struct v4l2_subdev_crop *crop)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct isp_device *isp = to_isp_device(res);
+	struct v4l2_mbus_framefmt *format_sink, *format_source;
+	struct resizer_ratio ratio;
+
+	/* Only sink pad has crop capability */
+	if (crop->pad != RESZ_PAD_SINK)
+		return -EINVAL;
+
+	format_sink = __resizer_get_format(res, fh, RESZ_PAD_SINK,
+					   crop->which);
+	format_source = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
+					     crop->which);
+
+	dev_dbg(isp->dev, "%s: L=%d,T=%d,W=%d,H=%d,which=%d\n", __func__,
+		crop->rect.left, crop->rect.top, crop->rect.width,
+		crop->rect.height, crop->which);
+
+	dev_dbg(isp->dev, "%s: input=%dx%d, output=%dx%d\n", __func__,
+		format_sink->width, format_sink->height,
+		format_source->width, format_source->height);
+
+	resizer_try_crop(format_sink, format_source, &crop->rect);
+	*__resizer_get_crop(res, fh, crop->which) = crop->rect;
+	resizer_calc_ratios(res, &crop->rect, format_source, &ratio);
+
+	if (crop->which == V4L2_SUBDEV_FORMAT_TRY)
+		return 0;
+
+	res->ratio = ratio;
+	res->crop.active = crop->rect;
+
+	/*
+	 * s_crop can be called while streaming is on. In this case
+	 * the crop values will be set in the next IRQ.
+	 */
+	if (res->state != ISP_PIPELINE_STREAM_STOPPED)
+		res->applycrop = 1;
+
+	return 0;
+}
+
+/* resizer pixel formats */
+static const unsigned int resizer_formats[] = {
+	V4L2_MBUS_FMT_UYVY8_1X16,
+	V4L2_MBUS_FMT_YUYV8_1X16,
+};
+
+static unsigned int resizer_max_in_width(struct isp_res_device *res)
+{
+	struct isp_device *isp = to_isp_device(res);
+
+	if (res->input == RESIZER_INPUT_MEMORY) {
+		return MAX_IN_WIDTH_MEMORY_MODE;
+	} else {
+		if (isp->revision == ISP_REVISION_1_0)
+			return MAX_IN_WIDTH_ONTHEFLY_MODE_ES1;
+		else
+			return MAX_IN_WIDTH_ONTHEFLY_MODE_ES2;
+	}
+}
+
+/*
+ * resizer_try_format - Handle try format by pad subdev method
+ * @res   : ISP resizer device
+ * @fh    : V4L2 subdev file handle
+ * @pad   : pad num
+ * @fmt   : pointer to v4l2 format structure
+ * @which : wanted subdev format
+ */
+static void resizer_try_format(struct isp_res_device *res,
+			       struct v4l2_subdev_fh *fh, unsigned int pad,
+			       struct v4l2_mbus_framefmt *fmt,
+			       enum v4l2_subdev_format_whence which)
+{
+	struct v4l2_mbus_framefmt *format;
+	struct resizer_ratio ratio;
+	struct v4l2_rect crop;
+
+	switch (pad) {
+	case RESZ_PAD_SINK:
+		if (fmt->code != V4L2_MBUS_FMT_YUYV8_1X16 &&
+		    fmt->code != V4L2_MBUS_FMT_UYVY8_1X16)
+			fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+
+		fmt->width = clamp_t(u32, fmt->width, MIN_IN_WIDTH,
+				     resizer_max_in_width(res));
+		fmt->height = clamp_t(u32, fmt->height, MIN_IN_HEIGHT,
+				      MAX_IN_HEIGHT);
+		break;
+
+	case RESZ_PAD_SOURCE:
+		format = __resizer_get_format(res, fh, RESZ_PAD_SINK, which);
+		fmt->code = format->code;
+
+		crop = *__resizer_get_crop(res, fh, which);
+		resizer_calc_ratios(res, &crop, fmt, &ratio);
+		break;
+	}
+
+	fmt->colorspace = V4L2_COLORSPACE_JPEG;
+	fmt->field = V4L2_FIELD_NONE;
+}
+
+/*
+ * resizer_enum_mbus_code - Handle pixel format enumeration
+ * @sd     : pointer to v4l2 subdev structure
+ * @fh     : V4L2 subdev file handle
+ * @code   : pointer to v4l2_subdev_mbus_code_enum structure
+ * return -EINVAL or zero on success
+ */
+static int resizer_enum_mbus_code(struct v4l2_subdev *sd,
+				  struct v4l2_subdev_fh *fh,
+				  struct v4l2_subdev_mbus_code_enum *code)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	if (code->pad == RESZ_PAD_SINK) {
+		if (code->index >= ARRAY_SIZE(resizer_formats))
+			return -EINVAL;
+
+		code->code = resizer_formats[code->index];
+	} else {
+		if (code->index != 0)
+			return -EINVAL;
+
+		format = __resizer_get_format(res, fh, RESZ_PAD_SINK,
+					      V4L2_SUBDEV_FORMAT_TRY);
+		code->code = format->code;
+	}
+
+	return 0;
+}
+
+static int resizer_enum_frame_size(struct v4l2_subdev *sd,
+				   struct v4l2_subdev_fh *fh,
+				   struct v4l2_subdev_frame_size_enum *fse)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt format;
+
+	if (fse->index != 0)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = 1;
+	format.height = 1;
+	resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->min_width = format.width;
+	fse->min_height = format.height;
+
+	if (format.code != fse->code)
+		return -EINVAL;
+
+	format.code = fse->code;
+	format.width = -1;
+	format.height = -1;
+	resizer_try_format(res, fh, fse->pad, &format, V4L2_SUBDEV_FORMAT_TRY);
+	fse->max_width = format.width;
+	fse->max_height = format.height;
+
+	return 0;
+}
+
+/*
+ * resizer_get_format - Handle get format by pads subdev method
+ * @sd    : pointer to v4l2 subdev structure
+ * @fh    : V4L2 subdev file handle
+ * @fmt   : pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int resizer_get_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+
+	format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	fmt->format = *format;
+	return 0;
+}
+
+/*
+ * resizer_set_format - Handle set format by pads subdev method
+ * @sd    : pointer to v4l2 subdev structure
+ * @fh    : V4L2 subdev file handle
+ * @fmt   : pointer to v4l2 subdev format structure
+ * return -EINVAL or zero on success
+ */
+static int resizer_set_format(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+			      struct v4l2_subdev_format *fmt)
+{
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+	struct v4l2_mbus_framefmt *format;
+	struct v4l2_rect *crop;
+
+	format = __resizer_get_format(res, fh, fmt->pad, fmt->which);
+	if (format == NULL)
+		return -EINVAL;
+
+	resizer_try_format(res, fh, fmt->pad, &fmt->format, fmt->which);
+	*format = fmt->format;
+
+	if (fmt->pad == RESZ_PAD_SINK) {
+		/* reset crop rectangle */
+		crop = __resizer_get_crop(res, fh, fmt->which);
+		crop->left = 0;
+		crop->top = 0;
+		crop->width = fmt->format.width;
+		crop->height = fmt->format.height;
+
+		/* Propagate the format from sink to source */
+		format = __resizer_get_format(res, fh, RESZ_PAD_SOURCE,
+					      fmt->which);
+		*format = fmt->format;
+		resizer_try_format(res, fh, RESZ_PAD_SOURCE, format,
+				   fmt->which);
+	}
+
+	if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE) {
+		/* Compute and store the active crop rectangle and resizer
+		 * ratios. format already points to the source pad active
+		 * format.
+		 */
+		res->crop.active = res->crop.request;
+		resizer_calc_ratios(res, &res->crop.active, format,
+				       &res->ratio);
+	}
+
+	return 0;
+}
+
+/*
+ * resizer_init_formats - Initialize formats on all pads
+ * @sd: ISP resizer V4L2 subdevice
+ * @fh: V4L2 subdev file handle
+ *
+ * Initialize all pad formats with default values. If fh is not NULL, try
+ * formats are initialized on the file handle. Otherwise active formats are
+ * initialized on the device.
+ */
+static int resizer_init_formats(struct v4l2_subdev *sd,
+				struct v4l2_subdev_fh *fh)
+{
+	struct v4l2_subdev_format format;
+
+	memset(&format, 0, sizeof(format));
+	format.pad = RESZ_PAD_SINK;
+	format.which = fh ? V4L2_SUBDEV_FORMAT_TRY : V4L2_SUBDEV_FORMAT_ACTIVE;
+	format.format.code = V4L2_MBUS_FMT_YUYV8_1X16;
+	format.format.width = 4096;
+	format.format.height = 4096;
+	resizer_set_format(sd, fh, &format);
+
+	return 0;
+}
+
+/* subdev video operations */
+static const struct v4l2_subdev_video_ops resizer_v4l2_video_ops = {
+	.s_stream = resizer_set_stream,
+};
+
+/* subdev pad operations */
+static const struct v4l2_subdev_pad_ops resizer_v4l2_pad_ops = {
+	.enum_mbus_code = resizer_enum_mbus_code,
+	.enum_frame_size = resizer_enum_frame_size,
+	.get_fmt = resizer_get_format,
+	.set_fmt = resizer_set_format,
+	.get_crop = resizer_g_crop,
+	.set_crop = resizer_s_crop,
+};
+
+/* subdev operations */
+static const struct v4l2_subdev_ops resizer_v4l2_ops = {
+	.video = &resizer_v4l2_video_ops,
+	.pad = &resizer_v4l2_pad_ops,
+};
+
+/* subdev internal operations */
+static const struct v4l2_subdev_internal_ops resizer_v4l2_internal_ops = {
+	.open = resizer_init_formats,
+};
+
+/* -----------------------------------------------------------------------------
+ * Media entity operations
+ */
+
+/*
+ * resizer_link_setup - Setup resizer connections.
+ * @entity : Pointer to media entity structure
+ * @local  : Pointer to local pad array
+ * @remote : Pointer to remote pad array
+ * @flags  : Link flags
+ * return -EINVAL or zero on success
+ */
+static int resizer_link_setup(struct media_entity *entity,
+			      const struct media_pad *local,
+			      const struct media_pad *remote, u32 flags)
+{
+	struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
+	struct isp_res_device *res = v4l2_get_subdevdata(sd);
+
+	switch (local->index | media_entity_type(remote->entity)) {
+	case RESZ_PAD_SINK | MEDIA_ENT_T_DEVNODE:
+		/* read from memory */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (res->input == RESIZER_INPUT_VP)
+				return -EBUSY;
+			res->input = RESIZER_INPUT_MEMORY;
+		} else {
+			if (res->input == RESIZER_INPUT_MEMORY)
+				res->input = RESIZER_INPUT_NONE;
+		}
+		break;
+
+	case RESZ_PAD_SINK | MEDIA_ENT_T_V4L2_SUBDEV:
+		/* read from ccdc or previewer */
+		if (flags & MEDIA_LNK_FL_ENABLED) {
+			if (res->input == RESIZER_INPUT_MEMORY)
+				return -EBUSY;
+			res->input = RESIZER_INPUT_VP;
+		} else {
+			if (res->input == RESIZER_INPUT_VP)
+				res->input = RESIZER_INPUT_NONE;
+		}
+		break;
+
+	case RESZ_PAD_SOURCE | MEDIA_ENT_T_DEVNODE:
+		/* resizer always write to memory */
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* media operations */
+static const struct media_entity_operations resizer_media_ops = {
+	.link_setup = resizer_link_setup,
+};
+
+/*
+ * resizer_init_entities - Initialize resizer subdev and media entity.
+ * @res : Pointer to resizer device structure
+ * return -ENOMEM or zero on success
+ */
+static int resizer_init_entities(struct isp_res_device *res)
+{
+	struct v4l2_subdev *sd = &res->subdev;
+	struct media_pad *pads = res->pads;
+	struct media_entity *me = &sd->entity;
+	int ret;
+
+	res->input = RESIZER_INPUT_NONE;
+
+	v4l2_subdev_init(sd, &resizer_v4l2_ops);
+	sd->internal_ops = &resizer_v4l2_internal_ops;
+	strlcpy(sd->name, "OMAP3 ISP resizer", sizeof(sd->name));
+	sd->grp_id = 1 << 16;	/* group ID for isp subdevs */
+	v4l2_set_subdevdata(sd, res);
+	sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+	pads[RESZ_PAD_SINK].flags = MEDIA_PAD_FL_SINK;
+	pads[RESZ_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
+
+	me->ops = &resizer_media_ops;
+	ret = media_entity_init(me, RESZ_PADS_NUM, pads, 0);
+	if (ret < 0)
+		return ret;
+
+	resizer_init_formats(sd, NULL);
+
+	res->video_in.type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	res->video_in.ops = &resizer_video_ops;
+	res->video_in.isp = to_isp_device(res);
+	res->video_in.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
+	res->video_in.bpl_alignment = 32;
+	res->video_out.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	res->video_out.ops = &resizer_video_ops;
+	res->video_out.isp = to_isp_device(res);
+	res->video_out.capture_mem = PAGE_ALIGN(4096 * 4096) * 2 * 3;
+	res->video_out.bpl_alignment = 32;
+
+	ret = omap3isp_video_init(&res->video_in, "resizer");
+	if (ret < 0)
+		return ret;
+
+	ret = omap3isp_video_init(&res->video_out, "resizer");
+	if (ret < 0)
+		return ret;
+
+	/* Connect the video nodes to the resizer subdev. */
+	ret = media_entity_create_link(&res->video_in.video.entity, 0,
+			&res->subdev.entity, RESZ_PAD_SINK, 0);
+	if (ret < 0)
+		return ret;
+
+	ret = media_entity_create_link(&res->subdev.entity, RESZ_PAD_SOURCE,
+			&res->video_out.video.entity, 0, 0);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+void omap3isp_resizer_unregister_entities(struct isp_res_device *res)
+{
+	media_entity_cleanup(&res->subdev.entity);
+
+	v4l2_device_unregister_subdev(&res->subdev);
+	omap3isp_video_unregister(&res->video_in);
+	omap3isp_video_unregister(&res->video_out);
+}
+
+int omap3isp_resizer_register_entities(struct isp_res_device *res,
+				       struct v4l2_device *vdev)
+{
+	int ret;
+
+	/* Register the subdev and video nodes. */
+	ret = v4l2_device_register_subdev(vdev, &res->subdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&res->video_in, vdev);
+	if (ret < 0)
+		goto error;
+
+	ret = omap3isp_video_register(&res->video_out, vdev);
+	if (ret < 0)
+		goto error;
+
+	return 0;
+
+error:
+	omap3isp_resizer_unregister_entities(res);
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * ISP resizer initialization and cleanup
+ */
+
+void omap3isp_resizer_cleanup(struct isp_device *isp)
+{
+}
+
+/*
+ * isp_resizer_init - Resizer initialization.
+ * @isp : Pointer to ISP device
+ * return -ENOMEM or zero on success
+ */
+int omap3isp_resizer_init(struct isp_device *isp)
+{
+	struct isp_res_device *res = &isp->isp_res;
+	int ret;
+
+	init_waitqueue_head(&res->wait);
+	atomic_set(&res->stopping, 0);
+	ret = resizer_init_entities(res);
+	if (ret < 0)
+		goto out;
+
+out:
+	if (ret)
+		omap3isp_resizer_cleanup(isp);
+
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispresizer.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispresizer.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispresizer.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispresizer.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,147 @@
+/*
+ * ispresizer.h
+ *
+ * TI OMAP3 ISP - Resizer module
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_RESIZER_H
+#define OMAP3_ISP_RESIZER_H
+
+#include <linux/types.h>
+
+/*
+ * Constants for filter coefficents count
+ */
+#define COEFF_CNT		32
+
+/*
+ * struct isprsz_coef - Structure for resizer filter coeffcients.
+ * @h_filter_coef_4tap: Horizontal filter coefficients for 8-phase/4-tap
+ *			mode (.5x-4x)
+ * @v_filter_coef_4tap: Vertical filter coefficients for 8-phase/4-tap
+ *			mode (.5x-4x)
+ * @h_filter_coef_7tap: Horizontal filter coefficients for 4-phase/7-tap
+ *			mode (.25x-.5x)
+ * @v_filter_coef_7tap: Vertical filter coefficients for 4-phase/7-tap
+ *			mode (.25x-.5x)
+ */
+struct isprsz_coef {
+	u16 h_filter_coef_4tap[32];
+	u16 v_filter_coef_4tap[32];
+	/* Every 8th value is a dummy value in the following arrays: */
+	u16 h_filter_coef_7tap[32];
+	u16 v_filter_coef_7tap[32];
+};
+
+/* Chrominance horizontal algorithm */
+enum resizer_chroma_algo {
+	RSZ_THE_SAME = 0,	/* Chrominance the same as Luminance */
+	RSZ_BILINEAR = 1,	/* Chrominance uses bilinear interpolation */
+};
+
+/* Resizer input type select */
+enum resizer_colors_type {
+	RSZ_YUV422 = 0,		/* YUV422 color is interleaved */
+	RSZ_COLOR8 = 1,		/* Color separate data on 8 bits */
+};
+
+/*
+ * Structure for horizontal and vertical resizing value
+ */
+struct resizer_ratio {
+	u32 horz;
+	u32 vert;
+};
+
+/*
+ * Structure for luminance enhancer parameters.
+ */
+struct resizer_luma_yenh {
+	u8 algo;		/* algorithm select. */
+	u8 gain;		/* maximum gain. */
+	u8 slope;		/* slope. */
+	u8 core;		/* core offset. */
+};
+
+enum resizer_input_entity {
+	RESIZER_INPUT_NONE,
+	RESIZER_INPUT_VP,	/* input video port - prev or ccdc */
+	RESIZER_INPUT_MEMORY,
+};
+
+/* Sink and source resizer pads */
+#define RESZ_PAD_SINK			0
+#define RESZ_PAD_SOURCE			1
+#define RESZ_PADS_NUM			2
+
+/*
+ * struct isp_res_device - OMAP3 ISP resizer module
+ * @crop.request: Crop rectangle requested by the user
+ * @crop.active: Active crop rectangle (based on hardware requirements)
+ */
+struct isp_res_device {
+	struct v4l2_subdev subdev;
+	struct media_pad pads[RESZ_PADS_NUM];
+	struct v4l2_mbus_framefmt formats[RESZ_PADS_NUM];
+
+	enum resizer_input_entity input;
+	struct isp_video video_in;
+	struct isp_video video_out;
+	unsigned int error;
+
+	u32 addr_base;   /* stored source buffer address in memory mode */
+	u32 crop_offset; /* additional offset for crop in memory mode */
+	struct resizer_ratio ratio;
+	int pm_state;
+	unsigned int applycrop:1;
+	enum isp_pipeline_stream_state state;
+	wait_queue_head_t wait;
+	atomic_t stopping;
+
+	struct {
+		struct v4l2_rect request;
+		struct v4l2_rect active;
+	} crop;
+};
+
+struct isp_device;
+
+int omap3isp_resizer_init(struct isp_device *isp);
+void omap3isp_resizer_cleanup(struct isp_device *isp);
+
+int omap3isp_resizer_register_entities(struct isp_res_device *res,
+				       struct v4l2_device *vdev);
+void omap3isp_resizer_unregister_entities(struct isp_res_device *res);
+void omap3isp_resizer_isr_frame_sync(struct isp_res_device *res);
+void omap3isp_resizer_isr(struct isp_res_device *isp_res);
+
+void omap3isp_resizer_max_rate(struct isp_res_device *res,
+			       unsigned int *max_rate);
+
+void omap3isp_resizer_suspend(struct isp_res_device *isp_res);
+
+void omap3isp_resizer_resume(struct isp_res_device *isp_res);
+
+int omap3isp_resizer_busy(struct isp_res_device *isp_res);
+
+#endif	/* OMAP3_ISP_RESIZER_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispstat.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispstat.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispstat.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispstat.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1092 @@
+/*
+ * ispstat.c
+ *
+ * TI OMAP3 ISP - Statistics core
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/dma-mapping.h>
+#include <linux/slab.h>
+#include <linux/uaccess.h>
+
+#include "isp.h"
+
+#define IS_COHERENT_BUF(stat)	((stat)->dma_ch >= 0)
+
+/*
+ * MAGIC_SIZE must always be the greatest common divisor of
+ * AEWB_PACKET_SIZE and AF_PAXEL_SIZE.
+ */
+#define MAGIC_SIZE		16
+#define MAGIC_NUM		0x55
+
+/* HACK: AF module seems to be writing one more paxel data than it should. */
+#define AF_EXTRA_DATA		OMAP3ISP_AF_PAXEL_SIZE
+
+/*
+ * HACK: H3A modules go to an invalid state after have a SBL overflow. It makes
+ * the next buffer to start to be written in the same point where the overflow
+ * occurred instead of the configured address. The only known way to make it to
+ * go back to a valid state is having a valid buffer processing. Of course it
+ * requires at least a doubled buffer size to avoid an access to invalid memory
+ * region. But it does not fix everything. It may happen more than one
+ * consecutive SBL overflows. In that case, it might be unpredictable how many
+ * buffers the allocated memory should fit. For that case, a recover
+ * configuration was created. It produces the minimum buffer size for each H3A
+ * module and decrease the change for more SBL overflows. This recover state
+ * will be enabled every time a SBL overflow occur. As the output buffer size
+ * isn't big, it's possible to have an extra size able to fit many recover
+ * buffers making it extreamily unlikely to have an access to invalid memory
+ * region.
+ */
+#define NUM_H3A_RECOVER_BUFS	10
+
+/*
+ * HACK: Because of HW issues the generic layer sometimes need to have
+ * different behaviour for different statistic modules.
+ */
+#define IS_H3A_AF(stat)		((stat) == &(stat)->isp->isp_af)
+#define IS_H3A_AEWB(stat)	((stat) == &(stat)->isp->isp_aewb)
+#define IS_H3A(stat)		(IS_H3A_AF(stat) || IS_H3A_AEWB(stat))
+
+static void __isp_stat_buf_sync_magic(struct ispstat *stat,
+				      struct ispstat_buffer *buf,
+				      u32 buf_size, enum dma_data_direction dir,
+				      void (*dma_sync)(struct device *,
+					dma_addr_t, unsigned long, size_t,
+					enum dma_data_direction))
+{
+	struct device *dev = stat->isp->dev;
+	struct page *pg;
+	dma_addr_t dma_addr;
+	u32 offset;
+
+	/* Initial magic words */
+	pg = vmalloc_to_page(buf->virt_addr);
+	dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
+	dma_sync(dev, dma_addr, 0, MAGIC_SIZE, dir);
+
+	/* Final magic words */
+	pg = vmalloc_to_page(buf->virt_addr + buf_size);
+	dma_addr = pfn_to_dma(dev, page_to_pfn(pg));
+	offset = ((u32)buf->virt_addr + buf_size) & ~PAGE_MASK;
+	dma_sync(dev, dma_addr, offset, MAGIC_SIZE, dir);
+}
+
+static void isp_stat_buf_sync_magic_for_device(struct ispstat *stat,
+					       struct ispstat_buffer *buf,
+					       u32 buf_size,
+					       enum dma_data_direction dir)
+{
+	if (IS_COHERENT_BUF(stat))
+		return;
+
+	__isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
+				  dma_sync_single_range_for_device);
+}
+
+static void isp_stat_buf_sync_magic_for_cpu(struct ispstat *stat,
+					    struct ispstat_buffer *buf,
+					    u32 buf_size,
+					    enum dma_data_direction dir)
+{
+	if (IS_COHERENT_BUF(stat))
+		return;
+
+	__isp_stat_buf_sync_magic(stat, buf, buf_size, dir,
+				  dma_sync_single_range_for_cpu);
+}
+
+static int isp_stat_buf_check_magic(struct ispstat *stat,
+				    struct ispstat_buffer *buf)
+{
+	const u32 buf_size = IS_H3A_AF(stat) ?
+			     buf->buf_size + AF_EXTRA_DATA : buf->buf_size;
+	u8 *w;
+	u8 *end;
+	int ret = -EINVAL;
+
+	isp_stat_buf_sync_magic_for_cpu(stat, buf, buf_size, DMA_FROM_DEVICE);
+
+	/* Checking initial magic numbers. They shouldn't be here anymore. */
+	for (w = buf->virt_addr, end = w + MAGIC_SIZE; w < end; w++)
+		if (likely(*w != MAGIC_NUM))
+			ret = 0;
+
+	if (ret) {
+		dev_dbg(stat->isp->dev, "%s: beginning magic check does not "
+					"match.\n", stat->subdev.name);
+		return ret;
+	}
+
+	/* Checking magic numbers at the end. They must be still here. */
+	for (w = buf->virt_addr + buf_size, end = w + MAGIC_SIZE;
+	     w < end; w++) {
+		if (unlikely(*w != MAGIC_NUM)) {
+			dev_dbg(stat->isp->dev, "%s: endding magic check does "
+				"not match.\n", stat->subdev.name);
+			return -EINVAL;
+		}
+	}
+
+	isp_stat_buf_sync_magic_for_device(stat, buf, buf_size,
+					   DMA_FROM_DEVICE);
+
+	return 0;
+}
+
+static void isp_stat_buf_insert_magic(struct ispstat *stat,
+				      struct ispstat_buffer *buf)
+{
+	const u32 buf_size = IS_H3A_AF(stat) ?
+			     stat->buf_size + AF_EXTRA_DATA : stat->buf_size;
+
+	isp_stat_buf_sync_magic_for_cpu(stat, buf, buf_size, DMA_FROM_DEVICE);
+
+	/*
+	 * Inserting MAGIC_NUM at the beginning and end of the buffer.
+	 * buf->buf_size is set only after the buffer is queued. For now the
+	 * right buf_size for the current configuration is pointed by
+	 * stat->buf_size.
+	 */
+	memset(buf->virt_addr, MAGIC_NUM, MAGIC_SIZE);
+	memset(buf->virt_addr + buf_size, MAGIC_NUM, MAGIC_SIZE);
+
+	isp_stat_buf_sync_magic_for_device(stat, buf, buf_size,
+					   DMA_BIDIRECTIONAL);
+}
+
+static void isp_stat_buf_sync_for_device(struct ispstat *stat,
+					 struct ispstat_buffer *buf)
+{
+	if (IS_COHERENT_BUF(stat))
+		return;
+
+	dma_sync_sg_for_device(stat->isp->dev, buf->iovm->sgt->sgl,
+			       buf->iovm->sgt->nents, DMA_FROM_DEVICE);
+}
+
+static void isp_stat_buf_sync_for_cpu(struct ispstat *stat,
+				      struct ispstat_buffer *buf)
+{
+	if (IS_COHERENT_BUF(stat))
+		return;
+
+	dma_sync_sg_for_cpu(stat->isp->dev, buf->iovm->sgt->sgl,
+			    buf->iovm->sgt->nents, DMA_FROM_DEVICE);
+}
+
+static void isp_stat_buf_clear(struct ispstat *stat)
+{
+	int i;
+
+	for (i = 0; i < STAT_MAX_BUFS; i++)
+		stat->buf[i].empty = 1;
+}
+
+static struct ispstat_buffer *
+__isp_stat_buf_find(struct ispstat *stat, int look_empty)
+{
+	struct ispstat_buffer *found = NULL;
+	int i;
+
+	for (i = 0; i < STAT_MAX_BUFS; i++) {
+		struct ispstat_buffer *curr = &stat->buf[i];
+
+		/*
+		 * Don't select the buffer which is being copied to
+		 * userspace or used by the module.
+		 */
+		if (curr == stat->locked_buf || curr == stat->active_buf)
+			continue;
+
+		/* Don't select uninitialised buffers if it's not required */
+		if (!look_empty && curr->empty)
+			continue;
+
+		/* Pick uninitialised buffer over anything else if look_empty */
+		if (curr->empty) {
+			found = curr;
+			break;
+		}
+
+		/* Choose the oldest buffer */
+		if (!found ||
+		    (s32)curr->frame_number - (s32)found->frame_number < 0)
+			found = curr;
+	}
+
+	return found;
+}
+
+static inline struct ispstat_buffer *
+isp_stat_buf_find_oldest(struct ispstat *stat)
+{
+	return __isp_stat_buf_find(stat, 0);
+}
+
+static inline struct ispstat_buffer *
+isp_stat_buf_find_oldest_or_empty(struct ispstat *stat)
+{
+	return __isp_stat_buf_find(stat, 1);
+}
+
+static int isp_stat_buf_queue(struct ispstat *stat)
+{
+	if (!stat->active_buf)
+		return STAT_NO_BUF;
+
+	do_gettimeofday(&stat->active_buf->ts);
+
+	stat->active_buf->buf_size = stat->buf_size;
+	if (isp_stat_buf_check_magic(stat, stat->active_buf)) {
+		dev_dbg(stat->isp->dev, "%s: data wasn't properly written.\n",
+			stat->subdev.name);
+		return STAT_NO_BUF;
+	}
+	stat->active_buf->config_counter = stat->config_counter;
+	stat->active_buf->frame_number = stat->frame_number;
+	stat->active_buf->empty = 0;
+	stat->active_buf = NULL;
+
+	return STAT_BUF_DONE;
+}
+
+/* Get next free buffer to write the statistics to and mark it active. */
+static void isp_stat_buf_next(struct ispstat *stat)
+{
+	if (unlikely(stat->active_buf))
+		/* Overwriting unused active buffer */
+		dev_dbg(stat->isp->dev, "%s: new buffer requested without "
+					"queuing active one.\n",
+					stat->subdev.name);
+	else
+		stat->active_buf = isp_stat_buf_find_oldest_or_empty(stat);
+}
+
+static void isp_stat_buf_release(struct ispstat *stat)
+{
+	unsigned long flags;
+
+	isp_stat_buf_sync_for_device(stat, stat->locked_buf);
+	spin_lock_irqsave(&stat->isp->stat_lock, flags);
+	stat->locked_buf = NULL;
+	spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+}
+
+/* Get buffer to userspace. */
+static struct ispstat_buffer *isp_stat_buf_get(struct ispstat *stat,
+					       struct omap3isp_stat_data *data)
+{
+	int rval = 0;
+	unsigned long flags;
+	struct ispstat_buffer *buf;
+
+	spin_lock_irqsave(&stat->isp->stat_lock, flags);
+
+	while (1) {
+		buf = isp_stat_buf_find_oldest(stat);
+		if (!buf) {
+			spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+			dev_dbg(stat->isp->dev, "%s: cannot find a buffer.\n",
+				stat->subdev.name);
+			return ERR_PTR(-EBUSY);
+		}
+		if (isp_stat_buf_check_magic(stat, buf)) {
+			dev_dbg(stat->isp->dev, "%s: current buffer has "
+				"corrupted data\n.", stat->subdev.name);
+			/* Mark empty because it doesn't have valid data. */
+			buf->empty = 1;
+		} else {
+			/* Buffer isn't corrupted. */
+			break;
+		}
+	}
+
+	stat->locked_buf = buf;
+
+	spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+
+	if (buf->buf_size > data->buf_size) {
+		dev_warn(stat->isp->dev, "%s: userspace's buffer size is "
+					 "not enough.\n", stat->subdev.name);
+		isp_stat_buf_release(stat);
+		return ERR_PTR(-EINVAL);
+	}
+
+	isp_stat_buf_sync_for_cpu(stat, buf);
+
+	rval = copy_to_user(data->buf,
+			    buf->virt_addr,
+			    buf->buf_size);
+
+	if (rval) {
+		dev_info(stat->isp->dev,
+			 "%s: failed copying %d bytes of stat data\n",
+			 stat->subdev.name, rval);
+		buf = ERR_PTR(-EFAULT);
+		isp_stat_buf_release(stat);
+	}
+
+	return buf;
+}
+
+static void isp_stat_bufs_free(struct ispstat *stat)
+{
+	struct isp_device *isp = stat->isp;
+	int i;
+
+	for (i = 0; i < STAT_MAX_BUFS; i++) {
+		struct ispstat_buffer *buf = &stat->buf[i];
+
+		if (!IS_COHERENT_BUF(stat)) {
+			if (IS_ERR_OR_NULL((void *)buf->iommu_addr))
+				continue;
+			if (buf->iovm)
+				dma_unmap_sg(isp->dev, buf->iovm->sgt->sgl,
+					     buf->iovm->sgt->nents,
+					     DMA_FROM_DEVICE);
+			iommu_vfree(isp->iommu, buf->iommu_addr);
+		} else {
+			if (!buf->virt_addr)
+				continue;
+			dma_free_coherent(stat->isp->dev, stat->buf_alloc_size,
+					  buf->virt_addr, buf->dma_addr);
+		}
+		buf->iommu_addr = 0;
+		buf->iovm = NULL;
+		buf->dma_addr = 0;
+		buf->virt_addr = NULL;
+		buf->empty = 1;
+	}
+
+	dev_dbg(stat->isp->dev, "%s: all buffers were freed.\n",
+		stat->subdev.name);
+
+	stat->buf_alloc_size = 0;
+	stat->active_buf = NULL;
+}
+
+static int isp_stat_bufs_alloc_iommu(struct ispstat *stat, unsigned int size)
+{
+	struct isp_device *isp = stat->isp;
+	int i;
+
+	stat->buf_alloc_size = size;
+
+	for (i = 0; i < STAT_MAX_BUFS; i++) {
+		struct ispstat_buffer *buf = &stat->buf[i];
+		struct iovm_struct *iovm;
+
+		WARN_ON(buf->dma_addr);
+		buf->iommu_addr = iommu_vmalloc(isp->iommu, 0, size,
+						IOMMU_FLAG);
+		if (IS_ERR((void *)buf->iommu_addr)) {
+			dev_err(stat->isp->dev,
+				 "%s: Can't acquire memory for "
+				 "buffer %d\n", stat->subdev.name, i);
+			isp_stat_bufs_free(stat);
+			return -ENOMEM;
+		}
+
+		iovm = find_iovm_area(isp->iommu, buf->iommu_addr);
+		if (!iovm ||
+		    !dma_map_sg(isp->dev, iovm->sgt->sgl, iovm->sgt->nents,
+				DMA_FROM_DEVICE)) {
+			isp_stat_bufs_free(stat);
+			return -ENOMEM;
+		}
+		buf->iovm = iovm;
+
+		buf->virt_addr = da_to_va(stat->isp->iommu,
+					  (u32)buf->iommu_addr);
+		buf->empty = 1;
+		dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
+			"iommu_addr=0x%08lx virt_addr=0x%08lx",
+			stat->subdev.name, i, buf->iommu_addr,
+			(unsigned long)buf->virt_addr);
+	}
+
+	return 0;
+}
+
+static int isp_stat_bufs_alloc_dma(struct ispstat *stat, unsigned int size)
+{
+	int i;
+
+	stat->buf_alloc_size = size;
+
+	for (i = 0; i < STAT_MAX_BUFS; i++) {
+		struct ispstat_buffer *buf = &stat->buf[i];
+
+		WARN_ON(buf->iommu_addr);
+		buf->virt_addr = dma_alloc_coherent(stat->isp->dev, size,
+					&buf->dma_addr, GFP_KERNEL | GFP_DMA);
+
+		if (!buf->virt_addr || !buf->dma_addr) {
+			dev_info(stat->isp->dev,
+				 "%s: Can't acquire memory for "
+				 "DMA buffer %d\n", stat->subdev.name, i);
+			isp_stat_bufs_free(stat);
+			return -ENOMEM;
+		}
+		buf->empty = 1;
+
+		dev_dbg(stat->isp->dev, "%s: buffer[%d] allocated."
+			"dma_addr=0x%08lx virt_addr=0x%08lx\n",
+			stat->subdev.name, i, (unsigned long)buf->dma_addr,
+			(unsigned long)buf->virt_addr);
+	}
+
+	return 0;
+}
+
+static int isp_stat_bufs_alloc(struct ispstat *stat, u32 size)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&stat->isp->stat_lock, flags);
+
+	BUG_ON(stat->locked_buf != NULL);
+
+	/* Are the old buffers big enough? */
+	if (stat->buf_alloc_size >= size) {
+		spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+		return 0;
+	}
+
+	if (stat->state != ISPSTAT_DISABLED || stat->buf_processing) {
+		dev_info(stat->isp->dev,
+			 "%s: trying to allocate memory when busy\n",
+			 stat->subdev.name);
+		spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+		return -EBUSY;
+	}
+
+	spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+
+	isp_stat_bufs_free(stat);
+
+	if (IS_COHERENT_BUF(stat))
+		return isp_stat_bufs_alloc_dma(stat, size);
+	else
+		return isp_stat_bufs_alloc_iommu(stat, size);
+}
+
+static void isp_stat_queue_event(struct ispstat *stat, int err)
+{
+	struct video_device *vdev = &stat->subdev.devnode;
+	struct v4l2_event event;
+	struct omap3isp_stat_event_status *status = (void *)event.u.data;
+
+	memset(&event, 0, sizeof(event));
+	if (!err) {
+		status->frame_number = stat->frame_number;
+		status->config_counter = stat->config_counter;
+	} else {
+		status->buf_err = 1;
+	}
+	event.type = stat->event_type;
+	v4l2_event_queue(vdev, &event);
+}
+
+
+/*
+ * omap3isp_stat_request_statistics - Request statistics.
+ * @data: Pointer to return statistics data.
+ *
+ * Returns 0 if successful.
+ */
+int omap3isp_stat_request_statistics(struct ispstat *stat,
+				     struct omap3isp_stat_data *data)
+{
+	struct ispstat_buffer *buf;
+
+	if (stat->state != ISPSTAT_ENABLED) {
+		dev_dbg(stat->isp->dev, "%s: engine not enabled.\n",
+			stat->subdev.name);
+		return -EINVAL;
+	}
+
+	mutex_lock(&stat->ioctl_lock);
+	buf = isp_stat_buf_get(stat, data);
+	if (IS_ERR(buf)) {
+		mutex_unlock(&stat->ioctl_lock);
+		return PTR_ERR(buf);
+	}
+
+	data->ts = buf->ts;
+	data->config_counter = buf->config_counter;
+	data->frame_number = buf->frame_number;
+	data->buf_size = buf->buf_size;
+
+	buf->empty = 1;
+	isp_stat_buf_release(stat);
+	mutex_unlock(&stat->ioctl_lock);
+
+	return 0;
+}
+
+/*
+ * omap3isp_stat_config - Receives new statistic engine configuration.
+ * @new_conf: Pointer to config structure.
+ *
+ * Returns 0 if successful, -EINVAL if new_conf pointer is NULL, -ENOMEM if
+ * was unable to allocate memory for the buffer, or other errors if parameters
+ * are invalid.
+ */
+int omap3isp_stat_config(struct ispstat *stat, void *new_conf)
+{
+	int ret;
+	unsigned long irqflags;
+	struct ispstat_generic_config *user_cfg = new_conf;
+	u32 buf_size = user_cfg->buf_size;
+
+	if (!new_conf) {
+		dev_dbg(stat->isp->dev, "%s: configuration is NULL\n",
+			stat->subdev.name);
+		return -EINVAL;
+	}
+
+	mutex_lock(&stat->ioctl_lock);
+
+	dev_dbg(stat->isp->dev, "%s: configuring module with buffer "
+		"size=0x%08lx\n", stat->subdev.name, (unsigned long)buf_size);
+
+	ret = stat->ops->validate_params(stat, new_conf);
+	if (ret) {
+		mutex_unlock(&stat->ioctl_lock);
+		dev_dbg(stat->isp->dev, "%s: configuration values are "
+					"invalid.\n", stat->subdev.name);
+		return ret;
+	}
+
+	if (buf_size != user_cfg->buf_size)
+		dev_dbg(stat->isp->dev, "%s: driver has corrected buffer size "
+			"request to 0x%08lx\n", stat->subdev.name,
+			(unsigned long)user_cfg->buf_size);
+
+	/*
+	 * Hack: H3A modules may need a doubled buffer size to avoid access
+	 * to a invalid memory address after a SBL overflow.
+	 * The buffer size is always PAGE_ALIGNED.
+	 * Hack 2: MAGIC_SIZE is added to buf_size so a magic word can be
+	 * inserted at the end to data integrity check purpose.
+	 * Hack 3: AF module writes one paxel data more than it should, so
+	 * the buffer allocation must consider it to avoid invalid memory
+	 * access.
+	 * Hack 4: H3A need to allocate extra space for the recover state.
+	 */
+	if (IS_H3A(stat)) {
+		buf_size = user_cfg->buf_size * 2 + MAGIC_SIZE;
+		if (IS_H3A_AF(stat))
+			/*
+			 * Adding one extra paxel data size for each recover
+			 * buffer + 2 regular ones.
+			 */
+			buf_size += AF_EXTRA_DATA * (NUM_H3A_RECOVER_BUFS + 2);
+		if (stat->recover_priv) {
+			struct ispstat_generic_config *recover_cfg =
+				stat->recover_priv;
+			buf_size += recover_cfg->buf_size *
+				    NUM_H3A_RECOVER_BUFS;
+		}
+		buf_size = PAGE_ALIGN(buf_size);
+	} else { /* Histogram */
+		buf_size = PAGE_ALIGN(user_cfg->buf_size + MAGIC_SIZE);
+	}
+
+	ret = isp_stat_bufs_alloc(stat, buf_size);
+	if (ret) {
+		mutex_unlock(&stat->ioctl_lock);
+		return ret;
+	}
+
+	spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
+	stat->ops->set_params(stat, new_conf);
+	spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+
+	/*
+	 * Returning the right future config_counter for this setup, so
+	 * userspace can *know* when it has been applied.
+	 */
+	user_cfg->config_counter = stat->config_counter + stat->inc_config;
+
+	/* Module has a valid configuration. */
+	stat->configured = 1;
+	dev_dbg(stat->isp->dev, "%s: module has been successfully "
+		"configured.\n", stat->subdev.name);
+
+	mutex_unlock(&stat->ioctl_lock);
+
+	return 0;
+}
+
+/*
+ * isp_stat_buf_process - Process statistic buffers.
+ * @buf_state: points out if buffer is ready to be processed. It's necessary
+ *	       because histogram needs to copy the data from internal memory
+ *	       before be able to process the buffer.
+ */
+static int isp_stat_buf_process(struct ispstat *stat, int buf_state)
+{
+	int ret = STAT_NO_BUF;
+
+	if (!atomic_add_unless(&stat->buf_err, -1, 0) &&
+	    buf_state == STAT_BUF_DONE && stat->state == ISPSTAT_ENABLED) {
+		ret = isp_stat_buf_queue(stat);
+		isp_stat_buf_next(stat);
+	}
+
+	return ret;
+}
+
+int omap3isp_stat_pcr_busy(struct ispstat *stat)
+{
+	return stat->ops->busy(stat);
+}
+
+int omap3isp_stat_busy(struct ispstat *stat)
+{
+	return omap3isp_stat_pcr_busy(stat) | stat->buf_processing |
+		(stat->state != ISPSTAT_DISABLED);
+}
+
+/*
+ * isp_stat_pcr_enable - Disables/Enables statistic engines.
+ * @pcr_enable: 0/1 - Disables/Enables the engine.
+ *
+ * Must be called from ISP driver when the module is idle and synchronized
+ * with CCDC.
+ */
+static void isp_stat_pcr_enable(struct ispstat *stat, u8 pcr_enable)
+{
+	if ((stat->state != ISPSTAT_ENABLING &&
+	     stat->state != ISPSTAT_ENABLED) && pcr_enable)
+		/* Userspace has disabled the module. Aborting. */
+		return;
+
+	stat->ops->enable(stat, pcr_enable);
+	if (stat->state == ISPSTAT_DISABLING && !pcr_enable)
+		stat->state = ISPSTAT_DISABLED;
+	else if (stat->state == ISPSTAT_ENABLING && pcr_enable)
+		stat->state = ISPSTAT_ENABLED;
+}
+
+void omap3isp_stat_suspend(struct ispstat *stat)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&stat->isp->stat_lock, flags);
+
+	if (stat->state != ISPSTAT_DISABLED)
+		stat->ops->enable(stat, 0);
+	if (stat->state == ISPSTAT_ENABLED)
+		stat->state = ISPSTAT_SUSPENDED;
+
+	spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+}
+
+void omap3isp_stat_resume(struct ispstat *stat)
+{
+	/* Module will be re-enabled with its pipeline */
+	if (stat->state == ISPSTAT_SUSPENDED)
+		stat->state = ISPSTAT_ENABLING;
+}
+
+static void isp_stat_try_enable(struct ispstat *stat)
+{
+	unsigned long irqflags;
+
+	if (stat->priv == NULL)
+		/* driver wasn't initialised */
+		return;
+
+	spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
+	if (stat->state == ISPSTAT_ENABLING && !stat->buf_processing &&
+	    stat->buf_alloc_size) {
+		/*
+		 * Userspace's requested to enable the engine but it wasn't yet.
+		 * Let's do that now.
+		 */
+		stat->update = 1;
+		isp_stat_buf_next(stat);
+		stat->ops->setup_regs(stat, stat->priv);
+		isp_stat_buf_insert_magic(stat, stat->active_buf);
+
+		/*
+		 * H3A module has some hw issues which forces the driver to
+		 * ignore next buffers even if it was disabled in the meantime.
+		 * On the other hand, Histogram shouldn't ignore buffers anymore
+		 * if it's being enabled.
+		 */
+		if (!IS_H3A(stat))
+			atomic_set(&stat->buf_err, 0);
+
+		isp_stat_pcr_enable(stat, 1);
+		spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+		dev_dbg(stat->isp->dev, "%s: module is enabled.\n",
+			stat->subdev.name);
+	} else {
+		spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+	}
+}
+
+void omap3isp_stat_isr_frame_sync(struct ispstat *stat)
+{
+	isp_stat_try_enable(stat);
+}
+
+void omap3isp_stat_sbl_overflow(struct ispstat *stat)
+{
+	unsigned long irqflags;
+
+	spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
+	/*
+	 * Due to a H3A hw issue which prevents the next buffer to start from
+	 * the correct memory address, 2 buffers must be ignored.
+	 */
+	atomic_set(&stat->buf_err, 2);
+
+	/*
+	 * If more than one SBL overflow happen in a row, H3A module may access
+	 * invalid memory region.
+	 * stat->sbl_ovl_recover is set to tell to the driver to temporarily use
+	 * a soft configuration which helps to avoid consecutive overflows.
+	 */
+	if (stat->recover_priv)
+		stat->sbl_ovl_recover = 1;
+	spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+}
+
+/*
+ * omap3isp_stat_enable - Disable/Enable statistic engine as soon as possible
+ * @enable: 0/1 - Disables/Enables the engine.
+ *
+ * Client should configure all the module registers before this.
+ * This function can be called from a userspace request.
+ */
+int omap3isp_stat_enable(struct ispstat *stat, u8 enable)
+{
+	unsigned long irqflags;
+
+	dev_dbg(stat->isp->dev, "%s: user wants to %s module.\n",
+		stat->subdev.name, enable ? "enable" : "disable");
+
+	/* Prevent enabling while configuring */
+	mutex_lock(&stat->ioctl_lock);
+
+	spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
+
+	if (!stat->configured && enable) {
+		spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+		mutex_unlock(&stat->ioctl_lock);
+		dev_dbg(stat->isp->dev, "%s: cannot enable module as it's "
+			"never been successfully configured so far.\n",
+			stat->subdev.name);
+		return -EINVAL;
+	}
+
+	if (enable) {
+		if (stat->state == ISPSTAT_DISABLING)
+			/* Previous disabling request wasn't done yet */
+			stat->state = ISPSTAT_ENABLED;
+		else if (stat->state == ISPSTAT_DISABLED)
+			/* Module is now being enabled */
+			stat->state = ISPSTAT_ENABLING;
+	} else {
+		if (stat->state == ISPSTAT_ENABLING) {
+			/* Previous enabling request wasn't done yet */
+			stat->state = ISPSTAT_DISABLED;
+		} else if (stat->state == ISPSTAT_ENABLED) {
+			/* Module is now being disabled */
+			stat->state = ISPSTAT_DISABLING;
+			isp_stat_buf_clear(stat);
+		}
+	}
+
+	spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+	mutex_unlock(&stat->ioctl_lock);
+
+	return 0;
+}
+
+int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable)
+{
+	struct ispstat *stat = v4l2_get_subdevdata(subdev);
+
+	if (enable) {
+		/*
+		 * Only set enable PCR bit if the module was previously
+		 * enabled through ioct.
+		 */
+		isp_stat_try_enable(stat);
+	} else {
+		unsigned long flags;
+		/* Disable PCR bit and config enable field */
+		omap3isp_stat_enable(stat, 0);
+		spin_lock_irqsave(&stat->isp->stat_lock, flags);
+		stat->ops->enable(stat, 0);
+		spin_unlock_irqrestore(&stat->isp->stat_lock, flags);
+
+		/*
+		 * If module isn't busy, a new interrupt may come or not to
+		 * set the state to DISABLED. As Histogram needs to read its
+		 * internal memory to clear it, let interrupt handler
+		 * responsible of changing state to DISABLED. If the last
+		 * interrupt is coming, it's still safe as the handler will
+		 * ignore the second time when state is already set to DISABLED.
+		 * It's necessary to synchronize Histogram with streamoff, once
+		 * the module may be considered idle before last SDMA transfer
+		 * starts if we return here.
+		 */
+		if (!omap3isp_stat_pcr_busy(stat))
+			omap3isp_stat_isr(stat);
+
+		dev_dbg(stat->isp->dev, "%s: module is being disabled\n",
+			stat->subdev.name);
+	}
+
+	return 0;
+}
+
+/*
+ * __stat_isr - Interrupt handler for statistic drivers
+ */
+static void __stat_isr(struct ispstat *stat, int from_dma)
+{
+	int ret = STAT_BUF_DONE;
+	int buf_processing;
+	unsigned long irqflags;
+	struct isp_pipeline *pipe;
+
+	/*
+	 * stat->buf_processing must be set before disable module. It's
+	 * necessary to not inform too early the buffers aren't busy in case
+	 * of SDMA is going to be used.
+	 */
+	spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
+	if (stat->state == ISPSTAT_DISABLED) {
+		spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+		return;
+	}
+	buf_processing = stat->buf_processing;
+	stat->buf_processing = 1;
+	stat->ops->enable(stat, 0);
+
+	if (buf_processing && !from_dma) {
+		if (stat->state == ISPSTAT_ENABLED) {
+			spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+			dev_err(stat->isp->dev,
+				"%s: interrupt occurred when module was still "
+				"processing a buffer.\n", stat->subdev.name);
+			ret = STAT_NO_BUF;
+			goto out;
+		} else {
+			/*
+			 * Interrupt handler was called from streamoff when
+			 * the module wasn't busy anymore to ensure it is being
+			 * disabled after process last buffer. If such buffer
+			 * processing has already started, no need to do
+			 * anything else.
+			 */
+			spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+			return;
+		}
+	}
+	spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+
+	/* If it's busy we can't process this buffer anymore */
+	if (!omap3isp_stat_pcr_busy(stat)) {
+		if (!from_dma && stat->ops->buf_process)
+			/* Module still need to copy data to buffer. */
+			ret = stat->ops->buf_process(stat);
+		if (ret == STAT_BUF_WAITING_DMA)
+			/* Buffer is not ready yet */
+			return;
+
+		spin_lock_irqsave(&stat->isp->stat_lock, irqflags);
+
+		/*
+		 * Histogram needs to read its internal memory to clear it
+		 * before be disabled. For that reason, common statistic layer
+		 * can return only after call stat's buf_process() operator.
+		 */
+		if (stat->state == ISPSTAT_DISABLING) {
+			stat->state = ISPSTAT_DISABLED;
+			spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+			stat->buf_processing = 0;
+			return;
+		}
+		pipe = to_isp_pipeline(&stat->subdev.entity);
+		stat->frame_number = atomic_read(&pipe->frame_number);
+
+		/*
+		 * Before this point, 'ret' stores the buffer's status if it's
+		 * ready to be processed. Afterwards, it holds the status if
+		 * it was processed successfully.
+		 */
+		ret = isp_stat_buf_process(stat, ret);
+
+		if (likely(!stat->sbl_ovl_recover)) {
+			stat->ops->setup_regs(stat, stat->priv);
+		} else {
+			/*
+			 * Using recover config to increase the chance to have
+			 * a good buffer processing and make the H3A module to
+			 * go back to a valid state.
+			 */
+			stat->update = 1;
+			stat->ops->setup_regs(stat, stat->recover_priv);
+			stat->sbl_ovl_recover = 0;
+
+			/*
+			 * Set 'update' in case of the module needs to use
+			 * regular configuration after next buffer.
+			 */
+			stat->update = 1;
+		}
+
+		isp_stat_buf_insert_magic(stat, stat->active_buf);
+
+		/*
+		 * Hack: H3A modules may access invalid memory address or send
+		 * corrupted data to userspace if more than 1 SBL overflow
+		 * happens in a row without re-writing its buffer's start memory
+		 * address in the meantime. Such situation is avoided if the
+		 * module is not immediately re-enabled when the ISR misses the
+		 * timing to process the buffer and to setup the registers.
+		 * Because of that, pcr_enable(1) was moved to inside this 'if'
+		 * block. But the next interruption will still happen as during
+		 * pcr_enable(0) the module was busy.
+		 */
+		isp_stat_pcr_enable(stat, 1);
+		spin_unlock_irqrestore(&stat->isp->stat_lock, irqflags);
+	} else {
+		/*
+		 * If a SBL overflow occurs and the H3A driver misses the timing
+		 * to process the buffer, stat->buf_err is set and won't be
+		 * cleared now. So the next buffer will be correctly ignored.
+		 * It's necessary due to a hw issue which makes the next H3A
+		 * buffer to start from the memory address where the previous
+		 * one stopped, instead of start where it was configured to.
+		 * Do not "stat->buf_err = 0" here.
+		 */
+
+		if (stat->ops->buf_process)
+			/*
+			 * Driver may need to erase current data prior to
+			 * process a new buffer. If it misses the timing, the
+			 * next buffer might be wrong. So should be ignored.
+			 * It happens only for Histogram.
+			 */
+			atomic_set(&stat->buf_err, 1);
+
+		ret = STAT_NO_BUF;
+		dev_dbg(stat->isp->dev, "%s: cannot process buffer, "
+					"device is busy.\n", stat->subdev.name);
+	}
+
+out:
+	stat->buf_processing = 0;
+	isp_stat_queue_event(stat, ret != STAT_BUF_DONE);
+}
+
+void omap3isp_stat_isr(struct ispstat *stat)
+{
+	__stat_isr(stat, 0);
+}
+
+void omap3isp_stat_dma_isr(struct ispstat *stat)
+{
+	__stat_isr(stat, 1);
+}
+
+static int isp_stat_init_entities(struct ispstat *stat, const char *name,
+				  const struct v4l2_subdev_ops *sd_ops)
+{
+	struct v4l2_subdev *subdev = &stat->subdev;
+	struct media_entity *me = &subdev->entity;
+
+	v4l2_subdev_init(subdev, sd_ops);
+	snprintf(subdev->name, V4L2_SUBDEV_NAME_SIZE, "OMAP3 ISP %s", name);
+	subdev->grp_id = 1 << 16;	/* group ID for isp subdevs */
+	subdev->flags |= V4L2_SUBDEV_FL_HAS_EVENTS | V4L2_SUBDEV_FL_HAS_DEVNODE;
+	subdev->nevents = STAT_NEVENTS;
+	v4l2_set_subdevdata(subdev, stat);
+
+	stat->pad.flags = MEDIA_PAD_FL_SINK;
+	me->ops = NULL;
+
+	return media_entity_init(me, 1, &stat->pad, 0);
+}
+
+int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
+				  struct v4l2_fh *fh,
+				  struct v4l2_event_subscription *sub)
+{
+	struct ispstat *stat = v4l2_get_subdevdata(subdev);
+
+	if (sub->type != stat->event_type)
+		return -EINVAL;
+
+	return v4l2_event_subscribe(fh, sub);
+}
+
+int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
+				    struct v4l2_fh *fh,
+				    struct v4l2_event_subscription *sub)
+{
+	return v4l2_event_unsubscribe(fh, sub);
+}
+
+void omap3isp_stat_unregister_entities(struct ispstat *stat)
+{
+	media_entity_cleanup(&stat->subdev.entity);
+	v4l2_device_unregister_subdev(&stat->subdev);
+}
+
+int omap3isp_stat_register_entities(struct ispstat *stat,
+				    struct v4l2_device *vdev)
+{
+	return v4l2_device_register_subdev(vdev, &stat->subdev);
+}
+
+int omap3isp_stat_init(struct ispstat *stat, const char *name,
+		       const struct v4l2_subdev_ops *sd_ops)
+{
+	stat->buf = kcalloc(STAT_MAX_BUFS, sizeof(*stat->buf), GFP_KERNEL);
+	if (!stat->buf)
+		return -ENOMEM;
+	isp_stat_buf_clear(stat);
+	mutex_init(&stat->ioctl_lock);
+	atomic_set(&stat->buf_err, 0);
+
+	return isp_stat_init_entities(stat, name, sd_ops);
+}
+
+void omap3isp_stat_free(struct ispstat *stat)
+{
+	isp_stat_bufs_free(stat);
+	kfree(stat->buf);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispstat.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispstat.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispstat.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispstat.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,169 @@
+/*
+ * ispstat.h
+ *
+ * TI OMAP3 ISP - Statistics core
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc
+ *
+ * Contacts: David Cohen <dacohen@gmail.com>
+ *	     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_STAT_H
+#define OMAP3_ISP_STAT_H
+
+#include <linux/types.h>
+#include <linux/omap3isp.h>
+#include <plat/dma.h>
+#include <media/v4l2-event.h>
+
+#include "isp.h"
+#include "ispvideo.h"
+
+#define STAT_MAX_BUFS		5
+#define STAT_NEVENTS		8
+
+#define STAT_BUF_DONE		0	/* Buffer is ready */
+#define STAT_NO_BUF		1	/* An error has occurred */
+#define STAT_BUF_WAITING_DMA	2	/* Histogram only: DMA is running */
+
+struct ispstat;
+
+struct ispstat_buffer {
+	unsigned long iommu_addr;
+	struct iovm_struct *iovm;
+	void *virt_addr;
+	dma_addr_t dma_addr;
+	struct timeval ts;
+	u32 buf_size;
+	u32 frame_number;
+	u16 config_counter;
+	u8 empty;
+};
+
+struct ispstat_ops {
+	/*
+	 * Validate new params configuration.
+	 * new_conf->buf_size value must be changed to the exact buffer size
+	 * necessary for the new configuration if it's smaller.
+	 */
+	int (*validate_params)(struct ispstat *stat, void *new_conf);
+
+	/*
+	 * Save new params configuration.
+	 * stat->priv->buf_size value must be set to the exact buffer size for
+	 * the new configuration.
+	 * stat->update is set to 1 if new configuration is different than
+	 * current one.
+	 */
+	void (*set_params)(struct ispstat *stat, void *new_conf);
+
+	/* Apply stored configuration. */
+	void (*setup_regs)(struct ispstat *stat, void *priv);
+
+	/* Enable/Disable module. */
+	void (*enable)(struct ispstat *stat, int enable);
+
+	/* Verify is module is busy. */
+	int (*busy)(struct ispstat *stat);
+
+	/* Used for specific operations during generic buf process task. */
+	int (*buf_process)(struct ispstat *stat);
+};
+
+enum ispstat_state_t {
+	ISPSTAT_DISABLED = 0,
+	ISPSTAT_DISABLING,
+	ISPSTAT_ENABLED,
+	ISPSTAT_ENABLING,
+	ISPSTAT_SUSPENDED,
+};
+
+struct ispstat {
+	struct v4l2_subdev subdev;
+	struct media_pad pad;	/* sink pad */
+
+	/* Control */
+	unsigned configured:1;
+	unsigned update:1;
+	unsigned buf_processing:1;
+	unsigned sbl_ovl_recover:1;
+	u8 inc_config;
+	atomic_t buf_err;
+	enum ispstat_state_t state;	/* enabling/disabling state */
+	struct omap_dma_channel_params dma_config;
+	struct isp_device *isp;
+	void *priv;		/* pointer to priv config struct */
+	void *recover_priv;	/* pointer to recover priv configuration */
+	struct mutex ioctl_lock; /* serialize private ioctl */
+
+	const struct ispstat_ops *ops;
+
+	/* Buffer */
+	u8 wait_acc_frames;
+	u16 config_counter;
+	u32 frame_number;
+	u32 buf_size;
+	u32 buf_alloc_size;
+	int dma_ch;
+	unsigned long event_type;
+	struct ispstat_buffer *buf;
+	struct ispstat_buffer *active_buf;
+	struct ispstat_buffer *locked_buf;
+};
+
+struct ispstat_generic_config {
+	/*
+	 * Fields must be in the same order as in:
+	 *  - omap3isp_h3a_aewb_config
+	 *  - omap3isp_h3a_af_config
+	 *  - omap3isp_hist_config
+	 */
+	u32 buf_size;
+	u16 config_counter;
+};
+
+int omap3isp_stat_config(struct ispstat *stat, void *new_conf);
+int omap3isp_stat_request_statistics(struct ispstat *stat,
+				     struct omap3isp_stat_data *data);
+int omap3isp_stat_init(struct ispstat *stat, const char *name,
+		       const struct v4l2_subdev_ops *sd_ops);
+void omap3isp_stat_free(struct ispstat *stat);
+int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
+				  struct v4l2_fh *fh,
+				  struct v4l2_event_subscription *sub);
+int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
+				    struct v4l2_fh *fh,
+				    struct v4l2_event_subscription *sub);
+int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
+
+int omap3isp_stat_busy(struct ispstat *stat);
+int omap3isp_stat_pcr_busy(struct ispstat *stat);
+void omap3isp_stat_suspend(struct ispstat *stat);
+void omap3isp_stat_resume(struct ispstat *stat);
+int omap3isp_stat_enable(struct ispstat *stat, u8 enable);
+void omap3isp_stat_sbl_overflow(struct ispstat *stat);
+void omap3isp_stat_isr(struct ispstat *stat);
+void omap3isp_stat_isr_frame_sync(struct ispstat *stat);
+void omap3isp_stat_dma_isr(struct ispstat *stat);
+int omap3isp_stat_register_entities(struct ispstat *stat,
+				    struct v4l2_device *vdev);
+void omap3isp_stat_unregister_entities(struct ispstat *stat);
+
+#endif /* OMAP3_ISP_STAT_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispvideo.c linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispvideo.c
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispvideo.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispvideo.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1335 @@
+/*
+ * ispvideo.c
+ *
+ * TI OMAP3 ISP - Generic video node
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 <asm/cacheflush.h>
+#include <linux/clk.h>
+#include <linux/mm.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-ioctl.h>
+#include <plat/iommu.h>
+#include <plat/iovmm.h>
+#include <plat/omap-pm.h>
+
+#include "ispvideo.h"
+#include "isp.h"
+
+
+/* -----------------------------------------------------------------------------
+ * Helper functions
+ */
+
+static struct isp_format_info formats[] = {
+	{ V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+	  V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
+	  V4L2_PIX_FMT_GREY, 8, },
+	{ V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
+	  V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
+	  V4L2_PIX_FMT_Y10, 10, },
+	{ V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
+	  V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
+	  V4L2_PIX_FMT_Y12, 12, },
+	{ V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+	  V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
+	  V4L2_PIX_FMT_SBGGR8, 8, },
+	{ V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+	  V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
+	  V4L2_PIX_FMT_SGBRG8, 8, },
+	{ V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+	  V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
+	  V4L2_PIX_FMT_SGRBG8, 8, },
+	{ V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+	  V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
+	  V4L2_PIX_FMT_SRGGB8, 8, },
+	{ V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
+	  V4L2_MBUS_FMT_SGRBG10_1X10, 0,
+	  V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
+	{ V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
+	  V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
+	  V4L2_PIX_FMT_SBGGR10, 10, },
+	{ V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
+	  V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
+	  V4L2_PIX_FMT_SGBRG10, 10, },
+	{ V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
+	  V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
+	  V4L2_PIX_FMT_SGRBG10, 10, },
+	{ V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
+	  V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
+	  V4L2_PIX_FMT_SRGGB10, 10, },
+	{ V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
+	  V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
+	  V4L2_PIX_FMT_SBGGR12, 12, },
+	{ V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
+	  V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
+	  V4L2_PIX_FMT_SGBRG12, 12, },
+	{ V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
+	  V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
+	  V4L2_PIX_FMT_SGRBG12, 12, },
+	{ V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
+	  V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
+	  V4L2_PIX_FMT_SRGGB12, 12, },
+	{ V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
+	  V4L2_MBUS_FMT_UYVY8_1X16, 0,
+	  V4L2_PIX_FMT_UYVY, 16, },
+	{ V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
+	  V4L2_MBUS_FMT_YUYV8_1X16, 0,
+	  V4L2_PIX_FMT_YUYV, 16, },
+};
+
+const struct isp_format_info *
+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code)
+{
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+		if (formats[i].code == code)
+			return &formats[i];
+	}
+
+	return NULL;
+}
+
+/*
+ * Decide whether desired output pixel code can be obtained with
+ * the lane shifter by shifting the input pixel code.
+ * @in: input pixelcode to shifter
+ * @out: output pixelcode from shifter
+ * @additional_shift: # of bits the sensor's LSB is offset from CAMEXT[0]
+ *
+ * return true if the combination is possible
+ * return false otherwise
+ */
+static bool isp_video_is_shiftable(enum v4l2_mbus_pixelcode in,
+		enum v4l2_mbus_pixelcode out,
+		unsigned int additional_shift)
+{
+	const struct isp_format_info *in_info, *out_info;
+
+	if (in == out)
+		return true;
+
+	in_info = omap3isp_video_format_info(in);
+	out_info = omap3isp_video_format_info(out);
+
+	if ((in_info->flavor == 0) || (out_info->flavor == 0))
+		return false;
+
+	if (in_info->flavor != out_info->flavor)
+		return false;
+
+	return in_info->bpp - out_info->bpp + additional_shift <= 6;
+}
+
+/*
+ * isp_video_mbus_to_pix - Convert v4l2_mbus_framefmt to v4l2_pix_format
+ * @video: ISP video instance
+ * @mbus: v4l2_mbus_framefmt format (input)
+ * @pix: v4l2_pix_format format (output)
+ *
+ * Fill the output pix structure with information from the input mbus format.
+ * The bytesperline and sizeimage fields are computed from the requested bytes
+ * per line value in the pix format and information from the video instance.
+ *
+ * Return the number of padding bytes at end of line.
+ */
+static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
+					  const struct v4l2_mbus_framefmt *mbus,
+					  struct v4l2_pix_format *pix)
+{
+	unsigned int bpl = pix->bytesperline;
+	unsigned int min_bpl;
+	unsigned int i;
+
+	memset(pix, 0, sizeof(*pix));
+	pix->width = mbus->width;
+	pix->height = mbus->height;
+
+	for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+		if (formats[i].code == mbus->code)
+			break;
+	}
+
+	if (WARN_ON(i == ARRAY_SIZE(formats)))
+		return 0;
+
+	min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8;
+
+	/* Clamp the requested bytes per line value. If the maximum bytes per
+	 * line value is zero, the module doesn't support user configurable line
+	 * sizes. Override the requested value with the minimum in that case.
+	 */
+	if (video->bpl_max)
+		bpl = clamp(bpl, min_bpl, video->bpl_max);
+	else
+		bpl = min_bpl;
+
+	if (!video->bpl_zero_padding || bpl != min_bpl)
+		bpl = ALIGN(bpl, video->bpl_alignment);
+
+	pix->pixelformat = formats[i].pixelformat;
+	pix->bytesperline = bpl;
+	pix->sizeimage = pix->bytesperline * pix->height;
+	pix->colorspace = mbus->colorspace;
+	pix->field = mbus->field;
+
+	return bpl - min_bpl;
+}
+
+static void isp_video_pix_to_mbus(const struct v4l2_pix_format *pix,
+				  struct v4l2_mbus_framefmt *mbus)
+{
+	unsigned int i;
+
+	memset(mbus, 0, sizeof(*mbus));
+	mbus->width = pix->width;
+	mbus->height = pix->height;
+
+	for (i = 0; i < ARRAY_SIZE(formats); ++i) {
+		if (formats[i].pixelformat == pix->pixelformat)
+			break;
+	}
+
+	if (WARN_ON(i == ARRAY_SIZE(formats)))
+		return;
+
+	mbus->code = formats[i].code;
+	mbus->colorspace = pix->colorspace;
+	mbus->field = pix->field;
+}
+
+static struct v4l2_subdev *
+isp_video_remote_subdev(struct isp_video *video, u32 *pad)
+{
+	struct media_pad *remote;
+
+	remote = media_entity_remote_source(&video->pad);
+
+	if (remote == NULL ||
+	    media_entity_type(remote->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+		return NULL;
+
+	if (pad)
+		*pad = remote->index;
+
+	return media_entity_to_v4l2_subdev(remote->entity);
+}
+
+/* Return a pointer to the ISP video instance at the far end of the pipeline. */
+static struct isp_video *
+isp_video_far_end(struct isp_video *video)
+{
+	struct media_entity_graph graph;
+	struct media_entity *entity = &video->video.entity;
+	struct media_device *mdev = entity->parent;
+	struct isp_video *far_end = NULL;
+
+	mutex_lock(&mdev->graph_mutex);
+	media_entity_graph_walk_start(&graph, entity);
+
+	while ((entity = media_entity_graph_walk_next(&graph))) {
+		if (entity == &video->video.entity)
+			continue;
+
+		if (media_entity_type(entity) != MEDIA_ENT_T_DEVNODE)
+			continue;
+
+		far_end = to_isp_video(media_entity_to_video_device(entity));
+		if (far_end->type != video->type)
+			break;
+
+		far_end = NULL;
+	}
+
+	mutex_unlock(&mdev->graph_mutex);
+	return far_end;
+}
+
+/*
+ * Validate a pipeline by checking both ends of all links for format
+ * discrepancies.
+ *
+ * Compute the minimum time per frame value as the maximum of time per frame
+ * limits reported by every block in the pipeline.
+ *
+ * Return 0 if all formats match, or -EPIPE if at least one link is found with
+ * different formats on its two ends.
+ */
+static int isp_video_validate_pipeline(struct isp_pipeline *pipe)
+{
+	struct isp_device *isp = pipe->output->isp;
+	struct v4l2_subdev_format fmt_source;
+	struct v4l2_subdev_format fmt_sink;
+	struct media_pad *pad;
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	pipe->max_rate = pipe->l3_ick;
+
+	subdev = isp_video_remote_subdev(pipe->output, NULL);
+	if (subdev == NULL)
+		return -EPIPE;
+
+	while (1) {
+		unsigned int shifter_link;
+		/* Retrieve the sink format */
+		pad = &subdev->entity.pads[0];
+		if (!(pad->flags & MEDIA_PAD_FL_SINK))
+			break;
+
+		fmt_sink.pad = pad->index;
+		fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_sink);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			return -EPIPE;
+
+		/* Update the maximum frame rate */
+		if (subdev == &isp->isp_res.subdev)
+			omap3isp_resizer_max_rate(&isp->isp_res,
+						  &pipe->max_rate);
+
+		/* Check ccdc maximum data rate when data comes from sensor
+		 * TODO: Include ccdc rate in pipe->max_rate and compare the
+		 *       total pipe rate with the input data rate from sensor.
+		 */
+		if (subdev == &isp->isp_ccdc.subdev && pipe->input == NULL) {
+			unsigned int rate = UINT_MAX;
+
+			omap3isp_ccdc_max_rate(&isp->isp_ccdc, &rate);
+			if (isp->isp_ccdc.vpcfg.pixelclk > rate)
+				return -ENOSPC;
+		}
+
+		/* If sink pad is on CCDC, the link has the lane shifter
+		 * in the middle of it. */
+		shifter_link = subdev == &isp->isp_ccdc.subdev;
+
+		/* Retrieve the source format */
+		pad = media_entity_remote_source(pad);
+		if (pad == NULL ||
+		    media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+			break;
+
+		subdev = media_entity_to_v4l2_subdev(pad->entity);
+
+		fmt_source.pad = pad->index;
+		fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+		ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
+		if (ret < 0 && ret != -ENOIOCTLCMD)
+			return -EPIPE;
+
+		/* Check if the two ends match */
+		if (fmt_source.format.width != fmt_sink.format.width ||
+		    fmt_source.format.height != fmt_sink.format.height)
+			return -EPIPE;
+
+		if (shifter_link) {
+			unsigned int parallel_shift = 0;
+			if (isp->isp_ccdc.input == CCDC_INPUT_PARALLEL) {
+				struct isp_parallel_platform_data *pdata =
+					&((struct isp_v4l2_subdevs_group *)
+					      subdev->host_priv)->bus.parallel;
+				parallel_shift = pdata->data_lane_shift * 2;
+			}
+			if (!isp_video_is_shiftable(fmt_source.format.code,
+						fmt_sink.format.code,
+						parallel_shift))
+				return -EPIPE;
+		} else if (fmt_source.format.code != fmt_sink.format.code)
+			return -EPIPE;
+	}
+
+	return 0;
+}
+
+static int
+__isp_video_get_format(struct isp_video *video, struct v4l2_format *format)
+{
+	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *subdev;
+	u32 pad;
+	int ret;
+
+	subdev = isp_video_remote_subdev(video, &pad);
+	if (subdev == NULL)
+		return -EINVAL;
+
+	mutex_lock(&video->mutex);
+
+	fmt.pad = pad;
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+	if (ret == -ENOIOCTLCMD)
+		ret = -EINVAL;
+
+	mutex_unlock(&video->mutex);
+
+	if (ret)
+		return ret;
+
+	format->type = video->type;
+	return isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
+}
+
+static int
+isp_video_check_format(struct isp_video *video, struct isp_video_fh *vfh)
+{
+	struct v4l2_format format;
+	int ret;
+
+	memcpy(&format, &vfh->format, sizeof(format));
+	ret = __isp_video_get_format(video, &format);
+	if (ret < 0)
+		return ret;
+
+	if (vfh->format.fmt.pix.pixelformat != format.fmt.pix.pixelformat ||
+	    vfh->format.fmt.pix.height != format.fmt.pix.height ||
+	    vfh->format.fmt.pix.width != format.fmt.pix.width ||
+	    vfh->format.fmt.pix.bytesperline != format.fmt.pix.bytesperline ||
+	    vfh->format.fmt.pix.sizeimage != format.fmt.pix.sizeimage)
+		return -EINVAL;
+
+	return ret;
+}
+
+/* -----------------------------------------------------------------------------
+ * IOMMU management
+ */
+
+#define IOMMU_FLAG	(IOVMF_ENDIAN_LITTLE | IOVMF_ELSZ_8)
+
+/*
+ * ispmmu_vmap - Wrapper for Virtual memory mapping of a scatter gather list
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @sglist: Pointer to source Scatter gather list to allocate.
+ * @sglen: Number of elements of the scatter-gatter list.
+ *
+ * Returns a resulting mapped device address by the ISP MMU, or -ENOMEM if
+ * we ran out of memory.
+ */
+static dma_addr_t
+ispmmu_vmap(struct isp_device *isp, const struct scatterlist *sglist, int sglen)
+{
+	struct sg_table *sgt;
+	u32 da;
+
+	sgt = kmalloc(sizeof(*sgt), GFP_KERNEL);
+	if (sgt == NULL)
+		return -ENOMEM;
+
+	sgt->sgl = (struct scatterlist *)sglist;
+	sgt->nents = sglen;
+	sgt->orig_nents = sglen;
+
+	da = iommu_vmap(isp->iommu, 0, sgt, IOMMU_FLAG);
+	if (IS_ERR_VALUE(da))
+		kfree(sgt);
+
+	return da;
+}
+
+/*
+ * ispmmu_vunmap - Unmap a device address from the ISP MMU
+ * @dev: Device pointer specific to the OMAP3 ISP.
+ * @da: Device address generated from a ispmmu_vmap call.
+ */
+static void ispmmu_vunmap(struct isp_device *isp, dma_addr_t da)
+{
+	struct sg_table *sgt;
+
+	sgt = iommu_vunmap(isp->iommu, (u32)da);
+	kfree(sgt);
+}
+
+/* -----------------------------------------------------------------------------
+ * Video queue operations
+ */
+
+static void isp_video_queue_prepare(struct isp_video_queue *queue,
+				    unsigned int *nbuffers, unsigned int *size)
+{
+	struct isp_video_fh *vfh =
+		container_of(queue, struct isp_video_fh, queue);
+	struct isp_video *video = vfh->video;
+
+	*size = vfh->format.fmt.pix.sizeimage;
+	if (*size == 0)
+		return;
+
+	*nbuffers = min(*nbuffers, video->capture_mem / PAGE_ALIGN(*size));
+}
+
+static void isp_video_buffer_cleanup(struct isp_video_buffer *buf)
+{
+	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_buffer *buffer = to_isp_buffer(buf);
+	struct isp_video *video = vfh->video;
+
+	if (buffer->isp_addr) {
+		ispmmu_vunmap(video->isp, buffer->isp_addr);
+		buffer->isp_addr = 0;
+	}
+}
+
+static int isp_video_buffer_prepare(struct isp_video_buffer *buf)
+{
+	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_buffer *buffer = to_isp_buffer(buf);
+	struct isp_video *video = vfh->video;
+	unsigned long addr;
+
+	addr = ispmmu_vmap(video->isp, buf->sglist, buf->sglen);
+	if (IS_ERR_VALUE(addr))
+		return -EIO;
+
+	if (!IS_ALIGNED(addr, 32)) {
+		dev_dbg(video->isp->dev, "Buffer address must be "
+			"aligned to 32 bytes boundary.\n");
+		ispmmu_vunmap(video->isp, buffer->isp_addr);
+		return -EINVAL;
+	}
+
+	buf->vbuf.bytesused = vfh->format.fmt.pix.sizeimage;
+	buffer->isp_addr = addr;
+	return 0;
+}
+
+/*
+ * isp_video_buffer_queue - Add buffer to streaming queue
+ * @buf: Video buffer
+ *
+ * In memory-to-memory mode, start streaming on the pipeline if buffers are
+ * queued on both the input and the output, if the pipeline isn't already busy.
+ * If the pipeline is busy, it will be restarted in the output module interrupt
+ * handler.
+ */
+static void isp_video_buffer_queue(struct isp_video_buffer *buf)
+{
+	struct isp_video_fh *vfh = isp_video_queue_to_isp_video_fh(buf->queue);
+	struct isp_buffer *buffer = to_isp_buffer(buf);
+	struct isp_video *video = vfh->video;
+	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
+	enum isp_pipeline_state state;
+	unsigned long flags;
+	unsigned int empty;
+	unsigned int start;
+
+	empty = list_empty(&video->dmaqueue);
+	list_add_tail(&buffer->buffer.irqlist, &video->dmaqueue);
+
+	if (empty) {
+		if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			state = ISP_PIPELINE_QUEUE_OUTPUT;
+		else
+			state = ISP_PIPELINE_QUEUE_INPUT;
+
+		spin_lock_irqsave(&pipe->lock, flags);
+		pipe->state |= state;
+		video->ops->queue(video, buffer);
+		video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
+
+		start = isp_pipeline_ready(pipe);
+		if (start)
+			pipe->state |= ISP_PIPELINE_STREAM;
+		spin_unlock_irqrestore(&pipe->lock, flags);
+
+		if (start)
+			omap3isp_pipeline_set_stream(pipe,
+						ISP_PIPELINE_STREAM_SINGLESHOT);
+	}
+}
+
+static const struct isp_video_queue_operations isp_video_queue_ops = {
+	.queue_prepare = &isp_video_queue_prepare,
+	.buffer_prepare = &isp_video_buffer_prepare,
+	.buffer_queue = &isp_video_buffer_queue,
+	.buffer_cleanup = &isp_video_buffer_cleanup,
+};
+
+/*
+ * omap3isp_video_buffer_next - Complete the current buffer and return the next
+ * @video: ISP video object
+ * @error: Whether an error occurred during capture
+ *
+ * Remove the current video buffer from the DMA queue and fill its timestamp,
+ * field count and state fields before waking up its completion handler.
+ *
+ * The buffer state is set to VIDEOBUF_DONE if no error occurred (@error is 0)
+ * or VIDEOBUF_ERROR otherwise (@error is non-zero).
+ *
+ * The DMA queue is expected to contain at least one buffer.
+ *
+ * Return a pointer to the next buffer in the DMA queue, or NULL if the queue is
+ * empty.
+ */
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
+					      unsigned int error)
+{
+	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
+	struct isp_video_queue *queue = video->queue;
+	enum isp_pipeline_state state;
+	struct isp_video_buffer *buf;
+	unsigned long flags;
+	struct timespec ts;
+
+	spin_lock_irqsave(&queue->irqlock, flags);
+	if (WARN_ON(list_empty(&video->dmaqueue))) {
+		spin_unlock_irqrestore(&queue->irqlock, flags);
+		return NULL;
+	}
+
+	buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
+			       irqlist);
+	list_del(&buf->irqlist);
+	spin_unlock_irqrestore(&queue->irqlock, flags);
+
+	ktime_get_ts(&ts);
+	buf->vbuf.timestamp.tv_sec = ts.tv_sec;
+	buf->vbuf.timestamp.tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+
+	/* Do frame number propagation only if this is the output video node.
+	 * Frame number either comes from the CSI receivers or it gets
+	 * incremented here if H3A is not active.
+	 * Note: There is no guarantee that the output buffer will finish
+	 * first, so the input number might lag behind by 1 in some cases.
+	 */
+	if (video == pipe->output && !pipe->do_propagation)
+		buf->vbuf.sequence = atomic_inc_return(&pipe->frame_number);
+	else
+		buf->vbuf.sequence = atomic_read(&pipe->frame_number);
+
+	buf->state = error ? ISP_BUF_STATE_ERROR : ISP_BUF_STATE_DONE;
+
+	wake_up(&buf->wait);
+
+	if (list_empty(&video->dmaqueue)) {
+		if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+			state = ISP_PIPELINE_QUEUE_OUTPUT
+			      | ISP_PIPELINE_STREAM;
+		else
+			state = ISP_PIPELINE_QUEUE_INPUT
+			      | ISP_PIPELINE_STREAM;
+
+		spin_lock_irqsave(&pipe->lock, flags);
+		pipe->state &= ~state;
+		if (video->pipe.stream_state == ISP_PIPELINE_STREAM_CONTINUOUS)
+			video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
+		spin_unlock_irqrestore(&pipe->lock, flags);
+		return NULL;
+	}
+
+	if (queue->type == V4L2_BUF_TYPE_VIDEO_CAPTURE && pipe->input != NULL) {
+		spin_lock_irqsave(&pipe->lock, flags);
+		pipe->state &= ~ISP_PIPELINE_STREAM;
+		spin_unlock_irqrestore(&pipe->lock, flags);
+	}
+
+	buf = list_first_entry(&video->dmaqueue, struct isp_video_buffer,
+			       irqlist);
+	buf->state = ISP_BUF_STATE_ACTIVE;
+	return to_isp_buffer(buf);
+}
+
+/*
+ * omap3isp_video_resume - Perform resume operation on the buffers
+ * @video: ISP video object
+ * @continuous: Pipeline is in single shot mode if 0 or continuous mode otherwise
+ *
+ * This function is intended to be used on suspend/resume scenario. It
+ * requests video queue layer to discard buffers marked as DONE if it's in
+ * continuous mode and requests ISP modules to queue again the ACTIVE buffer
+ * if there's any.
+ */
+void omap3isp_video_resume(struct isp_video *video, int continuous)
+{
+	struct isp_buffer *buf = NULL;
+
+	if (continuous && video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		omap3isp_video_queue_discard_done(video->queue);
+
+	if (!list_empty(&video->dmaqueue)) {
+		buf = list_first_entry(&video->dmaqueue,
+				       struct isp_buffer, buffer.irqlist);
+		video->ops->queue(video, buf);
+		video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_QUEUED;
+	} else {
+		if (continuous)
+			video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
+	}
+}
+
+/* -----------------------------------------------------------------------------
+ * V4L2 ioctls
+ */
+
+static int
+isp_video_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
+{
+	struct isp_video *video = video_drvdata(file);
+
+	strlcpy(cap->driver, ISP_VIDEO_DRIVER_NAME, sizeof(cap->driver));
+	strlcpy(cap->card, video->video.name, sizeof(cap->card));
+	strlcpy(cap->bus_info, "media", sizeof(cap->bus_info));
+	cap->version = ISP_VIDEO_DRIVER_VERSION;
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+	else
+		cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+
+	return 0;
+}
+
+static int
+isp_video_get_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+
+	if (format->type != video->type)
+		return -EINVAL;
+
+	mutex_lock(&video->mutex);
+	*format = vfh->format;
+	mutex_unlock(&video->mutex);
+
+	return 0;
+}
+
+static int
+isp_video_set_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	struct v4l2_mbus_framefmt fmt;
+
+	if (format->type != video->type)
+		return -EINVAL;
+
+	mutex_lock(&video->mutex);
+
+	/* Fill the bytesperline and sizeimage fields by converting to media bus
+	 * format and back to pixel format.
+	 */
+	isp_video_pix_to_mbus(&format->fmt.pix, &fmt);
+	isp_video_mbus_to_pix(video, &fmt, &format->fmt.pix);
+
+	vfh->format = *format;
+
+	mutex_unlock(&video->mutex);
+	return 0;
+}
+
+static int
+isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
+{
+	struct isp_video *video = video_drvdata(file);
+	struct v4l2_subdev_format fmt;
+	struct v4l2_subdev *subdev;
+	u32 pad;
+	int ret;
+
+	if (format->type != video->type)
+		return -EINVAL;
+
+	subdev = isp_video_remote_subdev(video, &pad);
+	if (subdev == NULL)
+		return -EINVAL;
+
+	isp_video_pix_to_mbus(&format->fmt.pix, &fmt.format);
+
+	fmt.pad = pad;
+	fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
+	if (ret)
+		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+	isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
+	return 0;
+}
+
+static int
+isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
+{
+	struct isp_video *video = video_drvdata(file);
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	subdev = isp_video_remote_subdev(video, NULL);
+	if (subdev == NULL)
+		return -EINVAL;
+
+	mutex_lock(&video->mutex);
+	ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
+	mutex_unlock(&video->mutex);
+
+	return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+}
+
+static int
+isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+	struct isp_video *video = video_drvdata(file);
+	struct v4l2_subdev_format format;
+	struct v4l2_subdev *subdev;
+	u32 pad;
+	int ret;
+
+	subdev = isp_video_remote_subdev(video, &pad);
+	if (subdev == NULL)
+		return -EINVAL;
+
+	/* Try the get crop operation first and fallback to get format if not
+	 * implemented.
+	 */
+	ret = v4l2_subdev_call(subdev, video, g_crop, crop);
+	if (ret != -ENOIOCTLCMD)
+		return ret;
+
+	format.pad = pad;
+	format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+	ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
+	if (ret < 0)
+		return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+
+	crop->c.left = 0;
+	crop->c.top = 0;
+	crop->c.width = format.format.width;
+	crop->c.height = format.format.height;
+
+	return 0;
+}
+
+static int
+isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+{
+	struct isp_video *video = video_drvdata(file);
+	struct v4l2_subdev *subdev;
+	int ret;
+
+	subdev = isp_video_remote_subdev(video, NULL);
+	if (subdev == NULL)
+		return -EINVAL;
+
+	mutex_lock(&video->mutex);
+	ret = v4l2_subdev_call(subdev, video, s_crop, crop);
+	mutex_unlock(&video->mutex);
+
+	return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+}
+
+static int
+isp_video_get_param(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+
+	if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+	    video->type != a->type)
+		return -EINVAL;
+
+	memset(a, 0, sizeof(*a));
+	a->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	a->parm.output.capability = V4L2_CAP_TIMEPERFRAME;
+	a->parm.output.timeperframe = vfh->timeperframe;
+
+	return 0;
+}
+
+static int
+isp_video_set_param(struct file *file, void *fh, struct v4l2_streamparm *a)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+
+	if (video->type != V4L2_BUF_TYPE_VIDEO_OUTPUT ||
+	    video->type != a->type)
+		return -EINVAL;
+
+	if (a->parm.output.timeperframe.denominator == 0)
+		a->parm.output.timeperframe.denominator = 1;
+
+	vfh->timeperframe = a->parm.output.timeperframe;
+
+	return 0;
+}
+
+static int
+isp_video_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+
+	return omap3isp_video_queue_reqbufs(&vfh->queue, rb);
+}
+
+static int
+isp_video_querybuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+
+	return omap3isp_video_queue_querybuf(&vfh->queue, b);
+}
+
+static int
+isp_video_qbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+
+	return omap3isp_video_queue_qbuf(&vfh->queue, b);
+}
+
+static int
+isp_video_dqbuf(struct file *file, void *fh, struct v4l2_buffer *b)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+
+	return omap3isp_video_queue_dqbuf(&vfh->queue, b,
+					  file->f_flags & O_NONBLOCK);
+}
+
+/*
+ * Stream management
+ *
+ * Every ISP pipeline has a single input and a single output. The input can be
+ * either a sensor or a video node. The output is always a video node.
+ *
+ * As every pipeline has an output video node, the ISP video objects at the
+ * pipeline output stores the pipeline state. It tracks the streaming state of
+ * both the input and output, as well as the availability of buffers.
+ *
+ * In sensor-to-memory mode, frames are always available at the pipeline input.
+ * Starting the sensor usually requires I2C transfers and must be done in
+ * interruptible context. The pipeline is started and stopped synchronously
+ * to the stream on/off commands. All modules in the pipeline will get their
+ * subdev set stream handler called. The module at the end of the pipeline must
+ * delay starting the hardware until buffers are available at its output.
+ *
+ * In memory-to-memory mode, starting/stopping the stream requires
+ * synchronization between the input and output. ISP modules can't be stopped
+ * in the middle of a frame, and at least some of the modules seem to become
+ * busy as soon as they're started, even if they don't receive a frame start
+ * event. For that reason frames need to be processed in single-shot mode. The
+ * driver needs to wait until a frame is completely processed and written to
+ * memory before restarting the pipeline for the next frame. Pipelined
+ * processing might be possible but requires more testing.
+ *
+ * Stream start must be delayed until buffers are available at both the input
+ * and output. The pipeline must be started in the videobuf queue callback with
+ * the buffers queue spinlock held. The modules subdev set stream operation must
+ * not sleep.
+ */
+static int
+isp_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	enum isp_pipeline_state state;
+	struct isp_pipeline *pipe;
+	struct isp_video *far_end;
+	unsigned long flags;
+	int ret;
+
+	if (type != video->type)
+		return -EINVAL;
+
+	mutex_lock(&video->stream_lock);
+
+	if (video->streaming) {
+		mutex_unlock(&video->stream_lock);
+		return -EBUSY;
+	}
+
+	/* Start streaming on the pipeline. No link touching an entity in the
+	 * pipeline can be activated or deactivated once streaming is started.
+	 */
+	pipe = video->video.entity.pipe
+	     ? to_isp_pipeline(&video->video.entity) : &video->pipe;
+	media_entity_pipeline_start(&video->video.entity, &pipe->pipe);
+
+	/* Verify that the currently configured format matches the output of
+	 * the connected subdev.
+	 */
+	ret = isp_video_check_format(video, vfh);
+	if (ret < 0)
+		goto error;
+
+	video->bpl_padding = ret;
+	video->bpl_value = vfh->format.fmt.pix.bytesperline;
+
+	/* Find the ISP video node connected at the far end of the pipeline and
+	 * update the pipeline.
+	 */
+	far_end = isp_video_far_end(video);
+
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		state = ISP_PIPELINE_STREAM_OUTPUT | ISP_PIPELINE_IDLE_OUTPUT;
+		pipe->input = far_end;
+		pipe->output = video;
+	} else {
+		if (far_end == NULL) {
+			ret = -EPIPE;
+			goto error;
+		}
+
+		state = ISP_PIPELINE_STREAM_INPUT | ISP_PIPELINE_IDLE_INPUT;
+		pipe->input = video;
+		pipe->output = far_end;
+	}
+
+	if (video->isp->pdata->set_constraints)
+		video->isp->pdata->set_constraints(video->isp, true);
+	pipe->l3_ick = clk_get_rate(video->isp->clock[ISP_CLK_L3_ICK]);
+
+	/* Validate the pipeline and update its state. */
+	ret = isp_video_validate_pipeline(pipe);
+	if (ret < 0)
+		goto error;
+
+	spin_lock_irqsave(&pipe->lock, flags);
+	pipe->state &= ~ISP_PIPELINE_STREAM;
+	pipe->state |= state;
+	spin_unlock_irqrestore(&pipe->lock, flags);
+
+	/* Set the maximum time per frame as the value requested by userspace.
+	 * This is a soft limit that can be overridden if the hardware doesn't
+	 * support the request limit.
+	 */
+	if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		pipe->max_timeperframe = vfh->timeperframe;
+
+	video->queue = &vfh->queue;
+	INIT_LIST_HEAD(&video->dmaqueue);
+	atomic_set(&pipe->frame_number, -1);
+
+	ret = omap3isp_video_queue_streamon(&vfh->queue);
+	if (ret < 0)
+		goto error;
+
+	/* In sensor-to-memory mode, the stream can be started synchronously
+	 * to the stream on command. In memory-to-memory mode, it will be
+	 * started when buffers are queued on both the input and output.
+	 */
+	if (pipe->input == NULL) {
+		ret = omap3isp_pipeline_set_stream(pipe,
+					      ISP_PIPELINE_STREAM_CONTINUOUS);
+		if (ret < 0)
+			goto error;
+		spin_lock_irqsave(&video->queue->irqlock, flags);
+		if (list_empty(&video->dmaqueue))
+			video->dmaqueue_flags |= ISP_VIDEO_DMAQUEUE_UNDERRUN;
+		spin_unlock_irqrestore(&video->queue->irqlock, flags);
+	}
+
+error:
+	if (ret < 0) {
+		omap3isp_video_queue_streamoff(&vfh->queue);
+		if (video->isp->pdata->set_constraints)
+			video->isp->pdata->set_constraints(video->isp, false);
+		media_entity_pipeline_stop(&video->video.entity);
+		video->queue = NULL;
+	}
+
+	if (!ret)
+		video->streaming = 1;
+
+	mutex_unlock(&video->stream_lock);
+	return ret;
+}
+
+static int
+isp_video_streamoff(struct file *file, void *fh, enum v4l2_buf_type type)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(fh);
+	struct isp_video *video = video_drvdata(file);
+	struct isp_pipeline *pipe = to_isp_pipeline(&video->video.entity);
+	enum isp_pipeline_state state;
+	unsigned int streaming;
+	unsigned long flags;
+
+	if (type != video->type)
+		return -EINVAL;
+
+	mutex_lock(&video->stream_lock);
+
+	/* Make sure we're not streaming yet. */
+	mutex_lock(&vfh->queue.lock);
+	streaming = vfh->queue.streaming;
+	mutex_unlock(&vfh->queue.lock);
+
+	if (!streaming)
+		goto done;
+
+	/* Update the pipeline state. */
+	if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		state = ISP_PIPELINE_STREAM_OUTPUT
+		      | ISP_PIPELINE_QUEUE_OUTPUT;
+	else
+		state = ISP_PIPELINE_STREAM_INPUT
+		      | ISP_PIPELINE_QUEUE_INPUT;
+
+	spin_lock_irqsave(&pipe->lock, flags);
+	pipe->state &= ~state;
+	spin_unlock_irqrestore(&pipe->lock, flags);
+
+	/* Stop the stream. */
+	omap3isp_pipeline_set_stream(pipe, ISP_PIPELINE_STREAM_STOPPED);
+	omap3isp_video_queue_streamoff(&vfh->queue);
+	video->queue = NULL;
+	video->streaming = 0;
+
+	if (video->isp->pdata->set_constraints)
+		video->isp->pdata->set_constraints(video->isp, false);
+	media_entity_pipeline_stop(&video->video.entity);
+
+done:
+	mutex_unlock(&video->stream_lock);
+	return 0;
+}
+
+static int
+isp_video_enum_input(struct file *file, void *fh, struct v4l2_input *input)
+{
+	if (input->index > 0)
+		return -EINVAL;
+
+	strlcpy(input->name, "camera", sizeof(input->name));
+	input->type = V4L2_INPUT_TYPE_CAMERA;
+
+	return 0;
+}
+
+static int
+isp_video_g_input(struct file *file, void *fh, unsigned int *input)
+{
+	*input = 0;
+
+	return 0;
+}
+
+static int
+isp_video_s_input(struct file *file, void *fh, unsigned int input)
+{
+	return input == 0 ? 0 : -EINVAL;
+}
+
+static const struct v4l2_ioctl_ops isp_video_ioctl_ops = {
+	.vidioc_querycap		= isp_video_querycap,
+	.vidioc_g_fmt_vid_cap		= isp_video_get_format,
+	.vidioc_s_fmt_vid_cap		= isp_video_set_format,
+	.vidioc_try_fmt_vid_cap		= isp_video_try_format,
+	.vidioc_g_fmt_vid_out		= isp_video_get_format,
+	.vidioc_s_fmt_vid_out		= isp_video_set_format,
+	.vidioc_try_fmt_vid_out		= isp_video_try_format,
+	.vidioc_cropcap			= isp_video_cropcap,
+	.vidioc_g_crop			= isp_video_get_crop,
+	.vidioc_s_crop			= isp_video_set_crop,
+	.vidioc_g_parm			= isp_video_get_param,
+	.vidioc_s_parm			= isp_video_set_param,
+	.vidioc_reqbufs			= isp_video_reqbufs,
+	.vidioc_querybuf		= isp_video_querybuf,
+	.vidioc_qbuf			= isp_video_qbuf,
+	.vidioc_dqbuf			= isp_video_dqbuf,
+	.vidioc_streamon		= isp_video_streamon,
+	.vidioc_streamoff		= isp_video_streamoff,
+	.vidioc_enum_input		= isp_video_enum_input,
+	.vidioc_g_input			= isp_video_g_input,
+	.vidioc_s_input			= isp_video_s_input,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 file operations
+ */
+
+static int isp_video_open(struct file *file)
+{
+	struct isp_video *video = video_drvdata(file);
+	struct isp_video_fh *handle;
+	int ret = 0;
+
+	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
+	if (handle == NULL)
+		return -ENOMEM;
+
+	v4l2_fh_init(&handle->vfh, &video->video);
+	v4l2_fh_add(&handle->vfh);
+
+	/* If this is the first user, initialise the pipeline. */
+	if (omap3isp_get(video->isp) == NULL) {
+		ret = -EBUSY;
+		goto done;
+	}
+
+	ret = omap3isp_pipeline_pm_use(&video->video.entity, 1);
+	if (ret < 0) {
+		omap3isp_put(video->isp);
+		goto done;
+	}
+
+	omap3isp_video_queue_init(&handle->queue, video->type,
+				  &isp_video_queue_ops, video->isp->dev,
+				  sizeof(struct isp_buffer));
+
+	memset(&handle->format, 0, sizeof(handle->format));
+	handle->format.type = video->type;
+	handle->timeperframe.denominator = 1;
+
+	handle->video = video;
+	file->private_data = &handle->vfh;
+
+done:
+	if (ret < 0) {
+		v4l2_fh_del(&handle->vfh);
+		kfree(handle);
+	}
+
+	return ret;
+}
+
+static int isp_video_release(struct file *file)
+{
+	struct isp_video *video = video_drvdata(file);
+	struct v4l2_fh *vfh = file->private_data;
+	struct isp_video_fh *handle = to_isp_video_fh(vfh);
+
+	/* Disable streaming and free the buffers queue resources. */
+	isp_video_streamoff(file, vfh, video->type);
+
+	mutex_lock(&handle->queue.lock);
+	omap3isp_video_queue_cleanup(&handle->queue);
+	mutex_unlock(&handle->queue.lock);
+
+	omap3isp_pipeline_pm_use(&video->video.entity, 0);
+
+	/* Release the file handle. */
+	v4l2_fh_del(vfh);
+	kfree(handle);
+	file->private_data = NULL;
+
+	omap3isp_put(video->isp);
+
+	return 0;
+}
+
+static unsigned int isp_video_poll(struct file *file, poll_table *wait)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
+	struct isp_video_queue *queue = &vfh->queue;
+
+	return omap3isp_video_queue_poll(queue, file, wait);
+}
+
+static int isp_video_mmap(struct file *file, struct vm_area_struct *vma)
+{
+	struct isp_video_fh *vfh = to_isp_video_fh(file->private_data);
+
+	return omap3isp_video_queue_mmap(&vfh->queue, vma);
+}
+
+static struct v4l2_file_operations isp_video_fops = {
+	.owner = THIS_MODULE,
+	.unlocked_ioctl = video_ioctl2,
+	.open = isp_video_open,
+	.release = isp_video_release,
+	.poll = isp_video_poll,
+	.mmap = isp_video_mmap,
+};
+
+/* -----------------------------------------------------------------------------
+ * ISP video core
+ */
+
+static const struct isp_video_operations isp_video_dummy_ops = {
+};
+
+int omap3isp_video_init(struct isp_video *video, const char *name)
+{
+	const char *direction;
+	int ret;
+
+	switch (video->type) {
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+		direction = "output";
+		video->pad.flags = MEDIA_PAD_FL_SINK;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+		direction = "input";
+		video->pad.flags = MEDIA_PAD_FL_SOURCE;
+		break;
+
+	default:
+		return -EINVAL;
+	}
+
+	ret = media_entity_init(&video->video.entity, 1, &video->pad, 0);
+	if (ret < 0)
+		return ret;
+
+	mutex_init(&video->mutex);
+	atomic_set(&video->active, 0);
+
+	spin_lock_init(&video->pipe.lock);
+	mutex_init(&video->stream_lock);
+
+	/* Initialize the video device. */
+	if (video->ops == NULL)
+		video->ops = &isp_video_dummy_ops;
+
+	video->video.fops = &isp_video_fops;
+	snprintf(video->video.name, sizeof(video->video.name),
+		 "OMAP3 ISP %s %s", name, direction);
+	video->video.vfl_type = VFL_TYPE_GRABBER;
+	video->video.release = video_device_release_empty;
+	video->video.ioctl_ops = &isp_video_ioctl_ops;
+	video->pipe.stream_state = ISP_PIPELINE_STREAM_STOPPED;
+
+	video_set_drvdata(&video->video, video);
+
+	return 0;
+}
+
+int omap3isp_video_register(struct isp_video *video, struct v4l2_device *vdev)
+{
+	int ret;
+
+	video->video.v4l2_dev = vdev;
+
+	ret = video_register_device(&video->video, VFL_TYPE_GRABBER, -1);
+	if (ret < 0)
+		printk(KERN_ERR "%s: could not register video device (%d)\n",
+			__func__, ret);
+
+	return ret;
+}
+
+void omap3isp_video_unregister(struct isp_video *video)
+{
+	if (video_is_registered(&video->video)) {
+		media_entity_cleanup(&video->video.entity);
+		video_unregister_device(&video->video);
+	}
+}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispvideo.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispvideo.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/ispvideo.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/ispvideo.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,205 @@
+/*
+ * ispvideo.h
+ *
+ * TI OMAP3 ISP - Generic video node
+ *
+ * Copyright (C) 2009-2010 Nokia Corporation
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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 OMAP3_ISP_VIDEO_H
+#define OMAP3_ISP_VIDEO_H
+
+#include <linux/v4l2-mediabus.h>
+#include <linux/version.h>
+#include <media/media-entity.h>
+#include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+
+#include "ispqueue.h"
+
+#define ISP_VIDEO_DRIVER_NAME		"ispvideo"
+#define ISP_VIDEO_DRIVER_VERSION	KERNEL_VERSION(0, 0, 1)
+
+struct isp_device;
+struct isp_video;
+struct v4l2_mbus_framefmt;
+struct v4l2_pix_format;
+
+/*
+ * struct isp_format_info - ISP media bus format information
+ * @code: V4L2 media bus format code
+ * @truncated: V4L2 media bus format code for the same format truncated to 10
+ *	bits. Identical to @code if the format is 10 bits wide or less.
+ * @uncompressed: V4L2 media bus format code for the corresponding uncompressed
+ *	format. Identical to @code if the format is not DPCM compressed.
+ * @flavor: V4L2 media bus format code for the same pixel layout but
+ *	shifted to be 8 bits per pixel. =0 if format is not shiftable.
+ * @pixelformat: V4L2 pixel format FCC identifier
+ * @bpp: Bits per pixel
+ */
+struct isp_format_info {
+	enum v4l2_mbus_pixelcode code;
+	enum v4l2_mbus_pixelcode truncated;
+	enum v4l2_mbus_pixelcode uncompressed;
+	enum v4l2_mbus_pixelcode flavor;
+	u32 pixelformat;
+	unsigned int bpp;
+};
+
+enum isp_pipeline_stream_state {
+	ISP_PIPELINE_STREAM_STOPPED = 0,
+	ISP_PIPELINE_STREAM_CONTINUOUS = 1,
+	ISP_PIPELINE_STREAM_SINGLESHOT = 2,
+};
+
+enum isp_pipeline_state {
+	/* The stream has been started on the input video node. */
+	ISP_PIPELINE_STREAM_INPUT = 1,
+	/* The stream has been started on the output video node. */
+	ISP_PIPELINE_STREAM_OUTPUT = 2,
+	/* At least one buffer is queued on the input video node. */
+	ISP_PIPELINE_QUEUE_INPUT = 4,
+	/* At least one buffer is queued on the output video node. */
+	ISP_PIPELINE_QUEUE_OUTPUT = 8,
+	/* The input entity is idle, ready to be started. */
+	ISP_PIPELINE_IDLE_INPUT = 16,
+	/* The output entity is idle, ready to be started. */
+	ISP_PIPELINE_IDLE_OUTPUT = 32,
+	/* The pipeline is currently streaming. */
+	ISP_PIPELINE_STREAM = 64,
+};
+
+struct isp_pipeline {
+	struct media_pipeline pipe;
+	spinlock_t lock;		/* Pipeline state and queue flags */
+	unsigned int state;
+	enum isp_pipeline_stream_state stream_state;
+	struct isp_video *input;
+	struct isp_video *output;
+	unsigned long l3_ick;
+	unsigned int max_rate;
+	atomic_t frame_number;
+	bool do_propagation; /* of frame number */
+	struct v4l2_fract max_timeperframe;
+};
+
+#define to_isp_pipeline(__e) \
+	container_of((__e)->pipe, struct isp_pipeline, pipe)
+
+static inline int isp_pipeline_ready(struct isp_pipeline *pipe)
+{
+	return pipe->state == (ISP_PIPELINE_STREAM_INPUT |
+			       ISP_PIPELINE_STREAM_OUTPUT |
+			       ISP_PIPELINE_QUEUE_INPUT |
+			       ISP_PIPELINE_QUEUE_OUTPUT |
+			       ISP_PIPELINE_IDLE_INPUT |
+			       ISP_PIPELINE_IDLE_OUTPUT);
+}
+
+/*
+ * struct isp_buffer - ISP buffer
+ * @buffer: ISP video buffer
+ * @isp_addr: MMU mapped address (a.k.a. device address) of the buffer.
+ */
+struct isp_buffer {
+	struct isp_video_buffer buffer;
+	dma_addr_t isp_addr;
+};
+
+#define to_isp_buffer(buf)	container_of(buf, struct isp_buffer, buffer)
+
+enum isp_video_dmaqueue_flags {
+	/* Set if DMA queue becomes empty when ISP_PIPELINE_STREAM_CONTINUOUS */
+	ISP_VIDEO_DMAQUEUE_UNDERRUN = (1 << 0),
+	/* Set when queuing buffer to an empty DMA queue */
+	ISP_VIDEO_DMAQUEUE_QUEUED = (1 << 1),
+};
+
+#define isp_video_dmaqueue_flags_clr(video)	\
+			({ (video)->dmaqueue_flags = 0; })
+
+/*
+ * struct isp_video_operations - ISP video operations
+ * @queue:	Resume streaming when a buffer is queued. Called on VIDIOC_QBUF
+ *		if there was no buffer previously queued.
+ */
+struct isp_video_operations {
+	int(*queue)(struct isp_video *video, struct isp_buffer *buffer);
+};
+
+struct isp_video {
+	struct video_device video;
+	enum v4l2_buf_type type;
+	struct media_pad pad;
+
+	struct mutex mutex;		/* format and crop settings */
+	atomic_t active;
+
+	struct isp_device *isp;
+
+	unsigned int capture_mem;
+	unsigned int bpl_alignment;	/* alignment value */
+	unsigned int bpl_zero_padding;	/* whether the alignment is optional */
+	unsigned int bpl_max;		/* maximum bytes per line value */
+	unsigned int bpl_value;		/* bytes per line value */
+	unsigned int bpl_padding;	/* padding at end of line */
+
+	/* Entity video node streaming */
+	unsigned int streaming:1;
+
+	/* Pipeline state */
+	struct isp_pipeline pipe;
+	struct mutex stream_lock;	/* pipeline and stream states */
+
+	/* Video buffers queue */
+	struct isp_video_queue *queue;
+	struct list_head dmaqueue;
+	enum isp_video_dmaqueue_flags dmaqueue_flags;
+
+	const struct isp_video_operations *ops;
+};
+
+#define to_isp_video(vdev)	container_of(vdev, struct isp_video, video)
+
+struct isp_video_fh {
+	struct v4l2_fh vfh;
+	struct isp_video *video;
+	struct isp_video_queue queue;
+	struct v4l2_format format;
+	struct v4l2_fract timeperframe;
+};
+
+#define to_isp_video_fh(fh)	container_of(fh, struct isp_video_fh, vfh)
+#define isp_video_queue_to_isp_video_fh(q) \
+				container_of(q, struct isp_video_fh, queue)
+
+int omap3isp_video_init(struct isp_video *video, const char *name);
+int omap3isp_video_register(struct isp_video *video,
+			    struct v4l2_device *vdev);
+void omap3isp_video_unregister(struct isp_video *video);
+struct isp_buffer *omap3isp_video_buffer_next(struct isp_video *video,
+					      unsigned int error);
+void omap3isp_video_resume(struct isp_video *video, int continuous);
+struct media_pad *omap3isp_video_remote_pad(struct isp_video *video);
+
+const struct isp_format_info *
+omap3isp_video_format_info(enum v4l2_mbus_pixelcode code);
+
+#endif /* OMAP3_ISP_VIDEO_H */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/luma_enhance_table.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/luma_enhance_table.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/luma_enhance_table.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/luma_enhance_table.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,42 @@
+/*
+ * luma_enhance_table.h
+ *
+ * TI OMAP3 ISP - Luminance enhancement table
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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
+ */
+
+1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
+1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
+1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552, 1047552,
+1047552, 1047552, 1047552, 1047552, 1048575, 1047551, 1046527, 1045503,
+1044479, 1043455, 1042431, 1041407, 1040383, 1039359, 1038335, 1037311,
+1036287, 1035263, 1034239, 1033215, 1032191, 1031167, 1030143, 1028096,
+1028096, 1028096, 1028096, 1028096, 1028096, 1028096, 1028096, 1028096,
+1028096, 1028100, 1032196, 1036292, 1040388, 1044484,       0,       0,
+      0,       5,    5125,   10245,   15365,   20485,   25605,   30720,
+  30720,   30720,   30720,   30720,   30720,   30720,   30720,   30720,
+  30720,   30720,   31743,   30719,   29695,   28671,   27647,   26623,
+  25599,   24575,   23551,   22527,   21503,   20479,   19455,   18431,
+  17407,   16383,   15359,   14335,   13311,   12287,   11263,   10239,
+   9215,    8191,    7167,    6143,    5119,    4095,    3071,    1024,
+   1024,    1024,    1024,    1024,    1024,    1024,    1024,    1024,
+   1024,    1024,    1024,    1024,    1024,    1024,    1024,    1024
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/Makefile linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/Makefile
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,13 @@
+# Makefile for OMAP3 ISP driver
+
+ifdef CONFIG_VIDEO_OMAP3_DEBUG
+EXTRA_CFLAGS += -DDEBUG
+endif
+
+omap3-isp-objs += \
+	isp.o ispqueue.o ispvideo.o \
+	ispcsiphy.o ispccp2.o ispcsi2.o \
+	ispccdc.o isppreview.o ispresizer.o \
+	ispstat.o isph3a_aewb.o isph3a_af.o isphist.o
+
+obj-$(CONFIG_VIDEO_OMAP3) += omap3-isp.o
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/noise_filter_table.h linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/noise_filter_table.h
--- linux-libre-2.6.38-gnu/drivers/media/video/omap3isp/noise_filter_table.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/omap3isp/noise_filter_table.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,30 @@
+/*
+ * noise_filter_table.h
+ *
+ * TI OMAP3 ISP - Noise filter table
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2009 Texas Instruments, Inc.
+ *
+ * Contacts: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	     Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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
+ */
+
+16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16,
+31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31,
+31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ov6650.c linux-libre-2.6.39-gnu/drivers/media/video/ov6650.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ov6650.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ov6650.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,7 +207,7 @@
 	V4L2_MBUS_FMT_YVYU8_2X8,
 	V4L2_MBUS_FMT_VYUY8_2X8,
 	V4L2_MBUS_FMT_SBGGR8_1X8,
-	V4L2_MBUS_FMT_GREY8_1X8,
+	V4L2_MBUS_FMT_Y8_1X8,
 };
 
 static const struct v4l2_queryctrl ov6650_controls[] = {
@@ -800,7 +800,7 @@
 
 	/* select color matrix configuration for given color encoding */
 	switch (code) {
-	case V4L2_MBUS_FMT_GREY8_1X8:
+	case V4L2_MBUS_FMT_Y8_1X8:
 		dev_dbg(&client->dev, "pixel format GREY8_1X8\n");
 		coma_mask |= COMA_RGB | COMA_WORD_SWAP | COMA_BYTE_SWAP;
 		coma_set |= COMA_BW;
@@ -846,7 +846,7 @@
 	}
 	priv->code = code;
 
-	if (code == V4L2_MBUS_FMT_GREY8_1X8 ||
+	if (code == V4L2_MBUS_FMT_Y8_1X8 ||
 			code == V4L2_MBUS_FMT_SBGGR8_1X8) {
 		coml_mask = COML_ONE_CHANNEL;
 		coml_set = 0;
@@ -936,8 +936,8 @@
 
 	switch (mf->code) {
 	case V4L2_MBUS_FMT_Y10_1X10:
-		mf->code = V4L2_MBUS_FMT_GREY8_1X8;
-	case V4L2_MBUS_FMT_GREY8_1X8:
+		mf->code = V4L2_MBUS_FMT_Y8_1X8;
+	case V4L2_MBUS_FMT_Y8_1X8:
 	case V4L2_MBUS_FMT_YVYU8_2X8:
 	case V4L2_MBUS_FMT_YUYV8_2X8:
 	case V4L2_MBUS_FMT_VYUY8_2X8:
@@ -1038,7 +1038,7 @@
 	ret = ov6650_reg_rmw(client, REG_COMA, COMA_RESET, 0);
 	if (ret)
 		dev_err(&client->dev,
-			"An error occured while entering soft reset!\n");
+			"An error occurred while entering soft reset!\n");
 
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ov9640.c linux-libre-2.6.39-gnu/drivers/media/video/ov9640.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ov9640.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/ov9640.c	2011-05-19 00:06:34.000000000 -0400
@@ -273,7 +273,7 @@
 	ret = ov9640_reg_write(client, OV9640_COM7, OV9640_COM7_SCCB_RESET);
 	if (ret)
 		dev_err(&client->dev,
-			"An error occured while entering soft reset!\n");
+			"An error occurred while entering soft reset!\n");
 
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/ov9740.c linux-libre-2.6.39-gnu/drivers/media/video/ov9740.c
--- linux-libre-2.6.38-gnu/drivers/media/video/ov9740.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/ov9740.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1009 @@
+/*
+ * OmniVision OV9740 Camera Driver
+ *
+ * Copyright (C) 2011 NVIDIA Corporation
+ *
+ * Based on ov9640 camera driver.
+ *
+ * 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/module.h>
+#include <linux/i2c.h>
+#include <linux/slab.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/soc_camera.h>
+
+#define to_ov9740(sd)		container_of(sd, struct ov9740_priv, subdev)
+
+/* General Status Registers */
+#define OV9740_MODEL_ID_HI		0x0000
+#define OV9740_MODEL_ID_LO		0x0001
+#define OV9740_REVISION_NUMBER		0x0002
+#define OV9740_MANUFACTURER_ID		0x0003
+#define OV9740_SMIA_VERSION		0x0004
+
+/* General Setup Registers */
+#define OV9740_MODE_SELECT		0x0100
+#define OV9740_IMAGE_ORT		0x0101
+#define OV9740_SOFTWARE_RESET		0x0103
+#define OV9740_GRP_PARAM_HOLD		0x0104
+#define OV9740_MSK_CORRUP_FM		0x0105
+
+/* Timing Setting */
+#define OV9740_FRM_LENGTH_LN_HI		0x0340 /* VTS */
+#define OV9740_FRM_LENGTH_LN_LO		0x0341 /* VTS */
+#define OV9740_LN_LENGTH_PCK_HI		0x0342 /* HTS */
+#define OV9740_LN_LENGTH_PCK_LO		0x0343 /* HTS */
+#define OV9740_X_ADDR_START_HI		0x0344
+#define OV9740_X_ADDR_START_LO		0x0345
+#define OV9740_Y_ADDR_START_HI		0x0346
+#define OV9740_Y_ADDR_START_LO		0x0347
+#define OV9740_X_ADDR_END_HI		0x0348
+#define OV9740_X_ADDR_END_LO		0x0349
+#define OV9740_Y_ADDR_END_HI		0x034A
+#define OV9740_Y_ADDR_END_LO		0x034B
+#define OV9740_X_OUTPUT_SIZE_HI		0x034C
+#define OV9740_X_OUTPUT_SIZE_LO		0x034D
+#define OV9740_Y_OUTPUT_SIZE_HI		0x034E
+#define OV9740_Y_OUTPUT_SIZE_LO		0x034F
+
+/* IO Control Registers */
+#define OV9740_IO_CREL00		0x3002
+#define OV9740_IO_CREL01		0x3004
+#define OV9740_IO_CREL02		0x3005
+#define OV9740_IO_OUTPUT_SEL01		0x3026
+#define OV9740_IO_OUTPUT_SEL02		0x3027
+
+/* AWB Registers */
+#define OV9740_AWB_MANUAL_CTRL		0x3406
+
+/* Analog Control Registers */
+#define OV9740_ANALOG_CTRL01		0x3601
+#define OV9740_ANALOG_CTRL02		0x3602
+#define OV9740_ANALOG_CTRL03		0x3603
+#define OV9740_ANALOG_CTRL04		0x3604
+#define OV9740_ANALOG_CTRL10		0x3610
+#define OV9740_ANALOG_CTRL12		0x3612
+#define OV9740_ANALOG_CTRL20		0x3620
+#define OV9740_ANALOG_CTRL21		0x3621
+#define OV9740_ANALOG_CTRL22		0x3622
+#define OV9740_ANALOG_CTRL30		0x3630
+#define OV9740_ANALOG_CTRL31		0x3631
+#define OV9740_ANALOG_CTRL32		0x3632
+#define OV9740_ANALOG_CTRL33		0x3633
+
+/* Sensor Control */
+#define OV9740_SENSOR_CTRL03		0x3703
+#define OV9740_SENSOR_CTRL04		0x3704
+#define OV9740_SENSOR_CTRL05		0x3705
+#define OV9740_SENSOR_CTRL07		0x3707
+
+/* Timing Control */
+#define OV9740_TIMING_CTRL17		0x3817
+#define OV9740_TIMING_CTRL19		0x3819
+#define OV9740_TIMING_CTRL33		0x3833
+#define OV9740_TIMING_CTRL35		0x3835
+
+/* Banding Filter */
+#define OV9740_AEC_MAXEXPO_60_H		0x3A02
+#define OV9740_AEC_MAXEXPO_60_L		0x3A03
+#define OV9740_AEC_B50_STEP_HI		0x3A08
+#define OV9740_AEC_B50_STEP_LO		0x3A09
+#define OV9740_AEC_B60_STEP_HI		0x3A0A
+#define OV9740_AEC_B60_STEP_LO		0x3A0B
+#define OV9740_AEC_CTRL0D		0x3A0D
+#define OV9740_AEC_CTRL0E		0x3A0E
+#define OV9740_AEC_MAXEXPO_50_H		0x3A14
+#define OV9740_AEC_MAXEXPO_50_L		0x3A15
+
+/* AEC/AGC Control */
+#define OV9740_AEC_ENABLE		0x3503
+#define OV9740_GAIN_CEILING_01		0x3A18
+#define OV9740_GAIN_CEILING_02		0x3A19
+#define OV9740_AEC_HI_THRESHOLD		0x3A11
+#define OV9740_AEC_3A1A			0x3A1A
+#define OV9740_AEC_CTRL1B_WPT2		0x3A1B
+#define OV9740_AEC_CTRL0F_WPT		0x3A0F
+#define OV9740_AEC_CTRL10_BPT		0x3A10
+#define OV9740_AEC_CTRL1E_BPT2		0x3A1E
+#define OV9740_AEC_LO_THRESHOLD		0x3A1F
+
+/* BLC Control */
+#define OV9740_BLC_AUTO_ENABLE		0x4002
+#define OV9740_BLC_MODE			0x4005
+
+/* VFIFO */
+#define OV9740_VFIFO_READ_START_HI	0x4608
+#define OV9740_VFIFO_READ_START_LO	0x4609
+
+/* DVP Control */
+#define OV9740_DVP_VSYNC_CTRL02		0x4702
+#define OV9740_DVP_VSYNC_MODE		0x4704
+#define OV9740_DVP_VSYNC_CTRL06		0x4706
+
+/* PLL Setting */
+#define OV9740_PLL_MODE_CTRL01		0x3104
+#define OV9740_PRE_PLL_CLK_DIV		0x0305
+#define OV9740_PLL_MULTIPLIER		0x0307
+#define OV9740_VT_SYS_CLK_DIV		0x0303
+#define OV9740_VT_PIX_CLK_DIV		0x0301
+#define OV9740_PLL_CTRL3010		0x3010
+#define OV9740_VFIFO_CTRL00		0x460E
+
+/* ISP Control */
+#define OV9740_ISP_CTRL00		0x5000
+#define OV9740_ISP_CTRL01		0x5001
+#define OV9740_ISP_CTRL03		0x5003
+#define OV9740_ISP_CTRL05		0x5005
+#define OV9740_ISP_CTRL12		0x5012
+#define OV9740_ISP_CTRL19		0x5019
+#define OV9740_ISP_CTRL1A		0x501A
+#define OV9740_ISP_CTRL1E		0x501E
+#define OV9740_ISP_CTRL1F		0x501F
+#define OV9740_ISP_CTRL20		0x5020
+#define OV9740_ISP_CTRL21		0x5021
+
+/* AWB */
+#define OV9740_AWB_CTRL00		0x5180
+#define OV9740_AWB_CTRL01		0x5181
+#define OV9740_AWB_CTRL02		0x5182
+#define OV9740_AWB_CTRL03		0x5183
+#define OV9740_AWB_ADV_CTRL01		0x5184
+#define OV9740_AWB_ADV_CTRL02		0x5185
+#define OV9740_AWB_ADV_CTRL03		0x5186
+#define OV9740_AWB_ADV_CTRL04		0x5187
+#define OV9740_AWB_ADV_CTRL05		0x5188
+#define OV9740_AWB_ADV_CTRL06		0x5189
+#define OV9740_AWB_ADV_CTRL07		0x518A
+#define OV9740_AWB_ADV_CTRL08		0x518B
+#define OV9740_AWB_ADV_CTRL09		0x518C
+#define OV9740_AWB_ADV_CTRL10		0x518D
+#define OV9740_AWB_ADV_CTRL11		0x518E
+#define OV9740_AWB_CTRL0F		0x518F
+#define OV9740_AWB_CTRL10		0x5190
+#define OV9740_AWB_CTRL11		0x5191
+#define OV9740_AWB_CTRL12		0x5192
+#define OV9740_AWB_CTRL13		0x5193
+#define OV9740_AWB_CTRL14		0x5194
+
+/* MIPI Control */
+#define OV9740_MIPI_CTRL00		0x4800
+#define OV9740_MIPI_3837		0x3837
+#define OV9740_MIPI_CTRL01		0x4801
+#define OV9740_MIPI_CTRL03		0x4803
+#define OV9740_MIPI_CTRL05		0x4805
+#define OV9740_VFIFO_RD_CTRL		0x4601
+#define OV9740_MIPI_CTRL_3012		0x3012
+#define OV9740_SC_CMMM_MIPI_CTR		0x3014
+
+/* supported resolutions */
+enum {
+	OV9740_VGA,
+	OV9740_720P,
+};
+
+struct ov9740_resolution {
+	unsigned int width;
+	unsigned int height;
+};
+
+static struct ov9740_resolution ov9740_resolutions[] = {
+	[OV9740_VGA] = {
+		.width	= 640,
+		.height	= 480,
+	},
+	[OV9740_720P] = {
+		.width	= 1280,
+		.height	= 720,
+	},
+};
+
+/* Misc. structures */
+struct ov9740_reg {
+	u16				reg;
+	u8				val;
+};
+
+struct ov9740_priv {
+	struct v4l2_subdev		subdev;
+
+	int				ident;
+	u16				model;
+	u8				revision;
+	u8				manid;
+	u8				smiaver;
+
+	bool				flag_vflip;
+	bool				flag_hflip;
+};
+
+static const struct ov9740_reg ov9740_defaults[] = {
+	/* Banding Filter */
+	{ OV9740_AEC_B50_STEP_HI,	0x00 },
+	{ OV9740_AEC_B50_STEP_LO,	0xe8 },
+	{ OV9740_AEC_CTRL0E,		0x03 },
+	{ OV9740_AEC_MAXEXPO_50_H,	0x15 },
+	{ OV9740_AEC_MAXEXPO_50_L,	0xc6 },
+	{ OV9740_AEC_B60_STEP_HI,	0x00 },
+	{ OV9740_AEC_B60_STEP_LO,	0xc0 },
+	{ OV9740_AEC_CTRL0D,		0x04 },
+	{ OV9740_AEC_MAXEXPO_60_H,	0x18 },
+	{ OV9740_AEC_MAXEXPO_60_L,	0x20 },
+
+	/* LC */
+	{ 0x5842, 0x02 }, { 0x5843, 0x5e }, { 0x5844, 0x04 }, { 0x5845, 0x32 },
+	{ 0x5846, 0x03 }, { 0x5847, 0x29 }, { 0x5848, 0x02 }, { 0x5849, 0xcc },
+
+	/* Un-documented OV9740 registers */
+	{ 0x5800, 0x29 }, { 0x5801, 0x25 }, { 0x5802, 0x20 }, { 0x5803, 0x21 },
+	{ 0x5804, 0x26 }, { 0x5805, 0x2e }, { 0x5806, 0x11 }, { 0x5807, 0x0c },
+	{ 0x5808, 0x09 }, { 0x5809, 0x0a }, { 0x580A, 0x0e }, { 0x580B, 0x16 },
+	{ 0x580C, 0x06 }, { 0x580D, 0x02 }, { 0x580E, 0x00 }, { 0x580F, 0x00 },
+	{ 0x5810, 0x04 }, { 0x5811, 0x0a }, { 0x5812, 0x05 }, { 0x5813, 0x02 },
+	{ 0x5814, 0x00 }, { 0x5815, 0x00 }, { 0x5816, 0x03 }, { 0x5817, 0x09 },
+	{ 0x5818, 0x0f }, { 0x5819, 0x0a }, { 0x581A, 0x07 }, { 0x581B, 0x08 },
+	{ 0x581C, 0x0b }, { 0x581D, 0x14 }, { 0x581E, 0x28 }, { 0x581F, 0x23 },
+	{ 0x5820, 0x1d }, { 0x5821, 0x1e }, { 0x5822, 0x24 }, { 0x5823, 0x2a },
+	{ 0x5824, 0x4f }, { 0x5825, 0x6f }, { 0x5826, 0x5f }, { 0x5827, 0x7f },
+	{ 0x5828, 0x9f }, { 0x5829, 0x5f }, { 0x582A, 0x8f }, { 0x582B, 0x9e },
+	{ 0x582C, 0x8f }, { 0x582D, 0x9f }, { 0x582E, 0x4f }, { 0x582F, 0x87 },
+	{ 0x5830, 0x86 }, { 0x5831, 0x97 }, { 0x5832, 0xae }, { 0x5833, 0x3f },
+	{ 0x5834, 0x8e }, { 0x5835, 0x7c }, { 0x5836, 0x7e }, { 0x5837, 0xaf },
+	{ 0x5838, 0x8f }, { 0x5839, 0x8f }, { 0x583A, 0x9f }, { 0x583B, 0x7f },
+	{ 0x583C, 0x5f },
+
+	/* Y Gamma */
+	{ 0x5480, 0x07 }, { 0x5481, 0x18 }, { 0x5482, 0x2c }, { 0x5483, 0x4e },
+	{ 0x5484, 0x5e }, { 0x5485, 0x6b }, { 0x5486, 0x77 }, { 0x5487, 0x82 },
+	{ 0x5488, 0x8c }, { 0x5489, 0x95 }, { 0x548A, 0xa4 }, { 0x548B, 0xb1 },
+	{ 0x548C, 0xc6 }, { 0x548D, 0xd8 }, { 0x548E, 0xe9 },
+
+	/* UV Gamma */
+	{ 0x5490, 0x0f }, { 0x5491, 0xff }, { 0x5492, 0x0d }, { 0x5493, 0x05 },
+	{ 0x5494, 0x07 }, { 0x5495, 0x1a }, { 0x5496, 0x04 }, { 0x5497, 0x01 },
+	{ 0x5498, 0x03 }, { 0x5499, 0x53 }, { 0x549A, 0x02 }, { 0x549B, 0xeb },
+	{ 0x549C, 0x02 }, { 0x549D, 0xa0 }, { 0x549E, 0x02 }, { 0x549F, 0x67 },
+	{ 0x54A0, 0x02 }, { 0x54A1, 0x3b }, { 0x54A2, 0x02 }, { 0x54A3, 0x18 },
+	{ 0x54A4, 0x01 }, { 0x54A5, 0xe7 }, { 0x54A6, 0x01 }, { 0x54A7, 0xc3 },
+	{ 0x54A8, 0x01 }, { 0x54A9, 0x94 }, { 0x54AA, 0x01 }, { 0x54AB, 0x72 },
+	{ 0x54AC, 0x01 }, { 0x54AD, 0x57 },
+
+	/* AWB */
+	{ OV9740_AWB_CTRL00,		0xf0 },
+	{ OV9740_AWB_CTRL01,		0x00 },
+	{ OV9740_AWB_CTRL02,		0x41 },
+	{ OV9740_AWB_CTRL03,		0x42 },
+	{ OV9740_AWB_ADV_CTRL01,	0x8a },
+	{ OV9740_AWB_ADV_CTRL02,	0x61 },
+	{ OV9740_AWB_ADV_CTRL03,	0xce },
+	{ OV9740_AWB_ADV_CTRL04,	0xa8 },
+	{ OV9740_AWB_ADV_CTRL05,	0x17 },
+	{ OV9740_AWB_ADV_CTRL06,	0x1f },
+	{ OV9740_AWB_ADV_CTRL07,	0x27 },
+	{ OV9740_AWB_ADV_CTRL08,	0x41 },
+	{ OV9740_AWB_ADV_CTRL09,	0x34 },
+	{ OV9740_AWB_ADV_CTRL10,	0xf0 },
+	{ OV9740_AWB_ADV_CTRL11,	0x10 },
+	{ OV9740_AWB_CTRL0F,		0xff },
+	{ OV9740_AWB_CTRL10,		0x00 },
+	{ OV9740_AWB_CTRL11,		0xff },
+	{ OV9740_AWB_CTRL12,		0x00 },
+	{ OV9740_AWB_CTRL13,		0xff },
+	{ OV9740_AWB_CTRL14,		0x00 },
+
+	/* CIP */
+	{ 0x530D, 0x12 },
+
+	/* CMX */
+	{ 0x5380, 0x01 }, { 0x5381, 0x00 }, { 0x5382, 0x00 }, { 0x5383, 0x17 },
+	{ 0x5384, 0x00 }, { 0x5385, 0x01 }, { 0x5386, 0x00 }, { 0x5387, 0x00 },
+	{ 0x5388, 0x00 }, { 0x5389, 0xe0 }, { 0x538A, 0x00 }, { 0x538B, 0x20 },
+	{ 0x538C, 0x00 }, { 0x538D, 0x00 }, { 0x538E, 0x00 }, { 0x538F, 0x16 },
+	{ 0x5390, 0x00 }, { 0x5391, 0x9c }, { 0x5392, 0x00 }, { 0x5393, 0xa0 },
+	{ 0x5394, 0x18 },
+
+	/* 50/60 Detection */
+	{ 0x3C0A, 0x9c }, { 0x3C0B, 0x3f },
+
+	/* Output Select */
+	{ OV9740_IO_OUTPUT_SEL01,	0x00 },
+	{ OV9740_IO_OUTPUT_SEL02,	0x00 },
+	{ OV9740_IO_CREL00,		0x00 },
+	{ OV9740_IO_CREL01,		0x00 },
+	{ OV9740_IO_CREL02,		0x00 },
+
+	/* AWB Control */
+	{ OV9740_AWB_MANUAL_CTRL,	0x00 },
+
+	/* Analog Control */
+	{ OV9740_ANALOG_CTRL03,		0xaa },
+	{ OV9740_ANALOG_CTRL32,		0x2f },
+	{ OV9740_ANALOG_CTRL20,		0x66 },
+	{ OV9740_ANALOG_CTRL21,		0xc0 },
+	{ OV9740_ANALOG_CTRL31,		0x52 },
+	{ OV9740_ANALOG_CTRL33,		0x50 },
+	{ OV9740_ANALOG_CTRL30,		0xca },
+	{ OV9740_ANALOG_CTRL04,		0x0c },
+	{ OV9740_ANALOG_CTRL01,		0x40 },
+	{ OV9740_ANALOG_CTRL02,		0x16 },
+	{ OV9740_ANALOG_CTRL10,		0xa1 },
+	{ OV9740_ANALOG_CTRL12,		0x24 },
+	{ OV9740_ANALOG_CTRL22,		0x9f },
+
+	/* Sensor Control */
+	{ OV9740_SENSOR_CTRL03,		0x42 },
+	{ OV9740_SENSOR_CTRL04,		0x10 },
+	{ OV9740_SENSOR_CTRL05,		0x45 },
+	{ OV9740_SENSOR_CTRL07,		0x14 },
+
+	/* Timing Control */
+	{ OV9740_TIMING_CTRL33,		0x04 },
+	{ OV9740_TIMING_CTRL35,		0x02 },
+	{ OV9740_TIMING_CTRL19,		0x6e },
+	{ OV9740_TIMING_CTRL17,		0x94 },
+
+	/* AEC/AGC Control */
+	{ OV9740_AEC_ENABLE,		0x10 },
+	{ OV9740_GAIN_CEILING_01,	0x00 },
+	{ OV9740_GAIN_CEILING_02,	0x7f },
+	{ OV9740_AEC_HI_THRESHOLD,	0xa0 },
+	{ OV9740_AEC_3A1A,		0x05 },
+	{ OV9740_AEC_CTRL1B_WPT2,	0x50 },
+	{ OV9740_AEC_CTRL0F_WPT,	0x50 },
+	{ OV9740_AEC_CTRL10_BPT,	0x4c },
+	{ OV9740_AEC_CTRL1E_BPT2,	0x4c },
+	{ OV9740_AEC_LO_THRESHOLD,	0x26 },
+
+	/* BLC Control */
+	{ OV9740_BLC_AUTO_ENABLE,	0x45 },
+	{ OV9740_BLC_MODE,		0x18 },
+
+	/* DVP Control */
+	{ OV9740_DVP_VSYNC_CTRL02,	0x04 },
+	{ OV9740_DVP_VSYNC_MODE,	0x00 },
+	{ OV9740_DVP_VSYNC_CTRL06,	0x08 },
+
+	/* PLL Setting */
+	{ OV9740_PLL_MODE_CTRL01,	0x20 },
+	{ OV9740_PRE_PLL_CLK_DIV,	0x03 },
+	{ OV9740_PLL_MULTIPLIER,	0x4c },
+	{ OV9740_VT_SYS_CLK_DIV,	0x01 },
+	{ OV9740_VT_PIX_CLK_DIV,	0x08 },
+	{ OV9740_PLL_CTRL3010,		0x01 },
+	{ OV9740_VFIFO_CTRL00,		0x82 },
+
+	/* Timing Setting */
+	/* VTS */
+	{ OV9740_FRM_LENGTH_LN_HI,	0x03 },
+	{ OV9740_FRM_LENGTH_LN_LO,	0x07 },
+	/* HTS */
+	{ OV9740_LN_LENGTH_PCK_HI,	0x06 },
+	{ OV9740_LN_LENGTH_PCK_LO,	0x62 },
+
+	/* MIPI Control */
+	{ OV9740_MIPI_CTRL00,		0x44 },
+	{ OV9740_MIPI_3837,		0x01 },
+	{ OV9740_MIPI_CTRL01,		0x0f },
+	{ OV9740_MIPI_CTRL03,		0x05 },
+	{ OV9740_MIPI_CTRL05,		0x10 },
+	{ OV9740_VFIFO_RD_CTRL,		0x16 },
+	{ OV9740_MIPI_CTRL_3012,	0x70 },
+	{ OV9740_SC_CMMM_MIPI_CTR,	0x01 },
+};
+
+static const struct ov9740_reg ov9740_regs_vga[] = {
+	{ OV9740_X_ADDR_START_HI,	0x00 },
+	{ OV9740_X_ADDR_START_LO,	0xa0 },
+	{ OV9740_Y_ADDR_START_HI,	0x00 },
+	{ OV9740_Y_ADDR_START_LO,	0x00 },
+	{ OV9740_X_ADDR_END_HI,		0x04 },
+	{ OV9740_X_ADDR_END_LO,		0x63 },
+	{ OV9740_Y_ADDR_END_HI,		0x02 },
+	{ OV9740_Y_ADDR_END_LO,		0xd3 },
+	{ OV9740_X_OUTPUT_SIZE_HI,	0x02 },
+	{ OV9740_X_OUTPUT_SIZE_LO,	0x80 },
+	{ OV9740_Y_OUTPUT_SIZE_HI,	0x01 },
+	{ OV9740_Y_OUTPUT_SIZE_LO,	0xe0 },
+	{ OV9740_ISP_CTRL1E,		0x03 },
+	{ OV9740_ISP_CTRL1F,		0xc0 },
+	{ OV9740_ISP_CTRL20,		0x02 },
+	{ OV9740_ISP_CTRL21,		0xd0 },
+	{ OV9740_VFIFO_READ_START_HI,	0x01 },
+	{ OV9740_VFIFO_READ_START_LO,	0x40 },
+	{ OV9740_ISP_CTRL00,		0xff },
+	{ OV9740_ISP_CTRL01,		0xff },
+	{ OV9740_ISP_CTRL03,		0xff },
+};
+
+static const struct ov9740_reg ov9740_regs_720p[] = {
+	{ OV9740_X_ADDR_START_HI,	0x00 },
+	{ OV9740_X_ADDR_START_LO,	0x00 },
+	{ OV9740_Y_ADDR_START_HI,	0x00 },
+	{ OV9740_Y_ADDR_START_LO,	0x00 },
+	{ OV9740_X_ADDR_END_HI,		0x05 },
+	{ OV9740_X_ADDR_END_LO,		0x03 },
+	{ OV9740_Y_ADDR_END_HI,		0x02 },
+	{ OV9740_Y_ADDR_END_LO,		0xd3 },
+	{ OV9740_X_OUTPUT_SIZE_HI,	0x05 },
+	{ OV9740_X_OUTPUT_SIZE_LO,	0x00 },
+	{ OV9740_Y_OUTPUT_SIZE_HI,	0x02 },
+	{ OV9740_Y_OUTPUT_SIZE_LO,	0xd0 },
+	{ OV9740_ISP_CTRL1E,		0x05 },
+	{ OV9740_ISP_CTRL1F,		0x00 },
+	{ OV9740_ISP_CTRL20,		0x02 },
+	{ OV9740_ISP_CTRL21,		0xd0 },
+	{ OV9740_VFIFO_READ_START_HI,	0x02 },
+	{ OV9740_VFIFO_READ_START_LO,	0x30 },
+	{ OV9740_ISP_CTRL00,		0xff },
+	{ OV9740_ISP_CTRL01,		0xef },
+	{ OV9740_ISP_CTRL03,		0xff },
+};
+
+static enum v4l2_mbus_pixelcode ov9740_codes[] = {
+	V4L2_MBUS_FMT_YUYV8_2X8,
+};
+
+static const struct v4l2_queryctrl ov9740_controls[] = {
+	{
+		.id		= V4L2_CID_VFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Vertically",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+	{
+		.id		= V4L2_CID_HFLIP,
+		.type		= V4L2_CTRL_TYPE_BOOLEAN,
+		.name		= "Flip Horizontally",
+		.minimum	= 0,
+		.maximum	= 1,
+		.step		= 1,
+		.default_value	= 0,
+	},
+};
+
+/* read a register */
+static int ov9740_reg_read(struct i2c_client *client, u16 reg, u8 *val)
+{
+	int ret;
+	struct i2c_msg msg[] = {
+		{
+			.addr	= client->addr,
+			.flags	= 0,
+			.len	= 2,
+			.buf	= (u8 *)&reg,
+		},
+		{
+			.addr	= client->addr,
+			.flags	= I2C_M_RD,
+			.len	= 1,
+			.buf	= val,
+		},
+	};
+
+	reg = swab16(reg);
+
+	ret = i2c_transfer(client->adapter, msg, 2);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed reading register 0x%04x!\n", reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+/* write a register */
+static int ov9740_reg_write(struct i2c_client *client, u16 reg, u8 val)
+{
+	struct i2c_msg msg;
+	struct {
+		u16 reg;
+		u8 val;
+	} __packed buf;
+	int ret;
+
+	reg = swab16(reg);
+
+	buf.reg = reg;
+	buf.val = val;
+
+	msg.addr	= client->addr;
+	msg.flags	= 0;
+	msg.len		= 3;
+	msg.buf		= (u8 *)&buf;
+
+	ret = i2c_transfer(client->adapter, &msg, 1);
+	if (ret < 0) {
+		dev_err(&client->dev, "Failed writing register 0x%04x!\n", reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+
+/* Read a register, alter its bits, write it back */
+static int ov9740_reg_rmw(struct i2c_client *client, u16 reg, u8 set, u8 unset)
+{
+	u8 val;
+	int ret;
+
+	ret = ov9740_reg_read(client, reg, &val);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"[Read]-Modify-Write of register %02x failed!\n", reg);
+		return ret;
+	}
+
+	val |= set;
+	val &= ~unset;
+
+	ret = ov9740_reg_write(client, reg, val);
+	if (ret < 0) {
+		dev_err(&client->dev,
+			"Read-Modify-[Write] of register %02x failed!\n", reg);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ov9740_reg_write_array(struct i2c_client *client,
+				  const struct ov9740_reg *regarray,
+				  int regarraylen)
+{
+	int i;
+	int ret;
+
+	for (i = 0; i < regarraylen; i++) {
+		ret = ov9740_reg_write(client,
+				       regarray[i].reg, regarray[i].val);
+		if (ret < 0)
+			return ret;
+	}
+
+	return 0;
+}
+
+/* Start/Stop streaming from the device */
+static int ov9740_s_stream(struct v4l2_subdev *sd, int enable)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	struct ov9740_priv *priv = to_ov9740(sd);
+	int ret;
+
+	/* Program orientation register. */
+	if (priv->flag_vflip)
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0x2, 0);
+	else
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0, 0x2);
+	if (ret < 0)
+		return ret;
+
+	if (priv->flag_hflip)
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0x1, 0);
+	else
+		ret = ov9740_reg_rmw(client, OV9740_IMAGE_ORT, 0, 0x1);
+	if (ret < 0)
+		return ret;
+
+	if (enable) {
+		dev_dbg(&client->dev, "Enabling Streaming\n");
+		/* Start Streaming */
+		ret = ov9740_reg_write(client, OV9740_MODE_SELECT, 0x01);
+
+	} else {
+		dev_dbg(&client->dev, "Disabling Streaming\n");
+		/* Software Reset */
+		ret = ov9740_reg_write(client, OV9740_SOFTWARE_RESET, 0x01);
+		if (!ret)
+			/* Setting Streaming to Standby */
+			ret = ov9740_reg_write(client, OV9740_MODE_SELECT,
+					       0x00);
+	}
+
+	return ret;
+}
+
+/* Alter bus settings on camera side */
+static int ov9740_set_bus_param(struct soc_camera_device *icd,
+				unsigned long flags)
+{
+	return 0;
+}
+
+/* Request bus settings on camera side */
+static unsigned long ov9740_query_bus_param(struct soc_camera_device *icd)
+{
+	struct soc_camera_link *icl = to_soc_camera_link(icd);
+
+	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
+		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
+		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;
+
+	return soc_camera_apply_sensor_flags(icl, flags);
+}
+
+/* Get status of additional camera capabilities */
+static int ov9740_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct ov9740_priv *priv = to_ov9740(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		ctrl->value = priv->flag_vflip;
+		break;
+	case V4L2_CID_HFLIP:
+		ctrl->value = priv->flag_hflip;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Set status of additional camera capabilities */
+static int ov9740_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+{
+	struct ov9740_priv *priv = to_ov9740(sd);
+
+	switch (ctrl->id) {
+	case V4L2_CID_VFLIP:
+		priv->flag_vflip = ctrl->value;
+		break;
+	case V4L2_CID_HFLIP:
+		priv->flag_hflip = ctrl->value;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* Get chip identification */
+static int ov9740_g_chip_ident(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_chip_ident *id)
+{
+	struct ov9740_priv *priv = to_ov9740(sd);
+
+	id->ident = priv->ident;
+	id->revision = priv->revision;
+
+	return 0;
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ov9740_get_register(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	int ret;
+	u8 val;
+
+	if (reg->reg & ~0xffff)
+		return -EINVAL;
+
+	reg->size = 2;
+
+	ret = ov9740_reg_read(client, reg->reg, &val);
+	if (ret)
+		return ret;
+
+	reg->val = (__u64)val;
+
+	return ret;
+}
+
+static int ov9740_set_register(struct v4l2_subdev *sd,
+			       struct v4l2_dbg_register *reg)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+	if (reg->reg & ~0xffff || reg->val & ~0xff)
+		return -EINVAL;
+
+	return ov9740_reg_write(client, reg->reg, reg->val);
+}
+#endif
+
+/* select nearest higher resolution for capture */
+static void ov9740_res_roundup(u32 *width, u32 *height)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(ov9740_resolutions); i++)
+		if ((ov9740_resolutions[i].width >= *width) &&
+		    (ov9740_resolutions[i].height >= *height)) {
+			*width = ov9740_resolutions[i].width;
+			*height = ov9740_resolutions[i].height;
+			return;
+		}
+
+	*width = ov9740_resolutions[OV9740_720P].width;
+	*height = ov9740_resolutions[OV9740_720P].height;
+}
+
+/* Setup registers according to resolution and color encoding */
+static int ov9740_set_res(struct i2c_client *client, u32 width)
+{
+	int ret;
+
+	/* select register configuration for given resolution */
+	if (width == ov9740_resolutions[OV9740_VGA].width) {
+		dev_dbg(&client->dev, "Setting image size to 640x480\n");
+		ret = ov9740_reg_write_array(client, ov9740_regs_vga,
+					     ARRAY_SIZE(ov9740_regs_vga));
+	} else if (width == ov9740_resolutions[OV9740_720P].width) {
+		dev_dbg(&client->dev, "Setting image size to 1280x720\n");
+		ret = ov9740_reg_write_array(client, ov9740_regs_720p,
+					     ARRAY_SIZE(ov9740_regs_720p));
+	} else {
+		dev_err(&client->dev, "Failed to select resolution!\n");
+		return -EINVAL;
+	}
+
+	return ret;
+}
+
+/* set the format we will capture in */
+static int ov9740_s_fmt(struct v4l2_subdev *sd,
+			struct v4l2_mbus_framefmt *mf)
+{
+	struct i2c_client *client = v4l2_get_subdevdata(sd);
+	enum v4l2_colorspace cspace;
+	enum v4l2_mbus_pixelcode code = mf->code;
+	int ret;
+
+	ov9740_res_roundup(&mf->width, &mf->height);
+
+	switch (code) {
+	case V4L2_MBUS_FMT_YUYV8_2X8:
+		cspace = V4L2_COLORSPACE_SRGB;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	ret = ov9740_reg_write_array(client, ov9740_defaults,
+				     ARRAY_SIZE(ov9740_defaults));
+	if (ret < 0)
+		return ret;
+
+	ret = ov9740_set_res(client, mf->width);
+	if (ret < 0)
+		return ret;
+
+	mf->code	= code;
+	mf->colorspace	= cspace;
+
+	return ret;
+}
+
+static int ov9740_try_fmt(struct v4l2_subdev *sd,
+			  struct v4l2_mbus_framefmt *mf)
+{
+	ov9740_res_roundup(&mf->width, &mf->height);
+
+	mf->field = V4L2_FIELD_NONE;
+	mf->code = V4L2_MBUS_FMT_YUYV8_2X8;
+	mf->colorspace = V4L2_COLORSPACE_SRGB;
+
+	return 0;
+}
+
+static int ov9740_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
+			   enum v4l2_mbus_pixelcode *code)
+{
+	if (index >= ARRAY_SIZE(ov9740_codes))
+		return -EINVAL;
+
+	*code = ov9740_codes[index];
+
+	return 0;
+}
+
+static int ov9740_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
+{
+	a->bounds.left		= 0;
+	a->bounds.top		= 0;
+	a->bounds.width		= ov9740_resolutions[OV9740_720P].width;
+	a->bounds.height	= ov9740_resolutions[OV9740_720P].height;
+	a->defrect		= a->bounds;
+	a->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	a->pixelaspect.numerator	= 1;
+	a->pixelaspect.denominator	= 1;
+
+	return 0;
+}
+
+static int ov9740_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+{
+	a->c.left		= 0;
+	a->c.top		= 0;
+	a->c.width		= ov9740_resolutions[OV9740_720P].width;
+	a->c.height		= ov9740_resolutions[OV9740_720P].height;
+	a->type			= V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+	return 0;
+}
+
+static int ov9740_video_probe(struct soc_camera_device *icd,
+			      struct i2c_client *client)
+{
+	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct ov9740_priv *priv = to_ov9740(sd);
+	u8 modelhi, modello;
+	int ret;
+
+	/*
+	 * We must have a parent by now. And it cannot be a wrong one.
+	 * So this entire test is completely redundant.
+	 */
+	if (!icd->dev.parent ||
+	    to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
+		dev_err(&client->dev, "Parent missing or invalid!\n");
+		ret = -ENODEV;
+		goto err;
+	}
+
+	/*
+	 * check and show product ID and manufacturer ID
+	 */
+	ret = ov9740_reg_read(client, OV9740_MODEL_ID_HI, &modelhi);
+	if (ret < 0)
+		goto err;
+
+	ret = ov9740_reg_read(client, OV9740_MODEL_ID_LO, &modello);
+	if (ret < 0)
+		goto err;
+
+	priv->model = (modelhi << 8) | modello;
+
+	ret = ov9740_reg_read(client, OV9740_REVISION_NUMBER, &priv->revision);
+	if (ret < 0)
+		goto err;
+
+	ret = ov9740_reg_read(client, OV9740_MANUFACTURER_ID, &priv->manid);
+	if (ret < 0)
+		goto err;
+
+	ret = ov9740_reg_read(client, OV9740_SMIA_VERSION, &priv->smiaver);
+	if (ret < 0)
+		goto err;
+
+	if (priv->model != 0x9740) {
+		ret = -ENODEV;
+		goto err;
+	}
+
+	priv->ident = V4L2_IDENT_OV9740;
+
+	dev_info(&client->dev, "ov9740 Model ID 0x%04x, Revision 0x%02x, "
+		 "Manufacturer 0x%02x, SMIA Version 0x%02x\n",
+		 priv->model, priv->revision, priv->manid, priv->smiaver);
+
+err:
+	return ret;
+}
+
+static struct soc_camera_ops ov9740_ops = {
+	.set_bus_param		= ov9740_set_bus_param,
+	.query_bus_param	= ov9740_query_bus_param,
+	.controls		= ov9740_controls,
+	.num_controls		= ARRAY_SIZE(ov9740_controls),
+};
+
+static struct v4l2_subdev_core_ops ov9740_core_ops = {
+	.g_ctrl			= ov9740_g_ctrl,
+	.s_ctrl			= ov9740_s_ctrl,
+	.g_chip_ident		= ov9740_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+	.g_register		= ov9740_get_register,
+	.s_register		= ov9740_set_register,
+#endif
+
+};
+
+static struct v4l2_subdev_video_ops ov9740_video_ops = {
+	.s_stream		= ov9740_s_stream,
+	.s_mbus_fmt		= ov9740_s_fmt,
+	.try_mbus_fmt		= ov9740_try_fmt,
+	.enum_mbus_fmt		= ov9740_enum_fmt,
+	.cropcap		= ov9740_cropcap,
+	.g_crop			= ov9740_g_crop,
+};
+
+static struct v4l2_subdev_ops ov9740_subdev_ops = {
+	.core			= &ov9740_core_ops,
+	.video			= &ov9740_video_ops,
+};
+
+/*
+ * i2c_driver function
+ */
+static int ov9740_probe(struct i2c_client *client,
+			const struct i2c_device_id *did)
+{
+	struct ov9740_priv *priv;
+	struct soc_camera_device *icd	= client->dev.platform_data;
+	struct soc_camera_link *icl;
+	int ret;
+
+	if (!icd) {
+		dev_err(&client->dev, "Missing soc-camera data!\n");
+		return -EINVAL;
+	}
+
+	icl = to_soc_camera_link(icd);
+	if (!icl) {
+		dev_err(&client->dev, "Missing platform_data for driver\n");
+		return -EINVAL;
+	}
+
+	priv = kzalloc(sizeof(struct ov9740_priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&client->dev, "Failed to allocate private data!\n");
+		return -ENOMEM;
+	}
+
+	v4l2_i2c_subdev_init(&priv->subdev, client, &ov9740_subdev_ops);
+
+	icd->ops = &ov9740_ops;
+
+	ret = ov9740_video_probe(icd, client);
+	if (ret < 0) {
+		icd->ops = NULL;
+		kfree(priv);
+	}
+
+	return ret;
+}
+
+static int ov9740_remove(struct i2c_client *client)
+{
+	struct ov9740_priv *priv = i2c_get_clientdata(client);
+
+	kfree(priv);
+
+	return 0;
+}
+
+static const struct i2c_device_id ov9740_id[] = {
+	{ "ov9740", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, ov9740_id);
+
+static struct i2c_driver ov9740_i2c_driver = {
+	.driver = {
+		.name = "ov9740",
+	},
+	.probe    = ov9740_probe,
+	.remove   = ov9740_remove,
+	.id_table = ov9740_id,
+};
+
+static int __init ov9740_module_init(void)
+{
+	return i2c_add_driver(&ov9740_i2c_driver);
+}
+
+static void __exit ov9740_module_exit(void)
+{
+	i2c_del_driver(&ov9740_i2c_driver);
+}
+
+module_init(ov9740_module_init);
+module_exit(ov9740_module_exit);
+
+MODULE_DESCRIPTION("SoC Camera driver for OmniVision OV9740");
+MODULE_AUTHOR("Andrew Chew <achew@nvidia.com>");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,9 +99,27 @@
 	.cnt = ARRAY_SIZE(routing_schemegv),
 };
 
+/* Specific to grabster av400 device */
+static const struct routing_scheme_item routing_schemeav400[] = {
+	[PVR2_CVAL_INPUT_COMPOSITE] = {
+		.vid = CX25840_COMPOSITE1,
+		.aud = CX25840_AUDIO_SERIAL,
+	},
+	[PVR2_CVAL_INPUT_SVIDEO] = {
+		.vid = (CX25840_SVIDEO_LUMA2|CX25840_SVIDEO_CHROMA4),
+		.aud = CX25840_AUDIO_SERIAL,
+	},
+};
+
+static const struct routing_scheme routing_defav400 = {
+	.def = routing_schemeav400,
+	.cnt = ARRAY_SIZE(routing_schemeav400),
+};
+
 static const struct routing_scheme *routing_schemes[] = {
 	[PVR2_ROUTING_SCHEME_HAUPPAUGE] = &routing_def0,
 	[PVR2_ROUTING_SCHEME_GOTVIEW] = &routing_defgv,
+	[PVR2_ROUTING_SCHEME_AV400] = &routing_defav400,
 };
 
 void pvr2_cx25840_subdev_update(struct pvr2_hdw *hdw, struct v4l2_subdev *sd)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-24 01:04:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-devattr.c	2012-03-24 03:29:15.000000000 -0400
@@ -157,6 +157,28 @@
 
 
 /*------------------------------------------------------------------------*/
+/* Terratec Grabster AV400 */
+
+static const struct pvr2_device_client_desc pvr2_cli_av400[] = {
+	{ .module_id = PVR2_CLIENT_ID_CX25840 },
+};
+
+static const struct pvr2_device_desc pvr2_device_av400 = {
+		.description = "Terratec Grabster AV400",
+		.shortname = "av400",
+		.flag_is_experimental = 1,
+		.client_table.lst = pvr2_cli_av400,
+		.client_table.cnt = ARRAY_SIZE(pvr2_cli_av400),
+		.flag_has_cx25840 = !0,
+		.flag_has_analogtuner = 0,
+		.flag_has_composite = !0,
+		.flag_has_svideo = !0,
+		.signal_routing_scheme = PVR2_ROUTING_SCHEME_AV400,
+};
+
+
+
+/*------------------------------------------------------------------------*/
 /* OnAir Creator */
 
 #ifdef CONFIG_VIDEO_PVRUSB2_DVB
@@ -517,6 +539,8 @@
 	  .driver_info = (kernel_ulong_t)&pvr2_device_750xx},
 	{ USB_DEVICE(0x2040, 0x7501),
 	  .driver_info = (kernel_ulong_t)&pvr2_device_751xx},
+	{ USB_DEVICE(0x0ccd, 0x0039),
+	  .driver_info = (kernel_ulong_t)&pvr2_device_av400},
 	{ }
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-eeprom.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-eeprom.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 
    Read and analyze data in the eeprom.  Use tveeprom to figure out
    the packet structure, since this is another Hauppauge device and
-   internally it has a family resemblence to ivtv-type devices
+   internally it has a family resemblance to ivtv-type devices
 
 */
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c	2012-03-24 01:04:54.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.c	2012-03-24 03:29:13.000000000 -0400
@@ -499,31 +499,35 @@
 	return 0;
 }
 
-static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *val)
+static int ctrl_cropw_max_get(struct pvr2_ctrl *cptr, int *width)
 {
 	struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-	int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+	int stat, bleftend, cleft;
+
+	stat = pvr2_hdw_check_cropcap(cptr->hdw);
 	if (stat != 0) {
 		return stat;
 	}
-	*val = 0;
-	if (cap->bounds.width > cptr->hdw->cropl_val) {
-		*val = cap->bounds.width - cptr->hdw->cropl_val;
-	}
+	bleftend = cap->bounds.left+cap->bounds.width;
+	cleft = cptr->hdw->cropl_val;
+
+	*width = cleft < bleftend ? bleftend-cleft : 0;
 	return 0;
 }
 
-static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *val)
+static int ctrl_croph_max_get(struct pvr2_ctrl *cptr, int *height)
 {
 	struct v4l2_cropcap *cap = &cptr->hdw->cropcap_info;
-	int stat = pvr2_hdw_check_cropcap(cptr->hdw);
+	int stat, btopend, ctop;
+
+	stat = pvr2_hdw_check_cropcap(cptr->hdw);
 	if (stat != 0) {
 		return stat;
 	}
-	*val = 0;
-	if (cap->bounds.height > cptr->hdw->cropt_val) {
-		*val = cap->bounds.height - cptr->hdw->cropt_val;
-	}
+	btopend = cap->bounds.top+cap->bounds.height;
+	ctop = cptr->hdw->cropt_val;
+
+	*height = ctop < btopend ? btopend-ctop : 0;
 	return 0;
 }
 
@@ -1114,6 +1118,7 @@
 		.internal_id = PVR2_CID_CROPW,
 		.default_value = 720,
 		DEFREF(cropw),
+		DEFINT(0, 864),
 		.get_max_value = ctrl_cropw_max_get,
 		.get_def_value = ctrl_get_cropcapdw,
 	}, {
@@ -1122,6 +1127,7 @@
 		.internal_id = PVR2_CID_CROPH,
 		.default_value = 480,
 		DEFREF(croph),
+		DEFINT(0, 576),
 		.get_max_value = ctrl_croph_max_get,
 		.get_def_value = ctrl_get_cropcapdh,
 	}, {
@@ -2027,6 +2033,8 @@
 		   hdw->decoder_client_id);
 	memset(&fmt, 0, sizeof(fmt));
 	fmt.type = V4L2_BUF_TYPE_SLICED_VBI_CAPTURE;
+	fmt.fmt.sliced.service_lines[0][21] = V4L2_SLICED_CAPTION_525;
+	fmt.fmt.sliced.service_lines[1][21] = V4L2_SLICED_CAPTION_525;
 	v4l2_device_call_all(&hdw->v4l2_dev, hdw->decoder_client_id,
 			     vbi, s_sliced_fmt, &fmt.fmt.sliced);
 }
@@ -2842,15 +2850,23 @@
 			PVR2_TRACE_ERROR_LEGS,
 			"WARNING: Failed to identify any viable standards");
 	}
+
+	/* Set up the dynamic control for this standard */
 	hdw->std_enum_names = kmalloc(sizeof(char *)*(std_cnt+1),GFP_KERNEL);
-	hdw->std_enum_names[0] = "none";
-	for (idx = 0; idx < std_cnt; idx++) {
-		hdw->std_enum_names[idx+1] =
-			newstd[idx].name;
+	if (hdw->std_enum_names) {
+		hdw->std_enum_names[0] = "none";
+		for (idx = 0; idx < std_cnt; idx++)
+			hdw->std_enum_names[idx+1] = newstd[idx].name;
+		hdw->std_info_enum.def.type_enum.value_names =
+						hdw->std_enum_names;
+		hdw->std_info_enum.def.type_enum.count = std_cnt+1;
+	} else {
+		pvr2_trace(
+			PVR2_TRACE_ERROR_LEGS,
+			"WARNING: Failed to alloc memory for names");
+		hdw->std_info_enum.def.type_enum.value_names = NULL;
+		hdw->std_info_enum.def.type_enum.count = 0;
 	}
-	// Set up the dynamic control for this standard
-	hdw->std_info_enum.def.type_enum.value_names = hdw->std_enum_names;
-	hdw->std_info_enum.def.type_enum.count = std_cnt+1;
 	hdw->std_defs = newstd;
 	hdw->std_enum_cnt = std_cnt+1;
 	hdw->std_enum_cur = 0;
@@ -3165,6 +3181,19 @@
 	struct pvr2_ctrl *cptr;
 	int disruptive_change;
 
+	if (hdw->input_dirty && hdw->state_pathway_ok &&
+	    (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
+	      PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
+	     hdw->pathway_state)) {
+		/* Change of mode being asked for... */
+		hdw->state_pathway_ok = 0;
+		trace_stbit("state_pathway_ok", hdw->state_pathway_ok);
+	}
+	if (!hdw->state_pathway_ok) {
+		/* Can't commit anything until pathway is ok. */
+		return 0;
+	}
+
 	/* Handle some required side effects when the video standard is
 	   changed.... */
 	if (hdw->std_dirty) {
@@ -3199,18 +3228,6 @@
 		}
 	}
 
-	if (hdw->input_dirty && hdw->state_pathway_ok &&
-	    (((hdw->input_val == PVR2_CVAL_INPUT_DTV) ?
-	      PVR2_PATHWAY_DIGITAL : PVR2_PATHWAY_ANALOG) !=
-	     hdw->pathway_state)) {
-		/* Change of mode being asked for... */
-		hdw->state_pathway_ok = 0;
-		trace_stbit("state_pathway_ok",hdw->state_pathway_ok);
-	}
-	if (!hdw->state_pathway_ok) {
-		/* Can't commit anything until pathway is ok. */
-		return 0;
-	}
 	/* The broadcast decoder can only scale down, so if
 	 * res_*_dirty && crop window < output format ==> enlarge crop.
 	 *
@@ -5159,8 +5176,7 @@
 	   using v4l2-subdev - therefore we can't support that AT ALL right
 	   now.  (Of course, no sub-drivers seem to implement it either.
 	   But now it's a a chicken and egg problem...) */
-	v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner,
-			     &hdw->tuner_signal_info);
+	v4l2_device_call_all(&hdw->v4l2_dev, 0, tuner, g_tuner, vtp);
 	pvr2_trace(PVR2_TRACE_CHIPS, "subdev status poll"
 		   " type=%u strength=%u audio=0x%x cap=0x%x"
 		   " low=%u hi=%u",
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-hdw.h	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
  *  (but it might still on the bus).  In this state there's nothing we can
  *  do; it must be replugged in order to recover.
  *
- *  COLD - Device is in an unusuable state, needs microcontroller firmware.
+ *  COLD - Device is in an unusable state, needs microcontroller firmware.
  *
  *  WARM - We can communicate with the device and the proper
  *  microcontroller firmware is running, but other device initialization is
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-i2c-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -578,7 +578,7 @@
 	switch (hdw->ir_scheme_active) {
 	case PVR2_IR_SCHEME_24XXX: /* FX2-controlled IR */
 	case PVR2_IR_SCHEME_29XXX: /* Original 29xxx device */
-		init_data->ir_codes              = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP;
 		init_data->type                  = RC_TYPE_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
@@ -593,7 +593,7 @@
 		break;
 	case PVR2_IR_SCHEME_ZILOG:     /* HVR-1950 style */
 	case PVR2_IR_SCHEME_24XXX_MCE: /* 24xxx MCE device */
-		init_data->ir_codes              = RC_MAP_HAUPPAUGE_NEW;
+		init_data->ir_codes              = RC_MAP_HAUPPAUGE;
 		init_data->internal_get_key_func = IR_KBD_GET_KEY_HAUP_XVR;
 		init_data->type                  = RC_TYPE_RC5;
 		init_data->name                  = hdw->hdw_desc->description;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -324,36 +324,45 @@
 	}
 	sfp->item_last = cip;
 
+	sysfs_attr_init(&cip->attr_name.attr);
 	cip->attr_name.attr.name = "name";
 	cip->attr_name.attr.mode = S_IRUGO;
 	cip->attr_name.show = show_name;
 
+	sysfs_attr_init(&cip->attr_type.attr);
 	cip->attr_type.attr.name = "type";
 	cip->attr_type.attr.mode = S_IRUGO;
 	cip->attr_type.show = show_type;
 
+	sysfs_attr_init(&cip->attr_min.attr);
 	cip->attr_min.attr.name = "min_val";
 	cip->attr_min.attr.mode = S_IRUGO;
 	cip->attr_min.show = show_min;
 
+	sysfs_attr_init(&cip->attr_max.attr);
 	cip->attr_max.attr.name = "max_val";
 	cip->attr_max.attr.mode = S_IRUGO;
 	cip->attr_max.show = show_max;
 
+	sysfs_attr_init(&cip->attr_def.attr);
 	cip->attr_def.attr.name = "def_val";
 	cip->attr_def.attr.mode = S_IRUGO;
 	cip->attr_def.show = show_def;
 
+	sysfs_attr_init(&cip->attr_val.attr);
 	cip->attr_val.attr.name = "cur_val";
 	cip->attr_val.attr.mode = S_IRUGO;
 
+	sysfs_attr_init(&cip->attr_custom.attr);
 	cip->attr_custom.attr.name = "custom_val";
 	cip->attr_custom.attr.mode = S_IRUGO;
 
+	sysfs_attr_init(&cip->attr_enum.attr);
 	cip->attr_enum.attr.name = "enum_val";
 	cip->attr_enum.attr.mode = S_IRUGO;
 	cip->attr_enum.show = show_enum;
 
+	sysfs_attr_init(&cip->attr_bits.attr);
 	cip->attr_bits.attr.name = "bit_val";
 	cip->attr_bits.attr.mode = S_IRUGO;
 	cip->attr_bits.show = show_bits;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pvrusb2/pvrusb2-v4l2.c	2011-05-19 00:06:34.000000000 -0400
@@ -795,12 +795,10 @@
 	case VIDIOC_S_CROP:
 	{
 		struct v4l2_crop *crop = (struct v4l2_crop *)arg;
-		struct v4l2_cropcap cap;
 		if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
 			ret = -EINVAL;
 			break;
 		}
-		cap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
 		ret = pvr2_ctrl_set_value(
 			pvr2_hdw_get_ctrl_by_id(hdw, PVR2_CID_CROPL),
 			crop->c.left);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pwc/pwc.h linux-libre-2.6.39-gnu/drivers/media/video/pwc/pwc.h
--- linux-libre-2.6.38-gnu/drivers/media/video/pwc/pwc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pwc/pwc.h	2011-05-19 00:06:34.000000000 -0400
@@ -339,8 +339,7 @@
 /* Private ioctl()s; see pwc-ioctl.h */
 extern long pwc_ioctl(struct pwc_device *pdev, unsigned int cmd, void *arg);
 
-/** Functions in pwc-v4l.c */
-extern long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg);
+extern const struct v4l2_ioctl_ops pwc_ioctl_ops;
 
 /** pwc-uncompress.c */
 /* Expand frame to image, possibly including decompression. Uses read_frame and fill_image */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pwc/pwc-if.c linux-libre-2.6.39-gnu/drivers/media/video/pwc/pwc-if.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pwc/pwc-if.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pwc/pwc-if.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,8 +151,6 @@
 static ssize_t pwc_video_read(struct file *file, char __user *buf,
 			  size_t count, loff_t *ppos);
 static unsigned int pwc_video_poll(struct file *file, poll_table *wait);
-static long  pwc_video_ioctl(struct file *file,
-			    unsigned int ioctlnr, unsigned long arg);
 static int  pwc_video_mmap(struct file *file, struct vm_area_struct *vma);
 
 static const struct v4l2_file_operations pwc_fops = {
@@ -162,7 +160,7 @@
 	.read =		pwc_video_read,
 	.poll =		pwc_video_poll,
 	.mmap =		pwc_video_mmap,
-	.unlocked_ioctl = pwc_video_ioctl,
+	.unlocked_ioctl = video_ioctl2,
 };
 static struct video_device pwc_template = {
 	.name =		"Philips Webcam",	/* Filled in later */
@@ -1098,7 +1096,6 @@
 		return -EBUSY;
 	}
 
-	mutex_lock(&pdev->modlock);
 	pwc_construct(pdev); /* set min/max sizes correct */
 	if (!pdev->usb_init) {
 		PWC_DEBUG_OPEN("Doing first time initialization.\n");
@@ -1130,7 +1127,6 @@
 	if (i < 0) {
 		PWC_DEBUG_OPEN("Failed to allocate buffers memory.\n");
 		pwc_free_buffers(pdev);
-		mutex_unlock(&pdev->modlock);
 		return i;
 	}
 
@@ -1171,7 +1167,6 @@
 	if (i) {
 		PWC_DEBUG_OPEN("Second attempt at set_video_mode failed.\n");
 		pwc_free_buffers(pdev);
-		mutex_unlock(&pdev->modlock);
 		return i;
 	}
 
@@ -1181,7 +1176,6 @@
 
 	pdev->vopen++;
 	file->private_data = vdev;
-	mutex_unlock(&pdev->modlock);
 	PWC_DEBUG_OPEN("<< video_open() returns 0.\n");
 	return 0;
 }
@@ -1210,7 +1204,6 @@
 	PWC_DEBUG_OPEN(">> video_close called(vdev = 0x%p).\n", vdev);
 
 	pdev = video_get_drvdata(vdev);
-	mutex_lock(&pdev->modlock);
 	if (pdev->vopen == 0)
 		PWC_DEBUG_MODULE("video_close() called on closed device?\n");
 
@@ -1248,7 +1241,6 @@
 			if (device_hint[hint].pdev == pdev)
 				device_hint[hint].pdev = NULL;
 	}
-	mutex_unlock(&pdev->modlock);
 
 	return 0;
 }
@@ -1283,7 +1275,6 @@
 	if (pdev == NULL)
 		return -EFAULT;
 
-	mutex_lock(&pdev->modlock);
 	if (pdev->error_status) {
 		rv = -pdev->error_status; /* Something happened, report what. */
 		goto err_out;
@@ -1318,8 +1309,10 @@
 				rv = -ERESTARTSYS;
 				goto err_out;
 			}
+			mutex_unlock(&pdev->modlock);
 			schedule();
 			set_current_state(TASK_INTERRUPTIBLE);
+			mutex_lock(&pdev->modlock);
 		}
 		remove_wait_queue(&pdev->frameq, &wait);
 		set_current_state(TASK_RUNNING);
@@ -1352,10 +1345,8 @@
 		pdev->image_read_pos = 0;
 		pwc_next_image(pdev);
 	}
-	mutex_unlock(&pdev->modlock);
 	return count;
 err_out:
-	mutex_unlock(&pdev->modlock);
 	return rv;
 }
 
@@ -1372,9 +1363,7 @@
 		return -EFAULT;
 
 	/* Start the stream (if not already started) */
-	mutex_lock(&pdev->modlock);
 	ret = pwc_isoc_init(pdev);
-	mutex_unlock(&pdev->modlock);
 	if (ret)
 		return ret;
 
@@ -1387,25 +1376,6 @@
 	return 0;
 }
 
-static long pwc_video_ioctl(struct file *file,
-			   unsigned int cmd, unsigned long arg)
-{
-	struct video_device *vdev = file->private_data;
-	struct pwc_device *pdev;
-	long r = -ENODEV;
-
-	if (!vdev)
-		goto out;
-	pdev = video_get_drvdata(vdev);
-
-	mutex_lock(&pdev->modlock);
-	if (!pdev->unplugged)
-		r = video_usercopy(file, cmd, arg, pwc_video_do_ioctl);
-	mutex_unlock(&pdev->modlock);
-out:
-	return r;
-}
-
 static int pwc_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct video_device *vdev = file->private_data;
@@ -1754,6 +1724,8 @@
 	}
 	memcpy(pdev->vdev, &pwc_template, sizeof(pwc_template));
 	pdev->vdev->parent = &intf->dev;
+	pdev->vdev->lock = &pdev->modlock;
+	pdev->vdev->ioctl_ops = &pwc_ioctl_ops;
 	strcpy(pdev->vdev->name, name);
 	video_set_drvdata(pdev->vdev, pdev);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pwc/pwc-v4l.c linux-libre-2.6.39-gnu/drivers/media/video/pwc/pwc-v4l.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pwc/pwc-v4l.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pwc/pwc-v4l.c	2011-05-19 00:06:34.000000000 -0400
@@ -341,604 +341,555 @@
 
 }
 
-long pwc_video_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+static int pwc_querycap(struct file *file, void *fh, struct v4l2_capability *cap)
 {
 	struct video_device *vdev = video_devdata(file);
-	struct pwc_device *pdev;
-	DECLARE_WAITQUEUE(wait, current);
-
-	if (vdev == NULL)
-		return -EFAULT;
-	pdev = video_get_drvdata(vdev);
-	if (pdev == NULL)
-		return -EFAULT;
-
-#ifdef CONFIG_USB_PWC_DEBUG
-	if (PWC_DEBUG_LEVEL_IOCTL & pwc_trace) {
-		v4l_printk_ioctl(cmd);
-		printk("\n");
-	}
-#endif
-
+	struct pwc_device *pdev = video_drvdata(file);
 
-	switch (cmd) {
-		/* V4L2 Layer */
-		case VIDIOC_QUERYCAP:
-		{
-		    struct v4l2_capability *cap = arg;
+	strcpy(cap->driver, PWC_NAME);
+	strlcpy(cap->card, vdev->name, sizeof(cap->card));
+	usb_make_path(pdev->udev, cap->bus_info, sizeof(cap->bus_info));
+	cap->version = PWC_VERSION_CODE;
+	cap->capabilities =
+		V4L2_CAP_VIDEO_CAPTURE	|
+		V4L2_CAP_STREAMING	|
+		V4L2_CAP_READWRITE;
+	return 0;
+}
 
-		    PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCAP) This application "\
-				       "try to use the v4l2 layer\n");
-		    strcpy(cap->driver,PWC_NAME);
-		    strlcpy(cap->card, vdev->name, sizeof(cap->card));
-		    usb_make_path(pdev->udev,cap->bus_info,sizeof(cap->bus_info));
-		    cap->version = PWC_VERSION_CODE;
-		    cap->capabilities =
-			V4L2_CAP_VIDEO_CAPTURE	|
-			V4L2_CAP_STREAMING	|
-			V4L2_CAP_READWRITE;
-		    return 0;
-		}
+static int pwc_enum_input(struct file *file, void *fh, struct v4l2_input *i)
+{
+	if (i->index)	/* Only one INPUT is supported */
+		return -EINVAL;
 
-		case VIDIOC_ENUMINPUT:
-		{
-		    struct v4l2_input *i = arg;
+	strcpy(i->name, "usb");
+	return 0;
+}
 
-		    if ( i->index )	/* Only one INPUT is supported */
-			  return -EINVAL;
+static int pwc_g_input(struct file *file, void *fh, unsigned int *i)
+{
+	*i = 0;
+	return 0;
+}
 
-		    memset(i, 0, sizeof(struct v4l2_input));
-		    strcpy(i->name, "usb");
-		    return 0;
-		}
+static int pwc_s_input(struct file *file, void *fh, unsigned int i)
+{
+	return i ? -EINVAL : 0;
+}
 
-		case VIDIOC_G_INPUT:
-		{
-		    int *i = arg;
-		    *i = 0;	/* Only one INPUT is supported */
-		    return 0;
-		}
-		case VIDIOC_S_INPUT:
-		{
-			int *i = arg;
+static int pwc_queryctrl(struct file *file, void *fh, struct v4l2_queryctrl *c)
+{
+	int i;
 
-			if ( *i ) {	/* Only one INPUT is supported */
-				PWC_DEBUG_IOCTL("Only one input source is"\
-					" supported with this webcam.\n");
-				return -EINVAL;
-			}
+	for (i = 0; i < sizeof(pwc_controls) / sizeof(struct v4l2_queryctrl); i++) {
+		if (pwc_controls[i].id == c->id) {
+			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
+			memcpy(c, &pwc_controls[i], sizeof(struct v4l2_queryctrl));
 			return 0;
 		}
+	}
+	return -EINVAL;
+}
 
-		/* TODO: */
-		case VIDIOC_QUERYCTRL:
-		{
-			struct v4l2_queryctrl *c = arg;
-			int i;
-
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) query id=%d\n", c->id);
-			for (i=0; i<sizeof(pwc_controls)/sizeof(struct v4l2_queryctrl); i++) {
-				if (pwc_controls[i].id == c->id) {
-					PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) found\n");
-					memcpy(c,&pwc_controls[i],sizeof(struct v4l2_queryctrl));
-					return 0;
-				}
-			}
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYCTRL) not found\n");
+static int pwc_g_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+	int ret;
 
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		c->value = pwc_get_brightness(pdev);
+		if (c->value < 0)
 			return -EINVAL;
-		}
-		case VIDIOC_G_CTRL:
-		{
-			struct v4l2_control *c = arg;
-			int ret;
-
-			switch (c->id)
-			{
-				case V4L2_CID_BRIGHTNESS:
-					c->value = pwc_get_brightness(pdev);
-					if (c->value<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_CONTRAST:
-					c->value = pwc_get_contrast(pdev);
-					if (c->value<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_SATURATION:
-					ret = pwc_get_saturation(pdev, &c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_GAMMA:
-					c->value = pwc_get_gamma(pdev);
-					if (c->value<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_RED_BALANCE:
-					ret = pwc_get_red_gain(pdev, &c->value);
-					if (ret<0)
-						return -EINVAL;
-					c->value >>= 8;
-					return 0;
-				case V4L2_CID_BLUE_BALANCE:
-					ret = pwc_get_blue_gain(pdev, &c->value);
-					if (ret<0)
-						return -EINVAL;
-					c->value >>= 8;
-					return 0;
-				case V4L2_CID_AUTO_WHITE_BALANCE:
-					ret = pwc_get_awb(pdev);
-					if (ret<0)
-						return -EINVAL;
-					c->value = (ret == PWC_WB_MANUAL)?0:1;
-					return 0;
-				case V4L2_CID_GAIN:
-					ret = pwc_get_agc(pdev, &c->value);
-					if (ret<0)
-						return -EINVAL;
-					c->value >>= 8;
-					return 0;
-				case V4L2_CID_AUTOGAIN:
-					ret = pwc_get_agc(pdev, &c->value);
-					if (ret<0)
-						return -EINVAL;
-					c->value = (c->value < 0)?1:0;
-					return 0;
-				case V4L2_CID_EXPOSURE:
-					ret = pwc_get_shutter_speed(pdev, &c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_COLOUR_MODE:
-					ret = pwc_get_colour_mode(pdev, &c->value);
-					if (ret < 0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_AUTOCONTOUR:
-					ret = pwc_get_contour(pdev, &c->value);
-					if (ret < 0)
-						return -EINVAL;
-					c->value=(c->value == -1?1:0);
-					return 0;
-				case V4L2_CID_PRIVATE_CONTOUR:
-					ret = pwc_get_contour(pdev, &c->value);
-					if (ret < 0)
-						return -EINVAL;
-					c->value >>= 10;
-					return 0;
-				case V4L2_CID_PRIVATE_BACKLIGHT:
-					ret = pwc_get_backlight(pdev, &c->value);
-					if (ret < 0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_FLICKERLESS:
-					ret = pwc_get_flicker(pdev, &c->value);
-					if (ret < 0)
-						return -EINVAL;
-					c->value=(c->value?1:0);
-					return 0;
-				case V4L2_CID_PRIVATE_NOISE_REDUCTION:
-					ret = pwc_get_dynamic_noise(pdev, &c->value);
-					if (ret < 0)
-						return -EINVAL;
-					return 0;
-
-				case V4L2_CID_PRIVATE_SAVE_USER:
-				case V4L2_CID_PRIVATE_RESTORE_USER:
-				case V4L2_CID_PRIVATE_RESTORE_FACTORY:
-					return -EINVAL;
-			}
+		return 0;
+	case V4L2_CID_CONTRAST:
+		c->value = pwc_get_contrast(pdev);
+		if (c->value < 0)
 			return -EINVAL;
-		}
-		case VIDIOC_S_CTRL:
-		{
-			struct v4l2_control *c = arg;
-			int ret;
-
-			switch (c->id)
-			{
-				case V4L2_CID_BRIGHTNESS:
-					c->value <<= 9;
-					ret = pwc_set_brightness(pdev, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_CONTRAST:
-					c->value <<= 10;
-					ret = pwc_set_contrast(pdev, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_SATURATION:
-					ret = pwc_set_saturation(pdev, c->value);
-					if (ret<0)
-					  return -EINVAL;
-					return 0;
-				case V4L2_CID_GAMMA:
-					c->value <<= 11;
-					ret = pwc_set_gamma(pdev, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_RED_BALANCE:
-					c->value <<= 8;
-					ret = pwc_set_red_gain(pdev, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_BLUE_BALANCE:
-					c->value <<= 8;
-					ret = pwc_set_blue_gain(pdev, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_AUTO_WHITE_BALANCE:
-					c->value = (c->value == 0)?PWC_WB_MANUAL:PWC_WB_AUTO;
-					ret = pwc_set_awb(pdev, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_EXPOSURE:
-					c->value <<= 8;
-					ret = pwc_set_shutter_speed(pdev, c->value?0:1, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_AUTOGAIN:
-					/* autogain off means nothing without a gain */
-					if (c->value == 0)
-						return 0;
-					ret = pwc_set_agc(pdev, c->value, 0);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_GAIN:
-					c->value <<= 8;
-					ret = pwc_set_agc(pdev, 0, c->value);
-					if (ret<0)
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_SAVE_USER:
-					if (pwc_save_user(pdev))
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_RESTORE_USER:
-					if (pwc_restore_user(pdev))
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_RESTORE_FACTORY:
-					if (pwc_restore_factory(pdev))
-						return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_COLOUR_MODE:
-					ret = pwc_set_colour_mode(pdev, c->value);
-					if (ret < 0)
-					  return -EINVAL;
-					return 0;
-				case V4L2_CID_PRIVATE_AUTOCONTOUR:
-				  c->value=(c->value == 1)?-1:0;
-				  ret = pwc_set_contour(pdev, c->value);
-				  if (ret < 0)
-				    return -EINVAL;
-				  return 0;
-				case V4L2_CID_PRIVATE_CONTOUR:
-				  c->value <<= 10;
-				  ret = pwc_set_contour(pdev, c->value);
-				  if (ret < 0)
-				    return -EINVAL;
-				  return 0;
-				case V4L2_CID_PRIVATE_BACKLIGHT:
-				  ret = pwc_set_backlight(pdev, c->value);
-				  if (ret < 0)
-				    return -EINVAL;
-				  return 0;
-				case V4L2_CID_PRIVATE_FLICKERLESS:
-				  ret = pwc_set_flicker(pdev, c->value);
-				  if (ret < 0)
-				    return -EINVAL;
-				case V4L2_CID_PRIVATE_NOISE_REDUCTION:
-				  ret = pwc_set_dynamic_noise(pdev, c->value);
-				  if (ret < 0)
-				    return -EINVAL;
-				  return 0;
-
-			}
+		return 0;
+	case V4L2_CID_SATURATION:
+		ret = pwc_get_saturation(pdev, &c->value);
+		if (ret < 0)
 			return -EINVAL;
-		}
+		return 0;
+	case V4L2_CID_GAMMA:
+		c->value = pwc_get_gamma(pdev);
+		if (c->value < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_RED_BALANCE:
+		ret = pwc_get_red_gain(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value >>= 8;
+		return 0;
+	case V4L2_CID_BLUE_BALANCE:
+		ret = pwc_get_blue_gain(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value >>= 8;
+		return 0;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		ret = pwc_get_awb(pdev);
+		if (ret < 0)
+			return -EINVAL;
+		c->value = (ret == PWC_WB_MANUAL) ? 0 : 1;
+		return 0;
+	case V4L2_CID_GAIN:
+		ret = pwc_get_agc(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value >>= 8;
+		return 0;
+	case V4L2_CID_AUTOGAIN:
+		ret = pwc_get_agc(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value = (c->value < 0) ? 1 : 0;
+		return 0;
+	case V4L2_CID_EXPOSURE:
+		ret = pwc_get_shutter_speed(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_COLOUR_MODE:
+		ret = pwc_get_colour_mode(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_AUTOCONTOUR:
+		ret = pwc_get_contour(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value = (c->value == -1 ? 1 : 0);
+		return 0;
+	case V4L2_CID_PRIVATE_CONTOUR:
+		ret = pwc_get_contour(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value >>= 10;
+		return 0;
+	case V4L2_CID_PRIVATE_BACKLIGHT:
+		ret = pwc_get_backlight(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_FLICKERLESS:
+		ret = pwc_get_flicker(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		c->value = (c->value ? 1 : 0);
+		return 0;
+	case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+		ret = pwc_get_dynamic_noise(pdev, &c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
 
-		case VIDIOC_ENUM_FMT:
-		{
-			struct v4l2_fmtdesc *f = arg;
-			int index;
+	case V4L2_CID_PRIVATE_SAVE_USER:
+	case V4L2_CID_PRIVATE_RESTORE_USER:
+	case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+		return -EINVAL;
+	}
+	return -EINVAL;
+}
 
-			if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			      return -EINVAL;
+static int pwc_s_ctrl(struct file *file, void *fh, struct v4l2_control *c)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+	int ret;
 
-			/* We only support two format: the raw format, and YUV */
-			index = f->index;
-			memset(f,0,sizeof(struct v4l2_fmtdesc));
-			f->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-			f->index = index;
-			switch(index)
-			{
-				case 0:
-					/* RAW format */
-					f->pixelformat = pdev->type<=646?V4L2_PIX_FMT_PWC1:V4L2_PIX_FMT_PWC2;
-					f->flags = V4L2_FMT_FLAG_COMPRESSED;
-					strlcpy(f->description,"Raw Philips Webcam",sizeof(f->description));
-					break;
-				case 1:
-					f->pixelformat = V4L2_PIX_FMT_YUV420;
-					strlcpy(f->description,"4:2:0, planar, Y-Cb-Cr",sizeof(f->description));
-					break;
-				default:
-					return -EINVAL;
-			}
+	switch (c->id) {
+	case V4L2_CID_BRIGHTNESS:
+		c->value <<= 9;
+		ret = pwc_set_brightness(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_CONTRAST:
+		c->value <<= 10;
+		ret = pwc_set_contrast(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_SATURATION:
+		ret = pwc_set_saturation(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_GAMMA:
+		c->value <<= 11;
+		ret = pwc_set_gamma(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_RED_BALANCE:
+		c->value <<= 8;
+		ret = pwc_set_red_gain(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_BLUE_BALANCE:
+		c->value <<= 8;
+		ret = pwc_set_blue_gain(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_AUTO_WHITE_BALANCE:
+		c->value = (c->value == 0) ? PWC_WB_MANUAL : PWC_WB_AUTO;
+		ret = pwc_set_awb(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_EXPOSURE:
+		c->value <<= 8;
+		ret = pwc_set_shutter_speed(pdev, c->value ? 0 : 1, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_AUTOGAIN:
+		/* autogain off means nothing without a gain */
+		if (c->value == 0)
 			return 0;
-		}
-
-		case VIDIOC_G_FMT:
-		{
-			struct v4l2_format *f = arg;
-
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",pdev->image.x,pdev->image.y);
-			if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-			      return -EINVAL;
+		ret = pwc_set_agc(pdev, c->value, 0);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_GAIN:
+		c->value <<= 8;
+		ret = pwc_set_agc(pdev, 0, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_SAVE_USER:
+		if (pwc_save_user(pdev))
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_RESTORE_USER:
+		if (pwc_restore_user(pdev))
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_RESTORE_FACTORY:
+		if (pwc_restore_factory(pdev))
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_COLOUR_MODE:
+		ret = pwc_set_colour_mode(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_AUTOCONTOUR:
+		c->value = (c->value == 1) ? -1 : 0;
+		ret = pwc_set_contour(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_CONTOUR:
+		c->value <<= 10;
+		ret = pwc_set_contour(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_BACKLIGHT:
+		ret = pwc_set_backlight(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
+	case V4L2_CID_PRIVATE_FLICKERLESS:
+		ret = pwc_set_flicker(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+	case V4L2_CID_PRIVATE_NOISE_REDUCTION:
+		ret = pwc_set_dynamic_noise(pdev, c->value);
+		if (ret < 0)
+			return -EINVAL;
+		return 0;
 
-			pwc_vidioc_fill_fmt(pdev, f);
+	}
+	return -EINVAL;
+}
 
-			return 0;
-		}
+static int pwc_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *f)
+{
+	struct pwc_device *pdev = video_drvdata(file);
 
-		case VIDIOC_TRY_FMT:
-			return pwc_vidioc_try_fmt(pdev, arg);
+	/* We only support two format: the raw format, and YUV */
+	switch (f->index) {
+	case 0:
+		/* RAW format */
+		f->pixelformat = pdev->type <= 646 ? V4L2_PIX_FMT_PWC1 : V4L2_PIX_FMT_PWC2;
+		f->flags = V4L2_FMT_FLAG_COMPRESSED;
+		strlcpy(f->description, "Raw Philips Webcam", sizeof(f->description));
+		break;
+	case 1:
+		f->pixelformat = V4L2_PIX_FMT_YUV420;
+		strlcpy(f->description, "4:2:0, planar, Y-Cb-Cr", sizeof(f->description));
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
 
-		case VIDIOC_S_FMT:
-			return pwc_vidioc_set_fmt(pdev, arg);
+static int pwc_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct pwc_device *pdev = video_drvdata(file);
 
-		case VIDIOC_G_STD:
-		{
-			v4l2_std_id *std = arg;
-			*std = V4L2_STD_UNKNOWN;
-			return 0;
-		}
+	PWC_DEBUG_IOCTL("ioctl(VIDIOC_G_FMT) return size %dx%d\n",
+			pdev->image.x, pdev->image.y);
+	pwc_vidioc_fill_fmt(pdev, f);
+	return 0;
+}
 
-		case VIDIOC_S_STD:
-		{
-			v4l2_std_id *std = arg;
-			if (*std != V4L2_STD_UNKNOWN)
-				return -EINVAL;
-			return 0;
-		}
+static int pwc_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct pwc_device *pdev = video_drvdata(file);
 
-		case VIDIOC_ENUMSTD:
-		{
-			struct v4l2_standard *std = arg;
-			if (std->index != 0)
-				return -EINVAL;
-			std->id = V4L2_STD_UNKNOWN;
-			strlcpy(std->name, "webcam", sizeof(std->name));
-			return 0;
-		}
+	return pwc_vidioc_try_fmt(pdev, f);
+}
 
-		case VIDIOC_REQBUFS:
-		{
-			struct v4l2_requestbuffers *rb = arg;
-			int nbuffers;
+static int pwc_s_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f)
+{
+	struct pwc_device *pdev = video_drvdata(file);
 
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n",rb->count);
-			if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-				return -EINVAL;
-			if (rb->memory != V4L2_MEMORY_MMAP)
-				return -EINVAL;
+	return pwc_vidioc_set_fmt(pdev, f);
+}
 
-			nbuffers = rb->count;
-			if (nbuffers < 2)
-				nbuffers = 2;
-			else if (nbuffers > pwc_mbufs)
-				nbuffers = pwc_mbufs;
-			/* Force to use our # of buffers */
-			rb->count = pwc_mbufs;
-			return 0;
-		}
+static int pwc_reqbufs(struct file *file, void *fh, struct v4l2_requestbuffers *rb)
+{
+	int nbuffers;
 
-		case VIDIOC_QUERYBUF:
-		{
-			struct v4l2_buffer *buf = arg;
-			int index;
+	PWC_DEBUG_IOCTL("ioctl(VIDIOC_REQBUFS) count=%d\n", rb->count);
+	if (rb->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (rb->memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
 
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n",buf->index);
-			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-				PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
-				return -EINVAL;
-			}
-			if (buf->memory != V4L2_MEMORY_MMAP) {
-				PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad memory type\n");
-				return -EINVAL;
-			}
-			index = buf->index;
-			if (index < 0 || index >= pwc_mbufs) {
-				PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
-				return -EINVAL;
-			}
+	nbuffers = rb->count;
+	if (nbuffers < 2)
+		nbuffers = 2;
+	else if (nbuffers > pwc_mbufs)
+		nbuffers = pwc_mbufs;
+	/* Force to use our # of buffers */
+	rb->count = pwc_mbufs;
+	return 0;
+}
 
-			memset(buf, 0, sizeof(struct v4l2_buffer));
-			buf->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-			buf->index = index;
-			buf->m.offset = index * pdev->len_per_image;
-			if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
-			else
-				buf->bytesused = pdev->view.size;
-			buf->field = V4L2_FIELD_NONE;
-			buf->memory = V4L2_MEMORY_MMAP;
-			//buf->flags = V4L2_BUF_FLAG_MAPPED;
-			buf->length = pdev->len_per_image;
+static int pwc_querybuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+	int index;
 
-			PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n",buf->index);
-			PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n",buf->m.offset);
-			PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n",buf->bytesused);
+	PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) index=%d\n", buf->index);
+	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad type\n");
+		return -EINVAL;
+	}
+	index = buf->index;
+	if (index < 0 || index >= pwc_mbufs) {
+		PWC_DEBUG_IOCTL("ioctl(VIDIOC_QUERYBUF) Bad index %d\n", buf->index);
+		return -EINVAL;
+	}
 
-			return 0;
-		}
+	buf->m.offset = index * pdev->len_per_image;
+	if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
+		buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+	else
+		buf->bytesused = pdev->view.size;
+	buf->field = V4L2_FIELD_NONE;
+	buf->memory = V4L2_MEMORY_MMAP;
+	/*buf->flags = V4L2_BUF_FLAG_MAPPED;*/
+	buf->length = pdev->len_per_image;
 
-		case VIDIOC_QBUF:
-		{
-			struct v4l2_buffer *buf = arg;
+	PWC_DEBUG_READ("VIDIOC_QUERYBUF: index=%d\n", buf->index);
+	PWC_DEBUG_READ("VIDIOC_QUERYBUF: m.offset=%d\n", buf->m.offset);
+	PWC_DEBUG_READ("VIDIOC_QUERYBUF: bytesused=%d\n", buf->bytesused);
 
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n",buf->index);
-			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-				return -EINVAL;
-			if (buf->memory != V4L2_MEMORY_MMAP)
-				return -EINVAL;
-			if (buf->index >= pwc_mbufs)
-				return -EINVAL;
+	return 0;
+}
 
-			buf->flags |= V4L2_BUF_FLAG_QUEUED;
-			buf->flags &= ~V4L2_BUF_FLAG_DONE;
+static int pwc_qbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	PWC_DEBUG_IOCTL("ioctl(VIDIOC_QBUF) index=%d\n", buf->index);
+	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+	if (buf->memory != V4L2_MEMORY_MMAP)
+		return -EINVAL;
+	if (buf->index >= pwc_mbufs)
+		return -EINVAL;
 
-			return 0;
-		}
+	buf->flags |= V4L2_BUF_FLAG_QUEUED;
+	buf->flags &= ~V4L2_BUF_FLAG_DONE;
 
-		case VIDIOC_DQBUF:
-		{
-			struct v4l2_buffer *buf = arg;
-			int ret;
+	return 0;
+}
 
-			PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
+static int pwc_dqbuf(struct file *file, void *fh, struct v4l2_buffer *buf)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	struct pwc_device *pdev = video_drvdata(file);
+	int ret;
 
-			if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-				return -EINVAL;
+	PWC_DEBUG_IOCTL("ioctl(VIDIOC_DQBUF)\n");
 
-			/* Add ourselves to the frame wait-queue.
+	if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
 
-			   FIXME: needs auditing for safety.
-			   QUESTION: In what respect? I think that using the
-				     frameq is safe now.
-			 */
-			add_wait_queue(&pdev->frameq, &wait);
-			while (pdev->full_frames == NULL) {
-				if (pdev->error_status) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -pdev->error_status;
-				}
+	add_wait_queue(&pdev->frameq, &wait);
+	while (pdev->full_frames == NULL) {
+		if (pdev->error_status) {
+			remove_wait_queue(&pdev->frameq, &wait);
+			set_current_state(TASK_RUNNING);
+			return -pdev->error_status;
+		}
 
-				if (signal_pending(current)) {
-					remove_wait_queue(&pdev->frameq, &wait);
-					set_current_state(TASK_RUNNING);
-					return -ERESTARTSYS;
-				}
-				schedule();
-				set_current_state(TASK_INTERRUPTIBLE);
-			}
+		if (signal_pending(current)) {
 			remove_wait_queue(&pdev->frameq, &wait);
 			set_current_state(TASK_RUNNING);
+			return -ERESTARTSYS;
+		}
+		mutex_unlock(&pdev->modlock);
+		schedule();
+		set_current_state(TASK_INTERRUPTIBLE);
+		mutex_lock(&pdev->modlock);
+	}
+	remove_wait_queue(&pdev->frameq, &wait);
+	set_current_state(TASK_RUNNING);
 
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
-			/* Decompress data in pdev->images[pdev->fill_image] */
-			ret = pwc_handle_frame(pdev);
-			if (ret)
-				return -EFAULT;
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: frame ready.\n");
+	/* Decompress data in pdev->images[pdev->fill_image] */
+	ret = pwc_handle_frame(pdev);
+	if (ret)
+		return -EFAULT;
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: after pwc_handle_frame\n");
 
-			buf->index = pdev->fill_image;
-			if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
-				buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
-			else
-				buf->bytesused = pdev->view.size;
-			buf->flags = V4L2_BUF_FLAG_MAPPED;
-			buf->field = V4L2_FIELD_NONE;
-			do_gettimeofday(&buf->timestamp);
-			buf->sequence = 0;
-			buf->memory = V4L2_MEMORY_MMAP;
-			buf->m.offset = pdev->fill_image * pdev->len_per_image;
-			buf->length = pdev->len_per_image;
-			pwc_next_image(pdev);
+	buf->index = pdev->fill_image;
+	if (pdev->pixfmt != V4L2_PIX_FMT_YUV420)
+		buf->bytesused = pdev->frame_size + sizeof(struct pwc_raw_frame);
+	else
+		buf->bytesused = pdev->view.size;
+	buf->flags = V4L2_BUF_FLAG_MAPPED;
+	buf->field = V4L2_FIELD_NONE;
+	do_gettimeofday(&buf->timestamp);
+	buf->sequence = 0;
+	buf->memory = V4L2_MEMORY_MMAP;
+	buf->m.offset = pdev->fill_image * pdev->len_per_image;
+	buf->length = pdev->len_per_image;
+	pwc_next_image(pdev);
 
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n",buf->index);
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n",buf->length);
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n",buf->m.offset);
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n",buf->bytesused);
-			PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
-			return 0;
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->index=%d\n", buf->index);
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: buf->length=%d\n", buf->length);
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: m.offset=%d\n", buf->m.offset);
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: bytesused=%d\n", buf->bytesused);
+	PWC_DEBUG_IOCTL("VIDIOC_DQBUF: leaving\n");
+	return 0;
 
-		}
+}
 
-		case VIDIOC_STREAMON:
-		{
-			return pwc_isoc_init(pdev);
-		}
+static int pwc_streamon(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+	struct pwc_device *pdev = video_drvdata(file);
 
-		case VIDIOC_STREAMOFF:
-		{
-			pwc_isoc_cleanup(pdev);
-			return 0;
-		}
+	return pwc_isoc_init(pdev);
+}
 
-		case VIDIOC_ENUM_FRAMESIZES:
-		{
-			struct v4l2_frmsizeenum *fsize = arg;
-			unsigned int i = 0, index = fsize->index;
+static int pwc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
+{
+	struct pwc_device *pdev = video_drvdata(file);
 
-			if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
-				for (i = 0; i < PSZ_MAX; i++) {
-					if (pdev->image_mask & (1UL << i)) {
-						if (!index--) {
-							fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-							fsize->discrete.width = pwc_image_sizes[i].x;
-							fsize->discrete.height = pwc_image_sizes[i].y;
-							return 0;
-						}
-					}
-				}
-			} else if (fsize->index == 0 &&
-				   ((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
-				    (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
+	pwc_isoc_cleanup(pdev);
+	return 0;
+}
 
-				fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
-				fsize->discrete.width = pdev->abs_max.x;
-				fsize->discrete.height = pdev->abs_max.y;
-				return 0;
+static int pwc_enum_framesizes(struct file *file, void *fh,
+					 struct v4l2_frmsizeenum *fsize)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+	unsigned int i = 0, index = fsize->index;
+
+	if (fsize->pixel_format == V4L2_PIX_FMT_YUV420) {
+		for (i = 0; i < PSZ_MAX; i++) {
+			if (pdev->image_mask & (1UL << i)) {
+				if (!index--) {
+					fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+					fsize->discrete.width = pwc_image_sizes[i].x;
+					fsize->discrete.height = pwc_image_sizes[i].y;
+					return 0;
+				}
 			}
-			return -EINVAL;
 		}
+	} else if (fsize->index == 0 &&
+			((fsize->pixel_format == V4L2_PIX_FMT_PWC1 && DEVICE_USE_CODEC1(pdev->type)) ||
+			 (fsize->pixel_format == V4L2_PIX_FMT_PWC2 && DEVICE_USE_CODEC23(pdev->type)))) {
 
-		case VIDIOC_ENUM_FRAMEINTERVALS:
-		{
-			struct v4l2_frmivalenum *fival = arg;
-			int size = -1;
-			unsigned int i;
+		fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
+		fsize->discrete.width = pdev->abs_max.x;
+		fsize->discrete.height = pdev->abs_max.y;
+		return 0;
+	}
+	return -EINVAL;
+}
 
-			for (i = 0; i < PSZ_MAX; i++) {
-				if (pwc_image_sizes[i].x == fival->width &&
-				    pwc_image_sizes[i].y == fival->height) {
-					size = i;
-					break;
-				}
-			}
+static int pwc_enum_frameintervals(struct file *file, void *fh,
+					   struct v4l2_frmivalenum *fival)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+	int size = -1;
+	unsigned int i;
 
-			/* TODO: Support raw format */
-			if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420) {
-				return -EINVAL;
-			}
+	for (i = 0; i < PSZ_MAX; i++) {
+		if (pwc_image_sizes[i].x == fival->width &&
+				pwc_image_sizes[i].y == fival->height) {
+			size = i;
+			break;
+		}
+	}
 
-			i = pwc_get_fps(pdev, fival->index, size);
-			if (!i)
-				return -EINVAL;
+	/* TODO: Support raw format */
+	if (size < 0 || fival->pixel_format != V4L2_PIX_FMT_YUV420)
+		return -EINVAL;
 
-			fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
-			fival->discrete.numerator = 1;
-			fival->discrete.denominator = i;
+	i = pwc_get_fps(pdev, fival->index, size);
+	if (!i)
+		return -EINVAL;
 
-			return 0;
-		}
+	fival->type = V4L2_FRMIVAL_TYPE_DISCRETE;
+	fival->discrete.numerator = 1;
+	fival->discrete.denominator = i;
 
-		default:
-			return pwc_ioctl(pdev, cmd, arg);
-	} /* ..switch */
 	return 0;
 }
 
+static long pwc_default(struct file *file, void *fh, bool valid_prio,
+			int cmd, void *arg)
+{
+	struct pwc_device *pdev = video_drvdata(file);
+
+	return pwc_ioctl(pdev, cmd, arg);
+}
+
+const struct v4l2_ioctl_ops pwc_ioctl_ops = {
+	.vidioc_querycap		    = pwc_querycap,
+	.vidioc_enum_input		    = pwc_enum_input,
+	.vidioc_g_input			    = pwc_g_input,
+	.vidioc_s_input			    = pwc_s_input,
+	.vidioc_enum_fmt_vid_cap	    = pwc_enum_fmt_vid_cap,
+	.vidioc_g_fmt_vid_cap		    = pwc_g_fmt_vid_cap,
+	.vidioc_s_fmt_vid_cap		    = pwc_s_fmt_vid_cap,
+	.vidioc_try_fmt_vid_cap		    = pwc_try_fmt_vid_cap,
+	.vidioc_queryctrl		    = pwc_queryctrl,
+	.vidioc_g_ctrl			    = pwc_g_ctrl,
+	.vidioc_s_ctrl			    = pwc_s_ctrl,
+	.vidioc_reqbufs			    = pwc_reqbufs,
+	.vidioc_querybuf		    = pwc_querybuf,
+	.vidioc_qbuf			    = pwc_qbuf,
+	.vidioc_dqbuf			    = pwc_dqbuf,
+	.vidioc_streamon		    = pwc_streamon,
+	.vidioc_streamoff		    = pwc_streamoff,
+	.vidioc_enum_framesizes		    = pwc_enum_framesizes,
+	.vidioc_enum_frameintervals	    = pwc_enum_frameintervals,
+	.vidioc_default		    = pwc_default,
+};
+
+
 /* vim: set cino= formatoptions=croql cindent shiftwidth=8 tabstop=8: */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/pxa_camera.c linux-libre-2.6.39-gnu/drivers/media/video/pxa_camera.c
--- linux-libre-2.6.38-gnu/drivers/media/video/pxa_camera.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/pxa_camera.c	2011-05-19 00:06:34.000000000 -0400
@@ -714,7 +714,7 @@
  *
  * The DMA chaining is done with DMA running. This means a tiny temporal window
  * remains, where a buffer is queued on the chain, while the chain is already
- * stopped. This means the tailed buffer would never be transfered by DMA.
+ * stopped. This means the tailed buffer would never be transferred by DMA.
  * This function restarts the capture for this corner case, where :
  *  - DADR() == DADDR_STOP
  *  - a videobuffer is queued on the pcdev->capture list
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-capture.c linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-capture.c
--- linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-capture.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-capture.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,13 +27,13 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-mem2mem.h>
-#include <media/videobuf-core.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
 
 #include "fimc-core.h"
 
 static struct v4l2_subdev *fimc_subdev_register(struct fimc_dev *fimc,
-					    struct s3c_fimc_isp_info *isp_info)
+					    struct s5p_fimc_isp_info *isp_info)
 {
 	struct i2c_adapter *i2c_adap;
 	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
@@ -86,19 +86,19 @@
 static int fimc_subdev_attach(struct fimc_dev *fimc, int index)
 {
 	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
-	struct s3c_platform_fimc *pdata = fimc->pdata;
-	struct s3c_fimc_isp_info *isp_info;
+	struct s5p_platform_fimc *pdata = fimc->pdata;
+	struct s5p_fimc_isp_info *isp_info;
 	struct v4l2_subdev *sd;
 	int i;
 
-	for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i) {
-		isp_info = pdata->isp_info[i];
+	for (i = 0; i < pdata->num_clients; ++i) {
+		isp_info = &pdata->isp_info[i];
 
-		if (!isp_info || (index >= 0 && i != index))
+		if (index >= 0 && i != index)
 			continue;
 
 		sd = fimc_subdev_register(fimc, isp_info);
-		if (sd) {
+		if (!IS_ERR_OR_NULL(sd)) {
 			vid_cap->sd = sd;
 			vid_cap->input_index = i;
 
@@ -113,60 +113,42 @@
 	return -ENODEV;
 }
 
-static int fimc_isp_subdev_init(struct fimc_dev *fimc, int index)
+static int fimc_isp_subdev_init(struct fimc_dev *fimc, unsigned int index)
 {
-	struct s3c_fimc_isp_info *isp_info;
+	struct s5p_fimc_isp_info *isp_info;
+	struct s5p_platform_fimc *pdata = fimc->pdata;
 	int ret;
 
-	ret = fimc_subdev_attach(fimc, index);
-	if (ret)
-		return ret;
+	if (index >= pdata->num_clients)
+		return -EINVAL;
 
-	isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
-	ret = fimc_hw_set_camera_polarity(fimc, isp_info);
-	if (!ret) {
-		ret = v4l2_subdev_call(fimc->vid_cap.sd, core,
-				       s_power, 1);
-		if (!ret)
-			return ret;
-	}
+	isp_info = &pdata->isp_info[index];
 
-	fimc_subdev_unregister(fimc);
-	err("ISP initialization failed: %d", ret);
-	return ret;
-}
+	if (isp_info->clk_frequency)
+		clk_set_rate(fimc->clock[CLK_CAM], isp_info->clk_frequency);
 
-/*
- * At least one buffer on the pending_buf_q queue is required.
- * Locking: The caller holds fimc->slock spinlock.
- */
-int fimc_vid_cap_buf_queue(struct fimc_dev *fimc,
-			     struct fimc_vid_buffer *fimc_vb)
-{
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	struct fimc_ctx *ctx = cap->ctx;
-	int ret = 0;
+	ret = clk_enable(fimc->clock[CLK_CAM]);
+	if (ret)
+		return ret;
 
-	BUG_ON(!fimc || !fimc_vb);
+	ret = fimc_subdev_attach(fimc, index);
+	if (ret)
+		return ret;
 
-	ret = fimc_prepare_addr(ctx, fimc_vb, &ctx->d_frame,
-				&fimc_vb->paddr);
+	ret = fimc_hw_set_camera_polarity(fimc, isp_info);
 	if (ret)
 		return ret;
 
-	if (test_bit(ST_CAPT_STREAM, &fimc->state)) {
-		fimc_pending_queue_add(cap, fimc_vb);
-	} else {
-		/* Setup the buffer directly for processing. */
-		int buf_id = (cap->reqbufs_count == 1) ? -1 : cap->buf_index;
-		fimc_hw_set_output_addr(fimc, &fimc_vb->paddr, buf_id);
+	ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 1);
+	if (!ret)
+		return ret;
 
-		fimc_vb->index = cap->buf_index;
-		active_queue_add(cap, fimc_vb);
+	/* enabling power failed so unregister subdev */
+	fimc_subdev_unregister(fimc);
+
+	v4l2_err(&fimc->vid_cap.v4l2_dev, "ISP initialization failed: %d\n",
+		 ret);
 
-		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
-			cap->buf_index = 0;
-	}
 	return ret;
 }
 
@@ -174,7 +156,7 @@
 {
 	unsigned long flags;
 	struct fimc_vid_cap *cap;
-	int ret;
+	struct fimc_vid_buffer *buf;
 
 	cap = &fimc->vid_cap;
 
@@ -187,24 +169,224 @@
 	spin_unlock_irqrestore(&fimc->slock, flags);
 
 	wait_event_timeout(fimc->irq_queue,
-			   test_bit(ST_CAPT_SHUT, &fimc->state),
+			   !test_bit(ST_CAPT_SHUT, &fimc->state),
 			   FIMC_SHUTDOWN_TIMEOUT);
 
-	ret = v4l2_subdev_call(cap->sd, video, s_stream, 0);
-	if (ret)
-		v4l2_err(&fimc->vid_cap.v4l2_dev, "s_stream(0) failed\n");
+	v4l2_subdev_call(cap->sd, video, s_stream, 0);
 
 	spin_lock_irqsave(&fimc->slock, flags);
 	fimc->state &= ~(1 << ST_CAPT_RUN | 1 << ST_CAPT_PEND |
-			1 << ST_CAPT_STREAM);
+			 1 << ST_CAPT_SHUT | 1 << ST_CAPT_STREAM);
 
 	fimc->vid_cap.active_buf_cnt = 0;
+
+	/* Release buffers that were enqueued in the driver by videobuf2. */
+	while (!list_empty(&cap->pending_buf_q)) {
+		buf = pending_queue_pop(cap);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+
+	while (!list_empty(&cap->active_buf_q)) {
+		buf = active_queue_pop(cap);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+	}
+
 	spin_unlock_irqrestore(&fimc->slock, flags);
 
 	dbg("state: 0x%lx", fimc->state);
 	return 0;
 }
 
+static int start_streaming(struct vb2_queue *q)
+{
+	struct fimc_ctx *ctx = q->drv_priv;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct s5p_fimc_isp_info *isp_info;
+	int ret;
+
+	fimc_hw_reset(fimc);
+
+	ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
+	if (ret && ret != -ENOIOCTLCMD)
+		return ret;
+
+	ret = fimc_prepare_config(ctx, ctx->state);
+	if (ret)
+		return ret;
+
+	isp_info = &fimc->pdata->isp_info[fimc->vid_cap.input_index];
+	fimc_hw_set_camera_type(fimc, isp_info);
+	fimc_hw_set_camera_source(fimc, isp_info);
+	fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
+
+	if (ctx->state & FIMC_PARAMS) {
+		ret = fimc_set_scaler_info(ctx);
+		if (ret) {
+			err("Scaler setup error");
+			return ret;
+		}
+		fimc_hw_set_input_path(ctx);
+		fimc_hw_set_prescaler(ctx);
+		fimc_hw_set_mainscaler(ctx);
+		fimc_hw_set_target_format(ctx);
+		fimc_hw_set_rotation(ctx);
+		fimc_hw_set_effect(ctx);
+	}
+
+	fimc_hw_set_output_path(ctx);
+	fimc_hw_set_out_dma(ctx);
+
+	INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
+	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
+	fimc->vid_cap.active_buf_cnt = 0;
+	fimc->vid_cap.frame_count = 0;
+	fimc->vid_cap.buf_index = 0;
+
+	set_bit(ST_CAPT_PEND, &fimc->state);
+
+	return 0;
+}
+
+static int stop_streaming(struct vb2_queue *q)
+{
+	struct fimc_ctx *ctx = q->drv_priv;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+
+	if (!fimc_capture_active(fimc))
+		return -EINVAL;
+
+	return fimc_stop_capture(fimc);
+}
+
+static unsigned int get_plane_size(struct fimc_frame *fr, unsigned int plane)
+{
+	if (!fr || plane >= fr->fmt->memplanes)
+		return 0;
+
+	dbg("%s: w: %d. h: %d. depth[%d]: %d",
+	    __func__, fr->width, fr->height, plane, fr->fmt->depth[plane]);
+
+	return fr->f_width * fr->f_height * fr->fmt->depth[plane] / 8;
+
+}
+
+static int queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
+		       unsigned int *num_planes, unsigned long sizes[],
+		       void *allocators[])
+{
+	struct fimc_ctx *ctx = vq->drv_priv;
+	struct fimc_fmt *fmt = ctx->d_frame.fmt;
+	int i;
+
+	if (!fmt)
+		return -EINVAL;
+
+	*num_planes = fmt->memplanes;
+
+	dbg("%s, buffer count=%d, plane count=%d",
+	    __func__, *num_buffers, *num_planes);
+
+	for (i = 0; i < fmt->memplanes; i++) {
+		sizes[i] = get_plane_size(&ctx->d_frame, i);
+		dbg("plane: %u, plane_size: %lu", i, sizes[i]);
+		allocators[i] = ctx->fimc_dev->alloc_ctx;
+	}
+
+	return 0;
+}
+
+static int buffer_init(struct vb2_buffer *vb)
+{
+	/* TODO: */
+	return 0;
+}
+
+static int buffer_prepare(struct vb2_buffer *vb)
+{
+	struct vb2_queue *vq = vb->vb2_queue;
+	struct fimc_ctx *ctx = vq->drv_priv;
+	struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
+	int i;
+
+	if (!ctx->d_frame.fmt || vq->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		return -EINVAL;
+
+	for (i = 0; i < ctx->d_frame.fmt->memplanes; i++) {
+		unsigned long size = get_plane_size(&ctx->d_frame, i);
+
+		if (vb2_plane_size(vb, i) < size) {
+			v4l2_err(v4l2_dev, "User buffer too small (%ld < %ld)\n",
+				 vb2_plane_size(vb, i), size);
+			return -EINVAL;
+		}
+
+		vb2_set_plane_payload(vb, i, size);
+	}
+
+	return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	struct fimc_vid_buffer *buf
+		= container_of(vb, struct fimc_vid_buffer, vb);
+	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
+	unsigned long flags;
+	int min_bufs;
+
+	spin_lock_irqsave(&fimc->slock, flags);
+	fimc_prepare_addr(ctx, &buf->vb, &ctx->d_frame, &buf->paddr);
+
+	if (!test_bit(ST_CAPT_STREAM, &fimc->state)
+	     && vid_cap->active_buf_cnt < FIMC_MAX_OUT_BUFS) {
+		/* Setup the buffer directly for processing. */
+		int buf_id = (vid_cap->reqbufs_count == 1) ? -1 :
+				vid_cap->buf_index;
+
+		fimc_hw_set_output_addr(fimc, &buf->paddr, buf_id);
+		buf->index = vid_cap->buf_index;
+		active_queue_add(vid_cap, buf);
+
+		if (++vid_cap->buf_index >= FIMC_MAX_OUT_BUFS)
+			vid_cap->buf_index = 0;
+	} else {
+		fimc_pending_queue_add(vid_cap, buf);
+	}
+
+	min_bufs = vid_cap->reqbufs_count > 1 ? 2 : 1;
+
+	if (vid_cap->active_buf_cnt >= min_bufs &&
+	    !test_and_set_bit(ST_CAPT_STREAM, &fimc->state))
+		fimc_activate_capture(ctx);
+
+	spin_unlock_irqrestore(&fimc->slock, flags);
+}
+
+static void fimc_lock(struct vb2_queue *vq)
+{
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
+	mutex_lock(&ctx->fimc_dev->lock);
+}
+
+static void fimc_unlock(struct vb2_queue *vq)
+{
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
+	mutex_unlock(&ctx->fimc_dev->lock);
+}
+
+static struct vb2_ops fimc_capture_qops = {
+	.queue_setup		= queue_setup,
+	.buf_prepare		= buffer_prepare,
+	.buf_queue		= buffer_queue,
+	.buf_init		= buffer_init,
+	.wait_prepare		= fimc_unlock,
+	.wait_finish		= fimc_lock,
+	.start_streaming	= start_streaming,
+	.stop_streaming		= stop_streaming,
+};
+
 static int fimc_capture_open(struct file *file)
 {
 	struct fimc_dev *fimc = video_drvdata(file);
@@ -216,44 +398,36 @@
 	if (fimc_m2m_active(fimc))
 		return -EBUSY;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	if (++fimc->vid_cap.refcnt == 1) {
-		ret = fimc_isp_subdev_init(fimc, -1);
+		ret = fimc_isp_subdev_init(fimc, 0);
 		if (ret) {
 			fimc->vid_cap.refcnt--;
-			ret = -EIO;
+			return -EIO;
 		}
 	}
 
 	file->private_data = fimc->vid_cap.ctx;
 
-	mutex_unlock(&fimc->lock);
-	return ret;
+	return 0;
 }
 
 static int fimc_capture_close(struct file *file)
 {
 	struct fimc_dev *fimc = video_drvdata(file);
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	dbg("pid: %d, state: 0x%lx", task_pid_nr(current), fimc->state);
 
 	if (--fimc->vid_cap.refcnt == 0) {
 		fimc_stop_capture(fimc);
-
-		videobuf_stop(&fimc->vid_cap.vbq);
-		videobuf_mmap_free(&fimc->vid_cap.vbq);
+		vb2_queue_release(&fimc->vid_cap.vbq);
 
 		v4l2_err(&fimc->vid_cap.v4l2_dev, "releasing ISP\n");
+
 		v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
+		clk_disable(fimc->clock[CLK_CAM]);
 		fimc_subdev_unregister(fimc);
 	}
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -262,32 +436,16 @@
 {
 	struct fimc_ctx *ctx = file->private_data;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	int ret;
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return POLLERR;
-
-	ret = videobuf_poll_stream(file, &cap->vbq, wait);
-	mutex_unlock(&fimc->lock);
 
-	return ret;
+	return vb2_poll(&fimc->vid_cap.vbq, file, wait);
 }
 
 static int fimc_capture_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct fimc_ctx *ctx = file->private_data;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	int ret;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
-	ret = videobuf_mmap_mapper(&cap->vbq, vma);
-	mutex_unlock(&fimc->lock);
-
-	return ret;
+	return vb2_mmap(&fimc->vid_cap.vbq, vma);
 }
 
 /* video device file operations */
@@ -310,7 +468,8 @@
 	strncpy(cap->card, fimc->pdev->name, sizeof(cap->card) - 1);
 	cap->bus_info[0] = 0;
 	cap->version = KERNEL_VERSION(1, 0, 0);
-	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE;
+	cap->capabilities = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_CAPTURE |
+			    V4L2_CAP_VIDEO_CAPTURE_MPLANE;
 
 	return 0;
 }
@@ -351,57 +510,54 @@
 	return 0;
 }
 
-static int fimc_cap_s_fmt(struct file *file, void *priv,
-			     struct v4l2_format *f)
+static int fimc_cap_s_fmt_mplane(struct file *file, void *priv,
+				 struct v4l2_format *f)
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct fimc_frame *frame;
-	struct v4l2_pix_format *pix;
+	struct v4l2_pix_format_mplane *pix;
 	int ret;
+	int i;
 
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
 
-	ret = fimc_vidioc_try_fmt(file, priv, f);
+	ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
 	if (ret)
 		return ret;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
-	if (fimc_capture_active(fimc)) {
-		ret = -EBUSY;
-		goto sf_unlock;
-	}
+	if (vb2_is_busy(&fimc->vid_cap.vbq) || fimc_capture_active(fimc))
+		return -EBUSY;
 
 	frame = &ctx->d_frame;
 
-	pix = &f->fmt.pix;
+	pix = &f->fmt.pix_mp;
 	frame->fmt = find_format(f, FMT_FLAGS_M2M | FMT_FLAGS_CAM);
 	if (!frame->fmt) {
 		err("fimc target format not found\n");
-		ret = -EINVAL;
-		goto sf_unlock;
+		return -EINVAL;
+	}
+
+	for (i = 0; i < frame->fmt->colplanes; i++) {
+		frame->payload[i] =
+			(pix->width * pix->height * frame->fmt->depth[i]) >> 3;
 	}
 
 	/* Output DMA frame pixel size and offsets. */
-	frame->f_width	= pix->bytesperline * 8 / frame->fmt->depth;
+	frame->f_width = pix->plane_fmt[0].bytesperline * 8
+			/ frame->fmt->depth[0];
 	frame->f_height = pix->height;
 	frame->width	= pix->width;
 	frame->height	= pix->height;
 	frame->o_width	= pix->width;
 	frame->o_height = pix->height;
-	frame->size	= (pix->width * pix->height * frame->fmt->depth) >> 3;
 	frame->offs_h	= 0;
 	frame->offs_v	= 0;
 
-	ret = sync_capture_fmt(ctx);
-
 	ctx->state |= (FIMC_PARAMS | FIMC_DST_FMT);
 
-sf_unlock:
-	mutex_unlock(&fimc->lock);
+	ret = sync_capture_fmt(ctx);
 	return ret;
 }
 
@@ -409,15 +565,13 @@
 				     struct v4l2_input *i)
 {
 	struct fimc_ctx *ctx = priv;
-	struct s3c_platform_fimc *pldata = ctx->fimc_dev->pdata;
-	struct s3c_fimc_isp_info *isp_info;
+	struct s5p_platform_fimc *pldata = ctx->fimc_dev->pdata;
+	struct s5p_fimc_isp_info *isp_info;
 
-	if (i->index >= FIMC_MAX_CAMIF_CLIENTS)
+	if (i->index >= pldata->num_clients)
 		return -EINVAL;
 
-	isp_info = pldata->isp_info[i->index];
-	if (isp_info == NULL)
-		return -EINVAL;
+	isp_info = &pldata->isp_info[i->index];
 
 	i->type = V4L2_INPUT_TYPE_CAMERA;
 	strncpy(i->name, isp_info->board_info->type, 32);
@@ -429,34 +583,27 @@
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct s3c_platform_fimc *pdata = fimc->pdata;
-	int ret;
+	struct s5p_platform_fimc *pdata = fimc->pdata;
 
 	if (fimc_capture_active(ctx->fimc_dev))
 		return -EBUSY;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
+	if (i >= pdata->num_clients)
+		return -EINVAL;
 
-	if (i >= FIMC_MAX_CAMIF_CLIENTS || !pdata->isp_info[i]) {
-		ret = -EINVAL;
-		goto si_unlock;
-	}
 
 	if (fimc->vid_cap.sd) {
-		ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
+		int ret = v4l2_subdev_call(fimc->vid_cap.sd, core, s_power, 0);
 		if (ret)
 			err("s_power failed: %d", ret);
+
+		clk_disable(fimc->clock[CLK_CAM]);
 	}
 
 	/* Release the attached sensor subdevice. */
 	fimc_subdev_unregister(fimc);
 
-	ret = fimc_isp_subdev_init(fimc, i);
-
-si_unlock:
-	mutex_unlock(&fimc->lock);
-	return ret;
+	return fimc_isp_subdev_init(fimc, i);
 }
 
 static int fimc_cap_g_input(struct file *file, void *priv,
@@ -470,66 +617,20 @@
 }
 
 static int fimc_cap_streamon(struct file *file, void *priv,
-			   enum v4l2_buf_type type)
+			     enum v4l2_buf_type type)
 {
-	struct s3c_fimc_isp_info *isp_info;
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	int ret = -EBUSY;
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
 
 	if (fimc_capture_active(fimc) || !fimc->vid_cap.sd)
-		goto s_unlock;
+		return -EBUSY;
 
 	if (!(ctx->state & FIMC_DST_FMT)) {
 		v4l2_err(&fimc->vid_cap.v4l2_dev, "Format is not set\n");
-		ret = -EINVAL;
-		goto s_unlock;
-	}
-
-	ret = v4l2_subdev_call(fimc->vid_cap.sd, video, s_stream, 1);
-	if (ret && ret != -ENOIOCTLCMD)
-		goto s_unlock;
-
-	ret = fimc_prepare_config(ctx, ctx->state);
-	if (ret)
-		goto s_unlock;
-
-	isp_info = fimc->pdata->isp_info[fimc->vid_cap.input_index];
-	fimc_hw_set_camera_type(fimc, isp_info);
-	fimc_hw_set_camera_source(fimc, isp_info);
-	fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
-
-	if (ctx->state & FIMC_PARAMS) {
-		ret = fimc_set_scaler_info(ctx);
-		if (ret) {
-			err("Scaler setup error");
-			goto s_unlock;
-		}
-		fimc_hw_set_input_path(ctx);
-		fimc_hw_set_scaler(ctx);
-		fimc_hw_set_target_format(ctx);
-		fimc_hw_set_rotation(ctx);
-		fimc_hw_set_effect(ctx);
+		return -EINVAL;
 	}
 
-	fimc_hw_set_output_path(ctx);
-	fimc_hw_set_out_dma(ctx);
-
-	INIT_LIST_HEAD(&fimc->vid_cap.pending_buf_q);
-	INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
-	fimc->vid_cap.active_buf_cnt = 0;
-	fimc->vid_cap.frame_count = 0;
-	fimc->vid_cap.buf_index = fimc_hw_get_frame_index(fimc);
-
-	set_bit(ST_CAPT_PEND, &fimc->state);
-	ret = videobuf_streamon(&fimc->vid_cap.vbq);
-
-s_unlock:
-	mutex_unlock(&fimc->lock);
-	return ret;
+	return vb2_streamon(&fimc->vid_cap.vbq, type);
 }
 
 static int fimc_cap_streamoff(struct file *file, void *priv,
@@ -537,46 +638,22 @@
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	unsigned long flags;
-	int ret;
-
-	spin_lock_irqsave(&fimc->slock, flags);
-	if (!fimc_capture_running(fimc) && !fimc_capture_pending(fimc)) {
-		spin_unlock_irqrestore(&fimc->slock, flags);
-		dbg("state: 0x%lx", fimc->state);
-		return -EINVAL;
-	}
-	spin_unlock_irqrestore(&fimc->slock, flags);
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
-	fimc_stop_capture(fimc);
-	ret = videobuf_streamoff(&cap->vbq);
-	mutex_unlock(&fimc->lock);
-	return ret;
+	return vb2_streamoff(&fimc->vid_cap.vbq, type);
 }
 
 static int fimc_cap_reqbufs(struct file *file, void *priv,
-			  struct v4l2_requestbuffers *reqbufs)
+			    struct v4l2_requestbuffers *reqbufs)
 {
 	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
+	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
 	int ret;
 
-	if (fimc_capture_active(ctx->fimc_dev))
-		return -EBUSY;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
-	ret = videobuf_reqbufs(&cap->vbq, reqbufs);
+	ret = vb2_reqbufs(&cap->vbq, reqbufs);
 	if (!ret)
 		cap->reqbufs_count = reqbufs->count;
 
-	mutex_unlock(&fimc->lock);
 	return ret;
 }
 
@@ -586,43 +663,23 @@
 	struct fimc_ctx *ctx = priv;
 	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
 
-	if (fimc_capture_active(ctx->fimc_dev))
-		return -EBUSY;
-
-	return videobuf_querybuf(&cap->vbq, buf);
+	return vb2_querybuf(&cap->vbq, buf);
 }
 
 static int fimc_cap_qbuf(struct file *file, void *priv,
 			  struct v4l2_buffer *buf)
 {
 	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	int ret;
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
-	ret = videobuf_qbuf(&cap->vbq, buf);
-
-	mutex_unlock(&fimc->lock);
-	return ret;
+	struct fimc_vid_cap *cap = &ctx->fimc_dev->vid_cap;
+	return vb2_qbuf(&cap->vbq, buf);
 }
 
 static int fimc_cap_dqbuf(struct file *file, void *priv,
 			   struct v4l2_buffer *buf)
 {
 	struct fimc_ctx *ctx = priv;
-	int ret;
-
-	if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
-		return -ERESTARTSYS;
-
-	ret = videobuf_dqbuf(&ctx->fimc_dev->vid_cap.vbq, buf,
+	return vb2_dqbuf(&ctx->fimc_dev->vid_cap.vbq, buf,
 		file->f_flags & O_NONBLOCK);
-
-	mutex_unlock(&ctx->fimc_dev->lock);
-	return ret;
 }
 
 static int fimc_cap_s_ctrl(struct file *file, void *priv,
@@ -631,9 +688,6 @@
 	struct fimc_ctx *ctx = priv;
 	int ret = -EINVAL;
 
-	if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
-		return -ERESTARTSYS;
-
 	/* Allow any controls but 90/270 rotation while streaming */
 	if (!fimc_capture_active(ctx->fimc_dev) ||
 	    ctrl->id != V4L2_CID_ROTATE ||
@@ -648,8 +702,6 @@
 	if (ret == -EINVAL)
 		ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
 				       core, s_ctrl, ctrl);
-
-	mutex_unlock(&ctx->fimc_dev->lock);
 	return ret;
 }
 
@@ -658,22 +710,18 @@
 {
 	struct fimc_frame *f;
 	struct fimc_ctx *ctx = fh;
-	struct fimc_dev *fimc = ctx->fimc_dev;
 
-	if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+	if (cr->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
 		return -EINVAL;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	f = &ctx->s_frame;
+
 	cr->bounds.left		= 0;
 	cr->bounds.top		= 0;
 	cr->bounds.width	= f->o_width;
 	cr->bounds.height	= f->o_height;
 	cr->defrect		= cr->bounds;
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -681,19 +729,14 @@
 {
 	struct fimc_frame *f;
 	struct fimc_ctx *ctx = file->private_data;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
 
 	f = &ctx->s_frame;
+
 	cr->c.left	= f->offs_h;
 	cr->c.top	= f->offs_v;
 	cr->c.width	= f->width;
 	cr->c.height	= f->height;
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -712,41 +755,38 @@
 	if (ret)
 		return ret;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	if (!(ctx->state & FIMC_DST_FMT)) {
 		v4l2_err(&fimc->vid_cap.v4l2_dev,
 			 "Capture color format not set\n");
-		goto sc_unlock;
+		return -EINVAL; /* TODO: make sure this is the right value */
 	}
 
 	f = &ctx->s_frame;
 	/* Check for the pixel scaling ratio when cropping input image. */
-	ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
+	ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height,
+				      ctx->d_frame.width, ctx->d_frame.height,
+				      ctx->rotation);
 	if (ret) {
-		v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range");
-	} else {
-		ret = 0;
-		f->offs_h = cr->c.left;
-		f->offs_v = cr->c.top;
-		f->width  = cr->c.width;
-		f->height = cr->c.height;
+		v4l2_err(&fimc->vid_cap.v4l2_dev, "Out of the scaler range\n");
+		return ret;
 	}
 
-sc_unlock:
-	mutex_unlock(&fimc->lock);
-	return ret;
+	f->offs_h = cr->c.left;
+	f->offs_v = cr->c.top;
+	f->width  = cr->c.width;
+	f->height = cr->c.height;
+
+	return 0;
 }
 
 
 static const struct v4l2_ioctl_ops fimc_capture_ioctl_ops = {
 	.vidioc_querycap		= fimc_vidioc_querycap_capture,
 
-	.vidioc_enum_fmt_vid_cap	= fimc_vidioc_enum_fmt,
-	.vidioc_try_fmt_vid_cap		= fimc_vidioc_try_fmt,
-	.vidioc_s_fmt_vid_cap		= fimc_cap_s_fmt,
-	.vidioc_g_fmt_vid_cap		= fimc_vidioc_g_fmt,
+	.vidioc_enum_fmt_vid_cap_mplane	= fimc_vidioc_enum_fmt_mplane,
+	.vidioc_try_fmt_vid_cap_mplane	= fimc_vidioc_try_fmt_mplane,
+	.vidioc_s_fmt_vid_cap_mplane	= fimc_cap_s_fmt_mplane,
+	.vidioc_g_fmt_vid_cap_mplane	= fimc_vidioc_g_fmt_mplane,
 
 	.vidioc_reqbufs			= fimc_cap_reqbufs,
 	.vidioc_querybuf		= fimc_cap_querybuf,
@@ -770,6 +810,7 @@
 	.vidioc_g_input			= fimc_cap_g_input,
 };
 
+/* fimc->lock must be already initialized */
 int fimc_register_capture_device(struct fimc_dev *fimc)
 {
 	struct v4l2_device *v4l2_dev = &fimc->vid_cap.v4l2_dev;
@@ -777,6 +818,8 @@
 	struct fimc_vid_cap *vid_cap;
 	struct fimc_ctx *ctx;
 	struct v4l2_format f;
+	struct fimc_frame *fr;
+	struct vb2_queue *q;
 	int ret;
 
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
@@ -788,8 +831,12 @@
 	ctx->out_path	 = FIMC_DMA;
 	ctx->state	 = FIMC_CTX_CAP;
 
-	f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB24;
-	ctx->d_frame.fmt = find_format(&f, FMT_FLAGS_M2M);
+	/* Default format of the output frames */
+	f.fmt.pix.pixelformat = V4L2_PIX_FMT_RGB32;
+	fr = &ctx->d_frame;
+	fr->fmt = find_format(&f, FMT_FLAGS_M2M);
+	fr->width = fr->f_width = fr->o_width = 640;
+	fr->height = fr->f_height = fr->o_height = 480;
 
 	if (!v4l2_dev->name[0])
 		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name),
@@ -812,6 +859,7 @@
 	vfd->ioctl_ops	= &fimc_capture_ioctl_ops;
 	vfd->minor	= -1;
 	vfd->release	= video_device_release;
+	vfd->lock	= &fimc->lock;
 	video_set_drvdata(vfd, fimc);
 
 	vid_cap = &fimc->vid_cap;
@@ -819,7 +867,7 @@
 	vid_cap->active_buf_cnt = 0;
 	vid_cap->reqbufs_count  = 0;
 	vid_cap->refcnt = 0;
-	/* The default color format for image sensor. */
+	/* Default color format for image sensor */
 	vid_cap->fmt.code = V4L2_MBUS_FMT_YUYV8_2X8;
 
 	INIT_LIST_HEAD(&vid_cap->pending_buf_q);
@@ -827,10 +875,16 @@
 	spin_lock_init(&ctx->slock);
 	vid_cap->ctx = ctx;
 
-	videobuf_queue_dma_contig_init(&vid_cap->vbq, &fimc_qops,
-		vid_cap->v4l2_dev.dev, &fimc->irqlock,
-		V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FIELD_NONE,
-		sizeof(struct fimc_vid_buffer), (void *)ctx, NULL);
+	q = &fimc->vid_cap.vbq;
+	memset(q, 0, sizeof(*q));
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = fimc->vid_cap.ctx;
+	q->ops = &fimc_capture_qops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct fimc_vid_buffer);
+
+	vb2_queue_init(q);
 
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
 	if (ret) {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-core.c linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,114 +25,141 @@
 #include <linux/slab.h>
 #include <linux/clk.h>
 #include <media/v4l2-ioctl.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
 
 #include "fimc-core.h"
 
-static char *fimc_clock_name[NUM_FIMC_CLOCKS] = { "sclk_fimc", "fimc" };
+static char *fimc_clocks[MAX_FIMC_CLOCKS] = {
+	"sclk_fimc", "fimc", "sclk_cam"
+};
 
 static struct fimc_fmt fimc_formats[] = {
 	{
-		.name	= "RGB565",
-		.fourcc	= V4L2_PIX_FMT_RGB565X,
-		.depth	= 16,
-		.color	= S5P_FIMC_RGB565,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.mbus_code = V4L2_MBUS_FMT_RGB565_2X8_BE,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "RGB565",
+		.fourcc		= V4L2_PIX_FMT_RGB565X,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_RGB565,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.mbus_code	= V4L2_MBUS_FMT_RGB565_2X8_BE,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name	= "BGR666",
-		.fourcc	= V4L2_PIX_FMT_BGR666,
-		.depth	= 32,
-		.color	= S5P_FIMC_RGB666,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "BGR666",
+		.fourcc		= V4L2_PIX_FMT_BGR666,
+		.depth		= { 32 },
+		.color		= S5P_FIMC_RGB666,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name = "XRGB-8-8-8-8, 32 bpp",
-		.fourcc	= V4L2_PIX_FMT_RGB32,
-		.depth = 32,
-		.color	= S5P_FIMC_RGB888,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "XRGB-8-8-8-8, 32 bpp",
+		.fourcc		= V4L2_PIX_FMT_RGB32,
+		.depth		= { 32 },
+		.color		= S5P_FIMC_RGB888,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name	= "YUV 4:2:2 packed, YCbYCr",
-		.fourcc	= V4L2_PIX_FMT_YUYV,
-		.depth	= 16,
-		.color	= S5P_FIMC_YCBYCR422,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.mbus_code = V4L2_MBUS_FMT_YUYV8_2X8,
-		.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
+		.name		= "YUV 4:2:2 packed, YCbYCr",
+		.fourcc		= V4L2_PIX_FMT_YUYV,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_YCBYCR422,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.mbus_code	= V4L2_MBUS_FMT_YUYV8_2X8,
+		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
-		.name	= "YUV 4:2:2 packed, CbYCrY",
-		.fourcc	= V4L2_PIX_FMT_UYVY,
-		.depth	= 16,
-		.color	= S5P_FIMC_CBYCRY422,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.mbus_code = V4L2_MBUS_FMT_UYVY8_2X8,
-		.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
+		.name		= "YUV 4:2:2 packed, CbYCrY",
+		.fourcc		= V4L2_PIX_FMT_UYVY,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_CBYCRY422,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.mbus_code	= V4L2_MBUS_FMT_UYVY8_2X8,
+		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
-		.name	= "YUV 4:2:2 packed, CrYCbY",
-		.fourcc	= V4L2_PIX_FMT_VYUY,
-		.depth	= 16,
-		.color	= S5P_FIMC_CRYCBY422,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.mbus_code = V4L2_MBUS_FMT_VYUY8_2X8,
-		.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
+		.name		= "YUV 4:2:2 packed, CrYCbY",
+		.fourcc		= V4L2_PIX_FMT_VYUY,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_CRYCBY422,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.mbus_code	= V4L2_MBUS_FMT_VYUY8_2X8,
+		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
-		.name	= "YUV 4:2:2 packed, YCrYCb",
-		.fourcc	= V4L2_PIX_FMT_YVYU,
-		.depth	= 16,
-		.color	= S5P_FIMC_YCRYCB422,
-		.buff_cnt = 1,
-		.planes_cnt = 1,
-		.mbus_code = V4L2_MBUS_FMT_YVYU8_2X8,
-		.flags = FMT_FLAGS_M2M | FMT_FLAGS_CAM,
+		.name		= "YUV 4:2:2 packed, YCrYCb",
+		.fourcc		= V4L2_PIX_FMT_YVYU,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_YCRYCB422,
+		.memplanes	= 1,
+		.colplanes	= 1,
+		.mbus_code	= V4L2_MBUS_FMT_YVYU8_2X8,
+		.flags		= FMT_FLAGS_M2M | FMT_FLAGS_CAM,
 	}, {
-		.name	= "YUV 4:2:2 planar, Y/Cb/Cr",
-		.fourcc	= V4L2_PIX_FMT_YUV422P,
-		.depth	= 12,
-		.color	= S5P_FIMC_YCBCR422,
-		.buff_cnt = 1,
-		.planes_cnt = 3,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "YUV 4:2:2 planar, Y/Cb/Cr",
+		.fourcc		= V4L2_PIX_FMT_YUV422P,
+		.depth		= { 12 },
+		.color		= S5P_FIMC_YCBYCR422,
+		.memplanes	= 1,
+		.colplanes	= 3,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name	= "YUV 4:2:2 planar, Y/CbCr",
-		.fourcc	= V4L2_PIX_FMT_NV16,
-		.depth	= 16,
-		.color	= S5P_FIMC_YCBCR422,
-		.buff_cnt = 1,
-		.planes_cnt = 2,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "YUV 4:2:2 planar, Y/CbCr",
+		.fourcc		= V4L2_PIX_FMT_NV16,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_YCBYCR422,
+		.memplanes	= 1,
+		.colplanes	= 2,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name	= "YUV 4:2:2 planar, Y/CrCb",
-		.fourcc	= V4L2_PIX_FMT_NV61,
-		.depth	= 16,
-		.color	= S5P_FIMC_RGB565,
-		.buff_cnt = 1,
-		.planes_cnt = 2,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "YUV 4:2:2 planar, Y/CrCb",
+		.fourcc		= V4L2_PIX_FMT_NV61,
+		.depth		= { 16 },
+		.color		= S5P_FIMC_YCRYCB422,
+		.memplanes	= 1,
+		.colplanes	= 2,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name	= "YUV 4:2:0 planar, YCbCr",
-		.fourcc	= V4L2_PIX_FMT_YUV420,
-		.depth	= 12,
-		.color	= S5P_FIMC_YCBCR420,
-		.buff_cnt = 1,
-		.planes_cnt = 3,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "YUV 4:2:0 planar, YCbCr",
+		.fourcc		= V4L2_PIX_FMT_YUV420,
+		.depth		= { 12 },
+		.color		= S5P_FIMC_YCBCR420,
+		.memplanes	= 1,
+		.colplanes	= 3,
+		.flags		= FMT_FLAGS_M2M,
 	}, {
-		.name	= "YUV 4:2:0 planar, Y/CbCr",
-		.fourcc	= V4L2_PIX_FMT_NV12,
-		.depth	= 12,
-		.color	= S5P_FIMC_YCBCR420,
-		.buff_cnt = 1,
-		.planes_cnt = 2,
-		.flags = FMT_FLAGS_M2M,
+		.name		= "YUV 4:2:0 planar, Y/CbCr",
+		.fourcc		= V4L2_PIX_FMT_NV12,
+		.depth		= { 12 },
+		.color		= S5P_FIMC_YCBCR420,
+		.memplanes	= 1,
+		.colplanes	= 2,
+		.flags		= FMT_FLAGS_M2M,
+	}, {
+		.name		= "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr",
+		.fourcc		= V4L2_PIX_FMT_NV12M,
+		.color		= S5P_FIMC_YCBCR420,
+		.depth		= { 8, 4 },
+		.memplanes	= 2,
+		.colplanes	= 2,
+		.flags		= FMT_FLAGS_M2M,
+	}, {
+		.name		= "YUV 4:2:0 non-contiguous 3-planar, Y/Cb/Cr",
+		.fourcc		= V4L2_PIX_FMT_YUV420M,
+		.color		= S5P_FIMC_YCBCR420,
+		.depth		= { 8, 2, 2 },
+		.memplanes	= 3,
+		.colplanes	= 3,
+		.flags		= FMT_FLAGS_M2M,
+	}, {
+		.name		= "YUV 4:2:0 non-contiguous 2-planar, Y/CbCr, tiled",
+		.fourcc		= V4L2_PIX_FMT_NV12MT,
+		.color		= S5P_FIMC_YCBCR420,
+		.depth		= { 8, 4 },
+		.memplanes	= 2,
+		.colplanes	= 2,
+		.flags		= FMT_FLAGS_M2M,
 	},
 };
 
@@ -173,24 +200,21 @@
 	return NULL;
 }
 
-int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f)
+int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot)
 {
-	if (r->width > f->width) {
-		if (f->width > (r->width * SCALER_MAX_HRATIO))
-			return -EINVAL;
-	} else {
-		if ((f->width * SCALER_MAX_HRATIO) < r->width)
-			return -EINVAL;
-	}
+	int tx, ty;
 
-	if (r->height > f->height) {
-		if (f->height > (r->height * SCALER_MAX_VRATIO))
-			return -EINVAL;
+	if (rot == 90 || rot == 270) {
+		ty = dw;
+		tx = dh;
 	} else {
-		if ((f->height * SCALER_MAX_VRATIO) < r->height)
-			return -EINVAL;
+		tx = dw;
+		ty = dh;
 	}
 
+	if ((sw >= SCALER_MAX_HRATIO * tx) || (sh >= SCALER_MAX_VRATIO * ty))
+		return -EINVAL;
+
 	return 0;
 }
 
@@ -221,6 +245,7 @@
 	struct fimc_scaler *sc = &ctx->scaler;
 	struct fimc_frame *s_frame = &ctx->s_frame;
 	struct fimc_frame *d_frame = &ctx->d_frame;
+	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
 	int tx, ty, sx, sy;
 	int ret;
 
@@ -259,8 +284,14 @@
 	sc->pre_dst_width = sx / sc->pre_hratio;
 	sc->pre_dst_height = sy / sc->pre_vratio;
 
-	sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
-	sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+	if (variant->has_mainscaler_ext) {
+		sc->main_hratio = (sx << 14) / (tx << sc->hfactor);
+		sc->main_vratio = (sy << 14) / (ty << sc->vfactor);
+	} else {
+		sc->main_hratio = (sx << 8) / (tx << sc->hfactor);
+		sc->main_vratio = (sy << 8) / (ty << sc->vfactor);
+
+	}
 
 	sc->scaleup_h = (tx >= sx) ? 1 : 0;
 	sc->scaleup_v = (ty >= sy) ? 1 : 0;
@@ -276,14 +307,75 @@
 	return 0;
 }
 
-static void fimc_capture_handler(struct fimc_dev *fimc)
+static void fimc_m2m_job_finish(struct fimc_ctx *ctx, int vb_state)
+{
+	struct vb2_buffer *src_vb, *dst_vb;
+	struct fimc_dev *fimc = ctx->fimc_dev;
+
+	if (!ctx || !ctx->m2m_ctx)
+		return;
+
+	src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+	dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+
+	if (src_vb && dst_vb) {
+		v4l2_m2m_buf_done(src_vb, vb_state);
+		v4l2_m2m_buf_done(dst_vb, vb_state);
+		v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
+	}
+}
+
+/* Complete the transaction which has been scheduled for execution. */
+static void fimc_m2m_shutdown(struct fimc_ctx *ctx)
+{
+	struct fimc_dev *fimc = ctx->fimc_dev;
+	int ret;
+
+	if (!fimc_m2m_pending(fimc))
+		return;
+
+	fimc_ctx_state_lock_set(FIMC_CTX_SHUT, ctx);
+
+	ret = wait_event_timeout(fimc->irq_queue,
+			   !fimc_ctx_state_is_set(FIMC_CTX_SHUT, ctx),
+			   FIMC_SHUTDOWN_TIMEOUT);
+	/*
+	 * In case of a timeout the buffers are not released in the interrupt
+	 * handler so return them here with the error flag set, if there are
+	 * any on the queue.
+	 */
+	if (ret == 0)
+		fimc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+}
+
+static int stop_streaming(struct vb2_queue *q)
+{
+	struct fimc_ctx *ctx = q->drv_priv;
+
+	fimc_m2m_shutdown(ctx);
+
+	return 0;
+}
+
+static void fimc_capture_irq_handler(struct fimc_dev *fimc)
 {
 	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	struct fimc_vid_buffer *v_buf = NULL;
+	struct fimc_vid_buffer *v_buf;
+	struct timeval *tv;
+	struct timespec ts;
+
+	if (!list_empty(&cap->active_buf_q) &&
+	    test_bit(ST_CAPT_RUN, &fimc->state)) {
+		ktime_get_real_ts(&ts);
 
-	if (!list_empty(&cap->active_buf_q)) {
 		v_buf = active_queue_pop(cap);
-		fimc_buf_finish(fimc, v_buf);
+
+		tv = &v_buf->vb.v4l2_buf.timestamp;
+		tv->tv_sec = ts.tv_sec;
+		tv->tv_usec = ts.tv_nsec / NSEC_PER_USEC;
+		v_buf->vb.v4l2_buf.sequence = cap->frame_count++;
+
+		vb2_buffer_done(&v_buf->vb, VB2_BUF_STATE_DONE);
 	}
 
 	if (test_and_clear_bit(ST_CAPT_SHUT, &fimc->state)) {
@@ -297,13 +389,6 @@
 		fimc_hw_set_output_addr(fimc, &v_buf->paddr, cap->buf_index);
 		v_buf->index = cap->buf_index;
 
-		dbg("hw ptr: %d, sw ptr: %d",
-		    fimc_hw_get_frame_index(fimc), cap->buf_index);
-
-		spin_lock(&fimc->irqlock);
-		v_buf->vb.state = VIDEOBUF_ACTIVE;
-		spin_unlock(&fimc->irqlock);
-
 		/* Move the buffer to the capture active queue */
 		active_queue_add(cap, v_buf);
 
@@ -312,77 +397,79 @@
 
 		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
 			cap->buf_index = 0;
+	}
 
-	} else if (test_and_clear_bit(ST_CAPT_STREAM, &fimc->state) &&
-		   cap->active_buf_cnt <= 1) {
-		fimc_deactivate_capture(fimc);
+	if (cap->active_buf_cnt == 0) {
+		clear_bit(ST_CAPT_RUN, &fimc->state);
+
+		if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
+			cap->buf_index = 0;
+	} else {
+		set_bit(ST_CAPT_RUN, &fimc->state);
 	}
 
-	dbg("frame: %d, active_buf_cnt= %d",
+	dbg("frame: %d, active_buf_cnt: %d",
 	    fimc_hw_get_frame_index(fimc), cap->active_buf_cnt);
 }
 
 static irqreturn_t fimc_isr(int irq, void *priv)
 {
-	struct fimc_vid_buffer *src_buf, *dst_buf;
-	struct fimc_ctx *ctx;
 	struct fimc_dev *fimc = priv;
+	struct fimc_vid_cap *cap = &fimc->vid_cap;
+	struct fimc_ctx *ctx;
 
-	BUG_ON(!fimc);
 	fimc_hw_clear_irq(fimc);
 
-	spin_lock(&fimc->slock);
-
 	if (test_and_clear_bit(ST_M2M_PEND, &fimc->state)) {
 		ctx = v4l2_m2m_get_curr_priv(fimc->m2m.m2m_dev);
-		if (!ctx || !ctx->m2m_ctx)
-			goto isr_unlock;
-		src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
-		dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
-		if (src_buf && dst_buf) {
-			spin_lock(&fimc->irqlock);
-			src_buf->vb.state = dst_buf->vb.state = VIDEOBUF_DONE;
-			wake_up(&src_buf->vb.done);
-			wake_up(&dst_buf->vb.done);
-			spin_unlock(&fimc->irqlock);
-			v4l2_m2m_job_finish(fimc->m2m.m2m_dev, ctx->m2m_ctx);
+		if (ctx != NULL) {
+			fimc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
+
+			spin_lock(&ctx->slock);
+			if (ctx->state & FIMC_CTX_SHUT) {
+				ctx->state &= ~FIMC_CTX_SHUT;
+				wake_up(&fimc->irq_queue);
+			}
+			spin_unlock(&ctx->slock);
 		}
-		goto isr_unlock;
 
+		return IRQ_HANDLED;
 	}
 
-	if (test_bit(ST_CAPT_RUN, &fimc->state))
-		fimc_capture_handler(fimc);
+	spin_lock(&fimc->slock);
 
-	if (test_and_clear_bit(ST_CAPT_PEND, &fimc->state)) {
-		set_bit(ST_CAPT_RUN, &fimc->state);
-		wake_up(&fimc->irq_queue);
+	if (test_bit(ST_CAPT_PEND, &fimc->state)) {
+		fimc_capture_irq_handler(fimc);
+
+		if (cap->active_buf_cnt == 1) {
+			fimc_deactivate_capture(fimc);
+			clear_bit(ST_CAPT_STREAM, &fimc->state);
+		}
 	}
 
-isr_unlock:
 	spin_unlock(&fimc->slock);
 	return IRQ_HANDLED;
 }
 
-/* The color format (planes_cnt, buff_cnt) must be already configured. */
-int fimc_prepare_addr(struct fimc_ctx *ctx, struct fimc_vid_buffer *buf,
+/* The color format (colplanes, memplanes) must be already configured. */
+int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
 		      struct fimc_frame *frame, struct fimc_addr *paddr)
 {
 	int ret = 0;
 	u32 pix_size;
 
-	if (buf == NULL || frame == NULL)
+	if (vb == NULL || frame == NULL)
 		return -EINVAL;
 
 	pix_size = frame->width * frame->height;
 
-	dbg("buff_cnt= %d, planes_cnt= %d, frame->size= %d, pix_size= %d",
-		frame->fmt->buff_cnt, frame->fmt->planes_cnt,
-		frame->size, pix_size);
+	dbg("memplanes= %d, colplanes= %d, pix_size= %d",
+		frame->fmt->memplanes, frame->fmt->colplanes, pix_size);
 
-	if (frame->fmt->buff_cnt == 1) {
-		paddr->y = videobuf_to_dma_contig(&buf->vb);
-		switch (frame->fmt->planes_cnt) {
+	paddr->y = vb2_dma_contig_plane_paddr(vb, 0);
+
+	if (frame->fmt->memplanes == 1) {
+		switch (frame->fmt->colplanes) {
 		case 1:
 			paddr->cb = 0;
 			paddr->cr = 0;
@@ -405,6 +492,12 @@
 		default:
 			return -EINVAL;
 		}
+	} else {
+		if (frame->fmt->memplanes >= 2)
+			paddr->cb = vb2_dma_contig_plane_paddr(vb, 1);
+
+		if (frame->fmt->memplanes == 3)
+			paddr->cr = vb2_dma_contig_plane_paddr(vb, 2);
 	}
 
 	dbg("PHYS_ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
@@ -423,34 +516,34 @@
 	/* Set order for 1 plane input formats. */
 	switch (ctx->s_frame.fmt->color) {
 	case S5P_FIMC_YCRYCB422:
-		ctx->in_order_1p = S5P_FIMC_IN_YCRYCB;
+		ctx->in_order_1p = S5P_MSCTRL_ORDER422_CBYCRY;
 		break;
 	case S5P_FIMC_CBYCRY422:
-		ctx->in_order_1p = S5P_FIMC_IN_CBYCRY;
+		ctx->in_order_1p = S5P_MSCTRL_ORDER422_YCRYCB;
 		break;
 	case S5P_FIMC_CRYCBY422:
-		ctx->in_order_1p = S5P_FIMC_IN_CRYCBY;
+		ctx->in_order_1p = S5P_MSCTRL_ORDER422_YCBYCR;
 		break;
 	case S5P_FIMC_YCBYCR422:
 	default:
-		ctx->in_order_1p = S5P_FIMC_IN_YCBYCR;
+		ctx->in_order_1p = S5P_MSCTRL_ORDER422_CRYCBY;
 		break;
 	}
 	dbg("ctx->in_order_1p= %d", ctx->in_order_1p);
 
 	switch (ctx->d_frame.fmt->color) {
 	case S5P_FIMC_YCRYCB422:
-		ctx->out_order_1p = S5P_FIMC_OUT_YCRYCB;
+		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_CBYCRY;
 		break;
 	case S5P_FIMC_CBYCRY422:
-		ctx->out_order_1p = S5P_FIMC_OUT_CBYCRY;
+		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_YCRYCB;
 		break;
 	case S5P_FIMC_CRYCBY422:
-		ctx->out_order_1p = S5P_FIMC_OUT_CRYCBY;
+		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_YCBYCR;
 		break;
 	case S5P_FIMC_YCBYCR422:
 	default:
-		ctx->out_order_1p = S5P_FIMC_OUT_YCBYCR;
+		ctx->out_order_1p = S5P_CIOCTRL_ORDER422_CRYCBY;
 		break;
 	}
 	dbg("ctx->out_order_1p= %d", ctx->out_order_1p);
@@ -459,10 +552,14 @@
 static void fimc_prepare_dma_offset(struct fimc_ctx *ctx, struct fimc_frame *f)
 {
 	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
+	u32 i, depth = 0;
+
+	for (i = 0; i < f->fmt->colplanes; i++)
+		depth += f->fmt->depth[i];
 
 	f->dma_offset.y_h = f->offs_h;
 	if (!variant->pix_hoff)
-		f->dma_offset.y_h *= (f->fmt->depth >> 3);
+		f->dma_offset.y_h *= (depth >> 3);
 
 	f->dma_offset.y_v = f->offs_v;
 
@@ -473,7 +570,7 @@
 	f->dma_offset.cr_v = f->offs_v;
 
 	if (!variant->pix_hoff) {
-		if (f->fmt->planes_cnt == 3) {
+		if (f->fmt->colplanes == 3) {
 			f->dma_offset.cb_h >>= 1;
 			f->dma_offset.cr_h >>= 1;
 		}
@@ -499,7 +596,7 @@
 int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags)
 {
 	struct fimc_frame *s_frame, *d_frame;
-	struct fimc_vid_buffer *buf = NULL;
+	struct vb2_buffer *vb = NULL;
 	int ret = 0;
 
 	s_frame = &ctx->s_frame;
@@ -522,15 +619,15 @@
 	ctx->scaler.enabled = 1;
 
 	if (flags & FIMC_SRC_ADDR) {
-		buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
-		ret = fimc_prepare_addr(ctx, buf, s_frame, &s_frame->paddr);
+		vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+		ret = fimc_prepare_addr(ctx, vb, s_frame, &s_frame->paddr);
 		if (ret)
 			return ret;
 	}
 
 	if (flags & FIMC_DST_ADDR) {
-		buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
-		ret = fimc_prepare_addr(ctx, buf, d_frame, &d_frame->paddr);
+		vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+		ret = fimc_prepare_addr(ctx, vb, d_frame, &d_frame->paddr);
 	}
 
 	return ret;
@@ -553,26 +650,28 @@
 
 	ctx->state |= (FIMC_SRC_ADDR | FIMC_DST_ADDR);
 	ret = fimc_prepare_config(ctx, ctx->state);
-	if (ret) {
-		err("Wrong parameters");
+	if (ret)
 		goto dma_unlock;
-	}
+
 	/* Reconfigure hardware if the context has changed. */
 	if (fimc->m2m.ctx != ctx) {
 		ctx->state |= FIMC_PARAMS;
 		fimc->m2m.ctx = ctx;
 	}
 
+	spin_lock(&fimc->slock);
 	fimc_hw_set_input_addr(fimc, &ctx->s_frame.paddr);
 
 	if (ctx->state & FIMC_PARAMS) {
 		fimc_hw_set_input_path(ctx);
 		fimc_hw_set_in_dma(ctx);
-		if (fimc_set_scaler_info(ctx)) {
-			err("Scaler setup error");
+		ret = fimc_set_scaler_info(ctx);
+		if (ret) {
+			spin_unlock(&fimc->slock);
 			goto dma_unlock;
 		}
-		fimc_hw_set_scaler(ctx);
+		fimc_hw_set_prescaler(ctx);
+		fimc_hw_set_mainscaler(ctx);
 		fimc_hw_set_target_format(ctx);
 		fimc_hw_set_rotation(ctx);
 		fimc_hw_set_effect(ctx);
@@ -587,8 +686,10 @@
 
 	fimc_activate_capture(ctx);
 
-	ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP);
+	ctx->state &= (FIMC_CTX_M2M | FIMC_CTX_CAP |
+		       FIMC_SRC_FMT | FIMC_DST_FMT);
 	fimc_hw_activate_input_dma(fimc, true);
+	spin_unlock(&fimc->slock);
 
 dma_unlock:
 	spin_unlock_irqrestore(&ctx->slock, flags);
@@ -596,109 +697,84 @@
 
 static void fimc_job_abort(void *priv)
 {
-	/* Nothing done in job_abort. */
+	fimc_m2m_shutdown(priv);
 }
 
-static void fimc_buf_release(struct videobuf_queue *vq,
-				    struct videobuf_buffer *vb)
+static int fimc_queue_setup(struct vb2_queue *vq, unsigned int *num_buffers,
+			    unsigned int *num_planes, unsigned long sizes[],
+			    void *allocators[])
 {
-	videobuf_dma_contig_free(vq, vb);
-	vb->state = VIDEOBUF_NEEDS_INIT;
-}
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
+	struct fimc_frame *f;
+	int i;
 
-static int fimc_buf_setup(struct videobuf_queue *vq, unsigned int *count,
-				unsigned int *size)
-{
-	struct fimc_ctx *ctx = vq->priv_data;
-	struct fimc_frame *frame;
+	f = ctx_get_frame(ctx, vq->type);
+	if (IS_ERR(f))
+		return PTR_ERR(f);
 
-	frame = ctx_get_frame(ctx, vq->type);
-	if (IS_ERR(frame))
-		return PTR_ERR(frame);
+	/*
+	 * Return number of non-contigous planes (plane buffers)
+	 * depending on the configured color format.
+	 */
+	if (f->fmt)
+		*num_planes = f->fmt->memplanes;
+
+	for (i = 0; i < f->fmt->memplanes; i++) {
+		sizes[i] = (f->width * f->height * f->fmt->depth[i]) >> 3;
+		allocators[i] = ctx->fimc_dev->alloc_ctx;
+	}
+
+	if (*num_buffers == 0)
+		*num_buffers = 1;
 
-	*size = (frame->width * frame->height * frame->fmt->depth) >> 3;
-	if (0 == *count)
-		*count = 1;
 	return 0;
 }
 
-static int fimc_buf_prepare(struct videobuf_queue *vq,
-		struct videobuf_buffer *vb, enum v4l2_field field)
+static int fimc_buf_prepare(struct vb2_buffer *vb)
 {
-	struct fimc_ctx *ctx = vq->priv_data;
-	struct v4l2_device *v4l2_dev = &ctx->fimc_dev->m2m.v4l2_dev;
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 	struct fimc_frame *frame;
-	int ret;
+	int i;
 
-	frame = ctx_get_frame(ctx, vq->type);
+	frame = ctx_get_frame(ctx, vb->vb2_queue->type);
 	if (IS_ERR(frame))
 		return PTR_ERR(frame);
 
-	if (vb->baddr) {
-		if (vb->bsize < frame->size) {
-			v4l2_err(v4l2_dev,
-				"User-provided buffer too small (%d < %d)\n",
-				 vb->bsize, frame->size);
-			WARN_ON(1);
-			return -EINVAL;
-		}
-	} else if (vb->state != VIDEOBUF_NEEDS_INIT
-		   && vb->bsize < frame->size) {
-		return -EINVAL;
-	}
-
-	vb->width       = frame->width;
-	vb->height      = frame->height;
-	vb->bytesperline = (frame->width * frame->fmt->depth) >> 3;
-	vb->size        = frame->size;
-	vb->field       = field;
-
-	if (VIDEOBUF_NEEDS_INIT == vb->state) {
-		ret = videobuf_iolock(vq, vb, NULL);
-		if (ret) {
-			v4l2_err(v4l2_dev, "Iolock failed\n");
-			fimc_buf_release(vq, vb);
-			return ret;
-		}
-	}
-	vb->state = VIDEOBUF_PREPARED;
+	for (i = 0; i < frame->fmt->memplanes; i++)
+		vb2_set_plane_payload(vb, i, frame->payload[i]);
 
 	return 0;
 }
 
-static void fimc_buf_queue(struct videobuf_queue *vq,
-				  struct videobuf_buffer *vb)
+static void fimc_buf_queue(struct vb2_buffer *vb)
 {
-	struct fimc_ctx *ctx = vq->priv_data;
-	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct fimc_vid_cap *cap = &fimc->vid_cap;
-	unsigned long flags;
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
 
 	dbg("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
 
-	if ((ctx->state & FIMC_CTX_M2M) && ctx->m2m_ctx) {
-		v4l2_m2m_buf_queue(ctx->m2m_ctx, vq, vb);
-	} else if (ctx->state & FIMC_CTX_CAP) {
-		spin_lock_irqsave(&fimc->slock, flags);
-		fimc_vid_cap_buf_queue(fimc, (struct fimc_vid_buffer *)vb);
+	if (ctx->m2m_ctx)
+		v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
 
-		dbg("fimc->cap.active_buf_cnt: %d",
-		    fimc->vid_cap.active_buf_cnt);
+static void fimc_lock(struct vb2_queue *vq)
+{
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
+	mutex_lock(&ctx->fimc_dev->lock);
+}
 
-		if (cap->active_buf_cnt >= cap->reqbufs_count ||
-		   cap->active_buf_cnt >= FIMC_MAX_OUT_BUFS) {
-			if (!test_and_set_bit(ST_CAPT_STREAM, &fimc->state))
-				fimc_activate_capture(ctx);
-		}
-		spin_unlock_irqrestore(&fimc->slock, flags);
-	}
+static void fimc_unlock(struct vb2_queue *vq)
+{
+	struct fimc_ctx *ctx = vb2_get_drv_priv(vq);
+	mutex_unlock(&ctx->fimc_dev->lock);
 }
 
-struct videobuf_queue_ops fimc_qops = {
-	.buf_setup	= fimc_buf_setup,
-	.buf_prepare	= fimc_buf_prepare,
-	.buf_queue	= fimc_buf_queue,
-	.buf_release	= fimc_buf_release,
+static struct vb2_ops fimc_qops = {
+	.queue_setup	 = fimc_queue_setup,
+	.buf_prepare	 = fimc_buf_prepare,
+	.buf_queue	 = fimc_buf_queue,
+	.wait_prepare	 = fimc_unlock,
+	.wait_finish	 = fimc_lock,
+	.stop_streaming	 = stop_streaming,
 };
 
 static int fimc_m2m_querycap(struct file *file, void *priv,
@@ -712,12 +788,13 @@
 	cap->bus_info[0] = 0;
 	cap->version = KERNEL_VERSION(1, 0, 0);
 	cap->capabilities = V4L2_CAP_STREAMING |
-		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT;
+		V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+		V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
 
 	return 0;
 }
 
-int fimc_vidioc_enum_fmt(struct file *file, void *priv,
+int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
 				struct v4l2_fmtdesc *f)
 {
 	struct fimc_fmt *fmt;
@@ -732,25 +809,39 @@
 	return 0;
 }
 
-int fimc_vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
+			     struct v4l2_format *f)
 {
 	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct fimc_frame *frame;
+	struct v4l2_pix_format_mplane *pixm;
+	int i;
 
 	frame = ctx_get_frame(ctx, f->type);
 	if (IS_ERR(frame))
 		return PTR_ERR(frame);
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
+	pixm = &f->fmt.pix_mp;
 
-	f->fmt.pix.width	= frame->width;
-	f->fmt.pix.height	= frame->height;
-	f->fmt.pix.field	= V4L2_FIELD_NONE;
-	f->fmt.pix.pixelformat	= frame->fmt->fourcc;
+	pixm->width		= frame->width;
+	pixm->height		= frame->height;
+	pixm->field		= V4L2_FIELD_NONE;
+	pixm->pixelformat	= frame->fmt->fourcc;
+	pixm->colorspace	= V4L2_COLORSPACE_JPEG;
+	pixm->num_planes	= frame->fmt->memplanes;
+
+	for (i = 0; i < pixm->num_planes; ++i) {
+		int bpl = frame->o_width;
+
+		if (frame->fmt->colplanes == 1) /* packed formats */
+			bpl = (bpl * frame->fmt->depth[0]) / 8;
+
+		pixm->plane_fmt[i].bytesperline = bpl;
+
+		pixm->plane_fmt[i].sizeimage = (frame->o_width *
+			frame->o_height * frame->fmt->depth[i]) / 8;
+	}
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -785,42 +876,40 @@
 }
 
 
-int fimc_vidioc_try_fmt(struct file *file, void *priv, struct v4l2_format *f)
+int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
+			       struct v4l2_format *f)
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct samsung_fimc_variant *variant = fimc->variant;
-	struct v4l2_pix_format *pix = &f->fmt.pix;
+	struct v4l2_pix_format_mplane *pix = &f->fmt.pix_mp;
 	struct fimc_fmt *fmt;
 	u32 max_width, mod_x, mod_y, mask;
-	int ret = -EINVAL, is_output = 0;
+	int i, is_output = 0;
 
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
-		if (ctx->state & FIMC_CTX_CAP)
+
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+		if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx))
 			return -EINVAL;
 		is_output = 1;
-	} else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+	} else if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		return -EINVAL;
 	}
 
-	dbg("w: %d, h: %d, bpl: %d",
-	    pix->width, pix->height, pix->bytesperline);
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
+	dbg("w: %d, h: %d", pix->width, pix->height);
 
 	mask = is_output ? FMT_FLAGS_M2M : FMT_FLAGS_M2M | FMT_FLAGS_CAM;
 	fmt = find_format(f, mask);
 	if (!fmt) {
 		v4l2_err(&fimc->m2m.v4l2_dev, "Fourcc format (0x%X) invalid.\n",
 			 pix->pixelformat);
-		goto tf_out;
+		return -EINVAL;
 	}
 
 	if (pix->field == V4L2_FIELD_ANY)
 		pix->field = V4L2_FIELD_NONE;
 	else if (V4L2_FIELD_NONE != pix->field)
-		goto tf_out;
+		return -EINVAL;
 
 	if (is_output) {
 		max_width = variant->pix_limit->scaler_dis_w;
@@ -834,7 +923,7 @@
 		mod_x = 6; /* 64 x 32 pixels tile */
 		mod_y = 5;
 	} else {
-		if (fimc->id == 1 && fimc->variant->pix_hoff)
+		if (fimc->id == 1 && variant->pix_hoff)
 			mod_y = fimc_fmt_is_rgb(fmt->color) ? 0 : 1;
 		else
 			mod_y = mod_x;
@@ -845,74 +934,74 @@
 	v4l_bound_align_image(&pix->width, 16, max_width, mod_x,
 		&pix->height, 8, variant->pix_limit->scaler_dis_w, mod_y, 0);
 
-	if (pix->bytesperline == 0 ||
-	    (pix->bytesperline * 8 / fmt->depth) > pix->width)
-		pix->bytesperline = (pix->width * fmt->depth) >> 3;
+	pix->num_planes = fmt->memplanes;
+	pix->colorspace	= V4L2_COLORSPACE_JPEG;
 
-	if (pix->sizeimage == 0)
-		pix->sizeimage = pix->height * pix->bytesperline;
 
-	dbg("w: %d, h: %d, bpl: %d, depth: %d",
-	    pix->width, pix->height, pix->bytesperline, fmt->depth);
+	for (i = 0; i < pix->num_planes; ++i) {
+		u32 bpl = pix->plane_fmt[i].bytesperline;
+		u32 *sizeimage = &pix->plane_fmt[i].sizeimage;
 
-	ret = 0;
+		if (fmt->colplanes > 1 && (bpl == 0 || bpl < pix->width))
+			bpl = pix->width; /* Planar */
 
-tf_out:
-	mutex_unlock(&fimc->lock);
-	return ret;
+		if (fmt->colplanes == 1 && /* Packed */
+		    (bpl == 0 || ((bpl * 8) / fmt->depth[i]) < pix->width))
+			bpl = (pix->width * fmt->depth[0]) / 8;
+
+		if (i == 0) /* Same bytesperline for each plane. */
+			mod_x = bpl;
+
+		pix->plane_fmt[i].bytesperline = mod_x;
+		*sizeimage = (pix->width * pix->height * fmt->depth[i]) / 8;
+	}
+
+	return 0;
 }
 
-static int fimc_m2m_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
+static int fimc_m2m_s_fmt_mplane(struct file *file, void *priv,
+				 struct v4l2_format *f)
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	struct v4l2_device *v4l2_dev = &fimc->m2m.v4l2_dev;
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 	struct fimc_frame *frame;
-	struct v4l2_pix_format *pix;
-	unsigned long flags;
-	int ret = 0;
+	struct v4l2_pix_format_mplane *pix;
+	int i, ret = 0;
 
-	ret = fimc_vidioc_try_fmt(file, priv, f);
+	ret = fimc_vidioc_try_fmt_mplane(file, priv, f);
 	if (ret)
 		return ret;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
-	mutex_lock(&vq->vb_lock);
 
-	if (videobuf_queue_is_busy(vq)) {
-		v4l2_err(v4l2_dev, "%s: queue (%d) busy\n", __func__, f->type);
-		ret = -EBUSY;
-		goto sf_out;
+	if (vb2_is_busy(vq)) {
+		v4l2_err(&fimc->m2m.v4l2_dev, "queue (%d) busy\n", f->type);
+		return -EBUSY;
 	}
 
-	spin_lock_irqsave(&ctx->slock, flags);
-	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+	if (f->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
 		frame = &ctx->s_frame;
-		ctx->state |= FIMC_SRC_FMT;
-	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+	} else if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
 		frame = &ctx->d_frame;
-		ctx->state |= FIMC_DST_FMT;
 	} else {
-		spin_unlock_irqrestore(&ctx->slock, flags);
-		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
+		v4l2_err(&fimc->m2m.v4l2_dev,
 			 "Wrong buffer/video queue type (%d)\n", f->type);
-		ret = -EINVAL;
-		goto sf_out;
+		return -EINVAL;
 	}
-	spin_unlock_irqrestore(&ctx->slock, flags);
 
-	pix = &f->fmt.pix;
+	pix = &f->fmt.pix_mp;
 	frame->fmt = find_format(f, FMT_FLAGS_M2M);
-	if (!frame->fmt) {
-		ret = -EINVAL;
-		goto sf_out;
+	if (!frame->fmt)
+		return -EINVAL;
+
+	for (i = 0; i < frame->fmt->colplanes; i++) {
+		frame->payload[i] =
+			(pix->width * pix->height * frame->fmt->depth[i]) / 8;
 	}
 
-	frame->f_width	= pix->bytesperline * 8 / frame->fmt->depth;
+	frame->f_width	= pix->plane_fmt[0].bytesperline * 8 /
+		frame->fmt->depth[0];
 	frame->f_height	= pix->height;
 	frame->width	= pix->width;
 	frame->height	= pix->height;
@@ -920,19 +1009,15 @@
 	frame->o_height = pix->height;
 	frame->offs_h	= 0;
 	frame->offs_v	= 0;
-	frame->size	= (pix->width * pix->height * frame->fmt->depth) >> 3;
-	vq->field	= pix->field;
 
-	spin_lock_irqsave(&ctx->slock, flags);
-	ctx->state |= FIMC_PARAMS;
-	spin_unlock_irqrestore(&ctx->slock, flags);
+	if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_DST_FMT, ctx);
+	else
+		fimc_ctx_state_lock_set(FIMC_PARAMS | FIMC_SRC_FMT, ctx);
 
 	dbg("f_w: %d, f_h: %d", frame->f_width, frame->f_height);
 
-sf_out:
-	mutex_unlock(&vq->vb_lock);
-	mutex_unlock(&fimc->lock);
-	return ret;
+	return 0;
 }
 
 static int fimc_m2m_reqbufs(struct file *file, void *priv,
@@ -968,6 +1053,15 @@
 			   enum v4l2_buf_type type)
 {
 	struct fimc_ctx *ctx = priv;
+
+	/* The source and target color format need to be set */
+	if (V4L2_TYPE_IS_OUTPUT(type)) {
+		if (!fimc_ctx_state_is_set(FIMC_SRC_FMT, ctx))
+			return -EINVAL;
+	} else if (!fimc_ctx_state_is_set(FIMC_DST_FMT, ctx)) {
+		return -EINVAL;
+	}
+
 	return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
 }
 
@@ -991,12 +1085,9 @@
 		return 0;
 	}
 
-	if (ctx->state & FIMC_CTX_CAP) {
-		if (mutex_lock_interruptible(&ctx->fimc_dev->lock))
-			return -ERESTARTSYS;
-		ret = v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
+	if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
+		return v4l2_subdev_call(ctx->fimc_dev->vid_cap.sd,
 					core, queryctrl, qc);
-		mutex_unlock(&ctx->fimc_dev->lock);
 	}
 	return ret;
 }
@@ -1006,10 +1097,6 @@
 {
 	struct fimc_ctx *ctx = priv;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	int ret = 0;
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
 
 	switch (ctrl->id) {
 	case V4L2_CID_HFLIP:
@@ -1022,19 +1109,17 @@
 		ctrl->value = ctx->rotation;
 		break;
 	default:
-		if (ctx->state & FIMC_CTX_CAP) {
-			ret = v4l2_subdev_call(fimc->vid_cap.sd, core,
-				       g_ctrl, ctrl);
+		if (fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx)) {
+			return v4l2_subdev_call(fimc->vid_cap.sd, core,
+						g_ctrl, ctrl);
 		} else {
-			v4l2_err(&fimc->m2m.v4l2_dev,
-				 "Invalid control\n");
-			ret = -EINVAL;
+			v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
+			return -EINVAL;
 		}
 	}
 	dbg("ctrl->value= %d", ctrl->value);
 
-	mutex_unlock(&fimc->lock);
-	return ret;
+	return 0;
 }
 
 int check_ctrl_val(struct fimc_ctx *ctx,  struct v4l2_control *ctrl)
@@ -1058,16 +1143,7 @@
 {
 	struct samsung_fimc_variant *variant = ctx->fimc_dev->variant;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	unsigned long flags;
-
-	if (ctx->rotation != 0 &&
-	    (ctrl->id == V4L2_CID_HFLIP || ctrl->id == V4L2_CID_VFLIP)) {
-		v4l2_err(&fimc->m2m.v4l2_dev,
-			 "Simultaneous flip and rotation is not supported\n");
-		return -EINVAL;
-	}
-
-	spin_lock_irqsave(&ctx->slock, flags);
+	int ret = 0;
 
 	switch (ctrl->id) {
 	case V4L2_CID_HFLIP:
@@ -1085,29 +1161,36 @@
 		break;
 
 	case V4L2_CID_ROTATE:
+		if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+			ret = fimc_check_scaler_ratio(ctx->s_frame.width,
+					ctx->s_frame.height, ctx->d_frame.width,
+					ctx->d_frame.height, ctrl->value);
+		}
+
+		if (ret) {
+			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
+			return -EINVAL;
+		}
+
 		/* Check for the output rotator availability */
 		if ((ctrl->value == 90 || ctrl->value == 270) &&
-		    (ctx->in_path == FIMC_DMA && !variant->has_out_rot)) {
-			spin_unlock_irqrestore(&ctx->slock, flags);
+		    (ctx->in_path == FIMC_DMA && !variant->has_out_rot))
 			return -EINVAL;
-		} else {
-			ctx->rotation = ctrl->value;
-		}
+		ctx->rotation = ctrl->value;
 		break;
 
 	default:
-		spin_unlock_irqrestore(&ctx->slock, flags);
 		v4l2_err(&fimc->m2m.v4l2_dev, "Invalid control\n");
 		return -EINVAL;
 	}
-	ctx->state |= FIMC_PARAMS;
-	spin_unlock_irqrestore(&ctx->slock, flags);
+
+	fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
 
 	return 0;
 }
 
 static int fimc_m2m_s_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
+			   struct v4l2_control *ctrl)
 {
 	struct fimc_ctx *ctx = priv;
 	int ret = 0;
@@ -1125,22 +1208,17 @@
 {
 	struct fimc_frame *frame;
 	struct fimc_ctx *ctx = fh;
-	struct fimc_dev *fimc = ctx->fimc_dev;
 
 	frame = ctx_get_frame(ctx, cr->type);
 	if (IS_ERR(frame))
 		return PTR_ERR(frame);
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	cr->bounds.left		= 0;
 	cr->bounds.top		= 0;
 	cr->bounds.width	= frame->f_width;
 	cr->bounds.height	= frame->f_height;
 	cr->defrect		= cr->bounds;
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -1148,21 +1226,16 @@
 {
 	struct fimc_frame *frame;
 	struct fimc_ctx *ctx = file->private_data;
-	struct fimc_dev *fimc = ctx->fimc_dev;
 
 	frame = ctx_get_frame(ctx, cr->type);
 	if (IS_ERR(frame))
 		return PTR_ERR(frame);
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
 	cr->c.left = frame->offs_h;
 	cr->c.top = frame->offs_v;
 	cr->c.width = frame->width;
 	cr->c.height = frame->height;
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -1170,7 +1243,9 @@
 {
 	struct fimc_dev *fimc = ctx->fimc_dev;
 	struct fimc_frame *f;
-	u32 min_size, halign;
+	u32 min_size, halign, depth = 0;
+	bool is_capture_ctx;
+	int i;
 
 	if (cr->c.top < 0 || cr->c.left < 0) {
 		v4l2_err(&fimc->m2m.v4l2_dev,
@@ -1178,10 +1253,12 @@
 		return -EINVAL;
 	}
 
-	if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		f = (ctx->state & FIMC_CTX_CAP) ? &ctx->s_frame : &ctx->d_frame;
-	else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
-		 ctx->state & FIMC_CTX_M2M)
+	is_capture_ctx = fimc_ctx_state_is_set(FIMC_CTX_CAP, ctx);
+
+	if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		f = is_capture_ctx ? &ctx->s_frame : &ctx->d_frame;
+	else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE &&
+		 !is_capture_ctx)
 		f = &ctx->s_frame;
 	else
 		return -EINVAL;
@@ -1189,21 +1266,24 @@
 	min_size = (f == &ctx->s_frame) ?
 		fimc->variant->min_inp_pixsize : fimc->variant->min_out_pixsize;
 
-	if (ctx->state & FIMC_CTX_M2M) {
+	/* Get pixel alignment constraints. */
+	if (is_capture_ctx) {
+		min_size = 16;
+		halign = 4;
+	} else {
 		if (fimc->id == 1 && fimc->variant->pix_hoff)
 			halign = fimc_fmt_is_rgb(f->fmt->color) ? 0 : 1;
 		else
 			halign = ffs(min_size) - 1;
-	/* there are more strict aligment requirements at camera interface */
-	} else {
-		min_size = 16;
-		halign = 4;
 	}
 
+	for (i = 0; i < f->fmt->colplanes; i++)
+		depth += f->fmt->depth[i];
+
 	v4l_bound_align_image(&cr->c.width, min_size, f->o_width,
 			      ffs(min_size) - 1,
 			      &cr->c.height, min_size, f->o_height,
-			      halign, 64/(ALIGN(f->fmt->depth, 8)));
+			      halign, 64/(ALIGN(depth, 8)));
 
 	/* adjust left/top if cropping rectangle is out of bounds */
 	if (cr->c.left + cr->c.width > f->o_width)
@@ -1212,8 +1292,7 @@
 		cr->c.top = f->o_height - cr->c.height;
 
 	cr->c.left = round_down(cr->c.left, min_size);
-	cr->c.top  = round_down(cr->c.top,
-				ctx->state & FIMC_CTX_M2M ? 8 : 16);
+	cr->c.top  = round_down(cr->c.top, is_capture_ctx ? 16 : 8);
 
 	dbg("l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
 	    cr->c.left, cr->c.top, cr->c.width, cr->c.height,
@@ -1222,12 +1301,10 @@
 	return 0;
 }
 
-
 static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
 {
 	struct fimc_ctx *ctx = file->private_data;
 	struct fimc_dev *fimc = ctx->fimc_dev;
-	unsigned long flags;
 	struct fimc_frame *f;
 	int ret;
 
@@ -1235,52 +1312,52 @@
 	if (ret)
 		return ret;
 
-	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) ?
+	f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
 		&ctx->s_frame : &ctx->d_frame;
 
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
-
-	spin_lock_irqsave(&ctx->slock, flags);
-	if (~ctx->state & (FIMC_SRC_FMT | FIMC_DST_FMT)) {
-		/* Check to see if scaling ratio is within supported range */
-		if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
-			ret = fimc_check_scaler_ratio(&cr->c, &ctx->d_frame);
-		else
-			ret = fimc_check_scaler_ratio(&cr->c, &ctx->s_frame);
+	/* Check to see if scaling ratio is within supported range */
+	if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
+		if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+			ret = fimc_check_scaler_ratio(cr->c.width, cr->c.height,
+						      ctx->d_frame.width,
+						      ctx->d_frame.height,
+						      ctx->rotation);
+		} else {
+			ret = fimc_check_scaler_ratio(ctx->s_frame.width,
+						      ctx->s_frame.height,
+						      cr->c.width, cr->c.height,
+						      ctx->rotation);
+		}
 		if (ret) {
-			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range");
-			ret = -EINVAL;
-			goto scr_unlock;
+			v4l2_err(&fimc->m2m.v4l2_dev, "Out of scaler range\n");
+			return -EINVAL;
 		}
 	}
-	ctx->state |= FIMC_PARAMS;
 
 	f->offs_h = cr->c.left;
 	f->offs_v = cr->c.top;
 	f->width  = cr->c.width;
 	f->height = cr->c.height;
 
-scr_unlock:
-	spin_unlock_irqrestore(&ctx->slock, flags);
-	mutex_unlock(&fimc->lock);
+	fimc_ctx_state_lock_set(FIMC_PARAMS, ctx);
+
 	return 0;
 }
 
 static const struct v4l2_ioctl_ops fimc_m2m_ioctl_ops = {
 	.vidioc_querycap		= fimc_m2m_querycap,
 
-	.vidioc_enum_fmt_vid_cap	= fimc_vidioc_enum_fmt,
-	.vidioc_enum_fmt_vid_out	= fimc_vidioc_enum_fmt,
+	.vidioc_enum_fmt_vid_cap_mplane	= fimc_vidioc_enum_fmt_mplane,
+	.vidioc_enum_fmt_vid_out_mplane	= fimc_vidioc_enum_fmt_mplane,
 
-	.vidioc_g_fmt_vid_cap		= fimc_vidioc_g_fmt,
-	.vidioc_g_fmt_vid_out		= fimc_vidioc_g_fmt,
+	.vidioc_g_fmt_vid_cap_mplane	= fimc_vidioc_g_fmt_mplane,
+	.vidioc_g_fmt_vid_out_mplane	= fimc_vidioc_g_fmt_mplane,
 
-	.vidioc_try_fmt_vid_cap		= fimc_vidioc_try_fmt,
-	.vidioc_try_fmt_vid_out		= fimc_vidioc_try_fmt,
+	.vidioc_try_fmt_vid_cap_mplane	= fimc_vidioc_try_fmt_mplane,
+	.vidioc_try_fmt_vid_out_mplane	= fimc_vidioc_try_fmt_mplane,
 
-	.vidioc_s_fmt_vid_cap		= fimc_m2m_s_fmt,
-	.vidioc_s_fmt_vid_out		= fimc_m2m_s_fmt,
+	.vidioc_s_fmt_vid_cap_mplane	= fimc_m2m_s_fmt_mplane,
+	.vidioc_s_fmt_vid_out_mplane	= fimc_m2m_s_fmt_mplane,
 
 	.vidioc_reqbufs			= fimc_m2m_reqbufs,
 	.vidioc_querybuf		= fimc_m2m_querybuf,
@@ -1301,26 +1378,39 @@
 
 };
 
-static void queue_init(void *priv, struct videobuf_queue *vq,
-		       enum v4l2_buf_type type)
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+		      struct vb2_queue *dst_vq)
 {
 	struct fimc_ctx *ctx = priv;
-	struct fimc_dev *fimc = ctx->fimc_dev;
+	int ret;
 
-	videobuf_queue_dma_contig_init(vq, &fimc_qops,
-		&fimc->pdev->dev,
-		&fimc->irqlock, type, V4L2_FIELD_NONE,
-		sizeof(struct fimc_vid_buffer), priv, NULL);
+	memset(src_vq, 0, sizeof(*src_vq));
+	src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+	src_vq->drv_priv = ctx;
+	src_vq->ops = &fimc_qops;
+	src_vq->mem_ops = &vb2_dma_contig_memops;
+	src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+
+	ret = vb2_queue_init(src_vq);
+	if (ret)
+		return ret;
+
+	memset(dst_vq, 0, sizeof(*dst_vq));
+	dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+	dst_vq->drv_priv = ctx;
+	dst_vq->ops = &fimc_qops;
+	dst_vq->mem_ops = &vb2_dma_contig_memops;
+	dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+
+	return vb2_queue_init(dst_vq);
 }
 
 static int fimc_m2m_open(struct file *file)
 {
 	struct fimc_dev *fimc = video_drvdata(file);
 	struct fimc_ctx *ctx = NULL;
-	int err = 0;
-
-	if (mutex_lock_interruptible(&fimc->lock))
-		return -ERESTARTSYS;
 
 	dbg("pid: %d, state: 0x%lx, refcnt: %d",
 		task_pid_nr(current), fimc->state, fimc->vid_cap.refcnt);
@@ -1329,19 +1419,15 @@
 	 * Return if the corresponding video capture node
 	 * is already opened.
 	 */
-	if (fimc->vid_cap.refcnt > 0) {
-		err = -EBUSY;
-		goto err_unlock;
-	}
+	if (fimc->vid_cap.refcnt > 0)
+		return -EBUSY;
 
 	fimc->m2m.refcnt++;
 	set_bit(ST_OUTDMA_RUN, &fimc->state);
 
 	ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
-	if (!ctx) {
-		err = -ENOMEM;
-		goto err_unlock;
-	}
+	if (!ctx)
+		return -ENOMEM;
 
 	file->private_data = ctx;
 	ctx->fimc_dev = fimc;
@@ -1355,15 +1441,14 @@
 	ctx->out_path = FIMC_DMA;
 	spin_lock_init(&ctx->slock);
 
-	ctx->m2m_ctx = v4l2_m2m_ctx_init(ctx, fimc->m2m.m2m_dev, queue_init);
+	ctx->m2m_ctx = v4l2_m2m_ctx_init(fimc->m2m.m2m_dev, ctx, queue_init);
 	if (IS_ERR(ctx->m2m_ctx)) {
-		err = PTR_ERR(ctx->m2m_ctx);
+		int err = PTR_ERR(ctx->m2m_ctx);
 		kfree(ctx);
+		return err;
 	}
 
-err_unlock:
-	mutex_unlock(&fimc->lock);
-	return err;
+	return 0;
 }
 
 static int fimc_m2m_release(struct file *file)
@@ -1371,8 +1456,6 @@
 	struct fimc_ctx *ctx = file->private_data;
 	struct fimc_dev *fimc = ctx->fimc_dev;
 
-	mutex_lock(&fimc->lock);
-
 	dbg("pid: %d, state: 0x%lx, refcnt= %d",
 		task_pid_nr(current), fimc->state, fimc->m2m.refcnt);
 
@@ -1381,7 +1464,6 @@
 	if (--fimc->m2m.refcnt <= 0)
 		clear_bit(ST_OUTDMA_RUN, &fimc->state);
 
-	mutex_unlock(&fimc->lock);
 	return 0;
 }
 
@@ -1415,7 +1497,6 @@
 	.job_abort	= fimc_job_abort,
 };
 
-
 static int fimc_register_m2m_device(struct fimc_dev *fimc)
 {
 	struct video_device *vfd;
@@ -1448,6 +1529,7 @@
 	vfd->ioctl_ops	= &fimc_m2m_ioctl_ops;
 	vfd->minor	= -1;
 	vfd->release	= video_device_release;
+	vfd->lock	= &fimc->lock;
 
 	snprintf(vfd->name, sizeof(vfd->name), "%s:m2m", dev_name(&pdev->dev));
 
@@ -1496,7 +1578,7 @@
 static void fimc_clk_release(struct fimc_dev *fimc)
 {
 	int i;
-	for (i = 0; i < NUM_FIMC_CLOCKS; i++) {
+	for (i = 0; i < fimc->num_clocks; i++) {
 		if (fimc->clock[i]) {
 			clk_disable(fimc->clock[i]);
 			clk_put(fimc->clock[i]);
@@ -1507,15 +1589,16 @@
 static int fimc_clk_get(struct fimc_dev *fimc)
 {
 	int i;
-	for (i = 0; i < NUM_FIMC_CLOCKS; i++) {
-		fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clock_name[i]);
-		if (IS_ERR(fimc->clock[i])) {
-			dev_err(&fimc->pdev->dev,
-				"failed to get fimc clock: %s\n",
-				fimc_clock_name[i]);
-			return -ENXIO;
+	for (i = 0; i < fimc->num_clocks; i++) {
+		fimc->clock[i] = clk_get(&fimc->pdev->dev, fimc_clocks[i]);
+
+		if (!IS_ERR_OR_NULL(fimc->clock[i])) {
+			clk_enable(fimc->clock[i]);
+			continue;
 		}
-		clk_enable(fimc->clock[i]);
+		dev_err(&fimc->pdev->dev, "failed to get fimc clock: %s\n",
+			fimc_clocks[i]);
+		return -ENXIO;
 	}
 	return 0;
 }
@@ -1525,7 +1608,9 @@
 	struct fimc_dev *fimc;
 	struct resource *res;
 	struct samsung_fimc_driverdata *drv_data;
+	struct s5p_platform_fimc *pdata;
 	int ret = 0;
+	int cap_input_index = -1;
 
 	dev_dbg(&pdev->dev, "%s():\n", __func__);
 
@@ -1545,10 +1630,10 @@
 	fimc->id = pdev->id;
 	fimc->variant = drv_data->variant[fimc->id];
 	fimc->pdev = pdev;
-	fimc->pdata = pdev->dev.platform_data;
+	pdata = pdev->dev.platform_data;
+	fimc->pdata = pdata;
 	fimc->state = ST_IDLE;
 
-	spin_lock_init(&fimc->irqlock);
 	init_waitqueue_head(&fimc->irq_queue);
 	spin_lock_init(&fimc->slock);
 
@@ -1576,10 +1661,18 @@
 		goto err_req_region;
 	}
 
+	fimc->num_clocks = MAX_FIMC_CLOCKS - 1;
+
+	/* Check if a video capture node needs to be registered. */
+	if (pdata && pdata->num_clients > 0) {
+		cap_input_index = 0;
+		fimc->num_clocks++;
+	}
+
 	ret = fimc_clk_get(fimc);
 	if (ret)
 		goto err_regs_unmap;
-	clk_set_rate(fimc->clock[0], drv_data->lclk_frequency);
+	clk_set_rate(fimc->clock[CLK_BUS], drv_data->lclk_frequency);
 
 	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	if (!res) {
@@ -1597,24 +1690,24 @@
 		goto err_clk;
 	}
 
+	/* Initialize contiguous memory allocator */
+	fimc->alloc_ctx = vb2_dma_contig_init_ctx(&fimc->pdev->dev);
+	if (IS_ERR(fimc->alloc_ctx)) {
+		ret = PTR_ERR(fimc->alloc_ctx);
+		goto err_irq;
+	}
+
 	ret = fimc_register_m2m_device(fimc);
 	if (ret)
 		goto err_irq;
 
 	/* At least one camera sensor is required to register capture node */
-	if (fimc->pdata) {
-		int i;
-		for (i = 0; i < FIMC_MAX_CAMIF_CLIENTS; ++i)
-			if (fimc->pdata->isp_info[i])
-				break;
-
-		if (i < FIMC_MAX_CAMIF_CLIENTS) {
-			ret = fimc_register_capture_device(fimc);
-			if (ret)
-				goto err_m2m;
-		}
+	if (cap_input_index >= 0) {
+		ret = fimc_register_capture_device(fimc);
+		if (ret)
+			goto err_m2m;
+		clk_disable(fimc->clock[CLK_CAM]);
 	}
-
 	/*
 	 * Exclude the additional output DMA address registers by masking
 	 * them out on HW revisions that provide extended capabilites.
@@ -1656,6 +1749,9 @@
 	fimc_unregister_capture_device(fimc);
 
 	fimc_clk_release(fimc);
+
+	vb2_dma_contig_cleanup_ctx(fimc->alloc_ctx);
+
 	iounmap(fimc->regs);
 	release_resource(fimc->regs_res);
 	kfree(fimc->regs_res);
@@ -1666,7 +1762,7 @@
 }
 
 /* Image pixel limits, similar across several FIMC HW revisions. */
-static struct fimc_pix_limit s5p_pix_limit[3] = {
+static struct fimc_pix_limit s5p_pix_limit[4] = {
 	[0] = {
 		.scaler_en_w	= 3264,
 		.scaler_dis_w	= 8192,
@@ -1691,6 +1787,14 @@
 		.out_rot_en_w	= 1280,
 		.out_rot_dis_w	= 1920,
 	},
+	[3] = {
+		.scaler_en_w	= 1920,
+		.scaler_dis_w	= 8192,
+		.in_rot_en_h	= 1366,
+		.in_rot_dis_w	= 8192,
+		.out_rot_en_w	= 1366,
+		.out_rot_dis_w	= 1920,
+	},
 };
 
 static struct samsung_fimc_variant fimc0_variant_s5p = {
@@ -1726,6 +1830,7 @@
 	.pix_hoff	 = 1,
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
+	.has_mainscaler_ext = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 1,
@@ -1742,11 +1847,12 @@
 	.pix_limit	 = &s5p_pix_limit[2],
 };
 
-static struct samsung_fimc_variant fimc0_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc0_variant_exynos4 = {
 	.pix_hoff	 = 1,
 	.has_inp_rot	 = 1,
 	.has_out_rot	 = 1,
 	.has_cistatus2	 = 1,
+	.has_mainscaler_ext = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 1,
@@ -1754,14 +1860,15 @@
 	.pix_limit	 = &s5p_pix_limit[1],
 };
 
-static struct samsung_fimc_variant fimc2_variant_s5pv310 = {
+static struct samsung_fimc_variant fimc2_variant_exynos4 = {
 	.pix_hoff	 = 1,
 	.has_cistatus2	 = 1,
+	.has_mainscaler_ext = 1,
 	.min_inp_pixsize = 16,
 	.min_out_pixsize = 16,
 	.hor_offs_align	 = 1,
 	.out_buf_count	 = 32,
-	.pix_limit	 = &s5p_pix_limit[2],
+	.pix_limit	 = &s5p_pix_limit[3],
 };
 
 /* S5PC100 */
@@ -1787,12 +1894,12 @@
 };
 
 /* S5PV310, S5PC210 */
-static struct samsung_fimc_driverdata fimc_drvdata_s5pv310 = {
+static struct samsung_fimc_driverdata fimc_drvdata_exynos4 = {
 	.variant = {
-		[0] = &fimc0_variant_s5pv310,
-		[1] = &fimc0_variant_s5pv310,
-		[2] = &fimc0_variant_s5pv310,
-		[3] = &fimc2_variant_s5pv310,
+		[0] = &fimc0_variant_exynos4,
+		[1] = &fimc0_variant_exynos4,
+		[2] = &fimc0_variant_exynos4,
+		[3] = &fimc2_variant_exynos4,
 	},
 	.num_entities = 4,
 	.lclk_frequency = 166000000UL,
@@ -1806,8 +1913,8 @@
 		.name		= "s5pv210-fimc",
 		.driver_data	= (unsigned long)&fimc_drvdata_s5pv210,
 	}, {
-		.name		= "s5pv310-fimc",
-		.driver_data	= (unsigned long)&fimc_drvdata_s5pv310,
+		.name		= "exynos4-fimc",
+		.driver_data	= (unsigned long)&fimc_drvdata_exynos4,
 	},
 	{},
 };
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-core.h linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-core.h
--- linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,29 +14,27 @@
 /*#define DEBUG*/
 
 #include <linux/sched.h>
+#include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/videodev2.h>
-#include <media/videobuf-core.h>
+#include <linux/io.h>
+#include <media/videobuf2-core.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-mem2mem.h>
 #include <media/v4l2-mediabus.h>
-#include <media/s3c_fimc.h>
+#include <media/s5p_fimc.h>
 
 #include "regs-fimc.h"
 
 #define err(fmt, args...) \
 	printk(KERN_ERR "%s:%d: " fmt "\n", __func__, __LINE__, ##args)
 
-#ifdef DEBUG
 #define dbg(fmt, args...) \
-	printk(KERN_DEBUG "%s:%d: " fmt "\n", __func__, __LINE__, ##args)
-#else
-#define dbg(fmt, args...)
-#endif
+	pr_debug("%s:%d: " fmt "\n", __func__, __LINE__, ##args)
 
 /* Time to wait for next frame VSYNC interrupt while stopping operation. */
 #define FIMC_SHUTDOWN_TIMEOUT	((100*HZ)/1000)
-#define NUM_FIMC_CLOCKS		2
+#define MAX_FIMC_CLOCKS		3
 #define MODULE_NAME		"s5p-fimc"
 #define FIMC_MAX_DEVS		4
 #define FIMC_MAX_OUT_BUFS	4
@@ -44,7 +42,13 @@
 #define SCALER_MAX_VRATIO	64
 #define DMA_MIN_SIZE		8
 
-/* FIMC device state flags */
+/* indices to the clocks array */
+enum {
+	CLK_BUS,
+	CLK_GATE,
+	CLK_CAM,
+};
+
 enum fimc_dev_flags {
 	/* for m2m node */
 	ST_IDLE,
@@ -63,20 +67,6 @@
 #define fimc_capture_running(dev) test_bit(ST_CAPT_RUN, &(dev)->state)
 #define fimc_capture_pending(dev) test_bit(ST_CAPT_PEND, &(dev)->state)
 
-#define fimc_capture_active(dev) \
-	(test_bit(ST_CAPT_RUN, &(dev)->state) || \
-	 test_bit(ST_CAPT_PEND, &(dev)->state))
-
-#define fimc_capture_streaming(dev) \
-	test_bit(ST_CAPT_STREAM, &(dev)->state)
-
-#define fimc_buf_finish(dev, vid_buf) do { \
-	spin_lock(&(dev)->irqlock); \
-	(vid_buf)->vb.state = VIDEOBUF_DONE; \
-	spin_unlock(&(dev)->irqlock); \
-	wake_up(&(vid_buf)->vb.done); \
-} while (0)
-
 enum fimc_datapath {
 	FIMC_CAMERA,
 	FIMC_DMA,
@@ -90,7 +80,6 @@
 	S5P_FIMC_RGB888,
 	S5P_FIMC_RGB30_LOCAL,
 	S5P_FIMC_YCBCR420 = 0x20,
-	S5P_FIMC_YCBCR422,
 	S5P_FIMC_YCBYCR422,
 	S5P_FIMC_YCRYCB422,
 	S5P_FIMC_CBYCRY422,
@@ -100,18 +89,6 @@
 
 #define fimc_fmt_is_rgb(x) ((x) & 0x10)
 
-/* Y/Cb/Cr components order at DMA output for 1 plane YCbCr 4:2:2 formats. */
-#define	S5P_FIMC_OUT_CRYCBY	S5P_CIOCTRL_ORDER422_CRYCBY
-#define	S5P_FIMC_OUT_CBYCRY	S5P_CIOCTRL_ORDER422_YCRYCB
-#define	S5P_FIMC_OUT_YCRYCB	S5P_CIOCTRL_ORDER422_CBYCRY
-#define	S5P_FIMC_OUT_YCBYCR	S5P_CIOCTRL_ORDER422_YCBYCR
-
-/* Input Y/Cb/Cr components order for 1 plane YCbCr 4:2:2 color formats. */
-#define	S5P_FIMC_IN_CRYCBY	S5P_MSCTRL_ORDER422_CRYCBY
-#define	S5P_FIMC_IN_CBYCRY	S5P_MSCTRL_ORDER422_YCRYCB
-#define	S5P_FIMC_IN_YCRYCB	S5P_MSCTRL_ORDER422_CBYCRY
-#define	S5P_FIMC_IN_YCBYCR	S5P_MSCTRL_ORDER422_YCBYCR
-
 /* Cb/Cr chrominance components order for 2 plane Y/CbCr 4:2:2 formats. */
 #define	S5P_FIMC_LSB_CRCB	S5P_CIOCTRL_ORDER422_2P_LSB_CRCB
 
@@ -131,6 +108,7 @@
 #define	FIMC_DST_FMT		(1 << 4)
 #define	FIMC_CTX_M2M		(1 << 5)
 #define	FIMC_CTX_CAP		(1 << 6)
+#define	FIMC_CTX_SHUT		(1 << 7)
 
 /* Image conversion flags */
 #define	FIMC_IN_DMA_ACCESS_TILED	(1 << 0)
@@ -157,18 +135,18 @@
  * @name: format description
  * @fourcc: the fourcc code for this format, 0 if not applicable
  * @color: the corresponding fimc_color_fmt
- * @depth: driver's private 'number of bits per pixel'
- * @buff_cnt: number of physically non-contiguous data planes
- * @planes_cnt: number of physically contiguous data planes
+ * @depth: per plane driver's private 'number of bits per pixel'
+ * @memplanes: number of physically non-contiguous data planes
+ * @colplanes: number of physically contiguous data planes
  */
 struct fimc_fmt {
 	enum v4l2_mbus_pixelcode mbus_code;
 	char	*name;
 	u32	fourcc;
 	u32	color;
-	u16	buff_cnt;
-	u16	planes_cnt;
-	u16	depth;
+	u16	memplanes;
+	u16	colplanes;
+	u8	depth[VIDEO_MAX_PLANES];
 	u16	flags;
 #define FMT_FLAGS_CAM	(1 << 0)
 #define FMT_FLAGS_M2M	(1 << 1)
@@ -260,7 +238,8 @@
  * @index: buffer index for the output DMA engine
  */
 struct fimc_vid_buffer {
-	struct videobuf_buffer	vb;
+	struct vb2_buffer	vb;
+	struct list_head	list;
 	struct fimc_addr	paddr;
 	int			index;
 };
@@ -277,7 +256,7 @@
  * @height:	image pixel weight
  * @paddr:	image frame buffer physical addresses
  * @buf_cnt:	number of buffers depending on a color format
- * @size:	image size in bytes
+ * @payload:	image size in bytes (w x h x bpp)
  * @color:	color format
  * @dma_offset:	DMA offset in bytes
  */
@@ -290,7 +269,7 @@
 	u32	offs_v;
 	u32	width;
 	u32	height;
-	u32	size;
+	unsigned long		payload[VIDEO_MAX_PLANES];
 	struct fimc_addr	paddr;
 	struct fimc_dma_offset	dma_offset;
 	struct fimc_fmt		*fmt;
@@ -331,13 +310,14 @@
  */
 struct fimc_vid_cap {
 	struct fimc_ctx			*ctx;
+	struct vb2_alloc_ctx		*alloc_ctx;
 	struct video_device		*vfd;
 	struct v4l2_device		v4l2_dev;
-	struct v4l2_subdev		*sd;
+	struct v4l2_subdev		*sd;;
 	struct v4l2_mbus_framefmt	fmt;
 	struct list_head		pending_buf_q;
 	struct list_head		active_buf_q;
-	struct videobuf_queue		vbq;
+	struct vb2_queue		vbq;
 	int				active_buf_cnt;
 	int				buf_index;
 	unsigned int			frame_count;
@@ -372,6 +352,8 @@
  * @has_inp_rot: set if has input rotator
  * @has_out_rot: set if has output rotator
  * @has_cistatus2: 1 if CISTATUS2 register is present in this IP revision
+ * @has_mainscaler_ext: 1 if extended mainscaler ratios in CIEXTEN register
+ *			 are present in this IP revision
  * @pix_limit: pixel size constraints for the scaler
  * @min_inp_pixsize: minimum input pixel size
  * @min_out_pixsize: minimum output pixel size
@@ -383,6 +365,7 @@
 	unsigned int	has_inp_rot:1;
 	unsigned int	has_out_rot:1;
 	unsigned int	has_cistatus2:1;
+	unsigned int	has_mainscaler_ext:1;
 	struct fimc_pix_limit *pix_limit;
 	u16		min_inp_pixsize;
 	u16		min_out_pixsize;
@@ -412,12 +395,12 @@
  * @lock:	the mutex protecting this data structure
  * @pdev:	pointer to the FIMC platform device
  * @pdata:	pointer to the device platform data
- * @id:		FIMC device index (0..2)
+ * @id:		FIMC device index (0..FIMC_MAX_DEVS)
+ * @num_clocks: the number of clocks managed by this device instance
  * @clock[]:	the clocks required for FIMC operation
  * @regs:	the mapped hardware registers
  * @regs_res:	the resource claimed for IO registers
  * @irq:	interrupt number of the FIMC subdevice
- * @irqlock:	spinlock protecting videobuffer queue
  * @irq_queue:
  * @m2m:	memory-to-memory V4L2 device information
  * @vid_cap:	camera capture device information
@@ -427,18 +410,19 @@
 	spinlock_t			slock;
 	struct mutex			lock;
 	struct platform_device		*pdev;
-	struct s3c_platform_fimc	*pdata;
+	struct s5p_platform_fimc	*pdata;
 	struct samsung_fimc_variant	*variant;
-	int				id;
-	struct clk			*clock[NUM_FIMC_CLOCKS];
+	u16				id;
+	u16				num_clocks;
+	struct clk			*clock[MAX_FIMC_CLOCKS];
 	void __iomem			*regs;
 	struct resource			*regs_res;
 	int				irq;
-	spinlock_t			irqlock;
 	wait_queue_head_t		irq_queue;
 	struct fimc_m2m_device		m2m;
 	struct fimc_vid_cap		vid_cap;
 	unsigned long			state;
+	struct vb2_alloc_ctx		*alloc_ctx;
 };
 
 /**
@@ -482,11 +466,41 @@
 	struct v4l2_m2m_ctx	*m2m_ctx;
 };
 
-extern struct videobuf_queue_ops fimc_qops;
+static inline bool fimc_capture_active(struct fimc_dev *fimc)
+{
+	unsigned long flags;
+	bool ret;
+
+	spin_lock_irqsave(&fimc->slock, flags);
+	ret = !!(fimc->state & (1 << ST_CAPT_RUN) ||
+		 fimc->state & (1 << ST_CAPT_PEND));
+	spin_unlock_irqrestore(&fimc->slock, flags);
+	return ret;
+}
+
+static inline void fimc_ctx_state_lock_set(u32 state, struct fimc_ctx *ctx)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&ctx->slock, flags);
+	ctx->state |= state;
+	spin_unlock_irqrestore(&ctx->slock, flags);
+}
+
+static inline bool fimc_ctx_state_is_set(u32 mask, struct fimc_ctx *ctx)
+{
+	unsigned long flags;
+	bool ret;
+
+	spin_lock_irqsave(&ctx->slock, flags);
+	ret = (ctx->state & mask) == mask;
+	spin_unlock_irqrestore(&ctx->slock, flags);
+	return ret;
+}
 
 static inline int tiled_fmt(struct fimc_fmt *fmt)
 {
-	return 0;
+	return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
 static inline void fimc_hw_clear_irq(struct fimc_dev *dev)
@@ -542,12 +556,12 @@
 {
 	struct fimc_frame *frame;
 
-	if (V4L2_BUF_TYPE_VIDEO_OUTPUT == type) {
-		if (ctx->state & FIMC_CTX_M2M)
+	if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) {
+		if (fimc_ctx_state_is_set(FIMC_CTX_M2M, ctx))
 			frame = &ctx->s_frame;
 		else
 			return ERR_PTR(-EINVAL);
-	} else if (V4L2_BUF_TYPE_VIDEO_CAPTURE == type) {
+	} else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) {
 		frame = &ctx->d_frame;
 	} else {
 		v4l2_err(&ctx->fimc_dev->m2m.v4l2_dev,
@@ -581,7 +595,8 @@
 void fimc_hw_set_out_dma(struct fimc_ctx *ctx);
 void fimc_hw_en_lastirq(struct fimc_dev *fimc, int enable);
 void fimc_hw_en_irq(struct fimc_dev *fimc, int enable);
-void fimc_hw_set_scaler(struct fimc_ctx *ctx);
+void fimc_hw_set_prescaler(struct fimc_ctx *ctx);
+void fimc_hw_set_mainscaler(struct fimc_ctx *ctx);
 void fimc_hw_en_capture(struct fimc_ctx *ctx);
 void fimc_hw_set_effect(struct fimc_ctx *ctx);
 void fimc_hw_set_in_dma(struct fimc_ctx *ctx);
@@ -589,23 +604,23 @@
 void fimc_hw_set_output_path(struct fimc_ctx *ctx);
 void fimc_hw_set_input_addr(struct fimc_dev *fimc, struct fimc_addr *paddr);
 void fimc_hw_set_output_addr(struct fimc_dev *fimc, struct fimc_addr *paddr,
-			      int index);
+			     int index);
 int fimc_hw_set_camera_source(struct fimc_dev *fimc,
-			      struct s3c_fimc_isp_info *cam);
+			      struct s5p_fimc_isp_info *cam);
 int fimc_hw_set_camera_offset(struct fimc_dev *fimc, struct fimc_frame *f);
 int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
-				struct s3c_fimc_isp_info *cam);
+				struct s5p_fimc_isp_info *cam);
 int fimc_hw_set_camera_type(struct fimc_dev *fimc,
-			    struct s3c_fimc_isp_info *cam);
+			    struct s5p_fimc_isp_info *cam);
 
 /* -----------------------------------------------------*/
 /* fimc-core.c */
-int fimc_vidioc_enum_fmt(struct file *file, void *priv,
-		      struct v4l2_fmtdesc *f);
-int fimc_vidioc_g_fmt(struct file *file, void *priv,
-		      struct v4l2_format *f);
-int fimc_vidioc_try_fmt(struct file *file, void *priv,
-			struct v4l2_format *f);
+int fimc_vidioc_enum_fmt_mplane(struct file *file, void *priv,
+				struct v4l2_fmtdesc *f);
+int fimc_vidioc_g_fmt_mplane(struct file *file, void *priv,
+			     struct v4l2_format *f);
+int fimc_vidioc_try_fmt_mplane(struct file *file, void *priv,
+			       struct v4l2_format *f);
 int fimc_vidioc_queryctrl(struct file *file, void *priv,
 			  struct v4l2_queryctrl *qc);
 int fimc_vidioc_g_ctrl(struct file *file, void *priv,
@@ -619,10 +634,10 @@
 struct fimc_fmt *find_mbus_format(struct v4l2_mbus_framefmt *f,
 				  unsigned int mask);
 
-int fimc_check_scaler_ratio(struct v4l2_rect *r, struct fimc_frame *f);
+int fimc_check_scaler_ratio(int sw, int sh, int dw, int dh, int rot);
 int fimc_set_scaler_info(struct fimc_ctx *ctx);
 int fimc_prepare_config(struct fimc_ctx *ctx, u32 flags);
-int fimc_prepare_addr(struct fimc_ctx *ctx, struct fimc_vid_buffer *buf,
+int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
 		      struct fimc_frame *frame, struct fimc_addr *paddr);
 
 /* -----------------------------------------------------*/
@@ -649,28 +664,27 @@
 }
 
 /*
- * Add video buffer to the active buffers queue.
- * The caller holds irqlock spinlock.
+ * Add buf to the capture active buffers queue.
+ * Locking: Need to be called with fimc_dev::slock held.
  */
 static inline void active_queue_add(struct fimc_vid_cap *vid_cap,
-					 struct fimc_vid_buffer *buf)
+				    struct fimc_vid_buffer *buf)
 {
-	buf->vb.state = VIDEOBUF_ACTIVE;
-	list_add_tail(&buf->vb.queue, &vid_cap->active_buf_q);
+	list_add_tail(&buf->list, &vid_cap->active_buf_q);
 	vid_cap->active_buf_cnt++;
 }
 
 /*
  * Pop a video buffer from the capture active buffers queue
- * Locking: Need to be called with dev->slock held.
+ * Locking: Need to be called with fimc_dev::slock held.
  */
 static inline struct fimc_vid_buffer *
 active_queue_pop(struct fimc_vid_cap *vid_cap)
 {
 	struct fimc_vid_buffer *buf;
 	buf = list_entry(vid_cap->active_buf_q.next,
-			 struct fimc_vid_buffer, vb.queue);
-	list_del(&buf->vb.queue);
+			 struct fimc_vid_buffer, list);
+	list_del(&buf->list);
 	vid_cap->active_buf_cnt--;
 	return buf;
 }
@@ -679,8 +693,7 @@
 static inline void fimc_pending_queue_add(struct fimc_vid_cap *vid_cap,
 					  struct fimc_vid_buffer *buf)
 {
-	buf->vb.state = VIDEOBUF_QUEUED;
-	list_add_tail(&buf->vb.queue, &vid_cap->pending_buf_q);
+	list_add_tail(&buf->list, &vid_cap->pending_buf_q);
 }
 
 /* Add video buffer to the capture pending buffers queue */
@@ -689,10 +702,9 @@
 {
 	struct fimc_vid_buffer *buf;
 	buf = list_entry(vid_cap->pending_buf_q.next,
-			struct fimc_vid_buffer, vb.queue);
-	list_del(&buf->vb.queue);
+			struct fimc_vid_buffer, list);
+	list_del(&buf->list);
 	return buf;
 }
 
-
 #endif /* FIMC_CORE_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-reg.c linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-reg.c
--- linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/fimc-reg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/fimc-reg.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
 #include <linux/io.h>
 #include <linux/delay.h>
 #include <mach/map.h>
-#include <media/s3c_fimc.h>
+#include <media/s5p_fimc.h>
 
 #include "fimc-core.h"
 
@@ -37,11 +37,11 @@
 	writel(cfg, dev->regs + S5P_CIGCTRL);
 }
 
-static u32 fimc_hw_get_in_flip(u32 ctx_flip)
+static u32 fimc_hw_get_in_flip(struct fimc_ctx *ctx)
 {
 	u32 flip = S5P_MSCTRL_FLIP_NORMAL;
 
-	switch (ctx_flip) {
+	switch (ctx->flip) {
 	case FLIP_X_AXIS:
 		flip = S5P_MSCTRL_FLIP_X_MIRROR;
 		break;
@@ -51,16 +51,20 @@
 	case FLIP_XY_AXIS:
 		flip = S5P_MSCTRL_FLIP_180;
 		break;
+	default:
+		break;
 	}
+	if (ctx->rotation <= 90)
+		return flip;
 
-	return flip;
+	return (flip ^ S5P_MSCTRL_FLIP_180) & S5P_MSCTRL_FLIP_180;
 }
 
-static u32 fimc_hw_get_target_flip(u32 ctx_flip)
+static u32 fimc_hw_get_target_flip(struct fimc_ctx *ctx)
 {
 	u32 flip = S5P_CITRGFMT_FLIP_NORMAL;
 
-	switch (ctx_flip) {
+	switch (ctx->flip) {
 	case FLIP_X_AXIS:
 		flip = S5P_CITRGFMT_FLIP_X_MIRROR;
 		break;
@@ -70,11 +74,13 @@
 	case FLIP_XY_AXIS:
 		flip = S5P_CITRGFMT_FLIP_180;
 		break;
-	case FLIP_NONE:
+	default:
 		break;
-
 	}
-	return flip;
+	if (ctx->rotation <= 90)
+		return flip;
+
+	return (flip ^ S5P_CITRGFMT_FLIP_180) & S5P_CITRGFMT_FLIP_180;
 }
 
 void fimc_hw_set_rotation(struct fimc_ctx *ctx)
@@ -84,10 +90,7 @@
 
 	cfg = readl(dev->regs + S5P_CITRGFMT);
 	cfg &= ~(S5P_CITRGFMT_INROT90 | S5P_CITRGFMT_OUTROT90 |
-		  S5P_CITRGFMT_FLIP_180);
-
-	flip = readl(dev->regs + S5P_MSCTRL);
-	flip &= ~S5P_MSCTRL_FLIP_MASK;
+		 S5P_CITRGFMT_FLIP_180);
 
 	/*
 	 * The input and output rotator cannot work simultaneously.
@@ -95,26 +98,22 @@
 	 * in direct fifo output mode.
 	 */
 	if (ctx->rotation == 90 || ctx->rotation == 270) {
-		if (ctx->out_path == FIMC_LCDFIFO) {
-			cfg |= S5P_CITRGFMT_INROT90;
-			if (ctx->rotation == 270)
-				flip |= S5P_MSCTRL_FLIP_180;
-		} else {
-			cfg |= S5P_CITRGFMT_OUTROT90;
-			if (ctx->rotation == 270)
-				cfg |= S5P_CITRGFMT_FLIP_180;
-		}
-	} else if (ctx->rotation == 180) {
 		if (ctx->out_path == FIMC_LCDFIFO)
-			flip |= S5P_MSCTRL_FLIP_180;
+			cfg |= S5P_CITRGFMT_INROT90;
 		else
-			cfg |= S5P_CITRGFMT_FLIP_180;
+			cfg |= S5P_CITRGFMT_OUTROT90;
 	}
-	if (ctx->rotation == 180 || ctx->rotation == 270)
-		writel(flip, dev->regs + S5P_MSCTRL);
 
-	cfg |= fimc_hw_get_target_flip(ctx->flip);
-	writel(cfg, dev->regs + S5P_CITRGFMT);
+	if (ctx->out_path == FIMC_DMA) {
+		cfg |= fimc_hw_get_target_flip(ctx);
+		writel(cfg, dev->regs + S5P_CITRGFMT);
+	} else {
+		/* LCD FIFO path */
+		flip = readl(dev->regs + S5P_MSCTRL);
+		flip &= ~S5P_MSCTRL_FLIP_MASK;
+		flip |= fimc_hw_get_in_flip(ctx);
+		writel(flip, dev->regs + S5P_MSCTRL);
+	}
 }
 
 void fimc_hw_set_target_format(struct fimc_ctx *ctx)
@@ -131,19 +130,14 @@
 		  S5P_CITRGFMT_VSIZE_MASK);
 
 	switch (frame->fmt->color) {
-	case S5P_FIMC_RGB565:
-	case S5P_FIMC_RGB666:
-	case S5P_FIMC_RGB888:
+	case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
 		cfg |= S5P_CITRGFMT_RGB;
 		break;
 	case S5P_FIMC_YCBCR420:
 		cfg |= S5P_CITRGFMT_YCBCR420;
 		break;
-	case S5P_FIMC_YCBYCR422:
-	case S5P_FIMC_YCRYCB422:
-	case S5P_FIMC_CBYCRY422:
-	case S5P_FIMC_CRYCBY422:
-		if (frame->fmt->planes_cnt == 1)
+	case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
+		if (frame->fmt->colplanes == 1)
 			cfg |= S5P_CITRGFMT_YCBCR422_1P;
 		else
 			cfg |= S5P_CITRGFMT_YCBCR422;
@@ -219,11 +213,11 @@
 	cfg &= ~(S5P_CIOCTRL_ORDER2P_MASK | S5P_CIOCTRL_ORDER422_MASK |
 		 S5P_CIOCTRL_YCBCR_PLANE_MASK);
 
-	if (frame->fmt->planes_cnt == 1)
+	if (frame->fmt->colplanes == 1)
 		cfg |= ctx->out_order_1p;
-	else if (frame->fmt->planes_cnt == 2)
+	else if (frame->fmt->colplanes == 2)
 		cfg |= ctx->out_order_2p | S5P_CIOCTRL_YCBCR_2PLANE;
-	else if (frame->fmt->planes_cnt == 3)
+	else if (frame->fmt->colplanes == 3)
 		cfg |= S5P_CIOCTRL_YCBCR_3PLANE;
 
 	writel(cfg, dev->regs + S5P_CIOCTRL);
@@ -249,7 +243,7 @@
 	writel(cfg, dev->regs + S5P_CIOCTRL);
 }
 
-static void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
+void fimc_hw_set_prescaler(struct fimc_ctx *ctx)
 {
 	struct fimc_dev *dev =  ctx->fimc_dev;
 	struct fimc_scaler *sc = &ctx->scaler;
@@ -267,7 +261,7 @@
 	writel(cfg, dev->regs + S5P_CISCPREDST);
 }
 
-void fimc_hw_set_scaler(struct fimc_ctx *ctx)
+static void fimc_hw_set_scaler(struct fimc_ctx *ctx)
 {
 	struct fimc_dev *dev = ctx->fimc_dev;
 	struct fimc_scaler *sc = &ctx->scaler;
@@ -275,8 +269,6 @@
 	struct fimc_frame *dst_frame = &ctx->d_frame;
 	u32 cfg = 0;
 
-	fimc_hw_set_prescaler(ctx);
-
 	if (!(ctx->flags & FIMC_COLOR_RANGE_NARROW))
 		cfg |= (S5P_CISCCTRL_CSCR2Y_WIDE | S5P_CISCCTRL_CSCY2R_WIDE);
 
@@ -316,13 +308,42 @@
 			cfg |= S5P_CISCCTRL_INTERLACE;
 	}
 
+	writel(cfg, dev->regs + S5P_CISCCTRL);
+}
+
+void fimc_hw_set_mainscaler(struct fimc_ctx *ctx)
+{
+	struct fimc_dev *dev = ctx->fimc_dev;
+	struct samsung_fimc_variant *variant = dev->variant;
+	struct fimc_scaler *sc = &ctx->scaler;
+	u32 cfg;
+
 	dbg("main_hratio= 0x%X  main_vratio= 0x%X",
 		sc->main_hratio, sc->main_vratio);
 
-	cfg |= S5P_CISCCTRL_SC_HORRATIO(sc->main_hratio);
-	cfg |= S5P_CISCCTRL_SC_VERRATIO(sc->main_vratio);
+	fimc_hw_set_scaler(ctx);
 
-	writel(cfg, dev->regs + S5P_CISCCTRL);
+	cfg = readl(dev->regs + S5P_CISCCTRL);
+
+	if (variant->has_mainscaler_ext) {
+		cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
+		cfg |= S5P_CISCCTRL_MHRATIO_EXT(sc->main_hratio);
+		cfg |= S5P_CISCCTRL_MVRATIO_EXT(sc->main_vratio);
+		writel(cfg, dev->regs + S5P_CISCCTRL);
+
+		cfg = readl(dev->regs + S5P_CIEXTEN);
+
+		cfg &= ~(S5P_CIEXTEN_MVRATIO_EXT_MASK |
+			 S5P_CIEXTEN_MHRATIO_EXT_MASK);
+		cfg |= S5P_CIEXTEN_MHRATIO_EXT(sc->main_hratio);
+		cfg |= S5P_CIEXTEN_MVRATIO_EXT(sc->main_vratio);
+		writel(cfg, dev->regs + S5P_CIEXTEN);
+	} else {
+		cfg &= ~(S5P_CISCCTRL_MHRATIO_MASK | S5P_CISCCTRL_MVRATIO_MASK);
+		cfg |= S5P_CISCCTRL_MHRATIO(sc->main_hratio);
+		cfg |= S5P_CISCCTRL_MVRATIO(sc->main_vratio);
+		writel(cfg, dev->regs + S5P_CISCCTRL);
+	}
 }
 
 void fimc_hw_en_capture(struct fimc_ctx *ctx)
@@ -335,7 +356,7 @@
 		/* one shot mode */
 		cfg |= S5P_CIIMGCPT_CPT_FREN_ENABLE | S5P_CIIMGCPT_IMGCPTEN;
 	} else {
-		/* Continous frame capture mode (freerun). */
+		/* Continuous frame capture mode (freerun). */
 		cfg &= ~(S5P_CIIMGCPT_CPT_FREN_ENABLE |
 			 S5P_CIIMGCPT_CPT_FRMOD_CNT);
 		cfg |= S5P_CIIMGCPT_IMGCPTEN;
@@ -410,41 +431,37 @@
 
 	/* Set the input DMA to process single frame only. */
 	cfg = readl(dev->regs + S5P_MSCTRL);
-	cfg &= ~(S5P_MSCTRL_FLIP_MASK
-		| S5P_MSCTRL_INFORMAT_MASK
+	cfg &= ~(S5P_MSCTRL_INFORMAT_MASK
 		| S5P_MSCTRL_IN_BURST_COUNT_MASK
 		| S5P_MSCTRL_INPUT_MASK
 		| S5P_MSCTRL_C_INT_IN_MASK
 		| S5P_MSCTRL_2P_IN_ORDER_MASK);
 
-	cfg |= (S5P_MSCTRL_FRAME_COUNT(1) | S5P_MSCTRL_INPUT_MEMORY);
+	cfg |= (S5P_MSCTRL_IN_BURST_COUNT(4)
+		| S5P_MSCTRL_INPUT_MEMORY
+		| S5P_MSCTRL_FIFO_CTRL_FULL);
 
 	switch (frame->fmt->color) {
-	case S5P_FIMC_RGB565:
-	case S5P_FIMC_RGB666:
-	case S5P_FIMC_RGB888:
+	case S5P_FIMC_RGB565...S5P_FIMC_RGB888:
 		cfg |= S5P_MSCTRL_INFORMAT_RGB;
 		break;
 	case S5P_FIMC_YCBCR420:
 		cfg |= S5P_MSCTRL_INFORMAT_YCBCR420;
 
-		if (frame->fmt->planes_cnt == 2)
+		if (frame->fmt->colplanes == 2)
 			cfg |= ctx->in_order_2p | S5P_MSCTRL_C_INT_IN_2PLANE;
 		else
 			cfg |= S5P_MSCTRL_C_INT_IN_3PLANE;
 
 		break;
-	case S5P_FIMC_YCBYCR422:
-	case S5P_FIMC_YCRYCB422:
-	case S5P_FIMC_CBYCRY422:
-	case S5P_FIMC_CRYCBY422:
-		if (frame->fmt->planes_cnt == 1) {
+	case S5P_FIMC_YCBYCR422...S5P_FIMC_CRYCBY422:
+		if (frame->fmt->colplanes == 1) {
 			cfg |= ctx->in_order_1p
 				| S5P_MSCTRL_INFORMAT_YCBCR422_1P;
 		} else {
 			cfg |= S5P_MSCTRL_INFORMAT_YCBCR422;
 
-			if (frame->fmt->planes_cnt == 2)
+			if (frame->fmt->colplanes == 2)
 				cfg |= ctx->in_order_2p
 					| S5P_MSCTRL_C_INT_IN_2PLANE;
 			else
@@ -455,13 +472,6 @@
 		break;
 	}
 
-	/*
-	 * Input DMA flip mode (and rotation).
-	 * Do not allow simultaneous rotation and flipping.
-	 */
-	if (!ctx->rotation && ctx->out_path == FIMC_LCDFIFO)
-		cfg |= fimc_hw_get_in_flip(ctx->flip);
-
 	writel(cfg, dev->regs + S5P_MSCTRL);
 
 	/* Input/output DMA linear/tiled mode. */
@@ -532,7 +542,7 @@
 }
 
 int fimc_hw_set_camera_polarity(struct fimc_dev *fimc,
-				struct s3c_fimc_isp_info *cam)
+				struct s5p_fimc_isp_info *cam)
 {
 	u32 cfg = readl(fimc->regs + S5P_CIGCTRL);
 
@@ -557,41 +567,46 @@
 }
 
 int fimc_hw_set_camera_source(struct fimc_dev *fimc,
-			      struct s3c_fimc_isp_info *cam)
+			      struct s5p_fimc_isp_info *cam)
 {
 	struct fimc_frame *f = &fimc->vid_cap.ctx->s_frame;
 	u32 cfg = 0;
+	u32 bus_width;
+	int i;
+
+	static const struct {
+		u32 pixelcode;
+		u32 cisrcfmt;
+		u16 bus_width;
+	} pix_desc[] = {
+		{ V4L2_MBUS_FMT_YUYV8_2X8, S5P_CISRCFMT_ORDER422_YCBYCR, 8 },
+		{ V4L2_MBUS_FMT_YVYU8_2X8, S5P_CISRCFMT_ORDER422_YCRYCB, 8 },
+		{ V4L2_MBUS_FMT_VYUY8_2X8, S5P_CISRCFMT_ORDER422_CRYCBY, 8 },
+		{ V4L2_MBUS_FMT_UYVY8_2X8, S5P_CISRCFMT_ORDER422_CBYCRY, 8 },
+		/* TODO: Add pixel codes for 16-bit bus width */
+	};
 
 	if (cam->bus_type == FIMC_ITU_601 || cam->bus_type == FIMC_ITU_656) {
+		for (i = 0; i < ARRAY_SIZE(pix_desc); i++) {
+			if (fimc->vid_cap.fmt.code == pix_desc[i].pixelcode) {
+				cfg = pix_desc[i].cisrcfmt;
+				bus_width = pix_desc[i].bus_width;
+				break;
+			}
+		}
 
-		switch (fimc->vid_cap.fmt.code) {
-		case V4L2_MBUS_FMT_YUYV8_2X8:
-			cfg = S5P_CISRCFMT_ORDER422_YCBYCR;
-			break;
-		case V4L2_MBUS_FMT_YVYU8_2X8:
-			cfg = S5P_CISRCFMT_ORDER422_YCRYCB;
-			break;
-		case V4L2_MBUS_FMT_VYUY8_2X8:
-			cfg = S5P_CISRCFMT_ORDER422_CRYCBY;
-			break;
-		case V4L2_MBUS_FMT_UYVY8_2X8:
-			cfg = S5P_CISRCFMT_ORDER422_CBYCRY;
-			break;
-		default:
-			err("camera image format not supported: %d",
-			    fimc->vid_cap.fmt.code);
+		if (i == ARRAY_SIZE(pix_desc)) {
+			v4l2_err(&fimc->vid_cap.v4l2_dev,
+				 "Camera color format not supported: %d\n",
+				 fimc->vid_cap.fmt.code);
 			return -EINVAL;
 		}
 
 		if (cam->bus_type == FIMC_ITU_601) {
-			if (cam->bus_width == 8) {
+			if (bus_width == 8)
 				cfg |= S5P_CISRCFMT_ITU601_8BIT;
-			} else if (cam->bus_width == 16) {
+			else if (bus_width == 16)
 				cfg |= S5P_CISRCFMT_ITU601_16BIT;
-			} else {
-				err("invalid bus width: %d", cam->bus_width);
-				return -EINVAL;
-			}
 		} /* else defaults to ITU-R BT.656 8-bit */
 	}
 
@@ -624,7 +639,7 @@
 }
 
 int fimc_hw_set_camera_type(struct fimc_dev *fimc,
-			    struct s3c_fimc_isp_info *cam)
+			    struct s5p_fimc_isp_info *cam)
 {
 	u32 cfg, tmp;
 	struct fimc_vid_cap *vid_cap = &fimc->vid_cap;
@@ -650,10 +665,12 @@
 			    vid_cap->fmt.code);
 			return -EINVAL;
 		}
-		writel(tmp | (0x1 << 8), fimc->regs + S5P_CSIIMGFMT);
+		tmp |= (cam->csi_data_align == 32) << 8;
+
+		writel(tmp, fimc->regs + S5P_CSIIMGFMT);
 
 	} else if (cam->bus_type == FIMC_ITU_601 ||
-		  cam->bus_type == FIMC_ITU_656) {
+		   cam->bus_type == FIMC_ITU_656) {
 		if (cam->mux_id == 0) /* ITU-A, ITU-B: 0, 1 */
 			cfg |= S5P_CIGCTRL_SELCAM_ITU_A;
 	} else if (cam->bus_type == FIMC_LCD_WB) {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/regs-fimc.h linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/regs-fimc.h
--- linux-libre-2.6.38-gnu/drivers/media/video/s5p-fimc/regs-fimc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/s5p-fimc/regs-fimc.h	2011-05-19 00:06:34.000000000 -0400
@@ -98,8 +98,8 @@
 #define S5P_CIOCTRL			0x4c
 #define S5P_CIOCTRL_ORDER422_MASK	(3 << 0)
 #define S5P_CIOCTRL_ORDER422_CRYCBY	(0 << 0)
-#define S5P_CIOCTRL_ORDER422_YCRYCB	(1 << 0)
-#define S5P_CIOCTRL_ORDER422_CBYCRY	(2 << 0)
+#define S5P_CIOCTRL_ORDER422_CBYCRY	(1 << 0)
+#define S5P_CIOCTRL_ORDER422_YCRYCB	(2 << 0)
 #define S5P_CIOCTRL_ORDER422_YCBYCR	(3 << 0)
 #define S5P_CIOCTRL_LASTIRQ_ENABLE	(1 << 2)
 #define S5P_CIOCTRL_YCBCR_3PLANE	(0 << 3)
@@ -139,8 +139,12 @@
 #define S5P_CISCCTRL_OUTRGB_FMT_MASK	(3 << 11)
 #define S5P_CISCCTRL_RGB_EXT		(1 << 10)
 #define S5P_CISCCTRL_ONE2ONE		(1 << 9)
-#define S5P_CISCCTRL_SC_HORRATIO(x)	((x) << 16)
-#define S5P_CISCCTRL_SC_VERRATIO(x)	((x) << 0)
+#define S5P_CISCCTRL_MHRATIO(x)		((x) << 16)
+#define S5P_CISCCTRL_MVRATIO(x)		((x) << 0)
+#define S5P_CISCCTRL_MHRATIO_MASK	(0x1ff << 16)
+#define S5P_CISCCTRL_MVRATIO_MASK	(0x1ff << 0)
+#define S5P_CISCCTRL_MHRATIO_EXT(x)	(((x) >> 6) << 16)
+#define S5P_CISCCTRL_MVRATIO_EXT(x)	(((x) >> 6) << 0)
 
 /* Target area */
 #define S5P_CITAREA			0x5c
@@ -210,7 +214,7 @@
 
 /* Input DMA control */
 #define S5P_MSCTRL			0xfc
-#define S5P_MSCTRL_IN_BURST_COUNT_MASK	(3 << 24)
+#define S5P_MSCTRL_IN_BURST_COUNT_MASK	(0xF << 24)
 #define S5P_MSCTRL_2P_IN_ORDER_MASK	(3 << 16)
 #define S5P_MSCTRL_2P_IN_ORDER_SHIFT	16
 #define S5P_MSCTRL_C_INT_IN_3PLANE	(0 << 15)
@@ -222,11 +226,12 @@
 #define S5P_MSCTRL_FLIP_X_MIRROR	(1 << 13)
 #define S5P_MSCTRL_FLIP_Y_MIRROR	(2 << 13)
 #define S5P_MSCTRL_FLIP_180		(3 << 13)
+#define S5P_MSCTRL_FIFO_CTRL_FULL	(1 << 12)
 #define S5P_MSCTRL_ORDER422_SHIFT	4
-#define S5P_MSCTRL_ORDER422_CRYCBY	(0 << 4)
-#define S5P_MSCTRL_ORDER422_YCRYCB	(1 << 4)
-#define S5P_MSCTRL_ORDER422_CBYCRY	(2 << 4)
-#define S5P_MSCTRL_ORDER422_YCBYCR	(3 << 4)
+#define S5P_MSCTRL_ORDER422_YCBYCR	(0 << 4)
+#define S5P_MSCTRL_ORDER422_CBYCRY	(1 << 4)
+#define S5P_MSCTRL_ORDER422_YCRYCB	(2 << 4)
+#define S5P_MSCTRL_ORDER422_CRYCBY	(3 << 4)
 #define S5P_MSCTRL_ORDER422_MASK	(3 << 4)
 #define S5P_MSCTRL_INPUT_EXTCAM		(0 << 3)
 #define S5P_MSCTRL_INPUT_MEMORY		(1 << 3)
@@ -237,7 +242,7 @@
 #define S5P_MSCTRL_INFORMAT_RGB		(3 << 1)
 #define S5P_MSCTRL_INFORMAT_MASK	(3 << 1)
 #define S5P_MSCTRL_ENVID		(1 << 0)
-#define S5P_MSCTRL_FRAME_COUNT(x)	((x) << 24)
+#define S5P_MSCTRL_IN_BURST_COUNT(x)	((x) << 24)
 
 /* Output DMA Y/Cb/Cr offset */
 #define S5P_CIOYOFF			0x168
@@ -263,6 +268,10 @@
 
 /* Real output DMA image size (extension register) */
 #define S5P_CIEXTEN			0x188
+#define S5P_CIEXTEN_MHRATIO_EXT(x)	(((x) & 0x3f) << 10)
+#define S5P_CIEXTEN_MVRATIO_EXT(x)	((x) & 0x3f)
+#define S5P_CIEXTEN_MHRATIO_EXT_MASK	(0x3f << 10)
+#define S5P_CIEXTEN_MVRATIO_EXT_MASK	0x3f
 
 #define S5P_CIDMAPARAM			0x18c
 #define S5P_CIDMAPARAM_R_LINEAR		(0 << 29)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7110.c linux-libre-2.6.39-gnu/drivers/media/video/saa7110.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7110.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7110.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 MODULE_DESCRIPTION("Philips SAA7110 video decoder driver");
 MODULE_AUTHOR("Pauline Middelink");
@@ -53,15 +54,12 @@
 
 struct saa7110 {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	u8 reg[SAA7110_NR_REG];
 
 	v4l2_std_id norm;
 	int input;
 	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 
 	wait_queue_head_t wq;
 };
@@ -71,6 +69,11 @@
 	return container_of(sd, struct saa7110, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct saa7110, hdl)->sd;
+}
+
 /* ----------------------------------------------------------------------- */
 /* I2C support functions						   */
 /* ----------------------------------------------------------------------- */
@@ -326,73 +329,22 @@
 	return 0;
 }
 
-static int saa7110_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 128);
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qc, 0, 127, 1, 64);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int saa7110_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct saa7110 *decoder = to_saa7110(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = decoder->bright;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = decoder->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = decoder->sat;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = decoder->hue;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int saa7110_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int saa7110_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct saa7110 *decoder = to_saa7110(sd);
+	struct v4l2_subdev *sd = to_sd(ctrl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		if (decoder->bright != ctrl->value) {
-			decoder->bright = ctrl->value;
-			saa7110_write(sd, 0x19, decoder->bright);
-		}
+		saa7110_write(sd, 0x19, ctrl->val);
 		break;
 	case V4L2_CID_CONTRAST:
-		if (decoder->contrast != ctrl->value) {
-			decoder->contrast = ctrl->value;
-			saa7110_write(sd, 0x13, decoder->contrast);
-		}
+		saa7110_write(sd, 0x13, ctrl->val);
 		break;
 	case V4L2_CID_SATURATION:
-		if (decoder->sat != ctrl->value) {
-			decoder->sat = ctrl->value;
-			saa7110_write(sd, 0x12, decoder->sat);
-		}
+		saa7110_write(sd, 0x12, ctrl->val);
 		break;
 	case V4L2_CID_HUE:
-		if (decoder->hue != ctrl->value) {
-			decoder->hue = ctrl->value;
-			saa7110_write(sd, 0x07, decoder->hue);
-		}
+		saa7110_write(sd, 0x07, ctrl->val);
 		break;
 	default:
 		return -EINVAL;
@@ -409,11 +361,19 @@
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops saa7110_ctrl_ops = {
+	.s_ctrl = saa7110_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops saa7110_core_ops = {
 	.g_chip_ident = saa7110_g_chip_ident,
-	.g_ctrl = saa7110_g_ctrl,
-	.s_ctrl = saa7110_s_ctrl,
-	.queryctrl = saa7110_queryctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 	.s_std = saa7110_s_std,
 };
 
@@ -454,10 +414,25 @@
 	decoder->norm = V4L2_STD_PAL;
 	decoder->input = 0;
 	decoder->enable = 1;
-	decoder->bright = 32768;
-	decoder->contrast = 32768;
-	decoder->hue = 32768;
-	decoder->sat = 32768;
+	v4l2_ctrl_handler_init(&decoder->hdl, 2);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 127, 1, 64);
+	v4l2_ctrl_new_std(&decoder->hdl, &saa7110_ctrl_ops,
+		V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+
 	init_waitqueue_head(&decoder->wq);
 
 	rv = saa7110_write_block(sd, initseq, sizeof(initseq));
@@ -490,9 +465,11 @@
 static int saa7110_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct saa7110 *decoder = to_saa7110(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_saa7110(sd));
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7134/Kconfig linux-libre-2.6.39-gnu/drivers/media/video/saa7134/Kconfig
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7134/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7134/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 	bool "Philips SAA7134 Remote Controller support"
 	depends on RC_CORE
 	depends on VIDEO_SAA7134
+	depends on !(RC_CORE=m && VIDEO_SAA7134=y)
 	default y
 	---help---
 	  Enables Remote Controller support on saa7134 driver.
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-cards.c linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-cards.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-cards.c	2012-03-24 01:00:57.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-cards.c	2012-03-24 03:26:51.000000000 -0400
@@ -3620,6 +3620,38 @@
 			.amux = 0,
 		},
 	},
+	[SAA7134_BOARD_ENCORE_ENLTV_FM3] = {
+		.name           = "Encore ENLTV-FM 3",
+		.audio_clock    = 0x02187de7,
+		.tuner_type     = TUNER_TENA_TNF_5337,
+		.radio_type     = TUNER_TEA5767,
+		.tuner_addr	= 0x61,
+		.radio_addr	= 0x60,
+		.inputs         = { {
+			.name = name_tv,
+			.vmux = 1,
+			.amux = LINE2,
+			.tv   = 1,
+		}, {
+			.name = name_comp1,
+			.vmux = 3,
+			.amux = LINE1,
+		}, {
+			.name = name_svideo,
+			.vmux = 8,
+			.amux = LINE1,
+		} },
+		.radio = {
+			.name = name_radio,
+			.vmux = 1,
+			.amux = LINE1,
+		},
+		.mute = {
+			.name = name_mute,
+			.amux = LINE1,
+			.gpio = 0x43000,
+		},
+	},
 	[SAA7134_BOARD_CINERGY_HT_PCI] = {
 		.name           = "Terratec Cinergy HT PCI",
 		.audio_clock    = 0x00187de7,
@@ -6387,6 +6419,12 @@
 		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM53,
 	}, {
 		.vendor       = PCI_VENDOR_ID_PHILIPS,
+		.device       = PCI_DEVICE_ID_PHILIPS_SAA7134,
+		.subvendor    = 0x1a7f,
+		.subdevice    = 0x2108,
+		.driver_data  = SAA7134_BOARD_ENCORE_ENLTV_FM3,
+	}, {
+		.vendor       = PCI_VENDOR_ID_PHILIPS,
 		.device       = PCI_DEVICE_ID_PHILIPS_SAA7133,
 		.subvendor    = 0x153b,
 		.subdevice    = 0x1175,
@@ -7102,6 +7140,7 @@
 	case SAA7134_BOARD_ENCORE_ENLTV:
 	case SAA7134_BOARD_ENCORE_ENLTV_FM:
 	case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM3:
 	case SAA7134_BOARD_10MOONSTVMASTER3:
 	case SAA7134_BOARD_BEHOLD_401:
 	case SAA7134_BOARD_BEHOLD_403:
@@ -7294,9 +7333,7 @@
 static void saa7134_tuner_setup(struct saa7134_dev *dev)
 {
 	struct tuner_setup tun_setup;
-	unsigned int mode_mask = T_RADIO     |
-				 T_ANALOG_TV |
-				 T_DIGITAL_TV;
+	unsigned int mode_mask = T_RADIO | T_ANALOG_TV;
 
 	memset(&tun_setup, 0, sizeof(tun_setup));
 	tun_setup.tuner_callback = saa7134_tuner_callback;
@@ -7423,7 +7460,7 @@
 				dev->tuner_type = TUNER_PHILIPS_FM1216ME_MK3;
 				break;
 			default:
-				printk(KERN_ERR "%s Cant determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+				printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
 			}
 		} else if ((data[1] != 0) && (data[1] != 0xff)) {
 			/* new config structure */
@@ -7443,7 +7480,7 @@
 					printk(KERN_INFO "%s Board has DVB-T\n", dev->name);
 				break;
 			default:
-				printk(KERN_ERR "%s Cant determine tuner type %x from EEPROM\n", dev->name, tuner_t);
+				printk(KERN_ERR "%s Can't determine tuner type %x from EEPROM\n", dev->name, tuner_t);
 			}
 		} else {
 			printk(KERN_ERR "%s unexpected config structure\n", dev->name);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-core.c linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -752,19 +752,28 @@
 	return 0;
 }
 
-static void __devinit must_configure_manually(void)
+static void __devinit must_configure_manually(int has_eeprom)
 {
 	unsigned int i,p;
 
-	printk(KERN_WARNING
-	       "saa7134: <rant>\n"
-	       "saa7134:  Congratulations!  Your TV card vendor saved a few\n"
-	       "saa7134:  cents for a eeprom, thus your pci board has no\n"
-	       "saa7134:  subsystem ID and I can't identify it automatically\n"
-	       "saa7134: </rant>\n"
-	       "saa7134: I feel better now.  Ok, here are the good news:\n"
-	       "saa7134: You can use the card=<nr> insmod option to specify\n"
-	       "saa7134: which board do you have.  The list:\n");
+	if (!has_eeprom)
+		printk(KERN_WARNING
+		       "saa7134: <rant>\n"
+		       "saa7134:  Congratulations!  Your TV card vendor saved a few\n"
+		       "saa7134:  cents for a eeprom, thus your pci board has no\n"
+		       "saa7134:  subsystem ID and I can't identify it automatically\n"
+		       "saa7134: </rant>\n"
+		       "saa7134: I feel better now.  Ok, here are the good news:\n"
+		       "saa7134: You can use the card=<nr> insmod option to specify\n"
+		       "saa7134: which board do you have.  The list:\n");
+	else
+		printk(KERN_WARNING
+		       "saa7134: Board is currently unknown. You might try to use the card=<nr>\n"
+		       "saa7134: insmod option to specify which board do you have, but this is\n"
+		       "saa7134: somewhat risky, as might damage your card. It is better to ask\n"
+		       "saa7134: for support at linux-media@vger.kernel.org.\n"
+		       "saa7134: The supported cards are:\n");
+
 	for (i = 0; i < saa7134_bcount; i++) {
 		printk(KERN_WARNING "saa7134:   card=%d -> %-40.40s",
 		       i,saa7134_boards[i].name);
@@ -936,8 +945,10 @@
 	if (card[dev->nr] >= 0 &&
 	    card[dev->nr] < saa7134_bcount)
 		dev->board = card[dev->nr];
-	if (SAA7134_BOARD_NOAUTO == dev->board) {
-		must_configure_manually();
+	if (SAA7134_BOARD_UNKNOWN == dev->board)
+		must_configure_manually(0);
+	else if (SAA7134_BOARD_NOAUTO == dev->board) {
+		must_configure_manually(1);
 		dev->board = SAA7134_BOARD_UNKNOWN;
 	}
 	dev->autodetected = card[dev->nr] != dev->board;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-empress.c linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-empress.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-empress.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-empress.c	2011-05-19 00:06:34.000000000 -0400
@@ -373,6 +373,10 @@
 	static const u32 mpeg_ctrls[] = {
 		V4L2_CID_MPEG_CLASS,
 		V4L2_CID_MPEG_STREAM_TYPE,
+		V4L2_CID_MPEG_STREAM_PID_PMT,
+		V4L2_CID_MPEG_STREAM_PID_AUDIO,
+		V4L2_CID_MPEG_STREAM_PID_VIDEO,
+		V4L2_CID_MPEG_STREAM_PID_PCR,
 		V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ,
 		V4L2_CID_MPEG_AUDIO_ENCODING,
 		V4L2_CID_MPEG_AUDIO_L2_BITRATE,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134.h linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134.h
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134.h	2011-05-19 00:06:34.000000000 -0400
@@ -327,6 +327,7 @@
 #define SAA7134_BOARD_TECHNOTREND_BUDGET_T3000 181
 #define SAA7134_BOARD_KWORLD_PCI_SBTVD_FULLSEG 182
 #define SAA7134_BOARD_VIDEOMATE_M1F         183
+#define SAA7134_BOARD_ENCORE_ENLTV_FM3      184
 
 #define SAA7134_MAXBOARDS 32
 #define SAA7134_INPUT_MAX 8
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-input.c linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-input.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7134/saa7134-input.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7134/saa7134-input.c	2011-05-19 00:06:34.000000000 -0400
@@ -414,6 +414,41 @@
 	if (ir->running)
 		return 0;
 
+	/* Moved here from saa7134_input_init1() because the latter
+	 * is not called on device resume */
+	switch (dev->board) {
+	case SAA7134_BOARD_MD2819:
+	case SAA7134_BOARD_KWORLD_VSTREAM_XPERT:
+	case SAA7134_BOARD_AVERMEDIA_305:
+	case SAA7134_BOARD_AVERMEDIA_307:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_305:
+	case SAA7134_BOARD_AVERMEDIA_STUDIO_505:
+	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:
+		/* Without this we won't receive key up events */
+		saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
+		saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_777:
+	case SAA7134_BOARD_AVERMEDIA_A16AR:
+		/* Without this we won't receive key up events */
+		saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
+		saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+		break;
+	case SAA7134_BOARD_AVERMEDIA_A16D:
+		/* Without this we won't receive key up events */
+		saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
+		saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+		break;
+	case SAA7134_BOARD_GOTVIEW_7135:
+		saa_setb(SAA7134_GPIO_GPMODE1, 0x80);
+		break;
+	}
+
 	ir->running = true;
 	ir->active = false;
 
@@ -548,9 +583,7 @@
 		mask_keycode = 0x0007C8;
 		mask_keydown = 0x000010;
 		polling      = 50; // ms
-		/* Set GPIO pin2 to high to enable the IR controller */
-		saa_setb(SAA7134_GPIO_GPMODE0, 0x4);
-		saa_setb(SAA7134_GPIO_GPSTATUS0, 0x4);
+		/* GPIO stuff moved to __saa7134_ir_start() */
 		break;
 	case SAA7134_BOARD_AVERMEDIA_M135A:
 		ir_codes     = RC_MAP_AVERMEDIA_M135A;
@@ -572,18 +605,14 @@
 		mask_keycode = 0x02F200;
 		mask_keydown = 0x000400;
 		polling      = 50; // ms
-		/* Without this we won't receive key up events */
-		saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
-		saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+		/* GPIO stuff moved to __saa7134_ir_start() */
 		break;
 	case SAA7134_BOARD_AVERMEDIA_A16D:
 		ir_codes     = RC_MAP_AVERMEDIA_A16D;
 		mask_keycode = 0x02F200;
 		mask_keydown = 0x000400;
 		polling      = 50; /* ms */
-		/* Without this we won't receive key up events */
-		saa_setb(SAA7134_GPIO_GPMODE1, 0x1);
-		saa_setb(SAA7134_GPIO_GPSTATUS1, 0x1);
+		/* GPIO stuff moved to __saa7134_ir_start() */
 		break;
 	case SAA7134_BOARD_KWORLD_TERMINATOR:
 		ir_codes     = RC_MAP_PIXELVIEW;
@@ -635,7 +664,7 @@
 		mask_keycode = 0x0003CC;
 		mask_keydown = 0x000010;
 		polling	     = 5; /* ms */
-		saa_setb(SAA7134_GPIO_GPMODE1, 0x80);
+		/* GPIO stuff moved to __saa7134_ir_start() */
 		break;
 	case SAA7134_BOARD_VIDEOMATE_TV_PVR:
 	case SAA7134_BOARD_VIDEOMATE_GOLD_PLUS:
@@ -681,6 +710,7 @@
 		polling      = 50; // ms
 		break;
 	case SAA7134_BOARD_ENCORE_ENLTV_FM53:
+	case SAA7134_BOARD_ENCORE_ENLTV_FM3:
 		ir_codes     = RC_MAP_ENCORE_ENLTV_FM53;
 		mask_keydown = 0x0040000;	/* Enable GPIO18 line on both edges */
 		mask_keyup   = 0x0040000;
@@ -863,7 +893,7 @@
 	case SAA7134_BOARD_HAUPPAUGE_HVR1110:
 		dev->init_data.name = "HVR 1110";
 		dev->init_data.get_key = get_key_hvr1110;
-		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE_NEW;
+		dev->init_data.ir_codes = RC_MAP_HAUPPAUGE;
 		info.addr = 0x71;
 		break;
 	case SAA7134_BOARD_BEHOLD_607FM_MK3:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-api.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-api.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-api.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-api.c	2011-05-19 00:06:34.000000000 -0400
@@ -743,7 +743,7 @@
 int saa7164_api_initialize_dif(struct saa7164_port *port)
 {
 	struct saa7164_dev *dev = port->dev;
-	struct saa7164_port *p = 0;
+	struct saa7164_port *p = NULL;
 	int ret = -EINVAL;
 	u32 std = 0;
 
@@ -926,9 +926,9 @@
 
 int saa7164_api_dump_subdevs(struct saa7164_dev *dev, u8 *buf, int len)
 {
-	struct saa7164_port *tsport = 0;
-	struct saa7164_port *encport = 0;
-	struct saa7164_port *vbiport = 0;
+	struct saa7164_port *tsport = NULL;
+	struct saa7164_port *encport = NULL;
+	struct saa7164_port *vbiport = NULL;
 	u32 idx, next_offset;
 	int i;
 	struct tmComResDescrHeader *hdr, *t;
@@ -1340,7 +1340,7 @@
 
 	/* Allocate enough storage for all of the descs */
 	buf = kzalloc(buflen, GFP_KERNEL);
-	if (buf == NULL)
+	if (!buf)
 		return SAA_ERR_NO_RESOURCES;
 
 	/* Retrieve them */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-buffer.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-buffer.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-buffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-buffer.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 	u32 len)
 {
 	struct tmHWStreamParameters *params = &port->hw_streamingparams;
-	struct saa7164_buffer *buf = 0;
+	struct saa7164_buffer *buf = NULL;
 	struct saa7164_dev *dev = port->dev;
 	int i;
 
@@ -103,7 +103,7 @@
 	}
 
 	buf = kzalloc(sizeof(struct saa7164_buffer), GFP_KERNEL);
-	if (buf == NULL) {
+	if (!buf) {
 		log_warn("%s() SAA_ERR_NO_RESOURCES\n", __func__);
 		goto ret;
 	}
@@ -157,7 +157,7 @@
 fail1:
 	kfree(buf);
 
-	buf = 0;
+	buf = NULL;
 ret:
 	return buf;
 }
@@ -289,14 +289,14 @@
 	struct saa7164_user_buffer *buf;
 
 	buf = kzalloc(sizeof(struct saa7164_user_buffer), GFP_KERNEL);
-	if (buf == 0)
-		return 0;
+	if (!buf)
+		return NULL;
 
 	buf->data = kzalloc(len, GFP_KERNEL);
 
-	if (buf->data == 0) {
+	if (!buf->data) {
 		kfree(buf);
-		return 0;
+		return NULL;
 	}
 
 	buf->actual_size = len;
@@ -315,7 +315,7 @@
 		return;
 
 	kfree(buf->data);
-	buf->data = 0;
+	buf->data = NULL;
 
 	kfree(buf);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-bus.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-bus.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-bus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-bus.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,7 +158,7 @@
 		return SAA_ERR_BAD_PARAMETER;
 	}
 
-	if ((msg->size > 0) && (buf == 0)) {
+	if ((msg->size > 0) && (buf == NULL)) {
 		printk(KERN_ERR "%s() Missing message buffer\n", __func__);
 		return SAA_ERR_BAD_PARAMETER;
 	}
@@ -315,7 +315,7 @@
 
 	saa7164_bus_verify(dev);
 
-	if (msg == 0)
+	if (msg == NULL)
 		return ret;
 
 	if (msg->size > dev->bus.m_wMaxReqSize) {
@@ -324,7 +324,7 @@
 		return ret;
 	}
 
-	if ((peekonly == 0) && (msg->size > 0) && (buf == 0)) {
+	if ((peekonly == 0) && (msg->size > 0) && (buf == NULL)) {
 		printk(KERN_ERR
 			"%s() Missing msg buf, size should be %d bytes\n",
 			__func__, msg->size);
@@ -392,7 +392,7 @@
 
 		printk(KERN_ERR "%s() Unexpected msg miss-match\n", __func__);
 		saa7164_bus_dumpmsg(dev, msg, buf);
-		saa7164_bus_dumpmsg(dev, &msg_tmp, 0);
+		saa7164_bus_dumpmsg(dev, &msg_tmp, NULL);
 		ret = SAA_ERR_INVALID_COMMAND;
 		goto out;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-cmd.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-cmd.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-cmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,7 @@
 {
 	int ret = SAA_OK, i = 0;
 	u32 timeout;
-	wait_queue_head_t *q = 0;
+	wait_queue_head_t *q = NULL;
 	u8 tmp[512];
 	dprintk(DBGLVL_CMD, "%s()\n", __func__);
 
@@ -137,7 +137,7 @@
 	int loop = 1;
 	int ret;
 	u32 timeout;
-	wait_queue_head_t *q = 0;
+	wait_queue_head_t *q = NULL;
 	u8 tmp[512];
 	dprintk(DBGLVL_CMD, "%s()\n", __func__);
 
@@ -257,11 +257,11 @@
 }
 
 /* Wait for a signal event, without holding a mutex. Either return TIMEOUT if
- * the event never occured, or SAA_OK if it was signaled during the wait.
+ * the event never occurred, or SAA_OK if it was signaled during the wait.
  */
 int saa7164_cmd_wait(struct saa7164_dev *dev, u8 seqno)
 {
-	wait_queue_head_t *q = 0;
+	wait_queue_head_t *q = NULL;
 	int ret = SAA_BUS_TIMEOUT;
 	unsigned long stamp;
 	int r;
@@ -357,7 +357,7 @@
 		"sel = 0x%x)\n", __func__, saa7164_unitid_name(dev, id), id,
 		command, controlselector);
 
-	if ((size == 0) || (buf == 0)) {
+	if ((size == 0) || (buf == NULL)) {
 		printk(KERN_ERR "%s() Invalid param\n", __func__);
 		return SAA_ERR_BAD_PARAMETER;
 	}
@@ -538,7 +538,7 @@
 
 			/* Invalid */
 			dprintk(DBGLVL_CMD, "%s() Invalid\n", __func__);
-			ret = saa7164_bus_get(dev, presponse_t, 0, 0);
+			ret = saa7164_bus_get(dev, presponse_t, NULL, 0);
 			if (ret != SAA_OK) {
 				printk(KERN_ERR "get failed\n");
 				return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-core.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -277,8 +277,8 @@
 static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
 {
 	struct saa7164_dev *dev = port->dev;
-	struct saa7164_buffer *buf = 0;
-	struct saa7164_user_buffer *ubuf = 0;
+	struct saa7164_buffer *buf = NULL;
+	struct saa7164_user_buffer *ubuf = NULL;
 	struct list_head *c, *n;
 	int i = 0;
 	u8 __iomem *p;
@@ -649,7 +649,7 @@
 	u32 intid, intstat[INT_SIZE/4];
 	int i, handled = 0, bit;
 
-	if (dev == 0) {
+	if (dev == NULL) {
 		printk(KERN_ERR "%s() No device specified\n", __func__);
 		handled = 0;
 		goto out;
@@ -945,7 +945,7 @@
 
 static int saa7164_port_init(struct saa7164_dev *dev, int portnr)
 {
-	struct saa7164_port *port = 0;
+	struct saa7164_port *port = NULL;
 
 	if ((portnr < 0) || (portnr >= SAA7164_MAX_PORTS))
 		BUG();
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-dvb.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-dvb.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-dvb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-dvb.c	2011-05-19 00:06:34.000000000 -0400
@@ -309,8 +309,8 @@
 
 	port->hw_streamingparams.pitch = 188;
 	port->hw_streamingparams.linethreshold = 0;
-	port->hw_streamingparams.pagetablelistvirt = 0;
-	port->hw_streamingparams.pagetablelistphys = 0;
+	port->hw_streamingparams.pagetablelistvirt = NULL;
+	port->hw_streamingparams.pagetablelistphys = NULL;
 	port->hw_streamingparams.numpagetables = 2 +
 		((SAA7164_TS_NUMBER_OF_LINES * 188) / PAGE_SIZE);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-encoder.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-encoder.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-encoder.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-encoder.c	2011-05-19 00:06:34.000000000 -0400
@@ -152,8 +152,8 @@
 	/* Init and establish defaults */
 	params->bitspersample = 8;
 	params->linethreshold = 0;
-	params->pagetablelistvirt = 0;
-	params->pagetablelistphys = 0;
+	params->pagetablelistvirt = NULL;
+	params->pagetablelistphys = NULL;
 	params->numpagetableentries = port->hwcfg.buffercount;
 
 	/* Allocate the PCI resources, buffers (hard) */
@@ -1108,7 +1108,7 @@
 
 struct saa7164_user_buffer *saa7164_enc_next_buf(struct saa7164_port *port)
 {
-	struct saa7164_user_buffer *ubuf = 0;
+	struct saa7164_user_buffer *ubuf = NULL;
 	struct saa7164_dev *dev = port->dev;
 	u32 crc;
 
@@ -1443,7 +1443,7 @@
 	port->v4l_device = saa7164_encoder_alloc(port,
 		dev->pci, &saa7164_mpeg_template, "mpeg");
 
-	if (port->v4l_device == NULL) {
+	if (!port->v4l_device) {
 		printk(KERN_INFO "%s: can't allocate mpeg device\n",
 			dev->name);
 		result = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-fw.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-fw.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-fw.c	2012-03-24 01:05:31.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-fw.c	2012-03-24 03:29:29.000000000 -0400
@@ -88,7 +88,7 @@
 		"%s(image=%p, size=%d, flags=0x%x, dst=%p, dstsize=0x%x)\n",
 		__func__, src, srcsize, dlflags, dst, dstsize);
 
-	if ((src == 0) || (dst == 0)) {
+	if ((src == NULL) || (dst == NULL)) {
 		ret = -EIO;
 		goto out;
 	}
@@ -444,7 +444,7 @@
 		printk(KERN_INFO " .Reserved = 0x%x\n", hdr->reserved);
 		printk(KERN_INFO " .Version = 0x%x\n", hdr->version);
 
-		/* Retreive bootloader if reqd */
+		/* Retrieve bootloader if reqd */
 		if ((hdr->firmwaresize == 0) && (hdr->bslsize == 0))
 			/* Second bootloader in the firmware file */
 			filesize = hdr->reserved * 16;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-types.h linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-types.h
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-types.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-types.h	2011-05-19 00:06:34.000000000 -0400
@@ -412,7 +412,7 @@
 	u8	StartLine; /* NTSC Start = 10 */
 	u8	EndLine; /* NTSC = 21 */
 	u8	FieldRate; /* 60 for NTSC */
-	u8	bNumLines; /* Unsed - scheduled for removal */
+	u8	bNumLines; /* Unused - scheduled for removal */
 } __attribute__((packed));
 
 struct tmComResProbeCommit {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-vbi.c linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-vbi.c
--- linux-libre-2.6.38-gnu/drivers/media/video/saa7164/saa7164-vbi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/saa7164/saa7164-vbi.c	2011-05-19 00:06:34.000000000 -0400
@@ -123,8 +123,8 @@
 		((params->numberoflines * params->pitch) / PAGE_SIZE);
 	params->bitspersample = 8;
 	params->linethreshold = 0;
-	params->pagetablelistvirt = 0;
-	params->pagetablelistphys = 0;
+	params->pagetablelistvirt = NULL;
+	params->pagetablelistphys = NULL;
 	params->numpagetableentries = port->hwcfg.buffercount;
 
 	/* Allocate the PCI resources, buffers (hard) */
@@ -1054,7 +1054,7 @@
 
 struct saa7164_user_buffer *saa7164_vbi_next_buf(struct saa7164_port *port)
 {
-	struct saa7164_user_buffer *ubuf = 0;
+	struct saa7164_user_buffer *ubuf = NULL;
 	struct saa7164_dev *dev = port->dev;
 	u32 crc;
 
@@ -1334,7 +1334,7 @@
 	port->v4l_device = saa7164_vbi_alloc(port,
 		dev->pci, &saa7164_vbi_template, "vbi");
 
-	if (port->v4l_device == NULL) {
+	if (!port->v4l_device) {
 		printk(KERN_INFO "%s: can't allocate vbi device\n",
 			dev->name);
 		result = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/sh_mobile_ceu_camera.c linux-libre-2.6.39-gnu/drivers/media/video/sh_mobile_ceu_camera.c
--- linux-libre-2.6.38-gnu/drivers/media/video/sh_mobile_ceu_camera.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/sh_mobile_ceu_camera.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 #include <media/v4l2-dev.h>
 #include <media/soc_camera.h>
 #include <media/sh_mobile_ceu.h>
-#include <media/videobuf-dma-contig.h>
+#include <media/videobuf2-dma-contig.h>
 #include <media/v4l2-mediabus.h>
 #include <media/soc_mediabus.h>
 
@@ -87,7 +87,8 @@
 
 /* per video frame buffer */
 struct sh_mobile_ceu_buffer {
-	struct videobuf_buffer vb; /* v4l buffer must be first */
+	struct vb2_buffer vb; /* v4l buffer must be first */
+	struct list_head queue;
 	enum v4l2_mbus_pixelcode code;
 };
 
@@ -99,16 +100,17 @@
 	void __iomem *base;
 	unsigned long video_limit;
 
-	/* lock used to protect videobuf */
-	spinlock_t lock;
+	spinlock_t lock;		/* Protects video buffer lists */
 	struct list_head capture;
-	struct videobuf_buffer *active;
+	struct vb2_buffer *active;
+	struct vb2_alloc_ctx *alloc_ctx;
 
 	struct sh_mobile_ceu_info *pdata;
 
 	u32 cflcr;
 
 	enum v4l2_field field;
+	int sequence;
 
 	unsigned int image_mode:1;
 	unsigned int is_16bit:1;
@@ -133,6 +135,11 @@
 	enum v4l2_mbus_pixelcode code;
 };
 
+static struct sh_mobile_ceu_buffer *to_ceu_vb(struct vb2_buffer *vb)
+{
+	return container_of(vb, struct sh_mobile_ceu_buffer, vb);
+}
+
 static unsigned long make_bus_param(struct sh_mobile_ceu_dev *pcdev)
 {
 	unsigned long flags;
@@ -205,11 +212,11 @@
 /*
  *  Videobuf operations
  */
-static int sh_mobile_ceu_videobuf_setup(struct videobuf_queue *vq,
-					unsigned int *count,
-					unsigned int *size)
+static int sh_mobile_ceu_videobuf_setup(struct vb2_queue *vq,
+			unsigned int *count, unsigned int *num_planes,
+			unsigned long sizes[], void *alloc_ctxs[])
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = container_of(vq, struct soc_camera_device, vb2_vidq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
 	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
@@ -218,39 +225,25 @@
 	if (bytes_per_line < 0)
 		return bytes_per_line;
 
-	*size = bytes_per_line * icd->user_height;
+	*num_planes = 1;
 
-	if (0 == *count)
+	pcdev->sequence = 0;
+	sizes[0] = bytes_per_line * icd->user_height;
+	alloc_ctxs[0] = pcdev->alloc_ctx;
+
+	if (!*count)
 		*count = 2;
 
 	if (pcdev->video_limit) {
-		if (PAGE_ALIGN(*size) * *count > pcdev->video_limit)
-			*count = pcdev->video_limit / PAGE_ALIGN(*size);
+		if (PAGE_ALIGN(sizes[0]) * *count > pcdev->video_limit)
+			*count = pcdev->video_limit / PAGE_ALIGN(sizes[0]);
 	}
 
-	dev_dbg(icd->dev.parent, "count=%d, size=%d\n", *count, *size);
+	dev_dbg(icd->dev.parent, "count=%d, size=%lu\n", *count, sizes[0]);
 
 	return 0;
 }
 
-static void free_buffer(struct videobuf_queue *vq,
-			struct sh_mobile_ceu_buffer *buf)
-{
-	struct soc_camera_device *icd = vq->priv_data;
-	struct device *dev = icd->dev.parent;
-
-	dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
-		&buf->vb, buf->vb.baddr, buf->vb.bsize);
-
-	if (in_interrupt())
-		BUG();
-
-	videobuf_waiton(vq, &buf->vb, 0, 0);
-	videobuf_dma_contig_free(vq, &buf->vb);
-	dev_dbg(dev, "%s freed\n", __func__);
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
-}
-
 #define CEU_CETCR_MAGIC 0x0317f313 /* acknowledge magical interrupt sources */
 #define CEU_CETCR_IGRW (1 << 4) /* prohibited register access interrupt bit */
 #define CEU_CEIER_CPEIE (1 << 0) /* one-frame capture end interrupt */
@@ -309,7 +302,8 @@
 		bottom2	= CDBCR;
 	}
 
-	phys_addr_top = videobuf_to_dma_contig(pcdev->active);
+	phys_addr_top = vb2_dma_contig_plane_paddr(pcdev->active, 0);
+
 	ceu_write(pcdev, top1, phys_addr_top);
 	if (V4L2_FIELD_NONE != pcdev->field) {
 		phys_addr_bottom = phys_addr_top + icd->user_width;
@@ -330,87 +324,67 @@
 		}
 	}
 
-	pcdev->active->state = VIDEOBUF_ACTIVE;
 	ceu_write(pcdev, CAPSR, 0x1); /* start capture */
 
 	return ret;
 }
 
-static int sh_mobile_ceu_videobuf_prepare(struct videobuf_queue *vq,
-					  struct videobuf_buffer *vb,
-					  enum v4l2_field field)
+static int sh_mobile_ceu_videobuf_prepare(struct vb2_buffer *vb)
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
 	struct sh_mobile_ceu_buffer *buf;
 	int bytes_per_line = soc_mbus_bytes_per_line(icd->user_width,
 						icd->current_fmt->host_fmt);
-	int ret;
+	unsigned long size;
 
 	if (bytes_per_line < 0)
 		return bytes_per_line;
 
-	buf = container_of(vb, struct sh_mobile_ceu_buffer, vb);
+	buf = to_ceu_vb(vb);
 
-	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
-		vb, vb->baddr, vb->bsize);
+	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
 	/* Added list head initialization on alloc */
-	WARN_ON(!list_empty(&vb->queue));
+	WARN(!list_empty(&buf->queue), "Buffer %p on queue!\n", vb);
 
 #ifdef DEBUG
 	/*
 	 * This can be useful if you want to see if we actually fill
 	 * the buffer with something
 	 */
-	memset((void *)vb->baddr, 0xaa, vb->bsize);
+	if (vb2_plane_vaddr(vb, 0))
+		memset(vb2_plane_vaddr(vb, 0), 0xaa, vb2_get_plane_payload(vb, 0));
 #endif
 
 	BUG_ON(NULL == icd->current_fmt);
 
-	if (buf->code	!= icd->current_fmt->code ||
-	    vb->width	!= icd->user_width ||
-	    vb->height	!= icd->user_height ||
-	    vb->field	!= field) {
-		buf->code	= icd->current_fmt->code;
-		vb->width	= icd->user_width;
-		vb->height	= icd->user_height;
-		vb->field	= field;
-		vb->state	= VIDEOBUF_NEEDS_INIT;
-	}
+	size = icd->user_height * bytes_per_line;
 
-	vb->size = vb->height * bytes_per_line;
-	if (0 != vb->baddr && vb->bsize < vb->size) {
-		ret = -EINVAL;
-		goto out;
+	if (vb2_plane_size(vb, 0) < size) {
+		dev_err(icd->dev.parent, "Buffer too small (%lu < %lu)\n",
+			vb2_plane_size(vb, 0), size);
+		return -ENOBUFS;
 	}
 
-	if (vb->state == VIDEOBUF_NEEDS_INIT) {
-		ret = videobuf_iolock(vq, vb, NULL);
-		if (ret)
-			goto fail;
-		vb->state = VIDEOBUF_PREPARED;
-	}
+	vb2_set_plane_payload(vb, 0, size);
 
 	return 0;
-fail:
-	free_buffer(vq, buf);
-out:
-	return ret;
 }
 
-/* Called under spinlock_irqsave(&pcdev->lock, ...) */
-static void sh_mobile_ceu_videobuf_queue(struct videobuf_queue *vq,
-					 struct videobuf_buffer *vb)
+static void sh_mobile_ceu_videobuf_queue(struct vb2_buffer *vb)
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+	struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
+	unsigned long flags;
 
-	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%08lx %zd\n", __func__,
-		vb, vb->baddr, vb->bsize);
+	dev_dbg(icd->dev.parent, "%s (vb=0x%p) 0x%p %lu\n", __func__,
+		vb, vb2_plane_vaddr(vb, 0), vb2_get_plane_payload(vb, 0));
 
-	vb->state = VIDEOBUF_QUEUED;
-	list_add_tail(&vb->queue, &pcdev->capture);
+	spin_lock_irqsave(&pcdev->lock, flags);
+	list_add_tail(&buf->queue, &pcdev->capture);
 
 	if (!pcdev->active) {
 		/*
@@ -421,13 +395,14 @@
 		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,
-					   struct videobuf_buffer *vb)
+static void sh_mobile_ceu_videobuf_release(struct vb2_buffer *vb)
 {
-	struct soc_camera_device *icd = vq->priv_data;
+	struct soc_camera_device *icd = container_of(vb->vb2_queue, struct soc_camera_device, vb2_vidq);
 	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct sh_mobile_ceu_buffer *buf = to_ceu_vb(vb);
 	struct sh_mobile_ceu_dev *pcdev = ici->priv;
 	unsigned long flags;
 
@@ -439,53 +414,60 @@
 		pcdev->active = NULL;
 	}
 
-	if ((vb->state == VIDEOBUF_ACTIVE || vb->state == VIDEOBUF_QUEUED) &&
-	    !list_empty(&vb->queue)) {
-		vb->state = VIDEOBUF_ERROR;
-		list_del_init(&vb->queue);
-	}
+	/* Doesn't hurt also if the list is empty */
+	list_del_init(&buf->queue);
 
 	spin_unlock_irqrestore(&pcdev->lock, flags);
+}
 
-	free_buffer(vq, container_of(vb, struct sh_mobile_ceu_buffer, vb));
+static int sh_mobile_ceu_videobuf_init(struct vb2_buffer *vb)
+{
+	/* This is for locking debugging only */
+	INIT_LIST_HEAD(&to_ceu_vb(vb)->queue);
+	return 0;
 }
 
-static struct videobuf_queue_ops sh_mobile_ceu_videobuf_ops = {
-	.buf_setup      = sh_mobile_ceu_videobuf_setup,
-	.buf_prepare    = sh_mobile_ceu_videobuf_prepare,
-	.buf_queue      = sh_mobile_ceu_videobuf_queue,
-	.buf_release    = sh_mobile_ceu_videobuf_release,
+static struct vb2_ops sh_mobile_ceu_videobuf_ops = {
+	.queue_setup	= sh_mobile_ceu_videobuf_setup,
+	.buf_prepare	= sh_mobile_ceu_videobuf_prepare,
+	.buf_queue	= sh_mobile_ceu_videobuf_queue,
+	.buf_cleanup	= sh_mobile_ceu_videobuf_release,
+	.buf_init	= sh_mobile_ceu_videobuf_init,
+	.wait_prepare	= soc_camera_unlock,
+	.wait_finish	= soc_camera_lock,
 };
 
 static irqreturn_t sh_mobile_ceu_irq(int irq, void *data)
 {
 	struct sh_mobile_ceu_dev *pcdev = data;
-	struct videobuf_buffer *vb;
-	unsigned long flags;
+	struct vb2_buffer *vb;
+	int ret;
 
-	spin_lock_irqsave(&pcdev->lock, flags);
+	spin_lock(&pcdev->lock);
 
 	vb = pcdev->active;
 	if (!vb)
 		/* Stale interrupt from a released buffer */
 		goto out;
 
-	list_del_init(&vb->queue);
+	list_del_init(&to_ceu_vb(vb)->queue);
 
 	if (!list_empty(&pcdev->capture))
-		pcdev->active = list_entry(pcdev->capture.next,
-					   struct videobuf_buffer, queue);
+		pcdev->active = &list_entry(pcdev->capture.next,
+					    struct sh_mobile_ceu_buffer, queue)->vb;
 	else
 		pcdev->active = NULL;
 
-	vb->state = (sh_mobile_ceu_capture(pcdev) < 0) ?
-		VIDEOBUF_ERROR : VIDEOBUF_DONE;
-	do_gettimeofday(&vb->ts);
-	vb->field_count++;
-	wake_up(&vb->done);
+	ret = sh_mobile_ceu_capture(pcdev);
+	do_gettimeofday(&vb->v4l2_buf.timestamp);
+	if (!ret) {
+		vb->v4l2_buf.field = pcdev->field;
+		vb->v4l2_buf.sequence = pcdev->sequence++;
+	}
+	vb2_buffer_done(vb, ret < 0 ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
 
 out:
-	spin_unlock_irqrestore(&pcdev->lock, flags);
+	spin_unlock(&pcdev->lock);
 
 	return IRQ_HANDLED;
 }
@@ -529,9 +511,8 @@
 	/* make sure active buffer is canceled */
 	spin_lock_irqsave(&pcdev->lock, flags);
 	if (pcdev->active) {
-		list_del(&pcdev->active->queue);
-		pcdev->active->state = VIDEOBUF_ERROR;
-		wake_up_all(&pcdev->active->done);
+		list_del_init(&to_ceu_vb(pcdev->active)->queue);
+		vb2_buffer_done(pcdev->active, VB2_BUF_STATE_ERROR);
 		pcdev->active = NULL;
 	}
 	spin_unlock_irqrestore(&pcdev->lock, flags);
@@ -686,6 +667,7 @@
 		ceu_write(pcdev, CAPSR, capsr);
 }
 
+/* Capture is not running, no interrupts, no locking needed */
 static int sh_mobile_ceu_set_bus_param(struct soc_camera_device *icd,
 				       __u32 pixfmt)
 {
@@ -940,7 +922,7 @@
 			/* Try 2560x1920, 1280x960, 640x480, 320x240 */
 			mf.width	= 2560 >> shift;
 			mf.height	= 1920 >> shift;
-			ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+			ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
 							 s_mbus_fmt, &mf);
 			if (ret < 0)
 				return ret;
@@ -1242,7 +1224,7 @@
 	struct v4l2_cropcap cap;
 	int ret;
 
-	ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+	ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
 					 s_mbus_fmt, mf);
 	if (ret < 0)
 		return ret;
@@ -1272,7 +1254,7 @@
 		tmp_h = min(2 * tmp_h, max_height);
 		mf->width = tmp_w;
 		mf->height = tmp_h;
-		ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+		ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
 						 s_mbus_fmt, mf);
 		dev_geo(dev, "Camera scaled to %ux%u\n",
 			mf->width, mf->height);
@@ -1364,7 +1346,7 @@
 	struct device *dev = icd->dev.parent;
 	struct v4l2_mbus_framefmt mf;
 	unsigned int scale_cam_h, scale_cam_v, scale_ceu_h, scale_ceu_v,
-		out_width, out_height, scale_h, scale_v;
+		out_width, out_height;
 	int interm_width, interm_height;
 	u32 capsr, cflcr;
 	int ret;
@@ -1422,10 +1404,6 @@
 	scale_ceu_h	= calc_scale(interm_width, &out_width);
 	scale_ceu_v	= calc_scale(interm_height, &out_height);
 
-	/* Calculate camera scales */
-	scale_h		= calc_generic_scale(cam_rect->width, out_width);
-	scale_v		= calc_generic_scale(cam_rect->height, out_height);
-
 	dev_geo(dev, "5: CEU scales %u:%u\n", scale_ceu_h, scale_ceu_v);
 
 	/* Apply CEU scales. */
@@ -1437,8 +1415,8 @@
 
 	icd->user_width	 = out_width;
 	icd->user_height = out_height;
-	cam->ceu_left	 = scale_down(rect->left - cam_rect->left, scale_h) & ~1;
-	cam->ceu_top	 = scale_down(rect->top - cam_rect->top, scale_v) & ~1;
+	cam->ceu_left	 = scale_down(rect->left - cam_rect->left, scale_cam_h) & ~1;
+	cam->ceu_top	 = scale_down(rect->top - cam_rect->top, scale_cam_v) & ~1;
 
 	/* 6. Use CEU cropping to crop to the new window. */
 	sh_mobile_ceu_set_rect(icd);
@@ -1449,7 +1427,7 @@
 		icd->user_width, icd->user_height,
 		cam->ceu_left, cam->ceu_top);
 
-	/* Restore capture */
+	/* Restore capture. The CE bit can be cleared by the hardware */
 	if (pcdev->active)
 		capsr |= 1;
 	capture_restore(pcdev, capsr);
@@ -1680,7 +1658,7 @@
 	mf.code		= xlate->code;
 	mf.colorspace	= pix->colorspace;
 
-	ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video, try_mbus_fmt, &mf);
+	ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video, try_mbus_fmt, &mf);
 	if (ret < 0)
 		return ret;
 
@@ -1704,7 +1682,7 @@
 			 */
 			mf.width = 2560;
 			mf.height = 1920;
-			ret = v4l2_device_call_until_err(sd->v4l2_dev, 0, video,
+			ret = v4l2_device_call_until_err(sd->v4l2_dev, (long)icd, video,
 							 try_mbus_fmt, &mf);
 			if (ret < 0) {
 				/* Shouldn't actually happen... */
@@ -1726,43 +1704,11 @@
 	return ret;
 }
 
-static int sh_mobile_ceu_reqbufs(struct soc_camera_device *icd,
-				 struct v4l2_requestbuffers *p)
-{
-	int i;
-
-	/*
-	 * This is for locking debugging only. I removed spinlocks and now I
-	 * check whether .prepare is ever called on a linked buffer, or whether
-	 * a dma IRQ can occur for an in-work or unlinked buffer. Until now
-	 * it hadn't triggered
-	 */
-	for (i = 0; i < p->count; i++) {
-		struct sh_mobile_ceu_buffer *buf;
-
-		buf = container_of(icd->vb_vidq.bufs[i],
-				   struct sh_mobile_ceu_buffer, vb);
-		INIT_LIST_HEAD(&buf->vb.queue);
-	}
-
-	return 0;
-}
-
 static unsigned int sh_mobile_ceu_poll(struct file *file, poll_table *pt)
 {
 	struct soc_camera_device *icd = file->private_data;
-	struct sh_mobile_ceu_buffer *buf;
 
-	buf = list_entry(icd->vb_vidq.stream.next,
-			 struct sh_mobile_ceu_buffer, vb.stream);
-
-	poll_wait(file, &buf->vb.done, pt);
-
-	if (buf->vb.state == VIDEOBUF_DONE ||
-	    buf->vb.state == VIDEOBUF_ERROR)
-		return POLLIN|POLLRDNORM;
-
-	return 0;
+	return vb2_poll(&icd->vb2_vidq, file, pt);
 }
 
 static int sh_mobile_ceu_querycap(struct soc_camera_host *ici,
@@ -1774,19 +1720,17 @@
 	return 0;
 }
 
-static void sh_mobile_ceu_init_videobuf(struct videobuf_queue *q,
-					struct soc_camera_device *icd)
+static int sh_mobile_ceu_init_videobuf(struct vb2_queue *q,
+				       struct soc_camera_device *icd)
 {
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
-	struct sh_mobile_ceu_dev *pcdev = ici->priv;
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR;
+	q->drv_priv = icd;
+	q->ops = &sh_mobile_ceu_videobuf_ops;
+	q->mem_ops = &vb2_dma_contig_memops;
+	q->buf_struct_size = sizeof(struct sh_mobile_ceu_buffer);
 
-	videobuf_queue_dma_contig_init(q,
-				       &sh_mobile_ceu_videobuf_ops,
-				       icd->dev.parent, &pcdev->lock,
-				       V4L2_BUF_TYPE_VIDEO_CAPTURE,
-				       pcdev->field,
-				       sizeof(struct sh_mobile_ceu_buffer),
-				       icd, &icd->video_lock);
+	return vb2_queue_init(q);
 }
 
 static int sh_mobile_ceu_get_ctrl(struct soc_camera_device *icd,
@@ -1850,11 +1794,10 @@
 	.try_fmt	= sh_mobile_ceu_try_fmt,
 	.set_ctrl	= sh_mobile_ceu_set_ctrl,
 	.get_ctrl	= sh_mobile_ceu_get_ctrl,
-	.reqbufs	= sh_mobile_ceu_reqbufs,
 	.poll		= sh_mobile_ceu_poll,
 	.querycap	= sh_mobile_ceu_querycap,
 	.set_bus_param	= sh_mobile_ceu_set_bus_param,
-	.init_videobuf	= sh_mobile_ceu_init_videobuf,
+	.init_videobuf2	= sh_mobile_ceu_init_videobuf,
 	.controls	= sh_mobile_ceu_controls,
 	.num_controls	= ARRAY_SIZE(sh_mobile_ceu_controls),
 };
@@ -2005,12 +1948,20 @@
 		}
 	}
 
+	pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+	if (IS_ERR(pcdev->alloc_ctx)) {
+		err = PTR_ERR(pcdev->alloc_ctx);
+		goto exit_module_put;
+	}
+
 	err = soc_camera_host_register(&pcdev->ici);
 	if (err)
-		goto exit_module_put;
+		goto exit_free_ctx;
 
 	return 0;
 
+exit_free_ctx:
+	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 exit_module_put:
 	if (csi2 && csi2->driver)
 		module_put(csi2->driver->owner);
@@ -2041,6 +1992,7 @@
 	if (platform_get_resource(pdev, IORESOURCE_MEM, 1))
 		dma_release_declared_memory(&pdev->dev);
 	iounmap(pcdev->base);
+	vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 	if (csi2 && csi2->driver)
 		module_put(csi2->driver->owner);
 	kfree(pcdev);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/sh_mobile_csi2.c linux-libre-2.6.39-gnu/drivers/media/video/sh_mobile_csi2.c
--- linux-libre-2.6.38-gnu/drivers/media/video/sh_mobile_csi2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/sh_mobile_csi2.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,8 @@
 	void __iomem			*base;
 	struct platform_device		*pdev;
 	struct sh_csi2_client_config	*client;
+	unsigned long (*query_bus_param)(struct soc_camera_device *);
+	int (*set_bus_param)(struct soc_camera_device *, unsigned long);
 };
 
 static int sh_csi2_try_fmt(struct v4l2_subdev *sd,
@@ -56,7 +58,7 @@
 		switch (mf->code) {
 		case V4L2_MBUS_FMT_UYVY8_2X8:		/* YUV422 */
 		case V4L2_MBUS_FMT_YUYV8_1_5X8:		/* YUV420 */
-		case V4L2_MBUS_FMT_GREY8_1X8:		/* RAW8 */
+		case V4L2_MBUS_FMT_Y8_1X8:		/* RAW8 */
 		case V4L2_MBUS_FMT_SBGGR8_1X8:
 		case V4L2_MBUS_FMT_SGRBG8_1X8:
 			break;
@@ -67,7 +69,7 @@
 		break;
 	case SH_CSI2I:
 		switch (mf->code) {
-		case V4L2_MBUS_FMT_GREY8_1X8:		/* RAW8 */
+		case V4L2_MBUS_FMT_Y8_1X8:		/* RAW8 */
 		case V4L2_MBUS_FMT_SBGGR8_1X8:
 		case V4L2_MBUS_FMT_SGRBG8_1X8:
 		case V4L2_MBUS_FMT_SBGGR10_1X10:	/* RAW10 */
@@ -111,7 +113,7 @@
 	case V4L2_MBUS_FMT_RGB565_2X8_BE:
 		tmp |= 0x22;	/* RGB565 */
 		break;
-	case V4L2_MBUS_FMT_GREY8_1X8:
+	case V4L2_MBUS_FMT_Y8_1X8:
 	case V4L2_MBUS_FMT_SBGGR8_1X8:
 	case V4L2_MBUS_FMT_SGRBG8_1X8:
 		tmp |= 0x2a;	/* RAW8 */
@@ -208,6 +210,7 @@
 	case BUS_NOTIFY_BOUND_DRIVER:
 		snprintf(priv->subdev.name, V4L2_SUBDEV_NAME_SIZE, "%s%s",
 			 dev_name(v4l2_dev->dev), ".mipi-csi");
+		priv->subdev.grp_id = (long)icd;
 		ret = v4l2_device_register_subdev(v4l2_dev, &priv->subdev);
 		dev_dbg(dev, "%s(%p): ret(register_subdev) = %d\n", __func__, priv, ret);
 		if (ret < 0)
@@ -215,6 +218,8 @@
 
 		priv->client = pdata->clients + i;
 
+		priv->set_bus_param		= icd->ops->set_bus_param;
+		priv->query_bus_param		= icd->ops->query_bus_param;
 		icd->ops->set_bus_param		= sh_csi2_set_bus_param;
 		icd->ops->query_bus_param	= sh_csi2_query_bus_param;
 
@@ -226,8 +231,10 @@
 		priv->client = NULL;
 
 		/* Driver is about to be unbound */
-		icd->ops->set_bus_param		= NULL;
-		icd->ops->query_bus_param	= NULL;
+		icd->ops->set_bus_param		= priv->set_bus_param;
+		icd->ops->query_bus_param	= priv->query_bus_param;
+		priv->set_bus_param		= NULL;
+		priv->query_bus_param		= NULL;
 
 		v4l2_device_unregister_subdev(&priv->subdev);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/sn9c102/sn9c102_core.c linux-libre-2.6.39-gnu/drivers/media/video/sn9c102/sn9c102_core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/sn9c102/sn9c102_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/sn9c102/sn9c102_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1430,9 +1430,9 @@
 		   sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
 static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
 		   sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static DEVICE_ATTR(green, S_IWUGO, NULL, sn9c102_store_green);
-static DEVICE_ATTR(blue, S_IWUGO, NULL, sn9c102_store_blue);
-static DEVICE_ATTR(red, S_IWUGO, NULL, sn9c102_store_red);
+static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
+static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
+static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
 static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
 
 
@@ -1810,7 +1810,7 @@
 		/*
 		   We will not release the "open_mutex" lock, so that only one
 		   process can be in the wait queue below. This way the process
-		   will be sleeping while holding the lock, without loosing its
+		   will be sleeping while holding the lock, without losing its
 		   priority after any wake_up().
 		*/
 		err = wait_event_interruptible_exclusive(cam->wait_open,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/sn9c102/sn9c102_sensor.h linux-libre-2.6.39-gnu/drivers/media/video/sn9c102/sn9c102_sensor.h
--- linux-libre-2.6.38-gnu/drivers/media/video/sn9c102/sn9c102_sensor.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/sn9c102/sn9c102_sensor.h	2011-05-19 00:06:34.000000000 -0400
@@ -180,7 +180,7 @@
 	   It should be used to initialize the sensor only, but may also
 	   configure part of the SN9C1XX chip if necessary. You don't need to
 	   setup picture settings like brightness, contrast, etc.. here, if
-	   the corrisponding controls are implemented (see below), since
+	   the corresponding controls are implemented (see below), since
 	   they are adjusted in the core driver by calling the set_ctrl()
 	   method after init(), where the arguments are the default values
 	   specified in the v4l2_queryctrl list of supported controls;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/soc_camera.c linux-libre-2.6.39-gnu/drivers/media/video/soc_camera.c
--- linux-libre-2.6.38-gnu/drivers/media/video/soc_camera.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/soc_camera.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-dev.h>
 #include <media/videobuf-core.h>
+#include <media/videobuf2-core.h>
 #include <media/soc_mediabus.h>
 
 /* Default to VGA resolution */
@@ -135,16 +136,59 @@
 }
 EXPORT_SYMBOL(soc_camera_apply_sensor_flags);
 
+#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
+	((x) >> 24) & 0xff
+
+static int soc_camera_try_fmt(struct soc_camera_device *icd,
+			      struct v4l2_format *f)
+{
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+	struct v4l2_pix_format *pix = &f->fmt.pix;
+	int ret;
+
+	dev_dbg(&icd->dev, "TRY_FMT(%c%c%c%c, %ux%u)\n",
+		pixfmtstr(pix->pixelformat), pix->width, pix->height);
+
+	pix->bytesperline = 0;
+	pix->sizeimage = 0;
+
+	ret = ici->ops->try_fmt(icd, f);
+	if (ret < 0)
+		return ret;
+
+	if (!pix->sizeimage) {
+		if (!pix->bytesperline) {
+			const struct soc_camera_format_xlate *xlate;
+
+			xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
+			if (!xlate)
+				return -EINVAL;
+
+			ret = soc_mbus_bytes_per_line(pix->width,
+						      xlate->host_fmt);
+			if (ret > 0)
+				pix->bytesperline = ret;
+		}
+		if (pix->bytesperline)
+			pix->sizeimage = pix->bytesperline * pix->height;
+	}
+
+	return 0;
+}
+
 static int soc_camera_try_fmt_vid_cap(struct file *file, void *priv,
 				      struct v4l2_format *f)
 {
 	struct soc_camera_device *icd = file->private_data;
-	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
 	WARN_ON(priv != file->private_data);
 
+	/* Only single-plane capture is supported so far */
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	/* limit format to hardware capabilities */
-	return ici->ops->try_fmt(icd, f);
+	return soc_camera_try_fmt(icd, f);
 }
 
 static int soc_camera_enum_input(struct file *file, void *priv,
@@ -191,6 +235,15 @@
 	return v4l2_subdev_call(sd, core, s_std, *a);
 }
 
+static int soc_camera_enum_fsizes(struct file *file, void *fh,
+					 struct v4l2_frmsizeenum *fsize)
+{
+	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
+
+	return ici->ops->enum_fsizes(icd, fsize);
+}
+
 static int soc_camera_reqbufs(struct file *file, void *priv,
 			      struct v4l2_requestbuffers *p)
 {
@@ -203,11 +256,16 @@
 	if (icd->streamer && icd->streamer != file)
 		return -EBUSY;
 
-	ret = videobuf_reqbufs(&icd->vb_vidq, p);
-	if (ret < 0)
-		return ret;
+	if (ici->ops->init_videobuf) {
+		ret = videobuf_reqbufs(&icd->vb_vidq, p);
+		if (ret < 0)
+			return ret;
+
+		ret = ici->ops->reqbufs(icd, p);
+	} else {
+		ret = vb2_reqbufs(&icd->vb2_vidq, p);
+	}
 
-	ret = ici->ops->reqbufs(icd, p);
 	if (!ret && !icd->streamer)
 		icd->streamer = file;
 
@@ -218,36 +276,48 @@
 			       struct v4l2_buffer *p)
 {
 	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
 	WARN_ON(priv != file->private_data);
 
-	return videobuf_querybuf(&icd->vb_vidq, p);
+	if (ici->ops->init_videobuf)
+		return videobuf_querybuf(&icd->vb_vidq, p);
+	else
+		return vb2_querybuf(&icd->vb2_vidq, p);
 }
 
 static int soc_camera_qbuf(struct file *file, void *priv,
 			   struct v4l2_buffer *p)
 {
 	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
 	WARN_ON(priv != file->private_data);
 
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	return videobuf_qbuf(&icd->vb_vidq, p);
+	if (ici->ops->init_videobuf)
+		return videobuf_qbuf(&icd->vb_vidq, p);
+	else
+		return vb2_qbuf(&icd->vb2_vidq, p);
 }
 
 static int soc_camera_dqbuf(struct file *file, void *priv,
 			    struct v4l2_buffer *p)
 {
 	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
 	WARN_ON(priv != file->private_data);
 
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	return videobuf_dqbuf(&icd->vb_vidq, p, file->f_flags & O_NONBLOCK);
+	if (ici->ops->init_videobuf)
+		return videobuf_dqbuf(&icd->vb_vidq, p, file->f_flags & O_NONBLOCK);
+	else
+		return vb2_dqbuf(&icd->vb2_vidq, p, file->f_flags & O_NONBLOCK);
 }
 
 /* Always entered with .video_lock held */
@@ -331,9 +401,6 @@
 	icd->user_formats = NULL;
 }
 
-#define pixfmtstr(x) (x) & 0xff, ((x) >> 8) & 0xff, ((x) >> 16) & 0xff, \
-	((x) >> 24) & 0xff
-
 /* Called with .vb_lock held, or from the first open(2), see comment there */
 static int soc_camera_set_fmt(struct soc_camera_device *icd,
 			      struct v4l2_format *f)
@@ -346,7 +413,7 @@
 		pixfmtstr(pix->pixelformat), pix->width, pix->height);
 
 	/* We always call try_fmt() before set_fmt() or set_crop() */
-	ret = ici->ops->try_fmt(icd, f);
+	ret = soc_camera_try_fmt(icd, f);
 	if (ret < 0)
 		return ret;
 
@@ -362,13 +429,12 @@
 
 	icd->user_width		= pix->width;
 	icd->user_height	= pix->height;
+	icd->bytesperline	= pix->bytesperline;
+	icd->sizeimage		= pix->sizeimage;
 	icd->colorspace		= pix->colorspace;
-	icd->vb_vidq.field	=
-		icd->field	= pix->field;
-
-	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		dev_warn(&icd->dev, "Attention! Wrong buf-type %d\n",
-			 f->type);
+	icd->field		= pix->field;
+	if (ici->ops->init_videobuf)
+		icd->vb_vidq.field = pix->field;
 
 	dev_dbg(&icd->dev, "set width: %d height: %d\n",
 		icd->user_width, icd->user_height);
@@ -444,7 +510,13 @@
 		if (ret < 0)
 			goto esfmt;
 
-		ici->ops->init_videobuf(&icd->vb_vidq, icd);
+		if (ici->ops->init_videobuf) {
+			ici->ops->init_videobuf(&icd->vb_vidq, icd);
+		} else {
+			ret = ici->ops->init_videobuf2(&icd->vb2_vidq, icd);
+			if (ret < 0)
+				goto einitvb;
+		}
 	}
 
 	file->private_data = icd;
@@ -456,6 +528,7 @@
 	 * First four errors are entered with the .video_lock held
 	 * and use_count == 1
 	 */
+einitvb:
 esfmt:
 	pm_runtime_disable(&icd->vdev->dev);
 eresume:
@@ -482,6 +555,8 @@
 		pm_runtime_disable(&icd->vdev->dev);
 
 		ici->ops->remove(icd);
+		if (ici->ops->init_videobuf2)
+			vb2_queue_release(&icd->vb2_vidq);
 
 		soc_camera_power_set(icd, icl, 0);
 	}
@@ -510,6 +585,7 @@
 static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
 {
 	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	int err;
 
 	dev_dbg(&icd->dev, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
@@ -517,7 +593,10 @@
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	err = videobuf_mmap_mapper(&icd->vb_vidq, vma);
+	if (ici->ops->init_videobuf)
+		err = videobuf_mmap_mapper(&icd->vb_vidq, vma);
+	else
+		err = vb2_mmap(&icd->vb2_vidq, vma);
 
 	dev_dbg(&icd->dev, "vma start=0x%08lx, size=%ld, ret=%d\n",
 		(unsigned long)vma->vm_start,
@@ -535,7 +614,7 @@
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	if (list_empty(&icd->vb_vidq.stream)) {
+	if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) {
 		dev_err(&icd->dev, "Trying to poll with no queued buffers!\n");
 		return POLLERR;
 	}
@@ -543,6 +622,20 @@
 	return ici->ops->poll(file, pt);
 }
 
+void soc_camera_lock(struct vb2_queue *vq)
+{
+	struct soc_camera_device *icd = vb2_get_drv_priv(vq);
+	mutex_lock(&icd->video_lock);
+}
+EXPORT_SYMBOL(soc_camera_lock);
+
+void soc_camera_unlock(struct vb2_queue *vq)
+{
+	struct soc_camera_device *icd = vb2_get_drv_priv(vq);
+	mutex_unlock(&icd->video_lock);
+}
+EXPORT_SYMBOL(soc_camera_unlock);
+
 static struct v4l2_file_operations soc_camera_fops = {
 	.owner		= THIS_MODULE,
 	.open		= soc_camera_open,
@@ -561,6 +654,11 @@
 
 	WARN_ON(priv != file->private_data);
 
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+		dev_warn(&icd->dev, "Wrong buf-type %d\n", f->type);
+		return -EINVAL;
+	}
+
 	if (icd->streamer && icd->streamer != file)
 		return -EBUSY;
 
@@ -604,16 +702,16 @@
 
 	WARN_ON(priv != file->private_data);
 
+	if (f->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		return -EINVAL;
+
 	pix->width		= icd->user_width;
 	pix->height		= icd->user_height;
-	pix->field		= icd->vb_vidq.field;
+	pix->bytesperline	= icd->bytesperline;
+	pix->sizeimage		= icd->sizeimage;
+	pix->field		= icd->field;
 	pix->pixelformat	= icd->current_fmt->host_fmt->fourcc;
-	pix->bytesperline	= soc_mbus_bytes_per_line(pix->width,
-						icd->current_fmt->host_fmt);
 	pix->colorspace		= icd->colorspace;
-	if (pix->bytesperline < 0)
-		return pix->bytesperline;
-	pix->sizeimage		= pix->height * pix->bytesperline;
 	dev_dbg(&icd->dev, "current_fmt->fourcc: 0x%08x\n",
 		icd->current_fmt->host_fmt->fourcc);
 	return 0;
@@ -635,6 +733,7 @@
 			       enum v4l2_buf_type i)
 {
 	struct soc_camera_device *icd = file->private_data;
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
 	int ret;
 
@@ -646,10 +745,14 @@
 	if (icd->streamer != file)
 		return -EBUSY;
 
-	v4l2_subdev_call(sd, video, s_stream, 1);
-
 	/* This calls buf_queue from host driver's videobuf_queue_ops */
-	ret = videobuf_streamon(&icd->vb_vidq);
+	if (ici->ops->init_videobuf)
+		ret = videobuf_streamon(&icd->vb_vidq);
+	else
+		ret = vb2_streamon(&icd->vb2_vidq, i);
+
+	if (!ret)
+		v4l2_subdev_call(sd, video, s_stream, 1);
 
 	return ret;
 }
@@ -659,6 +762,7 @@
 {
 	struct soc_camera_device *icd = file->private_data;
 	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	struct soc_camera_host *ici = to_soc_camera_host(icd->dev.parent);
 
 	WARN_ON(priv != file->private_data);
 
@@ -672,7 +776,10 @@
 	 * This calls buf_release from host driver's videobuf_queue_ops for all
 	 * remaining buffers. When the last buffer is freed, stop capture
 	 */
-	videobuf_streamoff(&icd->vb_vidq);
+	if (ici->ops->init_videobuf)
+		videobuf_streamoff(&icd->vb_vidq);
+	else
+		vb2_streamoff(&icd->vb2_vidq, i);
 
 	v4l2_subdev_call(sd, video, s_stream, 0);
 
@@ -925,10 +1032,11 @@
 {
 	struct i2c_client *client =
 		to_i2c_client(to_soc_camera_control(icd));
+	struct i2c_adapter *adap = client->adapter;
 	dev_set_drvdata(&icd->dev, NULL);
 	v4l2_device_unregister_subdev(i2c_get_clientdata(client));
 	i2c_unregister_device(client);
-	i2c_put_adapter(client->adapter);
+	i2c_put_adapter(adap);
 }
 #else
 #define soc_camera_init_i2c(icd, icl)	(-ENODEV)
@@ -1000,6 +1108,9 @@
 		}
 	}
 
+	sd = soc_camera_to_subdev(icd);
+	sd->grp_id = (long)icd;
+
 	/* At this point client .probe() should have run already */
 	ret = soc_camera_init_user_formats(icd);
 	if (ret < 0)
@@ -1021,7 +1132,6 @@
 		goto evidstart;
 
 	/* Try to improve our guess of a reasonable window format */
-	sd = soc_camera_to_subdev(icd);
 	if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
 		icd->user_width		= mf.width;
 		icd->user_height	= mf.height;
@@ -1175,6 +1285,31 @@
 	return v4l2_subdev_call(sd, video, s_parm, parm);
 }
 
+static int default_enum_fsizes(struct soc_camera_device *icd,
+			  struct v4l2_frmsizeenum *fsize)
+{
+	int ret;
+	struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+	const struct soc_camera_format_xlate *xlate;
+	__u32 pixfmt = fsize->pixel_format;
+	struct v4l2_frmsizeenum fsize_mbus = *fsize;
+
+	xlate = soc_camera_xlate_by_fourcc(icd, pixfmt);
+	if (!xlate)
+		return -EINVAL;
+	/* map xlate-code to pixel_format, sensor only handle xlate-code*/
+	fsize_mbus.pixel_format = xlate->code;
+
+	ret = v4l2_subdev_call(sd, video, enum_mbus_fsizes, &fsize_mbus);
+	if (ret < 0)
+		return ret;
+
+	*fsize = fsize_mbus;
+	fsize->pixel_format = pixfmt;
+
+	return 0;
+}
+
 static void soc_camera_device_init(struct device *dev, void *pdata)
 {
 	dev->platform_data	= pdata;
@@ -1192,8 +1327,9 @@
 	    !ici->ops->set_fmt ||
 	    !ici->ops->set_bus_param ||
 	    !ici->ops->querycap ||
-	    !ici->ops->init_videobuf ||
-	    !ici->ops->reqbufs ||
+	    ((!ici->ops->init_videobuf ||
+	      !ici->ops->reqbufs) &&
+	     !ici->ops->init_videobuf2) ||
 	    !ici->ops->add ||
 	    !ici->ops->remove ||
 	    !ici->ops->poll ||
@@ -1210,6 +1346,8 @@
 		ici->ops->set_parm = default_s_parm;
 	if (!ici->ops->get_parm)
 		ici->ops->get_parm = default_g_parm;
+	if (!ici->ops->enum_fsizes)
+		ici->ops->enum_fsizes = default_enum_fsizes;
 
 	mutex_lock(&list_lock);
 	list_for_each_entry(ix, &hosts, list) {
@@ -1317,6 +1455,7 @@
 	.vidioc_g_input		 = soc_camera_g_input,
 	.vidioc_s_input		 = soc_camera_s_input,
 	.vidioc_s_std		 = soc_camera_s_std,
+	.vidioc_enum_framesizes  = soc_camera_enum_fsizes,
 	.vidioc_reqbufs		 = soc_camera_reqbufs,
 	.vidioc_try_fmt_vid_cap  = soc_camera_try_fmt_vid_cap,
 	.vidioc_querybuf	 = soc_camera_querybuf,
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/soc_mediabus.c linux-libre-2.6.39-gnu/drivers/media/video/soc_mediabus.c
--- linux-libre-2.6.38-gnu/drivers/media/video/soc_mediabus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/soc_mediabus.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,7 +88,7 @@
 		.packing		= SOC_MBUS_PACKING_EXTEND16,
 		.order			= SOC_MBUS_ORDER_LE,
 	},
-	[MBUS_IDX(GREY8_1X8)] = {
+	[MBUS_IDX(Y8_1X8)] = {
 		.fourcc			= V4L2_PIX_FMT_GREY,
 		.name			= "Grey",
 		.bits_per_sample	= 8,
@@ -132,6 +132,20 @@
 	},
 };
 
+int soc_mbus_samples_per_pixel(const struct soc_mbus_pixelfmt *mf)
+{
+	switch (mf->packing) {
+	case SOC_MBUS_PACKING_NONE:
+	case SOC_MBUS_PACKING_EXTEND16:
+		return 1;
+	case SOC_MBUS_PACKING_2X8_PADHI:
+	case SOC_MBUS_PACKING_2X8_PADLO:
+		return 2;
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(soc_mbus_samples_per_pixel);
+
 s32 soc_mbus_bytes_per_line(u32 width, const struct soc_mbus_pixelfmt *mf)
 {
 	switch (mf->packing) {
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tcm825x.c linux-libre-2.6.39-gnu/drivers/media/video/tcm825x.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tcm825x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tcm825x.c	2011-05-19 00:06:34.000000000 -0400
@@ -493,7 +493,7 @@
 	int val, r;
 	struct vcontrol *lvc;
 
-	/* exposure time is special, spread accross 2 registers */
+	/* exposure time is special, spread across 2 registers */
 	if (vc->id == V4L2_CID_EXPOSURE) {
 		int val_lower, val_upper;
 
@@ -538,7 +538,7 @@
 	struct vcontrol *lvc;
 	int val = vc->value;
 
-	/* exposure time is special, spread accross 2 registers */
+	/* exposure time is special, spread across 2 registers */
 	if (vc->id == V4L2_CID_EXPOSURE) {
 		int val_lower, val_upper;
 		val_lower = val & TCM825X_MASK(TCM825X_ESRSPD_L);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tda9840.c linux-libre-2.6.39-gnu/drivers/media/video/tda9840.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tda9840.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tda9840.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,7 +171,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
 	if (sd == NULL)
 		return -ENOMEM;
 	v4l2_i2c_subdev_init(sd, client, &tda9840_ops);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tea6415c.c linux-libre-2.6.39-gnu/drivers/media/video/tea6415c.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tea6415c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tea6415c.c	2011-05-19 00:06:34.000000000 -0400
@@ -152,7 +152,7 @@
 
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
 	if (sd == NULL)
 		return -ENOMEM;
 	v4l2_i2c_subdev_init(sd, client, &tea6415c_ops);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tea6420.c linux-libre-2.6.39-gnu/drivers/media/video/tea6420.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tea6420.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tea6420.c	2011-05-19 00:06:34.000000000 -0400
@@ -125,7 +125,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	sd = kmalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
+	sd = kzalloc(sizeof(struct v4l2_subdev), GFP_KERNEL);
 	if (sd == NULL)
 		return -ENOMEM;
 	v4l2_i2c_subdev_init(sd, client, &tea6420_ops);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/timblogiw.c linux-libre-2.6.39-gnu/drivers/media/video/timblogiw.c
--- linux-libre-2.6.38-gnu/drivers/media/video/timblogiw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/timblogiw.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/dmaengine.h>
+#include <linux/mfd/core.h>
 #include <linux/scatterlist.h>
 #include <linux/interrupt.h>
 #include <linux/list.h>
@@ -790,7 +791,7 @@
 {
 	int err;
 	struct timblogiw *lw = NULL;
-	struct timb_video_platform_data *pdata = pdev->dev.platform_data;
+	struct timb_video_platform_data *pdata = mfd_get_data(pdev);
 
 	if (!pdata) {
 		dev_err(&pdev->dev, "No platform data\n");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tlg2300/pd-video.c linux-libre-2.6.39-gnu/drivers/media/video/tlg2300/pd-video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tlg2300/pd-video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tlg2300/pd-video.c	2011-05-19 00:06:34.000000000 -0400
@@ -764,10 +764,8 @@
 	}
 	ret |= send_set_req(pd, VIDEO_ROSOLU_SEL,
 				vid_resol, &cmd_status);
-	if (ret || cmd_status) {
-		mutex_unlock(&pd->lock);
+	if (ret || cmd_status)
 		return -EBUSY;
-	}
 
 	pix_def->pixelformat = pix->pixelformat; /* save it */
 	pix->height = (context->tvnormid & V4L2_STD_525_60) ?  480 : 576;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tlv320aic23b.c linux-libre-2.6.39-gnu/drivers/media/video/tlv320aic23b.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tlv320aic23b.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tlv320aic23b.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/i2c.h>
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
 
 MODULE_DESCRIPTION("tlv320aic23b driver");
 MODULE_AUTHOR("Scott Alfter, Ulf Eklund, Hans Verkuil");
@@ -41,7 +42,7 @@
 
 struct tlv320aic23b_state {
 	struct v4l2_subdev sd;
-	u8 muted;
+	struct v4l2_ctrl_handler hdl;
 };
 
 static inline struct tlv320aic23b_state *to_state(struct v4l2_subdev *sd)
@@ -49,6 +50,11 @@
 	return container_of(sd, struct tlv320aic23b_state, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tlv320aic23b_state, hdl)->sd;
+}
+
 static int tlv320aic23b_write(struct v4l2_subdev *sd, int reg, u16 val)
 {
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -85,44 +91,44 @@
 	return 0;
 }
 
-static int tlv320aic23b_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct tlv320aic23b_state *state = to_state(sd);
-
-	if (ctrl->id != V4L2_CID_AUDIO_MUTE)
-		return -EINVAL;
-	ctrl->value = state->muted;
-	return 0;
-}
-
-static int tlv320aic23b_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tlv320aic23b_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct tlv320aic23b_state *state = to_state(sd);
+	struct v4l2_subdev *sd = to_sd(ctrl);
 
-	if (ctrl->id != V4L2_CID_AUDIO_MUTE)
-		return -EINVAL;
-	state->muted = ctrl->value;
-	tlv320aic23b_write(sd, 0, 0x180); /* mute both channels */
-	/* set gain on both channels to +3.0 dB */
-	if (!state->muted)
-		tlv320aic23b_write(sd, 0, 0x119);
-	return 0;
+	switch (ctrl->id) {
+	case V4L2_CID_AUDIO_MUTE:
+		tlv320aic23b_write(sd, 0, 0x180); /* mute both channels */
+		/* set gain on both channels to +3.0 dB */
+		if (!ctrl->val)
+			tlv320aic23b_write(sd, 0, 0x119);
+		return 0;
+	}
+	return -EINVAL;
 }
 
 static int tlv320aic23b_log_status(struct v4l2_subdev *sd)
 {
 	struct tlv320aic23b_state *state = to_state(sd);
 
-	v4l2_info(sd, "Input: %s\n", state->muted ? "muted" : "active");
+	v4l2_ctrl_handler_log_status(&state->hdl, sd->name);
 	return 0;
 }
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops tlv320aic23b_ctrl_ops = {
+	.s_ctrl = tlv320aic23b_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops tlv320aic23b_core_ops = {
 	.log_status = tlv320aic23b_log_status,
-	.g_ctrl = tlv320aic23b_g_ctrl,
-	.s_ctrl = tlv320aic23b_s_ctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 };
 
 static const struct v4l2_subdev_audio_ops tlv320aic23b_audio_ops = {
@@ -161,7 +167,6 @@
 		return -ENOMEM;
 	sd = &state->sd;
 	v4l2_i2c_subdev_init(sd, client, &tlv320aic23b_ops);
-	state->muted = 0;
 
 	/* Initialize tlv320aic23b */
 
@@ -177,15 +182,30 @@
 	tlv320aic23b_write(sd, 8, 0x000);
 	/* activate digital interface */
 	tlv320aic23b_write(sd, 9, 0x001);
+
+	v4l2_ctrl_handler_init(&state->hdl, 1);
+	v4l2_ctrl_new_std(&state->hdl, &tlv320aic23b_ctrl_ops,
+			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	sd->ctrl_handler = &state->hdl;
+	if (state->hdl.error) {
+		int err = state->hdl.error;
+
+		v4l2_ctrl_handler_free(&state->hdl);
+		kfree(state);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&state->hdl);
 	return 0;
 }
 
 static int tlv320aic23b_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct tlv320aic23b_state *state = to_state(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_state(sd));
+	v4l2_ctrl_handler_free(&state->hdl);
+	kfree(state);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tuner-core.c linux-libre-2.6.39-gnu/drivers/media/video/tuner-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tuner-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tuner-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,17 @@
 /*
- *
  * i2c tv tuner chip device driver
  * core core, i.e. kernel interfaces, registering and so on
+ *
+ * Copyright(c) by Ralph Metzler, Gerd Knorr, Gunther Mayer
+ *
+ * Copyright(c) 2005-2011 by Mauro Carvalho Chehab
+ *	- Added support for a separate Radio tuner
+ *	- Major rework and cleanups at the code
+ *
+ * This driver supports many devices and the idea is to let the driver
+ * detect which device is present. So rather than listing all supported
+ * devices here, we pretend to support a single, fake device type that will
+ * handle both radio and analog TV tuning.
  */
 
 #include <linux/module.h>
@@ -32,9 +42,111 @@
 
 #define UNSET (-1U)
 
-#define PREFIX t->i2c->driver->driver.name
+#define PREFIX (t->i2c->driver->driver.name)
 
-/** This macro allows us to probe dynamically, avoiding static links */
+/*
+ * Driver modprobe parameters
+ */
+
+/* insmod options used at init time => read/only */
+static unsigned int addr;
+static unsigned int no_autodetect;
+static unsigned int show_i2c;
+
+module_param(addr, int, 0444);
+module_param(no_autodetect, int, 0444);
+module_param(show_i2c, int, 0444);
+
+/* insmod options used at runtime => read/write */
+static int tuner_debug;
+static unsigned int tv_range[2] = { 44, 958 };
+static unsigned int radio_range[2] = { 65, 108 };
+static char pal[] = "--";
+static char secam[] = "--";
+static char ntsc[] = "-";
+
+module_param_named(debug, tuner_debug, int, 0644);
+module_param_array(tv_range, int, NULL, 0644);
+module_param_array(radio_range, int, NULL, 0644);
+module_param_string(pal, pal, sizeof(pal), 0644);
+module_param_string(secam, secam, sizeof(secam), 0644);
+module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
+
+/*
+ * Static vars
+ */
+
+static LIST_HEAD(tuner_list);
+static const struct v4l2_subdev_ops tuner_ops;
+
+/*
+ * Debug macros
+ */
+
+#define tuner_warn(fmt, arg...) do {			\
+	printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
+	       i2c_adapter_id(t->i2c->adapter),		\
+	       t->i2c->addr, ##arg);			\
+	 } while (0)
+
+#define tuner_info(fmt, arg...) do {			\
+	printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX,	\
+	       i2c_adapter_id(t->i2c->adapter),		\
+	       t->i2c->addr, ##arg);			\
+	 } while (0)
+
+#define tuner_err(fmt, arg...) do {			\
+	printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX,	\
+	       i2c_adapter_id(t->i2c->adapter),		\
+	       t->i2c->addr, ##arg);			\
+	 } while (0)
+
+#define tuner_dbg(fmt, arg...) do {				\
+	if (tuner_debug)					\
+		printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX,	\
+		       i2c_adapter_id(t->i2c->adapter),		\
+		       t->i2c->addr, ##arg);			\
+	 } while (0)
+
+/*
+ * Internal struct used inside the driver
+ */
+
+struct tuner {
+	/* device */
+	struct dvb_frontend fe;
+	struct i2c_client   *i2c;
+	struct v4l2_subdev  sd;
+	struct list_head    list;
+
+	/* keep track of the current settings */
+	v4l2_std_id         std;
+	unsigned int        tv_freq;
+	unsigned int        radio_freq;
+	unsigned int        audmode;
+
+	enum v4l2_tuner_type mode;
+	unsigned int        mode_mask; /* Combination of allowable modes */
+
+	bool                standby;	/* Standby mode */
+
+	unsigned int        type; /* chip type id */
+	unsigned int        config;
+	const char          *name;
+};
+
+/*
+ * Function prototypes
+ */
+
+static void set_tv_freq(struct i2c_client *c, unsigned int freq);
+static void set_radio_freq(struct i2c_client *c, unsigned int freq);
+
+/*
+ * tuner attach/detach logic
+ */
+
+/* This macro allows us to probe dynamically, avoiding static links */
 #ifdef CONFIG_MEDIA_ATTACH
 #define tuner_symbol_probe(FUNCTION, ARGS...) ({ \
 	int __r = -EINVAL; \
@@ -74,92 +186,15 @@
 }
 #endif
 
-struct tuner {
-	/* device */
-	struct dvb_frontend fe;
-	struct i2c_client   *i2c;
-	struct v4l2_subdev  sd;
-	struct list_head    list;
-	unsigned int        using_v4l2:1;
-
-	/* keep track of the current settings */
-	v4l2_std_id         std;
-	unsigned int        tv_freq;
-	unsigned int        radio_freq;
-	unsigned int        audmode;
-
-	unsigned int        mode;
-	unsigned int        mode_mask; /* Combination of allowable modes */
-
-	unsigned int        type; /* chip type id */
-	unsigned int        config;
-	const char          *name;
-};
 
 static inline struct tuner *to_tuner(struct v4l2_subdev *sd)
 {
 	return container_of(sd, struct tuner, sd);
 }
 
-
-/* insmod options used at init time => read/only */
-static unsigned int addr;
-static unsigned int no_autodetect;
-static unsigned int show_i2c;
-
-/* insmod options used at runtime => read/write */
-static int tuner_debug;
-
-#define tuner_warn(fmt, arg...) do {			\
-	printk(KERN_WARNING "%s %d-%04x: " fmt, PREFIX, \
-	       i2c_adapter_id(t->i2c->adapter),		\
-	       t->i2c->addr, ##arg);			\
-	 } while (0)
-
-#define tuner_info(fmt, arg...) do {			\
-	printk(KERN_INFO "%s %d-%04x: " fmt, PREFIX,	\
-	       i2c_adapter_id(t->i2c->adapter),		\
-	       t->i2c->addr, ##arg);			\
-	 } while (0)
-
-#define tuner_err(fmt, arg...) do {			\
-	printk(KERN_ERR "%s %d-%04x: " fmt, PREFIX,	\
-	       i2c_adapter_id(t->i2c->adapter),		\
-	       t->i2c->addr, ##arg);			\
-	 } while (0)
-
-#define tuner_dbg(fmt, arg...) do {				\
-	if (tuner_debug)					\
-		printk(KERN_DEBUG "%s %d-%04x: " fmt, PREFIX,	\
-		       i2c_adapter_id(t->i2c->adapter),		\
-		       t->i2c->addr, ##arg);			\
-	 } while (0)
-
-/* ------------------------------------------------------------------------ */
-
-static unsigned int tv_range[2] = { 44, 958 };
-static unsigned int radio_range[2] = { 65, 108 };
-
-static char pal[] = "--";
-static char secam[] = "--";
-static char ntsc[] = "-";
-
-
-module_param(addr, int, 0444);
-module_param(no_autodetect, int, 0444);
-module_param(show_i2c, int, 0444);
-module_param_named(debug,tuner_debug, int, 0644);
-module_param_string(pal, pal, sizeof(pal), 0644);
-module_param_string(secam, secam, sizeof(secam), 0644);
-module_param_string(ntsc, ntsc, sizeof(ntsc), 0644);
-module_param_array(tv_range, int, NULL, 0644);
-module_param_array(radio_range, int, NULL, 0644);
-
-MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
-MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
-MODULE_LICENSE("GPL");
-
-/* ---------------------------------------------------------------------- */
+/*
+ * struct analog_demod_ops callbacks
+ */
 
 static void fe_set_params(struct dvb_frontend *fe,
 			  struct analog_parameters *params)
@@ -215,102 +250,25 @@
 	.tuner_status   = tuner_status
 };
 
-/* Set tuner frequency,  freq in Units of 62.5kHz = 1/16MHz */
-static void set_tv_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = to_tuner(i2c_get_clientdata(c));
-	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
-
-	struct analog_parameters params = {
-		.mode      = t->mode,
-		.audmode   = t->audmode,
-		.std       = t->std
-	};
-
-	if (t->type == UNSET) {
-		tuner_warn ("tuner type not set\n");
-		return;
-	}
-	if (NULL == analog_ops->set_params) {
-		tuner_warn ("Tuner has no way to set tv freq\n");
-		return;
-	}
-	if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
-		tuner_dbg ("TV freq (%d.%02d) out of range (%d-%d)\n",
-			   freq / 16, freq % 16 * 100 / 16, tv_range[0],
-			   tv_range[1]);
-		/* V4L2 spec: if the freq is not possible then the closest
-		   possible value should be selected */
-		if (freq < tv_range[0] * 16)
-			freq = tv_range[0] * 16;
-		else
-			freq = tv_range[1] * 16;
-	}
-	params.frequency = freq;
-
-	analog_ops->set_params(&t->fe, &params);
-}
-
-static void set_radio_freq(struct i2c_client *c, unsigned int freq)
-{
-	struct tuner *t = to_tuner(i2c_get_clientdata(c));
-	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
-
-	struct analog_parameters params = {
-		.mode      = t->mode,
-		.audmode   = t->audmode,
-		.std       = t->std
-	};
-
-	if (t->type == UNSET) {
-		tuner_warn ("tuner type not set\n");
-		return;
-	}
-	if (NULL == analog_ops->set_params) {
-		tuner_warn ("tuner has no way to set radio frequency\n");
-		return;
-	}
-	if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
-		tuner_dbg ("radio freq (%d.%02d) out of range (%d-%d)\n",
-			   freq / 16000, freq % 16000 * 100 / 16000,
-			   radio_range[0], radio_range[1]);
-		/* V4L2 spec: if the freq is not possible then the closest
-		   possible value should be selected */
-		if (freq < radio_range[0] * 16000)
-			freq = radio_range[0] * 16000;
-		else
-			freq = radio_range[1] * 16000;
-	}
-	params.frequency = freq;
-
-	analog_ops->set_params(&t->fe, &params);
-}
-
-static void set_freq(struct i2c_client *c, unsigned long freq)
-{
-	struct tuner *t = to_tuner(i2c_get_clientdata(c));
-
-	switch (t->mode) {
-	case V4L2_TUNER_RADIO:
-		tuner_dbg("radio freq set to %lu.%02lu\n",
-			  freq / 16000, freq % 16000 * 100 / 16000);
-		set_radio_freq(c, freq);
-		t->radio_freq = freq;
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-	case V4L2_TUNER_DIGITAL_TV:
-		tuner_dbg("tv freq set to %lu.%02lu\n",
-			  freq / 16, freq % 16 * 100 / 16);
-		set_tv_freq(c, freq);
-		t->tv_freq = freq;
-		break;
-	default:
-		tuner_dbg("freq set: unknown mode: 0x%04x!\n",t->mode);
-	}
-}
-
-static struct xc5000_config xc5000_cfg;
+/*
+ * Functions to select between radio and TV and tuner probe/remove functions
+ */
 
+/**
+ * set_type - Sets the tuner type for a given device
+ *
+ * @c:			i2c_client descriptoy
+ * @type:		type of the tuner (e. g. tuner number)
+ * @new_mode_mask:	Indicates if tuner supports TV and/or Radio
+ * @new_config:		an optional parameter ranging from 0-255 used by
+			a few tuners to adjust an internal parameter,
+			like LNA mode
+ * @tuner_callback:	an optional function to be called when switching
+ *			to analog mode
+ *
+ * This function applys the tuner config to tuner specified
+ * by tun_setup structure. It contains several per-tuner initialization "magic"
+ */
 static void set_type(struct i2c_client *c, unsigned int type,
 		     unsigned int new_mode_mask, unsigned int new_config,
 		     int (*tuner_callback) (void *dev, int component, int cmd, int arg))
@@ -322,7 +280,7 @@
 	int tune_now = 1;
 
 	if (type == UNSET || type == TUNER_ABSENT) {
-		tuner_dbg ("tuner 0x%02x: Tuner type absent\n",c->addr);
+		tuner_dbg("tuner 0x%02x: Tuner type absent\n", c->addr);
 		return;
 	}
 
@@ -334,12 +292,6 @@
 		t->fe.callback = tuner_callback;
 	}
 
-	if (t->mode == T_UNINITIALIZED) {
-		tuner_dbg ("tuner 0x%02x: called during i2c_client register by adapter's attach_inform\n", c->addr);
-
-		return;
-	}
-
 	/* discard private data, in case set_type() was previously called */
 	tuner_detach(&t->fe);
 	t->fe.analog_demod_priv = NULL;
@@ -414,9 +366,12 @@
 		break;
 	case TUNER_XC5000:
 	{
-		xc5000_cfg.i2c_address	  = t->i2c->addr;
-		/* if_khz will be set when the digital dvb_attach() occurs */
-		xc5000_cfg.if_khz	  = 0;
+		struct xc5000_config xc5000_cfg = {
+			.i2c_address = t->i2c->addr,
+			/* if_khz will be set at dvb_attach() */
+			.if_khz	  = 0,
+		};
+
 		if (!dvb_attach(xc5000_attach,
 				&t->fe, t->i2c->adapter, &xc5000_cfg))
 			goto attach_failed;
@@ -459,8 +414,7 @@
 
 	tuner_dbg("type set to %s\n", t->name);
 
-	if (t->mode_mask == T_UNINITIALIZED)
-		t->mode_mask = new_mode_mask;
+	t->mode_mask = new_mode_mask;
 
 	/* Some tuners require more initialization setup before use,
 	   such as firmware download or device calibration.
@@ -468,9 +422,12 @@
 	   FIXME: better to move set_freq to the tuner code. This is needed
 	   on analog tuners for PLL to properly work
 	 */
-	if (tune_now)
-		set_freq(c, (V4L2_TUNER_RADIO == t->mode) ?
-			    t->radio_freq : t->tv_freq);
+	if (tune_now) {
+		if (V4L2_TUNER_RADIO == t->mode)
+			set_radio_freq(c, t->radio_freq);
+		else
+			set_tv_freq(c, t->tv_freq);
+	}
 
 	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,
@@ -480,86 +437,426 @@
 attach_failed:
 	tuner_dbg("Tuner attach for type = %d failed.\n", t->type);
 	t->type = TUNER_ABSENT;
-	t->mode_mask = T_UNINITIALIZED;
 
 	return;
 }
 
-/*
- * This function apply tuner config to tuner specified
- * by tun_setup structure. I addr is unset, then admin status
- * and tun addr status is more precise then current status,
- * it's applied. Otherwise status and type are applied only to
- * tuner with exactly the same addr.
-*/
-
-static void set_addr(struct i2c_client *c, struct tuner_setup *tun_setup)
+/**
+ * tuner_s_type_addr - Sets the tuner type for a device
+ *
+ * @sd:		subdev descriptor
+ * @tun_setup:	type to be associated to a given tuner i2c address
+ *
+ * This function applys the tuner config to tuner specified
+ * by tun_setup structure.
+ * If tuner I2C address is UNSET, then it will only set the device
+ * if the tuner supports the mode specified in the call.
+ * If the address is specified, the change will be applied only if
+ * tuner I2C address matches.
+ * The call can change the tuner number and the tuner mode.
+ */
+static int tuner_s_type_addr(struct v4l2_subdev *sd,
+			     struct tuner_setup *tun_setup)
 {
-	struct tuner *t = to_tuner(i2c_get_clientdata(c));
+	struct tuner *t = to_tuner(sd);
+	struct i2c_client *c = v4l2_get_subdevdata(sd);
 
-	if ( (t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
-		(t->mode_mask & tun_setup->mode_mask))) ||
-		(tun_setup->addr == c->addr)) {
-			set_type(c, tun_setup->type, tun_setup->mode_mask,
-				 tun_setup->config, tun_setup->tuner_callback);
+	tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n",
+			tun_setup->type,
+			tun_setup->addr,
+			tun_setup->mode_mask,
+			tun_setup->config);
+
+	if ((t->type == UNSET && ((tun_setup->addr == ADDR_UNSET) &&
+	    (t->mode_mask & tun_setup->mode_mask))) ||
+	    (tun_setup->addr == c->addr)) {
+		set_type(c, tun_setup->type, tun_setup->mode_mask,
+			 tun_setup->config, tun_setup->tuner_callback);
 	} else
 		tuner_dbg("set addr discarded for type %i, mask %x. "
 			  "Asked to change tuner at addr 0x%02x, with mask %x\n",
 			  t->type, t->mode_mask,
 			  tun_setup->addr, tun_setup->mode_mask);
+
+	return 0;
 }
 
-static inline int check_mode(struct tuner *t, char *cmd)
+/**
+ * tuner_s_config - Sets tuner configuration
+ *
+ * @sd:		subdev descriptor
+ * @cfg:	tuner configuration
+ *
+ * Calls tuner set_config() private function to set some tuner-internal
+ * parameters
+ */
+static int tuner_s_config(struct v4l2_subdev *sd,
+			  const struct v4l2_priv_tun_config *cfg)
 {
-	if ((1 << t->mode & t->mode_mask) == 0) {
-		return -EINVAL;
+	struct tuner *t = to_tuner(sd);
+	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+	if (t->type != cfg->tuner)
+		return 0;
+
+	if (analog_ops->set_config) {
+		analog_ops->set_config(&t->fe, cfg->priv);
+		return 0;
 	}
 
-	switch (t->mode) {
-	case V4L2_TUNER_RADIO:
-		tuner_dbg("Cmd %s accepted for radio\n", cmd);
-		break;
-	case V4L2_TUNER_ANALOG_TV:
-		tuner_dbg("Cmd %s accepted for analog TV\n", cmd);
-		break;
-	case V4L2_TUNER_DIGITAL_TV:
-		tuner_dbg("Cmd %s accepted for digital TV\n", cmd);
-		break;
+	tuner_dbg("Tuner frontend module has no way to set config\n");
+	return 0;
+}
+
+/**
+ * tuner_lookup - Seek for tuner adapters
+ *
+ * @adap:	i2c_adapter struct
+ * @radio:	pointer to be filled if the adapter is radio
+ * @tv:		pointer to be filled if the adapter is TV
+ *
+ * Search for existing radio and/or TV tuners on the given I2C adapter,
+ * discarding demod-only adapters (tda9887).
+ *
+ * Note that when this function is called from tuner_probe you can be
+ * certain no other devices will be added/deleted at the same time, I2C
+ * core protects against that.
+ */
+static void tuner_lookup(struct i2c_adapter *adap,
+		struct tuner **radio, struct tuner **tv)
+{
+	struct tuner *pos;
+
+	*radio = NULL;
+	*tv = NULL;
+
+	list_for_each_entry(pos, &tuner_list, list) {
+		int mode_mask;
+
+		if (pos->i2c->adapter != adap ||
+		    strcmp(pos->i2c->driver->driver.name, "tuner"))
+			continue;
+
+		mode_mask = pos->mode_mask;
+		if (*radio == NULL && mode_mask == T_RADIO)
+			*radio = pos;
+		/* Note: currently TDA9887 is the only demod-only
+		   device. If other devices appear then we need to
+		   make this test more general. */
+		else if (*tv == NULL && pos->type != TUNER_TDA9887 &&
+			 (pos->mode_mask & T_ANALOG_TV))
+			*tv = pos;
+	}
+}
+
+/**
+ *tuner_probe - Probes the existing tuners on an I2C bus
+ *
+ * @client:	i2c_client descriptor
+ * @id:		not used
+ *
+ * This routine probes for tuners at the expected I2C addresses. On most
+ * cases, if a device answers to a given I2C address, it assumes that the
+ * device is a tuner. On a few cases, however, an additional logic is needed
+ * to double check if the device is really a tuner, or to identify the tuner
+ * type, like on tea5767/5761 devices.
+ *
+ * During client attach, set_type is called by adapter's attach_inform callback.
+ * set_type must then be completed by tuner_probe.
+ */
+static int tuner_probe(struct i2c_client *client,
+		       const struct i2c_device_id *id)
+{
+	struct tuner *t;
+	struct tuner *radio;
+	struct tuner *tv;
+
+	t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
+	if (NULL == t)
+		return -ENOMEM;
+	v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops);
+	t->i2c = client;
+	t->name = "(tuner unset)";
+	t->type = UNSET;
+	t->audmode = V4L2_TUNER_MODE_STEREO;
+	t->standby = 1;
+	t->radio_freq = 87.5 * 16000;	/* Initial freq range */
+	t->tv_freq = 400 * 16; /* Sets freq to VHF High - needed for some PLL's to properly start */
+
+	if (show_i2c) {
+		unsigned char buffer[16];
+		int i, rc;
+
+		memset(buffer, 0, sizeof(buffer));
+		rc = i2c_master_recv(client, buffer, sizeof(buffer));
+		tuner_info("I2C RECV = ");
+		for (i = 0; i < rc; i++)
+			printk(KERN_CONT "%02x ", buffer[i]);
+		printk("\n");
+	}
+
+	/* autodetection code based on the i2c addr */
+	if (!no_autodetect) {
+		switch (client->addr) {
+		case 0x10:
+			if (tuner_symbol_probe(tea5761_autodetection,
+					       t->i2c->adapter,
+					       t->i2c->addr) >= 0) {
+				t->type = TUNER_TEA5761;
+				t->mode_mask = T_RADIO;
+				tuner_lookup(t->i2c->adapter, &radio, &tv);
+				if (tv)
+					tv->mode_mask &= ~T_RADIO;
+
+				goto register_client;
+			}
+			kfree(t);
+			return -ENODEV;
+		case 0x42:
+		case 0x43:
+		case 0x4a:
+		case 0x4b:
+			/* If chip is not tda8290, don't register.
+			   since it can be tda9887*/
+			if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
+					       t->i2c->addr) >= 0) {
+				tuner_dbg("tda829x detected\n");
+			} else {
+				/* Default is being tda9887 */
+				t->type = TUNER_TDA9887;
+				t->mode_mask = T_RADIO | T_ANALOG_TV;
+				goto register_client;
+			}
+			break;
+		case 0x60:
+			if (tuner_symbol_probe(tea5767_autodetection,
+					       t->i2c->adapter, t->i2c->addr)
+					>= 0) {
+				t->type = TUNER_TEA5767;
+				t->mode_mask = T_RADIO;
+				/* Sets freq to FM range */
+				tuner_lookup(t->i2c->adapter, &radio, &tv);
+				if (tv)
+					tv->mode_mask &= ~T_RADIO;
+
+				goto register_client;
+			}
+			break;
+		}
 	}
+
+	/* Initializes only the first TV tuner on this adapter. Why only the
+	   first? Because there are some devices (notably the ones with TI
+	   tuners) that have more than one i2c address for the *same* device.
+	   Experience shows that, except for just one case, the first
+	   address is the right one. The exception is a Russian tuner
+	   (ACORP_Y878F). So, the desired behavior is just to enable the
+	   first found TV tuner. */
+	tuner_lookup(t->i2c->adapter, &radio, &tv);
+	if (tv == NULL) {
+		t->mode_mask = T_ANALOG_TV;
+		if (radio == NULL)
+			t->mode_mask |= T_RADIO;
+		tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask);
+	}
+
+	/* Should be just before return */
+register_client:
+	/* Sets a default mode */
+	if (t->mode_mask & T_ANALOG_TV)
+		t->mode = V4L2_TUNER_ANALOG_TV;
+	else
+		t->mode = V4L2_TUNER_RADIO;
+	set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
+	list_add_tail(&t->list, &tuner_list);
+
+	tuner_info("Tuner %d found with type(s)%s%s.\n",
+		   t->type,
+		   t->mode_mask & T_RADIO ? " Radio" : "",
+		   t->mode_mask & T_ANALOG_TV ? " TV" : "");
 	return 0;
 }
 
-/* get more precise norm info from insmod option */
+/**
+ * tuner_remove - detaches a tuner
+ *
+ * @client:	i2c_client descriptor
+ */
+
+static int tuner_remove(struct i2c_client *client)
+{
+	struct tuner *t = to_tuner(i2c_get_clientdata(client));
+
+	v4l2_device_unregister_subdev(&t->sd);
+	tuner_detach(&t->fe);
+	t->fe.analog_demod_priv = NULL;
+
+	list_del(&t->list);
+	kfree(t);
+	return 0;
+}
+
+/*
+ * Functions to switch between Radio and TV
+ *
+ * A few cards have a separate I2C tuner for radio. Those routines
+ * take care of switching between TV/Radio mode, filtering only the
+ * commands that apply to the Radio or TV tuner.
+ */
+
+/**
+ * check_mode - Verify if tuner supports the requested mode
+ * @t: a pointer to the module's internal struct_tuner
+ *
+ * This function checks if the tuner is capable of tuning analog TV,
+ * digital TV or radio, depending on what the caller wants. If the
+ * tuner can't support that mode, it returns -EINVAL. Otherwise, it
+ * returns 0.
+ * This function is needed for boards that have a separate tuner for
+ * radio (like devices with tea5767).
+ */
+static inline int check_mode(struct tuner *t, enum v4l2_tuner_type mode)
+{
+	if ((1 << mode & t->mode_mask) == 0)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * set_mode_freq - Switch tuner to other mode.
+ * @client:	struct i2c_client pointer
+ * @t:		a pointer to the module's internal struct_tuner
+ * @mode:	enum v4l2_type (radio or TV)
+ * @freq:	frequency to set (0 means to use the previous one)
+ *
+ * If tuner doesn't support the needed mode (radio or TV), prints a
+ * debug message and returns -EINVAL, changing its state to standby.
+ * Otherwise, changes the state and sets frequency to the last value, if
+ * the tuner can sleep or if it supports both Radio and TV.
+ */
+static int set_mode_freq(struct i2c_client *client, struct tuner *t,
+			 enum v4l2_tuner_type mode, unsigned int freq)
+{
+	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+	if (mode != t->mode) {
+		if (check_mode(t, mode) == -EINVAL) {
+			tuner_dbg("Tuner doesn't support mode %d. "
+				  "Putting tuner to sleep\n", mode);
+			t->standby = true;
+			if (analog_ops->standby)
+				analog_ops->standby(&t->fe);
+			return -EINVAL;
+		}
+		t->mode = mode;
+		tuner_dbg("Changing to mode %d\n", mode);
+	}
+	if (t->mode == V4L2_TUNER_RADIO) {
+		if (freq)
+			t->radio_freq = freq;
+		set_radio_freq(client, t->radio_freq);
+	} else {
+		if (freq)
+			t->tv_freq = freq;
+		set_tv_freq(client, t->tv_freq);
+	}
+
+	return 0;
+}
+
+/*
+ * Functions that are specific for TV mode
+ */
+
+/**
+ * set_tv_freq - Set tuner frequency,  freq in Units of 62.5 kHz = 1/16MHz
+ *
+ * @c:	i2c_client descriptor
+ * @freq: frequency
+ */
+static void set_tv_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = to_tuner(i2c_get_clientdata(c));
+	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+	struct analog_parameters params = {
+		.mode      = t->mode,
+		.audmode   = t->audmode,
+		.std       = t->std
+	};
+
+	if (t->type == UNSET) {
+		tuner_warn("tuner type not set\n");
+		return;
+	}
+	if (NULL == analog_ops->set_params) {
+		tuner_warn("Tuner has no way to set tv freq\n");
+		return;
+	}
+	if (freq < tv_range[0] * 16 || freq > tv_range[1] * 16) {
+		tuner_dbg("TV freq (%d.%02d) out of range (%d-%d)\n",
+			   freq / 16, freq % 16 * 100 / 16, tv_range[0],
+			   tv_range[1]);
+		/* V4L2 spec: if the freq is not possible then the closest
+		   possible value should be selected */
+		if (freq < tv_range[0] * 16)
+			freq = tv_range[0] * 16;
+		else
+			freq = tv_range[1] * 16;
+	}
+	params.frequency = freq;
+	tuner_dbg("tv freq set to %d.%02d\n",
+			freq / 16, freq % 16 * 100 / 16);
+	t->tv_freq = freq;
+	t->standby = false;
+
+	analog_ops->set_params(&t->fe, &params);
+}
+
+/**
+ * tuner_fixup_std - force a given video standard variant
+ *
+ * @t:	tuner internal struct
+ *
+ * A few devices or drivers have problem to detect some standard variations.
+ * On other operational systems, the drivers generally have a per-country
+ * code, and some logic to apply per-country hacks. V4L2 API doesn't provide
+ * such hacks. Instead, it relies on a proper video standard selection from
+ * the userspace application. However, as some apps are buggy, not allowing
+ * to distinguish all video standard variations, a modprobe parameter can
+ * be used to force a video standard match.
+ */
 static int tuner_fixup_std(struct tuner *t)
 {
 	if ((t->std & V4L2_STD_PAL) == V4L2_STD_PAL) {
 		switch (pal[0]) {
 		case '6':
-			tuner_dbg ("insmod fixup: PAL => PAL-60\n");
+			tuner_dbg("insmod fixup: PAL => PAL-60\n");
 			t->std = V4L2_STD_PAL_60;
 			break;
 		case 'b':
 		case 'B':
 		case 'g':
 		case 'G':
-			tuner_dbg ("insmod fixup: PAL => PAL-BG\n");
+			tuner_dbg("insmod fixup: PAL => PAL-BG\n");
 			t->std = V4L2_STD_PAL_BG;
 			break;
 		case 'i':
 		case 'I':
-			tuner_dbg ("insmod fixup: PAL => PAL-I\n");
+			tuner_dbg("insmod fixup: PAL => PAL-I\n");
 			t->std = V4L2_STD_PAL_I;
 			break;
 		case 'd':
 		case 'D':
 		case 'k':
 		case 'K':
-			tuner_dbg ("insmod fixup: PAL => PAL-DK\n");
+			tuner_dbg("insmod fixup: PAL => PAL-DK\n");
 			t->std = V4L2_STD_PAL_DK;
 			break;
 		case 'M':
 		case 'm':
-			tuner_dbg ("insmod fixup: PAL => PAL-M\n");
+			tuner_dbg("insmod fixup: PAL => PAL-M\n");
 			t->std = V4L2_STD_PAL_M;
 			break;
 		case 'N':
@@ -568,7 +865,7 @@
 				tuner_dbg("insmod fixup: PAL => PAL-Nc\n");
 				t->std = V4L2_STD_PAL_Nc;
 			} else {
-				tuner_dbg ("insmod fixup: PAL => PAL-N\n");
+				tuner_dbg("insmod fixup: PAL => PAL-N\n");
 				t->std = V4L2_STD_PAL_N;
 			}
 			break;
@@ -576,7 +873,7 @@
 			/* default parameter, do nothing */
 			break;
 		default:
-			tuner_warn ("pal= argument not recognised\n");
+			tuner_warn("pal= argument not recognised\n");
 			break;
 		}
 	}
@@ -589,22 +886,24 @@
 		case 'h':
 		case 'H':
 			tuner_dbg("insmod fixup: SECAM => SECAM-BGH\n");
-			t->std = V4L2_STD_SECAM_B | V4L2_STD_SECAM_G | V4L2_STD_SECAM_H;
+			t->std = V4L2_STD_SECAM_B |
+				 V4L2_STD_SECAM_G |
+				 V4L2_STD_SECAM_H;
 			break;
 		case 'd':
 		case 'D':
 		case 'k':
 		case 'K':
-			tuner_dbg ("insmod fixup: SECAM => SECAM-DK\n");
+			tuner_dbg("insmod fixup: SECAM => SECAM-DK\n");
 			t->std = V4L2_STD_SECAM_DK;
 			break;
 		case 'l':
 		case 'L':
-			if ((secam[1]=='C')||(secam[1]=='c')) {
-				tuner_dbg ("insmod fixup: SECAM => SECAM-L'\n");
+			if ((secam[1] == 'C') || (secam[1] == 'c')) {
+				tuner_dbg("insmod fixup: SECAM => SECAM-L'\n");
 				t->std = V4L2_STD_SECAM_LC;
 			} else {
-				tuner_dbg ("insmod fixup: SECAM => SECAM-L\n");
+				tuner_dbg("insmod fixup: SECAM => SECAM-L\n");
 				t->std = V4L2_STD_SECAM_L;
 			}
 			break;
@@ -612,7 +911,7 @@
 			/* default parameter, do nothing */
 			break;
 		default:
-			tuner_warn ("secam= argument not recognised\n");
+			tuner_warn("secam= argument not recognised\n");
 			break;
 		}
 	}
@@ -645,6 +944,66 @@
 	return 0;
 }
 
+/*
+ * Functions that are specific for Radio mode
+ */
+
+/**
+ * set_radio_freq - Set tuner frequency,  freq in Units of 62.5 Hz  = 1/16kHz
+ *
+ * @c:	i2c_client descriptor
+ * @freq: frequency
+ */
+static void set_radio_freq(struct i2c_client *c, unsigned int freq)
+{
+	struct tuner *t = to_tuner(i2c_get_clientdata(c));
+	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
+
+	struct analog_parameters params = {
+		.mode      = t->mode,
+		.audmode   = t->audmode,
+		.std       = t->std
+	};
+
+	if (t->type == UNSET) {
+		tuner_warn("tuner type not set\n");
+		return;
+	}
+	if (NULL == analog_ops->set_params) {
+		tuner_warn("tuner has no way to set radio frequency\n");
+		return;
+	}
+	if (freq < radio_range[0] * 16000 || freq > radio_range[1] * 16000) {
+		tuner_dbg("radio freq (%d.%02d) out of range (%d-%d)\n",
+			   freq / 16000, freq % 16000 * 100 / 16000,
+			   radio_range[0], radio_range[1]);
+		/* V4L2 spec: if the freq is not possible then the closest
+		   possible value should be selected */
+		if (freq < radio_range[0] * 16000)
+			freq = radio_range[0] * 16000;
+		else
+			freq = radio_range[1] * 16000;
+	}
+	params.frequency = freq;
+	tuner_dbg("radio freq set to %d.%02d\n",
+			freq / 16000, freq % 16000 * 100 / 16000);
+	t->radio_freq = freq;
+	t->standby = false;
+
+	analog_ops->set_params(&t->fe, &params);
+}
+
+/*
+ * Debug function for reporting tuner status to userspace
+ */
+
+/**
+ * tuner_status - Dumps the current tuner status at dmesg
+ * @fe: pointer to struct dvb_frontend
+ *
+ * This callback is used only for driver debug purposes, answering to
+ * VIDIOC_LOG_STATUS. No changes should happen on this call.
+ */
 static void tuner_status(struct dvb_frontend *fe)
 {
 	struct tuner *t = fe->analog_demod_priv;
@@ -654,10 +1013,16 @@
 	const char *p;
 
 	switch (t->mode) {
-		case V4L2_TUNER_RADIO: 	    p = "radio"; break;
-		case V4L2_TUNER_ANALOG_TV:  p = "analog TV"; break;
-		case V4L2_TUNER_DIGITAL_TV: p = "digital TV"; break;
-		default: p = "undefined"; break;
+	case V4L2_TUNER_RADIO:
+		p = "radio";
+		break;
+	case V4L2_TUNER_DIGITAL_TV:
+		p = "digital TV";
+		break;
+	case V4L2_TUNER_ANALOG_TV:
+	default:
+		p = "analog TV";
+		break;
 	}
 	if (t->mode == V4L2_TUNER_RADIO) {
 		freq = t->radio_freq / 16000;
@@ -666,11 +1031,12 @@
 		freq = t->tv_freq / 16;
 		freq_fraction = (t->tv_freq % 16) * 100 / 16;
 	}
-	tuner_info("Tuner mode:      %s\n", p);
+	tuner_info("Tuner mode:      %s%s\n", p,
+		   t->standby ? " on standby mode" : "");
 	tuner_info("Frequency:       %lu.%02lu MHz\n", freq, freq_fraction);
 	tuner_info("Standard:        0x%08lx\n", (unsigned long)t->std);
 	if (t->mode != V4L2_TUNER_RADIO)
-	       return;
+		return;
 	if (fe_tuner_ops->get_status) {
 		u32 tuner_status;
 
@@ -683,132 +1049,58 @@
 	if (analog_ops->has_signal)
 		tuner_info("Signal strength: %d\n",
 			   analog_ops->has_signal(fe));
-	if (analog_ops->is_stereo)
-		tuner_info("Stereo:          %s\n",
-			   analog_ops->is_stereo(fe) ? "yes" : "no");
 }
 
-/* ---------------------------------------------------------------------- */
-
 /*
- * Switch tuner to other mode. If tuner support both tv and radio,
- * set another frequency to some value (This is needed for some pal
- * tuners to avoid locking). Otherwise, just put second tuner in
- * standby mode.
+ * Function to splicitly change mode to radio. Probably not needed anymore
  */
 
-static inline int set_mode(struct i2c_client *client, struct tuner *t, int mode, char *cmd)
-{
-	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
-
-	if (mode == t->mode)
-		return 0;
-
-	t->mode = mode;
-
-	if (check_mode(t, cmd) == -EINVAL) {
-		tuner_dbg("Tuner doesn't support this mode. "
-			  "Putting tuner to sleep\n");
-		t->mode = T_STANDBY;
-		if (analog_ops->standby)
-			analog_ops->standby(&t->fe);
-		return -EINVAL;
-	}
-	return 0;
-}
-
-#define switch_v4l2()	if (!t->using_v4l2) \
-			    tuner_dbg("switching to v4l2\n"); \
-			t->using_v4l2 = 1;
-
-static inline int check_v4l2(struct tuner *t)
-{
-	/* bttv still uses both v4l1 and v4l2 calls to the tuner (v4l2 for
-	   TV, v4l1 for radio), until that is fixed this code is disabled.
-	   Otherwise the radio (v4l1) wouldn't tune after using the TV (v4l2)
-	   first. */
-	return 0;
-}
-
-static int tuner_s_type_addr(struct v4l2_subdev *sd, struct tuner_setup *type)
-{
-	struct tuner *t = to_tuner(sd);
-	struct i2c_client *client = v4l2_get_subdevdata(sd);
-
-	tuner_dbg("Calling set_type_addr for type=%d, addr=0x%02x, mode=0x%02x, config=0x%02x\n",
-			type->type,
-			type->addr,
-			type->mode_mask,
-			type->config);
-
-	set_addr(client, type);
-	return 0;
-}
-
 static int tuner_s_radio(struct v4l2_subdev *sd)
 {
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (set_mode(client, t, V4L2_TUNER_RADIO, "s_radio") == -EINVAL)
+	if (set_mode_freq(client, t, V4L2_TUNER_RADIO, 0) == -EINVAL)
 		return 0;
-	if (t->radio_freq)
-		set_freq(client, t->radio_freq);
 	return 0;
 }
 
+/*
+ * Tuner callbacks to handle userspace ioctl's
+ */
+
+/**
+ * tuner_s_power - controls the power state of the tuner
+ * @sd: pointer to struct v4l2_subdev
+ * @on: a zero value puts the tuner to sleep
+ */
 static int tuner_s_power(struct v4l2_subdev *sd, int on)
 {
 	struct tuner *t = to_tuner(sd);
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
+	/* FIXME: Why this function don't wake the tuner if on != 0 ? */
 	if (on)
 		return 0;
 
 	tuner_dbg("Putting tuner to sleep\n");
-
-	if (check_mode(t, "s_power") == -EINVAL)
-		return 0;
-	t->mode = T_STANDBY;
+	t->standby = true;
 	if (analog_ops->standby)
 		analog_ops->standby(&t->fe);
 	return 0;
 }
 
-static int tuner_s_config(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *cfg)
-{
-	struct tuner *t = to_tuner(sd);
-	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
-
-	if (t->type != cfg->tuner)
-		return 0;
-
-	if (analog_ops->set_config) {
-		analog_ops->set_config(&t->fe, cfg->priv);
-		return 0;
-	}
-
-	tuner_dbg("Tuner frontend module has no way to set config\n");
-	return 0;
-}
-
-/* --- v4l ioctls --- */
-/* take care: bttv does userspace copying, we'll get a
-   kernel pointer here... */
 static int tuner_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
 {
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (set_mode(client, t, V4L2_TUNER_ANALOG_TV, "s_std") == -EINVAL)
+	if (set_mode_freq(client, t, V4L2_TUNER_ANALOG_TV, 0) == -EINVAL)
 		return 0;
 
-	switch_v4l2();
-
 	t->std = std;
 	tuner_fixup_std(t);
-	if (t->tv_freq)
-		set_freq(client, t->tv_freq);
+
 	return 0;
 }
 
@@ -817,10 +1109,8 @@
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (set_mode(client, t, f->type, "s_frequency") == -EINVAL)
+	if (set_mode_freq(client, t, f->type, f->frequency) == -EINVAL)
 		return 0;
-	switch_v4l2();
-	set_freq(client, f->frequency);
 
 	return 0;
 }
@@ -830,21 +1120,20 @@
 	struct tuner *t = to_tuner(sd);
 	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
 
-	if (check_mode(t, "g_frequency") == -EINVAL)
+	if (check_mode(t, f->type) == -EINVAL)
 		return 0;
-	switch_v4l2();
 	f->type = t->mode;
-	if (fe_tuner_ops->get_frequency) {
+	if (fe_tuner_ops->get_frequency && !t->standby) {
 		u32 abs_freq;
 
 		fe_tuner_ops->get_frequency(&t->fe, &abs_freq);
 		f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
 			DIV_ROUND_CLOSEST(abs_freq * 2, 125) :
 			DIV_ROUND_CLOSEST(abs_freq, 62500);
-		return 0;
+	} else {
+		f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
+			t->radio_freq : t->tv_freq;
 	}
-	f->frequency = (V4L2_TUNER_RADIO == t->mode) ?
-		t->radio_freq : t->tv_freq;
 	return 0;
 }
 
@@ -854,10 +1143,8 @@
 	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 	struct dvb_tuner_ops *fe_tuner_ops = &t->fe.ops.tuner_ops;
 
-	if (check_mode(t, "g_tuner") == -EINVAL)
+	if (check_mode(t, vt->type) == -EINVAL)
 		return 0;
-	switch_v4l2();
-
 	vt->type = t->mode;
 	if (analog_ops->get_afc)
 		vt->afc = analog_ops->get_afc(&t->fe);
@@ -870,8 +1157,7 @@
 	}
 
 	/* radio mode */
-	vt->rxsubchans =
-		V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
+	vt->rxsubchans = V4L2_TUNER_SUB_MONO | V4L2_TUNER_SUB_STEREO;
 	if (fe_tuner_ops->get_status) {
 		u32 tuner_status;
 
@@ -880,21 +1166,14 @@
 			(tuner_status & TUNER_STATUS_STEREO) ?
 			V4L2_TUNER_SUB_STEREO :
 			V4L2_TUNER_SUB_MONO;
-	} else {
-		if (analog_ops->is_stereo) {
-			vt->rxsubchans =
-				analog_ops->is_stereo(&t->fe) ?
-				V4L2_TUNER_SUB_STEREO :
-				V4L2_TUNER_SUB_MONO;
-		}
 	}
 	if (analog_ops->has_signal)
 		vt->signal = analog_ops->has_signal(&t->fe);
-	vt->capability |=
-		V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
+	vt->capability |= V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
 	vt->audmode = t->audmode;
 	vt->rangelow = radio_range[0] * 16000;
 	vt->rangehigh = radio_range[1] * 16000;
+
 	return 0;
 }
 
@@ -903,16 +1182,12 @@
 	struct tuner *t = to_tuner(sd);
 	struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-	if (check_mode(t, "s_tuner") == -EINVAL)
+	if (set_mode_freq(client, t, vt->type, 0) == -EINVAL)
 		return 0;
 
-	switch_v4l2();
+	if (t->mode == V4L2_TUNER_RADIO)
+		t->audmode = vt->audmode;
 
-	/* do nothing unless we're a radio tuner */
-	if (t->mode != V4L2_TUNER_RADIO)
-		return 0;
-	t->audmode = vt->audmode;
-	set_radio_freq(client, t->radio_freq);
 	return 0;
 }
 
@@ -929,9 +1204,13 @@
 static int tuner_suspend(struct i2c_client *c, pm_message_t state)
 {
 	struct tuner *t = to_tuner(i2c_get_clientdata(c));
+	struct analog_demod_ops *analog_ops = &t->fe.ops.analog_ops;
 
 	tuner_dbg("suspend\n");
-	/* FIXME: power down ??? */
+
+	if (!t->standby && analog_ops->standby)
+		analog_ops->standby(&t->fe);
+
 	return 0;
 }
 
@@ -940,13 +1219,10 @@
 	struct tuner *t = to_tuner(i2c_get_clientdata(c));
 
 	tuner_dbg("resume\n");
-	if (V4L2_TUNER_RADIO == t->mode) {
-		if (t->radio_freq)
-			set_freq(c, t->radio_freq);
-	} else {
-		if (t->tv_freq)
-			set_freq(c, t->tv_freq);
-	}
+
+	if (!t->standby)
+		set_mode_freq(c, t, t->type, 0);
+
 	return 0;
 }
 
@@ -964,7 +1240,9 @@
 	return -ENOIOCTLCMD;
 }
 
-/* ----------------------------------------------------------------------- */
+/*
+ * Callback structs
+ */
 
 static const struct v4l2_subdev_core_ops tuner_core_ops = {
 	.log_status = tuner_log_status,
@@ -987,183 +1265,10 @@
 	.tuner = &tuner_tuner_ops,
 };
 
-/* ---------------------------------------------------------------------- */
-
-static LIST_HEAD(tuner_list);
-
-/* Search for existing radio and/or TV tuners on the given I2C adapter.
-   Note that when this function is called from tuner_probe you can be
-   certain no other devices will be added/deleted at the same time, I2C
-   core protects against that. */
-static void tuner_lookup(struct i2c_adapter *adap,
-		struct tuner **radio, struct tuner **tv)
-{
-	struct tuner *pos;
-
-	*radio = NULL;
-	*tv = NULL;
-
-	list_for_each_entry(pos, &tuner_list, list) {
-		int mode_mask;
-
-		if (pos->i2c->adapter != adap ||
-		    strcmp(pos->i2c->driver->driver.name, "tuner"))
-			continue;
-
-		mode_mask = pos->mode_mask & ~T_STANDBY;
-		if (*radio == NULL && mode_mask == T_RADIO)
-			*radio = pos;
-		/* Note: currently TDA9887 is the only demod-only
-		   device. If other devices appear then we need to
-		   make this test more general. */
-		else if (*tv == NULL && pos->type != TUNER_TDA9887 &&
-			 (pos->mode_mask & (T_ANALOG_TV | T_DIGITAL_TV)))
-			*tv = pos;
-	}
-}
-
-/* During client attach, set_type is called by adapter's attach_inform callback.
-   set_type must then be completed by tuner_probe.
+/*
+ * I2C structs and module init functions
  */
-static int tuner_probe(struct i2c_client *client,
-		       const struct i2c_device_id *id)
-{
-	struct tuner *t;
-	struct tuner *radio;
-	struct tuner *tv;
-
-	t = kzalloc(sizeof(struct tuner), GFP_KERNEL);
-	if (NULL == t)
-		return -ENOMEM;
-	v4l2_i2c_subdev_init(&t->sd, client, &tuner_ops);
-	t->i2c = client;
-	t->name = "(tuner unset)";
-	t->type = UNSET;
-	t->audmode = V4L2_TUNER_MODE_STEREO;
-	t->mode_mask = T_UNINITIALIZED;
-
-	if (show_i2c) {
-		unsigned char buffer[16];
-		int i, rc;
-
-		memset(buffer, 0, sizeof(buffer));
-		rc = i2c_master_recv(client, buffer, sizeof(buffer));
-		tuner_info("I2C RECV = ");
-		for (i = 0; i < rc; i++)
-			printk(KERN_CONT "%02x ", buffer[i]);
-		printk("\n");
-	}
-
-	/* autodetection code based on the i2c addr */
-	if (!no_autodetect) {
-		switch (client->addr) {
-		case 0x10:
-			if (tuner_symbol_probe(tea5761_autodetection,
-					       t->i2c->adapter,
-					       t->i2c->addr) >= 0) {
-				t->type = TUNER_TEA5761;
-				t->mode_mask = T_RADIO;
-				t->mode = T_STANDBY;
-				/* Sets freq to FM range */
-				t->radio_freq = 87.5 * 16000;
-				tuner_lookup(t->i2c->adapter, &radio, &tv);
-				if (tv)
-					tv->mode_mask &= ~T_RADIO;
-
-				goto register_client;
-			}
-			kfree(t);
-			return -ENODEV;
-		case 0x42:
-		case 0x43:
-		case 0x4a:
-		case 0x4b:
-			/* If chip is not tda8290, don't register.
-			   since it can be tda9887*/
-			if (tuner_symbol_probe(tda829x_probe, t->i2c->adapter,
-					       t->i2c->addr) >= 0) {
-				tuner_dbg("tda829x detected\n");
-			} else {
-				/* Default is being tda9887 */
-				t->type = TUNER_TDA9887;
-				t->mode_mask = T_RADIO | T_ANALOG_TV |
-					       T_DIGITAL_TV;
-				t->mode = T_STANDBY;
-				goto register_client;
-			}
-			break;
-		case 0x60:
-			if (tuner_symbol_probe(tea5767_autodetection,
-					       t->i2c->adapter, t->i2c->addr)
-					>= 0) {
-				t->type = TUNER_TEA5767;
-				t->mode_mask = T_RADIO;
-				t->mode = T_STANDBY;
-				/* Sets freq to FM range */
-				t->radio_freq = 87.5 * 16000;
-				tuner_lookup(t->i2c->adapter, &radio, &tv);
-				if (tv)
-					tv->mode_mask &= ~T_RADIO;
-
-				goto register_client;
-			}
-			break;
-		}
-	}
-
-	/* Initializes only the first TV tuner on this adapter. Why only the
-	   first? Because there are some devices (notably the ones with TI
-	   tuners) that have more than one i2c address for the *same* device.
-	   Experience shows that, except for just one case, the first
-	   address is the right one. The exception is a Russian tuner
-	   (ACORP_Y878F). So, the desired behavior is just to enable the
-	   first found TV tuner. */
-	tuner_lookup(t->i2c->adapter, &radio, &tv);
-	if (tv == NULL) {
-		t->mode_mask = T_ANALOG_TV | T_DIGITAL_TV;
-		if (radio == NULL)
-			t->mode_mask |= T_RADIO;
-		tuner_dbg("Setting mode_mask to 0x%02x\n", t->mode_mask);
-		t->tv_freq = 400 * 16; /* Sets freq to VHF High */
-		t->radio_freq = 87.5 * 16000; /* Sets freq to FM range */
-	}
 
-	/* Should be just before return */
-register_client:
-	tuner_info("chip found @ 0x%x (%s)\n", client->addr << 1,
-		       client->adapter->name);
-
-	/* Sets a default mode */
-	if (t->mode_mask & T_ANALOG_TV) {
-		t->mode = V4L2_TUNER_ANALOG_TV;
-	} else  if (t->mode_mask & T_RADIO) {
-		t->mode = V4L2_TUNER_RADIO;
-	} else {
-		t->mode = V4L2_TUNER_DIGITAL_TV;
-	}
-	set_type(client, t->type, t->mode_mask, t->config, t->fe.callback);
-	list_add_tail(&t->list, &tuner_list);
-	return 0;
-}
-
-static int tuner_remove(struct i2c_client *client)
-{
-	struct tuner *t = to_tuner(i2c_get_clientdata(client));
-
-	v4l2_device_unregister_subdev(&t->sd);
-	tuner_detach(&t->fe);
-	t->fe.analog_demod_priv = NULL;
-
-	list_del(&t->list);
-	kfree(t);
-	return 0;
-}
-
-/* ----------------------------------------------------------------------- */
-
-/* This driver supports many devices and the idea is to let the driver
-   detect which device is present. So rather than listing all supported
-   devices here, we pretend to support a single, fake device type. */
 static const struct i2c_device_id tuner_id[] = {
 	{ "tuner", }, /* autodetect */
 	{ }
@@ -1196,10 +1301,6 @@
 module_init(init_tuner);
 module_exit(exit_tuner);
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
+MODULE_DESCRIPTION("device driver for various TV and TV+FM radio tuners");
+MODULE_AUTHOR("Ralph Metzler, Gerd Knorr, Gunther Mayer");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tvaudio.c linux-libre-2.6.39-gnu/drivers/media/video/tvaudio.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tvaudio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tvaudio.c	2011-05-19 00:06:34.000000000 -0400
@@ -1058,11 +1058,11 @@
 #define TDA9875_MVR         0x1b  /* Main volume droite */
 #define TDA9875_MBA         0x1d  /* Main Basse */
 #define TDA9875_MTR         0x1e  /* Main treble */
-#define TDA9875_ACS         0x1f  /* Auxilary channel select (FM) 0b0000000*/
-#define TDA9875_AVL         0x20  /* Auxilary volume gauche */
-#define TDA9875_AVR         0x21  /* Auxilary volume droite */
-#define TDA9875_ABA         0x22  /* Auxilary Basse */
-#define TDA9875_ATR         0x23  /* Auxilary treble */
+#define TDA9875_ACS         0x1f  /* Auxiliary channel select (FM) 0b0000000*/
+#define TDA9875_AVL         0x20  /* Auxiliary volume gauche */
+#define TDA9875_AVR         0x21  /* Auxiliary volume droite */
+#define TDA9875_ABA         0x22  /* Auxiliary Basse */
+#define TDA9875_ATR         0x23  /* Auxiliary treble */
 
 #define TDA9875_MSR         0x02  /* Monitor select register */
 #define TDA9875_C1MSB       0x03  /* Carrier 1 (FM) frequency register MSB */
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tvp514x.c linux-libre-2.6.39-gnu/drivers/media/video/tvp514x.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tvp514x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tvp514x.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,6 +37,7 @@
 #include <media/v4l2-common.h>
 #include <media/v4l2-mediabus.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 #include <media/tvp514x.h>
 
 #include "tvp514x_regs.h"
@@ -97,6 +98,7 @@
  */
 struct tvp514x_decoder {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	struct tvp514x_reg tvp514x_regs[ARRAY_SIZE(tvp514x_reg_list_default)];
 	const struct tvp514x_platform_data *pdata;
 
@@ -238,6 +240,11 @@
 	return container_of(sd, struct tvp514x_decoder, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tvp514x_decoder, hdl)->sd;
+}
+
 
 /**
  * tvp514x_read_reg() - Read a value from a register in an TVP5146/47.
@@ -719,213 +726,54 @@
 }
 
 /**
- * tvp514x_queryctrl() - V4L2 decoder interface handler for queryctrl
- * @sd: pointer to standard V4L2 sub-device structure
- * @qctrl: standard V4L2 v4l2_queryctrl structure
- *
- * If the requested control is supported, returns the control information.
- * Otherwise, returns -EINVAL if the control is not supported.
- */
-static int
-tvp514x_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qctrl)
-{
-	int err = -EINVAL;
-
-	if (qctrl == NULL)
-		return err;
-
-	switch (qctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		/* Brightness supported is (0-255), */
-		err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128);
-		break;
-	case V4L2_CID_CONTRAST:
-	case V4L2_CID_SATURATION:
-		/**
-		 * Saturation and Contrast supported is -
-		 *	Contrast: 0 - 255 (Default - 128)
-		 *	Saturation: 0 - 255 (Default - 128)
-		 */
-		err = v4l2_ctrl_query_fill(qctrl, 0, 255, 1, 128);
-		break;
-	case V4L2_CID_HUE:
-		/* Hue Supported is -
-		 *	Hue - -180 - +180 (Default - 0, Step - +180)
-		 */
-		err = v4l2_ctrl_query_fill(qctrl, -180, 180, 180, 0);
-		break;
-	case V4L2_CID_AUTOGAIN:
-		/**
-		 * Auto Gain supported is -
-		 * 	0 - 1 (Default - 1)
-		 */
-		err = v4l2_ctrl_query_fill(qctrl, 0, 1, 1, 1);
-		break;
-	default:
-		v4l2_err(sd, "invalid control id %d\n", qctrl->id);
-		return err;
-	}
-
-	v4l2_dbg(1, debug, sd, "Query Control:%s: Min - %d, Max - %d, Def - %d\n",
-			qctrl->name, qctrl->minimum, qctrl->maximum,
-			qctrl->default_value);
-
-	return err;
-}
-
-/**
- * tvp514x_g_ctrl() - V4L2 decoder interface handler for g_ctrl
- * @sd: pointer to standard V4L2 sub-device structure
- * @ctrl: pointer to v4l2_control structure
- *
- * If the requested control is supported, returns the control's current
- * value from the decoder. Otherwise, returns -EINVAL if the control is not
- * supported.
- */
-static int
-tvp514x_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct tvp514x_decoder *decoder = to_decoder(sd);
-
-	if (ctrl == NULL)
-		return -EINVAL;
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = decoder->tvp514x_regs[REG_BRIGHTNESS].val;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = decoder->tvp514x_regs[REG_CONTRAST].val;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = decoder->tvp514x_regs[REG_SATURATION].val;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = decoder->tvp514x_regs[REG_HUE].val;
-		if (ctrl->value == 0x7F)
-			ctrl->value = 180;
-		else if (ctrl->value == 0x80)
-			ctrl->value = -180;
-		else
-			ctrl->value = 0;
-
-		break;
-	case V4L2_CID_AUTOGAIN:
-		ctrl->value = decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val;
-		if ((ctrl->value & 0x3) == 3)
-			ctrl->value = 1;
-		else
-			ctrl->value = 0;
-
-		break;
-	default:
-		v4l2_err(sd, "invalid control id %d\n", ctrl->id);
-		return -EINVAL;
-	}
-
-	v4l2_dbg(1, debug, sd, "Get Control: ID - %d - %d\n",
-			ctrl->id, ctrl->value);
-	return 0;
-}
-
-/**
  * tvp514x_s_ctrl() - V4L2 decoder interface handler for s_ctrl
- * @sd: pointer to standard V4L2 sub-device structure
- * @ctrl: pointer to v4l2_control structure
+ * @ctrl: pointer to v4l2_ctrl structure
  *
  * If the requested control is supported, sets the control's current
  * value in HW. Otherwise, returns -EINVAL if the control is not supported.
  */
-static int
-tvp514x_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tvp514x_s_ctrl(struct v4l2_ctrl *ctrl)
 {
+	struct v4l2_subdev *sd = to_sd(ctrl);
 	struct tvp514x_decoder *decoder = to_decoder(sd);
 	int err = -EINVAL, value;
 
-	if (ctrl == NULL)
-		return err;
-
-	value = ctrl->value;
+	value = ctrl->val;
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		if (ctrl->value < 0 || ctrl->value > 255) {
-			v4l2_err(sd, "invalid brightness setting %d\n",
-					ctrl->value);
-			return -ERANGE;
-		}
-		err = tvp514x_write_reg(sd, REG_BRIGHTNESS,
-				value);
-		if (err)
-			return err;
-
-		decoder->tvp514x_regs[REG_BRIGHTNESS].val = value;
+		err = tvp514x_write_reg(sd, REG_BRIGHTNESS, value);
+		if (!err)
+			decoder->tvp514x_regs[REG_BRIGHTNESS].val = value;
 		break;
 	case V4L2_CID_CONTRAST:
-		if (ctrl->value < 0 || ctrl->value > 255) {
-			v4l2_err(sd, "invalid contrast setting %d\n",
-					ctrl->value);
-			return -ERANGE;
-		}
 		err = tvp514x_write_reg(sd, REG_CONTRAST, value);
-		if (err)
-			return err;
-
-		decoder->tvp514x_regs[REG_CONTRAST].val = value;
+		if (!err)
+			decoder->tvp514x_regs[REG_CONTRAST].val = value;
 		break;
 	case V4L2_CID_SATURATION:
-		if (ctrl->value < 0 || ctrl->value > 255) {
-			v4l2_err(sd, "invalid saturation setting %d\n",
-					ctrl->value);
-			return -ERANGE;
-		}
 		err = tvp514x_write_reg(sd, REG_SATURATION, value);
-		if (err)
-			return err;
-
-		decoder->tvp514x_regs[REG_SATURATION].val = value;
+		if (!err)
+			decoder->tvp514x_regs[REG_SATURATION].val = value;
 		break;
 	case V4L2_CID_HUE:
 		if (value == 180)
 			value = 0x7F;
 		else if (value == -180)
 			value = 0x80;
-		else if (value == 0)
-			value = 0;
-		else {
-			v4l2_err(sd, "invalid hue setting %d\n", ctrl->value);
-			return -ERANGE;
-		}
 		err = tvp514x_write_reg(sd, REG_HUE, value);
-		if (err)
-			return err;
-
-		decoder->tvp514x_regs[REG_HUE].val = value;
+		if (!err)
+			decoder->tvp514x_regs[REG_HUE].val = value;
 		break;
 	case V4L2_CID_AUTOGAIN:
-		if (value == 1)
-			value = 0x0F;
-		else if (value == 0)
-			value = 0x0C;
-		else {
-			v4l2_err(sd, "invalid auto gain setting %d\n",
-					ctrl->value);
-			return -ERANGE;
-		}
-		err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value);
-		if (err)
-			return err;
-
-		decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value;
+		err = tvp514x_write_reg(sd, REG_AFE_GAIN_CTRL, value ? 0x0f : 0x0c);
+		if (!err)
+			decoder->tvp514x_regs[REG_AFE_GAIN_CTRL].val = value;
 		break;
-	default:
-		v4l2_err(sd, "invalid control id %d\n", ctrl->id);
-		return err;
 	}
 
 	v4l2_dbg(1, debug, sd, "Set Control: ID - %d - %d\n",
-			ctrl->id, ctrl->value);
-
+			ctrl->id, ctrl->val);
 	return err;
 }
 
@@ -1104,10 +952,18 @@
 	return err;
 }
 
-static const struct v4l2_subdev_core_ops tvp514x_core_ops = {
-	.queryctrl = tvp514x_queryctrl,
-	.g_ctrl = tvp514x_g_ctrl,
+static const struct v4l2_ctrl_ops tvp514x_ctrl_ops = {
 	.s_ctrl = tvp514x_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops tvp514x_core_ops = {
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 	.s_std = tvp514x_s_std,
 };
 
@@ -1190,6 +1046,27 @@
 	sd = &decoder->sd;
 	v4l2_i2c_subdev_init(sd, client, &tvp514x_ops);
 
+	v4l2_ctrl_handler_init(&decoder->hdl, 5);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_HUE, -180, 180, 180, 0);
+	v4l2_ctrl_new_std(&decoder->hdl, &tvp514x_ctrl_ops,
+		V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
+
 	v4l2_info(sd, "%s decoder driver registered !!\n", sd->name);
 
 	return 0;
@@ -1209,6 +1086,7 @@
 	struct tvp514x_decoder *decoder = to_decoder(sd);
 
 	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
 	kfree(decoder);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tvp5150.c linux-libre-2.6.39-gnu/drivers/media/video/tvp5150.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tvp5150.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tvp5150.c	2011-05-19 00:06:34.000000000 -0400
@@ -12,6 +12,7 @@
 #include <media/v4l2-device.h>
 #include <media/tvp5150.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 #include "tvp5150_reg.h"
 
@@ -24,58 +25,14 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
-/* supported controls */
-static struct v4l2_queryctrl tvp5150_qctrl[] = {
-	{
-		.id = V4L2_CID_BRIGHTNESS,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Brightness",
-		.minimum = 0,
-		.maximum = 255,
-		.step = 1,
-		.default_value = 128,
-		.flags = 0,
-	}, {
-		.id = V4L2_CID_CONTRAST,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Contrast",
-		.minimum = 0,
-		.maximum = 255,
-		.step = 0x1,
-		.default_value = 128,
-		.flags = 0,
-	}, {
-		 .id = V4L2_CID_SATURATION,
-		 .type = V4L2_CTRL_TYPE_INTEGER,
-		 .name = "Saturation",
-		 .minimum = 0,
-		 .maximum = 255,
-		 .step = 0x1,
-		 .default_value = 128,
-		 .flags = 0,
-	}, {
-		.id = V4L2_CID_HUE,
-		.type = V4L2_CTRL_TYPE_INTEGER,
-		.name = "Hue",
-		.minimum = -128,
-		.maximum = 127,
-		.step = 0x1,
-		.default_value = 0,
-		.flags = 0,
-	}
-};
-
 struct tvp5150 {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 
 	v4l2_std_id norm;	/* Current set standard */
 	u32 input;
 	u32 output;
 	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
 static inline struct tvp5150 *to_tvp5150(struct v4l2_subdev *sd)
@@ -83,6 +40,11 @@
 	return container_of(sd, struct tvp5150, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tvp5150, hdl)->sd;
+}
+
 static int tvp5150_read(struct v4l2_subdev *sd, unsigned char addr)
 {
 	struct i2c_client *c = v4l2_get_subdevdata(sd);
@@ -775,27 +737,6 @@
 static int tvp5150_reset(struct v4l2_subdev *sd, u32 val)
 {
 	struct tvp5150 *decoder = to_tvp5150(sd);
-	u8 msb_id, lsb_id, msb_rom, lsb_rom;
-
-	msb_id = tvp5150_read(sd, TVP5150_MSB_DEV_ID);
-	lsb_id = tvp5150_read(sd, TVP5150_LSB_DEV_ID);
-	msb_rom = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER);
-	lsb_rom = tvp5150_read(sd, TVP5150_ROM_MINOR_VER);
-
-	if (msb_rom == 4 && lsb_rom == 0) { /* Is TVP5150AM1 */
-		v4l2_info(sd, "tvp%02x%02xam1 detected.\n", msb_id, lsb_id);
-
-		/* ITU-T BT.656.4 timing */
-		tvp5150_write(sd, TVP5150_REV_SELECT, 0);
-	} else {
-		if (msb_rom == 3 || lsb_rom == 0x21) { /* Is TVP5150A */
-			v4l2_info(sd, "tvp%02x%02xa detected.\n", msb_id, lsb_id);
-		} else {
-			v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
-					msb_id, lsb_id);
-			v4l2_info(sd, "*** Rom ver is %d.%d\n", msb_rom, lsb_rom);
-		}
-	}
 
 	/* Initializes TVP5150 to its default values */
 	tvp5150_write_inittab(sd, tvp5150_init_default);
@@ -810,64 +751,28 @@
 	tvp5150_write_inittab(sd, tvp5150_init_enable);
 
 	/* Initialize image preferences */
-	tvp5150_write(sd, TVP5150_BRIGHT_CTL, decoder->bright);
-	tvp5150_write(sd, TVP5150_CONTRAST_CTL, decoder->contrast);
-	tvp5150_write(sd, TVP5150_SATURATION_CTL, decoder->contrast);
-	tvp5150_write(sd, TVP5150_HUE_CTL, decoder->hue);
+	v4l2_ctrl_handler_setup(&decoder->hdl);
 
 	tvp5150_set_std(sd, decoder->norm);
 	return 0;
 };
 
-static int tvp5150_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	v4l2_dbg(1, debug, sd, "g_ctrl called\n");
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = tvp5150_read(sd, TVP5150_BRIGHT_CTL);
-		return 0;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = tvp5150_read(sd, TVP5150_CONTRAST_CTL);
-		return 0;
-	case V4L2_CID_SATURATION:
-		ctrl->value = tvp5150_read(sd, TVP5150_SATURATION_CTL);
-		return 0;
-	case V4L2_CID_HUE:
-		ctrl->value = tvp5150_read(sd, TVP5150_HUE_CTL);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int tvp5150_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tvp5150_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	u8 i, n;
-	n = ARRAY_SIZE(tvp5150_qctrl);
-
-	for (i = 0; i < n; i++) {
-		if (ctrl->id != tvp5150_qctrl[i].id)
-			continue;
-		if (ctrl->value < tvp5150_qctrl[i].minimum ||
-		    ctrl->value > tvp5150_qctrl[i].maximum)
-			return -ERANGE;
-		v4l2_dbg(1, debug, sd, "s_ctrl: id=%d, value=%d\n",
-					ctrl->id, ctrl->value);
-		break;
-	}
+	struct v4l2_subdev *sd = to_sd(ctrl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->value);
+		tvp5150_write(sd, TVP5150_BRIGHT_CTL, ctrl->val);
 		return 0;
 	case V4L2_CID_CONTRAST:
-		tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->value);
+		tvp5150_write(sd, TVP5150_CONTRAST_CTL, ctrl->val);
 		return 0;
 	case V4L2_CID_SATURATION:
-		tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->value);
+		tvp5150_write(sd, TVP5150_SATURATION_CTL, ctrl->val);
 		return 0;
 	case V4L2_CID_HUE:
-		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->value);
+		tvp5150_write(sd, TVP5150_HUE_CTL, ctrl->val);
 		return 0;
 	}
 	return -EINVAL;
@@ -995,29 +900,21 @@
 	return 0;
 }
 
-static int tvp5150_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(tvp5150_qctrl); i++)
-		if (qc->id && qc->id == tvp5150_qctrl[i].id) {
-			memcpy(qc, &(tvp5150_qctrl[i]),
-			       sizeof(*qc));
-			return 0;
-		}
-
-	return -EINVAL;
-}
-
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops tvp5150_ctrl_ops = {
+	.s_ctrl = tvp5150_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops tvp5150_core_ops = {
 	.log_status = tvp5150_log_status,
-	.g_ctrl = tvp5150_g_ctrl,
-	.s_ctrl = tvp5150_s_ctrl,
-	.queryctrl = tvp5150_queryctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 	.s_std = tvp5150_s_std,
 	.reset = tvp5150_reset,
 	.g_chip_ident = tvp5150_g_chip_ident,
@@ -1059,6 +956,7 @@
 {
 	struct tvp5150 *core;
 	struct v4l2_subdev *sd;
+	u8 msb_id, lsb_id, msb_rom, lsb_rom;
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(c->adapter,
@@ -1074,13 +972,48 @@
 	v4l_info(c, "chip found @ 0x%02x (%s)\n",
 		 c->addr << 1, c->adapter->name);
 
+	msb_id = tvp5150_read(sd, TVP5150_MSB_DEV_ID);
+	lsb_id = tvp5150_read(sd, TVP5150_LSB_DEV_ID);
+	msb_rom = tvp5150_read(sd, TVP5150_ROM_MAJOR_VER);
+	lsb_rom = tvp5150_read(sd, TVP5150_ROM_MINOR_VER);
+
+	if (msb_rom == 4 && lsb_rom == 0) { /* Is TVP5150AM1 */
+		v4l2_info(sd, "tvp%02x%02xam1 detected.\n", msb_id, lsb_id);
+
+		/* ITU-T BT.656.4 timing */
+		tvp5150_write(sd, TVP5150_REV_SELECT, 0);
+	} else {
+		if (msb_rom == 3 || lsb_rom == 0x21) { /* Is TVP5150A */
+			v4l2_info(sd, "tvp%02x%02xa detected.\n", msb_id, lsb_id);
+		} else {
+			v4l2_info(sd, "*** unknown tvp%02x%02x chip detected.\n",
+					msb_id, lsb_id);
+			v4l2_info(sd, "*** Rom ver is %d.%d\n", msb_rom, lsb_rom);
+		}
+	}
+
 	core->norm = V4L2_STD_ALL;	/* Default is autodetect */
 	core->input = TVP5150_COMPOSITE1;
 	core->enable = 1;
-	core->bright = 128;
-	core->contrast = 128;
-	core->hue = 0;
-	core->sat = 128;
+
+	v4l2_ctrl_handler_init(&core->hdl, 4);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 128);
+	v4l2_ctrl_new_std(&core->hdl, &tvp5150_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	sd->ctrl_handler = &core->hdl;
+	if (core->hdl.error) {
+		int err = core->hdl.error;
+
+		v4l2_ctrl_handler_free(&core->hdl);
+		kfree(core);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&core->hdl);
 
 	if (debug > 1)
 		tvp5150_log_status(sd);
@@ -1090,12 +1023,14 @@
 static int tvp5150_remove(struct i2c_client *c)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(c);
+	struct tvp5150 *decoder = to_tvp5150(sd);
 
 	v4l2_dbg(1, debug, sd,
 		"tvp5150.c: removing tvp5150 adapter on address 0x%x\n",
 		c->addr << 1);
 
 	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&decoder->hdl);
 	kfree(to_tvp5150(sd));
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/tvp7002.c linux-libre-2.6.39-gnu/drivers/media/video/tvp7002.c
--- linux-libre-2.6.38-gnu/drivers/media/video/tvp7002.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/tvp7002.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
 #include "tvp7002_reg.h"
 
 MODULE_DESCRIPTION("TI TVP7002 Video and Graphics Digitizer driver");
@@ -421,13 +422,13 @@
 /* Device definition */
 struct tvp7002 {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	const struct tvp7002_config *pdata;
 
 	int ver;
 	int streaming;
 
 	const struct tvp7002_preset_definition *current_preset;
-	u8 gain;
 };
 
 /*
@@ -441,6 +442,11 @@
 	return container_of(sd, struct tvp7002, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct tvp7002, hdl)->sd;
+}
+
 /*
  * tvp7002_read - Read a value from a register in an TVP7002
  * @sd: ptr to v4l2_subdev struct
@@ -606,78 +612,25 @@
 }
 
 /*
- * tvp7002_g_ctrl() - Get a control
- * @sd: ptr to v4l2_subdev struct
- * @ctrl: ptr to v4l2_control struct
- *
- * Get a control for a TVP7002 decoder device.
- * Returns zero when successful or -EINVAL if register access fails.
- */
-static int tvp7002_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct tvp7002 *device = to_tvp7002(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_GAIN:
-		ctrl->value = device->gain;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-/*
  * tvp7002_s_ctrl() - Set a control
- * @sd: ptr to v4l2_subdev struct
- * @ctrl: ptr to v4l2_control struct
+ * @ctrl: ptr to v4l2_ctrl struct
  *
  * Set a control in TVP7002 decoder device.
  * Returns zero when successful or -EINVAL if register access fails.
  */
-static int tvp7002_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int tvp7002_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct tvp7002 *device = to_tvp7002(sd);
+	struct v4l2_subdev *sd = to_sd(ctrl);
 	int error = 0;
 
 	switch (ctrl->id) {
 	case V4L2_CID_GAIN:
-		tvp7002_write_err(sd, TVP7002_R_FINE_GAIN,
-						ctrl->value & 0xff, &error);
-		tvp7002_write_err(sd, TVP7002_G_FINE_GAIN,
-						ctrl->value & 0xff, &error);
-		tvp7002_write_err(sd, TVP7002_B_FINE_GAIN,
-						ctrl->value & 0xff, &error);
-
-		if (error < 0)
-			return error;
-
-		/* Set only after knowing there is no error */
-		device->gain = ctrl->value & 0xff;
-		return 0;
-	default:
-		return -EINVAL;
-	}
-}
-
-/*
- * tvp7002_queryctrl() - Query a control
- * @sd: ptr to v4l2_subdev struct
- * @qc: ptr to v4l2_queryctrl struct
- *
- * Query a control of a TVP7002 decoder device.
- * Returns zero when successful or -EINVAL if register read fails.
- */
-static int tvp7002_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_GAIN:
-		/*
-		 * Gain is supported [0-255, default=0, step=1]
-		 */
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 0);
-	default:
-		return -EINVAL;
+		tvp7002_write_err(sd, TVP7002_R_FINE_GAIN, ctrl->val, &error);
+		tvp7002_write_err(sd, TVP7002_G_FINE_GAIN, ctrl->val, &error);
+		tvp7002_write_err(sd, TVP7002_B_FINE_GAIN, ctrl->val, &error);
+		return error;
 	}
+	return -EINVAL;
 }
 
 /*
@@ -924,7 +877,7 @@
 					device->streaming ? "yes" : "no");
 
 	/* Print the current value of the gain control */
-	v4l2_info(sd, "Gain: %u\n", device->gain);
+	v4l2_ctrl_handler_log_status(&device->hdl, sd->name);
 
 	return 0;
 }
@@ -946,13 +899,21 @@
 	return v4l_fill_dv_preset_info(tvp7002_presets[preset->index].preset, preset);
 }
 
+static const struct v4l2_ctrl_ops tvp7002_ctrl_ops = {
+	.s_ctrl = tvp7002_s_ctrl,
+};
+
 /* V4L2 core operation handlers */
 static const struct v4l2_subdev_core_ops tvp7002_core_ops = {
 	.g_chip_ident = tvp7002_g_chip_ident,
 	.log_status = tvp7002_log_status,
-	.g_ctrl = tvp7002_g_ctrl,
-	.s_ctrl = tvp7002_s_ctrl,
-	.queryctrl = tvp7002_queryctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
 	.g_register = tvp7002_g_register,
 	.s_register = tvp7002_s_register,
@@ -977,12 +938,6 @@
 	.video = &tvp7002_video_ops,
 };
 
-static struct tvp7002 tvp7002_dev = {
-	.streaming = 0,
-	.current_preset = tvp7002_presets,
-	.gain = 0,
-};
-
 /*
  * tvp7002_probe - Probe a TVP7002 device
  * @c: ptr to i2c_client struct
@@ -1013,14 +968,14 @@
 		return -ENODEV;
 	}
 
-	device = kmalloc(sizeof(struct tvp7002), GFP_KERNEL);
+	device = kzalloc(sizeof(struct tvp7002), GFP_KERNEL);
 
 	if (!device)
 		return -ENOMEM;
 
-	*device = tvp7002_dev;
 	sd = &device->sd;
 	device->pdata = c->dev.platform_data;
+	device->current_preset = tvp7002_presets;
 
 	/* Tell v4l2 the device is ready */
 	v4l2_i2c_subdev_init(sd, c, &tvp7002_ops);
@@ -1060,6 +1015,19 @@
 	preset.preset = device->current_preset->preset;
 	error = tvp7002_s_dv_preset(sd, &preset);
 
+	v4l2_ctrl_handler_init(&device->hdl, 1);
+	v4l2_ctrl_new_std(&device->hdl, &tvp7002_ctrl_ops,
+			V4L2_CID_GAIN, 0, 255, 1, 0);
+	sd->ctrl_handler = &device->hdl;
+	if (device->hdl.error) {
+		int err = device->hdl.error;
+
+		v4l2_ctrl_handler_free(&device->hdl);
+		kfree(device);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&device->hdl);
+
 found_error:
 	if (error < 0)
 		kfree(device);
@@ -1083,6 +1051,7 @@
 				"on address 0x%x\n", c->addr);
 
 	v4l2_device_unregister_subdev(sd);
+	v4l2_ctrl_handler_free(&device->hdl);
 	kfree(device);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/upd64031a.c linux-libre-2.6.39-gnu/drivers/media/video/upd64031a.c
--- linux-libre-2.6.38-gnu/drivers/media/video/upd64031a.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/upd64031a.c	2011-05-19 00:06:34.000000000 -0400
@@ -230,7 +230,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct upd64031a_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	sd = &state->sd;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/upd64083.c linux-libre-2.6.39-gnu/drivers/media/video/upd64083.c
--- linux-libre-2.6.38-gnu/drivers/media/video/upd64083.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/upd64083.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,7 +202,7 @@
 	v4l_info(client, "chip found @ 0x%x (%s)\n",
 			client->addr << 1, client->adapter->name);
 
-	state = kmalloc(sizeof(struct upd64083_state), GFP_KERNEL);
+	state = kzalloc(sizeof(struct upd64083_state), GFP_KERNEL);
 	if (state == NULL)
 		return -ENOMEM;
 	sd = &state->sd;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_driver.c linux-libre-2.6.39-gnu/drivers/media/video/uvc/uvc_driver.c
--- linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/uvc/uvc_driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -1264,6 +1264,14 @@
 
 		break;
 
+	case UVC_OTT_VENDOR_SPECIFIC:
+	case UVC_OTT_DISPLAY:
+	case UVC_OTT_MEDIA_TRANSPORT_OUTPUT:
+		if (uvc_trace_param & UVC_TRACE_PROBE)
+			printk(" OT %d", entity->id);
+
+		break;
+
 	case UVC_TT_STREAMING:
 		if (UVC_ENTITY_IS_ITERM(entity)) {
 			if (uvc_trace_param & UVC_TRACE_PROBE)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_video.c linux-libre-2.6.39-gnu/drivers/media/video/uvc/uvc_video.c
--- linux-libre-2.6.38-gnu/drivers/media/video/uvc/uvc_video.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/uvc/uvc_video.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,15 +89,19 @@
 static void uvc_fixup_video_ctrl(struct uvc_streaming *stream,
 	struct uvc_streaming_control *ctrl)
 {
-	struct uvc_format *format;
+	struct uvc_format *format = NULL;
 	struct uvc_frame *frame = NULL;
 	unsigned int i;
 
-	if (ctrl->bFormatIndex <= 0 ||
-	    ctrl->bFormatIndex > stream->nformats)
-		return;
+	for (i = 0; i < stream->nformats; ++i) {
+		if (stream->format[i].index == ctrl->bFormatIndex) {
+			format = &stream->format[i];
+			break;
+		}
+	}
 
-	format = &stream->format[ctrl->bFormatIndex - 1];
+	if (format == NULL)
+		return;
 
 	for (i = 0; i < format->nframes; ++i) {
 		if (format->frame[i].bFrameIndex == ctrl->bFrameIndex) {
@@ -390,11 +394,11 @@
  *
  * uvc_video_decode_end is called with header data at the end of a bulk or
  * isochronous payload. It performs any additional header data processing and
- * returns 0 or a negative error code if an error occured. As header data have
+ * returns 0 or a negative error code if an error occurred. As header data have
  * already been processed by uvc_video_decode_start, this functions isn't
  * required to perform sanity checks a second time.
  *
- * For isochronous transfers where a payload is always transfered in a single
+ * For isochronous transfers where a payload is always transferred in a single
  * URB, the three functions will be called in a row.
  *
  * To let the decoder process header data and update its internal state even
@@ -654,7 +658,7 @@
 							    buf);
 		} while (ret == -EAGAIN);
 
-		/* If an error occured skip the rest of the payload. */
+		/* If an error occurred skip the rest of the payload. */
 		if (ret < 0 || buf == NULL) {
 			stream->bulk.skip_payload = 1;
 		} else {
@@ -817,7 +821,7 @@
 		return stream->urb_size / psize;
 
 	/* Compute the number of packets. Bulk endpoints might transfer UVC
-	 * payloads accross multiple URBs.
+	 * payloads across multiple URBs.
 	 */
 	npackets = DIV_ROUND_UP(size, psize);
 	if (npackets > UVC_MAX_PACKETS)
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-common.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-common.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-common.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,7 +59,6 @@
 #include <asm/pgtable.h>
 #include <asm/io.h>
 #include <asm/div64.h>
-#define __OLD_VIDIOC_ /* To allow fixing old calls*/
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ctrls.h>
@@ -81,69 +80,6 @@
  *  Video Standard Operations (contributed by Michael Schimek)
  */
 
-
-/* ----------------------------------------------------------------- */
-/* priority handling                                                 */
-
-#define V4L2_PRIO_VALID(val) (val == V4L2_PRIORITY_BACKGROUND   || \
-			      val == V4L2_PRIORITY_INTERACTIVE  || \
-			      val == V4L2_PRIORITY_RECORD)
-
-void v4l2_prio_init(struct v4l2_prio_state *global)
-{
-	memset(global, 0, sizeof(*global));
-}
-EXPORT_SYMBOL(v4l2_prio_init);
-
-int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
-		     enum v4l2_priority new)
-{
-	if (!V4L2_PRIO_VALID(new))
-		return -EINVAL;
-	if (*local == new)
-		return 0;
-
-	atomic_inc(&global->prios[new]);
-	if (V4L2_PRIO_VALID(*local))
-		atomic_dec(&global->prios[*local]);
-	*local = new;
-	return 0;
-}
-EXPORT_SYMBOL(v4l2_prio_change);
-
-void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local)
-{
-	v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT);
-}
-EXPORT_SYMBOL(v4l2_prio_open);
-
-void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local)
-{
-	if (V4L2_PRIO_VALID(local))
-		atomic_dec(&global->prios[local]);
-}
-EXPORT_SYMBOL(v4l2_prio_close);
-
-enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)
-{
-	if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0)
-		return V4L2_PRIORITY_RECORD;
-	if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0)
-		return V4L2_PRIORITY_INTERACTIVE;
-	if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0)
-		return V4L2_PRIORITY_BACKGROUND;
-	return V4L2_PRIORITY_UNSET;
-}
-EXPORT_SYMBOL(v4l2_prio_max);
-
-int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local)
-{
-	return (local < v4l2_prio_max(global)) ? -EBUSY : 0;
-}
-EXPORT_SYMBOL(v4l2_prio_check);
-
-/* ----------------------------------------------------------------- */
-
 /* Helper functions for control handling			     */
 
 /* Check for correctness of the ctrl's value based on the data from
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-compat-ioctl32.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-compat-ioctl32.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-compat-ioctl32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-compat-ioctl32.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,6 @@
  */
 
 #include <linux/compat.h>
-#define __OLD_VIDIOC_ /* To allow fixing old calls*/
 #include <linux/videodev2.h>
 #include <linux/module.h>
 #include <media/v4l2-ioctl.h>
@@ -97,6 +96,14 @@
 	return 0;
 }
 
+static inline int get_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+				struct v4l2_pix_format_mplane __user *up)
+{
+	if (copy_from_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+		return -EFAULT;
+	return 0;
+}
+
 static inline int put_v4l2_pix_format(struct v4l2_pix_format *kp, struct v4l2_pix_format __user *up)
 {
 	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format)))
@@ -104,6 +111,14 @@
 	return 0;
 }
 
+static inline int put_v4l2_pix_format_mplane(struct v4l2_pix_format_mplane *kp,
+				struct v4l2_pix_format_mplane __user *up)
+{
+	if (copy_to_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
+		return -EFAULT;
+	return 0;
+}
+
 static inline int get_v4l2_vbi_format(struct v4l2_vbi_format *kp, struct v4l2_vbi_format __user *up)
 {
 	if (copy_from_user(kp, up, sizeof(struct v4l2_vbi_format)))
@@ -136,6 +151,7 @@
 	enum v4l2_buf_type type;
 	union {
 		struct v4l2_pix_format	pix;
+		struct v4l2_pix_format_mplane	pix_mp;
 		struct v4l2_window32	win;
 		struct v4l2_vbi_format	vbi;
 		struct v4l2_sliced_vbi_format	sliced;
@@ -152,6 +168,10 @@
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
+						  &up->fmt.pix_mp);
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
@@ -181,6 +201,10 @@
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 		return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
+						  &up->fmt.pix_mp);
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 		return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
@@ -232,6 +256,17 @@
 	return 0;
 }
 
+struct v4l2_plane32 {
+	__u32			bytesused;
+	__u32			length;
+	union {
+		__u32		mem_offset;
+		compat_long_t	userptr;
+	} m;
+	__u32			data_offset;
+	__u32			reserved[11];
+};
+
 struct v4l2_buffer32 {
 	__u32			index;
 	enum v4l2_buf_type      type;
@@ -247,14 +282,64 @@
 	union {
 		__u32           offset;
 		compat_long_t   userptr;
+		compat_caddr_t  planes;
 	} m;
 	__u32			length;
 	__u32			input;
 	__u32			reserved;
 };
 
+static int get_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
+				enum v4l2_memory memory)
+{
+	void __user *up_pln;
+	compat_long_t p;
+
+	if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
+		copy_in_user(&up->data_offset, &up32->data_offset,
+				sizeof(__u32)))
+		return -EFAULT;
+
+	if (memory == V4L2_MEMORY_USERPTR) {
+		if (get_user(p, &up32->m.userptr))
+			return -EFAULT;
+		up_pln = compat_ptr(p);
+		if (put_user((unsigned long)up_pln, &up->m.userptr))
+			return -EFAULT;
+	} else {
+		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
+					sizeof(__u32)))
+			return -EFAULT;
+	}
+
+	return 0;
+}
+
+static int put_v4l2_plane32(struct v4l2_plane *up, struct v4l2_plane32 *up32,
+				enum v4l2_memory memory)
+{
+	if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
+		copy_in_user(&up32->data_offset, &up->data_offset,
+				sizeof(__u32)))
+		return -EFAULT;
+
+	/* For MMAP, driver might've set up the offset, so copy it back.
+	 * USERPTR stays the same (was userspace-provided), so no copying. */
+	if (memory == V4L2_MEMORY_MMAP)
+		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
+					sizeof(__u32)))
+			return -EFAULT;
+
+	return 0;
+}
+
 static int get_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
 {
+	struct v4l2_plane32 __user *uplane32;
+	struct v4l2_plane __user *uplane;
+	compat_caddr_t p;
+	int num_planes;
+	int ret;
 
 	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
 		get_user(kp->index, &up->index) ||
@@ -263,33 +348,84 @@
 		get_user(kp->memory, &up->memory) ||
 		get_user(kp->input, &up->input))
 			return -EFAULT;
-	switch (kp->memory) {
-	case V4L2_MEMORY_MMAP:
-		if (get_user(kp->length, &up->length) ||
-			get_user(kp->m.offset, &up->m.offset))
+
+	if (V4L2_TYPE_IS_OUTPUT(kp->type))
+		if (get_user(kp->bytesused, &up->bytesused) ||
+			get_user(kp->field, &up->field) ||
+			get_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
+			get_user(kp->timestamp.tv_usec,
+					&up->timestamp.tv_usec))
 			return -EFAULT;
-		break;
-	case V4L2_MEMORY_USERPTR:
-		{
-		compat_long_t tmp;
 
-		if (get_user(kp->length, &up->length) ||
-		    get_user(tmp, &up->m.userptr))
+	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+		if (get_user(kp->length, &up->length))
 			return -EFAULT;
 
-		kp->m.userptr = (unsigned long)compat_ptr(tmp);
+		num_planes = kp->length;
+		if (num_planes == 0) {
+			kp->m.planes = NULL;
+			/* num_planes == 0 is legal, e.g. when userspace doesn't
+			 * need planes array on DQBUF*/
+			return 0;
 		}
-		break;
-	case V4L2_MEMORY_OVERLAY:
-		if (get_user(kp->m.offset, &up->m.offset))
+
+		if (get_user(p, &up->m.planes))
 			return -EFAULT;
-		break;
+
+		uplane32 = compat_ptr(p);
+		if (!access_ok(VERIFY_READ, uplane32,
+				num_planes * sizeof(struct v4l2_plane32)))
+			return -EFAULT;
+
+		/* We don't really care if userspace decides to kill itself
+		 * by passing a very big num_planes value */
+		uplane = compat_alloc_user_space(num_planes *
+						sizeof(struct v4l2_plane));
+		kp->m.planes = uplane;
+
+		while (--num_planes >= 0) {
+			ret = get_v4l2_plane32(uplane, uplane32, kp->memory);
+			if (ret)
+				return ret;
+			++uplane;
+			++uplane32;
+		}
+	} else {
+		switch (kp->memory) {
+		case V4L2_MEMORY_MMAP:
+			if (get_user(kp->length, &up->length) ||
+				get_user(kp->m.offset, &up->m.offset))
+				return -EFAULT;
+			break;
+		case V4L2_MEMORY_USERPTR:
+			{
+			compat_long_t tmp;
+
+			if (get_user(kp->length, &up->length) ||
+			    get_user(tmp, &up->m.userptr))
+				return -EFAULT;
+
+			kp->m.userptr = (unsigned long)compat_ptr(tmp);
+			}
+			break;
+		case V4L2_MEMORY_OVERLAY:
+			if (get_user(kp->m.offset, &up->m.offset))
+				return -EFAULT;
+			break;
+		}
 	}
+
 	return 0;
 }
 
 static int put_v4l2_buffer32(struct v4l2_buffer *kp, struct v4l2_buffer32 __user *up)
 {
+	struct v4l2_plane32 __user *uplane32;
+	struct v4l2_plane __user *uplane;
+	compat_caddr_t p;
+	int num_planes;
+	int ret;
+
 	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
 		put_user(kp->index, &up->index) ||
 		put_user(kp->type, &up->type) ||
@@ -297,22 +433,7 @@
 		put_user(kp->memory, &up->memory) ||
 		put_user(kp->input, &up->input))
 			return -EFAULT;
-	switch (kp->memory) {
-	case V4L2_MEMORY_MMAP:
-		if (put_user(kp->length, &up->length) ||
-			put_user(kp->m.offset, &up->m.offset))
-			return -EFAULT;
-		break;
-	case V4L2_MEMORY_USERPTR:
-		if (put_user(kp->length, &up->length) ||
-			put_user(kp->m.userptr, &up->m.userptr))
-			return -EFAULT;
-		break;
-	case V4L2_MEMORY_OVERLAY:
-		if (put_user(kp->m.offset, &up->m.offset))
-			return -EFAULT;
-		break;
-	}
+
 	if (put_user(kp->bytesused, &up->bytesused) ||
 		put_user(kp->field, &up->field) ||
 		put_user(kp->timestamp.tv_sec, &up->timestamp.tv_sec) ||
@@ -321,6 +442,43 @@
 		put_user(kp->sequence, &up->sequence) ||
 		put_user(kp->reserved, &up->reserved))
 			return -EFAULT;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(kp->type)) {
+		num_planes = kp->length;
+		if (num_planes == 0)
+			return 0;
+
+		uplane = kp->m.planes;
+		if (get_user(p, &up->m.planes))
+			return -EFAULT;
+		uplane32 = compat_ptr(p);
+
+		while (--num_planes >= 0) {
+			ret = put_v4l2_plane32(uplane, uplane32, kp->memory);
+			if (ret)
+				return ret;
+			++uplane;
+			++uplane32;
+		}
+	} else {
+		switch (kp->memory) {
+		case V4L2_MEMORY_MMAP:
+			if (put_user(kp->length, &up->length) ||
+				put_user(kp->m.offset, &up->m.offset))
+				return -EFAULT;
+			break;
+		case V4L2_MEMORY_USERPTR:
+			if (put_user(kp->length, &up->length) ||
+				put_user(kp->m.userptr, &up->m.userptr))
+				return -EFAULT;
+			break;
+		case V4L2_MEMORY_OVERLAY:
+			if (put_user(kp->m.offset, &up->m.offset))
+				return -EFAULT;
+			break;
+		}
+	}
+
 	return 0;
 }
 
@@ -442,12 +600,13 @@
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
-	if (!access_ok(VERIFY_READ, ucontrols, n * sizeof(struct v4l2_ext_control)))
+	if (!access_ok(VERIFY_READ, ucontrols,
+			n * sizeof(struct v4l2_ext_control32)))
 		return -EFAULT;
 	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
 	kp->controls = kcontrols;
 	while (--n >= 0) {
-		if (copy_in_user(kcontrols, ucontrols, sizeof(*kcontrols)))
+		if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
 			return -EFAULT;
 		if (ctrl_is_pointer(kcontrols->id)) {
 			void __user *s;
@@ -483,7 +642,8 @@
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
-	if (!access_ok(VERIFY_WRITE, ucontrols, n * sizeof(struct v4l2_ext_control)))
+	if (!access_ok(VERIFY_WRITE, ucontrols,
+			n * sizeof(struct v4l2_ext_control32)))
 		return -EFAULT;
 
 	while (--n >= 0) {
@@ -517,9 +677,6 @@
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
 
 #define VIDIOC_OVERLAY32	_IOW ('V', 14, s32)
-#ifdef __OLD_VIDIOC_
-#define VIDIOC_OVERLAY32_OLD	_IOWR('V', 14, s32)
-#endif
 #define VIDIOC_STREAMON32	_IOW ('V', 18, s32)
 #define VIDIOC_STREAMOFF32	_IOW ('V', 19, s32)
 #define VIDIOC_G_INPUT32	_IOR ('V', 38, s32)
@@ -559,9 +716,6 @@
 	case VIDIOC_S_EXT_CTRLS32: cmd = VIDIOC_S_EXT_CTRLS; break;
 	case VIDIOC_TRY_EXT_CTRLS32: cmd = VIDIOC_TRY_EXT_CTRLS; break;
 	case VIDIOC_OVERLAY32: cmd = VIDIOC_OVERLAY; break;
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_OVERLAY32_OLD: cmd = VIDIOC_OVERLAY; break;
-#endif
 	case VIDIOC_STREAMON32: cmd = VIDIOC_STREAMON; break;
 	case VIDIOC_STREAMOFF32: cmd = VIDIOC_STREAMOFF; break;
 	case VIDIOC_G_INPUT32: cmd = VIDIOC_G_INPUT; break;
@@ -695,14 +849,6 @@
 		return ret;
 
 	switch (cmd) {
-#ifdef __OLD_VIDIOC_
-	case VIDIOC_OVERLAY32_OLD:
-	case VIDIOC_S_PARM_OLD:
-	case VIDIOC_S_CTRL_OLD:
-	case VIDIOC_G_AUDIO_OLD:
-	case VIDIOC_G_AUDOUT_OLD:
-	case VIDIOC_CROPCAP_OLD:
-#endif
 	case VIDIOC_QUERYCAP:
 	case VIDIOC_RESERVED:
 	case VIDIOC_ENUM_FMT:
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-ctrls.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-ctrls.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-ctrls.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-ctrls.c	2011-05-19 00:06:34.000000000 -0400
@@ -1364,6 +1364,8 @@
 
 int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
 {
+	if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+		return -EINVAL;
 	return v4l2_queryctrl(sd->ctrl_handler, qc);
 }
 EXPORT_SYMBOL(v4l2_subdev_queryctrl);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-dev.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-dev.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -143,6 +143,7 @@
 static void v4l2_device_release(struct device *cd)
 {
 	struct video_device *vdev = to_video_device(cd);
+	struct v4l2_device *v4l2_dev = vdev->v4l2_dev;
 
 	mutex_lock(&videodev_lock);
 	if (video_device[vdev->minor] != vdev) {
@@ -169,6 +170,10 @@
 	/* Release video_device and perform other
 	   cleanups as needed. */
 	vdev->release(vdev);
+
+	/* Decrease v4l2_device refcount */
+	if (v4l2_dev)
+		v4l2_device_put(v4l2_dev);
 }
 
 static struct class video_class = {
@@ -182,6 +187,70 @@
 }
 EXPORT_SYMBOL(video_devdata);
 
+
+/* Priority handling */
+
+static inline bool prio_is_valid(enum v4l2_priority prio)
+{
+	return prio == V4L2_PRIORITY_BACKGROUND ||
+	       prio == V4L2_PRIORITY_INTERACTIVE ||
+	       prio == V4L2_PRIORITY_RECORD;
+}
+
+void v4l2_prio_init(struct v4l2_prio_state *global)
+{
+	memset(global, 0, sizeof(*global));
+}
+EXPORT_SYMBOL(v4l2_prio_init);
+
+int v4l2_prio_change(struct v4l2_prio_state *global, enum v4l2_priority *local,
+		     enum v4l2_priority new)
+{
+	if (!prio_is_valid(new))
+		return -EINVAL;
+	if (*local == new)
+		return 0;
+
+	atomic_inc(&global->prios[new]);
+	if (prio_is_valid(*local))
+		atomic_dec(&global->prios[*local]);
+	*local = new;
+	return 0;
+}
+EXPORT_SYMBOL(v4l2_prio_change);
+
+void v4l2_prio_open(struct v4l2_prio_state *global, enum v4l2_priority *local)
+{
+	v4l2_prio_change(global, local, V4L2_PRIORITY_DEFAULT);
+}
+EXPORT_SYMBOL(v4l2_prio_open);
+
+void v4l2_prio_close(struct v4l2_prio_state *global, enum v4l2_priority local)
+{
+	if (prio_is_valid(local))
+		atomic_dec(&global->prios[local]);
+}
+EXPORT_SYMBOL(v4l2_prio_close);
+
+enum v4l2_priority v4l2_prio_max(struct v4l2_prio_state *global)
+{
+	if (atomic_read(&global->prios[V4L2_PRIORITY_RECORD]) > 0)
+		return V4L2_PRIORITY_RECORD;
+	if (atomic_read(&global->prios[V4L2_PRIORITY_INTERACTIVE]) > 0)
+		return V4L2_PRIORITY_INTERACTIVE;
+	if (atomic_read(&global->prios[V4L2_PRIORITY_BACKGROUND]) > 0)
+		return V4L2_PRIORITY_BACKGROUND;
+	return V4L2_PRIORITY_UNSET;
+}
+EXPORT_SYMBOL(v4l2_prio_max);
+
+int v4l2_prio_check(struct v4l2_prio_state *global, enum v4l2_priority local)
+{
+	return (local < v4l2_prio_max(global)) ? -EBUSY : 0;
+}
+EXPORT_SYMBOL(v4l2_prio_check);
+
+
 static ssize_t v4l2_read(struct file *filp, char __user *buf,
 		size_t sz, loff_t *off)
 {
@@ -303,6 +372,9 @@
 static int v4l2_open(struct inode *inode, struct file *filp)
 {
 	struct video_device *vdev;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	struct media_entity *entity = NULL;
+#endif
 	int ret = 0;
 
 	/* Check if the video device is available */
@@ -316,6 +388,17 @@
 	/* and increase the device refcount */
 	video_get(vdev);
 	mutex_unlock(&videodev_lock);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+	    vdev->vfl_type != VFL_TYPE_SUBDEV) {
+		entity = media_entity_get(&vdev->entity);
+		if (!entity) {
+			ret = -EBUSY;
+			video_put(vdev);
+			return ret;
+		}
+	}
+#endif
 	if (vdev->fops->open) {
 		if (vdev->lock && mutex_lock_interruptible(vdev->lock)) {
 			ret = -ERESTARTSYS;
@@ -331,8 +414,14 @@
 
 err:
 	/* decrease the refcount in case of an error */
-	if (ret)
+	if (ret) {
+#if defined(CONFIG_MEDIA_CONTROLLER)
+		if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+		    vdev->vfl_type != VFL_TYPE_SUBDEV)
+			media_entity_put(entity);
+#endif
 		video_put(vdev);
+	}
 	return ret;
 }
 
@@ -349,7 +438,11 @@
 		if (vdev->lock)
 			mutex_unlock(vdev->lock);
 	}
-
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+	    vdev->vfl_type != VFL_TYPE_SUBDEV)
+		media_entity_put(&vdev->entity);
+#endif
 	/* decrease the refcount unconditionally since the release()
 	   return value is ignored. */
 	video_put(vdev);
@@ -408,13 +501,14 @@
 }
 
 /**
- *	video_register_device - register video4linux devices
+ *	__video_register_device - register video4linux devices
  *	@vdev: video device structure we want to register
  *	@type: type of device to register
  *	@nr:   which device node number (0 == /dev/video0, 1 == /dev/video1, ...
  *             -1 == first free)
  *	@warn_if_nr_in_use: warn if the desired device node number
  *	       was already in use and another number was chosen instead.
+ *	@owner: module that owns the video device node
  *
  *	The registration code assigns minor numbers and device node numbers
  *	based on the requested type and registers the new device node with
@@ -435,9 +529,11 @@
  *	%VFL_TYPE_VBI - Vertical blank data (undecoded)
  *
  *	%VFL_TYPE_RADIO - A radio card
+ *
+ *	%VFL_TYPE_SUBDEV - A subdevice
  */
-static int __video_register_device(struct video_device *vdev, int type, int nr,
-		int warn_if_nr_in_use)
+int __video_register_device(struct video_device *vdev, int type, int nr,
+		int warn_if_nr_in_use, struct module *owner)
 {
 	int i = 0;
 	int ret;
@@ -469,6 +565,9 @@
 	case VFL_TYPE_RADIO:
 		name_base = "radio";
 		break;
+	case VFL_TYPE_SUBDEV:
+		name_base = "v4l-subdev";
+		break;
 	default:
 		printk(KERN_ERR "%s called with unknown type: %d\n",
 		       __func__, type);
@@ -482,6 +581,10 @@
 			vdev->parent = vdev->v4l2_dev->dev;
 		if (vdev->ctrl_handler == NULL)
 			vdev->ctrl_handler = vdev->v4l2_dev->ctrl_handler;
+		/* If the prio state pointer is NULL, then use the v4l2_device
+		   prio state. */
+		if (vdev->prio == NULL)
+			vdev->prio = &vdev->v4l2_dev->prio;
 	}
 
 	/* Part 2: find a free minor, device node number and device index. */
@@ -552,7 +655,7 @@
 		goto cleanup;
 	}
 	vdev->cdev->ops = &v4l2_fops;
-	vdev->cdev->owner = vdev->fops->owner;
+	vdev->cdev->owner = owner;
 	ret = cdev_add(vdev->cdev, MKDEV(VIDEO_MAJOR, vdev->minor), 1);
 	if (ret < 0) {
 		printk(KERN_ERR "%s: cdev_add failed\n", __func__);
@@ -580,11 +683,32 @@
 		printk(KERN_WARNING "%s: requested %s%d, got %s\n", __func__,
 			name_base, nr, video_device_node_name(vdev));
 
-	/* Part 5: Activate this minor. The char device can now be used. */
+	/* Increase v4l2_device refcount */
+	if (vdev->v4l2_dev)
+		v4l2_device_get(vdev->v4l2_dev);
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	/* Part 5: Register the entity. */
+	if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+	    vdev->vfl_type != VFL_TYPE_SUBDEV) {
+		vdev->entity.type = MEDIA_ENT_T_DEVNODE_V4L;
+		vdev->entity.name = vdev->name;
+		vdev->entity.v4l.major = VIDEO_MAJOR;
+		vdev->entity.v4l.minor = vdev->minor;
+		ret = media_device_register_entity(vdev->v4l2_dev->mdev,
+			&vdev->entity);
+		if (ret < 0)
+			printk(KERN_WARNING
+			       "%s: media_device_register_entity failed\n",
+			       __func__);
+	}
+#endif
+	/* Part 6: Activate this minor. The char device can now be used. */
 	set_bit(V4L2_FL_REGISTERED, &vdev->flags);
 	mutex_lock(&videodev_lock);
 	video_device[vdev->minor] = vdev;
 	mutex_unlock(&videodev_lock);
+
 	return 0;
 
 cleanup:
@@ -597,18 +721,7 @@
 	vdev->minor = -1;
 	return ret;
 }
-
-int video_register_device(struct video_device *vdev, int type, int nr)
-{
-	return __video_register_device(vdev, type, nr, 1);
-}
-EXPORT_SYMBOL(video_register_device);
-
-int video_register_device_no_warn(struct video_device *vdev, int type, int nr)
-{
-	return __video_register_device(vdev, type, nr, 0);
-}
-EXPORT_SYMBOL(video_register_device_no_warn);
+EXPORT_SYMBOL(__video_register_device);
 
 /**
  *	video_unregister_device - unregister a video4linux device
@@ -623,6 +736,12 @@
 	if (!vdev || !video_is_registered(vdev))
 		return;
 
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (vdev->v4l2_dev && vdev->v4l2_dev->mdev &&
+	    vdev->vfl_type != VFL_TYPE_SUBDEV)
+		media_device_unregister_entity(&vdev->entity);
+#endif
+
 	mutex_lock(&videodev_lock);
 	/* This must be in a critical section to prevent a race with v4l2_open.
 	 * Once this bit has been cleared video_get may never be called again.
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-device.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-device.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-device.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,8 @@
 	INIT_LIST_HEAD(&v4l2_dev->subdevs);
 	spin_lock_init(&v4l2_dev->lock);
 	mutex_init(&v4l2_dev->ioctl_lock);
+	v4l2_prio_init(&v4l2_dev->prio);
+	kref_init(&v4l2_dev->ref);
 	v4l2_dev->dev = dev;
 	if (dev == NULL) {
 		/* If dev == NULL, then name must be filled in by the caller */
@@ -47,13 +49,27 @@
 	if (!v4l2_dev->name[0])
 		snprintf(v4l2_dev->name, sizeof(v4l2_dev->name), "%s %s",
 			dev->driver->name, dev_name(dev));
-	if (dev_get_drvdata(dev))
-		v4l2_warn(v4l2_dev, "Non-NULL drvdata on register\n");
-	dev_set_drvdata(dev, v4l2_dev);
+	if (!dev_get_drvdata(dev))
+		dev_set_drvdata(dev, v4l2_dev);
 	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register);
 
+static void v4l2_device_release(struct kref *ref)
+{
+	struct v4l2_device *v4l2_dev =
+		container_of(ref, struct v4l2_device, ref);
+
+	if (v4l2_dev->release)
+		v4l2_dev->release(v4l2_dev);
+}
+
+int v4l2_device_put(struct v4l2_device *v4l2_dev)
+{
+	return kref_put(&v4l2_dev->ref, v4l2_device_release);
+}
+EXPORT_SYMBOL_GPL(v4l2_device_put);
+
 int v4l2_device_set_name(struct v4l2_device *v4l2_dev, const char *basename,
 						atomic_t *instance)
 {
@@ -72,10 +88,12 @@
 
 void v4l2_device_disconnect(struct v4l2_device *v4l2_dev)
 {
-	if (v4l2_dev->dev) {
+	if (v4l2_dev->dev == NULL)
+		return;
+
+	if (dev_get_drvdata(v4l2_dev->dev) == v4l2_dev)
 		dev_set_drvdata(v4l2_dev->dev, NULL);
-		v4l2_dev->dev = NULL;
-	}
+	v4l2_dev->dev = NULL;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_disconnect);
 
@@ -117,48 +135,116 @@
 EXPORT_SYMBOL_GPL(v4l2_device_unregister);
 
 int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
-						struct v4l2_subdev *sd)
+				struct v4l2_subdev *sd)
 {
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	struct media_entity *entity = &sd->entity;
+#endif
 	int err;
 
 	/* Check for valid input */
 	if (v4l2_dev == NULL || sd == NULL || !sd->name[0])
 		return -EINVAL;
+
 	/* Warn if we apparently re-register a subdev */
 	WARN_ON(sd->v4l2_dev != NULL);
+
 	if (!try_module_get(sd->owner))
 		return -ENODEV;
+
 	sd->v4l2_dev = v4l2_dev;
 	if (sd->internal_ops && sd->internal_ops->registered) {
 		err = sd->internal_ops->registered(sd);
-		if (err)
+		if (err) {
+			module_put(sd->owner);
 			return err;
+		}
 	}
+
 	/* This just returns 0 if either of the two args is NULL */
 	err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
 	if (err) {
 		if (sd->internal_ops && sd->internal_ops->unregistered)
 			sd->internal_ops->unregistered(sd);
+		module_put(sd->owner);
 		return err;
 	}
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	/* Register the entity. */
+	if (v4l2_dev->mdev) {
+		err = media_device_register_entity(v4l2_dev->mdev, entity);
+		if (err < 0) {
+			if (sd->internal_ops && sd->internal_ops->unregistered)
+				sd->internal_ops->unregistered(sd);
+			module_put(sd->owner);
+			return err;
+		}
+	}
+#endif
+
 	spin_lock(&v4l2_dev->lock);
 	list_add_tail(&sd->list, &v4l2_dev->subdevs);
 	spin_unlock(&v4l2_dev->lock);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(v4l2_device_register_subdev);
 
+int v4l2_device_register_subdev_nodes(struct v4l2_device *v4l2_dev)
+{
+	struct video_device *vdev;
+	struct v4l2_subdev *sd;
+	int err;
+
+	/* Register a device node for every subdev marked with the
+	 * V4L2_SUBDEV_FL_HAS_DEVNODE flag.
+	 */
+	list_for_each_entry(sd, &v4l2_dev->subdevs, list) {
+		if (!(sd->flags & V4L2_SUBDEV_FL_HAS_DEVNODE))
+			continue;
+
+		vdev = &sd->devnode;
+		strlcpy(vdev->name, sd->name, sizeof(vdev->name));
+		vdev->v4l2_dev = v4l2_dev;
+		vdev->fops = &v4l2_subdev_fops;
+		vdev->release = video_device_release_empty;
+		err = __video_register_device(vdev, VFL_TYPE_SUBDEV, -1, 1,
+					      sd->owner);
+		if (err < 0)
+			return err;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+		sd->entity.v4l.major = VIDEO_MAJOR;
+		sd->entity.v4l.minor = vdev->minor;
+#endif
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_device_register_subdev_nodes);
+
 void v4l2_device_unregister_subdev(struct v4l2_subdev *sd)
 {
+	struct v4l2_device *v4l2_dev;
+
 	/* return if it isn't registered */
 	if (sd == NULL || sd->v4l2_dev == NULL)
 		return;
-	spin_lock(&sd->v4l2_dev->lock);
+
+	v4l2_dev = sd->v4l2_dev;
+
+	spin_lock(&v4l2_dev->lock);
 	list_del(&sd->list);
-	spin_unlock(&sd->v4l2_dev->lock);
+	spin_unlock(&v4l2_dev->lock);
+
 	if (sd->internal_ops && sd->internal_ops->unregistered)
 		sd->internal_ops->unregistered(sd);
 	sd->v4l2_dev = NULL;
+
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (v4l2_dev->mdev)
+		media_device_unregister_entity(&sd->entity);
+#endif
+	video_unregister_device(&sd->devnode);
 	module_put(sd->owner);
 }
 EXPORT_SYMBOL_GPL(v4l2_device_unregister_subdev);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-fh.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-fh.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-fh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-fh.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
  */
 
 #include <linux/bitops.h>
+#include <linux/slab.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
@@ -33,6 +34,7 @@
 	fh->vdev = vdev;
 	INIT_LIST_HEAD(&fh->list);
 	set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
+	fh->prio = V4L2_PRIORITY_UNSET;
 
 	/*
 	 * fh->events only needs to be initialized if the driver
@@ -51,12 +53,28 @@
 {
 	unsigned long flags;
 
+	if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
+		v4l2_prio_open(fh->vdev->prio, &fh->prio);
 	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 	list_add(&fh->list, &fh->vdev->fh_list);
 	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_add);
 
+int v4l2_fh_open(struct file *filp)
+{
+	struct video_device *vdev = video_devdata(filp);
+	struct v4l2_fh *fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+
+	filp->private_data = fh;
+	if (fh == NULL)
+		return -ENOMEM;
+	v4l2_fh_init(fh, vdev);
+	v4l2_fh_add(fh);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_fh_open);
+
 void v4l2_fh_del(struct v4l2_fh *fh)
 {
 	unsigned long flags;
@@ -64,6 +82,8 @@
 	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
 	list_del_init(&fh->list);
 	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
+	if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
+		v4l2_prio_close(fh->vdev->prio, fh->prio);
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_del);
 
@@ -77,3 +97,30 @@
 	v4l2_event_free(fh);
 }
 EXPORT_SYMBOL_GPL(v4l2_fh_exit);
+
+int v4l2_fh_release(struct file *filp)
+{
+	struct v4l2_fh *fh = filp->private_data;
+
+	if (fh) {
+		v4l2_fh_del(fh);
+		v4l2_fh_exit(fh);
+		kfree(fh);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(v4l2_fh_release);
+
+int v4l2_fh_is_singular(struct v4l2_fh *fh)
+{
+	unsigned long flags;
+	int is_singular;
+
+	if (fh == NULL || fh->vdev == NULL)
+		return 0;
+	spin_lock_irqsave(&fh->vdev->fh_lock, flags);
+	is_singular = list_is_singular(&fh->list);
+	spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
+	return is_singular;
+}
+EXPORT_SYMBOL_GPL(v4l2_fh_is_singular);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-ioctl.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-ioctl.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 
-#define __OLD_VIDIOC_ /* To allow fixing old calls */
 #include <linux/videodev2.h>
 
 #include <media/v4l2-common.h>
@@ -25,6 +24,7 @@
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-fh.h>
 #include <media/v4l2-event.h>
+#include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 
 #define dbgarg(cmd, fmt, arg...) \
@@ -48,7 +48,7 @@
 			printk(KERN_CONT "%s: " fmt, vfd->name, ## arg);\
 		} while (0)
 
-/* Zero out the end of the struct pointed to by p.  Everthing after, but
+/* Zero out the end of the struct pointed to by p.  Everything after, but
  * not including, the specified field is cleared. */
 #define CLEAR_AFTER_FIELD(p, field) \
 	memset((u8 *)(p) + offsetof(typeof(*(p)), field) + sizeof((p)->field), \
@@ -165,6 +165,8 @@
 	[V4L2_BUF_TYPE_SLICED_VBI_CAPTURE] = "sliced-vbi-cap",
 	[V4L2_BUF_TYPE_SLICED_VBI_OUTPUT]  = "sliced-vbi-out",
 	[V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY] = "vid-out-overlay",
+	[V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE] = "vid-cap-mplane",
+	[V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE] = "vid-out-mplane",
 };
 EXPORT_SYMBOL(v4l2_type_names);
 
@@ -293,153 +295,37 @@
 }
 EXPORT_SYMBOL(v4l_printk_ioctl);
 
-/*
- * helper function -- handles userspace copying for ioctl arguments
- */
-
-#ifdef __OLD_VIDIOC_
-static unsigned int
-video_fix_command(unsigned int cmd)
-{
-	switch (cmd) {
-	case VIDIOC_OVERLAY_OLD:
-		cmd = VIDIOC_OVERLAY;
-		break;
-	case VIDIOC_S_PARM_OLD:
-		cmd = VIDIOC_S_PARM;
-		break;
-	case VIDIOC_S_CTRL_OLD:
-		cmd = VIDIOC_S_CTRL;
-		break;
-	case VIDIOC_G_AUDIO_OLD:
-		cmd = VIDIOC_G_AUDIO;
-		break;
-	case VIDIOC_G_AUDOUT_OLD:
-		cmd = VIDIOC_G_AUDOUT;
-		break;
-	case VIDIOC_CROPCAP_OLD:
-		cmd = VIDIOC_CROPCAP;
-		break;
-	}
-	return cmd;
-}
-#endif
-
-/*
- * Obsolete usercopy function - Should be removed soon
- */
-long
-video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
-		v4l2_kioctl func)
-{
-	char	sbuf[128];
-	void    *mbuf = NULL;
-	void	*parg = NULL;
-	long	err  = -EINVAL;
-	int     is_ext_ctrl;
-	size_t  ctrls_size = 0;
-	void __user *user_ptr = NULL;
-
-#ifdef __OLD_VIDIOC_
-	cmd = video_fix_command(cmd);
-#endif
-	is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
-		       cmd == VIDIOC_TRY_EXT_CTRLS);
-
-	/*  Copy arguments into temp kernel buffer  */
-	switch (_IOC_DIR(cmd)) {
-	case _IOC_NONE:
-		parg = NULL;
-		break;
-	case _IOC_READ:
-	case _IOC_WRITE:
-	case (_IOC_WRITE | _IOC_READ):
-		if (_IOC_SIZE(cmd) <= sizeof(sbuf)) {
-			parg = sbuf;
-		} else {
-			/* too big to allocate from stack */
-			mbuf = kmalloc(_IOC_SIZE(cmd), GFP_KERNEL);
-			if (NULL == mbuf)
-				return -ENOMEM;
-			parg = mbuf;
-		}
-
-		err = -EFAULT;
-		if (_IOC_DIR(cmd) & _IOC_WRITE)
-			if (copy_from_user(parg, (void __user *)arg, _IOC_SIZE(cmd)))
-				goto out;
-		break;
-	}
-	if (is_ext_ctrl) {
-		struct v4l2_ext_controls *p = parg;
-
-		/* In case of an error, tell the caller that it wasn't
-		   a specific control that caused it. */
-		p->error_idx = p->count;
-		user_ptr = (void __user *)p->controls;
-		if (p->count) {
-			ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
-			/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
-			mbuf = kmalloc(ctrls_size, GFP_KERNEL);
-			err = -ENOMEM;
-			if (NULL == mbuf)
-				goto out_ext_ctrl;
-			err = -EFAULT;
-			if (copy_from_user(mbuf, user_ptr, ctrls_size))
-				goto out_ext_ctrl;
-			p->controls = mbuf;
-		}
-	}
-
-	/* call driver */
-	err = func(file, cmd, parg);
-	if (err == -ENOIOCTLCMD)
-		err = -EINVAL;
-	if (is_ext_ctrl) {
-		struct v4l2_ext_controls *p = parg;
-
-		p->controls = (void *)user_ptr;
-		if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
-			err = -EFAULT;
-		goto out_ext_ctrl;
-	}
-	if (err < 0)
-		goto out;
-
-out_ext_ctrl:
-	/*  Copy results into user buffer  */
-	switch (_IOC_DIR(cmd)) {
-	case _IOC_READ:
-	case (_IOC_WRITE | _IOC_READ):
-		if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd)))
-			err = -EFAULT;
-		break;
-	}
-
-out:
-	kfree(mbuf);
-	return err;
-}
-EXPORT_SYMBOL(video_usercopy);
-
 static void dbgbuf(unsigned int cmd, struct video_device *vfd,
 					struct v4l2_buffer *p)
 {
 	struct v4l2_timecode *tc = &p->timecode;
+	struct v4l2_plane *plane;
+	int i;
 
 	dbgarg(cmd, "%02ld:%02d:%02d.%08ld index=%d, type=%s, "
-		"bytesused=%d, flags=0x%08d, "
-		"field=%0d, sequence=%d, memory=%s, offset/userptr=0x%08lx, length=%d\n",
+		"flags=0x%08d, field=%0d, sequence=%d, memory=%s\n",
 			p->timestamp.tv_sec / 3600,
 			(int)(p->timestamp.tv_sec / 60) % 60,
 			(int)(p->timestamp.tv_sec % 60),
 			(long)p->timestamp.tv_usec,
 			p->index,
 			prt_names(p->type, v4l2_type_names),
-			p->bytesused, p->flags,
-			p->field, p->sequence,
-			prt_names(p->memory, v4l2_memory_names),
-			p->m.userptr, p->length);
+			p->flags, p->field, p->sequence,
+			prt_names(p->memory, v4l2_memory_names));
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(p->type) && p->m.planes) {
+		for (i = 0; i < p->length; ++i) {
+			plane = &p->m.planes[i];
+			dbgarg2("plane %d: bytesused=%d, data_offset=0x%08x "
+				"offset/userptr=0x%08lx, length=%d\n",
+				i, plane->bytesused, plane->data_offset,
+				plane->m.userptr, plane->length);
+		}
+	} else {
+		dbgarg2("bytesused=%d, offset/userptr=0x%08lx, length=%d\n",
+			p->bytesused, p->m.userptr, p->length);
+	}
+
 	dbgarg2("timecode=%02d:%02d:%02d type=%d, "
 		"flags=0x%08d, frames=%d, userbits=0x%08x\n",
 			tc->hours, tc->minutes, tc->seconds,
@@ -467,6 +353,27 @@
 		fmt->bytesperline, fmt->sizeimage, fmt->colorspace);
 };
 
+static inline void v4l_print_pix_fmt_mplane(struct video_device *vfd,
+					    struct v4l2_pix_format_mplane *fmt)
+{
+	int i;
+
+	dbgarg2("width=%d, height=%d, format=%c%c%c%c, field=%s, "
+		"colorspace=%d, num_planes=%d\n",
+		fmt->width, fmt->height,
+		(fmt->pixelformat & 0xff),
+		(fmt->pixelformat >>  8) & 0xff,
+		(fmt->pixelformat >> 16) & 0xff,
+		(fmt->pixelformat >> 24) & 0xff,
+		prt_names(fmt->field, v4l2_field_names),
+		fmt->colorspace, fmt->num_planes);
+
+	for (i = 0; i < fmt->num_planes; ++i)
+		dbgarg2("plane %d: bytesperline=%d sizeimage=%d\n", i,
+			fmt->plane_fmt[i].bytesperline,
+			fmt->plane_fmt[i].sizeimage);
+}
+
 static inline void v4l_print_ext_ctrls(unsigned int cmd,
 	struct video_device *vfd, struct v4l2_ext_controls *c, int show_vals)
 {
@@ -520,7 +427,12 @@
 
 	switch (type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		if (ops->vidioc_g_fmt_vid_cap)
+		if (ops->vidioc_g_fmt_vid_cap ||
+				ops->vidioc_g_fmt_vid_cap_mplane)
+			return 0;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+		if (ops->vidioc_g_fmt_vid_cap_mplane)
 			return 0;
 		break;
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
@@ -528,7 +440,12 @@
 			return 0;
 		break;
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		if (ops->vidioc_g_fmt_vid_out)
+		if (ops->vidioc_g_fmt_vid_out ||
+				ops->vidioc_g_fmt_vid_out_mplane)
+			return 0;
+		break;
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+		if (ops->vidioc_g_fmt_vid_out_mplane)
 			return 0;
 		break;
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
@@ -559,12 +476,72 @@
 	return -EINVAL;
 }
 
+/**
+ * fmt_sp_to_mp() - Convert a single-plane format to its multi-planar 1-plane
+ * equivalent
+ */
+static int fmt_sp_to_mp(const struct v4l2_format *f_sp,
+			struct v4l2_format *f_mp)
+{
+	struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
+	const struct v4l2_pix_format *pix = &f_sp->fmt.pix;
+
+	if (f_sp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+		f_mp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+	else if (f_sp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+		f_mp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+	else
+		return -EINVAL;
+
+	pix_mp->width = pix->width;
+	pix_mp->height = pix->height;
+	pix_mp->pixelformat = pix->pixelformat;
+	pix_mp->field = pix->field;
+	pix_mp->colorspace = pix->colorspace;
+	pix_mp->num_planes = 1;
+	pix_mp->plane_fmt[0].sizeimage = pix->sizeimage;
+	pix_mp->plane_fmt[0].bytesperline = pix->bytesperline;
+
+	return 0;
+}
+
+/**
+ * fmt_mp_to_sp() - Convert a multi-planar 1-plane format to its single-planar
+ * equivalent
+ */
+static int fmt_mp_to_sp(const struct v4l2_format *f_mp,
+			struct v4l2_format *f_sp)
+{
+	const struct v4l2_pix_format_mplane *pix_mp = &f_mp->fmt.pix_mp;
+	struct v4l2_pix_format *pix = &f_sp->fmt.pix;
+
+	if (f_mp->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+		f_sp->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	else if (f_mp->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+		f_sp->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+	else
+		return -EINVAL;
+
+	pix->width = pix_mp->width;
+	pix->height = pix_mp->height;
+	pix->pixelformat = pix_mp->pixelformat;
+	pix->field = pix_mp->field;
+	pix->colorspace = pix_mp->colorspace;
+	pix->sizeimage = pix_mp->plane_fmt[0].sizeimage;
+	pix->bytesperline = pix_mp->plane_fmt[0].bytesperline;
+
+	return 0;
+}
+
 static long __video_do_ioctl(struct file *file,
 		unsigned int cmd, void *arg)
 {
 	struct video_device *vfd = video_devdata(file);
 	const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
 	void *fh = file->private_data;
+	struct v4l2_fh *vfh = NULL;
+	struct v4l2_format f_copy;
+	int use_fh_prio = 0;
 	long ret = -EINVAL;
 
 	if (ops == NULL) {
@@ -579,6 +556,45 @@
 		printk(KERN_CONT "\n");
 	}
 
+	if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+		vfh = file->private_data;
+		use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+	}
+
+	if (use_fh_prio) {
+		switch (cmd) {
+		case VIDIOC_S_CTRL:
+		case VIDIOC_S_STD:
+		case VIDIOC_S_INPUT:
+		case VIDIOC_S_OUTPUT:
+		case VIDIOC_S_TUNER:
+		case VIDIOC_S_FREQUENCY:
+		case VIDIOC_S_FMT:
+		case VIDIOC_S_CROP:
+		case VIDIOC_S_AUDIO:
+		case VIDIOC_S_AUDOUT:
+		case VIDIOC_S_EXT_CTRLS:
+		case VIDIOC_S_FBUF:
+		case VIDIOC_S_PRIORITY:
+		case VIDIOC_S_DV_PRESET:
+		case VIDIOC_S_DV_TIMINGS:
+		case VIDIOC_S_JPEGCOMP:
+		case VIDIOC_S_MODULATOR:
+		case VIDIOC_S_PARM:
+		case VIDIOC_S_HW_FREQ_SEEK:
+		case VIDIOC_ENCODER_CMD:
+		case VIDIOC_OVERLAY:
+		case VIDIOC_REQBUFS:
+		case VIDIOC_STREAMON:
+		case VIDIOC_STREAMOFF:
+			ret = v4l2_prio_check(vfd->prio, vfh->prio);
+			if (ret)
+				goto exit_prio;
+			ret = -EINVAL;
+			break;
+		}
+	}
+
 	switch (cmd) {
 
 	/* --- capabilities ------------------------------------------ */
@@ -605,9 +621,12 @@
 	{
 		enum v4l2_priority *p = arg;
 
-		if (!ops->vidioc_g_priority)
-			break;
-		ret = ops->vidioc_g_priority(file, fh, p);
+		if (ops->vidioc_g_priority) {
+			ret = ops->vidioc_g_priority(file, fh, p);
+		} else if (use_fh_prio) {
+			*p = v4l2_prio_max(&vfd->v4l2_dev->prio);
+			ret = 0;
+		}
 		if (!ret)
 			dbgarg(cmd, "priority is %d\n", *p);
 		break;
@@ -616,10 +635,13 @@
 	{
 		enum v4l2_priority *p = arg;
 
-		if (!ops->vidioc_s_priority)
-			break;
+		if (!ops->vidioc_s_priority && !use_fh_prio)
+				break;
 		dbgarg(cmd, "setting priority to %d\n", *p);
-		ret = ops->vidioc_s_priority(file, fh, *p);
+		if (ops->vidioc_s_priority)
+			ret = ops->vidioc_s_priority(file, fh, *p);
+		else
+			ret = v4l2_prio_change(&vfd->v4l2_dev->prio, &vfh->prio, *p);
 		break;
 	}
 
@@ -633,6 +655,11 @@
 			if (ops->vidioc_enum_fmt_vid_cap)
 				ret = ops->vidioc_enum_fmt_vid_cap(file, fh, f);
 			break;
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+			if (ops->vidioc_enum_fmt_vid_cap_mplane)
+				ret = ops->vidioc_enum_fmt_vid_cap_mplane(file,
+									fh, f);
+			break;
 		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 			if (ops->vidioc_enum_fmt_vid_overlay)
 				ret = ops->vidioc_enum_fmt_vid_overlay(file,
@@ -642,6 +669,11 @@
 			if (ops->vidioc_enum_fmt_vid_out)
 				ret = ops->vidioc_enum_fmt_vid_out(file, fh, f);
 			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+			if (ops->vidioc_enum_fmt_vid_out_mplane)
+				ret = ops->vidioc_enum_fmt_vid_out_mplane(file,
+									fh, f);
+			break;
 		case V4L2_BUF_TYPE_PRIVATE:
 			if (ops->vidioc_enum_fmt_type_private)
 				ret = ops->vidioc_enum_fmt_type_private(file,
@@ -670,22 +702,90 @@
 
 		switch (f->type) {
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-			if (ops->vidioc_g_fmt_vid_cap)
+			if (ops->vidioc_g_fmt_vid_cap) {
 				ret = ops->vidioc_g_fmt_vid_cap(file, fh, f);
+			} else if (ops->vidioc_g_fmt_vid_cap_mplane) {
+				if (fmt_sp_to_mp(f, &f_copy))
+					break;
+				ret = ops->vidioc_g_fmt_vid_cap_mplane(file, fh,
+								       &f_copy);
+				if (ret)
+					break;
+
+				/* Driver is currently in multi-planar format,
+				 * we can't return it in single-planar API*/
+				if (f_copy.fmt.pix_mp.num_planes > 1) {
+					ret = -EBUSY;
+					break;
+				}
+
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
 			if (!ret)
 				v4l_print_pix_fmt(vfd, &f->fmt.pix);
 			break;
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+			if (ops->vidioc_g_fmt_vid_cap_mplane) {
+				ret = ops->vidioc_g_fmt_vid_cap_mplane(file,
+									fh, f);
+			} else if (ops->vidioc_g_fmt_vid_cap) {
+				if (fmt_mp_to_sp(f, &f_copy))
+					break;
+				ret = ops->vidioc_g_fmt_vid_cap(file,
+								fh, &f_copy);
+				if (ret)
+					break;
+
+				ret = fmt_sp_to_mp(&f_copy, f);
+			}
+			if (!ret)
+				v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
+			break;
 		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 			if (ops->vidioc_g_fmt_vid_overlay)
 				ret = ops->vidioc_g_fmt_vid_overlay(file,
 								    fh, f);
 			break;
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-			if (ops->vidioc_g_fmt_vid_out)
+			if (ops->vidioc_g_fmt_vid_out) {
 				ret = ops->vidioc_g_fmt_vid_out(file, fh, f);
+			} else if (ops->vidioc_g_fmt_vid_out_mplane) {
+				if (fmt_sp_to_mp(f, &f_copy))
+					break;
+				ret = ops->vidioc_g_fmt_vid_out_mplane(file, fh,
+									&f_copy);
+				if (ret)
+					break;
+
+				/* Driver is currently in multi-planar format,
+				 * we can't return it in single-planar API*/
+				if (f_copy.fmt.pix_mp.num_planes > 1) {
+					ret = -EBUSY;
+					break;
+				}
+
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
 			if (!ret)
 				v4l_print_pix_fmt(vfd, &f->fmt.pix);
 			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+			if (ops->vidioc_g_fmt_vid_out_mplane) {
+				ret = ops->vidioc_g_fmt_vid_out_mplane(file,
+									fh, f);
+			} else if (ops->vidioc_g_fmt_vid_out) {
+				if (fmt_mp_to_sp(f, &f_copy))
+					break;
+				ret = ops->vidioc_g_fmt_vid_out(file,
+								fh, &f_copy);
+				if (ret)
+					break;
+
+				ret = fmt_sp_to_mp(&f_copy, f);
+			}
+			if (!ret)
+				v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
+			break;
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 			if (ops->vidioc_g_fmt_vid_out_overlay)
 				ret = ops->vidioc_g_fmt_vid_out_overlay(file,
@@ -729,8 +829,44 @@
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 			CLEAR_AFTER_FIELD(f, fmt.pix);
 			v4l_print_pix_fmt(vfd, &f->fmt.pix);
-			if (ops->vidioc_s_fmt_vid_cap)
+			if (ops->vidioc_s_fmt_vid_cap) {
 				ret = ops->vidioc_s_fmt_vid_cap(file, fh, f);
+			} else if (ops->vidioc_s_fmt_vid_cap_mplane) {
+				if (fmt_sp_to_mp(f, &f_copy))
+					break;
+				ret = ops->vidioc_s_fmt_vid_cap_mplane(file, fh,
+									&f_copy);
+				if (ret)
+					break;
+
+				if (f_copy.fmt.pix_mp.num_planes > 1) {
+					/* Drivers shouldn't adjust from 1-plane
+					 * to more than 1-plane formats */
+					ret = -EBUSY;
+					WARN_ON(1);
+					break;
+				}
+
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
+			break;
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+			CLEAR_AFTER_FIELD(f, fmt.pix_mp);
+			v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
+			if (ops->vidioc_s_fmt_vid_cap_mplane) {
+				ret = ops->vidioc_s_fmt_vid_cap_mplane(file,
+									fh, f);
+			} else if (ops->vidioc_s_fmt_vid_cap &&
+					f->fmt.pix_mp.num_planes == 1) {
+				if (fmt_mp_to_sp(f, &f_copy))
+					break;
+				ret = ops->vidioc_s_fmt_vid_cap(file,
+								fh, &f_copy);
+				if (ret)
+					break;
+
+				ret = fmt_sp_to_mp(&f_copy, f);
+			}
 			break;
 		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 			CLEAR_AFTER_FIELD(f, fmt.win);
@@ -741,8 +877,44 @@
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 			CLEAR_AFTER_FIELD(f, fmt.pix);
 			v4l_print_pix_fmt(vfd, &f->fmt.pix);
-			if (ops->vidioc_s_fmt_vid_out)
+			if (ops->vidioc_s_fmt_vid_out) {
 				ret = ops->vidioc_s_fmt_vid_out(file, fh, f);
+			} else if (ops->vidioc_s_fmt_vid_out_mplane) {
+				if (fmt_sp_to_mp(f, &f_copy))
+					break;
+				ret = ops->vidioc_s_fmt_vid_out_mplane(file, fh,
+									&f_copy);
+				if (ret)
+					break;
+
+				if (f_copy.fmt.pix_mp.num_planes > 1) {
+					/* Drivers shouldn't adjust from 1-plane
+					 * to more than 1-plane formats */
+					ret = -EBUSY;
+					WARN_ON(1);
+					break;
+				}
+
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
+			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+			CLEAR_AFTER_FIELD(f, fmt.pix_mp);
+			v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
+			if (ops->vidioc_s_fmt_vid_out_mplane) {
+				ret = ops->vidioc_s_fmt_vid_out_mplane(file,
+									fh, f);
+			} else if (ops->vidioc_s_fmt_vid_out &&
+					f->fmt.pix_mp.num_planes == 1) {
+				if (fmt_mp_to_sp(f, &f_copy))
+					break;
+				ret = ops->vidioc_s_fmt_vid_out(file,
+								fh, &f_copy);
+				if (ret)
+					break;
+
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
 			break;
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 			CLEAR_AFTER_FIELD(f, fmt.win);
@@ -791,11 +963,47 @@
 		switch (f->type) {
 		case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 			CLEAR_AFTER_FIELD(f, fmt.pix);
-			if (ops->vidioc_try_fmt_vid_cap)
+			if (ops->vidioc_try_fmt_vid_cap) {
 				ret = ops->vidioc_try_fmt_vid_cap(file, fh, f);
+			} else if (ops->vidioc_try_fmt_vid_cap_mplane) {
+				if (fmt_sp_to_mp(f, &f_copy))
+					break;
+				ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
+								fh, &f_copy);
+				if (ret)
+					break;
+
+				if (f_copy.fmt.pix_mp.num_planes > 1) {
+					/* Drivers shouldn't adjust from 1-plane
+					 * to more than 1-plane formats */
+					ret = -EBUSY;
+					WARN_ON(1);
+					break;
+				}
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
 			if (!ret)
 				v4l_print_pix_fmt(vfd, &f->fmt.pix);
 			break;
+		case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
+			CLEAR_AFTER_FIELD(f, fmt.pix_mp);
+			if (ops->vidioc_try_fmt_vid_cap_mplane) {
+				ret = ops->vidioc_try_fmt_vid_cap_mplane(file,
+									 fh, f);
+			} else if (ops->vidioc_try_fmt_vid_cap &&
+					f->fmt.pix_mp.num_planes == 1) {
+				if (fmt_mp_to_sp(f, &f_copy))
+					break;
+				ret = ops->vidioc_try_fmt_vid_cap(file,
+								  fh, &f_copy);
+				if (ret)
+					break;
+
+				ret = fmt_sp_to_mp(&f_copy, f);
+			}
+			if (!ret)
+				v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
+			break;
 		case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 			CLEAR_AFTER_FIELD(f, fmt.win);
 			if (ops->vidioc_try_fmt_vid_overlay)
@@ -804,11 +1012,47 @@
 			break;
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT:
 			CLEAR_AFTER_FIELD(f, fmt.pix);
-			if (ops->vidioc_try_fmt_vid_out)
+			if (ops->vidioc_try_fmt_vid_out) {
 				ret = ops->vidioc_try_fmt_vid_out(file, fh, f);
+			} else if (ops->vidioc_try_fmt_vid_out_mplane) {
+				if (fmt_sp_to_mp(f, &f_copy))
+					break;
+				ret = ops->vidioc_try_fmt_vid_out_mplane(file,
+								fh, &f_copy);
+				if (ret)
+					break;
+
+				if (f_copy.fmt.pix_mp.num_planes > 1) {
+					/* Drivers shouldn't adjust from 1-plane
+					 * to more than 1-plane formats */
+					ret = -EBUSY;
+					WARN_ON(1);
+					break;
+				}
+				ret = fmt_mp_to_sp(&f_copy, f);
+			}
 			if (!ret)
 				v4l_print_pix_fmt(vfd, &f->fmt.pix);
 			break;
+		case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
+			CLEAR_AFTER_FIELD(f, fmt.pix_mp);
+			if (ops->vidioc_try_fmt_vid_out_mplane) {
+				ret = ops->vidioc_try_fmt_vid_out_mplane(file,
+									 fh, f);
+			} else if (ops->vidioc_try_fmt_vid_out &&
+					f->fmt.pix_mp.num_planes == 1) {
+				if (fmt_mp_to_sp(f, &f_copy))
+					break;
+				ret = ops->vidioc_try_fmt_vid_out(file,
+								  fh, &f_copy);
+				if (ret)
+					break;
+
+				ret = fmt_sp_to_mp(&f_copy, f);
+			}
+			if (!ret)
+				v4l_print_pix_fmt_mplane(vfd, &f->fmt.pix_mp);
+			break;
 		case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 			CLEAR_AFTER_FIELD(f, fmt.win);
 			if (ops->vidioc_try_fmt_vid_out_overlay)
@@ -1942,13 +2186,18 @@
 	}
 	default:
 	{
+		bool valid_prio = true;
+
 		if (!ops->vidioc_default)
 			break;
-		ret = ops->vidioc_default(file, fh, cmd, arg);
+		if (use_fh_prio)
+			valid_prio = v4l2_prio_check(vfd->prio, vfh->prio) >= 0;
+		ret = ops->vidioc_default(file, fh, valid_prio, cmd, arg);
 		break;
 	}
 	} /* switch */
 
+exit_prio:
 	if (vfd->debug & V4L2_DEBUG_IOCTL_ARG) {
 		if (ret < 0) {
 			v4l_print_ioctl(vfd->name, cmd);
@@ -1973,7 +2222,7 @@
 	switch (cmd) {
 		CMDINSIZE(ENUM_FMT,		fmtdesc,	type);
 		CMDINSIZE(G_FMT,		format,		type);
-		CMDINSIZE(QUERYBUF,		buffer,		type);
+		CMDINSIZE(QUERYBUF,		buffer,		length);
 		CMDINSIZE(G_PARM,		streamparm,	type);
 		CMDINSIZE(ENUMSTD,		standard,	index);
 		CMDINSIZE(ENUMINPUT,		input,		index);
@@ -1998,22 +2247,61 @@
 	}
 }
 
-long video_ioctl2(struct file *file,
-	       unsigned int cmd, unsigned long arg)
+static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
+			    void * __user *user_ptr, void ***kernel_ptr)
+{
+	int ret = 0;
+
+	switch (cmd) {
+	case VIDIOC_QUERYBUF:
+	case VIDIOC_QBUF:
+	case VIDIOC_DQBUF: {
+		struct v4l2_buffer *buf = parg;
+
+		if (V4L2_TYPE_IS_MULTIPLANAR(buf->type) && buf->length > 0) {
+			if (buf->length > VIDEO_MAX_PLANES) {
+				ret = -EINVAL;
+				break;
+			}
+			*user_ptr = (void __user *)buf->m.planes;
+			*kernel_ptr = (void **)&buf->m.planes;
+			*array_size = sizeof(struct v4l2_plane) * buf->length;
+			ret = 1;
+		}
+		break;
+	}
+
+	case VIDIOC_S_EXT_CTRLS:
+	case VIDIOC_G_EXT_CTRLS:
+	case VIDIOC_TRY_EXT_CTRLS: {
+		struct v4l2_ext_controls *ctrls = parg;
+
+		if (ctrls->count != 0) {
+			*user_ptr = (void __user *)ctrls->controls;
+			*kernel_ptr = (void **)&ctrls->controls;
+			*array_size = sizeof(struct v4l2_ext_control)
+				    * ctrls->count;
+			ret = 1;
+		}
+		break;
+	}
+	}
+
+	return ret;
+}
+
+long
+video_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
+	       v4l2_kioctl func)
 {
 	char	sbuf[128];
 	void    *mbuf = NULL;
 	void	*parg = (void *)arg;
 	long	err  = -EINVAL;
-	int     is_ext_ctrl;
-	size_t  ctrls_size = 0;
+	bool	has_array_args;
+	size_t  array_size = 0;
 	void __user *user_ptr = NULL;
-
-#ifdef __OLD_VIDIOC_
-	cmd = video_fix_command(cmd);
-#endif
-	is_ext_ctrl = (cmd == VIDIOC_S_EXT_CTRLS || cmd == VIDIOC_G_EXT_CTRLS ||
-		       cmd == VIDIOC_TRY_EXT_CTRLS);
+	void	**kernel_ptr = NULL;
 
 	/*  Copy arguments into temp kernel buffer  */
 	if (_IOC_DIR(cmd) != _IOC_NONE) {
@@ -2043,43 +2331,43 @@
 		}
 	}
 
-	if (is_ext_ctrl) {
-		struct v4l2_ext_controls *p = parg;
+	err = check_array_args(cmd, parg, &array_size, &user_ptr, &kernel_ptr);
+	if (err < 0)
+		goto out;
+	has_array_args = err;
 
-		/* In case of an error, tell the caller that it wasn't
-		   a specific control that caused it. */
-		p->error_idx = p->count;
-		user_ptr = (void __user *)p->controls;
-		if (p->count) {
-			ctrls_size = sizeof(struct v4l2_ext_control) * p->count;
-			/* Note: v4l2_ext_controls fits in sbuf[] so mbuf is still NULL. */
-			mbuf = kmalloc(ctrls_size, GFP_KERNEL);
-			err = -ENOMEM;
-			if (NULL == mbuf)
-				goto out_ext_ctrl;
-			err = -EFAULT;
-			if (copy_from_user(mbuf, user_ptr, ctrls_size))
-				goto out_ext_ctrl;
-			p->controls = mbuf;
-		}
+	if (has_array_args) {
+		/*
+		 * When adding new types of array args, make sure that the
+		 * parent argument to ioctl (which contains the pointer to the
+		 * array) fits into sbuf (so that mbuf will still remain
+		 * unused up to here).
+		 */
+		mbuf = kmalloc(array_size, GFP_KERNEL);
+		err = -ENOMEM;
+		if (NULL == mbuf)
+			goto out_array_args;
+		err = -EFAULT;
+		if (copy_from_user(mbuf, user_ptr, array_size))
+			goto out_array_args;
+		*kernel_ptr = mbuf;
 	}
 
 	/* Handles IOCTL */
-	err = __video_do_ioctl(file, cmd, parg);
+	err = func(file, cmd, parg);
 	if (err == -ENOIOCTLCMD)
 		err = -EINVAL;
-	if (is_ext_ctrl) {
-		struct v4l2_ext_controls *p = parg;
 
-		p->controls = (void *)user_ptr;
-		if (p->count && err == 0 && copy_to_user(user_ptr, mbuf, ctrls_size))
+	if (has_array_args) {
+		*kernel_ptr = user_ptr;
+		if (copy_to_user(user_ptr, mbuf, array_size))
 			err = -EFAULT;
-		goto out_ext_ctrl;
+		goto out_array_args;
 	}
 	if (err < 0)
 		goto out;
 
-out_ext_ctrl:
+out_array_args:
 	/*  Copy results into user buffer  */
 	switch (_IOC_DIR(cmd)) {
 	case _IOC_READ:
@@ -2093,4 +2381,11 @@
 	kfree(mbuf);
 	return err;
 }
+EXPORT_SYMBOL(video_usercopy);
+
+long video_ioctl2(struct file *file,
+	       unsigned int cmd, unsigned long arg)
+{
+	return video_usercopy(file, cmd, arg, __video_do_ioctl);
+}
 EXPORT_SYMBOL(video_ioctl2);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-mem2mem.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-mem2mem.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-mem2mem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-mem2mem.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,7 @@
  * source and destination.
  *
  * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- * Pawel Osciak, <p.osciak@samsung.com>
+ * Pawel Osciak, <pawel@osciak.com>
  * Marek Szyprowski, <m.szyprowski@samsung.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -17,11 +17,11 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 
-#include <media/videobuf-core.h>
+#include <media/videobuf2-core.h>
 #include <media/v4l2-mem2mem.h>
 
 MODULE_DESCRIPTION("Mem to mem device framework for videobuf");
-MODULE_AUTHOR("Pawel Osciak, <p.osciak@samsung.com>");
+MODULE_AUTHOR("Pawel Osciak, <pawel@osciak.com>");
 MODULE_LICENSE("GPL");
 
 static bool debug;
@@ -65,21 +65,16 @@
 static struct v4l2_m2m_queue_ctx *get_queue_ctx(struct v4l2_m2m_ctx *m2m_ctx,
 						enum v4l2_buf_type type)
 {
-	switch (type) {
-	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-		return &m2m_ctx->cap_q_ctx;
-	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+	if (V4L2_TYPE_IS_OUTPUT(type))
 		return &m2m_ctx->out_q_ctx;
-	default:
-		printk(KERN_ERR "Invalid buffer type\n");
-		return NULL;
-	}
+	else
+		return &m2m_ctx->cap_q_ctx;
 }
 
 /**
- * v4l2_m2m_get_vq() - return videobuf_queue for the given type
+ * v4l2_m2m_get_vq() - return vb2_queue for the given type
  */
-struct videobuf_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
+struct vb2_queue *v4l2_m2m_get_vq(struct v4l2_m2m_ctx *m2m_ctx,
 				       enum v4l2_buf_type type)
 {
 	struct v4l2_m2m_queue_ctx *q_ctx;
@@ -95,27 +90,20 @@
 /**
  * v4l2_m2m_next_buf() - return next buffer from the list of ready buffers
  */
-void *v4l2_m2m_next_buf(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type)
+void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
 {
-	struct v4l2_m2m_queue_ctx *q_ctx;
-	struct videobuf_buffer *vb = NULL;
+	struct v4l2_m2m_buffer *b = NULL;
 	unsigned long flags;
 
-	q_ctx = get_queue_ctx(m2m_ctx, type);
-	if (!q_ctx)
-		return NULL;
-
-	spin_lock_irqsave(q_ctx->q.irqlock, flags);
+	spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
 
 	if (list_empty(&q_ctx->rdy_queue))
 		goto end;
 
-	vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer, queue);
-	vb->state = VIDEOBUF_ACTIVE;
-
+	b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
 end:
-	spin_unlock_irqrestore(q_ctx->q.irqlock, flags);
-	return vb;
+	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
+	return &b->vb;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_next_buf);
 
@@ -123,26 +111,21 @@
  * v4l2_m2m_buf_remove() - take off a buffer from the list of ready buffers and
  * return it
  */
-void *v4l2_m2m_buf_remove(struct v4l2_m2m_ctx *m2m_ctx, enum v4l2_buf_type type)
+void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
 {
-	struct v4l2_m2m_queue_ctx *q_ctx;
-	struct videobuf_buffer *vb = NULL;
+	struct v4l2_m2m_buffer *b = NULL;
 	unsigned long flags;
 
-	q_ctx = get_queue_ctx(m2m_ctx, type);
-	if (!q_ctx)
-		return NULL;
-
-	spin_lock_irqsave(q_ctx->q.irqlock, flags);
+	spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
 	if (!list_empty(&q_ctx->rdy_queue)) {
-		vb = list_entry(q_ctx->rdy_queue.next, struct videobuf_buffer,
-				queue);
-		list_del(&vb->queue);
+		b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer,
+				list);
+		list_del(&b->list);
 		q_ctx->num_rdy--;
 	}
-	spin_unlock_irqrestore(q_ctx->q.irqlock, flags);
+	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
 
-	return vb;
+	return &b->vb;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_remove);
 
@@ -235,20 +218,20 @@
 		return;
 	}
 
-	spin_lock_irqsave(m2m_ctx->out_q_ctx.q.irqlock, flags);
+	spin_lock_irqsave(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
 	if (list_empty(&m2m_ctx->out_q_ctx.rdy_queue)) {
-		spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags);
+		spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
 		dprintk("No input buffers available\n");
 		return;
 	}
 	if (list_empty(&m2m_ctx->cap_q_ctx.rdy_queue)) {
-		spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags);
+		spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags_job);
 		dprintk("No output buffers available\n");
 		return;
 	}
-	spin_unlock_irqrestore(m2m_ctx->out_q_ctx.q.irqlock, flags);
+	spin_unlock_irqrestore(&m2m_ctx->out_q_ctx.rdy_spinlock, flags);
 
 	if (m2m_dev->m2m_ops->job_ready
 		&& (!m2m_dev->m2m_ops->job_ready(m2m_ctx->priv))) {
@@ -291,6 +274,7 @@
 
 	list_del(&m2m_dev->curr_ctx->queue);
 	m2m_dev->curr_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
+	wake_up(&m2m_dev->curr_ctx->finished);
 	m2m_dev->curr_ctx = NULL;
 
 	spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
@@ -309,10 +293,10 @@
 int v4l2_m2m_reqbufs(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		     struct v4l2_requestbuffers *reqbufs)
 {
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, reqbufs->type);
-	return videobuf_reqbufs(vq, reqbufs);
+	return vb2_reqbufs(vq, reqbufs);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_reqbufs);
 
@@ -324,15 +308,22 @@
 int v4l2_m2m_querybuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		      struct v4l2_buffer *buf)
 {
-	struct videobuf_queue *vq;
-	int ret;
+	struct vb2_queue *vq;
+	int ret = 0;
+	unsigned int i;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-	ret = videobuf_querybuf(vq, buf);
+	ret = vb2_querybuf(vq, buf);
 
-	if (buf->memory == V4L2_MEMORY_MMAP
-	    && vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-		buf->m.offset += DST_QUEUE_OFF_BASE;
+	/* Adjust MMAP memory offsets for the CAPTURE queue */
+	if (buf->memory == V4L2_MEMORY_MMAP && !V4L2_TYPE_IS_OUTPUT(vq->type)) {
+		if (V4L2_TYPE_IS_MULTIPLANAR(vq->type)) {
+			for (i = 0; i < buf->length; ++i)
+				buf->m.planes[i].m.mem_offset
+					+= DST_QUEUE_OFF_BASE;
+		} else {
+			buf->m.offset += DST_QUEUE_OFF_BASE;
+		}
 	}
 
 	return ret;
@@ -346,11 +337,11 @@
 int v4l2_m2m_qbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		  struct v4l2_buffer *buf)
 {
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 	int ret;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-	ret = videobuf_qbuf(vq, buf);
+	ret = vb2_qbuf(vq, buf);
 	if (!ret)
 		v4l2_m2m_try_schedule(m2m_ctx);
 
@@ -365,10 +356,10 @@
 int v4l2_m2m_dqbuf(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		   struct v4l2_buffer *buf)
 {
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, buf->type);
-	return videobuf_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
+	return vb2_dqbuf(vq, buf, file->f_flags & O_NONBLOCK);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_dqbuf);
 
@@ -378,11 +369,11 @@
 int v4l2_m2m_streamon(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		      enum v4l2_buf_type type)
 {
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 	int ret;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, type);
-	ret = videobuf_streamon(vq);
+	ret = vb2_streamon(vq, type);
 	if (!ret)
 		v4l2_m2m_try_schedule(m2m_ctx);
 
@@ -396,10 +387,10 @@
 int v4l2_m2m_streamoff(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 		       enum v4l2_buf_type type)
 {
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 
 	vq = v4l2_m2m_get_vq(m2m_ctx, type);
-	return videobuf_streamoff(vq);
+	return vb2_streamoff(vq, type);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_streamoff);
 
@@ -414,44 +405,53 @@
 unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
 			   struct poll_table_struct *wait)
 {
-	struct videobuf_queue *src_q, *dst_q;
-	struct videobuf_buffer *src_vb = NULL, *dst_vb = NULL;
+	struct vb2_queue *src_q, *dst_q;
+	struct vb2_buffer *src_vb = NULL, *dst_vb = NULL;
 	unsigned int rc = 0;
+	unsigned long flags;
 
 	src_q = v4l2_m2m_get_src_vq(m2m_ctx);
 	dst_q = v4l2_m2m_get_dst_vq(m2m_ctx);
 
-	videobuf_queue_lock(src_q);
-	videobuf_queue_lock(dst_q);
-
-	if (src_q->streaming && !list_empty(&src_q->stream))
-		src_vb = list_first_entry(&src_q->stream,
-					  struct videobuf_buffer, stream);
-	if (dst_q->streaming && !list_empty(&dst_q->stream))
-		dst_vb = list_first_entry(&dst_q->stream,
-					  struct videobuf_buffer, stream);
-
-	if (!src_vb && !dst_vb) {
+	/*
+	 * There has to be at least one buffer queued on each queued_list, which
+	 * means either in driver already or waiting for driver to claim it
+	 * and start processing.
+	 */
+	if ((!src_q->streaming || list_empty(&src_q->queued_list))
+		&& (!dst_q->streaming || list_empty(&dst_q->queued_list))) {
 		rc = POLLERR;
 		goto end;
 	}
 
-	if (src_vb) {
-		poll_wait(file, &src_vb->done, wait);
-		if (src_vb->state == VIDEOBUF_DONE
-		    || src_vb->state == VIDEOBUF_ERROR)
-			rc |= POLLOUT | POLLWRNORM;
-	}
-	if (dst_vb) {
-		poll_wait(file, &dst_vb->done, wait);
-		if (dst_vb->state == VIDEOBUF_DONE
-		    || dst_vb->state == VIDEOBUF_ERROR)
-			rc |= POLLIN | POLLRDNORM;
-	}
+	if (m2m_ctx->m2m_dev->m2m_ops->unlock)
+		m2m_ctx->m2m_dev->m2m_ops->unlock(m2m_ctx->priv);
+
+	poll_wait(file, &src_q->done_wq, wait);
+	poll_wait(file, &dst_q->done_wq, wait);
+
+	if (m2m_ctx->m2m_dev->m2m_ops->lock)
+		m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
+
+	spin_lock_irqsave(&src_q->done_lock, flags);
+	if (!list_empty(&src_q->done_list))
+		src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
+						done_entry);
+	if (src_vb && (src_vb->state == VB2_BUF_STATE_DONE
+			|| src_vb->state == VB2_BUF_STATE_ERROR))
+		rc |= POLLOUT | POLLWRNORM;
+	spin_unlock_irqrestore(&src_q->done_lock, flags);
+
+	spin_lock_irqsave(&dst_q->done_lock, flags);
+	if (!list_empty(&dst_q->done_list))
+		dst_vb = list_first_entry(&dst_q->done_list, struct vb2_buffer,
+						done_entry);
+	if (dst_vb && (dst_vb->state == VB2_BUF_STATE_DONE
+			|| dst_vb->state == VB2_BUF_STATE_ERROR))
+		rc |= POLLIN | POLLRDNORM;
+	spin_unlock_irqrestore(&dst_q->done_lock, flags);
 
 end:
-	videobuf_queue_unlock(dst_q);
-	videobuf_queue_unlock(src_q);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_poll);
@@ -470,7 +470,7 @@
 			 struct vm_area_struct *vma)
 {
 	unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
-	struct videobuf_queue *vq;
+	struct vb2_queue *vq;
 
 	if (offset < DST_QUEUE_OFF_BASE) {
 		vq = v4l2_m2m_get_src_vq(m2m_ctx);
@@ -479,7 +479,7 @@
 		vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
 	}
 
-	return videobuf_mmap_mapper(vq, vma);
+	return vb2_mmap(vq, vma);
 }
 EXPORT_SYMBOL(v4l2_m2m_mmap);
 
@@ -531,36 +531,41 @@
  *
  * Usually called from driver's open() function.
  */
-struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(void *priv, struct v4l2_m2m_dev *m2m_dev,
-			void (*vq_init)(void *priv, struct videobuf_queue *,
-					enum v4l2_buf_type))
+struct v4l2_m2m_ctx *v4l2_m2m_ctx_init(struct v4l2_m2m_dev *m2m_dev,
+		void *drv_priv,
+		int (*queue_init)(void *priv, struct vb2_queue *src_vq, struct vb2_queue *dst_vq))
 {
 	struct v4l2_m2m_ctx *m2m_ctx;
 	struct v4l2_m2m_queue_ctx *out_q_ctx, *cap_q_ctx;
-
-	if (!vq_init)
-		return ERR_PTR(-EINVAL);
+	int ret;
 
 	m2m_ctx = kzalloc(sizeof *m2m_ctx, GFP_KERNEL);
 	if (!m2m_ctx)
 		return ERR_PTR(-ENOMEM);
 
-	m2m_ctx->priv = priv;
+	m2m_ctx->priv = drv_priv;
 	m2m_ctx->m2m_dev = m2m_dev;
+	init_waitqueue_head(&m2m_ctx->finished);
 
-	out_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	cap_q_ctx = get_queue_ctx(m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+	out_q_ctx = &m2m_ctx->out_q_ctx;
+	cap_q_ctx = &m2m_ctx->cap_q_ctx;
 
 	INIT_LIST_HEAD(&out_q_ctx->rdy_queue);
 	INIT_LIST_HEAD(&cap_q_ctx->rdy_queue);
+	spin_lock_init(&out_q_ctx->rdy_spinlock);
+	spin_lock_init(&cap_q_ctx->rdy_spinlock);
 
 	INIT_LIST_HEAD(&m2m_ctx->queue);
 
-	vq_init(priv, &out_q_ctx->q, V4L2_BUF_TYPE_VIDEO_OUTPUT);
-	vq_init(priv, &cap_q_ctx->q, V4L2_BUF_TYPE_VIDEO_CAPTURE);
-	out_q_ctx->q.priv_data = cap_q_ctx->q.priv_data = priv;
+	ret = queue_init(drv_priv, &out_q_ctx->q, &cap_q_ctx->q);
+
+	if (ret)
+		goto err;
 
 	return m2m_ctx;
+err:
+	kfree(m2m_ctx);
+	return ERR_PTR(ret);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_ctx_init);
 
@@ -572,7 +577,6 @@
 void v4l2_m2m_ctx_release(struct v4l2_m2m_ctx *m2m_ctx)
 {
 	struct v4l2_m2m_dev *m2m_dev;
-	struct videobuf_buffer *vb;
 	unsigned long flags;
 
 	m2m_dev = m2m_ctx->m2m_dev;
@@ -582,10 +586,7 @@
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 		m2m_dev->m2m_ops->job_abort(m2m_ctx->priv);
 		dprintk("m2m_ctx %p running, will wait to complete", m2m_ctx);
-		vb = v4l2_m2m_next_dst_buf(m2m_ctx);
-		BUG_ON(NULL == vb);
-		wait_event(vb->done, vb->state != VIDEOBUF_ACTIVE
-				     && vb->state != VIDEOBUF_QUEUED);
+		wait_event(m2m_ctx->finished, !(m2m_ctx->job_flags & TRANS_RUNNING));
 	} else if (m2m_ctx->job_flags & TRANS_QUEUED) {
 		list_del(&m2m_ctx->queue);
 		m2m_ctx->job_flags &= ~(TRANS_QUEUED | TRANS_RUNNING);
@@ -597,11 +598,8 @@
 		spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
 	}
 
-	videobuf_stop(&m2m_ctx->cap_q_ctx.q);
-	videobuf_stop(&m2m_ctx->out_q_ctx.q);
-
-	videobuf_mmap_free(&m2m_ctx->cap_q_ctx.q);
-	videobuf_mmap_free(&m2m_ctx->out_q_ctx.q);
+	vb2_queue_release(&m2m_ctx->cap_q_ctx.q);
+	vb2_queue_release(&m2m_ctx->out_q_ctx.q);
 
 	kfree(m2m_ctx);
 }
@@ -611,23 +609,21 @@
  * v4l2_m2m_buf_queue() - add a buffer to the proper ready buffers list.
  *
  * Call from buf_queue(), videobuf_queue_ops callback.
- *
- * Locking: Caller holds q->irqlock (taken by videobuf before calling buf_queue
- * callback in the driver).
  */
-void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct videobuf_queue *vq,
-			struct videobuf_buffer *vb)
+void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb)
 {
+	struct v4l2_m2m_buffer *b = container_of(vb, struct v4l2_m2m_buffer, vb);
 	struct v4l2_m2m_queue_ctx *q_ctx;
+	unsigned long flags;
 
-	q_ctx = get_queue_ctx(m2m_ctx, vq->type);
+	q_ctx = get_queue_ctx(m2m_ctx, vb->vb2_queue->type);
 	if (!q_ctx)
 		return;
 
-	list_add_tail(&vb->queue, &q_ctx->rdy_queue);
+	spin_lock_irqsave(&q_ctx->rdy_spinlock, flags);
+	list_add_tail(&b->list, &q_ctx->rdy_queue);
 	q_ctx->num_rdy++;
-
-	vb->state = VIDEOBUF_QUEUED;
+	spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
 }
 EXPORT_SYMBOL_GPL(v4l2_m2m_buf_queue);
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/v4l2-subdev.c linux-libre-2.6.39-gnu/drivers/media/video/v4l2-subdev.c
--- linux-libre-2.6.38-gnu/drivers/media/video/v4l2-subdev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/v4l2-subdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,332 @@
+/*
+ * V4L2 sub-device
+ *
+ * Copyright (C) 2010 Nokia Corporation
+ *
+ * Contact: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+ *	    Sakari Ailus <sakari.ailus@iki.fi>
+ *
+ * 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/ioctl.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+
+static int subdev_fh_init(struct v4l2_subdev_fh *fh, struct v4l2_subdev *sd)
+{
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+	/* Allocate try format and crop in the same memory block */
+	fh->try_fmt = kzalloc((sizeof(*fh->try_fmt) + sizeof(*fh->try_crop))
+			      * sd->entity.num_pads, GFP_KERNEL);
+	if (fh->try_fmt == NULL)
+		return -ENOMEM;
+
+	fh->try_crop = (struct v4l2_rect *)
+		(fh->try_fmt + sd->entity.num_pads);
+#endif
+	return 0;
+}
+
+static void subdev_fh_free(struct v4l2_subdev_fh *fh)
+{
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+	kfree(fh->try_fmt);
+	fh->try_fmt = NULL;
+	fh->try_crop = NULL;
+#endif
+}
+
+static int subdev_open(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+	struct v4l2_subdev_fh *subdev_fh;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	struct media_entity *entity = NULL;
+#endif
+	int ret;
+
+	subdev_fh = kzalloc(sizeof(*subdev_fh), GFP_KERNEL);
+	if (subdev_fh == NULL)
+		return -ENOMEM;
+
+	ret = subdev_fh_init(subdev_fh, sd);
+	if (ret) {
+		kfree(subdev_fh);
+		return ret;
+	}
+
+	ret = v4l2_fh_init(&subdev_fh->vfh, vdev);
+	if (ret)
+		goto err;
+
+	if (sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS) {
+		ret = v4l2_event_init(&subdev_fh->vfh);
+		if (ret)
+			goto err;
+
+		ret = v4l2_event_alloc(&subdev_fh->vfh, sd->nevents);
+		if (ret)
+			goto err;
+	}
+
+	v4l2_fh_add(&subdev_fh->vfh);
+	file->private_data = &subdev_fh->vfh;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (sd->v4l2_dev->mdev) {
+		entity = media_entity_get(&sd->entity);
+		if (!entity) {
+			ret = -EBUSY;
+			goto err;
+		}
+	}
+#endif
+
+	if (sd->internal_ops && sd->internal_ops->open) {
+		ret = sd->internal_ops->open(sd, subdev_fh);
+		if (ret < 0)
+			goto err;
+	}
+
+	return 0;
+
+err:
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (entity)
+		media_entity_put(entity);
+#endif
+	v4l2_fh_del(&subdev_fh->vfh);
+	v4l2_fh_exit(&subdev_fh->vfh);
+	subdev_fh_free(subdev_fh);
+	kfree(subdev_fh);
+
+	return ret;
+}
+
+static int subdev_close(struct file *file)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+	struct v4l2_fh *vfh = file->private_data;
+	struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+
+	if (sd->internal_ops && sd->internal_ops->close)
+		sd->internal_ops->close(sd, subdev_fh);
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	if (sd->v4l2_dev->mdev)
+		media_entity_put(&sd->entity);
+#endif
+	v4l2_fh_del(vfh);
+	v4l2_fh_exit(vfh);
+	subdev_fh_free(subdev_fh);
+	kfree(subdev_fh);
+	file->private_data = NULL;
+
+	return 0;
+}
+
+static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+	struct v4l2_fh *vfh = file->private_data;
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+	struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+#endif
+
+	switch (cmd) {
+	case VIDIOC_QUERYCTRL:
+		return v4l2_queryctrl(sd->ctrl_handler, arg);
+
+	case VIDIOC_QUERYMENU:
+		return v4l2_querymenu(sd->ctrl_handler, arg);
+
+	case VIDIOC_G_CTRL:
+		return v4l2_g_ctrl(sd->ctrl_handler, arg);
+
+	case VIDIOC_S_CTRL:
+		return v4l2_s_ctrl(sd->ctrl_handler, arg);
+
+	case VIDIOC_G_EXT_CTRLS:
+		return v4l2_g_ext_ctrls(sd->ctrl_handler, arg);
+
+	case VIDIOC_S_EXT_CTRLS:
+		return v4l2_s_ext_ctrls(sd->ctrl_handler, arg);
+
+	case VIDIOC_TRY_EXT_CTRLS:
+		return v4l2_try_ext_ctrls(sd->ctrl_handler, arg);
+
+	case VIDIOC_DQEVENT:
+		if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
+			return -ENOIOCTLCMD;
+
+		return v4l2_event_dequeue(vfh, arg, file->f_flags & O_NONBLOCK);
+
+	case VIDIOC_SUBSCRIBE_EVENT:
+		return v4l2_subdev_call(sd, core, subscribe_event, vfh, arg);
+
+	case VIDIOC_UNSUBSCRIBE_EVENT:
+		return v4l2_subdev_call(sd, core, unsubscribe_event, vfh, arg);
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+	case VIDIOC_SUBDEV_G_FMT: {
+		struct v4l2_subdev_format *format = arg;
+
+		if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+		    format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+			return -EINVAL;
+
+		if (format->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format);
+	}
+
+	case VIDIOC_SUBDEV_S_FMT: {
+		struct v4l2_subdev_format *format = arg;
+
+		if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+		    format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+			return -EINVAL;
+
+		if (format->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
+	}
+
+	case VIDIOC_SUBDEV_G_CROP: {
+		struct v4l2_subdev_crop *crop = arg;
+
+		if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
+		    crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+			return -EINVAL;
+
+		if (crop->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop);
+	}
+
+	case VIDIOC_SUBDEV_S_CROP: {
+		struct v4l2_subdev_crop *crop = arg;
+
+		if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
+		    crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+			return -EINVAL;
+
+		if (crop->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop);
+	}
+
+	case VIDIOC_SUBDEV_ENUM_MBUS_CODE: {
+		struct v4l2_subdev_mbus_code_enum *code = arg;
+
+		if (code->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, enum_mbus_code, subdev_fh,
+					code);
+	}
+
+	case VIDIOC_SUBDEV_ENUM_FRAME_SIZE: {
+		struct v4l2_subdev_frame_size_enum *fse = arg;
+
+		if (fse->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, enum_frame_size, subdev_fh,
+					fse);
+	}
+
+	case VIDIOC_SUBDEV_G_FRAME_INTERVAL:
+		return v4l2_subdev_call(sd, video, g_frame_interval, arg);
+
+	case VIDIOC_SUBDEV_S_FRAME_INTERVAL:
+		return v4l2_subdev_call(sd, video, s_frame_interval, arg);
+
+	case VIDIOC_SUBDEV_ENUM_FRAME_INTERVAL: {
+		struct v4l2_subdev_frame_interval_enum *fie = arg;
+
+		if (fie->pad >= sd->entity.num_pads)
+			return -EINVAL;
+
+		return v4l2_subdev_call(sd, pad, enum_frame_interval, subdev_fh,
+					fie);
+	}
+#endif
+	default:
+		return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
+	}
+
+	return 0;
+}
+
+static long subdev_ioctl(struct file *file, unsigned int cmd,
+	unsigned long arg)
+{
+	return video_usercopy(file, cmd, arg, subdev_do_ioctl);
+}
+
+static unsigned int subdev_poll(struct file *file, poll_table *wait)
+{
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_subdev *sd = vdev_to_v4l2_subdev(vdev);
+	struct v4l2_fh *fh = file->private_data;
+
+	if (!(sd->flags & V4L2_SUBDEV_FL_HAS_EVENTS))
+		return POLLERR;
+
+	poll_wait(file, &fh->events->wait, wait);
+
+	if (v4l2_event_pending(fh))
+		return POLLPRI;
+
+	return 0;
+}
+
+const struct v4l2_file_operations v4l2_subdev_fops = {
+	.owner = THIS_MODULE,
+	.open = subdev_open,
+	.unlocked_ioctl = subdev_ioctl,
+	.release = subdev_close,
+	.poll = subdev_poll,
+};
+
+void v4l2_subdev_init(struct v4l2_subdev *sd, const struct v4l2_subdev_ops *ops)
+{
+	INIT_LIST_HEAD(&sd->list);
+	BUG_ON(!ops);
+	sd->ops = ops;
+	sd->v4l2_dev = NULL;
+	sd->flags = 0;
+	sd->name[0] = '\0';
+	sd->grp_id = 0;
+	sd->dev_priv = NULL;
+	sd->host_priv = NULL;
+#if defined(CONFIG_MEDIA_CONTROLLER)
+	sd->entity.name = sd->name;
+	sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV;
+#endif
+}
+EXPORT_SYMBOL(v4l2_subdev_init);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/via-camera.c linux-libre-2.6.39-gnu/drivers/media/video/via-camera.c
--- linux-libre-2.6.38-gnu/drivers/media/video/via-camera.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/via-camera.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/via-core.h>
 #include <linux/via-gpio.h>
 #include <linux/via_i2c.h>
+#include <asm/olpc.h>
 
 #include "via-camera.h"
 
@@ -38,14 +39,12 @@
 		"If set, the sensor will be instructed to flip the image "
 		"vertically.");
 
-#ifdef CONFIG_OLPC_XO_1_5
 static int override_serial;
 module_param(override_serial, bool, 0444);
 MODULE_PARM_DESC(override_serial,
 		"The camera driver will normally refuse to load if "
 		"the XO 1.5 serial port is enabled.  Set this option "
-		"to force the issue.");
-#endif
+		"to force-enable the camera.");
 
 /*
  * Basic window sizes.
@@ -1246,6 +1245,62 @@
 /*
  * Power management.
  */
+#ifdef CONFIG_PM
+
+static int viacam_suspend(void *priv)
+{
+	struct via_camera *cam = priv;
+	enum viacam_opstate state = cam->opstate;
+
+	if (cam->opstate != S_IDLE) {
+		viacam_stop_engine(cam);
+		cam->opstate = state; /* So resume restarts */
+	}
+
+	return 0;
+}
+
+static int viacam_resume(void *priv)
+{
+	struct via_camera *cam = priv;
+	int ret = 0;
+
+	/*
+	 * Get back to a reasonable operating state.
+	 */
+	via_write_reg_mask(VIASR, 0x78, 0, 0x80);
+	via_write_reg_mask(VIASR, 0x1e, 0xc0, 0xc0);
+	viacam_int_disable(cam);
+	set_bit(CF_CONFIG_NEEDED, &cam->flags);
+	/*
+	 * Make sure the sensor's power state is correct
+	 */
+	if (cam->users > 0)
+		via_sensor_power_up(cam);
+	else
+		via_sensor_power_down(cam);
+	/*
+	 * If it was operating, try to restart it.
+	 */
+	if (cam->opstate != S_IDLE) {
+		mutex_lock(&cam->lock);
+		ret = viacam_configure_sensor(cam);
+		if (!ret)
+			ret = viacam_config_controller(cam);
+		mutex_unlock(&cam->lock);
+		if (!ret)
+			viacam_start_engine(cam);
+	}
+
+	return ret;
+}
+
+static struct viafb_pm_hooks viacam_pm_hooks = {
+	.suspend = viacam_suspend,
+	.resume = viacam_resume
+};
+
+#endif /* CONFIG_PM */
 
 /*
  * Setup stuff.
@@ -1261,6 +1316,37 @@
 	.release	= video_device_release_empty, /* Check this */
 };
 
+/*
+ * The OLPC folks put the serial port on the same pin as
+ * the camera.	They also get grumpy if we break the
+ * serial port and keep them from using it.  So we have
+ * to check the serial enable bit and not step on it.
+ */
+#define VIACAM_SERIAL_DEVFN 0x88
+#define VIACAM_SERIAL_CREG 0x46
+#define VIACAM_SERIAL_BIT 0x40
+
+static __devinit bool viacam_serial_is_enabled(void)
+{
+	struct pci_bus *pbus = pci_find_bus(0, 0);
+	u8 cbyte;
+
+	pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN,
+			VIACAM_SERIAL_CREG, &cbyte);
+	if ((cbyte & VIACAM_SERIAL_BIT) == 0)
+		return false; /* Not enabled */
+	if (override_serial == 0) {
+		printk(KERN_NOTICE "Via camera: serial port is enabled, " \
+				"refusing to load.\n");
+		printk(KERN_NOTICE "Specify override_serial=1 to force " \
+				"module loading.\n");
+		return true;
+	}
+	printk(KERN_NOTICE "Via camera: overriding serial port\n");
+	pci_bus_write_config_byte(pbus, VIACAM_SERIAL_DEVFN,
+			VIACAM_SERIAL_CREG, cbyte & ~VIACAM_SERIAL_BIT);
+	return false;
+}
 
 static __devinit int viacam_probe(struct platform_device *pdev)
 {
@@ -1292,6 +1378,10 @@
 		printk(KERN_ERR "viacam: No I/O memory, so no pictures\n");
 		return -ENOMEM;
 	}
+
+	if (machine_is_olpc() && viacam_serial_is_enabled())
+		return -EBUSY;
+
 	/*
 	 * Basic structure initialization.
 	 */
@@ -1369,6 +1459,14 @@
 		goto out_irq;
 	video_set_drvdata(&cam->vdev, cam);
 
+#ifdef CONFIG_PM
+	/*
+	 * Hook into PM events
+	 */
+	viacam_pm_hooks.private = cam;
+	viafb_pm_register(&viacam_pm_hooks);
+#endif
+
 	/* Power the sensor down until somebody opens the device */
 	via_sensor_power_down(cam);
 	return 0;
@@ -1395,7 +1493,6 @@
 	return 0;
 }
 
-
 static struct platform_driver viacam_driver = {
 	.driver = {
 		.name = "viafb-camera",
@@ -1404,50 +1501,8 @@
 	.remove = viacam_remove,
 };
 
-
-#ifdef CONFIG_OLPC_XO_1_5
-/*
- * The OLPC folks put the serial port on the same pin as
- * the camera.	They also get grumpy if we break the
- * serial port and keep them from using it.  So we have
- * to check the serial enable bit and not step on it.
- */
-#define VIACAM_SERIAL_DEVFN 0x88
-#define VIACAM_SERIAL_CREG 0x46
-#define VIACAM_SERIAL_BIT 0x40
-
-static __devinit int viacam_check_serial_port(void)
-{
-	struct pci_bus *pbus = pci_find_bus(0, 0);
-	u8 cbyte;
-
-	pci_bus_read_config_byte(pbus, VIACAM_SERIAL_DEVFN,
-			VIACAM_SERIAL_CREG, &cbyte);
-	if ((cbyte & VIACAM_SERIAL_BIT) == 0)
-		return 0; /* Not enabled */
-	if (override_serial == 0) {
-		printk(KERN_NOTICE "Via camera: serial port is enabled, " \
-				"refusing to load.\n");
-		printk(KERN_NOTICE "Specify override_serial=1 to force " \
-				"module loading.\n");
-		return -EBUSY;
-	}
-	printk(KERN_NOTICE "Via camera: overriding serial port\n");
-	pci_bus_write_config_byte(pbus, VIACAM_SERIAL_DEVFN,
-			VIACAM_SERIAL_CREG, cbyte & ~VIACAM_SERIAL_BIT);
-	return 0;
-}
-#endif
-
-
-
-
 static int viacam_init(void)
 {
-#ifdef CONFIG_OLPC_XO_1_5
-	if (viacam_check_serial_port())
-		return -EBUSY;
-#endif
 	return platform_driver_register(&viacam_driver);
 }
 module_init(viacam_init);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-core.c linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-core.c
--- linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1826 @@
+/*
+ * videobuf2-core.c - V4L2 driver helper framework
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.com>
+ *	   Marek Szyprowski <m.szyprowski@samsung.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.
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/sched.h>
+
+#include <media/videobuf2-core.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define dprintk(level, fmt, arg...)					\
+	do {								\
+		if (debug >= level)					\
+			printk(KERN_DEBUG "vb2: " fmt, ## arg);		\
+	} while (0)
+
+#define call_memop(q, plane, op, args...)				\
+	(((q)->mem_ops->op) ?						\
+		((q)->mem_ops->op(args)) : 0)
+
+#define call_qop(q, op, args...)					\
+	(((q)->ops->op) ? ((q)->ops->op(args)) : 0)
+
+#define V4L2_BUFFER_STATE_FLAGS	(V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED | \
+				 V4L2_BUF_FLAG_DONE | V4L2_BUF_FLAG_ERROR)
+
+/**
+ * __vb2_buf_mem_alloc() - allocate video memory for the given buffer
+ */
+static int __vb2_buf_mem_alloc(struct vb2_buffer *vb,
+				unsigned long *plane_sizes)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	void *mem_priv;
+	int plane;
+
+	/* Allocate memory for all planes in this buffer */
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		mem_priv = call_memop(q, plane, alloc, q->alloc_ctx[plane],
+					plane_sizes[plane]);
+		if (IS_ERR_OR_NULL(mem_priv))
+			goto free;
+
+		/* Associate allocator private data with this plane */
+		vb->planes[plane].mem_priv = mem_priv;
+		vb->v4l2_planes[plane].length = plane_sizes[plane];
+	}
+
+	return 0;
+free:
+	/* Free already allocated memory if one of the allocations failed */
+	for (; plane > 0; --plane)
+		call_memop(q, plane, put, vb->planes[plane - 1].mem_priv);
+
+	return -ENOMEM;
+}
+
+/**
+ * __vb2_buf_mem_free() - free memory of the given buffer
+ */
+static void __vb2_buf_mem_free(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
+
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		call_memop(q, plane, put, vb->planes[plane].mem_priv);
+		vb->planes[plane].mem_priv = NULL;
+		dprintk(3, "Freed plane %d of buffer %d\n",
+				plane, vb->v4l2_buf.index);
+	}
+}
+
+/**
+ * __vb2_buf_userptr_put() - release userspace memory associated with
+ * a USERPTR buffer
+ */
+static void __vb2_buf_userptr_put(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned int plane;
+
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		void *mem_priv = vb->planes[plane].mem_priv;
+
+		if (mem_priv) {
+			call_memop(q, plane, put_userptr, mem_priv);
+			vb->planes[plane].mem_priv = NULL;
+		}
+	}
+}
+
+/**
+ * __setup_offsets() - setup unique offsets ("cookies") for every plane in
+ * every buffer on the queue
+ */
+static void __setup_offsets(struct vb2_queue *q)
+{
+	unsigned int buffer, plane;
+	struct vb2_buffer *vb;
+	unsigned long off = 0;
+
+	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+		vb = q->bufs[buffer];
+		if (!vb)
+			continue;
+
+		for (plane = 0; plane < vb->num_planes; ++plane) {
+			vb->v4l2_planes[plane].m.mem_offset = off;
+
+			dprintk(3, "Buffer %d, plane %d offset 0x%08lx\n",
+					buffer, plane, off);
+
+			off += vb->v4l2_planes[plane].length;
+			off = PAGE_ALIGN(off);
+		}
+	}
+}
+
+/**
+ * __vb2_queue_alloc() - allocate videobuf buffer structures and (for MMAP type)
+ * video buffer memory for all buffers/planes on the queue and initializes the
+ * queue
+ *
+ * Returns the number of buffers successfully allocated.
+ */
+static int __vb2_queue_alloc(struct vb2_queue *q, enum v4l2_memory memory,
+			     unsigned int num_buffers, unsigned int num_planes,
+			     unsigned long plane_sizes[])
+{
+	unsigned int buffer;
+	struct vb2_buffer *vb;
+	int ret;
+
+	for (buffer = 0; buffer < num_buffers; ++buffer) {
+		/* Allocate videobuf buffer structures */
+		vb = kzalloc(q->buf_struct_size, GFP_KERNEL);
+		if (!vb) {
+			dprintk(1, "Memory alloc for buffer struct failed\n");
+			break;
+		}
+
+		/* Length stores number of planes for multiplanar buffers */
+		if (V4L2_TYPE_IS_MULTIPLANAR(q->type))
+			vb->v4l2_buf.length = num_planes;
+
+		vb->state = VB2_BUF_STATE_DEQUEUED;
+		vb->vb2_queue = q;
+		vb->num_planes = num_planes;
+		vb->v4l2_buf.index = buffer;
+		vb->v4l2_buf.type = q->type;
+		vb->v4l2_buf.memory = memory;
+
+		/* Allocate video buffer memory for the MMAP type */
+		if (memory == V4L2_MEMORY_MMAP) {
+			ret = __vb2_buf_mem_alloc(vb, plane_sizes);
+			if (ret) {
+				dprintk(1, "Failed allocating memory for "
+						"buffer %d\n", buffer);
+				kfree(vb);
+				break;
+			}
+			/*
+			 * Call the driver-provided buffer initialization
+			 * callback, if given. An error in initialization
+			 * results in queue setup failure.
+			 */
+			ret = call_qop(q, buf_init, vb);
+			if (ret) {
+				dprintk(1, "Buffer %d %p initialization"
+					" failed\n", buffer, vb);
+				__vb2_buf_mem_free(vb);
+				kfree(vb);
+				break;
+			}
+		}
+
+		q->bufs[buffer] = vb;
+	}
+
+	q->num_buffers = buffer;
+
+	__setup_offsets(q);
+
+	dprintk(1, "Allocated %d buffers, %d plane(s) each\n",
+			q->num_buffers, num_planes);
+
+	return buffer;
+}
+
+/**
+ * __vb2_free_mem() - release all video buffer memory for a given queue
+ */
+static void __vb2_free_mem(struct vb2_queue *q)
+{
+	unsigned int buffer;
+	struct vb2_buffer *vb;
+
+	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+		vb = q->bufs[buffer];
+		if (!vb)
+			continue;
+
+		/* Free MMAP buffers or release USERPTR buffers */
+		if (q->memory == V4L2_MEMORY_MMAP)
+			__vb2_buf_mem_free(vb);
+		else
+			__vb2_buf_userptr_put(vb);
+	}
+}
+
+/**
+ * __vb2_queue_free() - free the queue - video memory and related information
+ * and return the queue to an uninitialized state. Might be called even if the
+ * queue has already been freed.
+ */
+static void __vb2_queue_free(struct vb2_queue *q)
+{
+	unsigned int buffer;
+
+	/* Call driver-provided cleanup function for each buffer, if provided */
+	if (q->ops->buf_cleanup) {
+		for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+			if (NULL == q->bufs[buffer])
+				continue;
+			q->ops->buf_cleanup(q->bufs[buffer]);
+		}
+	}
+
+	/* Release video buffer memory */
+	__vb2_free_mem(q);
+
+	/* Free videobuf buffers */
+	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+		kfree(q->bufs[buffer]);
+		q->bufs[buffer] = NULL;
+	}
+
+	q->num_buffers = 0;
+	q->memory = 0;
+}
+
+/**
+ * __verify_planes_array() - verify that the planes array passed in struct
+ * v4l2_buffer from userspace can be safely used
+ */
+static int __verify_planes_array(struct vb2_buffer *vb, struct v4l2_buffer *b)
+{
+	/* Is memory for copying plane information present? */
+	if (NULL == b->m.planes) {
+		dprintk(1, "Multi-planar buffer passed but "
+			   "planes array not provided\n");
+		return -EINVAL;
+	}
+
+	if (b->length < vb->num_planes || b->length > VIDEO_MAX_PLANES) {
+		dprintk(1, "Incorrect planes array length, "
+			   "expected %d, got %d\n", vb->num_planes, b->length);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/**
+ * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
+ * returned to userspace
+ */
+static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	int ret = 0;
+
+	/* Copy back data such as timestamp, flags, input, etc. */
+	memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
+	b->input = vb->v4l2_buf.input;
+	b->reserved = vb->v4l2_buf.reserved;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
+		ret = __verify_planes_array(vb, b);
+		if (ret)
+			return ret;
+
+		/*
+		 * Fill in plane-related data if userspace provided an array
+		 * for it. The memory and size is verified above.
+		 */
+		memcpy(b->m.planes, vb->v4l2_planes,
+			b->length * sizeof(struct v4l2_plane));
+	} else {
+		/*
+		 * We use length and offset in v4l2_planes array even for
+		 * single-planar buffers, but userspace does not.
+		 */
+		b->length = vb->v4l2_planes[0].length;
+		b->bytesused = vb->v4l2_planes[0].bytesused;
+		if (q->memory == V4L2_MEMORY_MMAP)
+			b->m.offset = vb->v4l2_planes[0].m.mem_offset;
+		else if (q->memory == V4L2_MEMORY_USERPTR)
+			b->m.userptr = vb->v4l2_planes[0].m.userptr;
+	}
+
+	/*
+	 * Clear any buffer state related flags.
+	 */
+	b->flags &= ~V4L2_BUFFER_STATE_FLAGS;
+
+	switch (vb->state) {
+	case VB2_BUF_STATE_QUEUED:
+	case VB2_BUF_STATE_ACTIVE:
+		b->flags |= V4L2_BUF_FLAG_QUEUED;
+		break;
+	case VB2_BUF_STATE_ERROR:
+		b->flags |= V4L2_BUF_FLAG_ERROR;
+		/* fall through */
+	case VB2_BUF_STATE_DONE:
+		b->flags |= V4L2_BUF_FLAG_DONE;
+		break;
+	case VB2_BUF_STATE_DEQUEUED:
+		/* nothing */
+		break;
+	}
+
+	if (vb->num_planes_mapped == vb->num_planes)
+		b->flags |= V4L2_BUF_FLAG_MAPPED;
+
+	return ret;
+}
+
+/**
+ * vb2_querybuf() - query video buffer information
+ * @q:		videobuf queue
+ * @b:		buffer struct passed from userspace to vidioc_querybuf handler
+ *		in driver
+ *
+ * Should be called from vidioc_querybuf ioctl handler in driver.
+ * This function will verify the passed v4l2_buffer structure and fill the
+ * relevant information for the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_querybuf handler in driver.
+ */
+int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	struct vb2_buffer *vb;
+
+	if (b->type != q->type) {
+		dprintk(1, "querybuf: wrong buffer type\n");
+		return -EINVAL;
+	}
+
+	if (b->index >= q->num_buffers) {
+		dprintk(1, "querybuf: buffer index out of range\n");
+		return -EINVAL;
+	}
+	vb = q->bufs[b->index];
+
+	return __fill_v4l2_buffer(vb, b);
+}
+EXPORT_SYMBOL(vb2_querybuf);
+
+/**
+ * __verify_userptr_ops() - verify that all memory operations required for
+ * USERPTR queue type have been provided
+ */
+static int __verify_userptr_ops(struct vb2_queue *q)
+{
+	if (!(q->io_modes & VB2_USERPTR) || !q->mem_ops->get_userptr ||
+	    !q->mem_ops->put_userptr)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * __verify_mmap_ops() - verify that all memory operations required for
+ * MMAP queue type have been provided
+ */
+static int __verify_mmap_ops(struct vb2_queue *q)
+{
+	if (!(q->io_modes & VB2_MMAP) || !q->mem_ops->alloc ||
+	    !q->mem_ops->put || !q->mem_ops->mmap)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * __buffers_in_use() - return true if any buffers on the queue are in use and
+ * the queue cannot be freed (by the means of REQBUFS(0)) call
+ */
+static bool __buffers_in_use(struct vb2_queue *q)
+{
+	unsigned int buffer, plane;
+	struct vb2_buffer *vb;
+
+	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+		vb = q->bufs[buffer];
+		for (plane = 0; plane < vb->num_planes; ++plane) {
+			/*
+			 * If num_users() has not been provided, call_memop
+			 * will return 0, apparently nobody cares about this
+			 * case anyway. If num_users() returns more than 1,
+			 * we are not the only user of the plane's memory.
+			 */
+			if (call_memop(q, plane, num_users,
+					vb->planes[plane].mem_priv) > 1)
+				return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * vb2_reqbufs() - Initiate streaming
+ * @q:		videobuf2 queue
+ * @req:	struct passed from userspace to vidioc_reqbufs handler in driver
+ *
+ * Should be called from vidioc_reqbufs ioctl handler of a driver.
+ * This function:
+ * 1) verifies streaming parameters passed from the userspace,
+ * 2) sets up the queue,
+ * 3) negotiates number of buffers and planes per buffer with the driver
+ *    to be used during streaming,
+ * 4) allocates internal buffer structures (struct vb2_buffer), according to
+ *    the agreed parameters,
+ * 5) for MMAP memory type, allocates actual video memory, using the
+ *    memory handling/allocation routines provided during queue initialization
+ *
+ * If req->count is 0, all the memory will be freed instead.
+ * If the queue has been allocated previously (by a previous vb2_reqbufs) call
+ * and the queue is not busy, memory will be reallocated.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_reqbufs handler in driver.
+ */
+int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req)
+{
+	unsigned int num_buffers, num_planes;
+	unsigned long plane_sizes[VIDEO_MAX_PLANES];
+	int ret = 0;
+
+	if (q->fileio) {
+		dprintk(1, "reqbufs: file io in progress\n");
+		return -EBUSY;
+	}
+
+	if (req->memory != V4L2_MEMORY_MMAP
+			&& req->memory != V4L2_MEMORY_USERPTR) {
+		dprintk(1, "reqbufs: unsupported memory type\n");
+		return -EINVAL;
+	}
+
+	if (req->type != q->type) {
+		dprintk(1, "reqbufs: requested type is incorrect\n");
+		return -EINVAL;
+	}
+
+	if (q->streaming) {
+		dprintk(1, "reqbufs: streaming active\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Make sure all the required memory ops for given memory type
+	 * are available.
+	 */
+	if (req->memory == V4L2_MEMORY_MMAP && __verify_mmap_ops(q)) {
+		dprintk(1, "reqbufs: MMAP for current setup unsupported\n");
+		return -EINVAL;
+	}
+
+	if (req->memory == V4L2_MEMORY_USERPTR && __verify_userptr_ops(q)) {
+		dprintk(1, "reqbufs: USERPTR for current setup unsupported\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * If the same number of buffers and memory access method is requested
+	 * then return immediately.
+	 */
+	if (q->memory == req->memory && req->count == q->num_buffers)
+		return 0;
+
+	if (req->count == 0 || q->num_buffers != 0 || q->memory != req->memory) {
+		/*
+		 * We already have buffers allocated, so first check if they
+		 * are not in use and can be freed.
+		 */
+		if (q->memory == V4L2_MEMORY_MMAP && __buffers_in_use(q)) {
+			dprintk(1, "reqbufs: memory in use, cannot free\n");
+			return -EBUSY;
+		}
+
+		__vb2_queue_free(q);
+
+		/*
+		 * In case of REQBUFS(0) return immediately without calling
+		 * driver's queue_setup() callback and allocating resources.
+		 */
+		if (req->count == 0)
+			return 0;
+	}
+
+	/*
+	 * Make sure the requested values and current defaults are sane.
+	 */
+	num_buffers = min_t(unsigned int, req->count, VIDEO_MAX_FRAME);
+	memset(plane_sizes, 0, sizeof(plane_sizes));
+	memset(q->alloc_ctx, 0, sizeof(q->alloc_ctx));
+	q->memory = req->memory;
+
+	/*
+	 * Ask the driver how many buffers and planes per buffer it requires.
+	 * Driver also sets the size and allocator context for each plane.
+	 */
+	ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
+		       plane_sizes, q->alloc_ctx);
+	if (ret)
+		return ret;
+
+	/* Finally, allocate buffers and video memory */
+	ret = __vb2_queue_alloc(q, req->memory, num_buffers, num_planes,
+				plane_sizes);
+	if (ret < 0) {
+		dprintk(1, "Memory allocation failed with error: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Check if driver can handle the allocated number of buffers.
+	 */
+	if (ret < num_buffers) {
+		unsigned int orig_num_buffers;
+
+		orig_num_buffers = num_buffers = ret;
+		ret = call_qop(q, queue_setup, q, &num_buffers, &num_planes,
+			       plane_sizes, q->alloc_ctx);
+		if (ret)
+			goto free_mem;
+
+		if (orig_num_buffers < num_buffers) {
+			ret = -ENOMEM;
+			goto free_mem;
+		}
+
+		/*
+		 * Ok, driver accepted smaller number of buffers.
+		 */
+		ret = num_buffers;
+	}
+
+	/*
+	 * Return the number of successfully allocated buffers
+	 * to the userspace.
+	 */
+	req->count = ret;
+
+	return 0;
+
+free_mem:
+	__vb2_queue_free(q);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_reqbufs);
+
+/**
+ * vb2_plane_vaddr() - Return a kernel virtual address of a given plane
+ * @vb:		vb2_buffer to which the plane in question belongs to
+ * @plane_no:	plane number for which the address is to be returned
+ *
+ * This function returns a kernel virtual address of a given plane if
+ * such a mapping exist, NULL otherwise.
+ */
+void *vb2_plane_vaddr(struct vb2_buffer *vb, unsigned int plane_no)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+
+	if (plane_no > vb->num_planes)
+		return NULL;
+
+	return call_memop(q, plane_no, vaddr, vb->planes[plane_no].mem_priv);
+
+}
+EXPORT_SYMBOL_GPL(vb2_plane_vaddr);
+
+/**
+ * vb2_plane_cookie() - Return allocator specific cookie for the given plane
+ * @vb:		vb2_buffer to which the plane in question belongs to
+ * @plane_no:	plane number for which the cookie is to be returned
+ *
+ * This function returns an allocator specific cookie for a given plane if
+ * available, NULL otherwise. The allocator should provide some simple static
+ * inline function, which would convert this cookie to the allocator specific
+ * type that can be used directly by the driver to access the buffer. This can
+ * be for example physical address, pointer to scatter list or IOMMU mapping.
+ */
+void *vb2_plane_cookie(struct vb2_buffer *vb, unsigned int plane_no)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+
+	if (plane_no > vb->num_planes)
+		return NULL;
+
+	return call_memop(q, plane_no, cookie, vb->planes[plane_no].mem_priv);
+}
+EXPORT_SYMBOL_GPL(vb2_plane_cookie);
+
+/**
+ * vb2_buffer_done() - inform videobuf that an operation on a buffer is finished
+ * @vb:		vb2_buffer returned from the driver
+ * @state:	either VB2_BUF_STATE_DONE if the operation finished successfully
+ *		or VB2_BUF_STATE_ERROR if the operation finished with an error
+ *
+ * This function should be called by the driver after a hardware operation on
+ * a buffer is finished and the buffer may be returned to userspace. The driver
+ * cannot use this buffer anymore until it is queued back to it by videobuf
+ * by the means of buf_queue callback. Only buffers previously queued to the
+ * driver by buf_queue can be passed to this function.
+ */
+void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+	unsigned long flags;
+
+	if (vb->state != VB2_BUF_STATE_ACTIVE)
+		return;
+
+	if (state != VB2_BUF_STATE_DONE && state != VB2_BUF_STATE_ERROR)
+		return;
+
+	dprintk(4, "Done processing on buffer %d, state: %d\n",
+			vb->v4l2_buf.index, vb->state);
+
+	/* Add the buffer to the done buffers list */
+	spin_lock_irqsave(&q->done_lock, flags);
+	vb->state = state;
+	list_add_tail(&vb->done_entry, &q->done_list);
+	atomic_dec(&q->queued_count);
+	spin_unlock_irqrestore(&q->done_lock, flags);
+
+	/* Inform any processes that may be waiting for buffers */
+	wake_up(&q->done_wq);
+}
+EXPORT_SYMBOL_GPL(vb2_buffer_done);
+
+/**
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in
+ * a v4l2_buffer by the userspace
+ */
+static int __fill_vb2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b,
+				struct v4l2_plane *v4l2_planes)
+{
+	unsigned int plane;
+	int ret;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
+		/*
+		 * Verify that the userspace gave us a valid array for
+		 * plane information.
+		 */
+		ret = __verify_planes_array(vb, b);
+		if (ret)
+			return ret;
+
+		/* Fill in driver-provided information for OUTPUT types */
+		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+			/*
+			 * Will have to go up to b->length when API starts
+			 * accepting variable number of planes.
+			 */
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				v4l2_planes[plane].bytesused =
+					b->m.planes[plane].bytesused;
+				v4l2_planes[plane].data_offset =
+					b->m.planes[plane].data_offset;
+			}
+		}
+
+		if (b->memory == V4L2_MEMORY_USERPTR) {
+			for (plane = 0; plane < vb->num_planes; ++plane) {
+				v4l2_planes[plane].m.userptr =
+					b->m.planes[plane].m.userptr;
+				v4l2_planes[plane].length =
+					b->m.planes[plane].length;
+			}
+		}
+	} else {
+		/*
+		 * Single-planar buffers do not use planes array,
+		 * so fill in relevant v4l2_buffer struct fields instead.
+		 * In videobuf we use our internal V4l2_planes struct for
+		 * single-planar buffers as well, for simplicity.
+		 */
+		if (V4L2_TYPE_IS_OUTPUT(b->type))
+			v4l2_planes[0].bytesused = b->bytesused;
+
+		if (b->memory == V4L2_MEMORY_USERPTR) {
+			v4l2_planes[0].m.userptr = b->m.userptr;
+			v4l2_planes[0].length = b->length;
+		}
+	}
+
+	vb->v4l2_buf.field = b->field;
+	vb->v4l2_buf.timestamp = b->timestamp;
+	vb->v4l2_buf.input = b->input;
+	vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
+
+	return 0;
+}
+
+/**
+ * __qbuf_userptr() - handle qbuf of a USERPTR buffer
+ */
+static int __qbuf_userptr(struct vb2_buffer *vb, struct v4l2_buffer *b)
+{
+	struct v4l2_plane planes[VIDEO_MAX_PLANES];
+	struct vb2_queue *q = vb->vb2_queue;
+	void *mem_priv;
+	unsigned int plane;
+	int ret;
+	int write = !V4L2_TYPE_IS_OUTPUT(q->type);
+
+	/* Verify and copy relevant information provided by the userspace */
+	ret = __fill_vb2_buffer(vb, b, planes);
+	if (ret)
+		return ret;
+
+	for (plane = 0; plane < vb->num_planes; ++plane) {
+		/* Skip the plane if already verified */
+		if (vb->v4l2_planes[plane].m.userptr == planes[plane].m.userptr
+		    && vb->v4l2_planes[plane].length == planes[plane].length)
+			continue;
+
+		dprintk(3, "qbuf: userspace address for plane %d changed, "
+				"reacquiring memory\n", plane);
+
+		/* Release previously acquired memory if present */
+		if (vb->planes[plane].mem_priv)
+			call_memop(q, plane, put_userptr,
+					vb->planes[plane].mem_priv);
+
+		vb->planes[plane].mem_priv = NULL;
+
+		/* Acquire each plane's memory */
+		if (q->mem_ops->get_userptr) {
+			mem_priv = q->mem_ops->get_userptr(q->alloc_ctx[plane],
+							planes[plane].m.userptr,
+							planes[plane].length,
+							write);
+			if (IS_ERR(mem_priv)) {
+				dprintk(1, "qbuf: failed acquiring userspace "
+						"memory for plane %d\n", plane);
+				ret = PTR_ERR(mem_priv);
+				goto err;
+			}
+			vb->planes[plane].mem_priv = mem_priv;
+		}
+	}
+
+	/*
+	 * Call driver-specific initialization on the newly acquired buffer,
+	 * if provided.
+	 */
+	ret = call_qop(q, buf_init, vb);
+	if (ret) {
+		dprintk(1, "qbuf: buffer initialization failed\n");
+		goto err;
+	}
+
+	/*
+	 * Now that everything is in order, copy relevant information
+	 * provided by userspace.
+	 */
+	for (plane = 0; plane < vb->num_planes; ++plane)
+		vb->v4l2_planes[plane] = planes[plane];
+
+	return 0;
+err:
+	/* In case of errors, release planes that were already acquired */
+	for (; plane > 0; --plane) {
+		call_memop(q, plane, put_userptr,
+				vb->planes[plane - 1].mem_priv);
+		vb->planes[plane - 1].mem_priv = NULL;
+	}
+
+	return ret;
+}
+
+/**
+ * __qbuf_mmap() - handle qbuf of an MMAP buffer
+ */
+static int __qbuf_mmap(struct vb2_buffer *vb, struct v4l2_buffer *b)
+{
+	return __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+}
+
+/**
+ * __enqueue_in_driver() - enqueue a vb2_buffer in driver for processing
+ */
+static void __enqueue_in_driver(struct vb2_buffer *vb)
+{
+	struct vb2_queue *q = vb->vb2_queue;
+
+	vb->state = VB2_BUF_STATE_ACTIVE;
+	atomic_inc(&q->queued_count);
+	q->ops->buf_queue(vb);
+}
+
+/**
+ * vb2_qbuf() - Queue a buffer from userspace
+ * @q:		videobuf2 queue
+ * @b:		buffer structure passed from userspace to vidioc_qbuf handler
+ *		in driver
+ *
+ * Should be called from vidioc_qbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_prepare callback in the driver (if provided), in which
+ *    driver-specific buffer initialization can be performed,
+ * 3) if streaming is on, queues the buffer in driver by the means of buf_queue
+ *    callback for processing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_qbuf handler in driver.
+ */
+int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
+{
+	struct vb2_buffer *vb;
+	int ret = 0;
+
+	if (q->fileio) {
+		dprintk(1, "qbuf: file io in progress\n");
+		return -EBUSY;
+	}
+
+	if (b->type != q->type) {
+		dprintk(1, "qbuf: invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	if (b->index >= q->num_buffers) {
+		dprintk(1, "qbuf: buffer index out of range\n");
+		return -EINVAL;
+	}
+
+	vb = q->bufs[b->index];
+	if (NULL == vb) {
+		/* Should never happen */
+		dprintk(1, "qbuf: buffer is NULL\n");
+		return -EINVAL;
+	}
+
+	if (b->memory != q->memory) {
+		dprintk(1, "qbuf: invalid memory type\n");
+		return -EINVAL;
+	}
+
+	if (vb->state != VB2_BUF_STATE_DEQUEUED) {
+		dprintk(1, "qbuf: buffer already in use\n");
+		return -EINVAL;
+	}
+
+	if (q->memory == V4L2_MEMORY_MMAP)
+		ret = __qbuf_mmap(vb, b);
+	else if (q->memory == V4L2_MEMORY_USERPTR)
+		ret = __qbuf_userptr(vb, b);
+	else {
+		WARN(1, "Invalid queue type\n");
+		return -EINVAL;
+	}
+
+	if (ret)
+		return ret;
+
+	ret = call_qop(q, buf_prepare, vb);
+	if (ret) {
+		dprintk(1, "qbuf: buffer preparation failed\n");
+		return ret;
+	}
+
+	/*
+	 * Add to the queued buffers list, a buffer will stay on it until
+	 * dequeued in dqbuf.
+	 */
+	list_add_tail(&vb->queued_entry, &q->queued_list);
+	vb->state = VB2_BUF_STATE_QUEUED;
+
+	/*
+	 * If already streaming, give the buffer to driver for processing.
+	 * If not, the buffer will be given to driver on next streamon.
+	 */
+	if (q->streaming)
+		__enqueue_in_driver(vb);
+
+	dprintk(1, "qbuf of buffer %d succeeded\n", vb->v4l2_buf.index);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_qbuf);
+
+/**
+ * __vb2_wait_for_done_vb() - wait for a buffer to become available
+ * for dequeuing
+ *
+ * Will sleep if required for nonblocking == false.
+ */
+static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
+{
+	/*
+	 * All operations on vb_done_list are performed under done_lock
+	 * spinlock protection. However, buffers may be removed from
+	 * it and returned to userspace only while holding both driver's
+	 * lock and the done_lock spinlock. Thus we can be sure that as
+	 * long as we hold the driver's lock, the list will remain not
+	 * empty if list_empty() check succeeds.
+	 */
+
+	for (;;) {
+		int ret;
+
+		if (!q->streaming) {
+			dprintk(1, "Streaming off, will not wait for buffers\n");
+			return -EINVAL;
+		}
+
+		if (!list_empty(&q->done_list)) {
+			/*
+			 * Found a buffer that we were waiting for.
+			 */
+			break;
+		}
+
+		if (nonblocking) {
+			dprintk(1, "Nonblocking and no buffers to dequeue, "
+								"will not wait\n");
+			return -EAGAIN;
+		}
+
+		/*
+		 * We are streaming and blocking, wait for another buffer to
+		 * become ready or for streamoff. Driver's lock is released to
+		 * allow streamoff or qbuf to be called while waiting.
+		 */
+		call_qop(q, wait_prepare, q);
+
+		/*
+		 * All locks have been released, it is safe to sleep now.
+		 */
+		dprintk(3, "Will sleep waiting for buffers\n");
+		ret = wait_event_interruptible(q->done_wq,
+				!list_empty(&q->done_list) || !q->streaming);
+
+		/*
+		 * We need to reevaluate both conditions again after reacquiring
+		 * the locks or return an error if one occurred.
+		 */
+		call_qop(q, wait_finish, q);
+		if (ret)
+			return ret;
+	}
+	return 0;
+}
+
+/**
+ * __vb2_get_done_vb() - get a buffer ready for dequeuing
+ *
+ * Will sleep if required for nonblocking == false.
+ */
+static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
+				int nonblocking)
+{
+	unsigned long flags;
+	int ret;
+
+	/*
+	 * Wait for at least one buffer to become available on the done_list.
+	 */
+	ret = __vb2_wait_for_done_vb(q, nonblocking);
+	if (ret)
+		return ret;
+
+	/*
+	 * Driver's lock has been held since we last verified that done_list
+	 * is not empty, so no need for another list_empty(done_list) check.
+	 */
+	spin_lock_irqsave(&q->done_lock, flags);
+	*vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
+	list_del(&(*vb)->done_entry);
+	spin_unlock_irqrestore(&q->done_lock, flags);
+
+	return 0;
+}
+
+/**
+ * vb2_wait_for_all_buffers() - wait until all buffers are given back to vb2
+ * @q:		videobuf2 queue
+ *
+ * This function will wait until all buffers that have been given to the driver
+ * by buf_queue() are given back to vb2 with vb2_buffer_done(). It doesn't call
+ * wait_prepare, wait_finish pair. It is intended to be called with all locks
+ * taken, for example from stop_streaming() callback.
+ */
+int vb2_wait_for_all_buffers(struct vb2_queue *q)
+{
+	if (!q->streaming) {
+		dprintk(1, "Streaming off, will not wait for buffers\n");
+		return -EINVAL;
+	}
+
+	wait_event(q->done_wq, !atomic_read(&q->queued_count));
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_wait_for_all_buffers);
+
+/**
+ * vb2_dqbuf() - Dequeue a buffer to the userspace
+ * @q:		videobuf2 queue
+ * @b:		buffer structure passed from userspace to vidioc_dqbuf handler
+ *		in driver
+ * @nonblocking: if true, this call will not sleep waiting for a buffer if no
+ *		 buffers ready for dequeuing are present. Normally the driver
+ *		 would be passing (file->f_flags & O_NONBLOCK) here
+ *
+ * Should be called from vidioc_dqbuf ioctl handler of a driver.
+ * This function:
+ * 1) verifies the passed buffer,
+ * 2) calls buf_finish callback in the driver (if provided), in which
+ *    driver can perform any additional operations that may be required before
+ *    returning the buffer to userspace, such as cache sync,
+ * 3) the buffer struct members are filled with relevant information for
+ *    the userspace.
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_dqbuf handler in driver.
+ */
+int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
+{
+	struct vb2_buffer *vb = NULL;
+	int ret;
+
+	if (q->fileio) {
+		dprintk(1, "dqbuf: file io in progress\n");
+		return -EBUSY;
+	}
+
+	if (b->type != q->type) {
+		dprintk(1, "dqbuf: invalid buffer type\n");
+		return -EINVAL;
+	}
+
+	ret = __vb2_get_done_vb(q, &vb, nonblocking);
+	if (ret < 0) {
+		dprintk(1, "dqbuf: error getting next done buffer\n");
+		return ret;
+	}
+
+	ret = call_qop(q, buf_finish, vb);
+	if (ret) {
+		dprintk(1, "dqbuf: buffer finish failed\n");
+		return ret;
+	}
+
+	switch (vb->state) {
+	case VB2_BUF_STATE_DONE:
+		dprintk(3, "dqbuf: Returning done buffer\n");
+		break;
+	case VB2_BUF_STATE_ERROR:
+		dprintk(3, "dqbuf: Returning done buffer with errors\n");
+		break;
+	default:
+		dprintk(1, "dqbuf: Invalid buffer state\n");
+		return -EINVAL;
+	}
+
+	/* Fill buffer information for the userspace */
+	__fill_v4l2_buffer(vb, b);
+	/* Remove from videobuf queue */
+	list_del(&vb->queued_entry);
+
+	dprintk(1, "dqbuf of buffer %d, with state %d\n",
+			vb->v4l2_buf.index, vb->state);
+
+	vb->state = VB2_BUF_STATE_DEQUEUED;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_dqbuf);
+
+/**
+ * vb2_streamon - start streaming
+ * @q:		videobuf2 queue
+ * @type:	type argument passed from userspace to vidioc_streamon handler
+ *
+ * Should be called from vidioc_streamon handler of a driver.
+ * This function:
+ * 1) verifies current state
+ * 2) starts streaming and passes any previously queued buffers to the driver
+ *
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamon handler in the driver.
+ */
+int vb2_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+	struct vb2_buffer *vb;
+	int ret;
+
+	if (q->fileio) {
+		dprintk(1, "streamon: file io in progress\n");
+		return -EBUSY;
+	}
+
+	if (type != q->type) {
+		dprintk(1, "streamon: invalid stream type\n");
+		return -EINVAL;
+	}
+
+	if (q->streaming) {
+		dprintk(1, "streamon: already streaming\n");
+		return -EBUSY;
+	}
+
+	/*
+	 * Cannot start streaming on an OUTPUT device if no buffers have
+	 * been queued yet.
+	 */
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		if (list_empty(&q->queued_list)) {
+			dprintk(1, "streamon: no output buffers queued\n");
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Let driver notice that streaming state has been enabled.
+	 */
+	ret = call_qop(q, start_streaming, q);
+	if (ret) {
+		dprintk(1, "streamon: driver refused to start streaming\n");
+		return ret;
+	}
+
+	q->streaming = 1;
+
+	/*
+	 * If any buffers were queued before streamon,
+	 * we can now pass them to driver for processing.
+	 */
+	list_for_each_entry(vb, &q->queued_list, queued_entry)
+		__enqueue_in_driver(vb);
+
+	dprintk(3, "Streamon successful\n");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_streamon);
+
+/**
+ * __vb2_queue_cancel() - cancel and stop (pause) streaming
+ *
+ * Removes all queued buffers from driver's queue and all buffers queued by
+ * userspace from videobuf's queue. Returns to state after reqbufs.
+ */
+static void __vb2_queue_cancel(struct vb2_queue *q)
+{
+	unsigned int i;
+
+	/*
+	 * Tell driver to stop all transactions and release all queued
+	 * buffers.
+	 */
+	if (q->streaming)
+		call_qop(q, stop_streaming, q);
+	q->streaming = 0;
+
+	/*
+	 * Remove all buffers from videobuf's list...
+	 */
+	INIT_LIST_HEAD(&q->queued_list);
+	/*
+	 * ...and done list; userspace will not receive any buffers it
+	 * has not already dequeued before initiating cancel.
+	 */
+	INIT_LIST_HEAD(&q->done_list);
+	wake_up_all(&q->done_wq);
+
+	/*
+	 * Reinitialize all buffers for next use.
+	 */
+	for (i = 0; i < q->num_buffers; ++i)
+		q->bufs[i]->state = VB2_BUF_STATE_DEQUEUED;
+}
+
+/**
+ * vb2_streamoff - stop streaming
+ * @q:		videobuf2 queue
+ * @type:	type argument passed from userspace to vidioc_streamoff handler
+ *
+ * Should be called from vidioc_streamoff handler of a driver.
+ * This function:
+ * 1) verifies current state,
+ * 2) stop streaming and dequeues any queued buffers, including those previously
+ *    passed to the driver (after waiting for the driver to finish).
+ *
+ * This call can be used for pausing playback.
+ * The return values from this function are intended to be directly returned
+ * from vidioc_streamoff handler in the driver
+ */
+int vb2_streamoff(struct vb2_queue *q, enum v4l2_buf_type type)
+{
+	if (q->fileio) {
+		dprintk(1, "streamoff: file io in progress\n");
+		return -EBUSY;
+	}
+
+	if (type != q->type) {
+		dprintk(1, "streamoff: invalid stream type\n");
+		return -EINVAL;
+	}
+
+	if (!q->streaming) {
+		dprintk(1, "streamoff: not streaming\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Cancel will pause streaming and remove all buffers from the driver
+	 * and videobuf, effectively returning control over them to userspace.
+	 */
+	__vb2_queue_cancel(q);
+
+	dprintk(3, "Streamoff successful\n");
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_streamoff);
+
+/**
+ * __find_plane_by_offset() - find plane associated with the given offset off
+ */
+static int __find_plane_by_offset(struct vb2_queue *q, unsigned long off,
+			unsigned int *_buffer, unsigned int *_plane)
+{
+	struct vb2_buffer *vb;
+	unsigned int buffer, plane;
+
+	/*
+	 * Go over all buffers and their planes, comparing the given offset
+	 * with an offset assigned to each plane. If a match is found,
+	 * return its buffer and plane numbers.
+	 */
+	for (buffer = 0; buffer < q->num_buffers; ++buffer) {
+		vb = q->bufs[buffer];
+
+		for (plane = 0; plane < vb->num_planes; ++plane) {
+			if (vb->v4l2_planes[plane].m.mem_offset == off) {
+				*_buffer = buffer;
+				*_plane = plane;
+				return 0;
+			}
+		}
+	}
+
+	return -EINVAL;
+}
+
+/**
+ * vb2_mmap() - map video buffers into application address space
+ * @q:		videobuf2 queue
+ * @vma:	vma passed to the mmap file operation handler in the driver
+ *
+ * Should be called from mmap file operation handler of a driver.
+ * This function maps one plane of one of the available video buffers to
+ * userspace. To map whole video memory allocated on reqbufs, this function
+ * has to be called once per each plane per each buffer previously allocated.
+ *
+ * When the userspace application calls mmap, it passes to it an offset returned
+ * to it earlier by the means of vidioc_querybuf handler. That offset acts as
+ * a "cookie", which is then used to identify the plane to be mapped.
+ * This function finds a plane with a matching offset and a mapping is performed
+ * by the means of a provided memory operation.
+ *
+ * The return values from this function are intended to be directly returned
+ * from the mmap handler in driver.
+ */
+int vb2_mmap(struct vb2_queue *q, struct vm_area_struct *vma)
+{
+	unsigned long off = vma->vm_pgoff << PAGE_SHIFT;
+	struct vb2_plane *vb_plane;
+	struct vb2_buffer *vb;
+	unsigned int buffer, plane;
+	int ret;
+
+	if (q->memory != V4L2_MEMORY_MMAP) {
+		dprintk(1, "Queue is not currently set up for mmap\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Check memory area access mode.
+	 */
+	if (!(vma->vm_flags & VM_SHARED)) {
+		dprintk(1, "Invalid vma flags, VM_SHARED needed\n");
+		return -EINVAL;
+	}
+	if (V4L2_TYPE_IS_OUTPUT(q->type)) {
+		if (!(vma->vm_flags & VM_WRITE)) {
+			dprintk(1, "Invalid vma flags, VM_WRITE needed\n");
+			return -EINVAL;
+		}
+	} else {
+		if (!(vma->vm_flags & VM_READ)) {
+			dprintk(1, "Invalid vma flags, VM_READ needed\n");
+			return -EINVAL;
+		}
+	}
+
+	/*
+	 * Find the plane corresponding to the offset passed by userspace.
+	 */
+	ret = __find_plane_by_offset(q, off, &buffer, &plane);
+	if (ret)
+		return ret;
+
+	vb = q->bufs[buffer];
+	vb_plane = &vb->planes[plane];
+
+	ret = q->mem_ops->mmap(vb_plane->mem_priv, vma);
+	if (ret)
+		return ret;
+
+	vb_plane->mapped = 1;
+	vb->num_planes_mapped++;
+
+	dprintk(3, "Buffer %d, plane %d successfully mapped\n", buffer, plane);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_mmap);
+
+static int __vb2_init_fileio(struct vb2_queue *q, int read);
+static int __vb2_cleanup_fileio(struct vb2_queue *q);
+
+/**
+ * vb2_poll() - implements poll userspace operation
+ * @q:		videobuf2 queue
+ * @file:	file argument passed to the poll file operation handler
+ * @wait:	wait argument passed to the poll file operation handler
+ *
+ * This function implements poll file operation handler for a driver.
+ * For CAPTURE queues, if a buffer is ready to be dequeued, the userspace will
+ * be informed that the file descriptor of a video device is available for
+ * reading.
+ * For OUTPUT queues, if a buffer is ready to be dequeued, the file descriptor
+ * will be reported as available for writing.
+ *
+ * The return values from this function are intended to be directly returned
+ * from poll handler in driver.
+ */
+unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
+{
+	unsigned long flags;
+	unsigned int ret;
+	struct vb2_buffer *vb = NULL;
+
+	/*
+	 * Start file I/O emulator only if streaming API has not been used yet.
+	 */
+	if (q->num_buffers == 0 && q->fileio == NULL) {
+		if (!V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_READ)) {
+			ret = __vb2_init_fileio(q, 1);
+			if (ret)
+				return POLLERR;
+		}
+		if (V4L2_TYPE_IS_OUTPUT(q->type) && (q->io_modes & VB2_WRITE)) {
+			ret = __vb2_init_fileio(q, 0);
+			if (ret)
+				return POLLERR;
+			/*
+			 * Write to OUTPUT queue can be done immediately.
+			 */
+			return POLLOUT | POLLWRNORM;
+		}
+	}
+
+	/*
+	 * There is nothing to wait for if no buffers have already been queued.
+	 */
+	if (list_empty(&q->queued_list))
+		return POLLERR;
+
+	poll_wait(file, &q->done_wq, wait);
+
+	/*
+	 * Take first buffer available for dequeuing.
+	 */
+	spin_lock_irqsave(&q->done_lock, flags);
+	if (!list_empty(&q->done_list))
+		vb = list_first_entry(&q->done_list, struct vb2_buffer,
+					done_entry);
+	spin_unlock_irqrestore(&q->done_lock, flags);
+
+	if (vb && (vb->state == VB2_BUF_STATE_DONE
+			|| vb->state == VB2_BUF_STATE_ERROR)) {
+		return (V4L2_TYPE_IS_OUTPUT(q->type)) ? POLLOUT | POLLWRNORM :
+			POLLIN | POLLRDNORM;
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_poll);
+
+/**
+ * vb2_queue_init() - initialize a videobuf2 queue
+ * @q:		videobuf2 queue; this structure should be allocated in driver
+ *
+ * The vb2_queue structure should be allocated by the driver. The driver is
+ * responsible of clearing it's content and setting initial values for some
+ * required entries before calling this function.
+ * q->ops, q->mem_ops, q->type and q->io_modes are mandatory. Please refer
+ * to the struct vb2_queue description in include/media/videobuf2-core.h
+ * for more information.
+ */
+int vb2_queue_init(struct vb2_queue *q)
+{
+	BUG_ON(!q);
+	BUG_ON(!q->ops);
+	BUG_ON(!q->mem_ops);
+	BUG_ON(!q->type);
+	BUG_ON(!q->io_modes);
+
+	BUG_ON(!q->ops->queue_setup);
+	BUG_ON(!q->ops->buf_queue);
+
+	INIT_LIST_HEAD(&q->queued_list);
+	INIT_LIST_HEAD(&q->done_list);
+	spin_lock_init(&q->done_lock);
+	init_waitqueue_head(&q->done_wq);
+
+	if (q->buf_struct_size == 0)
+		q->buf_struct_size = sizeof(struct vb2_buffer);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_queue_init);
+
+/**
+ * vb2_queue_release() - stop streaming, release the queue and free memory
+ * @q:		videobuf2 queue
+ *
+ * This function stops streaming and performs necessary clean ups, including
+ * freeing video buffer memory. The driver is responsible for freeing
+ * the vb2_queue structure itself.
+ */
+void vb2_queue_release(struct vb2_queue *q)
+{
+	__vb2_cleanup_fileio(q);
+	__vb2_queue_cancel(q);
+	__vb2_queue_free(q);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_release);
+
+/**
+ * struct vb2_fileio_buf - buffer context used by file io emulator
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. This structure is used for
+ * tracking context related to the buffers.
+ */
+struct vb2_fileio_buf {
+	void *vaddr;
+	unsigned int size;
+	unsigned int pos;
+	unsigned int queued:1;
+};
+
+/**
+ * struct vb2_fileio_data - queue context used by file io emulator
+ *
+ * vb2 provides a compatibility layer and emulator of file io (read and
+ * write) calls on top of streaming API. For proper operation it required
+ * this structure to save the driver state between each call of the read
+ * or write function.
+ */
+struct vb2_fileio_data {
+	struct v4l2_requestbuffers req;
+	struct v4l2_buffer b;
+	struct vb2_fileio_buf bufs[VIDEO_MAX_FRAME];
+	unsigned int index;
+	unsigned int q_count;
+	unsigned int dq_count;
+	unsigned int flags;
+};
+
+/**
+ * __vb2_init_fileio() - initialize file io emulator
+ * @q:		videobuf2 queue
+ * @read:	mode selector (1 means read, 0 means write)
+ */
+static int __vb2_init_fileio(struct vb2_queue *q, int read)
+{
+	struct vb2_fileio_data *fileio;
+	int i, ret;
+	unsigned int count = 0;
+
+	/*
+	 * Sanity check
+	 */
+	if ((read && !(q->io_modes & VB2_READ)) ||
+	   (!read && !(q->io_modes & VB2_WRITE)))
+		BUG();
+
+	/*
+	 * Check if device supports mapping buffers to kernel virtual space.
+	 */
+	if (!q->mem_ops->vaddr)
+		return -EBUSY;
+
+	/*
+	 * Check if streaming api has not been already activated.
+	 */
+	if (q->streaming || q->num_buffers > 0)
+		return -EBUSY;
+
+	/*
+	 * Start with count 1, driver can increase it in queue_setup()
+	 */
+	count = 1;
+
+	dprintk(3, "setting up file io: mode %s, count %d, flags %08x\n",
+		(read) ? "read" : "write", count, q->io_flags);
+
+	fileio = kzalloc(sizeof(struct vb2_fileio_data), GFP_KERNEL);
+	if (fileio == NULL)
+		return -ENOMEM;
+
+	fileio->flags = q->io_flags;
+
+	/*
+	 * Request buffers and use MMAP type to force driver
+	 * to allocate buffers by itself.
+	 */
+	fileio->req.count = count;
+	fileio->req.memory = V4L2_MEMORY_MMAP;
+	fileio->req.type = q->type;
+	ret = vb2_reqbufs(q, &fileio->req);
+	if (ret)
+		goto err_kfree;
+
+	/*
+	 * Check if plane_count is correct
+	 * (multiplane buffers are not supported).
+	 */
+	if (q->bufs[0]->num_planes != 1) {
+		fileio->req.count = 0;
+		ret = -EBUSY;
+		goto err_reqbufs;
+	}
+
+	/*
+	 * Get kernel address of each buffer.
+	 */
+	for (i = 0; i < q->num_buffers; i++) {
+		fileio->bufs[i].vaddr = vb2_plane_vaddr(q->bufs[i], 0);
+		if (fileio->bufs[i].vaddr == NULL)
+			goto err_reqbufs;
+		fileio->bufs[i].size = vb2_plane_size(q->bufs[i], 0);
+	}
+
+	/*
+	 * Read mode requires pre queuing of all buffers.
+	 */
+	if (read) {
+		/*
+		 * Queue all buffers.
+		 */
+		for (i = 0; i < q->num_buffers; i++) {
+			struct v4l2_buffer *b = &fileio->b;
+			memset(b, 0, sizeof(*b));
+			b->type = q->type;
+			b->memory = q->memory;
+			b->index = i;
+			ret = vb2_qbuf(q, b);
+			if (ret)
+				goto err_reqbufs;
+			fileio->bufs[i].queued = 1;
+		}
+
+		/*
+		 * Start streaming.
+		 */
+		ret = vb2_streamon(q, q->type);
+		if (ret)
+			goto err_reqbufs;
+	}
+
+	q->fileio = fileio;
+
+	return ret;
+
+err_reqbufs:
+	vb2_reqbufs(q, &fileio->req);
+
+err_kfree:
+	kfree(fileio);
+	return ret;
+}
+
+/**
+ * __vb2_cleanup_fileio() - free resourced used by file io emulator
+ * @q:		videobuf2 queue
+ */
+static int __vb2_cleanup_fileio(struct vb2_queue *q)
+{
+	struct vb2_fileio_data *fileio = q->fileio;
+
+	if (fileio) {
+		/*
+		 * Hack fileio context to enable direct calls to vb2 ioctl
+		 * interface.
+		 */
+		q->fileio = NULL;
+
+		vb2_streamoff(q, q->type);
+		fileio->req.count = 0;
+		vb2_reqbufs(q, &fileio->req);
+		kfree(fileio);
+		dprintk(3, "file io emulator closed\n");
+	}
+	return 0;
+}
+
+/**
+ * __vb2_perform_fileio() - perform a single file io (read or write) operation
+ * @q:		videobuf2 queue
+ * @data:	pointed to target userspace buffer
+ * @count:	number of bytes to read or write
+ * @ppos:	file handle position tracking pointer
+ * @nonblock:	mode selector (1 means blocking calls, 0 means nonblocking)
+ * @read:	access mode selector (1 means read, 0 means write)
+ */
+static size_t __vb2_perform_fileio(struct vb2_queue *q, char __user *data, size_t count,
+		loff_t *ppos, int nonblock, int read)
+{
+	struct vb2_fileio_data *fileio;
+	struct vb2_fileio_buf *buf;
+	int ret, index;
+
+	dprintk(3, "file io: mode %s, offset %ld, count %zd, %sblocking\n",
+		read ? "read" : "write", (long)*ppos, count,
+		nonblock ? "non" : "");
+
+	if (!data)
+		return -EINVAL;
+
+	/*
+	 * Initialize emulator on first call.
+	 */
+	if (!q->fileio) {
+		ret = __vb2_init_fileio(q, read);
+		dprintk(3, "file io: vb2_init_fileio result: %d\n", ret);
+		if (ret)
+			return ret;
+	}
+	fileio = q->fileio;
+
+	/*
+	 * Hack fileio context to enable direct calls to vb2 ioctl interface.
+	 * The pointer will be restored before returning from this function.
+	 */
+	q->fileio = NULL;
+
+	index = fileio->index;
+	buf = &fileio->bufs[index];
+
+	/*
+	 * Check if we need to dequeue the buffer.
+	 */
+	if (buf->queued) {
+		struct vb2_buffer *vb;
+
+		/*
+		 * Call vb2_dqbuf to get buffer back.
+		 */
+		memset(&fileio->b, 0, sizeof(fileio->b));
+		fileio->b.type = q->type;
+		fileio->b.memory = q->memory;
+		fileio->b.index = index;
+		ret = vb2_dqbuf(q, &fileio->b, nonblock);
+		dprintk(5, "file io: vb2_dqbuf result: %d\n", ret);
+		if (ret)
+			goto end;
+		fileio->dq_count += 1;
+
+		/*
+		 * Get number of bytes filled by the driver
+		 */
+		vb = q->bufs[index];
+		buf->size = vb2_get_plane_payload(vb, 0);
+		buf->queued = 0;
+	}
+
+	/*
+	 * Limit count on last few bytes of the buffer.
+	 */
+	if (buf->pos + count > buf->size) {
+		count = buf->size - buf->pos;
+		dprintk(5, "reducing read count: %zd\n", count);
+	}
+
+	/*
+	 * Transfer data to userspace.
+	 */
+	dprintk(3, "file io: copying %zd bytes - buffer %d, offset %u\n",
+		count, index, buf->pos);
+	if (read)
+		ret = copy_to_user(data, buf->vaddr + buf->pos, count);
+	else
+		ret = copy_from_user(buf->vaddr + buf->pos, data, count);
+	if (ret) {
+		dprintk(3, "file io: error copying data\n");
+		ret = -EFAULT;
+		goto end;
+	}
+
+	/*
+	 * Update counters.
+	 */
+	buf->pos += count;
+	*ppos += count;
+
+	/*
+	 * Queue next buffer if required.
+	 */
+	if (buf->pos == buf->size ||
+	   (!read && (fileio->flags & VB2_FILEIO_WRITE_IMMEDIATELY))) {
+		/*
+		 * Check if this is the last buffer to read.
+		 */
+		if (read && (fileio->flags & VB2_FILEIO_READ_ONCE) &&
+		    fileio->dq_count == 1) {
+			dprintk(3, "file io: read limit reached\n");
+			/*
+			 * Restore fileio pointer and release the context.
+			 */
+			q->fileio = fileio;
+			return __vb2_cleanup_fileio(q);
+		}
+
+		/*
+		 * Call vb2_qbuf and give buffer to the driver.
+		 */
+		memset(&fileio->b, 0, sizeof(fileio->b));
+		fileio->b.type = q->type;
+		fileio->b.memory = q->memory;
+		fileio->b.index = index;
+		fileio->b.bytesused = buf->pos;
+		ret = vb2_qbuf(q, &fileio->b);
+		dprintk(5, "file io: vb2_dbuf result: %d\n", ret);
+		if (ret)
+			goto end;
+
+		/*
+		 * Buffer has been queued, update the status
+		 */
+		buf->pos = 0;
+		buf->queued = 1;
+		buf->size = q->bufs[0]->v4l2_planes[0].length;
+		fileio->q_count += 1;
+
+		/*
+		 * Switch to the next buffer
+		 */
+		fileio->index = (index + 1) % q->num_buffers;
+
+		/*
+		 * Start streaming if required.
+		 */
+		if (!read && !q->streaming) {
+			ret = vb2_streamon(q, q->type);
+			if (ret)
+				goto end;
+		}
+	}
+
+	/*
+	 * Return proper number of bytes processed.
+	 */
+	if (ret == 0)
+		ret = count;
+end:
+	/*
+	 * Restore the fileio context and block vb2 ioctl interface.
+	 */
+	q->fileio = fileio;
+	return ret;
+}
+
+size_t vb2_read(struct vb2_queue *q, char __user *data, size_t count,
+		loff_t *ppos, int nonblocking)
+{
+	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 1);
+}
+EXPORT_SYMBOL_GPL(vb2_read);
+
+size_t vb2_write(struct vb2_queue *q, char __user *data, size_t count,
+		loff_t *ppos, int nonblocking)
+{
+	return __vb2_perform_fileio(q, data, count, ppos, nonblocking, 0);
+}
+EXPORT_SYMBOL_GPL(vb2_write);
+
+MODULE_DESCRIPTION("Driver helper framework for Video for Linux 2");
+MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>, Marek Szyprowski");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-dma-contig.c linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-dma-contig.c
--- linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-dma-contig.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-dma-contig.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,185 @@
+/*
+ * videobuf2-dma-contig.c - DMA contig memory allocator for videobuf2
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.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.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-memops.h>
+
+struct vb2_dc_conf {
+	struct device		*dev;
+};
+
+struct vb2_dc_buf {
+	struct vb2_dc_conf		*conf;
+	void				*vaddr;
+	dma_addr_t			paddr;
+	unsigned long			size;
+	struct vm_area_struct		*vma;
+	atomic_t			refcount;
+	struct vb2_vmarea_handler	handler;
+};
+
+static void vb2_dma_contig_put(void *buf_priv);
+
+static void *vb2_dma_contig_alloc(void *alloc_ctx, unsigned long size)
+{
+	struct vb2_dc_conf *conf = alloc_ctx;
+	struct vb2_dc_buf *buf;
+
+	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	buf->vaddr = dma_alloc_coherent(conf->dev, size, &buf->paddr,
+					GFP_KERNEL);
+	if (!buf->vaddr) {
+		dev_err(conf->dev, "dma_alloc_coherent of size %ld failed\n",
+			size);
+		kfree(buf);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	buf->conf = conf;
+	buf->size = size;
+
+	buf->handler.refcount = &buf->refcount;
+	buf->handler.put = vb2_dma_contig_put;
+	buf->handler.arg = buf;
+
+	atomic_inc(&buf->refcount);
+
+	return buf;
+}
+
+static void vb2_dma_contig_put(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	if (atomic_dec_and_test(&buf->refcount)) {
+		dma_free_coherent(buf->conf->dev, buf->size, buf->vaddr,
+				  buf->paddr);
+		kfree(buf);
+	}
+}
+
+static void *vb2_dma_contig_cookie(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return &buf->paddr;
+}
+
+static void *vb2_dma_contig_vaddr(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+	if (!buf)
+		return 0;
+
+	return buf->vaddr;
+}
+
+static unsigned int vb2_dma_contig_num_users(void *buf_priv)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	return atomic_read(&buf->refcount);
+}
+
+static int vb2_dma_contig_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+	struct vb2_dc_buf *buf = buf_priv;
+
+	if (!buf) {
+		printk(KERN_ERR "No buffer to map\n");
+		return -EINVAL;
+	}
+
+	return vb2_mmap_pfn_range(vma, buf->paddr, buf->size,
+				  &vb2_common_vm_ops, &buf->handler);
+}
+
+static void *vb2_dma_contig_get_userptr(void *alloc_ctx, unsigned long vaddr,
+					unsigned long size, int write)
+{
+	struct vb2_dc_buf *buf;
+	struct vm_area_struct *vma;
+	dma_addr_t paddr = 0;
+	int ret;
+
+	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	if (!buf)
+		return ERR_PTR(-ENOMEM);
+
+	ret = vb2_get_contig_userptr(vaddr, size, &vma, &paddr);
+	if (ret) {
+		printk(KERN_ERR "Failed acquiring VMA for vaddr 0x%08lx\n",
+				vaddr);
+		kfree(buf);
+		return ERR_PTR(ret);
+	}
+
+	buf->size = size;
+	buf->paddr = paddr;
+	buf->vma = vma;
+
+	return buf;
+}
+
+static void vb2_dma_contig_put_userptr(void *mem_priv)
+{
+	struct vb2_dc_buf *buf = mem_priv;
+
+	if (!buf)
+		return;
+
+	vb2_put_vma(buf->vma);
+	kfree(buf);
+}
+
+const struct vb2_mem_ops vb2_dma_contig_memops = {
+	.alloc		= vb2_dma_contig_alloc,
+	.put		= vb2_dma_contig_put,
+	.cookie		= vb2_dma_contig_cookie,
+	.vaddr		= vb2_dma_contig_vaddr,
+	.mmap		= vb2_dma_contig_mmap,
+	.get_userptr	= vb2_dma_contig_get_userptr,
+	.put_userptr	= vb2_dma_contig_put_userptr,
+	.num_users	= vb2_dma_contig_num_users,
+};
+EXPORT_SYMBOL_GPL(vb2_dma_contig_memops);
+
+void *vb2_dma_contig_init_ctx(struct device *dev)
+{
+	struct vb2_dc_conf *conf;
+
+	conf = kzalloc(sizeof *conf, GFP_KERNEL);
+	if (!conf)
+		return ERR_PTR(-ENOMEM);
+
+	conf->dev = dev;
+
+	return conf;
+}
+EXPORT_SYMBOL_GPL(vb2_dma_contig_init_ctx);
+
+void vb2_dma_contig_cleanup_ctx(void *alloc_ctx)
+{
+	kfree(alloc_ctx);
+}
+EXPORT_SYMBOL_GPL(vb2_dma_contig_cleanup_ctx);
+
+MODULE_DESCRIPTION("DMA-contig memory handling routines for videobuf2");
+MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-dma-sg.c linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-dma-sg.c
--- linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-dma-sg.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-dma-sg.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,294 @@
+/*
+ * videobuf2-dma-sg.c - dma scatter/gather memory allocator for videobuf2
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Andrzej Pietrasiewicz <andrzej.p@samsung.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.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/scatterlist.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-memops.h>
+#include <media/videobuf2-dma-sg.h>
+
+struct vb2_dma_sg_buf {
+	void				*vaddr;
+	struct page			**pages;
+	int				write;
+	int				offset;
+	struct vb2_dma_sg_desc		sg_desc;
+	atomic_t			refcount;
+	struct vb2_vmarea_handler	handler;
+};
+
+static void vb2_dma_sg_put(void *buf_priv);
+
+static void *vb2_dma_sg_alloc(void *alloc_ctx, unsigned long size)
+{
+	struct vb2_dma_sg_buf *buf;
+	int i;
+
+	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	if (!buf)
+		return NULL;
+
+	buf->vaddr = NULL;
+	buf->write = 0;
+	buf->offset = 0;
+	buf->sg_desc.size = size;
+	buf->sg_desc.num_pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+
+	buf->sg_desc.sglist = vmalloc(buf->sg_desc.num_pages *
+				      sizeof(*buf->sg_desc.sglist));
+	if (!buf->sg_desc.sglist)
+		goto fail_sglist_alloc;
+	memset(buf->sg_desc.sglist, 0, buf->sg_desc.num_pages *
+	       sizeof(*buf->sg_desc.sglist));
+	sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages);
+
+	buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *),
+			     GFP_KERNEL);
+	if (!buf->pages)
+		goto fail_pages_array_alloc;
+
+	for (i = 0; i < buf->sg_desc.num_pages; ++i) {
+		buf->pages[i] = alloc_page(GFP_KERNEL | __GFP_ZERO);
+		if (NULL == buf->pages[i])
+			goto fail_pages_alloc;
+		sg_set_page(&buf->sg_desc.sglist[i],
+			    buf->pages[i], PAGE_SIZE, 0);
+	}
+
+	buf->handler.refcount = &buf->refcount;
+	buf->handler.put = vb2_dma_sg_put;
+	buf->handler.arg = buf;
+
+	atomic_inc(&buf->refcount);
+
+	printk(KERN_DEBUG "%s: Allocated buffer of %d pages\n",
+		__func__, buf->sg_desc.num_pages);
+
+	if (!buf->vaddr)
+		buf->vaddr = vm_map_ram(buf->pages,
+					buf->sg_desc.num_pages,
+					-1,
+					PAGE_KERNEL);
+	return buf;
+
+fail_pages_alloc:
+	while (--i >= 0)
+		__free_page(buf->pages[i]);
+	kfree(buf->pages);
+
+fail_pages_array_alloc:
+	vfree(buf->sg_desc.sglist);
+
+fail_sglist_alloc:
+	kfree(buf);
+	return NULL;
+}
+
+static void vb2_dma_sg_put(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+	int i = buf->sg_desc.num_pages;
+
+	if (atomic_dec_and_test(&buf->refcount)) {
+		printk(KERN_DEBUG "%s: Freeing buffer of %d pages\n", __func__,
+			buf->sg_desc.num_pages);
+		if (buf->vaddr)
+			vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
+		vfree(buf->sg_desc.sglist);
+		while (--i >= 0)
+			__free_page(buf->pages[i]);
+		kfree(buf->pages);
+		kfree(buf);
+	}
+}
+
+static void *vb2_dma_sg_get_userptr(void *alloc_ctx, unsigned long vaddr,
+				    unsigned long size, int write)
+{
+	struct vb2_dma_sg_buf *buf;
+	unsigned long first, last;
+	int num_pages_from_user, i;
+
+	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	if (!buf)
+		return NULL;
+
+	buf->vaddr = NULL;
+	buf->write = write;
+	buf->offset = vaddr & ~PAGE_MASK;
+	buf->sg_desc.size = size;
+
+	first = (vaddr           & PAGE_MASK) >> PAGE_SHIFT;
+	last  = ((vaddr + size - 1) & PAGE_MASK) >> PAGE_SHIFT;
+	buf->sg_desc.num_pages = last - first + 1;
+
+	buf->sg_desc.sglist = vmalloc(
+		buf->sg_desc.num_pages * sizeof(*buf->sg_desc.sglist));
+	if (!buf->sg_desc.sglist)
+		goto userptr_fail_sglist_alloc;
+
+	memset(buf->sg_desc.sglist, 0,
+		buf->sg_desc.num_pages * sizeof(*buf->sg_desc.sglist));
+	sg_init_table(buf->sg_desc.sglist, buf->sg_desc.num_pages);
+
+	buf->pages = kzalloc(buf->sg_desc.num_pages * sizeof(struct page *),
+			     GFP_KERNEL);
+	if (!buf->pages)
+		goto userptr_fail_pages_array_alloc;
+
+	down_read(&current->mm->mmap_sem);
+	num_pages_from_user = get_user_pages(current, current->mm,
+					     vaddr & PAGE_MASK,
+					     buf->sg_desc.num_pages,
+					     write,
+					     1, /* force */
+					     buf->pages,
+					     NULL);
+	up_read(&current->mm->mmap_sem);
+	if (num_pages_from_user != buf->sg_desc.num_pages)
+		goto userptr_fail_get_user_pages;
+
+	sg_set_page(&buf->sg_desc.sglist[0], buf->pages[0],
+		    PAGE_SIZE - buf->offset, buf->offset);
+	size -= PAGE_SIZE - buf->offset;
+	for (i = 1; i < buf->sg_desc.num_pages; ++i) {
+		sg_set_page(&buf->sg_desc.sglist[i], buf->pages[i],
+			    min_t(size_t, PAGE_SIZE, size), 0);
+		size -= min_t(size_t, PAGE_SIZE, size);
+	}
+	return buf;
+
+userptr_fail_get_user_pages:
+	printk(KERN_DEBUG "get_user_pages requested/got: %d/%d]\n",
+	       num_pages_from_user, buf->sg_desc.num_pages);
+	while (--num_pages_from_user >= 0)
+		put_page(buf->pages[num_pages_from_user]);
+	kfree(buf->pages);
+
+userptr_fail_pages_array_alloc:
+	vfree(buf->sg_desc.sglist);
+
+userptr_fail_sglist_alloc:
+	kfree(buf);
+	return NULL;
+}
+
+/*
+ * @put_userptr: inform the allocator that a USERPTR buffer will no longer
+ *		 be used
+ */
+static void vb2_dma_sg_put_userptr(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+	int i = buf->sg_desc.num_pages;
+
+	printk(KERN_DEBUG "%s: Releasing userspace buffer of %d pages\n",
+	       __func__, buf->sg_desc.num_pages);
+	if (buf->vaddr)
+		vm_unmap_ram(buf->vaddr, buf->sg_desc.num_pages);
+	while (--i >= 0) {
+		if (buf->write)
+			set_page_dirty_lock(buf->pages[i]);
+		put_page(buf->pages[i]);
+	}
+	vfree(buf->sg_desc.sglist);
+	kfree(buf->pages);
+	kfree(buf);
+}
+
+static void *vb2_dma_sg_vaddr(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+
+	BUG_ON(!buf);
+
+	if (!buf->vaddr)
+		buf->vaddr = vm_map_ram(buf->pages,
+					buf->sg_desc.num_pages,
+					-1,
+					PAGE_KERNEL);
+
+	/* add offset in case userptr is not page-aligned */
+	return buf->vaddr + buf->offset;
+}
+
+static unsigned int vb2_dma_sg_num_users(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+
+	return atomic_read(&buf->refcount);
+}
+
+static int vb2_dma_sg_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+	unsigned long uaddr = vma->vm_start;
+	unsigned long usize = vma->vm_end - vma->vm_start;
+	int i = 0;
+
+	if (!buf) {
+		printk(KERN_ERR "No memory to map\n");
+		return -EINVAL;
+	}
+
+	do {
+		int ret;
+
+		ret = vm_insert_page(vma, uaddr, buf->pages[i++]);
+		if (ret) {
+			printk(KERN_ERR "Remapping memory, error: %d\n", ret);
+			return ret;
+		}
+
+		uaddr += PAGE_SIZE;
+		usize -= PAGE_SIZE;
+	} while (usize > 0);
+
+
+	/*
+	 * Use common vm_area operations to track buffer refcount.
+	 */
+	vma->vm_private_data	= &buf->handler;
+	vma->vm_ops		= &vb2_common_vm_ops;
+
+	vma->vm_ops->open(vma);
+
+	return 0;
+}
+
+static void *vb2_dma_sg_cookie(void *buf_priv)
+{
+	struct vb2_dma_sg_buf *buf = buf_priv;
+
+	return &buf->sg_desc;
+}
+
+const struct vb2_mem_ops vb2_dma_sg_memops = {
+	.alloc		= vb2_dma_sg_alloc,
+	.put		= vb2_dma_sg_put,
+	.get_userptr	= vb2_dma_sg_get_userptr,
+	.put_userptr	= vb2_dma_sg_put_userptr,
+	.vaddr		= vb2_dma_sg_vaddr,
+	.mmap		= vb2_dma_sg_mmap,
+	.num_users	= vb2_dma_sg_num_users,
+	.cookie		= vb2_dma_sg_cookie,
+};
+EXPORT_SYMBOL_GPL(vb2_dma_sg_memops);
+
+MODULE_DESCRIPTION("dma scatter/gather memory handling routines for videobuf2");
+MODULE_AUTHOR("Andrzej Pietrasiewicz");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-memops.c linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-memops.c
--- linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-memops.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-memops.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,235 @@
+/*
+ * videobuf2-memops.c - generic memory handling routines for videobuf2
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.com>
+ *	   Marek Szyprowski <m.szyprowski@samsung.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.
+ */
+
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/dma-mapping.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
+#include <linux/sched.h>
+#include <linux/file.h>
+#include <linux/slab.h>
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-memops.h>
+
+/**
+ * vb2_get_vma() - acquire and lock the virtual memory area
+ * @vma:	given virtual memory area
+ *
+ * This function attempts to acquire an area mapped in the userspace for
+ * the duration of a hardware operation. The area is "locked" by performing
+ * the same set of operation that are done when process calls fork() and
+ * memory areas are duplicated.
+ *
+ * Returns a copy of a virtual memory region on success or NULL.
+ */
+struct vm_area_struct *vb2_get_vma(struct vm_area_struct *vma)
+{
+	struct vm_area_struct *vma_copy;
+
+	vma_copy = kmalloc(sizeof(*vma_copy), GFP_KERNEL);
+	if (vma_copy == NULL)
+		return NULL;
+
+	if (vma->vm_ops && vma->vm_ops->open)
+		vma->vm_ops->open(vma);
+
+	if (vma->vm_file)
+		get_file(vma->vm_file);
+
+	memcpy(vma_copy, vma, sizeof(*vma));
+
+	vma_copy->vm_mm = NULL;
+	vma_copy->vm_next = NULL;
+	vma_copy->vm_prev = NULL;
+
+	return vma_copy;
+}
+
+/**
+ * vb2_put_userptr() - release a userspace virtual memory area
+ * @vma:	virtual memory region associated with the area to be released
+ *
+ * This function releases the previously acquired memory area after a hardware
+ * operation.
+ */
+void vb2_put_vma(struct vm_area_struct *vma)
+{
+	if (!vma)
+		return;
+
+	if (vma->vm_file)
+		fput(vma->vm_file);
+
+	if (vma->vm_ops && vma->vm_ops->close)
+		vma->vm_ops->close(vma);
+
+	kfree(vma);
+}
+EXPORT_SYMBOL_GPL(vb2_put_vma);
+
+/**
+ * vb2_get_contig_userptr() - lock physically contiguous userspace mapped memory
+ * @vaddr:	starting virtual address of the area to be verified
+ * @size:	size of the area
+ * @res_paddr:	will return physical address for the given vaddr
+ * @res_vma:	will return locked copy of struct vm_area for the given area
+ *
+ * This function will go through memory area of size @size mapped at @vaddr and
+ * verify that the underlying physical pages are contiguous. If they are
+ * contiguous the virtual memory area is locked and a @res_vma is filled with
+ * the copy and @res_pa set to the physical address of the buffer.
+ *
+ * Returns 0 on success.
+ */
+int vb2_get_contig_userptr(unsigned long vaddr, unsigned long size,
+			   struct vm_area_struct **res_vma, dma_addr_t *res_pa)
+{
+	struct mm_struct *mm = current->mm;
+	struct vm_area_struct *vma;
+	unsigned long offset, start, end;
+	unsigned long this_pfn, prev_pfn;
+	dma_addr_t pa = 0;
+	int ret = -EFAULT;
+
+	start = vaddr;
+	offset = start & ~PAGE_MASK;
+	end = start + size;
+
+	down_read(&mm->mmap_sem);
+	vma = find_vma(mm, start);
+
+	if (vma == NULL || vma->vm_end < end)
+		goto done;
+
+	for (prev_pfn = 0; start < end; start += PAGE_SIZE) {
+		ret = follow_pfn(vma, start, &this_pfn);
+		if (ret)
+			goto done;
+
+		if (prev_pfn == 0)
+			pa = this_pfn << PAGE_SHIFT;
+		else if (this_pfn != prev_pfn + 1) {
+			ret = -EFAULT;
+			goto done;
+		}
+		prev_pfn = this_pfn;
+	}
+
+	/*
+	 * Memory is contigous, lock vma and return to the caller
+	 */
+	*res_vma = vb2_get_vma(vma);
+	if (*res_vma == NULL) {
+		ret = -ENOMEM;
+		goto done;
+	}
+	*res_pa = pa + offset;
+	ret = 0;
+
+done:
+	up_read(&mm->mmap_sem);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vb2_get_contig_userptr);
+
+/**
+ * vb2_mmap_pfn_range() - map physical pages to userspace
+ * @vma:	virtual memory region for the mapping
+ * @paddr:	starting physical address of the memory to be mapped
+ * @size:	size of the memory to be mapped
+ * @vm_ops:	vm operations to be assigned to the created area
+ * @priv:	private data to be associated with the area
+ *
+ * Returns 0 on success.
+ */
+int vb2_mmap_pfn_range(struct vm_area_struct *vma, unsigned long paddr,
+				unsigned long size,
+				const struct vm_operations_struct *vm_ops,
+				void *priv)
+{
+	int ret;
+
+	size = min_t(unsigned long, vma->vm_end - vma->vm_start, size);
+
+	vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+	ret = remap_pfn_range(vma, vma->vm_start, paddr >> PAGE_SHIFT,
+				size, vma->vm_page_prot);
+	if (ret) {
+		printk(KERN_ERR "Remapping memory failed, error: %d\n", ret);
+		return ret;
+	}
+
+	vma->vm_flags		|= VM_DONTEXPAND | VM_RESERVED;
+	vma->vm_private_data	= priv;
+	vma->vm_ops		= vm_ops;
+
+	vma->vm_ops->open(vma);
+
+	printk(KERN_DEBUG "%s: mapped paddr 0x%08lx at 0x%08lx, size %ld\n",
+			__func__, paddr, vma->vm_start, size);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(vb2_mmap_pfn_range);
+
+/**
+ * vb2_common_vm_open() - increase refcount of the vma
+ * @vma:	virtual memory region for the mapping
+ *
+ * This function adds another user to the provided vma. It expects
+ * struct vb2_vmarea_handler pointer in vma->vm_private_data.
+ */
+static void vb2_common_vm_open(struct vm_area_struct *vma)
+{
+	struct vb2_vmarea_handler *h = vma->vm_private_data;
+
+	printk(KERN_DEBUG "%s: %p, refcount: %d, vma: %08lx-%08lx\n",
+	       __func__, h, atomic_read(h->refcount), vma->vm_start,
+	       vma->vm_end);
+
+	atomic_inc(h->refcount);
+}
+
+/**
+ * vb2_common_vm_close() - decrease refcount of the vma
+ * @vma:	virtual memory region for the mapping
+ *
+ * This function releases the user from the provided vma. It expects
+ * struct vb2_vmarea_handler pointer in vma->vm_private_data.
+ */
+static void vb2_common_vm_close(struct vm_area_struct *vma)
+{
+	struct vb2_vmarea_handler *h = vma->vm_private_data;
+
+	printk(KERN_DEBUG "%s: %p, refcount: %d, vma: %08lx-%08lx\n",
+	       __func__, h, atomic_read(h->refcount), vma->vm_start,
+	       vma->vm_end);
+
+	h->put(h->arg);
+}
+
+/**
+ * vb2_common_vm_ops - common vm_ops used for tracking refcount of mmaped
+ * video buffers
+ */
+const struct vm_operations_struct vb2_common_vm_ops = {
+	.open = vb2_common_vm_open,
+	.close = vb2_common_vm_close,
+};
+EXPORT_SYMBOL_GPL(vb2_common_vm_ops);
+
+MODULE_DESCRIPTION("common memory handling routines for videobuf2");
+MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-vmalloc.c linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-vmalloc.c
--- linux-libre-2.6.38-gnu/drivers/media/video/videobuf2-vmalloc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/media/video/videobuf2-vmalloc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,132 @@
+/*
+ * videobuf2-vmalloc.c - vmalloc memory allocator for videobuf2
+ *
+ * Copyright (C) 2010 Samsung Electronics
+ *
+ * Author: Pawel Osciak <pawel@osciak.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.
+ */
+
+#include <linux/module.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-memops.h>
+
+struct vb2_vmalloc_buf {
+	void				*vaddr;
+	unsigned long			size;
+	atomic_t			refcount;
+	struct vb2_vmarea_handler	handler;
+};
+
+static void vb2_vmalloc_put(void *buf_priv);
+
+static void *vb2_vmalloc_alloc(void *alloc_ctx, unsigned long size)
+{
+	struct vb2_vmalloc_buf *buf;
+
+	buf = kzalloc(sizeof *buf, GFP_KERNEL);
+	if (!buf)
+		return NULL;
+
+	buf->size = size;
+	buf->vaddr = vmalloc_user(buf->size);
+	buf->handler.refcount = &buf->refcount;
+	buf->handler.put = vb2_vmalloc_put;
+	buf->handler.arg = buf;
+
+	if (!buf->vaddr) {
+		printk(KERN_ERR "vmalloc of size %ld failed\n", buf->size);
+		kfree(buf);
+		return NULL;
+	}
+
+	atomic_inc(&buf->refcount);
+	printk(KERN_DEBUG "Allocated vmalloc buffer of size %ld at vaddr=%p\n",
+			buf->size, buf->vaddr);
+
+	return buf;
+}
+
+static void vb2_vmalloc_put(void *buf_priv)
+{
+	struct vb2_vmalloc_buf *buf = buf_priv;
+
+	if (atomic_dec_and_test(&buf->refcount)) {
+		printk(KERN_DEBUG "%s: Freeing vmalloc mem at vaddr=%p\n",
+			__func__, buf->vaddr);
+		vfree(buf->vaddr);
+		kfree(buf);
+	}
+}
+
+static void *vb2_vmalloc_vaddr(void *buf_priv)
+{
+	struct vb2_vmalloc_buf *buf = buf_priv;
+
+	BUG_ON(!buf);
+
+	if (!buf->vaddr) {
+		printk(KERN_ERR "Address of an unallocated plane requested\n");
+		return NULL;
+	}
+
+	return buf->vaddr;
+}
+
+static unsigned int vb2_vmalloc_num_users(void *buf_priv)
+{
+	struct vb2_vmalloc_buf *buf = buf_priv;
+	return atomic_read(&buf->refcount);
+}
+
+static int vb2_vmalloc_mmap(void *buf_priv, struct vm_area_struct *vma)
+{
+	struct vb2_vmalloc_buf *buf = buf_priv;
+	int ret;
+
+	if (!buf) {
+		printk(KERN_ERR "No memory to map\n");
+		return -EINVAL;
+	}
+
+	ret = remap_vmalloc_range(vma, buf->vaddr, 0);
+	if (ret) {
+		printk(KERN_ERR "Remapping vmalloc memory, error: %d\n", ret);
+		return ret;
+	}
+
+	/*
+	 * Make sure that vm_areas for 2 buffers won't be merged together
+	 */
+	vma->vm_flags		|= VM_DONTEXPAND;
+
+	/*
+	 * Use common vm_area operations to track buffer refcount.
+	 */
+	vma->vm_private_data	= &buf->handler;
+	vma->vm_ops		= &vb2_common_vm_ops;
+
+	vma->vm_ops->open(vma);
+
+	return 0;
+}
+
+const struct vb2_mem_ops vb2_vmalloc_memops = {
+	.alloc		= vb2_vmalloc_alloc,
+	.put		= vb2_vmalloc_put,
+	.vaddr		= vb2_vmalloc_vaddr,
+	.mmap		= vb2_vmalloc_mmap,
+	.num_users	= vb2_vmalloc_num_users,
+};
+EXPORT_SYMBOL_GPL(vb2_vmalloc_memops);
+
+MODULE_DESCRIPTION("vmalloc memory handling routines for videobuf2");
+MODULE_AUTHOR("Pawel Osciak <pawel@osciak.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/vivi.c linux-libre-2.6.39-gnu/drivers/media/video/vivi.c
--- linux-libre-2.6.38-gnu/drivers/media/video/vivi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/vivi.c	2011-05-19 00:06:34.000000000 -0400
@@ -7,6 +7,9 @@
  *      John Sokol <sokol--a.t--videotechnology.com>
  *      http://v4l.videotechnology.com/
  *
+ *      Conversion to videobuf2 by Pawel Osciak & Marek Szyprowski
+ *      Copyright (c) 2010 Samsung Electronics
+ *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the BSD Licence, GNU General Public License
  * as published by the Free Software Foundation; either version 2 of the
@@ -23,12 +26,12 @@
 #include <linux/mutex.h>
 #include <linux/videodev2.h>
 #include <linux/kthread.h>
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20)
 #include <linux/freezer.h>
-#endif
-#include <media/videobuf-vmalloc.h>
+#include <media/videobuf2-vmalloc.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-fh.h>
 #include <media/v4l2-common.h>
 
 #define VIVI_MODULE_NAME "vivi"
@@ -42,7 +45,7 @@
 #define MAX_HEIGHT 1200
 
 #define VIVI_MAJOR_VERSION 0
-#define VIVI_MINOR_VERSION 7
+#define VIVI_MINOR_VERSION 8
 #define VIVI_RELEASE 0
 #define VIVI_VERSION \
 	KERNEL_VERSION(VIVI_MAJOR_VERSION, VIVI_MINOR_VERSION, VIVI_RELEASE)
@@ -133,16 +136,11 @@
 	return &formats[k];
 }
 
-struct sg_to_addr {
-	int pos;
-	struct scatterlist *sg;
-};
-
 /* buffer for one video frame */
 struct vivi_buffer {
 	/* common v4l buffer stuff -- must be first */
-	struct videobuf_buffer vb;
-
+	struct vb2_buffer	vb;
+	struct list_head	list;
 	struct vivi_fmt        *fmt;
 };
 
@@ -162,13 +160,20 @@
 struct vivi_dev {
 	struct list_head           vivi_devlist;
 	struct v4l2_device 	   v4l2_dev;
+	struct v4l2_ctrl_handler   ctrl_handler;
 
 	/* controls */
-	int 			   brightness;
-	int 			   contrast;
-	int 			   saturation;
-	int 			   hue;
-	int 			   volume;
+	struct v4l2_ctrl	   *brightness;
+	struct v4l2_ctrl	   *contrast;
+	struct v4l2_ctrl	   *saturation;
+	struct v4l2_ctrl	   *hue;
+	struct v4l2_ctrl	   *volume;
+	struct v4l2_ctrl	   *button;
+	struct v4l2_ctrl	   *boolean;
+	struct v4l2_ctrl	   *int32;
+	struct v4l2_ctrl	   *int64;
+	struct v4l2_ctrl	   *menu;
+	struct v4l2_ctrl	   *string;
 
 	spinlock_t                 slock;
 	struct mutex		   mutex;
@@ -181,6 +186,7 @@
 	/* Several counters */
 	unsigned 		   ms;
 	unsigned long              jiffies;
+	unsigned		   button_pressed;
 
 	int			   mv_count;	/* Controls bars movement */
 
@@ -190,9 +196,10 @@
 	/* video capture */
 	struct vivi_fmt            *fmt;
 	unsigned int               width, height;
-	struct videobuf_queue      vb_vidq;
+	struct vb2_queue	   vb_vidq;
+	enum v4l2_field		   field;
+	unsigned int		   field_count;
 
-	unsigned long 		   generating;
 	u8 			   bars[9][3];
 	u8 			   line[MAX_WIDTH * 4];
 };
@@ -443,10 +450,10 @@
 
 static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
 {
-	int hmax = buf->vb.height;
-	int wmax = buf->vb.width;
+	int wmax = dev->width;
+	int hmax = dev->height;
 	struct timeval ts;
-	void *vbuf = videobuf_to_vmalloc(&buf->vb);
+	void *vbuf = vb2_plane_vaddr(&buf->vb, 0);
 	unsigned ms;
 	char str[100];
 	int h, line = 1;
@@ -472,22 +479,38 @@
 			dev->width, dev->height, dev->input);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
 
+	mutex_lock(&dev->ctrl_handler.lock);
 	snprintf(str, sizeof(str), " brightness %3d, contrast %3d, saturation %3d, hue %d ",
-			dev->brightness,
-			dev->contrast,
-			dev->saturation,
-			dev->hue);
+			dev->brightness->cur.val,
+			dev->contrast->cur.val,
+			dev->saturation->cur.val,
+			dev->hue->cur.val);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
-	snprintf(str, sizeof(str), " volume %3d ", dev->volume);
+	snprintf(str, sizeof(str), " volume %3d ", dev->volume->cur.val);
+	gen_text(dev, vbuf, line++ * 16, 16, str);
+	snprintf(str, sizeof(str), " int32 %d, int64 %lld ",
+			dev->int32->cur.val,
+			dev->int64->cur.val64);
 	gen_text(dev, vbuf, line++ * 16, 16, str);
+	snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
+			dev->boolean->cur.val,
+			dev->menu->qmenu[dev->menu->cur.val],
+			dev->string->cur.string);
+	mutex_unlock(&dev->ctrl_handler.lock);
+	gen_text(dev, vbuf, line++ * 16, 16, str);
+	if (dev->button_pressed) {
+		dev->button_pressed--;
+		snprintf(str, sizeof(str), " button pressed!");
+		gen_text(dev, vbuf, line++ * 16, 16, str);
+	}
 
 	dev->mv_count += 2;
 
-	/* Advice that buffer was filled */
-	buf->vb.field_count++;
+	buf->vb.v4l2_buf.field = dev->field;
+	dev->field_count++;
+	buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
 	do_gettimeofday(&ts);
-	buf->vb.ts = ts;
-	buf->vb.state = VIDEOBUF_DONE;
+	buf->vb.v4l2_buf.timestamp = ts;
 }
 
 static void vivi_thread_tick(struct vivi_dev *dev)
@@ -504,23 +527,17 @@
 		goto unlock;
 	}
 
-	buf = list_entry(dma_q->active.next,
-			 struct vivi_buffer, vb.queue);
-
-	/* Nobody is waiting on this buffer, return */
-	if (!waitqueue_active(&buf->vb.done))
-		goto unlock;
-
-	list_del(&buf->vb.queue);
+	buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
+	list_del(&buf->list);
 
-	do_gettimeofday(&buf->vb.ts);
+	do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
 
 	/* Fill buffer */
 	vivi_fillbuff(dev, buf);
 	dprintk(dev, 1, "filled buffer %p\n", buf);
 
-	wake_up(&buf->vb.done);
-	dprintk(dev, 2, "[%p/%d] wakeup\n", buf, buf->vb. i);
+	vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+	dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
 unlock:
 	spin_unlock_irqrestore(&dev->slock, flags);
 }
@@ -571,17 +588,12 @@
 	return 0;
 }
 
-static void vivi_start_generating(struct file *file)
+static int vivi_start_generating(struct vivi_dev *dev)
 {
-	struct vivi_dev *dev = video_drvdata(file);
 	struct vivi_dmaqueue *dma_q = &dev->vidq;
 
 	dprintk(dev, 1, "%s\n", __func__);
 
-	if (test_and_set_bit(0, &dev->generating))
-		return;
-	file->private_data = dev;
-
 	/* Resets frame counters */
 	dev->ms = 0;
 	dev->mv_count = 0;
@@ -593,146 +605,200 @@
 
 	if (IS_ERR(dma_q->kthread)) {
 		v4l2_err(&dev->v4l2_dev, "kernel_thread() failed\n");
-		clear_bit(0, &dev->generating);
-		return;
+		return PTR_ERR(dma_q->kthread);
 	}
 	/* Wakes thread */
 	wake_up_interruptible(&dma_q->wq);
 
 	dprintk(dev, 1, "returning from %s\n", __func__);
+	return 0;
 }
 
-static void vivi_stop_generating(struct file *file)
+static void vivi_stop_generating(struct vivi_dev *dev)
 {
-	struct vivi_dev *dev = video_drvdata(file);
 	struct vivi_dmaqueue *dma_q = &dev->vidq;
 
 	dprintk(dev, 1, "%s\n", __func__);
 
-	if (!file->private_data)
-		return;
-	if (!test_and_clear_bit(0, &dev->generating))
-		return;
-
 	/* shutdown control thread */
 	if (dma_q->kthread) {
 		kthread_stop(dma_q->kthread);
 		dma_q->kthread = NULL;
 	}
-	videobuf_stop(&dev->vb_vidq);
-	videobuf_mmap_free(&dev->vb_vidq);
-}
 
-static int vivi_is_generating(struct vivi_dev *dev)
-{
-	return test_bit(0, &dev->generating);
-}
+	/*
+	 * Typical driver might need to wait here until dma engine stops.
+	 * In this case we can abort imiedetly, so it's just a noop.
+	 */
 
+	/* Release all active buffers */
+	while (!list_empty(&dma_q->active)) {
+		struct vivi_buffer *buf;
+		buf = list_entry(dma_q->active.next, struct vivi_buffer, list);
+		list_del(&buf->list);
+		vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+		dprintk(dev, 2, "[%p/%d] done\n", buf, buf->vb.v4l2_buf.index);
+	}
+}
 /* ------------------------------------------------------------------
 	Videobuf operations
    ------------------------------------------------------------------*/
-static int
-buffer_setup(struct videobuf_queue *vq, unsigned int *count, unsigned int *size)
+static int queue_setup(struct vb2_queue *vq, unsigned int *nbuffers,
+				unsigned int *nplanes, unsigned long sizes[],
+				void *alloc_ctxs[])
 {
-	struct vivi_dev *dev = vq->priv_data;
+	struct vivi_dev *dev = vb2_get_drv_priv(vq);
+	unsigned long size;
 
-	*size = dev->width * dev->height * 2;
+	size = dev->width * dev->height * 2;
 
-	if (0 == *count)
-		*count = 32;
+	if (0 == *nbuffers)
+		*nbuffers = 32;
 
-	while (*size * *count > vid_limit * 1024 * 1024)
-		(*count)--;
+	while (size * *nbuffers > vid_limit * 1024 * 1024)
+		(*nbuffers)--;
 
-	dprintk(dev, 1, "%s, count=%d, size=%d\n", __func__,
-		*count, *size);
+	*nplanes = 1;
+
+	sizes[0] = size;
+
+	/*
+	 * videobuf2-vmalloc allocator is context-less so no need to set
+	 * alloc_ctxs array.
+	 */
+
+	dprintk(dev, 1, "%s, count=%d, size=%ld\n", __func__,
+		*nbuffers, size);
 
 	return 0;
 }
 
-static void free_buffer(struct videobuf_queue *vq, struct vivi_buffer *buf)
+static int buffer_init(struct vb2_buffer *vb)
 {
-	struct vivi_dev *dev = vq->priv_data;
+	struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 
-	dprintk(dev, 1, "%s, state: %i\n", __func__, buf->vb.state);
+	BUG_ON(NULL == dev->fmt);
 
-	videobuf_vmalloc_free(&buf->vb);
-	dprintk(dev, 1, "free_buffer: freed\n");
-	buf->vb.state = VIDEOBUF_NEEDS_INIT;
+	/*
+	 * This callback is called once per buffer, after its allocation.
+	 *
+	 * Vivi does not allow changing format during streaming, but it is
+	 * possible to do so when streaming is paused (i.e. in streamoff state).
+	 * Buffers however are not freed when going into streamoff and so
+	 * buffer size verification has to be done in buffer_prepare, on each
+	 * qbuf.
+	 * It would be best to move verification code here to buf_init and
+	 * s_fmt though.
+	 */
+
+	return 0;
 }
 
-static int
-buffer_prepare(struct videobuf_queue *vq, struct videobuf_buffer *vb,
-						enum v4l2_field field)
+static int buffer_prepare(struct vb2_buffer *vb)
 {
-	struct vivi_dev *dev = vq->priv_data;
+	struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
-	int rc;
+	unsigned long size;
 
-	dprintk(dev, 1, "%s, field=%d\n", __func__, field);
+	dprintk(dev, 1, "%s, field=%d\n", __func__, vb->v4l2_buf.field);
 
 	BUG_ON(NULL == dev->fmt);
 
+	/*
+	 * Theses properties only change when queue is idle, see s_fmt.
+	 * The below checks should not be performed here, on each
+	 * buffer_prepare (i.e. on each qbuf). Most of the code in this function
+	 * should thus be moved to buffer_init and s_fmt.
+	 */
 	if (dev->width  < 48 || dev->width  > MAX_WIDTH ||
 	    dev->height < 32 || dev->height > MAX_HEIGHT)
 		return -EINVAL;
 
-	buf->vb.size = dev->width * dev->height * 2;
-	if (0 != buf->vb.baddr && buf->vb.bsize < buf->vb.size)
+	size = dev->width * dev->height * 2;
+	if (vb2_plane_size(vb, 0) < size) {
+		dprintk(dev, 1, "%s data will not fit into plane (%lu < %lu)\n",
+				__func__, vb2_plane_size(vb, 0), size);
 		return -EINVAL;
+	}
 
-	/* These properties only change when queue is idle, see s_fmt */
-	buf->fmt       = dev->fmt;
-	buf->vb.width  = dev->width;
-	buf->vb.height = dev->height;
-	buf->vb.field  = field;
+	vb2_set_plane_payload(&buf->vb, 0, size);
+
+	buf->fmt = dev->fmt;
 
 	precalculate_bars(dev);
 	precalculate_line(dev);
 
-	if (VIDEOBUF_NEEDS_INIT == buf->vb.state) {
-		rc = videobuf_iolock(vq, &buf->vb, NULL);
-		if (rc < 0)
-			goto fail;
-	}
+	return 0;
+}
 
-	buf->vb.state = VIDEOBUF_PREPARED;
+static int buffer_finish(struct vb2_buffer *vb)
+{
+	struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+	dprintk(dev, 1, "%s\n", __func__);
 	return 0;
+}
+
+static void buffer_cleanup(struct vb2_buffer *vb)
+{
+	struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
+	dprintk(dev, 1, "%s\n", __func__);
 
-fail:
-	free_buffer(vq, buf);
-	return rc;
 }
 
-static void
-buffer_queue(struct videobuf_queue *vq, struct videobuf_buffer *vb)
+static void buffer_queue(struct vb2_buffer *vb)
 {
-	struct vivi_dev *dev = vq->priv_data;
+	struct vivi_dev *dev = vb2_get_drv_priv(vb->vb2_queue);
 	struct vivi_buffer *buf = container_of(vb, struct vivi_buffer, vb);
 	struct vivi_dmaqueue *vidq = &dev->vidq;
+	unsigned long flags = 0;
 
 	dprintk(dev, 1, "%s\n", __func__);
 
-	buf->vb.state = VIDEOBUF_QUEUED;
-	list_add_tail(&buf->vb.queue, &vidq->active);
+	spin_lock_irqsave(&dev->slock, flags);
+	list_add_tail(&buf->list, &vidq->active);
+	spin_unlock_irqrestore(&dev->slock, flags);
 }
 
-static void buffer_release(struct videobuf_queue *vq,
-			   struct videobuf_buffer *vb)
+static int start_streaming(struct vb2_queue *vq)
 {
-	struct vivi_dev *dev = vq->priv_data;
-	struct vivi_buffer *buf  = container_of(vb, struct vivi_buffer, vb);
+	struct vivi_dev *dev = vb2_get_drv_priv(vq);
+	dprintk(dev, 1, "%s\n", __func__);
+	return vivi_start_generating(dev);
+}
 
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
+{
+	struct vivi_dev *dev = vb2_get_drv_priv(vq);
 	dprintk(dev, 1, "%s\n", __func__);
+	vivi_stop_generating(dev);
+	return 0;
+}
 
-	free_buffer(vq, buf);
+static void vivi_lock(struct vb2_queue *vq)
+{
+	struct vivi_dev *dev = vb2_get_drv_priv(vq);
+	mutex_lock(&dev->mutex);
 }
 
-static struct videobuf_queue_ops vivi_video_qops = {
-	.buf_setup      = buffer_setup,
-	.buf_prepare    = buffer_prepare,
-	.buf_queue      = buffer_queue,
-	.buf_release    = buffer_release,
+static void vivi_unlock(struct vb2_queue *vq)
+{
+	struct vivi_dev *dev = vb2_get_drv_priv(vq);
+	mutex_unlock(&dev->mutex);
+}
+
+
+static struct vb2_ops vivi_video_qops = {
+	.queue_setup		= queue_setup,
+	.buf_init		= buffer_init,
+	.buf_prepare		= buffer_prepare,
+	.buf_finish		= buffer_finish,
+	.buf_cleanup		= buffer_cleanup,
+	.buf_queue		= buffer_queue,
+	.start_streaming	= start_streaming,
+	.stop_streaming		= stop_streaming,
+	.wait_prepare		= vivi_unlock,
+	.wait_finish		= vivi_lock,
 };
 
 /* ------------------------------------------------------------------
@@ -774,7 +840,7 @@
 
 	f->fmt.pix.width        = dev->width;
 	f->fmt.pix.height       = dev->height;
-	f->fmt.pix.field        = dev->vb_vidq.field;
+	f->fmt.pix.field        = dev->field;
 	f->fmt.pix.pixelformat  = dev->fmt->fourcc;
 	f->fmt.pix.bytesperline =
 		(f->fmt.pix.width * dev->fmt->depth) >> 3;
@@ -820,82 +886,60 @@
 					struct v4l2_format *f)
 {
 	struct vivi_dev *dev = video_drvdata(file);
+	struct vb2_queue *q = &dev->vb_vidq;
 
 	int ret = vidioc_try_fmt_vid_cap(file, priv, f);
 	if (ret < 0)
 		return ret;
 
-	if (vivi_is_generating(dev)) {
+	if (vb2_is_streaming(q)) {
 		dprintk(dev, 1, "%s device busy\n", __func__);
-		ret = -EBUSY;
-		goto out;
+		return -EBUSY;
 	}
 
 	dev->fmt = get_format(f);
 	dev->width = f->fmt.pix.width;
 	dev->height = f->fmt.pix.height;
-	dev->vb_vidq.field = f->fmt.pix.field;
-	ret = 0;
-out:
-	return ret;
+	dev->field = f->fmt.pix.field;
+
+	return 0;
 }
 
 static int vidioc_reqbufs(struct file *file, void *priv,
 			  struct v4l2_requestbuffers *p)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-
-	return videobuf_reqbufs(&dev->vb_vidq, p);
+	return vb2_reqbufs(&dev->vb_vidq, p);
 }
 
 static int vidioc_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-
-	return videobuf_querybuf(&dev->vb_vidq, p);
+	return vb2_querybuf(&dev->vb_vidq, p);
 }
 
 static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-
-	return videobuf_qbuf(&dev->vb_vidq, p);
+	return vb2_qbuf(&dev->vb_vidq, p);
 }
 
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-
-	return videobuf_dqbuf(&dev->vb_vidq, p,
-				file->f_flags & O_NONBLOCK);
+	return vb2_dqbuf(&dev->vb_vidq, p, file->f_flags & O_NONBLOCK);
 }
 
 static int vidioc_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-	int ret;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	ret = videobuf_streamon(&dev->vb_vidq);
-	if (ret)
-		return ret;
-
-	vivi_start_generating(file);
-	return 0;
+	return vb2_streamon(&dev->vb_vidq, i);
 }
 
 static int vidioc_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-	int ret;
-
-	if (i != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-		return -EINVAL;
-	ret = videobuf_streamoff(&dev->vb_vidq);
-	if (!ret)
-		vivi_stop_generating(file);
-	return ret;
+	return vb2_streamoff(&dev->vb_vidq, i);
 }
 
 static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *i)
@@ -938,80 +982,14 @@
 }
 
 /* --- controls ---------------------------------------------- */
-static int vidioc_queryctrl(struct file *file, void *priv,
-			    struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 200);
-	case V4L2_CID_BRIGHTNESS:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
-	case V4L2_CID_CONTRAST:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 16);
-	case V4L2_CID_SATURATION:
-		return v4l2_ctrl_query_fill(qc, 0, 255, 1, 127);
-	case V4L2_CID_HUE:
-		return v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-	}
-	return -EINVAL;
-}
 
-static int vidioc_g_ctrl(struct file *file, void *priv,
-			 struct v4l2_control *ctrl)
-{
-	struct vivi_dev *dev = video_drvdata(file);
-
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		ctrl->value = dev->volume;
-		return 0;
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = dev->brightness;
-		return 0;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = dev->contrast;
-		return 0;
-	case V4L2_CID_SATURATION:
-		ctrl->value = dev->saturation;
-		return 0;
-	case V4L2_CID_HUE:
-		ctrl->value = dev->hue;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static int vidioc_s_ctrl(struct file *file, void *priv,
-				struct v4l2_control *ctrl)
+static int vivi_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct vivi_dev *dev = video_drvdata(file);
-	struct v4l2_queryctrl qc;
-	int err;
+	struct vivi_dev *dev = container_of(ctrl->handler, struct vivi_dev, ctrl_handler);
 
-	qc.id = ctrl->id;
-	err = vidioc_queryctrl(file, priv, &qc);
-	if (err < 0)
-		return err;
-	if (ctrl->value < qc.minimum || ctrl->value > qc.maximum)
-		return -ERANGE;
-	switch (ctrl->id) {
-	case V4L2_CID_AUDIO_VOLUME:
-		dev->volume = ctrl->value;
-		return 0;
-	case V4L2_CID_BRIGHTNESS:
-		dev->brightness = ctrl->value;
-		return 0;
-	case V4L2_CID_CONTRAST:
-		dev->contrast = ctrl->value;
-		return 0;
-	case V4L2_CID_SATURATION:
-		dev->saturation = ctrl->value;
-		return 0;
-	case V4L2_CID_HUE:
-		dev->hue = ctrl->value;
-		return 0;
-	}
-	return -EINVAL;
+	if (ctrl == dev->button)
+		dev->button_pressed = 30;
+	return 0;
 }
 
 /* ------------------------------------------------------------------
@@ -1023,21 +1001,19 @@
 {
 	struct vivi_dev *dev = video_drvdata(file);
 
-	vivi_start_generating(file);
-	return videobuf_read_stream(&dev->vb_vidq, data, count, ppos, 0,
-					file->f_flags & O_NONBLOCK);
+	dprintk(dev, 1, "read called\n");
+	return vb2_read(&dev->vb_vidq, data, count, ppos,
+		       file->f_flags & O_NONBLOCK);
 }
 
 static unsigned int
 vivi_poll(struct file *file, struct poll_table_struct *wait)
 {
 	struct vivi_dev *dev = video_drvdata(file);
-	struct videobuf_queue *q = &dev->vb_vidq;
+	struct vb2_queue *q = &dev->vb_vidq;
 
 	dprintk(dev, 1, "%s\n", __func__);
-
-	vivi_start_generating(file);
-	return videobuf_poll_stream(file, q, wait);
+	return vb2_poll(q, file, wait);
 }
 
 static int vivi_close(struct file *file)
@@ -1045,11 +1021,12 @@
 	struct video_device  *vdev = video_devdata(file);
 	struct vivi_dev *dev = video_drvdata(file);
 
-	vivi_stop_generating(file);
+	dprintk(dev, 1, "close called (dev=%s), file %p\n",
+		video_device_node_name(vdev), file);
 
-	dprintk(dev, 1, "close called (dev=%s)\n",
-		video_device_node_name(vdev));
-	return 0;
+	if (v4l2_fh_is_singular_file(file))
+		vb2_queue_release(&dev->vb_vidq);
+	return v4l2_fh_release(file);
 }
 
 static int vivi_mmap(struct file *file, struct vm_area_struct *vma)
@@ -1059,8 +1036,7 @@
 
 	dprintk(dev, 1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
 
-	ret = videobuf_mmap_mapper(&dev->vb_vidq, vma);
-
+	ret = vb2_mmap(&dev->vb_vidq, vma);
 	dprintk(dev, 1, "vma start=0x%08lx, size=%ld, ret=%d\n",
 		(unsigned long)vma->vm_start,
 		(unsigned long)vma->vm_end - (unsigned long)vma->vm_start,
@@ -1068,8 +1044,82 @@
 	return ret;
 }
 
+static const struct v4l2_ctrl_ops vivi_ctrl_ops = {
+	.s_ctrl = vivi_s_ctrl,
+};
+
+#define VIVI_CID_CUSTOM_BASE	(V4L2_CID_USER_BASE | 0xf000)
+
+static const struct v4l2_ctrl_config vivi_ctrl_button = {
+	.ops = &vivi_ctrl_ops,
+	.id = VIVI_CID_CUSTOM_BASE + 0,
+	.name = "Button",
+	.type = V4L2_CTRL_TYPE_BUTTON,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_boolean = {
+	.ops = &vivi_ctrl_ops,
+	.id = VIVI_CID_CUSTOM_BASE + 1,
+	.name = "Boolean",
+	.type = V4L2_CTRL_TYPE_BOOLEAN,
+	.min = 0,
+	.max = 1,
+	.step = 1,
+	.def = 1,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
+	.ops = &vivi_ctrl_ops,
+	.id = VIVI_CID_CUSTOM_BASE + 2,
+	.name = "Integer 32 Bits",
+	.type = V4L2_CTRL_TYPE_INTEGER,
+	.min = 0x80000000,
+	.max = 0x7fffffff,
+	.step = 1,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
+	.ops = &vivi_ctrl_ops,
+	.id = VIVI_CID_CUSTOM_BASE + 3,
+	.name = "Integer 64 Bits",
+	.type = V4L2_CTRL_TYPE_INTEGER64,
+};
+
+static const char * const vivi_ctrl_menu_strings[] = {
+	"Menu Item 0 (Skipped)",
+	"Menu Item 1",
+	"Menu Item 2 (Skipped)",
+	"Menu Item 3",
+	"Menu Item 4",
+	"Menu Item 5 (Skipped)",
+	NULL,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_menu = {
+	.ops = &vivi_ctrl_ops,
+	.id = VIVI_CID_CUSTOM_BASE + 4,
+	.name = "Menu",
+	.type = V4L2_CTRL_TYPE_MENU,
+	.min = 1,
+	.max = 4,
+	.def = 3,
+	.menu_skip_mask = 0x04,
+	.qmenu = vivi_ctrl_menu_strings,
+};
+
+static const struct v4l2_ctrl_config vivi_ctrl_string = {
+	.ops = &vivi_ctrl_ops,
+	.id = VIVI_CID_CUSTOM_BASE + 5,
+	.name = "String",
+	.type = V4L2_CTRL_TYPE_STRING,
+	.min = 2,
+	.max = 4,
+	.step = 1,
+};
+
 static const struct v4l2_file_operations vivi_fops = {
 	.owner		= THIS_MODULE,
+	.open		= v4l2_fh_open,
 	.release        = vivi_close,
 	.read           = vivi_read,
 	.poll		= vivi_poll,
@@ -1093,9 +1143,6 @@
 	.vidioc_s_input       = vidioc_s_input,
 	.vidioc_streamon      = vidioc_streamon,
 	.vidioc_streamoff     = vidioc_streamoff,
-	.vidioc_queryctrl     = vidioc_queryctrl,
-	.vidioc_g_ctrl        = vidioc_g_ctrl,
-	.vidioc_s_ctrl        = vidioc_s_ctrl,
 };
 
 static struct video_device vivi_template = {
@@ -1126,6 +1173,7 @@
 			video_device_node_name(dev->vfd));
 		video_unregister_device(dev->vfd);
 		v4l2_device_unregister(&dev->v4l2_dev);
+		v4l2_ctrl_handler_free(&dev->ctrl_handler);
 		kfree(dev);
 	}
 
@@ -1136,6 +1184,8 @@
 {
 	struct vivi_dev *dev;
 	struct video_device *vfd;
+	struct v4l2_ctrl_handler *hdl;
+	struct vb2_queue *q;
 	int ret;
 
 	dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -1151,20 +1201,46 @@
 	dev->fmt = &formats[0];
 	dev->width = 640;
 	dev->height = 480;
-	dev->volume = 200;
-	dev->brightness = 127;
-	dev->contrast = 16;
-	dev->saturation = 127;
-	dev->hue = 0;
+	hdl = &dev->ctrl_handler;
+	v4l2_ctrl_handler_init(hdl, 11);
+	dev->volume = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 255, 1, 200);
+	dev->brightness = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+			V4L2_CID_BRIGHTNESS, 0, 255, 1, 127);
+	dev->contrast = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+			V4L2_CID_CONTRAST, 0, 255, 1, 16);
+	dev->saturation = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+			V4L2_CID_SATURATION, 0, 255, 1, 127);
+	dev->hue = v4l2_ctrl_new_std(hdl, &vivi_ctrl_ops,
+			V4L2_CID_HUE, -128, 127, 1, 0);
+	dev->button = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_button, NULL);
+	dev->int32 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int32, NULL);
+	dev->int64 = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_int64, NULL);
+	dev->boolean = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_boolean, NULL);
+	dev->menu = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_menu, NULL);
+	dev->string = v4l2_ctrl_new_custom(hdl, &vivi_ctrl_string, NULL);
+	if (hdl->error) {
+		ret = hdl->error;
+		goto unreg_dev;
+	}
+	dev->v4l2_dev.ctrl_handler = hdl;
 
 	/* initialize locks */
 	spin_lock_init(&dev->slock);
-	mutex_init(&dev->mutex);
 
-	videobuf_queue_vmalloc_init(&dev->vb_vidq, &vivi_video_qops,
-			NULL, &dev->slock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
-			V4L2_FIELD_INTERLACED,
-			sizeof(struct vivi_buffer), dev, &dev->mutex);
+	/* initialize queue */
+	q = &dev->vb_vidq;
+	memset(q, 0, sizeof(dev->vb_vidq));
+	q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+	q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+	q->drv_priv = dev;
+	q->buf_struct_size = sizeof(struct vivi_buffer);
+	q->ops = &vivi_video_qops;
+	q->mem_ops = &vb2_vmalloc_memops;
+
+	vb2_queue_init(q);
+
+	mutex_init(&dev->mutex);
 
 	/* init video dma queues */
 	INIT_LIST_HEAD(&dev->vidq.active);
@@ -1178,6 +1254,12 @@
 	*vfd = vivi_template;
 	vfd->debug = debug;
 	vfd->v4l2_dev = &dev->v4l2_dev;
+	set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
+
+	/*
+	 * Provide a mutex to v4l2 core. It will be used to protect
+	 * all fops and v4l2 ioctls.
+	 */
 	vfd->lock = &dev->mutex;
 
 	ret = video_register_device(vfd, VFL_TYPE_GRABBER, video_nr);
@@ -1200,6 +1282,7 @@
 rel_vdev:
 	video_device_release(vfd);
 unreg_dev:
+	v4l2_ctrl_handler_free(hdl);
 	v4l2_device_unregister(&dev->v4l2_dev);
 free_dev:
 	kfree(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/vpx3220.c linux-libre-2.6.39-gnu/drivers/media/video/vpx3220.c
--- linux-libre-2.6.38-gnu/drivers/media/video/vpx3220.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/vpx3220.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
+#include <media/v4l2-ctrls.h>
 
 MODULE_DESCRIPTION("vpx3220a/vpx3216b/vpx3214c video decoder driver");
 MODULE_AUTHOR("Laurent Pinchart");
@@ -44,16 +45,13 @@
 
 struct vpx3220 {
 	struct v4l2_subdev sd;
+	struct v4l2_ctrl_handler hdl;
 	unsigned char reg[255];
 
 	v4l2_std_id norm;
 	int ident;
 	int input;
 	int enable;
-	int bright;
-	int contrast;
-	int hue;
-	int sat;
 };
 
 static inline struct vpx3220 *to_vpx3220(struct v4l2_subdev *sd)
@@ -61,6 +59,11 @@
 	return container_of(sd, struct vpx3220, sd);
 }
 
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+	return &container_of(ctrl->handler, struct vpx3220, hdl)->sd;
+}
+
 static char *inputs[] = { "internal", "composite", "svideo" };
 
 /* ----------------------------------------------------------------------- */
@@ -351,7 +354,7 @@
 
 	/* Here we back up the input selection because it gets
 	   overwritten when we fill the registers with the
-	   choosen video norm */
+	   chosen video norm */
 	temp_input = vpx3220_fp_read(sd, 0xf2);
 
 	v4l2_dbg(1, debug, sd, "s_std %llx\n", (unsigned long long)std);
@@ -417,88 +420,26 @@
 	return 0;
 }
 
-static int vpx3220_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
-{
-	switch (qc->id) {
-	case V4L2_CID_BRIGHTNESS:
-		v4l2_ctrl_query_fill(qc, -128, 127, 1, 0);
-		break;
-
-	case V4L2_CID_CONTRAST:
-		v4l2_ctrl_query_fill(qc, 0, 63, 1, 32);
-		break;
-
-	case V4L2_CID_SATURATION:
-		v4l2_ctrl_query_fill(qc, 0, 4095, 1, 2048);
-		break;
-
-	case V4L2_CID_HUE:
-		v4l2_ctrl_query_fill(qc, -512, 511, 1, 0);
-		break;
-
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int vpx3220_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
-{
-	struct vpx3220 *decoder = to_vpx3220(sd);
-
-	switch (ctrl->id) {
-	case V4L2_CID_BRIGHTNESS:
-		ctrl->value = decoder->bright;
-		break;
-	case V4L2_CID_CONTRAST:
-		ctrl->value = decoder->contrast;
-		break;
-	case V4L2_CID_SATURATION:
-		ctrl->value = decoder->sat;
-		break;
-	case V4L2_CID_HUE:
-		ctrl->value = decoder->hue;
-		break;
-	default:
-		return -EINVAL;
-	}
-	return 0;
-}
-
-static int vpx3220_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
+static int vpx3220_s_ctrl(struct v4l2_ctrl *ctrl)
 {
-	struct vpx3220 *decoder = to_vpx3220(sd);
+	struct v4l2_subdev *sd = to_sd(ctrl);
 
 	switch (ctrl->id) {
 	case V4L2_CID_BRIGHTNESS:
-		if (decoder->bright != ctrl->value) {
-			decoder->bright = ctrl->value;
-			vpx3220_write(sd, 0xe6, decoder->bright);
-		}
-		break;
+		vpx3220_write(sd, 0xe6, ctrl->val);
+		return 0;
 	case V4L2_CID_CONTRAST:
-		if (decoder->contrast != ctrl->value) {
-			/* Bit 7 and 8 is for noise shaping */
-			decoder->contrast = ctrl->value;
-			vpx3220_write(sd, 0xe7, decoder->contrast + 192);
-		}
-		break;
+		/* Bit 7 and 8 is for noise shaping */
+		vpx3220_write(sd, 0xe7, ctrl->val + 192);
+		return 0;
 	case V4L2_CID_SATURATION:
-		if (decoder->sat != ctrl->value) {
-			decoder->sat = ctrl->value;
-			vpx3220_fp_write(sd, 0xa0, decoder->sat);
-		}
-		break;
+		vpx3220_fp_write(sd, 0xa0, ctrl->val);
+		return 0;
 	case V4L2_CID_HUE:
-		if (decoder->hue != ctrl->value) {
-			decoder->hue = ctrl->value;
-			vpx3220_fp_write(sd, 0x1c, decoder->hue);
-		}
-		break;
-	default:
-		return -EINVAL;
+		vpx3220_fp_write(sd, 0x1c, ctrl->val);
+		return 0;
 	}
-	return 0;
+	return -EINVAL;
 }
 
 static int vpx3220_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
@@ -511,12 +452,20 @@
 
 /* ----------------------------------------------------------------------- */
 
+static const struct v4l2_ctrl_ops vpx3220_ctrl_ops = {
+	.s_ctrl = vpx3220_s_ctrl,
+};
+
 static const struct v4l2_subdev_core_ops vpx3220_core_ops = {
 	.g_chip_ident = vpx3220_g_chip_ident,
 	.init = vpx3220_init,
-	.g_ctrl = vpx3220_g_ctrl,
-	.s_ctrl = vpx3220_s_ctrl,
-	.queryctrl = vpx3220_queryctrl,
+	.g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+	.try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+	.s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+	.g_ctrl = v4l2_subdev_g_ctrl,
+	.s_ctrl = v4l2_subdev_s_ctrl,
+	.queryctrl = v4l2_subdev_queryctrl,
+	.querymenu = v4l2_subdev_querymenu,
 	.s_std = vpx3220_s_std,
 };
 
@@ -558,10 +507,24 @@
 	decoder->norm = V4L2_STD_PAL;
 	decoder->input = 0;
 	decoder->enable = 1;
-	decoder->bright = 32768;
-	decoder->contrast = 32768;
-	decoder->hue = 32768;
-	decoder->sat = 32768;
+	v4l2_ctrl_handler_init(&decoder->hdl, 4);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_CONTRAST, 0, 63, 1, 32);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_SATURATION, 0, 4095, 1, 2048);
+	v4l2_ctrl_new_std(&decoder->hdl, &vpx3220_ctrl_ops,
+		V4L2_CID_HUE, -512, 511, 1, 0);
+	sd->ctrl_handler = &decoder->hdl;
+	if (decoder->hdl.error) {
+		int err = decoder->hdl.error;
+
+		v4l2_ctrl_handler_free(&decoder->hdl);
+		kfree(decoder);
+		return err;
+	}
+	v4l2_ctrl_handler_setup(&decoder->hdl);
 
 	ver = i2c_smbus_read_byte_data(client, 0x00);
 	pn = (i2c_smbus_read_byte_data(client, 0x02) << 8) +
@@ -599,9 +562,11 @@
 static int vpx3220_remove(struct i2c_client *client)
 {
 	struct v4l2_subdev *sd = i2c_get_clientdata(client);
+	struct vpx3220 *decoder = to_vpx3220(sd);
 
 	v4l2_device_unregister_subdev(sd);
-	kfree(to_vpx3220(sd));
+	v4l2_ctrl_handler_free(&decoder->hdl);
+	kfree(decoder);
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/wm8775.c linux-libre-2.6.39-gnu/drivers/media/video/wm8775.c
--- linux-libre-2.6.38-gnu/drivers/media/video/wm8775.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/wm8775.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,7 @@
 #include <media/v4l2-device.h>
 #include <media/v4l2-chip-ident.h>
 #include <media/v4l2-ctrls.h>
+#include <media/wm8775.h>
 
 MODULE_DESCRIPTION("wm8775 driver");
 MODULE_AUTHOR("Ulf Eklund, Hans Verkuil");
@@ -50,10 +51,16 @@
 	TOT_REGS
 };
 
+#define ALC_HOLD 0x85 /* R17: use zero cross detection, ALC hold time 42.6 ms */
+#define ALC_EN 0x100  /* R17: ALC enable */
+
 struct wm8775_state {
 	struct v4l2_subdev sd;
 	struct v4l2_ctrl_handler hdl;
 	struct v4l2_ctrl *mute;
+	struct v4l2_ctrl *vol;
+	struct v4l2_ctrl *bal;
+	struct v4l2_ctrl *loud;
 	u8 input;		/* Last selected input (0-0xf) */
 };
 
@@ -85,6 +92,30 @@
 	return -1;
 }
 
+static void wm8775_set_audio(struct v4l2_subdev *sd, int quietly)
+{
+	struct wm8775_state *state = to_state(sd);
+	u8 vol_l, vol_r;
+	int muted = 0 != state->mute->val;
+	u16 volume = (u16)state->vol->val;
+	u16 balance = (u16)state->bal->val;
+
+	/* normalize ( 65535 to 0 -> 255 to 0 (+24dB to -103dB) ) */
+	vol_l = (min(65536 - balance, 32768) * volume) >> 23;
+	vol_r = (min(balance, (u16)32768) * volume) >> 23;
+
+	/* Mute */
+	if (muted || quietly)
+		wm8775_write(sd, R21, 0x0c0 | state->input);
+
+	wm8775_write(sd, R14, vol_l | 0x100); /* 0x100= Left channel ADC zero cross enable */
+	wm8775_write(sd, R15, vol_r | 0x100); /* 0x100= Right channel ADC zero cross enable */
+
+	/* Un-mute */
+	if (!muted)
+		wm8775_write(sd, R21, state->input);
+}
+
 static int wm8775_s_routing(struct v4l2_subdev *sd,
 			    u32 input, u32 output, u32 config)
 {
@@ -102,25 +133,26 @@
 	state->input = input;
 	if (!v4l2_ctrl_g_ctrl(state->mute))
 		return 0;
-	wm8775_write(sd, R21, 0x0c0);
-	wm8775_write(sd, R14, 0x1d4);
-	wm8775_write(sd, R15, 0x1d4);
-	wm8775_write(sd, R21, 0x100 + state->input);
+	if (!v4l2_ctrl_g_ctrl(state->vol))
+		return 0;
+	if (!v4l2_ctrl_g_ctrl(state->bal))
+		return 0;
+	wm8775_set_audio(sd, 1);
 	return 0;
 }
 
 static int wm8775_s_ctrl(struct v4l2_ctrl *ctrl)
 {
 	struct v4l2_subdev *sd = to_sd(ctrl);
-	struct wm8775_state *state = to_state(sd);
 
 	switch (ctrl->id) {
 	case V4L2_CID_AUDIO_MUTE:
-		wm8775_write(sd, R21, 0x0c0);
-		wm8775_write(sd, R14, 0x1d4);
-		wm8775_write(sd, R15, 0x1d4);
-		if (!ctrl->val)
-			wm8775_write(sd, R21, 0x100 + state->input);
+	case V4L2_CID_AUDIO_VOLUME:
+	case V4L2_CID_AUDIO_BALANCE:
+		wm8775_set_audio(sd, 0);
+		return 0;
+	case V4L2_CID_AUDIO_LOUDNESS:
+		wm8775_write(sd, R17, (ctrl->val ? ALC_EN : 0) | ALC_HOLD);
 		return 0;
 	}
 	return -EINVAL;
@@ -144,16 +176,7 @@
 
 static int wm8775_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *freq)
 {
-	struct wm8775_state *state = to_state(sd);
-
-	/* If I remove this, then it can happen that I have no
-	   sound the first time I tune from static to a valid channel.
-	   It's difficult to reproduce and is almost certainly related
-	   to the zero cross detect circuit. */
-	wm8775_write(sd, R21, 0x0c0);
-	wm8775_write(sd, R14, 0x1d4);
-	wm8775_write(sd, R15, 0x1d4);
-	wm8775_write(sd, R21, 0x100 + state->input);
+	wm8775_set_audio(sd, 0);
 	return 0;
 }
 
@@ -203,6 +226,13 @@
 {
 	struct wm8775_state *state;
 	struct v4l2_subdev *sd;
+	int err;
+	bool is_nova_s = false;
+
+	if (client->dev.platform_data) {
+		struct wm8775_platform_data *data = client->dev.platform_data;
+		is_nova_s = data->is_nova_s;
+	}
 
 	/* Check if the adapter supports the needed features */
 	if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
@@ -218,13 +248,18 @@
 	v4l2_i2c_subdev_init(sd, client, &wm8775_ops);
 	state->input = 2;
 
-	v4l2_ctrl_handler_init(&state->hdl, 1);
+	v4l2_ctrl_handler_init(&state->hdl, 4);
 	state->mute = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
 			V4L2_CID_AUDIO_MUTE, 0, 1, 1, 0);
+	state->vol = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_VOLUME, 0, 65535, (65535+99)/100, 0xCF00); /* 0dB*/
+	state->bal = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_BALANCE, 0, 65535, (65535+99)/100, 32768);
+	state->loud = v4l2_ctrl_new_std(&state->hdl, &wm8775_ctrl_ops,
+			V4L2_CID_AUDIO_LOUDNESS, 0, 1, 1, 1);
 	sd->ctrl_handler = &state->hdl;
-	if (state->hdl.error) {
-		int err = state->hdl.error;
-
+	err = state->hdl.error;
+	if (err) {
 		v4l2_ctrl_handler_free(&state->hdl);
 		kfree(state);
 		return err;
@@ -236,29 +271,44 @@
 	wm8775_write(sd, R23, 0x000);
 	/* Disable zero cross detect timeout */
 	wm8775_write(sd, R7, 0x000);
-	/* Left justified, 24-bit mode */
+	/* HPF enable, left justified, 24-bit (Philips) mode */
 	wm8775_write(sd, R11, 0x021);
 	/* Master mode, clock ratio 256fs */
 	wm8775_write(sd, R12, 0x102);
 	/* Powered up */
 	wm8775_write(sd, R13, 0x000);
-	/* ADC gain +2.5dB, enable zero cross */
-	wm8775_write(sd, R14, 0x1d4);
-	/* ADC gain +2.5dB, enable zero cross */
-	wm8775_write(sd, R15, 0x1d4);
-	/* ALC Stereo, ALC target level -1dB FS max gain +8dB */
-	wm8775_write(sd, R16, 0x1bf);
-	/* Enable gain control, use zero cross detection,
-	   ALC hold time 42.6 ms */
-	wm8775_write(sd, R17, 0x185);
+
+	if (!is_nova_s) {
+		/* ADC gain +2.5dB, enable zero cross */
+		wm8775_write(sd, R14, 0x1d4);
+		/* ADC gain +2.5dB, enable zero cross */
+		wm8775_write(sd, R15, 0x1d4);
+		/* ALC Stereo, ALC target level -1dB FS max gain +8dB */
+		wm8775_write(sd, R16, 0x1bf);
+		/* Enable gain control, use zero cross detection,
+		   ALC hold time 42.6 ms */
+		wm8775_write(sd, R17, 0x185);
+	} else {
+		/* ALC stereo, ALC target level -5dB FS, ALC max gain +8dB */
+		wm8775_write(sd, R16, 0x1bb);
+		/* Set ALC mode and hold time */
+		wm8775_write(sd, R17, (state->loud->val ? ALC_EN : 0) | ALC_HOLD);
+	}
 	/* ALC gain ramp up delay 34 s, ALC gain ramp down delay 33 ms */
 	wm8775_write(sd, R18, 0x0a2);
 	/* Enable noise gate, threshold -72dBfs */
 	wm8775_write(sd, R19, 0x005);
-	/* Transient window 4ms, lower PGA gain limit -1dB */
-	wm8775_write(sd, R20, 0x07a);
-	/* LRBOTH = 1, use input 2. */
-	wm8775_write(sd, R21, 0x102);
+	if (!is_nova_s) {
+		/* Transient window 4ms, lower PGA gain limit -1dB */
+		wm8775_write(sd, R20, 0x07a);
+		/* LRBOTH = 1, use input 2. */
+		wm8775_write(sd, R21, 0x102);
+	} else {
+		/* Transient window 4ms, ALC min gain -5dB  */
+		wm8775_write(sd, R20, 0x0fb);
+
+		wm8775_set_audio(sd, 1);      /* set volume/mute/mux */
+	}
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/zoran/videocodec.h linux-libre-2.6.39-gnu/drivers/media/video/zoran/videocodec.h
--- linux-libre-2.6.38-gnu/drivers/media/video/zoran/videocodec.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/zoran/videocodec.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
    therfor they may not be initialized.
 
    The other functions are just for convenience, as they are for sure used by
-   most/all of the codecs. The last ones may be ommited, too.
+   most/all of the codecs. The last ones may be omitted, too.
 
    See the structure declaration below for more information and which data has
    to be set up for the master and the slave.
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/zoran/zoran_driver.c linux-libre-2.6.39-gnu/drivers/media/video/zoran/zoran_driver.c
--- linux-libre-2.6.38-gnu/drivers/media/video/zoran/zoran_driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/zoran/zoran_driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -1254,7 +1254,7 @@
 {
 	struct zoran *zr = fh->zr;
 
-	/* If there is nothing to do, return immediatly */
+	/* If there is nothing to do, return immediately */
 	if ((on && fh->overlay_active != ZORAN_FREE) ||
 	    (!on && fh->overlay_active == ZORAN_FREE))
 		return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/media/video/zoran/zoran.h linux-libre-2.6.39-gnu/drivers/media/video/zoran/zoran.h
--- linux-libre-2.6.38-gnu/drivers/media/video/zoran/zoran.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/media/video/zoran/zoran.h	2011-05-19 00:06:34.000000000 -0400
@@ -259,7 +259,7 @@
 	struct vfe_polarity vfe_pol;
 	u8 gpio_pol[ZR_GPIO_MAX];
 
-	/* is the /GWS line conected? */
+	/* is the /GWS line connected? */
 	u8 gws_not_connected;
 
 	/* avs6eyes mux setting */
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/core/Makefile linux-libre-2.6.39-gnu/drivers/memstick/core/Makefile
--- linux-libre-2.6.38-gnu/drivers/memstick/core/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/memstick/core/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,10 +2,6 @@
 # Makefile for the kernel MemoryStick core.
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
-
 obj-$(CONFIG_MEMSTICK)		+= memstick.o
 
 obj-$(CONFIG_MSPRO_BLOCK)	+= mspro_block.o
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/core/mspro_block.c linux-libre-2.6.39-gnu/drivers/memstick/core/mspro_block.c
--- linux-libre-2.6.38-gnu/drivers/memstick/core/mspro_block.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/memstick/core/mspro_block.c	2011-05-19 00:06:34.000000000 -0400
@@ -973,7 +973,7 @@
 }
 
 /* Memory allocated for attributes by this function should be freed by
- * mspro_block_data_clear, no matter if the initialization process succeded
+ * mspro_block_data_clear, no matter if the initialization process succeeded
  * or failed.
  */
 static int mspro_block_read_attributes(struct memstick_dev *card)
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/host/Kconfig linux-libre-2.6.39-gnu/drivers/memstick/host/Kconfig
--- linux-libre-2.6.38-gnu/drivers/memstick/host/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/memstick/host/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -30,3 +30,15 @@
 
           To compile this driver as a module, choose M here: the
 	  module will be called jmb38x_ms.
+
+config MEMSTICK_R592
+	tristate "Ricoh R5C592 MemoryStick interface support (EXPERIMENTAL)"
+	depends on EXPERIMENTAL && PCI
+
+	help
+	  Say Y here if you want to be able to access MemoryStick cards with
+	  the Ricoh R5C592 MemoryStick card reader (which is part of 5 in one
+		multifunction reader)
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called r592.
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/host/Makefile linux-libre-2.6.39-gnu/drivers/memstick/host/Makefile
--- linux-libre-2.6.38-gnu/drivers/memstick/host/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/memstick/host/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,9 +2,6 @@
 # Makefile for MemoryStick host controller drivers
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS			+= -DDEBUG
-endif
-
 obj-$(CONFIG_MEMSTICK_TIFM_MS)		+= tifm_ms.o
 obj-$(CONFIG_MEMSTICK_JMICRON_38X)	+= jmb38x_ms.o
+obj-$(CONFIG_MEMSTICK_R592)		+= r592.o
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/host/r592.c linux-libre-2.6.39-gnu/drivers/memstick/host/r592.c
--- linux-libre-2.6.38-gnu/drivers/memstick/host/r592.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/memstick/host/r592.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,908 @@
+/*
+ * Copyright (C) 2010 - Maxim Levitsky
+ * driver for Ricoh memstick readers
+ *
+ * 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/freezer.h>
+#include <linux/jiffies.h>
+#include <linux/interrupt.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/kthread.h>
+#include <linux/sched.h>
+#include <linux/highmem.h>
+#include <asm/byteorder.h>
+#include <linux/swab.h>
+#include "r592.h"
+
+static int r592_enable_dma = 1;
+static int debug;
+
+static const char *tpc_names[] = {
+	"MS_TPC_READ_MG_STATUS",
+	"MS_TPC_READ_LONG_DATA",
+	"MS_TPC_READ_SHORT_DATA",
+	"MS_TPC_READ_REG",
+	"MS_TPC_READ_QUAD_DATA",
+	"INVALID",
+	"MS_TPC_GET_INT",
+	"MS_TPC_SET_RW_REG_ADRS",
+	"MS_TPC_EX_SET_CMD",
+	"MS_TPC_WRITE_QUAD_DATA",
+	"MS_TPC_WRITE_REG",
+	"MS_TPC_WRITE_SHORT_DATA",
+	"MS_TPC_WRITE_LONG_DATA",
+	"MS_TPC_SET_CMD",
+};
+
+/**
+ * memstick_debug_get_tpc_name - debug helper that returns string for
+ * a TPC number
+ */
+const char *memstick_debug_get_tpc_name(int tpc)
+{
+	return tpc_names[tpc-1];
+}
+EXPORT_SYMBOL(memstick_debug_get_tpc_name);
+
+
+/* Read a register*/
+static inline u32 r592_read_reg(struct r592_device *dev, int address)
+{
+	u32 value = readl(dev->mmio + address);
+	dbg_reg("reg #%02d == 0x%08x", address, value);
+	return value;
+}
+
+/* Write a register */
+static inline void r592_write_reg(struct r592_device *dev,
+							int address, u32 value)
+{
+	dbg_reg("reg #%02d <- 0x%08x", address, value);
+	writel(value, dev->mmio + address);
+}
+
+/* Reads a big endian DWORD register */
+static inline u32 r592_read_reg_raw_be(struct r592_device *dev, int address)
+{
+	u32 value = __raw_readl(dev->mmio + address);
+	dbg_reg("reg #%02d == 0x%08x", address, value);
+	return be32_to_cpu(value);
+}
+
+/* Writes a big endian DWORD register */
+static inline void r592_write_reg_raw_be(struct r592_device *dev,
+							int address, u32 value)
+{
+	dbg_reg("reg #%02d <- 0x%08x", address, value);
+	__raw_writel(cpu_to_be32(value), dev->mmio + address);
+}
+
+/* Set specific bits in a register (little endian) */
+static inline void r592_set_reg_mask(struct r592_device *dev,
+							int address, u32 mask)
+{
+	u32 reg = readl(dev->mmio + address);
+	dbg_reg("reg #%02d |= 0x%08x (old =0x%08x)", address, mask, reg);
+	writel(reg | mask , dev->mmio + address);
+}
+
+/* Clear specific bits in a register (little endian) */
+static inline void r592_clear_reg_mask(struct r592_device *dev,
+						int address, u32 mask)
+{
+	u32 reg = readl(dev->mmio + address);
+	dbg_reg("reg #%02d &= 0x%08x (old = 0x%08x, mask = 0x%08x)",
+						address, ~mask, reg, mask);
+	writel(reg & ~mask, dev->mmio + address);
+}
+
+
+/* Wait for status bits while checking for errors */
+static int r592_wait_status(struct r592_device *dev, u32 mask, u32 wanted_mask)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	u32 reg = r592_read_reg(dev, R592_STATUS);
+
+	if ((reg & mask) == wanted_mask)
+		return 0;
+
+	while (time_before(jiffies, timeout)) {
+
+		reg = r592_read_reg(dev, R592_STATUS);
+
+		if ((reg & mask) == wanted_mask)
+			return 0;
+
+		if (reg & (R592_STATUS_SEND_ERR | R592_STATUS_RECV_ERR))
+			return -EIO;
+
+		cpu_relax();
+	}
+	return -ETIME;
+}
+
+
+/* Enable/disable device */
+static int r592_enable_device(struct r592_device *dev, bool enable)
+{
+	dbg("%sabling the device", enable ? "en" : "dis");
+
+	if (enable) {
+
+		/* Power up the card */
+		r592_write_reg(dev, R592_POWER, R592_POWER_0 | R592_POWER_1);
+
+		/* Perform a reset */
+		r592_set_reg_mask(dev, R592_IO, R592_IO_RESET);
+
+		msleep(100);
+	} else
+		/* Power down the card */
+		r592_write_reg(dev, R592_POWER, 0);
+
+	return 0;
+}
+
+/* Set serial/parallel mode */
+static int r592_set_mode(struct r592_device *dev, bool parallel_mode)
+{
+	if (!parallel_mode) {
+		dbg("switching to serial mode");
+
+		/* Set serial mode */
+		r592_write_reg(dev, R592_IO_MODE, R592_IO_MODE_SERIAL);
+
+		r592_clear_reg_mask(dev, R592_POWER, R592_POWER_20);
+
+	} else {
+		dbg("switching to parallel mode");
+
+		/* This setting should be set _before_ switch TPC */
+		r592_set_reg_mask(dev, R592_POWER, R592_POWER_20);
+
+		r592_clear_reg_mask(dev, R592_IO,
+			R592_IO_SERIAL1 | R592_IO_SERIAL2);
+
+		/* Set the parallel mode now */
+		r592_write_reg(dev, R592_IO_MODE, R592_IO_MODE_PARALLEL);
+	}
+
+	dev->parallel_mode = parallel_mode;
+	return 0;
+}
+
+/* Perform a controller reset without powering down the card */
+static void r592_host_reset(struct r592_device *dev)
+{
+	r592_set_reg_mask(dev, R592_IO, R592_IO_RESET);
+	msleep(100);
+	r592_set_mode(dev, dev->parallel_mode);
+}
+
+/* Disable all hardware interrupts */
+static void r592_clear_interrupts(struct r592_device *dev)
+{
+	/* Disable & ACK all interrupts */
+	r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_ACK_MASK);
+	r592_clear_reg_mask(dev, R592_REG_MSC, IRQ_ALL_EN_MASK);
+}
+
+/* Tests if there is an CRC error */
+static int r592_test_io_error(struct r592_device *dev)
+{
+	if (!(r592_read_reg(dev, R592_STATUS) &
+		(R592_STATUS_SEND_ERR | R592_STATUS_RECV_ERR)))
+		return 0;
+
+	return -EIO;
+}
+
+/* Ensure that FIFO is ready for use */
+static int r592_test_fifo_empty(struct r592_device *dev)
+{
+	if (r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_FIFO_EMPTY)
+		return 0;
+
+	dbg("FIFO not ready, trying to reset the device");
+	r592_host_reset(dev);
+
+	if (r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_FIFO_EMPTY)
+		return 0;
+
+	message("FIFO still not ready, giving up");
+	return -EIO;
+}
+
+/* Activates the DMA transfer from to FIFO */
+static void r592_start_dma(struct r592_device *dev, bool is_write)
+{
+	unsigned long flags;
+	u32 reg;
+	spin_lock_irqsave(&dev->irq_lock, flags);
+
+	/* Ack interrupts (just in case) + enable them */
+	r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK);
+	r592_set_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK);
+
+	/* Set DMA address */
+	r592_write_reg(dev, R592_FIFO_DMA, sg_dma_address(&dev->req->sg));
+
+	/* Enable the DMA */
+	reg = r592_read_reg(dev, R592_FIFO_DMA_SETTINGS);
+	reg |= R592_FIFO_DMA_SETTINGS_EN;
+
+	if (!is_write)
+		reg |= R592_FIFO_DMA_SETTINGS_DIR;
+	else
+		reg &= ~R592_FIFO_DMA_SETTINGS_DIR;
+	r592_write_reg(dev, R592_FIFO_DMA_SETTINGS, reg);
+
+	spin_unlock_irqrestore(&dev->irq_lock, flags);
+}
+
+/* Cleanups DMA related settings */
+static void r592_stop_dma(struct r592_device *dev, int error)
+{
+	r592_clear_reg_mask(dev, R592_FIFO_DMA_SETTINGS,
+		R592_FIFO_DMA_SETTINGS_EN);
+
+	/* This is only a precation */
+	r592_write_reg(dev, R592_FIFO_DMA,
+			dev->dummy_dma_page_physical_address);
+
+	r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_EN_MASK);
+	r592_clear_reg_mask(dev, R592_REG_MSC, DMA_IRQ_ACK_MASK);
+	dev->dma_error = error;
+}
+
+/* Test if hardware supports DMA */
+static void r592_check_dma(struct r592_device *dev)
+{
+	dev->dma_capable = r592_enable_dma &&
+		(r592_read_reg(dev, R592_FIFO_DMA_SETTINGS) &
+			R592_FIFO_DMA_SETTINGS_CAP);
+}
+
+/* Transfers fifo contents in/out using DMA */
+static int r592_transfer_fifo_dma(struct r592_device *dev)
+{
+	int len, sg_count;
+	bool is_write;
+
+	if (!dev->dma_capable || !dev->req->long_data)
+		return -EINVAL;
+
+	len = dev->req->sg.length;
+	is_write = dev->req->data_dir == WRITE;
+
+	if (len != R592_LFIFO_SIZE)
+		return -EINVAL;
+
+	dbg_verbose("doing dma transfer");
+
+	dev->dma_error = 0;
+	INIT_COMPLETION(dev->dma_done);
+
+	/* TODO: hidden assumption about nenth beeing always 1 */
+	sg_count = dma_map_sg(&dev->pci_dev->dev, &dev->req->sg, 1, is_write ?
+		PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+
+	if (sg_count != 1 ||
+			(sg_dma_len(&dev->req->sg) < dev->req->sg.length)) {
+		message("problem in dma_map_sg");
+		return -EIO;
+	}
+
+	r592_start_dma(dev, is_write);
+
+	/* Wait for DMA completion */
+	if (!wait_for_completion_timeout(
+			&dev->dma_done, msecs_to_jiffies(1000))) {
+		message("DMA timeout");
+		r592_stop_dma(dev, -ETIMEDOUT);
+	}
+
+	dma_unmap_sg(&dev->pci_dev->dev, &dev->req->sg, 1, is_write ?
+		PCI_DMA_TODEVICE : PCI_DMA_FROMDEVICE);
+
+
+	return dev->dma_error;
+}
+
+/*
+ * Writes the FIFO in 4 byte chunks.
+ * If length isn't 4 byte aligned, rest of the data if put to a fifo
+ * to be written later
+ * Use r592_flush_fifo_write to flush that fifo when writing for the
+ * last time
+ */
+static void r592_write_fifo_pio(struct r592_device *dev,
+					unsigned char *buffer, int len)
+{
+	/* flush spill from former write */
+	if (!kfifo_is_empty(&dev->pio_fifo)) {
+
+		u8 tmp[4] = {0};
+		int copy_len = kfifo_in(&dev->pio_fifo, buffer, len);
+
+		if (!kfifo_is_full(&dev->pio_fifo))
+			return;
+		len -= copy_len;
+		buffer += copy_len;
+
+		copy_len = kfifo_out(&dev->pio_fifo, tmp, 4);
+		WARN_ON(copy_len != 4);
+		r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)tmp);
+	}
+
+	WARN_ON(!kfifo_is_empty(&dev->pio_fifo));
+
+	/* write full dwords */
+	while (len >= 4) {
+		r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer);
+		buffer += 4;
+		len -= 4;
+	}
+
+	/* put remaining bytes to the spill */
+	if (len)
+		kfifo_in(&dev->pio_fifo, buffer, len);
+}
+
+/* Flushes the temporary FIFO used to make aligned DWORD writes */
+static void r592_flush_fifo_write(struct r592_device *dev)
+{
+	u8 buffer[4] = { 0 };
+	int len;
+
+	if (kfifo_is_empty(&dev->pio_fifo))
+		return;
+
+	len = kfifo_out(&dev->pio_fifo, buffer, 4);
+	r592_write_reg_raw_be(dev, R592_FIFO_PIO, *(u32 *)buffer);
+}
+
+/*
+ * Read a fifo in 4 bytes chunks.
+ * If input doesn't fit the buffer, it places bytes of last dword in spill
+ * buffer, so that they don't get lost on last read, just throw these away.
+ */
+static void r592_read_fifo_pio(struct r592_device *dev,
+						unsigned char *buffer, int len)
+{
+	u8 tmp[4];
+
+	/* Read from last spill */
+	if (!kfifo_is_empty(&dev->pio_fifo)) {
+		int bytes_copied =
+			kfifo_out(&dev->pio_fifo, buffer, min(4, len));
+		buffer += bytes_copied;
+		len -= bytes_copied;
+
+		if (!kfifo_is_empty(&dev->pio_fifo))
+			return;
+	}
+
+	/* Reads dwords from FIFO */
+	while (len >= 4) {
+		*(u32 *)buffer = r592_read_reg_raw_be(dev, R592_FIFO_PIO);
+		buffer += 4;
+		len -= 4;
+	}
+
+	if (len) {
+		*(u32 *)tmp = r592_read_reg_raw_be(dev, R592_FIFO_PIO);
+		kfifo_in(&dev->pio_fifo, tmp, 4);
+		len -= kfifo_out(&dev->pio_fifo, buffer, len);
+	}
+
+	WARN_ON(len);
+	return;
+}
+
+/* Transfers actual data using PIO. */
+static int r592_transfer_fifo_pio(struct r592_device *dev)
+{
+	unsigned long flags;
+
+	bool is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS;
+	struct sg_mapping_iter miter;
+
+	kfifo_reset(&dev->pio_fifo);
+
+	if (!dev->req->long_data) {
+		if (is_write) {
+			r592_write_fifo_pio(dev, dev->req->data,
+							dev->req->data_len);
+			r592_flush_fifo_write(dev);
+		} else
+			r592_read_fifo_pio(dev, dev->req->data,
+							dev->req->data_len);
+		return 0;
+	}
+
+	local_irq_save(flags);
+	sg_miter_start(&miter, &dev->req->sg, 1, SG_MITER_ATOMIC |
+		(is_write ? SG_MITER_FROM_SG : SG_MITER_TO_SG));
+
+	/* Do the transfer fifo<->memory*/
+	while (sg_miter_next(&miter))
+		if (is_write)
+			r592_write_fifo_pio(dev, miter.addr, miter.length);
+		else
+			r592_read_fifo_pio(dev, miter.addr, miter.length);
+
+
+	/* Write last few non aligned bytes*/
+	if (is_write)
+		r592_flush_fifo_write(dev);
+
+	sg_miter_stop(&miter);
+	local_irq_restore(flags);
+	return 0;
+}
+
+/* Executes one TPC (data is read/written from small or large fifo) */
+static void r592_execute_tpc(struct r592_device *dev)
+{
+	bool is_write = dev->req->tpc >= MS_TPC_SET_RW_REG_ADRS;
+	int len, error;
+	u32 status, reg;
+
+	if (!dev->req) {
+		message("BUG: tpc execution without request!");
+		return;
+	}
+
+	len = dev->req->long_data ?
+		dev->req->sg.length : dev->req->data_len;
+
+	/* Ensure that FIFO can hold the input data */
+	if (len > R592_LFIFO_SIZE) {
+		message("IO: hardware doesn't support TPCs longer that 512");
+		error = -ENOSYS;
+		goto out;
+	}
+
+	if (!(r592_read_reg(dev, R592_REG_MSC) & R592_REG_MSC_PRSNT)) {
+		dbg("IO: refusing to send TPC because card is absent");
+		error = -ENODEV;
+		goto out;
+	}
+
+	dbg("IO: executing %s LEN=%d",
+			memstick_debug_get_tpc_name(dev->req->tpc), len);
+
+	/* Set IO direction */
+	if (is_write)
+		r592_set_reg_mask(dev, R592_IO, R592_IO_DIRECTION);
+	else
+		r592_clear_reg_mask(dev, R592_IO, R592_IO_DIRECTION);
+
+
+	error = r592_test_fifo_empty(dev);
+	if (error)
+		goto out;
+
+	/* Transfer write data */
+	if (is_write) {
+		error = r592_transfer_fifo_dma(dev);
+		if (error == -EINVAL)
+			error = r592_transfer_fifo_pio(dev);
+	}
+
+	if (error)
+		goto out;
+
+	/* Trigger the TPC */
+	reg = (len << R592_TPC_EXEC_LEN_SHIFT) |
+		(dev->req->tpc << R592_TPC_EXEC_TPC_SHIFT) |
+			R592_TPC_EXEC_BIG_FIFO;
+
+	r592_write_reg(dev, R592_TPC_EXEC, reg);
+
+	/* Wait for TPC completion */
+	status = R592_STATUS_RDY;
+	if (dev->req->need_card_int)
+		status |= R592_STATUS_CED;
+
+	error = r592_wait_status(dev, status, status);
+	if (error) {
+		message("card didn't respond");
+		goto out;
+	}
+
+	/* Test IO errors */
+	error = r592_test_io_error(dev);
+	if (error) {
+		dbg("IO error");
+		goto out;
+	}
+
+	/* Read data from FIFO */
+	if (!is_write) {
+		error = r592_transfer_fifo_dma(dev);
+		if (error == -EINVAL)
+			error = r592_transfer_fifo_pio(dev);
+	}
+
+	/* read INT reg. This can be shortened with shifts, but that way
+		its more readable */
+	if (dev->parallel_mode && dev->req->need_card_int) {
+
+		dev->req->int_reg = 0;
+		status = r592_read_reg(dev, R592_STATUS);
+
+		if (status & R592_STATUS_P_CMDNACK)
+			dev->req->int_reg |= MEMSTICK_INT_CMDNAK;
+		if (status & R592_STATUS_P_BREQ)
+			dev->req->int_reg |= MEMSTICK_INT_BREQ;
+		if (status & R592_STATUS_P_INTERR)
+			dev->req->int_reg |= MEMSTICK_INT_ERR;
+		if (status & R592_STATUS_P_CED)
+			dev->req->int_reg |= MEMSTICK_INT_CED;
+	}
+
+	if (error)
+		dbg("FIFO read error");
+out:
+	dev->req->error = error;
+	r592_clear_reg_mask(dev, R592_REG_MSC, R592_REG_MSC_LED);
+	return;
+}
+
+/* Main request processing thread */
+static int r592_process_thread(void *data)
+{
+	int error;
+	struct r592_device *dev = (struct r592_device *)data;
+	unsigned long flags;
+
+	while (!kthread_should_stop()) {
+		spin_lock_irqsave(&dev->io_thread_lock, flags);
+		set_current_state(TASK_INTERRUPTIBLE);
+		error = memstick_next_req(dev->host, &dev->req);
+		spin_unlock_irqrestore(&dev->io_thread_lock, flags);
+
+		if (error) {
+			if (error == -ENXIO || error == -EAGAIN) {
+				dbg_verbose("IO: done IO, sleeping");
+			} else {
+				dbg("IO: unknown error from "
+					"memstick_next_req %d", error);
+			}
+
+			if (kthread_should_stop())
+				set_current_state(TASK_RUNNING);
+
+			schedule();
+		} else {
+			set_current_state(TASK_RUNNING);
+			r592_execute_tpc(dev);
+		}
+	}
+	return 0;
+}
+
+/* Reprogram chip to detect change in card state */
+/* eg, if card is detected, arm it to detect removal, and vice versa */
+static void r592_update_card_detect(struct r592_device *dev)
+{
+	u32 reg = r592_read_reg(dev, R592_REG_MSC);
+	bool card_detected = reg & R592_REG_MSC_PRSNT;
+
+	dbg("update card detect. card state: %s", card_detected ?
+		"present" : "absent");
+
+	reg &= ~((R592_REG_MSC_IRQ_REMOVE | R592_REG_MSC_IRQ_INSERT) << 16);
+
+	if (card_detected)
+		reg |= (R592_REG_MSC_IRQ_REMOVE << 16);
+	else
+		reg |= (R592_REG_MSC_IRQ_INSERT << 16);
+
+	r592_write_reg(dev, R592_REG_MSC, reg);
+}
+
+/* Timer routine that fires 1 second after last card detection event, */
+static void r592_detect_timer(long unsigned int data)
+{
+	struct r592_device *dev = (struct r592_device *)data;
+	r592_update_card_detect(dev);
+	memstick_detect_change(dev->host);
+}
+
+/* Interrupt handler */
+static irqreturn_t r592_irq(int irq, void *data)
+{
+	struct r592_device *dev = (struct r592_device *)data;
+	irqreturn_t ret = IRQ_NONE;
+	u32 reg;
+	u16 irq_enable, irq_status;
+	unsigned long flags;
+	int error;
+
+	spin_lock_irqsave(&dev->irq_lock, flags);
+
+	reg = r592_read_reg(dev, R592_REG_MSC);
+	irq_enable = reg >> 16;
+	irq_status = reg & 0xFFFF;
+
+	/* Ack the interrupts */
+	reg &= ~irq_status;
+	r592_write_reg(dev, R592_REG_MSC, reg);
+
+	/* Get the IRQ status minus bits that aren't enabled */
+	irq_status &= (irq_enable);
+
+	/* Due to limitation of memstick core, we don't look at bits that
+		indicate that card was removed/inserted and/or present */
+	if (irq_status & (R592_REG_MSC_IRQ_INSERT | R592_REG_MSC_IRQ_REMOVE)) {
+
+		bool card_was_added = irq_status & R592_REG_MSC_IRQ_INSERT;
+		ret = IRQ_HANDLED;
+
+		message("IRQ: card %s", card_was_added ? "added" : "removed");
+
+		mod_timer(&dev->detect_timer,
+			jiffies + msecs_to_jiffies(card_was_added ? 500 : 50));
+	}
+
+	if (irq_status &
+		(R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR)) {
+		ret = IRQ_HANDLED;
+
+		if (irq_status & R592_REG_MSC_FIFO_DMA_ERR) {
+			message("IRQ: DMA error");
+			error = -EIO;
+		} else {
+			dbg_verbose("IRQ: dma done");
+			error = 0;
+		}
+
+		r592_stop_dma(dev, error);
+		complete(&dev->dma_done);
+	}
+
+	spin_unlock_irqrestore(&dev->irq_lock, flags);
+	return ret;
+}
+
+/* External inteface: set settings */
+static int r592_set_param(struct memstick_host *host,
+			enum memstick_param param, int value)
+{
+	struct r592_device *dev = memstick_priv(host);
+
+	switch (param) {
+	case MEMSTICK_POWER:
+		switch (value) {
+		case MEMSTICK_POWER_ON:
+			return r592_enable_device(dev, true);
+		case MEMSTICK_POWER_OFF:
+			return r592_enable_device(dev, false);
+		default:
+			return -EINVAL;
+		}
+	case MEMSTICK_INTERFACE:
+		switch (value) {
+		case MEMSTICK_SERIAL:
+			return r592_set_mode(dev, 0);
+		case MEMSTICK_PAR4:
+			return r592_set_mode(dev, 1);
+		default:
+			return -EINVAL;
+		}
+	default:
+		return -EINVAL;
+	}
+}
+
+/* External interface: submit requests */
+static void r592_submit_req(struct memstick_host *host)
+{
+	struct r592_device *dev = memstick_priv(host);
+	unsigned long flags;
+
+	if (dev->req)
+		return;
+
+	spin_lock_irqsave(&dev->io_thread_lock, flags);
+	if (wake_up_process(dev->io_thread))
+		dbg_verbose("IO thread woken to process requests");
+	spin_unlock_irqrestore(&dev->io_thread_lock, flags);
+}
+
+static const struct pci_device_id r592_pci_id_tbl[] = {
+
+	{ PCI_VDEVICE(RICOH, 0x0592), },
+	{ },
+};
+
+/* Main entry */
+static int r592_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	int error = -ENOMEM;
+	struct memstick_host *host;
+	struct r592_device *dev;
+
+	/* Allocate memory */
+	host = memstick_alloc_host(sizeof(struct r592_device), &pdev->dev);
+	if (!host)
+		goto error1;
+
+	dev = memstick_priv(host);
+	dev->host = host;
+	dev->pci_dev = pdev;
+	pci_set_drvdata(pdev, dev);
+
+	/* pci initialization */
+	error = pci_enable_device(pdev);
+	if (error)
+		goto error2;
+
+	pci_set_master(pdev);
+	error = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (error)
+		goto error3;
+
+	error = pci_request_regions(pdev, DRV_NAME);
+	if (error)
+		goto error3;
+
+	dev->mmio = pci_ioremap_bar(pdev, 0);
+	if (!dev->mmio)
+		goto error4;
+
+	dev->irq = pdev->irq;
+	spin_lock_init(&dev->irq_lock);
+	spin_lock_init(&dev->io_thread_lock);
+	init_completion(&dev->dma_done);
+	INIT_KFIFO(dev->pio_fifo);
+	setup_timer(&dev->detect_timer,
+		r592_detect_timer, (long unsigned int)dev);
+
+	/* Host initialization */
+	host->caps = MEMSTICK_CAP_PAR4;
+	host->request = r592_submit_req;
+	host->set_param = r592_set_param;
+	r592_check_dma(dev);
+
+	dev->io_thread = kthread_run(r592_process_thread, dev, "r592_io");
+	if (IS_ERR(dev->io_thread)) {
+		error = PTR_ERR(dev->io_thread);
+		goto error5;
+	}
+
+	/* This is just a precation, so don't fail */
+	dev->dummy_dma_page = pci_alloc_consistent(pdev, PAGE_SIZE,
+		&dev->dummy_dma_page_physical_address);
+	r592_stop_dma(dev , 0);
+
+	if (request_irq(dev->irq, &r592_irq, IRQF_SHARED,
+			  DRV_NAME, dev))
+		goto error6;
+
+	r592_update_card_detect(dev);
+	if (memstick_add_host(host))
+		goto error7;
+
+	message("driver successfully loaded");
+	return 0;
+error7:
+	free_irq(dev->irq, dev);
+error6:
+	if (dev->dummy_dma_page)
+		pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page,
+			dev->dummy_dma_page_physical_address);
+
+	kthread_stop(dev->io_thread);
+error5:
+	iounmap(dev->mmio);
+error4:
+	pci_release_regions(pdev);
+error3:
+	pci_disable_device(pdev);
+error2:
+	memstick_free_host(host);
+error1:
+	return error;
+}
+
+static void r592_remove(struct pci_dev *pdev)
+{
+	int error = 0;
+	struct r592_device *dev = pci_get_drvdata(pdev);
+
+	/* Stop the processing thread.
+	That ensures that we won't take any more requests */
+	kthread_stop(dev->io_thread);
+
+	r592_enable_device(dev, false);
+
+	while (!error && dev->req) {
+		dev->req->error = -ETIME;
+		error = memstick_next_req(dev->host, &dev->req);
+	}
+	memstick_remove_host(dev->host);
+
+	free_irq(dev->irq, dev);
+	iounmap(dev->mmio);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	memstick_free_host(dev->host);
+
+	if (dev->dummy_dma_page)
+		pci_free_consistent(pdev, PAGE_SIZE, dev->dummy_dma_page,
+			dev->dummy_dma_page_physical_address);
+}
+
+#ifdef CONFIG_PM
+static int r592_suspend(struct device *core_dev)
+{
+	struct pci_dev *pdev = to_pci_dev(core_dev);
+	struct r592_device *dev = pci_get_drvdata(pdev);
+
+	r592_clear_interrupts(dev);
+	memstick_suspend_host(dev->host);
+	del_timer_sync(&dev->detect_timer);
+	return 0;
+}
+
+static int r592_resume(struct device *core_dev)
+{
+	struct pci_dev *pdev = to_pci_dev(core_dev);
+	struct r592_device *dev = pci_get_drvdata(pdev);
+
+	r592_clear_interrupts(dev);
+	r592_enable_device(dev, false);
+	memstick_resume_host(dev->host);
+	r592_update_card_detect(dev);
+	return 0;
+}
+
+SIMPLE_DEV_PM_OPS(r592_pm_ops, r592_suspend, r592_resume);
+#endif
+
+MODULE_DEVICE_TABLE(pci, r592_pci_id_tbl);
+
+static struct pci_driver r852_pci_driver = {
+	.name		= DRV_NAME,
+	.id_table	= r592_pci_id_tbl,
+	.probe		= r592_probe,
+	.remove		= r592_remove,
+#ifdef CONFIG_PM
+	.driver.pm	= &r592_pm_ops,
+#endif
+};
+
+static __init int r592_module_init(void)
+{
+	return pci_register_driver(&r852_pci_driver);
+}
+
+static void __exit r592_module_exit(void)
+{
+	pci_unregister_driver(&r852_pci_driver);
+}
+
+module_init(r592_module_init);
+module_exit(r592_module_exit);
+
+module_param_named(enable_dma, r592_enable_dma, bool, S_IRUGO);
+MODULE_PARM_DESC(enable_dma, "Enable usage of the DMA (default)");
+module_param(debug, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug level (0-3)");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Maxim Levitsky <maximlevitsky@gmail.com>");
+MODULE_DESCRIPTION("Ricoh R5C592 Memstick/Memstick PRO card reader driver");
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/host/r592.h linux-libre-2.6.39-gnu/drivers/memstick/host/r592.h
--- linux-libre-2.6.38-gnu/drivers/memstick/host/r592.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/memstick/host/r592.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,175 @@
+/*
+ * Copyright (C) 2010 - Maxim Levitsky
+ * driver for Ricoh memstick readers
+ *
+ * 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 R592_H
+
+#include <linux/memstick.h>
+#include <linux/spinlock.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/kfifo.h>
+#include <linux/ctype.h>
+
+/* write to this reg (number,len) triggers TPC execution */
+#define R592_TPC_EXEC			0x00
+#define R592_TPC_EXEC_LEN_SHIFT		16		/* Bits 16..25 are TPC len */
+#define R592_TPC_EXEC_BIG_FIFO		(1 << 26)	/* If bit 26 is set, large fifo is used (reg 48) */
+#define R592_TPC_EXEC_TPC_SHIFT		28		/* Bits 28..31 are the TPC number */
+
+
+/* Window for small TPC fifo (big endian)*/
+/* reads and writes always are done in  8 byte chunks */
+/* Not used in driver, because large fifo does better job */
+#define R592_SFIFO			0x08
+
+
+/* Status register (ms int, small fifo, IO)*/
+#define R592_STATUS			0x10
+							/* Parallel INT bits */
+#define R592_STATUS_P_CMDNACK		(1 << 16)	/* INT reg: NACK (parallel mode) */
+#define R592_STATUS_P_BREQ		(1 << 17)	/* INT reg: card ready (parallel mode)*/
+#define R592_STATUS_P_INTERR		(1 << 18)	/* INT reg: int error (parallel mode)*/
+#define R592_STATUS_P_CED		(1 << 19)	/* INT reg: command done (parallel mode) */
+
+							/* Fifo status */
+#define R592_STATUS_SFIFO_FULL		(1 << 20)	/* Small Fifo almost full (last chunk is written) */
+#define R592_STATUS_SFIFO_EMPTY		(1 << 21)	/* Small Fifo empty */
+
+							/* Error detection via CRC */
+#define R592_STATUS_SEND_ERR		(1 << 24)	/* Send failed */
+#define R592_STATUS_RECV_ERR		(1 << 25)	/* Receive failed */
+
+							/* Card state */
+#define R592_STATUS_RDY			(1 << 28)	/* RDY signal received */
+#define R592_STATUS_CED			(1 << 29)	/* INT: Command done (serial mode)*/
+#define R592_STATUS_SFIFO_INPUT		(1 << 30)	/* Small fifo received data*/
+
+#define R592_SFIFO_SIZE			32		/* total size of small fifo is 32 bytes */
+#define R592_SFIFO_PACKET		8		/* packet size of small fifo */
+
+/* IO control */
+#define R592_IO				0x18
+#define	R592_IO_16			(1 << 16)	/* Set by default, can be cleared */
+#define	R592_IO_18			(1 << 18)	/* Set by default, can be cleared */
+#define	R592_IO_SERIAL1			(1 << 20)	/* Set by default, can be cleared, (cleared on parallel) */
+#define	R592_IO_22			(1 << 22)	/* Set by default, can be cleared */
+#define R592_IO_DIRECTION		(1 << 24)	/* TPC direction (1 write 0 read) */
+#define	R592_IO_26			(1 << 26)	/* Set by default, can be cleared */
+#define	R592_IO_SERIAL2			(1 << 30)	/* Set by default, can be cleared (cleared on parallel), serial doesn't work if unset */
+#define R592_IO_RESET			(1 << 31)	/* Reset, sets defaults*/
+
+
+/* Turns hardware on/off */
+#define R592_POWER			0x20		/* bits 0-7 writeable */
+#define R592_POWER_0			(1 << 0)	/* set on start, cleared on stop - must be set*/
+#define R592_POWER_1			(1 << 1)	/* set on start, cleared on stop - must be set*/
+#define R592_POWER_3			(1 << 3)	/* must be clear */
+#define R592_POWER_20			(1 << 5)	/* set before switch to parallel */
+
+/* IO mode*/
+#define R592_IO_MODE			0x24
+#define R592_IO_MODE_SERIAL		1
+#define R592_IO_MODE_PARALLEL		3
+
+
+/* IRQ,card detection,large fifo (first word irq status, second enable) */
+/* IRQs are ACKed by clearing the bits */
+#define R592_REG_MSC			0x28
+#define R592_REG_MSC_PRSNT		(1 << 1)	/* card present (only status)*/
+#define R592_REG_MSC_IRQ_INSERT		(1 << 8)	/* detect insert / card insered */
+#define R592_REG_MSC_IRQ_REMOVE		(1 << 9)	/* detect removal / card removed */
+#define R592_REG_MSC_FIFO_EMPTY		(1 << 10)	/* fifo is empty */
+#define R592_REG_MSC_FIFO_DMA_DONE	(1 << 11)	/* dma enable / dma done */
+
+#define R592_REG_MSC_FIFO_USER_ORN	(1 << 12)	/* set if software reads empty fifo (if R592_REG_MSC_FIFO_EMPTY is set) */
+#define R592_REG_MSC_FIFO_MISMATH	(1 << 13)	/* set if amount of data in fifo doesn't match amount in TPC */
+#define R592_REG_MSC_FIFO_DMA_ERR	(1 << 14)	/* IO failure */
+#define R592_REG_MSC_LED		(1 << 15)	/* clear to turn led off (only status)*/
+
+#define DMA_IRQ_ACK_MASK \
+	(R592_REG_MSC_FIFO_DMA_DONE | R592_REG_MSC_FIFO_DMA_ERR)
+
+#define DMA_IRQ_EN_MASK (DMA_IRQ_ACK_MASK << 16)
+
+#define IRQ_ALL_ACK_MASK 0x00007F00
+#define IRQ_ALL_EN_MASK (IRQ_ALL_ACK_MASK << 16)
+
+/* DMA address for large FIFO read/writes*/
+#define R592_FIFO_DMA			0x2C
+
+/* PIO access to large FIFO (512 bytes) (big endian)*/
+#define R592_FIFO_PIO			0x30
+#define R592_LFIFO_SIZE			512		/* large fifo size */
+
+
+/* large FIFO DMA settings */
+#define R592_FIFO_DMA_SETTINGS		0x34
+#define R592_FIFO_DMA_SETTINGS_EN	(1 << 0)	/* DMA enabled */
+#define R592_FIFO_DMA_SETTINGS_DIR	(1 << 1)	/* Dma direction (1 read, 0 write) */
+#define R592_FIFO_DMA_SETTINGS_CAP	(1 << 24)	/* Dma is aviable */
+
+/* Maybe just an delay */
+/* Bits 17..19 are just number */
+/* bit 16 is set, then bit 20 is waited */
+/* time to wait is about 50 spins * 2 ^ (bits 17..19) */
+/* seems to be possible just to ignore */
+/* Probably debug register */
+#define R592_REG38			0x38
+#define R592_REG38_CHANGE		(1 << 16)	/* Start bit */
+#define R592_REG38_DONE			(1 << 20)	/* HW set this after the delay */
+#define R592_REG38_SHIFT		17
+
+/* Debug register, written (0xABCDEF00) when error happens - not used*/
+#define R592_REG_3C			0x3C
+
+struct r592_device {
+	struct pci_dev *pci_dev;
+	struct memstick_host	*host;		/* host backpointer */
+	struct memstick_request *req;		/* current request */
+
+	/* Registers, IRQ */
+	void __iomem *mmio;
+	int irq;
+	spinlock_t irq_lock;
+	spinlock_t io_thread_lock;
+	struct timer_list detect_timer;
+
+	struct task_struct *io_thread;
+	bool parallel_mode;
+
+	DECLARE_KFIFO(pio_fifo, u8, sizeof(u32));
+
+	/* DMA area */
+	int dma_capable;
+	int dma_error;
+	struct completion dma_done;
+	void *dummy_dma_page;
+	dma_addr_t dummy_dma_page_physical_address;
+
+};
+
+#define DRV_NAME "r592"
+
+
+#define message(format, ...) \
+	printk(KERN_INFO DRV_NAME ": " format "\n", ## __VA_ARGS__)
+
+#define __dbg(level, format, ...) \
+	do { \
+		if (debug >= level) \
+			printk(KERN_DEBUG DRV_NAME \
+				": " format "\n", ## __VA_ARGS__); \
+	} while (0)
+
+
+#define dbg(format, ...)		__dbg(1, format, ## __VA_ARGS__)
+#define dbg_verbose(format, ...)	__dbg(2, format, ## __VA_ARGS__)
+#define dbg_reg(format, ...)		__dbg(3, format, ## __VA_ARGS__)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/memstick/Makefile linux-libre-2.6.39-gnu/drivers/memstick/Makefile
--- linux-libre-2.6.38-gnu/drivers/memstick/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/memstick/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,9 +2,7 @@
 # Makefile for the kernel MemoryStick device drivers.
 #
 
-ifeq ($(CONFIG_MEMSTICK_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+subdir-ccflags-$(CONFIG_MEMSTICK_DEBUG) := -DDEBUG
 
 obj-$(CONFIG_MEMSTICK)		+= core/
 obj-$(CONFIG_MEMSTICK)		+= host/
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_cnfg.h linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_cnfg.h
--- linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_cnfg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_cnfg.h	2011-05-19 00:06:34.000000000 -0400
@@ -2593,6 +2593,7 @@
 #define MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE              (0x03)
 #define MPI_SAS_IOUNIT0_RATE_1_5                            (0x08)
 #define MPI_SAS_IOUNIT0_RATE_3_0                            (0x09)
+#define MPI_SAS_IOUNIT0_RATE_6_0                            (0x0A)
 
 /* see mpi_sas.h for values for SAS IO Unit Page 0 ControllerPhyDeviceInfo values */
 
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_ioc.h linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_ioc.h
--- linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_ioc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_ioc.h	2011-05-19 00:06:34.000000000 -0400
@@ -841,6 +841,7 @@
 #define MPI_EVENT_SAS_PLS_LR_RATE_SATA_OOB_COMPLETE         (0x03)
 #define MPI_EVENT_SAS_PLS_LR_RATE_1_5                       (0x08)
 #define MPI_EVENT_SAS_PLS_LR_RATE_3_0                       (0x09)
+#define MPI_EVENT_SAS_PLS_LR_RATE_6_0                       (0x0A)
 
 /* SAS Discovery Event data */
 
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_log_fc.h linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_log_fc.h
--- linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_log_fc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_log_fc.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,8 +38,8 @@
 {
     MPI_IOCLOGINFO_FC_INIT_BASE                     = 0x20000000,
     MPI_IOCLOGINFO_FC_INIT_ERROR_OUT_OF_ORDER_FRAME = 0x20000001, /* received an out of order frame - unsupported */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primative */
-    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primative */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_START_OF_FRAME = 0x20000002, /* Bad Rx Frame, bad start of frame primitive */
+    MPI_IOCLOGINFO_FC_INIT_ERROR_BAD_END_OF_FRAME   = 0x20000003, /* Bad Rx Frame, bad end of frame primitive */
     MPI_IOCLOGINFO_FC_INIT_ERROR_OVER_RUN           = 0x20000004, /* Bad Rx Frame, overrun */
     MPI_IOCLOGINFO_FC_INIT_ERROR_RX_OTHER           = 0x20000005, /* Other errors caught by IOC which require retries */
     MPI_IOCLOGINFO_FC_INIT_ERROR_SUBPROC_DEAD       = 0x20000006, /* Main processor could not initialize sub-processor */
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_log_sas.h linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_log_sas.h
--- linux-libre-2.6.38-gnu/drivers/message/fusion/lsi/mpi_log_sas.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/lsi/mpi_log_sas.h	2011-05-19 00:06:34.000000000 -0400
@@ -56,9 +56,9 @@
 #define IOP_LOGINFO_CODE_FWUPLOAD_NO_FLASH_AVAILABLE         (0x0003E000) /* Tried to upload from flash, but there is none */
 #define IOP_LOGINFO_CODE_FWUPLOAD_UNKNOWN_IMAGE_TYPE         (0x0003E001) /* ImageType field contents were invalid */
 #define IOP_LOGINFO_CODE_FWUPLOAD_WRONG_IMAGE_SIZE           (0x0003E002) /* ImageSize field in TCSGE was bad/offset in MfgPg 4 was wrong */
-#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occured while attempting to upload the entire flash */
-#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED       (0x0003E004) /* Error occured while attempting to upload single flash region */
-#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE                (0x0003E005) /* Problem occured while DMAing FW to host memory */
+#define IOP_LOGINFO_CODE_FWUPLOAD_ENTIRE_FLASH_UPLOAD_FAILED (0x0003E003) /* Error occurred while attempting to upload the entire flash */
+#define IOP_LOGINFO_CODE_FWUPLOAD_REGION_UPLOAD_FAILED       (0x0003E004) /* Error occurred while attempting to upload single flash region */
+#define IOP_LOGINFO_CODE_FWUPLOAD_DMA_FAILURE                (0x0003E005) /* Problem occurred while DMAing FW to host memory */
 
 #define IOP_LOGINFO_CODE_DIAG_MSG_ERROR                      (0x00040000) /* Error handling diag msg - or'd with diag status */
 
@@ -187,8 +187,8 @@
 #define PL_LOGINFO_SUB_CODE_BREAK_ON_INCOMPLETE_BREAK_RCVD   (0x00005000)
 
 #define PL_LOGINFO_CODE_ENCL_MGMT_SMP_FRAME_FAILURE          (0x00200000) /* Can't get SMP Frame */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occured on SMP Read */
-#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR            (0x00200020) /* Error occured on SMP Write */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_READ_ERROR             (0x00200010) /* Error occurred on SMP Read */
+#define PL_LOGINFO_CODE_ENCL_MGMT_SMP_WRITE_ERROR            (0x00200020) /* Error occurred on SMP Write */
 #define PL_LOGINFO_CODE_ENCL_MGMT_NOT_SUPPORTED_ON_ENCL      (0x00200040) /* Encl Mgmt services not available for this WWID */
 #define PL_LOGINFO_CODE_ENCL_MGMT_ADDR_MODE_NOT_SUPPORTED    (0x00200050) /* Address Mode not suppored */
 #define PL_LOGINFO_CODE_ENCL_MGMT_BAD_SLOT_NUM               (0x00200060) /* Invalid Slot Number in SEP Msg */
@@ -207,8 +207,8 @@
 #define PL_LOGINFO_DA_SEP_RECEIVED_NACK_FROM_SLAVE           (0x00200103) /* SEP NACK'd, it is busy */
 #define PL_LOGINFO_DA_SEP_DID_NOT_RECEIVE_ACK                (0x00200104) /* SEP didn't rcv. ACK (Last Rcvd Bit = 1) */
 #define PL_LOGINFO_DA_SEP_BAD_STATUS_HDR_CHKSUM              (0x00200105) /* SEP stopped or sent bad chksum in Hdr */
-#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                       (0x00200106) /* SEP stopped while transfering data */
-#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                 (0x00200107) /* SEP stopped while transfering sense data */
+#define PL_LOGINFO_DA_SEP_STOP_ON_DATA                       (0x00200106) /* SEP stopped while transferring data */
+#define PL_LOGINFO_DA_SEP_STOP_ON_SENSE_DATA                 (0x00200107) /* SEP stopped while transferring sense data */
 #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_1          (0x00200108) /* SEP returned unknown scsi status */
 #define PL_LOGINFO_DA_SEP_UNSUPPORTED_SCSI_STATUS_2          (0x00200109) /* SEP returned unknown scsi status */
 #define PL_LOGINFO_DA_SEP_CHKSUM_ERROR_AFTER_STOP            (0x0020010A) /* SEP returned bad chksum after STOP */
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/Makefile linux-libre-2.6.39-gnu/drivers/message/fusion/Makefile
--- linux-libre-2.6.38-gnu/drivers/message/fusion/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
 
 # enable verbose logging
 # CONFIG_FUSION_LOGGING needs to be enabled in Kconfig
-#EXTRA_CFLAGS += -DMPT_DEBUG_VERBOSE
+#ccflags-y := -DMPT_DEBUG_VERBOSE
 
 
 #=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-} LSI_LOGIC
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/mptbase.c linux-libre-2.6.39-gnu/drivers/message/fusion/mptbase.c
--- linux-libre-2.6.38-gnu/drivers/message/fusion/mptbase.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/mptbase.c	2011-05-19 00:06:34.000000000 -0400
@@ -3435,7 +3435,7 @@
  *	If memory has already been allocated, the same (cached) value
  *	is returned.
  *
- *	Return 0 if successfull, or non-zero for failure
+ *	Return 0 if successful, or non-zero for failure
  **/
 int
 mpt_alloc_fw_memory(MPT_ADAPTER *ioc, int size)
@@ -6932,7 +6932,7 @@
  *	Message Unit Reset - instructs the IOC to reset the Reply Post and
  *	Free FIFO's. All the Message Frames on Reply Free FIFO are discarded.
  *	All posted buffers are freed, and event notification is turned off.
- *	IOC doesnt reply to any outstanding request. This will transfer IOC
+ *	IOC doesn't reply to any outstanding request. This will transfer IOC
  *	to READY state.
  **/
 int
@@ -7418,7 +7418,12 @@
 		case MPI_EVENT_SAS_PLS_LR_RATE_3_0:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
 			   "SAS PHY Link Status: Phy=%d:"
-			   " Rate 3.0 Gpbs",PhyNumber);
+			   " Rate 3.0 Gbps", PhyNumber);
+			break;
+		case MPI_EVENT_SAS_PLS_LR_RATE_6_0:
+			snprintf(evStr, EVENT_DESCR_STR_SZ,
+			   "SAS PHY Link Status: Phy=%d:"
+			   " Rate 6.0 Gbps", PhyNumber);
 			break;
 		default:
 			snprintf(evStr, EVENT_DESCR_STR_SZ,
@@ -7900,7 +7905,7 @@
 		    "Owner", 					/* 15h */
 		"Open Transmit DMA Abort",			/* 16h */
 		"IO Device Missing Delay Retry",		/* 17h */
-		"IO Cancelled Due to Recieve Error",		/* 18h */
+		"IO Cancelled Due to Receive Error",		/* 18h */
 		NULL,						/* 19h */
 		NULL,						/* 1Ah */
 		NULL,						/* 1Bh */
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/mptctl.c linux-libre-2.6.39-gnu/drivers/message/fusion/mptctl.c
--- linux-libre-2.6.38-gnu/drivers/message/fusion/mptctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/mptctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -985,7 +985,7 @@
 	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);
+		printk(MYIOC_s_INFO_FMT "F/W update successful!\n", iocp->name);
 		return 0;
 	} else if (iocstat == MPI_IOCSTATUS_INVALID_FUNCTION) {
 		printk(MYIOC_s_WARN_FMT "Hmmm...  F/W download not supported!?!\n",
@@ -1314,8 +1314,10 @@
 	else
 		karg->adapterType = MPT_IOCTL_INTERFACE_SCSI;
 
-	if (karg->hdr.port > 1)
+	if (karg->hdr.port > 1) {
+		kfree(karg);
 		return -EINVAL;
+	}
 	port = karg->hdr.port;
 
 	karg->port = port;
@@ -2405,7 +2407,7 @@
 	}
 
 	/* mf is null if command issued successfully
-	 * otherwise, failure occured after mf acquired.
+	 * otherwise, failure occurred after mf acquired.
 	 */
 	if (mf)
 		mpt_free_msg_frame(ioc, mf);
diff -druN linux-libre-2.6.38-gnu/drivers/message/fusion/mptsas.c linux-libre-2.6.39-gnu/drivers/message/fusion/mptsas.c
--- linux-libre-2.6.38-gnu/drivers/message/fusion/mptsas.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/fusion/mptsas.c	2011-05-19 00:06:34.000000000 -0400
@@ -307,7 +307,7 @@
 	spin_unlock_irqrestore(&ioc->fw_event_lock, flags);
 }
 
-/* free memory assoicated to a sas firmware event */
+/* free memory associated to a sas firmware event */
 static void
 mptsas_free_fw_event(MPT_ADAPTER *ioc, struct fw_event_work *fw_event)
 {
@@ -1094,7 +1094,7 @@
 /**
  * mptsas_target_reset_queue
  *
- * Receive request for TARGET_RESET after recieving an firmware
+ * Receive request for TARGET_RESET after receiving an firmware
  * event NOT_RESPONDING_EVENT, then put command in link list
  * and queue if task_queue already in use.
  *
@@ -1403,7 +1403,7 @@
 /**
  *	mptsas_add_end_device - report a new end device to sas transport layer
  *	@ioc: Pointer to MPT_ADAPTER structure
- *	@phy_info: decribes attached device
+ *	@phy_info: describes attached device
  *
  *	return (0) success (1) failure
  *
@@ -1481,7 +1481,7 @@
 /**
  *	mptsas_del_end_device - report a deleted end device to sas transport layer
  *	@ioc: Pointer to MPT_ADAPTER structure
- *	@phy_info: decribes attached device
+ *	@phy_info: describes attached device
  *
  **/
 static void
@@ -1973,7 +1973,6 @@
 	.change_queue_depth 		= mptscsih_change_queue_depth,
 	.eh_abort_handler		= mptscsih_abort,
 	.eh_device_reset_handler	= mptscsih_dev_reset,
-	.eh_bus_reset_handler		= mptscsih_bus_reset,
 	.eh_host_reset_handler		= mptscsih_host_reset,
 	.bios_param			= mptscsih_bios_param,
 	.can_queue			= MPT_SAS_CAN_QUEUE,
@@ -3063,6 +3062,9 @@
 	case MPI_SAS_IOUNIT0_RATE_3_0:
 		phy->negotiated_linkrate = SAS_LINK_RATE_3_0_GBPS;
 		break;
+	case MPI_SAS_IOUNIT0_RATE_6_0:
+		phy->negotiated_linkrate = SAS_LINK_RATE_6_0_GBPS;
+		break;
 	case MPI_SAS_IOUNIT0_RATE_SATA_OOB_COMPLETE:
 	case MPI_SAS_IOUNIT0_RATE_UNKNOWN:
 	default:
@@ -3691,7 +3693,8 @@
 	}
 
 	if (link_rate == MPI_SAS_IOUNIT0_RATE_1_5 ||
-	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0) {
+	    link_rate == MPI_SAS_IOUNIT0_RATE_3_0 ||
+	    link_rate == MPI_SAS_IOUNIT0_RATE_6_0) {
 
 		if (!port_info) {
 			if (ioc->old_sas_discovery_protocal) {
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/device.c linux-libre-2.6.39-gnu/drivers/message/i2o/device.c
--- linux-libre-2.6.38-gnu/drivers/message/i2o/device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/device.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
 
 	rc = i2o_device_issue_claim(dev, I2O_CMD_UTIL_CLAIM, I2O_CLAIM_PRIMARY);
 	if (!rc)
-		pr_debug("i2o: claim of device %d succeded\n",
+		pr_debug("i2o: claim of device %d succeeded\n",
 			 dev->lct_data.tid);
 	else
 		pr_debug("i2o: claim of device %d failed %d\n",
@@ -110,7 +110,7 @@
 	}
 
 	if (!rc)
-		pr_debug("i2o: claim release of device %d succeded\n",
+		pr_debug("i2o: claim release of device %d succeeded\n",
 			 dev->lct_data.tid);
 	else
 		pr_debug("i2o: claim release of device %d failed %d\n",
@@ -248,7 +248,7 @@
 			goto unreg_dev;
 	}
 
-	/* create user entries refering to this device */
+	/* create user entries referring to this device */
 	list_for_each_entry(tmp, &c->devices, list)
 	    if ((tmp->lct_data.user_tid == i2o_dev->lct_data.tid)
 		&& (tmp != i2o_dev)) {
@@ -267,7 +267,7 @@
 			goto rmlink1;
 	}
 
-	/* create parent entries refering to this device */
+	/* create parent entries referring to this device */
 	list_for_each_entry(tmp, &c->devices, list)
 	    if ((tmp->lct_data.parent_tid == i2o_dev->lct_data.tid)
 		&& (tmp != i2o_dev)) {
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/driver.c linux-libre-2.6.39-gnu/drivers/message/i2o/driver.c
--- linux-libre-2.6.38-gnu/drivers/message/i2o/driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,8 @@
 	osm_debug("Register driver %s\n", drv->name);
 
 	if (drv->event) {
-		drv->event_queue = create_workqueue(drv->name);
+		drv->event_queue = alloc_workqueue(drv->name,
+						   WQ_MEM_RECLAIM, 1);
 		if (!drv->event_queue) {
 			osm_err("Could not initialize event queue for driver "
 				"%s\n", drv->name);
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_block.c linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_block.c
--- linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_block.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_block.c	2011-05-19 00:06:34.000000000 -0400
@@ -610,7 +610,7 @@
 
 	/*
 	 * This is to deail with the case of an application
-	 * opening a device and then the device dissapears while
+	 * opening a device and then the device disappears while
 	 * it's in use, and then the application tries to release
 	 * it.  ex: Unmounting a deleted RAID volume at reboot.
 	 * If we send messages, it will just cause FAILs since
@@ -695,27 +695,29 @@
 };
 
 /**
- *	i2o_block_media_changed - Have we seen a media change?
+ *	i2o_block_check_events - Have we seen a media change?
  *	@disk: gendisk which should be verified
+ *	@clearing: events being cleared
  *
  *	Verifies if the media has changed.
  *
  *	Returns 1 if the media was changed or 0 otherwise.
  */
-static int i2o_block_media_changed(struct gendisk *disk)
+static unsigned int i2o_block_check_events(struct gendisk *disk,
+					   unsigned int clearing)
 {
 	struct i2o_block_device *p = disk->private_data;
 
 	if (p->media_change_flag) {
 		p->media_change_flag = 0;
-		return 1;
+		return DISK_EVENT_MEDIA_CHANGE;
 	}
 	return 0;
 }
 
 /**
  *	i2o_block_transfer - Transfer a request to/from the I2O controller
- *	@req: the request which should be transfered
+ *	@req: the request which should be transferred
  *
  *	This function converts the request into a I2O message. The necessary
  *	DMA buffers are allocated and after everything is setup post the message
@@ -895,11 +897,7 @@
 {
 	struct request *req;
 
-	while (!blk_queue_plugged(q)) {
-		req = blk_peek_request(q);
-		if (!req)
-			break;
-
+	while ((req = blk_peek_request(q)) != NULL) {
 		if (req->cmd_type == REQ_TYPE_FS) {
 			struct i2o_block_delayed_request *dreq;
 			struct i2o_block_request *ireq = req->special;
@@ -950,7 +948,7 @@
 	.ioctl = i2o_block_ioctl,
 	.compat_ioctl = i2o_block_ioctl,
 	.getgeo = i2o_block_getgeo,
-	.media_changed = i2o_block_media_changed
+	.check_events = i2o_block_check_events,
 };
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_block.h linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_block.h
--- linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_block.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_block.h	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
 	struct i2o_device *i2o_dev;	/* pointer to I2O device */
 	struct gendisk *gd;
 	spinlock_t lock;	/* queue lock */
-	struct list_head open_queue;	/* list of transfered, but unfinished
+	struct list_head open_queue;	/* list of transferred, but unfinished
 					   requests */
 	unsigned int open_queue_depth;	/* number of requests in the queue */
 
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_config.c linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_config.c
--- linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_config.c	2011-05-19 00:06:34.000000000 -0400
@@ -1044,8 +1044,7 @@
 
 static int cfg_open(struct inode *inode, struct file *file)
 {
-	struct i2o_cfg_info *tmp =
-	    (struct i2o_cfg_info *)kmalloc(sizeof(struct i2o_cfg_info),
+	struct i2o_cfg_info *tmp = kmalloc(sizeof(struct i2o_cfg_info),
 					   GFP_KERNEL);
 	unsigned long flags;
 
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_scsi.c linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_scsi.c
--- linux-libre-2.6.38-gnu/drivers/message/i2o/i2o_scsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/i2o_scsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -204,7 +204,7 @@
  *	i2o_scsi_probe - verify if dev is a I2O SCSI device and install it
  *	@dev: device to verify if it is a I2O SCSI device
  *
- *	Retrieve channel, id and lun for I2O device. If everthing goes well
+ *	Retrieve channel, id and lun for I2O device. If everything goes well
  *	register the I2O device as SCSI device on the I2O SCSI controller.
  *
  *	Returns 0 on success or negative error code on failure.
diff -druN linux-libre-2.6.38-gnu/drivers/message/i2o/README linux-libre-2.6.39-gnu/drivers/message/i2o/README
--- linux-libre-2.6.38-gnu/drivers/message/i2o/README	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/message/i2o/README	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 BoxHill Corporation
 	Loan of initial FibreChannel disk array used for development work.
 
-European Comission
+European Commission
 	Funding the work done by the University of Helsinki
 
 SysKonnect
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/88pm860x-core.c linux-libre-2.6.39-gnu/drivers/mfd/88pm860x-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/88pm860x-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/88pm860x-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,229 +17,137 @@
 #include <linux/platform_device.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
+#include <linux/regulator/machine.h>
 
 #define INT_STATUS_NUM			3
 
-char pm860x_backlight_name[][MFD_NAME_SIZE] = {
-	"backlight-0",
-	"backlight-1",
-	"backlight-2",
+static struct resource bk_resources[] __initdata = {
+	{PM8606_BACKLIGHT1, PM8606_BACKLIGHT1, "backlight-0", IORESOURCE_IO,},
+	{PM8606_BACKLIGHT2, PM8606_BACKLIGHT2, "backlight-1", IORESOURCE_IO,},
+	{PM8606_BACKLIGHT3, PM8606_BACKLIGHT3, "backlight-2", IORESOURCE_IO,},
 };
-EXPORT_SYMBOL(pm860x_backlight_name);
 
-char pm860x_led_name[][MFD_NAME_SIZE] = {
-	"led0-red",
-	"led0-green",
-	"led0-blue",
-	"led1-red",
-	"led1-green",
-	"led1-blue",
+static struct resource led_resources[] __initdata = {
+	{PM8606_LED1_RED,   PM8606_LED1_RED,   "led0-red",   IORESOURCE_IO,},
+	{PM8606_LED1_GREEN, PM8606_LED1_GREEN, "led0-green", IORESOURCE_IO,},
+	{PM8606_LED1_BLUE,  PM8606_LED1_BLUE,  "led0-blue",  IORESOURCE_IO,},
+	{PM8606_LED2_RED,   PM8606_LED2_RED,   "led1-red",   IORESOURCE_IO,},
+	{PM8606_LED2_GREEN, PM8606_LED2_GREEN, "led1-green", IORESOURCE_IO,},
+	{PM8606_LED2_BLUE,  PM8606_LED2_BLUE,  "led1-blue",  IORESOURCE_IO,},
 };
-EXPORT_SYMBOL(pm860x_led_name);
-
-#define PM8606_BACKLIGHT_RESOURCE(_i, _x)		\
-{							\
-	.name	= pm860x_backlight_name[_i],		\
-	.start	= PM8606_##_x,				\
-	.end	= PM8606_##_x,				\
-	.flags	= IORESOURCE_IO,			\
-}
 
-static struct resource backlight_resources[] = {
-	PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT1, WLED1A),
-	PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT2, WLED2A),
-	PM8606_BACKLIGHT_RESOURCE(PM8606_BACKLIGHT3, WLED3A),
+static struct resource regulator_resources[] __initdata = {
+	{PM8607_ID_BUCK1, PM8607_ID_BUCK1, "buck-1", IORESOURCE_IO,},
+	{PM8607_ID_BUCK2, PM8607_ID_BUCK2, "buck-2", IORESOURCE_IO,},
+	{PM8607_ID_BUCK3, PM8607_ID_BUCK3, "buck-3", IORESOURCE_IO,},
+	{PM8607_ID_LDO1,  PM8607_ID_LDO1,  "ldo-01", IORESOURCE_IO,},
+	{PM8607_ID_LDO2,  PM8607_ID_LDO2,  "ldo-02", IORESOURCE_IO,},
+	{PM8607_ID_LDO3,  PM8607_ID_LDO3,  "ldo-03", IORESOURCE_IO,},
+	{PM8607_ID_LDO4,  PM8607_ID_LDO4,  "ldo-04", IORESOURCE_IO,},
+	{PM8607_ID_LDO5,  PM8607_ID_LDO5,  "ldo-05", IORESOURCE_IO,},
+	{PM8607_ID_LDO6,  PM8607_ID_LDO6,  "ldo-06", IORESOURCE_IO,},
+	{PM8607_ID_LDO7,  PM8607_ID_LDO7,  "ldo-07", IORESOURCE_IO,},
+	{PM8607_ID_LDO8,  PM8607_ID_LDO8,  "ldo-08", IORESOURCE_IO,},
+	{PM8607_ID_LDO9,  PM8607_ID_LDO9,  "ldo-09", IORESOURCE_IO,},
+	{PM8607_ID_LDO10, PM8607_ID_LDO10, "ldo-10", IORESOURCE_IO,},
+	{PM8607_ID_LDO11, PM8607_ID_LDO11, "ldo-11", IORESOURCE_IO,},
+	{PM8607_ID_LDO12, PM8607_ID_LDO12, "ldo-12", IORESOURCE_IO,},
+	{PM8607_ID_LDO13, PM8607_ID_LDO13, "ldo-13", IORESOURCE_IO,},
+	{PM8607_ID_LDO14, PM8607_ID_LDO14, "ldo-14", IORESOURCE_IO,},
+	{PM8607_ID_LDO15, PM8607_ID_LDO15, "ldo-15", IORESOURCE_IO,},
 };
 
-#define PM8606_BACKLIGHT_DEVS(_i)			\
-{							\
-	.name		= "88pm860x-backlight",		\
-	.num_resources	= 1,				\
-	.resources	= &backlight_resources[_i],	\
-	.id		= _i,				\
-}
-
-static struct mfd_cell backlight_devs[] = {
-	PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT1),
-	PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT2),
-	PM8606_BACKLIGHT_DEVS(PM8606_BACKLIGHT3),
+static struct resource touch_resources[] __initdata = {
+	{PM8607_IRQ_PEN, PM8607_IRQ_PEN, "touch", IORESOURCE_IRQ,},
 };
 
-#define PM8606_LED_RESOURCE(_i, _x)			\
-{							\
-	.name	= pm860x_led_name[_i],			\
-	.start	= PM8606_##_x,				\
-	.end	= PM8606_##_x,				\
-	.flags	= IORESOURCE_IO,			\
-}
-
-static struct resource led_resources[] = {
-	PM8606_LED_RESOURCE(PM8606_LED1_RED, RGB1B),
-	PM8606_LED_RESOURCE(PM8606_LED1_GREEN, RGB1C),
-	PM8606_LED_RESOURCE(PM8606_LED1_BLUE, RGB1D),
-	PM8606_LED_RESOURCE(PM8606_LED2_RED, RGB2B),
-	PM8606_LED_RESOURCE(PM8606_LED2_GREEN, RGB2C),
-	PM8606_LED_RESOURCE(PM8606_LED2_BLUE, RGB2D),
+static struct resource onkey_resources[] __initdata = {
+	{PM8607_IRQ_ONKEY, PM8607_IRQ_ONKEY, "onkey", IORESOURCE_IRQ,},
 };
 
-#define PM8606_LED_DEVS(_i)				\
-{							\
-	.name		= "88pm860x-led",		\
-	.num_resources	= 1,				\
-	.resources	= &led_resources[_i],		\
-	.id		= _i,				\
-}
-
-static struct mfd_cell led_devs[] = {
-	PM8606_LED_DEVS(PM8606_LED1_RED),
-	PM8606_LED_DEVS(PM8606_LED1_GREEN),
-	PM8606_LED_DEVS(PM8606_LED1_BLUE),
-	PM8606_LED_DEVS(PM8606_LED2_RED),
-	PM8606_LED_DEVS(PM8606_LED2_GREEN),
-	PM8606_LED_DEVS(PM8606_LED2_BLUE),
+static struct resource codec_resources[] __initdata = {
+	/* Headset microphone insertion or removal */
+	{PM8607_IRQ_MICIN,   PM8607_IRQ_MICIN,   "micin",   IORESOURCE_IRQ,},
+	/* Hook-switch press or release */
+	{PM8607_IRQ_HOOK,    PM8607_IRQ_HOOK,    "hook",    IORESOURCE_IRQ,},
+	/* Headset insertion or removal */
+	{PM8607_IRQ_HEADSET, PM8607_IRQ_HEADSET, "headset", IORESOURCE_IRQ,},
+	/* Audio short */
+	{PM8607_IRQ_AUDIO_SHORT, PM8607_IRQ_AUDIO_SHORT, "audio-short", IORESOURCE_IRQ,},
 };
 
-static struct resource touch_resources[] = {
-	{
-		.start	= PM8607_IRQ_PEN,
-		.end	= PM8607_IRQ_PEN,
-		.flags	= IORESOURCE_IRQ,
-	},
+static struct resource battery_resources[] __initdata = {
+	{PM8607_IRQ_CC,  PM8607_IRQ_CC,  "columb counter", IORESOURCE_IRQ,},
+	{PM8607_IRQ_BAT, PM8607_IRQ_BAT, "battery",        IORESOURCE_IRQ,},
 };
 
-static struct mfd_cell touch_devs[] = {
-	{
-		.name		= "88pm860x-touch",
-		.num_resources	= 1,
-		.resources	= &touch_resources[0],
-	},
+static struct resource charger_resources[] __initdata = {
+	{PM8607_IRQ_CHG,  PM8607_IRQ_CHG,  "charger detect",  IORESOURCE_IRQ,},
+	{PM8607_IRQ_CHG_DONE,  PM8607_IRQ_CHG_DONE,  "charging done",       IORESOURCE_IRQ,},
+	{PM8607_IRQ_CHG_FAULT, PM8607_IRQ_CHG_FAULT, "charging timeout",    IORESOURCE_IRQ,},
+	{PM8607_IRQ_GPADC1,    PM8607_IRQ_GPADC1,    "battery temperature", IORESOURCE_IRQ,},
+	{PM8607_IRQ_VBAT, PM8607_IRQ_VBAT, "battery voltage", IORESOURCE_IRQ,},
+	{PM8607_IRQ_VCHG, PM8607_IRQ_VCHG, "vchg voltage",    IORESOURCE_IRQ,},
 };
 
-#define PM8607_REG_RESOURCE(_start, _end)		\
-{							\
-	.start	= PM8607_##_start,			\
-	.end	= PM8607_##_end,			\
-	.flags	= IORESOURCE_IO,			\
-}
-
-static struct resource power_supply_resources[] = {
-	{
-		.name		= "88pm860x-power",
-		.start		= PM8607_IRQ_CHG,
-		.end		= PM8607_IRQ_CHG,
-		.flags		= IORESOURCE_IRQ,
-	},
+static struct mfd_cell bk_devs[] __initdata = {
+	{"88pm860x-backlight", 0,},
+	{"88pm860x-backlight", 1,},
+	{"88pm860x-backlight", 2,},
 };
 
-static struct mfd_cell power_devs[] = {
-	{
-		.name		= "88pm860x-power",
-		.num_resources	= 1,
-		.resources	= &power_supply_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell led_devs[] __initdata = {
+	{"88pm860x-led", 0,},
+	{"88pm860x-led", 1,},
+	{"88pm860x-led", 2,},
+	{"88pm860x-led", 3,},
+	{"88pm860x-led", 4,},
+	{"88pm860x-led", 5,},
 };
 
-static struct resource onkey_resources[] = {
-	{
-		.name		= "88pm860x-onkey",
-		.start		= PM8607_IRQ_ONKEY,
-		.end		= PM8607_IRQ_ONKEY,
-		.flags		= IORESOURCE_IRQ,
-	},
+static struct mfd_cell regulator_devs[] __initdata = {
+	{"88pm860x-regulator", 0,},
+	{"88pm860x-regulator", 1,},
+	{"88pm860x-regulator", 2,},
+	{"88pm860x-regulator", 3,},
+	{"88pm860x-regulator", 4,},
+	{"88pm860x-regulator", 5,},
+	{"88pm860x-regulator", 6,},
+	{"88pm860x-regulator", 7,},
+	{"88pm860x-regulator", 8,},
+	{"88pm860x-regulator", 9,},
+	{"88pm860x-regulator", 10,},
+	{"88pm860x-regulator", 11,},
+	{"88pm860x-regulator", 12,},
+	{"88pm860x-regulator", 13,},
+	{"88pm860x-regulator", 14,},
+	{"88pm860x-regulator", 15,},
+	{"88pm860x-regulator", 16,},
+	{"88pm860x-regulator", 17,},
 };
 
-static struct mfd_cell onkey_devs[] = {
-	{
-		.name		= "88pm860x-onkey",
-		.num_resources	= 1,
-		.resources	= &onkey_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell touch_devs[] __initdata = {
+	{"88pm860x-touch", -1,},
 };
 
-static struct resource codec_resources[] = {
-	{
-		/* Headset microphone insertion or removal */
-		.name		= "micin",
-		.start		= PM8607_IRQ_MICIN,
-		.end		= PM8607_IRQ_MICIN,
-		.flags		= IORESOURCE_IRQ,
-	}, {
-		/* Hook-switch press or release */
-		.name		= "hook",
-		.start		= PM8607_IRQ_HOOK,
-		.end		= PM8607_IRQ_HOOK,
-		.flags		= IORESOURCE_IRQ,
-	}, {
-		/* Headset insertion or removal */
-		.name		= "headset",
-		.start		= PM8607_IRQ_HEADSET,
-		.end		= PM8607_IRQ_HEADSET,
-		.flags		= IORESOURCE_IRQ,
-	}, {
-		/* Audio short */
-		.name		= "audio-short",
-		.start		= PM8607_IRQ_AUDIO_SHORT,
-		.end		= PM8607_IRQ_AUDIO_SHORT,
-		.flags		= IORESOURCE_IRQ,
-	},
+static struct mfd_cell onkey_devs[] __initdata = {
+	{"88pm860x-onkey", -1,},
 };
 
-static struct mfd_cell codec_devs[] = {
-	{
-		.name		= "88pm860x-codec",
-		.num_resources	= ARRAY_SIZE(codec_resources),
-		.resources	= &codec_resources[0],
-		.id		= -1,
-	},
+static struct mfd_cell codec_devs[] __initdata = {
+	{"88pm860x-codec", -1,},
 };
 
-static struct resource regulator_resources[] = {
-	PM8607_REG_RESOURCE(BUCK1, BUCK1),
-	PM8607_REG_RESOURCE(BUCK2, BUCK2),
-	PM8607_REG_RESOURCE(BUCK3, BUCK3),
-	PM8607_REG_RESOURCE(LDO1,  LDO1),
-	PM8607_REG_RESOURCE(LDO2,  LDO2),
-	PM8607_REG_RESOURCE(LDO3,  LDO3),
-	PM8607_REG_RESOURCE(LDO4,  LDO4),
-	PM8607_REG_RESOURCE(LDO5,  LDO5),
-	PM8607_REG_RESOURCE(LDO6,  LDO6),
-	PM8607_REG_RESOURCE(LDO7,  LDO7),
-	PM8607_REG_RESOURCE(LDO8,  LDO8),
-	PM8607_REG_RESOURCE(LDO9,  LDO9),
-	PM8607_REG_RESOURCE(LDO10, LDO10),
-	PM8607_REG_RESOURCE(LDO12, LDO12),
-	PM8607_REG_RESOURCE(VIBRATOR_SET, VIBRATOR_SET),
-	PM8607_REG_RESOURCE(LDO14, LDO14),
+static struct mfd_cell power_devs[] = {
+	{"88pm860x-battery", -1,},
+	{"88pm860x-charger", -1,},
 };
 
-#define PM8607_REG_DEVS(_id)						\
-{									\
-	.name		= "88pm860x-regulator",				\
-	.num_resources	= 1,						\
-	.resources	= &regulator_resources[PM8607_ID_##_id],	\
-	.id		= PM8607_ID_##_id,				\
-}
-
-static struct mfd_cell regulator_devs[] = {
-	PM8607_REG_DEVS(BUCK1),
-	PM8607_REG_DEVS(BUCK2),
-	PM8607_REG_DEVS(BUCK3),
-	PM8607_REG_DEVS(LDO1),
-	PM8607_REG_DEVS(LDO2),
-	PM8607_REG_DEVS(LDO3),
-	PM8607_REG_DEVS(LDO4),
-	PM8607_REG_DEVS(LDO5),
-	PM8607_REG_DEVS(LDO6),
-	PM8607_REG_DEVS(LDO7),
-	PM8607_REG_DEVS(LDO8),
-	PM8607_REG_DEVS(LDO9),
-	PM8607_REG_DEVS(LDO10),
-	PM8607_REG_DEVS(LDO12),
-	PM8607_REG_DEVS(LDO13),
-	PM8607_REG_DEVS(LDO14),
-};
+static struct pm860x_backlight_pdata bk_pdata[ARRAY_SIZE(bk_devs)];
+static struct pm860x_led_pdata led_pdata[ARRAY_SIZE(led_devs)];
+static struct regulator_init_data regulator_pdata[ARRAY_SIZE(regulator_devs)];
+static struct pm860x_touch_pdata touch_pdata;
+static struct pm860x_power_pdata power_pdata;
 
 struct pm860x_irq_data {
 	int	reg;
@@ -508,7 +416,6 @@
 				: chip->companion;
 	unsigned char status_buf[INT_STATUS_NUM];
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-	struct irq_desc *desc;
 	int i, data, mask, ret = -EINVAL;
 	int __irq;
 
@@ -560,19 +467,17 @@
 	if (!chip->core_irq)
 		goto out;
 
-	desc = irq_to_desc(chip->core_irq);
-
 	/* register IRQ by genirq */
 	for (i = 0; i < ARRAY_SIZE(pm860x_irqs); i++) {
 		__irq = i + chip->irq_base;
-		set_irq_chip_data(__irq, chip);
-		set_irq_chip_and_handler(__irq, &pm860x_irq_chip,
+		irq_set_chip_data(__irq, chip);
+		irq_set_chip_and_handler(__irq, &pm860x_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(__irq, 1);
+		irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(__irq, IRQF_VALID);
 #else
-		set_irq_noprobe(__irq);
+		irq_set_noprobe(__irq);
 #endif
 	}
 
@@ -595,37 +500,212 @@
 		free_irq(chip->core_irq, chip);
 }
 
-static void __devinit device_8606_init(struct pm860x_chip *chip,
-				       struct i2c_client *i2c,
-				       struct pm860x_platform_data *pdata)
+static void __devinit device_bk_init(struct pm860x_chip *chip,
+				     struct i2c_client *i2c,
+				     struct pm860x_platform_data *pdata)
 {
 	int ret;
+	int i, j, id;
 
-	if (pdata && pdata->backlight) {
-		ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
-				      ARRAY_SIZE(backlight_devs),
-				      &backlight_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add backlight "
-				"subdev\n");
-			goto out_dev;
+	if ((pdata == NULL) || (pdata->backlight == NULL))
+		return;
+
+	if (pdata->num_backlights > ARRAY_SIZE(bk_devs))
+		pdata->num_backlights = ARRAY_SIZE(bk_devs);
+
+	for (i = 0; i < pdata->num_backlights; i++) {
+		memcpy(&bk_pdata[i], &pdata->backlight[i],
+			sizeof(struct pm860x_backlight_pdata));
+		bk_devs[i].mfd_data = &bk_pdata[i];
+
+		for (j = 0; j < ARRAY_SIZE(bk_devs); j++) {
+			id = bk_resources[j].start;
+			if (bk_pdata[i].flags != id)
+				continue;
+
+			bk_devs[i].num_resources = 1;
+			bk_devs[i].resources = &bk_resources[j];
+			ret = mfd_add_devices(chip->dev, 0,
+					      &bk_devs[i], 1,
+					      &bk_resources[j], 0);
+			if (ret < 0) {
+				dev_err(chip->dev, "Failed to add "
+					"backlight subdev\n");
+				return;
+			}
 		}
 	}
+}
 
-	if (pdata && pdata->led) {
-		ret = mfd_add_devices(chip->dev, 0, &led_devs[0],
-				      ARRAY_SIZE(led_devs),
-				      &led_resources[0], 0);
+static void __devinit device_led_init(struct pm860x_chip *chip,
+				      struct i2c_client *i2c,
+				      struct pm860x_platform_data *pdata)
+{
+	int ret;
+	int i, j, id;
+
+	if ((pdata == NULL) || (pdata->led == NULL))
+		return;
+
+	if (pdata->num_leds > ARRAY_SIZE(led_devs))
+		pdata->num_leds = ARRAY_SIZE(led_devs);
+
+	for (i = 0; i < pdata->num_leds; i++) {
+		memcpy(&led_pdata[i], &pdata->led[i],
+			sizeof(struct pm860x_led_pdata));
+		led_devs[i].mfd_data = &led_pdata[i];
+
+		for (j = 0; j < ARRAY_SIZE(led_devs); j++) {
+			id = led_resources[j].start;
+			if (led_pdata[i].flags != id)
+				continue;
+
+			led_devs[i].num_resources = 1;
+			led_devs[i].resources = &led_resources[j],
+			ret = mfd_add_devices(chip->dev, 0,
+					      &led_devs[i], 1,
+					      &led_resources[j], 0);
+			if (ret < 0) {
+				dev_err(chip->dev, "Failed to add "
+					"led subdev\n");
+				return;
+			}
+		}
+	}
+}
+
+static void __devinit device_regulator_init(struct pm860x_chip *chip,
+					    struct i2c_client *i2c,
+					    struct pm860x_platform_data *pdata)
+{
+	struct regulator_init_data *initdata;
+	int ret;
+	int i, j;
+
+	if ((pdata == NULL) || (pdata->regulator == NULL))
+		return;
+
+	if (pdata->num_regulators > ARRAY_SIZE(regulator_devs))
+		pdata->num_regulators = ARRAY_SIZE(regulator_devs);
+
+	for (i = 0, j = -1; i < pdata->num_regulators; i++) {
+		initdata = &pdata->regulator[i];
+		if (strstr(initdata->constraints.name, "BUCK")) {
+			sscanf(initdata->constraints.name, "BUCK%d", &j);
+			/* BUCK1 ~ BUCK3 */
+			if ((j < 1) || (j > 3)) {
+				dev_err(chip->dev, "Failed to add constraint "
+					"(%s)\n", initdata->constraints.name);
+				goto out;
+			}
+			j = (j - 1) + PM8607_ID_BUCK1;
+		}
+		if (strstr(initdata->constraints.name, "LDO")) {
+			sscanf(initdata->constraints.name, "LDO%d", &j);
+			/* LDO1 ~ LDO15 */
+			if ((j < 1) || (j > 15)) {
+				dev_err(chip->dev, "Failed to add constraint "
+					"(%s)\n", initdata->constraints.name);
+				goto out;
+			}
+			j = (j - 1) + PM8607_ID_LDO1;
+		}
+		if (j == -1) {
+			dev_err(chip->dev, "Failed to add constraint (%s)\n",
+				initdata->constraints.name);
+			goto out;
+		}
+		memcpy(&regulator_pdata[i], &pdata->regulator[i],
+			sizeof(struct regulator_init_data));
+		regulator_devs[i].mfd_data = &regulator_pdata[i];
+		regulator_devs[i].num_resources = 1;
+		regulator_devs[i].resources = &regulator_resources[j];
+
+		ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
+				      &regulator_resources[j], 0);
 		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add led "
-				"subdev\n");
-			goto out_dev;
+			dev_err(chip->dev, "Failed to add regulator subdev\n");
+			goto out;
 		}
 	}
+out:
 	return;
-out_dev:
-	mfd_remove_devices(chip->dev);
-	device_irq_exit(chip);
+}
+
+static void __devinit device_touch_init(struct pm860x_chip *chip,
+					struct i2c_client *i2c,
+					struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->touch == NULL))
+		return;
+
+	memcpy(&touch_pdata, pdata->touch, sizeof(struct pm860x_touch_pdata));
+	touch_devs[0].mfd_data = &touch_pdata;
+	touch_devs[0].num_resources = ARRAY_SIZE(touch_resources);
+	touch_devs[0].resources = &touch_resources[0];
+	ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
+			      ARRAY_SIZE(touch_devs), &touch_resources[0],
+			      chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add touch subdev\n");
+}
+
+static void __devinit device_power_init(struct pm860x_chip *chip,
+					struct i2c_client *i2c,
+					struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	if ((pdata == NULL) || (pdata->power == NULL))
+		return;
+
+	memcpy(&power_pdata, pdata->power, sizeof(struct pm860x_power_pdata));
+	power_devs[0].mfd_data = &power_pdata;
+	power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
+	power_devs[0].resources = &battery_resources[0],
+	ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
+			      &battery_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add battery subdev\n");
+
+	power_devs[1].mfd_data = &power_pdata;
+	power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
+	power_devs[1].resources = &charger_resources[0],
+	ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
+			      &charger_resources[0], chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add charger subdev\n");
+}
+
+static void __devinit device_onkey_init(struct pm860x_chip *chip,
+					struct i2c_client *i2c,
+					struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	onkey_devs[0].num_resources = ARRAY_SIZE(onkey_resources);
+	onkey_devs[0].resources = &onkey_resources[0],
+	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
+			      ARRAY_SIZE(onkey_devs), &onkey_resources[0],
+			      chip->irq_base);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add onkey subdev\n");
+}
+
+static void __devinit device_codec_init(struct pm860x_chip *chip,
+					struct i2c_client *i2c,
+					struct pm860x_platform_data *pdata)
+{
+	int ret;
+
+	codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);
+	codec_devs[0].resources = &codec_resources[0],
+	ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
+			      ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
+	if (ret < 0)
+		dev_err(chip->dev, "Failed to add codec subdev\n");
 }
 
 static void __devinit device_8607_init(struct pm860x_chip *chip,
@@ -683,55 +763,11 @@
 	if (ret < 0)
 		goto out;
 
-	ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
-			      ARRAY_SIZE(regulator_devs),
-			      &regulator_resources[0], 0);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to add regulator subdev\n");
-		goto out_dev;
-	}
-
-	if (pdata && pdata->touch) {
-		ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
-				      ARRAY_SIZE(touch_devs),
-				      &touch_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add touch "
-				"subdev\n");
-			goto out_dev;
-		}
-	}
-
-	if (pdata && pdata->power) {
-		ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
-				      ARRAY_SIZE(power_devs),
-				      &power_supply_resources[0], 0);
-		if (ret < 0) {
-			dev_err(chip->dev, "Failed to add power supply "
-				"subdev\n");
-			goto out_dev;
-		}
-	}
-
-	ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
-			      ARRAY_SIZE(onkey_devs),
-			      &onkey_resources[0], 0);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to add onkey subdev\n");
-		goto out_dev;
-	}
-
-	ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
-			      ARRAY_SIZE(codec_devs),
-			      &codec_resources[0], 0);
-	if (ret < 0) {
-		dev_err(chip->dev, "Failed to add codec subdev\n");
-		goto out_dev;
-	}
-	return;
-out_dev:
-	mfd_remove_devices(chip->dev);
-	device_irq_exit(chip);
+	device_regulator_init(chip, i2c, pdata);
+	device_onkey_init(chip, i2c, pdata);
+	device_touch_init(chip, i2c, pdata);
+	device_power_init(chip, i2c, pdata);
+	device_codec_init(chip, i2c, pdata);
 out:
 	return;
 }
@@ -743,7 +779,8 @@
 
 	switch (chip->id) {
 	case CHIP_PM8606:
-		device_8606_init(chip, chip->client, pdata);
+		device_bk_init(chip, chip->client, pdata);
+		device_led_init(chip, chip->client, pdata);
 		break;
 	case CHIP_PM8607:
 		device_8607_init(chip, chip->client, pdata);
@@ -753,7 +790,8 @@
 	if (chip->companion) {
 		switch (chip->id) {
 		case CHIP_PM8607:
-			device_8606_init(chip, chip->companion, pdata);
+			device_bk_init(chip, chip->companion, pdata);
+			device_led_init(chip, chip->companion, pdata);
 			break;
 		case CHIP_PM8606:
 			device_8607_init(chip, chip->companion, pdata);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/88pm860x-i2c.c linux-libre-2.6.39-gnu/drivers/mfd/88pm860x-i2c.c
--- linux-libre-2.6.38-gnu/drivers/mfd/88pm860x-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/88pm860x-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -126,6 +126,109 @@
 }
 EXPORT_SYMBOL(pm860x_set_bits);
 
+int pm860x_page_reg_read(struct i2c_client *i2c, int reg)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char zero = 0;
+	unsigned char data;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	pm860x_write_device(i2c, 0xFA, 0, &zero);
+	pm860x_write_device(i2c, 0xFB, 0, &zero);
+	pm860x_write_device(i2c, 0xFF, 0, &zero);
+	ret = pm860x_read_device(i2c, reg, 1, &data);
+	if (ret >= 0)
+		ret = (int)data;
+	pm860x_write_device(i2c, 0xFE, 0, &zero);
+	pm860x_write_device(i2c, 0xFC, 0, &zero);
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_page_reg_read);
+
+int pm860x_page_reg_write(struct i2c_client *i2c, int reg,
+			  unsigned char data)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char zero;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	pm860x_write_device(i2c, 0xFA, 0, &zero);
+	pm860x_write_device(i2c, 0xFB, 0, &zero);
+	pm860x_write_device(i2c, 0xFF, 0, &zero);
+	ret = pm860x_write_device(i2c, reg, 1, &data);
+	pm860x_write_device(i2c, 0xFE, 0, &zero);
+	pm860x_write_device(i2c, 0xFC, 0, &zero);
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_page_reg_write);
+
+int pm860x_page_bulk_read(struct i2c_client *i2c, int reg,
+			  int count, unsigned char *buf)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char zero = 0;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	pm860x_write_device(i2c, 0xFA, 0, &zero);
+	pm860x_write_device(i2c, 0xFB, 0, &zero);
+	pm860x_write_device(i2c, 0xFF, 0, &zero);
+	ret = pm860x_read_device(i2c, reg, count, buf);
+	pm860x_write_device(i2c, 0xFE, 0, &zero);
+	pm860x_write_device(i2c, 0xFC, 0, &zero);
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_page_bulk_read);
+
+int pm860x_page_bulk_write(struct i2c_client *i2c, int reg,
+			   int count, unsigned char *buf)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char zero = 0;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	pm860x_write_device(i2c, 0xFA, 0, &zero);
+	pm860x_write_device(i2c, 0xFB, 0, &zero);
+	pm860x_write_device(i2c, 0xFF, 0, &zero);
+	ret = pm860x_write_device(i2c, reg, count, buf);
+	pm860x_write_device(i2c, 0xFE, 0, &zero);
+	pm860x_write_device(i2c, 0xFC, 0, &zero);
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_page_bulk_write);
+
+int pm860x_page_set_bits(struct i2c_client *i2c, int reg,
+			 unsigned char mask, unsigned char data)
+{
+	struct pm860x_chip *chip = i2c_get_clientdata(i2c);
+	unsigned char zero;
+	unsigned char value;
+	int ret;
+
+	mutex_lock(&chip->io_lock);
+	pm860x_write_device(i2c, 0xFA, 0, &zero);
+	pm860x_write_device(i2c, 0xFB, 0, &zero);
+	pm860x_write_device(i2c, 0xFF, 0, &zero);
+	ret = pm860x_read_device(i2c, reg, 1, &value);
+	if (ret < 0)
+		goto out;
+	value &= ~mask;
+	value |= data;
+	ret = pm860x_write_device(i2c, reg, 1, &value);
+out:
+	pm860x_write_device(i2c, 0xFE, 0, &zero);
+	pm860x_write_device(i2c, 0xFC, 0, &zero);
+	mutex_unlock(&chip->io_lock);
+	return ret;
+}
+EXPORT_SYMBOL(pm860x_page_set_bits);
 
 static const struct i2c_device_id pm860x_id_table[] = {
 	{ "88PM860x", 0 },
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab3100-core.c linux-libre-2.6.39-gnu/drivers/mfd/ab3100-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab3100-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab3100-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -613,7 +613,7 @@
 	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,
+				S_IWUSR, ab3100_dir, &ab3100_get_priv,
 				&ab3100_get_set_reg_fops);
 	if (!ab3100_get_reg_file) {
 		err = -ENOMEM;
@@ -623,7 +623,7 @@
 	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,
+				S_IWUSR, ab3100_dir, &ab3100_set_priv,
 				&ab3100_get_set_reg_fops);
 	if (!ab3100_set_reg_file) {
 		err = -ENOMEM;
@@ -949,10 +949,8 @@
 		goto exit_no_ops;
 
 	/* Set up and register the platform devices. */
-	for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) {
-		ab3100_devs[i].platform_data = ab3100_plf_data;
-		ab3100_devs[i].data_size = sizeof(struct ab3100_platform_data);
-	}
+	for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++)
+		ab3100_devs[i].mfd_data = ab3100_plf_data;
 
 	err = mfd_add_devices(&client->dev, 0, ab3100_devs,
 		ARRAY_SIZE(ab3100_devs), NULL, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab3550-core.c linux-libre-2.6.39-gnu/drivers/mfd/ab3550-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab3550-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab3550-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -668,7 +668,7 @@
 	struct ab3550_platform_data *plf_data;
 	bool val;
 
-	ab = get_irq_chip_data(irq);
+	ab = irq_get_chip_data(irq);
 	plf_data = ab->i2c_client[0]->dev.platform_data;
 	irq -= plf_data->irq.base;
 	val = ((ab->startup_events[irq / 8] & BIT(irq % 8)) != 0);
@@ -1053,17 +1053,17 @@
 		goto exit_destroy_dir;
 
 	ab3550_bank_file = debugfs_create_file("register-bank",
-		(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_bank_fops);
+		(S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_bank_fops);
 	if (!ab3550_bank_file)
 		goto exit_destroy_reg;
 
 	ab3550_address_file = debugfs_create_file("register-address",
-		(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_address_fops);
+		(S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_address_fops);
 	if (!ab3550_address_file)
 		goto exit_destroy_bank;
 
 	ab3550_val_file = debugfs_create_file("register-value",
-		(S_IRUGO | S_IWUGO), ab3550_dir, ab, &ab3550_val_fops);
+		(S_IRUGO | S_IWUSR), ab3550_dir, ab, &ab3550_val_fops);
 	if (!ab3550_val_file)
 		goto exit_destroy_address;
 
@@ -1296,14 +1296,14 @@
 		unsigned int irq;
 
 		irq = ab3550_plf_data->irq.base + i;
-		set_irq_chip_data(irq, ab);
-		set_irq_chip_and_handler(irq, &ab3550_irq_chip,
-			handle_simple_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_chip_data(irq, ab);
+		irq_set_chip_and_handler(irq, &ab3550_irq_chip,
+					 handle_simple_irq);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -1320,10 +1320,8 @@
 		goto exit_no_ops;
 
 	/* Set up and register the platform devices. */
-	for (i = 0; i < AB3550_NUM_DEVICES; i++) {
-		ab3550_devs[i].platform_data = ab3550_plf_data->dev_data[i];
-		ab3550_devs[i].data_size = ab3550_plf_data->dev_data_sz[i];
-	}
+	for (i = 0; i < AB3550_NUM_DEVICES; i++)
+		ab3550_devs[i].mfd_data = ab3550_plf_data->dev_data[i];
 
 	err = mfd_add_devices(&client->dev, 0, ab3550_devs,
 		ARRAY_SIZE(ab3550_devs), NULL,
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab8500-core.c linux-libre-2.6.39-gnu/drivers/mfd/ab8500-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab8500-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab8500-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * License Terms: GNU General Public License v2
  * Author: Srinidhi Kasagar <srinidhi.kasagar@stericsson.com>
  * Author: Rabin Vincent <rabin.vincent@stericsson.com>
- * Changes: Mattias Wallin <mattias.wallin@stericsson.com>
+ * Author: Mattias Wallin <mattias.wallin@stericsson.com>
  */
 
 #include <linux/kernel.h>
@@ -90,6 +90,7 @@
 #define AB8500_IT_MASK24_REG		0x57
 
 #define AB8500_REV_REG			0x80
+#define AB8500_SWITCH_OFF_STATUS	0x00
 
 /*
  * Map interrupt numbers to the LATCH and MASK register offsets, Interrupt
@@ -333,14 +334,14 @@
 	int irq;
 
 	for (irq = base; irq < base + AB8500_NR_IRQS; irq++) {
-		set_irq_chip_data(irq, ab8500);
-		set_irq_chip_and_handler(irq, &ab8500_irq_chip,
+		irq_set_chip_data(irq, ab8500);
+		irq_set_chip_and_handler(irq, &ab8500_irq_chip,
 					 handle_simple_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -356,11 +357,20 @@
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
+static struct resource ab8500_gpio_resources[] = {
+	{
+		.name	= "GPIO_INT6",
+		.start	= AB8500_INT_GPIO6R,
+		.end	= AB8500_INT_GPIO41F,
+		.flags	= IORESOURCE_IRQ,
+	}
+};
+
 static struct resource ab8500_gpadc_resources[] = {
 	{
 		.name	= "HW_CONV_END",
@@ -595,6 +605,11 @@
 		.name = "ab8500-regulator",
 	},
 	{
+		.name = "ab8500-gpio",
+		.num_resources = ARRAY_SIZE(ab8500_gpio_resources),
+		.resources = ab8500_gpio_resources,
+	},
+	{
 		.name = "ab8500-gpadc",
 		.num_resources = ARRAY_SIZE(ab8500_gpadc_resources),
 		.resources = ab8500_gpadc_resources,
@@ -652,10 +667,38 @@
 	return sprintf(buf, "%#x\n", ab8500 ? ab8500->chip_id : -EINVAL);
 }
 
+/*
+ * ab8500 has switched off due to (SWITCH_OFF_STATUS):
+ * 0x01 Swoff bit programming
+ * 0x02 Thermal protection activation
+ * 0x04 Vbat lower then BattOk falling threshold
+ * 0x08 Watchdog expired
+ * 0x10 Non presence of 32kHz clock
+ * 0x20 Battery level lower than power on reset threshold
+ * 0x40 Power on key 1 pressed longer than 10 seconds
+ * 0x80 DB8500 thermal shutdown
+ */
+static ssize_t show_switch_off_status(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int ret;
+	u8 value;
+	struct ab8500 *ab8500;
+
+	ab8500 = dev_get_drvdata(dev);
+	ret = get_register_interruptible(ab8500, AB8500_RTC,
+		AB8500_SWITCH_OFF_STATUS, &value);
+	if (ret < 0)
+		return ret;
+	return sprintf(buf, "%#x\n", value);
+}
+
 static DEVICE_ATTR(chip_id, S_IRUGO, show_chip_id, NULL);
+static DEVICE_ATTR(switch_off_status, S_IRUGO, show_switch_off_status, NULL);
 
 static struct attribute *ab8500_sysfs_entries[] = {
 	&dev_attr_chip_id.attr,
+	&dev_attr_switch_off_status.attr,
 	NULL,
 };
 
@@ -686,9 +729,10 @@
 	 * 0x10 - Cut 1.0
 	 * 0x11 - Cut 1.1
 	 * 0x20 - Cut 2.0
+	 * 0x30 - Cut 3.0
 	 */
-	if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20) {
-		ab8500->revision = value;
+	if (value == 0x0 || value == 0x10 || value == 0x11 || value == 0x20 ||
+		value == 0x30) {
 		dev_info(ab8500->dev, "detected chip, revision: %#x\n", value);
 	} else {
 		dev_err(ab8500->dev, "unknown chip, revision: %#x\n", value);
@@ -696,6 +740,24 @@
 	}
 	ab8500->chip_id = value;
 
+	/*
+	 * ab8500 has switched off due to (SWITCH_OFF_STATUS):
+	 * 0x01 Swoff bit programming
+	 * 0x02 Thermal protection activation
+	 * 0x04 Vbat lower then BattOk falling threshold
+	 * 0x08 Watchdog expired
+	 * 0x10 Non presence of 32kHz clock
+	 * 0x20 Battery level lower than power on reset threshold
+	 * 0x40 Power on key 1 pressed longer than 10 seconds
+	 * 0x80 DB8500 thermal shutdown
+	 */
+
+	ret = get_register_interruptible(ab8500, AB8500_RTC,
+		AB8500_SWITCH_OFF_STATUS, &value);
+	if (ret < 0)
+		return ret;
+	dev_info(ab8500->dev, "switch off status: %#x", value);
+
 	if (plat && plat->init)
 		plat->init(ab8500);
 
@@ -764,6 +826,6 @@
 	return 0;
 }
 
-MODULE_AUTHOR("Srinidhi Kasagar, Rabin Vincent");
+MODULE_AUTHOR("Mattias Wallin, Srinidhi Kasagar, Rabin Vincent");
 MODULE_DESCRIPTION("AB8500 MFD core");
 MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab8500-debugfs.c linux-libre-2.6.39-gnu/drivers/mfd/ab8500-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab8500-debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab8500-debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -585,18 +585,18 @@
 		goto exit_destroy_dir;
 
 	ab8500_bank_file = debugfs_create_file("register-bank",
-		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_bank_fops);
+		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_bank_fops);
 	if (!ab8500_bank_file)
 		goto exit_destroy_reg;
 
 	ab8500_address_file = debugfs_create_file("register-address",
-		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev,
+		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev,
 		&ab8500_address_fops);
 	if (!ab8500_address_file)
 		goto exit_destroy_bank;
 
 	ab8500_val_file = debugfs_create_file("register-value",
-		(S_IRUGO | S_IWUGO), ab8500_dir, &plf->dev, &ab8500_val_fops);
+		(S_IRUGO | S_IWUSR), ab8500_dir, &plf->dev, &ab8500_val_fops);
 	if (!ab8500_val_file)
 		goto exit_destroy_address;
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab8500-gpadc.c linux-libre-2.6.39-gnu/drivers/mfd/ab8500-gpadc.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab8500-gpadc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab8500-gpadc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,614 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Arun R Murthy <arun.murthy@stericsson.com>
+ * Author: Daniel Willerud <daniel.willerud@stericsson.com>
+ * Author: Johan Palsson <johan.palsson@stericsson.com>
+ */
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/spinlock.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/completion.h>
+#include <linux/regulator/consumer.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/list.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500/gpadc.h>
+
+/*
+ * GPADC register offsets
+ * Bank : 0x0A
+ */
+#define AB8500_GPADC_CTRL1_REG		0x00
+#define AB8500_GPADC_CTRL2_REG		0x01
+#define AB8500_GPADC_CTRL3_REG		0x02
+#define AB8500_GPADC_AUTO_TIMER_REG	0x03
+#define AB8500_GPADC_STAT_REG		0x04
+#define AB8500_GPADC_MANDATAL_REG	0x05
+#define AB8500_GPADC_MANDATAH_REG	0x06
+#define AB8500_GPADC_AUTODATAL_REG	0x07
+#define AB8500_GPADC_AUTODATAH_REG	0x08
+#define AB8500_GPADC_MUX_CTRL_REG	0x09
+
+/*
+ * OTP register offsets
+ * Bank : 0x15
+ */
+#define AB8500_GPADC_CAL_1		0x0F
+#define AB8500_GPADC_CAL_2		0x10
+#define AB8500_GPADC_CAL_3		0x11
+#define AB8500_GPADC_CAL_4		0x12
+#define AB8500_GPADC_CAL_5		0x13
+#define AB8500_GPADC_CAL_6		0x14
+#define AB8500_GPADC_CAL_7		0x15
+
+/* gpadc constants */
+#define EN_VINTCORE12			0x04
+#define EN_VTVOUT			0x02
+#define EN_GPADC			0x01
+#define DIS_GPADC			0x00
+#define SW_AVG_16			0x60
+#define ADC_SW_CONV			0x04
+#define EN_ICHAR			0x80
+#define EN_BUF				0x40
+#define DIS_ZERO			0x00
+#define GPADC_BUSY			0x01
+
+/* GPADC constants from AB8500 spec, UM0836 */
+#define ADC_RESOLUTION			1024
+#define ADC_CH_BTEMP_MIN		0
+#define ADC_CH_BTEMP_MAX		1350
+#define ADC_CH_DIETEMP_MIN		0
+#define ADC_CH_DIETEMP_MAX		1350
+#define ADC_CH_CHG_V_MIN		0
+#define ADC_CH_CHG_V_MAX		20030
+#define ADC_CH_ACCDET2_MIN		0
+#define ADC_CH_ACCDET2_MAX		2500
+#define ADC_CH_VBAT_MIN			2300
+#define ADC_CH_VBAT_MAX			4800
+#define ADC_CH_CHG_I_MIN		0
+#define ADC_CH_CHG_I_MAX		1500
+#define ADC_CH_BKBAT_MIN		0
+#define ADC_CH_BKBAT_MAX		3200
+
+/* This is used to not lose precision when dividing to get gain and offset */
+#define CALIB_SCALE			1000
+
+enum cal_channels {
+	ADC_INPUT_VMAIN = 0,
+	ADC_INPUT_BTEMP,
+	ADC_INPUT_VBAT,
+	NBR_CAL_INPUTS,
+};
+
+/**
+ * struct adc_cal_data - Table for storing gain and offset for the calibrated
+ * ADC channels
+ * @gain:		Gain of the ADC channel
+ * @offset:		Offset of the ADC channel
+ */
+struct adc_cal_data {
+	u64 gain;
+	u64 offset;
+};
+
+/**
+ * struct ab8500_gpadc - AB8500 GPADC device information
+ * @dev:			pointer to the struct device
+ * @node:			a list of AB8500 GPADCs, hence prepared for
+				reentrance
+ * @ab8500_gpadc_complete:	pointer to the struct completion, to indicate
+ *				the completion of gpadc conversion
+ * @ab8500_gpadc_lock:		structure of type mutex
+ * @regu:			pointer to the struct regulator
+ * @irq:			interrupt number that is used by gpadc
+ * @cal_data			array of ADC calibration data structs
+ */
+struct ab8500_gpadc {
+	struct device *dev;
+	struct list_head node;
+	struct completion ab8500_gpadc_complete;
+	struct mutex ab8500_gpadc_lock;
+	struct regulator *regu;
+	int irq;
+	struct adc_cal_data cal_data[NBR_CAL_INPUTS];
+};
+
+static LIST_HEAD(ab8500_gpadc_list);
+
+/**
+ * ab8500_gpadc_get() - returns a reference to the primary AB8500 GPADC
+ * (i.e. the first GPADC in the instance list)
+ */
+struct ab8500_gpadc *ab8500_gpadc_get(char *name)
+{
+	struct ab8500_gpadc *gpadc;
+
+	list_for_each_entry(gpadc, &ab8500_gpadc_list, node) {
+		if (!strcmp(name, dev_name(gpadc->dev)))
+		    return gpadc;
+	}
+
+	return ERR_PTR(-ENOENT);
+}
+EXPORT_SYMBOL(ab8500_gpadc_get);
+
+static int ab8500_gpadc_ad_to_voltage(struct ab8500_gpadc *gpadc, u8 input,
+	int ad_value)
+{
+	int res;
+
+	switch (input) {
+	case MAIN_CHARGER_V:
+		/* For some reason we don't have calibrated data */
+		if (!gpadc->cal_data[ADC_INPUT_VMAIN].gain) {
+			res = ADC_CH_CHG_V_MIN + (ADC_CH_CHG_V_MAX -
+				ADC_CH_CHG_V_MIN) * ad_value /
+				ADC_RESOLUTION;
+			break;
+		}
+		/* Here we can use the calibrated data */
+		res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VMAIN].gain +
+			gpadc->cal_data[ADC_INPUT_VMAIN].offset) / CALIB_SCALE;
+		break;
+
+	case BAT_CTRL:
+	case BTEMP_BALL:
+	case ACC_DETECT1:
+	case ADC_AUX1:
+	case ADC_AUX2:
+		/* For some reason we don't have calibrated data */
+		if (!gpadc->cal_data[ADC_INPUT_BTEMP].gain) {
+			res = ADC_CH_BTEMP_MIN + (ADC_CH_BTEMP_MAX -
+				ADC_CH_BTEMP_MIN) * ad_value /
+				ADC_RESOLUTION;
+			break;
+		}
+		/* Here we can use the calibrated data */
+		res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_BTEMP].gain +
+			gpadc->cal_data[ADC_INPUT_BTEMP].offset) / CALIB_SCALE;
+		break;
+
+	case MAIN_BAT_V:
+		/* For some reason we don't have calibrated data */
+		if (!gpadc->cal_data[ADC_INPUT_VBAT].gain) {
+			res = ADC_CH_VBAT_MIN + (ADC_CH_VBAT_MAX -
+				ADC_CH_VBAT_MIN) * ad_value /
+				ADC_RESOLUTION;
+			break;
+		}
+		/* Here we can use the calibrated data */
+		res = (int) (ad_value * gpadc->cal_data[ADC_INPUT_VBAT].gain +
+			gpadc->cal_data[ADC_INPUT_VBAT].offset) / CALIB_SCALE;
+		break;
+
+	case DIE_TEMP:
+		res = ADC_CH_DIETEMP_MIN +
+			(ADC_CH_DIETEMP_MAX - ADC_CH_DIETEMP_MIN) * ad_value /
+			ADC_RESOLUTION;
+		break;
+
+	case ACC_DETECT2:
+		res = ADC_CH_ACCDET2_MIN +
+			(ADC_CH_ACCDET2_MAX - ADC_CH_ACCDET2_MIN) * ad_value /
+			ADC_RESOLUTION;
+		break;
+
+	case VBUS_V:
+		res = ADC_CH_CHG_V_MIN +
+			(ADC_CH_CHG_V_MAX - ADC_CH_CHG_V_MIN) * ad_value /
+			ADC_RESOLUTION;
+		break;
+
+	case MAIN_CHARGER_C:
+	case USB_CHARGER_C:
+		res = ADC_CH_CHG_I_MIN +
+			(ADC_CH_CHG_I_MAX - ADC_CH_CHG_I_MIN) * ad_value /
+			ADC_RESOLUTION;
+		break;
+
+	case BK_BAT_V:
+		res = ADC_CH_BKBAT_MIN +
+			(ADC_CH_BKBAT_MAX - ADC_CH_BKBAT_MIN) * ad_value /
+			ADC_RESOLUTION;
+		break;
+
+	default:
+		dev_err(gpadc->dev,
+			"unknown channel, not possible to convert\n");
+		res = -EINVAL;
+		break;
+
+	}
+	return res;
+}
+
+/**
+ * ab8500_gpadc_convert() - gpadc conversion
+ * @input:	analog input to be converted to digital data
+ *
+ * This function converts the selected analog i/p to digital
+ * data.
+ */
+int ab8500_gpadc_convert(struct ab8500_gpadc *gpadc, u8 input)
+{
+	int ret;
+	u16 data = 0;
+	int looplimit = 0;
+	u8 val, low_data, high_data;
+
+	if (!gpadc)
+		return -ENODEV;
+
+	mutex_lock(&gpadc->ab8500_gpadc_lock);
+	/* Enable VTVout LDO this is required for GPADC */
+	regulator_enable(gpadc->regu);
+
+	/* Check if ADC is not busy, lock and proceed */
+	do {
+		ret = abx500_get_register_interruptible(gpadc->dev,
+			AB8500_GPADC, AB8500_GPADC_STAT_REG, &val);
+		if (ret < 0)
+			goto out;
+		if (!(val & GPADC_BUSY))
+			break;
+		msleep(10);
+	} while (++looplimit < 10);
+	if (looplimit >= 10 && (val & GPADC_BUSY)) {
+		dev_err(gpadc->dev, "gpadc_conversion: GPADC busy");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Enable GPADC */
+	ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
+		AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_GPADC, EN_GPADC);
+	if (ret < 0) {
+		dev_err(gpadc->dev, "gpadc_conversion: enable gpadc failed\n");
+		goto out;
+	}
+	/* Select the input source and set average samples to 16 */
+	ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
+		AB8500_GPADC_CTRL2_REG, (input | SW_AVG_16));
+	if (ret < 0) {
+		dev_err(gpadc->dev,
+			"gpadc_conversion: set avg samples failed\n");
+		goto out;
+	}
+	/*
+	 * Enable ADC, buffering, select rising edge and enable ADC path
+	 * charging current sense if it needed
+	 */
+	switch (input) {
+	case MAIN_CHARGER_C:
+	case USB_CHARGER_C:
+		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
+			AB8500_GPADC, AB8500_GPADC_CTRL1_REG,
+			EN_BUF | EN_ICHAR,
+			EN_BUF | EN_ICHAR);
+		break;
+	default:
+		ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
+			AB8500_GPADC, AB8500_GPADC_CTRL1_REG, EN_BUF, EN_BUF);
+		break;
+	}
+	if (ret < 0) {
+		dev_err(gpadc->dev,
+			"gpadc_conversion: select falling edge failed\n");
+		goto out;
+	}
+	ret = abx500_mask_and_set_register_interruptible(gpadc->dev,
+		AB8500_GPADC, AB8500_GPADC_CTRL1_REG, ADC_SW_CONV, ADC_SW_CONV);
+	if (ret < 0) {
+		dev_err(gpadc->dev,
+			"gpadc_conversion: start s/w conversion failed\n");
+		goto out;
+	}
+	/* wait for completion of conversion */
+	if (!wait_for_completion_timeout(&gpadc->ab8500_gpadc_complete, 2*HZ)) {
+		dev_err(gpadc->dev,
+			"timeout: didn't receive GPADC conversion interrupt\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	/* Read the converted RAW data */
+	ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC,
+		AB8500_GPADC_MANDATAL_REG, &low_data);
+	if (ret < 0) {
+		dev_err(gpadc->dev, "gpadc_conversion: read low data failed\n");
+		goto out;
+	}
+
+	ret = abx500_get_register_interruptible(gpadc->dev, AB8500_GPADC,
+		AB8500_GPADC_MANDATAH_REG, &high_data);
+	if (ret < 0) {
+		dev_err(gpadc->dev,
+			"gpadc_conversion: read high data failed\n");
+		goto out;
+	}
+
+	data = (high_data << 8) | low_data;
+	/* Disable GPADC */
+	ret = abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
+		AB8500_GPADC_CTRL1_REG, DIS_GPADC);
+	if (ret < 0) {
+		dev_err(gpadc->dev, "gpadc_conversion: disable gpadc failed\n");
+		goto out;
+	}
+	/* Disable VTVout LDO this is required for GPADC */
+	regulator_disable(gpadc->regu);
+	mutex_unlock(&gpadc->ab8500_gpadc_lock);
+	ret = ab8500_gpadc_ad_to_voltage(gpadc, input, data);
+	return ret;
+
+out:
+	/*
+	 * It has shown to be needed to turn off the GPADC if an error occurs,
+	 * otherwise we might have problem when waiting for the busy bit in the
+	 * GPADC status register to go low. In V1.1 there wait_for_completion
+	 * seems to timeout when waiting for an interrupt.. Not seen in V2.0
+	 */
+	(void) abx500_set_register_interruptible(gpadc->dev, AB8500_GPADC,
+		AB8500_GPADC_CTRL1_REG, DIS_GPADC);
+	regulator_disable(gpadc->regu);
+	mutex_unlock(&gpadc->ab8500_gpadc_lock);
+	dev_err(gpadc->dev,
+		"gpadc_conversion: Failed to AD convert channel %d\n", input);
+	return ret;
+}
+EXPORT_SYMBOL(ab8500_gpadc_convert);
+
+/**
+ * ab8500_bm_gpswadcconvend_handler() - isr for s/w gpadc conversion completion
+ * @irq:	irq number
+ * @data:	pointer to the data passed during request irq
+ *
+ * This is a interrupt service routine for s/w gpadc conversion completion.
+ * Notifies the gpadc completion is completed and the converted raw value
+ * can be read from the registers.
+ * Returns IRQ status(IRQ_HANDLED)
+ */
+static irqreturn_t ab8500_bm_gpswadcconvend_handler(int irq, void *_gpadc)
+{
+	struct ab8500_gpadc *gpadc = _gpadc;
+
+	complete(&gpadc->ab8500_gpadc_complete);
+
+	return IRQ_HANDLED;
+}
+
+static int otp_cal_regs[] = {
+	AB8500_GPADC_CAL_1,
+	AB8500_GPADC_CAL_2,
+	AB8500_GPADC_CAL_3,
+	AB8500_GPADC_CAL_4,
+	AB8500_GPADC_CAL_5,
+	AB8500_GPADC_CAL_6,
+	AB8500_GPADC_CAL_7,
+};
+
+static void ab8500_gpadc_read_calibration_data(struct ab8500_gpadc *gpadc)
+{
+	int i;
+	int ret[ARRAY_SIZE(otp_cal_regs)];
+	u8 gpadc_cal[ARRAY_SIZE(otp_cal_regs)];
+
+	int vmain_high, vmain_low;
+	int btemp_high, btemp_low;
+	int vbat_high, vbat_low;
+
+	/* First we read all OTP registers and store the error code */
+	for (i = 0; i < ARRAY_SIZE(otp_cal_regs); i++) {
+		ret[i] = abx500_get_register_interruptible(gpadc->dev,
+			AB8500_OTP_EMUL, otp_cal_regs[i],  &gpadc_cal[i]);
+		if (ret[i] < 0)
+			dev_err(gpadc->dev, "%s: read otp reg 0x%02x failed\n",
+				__func__, otp_cal_regs[i]);
+	}
+
+	/*
+	 * The ADC calibration data is stored in OTP registers.
+	 * The layout of the calibration data is outlined below and a more
+	 * detailed description can be found in UM0836
+	 *
+	 * vm_h/l = vmain_high/low
+	 * bt_h/l = btemp_high/low
+	 * vb_h/l = vbat_high/low
+	 *
+	 * Data bits:
+	 * | 7	   | 6	   | 5	   | 4	   | 3	   | 2	   | 1	   | 0
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * |						   | vm_h9 | vm_h8
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * |		   | vm_h7 | vm_h6 | vm_h5 | vm_h4 | vm_h3 | vm_h2
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vm_h1 | vm_h0 | vm_l4 | vm_l3 | vm_l2 | vm_l1 | vm_l0 | bt_h9
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | bt_h8 | bt_h7 | bt_h6 | bt_h5 | bt_h4 | bt_h3 | bt_h2 | bt_h1
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | bt_h0 | bt_l4 | bt_l3 | bt_l2 | bt_l1 | bt_l0 | vb_h9 | vb_h8
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vb_h7 | vb_h6 | vb_h5 | vb_h4 | vb_h3 | vb_h2 | vb_h1 | vb_h0
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 * | vb_l5 | vb_l4 | vb_l3 | vb_l2 | vb_l1 | vb_l0 |
+	 * |.......|.......|.......|.......|.......|.......|.......|.......
+	 *
+	 *
+	 * Ideal output ADC codes corresponding to injected input voltages
+	 * during manufacturing is:
+	 *
+	 * vmain_high: Vin = 19500mV / ADC ideal code = 997
+	 * vmain_low:  Vin = 315mV   / ADC ideal code = 16
+	 * btemp_high: Vin = 1300mV  / ADC ideal code = 985
+	 * btemp_low:  Vin = 21mV    / ADC ideal code = 16
+	 * vbat_high:  Vin = 4700mV  / ADC ideal code = 982
+	 * vbat_low:   Vin = 2380mV  / ADC ideal code = 33
+	 */
+
+	/* Calculate gain and offset for VMAIN if all reads succeeded */
+	if (!(ret[0] < 0 || ret[1] < 0 || ret[2] < 0)) {
+		vmain_high = (((gpadc_cal[0] & 0x03) << 8) |
+			((gpadc_cal[1] & 0x3F) << 2) |
+			((gpadc_cal[2] & 0xC0) >> 6));
+
+		vmain_low = ((gpadc_cal[2] & 0x3E) >> 1);
+
+		gpadc->cal_data[ADC_INPUT_VMAIN].gain = CALIB_SCALE *
+			(19500 - 315) /	(vmain_high - vmain_low);
+
+		gpadc->cal_data[ADC_INPUT_VMAIN].offset = CALIB_SCALE * 19500 -
+			(CALIB_SCALE * (19500 - 315) /
+			 (vmain_high - vmain_low)) * vmain_high;
+	} else {
+		gpadc->cal_data[ADC_INPUT_VMAIN].gain = 0;
+	}
+
+	/* Calculate gain and offset for BTEMP if all reads succeeded */
+	if (!(ret[2] < 0 || ret[3] < 0 || ret[4] < 0)) {
+		btemp_high = (((gpadc_cal[2] & 0x01) << 9) |
+			(gpadc_cal[3] << 1) |
+			((gpadc_cal[4] & 0x80) >> 7));
+
+		btemp_low = ((gpadc_cal[4] & 0x7C) >> 2);
+
+		gpadc->cal_data[ADC_INPUT_BTEMP].gain =
+			CALIB_SCALE * (1300 - 21) / (btemp_high - btemp_low);
+
+		gpadc->cal_data[ADC_INPUT_BTEMP].offset = CALIB_SCALE * 1300 -
+			(CALIB_SCALE * (1300 - 21) /
+			(btemp_high - btemp_low)) * btemp_high;
+	} else {
+		gpadc->cal_data[ADC_INPUT_BTEMP].gain = 0;
+	}
+
+	/* Calculate gain and offset for VBAT if all reads succeeded */
+	if (!(ret[4] < 0 || ret[5] < 0 || ret[6] < 0)) {
+		vbat_high = (((gpadc_cal[4] & 0x03) << 8) | gpadc_cal[5]);
+		vbat_low = ((gpadc_cal[6] & 0xFC) >> 2);
+
+		gpadc->cal_data[ADC_INPUT_VBAT].gain = CALIB_SCALE *
+			(4700 - 2380) /	(vbat_high - vbat_low);
+
+		gpadc->cal_data[ADC_INPUT_VBAT].offset = CALIB_SCALE * 4700 -
+			(CALIB_SCALE * (4700 - 2380) /
+			(vbat_high - vbat_low)) * vbat_high;
+	} else {
+		gpadc->cal_data[ADC_INPUT_VBAT].gain = 0;
+	}
+
+	dev_dbg(gpadc->dev, "VMAIN gain %llu offset %llu\n",
+		gpadc->cal_data[ADC_INPUT_VMAIN].gain,
+		gpadc->cal_data[ADC_INPUT_VMAIN].offset);
+
+	dev_dbg(gpadc->dev, "BTEMP gain %llu offset %llu\n",
+		gpadc->cal_data[ADC_INPUT_BTEMP].gain,
+		gpadc->cal_data[ADC_INPUT_BTEMP].offset);
+
+	dev_dbg(gpadc->dev, "VBAT gain %llu offset %llu\n",
+		gpadc->cal_data[ADC_INPUT_VBAT].gain,
+		gpadc->cal_data[ADC_INPUT_VBAT].offset);
+}
+
+static int __devinit ab8500_gpadc_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+	struct ab8500_gpadc *gpadc;
+
+	gpadc = kzalloc(sizeof(struct ab8500_gpadc), GFP_KERNEL);
+	if (!gpadc) {
+		dev_err(&pdev->dev, "Error: No memory\n");
+		return -ENOMEM;
+	}
+
+	gpadc->irq = platform_get_irq_byname(pdev, "SW_CONV_END");
+	if (gpadc->irq < 0) {
+		dev_err(gpadc->dev, "failed to get platform irq-%d\n",
+			gpadc->irq);
+		ret = gpadc->irq;
+		goto fail;
+	}
+
+	gpadc->dev = &pdev->dev;
+	mutex_init(&gpadc->ab8500_gpadc_lock);
+
+	/* Initialize completion used to notify completion of conversion */
+	init_completion(&gpadc->ab8500_gpadc_complete);
+
+	/* Register interrupt  - SwAdcComplete */
+	ret = request_threaded_irq(gpadc->irq, NULL,
+		ab8500_bm_gpswadcconvend_handler,
+		IRQF_NO_SUSPEND | IRQF_SHARED, "ab8500-gpadc", gpadc);
+	if (ret < 0) {
+		dev_err(gpadc->dev, "Failed to register interrupt, irq: %d\n",
+			gpadc->irq);
+		goto fail;
+	}
+
+	/* VTVout LDO used to power up ab8500-GPADC */
+	gpadc->regu = regulator_get(&pdev->dev, "vddadc");
+	if (IS_ERR(gpadc->regu)) {
+		ret = PTR_ERR(gpadc->regu);
+		dev_err(gpadc->dev, "failed to get vtvout LDO\n");
+		goto fail_irq;
+	}
+	ab8500_gpadc_read_calibration_data(gpadc);
+	list_add_tail(&gpadc->node, &ab8500_gpadc_list);
+	dev_dbg(gpadc->dev, "probe success\n");
+	return 0;
+fail_irq:
+	free_irq(gpadc->irq, gpadc);
+fail:
+	kfree(gpadc);
+	gpadc = NULL;
+	return ret;
+}
+
+static int __devexit ab8500_gpadc_remove(struct platform_device *pdev)
+{
+	struct ab8500_gpadc *gpadc = platform_get_drvdata(pdev);
+
+	/* remove this gpadc entry from the list */
+	list_del(&gpadc->node);
+	/* remove interrupt  - completion of Sw ADC conversion */
+	free_irq(gpadc->irq, gpadc);
+	/* disable VTVout LDO that is being used by GPADC */
+	regulator_put(gpadc->regu);
+	kfree(gpadc);
+	gpadc = NULL;
+	return 0;
+}
+
+static struct platform_driver ab8500_gpadc_driver = {
+	.probe = ab8500_gpadc_probe,
+	.remove = __devexit_p(ab8500_gpadc_remove),
+	.driver = {
+		.name = "ab8500-gpadc",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init ab8500_gpadc_init(void)
+{
+	return platform_driver_register(&ab8500_gpadc_driver);
+}
+
+static void __exit ab8500_gpadc_exit(void)
+{
+	platform_driver_unregister(&ab8500_gpadc_driver);
+}
+
+subsys_initcall_sync(ab8500_gpadc_init);
+module_exit(ab8500_gpadc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR("Arun R Murthy, Daniel Willerud, Johan Palsson");
+MODULE_ALIAS("platform:ab8500_gpadc");
+MODULE_DESCRIPTION("AB8500 GPADC driver");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab8500-i2c.c linux-libre-2.6.39-gnu/drivers/mfd/ab8500-i2c.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab8500-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab8500-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 {
 	platform_driver_unregister(&ab8500_i2c_driver);
 }
-subsys_initcall(ab8500_i2c_init);
+arch_initcall(ab8500_i2c_init);
 module_exit(ab8500_i2c_exit);
 
 MODULE_AUTHOR("Mattias WALLIN <mattias.wallin@stericsson.com");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ab8500-sysctrl.c linux-libre-2.6.39-gnu/drivers/mfd/ab8500-sysctrl.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ab8500-sysctrl.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/ab8500-sysctrl.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) ST-Ericsson SA 2010
+ * Author: Mattias Nilsson <mattias.i.nilsson@stericsson.com> for ST Ericsson.
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/ab8500.h>
+#include <linux/mfd/abx500.h>
+#include <linux/mfd/ab8500/sysctrl.h>
+
+static struct device *sysctrl_dev;
+
+static inline bool valid_bank(u8 bank)
+{
+	return ((bank == AB8500_SYS_CTRL1_BLOCK) ||
+		(bank == AB8500_SYS_CTRL2_BLOCK));
+}
+
+int ab8500_sysctrl_read(u16 reg, u8 *value)
+{
+	u8 bank;
+
+	if (sysctrl_dev == NULL)
+		return -EAGAIN;
+
+	bank = (reg >> 8);
+	if (!valid_bank(bank))
+		return -EINVAL;
+
+	return abx500_get_register_interruptible(sysctrl_dev, bank,
+		(u8)(reg & 0xFF), value);
+}
+
+int ab8500_sysctrl_write(u16 reg, u8 mask, u8 value)
+{
+	u8 bank;
+
+	if (sysctrl_dev == NULL)
+		return -EAGAIN;
+
+	bank = (reg >> 8);
+	if (!valid_bank(bank))
+		return -EINVAL;
+
+	return abx500_mask_and_set_register_interruptible(sysctrl_dev, bank,
+		(u8)(reg & 0xFF), mask, value);
+}
+
+static int __devinit ab8500_sysctrl_probe(struct platform_device *pdev)
+{
+	sysctrl_dev = &pdev->dev;
+	return 0;
+}
+
+static int __devexit ab8500_sysctrl_remove(struct platform_device *pdev)
+{
+	sysctrl_dev = NULL;
+	return 0;
+}
+
+static struct platform_driver ab8500_sysctrl_driver = {
+	.driver = {
+		.name = "ab8500-sysctrl",
+		.owner = THIS_MODULE,
+	},
+	.probe = ab8500_sysctrl_probe,
+	.remove = __devexit_p(ab8500_sysctrl_remove),
+};
+
+static int __init ab8500_sysctrl_init(void)
+{
+	return platform_driver_register(&ab8500_sysctrl_driver);
+}
+subsys_initcall(ab8500_sysctrl_init);
+
+MODULE_AUTHOR("Mattias Nilsson <mattias.i.nilsson@stericsson.com");
+MODULE_DESCRIPTION("AB8500 system control driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/adp5520.c linux-libre-2.6.39-gnu/drivers/mfd/adp5520.c
--- linux-libre-2.6.38-gnu/drivers/mfd/adp5520.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/adp5520.c	2011-05-19 00:06:34.000000000 -0400
@@ -321,27 +321,27 @@
 }
 
 #ifdef CONFIG_PM
-static int adp5520_suspend(struct i2c_client *client,
-				 pm_message_t state)
+static int adp5520_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
 
 	adp5520_clr_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
 	return 0;
 }
 
-static int adp5520_resume(struct i2c_client *client)
+static int adp5520_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
 	struct adp5520_chip *chip = dev_get_drvdata(&client->dev);
 
 	adp5520_set_bits(chip->dev, ADP5520_MODE_STATUS, ADP5520_nSTNBY);
 	return 0;
 }
-#else
-#define adp5520_suspend	NULL
-#define adp5520_resume	NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(adp5520_pm, adp5520_suspend, adp5520_resume);
+
 static const struct i2c_device_id adp5520_id[] = {
 	{ "pmic-adp5520", ID_ADP5520 },
 	{ "pmic-adp5501", ID_ADP5501 },
@@ -353,11 +353,10 @@
 	.driver = {
 		.name	= "adp5520",
 		.owner	= THIS_MODULE,
+		.pm	= &adp5520_pm,
 	},
 	.probe		= adp5520_probe,
 	.remove		= __devexit_p(adp5520_remove),
-	.suspend	= adp5520_suspend,
-	.resume		= adp5520_resume,
 	.id_table 	= adp5520_id,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/asic3.c linux-libre-2.6.39-gnu/drivers/mfd/asic3.c
--- linux-libre-2.6.38-gnu/drivers/mfd/asic3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/asic3.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,13 +139,12 @@
 
 static void asic3_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
+	struct asic3 *asic = irq_desc_get_handler_data(desc);
+	struct irq_data *data = irq_desc_get_irq_data(desc);
 	int iter, i;
 	unsigned long flags;
-	struct asic3 *asic;
 
-	desc->irq_data.chip->irq_ack(&desc->irq_data);
-
-	asic = get_irq_data(irq);
+	data->chip->irq_ack(data);
 
 	for (iter = 0 ; iter < MAX_ASIC_ISR_LOOPS; iter++) {
 		u32 status;
@@ -188,8 +187,7 @@
 					irqnr = asic->irq_base +
 						(ASIC3_GPIOS_PER_BANK * bank)
 						+ i;
-					desc = irq_to_desc(irqnr);
-					desc->handle_irq(irqnr, desc);
+					generic_handle_irq(irqnr);
 					if (asic->irq_bothedge[bank] & bit)
 						asic3_irq_flip_edge(asic, base,
 								    bit);
@@ -200,11 +198,8 @@
 		/* Handle remaining IRQs in the status register */
 		for (i = ASIC3_NUM_GPIOS; i < ASIC3_NR_IRQS; i++) {
 			/* They start at bit 4 and go up */
-			if (status & (1 << (i - ASIC3_NUM_GPIOS + 4))) {
-				desc = irq_to_desc(asic->irq_base + i);
-				desc->handle_irq(asic->irq_base + i,
-						 desc);
-			}
+			if (status & (1 << (i - ASIC3_NUM_GPIOS + 4)))
+				generic_handle_irq(asic->irq_base + i);
 		}
 	}
 
@@ -393,21 +388,21 @@
 
 	for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
 		if (irq < asic->irq_base + ASIC3_NUM_GPIOS)
-			set_irq_chip(irq, &asic3_gpio_irq_chip);
+			irq_set_chip(irq, &asic3_gpio_irq_chip);
 		else
-			set_irq_chip(irq, &asic3_irq_chip);
+			irq_set_chip(irq, &asic3_irq_chip);
 
-		set_irq_chip_data(irq, asic);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_data(irq, asic);
+		irq_set_handler(irq, handle_level_irq);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
 	asic3_write_register(asic, ASIC3_OFFSET(INTR, INT_MASK),
 			     ASIC3_INTMASK_GINTMASK);
 
-	set_irq_chained_handler(asic->irq_nr, asic3_irq_demux);
-	set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
-	set_irq_data(asic->irq_nr, asic);
+	irq_set_chained_handler(asic->irq_nr, asic3_irq_demux);
+	irq_set_irq_type(asic->irq_nr, IRQ_TYPE_EDGE_RISING);
+	irq_set_handler_data(asic->irq_nr, asic);
 
 	return 0;
 }
@@ -421,11 +416,10 @@
 
 	for (irq = irq_base; irq < irq_base + ASIC3_NR_IRQS; irq++) {
 		set_irq_flags(irq, 0);
-		set_irq_handler(irq, NULL);
-		set_irq_chip(irq, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
-	set_irq_chained_handler(asic->irq_nr, NULL);
+	irq_set_chained_handler(asic->irq_nr, NULL);
 }
 
 /* GPIOs */
@@ -682,7 +676,7 @@
 	.name          = "ds1wm",
 	.enable        = ds1wm_enable,
 	.disable       = ds1wm_disable,
-	.driver_data   = &ds1wm_pdata,
+	.mfd_data      = &ds1wm_pdata,
 	.num_resources = ARRAY_SIZE(ds1wm_resources),
 	.resources     = ds1wm_resources,
 };
@@ -783,7 +777,7 @@
 	.name          = "tmio-mmc",
 	.enable        = asic3_mmc_enable,
 	.disable       = asic3_mmc_disable,
-	.driver_data   = &asic3_mmc_data,
+	.mfd_data      = &asic3_mmc_data,
 	.num_resources = ARRAY_SIZE(asic3_mmc_resources),
 	.resources     = asic3_mmc_resources,
 };
@@ -810,9 +804,6 @@
 	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 */
 	asic->tmio_cnf = ioremap((ASIC3_SD_CONFIG_BASE >> asic->bus_shift) +
 				 mem_sdio->start, 0x400 >> asic->bus_shift);
@@ -824,9 +815,6 @@
 	asic3_mmc_resources[0].start >>= asic->bus_shift;
 	asic3_mmc_resources[0].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)
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/cs5535-mfd.c linux-libre-2.6.39-gnu/drivers/mfd/cs5535-mfd.c
--- linux-libre-2.6.38-gnu/drivers/mfd/cs5535-mfd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/cs5535-mfd.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include <linux/mfd/core.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <asm/olpc.h>
 
 #define DRV_NAME "cs5535-mfd"
 
@@ -39,6 +40,37 @@
 	NR_BARS,
 };
 
+static int cs5535_mfd_res_enable(struct platform_device *pdev)
+{
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		return -EIO;
+	}
+
+	if (!request_region(res->start, resource_size(res), DRV_NAME)) {
+		dev_err(&pdev->dev, "can't request region\n");
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int cs5535_mfd_res_disable(struct platform_device *pdev)
+{
+	struct resource *res;
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!res) {
+		dev_err(&pdev->dev, "can't fetch device resource info\n");
+		return -EIO;
+	}
+
+	release_region(res->start, resource_size(res));
+	return 0;
+}
+
 static __devinitdata struct resource cs5535_mfd_resources[NR_BARS];
 
 static __devinitdata struct mfd_cell cs5535_mfd_cells[] = {
@@ -65,15 +97,35 @@
 		.name = "cs5535-pms",
 		.num_resources = 1,
 		.resources = &cs5535_mfd_resources[PMS_BAR],
+
+		.enable = cs5535_mfd_res_enable,
+		.disable = cs5535_mfd_res_disable,
 	},
 	{
 		.id = ACPI_BAR,
 		.name = "cs5535-acpi",
 		.num_resources = 1,
 		.resources = &cs5535_mfd_resources[ACPI_BAR],
+
+		.enable = cs5535_mfd_res_enable,
+		.disable = cs5535_mfd_res_disable,
 	},
 };
 
+#ifdef CONFIG_OLPC
+static void __devinit cs5535_clone_olpc_cells(void)
+{
+	const char *acpi_clones[] = { "olpc-xo1-pm-acpi", "olpc-xo1-sci-acpi" };
+
+	if (!machine_is_olpc())
+		return;
+
+	mfd_clone_cell("cs5535-acpi", acpi_clones, ARRAY_SIZE(acpi_clones));
+}
+#else
+static void cs5535_clone_olpc_cells(void) { }
+#endif
+
 static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
 		const struct pci_device_id *id)
 {
@@ -102,6 +154,7 @@
 		dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
 		goto err_disable;
 	}
+	cs5535_clone_olpc_cells();
 
 	dev_info(&pdev->dev, "%zu devices registered.\n",
 			ARRAY_SIZE(cs5535_mfd_cells));
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/davinci_voicecodec.c linux-libre-2.6.39-gnu/drivers/mfd/davinci_voicecodec.c
--- linux-libre-2.6.38-gnu/drivers/mfd/davinci_voicecodec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/davinci_voicecodec.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,12 +119,12 @@
 	/* Voice codec interface client */
 	cell = &davinci_vc->cells[DAVINCI_VC_VCIF_CELL];
 	cell->name = "davinci-vcif";
-	cell->driver_data = davinci_vc;
+	cell->mfd_data = davinci_vc;
 
 	/* Voice codec CQ93VC client */
 	cell = &davinci_vc->cells[DAVINCI_VC_CQ93VC_CELL];
 	cell->name = "cq93vc-codec";
-	cell->driver_data = davinci_vc;
+	cell->mfd_data = davinci_vc;
 
 	ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
 			      DAVINCI_VC_CELLS, NULL, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ezx-pcap.c linux-libre-2.6.39-gnu/drivers/mfd/ezx-pcap.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ezx-pcap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ezx-pcap.c	2011-05-19 00:06:34.000000000 -0400
@@ -162,6 +162,7 @@
 
 static struct irq_chip pcap_irq_chip = {
 	.name		= "pcap",
+	.irq_disable	= pcap_mask_irq,
 	.irq_mask	= pcap_mask_irq,
 	.irq_unmask	= pcap_unmask_irq,
 };
@@ -184,7 +185,7 @@
 		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 */
+		/* We can't 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;
@@ -196,17 +197,8 @@
 		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, "Invalid PCAP IRQ %d\n", irq))
-					break;
-
-				if (desc->status & IRQ_DISABLED)
-					note_interrupt(irq, desc, IRQ_NONE);
-				else
-					desc->handle_irq(irq, desc);
-			}
+			if (service & 1)
+				generic_handle_irq(irq);
 		}
 		local_irq_enable();
 		ezx_pcap_write(pcap, PCAP_REG_MSR, pcap->msr);
@@ -215,7 +207,7 @@
 
 static void pcap_irq_handler(unsigned int irq, struct irq_desc *desc)
 {
-	struct pcap_chip *pcap = get_irq_data(irq);
+	struct pcap_chip *pcap = irq_get_handler_data(irq);
 
 	desc->irq_data.chip->irq_ack(&desc->irq_data);
 	queue_work(pcap->workqueue, &pcap->isr_work);
@@ -419,7 +411,7 @@
 
 	/* cleanup irqchip */
 	for (i = pcap->irq_base; i < (pcap->irq_base + PCAP_NIRQS); i++)
-		set_irq_chip_and_handler(i, NULL, NULL);
+		irq_set_chip_and_handler(i, NULL, NULL);
 
 	destroy_workqueue(pcap->workqueue);
 
@@ -465,7 +457,7 @@
 	pcap->workqueue = create_singlethread_workqueue("pcapd");
 	if (!pcap->workqueue) {
 		ret = -ENOMEM;
-		dev_err(&spi->dev, "cant create pcap thread\n");
+		dev_err(&spi->dev, "can't create pcap thread\n");
 		goto free_pcap;
 	}
 
@@ -476,12 +468,12 @@
 
 	/* 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);
+		irq_set_chip_and_handler(i, &pcap_irq_chip, handle_simple_irq);
+		irq_set_chip_data(i, pcap);
 #ifdef CONFIG_ARM
 		set_irq_flags(i, IRQF_VALID);
 #else
-		set_irq_noprobe(i);
+		irq_set_noprobe(i);
 #endif
 	}
 
@@ -490,10 +482,10 @@
 	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);
+	irq_set_irq_type(spi->irq, IRQ_TYPE_EDGE_RISING);
+	irq_set_handler_data(spi->irq, pcap);
+	irq_set_chained_handler(spi->irq, pcap_irq_handler);
+	irq_set_irq_wake(spi->irq, 1);
 
 	/* ADC */
 	adc_irq = pcap_to_irq(pcap, (pdata->config & PCAP_SECOND_PORT) ?
@@ -522,7 +514,7 @@
 	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);
+		irq_set_chip_and_handler(i, NULL, NULL);
 /* destroy_workqueue: */
 	destroy_workqueue(pcap->workqueue);
 free_pcap:
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/htc-egpio.c linux-libre-2.6.39-gnu/drivers/mfd/htc-egpio.c
--- linux-libre-2.6.38-gnu/drivers/mfd/htc-egpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/htc-egpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,7 @@
 
 static void egpio_handler(unsigned int irq, struct irq_desc *desc)
 {
-	struct egpio_info *ei = get_irq_data(irq);
+	struct egpio_info *ei = irq_desc_get_handler_data(desc);
 	int irqpin;
 
 	/* Read current pins. */
@@ -113,9 +113,7 @@
 	for_each_set_bit(irqpin, &readval, ei->nirqs) {
 		/* Run irq handler */
 		pr_debug("got IRQ %d\n", irqpin);
-		irq = ei->irq_start + irqpin;
-		desc = irq_to_desc(irq);
-		desc->handle_irq(irq, desc);
+		generic_handle_irq(ei->irq_start + irqpin);
 	}
 }
 
@@ -346,14 +344,14 @@
 			ei->ack_write = 0;
 		irq_end = ei->irq_start + ei->nirqs;
 		for (irq = ei->irq_start; irq < irq_end; irq++) {
-			set_irq_chip(irq, &egpio_muxed_chip);
-			set_irq_chip_data(irq, ei);
-			set_irq_handler(irq, handle_simple_irq);
+			irq_set_chip_and_handler(irq, &egpio_muxed_chip,
+						 handle_simple_irq);
+			irq_set_chip_data(irq, ei);
 			set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 		}
-		set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
-		set_irq_data(ei->chained_irq, ei);
-		set_irq_chained_handler(ei->chained_irq, egpio_handler);
+		irq_set_irq_type(ei->chained_irq, IRQ_TYPE_EDGE_RISING);
+		irq_set_handler_data(ei->chained_irq, ei);
+		irq_set_chained_handler(ei->chained_irq, egpio_handler);
 		ack_irqs(ei);
 
 		device_init_wakeup(&pdev->dev, 1);
@@ -375,11 +373,10 @@
 	if (ei->chained_irq) {
 		irq_end = ei->irq_start + ei->nirqs;
 		for (irq = ei->irq_start; irq < irq_end; irq++) {
-			set_irq_chip(irq, NULL);
-			set_irq_handler(irq, NULL);
+			irq_set_chip_and_handler(irq, NULL, NULL);
 			set_irq_flags(irq, 0);
 		}
-		set_irq_chained_handler(ei->chained_irq, NULL);
+		irq_set_chained_handler(ei->chained_irq, NULL);
 		device_init_wakeup(&pdev->dev, 0);
 	}
 	iounmap(ei->base_addr);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/htc-i2cpld.c linux-libre-2.6.39-gnu/drivers/mfd/htc-i2cpld.c
--- linux-libre-2.6.38-gnu/drivers/mfd/htc-i2cpld.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/htc-i2cpld.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,6 +58,7 @@
 	uint                    irq_start;
 	int                     nirqs;
 
+	unsigned int		flow_type;
 	/*
 	 * Work structure to allow for setting values outside of any
 	 * possible interrupt context
@@ -97,12 +98,7 @@
 
 static int htcpld_set_type(struct irq_data *data, unsigned int flags)
 {
-	struct irq_desc *d = irq_to_desc(data->irq);
-
-	if (!d) {
-		pr_err("HTCPLD invalid IRQ: %d\n", data->irq);
-		return -EINVAL;
-	}
+	struct htcpld_chip *chip = irq_data_get_irq_chip_data(data);
 
 	if (flags & ~IRQ_TYPE_SENSE_MASK)
 		return -EINVAL;
@@ -111,9 +107,7 @@
 	if (flags & (IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH))
 		return -EINVAL;
 
-	d->status &= ~IRQ_TYPE_SENSE_MASK;
-	d->status |= flags;
-
+	chip->flow_type = flags;
 	return 0;
 }
 
@@ -135,7 +129,6 @@
 	unsigned int i;
 	unsigned long flags;
 	int irqpin;
-	struct irq_desc *desc;
 
 	if (!htcpld) {
 		pr_debug("htcpld is null in ISR\n");
@@ -195,23 +188,19 @@
 		 * associated interrupts.
 		 */
 		for (irqpin = 0; irqpin < chip->nirqs; irqpin++) {
-			unsigned oldb, newb;
-			int flags;
+			unsigned oldb, newb, type = chip->flow_type;
 
 			irq = chip->irq_start + irqpin;
-			desc = irq_to_desc(irq);
-			flags = desc->status;
 
 			/* Run the IRQ handler, but only if the bit value
 			 * changed, and the proper flags are set */
 			oldb = (old_val >> irqpin) & 1;
 			newb = (uval >> irqpin) & 1;
 
-			if ((!oldb && newb && (flags & IRQ_TYPE_EDGE_RISING)) ||
-			    (oldb && !newb &&
-			     (flags & IRQ_TYPE_EDGE_FALLING))) {
+			if ((!oldb && newb && (type & IRQ_TYPE_EDGE_RISING)) ||
+			    (oldb && !newb && (type & IRQ_TYPE_EDGE_FALLING))) {
 				pr_debug("fire IRQ %d\n", irqpin);
-				desc->handle_irq(irq, desc);
+				generic_handle_irq(irq);
 			}
 		}
 	}
@@ -359,13 +348,13 @@
 	/* Setup irq handlers */
 	irq_end = chip->irq_start + chip->nirqs;
 	for (irq = chip->irq_start; irq < irq_end; irq++) {
-		set_irq_chip(irq, &htcpld_muxed_chip);
-		set_irq_chip_data(irq, chip);
-		set_irq_handler(irq, handle_simple_irq);
+		irq_set_chip_and_handler(irq, &htcpld_muxed_chip,
+					 handle_simple_irq);
+		irq_set_chip_data(irq, chip);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 #else
-		set_irq_probe(irq);
+		irq_set_probe(irq);
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/htc-pasic3.c linux-libre-2.6.39-gnu/drivers/mfd/htc-pasic3.c
--- linux-libre-2.6.38-gnu/drivers/mfd/htc-pasic3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/htc-pasic3.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,7 +117,7 @@
 	.name          = "ds1wm",
 	.enable        = ds1wm_enable,
 	.disable       = ds1wm_disable,
-	.driver_data   = &ds1wm_pdata,
+	.mfd_data      = &ds1wm_pdata,
 	.num_resources = 2,
 	.resources     = ds1wm_resources,
 };
@@ -165,8 +165,6 @@
 		ds1wm_pdata.clock_rate = pdata->clock_rate;
 		/* the first 5 PASIC3 registers control the DS1WM */
 		ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;
-		ds1wm_cell.platform_data = &ds1wm_cell;
-		ds1wm_cell.data_size = sizeof(ds1wm_cell);
 		ret = mfd_add_devices(&pdev->dev, pdev->id,
 				&ds1wm_cell, 1, r, irq);
 		if (ret < 0)
@@ -174,9 +172,6 @@
 	}
 
 	if (pdata && pdata->led_pdata) {
-		led_cell.driver_data = pdata->led_pdata;
-		led_cell.platform_data = &led_cell;
-		led_cell.data_size = sizeof(ds1wm_cell);
 		ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
 		if (ret < 0)
 			dev_warn(dev, "failed to register LED device\n");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/janz-cmodio.c linux-libre-2.6.39-gnu/drivers/mfd/janz-cmodio.c
--- linux-libre-2.6.38-gnu/drivers/mfd/janz-cmodio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/janz-cmodio.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,8 +86,7 @@
 
 	/* Add platform data */
 	pdata->modno = modno;
-	cell->platform_data = pdata;
-	cell->data_size = sizeof(*pdata);
+	cell->mfd_data = pdata;
 
 	/* MODULbus registers -- PCI BAR3 is big-endian MODULbus access */
 	res->flags = IORESOURCE_MEM;
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/jz4740-adc.c linux-libre-2.6.39-gnu/drivers/mfd/jz4740-adc.c
--- linux-libre-2.6.38-gnu/drivers/mfd/jz4740-adc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/jz4740-adc.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,7 +112,7 @@
 
 static void jz4740_adc_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	struct jz4740_adc *adc = get_irq_desc_data(desc);
+	struct jz4740_adc *adc = irq_desc_get_handler_data(desc);
 	uint8_t status;
 	unsigned int i;
 
@@ -232,8 +232,6 @@
 		.name = "jz4740-hwmon",
 		.num_resources = ARRAY_SIZE(jz4740_hwmon_resources),
 		.resources = jz4740_hwmon_resources,
-		.platform_data = (void *)&jz4740_adc_cells[0],
-		.data_size = sizeof(struct mfd_cell),
 
 		.enable = jz4740_adc_cell_enable,
 		.disable = jz4740_adc_cell_disable,
@@ -243,8 +241,6 @@
 		.name = "jz4740-battery",
 		.num_resources = ARRAY_SIZE(jz4740_battery_resources),
 		.resources = jz4740_battery_resources,
-		.platform_data = (void *)&jz4740_adc_cells[1],
-		.data_size = sizeof(struct mfd_cell),
 
 		.enable = jz4740_adc_cell_enable,
 		.disable = jz4740_adc_cell_disable,
@@ -314,13 +310,13 @@
 	platform_set_drvdata(pdev, adc);
 
 	for (irq = adc->irq_base; irq < adc->irq_base + 5; ++irq) {
-		set_irq_chip_data(irq, adc);
-		set_irq_chip_and_handler(irq, &jz4740_adc_irq_chip,
-		    handle_level_irq);
+		irq_set_chip_data(irq, adc);
+		irq_set_chip_and_handler(irq, &jz4740_adc_irq_chip,
+					 handle_level_irq);
 	}
 
-	set_irq_data(adc->irq, adc);
-	set_irq_chained_handler(adc->irq, jz4740_adc_irq_demux);
+	irq_set_handler_data(adc->irq, adc);
+	irq_set_chained_handler(adc->irq, jz4740_adc_irq_demux);
 
 	writeb(0x00, adc->base + JZ_REG_ADC_ENABLE);
 	writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
@@ -351,8 +347,8 @@
 
 	mfd_remove_devices(&pdev->dev);
 
-	set_irq_data(adc->irq, NULL);
-	set_irq_chained_handler(adc->irq, NULL);
+	irq_set_handler_data(adc->irq, NULL);
+	irq_set_chained_handler(adc->irq, NULL);
 
 	iounmap(adc->base);
 	release_mem_region(adc->mem->start, resource_size(adc->mem));
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/Kconfig linux-libre-2.6.39-gnu/drivers/mfd/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mfd/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -60,15 +60,6 @@
 	  This driver supports the ASIC3 multifunction chip found on many
 	  PDAs (mainly iPAQ and HTC based ones)
 
-config MFD_SH_MOBILE_SDHI
-	bool "Support for SuperH Mobile SDHI"
-	depends on SUPERH || ARCH_SHMOBILE
-	select MFD_CORE
-	select TMIO_MMC_DMA
-	 ---help---
-	  This driver supports the SDHI hardware block found in many
-	  SuperH Mobile SoCs.
-
 config MFD_DAVINCI_VOICECODEC
 	tristate
 	select MFD_CORE
@@ -81,6 +72,17 @@
 	  boards.  MSP430 firmware manages resets and power sequencing,
 	  inputs from buttons and the IR remote, LEDs, an RTC, and more.
 
+config MFD_TI_SSP
+	tristate "TI Sequencer Serial Port support"
+	depends on ARCH_DAVINCI_TNETV107X
+	select MFD_CORE
+	---help---
+	  Say Y here if you want support for the Sequencer Serial Port
+	  in a Texas Instruments TNETV107X SoC.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ti-ssp.
+
 config HTC_EGPIO
 	bool "HTC EGPIO support"
 	depends on GENERIC_HARDIRQS && GPIOLIB && ARM
@@ -118,6 +120,18 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called ucb1400_core.
 
+config TPS6105X
+	tristate "TPS61050/61052 Boost Converters"
+	depends on I2C
+	select REGULATOR
+	select MFD_CORE
+	select REGULATOR_FIXED_VOLTAGE
+	help
+	  This option enables a driver for the TP61050/TPS61052
+	  high-power "white LED driver". This boost converter is
+	  sometimes used for other things than white LEDs, and
+	  also contains a GPIO pin.
+
 config TPS65010
 	tristate "TPS6501x Power Management chips"
 	depends on I2C && GPIOLIB
@@ -167,6 +181,16 @@
 	  high speed USB OTG transceiver, an audio codec (on most
 	  versions) and many other features.
 
+config TWL4030_MADC
+	tristate "Texas Instruments TWL4030 MADC"
+	depends on TWL4030_CORE
+	help
+	This driver provides support for triton TWL4030-MADC. The
+	driver supports both RT and SW conversion methods.
+
+	This driver can be built as a module. If so it will be
+	named twl4030-madc
+
 config TWL4030_POWER
 	bool "Support power resources on TWL4030 family chips"
 	depends on TWL4030_CORE && ARM
@@ -177,7 +201,7 @@
 	  as clock request handshaking.
 
 	  This driver uses board-specific data to initialize the resources
-	  and load scripts controling which resources are switched off/on
+	  and load scripts controlling which resources are switched off/on
 	  or reset when a sleep, wakeup or warm reset event occurs.
 
 config TWL4030_CODEC
@@ -233,11 +257,6 @@
 	bool
 	default n
 
-config TMIO_MMC_DMA
-	bool
-	select DMA_ENGINE
-	select DMADEVICES
-
 config MFD_T7L66XB
 	bool "Support Toshiba T7L66XB"
 	depends on ARM && HAVE_CLK
@@ -293,6 +312,18 @@
 	  accessing the device, additional drivers must be enabled in order
 	  to use the functionality of the device.
 
+config MFD_MAX8997
+	bool "Maxim Semiconductor MAX8997/8966 PMIC Support"
+	depends on I2C=y && GENERIC_HARDIRQS
+	select MFD_CORE
+	help
+	  Say yes here to support for Maxim Semiconductor MAX8998/8966.
+	  This is a Power Management IC with RTC, Flash, Fuel Gauge, Haptic,
+	  MUIC controls on chip.
+	  This driver provides common support for accessing the device;
+	  additional drivers must be enabled in order to use the functionality
+	  of the device.
+
 config MFD_MAX8998
 	bool "Maxim Semiconductor MAX8998/National LP3974 PMIC Support"
 	depends on I2C=y && GENERIC_HARDIRQS
@@ -523,6 +554,13 @@
          Select this option if you want debug information using the debug
          filesystem, debugfs.
 
+config AB8500_GPADC
+	bool "AB8500 GPADC driver"
+	depends on AB8500_CORE && REGULATOR_AB8500
+	default y
+	help
+	  AB8500 GPADC driver used to convert Acc and battery/ac/usb voltage
+
 config AB3550_CORE
         bool "ST-Ericsson AB3550 Mixed Signal Circuit core functions"
 	select MFD_CORE
@@ -540,7 +578,7 @@
 config MFD_CS5535
 	tristate "Support for CS5535 and CS5536 southbridge core functions"
 	select MFD_CORE
-	depends on PCI
+	depends on PCI && X86
 	---help---
 	  This is the core driver for CS5535/CS5536 MFD functions.  This is
           necessary for using the board's GPIO and MFGPT functionality.
@@ -615,7 +653,7 @@
 	  and/or vx855_gpio drivers for this to do anything useful.
 
 config MFD_WL1273_CORE
-	tristate
+	tristate "Support for TI WL1273 FM radio."
 	depends on I2C
 	select MFD_CORE
 	default n
@@ -624,6 +662,15 @@
 	  driver connects the radio-wl1273 V4L2 module and the wl1273
 	  audio codec.
 
+config MFD_OMAP_USB_HOST
+	bool "Support OMAP USBHS core driver"
+	depends on USB_EHCI_HCD_OMAP || USB_OHCI_HCD_OMAP3
+	default y
+	help
+	  This is the core driver for the OAMP EHCI and OHCI drivers.
+	  This MFD driver does the required setup functionalities for
+	  OMAP USB Host drivers.
+
 endif # MFD_SUPPORT
 
 menu "Multimedia Capabilities Port drivers"
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/lpc_sch.c linux-libre-2.6.39-gnu/drivers/mfd/lpc_sch.c
--- linux-libre-2.6.38-gnu/drivers/mfd/lpc_sch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/lpc_sch.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,7 @@
 
 static struct pci_device_id lpc_sch_ids[] = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
+	{ PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_ITC_LPC) },
 	{ 0, }
 };
 MODULE_DEVICE_TABLE(pci, lpc_sch_ids);
@@ -70,6 +71,7 @@
 {
 	unsigned int base_addr_cfg;
 	unsigned short base_addr;
+	int i;
 
 	pci_read_config_dword(dev, SMBASE, &base_addr_cfg);
 	if (!(base_addr_cfg & (1 << 31))) {
@@ -99,7 +101,10 @@
 	gpio_sch_resource.start = base_addr;
 	gpio_sch_resource.end = base_addr + GPIO_IO_SIZE - 1;
 
-	return mfd_add_devices(&dev->dev, -1,
+	for (i=0; i < ARRAY_SIZE(lpc_sch_cells); i++)
+		lpc_sch_cells[i].id = id->device;
+
+	return mfd_add_devices(&dev->dev, 0,
 			lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/Makefile linux-libre-2.6.39-gnu/drivers/mfd/Makefile
--- linux-libre-2.6.38-gnu/drivers/mfd/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,6 @@
 obj-$(CONFIG_MFD_88PM860X)	+= 88pm860x.o
 obj-$(CONFIG_MFD_SM501)		+= sm501.o
 obj-$(CONFIG_MFD_ASIC3)		+= asic3.o tmio_core.o
-obj-$(CONFIG_MFD_SH_MOBILE_SDHI)		+= sh_mobile_sdhi.o
 
 obj-$(CONFIG_HTC_EGPIO)		+= htc-egpio.o
 obj-$(CONFIG_HTC_PASIC3)	+= htc-pasic3.o
@@ -14,6 +13,7 @@
 
 obj-$(CONFIG_MFD_DAVINCI_VOICECODEC)	+= davinci_voicecodec.o
 obj-$(CONFIG_MFD_DM355EVM_MSP)	+= dm355evm_msp.o
+obj-$(CONFIG_MFD_TI_SSP)	+= ti-ssp.o
 
 obj-$(CONFIG_MFD_STMPE)		+= stmpe.o
 obj-$(CONFIG_MFD_TC3589X)	+= tc3589x.o
@@ -32,11 +32,13 @@
 obj-$(CONFIG_MFD_WM8350_I2C)	+= wm8350-i2c.o
 obj-$(CONFIG_MFD_WM8994)	+= wm8994-core.o wm8994-irq.o
 
+obj-$(CONFIG_TPS6105X)		+= tps6105x.o
 obj-$(CONFIG_TPS65010)		+= tps65010.o
 obj-$(CONFIG_TPS6507X)		+= tps6507x.o
 obj-$(CONFIG_MENELAUS)		+= menelaus.o
 
 obj-$(CONFIG_TWL4030_CORE)	+= twl-core.o twl4030-irq.o twl6030-irq.o
+obj-$(CONFIG_TWL4030_MADC)      += twl4030-madc.o
 obj-$(CONFIG_TWL4030_POWER)    += twl4030-power.o
 obj-$(CONFIG_TWL4030_CODEC)	+= twl4030-codec.o
 obj-$(CONFIG_TWL6030_PWM)	+= twl6030-pwm.o
@@ -60,6 +62,7 @@
 obj-$(CONFIG_PMIC_DA903X)	+= da903x.o
 max8925-objs			:= max8925-core.o max8925-i2c.o
 obj-$(CONFIG_MFD_MAX8925)	+= max8925.o
+obj-$(CONFIG_MFD_MAX8997)	+= max8997.o max8997-irq.o
 obj-$(CONFIG_MFD_MAX8998)	+= max8998.o max8998-irq.o
 
 pcf50633-objs			:= pcf50633-core.o pcf50633-irq.o
@@ -70,9 +73,10 @@
 obj-$(CONFIG_AB3100_CORE)	+= ab3100-core.o
 obj-$(CONFIG_AB3100_OTP)	+= ab3100-otp.o
 obj-$(CONFIG_AB3550_CORE)	+= ab3550-core.o
-obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o
+obj-$(CONFIG_AB8500_CORE)	+= ab8500-core.o ab8500-sysctrl.o
 obj-$(CONFIG_AB8500_I2C_CORE)	+= ab8500-i2c.o
 obj-$(CONFIG_AB8500_DEBUG)	+= ab8500-debugfs.o
+obj-$(CONFIG_AB8500_GPADC)	+= ab8500-gpadc.o
 obj-$(CONFIG_MFD_TIMBERDALE)    += timberdale.o
 obj-$(CONFIG_PMIC_ADP5520)	+= adp5520.o
 obj-$(CONFIG_LPC_SCH)		+= lpc_sch.o
@@ -83,3 +87,4 @@
 obj-$(CONFIG_MFD_VX855)		+= vx855.o
 obj-$(CONFIG_MFD_WL1273_CORE)	+= wl1273-core.o
 obj-$(CONFIG_MFD_CS5535)	+= cs5535-mfd.o
+obj-$(CONFIG_MFD_OMAP_USB_HOST)	+= omap-usb-host.o
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/max8925-core.c linux-libre-2.6.39-gnu/drivers/mfd/max8925-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/max8925-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/max8925-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -517,7 +517,6 @@
 			    struct max8925_platform_data *pdata)
 {
 	unsigned long flags = IRQF_TRIGGER_FALLING | IRQF_ONESHOT;
-	struct irq_desc *desc;
 	int i, ret;
 	int __irq;
 
@@ -544,19 +543,18 @@
 	mutex_init(&chip->irq_lock);
 	chip->core_irq = irq;
 	chip->irq_base = pdata->irq_base;
-	desc = irq_to_desc(chip->core_irq);
 
 	/* register with genirq */
 	for (i = 0; i < ARRAY_SIZE(max8925_irqs); i++) {
 		__irq = i + chip->irq_base;
-		set_irq_chip_data(__irq, chip);
-		set_irq_chip_and_handler(__irq, &max8925_irq_chip,
+		irq_set_chip_data(__irq, chip);
+		irq_set_chip_and_handler(__irq, &max8925_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(__irq, 1);
+		irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(__irq, IRQF_VALID);
 #else
-		set_irq_noprobe(__irq);
+		irq_set_noprobe(__irq);
 #endif
 	}
 	if (!irq) {
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/max8997.c linux-libre-2.6.39-gnu/drivers/mfd/max8997.c
--- linux-libre-2.6.38-gnu/drivers/mfd/max8997.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/max8997.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,427 @@
+/*
+ * max8997.c - mfd core driver for the Maxim 8966 and 8997
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@smasung.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
+ *
+ * This driver is based on max8998.c
+ */
+
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/mutex.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+
+#define I2C_ADDR_PMIC	(0xCC >> 1)
+#define I2C_ADDR_MUIC	(0x4A >> 1)
+#define I2C_ADDR_BATTERY	(0x6C >> 1)
+#define I2C_ADDR_RTC	(0x0C >> 1)
+#define I2C_ADDR_HAPTIC	(0x90 >> 1)
+
+static struct mfd_cell max8997_devs[] = {
+	{ .name = "max8997-pmic", },
+	{ .name = "max8997-rtc", },
+	{ .name = "max8997-battery", },
+	{ .name = "max8997-haptic", },
+	{ .name = "max8997-muic", },
+	{ .name = "max8997-flash", },
+};
+
+int max8997_read_reg(struct i2c_client *i2c, u8 reg, u8 *dest)
+{
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&max8997->iolock);
+	ret = i2c_smbus_read_byte_data(i2c, reg);
+	mutex_unlock(&max8997->iolock);
+	if (ret < 0)
+		return ret;
+
+	ret &= 0xff;
+	*dest = ret;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(max8997_read_reg);
+
+int max8997_bulk_read(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
+{
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&max8997->iolock);
+	ret = i2c_smbus_read_i2c_block_data(i2c, reg, count, buf);
+	mutex_unlock(&max8997->iolock);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(max8997_bulk_read);
+
+int max8997_write_reg(struct i2c_client *i2c, u8 reg, u8 value)
+{
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&max8997->iolock);
+	ret = i2c_smbus_write_byte_data(i2c, reg, value);
+	mutex_unlock(&max8997->iolock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(max8997_write_reg);
+
+int max8997_bulk_write(struct i2c_client *i2c, u8 reg, int count, u8 *buf)
+{
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&max8997->iolock);
+	ret = i2c_smbus_write_i2c_block_data(i2c, reg, count, buf);
+	mutex_unlock(&max8997->iolock);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(max8997_bulk_write);
+
+int max8997_update_reg(struct i2c_client *i2c, u8 reg, u8 val, u8 mask)
+{
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int ret;
+
+	mutex_lock(&max8997->iolock);
+	ret = i2c_smbus_read_byte_data(i2c, reg);
+	if (ret >= 0) {
+		u8 old_val = ret & 0xff;
+		u8 new_val = (val & mask) | (old_val & (~mask));
+		ret = i2c_smbus_write_byte_data(i2c, reg, new_val);
+	}
+	mutex_unlock(&max8997->iolock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(max8997_update_reg);
+
+static int max8997_i2c_probe(struct i2c_client *i2c,
+			    const struct i2c_device_id *id)
+{
+	struct max8997_dev *max8997;
+	struct max8997_platform_data *pdata = i2c->dev.platform_data;
+	int ret = 0;
+
+	max8997 = kzalloc(sizeof(struct max8997_dev), GFP_KERNEL);
+	if (max8997 == NULL)
+		return -ENOMEM;
+
+	i2c_set_clientdata(i2c, max8997);
+	max8997->dev = &i2c->dev;
+	max8997->i2c = i2c;
+	max8997->type = id->driver_data;
+
+	if (!pdata)
+		goto err;
+
+	max8997->wakeup = pdata->wakeup;
+
+	mutex_init(&max8997->iolock);
+
+	max8997->rtc = i2c_new_dummy(i2c->adapter, I2C_ADDR_RTC);
+	i2c_set_clientdata(max8997->rtc, max8997);
+	max8997->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
+	i2c_set_clientdata(max8997->haptic, max8997);
+	max8997->muic = i2c_new_dummy(i2c->adapter, I2C_ADDR_MUIC);
+	i2c_set_clientdata(max8997->muic, max8997);
+
+	pm_runtime_set_active(max8997->dev);
+
+	mfd_add_devices(max8997->dev, -1, max8997_devs,
+			ARRAY_SIZE(max8997_devs),
+			NULL, 0);
+
+	/*
+	 * TODO: enable others (flash, muic, rtc, battery, ...) and
+	 * check the return value
+	 */
+
+	if (ret < 0)
+		goto err_mfd;
+
+	return ret;
+
+err_mfd:
+	mfd_remove_devices(max8997->dev);
+	i2c_unregister_device(max8997->muic);
+	i2c_unregister_device(max8997->haptic);
+	i2c_unregister_device(max8997->rtc);
+err:
+	kfree(max8997);
+	return ret;
+}
+
+static int max8997_i2c_remove(struct i2c_client *i2c)
+{
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+
+	mfd_remove_devices(max8997->dev);
+	i2c_unregister_device(max8997->muic);
+	i2c_unregister_device(max8997->haptic);
+	i2c_unregister_device(max8997->rtc);
+	kfree(max8997);
+
+	return 0;
+}
+
+static const struct i2c_device_id max8997_i2c_id[] = {
+	{ "max8997", TYPE_MAX8997 },
+	{ "max8966", TYPE_MAX8966 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, max8998_i2c_id);
+
+u8 max8997_dumpaddr_pmic[] = {
+	MAX8997_REG_INT1MSK,
+	MAX8997_REG_INT2MSK,
+	MAX8997_REG_INT3MSK,
+	MAX8997_REG_INT4MSK,
+	MAX8997_REG_MAINCON1,
+	MAX8997_REG_MAINCON2,
+	MAX8997_REG_BUCKRAMP,
+	MAX8997_REG_BUCK1CTRL,
+	MAX8997_REG_BUCK1DVS1,
+	MAX8997_REG_BUCK1DVS2,
+	MAX8997_REG_BUCK1DVS3,
+	MAX8997_REG_BUCK1DVS4,
+	MAX8997_REG_BUCK1DVS5,
+	MAX8997_REG_BUCK1DVS6,
+	MAX8997_REG_BUCK1DVS7,
+	MAX8997_REG_BUCK1DVS8,
+	MAX8997_REG_BUCK2CTRL,
+	MAX8997_REG_BUCK2DVS1,
+	MAX8997_REG_BUCK2DVS2,
+	MAX8997_REG_BUCK2DVS3,
+	MAX8997_REG_BUCK2DVS4,
+	MAX8997_REG_BUCK2DVS5,
+	MAX8997_REG_BUCK2DVS6,
+	MAX8997_REG_BUCK2DVS7,
+	MAX8997_REG_BUCK2DVS8,
+	MAX8997_REG_BUCK3CTRL,
+	MAX8997_REG_BUCK3DVS,
+	MAX8997_REG_BUCK4CTRL,
+	MAX8997_REG_BUCK4DVS,
+	MAX8997_REG_BUCK5CTRL,
+	MAX8997_REG_BUCK5DVS1,
+	MAX8997_REG_BUCK5DVS2,
+	MAX8997_REG_BUCK5DVS3,
+	MAX8997_REG_BUCK5DVS4,
+	MAX8997_REG_BUCK5DVS5,
+	MAX8997_REG_BUCK5DVS6,
+	MAX8997_REG_BUCK5DVS7,
+	MAX8997_REG_BUCK5DVS8,
+	MAX8997_REG_BUCK6CTRL,
+	MAX8997_REG_BUCK6BPSKIPCTRL,
+	MAX8997_REG_BUCK7CTRL,
+	MAX8997_REG_BUCK7DVS,
+	MAX8997_REG_LDO1CTRL,
+	MAX8997_REG_LDO2CTRL,
+	MAX8997_REG_LDO3CTRL,
+	MAX8997_REG_LDO4CTRL,
+	MAX8997_REG_LDO5CTRL,
+	MAX8997_REG_LDO6CTRL,
+	MAX8997_REG_LDO7CTRL,
+	MAX8997_REG_LDO8CTRL,
+	MAX8997_REG_LDO9CTRL,
+	MAX8997_REG_LDO10CTRL,
+	MAX8997_REG_LDO11CTRL,
+	MAX8997_REG_LDO12CTRL,
+	MAX8997_REG_LDO13CTRL,
+	MAX8997_REG_LDO14CTRL,
+	MAX8997_REG_LDO15CTRL,
+	MAX8997_REG_LDO16CTRL,
+	MAX8997_REG_LDO17CTRL,
+	MAX8997_REG_LDO18CTRL,
+	MAX8997_REG_LDO21CTRL,
+	MAX8997_REG_MBCCTRL1,
+	MAX8997_REG_MBCCTRL2,
+	MAX8997_REG_MBCCTRL3,
+	MAX8997_REG_MBCCTRL4,
+	MAX8997_REG_MBCCTRL5,
+	MAX8997_REG_MBCCTRL6,
+	MAX8997_REG_OTPCGHCVS,
+	MAX8997_REG_SAFEOUTCTRL,
+	MAX8997_REG_LBCNFG1,
+	MAX8997_REG_LBCNFG2,
+	MAX8997_REG_BBCCTRL,
+
+	MAX8997_REG_FLASH1_CUR,
+	MAX8997_REG_FLASH2_CUR,
+	MAX8997_REG_MOVIE_CUR,
+	MAX8997_REG_GSMB_CUR,
+	MAX8997_REG_BOOST_CNTL,
+	MAX8997_REG_LEN_CNTL,
+	MAX8997_REG_FLASH_CNTL,
+	MAX8997_REG_WDT_CNTL,
+	MAX8997_REG_MAXFLASH1,
+	MAX8997_REG_MAXFLASH2,
+	MAX8997_REG_FLASHSTATUSMASK,
+
+	MAX8997_REG_GPIOCNTL1,
+	MAX8997_REG_GPIOCNTL2,
+	MAX8997_REG_GPIOCNTL3,
+	MAX8997_REG_GPIOCNTL4,
+	MAX8997_REG_GPIOCNTL5,
+	MAX8997_REG_GPIOCNTL6,
+	MAX8997_REG_GPIOCNTL7,
+	MAX8997_REG_GPIOCNTL8,
+	MAX8997_REG_GPIOCNTL9,
+	MAX8997_REG_GPIOCNTL10,
+	MAX8997_REG_GPIOCNTL11,
+	MAX8997_REG_GPIOCNTL12,
+
+	MAX8997_REG_LDO1CONFIG,
+	MAX8997_REG_LDO2CONFIG,
+	MAX8997_REG_LDO3CONFIG,
+	MAX8997_REG_LDO4CONFIG,
+	MAX8997_REG_LDO5CONFIG,
+	MAX8997_REG_LDO6CONFIG,
+	MAX8997_REG_LDO7CONFIG,
+	MAX8997_REG_LDO8CONFIG,
+	MAX8997_REG_LDO9CONFIG,
+	MAX8997_REG_LDO10CONFIG,
+	MAX8997_REG_LDO11CONFIG,
+	MAX8997_REG_LDO12CONFIG,
+	MAX8997_REG_LDO13CONFIG,
+	MAX8997_REG_LDO14CONFIG,
+	MAX8997_REG_LDO15CONFIG,
+	MAX8997_REG_LDO16CONFIG,
+	MAX8997_REG_LDO17CONFIG,
+	MAX8997_REG_LDO18CONFIG,
+	MAX8997_REG_LDO21CONFIG,
+
+	MAX8997_REG_DVSOKTIMER1,
+	MAX8997_REG_DVSOKTIMER2,
+	MAX8997_REG_DVSOKTIMER4,
+	MAX8997_REG_DVSOKTIMER5,
+};
+
+u8 max8997_dumpaddr_muic[] = {
+	MAX8997_MUIC_REG_INTMASK1,
+	MAX8997_MUIC_REG_INTMASK2,
+	MAX8997_MUIC_REG_INTMASK3,
+	MAX8997_MUIC_REG_CDETCTRL,
+	MAX8997_MUIC_REG_CONTROL1,
+	MAX8997_MUIC_REG_CONTROL2,
+	MAX8997_MUIC_REG_CONTROL3,
+};
+
+u8 max8997_dumpaddr_haptic[] = {
+	MAX8997_HAPTIC_REG_CONF1,
+	MAX8997_HAPTIC_REG_CONF2,
+	MAX8997_HAPTIC_REG_DRVCONF,
+	MAX8997_HAPTIC_REG_CYCLECONF1,
+	MAX8997_HAPTIC_REG_CYCLECONF2,
+	MAX8997_HAPTIC_REG_SIGCONF1,
+	MAX8997_HAPTIC_REG_SIGCONF2,
+	MAX8997_HAPTIC_REG_SIGCONF3,
+	MAX8997_HAPTIC_REG_SIGCONF4,
+	MAX8997_HAPTIC_REG_SIGDC1,
+	MAX8997_HAPTIC_REG_SIGDC2,
+	MAX8997_HAPTIC_REG_SIGPWMDC1,
+	MAX8997_HAPTIC_REG_SIGPWMDC2,
+	MAX8997_HAPTIC_REG_SIGPWMDC3,
+	MAX8997_HAPTIC_REG_SIGPWMDC4,
+};
+
+static int max8997_freeze(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
+		max8997_read_reg(i2c, max8997_dumpaddr_pmic[i],
+				&max8997->reg_dump[i]);
+
+	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
+		max8997_read_reg(i2c, max8997_dumpaddr_muic[i],
+				&max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
+
+	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
+		max8997_read_reg(i2c, max8997_dumpaddr_haptic[i],
+				&max8997->reg_dump[i + MAX8997_REG_PMIC_END +
+				MAX8997_MUIC_REG_END]);
+
+	return 0;
+}
+
+static int max8997_restore(struct device *dev)
+{
+	struct i2c_client *i2c = container_of(dev, struct i2c_client, dev);
+	struct max8997_dev *max8997 = i2c_get_clientdata(i2c);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_pmic); i++)
+		max8997_write_reg(i2c, max8997_dumpaddr_pmic[i],
+				max8997->reg_dump[i]);
+
+	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_muic); i++)
+		max8997_write_reg(i2c, max8997_dumpaddr_muic[i],
+				max8997->reg_dump[i + MAX8997_REG_PMIC_END]);
+
+	for (i = 0; i < ARRAY_SIZE(max8997_dumpaddr_haptic); i++)
+		max8997_write_reg(i2c, max8997_dumpaddr_haptic[i],
+				max8997->reg_dump[i + MAX8997_REG_PMIC_END +
+				MAX8997_MUIC_REG_END]);
+
+	return 0;
+}
+
+const struct dev_pm_ops max8997_pm = {
+	.freeze = max8997_freeze,
+	.restore = max8997_restore,
+};
+
+static struct i2c_driver max8997_i2c_driver = {
+	.driver = {
+		   .name = "max8997",
+		   .owner = THIS_MODULE,
+		   .pm = &max8997_pm,
+	},
+	.probe = max8997_i2c_probe,
+	.remove = max8997_i2c_remove,
+	.id_table = max8997_i2c_id,
+};
+
+static int __init max8997_i2c_init(void)
+{
+	return i2c_add_driver(&max8997_i2c_driver);
+}
+/* init early so consumer devices can complete system boot */
+subsys_initcall(max8997_i2c_init);
+
+static void __exit max8997_i2c_exit(void)
+{
+	i2c_del_driver(&max8997_i2c_driver);
+}
+module_exit(max8997_i2c_exit);
+
+MODULE_DESCRIPTION("MAXIM 8997 multi-function core driver");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/max8997-irq.c linux-libre-2.6.39-gnu/drivers/mfd/max8997-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/max8997-irq.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/max8997-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,377 @@
+/*
+ * max8997-irq.c - Interrupt controller support for MAX8997
+ *
+ * Copyright (C) 2011 Samsung Electronics Co.Ltd
+ * MyungJoo Ham <myungjoo.ham@samsung.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
+ *
+ * This driver is based on max8998-irq.c
+ */
+
+#include <linux/err.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+
+static const u8 max8997_mask_reg[] = {
+	[PMIC_INT1] = MAX8997_REG_INT1MSK,
+	[PMIC_INT2] = MAX8997_REG_INT2MSK,
+	[PMIC_INT3] = MAX8997_REG_INT3MSK,
+	[PMIC_INT4] = MAX8997_REG_INT4MSK,
+	[FUEL_GAUGE] = MAX8997_REG_INVALID,
+	[MUIC_INT1] = MAX8997_MUIC_REG_INTMASK1,
+	[MUIC_INT2] = MAX8997_MUIC_REG_INTMASK2,
+	[MUIC_INT3] = MAX8997_MUIC_REG_INTMASK3,
+	[GPIO_LOW] = MAX8997_REG_INVALID,
+	[GPIO_HI] = MAX8997_REG_INVALID,
+	[FLASH_STATUS] = MAX8997_REG_INVALID,
+};
+
+static struct i2c_client *get_i2c(struct max8997_dev *max8997,
+				enum max8997_irq_source src)
+{
+	switch (src) {
+	case PMIC_INT1 ... PMIC_INT4:
+		return max8997->i2c;
+	case FUEL_GAUGE:
+		return NULL;
+	case MUIC_INT1 ... MUIC_INT3:
+		return max8997->muic;
+	case GPIO_LOW ... GPIO_HI:
+		return max8997->i2c;
+	case FLASH_STATUS:
+		return max8997->i2c;
+	default:
+		return ERR_PTR(-EINVAL);
+	}
+
+	return ERR_PTR(-EINVAL);
+}
+
+struct max8997_irq_data {
+	int mask;
+	enum max8997_irq_source group;
+};
+
+#define DECLARE_IRQ(idx, _group, _mask)		\
+	[(idx)] = { .group = (_group), .mask = (_mask) }
+static const struct max8997_irq_data max8997_irqs[] = {
+	DECLARE_IRQ(MAX8997_PMICIRQ_PWRONR,	PMIC_INT1, 1 << 0),
+	DECLARE_IRQ(MAX8997_PMICIRQ_PWRONF,	PMIC_INT1, 1 << 1),
+	DECLARE_IRQ(MAX8997_PMICIRQ_PWRON1SEC,	PMIC_INT1, 1 << 3),
+	DECLARE_IRQ(MAX8997_PMICIRQ_JIGONR,	PMIC_INT1, 1 << 4),
+	DECLARE_IRQ(MAX8997_PMICIRQ_JIGONF,	PMIC_INT1, 1 << 5),
+	DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT2,	PMIC_INT1, 1 << 6),
+	DECLARE_IRQ(MAX8997_PMICIRQ_LOWBAT1,	PMIC_INT1, 1 << 7),
+
+	DECLARE_IRQ(MAX8997_PMICIRQ_JIGR,	PMIC_INT2, 1 << 0),
+	DECLARE_IRQ(MAX8997_PMICIRQ_JIGF,	PMIC_INT2, 1 << 1),
+	DECLARE_IRQ(MAX8997_PMICIRQ_MR,		PMIC_INT2, 1 << 2),
+	DECLARE_IRQ(MAX8997_PMICIRQ_DVS1OK,	PMIC_INT2, 1 << 3),
+	DECLARE_IRQ(MAX8997_PMICIRQ_DVS2OK,	PMIC_INT2, 1 << 4),
+	DECLARE_IRQ(MAX8997_PMICIRQ_DVS3OK,	PMIC_INT2, 1 << 5),
+	DECLARE_IRQ(MAX8997_PMICIRQ_DVS4OK,	PMIC_INT2, 1 << 6),
+
+	DECLARE_IRQ(MAX8997_PMICIRQ_CHGINS,	PMIC_INT3, 1 << 0),
+	DECLARE_IRQ(MAX8997_PMICIRQ_CHGRM,	PMIC_INT3, 1 << 1),
+	DECLARE_IRQ(MAX8997_PMICIRQ_DCINOVP,	PMIC_INT3, 1 << 2),
+	DECLARE_IRQ(MAX8997_PMICIRQ_TOPOFFR,	PMIC_INT3, 1 << 3),
+	DECLARE_IRQ(MAX8997_PMICIRQ_CHGRSTF,	PMIC_INT3, 1 << 5),
+	DECLARE_IRQ(MAX8997_PMICIRQ_MBCHGTMEXPD,	PMIC_INT3, 1 << 7),
+
+	DECLARE_IRQ(MAX8997_PMICIRQ_RTC60S,	PMIC_INT4, 1 << 0),
+	DECLARE_IRQ(MAX8997_PMICIRQ_RTCA1,	PMIC_INT4, 1 << 1),
+	DECLARE_IRQ(MAX8997_PMICIRQ_RTCA2,	PMIC_INT4, 1 << 2),
+	DECLARE_IRQ(MAX8997_PMICIRQ_SMPL_INT,	PMIC_INT4, 1 << 3),
+	DECLARE_IRQ(MAX8997_PMICIRQ_RTC1S,	PMIC_INT4, 1 << 4),
+	DECLARE_IRQ(MAX8997_PMICIRQ_WTSR,	PMIC_INT4, 1 << 5),
+
+	DECLARE_IRQ(MAX8997_MUICIRQ_ADCError,	MUIC_INT1, 1 << 2),
+	DECLARE_IRQ(MAX8997_MUICIRQ_ADCLow,	MUIC_INT1, 1 << 1),
+	DECLARE_IRQ(MAX8997_MUICIRQ_ADC,	MUIC_INT1, 1 << 0),
+
+	DECLARE_IRQ(MAX8997_MUICIRQ_VBVolt,	MUIC_INT2, 1 << 4),
+	DECLARE_IRQ(MAX8997_MUICIRQ_DBChg,	MUIC_INT2, 1 << 3),
+	DECLARE_IRQ(MAX8997_MUICIRQ_DCDTmr,	MUIC_INT2, 1 << 2),
+	DECLARE_IRQ(MAX8997_MUICIRQ_ChgDetRun,	MUIC_INT2, 1 << 1),
+	DECLARE_IRQ(MAX8997_MUICIRQ_ChgTyp,	MUIC_INT2, 1 << 0),
+
+	DECLARE_IRQ(MAX8997_MUICIRQ_OVP,	MUIC_INT3, 1 << 2),
+};
+
+static void max8997_irq_lock(struct irq_data *data)
+{
+	struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+
+	mutex_lock(&max8997->irqlock);
+}
+
+static void max8997_irq_sync_unlock(struct irq_data *data)
+{
+	struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+	int i;
+
+	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
+		u8 mask_reg = max8997_mask_reg[i];
+		struct i2c_client *i2c = get_i2c(max8997, i);
+
+		if (mask_reg == MAX8997_REG_INVALID ||
+				IS_ERR_OR_NULL(i2c))
+			continue;
+		max8997->irq_masks_cache[i] = max8997->irq_masks_cur[i];
+
+		max8997_write_reg(i2c, max8997_mask_reg[i],
+				max8997->irq_masks_cur[i]);
+	}
+
+	mutex_unlock(&max8997->irqlock);
+}
+
+static const inline struct max8997_irq_data *
+irq_to_max8997_irq(struct max8997_dev *max8997, int irq)
+{
+	return &max8997_irqs[irq - max8997->irq_base];
+}
+
+static void max8997_irq_mask(struct irq_data *data)
+{
+	struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+	const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
+								data->irq);
+
+	max8997->irq_masks_cur[irq_data->group] |= irq_data->mask;
+}
+
+static void max8997_irq_unmask(struct irq_data *data)
+{
+	struct max8997_dev *max8997 = irq_get_chip_data(data->irq);
+	const struct max8997_irq_data *irq_data = irq_to_max8997_irq(max8997,
+								data->irq);
+
+	max8997->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
+}
+
+static struct irq_chip max8997_irq_chip = {
+	.name			= "max8997",
+	.irq_bus_lock		= max8997_irq_lock,
+	.irq_bus_sync_unlock	= max8997_irq_sync_unlock,
+	.irq_mask		= max8997_irq_mask,
+	.irq_unmask		= max8997_irq_unmask,
+};
+
+#define MAX8997_IRQSRC_PMIC		(1 << 1)
+#define MAX8997_IRQSRC_FUELGAUGE	(1 << 2)
+#define MAX8997_IRQSRC_MUIC		(1 << 3)
+#define MAX8997_IRQSRC_GPIO		(1 << 4)
+#define MAX8997_IRQSRC_FLASH		(1 << 5)
+static irqreturn_t max8997_irq_thread(int irq, void *data)
+{
+	struct max8997_dev *max8997 = data;
+	u8 irq_reg[MAX8997_IRQ_GROUP_NR] = {};
+	u8 irq_src;
+	int ret;
+	int i;
+
+	ret = max8997_read_reg(max8997->i2c, MAX8997_REG_INTSRC, &irq_src);
+	if (ret < 0) {
+		dev_err(max8997->dev, "Failed to read interrupt source: %d\n",
+				ret);
+		return IRQ_NONE;
+	}
+
+	if (irq_src & MAX8997_IRQSRC_PMIC) {
+		/* PMIC INT1 ~ INT4 */
+		max8997_bulk_read(max8997->i2c, MAX8997_REG_INT1, 4,
+				&irq_reg[PMIC_INT1]);
+	}
+	if (irq_src & MAX8997_IRQSRC_FUELGAUGE) {
+		/*
+		 * TODO: FUEL GAUGE
+		 *
+		 * This is to be supported by Max17042 driver. When
+		 * an interrupt incurs here, it should be relayed to a
+		 * Max17042 device that is connected (probably by
+		 * platform-data). However, we do not have interrupt
+		 * handling in Max17042 driver currently. The Max17042 IRQ
+		 * driver should be ready to be used as a stand-alone device and
+		 * a Max8997-dependent device. Because it is not ready in
+		 * Max17042-side and it is not too critical in operating
+		 * Max8997, we do not implement this in initial releases.
+		 */
+		irq_reg[FUEL_GAUGE] = 0;
+	}
+	if (irq_src & MAX8997_IRQSRC_MUIC) {
+		/* MUIC INT1 ~ INT3 */
+		max8997_bulk_read(max8997->muic, MAX8997_MUIC_REG_INT1, 3,
+				&irq_reg[MUIC_INT1]);
+	}
+	if (irq_src & MAX8997_IRQSRC_GPIO) {
+		/* GPIO Interrupt */
+		u8 gpio_info[MAX8997_NUM_GPIO];
+
+		irq_reg[GPIO_LOW] = 0;
+		irq_reg[GPIO_HI] = 0;
+
+		max8997_bulk_read(max8997->i2c, MAX8997_REG_GPIOCNTL1,
+				MAX8997_NUM_GPIO, gpio_info);
+		for (i = 0; i < MAX8997_NUM_GPIO; i++) {
+			bool interrupt = false;
+
+			switch (gpio_info[i] & MAX8997_GPIO_INT_MASK) {
+			case MAX8997_GPIO_INT_BOTH:
+				if (max8997->gpio_status[i] != gpio_info[i])
+					interrupt = true;
+				break;
+			case MAX8997_GPIO_INT_RISE:
+				if ((max8997->gpio_status[i] != gpio_info[i]) &&
+				    (gpio_info[i] & MAX8997_GPIO_DATA_MASK))
+					interrupt = true;
+				break;
+			case MAX8997_GPIO_INT_FALL:
+				if ((max8997->gpio_status[i] != gpio_info[i]) &&
+				    !(gpio_info[i] & MAX8997_GPIO_DATA_MASK))
+					interrupt = true;
+				break;
+			default:
+				break;
+			}
+
+			if (interrupt) {
+				if (i < 8)
+					irq_reg[GPIO_LOW] |= (1 << i);
+				else
+					irq_reg[GPIO_HI] |= (1 << (i - 8));
+			}
+
+		}
+	}
+	if (irq_src & MAX8997_IRQSRC_FLASH) {
+		/* Flash Status Interrupt */
+		ret = max8997_read_reg(max8997->i2c, MAX8997_REG_FLASHSTATUS,
+				&irq_reg[FLASH_STATUS]);
+	}
+
+	/* Apply masking */
+	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++)
+		irq_reg[i] &= ~max8997->irq_masks_cur[i];
+
+	/* Report */
+	for (i = 0; i < MAX8997_IRQ_NR; i++) {
+		if (irq_reg[max8997_irqs[i].group] & max8997_irqs[i].mask)
+			handle_nested_irq(max8997->irq_base + i);
+	}
+
+	return IRQ_HANDLED;
+}
+
+int max8997_irq_resume(struct max8997_dev *max8997)
+{
+	if (max8997->irq && max8997->irq_base)
+		max8997_irq_thread(max8997->irq_base, max8997);
+	return 0;
+}
+
+int max8997_irq_init(struct max8997_dev *max8997)
+{
+	int i;
+	int cur_irq;
+	int ret;
+	u8 val;
+
+	if (!max8997->irq) {
+		dev_warn(max8997->dev, "No interrupt specified.\n");
+		max8997->irq_base = 0;
+		return 0;
+	}
+
+	if (!max8997->irq_base) {
+		dev_err(max8997->dev, "No interrupt base specified.\n");
+		return 0;
+	}
+
+	mutex_init(&max8997->irqlock);
+
+	/* Mask individual interrupt sources */
+	for (i = 0; i < MAX8997_IRQ_GROUP_NR; i++) {
+		struct i2c_client *i2c;
+
+		max8997->irq_masks_cur[i] = 0xff;
+		max8997->irq_masks_cache[i] = 0xff;
+		i2c = get_i2c(max8997, i);
+
+		if (IS_ERR_OR_NULL(i2c))
+			continue;
+		if (max8997_mask_reg[i] == MAX8997_REG_INVALID)
+			continue;
+
+		max8997_write_reg(i2c, max8997_mask_reg[i], 0xff);
+	}
+
+	for (i = 0; i < MAX8997_NUM_GPIO; i++) {
+		max8997->gpio_status[i] = (max8997_read_reg(max8997->i2c,
+						MAX8997_REG_GPIOCNTL1 + i,
+						&val)
+					& MAX8997_GPIO_DATA_MASK) ?
+					true : false;
+	}
+
+	/* Register with genirq */
+	for (i = 0; i < MAX8997_IRQ_NR; i++) {
+		cur_irq = i + max8997->irq_base;
+		irq_set_chip_data(cur_irq, max8997);
+		irq_set_chip_and_handler(cur_irq, &max8997_irq_chip,
+				handle_edge_irq);
+		irq_set_nested_thread(cur_irq, 1);
+#ifdef CONFIG_ARM
+		set_irq_flags(cur_irq, IRQF_VALID);
+#else
+		irq_set_noprobe(cur_irq);
+#endif
+	}
+
+	ret = request_threaded_irq(max8997->irq, NULL, max8997_irq_thread,
+			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+			"max8997-irq", max8997);
+
+	if (ret) {
+		dev_err(max8997->dev, "Failed to request IRQ %d: %d\n",
+				max8997->irq, ret);
+		return ret;
+	}
+
+	if (!max8997->ono)
+		return 0;
+
+	ret = request_threaded_irq(max8997->ono, NULL, max8997_irq_thread,
+			IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING |
+			IRQF_ONESHOT, "max8997-ono", max8997);
+
+	if (ret)
+		dev_err(max8997->dev, "Failed to request ono-IRQ %d: %d\n",
+				max8997->ono, ret);
+
+	return 0;
+}
+
+void max8997_irq_exit(struct max8997_dev *max8997)
+{
+	if (max8997->ono)
+		free_irq(max8997->ono, max8997);
+
+	if (max8997->irq)
+		free_irq(max8997->irq, max8997);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/max8998.c linux-libre-2.6.39-gnu/drivers/mfd/max8998.c
--- linux-libre-2.6.38-gnu/drivers/mfd/max8998.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/max8998.c	2011-05-19 00:06:34.000000000 -0400
@@ -209,7 +209,7 @@
 	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
 
 	if (max8998->wakeup)
-		set_irq_wake(max8998->irq, 1);
+		irq_set_irq_wake(max8998->irq, 1);
 	return 0;
 }
 
@@ -219,7 +219,7 @@
 	struct max8998_dev *max8998 = i2c_get_clientdata(i2c);
 
 	if (max8998->wakeup)
-		set_irq_wake(max8998->irq, 0);
+		irq_set_irq_wake(max8998->irq, 0);
 	/*
 	 * In LP3974, if IRQ registers are not "read & clear"
 	 * when it's set during sleep, the interrupt becomes
@@ -233,7 +233,7 @@
 	u8	val;
 };
 #define SAVE_ITEM(x)	{ .addr = (x), .val = 0x0, }
-struct max8998_reg_dump max8998_dump[] = {
+static struct max8998_reg_dump max8998_dump[] = {
 	SAVE_ITEM(MAX8998_REG_IRQM1),
 	SAVE_ITEM(MAX8998_REG_IRQM2),
 	SAVE_ITEM(MAX8998_REG_IRQM3),
@@ -298,7 +298,7 @@
 	return 0;
 }
 
-const struct dev_pm_ops max8998_pm = {
+static const struct dev_pm_ops max8998_pm = {
 	.suspend = max8998_suspend,
 	.resume = max8998_resume,
 	.freeze = max8998_freeze,
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/max8998-irq.c linux-libre-2.6.39-gnu/drivers/mfd/max8998-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/max8998-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/max8998-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -224,14 +224,14 @@
 	/* register with genirq */
 	for (i = 0; i < MAX8998_IRQ_NR; i++) {
 		cur_irq = i + max8998->irq_base;
-		set_irq_chip_data(cur_irq, max8998);
-		set_irq_chip_and_handler(cur_irq, &max8998_irq_chip,
+		irq_set_chip_data(cur_irq, max8998);
+		irq_set_chip_and_handler(cur_irq, &max8998_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(cur_irq, 1);
+		irq_set_nested_thread(cur_irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(cur_irq, IRQF_VALID);
 #else
-		set_irq_noprobe(cur_irq);
+		irq_set_noprobe(cur_irq);
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/mc13xxx-core.c linux-libre-2.6.39-gnu/drivers/mfd/mc13xxx-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/mc13xxx-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/mc13xxx-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -683,14 +683,13 @@
 EXPORT_SYMBOL_GPL(mc13783_adc_do_conversion);
 
 static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
-		const char *format, void *pdata, size_t pdata_size)
+		const char *format, void *pdata)
 {
 	char buf[30];
 	const char *name = mc13xxx_get_chipname(mc13xxx);
 
 	struct mfd_cell cell = {
-		.platform_data = pdata,
-		.data_size = pdata_size,
+		.mfd_data = pdata,
 	};
 
 	/* there is no asnprintf in the kernel :-( */
@@ -706,7 +705,7 @@
 
 static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
 {
-	return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL, 0);
+	return mc13xxx_add_subdevice_pdata(mc13xxx, format, NULL);
 }
 
 static int mc13xxx_probe(struct spi_device *spi)
@@ -764,13 +763,8 @@
 		mc13xxx_add_subdevice(mc13xxx, "%s-codec");
 
 	if (pdata->flags & MC13XXX_USE_REGULATOR) {
-		struct mc13xxx_regulator_platform_data regulator_pdata = {
-			.num_regulators = pdata->num_regulators,
-			.regulators = pdata->regulators,
-		};
-
 		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-regulator",
-				&regulator_pdata, sizeof(regulator_pdata));
+				&pdata->regulators);
 	}
 
 	if (pdata->flags & MC13XXX_USE_RTC)
@@ -779,10 +773,8 @@
 	if (pdata->flags & MC13XXX_USE_TOUCHSCREEN)
 		mc13xxx_add_subdevice(mc13xxx, "%s-ts");
 
-	if (pdata->flags & MC13XXX_USE_LED) {
-		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led",
-					pdata->leds, sizeof(*pdata->leds));
-	}
+	if (pdata->flags & MC13XXX_USE_LED)
+		mc13xxx_add_subdevice_pdata(mc13xxx, "%s-led", pdata->leds);
 
 	return 0;
 }
@@ -811,6 +803,7 @@
 		/* sentinel */
 	}
 };
+MODULE_DEVICE_TABLE(spi, mc13xxx_device_id);
 
 static struct spi_driver mc13xxx_driver = {
 	.id_table = mc13xxx_device_id,
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/mfd-core.c linux-libre-2.6.39-gnu/drivers/mfd/mfd-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/mfd-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/mfd-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,56 @@
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
 
+int mfd_cell_enable(struct platform_device *pdev)
+{
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	int err = 0;
+
+	/* only call enable hook if the cell wasn't previously enabled */
+	if (atomic_inc_return(cell->usage_count) == 1)
+		err = cell->enable(pdev);
+
+	/* if the enable hook failed, decrement counter to allow retries */
+	if (err)
+		atomic_dec(cell->usage_count);
+
+	return err;
+}
+EXPORT_SYMBOL(mfd_cell_enable);
+
+int mfd_cell_disable(struct platform_device *pdev)
+{
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	int err = 0;
+
+	/* only disable if no other clients are using it */
+	if (atomic_dec_return(cell->usage_count) == 0)
+		err = cell->disable(pdev);
+
+	/* if the disable hook failed, increment to allow retries */
+	if (err)
+		atomic_inc(cell->usage_count);
+
+	/* sanity check; did someone call disable too many times? */
+	WARN_ON(atomic_read(cell->usage_count) < 0);
+
+	return err;
+}
+EXPORT_SYMBOL(mfd_cell_disable);
+
+static int mfd_platform_add_cell(struct platform_device *pdev,
+				 const struct mfd_cell *cell)
+{
+	if (!cell)
+		return 0;
+
+	pdev->mfd_cell = kmemdup(cell, sizeof(*cell), GFP_KERNEL);
+	if (!pdev->mfd_cell)
+		return -ENOMEM;
+
+	return 0;
+}
+
 static int mfd_add_device(struct device *parent, int id,
 			  const struct mfd_cell *cell,
 			  struct resource *mem_base,
@@ -37,14 +87,10 @@
 		goto fail_device;
 
 	pdev->dev.parent = parent;
-	platform_set_drvdata(pdev, cell->driver_data);
 
-	if (cell->data_size) {
-		ret = platform_device_add_data(pdev,
-					cell->platform_data, cell->data_size);
-		if (ret)
-			goto fail_res;
-	}
+	ret = mfd_platform_add_cell(pdev, cell);
+	if (ret)
+		goto fail_res;
 
 	for (r = 0; r < cell->num_resources; r++) {
 		res[r].name = cell->resources[r].name;
@@ -90,7 +136,6 @@
 
 	return 0;
 
-/*	platform_device_del(pdev); */
 fail_res:
 	kfree(res);
 fail_device:
@@ -100,14 +145,22 @@
 }
 
 int mfd_add_devices(struct device *parent, int id,
-		    const struct mfd_cell *cells, int n_devs,
+		    struct mfd_cell *cells, int n_devs,
 		    struct resource *mem_base,
 		    int irq_base)
 {
 	int i;
 	int ret = 0;
+	atomic_t *cnts;
+
+	/* initialize reference counting for all cells */
+	cnts = kcalloc(sizeof(*cnts), n_devs, GFP_KERNEL);
+	if (!cnts)
+		return -ENOMEM;
 
 	for (i = 0; i < n_devs; i++) {
+		atomic_set(&cnts[i], 0);
+		cells[i].usage_count = &cnts[i];
 		ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
 		if (ret)
 			break;
@@ -120,17 +173,58 @@
 }
 EXPORT_SYMBOL(mfd_add_devices);
 
-static int mfd_remove_devices_fn(struct device *dev, void *unused)
+static int mfd_remove_devices_fn(struct device *dev, void *c)
 {
-	platform_device_unregister(to_platform_device(dev));
+	struct platform_device *pdev = to_platform_device(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	atomic_t **usage_count = c;
+
+	/* find the base address of usage_count pointers (for freeing) */
+	if (!*usage_count || (cell->usage_count < *usage_count))
+		*usage_count = cell->usage_count;
+
+	platform_device_unregister(pdev);
 	return 0;
 }
 
 void mfd_remove_devices(struct device *parent)
 {
-	device_for_each_child(parent, NULL, mfd_remove_devices_fn);
+	atomic_t *cnts = NULL;
+
+	device_for_each_child(parent, &cnts, mfd_remove_devices_fn);
+	kfree(cnts);
 }
 EXPORT_SYMBOL(mfd_remove_devices);
 
+int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
+{
+	struct mfd_cell cell_entry;
+	struct device *dev;
+	struct platform_device *pdev;
+	int i;
+
+	/* fetch the parent cell's device (should already be registered!) */
+	dev = bus_find_device_by_name(&platform_bus_type, NULL, cell);
+	if (!dev) {
+		printk(KERN_ERR "failed to find device for cell %s\n", cell);
+		return -ENODEV;
+	}
+	pdev = to_platform_device(dev);
+	memcpy(&cell_entry, mfd_get_cell(pdev), sizeof(cell_entry));
+
+	WARN_ON(!cell_entry.enable);
+
+	for (i = 0; i < n_clones; i++) {
+		cell_entry.name = clones[i];
+		/* don't give up if a single call fails; just report error */
+		if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
+			dev_err(dev, "failed to create platform device '%s'\n",
+					clones[i]);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(mfd_clone_cell);
+
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Ian Molton, Dmitry Baryshkov");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/omap-usb-host.c linux-libre-2.6.39-gnu/drivers/mfd/omap-usb-host.c
--- linux-libre-2.6.38-gnu/drivers/mfd/omap-usb-host.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/omap-usb-host.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1058 @@
+/**
+ * omap-usb-host.c - The USBHS core driver for OMAP EHCI & OHCI
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com
+ * Author: Keshava Munegowda <keshava_mgowda@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  of
+ * the 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, see <http://www.gnu.org/licenses/>.
+ */
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+#include <linux/dma-mapping.h>
+#include <linux/spinlock.h>
+#include <linux/gpio.h>
+#include <plat/usb.h>
+
+#define USBHS_DRIVER_NAME	"usbhs-omap"
+#define OMAP_EHCI_DEVICE	"ehci-omap"
+#define OMAP_OHCI_DEVICE	"ohci-omap3"
+
+/* OMAP USBHOST Register addresses  */
+
+/* TLL Register Set */
+#define	OMAP_USBTLL_REVISION				(0x00)
+#define	OMAP_USBTLL_SYSCONFIG				(0x10)
+#define	OMAP_USBTLL_SYSCONFIG_CACTIVITY			(1 << 8)
+#define	OMAP_USBTLL_SYSCONFIG_SIDLEMODE			(1 << 3)
+#define	OMAP_USBTLL_SYSCONFIG_ENAWAKEUP			(1 << 2)
+#define	OMAP_USBTLL_SYSCONFIG_SOFTRESET			(1 << 1)
+#define	OMAP_USBTLL_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define	OMAP_USBTLL_SYSSTATUS				(0x14)
+#define	OMAP_USBTLL_SYSSTATUS_RESETDONE			(1 << 0)
+
+#define	OMAP_USBTLL_IRQSTATUS				(0x18)
+#define	OMAP_USBTLL_IRQENABLE				(0x1C)
+
+#define	OMAP_TLL_SHARED_CONF				(0x30)
+#define	OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN		(1 << 6)
+#define	OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN		(1 << 5)
+#define	OMAP_TLL_SHARED_CONF_USB_DIVRATION		(1 << 2)
+#define	OMAP_TLL_SHARED_CONF_FCLK_REQ			(1 << 1)
+#define	OMAP_TLL_SHARED_CONF_FCLK_IS_ON			(1 << 0)
+
+#define	OMAP_TLL_CHANNEL_CONF(num)			(0x040 + 0x004 * num)
+#define OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT		24
+#define	OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF		(1 << 11)
+#define	OMAP_TLL_CHANNEL_CONF_ULPI_ULPIAUTOIDLE		(1 << 10)
+#define	OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE		(1 << 9)
+#define	OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE		(1 << 8)
+#define OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS		(1 << 1)
+#define	OMAP_TLL_CHANNEL_CONF_CHANEN			(1 << 0)
+
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0		0x0
+#define OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM		0x1
+#define OMAP_TLL_FSLSMODE_3PIN_PHY			0x2
+#define OMAP_TLL_FSLSMODE_4PIN_PHY			0x3
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0		0x4
+#define OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM		0x5
+#define OMAP_TLL_FSLSMODE_3PIN_TLL			0x6
+#define OMAP_TLL_FSLSMODE_4PIN_TLL			0x7
+#define OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0		0xA
+#define OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM		0xB
+
+#define	OMAP_TLL_ULPI_FUNCTION_CTRL(num)		(0x804 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INTERFACE_CTRL(num)		(0x807 + 0x100 * num)
+#define	OMAP_TLL_ULPI_OTG_CTRL(num)			(0x80A + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_EN_RISE(num)			(0x80D + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_EN_FALL(num)			(0x810 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_STATUS(num)			(0x813 + 0x100 * num)
+#define	OMAP_TLL_ULPI_INT_LATCH(num)			(0x814 + 0x100 * num)
+#define	OMAP_TLL_ULPI_DEBUG(num)			(0x815 + 0x100 * num)
+#define	OMAP_TLL_ULPI_SCRATCH_REGISTER(num)		(0x816 + 0x100 * num)
+
+#define OMAP_TLL_CHANNEL_COUNT				3
+#define OMAP_TLL_CHANNEL_1_EN_MASK			(1 << 0)
+#define OMAP_TLL_CHANNEL_2_EN_MASK			(1 << 1)
+#define OMAP_TLL_CHANNEL_3_EN_MASK			(1 << 2)
+
+/* UHH Register Set */
+#define	OMAP_UHH_REVISION				(0x00)
+#define	OMAP_UHH_SYSCONFIG				(0x10)
+#define	OMAP_UHH_SYSCONFIG_MIDLEMODE			(1 << 12)
+#define	OMAP_UHH_SYSCONFIG_CACTIVITY			(1 << 8)
+#define	OMAP_UHH_SYSCONFIG_SIDLEMODE			(1 << 3)
+#define	OMAP_UHH_SYSCONFIG_ENAWAKEUP			(1 << 2)
+#define	OMAP_UHH_SYSCONFIG_SOFTRESET			(1 << 1)
+#define	OMAP_UHH_SYSCONFIG_AUTOIDLE			(1 << 0)
+
+#define	OMAP_UHH_SYSSTATUS				(0x14)
+#define	OMAP_UHH_HOSTCONFIG				(0x40)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_BYPASS			(1 << 0)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS		(1 << 0)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS		(1 << 11)
+#define	OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS		(1 << 12)
+#define OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN		(1 << 2)
+#define OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN		(1 << 3)
+#define OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN		(1 << 4)
+#define OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN		(1 << 5)
+#define OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS		(1 << 8)
+#define OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS		(1 << 9)
+#define OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS		(1 << 10)
+#define OMAP4_UHH_HOSTCONFIG_APP_START_CLK		(1 << 31)
+
+/* OMAP4-specific defines */
+#define OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR		(3 << 2)
+#define OMAP4_UHH_SYSCONFIG_NOIDLE			(1 << 2)
+#define OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR		(3 << 4)
+#define OMAP4_UHH_SYSCONFIG_NOSTDBY			(1 << 4)
+#define OMAP4_UHH_SYSCONFIG_SOFTRESET			(1 << 0)
+
+#define OMAP4_P1_MODE_CLEAR				(3 << 16)
+#define OMAP4_P1_MODE_TLL				(1 << 16)
+#define OMAP4_P1_MODE_HSIC				(3 << 16)
+#define OMAP4_P2_MODE_CLEAR				(3 << 18)
+#define OMAP4_P2_MODE_TLL				(1 << 18)
+#define OMAP4_P2_MODE_HSIC				(3 << 18)
+
+#define OMAP_REV2_TLL_CHANNEL_COUNT			2
+
+#define	OMAP_UHH_DEBUG_CSR				(0x44)
+
+/* Values of UHH_REVISION - Note: these are not given in the TRM */
+#define OMAP_USBHS_REV1		0x00000010	/* OMAP3 */
+#define OMAP_USBHS_REV2		0x50700100	/* OMAP4 */
+
+#define is_omap_usbhs_rev1(x)	(x->usbhs_rev == OMAP_USBHS_REV1)
+#define is_omap_usbhs_rev2(x)	(x->usbhs_rev == OMAP_USBHS_REV2)
+
+#define is_ehci_phy_mode(x)	(x == OMAP_EHCI_PORT_MODE_PHY)
+#define is_ehci_tll_mode(x)	(x == OMAP_EHCI_PORT_MODE_TLL)
+#define is_ehci_hsic_mode(x)	(x == OMAP_EHCI_PORT_MODE_HSIC)
+
+
+struct usbhs_hcd_omap {
+	struct clk			*usbhost_ick;
+	struct clk			*usbhost_hs_fck;
+	struct clk			*usbhost_fs_fck;
+	struct clk			*xclk60mhsp1_ck;
+	struct clk			*xclk60mhsp2_ck;
+	struct clk			*utmi_p1_fck;
+	struct clk			*usbhost_p1_fck;
+	struct clk			*usbtll_p1_fck;
+	struct clk			*utmi_p2_fck;
+	struct clk			*usbhost_p2_fck;
+	struct clk			*usbtll_p2_fck;
+	struct clk			*init_60m_fclk;
+	struct clk			*usbtll_fck;
+	struct clk			*usbtll_ick;
+
+	void __iomem			*uhh_base;
+	void __iomem			*tll_base;
+
+	struct usbhs_omap_platform_data	platdata;
+
+	u32				usbhs_rev;
+	spinlock_t			lock;
+	int				count;
+};
+/*-------------------------------------------------------------------------*/
+
+const char usbhs_driver_name[] = USBHS_DRIVER_NAME;
+static u64 usbhs_dmamask = ~(u32)0;
+
+/*-------------------------------------------------------------------------*/
+
+static inline void usbhs_write(void __iomem *base, u32 reg, u32 val)
+{
+	__raw_writel(val, base + reg);
+}
+
+static inline u32 usbhs_read(void __iomem *base, u32 reg)
+{
+	return __raw_readl(base + reg);
+}
+
+static inline void usbhs_writeb(void __iomem *base, u8 reg, u8 val)
+{
+	__raw_writeb(val, base + reg);
+}
+
+static inline u8 usbhs_readb(void __iomem *base, u8 reg)
+{
+	return __raw_readb(base + reg);
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct platform_device *omap_usbhs_alloc_child(const char *name,
+			struct resource	*res, int num_resources, void *pdata,
+			size_t pdata_size, struct device *dev)
+{
+	struct platform_device	*child;
+	int			ret;
+
+	child = platform_device_alloc(name, 0);
+
+	if (!child) {
+		dev_err(dev, "platform_device_alloc %s failed\n", name);
+		goto err_end;
+	}
+
+	ret = platform_device_add_resources(child, res, num_resources);
+	if (ret) {
+		dev_err(dev, "platform_device_add_resources failed\n");
+		goto err_alloc;
+	}
+
+	ret = platform_device_add_data(child, pdata, pdata_size);
+	if (ret) {
+		dev_err(dev, "platform_device_add_data failed\n");
+		goto err_alloc;
+	}
+
+	child->dev.dma_mask		= &usbhs_dmamask;
+	child->dev.coherent_dma_mask	= 0xffffffff;
+	child->dev.parent		= dev;
+
+	ret = platform_device_add(child);
+	if (ret) {
+		dev_err(dev, "platform_device_add failed\n");
+		goto err_alloc;
+	}
+
+	return child;
+
+err_alloc:
+	platform_device_put(child);
+
+err_end:
+	return NULL;
+}
+
+static int omap_usbhs_alloc_children(struct platform_device *pdev)
+{
+	struct device				*dev = &pdev->dev;
+	struct usbhs_hcd_omap			*omap;
+	struct ehci_hcd_omap_platform_data	*ehci_data;
+	struct ohci_hcd_omap_platform_data	*ohci_data;
+	struct platform_device			*ehci;
+	struct platform_device			*ohci;
+	struct resource				*res;
+	struct resource				resources[2];
+	int					ret;
+
+	omap = platform_get_drvdata(pdev);
+	ehci_data = omap->platdata.ehci_data;
+	ohci_data = omap->platdata.ohci_data;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ehci");
+	if (!res) {
+		dev_err(dev, "EHCI get resource IORESOURCE_MEM failed\n");
+		ret = -ENODEV;
+		goto err_end;
+	}
+	resources[0] = *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ehci-irq");
+	if (!res) {
+		dev_err(dev, " EHCI get resource IORESOURCE_IRQ failed\n");
+		ret = -ENODEV;
+		goto err_end;
+	}
+	resources[1] = *res;
+
+	ehci = omap_usbhs_alloc_child(OMAP_EHCI_DEVICE, resources, 2, ehci_data,
+		sizeof(*ehci_data), dev);
+
+	if (!ehci) {
+		dev_err(dev, "omap_usbhs_alloc_child failed\n");
+		goto err_end;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ohci");
+	if (!res) {
+		dev_err(dev, "OHCI get resource IORESOURCE_MEM failed\n");
+		ret = -ENODEV;
+		goto err_ehci;
+	}
+	resources[0] = *res;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "ohci-irq");
+	if (!res) {
+		dev_err(dev, "OHCI get resource IORESOURCE_IRQ failed\n");
+		ret = -ENODEV;
+		goto err_ehci;
+	}
+	resources[1] = *res;
+
+	ohci = omap_usbhs_alloc_child(OMAP_OHCI_DEVICE, resources, 2, ohci_data,
+		sizeof(*ohci_data), dev);
+	if (!ohci) {
+		dev_err(dev, "omap_usbhs_alloc_child failed\n");
+		goto err_ehci;
+	}
+
+	return 0;
+
+err_ehci:
+	platform_device_put(ehci);
+
+err_end:
+	return ret;
+}
+
+/**
+ * usbhs_omap_probe - initialize TI-based HCDs
+ *
+ * Allocates basic resources for this USB host controller.
+ */
+static int __devinit usbhs_omap_probe(struct platform_device *pdev)
+{
+	struct device			*dev =  &pdev->dev;
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	struct usbhs_hcd_omap		*omap;
+	struct resource			*res;
+	int				ret = 0;
+	int				i;
+
+	if (!pdata) {
+		dev_err(dev, "Missing platform data\n");
+		ret = -ENOMEM;
+		goto end_probe;
+	}
+
+	omap = kzalloc(sizeof(*omap), GFP_KERNEL);
+	if (!omap) {
+		dev_err(dev, "Memory allocation failed\n");
+		ret = -ENOMEM;
+		goto end_probe;
+	}
+
+	spin_lock_init(&omap->lock);
+
+	for (i = 0; i < OMAP3_HS_USB_PORTS; i++)
+		omap->platdata.port_mode[i] = pdata->port_mode[i];
+
+	omap->platdata.ehci_data = pdata->ehci_data;
+	omap->platdata.ohci_data = pdata->ohci_data;
+
+	omap->usbhost_ick = clk_get(dev, "usbhost_ick");
+	if (IS_ERR(omap->usbhost_ick)) {
+		ret =  PTR_ERR(omap->usbhost_ick);
+		dev_err(dev, "usbhost_ick failed error:%d\n", ret);
+		goto err_end;
+	}
+
+	omap->usbhost_hs_fck = clk_get(dev, "hs_fck");
+	if (IS_ERR(omap->usbhost_hs_fck)) {
+		ret = PTR_ERR(omap->usbhost_hs_fck);
+		dev_err(dev, "usbhost_hs_fck failed error:%d\n", ret);
+		goto err_usbhost_ick;
+	}
+
+	omap->usbhost_fs_fck = clk_get(dev, "fs_fck");
+	if (IS_ERR(omap->usbhost_fs_fck)) {
+		ret = PTR_ERR(omap->usbhost_fs_fck);
+		dev_err(dev, "usbhost_fs_fck failed error:%d\n", ret);
+		goto err_usbhost_hs_fck;
+	}
+
+	omap->usbtll_fck = clk_get(dev, "usbtll_fck");
+	if (IS_ERR(omap->usbtll_fck)) {
+		ret = PTR_ERR(omap->usbtll_fck);
+		dev_err(dev, "usbtll_fck failed error:%d\n", ret);
+		goto err_usbhost_fs_fck;
+	}
+
+	omap->usbtll_ick = clk_get(dev, "usbtll_ick");
+	if (IS_ERR(omap->usbtll_ick)) {
+		ret = PTR_ERR(omap->usbtll_ick);
+		dev_err(dev, "usbtll_ick failed error:%d\n", ret);
+		goto err_usbtll_fck;
+	}
+
+	omap->utmi_p1_fck = clk_get(dev, "utmi_p1_gfclk");
+	if (IS_ERR(omap->utmi_p1_fck)) {
+		ret = PTR_ERR(omap->utmi_p1_fck);
+		dev_err(dev, "utmi_p1_gfclk failed error:%d\n",	ret);
+		goto err_usbtll_ick;
+	}
+
+	omap->xclk60mhsp1_ck = clk_get(dev, "xclk60mhsp1_ck");
+	if (IS_ERR(omap->xclk60mhsp1_ck)) {
+		ret = PTR_ERR(omap->xclk60mhsp1_ck);
+		dev_err(dev, "xclk60mhsp1_ck failed error:%d\n", ret);
+		goto err_utmi_p1_fck;
+	}
+
+	omap->utmi_p2_fck = clk_get(dev, "utmi_p2_gfclk");
+	if (IS_ERR(omap->utmi_p2_fck)) {
+		ret = PTR_ERR(omap->utmi_p2_fck);
+		dev_err(dev, "utmi_p2_gfclk failed error:%d\n", ret);
+		goto err_xclk60mhsp1_ck;
+	}
+
+	omap->xclk60mhsp2_ck = clk_get(dev, "xclk60mhsp2_ck");
+	if (IS_ERR(omap->xclk60mhsp2_ck)) {
+		ret = PTR_ERR(omap->xclk60mhsp2_ck);
+		dev_err(dev, "xclk60mhsp2_ck failed error:%d\n", ret);
+		goto err_utmi_p2_fck;
+	}
+
+	omap->usbhost_p1_fck = clk_get(dev, "usb_host_hs_utmi_p1_clk");
+	if (IS_ERR(omap->usbhost_p1_fck)) {
+		ret = PTR_ERR(omap->usbhost_p1_fck);
+		dev_err(dev, "usbhost_p1_fck failed error:%d\n", ret);
+		goto err_xclk60mhsp2_ck;
+	}
+
+	omap->usbtll_p1_fck = clk_get(dev, "usb_tll_hs_usb_ch0_clk");
+	if (IS_ERR(omap->usbtll_p1_fck)) {
+		ret = PTR_ERR(omap->usbtll_p1_fck);
+		dev_err(dev, "usbtll_p1_fck failed error:%d\n", ret);
+		goto err_usbhost_p1_fck;
+	}
+
+	omap->usbhost_p2_fck = clk_get(dev, "usb_host_hs_utmi_p2_clk");
+	if (IS_ERR(omap->usbhost_p2_fck)) {
+		ret = PTR_ERR(omap->usbhost_p2_fck);
+		dev_err(dev, "usbhost_p2_fck failed error:%d\n", ret);
+		goto err_usbtll_p1_fck;
+	}
+
+	omap->usbtll_p2_fck = clk_get(dev, "usb_tll_hs_usb_ch1_clk");
+	if (IS_ERR(omap->usbtll_p2_fck)) {
+		ret = PTR_ERR(omap->usbtll_p2_fck);
+		dev_err(dev, "usbtll_p2_fck failed error:%d\n", ret);
+		goto err_usbhost_p2_fck;
+	}
+
+	omap->init_60m_fclk = clk_get(dev, "init_60m_fclk");
+	if (IS_ERR(omap->init_60m_fclk)) {
+		ret = PTR_ERR(omap->init_60m_fclk);
+		dev_err(dev, "init_60m_fclk failed error:%d\n", ret);
+		goto err_usbtll_p2_fck;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "uhh");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		ret = -ENODEV;
+		goto err_init_60m_fclk;
+	}
+
+	omap->uhh_base = ioremap(res->start, resource_size(res));
+	if (!omap->uhh_base) {
+		dev_err(dev, "UHH ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_init_60m_fclk;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "tll");
+	if (!res) {
+		dev_err(dev, "UHH EHCI get resource failed\n");
+		ret = -ENODEV;
+		goto err_tll;
+	}
+
+	omap->tll_base = ioremap(res->start, resource_size(res));
+	if (!omap->tll_base) {
+		dev_err(dev, "TLL ioremap failed\n");
+		ret = -ENOMEM;
+		goto err_tll;
+	}
+
+	platform_set_drvdata(pdev, omap);
+
+	ret = omap_usbhs_alloc_children(pdev);
+	if (ret) {
+		dev_err(dev, "omap_usbhs_alloc_children failed\n");
+		goto err_alloc;
+	}
+
+	goto end_probe;
+
+err_alloc:
+	iounmap(omap->tll_base);
+
+err_tll:
+	iounmap(omap->uhh_base);
+
+err_init_60m_fclk:
+	clk_put(omap->init_60m_fclk);
+
+err_usbtll_p2_fck:
+	clk_put(omap->usbtll_p2_fck);
+
+err_usbhost_p2_fck:
+	clk_put(omap->usbhost_p2_fck);
+
+err_usbtll_p1_fck:
+	clk_put(omap->usbtll_p1_fck);
+
+err_usbhost_p1_fck:
+	clk_put(omap->usbhost_p1_fck);
+
+err_xclk60mhsp2_ck:
+	clk_put(omap->xclk60mhsp2_ck);
+
+err_utmi_p2_fck:
+	clk_put(omap->utmi_p2_fck);
+
+err_xclk60mhsp1_ck:
+	clk_put(omap->xclk60mhsp1_ck);
+
+err_utmi_p1_fck:
+	clk_put(omap->utmi_p1_fck);
+
+err_usbtll_ick:
+	clk_put(omap->usbtll_ick);
+
+err_usbtll_fck:
+	clk_put(omap->usbtll_fck);
+
+err_usbhost_fs_fck:
+	clk_put(omap->usbhost_fs_fck);
+
+err_usbhost_hs_fck:
+	clk_put(omap->usbhost_hs_fck);
+
+err_usbhost_ick:
+	clk_put(omap->usbhost_ick);
+
+err_end:
+	kfree(omap);
+
+end_probe:
+	return ret;
+}
+
+/**
+ * usbhs_omap_remove - shutdown processing for UHH & TLL HCDs
+ * @pdev: USB Host Controller being removed
+ *
+ * Reverses the effect of usbhs_omap_probe().
+ */
+static int __devexit usbhs_omap_remove(struct platform_device *pdev)
+{
+	struct usbhs_hcd_omap *omap = platform_get_drvdata(pdev);
+
+	if (omap->count != 0) {
+		dev_err(&pdev->dev,
+			"Either EHCI or OHCI is still using usbhs core\n");
+		return -EBUSY;
+	}
+
+	iounmap(omap->tll_base);
+	iounmap(omap->uhh_base);
+	clk_put(omap->init_60m_fclk);
+	clk_put(omap->usbtll_p2_fck);
+	clk_put(omap->usbhost_p2_fck);
+	clk_put(omap->usbtll_p1_fck);
+	clk_put(omap->usbhost_p1_fck);
+	clk_put(omap->xclk60mhsp2_ck);
+	clk_put(omap->utmi_p2_fck);
+	clk_put(omap->xclk60mhsp1_ck);
+	clk_put(omap->utmi_p1_fck);
+	clk_put(omap->usbtll_ick);
+	clk_put(omap->usbtll_fck);
+	clk_put(omap->usbhost_fs_fck);
+	clk_put(omap->usbhost_hs_fck);
+	clk_put(omap->usbhost_ick);
+	kfree(omap);
+
+	return 0;
+}
+
+static bool is_ohci_port(enum usbhs_omap_port_mode pmode)
+{
+	switch (pmode) {
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		return true;
+
+	default:
+		return false;
+	}
+}
+
+/*
+ * convert the port-mode enum to a value we can use in the FSLSMODE
+ * field of USBTLL_CHANNEL_CONF
+ */
+static unsigned ohci_omap3_fslsmode(enum usbhs_omap_port_mode mode)
+{
+	switch (mode) {
+	case OMAP_USBHS_PORT_MODE_UNUSED:
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_PHY_6PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DP_DM;
+
+	case OMAP_OHCI_PORT_MODE_PHY_3PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_3PIN_PHY;
+
+	case OMAP_OHCI_PORT_MODE_PHY_4PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_4PIN_PHY;
+
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_6PIN_TLL_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_TLL_6PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_6PIN_TLL_DP_DM;
+
+	case OMAP_OHCI_PORT_MODE_TLL_3PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_3PIN_TLL;
+
+	case OMAP_OHCI_PORT_MODE_TLL_4PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_4PIN_TLL;
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DATSE0:
+		return OMAP_TLL_FSLSMODE_2PIN_TLL_DAT_SE0;
+
+	case OMAP_OHCI_PORT_MODE_TLL_2PIN_DPDM:
+		return OMAP_TLL_FSLSMODE_2PIN_DAT_DP_DM;
+	default:
+		pr_warning("Invalid port mode, using default\n");
+		return OMAP_TLL_FSLSMODE_6PIN_PHY_DAT_SE0;
+	}
+}
+
+static void usbhs_omap_tll_init(struct device *dev, u8 tll_channel_count)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = dev->platform_data;
+	unsigned			reg;
+	int				i;
+
+	/* Program Common TLL register */
+	reg = usbhs_read(omap->tll_base, OMAP_TLL_SHARED_CONF);
+	reg |= (OMAP_TLL_SHARED_CONF_FCLK_IS_ON
+		| OMAP_TLL_SHARED_CONF_USB_DIVRATION);
+	reg &= ~OMAP_TLL_SHARED_CONF_USB_90D_DDR_EN;
+	reg &= ~OMAP_TLL_SHARED_CONF_USB_180D_SDR_EN;
+
+	usbhs_write(omap->tll_base, OMAP_TLL_SHARED_CONF, reg);
+
+	/* Enable channels now */
+	for (i = 0; i < tll_channel_count; i++) {
+		reg = usbhs_read(omap->tll_base,
+				OMAP_TLL_CHANNEL_CONF(i));
+
+		if (is_ohci_port(pdata->port_mode[i])) {
+			reg |= ohci_omap3_fslsmode(pdata->port_mode[i])
+				<< OMAP_TLL_CHANNEL_CONF_FSLSMODE_SHIFT;
+			reg |= OMAP_TLL_CHANNEL_CONF_CHANMODE_FSLS;
+		} else if (pdata->port_mode[i] == OMAP_EHCI_PORT_MODE_TLL) {
+
+			/* Disable AutoIdle, BitStuffing and use SDR Mode */
+			reg &= ~(OMAP_TLL_CHANNEL_CONF_UTMIAUTOIDLE
+				| OMAP_TLL_CHANNEL_CONF_ULPINOBITSTUFF
+				| OMAP_TLL_CHANNEL_CONF_ULPIDDRMODE);
+
+			reg |= (1 << (i + 1));
+		} else
+			continue;
+
+		reg |= OMAP_TLL_CHANNEL_CONF_CHANEN;
+		usbhs_write(omap->tll_base,
+				OMAP_TLL_CHANNEL_CONF(i), reg);
+
+		usbhs_writeb(omap->tll_base,
+				OMAP_TLL_ULPI_SCRATCH_REGISTER(i), 0xbe);
+	}
+}
+
+static int usbhs_enable(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	unsigned long			flags = 0;
+	int				ret = 0;
+	unsigned long			timeout;
+	unsigned			reg;
+
+	dev_dbg(dev, "starting TI HSUSB Controller\n");
+	if (!pdata) {
+		dev_dbg(dev, "missing platform_data\n");
+		return  -ENODEV;
+	}
+
+	spin_lock_irqsave(&omap->lock, flags);
+	if (omap->count > 0)
+		goto end_count;
+
+	clk_enable(omap->usbhost_ick);
+	clk_enable(omap->usbhost_hs_fck);
+	clk_enable(omap->usbhost_fs_fck);
+	clk_enable(omap->usbtll_fck);
+	clk_enable(omap->usbtll_ick);
+
+	if (pdata->ehci_data->phy_reset) {
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0])) {
+			gpio_request(pdata->ehci_data->reset_gpio_port[0],
+						"USB1 PHY reset");
+			gpio_direction_output
+				(pdata->ehci_data->reset_gpio_port[0], 0);
+		}
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1])) {
+			gpio_request(pdata->ehci_data->reset_gpio_port[1],
+						"USB2 PHY reset");
+			gpio_direction_output
+				(pdata->ehci_data->reset_gpio_port[1], 0);
+		}
+
+		/* Hold the PHY in RESET for enough time till DIR is high */
+		udelay(10);
+	}
+
+	omap->usbhs_rev = usbhs_read(omap->uhh_base, OMAP_UHH_REVISION);
+	dev_dbg(dev, "OMAP UHH_REVISION 0x%x\n", omap->usbhs_rev);
+
+	/* perform TLL soft reset, and wait until reset is complete */
+	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
+			OMAP_USBTLL_SYSCONFIG_SOFTRESET);
+
+	/* Wait for TLL reset to complete */
+	timeout = jiffies + msecs_to_jiffies(1000);
+	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
+			& OMAP_USBTLL_SYSSTATUS_RESETDONE)) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout)) {
+			dev_dbg(dev, "operation timed out\n");
+			ret = -EINVAL;
+			goto err_tll;
+		}
+	}
+
+	dev_dbg(dev, "TLL RESET DONE\n");
+
+	/* (1<<3) = no idle mode only for initial debugging */
+	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG,
+			OMAP_USBTLL_SYSCONFIG_ENAWAKEUP |
+			OMAP_USBTLL_SYSCONFIG_SIDLEMODE |
+			OMAP_USBTLL_SYSCONFIG_AUTOIDLE);
+
+	/* Put UHH in NoIdle/NoStandby mode */
+	reg = usbhs_read(omap->uhh_base, OMAP_UHH_SYSCONFIG);
+	if (is_omap_usbhs_rev1(omap)) {
+		reg |= (OMAP_UHH_SYSCONFIG_ENAWAKEUP
+				| OMAP_UHH_SYSCONFIG_SIDLEMODE
+				| OMAP_UHH_SYSCONFIG_CACTIVITY
+				| OMAP_UHH_SYSCONFIG_MIDLEMODE);
+		reg &= ~OMAP_UHH_SYSCONFIG_AUTOIDLE;
+
+
+	} else if (is_omap_usbhs_rev2(omap)) {
+		reg &= ~OMAP4_UHH_SYSCONFIG_IDLEMODE_CLEAR;
+		reg |= OMAP4_UHH_SYSCONFIG_NOIDLE;
+		reg &= ~OMAP4_UHH_SYSCONFIG_STDBYMODE_CLEAR;
+		reg |= OMAP4_UHH_SYSCONFIG_NOSTDBY;
+	}
+
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG, reg);
+
+	reg = usbhs_read(omap->uhh_base, OMAP_UHH_HOSTCONFIG);
+	/* setup ULPI bypass and burst configurations */
+	reg |= (OMAP_UHH_HOSTCONFIG_INCR4_BURST_EN
+			| OMAP_UHH_HOSTCONFIG_INCR8_BURST_EN
+			| OMAP_UHH_HOSTCONFIG_INCR16_BURST_EN);
+	reg |= OMAP4_UHH_HOSTCONFIG_APP_START_CLK;
+	reg &= ~OMAP_UHH_HOSTCONFIG_INCRX_ALIGN_EN;
+
+	if (is_omap_usbhs_rev1(omap)) {
+		if (pdata->port_mode[0] == OMAP_USBHS_PORT_MODE_UNUSED)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P1_CONNECT_STATUS;
+		if (pdata->port_mode[1] == OMAP_USBHS_PORT_MODE_UNUSED)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P2_CONNECT_STATUS;
+		if (pdata->port_mode[2] == OMAP_USBHS_PORT_MODE_UNUSED)
+			reg &= ~OMAP_UHH_HOSTCONFIG_P3_CONNECT_STATUS;
+
+		/* Bypass the TLL module for PHY mode operation */
+		if (cpu_is_omap3430() && (omap_rev() <= OMAP3430_REV_ES2_1)) {
+			dev_dbg(dev, "OMAP3 ES version <= ES2.1\n");
+			if (is_ehci_phy_mode(pdata->port_mode[0]) ||
+				is_ehci_phy_mode(pdata->port_mode[1]) ||
+					is_ehci_phy_mode(pdata->port_mode[2]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_BYPASS;
+		} else {
+			dev_dbg(dev, "OMAP3 ES version > ES2.1\n");
+			if (is_ehci_phy_mode(pdata->port_mode[0]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P1_BYPASS;
+			if (is_ehci_phy_mode(pdata->port_mode[1]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P2_BYPASS;
+			if (is_ehci_phy_mode(pdata->port_mode[2]))
+				reg &= ~OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+			else
+				reg |= OMAP_UHH_HOSTCONFIG_ULPI_P3_BYPASS;
+		}
+	} else if (is_omap_usbhs_rev2(omap)) {
+		/* Clear port mode fields for PHY mode*/
+		reg &= ~OMAP4_P1_MODE_CLEAR;
+		reg &= ~OMAP4_P2_MODE_CLEAR;
+
+		if (is_ehci_phy_mode(pdata->port_mode[0])) {
+			ret = clk_set_parent(omap->utmi_p1_fck,
+						omap->xclk60mhsp1_ck);
+			if (ret != 0) {
+				dev_err(dev, "xclk60mhsp1_ck set parent"
+				"failed error:%d\n", ret);
+				goto err_tll;
+			}
+		} else if (is_ehci_tll_mode(pdata->port_mode[0])) {
+			ret = clk_set_parent(omap->utmi_p1_fck,
+						omap->init_60m_fclk);
+			if (ret != 0) {
+				dev_err(dev, "init_60m_fclk set parent"
+				"failed error:%d\n", ret);
+				goto err_tll;
+			}
+			clk_enable(omap->usbhost_p1_fck);
+			clk_enable(omap->usbtll_p1_fck);
+		}
+
+		if (is_ehci_phy_mode(pdata->port_mode[1])) {
+			ret = clk_set_parent(omap->utmi_p2_fck,
+						omap->xclk60mhsp2_ck);
+			if (ret != 0) {
+				dev_err(dev, "xclk60mhsp1_ck set parent"
+					"failed error:%d\n", ret);
+				goto err_tll;
+			}
+		} else if (is_ehci_tll_mode(pdata->port_mode[1])) {
+			ret = clk_set_parent(omap->utmi_p2_fck,
+						omap->init_60m_fclk);
+			if (ret != 0) {
+				dev_err(dev, "init_60m_fclk set parent"
+				"failed error:%d\n", ret);
+				goto err_tll;
+			}
+			clk_enable(omap->usbhost_p2_fck);
+			clk_enable(omap->usbtll_p2_fck);
+		}
+
+		clk_enable(omap->utmi_p1_fck);
+		clk_enable(omap->utmi_p2_fck);
+
+		if (is_ehci_tll_mode(pdata->port_mode[0]) ||
+			(is_ohci_port(pdata->port_mode[0])))
+			reg |= OMAP4_P1_MODE_TLL;
+		else if (is_ehci_hsic_mode(pdata->port_mode[0]))
+			reg |= OMAP4_P1_MODE_HSIC;
+
+		if (is_ehci_tll_mode(pdata->port_mode[1]) ||
+			(is_ohci_port(pdata->port_mode[1])))
+			reg |= OMAP4_P2_MODE_TLL;
+		else if (is_ehci_hsic_mode(pdata->port_mode[1]))
+			reg |= OMAP4_P2_MODE_HSIC;
+	}
+
+	usbhs_write(omap->uhh_base, OMAP_UHH_HOSTCONFIG, reg);
+	dev_dbg(dev, "UHH setup done, uhh_hostconfig=%x\n", reg);
+
+	if (is_ehci_tll_mode(pdata->port_mode[0]) ||
+		is_ehci_tll_mode(pdata->port_mode[1]) ||
+		is_ehci_tll_mode(pdata->port_mode[2]) ||
+		(is_ohci_port(pdata->port_mode[0])) ||
+		(is_ohci_port(pdata->port_mode[1])) ||
+		(is_ohci_port(pdata->port_mode[2]))) {
+
+		/* Enable UTMI mode for required TLL channels */
+		if (is_omap_usbhs_rev2(omap))
+			usbhs_omap_tll_init(dev, OMAP_REV2_TLL_CHANNEL_COUNT);
+		else
+			usbhs_omap_tll_init(dev, OMAP_TLL_CHANNEL_COUNT);
+	}
+
+	if (pdata->ehci_data->phy_reset) {
+		/* Hold the PHY in RESET for enough time till
+		 * PHY is settled and ready
+		 */
+		udelay(10);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+			gpio_set_value
+				(pdata->ehci_data->reset_gpio_port[0], 1);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+			gpio_set_value
+				(pdata->ehci_data->reset_gpio_port[1], 1);
+	}
+
+end_count:
+	omap->count++;
+	spin_unlock_irqrestore(&omap->lock, flags);
+	return 0;
+
+err_tll:
+	if (pdata->ehci_data->phy_reset) {
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+	}
+
+	clk_disable(omap->usbtll_ick);
+	clk_disable(omap->usbtll_fck);
+	clk_disable(omap->usbhost_fs_fck);
+	clk_disable(omap->usbhost_hs_fck);
+	clk_disable(omap->usbhost_ick);
+	spin_unlock_irqrestore(&omap->lock, flags);
+	return ret;
+}
+
+static void usbhs_disable(struct device *dev)
+{
+	struct usbhs_hcd_omap		*omap = dev_get_drvdata(dev);
+	struct usbhs_omap_platform_data	*pdata = &omap->platdata;
+	unsigned long			flags = 0;
+	unsigned long			timeout;
+
+	dev_dbg(dev, "stopping TI HSUSB Controller\n");
+
+	spin_lock_irqsave(&omap->lock, flags);
+
+	if (omap->count == 0)
+		goto end_disble;
+
+	omap->count--;
+
+	if (omap->count != 0)
+		goto end_disble;
+
+	/* Reset OMAP modules for insmod/rmmod to work */
+	usbhs_write(omap->uhh_base, OMAP_UHH_SYSCONFIG,
+			is_omap_usbhs_rev2(omap) ?
+			OMAP4_UHH_SYSCONFIG_SOFTRESET :
+			OMAP_UHH_SYSCONFIG_SOFTRESET);
+
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+				& (1 << 0))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+				& (1 << 1))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	while (!(usbhs_read(omap->uhh_base, OMAP_UHH_SYSSTATUS)
+				& (1 << 2))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	usbhs_write(omap->tll_base, OMAP_USBTLL_SYSCONFIG, (1 << 1));
+
+	while (!(usbhs_read(omap->tll_base, OMAP_USBTLL_SYSSTATUS)
+				& (1 << 0))) {
+		cpu_relax();
+
+		if (time_after(jiffies, timeout))
+			dev_dbg(dev, "operation timed out\n");
+	}
+
+	if (pdata->ehci_data->phy_reset) {
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[0]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[0]);
+
+		if (gpio_is_valid(pdata->ehci_data->reset_gpio_port[1]))
+			gpio_free(pdata->ehci_data->reset_gpio_port[1]);
+	}
+
+	clk_disable(omap->utmi_p2_fck);
+	clk_disable(omap->utmi_p1_fck);
+	clk_disable(omap->usbtll_ick);
+	clk_disable(omap->usbtll_fck);
+	clk_disable(omap->usbhost_fs_fck);
+	clk_disable(omap->usbhost_hs_fck);
+	clk_disable(omap->usbhost_ick);
+
+end_disble:
+	spin_unlock_irqrestore(&omap->lock, flags);
+}
+
+int omap_usbhs_enable(struct device *dev)
+{
+	return  usbhs_enable(dev->parent);
+}
+EXPORT_SYMBOL_GPL(omap_usbhs_enable);
+
+void omap_usbhs_disable(struct device *dev)
+{
+	usbhs_disable(dev->parent);
+}
+EXPORT_SYMBOL_GPL(omap_usbhs_disable);
+
+static struct platform_driver usbhs_omap_driver = {
+	.driver = {
+		.name		= (char *)usbhs_driver_name,
+		.owner		= THIS_MODULE,
+	},
+	.remove		= __exit_p(usbhs_omap_remove),
+};
+
+MODULE_AUTHOR("Keshava Munegowda <keshava_mgowda@ti.com>");
+MODULE_ALIAS("platform:" USBHS_DRIVER_NAME);
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("usb host common core driver for omap EHCI and OHCI");
+
+static int __init omap_usbhs_drvinit(void)
+{
+	return platform_driver_probe(&usbhs_omap_driver, usbhs_omap_probe);
+}
+
+/*
+ * init before ehci and ohci drivers;
+ * The usbhs core driver should be initialized much before
+ * the omap ehci and ohci probe functions are called.
+ */
+fs_initcall(omap_usbhs_drvinit);
+
+static void __exit omap_usbhs_drvexit(void)
+{
+	platform_driver_unregister(&usbhs_omap_driver);
+}
+module_exit(omap_usbhs_drvexit);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/pcf50633-core.c linux-libre-2.6.39-gnu/drivers/mfd/pcf50633-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/pcf50633-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/pcf50633-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/pm.h>
 #include <linux/slab.h>
 
 #include <linux/mfd/pcf50633/core.h>
@@ -50,7 +51,7 @@
 
 }
 
-/* Read a block of upto 32 regs  */
+/* Read a block of up to 32 regs  */
 int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
 					int nr_regs, u8 *data)
 {
@@ -64,7 +65,7 @@
 }
 EXPORT_SYMBOL_GPL(pcf50633_read_block);
 
-/* Write a block of upto 32 regs  */
+/* Write a block of up to 32 regs  */
 int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
 					int nr_regs, u8 *data)
 {
@@ -230,27 +231,26 @@
 	}
 }
 
-#ifdef CONFIG_PM
-static int pcf50633_suspend(struct i2c_client *client, pm_message_t state)
+#ifdef CONFIG_PM_SLEEP
+static int pcf50633_suspend(struct device *dev)
 {
-	struct pcf50633 *pcf;
-	pcf = i2c_get_clientdata(client);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf50633 *pcf = i2c_get_clientdata(client);
 
 	return pcf50633_irq_suspend(pcf);
 }
 
-static int pcf50633_resume(struct i2c_client *client)
+static int pcf50633_resume(struct device *dev)
 {
-	struct pcf50633 *pcf;
-	pcf = i2c_get_clientdata(client);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf50633 *pcf = i2c_get_clientdata(client);
 
 	return pcf50633_irq_resume(pcf);
 }
-#else
-#define pcf50633_suspend NULL
-#define pcf50633_resume NULL
 #endif
 
+static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
+
 static int __devinit pcf50633_probe(struct i2c_client *client,
 				const struct i2c_device_id *ids)
 {
@@ -356,20 +356,20 @@
 	return 0;
 }
 
-static struct i2c_device_id pcf50633_id_table[] = {
+static const struct i2c_device_id pcf50633_id_table[] = {
 	{"pcf50633", 0x73},
 	{/* end of list */}
 };
+MODULE_DEVICE_TABLE(i2c, pcf50633_id_table);
 
 static struct i2c_driver pcf50633_driver = {
 	.driver = {
 		.name	= "pcf50633",
+		.pm	= &pcf50633_pm,
 	},
 	.id_table = pcf50633_id_table,
 	.probe = pcf50633_probe,
 	.remove = __devexit_p(pcf50633_remove),
-	.suspend = pcf50633_suspend,
-	.resume	= pcf50633_resume,
 };
 
 static int __init pcf50633_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/rdc321x-southbridge.c linux-libre-2.6.39-gnu/drivers/mfd/rdc321x-southbridge.c
--- linux-libre-2.6.38-gnu/drivers/mfd/rdc321x-southbridge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/rdc321x-southbridge.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,12 +61,12 @@
 		.name		= "rdc321x-wdt",
 		.resources	= rdc321x_wdt_resource,
 		.num_resources	= ARRAY_SIZE(rdc321x_wdt_resource),
-		.driver_data	= &rdc321x_wdt_pdata,
+		.mfd_data	= &rdc321x_wdt_pdata,
 	}, {
 		.name		= "rdc321x-gpio",
 		.resources	= rdc321x_gpio_resources,
 		.num_resources	= ARRAY_SIZE(rdc321x_gpio_resources),
-		.driver_data	= &rdc321x_gpio_pdata,
+		.mfd_data	= &rdc321x_gpio_pdata,
 	},
 };
 
@@ -97,6 +97,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_RDC, PCI_DEVICE_ID_RDC_R6030) },
 	{}
 };
+MODULE_DEVICE_TABLE(pci, rdc321x_sb_table);
 
 static struct pci_driver rdc321x_sb_driver = {
 	.name		= "RDC321x Southbridge",
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/sh_mobile_sdhi.c linux-libre-2.6.39-gnu/drivers/mfd/sh_mobile_sdhi.c
--- linux-libre-2.6.38-gnu/drivers/mfd/sh_mobile_sdhi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/sh_mobile_sdhi.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,202 +0,0 @@
-/*
- * SuperH Mobile SDHI
- *
- * 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 version 2 as
- * published by the Free Software Foundation.
- *
- * Based on "Compaq ASIC3 support":
- *
- * Copyright 2001 Compaq Computer Corporation.
- * Copyright 2004-2005 Phil Blundell
- * Copyright 2007-2008 OpenedHand Ltd.
- *
- * Authors: Phil Blundell <pb@handhelds.org>,
- *	    Samuel Ortiz <sameo@openedhand.com>
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/slab.h>
-#include <linux/platform_device.h>
-#include <linux/mmc/host.h>
-#include <linux/mfd/core.h>
-#include <linux/mfd/tmio.h>
-#include <linux/mfd/sh_mobile_sdhi.h>
-#include <linux/sh_dma.h>
-
-struct sh_mobile_sdhi {
-	struct clk *clk;
-	struct tmio_mmc_data mmc_data;
-	struct mfd_cell cell_mmc;
-	struct sh_dmae_slave param_tx;
-	struct sh_dmae_slave param_rx;
-	struct tmio_mmc_dma dma_priv;
-};
-
-static struct resource sh_mobile_sdhi_resources[] = {
-	{
-		.start = 0x000,
-		.end   = 0x1ff,
-		.flags = IORESOURCE_MEM,
-	},
-	{
-		.start = 0,
-		.end   = 0,
-		.flags = IORESOURCE_IRQ,
-	},
-};
-
-static struct mfd_cell sh_mobile_sdhi_cell = {
-	.name          = "tmio-mmc",
-	.num_resources = ARRAY_SIZE(sh_mobile_sdhi_resources),
-	.resources     = sh_mobile_sdhi_resources,
-};
-
-static void sh_mobile_sdhi_set_pwr(struct platform_device *tmio, int state)
-{
-	struct platform_device *pdev = to_platform_device(tmio->dev.parent);
-	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-	if (p && p->set_pwr)
-		p->set_pwr(pdev, state);
-}
-
-static int sh_mobile_sdhi_get_cd(struct platform_device *tmio)
-{
-	struct platform_device *pdev = to_platform_device(tmio->dev.parent);
-	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-
-	if (p && p->get_cd)
-		return p->get_cd(pdev);
-	else
-		return -ENOSYS;
-}
-
-static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
-{
-	struct sh_mobile_sdhi *priv;
-	struct tmio_mmc_data *mmc_data;
-	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
-	struct resource *mem;
-	char clk_name[8];
-	int ret, irq;
-
-	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!mem)
-		dev_err(&pdev->dev, "missing MEM resource\n");
-
-	irq = platform_get_irq(pdev, 0);
-	if (irq < 0)
-		dev_err(&pdev->dev, "missing IRQ resource\n");
-
-	if (!mem || (irq < 0))
-		return -EINVAL;
-
-	priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
-	if (priv == NULL) {
-		dev_err(&pdev->dev, "kzalloc failed\n");
-		return -ENOMEM;
-	}
-
-	mmc_data = &priv->mmc_data;
-
-	snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
-	priv->clk = clk_get(&pdev->dev, clk_name);
-	if (IS_ERR(priv->clk)) {
-		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
-		ret = PTR_ERR(priv->clk);
-		kfree(priv);
-		return ret;
-	}
-
-	clk_enable(priv->clk);
-
-	mmc_data->hclk = clk_get_rate(priv->clk);
-	mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
-	mmc_data->get_cd = sh_mobile_sdhi_get_cd;
-	mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
-	if (p) {
-		mmc_data->flags = p->tmio_flags;
-		mmc_data->ocr_mask = p->tmio_ocr_mask;
-		mmc_data->capabilities |= p->tmio_caps;
-	}
-
-	/*
-	 * All SDHI blocks support 2-byte and larger block sizes in 4-bit
-	 * bus width mode.
-	 */
-	mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES;
-
-	/*
-	 * All SDHI blocks support SDIO IRQ signalling.
-	 */
-	mmc_data->flags |= TMIO_MMC_SDIO_IRQ;
-
-	if (p && p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
-		priv->param_tx.slave_id = p->dma_slave_tx;
-		priv->param_rx.slave_id = p->dma_slave_rx;
-		priv->dma_priv.chan_priv_tx = &priv->param_tx;
-		priv->dma_priv.chan_priv_rx = &priv->param_rx;
-		priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
-		mmc_data->dma = &priv->dma_priv;
-	}
-
-	memcpy(&priv->cell_mmc, &sh_mobile_sdhi_cell, sizeof(priv->cell_mmc));
-	priv->cell_mmc.driver_data = mmc_data;
-	priv->cell_mmc.platform_data = &priv->cell_mmc;
-	priv->cell_mmc.data_size = sizeof(priv->cell_mmc);
-
-	platform_set_drvdata(pdev, priv);
-
-	ret = mfd_add_devices(&pdev->dev, pdev->id,
-			      &priv->cell_mmc, 1, mem, irq);
-	if (ret) {
-		clk_disable(priv->clk);
-		clk_put(priv->clk);
-		kfree(priv);
-	}
-
-	return ret;
-}
-
-static int sh_mobile_sdhi_remove(struct platform_device *pdev)
-{
-	struct sh_mobile_sdhi *priv = platform_get_drvdata(pdev);
-
-	mfd_remove_devices(&pdev->dev);
-	clk_disable(priv->clk);
-	clk_put(priv->clk);
-	kfree(priv);
-
-	return 0;
-}
-
-static struct platform_driver sh_mobile_sdhi_driver = {
-	.driver		= {
-		.name	= "sh_mobile_sdhi",
-		.owner	= THIS_MODULE,
-	},
-	.probe		= sh_mobile_sdhi_probe,
-	.remove		= __devexit_p(sh_mobile_sdhi_remove),
-};
-
-static int __init sh_mobile_sdhi_init(void)
-{
-	return platform_driver_register(&sh_mobile_sdhi_driver);
-}
-
-static void __exit sh_mobile_sdhi_exit(void)
-{
-	platform_driver_unregister(&sh_mobile_sdhi_driver);
-}
-
-module_init(sh_mobile_sdhi_init);
-module_exit(sh_mobile_sdhi_exit);
-
-MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
-MODULE_AUTHOR("Magnus Damm");
-MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/sm501.c linux-libre-2.6.39-gnu/drivers/mfd/sm501.c
--- linux-libre-2.6.38-gnu/drivers/mfd/sm501.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/sm501.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,10 +133,10 @@
 
 static void sm501_dump_clk(struct sm501_devdata *sm)
 {
-	unsigned long misct = readl(sm->regs + SM501_MISC_TIMING);
-	unsigned long pm0 = readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
-	unsigned long pm1 = readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
-	unsigned long pmc = readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	unsigned long misct = smc501_readl(sm->regs + SM501_MISC_TIMING);
+	unsigned long pm0 = smc501_readl(sm->regs + SM501_POWER_MODE_0_CLOCK);
+	unsigned long pm1 = smc501_readl(sm->regs + SM501_POWER_MODE_1_CLOCK);
+	unsigned long pmc = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
 	unsigned long sdclk0, sdclk1;
 	unsigned long pll2 = 0;
 
@@ -193,29 +193,29 @@
 	void __iomem *regs = sm->regs;
 
 	dev_info(sm->dev, "System Control   %08x\n",
-			readl(regs + SM501_SYSTEM_CONTROL));
+			smc501_readl(regs + SM501_SYSTEM_CONTROL));
 	dev_info(sm->dev, "Misc Control     %08x\n",
-			readl(regs + SM501_MISC_CONTROL));
+			smc501_readl(regs + SM501_MISC_CONTROL));
 	dev_info(sm->dev, "GPIO Control Low %08x\n",
-			readl(regs + SM501_GPIO31_0_CONTROL));
+			smc501_readl(regs + SM501_GPIO31_0_CONTROL));
 	dev_info(sm->dev, "GPIO Control Hi  %08x\n",
-			readl(regs + SM501_GPIO63_32_CONTROL));
+			smc501_readl(regs + SM501_GPIO63_32_CONTROL));
 	dev_info(sm->dev, "DRAM Control     %08x\n",
-			readl(regs + SM501_DRAM_CONTROL));
+			smc501_readl(regs + SM501_DRAM_CONTROL));
 	dev_info(sm->dev, "Arbitration Ctrl %08x\n",
-			readl(regs + SM501_ARBTRTN_CONTROL));
+			smc501_readl(regs + SM501_ARBTRTN_CONTROL));
 	dev_info(sm->dev, "Misc Timing      %08x\n",
-			readl(regs + SM501_MISC_TIMING));
+			smc501_readl(regs + SM501_MISC_TIMING));
 }
 
 static void sm501_dump_gate(struct sm501_devdata *sm)
 {
 	dev_info(sm->dev, "CurrentGate      %08x\n",
-			readl(sm->regs + SM501_CURRENT_GATE));
+			smc501_readl(sm->regs + SM501_CURRENT_GATE));
 	dev_info(sm->dev, "CurrentClock     %08x\n",
-			readl(sm->regs + SM501_CURRENT_CLOCK));
+			smc501_readl(sm->regs + SM501_CURRENT_CLOCK));
 	dev_info(sm->dev, "PowerModeControl %08x\n",
-			readl(sm->regs + SM501_POWER_MODE_CONTROL));
+			smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL));
 }
 
 #else
@@ -231,7 +231,7 @@
 
 static void sm501_sync_regs(struct sm501_devdata *sm)
 {
-	readl(sm->regs);
+	smc501_readl(sm->regs);
 }
 
 static inline void sm501_mdelay(struct sm501_devdata *sm, unsigned int delay)
@@ -261,11 +261,11 @@
 
 	spin_lock_irqsave(&sm->reg_lock, save);
 
-	misc = readl(sm->regs + SM501_MISC_CONTROL);
+	misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
 	to = (misc & ~clear) | set;
 
 	if (to != misc) {
-		writel(to, sm->regs + SM501_MISC_CONTROL);
+		smc501_writel(to, sm->regs + SM501_MISC_CONTROL);
 		sm501_sync_regs(sm);
 
 		dev_dbg(sm->dev, "MISC_CONTROL %08lx\n", misc);
@@ -294,11 +294,11 @@
 
 	spin_lock_irqsave(&sm->reg_lock, save);
 
-	data = readl(sm->regs + reg);
+	data = smc501_readl(sm->regs + reg);
 	data |= set;
 	data &= ~clear;
 
-	writel(data, sm->regs + reg);
+	smc501_writel(data, sm->regs + reg);
 	sm501_sync_regs(sm);
 
 	spin_unlock_irqrestore(&sm->reg_lock, save);
@@ -322,9 +322,9 @@
 
 	mutex_lock(&sm->clock_lock);
 
-	mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
-	gate = readl(sm->regs + SM501_CURRENT_GATE);
-	clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+	clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 
 	mode &= 3;		/* get current power mode */
 
@@ -356,14 +356,14 @@
 
 	switch (mode) {
 	case 1:
-		writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
 		mode = 0;
 		break;
 	case 2:
 	case 0:
-		writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
 		mode = 1;
 		break;
 
@@ -372,7 +372,7 @@
 		goto already;
 	}
 
-	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+	smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
 	sm501_sync_regs(sm);
 
 	dev_dbg(sm->dev, "gate %08lx, clock %08lx, mode %08lx\n",
@@ -519,9 +519,9 @@
 			      unsigned long req_freq)
 {
 	struct sm501_devdata *sm = dev_get_drvdata(dev);
-	unsigned long mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
-	unsigned long gate = readl(sm->regs + SM501_CURRENT_GATE);
-	unsigned long clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	unsigned long mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	unsigned long gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+	unsigned long clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 	unsigned char reg;
 	unsigned int pll_reg = 0;
 	unsigned long sm501_freq; /* the actual frequency achieved */
@@ -592,9 +592,9 @@
 
 	mutex_lock(&sm->clock_lock);
 
-	mode = readl(sm->regs + SM501_POWER_MODE_CONTROL);
-	gate = readl(sm->regs + SM501_CURRENT_GATE);
-	clock = readl(sm->regs + SM501_CURRENT_CLOCK);
+	mode = smc501_readl(sm->regs + SM501_POWER_MODE_CONTROL);
+	gate = smc501_readl(sm->regs + SM501_CURRENT_GATE);
+	clock = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 
 	clock = clock & ~(0xFF << clksrc);
 	clock |= reg<<clksrc;
@@ -603,14 +603,14 @@
 
 	switch (mode) {
 	case 1:
-		writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_0_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_0_CLOCK);
 		mode = 0;
 		break;
 	case 2:
 	case 0:
-		writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
-		writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
+		smc501_writel(gate, sm->regs + SM501_POWER_MODE_1_GATE);
+		smc501_writel(clock, sm->regs + SM501_POWER_MODE_1_CLOCK);
 		mode = 1;
 		break;
 
@@ -619,10 +619,11 @@
 		return -1;
 	}
 
-	writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
+	smc501_writel(mode, sm->regs + SM501_POWER_MODE_CONTROL);
 
 	if (pll_reg)
-		writel(pll_reg, sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
+		smc501_writel(pll_reg,
+				sm->regs + SM501_PROGRAMMABLE_PLL_CONTROL);
 
 	sm501_sync_regs(sm);
 
@@ -902,7 +903,7 @@
 	struct sm501_gpio_chip *smgpio = to_sm501_gpio(chip);
 	unsigned long result;
 
-	result = readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
+	result = smc501_readl(smgpio->regbase + SM501_GPIO_DATA_LOW);
 	result >>= offset;
 
 	return result & 1UL;
@@ -915,13 +916,13 @@
 
 	/* check and modify if this pin is not set as gpio. */
 
-	if (readl(smchip->control) & bit) {
+	if (smc501_readl(smchip->control) & bit) {
 		dev_info(sm501_gpio_to_dev(smchip->ourgpio)->dev,
 			 "changing mode of gpio, bit %08lx\n", bit);
 
-		ctrl = readl(smchip->control);
+		ctrl = smc501_readl(smchip->control);
 		ctrl &= ~bit;
-		writel(ctrl, smchip->control);
+		smc501_writel(ctrl, smchip->control);
 
 		sm501_sync_regs(sm501_gpio_to_dev(smchip->ourgpio));
 	}
@@ -942,10 +943,10 @@
 
 	spin_lock_irqsave(&smgpio->lock, save);
 
-	val = readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
+	val = smc501_readl(regs + SM501_GPIO_DATA_LOW) & ~bit;
 	if (value)
 		val |= bit;
-	writel(val, regs);
+	smc501_writel(val, regs);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
 	sm501_gpio_ensure_gpio(smchip, bit);
@@ -967,8 +968,8 @@
 
 	spin_lock_irqsave(&smgpio->lock, save);
 
-	ddr = readl(regs + SM501_GPIO_DDR_LOW);
-	writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
+	ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+	smc501_writel(ddr & ~bit, regs + SM501_GPIO_DDR_LOW);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
 	sm501_gpio_ensure_gpio(smchip, bit);
@@ -994,18 +995,18 @@
 
 	spin_lock_irqsave(&smgpio->lock, save);
 
-	val = readl(regs + SM501_GPIO_DATA_LOW);
+	val = smc501_readl(regs + SM501_GPIO_DATA_LOW);
 	if (value)
 		val |= bit;
 	else
 		val &= ~bit;
-	writel(val, regs);
+	smc501_writel(val, regs);
 
-	ddr = readl(regs + SM501_GPIO_DDR_LOW);
-	writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
+	ddr = smc501_readl(regs + SM501_GPIO_DDR_LOW);
+	smc501_writel(ddr | bit, regs + SM501_GPIO_DDR_LOW);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
-	writel(val, regs + SM501_GPIO_DATA_LOW);
+	smc501_writel(val, regs + SM501_GPIO_DATA_LOW);
 
 	sm501_sync_regs(sm501_gpio_to_dev(smgpio));
 	spin_unlock_irqrestore(&smgpio->lock, save);
@@ -1231,7 +1232,7 @@
 
 	for (reg = 0x00; reg < 0x70; reg += 4) {
 		ret = sprintf(ptr, "%08x = %08x\n",
-			      reg, readl(sm->regs + reg));
+			      reg, smc501_readl(sm->regs + reg));
 		ptr += ret;
 	}
 
@@ -1255,10 +1256,10 @@
 {
 	unsigned long tmp;
 
-	tmp = readl(sm->regs + reg);
+	tmp = smc501_readl(sm->regs + reg);
 	tmp &= ~r->mask;
 	tmp |= r->set;
-	writel(tmp, sm->regs + reg);
+	smc501_writel(tmp, sm->regs + reg);
 }
 
 /* sm501_init_regs
@@ -1299,7 +1300,7 @@
 
 static int sm501_check_clocks(struct sm501_devdata *sm)
 {
-	unsigned long pwrmode = readl(sm->regs + SM501_CURRENT_CLOCK);
+	unsigned long pwrmode = smc501_readl(sm->regs + SM501_CURRENT_CLOCK);
 	unsigned long msrc = (pwrmode & SM501_POWERMODE_M_SRC);
 	unsigned long m1src = (pwrmode & SM501_POWERMODE_M1_SRC);
 
@@ -1334,7 +1335,7 @@
 
 	INIT_LIST_HEAD(&sm->devices);
 
-	devid = readl(sm->regs + SM501_DEVICEID);
+	devid = smc501_readl(sm->regs + SM501_DEVICEID);
 
 	if ((devid & SM501_DEVICEID_IDMASK) != SM501_DEVICEID_SM501) {
 		dev_err(sm->dev, "incorrect device id %08lx\n", devid);
@@ -1342,9 +1343,9 @@
 	}
 
 	/* disable irqs */
-	writel(0, sm->regs + SM501_IRQ_MASK);
+	smc501_writel(0, sm->regs + SM501_IRQ_MASK);
 
-	dramctrl = readl(sm->regs + SM501_DRAM_CONTROL);
+	dramctrl = smc501_readl(sm->regs + SM501_DRAM_CONTROL);
 	mem_avail = sm501_mem_local[(dramctrl >> 13) & 0x7];
 
 	dev_info(sm->dev, "SM501 At %p: Version %08lx, %ld Mb, IRQ %d\n",
@@ -1376,7 +1377,7 @@
 			sm501_register_gpio(sm);
 	}
 
-	if (pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
+	if (pdata && pdata->gpio_i2c != NULL && pdata->gpio_i2c_nr > 0) {
 		if (!sm501_gpio_isregistered(sm))
 			dev_err(sm->dev, "no gpio available for i2c gpio.\n");
 		else
@@ -1421,6 +1422,7 @@
 
 	sm->io_res = platform_get_resource(dev, IORESOURCE_MEM, 1);
 	sm->mem_res = platform_get_resource(dev, IORESOURCE_MEM, 0);
+
 	if (sm->io_res == NULL || sm->mem_res == NULL) {
 		dev_err(&dev->dev, "failed to get IO resource\n");
 		ret = -ENOENT;
@@ -1489,7 +1491,7 @@
 	struct sm501_devdata *sm = platform_get_drvdata(pdev);
 
 	sm->in_suspend = 1;
-	sm->pm_misc = readl(sm->regs + SM501_MISC_CONTROL);
+	sm->pm_misc = smc501_readl(sm->regs + SM501_MISC_CONTROL);
 
 	sm501_dump_regs(sm);
 
@@ -1513,9 +1515,9 @@
 
 	/* check to see if we are in the same state as when suspended */
 
-	if (readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
+	if (smc501_readl(sm->regs + SM501_MISC_CONTROL) != sm->pm_misc) {
 		dev_info(sm->dev, "SM501_MISC_CONTROL changed over sleep\n");
-		writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
+		smc501_writel(sm->pm_misc, sm->regs + SM501_MISC_CONTROL);
 
 		/* our suspend causes the controller state to change,
 		 * either by something attempting setup, power loss,
@@ -1734,10 +1736,16 @@
 
 MODULE_ALIAS("platform:sm501");
 
+static struct of_device_id __devinitdata of_sm501_match_tbl[] = {
+	{ .compatible = "smi,sm501", },
+	{ /* end */ }
+};
+
 static struct platform_driver sm501_plat_driver = {
 	.driver		= {
 		.name	= "sm501",
 		.owner	= THIS_MODULE,
+		.of_match_table = of_sm501_match_tbl,
 	},
 	.probe		= sm501_plat_probe,
 	.remove		= sm501_plat_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/stmpe.c linux-libre-2.6.39-gnu/drivers/mfd/stmpe.c
--- linux-libre-2.6.38-gnu/drivers/mfd/stmpe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/stmpe.c	2011-05-19 00:06:34.000000000 -0400
@@ -762,14 +762,14 @@
 	int irq;
 
 	for (irq = base; irq < base + num_irqs; irq++) {
-		set_irq_chip_data(irq, stmpe);
-		set_irq_chip_and_handler(irq, &stmpe_irq_chip,
+		irq_set_chip_data(irq, stmpe);
+		irq_set_chip_and_handler(irq, &stmpe_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -786,8 +786,8 @@
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/t7l66xb.c linux-libre-2.6.39-gnu/drivers/mfd/t7l66xb.c
--- linux-libre-2.6.38-gnu/drivers/mfd/t7l66xb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/t7l66xb.c	2011-05-19 00:06:34.000000000 -0400
@@ -170,7 +170,7 @@
 		.name = "tmio-mmc",
 		.enable = t7l66xb_mmc_enable,
 		.disable = t7l66xb_mmc_disable,
-		.driver_data = &t7166xb_mmc_data,
+		.mfd_data = &t7166xb_mmc_data,
 		.num_resources = ARRAY_SIZE(t7l66xb_mmc_resources),
 		.resources = t7l66xb_mmc_resources,
 	},
@@ -186,7 +186,7 @@
 /* Handle the T7L66XB interrupt mux */
 static void t7l66xb_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct t7l66xb *t7l66xb = get_irq_data(irq);
+	struct t7l66xb *t7l66xb = irq_get_handler_data(irq);
 	unsigned int isr;
 	unsigned int i, irq_base;
 
@@ -243,17 +243,16 @@
 	irq_base = t7l66xb->irq_base;
 
 	for (irq = irq_base; irq < irq_base + T7L66XB_NR_IRQS; irq++) {
-		set_irq_chip(irq, &t7l66xb_chip);
-		set_irq_chip_data(irq, t7l66xb);
-		set_irq_handler(irq, handle_level_irq);
+		irq_set_chip_and_handler(irq, &t7l66xb_chip, handle_level_irq);
+		irq_set_chip_data(irq, t7l66xb);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 #endif
 	}
 
-	set_irq_type(t7l66xb->irq, IRQ_TYPE_EDGE_FALLING);
-	set_irq_data(t7l66xb->irq, t7l66xb);
-	set_irq_chained_handler(t7l66xb->irq, t7l66xb_irq);
+	irq_set_irq_type(t7l66xb->irq, IRQ_TYPE_EDGE_FALLING);
+	irq_set_handler_data(t7l66xb->irq, t7l66xb);
+	irq_set_chained_handler(t7l66xb->irq, t7l66xb_irq);
 }
 
 static void t7l66xb_detach_irq(struct platform_device *dev)
@@ -263,15 +262,15 @@
 
 	irq_base = t7l66xb->irq_base;
 
-	set_irq_chained_handler(t7l66xb->irq, NULL);
-	set_irq_data(t7l66xb->irq, NULL);
+	irq_set_chained_handler(t7l66xb->irq, NULL);
+	irq_set_handler_data(t7l66xb->irq, NULL);
 
 	for (irq = irq_base; irq < irq_base + T7L66XB_NR_IRQS; irq++) {
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip(irq, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip(irq, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
@@ -383,16 +382,7 @@
 
 	t7l66xb_attach_irq(dev);
 
-	t7l66xb_cells[T7L66XB_CELL_NAND].driver_data = pdata->nand_data;
-	t7l66xb_cells[T7L66XB_CELL_NAND].platform_data =
-		&t7l66xb_cells[T7L66XB_CELL_NAND];
-	t7l66xb_cells[T7L66XB_CELL_NAND].data_size =
-		sizeof(t7l66xb_cells[T7L66XB_CELL_NAND]);
-
-	t7l66xb_cells[T7L66XB_CELL_MMC].platform_data =
-		&t7l66xb_cells[T7L66XB_CELL_MMC];
-	t7l66xb_cells[T7L66XB_CELL_MMC].data_size =
-		sizeof(t7l66xb_cells[T7L66XB_CELL_MMC]);
+	t7l66xb_cells[T7L66XB_CELL_NAND].mfd_data = pdata->nand_data;
 
 	ret = mfd_add_devices(&dev->dev, dev->id,
 			      t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/tc3589x.c linux-libre-2.6.39-gnu/drivers/mfd/tc3589x.c
--- linux-libre-2.6.38-gnu/drivers/mfd/tc3589x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/tc3589x.c	2011-05-19 00:06:34.000000000 -0400
@@ -192,14 +192,14 @@
 	int irq;
 
 	for (irq = base; irq < base + TC3589x_NR_INTERNAL_IRQS; irq++) {
-		set_irq_chip_data(irq, tc3589x);
-		set_irq_chip_and_handler(irq, &dummy_irq_chip,
+		irq_set_chip_data(irq, tc3589x);
+		irq_set_chip_and_handler(irq, &dummy_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(irq, 1);
+		irq_set_nested_thread(irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, IRQF_VALID);
 #else
-		set_irq_noprobe(irq);
+		irq_set_noprobe(irq);
 #endif
 	}
 
@@ -215,8 +215,8 @@
 #ifdef CONFIG_ARM
 		set_irq_flags(irq, 0);
 #endif
-		set_irq_chip_and_handler(irq, NULL, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip_and_handler(irq, NULL, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/tc6387xb.c linux-libre-2.6.39-gnu/drivers/mfd/tc6387xb.c
--- linux-libre-2.6.38-gnu/drivers/mfd/tc6387xb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/tc6387xb.c	2011-05-19 00:06:34.000000000 -0400
@@ -131,7 +131,7 @@
 		.name = "tmio-mmc",
 		.enable = tc6387xb_mmc_enable,
 		.disable = tc6387xb_mmc_disable,
-		.driver_data = &tc6387xb_mmc_data,
+		.mfd_data = &tc6387xb_mmc_data,
 		.num_resources = ARRAY_SIZE(tc6387xb_mmc_resources),
 		.resources = tc6387xb_mmc_resources,
 	},
@@ -190,11 +190,6 @@
 
 	printk(KERN_INFO "Toshiba tc6387xb initialised\n");
 
-	tc6387xb_cells[TC6387XB_CELL_MMC].platform_data =
-		&tc6387xb_cells[TC6387XB_CELL_MMC];
-	tc6387xb_cells[TC6387XB_CELL_MMC].data_size =
-		sizeof(tc6387xb_cells[TC6387XB_CELL_MMC]);
-
 	ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
 			      ARRAY_SIZE(tc6387xb_cells), iomem, irq);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/tc6393xb.c linux-libre-2.6.39-gnu/drivers/mfd/tc6393xb.c
--- linux-libre-2.6.38-gnu/drivers/mfd/tc6393xb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/tc6393xb.c	2011-05-19 00:06:34.000000000 -0400
@@ -393,7 +393,7 @@
 		.name = "tmio-mmc",
 		.enable = tc6393xb_mmc_enable,
 		.resume = tc6393xb_mmc_resume,
-		.driver_data = &tc6393xb_mmc_data,
+		.mfd_data = &tc6393xb_mmc_data,
 		.num_resources = ARRAY_SIZE(tc6393xb_mmc_resources),
 		.resources = tc6393xb_mmc_resources,
 	},
@@ -513,7 +513,7 @@
 static void
 tc6393xb_irq(unsigned int irq, struct irq_desc *desc)
 {
-	struct tc6393xb *tc6393xb = get_irq_data(irq);
+	struct tc6393xb *tc6393xb = irq_get_handler_data(irq);
 	unsigned int isr;
 	unsigned int i, irq_base;
 
@@ -572,15 +572,14 @@
 	irq_base = tc6393xb->irq_base;
 
 	for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
-		set_irq_chip(irq, &tc6393xb_chip);
-		set_irq_chip_data(irq, tc6393xb);
-		set_irq_handler(irq, handle_edge_irq);
+		irq_set_chip_and_handler(irq, &tc6393xb_chip, handle_edge_irq);
+		irq_set_chip_data(irq, tc6393xb);
 		set_irq_flags(irq, IRQF_VALID | IRQF_PROBE);
 	}
 
-	set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
-	set_irq_data(tc6393xb->irq, tc6393xb);
-	set_irq_chained_handler(tc6393xb->irq, tc6393xb_irq);
+	irq_set_irq_type(tc6393xb->irq, IRQ_TYPE_EDGE_FALLING);
+	irq_set_handler_data(tc6393xb->irq, tc6393xb);
+	irq_set_chained_handler(tc6393xb->irq, tc6393xb_irq);
 }
 
 static void tc6393xb_detach_irq(struct platform_device *dev)
@@ -588,15 +587,15 @@
 	struct tc6393xb *tc6393xb = platform_get_drvdata(dev);
 	unsigned int irq, irq_base;
 
-	set_irq_chained_handler(tc6393xb->irq, NULL);
-	set_irq_data(tc6393xb->irq, NULL);
+	irq_set_chained_handler(tc6393xb->irq, NULL);
+	irq_set_handler_data(tc6393xb->irq, NULL);
 
 	irq_base = tc6393xb->irq_base;
 
 	for (irq = irq_base; irq < irq_base + TC6393XB_NR_IRQS; irq++) {
 		set_irq_flags(irq, 0);
-		set_irq_chip(irq, NULL);
-		set_irq_chip_data(irq, NULL);
+		irq_set_chip(irq, NULL);
+		irq_set_chip_data(irq, NULL);
 	}
 }
 
@@ -693,27 +692,8 @@
 			goto err_setup;
 	}
 
-	tc6393xb_cells[TC6393XB_CELL_NAND].driver_data = tcpd->nand_data;
-	tc6393xb_cells[TC6393XB_CELL_NAND].platform_data =
-		&tc6393xb_cells[TC6393XB_CELL_NAND];
-	tc6393xb_cells[TC6393XB_CELL_NAND].data_size =
-		sizeof(tc6393xb_cells[TC6393XB_CELL_NAND]);
-
-	tc6393xb_cells[TC6393XB_CELL_MMC].platform_data =
-		&tc6393xb_cells[TC6393XB_CELL_MMC];
-	tc6393xb_cells[TC6393XB_CELL_MMC].data_size =
-		sizeof(tc6393xb_cells[TC6393XB_CELL_MMC]);
-
-	tc6393xb_cells[TC6393XB_CELL_OHCI].platform_data =
-		&tc6393xb_cells[TC6393XB_CELL_OHCI];
-	tc6393xb_cells[TC6393XB_CELL_OHCI].data_size =
-		sizeof(tc6393xb_cells[TC6393XB_CELL_OHCI]);
-
-	tc6393xb_cells[TC6393XB_CELL_FB].driver_data = tcpd->fb_data;
-	tc6393xb_cells[TC6393XB_CELL_FB].platform_data =
-		&tc6393xb_cells[TC6393XB_CELL_FB];
-	tc6393xb_cells[TC6393XB_CELL_FB].data_size =
-		sizeof(tc6393xb_cells[TC6393XB_CELL_FB]);
+	tc6393xb_cells[TC6393XB_CELL_NAND].mfd_data = tcpd->nand_data;
+	tc6393xb_cells[TC6393XB_CELL_FB].mfd_data = tcpd->fb_data;
 
 	ret = mfd_add_devices(&dev->dev, dev->id,
 			tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/timberdale.c linux-libre-2.6.39-gnu/drivers/mfd/timberdale.c
--- linux-libre-2.6.38-gnu/drivers/mfd/timberdale.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/timberdale.c	2011-05-19 00:06:34.000000000 -0400
@@ -384,8 +384,7 @@
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
 		.resources = timberdale_dma_resources,
-		.platform_data = &timb_dma_platform_data,
-		.data_size = sizeof(timb_dma_platform_data),
+		.mfd_data = &timb_dma_platform_data,
 	},
 	{
 		.name = "timb-uart",
@@ -396,43 +395,37 @@
 		.name = "xiic-i2c",
 		.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
 		.resources = timberdale_xiic_resources,
-		.platform_data = &timberdale_xiic_platform_data,
-		.data_size = sizeof(timberdale_xiic_platform_data),
+		.mfd_data = &timberdale_xiic_platform_data,
 	},
 	{
 		.name = "timb-gpio",
 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
 		.resources = timberdale_gpio_resources,
-		.platform_data = &timberdale_gpio_platform_data,
-		.data_size = sizeof(timberdale_gpio_platform_data),
+		.mfd_data = &timberdale_gpio_platform_data,
 	},
 	{
 		.name = "timb-video",
 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
 		.resources = timberdale_video_resources,
-		.platform_data = &timberdale_video_platform_data,
-		.data_size = sizeof(timberdale_video_platform_data),
+		.mfd_data = &timberdale_video_platform_data,
 	},
 	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
-		.platform_data = &timberdale_radio_platform_data,
-		.data_size = sizeof(timberdale_radio_platform_data),
+		.mfd_data = &timberdale_radio_platform_data,
 	},
 	{
 		.name = "xilinx_spi",
 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
 		.resources = timberdale_spi_resources,
-		.platform_data = &timberdale_xspi_platform_data,
-		.data_size = sizeof(timberdale_xspi_platform_data),
+		.mfd_data = &timberdale_xspi_platform_data,
 	},
 	{
 		.name = "ks8842",
 		.num_resources = ARRAY_SIZE(timberdale_eth_resources),
 		.resources = timberdale_eth_resources,
-		.platform_data = &timberdale_ks8842_platform_data,
-		.data_size = sizeof(timberdale_ks8842_platform_data)
+		.mfd_data = &timberdale_ks8842_platform_data,
 	},
 };
 
@@ -441,8 +434,7 @@
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
 		.resources = timberdale_dma_resources,
-		.platform_data = &timb_dma_platform_data,
-		.data_size = sizeof(timb_dma_platform_data),
+		.mfd_data = &timb_dma_platform_data,
 	},
 	{
 		.name = "timb-uart",
@@ -458,15 +450,13 @@
 		.name = "xiic-i2c",
 		.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
 		.resources = timberdale_xiic_resources,
-		.platform_data = &timberdale_xiic_platform_data,
-		.data_size = sizeof(timberdale_xiic_platform_data),
+		.mfd_data = &timberdale_xiic_platform_data,
 	},
 	{
 		.name = "timb-gpio",
 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
 		.resources = timberdale_gpio_resources,
-		.platform_data = &timberdale_gpio_platform_data,
-		.data_size = sizeof(timberdale_gpio_platform_data),
+		.mfd_data = &timberdale_gpio_platform_data,
 	},
 	{
 		.name = "timb-mlogicore",
@@ -477,29 +467,25 @@
 		.name = "timb-video",
 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
 		.resources = timberdale_video_resources,
-		.platform_data = &timberdale_video_platform_data,
-		.data_size = sizeof(timberdale_video_platform_data),
+		.mfd_data = &timberdale_video_platform_data,
 	},
 	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
-		.platform_data = &timberdale_radio_platform_data,
-		.data_size = sizeof(timberdale_radio_platform_data),
+		.mfd_data = &timberdale_radio_platform_data,
 	},
 	{
 		.name = "xilinx_spi",
 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
 		.resources = timberdale_spi_resources,
-		.platform_data = &timberdale_xspi_platform_data,
-		.data_size = sizeof(timberdale_xspi_platform_data),
+		.mfd_data = &timberdale_xspi_platform_data,
 	},
 	{
 		.name = "ks8842",
 		.num_resources = ARRAY_SIZE(timberdale_eth_resources),
 		.resources = timberdale_eth_resources,
-		.platform_data = &timberdale_ks8842_platform_data,
-		.data_size = sizeof(timberdale_ks8842_platform_data)
+		.mfd_data = &timberdale_ks8842_platform_data,
 	},
 };
 
@@ -508,8 +494,7 @@
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
 		.resources = timberdale_dma_resources,
-		.platform_data = &timb_dma_platform_data,
-		.data_size = sizeof(timb_dma_platform_data),
+		.mfd_data = &timb_dma_platform_data,
 	},
 	{
 		.name = "timb-uart",
@@ -520,36 +505,31 @@
 		.name = "xiic-i2c",
 		.num_resources = ARRAY_SIZE(timberdale_xiic_resources),
 		.resources = timberdale_xiic_resources,
-		.platform_data = &timberdale_xiic_platform_data,
-		.data_size = sizeof(timberdale_xiic_platform_data),
+		.mfd_data = &timberdale_xiic_platform_data,
 	},
 	{
 		.name = "timb-gpio",
 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
 		.resources = timberdale_gpio_resources,
-		.platform_data = &timberdale_gpio_platform_data,
-		.data_size = sizeof(timberdale_gpio_platform_data),
+		.mfd_data = &timberdale_gpio_platform_data,
 	},
 	{
 		.name = "timb-video",
 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
 		.resources = timberdale_video_resources,
-		.platform_data = &timberdale_video_platform_data,
-		.data_size = sizeof(timberdale_video_platform_data),
+		.mfd_data = &timberdale_video_platform_data,
 	},
 	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
-		.platform_data = &timberdale_radio_platform_data,
-		.data_size = sizeof(timberdale_radio_platform_data),
+		.mfd_data = &timberdale_radio_platform_data,
 	},
 	{
 		.name = "xilinx_spi",
 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
 		.resources = timberdale_spi_resources,
-		.platform_data = &timberdale_xspi_platform_data,
-		.data_size = sizeof(timberdale_xspi_platform_data),
+		.mfd_data = &timberdale_xspi_platform_data,
 	},
 };
 
@@ -558,8 +538,7 @@
 		.name = "timb-dma",
 		.num_resources = ARRAY_SIZE(timberdale_dma_resources),
 		.resources = timberdale_dma_resources,
-		.platform_data = &timb_dma_platform_data,
-		.data_size = sizeof(timb_dma_platform_data),
+		.mfd_data = &timb_dma_platform_data,
 	},
 	{
 		.name = "timb-uart",
@@ -570,43 +549,37 @@
 		.name = "ocores-i2c",
 		.num_resources = ARRAY_SIZE(timberdale_ocores_resources),
 		.resources = timberdale_ocores_resources,
-		.platform_data = &timberdale_ocores_platform_data,
-		.data_size = sizeof(timberdale_ocores_platform_data),
+		.mfd_data = &timberdale_ocores_platform_data,
 	},
 	{
 		.name = "timb-gpio",
 		.num_resources = ARRAY_SIZE(timberdale_gpio_resources),
 		.resources = timberdale_gpio_resources,
-		.platform_data = &timberdale_gpio_platform_data,
-		.data_size = sizeof(timberdale_gpio_platform_data),
+		.mfd_data = &timberdale_gpio_platform_data,
 	},
 	{
 		.name = "timb-video",
 		.num_resources = ARRAY_SIZE(timberdale_video_resources),
 		.resources = timberdale_video_resources,
-		.platform_data = &timberdale_video_platform_data,
-		.data_size = sizeof(timberdale_video_platform_data),
+		.mfd_data = &timberdale_video_platform_data,
 	},
 	{
 		.name = "timb-radio",
 		.num_resources = ARRAY_SIZE(timberdale_radio_resources),
 		.resources = timberdale_radio_resources,
-		.platform_data = &timberdale_radio_platform_data,
-		.data_size = sizeof(timberdale_radio_platform_data),
+		.mfd_data = &timberdale_radio_platform_data,
 	},
 	{
 		.name = "xilinx_spi",
 		.num_resources = ARRAY_SIZE(timberdale_spi_resources),
 		.resources = timberdale_spi_resources,
-		.platform_data = &timberdale_xspi_platform_data,
-		.data_size = sizeof(timberdale_xspi_platform_data),
+		.mfd_data = &timberdale_xspi_platform_data,
 	},
 	{
 		.name = "ks8842",
 		.num_resources = ARRAY_SIZE(timberdale_eth_resources),
 		.resources = timberdale_eth_resources,
-		.platform_data = &timberdale_ks8842_platform_data,
-		.data_size = sizeof(timberdale_ks8842_platform_data)
+		.mfd_data = &timberdale_ks8842_platform_data,
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ti-ssp.c linux-libre-2.6.39-gnu/drivers/mfd/ti-ssp.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ti-ssp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/ti-ssp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,476 @@
+/*
+ * Sequencer Serial Port (SSP) driver for Texas Instruments' SoCs
+ *
+ * Copyright (C) 2010 Texas Instruments 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/wait.h>
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/ti_ssp.h>
+
+/* Register Offsets */
+#define REG_REV		0x00
+#define REG_IOSEL_1	0x04
+#define REG_IOSEL_2	0x08
+#define REG_PREDIV	0x0c
+#define REG_INTR_ST	0x10
+#define REG_INTR_EN	0x14
+#define REG_TEST_CTRL	0x18
+
+/* Per port registers */
+#define PORT_CFG_2	0x00
+#define PORT_ADDR	0x04
+#define PORT_DATA	0x08
+#define PORT_CFG_1	0x0c
+#define PORT_STATE	0x10
+
+#define SSP_PORT_CONFIG_MASK	(SSP_EARLY_DIN | SSP_DELAY_DOUT)
+#define SSP_PORT_CLKRATE_MASK	0x0f
+
+#define SSP_SEQRAM_WR_EN	BIT(4)
+#define SSP_SEQRAM_RD_EN	BIT(5)
+#define SSP_START		BIT(15)
+#define SSP_BUSY		BIT(10)
+#define SSP_PORT_ASL		BIT(7)
+#define SSP_PORT_CFO1		BIT(6)
+
+#define SSP_PORT_SEQRAM_SIZE	32
+
+static const int ssp_port_base[]   = {0x040, 0x080};
+static const int ssp_port_seqram[] = {0x100, 0x180};
+
+struct ti_ssp {
+	struct resource		*res;
+	struct device		*dev;
+	void __iomem		*regs;
+	spinlock_t		lock;
+	struct clk		*clk;
+	int			irq;
+	wait_queue_head_t	wqh;
+
+	/*
+	 * Some of the iosel2 register bits always read-back as 0, we need to
+	 * remember these values so that we don't clobber previously set
+	 * values.
+	 */
+	u32			iosel2;
+};
+
+static inline struct ti_ssp *dev_to_ssp(struct device *dev)
+{
+	return dev_get_drvdata(dev->parent);
+}
+
+static inline int dev_to_port(struct device *dev)
+{
+	return to_platform_device(dev)->id;
+}
+
+/* Register Access Helpers, rmw() functions need to run locked */
+static inline u32 ssp_read(struct ti_ssp *ssp, int reg)
+{
+	return __raw_readl(ssp->regs + reg);
+}
+
+static inline void ssp_write(struct ti_ssp *ssp, int reg, u32 val)
+{
+	__raw_writel(val, ssp->regs + reg);
+}
+
+static inline void ssp_rmw(struct ti_ssp *ssp, int reg, u32 mask, u32 bits)
+{
+	ssp_write(ssp, reg, (ssp_read(ssp, reg) & ~mask) | bits);
+}
+
+static inline u32 ssp_port_read(struct ti_ssp *ssp, int port, int reg)
+{
+	return ssp_read(ssp, ssp_port_base[port] + reg);
+}
+
+static inline void ssp_port_write(struct ti_ssp *ssp, int port, int reg,
+				  u32 val)
+{
+	ssp_write(ssp, ssp_port_base[port] + reg, val);
+}
+
+static inline void ssp_port_rmw(struct ti_ssp *ssp, int port, int reg,
+				u32 mask, u32 bits)
+{
+	ssp_rmw(ssp, ssp_port_base[port] + reg, mask, bits);
+}
+
+static inline void ssp_port_clr_bits(struct ti_ssp *ssp, int port, int reg,
+				     u32 bits)
+{
+	ssp_port_rmw(ssp, port, reg, bits, 0);
+}
+
+static inline void ssp_port_set_bits(struct ti_ssp *ssp, int port, int reg,
+				     u32 bits)
+{
+	ssp_port_rmw(ssp, port, reg, 0, bits);
+}
+
+/* Called to setup port clock mode, caller must hold ssp->lock */
+static int __set_mode(struct ti_ssp *ssp, int port, int mode)
+{
+	mode &= SSP_PORT_CONFIG_MASK;
+	ssp_port_rmw(ssp, port, PORT_CFG_1, SSP_PORT_CONFIG_MASK, mode);
+
+	return 0;
+}
+
+int ti_ssp_set_mode(struct device *dev, int mode)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int ret;
+
+	spin_lock(&ssp->lock);
+	ret = __set_mode(ssp, port, mode);
+	spin_unlock(&ssp->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL(ti_ssp_set_mode);
+
+/* Called to setup iosel2, caller must hold ssp->lock */
+static void __set_iosel2(struct ti_ssp *ssp, u32 mask, u32 val)
+{
+	ssp->iosel2 = (ssp->iosel2 & ~mask) | val;
+	ssp_write(ssp, REG_IOSEL_2, ssp->iosel2);
+}
+
+/* Called to setup port iosel, caller must hold ssp->lock */
+static void __set_iosel(struct ti_ssp *ssp, int port, u32 iosel)
+{
+	unsigned val, shift = port ? 16 : 0;
+
+	/* IOSEL1 gets the least significant 16 bits */
+	val = ssp_read(ssp, REG_IOSEL_1);
+	val &= 0xffff << (port ? 0 : 16);
+	val |= (iosel & 0xffff) << (port ? 16 : 0);
+	ssp_write(ssp, REG_IOSEL_1, val);
+
+	/* IOSEL2 gets the most significant 16 bits */
+	val = (iosel >> 16) & 0x7;
+	__set_iosel2(ssp, 0x7 << shift, val << shift);
+}
+
+int ti_ssp_set_iosel(struct device *dev, u32 iosel)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+
+	spin_lock(&ssp->lock);
+	__set_iosel(ssp, port, iosel);
+	spin_unlock(&ssp->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ti_ssp_set_iosel);
+
+int ti_ssp_load(struct device *dev, int offs, u32* prog, int len)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int i;
+
+	if (len > SSP_PORT_SEQRAM_SIZE)
+		return -ENOSPC;
+
+	spin_lock(&ssp->lock);
+
+	/* Enable SeqRAM access */
+	ssp_port_set_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
+
+	/* Copy code */
+	for (i = 0; i < len; i++) {
+		__raw_writel(prog[i], ssp->regs + offs + 4*i +
+			     ssp_port_seqram[port]);
+	}
+
+	/* Disable SeqRAM access */
+	ssp_port_clr_bits(ssp, port, PORT_CFG_2, SSP_SEQRAM_WR_EN);
+
+	spin_unlock(&ssp->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ti_ssp_load);
+
+int ti_ssp_raw_read(struct device *dev)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int shift = port ? 27 : 11;
+
+	return (ssp_read(ssp, REG_IOSEL_2) >> shift) & 0xf;
+}
+EXPORT_SYMBOL(ti_ssp_raw_read);
+
+int ti_ssp_raw_write(struct device *dev, u32 val)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev), shift;
+
+	spin_lock(&ssp->lock);
+
+	shift = port ? 22 : 6;
+	val &= 0xf;
+	__set_iosel2(ssp, 0xf << shift, val << shift);
+
+	spin_unlock(&ssp->lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(ti_ssp_raw_write);
+
+static inline int __xfer_done(struct ti_ssp *ssp, int port)
+{
+	return !(ssp_port_read(ssp, port, PORT_CFG_1) & SSP_BUSY);
+}
+
+int ti_ssp_run(struct device *dev, u32 pc, u32 input, u32 *output)
+{
+	struct ti_ssp *ssp = dev_to_ssp(dev);
+	int port = dev_to_port(dev);
+	int ret;
+
+	if (pc & ~(0x3f))
+		return -EINVAL;
+
+	/* Grab ssp->lock to serialize rmw on ssp registers */
+	spin_lock(&ssp->lock);
+
+	ssp_port_write(ssp, port, PORT_ADDR, input >> 16);
+	ssp_port_write(ssp, port, PORT_DATA, input & 0xffff);
+	ssp_port_rmw(ssp, port, PORT_CFG_1, 0x3f, pc);
+
+	/* grab wait queue head lock to avoid race with the isr */
+	spin_lock_irq(&ssp->wqh.lock);
+
+	/* kick off sequence execution in hardware */
+	ssp_port_set_bits(ssp, port, PORT_CFG_1, SSP_START);
+
+	/* drop ssp lock; no register writes beyond this */
+	spin_unlock(&ssp->lock);
+
+	ret = wait_event_interruptible_locked_irq(ssp->wqh,
+						  __xfer_done(ssp, port));
+	spin_unlock_irq(&ssp->wqh.lock);
+
+	if (ret < 0)
+		return ret;
+
+	if (output) {
+		*output = (ssp_port_read(ssp, port, PORT_ADDR) << 16) |
+			  (ssp_port_read(ssp, port, PORT_DATA) &  0xffff);
+	}
+
+	ret = ssp_port_read(ssp, port, PORT_STATE) & 0x3f; /* stop address */
+
+	return ret;
+}
+EXPORT_SYMBOL(ti_ssp_run);
+
+static irqreturn_t ti_ssp_interrupt(int irq, void *dev_data)
+{
+	struct ti_ssp *ssp = dev_data;
+
+	spin_lock(&ssp->wqh.lock);
+
+	ssp_write(ssp, REG_INTR_ST, 0x3);
+	wake_up_locked(&ssp->wqh);
+
+	spin_unlock(&ssp->wqh.lock);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit ti_ssp_probe(struct platform_device *pdev)
+{
+	static struct ti_ssp *ssp;
+	const struct ti_ssp_data *pdata = pdev->dev.platform_data;
+	int error = 0, prediv = 0xff, id;
+	unsigned long sysclk;
+	struct device *dev = &pdev->dev;
+	struct mfd_cell cells[2];
+
+	ssp = kzalloc(sizeof(*ssp), GFP_KERNEL);
+	if (!ssp) {
+		dev_err(dev, "cannot allocate device info\n");
+		return -ENOMEM;
+	}
+
+	ssp->dev = dev;
+	dev_set_drvdata(dev, ssp);
+
+	ssp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ssp->res) {
+		error = -ENODEV;
+		dev_err(dev, "cannot determine register area\n");
+		goto error_res;
+	}
+
+	if (!request_mem_region(ssp->res->start, resource_size(ssp->res),
+				pdev->name)) {
+		error = -ENOMEM;
+		dev_err(dev, "cannot claim register memory\n");
+		goto error_res;
+	}
+
+	ssp->regs = ioremap(ssp->res->start, resource_size(ssp->res));
+	if (!ssp->regs) {
+		error = -ENOMEM;
+		dev_err(dev, "cannot map register memory\n");
+		goto error_map;
+	}
+
+	ssp->clk = clk_get(dev, NULL);
+	if (IS_ERR(ssp->clk)) {
+		error = PTR_ERR(ssp->clk);
+		dev_err(dev, "cannot claim device clock\n");
+		goto error_clk;
+	}
+
+	ssp->irq = platform_get_irq(pdev, 0);
+	if (ssp->irq < 0) {
+		error = -ENODEV;
+		dev_err(dev, "unknown irq\n");
+		goto error_irq;
+	}
+
+	error = request_threaded_irq(ssp->irq, NULL, ti_ssp_interrupt, 0,
+				     dev_name(dev), ssp);
+	if (error < 0) {
+		dev_err(dev, "cannot acquire irq\n");
+		goto error_irq;
+	}
+
+	spin_lock_init(&ssp->lock);
+	init_waitqueue_head(&ssp->wqh);
+
+	/* Power on and initialize SSP */
+	error = clk_enable(ssp->clk);
+	if (error) {
+		dev_err(dev, "cannot enable device clock\n");
+		goto error_enable;
+	}
+
+	/* Reset registers to a sensible known state */
+	ssp_write(ssp, REG_IOSEL_1, 0);
+	ssp_write(ssp, REG_IOSEL_2, 0);
+	ssp_write(ssp, REG_INTR_EN, 0x3);
+	ssp_write(ssp, REG_INTR_ST, 0x3);
+	ssp_write(ssp, REG_TEST_CTRL, 0);
+	ssp_port_write(ssp, 0, PORT_CFG_1, SSP_PORT_ASL);
+	ssp_port_write(ssp, 1, PORT_CFG_1, SSP_PORT_ASL);
+	ssp_port_write(ssp, 0, PORT_CFG_2, SSP_PORT_CFO1);
+	ssp_port_write(ssp, 1, PORT_CFG_2, SSP_PORT_CFO1);
+
+	sysclk = clk_get_rate(ssp->clk);
+	if (pdata && pdata->out_clock)
+		prediv = (sysclk / pdata->out_clock) - 1;
+	prediv = clamp(prediv, 0, 0xff);
+	ssp_rmw(ssp, REG_PREDIV, 0xff, prediv);
+
+	memset(cells, 0, sizeof(cells));
+	for (id = 0; id < 2; id++) {
+		const struct ti_ssp_dev_data *data = &pdata->dev_data[id];
+
+		cells[id].id		= id;
+		cells[id].name		= data->dev_name;
+		cells[id].platform_data	= data->pdata;
+		cells[id].data_size	= data->pdata_size;
+	}
+
+	error = mfd_add_devices(dev, 0, cells, 2, NULL, 0);
+	if (error < 0) {
+		dev_err(dev, "cannot add mfd cells\n");
+		goto error_enable;
+	}
+
+	return 0;
+
+error_enable:
+	free_irq(ssp->irq, ssp);
+error_irq:
+	clk_put(ssp->clk);
+error_clk:
+	iounmap(ssp->regs);
+error_map:
+	release_mem_region(ssp->res->start, resource_size(ssp->res));
+error_res:
+	kfree(ssp);
+	return error;
+}
+
+static int __devexit ti_ssp_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct ti_ssp *ssp = dev_get_drvdata(dev);
+
+	mfd_remove_devices(dev);
+	clk_disable(ssp->clk);
+	free_irq(ssp->irq, ssp);
+	clk_put(ssp->clk);
+	iounmap(ssp->regs);
+	release_mem_region(ssp->res->start, resource_size(ssp->res));
+	kfree(ssp);
+	dev_set_drvdata(dev, NULL);
+	return 0;
+}
+
+static struct platform_driver ti_ssp_driver = {
+	.probe		= ti_ssp_probe,
+	.remove		= __devexit_p(ti_ssp_remove),
+	.driver		= {
+		.name	= "ti-ssp",
+		.owner	= THIS_MODULE,
+	}
+};
+
+static int __init ti_ssp_init(void)
+{
+	return platform_driver_register(&ti_ssp_driver);
+}
+module_init(ti_ssp_init);
+
+static void __exit ti_ssp_exit(void)
+{
+	platform_driver_unregister(&ti_ssp_driver);
+}
+module_exit(ti_ssp_exit);
+
+MODULE_DESCRIPTION("Sequencer Serial Port (SSP) Driver");
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ti-ssp");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/tps6105x.c linux-libre-2.6.39-gnu/drivers/mfd/tps6105x.c
--- linux-libre-2.6.38-gnu/drivers/mfd/tps6105x.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/tps6105x.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,246 @@
+/*
+ * Core driver for TPS61050/61052 boost converters, used for while LED
+ * driving, audio power amplification, white LED flash, and generic
+ * boost conversion. Additionally it provides a 1-bit GPIO pin (out or in)
+ * and a flash synchronization pin to synchronize flash events when used as
+ * flashgun.
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+#include <linux/gpio.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps6105x.h>
+
+int tps6105x_set(struct tps6105x *tps6105x, u8 reg, u8 value)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&tps6105x->lock);
+	if (ret)
+		return ret;
+	ret = i2c_smbus_write_byte_data(tps6105x->client, reg, value);
+	mutex_unlock(&tps6105x->lock);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(tps6105x_set);
+
+int tps6105x_get(struct tps6105x *tps6105x, u8 reg, u8 *buf)
+{
+	int ret;
+
+	ret = mutex_lock_interruptible(&tps6105x->lock);
+	if (ret)
+		return ret;
+	ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
+	mutex_unlock(&tps6105x->lock);
+	if (ret < 0)
+		return ret;
+
+	*buf = ret;
+	return 0;
+}
+EXPORT_SYMBOL(tps6105x_get);
+
+/*
+ * Masks off the bits in the mask and sets the bits in the bitvalues
+ * parameter in one atomic operation
+ */
+int tps6105x_mask_and_set(struct tps6105x *tps6105x, u8 reg,
+			  u8 bitmask, u8 bitvalues)
+{
+	int ret;
+	u8 regval;
+
+	ret = mutex_lock_interruptible(&tps6105x->lock);
+	if (ret)
+		return ret;
+	ret = i2c_smbus_read_byte_data(tps6105x->client, reg);
+	if (ret < 0)
+		goto fail;
+	regval = ret;
+	regval = (~bitmask & regval) | (bitmask & bitvalues);
+	ret = i2c_smbus_write_byte_data(tps6105x->client, reg, regval);
+fail:
+	mutex_unlock(&tps6105x->lock);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+EXPORT_SYMBOL(tps6105x_mask_and_set);
+
+static int __devinit tps6105x_startup(struct tps6105x *tps6105x)
+{
+	int ret;
+	u8 regval;
+
+	ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+	if (ret)
+		return ret;
+	switch (regval >> TPS6105X_REG0_MODE_SHIFT) {
+	case TPS6105X_REG0_MODE_SHUTDOWN:
+		dev_info(&tps6105x->client->dev,
+			 "TPS6105x found in SHUTDOWN mode\n");
+		break;
+	case TPS6105X_REG0_MODE_TORCH:
+		dev_info(&tps6105x->client->dev,
+			 "TPS6105x found in TORCH mode\n");
+		break;
+	case TPS6105X_REG0_MODE_TORCH_FLASH:
+		dev_info(&tps6105x->client->dev,
+			 "TPS6105x found in FLASH mode\n");
+		break;
+	case TPS6105X_REG0_MODE_VOLTAGE:
+		dev_info(&tps6105x->client->dev,
+			 "TPS6105x found in VOLTAGE mode\n");
+		break;
+	default:
+		break;
+	}
+
+	return ret;
+}
+
+/*
+ * MFD cells - we have one cell which is selected operation
+ * mode, and we always have a GPIO cell.
+ */
+static struct mfd_cell tps6105x_cells[] = {
+	{
+		/* name will be runtime assigned */
+		.id = -1,
+	},
+	{
+		.name = "tps6105x-gpio",
+		.id = -1,
+	},
+};
+
+static int __devinit tps6105x_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct tps6105x			*tps6105x;
+	struct tps6105x_platform_data	*pdata;
+	int ret;
+	int i;
+
+	tps6105x = kmalloc(sizeof(*tps6105x), GFP_KERNEL);
+	if (!tps6105x)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, tps6105x);
+	tps6105x->client = client;
+	pdata = client->dev.platform_data;
+	tps6105x->pdata = pdata;
+	mutex_init(&tps6105x->lock);
+
+	ret = tps6105x_startup(tps6105x);
+	if (ret) {
+		dev_err(&client->dev, "chip initialization failed\n");
+		goto fail;
+	}
+
+	/* Remove warning texts when you implement new cell drivers */
+	switch (pdata->mode) {
+	case TPS6105X_MODE_SHUTDOWN:
+		dev_info(&client->dev,
+			 "present, not used for anything, only GPIO\n");
+		break;
+	case TPS6105X_MODE_TORCH:
+		tps6105x_cells[0].name = "tps6105x-leds";
+		dev_warn(&client->dev,
+			 "torch mode is unsupported\n");
+		break;
+	case TPS6105X_MODE_TORCH_FLASH:
+		tps6105x_cells[0].name = "tps6105x-flash";
+		dev_warn(&client->dev,
+			 "flash mode is unsupported\n");
+		break;
+	case TPS6105X_MODE_VOLTAGE:
+		tps6105x_cells[0].name ="tps6105x-regulator";
+		break;
+	default:
+		break;
+	}
+
+	/* Set up and register the platform devices. */
+	for (i = 0; i < ARRAY_SIZE(tps6105x_cells); i++) {
+		/* One state holder for all drivers, this is simple */
+		tps6105x_cells[i].mfd_data = tps6105x;
+	}
+
+	ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
+		ARRAY_SIZE(tps6105x_cells), NULL, 0);
+	if (ret)
+		goto fail;
+
+	return 0;
+
+fail:
+	kfree(tps6105x);
+	return ret;
+}
+
+static int __devexit tps6105x_remove(struct i2c_client *client)
+{
+	struct tps6105x *tps6105x = i2c_get_clientdata(client);
+
+	mfd_remove_devices(&client->dev);
+
+	/* Put chip in shutdown mode */
+	tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+		TPS6105X_REG0_MODE_MASK,
+		TPS6105X_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
+
+	kfree(tps6105x);
+	return 0;
+}
+
+static const struct i2c_device_id tps6105x_id[] = {
+	{ "tps61050", 0 },
+	{ "tps61052", 0 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tps6105x_id);
+
+static struct i2c_driver tps6105x_driver = {
+	.driver = {
+		.name	= "tps6105x",
+	},
+	.probe		= tps6105x_probe,
+	.remove		= __devexit_p(tps6105x_remove),
+	.id_table	= tps6105x_id,
+};
+
+static int __init tps6105x_init(void)
+{
+	return i2c_add_driver(&tps6105x_driver);
+}
+subsys_initcall(tps6105x_init);
+
+static void __exit tps6105x_exit(void)
+{
+	i2c_del_driver(&tps6105x_driver);
+}
+module_exit(tps6105x_exit);
+
+MODULE_AUTHOR("Linus Walleij");
+MODULE_DESCRIPTION("TPS6105x White LED Boost Converter Driver");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/tps6586x.c linux-libre-2.6.39-gnu/drivers/mfd/tps6586x.c
--- linux-libre-2.6.38-gnu/drivers/mfd/tps6586x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/tps6586x.c	2011-05-19 00:06:34.000000000 -0400
@@ -288,12 +288,10 @@
 	return tps6586x_update(tps6586x->dev, TPS6586X_GPIOSET1, val, mask);
 }
 
-static void tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
+static int tps6586x_gpio_init(struct tps6586x *tps6586x, int gpio_base)
 {
-	int ret;
-
 	if (!gpio_base)
-		return;
+		return 0;
 
 	tps6586x->gpio.owner		= THIS_MODULE;
 	tps6586x->gpio.label		= tps6586x->client->name;
@@ -307,9 +305,7 @@
 	tps6586x->gpio.set		= tps6586x_gpio_set;
 	tps6586x->gpio.get		= tps6586x_gpio_get;
 
-	ret = gpiochip_add(&tps6586x->gpio);
-	if (ret)
-		dev_warn(tps6586x->dev, "GPIO registration failed: %d\n", ret);
+	return gpiochip_add(&tps6586x->gpio);
 }
 
 static int __remove_subdev(struct device *dev, void *unused)
@@ -426,10 +422,10 @@
 
 	for (i = 0; i < ARRAY_SIZE(tps6586x_irqs); i++) {
 		int __irq = i + tps6586x->irq_base;
-		set_irq_chip_data(__irq, tps6586x);
-		set_irq_chip_and_handler(__irq, &tps6586x->irq_chip,
+		irq_set_chip_data(__irq, tps6586x);
+		irq_set_chip_and_handler(__irq, &tps6586x->irq_chip,
 					 handle_simple_irq);
-		set_irq_nested_thread(__irq, 1);
+		irq_set_nested_thread(__irq, 1);
 #ifdef CONFIG_ARM
 		set_irq_flags(__irq, IRQF_VALID);
 #endif
@@ -517,17 +513,28 @@
 		}
 	}
 
+	ret = tps6586x_gpio_init(tps6586x, pdata->gpio_base);
+	if (ret) {
+		dev_err(&client->dev, "GPIO registration failed: %d\n", ret);
+		goto err_gpio_init;
+	}
+
 	ret = tps6586x_add_subdevs(tps6586x, pdata);
 	if (ret) {
 		dev_err(&client->dev, "add devices failed: %d\n", ret);
 		goto err_add_devs;
 	}
 
-	tps6586x_gpio_init(tps6586x, pdata->gpio_base);
-
 	return 0;
 
 err_add_devs:
+	if (pdata->gpio_base) {
+		ret = gpiochip_remove(&tps6586x->gpio);
+		if (ret)
+			dev_err(&client->dev, "Can't remove gpio chip: %d\n",
+				ret);
+	}
+err_gpio_init:
 	if (client->irq)
 		free_irq(client->irq, tps6586x);
 err_irq_init:
@@ -587,4 +594,3 @@
 MODULE_DESCRIPTION("TPS6586X core driver");
 MODULE_AUTHOR("Mike Rapoport <mike@compulab.co.il>");
 MODULE_LICENSE("GPL");
-
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/twl4030-codec.c linux-libre-2.6.39-gnu/drivers/mfd/twl4030-codec.c
--- linux-libre-2.6.38-gnu/drivers/mfd/twl4030-codec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/twl4030-codec.c	2011-05-19 00:06:34.000000000 -0400
@@ -208,15 +208,13 @@
 	if (pdata->audio) {
 		cell = &codec->cells[childs];
 		cell->name = "twl4030-codec";
-		cell->platform_data = pdata->audio;
-		cell->data_size = sizeof(*pdata->audio);
+		cell->mfd_data = pdata->audio;
 		childs++;
 	}
 	if (pdata->vibra) {
 		cell = &codec->cells[childs];
 		cell->name = "twl4030-vibra";
-		cell->platform_data = pdata->vibra;
-		cell->data_size = sizeof(*pdata->vibra);
+		cell->mfd_data = pdata->vibra;
 		childs++;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/twl4030-irq.c linux-libre-2.6.39-gnu/drivers/mfd/twl4030-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/twl4030-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/twl4030-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -320,24 +320,8 @@
 		for (module_irq = twl4030_irq_base;
 				pih_isr;
 				pih_isr >>= 1, module_irq++) {
-			if (pih_isr & 0x1) {
-				struct irq_desc *d = irq_to_desc(module_irq);
-
-				if (!d) {
-					pr_err("twl4030: Invalid SIH IRQ: %d\n",
-					       module_irq);
-					return -EINVAL;
-				}
-
-				/* These can't be masked ... always warn
-				 * if we get any surprises.
-				 */
-				if (d->status & IRQ_DISABLED)
-					note_interrupt(module_irq, d,
-							IRQ_NONE);
-				else
-					d->handle_irq(module_irq, d);
-			}
+			if (pih_isr & 0x1)
+				generic_handle_irq(module_irq);
 		}
 		local_irq_enable();
 
@@ -470,7 +454,7 @@
 	set_irq_flags(irq, IRQF_VALID);
 #else
 	/* same effect on other architectures */
-	set_irq_noprobe(irq);
+	irq_set_noprobe(irq);
 #endif
 }
 
@@ -560,24 +544,18 @@
 	/* Modify only the bits we know must change */
 	while (edge_change) {
 		int		i = fls(edge_change) - 1;
-		struct irq_desc	*d = irq_to_desc(i + agent->irq_base);
+		struct irq_data	*idata = irq_get_irq_data(i + agent->irq_base);
 		int		byte = 1 + (i >> 2);
 		int		off = (i & 0x3) * 2;
-
-		if (!d) {
-			pr_err("twl4030: Invalid IRQ: %d\n",
-			       i + agent->irq_base);
-			return;
-		}
+		unsigned int	type;
 
 		bytes[byte] &= ~(0x03 << off);
 
-		raw_spin_lock_irq(&d->lock);
-		if (d->status & IRQ_TYPE_EDGE_RISING)
+		type = irqd_get_trigger_type(idata);
+		if (type & IRQ_TYPE_EDGE_RISING)
 			bytes[byte] |= BIT(off + 1);
-		if (d->status & IRQ_TYPE_EDGE_FALLING)
+		if (type & IRQ_TYPE_EDGE_FALLING)
 			bytes[byte] |= BIT(off + 0);
-		raw_spin_unlock_irq(&d->lock);
 
 		edge_change &= ~BIT(i);
 	}
@@ -626,21 +604,13 @@
 static int twl4030_sih_set_type(struct irq_data *data, unsigned trigger)
 {
 	struct sih_agent *sih = irq_data_get_irq_chip_data(data);
-	struct irq_desc *desc = irq_to_desc(data->irq);
 	unsigned long flags;
 
-	if (!desc) {
-		pr_err("twl4030: Invalid IRQ: %d\n", data->irq);
-		return -EINVAL;
-	}
-
 	if (trigger & ~(IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
 		return -EINVAL;
 
 	spin_lock_irqsave(&sih_agent_lock, flags);
-	if ((desc->status & IRQ_TYPE_SENSE_MASK) != trigger) {
-		desc->status &= ~IRQ_TYPE_SENSE_MASK;
-		desc->status |= trigger;
+	if (irqd_get_trigger_type(data) != trigger) {
 		sih->edge_change |= BIT(data->irq - sih->irq_base);
 		queue_work(wq, &sih->edge_work);
 	}
@@ -680,7 +650,7 @@
  */
 static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc)
 {
-	struct sih_agent *agent = get_irq_data(irq);
+	struct sih_agent *agent = irq_get_handler_data(irq);
 	const struct sih *sih = agent->sih;
 	int isr;
 
@@ -754,9 +724,9 @@
 	for (i = 0; i < sih->bits; i++) {
 		irq = irq_base + i;
 
-		set_irq_chip_and_handler(irq, &twl4030_sih_irq_chip,
-				handle_edge_irq);
-		set_irq_chip_data(irq, agent);
+		irq_set_chip_and_handler(irq, &twl4030_sih_irq_chip,
+					 handle_edge_irq);
+		irq_set_chip_data(irq, agent);
 		activate_irq(irq);
 	}
 
@@ -765,8 +735,8 @@
 
 	/* replace generic PIH handler (handle_simple_irq) */
 	irq = sih_mod + twl4030_irq_base;
-	set_irq_data(irq, agent);
-	set_irq_chained_handler(irq, handle_twl4030_sih);
+	irq_set_handler_data(irq, agent);
+	irq_set_chained_handler(irq, handle_twl4030_sih);
 
 	pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name,
 			irq, irq_base, twl4030_irq_next - 1);
@@ -815,8 +785,8 @@
 	twl4030_sih_irq_chip.irq_ack = dummy_irq_chip.irq_ack;
 
 	for (i = irq_base; i < irq_end; i++) {
-		set_irq_chip_and_handler(i, &twl4030_irq_chip,
-				handle_simple_irq);
+		irq_set_chip_and_handler(i, &twl4030_irq_chip,
+					 handle_simple_irq);
 		activate_irq(i);
 	}
 	twl4030_irq_next = i;
@@ -856,7 +826,7 @@
 	/* clean up twl4030_sih_setup */
 fail:
 	for (i = irq_base; i < irq_end; i++)
-		set_irq_chip_and_handler(i, NULL, NULL);
+		irq_set_chip_and_handler(i, NULL, NULL);
 	destroy_workqueue(wq);
 	wq = NULL;
 	return status;
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/twl4030-madc.c linux-libre-2.6.39-gnu/drivers/mfd/twl4030-madc.c
--- linux-libre-2.6.38-gnu/drivers/mfd/twl4030-madc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mfd/twl4030-madc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,802 @@
+/*
+ *
+ * TWL4030 MADC module driver-This driver monitors the real time
+ * conversion of analog signals like battery temperature,
+ * battery type, battery level etc.
+ *
+ * Copyright (C) 2011 Texas Instruments Incorporated - http://www.ti.com/
+ * J Keerthy <j-keerthy@ti.com>
+ *
+ * Based on twl4030-madc.c
+ * Copyright (C) 2008 Nokia Corporation
+ * Mikko Ylinen <mikko.k.ylinen@nokia.com>
+ *
+ * Amit Kucheria <amit.kucheria@canonical.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
+ *
+ */
+
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/i2c/twl.h>
+#include <linux/i2c/twl4030-madc.h>
+#include <linux/module.h>
+#include <linux/stddef.h>
+#include <linux/mutex.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/types.h>
+#include <linux/gfp.h>
+#include <linux/err.h>
+
+/*
+ * struct twl4030_madc_data - a container for madc info
+ * @dev - pointer to device structure for madc
+ * @lock - mutex protecting this data structure
+ * @requests - Array of request struct corresponding to SW1, SW2 and RT
+ * @imr - Interrupt mask register of MADC
+ * @isr - Interrupt status register of MADC
+ */
+struct twl4030_madc_data {
+	struct device *dev;
+	struct mutex lock;	/* mutex protecting this data structure */
+	struct twl4030_madc_request requests[TWL4030_MADC_NUM_METHODS];
+	int imr;
+	int isr;
+};
+
+static struct twl4030_madc_data *twl4030_madc;
+
+struct twl4030_prescale_divider_ratios {
+	s16 numerator;
+	s16 denominator;
+};
+
+static const struct twl4030_prescale_divider_ratios
+twl4030_divider_ratios[16] = {
+	{1, 1},		/* CHANNEL 0 No Prescaler */
+	{1, 1},		/* CHANNEL 1 No Prescaler */
+	{6, 10},	/* CHANNEL 2 */
+	{6, 10},	/* CHANNEL 3 */
+	{6, 10},	/* CHANNEL 4 */
+	{6, 10},	/* CHANNEL 5 */
+	{6, 10},	/* CHANNEL 6 */
+	{6, 10},	/* CHANNEL 7 */
+	{3, 14},	/* CHANNEL 8 */
+	{1, 3},		/* CHANNEL 9 */
+	{1, 1},		/* CHANNEL 10 No Prescaler */
+	{15, 100},	/* CHANNEL 11 */
+	{1, 4},		/* CHANNEL 12 */
+	{1, 1},		/* CHANNEL 13 Reserved channels */
+	{1, 1},		/* CHANNEL 14 Reseved channels */
+	{5, 11},	/* CHANNEL 15 */
+};
+
+
+/*
+ * Conversion table from -3 to 55 degree Celcius
+ */
+static int therm_tbl[] = {
+30800,	29500,	28300,	27100,
+26000,	24900,	23900,	22900,	22000,	21100,	20300,	19400,	18700,	17900,
+17200,	16500,	15900,	15300,	14700,	14100,	13600,	13100,	12600,	12100,
+11600,	11200,	10800,	10400,	10000,	9630,	9280,	8950,	8620,	8310,
+8020,	7730,	7460,	7200,	6950,	6710,	6470,	6250,	6040,	5830,
+5640,	5450,	5260,	5090,	4920,	4760,	4600,	4450,	4310,	4170,
+4040,	3910,	3790,	3670,	3550
+};
+
+/*
+ * Structure containing the registers
+ * of different conversion methods supported by MADC.
+ * Hardware or RT real time conversion request initiated by external host
+ * processor for RT Signal conversions.
+ * External host processors can also request for non RT conversions
+ * SW1 and SW2 software conversions also called asynchronous or GPC request.
+ */
+static
+const struct twl4030_madc_conversion_method twl4030_conversion_methods[] = {
+	[TWL4030_MADC_RT] = {
+			     .sel = TWL4030_MADC_RTSELECT_LSB,
+			     .avg = TWL4030_MADC_RTAVERAGE_LSB,
+			     .rbase = TWL4030_MADC_RTCH0_LSB,
+			     },
+	[TWL4030_MADC_SW1] = {
+			      .sel = TWL4030_MADC_SW1SELECT_LSB,
+			      .avg = TWL4030_MADC_SW1AVERAGE_LSB,
+			      .rbase = TWL4030_MADC_GPCH0_LSB,
+			      .ctrl = TWL4030_MADC_CTRL_SW1,
+			      },
+	[TWL4030_MADC_SW2] = {
+			      .sel = TWL4030_MADC_SW2SELECT_LSB,
+			      .avg = TWL4030_MADC_SW2AVERAGE_LSB,
+			      .rbase = TWL4030_MADC_GPCH0_LSB,
+			      .ctrl = TWL4030_MADC_CTRL_SW2,
+			      },
+};
+
+/*
+ * Function to read a particular channel value.
+ * @madc - pointer to struct twl4030_madc_data
+ * @reg - lsb of ADC Channel
+ * If the i2c read fails it returns an error else returns 0.
+ */
+static int twl4030_madc_channel_raw_read(struct twl4030_madc_data *madc, u8 reg)
+{
+	u8 msb, lsb;
+	int ret;
+	/*
+	 * For each ADC channel, we have MSB and LSB register pair. MSB address
+	 * is always LSB address+1. reg parameter is the address of LSB register
+	 */
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &msb, reg + 1);
+	if (ret) {
+		dev_err(madc->dev, "unable to read MSB register 0x%X\n",
+			reg + 1);
+		return ret;
+	}
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &lsb, reg);
+	if (ret) {
+		dev_err(madc->dev, "unable to read LSB register 0x%X\n", reg);
+		return ret;
+	}
+
+	return (int)(((msb << 8) | lsb) >> 6);
+}
+
+/*
+ * Return battery temperature
+ * Or < 0 on failure.
+ */
+static int twl4030battery_temperature(int raw_volt)
+{
+	u8 val;
+	int temp, curr, volt, res, ret;
+
+	volt = (raw_volt * TEMP_STEP_SIZE) / TEMP_PSR_R;
+	/* Getting and calculating the supply current in micro ampers */
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+		REG_BCICTL2);
+	if (ret < 0)
+		return ret;
+	curr = ((val & TWL4030_BCI_ITHEN) + 1) * 10;
+	/* Getting and calculating the thermistor resistance in ohms */
+	res = volt * 1000 / curr;
+	/* calculating temperature */
+	for (temp = 58; temp >= 0; temp--) {
+		int actual = therm_tbl[temp];
+
+		if ((actual - res) >= 0)
+			break;
+	}
+
+	return temp + 1;
+}
+
+static int twl4030battery_current(int raw_volt)
+{
+	int ret;
+	u8 val;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE, &val,
+		TWL4030_BCI_BCICTL1);
+	if (ret)
+		return ret;
+	if (val & TWL4030_BCI_CGAIN) /* slope of 0.44 mV/mA */
+		return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R1;
+	else /* slope of 0.88 mV/mA */
+		return (raw_volt * CURR_STEP_SIZE) / CURR_PSR_R2;
+}
+/*
+ * Function to read channel values
+ * @madc - pointer to twl4030_madc_data struct
+ * @reg_base - Base address of the first channel
+ * @Channels - 16 bit bitmap. If the bit is set, channel value is read
+ * @buf - The channel values are stored here. if read fails error
+ * value is stored
+ * Returns the number of successfully read channels.
+ */
+static int twl4030_madc_read_channels(struct twl4030_madc_data *madc,
+				      u8 reg_base, unsigned
+						long channels, int *buf)
+{
+	int count = 0, count_req = 0, i;
+	u8 reg;
+
+	for_each_set_bit(i, &channels, TWL4030_MADC_MAX_CHANNELS) {
+		reg = reg_base + 2 * i;
+		buf[i] = twl4030_madc_channel_raw_read(madc, reg);
+		if (buf[i] < 0) {
+			dev_err(madc->dev,
+				"Unable to read register 0x%X\n", reg);
+			count_req++;
+			continue;
+		}
+		switch (i) {
+		case 10:
+			buf[i] = twl4030battery_current(buf[i]);
+			if (buf[i] < 0) {
+				dev_err(madc->dev, "err reading current\n");
+				count_req++;
+			} else {
+				count++;
+				buf[i] = buf[i] - 750;
+			}
+			break;
+		case 1:
+			buf[i] = twl4030battery_temperature(buf[i]);
+			if (buf[i] < 0) {
+				dev_err(madc->dev, "err reading temperature\n");
+				count_req++;
+			} else {
+				buf[i] -= 3;
+				count++;
+			}
+			break;
+		default:
+			count++;
+			/* Analog Input (V) = conv_result * step_size / R
+			 * conv_result = decimal value of 10-bit conversion
+			 *		 result
+			 * step size = 1.5 / (2 ^ 10 -1)
+			 * R = Prescaler ratio for input channels.
+			 * Result given in mV hence multiplied by 1000.
+			 */
+			buf[i] = (buf[i] * 3 * 1000 *
+				 twl4030_divider_ratios[i].denominator)
+				/ (2 * 1023 *
+				twl4030_divider_ratios[i].numerator);
+		}
+	}
+	if (count_req)
+		dev_err(madc->dev, "%d channel conversion failed\n", count_req);
+
+	return count;
+}
+
+/*
+ * Enables irq.
+ * @madc - pointer to twl4030_madc_data struct
+ * @id - irq number to be enabled
+ * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
+ * corresponding to RT, SW1, SW2 conversion requests.
+ * If the i2c read fails it returns an error else returns 0.
+ */
+static int twl4030_madc_enable_irq(struct twl4030_madc_data *madc, u8 id)
+{
+	u8 val;
+	int ret;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
+	if (ret) {
+		dev_err(madc->dev, "unable to read imr register 0x%X\n",
+			madc->imr);
+		return ret;
+	}
+	val &= ~(1 << id);
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
+	if (ret) {
+		dev_err(madc->dev,
+			"unable to write imr register 0x%X\n", madc->imr);
+		return ret;
+
+	}
+
+	return 0;
+}
+
+/*
+ * Disables irq.
+ * @madc - pointer to twl4030_madc_data struct
+ * @id - irq number to be disabled
+ * can take one of TWL4030_MADC_RT, TWL4030_MADC_SW1, TWL4030_MADC_SW2
+ * corresponding to RT, SW1, SW2 conversion requests.
+ * Returns error if i2c read/write fails.
+ */
+static int twl4030_madc_disable_irq(struct twl4030_madc_data *madc, u8 id)
+{
+	u8 val;
+	int ret;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &val, madc->imr);
+	if (ret) {
+		dev_err(madc->dev, "unable to read imr register 0x%X\n",
+			madc->imr);
+		return ret;
+	}
+	val |= (1 << id);
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, val, madc->imr);
+	if (ret) {
+		dev_err(madc->dev,
+			"unable to write imr register 0x%X\n", madc->imr);
+		return ret;
+	}
+
+	return 0;
+}
+
+static irqreturn_t twl4030_madc_threaded_irq_handler(int irq, void *_madc)
+{
+	struct twl4030_madc_data *madc = _madc;
+	const struct twl4030_madc_conversion_method *method;
+	u8 isr_val, imr_val;
+	int i, len, ret;
+	struct twl4030_madc_request *r;
+
+	mutex_lock(&madc->lock);
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &isr_val, madc->isr);
+	if (ret) {
+		dev_err(madc->dev, "unable to read isr register 0x%X\n",
+			madc->isr);
+		goto err_i2c;
+	}
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &imr_val, madc->imr);
+	if (ret) {
+		dev_err(madc->dev, "unable to read imr register 0x%X\n",
+			madc->imr);
+		goto err_i2c;
+	}
+	isr_val &= ~imr_val;
+	for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+		if (!(isr_val & (1 << i)))
+			continue;
+		ret = twl4030_madc_disable_irq(madc, i);
+		if (ret < 0)
+			dev_dbg(madc->dev, "Disable interrupt failed%d\n", i);
+		madc->requests[i].result_pending = 1;
+	}
+	for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+		r = &madc->requests[i];
+		/* No pending results for this method, move to next one */
+		if (!r->result_pending)
+			continue;
+		method = &twl4030_conversion_methods[r->method];
+		/* Read results */
+		len = twl4030_madc_read_channels(madc, method->rbase,
+						 r->channels, r->rbuf);
+		/* Return results to caller */
+		if (r->func_cb != NULL) {
+			r->func_cb(len, r->channels, r->rbuf);
+			r->func_cb = NULL;
+		}
+		/* Free request */
+		r->result_pending = 0;
+		r->active = 0;
+	}
+	mutex_unlock(&madc->lock);
+
+	return IRQ_HANDLED;
+
+err_i2c:
+	/*
+	 * In case of error check whichever request is active
+	 * and service the same.
+	 */
+	for (i = 0; i < TWL4030_MADC_NUM_METHODS; i++) {
+		r = &madc->requests[i];
+		if (r->active == 0)
+			continue;
+		method = &twl4030_conversion_methods[r->method];
+		/* Read results */
+		len = twl4030_madc_read_channels(madc, method->rbase,
+						 r->channels, r->rbuf);
+		/* Return results to caller */
+		if (r->func_cb != NULL) {
+			r->func_cb(len, r->channels, r->rbuf);
+			r->func_cb = NULL;
+		}
+		/* Free request */
+		r->result_pending = 0;
+		r->active = 0;
+	}
+	mutex_unlock(&madc->lock);
+
+	return IRQ_HANDLED;
+}
+
+static int twl4030_madc_set_irq(struct twl4030_madc_data *madc,
+				struct twl4030_madc_request *req)
+{
+	struct twl4030_madc_request *p;
+	int ret;
+
+	p = &madc->requests[req->method];
+	memcpy(p, req, sizeof(*req));
+	ret = twl4030_madc_enable_irq(madc, req->method);
+	if (ret < 0) {
+		dev_err(madc->dev, "enable irq failed!!\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Function which enables the madc conversion
+ * by writing to the control register.
+ * @madc - pointer to twl4030_madc_data struct
+ * @conv_method - can be TWL4030_MADC_RT, TWL4030_MADC_SW2, TWL4030_MADC_SW1
+ * corresponding to RT SW1 or SW2 conversion methods.
+ * Returns 0 if succeeds else a negative error value
+ */
+static int twl4030_madc_start_conversion(struct twl4030_madc_data *madc,
+					 int conv_method)
+{
+	const struct twl4030_madc_conversion_method *method;
+	int ret = 0;
+	method = &twl4030_conversion_methods[conv_method];
+	switch (conv_method) {
+	case TWL4030_MADC_SW1:
+	case TWL4030_MADC_SW2:
+		ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
+				       TWL4030_MADC_SW_START, method->ctrl);
+		if (ret) {
+			dev_err(madc->dev,
+				"unable to write ctrl register 0x%X\n",
+				method->ctrl);
+			return ret;
+		}
+		break;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
+/*
+ * Function that waits for conversion to be ready
+ * @madc - pointer to twl4030_madc_data struct
+ * @timeout_ms - timeout value in milliseconds
+ * @status_reg - ctrl register
+ * returns 0 if succeeds else a negative error value
+ */
+static int twl4030_madc_wait_conversion_ready(struct twl4030_madc_data *madc,
+					      unsigned int timeout_ms,
+					      u8 status_reg)
+{
+	unsigned long timeout;
+	int ret;
+
+	timeout = jiffies + msecs_to_jiffies(timeout_ms);
+	do {
+		u8 reg;
+
+		ret = twl_i2c_read_u8(TWL4030_MODULE_MADC, &reg, status_reg);
+		if (ret) {
+			dev_err(madc->dev,
+				"unable to read status register 0x%X\n",
+				status_reg);
+			return ret;
+		}
+		if (!(reg & TWL4030_MADC_BUSY) && (reg & TWL4030_MADC_EOC_SW))
+			return 0;
+		usleep_range(500, 2000);
+	} while (!time_after(jiffies, timeout));
+	dev_err(madc->dev, "conversion timeout!\n");
+
+	return -EAGAIN;
+}
+
+/*
+ * An exported function which can be called from other kernel drivers.
+ * @req twl4030_madc_request structure
+ * req->rbuf will be filled with read values of channels based on the
+ * channel index. If a particular channel reading fails there will
+ * be a negative error value in the corresponding array element.
+ * returns 0 if succeeds else error value
+ */
+int twl4030_madc_conversion(struct twl4030_madc_request *req)
+{
+	const struct twl4030_madc_conversion_method *method;
+	u8 ch_msb, ch_lsb;
+	int ret;
+
+	if (!req)
+		return -EINVAL;
+	mutex_lock(&twl4030_madc->lock);
+	if (req->method < TWL4030_MADC_RT || req->method > TWL4030_MADC_SW2) {
+		ret = -EINVAL;
+		goto out;
+	}
+	/* Do we have a conversion request ongoing */
+	if (twl4030_madc->requests[req->method].active) {
+		ret = -EBUSY;
+		goto out;
+	}
+	ch_msb = (req->channels >> 8) & 0xff;
+	ch_lsb = req->channels & 0xff;
+	method = &twl4030_conversion_methods[req->method];
+	/* Select channels to be converted */
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_msb, method->sel + 1);
+	if (ret) {
+		dev_err(twl4030_madc->dev,
+			"unable to write sel register 0x%X\n", method->sel + 1);
+		return ret;
+	}
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, ch_lsb, method->sel);
+	if (ret) {
+		dev_err(twl4030_madc->dev,
+			"unable to write sel register 0x%X\n", method->sel + 1);
+		return ret;
+	}
+	/* Select averaging for all channels if do_avg is set */
+	if (req->do_avg) {
+		ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
+				       ch_msb, method->avg + 1);
+		if (ret) {
+			dev_err(twl4030_madc->dev,
+				"unable to write avg register 0x%X\n",
+				method->avg + 1);
+			return ret;
+		}
+		ret = twl_i2c_write_u8(TWL4030_MODULE_MADC,
+				       ch_lsb, method->avg);
+		if (ret) {
+			dev_err(twl4030_madc->dev,
+				"unable to write sel reg 0x%X\n",
+				method->sel + 1);
+			return ret;
+		}
+	}
+	if (req->type == TWL4030_MADC_IRQ_ONESHOT && req->func_cb != NULL) {
+		ret = twl4030_madc_set_irq(twl4030_madc, req);
+		if (ret < 0)
+			goto out;
+		ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
+		if (ret < 0)
+			goto out;
+		twl4030_madc->requests[req->method].active = 1;
+		ret = 0;
+		goto out;
+	}
+	/* With RT method we should not be here anymore */
+	if (req->method == TWL4030_MADC_RT) {
+		ret = -EINVAL;
+		goto out;
+	}
+	ret = twl4030_madc_start_conversion(twl4030_madc, req->method);
+	if (ret < 0)
+		goto out;
+	twl4030_madc->requests[req->method].active = 1;
+	/* Wait until conversion is ready (ctrl register returns EOC) */
+	ret = twl4030_madc_wait_conversion_ready(twl4030_madc, 5, method->ctrl);
+	if (ret) {
+		twl4030_madc->requests[req->method].active = 0;
+		goto out;
+	}
+	ret = twl4030_madc_read_channels(twl4030_madc, method->rbase,
+					 req->channels, req->rbuf);
+	twl4030_madc->requests[req->method].active = 0;
+
+out:
+	mutex_unlock(&twl4030_madc->lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(twl4030_madc_conversion);
+
+/*
+ * Return channel value
+ * Or < 0 on failure.
+ */
+int twl4030_get_madc_conversion(int channel_no)
+{
+	struct twl4030_madc_request req;
+	int temp = 0;
+	int ret;
+
+	req.channels = (1 << channel_no);
+	req.method = TWL4030_MADC_SW2;
+	req.active = 0;
+	req.func_cb = NULL;
+	ret = twl4030_madc_conversion(&req);
+	if (ret < 0)
+		return ret;
+	if (req.rbuf[channel_no] > 0)
+		temp = req.rbuf[channel_no];
+
+	return temp;
+}
+EXPORT_SYMBOL_GPL(twl4030_get_madc_conversion);
+
+/*
+ * Function to enable or disable bias current for
+ * main battery type reading or temperature sensing
+ * @madc - pointer to twl4030_madc_data struct
+ * @chan - can be one of the two values
+ * TWL4030_BCI_ITHEN - Enables bias current for main battery type reading
+ * TWL4030_BCI_TYPEN - Enables bias current for main battery temperature
+ * sensing
+ * @on - enable or disable chan.
+ */
+static int twl4030_madc_set_current_generator(struct twl4030_madc_data *madc,
+					      int chan, int on)
+{
+	int ret;
+	u8 regval;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+			      &regval, TWL4030_BCI_BCICTL1);
+	if (ret) {
+		dev_err(madc->dev, "unable to read BCICTL1 reg 0x%X",
+			TWL4030_BCI_BCICTL1);
+		return ret;
+	}
+	if (on)
+		regval |= chan ? TWL4030_BCI_ITHEN : TWL4030_BCI_TYPEN;
+	else
+		regval &= chan ? ~TWL4030_BCI_ITHEN : ~TWL4030_BCI_TYPEN;
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+			       regval, TWL4030_BCI_BCICTL1);
+	if (ret) {
+		dev_err(madc->dev, "unable to write BCICTL1 reg 0x%X\n",
+			TWL4030_BCI_BCICTL1);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Function that sets MADC software power on bit to enable MADC
+ * @madc - pointer to twl4030_madc_data struct
+ * @on - Enable or disable MADC software powen on bit.
+ * returns error if i2c read/write fails else 0
+ */
+static int twl4030_madc_set_power(struct twl4030_madc_data *madc, int on)
+{
+	u8 regval;
+	int ret;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+			      &regval, TWL4030_MADC_CTRL1);
+	if (ret) {
+		dev_err(madc->dev, "unable to read madc ctrl1 reg 0x%X\n",
+			TWL4030_MADC_CTRL1);
+		return ret;
+	}
+	if (on)
+		regval |= TWL4030_MADC_MADCON;
+	else
+		regval &= ~TWL4030_MADC_MADCON;
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MADC, regval, TWL4030_MADC_CTRL1);
+	if (ret) {
+		dev_err(madc->dev, "unable to write madc ctrl1 reg 0x%X\n",
+			TWL4030_MADC_CTRL1);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Initialize MADC and request for threaded irq
+ */
+static int __devinit twl4030_madc_probe(struct platform_device *pdev)
+{
+	struct twl4030_madc_data *madc;
+	struct twl4030_madc_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+	u8 regval;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "platform_data not available\n");
+		return -EINVAL;
+	}
+	madc = kzalloc(sizeof(*madc), GFP_KERNEL);
+	if (!madc)
+		return -ENOMEM;
+
+	/*
+	 * Phoenix provides 2 interrupt lines. The first one is connected to
+	 * the OMAP. The other one can be connected to the other processor such
+	 * as modem. Hence two separate ISR and IMR registers.
+	 */
+	madc->imr = (pdata->irq_line == 1) ?
+	    TWL4030_MADC_IMR1 : TWL4030_MADC_IMR2;
+	madc->isr = (pdata->irq_line == 1) ?
+	    TWL4030_MADC_ISR1 : TWL4030_MADC_ISR2;
+	ret = twl4030_madc_set_power(madc, 1);
+	if (ret < 0)
+		goto err_power;
+	ret = twl4030_madc_set_current_generator(madc, 0, 1);
+	if (ret < 0)
+		goto err_current_generator;
+
+	ret = twl_i2c_read_u8(TWL4030_MODULE_MAIN_CHARGE,
+			      &regval, TWL4030_BCI_BCICTL1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to read reg BCI CTL1 0x%X\n",
+			TWL4030_BCI_BCICTL1);
+		goto err_i2c;
+	}
+	regval |= TWL4030_BCI_MESBAT;
+	ret = twl_i2c_write_u8(TWL4030_MODULE_MAIN_CHARGE,
+			       regval, TWL4030_BCI_BCICTL1);
+	if (ret) {
+		dev_err(&pdev->dev, "unable to write reg BCI Ctl1 0x%X\n",
+			TWL4030_BCI_BCICTL1);
+		goto err_i2c;
+	}
+	platform_set_drvdata(pdev, madc);
+	mutex_init(&madc->lock);
+	ret = request_threaded_irq(platform_get_irq(pdev, 0), NULL,
+				   twl4030_madc_threaded_irq_handler,
+				   IRQF_TRIGGER_RISING, "twl4030_madc", madc);
+	if (ret) {
+		dev_dbg(&pdev->dev, "could not request irq\n");
+		goto err_irq;
+	}
+	twl4030_madc = madc;
+	return 0;
+err_irq:
+	platform_set_drvdata(pdev, NULL);
+err_i2c:
+	twl4030_madc_set_current_generator(madc, 0, 0);
+err_current_generator:
+	twl4030_madc_set_power(madc, 0);
+err_power:
+	kfree(madc);
+
+	return ret;
+}
+
+static int __devexit twl4030_madc_remove(struct platform_device *pdev)
+{
+	struct twl4030_madc_data *madc = platform_get_drvdata(pdev);
+
+	free_irq(platform_get_irq(pdev, 0), madc);
+	platform_set_drvdata(pdev, NULL);
+	twl4030_madc_set_current_generator(madc, 0, 0);
+	twl4030_madc_set_power(madc, 0);
+	kfree(madc);
+
+	return 0;
+}
+
+static struct platform_driver twl4030_madc_driver = {
+	.probe = twl4030_madc_probe,
+	.remove = __exit_p(twl4030_madc_remove),
+	.driver = {
+		   .name = "twl4030_madc",
+		   .owner = THIS_MODULE,
+		   },
+};
+
+static int __init twl4030_madc_init(void)
+{
+	return platform_driver_register(&twl4030_madc_driver);
+}
+
+module_init(twl4030_madc_init);
+
+static void __exit twl4030_madc_exit(void)
+{
+	platform_driver_unregister(&twl4030_madc_driver);
+}
+
+module_exit(twl4030_madc_exit);
+
+MODULE_DESCRIPTION("TWL4030 ADC driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("J Keerthy");
+MODULE_ALIAS("platform:twl4030_madc");
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/twl4030-power.c linux-libre-2.6.39-gnu/drivers/mfd/twl4030-power.c
--- linux-libre-2.6.38-gnu/drivers/mfd/twl4030-power.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/twl4030-power.c	2011-05-19 00:06:34.000000000 -0400
@@ -447,12 +447,13 @@
 		if (err)
 			goto out;
 	}
-	if (tscript->flags & TWL4030_SLEEP_SCRIPT)
+	if (tscript->flags & TWL4030_SLEEP_SCRIPT) {
 		if (order)
 			pr_warning("TWL4030: Bad order of scripts (sleep "\
 					"script before wakeup) Leads to boot"\
 					"failure on some boards\n");
 		err = twl4030_config_sleep_sequence(address);
+	}
 out:
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/twl6030-irq.c linux-libre-2.6.39-gnu/drivers/mfd/twl6030-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/twl6030-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/twl6030-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,22 +140,7 @@
 			if (sts.int_sts & 0x1) {
 				int module_irq = twl6030_irq_base +
 					twl6030_interrupt_mapping[i];
-				struct irq_desc *d = irq_to_desc(module_irq);
-
-				if (!d) {
-					pr_err("twl6030: Invalid SIH IRQ: %d\n",
-					       module_irq);
-					return -EINVAL;
-				}
-
-				/* These can't be masked ... always warn
-				 * if we get any surprises.
-				 */
-				if (d->status & IRQ_DISABLED)
-					note_interrupt(module_irq, d,
-							IRQ_NONE);
-				else
-					d->handle_irq(module_irq, d);
+				generic_handle_irq(module_irq);
 
 			}
 		local_irq_enable();
@@ -198,7 +183,7 @@
 	set_irq_flags(irq, IRQF_VALID);
 #else
 	/* same effect on other architectures */
-	set_irq_noprobe(irq);
+	irq_set_noprobe(irq);
 #endif
 }
 
@@ -244,7 +229,7 @@
 	twl6030_interrupt_unmask(TWL6030_MMCDETECT_INT_MASK,
 						REG_INT_MSK_STS_B);
 	/*
-	 * Intially Configuring MMC_CTRL for receving interrupts &
+	 * Initially Configuring MMC_CTRL for receiving interrupts &
 	 * Card status on TWL6030 for MMC1
 	 */
 	ret = twl_i2c_read_u8(TWL6030_MODULE_ID0, &reg_val, TWL6030_MMCCTRL);
@@ -290,7 +275,7 @@
 		/* TWL6030 provide's Card detect support for
 		 * only MMC1 controller.
 		 */
-		pr_err("Unkown MMC controller %d in %s\n", pdev->id, __func__);
+		pr_err("Unknown MMC controller %d in %s\n", pdev->id, __func__);
 		return ret;
 	}
 	/*
@@ -335,8 +320,8 @@
 	twl6030_irq_chip.irq_set_type = NULL;
 
 	for (i = irq_base; i < irq_end; i++) {
-		set_irq_chip_and_handler(i, &twl6030_irq_chip,
-				handle_simple_irq);
+		irq_set_chip_and_handler(i, &twl6030_irq_chip,
+					 handle_simple_irq);
 		activate_irq(i);
 	}
 
@@ -365,7 +350,7 @@
 
 fail_kthread:
 	for (i = irq_base; i < irq_end; i++)
-		set_irq_chip_and_handler(i, NULL, NULL);
+		irq_set_chip_and_handler(i, NULL, NULL);
 	return status;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/twl-core.c linux-libre-2.6.39-gnu/drivers/mfd/twl-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/twl-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/twl-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -721,13 +721,13 @@
 
 	}
 
-	if (twl_has_watchdog()) {
+	if (twl_has_watchdog() && twl_class_is_4030()) {
 		child = add_child(0, "twl4030_wdt", NULL, 0, false, 0, 0);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
 	}
 
-	if (twl_has_pwrbutton()) {
+	if (twl_has_pwrbutton() && twl_class_is_4030()) {
 		child = add_child(1, "twl4030_pwrbutton",
 				NULL, 0, true, pdata->irq_base + 8 + 0, 0);
 		if (IS_ERR(child))
@@ -864,6 +864,10 @@
 		child = add_regulator(TWL6030_REG_VAUX3_6030, pdata->vaux3);
 		if (IS_ERR(child))
 			return PTR_ERR(child);
+
+		child = add_regulator(TWL6030_REG_CLK32KG, pdata->clk32kg);
+		if (IS_ERR(child))
+			return PTR_ERR(child);
 	}
 
 	if (twl_has_bci() && pdata->bci &&
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ucb1400_core.c linux-libre-2.6.39-gnu/drivers/mfd/ucb1400_core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ucb1400_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ucb1400_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
  *  Copyright:	MontaVista Software, Inc.
  *
  * Spliting done by: Marek Vasut <marek.vasut@gmail.com>
- * If something doesnt work and it worked before spliting, e-mail me,
+ * If something doesn't work and it worked before spliting, e-mail me,
  * dont bother Nicolas please ;-)
  *
  * This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/ucb1x00-ts.c linux-libre-2.6.39-gnu/drivers/mfd/ucb1x00-ts.c
--- linux-libre-2.6.38-gnu/drivers/mfd/ucb1x00-ts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/ucb1x00-ts.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,6 +60,7 @@
 	input_report_abs(idev, ABS_X, x);
 	input_report_abs(idev, ABS_Y, y);
 	input_report_abs(idev, ABS_PRESSURE, pressure);
+	input_report_key(idev, BTN_TOUCH, 1);
 	input_sync(idev);
 }
 
@@ -68,6 +69,7 @@
 	struct input_dev *idev = ts->idev;
 
 	input_report_abs(idev, ABS_PRESSURE, 0);
+	input_report_key(idev, BTN_TOUCH, 0);
 	input_sync(idev);
 }
 
@@ -384,7 +386,8 @@
 	idev->open       = ucb1x00_ts_open;
 	idev->close      = ucb1x00_ts_close;
 
-	__set_bit(EV_ABS, idev->evbit);
+	idev->evbit[0]   = BIT_MASK(EV_ABS) | BIT_MASK(EV_KEY);
+	idev->keybit[BIT_WORD(BTN_TOUCH)] = BIT_MASK(BTN_TOUCH);
 
 	input_set_drvdata(idev, ts);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/vx855.c linux-libre-2.6.39-gnu/drivers/mfd/vx855.c
--- linux-libre-2.6.38-gnu/drivers/mfd/vx855.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/vx855.c	2011-05-19 00:06:34.000000000 -0400
@@ -122,6 +122,7 @@
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_VX855) },
 	{ 0, }
 };
+MODULE_DEVICE_TABLE(pci, vx855_pci_tbl);
 
 static struct pci_driver vx855_pci_driver = {
 	.name		= "vx855",
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wl1273-core.c linux-libre-2.6.39-gnu/drivers/mfd/wl1273-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wl1273-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wl1273-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*
  * MFD driver for wl1273 FM radio and audio codec submodules.
  *
- * Copyright (C) 2010 Nokia Corporation
+ * Copyright (C) 2011 Nokia Corporation
  * Author: Matti Aaltonen <matti.j.aaltonen@nokia.com>
  *
  * This program is free software; you can redistribute it and/or modify
@@ -25,12 +25,151 @@
 
 #define DRIVER_DESC "WL1273 FM Radio Core"
 
-static struct i2c_device_id wl1273_driver_id_table[] = {
+static const struct i2c_device_id wl1273_driver_id_table[] = {
 	{ WL1273_FM_DRIVER_NAME, 0 },
 	{ }
 };
 MODULE_DEVICE_TABLE(i2c, wl1273_driver_id_table);
 
+static int wl1273_fm_read_reg(struct wl1273_core *core, u8 reg, u16 *value)
+{
+	struct i2c_client *client = core->client;
+	u8 b[2];
+	int r;
+
+	r = i2c_smbus_read_i2c_block_data(client, reg, sizeof(b), b);
+	if (r != 2) {
+		dev_err(&client->dev, "%s: Read: %d fails.\n", __func__, reg);
+		return -EREMOTEIO;
+	}
+
+	*value = (u16)b[0] << 8 | b[1];
+
+	return 0;
+}
+
+static int wl1273_fm_write_cmd(struct wl1273_core *core, u8 cmd, u16 param)
+{
+	struct i2c_client *client = core->client;
+	u8 buf[] = { (param >> 8) & 0xff, param & 0xff };
+	int r;
+
+	r = i2c_smbus_write_i2c_block_data(client, cmd, sizeof(buf), buf);
+	if (r) {
+		dev_err(&client->dev, "%s: Cmd: %d fails.\n", __func__, cmd);
+		return r;
+	}
+
+	return 0;
+}
+
+static int wl1273_fm_write_data(struct wl1273_core *core, u8 *data, u16 len)
+{
+	struct i2c_client *client = core->client;
+	struct i2c_msg msg;
+	int r;
+
+	msg.addr = client->addr;
+	msg.flags = 0;
+	msg.buf = data;
+	msg.len = len;
+
+	r = i2c_transfer(client->adapter, &msg, 1);
+	if (r != 1) {
+		dev_err(&client->dev, "%s: write error.\n", __func__);
+		return -EREMOTEIO;
+	}
+
+	return 0;
+}
+
+/**
+ * wl1273_fm_set_audio() -	Set audio mode.
+ * @core:			A pointer to the device struct.
+ * @new_mode:			The new audio mode.
+ *
+ * Audio modes are WL1273_AUDIO_DIGITAL and WL1273_AUDIO_ANALOG.
+ */
+static int wl1273_fm_set_audio(struct wl1273_core *core, unsigned int new_mode)
+{
+	int r = 0;
+
+	if (core->mode == WL1273_MODE_OFF ||
+	    core->mode == WL1273_MODE_SUSPENDED)
+		return -EPERM;
+
+	if (core->mode == WL1273_MODE_RX && new_mode == WL1273_AUDIO_DIGITAL) {
+		r = wl1273_fm_write_cmd(core, WL1273_PCM_MODE_SET,
+					WL1273_PCM_DEF_MODE);
+		if (r)
+			goto out;
+
+		r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
+					core->i2s_mode);
+		if (r)
+			goto out;
+
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+					WL1273_AUDIO_ENABLE_I2S);
+		if (r)
+			goto out;
+
+	} else if (core->mode == WL1273_MODE_RX &&
+		   new_mode == WL1273_AUDIO_ANALOG) {
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_ENABLE,
+					WL1273_AUDIO_ENABLE_ANALOG);
+		if (r)
+			goto out;
+
+	} else if (core->mode == WL1273_MODE_TX &&
+		   new_mode == WL1273_AUDIO_DIGITAL) {
+		r = wl1273_fm_write_cmd(core, WL1273_I2S_MODE_CONFIG_SET,
+					core->i2s_mode);
+		if (r)
+			goto out;
+
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
+					WL1273_AUDIO_IO_SET_I2S);
+		if (r)
+			goto out;
+
+	} else if (core->mode == WL1273_MODE_TX &&
+		   new_mode == WL1273_AUDIO_ANALOG) {
+		r = wl1273_fm_write_cmd(core, WL1273_AUDIO_IO_SET,
+					WL1273_AUDIO_IO_SET_ANALOG);
+		if (r)
+			goto out;
+	}
+
+	core->audio_mode = new_mode;
+out:
+	return r;
+}
+
+/**
+ * wl1273_fm_set_volume() -	Set volume.
+ * @core:			A pointer to the device struct.
+ * @volume:			The new volume value.
+ */
+static int wl1273_fm_set_volume(struct wl1273_core *core, unsigned int volume)
+{
+	u16 val;
+	int r;
+
+	if (volume > WL1273_MAX_VOLUME)
+		return -EINVAL;
+
+	if (core->volume == volume)
+		return 0;
+
+	r = wl1273_fm_write_cmd(core, WL1273_VOLUME_SET, volume);
+	if (r)
+		return r;
+
+	core->volume = volume;
+	return 0;
+}
+
 static int wl1273_core_remove(struct i2c_client *client)
 {
 	struct wl1273_core *core = i2c_get_clientdata(client);
@@ -38,7 +177,6 @@
 	dev_dbg(&client->dev, "%s\n", __func__);
 
 	mfd_remove_devices(&client->dev);
-	i2c_set_clientdata(client, NULL);
 	kfree(core);
 
 	return 0;
@@ -79,17 +217,21 @@
 
 	cell = &core->cells[children];
 	cell->name = "wl1273_fm_radio";
-	cell->platform_data = &core;
-	cell->data_size = sizeof(core);
+	cell->mfd_data = &core;
 	children++;
 
+	core->read = wl1273_fm_read_reg;
+	core->write = wl1273_fm_write_cmd;
+	core->write_data = wl1273_fm_write_data;
+	core->set_audio = wl1273_fm_set_audio;
+	core->set_volume = wl1273_fm_set_volume;
+
 	if (pdata->children & WL1273_CODEC_CHILD) {
 		cell = &core->cells[children];
 
 		dev_dbg(&client->dev, "%s: Have codec.\n", __func__);
 		cell->name = "wl1273-codec";
-		cell->platform_data = &core;
-		cell->data_size = sizeof(core);
+		cell->mfd_data = &core;
 		children++;
 	}
 
@@ -104,7 +246,6 @@
 	return 0;
 
 err:
-	i2c_set_clientdata(client, NULL);
 	pdata->free_resources();
 	kfree(core);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm831x-i2c.c linux-libre-2.6.39-gnu/drivers/mfd/wm831x-i2c.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm831x-i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm831x-i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,17 +51,25 @@
 				   int bytes, void *src)
 {
 	struct i2c_client *i2c = wm831x->control_data;
-	unsigned char msg[bytes + 2];
+	struct i2c_msg xfer[2];
 	int ret;
 
 	reg = cpu_to_be16(reg);
-	memcpy(&msg[0], &reg, 2);
-	memcpy(&msg[2], src, bytes);
 
-	ret = i2c_master_send(i2c, msg, bytes + 2);
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 2;
+	xfer[0].buf = (char *)&reg;
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_NOSTART;
+	xfer[1].len = bytes;
+	xfer[1].buf = (char *)src;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
 	if (ret < 0)
 		return ret;
-	if (ret < bytes + 2)
+	if (ret != 2)
 		return -EIO;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm831x-irq.c linux-libre-2.6.39-gnu/drivers/mfd/wm831x-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm831x-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm831x-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,15 +26,6 @@
 
 #include <linux/delay.h>
 
-/*
- * Since generic IRQs don't currently support interrupt controllers on
- * interrupt driven buses we don't use genirq but instead provide an
- * interface that looks very much like the standard ones.  This leads
- * to some bodges, including storing interrupt handler information in
- * the static irq_data table we use to look up the data for individual
- * interrupts, but hopefully won't last too long.
- */
-
 struct wm831x_irq_data {
 	int primary;
 	int reg;
@@ -361,6 +352,10 @@
 		/* If there's been a change in the mask write it back
 		 * to the hardware. */
 		if (wm831x->irq_masks_cur[i] != wm831x->irq_masks_cache[i]) {
+			dev_dbg(wm831x->dev, "IRQ mask sync: %x = %x\n",
+				WM831X_INTERRUPT_STATUS_1_MASK + i,
+				wm831x->irq_masks_cur[i]);
+
 			wm831x->irq_masks_cache[i] = wm831x->irq_masks_cur[i];
 			wm831x_reg_write(wm831x,
 					 WM831X_INTERRUPT_STATUS_1_MASK + i,
@@ -371,7 +366,7 @@
 	mutex_unlock(&wm831x->irq_lock);
 }
 
-static void wm831x_irq_unmask(struct irq_data *data)
+static void wm831x_irq_enable(struct irq_data *data)
 {
 	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
 	struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
@@ -380,7 +375,7 @@
 	wm831x->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
 }
 
-static void wm831x_irq_mask(struct irq_data *data)
+static void wm831x_irq_disable(struct irq_data *data)
 {
 	struct wm831x *wm831x = irq_data_get_irq_chip_data(data);
 	struct wm831x_irq_data *irq_data = irq_to_wm831x_irq(wm831x,
@@ -426,8 +421,8 @@
 	.name			= "wm831x",
 	.irq_bus_lock		= wm831x_irq_lock,
 	.irq_bus_sync_unlock	= wm831x_irq_sync_unlock,
-	.irq_mask		= wm831x_irq_mask,
-	.irq_unmask		= wm831x_irq_unmask,
+	.irq_disable		= wm831x_irq_disable,
+	.irq_enable		= wm831x_irq_enable,
 	.irq_set_type		= wm831x_irq_set_type,
 };
 
@@ -449,6 +444,18 @@
 		goto out;
 	}
 
+	/* The touch interrupts are visible in the primary register as
+	 * an optimisation; open code this to avoid complicating the
+	 * main handling loop and so we can also skip iterating the
+	 * descriptors.
+	 */
+	if (primary & WM831X_TCHPD_INT)
+		handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHPD);
+	if (primary & WM831X_TCHDATA_INT)
+		handle_nested_irq(wm831x->irq_base + WM831X_IRQ_TCHDATA);
+	if (primary & (WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT))
+		goto out;
+
 	for (i = 0; i < ARRAY_SIZE(wm831x_irqs); i++) {
 		int offset = wm831x_irqs[i].reg - 1;
 
@@ -481,6 +488,9 @@
 	}
 
 out:
+	/* Touchscreen interrupts are handled specially in the driver */
+	status_regs[0] &= ~(WM831X_TCHDATA_EINT | WM831X_TCHPD_EINT);
+
 	for (i = 0; i < ARRAY_SIZE(status_regs); i++) {
 		if (status_regs[i])
 			wm831x_reg_write(wm831x, WM831X_INTERRUPT_STATUS_1 + i,
@@ -517,6 +527,14 @@
 		return 0;
 	}
 
+	if (pdata->irq_cmos)
+		i = 0;
+	else
+		i = WM831X_IRQ_OD;
+
+	wm831x_set_bits(wm831x, WM831X_IRQ_CONFIG,
+			WM831X_IRQ_OD, i);
+
 	/* Try to flag /IRQ as a wake source; there are a number of
 	 * unconditional wake sources in the PMIC so this isn't
 	 * conditional but we don't actually care *too* much if it
@@ -535,17 +553,17 @@
 	for (cur_irq = wm831x->irq_base;
 	     cur_irq < ARRAY_SIZE(wm831x_irqs) + wm831x->irq_base;
 	     cur_irq++) {
-		set_irq_chip_data(cur_irq, wm831x);
-		set_irq_chip_and_handler(cur_irq, &wm831x_irq_chip,
+		irq_set_chip_data(cur_irq, wm831x);
+		irq_set_chip_and_handler(cur_irq, &wm831x_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(cur_irq, 1);
+		irq_set_nested_thread(cur_irq, 1);
 
 		/* ARM needs us to explicitly flag the IRQ as valid
 		 * and will set them noprobe when we do so. */
 #ifdef CONFIG_ARM
 		set_irq_flags(cur_irq, IRQF_VALID);
 #else
-		set_irq_noprobe(cur_irq);
+		irq_set_noprobe(cur_irq);
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm831x-spi.c linux-libre-2.6.39-gnu/drivers/mfd/wm831x-spi.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm831x-spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm831x-spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/pm.h>
 #include <linux/spi/spi.h>
 
 #include <linux/mfd/wm831x/core.h>
@@ -113,22 +114,27 @@
 	return 0;
 }
 
-static int wm831x_spi_suspend(struct spi_device *spi, pm_message_t m)
+static int wm831x_spi_suspend(struct device *dev)
 {
-	struct wm831x *wm831x = dev_get_drvdata(&spi->dev);
+	struct wm831x *wm831x = dev_get_drvdata(dev);
 
 	return wm831x_device_suspend(wm831x);
 }
 
+static const struct dev_pm_ops wm831x_spi_pm = {
+	.freeze = wm831x_spi_suspend,
+	.suspend = wm831x_spi_suspend,
+};
+
 static struct spi_driver wm8310_spi_driver = {
 	.driver = {
 		.name	= "wm8310",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8311_spi_driver = {
@@ -136,10 +142,10 @@
 		.name	= "wm8311",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8312_spi_driver = {
@@ -147,10 +153,10 @@
 		.name	= "wm8312",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8320_spi_driver = {
@@ -158,10 +164,10 @@
 		.name	= "wm8320",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8321_spi_driver = {
@@ -169,10 +175,10 @@
 		.name	= "wm8321",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8325_spi_driver = {
@@ -180,10 +186,10 @@
 		.name	= "wm8325",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static struct spi_driver wm8326_spi_driver = {
@@ -191,10 +197,10 @@
 		.name	= "wm8326",
 		.bus	= &spi_bus_type,
 		.owner	= THIS_MODULE,
+		.pm	= &wm831x_spi_pm,
 	},
 	.probe		= wm831x_spi_probe,
 	.remove		= __devexit_p(wm831x_spi_remove),
-	.suspend	= wm831x_spi_suspend,
 };
 
 static int __init wm831x_spi_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm8350-irq.c linux-libre-2.6.39-gnu/drivers/mfd/wm8350-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm8350-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm8350-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -518,17 +518,17 @@
 	for (cur_irq = wm8350->irq_base;
 	     cur_irq < ARRAY_SIZE(wm8350_irqs) + wm8350->irq_base;
 	     cur_irq++) {
-		set_irq_chip_data(cur_irq, wm8350);
-		set_irq_chip_and_handler(cur_irq, &wm8350_irq_chip,
+		irq_set_chip_data(cur_irq, wm8350);
+		irq_set_chip_and_handler(cur_irq, &wm8350_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(cur_irq, 1);
+		irq_set_nested_thread(cur_irq, 1);
 
 		/* ARM needs us to explicitly flag the IRQ as valid
 		 * and will set them noprobe when we do so. */
 #ifdef CONFIG_ARM
 		set_irq_flags(cur_irq, IRQF_VALID);
 #else
-		set_irq_noprobe(cur_irq);
+		irq_set_noprobe(cur_irq);
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm8400-core.c linux-libre-2.6.39-gnu/drivers/mfd/wm8400-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm8400-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm8400-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -245,7 +245,7 @@
 {
 	struct mfd_cell cell = {
 		.name = "wm8400-codec",
-		.driver_data = wm8400,
+		.mfd_data = wm8400,
 	};
 
 	return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm8994-core.c linux-libre-2.6.39-gnu/drivers/mfd/wm8994-core.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm8994-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm8994-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,10 +40,8 @@
 		return ret;
 
 	for (i = 0; i < bytes / 2; i++) {
-		buf[i] = be16_to_cpu(buf[i]);
-
 		dev_vdbg(wm8994->dev, "Read %04x from R%d(0x%x)\n",
-			 buf[i], reg + i, reg + i);
+			 be16_to_cpu(buf[i]), reg + i, reg + i);
 	}
 
 	return 0;
@@ -69,7 +67,7 @@
 	if (ret < 0)
 		return ret;
 	else
-		return val;
+		return be16_to_cpu(val);
 }
 EXPORT_SYMBOL_GPL(wm8994_reg_read);
 
@@ -79,7 +77,7 @@
  * @wm8994: Device to read from
  * @reg: First register
  * @count: Number of registers
- * @buf: Buffer to fill.
+ * @buf: Buffer to fill.  The data will be returned big endian.
  */
 int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
 		     int count, u16 *buf)
@@ -97,9 +95,9 @@
 EXPORT_SYMBOL_GPL(wm8994_bulk_read);
 
 static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
-			int bytes, void *src)
+			int bytes, const void *src)
 {
-	u16 *buf = src;
+	const u16 *buf = src;
 	int i;
 
 	BUG_ON(bytes % 2);
@@ -107,9 +105,7 @@
 
 	for (i = 0; i < bytes / 2; i++) {
 		dev_vdbg(wm8994->dev, "Write %04x to R%d(0x%x)\n",
-			 buf[i], reg + i, reg + i);
-
-		buf[i] = cpu_to_be16(buf[i]);
+			 be16_to_cpu(buf[i]), reg + i, reg + i);
 	}
 
 	return wm8994->write_dev(wm8994, reg, bytes, src);
@@ -127,6 +123,8 @@
 {
 	int ret;
 
+	val = cpu_to_be16(val);
+
 	mutex_lock(&wm8994->io_lock);
 
 	ret = wm8994_write(wm8994, reg, 2, &val);
@@ -138,6 +136,29 @@
 EXPORT_SYMBOL_GPL(wm8994_reg_write);
 
 /**
+ * wm8994_bulk_write: Write multiple WM8994 registers
+ *
+ * @wm8994: Device to write to
+ * @reg: First register
+ * @count: Number of registers
+ * @buf: Buffer to write from.  Data must be big-endian formatted.
+ */
+int wm8994_bulk_write(struct wm8994 *wm8994, unsigned short reg,
+		      int count, const u16 *buf)
+{
+	int ret;
+
+	mutex_lock(&wm8994->io_lock);
+
+	ret = wm8994_write(wm8994, reg, count * 2, buf);
+
+	mutex_unlock(&wm8994->io_lock);
+
+	return ret;
+}
+EXPORT_SYMBOL_GPL(wm8994_bulk_write);
+
+/**
  * wm8994_set_bits: Set the value of a bitfield in a WM8994 register
  *
  * @wm8994: Device to write to.
@@ -157,9 +178,13 @@
 	if (ret < 0)
 		goto out;
 
+	r = be16_to_cpu(r);
+
 	r &= ~mask;
 	r |= val;
 
+	r = cpu_to_be16(r);
+
 	ret = wm8994_write(wm8994, reg, 2, &r);
 
 out:
@@ -271,6 +296,11 @@
 	if (ret < 0)
 		dev_err(dev, "Failed to save LDO registers: %d\n", ret);
 
+	/* Explicitly put the device into reset in case regulators
+	 * don't get disabled in order to ensure consistent restart.
+	 */
+	wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);
+
 	wm8994->suspended = true;
 
 	ret = regulator_bulk_disable(wm8994->num_supplies,
@@ -552,25 +582,29 @@
 	return 0;
 }
 
-/* Currently we allocate the write buffer on the stack; this is OK for
- * small writes - if we need to do large writes this will need to be
- * revised.
- */
 static int wm8994_i2c_write_device(struct wm8994 *wm8994, unsigned short reg,
-				   int bytes, void *src)
+				   int bytes, const void *src)
 {
 	struct i2c_client *i2c = wm8994->control_data;
-	unsigned char msg[bytes + 2];
+	struct i2c_msg xfer[2];
 	int ret;
 
 	reg = cpu_to_be16(reg);
-	memcpy(&msg[0], &reg, 2);
-	memcpy(&msg[2], src, bytes);
 
-	ret = i2c_master_send(i2c, msg, bytes + 2);
+	xfer[0].addr = i2c->addr;
+	xfer[0].flags = 0;
+	xfer[0].len = 2;
+	xfer[0].buf = (char *)&reg;
+
+	xfer[1].addr = i2c->addr;
+	xfer[1].flags = I2C_M_NOSTART;
+	xfer[1].len = bytes;
+	xfer[1].buf = (char *)src;
+
+	ret = i2c_transfer(i2c->adapter, xfer, 2);
 	if (ret < 0)
 		return ret;
-	if (ret < bytes + 2)
+	if (ret != 2)
 		return -EIO;
 
 	return 0;
@@ -612,7 +646,8 @@
 };
 MODULE_DEVICE_TABLE(i2c, wm8994_i2c_id);
 
-UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume, NULL);
+static UNIVERSAL_DEV_PM_OPS(wm8994_pm_ops, wm8994_suspend, wm8994_resume,
+			    NULL);
 
 static struct i2c_driver wm8994_i2c_driver = {
 	.driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/mfd/wm8994-irq.c linux-libre-2.6.39-gnu/drivers/mfd/wm8994-irq.c
--- linux-libre-2.6.38-gnu/drivers/mfd/wm8994-irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mfd/wm8994-irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -182,7 +182,7 @@
 	mutex_unlock(&wm8994->irq_lock);
 }
 
-static void wm8994_irq_unmask(struct irq_data *data)
+static void wm8994_irq_enable(struct irq_data *data)
 {
 	struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
 	struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
@@ -191,7 +191,7 @@
 	wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
 }
 
-static void wm8994_irq_mask(struct irq_data *data)
+static void wm8994_irq_disable(struct irq_data *data)
 {
 	struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
 	struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
@@ -204,8 +204,8 @@
 	.name			= "wm8994",
 	.irq_bus_lock		= wm8994_irq_lock,
 	.irq_bus_sync_unlock	= wm8994_irq_sync_unlock,
-	.irq_mask		= wm8994_irq_mask,
-	.irq_unmask		= wm8994_irq_unmask,
+	.irq_disable		= wm8994_irq_disable,
+	.irq_enable		= wm8994_irq_enable,
 };
 
 /* The processing of the primary interrupt occurs in a thread so that
@@ -225,9 +225,11 @@
 		return IRQ_NONE;
 	}
 
-	/* Apply masking */
-	for (i = 0; i < WM8994_NUM_IRQ_REGS; i++)
+	/* Bit swap and apply masking */
+	for (i = 0; i < WM8994_NUM_IRQ_REGS; i++) {
+		status[i] = be16_to_cpu(status[i]);
 		status[i] &= ~wm8994->irq_masks_cur[i];
+	}
 
 	/* Report */
 	for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
@@ -276,17 +278,17 @@
 	for (cur_irq = wm8994->irq_base;
 	     cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
 	     cur_irq++) {
-		set_irq_chip_data(cur_irq, wm8994);
-		set_irq_chip_and_handler(cur_irq, &wm8994_irq_chip,
+		irq_set_chip_data(cur_irq, wm8994);
+		irq_set_chip_and_handler(cur_irq, &wm8994_irq_chip,
 					 handle_edge_irq);
-		set_irq_nested_thread(cur_irq, 1);
+		irq_set_nested_thread(cur_irq, 1);
 
 		/* ARM needs us to explicitly flag the IRQ as valid
 		 * and will set them noprobe when we do so. */
 #ifdef CONFIG_ARM
 		set_irq_flags(cur_irq, IRQF_VALID);
 #else
-		set_irq_noprobe(cur_irq);
+		irq_set_noprobe(cur_irq);
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/misc/apds9802als.c linux-libre-2.6.39-gnu/drivers/misc/apds9802als.c
--- linux-libre-2.6.38-gnu/drivers/misc/apds9802als.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/apds9802als.c	2011-05-19 00:06:34.000000000 -0400
@@ -245,9 +245,8 @@
 	als_set_default_config(client);
 	mutex_init(&data->mutex);
 
+	pm_runtime_set_active(&client->dev);
 	pm_runtime_enable(&client->dev);
-	pm_runtime_get(&client->dev);
-	pm_runtime_put(&client->dev);
 
 	return res;
 als_error1:
@@ -255,12 +254,19 @@
 	return res;
 }
 
-static int apds9802als_remove(struct i2c_client *client)
+static int __devexit apds9802als_remove(struct i2c_client *client)
 {
 	struct als_data *data = i2c_get_clientdata(client);
 
+	pm_runtime_get_sync(&client->dev);
+
 	als_set_power_state(client, false);
 	sysfs_remove_group(&client->dev.kobj, &m_als_gr);
+
+	pm_runtime_disable(&client->dev);
+	pm_runtime_set_suspended(&client->dev);
+	pm_runtime_put_noidle(&client->dev);
+
 	kfree(data);
 	return 0;
 }
@@ -275,9 +281,6 @@
 static int apds9802als_resume(struct i2c_client *client)
 {
 	als_set_default_config(client);
-
-	pm_runtime_get(&client->dev);
-	pm_runtime_put(&client->dev);
 	return 0;
 }
 
@@ -323,7 +326,7 @@
 		.pm = APDS9802ALS_PM_OPS,
 	},
 	.probe = apds9802als_probe,
-	.remove = apds9802als_remove,
+	.remove = __devexit_p(apds9802als_remove),
 	.suspend = apds9802als_suspend,
 	.resume = apds9802als_resume,
 	.id_table = apds9802als_id,
diff -druN linux-libre-2.6.38-gnu/drivers/misc/atmel_tclib.c linux-libre-2.6.39-gnu/drivers/misc/atmel_tclib.c
--- linux-libre-2.6.38-gnu/drivers/misc/atmel_tclib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/atmel_tclib.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 	return tc;
 
 fail_ioremap:
-	release_resource(r);
+	release_mem_region(r->start, ATMEL_TC_IOMEM_SIZE);
 fail:
 	tc = NULL;
 	goto out;
@@ -95,7 +95,7 @@
 	spin_lock(&tc_list_lock);
 	if (tc->regs) {
 		iounmap(tc->regs);
-		release_resource(tc->iomem);
+		release_mem_region(tc->iomem->start, ATMEL_TC_IOMEM_SIZE);
 		tc->regs = NULL;
 		tc->iomem = NULL;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/misc/bh1780gli.c linux-libre-2.6.39-gnu/drivers/misc/bh1780gli.c
--- linux-libre-2.6.38-gnu/drivers/misc/bh1780gli.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/bh1780gli.c	2011-05-19 00:06:34.000000000 -0400
@@ -196,10 +196,11 @@
 }
 
 #ifdef CONFIG_PM
-static int bh1780_suspend(struct i2c_client *client, pm_message_t mesg)
+static int bh1780_suspend(struct device *dev)
 {
 	struct bh1780_data *ddata;
 	int state, ret;
+	struct i2c_client *client = to_i2c_client(dev);
 
 	ddata = i2c_get_clientdata(client);
 	state = bh1780_read(ddata, BH1780_REG_CONTROL, "CONTROL");
@@ -217,14 +218,14 @@
 	return 0;
 }
 
-static int bh1780_resume(struct i2c_client *client)
+static int bh1780_resume(struct device *dev)
 {
 	struct bh1780_data *ddata;
 	int state, ret;
+	struct i2c_client *client = to_i2c_client(dev);
 
 	ddata = i2c_get_clientdata(client);
 	state = ddata->power_state;
-
 	ret = bh1780_write(ddata, BH1780_REG_CONTROL, state,
 				"CONTROL");
 
@@ -233,9 +234,10 @@
 
 	return 0;
 }
+static SIMPLE_DEV_PM_OPS(bh1780_pm, bh1780_suspend, bh1780_resume);
+#define BH1780_PMOPS (&bh1780_pm)
 #else
-#define bh1780_suspend NULL
-#define bh1780_resume NULL
+#define BH1780_PMOPS NULL
 #endif /* CONFIG_PM */
 
 static const struct i2c_device_id bh1780_id[] = {
@@ -247,11 +249,10 @@
 	.probe		= bh1780_probe,
 	.remove		= bh1780_remove,
 	.id_table	= bh1780_id,
-	.suspend	= bh1780_suspend,
-	.resume		= bh1780_resume,
 	.driver = {
-		.name = "bh1780"
-	},
+		.name = "bh1780",
+		.pm	= BH1780_PMOPS,
+},
 };
 
 static int __init bh1780_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/misc/bmp085.c linux-libre-2.6.39-gnu/drivers/misc/bmp085.c
--- linux-libre-2.6.38-gnu/drivers/misc/bmp085.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/bmp085.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
 
     This driver supports the bmp085 digital barometric pressure
     and temperature sensor from Bosch Sensortec. The datasheet
-    is avaliable from their website:
+    is available from their website:
     http://www.bosch-sensortec.com/content/language1/downloads/BST-BMP085-DS000-05.pdf
 
     A pressure measurement is issued by reading from pressure0_input.
@@ -402,7 +402,7 @@
 	return status;
 }
 
-static int bmp085_probe(struct i2c_client *client,
+static int __devinit bmp085_probe(struct i2c_client *client,
 			 const struct i2c_device_id *id)
 {
 	struct bmp085_data *data;
@@ -429,7 +429,7 @@
 	if (err)
 		goto exit_free;
 
-	dev_info(&data->client->dev, "Succesfully initialized bmp085!\n");
+	dev_info(&data->client->dev, "Successfully initialized bmp085!\n");
 	goto exit;
 
 exit_free:
@@ -438,7 +438,7 @@
 	return err;
 }
 
-static int bmp085_remove(struct i2c_client *client)
+static int __devexit bmp085_remove(struct i2c_client *client)
 {
 	sysfs_remove_group(&client->dev.kobj, &bmp085_attr_group);
 	kfree(i2c_get_clientdata(client));
@@ -458,7 +458,7 @@
 	},
 	.id_table	= bmp085_id,
 	.probe		= bmp085_probe,
-	.remove		= bmp085_remove,
+	.remove		= __devexit_p(bmp085_remove),
 
 	.detect		= bmp085_detect,
 	.address_list	= normal_i2c
diff -druN linux-libre-2.6.38-gnu/drivers/misc/c2port/c2port-duramar2150.c linux-libre-2.6.39-gnu/drivers/misc/c2port/c2port-duramar2150.c
--- linux-libre-2.6.38-gnu/drivers/misc/c2port/c2port-duramar2150.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/c2port/c2port-duramar2150.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
 		outb(v | (C2D | C2CK), DIR_PORT);
 	else
 		/* When access is "off" is important that both lines are set
-		 * as inputs or hi-impedence */
+		 * as inputs or hi-impedance */
 		outb(v & ~(C2D | C2CK), DIR_PORT);
 
 	mutex_unlock(&update_lock);
diff -druN linux-libre-2.6.38-gnu/drivers/misc/cb710/Makefile linux-libre-2.6.39-gnu/drivers/misc/cb710/Makefile
--- linux-libre-2.6.38-gnu/drivers/misc/cb710/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/cb710/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,4 @@
-ifeq ($(CONFIG_CB710_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_CB710_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_CB710_CORE)	+= cb710.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/misc/ep93xx_pwm.c linux-libre-2.6.39-gnu/drivers/misc/ep93xx_pwm.c
--- linux-libre-2.6.38-gnu/drivers/misc/ep93xx_pwm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/ep93xx_pwm.c	2011-05-19 00:06:34.000000000 -0400
@@ -249,11 +249,11 @@
 
 static DEVICE_ATTR(min_freq, S_IRUGO, ep93xx_pwm_get_min_freq, NULL);
 static DEVICE_ATTR(max_freq, S_IRUGO, ep93xx_pwm_get_max_freq, NULL);
-static DEVICE_ATTR(freq, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(freq, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_freq, ep93xx_pwm_set_freq);
-static DEVICE_ATTR(duty_percent, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(duty_percent, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_duty_percent, ep93xx_pwm_set_duty_percent);
-static DEVICE_ATTR(invert, S_IWUGO | S_IRUGO,
+static DEVICE_ATTR(invert, S_IWUSR | S_IRUGO,
 		   ep93xx_pwm_get_invert, ep93xx_pwm_set_invert);
 
 static struct attribute *ep93xx_pwm_attrs[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/misc/hmc6352.c linux-libre-2.6.39-gnu/drivers/misc/hmc6352.c
--- linux-libre-2.6.38-gnu/drivers/misc/hmc6352.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/hmc6352.c	2011-05-19 00:06:34.000000000 -0400
@@ -75,7 +75,7 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	unsigned char i2c_data[2];
-	unsigned int ret;
+	int ret;
 
 	mutex_lock(&compass_mutex);
 	ret = compass_command(client, 'A');
@@ -86,7 +86,7 @@
 	msleep(10); /* sending 'A' cmd we need to wait for 7-10 millisecs */
 	ret = i2c_master_recv(client, i2c_data, 2);
 	mutex_unlock(&compass_mutex);
-	if (ret != 1) {
+	if (ret < 0) {
 		dev_warn(dev, "i2c read data cmd failed\n");
 		return ret;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/misc/ibmasm/remote.h linux-libre-2.6.39-gnu/drivers/misc/ibmasm/remote.h
--- linux-libre-2.6.38-gnu/drivers/misc/ibmasm/remote.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/ibmasm/remote.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,7 @@
  *
  * Author: Max Asböck <amax@us.ibm.com>
  *
- * Orignally written by Pete Reynolds
+ * Originally written by Pete Reynolds
  */
 
 #ifndef _IBMASM_REMOTE_H_
diff -druN linux-libre-2.6.38-gnu/drivers/misc/iwmc3200top/iwmc3200top.h linux-libre-2.6.39-gnu/drivers/misc/iwmc3200top/iwmc3200top.h
--- linux-libre-2.6.38-gnu/drivers/misc/iwmc3200top/iwmc3200top.h	2012-03-24 01:12:42.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/iwmc3200top/iwmc3200top.h	2012-03-24 03:33:28.000000000 -0400
@@ -183,9 +183,7 @@
 	u32 barker;
 	struct iwmct_dbg dbg;
 
-	/* drivers work queue */
-	struct workqueue_struct *wq;
-	struct workqueue_struct *bus_rescan_wq;
+	/* drivers work items */
 	struct work_struct bus_rescan_worker;
 	struct work_struct isr_worker;
 
diff -druN linux-libre-2.6.38-gnu/drivers/misc/iwmc3200top/main.c linux-libre-2.6.39-gnu/drivers/misc/iwmc3200top/main.c
--- linux-libre-2.6.38-gnu/drivers/misc/iwmc3200top/main.c	2012-03-24 01:12:46.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/iwmc3200top/main.c	2012-03-24 03:33:30.000000000 -0400
@@ -89,7 +89,7 @@
 	switch (msg->hdr.opcode) {
 	case OP_OPR_ALIVE:
 		LOG_INFO(priv, FW_MSG, "Got ALIVE from device, wake rescan\n");
-		queue_work(priv->bus_rescan_wq, &priv->bus_rescan_worker);
+		schedule_work(&priv->bus_rescan_worker);
 		break;
 	default:
 		LOG_INFO(priv, FW_MSG, "Received msg opcode 0x%X\n",
@@ -268,7 +268,7 @@
 		LOG_INFO(priv, IRQ, "ACK barker arrived "
 				"- starting FW download\n");
 	} else { /* REBOOT barker */
-		LOG_INFO(priv, IRQ, "Recieved reboot barker: %x\n", barker);
+		LOG_INFO(priv, IRQ, "Received reboot barker: %x\n", barker);
 		priv->barker = barker;
 
 		if (barker & BARKER_DNLOAD_SYNC_MSK) {
@@ -360,7 +360,7 @@
 	/* clear the function's interrupt request bit (write 1 to clear) */
 	sdio_writeb(func, 1, IWMC_SDIO_INTR_CLEAR_ADDR, &ret);
 
-	queue_work(priv->wq, &priv->isr_worker);
+	schedule_work(&priv->isr_worker);
 
 	LOG_TRACE(priv, IRQ, "exit iwmct_irq\n");
 
@@ -506,10 +506,6 @@
 	priv->func = func;
 	sdio_set_drvdata(func, priv);
 
-
-	/* create drivers work queue */
-	priv->wq = create_workqueue(DRV_NAME "_wq");
-	priv->bus_rescan_wq = create_workqueue(DRV_NAME "_rescan_wq");
 	INIT_WORK(&priv->bus_rescan_worker, iwmct_rescan_worker);
 	INIT_WORK(&priv->isr_worker, iwmct_irq_read_worker);
 
@@ -604,9 +600,9 @@
 	sdio_release_irq(func);
 	sdio_release_host(func);
 
-	/* Safely destroy osc workqueue */
-	destroy_workqueue(priv->bus_rescan_wq);
-	destroy_workqueue(priv->wq);
+	/* Make sure works are finished */
+	flush_work_sync(&priv->bus_rescan_worker);
+	flush_work_sync(&priv->isr_worker);
 
 	sdio_claim_host(func);
 	sdio_disable_func(func);
diff -druN linux-libre-2.6.38-gnu/drivers/misc/Kconfig linux-libre-2.6.39-gnu/drivers/misc/Kconfig
--- linux-libre-2.6.38-gnu/drivers/misc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,14 @@
 # Misc strange devices
 #
 
+# This one has to live outside of the MISC_DEVICES conditional,
+# because it may be selected by drivers/platform/x86/hp_accel.
+config SENSORS_LIS3LV02D
+	tristate
+	depends on INPUT
+	select INPUT_POLLDEV
+	default n
+
 menuconfig MISC_DEVICES
 	bool "Misc devices"
 	---help---
@@ -394,6 +402,16 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called ds1682.
 
+config SPEAR13XX_PCIE_GADGET
+	bool "PCIe gadget support for SPEAr13XX platform"
+	depends on ARCH_SPEAR13XX
+	default n
+	help
+	 This option enables gadget support for PCIe controller. If
+	 board file defines any controller as PCIe endpoint then a sysfs
+	 entry will be created for that controller. User can use these
+	 sysfs node to configure PCIe EP as per his requirements.
+
 config TI_DAC7512
 	tristate "Texas Instruments DAC7512"
 	depends on SPI && SYSFS
@@ -441,7 +459,7 @@
 	  module will be called bmp085.
 
 config PCH_PHUB
-	tristate "PCH Packet Hub of Intel Topcliff"
+	tristate "PCH Packet Hub of Intel Topcliff / OKI SEMICONDUCTOR ML7213"
 	depends on PCI
 	help
 	  This driver is for PCH(Platform controller Hub) PHUB(Packet Hub) of
@@ -449,6 +467,11 @@
 	  processor. The Topcliff has MAC address and Option ROM data in SROM.
 	  This driver can access MAC address and Option ROM data in SROM.
 
+	  This driver also can be used for OKI SEMICONDUCTOR's ML7213 which is
+	  for IVI(In-Vehicle Infotainment) use.
+	  ML7213 is companion chip for Intel Atom E6xx series.
+	  ML7213 is completely compatible for Intel EG20T PCH.
+
 	  To compile this driver as a module, choose M here: the module will
 	  be called pch_phub.
 
@@ -457,5 +480,6 @@
 source "drivers/misc/cb710/Kconfig"
 source "drivers/misc/iwmc3200top/Kconfig"
 source "drivers/misc/ti-st/Kconfig"
+source "drivers/misc/lis3lv02d/Kconfig"
 
 endif # MISC_DEVICES
diff -druN linux-libre-2.6.38-gnu/drivers/misc/kgdbts.c linux-libre-2.6.39-gnu/drivers/misc/kgdbts.c
--- linux-libre-2.6.38-gnu/drivers/misc/kgdbts.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/kgdbts.c	2011-05-19 00:06:34.000000000 -0400
@@ -645,7 +645,7 @@
 
 	while (*chk_str != '\0' && *put_str != '\0') {
 		/* If someone does a * to match the rest of the string, allow
-		 * it, or stop if the recieved string is complete.
+		 * it, or stop if the received string is complete.
 		 */
 		if (*put_str == '#' || *chk_str == '*')
 			return 0;
@@ -988,7 +988,7 @@
 
 static int kgdbts_option_setup(char *opt)
 {
-	if (strlen(opt) > MAX_CONFIG_LEN) {
+	if (strlen(opt) >= MAX_CONFIG_LEN) {
 		printk(KERN_ERR "kgdbts: config string too long\n");
 		return -ENOSPC;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/Kconfig linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/Kconfig
--- linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,37 @@
+#
+# STMicroelectonics LIS3LV02D and similar accelerometers
+#
+
+config SENSORS_LIS3_SPI
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
+	depends on !ACPI && SPI_MASTER && INPUT
+	select SENSORS_LIS3LV02D
+	default n
+	help
+	  This driver provides support for the LIS3LV02Dx accelerometer connected
+	  via SPI. The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the laptop to act as a pinball machine-esque joystick.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for the SPI transport
+	  is called lis3lv02d_spi.
+
+config SENSORS_LIS3_I2C
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (I2C)"
+	depends on I2C && INPUT
+	select SENSORS_LIS3LV02D
+	default n
+	help
+	  This driver provides support for the LIS3LV02Dx accelerometer connected
+	  via I2C. The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the device to act as a pinball machine-esque joystick.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for the I2C transport
+	  is called lis3lv02d_i2c.
diff -druN linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d.c linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d.c
--- linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,999 @@
+/*
+ *  lis3lv02d.c - ST LIS3LV02DL accelerometer driver
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008 Eric Piel
+ *  Copyright (C) 2008-2009 Pavel Machek
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/input-polldev.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/miscdevice.h>
+#include <linux/pm_runtime.h>
+#include <linux/atomic.h>
+#include "lis3lv02d.h"
+
+#define DRIVER_NAME     "lis3lv02d"
+
+/* joystick device poll interval in milliseconds */
+#define MDPS_POLL_INTERVAL 50
+#define MDPS_POLL_MIN	   0
+#define MDPS_POLL_MAX	   2000
+
+#define LIS3_SYSFS_POWERDOWN_DELAY 5000 /* In milliseconds */
+
+#define SELFTEST_OK	       0
+#define SELFTEST_FAIL	       -1
+#define SELFTEST_IRQ	       -2
+
+#define IRQ_LINE0	       0
+#define IRQ_LINE1	       1
+
+/*
+ * The sensor can also generate interrupts (DRDY) but it's pretty pointless
+ * because they are generated even if the data do not change. So it's better
+ * to keep the interrupt for the free-fall event. The values are updated at
+ * 40Hz (at the lowest frequency), but as it can be pretty time consuming on
+ * some low processor, we poll the sensor only at 20Hz... enough for the
+ * joystick.
+ */
+
+#define LIS3_PWRON_DELAY_WAI_12B	(5000)
+#define LIS3_PWRON_DELAY_WAI_8B		(3000)
+
+/*
+ * LIS3LV02D spec says 1024 LSBs corresponds 1 G -> 1LSB is 1000/1024 mG
+ * LIS302D spec says: 18 mG / digit
+ * LIS3_ACCURACY is used to increase accuracy of the intermediate
+ * calculation results.
+ */
+#define LIS3_ACCURACY			1024
+/* Sensitivity values for -2G +2G scale */
+#define LIS3_SENSITIVITY_12B		((LIS3_ACCURACY * 1000) / 1024)
+#define LIS3_SENSITIVITY_8B		(18 * LIS3_ACCURACY)
+
+#define LIS3_DEFAULT_FUZZ_12B		3
+#define LIS3_DEFAULT_FLAT_12B		3
+#define LIS3_DEFAULT_FUZZ_8B		1
+#define LIS3_DEFAULT_FLAT_8B		1
+
+struct lis3lv02d lis3_dev = {
+	.misc_wait   = __WAIT_QUEUE_HEAD_INITIALIZER(lis3_dev.misc_wait),
+};
+EXPORT_SYMBOL_GPL(lis3_dev);
+
+/* just like param_set_int() but does sanity-check so that it won't point
+ * over the axis array size
+ */
+static int param_set_axis(const char *val, const struct kernel_param *kp)
+{
+	int ret = param_set_int(val, kp);
+	if (!ret) {
+		int val = *(int *)kp->arg;
+		if (val < 0)
+			val = -val;
+		if (!val || val > 3)
+			return -EINVAL;
+	}
+	return ret;
+}
+
+static struct kernel_param_ops param_ops_axis = {
+	.set = param_set_axis,
+	.get = param_get_int,
+};
+
+module_param_array_named(axes, lis3_dev.ac.as_array, axis, NULL, 0644);
+MODULE_PARM_DESC(axes, "Axis-mapping for x,y,z directions");
+
+static s16 lis3lv02d_read_8(struct lis3lv02d *lis3, int reg)
+{
+	s8 lo;
+	if (lis3->read(lis3, reg, &lo) < 0)
+		return 0;
+
+	return lo;
+}
+
+static s16 lis3lv02d_read_12(struct lis3lv02d *lis3, int reg)
+{
+	u8 lo, hi;
+
+	lis3->read(lis3, reg - 1, &lo);
+	lis3->read(lis3, reg, &hi);
+	/* In "12 bit right justified" mode, bit 6, bit 7, bit 8 = bit 5 */
+	return (s16)((hi << 8) | lo);
+}
+
+/**
+ * lis3lv02d_get_axis - For the given axis, give the value converted
+ * @axis:      1,2,3 - can also be negative
+ * @hw_values: raw values returned by the hardware
+ *
+ * Returns the converted value.
+ */
+static inline int lis3lv02d_get_axis(s8 axis, int hw_values[3])
+{
+	if (axis > 0)
+		return hw_values[axis - 1];
+	else
+		return -hw_values[-axis - 1];
+}
+
+/**
+ * lis3lv02d_get_xyz - Get X, Y and Z axis values from the accelerometer
+ * @lis3: pointer to the device struct
+ * @x:    where to store the X axis value
+ * @y:    where to store the Y axis value
+ * @z:    where to store the Z axis value
+ *
+ * Note that 40Hz input device can eat up about 10% CPU at 800MHZ
+ */
+static void lis3lv02d_get_xyz(struct lis3lv02d *lis3, int *x, int *y, int *z)
+{
+	int position[3];
+	int i;
+
+	if (lis3->blkread) {
+		if (lis3_dev.whoami == WAI_12B) {
+			u16 data[3];
+			lis3->blkread(lis3, OUTX_L, 6, (u8 *)data);
+			for (i = 0; i < 3; i++)
+				position[i] = (s16)le16_to_cpu(data[i]);
+		} else {
+			u8 data[5];
+			/* Data: x, dummy, y, dummy, z */
+			lis3->blkread(lis3, OUTX, 5, data);
+			for (i = 0; i < 3; i++)
+				position[i] = (s8)data[i * 2];
+		}
+	} else {
+		position[0] = lis3->read_data(lis3, OUTX);
+		position[1] = lis3->read_data(lis3, OUTY);
+		position[2] = lis3->read_data(lis3, OUTZ);
+	}
+
+	for (i = 0; i < 3; i++)
+		position[i] = (position[i] * lis3->scale) / LIS3_ACCURACY;
+
+	*x = lis3lv02d_get_axis(lis3->ac.x, position);
+	*y = lis3lv02d_get_axis(lis3->ac.y, position);
+	*z = lis3lv02d_get_axis(lis3->ac.z, position);
+}
+
+/* conversion btw sampling rate and the register values */
+static int lis3_12_rates[4] = {40, 160, 640, 2560};
+static int lis3_8_rates[2] = {100, 400};
+static int lis3_3dc_rates[16] = {0, 1, 10, 25, 50, 100, 200, 400, 1600, 5000};
+
+/* ODR is Output Data Rate */
+static int lis3lv02d_get_odr(void)
+{
+	u8 ctrl;
+	int shift;
+
+	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
+	ctrl &= lis3_dev.odr_mask;
+	shift = ffs(lis3_dev.odr_mask) - 1;
+	return lis3_dev.odrs[(ctrl >> shift)];
+}
+
+static int lis3lv02d_set_odr(int rate)
+{
+	u8 ctrl;
+	int i, len, shift;
+
+	if (!rate)
+		return -EINVAL;
+
+	lis3_dev.read(&lis3_dev, CTRL_REG1, &ctrl);
+	ctrl &= ~lis3_dev.odr_mask;
+	len = 1 << hweight_long(lis3_dev.odr_mask); /* # of possible values */
+	shift = ffs(lis3_dev.odr_mask) - 1;
+
+	for (i = 0; i < len; i++)
+		if (lis3_dev.odrs[i] == rate) {
+			lis3_dev.write(&lis3_dev, CTRL_REG1,
+					ctrl | (i << shift));
+			return 0;
+		}
+	return -EINVAL;
+}
+
+static int lis3lv02d_selftest(struct lis3lv02d *lis3, s16 results[3])
+{
+	u8 ctlreg, reg;
+	s16 x, y, z;
+	u8 selftest;
+	int ret;
+	u8 ctrl_reg_data;
+	unsigned char irq_cfg;
+
+	mutex_lock(&lis3->mutex);
+
+	irq_cfg = lis3->irq_cfg;
+	if (lis3_dev.whoami == WAI_8B) {
+		lis3->data_ready_count[IRQ_LINE0] = 0;
+		lis3->data_ready_count[IRQ_LINE1] = 0;
+
+		/* Change interrupt cfg to data ready for selftest */
+		atomic_inc(&lis3_dev.wake_thread);
+		lis3->irq_cfg = LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY;
+		lis3->read(lis3, CTRL_REG3, &ctrl_reg_data);
+		lis3->write(lis3, CTRL_REG3, (ctrl_reg_data &
+				~(LIS3_IRQ1_MASK | LIS3_IRQ2_MASK)) |
+				(LIS3_IRQ1_DATA_READY | LIS3_IRQ2_DATA_READY));
+	}
+
+	if (lis3_dev.whoami == WAI_3DC) {
+		ctlreg = CTRL_REG4;
+		selftest = CTRL4_ST0;
+	} else {
+		ctlreg = CTRL_REG1;
+		if (lis3_dev.whoami == WAI_12B)
+			selftest = CTRL1_ST;
+		else
+			selftest = CTRL1_STP;
+	}
+
+	lis3->read(lis3, ctlreg, &reg);
+	lis3->write(lis3, ctlreg, (reg | selftest));
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	/* Read directly to avoid axis remap */
+	x = lis3->read_data(lis3, OUTX);
+	y = lis3->read_data(lis3, OUTY);
+	z = lis3->read_data(lis3, OUTZ);
+
+	/* back to normal settings */
+	lis3->write(lis3, ctlreg, reg);
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	results[0] = x - lis3->read_data(lis3, OUTX);
+	results[1] = y - lis3->read_data(lis3, OUTY);
+	results[2] = z - lis3->read_data(lis3, OUTZ);
+
+	ret = 0;
+
+	if (lis3_dev.whoami == WAI_8B) {
+		/* Restore original interrupt configuration */
+		atomic_dec(&lis3_dev.wake_thread);
+		lis3->write(lis3, CTRL_REG3, ctrl_reg_data);
+		lis3->irq_cfg = irq_cfg;
+
+		if ((irq_cfg & LIS3_IRQ1_MASK) &&
+			lis3->data_ready_count[IRQ_LINE0] < 2) {
+			ret = SELFTEST_IRQ;
+			goto fail;
+		}
+
+		if ((irq_cfg & LIS3_IRQ2_MASK) &&
+			lis3->data_ready_count[IRQ_LINE1] < 2) {
+			ret = SELFTEST_IRQ;
+			goto fail;
+		}
+	}
+
+	if (lis3->pdata) {
+		int i;
+		for (i = 0; i < 3; i++) {
+			/* Check against selftest acceptance limits */
+			if ((results[i] < lis3->pdata->st_min_limits[i]) ||
+			    (results[i] > lis3->pdata->st_max_limits[i])) {
+				ret = SELFTEST_FAIL;
+				goto fail;
+			}
+		}
+	}
+
+	/* test passed */
+fail:
+	mutex_unlock(&lis3->mutex);
+	return ret;
+}
+
+/*
+ * Order of registers in the list affects to order of the restore process.
+ * Perhaps it is a good idea to set interrupt enable register as a last one
+ * after all other configurations
+ */
+static u8 lis3_wai8_regs[] = { FF_WU_CFG_1, FF_WU_THS_1, FF_WU_DURATION_1,
+			       FF_WU_CFG_2, FF_WU_THS_2, FF_WU_DURATION_2,
+			       CLICK_CFG, CLICK_SRC, CLICK_THSY_X, CLICK_THSZ,
+			       CLICK_TIMELIMIT, CLICK_LATENCY, CLICK_WINDOW,
+			       CTRL_REG1, CTRL_REG2, CTRL_REG3};
+
+static u8 lis3_wai12_regs[] = {FF_WU_CFG, FF_WU_THS_L, FF_WU_THS_H,
+			       FF_WU_DURATION, DD_CFG, DD_THSI_L, DD_THSI_H,
+			       DD_THSE_L, DD_THSE_H,
+			       CTRL_REG1, CTRL_REG3, CTRL_REG2};
+
+static inline void lis3_context_save(struct lis3lv02d *lis3)
+{
+	int i;
+	for (i = 0; i < lis3->regs_size; i++)
+		lis3->read(lis3, lis3->regs[i], &lis3->reg_cache[i]);
+	lis3->regs_stored = true;
+}
+
+static inline void lis3_context_restore(struct lis3lv02d *lis3)
+{
+	int i;
+	if (lis3->regs_stored)
+		for (i = 0; i < lis3->regs_size; i++)
+			lis3->write(lis3, lis3->regs[i], lis3->reg_cache[i]);
+}
+
+void lis3lv02d_poweroff(struct lis3lv02d *lis3)
+{
+	if (lis3->reg_ctrl)
+		lis3_context_save(lis3);
+	/* disable X,Y,Z axis and power down */
+	lis3->write(lis3, CTRL_REG1, 0x00);
+	if (lis3->reg_ctrl)
+		lis3->reg_ctrl(lis3, LIS3_REG_OFF);
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweroff);
+
+void lis3lv02d_poweron(struct lis3lv02d *lis3)
+{
+	u8 reg;
+
+	lis3->init(lis3);
+
+	/*
+	 * Common configuration
+	 * BDU: (12 bits sensors only) LSB and MSB values are not updated until
+	 *      both have been read. So the value read will always be correct.
+	 * Set BOOT bit to refresh factory tuning values.
+	 */
+	lis3->read(lis3, CTRL_REG2, &reg);
+	if (lis3->whoami ==  WAI_12B)
+		reg |= CTRL2_BDU | CTRL2_BOOT;
+	else
+		reg |= CTRL2_BOOT_8B;
+	lis3->write(lis3, CTRL_REG2, reg);
+
+	/* LIS3 power on delay is quite long */
+	msleep(lis3->pwron_delay / lis3lv02d_get_odr());
+
+	if (lis3->reg_ctrl)
+		lis3_context_restore(lis3);
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_poweron);
+
+
+static void lis3lv02d_joystick_poll(struct input_polled_dev *pidev)
+{
+	int x, y, z;
+
+	mutex_lock(&lis3_dev.mutex);
+	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+	input_report_abs(pidev->input, ABS_X, x);
+	input_report_abs(pidev->input, ABS_Y, y);
+	input_report_abs(pidev->input, ABS_Z, z);
+	input_sync(pidev->input);
+	mutex_unlock(&lis3_dev.mutex);
+}
+
+static void lis3lv02d_joystick_open(struct input_polled_dev *pidev)
+{
+	if (lis3_dev.pm_dev)
+		pm_runtime_get_sync(lis3_dev.pm_dev);
+
+	if (lis3_dev.pdata && lis3_dev.whoami == WAI_8B && lis3_dev.idev)
+		atomic_set(&lis3_dev.wake_thread, 1);
+	/*
+	 * Update coordinates for the case where poll interval is 0 and
+	 * the chip in running purely under interrupt control
+	 */
+	lis3lv02d_joystick_poll(pidev);
+}
+
+static void lis3lv02d_joystick_close(struct input_polled_dev *pidev)
+{
+	atomic_set(&lis3_dev.wake_thread, 0);
+	if (lis3_dev.pm_dev)
+		pm_runtime_put(lis3_dev.pm_dev);
+}
+
+static irqreturn_t lis302dl_interrupt(int irq, void *dummy)
+{
+	if (!test_bit(0, &lis3_dev.misc_opened))
+		goto out;
+
+	/*
+	 * Be careful: on some HP laptops the bios force DD when on battery and
+	 * the lid is closed. This leads to interrupts as soon as a little move
+	 * is done.
+	 */
+	atomic_inc(&lis3_dev.count);
+
+	wake_up_interruptible(&lis3_dev.misc_wait);
+	kill_fasync(&lis3_dev.async_queue, SIGIO, POLL_IN);
+out:
+	if (atomic_read(&lis3_dev.wake_thread))
+		return IRQ_WAKE_THREAD;
+	return IRQ_HANDLED;
+}
+
+static void lis302dl_interrupt_handle_click(struct lis3lv02d *lis3)
+{
+	struct input_dev *dev = lis3->idev->input;
+	u8 click_src;
+
+	mutex_lock(&lis3->mutex);
+	lis3->read(lis3, CLICK_SRC, &click_src);
+
+	if (click_src & CLICK_SINGLE_X) {
+		input_report_key(dev, lis3->mapped_btns[0], 1);
+		input_report_key(dev, lis3->mapped_btns[0], 0);
+	}
+
+	if (click_src & CLICK_SINGLE_Y) {
+		input_report_key(dev, lis3->mapped_btns[1], 1);
+		input_report_key(dev, lis3->mapped_btns[1], 0);
+	}
+
+	if (click_src & CLICK_SINGLE_Z) {
+		input_report_key(dev, lis3->mapped_btns[2], 1);
+		input_report_key(dev, lis3->mapped_btns[2], 0);
+	}
+	input_sync(dev);
+	mutex_unlock(&lis3->mutex);
+}
+
+static inline void lis302dl_data_ready(struct lis3lv02d *lis3, int index)
+{
+	int dummy;
+
+	/* Dummy read to ack interrupt */
+	lis3lv02d_get_xyz(lis3, &dummy, &dummy, &dummy);
+	lis3->data_ready_count[index]++;
+}
+
+static irqreturn_t lis302dl_interrupt_thread1_8b(int irq, void *data)
+{
+	struct lis3lv02d *lis3 = data;
+	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ1_MASK;
+
+	if (irq_cfg == LIS3_IRQ1_CLICK)
+		lis302dl_interrupt_handle_click(lis3);
+	else if (unlikely(irq_cfg == LIS3_IRQ1_DATA_READY))
+		lis302dl_data_ready(lis3, IRQ_LINE0);
+	else
+		lis3lv02d_joystick_poll(lis3->idev);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t lis302dl_interrupt_thread2_8b(int irq, void *data)
+{
+	struct lis3lv02d *lis3 = data;
+	u8 irq_cfg = lis3->irq_cfg & LIS3_IRQ2_MASK;
+
+	if (irq_cfg == LIS3_IRQ2_CLICK)
+		lis302dl_interrupt_handle_click(lis3);
+	else if (unlikely(irq_cfg == LIS3_IRQ2_DATA_READY))
+		lis302dl_data_ready(lis3, IRQ_LINE1);
+	else
+		lis3lv02d_joystick_poll(lis3->idev);
+
+	return IRQ_HANDLED;
+}
+
+static int lis3lv02d_misc_open(struct inode *inode, struct file *file)
+{
+	if (test_and_set_bit(0, &lis3_dev.misc_opened))
+		return -EBUSY; /* already open */
+
+	if (lis3_dev.pm_dev)
+		pm_runtime_get_sync(lis3_dev.pm_dev);
+
+	atomic_set(&lis3_dev.count, 0);
+	return 0;
+}
+
+static int lis3lv02d_misc_release(struct inode *inode, struct file *file)
+{
+	fasync_helper(-1, file, 0, &lis3_dev.async_queue);
+	clear_bit(0, &lis3_dev.misc_opened); /* release the device */
+	if (lis3_dev.pm_dev)
+		pm_runtime_put(lis3_dev.pm_dev);
+	return 0;
+}
+
+static ssize_t lis3lv02d_misc_read(struct file *file, char __user *buf,
+				size_t count, loff_t *pos)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	u32 data;
+	unsigned char byte_data;
+	ssize_t retval = 1;
+
+	if (count < 1)
+		return -EINVAL;
+
+	add_wait_queue(&lis3_dev.misc_wait, &wait);
+	while (true) {
+		set_current_state(TASK_INTERRUPTIBLE);
+		data = atomic_xchg(&lis3_dev.count, 0);
+		if (data)
+			break;
+
+		if (file->f_flags & O_NONBLOCK) {
+			retval = -EAGAIN;
+			goto out;
+		}
+
+		if (signal_pending(current)) {
+			retval = -ERESTARTSYS;
+			goto out;
+		}
+
+		schedule();
+	}
+
+	if (data < 255)
+		byte_data = data;
+	else
+		byte_data = 255;
+
+	/* make sure we are not going into copy_to_user() with
+	 * TASK_INTERRUPTIBLE state */
+	set_current_state(TASK_RUNNING);
+	if (copy_to_user(buf, &byte_data, sizeof(byte_data)))
+		retval = -EFAULT;
+
+out:
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&lis3_dev.misc_wait, &wait);
+
+	return retval;
+}
+
+static unsigned int lis3lv02d_misc_poll(struct file *file, poll_table *wait)
+{
+	poll_wait(file, &lis3_dev.misc_wait, wait);
+	if (atomic_read(&lis3_dev.count))
+		return POLLIN | POLLRDNORM;
+	return 0;
+}
+
+static int lis3lv02d_misc_fasync(int fd, struct file *file, int on)
+{
+	return fasync_helper(fd, file, on, &lis3_dev.async_queue);
+}
+
+static const struct file_operations lis3lv02d_misc_fops = {
+	.owner   = THIS_MODULE,
+	.llseek  = no_llseek,
+	.read    = lis3lv02d_misc_read,
+	.open    = lis3lv02d_misc_open,
+	.release = lis3lv02d_misc_release,
+	.poll    = lis3lv02d_misc_poll,
+	.fasync  = lis3lv02d_misc_fasync,
+};
+
+static struct miscdevice lis3lv02d_misc_device = {
+	.minor   = MISC_DYNAMIC_MINOR,
+	.name    = "freefall",
+	.fops    = &lis3lv02d_misc_fops,
+};
+
+int lis3lv02d_joystick_enable(void)
+{
+	struct input_dev *input_dev;
+	int err;
+	int max_val, fuzz, flat;
+	int btns[] = {BTN_X, BTN_Y, BTN_Z};
+
+	if (lis3_dev.idev)
+		return -EINVAL;
+
+	lis3_dev.idev = input_allocate_polled_device();
+	if (!lis3_dev.idev)
+		return -ENOMEM;
+
+	lis3_dev.idev->poll = lis3lv02d_joystick_poll;
+	lis3_dev.idev->open = lis3lv02d_joystick_open;
+	lis3_dev.idev->close = lis3lv02d_joystick_close;
+	lis3_dev.idev->poll_interval = MDPS_POLL_INTERVAL;
+	lis3_dev.idev->poll_interval_min = MDPS_POLL_MIN;
+	lis3_dev.idev->poll_interval_max = MDPS_POLL_MAX;
+	input_dev = lis3_dev.idev->input;
+
+	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, input_dev->evbit);
+	max_val = (lis3_dev.mdps_max_val * lis3_dev.scale) / LIS3_ACCURACY;
+	if (lis3_dev.whoami == WAI_12B) {
+		fuzz = LIS3_DEFAULT_FUZZ_12B;
+		flat = LIS3_DEFAULT_FLAT_12B;
+	} else {
+		fuzz = LIS3_DEFAULT_FUZZ_8B;
+		flat = LIS3_DEFAULT_FLAT_8B;
+	}
+	fuzz = (fuzz * lis3_dev.scale) / LIS3_ACCURACY;
+	flat = (flat * lis3_dev.scale) / LIS3_ACCURACY;
+
+	input_set_abs_params(input_dev, ABS_X, -max_val, max_val, fuzz, flat);
+	input_set_abs_params(input_dev, ABS_Y, -max_val, max_val, fuzz, flat);
+	input_set_abs_params(input_dev, ABS_Z, -max_val, max_val, fuzz, flat);
+
+	lis3_dev.mapped_btns[0] = lis3lv02d_get_axis(abs(lis3_dev.ac.x), btns);
+	lis3_dev.mapped_btns[1] = lis3lv02d_get_axis(abs(lis3_dev.ac.y), btns);
+	lis3_dev.mapped_btns[2] = lis3lv02d_get_axis(abs(lis3_dev.ac.z), btns);
+
+	err = input_register_polled_device(lis3_dev.idev);
+	if (err) {
+		input_free_polled_device(lis3_dev.idev);
+		lis3_dev.idev = NULL;
+	}
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_enable);
+
+void lis3lv02d_joystick_disable(void)
+{
+	if (lis3_dev.irq)
+		free_irq(lis3_dev.irq, &lis3_dev);
+	if (lis3_dev.pdata && lis3_dev.pdata->irq2)
+		free_irq(lis3_dev.pdata->irq2, &lis3_dev);
+
+	if (!lis3_dev.idev)
+		return;
+
+	if (lis3_dev.irq)
+		misc_deregister(&lis3lv02d_misc_device);
+	input_unregister_polled_device(lis3_dev.idev);
+	input_free_polled_device(lis3_dev.idev);
+	lis3_dev.idev = NULL;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_joystick_disable);
+
+/* Sysfs stuff */
+static void lis3lv02d_sysfs_poweron(struct lis3lv02d *lis3)
+{
+	/*
+	 * SYSFS functions are fast visitors so put-call
+	 * immediately after the get-call. However, keep
+	 * chip running for a while and schedule delayed
+	 * suspend. This way periodic sysfs calls doesn't
+	 * suffer from relatively long power up time.
+	 */
+
+	if (lis3->pm_dev) {
+		pm_runtime_get_sync(lis3->pm_dev);
+		pm_runtime_put_noidle(lis3->pm_dev);
+		pm_schedule_suspend(lis3->pm_dev, LIS3_SYSFS_POWERDOWN_DELAY);
+	}
+}
+
+static ssize_t lis3lv02d_selftest_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	s16 values[3];
+
+	static const char ok[] = "OK";
+	static const char fail[] = "FAIL";
+	static const char irq[] = "FAIL_IRQ";
+	const char *res;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	switch (lis3lv02d_selftest(&lis3_dev, values)) {
+	case SELFTEST_FAIL:
+		res = fail;
+		break;
+	case SELFTEST_IRQ:
+		res = irq;
+		break;
+	case SELFTEST_OK:
+	default:
+		res = ok;
+		break;
+	}
+	return sprintf(buf, "%s %d %d %d\n", res,
+		values[0], values[1], values[2]);
+}
+
+static ssize_t lis3lv02d_position_show(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int x, y, z;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	mutex_lock(&lis3_dev.mutex);
+	lis3lv02d_get_xyz(&lis3_dev, &x, &y, &z);
+	mutex_unlock(&lis3_dev.mutex);
+	return sprintf(buf, "(%d,%d,%d)\n", x, y, z);
+}
+
+static ssize_t lis3lv02d_rate_show(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	return sprintf(buf, "%d\n", lis3lv02d_get_odr());
+}
+
+static ssize_t lis3lv02d_rate_set(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
+{
+	unsigned long rate;
+
+	if (strict_strtoul(buf, 0, &rate))
+		return -EINVAL;
+
+	lis3lv02d_sysfs_poweron(&lis3_dev);
+	if (lis3lv02d_set_odr(rate))
+		return -EINVAL;
+
+	return count;
+}
+
+static DEVICE_ATTR(selftest, S_IRUSR, lis3lv02d_selftest_show, NULL);
+static DEVICE_ATTR(position, S_IRUGO, lis3lv02d_position_show, NULL);
+static DEVICE_ATTR(rate, S_IRUGO | S_IWUSR, lis3lv02d_rate_show,
+					    lis3lv02d_rate_set);
+
+static struct attribute *lis3lv02d_attributes[] = {
+	&dev_attr_selftest.attr,
+	&dev_attr_position.attr,
+	&dev_attr_rate.attr,
+	NULL
+};
+
+static struct attribute_group lis3lv02d_attribute_group = {
+	.attrs = lis3lv02d_attributes
+};
+
+
+static int lis3lv02d_add_fs(struct lis3lv02d *lis3)
+{
+	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->pdev->dev.kobj, &lis3lv02d_attribute_group);
+}
+
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3)
+{
+	sysfs_remove_group(&lis3->pdev->dev.kobj, &lis3lv02d_attribute_group);
+	platform_device_unregister(lis3->pdev);
+	if (lis3->pm_dev) {
+		/* Barrier after the sysfs remove */
+		pm_runtime_barrier(lis3->pm_dev);
+
+		/* SYSFS may have left chip running. Turn off if necessary */
+		if (!pm_runtime_suspended(lis3->pm_dev))
+			lis3lv02d_poweroff(&lis3_dev);
+
+		pm_runtime_disable(lis3->pm_dev);
+		pm_runtime_set_suspended(lis3->pm_dev);
+	}
+	kfree(lis3->reg_cache);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_remove_fs);
+
+static void lis3lv02d_8b_configure(struct lis3lv02d *dev,
+				struct lis3lv02d_platform_data *p)
+{
+	int err;
+	int ctrl2 = p->hipass_ctrl;
+
+	if (p->click_flags) {
+		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 (dev->idev) {
+			struct input_dev *input_dev = lis3_dev.idev->input;
+			input_set_capability(input_dev, EV_KEY, BTN_X);
+			input_set_capability(input_dev, EV_KEY, BTN_Y);
+			input_set_capability(input_dev, EV_KEY, BTN_Z);
+		}
+	}
+
+	if (p->wakeup_flags) {
+		dev->write(dev, FF_WU_CFG_1, p->wakeup_flags);
+		dev->write(dev, FF_WU_THS_1, p->wakeup_thresh & 0x7f);
+		/* pdata value + 1 to keep this backward compatible*/
+		dev->write(dev, FF_WU_DURATION_1, p->duration1 + 1);
+		ctrl2 ^= HP_FF_WU1; /* Xor to keep compatible with old pdata*/
+	}
+
+	if (p->wakeup_flags2) {
+		dev->write(dev, FF_WU_CFG_2, p->wakeup_flags2);
+		dev->write(dev, FF_WU_THS_2, p->wakeup_thresh2 & 0x7f);
+		/* pdata value + 1 to keep this backward compatible*/
+		dev->write(dev, FF_WU_DURATION_2, p->duration2 + 1);
+		ctrl2 ^= HP_FF_WU2; /* Xor to keep compatible with old pdata*/
+	}
+	/* Configure hipass filters */
+	dev->write(dev, CTRL_REG2, ctrl2);
+
+	if (p->irq2) {
+		err = request_threaded_irq(p->irq2,
+					NULL,
+					lis302dl_interrupt_thread2_8b,
+					IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+					(p->irq_flags2 & IRQF_TRIGGER_MASK),
+					DRIVER_NAME, &lis3_dev);
+		if (err < 0)
+			pr_err("No second IRQ. Limited functionality\n");
+	}
+}
+
+/*
+ * Initialise the accelerometer and the various subsystems.
+ * Should be rather independent of the bus system.
+ */
+int lis3lv02d_init_device(struct lis3lv02d *dev)
+{
+	int err;
+	irq_handler_t thread_fn;
+	int irq_flags = 0;
+
+	dev->whoami = lis3lv02d_read_8(dev, WHO_AM_I);
+
+	switch (dev->whoami) {
+	case WAI_12B:
+		pr_info("12 bits sensor found\n");
+		dev->read_data = lis3lv02d_read_12;
+		dev->mdps_max_val = 2048;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_12B;
+		dev->odrs = lis3_12_rates;
+		dev->odr_mask = CTRL1_DF0 | CTRL1_DF1;
+		dev->scale = LIS3_SENSITIVITY_12B;
+		dev->regs = lis3_wai12_regs;
+		dev->regs_size = ARRAY_SIZE(lis3_wai12_regs);
+		break;
+	case WAI_8B:
+		pr_info("8 bits sensor found\n");
+		dev->read_data = lis3lv02d_read_8;
+		dev->mdps_max_val = 128;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		dev->odrs = lis3_8_rates;
+		dev->odr_mask = CTRL1_DR;
+		dev->scale = LIS3_SENSITIVITY_8B;
+		dev->regs = lis3_wai8_regs;
+		dev->regs_size = ARRAY_SIZE(lis3_wai8_regs);
+		break;
+	case WAI_3DC:
+		pr_info("8 bits 3DC sensor found\n");
+		dev->read_data = lis3lv02d_read_8;
+		dev->mdps_max_val = 128;
+		dev->pwron_delay = LIS3_PWRON_DELAY_WAI_8B;
+		dev->odrs = lis3_3dc_rates;
+		dev->odr_mask = CTRL1_ODR0|CTRL1_ODR1|CTRL1_ODR2|CTRL1_ODR3;
+		dev->scale = LIS3_SENSITIVITY_8B;
+		break;
+	default:
+		pr_err("unknown sensor type 0x%X\n", dev->whoami);
+		return -EINVAL;
+	}
+
+	dev->reg_cache = kzalloc(max(sizeof(lis3_wai8_regs),
+				     sizeof(lis3_wai12_regs)), GFP_KERNEL);
+
+	if (dev->reg_cache == NULL) {
+		printk(KERN_ERR DRIVER_NAME "out of memory\n");
+		return -ENOMEM;
+	}
+
+	mutex_init(&dev->mutex);
+	atomic_set(&dev->wake_thread, 0);
+
+	lis3lv02d_add_fs(dev);
+	lis3lv02d_poweron(dev);
+
+	if (dev->pm_dev) {
+		pm_runtime_set_active(dev->pm_dev);
+		pm_runtime_enable(dev->pm_dev);
+	}
+
+	if (lis3lv02d_joystick_enable())
+		pr_err("joystick initialization failed\n");
+
+	/* 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 (dev->whoami == WAI_8B)
+			lis3lv02d_8b_configure(dev, p);
+
+		irq_flags = p->irq_flags1 & IRQF_TRIGGER_MASK;
+
+		dev->irq_cfg = p->irq_cfg;
+		if (p->irq_cfg)
+			dev->write(dev, CTRL_REG3, p->irq_cfg);
+
+		if (p->default_rate)
+			lis3lv02d_set_odr(p->default_rate);
+	}
+
+	/* bail if we did not get an IRQ from the bus layer */
+	if (!dev->irq) {
+		pr_debug("No IRQ. Disabling /dev/freefall\n");
+		goto out;
+	}
+
+	/*
+	 * The sensor can generate interrupts for free-fall and direction
+	 * detection (distinguishable with FF_WU_SRC and DD_SRC) but to keep
+	 * the things simple and _fast_ we activate it only for free-fall, so
+	 * no need to read register (very slow with ACPI). For the same reason,
+	 * we forbid shared interrupts.
+	 *
+	 * IRQF_TRIGGER_RISING seems pointless on HP laptops because the
+	 * io-apic is not configurable (and generates a warning) but I keep it
+	 * in case of support for other hardware.
+	 */
+	if (dev->pdata && dev->whoami == WAI_8B)
+		thread_fn = lis302dl_interrupt_thread1_8b;
+	else
+		thread_fn = NULL;
+
+	err = request_threaded_irq(dev->irq, lis302dl_interrupt,
+				thread_fn,
+				IRQF_TRIGGER_RISING | IRQF_ONESHOT |
+				irq_flags,
+				DRIVER_NAME, &lis3_dev);
+
+	if (err < 0) {
+		pr_err("Cannot get IRQ\n");
+		goto out;
+	}
+
+	if (misc_register(&lis3lv02d_misc_device))
+		pr_err("misc_register failed\n");
+out:
+	return 0;
+}
+EXPORT_SYMBOL_GPL(lis3lv02d_init_device);
+
+MODULE_DESCRIPTION("ST LIS3LV02Dx three-axis digital accelerometer driver");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d.h linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d.h
--- linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,291 @@
+/*
+ *  lis3lv02d.h - ST LIS3LV02DL accelerometer driver
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008-2009 Eric Piel
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/input-polldev.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * This driver tries to support the "digital" accelerometer chips from
+ * STMicroelectronics such as LIS3LV02DL, LIS302DL, LIS3L02DQ, LIS331DL,
+ * LIS35DE, or LIS202DL. They are very similar in terms of programming, with
+ * almost the same registers. In addition to differing on physical properties,
+ * they differ on the number of axes (2/3), precision (8/12 bits), and special
+ * features (freefall detection, click...). Unfortunately, not all the
+ * differences can be probed via a register.
+ * They can be connected either via IÂ²C or SPI.
+ */
+
+#include <linux/lis3lv02d.h>
+
+enum lis3_reg {
+	WHO_AM_I	= 0x0F,
+	OFFSET_X	= 0x16,
+	OFFSET_Y	= 0x17,
+	OFFSET_Z	= 0x18,
+	GAIN_X		= 0x19,
+	GAIN_Y		= 0x1A,
+	GAIN_Z		= 0x1B,
+	CTRL_REG1	= 0x20,
+	CTRL_REG2	= 0x21,
+	CTRL_REG3	= 0x22,
+	CTRL_REG4	= 0x23,
+	HP_FILTER_RESET	= 0x23,
+	STATUS_REG	= 0x27,
+	OUTX_L		= 0x28,
+	OUTX_H		= 0x29,
+	OUTX		= 0x29,
+	OUTY_L		= 0x2A,
+	OUTY_H		= 0x2B,
+	OUTY		= 0x2B,
+	OUTZ_L		= 0x2C,
+	OUTZ_H		= 0x2D,
+	OUTZ		= 0x2D,
+};
+
+enum lis302d_reg {
+	FF_WU_CFG_1	= 0x30,
+	FF_WU_SRC_1	= 0x31,
+	FF_WU_THS_1	= 0x32,
+	FF_WU_DURATION_1 = 0x33,
+	FF_WU_CFG_2	= 0x34,
+	FF_WU_SRC_2	= 0x35,
+	FF_WU_THS_2	= 0x36,
+	FF_WU_DURATION_2 = 0x37,
+	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 {
+	FF_WU_CFG	= 0x30,
+	FF_WU_SRC	= 0x31,
+	FF_WU_ACK	= 0x32,
+	FF_WU_THS_L	= 0x34,
+	FF_WU_THS_H	= 0x35,
+	FF_WU_DURATION	= 0x36,
+	DD_CFG		= 0x38,
+	DD_SRC		= 0x39,
+	DD_ACK		= 0x3A,
+	DD_THSI_L	= 0x3C,
+	DD_THSI_H	= 0x3D,
+	DD_THSE_L	= 0x3E,
+	DD_THSE_H	= 0x3F,
+};
+
+enum lis3_who_am_i {
+	WAI_3DC		= 0x33,	/* 8 bits: LIS3DC, HP3DC */
+	WAI_12B		= 0x3A, /* 12 bits: LIS3LV02D[LQ]... */
+	WAI_8B		= 0x3B, /* 8 bits: LIS[23]02D[LQ]... */
+	WAI_6B		= 0x52, /* 6 bits: LIS331DLF - not supported */
+};
+
+enum lis3lv02d_ctrl1_12b {
+	CTRL1_Xen	= 0x01,
+	CTRL1_Yen	= 0x02,
+	CTRL1_Zen	= 0x04,
+	CTRL1_ST	= 0x08,
+	CTRL1_DF0	= 0x10,
+	CTRL1_DF1	= 0x20,
+	CTRL1_PD0	= 0x40,
+	CTRL1_PD1	= 0x80,
+};
+
+/* Delta to ctrl1_12b version */
+enum lis3lv02d_ctrl1_8b {
+	CTRL1_STM	= 0x08,
+	CTRL1_STP	= 0x10,
+	CTRL1_FS	= 0x20,
+	CTRL1_PD	= 0x40,
+	CTRL1_DR	= 0x80,
+};
+
+enum lis3lv02d_ctrl1_3dc {
+	CTRL1_ODR0	= 0x10,
+	CTRL1_ODR1	= 0x20,
+	CTRL1_ODR2	= 0x40,
+	CTRL1_ODR3	= 0x80,
+};
+
+enum lis3lv02d_ctrl2 {
+	CTRL2_DAS	= 0x01,
+	CTRL2_SIM	= 0x02,
+	CTRL2_DRDY	= 0x04,
+	CTRL2_IEN	= 0x08,
+	CTRL2_BOOT	= 0x10,
+	CTRL2_BLE	= 0x20,
+	CTRL2_BDU	= 0x40, /* Block Data Update */
+	CTRL2_FS	= 0x80, /* Full Scale selection */
+};
+
+enum lis3lv02d_ctrl4_3dc {
+	CTRL4_SIM	= 0x01,
+	CTRL4_ST0	= 0x02,
+	CTRL4_ST1	= 0x04,
+	CTRL4_FS0	= 0x10,
+	CTRL4_FS1	= 0x20,
+};
+
+enum lis302d_ctrl2 {
+	HP_FF_WU2	= 0x08,
+	HP_FF_WU1	= 0x04,
+	CTRL2_BOOT_8B   = 0x40,
+};
+
+enum lis3lv02d_ctrl3 {
+	CTRL3_CFS0	= 0x01,
+	CTRL3_CFS1	= 0x02,
+	CTRL3_FDS	= 0x10,
+	CTRL3_HPFF	= 0x20,
+	CTRL3_HPDD	= 0x40,
+	CTRL3_ECK	= 0x80,
+};
+
+enum lis3lv02d_status_reg {
+	STATUS_XDA	= 0x01,
+	STATUS_YDA	= 0x02,
+	STATUS_ZDA	= 0x04,
+	STATUS_XYZDA	= 0x08,
+	STATUS_XOR	= 0x10,
+	STATUS_YOR	= 0x20,
+	STATUS_ZOR	= 0x40,
+	STATUS_XYZOR	= 0x80,
+};
+
+enum lis3lv02d_ff_wu_cfg {
+	FF_WU_CFG_XLIE	= 0x01,
+	FF_WU_CFG_XHIE	= 0x02,
+	FF_WU_CFG_YLIE	= 0x04,
+	FF_WU_CFG_YHIE	= 0x08,
+	FF_WU_CFG_ZLIE	= 0x10,
+	FF_WU_CFG_ZHIE	= 0x20,
+	FF_WU_CFG_LIR	= 0x40,
+	FF_WU_CFG_AOI	= 0x80,
+};
+
+enum lis3lv02d_ff_wu_src {
+	FF_WU_SRC_XL	= 0x01,
+	FF_WU_SRC_XH	= 0x02,
+	FF_WU_SRC_YL	= 0x04,
+	FF_WU_SRC_YH	= 0x08,
+	FF_WU_SRC_ZL	= 0x10,
+	FF_WU_SRC_ZH	= 0x20,
+	FF_WU_SRC_IA	= 0x40,
+};
+
+enum lis3lv02d_dd_cfg {
+	DD_CFG_XLIE	= 0x01,
+	DD_CFG_XHIE	= 0x02,
+	DD_CFG_YLIE	= 0x04,
+	DD_CFG_YHIE	= 0x08,
+	DD_CFG_ZLIE	= 0x10,
+	DD_CFG_ZHIE	= 0x20,
+	DD_CFG_LIR	= 0x40,
+	DD_CFG_IEND	= 0x80,
+};
+
+enum lis3lv02d_dd_src {
+	DD_SRC_XL	= 0x01,
+	DD_SRC_XH	= 0x02,
+	DD_SRC_YL	= 0x04,
+	DD_SRC_YH	= 0x08,
+	DD_SRC_ZL	= 0x10,
+	DD_SRC_ZH	= 0x20,
+	DD_SRC_IA	= 0x40,
+};
+
+enum lis3lv02d_click_src_8b {
+	CLICK_SINGLE_X	= 0x01,
+	CLICK_DOUBLE_X	= 0x02,
+	CLICK_SINGLE_Y	= 0x04,
+	CLICK_DOUBLE_Y	= 0x08,
+	CLICK_SINGLE_Z	= 0x10,
+	CLICK_DOUBLE_Z	= 0x20,
+	CLICK_IA	= 0x40,
+};
+
+enum lis3lv02d_reg_state {
+	LIS3_REG_OFF	= 0x00,
+	LIS3_REG_ON	= 0x01,
+};
+
+union axis_conversion {
+	struct {
+		int x, y, z;
+	};
+	int as_array[3];
+
+};
+
+struct lis3lv02d {
+	void			*bus_priv; /* used by the bus layer only */
+	struct device		*pm_dev; /* for pm_runtime purposes */
+	int (*init) (struct lis3lv02d *lis3);
+	int (*write) (struct lis3lv02d *lis3, int reg, u8 val);
+	int (*read) (struct lis3lv02d *lis3, int reg, u8 *ret);
+	int (*blkread) (struct lis3lv02d *lis3, int reg, int len, u8 *ret);
+	int (*reg_ctrl) (struct lis3lv02d *lis3, bool state);
+
+	int                     *odrs;     /* Supported output data rates */
+	u8			*regs;	   /* Regs to store / restore */
+	int			regs_size;
+	u8                      *reg_cache;
+	bool			regs_stored;
+	u8                      odr_mask;  /* ODR bit mask */
+	u8			whoami;    /* indicates measurement precision */
+	s16 (*read_data) (struct lis3lv02d *lis3, int reg);
+	int			mdps_max_val;
+	int			pwron_delay;
+	int                     scale; /*
+					* relationship between 1 LBS and mG
+					* (1/1000th of earth gravity)
+					*/
+
+	struct input_polled_dev	*idev;     /* input device */
+	struct platform_device	*pdev;     /* platform device */
+	struct regulator_bulk_data regulators[2];
+	atomic_t		count;     /* interrupt count after last read */
+	union axis_conversion	ac;        /* hw -> logical axis */
+	int			mapped_btns[3];
+
+	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 */
+	int                     data_ready_count[2];
+	atomic_t		wake_thread;
+	unsigned char           irq_cfg;
+
+	struct lis3lv02d_platform_data *pdata;	/* for passing board config */
+	struct mutex		mutex;     /* Serialize poll and selftest */
+};
+
+int lis3lv02d_init_device(struct lis3lv02d *lis3);
+int lis3lv02d_joystick_enable(void);
+void lis3lv02d_joystick_disable(void);
+void lis3lv02d_poweroff(struct lis3lv02d *lis3);
+void lis3lv02d_poweron(struct lis3lv02d *lis3);
+int lis3lv02d_remove_fs(struct lis3lv02d *lis3);
+
+extern struct lis3lv02d lis3_dev;
diff -druN linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c
--- linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,279 @@
+/*
+ * drivers/hwmon/lis3lv02d_i2c.c
+ *
+ * Implements I2C interface for lis3lv02d (STMicroelectronics) accelerometer.
+ * Driver is based on corresponding SPI driver written by Daniel Mack
+ * (lis3lv02d_spi.c (C) 2009 Daniel Mack <daniel@caiaq.de> ).
+ *
+ * Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+ *
+ * Contact: Samu Onkalo <samu.p.onkalo@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
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/pm_runtime.h>
+#include <linux/delay.h>
+#include "lis3lv02d.h"
+
+#define DRV_NAME	"lis3lv02d_i2c"
+
+static const char reg_vdd[]    = "Vdd";
+static const char reg_vdd_io[] = "Vdd_IO";
+
+static int lis3_reg_ctrl(struct lis3lv02d *lis3, bool state)
+{
+	int ret;
+	if (state == LIS3_REG_OFF) {
+		ret = regulator_bulk_disable(ARRAY_SIZE(lis3->regulators),
+					lis3->regulators);
+	} else {
+		ret = regulator_bulk_enable(ARRAY_SIZE(lis3->regulators),
+					lis3->regulators);
+		/* Chip needs time to wakeup. Not mentioned in datasheet */
+		usleep_range(10000, 20000);
+	}
+	return ret;
+}
+
+static inline s32 lis3_i2c_write(struct lis3lv02d *lis3, int reg, u8 value)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	return i2c_smbus_write_byte_data(c, reg, value);
+}
+
+static inline s32 lis3_i2c_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	*v = i2c_smbus_read_byte_data(c, reg);
+	return 0;
+}
+
+static inline s32 lis3_i2c_blockread(struct lis3lv02d *lis3, int reg, int len,
+				u8 *v)
+{
+	struct i2c_client *c = lis3->bus_priv;
+	reg |= (1 << 7); /* 7th bit enables address auto incrementation */
+	return i2c_smbus_read_i2c_block_data(c, reg, len, v);
+}
+
+static int lis3_i2c_init(struct lis3lv02d *lis3)
+{
+	u8 reg;
+	int ret;
+
+	if (lis3->reg_ctrl)
+		lis3_reg_ctrl(lis3, LIS3_REG_ON);
+
+	lis3->read(lis3, WHO_AM_I, &reg);
+	if (reg != lis3->whoami)
+		printk(KERN_ERR "lis3: power on failure\n");
+
+	/* power up the device */
+	ret = lis3->read(lis3, CTRL_REG1, &reg);
+	if (ret < 0)
+		return ret;
+
+	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
+	return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+/* Default axis mapping but it can be overwritten by platform data */
+static union axis_conversion lis3lv02d_axis_map =
+	{ .as_array = { LIS3_DEV_X, LIS3_DEV_Y, LIS3_DEV_Z } };
+
+static int __devinit lis3lv02d_i2c_probe(struct i2c_client *client,
+					const struct i2c_device_id *id)
+{
+	int ret = 0;
+	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata) {
+		/* Regulator control is optional */
+		if (pdata->driver_features & LIS3_USE_REGULATOR_CTRL)
+			lis3_dev.reg_ctrl = lis3_reg_ctrl;
+
+		if ((pdata->driver_features & LIS3_USE_BLOCK_READ) &&
+			(i2c_check_functionality(client->adapter,
+						I2C_FUNC_SMBUS_I2C_BLOCK)))
+			lis3_dev.blkread  = lis3_i2c_blockread;
+
+		if (pdata->axis_x)
+			lis3lv02d_axis_map.x = pdata->axis_x;
+
+		if (pdata->axis_y)
+			lis3lv02d_axis_map.y = pdata->axis_y;
+
+		if (pdata->axis_z)
+			lis3lv02d_axis_map.z = pdata->axis_z;
+
+		if (pdata->setup_resources)
+			ret = pdata->setup_resources();
+
+		if (ret)
+			goto fail;
+	}
+
+	if (lis3_dev.reg_ctrl) {
+		lis3_dev.regulators[0].supply = reg_vdd;
+		lis3_dev.regulators[1].supply = reg_vdd_io;
+		ret = regulator_bulk_get(&client->dev,
+					ARRAY_SIZE(lis3_dev.regulators),
+					lis3_dev.regulators);
+		if (ret < 0)
+			goto fail;
+	}
+
+	lis3_dev.pdata	  = pdata;
+	lis3_dev.bus_priv = client;
+	lis3_dev.init	  = lis3_i2c_init;
+	lis3_dev.read	  = lis3_i2c_read;
+	lis3_dev.write	  = lis3_i2c_write;
+	lis3_dev.irq	  = client->irq;
+	lis3_dev.ac	  = lis3lv02d_axis_map;
+	lis3_dev.pm_dev	  = &client->dev;
+
+	i2c_set_clientdata(client, &lis3_dev);
+
+	/* Provide power over the init call */
+	if (lis3_dev.reg_ctrl)
+		lis3_reg_ctrl(&lis3_dev, LIS3_REG_ON);
+
+	ret = lis3lv02d_init_device(&lis3_dev);
+
+	if (lis3_dev.reg_ctrl)
+		lis3_reg_ctrl(&lis3_dev, LIS3_REG_OFF);
+
+	if (ret == 0)
+		return 0;
+fail:
+	if (pdata && pdata->release_resources)
+		pdata->release_resources();
+	return ret;
+}
+
+static int __devexit lis3lv02d_i2c_remove(struct i2c_client *client)
+{
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+	struct lis3lv02d_platform_data *pdata = client->dev.platform_data;
+
+	if (pdata && pdata->release_resources)
+		pdata->release_resources();
+
+	lis3lv02d_joystick_disable();
+	lis3lv02d_remove_fs(&lis3_dev);
+
+	if (lis3_dev.reg_ctrl)
+		regulator_bulk_free(ARRAY_SIZE(lis3->regulators),
+				lis3_dev.regulators);
+	return 0;
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lis3lv02d_i2c_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+		lis3lv02d_poweroff(lis3);
+	return 0;
+}
+
+static int lis3lv02d_i2c_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	/*
+	 * pm_runtime documentation says that devices should always
+	 * be powered on at resume. Pm_runtime turns them off after system
+	 * wide resume is complete.
+	 */
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags ||
+		pm_runtime_suspended(dev))
+		lis3lv02d_poweron(lis3);
+
+	return 0;
+}
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM_RUNTIME
+static int lis3_i2c_runtime_suspend(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	lis3lv02d_poweroff(lis3);
+	return 0;
+}
+
+static int lis3_i2c_runtime_resume(struct device *dev)
+{
+	struct i2c_client *client = container_of(dev, struct i2c_client, dev);
+	struct lis3lv02d *lis3 = i2c_get_clientdata(client);
+
+	lis3lv02d_poweron(lis3);
+	return 0;
+}
+#endif /* CONFIG_PM_RUNTIME */
+
+static const struct i2c_device_id lis3lv02d_id[] = {
+	{"lis3lv02d", 0 },
+	{}
+};
+
+MODULE_DEVICE_TABLE(i2c, lis3lv02d_id);
+
+static const struct dev_pm_ops lis3_pm_ops = {
+	SET_SYSTEM_SLEEP_PM_OPS(lis3lv02d_i2c_suspend,
+				lis3lv02d_i2c_resume)
+	SET_RUNTIME_PM_OPS(lis3_i2c_runtime_suspend,
+			   lis3_i2c_runtime_resume,
+			   NULL)
+};
+
+static struct i2c_driver lis3lv02d_i2c_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+		.pm     = &lis3_pm_ops,
+	},
+	.probe	= lis3lv02d_i2c_probe,
+	.remove	= __devexit_p(lis3lv02d_i2c_remove),
+	.id_table = lis3lv02d_id,
+};
+
+static int __init lis3lv02d_init(void)
+{
+	return i2c_add_driver(&lis3lv02d_i2c_driver);
+}
+
+static void __exit lis3lv02d_exit(void)
+{
+	i2c_del_driver(&lis3lv02d_i2c_driver);
+}
+
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_DESCRIPTION("lis3lv02d I2C interface");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init);
+module_exit(lis3lv02d_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c
--- linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/lis3lv02d_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,145 @@
+/*
+ * lis3lv02d_spi - SPI glue layer for lis3lv02d
+ *
+ * Copyright (c) 2009 Daniel Mack <daniel@caiaq.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
+ *  publishhed by the Free Software Foundation.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/input.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/spi/spi.h>
+#include <linux/pm.h>
+
+#include "lis3lv02d.h"
+
+#define DRV_NAME 	"lis3lv02d_spi"
+#define LIS3_SPI_READ	0x80
+
+static int lis3_spi_read(struct lis3lv02d *lis3, int reg, u8 *v)
+{
+	struct spi_device *spi = lis3->bus_priv;
+	int ret = spi_w8r8(spi, reg | LIS3_SPI_READ);
+	if (ret < 0)
+		return -EINVAL;
+
+	*v = (u8) ret;
+	return 0;
+}
+
+static int lis3_spi_write(struct lis3lv02d *lis3, int reg, u8 val)
+{
+	u8 tmp[2] = { reg, val };
+	struct spi_device *spi = lis3->bus_priv;
+	return spi_write(spi, tmp, sizeof(tmp));
+}
+
+static int lis3_spi_init(struct lis3lv02d *lis3)
+{
+	u8 reg;
+	int ret;
+
+	/* power up the device */
+	ret = lis3->read(lis3, CTRL_REG1, &reg);
+	if (ret < 0)
+		return ret;
+
+	reg |= CTRL1_PD0 | CTRL1_Xen | CTRL1_Yen | CTRL1_Zen;
+	return lis3->write(lis3, CTRL_REG1, reg);
+}
+
+static union axis_conversion lis3lv02d_axis_normal =
+	{ .as_array = { 1, 2, 3 } };
+
+static int __devinit lis302dl_spi_probe(struct spi_device *spi)
+{
+	int ret;
+
+	spi->bits_per_word = 8;
+	spi->mode = SPI_MODE_0;
+	ret = spi_setup(spi);
+	if (ret < 0)
+		return ret;
+
+	lis3_dev.bus_priv	= spi;
+	lis3_dev.init		= lis3_spi_init;
+	lis3_dev.read		= lis3_spi_read;
+	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);
+
+	return lis3lv02d_init_device(&lis3_dev);
+}
+
+static int __devexit lis302dl_spi_remove(struct spi_device *spi)
+{
+	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+	lis3lv02d_joystick_disable();
+	lis3lv02d_poweroff(lis3);
+
+	return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int lis3lv02d_spi_suspend(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+		lis3lv02d_poweroff(&lis3_dev);
+
+	return 0;
+}
+
+static int lis3lv02d_spi_resume(struct device *dev)
+{
+	struct spi_device *spi = to_spi_device(dev);
+	struct lis3lv02d *lis3 = spi_get_drvdata(spi);
+
+	if (!lis3->pdata || !lis3->pdata->wakeup_flags)
+		lis3lv02d_poweron(lis3);
+
+	return 0;
+}
+#endif
+
+static SIMPLE_DEV_PM_OPS(lis3lv02d_spi_pm, lis3lv02d_spi_suspend,
+			 lis3lv02d_spi_resume);
+
+static struct spi_driver lis302dl_spi_driver = {
+	.driver	 = {
+		.name   = DRV_NAME,
+		.owner  = THIS_MODULE,
+		.pm	= &lis3lv02d_spi_pm,
+	},
+	.probe	= lis302dl_spi_probe,
+	.remove	= __devexit_p(lis302dl_spi_remove),
+};
+
+static int __init lis302dl_init(void)
+{
+	return spi_register_driver(&lis302dl_spi_driver);
+}
+
+static void __exit lis302dl_exit(void)
+{
+	spi_unregister_driver(&lis302dl_spi_driver);
+}
+
+module_init(lis302dl_init);
+module_exit(lis302dl_exit);
+
+MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
+MODULE_DESCRIPTION("lis3lv02d SPI glue layer");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("spi:" DRV_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/Makefile linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/Makefile
--- linux-libre-2.6.38-gnu/drivers/misc/lis3lv02d/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/lis3lv02d/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,7 @@
+#
+# STMicroelectonics LIS3LV02D and similar accelerometers
+#
+
+obj-$(CONFIG_SENSORS_LIS3LV02D) += lis3lv02d.o
+obj-$(CONFIG_SENSORS_LIS3_SPI)	+= lis3lv02d_spi.o
+obj-$(CONFIG_SENSORS_LIS3_I2C)	+= lis3lv02d_i2c.o
diff -druN linux-libre-2.6.38-gnu/drivers/misc/Makefile linux-libre-2.6.39-gnu/drivers/misc/Makefile
--- linux-libre-2.6.38-gnu/drivers/misc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -37,8 +37,10 @@
 obj-$(CONFIG_HMC6352)		+= hmc6352.o
 obj-y				+= eeprom/
 obj-y				+= cb710/
+obj-$(CONFIG_SPEAR13XX_PCIE_GADGET)	+= spear13xx_pcie_gadget.o
 obj-$(CONFIG_VMWARE_BALLOON)	+= vmw_balloon.o
 obj-$(CONFIG_ARM_CHARLCD)	+= arm-charlcd.o
 obj-$(CONFIG_PCH_PHUB)		+= pch_phub.o
 obj-y				+= ti-st/
 obj-$(CONFIG_AB8500_PWM)	+= ab8500-pwm.o
+obj-y				+= lis3lv02d/
diff -druN linux-libre-2.6.38-gnu/drivers/misc/pch_phub.c linux-libre-2.6.39-gnu/drivers/misc/pch_phub.c
--- linux-libre-2.6.38-gnu/drivers/misc/pch_phub.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/pch_phub.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2010 OKI SEMICONDUCTOR Co., LTD.
+ * Copyright (C) 2010 OKI SEMICONDUCTOR CO., 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
@@ -27,13 +27,19 @@
 #include <linux/mutex.h>
 #include <linux/if_ether.h>
 #include <linux/ctype.h>
+#include <linux/dmi.h>
 
 #define PHUB_STATUS 0x00		/* Status Register offset */
 #define PHUB_CONTROL 0x04		/* Control Register offset */
 #define PHUB_TIMEOUT 0x05		/* Time out value for Status Register */
 #define PCH_PHUB_ROM_WRITE_ENABLE 0x01	/* Enabling for writing ROM */
 #define PCH_PHUB_ROM_WRITE_DISABLE 0x00	/* Disabling for writing ROM */
-#define PCH_PHUB_ROM_START_ADDR 0x14	/* ROM data area start address offset */
+#define PCH_PHUB_MAC_START_ADDR 0x20C  /* MAC data area start address offset */
+#define PCH_PHUB_ROM_START_ADDR_EG20T 0x14 /* ROM data area start address offset
+					      (Intel EG20T PCH)*/
+#define PCH_PHUB_ROM_START_ADDR_ML7213 0x400 /* ROM data area start address
+						offset(OKI SEMICONDUCTOR ML7213)
+					      */
 
 /* MAX number of INT_REDUCE_CONTROL registers */
 #define MAX_NUM_INT_REDUCE_CONTROL_REG 128
@@ -41,6 +47,21 @@
 #define PCH_MINOR_NOS 1
 #define CLKCFG_CAN_50MHZ 0x12000000
 #define CLKCFG_CANCLK_MASK 0xFF000000
+#define CLKCFG_UART_MASK			0xFFFFFF
+
+/* CM-iTC */
+#define CLKCFG_UART_48MHZ			(1 << 16)
+#define CLKCFG_BAUDDIV				(2 << 20)
+#define CLKCFG_PLL2VCO				(8 << 9)
+#define CLKCFG_UARTCLKSEL			(1 << 18)
+
+/* Macros for ML7213 */
+#define PCI_VENDOR_ID_ROHM			0x10db
+#define PCI_DEVICE_ID_ROHM_ML7213_PHUB		0x801A
+
+/* Macros for ML7213 */
+#define PCI_VENDOR_ID_ROHM			0x10db
+#define PCI_DEVICE_ID_ROHM_ML7213_PHUB		0x801A
 
 /* SROM ACCESS Macro */
 #define PCH_WORD_ADDR_MASK (~((1 << 2) - 1))
@@ -298,7 +319,7 @@
 {
 	unsigned int mem_addr;
 
-	mem_addr = PCH_PHUB_ROM_START_ADDR +
+	mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T +
 			pch_phub_mac_offset[offset_address];
 
 	pch_phub_read_serial_rom(chip, mem_addr, data);
@@ -315,7 +336,7 @@
 	int retval;
 	unsigned int mem_addr;
 
-	mem_addr = PCH_PHUB_ROM_START_ADDR +
+	mem_addr = PCH_PHUB_ROM_START_ADDR_EG20T +
 			pch_phub_mac_offset[offset_address];
 
 	retval = pch_phub_write_serial_rom(chip, mem_addr, data);
@@ -594,23 +615,46 @@
 		"pch_phub_extrom_base_address variable is %p\n", __func__,
 		chip->pch_phub_extrom_base_address);
 
-	pci_set_drvdata(pdev, chip);
+	if (id->driver_data == 1) {
+		retval = sysfs_create_file(&pdev->dev.kobj,
+					   &dev_attr_pch_mac.attr);
+		if (retval)
+			goto err_sysfs_create;
 
-	retval = sysfs_create_file(&pdev->dev.kobj, &dev_attr_pch_mac.attr);
-	if (retval)
-		goto err_sysfs_create;
+		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (retval)
+			goto exit_bin_attr;
 
-	retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
-	if (retval)
-		goto exit_bin_attr;
+		pch_phub_read_modify_write_reg(chip,
+					       (unsigned int)CLKCFG_REG_OFFSET,
+					       CLKCFG_CAN_50MHZ,
+					       CLKCFG_CANCLK_MASK);
 
-	pch_phub_read_modify_write_reg(chip, (unsigned int)CLKCFG_REG_OFFSET,
-					CLKCFG_CAN_50MHZ, CLKCFG_CANCLK_MASK);
+		/* quirk for CM-iTC board */
+		if (strstr(dmi_get_system_info(DMI_BOARD_NAME), "CM-iTC"))
+			pch_phub_read_modify_write_reg(chip,
+						(unsigned int)CLKCFG_REG_OFFSET,
+						CLKCFG_UART_48MHZ | CLKCFG_BAUDDIV |
+						CLKCFG_PLL2VCO | CLKCFG_UARTCLKSEL,
+						CLKCFG_UART_MASK);
 
-	/* set the prefech value */
-	iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
-	/* set the interrupt delay value */
-	iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+		/* set the prefech value */
+		iowrite32(0x000affaa, chip->pch_phub_base_address + 0x14);
+		/* set the interrupt delay value */
+		iowrite32(0x25, chip->pch_phub_base_address + 0x44);
+	} else if (id->driver_data == 2) {
+		retval = sysfs_create_bin_file(&pdev->dev.kobj, &pch_bin_attr);
+		if (retval)
+			goto err_sysfs_create;
+		/* set the prefech value
+		 * Device2(USB OHCI #1/ USB EHCI #1/ USB Device):a
+		 * Device4(SDIO #0,1,2):f
+		 * Device6(SATA 2):f
+		 * Device8(USB OHCI #0/ USB EHCI #0):a
+		 */
+		iowrite32(0x000affa0, chip->pch_phub_base_address + 0x14);
+	}
+	pci_set_drvdata(pdev, chip);
 
 	return 0;
 exit_bin_attr:
@@ -687,9 +731,11 @@
 #endif /* CONFIG_PM */
 
 static struct pci_device_id pch_phub_pcidev_id[] = {
-	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_PCH1_PHUB)},
-	{0,}
+	{ PCI_VDEVICE(INTEL, PCI_DEVICE_ID_PCH1_PHUB),       1,  },
+	{ PCI_VDEVICE(ROHM, PCI_DEVICE_ID_ROHM_ML7213_PHUB), 2,  },
+	{ }
 };
+MODULE_DEVICE_TABLE(pci, pch_phub_pcidev_id);
 
 static struct pci_driver pch_phub_driver = {
 	.name = "pch_phub",
diff -druN linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/grufile.c linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/grufile.c
--- linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/grufile.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/grufile.c	2011-05-19 00:06:34.000000000 -0400
@@ -348,15 +348,15 @@
 
 static int gru_irq_count[GRU_CHIPLETS_PER_BLADE];
 
-static void gru_noop(unsigned int irq)
+static void gru_noop(struct irq_data *d)
 {
 }
 
 static struct irq_chip gru_chip[GRU_CHIPLETS_PER_BLADE] = {
 	[0 ... GRU_CHIPLETS_PER_BLADE - 1] {
-		.mask		= gru_noop,
-		.unmask		= gru_noop,
-		.ack		= gru_noop
+		.irq_mask	= gru_noop,
+		.irq_unmask	= gru_noop,
+		.irq_ack	= gru_noop
 	}
 };
 
@@ -373,7 +373,7 @@
 
 	if (gru_irq_count[chiplet] == 0) {
 		gru_chip[chiplet].name = irq_name;
-		ret = set_irq_chip(irq, &gru_chip[chiplet]);
+		ret = irq_set_chip(irq, &gru_chip[chiplet]);
 		if (ret) {
 			printk(KERN_ERR "%s: set_irq_chip failed, errno=%d\n",
 			       GRU_DRIVER_ID_STR, -ret);
diff -druN linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/grukservices.c linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/grukservices.c
--- linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/grukservices.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/grukservices.c	2011-05-19 00:06:34.000000000 -0400
@@ -229,7 +229,7 @@
 	bid = blade_id < 0 ? uv_numa_blade_id() : blade_id;
 	bs = gru_base[bid];
 
-	/* Handle the case where migration occured while waiting for the sema */
+	/* Handle the case where migration occurred while waiting for the sema */
 	down_read(&bs->bs_kgts_sema);
 	if (blade_id < 0 && bid != uv_numa_blade_id()) {
 		up_read(&bs->bs_kgts_sema);
diff -druN linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/grutables.h linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/grutables.h
--- linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/grutables.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/grutables.h	2011-05-19 00:06:34.000000000 -0400
@@ -379,7 +379,7 @@
 						   required for contest */
 	char			ts_cch_req_slice;/* CCH packet slice */
 	char			ts_blade;	/* If >= 0, migrate context if
-						   ref from diferent blade */
+						   ref from different blade */
 	char			ts_force_cch_reload;
 	char			ts_cbr_idx[GRU_CBR_AU];/* CBR numbers of each
 							  allocated CB */
diff -druN linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/Makefile linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/Makefile
--- linux-libre-2.6.38-gnu/drivers/misc/sgi-gru/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/sgi-gru/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,4 @@
-ifdef CONFIG_SGI_GRU_DEBUG
-  EXTRA_CFLAGS	+= -DDEBUG
-endif
+ccflags-$(CONFIG_SGI_GRU_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_SGI_GRU) := gru.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.38-gnu/drivers/misc/spear13xx_pcie_gadget.c linux-libre-2.6.39-gnu/drivers/misc/spear13xx_pcie_gadget.c
--- linux-libre-2.6.38-gnu/drivers/misc/spear13xx_pcie_gadget.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/misc/spear13xx_pcie_gadget.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,908 @@
+/*
+ * drivers/misc/spear13xx_pcie_gadget.c
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Pratyush Anand<pratyush.anand@st.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/clk.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/interrupt.h>
+#include <linux/irq.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/pci_regs.h>
+#include <linux/configfs.h>
+#include <mach/pcie.h>
+#include <mach/misc_regs.h>
+
+#define IN0_MEM_SIZE	(200 * 1024 * 1024 - 1)
+/* In current implementation address translation is done using IN0 only.
+ * So IN1 start address and IN0 end address has been kept same
+*/
+#define IN1_MEM_SIZE	(0 * 1024 * 1024 - 1)
+#define IN_IO_SIZE	(20 * 1024 * 1024 - 1)
+#define IN_CFG0_SIZE	(12 * 1024 * 1024 - 1)
+#define IN_CFG1_SIZE	(12 * 1024 * 1024 - 1)
+#define IN_MSG_SIZE	(12 * 1024 * 1024 - 1)
+/* Keep default BAR size as 4K*/
+/* AORAM would be mapped by default*/
+#define INBOUND_ADDR_MASK	(SPEAR13XX_SYSRAM1_SIZE - 1)
+
+#define INT_TYPE_NO_INT	0
+#define INT_TYPE_INTX	1
+#define INT_TYPE_MSI	2
+struct spear_pcie_gadget_config {
+	void __iomem *base;
+	void __iomem *va_app_base;
+	void __iomem *va_dbi_base;
+	char int_type[10];
+	ulong requested_msi;
+	ulong configured_msi;
+	ulong bar0_size;
+	ulong bar0_rw_offset;
+	void __iomem *va_bar0_address;
+};
+
+struct pcie_gadget_target {
+	struct configfs_subsystem subsys;
+	struct spear_pcie_gadget_config config;
+};
+
+struct pcie_gadget_target_attr {
+	struct configfs_attribute	attr;
+	ssize_t		(*show)(struct spear_pcie_gadget_config *config,
+						char *buf);
+	ssize_t		(*store)(struct spear_pcie_gadget_config *config,
+						 const char *buf,
+						 size_t count);
+};
+
+static void enable_dbi_access(struct pcie_app_reg __iomem *app_reg)
+{
+	/* Enable DBI access */
+	writel(readl(&app_reg->slv_armisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) | (1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void disable_dbi_access(struct pcie_app_reg __iomem *app_reg)
+{
+	/* disable DBI access */
+	writel(readl(&app_reg->slv_armisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_armisc);
+	writel(readl(&app_reg->slv_awmisc) & ~(1 << AXI_OP_DBI_ACCESS_ID),
+			&app_reg->slv_awmisc);
+
+}
+
+static void spear_dbi_read_reg(struct spear_pcie_gadget_config *config,
+		int where, int size, u32 *val)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (ulong)config->va_dbi_base + (where & ~0x3);
+
+	*val = readl(va_address);
+
+	if (size == 1)
+		*val = (*val >> (8 * (where & 3))) & 0xff;
+	else if (size == 2)
+		*val = (*val >> (8 * (where & 3))) & 0xffff;
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+static void spear_dbi_write_reg(struct spear_pcie_gadget_config *config,
+		int where, int size, u32 val)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong va_address;
+
+	/* Enable DBI access */
+	enable_dbi_access(app_reg);
+
+	va_address = (ulong)config->va_dbi_base + (where & ~0x3);
+
+	if (size == 4)
+		writel(val, va_address);
+	else if (size == 2)
+		writew(val, va_address + (where & 2));
+	else if (size == 1)
+		writeb(val, va_address + (where & 3));
+
+	/* Disable DBI access */
+	disable_dbi_access(app_reg);
+}
+
+#define PCI_FIND_CAP_TTL	48
+
+static int pci_find_own_next_cap_ttl(struct spear_pcie_gadget_config *config,
+		u32 pos, int cap, int *ttl)
+{
+	u32 id;
+
+	while ((*ttl)--) {
+		spear_dbi_read_reg(config, pos, 1, &pos);
+		if (pos < 0x40)
+			break;
+		pos &= ~3;
+		spear_dbi_read_reg(config, pos + PCI_CAP_LIST_ID, 1, &id);
+		if (id == 0xff)
+			break;
+		if (id == cap)
+			return pos;
+		pos += PCI_CAP_LIST_NEXT;
+	}
+	return 0;
+}
+
+static int pci_find_own_next_cap(struct spear_pcie_gadget_config *config,
+			u32 pos, int cap)
+{
+	int ttl = PCI_FIND_CAP_TTL;
+
+	return pci_find_own_next_cap_ttl(config, pos, cap, &ttl);
+}
+
+static int pci_find_own_cap_start(struct spear_pcie_gadget_config *config,
+				u8 hdr_type)
+{
+	u32 status;
+
+	spear_dbi_read_reg(config, PCI_STATUS, 2, &status);
+	if (!(status & PCI_STATUS_CAP_LIST))
+		return 0;
+
+	switch (hdr_type) {
+	case PCI_HEADER_TYPE_NORMAL:
+	case PCI_HEADER_TYPE_BRIDGE:
+		return PCI_CAPABILITY_LIST;
+	case PCI_HEADER_TYPE_CARDBUS:
+		return PCI_CB_CAPABILITY_LIST;
+	default:
+		return 0;
+	}
+
+	return 0;
+}
+
+/*
+ * Tell if a device supports a given PCI capability.
+ * Returns the address of the requested capability structure within the
+ * device's PCI configuration space or 0 in case the device does not
+ * support it. Possible values for @cap:
+ *
+ * %PCI_CAP_ID_PM	Power Management
+ * %PCI_CAP_ID_AGP	Accelerated Graphics Port
+ * %PCI_CAP_ID_VPD	Vital Product Data
+ * %PCI_CAP_ID_SLOTID	Slot Identification
+ * %PCI_CAP_ID_MSI	Message Signalled Interrupts
+ * %PCI_CAP_ID_CHSWP	CompactPCI HotSwap
+ * %PCI_CAP_ID_PCIX	PCI-X
+ * %PCI_CAP_ID_EXP	PCI Express
+ */
+static int pci_find_own_capability(struct spear_pcie_gadget_config *config,
+		int cap)
+{
+	u32 pos;
+	u32 hdr_type;
+
+	spear_dbi_read_reg(config, PCI_HEADER_TYPE, 1, &hdr_type);
+
+	pos = pci_find_own_cap_start(config, hdr_type);
+	if (pos)
+		pos = pci_find_own_next_cap(config, pos, cap);
+
+	return pos;
+}
+
+static irqreturn_t spear_pcie_gadget_irq(int irq, void *dev_id)
+{
+	return 0;
+}
+
+/*
+ * configfs interfaces show/store functions
+ */
+static ssize_t pcie_gadget_show_link(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	if (readl(&app_reg->app_status_1) & ((u32)1 << XMLH_LINK_UP_ID))
+		return sprintf(buf, "UP");
+	else
+		return sprintf(buf, "DOWN");
+}
+
+static ssize_t pcie_gadget_store_link(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	if (sysfs_streq(buf, "UP"))
+		writel(readl(&app_reg->app_ctrl_0) | (1 << APP_LTSSM_ENABLE_ID),
+			&app_reg->app_ctrl_0);
+	else if (sysfs_streq(buf, "DOWN"))
+		writel(readl(&app_reg->app_ctrl_0)
+				& ~(1 << APP_LTSSM_ENABLE_ID),
+				&app_reg->app_ctrl_0);
+	else
+		return -EINVAL;
+	return count;
+}
+
+static ssize_t pcie_gadget_show_int_type(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	return sprintf(buf, "%s", config->int_type);
+}
+
+static ssize_t pcie_gadget_store_int_type(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	u32 cap, vec, flags;
+	ulong vector;
+
+	if (sysfs_streq(buf, "INTA"))
+		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+
+	else if (sysfs_streq(buf, "MSI")) {
+		vector = config->requested_msi;
+		vec = 0;
+		while (vector > 1) {
+			vector /= 2;
+			vec++;
+		}
+		spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 0);
+		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
+		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
+		flags &= ~PCI_MSI_FLAGS_QMASK;
+		flags |= vec << 1;
+		spear_dbi_write_reg(config, cap + PCI_MSI_FLAGS, 1, flags);
+	} else
+		return -EINVAL;
+
+	strcpy(config->int_type, buf);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_no_of_msi(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	u32 cap, vec, flags;
+	ulong vector;
+
+	if ((readl(&app_reg->msg_status) & (1 << CFG_MSI_EN_ID))
+			!= (1 << CFG_MSI_EN_ID))
+		vector = 0;
+	else {
+		cap = pci_find_own_capability(config, PCI_CAP_ID_MSI);
+		spear_dbi_read_reg(config, cap + PCI_MSI_FLAGS, 1, &flags);
+		flags &= ~PCI_MSI_FLAGS_QSIZE;
+		vec = flags >> 4;
+		vector = 1;
+		while (vec--)
+			vector *= 2;
+	}
+	config->configured_msi = vector;
+
+	return sprintf(buf, "%lu", vector);
+}
+
+static ssize_t pcie_gadget_store_no_of_msi(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	if (strict_strtoul(buf, 0, &config->requested_msi))
+		return -EINVAL;
+	if (config->requested_msi > 32)
+		config->requested_msi = 32;
+
+	return count;
+}
+
+static ssize_t pcie_gadget_store_inta(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong en;
+
+	if (strict_strtoul(buf, 0, &en))
+		return -EINVAL;
+
+	if (en)
+		writel(readl(&app_reg->app_ctrl_0) | (1 << SYS_INT_ID),
+				&app_reg->app_ctrl_0);
+	else
+		writel(readl(&app_reg->app_ctrl_0) & ~(1 << SYS_INT_ID),
+				&app_reg->app_ctrl_0);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_store_send_msi(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong vector;
+	u32 ven_msi;
+
+	if (strict_strtoul(buf, 0, &vector))
+		return -EINVAL;
+
+	if (!config->configured_msi)
+		return -EINVAL;
+
+	if (vector >= config->configured_msi)
+		return -EINVAL;
+
+	ven_msi = readl(&app_reg->ven_msi_1);
+	ven_msi &= ~VEN_MSI_FUN_NUM_MASK;
+	ven_msi |= 0 << VEN_MSI_FUN_NUM_ID;
+	ven_msi &= ~VEN_MSI_TC_MASK;
+	ven_msi |= 0 << VEN_MSI_TC_ID;
+	ven_msi &= ~VEN_MSI_VECTOR_MASK;
+	ven_msi |= vector << VEN_MSI_VECTOR_ID;
+
+	/* generating interrupt for msi vector */
+	ven_msi |= VEN_MSI_REQ_EN;
+	writel(ven_msi, &app_reg->ven_msi_1);
+	udelay(1);
+	ven_msi &= ~VEN_MSI_REQ_EN;
+	writel(ven_msi, &app_reg->ven_msi_1);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_vendor_id(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	u32 id;
+
+	spear_dbi_read_reg(config, PCI_VENDOR_ID, 2, &id);
+
+	return sprintf(buf, "%x", id);
+}
+
+static ssize_t pcie_gadget_store_vendor_id(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong id;
+
+	if (strict_strtoul(buf, 0, &id))
+		return -EINVAL;
+
+	spear_dbi_write_reg(config, PCI_VENDOR_ID, 2, id);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_device_id(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	u32 id;
+
+	spear_dbi_read_reg(config, PCI_DEVICE_ID, 2, &id);
+
+	return sprintf(buf, "%x", id);
+}
+
+static ssize_t pcie_gadget_store_device_id(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong id;
+
+	if (strict_strtoul(buf, 0, &id))
+		return -EINVAL;
+
+	spear_dbi_write_reg(config, PCI_DEVICE_ID, 2, id);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_size(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	return sprintf(buf, "%lx", config->bar0_size);
+}
+
+static ssize_t pcie_gadget_store_bar0_size(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong size;
+	u32 pos, pos1;
+	u32 no_of_bit = 0;
+
+	if (strict_strtoul(buf, 0, &size))
+		return -EINVAL;
+	/* min bar size is 256 */
+	if (size <= 0x100)
+		size = 0x100;
+	/* max bar size is 1MB*/
+	else if (size >= 0x100000)
+		size = 0x100000;
+	else {
+		pos = 0;
+		pos1 = 0;
+		while (pos < 21) {
+			pos = find_next_bit((ulong *)&size, 21, pos);
+			if (pos != 21)
+				pos1 = pos + 1;
+			pos++;
+			no_of_bit++;
+		}
+		if (no_of_bit == 2)
+			pos1--;
+
+		size = 1 << pos1;
+	}
+	config->bar0_size = size;
+	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, size - 1);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_address(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	u32 address = readl(&app_reg->pim0_mem_addr_start);
+
+	return sprintf(buf, "%x", address);
+}
+
+static ssize_t pcie_gadget_store_bar0_address(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+	ulong address;
+
+	if (strict_strtoul(buf, 0, &address))
+		return -EINVAL;
+
+	address &= ~(config->bar0_size - 1);
+	if (config->va_bar0_address)
+		iounmap(config->va_bar0_address);
+	config->va_bar0_address = ioremap(address, config->bar0_size);
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	writel(address, &app_reg->pim0_mem_addr_start);
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_rw_offset(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	return sprintf(buf, "%lx", config->bar0_rw_offset);
+}
+
+static ssize_t pcie_gadget_store_bar0_rw_offset(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong offset;
+
+	if (strict_strtoul(buf, 0, &offset))
+		return -EINVAL;
+
+	if (offset % 4)
+		return -EINVAL;
+
+	config->bar0_rw_offset = offset;
+
+	return count;
+}
+
+static ssize_t pcie_gadget_show_bar0_data(
+		struct spear_pcie_gadget_config *config,
+		char *buf)
+{
+	ulong data;
+
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	data = readl((ulong)config->va_bar0_address + config->bar0_rw_offset);
+
+	return sprintf(buf, "%lx", data);
+}
+
+static ssize_t pcie_gadget_store_bar0_data(
+		struct spear_pcie_gadget_config *config,
+		const char *buf, size_t count)
+{
+	ulong data;
+
+	if (strict_strtoul(buf, 0, &data))
+		return -EINVAL;
+
+	if (!config->va_bar0_address)
+		return -ENOMEM;
+
+	writel(data, (ulong)config->va_bar0_address + config->bar0_rw_offset);
+
+	return count;
+}
+
+/*
+ * Attribute definitions.
+ */
+
+#define PCIE_GADGET_TARGET_ATTR_RO(_name)				\
+static struct pcie_gadget_target_attr pcie_gadget_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IRUGO, pcie_gadget_show_##_name, NULL)
+
+#define PCIE_GADGET_TARGET_ATTR_WO(_name)				\
+static struct pcie_gadget_target_attr pcie_gadget_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IWUSR, NULL, pcie_gadget_store_##_name)
+
+#define PCIE_GADGET_TARGET_ATTR_RW(_name)				\
+static struct pcie_gadget_target_attr pcie_gadget_target_##_name =	\
+	__CONFIGFS_ATTR(_name, S_IRUGO | S_IWUSR, pcie_gadget_show_##_name, \
+			pcie_gadget_store_##_name)
+PCIE_GADGET_TARGET_ATTR_RW(link);
+PCIE_GADGET_TARGET_ATTR_RW(int_type);
+PCIE_GADGET_TARGET_ATTR_RW(no_of_msi);
+PCIE_GADGET_TARGET_ATTR_WO(inta);
+PCIE_GADGET_TARGET_ATTR_WO(send_msi);
+PCIE_GADGET_TARGET_ATTR_RW(vendor_id);
+PCIE_GADGET_TARGET_ATTR_RW(device_id);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_size);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_address);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_rw_offset);
+PCIE_GADGET_TARGET_ATTR_RW(bar0_data);
+
+static struct configfs_attribute *pcie_gadget_target_attrs[] = {
+	&pcie_gadget_target_link.attr,
+	&pcie_gadget_target_int_type.attr,
+	&pcie_gadget_target_no_of_msi.attr,
+	&pcie_gadget_target_inta.attr,
+	&pcie_gadget_target_send_msi.attr,
+	&pcie_gadget_target_vendor_id.attr,
+	&pcie_gadget_target_device_id.attr,
+	&pcie_gadget_target_bar0_size.attr,
+	&pcie_gadget_target_bar0_address.attr,
+	&pcie_gadget_target_bar0_rw_offset.attr,
+	&pcie_gadget_target_bar0_data.attr,
+	NULL,
+};
+
+static struct pcie_gadget_target *to_target(struct config_item *item)
+{
+	return item ?
+		container_of(to_configfs_subsystem(to_config_group(item)),
+				struct pcie_gadget_target, subsys) : NULL;
+}
+
+/*
+ * Item operations and type for pcie_gadget_target.
+ */
+
+static ssize_t pcie_gadget_target_attr_show(struct config_item *item,
+					   struct configfs_attribute *attr,
+					   char *buf)
+{
+	ssize_t ret = -EINVAL;
+	struct pcie_gadget_target *target = to_target(item);
+	struct pcie_gadget_target_attr *t_attr =
+		container_of(attr, struct pcie_gadget_target_attr, attr);
+
+	if (t_attr->show)
+		ret = t_attr->show(&target->config, buf);
+	return ret;
+}
+
+static ssize_t pcie_gadget_target_attr_store(struct config_item *item,
+					struct configfs_attribute *attr,
+					const char *buf,
+					size_t count)
+{
+	ssize_t ret = -EINVAL;
+	struct pcie_gadget_target *target = to_target(item);
+	struct pcie_gadget_target_attr *t_attr =
+		container_of(attr, struct pcie_gadget_target_attr, attr);
+
+	if (t_attr->store)
+		ret = t_attr->store(&target->config, buf, count);
+	return ret;
+}
+
+static struct configfs_item_operations pcie_gadget_target_item_ops = {
+	.show_attribute		= pcie_gadget_target_attr_show,
+	.store_attribute	= pcie_gadget_target_attr_store,
+};
+
+static struct config_item_type pcie_gadget_target_type = {
+	.ct_attrs		= pcie_gadget_target_attrs,
+	.ct_item_ops		= &pcie_gadget_target_item_ops,
+	.ct_owner		= THIS_MODULE,
+};
+
+static void spear13xx_pcie_device_init(struct spear_pcie_gadget_config *config)
+{
+	struct pcie_app_reg __iomem *app_reg = config->va_app_base;
+
+	/*setup registers for outbound translation */
+
+	writel(config->base, &app_reg->in0_mem_addr_start);
+	writel(app_reg->in0_mem_addr_start + IN0_MEM_SIZE,
+			&app_reg->in0_mem_addr_limit);
+	writel(app_reg->in0_mem_addr_limit + 1, &app_reg->in1_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start + IN1_MEM_SIZE,
+			&app_reg->in1_mem_addr_limit);
+	writel(app_reg->in1_mem_addr_limit + 1, &app_reg->in_io_addr_start);
+	writel(app_reg->in_io_addr_start + IN_IO_SIZE,
+			&app_reg->in_io_addr_limit);
+	writel(app_reg->in_io_addr_limit + 1, &app_reg->in_cfg0_addr_start);
+	writel(app_reg->in_cfg0_addr_start + IN_CFG0_SIZE,
+			&app_reg->in_cfg0_addr_limit);
+	writel(app_reg->in_cfg0_addr_limit + 1, &app_reg->in_cfg1_addr_start);
+	writel(app_reg->in_cfg1_addr_start + IN_CFG1_SIZE,
+			&app_reg->in_cfg1_addr_limit);
+	writel(app_reg->in_cfg1_addr_limit + 1, &app_reg->in_msg_addr_start);
+	writel(app_reg->in_msg_addr_start + IN_MSG_SIZE,
+			&app_reg->in_msg_addr_limit);
+
+	writel(app_reg->in0_mem_addr_start, &app_reg->pom0_mem_addr_start);
+	writel(app_reg->in1_mem_addr_start, &app_reg->pom1_mem_addr_start);
+	writel(app_reg->in_io_addr_start, &app_reg->pom_io_addr_start);
+
+	/*setup registers for inbound translation */
+
+	/* Keep AORAM mapped at BAR0 as default */
+	config->bar0_size = INBOUND_ADDR_MASK + 1;
+	spear_dbi_write_reg(config, PCIE_BAR0_MASK_REG, 4, INBOUND_ADDR_MASK);
+	spear_dbi_write_reg(config, PCI_BASE_ADDRESS_0, 4, 0xC);
+	config->va_bar0_address = ioremap(SPEAR13XX_SYSRAM1_BASE,
+			config->bar0_size);
+
+	writel(SPEAR13XX_SYSRAM1_BASE, &app_reg->pim0_mem_addr_start);
+	writel(0, &app_reg->pim1_mem_addr_start);
+	writel(INBOUND_ADDR_MASK + 1, &app_reg->mem0_addr_offset_limit);
+
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_io_addr_start);
+	writel(0x0, &app_reg->pim_rom_addr_start);
+
+	writel(DEVICE_TYPE_EP | (1 << MISCTRL_EN_ID)
+			| ((u32)1 << REG_TRANSLATION_ENABLE),
+			&app_reg->app_ctrl_0);
+	/* disable all rx interrupts */
+	writel(0, &app_reg->int_mask);
+
+	/* Select INTA as default*/
+	spear_dbi_write_reg(config, PCI_INTERRUPT_LINE, 1, 1);
+}
+
+static int __devinit spear_pcie_gadget_probe(struct platform_device *pdev)
+{
+	struct resource *res0, *res1;
+	unsigned int status = 0;
+	int irq;
+	struct clk *clk;
+	static struct pcie_gadget_target *target;
+	struct spear_pcie_gadget_config *config;
+	struct config_item		*cg_item;
+	struct configfs_subsystem *subsys;
+
+	/* get resource for application registers*/
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res0) {
+		dev_err(&pdev->dev, "no resource defined\n");
+		return -EBUSY;
+	}
+	if (!request_mem_region(res0->start, resource_size(res0),
+				pdev->name)) {
+		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
+		return -EBUSY;
+	}
+	/* get resource for dbi registers*/
+
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res1) {
+		dev_err(&pdev->dev, "no resource defined\n");
+		goto err_rel_res0;
+	}
+	if (!request_mem_region(res1->start, resource_size(res1),
+				pdev->name)) {
+		dev_err(&pdev->dev, "pcie gadget region already	claimed\n");
+		goto err_rel_res0;
+	}
+
+	target = kzalloc(sizeof(*target), GFP_KERNEL);
+	if (!target) {
+		dev_err(&pdev->dev, "out of memory\n");
+		status = -ENOMEM;
+		goto err_rel_res;
+	}
+
+	cg_item = &target->subsys.su_group.cg_item;
+	sprintf(cg_item->ci_namebuf, "pcie_gadget.%d", pdev->id);
+	cg_item->ci_type	= &pcie_gadget_target_type;
+	config = &target->config;
+	config->va_app_base = (void __iomem *)ioremap(res0->start,
+			resource_size(res0));
+	if (!config->va_app_base) {
+		dev_err(&pdev->dev, "ioremap fail\n");
+		status = -ENOMEM;
+		goto err_kzalloc;
+	}
+
+	config->base = (void __iomem *)res1->start;
+
+	config->va_dbi_base = (void __iomem *)ioremap(res1->start,
+			resource_size(res1));
+	if (!config->va_dbi_base) {
+		dev_err(&pdev->dev, "ioremap fail\n");
+		status = -ENOMEM;
+		goto err_iounmap_app;
+	}
+
+	dev_set_drvdata(&pdev->dev, target);
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "no update irq?\n");
+		status = irq;
+		goto err_iounmap;
+	}
+
+	status = request_irq(irq, spear_pcie_gadget_irq, 0, pdev->name, NULL);
+	if (status) {
+		dev_err(&pdev->dev, "pcie gadget interrupt IRQ%d already \
+				claimed\n", irq);
+		goto err_iounmap;
+	}
+
+	/* Register configfs hooks */
+	subsys = &target->subsys;
+	config_group_init(&subsys->su_group);
+	mutex_init(&subsys->su_mutex);
+	status = configfs_register_subsystem(subsys);
+	if (status)
+		goto err_irq;
+
+	/*
+	 * init basic pcie application registers
+	 * do not enable clock if it is PCIE0.Ideally , all controller should
+	 * have been independent from others with respect to clock. But PCIE1
+	 * and 2 depends on PCIE0.So PCIE0 clk is provided during board init.
+	 */
+	if (pdev->id == 1) {
+		/*
+		 * Ideally CFG Clock should have been also enabled here. But
+		 * it is done currently during board init routne
+		 */
+		clk = clk_get_sys("pcie1", NULL);
+		if (IS_ERR(clk)) {
+			pr_err("%s:couldn't get clk for pcie1\n", __func__);
+			goto err_irq;
+		}
+		if (clk_enable(clk)) {
+			pr_err("%s:couldn't enable clk for pcie1\n", __func__);
+			goto err_irq;
+		}
+	} else if (pdev->id == 2) {
+		/*
+		 * Ideally CFG Clock should have been also enabled here. But
+		 * it is done currently during board init routne
+		 */
+		clk = clk_get_sys("pcie2", NULL);
+		if (IS_ERR(clk)) {
+			pr_err("%s:couldn't get clk for pcie2\n", __func__);
+			goto err_irq;
+		}
+		if (clk_enable(clk)) {
+			pr_err("%s:couldn't enable clk for pcie2\n", __func__);
+			goto err_irq;
+		}
+	}
+	spear13xx_pcie_device_init(config);
+
+	return 0;
+err_irq:
+	free_irq(irq, NULL);
+err_iounmap:
+	iounmap(config->va_dbi_base);
+err_iounmap_app:
+	iounmap(config->va_app_base);
+err_kzalloc:
+	kfree(config);
+err_rel_res:
+	release_mem_region(res1->start, resource_size(res1));
+err_rel_res0:
+	release_mem_region(res0->start, resource_size(res0));
+	return status;
+}
+
+static int __devexit spear_pcie_gadget_remove(struct platform_device *pdev)
+{
+	struct resource *res0, *res1;
+	static struct pcie_gadget_target *target;
+	struct spear_pcie_gadget_config *config;
+	int irq;
+
+	res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	res1 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	irq = platform_get_irq(pdev, 0);
+	target = dev_get_drvdata(&pdev->dev);
+	config = &target->config;
+
+	free_irq(irq, NULL);
+	iounmap(config->va_dbi_base);
+	iounmap(config->va_app_base);
+	release_mem_region(res1->start, resource_size(res1));
+	release_mem_region(res0->start, resource_size(res0));
+	configfs_unregister_subsystem(&target->subsys);
+	kfree(target);
+
+	return 0;
+}
+
+static void spear_pcie_gadget_shutdown(struct platform_device *pdev)
+{
+}
+
+static struct platform_driver spear_pcie_gadget_driver = {
+	.probe = spear_pcie_gadget_probe,
+	.remove = spear_pcie_gadget_remove,
+	.shutdown = spear_pcie_gadget_shutdown,
+	.driver = {
+		.name = "pcie-gadget-spear",
+		.bus = &platform_bus_type
+	},
+};
+
+static int __init spear_pcie_gadget_init(void)
+{
+	return platform_driver_register(&spear_pcie_gadget_driver);
+}
+module_init(spear_pcie_gadget_init);
+
+static void __exit spear_pcie_gadget_exit(void)
+{
+	platform_driver_unregister(&spear_pcie_gadget_driver);
+}
+module_exit(spear_pcie_gadget_exit);
+
+MODULE_ALIAS("pcie-gadget-spear");
+MODULE_AUTHOR("Pratyush Anand");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/misc/ti-st/st_core.c linux-libre-2.6.39-gnu/drivers/misc/ti-st/st_core.c
--- linux-libre-2.6.38-gnu/drivers/misc/ti-st/st_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/ti-st/st_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,10 +25,9 @@
 #include <linux/init.h>
 #include <linux/tty.h>
 
-/* understand BT, FM and GPS for now */
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-#include <net/bluetooth/hci.h>
+#include <linux/seq_file.h>
+#include <linux/skbuff.h>
+
 #include <linux/ti_wilink_st.h>
 
 /* function pointer pointing to either,
@@ -38,21 +37,38 @@
 void (*st_recv) (void*, const unsigned char*, long);
 
 /********************************************************************/
-#if 0
-/* internal misc functions */
-bool is_protocol_list_empty(void)
+static void add_channel_to_table(struct st_data_s *st_gdata,
+		struct st_proto_s *new_proto)
 {
-	unsigned char i = 0;
-	pr_debug(" %s ", __func__);
-	for (i = 0; i < ST_MAX; i++) {
-		if (st_gdata->list[i] != NULL)
-			return ST_NOTEMPTY;
-		/* not empty */
+	pr_info("%s: id %d\n", __func__, new_proto->chnl_id);
+	/* list now has the channel id as index itself */
+	st_gdata->list[new_proto->chnl_id] = new_proto;
+}
+
+static void remove_channel_from_table(struct st_data_s *st_gdata,
+		struct st_proto_s *proto)
+{
+	pr_info("%s: id %d\n", __func__, proto->chnl_id);
+	st_gdata->list[proto->chnl_id] = NULL;
+}
+
+/*
+ * called from KIM during firmware download.
+ *
+ * This is a wrapper function to tty->ops->write_room.
+ * It returns number of free space available in
+ * uart tx buffer.
+ */
+int st_get_uart_wr_room(struct st_data_s *st_gdata)
+{
+	struct tty_struct *tty;
+	if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
+		pr_err("tty unavailable to perform write");
+		return -1;
 	}
-	/* list empty */
-	return ST_EMPTY;
+	tty = st_gdata->tty;
+	return tty->ops->write_room(tty);
 }
-#endif
 
 /* can be called in from
  * -- KIM (during fw download)
@@ -67,7 +83,7 @@
 	struct tty_struct *tty;
 	if (unlikely(st_gdata == NULL || st_gdata->tty == NULL)) {
 		pr_err("tty unavailable to perform write");
-		return -1;
+		return -EINVAL;
 	}
 	tty = st_gdata->tty;
 #ifdef VERBOSE
@@ -82,15 +98,15 @@
  * push the skb received to relevant
  * protocol stacks
  */
-void st_send_frame(enum proto_type protoid, struct st_data_s *st_gdata)
+void st_send_frame(unsigned char chnl_id, struct st_data_s *st_gdata)
 {
-	pr_info(" %s(prot:%d) ", __func__, protoid);
+	pr_debug(" %s(prot:%d) ", __func__, chnl_id);
 
 	if (unlikely
 	    (st_gdata == NULL || st_gdata->rx_skb == NULL
-	     || st_gdata->list[protoid] == NULL)) {
-		pr_err("protocol %d not registered, no data to send?",
-			   protoid);
+	     || st_gdata->list[chnl_id] == NULL)) {
+		pr_err("chnl_id %d not registered, no data to send?",
+			   chnl_id);
 		kfree_skb(st_gdata->rx_skb);
 		return;
 	}
@@ -99,17 +115,17 @@
 	 * - should be just skb_queue_tail for the
 	 *   protocol stack driver
 	 */
-	if (likely(st_gdata->list[protoid]->recv != NULL)) {
+	if (likely(st_gdata->list[chnl_id]->recv != NULL)) {
 		if (unlikely
-			(st_gdata->list[protoid]->recv
-			(st_gdata->list[protoid]->priv_data, st_gdata->rx_skb)
+			(st_gdata->list[chnl_id]->recv
+			(st_gdata->list[chnl_id]->priv_data, st_gdata->rx_skb)
 			     != 0)) {
-			pr_err(" proto stack %d's ->recv failed", protoid);
+			pr_err(" proto stack %d's ->recv failed", chnl_id);
 			kfree_skb(st_gdata->rx_skb);
 			return;
 		}
 	} else {
-		pr_err(" proto stack %d's ->recv null", protoid);
+		pr_err(" proto stack %d's ->recv null", chnl_id);
 		kfree_skb(st_gdata->rx_skb);
 	}
 	return;
@@ -124,16 +140,22 @@
 {
 	unsigned char i = 0;
 	pr_info(" %s ", __func__);
-	for (i = 0; i < ST_MAX; i++) {
+	for (i = 0; i < ST_MAX_CHANNELS; i++) {
 		if (likely(st_gdata != NULL && st_gdata->list[i] != NULL &&
-			   st_gdata->list[i]->reg_complete_cb != NULL))
+			   st_gdata->list[i]->reg_complete_cb != NULL)) {
 			st_gdata->list[i]->reg_complete_cb
 				(st_gdata->list[i]->priv_data, err);
+			pr_info("protocol %d's cb sent %d\n", i, err);
+			if (err) { /* cleanup registered protocol */
+				st_gdata->protos_registered--;
+				st_gdata->list[i] = NULL;
+			}
+		}
 	}
 }
 
 static inline int st_check_data_len(struct st_data_s *st_gdata,
-	int protoid, int len)
+	unsigned char chnl_id, int len)
 {
 	int room = skb_tailroom(st_gdata->rx_skb);
 
@@ -144,7 +166,7 @@
 		 * has zero length payload. So, ask ST CORE to
 		 * forward the packet to protocol driver (BT/FM/GPS)
 		 */
-		st_send_frame(protoid, st_gdata);
+		st_send_frame(chnl_id, st_gdata);
 
 	} else if (len > room) {
 		/* Received packet's payload length is larger.
@@ -157,7 +179,7 @@
 		/* Packet header has non-zero payload length and
 		 * we have enough space in created skb. Lets read
 		 * payload data */
-		st_gdata->rx_state = ST_BT_W4_DATA;
+		st_gdata->rx_state = ST_W4_DATA;
 		st_gdata->rx_count = len;
 		return len;
 	}
@@ -167,6 +189,7 @@
 	st_gdata->rx_state = ST_W4_PACKET_TYPE;
 	st_gdata->rx_skb = NULL;
 	st_gdata->rx_count = 0;
+	st_gdata->rx_chnl = 0;
 
 	return 0;
 }
@@ -208,14 +231,12 @@
 	const unsigned char *data, long count)
 {
 	char *ptr;
-	struct hci_event_hdr *eh;
-	struct hci_acl_hdr *ah;
-	struct hci_sco_hdr *sh;
-	struct fm_event_hdr *fm;
-	struct gps_event_hdr *gps;
-	int len = 0, type = 0, dlen = 0;
-	static enum proto_type protoid = ST_MAX;
+	struct st_proto_s *proto;
+	unsigned short payload_len = 0;
+	int len = 0, type = 0;
+	unsigned char *plen;
 	struct st_data_s *st_gdata = (struct st_data_s *)disc_data;
+	unsigned long flags;
 
 	ptr = (char *)data;
 	/* tty_receive sent null ? */
@@ -224,10 +245,11 @@
 		return;
 	}
 
-	pr_info("count %ld rx_state %ld"
+	pr_debug("count %ld rx_state %ld"
 		   "rx_count %ld", count, st_gdata->rx_state,
 		   st_gdata->rx_count);
 
+	spin_lock_irqsave(&st_gdata->lock, flags);
 	/* Decode received bytes here */
 	while (count) {
 		if (st_gdata->rx_count) {
@@ -242,64 +264,36 @@
 
 			/* Check ST RX state machine , where are we? */
 			switch (st_gdata->rx_state) {
-
-				/* Waiting for complete packet ? */
-			case ST_BT_W4_DATA:
+			/* Waiting for complete packet ? */
+			case ST_W4_DATA:
 				pr_debug("Complete pkt received");
-
 				/* Ask ST CORE to forward
 				 * the packet to protocol driver */
-				st_send_frame(protoid, st_gdata);
+				st_send_frame(st_gdata->rx_chnl, st_gdata);
 
 				st_gdata->rx_state = ST_W4_PACKET_TYPE;
 				st_gdata->rx_skb = NULL;
-				protoid = ST_MAX;	/* is this required ? */
 				continue;
-
-				/* Waiting for Bluetooth event header ? */
-			case ST_BT_W4_EVENT_HDR:
-				eh = (struct hci_event_hdr *)st_gdata->rx_skb->
-				    data;
-
-				pr_debug("Event header: evt 0x%2.2x"
-					   "plen %d", eh->evt, eh->plen);
-
-				st_check_data_len(st_gdata, protoid, eh->plen);
-				continue;
-
-				/* Waiting for Bluetooth acl header ? */
-			case ST_BT_W4_ACL_HDR:
-				ah = (struct hci_acl_hdr *)st_gdata->rx_skb->
-				    data;
-				dlen = __le16_to_cpu(ah->dlen);
-
-				pr_info("ACL header: dlen %d", dlen);
-
-				st_check_data_len(st_gdata, protoid, dlen);
-				continue;
-
-				/* Waiting for Bluetooth sco header ? */
-			case ST_BT_W4_SCO_HDR:
-				sh = (struct hci_sco_hdr *)st_gdata->rx_skb->
-				    data;
-
-				pr_info("SCO header: dlen %d", sh->dlen);
-
-				st_check_data_len(st_gdata, protoid, sh->dlen);
-				continue;
-			case ST_FM_W4_EVENT_HDR:
-				fm = (struct fm_event_hdr *)st_gdata->rx_skb->
-				    data;
-				pr_info("FM Header: ");
-				st_check_data_len(st_gdata, ST_FM, fm->plen);
-				continue;
-				/* TODO : Add GPS packet machine logic here */
-			case ST_GPS_W4_EVENT_HDR:
-				/* [0x09 pkt hdr][R/W byte][2 byte len] */
-				gps = (struct gps_event_hdr *)st_gdata->rx_skb->
-				     data;
-				pr_info("GPS Header: ");
-				st_check_data_len(st_gdata, ST_GPS, gps->plen);
+			/* parse the header to know details */
+			case ST_W4_HEADER:
+				proto = st_gdata->list[st_gdata->rx_chnl];
+				plen =
+				&st_gdata->rx_skb->data
+				[proto->offset_len_in_hdr];
+				pr_debug("plen pointing to %x\n", *plen);
+				if (proto->len_size == 1)/* 1 byte len field */
+					payload_len = *(unsigned char *)plen;
+				else if (proto->len_size == 2)
+					payload_len =
+					__le16_to_cpu(*(unsigned short *)plen);
+				else
+					pr_info("%s: invalid length "
+					"for id %d\n",
+					__func__, proto->chnl_id);
+				st_check_data_len(st_gdata, proto->chnl_id,
+						payload_len);
+				pr_debug("off %d, pay len %d\n",
+					proto->offset_len_in_hdr, payload_len);
 				continue;
 			}	/* end of switch rx_state */
 		}
@@ -308,123 +302,56 @@
 		/* Check first byte of packet and identify module
 		 * owner (BT/FM/GPS) */
 		switch (*ptr) {
-
-			/* Bluetooth event packet? */
-		case HCI_EVENT_PKT:
-			pr_info("Event packet");
-			st_gdata->rx_state = ST_BT_W4_EVENT_HDR;
-			st_gdata->rx_count = HCI_EVENT_HDR_SIZE;
-			type = HCI_EVENT_PKT;
-			protoid = ST_BT;
-			break;
-
-			/* Bluetooth acl packet? */
-		case HCI_ACLDATA_PKT:
-			pr_info("ACL packet");
-			st_gdata->rx_state = ST_BT_W4_ACL_HDR;
-			st_gdata->rx_count = HCI_ACL_HDR_SIZE;
-			type = HCI_ACLDATA_PKT;
-			protoid = ST_BT;
-			break;
-
-			/* Bluetooth sco packet? */
-		case HCI_SCODATA_PKT:
-			pr_info("SCO packet");
-			st_gdata->rx_state = ST_BT_W4_SCO_HDR;
-			st_gdata->rx_count = HCI_SCO_HDR_SIZE;
-			type = HCI_SCODATA_PKT;
-			protoid = ST_BT;
-			break;
-
-			/* Channel 8(FM) packet? */
-		case ST_FM_CH8_PKT:
-			pr_info("FM CH8 packet");
-			type = ST_FM_CH8_PKT;
-			st_gdata->rx_state = ST_FM_W4_EVENT_HDR;
-			st_gdata->rx_count = FM_EVENT_HDR_SIZE;
-			protoid = ST_FM;
-			break;
-
-			/* Channel 9(GPS) packet? */
-		case 0x9:	/*ST_LL_GPS_CH9_PKT */
-			pr_info("GPS CH9 packet");
-			type = 0x9;	/* ST_LL_GPS_CH9_PKT; */
-			protoid = ST_GPS;
-			st_gdata->rx_state = ST_GPS_W4_EVENT_HDR;
-			st_gdata->rx_count = 3;	/* GPS_EVENT_HDR_SIZE -1*/
-			break;
 		case LL_SLEEP_IND:
 		case LL_SLEEP_ACK:
 		case LL_WAKE_UP_IND:
-			pr_info("PM packet");
+			pr_debug("PM packet");
 			/* this takes appropriate action based on
 			 * sleep state received --
 			 */
 			st_ll_sleep_state(st_gdata, *ptr);
+			/* if WAKEUP_IND collides copy from waitq to txq
+			 * and assume chip awake
+			 */
+			spin_unlock_irqrestore(&st_gdata->lock, flags);
+			if (st_ll_getstate(st_gdata) == ST_LL_AWAKE)
+				st_wakeup_ack(st_gdata, LL_WAKE_UP_ACK);
+			spin_lock_irqsave(&st_gdata->lock, flags);
+
 			ptr++;
 			count--;
 			continue;
 		case LL_WAKE_UP_ACK:
-			pr_info("PM packet");
+			pr_debug("PM packet");
+
+			spin_unlock_irqrestore(&st_gdata->lock, flags);
 			/* wake up ack received */
 			st_wakeup_ack(st_gdata, *ptr);
+			spin_lock_irqsave(&st_gdata->lock, flags);
+
 			ptr++;
 			count--;
 			continue;
 			/* Unknow packet? */
 		default:
-			pr_err("Unknown packet type %2.2x", (__u8) *ptr);
-			ptr++;
-			count--;
-			continue;
+			type = *ptr;
+			st_gdata->rx_skb = alloc_skb(
+					st_gdata->list[type]->max_frame_size,
+					GFP_ATOMIC);
+			skb_reserve(st_gdata->rx_skb,
+					st_gdata->list[type]->reserve);
+			/* next 2 required for BT only */
+			st_gdata->rx_skb->cb[0] = type; /*pkt_type*/
+			st_gdata->rx_skb->cb[1] = 0; /*incoming*/
+			st_gdata->rx_chnl = *ptr;
+			st_gdata->rx_state = ST_W4_HEADER;
+			st_gdata->rx_count = st_gdata->list[type]->hdr_len;
+			pr_debug("rx_count %ld\n", st_gdata->rx_count);
 		};
 		ptr++;
 		count--;
-
-		switch (protoid) {
-		case ST_BT:
-			/* Allocate new packet to hold received data */
-			st_gdata->rx_skb =
-			    bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
-			if (!st_gdata->rx_skb) {
-				pr_err("Can't allocate mem for new packet");
-				st_gdata->rx_state = ST_W4_PACKET_TYPE;
-				st_gdata->rx_count = 0;
-				return;
-			}
-			bt_cb(st_gdata->rx_skb)->pkt_type = type;
-			break;
-		case ST_FM:	/* for FM */
-			st_gdata->rx_skb =
-			    alloc_skb(FM_MAX_FRAME_SIZE, GFP_ATOMIC);
-			if (!st_gdata->rx_skb) {
-				pr_err("Can't allocate mem for new packet");
-				st_gdata->rx_state = ST_W4_PACKET_TYPE;
-				st_gdata->rx_count = 0;
-				return;
-			}
-			/* place holder 0x08 */
-			skb_reserve(st_gdata->rx_skb, 1);
-			st_gdata->rx_skb->cb[0] = ST_FM_CH8_PKT;
-			break;
-		case ST_GPS:
-			/* for GPS */
-			st_gdata->rx_skb =
-			    alloc_skb(100 /*GPS_MAX_FRAME_SIZE */ , GFP_ATOMIC);
-			if (!st_gdata->rx_skb) {
-				pr_err("Can't allocate mem for new packet");
-				st_gdata->rx_state = ST_W4_PACKET_TYPE;
-				st_gdata->rx_count = 0;
-				return;
-			}
-			/* place holder 0x09 */
-			skb_reserve(st_gdata->rx_skb, 1);
-			st_gdata->rx_skb->cb[0] = 0x09;	/*ST_GPS_CH9_PKT; */
-			break;
-		case ST_MAX:
-			break;
-		}
 	}
+	spin_unlock_irqrestore(&st_gdata->lock, flags);
 	pr_debug("done %s", __func__);
 	return;
 }
@@ -466,7 +393,7 @@
 
 	switch (st_ll_getstate(st_gdata)) {
 	case ST_LL_AWAKE:
-		pr_info("ST LL is AWAKE, sending normally");
+		pr_debug("ST LL is AWAKE, sending normally");
 		skb_queue_tail(&st_gdata->txq, skb);
 		break;
 	case ST_LL_ASLEEP_TO_AWAKE:
@@ -506,7 +433,7 @@
 	pr_debug("%s", __func__);
 	/* check for sending & set flag sending here */
 	if (test_and_set_bit(ST_TX_SENDING, &st_data->tx_state)) {
-		pr_info("ST already sending");
+		pr_debug("ST already sending");
 		/* keep sending */
 		set_bit(ST_TX_WAKEUP, &st_data->tx_state);
 		return;
@@ -548,9 +475,9 @@
 {
 	seq_printf(buf, "[%d]\nBT=%c\nFM=%c\nGPS=%c\n",
 			st_gdata->protos_registered,
-			st_gdata->list[ST_BT] != NULL ? 'R' : 'U',
-			st_gdata->list[ST_FM] != NULL ? 'R' : 'U',
-			st_gdata->list[ST_GPS] != NULL ? 'R' : 'U');
+			st_gdata->list[0x04] != NULL ? 'R' : 'U',
+			st_gdata->list[0x08] != NULL ? 'R' : 'U',
+			st_gdata->list[0x09] != NULL ? 'R' : 'U');
 }
 
 /********************************************************************/
@@ -565,20 +492,20 @@
 	unsigned long flags = 0;
 
 	st_kim_ref(&st_gdata, 0);
-	pr_info("%s(%d) ", __func__, new_proto->type);
+	pr_info("%s(%d) ", __func__, new_proto->chnl_id);
 	if (st_gdata == NULL || new_proto == NULL || new_proto->recv == NULL
 	    || new_proto->reg_complete_cb == NULL) {
 		pr_err("gdata/new_proto/recv or reg_complete_cb not ready");
-		return -1;
+		return -EINVAL;
 	}
 
-	if (new_proto->type < ST_BT || new_proto->type >= ST_MAX) {
-		pr_err("protocol %d not supported", new_proto->type);
+	if (new_proto->chnl_id >= ST_MAX_CHANNELS) {
+		pr_err("chnl_id %d not supported", new_proto->chnl_id);
 		return -EPROTONOSUPPORT;
 	}
 
-	if (st_gdata->list[new_proto->type] != NULL) {
-		pr_err("protocol %d already registered", new_proto->type);
+	if (st_gdata->list[new_proto->chnl_id] != NULL) {
+		pr_err("chnl_id %d already registered", new_proto->chnl_id);
 		return -EALREADY;
 	}
 
@@ -586,11 +513,10 @@
 	spin_lock_irqsave(&st_gdata->lock, flags);
 
 	if (test_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state)) {
-		pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->type);
+		pr_info(" ST_REG_IN_PROGRESS:%d ", new_proto->chnl_id);
 		/* fw download in progress */
-		st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE);
 
-		st_gdata->list[new_proto->type] = new_proto;
+		add_channel_to_table(st_gdata, new_proto);
 		st_gdata->protos_registered++;
 		new_proto->write = st_write;
 
@@ -598,7 +524,7 @@
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
 		return -EINPROGRESS;
 	} else if (st_gdata->protos_registered == ST_EMPTY) {
-		pr_info(" protocol list empty :%d ", new_proto->type);
+		pr_info(" chnl_id list empty :%d ", new_proto->chnl_id);
 		set_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
 		st_recv = st_kim_recv;
 
@@ -616,16 +542,11 @@
 			if ((st_gdata->protos_registered != ST_EMPTY) &&
 			    (test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
 				pr_err(" KIM failure complete callback ");
-				st_reg_complete(st_gdata, -1);
+				st_reg_complete(st_gdata, err);
 			}
-
-			return -1;
+			return -EINVAL;
 		}
 
-		/* the protocol might require other gpios to be toggled
-		 */
-		st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE);
-
 		clear_bit(ST_REG_IN_PROGRESS, &st_gdata->st_state);
 		st_recv = st_int_recv;
 
@@ -642,14 +563,14 @@
 		/* check for already registered once more,
 		 * since the above check is old
 		 */
-		if (st_gdata->list[new_proto->type] != NULL) {
+		if (st_gdata->list[new_proto->chnl_id] != NULL) {
 			pr_err(" proto %d already registered ",
-				   new_proto->type);
+				   new_proto->chnl_id);
 			return -EALREADY;
 		}
 
 		spin_lock_irqsave(&st_gdata->lock, flags);
-		st_gdata->list[new_proto->type] = new_proto;
+		add_channel_to_table(st_gdata, new_proto);
 		st_gdata->protos_registered++;
 		new_proto->write = st_write;
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
@@ -657,22 +578,7 @@
 	}
 	/* if fw is already downloaded & new stack registers protocol */
 	else {
-		switch (new_proto->type) {
-		case ST_BT:
-			/* do nothing */
-			break;
-		case ST_FM:
-		case ST_GPS:
-			st_kim_chip_toggle(new_proto->type, KIM_GPIO_ACTIVE);
-			break;
-		case ST_MAX:
-		default:
-			pr_err("%d protocol not supported",
-				   new_proto->type);
-			spin_unlock_irqrestore(&st_gdata->lock, flags);
-			return -EPROTONOSUPPORT;
-		}
-		st_gdata->list[new_proto->type] = new_proto;
+		add_channel_to_table(st_gdata, new_proto);
 		st_gdata->protos_registered++;
 		new_proto->write = st_write;
 
@@ -680,48 +586,42 @@
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
 		return err;
 	}
-	pr_debug("done %s(%d) ", __func__, new_proto->type);
+	pr_debug("done %s(%d) ", __func__, new_proto->chnl_id);
 }
 EXPORT_SYMBOL_GPL(st_register);
 
 /* to unregister a protocol -
  * to be called from protocol stack driver
  */
-long st_unregister(enum proto_type type)
+long st_unregister(struct st_proto_s *proto)
 {
 	long err = 0;
 	unsigned long flags = 0;
 	struct st_data_s	*st_gdata;
 
-	pr_debug("%s: %d ", __func__, type);
+	pr_debug("%s: %d ", __func__, proto->chnl_id);
 
 	st_kim_ref(&st_gdata, 0);
-	if (type < ST_BT || type >= ST_MAX) {
-		pr_err(" protocol %d not supported", type);
+	if (proto->chnl_id >= ST_MAX_CHANNELS) {
+		pr_err(" chnl_id %d not supported", proto->chnl_id);
 		return -EPROTONOSUPPORT;
 	}
 
 	spin_lock_irqsave(&st_gdata->lock, flags);
 
-	if (st_gdata->list[type] == NULL) {
-		pr_err(" protocol %d not registered", type);
+	if (st_gdata->list[proto->chnl_id] == NULL) {
+		pr_err(" chnl_id %d not registered", proto->chnl_id);
 		spin_unlock_irqrestore(&st_gdata->lock, flags);
 		return -EPROTONOSUPPORT;
 	}
 
 	st_gdata->protos_registered--;
-	st_gdata->list[type] = NULL;
-
-	/* kim ignores BT in the below function
-	 * and handles the rest, BT is toggled
-	 * only in kim_start and kim_stop
-	 */
-	st_kim_chip_toggle(type, KIM_GPIO_INACTIVE);
+	remove_channel_from_table(st_gdata, proto);
 	spin_unlock_irqrestore(&st_gdata->lock, flags);
 
 	if ((st_gdata->protos_registered == ST_EMPTY) &&
 	    (!test_bit(ST_REG_PENDING, &st_gdata->st_state))) {
-		pr_info(" all protocols unregistered ");
+		pr_info(" all chnl_ids unregistered ");
 
 		/* stop traffic on tty */
 		if (st_gdata->tty) {
@@ -729,7 +629,7 @@
 			stop_tty(st_gdata->tty);
 		}
 
-		/* all protocols now unregistered */
+		/* all chnl_ids now unregistered */
 		st_kim_stop(st_gdata->kim_data);
 		/* disable ST LL */
 		st_ll_disable(st_gdata);
@@ -744,37 +644,15 @@
 long st_write(struct sk_buff *skb)
 {
 	struct st_data_s *st_gdata;
-#ifdef DEBUG
-	enum proto_type protoid = ST_MAX;
-#endif
 	long len;
 
 	st_kim_ref(&st_gdata, 0);
 	if (unlikely(skb == NULL || st_gdata == NULL
 		|| st_gdata->tty == NULL)) {
 		pr_err("data/tty unavailable to perform write");
-		return -1;
-	}
-#ifdef DEBUG			/* open-up skb to read the 1st byte */
-	switch (skb->data[0]) {
-	case HCI_COMMAND_PKT:
-	case HCI_ACLDATA_PKT:
-	case HCI_SCODATA_PKT:
-		protoid = ST_BT;
-		break;
-	case ST_FM_CH8_PKT:
-		protoid = ST_FM;
-		break;
-	case 0x09:
-		protoid = ST_GPS;
-		break;
-	}
-	if (unlikely(st_gdata->list[protoid] == NULL)) {
-		pr_err(" protocol %d not registered, and writing? ",
-			   protoid);
-		return -1;
+		return -EINVAL;
 	}
-#endif
+
 	pr_debug("%d to be written", skb->len);
 	len = skb->len;
 
@@ -824,7 +702,7 @@
 
 static void st_tty_close(struct tty_struct *tty)
 {
-	unsigned char i = ST_MAX;
+	unsigned char i = ST_MAX_CHANNELS;
 	unsigned long flags = 0;
 	struct	st_data_s *st_gdata = tty->disc_data;
 
@@ -835,7 +713,7 @@
 	 * un-installed for some reason - what should be done ?
 	 */
 	spin_lock_irqsave(&st_gdata->lock, flags);
-	for (i = ST_BT; i < ST_MAX; i++) {
+	for (i = ST_BT; i < ST_MAX_CHANNELS; i++) {
 		if (st_gdata->list[i] != NULL)
 			pr_err("%d not un-registered", i);
 		st_gdata->list[i] = NULL;
@@ -869,7 +747,6 @@
 static void st_tty_receive(struct tty_struct *tty, const unsigned char *data,
 			   char *tty_flags, int count)
 {
-
 #ifdef VERBOSE
 	print_hex_dump(KERN_DEBUG, ">in>", DUMP_PREFIX_NONE,
 		16, 1, data, count, 0);
@@ -960,7 +837,7 @@
 		err = tty_unregister_ldisc(N_TI_WL);
 		if (err)
 			pr_err("unable to un-register ldisc");
-		return -1;
+		return err;
 	}
 	*core_data = st_gdata;
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/misc/ti-st/st_kim.c linux-libre-2.6.39-gnu/drivers/misc/ti-st/st_kim.c
--- linux-libre-2.6.38-gnu/drivers/misc/ti-st/st_kim.c	2012-03-24 01:16:16.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/ti-st/st_kim.c	2012-03-24 03:35:28.000000000 -0400
@@ -30,50 +30,12 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/sched.h>
-#include <linux/rfkill.h>
-
-/* understand BT events for fw response */
-#include <net/bluetooth/bluetooth.h>
-#include <net/bluetooth/hci_core.h>
-#include <net/bluetooth/hci.h>
+#include <linux/tty.h>
 
+#include <linux/skbuff.h>
 #include <linux/ti_wilink_st.h>
 
 
-static int kim_probe(struct platform_device *pdev);
-static int kim_remove(struct platform_device *pdev);
-
-/* KIM platform device driver structure */
-static struct platform_driver kim_platform_driver = {
-	.probe = kim_probe,
-	.remove = kim_remove,
-	/* TODO: ST driver power management during suspend/resume ?
-	 */
-#if 0
-	.suspend = kim_suspend,
-	.resume = kim_resume,
-#endif
-	.driver = {
-		   .name = "kim",
-		   .owner = THIS_MODULE,
-		   },
-};
-
-static int kim_toggle_radio(void*, bool);
-static const struct rfkill_ops kim_rfkill_ops = {
-	.set_block = kim_toggle_radio,
-};
-
-/* strings to be used for rfkill entries and by
- * ST Core to be used for sysfs debug entry
- */
-#define PROTO_ENTRY(type, name)	name
-const unsigned char *protocol_names[] = {
-	PROTO_ENTRY(ST_BT, "Bluetooth"),
-	PROTO_ENTRY(ST_FM, "FM"),
-	PROTO_ENTRY(ST_GPS, "GPS"),
-};
-
 #define MAX_ST_DEVICES	3	/* Imagine 1 on each UART for now */
 static struct platform_device *st_kim_devices[MAX_ST_DEVICES];
 
@@ -134,7 +96,7 @@
 		/* Packet header has non-zero payload length and
 		 * we have enough space in created skb. Lets read
 		 * payload data */
-		kim_gdata->rx_state = ST_BT_W4_DATA;
+		kim_gdata->rx_state = ST_W4_DATA;
 		kim_gdata->rx_count = len;
 		return len;
 	}
@@ -158,8 +120,8 @@
 	const unsigned char *data, long count)
 {
 	const unsigned char *ptr;
-	struct hci_event_hdr *eh;
 	int len = 0, type = 0;
+	unsigned char *plen;
 
 	pr_debug("%s", __func__);
 	/* Decode received bytes here */
@@ -183,29 +145,27 @@
 			/* Check ST RX state machine , where are we? */
 			switch (kim_gdata->rx_state) {
 				/* Waiting for complete packet ? */
-			case ST_BT_W4_DATA:
+			case ST_W4_DATA:
 				pr_debug("Complete pkt received");
 				validate_firmware_response(kim_gdata);
 				kim_gdata->rx_state = ST_W4_PACKET_TYPE;
 				kim_gdata->rx_skb = NULL;
 				continue;
 				/* Waiting for Bluetooth event header ? */
-			case ST_BT_W4_EVENT_HDR:
-				eh = (struct hci_event_hdr *)kim_gdata->
-				    rx_skb->data;
-				pr_debug("Event header: evt 0x%2.2x"
-					   "plen %d", eh->evt, eh->plen);
-				kim_check_data_len(kim_gdata, eh->plen);
+			case ST_W4_HEADER:
+				plen =
+				(unsigned char *)&kim_gdata->rx_skb->data[1];
+				pr_debug("event hdr: plen 0x%02x\n", *plen);
+				kim_check_data_len(kim_gdata, *plen);
 				continue;
 			}	/* end of switch */
 		}		/* end of if rx_state */
 		switch (*ptr) {
 			/* Bluetooth event packet? */
-		case HCI_EVENT_PKT:
-			pr_info("Event packet");
-			kim_gdata->rx_state = ST_BT_W4_EVENT_HDR;
-			kim_gdata->rx_count = HCI_EVENT_HDR_SIZE;
-			type = HCI_EVENT_PKT;
+		case 0x04:
+			kim_gdata->rx_state = ST_W4_HEADER;
+			kim_gdata->rx_count = 2;
+			type = *ptr;
 			break;
 		default:
 			pr_info("unknown packet");
@@ -216,16 +176,18 @@
 		ptr++;
 		count--;
 		kim_gdata->rx_skb =
-		    bt_skb_alloc(HCI_MAX_FRAME_SIZE, GFP_ATOMIC);
+			alloc_skb(1024+8, GFP_ATOMIC);
 		if (!kim_gdata->rx_skb) {
 			pr_err("can't allocate mem for new packet");
 			kim_gdata->rx_state = ST_W4_PACKET_TYPE;
 			kim_gdata->rx_count = 0;
 			return;
 		}
-		bt_cb(kim_gdata->rx_skb)->pkt_type = type;
+		skb_reserve(kim_gdata->rx_skb, 8);
+		kim_gdata->rx_skb->cb[0] = 4;
+		kim_gdata->rx_skb->cb[1] = 0;
+
 	}
-	pr_info("done %s", __func__);
 	return;
 }
 
@@ -239,13 +201,13 @@
 	INIT_COMPLETION(kim_gdata->kim_rcvd);
 	if (4 != st_int_write(kim_gdata->core_data, read_ver_cmd, 4)) {
 		pr_err("kim: couldn't write 4 bytes");
-		return -1;
+		return -EIO;
 	}
 
 	if (!wait_for_completion_timeout
 	    (&kim_gdata->kim_rcvd, msecs_to_jiffies(CMD_RESP_TIME))) {
 		pr_err(" waiting for ver info- timed out ");
-		return -1;
+		return -ETIMEDOUT;
 	}
 
 	version =
@@ -270,6 +232,26 @@
 	return 0;
 }
 
+void skip_change_remote_baud(unsigned char **ptr, long *len)
+{
+	unsigned char *nxt_action, *cur_action;
+	cur_action = *ptr;
+
+	nxt_action = cur_action + sizeof(struct bts_action) +
+		((struct bts_action *) cur_action)->size;
+
+	if (((struct bts_action *) nxt_action)->type != ACTION_WAIT_EVENT) {
+		pr_err("invalid action after change remote baud command");
+	} else {
+		*ptr = *ptr + sizeof(struct bts_action) +
+			((struct bts_action *)nxt_action)->size;
+		*len = *len - (sizeof(struct bts_action) +
+				((struct bts_action *)nxt_action)->size);
+		/* warn user on not commenting these in firmware */
+		pr_warn("skipping the wait event of change remote baud");
+	}
+}
+
 /**
  * download_firmware -
  *	internal function which parses through the .bts firmware
@@ -282,6 +264,9 @@
 	unsigned char *ptr = NULL;
 	unsigned char *action_ptr = NULL;
 	unsigned char bts_scr_name[30] = { 0 };	/* 30 char long bts scr name? */
+	int wr_room_space;
+	int cmd_size;
+	unsigned long timeout;
 
 	err = read_local_version(kim_gdata, bts_scr_name);
 	if (err != 0) {
@@ -295,7 +280,7 @@
 		     (kim_gdata->fw_entry->size == 0))) {
 		pr_err(" reject_firmware failed(errno %ld) for %s", err,
 			   bts_scr_name);
-		return -1;
+		return -EINVAL;
 	}
 	ptr = (void *)kim_gdata->fw_entry->data;
 	len = kim_gdata->fw_entry->size;
@@ -318,29 +303,72 @@
 			     0xFF36)) {
 				/* ignore remote change
 				 * baud rate HCI VS command */
-				pr_err
-				    (" change remote baud"
+				pr_warn("change remote baud"
 				    " rate command in firmware");
+				skip_change_remote_baud(&ptr, &len);
 				break;
 			}
+			/*
+			 * Make sure we have enough free space in uart
+			 * tx buffer to write current firmware command
+			 */
+			cmd_size = ((struct bts_action *)ptr)->size;
+			timeout = jiffies + msecs_to_jiffies(CMD_WR_TIME);
+			do {
+				wr_room_space =
+					st_get_uart_wr_room(kim_gdata->core_data);
+				if (wr_room_space < 0) {
+					pr_err("Unable to get free "
+							"space info from uart tx buffer");
+					release_firmware(kim_gdata->fw_entry);
+					return wr_room_space;
+				}
+				mdelay(1); /* wait 1ms before checking room */
+			} while ((wr_room_space < cmd_size) &&
+					time_before(jiffies, timeout));
+
+			/* Timeout happened ? */
+			if (time_after_eq(jiffies, timeout)) {
+				pr_err("Timeout while waiting for free "
+						"free space in uart tx buffer");
+				release_firmware(kim_gdata->fw_entry);
+				return -ETIMEDOUT;
+			}
 
-			INIT_COMPLETION(kim_gdata->kim_rcvd);
+			/*
+			 * Free space found in uart buffer, call st_int_write
+			 * to send current firmware command to the uart tx
+			 * buffer.
+			 */
 			err = st_int_write(kim_gdata->core_data,
 			((struct bts_action_send *)action_ptr)->data,
 					   ((struct bts_action *)ptr)->size);
 			if (unlikely(err < 0)) {
 				release_firmware(kim_gdata->fw_entry);
-				return -1;
+				return err;
+			}
+			/*
+			 * Check number of bytes written to the uart tx buffer
+			 * and requested command write size
+			 */
+			if (err != cmd_size) {
+				pr_err("Number of bytes written to uart "
+						"tx buffer are not matching with "
+						"requested cmd write size");
+				release_firmware(kim_gdata->fw_entry);
+				return -EIO;
 			}
+			break;
+		case ACTION_WAIT_EVENT:  /* wait */
 			if (!wait_for_completion_timeout
-			    (&kim_gdata->kim_rcvd,
-			     msecs_to_jiffies(CMD_RESP_TIME))) {
-				pr_err
-				    (" response timeout during fw download ");
+					(&kim_gdata->kim_rcvd,
+					 msecs_to_jiffies(CMD_RESP_TIME))) {
+				pr_err("response timeout during fw download ");
 				/* timed out */
 				release_firmware(kim_gdata->fw_entry);
-				return -1;
+				return -ETIMEDOUT;
 			}
+			INIT_COMPLETION(kim_gdata->kim_rcvd);
 			break;
 		case ACTION_DELAY:	/* sleep */
 			pr_info("sleep command in scr");
@@ -362,50 +390,6 @@
 
 /**********************************************************************/
 /* functions called from ST core */
-/* function to toggle the GPIO
- * needs to know whether the GPIO is active high or active low
- */
-void st_kim_chip_toggle(enum proto_type type, enum kim_gpio_state state)
-{
-	struct platform_device	*kim_pdev;
-	struct kim_data_s	*kim_gdata;
-	pr_info(" %s ", __func__);
-
-	kim_pdev = st_get_plat_device(0);
-	kim_gdata = dev_get_drvdata(&kim_pdev->dev);
-
-	if (kim_gdata->gpios[type] == -1) {
-		pr_info(" gpio not requested for protocol %s",
-			   protocol_names[type]);
-		return;
-	}
-	switch (type) {
-	case ST_BT:
-		/*Do Nothing */
-		break;
-
-	case ST_FM:
-		if (state == KIM_GPIO_ACTIVE)
-			gpio_set_value(kim_gdata->gpios[ST_FM], GPIO_LOW);
-		else
-			gpio_set_value(kim_gdata->gpios[ST_FM], GPIO_HIGH);
-		break;
-
-	case ST_GPS:
-		if (state == KIM_GPIO_ACTIVE)
-			gpio_set_value(kim_gdata->gpios[ST_GPS], GPIO_HIGH);
-		else
-			gpio_set_value(kim_gdata->gpios[ST_GPS], GPIO_LOW);
-		break;
-
-	case ST_MAX:
-	default:
-		break;
-	}
-
-	return;
-}
-
 /* called from ST Core, when REG_IN_PROGRESS (registration in progress)
  * can be because of
  * 1. response to read local version
@@ -416,7 +400,6 @@
 	struct st_data_s	*st_gdata = (struct st_data_s *)disc_data;
 	struct kim_data_s	*kim_gdata = st_gdata->kim_data;
 
-	pr_info(" %s ", __func__);
 	/* copy to local buffer */
 	if (unlikely(data[4] == 0x01 && data[5] == 0x10 && data[0] == 0x04)) {
 		/* must be the read_ver_cmd */
@@ -455,35 +438,28 @@
 	pr_info(" %s", __func__);
 
 	do {
-		/* TODO: this is only because rfkill sub-system
-		 * doesn't send events to user-space if the state
-		 * isn't changed
-		 */
-		rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1);
 		/* Configure BT nShutdown to HIGH state */
-		gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
+		gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
 		mdelay(5);	/* FIXME: a proper toggle */
-		gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_HIGH);
+		gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
 		mdelay(100);
 		/* re-initialize the completion */
 		INIT_COMPLETION(kim_gdata->ldisc_installed);
-#if 0 /* older way of signalling user-space UIM */
-		/* send signal to UIM */
-		err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 0);
-		if (err != 0) {
-			pr_info(" sending SIGUSR2 to uim failed %ld", err);
-			err = -1;
-			continue;
-		}
-#endif
-		/* unblock and send event to UIM via /dev/rfkill */
-		rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 0);
+		/* send notification to UIM */
+		kim_gdata->ldisc_install = 1;
+		pr_info("ldisc_install = 1");
+		sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
+				NULL, "install");
 		/* wait for ldisc to be installed */
 		err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
 				msecs_to_jiffies(LDISC_TIME));
 		if (!err) {	/* timeout */
 			pr_err("line disc installation timed out ");
-			err = -1;
+			kim_gdata->ldisc_install = 0;
+			pr_info("ldisc_install = 0");
+			sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
+					NULL, "install");
+			err = -ETIMEDOUT;
 			continue;
 		} else {
 			/* ldisc installed now */
@@ -491,6 +467,10 @@
 			err = download_firmware(kim_gdata);
 			if (err != 0) {
 				pr_err("download firmware failed");
+				kim_gdata->ldisc_install = 0;
+				pr_info("ldisc_install = 0");
+				sysfs_notify(&kim_gdata->kim_pdev->dev.kobj,
+						NULL, "install");
 				continue;
 			} else {	/* on success don't retry */
 				break;
@@ -510,31 +490,30 @@
 	struct kim_data_s	*kim_gdata = (struct kim_data_s *)kim_data;
 
 	INIT_COMPLETION(kim_gdata->ldisc_installed);
-#if 0 /* older way of signalling user-space UIM */
-	/* send signal to UIM */
-	err = kill_pid(find_get_pid(kim_gdata->uim_pid), SIGUSR2, 1);
-	if (err != 0) {
-		pr_err("sending SIGUSR2 to uim failed %ld", err);
-		return -1;
-	}
-#endif
-	/* set BT rfkill to be blocked */
-	err = rfkill_set_hw_state(kim_gdata->rfkill[ST_BT], 1);
+
+	/* Flush any pending characters in the driver and discipline. */
+	tty_ldisc_flush(kim_gdata->core_data->tty);
+	tty_driver_flush_buffer(kim_gdata->core_data->tty);
+
+	/* send uninstall notification to UIM */
+	pr_info("ldisc_install = 0");
+	kim_gdata->ldisc_install = 0;
+	sysfs_notify(&kim_gdata->kim_pdev->dev.kobj, NULL, "install");
 
 	/* wait for ldisc to be un-installed */
 	err = wait_for_completion_timeout(&kim_gdata->ldisc_installed,
 			msecs_to_jiffies(LDISC_TIME));
 	if (!err) {		/* timeout */
 		pr_err(" timed out waiting for ldisc to be un-installed");
-		return -1;
+		return -ETIMEDOUT;
 	}
 
 	/* By default configure BT nShutdown to LOW state */
-	gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
 	mdelay(1);
-	gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_HIGH);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
 	mdelay(1);
-	gpio_set_value(kim_gdata->gpios[ST_BT], GPIO_LOW);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
 	return err;
 }
 
@@ -558,33 +537,59 @@
 	return 0;
 }
 
-/* function called from rfkill subsystem, when someone from
- * user space would write 0/1 on the sysfs entry
- * /sys/class/rfkill/rfkill0,1,3/state
- */
-static int kim_toggle_radio(void *data, bool blocked)
+static ssize_t show_install(struct device *dev,
+		struct device_attribute *attr, char *buf)
 {
-	enum proto_type type = *((enum proto_type *)data);
-	pr_debug(" %s: %d ", __func__, type);
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", kim_data->ldisc_install);
+}
 
-	switch (type) {
-	case ST_BT:
-		/* do nothing */
-	break;
-	case ST_FM:
-	case ST_GPS:
-		if (blocked)
-			st_kim_chip_toggle(type, KIM_GPIO_INACTIVE);
-		else
-			st_kim_chip_toggle(type, KIM_GPIO_ACTIVE);
-	break;
-	case ST_MAX:
-		pr_err(" wrong proto type ");
-	break;
-	}
-	return 0;
+static ssize_t show_dev_name(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", kim_data->dev_name);
 }
 
+static ssize_t show_baud_rate(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%ld\n", kim_data->baud_rate);
+}
+
+static ssize_t show_flow_cntrl(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct kim_data_s *kim_data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", kim_data->flow_cntrl);
+}
+
+/* structures specific for sysfs entries */
+static struct kobj_attribute ldisc_install =
+__ATTR(install, 0444, (void *)show_install, NULL);
+
+static struct kobj_attribute uart_dev_name =
+__ATTR(dev_name, 0444, (void *)show_dev_name, NULL);
+
+static struct kobj_attribute uart_baud_rate =
+__ATTR(baud_rate, 0444, (void *)show_baud_rate, NULL);
+
+static struct kobj_attribute uart_flow_cntrl =
+__ATTR(flow_cntrl, 0444, (void *)show_flow_cntrl, NULL);
+
+static struct attribute *uim_attrs[] = {
+	&ldisc_install.attr,
+	&uart_dev_name.attr,
+	&uart_baud_rate.attr,
+	&uart_flow_cntrl.attr,
+	NULL,
+};
+
+static struct attribute_group uim_attr_grp = {
+	.attrs = uim_attrs,
+};
+
 /**
  * st_kim_ref - reference the core's data
  *	This references the per-ST platform device in the arch/xx/
@@ -637,15 +642,14 @@
 static int kim_probe(struct platform_device *pdev)
 {
 	long status;
-	long proto;
-	long *gpios = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
 
 	if ((pdev->id != -1) && (pdev->id < MAX_ST_DEVICES)) {
 		/* multiple devices could exist */
 		st_kim_devices[pdev->id] = pdev;
 	} else {
-		/* platform's sure about existance of 1 device */
+		/* platform's sure about existence of 1 device */
 		st_kim_devices[0] = pdev;
 	}
 
@@ -659,44 +663,24 @@
 	status = st_core_init(&kim_gdata->core_data);
 	if (status != 0) {
 		pr_err(" ST core init failed");
-		return -1;
+		return -EIO;
 	}
 	/* refer to itself */
 	kim_gdata->core_data->kim_data = kim_gdata;
 
-	for (proto = 0; proto < ST_MAX; proto++) {
-		kim_gdata->gpios[proto] = gpios[proto];
-		pr_info(" %ld gpio to be requested", gpios[proto]);
+	/* Claim the chip enable nShutdown gpio from the system */
+	kim_gdata->nshutdown = pdata->nshutdown_gpio;
+	status = gpio_request(kim_gdata->nshutdown, "kim");
+	if (unlikely(status)) {
+		pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
+		return status;
 	}
 
-	for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) {
-		/* Claim the Bluetooth/FM/GPIO
-		 * nShutdown gpio from the system
-		 */
-		status = gpio_request(gpios[proto], "kim");
-		if (unlikely(status)) {
-			pr_err(" gpio %ld request failed ", gpios[proto]);
-			proto -= 1;
-			while (proto >= 0) {
-				if (gpios[proto] != -1)
-					gpio_free(gpios[proto]);
-			}
-			return status;
-		}
-
-		/* Configure nShutdown GPIO as output=0 */
-		status =
-		    gpio_direction_output(gpios[proto], 0);
-		if (unlikely(status)) {
-			pr_err(" unable to configure gpio %ld",
-				   gpios[proto]);
-			proto -= 1;
-			while (proto >= 0) {
-				if (gpios[proto] != -1)
-					gpio_free(gpios[proto]);
-			}
-			return status;
-		}
+	/* Configure nShutdown GPIO as output=0 */
+	status = gpio_direction_output(kim_gdata->nshutdown, 0);
+	if (unlikely(status)) {
+		pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
+		return status;
 	}
 	/* get reference of pdev for reject_firmware
 	 */
@@ -704,34 +688,23 @@
 	init_completion(&kim_gdata->kim_rcvd);
 	init_completion(&kim_gdata->ldisc_installed);
 
-	for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) {
-		/* TODO: should all types be rfkill_type_bt ? */
-		kim_gdata->rf_protos[proto] = proto;
-		kim_gdata->rfkill[proto] = rfkill_alloc(protocol_names[proto],
-			&pdev->dev, RFKILL_TYPE_BLUETOOTH,
-			&kim_rfkill_ops, &kim_gdata->rf_protos[proto]);
-		if (kim_gdata->rfkill[proto] == NULL) {
-			pr_err("cannot create rfkill entry for gpio %ld",
-				   gpios[proto]);
-			continue;
-		}
-		/* block upon creation */
-		rfkill_init_sw_state(kim_gdata->rfkill[proto], 1);
-		status = rfkill_register(kim_gdata->rfkill[proto]);
-		if (unlikely(status)) {
-			pr_err("rfkill registration failed for gpio %ld",
-				   gpios[proto]);
-			rfkill_unregister(kim_gdata->rfkill[proto]);
-			continue;
-		}
-		pr_info("rfkill entry created for %ld", gpios[proto]);
+	status = sysfs_create_group(&pdev->dev.kobj, &uim_attr_grp);
+	if (status) {
+		pr_err("failed to create sysfs entries");
+		return status;
 	}
 
+	/* copying platform data */
+	strncpy(kim_gdata->dev_name, pdata->dev_name, UART_DEV_NAME_LEN);
+	kim_gdata->flow_cntrl = pdata->flow_cntrl;
+	kim_gdata->baud_rate = pdata->baud_rate;
+	pr_info("sysfs entries created\n");
+
 	kim_debugfs_dir = debugfs_create_dir("ti-st", NULL);
 	if (IS_ERR(kim_debugfs_dir)) {
 		pr_err(" debugfs entries creation failed ");
 		kim_debugfs_dir = NULL;
-		return -1;
+		return -EIO;
 	}
 
 	debugfs_create_file("version", S_IRUGO, kim_debugfs_dir,
@@ -744,25 +717,22 @@
 
 static int kim_remove(struct platform_device *pdev)
 {
-	/* free the GPIOs requested
-	 */
-	long *gpios = pdev->dev.platform_data;
-	long proto;
+	/* free the GPIOs requested */
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
 
 	kim_gdata = dev_get_drvdata(&pdev->dev);
 
-	for (proto = 0; (proto < ST_MAX) && (gpios[proto] != -1); proto++) {
-		/* Claim the Bluetooth/FM/GPIO
-		 * nShutdown gpio from the system
-		 */
-		gpio_free(gpios[proto]);
-		rfkill_unregister(kim_gdata->rfkill[proto]);
-		rfkill_destroy(kim_gdata->rfkill[proto]);
-		kim_gdata->rfkill[proto] = NULL;
-	}
-	pr_info("kim: GPIO Freed");
+	/* Free the Bluetooth/FM/GPIO
+	 * nShutdown gpio from the system
+	 */
+	gpio_free(pdata->nshutdown_gpio);
+	pr_info("nshutdown GPIO Freed");
+
 	debugfs_remove_recursive(kim_debugfs_dir);
+	sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
+	pr_info("sysfs entries removed");
+
 	kim_gdata->kim_pdev = NULL;
 	st_core_exit(kim_gdata->core_data);
 
@@ -771,23 +741,46 @@
 	return 0;
 }
 
+int kim_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
+
+	if (pdata->suspend)
+		return pdata->suspend(pdev, state);
+
+	return -EOPNOTSUPP;
+}
+
+int kim_resume(struct platform_device *pdev)
+{
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
+
+	if (pdata->resume)
+		return pdata->resume(pdev);
+
+	return -EOPNOTSUPP;
+}
+
 /**********************************************************************/
 /* entry point for ST KIM module, called in from ST Core */
+static struct platform_driver kim_platform_driver = {
+	.probe = kim_probe,
+	.remove = kim_remove,
+	.suspend = kim_suspend,
+	.resume = kim_resume,
+	.driver = {
+		.name = "kim",
+		.owner = THIS_MODULE,
+	},
+};
 
 static int __init st_kim_init(void)
 {
-	long ret = 0;
-	ret = platform_driver_register(&kim_platform_driver);
-	if (ret != 0) {
-		pr_err("platform drv registration failed");
-		return -1;
-	}
-	return 0;
+	return platform_driver_register(&kim_platform_driver);
 }
 
 static void __exit st_kim_deinit(void)
 {
-	/* the following returns void */
 	platform_driver_unregister(&kim_platform_driver);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/misc/ti-st/st_ll.c linux-libre-2.6.39-gnu/drivers/misc/ti-st/st_ll.c
--- linux-libre-2.6.38-gnu/drivers/misc/ti-st/st_ll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/misc/ti-st/st_ll.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 	unsigned char cmd)
 {
 
-	pr_info("%s: writing %x", __func__, cmd);
+	pr_debug("%s: writing %x", __func__, cmd);
 	st_int_write(st_data, &cmd, 1);
 	return;
 }
@@ -114,23 +114,23 @@
 {
 	switch (cmd) {
 	case LL_SLEEP_IND:	/* sleep ind */
-		pr_info("sleep indication recvd");
+		pr_debug("sleep indication recvd");
 		ll_device_want_to_sleep(st_data);
 		break;
 	case LL_SLEEP_ACK:	/* sleep ack */
 		pr_err("sleep ack rcvd: host shouldn't");
 		break;
 	case LL_WAKE_UP_IND:	/* wake ind */
-		pr_info("wake indication recvd");
+		pr_debug("wake indication recvd");
 		ll_device_want_to_wakeup(st_data);
 		break;
 	case LL_WAKE_UP_ACK:	/* wake ack */
-		pr_info("wake ack rcvd");
+		pr_debug("wake ack rcvd");
 		st_data->ll_state = ST_LL_AWAKE;
 		break;
 	default:
 		pr_err(" unknown input/state ");
-		return -1;
+		return -EINVAL;
 	}
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/card/block.c linux-libre-2.6.39-gnu/drivers/mmc/card/block.c
--- linux-libre-2.6.38-gnu/drivers/mmc/card/block.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/card/block.c	2011-05-19 00:06:34.000000000 -0400
@@ -621,6 +621,7 @@
 	md->disk->private_data = md;
 	md->disk->queue = md->queue.queue;
 	md->disk->driverfs_dev = &card->dev;
+	set_disk_ro(md->disk, md->read_only);
 
 	/*
 	 * As discussed on lkml, GENHD_FL_REMOVABLE should:
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/card/Kconfig linux-libre-2.6.39-gnu/drivers/mmc/card/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mmc/card/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/card/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -58,12 +58,11 @@
 
 config MMC_TEST
 	tristate "MMC host test driver"
-	default n
 	help
 	  Development driver that performs a series of reads and writes
 	  to a memory card in order to expose certain well known bugs
 	  in host controllers. The tests are executed by writing to the
-	  "test" file in sysfs under each card. Note that whatever is
+	  "test" file in debugfs under each card. Note that whatever is
 	  on your card will be overwritten by these tests.
 
 	  This driver is only of interest to those developing or
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/card/mmc_test.c linux-libre-2.6.39-gnu/drivers/mmc/card/mmc_test.c
--- linux-libre-2.6.38-gnu/drivers/mmc/card/mmc_test.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/card/mmc_test.c	2011-05-19 00:06:34.000000000 -0400
@@ -88,6 +88,7 @@
  * @sectors: amount of sectors to check in one group
  * @ts: time values of transfer
  * @rate: calculated transfer rate
+ * @iops: I/O operations per second (times 100)
  */
 struct mmc_test_transfer_result {
 	struct list_head link;
@@ -95,6 +96,7 @@
 	unsigned int sectors;
 	struct timespec ts;
 	unsigned int rate;
+	unsigned int iops;
 };
 
 /**
@@ -226,9 +228,10 @@
 
 		if (!busy && mmc_test_busy(&cmd)) {
 			busy = 1;
-			printk(KERN_INFO "%s: Warning: Host did not "
-				"wait for busy state to end.\n",
-				mmc_hostname(test->card->host));
+			if (test->card->host->caps & MMC_CAP_WAIT_WHILE_BUSY)
+				printk(KERN_INFO "%s: Warning: Host did not "
+					"wait for busy state to end.\n",
+					mmc_hostname(test->card->host));
 		}
 	} while (mmc_test_busy(&cmd));
 
@@ -289,7 +292,7 @@
 }
 
 /*
- * Allocate a lot of memory, preferrably max_sz but at least min_sz.  In case
+ * Allocate a lot of memory, preferably max_sz but at least min_sz.  In case
  * there isn't much memory do not exceed 1/16th total lowmem pages.  Also do
  * not exceed a maximum number of segments and try not to make segments much
  * bigger than maximum segment size.
@@ -494,7 +497,7 @@
  */
 static void mmc_test_save_transfer_result(struct mmc_test_card *test,
 	unsigned int count, unsigned int sectors, struct timespec ts,
-	unsigned int rate)
+	unsigned int rate, unsigned int iops)
 {
 	struct mmc_test_transfer_result *tr;
 
@@ -509,6 +512,7 @@
 	tr->sectors = sectors;
 	tr->ts = ts;
 	tr->rate = rate;
+	tr->iops = iops;
 
 	list_add_tail(&tr->link, &test->gr->tr_lst);
 }
@@ -519,20 +523,22 @@
 static void mmc_test_print_rate(struct mmc_test_card *test, uint64_t bytes,
 				struct timespec *ts1, struct timespec *ts2)
 {
-	unsigned int rate, sectors = bytes >> 9;
+	unsigned int rate, iops, sectors = bytes >> 9;
 	struct timespec ts;
 
 	ts = timespec_sub(*ts2, *ts1);
 
 	rate = mmc_test_rate(bytes, &ts);
+	iops = mmc_test_rate(100, &ts); /* I/O ops per sec x 100 */
 
 	printk(KERN_INFO "%s: Transfer of %u sectors (%u%s KiB) took %lu.%09lu "
-			 "seconds (%u kB/s, %u KiB/s)\n",
+			 "seconds (%u kB/s, %u KiB/s, %u.%02u IOPS)\n",
 			 mmc_hostname(test->card->host), sectors, sectors >> 1,
 			 (sectors & 1 ? ".5" : ""), (unsigned long)ts.tv_sec,
-			 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024);
+			 (unsigned long)ts.tv_nsec, rate / 1000, rate / 1024,
+			 iops / 100, iops % 100);
 
-	mmc_test_save_transfer_result(test, 1, sectors, ts, rate);
+	mmc_test_save_transfer_result(test, 1, sectors, ts, rate, iops);
 }
 
 /*
@@ -542,22 +548,24 @@
 				    unsigned int count, struct timespec *ts1,
 				    struct timespec *ts2)
 {
-	unsigned int rate, sectors = bytes >> 9;
+	unsigned int rate, iops, sectors = bytes >> 9;
 	uint64_t tot = bytes * count;
 	struct timespec ts;
 
 	ts = timespec_sub(*ts2, *ts1);
 
 	rate = mmc_test_rate(tot, &ts);
+	iops = mmc_test_rate(count * 100, &ts); /* I/O ops per sec x 100 */
 
 	printk(KERN_INFO "%s: Transfer of %u x %u sectors (%u x %u%s KiB) took "
-			 "%lu.%09lu seconds (%u kB/s, %u KiB/s)\n",
+			 "%lu.%09lu seconds (%u kB/s, %u KiB/s, "
+			 "%u.%02u IOPS)\n",
 			 mmc_hostname(test->card->host), count, sectors, count,
 			 sectors >> 1, (sectors & 1 ? ".5" : ""),
 			 (unsigned long)ts.tv_sec, (unsigned long)ts.tv_nsec,
-			 rate / 1000, rate / 1024);
+			 rate / 1000, rate / 1024, iops / 100, iops % 100);
 
-	mmc_test_save_transfer_result(test, count, sectors, ts, rate);
+	mmc_test_save_transfer_result(test, count, sectors, ts, rate, iops);
 }
 
 /*
@@ -1425,28 +1433,29 @@
 }
 
 /*
- * Initialize an area for testing large transfers.  The size of the area is the
- * preferred erase size which is a good size for optimal transfer speed.  Note
- * that is typically 4MiB for modern cards.  The test area is set to the middle
- * of the card because cards may have different charateristics at the front
- * (for FAT file system optimization).  Optionally, the area is erased (if the
- * card supports it) which may improve write performance.  Optionally, the area
- * is filled with data for subsequent read tests.
+ * Initialize an area for testing large transfers.  The test area is set to the
+ * middle of the card because cards may have different charateristics at the
+ * front (for FAT file system optimization).  Optionally, the area is erased
+ * (if the card supports it) which may improve write performance.  Optionally,
+ * the area is filled with data for subsequent read tests.
  */
 static int mmc_test_area_init(struct mmc_test_card *test, int erase, int fill)
 {
 	struct mmc_test_area *t = &test->area;
-	unsigned long min_sz = 64 * 1024;
+	unsigned long min_sz = 64 * 1024, sz;
 	int ret;
 
 	ret = mmc_test_set_blksize(test, 512);
 	if (ret)
 		return ret;
 
-	if (test->card->pref_erase > TEST_AREA_MAX_SIZE >> 9)
-		t->max_sz = TEST_AREA_MAX_SIZE;
-	else
-		t->max_sz = (unsigned long)test->card->pref_erase << 9;
+	/* Make the test area size about 4MiB */
+	sz = (unsigned long)test->card->pref_erase << 9;
+	t->max_sz = sz;
+	while (t->max_sz < 4 * 1024 * 1024)
+		t->max_sz += sz;
+	while (t->max_sz > TEST_AREA_MAX_SIZE && t->max_sz > sz)
+		t->max_sz -= sz;
 
 	t->max_segs = test->card->host->max_segs;
 	t->max_seg_sz = test->card->host->max_seg_size;
@@ -1766,6 +1775,187 @@
 	return 0;
 }
 
+static unsigned int rnd_next = 1;
+
+static unsigned int mmc_test_rnd_num(unsigned int rnd_cnt)
+{
+	uint64_t r;
+
+	rnd_next = rnd_next * 1103515245 + 12345;
+	r = (rnd_next >> 16) & 0x7fff;
+	return (r * rnd_cnt) >> 15;
+}
+
+static int mmc_test_rnd_perf(struct mmc_test_card *test, int write, int print,
+			     unsigned long sz)
+{
+	unsigned int dev_addr, cnt, rnd_addr, range1, range2, last_ea = 0, ea;
+	unsigned int ssz;
+	struct timespec ts1, ts2, ts;
+	int ret;
+
+	ssz = sz >> 9;
+
+	rnd_addr = mmc_test_capacity(test->card) / 4;
+	range1 = rnd_addr / test->card->pref_erase;
+	range2 = range1 / ssz;
+
+	getnstimeofday(&ts1);
+	for (cnt = 0; cnt < UINT_MAX; cnt++) {
+		getnstimeofday(&ts2);
+		ts = timespec_sub(ts2, ts1);
+		if (ts.tv_sec >= 10)
+			break;
+		ea = mmc_test_rnd_num(range1);
+		if (ea == last_ea)
+			ea -= 1;
+		last_ea = ea;
+		dev_addr = rnd_addr + test->card->pref_erase * ea +
+			   ssz * mmc_test_rnd_num(range2);
+		ret = mmc_test_area_io(test, sz, dev_addr, write, 0, 0);
+		if (ret)
+			return ret;
+	}
+	if (print)
+		mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+	return 0;
+}
+
+static int mmc_test_random_perf(struct mmc_test_card *test, int write)
+{
+	unsigned int next;
+	unsigned long sz;
+	int ret;
+
+	for (sz = 512; sz < test->area.max_tfr; sz <<= 1) {
+		/*
+		 * When writing, try to get more consistent results by running
+		 * the test twice with exactly the same I/O but outputting the
+		 * results only for the 2nd run.
+		 */
+		if (write) {
+			next = rnd_next;
+			ret = mmc_test_rnd_perf(test, write, 0, sz);
+			if (ret)
+				return ret;
+			rnd_next = next;
+		}
+		ret = mmc_test_rnd_perf(test, write, 1, sz);
+		if (ret)
+			return ret;
+	}
+	sz = test->area.max_tfr;
+	if (write) {
+		next = rnd_next;
+		ret = mmc_test_rnd_perf(test, write, 0, sz);
+		if (ret)
+			return ret;
+		rnd_next = next;
+	}
+	return mmc_test_rnd_perf(test, write, 1, sz);
+}
+
+/*
+ * Random read performance by transfer size.
+ */
+static int mmc_test_random_read_perf(struct mmc_test_card *test)
+{
+	return mmc_test_random_perf(test, 0);
+}
+
+/*
+ * Random write performance by transfer size.
+ */
+static int mmc_test_random_write_perf(struct mmc_test_card *test)
+{
+	return mmc_test_random_perf(test, 1);
+}
+
+static int mmc_test_seq_perf(struct mmc_test_card *test, int write,
+			     unsigned int tot_sz, int max_scatter)
+{
+	unsigned int dev_addr, i, cnt, sz, ssz;
+	struct timespec ts1, ts2;
+	int ret;
+
+	sz = test->area.max_tfr;
+	/*
+	 * In the case of a maximally scattered transfer, the maximum transfer
+	 * size is further limited by using PAGE_SIZE segments.
+	 */
+	if (max_scatter) {
+		struct mmc_test_area *t = &test->area;
+		unsigned long max_tfr;
+
+		if (t->max_seg_sz >= PAGE_SIZE)
+			max_tfr = t->max_segs * PAGE_SIZE;
+		else
+			max_tfr = t->max_segs * t->max_seg_sz;
+		if (sz > max_tfr)
+			sz = max_tfr;
+	}
+
+	ssz = sz >> 9;
+	dev_addr = mmc_test_capacity(test->card) / 4;
+	if (tot_sz > dev_addr << 9)
+		tot_sz = dev_addr << 9;
+	cnt = tot_sz / sz;
+	dev_addr &= 0xffff0000; /* Round to 64MiB boundary */
+
+	getnstimeofday(&ts1);
+	for (i = 0; i < cnt; i++) {
+		ret = mmc_test_area_io(test, sz, dev_addr, write,
+				       max_scatter, 0);
+		if (ret)
+			return ret;
+		dev_addr += ssz;
+	}
+	getnstimeofday(&ts2);
+
+	mmc_test_print_avg_rate(test, sz, cnt, &ts1, &ts2);
+
+	return 0;
+}
+
+static int mmc_test_large_seq_perf(struct mmc_test_card *test, int write)
+{
+	int ret, i;
+
+	for (i = 0; i < 10; i++) {
+		ret = mmc_test_seq_perf(test, write, 10 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < 5; i++) {
+		ret = mmc_test_seq_perf(test, write, 100 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+	for (i = 0; i < 3; i++) {
+		ret = mmc_test_seq_perf(test, write, 1000 * 1024 * 1024, 1);
+		if (ret)
+			return ret;
+	}
+
+	return ret;
+}
+
+/*
+ * Large sequential read performance.
+ */
+static int mmc_test_large_seq_read_perf(struct mmc_test_card *test)
+{
+	return mmc_test_large_seq_perf(test, 0);
+}
+
+/*
+ * Large sequential write performance.
+ */
+static int mmc_test_large_seq_write_perf(struct mmc_test_card *test)
+{
+	return mmc_test_large_seq_perf(test, 1);
+}
+
 static const struct mmc_test_case mmc_test_cases[] = {
 	{
 		.name = "Basic write (no data verification)",
@@ -2005,6 +2195,34 @@
 		.cleanup = mmc_test_area_cleanup,
 	},
 
+	{
+		.name = "Random read performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_random_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Random write performance by transfer size",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_random_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Large sequential read into scattered pages",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_large_seq_read_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
+	{
+		.name = "Large sequential write from scattered pages",
+		.prepare = mmc_test_area_prepare,
+		.run = mmc_test_large_seq_write_perf,
+		.cleanup = mmc_test_area_cleanup,
+	},
+
 };
 
 static DEFINE_MUTEX(mmc_test_lock);
@@ -2148,11 +2366,11 @@
 		seq_printf(sf, "Test %d: %d\n", gr->testcase + 1, gr->result);
 
 		list_for_each_entry(tr, &gr->tr_lst, link) {
-			seq_printf(sf, "%u %d %lu.%09lu %u\n",
+			seq_printf(sf, "%u %d %lu.%09lu %u %u.%02u\n",
 				tr->count, tr->sectors,
 				(unsigned long)tr->ts.tv_sec,
 				(unsigned long)tr->ts.tv_nsec,
-				tr->rate);
+				tr->rate, tr->iops / 100, tr->iops % 100);
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/card/queue.c linux-libre-2.6.39-gnu/drivers/mmc/card/queue.c
--- linux-libre-2.6.38-gnu/drivers/mmc/card/queue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/card/queue.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,8 +55,7 @@
 
 		spin_lock_irq(q->queue_lock);
 		set_current_state(TASK_INTERRUPTIBLE);
-		if (!blk_queue_plugged(q))
-			req = blk_fetch_request(q);
+		req = blk_fetch_request(q);
 		mq->req = req;
 		spin_unlock_irq(q->queue_lock);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/card/sdio_uart.c linux-libre-2.6.39-gnu/drivers/mmc/card/sdio_uart.c
--- linux-libre-2.6.38-gnu/drivers/mmc/card/sdio_uart.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/card/sdio_uart.c	2011-05-19 00:06:34.000000000 -0400
@@ -956,7 +956,7 @@
 	return 0;
 }
 
-static int sdio_uart_tiocmget(struct tty_struct *tty, struct file *file)
+static int sdio_uart_tiocmget(struct tty_struct *tty)
 {
 	struct sdio_uart_port *port = tty->driver_data;
 	int result;
@@ -970,7 +970,7 @@
 	return result;
 }
 
-static int sdio_uart_tiocmset(struct tty_struct *tty, struct file *file,
+static int sdio_uart_tiocmset(struct tty_struct *tty,
 			      unsigned int set, unsigned int clear)
 {
 	struct sdio_uart_port *port = tty->driver_data;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/bus.c linux-libre-2.6.39-gnu/drivers/mmc/core/bus.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/bus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/bus.c	2011-05-19 00:06:34.000000000 -0400
@@ -284,6 +284,7 @@
 		type = "SD-combo";
 		if (mmc_card_blockaddr(card))
 			type = "SDHC-combo";
+		break;
 	default:
 		type = "?";
 		break;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/core.c linux-libre-2.6.39-gnu/drivers/mmc/core/core.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,8 +167,6 @@
 
 	WARN_ON(!host->claimed);
 
-	led_trigger_event(host->led, LED_FULL);
-
 	mrq->cmd->error = 0;
 	mrq->cmd->mrq = mrq;
 	if (mrq->data) {
@@ -194,6 +192,7 @@
 		}
 	}
 	mmc_host_clk_ungate(host);
+	led_trigger_event(host->led, LED_FULL);
 	host->ops->request(host, mrq);
 }
 
@@ -528,7 +527,14 @@
 }
 EXPORT_SYMBOL(mmc_try_claim_host);
 
-static void mmc_do_release_host(struct mmc_host *host)
+/**
+ *	mmc_do_release_host - release a claimed host
+ *	@host: mmc host to release
+ *
+ *	If you successfully claimed a host, this function will
+ *	release it again.
+ */
+void mmc_do_release_host(struct mmc_host *host)
 {
 	unsigned long flags;
 
@@ -543,6 +549,7 @@
 		wake_up(&host->wq);
 	}
 }
+EXPORT_SYMBOL(mmc_do_release_host);
 
 void mmc_host_deeper_disable(struct work_struct *work)
 {
@@ -1002,6 +1009,13 @@
 {
 	host->ios.clock = 0;
 	host->ios.vdd = 0;
+
+	/*
+	 * Reset ocr mask to be the highest possible voltage supported for
+	 * this mmc host. This value will be used at next power up.
+	 */
+	host->ocr = 1 << (fls(host->ocr_avail) - 1);
+
 	if (!mmc_host_is_spi(host)) {
 		host->ios.bus_mode = MMC_BUSMODE_OPENDRAIN;
 		host->ios.chip_select = MMC_CS_DONTCARE;
@@ -1495,6 +1509,12 @@
 		mmc_hostname(host), __func__, host->f_init);
 #endif
 	mmc_power_up(host);
+
+	/*
+	 * sdio_reset sends CMD52 to reset card.  Since we do not know
+	 * if the card is being re-initialized, just send it.  CMD52
+	 * should be ignored by SD/eMMC cards.
+	 */
 	sdio_reset(host);
 	mmc_go_idle(host);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/core.h linux-libre-2.6.39-gnu/drivers/mmc/core/core.h
--- linux-libre-2.6.38-gnu/drivers/mmc/core/core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/core.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,8 @@
 int mmc_attach_sd(struct mmc_host *host);
 int mmc_attach_sdio(struct mmc_host *host);
 
+void mmc_fixup_device(struct mmc_card *card);
+
 /* Module parameters */
 extern int use_spi_crc;
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/host.c linux-libre-2.6.39-gnu/drivers/mmc/core/host.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/host.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/host.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,10 +160,7 @@
 	 * gate the clock, because there is somebody out there that may still
 	 * be using it.
 	 */
-	if (mmc_card_sdio(card))
-		return false;
-
-	return true;
+	return !(card->quirks & MMC_QUIRK_BROKEN_CLK_GATING);
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/Makefile linux-libre-2.6.39-gnu/drivers/mmc/core/Makefile
--- linux-libre-2.6.38-gnu/drivers/mmc/core/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
 mmc_core-y			:= core.o bus.o host.o \
 				   mmc.o mmc_ops.o sd.o sd_ops.o \
 				   sdio.o sdio_ops.o sdio_bus.o \
-				   sdio_cis.o sdio_io.o sdio_irq.o
+				   sdio_cis.o sdio_io.o sdio_irq.o \
+				   quirks.o
 
 mmc_core-$(CONFIG_DEBUG_FS)	+= debugfs.o
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/mmc.c linux-libre-2.6.39-gnu/drivers/mmc/core/mmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/mmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -302,6 +302,44 @@
 	}
 
 	if (card->ext_csd.rev >= 4) {
+		/*
+		 * Enhanced area feature support -- check whether the eMMC
+		 * card has the Enhanced area enabled.  If so, export enhanced
+		 * area offset and size to user by adding sysfs interface.
+		 */
+		if ((ext_csd[EXT_CSD_PARTITION_SUPPORT] & 0x2) &&
+				(ext_csd[EXT_CSD_PARTITION_ATTRIBUTE] & 0x1)) {
+			u8 hc_erase_grp_sz =
+				ext_csd[EXT_CSD_HC_ERASE_GRP_SIZE];
+			u8 hc_wp_grp_sz =
+				ext_csd[EXT_CSD_HC_WP_GRP_SIZE];
+
+			card->ext_csd.enhanced_area_en = 1;
+			/*
+			 * calculate the enhanced data area offset, in bytes
+			 */
+			card->ext_csd.enhanced_area_offset =
+				(ext_csd[139] << 24) + (ext_csd[138] << 16) +
+				(ext_csd[137] << 8) + ext_csd[136];
+			if (mmc_card_blockaddr(card))
+				card->ext_csd.enhanced_area_offset <<= 9;
+			/*
+			 * calculate the enhanced data area size, in kilobytes
+			 */
+			card->ext_csd.enhanced_area_size =
+				(ext_csd[142] << 16) + (ext_csd[141] << 8) +
+				ext_csd[140];
+			card->ext_csd.enhanced_area_size *=
+				(size_t)(hc_erase_grp_sz * hc_wp_grp_sz);
+			card->ext_csd.enhanced_area_size <<= 9;
+		} else {
+			/*
+			 * If the enhanced area is not enabled, disable these
+			 * device attributes.
+			 */
+			card->ext_csd.enhanced_area_offset = -EINVAL;
+			card->ext_csd.enhanced_area_size = -EINVAL;
+		}
 		card->ext_csd.sec_trim_mult =
 			ext_csd[EXT_CSD_SEC_TRIM_MULT];
 		card->ext_csd.sec_erase_mult =
@@ -336,6 +374,9 @@
 MMC_DEV_ATTR(name, "%s\n", card->cid.prod_name);
 MMC_DEV_ATTR(oemid, "0x%04x\n", card->cid.oemid);
 MMC_DEV_ATTR(serial, "0x%08x\n", card->cid.serial);
+MMC_DEV_ATTR(enhanced_area_offset, "%llu\n",
+		card->ext_csd.enhanced_area_offset);
+MMC_DEV_ATTR(enhanced_area_size, "%u\n", card->ext_csd.enhanced_area_size);
 
 static struct attribute *mmc_std_attrs[] = {
 	&dev_attr_cid.attr,
@@ -349,6 +390,8 @@
 	&dev_attr_name.attr,
 	&dev_attr_oemid.attr,
 	&dev_attr_serial.attr,
+	&dev_attr_enhanced_area_offset.attr,
+	&dev_attr_enhanced_area_size.attr,
 	NULL,
 };
 
@@ -378,6 +421,7 @@
 	int err, ddr = 0;
 	u32 cid[4];
 	unsigned int max_dtr;
+	u32 rocr;
 
 	BUG_ON(!host);
 	WARN_ON(!host->claimed);
@@ -391,7 +435,7 @@
 	mmc_go_idle(host);
 
 	/* The extra bit indicates that we support high capacity */
-	err = mmc_send_op_cond(host, ocr | (1 << 30), NULL);
+	err = mmc_send_op_cond(host, ocr | (1 << 30), &rocr);
 	if (err)
 		goto err;
 
@@ -479,11 +523,51 @@
 		err = mmc_read_ext_csd(card);
 		if (err)
 			goto free_card;
+
+		/* If doing byte addressing, check if required to do sector
+		 * addressing.  Handle the case of <2GB cards needing sector
+		 * addressing.  See section 8.1 JEDEC Standard JED84-A441;
+		 * ocr register has bit 30 set for sector addressing.
+		 */
+		if (!(mmc_card_blockaddr(card)) && (rocr & (1<<30)))
+			mmc_card_set_blockaddr(card);
+
 		/* Erase size depends on CSD and Extended CSD */
 		mmc_set_erase_size(card);
 	}
 
 	/*
+	 * If enhanced_area_en is TRUE, host needs to enable ERASE_GRP_DEF
+	 * bit.  This bit will be lost every time after a reset or power off.
+	 */
+	if (card->ext_csd.enhanced_area_en) {
+		err = mmc_switch(card, EXT_CSD_CMD_SET_NORMAL,
+				EXT_CSD_ERASE_GROUP_DEF, 1);
+
+		if (err && err != -EBADMSG)
+			goto free_card;
+
+		if (err) {
+			err = 0;
+			/*
+			 * Just disable enhanced area off & sz
+			 * will try to enable ERASE_GROUP_DEF
+			 * during next time reinit
+			 */
+			card->ext_csd.enhanced_area_offset = -EINVAL;
+			card->ext_csd.enhanced_area_size = -EINVAL;
+		} else {
+			card->ext_csd.erase_group_def = 1;
+			/*
+			 * enable ERASE_GRP_DEF successfully.
+			 * This will affect the erase size, so
+			 * here need to reset erase size
+			 */
+			mmc_set_erase_size(card);
+		}
+	}
+
+	/*
 	 * Activate high speed (if supported)
 	 */
 	if ((card->ext_csd.hs_max_dtr != 0) &&
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/mmc_ops.c linux-libre-2.6.39-gnu/drivers/mmc/core/mmc_ops.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/mmc_ops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/mmc_ops.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,7 +105,7 @@
 	 * that in case of hardware that won't pull up DAT3/nCS otherwise.
 	 *
 	 * SPI hosts ignore ios.chip_select; it's managed according to
-	 * rules that must accomodate non-MMC slaves which this layer
+	 * rules that must accommodate non-MMC slaves which this layer
 	 * won't even know about.
 	 */
 	if (!mmc_host_is_spi(host)) {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/quirks.c linux-libre-2.6.39-gnu/drivers/mmc/core/quirks.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/quirks.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/quirks.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,84 @@
+/*
+ *  This file contains work-arounds for many known sdio hardware
+ *  bugs.
+ *
+ *  Copyright (c) 2011 Pierre Tardy <tardyp@gmail.com>
+ *  Inspired from pci fixup code:
+ *  Copyright (c) 1999 Martin Mares <mj@ucw.cz>
+ *
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/mmc/card.h>
+#include <linux/mod_devicetable.h>
+
+/*
+ *  The world is not perfect and supplies us with broken mmc/sdio devices.
+ *  For at least a part of these bugs we need a work-around
+ */
+
+struct mmc_fixup {
+	u16 vendor, device;	/* You can use SDIO_ANY_ID here of course */
+	void (*vendor_fixup)(struct mmc_card *card, int data);
+	int data;
+};
+
+/*
+ * This hook just adds a quirk unconditionnally
+ */
+static void __maybe_unused add_quirk(struct mmc_card *card, int data)
+{
+	card->quirks |= data;
+}
+
+/*
+ * This hook just removes a quirk unconditionnally
+ */
+static void __maybe_unused remove_quirk(struct mmc_card *card, int data)
+{
+	card->quirks &= ~data;
+}
+
+/*
+ * This hook just adds a quirk for all sdio devices
+ */
+static void add_quirk_for_sdio_devices(struct mmc_card *card, int data)
+{
+	if (mmc_card_sdio(card))
+		card->quirks |= data;
+}
+
+#ifndef SDIO_VENDOR_ID_TI
+#define SDIO_VENDOR_ID_TI		0x0097
+#endif
+
+#ifndef SDIO_DEVICE_ID_TI_WL1271
+#define SDIO_DEVICE_ID_TI_WL1271	0x4076
+#endif
+
+static const struct mmc_fixup mmc_fixup_methods[] = {
+	/* by default sdio devices are considered CLK_GATING broken */
+	/* good cards will be whitelisted as they are tested */
+	{ SDIO_ANY_ID, SDIO_ANY_ID,
+		add_quirk_for_sdio_devices, MMC_QUIRK_BROKEN_CLK_GATING },
+	{ SDIO_VENDOR_ID_TI, SDIO_DEVICE_ID_TI_WL1271,
+		remove_quirk, MMC_QUIRK_BROKEN_CLK_GATING },
+	{ 0 }
+};
+
+void mmc_fixup_device(struct mmc_card *card)
+{
+	const struct mmc_fixup *f;
+
+	for (f = mmc_fixup_methods; f->vendor_fixup; f++) {
+		if ((f->vendor == card->cis.vendor
+		     || f->vendor == (u16) SDIO_ANY_ID) &&
+		    (f->device == card->cis.device
+		     || f->device == (u16) SDIO_ANY_ID)) {
+			dev_dbg(&card->dev, "calling %pF\n", f->vendor_fixup);
+			f->vendor_fixup(card, f->data);
+		}
+	}
+}
+EXPORT_SYMBOL(mmc_fixup_device);
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/sd.c linux-libre-2.6.39-gnu/drivers/mmc/core/sd.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/sd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/sd.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,7 @@
 #include "core.h"
 #include "bus.h"
 #include "mmc_ops.h"
+#include "sd.h"
 #include "sd_ops.h"
 
 static const unsigned int tran_exp[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/sdio.c linux-libre-2.6.39-gnu/drivers/mmc/core/sdio.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/sdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/sdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -395,6 +395,14 @@
 		if (err)
 			goto remove;
 
+		/*
+		 * Update oldcard with the new RCA received from the SDIO
+		 * device -- we're doing this so that it's updated in the
+		 * "card" struct when oldcard overwrites that later.
+		 */
+		if (oldcard)
+			oldcard->rca = card->rca;
+
 		mmc_set_bus_mode(host, MMC_BUSMODE_PUSHPULL);
 	}
 
@@ -458,6 +466,7 @@
 
 		card = oldcard;
 	}
+	mmc_fixup_device(card);
 
 	if (card->type == MMC_TYPE_SD_COMBO) {
 		err = mmc_sd_setup_card(host, card, oldcard != NULL);
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/sdio_irq.c linux-libre-2.6.39-gnu/drivers/mmc/core/sdio_irq.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/sdio_irq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/sdio_irq.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 			struct sdio_func *func = card->sdio_func[i - 1];
 			if (!func) {
 				printk(KERN_WARNING "%s: pending IRQ for "
-					"non-existant function\n",
+					"non-existent function\n",
 					mmc_card_id(card));
 				ret = -EINVAL;
 			} else if (func->irq_handler) {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/core/sd_ops.c linux-libre-2.6.39-gnu/drivers/mmc/core/sd_ops.c
--- linux-libre-2.6.38-gnu/drivers/mmc/core/sd_ops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/core/sd_ops.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
  * your option) any later version.
  */
 
+#include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/scatterlist.h>
 
@@ -252,6 +253,7 @@
 	struct mmc_command cmd;
 	struct mmc_data data;
 	struct scatterlist sg;
+	void *data_buf;
 
 	BUG_ON(!card);
 	BUG_ON(!card->host);
@@ -263,6 +265,13 @@
 	if (err)
 		return err;
 
+	/* dma onto stack is unsafe/nonportable, but callers to this
+	 * routine normally provide temporary on-stack buffers ...
+	 */
+	data_buf = kmalloc(sizeof(card->raw_scr), GFP_KERNEL);
+	if (data_buf == NULL)
+		return -ENOMEM;
+
 	memset(&mrq, 0, sizeof(struct mmc_request));
 	memset(&cmd, 0, sizeof(struct mmc_command));
 	memset(&data, 0, sizeof(struct mmc_data));
@@ -280,12 +289,15 @@
 	data.sg = &sg;
 	data.sg_len = 1;
 
-	sg_init_one(&sg, scr, 8);
+	sg_init_one(&sg, data_buf, 8);
 
 	mmc_set_data_timeout(&data, card);
 
 	mmc_wait_for_req(card->host, &mrq);
 
+	memcpy(scr, data_buf, sizeof(card->raw_scr));
+	kfree(data_buf);
+
 	if (cmd.error)
 		return cmd.error;
 	if (data.error)
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/atmel-mci.c linux-libre-2.6.39-gnu/drivers/mmc/host/atmel-mci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/atmel-mci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/atmel-mci.c	2011-05-19 00:06:34.000000000 -0400
@@ -127,7 +127,7 @@
  * EVENT_DATA_COMPLETE is set in @pending_events, all data-related
  * interrupts must be disabled and @data_status updated with a
  * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the
- * CMDRDY interupt must be disabled and @cmd_status updated with a
+ * CMDRDY interrupt must be disabled and @cmd_status updated with a
  * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the
  * bytes_xfered field of @data must be written. This is ensured by
  * using barriers.
@@ -578,7 +578,8 @@
 	struct mmc_data			*data = host->data;
 
 	if (data)
-		dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len,
+		dma_unmap_sg(host->dma.chan->device->dev,
+			     data->sg, data->sg_len,
 			     ((data->flags & MMC_DATA_WRITE)
 			      ? DMA_TO_DEVICE : DMA_FROM_DEVICE));
 }
@@ -588,7 +589,7 @@
 	struct dma_chan *chan = host->data_chan;
 
 	if (chan) {
-	  chan->device->device_control(chan, DMA_TERMINATE_ALL, 0);
+		dmaengine_terminate_all(chan);
 		atmci_dma_cleanup(host);
 	} else {
 		/* Data transfer was stopped by the interrupt handler */
@@ -684,11 +685,11 @@
 	else
 		direction = DMA_TO_DEVICE;
 
-	sglen = dma_map_sg(&host->pdev->dev, data->sg, data->sg_len, direction);
-	if (sglen != data->sg_len)
-		goto unmap_exit;
+	sglen = dma_map_sg(chan->device->dev, data->sg,
+			   data->sg_len, direction);
+
 	desc = chan->device->device_prep_slave_sg(chan,
-			data->sg, data->sg_len, direction,
+			data->sg, sglen, direction,
 			DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	if (!desc)
 		goto unmap_exit;
@@ -699,7 +700,7 @@
 
 	return 0;
 unmap_exit:
-	dma_unmap_sg(&host->pdev->dev, data->sg, sglen, direction);
+	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, direction);
 	return -ENOMEM;
 }
 
@@ -709,8 +710,8 @@
 	struct dma_async_tx_descriptor	*desc = host->dma.data_desc;
 
 	if (chan) {
-		desc->tx_submit(desc);
-		chan->device->device_issue_pending(chan);
+		dmaengine_submit(desc);
+		dma_async_issue_pending(chan);
 	}
 }
 
@@ -1081,7 +1082,7 @@
 	/*
 	 * Update the MMC clock rate if necessary. This may be
 	 * necessary if set_ios() is called when a different slot is
-	 * busy transfering data.
+	 * busy transferring data.
 	 */
 	if (host->need_clock_update) {
 		mci_writel(host, MR, host->mode_reg);
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/cb710-mmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/cb710-mmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/cb710-mmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/cb710-mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -205,7 +205,7 @@
 			"WAIT12: waited %d loops, mask %02X, entry val %08X, exit val %08X\n",
 			limit, mask, e, x);
 #endif
-	return 0;
+	return err;
 }
 
 static void cb710_mmc_set_transfer_size(struct cb710_slot *slot,
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/dw_mmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/dw_mmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/dw_mmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/dw_mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include <linux/mmc/mmc.h>
 #include <linux/mmc/dw_mmc.h>
 #include <linux/bitops.h>
+#include <linux/regulator/consumer.h>
 
 #include "dw_mmc.h"
 
@@ -315,7 +316,7 @@
 
 	/* Stop the IDMAC running */
 	temp = mci_readl(host, BMOD);
-	temp &= ~SDMMC_IDMAC_ENABLE;
+	temp &= ~(SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB);
 	mci_writel(host, BMOD, temp);
 }
 
@@ -384,7 +385,7 @@
 
 	/* Enable the IDMAC */
 	temp = mci_readl(host, BMOD);
-	temp |= SDMMC_IDMAC_ENABLE;
+	temp |= SDMMC_IDMAC_ENABLE | SDMMC_IDMAC_FB;
 	mci_writel(host, BMOD, temp);
 
 	/* Start it running */
@@ -562,7 +563,8 @@
 			     SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
 
 		/* enable clock */
-		mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE);
+		mci_writel(host, CLKENA, SDMMC_CLKEN_ENABLE |
+			   SDMMC_CLKEN_LOW_PWR);
 
 		/* inform CIU */
 		mci_send_cmd(slot,
@@ -661,6 +663,7 @@
 static void dw_mci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct dw_mci_slot *slot = mmc_priv(mmc);
+	u32 regs;
 
 	/* set default 1 bit mode */
 	slot->ctype = SDMMC_CTYPE_1BIT;
@@ -672,6 +675,16 @@
 	case MMC_BUS_WIDTH_4:
 		slot->ctype = SDMMC_CTYPE_4BIT;
 		break;
+	case MMC_BUS_WIDTH_8:
+		slot->ctype = SDMMC_CTYPE_8BIT;
+		break;
+	}
+
+	/* DDR mode set */
+	if (ios->ddr) {
+		regs = mci_readl(slot->host, UHS_REG);
+		regs |= (0x1 << slot->id) << 16;
+		mci_writel(slot->host, UHS_REG, regs);
 	}
 
 	if (ios->clock) {
@@ -717,7 +730,9 @@
 	struct dw_mci_board *brd = slot->host->pdata;
 
 	/* Use platform get_cd function, else try onboard card detect */
-	if (brd->get_cd)
+	if (brd->quirks & DW_MCI_QUIRK_BROKEN_CARD_DETECTION)
+		present = 1;
+	else if (brd->get_cd)
 		present = !brd->get_cd(slot->id);
 	else
 		present = (mci_readl(slot->host, CDETECT) & (1 << slot->id))
@@ -1019,13 +1034,10 @@
 	struct mmc_data	*data = host->data;
 	int shift = host->data_shift;
 	u32 status;
-	unsigned int nbytes = 0, len, old_len, count = 0;
+	unsigned int nbytes = 0, len;
 
 	do {
 		len = SDMMC_GET_FCNT(mci_readl(host, STATUS)) << shift;
-		if (count == 0)
-			old_len = len;
-
 		if (offset + len <= sg->length) {
 			host->pull_data(host, (void *)(buf + offset), len);
 
@@ -1070,7 +1082,6 @@
 			tasklet_schedule(&host->tasklet);
 			return;
 		}
-		count++;
 	} while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
 	len = SDMMC_GET_FCNT(mci_readl(host, STATUS));
 	host->pio_offset = offset;
@@ -1395,7 +1406,11 @@
 	if (host->pdata->setpower)
 		host->pdata->setpower(id, 0);
 
-	mmc->caps = 0;
+	if (host->pdata->caps)
+		mmc->caps = host->pdata->caps;
+	else
+		mmc->caps = 0;
+
 	if (host->pdata->get_bus_wd)
 		if (host->pdata->get_bus_wd(slot->id) >= 4)
 			mmc->caps |= MMC_CAP_4_BIT_DATA;
@@ -1426,6 +1441,13 @@
 	}
 #endif /* CONFIG_MMC_DW_IDMAC */
 
+	host->vmmc = regulator_get(mmc_dev(mmc), "vmmc");
+	if (IS_ERR(host->vmmc)) {
+		printk(KERN_INFO "%s: no vmmc regulator found\n", mmc_hostname(mmc));
+		host->vmmc = NULL;
+	} else
+		regulator_enable(host->vmmc);
+
 	if (dw_mci_get_cd(mmc))
 		set_bit(DW_MMC_CARD_PRESENT, &slot->flags);
 	else
@@ -1441,6 +1463,12 @@
 	/* Card initially undetected */
 	slot->last_detect_state = 0;
 
+	/*
+	 * Card may have been plugged in prior to boot so we
+	 * need to run the detect tasklet
+	 */
+	tasklet_schedule(&host->card_tasklet);
+
 	return 0;
 }
 
@@ -1619,8 +1647,9 @@
 	 */
 	fifo_size = mci_readl(host, FIFOTH);
 	fifo_size = (fifo_size >> 16) & 0x7ff;
-	mci_writel(host, FIFOTH, ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
-				  ((fifo_size/2) << 0)));
+	host->fifoth_val = ((0x2 << 28) | ((fifo_size/2 - 1) << 16) |
+			((fifo_size/2) << 0));
+	mci_writel(host, FIFOTH, host->fifoth_val);
 
 	/* disable clock to CIU */
 	mci_writel(host, CLKENA, 0);
@@ -1683,6 +1712,12 @@
 			  host->sg_cpu, host->sg_dma);
 	iounmap(host->regs);
 
+	if (host->vmmc) {
+		regulator_disable(host->vmmc);
+		regulator_put(host->vmmc);
+	}
+
+
 err_freehost:
 	kfree(host);
 	return ret;
@@ -1714,6 +1749,11 @@
 	if (host->use_dma && host->dma_ops->exit)
 		host->dma_ops->exit(host);
 
+	if (host->vmmc) {
+		regulator_disable(host->vmmc);
+		regulator_put(host->vmmc);
+	}
+
 	iounmap(host->regs);
 
 	kfree(host);
@@ -1729,6 +1769,9 @@
 	int i, ret;
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
+	if (host->vmmc)
+		regulator_enable(host->vmmc);
+
 	for (i = 0; i < host->num_slots; i++) {
 		struct dw_mci_slot *slot = host->slot[i];
 		if (!slot)
@@ -1744,6 +1787,9 @@
 		}
 	}
 
+	if (host->vmmc)
+		regulator_disable(host->vmmc);
+
 	return 0;
 }
 
@@ -1752,6 +1798,23 @@
 	int i, ret;
 	struct dw_mci *host = platform_get_drvdata(pdev);
 
+	if (host->dma_ops->init)
+		host->dma_ops->init(host);
+
+	if (!mci_wait_reset(&pdev->dev, host)) {
+		ret = -ENODEV;
+		return ret;
+	}
+
+	/* Restore the old value at FIFOTH register */
+	mci_writel(host, FIFOTH, host->fifoth_val);
+
+	mci_writel(host, RINTSTS, 0xFFFFFFFF);
+	mci_writel(host, INTMASK, SDMMC_INT_CMD_DONE | SDMMC_INT_DATA_OVER |
+		   SDMMC_INT_TXDR | SDMMC_INT_RXDR |
+		   DW_MCI_ERROR_FLAGS | SDMMC_INT_CD);
+	mci_writel(host, CTRL, SDMMC_CTRL_INT_ENABLE);
+
 	for (i = 0; i < host->num_slots; i++) {
 		struct dw_mci_slot *slot = host->slot[i];
 		if (!slot)
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/dw_mmc.h linux-libre-2.6.39-gnu/drivers/mmc/host/dw_mmc.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/dw_mmc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/dw_mmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,7 @@
 #define SDMMC_USRID		0x068
 #define SDMMC_VERID		0x06c
 #define SDMMC_HCON		0x070
+#define SDMMC_UHS_REG		0x074
 #define SDMMC_BMOD		0x080
 #define SDMMC_PLDMND		0x084
 #define SDMMC_DBADDR		0x088
@@ -51,7 +52,6 @@
 #define SDMMC_DSCADDR		0x094
 #define SDMMC_BUFADDR		0x098
 #define SDMMC_DATA		0x100
-#define SDMMC_DATA_ADR		0x100
 
 /* shift bit field */
 #define _SBF(f, v)		((v) << (f))
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/Kconfig linux-libre-2.6.39-gnu/drivers/mmc/host/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mmc/host/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -225,7 +225,7 @@
 
 config MMC_OMAP_HS
 	tristate "TI OMAP High Speed Multimedia Card Interface support"
-	depends on ARCH_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
+	depends on SOC_OMAP2430 || ARCH_OMAP3 || ARCH_OMAP4
 	help
 	  This selects the TI OMAP High Speed Multimedia card Interface.
 	  If you have an OMAP2430 or OMAP3 board or OMAP4 board with a
@@ -311,7 +311,7 @@
 
 config MMC_MXC
 	tristate "Freescale i.MX2/3 Multimedia Card Interface support"
-	depends on ARCH_MXC
+	depends on MACH_MX21 || MACH_MX27 || ARCH_MX31
 	help
 	  This selects the Freescale i.MX2/3 Multimedia card Interface.
 	  If you have a i.MX platform with a Multimedia Card slot,
@@ -319,6 +319,15 @@
 
 	  If unsure, say N.
 
+config MMC_MXS
+	tristate "Freescale MXS Multimedia Card Interface support"
+	depends on ARCH_MXS && MXS_DMA
+	help
+	  This selects the Freescale SSP MMC controller found on MXS based
+	  platforms like mx23/28.
+
+	  If unsure, say N.
+
 config MMC_TIFM_SD
 	tristate "TI Flash Media MMC/SD Interface support  (EXPERIMENTAL)"
 	depends on EXPERIMENTAL && PCI
@@ -430,13 +439,25 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called sdricoh_cs.
 
+config MMC_TMIO_CORE
+	tristate
+
 config MMC_TMIO
 	tristate "Toshiba Mobile IO Controller (TMIO) MMC/SD function support"
-	depends on MFD_TMIO || MFD_ASIC3 || MFD_SH_MOBILE_SDHI
+	depends on MFD_TMIO || MFD_ASIC3
+	select MMC_TMIO_CORE
 	help
 	  This provides support for the SD/MMC cell found in TC6393XB,
 	  T7L66XB and also HTC ASIC3
 
+config MMC_SDHI
+	tristate "SH-Mobile SDHI SD/SDIO controller support"
+	depends on SUPERH || ARCH_SHMOBILE
+	select MMC_TMIO_CORE
+	help
+	  This provides support for the SDHI SD/SDIO controller found in
+	  SuperH and ARM SH-Mobile SoCs
+
 config MMC_CB710
 	tristate "ENE CB710 MMC/SD Interface support"
 	depends on PCI
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/Makefile linux-libre-2.6.39-gnu/drivers/mmc/host/Makefile
--- linux-libre-2.6.38-gnu/drivers/mmc/host/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,7 @@
 obj-$(CONFIG_MMC_PXA)		+= pxamci.o
 obj-$(CONFIG_MMC_IMX)		+= imxmmc.o
 obj-$(CONFIG_MMC_MXC)		+= mxcmmc.o
+obj-$(CONFIG_MMC_MXS)		+= mxs-mmc.o
 obj-$(CONFIG_MMC_SDHCI)		+= sdhci.o
 obj-$(CONFIG_MMC_SDHCI_PCI)	+= sdhci-pci.o
 obj-$(CONFIG_MMC_SDHCI_PXA)	+= sdhci-pxa.o
@@ -28,7 +29,13 @@
 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_TMIO_CORE)	+= tmio_mmc_core.o
+tmio_mmc_core-y			:= tmio_mmc_pio.o
+ifneq ($(CONFIG_MMC_SDHI),n)
+tmio_mmc_core-y			+= tmio_mmc_dma.o
+endif
+obj-$(CONFIG_MMC_SDHI)		+= sh_mobile_sdhi.o
+obj-$(CONFIG_MMC_CB710)		+= cb710-mmc.o
 obj-$(CONFIG_MMC_VIA_SDMMC)	+= via-sdmmc.o
 obj-$(CONFIG_SDH_BFIN)		+= bfin_sdh.o
 obj-$(CONFIG_MMC_DW)		+= dw_mmc.o
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/mmci.c linux-libre-2.6.39-gnu/drivers/mmc/host/mmci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/mmci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/mmci.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  *  linux/drivers/mmc/host/mmci.c - ARM PrimeCell MMCI PL180/1 driver
  *
  *  Copyright (C) 2003 Deep Blue Solutions, Ltd, All Rights Reserved.
- *  Copyright (C) 2010 ST-Ericsson AB.
+ *  Copyright (C) 2010 ST-Ericsson SA
  *
  * 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
@@ -25,8 +25,10 @@
 #include <linux/clk.h>
 #include <linux/scatterlist.h>
 #include <linux/gpio.h>
-#include <linux/amba/mmci.h>
 #include <linux/regulator/consumer.h>
+#include <linux/dmaengine.h>
+#include <linux/dma-mapping.h>
+#include <linux/amba/mmci.h>
 
 #include <asm/div64.h>
 #include <asm/io.h>
@@ -66,6 +68,12 @@
 	.datalength_bits	= 16,
 };
 
+static struct variant_data variant_arm_extended_fifo = {
+	.fifosize		= 128 * 4,
+	.fifohalfsize		= 64 * 4,
+	.datalength_bits	= 16,
+};
+
 static struct variant_data variant_u300 = {
 	.fifosize		= 16 * 4,
 	.fifohalfsize		= 8 * 4,
@@ -142,9 +150,6 @@
 	host->mrq = NULL;
 	host->cmd = NULL;
 
-	if (mrq->data)
-		mrq->data->bytes_xfered = host->data_xfered;
-
 	/*
 	 * Need to drop the host lock here; mmc_request_done may call
 	 * back into the driver...
@@ -189,6 +194,248 @@
 	sg_miter_start(&host->sg_miter, data->sg, data->sg_len, flags);
 }
 
+/*
+ * All the DMA operation mode stuff goes inside this ifdef.
+ * This assumes that you have a generic DMA device interface,
+ * no custom DMA interfaces are supported.
+ */
+#ifdef CONFIG_DMA_ENGINE
+static void __devinit mmci_dma_setup(struct mmci_host *host)
+{
+	struct mmci_platform_data *plat = host->plat;
+	const char *rxname, *txname;
+	dma_cap_mask_t mask;
+
+	if (!plat || !plat->dma_filter) {
+		dev_info(mmc_dev(host->mmc), "no DMA platform data\n");
+		return;
+	}
+
+	/* Try to acquire a generic DMA engine slave channel */
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+
+	/*
+	 * If only an RX channel is specified, the driver will
+	 * attempt to use it bidirectionally, however if it is
+	 * is specified but cannot be located, DMA will be disabled.
+	 */
+	if (plat->dma_rx_param) {
+		host->dma_rx_channel = dma_request_channel(mask,
+							   plat->dma_filter,
+							   plat->dma_rx_param);
+		/* E.g if no DMA hardware is present */
+		if (!host->dma_rx_channel)
+			dev_err(mmc_dev(host->mmc), "no RX DMA channel\n");
+	}
+
+	if (plat->dma_tx_param) {
+		host->dma_tx_channel = dma_request_channel(mask,
+							   plat->dma_filter,
+							   plat->dma_tx_param);
+		if (!host->dma_tx_channel)
+			dev_warn(mmc_dev(host->mmc), "no TX DMA channel\n");
+	} else {
+		host->dma_tx_channel = host->dma_rx_channel;
+	}
+
+	if (host->dma_rx_channel)
+		rxname = dma_chan_name(host->dma_rx_channel);
+	else
+		rxname = "none";
+
+	if (host->dma_tx_channel)
+		txname = dma_chan_name(host->dma_tx_channel);
+	else
+		txname = "none";
+
+	dev_info(mmc_dev(host->mmc), "DMA channels RX %s, TX %s\n",
+		 rxname, txname);
+
+	/*
+	 * Limit the maximum segment size in any SG entry according to
+	 * the parameters of the DMA engine device.
+	 */
+	if (host->dma_tx_channel) {
+		struct device *dev = host->dma_tx_channel->device->dev;
+		unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+		if (max_seg_size < host->mmc->max_seg_size)
+			host->mmc->max_seg_size = max_seg_size;
+	}
+	if (host->dma_rx_channel) {
+		struct device *dev = host->dma_rx_channel->device->dev;
+		unsigned int max_seg_size = dma_get_max_seg_size(dev);
+
+		if (max_seg_size < host->mmc->max_seg_size)
+			host->mmc->max_seg_size = max_seg_size;
+	}
+}
+
+/*
+ * This is used in __devinit or __devexit so inline it
+ * so it can be discarded.
+ */
+static inline void mmci_dma_release(struct mmci_host *host)
+{
+	struct mmci_platform_data *plat = host->plat;
+
+	if (host->dma_rx_channel)
+		dma_release_channel(host->dma_rx_channel);
+	if (host->dma_tx_channel && plat->dma_tx_param)
+		dma_release_channel(host->dma_tx_channel);
+	host->dma_rx_channel = host->dma_tx_channel = NULL;
+}
+
+static void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
+{
+	struct dma_chan *chan = host->dma_current;
+	enum dma_data_direction dir;
+	u32 status;
+	int i;
+
+	/* Wait up to 1ms for the DMA to complete */
+	for (i = 0; ; i++) {
+		status = readl(host->base + MMCISTATUS);
+		if (!(status & MCI_RXDATAAVLBLMASK) || i >= 100)
+			break;
+		udelay(10);
+	}
+
+	/*
+	 * Check to see whether we still have some data left in the FIFO -
+	 * this catches DMA controllers which are unable to monitor the
+	 * DMALBREQ and DMALSREQ signals while allowing us to DMA to non-
+	 * contiguous buffers.  On TX, we'll get a FIFO underrun error.
+	 */
+	if (status & MCI_RXDATAAVLBLMASK) {
+		dmaengine_terminate_all(chan);
+		if (!data->error)
+			data->error = -EIO;
+	}
+
+	if (data->flags & MMC_DATA_WRITE) {
+		dir = DMA_TO_DEVICE;
+	} else {
+		dir = DMA_FROM_DEVICE;
+	}
+
+	dma_unmap_sg(chan->device->dev, data->sg, data->sg_len, dir);
+
+	/*
+	 * Use of DMA with scatter-gather is impossible.
+	 * Give up with DMA and switch back to PIO mode.
+	 */
+	if (status & MCI_RXDATAAVLBLMASK) {
+		dev_err(mmc_dev(host->mmc), "buggy DMA detected. Taking evasive action.\n");
+		mmci_dma_release(host);
+	}
+}
+
+static void mmci_dma_data_error(struct mmci_host *host)
+{
+	dev_err(mmc_dev(host->mmc), "error during DMA transfer!\n");
+	dmaengine_terminate_all(host->dma_current);
+}
+
+static int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+	struct variant_data *variant = host->variant;
+	struct dma_slave_config conf = {
+		.src_addr = host->phybase + MMCIFIFO,
+		.dst_addr = host->phybase + MMCIFIFO,
+		.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+		.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES,
+		.src_maxburst = variant->fifohalfsize >> 2, /* # of words */
+		.dst_maxburst = variant->fifohalfsize >> 2, /* # of words */
+	};
+	struct mmc_data *data = host->data;
+	struct dma_chan *chan;
+	struct dma_device *device;
+	struct dma_async_tx_descriptor *desc;
+	int nr_sg;
+
+	host->dma_current = NULL;
+
+	if (data->flags & MMC_DATA_READ) {
+		conf.direction = DMA_FROM_DEVICE;
+		chan = host->dma_rx_channel;
+	} else {
+		conf.direction = DMA_TO_DEVICE;
+		chan = host->dma_tx_channel;
+	}
+
+	/* If there's no DMA channel, fall back to PIO */
+	if (!chan)
+		return -EINVAL;
+
+	/* If less than or equal to the fifo size, don't bother with DMA */
+	if (host->size <= variant->fifosize)
+		return -EINVAL;
+
+	device = chan->device;
+	nr_sg = dma_map_sg(device->dev, data->sg, data->sg_len, conf.direction);
+	if (nr_sg == 0)
+		return -EINVAL;
+
+	dmaengine_slave_config(chan, &conf);
+	desc = device->device_prep_slave_sg(chan, data->sg, nr_sg,
+					    conf.direction, DMA_CTRL_ACK);
+	if (!desc)
+		goto unmap_exit;
+
+	/* Okay, go for it. */
+	host->dma_current = chan;
+
+	dev_vdbg(mmc_dev(host->mmc),
+		 "Submit MMCI DMA job, sglen %d blksz %04x blks %04x flags %08x\n",
+		 data->sg_len, data->blksz, data->blocks, data->flags);
+	dmaengine_submit(desc);
+	dma_async_issue_pending(chan);
+
+	datactrl |= MCI_DPSM_DMAENABLE;
+
+	/* Trigger the DMA transfer */
+	writel(datactrl, host->base + MMCIDATACTRL);
+
+	/*
+	 * Let the MMCI say when the data is ended and it's time
+	 * to fire next DMA request. When that happens, MMCI will
+	 * call mmci_data_end()
+	 */
+	writel(readl(host->base + MMCIMASK0) | MCI_DATAENDMASK,
+	       host->base + MMCIMASK0);
+	return 0;
+
+unmap_exit:
+	dmaengine_terminate_all(chan);
+	dma_unmap_sg(device->dev, data->sg, data->sg_len, conf.direction);
+	return -ENOMEM;
+}
+#else
+/* Blank functions if the DMA engine is not available */
+static inline void mmci_dma_setup(struct mmci_host *host)
+{
+}
+
+static inline void mmci_dma_release(struct mmci_host *host)
+{
+}
+
+static inline void mmci_dma_unmap(struct mmci_host *host, struct mmc_data *data)
+{
+}
+
+static inline void mmci_dma_data_error(struct mmci_host *host)
+{
+}
+
+static inline int mmci_dma_start_data(struct mmci_host *host, unsigned int datactrl)
+{
+	return -ENOSYS;
+}
+#endif
+
 static void mmci_start_data(struct mmci_host *host, struct mmc_data *data)
 {
 	struct variant_data *variant = host->variant;
@@ -202,9 +449,7 @@
 
 	host->data = data;
 	host->size = data->blksz * data->blocks;
-	host->data_xfered = 0;
-
-	mmci_init_sg(host, data);
+	data->bytes_xfered = 0;
 
 	clks = (unsigned long long)data->timeout_ns * host->cclk;
 	do_div(clks, 1000000000UL);
@@ -219,15 +464,29 @@
 	BUG_ON(1 << blksz_bits != data->blksz);
 
 	datactrl = MCI_DPSM_ENABLE | blksz_bits << 4;
-	if (data->flags & MMC_DATA_READ) {
+
+	if (data->flags & MMC_DATA_READ)
 		datactrl |= MCI_DPSM_DIRECTION;
+
+	/*
+	 * Attempt to use DMA operation mode, if this
+	 * should fail, fall back to PIO mode
+	 */
+	if (!mmci_dma_start_data(host, datactrl))
+		return;
+
+	/* IRQ mode, map the SG list for CPU reading/writing */
+	mmci_init_sg(host, data);
+
+	if (data->flags & MMC_DATA_READ) {
 		irqmask = MCI_RXFIFOHALFFULLMASK;
 
 		/*
-		 * If we have less than a FIFOSIZE of bytes to transfer,
-		 * trigger a PIO interrupt as soon as any data is available.
+		 * If we have less than the fifo 'half-full' threshold to
+		 * transfer, trigger a PIO interrupt as soon as any data
+		 * is available.
 		 */
-		if (host->size < variant->fifosize)
+		if (host->size < variant->fifohalfsize)
 			irqmask |= MCI_RXDATAAVLBLMASK;
 	} else {
 		/*
@@ -283,49 +542,51 @@
 	if (status & (MCI_DATACRCFAIL|MCI_DATATIMEOUT|MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
 		u32 remain, success;
 
-		/* Calculate how far we are into the transfer */
+		/* Terminate the DMA transfer */
+		if (dma_inprogress(host))
+			mmci_dma_data_error(host);
+
+		/*
+		 * Calculate how far we are into the transfer.  Note that
+		 * the data counter gives the number of bytes transferred
+		 * on the MMC bus, not on the host side.  On reads, this
+		 * can be as much as a FIFO-worth of data ahead.  This
+		 * matters for FIFO overruns only.
+		 */
 		remain = readl(host->base + MMCIDATACNT);
 		success = data->blksz * data->blocks - remain;
 
-		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ (status %08x)\n", status);
+		dev_dbg(mmc_dev(host->mmc), "MCI ERROR IRQ, status 0x%08x at 0x%08x\n",
+			status, success);
 		if (status & MCI_DATACRCFAIL) {
 			/* Last block was not successful */
-			host->data_xfered = round_down(success - 1, data->blksz);
+			success -= 1;
 			data->error = -EILSEQ;
 		} else if (status & MCI_DATATIMEOUT) {
-			host->data_xfered = round_down(success, data->blksz);
 			data->error = -ETIMEDOUT;
-		} else if (status & (MCI_TXUNDERRUN|MCI_RXOVERRUN)) {
-			host->data_xfered = round_down(success, data->blksz);
+		} else if (status & MCI_TXUNDERRUN) {
+			data->error = -EIO;
+		} else if (status & MCI_RXOVERRUN) {
+			if (success > host->variant->fifosize)
+				success -= host->variant->fifosize;
+			else
+				success = 0;
 			data->error = -EIO;
 		}
-
-		/*
-		 * We hit an error condition.  Ensure that any data
-		 * partially written to a page is properly coherent.
-		 */
-		if (data->flags & MMC_DATA_READ) {
-			struct sg_mapping_iter *sg_miter = &host->sg_miter;
-			unsigned long flags;
-
-			local_irq_save(flags);
-			if (sg_miter_next(sg_miter)) {
-				flush_dcache_page(sg_miter->page);
-				sg_miter_stop(sg_miter);
-			}
-			local_irq_restore(flags);
-		}
+		data->bytes_xfered = round_down(success, data->blksz);
 	}
 
 	if (status & MCI_DATABLOCKEND)
 		dev_err(mmc_dev(host->mmc), "stray MCI_DATABLOCKEND interrupt\n");
 
 	if (status & MCI_DATAEND || data->error) {
+		if (dma_inprogress(host))
+			mmci_dma_unmap(host, data);
 		mmci_stop_data(host);
 
 		if (!data->error)
 			/* The error clause is handled above, success! */
-			host->data_xfered += data->blksz * data->blocks;
+			data->bytes_xfered = data->blksz * data->blocks;
 
 		if (!data->stop) {
 			mmci_request_end(host, data->mrq);
@@ -498,9 +759,6 @@
 		if (remain)
 			break;
 
-		if (status & MCI_RXACTIVE)
-			flush_dcache_page(sg_miter->page);
-
 		status = readl(base + MMCISTATUS);
 	} while (1);
 
@@ -509,10 +767,10 @@
 	local_irq_restore(flags);
 
 	/*
-	 * If we're nearing the end of the read, switch to
-	 * "any data available" mode.
+	 * If we have less than the fifo 'half-full' threshold to transfer,
+	 * trigger a PIO interrupt as soon as any data is available.
 	 */
-	if (status & MCI_RXACTIVE && host->size < variant->fifosize)
+	if (status & MCI_RXACTIVE && host->size < variant->fifohalfsize)
 		mmci_set_mask1(host, MCI_RXDATAAVLBLMASK);
 
 	/*
@@ -713,7 +971,8 @@
 	.get_cd		= mmci_get_cd,
 };
 
-static int __devinit mmci_probe(struct amba_device *dev, struct amba_id *id)
+static int __devinit mmci_probe(struct amba_device *dev,
+	const struct amba_id *id)
 {
 	struct mmci_platform_data *plat = dev->dev.platform_data;
 	struct variant_data *variant = id->data;
@@ -776,6 +1035,7 @@
 		dev_dbg(mmc_dev(mmc), "eventual mclk rate: %u Hz\n",
 			host->mclk);
 	}
+	host->phybase = dev->res.start;
 	host->base = ioremap(dev->res.start, resource_size(&dev->res));
 	if (!host->base) {
 		ret = -ENOMEM;
@@ -903,9 +1163,12 @@
 
 	amba_set_drvdata(dev, mmc);
 
-	dev_info(&dev->dev, "%s: PL%03x rev%u at 0x%08llx irq %d,%d\n",
-		mmc_hostname(mmc), amba_part(dev), amba_rev(dev),
-		(unsigned long long)dev->res.start, dev->irq[0], dev->irq[1]);
+	dev_info(&dev->dev, "%s: PL%03x manf %x rev%u at 0x%08llx irq %d,%d (pio)\n",
+		 mmc_hostname(mmc), amba_part(dev), amba_manf(dev),
+		 amba_rev(dev), (unsigned long long)dev->res.start,
+		 dev->irq[0], dev->irq[1]);
+
+	mmci_dma_setup(host);
 
 	mmc_add_host(mmc);
 
@@ -952,6 +1215,7 @@
 		writel(0, host->base + MMCICOMMAND);
 		writel(0, host->base + MMCIDATACTRL);
 
+		mmci_dma_release(host);
 		free_irq(dev->irq[0], host);
 		if (!host->singleirq)
 			free_irq(dev->irq[1], host);
@@ -1019,10 +1283,15 @@
 static struct amba_id mmci_ids[] = {
 	{
 		.id	= 0x00041180,
-		.mask	= 0x000fffff,
+		.mask	= 0xff0fffff,
 		.data	= &variant_arm,
 	},
 	{
+		.id	= 0x01041180,
+		.mask	= 0xff0fffff,
+		.data	= &variant_arm_extended_fifo,
+	},
+	{
 		.id	= 0x00041181,
 		.mask	= 0x000fffff,
 		.data	= &variant_arm,
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/mmci.h linux-libre-2.6.39-gnu/drivers/mmc/host/mmci.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/mmci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/mmci.h	2011-05-19 00:06:34.000000000 -0400
@@ -148,8 +148,10 @@
 
 struct clk;
 struct variant_data;
+struct dma_chan;
 
 struct mmci_host {
+	phys_addr_t		phybase;
 	void __iomem		*base;
 	struct mmc_request	*mrq;
 	struct mmc_command	*cmd;
@@ -161,8 +163,6 @@
 	int			gpio_cd_irq;
 	bool			singleirq;
 
-	unsigned int		data_xfered;
-
 	spinlock_t		lock;
 
 	unsigned int		mclk;
@@ -181,5 +181,16 @@
 	struct sg_mapping_iter	sg_miter;
 	unsigned int		size;
 	struct regulator	*vcc;
+
+#ifdef CONFIG_DMA_ENGINE
+	/* DMA stuff */
+	struct dma_chan		*dma_current;
+	struct dma_chan		*dma_rx_channel;
+	struct dma_chan		*dma_tx_channel;
+
+#define dma_inprogress(host)	((host)->dma_current)
+#else
+#define dma_inprogress(host)	(0)
+#endif
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/mmc_spi.c linux-libre-2.6.39-gnu/drivers/mmc/host/mmc_spi.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/mmc_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/mmc_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 #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
+ * be transferred 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
@@ -1516,21 +1516,17 @@
 	return 0;
 }
 
-#if defined(CONFIG_OF)
 static struct of_device_id mmc_spi_of_match_table[] __devinitdata = {
 	{ .compatible = "mmc-spi-slot", },
 	{},
 };
-#endif
 
 static struct spi_driver mmc_spi_driver = {
 	.driver = {
 		.name =		"mmc_spi",
 		.bus =		&spi_bus_type,
 		.owner =	THIS_MODULE,
-#if defined(CONFIG_OF)
 		.of_match_table = mmc_spi_of_match_table,
-#endif
 	},
 	.probe =	mmc_spi_probe,
 	.remove =	__devexit_p(mmc_spi_remove),
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/msm_sdcc.c linux-libre-2.6.39-gnu/drivers/mmc/host/msm_sdcc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/msm_sdcc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/msm_sdcc.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,7 @@
 #include <linux/io.h>
 #include <linux/memory.h>
 #include <linux/gfp.h>
+#include <linux/gpio.h>
 
 #include <asm/cacheflush.h>
 #include <asm/div64.h>
@@ -266,14 +267,6 @@
 	dma_unmap_sg(mmc_dev(host->mmc), host->dma.sg, host->dma.num_ents,
 		     host->dma.dir);
 
-	if (host->curr.user_pages) {
-		struct scatterlist *sg = host->dma.sg;
-		int i;
-
-		for (i = 0; i < host->dma.num_ents; i++)
-			flush_dcache_page(sg_page(sg++));
-	}
-
 	host->dma.sg = NULL;
 	host->dma.busy = 0;
 
@@ -941,6 +934,38 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+static void msmsdcc_setup_gpio(struct msmsdcc_host *host, bool enable)
+{
+	struct msm_mmc_gpio_data *curr;
+	int i, rc = 0;
+
+	if (!host->plat->gpio_data && host->gpio_config_status == enable)
+		return;
+
+	curr = host->plat->gpio_data;
+	for (i = 0; i < curr->size; i++) {
+		if (enable) {
+			rc = gpio_request(curr->gpio[i].no,
+						curr->gpio[i].name);
+			if (rc) {
+				pr_err("%s: gpio_request(%d, %s) failed %d\n",
+					mmc_hostname(host->mmc),
+					curr->gpio[i].no,
+					curr->gpio[i].name, rc);
+				goto free_gpios;
+			}
+		} else {
+			gpio_free(curr->gpio[i].no);
+		}
+	}
+	host->gpio_config_status = enable;
+	return;
+
+free_gpios:
+	for (; i >= 0; i--)
+		gpio_free(curr->gpio[i].no);
+}
+
 static void
 msmsdcc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
@@ -953,6 +978,8 @@
 
 	msmsdcc_enable_clocks(host);
 
+	spin_unlock_irqrestore(&host->lock, flags);
+
 	if (ios->clock) {
 		if (ios->clock != host->clk_rate) {
 			rc = clk_set_rate(host->clk, ios->clock);
@@ -979,9 +1006,11 @@
 
 	switch (ios->power_mode) {
 	case MMC_POWER_OFF:
+		msmsdcc_setup_gpio(host, false);
 		break;
 	case MMC_POWER_UP:
 		pwr |= MCI_PWR_UP;
+		msmsdcc_setup_gpio(host, true);
 		break;
 	case MMC_POWER_ON:
 		pwr |= MCI_PWR_ON;
@@ -998,9 +1027,10 @@
 		msmsdcc_writel(host, pwr, MMCIPOWER);
 	}
 #if BUSCLK_PWRSAVE
+	spin_lock_irqsave(&host->lock, flags);
 	msmsdcc_disable_clocks(host, 1);
-#endif
 	spin_unlock_irqrestore(&host->lock, flags);
+#endif
 }
 
 static void msmsdcc_enable_sdio_irq(struct mmc_host *mmc, int enable)
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/msm_sdcc.h linux-libre-2.6.39-gnu/drivers/mmc/host/msm_sdcc.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/msm_sdcc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/msm_sdcc.h	2011-05-19 00:06:34.000000000 -0400
@@ -243,6 +243,7 @@
 	unsigned int		cmd_datactrl;
 	struct mmc_command	*cmd_cmd;
 	u32			cmd_c;
+	bool			gpio_config_status;
 
 	bool prog_scan;
 	bool prog_enable;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/mxcmmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/mxcmmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/mxcmmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/mxcmmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,16 +32,14 @@
 #include <linux/io.h>
 #include <linux/gpio.h>
 #include <linux/regulator/consumer.h>
+#include <linux/dmaengine.h>
 
 #include <asm/dma.h>
 #include <asm/irq.h>
 #include <asm/sizes.h>
 #include <mach/mmc.h>
 
-#ifdef CONFIG_ARCH_MX2
-#include <mach/dma-mx1-mx2.h>
-#define HAS_DMA
-#endif
+#include <mach/dma.h>
 
 #define DRIVER_NAME "mxc-mmc"
 
@@ -118,7 +116,8 @@
 	void __iomem		*base;
 	int			irq;
 	int			detect_irq;
-	int			dma;
+	struct dma_chan		*dma;
+	struct dma_async_tx_descriptor *desc;
 	int			do_dma;
 	int			default_irq_mask;
 	int			use_sdio;
@@ -129,7 +128,6 @@
 	struct mmc_command	*cmd;
 	struct mmc_data		*data;
 
-	unsigned int		dma_nents;
 	unsigned int		datasize;
 	unsigned int		dma_dir;
 
@@ -144,6 +142,11 @@
 	spinlock_t		lock;
 
 	struct regulator	*vcc;
+
+	int			burstlen;
+	int			dmareq;
+	struct dma_slave_config dma_slave_config;
+	struct imx_dma_data	dma_data;
 };
 
 static void mxcmci_set_clk_rate(struct mxcmci_host *host, unsigned int clk_ios);
@@ -206,17 +209,16 @@
 
 	writew(0xff, host->base + MMC_REG_RES_TO);
 }
+static int mxcmci_setup_dma(struct mmc_host *mmc);
 
 static int mxcmci_setup_data(struct mxcmci_host *host, struct mmc_data *data)
 {
 	unsigned int nob = data->blocks;
 	unsigned int blksz = data->blksz;
 	unsigned int datasize = nob * blksz;
-#ifdef HAS_DMA
 	struct scatterlist *sg;
-	int i;
-	int ret;
-#endif
+	int i, nents;
+
 	if (data->flags & MMC_DATA_STREAM)
 		nob = 0xffff;
 
@@ -227,7 +229,9 @@
 	writew(blksz, host->base + MMC_REG_BLK_LEN);
 	host->datasize = datasize;
 
-#ifdef HAS_DMA
+	if (!mxcmci_use_dma(host))
+		return 0;
+
 	for_each_sg(data->sg, sg, data->sg_len, i) {
 		if (sg->offset & 3 || sg->length & 3) {
 			host->do_dma = 0;
@@ -235,34 +239,30 @@
 		}
 	}
 
-	if (data->flags & MMC_DATA_READ) {
+	if (data->flags & MMC_DATA_READ)
 		host->dma_dir = DMA_FROM_DEVICE;
-		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-					     data->sg_len,  host->dma_dir);
-
-		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-				datasize,
-				host->res->start + MMC_REG_BUFFER_ACCESS,
-				DMA_MODE_READ);
-	} else {
+	else
 		host->dma_dir = DMA_TO_DEVICE;
-		host->dma_nents = dma_map_sg(mmc_dev(host->mmc), data->sg,
-					     data->sg_len,  host->dma_dir);
 
-		ret = imx_dma_setup_sg(host->dma, data->sg, host->dma_nents,
-				datasize,
-				host->res->start + MMC_REG_BUFFER_ACCESS,
-				DMA_MODE_WRITE);
-	}
+	nents = dma_map_sg(host->dma->device->dev, data->sg,
+				     data->sg_len,  host->dma_dir);
+	if (nents != data->sg_len)
+		return -EINVAL;
 
-	if (ret) {
-		dev_err(mmc_dev(host->mmc), "failed to setup DMA : %d\n", ret);
-		return ret;
+	host->desc = host->dma->device->device_prep_slave_sg(host->dma,
+		data->sg, data->sg_len, host->dma_dir,
+		DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
+
+	if (!host->desc) {
+		dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
+				host->dma_dir);
+		host->do_dma = 0;
+		return 0; /* Fall back to PIO */
 	}
 	wmb();
 
-	imx_dma_enable(host->dma);
-#endif /* HAS_DMA */
+	dmaengine_submit(host->desc);
+
 	return 0;
 }
 
@@ -337,13 +337,11 @@
 	struct mmc_data *data = host->data;
 	int data_error;
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host)) {
-		imx_dma_disable(host->dma);
-		dma_unmap_sg(mmc_dev(host->mmc), data->sg, host->dma_nents,
+		dmaengine_terminate_all(host->dma);
+		dma_unmap_sg(host->dma->device->dev, data->sg, data->sg_len,
 				host->dma_dir);
 	}
-#endif
 
 	if (stat & STATUS_ERR_MASK) {
 		dev_dbg(mmc_dev(host->mmc), "request failed. status: 0x%08x\n",
@@ -545,7 +543,6 @@
 	}
 }
 
-#ifdef HAS_DMA
 static void mxcmci_data_done(struct mxcmci_host *host, unsigned int stat)
 {
 	struct mmc_data *data = host->data;
@@ -568,7 +565,6 @@
 		mxcmci_finish_request(host, host->req);
 	}
 }
-#endif /* HAS_DMA */
 
 static void mxcmci_cmd_done(struct mxcmci_host *host, unsigned int stat)
 {
@@ -606,12 +602,10 @@
 	sdio_irq = (stat & STATUS_SDIO_INT_ACTIVE) && host->use_sdio;
 	spin_unlock_irqrestore(&host->lock, flags);
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 	    (stat & (STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE)))
 		writel(STATUS_READ_OP_DONE | STATUS_WRITE_OP_DONE,
 			host->base + MMC_REG_STATUS);
-#endif
 
 	if (sdio_irq) {
 		writel(STATUS_SDIO_INT_ACTIVE, host->base + MMC_REG_STATUS);
@@ -621,14 +615,14 @@
 	if (stat & STATUS_END_CMD_RESP)
 		mxcmci_cmd_done(host, stat);
 
-#ifdef HAS_DMA
 	if (mxcmci_use_dma(host) &&
 		  (stat & (STATUS_DATA_TRANS_DONE | STATUS_WRITE_OP_DONE)))
 		mxcmci_data_done(host, stat);
-#endif
+
 	if (host->default_irq_mask &&
 		  (stat & (STATUS_CARD_INSERTION | STATUS_CARD_REMOVAL)))
 		mmc_detect_change(host->mmc, msecs_to_jiffies(200));
+
 	return IRQ_HANDLED;
 }
 
@@ -642,9 +636,10 @@
 
 	host->req = req;
 	host->cmdat &= ~CMD_DAT_CONT_INIT;
-#ifdef HAS_DMA
-	host->do_dma = 1;
-#endif
+
+	if (host->dma)
+		host->do_dma = 1;
+
 	if (req->data) {
 		error = mxcmci_setup_data(host, req->data);
 		if (error) {
@@ -660,6 +655,7 @@
 	}
 
 	error = mxcmci_start_cmd(host, req->cmd, cmdat);
+
 out:
 	if (error)
 		mxcmci_finish_request(host, req);
@@ -698,22 +694,46 @@
 			prescaler, divider, clk_in, clk_ios);
 }
 
+static int mxcmci_setup_dma(struct mmc_host *mmc)
+{
+	struct mxcmci_host *host = mmc_priv(mmc);
+	struct dma_slave_config *config = &host->dma_slave_config;
+
+	config->dst_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
+	config->src_addr = host->res->start + MMC_REG_BUFFER_ACCESS;
+	config->dst_addr_width = 4;
+	config->src_addr_width = 4;
+	config->dst_maxburst = host->burstlen;
+	config->src_maxburst = host->burstlen;
+
+	return dmaengine_slave_config(host->dma, config);
+}
+
 static void mxcmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct mxcmci_host *host = mmc_priv(mmc);
-#ifdef HAS_DMA
-	unsigned int blen;
+	int burstlen, ret;
+
 	/*
 	 * use burstlen of 64 in 4 bit mode (--> reg value  0)
 	 * use burstlen of 16 in 1 bit mode (--> reg value 16)
 	 */
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
-		blen = 0;
+		burstlen = 64;
 	else
-		blen = 16;
+		burstlen = 16;
+
+	if (mxcmci_use_dma(host) && burstlen != host->burstlen) {
+		host->burstlen = burstlen;
+		ret = mxcmci_setup_dma(mmc);
+		if (ret) {
+			dev_err(mmc_dev(host->mmc),
+				"failed to config DMA channel. Falling back to PIO\n");
+			dma_release_channel(host->dma);
+			host->do_dma = 0;
+		}
+	}
 
-	imx_dma_config_burstlen(host->dma, blen);
-#endif
 	if (ios->bus_width == MMC_BUS_WIDTH_4)
 		host->cmdat |= CMD_DAT_CONT_BUS_WIDTH_4;
 	else
@@ -794,6 +814,18 @@
 		host->caps |= MMC_CAP_4_BIT_DATA;
 }
 
+static bool filter(struct dma_chan *chan, void *param)
+{
+	struct mxcmci_host *host = param;
+
+	if (!imx_dma_is_general_purpose(chan))
+		return false;
+
+	chan->private = &host->dma_data;
+
+	return true;
+}
+
 static const struct mmc_host_ops mxcmci_ops = {
 	.request		= mxcmci_request,
 	.set_ios		= mxcmci_set_ios,
@@ -808,6 +840,7 @@
 	struct mxcmci_host *host = NULL;
 	struct resource *iores, *r;
 	int ret = 0, irq;
+	dma_cap_mask_t mask;
 
 	printk(KERN_INFO "i.MX SDHC driver\n");
 
@@ -883,29 +916,23 @@
 
 	writel(host->default_irq_mask, host->base + MMC_REG_INT_CNTR);
 
-#ifdef HAS_DMA
-	host->dma = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_LOW);
-	if (host->dma < 0) {
-		dev_err(mmc_dev(host->mmc), "imx_dma_request_by_prio failed\n");
-		ret = -EBUSY;
-		goto out_clk_put;
-	}
-
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 0);
-	if (!r) {
-		ret = -EINVAL;
-		goto out_free_dma;
+	if (r) {
+		host->dmareq = r->start;
+		host->dma_data.peripheral_type = IMX_DMATYPE_SDHC;
+		host->dma_data.priority = DMA_PRIO_LOW;
+		host->dma_data.dma_request = host->dmareq;
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+		host->dma = dma_request_channel(mask, filter, host);
+		if (host->dma)
+			mmc->max_seg_size = dma_get_max_seg_size(
+					host->dma->device->dev);
 	}
 
-	ret = imx_dma_config_channel(host->dma,
-				     IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_FIFO,
-				     IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR,
-				     r->start, 0);
-	if (ret) {
-		dev_err(mmc_dev(host->mmc), "failed to config DMA channel\n");
-		goto out_free_dma;
-	}
-#endif
+	if (!host->dma)
+		dev_info(mmc_dev(host->mmc), "dma not available. Using PIO\n");
+
 	INIT_WORK(&host->datawork, mxcmci_datawork);
 
 	ret = request_irq(host->irq, mxcmci_irq, 0, DRIVER_NAME, host);
@@ -928,9 +955,8 @@
 out_free_irq:
 	free_irq(host->irq, host);
 out_free_dma:
-#ifdef HAS_DMA
-	imx_dma_free(host->dma);
-#endif
+	if (host->dma)
+		dma_release_channel(host->dma);
 out_clk_put:
 	clk_disable(host->clk);
 	clk_put(host->clk);
@@ -960,9 +986,10 @@
 
 	free_irq(host->irq, host);
 	iounmap(host->base);
-#ifdef HAS_DMA
-	imx_dma_free(host->dma);
-#endif
+
+	if (host->dma)
+		dma_release_channel(host->dma);
+
 	clk_disable(host->clk);
 	clk_put(host->clk);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/mxs-mmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/mxs-mmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/mxs-mmc.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/mxs-mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,874 @@
+/*
+ * Portions copyright (C) 2003 Russell King, PXA MMCI Driver
+ * Portions copyright (C) 2004-2005 Pierre Ossman, W83L51xD SD/MMC driver
+ *
+ * Copyright 2008 Embedded Alley Solutions, Inc.
+ * Copyright 2009-2011 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See 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/init.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/dma-mapping.h>
+#include <linux/dmaengine.h>
+#include <linux/highmem.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
+#include <linux/gpio.h>
+#include <linux/regulator/consumer.h>
+
+#include <mach/mxs.h>
+#include <mach/common.h>
+#include <mach/dma.h>
+#include <mach/mmc.h>
+
+#define DRIVER_NAME	"mxs-mmc"
+
+/* card detect polling timeout */
+#define MXS_MMC_DETECT_TIMEOUT			(HZ/2)
+
+#define SSP_VERSION_LATEST	4
+#define ssp_is_old()		(host->version < SSP_VERSION_LATEST)
+
+/* SSP registers */
+#define HW_SSP_CTRL0				0x000
+#define  BM_SSP_CTRL0_RUN			(1 << 29)
+#define  BM_SSP_CTRL0_SDIO_IRQ_CHECK		(1 << 28)
+#define  BM_SSP_CTRL0_IGNORE_CRC		(1 << 26)
+#define  BM_SSP_CTRL0_READ			(1 << 25)
+#define  BM_SSP_CTRL0_DATA_XFER			(1 << 24)
+#define  BP_SSP_CTRL0_BUS_WIDTH			(22)
+#define  BM_SSP_CTRL0_BUS_WIDTH			(0x3 << 22)
+#define  BM_SSP_CTRL0_WAIT_FOR_IRQ		(1 << 21)
+#define  BM_SSP_CTRL0_LONG_RESP			(1 << 19)
+#define  BM_SSP_CTRL0_GET_RESP			(1 << 17)
+#define  BM_SSP_CTRL0_ENABLE			(1 << 16)
+#define  BP_SSP_CTRL0_XFER_COUNT		(0)
+#define  BM_SSP_CTRL0_XFER_COUNT		(0xffff)
+#define HW_SSP_CMD0				0x010
+#define  BM_SSP_CMD0_DBL_DATA_RATE_EN		(1 << 25)
+#define  BM_SSP_CMD0_SLOW_CLKING_EN		(1 << 22)
+#define  BM_SSP_CMD0_CONT_CLKING_EN		(1 << 21)
+#define  BM_SSP_CMD0_APPEND_8CYC		(1 << 20)
+#define  BP_SSP_CMD0_BLOCK_SIZE			(16)
+#define  BM_SSP_CMD0_BLOCK_SIZE			(0xf << 16)
+#define  BP_SSP_CMD0_BLOCK_COUNT		(8)
+#define  BM_SSP_CMD0_BLOCK_COUNT		(0xff << 8)
+#define  BP_SSP_CMD0_CMD			(0)
+#define  BM_SSP_CMD0_CMD			(0xff)
+#define HW_SSP_CMD1				0x020
+#define HW_SSP_XFER_SIZE			0x030
+#define HW_SSP_BLOCK_SIZE			0x040
+#define  BP_SSP_BLOCK_SIZE_BLOCK_COUNT		(4)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_COUNT		(0xffffff << 4)
+#define  BP_SSP_BLOCK_SIZE_BLOCK_SIZE		(0)
+#define  BM_SSP_BLOCK_SIZE_BLOCK_SIZE		(0xf)
+#define HW_SSP_TIMING				(ssp_is_old() ? 0x050 : 0x070)
+#define  BP_SSP_TIMING_TIMEOUT			(16)
+#define  BM_SSP_TIMING_TIMEOUT			(0xffff << 16)
+#define  BP_SSP_TIMING_CLOCK_DIVIDE		(8)
+#define  BM_SSP_TIMING_CLOCK_DIVIDE		(0xff << 8)
+#define  BP_SSP_TIMING_CLOCK_RATE		(0)
+#define  BM_SSP_TIMING_CLOCK_RATE		(0xff)
+#define HW_SSP_CTRL1				(ssp_is_old() ? 0x060 : 0x080)
+#define  BM_SSP_CTRL1_SDIO_IRQ			(1 << 31)
+#define  BM_SSP_CTRL1_SDIO_IRQ_EN		(1 << 30)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ		(1 << 29)
+#define  BM_SSP_CTRL1_RESP_ERR_IRQ_EN		(1 << 28)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ		(1 << 27)
+#define  BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN	(1 << 26)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ		(1 << 25)
+#define  BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN	(1 << 24)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ		(1 << 23)
+#define  BM_SSP_CTRL1_DATA_CRC_IRQ_EN		(1 << 22)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ		(1 << 21)
+#define  BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ_EN	(1 << 20)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ		(1 << 17)
+#define  BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN	(1 << 16)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ		(1 << 15)
+#define  BM_SSP_CTRL1_FIFO_OVERRUN_IRQ_EN	(1 << 14)
+#define  BM_SSP_CTRL1_DMA_ENABLE		(1 << 13)
+#define  BM_SSP_CTRL1_POLARITY			(1 << 9)
+#define  BP_SSP_CTRL1_WORD_LENGTH		(4)
+#define  BM_SSP_CTRL1_WORD_LENGTH		(0xf << 4)
+#define  BP_SSP_CTRL1_SSP_MODE			(0)
+#define  BM_SSP_CTRL1_SSP_MODE			(0xf)
+#define HW_SSP_SDRESP0				(ssp_is_old() ? 0x080 : 0x0a0)
+#define HW_SSP_SDRESP1				(ssp_is_old() ? 0x090 : 0x0b0)
+#define HW_SSP_SDRESP2				(ssp_is_old() ? 0x0a0 : 0x0c0)
+#define HW_SSP_SDRESP3				(ssp_is_old() ? 0x0b0 : 0x0d0)
+#define HW_SSP_STATUS				(ssp_is_old() ? 0x0c0 : 0x100)
+#define  BM_SSP_STATUS_CARD_DETECT		(1 << 28)
+#define  BM_SSP_STATUS_SDIO_IRQ			(1 << 17)
+#define HW_SSP_VERSION				(cpu_is_mx23() ? 0x110 : 0x130)
+#define  BP_SSP_VERSION_MAJOR			(24)
+
+#define BF_SSP(value, field)	(((value) << BP_SSP_##field) & BM_SSP_##field)
+
+#define MXS_MMC_IRQ_BITS	(BM_SSP_CTRL1_SDIO_IRQ		| \
+				 BM_SSP_CTRL1_RESP_ERR_IRQ	| \
+				 BM_SSP_CTRL1_RESP_TIMEOUT_IRQ	| \
+				 BM_SSP_CTRL1_DATA_TIMEOUT_IRQ	| \
+				 BM_SSP_CTRL1_DATA_CRC_IRQ	| \
+				 BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ	| \
+				 BM_SSP_CTRL1_RECV_TIMEOUT_IRQ  | \
+				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ)
+
+#define SSP_PIO_NUM	3
+
+struct mxs_mmc_host {
+	struct mmc_host			*mmc;
+	struct mmc_request		*mrq;
+	struct mmc_command		*cmd;
+	struct mmc_data			*data;
+
+	void __iomem			*base;
+	int				irq;
+	struct resource			*res;
+	struct resource			*dma_res;
+	struct clk			*clk;
+	unsigned int			clk_rate;
+
+	struct dma_chan         	*dmach;
+	struct mxs_dma_data		dma_data;
+	unsigned int			dma_dir;
+	u32				ssp_pio_words[SSP_PIO_NUM];
+
+	unsigned int			version;
+	unsigned char			bus_width;
+	spinlock_t			lock;
+	int				sdio_irq_en;
+};
+
+static int mxs_mmc_get_ro(struct mmc_host *mmc)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct mxs_mmc_platform_data *pdata =
+		mmc_dev(host->mmc)->platform_data;
+
+	if (!pdata)
+		return -EFAULT;
+
+	if (!gpio_is_valid(pdata->wp_gpio))
+		return -EINVAL;
+
+	return gpio_get_value(pdata->wp_gpio);
+}
+
+static int mxs_mmc_get_cd(struct mmc_host *mmc)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	return !(readl(host->base + HW_SSP_STATUS) &
+		 BM_SSP_STATUS_CARD_DETECT);
+}
+
+static void mxs_mmc_reset(struct mxs_mmc_host *host)
+{
+	u32 ctrl0, ctrl1;
+
+	mxs_reset_block(host->base);
+
+	ctrl0 = BM_SSP_CTRL0_IGNORE_CRC;
+	ctrl1 = BF_SSP(0x3, CTRL1_SSP_MODE) |
+		BF_SSP(0x7, CTRL1_WORD_LENGTH) |
+		BM_SSP_CTRL1_DMA_ENABLE |
+		BM_SSP_CTRL1_POLARITY |
+		BM_SSP_CTRL1_RECV_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_DATA_CRC_IRQ_EN |
+		BM_SSP_CTRL1_DATA_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_TIMEOUT_IRQ_EN |
+		BM_SSP_CTRL1_RESP_ERR_IRQ_EN;
+
+	writel(BF_SSP(0xffff, TIMING_TIMEOUT) |
+	       BF_SSP(2, TIMING_CLOCK_DIVIDE) |
+	       BF_SSP(0, TIMING_CLOCK_RATE),
+	       host->base + HW_SSP_TIMING);
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		ctrl1 |= BM_SSP_CTRL1_SDIO_IRQ_EN;
+	}
+
+	writel(ctrl0, host->base + HW_SSP_CTRL0);
+	writel(ctrl1, host->base + HW_SSP_CTRL1);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+			      struct mmc_command *cmd);
+
+static void mxs_mmc_request_done(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = host->data;
+	struct mmc_request *mrq = host->mrq;
+
+	if (mmc_resp_type(cmd) & MMC_RSP_PRESENT) {
+		if (mmc_resp_type(cmd) & MMC_RSP_136) {
+			cmd->resp[3] = readl(host->base + HW_SSP_SDRESP0);
+			cmd->resp[2] = readl(host->base + HW_SSP_SDRESP1);
+			cmd->resp[1] = readl(host->base + HW_SSP_SDRESP2);
+			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP3);
+		} else {
+			cmd->resp[0] = readl(host->base + HW_SSP_SDRESP0);
+		}
+	}
+
+	if (data) {
+		dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+			     data->sg_len, host->dma_dir);
+		/*
+		 * If there was an error on any block, we mark all
+		 * data blocks as being in error.
+		 */
+		if (!data->error)
+			data->bytes_xfered = data->blocks * data->blksz;
+		else
+			data->bytes_xfered = 0;
+
+		host->data = NULL;
+		if (mrq->stop) {
+			mxs_mmc_start_cmd(host, mrq->stop);
+			return;
+		}
+	}
+
+	host->mrq = NULL;
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void mxs_mmc_dma_irq_callback(void *param)
+{
+	struct mxs_mmc_host *host = param;
+
+	mxs_mmc_request_done(host);
+}
+
+static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
+{
+	struct mxs_mmc_host *host = dev_id;
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = host->data;
+	u32 stat;
+
+	spin_lock(&host->lock);
+
+	stat = readl(host->base + HW_SSP_CTRL1);
+	writel(stat & MXS_MMC_IRQ_BITS,
+	       host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+
+	if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
+		mmc_signal_sdio_irq(host->mmc);
+
+	spin_unlock(&host->lock);
+
+	if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
+		cmd->error = -ETIMEDOUT;
+	else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
+		cmd->error = -EIO;
+
+	if (data) {
+		if (stat & (BM_SSP_CTRL1_DATA_TIMEOUT_IRQ |
+			    BM_SSP_CTRL1_RECV_TIMEOUT_IRQ))
+			data->error = -ETIMEDOUT;
+		else if (stat & BM_SSP_CTRL1_DATA_CRC_IRQ)
+			data->error = -EILSEQ;
+		else if (stat & (BM_SSP_CTRL1_FIFO_UNDERRUN_IRQ |
+				 BM_SSP_CTRL1_FIFO_OVERRUN_IRQ))
+			data->error = -EIO;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static struct dma_async_tx_descriptor *mxs_mmc_prep_dma(
+	struct mxs_mmc_host *host, unsigned int append)
+{
+	struct dma_async_tx_descriptor *desc;
+	struct mmc_data *data = host->data;
+	struct scatterlist * sgl;
+	unsigned int sg_len;
+
+	if (data) {
+		/* data */
+		dma_map_sg(mmc_dev(host->mmc), data->sg,
+			   data->sg_len, host->dma_dir);
+		sgl = data->sg;
+		sg_len = data->sg_len;
+	} else {
+		/* pio */
+		sgl = (struct scatterlist *) host->ssp_pio_words;
+		sg_len = SSP_PIO_NUM;
+	}
+
+	desc = host->dmach->device->device_prep_slave_sg(host->dmach,
+				sgl, sg_len, host->dma_dir, append);
+	if (desc) {
+		desc->callback = mxs_mmc_dma_irq_callback;
+		desc->callback_param = host;
+	} else {
+		if (data)
+			dma_unmap_sg(mmc_dev(host->mmc), data->sg,
+				     data->sg_len, host->dma_dir);
+	}
+
+	return desc;
+}
+
+static void mxs_mmc_bc(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct dma_async_tx_descriptor *desc;
+	u32 ctrl0, cmd0, cmd1;
+
+	ctrl0 = BM_SSP_CTRL0_ENABLE | BM_SSP_CTRL0_IGNORE_CRC;
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD) | BM_SSP_CMD0_APPEND_8CYC;
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_ac(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct dma_async_tx_descriptor *desc;
+	u32 ignore_crc, get_resp, long_resp;
+	u32 ctrl0, cmd0, cmd1;
+
+	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+			0 : BM_SSP_CTRL0_IGNORE_CRC;
+	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+			BM_SSP_CTRL0_GET_RESP : 0;
+	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+			BM_SSP_CTRL0_LONG_RESP : 0;
+
+	ctrl0 = BM_SSP_CTRL0_ENABLE | ignore_crc | get_resp | long_resp;
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static unsigned short mxs_ns_to_ssp_ticks(unsigned clock_rate, unsigned ns)
+{
+	const unsigned int ssp_timeout_mul = 4096;
+	/*
+	 * Calculate ticks in ms since ns are large numbers
+	 * and might overflow
+	 */
+	const unsigned int clock_per_ms = clock_rate / 1000;
+	const unsigned int ms = ns / 1000;
+	const unsigned int ticks = ms * clock_per_ms;
+	const unsigned int ssp_ticks = ticks / ssp_timeout_mul;
+
+	WARN_ON(ssp_ticks == 0);
+	return ssp_ticks;
+}
+
+static void mxs_mmc_adtc(struct mxs_mmc_host *host)
+{
+	struct mmc_command *cmd = host->cmd;
+	struct mmc_data *data = cmd->data;
+	struct dma_async_tx_descriptor *desc;
+	struct scatterlist *sgl = data->sg, *sg;
+	unsigned int sg_len = data->sg_len;
+	int i;
+
+	unsigned short dma_data_dir, timeout;
+	unsigned int data_size = 0, log2_blksz;
+	unsigned int blocks = data->blocks;
+
+	u32 ignore_crc, get_resp, long_resp, read;
+	u32 ctrl0, cmd0, cmd1, val;
+
+	ignore_crc = (mmc_resp_type(cmd) & MMC_RSP_CRC) ?
+			0 : BM_SSP_CTRL0_IGNORE_CRC;
+	get_resp = (mmc_resp_type(cmd) & MMC_RSP_PRESENT) ?
+			BM_SSP_CTRL0_GET_RESP : 0;
+	long_resp = (mmc_resp_type(cmd) & MMC_RSP_136) ?
+			BM_SSP_CTRL0_LONG_RESP : 0;
+
+	if (data->flags & MMC_DATA_WRITE) {
+		dma_data_dir = DMA_TO_DEVICE;
+		read = 0;
+	} else {
+		dma_data_dir = DMA_FROM_DEVICE;
+		read = BM_SSP_CTRL0_READ;
+	}
+
+	ctrl0 = BF_SSP(host->bus_width, CTRL0_BUS_WIDTH) |
+		ignore_crc | get_resp | long_resp |
+		BM_SSP_CTRL0_DATA_XFER | read |
+		BM_SSP_CTRL0_WAIT_FOR_IRQ |
+		BM_SSP_CTRL0_ENABLE;
+
+	cmd0 = BF_SSP(cmd->opcode, CMD0_CMD);
+
+	/* get logarithm to base 2 of block size for setting register */
+	log2_blksz = ilog2(data->blksz);
+
+	/*
+	 * take special care of the case that data size from data->sg
+	 * is not equal to blocks x blksz
+	 */
+	for_each_sg(sgl, sg, sg_len, i)
+		data_size += sg->length;
+
+	if (data_size != data->blocks * data->blksz)
+		blocks = 1;
+
+	/* xfer count, block size and count need to be set differently */
+	if (ssp_is_old()) {
+		ctrl0 |= BF_SSP(data_size, CTRL0_XFER_COUNT);
+		cmd0 |= BF_SSP(log2_blksz, CMD0_BLOCK_SIZE) |
+			BF_SSP(blocks - 1, CMD0_BLOCK_COUNT);
+	} else {
+		writel(data_size, host->base + HW_SSP_XFER_SIZE);
+		writel(BF_SSP(log2_blksz, BLOCK_SIZE_BLOCK_SIZE) |
+		       BF_SSP(blocks - 1, BLOCK_SIZE_BLOCK_COUNT),
+		       host->base + HW_SSP_BLOCK_SIZE);
+	}
+
+	if ((cmd->opcode == MMC_STOP_TRANSMISSION) ||
+	    (cmd->opcode == SD_IO_RW_EXTENDED))
+		cmd0 |= BM_SSP_CMD0_APPEND_8CYC;
+
+	cmd1 = cmd->arg;
+
+	if (host->sdio_irq_en) {
+		ctrl0 |= BM_SSP_CTRL0_SDIO_IRQ_CHECK;
+		cmd0 |= BM_SSP_CMD0_CONT_CLKING_EN | BM_SSP_CMD0_SLOW_CLKING_EN;
+	}
+
+	/* set the timeout count */
+	timeout = mxs_ns_to_ssp_ticks(host->clk_rate, data->timeout_ns);
+	val = readl(host->base + HW_SSP_TIMING);
+	val &= ~(BM_SSP_TIMING_TIMEOUT);
+	val |= BF_SSP(timeout, TIMING_TIMEOUT);
+	writel(val, host->base + HW_SSP_TIMING);
+
+	/* pio */
+	host->ssp_pio_words[0] = ctrl0;
+	host->ssp_pio_words[1] = cmd0;
+	host->ssp_pio_words[2] = cmd1;
+	host->dma_dir = DMA_NONE;
+	desc = mxs_mmc_prep_dma(host, 0);
+	if (!desc)
+		goto out;
+
+	/* append data sg */
+	WARN_ON(host->data != NULL);
+	host->data = data;
+	host->dma_dir = dma_data_dir;
+	desc = mxs_mmc_prep_dma(host, 1);
+	if (!desc)
+		goto out;
+
+	dmaengine_submit(desc);
+	return;
+out:
+	dev_warn(mmc_dev(host->mmc),
+		 "%s: failed to prep dma\n", __func__);
+}
+
+static void mxs_mmc_start_cmd(struct mxs_mmc_host *host,
+			      struct mmc_command *cmd)
+{
+	host->cmd = cmd;
+
+	switch (mmc_cmd_type(cmd)) {
+	case MMC_CMD_BC:
+		mxs_mmc_bc(host);
+		break;
+	case MMC_CMD_BCR:
+		mxs_mmc_ac(host);
+		break;
+	case MMC_CMD_AC:
+		mxs_mmc_ac(host);
+		break;
+	case MMC_CMD_ADTC:
+		mxs_mmc_adtc(host);
+		break;
+	default:
+		dev_warn(mmc_dev(host->mmc),
+			 "%s: unknown MMC command\n", __func__);
+		break;
+	}
+}
+
+static void mxs_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	WARN_ON(host->mrq != NULL);
+	host->mrq = mrq;
+	mxs_mmc_start_cmd(host, mrq->cmd);
+}
+
+static void mxs_mmc_set_clk_rate(struct mxs_mmc_host *host, unsigned int rate)
+{
+	unsigned int ssp_rate, bit_rate;
+	u32 div1, div2;
+	u32 val;
+
+	ssp_rate = clk_get_rate(host->clk);
+
+	for (div1 = 2; div1 < 254; div1 += 2) {
+		div2 = ssp_rate / rate / div1;
+		if (div2 < 0x100)
+			break;
+	}
+
+	if (div1 >= 254) {
+		dev_err(mmc_dev(host->mmc),
+			"%s: cannot set clock to %d\n", __func__, rate);
+		return;
+	}
+
+	if (div2 == 0)
+		bit_rate = ssp_rate / div1;
+	else
+		bit_rate = ssp_rate / div1 / div2;
+
+	val = readl(host->base + HW_SSP_TIMING);
+	val &= ~(BM_SSP_TIMING_CLOCK_DIVIDE | BM_SSP_TIMING_CLOCK_RATE);
+	val |= BF_SSP(div1, TIMING_CLOCK_DIVIDE);
+	val |= BF_SSP(div2 - 1, TIMING_CLOCK_RATE);
+	writel(val, host->base + HW_SSP_TIMING);
+
+	host->clk_rate = bit_rate;
+
+	dev_dbg(mmc_dev(host->mmc),
+		"%s: div1 %d, div2 %d, ssp %d, bit %d, rate %d\n",
+		__func__, div1, div2, ssp_rate, bit_rate, rate);
+}
+
+static void mxs_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+
+	if (ios->bus_width == MMC_BUS_WIDTH_8)
+		host->bus_width = 2;
+	else if (ios->bus_width == MMC_BUS_WIDTH_4)
+		host->bus_width = 1;
+	else
+		host->bus_width = 0;
+
+	if (ios->clock)
+		mxs_mmc_set_clk_rate(host, ios->clock);
+}
+
+static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+
+	host->sdio_irq_en = enable;
+
+	if (enable) {
+		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+		       host->base + HW_SSP_CTRL0 + MXS_SET_ADDR);
+		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+		       host->base + HW_SSP_CTRL1 + MXS_SET_ADDR);
+
+		if (readl(host->base + HW_SSP_STATUS) & BM_SSP_STATUS_SDIO_IRQ)
+			mmc_signal_sdio_irq(host->mmc);
+
+	} else {
+		writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
+		       host->base + HW_SSP_CTRL0 + MXS_CLR_ADDR);
+		writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
+		       host->base + HW_SSP_CTRL1 + MXS_CLR_ADDR);
+	}
+
+	spin_unlock_irqrestore(&host->lock, flags);
+}
+
+static const struct mmc_host_ops mxs_mmc_ops = {
+	.request = mxs_mmc_request,
+	.get_ro = mxs_mmc_get_ro,
+	.get_cd = mxs_mmc_get_cd,
+	.set_ios = mxs_mmc_set_ios,
+	.enable_sdio_irq = mxs_mmc_enable_sdio_irq,
+};
+
+static bool mxs_mmc_dma_filter(struct dma_chan *chan, void *param)
+{
+	struct mxs_mmc_host *host = param;
+
+	if (!mxs_dma_is_apbh(chan))
+		return false;
+
+	if (chan->chan_id != host->dma_res->start)
+		return false;
+
+	chan->private = &host->dma_data;
+
+	return true;
+}
+
+static int mxs_mmc_probe(struct platform_device *pdev)
+{
+	struct mxs_mmc_host *host;
+	struct mmc_host *mmc;
+	struct resource *iores, *dmares, *r;
+	struct mxs_mmc_platform_data *pdata;
+	int ret = 0, irq_err, irq_dma;
+	dma_cap_mask_t mask;
+
+	iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0);
+	irq_err = platform_get_irq(pdev, 0);
+	irq_dma = platform_get_irq(pdev, 1);
+	if (!iores || !dmares || irq_err < 0 || irq_dma < 0)
+		return -EINVAL;
+
+	r = request_mem_region(iores->start, resource_size(iores), pdev->name);
+	if (!r)
+		return -EBUSY;
+
+	mmc = mmc_alloc_host(sizeof(struct mxs_mmc_host), &pdev->dev);
+	if (!mmc) {
+		ret = -ENOMEM;
+		goto out_release_mem;
+	}
+
+	host = mmc_priv(mmc);
+	host->base = ioremap(r->start, resource_size(r));
+	if (!host->base) {
+		ret = -ENOMEM;
+		goto out_mmc_free;
+	}
+
+	/* only major verion does matter */
+	host->version = readl(host->base + HW_SSP_VERSION) >>
+			BP_SSP_VERSION_MAJOR;
+
+	host->mmc = mmc;
+	host->res = r;
+	host->dma_res = dmares;
+	host->irq = irq_err;
+	host->sdio_irq_en = 0;
+
+	host->clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(host->clk)) {
+		ret = PTR_ERR(host->clk);
+		goto out_iounmap;
+	}
+	clk_enable(host->clk);
+
+	mxs_mmc_reset(host);
+
+	dma_cap_zero(mask);
+	dma_cap_set(DMA_SLAVE, mask);
+	host->dma_data.chan_irq = irq_dma;
+	host->dmach = dma_request_channel(mask, mxs_mmc_dma_filter, host);
+	if (!host->dmach) {
+		dev_err(mmc_dev(host->mmc),
+			"%s: failed to request dma\n", __func__);
+		goto out_clk_put;
+	}
+
+	/* set mmc core parameters */
+	mmc->ops = &mxs_mmc_ops;
+	mmc->caps = MMC_CAP_SD_HIGHSPEED | MMC_CAP_MMC_HIGHSPEED |
+		    MMC_CAP_SDIO_IRQ | MMC_CAP_NEEDS_POLL;
+
+	pdata =	mmc_dev(host->mmc)->platform_data;
+	if (pdata) {
+		if (pdata->flags & SLOTF_8_BIT_CAPABLE)
+			mmc->caps |= MMC_CAP_4_BIT_DATA | MMC_CAP_8_BIT_DATA;
+		if (pdata->flags & SLOTF_4_BIT_CAPABLE)
+			mmc->caps |= MMC_CAP_4_BIT_DATA;
+	}
+
+	mmc->f_min = 400000;
+	mmc->f_max = 288000000;
+	mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	mmc->max_segs = 52;
+	mmc->max_blk_size = 1 << 0xf;
+	mmc->max_blk_count = (ssp_is_old()) ? 0xff : 0xffffff;
+	mmc->max_req_size = (ssp_is_old()) ? 0xffff : 0xffffffff;
+	mmc->max_seg_size = dma_get_max_seg_size(host->dmach->device->dev);
+
+	platform_set_drvdata(pdev, mmc);
+
+	ret = request_irq(host->irq, mxs_mmc_irq_handler, 0, DRIVER_NAME, host);
+	if (ret)
+		goto out_free_dma;
+
+	spin_lock_init(&host->lock);
+
+	ret = mmc_add_host(mmc);
+	if (ret)
+		goto out_free_irq;
+
+	dev_info(mmc_dev(host->mmc), "initialized\n");
+
+	return 0;
+
+out_free_irq:
+	free_irq(host->irq, host);
+out_free_dma:
+	if (host->dmach)
+		dma_release_channel(host->dmach);
+out_clk_put:
+	clk_disable(host->clk);
+	clk_put(host->clk);
+out_iounmap:
+	iounmap(host->base);
+out_mmc_free:
+	mmc_free_host(mmc);
+out_release_mem:
+	release_mem_region(iores->start, resource_size(iores));
+	return ret;
+}
+
+static int mxs_mmc_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	struct resource *res = host->res;
+
+	mmc_remove_host(mmc);
+
+	free_irq(host->irq, host);
+
+	platform_set_drvdata(pdev, NULL);
+
+	if (host->dmach)
+		dma_release_channel(host->dmach);
+
+	clk_disable(host->clk);
+	clk_put(host->clk);
+
+	iounmap(host->base);
+
+	mmc_free_host(mmc);
+
+	release_mem_region(res->start, resource_size(res));
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int mxs_mmc_suspend(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	int ret = 0;
+
+	ret = mmc_suspend_host(mmc);
+
+	clk_disable(host->clk);
+
+	return ret;
+}
+
+static int mxs_mmc_resume(struct device *dev)
+{
+	struct mmc_host *mmc = dev_get_drvdata(dev);
+	struct mxs_mmc_host *host = mmc_priv(mmc);
+	int ret = 0;
+
+	clk_enable(host->clk);
+
+	ret = mmc_resume_host(mmc);
+
+	return ret;
+}
+
+static const struct dev_pm_ops mxs_mmc_pm_ops = {
+	.suspend	= mxs_mmc_suspend,
+	.resume		= mxs_mmc_resume,
+};
+#endif
+
+static struct platform_driver mxs_mmc_driver = {
+	.probe		= mxs_mmc_probe,
+	.remove		= mxs_mmc_remove,
+	.driver		= {
+		.name	= DRIVER_NAME,
+		.owner	= THIS_MODULE,
+#ifdef CONFIG_PM
+		.pm	= &mxs_mmc_pm_ops,
+#endif
+	},
+};
+
+static int __init mxs_mmc_init(void)
+{
+	return platform_driver_register(&mxs_mmc_driver);
+}
+
+static void __exit mxs_mmc_exit(void)
+{
+	platform_driver_unregister(&mxs_mmc_driver);
+}
+
+module_init(mxs_mmc_init);
+module_exit(mxs_mmc_exit);
+
+MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral");
+MODULE_AUTHOR("Freescale Semiconductor");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/of_mmc_spi.c linux-libre-2.6.39-gnu/drivers/mmc/host/of_mmc_spi.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/of_mmc_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/of_mmc_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,9 +15,11 @@
 #include <linux/module.h>
 #include <linux/device.h>
 #include <linux/slab.h>
+#include <linux/irq.h>
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
+#include <linux/of_irq.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/mmc_spi.h>
 #include <linux/mmc/core.h>
@@ -34,6 +36,7 @@
 struct of_mmc_spi {
 	int gpios[NUM_GPIOS];
 	bool alow_gpios[NUM_GPIOS];
+	int detect_irq;
 	struct mmc_spi_platform_data pdata;
 };
 
@@ -61,6 +64,22 @@
 	return of_mmc_spi_read_gpio(dev, WP_GPIO);
 }
 
+static int of_mmc_spi_init(struct device *dev,
+			   irqreturn_t (*irqhandler)(int, void *), void *mmc)
+{
+	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+
+	return request_threaded_irq(oms->detect_irq, NULL, irqhandler, 0,
+				    dev_name(dev), mmc);
+}
+
+static void of_mmc_spi_exit(struct device *dev, void *mmc)
+{
+	struct of_mmc_spi *oms = to_of_mmc_spi(dev);
+
+	free_irq(oms->detect_irq, mmc);
+}
+
 struct mmc_spi_platform_data *mmc_spi_get_pdata(struct spi_device *spi)
 {
 	struct device *dev = &spi->dev;
@@ -121,8 +140,13 @@
 	if (gpio_is_valid(oms->gpios[WP_GPIO]))
 		oms->pdata.get_ro = of_mmc_spi_get_ro;
 
-	/* We don't support interrupts yet, let's poll. */
-	oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
+	oms->detect_irq = irq_of_parse_and_map(np, 0);
+	if (oms->detect_irq != NO_IRQ) {
+		oms->pdata.init = of_mmc_spi_init;
+		oms->pdata.exit = of_mmc_spi_exit;
+	} else {
+		oms->pdata.caps |= MMC_CAP_NEEDS_POLL;
+	}
 
 	dev->platform_data = &oms->pdata;
 	return dev->platform_data;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/omap.c linux-libre-2.6.39-gnu/drivers/mmc/host/omap.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/omap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/omap.c	2011-05-19 00:06:34.000000000 -0400
@@ -832,7 +832,7 @@
 		return IRQ_HANDLED;
 	}
 
-	if (end_command)
+	if (end_command && host->cmd)
 		mmc_omap_cmd_done(host, host->cmd);
 	if (host->data != NULL) {
 		if (transfer_error)
@@ -1417,7 +1417,7 @@
 	if (res == NULL || irq < 0)
 		return -ENXIO;
 
-	res = request_mem_region(res->start, res->end - res->start + 1,
+	res = request_mem_region(res->start, resource_size(res),
 				 pdev->name);
 	if (res == NULL)
 		return -EBUSY;
@@ -1457,7 +1457,7 @@
 
 	host->irq = irq;
 	host->phys_base = host->mem_res->start;
-	host->virt_base = ioremap(res->start, res->end - res->start + 1);
+	host->virt_base = ioremap(res->start, resource_size(res));
 	if (!host->virt_base)
 		goto err_ioremap;
 
@@ -1514,7 +1514,7 @@
 err_ioremap:
 	kfree(host);
 err_free_mem_region:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/omap_hsmmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/omap_hsmmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/omap_hsmmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/omap_hsmmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,7 @@
 
 #define MMC_TIMEOUT_MS		20
 #define OMAP_MMC_MASTER_CLOCK	96000000
-#define DRIVER_NAME		"mmci-omap-hs"
+#define DRIVER_NAME		"omap_hsmmc"
 
 /* Timeouts for entering power saving states on inactivity, msec */
 #define OMAP_MMC_DISABLED_TIMEOUT	100
@@ -260,7 +260,7 @@
 	return ret;
 }
 
-static int omap_hsmmc_23_set_power(struct device *dev, int slot, int power_on,
+static int omap_hsmmc_235_set_power(struct device *dev, int slot, int power_on,
 				   int vdd)
 {
 	struct omap_hsmmc_host *host =
@@ -316,6 +316,12 @@
 	return ret;
 }
 
+static int omap_hsmmc_4_set_power(struct device *dev, int slot, int power_on,
+					int vdd)
+{
+	return 0;
+}
+
 static int omap_hsmmc_1_set_sleep(struct device *dev, int slot, int sleep,
 				  int vdd, int cardsleep)
 {
@@ -326,7 +332,7 @@
 	return regulator_set_mode(host->vcc, mode);
 }
 
-static int omap_hsmmc_23_set_sleep(struct device *dev, int slot, int sleep,
+static int omap_hsmmc_235_set_sleep(struct device *dev, int slot, int sleep,
 				   int vdd, int cardsleep)
 {
 	struct omap_hsmmc_host *host =
@@ -365,6 +371,12 @@
 		return regulator_enable(host->vcc_aux);
 }
 
+static int omap_hsmmc_4_set_sleep(struct device *dev, int slot, int sleep,
+					int vdd, int cardsleep)
+{
+	return 0;
+}
+
 static int omap_hsmmc_reg_get(struct omap_hsmmc_host *host)
 {
 	struct regulator *reg;
@@ -379,10 +391,14 @@
 		break;
 	case OMAP_MMC2_DEVID:
 	case OMAP_MMC3_DEVID:
+	case OMAP_MMC5_DEVID:
 		/* Off-chip level shifting, or none */
-		mmc_slot(host).set_power = omap_hsmmc_23_set_power;
-		mmc_slot(host).set_sleep = omap_hsmmc_23_set_sleep;
+		mmc_slot(host).set_power = omap_hsmmc_235_set_power;
+		mmc_slot(host).set_sleep = omap_hsmmc_235_set_sleep;
 		break;
+	case OMAP_MMC4_DEVID:
+		mmc_slot(host).set_power = omap_hsmmc_4_set_power;
+		mmc_slot(host).set_sleep = omap_hsmmc_4_set_sleep;
 	default:
 		pr_err("MMC%d configuration not supported!\n", host->id);
 		return -EINVAL;
@@ -1555,7 +1571,7 @@
 		break;
 	}
 
-	if (host->id == OMAP_MMC1_DEVID) {
+	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		/* Only MMC1 can interface at 3V without some flavor
 		 * of external transceiver; but they all handle 1.8V.
 		 */
@@ -1647,7 +1663,7 @@
 	u32 hctl, capa, value;
 
 	/* Only MMC1 supports 3.0V */
-	if (host->id == OMAP_MMC1_DEVID) {
+	if (host->pdata->controller_flags & OMAP_HSMMC_SUPPORTS_DUAL_VOLT) {
 		hctl = SDVS30;
 		capa = VS30 | VS18;
 	} else {
@@ -2031,8 +2047,7 @@
 
 	res->start += pdata->reg_offset;
 	res->end += pdata->reg_offset;
-	res = request_mem_region(res->start, res->end - res->start + 1,
-							pdev->name);
+	res = request_mem_region(res->start, resource_size(res), pdev->name);
 	if (res == NULL)
 		return -EBUSY;
 
@@ -2101,14 +2116,14 @@
 	/* we start off in DISABLED state */
 	host->dpm_state = DISABLED;
 
-	if (mmc_host_enable(host->mmc) != 0) {
+	if (clk_enable(host->iclk) != 0) {
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
 	}
 
-	if (clk_enable(host->iclk) != 0) {
-		mmc_host_disable(host->mmc);
+	if (mmc_host_enable(host->mmc) != 0) {
+		clk_disable(host->iclk);
 		clk_put(host->iclk);
 		clk_put(host->fclk);
 		goto err1;
@@ -2271,7 +2286,7 @@
 err_alloc:
 	omap_hsmmc_gpio_free(pdata);
 err:
-	release_mem_region(res->start, res->end - res->start + 1);
+	release_mem_region(res->start, resource_size(res));
 	return ret;
 }
 
@@ -2308,7 +2323,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));
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/s3cmci.c linux-libre-2.6.39-gnu/drivers/mmc/host/s3cmci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/s3cmci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/s3cmci.c	2011-05-19 00:06:34.000000000 -0400
@@ -874,7 +874,7 @@
 	if (!mrq->data)
 		goto request_done;
 
-	/* Calulate the amout of bytes transfer if there was no error */
+	/* Calculate the amout of bytes transfer if there was no error */
 	if (mrq->data->error == 0) {
 		mrq->data->bytes_xfered =
 			(mrq->data->blocks * mrq->data->blksz);
@@ -882,7 +882,7 @@
 		mrq->data->bytes_xfered = 0;
 	}
 
-	/* If we had an error while transfering data we flush the
+	/* If we had an error while transferring data we flush the
 	 * DMA channel and the fifo to clear out any garbage. */
 	if (mrq->data->error != 0) {
 		if (s3cmci_host_usedma(host))
@@ -980,7 +980,7 @@
 
 	if ((data->blksz & 3) != 0) {
 		/* We cannot deal with unaligned blocks with more than
-		 * one block being transfered. */
+		 * one block being transferred. */
 
 		if (data->blocks > 1) {
 			pr_warning("%s: can't do non-word sized block transfers (blksz %d)\n", __func__, data->blksz);
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci.c	2011-05-19 00:06:34.000000000 -0400
@@ -1334,6 +1334,13 @@
 
 	host = (struct sdhci_host*)param;
 
+        /*
+         * If this tasklet gets rescheduled while running, it will
+         * be run again afterwards but without any active request.
+         */
+	if (!host->mrq)
+		return;
+
 	spin_lock_irqsave(&host->lock, flags);
 
 	del_timer(&host->timer);
@@ -1345,7 +1352,7 @@
 	 * upon error conditions.
 	 */
 	if (!(host->flags & SDHCI_DEVICE_DEAD) &&
-		(mrq->cmd->error ||
+	    ((mrq->cmd && mrq->cmd->error) ||
 		 (mrq->data && (mrq->data->error ||
 		  (mrq->data->stop && mrq->data->stop->error))) ||
 		   (host->quirks & SDHCI_QUIRK_RESET_AFTER_REQUEST))) {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-esdhc.h linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-esdhc.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-esdhc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-esdhc.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,13 +19,11 @@
  */
 
 #define ESDHC_DEFAULT_QUIRKS	(SDHCI_QUIRK_FORCE_BLK_SZ_2048 | \
-				SDHCI_QUIRK_BROKEN_CARD_DETECTION | \
 				SDHCI_QUIRK_NO_BUSY_IRQ | \
 				SDHCI_QUIRK_NONSTANDARD_CLOCK | \
 				SDHCI_QUIRK_DATA_TIMEOUT_USES_SDCLK | \
 				SDHCI_QUIRK_PIO_NEEDS_DELAY | \
-				SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET | \
-				SDHCI_QUIRK_NO_CARD_NO_RESET)
+				SDHCI_QUIRK_RESTORE_IRQS_AFTER_RESET)
 
 #define ESDHC_SYSTEM_CONTROL	0x2c
 #define ESDHC_CLOCK_MASK	0x0000fff0
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-esdhc-imx.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-esdhc-imx.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-esdhc-imx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-esdhc-imx.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,13 +15,41 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdhci-pltfm.h>
+#include <linux/mmc/mmc.h>
+#include <linux/mmc/sdio.h>
 #include <mach/hardware.h>
+#include <mach/esdhc.h>
 #include "sdhci.h"
 #include "sdhci-pltfm.h"
 #include "sdhci-esdhc.h"
 
+/* VENDOR SPEC register */
+#define SDHCI_VENDOR_SPEC		0xC0
+#define  SDHCI_VENDOR_SPEC_SDIO_QUIRK	0x00000002
+
+#define ESDHC_FLAG_GPIO_FOR_CD_WP	(1 << 0)
+/*
+ * The CMDTYPE of the CMD register (offset 0xE) should be set to
+ * "11" when the STOP CMD12 is issued on imx53 to abort one
+ * open ended multi-blk IO. Otherwise the TC INT wouldn't
+ * be generated.
+ * In exact block transfer, the controller doesn't complete the
+ * operations automatically as required at the end of the
+ * transfer and remains on hold if the abort command is not sent.
+ * As a result, the TC flag is not asserted and SW  received timeout
+ * exeception. Bit1 of Vendor Spec registor is used to fix it.
+ */
+#define ESDHC_FLAG_MULTIBLK_NO_INT	(1 << 1)
+
+struct pltfm_imx_data {
+	int flags;
+	u32 scratchpad;
+};
+
 static inline void esdhc_clrset_le(struct sdhci_host *host, u32 mask, u32 val, int reg)
 {
 	void __iomem *base = host->ioaddr + (reg & ~0x3);
@@ -30,6 +58,56 @@
 	writel(((readl(base) & ~(mask << shift)) | (val << shift)), base);
 }
 
+static u32 esdhc_readl_le(struct sdhci_host *host, int reg)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+	/* fake CARD_PRESENT flag on mx25/35 */
+	u32 val = readl(host->ioaddr + reg);
+
+	if (unlikely((reg == SDHCI_PRESENT_STATE)
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP))) {
+		struct esdhc_platform_data *boarddata =
+				host->mmc->parent->platform_data;
+
+		if (boarddata && gpio_is_valid(boarddata->cd_gpio)
+				&& gpio_get_value(boarddata->cd_gpio))
+			/* no card, if a valid gpio says so... */
+			val &= SDHCI_CARD_PRESENT;
+		else
+			/* ... in all other cases assume card is present */
+			val |= SDHCI_CARD_PRESENT;
+	}
+
+	return val;
+}
+
+static void esdhc_writel_le(struct sdhci_host *host, u32 val, int reg)
+{
+	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+	if (unlikely((reg == SDHCI_INT_ENABLE || reg == SDHCI_SIGNAL_ENABLE)
+			&& (imx_data->flags & ESDHC_FLAG_GPIO_FOR_CD_WP)))
+		/*
+		 * these interrupts won't work with a custom card_detect gpio
+		 * (only applied to mx25/35)
+		 */
+		val &= ~(SDHCI_INT_CARD_REMOVE | SDHCI_INT_CARD_INSERT);
+
+	if (unlikely((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
+				&& (reg == SDHCI_INT_STATUS)
+				&& (val & SDHCI_INT_DATA_END))) {
+			u32 v;
+			v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
+			v &= ~SDHCI_VENDOR_SPEC_SDIO_QUIRK;
+			writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
+	}
+
+	writel(val, host->ioaddr + reg);
+}
+
 static u16 esdhc_readw_le(struct sdhci_host *host, int reg)
 {
 	if (unlikely(reg == SDHCI_HOST_VERSION))
@@ -41,6 +119,7 @@
 static void esdhc_writew_le(struct sdhci_host *host, u16 val, int reg)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
 
 	switch (reg) {
 	case SDHCI_TRANSFER_MODE:
@@ -48,10 +127,22 @@
 		 * Postpone this write, we must do it together with a
 		 * command write that is down below.
 		 */
-		pltfm_host->scratchpad = val;
+		if ((imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT)
+				&& (host->cmd->opcode == SD_IO_RW_EXTENDED)
+				&& (host->cmd->data->blocks > 1)
+				&& (host->cmd->data->flags & MMC_DATA_READ)) {
+			u32 v;
+			v = readl(host->ioaddr + SDHCI_VENDOR_SPEC);
+			v |= SDHCI_VENDOR_SPEC_SDIO_QUIRK;
+			writel(v, host->ioaddr + SDHCI_VENDOR_SPEC);
+		}
+		imx_data->scratchpad = val;
 		return;
 	case SDHCI_COMMAND:
-		writel(val << 16 | pltfm_host->scratchpad,
+		if ((host->cmd->opcode == MMC_STOP_TRANSMISSION)
+			&& (imx_data->flags & ESDHC_FLAG_MULTIBLK_NO_INT))
+			val |= SDHCI_CMD_ABORTCMD;
+		writel(val << 16 | imx_data->scratchpad,
 			host->ioaddr + SDHCI_TRANSFER_MODE);
 		return;
 	case SDHCI_BLOCK_SIZE:
@@ -100,10 +191,42 @@
 	return clk_get_rate(pltfm_host->clk) / 256 / 16;
 }
 
+static unsigned int esdhc_pltfm_get_ro(struct sdhci_host *host)
+{
+	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+
+	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+		return gpio_get_value(boarddata->wp_gpio);
+	else
+		return -ENOSYS;
+}
+
+static struct sdhci_ops sdhci_esdhc_ops = {
+	.read_l = esdhc_readl_le,
+	.read_w = esdhc_readw_le,
+	.write_l = esdhc_writel_le,
+	.write_w = esdhc_writew_le,
+	.write_b = esdhc_writeb_le,
+	.set_clock = esdhc_set_clock,
+	.get_max_clock = esdhc_pltfm_get_max_clock,
+	.get_min_clock = esdhc_pltfm_get_min_clock,
+};
+
+static irqreturn_t cd_irq(int irq, void *data)
+{
+	struct sdhci_host *sdhost = (struct sdhci_host *)data;
+
+	tasklet_schedule(&sdhost->card_tasklet);
+	return IRQ_HANDLED;
+};
+
 static int esdhc_pltfm_init(struct sdhci_host *host, struct sdhci_pltfm_data *pdata)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
 	struct clk *clk;
+	int err;
+	struct pltfm_imx_data *imx_data;
 
 	clk = clk_get(mmc_dev(host->mmc), NULL);
 	if (IS_ERR(clk)) {
@@ -113,35 +236,94 @@
 	clk_enable(clk);
 	pltfm_host->clk = clk;
 
-	if (cpu_is_mx35() || cpu_is_mx51())
+	imx_data = kzalloc(sizeof(struct pltfm_imx_data), GFP_KERNEL);
+	if (!imx_data) {
+		clk_disable(pltfm_host->clk);
+		clk_put(pltfm_host->clk);
+		return -ENOMEM;
+	}
+	pltfm_host->priv = imx_data;
+
+	if (!cpu_is_mx25())
 		host->quirks |= SDHCI_QUIRK_BROKEN_TIMEOUT_VAL;
 
-	/* Fix errata ENGcm07207 which is present on i.MX25 and i.MX35 */
-	if (cpu_is_mx25() || cpu_is_mx35())
+	if (cpu_is_mx25() || cpu_is_mx35()) {
+		/* Fix errata ENGcm07207 present on i.MX25 and i.MX35 */
 		host->quirks |= SDHCI_QUIRK_NO_MULTIBLOCK;
+		/* write_protect can't be routed to controller, use gpio */
+		sdhci_esdhc_ops.get_ro = esdhc_pltfm_get_ro;
+	}
+
+	if (!(cpu_is_mx25() || cpu_is_mx35() || cpu_is_mx51()))
+		imx_data->flags |= ESDHC_FLAG_MULTIBLK_NO_INT;
+
+	if (boarddata) {
+		err = gpio_request_one(boarddata->wp_gpio, GPIOF_IN, "ESDHC_WP");
+		if (err) {
+			dev_warn(mmc_dev(host->mmc),
+				"no write-protect pin available!\n");
+			boarddata->wp_gpio = err;
+		}
+
+		err = gpio_request_one(boarddata->cd_gpio, GPIOF_IN, "ESDHC_CD");
+		if (err) {
+			dev_warn(mmc_dev(host->mmc),
+				"no card-detect pin available!\n");
+			goto no_card_detect_pin;
+		}
+
+		/* i.MX5x has issues to be researched */
+		if (!cpu_is_mx25() && !cpu_is_mx35())
+			goto not_supported;
+
+		err = request_irq(gpio_to_irq(boarddata->cd_gpio), cd_irq,
+				 IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING,
+				 mmc_hostname(host->mmc), host);
+		if (err) {
+			dev_warn(mmc_dev(host->mmc), "request irq error\n");
+			goto no_card_detect_irq;
+		}
+
+		imx_data->flags |= ESDHC_FLAG_GPIO_FOR_CD_WP;
+		/* Now we have a working card_detect again */
+		host->quirks &= ~SDHCI_QUIRK_BROKEN_CARD_DETECTION;
+	}
 
 	return 0;
+
+ no_card_detect_irq:
+	gpio_free(boarddata->cd_gpio);
+ no_card_detect_pin:
+	boarddata->cd_gpio = err;
+ not_supported:
+	kfree(imx_data);
+	return 0;
 }
 
 static void esdhc_pltfm_exit(struct sdhci_host *host)
 {
 	struct sdhci_pltfm_host *pltfm_host = sdhci_priv(host);
+	struct esdhc_platform_data *boarddata = host->mmc->parent->platform_data;
+	struct pltfm_imx_data *imx_data = pltfm_host->priv;
+
+	if (boarddata && gpio_is_valid(boarddata->wp_gpio))
+		gpio_free(boarddata->wp_gpio);
+
+	if (boarddata && gpio_is_valid(boarddata->cd_gpio)) {
+		gpio_free(boarddata->cd_gpio);
+
+		if (!(host->quirks & SDHCI_QUIRK_BROKEN_CARD_DETECTION))
+			free_irq(gpio_to_irq(boarddata->cd_gpio), host);
+	}
 
 	clk_disable(pltfm_host->clk);
 	clk_put(pltfm_host->clk);
+	kfree(imx_data);
 }
 
-static struct sdhci_ops sdhci_esdhc_ops = {
-	.read_w = esdhc_readw_le,
-	.write_w = esdhc_writew_le,
-	.write_b = esdhc_writeb_le,
-	.set_clock = esdhc_set_clock,
-	.get_max_clock = esdhc_pltfm_get_max_clock,
-	.get_min_clock = esdhc_pltfm_get_min_clock,
-};
-
 struct sdhci_pltfm_data sdhci_esdhc_imx_pdata = {
-	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA,
+	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_ADMA
+			| SDHCI_QUIRK_BROKEN_CARD_DETECTION,
 	/* ADMA has issues. Might be fixable */
 	.ops = &sdhci_esdhc_ops,
 	.init = esdhc_pltfm_init,
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci.h linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 #define  SDHCI_CMD_CRC		0x08
 #define  SDHCI_CMD_INDEX	0x10
 #define  SDHCI_CMD_DATA		0x20
+#define  SDHCI_CMD_ABORTCMD	0xC0
 
 #define  SDHCI_CMD_RESP_NONE	0x00
 #define  SDHCI_CMD_RESP_LONG	0x01
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-of-core.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-of-core.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-of-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-of-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -124,17 +124,23 @@
 #endif
 }
 
-static int __devinit sdhci_of_probe(struct platform_device *ofdev,
-				 const struct of_device_id *match)
+static const struct of_device_id sdhci_of_match[];
+static int __devinit sdhci_of_probe(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
 	struct device_node *np = ofdev->dev.of_node;
-	struct sdhci_of_data *sdhci_of_data = match->data;
+	struct sdhci_of_data *sdhci_of_data;
 	struct sdhci_host *host;
 	struct sdhci_of_host *of_host;
 	const __be32 *clk;
 	int size;
 	int ret;
 
+	match = of_match_device(sdhci_of_match, &ofdev->dev);
+	if (!match)
+		return -EINVAL;
+	sdhci_of_data = match->data;
+
 	if (!of_device_is_available(np))
 		return -ENODEV;
 
@@ -217,7 +223,7 @@
 };
 MODULE_DEVICE_TABLE(of, sdhci_of_match);
 
-static struct of_platform_driver sdhci_of_driver = {
+static struct platform_driver sdhci_of_driver = {
 	.driver = {
 		.name = "sdhci-of",
 		.owner = THIS_MODULE,
@@ -231,13 +237,13 @@
 
 static int __init sdhci_of_init(void)
 {
-	return of_register_platform_driver(&sdhci_of_driver);
+	return platform_driver_register(&sdhci_of_driver);
 }
 module_init(sdhci_of_init);
 
 static void __exit sdhci_of_exit(void)
 {
-	of_unregister_platform_driver(&sdhci_of_driver);
+	platform_driver_unregister(&sdhci_of_driver);
 }
 module_exit(sdhci_of_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-of-esdhc.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-of-esdhc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-of-esdhc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-of-esdhc.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,9 @@
 }
 
 struct sdhci_of_data sdhci_esdhc = {
-	.quirks = ESDHC_DEFAULT_QUIRKS,
+	/* card detection could be handled via GPIO */
+	.quirks = ESDHC_DEFAULT_QUIRKS | SDHCI_QUIRK_BROKEN_CARD_DETECTION
+		| SDHCI_QUIRK_NO_CARD_NO_RESET,
 	.ops = {
 		.read_l = sdhci_be32bs_readl,
 		.read_w = esdhc_readw,
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-pci.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-pci.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -547,6 +547,14 @@
 	},
 
 	{
+		.vendor         = PCI_VENDOR_ID_RICOH,
+		.device         = 0xe823,
+		.subvendor      = PCI_ANY_ID,
+		.subdevice      = PCI_ANY_ID,
+		.driver_data    = (kernel_ulong_t)&sdhci_ricoh_mmc,
+	},
+
+	{
 		.vendor		= PCI_VENDOR_ID_ENE,
 		.device		= PCI_DEVICE_ID_ENE_CB712_SD,
 		.subvendor	= PCI_ANY_ID,
@@ -900,9 +908,6 @@
 {
 	struct sdhci_pci_slot *slot;
 	struct sdhci_host *host;
-
-	resource_size_t addr;
-
 	int ret;
 
 	if (!(pci_resource_flags(pdev, bar) & IORESOURCE_MEM)) {
@@ -949,10 +954,10 @@
 		goto free;
 	}
 
-	addr = pci_resource_start(pdev, bar);
 	host->ioaddr = pci_ioremap_bar(pdev, bar);
 	if (!host->ioaddr) {
 		dev_err(&pdev->dev, "failed to remap registers\n");
+		ret = -ENOMEM;
 		goto release;
 	}
 
@@ -1012,16 +1017,14 @@
 	struct sdhci_pci_chip *chip;
 	struct sdhci_pci_slot *slot;
 
-	u8 slots, rev, first_bar;
+	u8 slots, first_bar;
 	int ret, i;
 
 	BUG_ON(pdev == NULL);
 	BUG_ON(ent == NULL);
 
-	pci_read_config_byte(pdev, PCI_CLASS_REVISION, &rev);
-
 	dev_info(&pdev->dev, "SDHCI controller found [%04x:%04x] (rev %x)\n",
-		 (int)pdev->vendor, (int)pdev->device, (int)rev);
+		 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
 
 	ret = pci_read_config_byte(pdev, PCI_SLOT_INFO, &slots);
 	if (ret)
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-pltfm.h linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-pltfm.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-pltfm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-pltfm.h	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
 
 struct sdhci_pltfm_host {
 	struct clk *clk;
-	u32 scratchpad; /* to handle quirks across io-accessor calls */
+	void *priv; /* to handle quirks across io-accessor calls */
 };
 
 extern struct sdhci_pltfm_data sdhci_cns3xxx_pdata;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-s3c.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-s3c.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-s3c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-s3c.c	2011-05-19 00:06:34.000000000 -0400
@@ -499,6 +499,9 @@
 	 * SDHCI block, or a missing configuration that needs to be set. */
 	host->quirks |= SDHCI_QUIRK_NO_BUSY_IRQ;
 
+	/* This host supports the Auto CMD12 */
+	host->quirks |= SDHCI_QUIRK_MULTIBLOCK_READ_ACMD12;
+
 	if (pdata->cd_type == S3C_SDHCI_CD_NONE ||
 	    pdata->cd_type == S3C_SDHCI_CD_PERMANENT)
 		host->quirks |= SDHCI_QUIRK_BROKEN_CARD_DETECTION;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-spear.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-spear.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-spear.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-spear.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 	/* val == 1 -> card removed, val == 0 -> card inserted */
 	/* if card removed - set irq for low level, else vice versa */
 	gpio_irq_type = val ? IRQF_TRIGGER_LOW : IRQF_TRIGGER_HIGH;
-	set_irq_type(irq, gpio_irq_type);
+	irq_set_irq_type(irq, gpio_irq_type);
 
 	if (sdhci->data->card_power_gpio >= 0) {
 		if (!sdhci->data->power_always_enb) {
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-tegra.c linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-tegra.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sdhci-tegra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sdhci-tegra.c	2011-05-19 00:06:34.000000000 -0400
@@ -169,7 +169,7 @@
 		if (rc) {
 			dev_err(mmc_dev(host->mmc),
 				"failed to allocate wp gpio\n");
-			goto out_cd;
+			goto out_irq;
 		}
 		tegra_gpio_enable(plat->wp_gpio);
 		gpio_direction_input(plat->wp_gpio);
@@ -195,6 +195,9 @@
 		gpio_free(plat->wp_gpio);
 	}
 
+out_irq:
+	if (gpio_is_valid(plat->cd_gpio))
+		free_irq(gpio_to_irq(plat->cd_gpio), host);
 out_cd:
 	if (gpio_is_valid(plat->cd_gpio)) {
 		tegra_gpio_disable(plat->cd_gpio);
@@ -225,6 +228,7 @@
 	}
 
 	if (gpio_is_valid(plat->cd_gpio)) {
+		free_irq(gpio_to_irq(plat->cd_gpio), host);
 		tegra_gpio_disable(plat->cd_gpio);
 		gpio_free(plat->cd_gpio);
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sh_mmcif.c linux-libre-2.6.39-gnu/drivers/mmc/host/sh_mmcif.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sh_mmcif.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sh_mmcif.c	2011-05-19 00:06:34.000000000 -0400
@@ -169,7 +169,7 @@
 	struct dma_chan		*chan_rx;
 	struct dma_chan		*chan_tx;
 	struct completion	dma_complete;
-	unsigned int            dma_sglen;
+	bool			dma_active;
 };
 
 static inline void sh_mmcif_bitset(struct sh_mmcif_host *host,
@@ -194,10 +194,12 @@
 		return;
 
 	if (host->data->flags & MMC_DATA_READ)
-		dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+		dma_unmap_sg(host->chan_rx->device->dev,
+			     host->data->sg, host->data->sg_len,
 			     DMA_FROM_DEVICE);
 	else
-		dma_unmap_sg(&host->pd->dev, host->data->sg, host->dma_sglen,
+		dma_unmap_sg(host->chan_tx->device->dev,
+			     host->data->sg, host->data->sg_len,
 			     DMA_TO_DEVICE);
 
 	complete(&host->dma_complete);
@@ -211,9 +213,10 @@
 	dma_cookie_t cookie = -EINVAL;
 	int ret;
 
-	ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_FROM_DEVICE);
+	ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+			 DMA_FROM_DEVICE);
 	if (ret > 0) {
-		host->dma_sglen = ret;
+		host->dma_active = true;
 		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
 			DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	}
@@ -221,14 +224,9 @@
 	if (desc) {
 		desc->callback = mmcif_dma_complete;
 		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		} else {
-			sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
-			chan->device->device_issue_pending(chan);
-		}
+		cookie = dmaengine_submit(desc);
+		sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAREN);
+		dma_async_issue_pending(chan);
 	}
 	dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
 		__func__, host->data->sg_len, ret, cookie);
@@ -238,7 +236,7 @@
 		if (ret >= 0)
 			ret = -EIO;
 		host->chan_rx = NULL;
-		host->dma_sglen = 0;
+		host->dma_active = false;
 		dma_release_channel(chan);
 		/* Free the Tx channel too */
 		chan = host->chan_tx;
@@ -263,9 +261,10 @@
 	dma_cookie_t cookie = -EINVAL;
 	int ret;
 
-	ret = dma_map_sg(&host->pd->dev, sg, host->data->sg_len, DMA_TO_DEVICE);
+	ret = dma_map_sg(chan->device->dev, sg, host->data->sg_len,
+			 DMA_TO_DEVICE);
 	if (ret > 0) {
-		host->dma_sglen = ret;
+		host->dma_active = true;
 		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
 			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
 	}
@@ -273,14 +272,9 @@
 	if (desc) {
 		desc->callback = mmcif_dma_complete;
 		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		} else {
-			sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
-			chan->device->device_issue_pending(chan);
-		}
+		cookie = dmaengine_submit(desc);
+		sh_mmcif_bitset(host, MMCIF_CE_BUF_ACC, BUF_ACC_DMAWEN);
+		dma_async_issue_pending(chan);
 	}
 	dev_dbg(&host->pd->dev, "%s(): mapped %d -> %d, cookie %d\n",
 		__func__, host->data->sg_len, ret, cookie);
@@ -290,7 +284,7 @@
 		if (ret >= 0)
 			ret = -EIO;
 		host->chan_tx = NULL;
-		host->dma_sglen = 0;
+		host->dma_active = false;
 		dma_release_channel(chan);
 		/* Free the Rx channel too */
 		chan = host->chan_rx;
@@ -317,7 +311,7 @@
 static void sh_mmcif_request_dma(struct sh_mmcif_host *host,
 				 struct sh_mmcif_plat_data *pdata)
 {
-	host->dma_sglen = 0;
+	host->dma_active = false;
 
 	/* We can only either use DMA for both Tx and Rx or not use it at all */
 	if (pdata->dma) {
@@ -364,7 +358,7 @@
 		dma_release_channel(chan);
 	}
 
-	host->dma_sglen = 0;
+	host->dma_active = false;
 }
 
 static void sh_mmcif_clock_control(struct sh_mmcif_host *host, unsigned int clk)
@@ -753,7 +747,7 @@
 	}
 	sh_mmcif_get_response(host, cmd);
 	if (host->data) {
-		if (!host->dma_sglen) {
+		if (!host->dma_active) {
 			ret = sh_mmcif_data_trans(host, mrq, cmd->opcode);
 		} else {
 			long time =
@@ -765,7 +759,7 @@
 				ret = time;
 			sh_mmcif_bitclr(host, MMCIF_CE_BUF_ACC,
 					BUF_ACC_DMAREN | BUF_ACC_DMAWEN);
-			host->dma_sglen = 0;
+			host->dma_active = false;
 		}
 		if (ret < 0)
 			mrq->data->bytes_xfered = 0;
@@ -850,15 +844,15 @@
 	struct sh_mmcif_host *host = mmc_priv(mmc);
 	struct sh_mmcif_plat_data *p = host->pd->dev.platform_data;
 
-	if (ios->power_mode == MMC_POWER_OFF) {
+	if (ios->power_mode == MMC_POWER_UP) {
+		if (p->set_pwr)
+			p->set_pwr(host->pd, ios->power_mode);
+	} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
 		/* clock stop */
 		sh_mmcif_clock_control(host, 0);
-		if (p->down_pwr)
+		if (ios->power_mode == MMC_POWER_OFF && p->down_pwr)
 			p->down_pwr(host->pd);
 		return;
-	} else if (ios->power_mode == MMC_POWER_UP) {
-		if (p->set_pwr)
-			p->set_pwr(host->pd, ios->power_mode);
 	}
 
 	if (ios->clock)
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/sh_mobile_sdhi.c linux-libre-2.6.39-gnu/drivers/mmc/host/sh_mobile_sdhi.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/sh_mobile_sdhi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/sh_mobile_sdhi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,171 @@
+/*
+ * SuperH Mobile SDHI
+ *
+ * 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 version 2 as
+ * published by the Free Software Foundation.
+ *
+ * Based on "Compaq ASIC3 support":
+ *
+ * Copyright 2001 Compaq Computer Corporation.
+ * Copyright 2004-2005 Phil Blundell
+ * Copyright 2007-2008 OpenedHand Ltd.
+ *
+ * Authors: Phil Blundell <pb@handhelds.org>,
+ *	    Samuel Ortiz <sameo@openedhand.com>
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/sh_mobile_sdhi.h>
+#include <linux/mfd/tmio.h>
+#include <linux/sh_dma.h>
+
+#include "tmio_mmc.h"
+
+struct sh_mobile_sdhi {
+	struct clk *clk;
+	struct tmio_mmc_data mmc_data;
+	struct sh_dmae_slave param_tx;
+	struct sh_dmae_slave param_rx;
+	struct tmio_mmc_dma dma_priv;
+};
+
+static void sh_mobile_sdhi_set_pwr(struct platform_device *pdev, int state)
+{
+	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+
+	if (p && p->set_pwr)
+		p->set_pwr(pdev, state);
+}
+
+static int sh_mobile_sdhi_get_cd(struct platform_device *pdev)
+{
+	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+
+	if (p && p->get_cd)
+		return p->get_cd(pdev);
+	else
+		return -ENOSYS;
+}
+
+static int __devinit sh_mobile_sdhi_probe(struct platform_device *pdev)
+{
+	struct sh_mobile_sdhi *priv;
+	struct tmio_mmc_data *mmc_data;
+	struct sh_mobile_sdhi_info *p = pdev->dev.platform_data;
+	struct tmio_mmc_host *host;
+	char clk_name[8];
+	int ret;
+
+	priv = kzalloc(sizeof(struct sh_mobile_sdhi), GFP_KERNEL);
+	if (priv == NULL) {
+		dev_err(&pdev->dev, "kzalloc failed\n");
+		return -ENOMEM;
+	}
+
+	mmc_data = &priv->mmc_data;
+
+	snprintf(clk_name, sizeof(clk_name), "sdhi%d", pdev->id);
+	priv->clk = clk_get(&pdev->dev, clk_name);
+	if (IS_ERR(priv->clk)) {
+		dev_err(&pdev->dev, "cannot get clock \"%s\"\n", clk_name);
+		ret = PTR_ERR(priv->clk);
+		goto eclkget;
+	}
+
+	clk_enable(priv->clk);
+
+	mmc_data->hclk = clk_get_rate(priv->clk);
+	mmc_data->set_pwr = sh_mobile_sdhi_set_pwr;
+	mmc_data->get_cd = sh_mobile_sdhi_get_cd;
+	mmc_data->capabilities = MMC_CAP_MMC_HIGHSPEED;
+	if (p) {
+		mmc_data->flags = p->tmio_flags;
+		mmc_data->ocr_mask = p->tmio_ocr_mask;
+		mmc_data->capabilities |= p->tmio_caps;
+
+		if (p->dma_slave_tx >= 0 && p->dma_slave_rx >= 0) {
+			priv->param_tx.slave_id = p->dma_slave_tx;
+			priv->param_rx.slave_id = p->dma_slave_rx;
+			priv->dma_priv.chan_priv_tx = &priv->param_tx;
+			priv->dma_priv.chan_priv_rx = &priv->param_rx;
+			priv->dma_priv.alignment_shift = 1; /* 2-byte alignment */
+			mmc_data->dma = &priv->dma_priv;
+		}
+	}
+
+	/*
+	 * All SDHI blocks support 2-byte and larger block sizes in 4-bit
+	 * bus width mode.
+	 */
+	mmc_data->flags |= TMIO_MMC_BLKSZ_2BYTES;
+
+	/*
+	 * All SDHI blocks support SDIO IRQ signalling.
+	 */
+	mmc_data->flags |= TMIO_MMC_SDIO_IRQ;
+
+	ret = tmio_mmc_host_probe(&host, pdev, mmc_data);
+	if (ret < 0)
+		goto eprobe;
+
+	pr_info("%s at 0x%08lx irq %d\n", mmc_hostname(host->mmc),
+		(unsigned long)host->ctl, host->irq);
+
+	return ret;
+
+eprobe:
+	clk_disable(priv->clk);
+	clk_put(priv->clk);
+eclkget:
+	kfree(priv);
+	return ret;
+}
+
+static int sh_mobile_sdhi_remove(struct platform_device *pdev)
+{
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+	struct sh_mobile_sdhi *priv = container_of(host->pdata, struct sh_mobile_sdhi, mmc_data);
+
+	tmio_mmc_host_remove(host);
+	clk_disable(priv->clk);
+	clk_put(priv->clk);
+	kfree(priv);
+
+	return 0;
+}
+
+static struct platform_driver sh_mobile_sdhi_driver = {
+	.driver		= {
+		.name	= "sh_mobile_sdhi",
+		.owner	= THIS_MODULE,
+	},
+	.probe		= sh_mobile_sdhi_probe,
+	.remove		= __devexit_p(sh_mobile_sdhi_remove),
+};
+
+static int __init sh_mobile_sdhi_init(void)
+{
+	return platform_driver_register(&sh_mobile_sdhi_driver);
+}
+
+static void __exit sh_mobile_sdhi_exit(void)
+{
+	platform_driver_unregister(&sh_mobile_sdhi_driver);
+}
+
+module_init(sh_mobile_sdhi_init);
+module_exit(sh_mobile_sdhi_exit);
+
+MODULE_DESCRIPTION("SuperH Mobile SDHI driver");
+MODULE_AUTHOR("Magnus Damm");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:sh_mobile_sdhi");
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,8 @@
 /*
- *  linux/drivers/mmc/tmio_mmc.c
+ * linux/drivers/mmc/host/tmio_mmc.c
  *
- *  Copyright (C) 2004 Ian Molton
- *  Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
  *
  * 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,1203 +11,22 @@
  * Driver for the MMC / SD / SDIO cell found in:
  *
  * 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
- * support). (Further 4 bit support from a later datasheet).
- *
- * TODO:
- *   Investigate using a workqueue for PIO transfers
- *   Eliminate FIXMEs
- *   SDIO support
- *   Better Power management
- *   Handle MMC errors better
- *   double buffer support
- *
  */
 
-#include <linux/delay.h>
 #include <linux/device.h>
-#include <linux/dmaengine.h>
-#include <linux/highmem.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/irq.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/tmio.h>
 #include <linux/mmc/host.h>
 #include <linux/module.h>
 #include <linux/pagemap.h>
 #include <linux/scatterlist.h>
-#include <linux/workqueue.h>
-#include <linux/spinlock.h>
-
-#define CTL_SD_CMD 0x00
-#define CTL_ARG_REG 0x04
-#define CTL_STOP_INTERNAL_ACTION 0x08
-#define CTL_XFER_BLK_COUNT 0xa
-#define CTL_RESPONSE 0x0c
-#define CTL_STATUS 0x1c
-#define CTL_IRQ_MASK 0x20
-#define CTL_SD_CARD_CLK_CTL 0x24
-#define CTL_SD_XFER_LEN 0x26
-#define CTL_SD_MEM_CARD_OPT 0x28
-#define CTL_SD_ERROR_DETAIL_STATUS 0x2c
-#define CTL_SD_DATA_PORT 0x30
-#define CTL_TRANSACTION_CTL 0x34
-#define CTL_SDIO_STATUS 0x36
-#define CTL_SDIO_IRQ_MASK 0x38
-#define CTL_RESET_SD 0xe0
-#define CTL_SDIO_REGS 0x100
-#define CTL_CLK_AND_WAIT_CTL 0x138
-#define CTL_RESET_SDIO 0x1e0
-
-/* Definitions for values the CTRL_STATUS register can take. */
-#define TMIO_STAT_CMDRESPEND    0x00000001
-#define TMIO_STAT_DATAEND       0x00000004
-#define TMIO_STAT_CARD_REMOVE   0x00000008
-#define TMIO_STAT_CARD_INSERT   0x00000010
-#define TMIO_STAT_SIGSTATE      0x00000020
-#define TMIO_STAT_WRPROTECT     0x00000080
-#define TMIO_STAT_CARD_REMOVE_A 0x00000100
-#define TMIO_STAT_CARD_INSERT_A 0x00000200
-#define TMIO_STAT_SIGSTATE_A    0x00000400
-#define TMIO_STAT_CMD_IDX_ERR   0x00010000
-#define TMIO_STAT_CRCFAIL       0x00020000
-#define TMIO_STAT_STOPBIT_ERR   0x00040000
-#define TMIO_STAT_DATATIMEOUT   0x00080000
-#define TMIO_STAT_RXOVERFLOW    0x00100000
-#define TMIO_STAT_TXUNDERRUN    0x00200000
-#define TMIO_STAT_CMDTIMEOUT    0x00400000
-#define TMIO_STAT_RXRDY         0x01000000
-#define TMIO_STAT_TXRQ          0x02000000
-#define TMIO_STAT_ILL_FUNC      0x20000000
-#define TMIO_STAT_CMD_BUSY      0x40000000
-#define TMIO_STAT_ILL_ACCESS    0x80000000
-
-/* Definitions for values the CTRL_SDIO_STATUS register can take. */
-#define TMIO_SDIO_STAT_IOIRQ	0x0001
-#define TMIO_SDIO_STAT_EXPUB52	0x4000
-#define TMIO_SDIO_STAT_EXWT	0x8000
-#define TMIO_SDIO_MASK_ALL	0xc007
-
-/* Define some IRQ masks */
-/* This is the mask used at reset by the chip */
-#define TMIO_MASK_ALL           0x837f031d
-#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
-#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
-#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
-		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(host, i) \
-	do { \
-		u32 mask;\
-		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
-		mask &= ~((i) & TMIO_MASK_IRQ); \
-		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
-	} while (0)
-
-#define disable_mmc_irqs(host, i) \
-	do { \
-		u32 mask;\
-		mask  = sd_ctrl_read32((host), CTL_IRQ_MASK); \
-		mask |= ((i) & TMIO_MASK_IRQ); \
-		sd_ctrl_write32((host), CTL_IRQ_MASK, mask); \
-	} while (0)
-
-#define ack_mmc_irqs(host, i) \
-	do { \
-		sd_ctrl_write32((host), CTL_STATUS, ~(i)); \
-	} while (0)
-
-/* This is arbitrary, just noone needed any higher alignment yet */
-#define MAX_ALIGN 4
-
-struct tmio_mmc_host {
-	void __iomem *ctl;
-	unsigned long bus_shift;
-	struct mmc_command      *cmd;
-	struct mmc_request      *mrq;
-	struct mmc_data         *data;
-	struct mmc_host         *mmc;
-	int                     irq;
-	unsigned int		sdio_irq_enabled;
-
-	/* Callbacks for clock / power control */
-	void (*set_pwr)(struct platform_device *host, int state);
-	void (*set_clk_div)(struct platform_device *host, int state);
 
-	/* pio related stuff */
-	struct scatterlist      *sg_ptr;
-	struct scatterlist      *sg_orig;
-	unsigned int            sg_len;
-	unsigned int            sg_off;
-
-	struct platform_device *pdev;
-
-	/* DMA support */
-	struct dma_chan		*chan_rx;
-	struct dma_chan		*chan_tx;
-	struct tasklet_struct	dma_complete;
-	struct tasklet_struct	dma_issue;
-#ifdef CONFIG_TMIO_MMC_DMA
-	unsigned int            dma_sglen;
-	u8			bounce_buf[PAGE_CACHE_SIZE] __attribute__((aligned(MAX_ALIGN)));
-	struct scatterlist	bounce_sg;
-#endif
-
-	/* Track lost interrupts */
-	struct delayed_work	delayed_reset_work;
-	spinlock_t		lock;
-	unsigned long		last_req_ts;
-};
-
-static void tmio_check_bounce_buffer(struct tmio_mmc_host *host);
-
-static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
-{
-	return readw(host->ctl + (addr << host->bus_shift));
-}
-
-static 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 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 void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
-{
-	writew(val, host->ctl + (addr << host->bus_shift));
-}
-
-static 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 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 void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data)
-{
-	host->sg_len = data->sg_len;
-	host->sg_ptr = data->sg;
-	host->sg_orig = data->sg;
-	host->sg_off = 0;
-}
-
-static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
-{
-	host->sg_ptr = sg_next(host->sg_ptr);
-	host->sg_off = 0;
-	return --host->sg_len;
-}
-
-static char *tmio_mmc_kmap_atomic(struct scatterlist *sg, unsigned long *flags)
-{
-	local_irq_save(*flags);
-	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
-}
-
-static void tmio_mmc_kunmap_atomic(void *virt, unsigned long *flags)
-{
-	kunmap_atomic(virt, KM_BIO_SRC_IRQ);
-	local_irq_restore(*flags);
-}
-
-#ifdef CONFIG_MMC_DEBUG
-
-#define STATUS_TO_TEXT(a) \
-	do { \
-		if (status & TMIO_STAT_##a) \
-			printk(#a); \
-	} while (0)
-
-void pr_debug_status(u32 status)
-{
-	printk(KERN_DEBUG "status: %08x = ", status);
-	STATUS_TO_TEXT(CARD_REMOVE);
-	STATUS_TO_TEXT(CARD_INSERT);
-	STATUS_TO_TEXT(SIGSTATE);
-	STATUS_TO_TEXT(WRPROTECT);
-	STATUS_TO_TEXT(CARD_REMOVE_A);
-	STATUS_TO_TEXT(CARD_INSERT_A);
-	STATUS_TO_TEXT(SIGSTATE_A);
-	STATUS_TO_TEXT(CMD_IDX_ERR);
-	STATUS_TO_TEXT(STOPBIT_ERR);
-	STATUS_TO_TEXT(ILL_FUNC);
-	STATUS_TO_TEXT(CMD_BUSY);
-	STATUS_TO_TEXT(CMDRESPEND);
-	STATUS_TO_TEXT(DATAEND);
-	STATUS_TO_TEXT(CRCFAIL);
-	STATUS_TO_TEXT(DATATIMEOUT);
-	STATUS_TO_TEXT(CMDTIMEOUT);
-	STATUS_TO_TEXT(RXOVERFLOW);
-	STATUS_TO_TEXT(TXUNDERRUN);
-	STATUS_TO_TEXT(RXRDY);
-	STATUS_TO_TEXT(TXRQ);
-	STATUS_TO_TEXT(ILL_ACCESS);
-	printk("\n");
-}
-
-#else
-#define pr_debug_status(s)  do { } while (0)
-#endif
-
-static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
-{
-	struct tmio_mmc_host *host = mmc_priv(mmc);
-
-	if (enable) {
-		host->sdio_irq_enabled = 1;
-		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
-		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
-			(TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
-	} else {
-		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
-		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
-		host->sdio_irq_enabled = 0;
-	}
-}
-
-static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
-{
-	u32 clk = 0, clock;
-
-	if (new_clock) {
-		for (clock = host->mmc->f_min, clk = 0x80000080;
-			new_clock >= (clock<<1); clk >>= 1)
-			clock <<= 1;
-		clk |= 0x100;
-	}
-
-	if (host->set_clk_div)
-		host->set_clk_div(host->pdev, (clk>>22) & 1);
-
-	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
-}
-
-static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
-{
-	struct mfd_cell *cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-
-	/*
-	 * Testing on sh-mobile showed that SDIO IRQs are unmasked when
-	 * CTL_CLK_AND_WAIT_CTL gets written, so we have to disable the
-	 * device IRQ here and restore the SDIO IRQ mask before
-	 * re-enabling the device IRQ.
-	 */
-	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
-		disable_irq(host->irq);
-	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
-	msleep(10);
-	if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
-		tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
-		enable_irq(host->irq);
-	}
-	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)
-{
-	struct mfd_cell *cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-
-	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
-		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
-	msleep(10);
-	/* see comment in tmio_mmc_clk_stop above */
-	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
-		disable_irq(host->irq);
-	sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
-	msleep(10);
-	if (pdata->flags & TMIO_MMC_SDIO_IRQ) {
-		tmio_mmc_enable_sdio_irq(host->mmc, host->sdio_irq_enabled);
-		enable_irq(host->irq);
-	}
-}
-
-static void reset(struct tmio_mmc_host *host)
-{
-	/* FIXME - should we set stop clock reg here */
-	sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
-	sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
-	msleep(10);
-	sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
-	sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
-	msleep(10);
-}
-
-static void tmio_mmc_reset_work(struct work_struct *work)
-{
-	struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
-						  delayed_reset_work.work);
-	struct mmc_request *mrq;
-	unsigned long flags;
-
-	spin_lock_irqsave(&host->lock, flags);
-	mrq = host->mrq;
-
-	/* request already finished */
-	if (!mrq
-	    || time_is_after_jiffies(host->last_req_ts +
-		msecs_to_jiffies(2000))) {
-		spin_unlock_irqrestore(&host->lock, flags);
-		return;
-	}
-
-	dev_warn(&host->pdev->dev,
-		"timeout waiting for hardware interrupt (CMD%u)\n",
-		mrq->cmd->opcode);
-
-	if (host->data)
-		host->data->error = -ETIMEDOUT;
-	else if (host->cmd)
-		host->cmd->error = -ETIMEDOUT;
-	else
-		mrq->cmd->error = -ETIMEDOUT;
-
-	host->cmd = NULL;
-	host->data = NULL;
-	host->mrq = NULL;
-
-	spin_unlock_irqrestore(&host->lock, flags);
-
-	reset(host);
-
-	mmc_request_done(host->mmc, mrq);
-}
-
-static void
-tmio_mmc_finish_request(struct tmio_mmc_host *host)
-{
-	struct mmc_request *mrq = host->mrq;
-
-	if (!mrq)
-		return;
-
-	host->mrq = NULL;
-	host->cmd = NULL;
-	host->data = NULL;
-
-	cancel_delayed_work(&host->delayed_reset_work);
-
-	mmc_request_done(host->mmc, mrq);
-}
-
-/* These are the bitmasks the tmio chip requires to implement the MMC response
- * types. Note that R1 and R6 are the same in this scheme. */
-#define APP_CMD        0x0040
-#define RESP_NONE      0x0300
-#define RESP_R1        0x0400
-#define RESP_R1B       0x0500
-#define RESP_R2        0x0600
-#define RESP_R3        0x0700
-#define DATA_PRESENT   0x0800
-#define TRANSFER_READ  0x1000
-#define TRANSFER_MULTI 0x2000
-#define SECURITY_CMD   0x4000
-
-static int
-tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
-{
-	struct mmc_data *data = host->data;
-	int c = cmd->opcode;
-
-	/* Command 12 is handled by hardware */
-	if (cmd->opcode == 12 && !cmd->arg) {
-		sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
-		return 0;
-	}
-
-	switch (mmc_resp_type(cmd)) {
-	case MMC_RSP_NONE: c |= RESP_NONE; break;
-	case MMC_RSP_R1:   c |= RESP_R1;   break;
-	case MMC_RSP_R1B:  c |= RESP_R1B;  break;
-	case MMC_RSP_R2:   c |= RESP_R2;   break;
-	case MMC_RSP_R3:   c |= RESP_R3;   break;
-	default:
-		pr_debug("Unknown response type %d\n", mmc_resp_type(cmd));
-		return -EINVAL;
-	}
-
-	host->cmd = cmd;
-
-/* FIXME - this seems to be ok commented out but the spec suggest this bit
- *         should be set when issuing app commands.
- *	if(cmd->flags & MMC_FLAG_ACMD)
- *		c |= APP_CMD;
- */
-	if (data) {
-		c |= DATA_PRESENT;
-		if (data->blocks > 1) {
-			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
-			c |= TRANSFER_MULTI;
-		}
-		if (data->flags & MMC_DATA_READ)
-			c |= TRANSFER_READ;
-	}
-
-	enable_mmc_irqs(host, TMIO_MASK_CMD);
-
-	/* Fire off the command */
-	sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
-	sd_ctrl_write16(host, CTL_SD_CMD, c);
-
-	return 0;
-}
-
-/*
- * This chip always returns (at least?) as much data as you ask for.
- * I'm unsure what happens if you ask for less than a block. This should be
- * looked into to ensure that a funny length read doesnt hose the controller.
- */
-static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
-{
-	struct mmc_data *data = host->data;
-	void *sg_virt;
-	unsigned short *buf;
-	unsigned int count;
-	unsigned long flags;
-
-	if (!data) {
-		pr_debug("Spurious PIO IRQ\n");
-		return;
-	}
-
-	sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags);
-	buf = (unsigned short *)(sg_virt + host->sg_off);
-
-	count = host->sg_ptr->length - host->sg_off;
-	if (count > data->blksz)
-		count = data->blksz;
-
-	pr_debug("count: %08x offset: %08x flags %08x\n",
-		 count, host->sg_off, data->flags);
-
-	/* Transfer the data */
-	if (data->flags & MMC_DATA_READ)
-		sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
-	else
-		sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
-
-	host->sg_off += count;
-
-	tmio_mmc_kunmap_atomic(sg_virt, &flags);
-
-	if (host->sg_off == host->sg_ptr->length)
-		tmio_mmc_next_sg(host);
-
-	return;
-}
-
-/* needs to be called with host->lock held */
-static void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
-{
-	struct mmc_data *data = host->data;
-	struct mmc_command *stop;
-
-	host->data = NULL;
-
-	if (!data) {
-		dev_warn(&host->pdev->dev, "Spurious data end IRQ\n");
-		return;
-	}
-	stop = data->stop;
-
-	/* FIXME - return correct transfer count on errors */
-	if (!data->error)
-		data->bytes_xfered = data->blocks * data->blksz;
-	else
-		data->bytes_xfered = 0;
-
-	pr_debug("Completed data request\n");
-
-	/*
-	 * FIXME: other drivers allow an optional stop command of any given type
-	 *        which we dont do, as the chip can auto generate them.
-	 *        Perhaps we can be smarter about when to use auto CMD12 and
-	 *        only issue the auto request when we know this is the desired
-	 *        stop command, allowing fallback to the stop command the
-	 *        upper layers expect. For now, we do what works.
-	 */
-
-	if (data->flags & MMC_DATA_READ) {
-		if (!host->chan_rx)
-			disable_mmc_irqs(host, TMIO_MASK_READOP);
-		else
-			tmio_check_bounce_buffer(host);
-		dev_dbg(&host->pdev->dev, "Complete Rx request %p\n",
-			host->mrq);
-	} else {
-		if (!host->chan_tx)
-			disable_mmc_irqs(host, TMIO_MASK_WRITEOP);
-		dev_dbg(&host->pdev->dev, "Complete Tx request %p\n",
-			host->mrq);
-	}
-
-	if (stop) {
-		if (stop->opcode == 12 && !stop->arg)
-			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
-		else
-			BUG();
-	}
-
-	tmio_mmc_finish_request(host);
-}
-
-static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
-{
-	struct mmc_data *data;
-	spin_lock(&host->lock);
-	data = host->data;
-
-	if (!data)
-		goto out;
-
-	if (host->chan_tx && (data->flags & MMC_DATA_WRITE)) {
-		/*
-		 * Has all data been written out yet? Testing on SuperH showed,
-		 * that in most cases the first interrupt comes already with the
-		 * BUSY status bit clear, but on some operations, like mount or
-		 * in the beginning of a write / sync / umount, there is one
-		 * DATAEND interrupt with the BUSY bit set, in this cases
-		 * waiting for one more interrupt fixes the problem.
-		 */
-		if (!(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_CMD_BUSY)) {
-			disable_mmc_irqs(host, TMIO_STAT_DATAEND);
-			tasklet_schedule(&host->dma_complete);
-		}
-	} else if (host->chan_rx && (data->flags & MMC_DATA_READ)) {
-		disable_mmc_irqs(host, TMIO_STAT_DATAEND);
-		tasklet_schedule(&host->dma_complete);
-	} else {
-		tmio_mmc_do_data_irq(host);
-	}
-out:
-	spin_unlock(&host->lock);
-}
-
-static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
-	unsigned int stat)
-{
-	struct mmc_command *cmd = host->cmd;
-	int i, addr;
-
-	spin_lock(&host->lock);
-
-	if (!host->cmd) {
-		pr_debug("Spurious CMD irq\n");
-		goto out;
-	}
-
-	host->cmd = NULL;
-
-	/* This controller is sicker than the PXA one. Not only do we need to
-	 * drop the top 8 bits of the first response word, we also need to
-	 * modify the order of the response for short response command types.
-	 */
-
-	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);
-		cmd->resp[1] = (cmd->resp[1] << 8) | (cmd->resp[2] >> 24);
-		cmd->resp[2] = (cmd->resp[2] << 8) | (cmd->resp[3] >> 24);
-		cmd->resp[3] <<= 8;
-	} else if (cmd->flags & MMC_RSP_R3) {
-		cmd->resp[0] = cmd->resp[3];
-	}
-
-	if (stat & TMIO_STAT_CMDTIMEOUT)
-		cmd->error = -ETIMEDOUT;
-	else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
-		cmd->error = -EILSEQ;
-
-	/* If there is data to handle we enable data IRQs here, and
-	 * we will ultimatley finish the request in the data_end handler.
-	 * If theres no data or we encountered an error, finish now.
-	 */
-	if (host->data && !cmd->error) {
-		if (host->data->flags & MMC_DATA_READ) {
-			if (!host->chan_rx)
-				enable_mmc_irqs(host, TMIO_MASK_READOP);
-		} else {
-			if (!host->chan_tx)
-				enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
-			else
-				tasklet_schedule(&host->dma_issue);
-		}
-	} else {
-		tmio_mmc_finish_request(host);
-	}
-
-out:
-	spin_unlock(&host->lock);
-
-	return;
-}
-
-static irqreturn_t tmio_mmc_irq(int irq, void *devid)
-{
-	struct tmio_mmc_host *host = devid;
-	struct mfd_cell	*cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-	unsigned int ireg, irq_mask, status;
-	unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
-
-	pr_debug("MMC IRQ begin\n");
-
-	status = sd_ctrl_read32(host, CTL_STATUS);
-	irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
-	ireg = status & TMIO_MASK_IRQ & ~irq_mask;
-
-	sdio_ireg = 0;
-	if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
-		sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
-		sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
-		sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
-
-		sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
-
-		if (sdio_ireg && !host->sdio_irq_enabled) {
-			pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
-				   sdio_status, sdio_irq_mask, sdio_ireg);
-			tmio_mmc_enable_sdio_irq(host->mmc, 0);
-			goto out;
-		}
-
-		if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
-			sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
-			mmc_signal_sdio_irq(host->mmc);
-
-		if (sdio_ireg)
-			goto out;
-	}
-
-	pr_debug_status(status);
-	pr_debug_status(ireg);
-
-	if (!ireg) {
-		disable_mmc_irqs(host, status & ~irq_mask);
-
-		pr_warning("tmio_mmc: Spurious irq, disabling! "
-			"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
-		pr_debug_status(status);
-
-		goto out;
-	}
-
-	while (ireg) {
-		/* Card insert / remove attempts */
-		if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
-			ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
-				TMIO_STAT_CARD_REMOVE);
-			mmc_detect_change(host->mmc, msecs_to_jiffies(100));
-		}
-
-		/* CRC and other errors */
-/*		if (ireg & TMIO_STAT_ERR_IRQ)
- *			handled |= tmio_error_irq(host, irq, stat);
- */
-
-		/* Command completion */
-		if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
-			ack_mmc_irqs(host,
-				     TMIO_STAT_CMDRESPEND |
-				     TMIO_STAT_CMDTIMEOUT);
-			tmio_mmc_cmd_irq(host, status);
-		}
-
-		/* Data transfer */
-		if (ireg & (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(host, TMIO_STAT_DATAEND);
-			tmio_mmc_data_irq(host);
-		}
-
-		/* Check status - keep going until we've handled it all */
-		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);
-		pr_debug_status(status);
-	}
-	pr_debug("MMC IRQ end\n");
-
-out:
-	return IRQ_HANDLED;
-}
-
-#ifdef CONFIG_TMIO_MMC_DMA
-static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
-{
-	if (host->sg_ptr == &host->bounce_sg) {
-		unsigned long flags;
-		void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags);
-		memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length);
-		tmio_mmc_kunmap_atomic(sg_vaddr, &flags);
-	}
-}
-
-static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
-{
-#if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
-	/* Switch DMA mode on or off - SuperH specific? */
-	sd_ctrl_write16(host, 0xd8, enable ? 2 : 0);
-#endif
-}
-
-static void tmio_dma_complete(void *arg)
-{
-	struct tmio_mmc_host *host = arg;
-
-	dev_dbg(&host->pdev->dev, "Command completed\n");
-
-	if (!host->data)
-		dev_warn(&host->pdev->dev, "NULL data in DMA completion!\n");
-	else
-		enable_mmc_irqs(host, TMIO_STAT_DATAEND);
-}
-
-static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
-{
-	struct scatterlist *sg = host->sg_ptr, *sg_tmp;
-	struct dma_async_tx_descriptor *desc = NULL;
-	struct dma_chan *chan = host->chan_rx;
-	struct mfd_cell	*cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-	dma_cookie_t cookie;
-	int ret, i;
-	bool aligned = true, multiple = true;
-	unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
-
-	for_each_sg(sg, sg_tmp, host->sg_len, i) {
-		if (sg_tmp->offset & align)
-			aligned = false;
-		if (sg_tmp->length & align) {
-			multiple = false;
-			break;
-		}
-	}
-
-	if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
-			  align >= MAX_ALIGN)) || !multiple) {
-		ret = -EINVAL;
-		goto pio;
-	}
-
-	/* The only sg element can be unaligned, use our bounce buffer then */
-	if (!aligned) {
-		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
-		host->sg_ptr = &host->bounce_sg;
-		sg = host->sg_ptr;
-	}
-
-	ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_FROM_DEVICE);
-	if (ret > 0) {
-		host->dma_sglen = ret;
-		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-			DMA_FROM_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	}
-
-	if (desc) {
-		desc->callback = tmio_dma_complete;
-		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		} else {
-			chan->device->device_issue_pending(chan);
-		}
-	}
-	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
-		__func__, host->sg_len, ret, cookie, host->mrq);
-
-pio:
-	if (!desc) {
-		/* DMA failed, fall back to PIO */
-		if (ret >= 0)
-			ret = -EIO;
-		host->chan_rx = NULL;
-		dma_release_channel(chan);
-		/* Free the Tx channel too */
-		chan = host->chan_tx;
-		if (chan) {
-			host->chan_tx = NULL;
-			dma_release_channel(chan);
-		}
-		dev_warn(&host->pdev->dev,
-			 "DMA failed: %d, falling back to PIO\n", ret);
-		tmio_mmc_enable_dma(host, false);
-	}
-
-	dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
-		desc, cookie, host->sg_len);
-}
-
-static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
-{
-	struct scatterlist *sg = host->sg_ptr, *sg_tmp;
-	struct dma_async_tx_descriptor *desc = NULL;
-	struct dma_chan *chan = host->chan_tx;
-	struct mfd_cell	*cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-	dma_cookie_t cookie;
-	int ret, i;
-	bool aligned = true, multiple = true;
-	unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
-
-	for_each_sg(sg, sg_tmp, host->sg_len, i) {
-		if (sg_tmp->offset & align)
-			aligned = false;
-		if (sg_tmp->length & align) {
-			multiple = false;
-			break;
-		}
-	}
-
-	if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
-			  align >= MAX_ALIGN)) || !multiple) {
-		ret = -EINVAL;
-		goto pio;
-	}
-
-	/* The only sg element can be unaligned, use our bounce buffer then */
-	if (!aligned) {
-		unsigned long flags;
-		void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags);
-		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
-		memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length);
-		tmio_mmc_kunmap_atomic(sg_vaddr, &flags);
-		host->sg_ptr = &host->bounce_sg;
-		sg = host->sg_ptr;
-	}
-
-	ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, DMA_TO_DEVICE);
-	if (ret > 0) {
-		host->dma_sglen = ret;
-		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
-			DMA_TO_DEVICE, DMA_PREP_INTERRUPT | DMA_CTRL_ACK);
-	}
-
-	if (desc) {
-		desc->callback = tmio_dma_complete;
-		desc->callback_param = host;
-		cookie = desc->tx_submit(desc);
-		if (cookie < 0) {
-			desc = NULL;
-			ret = cookie;
-		}
-	}
-	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
-		__func__, host->sg_len, ret, cookie, host->mrq);
-
-pio:
-	if (!desc) {
-		/* DMA failed, fall back to PIO */
-		if (ret >= 0)
-			ret = -EIO;
-		host->chan_tx = NULL;
-		dma_release_channel(chan);
-		/* Free the Rx channel too */
-		chan = host->chan_rx;
-		if (chan) {
-			host->chan_rx = NULL;
-			dma_release_channel(chan);
-		}
-		dev_warn(&host->pdev->dev,
-			 "DMA failed: %d, falling back to PIO\n", ret);
-		tmio_mmc_enable_dma(host, false);
-	}
-
-	dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
-		desc, cookie);
-}
-
-static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
-			       struct mmc_data *data)
-{
-	if (data->flags & MMC_DATA_READ) {
-		if (host->chan_rx)
-			tmio_mmc_start_dma_rx(host);
-	} else {
-		if (host->chan_tx)
-			tmio_mmc_start_dma_tx(host);
-	}
-}
-
-static void tmio_issue_tasklet_fn(unsigned long priv)
-{
-	struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
-	struct dma_chan *chan = host->chan_tx;
-
-	chan->device->device_issue_pending(chan);
-}
-
-static void tmio_tasklet_fn(unsigned long arg)
-{
-	struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
-	unsigned long flags;
-
-	spin_lock_irqsave(&host->lock, flags);
-
-	if (!host->data)
-		goto out;
-
-	if (host->data->flags & MMC_DATA_READ)
-		dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
-			     DMA_FROM_DEVICE);
-	else
-		dma_unmap_sg(&host->pdev->dev, host->sg_ptr, host->dma_sglen,
-			     DMA_TO_DEVICE);
-
-	tmio_mmc_do_data_irq(host);
-out:
-	spin_unlock_irqrestore(&host->lock, flags);
-}
-
-/* It might be necessary to make filter MFD specific */
-static bool tmio_mmc_filter(struct dma_chan *chan, void *arg)
-{
-	dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
-	chan->private = arg;
-	return true;
-}
-
-static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
-				 struct tmio_mmc_data *pdata)
-{
-	/* We can only either use DMA for both Tx and Rx or not use it at all */
-	if (pdata->dma) {
-		dma_cap_mask_t mask;
-
-		dma_cap_zero(mask);
-		dma_cap_set(DMA_SLAVE, mask);
-
-		host->chan_tx = dma_request_channel(mask, tmio_mmc_filter,
-						    pdata->dma->chan_priv_tx);
-		dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__,
-			host->chan_tx);
-
-		if (!host->chan_tx)
-			return;
-
-		host->chan_rx = dma_request_channel(mask, tmio_mmc_filter,
-						    pdata->dma->chan_priv_rx);
-		dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__,
-			host->chan_rx);
-
-		if (!host->chan_rx) {
-			dma_release_channel(host->chan_tx);
-			host->chan_tx = NULL;
-			return;
-		}
-
-		tasklet_init(&host->dma_complete, tmio_tasklet_fn, (unsigned long)host);
-		tasklet_init(&host->dma_issue, tmio_issue_tasklet_fn, (unsigned long)host);
-
-		tmio_mmc_enable_dma(host, true);
-	}
-}
-
-static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
-{
-	if (host->chan_tx) {
-		struct dma_chan *chan = host->chan_tx;
-		host->chan_tx = NULL;
-		dma_release_channel(chan);
-	}
-	if (host->chan_rx) {
-		struct dma_chan *chan = host->chan_rx;
-		host->chan_rx = NULL;
-		dma_release_channel(chan);
-	}
-}
-#else
-static void tmio_check_bounce_buffer(struct tmio_mmc_host *host)
-{
-}
-
-static void tmio_mmc_start_dma(struct tmio_mmc_host *host,
-			       struct mmc_data *data)
-{
-}
-
-static void tmio_mmc_request_dma(struct tmio_mmc_host *host,
-				 struct tmio_mmc_data *pdata)
-{
-	host->chan_tx = NULL;
-	host->chan_rx = NULL;
-}
-
-static void tmio_mmc_release_dma(struct tmio_mmc_host *host)
-{
-}
-#endif
-
-static int tmio_mmc_start_data(struct tmio_mmc_host *host,
-	struct mmc_data *data)
-{
-	struct mfd_cell *cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-
-	pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",
-		 data->blksz, data->blocks);
-
-	/* Some hardware cannot perform 2 byte requests in 4 bit mode */
-	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
-		int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;
-
-		if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) {
-			pr_err("%s: %d byte block unsupported in 4 bit mode\n",
-			       mmc_hostname(host->mmc), data->blksz);
-			return -EINVAL;
-		}
-	}
-
-	tmio_mmc_init_sg(host, data);
-	host->data = data;
-
-	/* Set transfer length / blocksize */
-	sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
-	sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
-
-	tmio_mmc_start_dma(host, data);
-
-	return 0;
-}
-
-/* Process requests from the MMC layer */
-static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
-{
-	struct tmio_mmc_host *host = mmc_priv(mmc);
-	int ret;
-
-	if (host->mrq)
-		pr_debug("request not null\n");
-
-	host->last_req_ts = jiffies;
-	wmb();
-	host->mrq = mrq;
-
-	if (mrq->data) {
-		ret = tmio_mmc_start_data(host, mrq->data);
-		if (ret)
-			goto fail;
-	}
-
-	ret = tmio_mmc_start_command(host, mrq->cmd);
-	if (!ret) {
-		schedule_delayed_work(&host->delayed_reset_work,
-				      msecs_to_jiffies(2000));
-		return;
-	}
-
-fail:
-	host->mrq = NULL;
-	mrq->cmd->error = ret;
-	mmc_request_done(mmc, mrq);
-}
-
-/* Set MMC clock / power.
- * Note: This controller uses a simple divider scheme therefore it cannot
- * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
- * MMC wont run that fast, it has to be clocked at 12MHz which is the next
- * slowest setting.
- */
-static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
-{
-	struct tmio_mmc_host *host = mmc_priv(mmc);
-
-	if (ios->clock)
-		tmio_mmc_set_clock(host, ios->clock);
-
-	/* Power sequence - OFF -> ON -> UP */
-	switch (ios->power_mode) {
-	case MMC_POWER_OFF: /* power down SD bus */
-		if (host->set_pwr)
-			host->set_pwr(host->pdev, 0);
-		tmio_mmc_clk_stop(host);
-		break;
-	case MMC_POWER_ON: /* power up SD bus */
-		if (host->set_pwr)
-			host->set_pwr(host->pdev, 1);
-		break;
-	case MMC_POWER_UP: /* start bus clock */
-		tmio_mmc_clk_start(host);
-		break;
-	}
-
-	switch (ios->bus_width) {
-	case MMC_BUS_WIDTH_1:
-		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
-	break;
-	case MMC_BUS_WIDTH_4:
-		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
-	break;
-	}
-
-	/* Let things settle. delay taken from winCE driver */
-	udelay(140);
-}
-
-static int tmio_mmc_get_ro(struct mmc_host *mmc)
-{
-	struct tmio_mmc_host *host = mmc_priv(mmc);
-	struct mfd_cell	*cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-
-	return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
-		(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT)) ? 0 : 1;
-}
-
-static int tmio_mmc_get_cd(struct mmc_host *mmc)
-{
-	struct tmio_mmc_host *host = mmc_priv(mmc);
-	struct mfd_cell	*cell = host->pdev->dev.platform_data;
-	struct tmio_mmc_data *pdata = cell->driver_data;
-
-	if (!pdata->get_cd)
-		return -ENOSYS;
-	else
-		return pdata->get_cd(host->pdev);
-}
-
-static const struct mmc_host_ops tmio_mmc_ops = {
-	.request	= tmio_mmc_request,
-	.set_ios	= tmio_mmc_set_ios,
-	.get_ro         = tmio_mmc_get_ro,
-	.get_cd		= tmio_mmc_get_cd,
-	.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
-};
+#include "tmio_mmc.h"
 
 #ifdef CONFIG_PM
 static int tmio_mmc_suspend(struct platform_device *dev, pm_message_t state)
 {
-	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
+	const struct mfd_cell *cell = mfd_get_cell(dev);
 	struct mmc_host *mmc = platform_get_drvdata(dev);
 	int ret;
 
@@ -1222,7 +41,7 @@
 
 static int tmio_mmc_resume(struct platform_device *dev)
 {
-	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
+	const struct mfd_cell *cell = mfd_get_cell(dev);
 	struct mmc_host *mmc = platform_get_drvdata(dev);
 	int ret = 0;
 
@@ -1243,138 +62,54 @@
 #define tmio_mmc_resume NULL
 #endif
 
-static int __devinit tmio_mmc_probe(struct platform_device *dev)
+static int __devinit tmio_mmc_probe(struct platform_device *pdev)
 {
-	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
 	struct tmio_mmc_data *pdata;
-	struct resource *res_ctl;
 	struct tmio_mmc_host *host;
-	struct mmc_host *mmc;
 	int ret = -EINVAL;
-	u32 irq_mask = TMIO_MASK_CMD;
 
-	if (dev->num_resources != 2)
-		goto out;
-
-	res_ctl = platform_get_resource(dev, IORESOURCE_MEM, 0);
-	if (!res_ctl)
+	if (pdev->num_resources != 2)
 		goto out;
 
-	pdata = cell->driver_data;
+	pdata = mfd_get_data(pdev);
 	if (!pdata || !pdata->hclk)
 		goto out;
 
-	ret = -ENOMEM;
-
-	mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &dev->dev);
-	if (!mmc)
-		goto out;
-
-	host = mmc_priv(mmc);
-	host->mmc = mmc;
-	host->pdev = dev;
-	platform_set_drvdata(dev, mmc);
-
-	host->set_pwr = pdata->set_pwr;
-	host->set_clk_div = pdata->set_clk_div;
-
-	/* 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;
-
-	mmc->ops = &tmio_mmc_ops;
-	mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
-	mmc->f_max = pdata->hclk;
-	mmc->f_min = mmc->f_max / 512;
-	mmc->max_segs = 32;
-	mmc->max_blk_size = 512;
-	mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
-		mmc->max_segs;
-	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
-	mmc->max_seg_size = mmc->max_req_size;
-	if (pdata->ocr_mask)
-		mmc->ocr_avail = pdata->ocr_mask;
-	else
-		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
-
 	/* Tell the MFD core we are ready to be enabled */
 	if (cell->enable) {
-		ret = cell->enable(dev);
+		ret = cell->enable(pdev);
 		if (ret)
-			goto unmap_ctl;
+			goto out;
 	}
 
-	tmio_mmc_clk_stop(host);
-	reset(host);
-
-	ret = platform_get_irq(dev, 0);
-	if (ret >= 0)
-		host->irq = ret;
-	else
-		goto cell_disable;
-
-	disable_mmc_irqs(host, TMIO_MASK_ALL);
-	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
-		tmio_mmc_enable_sdio_irq(mmc, 0);
-
-	ret = request_irq(host->irq, tmio_mmc_irq, IRQF_DISABLED |
-		IRQF_TRIGGER_FALLING, dev_name(&dev->dev), host);
+	ret = tmio_mmc_host_probe(&host, pdev, pdata);
 	if (ret)
 		goto cell_disable;
 
-	spin_lock_init(&host->lock);
-
-	/* Init delayed work for request timeouts */
-	INIT_DELAYED_WORK(&host->delayed_reset_work, tmio_mmc_reset_work);
-
-	/* See if we also get DMA */
-	tmio_mmc_request_dma(host, pdata);
-
-	mmc_add_host(mmc);
-
 	pr_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 */
-	if (!host->chan_rx)
-		irq_mask |= TMIO_MASK_READOP;
-	if (!host->chan_tx)
-		irq_mask |= TMIO_MASK_WRITEOP;
-	enable_mmc_irqs(host, irq_mask);
-
 	return 0;
 
 cell_disable:
 	if (cell->disable)
-		cell->disable(dev);
-unmap_ctl:
-	iounmap(host->ctl);
-host_free:
-	mmc_free_host(mmc);
+		cell->disable(pdev);
 out:
 	return ret;
 }
 
-static int __devexit tmio_mmc_remove(struct platform_device *dev)
+static int __devexit tmio_mmc_remove(struct platform_device *pdev)
 {
-	struct mfd_cell	*cell = (struct mfd_cell *)dev->dev.platform_data;
-	struct mmc_host *mmc = platform_get_drvdata(dev);
+	const struct mfd_cell *cell = mfd_get_cell(pdev);
+	struct mmc_host *mmc = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(dev, NULL);
+	platform_set_drvdata(pdev, NULL);
 
 	if (mmc) {
-		struct tmio_mmc_host *host = mmc_priv(mmc);
-		mmc_remove_host(mmc);
-		cancel_delayed_work_sync(&host->delayed_reset_work);
-		tmio_mmc_release_dma(host);
-		free_irq(host->irq, host);
+		tmio_mmc_host_remove(mmc_priv(mmc));
 		if (cell->disable)
-			cell->disable(dev);
-		iounmap(host->ctl);
-		mmc_free_host(mmc);
+			cell->disable(pdev);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc_dma.c linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc_dma.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc_dma.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc_dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,317 @@
+/*
+ * linux/drivers/mmc/tmio_mmc_dma.c
+ *
+ * Copyright (C) 2010-2011 Guennadi Liakhovetski
+ *
+ * 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 function for TMIO MMC implementations
+ */
+
+#include <linux/device.h>
+#include <linux/dmaengine.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/tmio.h>
+#include <linux/pagemap.h>
+#include <linux/scatterlist.h>
+
+#include "tmio_mmc.h"
+
+#define TMIO_MMC_MIN_DMA_LEN 8
+
+static void tmio_mmc_enable_dma(struct tmio_mmc_host *host, bool enable)
+{
+#if defined(CONFIG_SUPERH) || defined(CONFIG_ARCH_SHMOBILE)
+	/* Switch DMA mode on or off - SuperH specific? */
+	writew(enable ? 2 : 0, host->ctl + (0xd8 << host->bus_shift));
+#endif
+}
+
+static void tmio_mmc_start_dma_rx(struct tmio_mmc_host *host)
+{
+	struct scatterlist *sg = host->sg_ptr, *sg_tmp;
+	struct dma_async_tx_descriptor *desc = NULL;
+	struct dma_chan *chan = host->chan_rx;
+	struct tmio_mmc_data *pdata = host->pdata;
+	dma_cookie_t cookie;
+	int ret, i;
+	bool aligned = true, multiple = true;
+	unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
+
+	for_each_sg(sg, sg_tmp, host->sg_len, i) {
+		if (sg_tmp->offset & align)
+			aligned = false;
+		if (sg_tmp->length & align) {
+			multiple = false;
+			break;
+		}
+	}
+
+	if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
+			  (align & PAGE_MASK))) || !multiple) {
+		ret = -EINVAL;
+		goto pio;
+	}
+
+	if (sg->length < TMIO_MMC_MIN_DMA_LEN) {
+		host->force_pio = true;
+		return;
+	}
+
+	tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_RXRDY);
+
+	/* The only sg element can be unaligned, use our bounce buffer then */
+	if (!aligned) {
+		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
+		host->sg_ptr = &host->bounce_sg;
+		sg = host->sg_ptr;
+	}
+
+	ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_FROM_DEVICE);
+	if (ret > 0)
+		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+			DMA_FROM_DEVICE, DMA_CTRL_ACK);
+
+	if (desc) {
+		cookie = dmaengine_submit(desc);
+		if (cookie < 0) {
+			desc = NULL;
+			ret = cookie;
+		}
+	}
+	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
+		__func__, host->sg_len, ret, cookie, host->mrq);
+
+pio:
+	if (!desc) {
+		/* DMA failed, fall back to PIO */
+		if (ret >= 0)
+			ret = -EIO;
+		host->chan_rx = NULL;
+		dma_release_channel(chan);
+		/* Free the Tx channel too */
+		chan = host->chan_tx;
+		if (chan) {
+			host->chan_tx = NULL;
+			dma_release_channel(chan);
+		}
+		dev_warn(&host->pdev->dev,
+			 "DMA failed: %d, falling back to PIO\n", ret);
+		tmio_mmc_enable_dma(host, false);
+	}
+
+	dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d, sg[%d]\n", __func__,
+		desc, cookie, host->sg_len);
+}
+
+static void tmio_mmc_start_dma_tx(struct tmio_mmc_host *host)
+{
+	struct scatterlist *sg = host->sg_ptr, *sg_tmp;
+	struct dma_async_tx_descriptor *desc = NULL;
+	struct dma_chan *chan = host->chan_tx;
+	struct tmio_mmc_data *pdata = host->pdata;
+	dma_cookie_t cookie;
+	int ret, i;
+	bool aligned = true, multiple = true;
+	unsigned int align = (1 << pdata->dma->alignment_shift) - 1;
+
+	for_each_sg(sg, sg_tmp, host->sg_len, i) {
+		if (sg_tmp->offset & align)
+			aligned = false;
+		if (sg_tmp->length & align) {
+			multiple = false;
+			break;
+		}
+	}
+
+	if ((!aligned && (host->sg_len > 1 || sg->length > PAGE_CACHE_SIZE ||
+			  (align & PAGE_MASK))) || !multiple) {
+		ret = -EINVAL;
+		goto pio;
+	}
+
+	if (sg->length < TMIO_MMC_MIN_DMA_LEN) {
+		host->force_pio = true;
+		return;
+	}
+
+	tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_TXRQ);
+
+	/* The only sg element can be unaligned, use our bounce buffer then */
+	if (!aligned) {
+		unsigned long flags;
+		void *sg_vaddr = tmio_mmc_kmap_atomic(sg, &flags);
+		sg_init_one(&host->bounce_sg, host->bounce_buf, sg->length);
+		memcpy(host->bounce_buf, sg_vaddr, host->bounce_sg.length);
+		tmio_mmc_kunmap_atomic(sg, &flags, sg_vaddr);
+		host->sg_ptr = &host->bounce_sg;
+		sg = host->sg_ptr;
+	}
+
+	ret = dma_map_sg(chan->device->dev, sg, host->sg_len, DMA_TO_DEVICE);
+	if (ret > 0)
+		desc = chan->device->device_prep_slave_sg(chan, sg, ret,
+			DMA_TO_DEVICE, DMA_CTRL_ACK);
+
+	if (desc) {
+		cookie = dmaengine_submit(desc);
+		if (cookie < 0) {
+			desc = NULL;
+			ret = cookie;
+		}
+	}
+	dev_dbg(&host->pdev->dev, "%s(): mapped %d -> %d, cookie %d, rq %p\n",
+		__func__, host->sg_len, ret, cookie, host->mrq);
+
+pio:
+	if (!desc) {
+		/* DMA failed, fall back to PIO */
+		if (ret >= 0)
+			ret = -EIO;
+		host->chan_tx = NULL;
+		dma_release_channel(chan);
+		/* Free the Rx channel too */
+		chan = host->chan_rx;
+		if (chan) {
+			host->chan_rx = NULL;
+			dma_release_channel(chan);
+		}
+		dev_warn(&host->pdev->dev,
+			 "DMA failed: %d, falling back to PIO\n", ret);
+		tmio_mmc_enable_dma(host, false);
+	}
+
+	dev_dbg(&host->pdev->dev, "%s(): desc %p, cookie %d\n", __func__,
+		desc, cookie);
+}
+
+void tmio_mmc_start_dma(struct tmio_mmc_host *host,
+			       struct mmc_data *data)
+{
+	if (data->flags & MMC_DATA_READ) {
+		if (host->chan_rx)
+			tmio_mmc_start_dma_rx(host);
+	} else {
+		if (host->chan_tx)
+			tmio_mmc_start_dma_tx(host);
+	}
+}
+
+static void tmio_mmc_issue_tasklet_fn(unsigned long priv)
+{
+	struct tmio_mmc_host *host = (struct tmio_mmc_host *)priv;
+	struct dma_chan *chan = NULL;
+
+	spin_lock_irq(&host->lock);
+
+	if (host && host->data) {
+		if (host->data->flags & MMC_DATA_READ)
+			chan = host->chan_rx;
+		else
+			chan = host->chan_tx;
+	}
+
+	spin_unlock_irq(&host->lock);
+
+	tmio_mmc_enable_mmc_irqs(host, TMIO_STAT_DATAEND);
+
+	if (chan)
+		dma_async_issue_pending(chan);
+}
+
+static void tmio_mmc_tasklet_fn(unsigned long arg)
+{
+	struct tmio_mmc_host *host = (struct tmio_mmc_host *)arg;
+
+	spin_lock_irq(&host->lock);
+
+	if (!host->data)
+		goto out;
+
+	if (host->data->flags & MMC_DATA_READ)
+		dma_unmap_sg(host->chan_rx->device->dev,
+			     host->sg_ptr, host->sg_len,
+			     DMA_FROM_DEVICE);
+	else
+		dma_unmap_sg(host->chan_tx->device->dev,
+			     host->sg_ptr, host->sg_len,
+			     DMA_TO_DEVICE);
+
+	tmio_mmc_do_data_irq(host);
+out:
+	spin_unlock_irq(&host->lock);
+}
+
+/* It might be necessary to make filter MFD specific */
+static bool tmio_mmc_filter(struct dma_chan *chan, void *arg)
+{
+	dev_dbg(chan->device->dev, "%s: slave data %p\n", __func__, arg);
+	chan->private = arg;
+	return true;
+}
+
+void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata)
+{
+	/* We can only either use DMA for both Tx and Rx or not use it at all */
+	if (pdata->dma) {
+		dma_cap_mask_t mask;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_SLAVE, mask);
+
+		host->chan_tx = dma_request_channel(mask, tmio_mmc_filter,
+						    pdata->dma->chan_priv_tx);
+		dev_dbg(&host->pdev->dev, "%s: TX: got channel %p\n", __func__,
+			host->chan_tx);
+
+		if (!host->chan_tx)
+			return;
+
+		host->chan_rx = dma_request_channel(mask, tmio_mmc_filter,
+						    pdata->dma->chan_priv_rx);
+		dev_dbg(&host->pdev->dev, "%s: RX: got channel %p\n", __func__,
+			host->chan_rx);
+
+		if (!host->chan_rx)
+			goto ereqrx;
+
+		host->bounce_buf = (u8 *)__get_free_page(GFP_KERNEL | GFP_DMA);
+		if (!host->bounce_buf)
+			goto ebouncebuf;
+
+		tasklet_init(&host->dma_complete, tmio_mmc_tasklet_fn, (unsigned long)host);
+		tasklet_init(&host->dma_issue, tmio_mmc_issue_tasklet_fn, (unsigned long)host);
+
+		tmio_mmc_enable_dma(host, true);
+
+		return;
+ebouncebuf:
+		dma_release_channel(host->chan_rx);
+		host->chan_rx = NULL;
+ereqrx:
+		dma_release_channel(host->chan_tx);
+		host->chan_tx = NULL;
+		return;
+	}
+}
+
+void tmio_mmc_release_dma(struct tmio_mmc_host *host)
+{
+	if (host->chan_tx) {
+		struct dma_chan *chan = host->chan_tx;
+		host->chan_tx = NULL;
+		dma_release_channel(chan);
+	}
+	if (host->chan_rx) {
+		struct dma_chan *chan = host->chan_rx;
+		host->chan_rx = NULL;
+		dma_release_channel(chan);
+	}
+	if (host->bounce_buf) {
+		free_pages((unsigned long)host->bounce_buf, 0);
+		host->bounce_buf = NULL;
+	}
+}
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc.h linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc.h
--- linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,123 @@
+/*
+ * linux/drivers/mmc/host/tmio_mmc.h
+ *
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
+ *
+ * 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 MMC / SD / SDIO cell found in:
+ *
+ * TC6393XB TC6391XB TC6387XB T7L66XB ASIC3
+ */
+
+#ifndef TMIO_MMC_H
+#define TMIO_MMC_H
+
+#include <linux/highmem.h>
+#include <linux/mmc/tmio.h>
+#include <linux/pagemap.h>
+
+/* Definitions for values the CTRL_SDIO_STATUS register can take. */
+#define TMIO_SDIO_STAT_IOIRQ	0x0001
+#define TMIO_SDIO_STAT_EXPUB52	0x4000
+#define TMIO_SDIO_STAT_EXWT	0x8000
+#define TMIO_SDIO_MASK_ALL	0xc007
+
+/* Define some IRQ masks */
+/* This is the mask used at reset by the chip */
+#define TMIO_MASK_ALL           0x837f031d
+#define TMIO_MASK_READOP  (TMIO_STAT_RXRDY | TMIO_STAT_DATAEND)
+#define TMIO_MASK_WRITEOP (TMIO_STAT_TXRQ | TMIO_STAT_DATAEND)
+#define TMIO_MASK_CMD     (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT | \
+		TMIO_STAT_CARD_REMOVE | TMIO_STAT_CARD_INSERT)
+#define TMIO_MASK_IRQ     (TMIO_MASK_READOP | TMIO_MASK_WRITEOP | TMIO_MASK_CMD)
+
+struct tmio_mmc_data;
+
+struct tmio_mmc_host {
+	void __iomem *ctl;
+	unsigned long bus_shift;
+	struct mmc_command      *cmd;
+	struct mmc_request      *mrq;
+	struct mmc_data         *data;
+	struct mmc_host         *mmc;
+	int                     irq;
+	unsigned int		sdio_irq_enabled;
+
+	/* Callbacks for clock / power control */
+	void (*set_pwr)(struct platform_device *host, int state);
+	void (*set_clk_div)(struct platform_device *host, int state);
+
+	/* pio related stuff */
+	struct scatterlist      *sg_ptr;
+	struct scatterlist      *sg_orig;
+	unsigned int            sg_len;
+	unsigned int            sg_off;
+
+	struct platform_device *pdev;
+	struct tmio_mmc_data *pdata;
+
+	/* DMA support */
+	bool			force_pio;
+	struct dma_chan		*chan_rx;
+	struct dma_chan		*chan_tx;
+	struct tasklet_struct	dma_complete;
+	struct tasklet_struct	dma_issue;
+	struct scatterlist	bounce_sg;
+	u8			*bounce_buf;
+
+	/* Track lost interrupts */
+	struct delayed_work	delayed_reset_work;
+	spinlock_t		lock;
+	unsigned long		last_req_ts;
+};
+
+int tmio_mmc_host_probe(struct tmio_mmc_host **host,
+			struct platform_device *pdev,
+			struct tmio_mmc_data *pdata);
+void tmio_mmc_host_remove(struct tmio_mmc_host *host);
+void tmio_mmc_do_data_irq(struct tmio_mmc_host *host);
+
+void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
+void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i);
+
+static inline char *tmio_mmc_kmap_atomic(struct scatterlist *sg,
+					 unsigned long *flags)
+{
+	local_irq_save(*flags);
+	return kmap_atomic(sg_page(sg), KM_BIO_SRC_IRQ) + sg->offset;
+}
+
+static inline void tmio_mmc_kunmap_atomic(struct scatterlist *sg,
+					  unsigned long *flags, void *virt)
+{
+	kunmap_atomic(virt - sg->offset, KM_BIO_SRC_IRQ);
+	local_irq_restore(*flags);
+}
+
+#if defined(CONFIG_MMC_SDHI) || defined(CONFIG_MMC_SDHI_MODULE)
+void tmio_mmc_start_dma(struct tmio_mmc_host *host, struct mmc_data *data);
+void tmio_mmc_request_dma(struct tmio_mmc_host *host, struct tmio_mmc_data *pdata);
+void tmio_mmc_release_dma(struct tmio_mmc_host *host);
+#else
+static inline void tmio_mmc_start_dma(struct tmio_mmc_host *host,
+			       struct mmc_data *data)
+{
+}
+
+static inline void tmio_mmc_request_dma(struct tmio_mmc_host *host,
+				 struct tmio_mmc_data *pdata)
+{
+	host->chan_tx = NULL;
+	host->chan_rx = NULL;
+}
+
+static inline void tmio_mmc_release_dma(struct tmio_mmc_host *host)
+{
+}
+#endif
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc_pio.c linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc_pio.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/tmio_mmc_pio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/tmio_mmc_pio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,897 @@
+/*
+ * linux/drivers/mmc/host/tmio_mmc_pio.c
+ *
+ * Copyright (C) 2011 Guennadi Liakhovetski
+ * Copyright (C) 2007 Ian Molton
+ * Copyright (C) 2004 Ian Molton
+ *
+ * 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 MMC / SD / SDIO IP found in:
+ *
+ * TC6393XB, TC6391XB, TC6387XB, T7L66XB, ASIC3, SH-Mobile SoCs
+ *
+ * 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
+ * support). (Further 4 bit support from a later datasheet).
+ *
+ * TODO:
+ *   Investigate using a workqueue for PIO transfers
+ *   Eliminate FIXMEs
+ *   SDIO support
+ *   Better Power management
+ *   Handle MMC errors better
+ *   double buffer support
+ *
+ */
+
+#include <linux/delay.h>
+#include <linux/device.h>
+#include <linux/highmem.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/mfd/tmio.h>
+#include <linux/mmc/host.h>
+#include <linux/mmc/tmio.h>
+#include <linux/module.h>
+#include <linux/pagemap.h>
+#include <linux/platform_device.h>
+#include <linux/scatterlist.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+
+#include "tmio_mmc.h"
+
+static u16 sd_ctrl_read16(struct tmio_mmc_host *host, int addr)
+{
+	return readw(host->ctl + (addr << host->bus_shift));
+}
+
+static 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 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 void sd_ctrl_write16(struct tmio_mmc_host *host, int addr, u16 val)
+{
+	writew(val, host->ctl + (addr << host->bus_shift));
+}
+
+static 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 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));
+}
+
+void tmio_mmc_enable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
+{
+	u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) & ~(i & TMIO_MASK_IRQ);
+	sd_ctrl_write32(host, CTL_IRQ_MASK, mask);
+}
+
+void tmio_mmc_disable_mmc_irqs(struct tmio_mmc_host *host, u32 i)
+{
+	u32 mask = sd_ctrl_read32(host, CTL_IRQ_MASK) | (i & TMIO_MASK_IRQ);
+	sd_ctrl_write32(host, CTL_IRQ_MASK, mask);
+}
+
+static void tmio_mmc_ack_mmc_irqs(struct tmio_mmc_host *host, u32 i)
+{
+	sd_ctrl_write32(host, CTL_STATUS, ~i);
+}
+
+static void tmio_mmc_init_sg(struct tmio_mmc_host *host, struct mmc_data *data)
+{
+	host->sg_len = data->sg_len;
+	host->sg_ptr = data->sg;
+	host->sg_orig = data->sg;
+	host->sg_off = 0;
+}
+
+static int tmio_mmc_next_sg(struct tmio_mmc_host *host)
+{
+	host->sg_ptr = sg_next(host->sg_ptr);
+	host->sg_off = 0;
+	return --host->sg_len;
+}
+
+#ifdef CONFIG_MMC_DEBUG
+
+#define STATUS_TO_TEXT(a, status, i) \
+	do { \
+		if (status & TMIO_STAT_##a) { \
+			if (i++) \
+				printk(" | "); \
+			printk(#a); \
+		} \
+	} while (0)
+
+static void pr_debug_status(u32 status)
+{
+	int i = 0;
+	printk(KERN_DEBUG "status: %08x = ", status);
+	STATUS_TO_TEXT(CARD_REMOVE, status, i);
+	STATUS_TO_TEXT(CARD_INSERT, status, i);
+	STATUS_TO_TEXT(SIGSTATE, status, i);
+	STATUS_TO_TEXT(WRPROTECT, status, i);
+	STATUS_TO_TEXT(CARD_REMOVE_A, status, i);
+	STATUS_TO_TEXT(CARD_INSERT_A, status, i);
+	STATUS_TO_TEXT(SIGSTATE_A, status, i);
+	STATUS_TO_TEXT(CMD_IDX_ERR, status, i);
+	STATUS_TO_TEXT(STOPBIT_ERR, status, i);
+	STATUS_TO_TEXT(ILL_FUNC, status, i);
+	STATUS_TO_TEXT(CMD_BUSY, status, i);
+	STATUS_TO_TEXT(CMDRESPEND, status, i);
+	STATUS_TO_TEXT(DATAEND, status, i);
+	STATUS_TO_TEXT(CRCFAIL, status, i);
+	STATUS_TO_TEXT(DATATIMEOUT, status, i);
+	STATUS_TO_TEXT(CMDTIMEOUT, status, i);
+	STATUS_TO_TEXT(RXOVERFLOW, status, i);
+	STATUS_TO_TEXT(TXUNDERRUN, status, i);
+	STATUS_TO_TEXT(RXRDY, status, i);
+	STATUS_TO_TEXT(TXRQ, status, i);
+	STATUS_TO_TEXT(ILL_ACCESS, status, i);
+	printk("\n");
+}
+
+#else
+#define pr_debug_status(s)  do { } while (0)
+#endif
+
+static void tmio_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+
+	if (enable) {
+		host->sdio_irq_enabled = 1;
+		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0001);
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK,
+			(TMIO_SDIO_MASK_ALL & ~TMIO_SDIO_STAT_IOIRQ));
+	} else {
+		sd_ctrl_write16(host, CTL_SDIO_IRQ_MASK, TMIO_SDIO_MASK_ALL);
+		sd_ctrl_write16(host, CTL_TRANSACTION_CTL, 0x0000);
+		host->sdio_irq_enabled = 0;
+	}
+}
+
+static void tmio_mmc_set_clock(struct tmio_mmc_host *host, int new_clock)
+{
+	u32 clk = 0, clock;
+
+	if (new_clock) {
+		for (clock = host->mmc->f_min, clk = 0x80000080;
+			new_clock >= (clock<<1); clk >>= 1)
+			clock <<= 1;
+		clk |= 0x100;
+	}
+
+	if (host->set_clk_div)
+		host->set_clk_div(host->pdev, (clk>>22) & 1);
+
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, clk & 0x1ff);
+}
+
+static void tmio_mmc_clk_stop(struct tmio_mmc_host *host)
+{
+	struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+
+	/* implicit BUG_ON(!res) */
+	if (resource_size(res) > 0x100) {
+		sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0000);
+		msleep(10);
+	}
+
+	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)
+{
+	struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+
+	sd_ctrl_write16(host, CTL_SD_CARD_CLK_CTL, 0x0100 |
+		sd_ctrl_read16(host, CTL_SD_CARD_CLK_CTL));
+	msleep(10);
+
+	/* implicit BUG_ON(!res) */
+	if (resource_size(res) > 0x100) {
+		sd_ctrl_write16(host, CTL_CLK_AND_WAIT_CTL, 0x0100);
+		msleep(10);
+	}
+}
+
+static void tmio_mmc_reset(struct tmio_mmc_host *host)
+{
+	struct resource *res = platform_get_resource(host->pdev, IORESOURCE_MEM, 0);
+
+	/* FIXME - should we set stop clock reg here */
+	sd_ctrl_write16(host, CTL_RESET_SD, 0x0000);
+	/* implicit BUG_ON(!res) */
+	if (resource_size(res) > 0x100)
+		sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0000);
+	msleep(10);
+	sd_ctrl_write16(host, CTL_RESET_SD, 0x0001);
+	if (resource_size(res) > 0x100)
+		sd_ctrl_write16(host, CTL_RESET_SDIO, 0x0001);
+	msleep(10);
+}
+
+static void tmio_mmc_reset_work(struct work_struct *work)
+{
+	struct tmio_mmc_host *host = container_of(work, struct tmio_mmc_host,
+						  delayed_reset_work.work);
+	struct mmc_request *mrq;
+	unsigned long flags;
+
+	spin_lock_irqsave(&host->lock, flags);
+	mrq = host->mrq;
+
+	/* request already finished */
+	if (!mrq
+	    || time_is_after_jiffies(host->last_req_ts +
+		msecs_to_jiffies(2000))) {
+		spin_unlock_irqrestore(&host->lock, flags);
+		return;
+	}
+
+	dev_warn(&host->pdev->dev,
+		"timeout waiting for hardware interrupt (CMD%u)\n",
+		mrq->cmd->opcode);
+
+	if (host->data)
+		host->data->error = -ETIMEDOUT;
+	else if (host->cmd)
+		host->cmd->error = -ETIMEDOUT;
+	else
+		mrq->cmd->error = -ETIMEDOUT;
+
+	host->cmd = NULL;
+	host->data = NULL;
+	host->mrq = NULL;
+	host->force_pio = false;
+
+	spin_unlock_irqrestore(&host->lock, flags);
+
+	tmio_mmc_reset(host);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+static void tmio_mmc_finish_request(struct tmio_mmc_host *host)
+{
+	struct mmc_request *mrq = host->mrq;
+
+	if (!mrq)
+		return;
+
+	host->mrq = NULL;
+	host->cmd = NULL;
+	host->data = NULL;
+	host->force_pio = false;
+
+	cancel_delayed_work(&host->delayed_reset_work);
+
+	mmc_request_done(host->mmc, mrq);
+}
+
+/* These are the bitmasks the tmio chip requires to implement the MMC response
+ * types. Note that R1 and R6 are the same in this scheme. */
+#define APP_CMD        0x0040
+#define RESP_NONE      0x0300
+#define RESP_R1        0x0400
+#define RESP_R1B       0x0500
+#define RESP_R2        0x0600
+#define RESP_R3        0x0700
+#define DATA_PRESENT   0x0800
+#define TRANSFER_READ  0x1000
+#define TRANSFER_MULTI 0x2000
+#define SECURITY_CMD   0x4000
+
+static int tmio_mmc_start_command(struct tmio_mmc_host *host, struct mmc_command *cmd)
+{
+	struct mmc_data *data = host->data;
+	int c = cmd->opcode;
+
+	/* Command 12 is handled by hardware */
+	if (cmd->opcode == 12 && !cmd->arg) {
+		sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x001);
+		return 0;
+	}
+
+	switch (mmc_resp_type(cmd)) {
+	case MMC_RSP_NONE: c |= RESP_NONE; break;
+	case MMC_RSP_R1:   c |= RESP_R1;   break;
+	case MMC_RSP_R1B:  c |= RESP_R1B;  break;
+	case MMC_RSP_R2:   c |= RESP_R2;   break;
+	case MMC_RSP_R3:   c |= RESP_R3;   break;
+	default:
+		pr_debug("Unknown response type %d\n", mmc_resp_type(cmd));
+		return -EINVAL;
+	}
+
+	host->cmd = cmd;
+
+/* FIXME - this seems to be ok commented out but the spec suggest this bit
+ *         should be set when issuing app commands.
+ *	if(cmd->flags & MMC_FLAG_ACMD)
+ *		c |= APP_CMD;
+ */
+	if (data) {
+		c |= DATA_PRESENT;
+		if (data->blocks > 1) {
+			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x100);
+			c |= TRANSFER_MULTI;
+		}
+		if (data->flags & MMC_DATA_READ)
+			c |= TRANSFER_READ;
+	}
+
+	tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_CMD);
+
+	/* Fire off the command */
+	sd_ctrl_write32(host, CTL_ARG_REG, cmd->arg);
+	sd_ctrl_write16(host, CTL_SD_CMD, c);
+
+	return 0;
+}
+
+/*
+ * This chip always returns (at least?) as much data as you ask for.
+ * I'm unsure what happens if you ask for less than a block. This should be
+ * looked into to ensure that a funny length read doesn't hose the controller.
+ */
+static void tmio_mmc_pio_irq(struct tmio_mmc_host *host)
+{
+	struct mmc_data *data = host->data;
+	void *sg_virt;
+	unsigned short *buf;
+	unsigned int count;
+	unsigned long flags;
+
+	if ((host->chan_tx || host->chan_rx) && !host->force_pio) {
+		pr_err("PIO IRQ in DMA mode!\n");
+		return;
+	} else if (!data) {
+		pr_debug("Spurious PIO IRQ\n");
+		return;
+	}
+
+	sg_virt = tmio_mmc_kmap_atomic(host->sg_ptr, &flags);
+	buf = (unsigned short *)(sg_virt + host->sg_off);
+
+	count = host->sg_ptr->length - host->sg_off;
+	if (count > data->blksz)
+		count = data->blksz;
+
+	pr_debug("count: %08x offset: %08x flags %08x\n",
+		 count, host->sg_off, data->flags);
+
+	/* Transfer the data */
+	if (data->flags & MMC_DATA_READ)
+		sd_ctrl_read16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+	else
+		sd_ctrl_write16_rep(host, CTL_SD_DATA_PORT, buf, count >> 1);
+
+	host->sg_off += count;
+
+	tmio_mmc_kunmap_atomic(host->sg_ptr, &flags, sg_virt);
+
+	if (host->sg_off == host->sg_ptr->length)
+		tmio_mmc_next_sg(host);
+
+	return;
+}
+
+static void tmio_mmc_check_bounce_buffer(struct tmio_mmc_host *host)
+{
+	if (host->sg_ptr == &host->bounce_sg) {
+		unsigned long flags;
+		void *sg_vaddr = tmio_mmc_kmap_atomic(host->sg_orig, &flags);
+		memcpy(sg_vaddr, host->bounce_buf, host->bounce_sg.length);
+		tmio_mmc_kunmap_atomic(host->sg_orig, &flags, sg_vaddr);
+	}
+}
+
+/* needs to be called with host->lock held */
+void tmio_mmc_do_data_irq(struct tmio_mmc_host *host)
+{
+	struct mmc_data *data = host->data;
+	struct mmc_command *stop;
+
+	host->data = NULL;
+
+	if (!data) {
+		dev_warn(&host->pdev->dev, "Spurious data end IRQ\n");
+		return;
+	}
+	stop = data->stop;
+
+	/* FIXME - return correct transfer count on errors */
+	if (!data->error)
+		data->bytes_xfered = data->blocks * data->blksz;
+	else
+		data->bytes_xfered = 0;
+
+	pr_debug("Completed data request\n");
+
+	/*
+	 * FIXME: other drivers allow an optional stop command of any given type
+	 *        which we dont do, as the chip can auto generate them.
+	 *        Perhaps we can be smarter about when to use auto CMD12 and
+	 *        only issue the auto request when we know this is the desired
+	 *        stop command, allowing fallback to the stop command the
+	 *        upper layers expect. For now, we do what works.
+	 */
+
+	if (data->flags & MMC_DATA_READ) {
+		if (host->chan_rx && !host->force_pio)
+			tmio_mmc_check_bounce_buffer(host);
+		dev_dbg(&host->pdev->dev, "Complete Rx request %p\n",
+			host->mrq);
+	} else {
+		dev_dbg(&host->pdev->dev, "Complete Tx request %p\n",
+			host->mrq);
+	}
+
+	if (stop) {
+		if (stop->opcode == 12 && !stop->arg)
+			sd_ctrl_write16(host, CTL_STOP_INTERNAL_ACTION, 0x000);
+		else
+			BUG();
+	}
+
+	tmio_mmc_finish_request(host);
+}
+
+static void tmio_mmc_data_irq(struct tmio_mmc_host *host)
+{
+	struct mmc_data *data;
+	spin_lock(&host->lock);
+	data = host->data;
+
+	if (!data)
+		goto out;
+
+	if (host->chan_tx && (data->flags & MMC_DATA_WRITE) && !host->force_pio) {
+		/*
+		 * Has all data been written out yet? Testing on SuperH showed,
+		 * that in most cases the first interrupt comes already with the
+		 * BUSY status bit clear, but on some operations, like mount or
+		 * in the beginning of a write / sync / umount, there is one
+		 * DATAEND interrupt with the BUSY bit set, in this cases
+		 * waiting for one more interrupt fixes the problem.
+		 */
+		if (!(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_CMD_BUSY)) {
+			tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_DATAEND);
+			tasklet_schedule(&host->dma_complete);
+		}
+	} else if (host->chan_rx && (data->flags & MMC_DATA_READ) && !host->force_pio) {
+		tmio_mmc_disable_mmc_irqs(host, TMIO_STAT_DATAEND);
+		tasklet_schedule(&host->dma_complete);
+	} else {
+		tmio_mmc_do_data_irq(host);
+		tmio_mmc_disable_mmc_irqs(host, TMIO_MASK_READOP | TMIO_MASK_WRITEOP);
+	}
+out:
+	spin_unlock(&host->lock);
+}
+
+static void tmio_mmc_cmd_irq(struct tmio_mmc_host *host,
+	unsigned int stat)
+{
+	struct mmc_command *cmd = host->cmd;
+	int i, addr;
+
+	spin_lock(&host->lock);
+
+	if (!host->cmd) {
+		pr_debug("Spurious CMD irq\n");
+		goto out;
+	}
+
+	host->cmd = NULL;
+
+	/* This controller is sicker than the PXA one. Not only do we need to
+	 * drop the top 8 bits of the first response word, we also need to
+	 * modify the order of the response for short response command types.
+	 */
+
+	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);
+		cmd->resp[1] = (cmd->resp[1] << 8) | (cmd->resp[2] >> 24);
+		cmd->resp[2] = (cmd->resp[2] << 8) | (cmd->resp[3] >> 24);
+		cmd->resp[3] <<= 8;
+	} else if (cmd->flags & MMC_RSP_R3) {
+		cmd->resp[0] = cmd->resp[3];
+	}
+
+	if (stat & TMIO_STAT_CMDTIMEOUT)
+		cmd->error = -ETIMEDOUT;
+	else if (stat & TMIO_STAT_CRCFAIL && cmd->flags & MMC_RSP_CRC)
+		cmd->error = -EILSEQ;
+
+	/* If there is data to handle we enable data IRQs here, and
+	 * we will ultimatley finish the request in the data_end handler.
+	 * If theres no data or we encountered an error, finish now.
+	 */
+	if (host->data && !cmd->error) {
+		if (host->data->flags & MMC_DATA_READ) {
+			if (host->force_pio || !host->chan_rx)
+				tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_READOP);
+			else
+				tasklet_schedule(&host->dma_issue);
+		} else {
+			if (host->force_pio || !host->chan_tx)
+				tmio_mmc_enable_mmc_irqs(host, TMIO_MASK_WRITEOP);
+			else
+				tasklet_schedule(&host->dma_issue);
+		}
+	} else {
+		tmio_mmc_finish_request(host);
+	}
+
+out:
+	spin_unlock(&host->lock);
+}
+
+static irqreturn_t tmio_mmc_irq(int irq, void *devid)
+{
+	struct tmio_mmc_host *host = devid;
+	struct tmio_mmc_data *pdata = host->pdata;
+	unsigned int ireg, irq_mask, status;
+	unsigned int sdio_ireg, sdio_irq_mask, sdio_status;
+
+	pr_debug("MMC IRQ begin\n");
+
+	status = sd_ctrl_read32(host, CTL_STATUS);
+	irq_mask = sd_ctrl_read32(host, CTL_IRQ_MASK);
+	ireg = status & TMIO_MASK_IRQ & ~irq_mask;
+
+	sdio_ireg = 0;
+	if (!ireg && pdata->flags & TMIO_MMC_SDIO_IRQ) {
+		sdio_status = sd_ctrl_read16(host, CTL_SDIO_STATUS);
+		sdio_irq_mask = sd_ctrl_read16(host, CTL_SDIO_IRQ_MASK);
+		sdio_ireg = sdio_status & TMIO_SDIO_MASK_ALL & ~sdio_irq_mask;
+
+		sd_ctrl_write16(host, CTL_SDIO_STATUS, sdio_status & ~TMIO_SDIO_MASK_ALL);
+
+		if (sdio_ireg && !host->sdio_irq_enabled) {
+			pr_warning("tmio_mmc: Spurious SDIO IRQ, disabling! 0x%04x 0x%04x 0x%04x\n",
+				   sdio_status, sdio_irq_mask, sdio_ireg);
+			tmio_mmc_enable_sdio_irq(host->mmc, 0);
+			goto out;
+		}
+
+		if (host->mmc->caps & MMC_CAP_SDIO_IRQ &&
+			sdio_ireg & TMIO_SDIO_STAT_IOIRQ)
+			mmc_signal_sdio_irq(host->mmc);
+
+		if (sdio_ireg)
+			goto out;
+	}
+
+	pr_debug_status(status);
+	pr_debug_status(ireg);
+
+	if (!ireg) {
+		tmio_mmc_disable_mmc_irqs(host, status & ~irq_mask);
+
+		pr_warning("tmio_mmc: Spurious irq, disabling! "
+			"0x%08x 0x%08x 0x%08x\n", status, irq_mask, ireg);
+		pr_debug_status(status);
+
+		goto out;
+	}
+
+	while (ireg) {
+		/* Card insert / remove attempts */
+		if (ireg & (TMIO_STAT_CARD_INSERT | TMIO_STAT_CARD_REMOVE)) {
+			tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_CARD_INSERT |
+				TMIO_STAT_CARD_REMOVE);
+			mmc_detect_change(host->mmc, msecs_to_jiffies(100));
+		}
+
+		/* CRC and other errors */
+/*		if (ireg & TMIO_STAT_ERR_IRQ)
+ *			handled |= tmio_error_irq(host, irq, stat);
+ */
+
+		/* Command completion */
+		if (ireg & (TMIO_STAT_CMDRESPEND | TMIO_STAT_CMDTIMEOUT)) {
+			tmio_mmc_ack_mmc_irqs(host,
+				     TMIO_STAT_CMDRESPEND |
+				     TMIO_STAT_CMDTIMEOUT);
+			tmio_mmc_cmd_irq(host, status);
+		}
+
+		/* Data transfer */
+		if (ireg & (TMIO_STAT_RXRDY | TMIO_STAT_TXRQ)) {
+			tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_RXRDY | TMIO_STAT_TXRQ);
+			tmio_mmc_pio_irq(host);
+		}
+
+		/* Data transfer completion */
+		if (ireg & TMIO_STAT_DATAEND) {
+			tmio_mmc_ack_mmc_irqs(host, TMIO_STAT_DATAEND);
+			tmio_mmc_data_irq(host);
+		}
+
+		/* Check status - keep going until we've handled it all */
+		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);
+		pr_debug_status(status);
+	}
+	pr_debug("MMC IRQ end\n");
+
+out:
+	return IRQ_HANDLED;
+}
+
+static int tmio_mmc_start_data(struct tmio_mmc_host *host,
+	struct mmc_data *data)
+{
+	struct tmio_mmc_data *pdata = host->pdata;
+
+	pr_debug("setup data transfer: blocksize %08x  nr_blocks %d\n",
+		 data->blksz, data->blocks);
+
+	/* Some hardware cannot perform 2 byte requests in 4 bit mode */
+	if (host->mmc->ios.bus_width == MMC_BUS_WIDTH_4) {
+		int blksz_2bytes = pdata->flags & TMIO_MMC_BLKSZ_2BYTES;
+
+		if (data->blksz < 2 || (data->blksz < 4 && !blksz_2bytes)) {
+			pr_err("%s: %d byte block unsupported in 4 bit mode\n",
+			       mmc_hostname(host->mmc), data->blksz);
+			return -EINVAL;
+		}
+	}
+
+	tmio_mmc_init_sg(host, data);
+	host->data = data;
+
+	/* Set transfer length / blocksize */
+	sd_ctrl_write16(host, CTL_SD_XFER_LEN, data->blksz);
+	sd_ctrl_write16(host, CTL_XFER_BLK_COUNT, data->blocks);
+
+	tmio_mmc_start_dma(host, data);
+
+	return 0;
+}
+
+/* Process requests from the MMC layer */
+static void tmio_mmc_request(struct mmc_host *mmc, struct mmc_request *mrq)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+	int ret;
+
+	if (host->mrq)
+		pr_debug("request not null\n");
+
+	host->last_req_ts = jiffies;
+	wmb();
+	host->mrq = mrq;
+
+	if (mrq->data) {
+		ret = tmio_mmc_start_data(host, mrq->data);
+		if (ret)
+			goto fail;
+	}
+
+	ret = tmio_mmc_start_command(host, mrq->cmd);
+	if (!ret) {
+		schedule_delayed_work(&host->delayed_reset_work,
+				      msecs_to_jiffies(2000));
+		return;
+	}
+
+fail:
+	host->mrq = NULL;
+	host->force_pio = false;
+	mrq->cmd->error = ret;
+	mmc_request_done(mmc, mrq);
+}
+
+/* Set MMC clock / power.
+ * Note: This controller uses a simple divider scheme therefore it cannot
+ * run a MMC card at full speed (20MHz). The max clock is 24MHz on SD, but as
+ * MMC wont run that fast, it has to be clocked at 12MHz which is the next
+ * slowest setting.
+ */
+static void tmio_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+
+	if (ios->clock)
+		tmio_mmc_set_clock(host, ios->clock);
+
+	/* Power sequence - OFF -> UP -> ON */
+	if (ios->power_mode == MMC_POWER_UP) {
+		/* power up SD bus */
+		if (host->set_pwr)
+			host->set_pwr(host->pdev, 1);
+	} else if (ios->power_mode == MMC_POWER_OFF || !ios->clock) {
+		/* power down SD bus */
+		if (ios->power_mode == MMC_POWER_OFF && host->set_pwr)
+			host->set_pwr(host->pdev, 0);
+		tmio_mmc_clk_stop(host);
+	} else {
+		/* start bus clock */
+		tmio_mmc_clk_start(host);
+	}
+
+	switch (ios->bus_width) {
+	case MMC_BUS_WIDTH_1:
+		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x80e0);
+	break;
+	case MMC_BUS_WIDTH_4:
+		sd_ctrl_write16(host, CTL_SD_MEM_CARD_OPT, 0x00e0);
+	break;
+	}
+
+	/* Let things settle. delay taken from winCE driver */
+	udelay(140);
+}
+
+static int tmio_mmc_get_ro(struct mmc_host *mmc)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+	struct tmio_mmc_data *pdata = host->pdata;
+
+	return ((pdata->flags & TMIO_MMC_WRPROTECT_DISABLE) ||
+		!(sd_ctrl_read32(host, CTL_STATUS) & TMIO_STAT_WRPROTECT));
+}
+
+static int tmio_mmc_get_cd(struct mmc_host *mmc)
+{
+	struct tmio_mmc_host *host = mmc_priv(mmc);
+	struct tmio_mmc_data *pdata = host->pdata;
+
+	if (!pdata->get_cd)
+		return -ENOSYS;
+	else
+		return pdata->get_cd(host->pdev);
+}
+
+static const struct mmc_host_ops tmio_mmc_ops = {
+	.request	= tmio_mmc_request,
+	.set_ios	= tmio_mmc_set_ios,
+	.get_ro         = tmio_mmc_get_ro,
+	.get_cd		= tmio_mmc_get_cd,
+	.enable_sdio_irq = tmio_mmc_enable_sdio_irq,
+};
+
+int __devinit tmio_mmc_host_probe(struct tmio_mmc_host **host,
+				  struct platform_device *pdev,
+				  struct tmio_mmc_data *pdata)
+{
+	struct tmio_mmc_host *_host;
+	struct mmc_host *mmc;
+	struct resource *res_ctl;
+	int ret;
+	u32 irq_mask = TMIO_MASK_CMD;
+
+	res_ctl = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res_ctl)
+		return -EINVAL;
+
+	mmc = mmc_alloc_host(sizeof(struct tmio_mmc_host), &pdev->dev);
+	if (!mmc)
+		return -ENOMEM;
+
+	_host = mmc_priv(mmc);
+	_host->pdata = pdata;
+	_host->mmc = mmc;
+	_host->pdev = pdev;
+	platform_set_drvdata(pdev, mmc);
+
+	_host->set_pwr = pdata->set_pwr;
+	_host->set_clk_div = pdata->set_clk_div;
+
+	/* 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) {
+		ret = -ENOMEM;
+		goto host_free;
+	}
+
+	mmc->ops = &tmio_mmc_ops;
+	mmc->caps = MMC_CAP_4_BIT_DATA | pdata->capabilities;
+	mmc->f_max = pdata->hclk;
+	mmc->f_min = mmc->f_max / 512;
+	mmc->max_segs = 32;
+	mmc->max_blk_size = 512;
+	mmc->max_blk_count = (PAGE_CACHE_SIZE / mmc->max_blk_size) *
+		mmc->max_segs;
+	mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+	mmc->max_seg_size = mmc->max_req_size;
+	if (pdata->ocr_mask)
+		mmc->ocr_avail = pdata->ocr_mask;
+	else
+		mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34;
+
+	tmio_mmc_clk_stop(_host);
+	tmio_mmc_reset(_host);
+
+	ret = platform_get_irq(pdev, 0);
+	if (ret < 0)
+		goto unmap_ctl;
+
+	_host->irq = ret;
+
+	tmio_mmc_disable_mmc_irqs(_host, TMIO_MASK_ALL);
+	if (pdata->flags & TMIO_MMC_SDIO_IRQ)
+		tmio_mmc_enable_sdio_irq(mmc, 0);
+
+	ret = request_irq(_host->irq, tmio_mmc_irq, IRQF_DISABLED |
+		IRQF_TRIGGER_FALLING, dev_name(&pdev->dev), _host);
+	if (ret)
+		goto unmap_ctl;
+
+	spin_lock_init(&_host->lock);
+
+	/* Init delayed work for request timeouts */
+	INIT_DELAYED_WORK(&_host->delayed_reset_work, tmio_mmc_reset_work);
+
+	/* See if we also get DMA */
+	tmio_mmc_request_dma(_host, pdata);
+
+	mmc_add_host(mmc);
+
+	/* Unmask the IRQs we want to know about */
+	if (!_host->chan_rx)
+		irq_mask |= TMIO_MASK_READOP;
+	if (!_host->chan_tx)
+		irq_mask |= TMIO_MASK_WRITEOP;
+
+	tmio_mmc_enable_mmc_irqs(_host, irq_mask);
+
+	*host = _host;
+
+	return 0;
+
+unmap_ctl:
+	iounmap(_host->ctl);
+host_free:
+	mmc_free_host(mmc);
+
+	return ret;
+}
+EXPORT_SYMBOL(tmio_mmc_host_probe);
+
+void tmio_mmc_host_remove(struct tmio_mmc_host *host)
+{
+	mmc_remove_host(host->mmc);
+	cancel_delayed_work_sync(&host->delayed_reset_work);
+	tmio_mmc_release_dma(host);
+	free_irq(host->irq, host);
+	iounmap(host->ctl);
+	mmc_free_host(host->mmc);
+}
+EXPORT_SYMBOL(tmio_mmc_host_remove);
+
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/via-sdmmc.c linux-libre-2.6.39-gnu/drivers/mmc/host/via-sdmmc.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/via-sdmmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/via-sdmmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -802,12 +802,9 @@
 
 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);
@@ -1090,14 +1087,13 @@
 	struct mmc_host *mmc;
 	struct via_crdr_mmc_host *sdhost;
 	u32 base, len;
-	u8 rev, gatt;
+	u8  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);
+		(int)pcidev->revision);
 
 	ret = pci_enable_device(pcidev);
 	if (ret)
diff -druN linux-libre-2.6.38-gnu/drivers/mmc/host/wbsd.c linux-libre-2.6.39-gnu/drivers/mmc/host/wbsd.c
--- linux-libre-2.6.38-gnu/drivers/mmc/host/wbsd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mmc/host/wbsd.c	2011-05-19 00:06:34.000000000 -0400
@@ -484,7 +484,7 @@
 
 	/*
 	 * Check that we aren't being called after the
-	 * entire buffer has been transfered.
+	 * entire buffer has been transferred.
 	 */
 	if (host->num_sg == 0)
 		return;
@@ -828,7 +828,7 @@
 	/*
 	 * If this is a data transfer the request
 	 * will be finished after the data has
-	 * transfered.
+	 * transferred.
 	 */
 	if (cmd->data && !cmd->error) {
 		/*
@@ -904,7 +904,7 @@
 			setup &= ~WBSD_DAT3_H;
 
 			/*
-			 * We cannot resume card detection immediatly
+			 * We cannot resume card detection immediately
 			 * because of capacitance and delays in the chip.
 			 */
 			mod_timer(&host->ignore_timer, jiffies + HZ / 100);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_cmdset_0001.c linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_cmdset_0001.c
--- linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_cmdset_0001.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_cmdset_0001.c	2011-05-19 00:06:34.000000000 -0400
@@ -455,7 +455,7 @@
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
 	mtd->writesize = 1;
-	mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+	mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 
 	mtd->reboot_notifier.notifier_call = cfi_intelext_reboot;
 
@@ -1247,12 +1247,12 @@
 			break;
 
 		if (chip->erase_suspended && chip_state == FL_ERASING)  {
-			/* Erase suspend occured while sleep: reset timeout */
+			/* Erase suspend occurred while sleep: reset timeout */
 			timeo = reset_timeo;
 			chip->erase_suspended = 0;
 		}
 		if (chip->write_suspended && chip_state == FL_WRITING)  {
-			/* Write suspend occured while sleep: reset timeout */
+			/* Write suspend occurred while sleep: reset timeout */
 			timeo = reset_timeo;
 			chip->write_suspended = 0;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_cmdset_0002.c linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_cmdset_0002.c
--- linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_cmdset_0002.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_cmdset_0002.c	2011-05-19 00:06:34.000000000 -0400
@@ -263,7 +263,7 @@
 	struct cfi_private *cfi = map->fldrv_priv;
 
 	/*
-	 * These flashes report two seperate eraseblock regions based on the
+	 * These flashes report two separate eraseblock regions based on the
 	 * sector_erase-size and block_erase-size, although they both operate on the
 	 * same memory. This is not allowed according to CFI, so we just pick the
 	 * sector_erase-size.
@@ -349,6 +349,7 @@
 	{ CFI_MFR_ATMEL, CFI_ID_ANY, fixup_convert_atmel_pri },
 #ifdef AMD_BOOTLOC_BUG
 	{ CFI_MFR_AMD, CFI_ID_ANY, fixup_amd_bootblock },
+	{ CFI_MFR_AMIC, CFI_ID_ANY, fixup_amd_bootblock },
 	{ CFI_MFR_MACRONIX, CFI_ID_ANY, fixup_amd_bootblock },
 #endif
 	{ CFI_MFR_AMD, 0x0050, fixup_use_secsi },
@@ -440,7 +441,7 @@
 	mtd->flags   = MTD_CAP_NORFLASH;
 	mtd->name    = map->name;
 	mtd->writesize = 1;
-	mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+	mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 
 	DEBUG(MTD_DEBUG_LEVEL3, "MTD %s(): write buffer size %d\n",
 		__func__, mtd->writebufsize);
@@ -610,8 +611,8 @@
  *
  * Note that anything more complicated than checking if no bits are toggling
  * (including checking DQ5 for an error status) is tricky to get working
- * correctly and is therefore not done	(particulary with interleaved chips
- * as each chip must be checked independantly of the others).
+ * correctly and is therefore not done	(particularly with interleaved chips
+ * as each chip must be checked independently of the others).
  */
 static int __xipram chip_ready(struct map_info *map, unsigned long addr)
 {
@@ -634,8 +635,8 @@
  *
  * Note that anything more complicated than checking if no bits are toggling
  * (including checking DQ5 for an error status) is tricky to get working
- * correctly and is therefore not done	(particulary with interleaved chips
- * as each chip must be checked independantly of the others).
+ * correctly and is therefore not done	(particularly with interleaved chips
+ * as each chip must be checked independently of the others).
  *
  */
 static int __xipram chip_good(struct map_info *map, unsigned long addr, map_word expected)
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_cmdset_0020.c linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_cmdset_0020.c
--- linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_cmdset_0020.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_cmdset_0020.c	2011-05-19 00:06:34.000000000 -0400
@@ -238,7 +238,7 @@
 	mtd->resume = cfi_staa_resume;
 	mtd->flags = MTD_CAP_NORFLASH & ~MTD_BIT_WRITEABLE;
 	mtd->writesize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
-	mtd->writebufsize = 1 << cfi->cfiq->MaxBufWriteSize;
+	mtd->writebufsize = cfi_interleave(cfi) << cfi->cfiq->MaxBufWriteSize;
 	map->fldrv = &cfi_staa_chipdrv;
 	__module_get(THIS_MODULE);
 	mtd->name = map->name;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_util.c linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_util.c
--- linux-libre-2.6.38-gnu/drivers/mtd/chips/cfi_util.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/chips/cfi_util.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /*
  * Common Flash Interface support:
- *   Generic utility functions not dependant on command set
+ *   Generic utility functions not dependent on command set
  *
  * Copyright (C) 2002 Red Hat
  * Copyright (C) 2003 STMicroelectronics Limited
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/chips/jedec_probe.c linux-libre-2.6.39-gnu/drivers/mtd/chips/jedec_probe.c
--- linux-libre-2.6.38-gnu/drivers/mtd/chips/jedec_probe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/chips/jedec_probe.c	2011-05-19 00:06:34.000000000 -0400
@@ -2075,7 +2075,7 @@
 	}
 
 	/*
-	 * Make sure the ID's dissappear when the device is taken out of
+	 * Make sure the ID's disappear when the device is taken out of
 	 * ID mode.  The only time this should fail when it should succeed
 	 * is when the ID's are written as data to the same
 	 * addresses.  For this rare and unfortunate case the chip
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/chips/Kconfig linux-libre-2.6.39-gnu/drivers/mtd/chips/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mtd/chips/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/chips/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 	help
 	  This option enables JEDEC-style probing of flash chips which are not
 	  compatible with the Common Flash Interface, but will use the common
-	  CFI-targetted flash drivers for any chips which are identified which
+	  CFI-targeted flash drivers for any chips which are identified which
 	  are in fact compatible in all but the probe method. This actually
 	  covers most AMD/Fujitsu-compatible chips and also non-CFI
 	  Intel chips.
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/block2mtd.c linux-libre-2.6.39-gnu/drivers/mtd/devices/block2mtd.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/block2mtd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/block2mtd.c	2011-05-19 00:06:34.000000000 -0400
@@ -295,7 +295,7 @@
 	dev->mtd.owner = THIS_MODULE;
 
 	if (add_mtd_device(&dev->mtd)) {
-		/* Device didnt get added, so free the entry */
+		/* Device didn't get added, so free the entry */
 		goto devinit_err;
 	}
 	list_add(&dev->list, &blkmtd_device_list);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/doc2001plus.c linux-libre-2.6.39-gnu/drivers/mtd/devices/doc2001plus.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/doc2001plus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/doc2001plus.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,7 +90,7 @@
 	return ret;
 }
 
-/* For some reason the Millennium Plus seems to occassionally put itself
+/* For some reason the Millennium Plus seems to occasionally put itself
  * into reset mode. For me this happens randomly, with no pattern that I
  * can detect. M-systems suggest always check this on any block level
  * operation and setting to normal mode if in reset mode.
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/docecc.c linux-libre-2.6.39-gnu/drivers/mtd/devices/docecc.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/docecc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/docecc.c	2011-05-19 00:06:34.000000000 -0400
@@ -109,7 +109,7 @@
    of the integer "alpha_to[i]" with a(0) being the LSB and a(m-1) the MSB. Thus for
    example the polynomial representation of @^5 would be given by the binary
    representation of the integer "alpha_to[5]".
-                   Similarily, index_of[] can be used as follows:
+                   Similarly, index_of[] can be used as follows:
         As above, let @ represent the primitive element of GF(2^m) that is
    the root of the primitive polynomial p(x). In order to find the power
    of @ (alpha) that has the polynomial representation
@@ -121,7 +121,7 @@
    NOTE:
         The element alpha_to[2^m-1] = 0 always signifying that the
    representation of "@^infinity" = 0 is (0,0,0,...,0).
-        Similarily, the element index_of[0] = A0 always signifying
+        Similarly, the element index_of[0] = A0 always signifying
    that the power of alpha which has the polynomial representation
    (0,0,...,0) is "infinity".
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/lart.c linux-libre-2.6.39-gnu/drivers/mtd/devices/lart.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/lart.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/lart.c	2011-05-19 00:06:34.000000000 -0400
@@ -353,7 +353,7 @@
    /* put the flash back into command mode */
    write32 (DATA_TO_FLASH (READ_ARRAY),offset);
 
-   /* was the erase successfull? */
+   /* was the erase successful? */
    if ((status & STATUS_ERASE_ERR))
 	 {
 		printk (KERN_WARNING "%s: erase error at address 0x%.8x.\n",module_name,offset);
@@ -508,7 +508,7 @@
    /* put the flash back into command mode */
    write32 (DATA_TO_FLASH (READ_ARRAY),offset);
 
-   /* was the write successfull? */
+   /* was the write successful? */
    if ((status & STATUS_PGM_ERR) || read32 (offset) != x)
 	 {
 		printk (KERN_WARNING "%s: write error at address 0x%.8x.\n",module_name,offset);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/m25p80.c linux-libre-2.6.39-gnu/drivers/mtd/devices/m25p80.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/m25p80.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/m25p80.c	2011-05-19 00:06:34.000000000 -0400
@@ -655,7 +655,8 @@
 	{ "at26df161a", INFO(0x1f4601, 0, 64 * 1024, 32, SECT_4K) },
 	{ "at26df321",  INFO(0x1f4700, 0, 64 * 1024, 64, SECT_4K) },
 
-	/* EON -- en25pxx */
+	/* EON -- en25xxx */
+	{ "en25f32", INFO(0x1c3116, 0, 64 * 1024,  64, SECT_4K) },
 	{ "en25p32", INFO(0x1c2016, 0, 64 * 1024,  64, 0) },
 	{ "en25p64", INFO(0x1c2017, 0, 64 * 1024, 128, 0) },
 
@@ -728,6 +729,8 @@
 	{ "m25pe80", INFO(0x208014,  0, 64 * 1024, 16,       0) },
 	{ "m25pe16", INFO(0x208015,  0, 64 * 1024, 32, SECT_4K) },
 
+	{ "m25px64", INFO(0x207117,  0, 64 * 1024, 128, 0) },
+
 	/* Winbond -- w25x "blocks" are 64K, "sectors" are 4KiB */
 	{ "w25x10", INFO(0xef3011, 0, 64 * 1024,  2,  SECT_4K) },
 	{ "w25x20", INFO(0xef3012, 0, 64 * 1024,  4,  SECT_4K) },
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/mtdram.c linux-libre-2.6.39-gnu/drivers/mtd/devices/mtdram.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/mtdram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/mtdram.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,6 +121,7 @@
 	mtd->flags = MTD_CAP_RAM;
 	mtd->size = size;
 	mtd->writesize = 1;
+	mtd->writebufsize = 64; /* Mimic CFI NOR flashes */
 	mtd->erasesize = MTDRAM_ERASE_SIZE;
 	mtd->priv = mapped_address;
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/phram.c linux-libre-2.6.39-gnu/drivers/mtd/devices/phram.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/phram.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/phram.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,6 +117,7 @@
 	list_for_each_entry_safe(this, safe, &phram_list, list) {
 		del_mtd_device(&this->mtd);
 		iounmap(this->mtd.priv);
+		kfree(this->mtd.name);
 		kfree(this);
 	}
 }
@@ -275,6 +276,8 @@
 	ret = register_device(name, start, len);
 	if (!ret)
 		pr_info("%s device: %#x at %#x\n", name, len, start);
+	else
+		kfree(name);
 
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/devices/pmc551.c linux-libre-2.6.39-gnu/drivers/mtd/devices/pmc551.c
--- linux-libre-2.6.38-gnu/drivers/mtd/devices/pmc551.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/devices/pmc551.c	2011-05-19 00:06:34.000000000 -0400
@@ -351,7 +351,7 @@
  * Fixup routines for the V370PDC
  * PCI device ID 0x020011b0
  *
- * This function basicly kick starts the DRAM oboard the card and gets it
+ * This function basically kick starts the DRAM oboard the card and gets it
  * ready to be used.  Before this is done the device reads VERY erratic, so
  * much that it can crash the Linux 2.2.x series kernels when a user cat's
  * /proc/pci .. though that is mainly a kernel bug in handling the PCI DEVSEL
@@ -540,7 +540,7 @@
 
 	/*
 	 * Check to make certain the DEVSEL is set correctly, this device
-	 * has a tendancy to assert DEVSEL and TRDY when a write is performed
+	 * has a tendency to assert DEVSEL and TRDY when a write is performed
 	 * to the memory when memory is read-only
 	 */
 	if ((cmd & PCI_STATUS_DEVSEL_MASK) != 0x0) {
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/Kconfig linux-libre-2.6.39-gnu/drivers/mtd/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mtd/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -33,14 +33,6 @@
 	  should normally be compiled as kernel modules. The modules perform
 	  various checks and verifications when loaded.
 
-config MTD_CONCAT
-	tristate "MTD concatenating support"
-	help
-	  Support for concatenating several MTD devices into a single
-	  (virtual) one. This allows you to have -for example- a JFFS(2)
-	  file system spanning multiple physical flash chips. If unsure,
-	  say 'Y'.
-
 config MTD_PARTITIONS
 	bool "MTD partitioning support"
 	help
@@ -333,6 +325,16 @@
 	  To use, add console=ttyMTDx to the kernel command line,
 	  where x is the MTD device number to use.
 
+config MTD_SWAP
+	tristate "Swap on MTD device support"
+	depends on MTD && SWAP
+	select MTD_BLKDEVS
+	help
+	  Provides volatile block device driver on top of mtd partition
+          suitable for swapping.  The mapping of written blocks is not saved.
+	  The driver provides wear leveling by storing erase counter into the
+	  OOB.
+
 source "drivers/mtd/chips/Kconfig"
 
 source "drivers/mtd/maps/Kconfig"
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/lpddr/lpddr_cmds.c linux-libre-2.6.39-gnu/drivers/mtd/lpddr/lpddr_cmds.c
--- linux-libre-2.6.38-gnu/drivers/mtd/lpddr/lpddr_cmds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/lpddr/lpddr_cmds.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  * erase, lock/unlock support for LPDDR flash memories
  * (C) 2008 Korolev Alexey <akorolev@infradead.org>
  * (C) 2008 Vasiliy Leonenko <vasiliy.leonenko@gmail.com>
- * Many thanks to Roman Borisov for intial enabling
+ * Many thanks to Roman Borisov for initial enabling
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -171,7 +171,7 @@
 			mutex_lock(&chip->mutex);
 		}
 		if (chip->erase_suspended || chip->write_suspended)  {
-			/* Suspend has occured while sleep: reset timeout */
+			/* Suspend has occurred while sleep: reset timeout */
 			timeo = reset_timeo;
 			chip->erase_suspended = chip->write_suspended = 0;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/Makefile linux-libre-2.6.39-gnu/drivers/mtd/Makefile
--- linux-libre-2.6.38-gnu/drivers/mtd/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,11 +4,10 @@
 
 # Core functionality.
 obj-$(CONFIG_MTD)		+= mtd.o
-mtd-y				:= mtdcore.o mtdsuper.o
+mtd-y				:= mtdcore.o mtdsuper.o mtdconcat.o
 mtd-$(CONFIG_MTD_PARTITIONS)	+= mtdpart.o
 mtd-$(CONFIG_MTD_OF_PARTS)	+= ofpart.o
 
-obj-$(CONFIG_MTD_CONCAT)	+= mtdconcat.o
 obj-$(CONFIG_MTD_REDBOOT_PARTS) += redboot.o
 obj-$(CONFIG_MTD_CMDLINE_PARTS) += cmdlinepart.o
 obj-$(CONFIG_MTD_AFS_PARTS)	+= afs.o
@@ -26,6 +25,7 @@
 obj-$(CONFIG_SSFDC)		+= ssfdc.o
 obj-$(CONFIG_SM_FTL)		+= sm_ftl.o
 obj-$(CONFIG_MTD_OOPS)		+= mtdoops.o
+obj-$(CONFIG_MTD_SWAP)		+= mtdswap.o
 
 nftl-objs		:= nftlcore.o nftlmount.o
 inftl-objs		:= inftlcore.o inftlmount.o
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/ceiva.c linux-libre-2.6.39-gnu/drivers/mtd/maps/ceiva.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/ceiva.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/ceiva.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,7 @@
  *
  * Please note:
  *  1. The flash size given should be the largest flash size that can
- *     be accomodated.
+ *     be accommodated.
  *
  *  2. The bus width must defined in clps_setup_flash.
  *
@@ -58,7 +58,7 @@
 #define BOOT_PARTITION_SIZE_KiB       (16)
 #define PARAMS_PARTITION_SIZE_KiB     (8)
 #define KERNEL_PARTITION_SIZE_KiB     (4*128)
-/* Use both remaing portion of first flash, and all of second flash */
+/* Use both remaining portion of first flash, and all of second flash */
 #define ROOT_PARTITION_SIZE_KiB       (3*128) + (8*128)
 
 static struct mtd_partition ceiva_partitions[] = {
@@ -194,16 +194,10 @@
 			 * We detected multiple devices.  Concatenate
 			 * them together.
 			 */
-#ifdef CONFIG_MTD_CONCAT
 			*rmtd = mtd_concat_create(subdev, found,
 						  "clps flash");
 			if (*rmtd == NULL)
 				ret = -ENXIO;
-#else
-			printk(KERN_ERR "clps flash: multiple devices "
-			       "found but MTD concat support disabled.\n");
-			ret = -ENXIO;
-#endif
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/cfi_flagadm.c linux-libre-2.6.39-gnu/drivers/mtd/maps/cfi_flagadm.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/cfi_flagadm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/cfi_flagadm.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 
 
 /* We split the flash chip up into four parts.
- * 1: bootloader firts 128k			(0x00000000 - 0x0001FFFF) size 0x020000
+ * 1: bootloader first 128k			(0x00000000 - 0x0001FFFF) size 0x020000
  * 2: kernel 640k					(0x00020000 - 0x000BFFFF) size 0x0A0000
  * 3: compressed 1536k root ramdisk	(0x000C0000 - 0x0023FFFF) size 0x180000
  * 4: writeable diskpartition (jffs)(0x00240000 - 0x003FFFFF) size 0x1C0000
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/integrator-flash.c linux-libre-2.6.39-gnu/drivers/mtd/maps/integrator-flash.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/integrator-flash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/integrator-flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,7 +202,6 @@
 	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];
 
 		/*
@@ -215,11 +214,6 @@
 					      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)
@@ -244,10 +238,8 @@
  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:
@@ -272,10 +264,8 @@
 	if (info) {
 		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);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/Kconfig linux-libre-2.6.39-gnu/drivers/mtd/maps/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -114,7 +114,7 @@
 
 config MTD_SC520CDP
 	tristate "CFI Flash device mapped on AMD SC520 CDP"
-	depends on X86 && MTD_CFI && MTD_CONCAT
+	depends on X86 && MTD_CFI
 	help
 	  The SC520 CDP board has two banks of CFI-compliant chips and one
 	  Dual-in-line JEDEC chip. This 'mapping' driver supports that
@@ -262,7 +262,7 @@
 
 config MTD_DILNETPC
 	tristate "CFI Flash device mapped on DIL/Net PC"
-	depends on X86 && MTD_CONCAT && MTD_PARTITIONS && MTD_CFI_INTELEXT && BROKEN
+	depends on X86 && 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>
@@ -552,4 +552,13 @@
 
 	  When built as a module, it will be called pismo.ko
 
+config MTD_LATCH_ADDR
+        tristate "Latch-assisted Flash Chip Support"
+        depends on MTD_COMPLEX_MAPPINGS
+        help
+          Map driver which allows flashes to be partially physically addressed
+          and have the upper address lines set by a board specific code.
+
+          If compiled as a module, it will be called latch-addr-flash.
+
 endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/latch-addr-flash.c linux-libre-2.6.39-gnu/drivers/mtd/maps/latch-addr-flash.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/latch-addr-flash.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/latch-addr-flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,272 @@
+/*
+ * Interface for NOR flash driver whose high address lines are latched
+ *
+ * Copyright Â© 2000 Nicolas Pitre <nico@cam.org>
+ * Copyright Â© 2005-2008 Analog Devices Inc.
+ * Copyright Â© 2008 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/kernel.h>
+#include <linux/module.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/map.h>
+#include <linux/mtd/partitions.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/latch-addr-flash.h>
+#include <linux/slab.h>
+
+#define DRIVER_NAME "latch-addr-flash"
+
+struct latch_addr_flash_info {
+	struct mtd_info		*mtd;
+	struct map_info		map;
+	struct resource		*res;
+
+	void			(*set_window)(unsigned long offset, void *data);
+	void			*data;
+
+	/* cache; could be found out of res */
+	unsigned long		win_mask;
+
+	int			nr_parts;
+	struct mtd_partition	*parts;
+
+	spinlock_t		lock;
+};
+
+static map_word lf_read(struct map_info *map, unsigned long ofs)
+{
+	struct latch_addr_flash_info *info;
+	map_word datum;
+
+	info = (struct latch_addr_flash_info *)map->map_priv_1;
+
+	spin_lock(&info->lock);
+
+	info->set_window(ofs, info->data);
+	datum = inline_map_read(map, info->win_mask & ofs);
+
+	spin_unlock(&info->lock);
+
+	return datum;
+}
+
+static void lf_write(struct map_info *map, map_word datum, unsigned long ofs)
+{
+	struct latch_addr_flash_info *info;
+
+	info = (struct latch_addr_flash_info *)map->map_priv_1;
+
+	spin_lock(&info->lock);
+
+	info->set_window(ofs, info->data);
+	inline_map_write(map, datum, info->win_mask & ofs);
+
+	spin_unlock(&info->lock);
+}
+
+static void lf_copy_from(struct map_info *map, void *to,
+		unsigned long from, ssize_t len)
+{
+	struct latch_addr_flash_info *info =
+		(struct latch_addr_flash_info *) map->map_priv_1;
+	unsigned n;
+
+	while (len > 0) {
+		n = info->win_mask + 1 - (from & info->win_mask);
+		if (n > len)
+			n = len;
+
+		spin_lock(&info->lock);
+
+		info->set_window(from, info->data);
+		memcpy_fromio(to, map->virt + (from & info->win_mask), n);
+
+		spin_unlock(&info->lock);
+
+		to += n;
+		from += n;
+		len -= n;
+	}
+}
+
+static char *rom_probe_types[] = { "cfi_probe", NULL };
+
+static char *part_probe_types[] = { "cmdlinepart", NULL };
+
+static int latch_addr_flash_remove(struct platform_device *dev)
+{
+	struct latch_addr_flash_info *info;
+	struct latch_addr_flash_data *latch_addr_data;
+
+	info = platform_get_drvdata(dev);
+	if (info == NULL)
+		return 0;
+	platform_set_drvdata(dev, NULL);
+
+	latch_addr_data = dev->dev.platform_data;
+
+	if (info->mtd != NULL) {
+		if (mtd_has_partitions()) {
+			if (info->nr_parts) {
+				del_mtd_partitions(info->mtd);
+				kfree(info->parts);
+			} else if (latch_addr_data->nr_parts) {
+				del_mtd_partitions(info->mtd);
+			} else {
+				del_mtd_device(info->mtd);
+			}
+		} else {
+			del_mtd_device(info->mtd);
+		}
+		map_destroy(info->mtd);
+	}
+
+	if (info->map.virt != NULL)
+		iounmap(info->map.virt);
+
+	if (info->res != NULL)
+		release_mem_region(info->res->start, resource_size(info->res));
+
+	kfree(info);
+
+	if (latch_addr_data->done)
+		latch_addr_data->done(latch_addr_data->data);
+
+	return 0;
+}
+
+static int __devinit latch_addr_flash_probe(struct platform_device *dev)
+{
+	struct latch_addr_flash_data *latch_addr_data;
+	struct latch_addr_flash_info *info;
+	resource_size_t win_base = dev->resource->start;
+	resource_size_t win_size = resource_size(dev->resource);
+	char **probe_type;
+	int chipsel;
+	int err;
+
+	latch_addr_data = dev->dev.platform_data;
+	if (latch_addr_data == NULL)
+		return -ENODEV;
+
+	pr_notice("latch-addr platform flash device: %#llx byte "
+		  "window at %#.8llx\n",
+		  (unsigned long long)win_size, (unsigned long long)win_base);
+
+	chipsel = dev->id;
+
+	if (latch_addr_data->init) {
+		err = latch_addr_data->init(latch_addr_data->data, chipsel);
+		if (err != 0)
+			return err;
+	}
+
+	info = kzalloc(sizeof(struct latch_addr_flash_info), GFP_KERNEL);
+	if (info == NULL) {
+		err = -ENOMEM;
+		goto done;
+	}
+
+	platform_set_drvdata(dev, info);
+
+	info->res = request_mem_region(win_base, win_size, DRIVER_NAME);
+	if (info->res == NULL) {
+		dev_err(&dev->dev, "Could not reserve memory region\n");
+		err = -EBUSY;
+		goto free_info;
+	}
+
+	info->map.name		= DRIVER_NAME;
+	info->map.size		= latch_addr_data->size;
+	info->map.bankwidth	= latch_addr_data->width;
+
+	info->map.phys		= NO_XIP;
+	info->map.virt		= ioremap(win_base, win_size);
+	if (!info->map.virt) {
+		err = -ENOMEM;
+		goto free_res;
+	}
+
+	info->map.map_priv_1	= (unsigned long)info;
+
+	info->map.read		= lf_read;
+	info->map.copy_from	= lf_copy_from;
+	info->map.write		= lf_write;
+	info->set_window	= latch_addr_data->set_window;
+	info->data		= latch_addr_data->data;
+	info->win_mask		= win_size - 1;
+
+	spin_lock_init(&info->lock);
+
+	for (probe_type = rom_probe_types; !info->mtd && *probe_type;
+		probe_type++)
+		info->mtd = do_map_probe(*probe_type, &info->map);
+
+	if (info->mtd == NULL) {
+		dev_err(&dev->dev, "map_probe failed\n");
+		err = -ENODEV;
+		goto iounmap;
+	}
+	info->mtd->owner = THIS_MODULE;
+
+	if (mtd_has_partitions()) {
+
+		err = parse_mtd_partitions(info->mtd,
+					   (const char **)part_probe_types,
+					   &info->parts, 0);
+		if (err > 0) {
+			add_mtd_partitions(info->mtd, info->parts, err);
+			return 0;
+		}
+		if (latch_addr_data->nr_parts) {
+			pr_notice("Using latch-addr-flash partition information\n");
+			add_mtd_partitions(info->mtd, latch_addr_data->parts,
+					latch_addr_data->nr_parts);
+			return 0;
+		}
+	}
+	add_mtd_device(info->mtd);
+	return 0;
+
+iounmap:
+	iounmap(info->map.virt);
+free_res:
+	release_mem_region(info->res->start, resource_size(info->res));
+free_info:
+	kfree(info);
+done:
+	if (latch_addr_data->done)
+		latch_addr_data->done(latch_addr_data->data);
+	return err;
+}
+
+static struct platform_driver latch_addr_flash_driver = {
+	.probe		= latch_addr_flash_probe,
+	.remove		= __devexit_p(latch_addr_flash_remove),
+	.driver		= {
+		.name	= DRIVER_NAME,
+	},
+};
+
+static int __init latch_addr_flash_init(void)
+{
+	return platform_driver_register(&latch_addr_flash_driver);
+}
+module_init(latch_addr_flash_init);
+
+static void __exit latch_addr_flash_exit(void)
+{
+	platform_driver_unregister(&latch_addr_flash_driver);
+}
+module_exit(latch_addr_flash_exit);
+
+MODULE_AUTHOR("David Griego <dgriego@mvista.com>");
+MODULE_DESCRIPTION("MTD map driver for flashes addressed physically with upper "
+		"address lines being set board specifically");
+MODULE_LICENSE("GPL v2");
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/Makefile linux-libre-2.6.39-gnu/drivers/mtd/maps/Makefile
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -59,3 +59,4 @@
 obj-$(CONFIG_MTD_VMU)		+= vmu-flash.o
 obj-$(CONFIG_MTD_GPIO_ADDR)	+= gpio-addr-flash.o
 obj-$(CONFIG_MTD_BCM963XX)	+= bcm963xx-flash.o
+obj-$(CONFIG_MTD_LATCH_ADDR)	+= latch-addr-flash.o
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/pcmciamtd.c linux-libre-2.6.39-gnu/drivers/mtd/maps/pcmciamtd.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/pcmciamtd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/pcmciamtd.c	2011-05-19 00:06:34.000000000 -0400
@@ -497,7 +497,7 @@
 		dev->pcmcia_map.set_vpp = pcmciamtd_set_vpp;
 
 	/* Request a memory window for PCMCIA. Some architeures can map windows
-	 * upto the maximum that PCMCIA can support (64MiB) - this is ideal and
+	 * up to the maximum that PCMCIA can support (64MiB) - this is ideal and
 	 * we aim for a window the size of the whole card - otherwise we try
 	 * smaller windows until we succeed
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/physmap.c linux-libre-2.6.39-gnu/drivers/mtd/maps/physmap.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/physmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/physmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,10 +59,8 @@
 #else
 		del_mtd_device(info->cmtd);
 #endif
-#ifdef CONFIG_MTD_CONCAT
 		if (info->cmtd != info->mtd[0])
 			mtd_concat_destroy(info->cmtd);
-#endif
 	}
 
 	for (i = 0; i < MAX_RESOURCES; i++) {
@@ -159,15 +157,9 @@
 		/*
 		 * We detected multiple devices. Concatenate them together.
 		 */
-#ifdef CONFIG_MTD_CONCAT
 		info->cmtd = mtd_concat_create(info->mtd, devices_found, dev_name(&dev->dev));
 		if (info->cmtd == NULL)
 			err = -ENXIO;
-#else
-		printk(KERN_ERR "physmap-flash: multiple devices "
-		       "found but MTD concat support disabled.\n");
-		err = -ENXIO;
-#endif
 	}
 	if (err)
 		goto err_out;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/physmap_of.c linux-libre-2.6.39-gnu/drivers/mtd/maps/physmap_of.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/physmap_of.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/physmap_of.c	2011-05-19 00:06:34.000000000 -0400
@@ -104,12 +104,10 @@
 		return 0;
 	dev_set_drvdata(&dev->dev, NULL);
 
-#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)) {
@@ -216,16 +214,17 @@
 }
 #endif
 
-static int __devinit of_flash_probe(struct platform_device *dev,
-				    const struct of_device_id *match)
+static struct of_device_id of_flash_match[];
+static int __devinit of_flash_probe(struct platform_device *dev)
 {
 #ifdef CONFIG_MTD_PARTITIONS
 	const char **part_probe_types;
 #endif
+	const struct of_device_id *match;
 	struct device_node *dp = dev->dev.of_node;
 	struct resource res;
 	struct of_flash *info;
-	const char *probe_type = match->data;
+	const char *probe_type;
 	const __be32 *width;
 	int err;
 	int i;
@@ -235,6 +234,11 @@
 	struct mtd_info **mtd_list = NULL;
 	resource_size_t res_size;
 
+	match = of_match_device(of_flash_match, &dev->dev);
+	if (!match)
+		return -EINVAL;
+	probe_type = match->data;
+
 	reg_tuple_size = (of_n_addr_cells(dp) + of_n_size_cells(dp)) * sizeof(u32);
 
 	/*
@@ -334,16 +338,10 @@
 		/*
 		 * 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;
@@ -418,7 +416,7 @@
 };
 MODULE_DEVICE_TABLE(of, of_flash_match);
 
-static struct of_platform_driver of_flash_driver = {
+static struct platform_driver of_flash_driver = {
 	.driver = {
 		.name = "of-flash",
 		.owner = THIS_MODULE,
@@ -430,12 +428,12 @@
 
 static int __init of_flash_init(void)
 {
-	return of_register_platform_driver(&of_flash_driver);
+	return platform_driver_register(&of_flash_driver);
 }
 
 static void __exit of_flash_exit(void)
 {
-	of_unregister_platform_driver(&of_flash_driver);
+	platform_driver_unregister(&of_flash_driver);
 }
 
 module_init(of_flash_init);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/pmcmsp-flash.c linux-libre-2.6.39-gnu/drivers/mtd/maps/pmcmsp-flash.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/pmcmsp-flash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/pmcmsp-flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  * Config with both CFI and JEDEC device support.
  *
  * Basically physmap.c with the addition of partitions and
- * an array of mapping info to accomodate more than one flash type per board.
+ * an array of mapping info to accommodate more than one flash type per board.
  *
  * Copyright 2005-2007 PMC-Sierra, Inc.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/sa1100-flash.c linux-libre-2.6.39-gnu/drivers/mtd/maps/sa1100-flash.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/sa1100-flash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/sa1100-flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -232,10 +232,8 @@
 		else
 			del_mtd_partitions(info->mtd);
 #endif
-#ifdef CONFIG_MTD_CONCAT
 		if (info->mtd != info->subdev[0].mtd)
 			mtd_concat_destroy(info->mtd);
-#endif
 	}
 
 	kfree(info->parts);
@@ -321,7 +319,6 @@
 		info->mtd = info->subdev[0].mtd;
 		ret = 0;
 	} else if (info->num_subdev > 1) {
-#ifdef CONFIG_MTD_CONCAT
 		struct mtd_info *cdev[nr];
 		/*
 		 * We detected multiple devices.  Concatenate them together.
@@ -333,11 +330,6 @@
 					      plat->name);
 		if (info->mtd == NULL)
 			ret = -ENXIO;
-#else
-		printk(KERN_ERR "SA1100 flash: multiple devices "
-		       "found but MTD concat support disabled.\n");
-		ret = -ENXIO;
-#endif
 	}
 
 	if (ret == 0)
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/sc520cdp.c linux-libre-2.6.39-gnu/drivers/mtd/maps/sc520cdp.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/sc520cdp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/sc520cdp.c	2011-05-19 00:06:34.000000000 -0400
@@ -197,7 +197,7 @@
 	}
 
 	/*
-	** Find the PARxx registers that are reponsible for activating
+	** Find the PARxx registers that are responsible for activating
 	** ROMCS0, ROMCS1 and BOOTCS. Reprogram each of these with a
 	** new value from the table.
 	*/
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/sun_uflash.c linux-libre-2.6.39-gnu/drivers/mtd/maps/sun_uflash.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/sun_uflash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/sun_uflash.c	2011-05-19 00:06:34.000000000 -0400
@@ -108,7 +108,7 @@
 	return 0;
 }
 
-static int __devinit uflash_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit uflash_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 
@@ -148,7 +148,7 @@
 
 MODULE_DEVICE_TABLE(of, uflash_match);
 
-static struct of_platform_driver uflash_driver = {
+static struct platform_driver uflash_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -160,12 +160,12 @@
 
 static int __init uflash_init(void)
 {
-	return of_register_platform_driver(&uflash_driver);
+	return platform_driver_register(&uflash_driver);
 }
 
 static void __exit uflash_exit(void)
 {
-	of_unregister_platform_driver(&uflash_driver);
+	platform_driver_unregister(&uflash_driver);
 }
 
 module_init(uflash_init);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/tqm8xxl.c linux-libre-2.6.39-gnu/drivers/mtd/maps/tqm8xxl.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/tqm8xxl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/tqm8xxl.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,7 @@
  */
 
 #ifdef CONFIG_MTD_PARTITIONS
-/* Currently, TQM8xxL has upto 8MiB flash */
+/* Currently, TQM8xxL has up to 8MiB flash */
 static unsigned long tqm8xxl_max_flash_size = 0x00800000;
 
 /* partition definition for first flash bank
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/maps/ts5500_flash.c linux-libre-2.6.39-gnu/drivers/mtd/maps/ts5500_flash.c
--- linux-libre-2.6.38-gnu/drivers/mtd/maps/ts5500_flash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/maps/ts5500_flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,6 @@
 	return 0;
 
 err1:
-	map_destroy(mymtd);
 	iounmap(ts5500_map.virt);
 err2:
 	return rc;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtd_blkdevs.c linux-libre-2.6.39-gnu/drivers/mtd/mtd_blkdevs.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtd_blkdevs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/mtd_blkdevs.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 static LIST_HEAD(blktrans_majors);
 static DEFINE_MUTEX(blktrans_ref_mutex);
 
-void blktrans_dev_release(struct kref *kref)
+static void blktrans_dev_release(struct kref *kref)
 {
 	struct mtd_blktrans_dev *dev =
 		container_of(kref, struct mtd_blktrans_dev, ref);
@@ -67,7 +67,7 @@
 	return dev;
 }
 
-void blktrans_dev_put(struct mtd_blktrans_dev *dev)
+static void blktrans_dev_put(struct mtd_blktrans_dev *dev)
 {
 	mutex_lock(&blktrans_ref_mutex);
 	kref_put(&dev->ref, blktrans_dev_release);
@@ -119,18 +119,43 @@
 	}
 }
 
+int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev)
+{
+	if (kthread_should_stop())
+		return 1;
+
+	return dev->bg_stop;
+}
+EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background);
+
 static int mtd_blktrans_thread(void *arg)
 {
 	struct mtd_blktrans_dev *dev = arg;
+	struct mtd_blktrans_ops *tr = dev->tr;
 	struct request_queue *rq = dev->rq;
 	struct request *req = NULL;
+	int background_done = 0;
 
 	spin_lock_irq(rq->queue_lock);
 
 	while (!kthread_should_stop()) {
 		int res;
 
+		dev->bg_stop = false;
 		if (!req && !(req = blk_fetch_request(rq))) {
+			if (tr->background && !background_done) {
+				spin_unlock_irq(rq->queue_lock);
+				mutex_lock(&dev->lock);
+				tr->background(dev);
+				mutex_unlock(&dev->lock);
+				spin_lock_irq(rq->queue_lock);
+				/*
+				 * Do background processing just once per idle
+				 * period.
+				 */
+				background_done = !dev->bg_stop;
+				continue;
+			}
 			set_current_state(TASK_INTERRUPTIBLE);
 
 			if (kthread_should_stop())
@@ -152,6 +177,8 @@
 
 		if (!__blk_end_request_cur(req, res))
 			req = NULL;
+
+		background_done = 0;
 	}
 
 	if (req)
@@ -172,8 +199,10 @@
 	if (!dev)
 		while ((req = blk_fetch_request(rq)) != NULL)
 			__blk_end_request_all(req, -ENODEV);
-	else
+	else {
+		dev->bg_stop = true;
 		wake_up_process(dev->thread);
+	}
 }
 
 static int blktrans_open(struct block_device *bdev, fmode_t mode)
@@ -379,9 +408,10 @@
 	new->rq->queuedata = new;
 	blk_queue_logical_block_size(new->rq, tr->blksize);
 
-	if (tr->discard)
-		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD,
-					new->rq);
+	if (tr->discard) {
+		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, new->rq);
+		new->rq->limits.max_discard_sectors = UINT_MAX;
+	}
 
 	gd->queue = new->rq;
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtdblock.c linux-libre-2.6.39-gnu/drivers/mtd/mtdblock.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtdblock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/mtdblock.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,7 +129,7 @@
 		return ret;
 
 	/*
-	 * Here we could argubly set the cache state to STATE_CLEAN.
+	 * Here we could arguably set the cache state to STATE_CLEAN.
 	 * However this could lead to inconsistency since we will not
 	 * be notified if this content is altered on the flash by other
 	 * means.  Let's declare it empty and leave buffering tasks to
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtdchar.c linux-libre-2.6.39-gnu/drivers/mtd/mtdchar.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtdchar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/mtdchar.c	2011-05-19 00:06:34.000000000 -0400
@@ -234,7 +234,7 @@
 		 * the data. For our userspace tools it is important
 		 * to dump areas with ecc errors !
 		 * For kernel internal usage it also might return -EUCLEAN
-		 * to signal the caller that a bitflip has occured and has
+		 * to signal the caller that a bitflip has occurred and has
 		 * been corrected by the ECC algorithm.
 		 * Userspace software which accesses NAND this way
 		 * must be aware of the fact that it deals with NAND
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtdconcat.c linux-libre-2.6.39-gnu/drivers/mtd/mtdconcat.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtdconcat.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/mtdconcat.c	2011-05-19 00:06:34.000000000 -0400
@@ -750,6 +750,7 @@
 	struct mtd_concat *concat;
 	uint32_t max_erasesize, curr_erasesize;
 	int num_erase_region;
+	int max_writebufsize = 0;
 
 	printk(KERN_NOTICE "Concatenating MTD devices:\n");
 	for (i = 0; i < num_devs; i++)
@@ -776,7 +777,12 @@
 	concat->mtd.size = subdev[0]->size;
 	concat->mtd.erasesize = subdev[0]->erasesize;
 	concat->mtd.writesize = subdev[0]->writesize;
-	concat->mtd.writebufsize = subdev[0]->writebufsize;
+
+	for (i = 0; i < num_devs; i++)
+		if (max_writebufsize < subdev[i]->writebufsize)
+			max_writebufsize = subdev[i]->writebufsize;
+	concat->mtd.writebufsize = max_writebufsize;
+
 	concat->mtd.subpage_sft = subdev[0]->subpage_sft;
 	concat->mtd.oobsize = subdev[0]->oobsize;
 	concat->mtd.oobavail = subdev[0]->oobavail;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtdcore.c linux-libre-2.6.39-gnu/drivers/mtd/mtdcore.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtdcore.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/mtdcore.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,7 +43,7 @@
  * backing device capabilities for non-mappable devices (such as NAND flash)
  * - permits private mappings, copies are taken of the data
  */
-struct backing_dev_info mtd_bdi_unmappable = {
+static struct backing_dev_info mtd_bdi_unmappable = {
 	.capabilities	= BDI_CAP_MAP_COPY,
 };
 
@@ -52,7 +52,7 @@
  * - permits private mappings, copies are taken of the data
  * - permits non-writable shared mappings
  */
-struct backing_dev_info mtd_bdi_ro_mappable = {
+static struct backing_dev_info mtd_bdi_ro_mappable = {
 	.capabilities	= (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
 			   BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP),
 };
@@ -62,7 +62,7 @@
  * - permits private mappings, copies are taken of the data
  * - permits non-writable shared mappings
  */
-struct backing_dev_info mtd_bdi_rw_mappable = {
+static struct backing_dev_info mtd_bdi_rw_mappable = {
 	.capabilities	= (BDI_CAP_MAP_COPY | BDI_CAP_MAP_DIRECT |
 			   BDI_CAP_EXEC_MAP | BDI_CAP_READ_MAP |
 			   BDI_CAP_WRITE_MAP),
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/mtdswap.c linux-libre-2.6.39-gnu/drivers/mtd/mtdswap.c
--- linux-libre-2.6.38-gnu/drivers/mtd/mtdswap.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mtd/mtdswap.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1587 @@
+/*
+ * Swap block device support for MTDs
+ * Turns an MTD device into a swap device with block wear leveling
+ *
+ * Copyright Â© 2007,2011 Nokia Corporation. All rights reserved.
+ *
+ * Authors: Jarkko Lavinen <jarkko.lavinen@nokia.com>
+ *
+ * Based on Richard Purdie's earlier implementation in 2007. Background
+ * support and lock-less operation written by Adrian Hunter.
+ *
+ * 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/mtd/mtd.h>
+#include <linux/mtd/blktrans.h>
+#include <linux/rbtree.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/vmalloc.h>
+#include <linux/genhd.h>
+#include <linux/swap.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/device.h>
+#include <linux/math64.h>
+
+#define MTDSWAP_PREFIX "mtdswap"
+
+/*
+ * The number of free eraseblocks when GC should stop
+ */
+#define CLEAN_BLOCK_THRESHOLD	20
+
+/*
+ * Number of free eraseblocks below which GC can also collect low frag
+ * blocks.
+ */
+#define LOW_FRAG_GC_TRESHOLD	5
+
+/*
+ * Wear level cost amortization. We want to do wear leveling on the background
+ * without disturbing gc too much. This is made by defining max GC frequency.
+ * Frequency value 6 means 1/6 of the GC passes will pick an erase block based
+ * on the biggest wear difference rather than the biggest dirtiness.
+ *
+ * The lower freq2 should be chosen so that it makes sure the maximum erase
+ * difference will decrease even if a malicious application is deliberately
+ * trying to make erase differences large.
+ */
+#define MAX_ERASE_DIFF		4000
+#define COLLECT_NONDIRTY_BASE	MAX_ERASE_DIFF
+#define COLLECT_NONDIRTY_FREQ1	6
+#define COLLECT_NONDIRTY_FREQ2	4
+
+#define PAGE_UNDEF		UINT_MAX
+#define BLOCK_UNDEF		UINT_MAX
+#define BLOCK_ERROR		(UINT_MAX - 1)
+#define BLOCK_MAX		(UINT_MAX - 2)
+
+#define EBLOCK_BAD		(1 << 0)
+#define EBLOCK_NOMAGIC		(1 << 1)
+#define EBLOCK_BITFLIP		(1 << 2)
+#define EBLOCK_FAILED		(1 << 3)
+#define EBLOCK_READERR		(1 << 4)
+#define EBLOCK_IDX_SHIFT	5
+
+struct swap_eb {
+	struct rb_node rb;
+	struct rb_root *root;
+
+	unsigned int flags;
+	unsigned int active_count;
+	unsigned int erase_count;
+	unsigned int pad;		/* speeds up pointer decremtnt */
+};
+
+#define MTDSWAP_ECNT_MIN(rbroot) (rb_entry(rb_first(rbroot), struct swap_eb, \
+				rb)->erase_count)
+#define MTDSWAP_ECNT_MAX(rbroot) (rb_entry(rb_last(rbroot), struct swap_eb, \
+				rb)->erase_count)
+
+struct mtdswap_tree {
+	struct rb_root root;
+	unsigned int count;
+};
+
+enum {
+	MTDSWAP_CLEAN,
+	MTDSWAP_USED,
+	MTDSWAP_LOWFRAG,
+	MTDSWAP_HIFRAG,
+	MTDSWAP_DIRTY,
+	MTDSWAP_BITFLIP,
+	MTDSWAP_FAILING,
+	MTDSWAP_TREE_CNT,
+};
+
+struct mtdswap_dev {
+	struct mtd_blktrans_dev *mbd_dev;
+	struct mtd_info *mtd;
+	struct device *dev;
+
+	unsigned int *page_data;
+	unsigned int *revmap;
+
+	unsigned int eblks;
+	unsigned int spare_eblks;
+	unsigned int pages_per_eblk;
+	unsigned int max_erase_count;
+	struct swap_eb *eb_data;
+
+	struct mtdswap_tree trees[MTDSWAP_TREE_CNT];
+
+	unsigned long long sect_read_count;
+	unsigned long long sect_write_count;
+	unsigned long long mtd_write_count;
+	unsigned long long mtd_read_count;
+	unsigned long long discard_count;
+	unsigned long long discard_page_count;
+
+	unsigned int curr_write_pos;
+	struct swap_eb *curr_write;
+
+	char *page_buf;
+	char *oob_buf;
+
+	struct dentry *debugfs_root;
+};
+
+struct mtdswap_oobdata {
+	__le16 magic;
+	__le32 count;
+} __attribute__((packed));
+
+#define MTDSWAP_MAGIC_CLEAN	0x2095
+#define MTDSWAP_MAGIC_DIRTY	(MTDSWAP_MAGIC_CLEAN + 1)
+#define MTDSWAP_TYPE_CLEAN	0
+#define MTDSWAP_TYPE_DIRTY	1
+#define MTDSWAP_OOBSIZE		sizeof(struct mtdswap_oobdata)
+
+#define MTDSWAP_ERASE_RETRIES	3 /* Before marking erase block bad */
+#define MTDSWAP_IO_RETRIES	3
+
+enum {
+	MTDSWAP_SCANNED_CLEAN,
+	MTDSWAP_SCANNED_DIRTY,
+	MTDSWAP_SCANNED_BITFLIP,
+	MTDSWAP_SCANNED_BAD,
+};
+
+/*
+ * In the worst case mtdswap_writesect() has allocated the last clean
+ * page from the current block and is then pre-empted by the GC
+ * thread. The thread can consume a full erase block when moving a
+ * block.
+ */
+#define MIN_SPARE_EBLOCKS	2
+#define MIN_ERASE_BLOCKS	(MIN_SPARE_EBLOCKS + 1)
+
+#define TREE_ROOT(d, name) (&d->trees[MTDSWAP_ ## name].root)
+#define TREE_EMPTY(d, name) (TREE_ROOT(d, name)->rb_node == NULL)
+#define TREE_NONEMPTY(d, name) (!TREE_EMPTY(d, name))
+#define TREE_COUNT(d, name) (d->trees[MTDSWAP_ ## name].count)
+
+#define MTDSWAP_MBD_TO_MTDSWAP(dev) ((struct mtdswap_dev *)dev->priv)
+
+static char partitions[128] = "";
+module_param_string(partitions, partitions, sizeof(partitions), 0444);
+MODULE_PARM_DESC(partitions, "MTD partition numbers to use as swap "
+		"partitions=\"1,3,5\"");
+
+static unsigned int spare_eblocks = 10;
+module_param(spare_eblocks, uint, 0444);
+MODULE_PARM_DESC(spare_eblocks, "Percentage of spare erase blocks for "
+		"garbage collection (default 10%)");
+
+static bool header; /* false */
+module_param(header, bool, 0444);
+MODULE_PARM_DESC(header,
+		"Include builtin swap header (default 0, without header)");
+
+static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background);
+
+static loff_t mtdswap_eb_offset(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	return (loff_t)(eb - d->eb_data) * d->mtd->erasesize;
+}
+
+static void mtdswap_eb_detach(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	unsigned int oldidx;
+	struct mtdswap_tree *tp;
+
+	if (eb->root) {
+		tp = container_of(eb->root, struct mtdswap_tree, root);
+		oldidx = tp - &d->trees[0];
+
+		d->trees[oldidx].count--;
+		rb_erase(&eb->rb, eb->root);
+	}
+}
+
+static void __mtdswap_rb_add(struct rb_root *root, struct swap_eb *eb)
+{
+	struct rb_node **p, *parent = NULL;
+	struct swap_eb *cur;
+
+	p = &root->rb_node;
+	while (*p) {
+		parent = *p;
+		cur = rb_entry(parent, struct swap_eb, rb);
+		if (eb->erase_count > cur->erase_count)
+			p = &(*p)->rb_right;
+		else
+			p = &(*p)->rb_left;
+	}
+
+	rb_link_node(&eb->rb, parent, p);
+	rb_insert_color(&eb->rb, root);
+}
+
+static void mtdswap_rb_add(struct mtdswap_dev *d, struct swap_eb *eb, int idx)
+{
+	struct rb_root *root;
+
+	if (eb->root == &d->trees[idx].root)
+		return;
+
+	mtdswap_eb_detach(d, eb);
+	root = &d->trees[idx].root;
+	__mtdswap_rb_add(root, eb);
+	eb->root = root;
+	d->trees[idx].count++;
+}
+
+static struct rb_node *mtdswap_rb_index(struct rb_root *root, unsigned int idx)
+{
+	struct rb_node *p;
+	unsigned int i;
+
+	p = rb_first(root);
+	i = 0;
+	while (i < idx && p) {
+		p = rb_next(p);
+		i++;
+	}
+
+	return p;
+}
+
+static int mtdswap_handle_badblock(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	int ret;
+	loff_t offset;
+
+	d->spare_eblks--;
+	eb->flags |= EBLOCK_BAD;
+	mtdswap_eb_detach(d, eb);
+	eb->root = NULL;
+
+	/* badblocks not supported */
+	if (!d->mtd->block_markbad)
+		return 1;
+
+	offset = mtdswap_eb_offset(d, eb);
+	dev_warn(d->dev, "Marking bad block at %08llx\n", offset);
+	ret = d->mtd->block_markbad(d->mtd, offset);
+
+	if (ret) {
+		dev_warn(d->dev, "Mark block bad failed for block at %08llx "
+			"error %d\n", offset, ret);
+		return ret;
+	}
+
+	return 1;
+
+}
+
+static int mtdswap_handle_write_error(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	unsigned int marked = eb->flags & EBLOCK_FAILED;
+	struct swap_eb *curr_write = d->curr_write;
+
+	eb->flags |= EBLOCK_FAILED;
+	if (curr_write == eb) {
+		d->curr_write = NULL;
+
+		if (!marked && d->curr_write_pos != 0) {
+			mtdswap_rb_add(d, eb, MTDSWAP_FAILING);
+			return 0;
+		}
+	}
+
+	return mtdswap_handle_badblock(d, eb);
+}
+
+static int mtdswap_read_oob(struct mtdswap_dev *d, loff_t from,
+			struct mtd_oob_ops *ops)
+{
+	int ret = d->mtd->read_oob(d->mtd, from, ops);
+
+	if (ret == -EUCLEAN)
+		return ret;
+
+	if (ret) {
+		dev_warn(d->dev, "Read OOB failed %d for block at %08llx\n",
+			ret, from);
+		return ret;
+	}
+
+	if (ops->oobretlen < ops->ooblen) {
+		dev_warn(d->dev, "Read OOB return short read (%zd bytes not "
+			"%zd) for block at %08llx\n",
+			ops->oobretlen, ops->ooblen, from);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mtdswap_read_markers(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	struct mtdswap_oobdata *data, *data2;
+	int ret;
+	loff_t offset;
+	struct mtd_oob_ops ops;
+
+	offset = mtdswap_eb_offset(d, eb);
+
+	/* Check first if the block is bad. */
+	if (d->mtd->block_isbad && d->mtd->block_isbad(d->mtd, offset))
+		return MTDSWAP_SCANNED_BAD;
+
+	ops.ooblen = 2 * d->mtd->ecclayout->oobavail;
+	ops.oobbuf = d->oob_buf;
+	ops.ooboffs = 0;
+	ops.datbuf = NULL;
+	ops.mode = MTD_OOB_AUTO;
+
+	ret = mtdswap_read_oob(d, offset, &ops);
+
+	if (ret && ret != -EUCLEAN)
+		return ret;
+
+	data = (struct mtdswap_oobdata *)d->oob_buf;
+	data2 = (struct mtdswap_oobdata *)
+		(d->oob_buf + d->mtd->ecclayout->oobavail);
+
+	if (le16_to_cpu(data->magic) == MTDSWAP_MAGIC_CLEAN) {
+		eb->erase_count = le32_to_cpu(data->count);
+		if (ret == -EUCLEAN)
+			ret = MTDSWAP_SCANNED_BITFLIP;
+		else {
+			if (le16_to_cpu(data2->magic) == MTDSWAP_MAGIC_DIRTY)
+				ret = MTDSWAP_SCANNED_DIRTY;
+			else
+				ret = MTDSWAP_SCANNED_CLEAN;
+		}
+	} else {
+		eb->flags |= EBLOCK_NOMAGIC;
+		ret = MTDSWAP_SCANNED_DIRTY;
+	}
+
+	return ret;
+}
+
+static int mtdswap_write_marker(struct mtdswap_dev *d, struct swap_eb *eb,
+				u16 marker)
+{
+	struct mtdswap_oobdata n;
+	int ret;
+	loff_t offset;
+	struct mtd_oob_ops ops;
+
+	ops.ooboffs = 0;
+	ops.oobbuf = (uint8_t *)&n;
+	ops.mode = MTD_OOB_AUTO;
+	ops.datbuf = NULL;
+
+	if (marker == MTDSWAP_TYPE_CLEAN) {
+		n.magic = cpu_to_le16(MTDSWAP_MAGIC_CLEAN);
+		n.count = cpu_to_le32(eb->erase_count);
+		ops.ooblen = MTDSWAP_OOBSIZE;
+		offset = mtdswap_eb_offset(d, eb);
+	} else {
+		n.magic = cpu_to_le16(MTDSWAP_MAGIC_DIRTY);
+		ops.ooblen = sizeof(n.magic);
+		offset = mtdswap_eb_offset(d, eb) + d->mtd->writesize;
+	}
+
+	ret = d->mtd->write_oob(d->mtd, offset , &ops);
+
+	if (ret) {
+		dev_warn(d->dev, "Write OOB failed for block at %08llx "
+			"error %d\n", offset, ret);
+		if (ret == -EIO || ret == -EBADMSG)
+			mtdswap_handle_write_error(d, eb);
+		return ret;
+	}
+
+	if (ops.oobretlen != ops.ooblen) {
+		dev_warn(d->dev, "Short OOB write for block at %08llx: "
+			"%zd not %zd\n",
+			offset, ops.oobretlen, ops.ooblen);
+		return ret;
+	}
+
+	return 0;
+}
+
+/*
+ * Are there any erase blocks without MAGIC_CLEAN header, presumably
+ * because power was cut off after erase but before header write? We
+ * need to guestimate the erase count.
+ */
+static void mtdswap_check_counts(struct mtdswap_dev *d)
+{
+	struct rb_root hist_root = RB_ROOT;
+	struct rb_node *medrb;
+	struct swap_eb *eb;
+	unsigned int i, cnt, median;
+
+	cnt = 0;
+	for (i = 0; i < d->eblks; i++) {
+		eb = d->eb_data + i;
+
+		if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_BAD | EBLOCK_READERR))
+			continue;
+
+		__mtdswap_rb_add(&hist_root, eb);
+		cnt++;
+	}
+
+	if (cnt == 0)
+		return;
+
+	medrb = mtdswap_rb_index(&hist_root, cnt / 2);
+	median = rb_entry(medrb, struct swap_eb, rb)->erase_count;
+
+	d->max_erase_count = MTDSWAP_ECNT_MAX(&hist_root);
+
+	for (i = 0; i < d->eblks; i++) {
+		eb = d->eb_data + i;
+
+		if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_READERR))
+			eb->erase_count = median;
+
+		if (eb->flags & (EBLOCK_NOMAGIC | EBLOCK_BAD | EBLOCK_READERR))
+			continue;
+
+		rb_erase(&eb->rb, &hist_root);
+	}
+}
+
+static void mtdswap_scan_eblks(struct mtdswap_dev *d)
+{
+	int status;
+	unsigned int i, idx;
+	struct swap_eb *eb;
+
+	for (i = 0; i < d->eblks; i++) {
+		eb = d->eb_data + i;
+
+		status = mtdswap_read_markers(d, eb);
+		if (status < 0)
+			eb->flags |= EBLOCK_READERR;
+		else if (status == MTDSWAP_SCANNED_BAD) {
+			eb->flags |= EBLOCK_BAD;
+			continue;
+		}
+
+		switch (status) {
+		case MTDSWAP_SCANNED_CLEAN:
+			idx = MTDSWAP_CLEAN;
+			break;
+		case MTDSWAP_SCANNED_DIRTY:
+		case MTDSWAP_SCANNED_BITFLIP:
+			idx = MTDSWAP_DIRTY;
+			break;
+		default:
+			idx = MTDSWAP_FAILING;
+		}
+
+		eb->flags |= (idx << EBLOCK_IDX_SHIFT);
+	}
+
+	mtdswap_check_counts(d);
+
+	for (i = 0; i < d->eblks; i++) {
+		eb = d->eb_data + i;
+
+		if (eb->flags & EBLOCK_BAD)
+			continue;
+
+		idx = eb->flags >> EBLOCK_IDX_SHIFT;
+		mtdswap_rb_add(d, eb, idx);
+	}
+}
+
+/*
+ * Place eblk into a tree corresponding to its number of active blocks
+ * it contains.
+ */
+static void mtdswap_store_eb(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	unsigned int weight = eb->active_count;
+	unsigned int maxweight = d->pages_per_eblk;
+
+	if (eb == d->curr_write)
+		return;
+
+	if (eb->flags & EBLOCK_BITFLIP)
+		mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP);
+	else if (eb->flags & (EBLOCK_READERR | EBLOCK_FAILED))
+		mtdswap_rb_add(d, eb, MTDSWAP_FAILING);
+	if (weight == maxweight)
+		mtdswap_rb_add(d, eb, MTDSWAP_USED);
+	else if (weight == 0)
+		mtdswap_rb_add(d, eb, MTDSWAP_DIRTY);
+	else if (weight > (maxweight/2))
+		mtdswap_rb_add(d, eb, MTDSWAP_LOWFRAG);
+	else
+		mtdswap_rb_add(d, eb, MTDSWAP_HIFRAG);
+}
+
+
+static void mtdswap_erase_callback(struct erase_info *done)
+{
+	wait_queue_head_t *wait_q = (wait_queue_head_t *)done->priv;
+	wake_up(wait_q);
+}
+
+static int mtdswap_erase_block(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	struct mtd_info *mtd = d->mtd;
+	struct erase_info erase;
+	wait_queue_head_t wq;
+	unsigned int retries = 0;
+	int ret;
+
+	eb->erase_count++;
+	if (eb->erase_count > d->max_erase_count)
+		d->max_erase_count = eb->erase_count;
+
+retry:
+	init_waitqueue_head(&wq);
+	memset(&erase, 0, sizeof(struct erase_info));
+
+	erase.mtd	= mtd;
+	erase.callback	= mtdswap_erase_callback;
+	erase.addr	= mtdswap_eb_offset(d, eb);
+	erase.len	= mtd->erasesize;
+	erase.priv	= (u_long)&wq;
+
+	ret = mtd->erase(mtd, &erase);
+	if (ret) {
+		if (retries++ < MTDSWAP_ERASE_RETRIES) {
+			dev_warn(d->dev,
+				"erase of erase block %#llx on %s failed",
+				erase.addr, mtd->name);
+			yield();
+			goto retry;
+		}
+
+		dev_err(d->dev, "Cannot erase erase block %#llx on %s\n",
+			erase.addr, mtd->name);
+
+		mtdswap_handle_badblock(d, eb);
+		return -EIO;
+	}
+
+	ret = wait_event_interruptible(wq, erase.state == MTD_ERASE_DONE ||
+					   erase.state == MTD_ERASE_FAILED);
+	if (ret) {
+		dev_err(d->dev, "Interrupted erase block %#llx erassure on %s",
+			erase.addr, mtd->name);
+		return -EINTR;
+	}
+
+	if (erase.state == MTD_ERASE_FAILED) {
+		if (retries++ < MTDSWAP_ERASE_RETRIES) {
+			dev_warn(d->dev,
+				"erase of erase block %#llx on %s failed",
+				erase.addr, mtd->name);
+			yield();
+			goto retry;
+		}
+
+		mtdswap_handle_badblock(d, eb);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mtdswap_map_free_block(struct mtdswap_dev *d, unsigned int page,
+				unsigned int *block)
+{
+	int ret;
+	struct swap_eb *old_eb = d->curr_write;
+	struct rb_root *clean_root;
+	struct swap_eb *eb;
+
+	if (old_eb == NULL || d->curr_write_pos >= d->pages_per_eblk) {
+		do {
+			if (TREE_EMPTY(d, CLEAN))
+				return -ENOSPC;
+
+			clean_root = TREE_ROOT(d, CLEAN);
+			eb = rb_entry(rb_first(clean_root), struct swap_eb, rb);
+			rb_erase(&eb->rb, clean_root);
+			eb->root = NULL;
+			TREE_COUNT(d, CLEAN)--;
+
+			ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_DIRTY);
+		} while (ret == -EIO || ret == -EBADMSG);
+
+		if (ret)
+			return ret;
+
+		d->curr_write_pos = 0;
+		d->curr_write = eb;
+		if (old_eb)
+			mtdswap_store_eb(d, old_eb);
+	}
+
+	*block = (d->curr_write - d->eb_data) * d->pages_per_eblk +
+		d->curr_write_pos;
+
+	d->curr_write->active_count++;
+	d->revmap[*block] = page;
+	d->curr_write_pos++;
+
+	return 0;
+}
+
+static unsigned int mtdswap_free_page_cnt(struct mtdswap_dev *d)
+{
+	return TREE_COUNT(d, CLEAN) * d->pages_per_eblk +
+		d->pages_per_eblk - d->curr_write_pos;
+}
+
+static unsigned int mtdswap_enough_free_pages(struct mtdswap_dev *d)
+{
+	return mtdswap_free_page_cnt(d) > d->pages_per_eblk;
+}
+
+static int mtdswap_write_block(struct mtdswap_dev *d, char *buf,
+			unsigned int page, unsigned int *bp, int gc_context)
+{
+	struct mtd_info *mtd = d->mtd;
+	struct swap_eb *eb;
+	size_t retlen;
+	loff_t writepos;
+	int ret;
+
+retry:
+	if (!gc_context)
+		while (!mtdswap_enough_free_pages(d))
+			if (mtdswap_gc(d, 0) > 0)
+				return -ENOSPC;
+
+	ret = mtdswap_map_free_block(d, page, bp);
+	eb = d->eb_data + (*bp / d->pages_per_eblk);
+
+	if (ret == -EIO || ret == -EBADMSG) {
+		d->curr_write = NULL;
+		eb->active_count--;
+		d->revmap[*bp] = PAGE_UNDEF;
+		goto retry;
+	}
+
+	if (ret < 0)
+		return ret;
+
+	writepos = (loff_t)*bp << PAGE_SHIFT;
+	ret =  mtd->write(mtd, writepos, PAGE_SIZE, &retlen, buf);
+	if (ret == -EIO || ret == -EBADMSG) {
+		d->curr_write_pos--;
+		eb->active_count--;
+		d->revmap[*bp] = PAGE_UNDEF;
+		mtdswap_handle_write_error(d, eb);
+		goto retry;
+	}
+
+	if (ret < 0) {
+		dev_err(d->dev, "Write to MTD device failed: %d (%zd written)",
+			ret, retlen);
+		goto err;
+	}
+
+	if (retlen != PAGE_SIZE) {
+		dev_err(d->dev, "Short write to MTD device: %zd written",
+			retlen);
+		ret = -EIO;
+		goto err;
+	}
+
+	return ret;
+
+err:
+	d->curr_write_pos--;
+	eb->active_count--;
+	d->revmap[*bp] = PAGE_UNDEF;
+
+	return ret;
+}
+
+static int mtdswap_move_block(struct mtdswap_dev *d, unsigned int oldblock,
+		unsigned int *newblock)
+{
+	struct mtd_info *mtd = d->mtd;
+	struct swap_eb *eb, *oldeb;
+	int ret;
+	size_t retlen;
+	unsigned int page, retries;
+	loff_t readpos;
+
+	page = d->revmap[oldblock];
+	readpos = (loff_t) oldblock << PAGE_SHIFT;
+	retries = 0;
+
+retry:
+	ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, d->page_buf);
+
+	if (ret < 0 && ret != -EUCLEAN) {
+		oldeb = d->eb_data + oldblock / d->pages_per_eblk;
+		oldeb->flags |= EBLOCK_READERR;
+
+		dev_err(d->dev, "Read Error: %d (block %u)\n", ret,
+			oldblock);
+		retries++;
+		if (retries < MTDSWAP_IO_RETRIES)
+			goto retry;
+
+		goto read_error;
+	}
+
+	if (retlen != PAGE_SIZE) {
+		dev_err(d->dev, "Short read: %zd (block %u)\n", retlen,
+		       oldblock);
+		ret = -EIO;
+		goto read_error;
+	}
+
+	ret = mtdswap_write_block(d, d->page_buf, page, newblock, 1);
+	if (ret < 0) {
+		d->page_data[page] = BLOCK_ERROR;
+		dev_err(d->dev, "Write error: %d\n", ret);
+		return ret;
+	}
+
+	eb = d->eb_data + *newblock / d->pages_per_eblk;
+	d->page_data[page] = *newblock;
+	d->revmap[oldblock] = PAGE_UNDEF;
+	eb = d->eb_data + oldblock / d->pages_per_eblk;
+	eb->active_count--;
+
+	return 0;
+
+read_error:
+	d->page_data[page] = BLOCK_ERROR;
+	d->revmap[oldblock] = PAGE_UNDEF;
+	return ret;
+}
+
+static int mtdswap_gc_eblock(struct mtdswap_dev *d, struct swap_eb *eb)
+{
+	unsigned int i, block, eblk_base, newblock;
+	int ret, errcode;
+
+	errcode = 0;
+	eblk_base = (eb - d->eb_data) * d->pages_per_eblk;
+
+	for (i = 0; i < d->pages_per_eblk; i++) {
+		if (d->spare_eblks < MIN_SPARE_EBLOCKS)
+			return -ENOSPC;
+
+		block = eblk_base + i;
+		if (d->revmap[block] == PAGE_UNDEF)
+			continue;
+
+		ret = mtdswap_move_block(d, block, &newblock);
+		if (ret < 0 && !errcode)
+			errcode = ret;
+	}
+
+	return errcode;
+}
+
+static int __mtdswap_choose_gc_tree(struct mtdswap_dev *d)
+{
+	int idx, stopat;
+
+	if (TREE_COUNT(d, CLEAN) < LOW_FRAG_GC_TRESHOLD)
+		stopat = MTDSWAP_LOWFRAG;
+	else
+		stopat = MTDSWAP_HIFRAG;
+
+	for (idx = MTDSWAP_BITFLIP; idx >= stopat; idx--)
+		if (d->trees[idx].root.rb_node != NULL)
+			return idx;
+
+	return -1;
+}
+
+static int mtdswap_wlfreq(unsigned int maxdiff)
+{
+	unsigned int h, x, y, dist, base;
+
+	/*
+	 * Calculate linear ramp down from f1 to f2 when maxdiff goes from
+	 * MAX_ERASE_DIFF to MAX_ERASE_DIFF + COLLECT_NONDIRTY_BASE.  Similar
+	 * to triangle with height f1 - f1 and width COLLECT_NONDIRTY_BASE.
+	 */
+
+	dist = maxdiff - MAX_ERASE_DIFF;
+	if (dist > COLLECT_NONDIRTY_BASE)
+		dist = COLLECT_NONDIRTY_BASE;
+
+	/*
+	 * Modelling the slop as right angular triangle with base
+	 * COLLECT_NONDIRTY_BASE and height freq1 - freq2. The ratio y/x is
+	 * equal to the ratio h/base.
+	 */
+	h = COLLECT_NONDIRTY_FREQ1 - COLLECT_NONDIRTY_FREQ2;
+	base = COLLECT_NONDIRTY_BASE;
+
+	x = dist - base;
+	y = (x * h + base / 2) / base;
+
+	return COLLECT_NONDIRTY_FREQ2 + y;
+}
+
+static int mtdswap_choose_wl_tree(struct mtdswap_dev *d)
+{
+	static unsigned int pick_cnt;
+	unsigned int i, idx = -1, wear, max;
+	struct rb_root *root;
+
+	max = 0;
+	for (i = 0; i <= MTDSWAP_DIRTY; i++) {
+		root = &d->trees[i].root;
+		if (root->rb_node == NULL)
+			continue;
+
+		wear = d->max_erase_count - MTDSWAP_ECNT_MIN(root);
+		if (wear > max) {
+			max = wear;
+			idx = i;
+		}
+	}
+
+	if (max > MAX_ERASE_DIFF && pick_cnt >= mtdswap_wlfreq(max) - 1) {
+		pick_cnt = 0;
+		return idx;
+	}
+
+	pick_cnt++;
+	return -1;
+}
+
+static int mtdswap_choose_gc_tree(struct mtdswap_dev *d,
+				unsigned int background)
+{
+	int idx;
+
+	if (TREE_NONEMPTY(d, FAILING) &&
+		(background || (TREE_EMPTY(d, CLEAN) && TREE_EMPTY(d, DIRTY))))
+		return MTDSWAP_FAILING;
+
+	idx = mtdswap_choose_wl_tree(d);
+	if (idx >= MTDSWAP_CLEAN)
+		return idx;
+
+	return __mtdswap_choose_gc_tree(d);
+}
+
+static struct swap_eb *mtdswap_pick_gc_eblk(struct mtdswap_dev *d,
+					unsigned int background)
+{
+	struct rb_root *rp = NULL;
+	struct swap_eb *eb = NULL;
+	int idx;
+
+	if (background && TREE_COUNT(d, CLEAN) > CLEAN_BLOCK_THRESHOLD &&
+		TREE_EMPTY(d, DIRTY) && TREE_EMPTY(d, FAILING))
+		return NULL;
+
+	idx = mtdswap_choose_gc_tree(d, background);
+	if (idx < 0)
+		return NULL;
+
+	rp = &d->trees[idx].root;
+	eb = rb_entry(rb_first(rp), struct swap_eb, rb);
+
+	rb_erase(&eb->rb, rp);
+	eb->root = NULL;
+	d->trees[idx].count--;
+	return eb;
+}
+
+static unsigned int mtdswap_test_patt(unsigned int i)
+{
+	return i % 2 ? 0x55555555 : 0xAAAAAAAA;
+}
+
+static unsigned int mtdswap_eblk_passes(struct mtdswap_dev *d,
+					struct swap_eb *eb)
+{
+	struct mtd_info *mtd = d->mtd;
+	unsigned int test, i, j, patt, mtd_pages;
+	loff_t base, pos;
+	unsigned int *p1 = (unsigned int *)d->page_buf;
+	unsigned char *p2 = (unsigned char *)d->oob_buf;
+	struct mtd_oob_ops ops;
+	int ret;
+
+	ops.mode = MTD_OOB_AUTO;
+	ops.len = mtd->writesize;
+	ops.ooblen = mtd->ecclayout->oobavail;
+	ops.ooboffs = 0;
+	ops.datbuf = d->page_buf;
+	ops.oobbuf = d->oob_buf;
+	base = mtdswap_eb_offset(d, eb);
+	mtd_pages = d->pages_per_eblk * PAGE_SIZE / mtd->writesize;
+
+	for (test = 0; test < 2; test++) {
+		pos = base;
+		for (i = 0; i < mtd_pages; i++) {
+			patt = mtdswap_test_patt(test + i);
+			memset(d->page_buf, patt, mtd->writesize);
+			memset(d->oob_buf, patt, mtd->ecclayout->oobavail);
+			ret = mtd->write_oob(mtd, pos, &ops);
+			if (ret)
+				goto error;
+
+			pos += mtd->writesize;
+		}
+
+		pos = base;
+		for (i = 0; i < mtd_pages; i++) {
+			ret = mtd->read_oob(mtd, pos, &ops);
+			if (ret)
+				goto error;
+
+			patt = mtdswap_test_patt(test + i);
+			for (j = 0; j < mtd->writesize/sizeof(int); j++)
+				if (p1[j] != patt)
+					goto error;
+
+			for (j = 0; j < mtd->ecclayout->oobavail; j++)
+				if (p2[j] != (unsigned char)patt)
+					goto error;
+
+			pos += mtd->writesize;
+		}
+
+		ret = mtdswap_erase_block(d, eb);
+		if (ret)
+			goto error;
+	}
+
+	eb->flags &= ~EBLOCK_READERR;
+	return 1;
+
+error:
+	mtdswap_handle_badblock(d, eb);
+	return 0;
+}
+
+static int mtdswap_gc(struct mtdswap_dev *d, unsigned int background)
+{
+	struct swap_eb *eb;
+	int ret;
+
+	if (d->spare_eblks < MIN_SPARE_EBLOCKS)
+		return 1;
+
+	eb = mtdswap_pick_gc_eblk(d, background);
+	if (!eb)
+		return 1;
+
+	ret = mtdswap_gc_eblock(d, eb);
+	if (ret == -ENOSPC)
+		return 1;
+
+	if (eb->flags & EBLOCK_FAILED) {
+		mtdswap_handle_badblock(d, eb);
+		return 0;
+	}
+
+	eb->flags &= ~EBLOCK_BITFLIP;
+	ret = mtdswap_erase_block(d, eb);
+	if ((eb->flags & EBLOCK_READERR) &&
+		(ret || !mtdswap_eblk_passes(d, eb)))
+		return 0;
+
+	if (ret == 0)
+		ret = mtdswap_write_marker(d, eb, MTDSWAP_TYPE_CLEAN);
+
+	if (ret == 0)
+		mtdswap_rb_add(d, eb, MTDSWAP_CLEAN);
+	else if (ret != -EIO && ret != -EBADMSG)
+		mtdswap_rb_add(d, eb, MTDSWAP_DIRTY);
+
+	return 0;
+}
+
+static void mtdswap_background(struct mtd_blktrans_dev *dev)
+{
+	struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+	int ret;
+
+	while (1) {
+		ret = mtdswap_gc(d, 1);
+		if (ret || mtd_blktrans_cease_background(dev))
+			return;
+	}
+}
+
+static void mtdswap_cleanup(struct mtdswap_dev *d)
+{
+	vfree(d->eb_data);
+	vfree(d->revmap);
+	vfree(d->page_data);
+	kfree(d->oob_buf);
+	kfree(d->page_buf);
+}
+
+static int mtdswap_flush(struct mtd_blktrans_dev *dev)
+{
+	struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+
+	if (d->mtd->sync)
+		d->mtd->sync(d->mtd);
+	return 0;
+}
+
+static unsigned int mtdswap_badblocks(struct mtd_info *mtd, uint64_t size)
+{
+	loff_t offset;
+	unsigned int badcnt;
+
+	badcnt = 0;
+
+	if (mtd->block_isbad)
+		for (offset = 0; offset < size; offset += mtd->erasesize)
+			if (mtd->block_isbad(mtd, offset))
+				badcnt++;
+
+	return badcnt;
+}
+
+static int mtdswap_writesect(struct mtd_blktrans_dev *dev,
+			unsigned long page, char *buf)
+{
+	struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+	unsigned int newblock, mapped;
+	struct swap_eb *eb;
+	int ret;
+
+	d->sect_write_count++;
+
+	if (d->spare_eblks < MIN_SPARE_EBLOCKS)
+		return -ENOSPC;
+
+	if (header) {
+		/* Ignore writes to the header page */
+		if (unlikely(page == 0))
+			return 0;
+
+		page--;
+	}
+
+	mapped = d->page_data[page];
+	if (mapped <= BLOCK_MAX) {
+		eb = d->eb_data + (mapped / d->pages_per_eblk);
+		eb->active_count--;
+		mtdswap_store_eb(d, eb);
+		d->page_data[page] = BLOCK_UNDEF;
+		d->revmap[mapped] = PAGE_UNDEF;
+	}
+
+	ret = mtdswap_write_block(d, buf, page, &newblock, 0);
+	d->mtd_write_count++;
+
+	if (ret < 0)
+		return ret;
+
+	eb = d->eb_data + (newblock / d->pages_per_eblk);
+	d->page_data[page] = newblock;
+
+	return 0;
+}
+
+/* Provide a dummy swap header for the kernel */
+static int mtdswap_auto_header(struct mtdswap_dev *d, char *buf)
+{
+	union swap_header *hd = (union swap_header *)(buf);
+
+	memset(buf, 0, PAGE_SIZE - 10);
+
+	hd->info.version = 1;
+	hd->info.last_page = d->mbd_dev->size - 1;
+	hd->info.nr_badpages = 0;
+
+	memcpy(buf + PAGE_SIZE - 10, "SWAPSPACE2", 10);
+
+	return 0;
+}
+
+static int mtdswap_readsect(struct mtd_blktrans_dev *dev,
+			unsigned long page, char *buf)
+{
+	struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+	struct mtd_info *mtd = d->mtd;
+	unsigned int realblock, retries;
+	loff_t readpos;
+	struct swap_eb *eb;
+	size_t retlen;
+	int ret;
+
+	d->sect_read_count++;
+
+	if (header) {
+		if (unlikely(page == 0))
+			return mtdswap_auto_header(d, buf);
+
+		page--;
+	}
+
+	realblock = d->page_data[page];
+	if (realblock > BLOCK_MAX) {
+		memset(buf, 0x0, PAGE_SIZE);
+		if (realblock == BLOCK_UNDEF)
+			return 0;
+		else
+			return -EIO;
+	}
+
+	eb = d->eb_data + (realblock / d->pages_per_eblk);
+	BUG_ON(d->revmap[realblock] == PAGE_UNDEF);
+
+	readpos = (loff_t)realblock << PAGE_SHIFT;
+	retries = 0;
+
+retry:
+	ret = mtd->read(mtd, readpos, PAGE_SIZE, &retlen, buf);
+
+	d->mtd_read_count++;
+	if (ret == -EUCLEAN) {
+		eb->flags |= EBLOCK_BITFLIP;
+		mtdswap_rb_add(d, eb, MTDSWAP_BITFLIP);
+		ret = 0;
+	}
+
+	if (ret < 0) {
+		dev_err(d->dev, "Read error %d\n", ret);
+		eb->flags |= EBLOCK_READERR;
+		mtdswap_rb_add(d, eb, MTDSWAP_FAILING);
+		retries++;
+		if (retries < MTDSWAP_IO_RETRIES)
+			goto retry;
+
+		return ret;
+	}
+
+	if (retlen != PAGE_SIZE) {
+		dev_err(d->dev, "Short read %zd\n", retlen);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+static int mtdswap_discard(struct mtd_blktrans_dev *dev, unsigned long first,
+			unsigned nr_pages)
+{
+	struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+	unsigned long page;
+	struct swap_eb *eb;
+	unsigned int mapped;
+
+	d->discard_count++;
+
+	for (page = first; page < first + nr_pages; page++) {
+		mapped = d->page_data[page];
+		if (mapped <= BLOCK_MAX) {
+			eb = d->eb_data + (mapped / d->pages_per_eblk);
+			eb->active_count--;
+			mtdswap_store_eb(d, eb);
+			d->page_data[page] = BLOCK_UNDEF;
+			d->revmap[mapped] = PAGE_UNDEF;
+			d->discard_page_count++;
+		} else if (mapped == BLOCK_ERROR) {
+			d->page_data[page] = BLOCK_UNDEF;
+			d->discard_page_count++;
+		}
+	}
+
+	return 0;
+}
+
+static int mtdswap_show(struct seq_file *s, void *data)
+{
+	struct mtdswap_dev *d = (struct mtdswap_dev *) s->private;
+	unsigned long sum;
+	unsigned int count[MTDSWAP_TREE_CNT];
+	unsigned int min[MTDSWAP_TREE_CNT];
+	unsigned int max[MTDSWAP_TREE_CNT];
+	unsigned int i, cw = 0, cwp = 0, cwecount = 0, bb_cnt, mapped, pages;
+	uint64_t use_size;
+	char *name[] = {"clean", "used", "low", "high", "dirty", "bitflip",
+			"failing"};
+
+	mutex_lock(&d->mbd_dev->lock);
+
+	for (i = 0; i < MTDSWAP_TREE_CNT; i++) {
+		struct rb_root *root = &d->trees[i].root;
+
+		if (root->rb_node) {
+			count[i] = d->trees[i].count;
+			min[i] = rb_entry(rb_first(root), struct swap_eb,
+					rb)->erase_count;
+			max[i] = rb_entry(rb_last(root), struct swap_eb,
+					rb)->erase_count;
+		} else
+			count[i] = 0;
+	}
+
+	if (d->curr_write) {
+		cw = 1;
+		cwp = d->curr_write_pos;
+		cwecount = d->curr_write->erase_count;
+	}
+
+	sum = 0;
+	for (i = 0; i < d->eblks; i++)
+		sum += d->eb_data[i].erase_count;
+
+	use_size = (uint64_t)d->eblks * d->mtd->erasesize;
+	bb_cnt = mtdswap_badblocks(d->mtd, use_size);
+
+	mapped = 0;
+	pages = d->mbd_dev->size;
+	for (i = 0; i < pages; i++)
+		if (d->page_data[i] != BLOCK_UNDEF)
+			mapped++;
+
+	mutex_unlock(&d->mbd_dev->lock);
+
+	for (i = 0; i < MTDSWAP_TREE_CNT; i++) {
+		if (!count[i])
+			continue;
+
+		if (min[i] != max[i])
+			seq_printf(s, "%s:\t%5d erase blocks, erased min %d, "
+				"max %d times\n",
+				name[i], count[i], min[i], max[i]);
+		else
+			seq_printf(s, "%s:\t%5d erase blocks, all erased %d "
+				"times\n", name[i], count[i], min[i]);
+	}
+
+	if (bb_cnt)
+		seq_printf(s, "bad:\t%5u erase blocks\n", bb_cnt);
+
+	if (cw)
+		seq_printf(s, "current erase block: %u pages used, %u free, "
+			"erased %u times\n",
+			cwp, d->pages_per_eblk - cwp, cwecount);
+
+	seq_printf(s, "total erasures: %lu\n", sum);
+
+	seq_printf(s, "\n");
+
+	seq_printf(s, "mtdswap_readsect count: %llu\n", d->sect_read_count);
+	seq_printf(s, "mtdswap_writesect count: %llu\n", d->sect_write_count);
+	seq_printf(s, "mtdswap_discard count: %llu\n", d->discard_count);
+	seq_printf(s, "mtd read count: %llu\n", d->mtd_read_count);
+	seq_printf(s, "mtd write count: %llu\n", d->mtd_write_count);
+	seq_printf(s, "discarded pages count: %llu\n", d->discard_page_count);
+
+	seq_printf(s, "\n");
+	seq_printf(s, "total pages: %u\n", pages);
+	seq_printf(s, "pages mapped: %u\n", mapped);
+
+	return 0;
+}
+
+static int mtdswap_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, mtdswap_show, inode->i_private);
+}
+
+static const struct file_operations mtdswap_fops = {
+	.open		= mtdswap_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= single_release,
+};
+
+static int mtdswap_add_debugfs(struct mtdswap_dev *d)
+{
+	struct gendisk *gd = d->mbd_dev->disk;
+	struct device *dev = disk_to_dev(gd);
+
+	struct dentry *root;
+	struct dentry *dent;
+
+	root = debugfs_create_dir(gd->disk_name, NULL);
+	if (IS_ERR(root))
+		return 0;
+
+	if (!root) {
+		dev_err(dev, "failed to initialize debugfs\n");
+		return -1;
+	}
+
+	d->debugfs_root = root;
+
+	dent = debugfs_create_file("stats", S_IRUSR, root, d,
+				&mtdswap_fops);
+	if (!dent) {
+		dev_err(d->dev, "debugfs_create_file failed\n");
+		debugfs_remove_recursive(root);
+		d->debugfs_root = NULL;
+		return -1;
+	}
+
+	return 0;
+}
+
+static int mtdswap_init(struct mtdswap_dev *d, unsigned int eblocks,
+			unsigned int spare_cnt)
+{
+	struct mtd_info *mtd = d->mbd_dev->mtd;
+	unsigned int i, eblk_bytes, pages, blocks;
+	int ret = -ENOMEM;
+
+	d->mtd = mtd;
+	d->eblks = eblocks;
+	d->spare_eblks = spare_cnt;
+	d->pages_per_eblk = mtd->erasesize >> PAGE_SHIFT;
+
+	pages = d->mbd_dev->size;
+	blocks = eblocks * d->pages_per_eblk;
+
+	for (i = 0; i < MTDSWAP_TREE_CNT; i++)
+		d->trees[i].root = RB_ROOT;
+
+	d->page_data = vmalloc(sizeof(int)*pages);
+	if (!d->page_data)
+		goto page_data_fail;
+
+	d->revmap = vmalloc(sizeof(int)*blocks);
+	if (!d->revmap)
+		goto revmap_fail;
+
+	eblk_bytes = sizeof(struct swap_eb)*d->eblks;
+	d->eb_data = vmalloc(eblk_bytes);
+	if (!d->eb_data)
+		goto eb_data_fail;
+
+	memset(d->eb_data, 0, eblk_bytes);
+	for (i = 0; i < pages; i++)
+		d->page_data[i] = BLOCK_UNDEF;
+
+	for (i = 0; i < blocks; i++)
+		d->revmap[i] = PAGE_UNDEF;
+
+	d->page_buf = kmalloc(PAGE_SIZE, GFP_KERNEL);
+	if (!d->page_buf)
+		goto page_buf_fail;
+
+	d->oob_buf = kmalloc(2 * mtd->ecclayout->oobavail, GFP_KERNEL);
+	if (!d->oob_buf)
+		goto oob_buf_fail;
+
+	mtdswap_scan_eblks(d);
+
+	return 0;
+
+oob_buf_fail:
+	kfree(d->page_buf);
+page_buf_fail:
+	vfree(d->eb_data);
+eb_data_fail:
+	vfree(d->revmap);
+revmap_fail:
+	vfree(d->page_data);
+page_data_fail:
+	printk(KERN_ERR "%s: init failed (%d)\n", MTDSWAP_PREFIX, ret);
+	return ret;
+}
+
+static void mtdswap_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
+{
+	struct mtdswap_dev *d;
+	struct mtd_blktrans_dev *mbd_dev;
+	char *parts;
+	char *this_opt;
+	unsigned long part;
+	unsigned int eblocks, eavailable, bad_blocks, spare_cnt;
+	uint64_t swap_size, use_size, size_limit;
+	struct nand_ecclayout *oinfo;
+	int ret;
+
+	parts = &partitions[0];
+	if (!*parts)
+		return;
+
+	while ((this_opt = strsep(&parts, ",")) != NULL) {
+		if (strict_strtoul(this_opt, 0, &part) < 0)
+			return;
+
+		if (mtd->index == part)
+			break;
+	}
+
+	if (mtd->index != part)
+		return;
+
+	if (mtd->erasesize < PAGE_SIZE || mtd->erasesize % PAGE_SIZE) {
+		printk(KERN_ERR "%s: Erase size %u not multiple of PAGE_SIZE "
+			"%lu\n", MTDSWAP_PREFIX, mtd->erasesize, PAGE_SIZE);
+		return;
+	}
+
+	if (PAGE_SIZE % mtd->writesize || mtd->writesize > PAGE_SIZE) {
+		printk(KERN_ERR "%s: PAGE_SIZE %lu not multiple of write size"
+			" %u\n", MTDSWAP_PREFIX, PAGE_SIZE, mtd->writesize);
+		return;
+	}
+
+	oinfo = mtd->ecclayout;
+	if (!mtd->oobsize || !oinfo || oinfo->oobavail < MTDSWAP_OOBSIZE) {
+		printk(KERN_ERR "%s: Not enough free bytes in OOB, "
+			"%d available, %zu needed.\n",
+			MTDSWAP_PREFIX, oinfo->oobavail, MTDSWAP_OOBSIZE);
+		return;
+	}
+
+	if (spare_eblocks > 100)
+		spare_eblocks = 100;
+
+	use_size = mtd->size;
+	size_limit = (uint64_t) BLOCK_MAX * PAGE_SIZE;
+
+	if (mtd->size > size_limit) {
+		printk(KERN_WARNING "%s: Device too large. Limiting size to "
+			"%llu bytes\n", MTDSWAP_PREFIX, size_limit);
+		use_size = size_limit;
+	}
+
+	eblocks = mtd_div_by_eb(use_size, mtd);
+	use_size = eblocks * mtd->erasesize;
+	bad_blocks = mtdswap_badblocks(mtd, use_size);
+	eavailable = eblocks - bad_blocks;
+
+	if (eavailable < MIN_ERASE_BLOCKS) {
+		printk(KERN_ERR "%s: Not enough erase blocks. %u available, "
+			"%d needed\n", MTDSWAP_PREFIX, eavailable,
+			MIN_ERASE_BLOCKS);
+		return;
+	}
+
+	spare_cnt = div_u64((uint64_t)eavailable * spare_eblocks, 100);
+
+	if (spare_cnt < MIN_SPARE_EBLOCKS)
+		spare_cnt = MIN_SPARE_EBLOCKS;
+
+	if (spare_cnt > eavailable - 1)
+		spare_cnt = eavailable - 1;
+
+	swap_size = (uint64_t)(eavailable - spare_cnt) * mtd->erasesize +
+		(header ? PAGE_SIZE : 0);
+
+	printk(KERN_INFO "%s: Enabling MTD swap on device %lu, size %llu KB, "
+		"%u spare, %u bad blocks\n",
+		MTDSWAP_PREFIX, part, swap_size / 1024, spare_cnt, bad_blocks);
+
+	d = kzalloc(sizeof(struct mtdswap_dev), GFP_KERNEL);
+	if (!d)
+		return;
+
+	mbd_dev = kzalloc(sizeof(struct mtd_blktrans_dev), GFP_KERNEL);
+	if (!mbd_dev) {
+		kfree(d);
+		return;
+	}
+
+	d->mbd_dev = mbd_dev;
+	mbd_dev->priv = d;
+
+	mbd_dev->mtd = mtd;
+	mbd_dev->devnum = mtd->index;
+	mbd_dev->size = swap_size >> PAGE_SHIFT;
+	mbd_dev->tr = tr;
+
+	if (!(mtd->flags & MTD_WRITEABLE))
+		mbd_dev->readonly = 1;
+
+	if (mtdswap_init(d, eblocks, spare_cnt) < 0)
+		goto init_failed;
+
+	if (add_mtd_blktrans_dev(mbd_dev) < 0)
+		goto cleanup;
+
+	d->dev = disk_to_dev(mbd_dev->disk);
+
+	ret = mtdswap_add_debugfs(d);
+	if (ret < 0)
+		goto debugfs_failed;
+
+	return;
+
+debugfs_failed:
+	del_mtd_blktrans_dev(mbd_dev);
+
+cleanup:
+	mtdswap_cleanup(d);
+
+init_failed:
+	kfree(mbd_dev);
+	kfree(d);
+}
+
+static void mtdswap_remove_dev(struct mtd_blktrans_dev *dev)
+{
+	struct mtdswap_dev *d = MTDSWAP_MBD_TO_MTDSWAP(dev);
+
+	debugfs_remove_recursive(d->debugfs_root);
+	del_mtd_blktrans_dev(dev);
+	mtdswap_cleanup(d);
+	kfree(d);
+}
+
+static struct mtd_blktrans_ops mtdswap_ops = {
+	.name		= "mtdswap",
+	.major		= 0,
+	.part_bits	= 0,
+	.blksize	= PAGE_SIZE,
+	.flush		= mtdswap_flush,
+	.readsect	= mtdswap_readsect,
+	.writesect	= mtdswap_writesect,
+	.discard	= mtdswap_discard,
+	.background	= mtdswap_background,
+	.add_mtd	= mtdswap_add_mtd,
+	.remove_dev	= mtdswap_remove_dev,
+	.owner		= THIS_MODULE,
+};
+
+static int __init mtdswap_modinit(void)
+{
+	return register_mtd_blktrans(&mtdswap_ops);
+}
+
+static void __exit mtdswap_modexit(void)
+{
+	deregister_mtd_blktrans(&mtdswap_ops);
+}
+
+module_init(mtdswap_modinit);
+module_exit(mtdswap_modexit);
+
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Jarkko Lavinen <jarkko.lavinen@nokia.com>");
+MODULE_DESCRIPTION("Block device access to an MTD suitable for using as "
+		"swap space");
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/ams-delta.c linux-libre-2.6.39-gnu/drivers/mtd/nand/ams-delta.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/ams-delta.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/ams-delta.c	2011-05-19 00:06:34.000000000 -0400
@@ -228,7 +228,7 @@
 					  AMS_DELTA_LATCH2_NAND_NCE |
 					  AMS_DELTA_LATCH2_NAND_NWP);
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(ams_delta_mtd, 1)) {
 		err = -ENXIO;
 		goto out_mtd;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/atmel_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/atmel_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/atmel_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/atmel_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,6 +48,9 @@
 #define no_ecc		0
 #endif
 
+static int use_dma = 1;
+module_param(use_dma, int, 0);
+
 static int on_flash_bbt = 0;
 module_param(on_flash_bbt, int, 0);
 
@@ -89,11 +92,20 @@
 	struct nand_chip	nand_chip;
 	struct mtd_info		mtd;
 	void __iomem		*io_base;
+	dma_addr_t		io_phys;
 	struct atmel_nand_data	*board;
 	struct device		*dev;
 	void __iomem		*ecc;
+
+	struct completion	comp;
+	struct dma_chan		*dma_chan;
 };
 
+static int cpu_has_dma(void)
+{
+	return cpu_is_at91sam9rl() || cpu_is_at91sam9g45();
+}
+
 /*
  * Enable NAND.
  */
@@ -150,7 +162,7 @@
 /*
  * Minimal-overhead PIO for data access.
  */
-static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+static void atmel_read_buf8(struct mtd_info *mtd, u8 *buf, int len)
 {
 	struct nand_chip	*nand_chip = mtd->priv;
 
@@ -164,7 +176,7 @@
 	__raw_readsw(nand_chip->IO_ADDR_R, buf, len / 2);
 }
 
-static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+static void atmel_write_buf8(struct mtd_info *mtd, const u8 *buf, int len)
 {
 	struct nand_chip	*nand_chip = mtd->priv;
 
@@ -178,6 +190,109 @@
 	__raw_writesw(nand_chip->IO_ADDR_W, buf, len / 2);
 }
 
+static void dma_complete_func(void *completion)
+{
+	complete(completion);
+}
+
+static int atmel_nand_dma_op(struct mtd_info *mtd, void *buf, int len,
+			       int is_read)
+{
+	struct dma_device *dma_dev;
+	enum dma_ctrl_flags flags;
+	dma_addr_t dma_src_addr, dma_dst_addr, phys_addr;
+	struct dma_async_tx_descriptor *tx = NULL;
+	dma_cookie_t cookie;
+	struct nand_chip *chip = mtd->priv;
+	struct atmel_nand_host *host = chip->priv;
+	void *p = buf;
+	int err = -EIO;
+	enum dma_data_direction dir = is_read ? DMA_FROM_DEVICE : DMA_TO_DEVICE;
+
+	if (buf >= high_memory)
+		goto err_buf;
+
+	dma_dev = host->dma_chan->device;
+
+	flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT | DMA_COMPL_SKIP_SRC_UNMAP |
+		DMA_COMPL_SKIP_DEST_UNMAP;
+
+	phys_addr = dma_map_single(dma_dev->dev, p, len, dir);
+	if (dma_mapping_error(dma_dev->dev, phys_addr)) {
+		dev_err(host->dev, "Failed to dma_map_single\n");
+		goto err_buf;
+	}
+
+	if (is_read) {
+		dma_src_addr = host->io_phys;
+		dma_dst_addr = phys_addr;
+	} else {
+		dma_src_addr = phys_addr;
+		dma_dst_addr = host->io_phys;
+	}
+
+	tx = dma_dev->device_prep_dma_memcpy(host->dma_chan, dma_dst_addr,
+					     dma_src_addr, len, flags);
+	if (!tx) {
+		dev_err(host->dev, "Failed to prepare DMA memcpy\n");
+		goto err_dma;
+	}
+
+	init_completion(&host->comp);
+	tx->callback = dma_complete_func;
+	tx->callback_param = &host->comp;
+
+	cookie = tx->tx_submit(tx);
+	if (dma_submit_error(cookie)) {
+		dev_err(host->dev, "Failed to do DMA tx_submit\n");
+		goto err_dma;
+	}
+
+	dma_async_issue_pending(host->dma_chan);
+	wait_for_completion(&host->comp);
+
+	err = 0;
+
+err_dma:
+	dma_unmap_single(dma_dev->dev, phys_addr, len, dir);
+err_buf:
+	if (err != 0)
+		dev_warn(host->dev, "Fall back to CPU I/O\n");
+	return err;
+}
+
+static void atmel_read_buf(struct mtd_info *mtd, u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct atmel_nand_host *host = chip->priv;
+
+	if (use_dma && len > mtd->oobsize)
+		/* only use DMA for bigger than oob size: better performances */
+		if (atmel_nand_dma_op(mtd, buf, len, 1) == 0)
+			return;
+
+	if (host->board->bus_width_16)
+		atmel_read_buf16(mtd, buf, len);
+	else
+		atmel_read_buf8(mtd, buf, len);
+}
+
+static void atmel_write_buf(struct mtd_info *mtd, const u8 *buf, int len)
+{
+	struct nand_chip *chip = mtd->priv;
+	struct atmel_nand_host *host = chip->priv;
+
+	if (use_dma && len > mtd->oobsize)
+		/* only use DMA for bigger than oob size: better performances */
+		if (atmel_nand_dma_op(mtd, (void *)buf, len, 0) == 0)
+			return;
+
+	if (host->board->bus_width_16)
+		atmel_write_buf16(mtd, buf, len);
+	else
+		atmel_write_buf8(mtd, buf, len);
+}
+
 /*
  * Calculate HW ECC
  *
@@ -398,6 +513,8 @@
 		return -ENOMEM;
 	}
 
+	host->io_phys = (dma_addr_t)mem->start;
+
 	host->io_base = ioremap(mem->start, mem->end - mem->start + 1);
 	if (host->io_base == NULL) {
 		printk(KERN_ERR "atmel_nand: ioremap failed\n");
@@ -448,14 +565,11 @@
 
 	nand_chip->chip_delay = 20;		/* 20us command delay time */
 
-	if (host->board->bus_width_16) {	/* 16-bit bus width */
+	if (host->board->bus_width_16)	/* 16-bit bus width */
 		nand_chip->options |= NAND_BUSWIDTH_16;
-		nand_chip->read_buf = atmel_read_buf16;
-		nand_chip->write_buf = atmel_write_buf16;
-	} else {
-		nand_chip->read_buf = atmel_read_buf;
-		nand_chip->write_buf = atmel_write_buf;
-	}
+
+	nand_chip->read_buf = atmel_read_buf;
+	nand_chip->write_buf = atmel_write_buf;
 
 	platform_set_drvdata(pdev, host);
 	atmel_nand_enable(host);
@@ -473,6 +587,26 @@
 		nand_chip->options |= NAND_USE_FLASH_BBT;
 	}
 
+	if (!cpu_has_dma())
+		use_dma = 0;
+
+	if (use_dma) {
+		dma_cap_mask_t mask;
+
+		dma_cap_zero(mask);
+		dma_cap_set(DMA_MEMCPY, mask);
+		host->dma_chan = dma_request_channel(mask, 0, NULL);
+		if (!host->dma_chan) {
+			dev_err(host->dev, "Failed to request DMA channel\n");
+			use_dma = 0;
+		}
+	}
+	if (use_dma)
+		dev_info(host->dev, "Using %s for DMA transfers.\n",
+					dma_chan_name(host->dma_chan));
+	else
+		dev_info(host->dev, "No DMA support for NAND access.\n");
+
 	/* first scan to find the device and get the page size */
 	if (nand_scan_ident(mtd, 1, NULL)) {
 		res = -ENXIO;
@@ -555,6 +689,8 @@
 err_no_card:
 	atmel_nand_disable(host);
 	platform_set_drvdata(pdev, NULL);
+	if (host->dma_chan)
+		dma_release_channel(host->dma_chan);
 	if (host->ecc)
 		iounmap(host->ecc);
 err_ecc_ioremap:
@@ -578,6 +714,10 @@
 
 	if (host->ecc)
 		iounmap(host->ecc);
+
+	if (host->dma_chan)
+		dma_release_channel(host->dma_chan);
+
 	iounmap(host->io_base);
 	kfree(host);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/autcpu12.c linux-libre-2.6.39-gnu/drivers/mtd/nand/autcpu12.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/autcpu12.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/autcpu12.c	2011-05-19 00:06:34.000000000 -0400
@@ -176,7 +176,7 @@
 	 */
 	this->options = NAND_USE_FLASH_BBT;
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(autcpu12_mtd, 1)) {
 		err = -ENXIO;
 		goto out_ior;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/cs553x_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/cs553x_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/cs553x_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/cs553x_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,7 +241,7 @@
 	/* Enable the following for a flash based bad block table */
 	this->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(new_mtd, 1)) {
 		err = -ENXIO;
 		goto out_ior;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/davinci_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/davinci_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/davinci_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/davinci_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,9 +37,6 @@
 #include <mach/nand.h>
 #include <mach/aemif.h>
 
-#include <asm/mach-types.h>
-
-
 /*
  * This is a device driver for the NAND flash controller found on the
  * various DaVinci family chips.  It handles up to four SoC chipselects,
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/denali.c linux-libre-2.6.39-gnu/drivers/mtd/nand/denali.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/denali.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/denali.c	2011-05-19 00:06:34.000000000 -0400
@@ -724,7 +724,7 @@
 }
 
 /* This helper function setups the registers for ECC and whether or not
- * the spare area will be transfered. */
+ * the spare area will be transferred. */
 static void setup_ecc_for_xfer(struct denali_nand_info *denali, bool ecc_en,
 				bool transfer_spare)
 {
@@ -965,7 +965,7 @@
 
 			if (ECC_ERROR_CORRECTABLE(err_correction_info)) {
 				/* If err_byte is larger than ECC_SECTOR_SIZE,
-				 * means error happend in OOB, so we ignore
+				 * means error happened in OOB, so we ignore
 				 * it. It's no need for us to correct it
 				 * err_device is represented the NAND error
 				 * bits are happened in if there are more
@@ -1109,7 +1109,7 @@
 }
 
 /* This is the callback that the NAND core calls to write a page without ECC.
- * raw access is similiar to ECC page writes, so all the work is done in the
+ * raw access is similar to ECC page writes, so all the work is done in the
  * write_page() function above.
  */
 static void denali_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip,
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/diskonchip.c linux-libre-2.6.39-gnu/drivers/mtd/nand/diskonchip.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/diskonchip.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/diskonchip.c	2011-05-19 00:06:34.000000000 -0400
@@ -137,7 +137,7 @@
  *
  * Fabrice Bellard figured this out in the old docecc code. I added
  * some comments, improved a minor bit and converted it to make use
- * of the generic Reed-Solomon libary. tglx
+ * of the generic Reed-Solomon library. tglx
  */
 static int doc_ecc_decode(struct rs_control *rs, uint8_t *data, uint8_t *ecc)
 {
@@ -400,7 +400,7 @@
 	doc200x_hwcontrol(mtd, 0, NAND_CTRL_ALE | NAND_CTRL_CHANGE);
 	doc200x_hwcontrol(mtd, NAND_CMD_NONE, NAND_NCE | NAND_CTRL_CHANGE);
 
-	/* We cant' use dev_ready here, but at least we wait for the
+	/* We can't use dev_ready here, but at least we wait for the
 	 * command to complete
 	 */
 	udelay(50);
@@ -986,7 +986,7 @@
 		dummy = ReadDOC(docptr, ECCConf);
 	}
 
-	/* Error occured ? */
+	/* Error occurred ? */
 	if (dummy & 0x80) {
 		for (i = 0; i < 6; i++) {
 			if (DoC_is_MillenniumPlus(doc))
@@ -1160,7 +1160,7 @@
 	/* NOTE: The lines below modify internal variables of the NAND and MTD
 	   layers; variables with have already been configured by nand_scan.
 	   Unfortunately, we didn't know before this point what these values
-	   should be.  Thus, this code is somewhat dependant on the exact
+	   should be.  Thus, this code is somewhat dependent on the exact
 	   implementation of the NAND layer.  */
 	if (mh->UnitSizeFactor != 0xff) {
 		this->bbt_erase_shift += (0xff - mh->UnitSizeFactor);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/fsl_elbc_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/fsl_elbc_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/fsl_elbc_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/fsl_elbc_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,7 +59,7 @@
 	unsigned int fmr;       /* FCM Flash Mode Register value     */
 };
 
-/* Freescale eLBC FCM controller infomation */
+/* Freescale eLBC FCM controller information */
 
 struct fsl_elbc_fcm_ctrl {
 	struct nand_hw_control controller;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/fsl_upm.c linux-libre-2.6.39-gnu/drivers/mtd/nand/fsl_upm.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/fsl_upm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/fsl_upm.c	2011-05-19 00:06:34.000000000 -0400
@@ -217,8 +217,7 @@
 	return ret;
 }
 
-static int __devinit fun_probe(struct platform_device *ofdev,
-			       const struct of_device_id *ofid)
+static int __devinit fun_probe(struct platform_device *ofdev)
 {
 	struct fsl_upm_nand *fun;
 	struct resource io_res;
@@ -360,7 +359,7 @@
 };
 MODULE_DEVICE_TABLE(of, of_fun_match);
 
-static struct of_platform_driver of_fun_driver = {
+static struct platform_driver of_fun_driver = {
 	.driver = {
 		.name = "fsl,upm-nand",
 		.owner = THIS_MODULE,
@@ -372,13 +371,13 @@
 
 static int __init fun_module_init(void)
 {
-	return of_register_platform_driver(&of_fun_driver);
+	return platform_driver_register(&of_fun_driver);
 }
 module_init(fun_module_init);
 
 static void __exit fun_module_exit(void)
 {
-	of_unregister_platform_driver(&of_fun_driver);
+	platform_driver_unregister(&of_fun_driver);
 }
 module_exit(fun_module_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/fsmc_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/fsmc_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/fsmc_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/fsmc_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -335,7 +335,7 @@
 
 /*
  * fsmc_read_hwecc_ecc4 - Hardware ECC calculator for ecc4 option supported by
- * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction upto
+ * FSMC. ECC is 13 bytes for 512 bytes of data (supports error correction up to
  * max of 8-bits)
  */
 static int fsmc_read_hwecc_ecc4(struct mtd_info *mtd, const uint8_t *data,
@@ -381,7 +381,7 @@
 
 /*
  * fsmc_read_hwecc_ecc1 - Hardware ECC calculator for ecc1 option supported by
- * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction upto
+ * FSMC. ECC is 3 bytes for 512 bytes of data (supports error correction up to
  * max of 1-bit)
  */
 static int fsmc_read_hwecc_ecc1(struct mtd_info *mtd, const uint8_t *data,
@@ -408,10 +408,10 @@
  * @buf:	buffer to store read data
  * @page:	page number to read
  *
- * This routine is needed for fsmc verison 8 as reading from NAND chip has to be
+ * This routine is needed for fsmc version 8 as reading from NAND chip has to be
  * performed in a strict sequence as follows:
  * data(512 byte) -> ecc(13 byte)
- * After this read, fsmc hardware generates and reports error data bits(upto a
+ * After this read, fsmc hardware generates and reports error data bits(up to a
  * max of 8 bits)
  */
 static int fsmc_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
@@ -686,7 +686,7 @@
 	}
 
 	/*
-	 * Scan to find existance of the device
+	 * Scan to find existence of the device
 	 */
 	if (nand_scan_ident(&host->mtd, 1, NULL)) {
 		ret = -ENXIO;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/Kconfig linux-libre-2.6.39-gnu/drivers/mtd/nand/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,21 @@
 	  device thinks the write was successful, a bit could have been
 	  flipped accidentally due to device wear or something else.
 
+config MTD_NAND_BCH
+	tristate
+	select BCH
+	depends on MTD_NAND_ECC_BCH
+	default MTD_NAND
+
+config MTD_NAND_ECC_BCH
+	bool "Support software BCH ECC"
+	default n
+	help
+	  This enables support for software BCH error correction. Binary BCH
+	  codes are more powerful and cpu intensive than traditional Hamming
+	  ECC codes. They are used with NAND devices requiring more than 1 bit
+	  of error correction.
+
 config MTD_SM_COMMON
 	tristate
 	default n
@@ -106,23 +121,6 @@
 	help
           Support for NAND flash on Texas Instruments OMAP2 and OMAP3 platforms.
 
-config MTD_NAND_OMAP_PREFETCH
-	bool "GPMC prefetch support for NAND Flash device"
-	depends on MTD_NAND_OMAP2
-	default y
-	help
-	 The NAND device can be accessed for Read/Write using GPMC PREFETCH engine
-	 to improve the performance.
-
-config MTD_NAND_OMAP_PREFETCH_DMA
-	depends on MTD_NAND_OMAP_PREFETCH
-	bool "DMA mode"
-	default n
-	help
-	 The GPMC PREFETCH engine can be configured eigther in MPU interrupt mode
-	 or in DMA interrupt mode.
-	 Say y for DMA mode or MPU mode will be used
-
 config MTD_NAND_IDS
 	tristate
 
@@ -241,7 +239,7 @@
 	help
 	  This enables the NAND flash controller on the BCM UMI block.
 
-	  No board specfic support is done by this driver, each board
+	  No board specific support is done by this driver, each board
 	  must advertise a platform_device for the driver to attach.
 
 config MTD_NAND_BCM_UMI_HWCS
@@ -476,7 +474,7 @@
 
 config MTD_NAND_MXC
 	tristate "MXC NAND support"
-	depends on ARCH_MX2 || ARCH_MX25 || ARCH_MX3 || ARCH_MX51
+	depends on IMX_HAVE_PLATFORM_MXC_NAND
 	help
 	  This enables the driver for the NAND flash controller on the
 	  MXC processors.
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/Makefile linux-libre-2.6.39-gnu/drivers/mtd/nand/Makefile
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_MTD_NAND)			+= nand.o
 obj-$(CONFIG_MTD_NAND_ECC)		+= nand_ecc.o
+obj-$(CONFIG_MTD_NAND_BCH)		+= nand_bch.o
 obj-$(CONFIG_MTD_NAND_IDS)		+= nand_ids.o
 obj-$(CONFIG_MTD_SM_COMMON) 		+= sm_common.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/mpc5121_nfc.c linux-libre-2.6.39-gnu/drivers/mtd/nand/mpc5121_nfc.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/mpc5121_nfc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/mpc5121_nfc.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #include <linux/clk.h>
 #include <linux/gfp.h>
 #include <linux/delay.h>
+#include <linux/err.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/io.h>
@@ -650,8 +651,7 @@
 		iounmap(prv->csreg);
 }
 
-static int __devinit mpc5121_nfc_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc5121_nfc_probe(struct platform_device *op)
 {
 	struct device_node *rootnode, *dn = op->dev.of_node;
 	struct device *dev = &op->dev;
@@ -758,9 +758,9 @@
 
 	/* Enable NFC clock */
 	prv->clk = clk_get(dev, "nfc_clk");
-	if (!prv->clk) {
+	if (IS_ERR(prv->clk)) {
 		dev_err(dev, "Unable to acquire NFC clock!\n");
-		retval = -ENODEV;
+		retval = PTR_ERR(prv->clk);
 		goto error;
 	}
 
@@ -891,7 +891,7 @@
 	{},
 };
 
-static struct of_platform_driver mpc5121_nfc_driver = {
+static struct platform_driver mpc5121_nfc_driver = {
 	.probe		= mpc5121_nfc_probe,
 	.remove		= __devexit_p(mpc5121_nfc_remove),
 	.driver		= {
@@ -903,14 +903,14 @@
 
 static int __init mpc5121_nfc_init(void)
 {
-	return of_register_platform_driver(&mpc5121_nfc_driver);
+	return platform_driver_register(&mpc5121_nfc_driver);
 }
 
 module_init(mpc5121_nfc_init);
 
 static void __exit mpc5121_nfc_cleanup(void)
 {
-	of_unregister_platform_driver(&mpc5121_nfc_driver);
+	platform_driver_unregister(&mpc5121_nfc_driver);
 }
 
 module_exit(mpc5121_nfc_cleanup);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/mxc_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/mxc_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/mxc_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/mxc_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -211,6 +211,31 @@
 	}
 };
 
+/* OOB description for 4096 byte pages with 128 byte OOB */
+static struct nand_ecclayout nandv2_hw_eccoob_4k = {
+	.eccbytes = 8 * 9,
+	.eccpos = {
+		7,  8,  9, 10, 11, 12, 13, 14, 15,
+		23, 24, 25, 26, 27, 28, 29, 30, 31,
+		39, 40, 41, 42, 43, 44, 45, 46, 47,
+		55, 56, 57, 58, 59, 60, 61, 62, 63,
+		71, 72, 73, 74, 75, 76, 77, 78, 79,
+		87, 88, 89, 90, 91, 92, 93, 94, 95,
+		103, 104, 105, 106, 107, 108, 109, 110, 111,
+		119, 120, 121, 122, 123, 124, 125, 126, 127,
+	},
+	.oobfree = {
+		{.offset = 2, .length = 4},
+		{.offset = 16, .length = 7},
+		{.offset = 32, .length = 7},
+		{.offset = 48, .length = 7},
+		{.offset = 64, .length = 7},
+		{.offset = 80, .length = 7},
+		{.offset = 96, .length = 7},
+		{.offset = 112, .length = 7},
+	}
+};
+
 #ifdef CONFIG_MTD_PARTITIONS
 static const char *part_probes[] = { "RedBoot", "cmdlinepart", NULL };
 #endif
@@ -641,9 +666,9 @@
 
 	n = min(n, len);
 
-	memcpy(buf, host->data_buf + col, len);
+	memcpy(buf, host->data_buf + col, n);
 
-	host->buf_start += len;
+	host->buf_start += n;
 }
 
 /* Used by the upper layer to verify the data in NAND Flash
@@ -722,9 +747,8 @@
 		/*
 		 * MXC NANDFC can only perform full page+spare or
 		 * spare-only read/write.  When the upper layers
-		 * layers perform a read/write buf operation,
-		 * we will used the saved column address to index into
-		 * the full page.
+		 * perform a read/write buf operation, the saved column
+		  * address is used to index into the full page.
 		 */
 		host->send_addr(host, 0, page_addr == -1);
 		if (mtd->writesize > 512)
@@ -1186,6 +1210,8 @@
 
 	if (mtd->writesize == 2048)
 		this->ecc.layout = oob_largepage;
+	if (nfc_is_v21() && mtd->writesize == 4096)
+		this->ecc.layout = &nandv2_hw_eccoob_4k;
 
 	/* second phase scan */
 	if (nand_scan_tail(mtd)) {
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_base.c linux-libre-2.6.39-gnu/drivers/mtd/nand/nand_base.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/nand_base.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,7 @@
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand_ecc.h>
+#include <linux/mtd/nand_bch.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
 #include <linux/leds.h>
@@ -1581,7 +1582,7 @@
 }
 
 /**
- * nand_read - [MTD Interface] MTD compability function for nand_do_read_ecc
+ * nand_read - [MTD Interface] MTD compatibility function for nand_do_read_ecc
  * @mtd:	MTD device structure
  * @from:	offset to read from
  * @len:	number of bytes to read
@@ -2377,7 +2378,7 @@
 		return -EINVAL;
 	}
 
-	/* Do not allow reads past end of device */
+	/* Do not allow write past end of device */
 	if (unlikely(to >= mtd->size ||
 		     ops->ooboffs + ops->ooblen >
 			((mtd->size >> chip->page_shift) -
@@ -3248,7 +3249,7 @@
 	/*
 	 * If no default placement scheme is given, select an appropriate one
 	 */
-	if (!chip->ecc.layout) {
+	if (!chip->ecc.layout && (chip->ecc.mode != NAND_ECC_SOFT_BCH)) {
 		switch (mtd->oobsize) {
 		case 8:
 			chip->ecc.layout = &nand_oob_8;
@@ -3351,6 +3352,40 @@
 		chip->ecc.bytes = 3;
 		break;
 
+	case NAND_ECC_SOFT_BCH:
+		if (!mtd_nand_has_bch()) {
+			printk(KERN_WARNING "CONFIG_MTD_ECC_BCH not enabled\n");
+			BUG();
+		}
+		chip->ecc.calculate = nand_bch_calculate_ecc;
+		chip->ecc.correct = nand_bch_correct_data;
+		chip->ecc.read_page = nand_read_page_swecc;
+		chip->ecc.read_subpage = nand_read_subpage;
+		chip->ecc.write_page = nand_write_page_swecc;
+		chip->ecc.read_page_raw = nand_read_page_raw;
+		chip->ecc.write_page_raw = nand_write_page_raw;
+		chip->ecc.read_oob = nand_read_oob_std;
+		chip->ecc.write_oob = nand_write_oob_std;
+		/*
+		 * Board driver should supply ecc.size and ecc.bytes values to
+		 * select how many bits are correctable; see nand_bch_init()
+		 * for details.
+		 * Otherwise, default to 4 bits for large page devices
+		 */
+		if (!chip->ecc.size && (mtd->oobsize >= 64)) {
+			chip->ecc.size = 512;
+			chip->ecc.bytes = 7;
+		}
+		chip->ecc.priv = nand_bch_init(mtd,
+					       chip->ecc.size,
+					       chip->ecc.bytes,
+					       &chip->ecc.layout);
+		if (!chip->ecc.priv) {
+			printk(KERN_WARNING "BCH ECC initialization failed!\n");
+			BUG();
+		}
+		break;
+
 	case NAND_ECC_NONE:
 		printk(KERN_WARNING "NAND_ECC_NONE selected by board driver. "
 		       "This is not recommended !!\n");
@@ -3501,6 +3536,9 @@
 {
 	struct nand_chip *chip = mtd->priv;
 
+	if (chip->ecc.mode == NAND_ECC_SOFT_BCH)
+		nand_bch_free((struct nand_bch_control *)chip->ecc.priv);
+
 #ifdef CONFIG_MTD_PARTITIONS
 	/* Deregister partitions */
 	del_mtd_partitions(mtd);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_bbt.c linux-libre-2.6.39-gnu/drivers/mtd/nand/nand_bbt.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_bbt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/nand_bbt.c	2011-05-19 00:06:34.000000000 -0400
@@ -945,7 +945,7 @@
 		rd2 = NULL;
 		/* Per chip or per device ? */
 		chipsel = (td->options & NAND_BBT_PERCHIP) ? i : -1;
-		/* Mirrored table avilable ? */
+		/* Mirrored table available ? */
 		if (md) {
 			if (td->pages[i] == -1 && md->pages[i] == -1) {
 				writeops = 0x03;
@@ -1101,12 +1101,16 @@
 static void verify_bbt_descr(struct mtd_info *mtd, struct nand_bbt_descr *bd)
 {
 	struct nand_chip *this = mtd->priv;
-	u32 pattern_len = bd->len;
-	u32 bits = bd->options & NAND_BBT_NRBITS_MSK;
+	u32 pattern_len;
+	u32 bits;
 	u32 table_size;
 
 	if (!bd)
 		return;
+
+	pattern_len = bd->len;
+	bits = bd->options & NAND_BBT_NRBITS_MSK;
+
 	BUG_ON((this->options & NAND_USE_FLASH_BBT_NO_OOB) &&
 			!(this->options & NAND_USE_FLASH_BBT));
 	BUG_ON(!bits);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_bch.c linux-libre-2.6.39-gnu/drivers/mtd/nand/nand_bch.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/nand_bch.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/nand_bch.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,243 @@
+/*
+ * This file provides ECC correction for more than 1 bit per block of data,
+ * using binary BCH codes. It relies on the generic BCH library lib/bch.c.
+ *
+ * Copyright Â© 2011 Ivan Djelic <ivan.djelic@parrot.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 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 file; 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/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/bitops.h>
+#include <linux/mtd/mtd.h>
+#include <linux/mtd/nand.h>
+#include <linux/mtd/nand_bch.h>
+#include <linux/bch.h>
+
+/**
+ * struct nand_bch_control - private NAND BCH control structure
+ * @bch:       BCH control structure
+ * @ecclayout: private ecc layout for this BCH configuration
+ * @errloc:    error location array
+ * @eccmask:   XOR ecc mask, allows erased pages to be decoded as valid
+ */
+struct nand_bch_control {
+	struct bch_control   *bch;
+	struct nand_ecclayout ecclayout;
+	unsigned int         *errloc;
+	unsigned char        *eccmask;
+};
+
+/**
+ * nand_bch_calculate_ecc - [NAND Interface] Calculate ECC for data block
+ * @mtd:	MTD block structure
+ * @buf:	input buffer with raw data
+ * @code:	output buffer with ECC
+ */
+int nand_bch_calculate_ecc(struct mtd_info *mtd, const unsigned char *buf,
+			   unsigned char *code)
+{
+	const struct nand_chip *chip = mtd->priv;
+	struct nand_bch_control *nbc = chip->ecc.priv;
+	unsigned int i;
+
+	memset(code, 0, chip->ecc.bytes);
+	encode_bch(nbc->bch, buf, chip->ecc.size, code);
+
+	/* apply mask so that an erased page is a valid codeword */
+	for (i = 0; i < chip->ecc.bytes; i++)
+		code[i] ^= nbc->eccmask[i];
+
+	return 0;
+}
+EXPORT_SYMBOL(nand_bch_calculate_ecc);
+
+/**
+ * nand_bch_correct_data - [NAND Interface] Detect and correct bit error(s)
+ * @mtd:	MTD block structure
+ * @buf:	raw data read from the chip
+ * @read_ecc:	ECC from the chip
+ * @calc_ecc:	the ECC calculated from raw data
+ *
+ * Detect and correct bit errors for a data byte block
+ */
+int nand_bch_correct_data(struct mtd_info *mtd, unsigned char *buf,
+			  unsigned char *read_ecc, unsigned char *calc_ecc)
+{
+	const struct nand_chip *chip = mtd->priv;
+	struct nand_bch_control *nbc = chip->ecc.priv;
+	unsigned int *errloc = nbc->errloc;
+	int i, count;
+
+	count = decode_bch(nbc->bch, NULL, chip->ecc.size, read_ecc, calc_ecc,
+			   NULL, errloc);
+	if (count > 0) {
+		for (i = 0; i < count; i++) {
+			if (errloc[i] < (chip->ecc.size*8))
+				/* error is located in data, correct it */
+				buf[errloc[i] >> 3] ^= (1 << (errloc[i] & 7));
+			/* else error in ecc, no action needed */
+
+			DEBUG(MTD_DEBUG_LEVEL0, "%s: corrected bitflip %u\n",
+			      __func__, errloc[i]);
+		}
+	} else if (count < 0) {
+		printk(KERN_ERR "ecc unrecoverable error\n");
+		count = -1;
+	}
+	return count;
+}
+EXPORT_SYMBOL(nand_bch_correct_data);
+
+/**
+ * nand_bch_init - [NAND Interface] Initialize NAND BCH error correction
+ * @mtd:	MTD block structure
+ * @eccsize:	ecc block size in bytes
+ * @eccbytes:	ecc length in bytes
+ * @ecclayout:	output default layout
+ *
+ * Returns:
+ *  a pointer to a new NAND BCH control structure, or NULL upon failure
+ *
+ * Initialize NAND BCH error correction. Parameters @eccsize and @eccbytes
+ * are used to compute BCH parameters m (Galois field order) and t (error
+ * correction capability). @eccbytes should be equal to the number of bytes
+ * required to store m*t bits, where m is such that 2^m-1 > @eccsize*8.
+ *
+ * Example: to configure 4 bit correction per 512 bytes, you should pass
+ * @eccsize = 512  (thus, m=13 is the smallest integer such that 2^m-1 > 512*8)
+ * @eccbytes = 7   (7 bytes are required to store m*t = 13*4 = 52 bits)
+ */
+struct nand_bch_control *
+nand_bch_init(struct mtd_info *mtd, unsigned int eccsize, unsigned int eccbytes,
+	      struct nand_ecclayout **ecclayout)
+{
+	unsigned int m, t, eccsteps, i;
+	struct nand_ecclayout *layout;
+	struct nand_bch_control *nbc = NULL;
+	unsigned char *erased_page;
+
+	if (!eccsize || !eccbytes) {
+		printk(KERN_WARNING "ecc parameters not supplied\n");
+		goto fail;
+	}
+
+	m = fls(1+8*eccsize);
+	t = (eccbytes*8)/m;
+
+	nbc = kzalloc(sizeof(*nbc), GFP_KERNEL);
+	if (!nbc)
+		goto fail;
+
+	nbc->bch = init_bch(m, t, 0);
+	if (!nbc->bch)
+		goto fail;
+
+	/* verify that eccbytes has the expected value */
+	if (nbc->bch->ecc_bytes != eccbytes) {
+		printk(KERN_WARNING "invalid eccbytes %u, should be %u\n",
+		       eccbytes, nbc->bch->ecc_bytes);
+		goto fail;
+	}
+
+	eccsteps = mtd->writesize/eccsize;
+
+	/* if no ecc placement scheme was provided, build one */
+	if (!*ecclayout) {
+
+		/* handle large page devices only */
+		if (mtd->oobsize < 64) {
+			printk(KERN_WARNING "must provide an oob scheme for "
+			       "oobsize %d\n", mtd->oobsize);
+			goto fail;
+		}
+
+		layout = &nbc->ecclayout;
+		layout->eccbytes = eccsteps*eccbytes;
+
+		/* reserve 2 bytes for bad block marker */
+		if (layout->eccbytes+2 > mtd->oobsize) {
+			printk(KERN_WARNING "no suitable oob scheme available "
+			       "for oobsize %d eccbytes %u\n", mtd->oobsize,
+			       eccbytes);
+			goto fail;
+		}
+		/* put ecc bytes at oob tail */
+		for (i = 0; i < layout->eccbytes; i++)
+			layout->eccpos[i] = mtd->oobsize-layout->eccbytes+i;
+
+		layout->oobfree[0].offset = 2;
+		layout->oobfree[0].length = mtd->oobsize-2-layout->eccbytes;
+
+		*ecclayout = layout;
+	}
+
+	/* sanity checks */
+	if (8*(eccsize+eccbytes) >= (1 << m)) {
+		printk(KERN_WARNING "eccsize %u is too large\n", eccsize);
+		goto fail;
+	}
+	if ((*ecclayout)->eccbytes != (eccsteps*eccbytes)) {
+		printk(KERN_WARNING "invalid ecc layout\n");
+		goto fail;
+	}
+
+	nbc->eccmask = kmalloc(eccbytes, GFP_KERNEL);
+	nbc->errloc = kmalloc(t*sizeof(*nbc->errloc), GFP_KERNEL);
+	if (!nbc->eccmask || !nbc->errloc)
+		goto fail;
+	/*
+	 * compute and store the inverted ecc of an erased ecc block
+	 */
+	erased_page = kmalloc(eccsize, GFP_KERNEL);
+	if (!erased_page)
+		goto fail;
+
+	memset(erased_page, 0xff, eccsize);
+	memset(nbc->eccmask, 0, eccbytes);
+	encode_bch(nbc->bch, erased_page, eccsize, nbc->eccmask);
+	kfree(erased_page);
+
+	for (i = 0; i < eccbytes; i++)
+		nbc->eccmask[i] ^= 0xff;
+
+	return nbc;
+fail:
+	nand_bch_free(nbc);
+	return NULL;
+}
+EXPORT_SYMBOL(nand_bch_init);
+
+/**
+ * nand_bch_free - [NAND Interface] Release NAND BCH ECC resources
+ * @nbc:	NAND BCH control structure
+ */
+void nand_bch_free(struct nand_bch_control *nbc)
+{
+	if (nbc) {
+		free_bch(nbc->bch);
+		kfree(nbc->errloc);
+		kfree(nbc->eccmask);
+		kfree(nbc);
+	}
+}
+EXPORT_SYMBOL(nand_bch_free);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ivan Djelic <ivan.djelic@parrot.com>");
+MODULE_DESCRIPTION("NAND software BCH ECC support");
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/nandsim.c linux-libre-2.6.39-gnu/drivers/mtd/nand/nandsim.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/nandsim.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/nandsim.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,7 @@
 #include <linux/string.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
+#include <linux/mtd/nand_bch.h>
 #include <linux/mtd/partitions.h>
 #include <linux/delay.h>
 #include <linux/list.h>
@@ -108,6 +109,7 @@
 static unsigned int overridesize = 0;
 static char *cache_file = NULL;
 static unsigned int bbt;
+static unsigned int bch;
 
 module_param(first_id_byte,  uint, 0400);
 module_param(second_id_byte, uint, 0400);
@@ -132,6 +134,7 @@
 module_param(overridesize,   uint, 0400);
 module_param(cache_file,     charp, 0400);
 module_param(bbt,	     uint, 0400);
+module_param(bch,	     uint, 0400);
 
 MODULE_PARM_DESC(first_id_byte,  "The first byte returned by NAND Flash 'read ID' command (manufacturer ID)");
 MODULE_PARM_DESC(second_id_byte, "The second byte returned by NAND Flash 'read ID' command (chip ID)");
@@ -159,12 +162,14 @@
 MODULE_PARM_DESC(gravepages,     "Pages that lose data [: maximum reads (defaults to 3)]"
 				 " separated by commas e.g. 1401:2 means page 1401"
 				 " can be read only twice before failing");
-MODULE_PARM_DESC(rptwear,        "Number of erases inbetween reporting wear, if not zero");
+MODULE_PARM_DESC(rptwear,        "Number of erases between reporting wear, if not zero");
 MODULE_PARM_DESC(overridesize,   "Specifies the NAND Flash size overriding the ID bytes. "
 				 "The size is specified in erase blocks and as the exponent of a power of two"
 				 " e.g. 5 means a size of 32 erase blocks");
 MODULE_PARM_DESC(cache_file,     "File to use to cache nand pages instead of memory");
 MODULE_PARM_DESC(bbt,		 "0 OOB, 1 BBT with marker in OOB, 2 BBT with marker in data area");
+MODULE_PARM_DESC(bch,		 "Enable BCH ecc and set how many bits should "
+				 "be correctable in 512-byte blocks");
 
 /* The largest possible page size */
 #define NS_LARGEST_PAGE_SIZE	4096
@@ -2309,7 +2314,43 @@
 	if ((retval = parse_gravepages()) != 0)
 		goto error;
 
-	if ((retval = nand_scan(nsmtd, 1)) != 0) {
+	retval = nand_scan_ident(nsmtd, 1, NULL);
+	if (retval) {
+		NS_ERR("cannot scan NAND Simulator device\n");
+		if (retval > 0)
+			retval = -ENXIO;
+		goto error;
+	}
+
+	if (bch) {
+		unsigned int eccsteps, eccbytes;
+		if (!mtd_nand_has_bch()) {
+			NS_ERR("BCH ECC support is disabled\n");
+			retval = -EINVAL;
+			goto error;
+		}
+		/* use 512-byte ecc blocks */
+		eccsteps = nsmtd->writesize/512;
+		eccbytes = (bch*13+7)/8;
+		/* do not bother supporting small page devices */
+		if ((nsmtd->oobsize < 64) || !eccsteps) {
+			NS_ERR("bch not available on small page devices\n");
+			retval = -EINVAL;
+			goto error;
+		}
+		if ((eccbytes*eccsteps+2) > nsmtd->oobsize) {
+			NS_ERR("invalid bch value %u\n", bch);
+			retval = -EINVAL;
+			goto error;
+		}
+		chip->ecc.mode = NAND_ECC_SOFT_BCH;
+		chip->ecc.size = 512;
+		chip->ecc.bytes = eccbytes;
+		NS_INFO("using %u-bit/%u bytes BCH ECC\n", bch, chip->ecc.size);
+	}
+
+	retval = nand_scan_tail(nsmtd);
+	if (retval) {
 		NS_ERR("can't register NAND Simulator\n");
 		if (retval > 0)
 			retval = -ENXIO;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/ndfc.c linux-libre-2.6.39-gnu/drivers/mtd/nand/ndfc.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/ndfc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/ndfc.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,8 +225,7 @@
 	return ret;
 }
 
-static int __devinit ndfc_probe(struct platform_device *ofdev,
-				const struct of_device_id *match)
+static int __devinit ndfc_probe(struct platform_device *ofdev)
 {
 	struct ndfc_controller *ndfc = &ndfc_ctrl;
 	const __be32 *reg;
@@ -292,7 +291,7 @@
 };
 MODULE_DEVICE_TABLE(of, ndfc_match);
 
-static struct of_platform_driver ndfc_driver = {
+static struct platform_driver ndfc_driver = {
 	.driver = {
 		.name = "ndfc",
 		.owner = THIS_MODULE,
@@ -304,12 +303,12 @@
 
 static int __init ndfc_nand_init(void)
 {
-	return of_register_platform_driver(&ndfc_driver);
+	return platform_driver_register(&ndfc_driver);
 }
 
 static void __exit ndfc_nand_exit(void)
 {
-	of_unregister_platform_driver(&ndfc_driver);
+	platform_driver_unregister(&ndfc_driver);
 }
 
 module_init(ndfc_nand_init);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/nomadik_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/nomadik_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/nomadik_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/nomadik_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,7 +151,7 @@
 	nand->options = pdata->options;
 
 	/*
-	 * Scan to find existance of the device
+	 * Scan to find existence of the device
 	 */
 	if (nand_scan(&host->mtd, 1)) {
 		ret = -ENXIO;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/omap2.c linux-libre-2.6.39-gnu/drivers/mtd/nand/omap2.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/omap2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/omap2.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,6 +11,7 @@
 #include <linux/platform_device.h>
 #include <linux/dma-mapping.h>
 #include <linux/delay.h>
+#include <linux/interrupt.h>
 #include <linux/jiffies.h>
 #include <linux/sched.h>
 #include <linux/mtd/mtd.h>
@@ -24,6 +25,7 @@
 #include <plat/nand.h>
 
 #define	DRIVER_NAME	"omap2-nand"
+#define	OMAP_NAND_TIMEOUT_MS	5000
 
 #define NAND_Ecc_P1e		(1 << 0)
 #define NAND_Ecc_P2e		(1 << 1)
@@ -96,26 +98,19 @@
 static const char *part_probes[] = { "cmdlinepart", NULL };
 #endif
 
-#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH
-static int use_prefetch = 1;
-
-/* "modprobe ... use_prefetch=0" etc */
-module_param(use_prefetch, bool, 0);
-MODULE_PARM_DESC(use_prefetch, "enable/disable use of PREFETCH");
-
-#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
-static int use_dma = 1;
+/* oob info generated runtime depending on ecc algorithm and layout selected */
+static struct nand_ecclayout omap_oobinfo;
+/* Define some generic bad / good block scan pattern which are used
+ * while scanning a device for factory marked good / bad blocks
+ */
+static uint8_t scan_ff_pattern[] = { 0xff };
+static struct nand_bbt_descr bb_descrip_flashbased = {
+	.options = NAND_BBT_SCANEMPTY | NAND_BBT_SCANALLPAGES,
+	.offs = 0,
+	.len = 1,
+	.pattern = scan_ff_pattern,
+};
 
-/* "modprobe ... use_dma=0" etc */
-module_param(use_dma, bool, 0);
-MODULE_PARM_DESC(use_dma, "enable/disable use of DMA");
-#else
-static const int use_dma;
-#endif
-#else
-const int use_prefetch;
-static const int use_dma;
-#endif
 
 struct omap_nand_info {
 	struct nand_hw_control		controller;
@@ -129,6 +124,13 @@
 	unsigned long			phys_base;
 	struct completion		comp;
 	int				dma_ch;
+	int				gpmc_irq;
+	enum {
+		OMAP_NAND_IO_READ = 0,	/* read */
+		OMAP_NAND_IO_WRITE,	/* write */
+	} iomode;
+	u_char				*buf;
+	int					buf_len;
 };
 
 /**
@@ -256,7 +258,8 @@
 	}
 
 	/* configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x0);
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x0);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -288,9 +291,10 @@
 {
 	struct omap_nand_info *info = container_of(mtd,
 						struct omap_nand_info, mtd);
-	uint32_t pref_count = 0, w_count = 0;
+	uint32_t w_count = 0;
 	int i = 0, ret = 0;
 	u16 *p;
+	unsigned long tim, limit;
 
 	/* take care of subpage writes */
 	if (len % 2 != 0) {
@@ -300,7 +304,8 @@
 	}
 
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs, 0x0, len, 0x1);
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x0, len, 0x1);
 	if (ret) {
 		/* PFPW engine is busy, use cpu copy method */
 		if (info->nand.options & NAND_BUSWIDTH_16)
@@ -316,15 +321,17 @@
 				iowrite16(*p++, info->nand.IO_ADDR_W);
 		}
 		/* wait for data to flushed-out before reset the prefetch */
-		do {
-			pref_count = gpmc_read_status(GPMC_PREFETCH_COUNT);
-		} while (pref_count);
+		tim = 0;
+		limit = (loops_per_jiffy *
+					msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
+		while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+			cpu_relax();
+
 		/* disable and stop the PFPW engine */
 		gpmc_prefetch_reset(info->gpmc_cs);
 	}
 }
 
-#ifdef CONFIG_MTD_NAND_OMAP_PREFETCH_DMA
 /*
  * omap_nand_dma_cb: callback on the completion of dma transfer
  * @lch: logical channel
@@ -348,14 +355,15 @@
 {
 	struct omap_nand_info *info = container_of(mtd,
 					struct omap_nand_info, mtd);
-	uint32_t prefetch_status = 0;
 	enum dma_data_direction dir = is_write ? DMA_TO_DEVICE :
 							DMA_FROM_DEVICE;
 	dma_addr_t dma_addr;
 	int ret;
+	unsigned long tim, limit;
 
-	/* The fifo depth is 64 bytes. We have a sync at each frame and frame
-	 * length is 64 bytes.
+	/* The fifo depth is 64 bytes max.
+	 * But configure the FIFO-threahold to 32 to get a sync at each frame
+	 * and frame length is 32 bytes.
 	 */
 	int buf_len = len >> 6;
 
@@ -396,9 +404,10 @@
 					OMAP24XX_DMA_GPMC, OMAP_DMA_SRC_SYNC);
 	}
 	/*  configure and start prefetch transfer */
-	ret = gpmc_prefetch_enable(info->gpmc_cs, 0x1, len, is_write);
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX, 0x1, len, is_write);
 	if (ret)
-		/* PFPW engine is busy, use cpu copy methode */
+		/* PFPW engine is busy, use cpu copy method */
 		goto out_copy;
 
 	init_completion(&info->comp);
@@ -407,10 +416,11 @@
 
 	/* setup and start DMA using dma_addr */
 	wait_for_completion(&info->comp);
+	tim = 0;
+	limit = (loops_per_jiffy * msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
+	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		cpu_relax();
 
-	do {
-		prefetch_status = gpmc_read_status(GPMC_PREFETCH_COUNT);
-	} while (prefetch_status);
 	/* disable and stop the PFPW engine */
 	gpmc_prefetch_reset(info->gpmc_cs);
 
@@ -426,14 +436,6 @@
 			: omap_write_buf8(mtd, (u_char *) addr, len);
 	return 0;
 }
-#else
-static void omap_nand_dma_cb(int lch, u16 ch_status, void *data) {}
-static inline int omap_nand_dma_transfer(struct mtd_info *mtd, void *addr,
-					unsigned int len, int is_write)
-{
-	return 0;
-}
-#endif
 
 /**
  * omap_read_buf_dma_pref - read data from NAND controller into buffer
@@ -466,6 +468,157 @@
 		omap_nand_dma_transfer(mtd, (u_char *) buf, len, 0x1);
 }
 
+/*
+ * omap_nand_irq - GMPC irq handler
+ * @this_irq: gpmc irq number
+ * @dev: omap_nand_info structure pointer is passed here
+ */
+static irqreturn_t omap_nand_irq(int this_irq, void *dev)
+{
+	struct omap_nand_info *info = (struct omap_nand_info *) dev;
+	u32 bytes;
+	u32 irq_stat;
+
+	irq_stat = gpmc_read_status(GPMC_GET_IRQ_STATUS);
+	bytes = gpmc_read_status(GPMC_PREFETCH_FIFO_CNT);
+	bytes = bytes  & 0xFFFC; /* io in multiple of 4 bytes */
+	if (info->iomode == OMAP_NAND_IO_WRITE) { /* checks for write io */
+		if (irq_stat & 0x2)
+			goto done;
+
+		if (info->buf_len && (info->buf_len < bytes))
+			bytes = info->buf_len;
+		else if (!info->buf_len)
+			bytes = 0;
+		iowrite32_rep(info->nand.IO_ADDR_W,
+						(u32 *)info->buf, bytes >> 2);
+		info->buf = info->buf + bytes;
+		info->buf_len -= bytes;
+
+	} else {
+		ioread32_rep(info->nand.IO_ADDR_R,
+						(u32 *)info->buf, bytes >> 2);
+		info->buf = info->buf + bytes;
+
+		if (irq_stat & 0x2)
+			goto done;
+	}
+	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+
+	return IRQ_HANDLED;
+
+done:
+	complete(&info->comp);
+	/* disable irq */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ, 0);
+
+	/* clear status */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_SET_IRQ_STATUS, irq_stat);
+
+	return IRQ_HANDLED;
+}
+
+/*
+ * omap_read_buf_irq_pref - 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_buf_irq_pref(struct mtd_info *mtd, u_char *buf, int len)
+{
+	struct omap_nand_info *info = container_of(mtd,
+						struct omap_nand_info, mtd);
+	int ret = 0;
+
+	if (len <= mtd->oobsize) {
+		omap_read_buf_pref(mtd, buf, len);
+		return;
+	}
+
+	info->iomode = OMAP_NAND_IO_READ;
+	info->buf = buf;
+	init_completion(&info->comp);
+
+	/*  configure and start prefetch transfer */
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			PREFETCH_FIFOTHRESHOLD_MAX/2, 0x0, len, 0x0);
+	if (ret)
+		/* PFPW engine is busy, use cpu copy method */
+		goto out_copy;
+
+	info->buf_len = len;
+	/* enable irq */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
+		(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	/* waiting for read to complete */
+	wait_for_completion(&info->comp);
+
+	/* disable and stop the PFPW engine */
+	gpmc_prefetch_reset(info->gpmc_cs);
+	return;
+
+out_copy:
+	if (info->nand.options & NAND_BUSWIDTH_16)
+		omap_read_buf16(mtd, buf, len);
+	else
+		omap_read_buf8(mtd, buf, len);
+}
+
+/*
+ * omap_write_buf_irq_pref - write buffer to NAND controller
+ * @mtd: MTD device structure
+ * @buf: data buffer
+ * @len: number of bytes to write
+ */
+static void omap_write_buf_irq_pref(struct mtd_info *mtd,
+					const u_char *buf, int len)
+{
+	struct omap_nand_info *info = container_of(mtd,
+						struct omap_nand_info, mtd);
+	int ret = 0;
+	unsigned long tim, limit;
+
+	if (len <= mtd->oobsize) {
+		omap_write_buf_pref(mtd, buf, len);
+		return;
+	}
+
+	info->iomode = OMAP_NAND_IO_WRITE;
+	info->buf = (u_char *) buf;
+	init_completion(&info->comp);
+
+	/* configure and start prefetch transfer : size=24 */
+	ret = gpmc_prefetch_enable(info->gpmc_cs,
+			(PREFETCH_FIFOTHRESHOLD_MAX * 3) / 8, 0x0, len, 0x1);
+	if (ret)
+		/* PFPW engine is busy, use cpu copy method */
+		goto out_copy;
+
+	info->buf_len = len;
+	/* enable irq */
+	gpmc_cs_configure(info->gpmc_cs, GPMC_ENABLE_IRQ,
+			(GPMC_IRQ_FIFOEVENTENABLE | GPMC_IRQ_COUNT_EVENT));
+
+	/* waiting for write to complete */
+	wait_for_completion(&info->comp);
+	/* wait for data to flushed-out before reset the prefetch */
+	tim = 0;
+	limit = (loops_per_jiffy *  msecs_to_jiffies(OMAP_NAND_TIMEOUT_MS));
+	while (gpmc_read_status(GPMC_PREFETCH_COUNT) && (tim++ < limit))
+		cpu_relax();
+
+	/* disable and stop the PFPW engine */
+	gpmc_prefetch_reset(info->gpmc_cs);
+	return;
+
+out_copy:
+	if (info->nand.options & NAND_BUSWIDTH_16)
+		omap_write_buf16(mtd, buf, len);
+	else
+		omap_write_buf8(mtd, buf, len);
+}
+
 /**
  * omap_verify_buf - Verify chip data against buffer
  * @mtd: MTD device structure
@@ -487,8 +640,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_MTD_NAND_OMAP_HWECC
-
 /**
  * gen_true_ecc - This function will generate true ECC value
  * @ecc_buf: buffer to store ecc code
@@ -517,6 +668,8 @@
  *
  * 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.
+ * If there is no error, %0 is returned. If there is an error but it
+ * was corrected, %1 is returned. Otherwise, %-1 is returned.
  */
 static int omap_compare_ecc(u8 *ecc_data1,	/* read from NAND memory */
 			    u8 *ecc_data2,	/* read from register */
@@ -622,7 +775,7 @@
 
 		page_data[find_byte] ^= (1 << find_bit);
 
-		return 0;
+		return 1;
 	default:
 		if (isEccFF) {
 			if (ecc_data2[0] == 0 &&
@@ -643,8 +796,11 @@
  * @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.
+ * and if ECC's mismatched, it will call 'omap_compare_ecc' for error
+ * detection and correction. If there are no errors, %0 is returned. If
+ * there were errors and all of the errors were corrected, the number of
+ * corrected errors is returned. If uncorrectable errors exist, %-1 is
+ * returned.
  */
 static int omap_correct_data(struct mtd_info *mtd, u_char *dat,
 				u_char *read_ecc, u_char *calc_ecc)
@@ -652,6 +808,7 @@
 	struct omap_nand_info *info = container_of(mtd, struct omap_nand_info,
 							mtd);
 	int blockCnt = 0, i = 0, ret = 0;
+	int stat = 0;
 
 	/* Ex NAND_ECC_HW12_2048 */
 	if ((info->nand.ecc.mode == NAND_ECC_HW) &&
@@ -665,12 +822,14 @@
 			ret = omap_compare_ecc(read_ecc, calc_ecc, dat);
 			if (ret < 0)
 				return ret;
+			/* keep track of the number of corrected errors */
+			stat += ret;
 		}
 		read_ecc += 3;
 		calc_ecc += 3;
 		dat      += 512;
 	}
-	return 0;
+	return stat;
 }
 
 /**
@@ -708,8 +867,6 @@
 	gpmc_enable_hwecc(info->gpmc_cs, mode, dev_width, info->nand.ecc.size);
 }
 
-#endif
-
 /**
  * omap_wait - wait until the command is done
  * @mtd: MTD device structure
@@ -779,6 +936,7 @@
 	struct omap_nand_info		*info;
 	struct omap_nand_platform_data	*pdata;
 	int				err;
+	int				i, offset;
 
 	pdata = pdev->dev.platform_data;
 	if (pdata == NULL) {
@@ -804,7 +962,7 @@
 	info->mtd.name		= dev_name(&pdev->dev);
 	info->mtd.owner		= THIS_MODULE;
 
-	info->nand.options	|= pdata->devsize ? NAND_BUSWIDTH_16 : 0;
+	info->nand.options	= pdata->devsize;
 	info->nand.options	|= NAND_SKIP_BBTSCAN;
 
 	/* NAND write protect off */
@@ -842,28 +1000,13 @@
 		info->nand.chip_delay = 50;
 	}
 
-	if (use_prefetch) {
-
+	switch (pdata->xfer_type) {
+	case NAND_OMAP_PREFETCH_POLLED:
 		info->nand.read_buf   = omap_read_buf_pref;
 		info->nand.write_buf  = omap_write_buf_pref;
-		if (use_dma) {
-			err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
-				omap_nand_dma_cb, &info->comp, &info->dma_ch);
-			if (err < 0) {
-				info->dma_ch = -1;
-				printk(KERN_WARNING "DMA request failed."
-					" Non-dma data transfer mode\n");
-			} else {
-				omap_set_dma_dest_burst_mode(info->dma_ch,
-						OMAP_DMA_DATA_BURST_16);
-				omap_set_dma_src_burst_mode(info->dma_ch,
-						OMAP_DMA_DATA_BURST_16);
+		break;
 
-				info->nand.read_buf   = omap_read_buf_dma_pref;
-				info->nand.write_buf  = omap_write_buf_dma_pref;
-			}
-		}
-	} else {
+	case NAND_OMAP_POLLED:
 		if (info->nand.options & NAND_BUSWIDTH_16) {
 			info->nand.read_buf   = omap_read_buf16;
 			info->nand.write_buf  = omap_write_buf16;
@@ -871,20 +1014,61 @@
 			info->nand.read_buf   = omap_read_buf8;
 			info->nand.write_buf  = omap_write_buf8;
 		}
+		break;
+
+	case NAND_OMAP_PREFETCH_DMA:
+		err = omap_request_dma(OMAP24XX_DMA_GPMC, "NAND",
+				omap_nand_dma_cb, &info->comp, &info->dma_ch);
+		if (err < 0) {
+			info->dma_ch = -1;
+			dev_err(&pdev->dev, "DMA request failed!\n");
+			goto out_release_mem_region;
+		} else {
+			omap_set_dma_dest_burst_mode(info->dma_ch,
+					OMAP_DMA_DATA_BURST_16);
+			omap_set_dma_src_burst_mode(info->dma_ch,
+					OMAP_DMA_DATA_BURST_16);
+
+			info->nand.read_buf   = omap_read_buf_dma_pref;
+			info->nand.write_buf  = omap_write_buf_dma_pref;
+		}
+		break;
+
+	case NAND_OMAP_PREFETCH_IRQ:
+		err = request_irq(pdata->gpmc_irq,
+				omap_nand_irq, IRQF_SHARED, "gpmc-nand", info);
+		if (err) {
+			dev_err(&pdev->dev, "requesting irq(%d) error:%d",
+							pdata->gpmc_irq, err);
+			goto out_release_mem_region;
+		} else {
+			info->gpmc_irq	     = pdata->gpmc_irq;
+			info->nand.read_buf  = omap_read_buf_irq_pref;
+			info->nand.write_buf = omap_write_buf_irq_pref;
+		}
+		break;
+
+	default:
+		dev_err(&pdev->dev,
+			"xfer_type(%d) not supported!\n", pdata->xfer_type);
+		err = -EINVAL;
+		goto out_release_mem_region;
 	}
-	info->nand.verify_buf = omap_verify_buf;
 
-#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;
+	info->nand.verify_buf = omap_verify_buf;
 
-#else
-	info->nand.ecc.mode = NAND_ECC_SOFT;
-#endif
+	/* selsect the ecc type */
+	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_DEFAULT)
+		info->nand.ecc.mode = NAND_ECC_SOFT;
+	else if ((pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW) ||
+		(pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE)) {
+		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;
+	}
 
 	/* DIP switches on some boards change between 8 and 16 bit
 	 * bus widths for flash.  Try the other width if the first try fails.
@@ -897,6 +1081,26 @@
 		}
 	}
 
+	/* rom code layout */
+	if (pdata->ecc_opt == OMAP_ECC_HAMMING_CODE_HW_ROMCODE) {
+
+		if (info->nand.options & NAND_BUSWIDTH_16)
+			offset = 2;
+		else {
+			offset = 1;
+			info->nand.badblock_pattern = &bb_descrip_flashbased;
+		}
+		omap_oobinfo.eccbytes = 3 * (info->mtd.oobsize/16);
+		for (i = 0; i < omap_oobinfo.eccbytes; i++)
+			omap_oobinfo.eccpos[i] = i+offset;
+
+		omap_oobinfo.oobfree->offset = offset + omap_oobinfo.eccbytes;
+		omap_oobinfo.oobfree->length = info->mtd.oobsize -
+					(offset + omap_oobinfo.eccbytes);
+
+		info->nand.ecc.layout = &omap_oobinfo;
+	}
+
 #ifdef CONFIG_MTD_PARTITIONS
 	err = parse_mtd_partitions(&info->mtd, part_probes, &info->parts, 0);
 	if (err > 0)
@@ -926,9 +1130,12 @@
 							mtd);
 
 	platform_set_drvdata(pdev, NULL);
-	if (use_dma)
+	if (info->dma_ch != -1)
 		omap_free_dma(info->dma_ch);
 
+	if (info->gpmc_irq)
+		free_irq(info->gpmc_irq, info);
+
 	/* Release NAND device, its internal structures and partitions */
 	nand_release(&info->mtd);
 	iounmap(info->nand.IO_ADDR_R);
@@ -947,16 +1154,8 @@
 
 static int __init omap_nand_init(void)
 {
-	printk(KERN_INFO "%s driver initializing\n", DRIVER_NAME);
+	pr_info("%s driver initializing\n", DRIVER_NAME);
 
-	/* This check is required if driver is being
-	 * loaded run time as a module
-	 */
-	if ((1 == use_dma) && (0 == use_prefetch)) {
-		printk(KERN_INFO"Wrong parameters: 'use_dma' can not be 1 "
-				"without use_prefetch'. Prefetch will not be"
-				" used in either mode (mpu or dma)\n");
-	}
 	return platform_driver_register(&omap_nand_driver);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/pasemi_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/pasemi_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/pasemi_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/pasemi_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,8 +89,7 @@
 	return !!(inl(lpcctl) & LBICTRL_LPCCTL_NR);
 }
 
-static int __devinit pasemi_nand_probe(struct platform_device *ofdev,
-				      const struct of_device_id *match)
+static int __devinit pasemi_nand_probe(struct platform_device *ofdev)
 {
 	struct pci_dev *pdev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -158,7 +157,7 @@
 	/* Enable the following for a flash based bad block table */
 	chip->options = NAND_USE_FLASH_BBT | NAND_NO_AUTOINCR;
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(pasemi_nand_mtd, 1)) {
 		err = -ENXIO;
 		goto out_lpc;
@@ -219,7 +218,7 @@
 
 MODULE_DEVICE_TABLE(of, pasemi_nand_match);
 
-static struct of_platform_driver pasemi_nand_driver =
+static struct platform_driver pasemi_nand_driver =
 {
 	.driver = {
 		.name = (char*)driver_name,
@@ -232,13 +231,13 @@
 
 static int __init pasemi_nand_init(void)
 {
-	return of_register_platform_driver(&pasemi_nand_driver);
+	return platform_driver_register(&pasemi_nand_driver);
 }
 module_init(pasemi_nand_init);
 
 static void __exit pasemi_nand_exit(void)
 {
-	of_unregister_platform_driver(&pasemi_nand_driver);
+	platform_driver_unregister(&pasemi_nand_driver);
 }
 module_exit(pasemi_nand_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/plat_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/plat_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/plat_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/plat_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,7 +95,7 @@
 			goto out;
 	}
 
-	/* Scan to find existance of the device */
+	/* Scan to find existence of the device */
 	if (nand_scan(&data->mtd, pdata->chip.nr_chips)) {
 		err = -ENXIO;
 		goto out;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/pxa3xx_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/pxa3xx_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/pxa3xx_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/pxa3xx_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,8 @@
 #include <plat/pxa3xx_nand.h>
 
 #define	CHIP_DELAY_TIMEOUT	(2 * HZ/10)
+#define NAND_STOP_DELAY		(2 * HZ/50)
+#define PAGE_CHUNK_SIZE		(2048)
 
 /* registers and bit definitions */
 #define NDCR		(0x00) /* Control register */
@@ -52,16 +54,18 @@
 #define NDCR_ND_MODE		(0x3 << 21)
 #define NDCR_NAND_MODE   	(0x0)
 #define NDCR_CLR_PG_CNT		(0x1 << 20)
-#define NDCR_CLR_ECC		(0x1 << 19)
+#define NDCR_STOP_ON_UNCOR	(0x1 << 19)
 #define NDCR_RD_ID_CNT_MASK	(0x7 << 16)
 #define NDCR_RD_ID_CNT(x)	(((x) << 16) & NDCR_RD_ID_CNT_MASK)
 
 #define NDCR_RA_START		(0x1 << 15)
 #define NDCR_PG_PER_BLK		(0x1 << 14)
 #define NDCR_ND_ARB_EN		(0x1 << 12)
+#define NDCR_INT_MASK           (0xFFF)
 
 #define NDSR_MASK		(0xfff)
-#define NDSR_RDY		(0x1 << 11)
+#define NDSR_RDY                (0x1 << 12)
+#define NDSR_FLASH_RDY          (0x1 << 11)
 #define NDSR_CS0_PAGED		(0x1 << 10)
 #define NDSR_CS1_PAGED		(0x1 << 9)
 #define NDSR_CS0_CMDD		(0x1 << 8)
@@ -74,6 +78,7 @@
 #define NDSR_RDDREQ		(0x1 << 1)
 #define NDSR_WRCMDREQ		(0x1)
 
+#define NDCB0_ST_ROW_EN         (0x1 << 26)
 #define NDCB0_AUTO_RS		(0x1 << 25)
 #define NDCB0_CSEL		(0x1 << 24)
 #define NDCB0_CMD_TYPE_MASK	(0x7 << 21)
@@ -104,18 +109,21 @@
 };
 
 enum {
-	STATE_READY	= 0,
+	STATE_IDLE = 0,
 	STATE_CMD_HANDLE,
 	STATE_DMA_READING,
 	STATE_DMA_WRITING,
 	STATE_DMA_DONE,
 	STATE_PIO_READING,
 	STATE_PIO_WRITING,
+	STATE_CMD_DONE,
+	STATE_READY,
 };
 
 struct pxa3xx_nand_info {
 	struct nand_chip	nand_chip;
 
+	struct nand_hw_control	controller;
 	struct platform_device	 *pdev;
 	struct pxa3xx_nand_cmdset *cmdset;
 
@@ -126,6 +134,7 @@
 	unsigned int 		buf_start;
 	unsigned int		buf_count;
 
+	struct mtd_info         *mtd;
 	/* DMA information */
 	int			drcmr_dat;
 	int			drcmr_cmd;
@@ -149,6 +158,7 @@
 
 	int			use_ecc;	/* use HW ECC ? */
 	int			use_dma;	/* use DMA ? */
+	int			is_ready;
 
 	unsigned int		page_size;	/* page size of attached chip */
 	unsigned int		data_size;	/* data size in FIFO */
@@ -174,7 +184,7 @@
 
 static int use_dma = 1;
 module_param(use_dma, bool, 0444);
-MODULE_PARM_DESC(use_dma, "enable DMA for data transfering to/from NAND HW");
+MODULE_PARM_DESC(use_dma, "enable DMA for data transferring to/from NAND HW");
 
 /*
  * Default NAND flash controller configuration setup by the
@@ -201,20 +211,22 @@
 };
 
 static struct pxa3xx_nand_flash builtin_flash_types[] = {
-	{      0,   0, 2048,  8,  8,    0, &default_cmdset, &timing[0] },
-	{ 0x46ec,  32,  512, 16, 16, 4096, &default_cmdset, &timing[1] },
-	{ 0xdaec,  64, 2048,  8,  8, 2048, &default_cmdset, &timing[1] },
-	{ 0xd7ec, 128, 4096,  8,  8, 8192, &default_cmdset, &timing[1] },
-	{ 0xa12c,  64, 2048,  8,  8, 1024, &default_cmdset, &timing[2] },
-	{ 0xb12c,  64, 2048, 16, 16, 1024, &default_cmdset, &timing[2] },
-	{ 0xdc2c,  64, 2048,  8,  8, 4096, &default_cmdset, &timing[2] },
-	{ 0xcc2c,  64, 2048, 16, 16, 4096, &default_cmdset, &timing[2] },
-	{ 0xba20,  64, 2048, 16, 16, 2048, &default_cmdset, &timing[3] },
+{ "DEFAULT FLASH",      0,   0, 2048,  8,  8,    0, &timing[0] },
+{ "64MiB 16-bit",  0x46ec,  32,  512, 16, 16, 4096, &timing[1] },
+{ "256MiB 8-bit",  0xdaec,  64, 2048,  8,  8, 2048, &timing[1] },
+{ "4GiB 8-bit",    0xd7ec, 128, 4096,  8,  8, 8192, &timing[1] },
+{ "128MiB 8-bit",  0xa12c,  64, 2048,  8,  8, 1024, &timing[2] },
+{ "128MiB 16-bit", 0xb12c,  64, 2048, 16, 16, 1024, &timing[2] },
+{ "512MiB 8-bit",  0xdc2c,  64, 2048,  8,  8, 4096, &timing[2] },
+{ "512MiB 16-bit", 0xcc2c,  64, 2048, 16, 16, 4096, &timing[2] },
+{ "256MiB 16-bit", 0xba20,  64, 2048, 16, 16, 2048, &timing[3] },
 };
 
 /* Define a default flash type setting serve as flash detecting only */
 #define DEFAULT_FLASH_TYPE (&builtin_flash_types[0])
 
+const char *mtd_names[] = {"pxa3xx_nand-0", NULL};
+
 #define NDTR0_tCH(c)	(min((c), 7) << 19)
 #define NDTR0_tCS(c)	(min((c), 7) << 16)
 #define NDTR0_tWH(c)	(min((c), 7) << 11)
@@ -252,25 +264,6 @@
 	nand_writel(info, NDTR1CS0, ndtr1);
 }
 
-#define WAIT_EVENT_TIMEOUT	10
-
-static int wait_for_event(struct pxa3xx_nand_info *info, uint32_t event)
-{
-	int timeout = WAIT_EVENT_TIMEOUT;
-	uint32_t ndsr;
-
-	while (timeout--) {
-		ndsr = nand_readl(info, NDSR) & NDSR_MASK;
-		if (ndsr & event) {
-			nand_writel(info, NDSR, ndsr);
-			return 0;
-		}
-		udelay(10);
-	}
-
-	return -ETIMEDOUT;
-}
-
 static void pxa3xx_set_datasize(struct pxa3xx_nand_info *info)
 {
 	int oob_enable = info->reg_ndcr & NDCR_SPARE_EN;
@@ -291,69 +284,45 @@
 	}
 }
 
-static int prepare_read_prog_cmd(struct pxa3xx_nand_info *info,
-		uint16_t cmd, int column, int page_addr)
+/**
+ * NOTE: it is a must to set ND_RUN firstly, then write
+ * command buffer, otherwise, it does not work.
+ * We enable all the interrupt at the same time, and
+ * let pxa3xx_nand_irq to handle all logic.
+ */
+static void pxa3xx_nand_start(struct pxa3xx_nand_info *info)
 {
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	pxa3xx_set_datasize(info);
-
-	/* generate values for NDCBx registers */
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb1 = 0;
-	info->ndcb2 = 0;
-	info->ndcb0 |= NDCB0_ADDR_CYC(info->row_addr_cycles + info->col_addr_cycles);
-
-	if (info->col_addr_cycles == 2) {
-		/* large block, 2 cycles for column address
-		 * row address starts from 3rd cycle
-		 */
-		info->ndcb1 |= page_addr << 16;
-		if (info->row_addr_cycles == 3)
-			info->ndcb2 = (page_addr >> 16) & 0xff;
-	} else
-		/* small block, 1 cycles for column address
-		 * row address starts from 2nd cycle
-		 */
-		info->ndcb1 = page_addr << 8;
-
-	if (cmd == cmdset->program)
-		info->ndcb0 |= NDCB0_CMD_TYPE(1) | NDCB0_AUTO_RS;
+	uint32_t ndcr;
 
-	return 0;
-}
+	ndcr = info->reg_ndcr;
+	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
+	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
+	ndcr |= NDCR_ND_RUN;
 
-static int prepare_erase_cmd(struct pxa3xx_nand_info *info,
-			uint16_t cmd, int page_addr)
-{
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb0 |= NDCB0_CMD_TYPE(2) | NDCB0_AUTO_RS | NDCB0_ADDR_CYC(3);
-	info->ndcb1 = page_addr;
-	info->ndcb2 = 0;
-	return 0;
+	/* clear status bits and run */
+	nand_writel(info, NDCR, 0);
+	nand_writel(info, NDSR, NDSR_MASK);
+	nand_writel(info, NDCR, ndcr);
 }
 
-static int prepare_other_cmd(struct pxa3xx_nand_info *info, uint16_t cmd)
+static void pxa3xx_nand_stop(struct pxa3xx_nand_info *info)
 {
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-
-	info->ndcb0 = cmd | ((cmd & 0xff00) ? NDCB0_DBC : 0);
-	info->ndcb1 = 0;
-	info->ndcb2 = 0;
+	uint32_t ndcr;
+	int timeout = NAND_STOP_DELAY;
 
-	info->oob_size = 0;
-	if (cmd == cmdset->read_id) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(3);
-		info->data_size = 8;
-	} else if (cmd == cmdset->read_status) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(4);
-		info->data_size = 8;
-	} else if (cmd == cmdset->reset || cmd == cmdset->lock ||
-		   cmd == cmdset->unlock) {
-		info->ndcb0 |= NDCB0_CMD_TYPE(5);
-	} else
-		return -EINVAL;
+	/* wait RUN bit in NDCR become 0 */
+	ndcr = nand_readl(info, NDCR);
+	while ((ndcr & NDCR_ND_RUN) && (timeout-- > 0)) {
+		ndcr = nand_readl(info, NDCR);
+		udelay(1);
+	}
 
-	return 0;
+	if (timeout <= 0) {
+		ndcr &= ~NDCR_ND_RUN;
+		nand_writel(info, NDCR, ndcr);
+	}
+	/* clear status bits */
+	nand_writel(info, NDSR, NDSR_MASK);
 }
 
 static void enable_int(struct pxa3xx_nand_info *info, uint32_t int_mask)
@@ -372,39 +341,8 @@
 	nand_writel(info, NDCR, ndcr | int_mask);
 }
 
-/* NOTE: it is a must to set ND_RUN firstly, then write command buffer
- * otherwise, it does not work
- */
-static int write_cmd(struct pxa3xx_nand_info *info)
-{
-	uint32_t ndcr;
-
-	/* clear status bits and run */
-	nand_writel(info, NDSR, NDSR_MASK);
-
-	ndcr = info->reg_ndcr;
-
-	ndcr |= info->use_ecc ? NDCR_ECC_EN : 0;
-	ndcr |= info->use_dma ? NDCR_DMA_EN : 0;
-	ndcr |= NDCR_ND_RUN;
-
-	nand_writel(info, NDCR, ndcr);
-
-	if (wait_for_event(info, NDSR_WRCMDREQ)) {
-		printk(KERN_ERR "timed out writing command\n");
-		return -ETIMEDOUT;
-	}
-
-	nand_writel(info, NDCB0, info->ndcb0);
-	nand_writel(info, NDCB0, info->ndcb1);
-	nand_writel(info, NDCB0, info->ndcb2);
-	return 0;
-}
-
-static int handle_data_pio(struct pxa3xx_nand_info *info)
+static void handle_data_pio(struct pxa3xx_nand_info *info)
 {
-	int ret, timeout = CHIP_DELAY_TIMEOUT;
-
 	switch (info->state) {
 	case STATE_PIO_WRITING:
 		__raw_writesl(info->mmio_base + NDDB, info->data_buff,
@@ -412,14 +350,6 @@
 		if (info->oob_size > 0)
 			__raw_writesl(info->mmio_base + NDDB, info->oob_buff,
 					DIV_ROUND_UP(info->oob_size, 4));
-
-		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-
-		ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-		if (!ret) {
-			printk(KERN_ERR "program command time out\n");
-			return -1;
-		}
 		break;
 	case STATE_PIO_READING:
 		__raw_readsl(info->mmio_base + NDDB, info->data_buff,
@@ -431,14 +361,11 @@
 	default:
 		printk(KERN_ERR "%s: invalid state %d\n", __func__,
 				info->state);
-		return -EINVAL;
+		BUG();
 	}
-
-	info->state = STATE_READY;
-	return 0;
 }
 
-static void start_data_dma(struct pxa3xx_nand_info *info, int dir_out)
+static void start_data_dma(struct pxa3xx_nand_info *info)
 {
 	struct pxa_dma_desc *desc = info->data_desc;
 	int dma_len = ALIGN(info->data_size + info->oob_size, 32);
@@ -446,14 +373,21 @@
 	desc->ddadr = DDADR_STOP;
 	desc->dcmd = DCMD_ENDIRQEN | DCMD_WIDTH4 | DCMD_BURST32 | dma_len;
 
-	if (dir_out) {
+	switch (info->state) {
+	case STATE_DMA_WRITING:
 		desc->dsadr = info->data_buff_phys;
 		desc->dtadr = info->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCSRCADDR | DCMD_FLOWTRG;
-	} else {
+		break;
+	case STATE_DMA_READING:
 		desc->dtadr = info->data_buff_phys;
 		desc->dsadr = info->mmio_phys + NDDB;
 		desc->dcmd |= DCMD_INCTRGADDR | DCMD_FLOWSRC;
+		break;
+	default:
+		printk(KERN_ERR "%s: invalid state %d\n", __func__,
+				info->state);
+		BUG();
 	}
 
 	DRCMR(info->drcmr_dat) = DRCMR_MAPVLD | info->data_dma_ch;
@@ -471,93 +405,62 @@
 
 	if (dcsr & DCSR_BUSERR) {
 		info->retcode = ERR_DMABUSERR;
-		complete(&info->cmd_complete);
 	}
 
-	if (info->state == STATE_DMA_WRITING) {
-		info->state = STATE_DMA_DONE;
-		enable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-	} else {
-		info->state = STATE_READY;
-		complete(&info->cmd_complete);
-	}
+	info->state = STATE_DMA_DONE;
+	enable_int(info, NDCR_INT_MASK);
+	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
 }
 
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
-	unsigned int status;
+	unsigned int status, is_completed = 0;
 
 	status = nand_readl(info, NDSR);
 
-	if (status & (NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR)) {
-		if (status & NDSR_DBERR)
-			info->retcode = ERR_DBERR;
-		else if (status & NDSR_SBERR)
-			info->retcode = ERR_SBERR;
-
-		disable_int(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
-		if (info->use_dma) {
-			info->state = STATE_DMA_READING;
-			start_data_dma(info, 0);
-		} else {
-			info->state = STATE_PIO_READING;
-			complete(&info->cmd_complete);
-		}
-	} else if (status & NDSR_WRDREQ) {
-		disable_int(info, NDSR_WRDREQ);
+	if (status & NDSR_DBERR)
+		info->retcode = ERR_DBERR;
+	if (status & NDSR_SBERR)
+		info->retcode = ERR_SBERR;
+	if (status & (NDSR_RDDREQ | NDSR_WRDREQ)) {
+		/* whether use dma to transfer data */
 		if (info->use_dma) {
-			info->state = STATE_DMA_WRITING;
-			start_data_dma(info, 1);
+			disable_int(info, NDCR_INT_MASK);
+			info->state = (status & NDSR_RDDREQ) ?
+				      STATE_DMA_READING : STATE_DMA_WRITING;
+			start_data_dma(info);
+			goto NORMAL_IRQ_EXIT;
 		} else {
-			info->state = STATE_PIO_WRITING;
-			complete(&info->cmd_complete);
+			info->state = (status & NDSR_RDDREQ) ?
+				      STATE_PIO_READING : STATE_PIO_WRITING;
+			handle_data_pio(info);
 		}
-	} else if (status & (NDSR_CS0_BBD | NDSR_CS0_CMDD)) {
-		if (status & NDSR_CS0_BBD)
-			info->retcode = ERR_BBERR;
-
-		disable_int(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-		info->state = STATE_READY;
-		complete(&info->cmd_complete);
 	}
-	nand_writel(info, NDSR, status);
-	return IRQ_HANDLED;
-}
-
-static int pxa3xx_nand_do_cmd(struct pxa3xx_nand_info *info, uint32_t event)
-{
-	uint32_t ndcr;
-	int ret, timeout = CHIP_DELAY_TIMEOUT;
-
-	if (write_cmd(info)) {
-		info->retcode = ERR_SENDCMD;
-		goto fail_stop;
+	if (status & NDSR_CS0_CMDD) {
+		info->state = STATE_CMD_DONE;
+		is_completed = 1;
 	}
-
-	info->state = STATE_CMD_HANDLE;
-
-	enable_int(info, event);
-
-	ret = wait_for_completion_timeout(&info->cmd_complete, timeout);
-	if (!ret) {
-		printk(KERN_ERR "command execution timed out\n");
-		info->retcode = ERR_SENDCMD;
-		goto fail_stop;
+	if (status & NDSR_FLASH_RDY) {
+		info->is_ready = 1;
+		info->state = STATE_READY;
 	}
 
-	if (info->use_dma == 0 && info->data_size > 0)
-		if (handle_data_pio(info))
-			goto fail_stop;
-
-	return 0;
+	if (status & NDSR_WRCMDREQ) {
+		nand_writel(info, NDSR, NDSR_WRCMDREQ);
+		status &= ~NDSR_WRCMDREQ;
+		info->state = STATE_CMD_HANDLE;
+		nand_writel(info, NDCB0, info->ndcb0);
+		nand_writel(info, NDCB0, info->ndcb1);
+		nand_writel(info, NDCB0, info->ndcb2);
+	}
 
-fail_stop:
-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-	udelay(10);
-	return -ETIMEDOUT;
+	/* clear NDSR to let the controller exit the IRQ */
+	nand_writel(info, NDSR, status);
+	if (is_completed)
+		complete(&info->cmd_complete);
+NORMAL_IRQ_EXIT:
+	return IRQ_HANDLED;
 }
 
 static int pxa3xx_nand_dev_ready(struct mtd_info *mtd)
@@ -574,125 +477,218 @@
 	return 1;
 }
 
-static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
-				int column, int page_addr)
+static int prepare_command_pool(struct pxa3xx_nand_info *info, int command,
+		uint16_t column, int page_addr)
 {
-	struct pxa3xx_nand_info *info = mtd->priv;
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	int ret;
+	uint16_t cmd;
+	int addr_cycle, exec_cmd, ndcb0;
+	struct mtd_info *mtd = info->mtd;
 
-	info->use_dma = (use_dma) ? 1 : 0;
-	info->use_ecc = 0;
-	info->data_size = 0;
-	info->state = STATE_READY;
+	ndcb0 = 0;
+	addr_cycle = 0;
+	exec_cmd = 1;
 
-	init_completion(&info->cmd_complete);
+	/* reset data and oob column point to handle data */
+	info->buf_start		= 0;
+	info->buf_count		= 0;
+	info->oob_size		= 0;
+	info->use_ecc		= 0;
+	info->is_ready		= 0;
+	info->retcode		= ERR_NONE;
 
 	switch (command) {
+	case NAND_CMD_READ0:
+	case NAND_CMD_PAGEPROG:
+		info->use_ecc = 1;
 	case NAND_CMD_READOOB:
-		/* disable HW ECC to get all the OOB data */
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		info->buf_start = mtd->writesize + column;
-		memset(info->data_buff, 0xFF, info->buf_count);
-
-		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-			break;
-
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
-
-		/* We only are OOB, so if the data has error, does not matter */
-		if (info->retcode == ERR_DBERR)
-			info->retcode = ERR_NONE;
+		pxa3xx_set_datasize(info);
+		break;
+	case NAND_CMD_SEQIN:
+		exec_cmd = 0;
+		break;
+	default:
+		info->ndcb1 = 0;
+		info->ndcb2 = 0;
 		break;
+	}
 
+	info->ndcb0 = ndcb0;
+	addr_cycle = NDCB0_ADDR_CYC(info->row_addr_cycles
+				    + info->col_addr_cycles);
+
+	switch (command) {
+	case NAND_CMD_READOOB:
 	case NAND_CMD_READ0:
-		info->use_ecc = 1;
-		info->retcode = ERR_NONE;
-		info->buf_start = column;
-		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xFF, info->buf_count);
+		cmd = info->cmdset->read1;
+		if (command == NAND_CMD_READOOB)
+			info->buf_start = mtd->writesize + column;
+		else
+			info->buf_start = column;
 
-		if (prepare_read_prog_cmd(info, cmdset->read1, column, page_addr))
-			break;
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE))
+			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+					| addr_cycle
+					| (cmd & NDCB0_CMD1_MASK);
+		else
+			info->ndcb0 |= NDCB0_CMD_TYPE(0)
+					| NDCB0_DBC
+					| addr_cycle
+					| cmd;
 
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ | NDSR_DBERR | NDSR_SBERR);
+	case NAND_CMD_SEQIN:
+		/* small page addr setting */
+		if (unlikely(info->page_size < PAGE_CHUNK_SIZE)) {
+			info->ndcb1 = ((page_addr & 0xFFFFFF) << 8)
+					| (column & 0xFF);
 
-		if (info->retcode == ERR_DBERR) {
-			/* for blank page (all 0xff), HW will calculate its ECC as
-			 * 0, which is different from the ECC information within
-			 * OOB, ignore such double bit errors
-			 */
-			if (is_buf_blank(info->data_buff, mtd->writesize))
-				info->retcode = ERR_NONE;
+			info->ndcb2 = 0;
+		} else {
+			info->ndcb1 = ((page_addr & 0xFFFF) << 16)
+					| (column & 0xFFFF);
+
+			if (page_addr & 0xFF0000)
+				info->ndcb2 = (page_addr & 0xFF0000) >> 16;
+			else
+				info->ndcb2 = 0;
 		}
-		break;
-	case NAND_CMD_SEQIN:
-		info->buf_start = column;
+
 		info->buf_count = mtd->writesize + mtd->oobsize;
-		memset(info->data_buff, 0xff, info->buf_count);
+		memset(info->data_buff, 0xFF, info->buf_count);
 
-		/* save column/page_addr for next CMD_PAGEPROG */
-		info->seqin_column = column;
-		info->seqin_page_addr = page_addr;
 		break;
-	case NAND_CMD_PAGEPROG:
-		info->use_ecc = (info->seqin_column >= mtd->writesize) ? 0 : 1;
 
-		if (prepare_read_prog_cmd(info, cmdset->program,
-				info->seqin_column, info->seqin_page_addr))
+	case NAND_CMD_PAGEPROG:
+		if (is_buf_blank(info->data_buff,
+					(mtd->writesize + mtd->oobsize))) {
+			exec_cmd = 0;
 			break;
+		}
 
-		pxa3xx_nand_do_cmd(info, NDSR_WRDREQ);
+		cmd = info->cmdset->program;
+		info->ndcb0 |= NDCB0_CMD_TYPE(0x1)
+				| NDCB0_AUTO_RS
+				| NDCB0_ST_ROW_EN
+				| NDCB0_DBC
+				| cmd
+				| addr_cycle;
 		break;
-	case NAND_CMD_ERASE1:
-		if (prepare_erase_cmd(info, cmdset->erase, page_addr))
-			break;
 
-		pxa3xx_nand_do_cmd(info, NDSR_CS0_BBD | NDSR_CS0_CMDD);
-		break;
-	case NAND_CMD_ERASE2:
-		break;
 	case NAND_CMD_READID:
+		cmd = info->cmdset->read_id;
+		info->buf_count = info->read_id_bytes;
+		info->ndcb0 |= NDCB0_CMD_TYPE(3)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
+
+		info->data_size = 8;
+		break;
 	case NAND_CMD_STATUS:
-		info->use_dma = 0;	/* force PIO read */
-		info->buf_start = 0;
-		info->buf_count = (command == NAND_CMD_READID) ?
-				info->read_id_bytes : 1;
+		cmd = info->cmdset->read_status;
+		info->buf_count = 1;
+		info->ndcb0 |= NDCB0_CMD_TYPE(4)
+				| NDCB0_ADDR_CYC(1)
+				| cmd;
 
-		if (prepare_other_cmd(info, (command == NAND_CMD_READID) ?
-				cmdset->read_id : cmdset->read_status))
-			break;
+		info->data_size = 8;
+		break;
+
+	case NAND_CMD_ERASE1:
+		cmd = info->cmdset->erase;
+		info->ndcb0 |= NDCB0_CMD_TYPE(2)
+				| NDCB0_AUTO_RS
+				| NDCB0_ADDR_CYC(3)
+				| NDCB0_DBC
+				| cmd;
+		info->ndcb1 = page_addr;
+		info->ndcb2 = 0;
 
-		pxa3xx_nand_do_cmd(info, NDSR_RDDREQ);
 		break;
 	case NAND_CMD_RESET:
-		if (prepare_other_cmd(info, cmdset->reset))
-			break;
-
-		ret = pxa3xx_nand_do_cmd(info, NDSR_CS0_CMDD);
-		if (ret == 0) {
-			int timeout = 2;
-			uint32_t ndcr;
+		cmd = info->cmdset->reset;
+		info->ndcb0 |= NDCB0_CMD_TYPE(5)
+				| cmd;
 
-			while (timeout--) {
-				if (nand_readl(info, NDSR) & NDSR_RDY)
-					break;
-				msleep(10);
-			}
+		break;
 
-			ndcr = nand_readl(info, NDCR);
-			nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-		}
+	case NAND_CMD_ERASE2:
+		exec_cmd = 0;
 		break;
+
 	default:
-		printk(KERN_ERR "non-supported command.\n");
+		exec_cmd = 0;
+		printk(KERN_ERR "pxa3xx-nand: non-supported"
+			" command %x\n", command);
 		break;
 	}
 
-	if (info->retcode == ERR_DBERR) {
-		printk(KERN_ERR "double bit error @ page %08x\n", page_addr);
-		info->retcode = ERR_NONE;
+	return exec_cmd;
+}
+
+static void pxa3xx_nand_cmdfunc(struct mtd_info *mtd, unsigned command,
+				int column, int page_addr)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+	int ret, exec_cmd;
+
+	/*
+	 * if this is a x16 device ,then convert the input
+	 * "byte" address into a "word" address appropriate
+	 * for indexing a word-oriented device
+	 */
+	if (info->reg_ndcr & NDCR_DWIDTH_M)
+		column /= 2;
+
+	exec_cmd = prepare_command_pool(info, command, column, page_addr);
+	if (exec_cmd) {
+		init_completion(&info->cmd_complete);
+		pxa3xx_nand_start(info);
+
+		ret = wait_for_completion_timeout(&info->cmd_complete,
+				CHIP_DELAY_TIMEOUT);
+		if (!ret) {
+			printk(KERN_ERR "Wait time out!!!\n");
+			/* Stop State Machine for next command cycle */
+			pxa3xx_nand_stop(info);
+		}
+		info->state = STATE_IDLE;
+	}
+}
+
+static void pxa3xx_nand_write_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, const uint8_t *buf)
+{
+	chip->write_buf(mtd, buf, mtd->writesize);
+	chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
+}
+
+static int pxa3xx_nand_read_page_hwecc(struct mtd_info *mtd,
+		struct nand_chip *chip, uint8_t *buf, int page)
+{
+	struct pxa3xx_nand_info *info = mtd->priv;
+
+	chip->read_buf(mtd, buf, mtd->writesize);
+	chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
+
+	if (info->retcode == ERR_SBERR) {
+		switch (info->use_ecc) {
+		case 1:
+			mtd->ecc_stats.corrected++;
+			break;
+		case 0:
+		default:
+			break;
+		}
+	} else if (info->retcode == ERR_DBERR) {
+		/*
+		 * for blank page (all 0xff), HW will calculate its ECC as
+		 * 0, which is different from the ECC information within
+		 * OOB, ignore such double bit errors
+		 */
+		if (is_buf_blank(buf, mtd->writesize))
+			mtd->ecc_stats.failed++;
 	}
+
+	return 0;
 }
 
 static uint8_t pxa3xx_nand_read_byte(struct mtd_info *mtd)
@@ -769,73 +765,12 @@
 	return 0;
 }
 
-static void pxa3xx_nand_ecc_hwctl(struct mtd_info *mtd, int mode)
-{
-	return;
-}
-
-static int pxa3xx_nand_ecc_calculate(struct mtd_info *mtd,
-		const uint8_t *dat, uint8_t *ecc_code)
-{
-	return 0;
-}
-
-static int pxa3xx_nand_ecc_correct(struct mtd_info *mtd,
-		uint8_t *dat, uint8_t *read_ecc, uint8_t *calc_ecc)
-{
-	struct pxa3xx_nand_info *info = mtd->priv;
-	/*
-	 * Any error include ERR_SEND_CMD, ERR_DBERR, ERR_BUSERR, we
-	 * consider it as a ecc error which will tell the caller the
-	 * read fail We have distinguish all the errors, but the
-	 * nand_read_ecc only check this function return value
-	 *
-	 * Corrected (single-bit) errors must also be noted.
-	 */
-	if (info->retcode == ERR_SBERR)
-		return 1;
-	else if (info->retcode != ERR_NONE)
-		return -1;
-
-	return 0;
-}
-
-static int __readid(struct pxa3xx_nand_info *info, uint32_t *id)
-{
-	const struct pxa3xx_nand_cmdset *cmdset = info->cmdset;
-	uint32_t ndcr;
-	uint8_t  id_buff[8];
-
-	if (prepare_other_cmd(info, cmdset->read_id)) {
-		printk(KERN_ERR "failed to prepare command\n");
-		return -EINVAL;
-	}
-
-	/* Send command */
-	if (write_cmd(info))
-		goto fail_timeout;
-
-	/* Wait for CMDDM(command done successfully) */
-	if (wait_for_event(info, NDSR_RDDREQ))
-		goto fail_timeout;
-
-	__raw_readsl(info->mmio_base + NDDB, id_buff, 2);
-	*id = id_buff[0] | (id_buff[1] << 8);
-	return 0;
-
-fail_timeout:
-	ndcr = nand_readl(info, NDCR);
-	nand_writel(info, NDCR, ndcr & ~NDCR_ND_RUN);
-	udelay(10);
-	return -ETIMEDOUT;
-}
-
 static int pxa3xx_nand_config_flash(struct pxa3xx_nand_info *info,
 				    const struct pxa3xx_nand_flash *f)
 {
 	struct platform_device *pdev = info->pdev;
 	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
-	uint32_t ndcr = 0x00000FFF; /* disable all interrupts */
+	uint32_t ndcr = 0x0; /* enable all interrupts */
 
 	if (f->page_size != 2048 && f->page_size != 512)
 		return -EINVAL;
@@ -844,9 +779,8 @@
 		return -EINVAL;
 
 	/* calculate flash information */
-	info->cmdset = f->cmdset;
+	info->cmdset = &default_cmdset;
 	info->page_size = f->page_size;
-	info->oob_buff = info->data_buff + f->page_size;
 	info->read_id_bytes = (f->page_size == 2048) ? 4 : 2;
 
 	/* calculate addressing information */
@@ -876,87 +810,18 @@
 static int pxa3xx_nand_detect_config(struct pxa3xx_nand_info *info)
 {
 	uint32_t ndcr = nand_readl(info, NDCR);
-	struct nand_flash_dev *type = NULL;
-	uint32_t id = -1, page_per_block, num_blocks;
-	int i;
-
-	page_per_block = ndcr & NDCR_PG_PER_BLK ? 64 : 32;
 	info->page_size = ndcr & NDCR_PAGE_SZ ? 2048 : 512;
-	/* set info fields needed to __readid */
+	/* set info fields needed to read id */
 	info->read_id_bytes = (info->page_size == 2048) ? 4 : 2;
 	info->reg_ndcr = ndcr;
 	info->cmdset = &default_cmdset;
 
-	if (__readid(info, &id))
-		return -ENODEV;
-
-	/* Lookup the flash id */
-	id = (id >> 8) & 0xff;		/* device id is byte 2 */
-	for (i = 0; nand_flash_ids[i].name != NULL; i++) {
-		if (id == nand_flash_ids[i].id) {
-			type =  &nand_flash_ids[i];
-			break;
-		}
-	}
-
-	if (!type)
-		return -ENODEV;
-
-	/* fill the missing flash information */
-	i = __ffs(page_per_block * info->page_size);
-	num_blocks = type->chipsize << (20 - i);
-
-	/* calculate addressing information */
-	info->col_addr_cycles = (info->page_size == 2048) ? 2 : 1;
-
-	if (num_blocks * page_per_block > 65536)
-		info->row_addr_cycles = 3;
-	else
-		info->row_addr_cycles = 2;
-
 	info->ndtr0cs0 = nand_readl(info, NDTR0CS0);
 	info->ndtr1cs0 = nand_readl(info, NDTR1CS0);
 
 	return 0;
 }
 
-static int pxa3xx_nand_detect_flash(struct pxa3xx_nand_info *info,
-				    const struct pxa3xx_nand_platform_data *pdata)
-{
-	const struct pxa3xx_nand_flash *f;
-	uint32_t id = -1;
-	int i;
-
-	if (pdata->keep_config)
-		if (pxa3xx_nand_detect_config(info) == 0)
-			return 0;
-
-	/* we use default timing to detect id */
-	f = DEFAULT_FLASH_TYPE;
-	pxa3xx_nand_config_flash(info, f);
-	if (__readid(info, &id))
-		goto fail_detect;
-
-	for (i=0; i<ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1; i++) {
-		/* we first choose the flash definition from platfrom */
-		if (i < pdata->num_flash)
-			f = pdata->flash + i;
-		else
-			f = &builtin_flash_types[i - pdata->num_flash + 1];
-		if (f->chip_id == id) {
-			dev_info(&info->pdev->dev, "detect chip id: 0x%x\n", id);
-			pxa3xx_nand_config_flash(info, f);
-			return 0;
-		}
-	}
-
-	dev_warn(&info->pdev->dev,
-		 "failed to detect configured nand flash; found %04x instead of\n",
-		 id);
-fail_detect:
-	return -ENODEV;
-}
-
 /* the maximum possible buffer size for large page with OOB data
  * is: 2048 + 64 = 2112 bytes, allocate a page here for both the
  * data buffer and the DMA descriptor
@@ -998,82 +863,144 @@
 	return 0;
 }
 
-static struct nand_ecclayout hw_smallpage_ecclayout = {
-	.eccbytes = 6,
-	.eccpos = {8, 9, 10, 11, 12, 13 },
-	.oobfree = { {2, 6} }
-};
+static int pxa3xx_nand_sensing(struct pxa3xx_nand_info *info)
+{
+	struct mtd_info *mtd = info->mtd;
+	struct nand_chip *chip = mtd->priv;
 
-static struct nand_ecclayout hw_largepage_ecclayout = {
-	.eccbytes = 24,
-	.eccpos = {
-		40, 41, 42, 43, 44, 45, 46, 47,
-		48, 49, 50, 51, 52, 53, 54, 55,
-		56, 57, 58, 59, 60, 61, 62, 63},
-	.oobfree = { {2, 38} }
-};
+	/* use the common timing to make a try */
+	pxa3xx_nand_config_flash(info, &builtin_flash_types[0]);
+	chip->cmdfunc(mtd, NAND_CMD_RESET, 0, 0);
+	if (info->is_ready)
+		return 1;
+	else
+		return 0;
+}
 
-static void pxa3xx_nand_init_mtd(struct mtd_info *mtd,
-				 struct pxa3xx_nand_info *info)
+static int pxa3xx_nand_scan(struct mtd_info *mtd)
 {
-	struct nand_chip *this = &info->nand_chip;
+	struct pxa3xx_nand_info *info = mtd->priv;
+	struct platform_device *pdev = info->pdev;
+	struct pxa3xx_nand_platform_data *pdata = pdev->dev.platform_data;
+	struct nand_flash_dev pxa3xx_flash_ids[2] = { {NULL,}, {NULL,} };
+	const struct pxa3xx_nand_flash *f = NULL;
+	struct nand_chip *chip = mtd->priv;
+	uint32_t id = -1;
+	uint64_t chipsize;
+	int i, ret, num;
 
-	this->options = (info->reg_ndcr & NDCR_DWIDTH_C) ? NAND_BUSWIDTH_16: 0;
+	if (pdata->keep_config && !pxa3xx_nand_detect_config(info))
+		goto KEEP_CONFIG;
 
-	this->waitfunc		= pxa3xx_nand_waitfunc;
-	this->select_chip	= pxa3xx_nand_select_chip;
-	this->dev_ready		= pxa3xx_nand_dev_ready;
-	this->cmdfunc		= pxa3xx_nand_cmdfunc;
-	this->read_word		= pxa3xx_nand_read_word;
-	this->read_byte		= pxa3xx_nand_read_byte;
-	this->read_buf		= pxa3xx_nand_read_buf;
-	this->write_buf		= pxa3xx_nand_write_buf;
-	this->verify_buf	= pxa3xx_nand_verify_buf;
+	ret = pxa3xx_nand_sensing(info);
+	if (!ret) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_INFO "There is no nand chip on cs 0!\n");
 
-	this->ecc.mode		= NAND_ECC_HW;
-	this->ecc.hwctl		= pxa3xx_nand_ecc_hwctl;
-	this->ecc.calculate	= pxa3xx_nand_ecc_calculate;
-	this->ecc.correct	= pxa3xx_nand_ecc_correct;
-	this->ecc.size		= info->page_size;
+		return -EINVAL;
+	}
 
-	if (info->page_size == 2048)
-		this->ecc.layout = &hw_largepage_ecclayout;
+	chip->cmdfunc(mtd, NAND_CMD_READID, 0, 0);
+	id = *((uint16_t *)(info->data_buff));
+	if (id != 0)
+		printk(KERN_INFO "Detect a flash id %x\n", id);
+	else {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_WARNING "Read out ID 0, potential timing set wrong!!\n");
+
+		return -EINVAL;
+	}
+
+	num = ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1;
+	for (i = 0; i < num; i++) {
+		if (i < pdata->num_flash)
+			f = pdata->flash + i;
+		else
+			f = &builtin_flash_types[i - pdata->num_flash + 1];
+
+		/* find the chip in default list */
+		if (f->chip_id == id)
+			break;
+	}
+
+	if (i >= (ARRAY_SIZE(builtin_flash_types) + pdata->num_flash - 1)) {
+		kfree(mtd);
+		info->mtd = NULL;
+		printk(KERN_ERR "ERROR!! flash not defined!!!\n");
+
+		return -EINVAL;
+	}
+
+	pxa3xx_nand_config_flash(info, f);
+	pxa3xx_flash_ids[0].name = f->name;
+	pxa3xx_flash_ids[0].id = (f->chip_id >> 8) & 0xffff;
+	pxa3xx_flash_ids[0].pagesize = f->page_size;
+	chipsize = (uint64_t)f->num_blocks * f->page_per_block * f->page_size;
+	pxa3xx_flash_ids[0].chipsize = chipsize >> 20;
+	pxa3xx_flash_ids[0].erasesize = f->page_size * f->page_per_block;
+	if (f->flash_width == 16)
+		pxa3xx_flash_ids[0].options = NAND_BUSWIDTH_16;
+KEEP_CONFIG:
+	if (nand_scan_ident(mtd, 1, pxa3xx_flash_ids))
+		return -ENODEV;
+	/* calculate addressing information */
+	info->col_addr_cycles = (mtd->writesize >= 2048) ? 2 : 1;
+	info->oob_buff = info->data_buff + mtd->writesize;
+	if ((mtd->size >> chip->page_shift) > 65536)
+		info->row_addr_cycles = 3;
 	else
-		this->ecc.layout = &hw_smallpage_ecclayout;
+		info->row_addr_cycles = 2;
+	mtd->name = mtd_names[0];
+	chip->ecc.mode = NAND_ECC_HW;
+	chip->ecc.size = f->page_size;
 
-	this->chip_delay = 25;
+	chip->options = (f->flash_width == 16) ? NAND_BUSWIDTH_16 : 0;
+	chip->options |= NAND_NO_AUTOINCR;
+	chip->options |= NAND_NO_READRDY;
+
+	return nand_scan_tail(mtd);
 }
 
-static int pxa3xx_nand_probe(struct platform_device *pdev)
+static
+struct pxa3xx_nand_info *alloc_nand_resource(struct platform_device *pdev)
 {
-	struct pxa3xx_nand_platform_data *pdata;
 	struct pxa3xx_nand_info *info;
-	struct nand_chip *this;
+	struct nand_chip *chip;
 	struct mtd_info *mtd;
 	struct resource *r;
-	int ret = 0, irq;
-
-	pdata = pdev->dev.platform_data;
-
-	if (!pdata) {
-		dev_err(&pdev->dev, "no platform data defined\n");
-		return -ENODEV;
-	}
+	int ret, irq;
 
 	mtd = kzalloc(sizeof(struct mtd_info) + sizeof(struct pxa3xx_nand_info),
 			GFP_KERNEL);
 	if (!mtd) {
 		dev_err(&pdev->dev, "failed to allocate memory\n");
-		return -ENOMEM;
+		return NULL;
 	}
 
 	info = (struct pxa3xx_nand_info *)(&mtd[1]);
+	chip = (struct nand_chip *)(&mtd[1]);
 	info->pdev = pdev;
-
-	this = &info->nand_chip;
+	info->mtd = mtd;
 	mtd->priv = info;
 	mtd->owner = THIS_MODULE;
 
+	chip->ecc.read_page	= pxa3xx_nand_read_page_hwecc;
+	chip->ecc.write_page	= pxa3xx_nand_write_page_hwecc;
+	chip->controller        = &info->controller;
+	chip->waitfunc		= pxa3xx_nand_waitfunc;
+	chip->select_chip	= pxa3xx_nand_select_chip;
+	chip->dev_ready		= pxa3xx_nand_dev_ready;
+	chip->cmdfunc		= pxa3xx_nand_cmdfunc;
+	chip->read_word		= pxa3xx_nand_read_word;
+	chip->read_byte		= pxa3xx_nand_read_byte;
+	chip->read_buf		= pxa3xx_nand_read_buf;
+	chip->write_buf		= pxa3xx_nand_write_buf;
+	chip->verify_buf	= pxa3xx_nand_verify_buf;
+
+	spin_lock_init(&chip->controller->lock);
+	init_waitqueue_head(&chip->controller->wq);
 	info->clk = clk_get(&pdev->dev, NULL);
 	if (IS_ERR(info->clk)) {
 		dev_err(&pdev->dev, "failed to get nand clock\n");
@@ -1141,43 +1068,12 @@
 		goto fail_free_buf;
 	}
 
-	ret = pxa3xx_nand_detect_flash(info, pdata);
-	if (ret) {
-		dev_err(&pdev->dev, "failed to detect flash\n");
-		ret = -ENODEV;
-		goto fail_free_irq;
-	}
-
-	pxa3xx_nand_init_mtd(mtd, info);
-
-	platform_set_drvdata(pdev, mtd);
-
-	if (nand_scan(mtd, 1)) {
-		dev_err(&pdev->dev, "failed to scan nand\n");
-		ret = -ENXIO;
-		goto fail_free_irq;
-	}
-
-#ifdef CONFIG_MTD_PARTITIONS
-	if (mtd_has_cmdlinepart()) {
-		static const char *probes[] = { "cmdlinepart", NULL };
-		struct mtd_partition *parts;
-		int nr_parts;
-
-		nr_parts = parse_mtd_partitions(mtd, probes, &parts, 0);
-
-		if (nr_parts)
-			return add_mtd_partitions(mtd, parts, nr_parts);
-	}
+	platform_set_drvdata(pdev, info);
 
-	return add_mtd_partitions(mtd, pdata->parts, pdata->nr_parts);
-#else
-	return 0;
-#endif
+	return info;
 
-fail_free_irq:
-	free_irq(irq, info);
 fail_free_buf:
+	free_irq(irq, info);
 	if (use_dma) {
 		pxa_free_dma(info->data_dma_ch);
 		dma_free_coherent(&pdev->dev, info->data_buff_size,
@@ -1193,22 +1089,18 @@
 	clk_put(info->clk);
 fail_free_mtd:
 	kfree(mtd);
-	return ret;
+	return NULL;
 }
 
 static int pxa3xx_nand_remove(struct platform_device *pdev)
 {
-	struct mtd_info *mtd = platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 	struct resource *r;
 	int irq;
 
 	platform_set_drvdata(pdev, NULL);
 
-	del_mtd_device(mtd);
-#ifdef CONFIG_MTD_PARTITIONS
-	del_mtd_partitions(mtd);
-#endif
 	irq = platform_get_irq(pdev, 0);
 	if (irq >= 0)
 		free_irq(irq, info);
@@ -1226,17 +1118,62 @@
 	clk_disable(info->clk);
 	clk_put(info->clk);
 
-	kfree(mtd);
+	if (mtd) {
+		del_mtd_device(mtd);
+#ifdef CONFIG_MTD_PARTITIONS
+		del_mtd_partitions(mtd);
+#endif
+		kfree(mtd);
+	}
+	return 0;
+}
+
+static int pxa3xx_nand_probe(struct platform_device *pdev)
+{
+	struct pxa3xx_nand_platform_data *pdata;
+	struct pxa3xx_nand_info *info;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform data defined\n");
+		return -ENODEV;
+	}
+
+	info = alloc_nand_resource(pdev);
+	if (info == NULL)
+		return -ENOMEM;
+
+	if (pxa3xx_nand_scan(info->mtd)) {
+		dev_err(&pdev->dev, "failed to scan nand\n");
+		pxa3xx_nand_remove(pdev);
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_MTD_PARTITIONS
+	if (mtd_has_cmdlinepart()) {
+		const char *probes[] = { "cmdlinepart", NULL };
+		struct mtd_partition *parts;
+		int nr_parts;
+
+		nr_parts = parse_mtd_partitions(info->mtd, probes, &parts, 0);
+
+		if (nr_parts)
+			return add_mtd_partitions(info->mtd, parts, nr_parts);
+	}
+
+	return add_mtd_partitions(info->mtd, pdata->parts, pdata->nr_parts);
+#else
 	return 0;
+#endif
 }
 
 #ifdef CONFIG_PM
 static int pxa3xx_nand_suspend(struct platform_device *pdev, pm_message_t state)
 {
-	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 
-	if (info->state != STATE_READY) {
+	if (info->state) {
 		dev_err(&pdev->dev, "driver busy, state = %d\n", info->state);
 		return -EAGAIN;
 	}
@@ -1246,8 +1183,8 @@
 
 static int pxa3xx_nand_resume(struct platform_device *pdev)
 {
-	struct mtd_info *mtd = (struct mtd_info *)platform_get_drvdata(pdev);
-	struct pxa3xx_nand_info *info = mtd->priv;
+	struct pxa3xx_nand_info *info = platform_get_drvdata(pdev);
+	struct mtd_info *mtd = info->mtd;
 
 	nand_writel(info, NDTR0CS0, info->ndtr0cs0);
 	nand_writel(info, NDTR1CS0, info->ndtr1cs0);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/r852.c linux-libre-2.6.39-gnu/drivers/mtd/nand/r852.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/r852.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/r852.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,7 +185,7 @@
 
 	dbg_verbose("doing dma %s ", do_read ? "read" : "write");
 
-	/* Set intial dma state: for reading first fill on board buffer,
+	/* Set initial dma state: for reading first fill on board buffer,
 	  from device, for writes first fill the buffer  from memory*/
 	dev->dma_state = do_read ? DMA_INTERNAL : DMA_MEMORY;
 
@@ -766,7 +766,7 @@
 		ret = IRQ_HANDLED;
 		dev->card_detected = !!(card_status & R852_CARD_IRQ_INSERT);
 
-		/* we shouldn't recieve any interrupts if we wait for card
+		/* we shouldn't receive any interrupts if we wait for card
 			to settle */
 		WARN_ON(dev->card_unstable);
 
@@ -794,13 +794,13 @@
 		ret = IRQ_HANDLED;
 
 		if (dma_status & R852_DMA_IRQ_ERROR) {
-			dbg("recieved dma error IRQ");
+			dbg("received dma error IRQ");
 			r852_dma_done(dev, -EIO);
 			complete(&dev->dma_done);
 			goto out;
 		}
 
-		/* recieved DMA interrupt out of nowhere? */
+		/* received DMA interrupt out of nowhere? */
 		WARN_ON_ONCE(dev->dma_stage == 0);
 
 		if (dev->dma_stage == 0)
@@ -960,7 +960,7 @@
 		&dev->card_detect_work, 0);
 
 
-	printk(KERN_NOTICE DRV_NAME ": driver loaded succesfully\n");
+	printk(KERN_NOTICE DRV_NAME ": driver loaded successfully\n");
 	return 0;
 
 error10:
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/sh_flctl.c linux-libre-2.6.39-gnu/drivers/mtd/nand/sh_flctl.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/sh_flctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/sh_flctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,7 +78,7 @@
 
 static void timeout_error(struct sh_flctl *flctl, const char *str)
 {
-	dev_err(&flctl->pdev->dev, "Timeout occured in %s\n", str);
+	dev_err(&flctl->pdev->dev, "Timeout occurred in %s\n", str);
 }
 
 static void wait_completion(struct sh_flctl *flctl)
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/sm_common.c linux-libre-2.6.39-gnu/drivers/mtd/nand/sm_common.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/sm_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/sm_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,7 +121,7 @@
 	if (ret)
 		return ret;
 
-	/* Bad block marker postion */
+	/* Bad block marker position */
 	chip->badblockpos = 0x05;
 	chip->badblockbits = 7;
 	chip->block_markbad = sm_block_markbad;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/socrates_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/socrates_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/socrates_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/socrates_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -162,8 +162,7 @@
 /*
  * Probe for the NAND device.
  */
-static int __devinit socrates_nand_probe(struct platform_device *ofdev,
-					 const struct of_device_id *ofid)
+static int __devinit socrates_nand_probe(struct platform_device *ofdev)
 {
 	struct socrates_nand_host *host;
 	struct mtd_info *mtd;
@@ -300,7 +299,7 @@
 
 MODULE_DEVICE_TABLE(of, socrates_nand_match);
 
-static struct of_platform_driver socrates_nand_driver = {
+static struct platform_driver socrates_nand_driver = {
 	.driver = {
 		.name = "socrates_nand",
 		.owner = THIS_MODULE,
@@ -312,12 +311,12 @@
 
 static int __init socrates_nand_init(void)
 {
-	return of_register_platform_driver(&socrates_nand_driver);
+	return platform_driver_register(&socrates_nand_driver);
 }
 
 static void __exit socrates_nand_exit(void)
 {
-	of_unregister_platform_driver(&socrates_nand_driver);
+	platform_driver_unregister(&socrates_nand_driver);
 }
 
 module_init(socrates_nand_init);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/nand/tmio_nand.c linux-libre-2.6.39-gnu/drivers/mtd/nand/tmio_nand.c
--- linux-libre-2.6.38-gnu/drivers/mtd/nand/tmio_nand.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/nand/tmio_nand.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * Slightly murky pre-git history of the driver:
  *
  * Copyright (c) Ian Molton 2004, 2005, 2008
- *    Original work, independant of sharps code. Included hardware ECC support.
+ *    Original work, independent of sharps code. Included hardware ECC support.
  *    Hard ECC did not work for writes in the early revisions.
  * Copyright (c) Dirk Opfer 2005.
  *    Modifications developed from sharps code but
@@ -319,7 +319,7 @@
 
 static int tmio_hw_init(struct platform_device *dev, struct tmio_nand *tmio)
 {
-	struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+	const struct mfd_cell *cell = mfd_get_cell(dev);
 	int ret;
 
 	if (cell->enable) {
@@ -363,7 +363,7 @@
 
 static void tmio_hw_stop(struct platform_device *dev, struct tmio_nand *tmio)
 {
-	struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+	const struct mfd_cell *cell = mfd_get_cell(dev);
 
 	tmio_iowrite8(FCR_MODE_POWER_OFF, tmio->fcr + FCR_MODE);
 	if (cell->disable)
@@ -372,8 +372,7 @@
 
 static int tmio_probe(struct platform_device *dev)
 {
-	struct mfd_cell *cell = dev_get_platdata(&dev->dev);
-	struct tmio_nand_data *data = cell->driver_data;
+	struct tmio_nand_data *data = mfd_get_data(dev);
 	struct resource *fcr = platform_get_resource(dev,
 			IORESOURCE_MEM, 0);
 	struct resource *ccr = platform_get_resource(dev,
@@ -516,7 +515,7 @@
 #ifdef CONFIG_PM
 static int tmio_suspend(struct platform_device *dev, pm_message_t state)
 {
-	struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+	const struct mfd_cell *cell = mfd_get_cell(dev);
 
 	if (cell->suspend)
 		cell->suspend(dev);
@@ -527,7 +526,7 @@
 
 static int tmio_resume(struct platform_device *dev)
 {
-	struct mfd_cell *cell = dev_get_platdata(&dev->dev);
+	const struct mfd_cell *cell = mfd_get_cell(dev);
 
 	/* FIXME - is this required or merely another attack of the broken
 	 * SHARP platform? Looks suspicious.
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/onenand/Kconfig linux-libre-2.6.39-gnu/drivers/mtd/onenand/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mtd/onenand/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/onenand/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 
 config MTD_ONENAND_SAMSUNG
         tristate "OneNAND on Samsung SOC controller support"
-        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5PV310
+        depends on ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_EXYNOS4
         help
           Support for a OneNAND flash device connected to an Samsung SOC.
           S3C64XX/S5PC100 use command mapping method.
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/onenand/omap2.c linux-libre-2.6.39-gnu/drivers/mtd/onenand/omap2.c
--- linux-libre-2.6.38-gnu/drivers/mtd/onenand/omap2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/onenand/omap2.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,7 @@
 	struct completion dma_done;
 	int dma_channel;
 	int freq;
-	int (*setup)(void __iomem *base, int freq);
+	int (*setup)(void __iomem *base, int *freq_ptr);
 	struct regulator *regulator;
 };
 
@@ -148,11 +148,9 @@
 			wait_err("controller error", state, ctrl, intr);
 			return -EIO;
 		}
-		if ((intr & intr_flags) != intr_flags) {
-			wait_err("timeout", state, ctrl, intr);
-			return -EIO;
-		}
-		return 0;
+		if ((intr & intr_flags) == intr_flags)
+			return 0;
+		/* Continue in wait for interrupt branch */
 	}
 
 	if (state != FL_READING) {
@@ -581,7 +579,7 @@
 
 	/* DMA is not in use so this is all that is needed */
 	/* Revisit for OMAP3! */
-	ret = c->setup(c->onenand.base, c->freq);
+	ret = c->setup(c->onenand.base, &c->freq);
 
 	return ret;
 }
@@ -610,7 +608,7 @@
 
 	ret = regulator_enable(c->regulator);
 	if (ret != 0)
-		dev_err(&c->pdev->dev, "cant enable regulator\n");
+		dev_err(&c->pdev->dev, "can't enable regulator\n");
 
 	return ret;
 }
@@ -622,7 +620,7 @@
 
 	ret = regulator_disable(c->regulator);
 	if (ret != 0)
-		dev_err(&c->pdev->dev, "cant disable regulator\n");
+		dev_err(&c->pdev->dev, "can't disable regulator\n");
 
 	return ret;
 }
@@ -631,6 +629,7 @@
 {
 	struct omap_onenand_platform_data *pdata;
 	struct omap2_onenand *c;
+	struct onenand_chip *this;
 	int r;
 
 	pdata = pdev->dev.platform_data;
@@ -673,7 +672,7 @@
 	}
 
 	if (pdata->onenand_setup != NULL) {
-		r = pdata->onenand_setup(c->onenand.base, c->freq);
+		r = pdata->onenand_setup(c->onenand.base, &c->freq);
 		if (r < 0) {
 			dev_err(&pdev->dev, "Onenand platform setup failed: "
 				"%d\n", r);
@@ -718,8 +717,8 @@
 	}
 
 	dev_info(&pdev->dev, "initializing on CS%d, phys base 0x%08lx, virtual "
-		 "base %p\n", c->gpmc_cs, c->phys_base,
-		 c->onenand.base);
+		 "base %p, freq %d MHz\n", c->gpmc_cs, c->phys_base,
+		 c->onenand.base, c->freq);
 
 	c->pdev = pdev;
 	c->mtd.name = dev_name(&pdev->dev);
@@ -728,9 +727,8 @@
 
 	c->mtd.dev.parent = &pdev->dev;
 
+	this = &c->onenand;
 	if (c->dma_channel >= 0) {
-		struct onenand_chip *this = &c->onenand;
-
 		this->wait = omap2_onenand_wait;
 		if (cpu_is_omap34xx()) {
 			this->read_bufferram = omap3_onenand_read_bufferram;
@@ -751,27 +749,12 @@
 		c->onenand.disable = omap2_onenand_disable;
 	}
 
+	if (pdata->skip_initial_unlocking)
+		this->options |= ONENAND_SKIP_INITIAL_UNLOCKING;
+
 	if ((r = onenand_scan(&c->mtd, 1)) < 0)
 		goto err_release_regulator;
 
-	switch ((c->onenand.version_id >> 4) & 0xf) {
-	case 0:
-		c->freq = 40;
-		break;
-	case 1:
-		c->freq = 54;
-		break;
-	case 2:
-		c->freq = 66;
-		break;
-	case 3:
-		c->freq = 83;
-		break;
-	case 4:
-		c->freq = 104;
-		break;
-	}
-
 #ifdef CONFIG_MTD_PARTITIONS
 	r = parse_mtd_partitions(&c->mtd, part_probes, &c->parts, 0);
 	if (r > 0)
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/onenand/onenand_base.c linux-libre-2.6.39-gnu/drivers/mtd/onenand/onenand_base.c
--- linux-libre-2.6.38-gnu/drivers/mtd/onenand/onenand_base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/onenand/onenand_base.c	2011-05-19 00:06:34.000000000 -0400
@@ -1132,6 +1132,8 @@
 			onenand_update_bufferram(mtd, from, !ret);
 			if (ret == -EBADMSG)
 				ret = 0;
+			if (ret)
+				break;
 		}
 
 		this->read_bufferram(mtd, ONENAND_DATARAM, buf, column, thislen);
@@ -1646,11 +1648,10 @@
 	int ret = 0;
 	int thislen, column;
 
+	column = addr & (this->writesize - 1);
+
 	while (len != 0) {
-		thislen = min_t(int, this->writesize, len);
-		column = addr & (this->writesize - 1);
-		if (column + thislen > this->writesize)
-			thislen = this->writesize - column;
+		thislen = min_t(int, this->writesize - column, len);
 
 		this->command(mtd, ONENAND_CMD_READ, addr, this->writesize);
 
@@ -1664,12 +1665,13 @@
 
 		this->read_bufferram(mtd, ONENAND_DATARAM, this->verify_buf, 0, mtd->writesize);
 
-		if (memcmp(buf, this->verify_buf, thislen))
+		if (memcmp(buf, this->verify_buf + column, thislen))
 			return -EBADMSG;
 
 		len -= thislen;
 		buf += thislen;
 		addr += thislen;
+		column = 0;
 	}
 
 	return 0;
@@ -4083,7 +4085,8 @@
 	mtd->writebufsize = mtd->writesize;
 
 	/* Unlock whole block */
-	this->unlock_all(mtd);
+	if (!(this->options & ONENAND_SKIP_INITIAL_UNLOCKING))
+		this->unlock_all(mtd);
 
 	ret = this->scan_bbt(mtd);
 	if ((!FLEXONENAND(this)) || ret)
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/onenand/onenand_sim.c linux-libre-2.6.39-gnu/drivers/mtd/onenand/onenand_sim.c
--- linux-libre-2.6.38-gnu/drivers/mtd/onenand/onenand_sim.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/onenand/onenand_sim.c	2011-05-19 00:06:34.000000000 -0400
@@ -321,7 +321,7 @@
 				continue;
 			if (memcmp(dest + off, ffchars, this->subpagesize) &&
 			    onenand_check_overwrite(dest + off, src + off, this->subpagesize))
-				printk(KERN_ERR "over-write happend at 0x%08x\n", offset);
+				printk(KERN_ERR "over-write happened at 0x%08x\n", offset);
 			memcpy(dest + off, src + off, this->subpagesize);
 		}
 		/* Fall through */
@@ -335,7 +335,7 @@
 		dest = ONENAND_CORE_SPARE(flash, this, offset);
 		if (memcmp(dest, ffchars, mtd->oobsize) &&
 		    onenand_check_overwrite(dest, src, mtd->oobsize))
-			printk(KERN_ERR "OOB: over-write happend at 0x%08x\n",
+			printk(KERN_ERR "OOB: over-write happened at 0x%08x\n",
 			       offset);
 		memcpy(dest, src, mtd->oobsize);
 		break;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/sm_ftl.c linux-libre-2.6.39-gnu/drivers/mtd/sm_ftl.c
--- linux-libre-2.6.38-gnu/drivers/mtd/sm_ftl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/sm_ftl.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,12 +64,16 @@
 					SM_SMALL_PAGE - SM_CIS_VENDOR_OFFSET);
 
 	char *vendor = kmalloc(vendor_len, GFP_KERNEL);
+	if (!vendor)
+		goto error1;
 	memcpy(vendor, ftl->cis_buffer + SM_CIS_VENDOR_OFFSET, vendor_len);
 	vendor[vendor_len] = 0;
 
 	/* Initialize sysfs attributes */
 	vendor_attribute =
 		kzalloc(sizeof(struct sm_sysfs_attribute), GFP_KERNEL);
+	if (!vendor_attribute)
+		goto error2;
 
 	sysfs_attr_init(&vendor_attribute->dev_attr.attr);
 
@@ -83,12 +87,24 @@
 	/* Create array of pointers to the attributes */
 	attributes = kzalloc(sizeof(struct attribute *) * (NUM_ATTRIBUTES + 1),
 								GFP_KERNEL);
+	if (!attributes)
+		goto error3;
 	attributes[0] = &vendor_attribute->dev_attr.attr;
 
 	/* Finally create the attribute group */
 	attr_group = kzalloc(sizeof(struct attribute_group), GFP_KERNEL);
+	if (!attr_group)
+		goto error4;
 	attr_group->attrs = attributes;
 	return attr_group;
+error4:
+	kfree(attributes);
+error3:
+	kfree(vendor_attribute);
+error2:
+	kfree(vendor);
+error1:
+	return NULL;
 }
 
 void sm_delete_sysfs_attributes(struct sm_ftl *ftl)
@@ -524,7 +540,7 @@
 			return -EIO;
 	}
 
-	/* If the block is sliced (partialy erased usually) erase it */
+	/* If the block is sliced (partially erased usually) erase it */
 	if (i == 2) {
 		sm_erase_block(ftl, zone, block, 1);
 		return 1;
@@ -862,7 +878,7 @@
 	return 0;
 }
 
-/* Get and automaticly initialize an FTL mapping for one zone */
+/* Get and automatically initialize an FTL mapping for one zone */
 struct ftl_zone *sm_get_zone(struct sm_ftl *ftl, int zone_num)
 {
 	struct ftl_zone *zone;
@@ -1178,6 +1194,8 @@
 	}
 
 	ftl->disk_attributes = sm_create_sysfs_attributes(ftl);
+	if (!ftl->disk_attributes)
+		goto error6;
 	trans->disk_attributes = ftl->disk_attributes;
 
 	sm_printk("Found %d MiB xD/SmartMedia FTL on mtd%d",
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/tests/mtd_speedtest.c linux-libre-2.6.39-gnu/drivers/mtd/tests/mtd_speedtest.c
--- linux-libre-2.6.38-gnu/drivers/mtd/tests/mtd_speedtest.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/tests/mtd_speedtest.c	2011-05-19 00:06:34.000000000 -0400
@@ -16,7 +16,7 @@
  *
  * Test read and write speed of a MTD device.
  *
- * Author: Adrian Hunter <ext-adrian.hunter@nokia.com>
+ * Author: Adrian Hunter <adrian.hunter@nokia.com>
  */
 
 #include <linux/init.h>
@@ -33,6 +33,11 @@
 module_param(dev, int, S_IRUGO);
 MODULE_PARM_DESC(dev, "MTD device number to use");
 
+static int count;
+module_param(count, int, S_IRUGO);
+MODULE_PARM_DESC(count, "Maximum number of eraseblocks to use "
+			"(0 means use all)");
+
 static struct mtd_info *mtd;
 static unsigned char *iobuf;
 static unsigned char *bbt;
@@ -89,6 +94,33 @@
 	return 0;
 }
 
+static int multiblock_erase(int ebnum, int blocks)
+{
+	int err;
+	struct erase_info ei;
+	loff_t addr = ebnum * mtd->erasesize;
+
+	memset(&ei, 0, sizeof(struct erase_info));
+	ei.mtd  = mtd;
+	ei.addr = addr;
+	ei.len  = mtd->erasesize * blocks;
+
+	err = mtd->erase(mtd, &ei);
+	if (err) {
+		printk(PRINT_PREF "error %d while erasing EB %d, blocks %d\n",
+		       err, ebnum, blocks);
+		return err;
+	}
+
+	if (ei.state == MTD_ERASE_FAILED) {
+		printk(PRINT_PREF "some erase error occurred at EB %d,"
+		       "blocks %d\n", ebnum, blocks);
+		return -EIO;
+	}
+
+	return 0;
+}
+
 static int erase_whole_device(void)
 {
 	int err;
@@ -282,13 +314,16 @@
 
 static long calc_speed(void)
 {
-	long ms, k, speed;
+	uint64_t k;
+	long ms;
 
 	ms = (finish.tv_sec - start.tv_sec) * 1000 +
 	     (finish.tv_usec - start.tv_usec) / 1000;
-	k = goodebcnt * mtd->erasesize / 1024;
-	speed = (k * 1000) / ms;
-	return speed;
+	if (ms == 0)
+		return 0;
+	k = goodebcnt * (mtd->erasesize / 1024) * 1000;
+	do_div(k, ms);
+	return k;
 }
 
 static int scan_for_bad_eraseblocks(void)
@@ -320,13 +355,16 @@
 
 static int __init mtd_speedtest_init(void)
 {
-	int err, i;
+	int err, i, blocks, j, k;
 	long speed;
 	uint64_t tmp;
 
 	printk(KERN_INFO "\n");
 	printk(KERN_INFO "=================================================\n");
-	printk(PRINT_PREF "MTD device: %d\n", dev);
+	if (count)
+		printk(PRINT_PREF "MTD device: %d    count: %d\n", dev, count);
+	else
+		printk(PRINT_PREF "MTD device: %d\n", dev);
 
 	mtd = get_mtd_device(NULL, dev);
 	if (IS_ERR(mtd)) {
@@ -353,6 +391,9 @@
 	       (unsigned long long)mtd->size, mtd->erasesize,
 	       pgsize, ebcnt, pgcnt, mtd->oobsize);
 
+	if (count > 0 && count < ebcnt)
+		ebcnt = count;
+
 	err = -ENOMEM;
 	iobuf = kmalloc(mtd->erasesize, GFP_KERNEL);
 	if (!iobuf) {
@@ -484,6 +525,31 @@
 	speed = calc_speed();
 	printk(PRINT_PREF "erase speed is %ld KiB/s\n", speed);
 
+	/* Multi-block erase all eraseblocks */
+	for (k = 1; k < 7; k++) {
+		blocks = 1 << k;
+		printk(PRINT_PREF "Testing %dx multi-block erase speed\n",
+		       blocks);
+		start_timing();
+		for (i = 0; i < ebcnt; ) {
+			for (j = 0; j < blocks && (i + j) < ebcnt; j++)
+				if (bbt[i + j])
+					break;
+			if (j < 1) {
+				i++;
+				continue;
+			}
+			err = multiblock_erase(i, j);
+			if (err)
+				goto out;
+			cond_resched();
+			i += j;
+		}
+		stop_timing();
+		speed = calc_speed();
+		printk(PRINT_PREF "%dx multi-block erase speed is %ld KiB/s\n",
+		       blocks, speed);
+	}
 	printk(PRINT_PREF "finished\n");
 out:
 	kfree(iobuf);
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/tests/mtd_subpagetest.c linux-libre-2.6.39-gnu/drivers/mtd/tests/mtd_subpagetest.c
--- linux-libre-2.6.38-gnu/drivers/mtd/tests/mtd_subpagetest.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/tests/mtd_subpagetest.c	2011-05-19 00:06:34.000000000 -0400
@@ -394,6 +394,11 @@
 	}
 
 	subpgsize = mtd->writesize >> mtd->subpage_sft;
+	tmp = mtd->size;
+	do_div(tmp, mtd->erasesize);
+	ebcnt = tmp;
+	pgcnt = mtd->erasesize / mtd->writesize;
+
 	printk(PRINT_PREF "MTD device size %llu, eraseblock size %u, "
 	       "page size %u, subpage size %u, count of eraseblocks %u, "
 	       "pages per eraseblock %u, OOB size %u\n",
@@ -413,11 +418,6 @@
 		goto out;
 	}
 
-	tmp = mtd->size;
-	do_div(tmp, mtd->erasesize);
-	ebcnt = tmp;
-	pgcnt = mtd->erasesize / mtd->writesize;
-
 	err = scan_for_bad_eraseblocks();
 	if (err)
 		goto out;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/build.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/build.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/build.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/build.c	2011-05-19 00:06:34.000000000 -0400
@@ -690,11 +690,25 @@
 	ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size);
 	ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);
 
+	ubi->max_write_size = ubi->mtd->writebufsize;
+	/*
+	 * Maximum write size has to be greater or equivalent to min. I/O
+	 * size, and be multiple of min. I/O size.
+	 */
+	if (ubi->max_write_size < ubi->min_io_size ||
+	    ubi->max_write_size % ubi->min_io_size ||
+	    !is_power_of_2(ubi->max_write_size)) {
+		ubi_err("bad write buffer size %d for %d min. I/O unit",
+			ubi->max_write_size, ubi->min_io_size);
+		return -EINVAL;
+	}
+
 	/* Calculate default aligned sizes of EC and VID headers */
 	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
 	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
 
 	dbg_msg("min_io_size      %d", ubi->min_io_size);
+	dbg_msg("max_write_size   %d", ubi->max_write_size);
 	dbg_msg("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
 	dbg_msg("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);
 	dbg_msg("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);
@@ -711,7 +725,7 @@
 	}
 
 	/* Similar for the data offset */
-	ubi->leb_start = ubi->vid_hdr_offset + UBI_EC_HDR_SIZE;
+	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
 	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
 
 	dbg_msg("vid_hdr_offset   %d", ubi->vid_hdr_offset);
@@ -923,6 +937,8 @@
 	spin_lock_init(&ubi->volumes_lock);
 
 	ubi_msg("attaching mtd%d to ubi%d", mtd->index, ubi_num);
+	dbg_msg("sizeof(struct ubi_scan_leb) %zu", sizeof(struct ubi_scan_leb));
+	dbg_msg("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
 
 	err = io_init(ubi);
 	if (err)
@@ -937,13 +953,6 @@
 	if (!ubi->peb_buf2)
 		goto out_free;
 
-#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)
-		goto out_free;
-#endif
-
 	err = attach_by_scanning(ubi);
 	if (err) {
 		dbg_err("failed to attach by scanning, error %d", err);
@@ -991,8 +1000,7 @@
 	 * 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;
+	ubi->thread_enabled = 1;
 	wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 
@@ -1009,9 +1017,6 @@
 out_free:
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-	vfree(ubi->dbg_peb_buf);
-#endif
 	if (ref)
 		put_device(&ubi->dev);
 	else
@@ -1082,9 +1087,6 @@
 	put_mtd_device(ubi->mtd);
 	vfree(ubi->peb_buf1);
 	vfree(ubi->peb_buf2);
-#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);
 	put_device(&ubi->dev);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/debug.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/debug.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,20 @@
 #ifdef CONFIG_MTD_UBI_DEBUG
 
 #include "ubi.h"
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+
+unsigned int ubi_msg_flags;
+unsigned int ubi_chk_flags;
+unsigned int ubi_tst_flags;
+
+module_param_named(debug_msgs, ubi_msg_flags, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug_chks, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
+module_param_named(debug_tsts, ubi_chk_flags, uint, S_IRUGO | S_IWUSR);
+
+MODULE_PARM_DESC(debug_msgs, "Debug message type flags");
+MODULE_PARM_DESC(debug_chks, "Debug check flags");
+MODULE_PARM_DESC(debug_tsts, "Debug special test flags");
 
 /**
  * ubi_dbg_dump_ec_hdr - dump an erase counter header.
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/debug.h linux-libre-2.6.39-gnu/drivers/mtd/ubi/debug.h
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/debug.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,11 @@
 	printk(KERN_DEBUG "UBI DBG (pid %d): %s: " fmt "\n", \
 	       current->pid, __func__, ##__VA_ARGS__)
 
+#define dbg_do_msg(typ, fmt, ...) do {                       \
+	if (ubi_msg_flags & typ)                             \
+		dbg_msg(fmt, ##__VA_ARGS__);                 \
+} while (0)
+
 #define ubi_dbg_dump_stack() dump_stack()
 
 struct ubi_ec_hdr;
@@ -57,62 +62,88 @@
 void ubi_dbg_dump_mkvol_req(const struct ubi_mkvol_req *req);
 void ubi_dbg_dump_flash(struct ubi_device *ubi, int pnum, int offset, int len);
 
+extern unsigned int ubi_msg_flags;
+
+/*
+ * Debugging message type flags (must match msg_type_names in debug.c).
+ *
+ * UBI_MSG_GEN: general messages
+ * UBI_MSG_EBA: journal messages
+ * UBI_MSG_WL: mount messages
+ * UBI_MSG_IO: commit messages
+ * UBI_MSG_BLD: LEB find messages
+ */
+enum {
+	UBI_MSG_GEN  = 0x1,
+	UBI_MSG_EBA  = 0x2,
+	UBI_MSG_WL   = 0x4,
+	UBI_MSG_IO   = 0x8,
+	UBI_MSG_BLD  = 0x10,
+};
+
 #define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  \
 		print_hex_dump(l, ps, pt, r, g, b, len, a)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG
 /* General debugging messages */
-#define dbg_gen(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_gen(fmt, ...) ({})
-#endif
+#define dbg_gen(fmt, ...) dbg_do_msg(UBI_MSG_GEN, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_EBA
 /* Messages from the eraseblock association sub-system */
-#define dbg_eba(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_eba(fmt, ...) ({})
-#endif
+#define dbg_eba(fmt, ...) dbg_do_msg(UBI_MSG_EBA, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_WL
 /* Messages from the wear-leveling sub-system */
-#define dbg_wl(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_wl(fmt, ...) ({})
-#endif
+#define dbg_wl(fmt, ...) dbg_do_msg(UBI_MSG_WL, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_IO
 /* Messages from the input/output sub-system */
-#define dbg_io(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#else
-#define dbg_io(fmt, ...) ({})
-#endif
+#define dbg_io(fmt, ...) dbg_do_msg(UBI_MSG_IO, fmt, ##__VA_ARGS__)
 
-#ifdef CONFIG_MTD_UBI_DEBUG_MSG_BLD
 /* Initialization and build messages */
-#define dbg_bld(fmt, ...) dbg_msg(fmt, ##__VA_ARGS__)
-#define UBI_IO_DEBUG 1
-#else
-#define dbg_bld(fmt, ...) ({})
-#define UBI_IO_DEBUG 0
-#endif
+#define dbg_bld(fmt, ...) dbg_do_msg(UBI_MSG_BLD, fmt, ##__VA_ARGS__)
+
+extern unsigned int ubi_chk_flags;
+
+/*
+ * Debugging check flags.
+ *
+ * UBI_CHK_GEN: general checks
+ * UBI_CHK_IO: check writes and erases
+ */
+enum {
+	UBI_CHK_GEN = 0x1,
+	UBI_CHK_IO  = 0x2,
+};
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
 int ubi_dbg_check_all_ff(struct ubi_device *ubi, int pnum, int offset, int len);
 int ubi_dbg_check_write(struct ubi_device *ubi, const void *buf, int pnum,
 			int offset, int len);
-#else
-#define ubi_dbg_check_all_ff(ubi, pnum, offset, len) 0
-#define ubi_dbg_check_write(ubi, buf, pnum, offset, len) 0
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_DISABLE_BGT
-#define DBG_DISABLE_BGT 1
-#else
-#define DBG_DISABLE_BGT 0
-#endif
+extern unsigned int ubi_tst_flags;
+
+/*
+ * Special testing flags.
+ *
+ * UBIFS_TST_DISABLE_BGT: disable the background thread
+ * UBI_TST_EMULATE_BITFLIPS: emulate bit-flips
+ * UBI_TST_EMULATE_WRITE_FAILURES: emulate write failures
+ * UBI_TST_EMULATE_ERASE_FAILURES: emulate erase failures
+ */
+enum {
+	UBI_TST_DISABLE_BGT            = 0x1,
+	UBI_TST_EMULATE_BITFLIPS       = 0x2,
+	UBI_TST_EMULATE_WRITE_FAILURES = 0x4,
+	UBI_TST_EMULATE_ERASE_FAILURES = 0x8,
+};
+
+/**
+ * ubi_dbg_is_bgt_disabled - if the background thread is disabled.
+ *
+ * Returns non-zero if the UBI background thread is disabled for testing
+ * purposes.
+ */
+static inline int ubi_dbg_is_bgt_disabled(void)
+{
+	return ubi_tst_flags & UBI_TST_DISABLE_BGT;
+}
 
-#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_BITFLIPS
 /**
  * ubi_dbg_is_bitflip - if it is time to emulate a bit-flip.
  *
@@ -120,13 +151,11 @@
  */
 static inline int ubi_dbg_is_bitflip(void)
 {
-	return !(random32() % 200);
+	if (ubi_tst_flags & UBI_TST_EMULATE_BITFLIPS)
+		return !(random32() % 200);
+	return 0;
 }
-#else
-#define ubi_dbg_is_bitflip() 0
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
 /**
  * ubi_dbg_is_write_failure - if it is time to emulate a write failure.
  *
@@ -135,13 +164,11 @@
  */
 static inline int ubi_dbg_is_write_failure(void)
 {
-	return !(random32() % 500);
+	if (ubi_tst_flags & UBI_TST_EMULATE_WRITE_FAILURES)
+		return !(random32() % 500);
+	return 0;
 }
-#else
-#define ubi_dbg_is_write_failure() 0
-#endif
 
-#ifdef CONFIG_MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
 /**
  * ubi_dbg_is_erase_failure - if its time to emulate an erase failure.
  *
@@ -150,11 +177,10 @@
  */
 static inline int ubi_dbg_is_erase_failure(void)
 {
+	if (ubi_tst_flags & UBI_TST_EMULATE_ERASE_FAILURES)
 		return !(random32() % 400);
+	return 0;
 }
-#else
-#define ubi_dbg_is_erase_failure() 0
-#endif
 
 #else
 
@@ -177,8 +203,7 @@
 #define ubi_dbg_dump_flash(ubi, pnum, offset, len) ({})
 #define ubi_dbg_print_hex_dump(l, ps, pt, r, g, b, len, a)  ({})
 
-#define UBI_IO_DEBUG               0
-#define DBG_DISABLE_BGT            0
+#define ubi_dbg_is_bgt_disabled()  0
 #define ubi_dbg_is_bitflip()       0
 #define ubi_dbg_is_write_failure() 0
 #define ubi_dbg_is_erase_failure() 0
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/io.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/io.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/io.c	2011-05-19 00:06:34.000000000 -0400
@@ -91,7 +91,7 @@
 #include <linux/slab.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_not_bad(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_peb_ec_hdr(const struct ubi_device *ubi, int pnum);
 static int paranoid_check_ec_hdr(const struct ubi_device *ubi, int pnum,
@@ -146,6 +146,28 @@
 	if (err)
 		return err;
 
+	/*
+	 * Deliberately corrupt the buffer to improve robustness. Indeed, if we
+	 * do not do this, the following may happen:
+	 * 1. The buffer contains data from previous operation, e.g., read from
+	 *    another PEB previously. The data looks like expected, e.g., if we
+	 *    just do not read anything and return - the caller would not
+	 *    notice this. E.g., if we are reading a VID header, the buffer may
+	 *    contain a valid VID header from another PEB.
+	 * 2. The driver is buggy and returns us success or -EBADMSG or
+	 *    -EUCLEAN, but it does not actually put any data to the buffer.
+	 *
+	 * This may confuse UBI or upper layers - they may think the buffer
+	 * contains valid data while in fact it is just old data. This is
+	 * especially possible because UBI (and UBIFS) relies on CRC, and
+	 * treats data as correct even in case of ECC errors if the CRC is
+	 * correct.
+	 *
+	 * Try to prevent this situation by changing the first byte of the
+	 * buffer.
+	 */
+	*((uint8_t *)buf) ^= 0xFF;
+
 	addr = (loff_t)pnum * ubi->peb_size + offset;
 retry:
 	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
@@ -166,7 +188,7 @@
 			return UBI_IO_BITFLIPS;
 		}
 
-		if (read != len && retries++ < UBI_IO_RETRIES) {
+		if (retries++ < UBI_IO_RETRIES) {
 			dbg_io("error %d%s while reading %d bytes from PEB %d:%d,"
 			       " read only %zd bytes, retry",
 			       err, errstr, len, pnum, offset, read);
@@ -322,6 +344,12 @@
 	wait_queue_head_t wq;
 
 	dbg_io("erase PEB %d", pnum);
+	ubi_assert(pnum >= 0 && pnum < ubi->peb_count);
+
+	if (ubi->ro_mode) {
+		ubi_err("read-only mode");
+		return -EROFS;
+	}
 
 retry:
 	init_waitqueue_head(&wq);
@@ -368,7 +396,7 @@
 	if (err)
 		return err;
 
-	if (ubi_dbg_is_erase_failure() && !err) {
+	if (ubi_dbg_is_erase_failure()) {
 		dbg_err("cannot erase PEB %d (emulated)", pnum);
 		return -EIO;
 	}
@@ -480,6 +508,13 @@
 	size_t written;
 	loff_t addr;
 	uint32_t data = 0;
+	/*
+	 * Note, we cannot generally define VID header buffers on stack,
+	 * because of the way we deal with these buffers (see the header
+	 * comment in this file). But we know this is a NOR-specific piece of
+	 * code, so we can do this. But yes, this is error-prone and we should
+	 * (pre-)allocate VID header buffer instead.
+	 */
 	struct ubi_vid_hdr vid_hdr;
 
 	/*
@@ -507,11 +542,13 @@
 	 * PEB.
 	 */
 	err1 = ubi_io_read_vid_hdr(ubi, pnum, &vid_hdr, 0);
-	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR) {
+	if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR ||
+	    err1 == UBI_IO_FF) {
 		struct ubi_ec_hdr ec_hdr;
 
 		err1 = ubi_io_read_ec_hdr(ubi, pnum, &ec_hdr, 0);
-		if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR)
+		if (err1 == UBI_IO_BAD_HDR_EBADMSG || err1 == UBI_IO_BAD_HDR ||
+		    err1 == UBI_IO_FF)
 			/*
 			 * Both VID and EC headers are corrupted, so we can
 			 * safely erase this PEB and not afraid that it will be
@@ -752,9 +789,8 @@
 			if (verbose)
 				ubi_warn("no EC header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
-			else if (UBI_IO_DEBUG)
-				dbg_msg("no EC header found at PEB %d, "
-					"only 0xFF bytes", pnum);
+			dbg_bld("no EC header found at PEB %d, "
+				"only 0xFF bytes", pnum);
 			if (!read_err)
 				return UBI_IO_FF;
 			else
@@ -769,9 +805,9 @@
 			ubi_warn("bad magic number at PEB %d: %08x instead of "
 				 "%08x", pnum, magic, UBI_EC_HDR_MAGIC);
 			ubi_dbg_dump_ec_hdr(ec_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad magic number at PEB %d: %08x instead of "
-				"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
+		}
+		dbg_bld("bad magic number at PEB %d: %08x instead of "
+			"%08x", pnum, magic, UBI_EC_HDR_MAGIC);
 		return UBI_IO_BAD_HDR;
 	}
 
@@ -783,9 +819,9 @@
 			ubi_warn("bad EC header CRC at PEB %d, calculated "
 				 "%#08x, read %#08x", pnum, crc, hdr_crc);
 			ubi_dbg_dump_ec_hdr(ec_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad EC header CRC at PEB %d, calculated "
-				"%#08x, read %#08x", pnum, crc, hdr_crc);
+		}
+		dbg_bld("bad EC header CRC at PEB %d, calculated "
+			"%#08x, read %#08x", pnum, crc, hdr_crc);
 
 		if (!read_err)
 			return UBI_IO_BAD_HDR;
@@ -1008,9 +1044,8 @@
 			if (verbose)
 				ubi_warn("no VID header found at PEB %d, "
 					 "only 0xFF bytes", pnum);
-			else if (UBI_IO_DEBUG)
-				dbg_msg("no VID header found at PEB %d, "
-					"only 0xFF bytes", pnum);
+			dbg_bld("no VID header found at PEB %d, "
+				"only 0xFF bytes", pnum);
 			if (!read_err)
 				return UBI_IO_FF;
 			else
@@ -1021,9 +1056,9 @@
 			ubi_warn("bad magic number at PEB %d: %08x instead of "
 				 "%08x", pnum, magic, UBI_VID_HDR_MAGIC);
 			ubi_dbg_dump_vid_hdr(vid_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad magic number at PEB %d: %08x instead of "
-				"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
+		}
+		dbg_bld("bad magic number at PEB %d: %08x instead of "
+			"%08x", pnum, magic, UBI_VID_HDR_MAGIC);
 		return UBI_IO_BAD_HDR;
 	}
 
@@ -1035,9 +1070,9 @@
 			ubi_warn("bad CRC at PEB %d, calculated %#08x, "
 				 "read %#08x", pnum, crc, hdr_crc);
 			ubi_dbg_dump_vid_hdr(vid_hdr);
-		} else if (UBI_IO_DEBUG)
-			dbg_msg("bad CRC at PEB %d, calculated %#08x, "
-				"read %#08x", pnum, crc, hdr_crc);
+		}
+		dbg_bld("bad CRC at PEB %d, calculated %#08x, "
+			"read %#08x", pnum, crc, hdr_crc);
 		if (!read_err)
 			return UBI_IO_BAD_HDR;
 		else
@@ -1097,7 +1132,7 @@
 	return err;
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_not_bad - ensure that a physical eraseblock is not bad.
@@ -1111,6 +1146,9 @@
 {
 	int err;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	err = ubi_io_is_bad(ubi, pnum);
 	if (!err)
 		return err;
@@ -1135,6 +1173,9 @@
 	int err;
 	uint32_t magic;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	magic = be32_to_cpu(ec_hdr->magic);
 	if (magic != UBI_EC_HDR_MAGIC) {
 		ubi_err("bad magic %#08x, must be %#08x",
@@ -1170,6 +1211,9 @@
 	uint32_t crc, hdr_crc;
 	struct ubi_ec_hdr *ec_hdr;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
@@ -1211,6 +1255,9 @@
 	int err;
 	uint32_t magic;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	magic = be32_to_cpu(vid_hdr->magic);
 	if (magic != UBI_VID_HDR_MAGIC) {
 		ubi_err("bad VID header magic %#08x at PEB %d, must be %#08x",
@@ -1249,6 +1296,9 @@
 	struct ubi_vid_hdr *vid_hdr;
 	void *p;
 
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
 	vid_hdr = ubi_zalloc_vid_hdr(ubi, GFP_NOFS);
 	if (!vid_hdr)
 		return -ENOMEM;
@@ -1294,15 +1344,26 @@
 			int offset, int len)
 {
 	int err, i;
+	size_t read;
+	void *buf1;
+	loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-	mutex_lock(&ubi->dbg_buf_mutex);
-	err = ubi_io_read(ubi, ubi->dbg_peb_buf, pnum, offset, len);
-	if (err)
-		goto out_unlock;
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
+	buf1 = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
+	if (!buf1) {
+		ubi_err("cannot allocate memory to check writes");
+		return 0;
+	}
+
+	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf1);
+	if (err && err != -EUCLEAN)
+		goto out_free;
 
 	for (i = 0; i < len; i++) {
 		uint8_t c = ((uint8_t *)buf)[i];
-		uint8_t c1 = ((uint8_t *)ubi->dbg_peb_buf)[i];
+		uint8_t c1 = ((uint8_t *)buf1)[i];
 		int dump_len;
 
 		if (c == c1)
@@ -1319,17 +1380,17 @@
 		ubi_msg("hex dump of the read buffer from %d to %d",
 			i, i + dump_len);
 		print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-			       ubi->dbg_peb_buf + i, dump_len, 1);
+			       buf1 + i, dump_len, 1);
 		ubi_dbg_dump_stack();
 		err = -EINVAL;
-		goto out_unlock;
+		goto out_free;
 	}
-	mutex_unlock(&ubi->dbg_buf_mutex);
 
+	vfree(buf1);
 	return 0;
 
-out_unlock:
-	mutex_unlock(&ubi->dbg_buf_mutex);
+out_free:
+	vfree(buf1);
 	return err;
 }
 
@@ -1348,36 +1409,44 @@
 {
 	size_t read;
 	int err;
+	void *buf;
 	loff_t addr = (loff_t)pnum * ubi->peb_size + offset;
 
-	mutex_lock(&ubi->dbg_buf_mutex);
-	err = ubi->mtd->read(ubi->mtd, addr, len, &read, ubi->dbg_peb_buf);
+	if (!(ubi_chk_flags & UBI_CHK_IO))
+		return 0;
+
+	buf = __vmalloc(len, GFP_NOFS, PAGE_KERNEL);
+	if (!buf) {
+		ubi_err("cannot allocate memory to check for 0xFFs");
+		return 0;
+	}
+
+	err = ubi->mtd->read(ubi->mtd, addr, len, &read, buf);
 	if (err && err != -EUCLEAN) {
 		ubi_err("error %d while reading %d bytes from PEB %d:%d, "
 			"read %zd bytes", err, len, pnum, offset, read);
 		goto error;
 	}
 
-	err = ubi_check_pattern(ubi->dbg_peb_buf, 0xFF, len);
+	err = ubi_check_pattern(buf, 0xFF, len);
 	if (err == 0) {
 		ubi_err("flash region at PEB %d:%d, length %d does not "
 			"contain all 0xFF bytes", pnum, offset, len);
 		goto fail;
 	}
-	mutex_unlock(&ubi->dbg_buf_mutex);
 
+	vfree(buf);
 	return 0;
 
 fail:
 	ubi_err("paranoid check failed for PEB %d", pnum);
 	ubi_msg("hex dump of the %d-%d region", offset, offset + len);
-	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1,
-		       ubi->dbg_peb_buf, len, 1);
+	print_hex_dump(KERN_DEBUG, "", DUMP_PREFIX_OFFSET, 32, 1, buf, len, 1);
 	err = -EINVAL;
 error:
 	ubi_dbg_dump_stack();
-	mutex_unlock(&ubi->dbg_buf_mutex);
+	vfree(buf);
 	return err;
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/kapi.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/kapi.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/kapi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/kapi.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,9 @@
 {
 	di->ubi_num = ubi->ubi_num;
 	di->leb_size = ubi->leb_size;
+	di->leb_start = ubi->leb_start;
 	di->min_io_size = ubi->min_io_size;
+	di->max_write_size = ubi->max_write_size;
 	di->ro_mode = ubi->ro_mode;
 	di->cdev = ubi->cdev.dev;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/Kconfig linux-libre-2.6.39-gnu/drivers/mtd/ubi/Kconfig
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -52,6 +52,12 @@
 	   work on top of UBI. Do not enable this unless you use legacy
 	   software.
 
-source "drivers/mtd/ubi/Kconfig.debug"
+config MTD_UBI_DEBUG
+	bool "UBI debugging"
+	depends on SYSFS
+	select DEBUG_FS
+	select KALLSYMS
+	help
+	  This option enables UBI debugging.
 
 endif # MTD_UBI
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/Kconfig.debug linux-libre-2.6.39-gnu/drivers/mtd/ubi/Kconfig.debug
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/Kconfig.debug	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/Kconfig.debug	1969-12-31 19:00:00.000000000 -0500
@@ -1,73 +0,0 @@
-comment "UBI debugging options"
-
-config MTD_UBI_DEBUG
-	bool "UBI debugging"
-	depends on SYSFS
-	select DEBUG_FS
-	select KALLSYMS_ALL if KALLSYMS && DEBUG_KERNEL
-	help
-	  This option enables UBI debugging.
-
-if MTD_UBI_DEBUG
-
-config MTD_UBI_DEBUG_MSG
-	bool "UBI debugging messages"
-	help
-	  This option enables UBI debugging messages.
-
-config MTD_UBI_DEBUG_PARANOID
-	bool "Extra self-checks"
-	help
-	  This option enables extra checks in UBI code. Note this slows UBI down
-	  significantly.
-
-config MTD_UBI_DEBUG_DISABLE_BGT
-	bool "Do not enable the UBI background thread"
-	help
-	  This option switches the background thread off by default. The thread
-	  may be also be enabled/disabled via UBI sysfs.
-
-config MTD_UBI_DEBUG_EMULATE_BITFLIPS
-	bool "Emulate flash bit-flips"
-	help
-	  This option emulates bit-flips with probability 1/50, which in turn
-	  causes scrubbing. Useful for debugging and stressing UBI.
-
-config MTD_UBI_DEBUG_EMULATE_WRITE_FAILURES
-	bool "Emulate flash write failures"
-	help
-	  This option emulates write failures with probability 1/100. Useful for
-	  debugging and testing how UBI handlines errors.
-
-config MTD_UBI_DEBUG_EMULATE_ERASE_FAILURES
-	bool "Emulate flash erase failures"
-	help
-	  This option emulates erase failures with probability 1/100. Useful for
-	  debugging and testing how UBI handlines errors.
-
-comment "Additional UBI debugging messages"
-
-config MTD_UBI_DEBUG_MSG_BLD
-	bool "Additional UBI initialization and build messages"
-	help
-	  This option enables detailed UBI initialization and device build
-	  debugging messages.
-
-config MTD_UBI_DEBUG_MSG_EBA
-	bool "Eraseblock association unit messages"
-	help
-	  This option enables debugging messages from the UBI eraseblock
-	  association unit.
-
-config MTD_UBI_DEBUG_MSG_WL
-	bool "Wear-leveling unit messages"
-	help
-	  This option enables debugging messages from the UBI wear-leveling
-	  unit.
-
-config MTD_UBI_DEBUG_MSG_IO
-	bool "Input/output unit messages"
-	help
-	  This option enables debugging messages from the UBI input/output unit.
-
-endif # MTD_UBI_DEBUG
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/scan.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/scan.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,32 +39,46 @@
  * eraseblocks are put to the @free list and the physical eraseblock to be
  * erased are put to the @erase list.
  *
+ * About corruptions
+ * ~~~~~~~~~~~~~~~~~
+ *
+ * UBI protects EC and VID headers with CRC-32 checksums, so it can detect
+ * whether the headers are corrupted or not. Sometimes UBI also protects the
+ * data with CRC-32, e.g., when it executes the atomic LEB change operation, or
+ * when it moves the contents of a PEB for wear-leveling purposes.
+ *
  * UBI tries to distinguish between 2 types of corruptions.
- * 1. Corruptions caused by power cuts. These are harmless and expected
- *    corruptions and UBI tries to handle them gracefully, without printing too
- *    many warnings and error messages. The idea is that we do not lose
- *    important data in these case - we may lose only the data which was being
- *    written to the media just before the power cut happened, and the upper
- *    layers (e.g., UBIFS) are supposed to handle these situations. UBI puts
- *    these PEBs to the head of the @erase list and they are scheduled for
- *    erasure.
+ *
+ * 1. Corruptions caused by power cuts. These are expected corruptions and UBI
+ * tries to handle them gracefully, without printing too many warnings and
+ * error messages. The idea is that we do not lose important data in these case
+ * - we may lose only the data which was being written to the media just before
+ * the power cut happened, and the upper layers (e.g., UBIFS) are supposed to
+ * handle such data losses (e.g., by using the FS journal).
+ *
+ * When UBI detects a corruption (CRC-32 mismatch) in a PEB, and it looks like
+ * the reason is a power cut, UBI puts this PEB to the @erase list, and all
+ * PEBs in the @erase list are scheduled for erasure later.
  *
  * 2. Unexpected corruptions which are not caused by power cuts. During
- *    scanning, such PEBs are put to the @corr list and UBI preserves them.
- *    Obviously, this lessens the amount of available PEBs, and if at some
- *    point UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly
- *    informs about such PEBs every time the MTD device is attached.
+ * scanning, such PEBs are put to the @corr list and UBI preserves them.
+ * Obviously, this lessens the amount of available PEBs, and if at some  point
+ * UBI runs out of free PEBs, it switches to R/O mode. UBI also loudly informs
+ * about such PEBs every time the MTD device is attached.
  *
  * However, it is difficult to reliably distinguish between these types of
- * corruptions and UBI's strategy is as follows. UBI assumes (2.) if the VID
- * header is corrupted and the data area does not contain all 0xFFs, and there
- * were not bit-flips or integrity errors while reading the data area. Otherwise
- * UBI assumes (1.). The assumptions are:
- *   o if the data area contains only 0xFFs, there is no data, and it is safe
- *     to just erase this PEB.
- *   o if the data area has bit-flips and data integrity errors (ECC errors on
+ * corruptions and UBI's strategy is as follows. UBI assumes corruption type 2
+ * if the VID header is corrupted and the data area does not contain all 0xFFs,
+ * and there were no bit-flips or integrity errors while reading the data area.
+ * Otherwise UBI assumes corruption type 1. So the decision criteria are as
+ * follows.
+ *   o If the data area contains only 0xFFs, there is no data, and it is safe
+ *     to just erase this PEB - this is corruption type 1.
+ *   o If the data area has bit-flips or data integrity errors (ECC errors on
  *     NAND), it is probably a PEB which was being erased when power cut
- *     happened.
+ *     happened, so this is corruption type 1. However, this is just a guess,
+ *     which might be wrong.
+ *   o Otherwise this it corruption type 2.
  */
 
 #include <linux/err.h>
@@ -74,7 +88,7 @@
 #include <linux/random.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_si(struct ubi_device *ubi, struct ubi_scan_info *si);
 #else
 #define paranoid_check_si(ubi, si) 0
@@ -115,7 +129,7 @@
 	} else
 		BUG();
 
-	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 	if (!seb)
 		return -ENOMEM;
 
@@ -144,7 +158,7 @@
 
 	dbg_bld("add to corrupted: PEB %d, EC %d", pnum, ec);
 
-	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 	if (!seb)
 		return -ENOMEM;
 
@@ -553,7 +567,7 @@
 	if (err)
 		return err;
 
-	seb = kmalloc(sizeof(struct ubi_scan_leb), GFP_KERNEL);
+	seb = kmem_cache_alloc(si->scan_leb_slab, GFP_KERNEL);
 	if (!seb)
 		return -ENOMEM;
 
@@ -954,7 +968,7 @@
 			 * contains garbage because of a power cut during erase
 			 * operation. So we just schedule this PEB for erasure.
 			 *
-			 * Besides, in case of NOR flash, we deliberatly
+			 * Besides, in case of NOR flash, we deliberately
 			 * corrupt both headers because NOR flash erasure is
 			 * slow and can start from the end.
 			 */
@@ -1152,9 +1166,15 @@
 	si->volumes = RB_ROOT;
 
 	err = -ENOMEM;
+	si->scan_leb_slab = kmem_cache_create("ubi_scan_leb_slab",
+					      sizeof(struct ubi_scan_leb),
+					      0, 0, NULL);
+	if (!si->scan_leb_slab)
+		goto out_si;
+
 	ech = kzalloc(ubi->ec_hdr_alsize, GFP_KERNEL);
 	if (!ech)
-		goto out_si;
+		goto out_slab;
 
 	vidh = ubi_zalloc_vid_hdr(ubi, GFP_KERNEL);
 	if (!vidh)
@@ -1215,6 +1235,8 @@
 	ubi_free_vid_hdr(ubi, vidh);
 out_ech:
 	kfree(ech);
+out_slab:
+	kmem_cache_destroy(si->scan_leb_slab);
 out_si:
 	ubi_scan_destroy_si(si);
 	return ERR_PTR(err);
@@ -1223,11 +1245,12 @@
 /**
  * destroy_sv - free the scanning volume information
  * @sv: scanning volume information
+ * @si: scanning information
  *
  * This function destroys the volume RB-tree (@sv->root) and the scanning
  * volume information.
  */
-static void destroy_sv(struct ubi_scan_volume *sv)
+static void destroy_sv(struct ubi_scan_info *si, struct ubi_scan_volume *sv)
 {
 	struct ubi_scan_leb *seb;
 	struct rb_node *this = sv->root.rb_node;
@@ -1247,7 +1270,7 @@
 					this->rb_right = NULL;
 			}
 
-			kfree(seb);
+			kmem_cache_free(si->scan_leb_slab, seb);
 		}
 	}
 	kfree(sv);
@@ -1265,19 +1288,19 @@
 
 	list_for_each_entry_safe(seb, seb_tmp, &si->alien, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 	list_for_each_entry_safe(seb, seb_tmp, &si->erase, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 	list_for_each_entry_safe(seb, seb_tmp, &si->corr, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 	list_for_each_entry_safe(seb, seb_tmp, &si->free, u.list) {
 		list_del(&seb->u.list);
-		kfree(seb);
+		kmem_cache_free(si->scan_leb_slab, seb);
 	}
 
 	/* Destroy the volume RB-tree */
@@ -1298,14 +1321,15 @@
 					rb->rb_right = NULL;
 			}
 
-			destroy_sv(sv);
+			destroy_sv(si, sv);
 		}
 	}
 
+	kmem_cache_destroy(si->scan_leb_slab);
 	kfree(si);
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_si - check the scanning information.
@@ -1323,6 +1347,9 @@
 	struct ubi_scan_leb *seb, *last_seb;
 	uint8_t *buf;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	/*
 	 * At first, check that scanning information is OK.
 	 */
@@ -1575,4 +1602,4 @@
 	return -EINVAL;
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/scan.h linux-libre-2.6.39-gnu/drivers/mtd/ubi/scan.h
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/scan.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/scan.h	2011-05-19 00:06:34.000000000 -0400
@@ -109,6 +109,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
+ * @scan_leb_slab: slab cache for &struct ubi_scan_leb objects
  *
  * 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
@@ -134,6 +135,7 @@
 	int mean_ec;
 	uint64_t ec_sum;
 	int ec_count;
+	struct kmem_cache *scan_leb_slab;
 };
 
 struct ubi_device;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/ubi.h linux-libre-2.6.39-gnu/drivers/mtd/ubi/ubi.h
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/ubi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/ubi.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 #include <linux/notifier.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/ubi.h>
+#include <asm/pgtable.h>
 
 #include "ubi-media.h"
 #include "scan.h"
@@ -381,14 +382,14 @@
  * @bad_allowed: whether the MTD device admits of bad physical eraseblocks or
  *               not
  * @nor_flash: non-zero if working on top of NOR flash
+ * @max_write_size: maximum amount of bytes the underlying flash can write at a
+ *                  time (MTD write buffer size)
  * @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
- * @dbg_peb_buf: buffer of PEB size used for debugging
- * @dbg_buf_mutex: protects @dbg_peb_buf
  */
 struct ubi_device {
 	struct cdev cdev;
@@ -464,16 +465,13 @@
 	int vid_hdr_shift;
 	unsigned int bad_allowed:1;
 	unsigned int nor_flash:1;
+	int max_write_size;
 	struct mtd_info *mtd;
 
 	void *peb_buf1;
 	void *peb_buf2;
 	struct mutex buf_mutex;
 	struct mutex ckvol_mutex;
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
-	void *dbg_peb_buf;
-	struct mutex dbg_buf_mutex;
-#endif
 };
 
 extern struct kmem_cache *ubi_wl_entry_slab;
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/vmt.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/vmt.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/vmt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/vmt.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,7 @@
 #include <linux/slab.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_volumes(struct ubi_device *ubi);
 #else
 #define paranoid_check_volumes(ubi) 0
@@ -711,7 +711,7 @@
 	volume_sysfs_close(vol);
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_volume - check volume information.
@@ -790,11 +790,6 @@
 		goto fail;
 	}
 
-	if (!vol->name) {
-		ubi_err("NULL volume name");
-		goto fail;
-	}
-
 	n = strnlen(vol->name, vol->name_len + 1);
 	if (n != vol->name_len) {
 		ubi_err("bad name_len %lld", n);
@@ -876,6 +871,9 @@
 {
 	int i, err = 0;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	for (i = 0; i < ubi->vtbl_slots; i++) {
 		err = paranoid_check_volume(ubi, i);
 		if (err)
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/vtbl.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/vtbl.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/vtbl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/vtbl.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 #include <asm/div64.h>
 #include "ubi.h"
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static void paranoid_vtbl_check(const struct ubi_device *ubi);
 #else
 #define paranoid_vtbl_check(ubi)
@@ -868,7 +868,7 @@
 	return err;
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_vtbl_check - check volume table.
@@ -876,10 +876,13 @@
  */
 static void paranoid_vtbl_check(const struct ubi_device *ubi)
 {
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return;
+
 	if (vtbl_check(ubi, ubi->vtbl)) {
 		ubi_err("paranoid check failed");
 		BUG();
 	}
 }
 
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/mtd/ubi/wl.c linux-libre-2.6.39-gnu/drivers/mtd/ubi/wl.c
--- linux-libre-2.6.38-gnu/drivers/mtd/ubi/wl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/mtd/ubi/wl.c	2011-05-19 00:06:34.000000000 -0400
@@ -161,7 +161,7 @@
 	int torture;
 };
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 static int paranoid_check_ec(struct ubi_device *ubi, int pnum, int ec);
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
 				     struct rb_root *root);
@@ -613,7 +613,7 @@
 	list_add_tail(&wrk->list, &ubi->works);
 	ubi_assert(ubi->works_count >= 0);
 	ubi->works_count += 1;
-	if (ubi->thread_enabled)
+	if (ubi->thread_enabled && !ubi_dbg_is_bgt_disabled())
 		wake_up_process(ubi->bgt_thread);
 	spin_unlock(&ubi->wl_lock);
 }
@@ -1364,7 +1364,7 @@
 
 		spin_lock(&ubi->wl_lock);
 		if (list_empty(&ubi->works) || ubi->ro_mode ||
-			       !ubi->thread_enabled) {
+		    !ubi->thread_enabled || ubi_dbg_is_bgt_disabled()) {
 			set_current_state(TASK_INTERRUPTIBLE);
 			spin_unlock(&ubi->wl_lock);
 			schedule();
@@ -1561,7 +1561,7 @@
 	kfree(ubi->lookuptbl);
 }
 
-#ifdef CONFIG_MTD_UBI_DEBUG_PARANOID
+#ifdef CONFIG_MTD_UBI_DEBUG
 
 /**
  * paranoid_check_ec - make sure that the erase counter of a PEB is correct.
@@ -1578,6 +1578,9 @@
 	long long read_ec;
 	struct ubi_ec_hdr *ec_hdr;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	ec_hdr = kzalloc(ubi->ec_hdr_alsize, GFP_NOFS);
 	if (!ec_hdr)
 		return -ENOMEM;
@@ -1614,6 +1617,9 @@
 static int paranoid_check_in_wl_tree(struct ubi_wl_entry *e,
 				     struct rb_root *root)
 {
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	if (in_wl_tree(e, root))
 		return 0;
 
@@ -1636,6 +1642,9 @@
 	struct ubi_wl_entry *p;
 	int i;
 
+	if (!(ubi_chk_flags & UBI_CHK_GEN))
+		return 0;
+
 	for (i = 0; i < UBI_PROT_QUEUE_LEN; ++i)
 		list_for_each_entry(p, &ubi->pq[i], u.list)
 			if (p == e)
@@ -1646,4 +1655,5 @@
 	ubi_dbg_dump_stack();
 	return -EINVAL;
 }
-#endif /* CONFIG_MTD_UBI_DEBUG_PARANOID */
+
+#endif /* CONFIG_MTD_UBI_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/net/3c501.c linux-libre-2.6.39-gnu/drivers/net/3c501.c
--- linux-libre-2.6.38-gnu/drivers/net/3c501.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/3c501.c	2011-05-19 00:06:34.000000000 -0400
@@ -399,7 +399,7 @@
  * as we may still be attempting to retrieve the last RX packet buffer.
  *
  * When a transmit times out we dump the card into control mode and just
- * start again. It happens enough that it isnt worth logging.
+ * start again. It happens enough that it isn't worth logging.
  *
  * We avoid holding the spin locks when doing the packet load to the board.
  * The device is very slow, and its DMA mode is even slower. If we held the
@@ -499,7 +499,7 @@
  *
  * Handle the ether interface interrupts. The 3c501 needs a lot more
  * hand holding than most cards. In particular we get a transmit interrupt
- * with a collision error because the board firmware isnt capable of rewinding
+ * with a collision error because the board firmware isn't capable of rewinding
  * its own transmit buffer pointers. It can however count to 16 for us.
  *
  * On the receive side the card is also very dumb. It has no buffering to
@@ -732,7 +732,7 @@
  * el_reset: Reset a 3c501 card
  * @dev: The 3c501 card about to get zapped
  *
- * Even resetting a 3c501 isnt simple. When you activate reset it loses all
+ * Even resetting a 3c501 isn't simple. When you activate reset it loses all
  * its configuration. You must hold the lock when doing this. The function
  * cannot take the lock itself as it is callable from the irq handler.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/3c523.c linux-libre-2.6.39-gnu/drivers/net/3c523.c
--- linux-libre-2.6.38-gnu/drivers/net/3c523.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/3c523.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,7 @@
    this for the 64K version would require a lot of heinous bank
    switching, which I'm sure not interested in doing.  If you try to
    implement a bank switching version, you'll basically have to remember
-   what bank is enabled and do a switch everytime you access a memory
+   what bank is enabled and do a switch every time you access a memory
    location that's not current.  You'll also have to remap pointers on
    the driver side, because it only knows about 16K of the memory.
    Anyone desperate or masochistic enough to try?
diff -druN linux-libre-2.6.38-gnu/drivers/net/3c527.c linux-libre-2.6.39-gnu/drivers/net/3c527.c
--- linux-libre-2.6.38-gnu/drivers/net/3c527.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/3c527.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
  *	circular buffer queues.
  *
  *	The mailboxes can be used for controlling how the card traverses
- *	its buffer rings, but are used only for inital setup in this
+ *	its buffer rings, but are used only for initial setup in this
  *	implementation.  The exec mailbox allows a variety of commands to
  *	be executed. Each command must complete before the next is
  *	executed. Primarily we use the exec mailbox for controlling the
@@ -813,7 +813,7 @@
  *
  *	This sets up the host transmit data-structures.
  *
- *	First, we obtain from the card it's current postion in the tx
+ *	First, we obtain from the card it's current position in the tx
  *	ring, so that we will know where to begin transmitting
  *	packets.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/net/3c59x.c linux-libre-2.6.39-gnu/drivers/net/3c59x.c
--- linux-libre-2.6.38-gnu/drivers/net/3c59x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/3c59x.c	2011-05-19 00:06:34.000000000 -0400
@@ -984,7 +984,7 @@
 		 * any device have been found when we exit from
 		 * eisa_driver_register (the bus root driver may not be
 		 * initialized yet). So we blindly assume something was
-		 * found, and let the sysfs magic happend...
+		 * found, and let the sysfs magic happened...
 		 */
 		eisa_found = 1;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/a2065.c linux-libre-2.6.39-gnu/drivers/net/a2065.c
--- linux-libre-2.6.38-gnu/drivers/net/a2065.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/a2065.c	2011-05-19 00:06:34.000000000 -0400
@@ -711,14 +711,14 @@
 		return -EBUSY;
 	r2 = request_mem_region(mem_start, A2065_RAM_SIZE, "RAM");
 	if (!r2) {
-		release_resource(r1);
+		release_mem_region(base_addr, sizeof(struct lance_regs));
 		return -EBUSY;
 	}
 
 	dev = alloc_etherdev(sizeof(struct lance_private));
 	if (dev == NULL) {
-		release_resource(r1);
-		release_resource(r2);
+		release_mem_region(base_addr, sizeof(struct lance_regs));
+		release_mem_region(mem_start, A2065_RAM_SIZE);
 		return -ENOMEM;
 	}
 
@@ -764,8 +764,8 @@
 
 	err = register_netdev(dev);
 	if (err) {
-		release_resource(r1);
-		release_resource(r2);
+		release_mem_region(base_addr, sizeof(struct lance_regs));
+		release_mem_region(mem_start, A2065_RAM_SIZE);
 		free_netdev(dev);
 		return err;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/acenic.c linux-libre-2.6.39-gnu/drivers/net/acenic.c
--- linux-libre-2.6.38-gnu/drivers/net/acenic.c	2012-03-24 01:06:10.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/acenic.c	2012-03-24 03:29:51.000000000 -0400
@@ -1584,7 +1584,7 @@
 	/*
 	 * We haven't received a stats update event for more than 2.5
 	 * seconds and there is data in the transmit queue, thus we
-	 * asume the card is stuck.
+	 * assume the card is stuck.
 	 */
 	if (*ap->tx_csm != ap->tx_ret_csm) {
 		printk(KERN_WARNING "%s: Transmitter is stuck, %08x\n",
@@ -2564,7 +2564,7 @@
 
 		/*
 		 * A TX-descriptor producer (an IRQ) might have gotten
-		 * inbetween, making the ring free again. Since xmit is
+		 * between, making the ring free again. Since xmit is
 		 * serialized, this is the only situation we have to
 		 * re-test.
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/amd8111e.c linux-libre-2.6.39-gnu/drivers/net/amd8111e.c
--- linux-libre-2.6.38-gnu/drivers/net/amd8111e.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/amd8111e.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(pci, amd8111e_pci_tbl);
 module_param_array(speed_duplex, int, NULL, 0);
-MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotitate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
+MODULE_PARM_DESC(speed_duplex, "Set device speed and duplex modes, 0: Auto Negotiate, 1: 10Mbps Half Duplex, 2: 10Mbps Full Duplex, 3: 100Mbps Half Duplex, 4: 100Mbps Full Duplex");
 module_param_array(coalesce, bool, NULL, 0);
 MODULE_PARM_DESC(coalesce, "Enable or Disable interrupt coalescing, 1: Enable, 0: Disable");
 module_param_array(dynamic_ipg, bool, NULL, 0);
@@ -1398,7 +1398,7 @@
 		mc_filter[1] = mc_filter[0] = 0;
 		lp->options &= ~OPTION_MULTICAST_ENABLE;
 		amd8111e_writeq(*(u64*)mc_filter,lp->mmio + LADRF);
-		/* disable promiscous mode */
+		/* disable promiscuous mode */
 		writel(PROM, lp->mmio + CMD2);
 		return;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/appletalk/Kconfig linux-libre-2.6.39-gnu/drivers/net/appletalk/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/appletalk/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/appletalk/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,6 @@
 #
 config ATALK
 	tristate "Appletalk protocol support"
-	depends on BKL # waiting to be removed from net/appletalk/ddp.c
 	select LLC
 	---help---
 	  AppleTalk is the protocol that Apple computers can use to communicate
diff -druN linux-libre-2.6.38-gnu/drivers/net/ariadne.c linux-libre-2.6.39-gnu/drivers/net/ariadne.c
--- linux-libre-2.6.38-gnu/drivers/net/ariadne.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ariadne.c	2011-05-19 00:06:34.000000000 -0400
@@ -182,14 +182,14 @@
 	return -EBUSY;
     r2 = request_mem_region(mem_start, ARIADNE_RAM_SIZE, "RAM");
     if (!r2) {
-	release_resource(r1);
+	release_mem_region(base_addr, sizeof(struct Am79C960));
 	return -EBUSY;
     }
 
     dev = alloc_etherdev(sizeof(struct ariadne_private));
     if (dev == NULL) {
-	release_resource(r1);
-	release_resource(r2);
+	release_mem_region(base_addr, sizeof(struct Am79C960));
+	release_mem_region(mem_start, ARIADNE_RAM_SIZE);
 	return -ENOMEM;
     }
 
@@ -213,8 +213,8 @@
 
     err = register_netdev(dev);
     if (err) {
-	release_resource(r1);
-	release_resource(r2);
+	release_mem_region(base_addr, sizeof(struct Am79C960));
+	release_mem_region(mem_start, ARIADNE_RAM_SIZE);
 	free_netdev(dev);
 	return err;
     }
diff -druN linux-libre-2.6.38-gnu/drivers/net/arm/etherh.c linux-libre-2.6.39-gnu/drivers/net/arm/etherh.c
--- linux-libre-2.6.38-gnu/drivers/net/arm/etherh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/arm/etherh.c	2011-05-19 00:06:34.000000000 -0400
@@ -527,7 +527,7 @@
  * Read the ethernet address string from the on board rom.
  * This is an ascii string...
  */
-static int __init etherh_addr(char *addr, struct expansion_card *ec)
+static int __devinit etherh_addr(char *addr, struct expansion_card *ec)
 {
 	struct in_chunk_dir cd;
 	char *s;
@@ -655,7 +655,7 @@
 static u32 etherh_regoffsets[16];
 static u32 etherm_regoffsets[16];
 
-static int __init
+static int __devinit
 etherh_probe(struct expansion_card *ec, const struct ecard_id *id)
 {
 	const struct etherh_data *data = id->data;
diff -druN linux-libre-2.6.38-gnu/drivers/net/at1700.c linux-libre-2.6.39-gnu/drivers/net/at1700.c
--- linux-libre-2.6.38-gnu/drivers/net/at1700.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/at1700.c	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,7 @@
 /* Run-time register bank 2 definitions. */
 #define DATAPORT		8		/* Word-wide DMA or programmed-I/O dataport. */
 #define TX_START		10
-#define COL16CNTL		11		/* Controll Reg for 16 collisions */
+#define COL16CNTL		11		/* Control Reg for 16 collisions */
 #define MODE13			13
 #define RX_CTRL			14
 /* Configuration registers only on the '865A/B chips. */
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c.h linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c.h
--- linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c.h	2011-05-19 00:06:34.000000000 -0400
@@ -265,7 +265,7 @@
 	__le32	word3;
 };
 
-/* RFD desciptor */
+/* RFD descriptor */
 struct atl1c_rx_free_desc {
 	__le64	buffer_addr;
 };
@@ -531,7 +531,7 @@
 	struct atl1c_buffer *buffer_info;
 };
 
-/* receive return desciptor (rrd) ring */
+/* receive return descriptor (rrd) ring */
 struct atl1c_rrd_ring {
 	void *desc;		/* descriptor ring virtual address */
 	dma_addr_t dma;		/* descriptor ring physical address */
@@ -566,9 +566,9 @@
 #define __AT_TESTING        0x0001
 #define __AT_RESETTING      0x0002
 #define __AT_DOWN           0x0003
-	u8 work_event;
-#define ATL1C_WORK_EVENT_RESET 		0x01
-#define ATL1C_WORK_EVENT_LINK_CHANGE	0x02
+	unsigned long work_event;
+#define	ATL1C_WORK_EVENT_RESET		0
+#define	ATL1C_WORK_EVENT_LINK_CHANGE	1
 	u32 msg_enable;
 
 	bool have_msi;
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_hw.c linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c_hw.c
--- linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c_hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -345,7 +345,7 @@
  */
 static int atl1c_phy_setup_adv(struct atl1c_hw *hw)
 {
-	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_SPEED_MASK;
+	u16 mii_adv_data = ADVERTISE_DEFAULT_CAP & ~ADVERTISE_ALL;
 	u16 mii_giga_ctrl_data = GIGA_CR_1000T_DEFAULT_CAP &
 				~GIGA_CR_1000T_SPEED_MASK;
 
@@ -373,7 +373,7 @@
 	}
 
 	if (atl1c_write_phy_reg(hw, MII_ADVERTISE, mii_adv_data) != 0 ||
-	    atl1c_write_phy_reg(hw, MII_GIGA_CR, mii_giga_ctrl_data) != 0)
+	    atl1c_write_phy_reg(hw, MII_CTRL1000, mii_giga_ctrl_data) != 0)
 		return -1;
 	return 0;
 }
@@ -517,19 +517,18 @@
 					"Error Setting up Auto-Negotiation\n");
 			return ret_val;
 		}
-		mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+		mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
 		break;
 	case MEDIA_TYPE_100M_FULL:
-		mii_bmcr_data |= BMCR_SPEED_100 | BMCR_FULL_DUPLEX;
+		mii_bmcr_data |= BMCR_SPEED100 | BMCR_FULLDPLX;
 		break;
 	case MEDIA_TYPE_100M_HALF:
-		mii_bmcr_data |= BMCR_SPEED_100;
+		mii_bmcr_data |= BMCR_SPEED100;
 		break;
 	case MEDIA_TYPE_10M_FULL:
-		mii_bmcr_data |= BMCR_SPEED_10 | BMCR_FULL_DUPLEX;
+		mii_bmcr_data |= BMCR_FULLDPLX;
 		break;
 	case MEDIA_TYPE_10M_HALF:
-		mii_bmcr_data |= BMCR_SPEED_10;
 		break;
 	default:
 		if (netif_msg_link(adapter))
@@ -657,7 +656,7 @@
 	err = atl1c_phy_setup_adv(hw);
 	if (err)
 		return err;
-	mii_bmcr_data |= BMCR_AUTO_NEG_EN | BMCR_RESTART_AUTO_NEG;
+	mii_bmcr_data |= BMCR_ANENABLE | BMCR_ANRESTART;
 
 	return atl1c_write_phy_reg(hw, MII_BMCR, mii_bmcr_data);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_hw.h linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -736,55 +736,16 @@
 #define REG_DEBUG_DATA0 		0x1900
 #define REG_DEBUG_DATA1 		0x1904
 
-/* PHY Control Register */
-#define MII_BMCR			0x00
-#define BMCR_SPEED_SELECT_MSB		0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define BMCR_COLL_TEST_ENABLE		0x0080  /* Collision test enable */
-#define BMCR_FULL_DUPLEX		0x0100  /* FDX =1, half duplex =0 */
-#define BMCR_RESTART_AUTO_NEG		0x0200  /* Restart auto negotiation */
-#define BMCR_ISOLATE			0x0400  /* Isolate PHY from MII */
-#define BMCR_POWER_DOWN			0x0800  /* Power down */
-#define BMCR_AUTO_NEG_EN		0x1000  /* Auto Neg Enable */
-#define BMCR_SPEED_SELECT_LSB		0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define BMCR_LOOPBACK			0x4000  /* 0 = normal, 1 = loopback */
-#define BMCR_RESET			0x8000  /* 0 = normal, 1 = PHY reset */
-#define BMCR_SPEED_MASK			0x2040
-#define BMCR_SPEED_1000			0x0040
-#define BMCR_SPEED_100			0x2000
-#define BMCR_SPEED_10			0x0000
-
-/* PHY Status Register */
-#define MII_BMSR			0x01
-#define BMMSR_EXTENDED_CAPS		0x0001  /* Extended register capabilities */
-#define BMSR_JABBER_DETECT		0x0002  /* Jabber Detected */
-#define BMSR_LINK_STATUS		0x0004  /* Link Status 1 = link */
-#define BMSR_AUTONEG_CAPS		0x0008  /* Auto Neg Capable */
-#define BMSR_REMOTE_FAULT		0x0010  /* Remote Fault Detect */
-#define BMSR_AUTONEG_COMPLETE		0x0020  /* Auto Neg Complete */
-#define BMSR_PREAMBLE_SUPPRESS		0x0040  /* Preamble may be suppressed */
-#define BMSR_EXTENDED_STATUS		0x0100  /* Ext. status info in Reg 0x0F */
-#define BMSR_100T2_HD_CAPS		0x0200  /* 100T2 Half Duplex Capable */
-#define BMSR_100T2_FD_CAPS		0x0400  /* 100T2 Full Duplex Capable */
-#define BMSR_10T_HD_CAPS		0x0800  /* 10T   Half Duplex Capable */
-#define BMSR_10T_FD_CAPS		0x1000  /* 10T   Full Duplex Capable */
-#define BMSR_100X_HD_CAPS		0x2000  /* 100X  Half Duplex Capable */
-#define BMMII_SR_100X_FD_CAPS		0x4000  /* 100X  Full Duplex Capable */
-#define BMMII_SR_100T4_CAPS		0x8000  /* 100T4 Capable */
-
-#define MII_PHYSID1			0x02
-#define MII_PHYSID2			0x03
 #define L1D_MPW_PHYID1			0xD01C  /* V7 */
 #define L1D_MPW_PHYID2			0xD01D  /* V1-V6 */
 #define L1D_MPW_PHYID3			0xD01E  /* V8 */
 
 
 /* Autoneg Advertisement Register */
-#define MII_ADVERTISE			0x04
-#define ADVERTISE_SPEED_MASK		0x01E0
-#define ADVERTISE_DEFAULT_CAP		0x0DE0
+#define ADVERTISE_DEFAULT_CAP \
+	(ADVERTISE_ALL | ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM)
 
 /* 1000BASE-T Control Register */
-#define MII_GIGA_CR			0x09
 #define GIGA_CR_1000T_REPEATER_DTE	0x0400  /* 1=Repeater/switch device port 0=DTE device */
 
 #define GIGA_CR_1000T_MS_VALUE		0x0800  /* 1=Configure PHY as Master 0=Configure PHY as Slave */
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_main.c linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c_main.c
--- linux-libre-2.6.38-gnu/drivers/net/atl1c/atl1c_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1c/atl1c_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -325,7 +325,7 @@
 		}
 	}
 
-	adapter->work_event |= ATL1C_WORK_EVENT_LINK_CHANGE;
+	set_bit(ATL1C_WORK_EVENT_LINK_CHANGE, &adapter->work_event);
 	schedule_work(&adapter->common_task);
 }
 
@@ -337,20 +337,16 @@
 	adapter = container_of(work, struct atl1c_adapter, common_task);
 	netdev = adapter->netdev;
 
-	if (adapter->work_event & ATL1C_WORK_EVENT_RESET) {
-		adapter->work_event &= ~ATL1C_WORK_EVENT_RESET;
+	if (test_and_clear_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event)) {
 		netif_device_detach(netdev);
 		atl1c_down(adapter);
 		atl1c_up(adapter);
 		netif_device_attach(netdev);
-		return;
 	}
 
-	if (adapter->work_event & ATL1C_WORK_EVENT_LINK_CHANGE) {
-		adapter->work_event &= ~ATL1C_WORK_EVENT_LINK_CHANGE;
+	if (test_and_clear_bit(ATL1C_WORK_EVENT_LINK_CHANGE,
+		&adapter->work_event))
 		atl1c_check_link_status(adapter);
-	}
-	return;
 }
 
 
@@ -369,7 +365,7 @@
 	struct atl1c_adapter *adapter = netdev_priv(netdev);
 
 	/* Do the reset outside of interrupt context */
-	adapter->work_event |= ATL1C_WORK_EVENT_RESET;
+	set_bit(ATL1C_WORK_EVENT_RESET, &adapter->work_event);
 	schedule_work(&adapter->common_task);
 }
 
@@ -1102,10 +1098,10 @@
 	AT_READ_REG(hw, REG_DEVICE_CTRL, &dev_ctrl_data);
 	max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT) &
 			DEVICE_CTRL_MAX_PAYLOAD_MASK;
-	hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+	hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block);
 	max_pay_load  = (dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT) &
 			DEVICE_CTRL_MAX_RREQ_SZ_MASK;
-	hw->dmar_block = min(max_pay_load, hw->dmar_block);
+	hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block);
 
 	txq_ctrl_data = (hw->tpd_burst & TXQ_NUM_TPD_BURST_MASK) <<
 			TXQ_NUM_TPD_BURST_SHIFT;
@@ -2718,7 +2714,6 @@
 		goto err_reset;
 	}
 
-	device_init_wakeup(&pdev->dev, 1);
 	/* reset the controller to
 	 * put the device in a known good starting state */
 	err = atl1c_phy_init(&adapter->hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_ethtool.c linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,18 +95,18 @@
 		ecmd->advertising = hw->autoneg_advertised |
 				    ADVERTISED_TP | ADVERTISED_Autoneg;
 
-		adv4 = hw->mii_autoneg_adv_reg & ~MII_AR_SPEED_MASK;
+		adv4 = hw->mii_autoneg_adv_reg & ~ADVERTISE_ALL;
 		adv9 = hw->mii_1000t_ctrl_reg & ~MII_AT001_CR_1000T_SPEED_MASK;
 		if (hw->autoneg_advertised & ADVERTISE_10_HALF)
-			adv4 |= MII_AR_10T_HD_CAPS;
+			adv4 |= ADVERTISE_10HALF;
 		if (hw->autoneg_advertised & ADVERTISE_10_FULL)
-			adv4 |= MII_AR_10T_FD_CAPS;
+			adv4 |= ADVERTISE_10FULL;
 		if (hw->autoneg_advertised & ADVERTISE_100_HALF)
-			adv4 |= MII_AR_100TX_HD_CAPS;
+			adv4 |= ADVERTISE_100HALF;
 		if (hw->autoneg_advertised & ADVERTISE_100_FULL)
-			adv4 |= MII_AR_100TX_FD_CAPS;
+			adv4 |= ADVERTISE_100FULL;
 		if (hw->autoneg_advertised & ADVERTISE_1000_FULL)
-			adv9 |= MII_AT001_CR_1000T_FD_CAPS;
+			adv9 |= ADVERTISE_1000FULL;
 
 		if (adv4 != hw->mii_autoneg_adv_reg ||
 				adv9 != hw->mii_1000t_ctrl_reg) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_hw.c linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_hw.c
--- linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -318,7 +318,7 @@
 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
 	 * the  1000Base-T control Register (Address 9).
 	 */
-	mii_autoneg_adv_reg &= ~MII_AR_SPEED_MASK;
+	mii_autoneg_adv_reg &= ~ADVERTISE_ALL;
 	mii_1000t_ctrl_reg  &= ~MII_AT001_CR_1000T_SPEED_MASK;
 
 	/*
@@ -327,44 +327,37 @@
 	 */
 	switch (hw->media_type) {
 	case MEDIA_TYPE_AUTO_SENSOR:
-		mii_autoneg_adv_reg |= (MII_AR_10T_HD_CAPS   |
-					MII_AR_10T_FD_CAPS   |
-					MII_AR_100TX_HD_CAPS |
-					MII_AR_100TX_FD_CAPS);
-		hw->autoneg_advertised = ADVERTISE_10_HALF  |
-					 ADVERTISE_10_FULL  |
-					 ADVERTISE_100_HALF |
-					 ADVERTISE_100_FULL;
+		mii_autoneg_adv_reg |= ADVERTISE_ALL;
+		hw->autoneg_advertised = ADVERTISE_ALL;
 		if (hw->nic_type == athr_l1e) {
-			mii_1000t_ctrl_reg |=
-				MII_AT001_CR_1000T_FD_CAPS;
+			mii_1000t_ctrl_reg |= ADVERTISE_1000FULL;
 			hw->autoneg_advertised |= ADVERTISE_1000_FULL;
 		}
 		break;
 
 	case MEDIA_TYPE_100M_FULL:
-		mii_autoneg_adv_reg   |= MII_AR_100TX_FD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_100FULL;
 		hw->autoneg_advertised = ADVERTISE_100_FULL;
 		break;
 
 	case MEDIA_TYPE_100M_HALF:
-		mii_autoneg_adv_reg   |= MII_AR_100TX_HD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_100_HALF;
 		hw->autoneg_advertised = ADVERTISE_100_HALF;
 		break;
 
 	case MEDIA_TYPE_10M_FULL:
-		mii_autoneg_adv_reg   |= MII_AR_10T_FD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_10_FULL;
 		hw->autoneg_advertised = ADVERTISE_10_FULL;
 		break;
 
 	default:
-		mii_autoneg_adv_reg   |= MII_AR_10T_HD_CAPS;
+		mii_autoneg_adv_reg   |= ADVERTISE_10_HALF;
 		hw->autoneg_advertised = ADVERTISE_10_HALF;
 		break;
 	}
 
 	/* flow control fixed to enable all */
-	mii_autoneg_adv_reg |= (MII_AR_ASM_DIR | MII_AR_PAUSE);
+	mii_autoneg_adv_reg |= (ADVERTISE_PAUSE_ASYM | ADVERTISE_PAUSE_CAP);
 
 	hw->mii_autoneg_adv_reg = mii_autoneg_adv_reg;
 	hw->mii_1000t_ctrl_reg  = mii_1000t_ctrl_reg;
@@ -374,7 +367,7 @@
 		return ret_val;
 
 	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
-		ret_val = atl1e_write_phy_reg(hw, MII_AT001_CR,
+		ret_val = atl1e_write_phy_reg(hw, MII_CTRL1000,
 					   mii_1000t_ctrl_reg);
 		if (ret_val)
 			return ret_val;
@@ -397,7 +390,7 @@
 	int ret_val;
 	u16 phy_data;
 
-	phy_data = MII_CR_RESET | MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG;
+	phy_data = BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART;
 
 	ret_val = atl1e_write_phy_reg(hw, MII_BMCR, phy_data);
 	if (ret_val) {
@@ -645,15 +638,14 @@
 		return err;
 
 	if (hw->nic_type == athr_l1e || hw->nic_type == athr_l2e_revA) {
-		err = atl1e_write_phy_reg(hw, MII_AT001_CR,
+		err = atl1e_write_phy_reg(hw, MII_CTRL1000,
 				       hw->mii_1000t_ctrl_reg);
 		if (err)
 			return err;
 	}
 
 	err = atl1e_write_phy_reg(hw, MII_BMCR,
-			MII_CR_RESET | MII_CR_AUTO_NEG_EN |
-			MII_CR_RESTART_AUTO_NEG);
+			BMCR_RESET | BMCR_ANENABLE | BMCR_ANRESTART);
 	return err;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_hw.h linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -629,127 +629,24 @@
 
 /***************************** MII definition ***************************************/
 /* PHY Common Register */
-#define MII_BMCR                        0x00
-#define MII_BMSR                        0x01
-#define MII_PHYSID1                     0x02
-#define MII_PHYSID2                     0x03
-#define MII_ADVERTISE                   0x04
-#define MII_LPA                         0x05
-#define MII_EXPANSION                   0x06
-#define MII_AT001_CR                    0x09
-#define MII_AT001_SR                    0x0A
-#define MII_AT001_ESR                   0x0F
 #define MII_AT001_PSCR                  0x10
 #define MII_AT001_PSSR                  0x11
 #define MII_INT_CTRL                    0x12
 #define MII_INT_STATUS                  0x13
 #define MII_SMARTSPEED                  0x14
-#define MII_RERRCOUNTER                 0x15
-#define MII_SREVISION                   0x16
-#define MII_RESV1                       0x17
 #define MII_LBRERROR                    0x18
-#define MII_PHYADDR                     0x19
 #define MII_RESV2                       0x1a
-#define MII_TPISTATUS                   0x1b
-#define MII_NCONFIG                     0x1c
 
 #define MII_DBG_ADDR			0x1D
 #define MII_DBG_DATA			0x1E
 
-
-/* PHY Control Register */
-#define MII_CR_SPEED_SELECT_MSB                  0x0040  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_COLL_TEST_ENABLE                  0x0080  /* Collision test enable */
-#define MII_CR_FULL_DUPLEX                       0x0100  /* FDX =1, half duplex =0 */
-#define MII_CR_RESTART_AUTO_NEG                  0x0200  /* Restart auto negotiation */
-#define MII_CR_ISOLATE                           0x0400  /* Isolate PHY from MII */
-#define MII_CR_POWER_DOWN                        0x0800  /* Power down */
-#define MII_CR_AUTO_NEG_EN                       0x1000  /* Auto Neg Enable */
-#define MII_CR_SPEED_SELECT_LSB                  0x2000  /* bits 6,13: 10=1000, 01=100, 00=10 */
-#define MII_CR_LOOPBACK                          0x4000  /* 0 = normal, 1 = loopback */
-#define MII_CR_RESET                             0x8000  /* 0 = normal, 1 = PHY reset */
-#define MII_CR_SPEED_MASK                        0x2040
-#define MII_CR_SPEED_1000                        0x0040
-#define MII_CR_SPEED_100                         0x2000
-#define MII_CR_SPEED_10                          0x0000
-
-
-/* PHY Status Register */
-#define MII_SR_EXTENDED_CAPS                     0x0001  /* Extended register capabilities */
-#define MII_SR_JABBER_DETECT                     0x0002  /* Jabber Detected */
-#define MII_SR_LINK_STATUS                       0x0004  /* Link Status 1 = link */
-#define MII_SR_AUTONEG_CAPS                      0x0008  /* Auto Neg Capable */
-#define MII_SR_REMOTE_FAULT                      0x0010  /* Remote Fault Detect */
-#define MII_SR_AUTONEG_COMPLETE                  0x0020  /* Auto Neg Complete */
-#define MII_SR_PREAMBLE_SUPPRESS                 0x0040  /* Preamble may be suppressed */
-#define MII_SR_EXTENDED_STATUS                   0x0100  /* Ext. status info in Reg 0x0F */
-#define MII_SR_100T2_HD_CAPS                     0x0200  /* 100T2 Half Duplex Capable */
-#define MII_SR_100T2_FD_CAPS                     0x0400  /* 100T2 Full Duplex Capable */
-#define MII_SR_10T_HD_CAPS                       0x0800  /* 10T   Half Duplex Capable */
-#define MII_SR_10T_FD_CAPS                       0x1000  /* 10T   Full Duplex Capable */
-#define MII_SR_100X_HD_CAPS                      0x2000  /* 100X  Half Duplex Capable */
-#define MII_SR_100X_FD_CAPS                      0x4000  /* 100X  Full Duplex Capable */
-#define MII_SR_100T4_CAPS                        0x8000  /* 100T4 Capable */
-
-/* Link partner ability register. */
-#define MII_LPA_SLCT                             0x001f  /* Same as advertise selector  */
-#define MII_LPA_10HALF                           0x0020  /* Can do 10mbps half-duplex   */
-#define MII_LPA_10FULL                           0x0040  /* Can do 10mbps full-duplex   */
-#define MII_LPA_100HALF                          0x0080  /* Can do 100mbps half-duplex  */
-#define MII_LPA_100FULL                          0x0100  /* Can do 100mbps full-duplex  */
-#define MII_LPA_100BASE4                         0x0200  /* 100BASE-T4  */
-#define MII_LPA_PAUSE                            0x0400  /* PAUSE */
-#define MII_LPA_ASYPAUSE                         0x0800  /* Asymmetrical PAUSE */
-#define MII_LPA_RFAULT                           0x2000  /* Link partner faulted        */
-#define MII_LPA_LPACK                            0x4000  /* Link partner acked us       */
-#define MII_LPA_NPAGE                            0x8000  /* Next page bit               */
-
 /* Autoneg Advertisement Register */
-#define MII_AR_SELECTOR_FIELD                   0x0001  /* indicates IEEE 802.3 CSMA/CD */
-#define MII_AR_10T_HD_CAPS                      0x0020  /* 10T   Half Duplex Capable */
-#define MII_AR_10T_FD_CAPS                      0x0040  /* 10T   Full Duplex Capable */
-#define MII_AR_100TX_HD_CAPS                    0x0080  /* 100TX Half Duplex Capable */
-#define MII_AR_100TX_FD_CAPS                    0x0100  /* 100TX Full Duplex Capable */
-#define MII_AR_100T4_CAPS                       0x0200  /* 100T4 Capable */
-#define MII_AR_PAUSE                            0x0400  /* Pause operation desired */
-#define MII_AR_ASM_DIR                          0x0800  /* Asymmetric Pause Direction bit */
-#define MII_AR_REMOTE_FAULT                     0x2000  /* Remote Fault detected */
-#define MII_AR_NEXT_PAGE                        0x8000  /* Next Page ability supported */
-#define MII_AR_SPEED_MASK                       0x01E0
-#define MII_AR_DEFAULT_CAP_MASK                 0x0DE0
+#define MII_AR_DEFAULT_CAP_MASK                 0
 
 /* 1000BASE-T Control Register */
-#define MII_AT001_CR_1000T_HD_CAPS              0x0100  /* Advertise 1000T HD capability */
-#define MII_AT001_CR_1000T_FD_CAPS              0x0200  /* Advertise 1000T FD capability  */
-#define MII_AT001_CR_1000T_REPEATER_DTE         0x0400  /* 1=Repeater/switch device port */
-/* 0=DTE device */
-#define MII_AT001_CR_1000T_MS_VALUE             0x0800  /* 1=Configure PHY as Master */
-/* 0=Configure PHY as Slave */
-#define MII_AT001_CR_1000T_MS_ENABLE            0x1000  /* 1=Master/Slave manual config value */
-/* 0=Automatic Master/Slave config */
-#define MII_AT001_CR_1000T_TEST_MODE_NORMAL     0x0000  /* Normal Operation */
-#define MII_AT001_CR_1000T_TEST_MODE_1          0x2000  /* Transmit Waveform test */
-#define MII_AT001_CR_1000T_TEST_MODE_2          0x4000  /* Master Transmit Jitter test */
-#define MII_AT001_CR_1000T_TEST_MODE_3          0x6000  /* Slave Transmit Jitter test */
-#define MII_AT001_CR_1000T_TEST_MODE_4          0x8000  /* Transmitter Distortion test */
-#define MII_AT001_CR_1000T_SPEED_MASK           0x0300
-#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK     0x0300
-
-/* 1000BASE-T Status Register */
-#define MII_AT001_SR_1000T_LP_HD_CAPS           0x0400  /* LP is 1000T HD capable */
-#define MII_AT001_SR_1000T_LP_FD_CAPS           0x0800  /* LP is 1000T FD capable */
-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS     0x1000  /* Remote receiver OK */
-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS      0x2000  /* Local receiver OK */
-#define MII_AT001_SR_1000T_MS_CONFIG_RES        0x4000  /* 1=Local TX is Master, 0=Slave */
-#define MII_AT001_SR_1000T_MS_CONFIG_FAULT      0x8000  /* Master/Slave config fault */
-#define MII_AT001_SR_1000T_REMOTE_RX_STATUS_SHIFT   12
-#define MII_AT001_SR_1000T_LOCAL_RX_STATUS_SHIFT    13
-
-/* Extended Status Register */
-#define MII_AT001_ESR_1000T_HD_CAPS             0x1000  /* 1000T HD capable */
-#define MII_AT001_ESR_1000T_FD_CAPS             0x2000  /* 1000T FD capable */
-#define MII_AT001_ESR_1000X_HD_CAPS             0x4000  /* 1000X HD capable */
-#define MII_AT001_ESR_1000X_FD_CAPS             0x8000  /* 1000X FD capable */
+#define MII_AT001_CR_1000T_SPEED_MASK \
+	(ADVERTISE_1000FULL | ADVERTISE_1000HALF)
+#define MII_AT001_CR_1000T_DEFAULT_CAP_MASK	MII_AT001_CR_1000T_SPEED_MASK
 
 /* AT001 PHY Specific Control Register */
 #define MII_AT001_PSCR_JABBER_DISABLE           0x0001  /* 1=Jabber Function disabled */
diff -druN linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_main.c linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_main.c
--- linux-libre-2.6.38-gnu/drivers/net/atl1e/atl1e_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atl1e/atl1e_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -547,8 +547,8 @@
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_id = pdev->subsystem_device;
+	hw->revision_id  = pdev->revision;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
 	phy_status_data = AT_READ_REG(hw, REG_PHY_STATUS);
@@ -932,11 +932,11 @@
 	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_PAYLOAD_SHIFT)) &
 			DEVICE_CTRL_MAX_PAYLOAD_MASK;
 
-	hw->dmaw_block = min(max_pay_load, hw->dmaw_block);
+	hw->dmaw_block = min_t(u32, max_pay_load, hw->dmaw_block);
 
 	max_pay_load  = ((dev_ctrl_data >> DEVICE_CTRL_MAX_RREQ_SZ_SHIFT)) &
 			DEVICE_CTRL_MAX_RREQ_SZ_MASK;
-	hw->dmar_block = min(max_pay_load, hw->dmar_block);
+	hw->dmar_block = min_t(u32, max_pay_load, hw->dmar_block);
 
 	if (hw->nic_type != athr_l2e_revB)
 		AT_WRITE_REGW(hw, REG_TXQ_CTRL + 2,
@@ -2051,9 +2051,9 @@
 		atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
 		atl1e_read_phy_reg(hw, MII_BMSR, (u16 *)&mii_bmsr_data);
 
-		mii_advertise_data = MII_AR_10T_HD_CAPS;
+		mii_advertise_data = ADVERTISE_10HALF;
 
-		if ((atl1e_write_phy_reg(hw, MII_AT001_CR, 0) != 0) ||
+		if ((atl1e_write_phy_reg(hw, MII_CTRL1000, 0) != 0) ||
 		    (atl1e_write_phy_reg(hw,
 			   MII_ADVERTISE, mii_advertise_data) != 0) ||
 		    (atl1e_phy_commit(hw)) != 0) {
@@ -2509,7 +2509,7 @@
 	.id_table = atl1e_pci_tbl,
 	.probe    = atl1e_probe,
 	.remove   = __devexit_p(atl1e_remove),
-	/* Power Managment Hooks */
+	/* Power Management Hooks */
 #ifdef CONFIG_PM
 	.suspend  = atl1e_suspend,
 	.resume   = atl1e_resume,
diff -druN linux-libre-2.6.38-gnu/drivers/net/atlx/atl1.c linux-libre-2.6.39-gnu/drivers/net/atlx/atl1.c
--- linux-libre-2.6.38-gnu/drivers/net/atlx/atl1.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atlx/atl1.c	2011-05-19 00:06:34.000000000 -0400
@@ -950,6 +950,7 @@
 	hw->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
 	adapter->wol = 0;
+	device_set_wakeup_enable(&adapter->pdev->dev, false);
 	adapter->rx_buffer_len = (hw->max_frame_size + 7) & ~7;
 	adapter->ict = 50000;		/* 100ms */
 	adapter->link_speed = SPEED_0;	/* hardware init */
@@ -2735,15 +2736,15 @@
 }
 
 #ifdef CONFIG_PM
-static int atl1_suspend(struct pci_dev *pdev, pm_message_t state)
+static int atl1_suspend(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct atl1_adapter *adapter = netdev_priv(netdev);
 	struct atl1_hw *hw = &adapter->hw;
 	u32 ctrl = 0;
 	u32 wufc = adapter->wol;
 	u32 val;
-	int retval;
 	u16 speed;
 	u16 duplex;
 
@@ -2751,17 +2752,15 @@
 	if (netif_running(netdev))
 		atl1_down(adapter);
 
-	retval = pci_save_state(pdev);
-	if (retval)
-		return retval;
-
 	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
 	atl1_read_phy_reg(hw, MII_BMSR, (u16 *) & ctrl);
 	val = ctrl & BMSR_LSTATUS;
 	if (val)
 		wufc &= ~ATLX_WUFC_LNKC;
+	if (!wufc)
+		goto disable_wol;
 
-	if (val && wufc) {
+	if (val) {
 		val = atl1_get_speed_and_duplex(hw, &speed, &duplex);
 		if (val) {
 			if (netif_msg_ifdown(adapter))
@@ -2798,23 +2797,18 @@
 		ctrl |= PCIE_PHYMISC_FORCE_RCV_DET;
 		iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
 		ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
-
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-		goto exit;
-	}
-
-	if (!val && wufc) {
+	} else {
 		ctrl |= (WOL_LINK_CHG_EN | WOL_LINK_CHG_PME_EN);
 		iowrite32(ctrl, hw->hw_addr + REG_WOL_CTRL);
 		ioread32(hw->hw_addr + REG_WOL_CTRL);
 		iowrite32(0, hw->hw_addr + REG_MAC_CTRL);
 		ioread32(hw->hw_addr + REG_MAC_CTRL);
 		hw->phy_configured = false;
-		pci_enable_wake(pdev, pci_choose_state(pdev, state), 1);
-		goto exit;
 	}
 
-disable_wol:
+	return 0;
+
+ disable_wol:
 	iowrite32(0, hw->hw_addr + REG_WOL_CTRL);
 	ioread32(hw->hw_addr + REG_WOL_CTRL);
 	ctrl = ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
@@ -2822,37 +2816,17 @@
 	iowrite32(ctrl, hw->hw_addr + REG_PCIE_PHYMISC);
 	ioread32(hw->hw_addr + REG_PCIE_PHYMISC);
 	hw->phy_configured = false;
-	pci_enable_wake(pdev, pci_choose_state(pdev, state), 0);
-exit:
-	if (netif_running(netdev))
-		pci_disable_msi(adapter->pdev);
-	pci_disable_device(pdev);
-	pci_set_power_state(pdev, pci_choose_state(pdev, state));
 
 	return 0;
 }
 
-static int atl1_resume(struct pci_dev *pdev)
+static int atl1_resume(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct atl1_adapter *adapter = netdev_priv(netdev);
-	u32 err;
-
-	pci_set_power_state(pdev, PCI_D0);
-	pci_restore_state(pdev);
 
-	err = pci_enable_device(pdev);
-	if (err) {
-		if (netif_msg_ifup(adapter))
-			dev_printk(KERN_DEBUG, &pdev->dev,
-				"error enabling pci device\n");
-		return err;
-	}
-
-	pci_set_master(pdev);
 	iowrite32(0, adapter->hw.hw_addr + REG_WOL_CTRL);
-	pci_enable_wake(pdev, PCI_D3hot, 0);
-	pci_enable_wake(pdev, PCI_D3cold, 0);
 
 	atl1_reset_hw(&adapter->hw);
 
@@ -2864,16 +2838,25 @@
 
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(atl1_pm_ops, atl1_suspend, atl1_resume);
+#define ATL1_PM_OPS	(&atl1_pm_ops)
+
 #else
-#define atl1_suspend NULL
-#define atl1_resume NULL
+
+static int atl1_suspend(struct device *dev) { return 0; }
+
+#define ATL1_PM_OPS	NULL
 #endif
 
 static void atl1_shutdown(struct pci_dev *pdev)
 {
-#ifdef CONFIG_PM
-	atl1_suspend(pdev, PMSG_SUSPEND);
-#endif
+	struct net_device *netdev = pci_get_drvdata(pdev);
+	struct atl1_adapter *adapter = netdev_priv(netdev);
+
+	atl1_suspend(&pdev->dev);
+	pci_wake_from_d3(pdev, adapter->wol);
+	pci_set_power_state(pdev, PCI_D3hot);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -3117,9 +3100,8 @@
 	.id_table = atl1_pci_tbl,
 	.probe = atl1_probe,
 	.remove = __devexit_p(atl1_remove),
-	.suspend = atl1_suspend,
-	.resume = atl1_resume,
-	.shutdown = atl1_shutdown
+	.shutdown = atl1_shutdown,
+	.driver.pm = ATL1_PM_OPS,
 };
 
 /*
@@ -3409,6 +3391,9 @@
 	adapter->wol = 0;
 	if (wol->wolopts & WAKE_MAGIC)
 		adapter->wol |= ATLX_WUFC_MAG;
+
+	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/atlx/atl2.c linux-libre-2.6.39-gnu/drivers/net/atlx/atl2.c
--- linux-libre-2.6.38-gnu/drivers/net/atlx/atl2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/atlx/atl2.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,8 +93,8 @@
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_id = pdev->subsystem_device;
+	hw->revision_id  = pdev->revision;
 
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
 	pci_read_config_word(pdev, PCI_COMMAND, &hw->pci_cmd_word);
 
 	adapter->wol = 0;
@@ -1701,7 +1701,7 @@
 	.id_table = atl2_pci_tbl,
 	.probe    = atl2_probe,
 	.remove   = __devexit_p(atl2_remove),
-	/* Power Managment Hooks */
+	/* Power Management Hooks */
 	.suspend  = atl2_suspend,
 #ifdef CONFIG_PM
 	.resume   = atl2_resume,
@@ -1996,13 +1996,15 @@
 	if (!eeprom_buff)
 		return -ENOMEM;
 
-	ptr = (u32 *)eeprom_buff;
+	ptr = eeprom_buff;
 
 	if (eeprom->offset & 3) {
 		/* need read/modify/write of first changed EEPROM word */
 		/* only the second byte of the word is being modified */
-		if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0])))
-			return -EIO;
+		if (!atl2_read_eeprom(hw, first_dword*4, &(eeprom_buff[0]))) {
+			ret_val = -EIO;
+			goto out;
+		}
 		ptr++;
 	}
 	if (((eeprom->offset + eeprom->len) & 3)) {
@@ -2011,18 +2013,22 @@
 		 * only the first byte of the word is being modified
 		 */
 		if (!atl2_read_eeprom(hw, last_dword * 4,
-			&(eeprom_buff[last_dword - first_dword])))
-			return -EIO;
+					&(eeprom_buff[last_dword - first_dword]))) {
+			ret_val = -EIO;
+			goto out;
+		}
 	}
 
 	/* Device's eeprom is always little-endian, word addressable */
 	memcpy(ptr, bytes, eeprom->len);
 
 	for (i = 0; i < last_dword - first_dword + 1; i++) {
-		if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i]))
-			return -EIO;
+		if (!atl2_write_eeprom(hw, ((first_dword+i)*4), eeprom_buff[i])) {
+			ret_val = -EIO;
+			goto out;
+		}
 	}
-
+ out:
 	kfree(eeprom_buff);
 	return ret_val;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/ax88796.c linux-libre-2.6.39-gnu/drivers/net/ax88796.c
--- linux-libre-2.6.38-gnu/drivers/net/ax88796.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ax88796.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
  * 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>
@@ -17,46 +17,45 @@
 #include <linux/isapnp.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/delay.h>
 #include <linux/timer.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
-#include <linux/mii.h>
+#include <linux/mdio-bitbang.h>
+#include <linux/phy.h>
 #include <linux/eeprom_93cx6.h>
 #include <linux/slab.h>
 
 #include <net/ax88796.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
-
-static int phy_debug = 0;
 
 /* Rename the lib8390.c functions to show that they are in this driver */
-#define __ei_open       ax_ei_open
-#define __ei_close      ax_ei_close
-#define __ei_poll	ax_ei_poll
+#define __ei_open ax_ei_open
+#define __ei_close ax_ei_close
+#define __ei_poll ax_ei_poll
 #define __ei_start_xmit ax_ei_start_xmit
 #define __ei_tx_timeout ax_ei_tx_timeout
-#define __ei_get_stats  ax_ei_get_stats
+#define __ei_get_stats ax_ei_get_stats
 #define __ei_set_multicast_list ax_ei_set_multicast_list
-#define __ei_interrupt  ax_ei_interrupt
+#define __ei_interrupt ax_ei_interrupt
 #define ____alloc_ei_netdev ax__alloc_ei_netdev
-#define __NS8390_init   ax_NS8390_init
+#define __NS8390_init ax_NS8390_init
 
 /* force unsigned long back to 'void __iomem *' */
 #define ax_convert_addr(_a) ((void __force __iomem *)(_a))
 
-#define ei_inb(_a)	readb(ax_convert_addr(_a))
+#define ei_inb(_a) readb(ax_convert_addr(_a))
 #define ei_outb(_v, _a) writeb(_v, ax_convert_addr(_a))
 
-#define ei_inb_p(_a)	ei_inb(_a)
+#define ei_inb_p(_a) ei_inb(_a)
 #define ei_outb_p(_v, _a) ei_outb(_v, _a)
 
 /* define EI_SHIFT() to take into account our register offsets */
-#define EI_SHIFT(x)     (ei_local->reg_offset[(x)])
+#define EI_SHIFT(x) (ei_local->reg_offset[(x)])
 
 /* Ensure we have our RCR base value */
 #define AX88796_PLATFORM
@@ -74,43 +73,46 @@
 #define NE_DATAPORT	EI_SHIFT(0x10)
 
 #define NE1SM_START_PG	0x20	/* First page of TX buffer */
-#define NE1SM_STOP_PG 	0x40	/* Last page +1 of RX ring */
+#define NE1SM_STOP_PG	0x40	/* Last page +1 of RX ring */
 #define NESM_START_PG	0x40	/* First page of TX buffer */
 #define NESM_STOP_PG	0x80	/* Last page +1 of RX ring */
 
+#define AX_GPOC_PPDSET	BIT(6)
+
 /* device private data */
 
 struct ax_device {
-	struct timer_list	 mii_timer;
-	spinlock_t		 mii_lock;
-	struct mii_if_info	 mii;
+	struct mii_bus *mii_bus;
+	struct mdiobb_ctrl bb_ctrl;
+	struct phy_device *phy_dev;
+	void __iomem *addr_memr;
+	u8 reg_memr;
+	int link;
+	int speed;
+	int duplex;
 
-	u32			 msg_enable;
-	void __iomem		*map2;
-	struct platform_device	*dev;
-	struct resource		*mem;
-	struct resource		*mem2;
-	struct ax_plat_data	*plat;
+	void __iomem *map2;
+	const struct ax_plat_data *plat;
 
-	unsigned char		 running;
-	unsigned char		 resume_open;
-	unsigned int		 irqflags;
+	unsigned char running;
+	unsigned char resume_open;
+	unsigned int irqflags;
 
-	u32			 reg_offsets[0x20];
+	u32 reg_offsets[0x20];
 };
 
 static inline struct ax_device *to_ax_dev(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	return (struct ax_device *)(ei_local+1);
+	return (struct ax_device *)(ei_local + 1);
 }
 
-/* ax_initial_check
+/*
+ * ax_initial_check
  *
  * do an initial probe for the card to check wether it exists
  * and is functional
  */
-
 static int ax_initial_check(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
@@ -122,10 +124,10 @@
 	if (reg0 == 0xFF)
 		return -ENODEV;
 
-	ei_outb(E8390_NODMA+E8390_PAGE1+E8390_STOP, ioaddr + E8390_CMD);
+	ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, ioaddr + E8390_CMD);
 	regd = ei_inb(ioaddr + 0x0d);
 	ei_outb(0xff, ioaddr + 0x0d);
-	ei_outb(E8390_NODMA+E8390_PAGE0, ioaddr + E8390_CMD);
+	ei_outb(E8390_NODMA + E8390_PAGE0, ioaddr + E8390_CMD);
 	ei_inb(ioaddr + EN0_COUNTER0); /* Clear the counter by reading. */
 	if (ei_inb(ioaddr + EN0_COUNTER0) != 0) {
 		ei_outb(reg0, ioaddr);
@@ -136,29 +138,28 @@
 	return 0;
 }
 
-/* Hard reset the card.  This used to pause for the same period that a
-   8390 reset command required, but that shouldn't be necessary. */
-
+/*
+ * Hard reset the card. This used to pause for the same period that a
+ * 8390 reset command required, but that shouldn't be necessary.
+ */
 static void ax_reset_8390(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	unsigned long reset_start_time = jiffies;
 	void __iomem *addr = (void __iomem *)dev->base_addr;
 
 	if (ei_debug > 1)
-		dev_dbg(&ax->dev->dev, "resetting the 8390 t=%ld\n", jiffies);
+		netdev_dbg(dev, "resetting the 8390 t=%ld\n", jiffies);
 
 	ei_outb(ei_inb(addr + NE_RESET), addr + NE_RESET);
 
-	ei_status.txing = 0;
-	ei_status.dmaing = 0;
+	ei_local->txing = 0;
+	ei_local->dmaing = 0;
 
 	/* This check _should_not_ be necessary, omit eventually. */
 	while ((ei_inb(addr + EN0_ISR) & ENISR_RESET) == 0) {
-		if (jiffies - reset_start_time > 2*HZ/100) {
-			dev_warn(&ax->dev->dev, "%s: %s did not complete.\n",
-			       __func__, dev->name);
+		if (jiffies - reset_start_time > 2 * HZ / 100) {
+			netdev_warn(dev, "%s: did not complete.\n", __func__);
 			break;
 		}
 	}
@@ -171,70 +172,72 @@
 			    int ring_page)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	void __iomem *nic_base = ei_local->mem;
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing) {
-		dev_err(&ax->dev->dev, "%s: DMAing conflict in %s "
+	if (ei_local->dmaing) {
+		netdev_err(dev, "DMAing conflict in %s "
 			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, __func__,
-			ei_status.dmaing, ei_status.irqlock);
+			__func__,
+			ei_local->dmaing, ei_local->irqlock);
 		return;
 	}
 
-	ei_status.dmaing |= 0x01;
-	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_local->dmaing |= 0x01;
+	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_START, nic_base + NE_CMD);
 	ei_outb(sizeof(struct e8390_pkt_hdr), nic_base + EN0_RCNTLO);
 	ei_outb(0, nic_base + EN0_RCNTHI);
 	ei_outb(0, nic_base + EN0_RSARLO);		/* On page boundary */
 	ei_outb(ring_page, nic_base + EN0_RSARHI);
 	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-	if (ei_status.word16)
-		readsw(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr)>>1);
+	if (ei_local->word16)
+		readsw(nic_base + NE_DATAPORT, hdr,
+		       sizeof(struct e8390_pkt_hdr) >> 1);
 	else
-		readsb(nic_base + NE_DATAPORT, hdr, sizeof(struct e8390_pkt_hdr));
+		readsb(nic_base + NE_DATAPORT, hdr,
+		       sizeof(struct e8390_pkt_hdr));
 
 	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
+	ei_local->dmaing &= ~0x01;
 
 	le16_to_cpus(&hdr->count);
 }
 
 
-/* Block input and output, similar to the Crynwr packet driver.  If you
-   are porting to a new ethercard, look at the packet driver source for hints.
-   The NEx000 doesn't share the on-board packet memory -- you have to put
-   the packet out through the "remote DMA" dataport using ei_outb. */
-
+/*
+ * Block input and output, similar to the Crynwr packet driver. If
+ * you are porting to a new ethercard, look at the packet driver
+ * source for hints. The NEx000 doesn't share the on-board packet
+ * memory -- you have to put the packet out through the "remote DMA"
+ * dataport using ei_outb.
+ */
 static void ax_block_input(struct net_device *dev, int count,
 			   struct sk_buff *skb, int ring_offset)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	void __iomem *nic_base = ei_local->mem;
 	char *buf = skb->data;
 
-	if (ei_status.dmaing) {
-		dev_err(&ax->dev->dev,
-			"%s: DMAing conflict in %s "
+	if (ei_local->dmaing) {
+		netdev_err(dev,
+			"DMAing conflict in %s "
 			"[DMAstat:%d][irqlock:%d].\n",
-			dev->name, __func__,
-			ei_status.dmaing, ei_status.irqlock);
+			__func__,
+			ei_local->dmaing, ei_local->irqlock);
 		return;
 	}
 
-	ei_status.dmaing |= 0x01;
+	ei_local->dmaing |= 0x01;
 
-	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base+ NE_CMD);
+	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_START, nic_base + NE_CMD);
 	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
 	ei_outb(count >> 8, nic_base + EN0_RCNTHI);
 	ei_outb(ring_offset & 0xff, nic_base + EN0_RSARLO);
 	ei_outb(ring_offset >> 8, nic_base + EN0_RSARHI);
 	ei_outb(E8390_RREAD+E8390_START, nic_base + NE_CMD);
 
-	if (ei_status.word16) {
+	if (ei_local->word16) {
 		readsw(nic_base + NE_DATAPORT, buf, count >> 1);
 		if (count & 0x01)
 			buf[count-1] = ei_inb(nic_base + NE_DATAPORT);
@@ -243,34 +246,34 @@
 		readsb(nic_base + NE_DATAPORT, buf, count);
 	}
 
-	ei_status.dmaing &= ~1;
+	ei_local->dmaing &= ~1;
 }
 
 static void ax_block_output(struct net_device *dev, int count,
 			    const unsigned char *buf, const int start_page)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
 	void __iomem *nic_base = ei_local->mem;
 	unsigned long dma_start;
 
-	/* Round the count up for word writes.  Do we need to do this?
-	   What effect will an odd byte count have on the 8390?
-	   I should check someday. */
-
-	if (ei_status.word16 && (count & 0x01))
+	/*
+	 * Round the count up for word writes. Do we need to do this?
+	 * What effect will an odd byte count have on the 8390?  I
+	 * should check someday.
+	 */
+	if (ei_local->word16 && (count & 0x01))
 		count++;
 
 	/* This *shouldn't* happen. If it does, it's the last thing you'll see */
-	if (ei_status.dmaing) {
-		dev_err(&ax->dev->dev, "%s: DMAing conflict in %s."
+	if (ei_local->dmaing) {
+		netdev_err(dev, "DMAing conflict in %s."
 			"[DMAstat:%d][irqlock:%d]\n",
-			dev->name, __func__,
-		       ei_status.dmaing, ei_status.irqlock);
+			__func__,
+		       ei_local->dmaing, ei_local->irqlock);
 		return;
 	}
 
-	ei_status.dmaing |= 0x01;
+	ei_local->dmaing |= 0x01;
 	/* We should already be in page 0, but to be safe... */
 	ei_outb(E8390_PAGE0+E8390_START+E8390_NODMA, nic_base + NE_CMD);
 
@@ -278,250 +281,170 @@
 
 	/* Now the normal output. */
 	ei_outb(count & 0xff, nic_base + EN0_RCNTLO);
-	ei_outb(count >> 8,   nic_base + EN0_RCNTHI);
+	ei_outb(count >> 8, nic_base + EN0_RCNTHI);
 	ei_outb(0x00, nic_base + EN0_RSARLO);
 	ei_outb(start_page, nic_base + EN0_RSARHI);
 
 	ei_outb(E8390_RWRITE+E8390_START, nic_base + NE_CMD);
-	if (ei_status.word16) {
-		writesw(nic_base + NE_DATAPORT, buf, count>>1);
-	} else {
+	if (ei_local->word16)
+		writesw(nic_base + NE_DATAPORT, buf, count >> 1);
+	else
 		writesb(nic_base + NE_DATAPORT, buf, count);
-	}
 
 	dma_start = jiffies;
 
 	while ((ei_inb(nic_base + EN0_ISR) & ENISR_RDC) == 0) {
-		if (jiffies - dma_start > 2*HZ/100) {		/* 20ms */
-			dev_warn(&ax->dev->dev,
-				 "%s: timeout waiting for Tx RDC.\n", dev->name);
+		if (jiffies - dma_start > 2 * HZ / 100) {		/* 20ms */
+			netdev_warn(dev, "timeout waiting for Tx RDC.\n");
 			ax_reset_8390(dev);
-			ax_NS8390_init(dev,1);
+			ax_NS8390_init(dev, 1);
 			break;
 		}
 	}
 
 	ei_outb(ENISR_RDC, nic_base + EN0_ISR);	/* Ack intr. */
-	ei_status.dmaing &= ~0x01;
+	ei_local->dmaing &= ~0x01;
 }
 
 /* definitions for accessing MII/EEPROM interface */
 
 #define AX_MEMR			EI_SHIFT(0x14)
-#define AX_MEMR_MDC		(1<<0)
-#define AX_MEMR_MDIR		(1<<1)
-#define AX_MEMR_MDI		(1<<2)
-#define AX_MEMR_MDO		(1<<3)
-#define AX_MEMR_EECS		(1<<4)
-#define AX_MEMR_EEI		(1<<5)
-#define AX_MEMR_EEO		(1<<6)
-#define AX_MEMR_EECLK		(1<<7)
-
-/* ax_mii_ei_outbits
- *
- * write the specified set of bits to the phy
-*/
+#define AX_MEMR_MDC		BIT(0)
+#define AX_MEMR_MDIR		BIT(1)
+#define AX_MEMR_MDI		BIT(2)
+#define AX_MEMR_MDO		BIT(3)
+#define AX_MEMR_EECS		BIT(4)
+#define AX_MEMR_EEI		BIT(5)
+#define AX_MEMR_EEO		BIT(6)
+#define AX_MEMR_EECLK		BIT(7)
 
-static void
-ax_mii_ei_outbits(struct net_device *dev, unsigned int bits, int len)
+static void ax_handle_link_change(struct net_device *dev)
 {
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
-	unsigned int memr;
-
-	/* clock low, data to output mode */
-	memr = ei_inb(memr_addr);
-	memr &= ~(AX_MEMR_MDC | AX_MEMR_MDIR);
-	ei_outb(memr, memr_addr);
-
-	for (len--; len >= 0; len--) {
-		if (bits & (1 << len))
-			memr |= AX_MEMR_MDO;
-		else
-			memr &= ~AX_MEMR_MDO;
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = ax->phy_dev;
+	int status_change = 0;
 
-		ei_outb(memr, memr_addr);
+	if (phy_dev->link && ((ax->speed != phy_dev->speed) ||
+			     (ax->duplex != phy_dev->duplex))) {
 
-		/* clock high */
+		ax->speed = phy_dev->speed;
+		ax->duplex = phy_dev->duplex;
+		status_change = 1;
+	}
 
-		ei_outb(memr | AX_MEMR_MDC, memr_addr);
-		udelay(1);
+	if (phy_dev->link != ax->link) {
+		if (!phy_dev->link) {
+			ax->speed = 0;
+			ax->duplex = -1;
+		}
+		ax->link = phy_dev->link;
 
-		/* clock low */
-		ei_outb(memr, memr_addr);
+		status_change = 1;
 	}
 
-	/* leaves the clock line low, mdir input */
-	memr |= AX_MEMR_MDIR;
-	ei_outb(memr, (void __iomem *)dev->base_addr + AX_MEMR);
+	if (status_change)
+		phy_print_status(phy_dev);
 }
 
-/* ax_phy_ei_inbits
- *
- * read a specified number of bits from the phy
-*/
-
-static unsigned int
-ax_phy_ei_inbits(struct net_device *dev, int no)
+static int ax_mii_probe(struct net_device *dev)
 {
-	struct ei_device *ei_local = netdev_priv(dev);
-	void __iomem *memr_addr = (void __iomem *)dev->base_addr + AX_MEMR;
-	unsigned int memr;
-	unsigned int result = 0;
-
-	/* clock low, data to input mode */
-	memr = ei_inb(memr_addr);
-	memr &= ~AX_MEMR_MDC;
-	memr |= AX_MEMR_MDIR;
-	ei_outb(memr, memr_addr);
-
-	for (no--; no >= 0; no--) {
-		ei_outb(memr | AX_MEMR_MDC, memr_addr);
-
-		udelay(1);
+	struct ax_device  *ax = to_ax_dev(dev);
+	struct phy_device *phy_dev = NULL;
+	int ret;
 
-		if (ei_inb(memr_addr) & AX_MEMR_MDI)
-			result |= (1<<no);
+	/* find the first phy */
+	phy_dev = phy_find_first(ax->mii_bus);
+	if (!phy_dev) {
+		netdev_err(dev, "no PHY found\n");
+		return -ENODEV;
+	}
 
-		ei_outb(memr, memr_addr);
+	ret = phy_connect_direct(dev, phy_dev, ax_handle_link_change, 0,
+				 PHY_INTERFACE_MODE_MII);
+	if (ret) {
+		netdev_err(dev, "Could not attach to PHY\n");
+		return ret;
 	}
 
-	return result;
-}
+	/* mask with MAC supported features */
+	phy_dev->supported &= PHY_BASIC_FEATURES;
+	phy_dev->advertising = phy_dev->supported;
 
-/* ax_phy_issueaddr
- *
- * use the low level bit shifting routines to send the address
- * and command to the specified phy
-*/
+	ax->phy_dev = phy_dev;
 
-static void
-ax_phy_issueaddr(struct net_device *dev, int phy_addr, int reg, int opc)
-{
-	if (phy_debug)
-		pr_debug("%s: dev %p, %04x, %04x, %d\n",
-			__func__, dev, phy_addr, reg, opc);
+	netdev_info(dev, "PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n",
+		    phy_dev->drv->name, dev_name(&phy_dev->dev), phy_dev->irq);
 
-	ax_mii_ei_outbits(dev, 0x3f, 6);	/* pre-amble */
-	ax_mii_ei_outbits(dev, 1, 2);		/* frame-start */
-	ax_mii_ei_outbits(dev, opc, 2);		/* op code */
-	ax_mii_ei_outbits(dev, phy_addr, 5);	/* phy address */
-	ax_mii_ei_outbits(dev, reg, 5);		/* reg address */
+	return 0;
 }
 
-static int
-ax_phy_read(struct net_device *dev, int phy_addr, int reg)
+static void ax_phy_switch(struct net_device *dev, int on)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
-	unsigned long flags;
- 	unsigned int result;
-
-      	spin_lock_irqsave(&ei_local->page_lock, flags);
-
-	ax_phy_issueaddr(dev, phy_addr, reg, 2);
-
-	result = ax_phy_ei_inbits(dev, 17);
-	result &= ~(3<<16);
-
-      	spin_unlock_irqrestore(&ei_local->page_lock, flags);
-
-	if (phy_debug)
-		pr_debug("%s: %04x.%04x => read %04x\n", __func__,
-			 phy_addr, reg, result);
-
-	return result;
-}
-
-static void
-ax_phy_write(struct net_device *dev, int phy_addr, int reg, int value)
-{
-	struct ei_device *ei = netdev_priv(dev);
-	struct ax_device  *ax = to_ax_dev(dev);
-	unsigned long flags;
-
-	dev_dbg(&ax->dev->dev, "%s: %p, %04x, %04x %04x\n",
-		__func__, dev, phy_addr, reg, value);
-
-      	spin_lock_irqsave(&ei->page_lock, flags);
-
-	ax_phy_issueaddr(dev, phy_addr, reg, 1);
-	ax_mii_ei_outbits(dev, 2, 2);		/* send TA */
-	ax_mii_ei_outbits(dev, value, 16);
-
-      	spin_unlock_irqrestore(&ei->page_lock, flags);
-}
+	struct ax_device *ax = to_ax_dev(dev);
 
-static void ax_mii_expiry(unsigned long data)
-{
-	struct net_device *dev = (struct net_device *)data;
-	struct ax_device  *ax = to_ax_dev(dev);
-	unsigned long flags;
+	u8 reg_gpoc =  ax->plat->gpoc_val;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	mii_check_media(&ax->mii, netif_msg_link(ax), 0);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
+	if (!!on)
+		reg_gpoc &= ~AX_GPOC_PPDSET;
+	else
+		reg_gpoc |= AX_GPOC_PPDSET;
 
-	if (ax->running) {
-		ax->mii_timer.expires = jiffies + HZ*2;
-		add_timer(&ax->mii_timer);
-	}
+	ei_outb(reg_gpoc, ei_local->mem + EI_SHIFT(0x17));
 }
 
 static int ax_open(struct net_device *dev)
 {
-	struct ax_device  *ax = to_ax_dev(dev);
-	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
 	int ret;
 
-	dev_dbg(&ax->dev->dev, "%s: open\n", dev->name);
+	netdev_dbg(dev, "open\n");
 
 	ret = request_irq(dev->irq, ax_ei_interrupt, ax->irqflags,
 			  dev->name, dev);
 	if (ret)
-		return ret;
-
-	ret = ax_ei_open(dev);
-	if (ret) {
-		free_irq(dev->irq, dev);
-		return ret;
-	}
+		goto failed_request_irq;
 
 	/* turn the phy on (if turned off) */
+	ax_phy_switch(dev, 1);
 
-	ei_outb(ax->plat->gpoc_val, ei_local->mem + EI_SHIFT(0x17));
-	ax->running = 1;
-
-	/* start the MII timer */
-
-	init_timer(&ax->mii_timer);
+	ret = ax_mii_probe(dev);
+	if (ret)
+		goto failed_mii_probe;
+	phy_start(ax->phy_dev);
 
-	ax->mii_timer.expires  = jiffies+1;
-	ax->mii_timer.data     = (unsigned long) dev;
-	ax->mii_timer.function = ax_mii_expiry;
+	ret = ax_ei_open(dev);
+	if (ret)
+		goto failed_ax_ei_open;
 
-	add_timer(&ax->mii_timer);
+	ax->running = 1;
 
 	return 0;
+
+ failed_ax_ei_open:
+	phy_disconnect(ax->phy_dev);
+ failed_mii_probe:
+	ax_phy_switch(dev, 0);
+	free_irq(dev->irq, dev);
+ failed_request_irq:
+	return ret;
 }
 
 static int ax_close(struct net_device *dev)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	struct ei_device *ei_local = netdev_priv(dev);
 
-	dev_dbg(&ax->dev->dev, "%s: close\n", dev->name);
-
-	/* turn the phy off */
-
-	ei_outb(ax->plat->gpoc_val | (1<<6),
-	       ei_local->mem + EI_SHIFT(0x17));
+	netdev_dbg(dev, "close\n");
 
 	ax->running = 0;
 	wmb();
 
-	del_timer_sync(&ax->mii_timer);
 	ax_ei_close(dev);
 
+	/* turn the phy off */
+	ax_phy_switch(dev, 0);
+	phy_disconnect(ax->phy_dev);
+
 	free_irq(dev->irq, dev);
 	return 0;
 }
@@ -529,17 +452,15 @@
 static int ax_ioctl(struct net_device *dev, struct ifreq *req, int cmd)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	unsigned long flags;
-	int rc;
+	struct phy_device *phy_dev = ax->phy_dev;
 
 	if (!netif_running(dev))
 		return -EINVAL;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	rc = generic_mii_ioctl(&ax->mii, if_mii(req), cmd, NULL);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
+	if (!phy_dev)
+		return -ENODEV;
 
-	return rc;
+	return phy_mii_ioctl(phy_dev, req, cmd);
 }
 
 /* ethtool ops */
@@ -547,56 +468,40 @@
 static void ax_get_drvinfo(struct net_device *dev,
 			   struct ethtool_drvinfo *info)
 {
-	struct ax_device *ax = to_ax_dev(dev);
+	struct platform_device *pdev = to_platform_device(dev->dev.parent);
 
 	strcpy(info->driver, DRV_NAME);
 	strcpy(info->version, DRV_VERSION);
-	strcpy(info->bus_info, ax->dev->name);
+	strcpy(info->bus_info, pdev->name);
 }
 
 static int ax_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	unsigned long flags;
+	struct phy_device *phy_dev = ax->phy_dev;
 
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	mii_ethtool_gset(&ax->mii, cmd);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
+	if (!phy_dev)
+		return -ENODEV;
 
-	return 0;
+	return phy_ethtool_gset(phy_dev, cmd);
 }
 
 static int ax_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct ax_device *ax = to_ax_dev(dev);
-	unsigned long flags;
-	int rc;
-
-	spin_lock_irqsave(&ax->mii_lock, flags);
-	rc = mii_ethtool_sset(&ax->mii, cmd);
-	spin_unlock_irqrestore(&ax->mii_lock, flags);
-
-	return rc;
-}
+	struct phy_device *phy_dev = ax->phy_dev;
 
-static int ax_nway_reset(struct net_device *dev)
-{
-	struct ax_device *ax = to_ax_dev(dev);
-	return mii_nway_restart(&ax->mii);
-}
+	if (!phy_dev)
+		return -ENODEV;
 
-static u32 ax_get_link(struct net_device *dev)
-{
-	struct ax_device *ax = to_ax_dev(dev);
-	return mii_link_ok(&ax->mii);
+	return phy_ethtool_sset(phy_dev, cmd);
 }
 
 static const struct ethtool_ops ax_ethtool_ops = {
 	.get_drvinfo		= ax_get_drvinfo,
 	.get_settings		= ax_get_settings,
 	.set_settings		= ax_set_settings,
-	.nway_reset		= ax_nway_reset,
-	.get_link		= ax_get_link,
+	.get_link		= ethtool_op_get_link,
 };
 
 #ifdef CONFIG_AX88796_93CX6
@@ -640,37 +545,131 @@
 	.ndo_get_stats		= ax_ei_get_stats,
 	.ndo_set_multicast_list = ax_ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= ax_ei_poll,
 #endif
 };
 
+static void ax_bb_mdc(struct mdiobb_ctrl *ctrl, int level)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+	if (level)
+		ax->reg_memr |= AX_MEMR_MDC;
+	else
+		ax->reg_memr &= ~AX_MEMR_MDC;
+
+	ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static void ax_bb_dir(struct mdiobb_ctrl *ctrl, int output)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+	if (output)
+		ax->reg_memr &= ~AX_MEMR_MDIR;
+	else
+		ax->reg_memr |= AX_MEMR_MDIR;
+
+	ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static void ax_bb_set_data(struct mdiobb_ctrl *ctrl, int value)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+
+	if (value)
+		ax->reg_memr |= AX_MEMR_MDO;
+	else
+		ax->reg_memr &= ~AX_MEMR_MDO;
+
+	ei_outb(ax->reg_memr, ax->addr_memr);
+}
+
+static int ax_bb_get_data(struct mdiobb_ctrl *ctrl)
+{
+	struct ax_device *ax = container_of(ctrl, struct ax_device, bb_ctrl);
+	int reg_memr = ei_inb(ax->addr_memr);
+
+	return reg_memr & AX_MEMR_MDI ? 1 : 0;
+}
+
+static struct mdiobb_ops bb_ops = {
+	.owner = THIS_MODULE,
+	.set_mdc = ax_bb_mdc,
+	.set_mdio_dir = ax_bb_dir,
+	.set_mdio_data = ax_bb_set_data,
+	.get_mdio_data = ax_bb_get_data,
+};
+
 /* setup code */
 
+static int ax_mii_init(struct net_device *dev)
+{
+	struct platform_device *pdev = to_platform_device(dev->dev.parent);
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	int err, i;
+
+	ax->bb_ctrl.ops = &bb_ops;
+	ax->addr_memr = ei_local->mem + AX_MEMR;
+	ax->mii_bus = alloc_mdio_bitbang(&ax->bb_ctrl);
+	if (!ax->mii_bus) {
+		err = -ENOMEM;
+		goto out;
+	}
+
+	ax->mii_bus->name = "ax88796_mii_bus";
+	ax->mii_bus->parent = dev->dev.parent;
+	snprintf(ax->mii_bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+	ax->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
+	if (!ax->mii_bus->irq) {
+		err = -ENOMEM;
+		goto out_free_mdio_bitbang;
+	}
+
+	for (i = 0; i < PHY_MAX_ADDR; i++)
+		ax->mii_bus->irq[i] = PHY_POLL;
+
+	err = mdiobus_register(ax->mii_bus);
+	if (err)
+		goto out_free_irq;
+
+	return 0;
+
+ out_free_irq:
+	kfree(ax->mii_bus->irq);
+ out_free_mdio_bitbang:
+	free_mdio_bitbang(ax->mii_bus);
+ out:
+	return err;
+}
+
 static void ax_initial_setup(struct net_device *dev, struct ei_device *ei_local)
 {
 	void __iomem *ioaddr = ei_local->mem;
 	struct ax_device *ax = to_ax_dev(dev);
 
-	/* Select page 0*/
-	ei_outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, ioaddr + E8390_CMD);
+	/* Select page 0 */
+	ei_outb(E8390_NODMA + E8390_PAGE0 + E8390_STOP, ioaddr + E8390_CMD);
 
 	/* set to byte access */
 	ei_outb(ax->plat->dcr_val & ~1, ioaddr + EN0_DCFG);
 	ei_outb(ax->plat->gpoc_val, ioaddr + EI_SHIFT(0x17));
 }
 
-/* ax_init_dev
+/*
+ * ax_init_dev
  *
  * initialise the specified device, taking care to note the MAC
  * address it may already have (if configured), ensure
  * the device is ready to be used by lib8390.c and registerd with
  * the network layer.
  */
-
-static int ax_init_dev(struct net_device *dev, int first_init)
+static int ax_init_dev(struct net_device *dev)
 {
 	struct ei_device *ei_local = netdev_priv(dev);
 	struct ax_device *ax = to_ax_dev(dev);
@@ -690,23 +689,23 @@
 
 	/* read the mac from the card prom if we need it */
 
-	if (first_init && ax->plat->flags & AXFLG_HAS_EEPROM) {
+	if (ax->plat->flags & AXFLG_HAS_EEPROM) {
 		unsigned char SA_prom[32];
 
-		for(i = 0; i < sizeof(SA_prom); i+=2) {
+		for (i = 0; i < sizeof(SA_prom); i += 2) {
 			SA_prom[i] = ei_inb(ioaddr + NE_DATAPORT);
-			SA_prom[i+1] = ei_inb(ioaddr + NE_DATAPORT);
+			SA_prom[i + 1] = ei_inb(ioaddr + NE_DATAPORT);
 		}
 
 		if (ax->plat->wordlength == 2)
 			for (i = 0; i < 16; i++)
 				SA_prom[i] = SA_prom[i+i];
 
-		memcpy(dev->dev_addr,  SA_prom, 6);
+		memcpy(dev->dev_addr, SA_prom, 6);
 	}
 
 #ifdef CONFIG_AX88796_93CX6
-	if (first_init && ax->plat->flags & AXFLG_HAS_93CX6) {
+	if (ax->plat->flags & AXFLG_HAS_93CX6) {
 		unsigned char mac_addr[6];
 		struct eeprom_93cx6 eeprom;
 
@@ -719,7 +718,7 @@
 				       (__le16 __force *)mac_addr,
 				       sizeof(mac_addr) >> 1);
 
-		memcpy(dev->dev_addr,  mac_addr, 6);
+		memcpy(dev->dev_addr, mac_addr, 6);
 	}
 #endif
 	if (ax->plat->wordlength == 2) {
@@ -732,67 +731,56 @@
 		stop_page = NE1SM_STOP_PG;
 	}
 
-	/* load the mac-address from the device if this is the
-	 * first time we've initialised */
-
-	if (first_init) {
-		if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
-			ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
-				ei_local->mem + E8390_CMD); /* 0x61 */
-			for (i = 0; i < ETHER_ADDR_LEN; i++)
-				dev->dev_addr[i] =
-					ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
-		}
-
-		if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
-		     ax->plat->mac_addr)
-			memcpy(dev->dev_addr, ax->plat->mac_addr,
-				ETHER_ADDR_LEN);
+	/* load the mac-address from the device */
+	if (ax->plat->flags & AXFLG_MAC_FROMDEV) {
+		ei_outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP,
+			ei_local->mem + E8390_CMD); /* 0x61 */
+		for (i = 0; i < ETHER_ADDR_LEN; i++)
+			dev->dev_addr[i] =
+				ei_inb(ioaddr + EN1_PHYS_SHIFT(i));
 	}
 
+	if ((ax->plat->flags & AXFLG_MAC_FROMPLATFORM) &&
+	    ax->plat->mac_addr)
+		memcpy(dev->dev_addr, ax->plat->mac_addr,
+		       ETHER_ADDR_LEN);
+
 	ax_reset_8390(dev);
 
-	ei_status.name = "AX88796";
-	ei_status.tx_start_page = start_page;
-	ei_status.stop_page = stop_page;
-	ei_status.word16 = (ax->plat->wordlength == 2);
-	ei_status.rx_start_page = start_page + TX_PAGES;
+	ei_local->name = "AX88796";
+	ei_local->tx_start_page = start_page;
+	ei_local->stop_page = stop_page;
+	ei_local->word16 = (ax->plat->wordlength == 2);
+	ei_local->rx_start_page = start_page + TX_PAGES;
 
 #ifdef PACKETBUF_MEMSIZE
-	 /* Allow the packet buffer size to be overridden by know-it-alls. */
-	ei_status.stop_page = ei_status.tx_start_page + PACKETBUF_MEMSIZE;
+	/* Allow the packet buffer size to be overridden by know-it-alls. */
+	ei_local->stop_page = ei_local->tx_start_page + PACKETBUF_MEMSIZE;
 #endif
 
-	ei_status.reset_8390	= &ax_reset_8390;
-	ei_status.block_input	= &ax_block_input;
-	ei_status.block_output	= &ax_block_output;
-	ei_status.get_8390_hdr	= &ax_get_8390_hdr;
-	ei_status.priv = 0;
+	ei_local->reset_8390 = &ax_reset_8390;
+	ei_local->block_input = &ax_block_input;
+	ei_local->block_output = &ax_block_output;
+	ei_local->get_8390_hdr = &ax_get_8390_hdr;
+	ei_local->priv = 0;
 
-	dev->netdev_ops		= &ax_netdev_ops;
-	dev->ethtool_ops	= &ax_ethtool_ops;
+	dev->netdev_ops = &ax_netdev_ops;
+	dev->ethtool_ops = &ax_ethtool_ops;
 
-	ax->msg_enable		= NETIF_MSG_LINK;
-	ax->mii.phy_id_mask	= 0x1f;
-	ax->mii.reg_num_mask	= 0x1f;
-	ax->mii.phy_id		= 0x10;		/* onboard phy */
-	ax->mii.force_media	= 0;
-	ax->mii.full_duplex	= 0;
-	ax->mii.mdio_read	= ax_phy_read;
-	ax->mii.mdio_write	= ax_phy_write;
-	ax->mii.dev		= dev;
+	ret = ax_mii_init(dev);
+	if (ret)
+		goto out_irq;
 
 	ax_NS8390_init(dev, 0);
 
-	if (first_init)
-		dev_info(&ax->dev->dev, "%dbit, irq %d, %lx, MAC: %pM\n",
-			 ei_status.word16 ? 16:8, dev->irq, dev->base_addr,
-			 dev->dev_addr);
-
 	ret = register_netdev(dev);
 	if (ret)
 		goto out_irq;
 
+	netdev_info(dev, "%dbit, irq %d, %lx, MAC: %pM\n",
+		    ei_local->word16 ? 16 : 8, dev->irq, dev->base_addr,
+		    dev->dev_addr);
+
 	return 0;
 
  out_irq:
@@ -802,24 +790,24 @@
 	return ret;
 }
 
-static int ax_remove(struct platform_device *_dev)
+static int ax_remove(struct platform_device *pdev)
 {
-	struct net_device *dev = platform_get_drvdata(_dev);
-	struct ax_device  *ax;
-
-	ax = to_ax_dev(dev);
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct ei_device *ei_local = netdev_priv(dev);
+	struct ax_device *ax = to_ax_dev(dev);
+	struct resource *mem;
 
 	unregister_netdev(dev);
 	free_irq(dev->irq, dev);
 
-	iounmap(ei_status.mem);
-	release_resource(ax->mem);
-	kfree(ax->mem);
+	iounmap(ei_local->mem);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
 
 	if (ax->map2) {
 		iounmap(ax->map2);
-		release_resource(ax->mem2);
-		kfree(ax->mem2);
+		mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+		release_mem_region(mem->start, resource_size(mem));
 	}
 
 	free_netdev(dev);
@@ -827,19 +815,20 @@
 	return 0;
 }
 
-/* ax_probe
+/*
+ * ax_probe
  *
  * This is the entry point when the platform device system uses to
- * notify us of a new device to attach to. Allocate memory, find
- * the resources and information passed, and map the necessary registers.
-*/
-
+ * notify us of a new device to attach to. Allocate memory, find the
+ * resources and information passed, and map the necessary registers.
+ */
 static int ax_probe(struct platform_device *pdev)
 {
 	struct net_device *dev;
-	struct ax_device  *ax;
-	struct resource   *res;
-	size_t size;
+	struct ei_device *ei_local;
+	struct ax_device *ax;
+	struct resource *irq, *mem, *mem2;
+	resource_size_t mem_size, mem2_size = 0;
 	int ret = 0;
 
 	dev = ax__alloc_ei_netdev(sizeof(struct ax_device));
@@ -847,120 +836,107 @@
 		return -ENOMEM;
 
 	/* ok, let's setup our device */
+	SET_NETDEV_DEV(dev, &pdev->dev);
+	ei_local = netdev_priv(dev);
 	ax = to_ax_dev(dev);
 
-	memset(ax, 0, sizeof(struct ax_device));
-
-	spin_lock_init(&ax->mii_lock);
-
-	ax->dev = pdev;
 	ax->plat = pdev->dev.platform_data;
 	platform_set_drvdata(pdev, dev);
 
-	ei_status.rxcr_base  = ax->plat->rcr_val;
+	ei_local->rxcr_base = ax->plat->rcr_val;
 
 	/* find the platform resources */
-
-	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
-	if (res == NULL) {
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
 		dev_err(&pdev->dev, "no IRQ specified\n");
 		ret = -ENXIO;
 		goto exit_mem;
 	}
 
-	dev->irq = res->start;
-	ax->irqflags = res->flags & IRQF_TRIGGER_MASK;
+	dev->irq = irq->start;
+	ax->irqflags = irq->flags & IRQF_TRIGGER_MASK;
 
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (res == NULL) {
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
 		dev_err(&pdev->dev, "no MEM specified\n");
 		ret = -ENXIO;
 		goto exit_mem;
 	}
 
-	size = (res->end - res->start) + 1;
-
-	/* setup the register offsets from either the platform data
-	 * or by using the size of the resource provided */
+	mem_size = resource_size(mem);
 
+	/*
+	 * setup the register offsets from either the platform data or
+	 * by using the size of the resource provided
+	 */
 	if (ax->plat->reg_offsets)
-		ei_status.reg_offset = ax->plat->reg_offsets;
+		ei_local->reg_offset = ax->plat->reg_offsets;
 	else {
-		ei_status.reg_offset = ax->reg_offsets;
+		ei_local->reg_offset = ax->reg_offsets;
 		for (ret = 0; ret < 0x18; ret++)
-			ax->reg_offsets[ret] = (size / 0x18) * ret;
+			ax->reg_offsets[ret] = (mem_size / 0x18) * ret;
 	}
 
-	ax->mem = request_mem_region(res->start, size, pdev->name);
-	if (ax->mem == NULL) {
+	if (!request_mem_region(mem->start, mem_size, pdev->name)) {
 		dev_err(&pdev->dev, "cannot reserve registers\n");
- 		ret = -ENXIO;
+		ret = -ENXIO;
 		goto exit_mem;
 	}
 
-	ei_status.mem = ioremap(res->start, size);
-	dev->base_addr = (unsigned long)ei_status.mem;
+	ei_local->mem = ioremap(mem->start, mem_size);
+	dev->base_addr = (unsigned long)ei_local->mem;
 
-	if (ei_status.mem == NULL) {
-		dev_err(&pdev->dev, "Cannot ioremap area (%08llx,%08llx)\n",
-			(unsigned long long)res->start,
-			(unsigned long long)res->end);
+	if (ei_local->mem == NULL) {
+		dev_err(&pdev->dev, "Cannot ioremap area %pR\n", mem);
 
- 		ret = -ENXIO;
+		ret = -ENXIO;
 		goto exit_req;
 	}
 
 	/* look for reset area */
-
-	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (res == NULL) {
+	mem2 = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!mem2) {
 		if (!ax->plat->reg_offsets) {
 			for (ret = 0; ret < 0x20; ret++)
-				ax->reg_offsets[ret] = (size / 0x20) * ret;
+				ax->reg_offsets[ret] = (mem_size / 0x20) * ret;
 		}
-
-		ax->map2 = NULL;
 	} else {
- 		size = (res->end - res->start) + 1;
+		mem2_size = resource_size(mem2);
 
-		ax->mem2 = request_mem_region(res->start, size, pdev->name);
-		if (ax->mem2 == NULL) {
+		if (!request_mem_region(mem2->start, mem2_size, pdev->name)) {
 			dev_err(&pdev->dev, "cannot reserve registers\n");
 			ret = -ENXIO;
 			goto exit_mem1;
 		}
 
-		ax->map2 = ioremap(res->start, size);
-		if (ax->map2 == NULL) {
+		ax->map2 = ioremap(mem2->start, mem2_size);
+		if (!ax->map2) {
 			dev_err(&pdev->dev, "cannot map reset register\n");
 			ret = -ENXIO;
 			goto exit_mem2;
 		}
 
-		ei_status.reg_offset[0x1f] = ax->map2 - ei_status.mem;
+		ei_local->reg_offset[0x1f] = ax->map2 - ei_local->mem;
 	}
 
 	/* got resources, now initialise and register device */
-
-	ret = ax_init_dev(dev, 1);
+	ret = ax_init_dev(dev);
 	if (!ret)
 		return 0;
 
-	if (ax->map2 == NULL)
+	if (!ax->map2)
 		goto exit_mem1;
 
 	iounmap(ax->map2);
 
  exit_mem2:
-	release_resource(ax->mem2);
-	kfree(ax->mem2);
+	release_mem_region(mem2->start, mem2_size);
 
  exit_mem1:
-	iounmap(ei_status.mem);
+	iounmap(ei_local->mem);
 
  exit_req:
-	release_resource(ax->mem);
-	kfree(ax->mem);
+	release_mem_region(mem->start, mem_size);
 
  exit_mem:
 	free_netdev(dev);
@@ -974,7 +950,7 @@
 static int ax_suspend(struct platform_device *dev, pm_message_t state)
 {
 	struct net_device *ndev = platform_get_drvdata(dev);
-	struct ax_device  *ax = to_ax_dev(ndev);
+	struct ax_device *ax = to_ax_dev(ndev);
 
 	ax->resume_open = ax->running;
 
@@ -987,7 +963,7 @@
 static int ax_resume(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
-	struct ax_device  *ax = to_ax_dev(ndev);
+	struct ax_device *ax = to_ax_dev(ndev);
 
 	ax_initial_setup(ndev, netdev_priv(ndev));
 	ax_NS8390_init(ndev, ax->resume_open);
@@ -1001,7 +977,7 @@
 
 #else
 #define ax_suspend NULL
-#define ax_resume  NULL
+#define ax_resume NULL
 #endif
 
 static struct platform_driver axdrv = {
diff -druN linux-libre-2.6.38-gnu/drivers/net/bcm63xx_enet.c linux-libre-2.6.39-gnu/drivers/net/bcm63xx_enet.c
--- linux-libre-2.6.38-gnu/drivers/net/bcm63xx_enet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bcm63xx_enet.c	2011-05-19 00:06:34.000000000 -0400
@@ -597,7 +597,7 @@
 }
 
 /*
- * Change rx mode (promiscous/allmulti) and update multicast list
+ * Change rx mode (promiscuous/allmulti) and update multicast list
  */
 static void bcm_enet_set_multicast_list(struct net_device *dev)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/benet/be_cmds.c linux-libre-2.6.39-gnu/drivers/net/benet/be_cmds.c
--- linux-libre-2.6.38-gnu/drivers/net/benet/be_cmds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/benet/be_cmds.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,21 +8,30 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #include "be.h"
 #include "be_cmds.h"
 
+/* Must be a power of 2 or else MODULO will BUG_ON */
+static int be_get_temp_freq = 32;
+
 static void be_mcc_notify(struct be_adapter *adapter)
 {
 	struct be_queue_info *mccq = &adapter->mcc_obj.q;
 	u32 val = 0;
 
+	if (adapter->eeh_err) {
+		dev_info(&adapter->pdev->dev,
+			"Error in Card Detected! Cannot issue commands\n");
+		return;
+	}
+
 	val |= mccq->id & DB_MCCQ_RING_ID_MASK;
 	val |= 1 << DB_MCCQ_NUM_POSTED_SHIFT;
 
@@ -75,7 +84,7 @@
 			be_dws_le_to_cpu(&resp->hw_stats,
 						sizeof(resp->hw_stats));
 			netdev_stats_update(adapter);
-			adapter->stats_ioctl_sent = false;
+			adapter->stats_cmd_sent = false;
 		}
 	} else if ((compl_status != MCC_STATUS_NOT_SUPPORTED) &&
 		   (compl->tag0 != OPCODE_COMMON_NTWK_MAC_QUERY)) {
@@ -102,6 +111,7 @@
 {
 	if (evt->valid) {
 		adapter->vlan_prio_bmap = evt->available_priority_bmap;
+		adapter->recommended_prio &= ~VLAN_PRIO_MASK;
 		adapter->recommended_prio =
 			evt->reco_default_priority << VLAN_PRIO_SHIFT;
 	}
@@ -117,6 +127,16 @@
 	}
 }
 
+/*Grp5 PVID evt*/
+static void be_async_grp5_pvid_state_process(struct be_adapter *adapter,
+		struct be_async_event_grp5_pvid_state *evt)
+{
+	if (evt->enabled)
+		adapter->pvid = le16_to_cpu(evt->tag);
+	else
+		adapter->pvid = 0;
+}
+
 static void be_async_grp5_evt_process(struct be_adapter *adapter,
 		u32 trailer, struct be_mcc_compl *evt)
 {
@@ -134,6 +154,10 @@
 		be_async_grp5_qos_speed_process(adapter,
 		(struct be_async_event_grp5_qos_link_speed *)evt);
 	break;
+	case ASYNC_EVENT_PVID_STATE:
+		be_async_grp5_pvid_state_process(adapter,
+		(struct be_async_event_grp5_pvid_state *)evt);
+	break;
 	default:
 		dev_warn(&adapter->pdev->dev, "Unknown grp5 event!\n");
 		break;
@@ -216,6 +240,9 @@
 	int i, num, status = 0;
 	struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
+	if (adapter->eeh_err)
+		return -EIO;
+
 	for (i = 0; i < mcc_timeout; i++) {
 		num = be_process_mcc(adapter, &status);
 		if (num)
@@ -245,6 +272,12 @@
 	int msecs = 0;
 	u32 ready;
 
+	if (adapter->eeh_err) {
+		dev_err(&adapter->pdev->dev,
+			"Error detected in card.Cannot issue commands\n");
+		return -EIO;
+	}
+
 	do {
 		ready = ioread32(db);
 		if (ready == 0xffffffff) {
@@ -598,7 +631,7 @@
 
 /* Uses synchronous MCCQ */
 int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
-		u32 if_id, u32 *pmac_id)
+		u32 if_id, u32 *pmac_id, u32 domain)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_pmac_add *req;
@@ -619,6 +652,7 @@
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_PMAC_ADD, sizeof(*req));
 
+	req->hdr.domain = domain;
 	req->if_id = cpu_to_le32(if_id);
 	memcpy(req->mac_address, mac_addr, ETH_ALEN);
 
@@ -634,7 +668,7 @@
 }
 
 /* Uses synchronous MCCQ */
-int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id)
+int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id, u32 dom)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_pmac_del *req;
@@ -655,6 +689,7 @@
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_PMAC_DEL, sizeof(*req));
 
+	req->hdr.domain = dom;
 	req->if_id = cpu_to_le32(if_id);
 	req->pmac_id = cpu_to_le32(pmac_id);
 
@@ -691,7 +726,7 @@
 
 	req->num_pages =  cpu_to_le16(PAGES_4K_SPANNED(q_mem->va, q_mem->size));
 	if (lancer_chip(adapter)) {
-		req->hdr.version = 1;
+		req->hdr.version = 2;
 		req->page_size = 1; /* 1 for 4K */
 		AMAP_SET_BITS(struct amap_cq_context_lancer, coalescwm, ctxt,
 								coalesce_wm);
@@ -827,6 +862,12 @@
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_ETH, OPCODE_ETH_TX_CREATE,
 		sizeof(*req));
 
+	if (lancer_chip(adapter)) {
+		req->hdr.version = 1;
+		AMAP_SET_BITS(struct amap_tx_context, if_id, ctxt,
+					adapter->if_handle);
+	}
+
 	req->num_pages = PAGES_4K_SPANNED(q_mem->va, q_mem->size);
 	req->ulp_num = BE_ULP1_NUM;
 	req->type = BE_ETH_TX_RING_TYPE_STANDARD;
@@ -995,7 +1036,7 @@
 }
 
 /* Uses mbox */
-int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id)
+int be_cmd_if_destroy(struct be_adapter *adapter, u32 interface_id, u32 domain)
 {
 	struct be_mcc_wrb *wrb;
 	struct be_cmd_req_if_destroy *req;
@@ -1016,6 +1057,7 @@
 	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
 		OPCODE_COMMON_NTWK_INTERFACE_DESTROY, sizeof(*req));
 
+	req->hdr.domain = domain;
 	req->interface_id = cpu_to_le32(interface_id);
 
 	status = be_mbox_notify_wait(adapter);
@@ -1036,6 +1078,9 @@
 	struct be_sge *sge;
 	int status = 0;
 
+	if (MODULO(adapter->work_counter, be_get_temp_freq) == 0)
+		be_cmd_get_die_temperature(adapter);
+
 	spin_lock_bh(&adapter->mcc_lock);
 
 	wrb = wrb_from_mccq(adapter);
@@ -1056,7 +1101,7 @@
 	sge->len = cpu_to_le32(nonemb_cmd->size);
 
 	be_mcc_notify(adapter);
-	adapter->stats_ioctl_sent = true;
+	adapter->stats_cmd_sent = true;
 
 err:
 	spin_unlock_bh(&adapter->mcc_lock);
@@ -1103,6 +1148,44 @@
 	return status;
 }
 
+/* Uses synchronous mcc */
+int be_cmd_get_die_temperature(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_get_cntl_addnl_attribs *req;
+	int status;
+
+	spin_lock_bh(&adapter->mcc_lock);
+
+	wrb = wrb_from_mccq(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+			OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES, sizeof(*req));
+
+	status = be_mcc_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_get_cntl_addnl_attribs *resp =
+						embedded_payload(wrb);
+		adapter->drv_stats.be_on_die_temperature =
+						resp->on_die_temperature;
+	}
+	/* If IOCTL fails once, do not bother issuing it again */
+	else
+		be_get_temp_freq = 0;
+
+err:
+	spin_unlock_bh(&adapter->mcc_lock);
+	return status;
+}
+
 /* Uses Mbox */
 int be_cmd_get_fw_ver(struct be_adapter *adapter, char *fw_ver)
 {
@@ -1248,7 +1331,7 @@
 
 /*
  * Uses MCC for this command as it may be called in BH context
- * (mc == NULL) => multicast promiscous
+ * (mc == NULL) => multicast promiscuous
  */
 int be_cmd_multicast_set(struct be_adapter *adapter, u32 if_id,
 		struct net_device *netdev, struct be_dma_mem *mem)
@@ -1868,8 +1951,8 @@
 			OPCODE_COMMON_SET_QOS, sizeof(*req));
 
 	req->hdr.domain = domain;
-	req->valid_bits = BE_QOS_BITS_NIC;
-	req->max_bps_nic = bps;
+	req->valid_bits = cpu_to_le32(BE_QOS_BITS_NIC);
+	req->max_bps_nic = cpu_to_le32(bps);
 
 	status = be_mcc_notify_wait(adapter);
 
@@ -1877,3 +1960,96 @@
 	spin_unlock_bh(&adapter->mcc_lock);
 	return status;
 }
+
+int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_cntl_attribs *req;
+	struct be_cmd_resp_cntl_attribs *resp;
+	struct be_sge *sge;
+	int status;
+	int payload_len = max(sizeof(*req), sizeof(*resp));
+	struct mgmt_controller_attrib *attribs;
+	struct be_dma_mem attribs_cmd;
+
+	memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
+	attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
+	attribs_cmd.va = pci_alloc_consistent(adapter->pdev, attribs_cmd.size,
+						&attribs_cmd.dma);
+	if (!attribs_cmd.va) {
+		dev_err(&adapter->pdev->dev,
+				"Memory allocation failure\n");
+		return -ENOMEM;
+	}
+
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+	req = attribs_cmd.va;
+	sge = nonembedded_sgl(wrb);
+
+	be_wrb_hdr_prepare(wrb, payload_len, false, 1,
+			OPCODE_COMMON_GET_CNTL_ATTRIBUTES);
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+			 OPCODE_COMMON_GET_CNTL_ATTRIBUTES, payload_len);
+	sge->pa_hi = cpu_to_le32(upper_32_bits(attribs_cmd.dma));
+	sge->pa_lo = cpu_to_le32(attribs_cmd.dma & 0xFFFFFFFF);
+	sge->len = cpu_to_le32(attribs_cmd.size);
+
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		attribs = (struct mgmt_controller_attrib *)( attribs_cmd.va +
+					sizeof(struct be_cmd_resp_hdr));
+		adapter->hba_port_num = attribs->hba_attribs.phy_port;
+	}
+
+err:
+	mutex_unlock(&adapter->mbox_lock);
+	pci_free_consistent(adapter->pdev, attribs_cmd.size, attribs_cmd.va,
+					attribs_cmd.dma);
+	return status;
+}
+
+/* Uses mbox */
+int be_cmd_check_native_mode(struct be_adapter *adapter)
+{
+	struct be_mcc_wrb *wrb;
+	struct be_cmd_req_set_func_cap *req;
+	int status;
+
+	if (mutex_lock_interruptible(&adapter->mbox_lock))
+		return -1;
+
+	wrb = wrb_from_mbox(adapter);
+	if (!wrb) {
+		status = -EBUSY;
+		goto err;
+	}
+
+	req = embedded_payload(wrb);
+
+	be_wrb_hdr_prepare(wrb, sizeof(*req), true, 0,
+		OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP);
+
+	be_cmd_hdr_prepare(&req->hdr, CMD_SUBSYSTEM_COMMON,
+		OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP, sizeof(*req));
+
+	req->valid_cap_flags = cpu_to_le32(CAPABILITY_SW_TIMESTAMPS |
+				CAPABILITY_BE3_NATIVE_ERX_API);
+	req->cap_flags = cpu_to_le32(CAPABILITY_BE3_NATIVE_ERX_API);
+
+	status = be_mbox_notify_wait(adapter);
+	if (!status) {
+		struct be_cmd_resp_set_func_cap *resp = embedded_payload(wrb);
+		adapter->be3_native = le32_to_cpu(resp->cap_flags) &
+					CAPABILITY_BE3_NATIVE_ERX_API;
+	}
+err:
+	mutex_unlock(&adapter->mbox_lock);
+	return status;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/benet/be_cmds.h linux-libre-2.6.39-gnu/drivers/net/benet/be_cmds.h
--- linux-libre-2.6.38-gnu/drivers/net/benet/be_cmds.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/benet/be_cmds.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 /*
@@ -88,6 +88,7 @@
 #define ASYNC_EVENT_CODE_GRP_5		0x5
 #define ASYNC_EVENT_QOS_SPEED		0x1
 #define ASYNC_EVENT_COS_PRIORITY	0x2
+#define ASYNC_EVENT_PVID_STATE		0x3
 struct be_async_event_trailer {
 	u32 code;
 };
@@ -134,6 +135,18 @@
 	struct be_async_event_trailer trailer;
 } __packed;
 
+/* When the event code of an async trailer is GRP5 and event type is
+ * PVID state, the mcc_compl must be interpreted as follows
+ */
+struct be_async_event_grp5_pvid_state {
+	u8 enabled;
+	u8 rsvd0;
+	u16 tag;
+	u32 event_tag;
+	u32 rsvd1;
+	struct be_async_event_trailer trailer;
+} __packed;
+
 struct be_mcc_mailbox {
 	struct be_mcc_wrb wrb;
 	struct be_mcc_compl compl;
@@ -156,6 +169,7 @@
 #define OPCODE_COMMON_SET_QOS				28
 #define OPCODE_COMMON_MCC_CREATE_EXT			90
 #define OPCODE_COMMON_SEEPROM_READ			30
+#define OPCODE_COMMON_GET_CNTL_ATTRIBUTES               32
 #define OPCODE_COMMON_NTWK_RX_FILTER    		34
 #define OPCODE_COMMON_GET_FW_VERSION			35
 #define OPCODE_COMMON_SET_FLOW_CONTROL			36
@@ -176,6 +190,8 @@
 #define OPCODE_COMMON_GET_BEACON_STATE			70
 #define OPCODE_COMMON_READ_TRANSRECV_DATA		73
 #define OPCODE_COMMON_GET_PHY_DETAILS			102
+#define OPCODE_COMMON_SET_DRIVER_FUNCTION_CAP		103
+#define OPCODE_COMMON_GET_CNTL_ADDITIONAL_ATTRIBUTES	121
 
 #define OPCODE_ETH_RSS_CONFIG				1
 #define OPCODE_ETH_ACPI_CONFIG				2
@@ -415,7 +431,7 @@
 /* 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_tx_context {
-	u8 rsvd0[16];		/* dword 0 */
+	u8 if_id[16];		/* dword 0 */
 	u8 tx_ring_size[4];	/* dword 0 */
 	u8 rsvd1[26];		/* dword 0 */
 	u8 pci_func_id[8];	/* dword 1 */
@@ -503,7 +519,8 @@
 	BE_IF_FLAGS_VLAN = 0x100,
 	BE_IF_FLAGS_MCAST_PROMISCUOUS = 0x200,
 	BE_IF_FLAGS_PASS_L2_ERRORS = 0x400,
-	BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800
+	BE_IF_FLAGS_PASS_L3L4_ERRORS = 0x800,
+	BE_IF_FLAGS_MULTICAST = 0x1000
 };
 
 /* An RX interface is an object with one or more MAC addresses and
@@ -619,7 +636,10 @@
 	u32 rx_drops_invalid_ring;	/* dword 145*/
 	u32 forwarded_packets;	/* dword 146*/
 	u32 rx_drops_mtu;	/* dword 147*/
-	u32 rsvd0[15];
+	u32 rsvd0[7];
+	u32 port0_jabber_events;
+	u32 port1_jabber_events;
+	u32 rsvd1[6];
 };
 
 struct be_erx_stats {
@@ -630,11 +650,16 @@
 	u32 debug_pmem_pbuf_dealloc;       /* dword 47*/
 };
 
+struct be_pmem_stats {
+	u32 eth_red_drops;
+	u32 rsvd[4];
+};
+
 struct be_hw_stats {
 	struct be_rxf_stats rxf;
 	u32 rsvd[48];
 	struct be_erx_stats erx;
-	u32 rsvd1[6];
+	struct be_pmem_stats pmem;
 };
 
 struct be_cmd_req_get_stats {
@@ -647,6 +672,20 @@
 	struct be_hw_stats hw_stats;
 };
 
+struct be_cmd_req_get_cntl_addnl_attribs {
+	struct be_cmd_req_hdr hdr;
+	u8 rsvd[8];
+};
+
+struct be_cmd_resp_get_cntl_addnl_attribs {
+	struct be_cmd_resp_hdr hdr;
+	u16 ipl_file_number;
+	u8 ipl_file_version;
+	u8 rsvd0;
+	u8 on_die_temperature; /* in degrees centigrade*/
+	u8 rsvd1[3];
+};
+
 struct be_cmd_req_vlan_config {
 	struct be_cmd_req_hdr hdr;
 	u8 interface_id;
@@ -994,17 +1033,47 @@
 	u32 rsvd;
 };
 
+/*********************** Controller Attributes ***********************/
+struct be_cmd_req_cntl_attribs {
+	struct be_cmd_req_hdr hdr;
+};
+
+struct be_cmd_resp_cntl_attribs {
+	struct be_cmd_resp_hdr hdr;
+	struct mgmt_controller_attrib attribs;
+};
+
+/*********************** Set driver function ***********************/
+#define CAPABILITY_SW_TIMESTAMPS	2
+#define CAPABILITY_BE3_NATIVE_ERX_API	4
+
+struct be_cmd_req_set_func_cap {
+	struct be_cmd_req_hdr hdr;
+	u32 valid_cap_flags;
+	u32 cap_flags;
+	u8 rsvd[212];
+};
+
+struct be_cmd_resp_set_func_cap {
+	struct be_cmd_resp_hdr hdr;
+	u32 valid_cap_flags;
+	u32 cap_flags;
+	u8 rsvd[212];
+};
+
 extern int be_pci_fnum_get(struct be_adapter *adapter);
 extern int be_cmd_POST(struct be_adapter *adapter);
 extern int be_cmd_mac_addr_query(struct be_adapter *adapter, u8 *mac_addr,
 			u8 type, bool permanent, u32 if_handle);
 extern int be_cmd_pmac_add(struct be_adapter *adapter, u8 *mac_addr,
-			u32 if_id, u32 *pmac_id);
-extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id, u32 pmac_id);
+			u32 if_id, u32 *pmac_id, u32 domain);
+extern int be_cmd_pmac_del(struct be_adapter *adapter, u32 if_id,
+			u32 pmac_id, u32 domain);
 extern int be_cmd_if_create(struct be_adapter *adapter, u32 cap_flags,
 			u32 en_flags, u8 *mac, bool pmac_invalid,
 			u32 *if_handle, u32 *pmac_id, u32 domain);
-extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle);
+extern int be_cmd_if_destroy(struct be_adapter *adapter, u32 if_handle,
+			u32 domain);
 extern int be_cmd_eq_create(struct be_adapter *adapter,
 			struct be_queue_info *eq, int eq_delay);
 extern int be_cmd_cq_create(struct be_adapter *adapter,
@@ -1076,4 +1145,7 @@
 		struct be_dma_mem *cmd);
 extern int be_cmd_set_qos(struct be_adapter *adapter, u32 bps, u32 domain);
 extern void be_detect_dump_ue(struct be_adapter *adapter);
+extern int be_cmd_get_die_temperature(struct be_adapter *adapter);
+extern int be_cmd_get_cntl_attributes(struct be_adapter *adapter);
+extern int be_cmd_check_native_mode(struct be_adapter *adapter);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/benet/be_ethtool.c linux-libre-2.6.39-gnu/drivers/net/benet/be_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/benet/be_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/benet/be_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #include "be.h"
@@ -26,7 +26,8 @@
 	int offset;
 };
 
-enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT};
+enum {NETSTAT, PORTSTAT, MISCSTAT, DRVSTAT_TX, DRVSTAT_RX, ERXSTAT,
+			PMEMSTAT, DRVSTAT};
 #define FIELDINFO(_struct, field) FIELD_SIZEOF(_struct, field), \
 					offsetof(_struct, field)
 #define NETSTAT_INFO(field) 	#field, NETSTAT,\
@@ -43,6 +44,11 @@
 						field)
 #define ERXSTAT_INFO(field) 	#field, ERXSTAT,\
 					FIELDINFO(struct be_erx_stats, field)
+#define PMEMSTAT_INFO(field) 	#field, PMEMSTAT,\
+					FIELDINFO(struct be_pmem_stats, field)
+#define	DRVSTAT_INFO(field)	#field, DRVSTAT,\
+					FIELDINFO(struct be_drv_stats, \
+						field)
 
 static const struct be_ethtool_stat et_stats[] = {
 	{NETSTAT_INFO(rx_packets)},
@@ -99,7 +105,11 @@
 	{MISCSTAT_INFO(rx_drops_too_many_frags)},
 	{MISCSTAT_INFO(rx_drops_invalid_ring)},
 	{MISCSTAT_INFO(forwarded_packets)},
-	{MISCSTAT_INFO(rx_drops_mtu)}
+	{MISCSTAT_INFO(rx_drops_mtu)},
+	{MISCSTAT_INFO(port0_jabber_events)},
+	{MISCSTAT_INFO(port1_jabber_events)},
+	{PMEMSTAT_INFO(eth_red_drops)},
+	{DRVSTAT_INFO(be_on_die_temperature)}
 };
 #define ETHTOOL_STATS_NUM ARRAY_SIZE(et_stats)
 
@@ -121,7 +131,7 @@
 	"MAC Loopback test",
 	"PHY Loopback test",
 	"External Loopback test",
-	"DDR DMA test"
+	"DDR DMA test",
 	"Link test"
 };
 
@@ -276,6 +286,12 @@
 		case MISCSTAT:
 			p = &hw_stats->rxf;
 			break;
+		case PMEMSTAT:
+			p = &hw_stats->pmem;
+			break;
+		case DRVSTAT:
+			p = &adapter->drv_stats;
+			break;
 		}
 
 		p = (u8 *)p + et_stats[i].offset;
@@ -376,8 +392,9 @@
 		}
 
 		phy_cmd.size = sizeof(struct be_cmd_req_get_phy_info);
-		phy_cmd.va = pci_alloc_consistent(adapter->pdev, phy_cmd.size,
-					&phy_cmd.dma);
+		phy_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+						phy_cmd.size, &phy_cmd.dma,
+						GFP_KERNEL);
 		if (!phy_cmd.va) {
 			dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
 			return -ENOMEM;
@@ -416,8 +433,8 @@
 		adapter->port_type = ecmd->port;
 		adapter->transceiver = ecmd->transceiver;
 		adapter->autoneg = ecmd->autoneg;
-		pci_free_consistent(adapter->pdev, phy_cmd.size,
-					phy_cmd.va, phy_cmd.dma);
+		dma_free_coherent(&adapter->pdev->dev, phy_cmd.size, phy_cmd.va,
+				  phy_cmd.dma);
 	} else {
 		ecmd->speed = adapter->link_speed;
 		ecmd->port = adapter->port_type;
@@ -496,7 +513,7 @@
 	int status;
 	u32 cur;
 
-	be_cmd_get_beacon_state(adapter, adapter->port_num, &cur);
+	be_cmd_get_beacon_state(adapter, adapter->hba_port_num, &cur);
 
 	if (cur == BEACON_STATE_ENABLED)
 		return 0;
@@ -504,23 +521,34 @@
 	if (data < 2)
 		data = 2;
 
-	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
+	status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 			BEACON_STATE_ENABLED);
 	set_current_state(TASK_INTERRUPTIBLE);
 	schedule_timeout(data*HZ);
 
-	status = be_cmd_set_beacon_state(adapter, adapter->port_num, 0, 0,
+	status = be_cmd_set_beacon_state(adapter, adapter->hba_port_num, 0, 0,
 			BEACON_STATE_DISABLED);
 
 	return status;
 }
 
+static bool
+be_is_wol_supported(struct be_adapter *adapter)
+{
+	if (!be_physfn(adapter))
+		return false;
+	else
+		return true;
+}
+
 static void
 be_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct be_adapter *adapter = netdev_priv(netdev);
 
-	wol->supported = WAKE_MAGIC;
+	if (be_is_wol_supported(adapter))
+		wol->supported = WAKE_MAGIC;
+
 	if (adapter->wol)
 		wol->wolopts = WAKE_MAGIC;
 	else
@@ -536,7 +564,7 @@
 	if (wol->wolopts & ~WAKE_MAGIC)
 		return -EINVAL;
 
-	if (wol->wolopts & WAKE_MAGIC)
+	if ((wol->wolopts & WAKE_MAGIC) && be_is_wol_supported(adapter))
 		adapter->wol = true;
 	else
 		adapter->wol = false;
@@ -554,8 +582,8 @@
 	};
 
 	ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
-	ddrdma_cmd.va = pci_alloc_consistent(adapter->pdev, ddrdma_cmd.size,
-					&ddrdma_cmd.dma);
+	ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, ddrdma_cmd.size,
+					   &ddrdma_cmd.dma, GFP_KERNEL);
 	if (!ddrdma_cmd.va) {
 		dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
 		return -ENOMEM;
@@ -569,20 +597,20 @@
 	}
 
 err:
-	pci_free_consistent(adapter->pdev, ddrdma_cmd.size,
-			ddrdma_cmd.va, ddrdma_cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, ddrdma_cmd.size, ddrdma_cmd.va,
+			  ddrdma_cmd.dma);
 	return ret;
 }
 
 static u64 be_loopback_test(struct be_adapter *adapter, u8 loopback_type,
 				u64 *status)
 {
-	be_cmd_set_loopback(adapter, adapter->port_num,
+	be_cmd_set_loopback(adapter, adapter->hba_port_num,
 				loopback_type, 1);
-	*status = be_cmd_loopback_test(adapter, adapter->port_num,
+	*status = be_cmd_loopback_test(adapter, adapter->hba_port_num,
 				loopback_type, 1500,
 				2, 0xabc);
-	be_cmd_set_loopback(adapter, adapter->port_num,
+	be_cmd_set_loopback(adapter, adapter->hba_port_num,
 				BE_NO_LOOPBACK, 1);
 	return *status;
 }
@@ -621,7 +649,8 @@
 				&qos_link_speed) != 0) {
 		test->flags |= ETH_TEST_FL_FAILED;
 		data[4] = -1;
-	} else if (mac_speed) {
+	} else if (!mac_speed) {
+		test->flags |= ETH_TEST_FL_FAILED;
 		data[4] = 1;
 	}
 }
@@ -662,8 +691,8 @@
 
 	memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
 	eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
-	eeprom_cmd.va = pci_alloc_consistent(adapter->pdev, eeprom_cmd.size,
-				&eeprom_cmd.dma);
+	eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, eeprom_cmd.size,
+					   &eeprom_cmd.dma, GFP_KERNEL);
 
 	if (!eeprom_cmd.va) {
 		dev_err(&adapter->pdev->dev,
@@ -677,8 +706,8 @@
 		resp = (struct be_cmd_resp_seeprom_read *) eeprom_cmd.va;
 		memcpy(data, resp->seeprom_data + eeprom->offset, eeprom->len);
 	}
-	pci_free_consistent(adapter->pdev, eeprom_cmd.size, eeprom_cmd.va,
-			eeprom_cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, eeprom_cmd.size, eeprom_cmd.va,
+			  eeprom_cmd.dma);
 
 	return status;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/benet/be.h linux-libre-2.6.39-gnu/drivers/net/benet/be.h
--- linux-libre-2.6.38-gnu/drivers/net/benet/be.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/benet/be.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #ifndef BE_H
@@ -33,7 +33,7 @@
 
 #include "be_hw.h"
 
-#define DRV_VER			"2.103.175u"
+#define DRV_VER			"4.0.100u"
 #define DRV_NAME		"be2net"
 #define BE_NAME			"ServerEngines BladeEngine2 10Gbps NIC"
 #define BE3_NAME		"ServerEngines BladeEngine3 10Gbps NIC"
@@ -67,7 +67,7 @@
 }
 
 /* Number of bytes of an RX frame that are copied to skb->data */
-#define BE_HDR_LEN 		64
+#define BE_HDR_LEN		((u16) 64)
 #define BE_MAX_JUMBO_FRAME_SIZE	9018
 #define BE_MIN_MTU		256
 
@@ -154,7 +154,7 @@
 	u16 min_eqd;		/* in usecs */
 	u16 max_eqd;		/* in usecs */
 	u16 cur_eqd;		/* in usecs */
-	u8  msix_vec_idx;
+	u8  eq_idx;
 
 	struct napi_struct napi;
 };
@@ -211,18 +211,40 @@
 	u32 rx_fps;		/* Rx frags per second */
 };
 
+struct be_rx_compl_info {
+	u32 rss_hash;
+	u16 vlan_tag;
+	u16 pkt_size;
+	u16 rxq_idx;
+	u16 mac_id;
+	u8 vlanf;
+	u8 num_rcvd;
+	u8 err;
+	u8 ipf;
+	u8 tcpf;
+	u8 udpf;
+	u8 ip_csum;
+	u8 l4_csum;
+	u8 ipv6;
+	u8 vtm;
+	u8 pkt_type;
+};
+
 struct be_rx_obj {
 	struct be_adapter *adapter;
 	struct be_queue_info q;
 	struct be_queue_info cq;
+	struct be_rx_compl_info rxcp;
 	struct be_rx_page_info page_info_tbl[RX_Q_LEN];
 	struct be_eq_obj rx_eq;
 	struct be_rx_stats stats;
 	u8 rss_id;
 	bool rx_post_starved;	/* Zero rx frags have been posted to BE */
-	u16 last_frag_index;
-	u16 rsvd;
-	u32 cache_line_barrier[15];
+	u32 cache_line_barrier[16];
+};
+
+struct be_drv_stats {
+	u8 be_on_die_temperature;
 };
 
 struct be_vf_cfg {
@@ -234,6 +256,7 @@
 };
 
 #define BE_INVALID_PMAC_ID		0xffffffff
+
 struct be_adapter {
 	struct pci_dev *pdev;
 	struct net_device *netdev;
@@ -268,7 +291,8 @@
 	u32 num_rx_qs;
 	u32 big_page_size;	/* Compounded page size shared by rx wrbs */
 
-	u8 msix_vec_next_idx;
+	u8 eq_next_idx;
+	struct be_drv_stats drv_stats;
 
 	struct vlan_group *vlan_grp;
 	u16 vlans_added;
@@ -281,6 +305,7 @@
 	struct be_dma_mem stats_cmd;
 	/* Work queue used to perform periodic tasks like getting statistics */
 	struct delayed_work work;
+	u16 work_counter;
 
 	/* Ethtool knobs and info */
 	bool rx_csum; 		/* BE card must perform rx-checksumming */
@@ -298,7 +323,7 @@
 	u32 rx_fc;		/* Rx flow control */
 	u32 tx_fc;		/* Tx flow control */
 	bool ue_detected;
-	bool stats_ioctl_sent;
+	bool stats_cmd_sent;
 	int link_speed;
 	u8 port_type;
 	u8 transceiver;
@@ -307,10 +332,13 @@
 	u32 flash_status;
 	struct completion flash_compl;
 
+	bool be3_native;
 	bool sriov_enabled;
 	struct be_vf_cfg vf_cfg[BE_MAX_VF];
 	u8 is_virtfn;
 	u32 sli_family;
+	u8 hba_port_num;
+	u16 pvid;
 };
 
 #define be_physfn(adapter) (!adapter->is_virtfn)
@@ -450,9 +478,8 @@
 	mac[5] = (u8)(addr & 0xFF);
 	mac[4] = (u8)((addr >> 8) & 0xFF);
 	mac[3] = (u8)((addr >> 16) & 0xFF);
-	mac[2] = 0xC9;
-	mac[1] = 0x00;
-	mac[0] = 0x00;
+	/* Use the OUI from the current MAC address */
+	memcpy(mac, adapter->netdev->dev_addr, 3);
 }
 
 extern void be_cq_notify(struct be_adapter *adapter, u16 qid, bool arm,
diff -druN linux-libre-2.6.38-gnu/drivers/net/benet/be_hw.h linux-libre-2.6.39-gnu/drivers/net/benet/be_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/benet/be_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/benet/be_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 /********* Mailbox door bell *************/
@@ -44,6 +44,18 @@
 #define POST_STAGE_BE_RESET		0x3 /* Host wants to reset chip */
 #define POST_STAGE_ARMFW_RDY		0xc000	/* FW is done with POST */
 
+
+/* Lancer SLIPORT_CONTROL SLIPORT_STATUS registers */
+#define SLIPORT_STATUS_OFFSET		0x404
+#define SLIPORT_CONTROL_OFFSET		0x408
+
+#define SLIPORT_STATUS_ERR_MASK		0x80000000
+#define SLIPORT_STATUS_RN_MASK		0x01000000
+#define SLIPORT_STATUS_RDY_MASK		0x00800000
+
+
+#define SLI_PORT_CONTROL_IP_MASK	0x08000000
+
 /********* Memory BAR register ************/
 #define PCICFG_MEMBAR_CTRL_INT_CTRL_OFFSET 	0xfc
 /* Host Interrupt Enable, if set interrupts are enabled although "PCI Interrupt
@@ -289,10 +301,10 @@
 
 /* RX Compl Queue Descriptor */
 
-/* Pseudo amap definition for eth_rx_compl in which each bit of the
- * actual structure is defined as a byte: used to calculate
+/* Pseudo amap definition for BE2 and BE3 legacy mode eth_rx_compl in which
+ * each bit of the actual structure is defined as a byte: used to calculate
  * offset/shift/mask of each field */
-struct amap_eth_rx_compl {
+struct amap_eth_rx_compl_v0 {
 	u8 vlan_tag[16];	/* dword 0 */
 	u8 pktsize[14];		/* dword 0 */
 	u8 port;		/* dword 0 */
@@ -323,10 +335,92 @@
 	u8 rsshash[32];		/* dword 3 */
 } __packed;
 
+/* Pseudo amap definition for BE3 native mode eth_rx_compl in which
+ * each bit of the actual structure is defined as a byte: used to calculate
+ * offset/shift/mask of each field */
+struct amap_eth_rx_compl_v1 {
+	u8 vlan_tag[16];	/* dword 0 */
+	u8 pktsize[14];		/* dword 0 */
+	u8 vtp;			/* dword 0 */
+	u8 ip_opt;		/* dword 0 */
+	u8 err;			/* dword 1 */
+	u8 rsshp;		/* dword 1 */
+	u8 ipf;			/* dword 1 */
+	u8 tcpf;		/* dword 1 */
+	u8 udpf;		/* dword 1 */
+	u8 ipcksm;		/* dword 1 */
+	u8 l4_cksm;		/* dword 1 */
+	u8 ip_version;		/* dword 1 */
+	u8 macdst[7];		/* dword 1 */
+	u8 rsvd0;		/* dword 1 */
+	u8 fragndx[10];		/* dword 1 */
+	u8 ct[2];		/* dword 1 */
+	u8 sw;			/* dword 1 */
+	u8 numfrags[3];		/* dword 1 */
+	u8 rss_flush;		/* dword 2 */
+	u8 cast_enc[2];		/* dword 2 */
+	u8 vtm;			/* dword 2 */
+	u8 rss_bank;		/* dword 2 */
+	u8 port[2];		/* dword 2 */
+	u8 vntagp;		/* dword 2 */
+	u8 header_len[8];	/* dword 2 */
+	u8 header_split[2];	/* dword 2 */
+	u8 rsvd1[13];		/* dword 2 */
+	u8 valid;		/* dword 2 */
+	u8 rsshash[32];		/* dword 3 */
+} __packed;
+
 struct be_eth_rx_compl {
 	u32 dw[4];
 };
 
+struct mgmt_hba_attribs {
+	u8 flashrom_version_string[32];
+	u8 manufacturer_name[32];
+	u32 supported_modes;
+	u32 rsvd0[3];
+	u8 ncsi_ver_string[12];
+	u32 default_extended_timeout;
+	u8 controller_model_number[32];
+	u8 controller_description[64];
+	u8 controller_serial_number[32];
+	u8 ip_version_string[32];
+	u8 firmware_version_string[32];
+	u8 bios_version_string[32];
+	u8 redboot_version_string[32];
+	u8 driver_version_string[32];
+	u8 fw_on_flash_version_string[32];
+	u32 functionalities_supported;
+	u16 max_cdblength;
+	u8 asic_revision;
+	u8 generational_guid[16];
+	u8 hba_port_count;
+	u16 default_link_down_timeout;
+	u8 iscsi_ver_min_max;
+	u8 multifunction_device;
+	u8 cache_valid;
+	u8 hba_status;
+	u8 max_domains_supported;
+	u8 phy_port;
+	u32 firmware_post_status;
+	u32 hba_mtu[8];
+	u32 rsvd1[4];
+};
+
+struct mgmt_controller_attrib {
+	struct mgmt_hba_attribs hba_attribs;
+	u16 pci_vendor_id;
+	u16 pci_device_id;
+	u16 pci_sub_vendor_id;
+	u16 pci_sub_system_id;
+	u8 pci_bus_number;
+	u8 pci_device_number;
+	u8 pci_function_number;
+	u8 interface_type;
+	u64 unique_identifier;
+	u32 rsvd0[5];
+};
+
 struct controller_id {
 	u32 vendor;
 	u32 device;
diff -druN linux-libre-2.6.38-gnu/drivers/net/benet/be_main.c linux-libre-2.6.39-gnu/drivers/net/benet/be_main.c
--- linux-libre-2.6.38-gnu/drivers/net/benet/be_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/benet/be_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2005 - 2010 ServerEngines
+ * Copyright (C) 2005 - 2011 Emulex
  * All rights reserved.
  *
  * This program is free software; you can redistribute it and/or
@@ -8,11 +8,11 @@
  * Public License is included in this distribution in the file called COPYING.
  *
  * Contact Information:
- * linux-drivers@serverengines.com
+ * linux-drivers@emulex.com
  *
- * ServerEngines
- * 209 N. Fair Oaks Ave
- * Sunnyvale, CA 94085
+ * Emulex
+ * 3333 Susan Street
+ * Costa Mesa, CA 92626
  */
 
 #include "be.h"
@@ -25,9 +25,9 @@
 MODULE_AUTHOR("ServerEngines Corporation");
 MODULE_LICENSE("GPL");
 
-static unsigned int rx_frag_size = 2048;
+static ushort rx_frag_size = 2048;
 static unsigned int num_vfs;
-module_param(rx_frag_size, uint, S_IRUGO);
+module_param(rx_frag_size, ushort, S_IRUGO);
 module_param(num_vfs, uint, S_IRUGO);
 MODULE_PARM_DESC(rx_frag_size, "Size of a fragment that holds rcvd data.");
 MODULE_PARM_DESC(num_vfs, "Number of PCI VFs to initialize");
@@ -125,8 +125,8 @@
 {
 	struct be_dma_mem *mem = &q->dma_mem;
 	if (mem->va)
-		pci_free_consistent(adapter->pdev, mem->size,
-			mem->va, mem->dma);
+		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
+				  mem->dma);
 }
 
 static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
@@ -138,7 +138,8 @@
 	q->len = len;
 	q->entry_size = entry_size;
 	mem->size = len * entry_size;
-	mem->va = pci_alloc_consistent(adapter->pdev, mem->size, &mem->dma);
+	mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
+				     GFP_KERNEL);
 	if (!mem->va)
 		return -1;
 	memset(mem->va, 0, mem->size);
@@ -235,12 +236,13 @@
 	if (!be_physfn(adapter))
 		goto netdev_addr;
 
-	status = be_cmd_pmac_del(adapter, adapter->if_handle, adapter->pmac_id);
+	status = be_cmd_pmac_del(adapter, adapter->if_handle,
+				adapter->pmac_id, 0);
 	if (status)
 		return status;
 
 	status = be_cmd_pmac_add(adapter, (u8 *)addr->sa_data,
-			adapter->if_handle, &adapter->pmac_id);
+				adapter->if_handle, &adapter->pmac_id, 0);
 netdev_addr:
 	if (!status)
 		memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
@@ -484,7 +486,7 @@
 	AMAP_SET_BITS(struct amap_eth_hdr_wrb, len, hdr, len);
 }
 
-static void unmap_tx_frag(struct pci_dev *pdev, struct be_eth_wrb *wrb,
+static void unmap_tx_frag(struct device *dev, struct be_eth_wrb *wrb,
 		bool unmap_single)
 {
 	dma_addr_t dma;
@@ -494,11 +496,10 @@
 	dma = (u64)wrb->frag_pa_hi << 32 | (u64)wrb->frag_pa_lo;
 	if (wrb->frag_len) {
 		if (unmap_single)
-			pci_unmap_single(pdev, dma, wrb->frag_len,
-				PCI_DMA_TODEVICE);
+			dma_unmap_single(dev, dma, wrb->frag_len,
+					 DMA_TO_DEVICE);
 		else
-			pci_unmap_page(pdev, dma, wrb->frag_len,
-				PCI_DMA_TODEVICE);
+			dma_unmap_page(dev, dma, wrb->frag_len, DMA_TO_DEVICE);
 	}
 }
 
@@ -507,7 +508,7 @@
 {
 	dma_addr_t busaddr;
 	int i, copied = 0;
-	struct pci_dev *pdev = adapter->pdev;
+	struct device *dev = &adapter->pdev->dev;
 	struct sk_buff *first_skb = skb;
 	struct be_queue_info *txq = &adapter->tx_obj.q;
 	struct be_eth_wrb *wrb;
@@ -521,9 +522,8 @@
 
 	if (skb->len > skb->data_len) {
 		int len = skb_headlen(skb);
-		busaddr = pci_map_single(pdev, skb->data, len,
-					 PCI_DMA_TODEVICE);
-		if (pci_dma_mapping_error(pdev, busaddr))
+		busaddr = dma_map_single(dev, skb->data, len, DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, busaddr))
 			goto dma_err;
 		map_single = true;
 		wrb = queue_head_node(txq);
@@ -536,10 +536,9 @@
 	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);
-		if (pci_dma_mapping_error(pdev, busaddr))
+		busaddr = dma_map_page(dev, frag->page, frag->page_offset,
+				       frag->size, DMA_TO_DEVICE);
+		if (dma_mapping_error(dev, busaddr))
 			goto dma_err;
 		wrb = queue_head_node(txq);
 		wrb_fill(wrb, busaddr, frag->size);
@@ -563,7 +562,7 @@
 	txq->head = map_head;
 	while (copied) {
 		wrb = queue_head_node(txq);
-		unmap_tx_frag(pdev, wrb, map_single);
+		unmap_tx_frag(dev, wrb, map_single);
 		map_single = false;
 		copied -= wrb->frag_len;
 		queue_head_inc(txq);
@@ -709,7 +708,7 @@
 		goto done;
 	}
 
-	/* BE was previously in promiscous mode; disable it */
+	/* BE was previously in promiscuous mode; disable it */
 	if (adapter->promiscuous) {
 		adapter->promiscuous = false;
 		be_cmd_promiscuous_config(adapter, adapter->port_num, 0);
@@ -743,11 +742,11 @@
 	if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
 		status = be_cmd_pmac_del(adapter,
 					adapter->vf_cfg[vf].vf_if_handle,
-					adapter->vf_cfg[vf].vf_pmac_id);
+					adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
 
 	status = be_cmd_pmac_add(adapter, mac,
 				adapter->vf_cfg[vf].vf_if_handle,
-				&adapter->vf_cfg[vf].vf_pmac_id);
+				&adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
 
 	if (status)
 		dev_err(&adapter->pdev->dev, "MAC %pM set on VF %d Failed\n",
@@ -822,7 +821,7 @@
 		rate = 10000;
 
 	adapter->vf_cfg[vf].vf_tx_rate = rate;
-	status = be_cmd_set_qos(adapter, rate / 10, vf);
+	status = be_cmd_set_qos(adapter, rate / 10, vf + 1);
 
 	if (status)
 		dev_info(&adapter->pdev->dev,
@@ -852,28 +851,26 @@
 }
 
 static void be_rx_stats_update(struct be_rx_obj *rxo,
-		u32 pktsize, u16 numfrags, u8 pkt_type)
+		struct be_rx_compl_info *rxcp)
 {
 	struct be_rx_stats *stats = &rxo->stats;
 
 	stats->rx_compl++;
-	stats->rx_frags += numfrags;
-	stats->rx_bytes += pktsize;
+	stats->rx_frags += rxcp->num_rcvd;
+	stats->rx_bytes += rxcp->pkt_size;
 	stats->rx_pkts++;
-	if (pkt_type == BE_MULTICAST_PACKET)
+	if (rxcp->pkt_type == BE_MULTICAST_PACKET)
 		stats->rx_mcast_pkts++;
+	if (rxcp->err)
+		stats->rxcp_err++;
 }
 
-static inline bool csum_passed(struct be_eth_rx_compl *rxcp)
+static inline bool csum_passed(struct be_rx_compl_info *rxcp)
 {
-	u8 l4_cksm, ipv6, ipcksm;
-
-	l4_cksm = AMAP_GET_BITS(struct amap_eth_rx_compl, l4_cksm, rxcp);
-	ipcksm = AMAP_GET_BITS(struct amap_eth_rx_compl, ipcksm, rxcp);
-	ipv6 = AMAP_GET_BITS(struct amap_eth_rx_compl, ip_version, rxcp);
-
-	/* Ignore ipcksm for ipv6 pkts */
-	return l4_cksm && (ipcksm || ipv6);
+	/* L4 checksum is not reliable for non TCP/UDP packets.
+	 * Also ignore ipcksm for ipv6 pkts */
+	return (rxcp->tcpf || rxcp->udpf) && rxcp->l4_csum &&
+				(rxcp->ip_csum || rxcp->ipv6);
 }
 
 static struct be_rx_page_info *
@@ -888,8 +885,9 @@
 	BUG_ON(!rx_page_info->page);
 
 	if (rx_page_info->last_page_user) {
-		pci_unmap_page(adapter->pdev, dma_unmap_addr(rx_page_info, bus),
-			adapter->big_page_size, PCI_DMA_FROMDEVICE);
+		dma_unmap_page(&adapter->pdev->dev,
+			       dma_unmap_addr(rx_page_info, bus),
+			       adapter->big_page_size, DMA_FROM_DEVICE);
 		rx_page_info->last_page_user = false;
 	}
 
@@ -900,26 +898,17 @@
 /* Throwaway the data in the Rx completion */
 static void be_rx_compl_discard(struct be_adapter *adapter,
 		struct be_rx_obj *rxo,
-		struct be_eth_rx_compl *rxcp)
+		struct be_rx_compl_info *rxcp)
 {
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_rx_page_info *page_info;
-	u16 rxq_idx, i, num_rcvd;
-
-	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
-	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-
-	 /* Skip out-of-buffer compl(lancer) or flush compl(BE) */
-	if (likely(rxq_idx != rxo->last_frag_index && num_rcvd != 0)) {
-
-		rxo->last_frag_index = rxq_idx;
+	u16 i, num_rcvd = rxcp->num_rcvd;
 
-		for (i = 0; i < num_rcvd; i++) {
-			page_info = get_rx_page_info(adapter, rxo, rxq_idx);
-			put_page(page_info->page);
-			memset(page_info, 0, sizeof(*page_info));
-			index_inc(&rxq_idx, rxq->len);
-		}
+	for (i = 0; i < num_rcvd; i++) {
+		page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+		put_page(page_info->page);
+		memset(page_info, 0, sizeof(*page_info));
+		index_inc(&rxcp->rxq_idx, rxq->len);
 	}
 }
 
@@ -928,30 +917,23 @@
  * indicated by rxcp.
  */
 static void skb_fill_rx_data(struct be_adapter *adapter, struct be_rx_obj *rxo,
-			struct sk_buff *skb, struct be_eth_rx_compl *rxcp,
-			u16 num_rcvd)
+			struct sk_buff *skb, struct be_rx_compl_info *rxcp)
 {
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_rx_page_info *page_info;
-	u16 rxq_idx, i, j;
-	u32 pktsize, hdr_len, curr_frag_len, size;
+	u16 i, j;
+	u16 hdr_len, curr_frag_len, remaining;
 	u8 *start;
-	u8 pkt_type;
-
-	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
-	pktsize = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
-	pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
-
-	page_info = get_rx_page_info(adapter, rxo, rxq_idx);
 
+	page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
 	start = page_address(page_info->page) + page_info->page_offset;
 	prefetch(start);
 
 	/* Copy data in the first descriptor of this completion */
-	curr_frag_len = min(pktsize, rx_frag_size);
+	curr_frag_len = min(rxcp->pkt_size, rx_frag_size);
 
 	/* Copy the header portion into skb_data */
-	hdr_len = min((u32)BE_HDR_LEN, curr_frag_len);
+	hdr_len = min(BE_HDR_LEN, curr_frag_len);
 	memcpy(skb->data, start, hdr_len);
 	skb->len = curr_frag_len;
 	if (curr_frag_len <= BE_HDR_LEN) { /* tiny packet */
@@ -970,19 +952,17 @@
 	}
 	page_info->page = NULL;
 
-	if (pktsize <= rx_frag_size) {
-		BUG_ON(num_rcvd != 1);
-		goto done;
+	if (rxcp->pkt_size <= rx_frag_size) {
+		BUG_ON(rxcp->num_rcvd != 1);
+		return;
 	}
 
 	/* More frags present for this completion */
-	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, rxo, rxq_idx);
-
-		curr_frag_len = min(size, rx_frag_size);
+	index_inc(&rxcp->rxq_idx, rxq->len);
+	remaining = rxcp->pkt_size - curr_frag_len;
+	for (i = 1, j = 0; i < rxcp->num_rcvd; i++) {
+		page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
+		curr_frag_len = min(remaining, rx_frag_size);
 
 		/* Coalesce all frags from the same physical page in one slot */
 		if (page_info->page_offset == 0) {
@@ -1001,25 +981,19 @@
 		skb->len += curr_frag_len;
 		skb->data_len += curr_frag_len;
 
+		remaining -= curr_frag_len;
+		index_inc(&rxcp->rxq_idx, rxq->len);
 		page_info->page = NULL;
 	}
 	BUG_ON(j > MAX_SKB_FRAGS);
-
-done:
-	be_rx_stats_update(rxo, pktsize, num_rcvd, pkt_type);
 }
 
 /* Process the RX completion indicated by rxcp when GRO is disabled */
 static void be_rx_compl_process(struct be_adapter *adapter,
 			struct be_rx_obj *rxo,
-			struct be_eth_rx_compl *rxcp)
+			struct be_rx_compl_info *rxcp)
 {
 	struct sk_buff *skb;
-	u32 vlanf, vid;
-	u16 num_rcvd;
-	u8 vtm;
-
-	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
 
 	skb = netdev_alloc_skb_ip_align(adapter->netdev, BE_HDR_LEN);
 	if (unlikely(!skb)) {
@@ -1029,7 +1003,7 @@
 		return;
 	}
 
-	skb_fill_rx_data(adapter, rxo, skb, rxcp, num_rcvd);
+	skb_fill_rx_data(adapter, rxo, skb, rxcp);
 
 	if (likely(adapter->rx_csum && csum_passed(rxcp)))
 		skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -1039,23 +1013,13 @@
 	skb->truesize = skb->len + sizeof(struct sk_buff);
 	skb->protocol = eth_type_trans(skb, adapter->netdev);
 
-	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
-	vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
-
-	/* vlanf could be wrongly set in some cards.
-	 * ignore if vtm is not set */
-	if ((adapter->function_mode & 0x400) && !vtm)
-		vlanf = 0;
-
-	if (unlikely(vlanf)) {
+	if (unlikely(rxcp->vlanf)) {
 		if (!adapter->vlan_grp || adapter->vlans_added == 0) {
 			kfree_skb(skb);
 			return;
 		}
-		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-		if (!lancer_chip(adapter))
-			vid = swab16(vid);
-		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp, vid);
+		vlan_hwaccel_receive_skb(skb, adapter->vlan_grp,
+					rxcp->vlan_tag);
 	} else {
 		netif_receive_skb(skb);
 	}
@@ -1064,28 +1028,14 @@
 /* Process the RX completion indicated by rxcp when GRO is enabled */
 static void be_rx_compl_process_gro(struct be_adapter *adapter,
 		struct be_rx_obj *rxo,
-		struct be_eth_rx_compl *rxcp)
+		struct be_rx_compl_info *rxcp)
 {
 	struct be_rx_page_info *page_info;
 	struct sk_buff *skb = NULL;
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_eq_obj *eq_obj =  &rxo->rx_eq;
-	u32 num_rcvd, pkt_size, remaining, vlanf, curr_frag_len;
-	u16 i, rxq_idx = 0, vid, j;
-	u8 vtm;
-	u8 pkt_type;
-
-	num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags, rxcp);
-	pkt_size = AMAP_GET_BITS(struct amap_eth_rx_compl, pktsize, rxcp);
-	vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl, vtp, rxcp);
-	rxq_idx = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx, rxcp);
-	vtm = AMAP_GET_BITS(struct amap_eth_rx_compl, vtm, rxcp);
-	pkt_type = AMAP_GET_BITS(struct amap_eth_rx_compl, cast_enc, rxcp);
-
-	/* vlanf could be wrongly set in some cards.
-	 * ignore if vtm is not set */
-	if ((adapter->function_mode & 0x400) && !vtm)
-		vlanf = 0;
+	u16 remaining, curr_frag_len;
+	u16 i, j;
 
 	skb = napi_get_frags(&eq_obj->napi);
 	if (!skb) {
@@ -1093,9 +1043,9 @@
 		return;
 	}
 
-	remaining = pkt_size;
-	for (i = 0, j = -1; i < num_rcvd; i++) {
-		page_info = get_rx_page_info(adapter, rxo, rxq_idx);
+	remaining = rxcp->pkt_size;
+	for (i = 0, j = -1; i < rxcp->num_rcvd; i++) {
+		page_info = get_rx_page_info(adapter, rxo, rxcp->rxq_idx);
 
 		curr_frag_len = min(remaining, rx_frag_size);
 
@@ -1113,70 +1063,130 @@
 		skb_shinfo(skb)->frags[j].size += curr_frag_len;
 
 		remaining -= curr_frag_len;
-		index_inc(&rxq_idx, rxq->len);
+		index_inc(&rxcp->rxq_idx, rxq->len);
 		memset(page_info, 0, sizeof(*page_info));
 	}
 	BUG_ON(j > MAX_SKB_FRAGS);
 
 	skb_shinfo(skb)->nr_frags = j + 1;
-	skb->len = pkt_size;
-	skb->data_len = pkt_size;
-	skb->truesize += pkt_size;
+	skb->len = rxcp->pkt_size;
+	skb->data_len = rxcp->pkt_size;
+	skb->truesize += rxcp->pkt_size;
 	skb->ip_summed = CHECKSUM_UNNECESSARY;
 
-	if (likely(!vlanf)) {
+	if (likely(!rxcp->vlanf))
 		napi_gro_frags(&eq_obj->napi);
-	} else {
-		vid = AMAP_GET_BITS(struct amap_eth_rx_compl, vlan_tag, rxcp);
-		if (!lancer_chip(adapter))
-			vid = swab16(vid);
-
-		if (!adapter->vlan_grp || adapter->vlans_added == 0)
-			return;
+	else
+		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp,
+				rxcp->vlan_tag);
+}
 
-		vlan_gro_frags(&eq_obj->napi, adapter->vlan_grp, vid);
-	}
+static void be_parse_rx_compl_v1(struct be_adapter *adapter,
+				struct be_eth_rx_compl *compl,
+				struct be_rx_compl_info *rxcp)
+{
+	rxcp->pkt_size =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, pktsize, compl);
+	rxcp->vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtp, compl);
+	rxcp->err = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, err, compl);
+	rxcp->tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, tcpf, compl);
+	rxcp->udpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, udpf, compl);
+	rxcp->ip_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ipcksm, compl);
+	rxcp->l4_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, l4_cksm, compl);
+	rxcp->ipv6 =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, ip_version, compl);
+	rxcp->rxq_idx =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, fragndx, compl);
+	rxcp->num_rcvd =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, numfrags, compl);
+	rxcp->pkt_type =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v1, cast_enc, compl);
+	rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vtm, compl);
+	rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v1, vlan_tag,
+					compl);
+}
 
-	be_rx_stats_update(rxo, pkt_size, num_rcvd, pkt_type);
+static void be_parse_rx_compl_v0(struct be_adapter *adapter,
+				struct be_eth_rx_compl *compl,
+				struct be_rx_compl_info *rxcp)
+{
+	rxcp->pkt_size =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, pktsize, compl);
+	rxcp->vlanf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtp, compl);
+	rxcp->err = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, err, compl);
+	rxcp->tcpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, tcpf, compl);
+	rxcp->udpf = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, udpf, compl);
+	rxcp->ip_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ipcksm, compl);
+	rxcp->l4_csum =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, l4_cksm, compl);
+	rxcp->ipv6 =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, ip_version, compl);
+	rxcp->rxq_idx =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, fragndx, compl);
+	rxcp->num_rcvd =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, numfrags, compl);
+	rxcp->pkt_type =
+		AMAP_GET_BITS(struct amap_eth_rx_compl_v0, cast_enc, compl);
+	rxcp->vtm = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vtm, compl);
+	rxcp->vlan_tag = AMAP_GET_BITS(struct amap_eth_rx_compl_v0, vlan_tag,
+					compl);
 }
 
-static struct be_eth_rx_compl *be_rx_compl_get(struct be_rx_obj *rxo)
+static struct be_rx_compl_info *be_rx_compl_get(struct be_rx_obj *rxo)
 {
-	struct be_eth_rx_compl *rxcp = queue_tail_node(&rxo->cq);
+	struct be_eth_rx_compl *compl = queue_tail_node(&rxo->cq);
+	struct be_rx_compl_info *rxcp = &rxo->rxcp;
+	struct be_adapter *adapter = rxo->adapter;
 
-	if (rxcp->dw[offsetof(struct amap_eth_rx_compl, valid) / 32] == 0)
+	/* For checking the valid bit it is Ok to use either definition as the
+	 * valid bit is at the same position in both v0 and v1 Rx compl */
+	if (compl->dw[offsetof(struct amap_eth_rx_compl_v1, valid) / 32] == 0)
 		return NULL;
 
 	rmb();
-	be_dws_le_to_cpu(rxcp, sizeof(*rxcp));
+	be_dws_le_to_cpu(compl, sizeof(*compl));
+
+	if (adapter->be3_native)
+		be_parse_rx_compl_v1(adapter, compl, rxcp);
+	else
+		be_parse_rx_compl_v0(adapter, compl, rxcp);
+
+	/* vlanf could be wrongly set in some cards. ignore if vtm is not set */
+	if ((adapter->function_mode & 0x400) && !rxcp->vtm)
+		rxcp->vlanf = 0;
+
+	if (!lancer_chip(adapter))
+		rxcp->vlan_tag = swab16(rxcp->vlan_tag);
+
+	if (((adapter->pvid & VLAN_VID_MASK) ==
+		(rxcp->vlan_tag & VLAN_VID_MASK)) &&
+		!adapter->vlan_tag[rxcp->vlan_tag])
+		rxcp->vlanf = 0;
+
+	/* As the compl has been parsed, reset it; we wont touch it again */
+	compl->dw[offsetof(struct amap_eth_rx_compl_v1, valid) / 32] = 0;
 
 	queue_tail_inc(&rxo->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)
+static inline struct page *be_alloc_pages(u32 size, gfp_t gfp)
 {
-	gfp_t alloc_flags = GFP_ATOMIC;
 	u32 order = get_order(size);
+
 	if (order > 0)
-		alloc_flags |= __GFP_COMP;
-	return  alloc_pages(alloc_flags, order);
+		gfp |= __GFP_COMP;
+	return  alloc_pages(gfp, order);
 }
 
 /*
  * Allocate a page, split it to fragments of size rx_frag_size and post as
  * receive buffers to BE
  */
-static void be_post_rx_frags(struct be_rx_obj *rxo)
+static void be_post_rx_frags(struct be_rx_obj *rxo, gfp_t gfp)
 {
 	struct be_adapter *adapter = rxo->adapter;
 	struct be_rx_page_info *page_info_tbl = rxo->page_info_tbl;
@@ -1190,14 +1200,14 @@
 	page_info = &rxo->page_info_tbl[rxq->head];
 	for (posted = 0; posted < MAX_RX_POST && !page_info->page; posted++) {
 		if (!pagep) {
-			pagep = be_alloc_pages(adapter->big_page_size);
+			pagep = be_alloc_pages(adapter->big_page_size, gfp);
 			if (unlikely(!pagep)) {
 				rxo->stats.rx_post_fail++;
 				break;
 			}
-			page_dmaaddr = pci_map_page(adapter->pdev, pagep, 0,
-						adapter->big_page_size,
-						PCI_DMA_FROMDEVICE);
+			page_dmaaddr = dma_map_page(&adapter->pdev->dev, pagep,
+						    0, adapter->big_page_size,
+						    DMA_FROM_DEVICE);
 			page_info->page_offset = 0;
 		} else {
 			get_page(pagep);
@@ -1270,8 +1280,8 @@
 	do {
 		cur_index = txq->tail;
 		wrb = queue_tail_node(txq);
-		unmap_tx_frag(adapter->pdev, wrb, (unmap_skb_hdr &&
-					skb_headlen(sent_skb)));
+		unmap_tx_frag(&adapter->pdev->dev, wrb,
+			      (unmap_skb_hdr && skb_headlen(sent_skb)));
 		unmap_skb_hdr = false;
 
 		num_wrbs++;
@@ -1339,13 +1349,12 @@
 	struct be_rx_page_info *page_info;
 	struct be_queue_info *rxq = &rxo->q;
 	struct be_queue_info *rx_cq = &rxo->cq;
-	struct be_eth_rx_compl *rxcp;
+	struct be_rx_compl_info *rxcp;
 	u16 tail;
 
 	/* First cleanup pending rx completions */
 	while ((rxcp = be_rx_compl_get(rxo)) != NULL) {
 		be_rx_compl_discard(adapter, rxo, rxcp);
-		be_rx_compl_reset(rxcp);
 		be_cq_notify(adapter, rx_cq->id, false, 1);
 	}
 
@@ -1494,7 +1503,7 @@
 	if (be_cmd_eq_create(adapter, eq, adapter->tx_eq.cur_eqd))
 		goto tx_eq_free;
 
-	adapter->tx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+	adapter->tx_eq.eq_idx = adapter->eq_next_idx++;
 
 
 	/* Alloc TX eth compl queue */
@@ -1573,9 +1582,6 @@
 	adapter->big_page_size = (1 << get_order(rx_frag_size)) * PAGE_SIZE;
 	for_all_rx_queues(adapter, rxo, i) {
 		rxo->adapter = adapter;
-		/* Init last_frag_index so that the frag index in the first
-		 * completion will never match */
-		rxo->last_frag_index = 0xffff;
 		rxo->rx_eq.max_eqd = BE_MAX_EQD;
 		rxo->rx_eq.enable_aic = true;
 
@@ -1590,7 +1596,7 @@
 		if (rc)
 			goto err;
 
-		rxo->rx_eq.msix_vec_idx = adapter->msix_vec_next_idx++;
+		rxo->rx_eq.eq_idx = adapter->eq_next_idx++;
 
 		/* CQ */
 		cq = &rxo->cq;
@@ -1666,11 +1672,11 @@
 		if (!isr)
 			return IRQ_NONE;
 
-		if ((1 << adapter->tx_eq.msix_vec_idx & isr))
+		if ((1 << adapter->tx_eq.eq_idx & isr))
 			event_handle(adapter, &adapter->tx_eq);
 
 		for_all_rx_queues(adapter, rxo, i) {
-			if ((1 << rxo->rx_eq.msix_vec_idx & isr))
+			if ((1 << rxo->rx_eq.eq_idx & isr))
 				event_handle(adapter, &rxo->rx_eq);
 		}
 	}
@@ -1697,15 +1703,9 @@
 	return IRQ_HANDLED;
 }
 
-static inline bool do_gro(struct be_rx_obj *rxo,
-			struct be_eth_rx_compl *rxcp, u8 err)
+static inline bool do_gro(struct be_rx_compl_info *rxcp)
 {
-	int tcp_frame = AMAP_GET_BITS(struct amap_eth_rx_compl, tcpf, rxcp);
-
-	if (err)
-		rxo->stats.rxcp_err++;
-
-	return (tcp_frame && !err) ? true : false;
+	return (rxcp->tcpf && !rxcp->err) ? true : false;
 }
 
 static int be_poll_rx(struct napi_struct *napi, int budget)
@@ -1714,10 +1714,8 @@
 	struct be_rx_obj *rxo = container_of(rx_eq, struct be_rx_obj, rx_eq);
 	struct be_adapter *adapter = rxo->adapter;
 	struct be_queue_info *rx_cq = &rxo->cq;
-	struct be_eth_rx_compl *rxcp;
+	struct be_rx_compl_info *rxcp;
 	u32 work_done;
-	u16 frag_index, num_rcvd;
-	u8 err;
 
 	rxo->stats.rx_polls++;
 	for (work_done = 0; work_done < budget; work_done++) {
@@ -1725,29 +1723,19 @@
 		if (!rxcp)
 			break;
 
-		err = AMAP_GET_BITS(struct amap_eth_rx_compl, err, rxcp);
-		frag_index = AMAP_GET_BITS(struct amap_eth_rx_compl, fragndx,
-								rxcp);
-		num_rcvd = AMAP_GET_BITS(struct amap_eth_rx_compl, numfrags,
-								rxcp);
-
-		/* Skip out-of-buffer compl(lancer) or flush compl(BE) */
-		if (likely(frag_index != rxo->last_frag_index &&
-				num_rcvd != 0)) {
-			rxo->last_frag_index = frag_index;
-
-			if (do_gro(rxo, rxcp, err))
+		/* Ignore flush completions */
+		if (rxcp->num_rcvd) {
+			if (do_gro(rxcp))
 				be_rx_compl_process_gro(adapter, rxo, rxcp);
 			else
 				be_rx_compl_process(adapter, rxo, rxcp);
 		}
-
-		be_rx_compl_reset(rxcp);
+		be_rx_stats_update(rxo, rxcp);
 	}
 
 	/* Refill the queue */
 	if (atomic_read(&rxo->q.used) < RX_FRAGS_REFILL_WM)
-		be_post_rx_frags(rxo);
+		be_post_rx_frags(rxo, GFP_ATOMIC);
 
 	/* All consumed */
 	if (work_done < budget) {
@@ -1827,6 +1815,7 @@
 
 	if (ue_status_lo || ue_status_hi) {
 		adapter->ue_detected = true;
+		adapter->eeh_err = true;
 		dev_err(&adapter->pdev->dev, "UE Detected!!\n");
 	}
 
@@ -1865,10 +1854,14 @@
 			struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 			be_cq_notify(adapter, mcc_obj->cq.id, false, mcc_compl);
 		}
+
+		if (!adapter->ue_detected && !lancer_chip(adapter))
+			be_detect_dump_ue(adapter);
+
 		goto reschedule;
 	}
 
-	if (!adapter->stats_ioctl_sent)
+	if (!adapter->stats_cmd_sent)
 		be_cmd_get_stats(adapter, &adapter->stats_cmd);
 
 	be_tx_rate_update(adapter);
@@ -1879,13 +1872,14 @@
 
 		if (rxo->rx_post_starved) {
 			rxo->rx_post_starved = false;
-			be_post_rx_frags(rxo);
+			be_post_rx_frags(rxo, GFP_KERNEL);
 		}
 	}
 	if (!adapter->ue_detected && !lancer_chip(adapter))
 		be_detect_dump_ue(adapter);
 
 reschedule:
+	adapter->work_counter++;
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(1000));
 }
 
@@ -1964,7 +1958,7 @@
 static inline int be_msix_vec_get(struct be_adapter *adapter,
 					struct be_eq_obj *eq_obj)
 {
-	return adapter->msix_entries[eq_obj->msix_vec_idx].vector;
+	return adapter->msix_entries[eq_obj->eq_idx].vector;
 }
 
 static int be_request_irq(struct be_adapter *adapter,
@@ -2083,13 +2077,24 @@
 
 	be_async_mcc_disable(adapter);
 
-	netif_stop_queue(netdev);
 	netif_carrier_off(netdev);
 	adapter->link_up = false;
 
 	if (!lancer_chip(adapter))
 		be_intr_set(adapter, false);
 
+	for_all_rx_queues(adapter, rxo, i)
+		napi_disable(&rxo->rx_eq.napi);
+
+	napi_disable(&tx_eq->napi);
+
+	if (lancer_chip(adapter)) {
+		be_cq_notify(adapter, adapter->tx_obj.cq.id, false, 0);
+		be_cq_notify(adapter, adapter->mcc_obj.cq.id, false, 0);
+		for_all_rx_queues(adapter, rxo, i)
+			 be_cq_notify(adapter, rxo->cq.id, false, 0);
+	}
+
 	if (adapter->msix_enabled) {
 		vec = be_msix_vec_get(adapter, tx_eq);
 		synchronize_irq(vec);
@@ -2103,11 +2108,6 @@
 	}
 	be_irq_unregister(adapter);
 
-	for_all_rx_queues(adapter, rxo, i)
-		napi_disable(&rxo->rx_eq.napi);
-
-	napi_disable(&tx_eq->napi);
-
 	/* Wait for all pending tx completions to arrive so that
 	 * all tx skbs are freed.
 	 */
@@ -2127,7 +2127,7 @@
 	u16 link_speed;
 
 	for_all_rx_queues(adapter, rxo, i) {
-		be_post_rx_frags(rxo);
+		be_post_rx_frags(rxo, GFP_KERNEL);
 		napi_enable(&rxo->rx_eq.napi);
 	}
 	napi_enable(&tx_eq->napi);
@@ -2179,7 +2179,8 @@
 	memset(mac, 0, ETH_ALEN);
 
 	cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
-	cmd.va = pci_alloc_consistent(adapter->pdev, cmd.size, &cmd.dma);
+	cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+				    GFP_KERNEL);
 	if (cmd.va == NULL)
 		return -1;
 	memset(cmd.va, 0, cmd.size);
@@ -2190,8 +2191,8 @@
 		if (status) {
 			dev_err(&adapter->pdev->dev,
 				"Could not enable Wake-on-lan\n");
-			pci_free_consistent(adapter->pdev, cmd.size, cmd.va,
-					cmd.dma);
+			dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va,
+					  cmd.dma);
 			return status;
 		}
 		status = be_cmd_enable_magic_wol(adapter,
@@ -2204,7 +2205,7 @@
 		pci_enable_wake(adapter->pdev, PCI_D3cold, 0);
 	}
 
-	pci_free_consistent(adapter->pdev, cmd.size, cmd.va, cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, cmd.size, cmd.va, cmd.dma);
 	return status;
 }
 
@@ -2225,7 +2226,8 @@
 	for (vf = 0; vf < num_vfs; vf++) {
 		status = be_cmd_pmac_add(adapter, mac,
 					adapter->vf_cfg[vf].vf_if_handle,
-					&adapter->vf_cfg[vf].vf_pmac_id);
+					&adapter->vf_cfg[vf].vf_pmac_id,
+					vf + 1);
 		if (status)
 			dev_err(&adapter->pdev->dev,
 				"Mac address add failed for VF %d\n", vf);
@@ -2245,7 +2247,7 @@
 		if (adapter->vf_cfg[vf].vf_pmac_id != BE_INVALID_PMAC_ID)
 			be_cmd_pmac_del(adapter,
 					adapter->vf_cfg[vf].vf_if_handle,
-					adapter->vf_cfg[vf].vf_pmac_id);
+					adapter->vf_cfg[vf].vf_pmac_id, vf + 1);
 	}
 }
 
@@ -2256,7 +2258,9 @@
 	int status;
 	u8 mac[ETH_ALEN];
 
-	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED | BE_IF_FLAGS_BROADCAST;
+	cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
+				BE_IF_FLAGS_BROADCAST |
+				BE_IF_FLAGS_MULTICAST;
 
 	if (be_physfn(adapter)) {
 		cap_flags |= BE_IF_FLAGS_MCAST_PROMISCUOUS |
@@ -2277,22 +2281,26 @@
 		goto do_none;
 
 	if (be_physfn(adapter)) {
-		while (vf < num_vfs) {
-			cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED
-					| BE_IF_FLAGS_BROADCAST;
-			status = be_cmd_if_create(adapter, cap_flags, en_flags,
-					mac, true,
+		if (adapter->sriov_enabled) {
+			while (vf < num_vfs) {
+				cap_flags = en_flags = BE_IF_FLAGS_UNTAGGED |
+							BE_IF_FLAGS_BROADCAST;
+				status = be_cmd_if_create(adapter, cap_flags,
+					en_flags, mac, true,
 					&adapter->vf_cfg[vf].vf_if_handle,
 					NULL, vf+1);
-			if (status) {
-				dev_err(&adapter->pdev->dev,
-				"Interface Create failed for VF %d\n", vf);
-				goto if_destroy;
+				if (status) {
+					dev_err(&adapter->pdev->dev,
+					"Interface Create failed for VF %d\n",
+					vf);
+					goto if_destroy;
+				}
+				adapter->vf_cfg[vf].vf_pmac_id =
+							BE_INVALID_PMAC_ID;
+				vf++;
 			}
-			adapter->vf_cfg[vf].vf_pmac_id = BE_INVALID_PMAC_ID;
-			vf++;
 		}
-	} else if (!be_physfn(adapter)) {
+	} else {
 		status = be_cmd_mac_addr_query(adapter, mac,
 			MAC_ADDRESS_TYPE_NETWORK, false, adapter->if_handle);
 		if (!status) {
@@ -2313,44 +2321,47 @@
 	if (status != 0)
 		goto rx_qs_destroy;
 
-	if (be_physfn(adapter)) {
-		status = be_vf_eth_addr_config(adapter);
-		if (status)
-			goto mcc_q_destroy;
-	}
-
 	adapter->link_speed = -1;
 
 	return 0;
 
-mcc_q_destroy:
-	if (be_physfn(adapter))
-		be_vf_eth_addr_rem(adapter);
 	be_mcc_queues_destroy(adapter);
 rx_qs_destroy:
 	be_rx_queues_destroy(adapter);
 tx_qs_destroy:
 	be_tx_queues_destroy(adapter);
 if_destroy:
-	for (vf = 0; vf < num_vfs; vf++)
-		if (adapter->vf_cfg[vf].vf_if_handle)
-			be_cmd_if_destroy(adapter,
-					adapter->vf_cfg[vf].vf_if_handle);
-	be_cmd_if_destroy(adapter, adapter->if_handle);
+	if (be_physfn(adapter) && adapter->sriov_enabled)
+		for (vf = 0; vf < num_vfs; vf++)
+			if (adapter->vf_cfg[vf].vf_if_handle)
+				be_cmd_if_destroy(adapter,
+					adapter->vf_cfg[vf].vf_if_handle,
+					vf + 1);
+	be_cmd_if_destroy(adapter, adapter->if_handle, 0);
 do_none:
 	return status;
 }
 
 static int be_clear(struct be_adapter *adapter)
 {
-	if (be_physfn(adapter))
+	int vf;
+
+	if (be_physfn(adapter) && adapter->sriov_enabled)
 		be_vf_eth_addr_rem(adapter);
 
 	be_mcc_queues_destroy(adapter);
 	be_rx_queues_destroy(adapter);
 	be_tx_queues_destroy(adapter);
+	adapter->eq_next_idx = 0;
 
-	be_cmd_if_destroy(adapter, adapter->if_handle);
+	if (be_physfn(adapter) && adapter->sriov_enabled)
+		for (vf = 0; vf < num_vfs; vf++)
+			if (adapter->vf_cfg[vf].vf_if_handle)
+				be_cmd_if_destroy(adapter,
+					adapter->vf_cfg[vf].vf_if_handle,
+					vf + 1);
+
+	be_cmd_if_destroy(adapter, adapter->if_handle,  0);
 
 	/* tell fw we're done with firing cmds */
 	be_cmd_fw_clean(adapter);
@@ -2453,8 +2464,8 @@
 			continue;
 		if ((pflashcomp[i].optype == IMG_TYPE_REDBOOT) &&
 			(!be_flash_redboot(adapter, fw->data,
-			 pflashcomp[i].offset, pflashcomp[i].size,
-			 filehdr_size)))
+			pflashcomp[i].offset, pflashcomp[i].size, filehdr_size +
+			(num_of_images * sizeof(struct image_hdr)))))
 			continue;
 		p = fw->data;
 		p += filehdr_size + pflashcomp[i].offset
@@ -2528,8 +2539,8 @@
 	dev_info(&adapter->pdev->dev, "Flashing firmware file %s\n", fw_file);
 
 	flash_cmd.size = sizeof(struct be_cmd_write_flashrom) + 32*1024;
-	flash_cmd.va = pci_alloc_consistent(adapter->pdev, flash_cmd.size,
-					&flash_cmd.dma);
+	flash_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, flash_cmd.size,
+					  &flash_cmd.dma, GFP_KERNEL);
 	if (!flash_cmd.va) {
 		status = -ENOMEM;
 		dev_err(&adapter->pdev->dev,
@@ -2558,8 +2569,8 @@
 		status = -1;
 	}
 
-	pci_free_consistent(adapter->pdev, flash_cmd.size, flash_cmd.va,
-				flash_cmd.dma);
+	dma_free_coherent(&adapter->pdev->dev, flash_cmd.size, flash_cmd.va,
+			  flash_cmd.dma);
 	if (status) {
 		dev_err(&adapter->pdev->dev, "Firmware load error\n");
 		goto fw_exit;
@@ -2700,13 +2711,13 @@
 	be_unmap_pci_bars(adapter);
 
 	if (mem->va)
-		pci_free_consistent(adapter->pdev, mem->size,
-			mem->va, mem->dma);
+		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
+				  mem->dma);
 
 	mem = &adapter->mc_cmd_mem;
 	if (mem->va)
-		pci_free_consistent(adapter->pdev, mem->size,
-			mem->va, mem->dma);
+		dma_free_coherent(&adapter->pdev->dev, mem->size, mem->va,
+				  mem->dma);
 }
 
 static int be_ctrl_init(struct be_adapter *adapter)
@@ -2721,8 +2732,10 @@
 		goto done;
 
 	mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
-	mbox_mem_alloc->va = pci_alloc_consistent(adapter->pdev,
-				mbox_mem_alloc->size, &mbox_mem_alloc->dma);
+	mbox_mem_alloc->va = dma_alloc_coherent(&adapter->pdev->dev,
+						mbox_mem_alloc->size,
+						&mbox_mem_alloc->dma,
+						GFP_KERNEL);
 	if (!mbox_mem_alloc->va) {
 		status = -ENOMEM;
 		goto unmap_pci_bars;
@@ -2734,8 +2747,9 @@
 	memset(mbox_mem_align->va, 0, sizeof(struct be_mcc_mailbox));
 
 	mc_cmd_mem->size = sizeof(struct be_cmd_req_mcast_mac_config);
-	mc_cmd_mem->va = pci_alloc_consistent(adapter->pdev, mc_cmd_mem->size,
-			&mc_cmd_mem->dma);
+	mc_cmd_mem->va = dma_alloc_coherent(&adapter->pdev->dev,
+					    mc_cmd_mem->size, &mc_cmd_mem->dma,
+					    GFP_KERNEL);
 	if (mc_cmd_mem->va == NULL) {
 		status = -ENOMEM;
 		goto free_mbox;
@@ -2751,8 +2765,8 @@
 	return 0;
 
 free_mbox:
-	pci_free_consistent(adapter->pdev, mbox_mem_alloc->size,
-		mbox_mem_alloc->va, mbox_mem_alloc->dma);
+	dma_free_coherent(&adapter->pdev->dev, mbox_mem_alloc->size,
+			  mbox_mem_alloc->va, mbox_mem_alloc->dma);
 
 unmap_pci_bars:
 	be_unmap_pci_bars(adapter);
@@ -2766,8 +2780,8 @@
 	struct be_dma_mem *cmd = &adapter->stats_cmd;
 
 	if (cmd->va)
-		pci_free_consistent(adapter->pdev, cmd->size,
-			cmd->va, cmd->dma);
+		dma_free_coherent(&adapter->pdev->dev, cmd->size,
+				  cmd->va, cmd->dma);
 }
 
 static int be_stats_init(struct be_adapter *adapter)
@@ -2775,7 +2789,8 @@
 	struct be_dma_mem *cmd = &adapter->stats_cmd;
 
 	cmd->size = sizeof(struct be_cmd_req_get_stats);
-	cmd->va = pci_alloc_consistent(adapter->pdev, cmd->size, &cmd->dma);
+	cmd->va = dma_alloc_coherent(&adapter->pdev->dev, cmd->size, &cmd->dma,
+				     GFP_KERNEL);
 	if (cmd->va == NULL)
 		return -1;
 	memset(cmd->va, 0, cmd->size);
@@ -2845,6 +2860,11 @@
 	else
 		adapter->max_vlans = BE_NUM_VLANS_SUPPORTED;
 
+	status = be_cmd_get_cntl_attributes(adapter);
+	if (status)
+		return status;
+
+	be_cmd_check_native_mode(adapter);
 	return 0;
 }
 
@@ -2886,6 +2906,54 @@
 	return 0;
 }
 
+static int lancer_wait_ready(struct be_adapter *adapter)
+{
+#define SLIPORT_READY_TIMEOUT 500
+	u32 sliport_status;
+	int status = 0, i;
+
+	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
+		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
+			break;
+
+		msleep(20);
+	}
+
+	if (i == SLIPORT_READY_TIMEOUT)
+		status = -1;
+
+	return status;
+}
+
+static int lancer_test_and_set_rdy_state(struct be_adapter *adapter)
+{
+	int status;
+	u32 sliport_status, err, reset_needed;
+	status = lancer_wait_ready(adapter);
+	if (!status) {
+		sliport_status = ioread32(adapter->db + SLIPORT_STATUS_OFFSET);
+		err = sliport_status & SLIPORT_STATUS_ERR_MASK;
+		reset_needed = sliport_status & SLIPORT_STATUS_RN_MASK;
+		if (err && reset_needed) {
+			iowrite32(SLI_PORT_CONTROL_IP_MASK,
+					adapter->db + SLIPORT_CONTROL_OFFSET);
+
+			/* check adapter has corrected the error */
+			status = lancer_wait_ready(adapter);
+			sliport_status = ioread32(adapter->db +
+							SLIPORT_STATUS_OFFSET);
+			sliport_status &= (SLIPORT_STATUS_ERR_MASK |
+						SLIPORT_STATUS_RN_MASK);
+			if (status || sliport_status)
+				status = -1;
+		} else if (err || reset_needed) {
+			status = -1;
+		}
+	}
+	return status;
+}
+
 static int __devinit be_probe(struct pci_dev *pdev,
 			const struct pci_device_id *pdev_id)
 {
@@ -2918,11 +2986,11 @@
 	adapter->netdev = netdev;
 	SET_NETDEV_DEV(netdev, &pdev->dev);
 
-	status = pci_set_dma_mask(pdev, DMA_BIT_MASK(64));
+	status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
 	if (!status) {
 		netdev->features |= NETIF_F_HIGHDMA;
 	} else {
-		status = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		status = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 		if (status) {
 			dev_err(&pdev->dev, "Could not set PCI DMA Mask\n");
 			goto free_netdev;
@@ -2935,6 +3003,14 @@
 	if (status)
 		goto free_netdev;
 
+	if (lancer_chip(adapter)) {
+		status = lancer_test_and_set_rdy_state(adapter);
+		if (status) {
+			dev_err(&pdev->dev, "Adapter in non recoverable error\n");
+			goto free_netdev;
+		}
+	}
+
 	/* sync up with fw's ready state */
 	if (be_physfn(adapter)) {
 		status = be_cmd_POST(adapter);
@@ -2947,11 +3023,9 @@
 	if (status)
 		goto ctrl_clean;
 
-	if (be_physfn(adapter)) {
-		status = be_cmd_reset_function(adapter);
-		if (status)
-			goto ctrl_clean;
-	}
+	status = be_cmd_reset_function(adapter);
+	if (status)
+		goto ctrl_clean;
 
 	status = be_stats_init(adapter);
 	if (status)
@@ -2975,10 +3049,18 @@
 		goto unsetup;
 	netif_carrier_off(netdev);
 
+	if (be_physfn(adapter) && adapter->sriov_enabled) {
+		status = be_vf_eth_addr_config(adapter);
+		if (status)
+			goto unreg_netdev;
+	}
+
 	dev_info(&pdev->dev, "%s port %d\n", nic_name(pdev), adapter->port_num);
 	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
 	return 0;
 
+unreg_netdev:
+	unregister_netdev(netdev);
 unsetup:
 	be_clear(adapter);
 msix_disable:
@@ -3005,6 +3087,7 @@
 	struct be_adapter *adapter = pci_get_drvdata(pdev);
 	struct net_device *netdev =  adapter->netdev;
 
+	cancel_delayed_work_sync(&adapter->work);
 	if (adapter->wol)
 		be_setup_wol(adapter, true);
 
@@ -3017,6 +3100,7 @@
 	be_cmd_get_flow_control(adapter, &adapter->tx_fc, &adapter->rx_fc);
 	be_clear(adapter);
 
+	be_msix_disable(adapter);
 	pci_save_state(pdev);
 	pci_disable_device(pdev);
 	pci_set_power_state(pdev, pci_choose_state(pdev, state));
@@ -3038,6 +3122,7 @@
 	pci_set_power_state(pdev, 0);
 	pci_restore_state(pdev);
 
+	be_msix_enable(adapter);
 	/* tell fw we're ready to fire cmds */
 	status = be_cmd_fw_init(adapter);
 	if (status)
@@ -3053,6 +3138,8 @@
 
 	if (adapter->wol)
 		be_setup_wol(adapter, false);
+
+	schedule_delayed_work(&adapter->work, msecs_to_jiffies(100));
 	return 0;
 }
 
@@ -3062,9 +3149,14 @@
 static void be_shutdown(struct pci_dev *pdev)
 {
 	struct be_adapter *adapter = pci_get_drvdata(pdev);
-	struct net_device *netdev =  adapter->netdev;
 
-	netif_device_detach(netdev);
+	if (!adapter)
+		return;
+
+	if (netif_running(adapter->netdev))
+		cancel_delayed_work_sync(&adapter->work);
+
+	netif_device_detach(adapter->netdev);
 
 	be_cmd_reset_function(adapter);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bfin_mac.c linux-libre-2.6.39-gnu/drivers/net/bfin_mac.c
--- linux-libre-2.6.38-gnu/drivers/net/bfin_mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bfin_mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -1237,8 +1237,17 @@
 
 	if (phydev->interface == PHY_INTERFACE_MODE_RMII) {
 		opmode |= RMII; /* For Now only 100MBit are supported */
-#if (defined(CONFIG_BF537) || defined(CONFIG_BF536)) && CONFIG_BF_REV_0_2
-		opmode |= TE;
+#if defined(CONFIG_BF537) || defined(CONFIG_BF536)
+		if (__SILICON_REVISION__ < 3) {
+			/*
+			 * This isn't publicly documented (fun times!), but in
+			 * silicon <=0.2, the RX and TX pins are clocked together.
+			 * So in order to recv, we must enable the transmit side
+			 * as well.  This will cause a spurious TX interrupt too,
+			 * but we can easily consume that.
+			 */
+			opmode |= TE;
+		}
 #endif
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bfa_ioc.c linux-libre-2.6.39-gnu/drivers/net/bna/bfa_ioc.c
--- linux-libre-2.6.38-gnu/drivers/net/bna/bfa_ioc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bfa_ioc.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,6 +38,8 @@
 #define bfa_ioc_map_port(__ioc) ((__ioc)->ioc_hwif->ioc_map_port(__ioc))
 #define bfa_ioc_notify_fail(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_notify_fail(__ioc))
+#define bfa_ioc_sync_start(__ioc)               \
+			((__ioc)->ioc_hwif->ioc_sync_start(__ioc))
 #define bfa_ioc_sync_join(__ioc)			\
 			((__ioc)->ioc_hwif->ioc_sync_join(__ioc))
 #define bfa_ioc_sync_leave(__ioc)			\
@@ -602,7 +604,7 @@
 	switch (event) {
 	case IOCPF_E_SEMLOCKED:
 		if (bfa_ioc_firmware_lock(ioc)) {
-			if (bfa_ioc_sync_complete(ioc)) {
+			if (bfa_ioc_sync_start(ioc)) {
 				iocpf->retry_count = 0;
 				bfa_ioc_sync_join(ioc);
 				bfa_fsm_set_state(iocpf, bfa_iocpf_sm_hwinit);
@@ -1314,7 +1316,7 @@
  * execution context (driver/bios) must match.
  */
 static bool
-bfa_ioc_fwver_valid(struct bfa_ioc *ioc)
+bfa_ioc_fwver_valid(struct bfa_ioc *ioc, u32 boot_env)
 {
 	struct bfi_ioc_image_hdr fwhdr, *drv_fwhdr;
 
@@ -1325,7 +1327,7 @@
 	if (fwhdr.signature != drv_fwhdr->signature)
 		return false;
 
-	if (fwhdr.exec != drv_fwhdr->exec)
+	if (swab32(fwhdr.param) != boot_env)
 		return false;
 
 	return bfa_nw_ioc_fwver_cmp(ioc, &fwhdr);
@@ -1352,9 +1354,12 @@
 {
 	enum bfi_ioc_state ioc_fwstate;
 	bool fwvalid;
+	u32 boot_env;
 
 	ioc_fwstate = readl(ioc->ioc_regs.ioc_fwstate);
 
+	boot_env = BFI_BOOT_LOADER_OS;
+
 	if (force)
 		ioc_fwstate = BFI_IOC_UNINIT;
 
@@ -1362,10 +1367,10 @@
 	 * check if firmware is valid
 	 */
 	fwvalid = (ioc_fwstate == BFI_IOC_UNINIT) ?
-		false : bfa_ioc_fwver_valid(ioc);
+		false : bfa_ioc_fwver_valid(ioc, boot_env);
 
 	if (!fwvalid) {
-		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+		bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
 		return;
 	}
 
@@ -1396,7 +1401,7 @@
 	/**
 	 * Initialize the h/w for any other states.
 	 */
-	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, ioc->pcidev.device_id);
+	bfa_ioc_boot(ioc, BFI_BOOT_TYPE_NORMAL, boot_env);
 }
 
 void
@@ -1506,7 +1511,7 @@
  */
 static void
 bfa_ioc_download_fw(struct bfa_ioc *ioc, u32 boot_type,
-		    u32 boot_param)
+		    u32 boot_env)
 {
 	u32 *fwimg;
 	u32 pgnum, pgoff;
@@ -1558,10 +1563,10 @@
 	/*
 	 * Set boot type and boot param at the end.
 	*/
-	writel((swab32(swab32(boot_type))), ((ioc->ioc_regs.smem_page_start)
+	writel(boot_type, ((ioc->ioc_regs.smem_page_start)
 			+ (BFI_BOOT_TYPE_OFF)));
-	writel((swab32(swab32(boot_param))), ((ioc->ioc_regs.smem_page_start)
-			+ (BFI_BOOT_PARAM_OFF)));
+	writel(boot_env, ((ioc->ioc_regs.smem_page_start)
+			+ (BFI_BOOT_LOADER_OFF)));
 }
 
 static void
@@ -1721,7 +1726,7 @@
  * as the entry vector.
  */
 static void
-bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_param)
+bfa_ioc_boot(struct bfa_ioc *ioc, u32 boot_type, u32 boot_env)
 {
 	void __iomem *rb;
 
@@ -1734,7 +1739,7 @@
 	 * Initialize IOC state of all functions on a chip reset.
 	 */
 	rb = ioc->pcidev.pci_bar_kva;
-	if (boot_param == BFI_BOOT_TYPE_MEMTEST) {
+	if (boot_type == BFI_BOOT_TYPE_MEMTEST) {
 		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC0_STATE_REG));
 		writel(BFI_IOC_MEMTEST, (rb + BFA_IOC1_STATE_REG));
 	} else {
@@ -1743,7 +1748,7 @@
 	}
 
 	bfa_ioc_msgflush(ioc);
-	bfa_ioc_download_fw(ioc, boot_type, boot_param);
+	bfa_ioc_download_fw(ioc, boot_type, boot_env);
 
 	/**
 	 * Enable interrupts just before starting LPU
@@ -2219,13 +2224,9 @@
 static void
 bfa_ioc_recover(struct bfa_ioc *ioc)
 {
-	u16 bdf;
-
-	bdf = (ioc->pcidev.pci_slot << 8 | ioc->pcidev.pci_func << 3 |
-					ioc->pcidev.device_id);
-
-	pr_crit("Firmware heartbeat failure at %d", bdf);
-	BUG_ON(1);
+	pr_crit("Heart Beat of IOC has failed\n");
+	bfa_ioc_stats(ioc, ioc_hbfails);
+	bfa_fsm_send_event(ioc, IOC_E_HBFAIL);
 }
 
 static void
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bfa_ioc_ct.c linux-libre-2.6.39-gnu/drivers/net/bna/bfa_ioc_ct.c
--- linux-libre-2.6.38-gnu/drivers/net/bna/bfa_ioc_ct.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bfa_ioc_ct.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,6 +41,7 @@
 static void bfa_ioc_ct_isr_mode_set(struct bfa_ioc *ioc, bool msix);
 static void bfa_ioc_ct_notify_fail(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_ownership_reset(struct bfa_ioc *ioc);
+static bool bfa_ioc_ct_sync_start(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_join(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_leave(struct bfa_ioc *ioc);
 static void bfa_ioc_ct_sync_ack(struct bfa_ioc *ioc);
@@ -63,6 +64,7 @@
 	nw_hwif_ct.ioc_isr_mode_set = bfa_ioc_ct_isr_mode_set;
 	nw_hwif_ct.ioc_notify_fail = bfa_ioc_ct_notify_fail;
 	nw_hwif_ct.ioc_ownership_reset = bfa_ioc_ct_ownership_reset;
+	nw_hwif_ct.ioc_sync_start = bfa_ioc_ct_sync_start;
 	nw_hwif_ct.ioc_sync_join = bfa_ioc_ct_sync_join;
 	nw_hwif_ct.ioc_sync_leave = bfa_ioc_ct_sync_leave;
 	nw_hwif_ct.ioc_sync_ack = bfa_ioc_ct_sync_ack;
@@ -345,6 +347,32 @@
 /**
  * Synchronized IOC failure processing routines
  */
+static bool
+bfa_ioc_ct_sync_start(struct bfa_ioc *ioc)
+{
+	u32 r32 = readl(ioc->ioc_regs.ioc_fail_sync);
+	u32 sync_reqd = bfa_ioc_ct_get_sync_reqd(r32);
+
+	/*
+	 * Driver load time.  If the sync required bit for this PCI fn
+	 * is set, it is due to an unclean exit by the driver for this
+	 * PCI fn in the previous incarnation. Whoever comes here first
+	 * should clean it up, no matter which PCI fn.
+	 */
+
+	if (sync_reqd & bfa_ioc_ct_sync_pos(ioc)) {
+		writel(0, ioc->ioc_regs.ioc_fail_sync);
+		writel(1, ioc->ioc_regs.ioc_usage_reg);
+		writel(BFI_IOC_UNINIT, ioc->ioc_regs.ioc_fwstate);
+		writel(BFI_IOC_UNINIT, ioc->ioc_regs.alt_ioc_fwstate);
+		return true;
+	}
+
+	return bfa_ioc_ct_sync_complete(ioc);
+}
+/**
+ * Synchronized IOC failure processing routines
+ */
 static void
 bfa_ioc_ct_sync_join(struct bfa_ioc *ioc)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bfa_ioc.h linux-libre-2.6.39-gnu/drivers/net/bna/bfa_ioc.h
--- linux-libre-2.6.38-gnu/drivers/net/bna/bfa_ioc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bfa_ioc.h	2011-05-19 00:06:34.000000000 -0400
@@ -194,6 +194,7 @@
 					bool msix);
 	void		(*ioc_notify_fail)	(struct bfa_ioc *ioc);
 	void		(*ioc_ownership_reset)	(struct bfa_ioc *ioc);
+	bool		(*ioc_sync_start)       (struct bfa_ioc *ioc);
 	void		(*ioc_sync_join)	(struct bfa_ioc *ioc);
 	void		(*ioc_sync_leave)	(struct bfa_ioc *ioc);
 	void		(*ioc_sync_ack)		(struct bfa_ioc *ioc);
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bfi.h linux-libre-2.6.39-gnu/drivers/net/bna/bfi.h
--- linux-libre-2.6.38-gnu/drivers/net/bna/bfi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bfi.h	2011-05-19 00:06:34.000000000 -0400
@@ -184,12 +184,14 @@
 #define BFI_IOC_MSGLEN_MAX	32	/* 32 bytes */
 
 #define BFI_BOOT_TYPE_OFF		8
-#define BFI_BOOT_PARAM_OFF		12
+#define BFI_BOOT_LOADER_OFF		12
 
-#define BFI_BOOT_TYPE_NORMAL 		0	/* param is device id */
+#define BFI_BOOT_TYPE_NORMAL 		0
 #define	BFI_BOOT_TYPE_FLASH		1
 #define	BFI_BOOT_TYPE_MEMTEST		2
 
+#define BFI_BOOT_LOADER_OS		0
+
 #define BFI_BOOT_MEMTEST_RES_ADDR   0x900
 #define BFI_BOOT_MEMTEST_RES_SIG    0xA0A1A2A3
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bnad.c linux-libre-2.6.39-gnu/drivers/net/bna/bnad.c
--- linux-libre-2.6.38-gnu/drivers/net/bna/bnad.c	2012-03-24 01:06:29.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bnad.c	2012-03-24 03:30:02.000000000 -0400
@@ -126,22 +126,22 @@
 		}
 		unmap_array[unmap_cons].skb = NULL;
 
-		pci_unmap_single(bnad->pcidev,
-				 pci_unmap_addr(&unmap_array[unmap_cons],
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
 						dma_addr), skb_headlen(skb),
-						PCI_DMA_TODEVICE);
+						DMA_TO_DEVICE);
 
-		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+		dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
 		if (++unmap_cons >= unmap_q->q_depth)
 			break;
 
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-			pci_unmap_page(bnad->pcidev,
-				       pci_unmap_addr(&unmap_array[unmap_cons],
+			dma_unmap_page(&bnad->pcidev->dev,
+				       dma_unmap_addr(&unmap_array[unmap_cons],
 						      dma_addr),
 				       skb_shinfo(skb)->frags[i].size,
-				       PCI_DMA_TODEVICE);
-			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+				       DMA_TO_DEVICE);
+			dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
 					   0);
 			if (++unmap_cons >= unmap_q->q_depth)
 				break;
@@ -199,23 +199,23 @@
 		sent_bytes += skb->len;
 		wis -= BNA_TXQ_WI_NEEDED(1 + skb_shinfo(skb)->nr_frags);
 
-		pci_unmap_single(bnad->pcidev,
-				 pci_unmap_addr(&unmap_array[unmap_cons],
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
 						dma_addr), skb_headlen(skb),
-				 PCI_DMA_TODEVICE);
-		pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
+				 DMA_TO_DEVICE);
+		dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr, 0);
 		BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
 
 		prefetch(&unmap_array[unmap_cons + 1]);
 		for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
 			prefetch(&unmap_array[unmap_cons + 1]);
 
-			pci_unmap_page(bnad->pcidev,
-				       pci_unmap_addr(&unmap_array[unmap_cons],
+			dma_unmap_page(&bnad->pcidev->dev,
+				       dma_unmap_addr(&unmap_array[unmap_cons],
 						      dma_addr),
 				       skb_shinfo(skb)->frags[i].size,
-				       PCI_DMA_TODEVICE);
-			pci_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
+				       DMA_TO_DEVICE);
+			dma_unmap_addr_set(&unmap_array[unmap_cons], dma_addr,
 					   0);
 			BNA_QE_INDX_ADD(unmap_cons, 1, unmap_q->q_depth);
 		}
@@ -340,19 +340,22 @@
 bnad_free_all_rxbufs(struct bnad *bnad, struct bna_rcb *rcb)
 {
 	struct bnad_unmap_q *unmap_q;
+	struct bnad_skb_unmap *unmap_array;
 	struct sk_buff *skb;
 	int unmap_cons;
 
 	unmap_q = rcb->unmap_q;
+	unmap_array = unmap_q->unmap_array;
 	for (unmap_cons = 0; unmap_cons < unmap_q->q_depth; unmap_cons++) {
-		skb = unmap_q->unmap_array[unmap_cons].skb;
+		skb = unmap_array[unmap_cons].skb;
 		if (!skb)
 			continue;
-		unmap_q->unmap_array[unmap_cons].skb = NULL;
-		pci_unmap_single(bnad->pcidev, pci_unmap_addr(&unmap_q->
-					unmap_array[unmap_cons],
-					dma_addr), rcb->rxq->buffer_size,
-					PCI_DMA_FROMDEVICE);
+		unmap_array[unmap_cons].skb = NULL;
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
+						dma_addr),
+				 rcb->rxq->buffer_size,
+				 DMA_FROM_DEVICE);
 		dev_kfree_skb(skb);
 	}
 	bnad_reset_rcb(bnad, rcb);
@@ -391,9 +394,10 @@
 		skb->dev = bnad->netdev;
 		skb_reserve(skb, NET_IP_ALIGN);
 		unmap_array[unmap_prod].skb = skb;
-		dma_addr = pci_map_single(bnad->pcidev, skb->data,
-			rcb->rxq->buffer_size, PCI_DMA_FROMDEVICE);
-		pci_unmap_addr_set(&unmap_array[unmap_prod], dma_addr,
+		dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
+					  rcb->rxq->buffer_size,
+					  DMA_FROM_DEVICE);
+		dma_unmap_addr_set(&unmap_array[unmap_prod], dma_addr,
 				   dma_addr);
 		BNA_SET_DMA_ADDR(dma_addr, &rxent->host_addr);
 		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
@@ -434,8 +438,9 @@
 	struct bna_rcb *rcb = NULL;
 	unsigned int wi_range, packets = 0, wis = 0;
 	struct bnad_unmap_q *unmap_q;
+	struct bnad_skb_unmap *unmap_array;
 	struct sk_buff *skb;
-	u32 flags;
+	u32 flags, unmap_cons;
 	u32 qid0 = ccb->rcb[0]->rxq->rxq_id;
 	struct bna_pkt_rate *pkt_rt = &ccb->pkt_rate;
 
@@ -456,17 +461,17 @@
 			rcb = ccb->rcb[1];
 
 		unmap_q = rcb->unmap_q;
+		unmap_array = unmap_q->unmap_array;
+		unmap_cons = unmap_q->consumer_index;
 
-		skb = unmap_q->unmap_array[unmap_q->consumer_index].skb;
+		skb = unmap_array[unmap_cons].skb;
 		BUG_ON(!(skb));
-		unmap_q->unmap_array[unmap_q->consumer_index].skb = NULL;
-		pci_unmap_single(bnad->pcidev,
-				 pci_unmap_addr(&unmap_q->
-						unmap_array[unmap_q->
-							    consumer_index],
+		unmap_array[unmap_cons].skb = NULL;
+		dma_unmap_single(&bnad->pcidev->dev,
+				 dma_unmap_addr(&unmap_array[unmap_cons],
 						dma_addr),
-						rcb->rxq->buffer_size,
-						PCI_DMA_FROMDEVICE);
+				 rcb->rxq->buffer_size,
+				 DMA_FROM_DEVICE);
 		BNA_QE_INDX_ADD(unmap_q->consumer_index, 1, unmap_q->q_depth);
 
 		/* Should be more efficient ? Performance ? */
@@ -1015,9 +1020,9 @@
 			if (mem_info->mem_type == BNA_MEM_T_DMA) {
 				BNA_GET_DMA_ADDR(&(mem_info->mdl[i].dma),
 						dma_pa);
-				pci_free_consistent(bnad->pcidev,
-						mem_info->mdl[i].len,
-						mem_info->mdl[i].kva, dma_pa);
+				dma_free_coherent(&bnad->pcidev->dev,
+						  mem_info->mdl[i].len,
+						  mem_info->mdl[i].kva, dma_pa);
 			} else
 				kfree(mem_info->mdl[i].kva);
 		}
@@ -1047,8 +1052,9 @@
 		for (i = 0; i < mem_info->num; i++) {
 			mem_info->mdl[i].len = mem_info->len;
 			mem_info->mdl[i].kva =
-				pci_alloc_consistent(bnad->pcidev,
-						mem_info->len, &dma_pa);
+				dma_alloc_coherent(&bnad->pcidev->dev,
+						mem_info->len, &dma_pa,
+						GFP_KERNEL);
 
 			if (mem_info->mdl[i].kva == NULL)
 				goto err_return;
@@ -1831,7 +1837,6 @@
 	/* Initialize the Rx event handlers */
 	rx_cbfn.rcb_setup_cbfn = bnad_cb_rcb_setup;
 	rx_cbfn.rcb_destroy_cbfn = bnad_cb_rcb_destroy;
-	rx_cbfn.rcb_destroy_cbfn = NULL;
 	rx_cbfn.ccb_setup_cbfn = bnad_cb_ccb_setup;
 	rx_cbfn.ccb_destroy_cbfn = bnad_cb_ccb_destroy;
 	rx_cbfn.rx_cleanup_cbfn = bnad_cb_rx_cleanup;
@@ -2600,9 +2605,9 @@
 	unmap_q->unmap_array[unmap_prod].skb = skb;
 	BUG_ON(!(skb_headlen(skb) <= BFI_TX_MAX_DATA_PER_VECTOR));
 	txqent->vector[vect_id].length = htons(skb_headlen(skb));
-	dma_addr = pci_map_single(bnad->pcidev, skb->data, skb_headlen(skb),
-		PCI_DMA_TODEVICE);
-	pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+	dma_addr = dma_map_single(&bnad->pcidev->dev, skb->data,
+				  skb_headlen(skb), DMA_TO_DEVICE);
+	dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
 			   dma_addr);
 
 	BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
@@ -2630,11 +2635,9 @@
 
 		BUG_ON(!(size <= BFI_TX_MAX_DATA_PER_VECTOR));
 		txqent->vector[vect_id].length = htons(size);
-		dma_addr =
-			pci_map_page(bnad->pcidev, frag->page,
-				     frag->page_offset, size,
-				     PCI_DMA_TODEVICE);
-		pci_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
+		dma_addr = dma_map_page(&bnad->pcidev->dev, frag->page,
+					frag->page_offset, size, DMA_TO_DEVICE);
+		dma_unmap_addr_set(&unmap_q->unmap_array[unmap_prod], dma_addr,
 				   dma_addr);
 		BNA_SET_DMA_ADDR(dma_addr, &txqent->vector[vect_id].host_addr);
 		BNA_QE_INDX_ADD(unmap_prod, 1, unmap_q->q_depth);
@@ -3022,14 +3025,14 @@
 	err = pci_request_regions(pdev, BNAD_NAME);
 	if (err)
 		goto disable_device;
-	if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) &&
-	    !pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64))) {
+	if (!dma_set_mask(&pdev->dev, DMA_BIT_MASK(64)) &&
+	    !dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64))) {
 		*using_dac = 1;
 	} else {
-		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		err = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
 		if (err) {
-			err = pci_set_consistent_dma_mask(pdev,
-						DMA_BIT_MASK(32));
+			err = dma_set_coherent_mask(&pdev->dev,
+						    DMA_BIT_MASK(32));
 			if (err)
 				goto release_regions;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bnad.h linux-libre-2.6.39-gnu/drivers/net/bna/bnad.h
--- linux-libre-2.6.38-gnu/drivers/net/bna/bnad.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bnad.h	2011-05-19 00:06:34.000000000 -0400
@@ -181,7 +181,7 @@
 /* Unmap queues for Tx / Rx cleanup */
 struct bnad_skb_unmap {
 	struct sk_buff		*skb;
-	DECLARE_PCI_UNMAP_ADDR(dma_addr)
+	DEFINE_DMA_UNMAP_ADDR(dma_addr);
 };
 
 struct bnad_unmap_q {
diff -druN linux-libre-2.6.38-gnu/drivers/net/bna/bna_hw.h linux-libre-2.6.39-gnu/drivers/net/bna/bna_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/bna/bna_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bna/bna_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -897,7 +897,7 @@
  * Catapult RSS Table Base Offset Address
  *
  * Exists in RAD memory space.
- * Each entry is 352 bits, but alligned on
+ * Each entry is 352 bits, but aligned on
  * 64 byte (512 bit) boundary. Accessed
  * 4 byte words, the whole entry can be
  * broken into 11 word accesses.
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2.c linux-libre-2.6.39-gnu/drivers/net/bnx2.c
--- linux-libre-2.6.38-gnu/drivers/net/bnx2.c	2012-03-24 01:06:46.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2.c	2012-03-24 03:30:12.000000000 -0400
@@ -1,6 +1,6 @@
 /* bnx2.c: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004-2010 Broadcom Corporation
+ * Copyright (c) 2004-2011 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
@@ -56,8 +56,8 @@
 #include "bnx2_fw.h"
 
 #define DRV_MODULE_NAME		"bnx2"
-#define DRV_MODULE_VERSION	"2.0.21"
-#define DRV_MODULE_RELDATE	"Dec 23, 2010"
+#define DRV_MODULE_VERSION	"2.1.6"
+#define DRV_MODULE_RELDATE	"Mar 7, 2011"
 #define FW_MIPS_FILE_06		"/*(DEBLOBBED)*/"
 #define FW_RV2P_FILE_06		"/*(DEBLOBBED)*/"
 #define FW_MIPS_FILE_09		"/*(DEBLOBBED)*/"
@@ -431,7 +431,8 @@
 	struct cnic_ctl_info info;
 
 	mutex_lock(&bp->cnic_lock);
-	c_ops = bp->cnic_ops;
+	c_ops = rcu_dereference_protected(bp->cnic_ops,
+					  lockdep_is_held(&bp->cnic_lock));
 	if (c_ops) {
 		info.cmd = CNIC_CTL_STOP_CMD;
 		c_ops->cnic_ctl(bp->cnic_data, &info);
@@ -446,7 +447,8 @@
 	struct cnic_ctl_info info;
 
 	mutex_lock(&bp->cnic_lock);
-	c_ops = bp->cnic_ops;
+	c_ops = rcu_dereference_protected(bp->cnic_ops,
+					  lockdep_is_held(&bp->cnic_lock));
 	if (c_ops) {
 		if (!(bp->flags & BNX2_FLAG_USING_MSIX)) {
 			struct bnx2_napi *bnapi = &bp->bnx2_napi[0];
@@ -8311,7 +8313,7 @@
 #endif
 };
 
-static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+static inline void vlan_features_add(struct net_device *dev, u32 flags)
 {
 	dev->vlan_features |= flags;
 }
@@ -8407,6 +8409,8 @@
 
 	unregister_netdev(dev);
 
+	del_timer_sync(&bp->timer);
+
 	if (bp->mips_firmware)
 		release_firmware(bp->mips_firmware);
 	if (bp->rv2p_firmware)
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2.h linux-libre-2.6.39-gnu/drivers/net/bnx2.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /* bnx2.h: Broadcom NX2 network driver.
  *
- * Copyright (c) 2004-2009 Broadcom Corporation
+ * Copyright (c) 2004-2011 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
@@ -6207,6 +6207,8 @@
 
 #define BNX2_CP_SCRATCH					0x001a0000
 
+#define BNX2_FW_MAX_ISCSI_CONN				 0x001a0080
+
 
 /*
  *  mcp_reg definition
@@ -6759,7 +6761,7 @@
 	u32		tx_wake_thresh;
 
 #ifdef BCM_CNIC
-	struct cnic_ops		*cnic_ops;
+	struct cnic_ops	__rcu	*cnic_ops;
 	void			*cnic_data;
 #endif
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_cmn.c linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_cmn.c
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_cmn.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_cmn.c	2011-05-19 00:06:34.000000000 -0400
@@ -232,7 +232,7 @@
 	/* move empty skb from pool to prod and map it */
 	prod_rx_buf->skb = fp->tpa_pool[queue].skb;
 	mapping = dma_map_single(&bp->pdev->dev, fp->tpa_pool[queue].skb->data,
-				 bp->rx_buf_size, DMA_FROM_DEVICE);
+				 fp->rx_buf_size, DMA_FROM_DEVICE);
 	dma_unmap_addr_set(prod_rx_buf, mapping, mapping);
 
 	/* move partial skb from cons to pool (don't unmap yet) */
@@ -367,13 +367,13 @@
 	struct sw_rx_bd *rx_buf = &fp->tpa_pool[queue];
 	struct sk_buff *skb = rx_buf->skb;
 	/* alloc new skb */
-	struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+	struct sk_buff *new_skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 
 	/* Unmap skb in the pool anyway, as we are going to change
 	   pool entry status to BNX2X_TPA_STOP even if new skb allocation
 	   fails. */
 	dma_unmap_single(&bp->pdev->dev, dma_unmap_addr(rx_buf, mapping),
-			 bp->rx_buf_size, DMA_FROM_DEVICE);
+			 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 	if (likely(new_skb)) {
 		/* fix ip xsum and give it to the stack */
@@ -385,10 +385,10 @@
 		prefetch(((char *)(skb)) + L1_CACHE_BYTES);
 
 #ifdef BNX2X_STOP_ON_ERROR
-		if (pad + len > bp->rx_buf_size) {
+		if (pad + len > fp->rx_buf_size) {
 			BNX2X_ERR("skb_put is about to fail...  "
 				  "pad %d  len %d  rx_buf_size %d\n",
-				  pad, len, bp->rx_buf_size);
+				  pad, len, fp->rx_buf_size);
 			bnx2x_panic();
 			return;
 		}
@@ -618,7 +618,7 @@
 			if (likely(bnx2x_alloc_rx_skb(bp, fp, bd_prod) == 0)) {
 				dma_unmap_single(&bp->pdev->dev,
 					dma_unmap_addr(rx_buf, mapping),
-						 bp->rx_buf_size,
+						 fp->rx_buf_size,
 						 DMA_FROM_DEVICE);
 				skb_reserve(skb, pad);
 				skb_put(skb, len);
@@ -858,19 +858,16 @@
 	u16 ring_prod;
 	int i, j;
 
-	bp->rx_buf_size = bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
-		IP_HEADER_ALIGNMENT_PADDING;
-
-	DP(NETIF_MSG_IFUP,
-	   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, bp->rx_buf_size);
-
 	for_each_rx_queue(bp, j) {
 		struct bnx2x_fastpath *fp = &bp->fp[j];
 
+		DP(NETIF_MSG_IFUP,
+		   "mtu %d  rx_buf_size %d\n", bp->dev->mtu, fp->rx_buf_size);
+
 		if (!fp->disable_tpa) {
 			for (i = 0; i < max_agg_queues; i++) {
 				fp->tpa_pool[i].skb =
-				   netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+				   netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 				if (!fp->tpa_pool[i].skb) {
 					BNX2X_ERR("Failed to allocate TPA "
 						  "skb pool for queue[%d] - "
@@ -978,7 +975,7 @@
 
 			dma_unmap_single(&bp->pdev->dev,
 					 dma_unmap_addr(rx_buf, mapping),
-					 bp->rx_buf_size, DMA_FROM_DEVICE);
+					 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 			rx_buf->skb = NULL;
 			dev_kfree_skb(skb);
@@ -1303,6 +1300,31 @@
 	return rc;
 }
 
+static inline void bnx2x_set_rx_buf_size(struct bnx2x *bp)
+{
+	int i;
+
+	for_each_queue(bp, i) {
+		struct bnx2x_fastpath *fp = &bp->fp[i];
+
+		/* Always use a mini-jumbo MTU for the FCoE L2 ring */
+		if (IS_FCOE_IDX(i))
+			/*
+			 * Although there are no IP frames expected to arrive to
+			 * this ring we still want to add an
+			 * IP_HEADER_ALIGNMENT_PADDING to prevent a buffer
+			 * overrun attack.
+			 */
+			fp->rx_buf_size =
+				BNX2X_FCOE_MINI_JUMBO_MTU + ETH_OVREHEAD +
+				BNX2X_RX_ALIGN + IP_HEADER_ALIGNMENT_PADDING;
+		else
+			fp->rx_buf_size =
+				bp->dev->mtu + ETH_OVREHEAD + BNX2X_RX_ALIGN +
+				IP_HEADER_ALIGNMENT_PADDING;
+	}
+}
+
 /* must be called with rtnl_lock */
 int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
 {
@@ -1326,6 +1348,9 @@
 	/* must be called before memory allocation and HW init */
 	bnx2x_ilt_set_info(bp);
 
+	/* Set the receive queues buffer size */
+	bnx2x_set_rx_buf_size(bp);
+
 	if (bnx2x_alloc_mem(bp))
 		return -ENOMEM;
 
@@ -1481,6 +1506,15 @@
 
 	bnx2x_set_eth_mac(bp, 1);
 
+	/* Clear MC configuration */
+	if (CHIP_IS_E1(bp))
+		bnx2x_invalidate_e1_mc_list(bp);
+	else
+		bnx2x_invalidate_e1h_mc_list(bp);
+
+	/* Clear UC lists configuration */
+	bnx2x_invalidate_uc_list(bp);
+
 	if (bp->pending_max) {
 		bnx2x_update_max_mf_config(bp, bp->pending_max);
 		bp->pending_max = 0;
@@ -1489,25 +1523,23 @@
 	if (bp->port.pmf)
 		bnx2x_initial_phy_init(bp, load_mode);
 
+	/* Initialize Rx filtering */
+	bnx2x_set_rx_mode(bp->dev);
+
 	/* Start fast path */
 	switch (load_mode) {
 	case LOAD_NORMAL:
 		/* Tx queue should be only reenabled */
 		netif_tx_wake_all_queues(bp->dev);
 		/* Initialize the receive filter. */
-		bnx2x_set_rx_mode(bp->dev);
 		break;
 
 	case LOAD_OPEN:
 		netif_tx_start_all_queues(bp->dev);
 		smp_mb__after_clear_bit();
-		/* Initialize the receive filter. */
-		bnx2x_set_rx_mode(bp->dev);
 		break;
 
 	case LOAD_DIAG:
-		/* Initialize the receive filter. */
-		bnx2x_set_rx_mode(bp->dev);
 		bp->state = BNX2X_STATE_DIAG;
 		break;
 
@@ -1987,15 +2019,23 @@
 static inline  u8 bnx2x_set_pbd_csum_e2(struct bnx2x *bp, struct sk_buff *skb,
 	u32 *parsing_data, u32 xmit_type)
 {
-	*parsing_data |= ((tcp_hdrlen(skb)/4) <<
-		ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
-		ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
+	*parsing_data |=
+			((((u8 *)skb_transport_header(skb) - skb->data) >> 1) <<
+			ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
+			ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
 
-	*parsing_data |= ((((u8 *)tcp_hdr(skb) - skb->data) / 2) <<
-		ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W_SHIFT) &
-		ETH_TX_PARSE_BD_E2_TCP_HDR_START_OFFSET_W;
+	if (xmit_type & XMIT_CSUM_TCP) {
+		*parsing_data |= ((tcp_hdrlen(skb) / 4) <<
+			ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW_SHIFT) &
+			ETH_TX_PARSE_BD_E2_TCP_HDR_LENGTH_DW;
 
-	return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+		return skb_transport_header(skb) + tcp_hdrlen(skb) - skb->data;
+	} else
+		/* We support checksum offload for TCP and UDP only.
+		 * No need to pass the UDP header length - it's a constant.
+		 */
+		return skb_transport_header(skb) +
+				sizeof(struct udphdr) - skb->data;
 }
 
 /**
@@ -2011,7 +2051,7 @@
 	struct eth_tx_parse_bd_e1x *pbd,
 	u32 xmit_type)
 {
-	u8 hlen = (skb_network_header(skb) - skb->data) / 2;
+	u8 hlen = (skb_network_header(skb) - skb->data) >> 1;
 
 	/* for now NS flag is not used in Linux */
 	pbd->global_data =
@@ -2019,9 +2059,15 @@
 			 ETH_TX_PARSE_BD_E1X_LLC_SNAP_EN_SHIFT));
 
 	pbd->ip_hlen_w = (skb_transport_header(skb) -
-			skb_network_header(skb)) / 2;
+			skb_network_header(skb)) >> 1;
 
-	hlen += pbd->ip_hlen_w + tcp_hdrlen(skb) / 2;
+	hlen += pbd->ip_hlen_w;
+
+	/* We support checksum offload for TCP and UDP only */
+	if (xmit_type & XMIT_CSUM_TCP)
+		hlen += tcp_hdrlen(skb) / 2;
+	else
+		hlen += sizeof(struct udphdr) / 2;
 
 	pbd->total_hlen_w = cpu_to_le16(hlen);
 	hlen = hlen*2;
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_cmn.h linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_cmn.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_cmn.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_cmn.h	2011-05-19 00:06:34.000000000 -0400
@@ -831,11 +831,11 @@
 	struct eth_rx_bd *rx_bd = &fp->rx_desc_ring[index];
 	dma_addr_t mapping;
 
-	skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+	skb = netdev_alloc_skb(bp->dev, fp->rx_buf_size);
 	if (unlikely(skb == NULL))
 		return -ENOMEM;
 
-	mapping = dma_map_single(&bp->pdev->dev, skb->data, bp->rx_buf_size,
+	mapping = dma_map_single(&bp->pdev->dev, skb->data, fp->rx_buf_size,
 				 DMA_FROM_DEVICE);
 	if (unlikely(dma_mapping_error(&bp->pdev->dev, mapping))) {
 		dev_kfree_skb(skb);
@@ -901,7 +901,7 @@
 		if (fp->tpa_state[i] == BNX2X_TPA_START)
 			dma_unmap_single(&bp->pdev->dev,
 					 dma_unmap_addr(rx_buf, mapping),
-					 bp->rx_buf_size, DMA_FROM_DEVICE);
+					 fp->rx_buf_size, DMA_FROM_DEVICE);
 
 		dev_kfree_skb(skb);
 		rx_buf->skb = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_dcb.c linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_dcb.c
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_dcb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_dcb.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,9 @@
 #include <linux/netdevice.h>
 #include <linux/types.h>
 #include <linux/errno.h>
+#ifdef BCM_DCBNL
+#include <linux/dcbnl.h>
+#endif
 
 #include "bnx2x.h"
 #include "bnx2x_cmn.h"
@@ -508,13 +511,75 @@
 	return 0;
 }
 
+
+#ifdef BCM_DCBNL
+static inline
+u8 bnx2x_dcbx_dcbnl_app_up(struct dcbx_app_priority_entry *ent)
+{
+	u8 pri;
+
+	/* Choose the highest priority */
+	for (pri = MAX_PFC_PRIORITIES - 1; pri > 0; pri--)
+		if (ent->pri_bitmap & (1 << pri))
+			break;
+	return pri;
+}
+
+static inline
+u8 bnx2x_dcbx_dcbnl_app_idtype(struct dcbx_app_priority_entry *ent)
+{
+	return ((ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) ==
+		DCBX_APP_SF_PORT) ? DCB_APP_IDTYPE_PORTNUM :
+		DCB_APP_IDTYPE_ETHTYPE;
+}
+
+static inline
+void bnx2x_dcbx_invalidate_local_apps(struct bnx2x *bp)
+{
+	int i;
+	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
+		bp->dcbx_local_feat.app.app_pri_tbl[i].appBitfield &=
+							~DCBX_APP_ENTRY_VALID;
+}
+
+int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall)
+{
+	int i, err = 0;
+
+	for (i = 0; i < DCBX_MAX_APP_PROTOCOL && err == 0; i++) {
+		struct dcbx_app_priority_entry *ent =
+			&bp->dcbx_local_feat.app.app_pri_tbl[i];
+
+		if (ent->appBitfield & DCBX_APP_ENTRY_VALID) {
+			u8 up = bnx2x_dcbx_dcbnl_app_up(ent);
+
+			/* avoid invalid user-priority */
+			if (up) {
+				struct dcb_app app;
+				app.selector = bnx2x_dcbx_dcbnl_app_idtype(ent);
+				app.protocol = ent->app_id;
+				app.priority = delall ? 0 : up;
+				err = dcb_setapp(bp->dev, &app);
+			}
+		}
+	}
+	return err;
+}
+#endif
+
 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state)
 {
 	switch (state) {
 	case BNX2X_DCBX_STATE_NEG_RECEIVED:
 		{
 			DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_NEG_RECEIVED\n");
-
+#ifdef BCM_DCBNL
+			/**
+			 * Delete app tlvs from dcbnl before reading new
+			 * negotiation results
+			 */
+			bnx2x_dcbnl_update_applist(bp, true);
+#endif
 			/* Read neg results if dcbx is in the FW */
 			if (bnx2x_dcbx_read_shmem_neg_results(bp))
 				return;
@@ -526,10 +591,24 @@
 						 bp->dcbx_error);
 
 			if (bp->state != BNX2X_STATE_OPENING_WAIT4_LOAD) {
+#ifdef BCM_DCBNL
+				/**
+				 * Add new app tlvs to dcbnl
+				 */
+				bnx2x_dcbnl_update_applist(bp, false);
+#endif
 				bnx2x_dcbx_stop_hw_tx(bp);
 				return;
 			}
 			/* fall through */
+#ifdef BCM_DCBNL
+			/**
+			 * Invalidate the local app tlvs if they are not added
+			 * to the dcbnl app list to avoid deleting them from
+			 * the list later on
+			 */
+			bnx2x_dcbx_invalidate_local_apps(bp);
+#endif
 		}
 	case BNX2X_DCBX_STATE_TX_PAUSED:
 		DP(NETIF_MSG_LINK, "BNX2X_DCBX_STATE_TX_PAUSED\n");
@@ -1505,8 +1584,7 @@
 	bnx2x_dcbx_print_cos_params(bp,	pfc_fw_cfg);
 }
 /* DCB netlink */
-#ifdef BCM_DCB
-#include <linux/dcbnl.h>
+#ifdef BCM_DCBNL
 
 #define BNX2X_DCBX_CAPS		(DCB_CAP_DCBX_LLD_MANAGED | \
 				DCB_CAP_DCBX_VER_CEE | DCB_CAP_DCBX_STATIC)
@@ -1816,32 +1894,6 @@
 	bp->dcbx_config_params.admin_pfc_enable = (state ? 1 : 0);
 }
 
-static bool bnx2x_app_is_equal(struct dcbx_app_priority_entry *app_ent,
-			       u8 idtype, u16 idval)
-{
-	if (!(app_ent->appBitfield & DCBX_APP_ENTRY_VALID))
-		return false;
-
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-		if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
-			DCBX_APP_SF_ETH_TYPE)
-			return false;
-		break;
-	case DCB_APP_IDTYPE_PORTNUM:
-		if ((app_ent->appBitfield & DCBX_APP_ENTRY_SF_MASK) !=
-			DCBX_APP_SF_PORT)
-			return false;
-		break;
-	default:
-		return false;
-	}
-	if (app_ent->app_id != idval)
-		return false;
-
-	return true;
-}
-
 static void bnx2x_admin_app_set_ent(
 	struct bnx2x_admin_priority_app_table *app_ent,
 	u8 idtype, u16 idval, u8 up)
@@ -1943,30 +1995,6 @@
 	return bnx2x_set_admin_app_up(bp, idtype, idval, up);
 }
 
-static u8 bnx2x_dcbnl_get_app_up(struct net_device *netdev, u8 idtype,
-				 u16 idval)
-{
-	int i;
-	u8 up = 0;
-
-	struct bnx2x *bp = netdev_priv(netdev);
-	DP(NETIF_MSG_LINK, "app_type %d, app_id 0x%x\n", idtype, idval);
-
-	/* iterate over the app entries looking for idtype and idval */
-	for (i = 0; i < DCBX_MAX_APP_PROTOCOL; i++)
-		if (bnx2x_app_is_equal(&bp->dcbx_local_feat.app.app_pri_tbl[i],
-				       idtype, idval))
-			break;
-
-	if (i < DCBX_MAX_APP_PROTOCOL)
-		/* if found return up */
-		up = bp->dcbx_local_feat.app.app_pri_tbl[i].pri_bitmap;
-	else
-		DP(NETIF_MSG_LINK, "app not found\n");
-
-	return up;
-}
-
 static u8 bnx2x_dcbnl_get_dcbx(struct net_device *netdev)
 {
 	struct bnx2x *bp = netdev_priv(netdev);
@@ -2107,7 +2135,6 @@
 	.setnumtcs      = bnx2x_dcbnl_set_numtcs,
 	.getpfcstate    = bnx2x_dcbnl_get_pfc_state,
 	.setpfcstate    = bnx2x_dcbnl_set_pfc_state,
-	.getapp         = bnx2x_dcbnl_get_app_up,
 	.setapp         = bnx2x_dcbnl_set_app_up,
 	.getdcbx        = bnx2x_dcbnl_get_dcbx,
 	.setdcbx        = bnx2x_dcbnl_set_dcbx,
@@ -2115,4 +2142,4 @@
 	.setfeatcfg     = bnx2x_dcbnl_set_featcfg,
 };
 
-#endif /* BCM_DCB */
+#endif /* BCM_DCBNL */
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_dcb.h linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_dcb.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_dcb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_dcb.h	2011-05-19 00:06:34.000000000 -0400
@@ -189,8 +189,9 @@
 void bnx2x_dcbx_set_params(struct bnx2x *bp, u32 state);
 
 /* DCB netlink */
-#ifdef BCM_DCB
+#ifdef BCM_DCBNL
 extern const struct dcbnl_rtnl_ops bnx2x_dcbnl_ops;
-#endif /* BCM_DCB */
+int bnx2x_dcbnl_update_applist(struct bnx2x *bp, bool delall);
+#endif /* BCM_DCBNL */
 
 #endif /* BNX2X_DCB_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_ethtool.c linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -1617,7 +1617,7 @@
 	/* prepare the loopback packet */
 	pkt_size = (((bp->dev->mtu < ETH_MAX_PACKET_SIZE) ?
 		     bp->dev->mtu : ETH_MAX_PACKET_SIZE) + ETH_HLEN);
-	skb = netdev_alloc_skb(bp->dev, bp->rx_buf_size);
+	skb = netdev_alloc_skb(bp->dev, fp_rx->rx_buf_size);
 	if (!skb) {
 		rc = -ENOMEM;
 		goto test_loopback_exit;
@@ -2114,23 +2114,75 @@
 	for (i = 0; i < (data * 2); i++) {
 		if ((i % 2) == 0)
 			bnx2x_set_led(&bp->link_params, &bp->link_vars,
-				      LED_MODE_OPER, SPEED_1000);
+				      LED_MODE_ON, SPEED_1000);
 		else
 			bnx2x_set_led(&bp->link_params, &bp->link_vars,
-				      LED_MODE_OFF, 0);
+				      LED_MODE_FRONT_PANEL_OFF, 0);
 
 		msleep_interruptible(500);
 		if (signal_pending(current))
 			break;
 	}
 
-	if (bp->link_vars.link_up)
-		bnx2x_set_led(&bp->link_params, &bp->link_vars, LED_MODE_OPER,
-			      bp->link_vars.line_speed);
+	bnx2x_set_led(&bp->link_params, &bp->link_vars,
+		      LED_MODE_OPER, bp->link_vars.line_speed);
 
 	return 0;
 }
 
+static int bnx2x_get_rxnfc(struct net_device *dev, struct ethtool_rxnfc *info,
+			   void *rules __always_unused)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+
+	switch (info->cmd) {
+	case ETHTOOL_GRXRINGS:
+		info->data = BNX2X_NUM_ETH_QUEUES(bp);
+		return 0;
+
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static int bnx2x_get_rxfh_indir(struct net_device *dev,
+				struct ethtool_rxfh_indir *indir)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	size_t copy_size =
+		min_t(size_t, indir->size, TSTORM_INDIRECTION_TABLE_SIZE);
+
+	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+		return -EOPNOTSUPP;
+
+	indir->size = TSTORM_INDIRECTION_TABLE_SIZE;
+	memcpy(indir->ring_index, bp->rx_indir_table,
+	       copy_size * sizeof(bp->rx_indir_table[0]));
+	return 0;
+}
+
+static int bnx2x_set_rxfh_indir(struct net_device *dev,
+				const struct ethtool_rxfh_indir *indir)
+{
+	struct bnx2x *bp = netdev_priv(dev);
+	size_t i;
+
+	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
+		return -EOPNOTSUPP;
+
+	/* Validate size and indices */
+	if (indir->size != TSTORM_INDIRECTION_TABLE_SIZE)
+		return -EINVAL;
+	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+		if (indir->ring_index[i] >= BNX2X_NUM_ETH_QUEUES(bp))
+			return -EINVAL;
+
+	memcpy(bp->rx_indir_table, indir->ring_index,
+	       indir->size * sizeof(bp->rx_indir_table[0]));
+	bnx2x_push_indir_table(bp);
+	return 0;
+}
+
 static const struct ethtool_ops bnx2x_ethtool_ops = {
 	.get_settings		= bnx2x_get_settings,
 	.set_settings		= bnx2x_set_settings,
@@ -2167,6 +2219,9 @@
 	.get_strings		= bnx2x_get_strings,
 	.phys_id		= bnx2x_phys_id,
 	.get_ethtool_stats	= bnx2x_get_ethtool_stats,
+	.get_rxnfc		= bnx2x_get_rxnfc,
+	.get_rxfh_indir		= bnx2x_get_rxfh_indir,
+	.set_rxfh_indir		= bnx2x_set_rxfh_indir,
 };
 
 void bnx2x_set_ethtool_ops(struct net_device *netdev)
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x.h linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,8 +22,8 @@
  * (you will need to reboot afterwards) */
 /* #define BNX2X_STOP_ON_ERROR */
 
-#define DRV_MODULE_VERSION      "1.62.00-6"
-#define DRV_MODULE_RELDATE      "2011/01/30"
+#define DRV_MODULE_VERSION      "1.62.11-0"
+#define DRV_MODULE_RELDATE      "2011/01/31"
 #define BNX2X_BC_VER            0x040200
 
 #define BNX2X_MULTI_QUEUE
@@ -31,7 +31,7 @@
 #define BNX2X_NEW_NAPI
 
 #if defined(CONFIG_DCB)
-#define BCM_DCB
+#define BCM_DCBNL
 #endif
 #if defined(CONFIG_CNIC) || defined(CONFIG_CNIC_MODULE)
 #define BCM_CNIC 1
@@ -129,6 +129,7 @@
 #endif
 
 #define bnx2x_mc_addr(ha)      ((ha)->addr)
+#define bnx2x_uc_addr(ha)      ((ha)->addr)
 
 #define U64_LO(x)			(u32)(((u64)(x)) & 0xffffffff)
 #define U64_HI(x)			(u32)(((u64)(x)) >> 32)
@@ -341,6 +342,8 @@
 	/* chip independed shortcut into rx_prods_offset memory */
 	u32			ustorm_rx_prods_offset;
 
+	u32			rx_buf_size;
+
 	dma_addr_t		status_blk_mapping;
 
 	struct sw_tx_bd		*tx_buf_ring;
@@ -428,6 +431,10 @@
 };
 
 #define bnx2x_fp(bp, nr, var)		(bp->fp[nr].var)
+
+/* Use 2500 as a mini-jumbo MTU for FCoE */
+#define BNX2X_FCOE_MINI_JUMBO_MTU	2500
+
 #ifdef BCM_CNIC
 /* FCoE L2 `fastpath' is right after the eth entries */
 #define FCOE_IDX			BNX2X_NUM_ETH_QUEUES(bp)
@@ -810,6 +817,7 @@
 	struct eth_stats_query		fw_stats;
 	struct mac_configuration_cmd	mac_config;
 	struct mac_configuration_cmd	mcast_config;
+	struct mac_configuration_cmd	uc_mac_config;
 	struct client_init_ramrod_data	client_init_data;
 
 	/* used by dmae command executer */
@@ -911,7 +919,6 @@
 	int			tx_ring_size;
 
 	u32			rx_csum;
-	u32			rx_buf_size;
 /* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
 #define ETH_OVREHEAD		(ETH_HLEN + 8 + 8)
 #define ETH_MIN_PACKET_SIZE		60
@@ -939,7 +946,7 @@
 	struct eth_spe		*spq_prod_bd;
 	struct eth_spe		*spq_last_bd;
 	__le16			*dsb_sp_prod;
-	atomic_t		spq_left; /* serialize spq */
+	atomic_t		cq_spq_left; /* ETH_XXX ramrods credit */
 	/* used to synchronize spq accesses */
 	spinlock_t		spq_lock;
 
@@ -949,6 +956,7 @@
 	u16			eq_prod;
 	u16			eq_cons;
 	__le16			*eq_cons_sb;
+	atomic_t		eq_spq_left; /* COMMON_XXX ramrods credit */
 
 	/* Flags for marking that there is a STAT_QUERY or
 	   SET_MAC ramrod pending */
@@ -976,8 +984,12 @@
 #define MF_FUNC_DIS			0x1000
 #define FCOE_MACS_SET			0x2000
 #define NO_FCOE_FLAG			0x4000
+#define NO_ISCSI_OOO_FLAG		0x8000
+#define NO_ISCSI_FLAG			0x10000
 
 #define NO_FCOE(bp)		((bp)->flags & NO_FCOE_FLAG)
+#define NO_ISCSI(bp)		((bp)->flags & NO_ISCSI_FLAG)
+#define NO_ISCSI_OOO(bp)	((bp)->flags & NO_ISCSI_OOO_FLAG)
 
 	int			pf_num;	/* absolute PF number */
 	int			pfid;	/* per-path PF number */
@@ -1064,6 +1076,7 @@
 	int			num_queues;
 	int			disable_tpa;
 	int			int_mode;
+	u32			*rx_indir_table;
 
 	struct tstorm_eth_mac_filter_config	mac_filters;
 #define BNX2X_ACCEPT_NONE		0x0000
@@ -1110,7 +1123,7 @@
 #define BNX2X_CNIC_FLAG_MAC_SET		1
 	void			*t2;
 	dma_addr_t		t2_mapping;
-	struct cnic_ops		*cnic_ops;
+	struct cnic_ops	__rcu	*cnic_ops;
 	void			*cnic_data;
 	u32			cnic_tag;
 	struct cnic_eth_dev	cnic_eth_dev;
@@ -1125,13 +1138,12 @@
 	u16			cnic_kwq_pending;
 	u16			cnic_spq_pending;
 	struct mutex		cnic_mutex;
-	u8			iscsi_mac[ETH_ALEN];
 	u8			fip_mac[ETH_ALEN];
 #endif
 
 	int			dmae_ready;
 	/* used to synchronize dmae accesses */
-	struct mutex		dmae_mutex;
+	spinlock_t		dmae_lock;
 
 	/* used to protect the FW mail box */
 	struct mutex		fw_mb_mutex;
@@ -1208,7 +1220,7 @@
 	struct bnx2x_dcbx_port_params		dcbx_port_params;
 	int					dcb_version;
 
-	/* DCBX Negotation results */
+	/* DCBX Negotiation results */
 	struct dcbx_features			dcbx_local_feat;
 	u32					dcbx_error;
 	u32					pending_max;
@@ -1448,6 +1460,12 @@
 void bnx2x_calc_fc_adv(struct bnx2x *bp);
 int bnx2x_sp_post(struct bnx2x *bp, int command, int cid,
 		  u32 data_hi, u32 data_lo, int common);
+
+/* Clears multicast and unicast list configuration in the chip. */
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp);
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp);
+void bnx2x_invalidate_uc_list(struct bnx2x *bp);
+
 void bnx2x_update_coalesce(struct bnx2x *bp);
 int bnx2x_get_link_cfg_idx(struct bnx2x *bp);
 
@@ -1787,5 +1805,6 @@
 BNX2X_EXTERN int load_count[2][3]; /* per path: 0-common, 1-port0, 2-port1 */
 
 extern void bnx2x_set_ethtool_ops(struct net_device *netdev);
+void bnx2x_push_indir_table(struct bnx2x *bp);
 
 #endif /* bnx2x.h */
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_hsi.h linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_hsi.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_hsi.h	2012-03-24 01:07:06.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_hsi.h	2012-03-24 03:30:25.000000000 -0400
@@ -11,20 +11,27 @@
 
 #include "bnx2x_fw_defs.h"
 
+#define FW_ENCODE_32BIT_PATTERN		0x1e1e1e1e
+
 struct license_key {
 	u32 reserved[6];
 
-#if defined(__BIG_ENDIAN)
-	u16 max_iscsi_init_conn;
-	u16 max_iscsi_trgt_conn;
-#elif defined(__LITTLE_ENDIAN)
-	u16 max_iscsi_trgt_conn;
-	u16 max_iscsi_init_conn;
-#endif
+	u32 max_iscsi_conn;
+#define BNX2X_MAX_ISCSI_TRGT_CONN_MASK	0xFFFF
+#define BNX2X_MAX_ISCSI_TRGT_CONN_SHIFT	0
+#define BNX2X_MAX_ISCSI_INIT_CONN_MASK	0xFFFF0000
+#define BNX2X_MAX_ISCSI_INIT_CONN_SHIFT	16
 
-	u32 reserved_a[6];
-};
+	u32 reserved_a;
+
+	u32 max_fcoe_conn;
+#define BNX2X_MAX_FCOE_TRGT_CONN_MASK	0xFFFF
+#define BNX2X_MAX_FCOE_TRGT_CONN_SHIFT	0
+#define BNX2X_MAX_FCOE_INIT_CONN_MASK	0xFFFF0000
+#define BNX2X_MAX_FCOE_INIT_CONN_SHIFT	16
 
+	u32 reserved_b[4];
+};
 
 #define PORT_0				0
 #define PORT_1				1
@@ -237,8 +244,26 @@
 #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT	      16
 
 
-	u32 Reserved0[16];				    /* 0x158 */
+	u32 Reserved0[3];				    /* 0x158 */
+	/*	Controls the TX laser of the SFP+ module */
+	u32 sfp_ctrl;					/* 0x164 */
+#define PORT_HW_CFG_TX_LASER_MASK			      0x000000FF
+#define PORT_HW_CFG_TX_LASER_SHIFT			      0
+#define PORT_HW_CFG_TX_LASER_MDIO			      0x00000000
+#define PORT_HW_CFG_TX_LASER_GPIO0			      0x00000001
+#define PORT_HW_CFG_TX_LASER_GPIO1			      0x00000002
+#define PORT_HW_CFG_TX_LASER_GPIO2			      0x00000003
+#define PORT_HW_CFG_TX_LASER_GPIO3			      0x00000004
 
+    /*	Controls the fault module LED of the SFP+ */
+#define PORT_HW_CFG_FAULT_MODULE_LED_MASK		      0x0000FF00
+#define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT		      8
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0		      0x00000000
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1		      0x00000100
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2		      0x00000200
+#define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3		      0x00000300
+#define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED		      0x00000400
+	u32 Reserved01[12];				    /* 0x158 */
 	/*  for external PHY, or forced mode or during AN */
 	u16 xgxs_config_rx[4];				    /* 0x198 */
 
@@ -246,12 +271,78 @@
 
 	u32 Reserved1[56];				    /* 0x1A8 */
 	u32 default_cfg;				    /* 0x288 */
+#define PORT_HW_CFG_GPIO0_CONFIG_MASK			      0x00000003
+#define PORT_HW_CFG_GPIO0_CONFIG_SHIFT			      0
+#define PORT_HW_CFG_GPIO0_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO0_CONFIG_LOW			      0x00000001
+#define PORT_HW_CFG_GPIO0_CONFIG_HIGH			      0x00000002
+#define PORT_HW_CFG_GPIO0_CONFIG_INPUT			      0x00000003
+
+#define PORT_HW_CFG_GPIO1_CONFIG_MASK			      0x0000000C
+#define PORT_HW_CFG_GPIO1_CONFIG_SHIFT			      2
+#define PORT_HW_CFG_GPIO1_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO1_CONFIG_LOW			      0x00000004
+#define PORT_HW_CFG_GPIO1_CONFIG_HIGH			      0x00000008
+#define PORT_HW_CFG_GPIO1_CONFIG_INPUT			      0x0000000c
+
+#define PORT_HW_CFG_GPIO2_CONFIG_MASK			      0x00000030
+#define PORT_HW_CFG_GPIO2_CONFIG_SHIFT			      4
+#define PORT_HW_CFG_GPIO2_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO2_CONFIG_LOW			      0x00000010
+#define PORT_HW_CFG_GPIO2_CONFIG_HIGH			      0x00000020
+#define PORT_HW_CFG_GPIO2_CONFIG_INPUT			      0x00000030
+
+#define PORT_HW_CFG_GPIO3_CONFIG_MASK			      0x000000C0
+#define PORT_HW_CFG_GPIO3_CONFIG_SHIFT			      6
+#define PORT_HW_CFG_GPIO3_CONFIG_NA			      0x00000000
+#define PORT_HW_CFG_GPIO3_CONFIG_LOW			      0x00000040
+#define PORT_HW_CFG_GPIO3_CONFIG_HIGH			      0x00000080
+#define PORT_HW_CFG_GPIO3_CONFIG_INPUT			      0x000000c0
+
+	/*
+	 * When KR link is required to be set to force which is not
+	 * KR-compliant, this parameter determine what is the trigger for it.
+	 * When GPIO is selected, low input will force the speed. Currently
+	 * default speed is 1G. In the future, it may be widen to select the
+	 * forced speed in with another parameter. Note when force-1G is
+	 * enabled, it override option 56: Link Speed option.
+	 */
+#define PORT_HW_CFG_FORCE_KR_ENABLER_MASK		      0x00000F00
+#define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT		      8
+#define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED		      0x00000000
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0		      0x00000100
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0		      0x00000200
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0		      0x00000300
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0		      0x00000400
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1		      0x00000500
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1		      0x00000600
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1		      0x00000700
+#define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1		      0x00000800
+#define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED		      0x00000900
+    /*	Enable to determine with which GPIO to reset the external phy */
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK		      0x000F0000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT		      16
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE		      0x00000000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0		      0x00010000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0		      0x00020000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0		      0x00030000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0		      0x00040000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1		      0x00050000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1		      0x00060000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1		      0x00070000
+#define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1		      0x00080000
 	/*  Enable BAM on KR */
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK		      0x00100000
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT		      20
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_DISABLED		      0x00000000
 #define PORT_HW_CFG_ENABLE_BAM_ON_KR_ENABLED		      0x00100000
 
+	/*  Enable Common Mode Sense */
+#define PORT_HW_CFG_ENABLE_CMS_MASK			      0x00200000
+#define PORT_HW_CFG_ENABLE_CMS_SHIFT			      21
+#define PORT_HW_CFG_ENABLE_CMS_DISABLED			      0x00000000
+#define PORT_HW_CFG_ENABLE_CMS_ENABLED			      0x00200000
+
 	u32 speed_capability_mask2;			    /* 0x28C */
 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_MASK		      0x0000FFFF
 #define PORT_HW_CFG_SPEED_CAPABILITY2_D3_SHIFT		      0
@@ -381,6 +472,7 @@
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727	    0x00000900
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727_NOC   0x00000a00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823	    0x00000b00
+#define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833	    0x00000d00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE	    0x0000fd00
 #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_NOT_CONN	    0x0000ff00
 
@@ -2923,7 +3015,7 @@
 
 
 /*
- * common flag to indicate existance of TPA.
+ * common flag to indicate existence of TPA.
  */
 struct tstorm_eth_tpa_exist {
 #if defined(__BIG_ENDIAN)
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_link.c linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_link.c
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_link.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_link.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright 2008-2009 Broadcom Corporation
+/* Copyright 2008-2011 Broadcom Corporation
  *
  * Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -28,12 +28,13 @@
 
 /********************************************************/
 #define ETH_HLEN			14
-#define ETH_OVREHEAD		(ETH_HLEN + 8 + 8)/* 16 for CRC + VLAN + LLC */
+/* L2 header size + 2*VLANs (8 bytes) + LLC SNAP (8 bytes) */
+#define ETH_OVREHEAD			(ETH_HLEN + 8 + 8)
 #define ETH_MIN_PACKET_SIZE		60
 #define ETH_MAX_PACKET_SIZE		1500
 #define ETH_MAX_JUMBO_PACKET_SIZE	9600
 #define MDIO_ACCESS_TIMEOUT		1000
-#define BMAC_CONTROL_RX_ENABLE	2
+#define BMAC_CONTROL_RX_ENABLE		2
 
 /***********************************************************/
 /*			Shortcut definitions		   */
@@ -79,7 +80,7 @@
 
 #define AUTONEG_CL37		SHARED_HW_CFG_AN_ENABLE_CL37
 #define AUTONEG_CL73		SHARED_HW_CFG_AN_ENABLE_CL73
-#define AUTONEG_BAM 		SHARED_HW_CFG_AN_ENABLE_BAM
+#define AUTONEG_BAM		SHARED_HW_CFG_AN_ENABLE_BAM
 #define AUTONEG_PARALLEL \
 				SHARED_HW_CFG_AN_ENABLE_PARALLEL_DETECTION
 #define AUTONEG_SGMII_FIBER_AUTODET \
@@ -112,10 +113,10 @@
 #define GP_STATUS_10G_KX4 \
 			MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_KX4
 
-#define LINK_10THD			LINK_STATUS_SPEED_AND_DUPLEX_10THD
-#define LINK_10TFD			LINK_STATUS_SPEED_AND_DUPLEX_10TFD
+#define LINK_10THD		LINK_STATUS_SPEED_AND_DUPLEX_10THD
+#define LINK_10TFD		LINK_STATUS_SPEED_AND_DUPLEX_10TFD
 #define LINK_100TXHD		LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
-#define LINK_100T4			LINK_STATUS_SPEED_AND_DUPLEX_100T4
+#define LINK_100T4		LINK_STATUS_SPEED_AND_DUPLEX_100T4
 #define LINK_100TXFD		LINK_STATUS_SPEED_AND_DUPLEX_100TXFD
 #define LINK_1000THD		LINK_STATUS_SPEED_AND_DUPLEX_1000THD
 #define LINK_1000TFD		LINK_STATUS_SPEED_AND_DUPLEX_1000TFD
@@ -123,18 +124,18 @@
 #define LINK_2500THD		LINK_STATUS_SPEED_AND_DUPLEX_2500THD
 #define LINK_2500TFD		LINK_STATUS_SPEED_AND_DUPLEX_2500TFD
 #define LINK_2500XFD		LINK_STATUS_SPEED_AND_DUPLEX_2500XFD
-#define LINK_10GTFD			LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
-#define LINK_10GXFD			LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
-#define LINK_12GTFD			LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
-#define LINK_12GXFD			LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
+#define LINK_10GTFD		LINK_STATUS_SPEED_AND_DUPLEX_10GTFD
+#define LINK_10GXFD		LINK_STATUS_SPEED_AND_DUPLEX_10GXFD
+#define LINK_12GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12GTFD
+#define LINK_12GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12GXFD
 #define LINK_12_5GTFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GTFD
 #define LINK_12_5GXFD		LINK_STATUS_SPEED_AND_DUPLEX_12_5GXFD
-#define LINK_13GTFD			LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
-#define LINK_13GXFD			LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
-#define LINK_15GTFD			LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
-#define LINK_15GXFD			LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
-#define LINK_16GTFD			LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
-#define LINK_16GXFD			LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
+#define LINK_13GTFD		LINK_STATUS_SPEED_AND_DUPLEX_13GTFD
+#define LINK_13GXFD		LINK_STATUS_SPEED_AND_DUPLEX_13GXFD
+#define LINK_15GTFD		LINK_STATUS_SPEED_AND_DUPLEX_15GTFD
+#define LINK_15GXFD		LINK_STATUS_SPEED_AND_DUPLEX_15GXFD
+#define LINK_16GTFD		LINK_STATUS_SPEED_AND_DUPLEX_16GTFD
+#define LINK_16GXFD		LINK_STATUS_SPEED_AND_DUPLEX_16GXFD
 
 #define PHY_XGXS_FLAG			0x1
 #define PHY_SGMII_FLAG			0x2
@@ -142,7 +143,7 @@
 
 /* */
 #define SFP_EEPROM_CON_TYPE_ADDR		0x2
-	#define SFP_EEPROM_CON_TYPE_VAL_LC 		0x7
+	#define SFP_EEPROM_CON_TYPE_VAL_LC	0x7
 	#define SFP_EEPROM_CON_TYPE_VAL_COPPER	0x21
 
 
@@ -153,15 +154,15 @@
 
 #define SFP_EEPROM_FC_TX_TECH_ADDR		0x8
 	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4
-	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE	 0x8
+	#define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE  0x8
 
-#define SFP_EEPROM_OPTIONS_ADDR 		0x40
+#define SFP_EEPROM_OPTIONS_ADDR			0x40
 	#define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1
-#define SFP_EEPROM_OPTIONS_SIZE 		2
+#define SFP_EEPROM_OPTIONS_SIZE			2
 
-#define EDC_MODE_LINEAR	 			0x0022
-#define EDC_MODE_LIMITING	 			0x0044
-#define EDC_MODE_PASSIVE_DAC 			0x0055
+#define EDC_MODE_LINEAR				0x0022
+#define EDC_MODE_LIMITING				0x0044
+#define EDC_MODE_PASSIVE_DAC			0x0055
 
 
 #define ETS_BW_LIMIT_CREDIT_UPPER_BOUND		(0x5000)
@@ -170,24 +171,18 @@
 /*                     INTERFACE                          */
 /**********************************************************/
 
-#define CL45_WR_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+#define CL22_WR_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
 	bnx2x_cl45_write(_bp, _phy, \
 		(_phy)->def_md_devad, \
 		(_bank + (_addr & 0xf)), \
 		_val)
 
-#define CL45_RD_OVER_CL22(_bp, _phy, _bank, _addr, _val) \
+#define CL22_RD_OVER_CL45(_bp, _phy, _bank, _addr, _val) \
 	bnx2x_cl45_read(_bp, _phy, \
 		(_phy)->def_md_devad, \
 		(_bank + (_addr & 0xf)), \
 		_val)
 
-static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
-			  u8 devad, u16 reg, u16 *ret_val);
-
-static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-			   u8 devad, u16 reg, u16 val);
-
 static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits)
 {
 	u32 val = REG_RD(bp, reg);
@@ -216,7 +211,7 @@
 
 	DP(NETIF_MSG_LINK, "ETS disabled configuration\n");
 
-	/**
+	/*
 	 * mapping between entry  priority to client number (0,1,2 -debug and
 	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
 	 * 3bits client num.
@@ -225,7 +220,7 @@
 	 */
 
 	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, 0x4688);
-	/**
+	/*
 	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
 	 * as strict.  Bits 0,1,2 - debug and management entries, 3 -
 	 * COS0 entry, 4 - COS1 entry.
@@ -237,12 +232,12 @@
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
 	/* defines which entries (clients) are subjected to WFQ arbitration */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0);
-	/**
-	* For strict priority entries defines the number of consecutive
-	* slots for the highest priority.
-	*/
+	/*
+	 * For strict priority entries defines the number of consecutive
+	 * slots for the highest priority.
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_NUM_STRICT_ARB_SLOTS, 0x100);
-	/**
+	/*
 	 * mapping between the CREDIT_WEIGHT registers and actual client
 	 * numbers
 	 */
@@ -255,7 +250,7 @@
 	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, 0);
 	/* ETS mode disable */
 	REG_WR(bp, PBF_REG_ETS_ENABLED, 0);
-	/**
+	/*
 	 * If ETS mode is enabled (there is no strict priority) defines a WFQ
 	 * weight for COS0/COS1.
 	 */
@@ -268,24 +263,24 @@
 	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
 }
 
-void bnx2x_ets_bw_limit_common(const struct link_params *params)
+static void bnx2x_ets_bw_limit_common(const struct link_params *params)
 {
 	/* ETS disabled configuration */
 	struct bnx2x *bp = params->bp;
 	DP(NETIF_MSG_LINK, "ETS enabled BW limit configuration\n");
-	/**
-	* defines which entries (clients) are subjected to WFQ arbitration
-	* COS0 0x8
-	* COS1 0x10
-	*/
+	/*
+	 * defines which entries (clients) are subjected to WFQ arbitration
+	 * COS0 0x8
+	 * COS1 0x10
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_SUBJECT2WFQ, 0x18);
-	/**
-	* mapping between the ARB_CREDIT_WEIGHT registers and actual
-	* client numbers (WEIGHT_0 does not actually have to represent
-	* client 0)
-	*    PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
-	*  cos1-001     cos0-000     dbg1-100     dbg0-011     MCP-010
-	*/
+	/*
+	 * mapping between the ARB_CREDIT_WEIGHT registers and actual
+	 * client numbers (WEIGHT_0 does not actually have to represent
+	 * client 0)
+	 *    PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	 *  cos1-001     cos0-000     dbg1-100     dbg0-011     MCP-010
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_CREDIT_MAP, 0x111A);
 
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CREDIT_UPPER_BOUND_0,
@@ -298,14 +293,14 @@
 
 	/* Defines the number of consecutive slots for the strict priority */
 	REG_WR(bp, PBF_REG_NUM_STRICT_ARB_SLOTS, 0);
-	/**
-	* Bitmap of 5bits length. Each bit specifies whether the entry behaves
-	* as strict.  Bits 0,1,2 - debug and management entries, 3 - COS0
-	* entry, 4 - COS1 entry.
-	* COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
-	* bit4   bit3	  bit2     bit1	   bit0
-	* MCP and debug are strict
-	*/
+	/*
+	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
+	 * as strict.  Bits 0,1,2 - debug and management entries, 3 - COS0
+	 * entry, 4 - COS1 entry.
+	 * COS1 | COS0 | DEBUG21 | DEBUG0 | MGMT
+	 * bit4   bit3	  bit2     bit1	   bit0
+	 * MCP and debug are strict
+	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x7);
 
 	/* Upper bound that COS0_WEIGHT can reach in the WFQ arbiter.*/
@@ -329,8 +324,7 @@
 	if ((0 == total_bw) ||
 	    (0 == cos0_bw) ||
 	    (0 == cos1_bw)) {
-		DP(NETIF_MSG_LINK,
-		   "bnx2x_ets_bw_limit: Total BW can't be zero\n");
+		DP(NETIF_MSG_LINK, "Total BW can't be zero\n");
 		return;
 	}
 
@@ -355,7 +349,7 @@
 	u32 val	= 0;
 
 	DP(NETIF_MSG_LINK, "ETS enabled strict configuration\n");
-	/**
+	/*
 	 * Bitmap of 5bits length. Each bit specifies whether the entry behaves
 	 * as strict.  Bits 0,1,2 - debug and management entries,
 	 * 3 - COS0 entry, 4 - COS1 entry.
@@ -364,7 +358,7 @@
 	 * MCP and debug are strict
 	 */
 	REG_WR(bp, NIG_REG_P0_TX_ARB_CLIENT_IS_STRICT, 0x1F);
-	/**
+	/*
 	 * For strict priority entries defines the number of consecutive slots
 	 * for the highest priority.
 	 */
@@ -377,14 +371,14 @@
 	/* Defines the number of consecutive slots for the strict priority */
 	REG_WR(bp, PBF_REG_HIGH_PRIORITY_COS_NUM, strict_cos);
 
-	/**
-	* mapping between entry  priority to client number (0,1,2 -debug and
-	* management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
-	* 3bits client num.
-	*   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
-	* dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
-	* dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
-	*/
+	/*
+	 * mapping between entry  priority to client number (0,1,2 -debug and
+	 * management clients, 3 - COS0 client, 4 - COS client)(HIGHEST)
+	 * 3bits client num.
+	 *   PRI4    |    PRI3    |    PRI2    |    PRI1    |    PRI0
+	 * dbg0-010     dbg1-001     cos1-100     cos0-011     MCP-000
+	 * dbg0-010     dbg1-001     cos0-011     cos1-100     MCP-000
+	 */
 	val = (0 == strict_cos) ? 0x2318 : 0x22E0;
 	REG_WR(bp, NIG_REG_P0_TX_ARB_PRIORITY_CLIENT, val);
 
@@ -471,7 +465,7 @@
 /*			MAC/PBF section				  */
 /******************************************************************/
 static void bnx2x_emac_init(struct link_params *params,
-			   struct link_vars *vars)
+			    struct link_vars *vars)
 {
 	/* reset and unreset the emac core */
 	struct bnx2x *bp = params->bp;
@@ -481,10 +475,10 @@
 	u16 timeout;
 
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-		   (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
 	udelay(5);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-		   (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_EMAC0_HARD_CORE << port));
 
 	/* init emac - use read-modify-write */
 	/* self clear reset */
@@ -515,7 +509,7 @@
 }
 
 static u8 bnx2x_emac_enable(struct link_params *params,
-			  struct link_vars *vars, u8 lb)
+			    struct link_vars *vars, u8 lb)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -527,55 +521,33 @@
 	/* enable emac and not bmac */
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + port*4, 1);
 
-	/* for paladium */
-	if (CHIP_REV_IS_EMUL(bp)) {
-		/* Use lane 1 (of lanes 0-3) */
-		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
-			    port*4, 1);
-	}
-	/* for fpga */
-	else
-
-	if (CHIP_REV_IS_FPGA(bp)) {
-		/* Use lane 1 (of lanes 0-3) */
-		DP(NETIF_MSG_LINK, "bnx2x_emac_enable: Setting FPGA\n");
-
-		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, 1);
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4,
-			    0);
-	} else
 	/* ASIC */
 	if (vars->phy_flags & PHY_XGXS_FLAG) {
 		u32 ser_lane = ((params->lane_config &
-			    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-			    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+				 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
+				PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 
 		DP(NETIF_MSG_LINK, "XGXS\n");
 		/* select the master lanes (out of 0-3) */
-		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 +
-			   port*4, ser_lane);
+		REG_WR(bp, NIG_REG_XGXS_LANE_SEL_P0 + port*4, ser_lane);
 		/* select XGXS */
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
-			   port*4, 1);
+		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 1);
 
 	} else { /* SerDes */
 		DP(NETIF_MSG_LINK, "SerDes\n");
 		/* select SerDes */
-		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL +
-			   port*4, 0);
+		REG_WR(bp, NIG_REG_XGXS_SERDES0_MODE_SEL + port*4, 0);
 	}
 
 	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
-		    EMAC_RX_MODE_RESET);
+		      EMAC_RX_MODE_RESET);
 	bnx2x_bits_en(bp, emac_base + EMAC_REG_EMAC_TX_MODE,
-		    EMAC_TX_MODE_RESET);
+		      EMAC_TX_MODE_RESET);
 
 	if (CHIP_REV_IS_SLOW(bp)) {
 		/* config GMII mode */
 		val = REG_RD(bp, emac_base + EMAC_REG_EMAC_MODE);
-		EMAC_WR(bp, EMAC_REG_EMAC_MODE,
-			    (val | EMAC_MODE_PORT_GMII));
+		EMAC_WR(bp, EMAC_REG_EMAC_MODE, (val | EMAC_MODE_PORT_GMII));
 	} else { /* ASIC */
 		/* pause enable/disable */
 		bnx2x_bits_dis(bp, emac_base + EMAC_REG_EMAC_RX_MODE,
@@ -605,14 +577,14 @@
 	val = REG_RD(bp, emac_base + EMAC_REG_EMAC_RX_MODE);
 	val |= EMAC_RX_MODE_KEEP_VLAN_TAG | EMAC_RX_MODE_PROMISCUOUS;
 
-	/**
-	* Setting this bit causes MAC control frames (except for pause
-	* frames) to be passed on for processing. This setting has no
-	* affect on the operation of the pause frames. This bit effects
-	* all packets regardless of RX Parser packet sorting logic.
-	* Turn the PFC off to make sure we are in Xon state before
-	* enabling it.
-	*/
+	/*
+	 * Setting this bit causes MAC control frames (except for pause
+	 * frames) to be passed on for processing. This setting has no
+	 * affect on the operation of the pause frames. This bit effects
+	 * all packets regardless of RX Parser packet sorting logic.
+	 * Turn the PFC off to make sure we are in Xon state before
+	 * enabling it.
+	 */
 	EMAC_WR(bp, EMAC_REG_RX_PFC_MODE, 0);
 	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED) {
 		DP(NETIF_MSG_LINK, "PFC is enabled\n");
@@ -666,16 +638,7 @@
 	REG_WR(bp, NIG_REG_EMAC0_PAUSE_OUT_EN + port*4, val);
 	REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0x1);
 
-	if (CHIP_REV_IS_EMUL(bp)) {
-		/* take the BigMac out of reset */
-		REG_WR(bp,
-			   GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-			   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
-
-		/* enable access for bmac registers */
-		REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
-	} else
-		REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
+	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x0);
 
 	vars->mac_type = MAC_TYPE_EMAC;
 	return 0;
@@ -731,8 +694,7 @@
 		val |= (1<<5);
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_CONTROL, wb_data, 2);
 	udelay(30);
 
 	/* Tx control */
@@ -768,12 +730,12 @@
 
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_PFC_CONTROL, wb_data, 2);
 
-	/**
-	* Set Time (based unit is 512 bit time) between automatic
-	* re-sending of PP packets amd enable automatic re-send of
-	* Per-Priroity Packet as long as pp_gen is asserted and
-	* pp_disable is low.
-	*/
+	/*
+	 * Set Time (based unit is 512 bit time) between automatic
+	 * re-sending of PP packets amd enable automatic re-send of
+	 * Per-Priroity Packet as long as pp_gen is asserted and
+	 * pp_disable is low.
+	 */
 	val = 0x8000;
 	if (params->feature_config_flags & FEATURE_CONFIG_PFC_ENABLED)
 		val |= (1<<16); /* enable automatic re-send */
@@ -781,7 +743,7 @@
 	wb_data[0] = val;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_PAUSE_CONTROL,
-			wb_data, 2);
+		    wb_data, 2);
 
 	/* mac control */
 	val = 0x3; /* Enable RX and TX */
@@ -795,8 +757,7 @@
 
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 }
 
 static void bnx2x_update_pfc_brb(struct link_params *params,
@@ -825,17 +786,25 @@
 			full_xon_th =
 			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
 		}
-	/* The number of free blocks below which the pause signal to class 0
-	   of MAC #n is asserted. n=0,1 */
+	/*
+	 * The number of free blocks below which the pause signal to class 0
+	 * of MAC #n is asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_PAUSE_0_XOFF_THRESHOLD_0 , pause_xoff_th);
-	/* The number of free blocks above which the pause signal to class 0
-	   of MAC #n is de-asserted. n=0,1 */
+	/*
+	 * The number of free blocks above which the pause signal to class 0
+	 * of MAC #n is de-asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_PAUSE_0_XON_THRESHOLD_0 , pause_xon_th);
-	/* The number of free blocks below which the full signal to class 0
-	   of MAC #n is asserted. n=0,1 */
+	/*
+	 * The number of free blocks below which the full signal to class 0
+	 * of MAC #n is asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_FULL_0_XOFF_THRESHOLD_0 , full_xoff_th);
-	/* The number of free blocks above which the full signal to class 0
-	   of MAC #n is de-asserted. n=0,1 */
+	/*
+	 * The number of free blocks above which the full signal to class 0
+	 * of MAC #n is de-asserted. n=0,1
+	 */
 	REG_WR(bp, BRB1_REG_FULL_0_XON_THRESHOLD_0 , full_xon_th);
 
 	if (set_pfc && pfc_params) {
@@ -859,25 +828,25 @@
 			full_xon_th =
 			  PFC_BRB_MAC_FULL_XON_THRESHOLD_NON_PAUSEABLE;
 		}
-		/**
+		/*
 		 * The number of free blocks below which the pause signal to
 		 * class 1 of MAC #n is asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_PAUSE_1_XOFF_THRESHOLD_0, pause_xoff_th);
-		/**
+		/*
 		 * The number of free blocks above which the pause signal to
 		 * class 1 of MAC #n is de-asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_PAUSE_1_XON_THRESHOLD_0, pause_xon_th);
-		/**
+		/*
 		 * The number of free blocks below which the full signal to
 		 * class 1 of MAC #n is asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_FULL_1_XOFF_THRESHOLD_0, full_xoff_th);
-		/**
+		/*
 		 * The number of free blocks above which the full signal to
 		 * class 1 of MAC #n is de-asserted. n=0,1
-		 **/
+		 */
 		REG_WR(bp, BRB1_REG_FULL_1_XON_THRESHOLD_0, full_xon_th);
 	}
 }
@@ -896,7 +865,7 @@
 		FEATURE_CONFIG_PFC_ENABLED;
 	DP(NETIF_MSG_LINK, "updating pfc nig parameters\n");
 
-	/**
+	/*
 	 * When NIG_LLH0_XCM_MASK_REG_LLHX_XCM_MASK_BCN bit is set
 	 * MAC control frames (that are not pause packets)
 	 * will be forwarded to the XCM.
@@ -904,7 +873,7 @@
 	xcm_mask = REG_RD(bp,
 				port ? NIG_REG_LLH1_XCM_MASK :
 				NIG_REG_LLH0_XCM_MASK);
-	/**
+	/*
 	 * nig params will override non PFC params, since it's possible to
 	 * do transition from PFC to SAFC
 	 */
@@ -994,7 +963,7 @@
 		      struct link_vars *vars,
 		      struct bnx2x_nig_brb_pfc_port_params *pfc_params)
 {
-	/**
+	/*
 	 * The PFC and pause are orthogonal to one another, meaning when
 	 * PFC is enabled, the pause are disabled, and when PFC is
 	 * disabled, pause are set according to the pause result.
@@ -1035,7 +1004,7 @@
 
 static u8 bnx2x_bmac1_enable(struct link_params *params,
 			     struct link_vars *vars,
-			  u8 is_lb)
+			     u8 is_lb)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1049,9 +1018,8 @@
 	/* XGXS control */
 	wb_data[0] = 0x3c;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr +
-		      BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
-		      wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_XGXS_CONTROL,
+		    wb_data, 2);
 
 	/* tx MAC SA */
 	wb_data[0] = ((params->mac_addr[2] << 24) |
@@ -1060,8 +1028,7 @@
 			params->mac_addr[5]);
 	wb_data[1] = ((params->mac_addr[0] << 8) |
 			params->mac_addr[1]);
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR,
-		    wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_SOURCE_ADDR, wb_data, 2);
 
 	/* mac control */
 	val = 0x3;
@@ -1071,43 +1038,30 @@
 	}
 	wb_data[0] = val;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL,
-		    wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_BMAC_CONTROL, wb_data, 2);
 
 	/* set rx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_MAX_SIZE, wb_data, 2);
 
 	bnx2x_update_pfc_bmac1(params, vars);
 
 	/* set tx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_TX_MAX_SIZE, wb_data, 2);
 
 	/* set cnt max size */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE,
-		    wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 
 	/* configure safc */
 	wb_data[0] = 0x1000200;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC_REGISTER_RX_LLFC_MSG_FLDS,
 		    wb_data, 2);
-	/* fix for emulation */
-	if (CHIP_REV_IS_EMUL(bp)) {
-		wb_data[0] = 0xf000;
-		wb_data[1] = 0;
-		REG_WR_DMAE(bp,
-			    bmac_addr + BIGMAC_REGISTER_TX_PAUSE_THRESHOLD,
-			    wb_data, 2);
-	}
-
 
 	return 0;
 }
@@ -1126,16 +1080,14 @@
 
 	wb_data[0] = 0;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_CONTROL, wb_data, 2);
 	udelay(30);
 
 	/* XGXS control: Reset phy HW, MDIO registers, PHY PLL and BMAC */
 	wb_data[0] = 0x3c;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr +
-			BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_BMAC_XGXS_CONTROL,
+		    wb_data, 2);
 
 	udelay(30);
 
@@ -1147,7 +1099,7 @@
 	wb_data[1] = ((params->mac_addr[0] << 8) |
 			params->mac_addr[1]);
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_SOURCE_ADDR,
-			wb_data, 2);
+		    wb_data, 2);
 
 	udelay(30);
 
@@ -1155,27 +1107,24 @@
 	wb_data[0] = 0x1000200;
 	wb_data[1] = 0;
 	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_LLFC_MSG_FLDS,
-			wb_data, 2);
+		    wb_data, 2);
 	udelay(30);
 
 	/* set rx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_RX_MAX_SIZE, wb_data, 2);
 	udelay(30);
 
 	/* set tx mtu */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_TX_MAX_SIZE, wb_data, 2);
 	udelay(30);
 	/* set cnt max size */
 	wb_data[0] = ETH_MAX_JUMBO_PACKET_SIZE + ETH_OVREHEAD - 2;
 	wb_data[1] = 0;
-	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE,
-			wb_data, 2);
+	REG_WR_DMAE(bp, bmac_addr + BIGMAC2_REGISTER_CNT_MAX_SIZE, wb_data, 2);
 	udelay(30);
 	bnx2x_update_pfc_bmac2(params, vars, is_lb);
 
@@ -1191,11 +1140,11 @@
 	u32 val;
 	/* reset and unreset the BigMac */
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
-		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 	msleep(1);
 
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_SET,
-		     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 
 	/* enable access for bmac registers */
 	REG_WR(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4, 0x1);
@@ -1230,15 +1179,14 @@
 	struct bnx2x *bp = params->bp;
 
 	REG_WR(bp, params->shmem_base +
-		   offsetof(struct shmem_region,
-			    port_mb[params->port].link_status),
-			link_status);
+	       offsetof(struct shmem_region,
+			port_mb[params->port].link_status), link_status);
 }
 
 static void bnx2x_bmac_rx_disable(struct bnx2x *bp, u8 port)
 {
 	u32 bmac_addr = port ? NIG_REG_INGRESS_BMAC1_MEM :
-		NIG_REG_INGRESS_BMAC0_MEM;
+			NIG_REG_INGRESS_BMAC0_MEM;
 	u32 wb_data[2];
 	u32 nig_bmac_enable = REG_RD(bp, NIG_REG_BMAC0_REGS_OUT_EN + port*4);
 
@@ -1250,12 +1198,12 @@
 		if (CHIP_IS_E2(bp)) {
 			/* Clear Rx Enable bit in BMAC_CONTROL register */
 			REG_RD_DMAE(bp, bmac_addr +
-					BIGMAC2_REGISTER_BMAC_CONTROL,
-					wb_data, 2);
+				    BIGMAC2_REGISTER_BMAC_CONTROL,
+				    wb_data, 2);
 			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
 			REG_WR_DMAE(bp, bmac_addr +
-					BIGMAC2_REGISTER_BMAC_CONTROL,
-					wb_data, 2);
+				    BIGMAC2_REGISTER_BMAC_CONTROL,
+				    wb_data, 2);
 		} else {
 			/* Clear Rx Enable bit in BMAC_CONTROL register */
 			REG_RD_DMAE(bp, bmac_addr +
@@ -1271,7 +1219,7 @@
 }
 
 static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl,
-			 u32 line_speed)
+			   u32 line_speed)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
@@ -1308,7 +1256,7 @@
 		/* update threshold */
 		REG_WR(bp, PBF_REG_P0_ARB_THRSH + port*4, 0);
 		/* update init credit */
-		init_crd = 778; 	/* (800-18-4) */
+		init_crd = 778;		/* (800-18-4) */
 
 	} else {
 		u32 thresh = (ETH_MAX_JUMBO_PACKET_SIZE +
@@ -1353,6 +1301,23 @@
 	return 0;
 }
 
+/*
+ * get_emac_base
+ *
+ * @param cb
+ * @param mdc_mdio_access
+ * @param port
+ *
+ * @return u32
+ *
+ * This function selects the MDC/MDIO access (through emac0 or
+ * emac1) depend on the mdc_mdio_access, port, port swapped. Each
+ * phy has a default access mode, which could also be overridden
+ * by nvram configuration. This parameter, whether this is the
+ * default phy configuration, or the nvram overrun
+ * configuration, is passed here as mdc_mdio_access and selects
+ * the emac_base for the CL45 read/writes operations
+ */
 static u32 bnx2x_get_emac_base(struct bnx2x *bp,
 			       u32 mdc_mdio_access, u8 port)
 {
@@ -1385,13 +1350,16 @@
 
 }
 
-u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
-		    u8 devad, u16 reg, u16 val)
+/******************************************************************/
+/*			CL45 access functions			  */
+/******************************************************************/
+static u8 bnx2x_cl45_write(struct bnx2x *bp, struct bnx2x_phy *phy,
+			   u8 devad, u16 reg, u16 val)
 {
 	u32 tmp, saved_mode;
 	u8 i, rc = 0;
-
-	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	/*
+	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
 	 * (a value of 49==0x31) and make sure that the AUTO poll is off
 	 */
 
@@ -1414,8 +1382,7 @@
 	for (i = 0; i < 50; i++) {
 		udelay(10);
 
-		tmp = REG_RD(bp, phy->mdio_ctrl +
-				   EMAC_REG_EMAC_MDIO_COMM);
+		tmp = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_COMM);
 		if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 			udelay(5);
 			break;
@@ -1423,6 +1390,7 @@
 	}
 	if (tmp & EMAC_MDIO_COMM_START_BUSY) {
 		DP(NETIF_MSG_LINK, "write phy register failed\n");
+		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		rc = -EFAULT;
 	} else {
 		/* data */
@@ -1435,7 +1403,7 @@
 			udelay(10);
 
 			tmp = REG_RD(bp, phy->mdio_ctrl +
-					 EMAC_REG_EMAC_MDIO_COMM);
+				     EMAC_REG_EMAC_MDIO_COMM);
 			if (!(tmp & EMAC_MDIO_COMM_START_BUSY)) {
 				udelay(5);
 				break;
@@ -1443,6 +1411,7 @@
 		}
 		if (tmp & EMAC_MDIO_COMM_START_BUSY) {
 			DP(NETIF_MSG_LINK, "write phy register failed\n");
+			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 			rc = -EFAULT;
 		}
 	}
@@ -1453,20 +1422,20 @@
 	return rc;
 }
 
-u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
-		   u8 devad, u16 reg, u16 *ret_val)
+static u8 bnx2x_cl45_read(struct bnx2x *bp, struct bnx2x_phy *phy,
+			  u8 devad, u16 reg, u16 *ret_val)
 {
 	u32 val, saved_mode;
 	u16 i;
 	u8 rc = 0;
-
-	/* set clause 45 mode, slow down the MDIO clock to 2.5MHz
+	/*
+	 * Set clause 45 mode, slow down the MDIO clock to 2.5MHz
 	 * (a value of 49==0x31) and make sure that the AUTO poll is off
 	 */
 
 	saved_mode = REG_RD(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE);
 	val = saved_mode & ~((EMAC_MDIO_MODE_AUTO_POLL |
-			     EMAC_MDIO_MODE_CLOCK_CNT));
+			      EMAC_MDIO_MODE_CLOCK_CNT));
 	val |= (EMAC_MDIO_MODE_CLAUSE_45 |
 		(49L << EMAC_MDIO_MODE_CLOCK_CNT_BITSHIFT));
 	REG_WR(bp, phy->mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE, val);
@@ -1490,7 +1459,7 @@
 	}
 	if (val & EMAC_MDIO_COMM_START_BUSY) {
 		DP(NETIF_MSG_LINK, "read phy register failed\n");
-
+		netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 		*ret_val = 0;
 		rc = -EFAULT;
 
@@ -1505,7 +1474,7 @@
 			udelay(10);
 
 			val = REG_RD(bp, phy->mdio_ctrl +
-					  EMAC_REG_EMAC_MDIO_COMM);
+				     EMAC_REG_EMAC_MDIO_COMM);
 			if (!(val & EMAC_MDIO_COMM_START_BUSY)) {
 				*ret_val = (u16)(val & EMAC_MDIO_COMM_DATA);
 				break;
@@ -1513,7 +1482,7 @@
 		}
 		if (val & EMAC_MDIO_COMM_START_BUSY) {
 			DP(NETIF_MSG_LINK, "read phy register failed\n");
-
+			netdev_err(bp->dev,  "MDC/MDIO access timeout\n");
 			*ret_val = 0;
 			rc = -EFAULT;
 		}
@@ -1529,7 +1498,7 @@
 		  u8 devad, u16 reg, u16 *ret_val)
 {
 	u8 phy_index;
-	/**
+	/*
 	 * Probe for the phy according to the given phy_addr, and execute
 	 * the read request on it
 	 */
@@ -1547,7 +1516,7 @@
 		   u8 devad, u16 reg, u16 val)
 {
 	u8 phy_index;
-	/**
+	/*
 	 * Probe for the phy according to the given phy_addr, and execute
 	 * the write request on it
 	 */
@@ -1576,16 +1545,15 @@
 		aer_val = 0x3800 + offset - 1;
 	else
 		aer_val = 0x3800 + offset;
-	CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_AER_BLOCK,
-				MDIO_AER_BLOCK_AER_REG, aer_val);
+	CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, aer_val);
 }
 static void bnx2x_set_aer_mmd_serdes(struct bnx2x *bp,
 				     struct bnx2x_phy *phy)
 {
-	CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_AER_BLOCK,
-				MDIO_AER_BLOCK_AER_REG, 0x3800);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_AER_BLOCK,
+			  MDIO_AER_BLOCK_AER_REG, 0x3800);
 }
 
 /******************************************************************/
@@ -1621,9 +1589,8 @@
 
 	bnx2x_set_serdes_access(bp, port);
 
-	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD +
-		     port*0x10,
-		     DEFAULT_PHY_DEV_ADDR);
+	REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + port*0x10,
+	       DEFAULT_PHY_DEV_ADDR);
 }
 
 static void bnx2x_xgxs_deassert(struct link_params *params)
@@ -1641,23 +1608,22 @@
 	udelay(500);
 	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val);
 
-	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST +
-		     port*0x18, 0);
+	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + port*0x18, 0);
 	REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-		     params->phy[INT_PHY].def_md_devad);
+	       params->phy[INT_PHY].def_md_devad);
 }
 
 
 void bnx2x_link_status_update(struct link_params *params,
-			    struct link_vars   *vars)
+			      struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u8 link_10g;
 	u8 port = params->port;
 
 	vars->link_status = REG_RD(bp, params->shmem_base +
-					  offsetof(struct shmem_region,
-					   port_mb[port].link_status));
+				   offsetof(struct shmem_region,
+					    port_mb[port].link_status));
 
 	vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP);
 
@@ -1667,7 +1633,7 @@
 		vars->phy_link_up = 1;
 		vars->duplex = DUPLEX_FULL;
 		switch (vars->link_status &
-					LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
+			LINK_STATUS_SPEED_AND_DUPLEX_MASK) {
 			case LINK_10THD:
 				vars->duplex = DUPLEX_HALF;
 				/* fall thru */
@@ -1779,20 +1745,20 @@
 {
 	struct bnx2x *bp = params->bp;
 	u16 new_master_ln, ser_lane;
-	ser_lane =  ((params->lane_config &
+	ser_lane = ((params->lane_config &
 		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 
 	/* set the master_ln for AN */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_XGXS_BLOCK2,
-			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
-			      &new_master_ln);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_XGXS_BLOCK2,
+			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
+			  &new_master_ln);
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_XGXS_BLOCK2 ,
-			      MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
-			      (new_master_ln | ser_lane));
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_XGXS_BLOCK2 ,
+			  MDIO_XGXS_BLOCK2_TEST_MODE_LANE,
+			  (new_master_ln | ser_lane));
 }
 
 static u8 bnx2x_reset_unicore(struct link_params *params,
@@ -1802,17 +1768,16 @@
 	struct bnx2x *bp = params->bp;
 	u16 mii_control;
 	u16 i;
-
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, &mii_control);
 
 	/* reset the unicore */
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL,
-			      (mii_control |
-			       MDIO_COMBO_IEEO_MII_CONTROL_RESET));
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL,
+			  (mii_control |
+			   MDIO_COMBO_IEEO_MII_CONTROL_RESET));
 	if (set_serdes)
 		bnx2x_set_serdes_access(bp, params->port);
 
@@ -1821,10 +1786,10 @@
 		udelay(5);
 
 		/* the reset erased the previous bank value */
-		CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL,
-			      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  &mii_control);
 
 		if (!(mii_control & MDIO_COMBO_IEEO_MII_CONTROL_RESET)) {
 			udelay(5);
@@ -1832,6 +1797,9 @@
 		}
 	}
 
+	netdev_err(bp->dev,  "Warning: PHY was not initialized,"
+			      " Port %d\n",
+			 params->port);
 	DP(NETIF_MSG_LINK, "BUG! XGXS is still in reset!\n");
 	return -EINVAL;
 
@@ -1841,43 +1809,45 @@
 				 struct bnx2x_phy *phy)
 {
 	struct bnx2x *bp = params->bp;
-	/* Each two bits represents a lane number:
-	   No swap is 0123 => 0x1b no need to enable the swap */
+	/*
+	 *  Each two bits represents a lane number:
+	 *  No swap is 0123 => 0x1b no need to enable the swap
+	 */
 	u16 ser_lane, rx_lane_swap, tx_lane_swap;
 
 	ser_lane = ((params->lane_config &
-			 PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
-			PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
+		     PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
+		    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT);
 	rx_lane_swap = ((params->lane_config &
-			     PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
-			    PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
+			 PORT_HW_CFG_LANE_SWAP_CFG_RX_MASK) >>
+			PORT_HW_CFG_LANE_SWAP_CFG_RX_SHIFT);
 	tx_lane_swap = ((params->lane_config &
-			     PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
-			    PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
+			 PORT_HW_CFG_LANE_SWAP_CFG_TX_MASK) >>
+			PORT_HW_CFG_LANE_SWAP_CFG_TX_SHIFT);
 
 	if (rx_lane_swap != 0x1b) {
-		CL45_WR_OVER_CL22(bp, phy,
-				    MDIO_REG_BANK_XGXS_BLOCK2,
-				    MDIO_XGXS_BLOCK2_RX_LN_SWAP,
-				    (rx_lane_swap |
-				    MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
-				    MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_RX_LN_SWAP,
+				  (rx_lane_swap |
+				   MDIO_XGXS_BLOCK2_RX_LN_SWAP_ENABLE |
+				   MDIO_XGXS_BLOCK2_RX_LN_SWAP_FORCE_ENABLE));
 	} else {
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_XGXS_BLOCK2,
-				      MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_RX_LN_SWAP, 0);
 	}
 
 	if (tx_lane_swap != 0x1b) {
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_XGXS_BLOCK2,
-				      MDIO_XGXS_BLOCK2_TX_LN_SWAP,
-				      (tx_lane_swap |
-				       MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_TX_LN_SWAP,
+				  (tx_lane_swap |
+				   MDIO_XGXS_BLOCK2_TX_LN_SWAP_ENABLE));
 	} else {
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_XGXS_BLOCK2,
-				      MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_TX_LN_SWAP, 0);
 	}
 }
 
@@ -1886,66 +1856,66 @@
 {
 	struct bnx2x *bp = params->bp;
 	u16 control2;
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
-			      &control2);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
+			  &control2);
 	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
 		control2 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
 	else
 		control2 &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL2_PRL_DT_EN;
 	DP(NETIF_MSG_LINK, "phy->speed_cap_mask = 0x%x, control2 = 0x%x\n",
 		phy->speed_cap_mask, control2);
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
-			      control2);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL2,
+			  control2);
 
 	if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) &&
 	     (phy->speed_cap_mask &
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) {
 		DP(NETIF_MSG_LINK, "XGXS\n");
 
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_10G_PARALLEL_DETECT,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
+		CL22_WR_OVER_CL45(bp, phy,
+				 MDIO_REG_BANK_10G_PARALLEL_DETECT,
+				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK,
+				 MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_LINK_CNT);
 
-		CL45_RD_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_10G_PARALLEL_DETECT,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
-				&control2);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_10G_PARALLEL_DETECT,
+				  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
+				  &control2);
 
 
 		control2 |=
 		    MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL_PARDET10G_EN;
 
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_10G_PARALLEL_DETECT,
-				MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
-				control2);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_10G_PARALLEL_DETECT,
+				  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_CONTROL,
+				  control2);
 
 		/* Disable parallel detection of HiG */
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_XGXS_BLOCK2,
-				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
-				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
-				MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_XGXS_BLOCK2,
+				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G,
+				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_CX4_XGXS |
+				  MDIO_XGXS_BLOCK2_UNICORE_MODE_10G_HIGIG_XGXS);
 	}
 }
 
 static void bnx2x_set_autoneg(struct bnx2x_phy *phy,
 			      struct link_params *params,
-			    struct link_vars *vars,
-			    u8 enable_cl73)
+			      struct link_vars *vars,
+			      u8 enable_cl73)
 {
 	struct bnx2x *bp = params->bp;
 	u16 reg_val;
 
 	/* CL37 Autoneg */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
 
 	/* CL37 Autoneg Enabled */
 	if (vars->line_speed == SPEED_AUTO_NEG)
@@ -1954,15 +1924,15 @@
 		reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 			     MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN);
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
 
 	/* Enable/Disable Autodetection */
 
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_val);
 	reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN |
 		    MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT);
 	reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE;
@@ -1971,14 +1941,14 @@
 	else
 		reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET;
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, reg_val);
 
 	/* Enable TetonII and BAM autoneg */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_BAM_NEXT_PAGE,
-			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_BAM_NEXT_PAGE,
+			  MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
 			  &reg_val);
 	if (vars->line_speed == SPEED_AUTO_NEG) {
 		/* Enable BAM aneg Mode and TetonII aneg Mode */
@@ -1989,20 +1959,20 @@
 		reg_val &= ~(MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_BAM_MODE |
 			     MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL_TETON_AN);
 	}
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_BAM_NEXT_PAGE,
-			      MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
-			      reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_BAM_NEXT_PAGE,
+			  MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL,
+			  reg_val);
 
 	if (enable_cl73) {
 		/* Enable Cl73 FSM status bits */
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_CL73_USERB0,
-				    MDIO_CL73_USERB0_CL73_UCTRL,
-				      0xe);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_USERB0,
+				  MDIO_CL73_USERB0_CL73_UCTRL,
+				  0xe);
 
 		/* Enable BAM Station Manager*/
-		CL45_WR_OVER_CL22(bp, phy,
+		CL22_WR_OVER_CL45(bp, phy,
 			MDIO_REG_BANK_CL73_USERB0,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1,
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN |
@@ -2010,10 +1980,10 @@
 			MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN);
 
 		/* Advertise CL73 link speeds */
-		CL45_RD_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_CL73_IEEEB1,
-					      MDIO_CL73_IEEEB1_AN_ADV2,
-					      &reg_val);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB1,
+				  MDIO_CL73_IEEEB1_AN_ADV2,
+				  &reg_val);
 		if (phy->speed_cap_mask &
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4;
@@ -2021,10 +1991,10 @@
 		    PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
 			reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX;
 
-		CL45_WR_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_CL73_IEEEB1,
-					      MDIO_CL73_IEEEB1_AN_ADV2,
-				      reg_val);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB1,
+				  MDIO_CL73_IEEEB1_AN_ADV2,
+				  reg_val);
 
 		/* CL73 Autoneg Enabled */
 		reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN;
@@ -2032,37 +2002,39 @@
 	} else /* CL73 Autoneg Disabled */
 		reg_val = 0;
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB0,
-			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB0,
+			  MDIO_CL73_IEEEB0_CL73_AN_CONTROL, reg_val);
 }
 
 /* program SerDes, forced speed */
 static void bnx2x_program_serdes(struct bnx2x_phy *phy,
 				 struct link_params *params,
-			       struct link_vars *vars)
+				 struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 reg_val;
 
 	/* program duplex, disable autoneg and sgmii*/
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, &reg_val);
 	reg_val &= ~(MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX |
 		     MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 		     MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK);
 	if (phy->req_duplex == DUPLEX_FULL)
 		reg_val |= MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_MII_CONTROL, reg_val);
 
-	/* program speed
-	   - needed only if the speed is greater than 1G (2.5G or 10G) */
-	CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_SERDES_DIGITAL,
-				      MDIO_SERDES_DIGITAL_MISC1, &reg_val);
+	/*
+	 * program speed
+	 *  - needed only if the speed is greater than 1G (2.5G or 10G)
+	 */
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_MISC1, &reg_val);
 	/* clearing the speed value before setting the right speed */
 	DP(NETIF_MSG_LINK, "MDIO_REG_BANK_SERDES_DIGITAL = 0x%x\n", reg_val);
 
@@ -2083,9 +2055,9 @@
 				MDIO_SERDES_DIGITAL_MISC1_FORCE_SPEED_13G;
 	}
 
-	CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_SERDES_DIGITAL,
-				      MDIO_SERDES_DIGITAL_MISC1, reg_val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_MISC1, reg_val);
 
 }
 
@@ -2102,13 +2074,13 @@
 		val |= MDIO_OVER_1G_UP1_2_5G;
 	if (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 		val |= MDIO_OVER_1G_UP1_10G;
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_OVER_1G,
-			      MDIO_OVER_1G_UP1, val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_OVER_1G,
+			  MDIO_OVER_1G_UP1, val);
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_OVER_1G,
-			      MDIO_OVER_1G_UP3, 0x400);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_OVER_1G,
+			  MDIO_OVER_1G_UP3, 0x400);
 }
 
 static void bnx2x_calc_ieee_aneg_adv(struct bnx2x_phy *phy,
@@ -2116,22 +2088,21 @@
 {
 	struct bnx2x *bp = params->bp;
 	*ieee_fc = MDIO_COMBO_IEEE0_AUTO_NEG_ADV_FULL_DUPLEX;
-	/* resolve pause mode and advertisement
-	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec */
+	/*
+	 * Resolve pause mode and advertisement.
+	 * Please refer to Table 28B-3 of the 802.3ab-1999 spec
+	 */
 
 	switch (phy->req_flow_ctrl) {
 	case BNX2X_FLOW_CTRL_AUTO:
-		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH) {
-			*ieee_fc |=
-			     MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
-		} else {
+		if (params->req_fc_auto_adv == BNX2X_FLOW_CTRL_BOTH)
+			*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+		else
 			*ieee_fc |=
-		       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
-		}
+			MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
 		break;
 	case BNX2X_FLOW_CTRL_TX:
-		*ieee_fc |=
-		       MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+		*ieee_fc |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
 		break;
 
 	case BNX2X_FLOW_CTRL_RX:
@@ -2149,23 +2120,23 @@
 
 static void bnx2x_set_ieee_aneg_advertisment(struct bnx2x_phy *phy,
 					     struct link_params *params,
-					   u16 ieee_fc)
+					     u16 ieee_fc)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val;
 	/* for AN, we are always publishing full duplex */
 
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_COMBO_IEEE0,
-			      MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB1,
-			      MDIO_CL73_IEEEB1_AN_ADV1, &val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_COMBO_IEEE0,
+			  MDIO_COMBO_IEEE0_AUTO_NEG_ADV, ieee_fc);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB1,
+			  MDIO_CL73_IEEEB1_AN_ADV1, &val);
 	val &= ~MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_BOTH;
 	val |= ((ieee_fc<<3) & MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK);
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB1,
-			      MDIO_CL73_IEEEB1_AN_ADV1, val);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB1,
+			  MDIO_CL73_IEEEB1_AN_ADV1, val);
 }
 
 static void bnx2x_restart_autoneg(struct bnx2x_phy *phy,
@@ -2179,67 +2150,67 @@
 	/* Enable and restart BAM/CL37 aneg */
 
 	if (enable_cl73) {
-		CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_CL73_IEEEB0,
-				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB0,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+				  &mii_control);
 
-		CL45_WR_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_CL73_IEEEB0,
-				MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				(mii_control |
-				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
-				MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB0,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+				  (mii_control |
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN |
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN));
 	} else {
 
-		CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  &mii_control);
 		DP(NETIF_MSG_LINK,
 			 "bnx2x_restart_autoneg mii_control before = 0x%x\n",
 			 mii_control);
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      (mii_control |
-				       MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
-				       MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  (mii_control |
+				   MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
+				   MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN));
 	}
 }
 
 static void bnx2x_initialize_sgmii_process(struct bnx2x_phy *phy,
 					   struct link_params *params,
-					 struct link_vars *vars)
+					   struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
 	u16 control1;
 
 	/* in SGMII mode, the unicore is always slave */
 
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
-		      &control1);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
+			  &control1);
 	control1 |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT;
 	/* set sgmii mode (and not fiber) */
 	control1 &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE |
 		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET |
 		      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_MSTR_MODE);
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
-			      control1);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_CONTROL1,
+			  control1);
 
 	/* if forced speed */
 	if (!(vars->line_speed == SPEED_AUTO_NEG)) {
 		/* set speed, disable autoneg */
 		u16 mii_control;
 
-		CL45_RD_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      &mii_control);
+		CL22_RD_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  &mii_control);
 		mii_control &= ~(MDIO_COMBO_IEEO_MII_CONTROL_AN_EN |
 				 MDIO_COMBO_IEEO_MII_CONTROL_MAN_SGMII_SP_MASK|
 				 MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX);
@@ -2267,10 +2238,10 @@
 		if (phy->req_duplex == DUPLEX_FULL)
 			mii_control |=
 				MDIO_COMBO_IEEO_MII_CONTROL_FULL_DUPLEX;
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_COMBO_IEEE0,
-				      MDIO_COMBO_IEEE0_MII_CONTROL,
-				      mii_control);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_COMBO_IEEE0,
+				  MDIO_COMBO_IEEE0_MII_CONTROL,
+				  mii_control);
 
 	} else { /* AN mode */
 		/* enable and restart AN */
@@ -2285,19 +2256,19 @@
 
 static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result)
 {						/*  LD	    LP	 */
-	switch (pause_result) { 		/* ASYM P ASYM P */
-	case 0xb:       			/*   1  0   1  1 */
+	switch (pause_result) {			/* ASYM P ASYM P */
+	case 0xb:				/*   1  0   1  1 */
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_TX;
 		break;
 
-	case 0xe:       			/*   1  1   1  0 */
+	case 0xe:				/*   1  1   1  0 */
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_RX;
 		break;
 
-	case 0x5:       			/*   0  1   0  1 */
-	case 0x7:       			/*   0  1   1  1 */
-	case 0xd:       			/*   1  1   0  1 */
-	case 0xf:       			/*   1  1   1  1 */
+	case 0x5:				/*   0  1   0  1 */
+	case 0x7:				/*   0  1   1  1 */
+	case 0xd:				/*   1  1   0  1 */
+	case 0xf:				/*   1  1   1  1 */
 		vars->flow_ctrl = BNX2X_FLOW_CTRL_BOTH;
 		break;
 
@@ -2317,24 +2288,24 @@
 	u16 pd_10g, status2_1000x;
 	if (phy->req_line_speed != SPEED_AUTO_NEG)
 		return 0;
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
-			      &status2_1000x);
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_SERDES_DIGITAL,
-			      MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
-			      &status2_1000x);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
+			  &status2_1000x);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_SERDES_DIGITAL,
+			  MDIO_SERDES_DIGITAL_A_1000X_STATUS2,
+			  &status2_1000x);
 	if (status2_1000x & MDIO_SERDES_DIGITAL_A_1000X_STATUS2_AN_DISABLED) {
 		DP(NETIF_MSG_LINK, "1G parallel detect link on port %d\n",
 			 params->port);
 		return 1;
 	}
 
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_10G_PARALLEL_DETECT,
-			      MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
-			      &pd_10g);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_10G_PARALLEL_DETECT,
+			  MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS,
+			  &pd_10g);
 
 	if (pd_10g & MDIO_10G_PARALLEL_DETECT_PAR_DET_10G_STATUS_PD_LINK) {
 		DP(NETIF_MSG_LINK, "10G parallel detect link on port %d\n",
@@ -2373,14 +2344,14 @@
 		    (MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_AUTONEG_COMPLETE |
 		     MDIO_GP_STATUS_TOP_AN_STATUS1_CL73_MR_LP_NP_AN_ABLE)) {
 
-			CL45_RD_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_CL73_IEEEB1,
-					      MDIO_CL73_IEEEB1_AN_ADV1,
-					      &ld_pause);
-			CL45_RD_OVER_CL22(bp, phy,
-					     MDIO_REG_BANK_CL73_IEEEB1,
-					     MDIO_CL73_IEEEB1_AN_LP_ADV1,
-					     &lp_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+					  MDIO_REG_BANK_CL73_IEEEB1,
+					  MDIO_CL73_IEEEB1_AN_ADV1,
+					  &ld_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+					  MDIO_REG_BANK_CL73_IEEEB1,
+					  MDIO_CL73_IEEEB1_AN_LP_ADV1,
+					  &lp_pause);
 			pause_result = (ld_pause &
 					MDIO_CL73_IEEEB1_AN_ADV1_PAUSE_MASK)
 					>> 8;
@@ -2390,18 +2361,18 @@
 			DP(NETIF_MSG_LINK, "pause_result CL73 0x%x\n",
 				 pause_result);
 		} else {
-			CL45_RD_OVER_CL22(bp, phy,
-					      MDIO_REG_BANK_COMBO_IEEE0,
-					      MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
-					      &ld_pause);
-			CL45_RD_OVER_CL22(bp, phy,
-			       MDIO_REG_BANK_COMBO_IEEE0,
-			       MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
-			       &lp_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+					  MDIO_REG_BANK_COMBO_IEEE0,
+					  MDIO_COMBO_IEEE0_AUTO_NEG_ADV,
+					  &ld_pause);
+			CL22_RD_OVER_CL45(bp, phy,
+				MDIO_REG_BANK_COMBO_IEEE0,
+				MDIO_COMBO_IEEE0_AUTO_NEG_LINK_PARTNER_ABILITY1,
+				&lp_pause);
 			pause_result = (ld_pause &
 				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>5;
 			pause_result |= (lp_pause &
-				 MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
+				MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_MASK)>>7;
 			DP(NETIF_MSG_LINK, "pause_result CL37 0x%x\n",
 				 pause_result);
 		}
@@ -2417,25 +2388,25 @@
 	u16 rx_status, ustat_val, cl37_fsm_recieved;
 	DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n");
 	/* Step 1: Make sure signal is detected */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_RX0,
-			      MDIO_RX0_RX_STATUS,
-			      &rx_status);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_RX0,
+			  MDIO_RX0_RX_STATUS,
+			  &rx_status);
 	if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) !=
 	    (MDIO_RX0_RX_STATUS_SIGDET)) {
 		DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73."
 			     "rx_status(0x80b0) = 0x%x\n", rx_status);
-		CL45_WR_OVER_CL22(bp, phy,
-				      MDIO_REG_BANK_CL73_IEEEB0,
-				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-				      MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
+		CL22_WR_OVER_CL45(bp, phy,
+				  MDIO_REG_BANK_CL73_IEEEB0,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+				  MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN);
 		return;
 	}
 	/* Step 2: Check CL73 state machine */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_USERB0,
-			      MDIO_CL73_USERB0_CL73_USTAT1,
-			      &ustat_val);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_USERB0,
+			  MDIO_CL73_USERB0_CL73_USTAT1,
+			  &ustat_val);
 	if ((ustat_val &
 	     (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK |
 	      MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) !=
@@ -2445,12 +2416,14 @@
 			     "ustat_val(0x8371) = 0x%x\n", ustat_val);
 		return;
 	}
-	/* Step 3: Check CL37 Message Pages received to indicate LP
-	supports only CL37 */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_REMOTE_PHY,
-			      MDIO_REMOTE_PHY_MISC_RX_STATUS,
-			      &cl37_fsm_recieved);
+	/*
+	 * Step 3: Check CL37 Message Pages received to indicate LP
+	 * supports only CL37
+	 */
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_REMOTE_PHY,
+			  MDIO_REMOTE_PHY_MISC_RX_STATUS,
+			  &cl37_fsm_recieved);
 	if ((cl37_fsm_recieved &
 	     (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG |
 	     MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) !=
@@ -2461,14 +2434,18 @@
 			 cl37_fsm_recieved);
 		return;
 	}
-	/* The combined cl37/cl73 fsm state information indicating that we are
-	connected to a device which does not support cl73, but does support
-	cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */
+	/*
+	 * The combined cl37/cl73 fsm state information indicating that
+	 * we are connected to a device which does not support cl73, but
+	 * does support cl37 BAM. In this case we disable cl73 and
+	 * restart cl37 auto-neg
+	 */
+
 	/* Disable CL73 */
-	CL45_WR_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_CL73_IEEEB0,
-			      MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
-			      0);
+	CL22_WR_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_CL73_IEEEB0,
+			  MDIO_CL73_IEEEB0_CL73_AN_CONTROL,
+			  0);
 	/* Restart CL37 autoneg */
 	bnx2x_restart_autoneg(phy, params, 0);
 	DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n");
@@ -2493,14 +2470,14 @@
 				     struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 new_line_speed , gp_status;
+	u16 new_line_speed, gp_status;
 	u8 rc = 0;
 
 	/* Read gp_status */
-	CL45_RD_OVER_CL22(bp, phy,
-				MDIO_REG_BANK_GP_STATUS,
-				MDIO_GP_STATUS_TOP_AN_STATUS1,
-				&gp_status);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_GP_STATUS,
+			  MDIO_GP_STATUS_TOP_AN_STATUS1,
+			  &gp_status);
 
 	if (phy->req_line_speed == SPEED_AUTO_NEG)
 		vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_ENABLED;
@@ -2637,9 +2614,9 @@
 	u16 bank;
 
 	/* read precomp */
-	CL45_RD_OVER_CL22(bp, phy,
-			      MDIO_REG_BANK_OVER_1G,
-			      MDIO_OVER_1G_LP_UP2, &lp_up2);
+	CL22_RD_OVER_CL45(bp, phy,
+			  MDIO_REG_BANK_OVER_1G,
+			  MDIO_OVER_1G_LP_UP2, &lp_up2);
 
 	/* bits [10:7] at lp_up2, positioned at [15:12] */
 	lp_up2 = (((lp_up2 & MDIO_OVER_1G_LP_UP2_PREEMPHASIS_MASK) >>
@@ -2651,18 +2628,18 @@
 
 	for (bank = MDIO_REG_BANK_TX0; bank <= MDIO_REG_BANK_TX3;
 	      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0)) {
-		CL45_RD_OVER_CL22(bp, phy,
-				      bank,
-				      MDIO_TX0_TX_DRIVER, &tx_driver);
+		CL22_RD_OVER_CL45(bp, phy,
+				  bank,
+				  MDIO_TX0_TX_DRIVER, &tx_driver);
 
 		/* replace tx_driver bits [15:12] */
 		if (lp_up2 !=
 		    (tx_driver & MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK)) {
 			tx_driver &= ~MDIO_TX0_TX_DRIVER_PREEMPHASIS_MASK;
 			tx_driver |= lp_up2;
-			CL45_WR_OVER_CL22(bp, phy,
-					      bank,
-					      MDIO_TX0_TX_DRIVER, tx_driver);
+			CL22_WR_OVER_CL45(bp, phy,
+					  bank,
+					  MDIO_TX0_TX_DRIVER, tx_driver);
 		}
 	}
 }
@@ -2676,10 +2653,10 @@
 
 	DP(NETIF_MSG_LINK, "setting link speed & duplex\n");
 	bnx2x_bits_dis(bp, GRCBASE_EMAC0 + port*0x400 +
-		     EMAC_REG_EMAC_MODE,
-		     (EMAC_MODE_25G_MODE |
-		     EMAC_MODE_PORT_MII_10M |
-		     EMAC_MODE_HALF_DUPLEX));
+		       EMAC_REG_EMAC_MODE,
+		       (EMAC_MODE_25G_MODE |
+			EMAC_MODE_PORT_MII_10M |
+			EMAC_MODE_HALF_DUPLEX));
 	switch (vars->line_speed) {
 	case SPEED_10:
 		mode |= EMAC_MODE_PORT_MII_10M;
@@ -2707,8 +2684,8 @@
 	if (vars->duplex == DUPLEX_HALF)
 		mode |= EMAC_MODE_HALF_DUPLEX;
 	bnx2x_bits_en(bp,
-		    GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
-		    mode);
+		      GRCBASE_EMAC0 + port*0x400 + EMAC_REG_EMAC_MODE,
+		      mode);
 
 	bnx2x_set_led(params, vars, LED_MODE_OPER, vars->line_speed);
 	return 0;
@@ -2723,7 +2700,7 @@
 
 	for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3;
 	      bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) {
-			CL45_WR_OVER_CL22(bp, phy,
+			CL22_WR_OVER_CL45(bp, phy,
 					  bank,
 					  MDIO_RX0_RX_EQ_BOOST,
 					  phy->rx_preemphasis[i]);
@@ -2731,7 +2708,7 @@
 
 	for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3;
 		      bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) {
-			CL45_WR_OVER_CL22(bp, phy,
+			CL22_WR_OVER_CL45(bp, phy,
 					  bank,
 					  MDIO_TX0_TX_DRIVER,
 					  phy->tx_preemphasis[i]);
@@ -2754,7 +2731,7 @@
 		/* forced speed requested? */
 		if (vars->line_speed != SPEED_AUTO_NEG ||
 		    (SINGLE_MEDIA_DIRECT(params) &&
-			  params->loopback_mode == LOOPBACK_EXT)) {
+		     params->loopback_mode == LOOPBACK_EXT)) {
 			DP(NETIF_MSG_LINK, "not SGMII, no AN\n");
 
 			/* disable autoneg */
@@ -2771,7 +2748,7 @@
 
 			/* program duplex & pause advertisement (for aneg) */
 			bnx2x_set_ieee_aneg_advertisment(phy, params,
-						       vars->ieee_fc);
+							 vars->ieee_fc);
 
 			/* enable autoneg */
 			bnx2x_set_autoneg(phy, params, vars, enable_cl73);
@@ -2842,10 +2819,11 @@
 }
 
 static u16 bnx2x_wait_reset_complete(struct bnx2x *bp,
-				     struct bnx2x_phy *phy)
+				     struct bnx2x_phy *phy,
+				     struct link_params *params)
 {
 	u16 cnt, ctrl;
-	/* Wait for soft reset to get cleared upto 1 sec */
+	/* Wait for soft reset to get cleared up to 1 sec */
 	for (cnt = 0; cnt < 1000; cnt++) {
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl);
@@ -2853,6 +2831,11 @@
 			break;
 		msleep(1);
 	}
+
+	if (cnt == 1000)
+		netdev_err(bp->dev,  "Warning: PHY was not initialized,"
+				      " Port %d\n",
+			 params->port);
 	DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt);
 	return cnt;
 }
@@ -2863,9 +2846,7 @@
 	u32 mask;
 	struct bnx2x *bp = params->bp;
 
-	/* setting the status to report on link up
-	   for either XGXS or SerDes */
-
+	/* Setting the status to report on link up for either XGXS or SerDes */
 	if (params->switch_cfg == SWITCH_CFG_10G) {
 		mask = (NIG_MASK_XGXS0_LINK10G |
 			NIG_MASK_XGXS0_LINK_STATUS);
@@ -2908,7 +2889,7 @@
 {
 	u32 latch_status = 0;
 
-	/**
+	/*
 	 * Disable the MI INT ( external phy int ) by writing 1 to the
 	 * status register. Link down indication is high-active-signal,
 	 * so in this case we need to write the status to clear the XOR
@@ -2933,27 +2914,30 @@
 
 		/* For all latched-signal=up : Re-Arm Latch signals */
 		REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8,
-			     (latch_status & 0xfffe) | (latch_status & 1));
+		       (latch_status & 0xfffe) | (latch_status & 1));
 	}
 	/* For all latched-signal=up,Write original_signal to status */
 }
 
 static void bnx2x_link_int_ack(struct link_params *params,
-			     struct link_vars *vars, u8 is_10g)
+			       struct link_vars *vars, u8 is_10g)
 {
 	struct bnx2x *bp = params->bp;
 	u8 port = params->port;
 
-	/* first reset all status
-	 * we assume only one line will be change at a time */
+	/*
+	 * First reset all status we assume only one line will be
+	 * change at a time
+	 */
 	bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
-		     (NIG_STATUS_XGXS0_LINK10G |
-		      NIG_STATUS_XGXS0_LINK_STATUS |
-		      NIG_STATUS_SERDES0_LINK_STATUS));
+		       (NIG_STATUS_XGXS0_LINK10G |
+			NIG_STATUS_XGXS0_LINK_STATUS |
+			NIG_STATUS_SERDES0_LINK_STATUS));
 	if (vars->phy_link_up) {
 		if (is_10g) {
-			/* Disable the 10G link interrupt
-			 * by writing 1 to the status register
+			/*
+			 * Disable the 10G link interrupt by writing 1 to the
+			 * status register
 			 */
 			DP(NETIF_MSG_LINK, "10G XGXS phy link up\n");
 			bnx2x_bits_en(bp,
@@ -2961,9 +2945,9 @@
 				      NIG_STATUS_XGXS0_LINK10G);
 
 		} else if (params->switch_cfg == SWITCH_CFG_10G) {
-			/* Disable the link interrupt
-			 * by writing 1 to the relevant lane
-			 * in the status register
+			/*
+			 * Disable the link interrupt by writing 1 to the
+			 * relevant lane in the status register
 			 */
 			u32 ser_lane = ((params->lane_config &
 				    PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >>
@@ -2978,8 +2962,9 @@
 
 		} else { /* SerDes */
 			DP(NETIF_MSG_LINK, "SerDes phy link up\n");
-			/* Disable the link interrupt
-			 * by writing 1 to the status register
+			/*
+			 * Disable the link interrupt by writing 1 to the status
+			 * register
 			 */
 			bnx2x_bits_en(bp,
 				      NIG_REG_STATUS_INTERRUPT_PORT0 + port*4,
@@ -3059,8 +3044,7 @@
 	}
 	if ((params->num_phys == MAX_PHYS) &&
 	    (params->phy[EXT_PHY2].ver_addr != 0)) {
-		spirom_ver = REG_RD(bp,
-					  params->phy[EXT_PHY2].ver_addr);
+		spirom_ver = REG_RD(bp, params->phy[EXT_PHY2].ver_addr);
 		if (params->phy[EXT_PHY2].format_fw_ver) {
 			*ver_p = '/';
 			ver_p++;
@@ -3089,29 +3073,27 @@
 
 		/* change the uni_phy_addr in the nig */
 		md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD +
-					  port*0x18));
+				       port*0x18));
 
 		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5);
 
 		bnx2x_cl45_write(bp, phy,
-			       5,
-			       (MDIO_REG_BANK_AER_BLOCK +
-				(MDIO_AER_BLOCK_AER_REG & 0xf)),
-			       0x2800);
+				 5,
+				 (MDIO_REG_BANK_AER_BLOCK +
+				  (MDIO_AER_BLOCK_AER_REG & 0xf)),
+				 0x2800);
 
 		bnx2x_cl45_write(bp, phy,
-			       5,
-			       (MDIO_REG_BANK_CL73_IEEEB0 +
-				(MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
-			       0x6041);
+				 5,
+				 (MDIO_REG_BANK_CL73_IEEEB0 +
+				  (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)),
+				 0x6041);
 		msleep(200);
 		/* set aer mmd back */
 		bnx2x_set_aer_mmd_xgxs(params, phy);
 
 		/* and md_devad */
-		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18,
-			    md_devad);
-
+		REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, md_devad);
 	} else {
 		u16 mii_ctrl;
 		DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n");
@@ -3152,26 +3134,26 @@
 	case LED_MODE_OFF:
 		REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0);
 		REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
-			   SHARED_HW_CFG_LED_MAC1);
+		       SHARED_HW_CFG_LED_MAC1);
 
 		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
 		EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE));
 		break;
 
 	case LED_MODE_OPER:
-		/**
+		/*
 		 * For all other phys, OPER mode is same as ON, so in case
 		 * link is down, do nothing
-		 **/
+		 */
 		if (!vars->link_up)
 			break;
 	case LED_MODE_ON:
 		if (params->phy[EXT_PHY1].type ==
 		    PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727 &&
 		    CHIP_IS_E2(bp) && params->num_phys == 2) {
-			/**
-			* This is a work-around for E2+8727 Configurations
-			*/
+			/*
+			 * This is a work-around for E2+8727 Configurations
+			 */
 			if (mode == LED_MODE_ON ||
 				speed == SPEED_10000){
 				REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
@@ -3183,41 +3165,40 @@
 				return rc;
 			}
 		} else if (SINGLE_MEDIA_DIRECT(params)) {
-			/**
-			* This is a work-around for HW issue found when link
-			* is up in CL73
-			*/
+			/*
+			 * This is a work-around for HW issue found when link
+			 * is up in CL73
+			 */
 			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0);
 			REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1);
 		} else {
-			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4,
-				   hw_led_mode);
+			REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, hw_led_mode);
 		}
 
-		REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 +
-			   port*4, 0);
+		REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + port*4, 0);
 		/* Set blinking rate to ~15.9Hz */
 		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4,
-			   LED_BLINK_RATE_VAL);
+		       LED_BLINK_RATE_VAL);
 		REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 +
-			   port*4, 1);
+		       port*4, 1);
 		tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED);
-		EMAC_WR(bp, EMAC_REG_EMAC_LED,
-			    (tmp & (~EMAC_LED_OVERRIDE)));
+		EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp & (~EMAC_LED_OVERRIDE)));
 
 		if (CHIP_IS_E1(bp) &&
 		    ((speed == SPEED_2500) ||
 		     (speed == SPEED_1000) ||
 		     (speed == SPEED_100) ||
 		     (speed == SPEED_10))) {
-			/* On Everest 1 Ax chip versions for speeds less than
-			10G LED scheme is different */
+			/*
+			 * On Everest 1 Ax chip versions for speeds less than
+			 * 10G LED scheme is different
+			 */
 			REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0
-				   + port*4, 1);
+			       + port*4, 1);
 			REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 +
-				   port*4, 0);
+			       port*4, 0);
 			REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 +
-				   port*4, 1);
+			       port*4, 1);
 		}
 		break;
 
@@ -3231,7 +3212,7 @@
 
 }
 
-/**
+/*
  * This function comes to reflect the actual link state read DIRECTLY from the
  * HW
  */
@@ -3243,10 +3224,10 @@
 	u8 ext_phy_link_up = 0, serdes_phy_type;
 	struct link_vars temp_vars;
 
-	CL45_RD_OVER_CL22(bp, &params->phy[INT_PHY],
-			      MDIO_REG_BANK_GP_STATUS,
-			      MDIO_GP_STATUS_TOP_AN_STATUS1,
-			      &gp_status);
+	CL22_RD_OVER_CL45(bp, &params->phy[INT_PHY],
+			  MDIO_REG_BANK_GP_STATUS,
+			  MDIO_GP_STATUS_TOP_AN_STATUS1,
+			  &gp_status);
 	/* link is up only if both local phy and external phy are up */
 	if (!(gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS))
 		return -ESRCH;
@@ -3290,15 +3271,15 @@
 	u8 rc = 0;
 	u8 phy_index, non_ext_phy;
 	struct bnx2x *bp = params->bp;
-	/**
-	* In case of external phy existence, the line speed would be the
-	* line speed linked up by the external phy. In case it is direct
-	* only, then the line_speed during initialization will be
-	* equal to the req_line_speed
-	*/
+	/*
+	 * In case of external phy existence, the line speed would be the
+	 * line speed linked up by the external phy. In case it is direct
+	 * only, then the line_speed during initialization will be
+	 * equal to the req_line_speed
+	 */
 	vars->line_speed = params->phy[INT_PHY].req_line_speed;
 
-	/**
+	/*
 	 * Initialize the internal phy in case this is a direct board
 	 * (no external phys), or this board has external phy which requires
 	 * to first.
@@ -3326,17 +3307,16 @@
 	if (!non_ext_phy)
 		for (phy_index = EXT_PHY1; phy_index < params->num_phys;
 		      phy_index++) {
-			/**
+			/*
 			 * No need to initialize second phy in case of first
 			 * phy only selection. In case of second phy, we do
 			 * need to initialize the first phy, since they are
 			 * connected.
-			 **/
+			 */
 			if (phy_index == EXT_PHY2 &&
 			    (bnx2x_phy_selection(params) ==
 			     PORT_HW_CFG_PHY_SELECTION_FIRST_PHY)) {
-				DP(NETIF_MSG_LINK, "Not initializing"
-						   "second phy\n");
+				DP(NETIF_MSG_LINK, "Ignoring second phy\n");
 				continue;
 			}
 			params->phy[phy_index].config_init(
@@ -3358,9 +3338,8 @@
 				 struct link_params *params)
 {
 	/* reset the SerDes/XGXS */
-	REG_WR(params->bp, GRCBASE_MISC +
-		     MISC_REGISTERS_RESET_REG_3_CLEAR,
-		     (0x1ff << (params->port*16)));
+	REG_WR(params->bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR,
+	       (0x1ff << (params->port*16)));
 }
 
 static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy,
@@ -3374,11 +3353,11 @@
 	else
 		gpio_port = params->port;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       gpio_port);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       gpio_port);
 	DP(NETIF_MSG_LINK, "reset external PHY\n");
 }
 
@@ -3409,9 +3388,8 @@
 
 	/* reset BigMac */
 	bnx2x_bmac_rx_disable(bp, params->port);
-	REG_WR(bp, GRCBASE_MISC +
-		   MISC_REGISTERS_RESET_REG_2_CLEAR,
-		   (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
+	REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR,
+	       (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port));
 	return 0;
 }
 
@@ -3462,7 +3440,7 @@
 	msleep(20);
 	return rc;
 }
-/**
+/*
  * The bnx2x_link_update function should be called upon link
  * interrupt.
  * Link is considered up as follows:
@@ -3501,12 +3479,11 @@
 		 REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4));
 
 	is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT +
-				    port*0x18) > 0);
+				port*0x18) > 0);
 	DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n",
 		 REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4),
 		 is_mi_int,
-		 REG_RD(bp,
-			    NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
+		 REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c));
 
 	DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n",
 	  REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68),
@@ -3515,14 +3492,14 @@
 	/* disable emac */
 	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
-	/**
-	* Step 1:
-	* Check external link change only for external phys, and apply
-	* priority selection between them in case the link on both phys
-	* is up. Note that the instead of the common vars, a temporary
-	* vars argument is used since each phy may have different link/
-	* speed/duplex result
-	*/
+	/*
+	 * Step 1:
+	 * Check external link change only for external phys, and apply
+	 * priority selection between them in case the link on both phys
+	 * is up. Note that the instead of the common vars, a temporary
+	 * vars argument is used since each phy may have different link/
+	 * speed/duplex result
+	 */
 	for (phy_index = EXT_PHY1; phy_index < params->num_phys;
 	      phy_index++) {
 		struct bnx2x_phy *phy = &params->phy[phy_index];
@@ -3547,22 +3524,22 @@
 			switch (bnx2x_phy_selection(params)) {
 			case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
 			case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
-			/**
+			/*
 			 * In this option, the first PHY makes sure to pass the
 			 * traffic through itself only.
 			 * Its not clear how to reset the link on the second phy
-			 **/
+			 */
 				active_external_phy = EXT_PHY1;
 				break;
 			case PORT_HW_CFG_PHY_SELECTION_SECOND_PHY_PRIORITY:
-			/**
+			/*
 			 * In this option, the first PHY makes sure to pass the
 			 * traffic through the second PHY.
-			 **/
+			 */
 				active_external_phy = EXT_PHY2;
 				break;
 			default:
-			/**
+			/*
 			 * Link indication on both PHYs with the following cases
 			 * is invalid:
 			 * - FIRST_PHY means that second phy wasn't initialized,
@@ -3570,7 +3547,7 @@
 			 * - SECOND_PHY means that first phy should not be able
 			 * to link up by itself (using configuration)
 			 * - DEFAULT should be overriden during initialiazation
-			 **/
+			 */
 				DP(NETIF_MSG_LINK, "Invalid link indication"
 					   "mpc=0x%x. DISABLING LINK !!!\n",
 					   params->multi_phy_config);
@@ -3580,18 +3557,18 @@
 		}
 	}
 	prev_line_speed = vars->line_speed;
-	/**
-	* Step 2:
-	* Read the status of the internal phy. In case of
-	* DIRECT_SINGLE_MEDIA board, this link is the external link,
-	* otherwise this is the link between the 577xx and the first
-	* external phy
-	*/
+	/*
+	 * Step 2:
+	 * Read the status of the internal phy. In case of
+	 * DIRECT_SINGLE_MEDIA board, this link is the external link,
+	 * otherwise this is the link between the 577xx and the first
+	 * external phy
+	 */
 	if (params->phy[INT_PHY].read_status)
 		params->phy[INT_PHY].read_status(
 			&params->phy[INT_PHY],
 			params, vars);
-	/**
+	/*
 	 * The INT_PHY flow control reside in the vars. This include the
 	 * case where the speed or flow control are not set to AUTO.
 	 * Otherwise, the active external phy flow control result is set
@@ -3601,13 +3578,13 @@
 	 */
 	if (active_external_phy > INT_PHY) {
 		vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl;
-		/**
+		/*
 		 * Link speed is taken from the XGXS. AN and FC result from
 		 * the external phy.
 		 */
 		vars->link_status |= phy_vars[active_external_phy].link_status;
 
-		/**
+		/*
 		 * if active_external_phy is first PHY and link is up - disable
 		 * disable TX on second external PHY
 		 */
@@ -3643,7 +3620,7 @@
 	DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x,"
 		   " ext_phy_line_speed = %d\n", vars->flow_ctrl,
 		   vars->link_status, ext_phy_line_speed);
-	/**
+	/*
 	 * Upon link speed change set the NIG into drain mode. Comes to
 	 * deals with possible FIFO glitch due to clk change when speed
 	 * is decreased without link down indicator
@@ -3658,8 +3635,8 @@
 				   ext_phy_line_speed);
 			vars->phy_link_up = 0;
 		} else if (prev_line_speed != vars->line_speed) {
-			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
-				     + params->port*4, 0);
+			REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4,
+			       0);
 			msleep(1);
 		}
 	}
@@ -3674,14 +3651,14 @@
 
 	bnx2x_link_int_ack(params, vars, link_10g);
 
-	/**
-	* In case external phy link is up, and internal link is down
-	* (not initialized yet probably after link initialization, it
-	* needs to be initialized.
-	* Note that after link down-up as result of cable plug, the xgxs
-	* link would probably become up again without the need
-	* initialize it
-	*/
+	/*
+	 * In case external phy link is up, and internal link is down
+	 * (not initialized yet probably after link initialization, it
+	 * needs to be initialized.
+	 * Note that after link down-up as result of cable plug, the xgxs
+	 * link would probably become up again without the need
+	 * initialize it
+	 */
 	if (!(SINGLE_MEDIA_DIRECT(params))) {
 		DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d,"
 			   " init_preceding = %d\n", ext_phy_link_up,
@@ -3701,9 +3678,9 @@
 						vars);
 		}
 	}
-	/**
-	 *  Link is up only if both local phy and external phy (in case of
-	 *  non-direct board) are up
+	/*
+	 * Link is up only if both local phy and external phy (in case of
+	 * non-direct board) are up
 	 */
 	vars->link_up = (vars->phy_link_up &&
 			 (ext_phy_link_up ||
@@ -3724,10 +3701,10 @@
 void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port)
 {
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 	msleep(1);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
 }
 
 static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port,
@@ -3747,9 +3724,9 @@
 	u16 fw_ver1, fw_ver2;
 
 	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+			MDIO_PMA_REG_ROM_VER1, &fw_ver1);
 	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2, &fw_ver2);
+			MDIO_PMA_REG_ROM_VER2, &fw_ver2);
 	bnx2x_save_spirom_version(bp, port, (u32)(fw_ver1<<16 | fw_ver2),
 				  phy->ver_addr);
 }
@@ -3770,7 +3747,7 @@
 	if ((vars->ieee_fc &
 	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
 	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
-		val |=  MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
+		val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC;
 	}
 	if ((vars->ieee_fc &
 	    MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
@@ -3801,11 +3778,11 @@
 	else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) {
 		ret = 1;
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_AN_DEVAD,
-			      MDIO_AN_REG_ADV_PAUSE, &ld_pause);
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_ADV_PAUSE, &ld_pause);
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_AN_DEVAD,
-			      MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
+				MDIO_AN_DEVAD,
+				MDIO_AN_REG_LP_AUTO_NEG, &lp_pause);
 		pause_result = (ld_pause &
 				MDIO_AN_REG_ADV_PAUSE_MASK) >> 8;
 		pause_result |= (lp_pause &
@@ -3881,31 +3858,31 @@
 	/* Boot port from external ROM  */
 	/* EDC grst */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x0001);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 0x0001);
 
 	/* ucode reboot and rst */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       0x008c);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 0x008c);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
 
 	/* Reset internal microprocessor */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
 
 	/* Release srst bit */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
 
 	/* Delay 100ms per the PHY specifications */
 	msleep(100);
@@ -3936,8 +3913,8 @@
 
 	/* Clear ser_boot_ctl bit */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
 	bnx2x_save_bcm_spirom_ver(bp, phy, port);
 
 	DP(NETIF_MSG_LINK,
@@ -3958,8 +3935,8 @@
 
 	/* Read 8073 HW revision*/
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8073_CHIP_REV, &val);
 
 	if (val != 1) {
 		/* No need to workaround in 8073 A1 */
@@ -3967,8 +3944,8 @@
 	}
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_ROM_VER2, &val);
 
 	/* SNR should be applied only for version 0x102 */
 	if (val != 0x102)
@@ -3982,8 +3959,8 @@
 	u16 val, cnt, cnt1 ;
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_8073_CHIP_REV, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_8073_CHIP_REV, &val);
 
 	if (val > 0) {
 		/* No need to workaround in 8073 A1 */
@@ -3991,26 +3968,32 @@
 	}
 	/* XAUI workaround in 8073 A0: */
 
-	/* After loading the boot ROM and restarting Autoneg,
-	poll Dev1, Reg $C820: */
+	/*
+	 * After loading the boot ROM and restarting Autoneg, poll
+	 * Dev1, Reg $C820:
+	 */
 
 	for (cnt = 0; cnt < 1000; cnt++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
-			      &val);
-		  /* If bit [14] = 0 or bit [13] = 0, continue on with
-		   system initialization (XAUI work-around not required,
-		    as these bits indicate 2.5G or 1G link up). */
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8073_SPEED_LINK_STATUS,
+				&val);
+		  /*
+		   * If bit [14] = 0 or bit [13] = 0, continue on with
+		   * system initialization (XAUI work-around not required, as
+		   * these bits indicate 2.5G or 1G link up).
+		   */
 		if (!(val & (1<<14)) || !(val & (1<<13))) {
 			DP(NETIF_MSG_LINK, "XAUI work-around not required\n");
 			return 0;
 		} else if (!(val & (1<<15))) {
-			DP(NETIF_MSG_LINK, "clc bit 15 went off\n");
-			 /* If bit 15 is 0, then poll Dev1, Reg $C841 until
-			  it's MSB (bit 15) goes to 1 (indicating that the
-			  XAUI workaround has completed),
-			  then continue on with system initialization.*/
+			DP(NETIF_MSG_LINK, "bit 15 went off\n");
+			/*
+			 * If bit 15 is 0, then poll Dev1, Reg $C841 until it's
+			 * MSB (bit15) goes to 1 (indicating that the XAUI
+			 * workaround has completed), then continue on with
+			 * system initialization.
+			 */
 			for (cnt1 = 0; cnt1 < 1000; cnt1++) {
 				bnx2x_cl45_read(bp, phy,
 					MDIO_PMA_DEVAD,
@@ -4093,10 +4076,10 @@
 		gpio_port = params->port;
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
 
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port);
 
 	/* enable LASI */
 	bnx2x_cl45_write(bp, phy,
@@ -4114,10 +4097,6 @@
 
 	DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1);
 
-	/**
-	 * If this is forced speed, set to KR or KX (all other are not
-	 * supported)
-	 */
 	/* Swap polarity if required - Must be done only in non-1G mode */
 	if (params->lane_config & PORT_HW_CFG_SWAP_PHY_POLARITY_ENABLED) {
 		/* Configure the 8073 to swap _P and _N of the KR lines */
@@ -4160,8 +4139,10 @@
 			val = (1<<7);
 		} else if (phy->req_line_speed ==  SPEED_2500) {
 			val = (1<<5);
-			/* Note that 2.5G works only
-			when used with 1G advertisment */
+			/*
+			 * Note that 2.5G works only when used with 1G
+			 * advertisement
+			 */
 		} else
 			val = (1<<5);
 	} else {
@@ -4170,8 +4151,7 @@
 			PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
 			val |= (1<<7);
 
-		/* Note that 2.5G works only when
-		used with 1G advertisment */
+		/* Note that 2.5G works only when used with 1G advertisement */
 		if (phy->speed_cap_mask &
 			(PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
 			 PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
@@ -4211,9 +4191,11 @@
 	/* Add support for CL37 (passive mode) III */
 	bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
 
-	/* The SNR will improve about 2db by changing
-	BW and FEE main tap. Rest commands are executed
-	after link is up*/
+	/*
+	 * The SNR will improve about 2db by changing BW and FEE main
+	 * tap. Rest commands are executed after link is up
+	 * Change FFE main cursor to 5 in EDC register
+	 */
 	if (bnx2x_8073_is_snr_needed(bp, phy))
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN,
@@ -4297,12 +4279,11 @@
 
 	link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1)));
 	if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) {
-		/* The SNR will improve about 2dbby
-		changing the BW and FEE main tap.*/
-		/* The 1st write to change FFE main
-		tap is set before restart AN */
-		/* Change PLL Bandwidth in EDC
-		register */
+		/*
+		 * The SNR will improve about 2dbby changing the BW and FEE main
+		 * tap. The 1st write to change FFE main tap is set before
+		 * restart AN. Change PLL Bandwidth in EDC register
+		 */
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH,
 				 0x26BC);
@@ -4346,10 +4327,10 @@
 			bnx2x_cl45_read(bp, phy,
 					MDIO_XS_DEVAD,
 					MDIO_XS_REG_8073_RX_CTRL_PCIE, &val1);
-			/**
-			* Set bit 3 to invert Rx in 1G mode and clear this bit
-			* when it`s in 10G mode.
-			*/
+			/*
+			 * Set bit 3 to invert Rx in 1G mode and clear this bit
+			 * when it`s in 10G mode.
+			 */
 			if (vars->line_speed == SPEED_1000) {
 				DP(NETIF_MSG_LINK, "Swapping 1G polarity for"
 					      "the 8073\n");
@@ -4381,8 +4362,8 @@
 	DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n",
 	   gpio_port);
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    gpio_port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       gpio_port);
 }
 
 /******************************************************************/
@@ -4396,11 +4377,11 @@
 	DP(NETIF_MSG_LINK, "init 8705\n");
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288);
@@ -4451,35 +4432,79 @@
 /******************************************************************/
 /*			SFP+ module Section			  */
 /******************************************************************/
-static void bnx2x_sfp_set_transmitter(struct bnx2x *bp,
+static u8 bnx2x_get_gpio_port(struct link_params *params)
+{
+	u8 gpio_port;
+	u32 swap_val, swap_override;
+	struct bnx2x *bp = params->bp;
+	if (CHIP_IS_E2(bp))
+		gpio_port = BP_PATH(bp);
+	else
+		gpio_port = params->port;
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
+	return gpio_port ^ (swap_val && swap_override);
+}
+static void bnx2x_sfp_set_transmitter(struct link_params *params,
 				      struct bnx2x_phy *phy,
-				      u8 port,
 				      u8 tx_en)
 {
 	u16 val;
+	u8 port = params->port;
+	struct bnx2x *bp = params->bp;
+	u32 tx_en_mode;
 
-	DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n",
-		 tx_en, port);
 	/* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/
-	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_PHY_IDENTIFIER,
-		      &val);
+	tx_en_mode = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+				     dev_info.port_hw_config[port].sfp_ctrl)) &
+		PORT_HW_CFG_TX_LASER_MASK;
+	DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x "
+			   "mode = %x\n", tx_en, port, tx_en_mode);
+	switch (tx_en_mode) {
+	case PORT_HW_CFG_TX_LASER_MDIO:
 
-	if (tx_en)
-		val &= ~(1<<15);
-	else
-		val |= (1<<15);
+		bnx2x_cl45_read(bp, phy,
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_PHY_IDENTIFIER,
+				&val);
 
-	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       val);
+		if (tx_en)
+			val &= ~(1<<15);
+		else
+			val |= (1<<15);
+
+		bnx2x_cl45_write(bp, phy,
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_PHY_IDENTIFIER,
+				 val);
+	break;
+	case PORT_HW_CFG_TX_LASER_GPIO0:
+	case PORT_HW_CFG_TX_LASER_GPIO1:
+	case PORT_HW_CFG_TX_LASER_GPIO2:
+	case PORT_HW_CFG_TX_LASER_GPIO3:
+	{
+		u16 gpio_pin;
+		u8 gpio_port, gpio_mode;
+		if (tx_en)
+			gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_HIGH;
+		else
+			gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_LOW;
+
+		gpio_pin = tx_en_mode - PORT_HW_CFG_TX_LASER_GPIO0;
+		gpio_port = bnx2x_get_gpio_port(params);
+		bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port);
+		break;
+	}
+	default:
+		DP(NETIF_MSG_LINK, "Invalid TX_LASER_MDIO 0x%x\n", tx_en_mode);
+		break;
+	}
 }
 
 static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 					    struct link_params *params,
-					  u16 addr, u8 byte_cnt, u8 *o_buf)
+					    u16 addr, u8 byte_cnt, u8 *o_buf)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val = 0;
@@ -4492,23 +4517,23 @@
 	/* Set the read command byte count */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
-		       (byte_cnt | 0xa000));
+			 (byte_cnt | 0xa000));
 
 	/* Set the read command address */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-		       addr);
+			 addr);
 
 	/* Activate read command */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		       0x2c0f);
+			 0x2c0f);
 
 	/* Wait up to 500us for command complete status */
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
 			break;
@@ -4526,15 +4551,15 @@
 	/* Read the buffer */
 	for (i = 0; i < byte_cnt; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val);
 		o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK);
 	}
 
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
 			return 0;
@@ -4545,7 +4570,7 @@
 
 static u8 bnx2x_8727_read_sfp_module_eeprom(struct bnx2x_phy *phy,
 					    struct link_params *params,
-					  u16 addr, u8 byte_cnt, u8 *o_buf)
+					    u16 addr, u8 byte_cnt, u8 *o_buf)
 {
 	struct bnx2x *bp = params->bp;
 	u16 val, i;
@@ -4558,41 +4583,43 @@
 
 	/* Need to read from 1.8000 to clear it */
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		      &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+			&val);
 
 	/* Set the read command byte count */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
-		       ((byte_cnt < 2) ? 2 : byte_cnt));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_SFP_TWO_WIRE_BYTE_CNT,
+			 ((byte_cnt < 2) ? 2 : byte_cnt));
 
 	/* Set the read command address */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
-		       addr);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_SFP_TWO_WIRE_MEM_ADDR,
+			 addr);
 	/* Set the destination address */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       0x8004,
-		       MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
+			 MDIO_PMA_DEVAD,
+			 0x8004,
+			 MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF);
 
 	/* Activate read command */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
-		       0x8002);
-	/* Wait appropriate time for two-wire command to finish before
-	polling the status register */
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_SFP_TWO_WIRE_CTRL,
+			 0x8002);
+	/*
+	 * Wait appropriate time for two-wire command to finish before
+	 * polling the status register
+	 */
 	msleep(1);
 
 	/* Wait up to 500us for command complete status */
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_COMPLETE)
 			break;
@@ -4604,21 +4631,21 @@
 		DP(NETIF_MSG_LINK,
 			 "Got bad status 0x%x when reading from SFP+ EEPROM\n",
 			 (val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK));
-		return -EINVAL;
+		return -EFAULT;
 	}
 
 	/* Read the buffer */
 	for (i = 0; i < byte_cnt; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_8727_TWO_WIRE_DATA_BUF + i, &val);
 		o_buf[i] = (u8)(val & MDIO_PMA_REG_8727_TWO_WIRE_DATA_MASK);
 	}
 
 	for (i = 0; i < 100; i++) {
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val);
 		if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) ==
 		    MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE)
 			return 0;
@@ -4628,22 +4655,22 @@
 	return -EINVAL;
 }
 
-static u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
-				       struct link_params *params, u16 addr,
-				       u8 byte_cnt, u8 *o_buf)
+u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+				struct link_params *params, u16 addr,
+				u8 byte_cnt, u8 *o_buf)
 {
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
 		return bnx2x_8726_read_sfp_module_eeprom(phy, params, addr,
-						       byte_cnt, o_buf);
+							 byte_cnt, o_buf);
 	else if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
 		return bnx2x_8727_read_sfp_module_eeprom(phy, params, addr,
-						       byte_cnt, o_buf);
+							 byte_cnt, o_buf);
 	return -EINVAL;
 }
 
 static u8 bnx2x_get_edc_mode(struct bnx2x_phy *phy,
 			     struct link_params *params,
-				  u16 *edc_mode)
+			     u16 *edc_mode)
 {
 	struct bnx2x *bp = params->bp;
 	u8 val, check_limiting_mode = 0;
@@ -4664,8 +4691,10 @@
 	{
 		u8 copper_module_type;
 
-		/* Check if its active cable( includes SFP+ module)
-		of passive cable*/
+		/*
+		 * Check if its active cable (includes SFP+ module)
+		 * of passive cable
+		 */
 		if (bnx2x_read_sfp_module_eeprom(phy,
 					       params,
 					       SFP_EEPROM_FC_TX_TECH_ADDR,
@@ -4724,8 +4753,10 @@
 	DP(NETIF_MSG_LINK, "EDC mode is set to 0x%x\n", *edc_mode);
 	return 0;
 }
-/* This function read the relevant field from the module ( SFP+ ),
-	and verify it is compliant with this board */
+/*
+ * This function read the relevant field from the module (SFP+), and verify it
+ * is compliant with this board
+ */
 static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy,
 				  struct link_params *params)
 {
@@ -4774,24 +4805,24 @@
 	/* format the warning message */
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
-				       SFP_EEPROM_VENDOR_NAME_ADDR,
-				       SFP_EEPROM_VENDOR_NAME_SIZE,
-				       (u8 *)vendor_name))
+					 SFP_EEPROM_VENDOR_NAME_ADDR,
+					 SFP_EEPROM_VENDOR_NAME_SIZE,
+					 (u8 *)vendor_name))
 		vendor_name[0] = '\0';
 	else
 		vendor_name[SFP_EEPROM_VENDOR_NAME_SIZE] = '\0';
 	if (bnx2x_read_sfp_module_eeprom(phy,
 					 params,
-				       SFP_EEPROM_PART_NO_ADDR,
-				       SFP_EEPROM_PART_NO_SIZE,
-				       (u8 *)vendor_pn))
+					 SFP_EEPROM_PART_NO_ADDR,
+					 SFP_EEPROM_PART_NO_SIZE,
+					 (u8 *)vendor_pn))
 		vendor_pn[0] = '\0';
 	else
 		vendor_pn[SFP_EEPROM_PART_NO_SIZE] = '\0';
 
-	netdev_info(bp->dev, "Warning: Unqualified SFP+ module detected,"
-			     " Port %d from %s part number %s\n",
-		    params->port, vendor_name, vendor_pn);
+	netdev_err(bp->dev,  "Warning: Unqualified SFP+ module detected,"
+			      " Port %d from %s part number %s\n",
+			 params->port, vendor_name, vendor_pn);
 	phy->flags |= FLAGS_SFP_NOT_APPROVED;
 	return -EINVAL;
 }
@@ -4803,8 +4834,11 @@
 	u8 val;
 	struct bnx2x *bp = params->bp;
 	u16 timeout;
-	/* Initialization time after hot-plug may take up to 300ms for some
-	phys type ( e.g. JDSU ) */
+	/*
+	 * Initialization time after hot-plug may take up to 300ms for
+	 * some phys type ( e.g. JDSU )
+	 */
+
 	for (timeout = 0; timeout < 60; timeout++) {
 		if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val)
 		    == 0) {
@@ -4823,16 +4857,14 @@
 	/* Make sure GPIOs are not using for LED mode */
 	u16 val;
 	/*
-	 * In the GPIO register, bit 4 is use to detemine if the GPIOs are
+	 * In the GPIO register, bit 4 is use to determine if the GPIOs are
 	 * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for
 	 * output
 	 * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0
 	 * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1
 	 * where the 1st bit is the over-current(only input), and 2nd bit is
 	 * for power( only output )
-	*/
-
-	/*
+	 *
 	 * In case of NOC feature is disabled and power is up, set GPIO control
 	 *  as input to enable listening of over-current indication
 	 */
@@ -4861,15 +4893,14 @@
 	u16 cur_limiting_mode;
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2,
-		      &cur_limiting_mode);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_ROM_VER2,
+			&cur_limiting_mode);
 	DP(NETIF_MSG_LINK, "Current Limiting mode is 0x%x\n",
 		 cur_limiting_mode);
 
 	if (edc_mode == EDC_MODE_LIMITING) {
-		DP(NETIF_MSG_LINK,
-			 "Setting LIMITING MODE\n");
+		DP(NETIF_MSG_LINK, "Setting LIMITING MODE\n");
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD,
 				 MDIO_PMA_REG_ROM_VER2,
@@ -4878,62 +4909,63 @@
 
 		DP(NETIF_MSG_LINK, "Setting LRM MODE\n");
 
-		/* Changing to LRM mode takes quite few seconds.
-		So do it only if current mode is limiting
-		( default is LRM )*/
+		/*
+		 * Changing to LRM mode takes quite few seconds. So do it only
+		 * if current mode is limiting (default is LRM)
+		 */
 		if (cur_limiting_mode != EDC_MODE_LIMITING)
 			return 0;
 
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_LRM_MODE,
-			       0);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_LRM_MODE,
+				 0);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_ROM_VER2,
-			       0x128);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_ROM_VER2,
+				 0x128);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_MISC_CTRL0,
-			       0x4008);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_MISC_CTRL0,
+				 0x4008);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_LRM_MODE,
-			       0xaaaa);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_LRM_MODE,
+				 0xaaaa);
 	}
 	return 0;
 }
 
 static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp,
 				       struct bnx2x_phy *phy,
-					u16 edc_mode)
+				       u16 edc_mode)
 {
 	u16 phy_identifier;
 	u16 rom_ver2_val;
 	bnx2x_cl45_read(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       &phy_identifier);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_PHY_IDENTIFIER,
+			&phy_identifier);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       (phy_identifier & ~(1<<9)));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_PHY_IDENTIFIER,
+			 (phy_identifier & ~(1<<9)));
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_ROM_VER2,
-		      &rom_ver2_val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_ROM_VER2,
+			&rom_ver2_val);
 	/* Keep the MSB 8-bits, and set the LSB 8-bits with the edc_mode */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_ROM_VER2,
-		       (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_ROM_VER2,
+			 (rom_ver2_val & 0xff00) | (edc_mode & 0x00ff));
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_PHY_IDENTIFIER,
-		       (phy_identifier | (1<<9)));
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_PHY_IDENTIFIER,
+			 (phy_identifier | (1<<9)));
 
 	return 0;
 }
@@ -4946,11 +4978,11 @@
 
 	switch (action) {
 	case DISABLE_TX:
-		bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+		bnx2x_sfp_set_transmitter(params, phy, 0);
 		break;
 	case ENABLE_TX:
 		if (!(phy->flags & FLAGS_SFP_NOT_APPROVED))
-			bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
+			bnx2x_sfp_set_transmitter(params, phy, 1);
 		break;
 	default:
 		DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n",
@@ -4959,6 +4991,38 @@
 	}
 }
 
+static void bnx2x_set_sfp_module_fault_led(struct link_params *params,
+					   u8 gpio_mode)
+{
+	struct bnx2x *bp = params->bp;
+
+	u32 fault_led_gpio = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].sfp_ctrl)) &
+		PORT_HW_CFG_FAULT_MODULE_LED_MASK;
+	switch (fault_led_gpio) {
+	case PORT_HW_CFG_FAULT_MODULE_LED_DISABLED:
+		return;
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO0:
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO1:
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO2:
+	case PORT_HW_CFG_FAULT_MODULE_LED_GPIO3:
+	{
+		u8 gpio_port = bnx2x_get_gpio_port(params);
+		u16 gpio_pin = fault_led_gpio -
+			PORT_HW_CFG_FAULT_MODULE_LED_GPIO0;
+		DP(NETIF_MSG_LINK, "Set fault module-detected led "
+				   "pin %x port %x mode %x\n",
+			       gpio_pin, gpio_port, gpio_mode);
+		bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port);
+	}
+	break;
+	default:
+		DP(NETIF_MSG_LINK, "Error: Invalid fault led mode 0x%x\n",
+			       fault_led_gpio);
+	}
+}
+
 static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy,
 				     struct link_params *params)
 {
@@ -4976,15 +5040,14 @@
 	if (bnx2x_get_edc_mode(phy, params, &edc_mode) != 0) {
 		DP(NETIF_MSG_LINK, "Failed to get valid module type\n");
 		return -EINVAL;
-	} else if (bnx2x_verify_sfp_module(phy, params) !=
-		   0) {
+	} else if (bnx2x_verify_sfp_module(phy, params) != 0) {
 		/* check SFP+ module compatibility */
 		DP(NETIF_MSG_LINK, "Module verification failed!!\n");
 		rc = -EINVAL;
 		/* Turn on fault module-detected led */
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				  MISC_REGISTERS_GPIO_HIGH,
-				  params->port);
+		bnx2x_set_sfp_module_fault_led(params,
+					       MISC_REGISTERS_GPIO_HIGH);
+
 		if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) &&
 		    ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		     PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) {
@@ -4995,18 +5058,17 @@
 		}
 	} else {
 		/* Turn off fault module-detected led */
-		DP(NETIF_MSG_LINK, "Turn off fault module-detected led\n");
-		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-					  MISC_REGISTERS_GPIO_LOW,
-					  params->port);
+		bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW);
 	}
 
 	/* power up the SFP module */
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727)
 		bnx2x_8727_power_module(bp, phy, 1);
 
-	/* Check and set limiting mode / LRM mode on 8726.
-	On 8727 it is done automatically */
+	/*
+	 * Check and set limiting mode / LRM mode on 8726. On 8727 it
+	 * is done automatically
+	 */
 	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)
 		bnx2x_8726_set_limiting_mode(bp, phy, edc_mode);
 	else
@@ -5018,9 +5080,9 @@
 	if (rc == 0 ||
 	    (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) !=
 	    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-		bnx2x_sfp_set_transmitter(bp, phy, params->port, 1);
+		bnx2x_sfp_set_transmitter(params, phy, 1);
 	else
-		bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+		bnx2x_sfp_set_transmitter(params, phy, 0);
 
 	return rc;
 }
@@ -5033,11 +5095,9 @@
 	u8 port = params->port;
 
 	/* Set valid module led off */
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-			  MISC_REGISTERS_GPIO_HIGH,
-			  params->port);
+	bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH);
 
-	/* Get current gpio val refelecting module plugged in / out*/
+	/* Get current gpio val reflecting module plugged in / out*/
 	gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port);
 
 	/* Call the handling function in case module is detected */
@@ -5053,18 +5113,20 @@
 			DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n");
 	} else {
 		u32 val = REG_RD(bp, params->shmem_base +
-				     offsetof(struct shmem_region, dev_info.
-					      port_feature_config[params->port].
-					      config));
+				 offsetof(struct shmem_region, dev_info.
+					  port_feature_config[params->port].
+					  config));
 
 		bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3,
 				   MISC_REGISTERS_GPIO_INT_OUTPUT_SET,
 				   port);
-		/* Module was plugged out. */
-		/* Disable transmit for this module */
+		/*
+		 * Module was plugged out.
+		 * Disable transmit for this module
+		 */
 		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+			bnx2x_sfp_set_transmitter(params, phy, 0);
 	}
 }
 
@@ -5100,9 +5162,9 @@
 
 	DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps"
 			" link_status 0x%x\n", rx_sd, pcs_status, val2);
-	/* link is up if both bit 0 of pmd_rx_sd and
-	 * bit 0 of pcs_status are set, or if the autoneg bit
-	 * 1 is set
+	/*
+	 * link is up if both bit 0 of pmd_rx_sd and bit 0 of pcs_status
+	 * are set, or if the autoneg bit 1 is set
 	 */
 	link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1)));
 	if (link_up) {
@@ -5123,14 +5185,15 @@
 				 struct link_params *params,
 				 struct link_vars *vars)
 {
-	u16 cnt, val;
+	u32 tx_en_mode;
+	u16 cnt, val, tmp1;
 	struct bnx2x *bp = params->bp;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	/* Wait until fw is loaded */
 	for (cnt = 0; cnt < 100; cnt++) {
@@ -5169,14 +5232,14 @@
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 1);
 	} else {
-		/* Force 1Gbps using autoneg with 1G advertisment */
+		/* Force 1Gbps using autoneg with 1G advertisement */
 
 		/* Allow CL37 through CL73 */
 		DP(NETIF_MSG_LINK, "XGXS 8706 AutoNeg\n");
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_CL73, 0x040c);
 
-		/* Enable Full-Duplex advertisment on CL37 */
+		/* Enable Full-Duplex advertisement on CL37 */
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LP, 0x0020);
 		/* Enable CL37 AN */
@@ -5197,6 +5260,26 @@
 				 0x0004);
 	}
 	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
+
+	/*
+	 * If TX Laser is controlled by GPIO_0, do not let PHY go into low
+	 * power mode, if TX Laser is disabled
+	 */
+
+	tx_en_mode = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+				dev_info.port_hw_config[params->port].sfp_ctrl))
+			& PORT_HW_CFG_TX_LASER_MASK;
+
+	if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
+		DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n");
+		bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, &tmp1);
+		tmp1 |= 0x1;
+		bnx2x_cl45_write(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, tmp1);
+	}
+
 	return 0;
 }
 
@@ -5231,26 +5314,26 @@
 
 	/* Set soft reset */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0001);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0001);
 
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_GEN_CTRL,
-		       MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_GEN_CTRL,
+			 MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
 
 	/* wait for 150ms for microcode load */
 	msleep(150);
 
 	/* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */
 	bnx2x_cl45_write(bp, phy,
-		       MDIO_PMA_DEVAD,
-		       MDIO_PMA_REG_MISC_CTRL1, 0x0000);
+			 MDIO_PMA_DEVAD,
+			 MDIO_PMA_REG_MISC_CTRL1, 0x0000);
 
 	msleep(200);
 	bnx2x_save_bcm_spirom_ver(bp, phy, params->port);
@@ -5285,23 +5368,18 @@
 	u32 val;
 	u32 swap_val, swap_override, aeu_gpio_mask, offset;
 	DP(NETIF_MSG_LINK, "Initializing BCM8726\n");
-	/* Restore normal power mode*/
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
-
-	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_8726_external_rom_boot(phy, params);
 
-	/* Need to call module detected on initialization since
-	the module detection triggered by actual module
-	insertion might occur before driver is loaded, and when
-	driver is loaded, it reset all registers, including the
-	transmitter */
+	/*
+	 * Need to call module detected on initialization since the module
+	 * detection triggered by actual module insertion might occur before
+	 * driver is loaded, and when driver is loaded, it reset all
+	 * registers, including the transmitter
+	 */
 	bnx2x_sfp_module_detection(phy, params);
 
 	if (phy->req_line_speed == SPEED_1000) {
@@ -5334,8 +5412,10 @@
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000);
 		bnx2x_cl45_write(bp, phy,
 				MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200);
-		/* Enable RX-ALARM control to receive
-		interrupt for 1G speed change */
+		/*
+		 * Enable RX-ALARM control to receive interrupt for 1G speed
+		 * change
+		 */
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x4);
 		bnx2x_cl45_write(bp, phy,
@@ -5367,7 +5447,7 @@
 
 	/* Set GPIO3 to trigger SFP+ module insertion/removal */
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			    MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
+		       MISC_REGISTERS_GPIO_INPUT_HI_Z, params->port);
 
 	/* The GPIO should be swapped if the swap register is set and active */
 	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
@@ -5458,7 +5538,7 @@
 				struct link_params *params) {
 	u32 swap_val, swap_override;
 	u8 port;
-	/**
+	/*
 	 * The PHY reset is controlled by GPIO 1. Fake the port number
 	 * to cancel the swap done in set_gpio()
 	 */
@@ -5467,20 +5547,21 @@
 	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
 	port = (swap_val && swap_override) ^ 1;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 }
 
 static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy,
 				 struct link_params *params,
 				 struct link_vars *vars)
 {
-	u16 tmp1, val, mod_abs;
+	u32 tx_en_mode;
+	u16 tmp1, val, mod_abs, tmp2;
 	u16 rx_alarm_ctrl_val;
 	u16 lasi_ctrl_val;
 	struct bnx2x *bp = params->bp;
 	/* Enable PMD link, MOD_ABS_FLT, and 1G link alarm */
 
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 	rx_alarm_ctrl_val = (1<<2) | (1<<5) ;
 	lasi_ctrl_val = 0x0004;
 
@@ -5493,14 +5574,17 @@
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, lasi_ctrl_val);
 
-	/* Initially configure  MOD_ABS to interrupt when
-	module is presence( bit 8) */
+	/*
+	 * Initially configure MOD_ABS to interrupt when module is
+	 * presence( bit 8)
+	 */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
-	/* Set EDC off by setting OPTXLOS signal input to low
-	(bit 9).
-	When the EDC is off it locks onto a reference clock and
-	avoids becoming 'lost'.*/
+	/*
+	 * Set EDC off by setting OPTXLOS signal input to low (bit 9).
+	 * When the EDC is off it locks onto a reference clock and avoids
+	 * becoming 'lost'
+	 */
 	mod_abs &= ~(1<<8);
 	if (!(phy->flags & FLAGS_NOC))
 		mod_abs &= ~(1<<9);
@@ -5515,7 +5599,7 @@
 	if (phy->flags & FLAGS_NOC)
 		val |= (3<<5);
 
-	/**
+	/*
 	 * Set 8727 GPIOs to input to allow reading from the 8727 GPIO0
 	 * status which reflect SFP+ module over-current
 	 */
@@ -5542,7 +5626,7 @@
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, &tmp1);
 		DP(NETIF_MSG_LINK, "1.7 = 0x%x\n", tmp1);
-		/**
+		/*
 		 * Power down the XAUI until link is up in case of dual-media
 		 * and 1G
 		 */
@@ -5568,7 +5652,7 @@
 		bnx2x_cl45_write(bp, phy,
 				 MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1300);
 	} else {
-		/**
+		/*
 		 * Since the 8727 has only single reset pin, need to set the 10G
 		 * registers although it is default
 		 */
@@ -5584,7 +5668,8 @@
 				 0x0008);
 	}
 
-	/* Set 2-wire transfer rate of SFP+ module EEPROM
+	/*
+	 * Set 2-wire transfer rate of SFP+ module EEPROM
 	 * to 100Khz since some DACs(direct attached cables) do
 	 * not work at 400Khz.
 	 */
@@ -5607,6 +5692,26 @@
 				 phy->tx_preemphasis[1]);
 	}
 
+	/*
+	 * If TX Laser is controlled by GPIO_0, do not let PHY go into low
+	 * power mode, if TX Laser is disabled
+	 */
+	tx_en_mode = REG_RD(bp, params->shmem_base +
+			    offsetof(struct shmem_region,
+				dev_info.port_hw_config[params->port].sfp_ctrl))
+			& PORT_HW_CFG_TX_LASER_MASK;
+
+	if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) {
+
+		DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n");
+		bnx2x_cl45_read(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, &tmp2);
+		tmp2 |= 0x1000;
+		tmp2 &= 0xFFEF;
+		bnx2x_cl45_write(bp, phy,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2);
+	}
+
 	return 0;
 }
 
@@ -5620,46 +5725,49 @@
 				      port_feature_config[params->port].
 				      config));
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_PHY_IDENTIFIER, &mod_abs);
 	if (mod_abs & (1<<8)) {
 
 		/* Module is absent */
 		DP(NETIF_MSG_LINK, "MOD_ABS indication "
 			    "show module is absent\n");
 
-		/* 1. Set mod_abs to detect next module
-		presence event
-		   2. Set EDC off by setting OPTXLOS signal input to low
-			(bit 9).
-			When the EDC is off it locks onto a reference clock and
-			avoids becoming 'lost'.*/
+		/*
+		 * 1. Set mod_abs to detect next module
+		 *    presence event
+		 * 2. Set EDC off by setting OPTXLOS signal input to low
+		 *    (bit 9).
+		 *    When the EDC is off it locks onto a reference clock and
+		 *    avoids becoming 'lost'.
+		 */
 		mod_abs &= ~(1<<8);
 		if (!(phy->flags & FLAGS_NOC))
 			mod_abs &= ~(1<<9);
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
 
-		/* Clear RX alarm since it stays up as long as
-		the mod_abs wasn't changed */
+		/*
+		 * Clear RX alarm since it stays up as long as
+		 * the mod_abs wasn't changed
+		 */
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
 
 	} else {
 		/* Module is present */
 		DP(NETIF_MSG_LINK, "MOD_ABS indication "
 			    "show module is present\n");
-		/* First thing, disable transmitter,
-		and if the module is ok, the
-		module_detection will enable it*/
-
-		/* 1. Set mod_abs to detect next module
-		absent event ( bit 8)
-		   2. Restore the default polarity of the OPRXLOS signal and
-		this signal will then correctly indicate the presence or
-		absence of the Rx signal. (bit 9) */
+		/*
+		 * First disable transmitter, and if the module is ok, the
+		 * module_detection will enable it
+		 * 1. Set mod_abs to detect next module absent event ( bit 8)
+		 * 2. Restore the default polarity of the OPRXLOS signal and
+		 * this signal will then correctly indicate the presence or
+		 * absence of the Rx signal. (bit 9)
+		 */
 		mod_abs |= (1<<8);
 		if (!(phy->flags & FLAGS_NOC))
 			mod_abs |= (1<<9);
@@ -5667,10 +5775,12 @@
 				 MDIO_PMA_DEVAD,
 				 MDIO_PMA_REG_PHY_IDENTIFIER, mod_abs);
 
-		/* Clear RX alarm since it stays up as long as
-		the mod_abs wasn't changed. This is need to be done
-		before calling the module detection, otherwise it will clear
-		the link update alarm */
+		/*
+		 * Clear RX alarm since it stays up as long as the mod_abs
+		 * wasn't changed. This is need to be done before calling the
+		 * module detection, otherwise it will clear* the link update
+		 * alarm
+		 */
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_REG_RX_ALARM, &rx_alarm_status);
@@ -5678,7 +5788,7 @@
 
 		if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) ==
 		    PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER)
-			bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+			bnx2x_sfp_set_transmitter(params, phy, 0);
 
 		if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0)
 			bnx2x_sfp_module_detection(phy, params);
@@ -5687,9 +5797,8 @@
 	}
 
 	DP(NETIF_MSG_LINK, "8727 RX_ALARM_STATUS 0x%x\n",
-		 rx_alarm_status);
-	/* No need to check link status in case of
-	module plugged in/out */
+		   rx_alarm_status);
+	/* No need to check link status in case of module plugged in/out */
 }
 
 static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy,
@@ -5725,7 +5834,7 @@
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1);
 
-	/**
+	/*
 	 * If a module is present and there is need to check
 	 * for over current
 	 */
@@ -5745,12 +5854,8 @@
 					    " Please remove the SFP+ module and"
 					    " restart the system to clear this"
 					    " error.\n",
-				   params->port);
-
-			/*
-			 * Disable all RX_ALARMs except for
-			 * mod_abs
-			 */
+			 params->port);
+			/* Disable all RX_ALARMs except for mod_abs */
 			bnx2x_cl45_write(bp, phy,
 					 MDIO_PMA_DEVAD,
 					 MDIO_PMA_REG_RX_ALARM_CTRL, (1<<5));
@@ -5793,11 +5898,15 @@
 			MDIO_PMA_DEVAD,
 			MDIO_PMA_REG_8073_SPEED_LINK_STATUS, &link_status);
 
-	/* Bits 0..2 --> speed detected,
-	   bits 13..15--> link is down */
+	/*
+	 * Bits 0..2 --> speed detected,
+	 * Bits 13..15--> link is down
+	 */
 	if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) {
 		link_up = 1;
 		vars->line_speed = SPEED_10000;
+		DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n",
+			   params->port);
 	} else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) {
 		link_up = 1;
 		vars->line_speed = SPEED_1000;
@@ -5819,7 +5928,7 @@
 		bnx2x_cl45_read(bp, phy,
 				MDIO_PMA_DEVAD,
 				MDIO_PMA_REG_8727_PCS_GP, &val1);
-		/**
+		/*
 		 * In case of dual-media board and 1G, power up the XAUI side,
 		 * otherwise power it down. For 10G it is done automatically
 		 */
@@ -5839,7 +5948,7 @@
 {
 	struct bnx2x *bp = params->bp;
 	/* Disable Transmitter */
-	bnx2x_sfp_set_transmitter(bp, phy, params->port, 0);
+	bnx2x_sfp_set_transmitter(params, phy, 0);
 	/* Clear LASI */
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0);
 
@@ -5851,19 +5960,23 @@
 static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy,
 					   struct link_params *params)
 {
-	u16 val, fw_ver1, fw_ver2, cnt;
+	u16 val, fw_ver1, fw_ver2, cnt, adj;
 	struct bnx2x *bp = params->bp;
 
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = -1;
+
 	/* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/
 	/* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0014);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, 0x0300);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x0009);
 
 	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
 		if (val & 1)
 			break;
 		udelay(5);
@@ -5877,11 +5990,11 @@
 
 
 	/* 2) read register 0xc200_0000 (SPI_FW_STATUS) */
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200);
-	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819 + adj, 0x0000);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A + adj, 0xc200);
+	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817 + adj, 0x000A);
 	for (cnt = 0; cnt < 100; cnt++) {
-		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val);
+		bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818 + adj, &val);
 		if (val & 1)
 			break;
 		udelay(5);
@@ -5894,9 +6007,9 @@
 	}
 
 	/* lower 16 bits of the register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B + adj, &fw_ver1);
 	/* upper 16 bits of register SPI_FW_STATUS */
-	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2);
+	bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C + adj, &fw_ver2);
 
 	bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1,
 				  phy->ver_addr);
@@ -5905,49 +6018,53 @@
 static void bnx2x_848xx_set_led(struct bnx2x *bp,
 				struct bnx2x_phy *phy)
 {
-	u16 val;
+	u16 val, adj;
+
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = -1;
 
 	/* PHYC_CTL_LED_CTL */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LINK_SIGNAL, &val);
+			MDIO_PMA_REG_8481_LINK_SIGNAL + adj, &val);
 	val &= 0xFE00;
 	val |= 0x0092;
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LINK_SIGNAL, val);
+			 MDIO_PMA_REG_8481_LINK_SIGNAL + adj, val);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED1_MASK,
+			 MDIO_PMA_REG_8481_LED1_MASK + adj,
 			 0x80);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED2_MASK,
+			 MDIO_PMA_REG_8481_LED2_MASK + adj,
 			 0x18);
 
 	/* Select activity source by Tx and Rx, as suggested by PHY AE */
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_8481_LED3_MASK,
+			 MDIO_PMA_REG_8481_LED3_MASK + adj,
 			 0x0006);
 
 	/* Select the closest activity blink rate to that in 10/100/1000 */
 	bnx2x_cl45_write(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_8481_LED3_BLINK,
+			MDIO_PMA_REG_8481_LED3_BLINK + adj,
 			0);
 
 	bnx2x_cl45_read(bp, phy,
 			MDIO_PMA_DEVAD,
-			MDIO_PMA_REG_84823_CTL_LED_CTL_1, &val);
+			MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, &val);
 	val |= MDIO_PMA_REG_84823_LED3_STRETCH_EN; /* stretch_en for LED3*/
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD,
-			 MDIO_PMA_REG_84823_CTL_LED_CTL_1, val);
+			 MDIO_PMA_REG_84823_CTL_LED_CTL_1 + adj, val);
 
 	/* 'Interrupt Mask' */
 	bnx2x_cl45_write(bp, phy,
@@ -5961,7 +6078,11 @@
 {
 	struct bnx2x *bp = params->bp;
 	u16 autoneg_val, an_1000_val, an_10_100_val;
-
+	/*
+	 * This phy uses the NIG latch mechanism since link indication
+	 * arrives through its LED4 and not via its LASI signal, so we
+	 * get steady signal instead of clear on read
+	 */
 	bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4,
 		      1 << NIG_LATCH_BC_ENABLE_MI_INT);
 
@@ -6086,11 +6207,11 @@
 	struct bnx2x *bp = params->bp;
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
 	return bnx2x_848xx_cmn_config_init(phy, params, vars);
@@ -6102,12 +6223,15 @@
 {
 	struct bnx2x *bp = params->bp;
 	u8 port, initialize = 1;
-	u16 val;
+	u16 val, adj;
 	u16 temp;
-	u32 actual_phy_selection;
+	u32 actual_phy_selection, cms_enable;
 	u8 rc = 0;
 
 	/* This is just for MDIO_CTL_REG_84823_MEDIA register. */
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = 3;
 
 	msleep(1);
 	if (CHIP_IS_E2(bp))
@@ -6117,11 +6241,12 @@
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
 		       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
 		       port);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 	/* Wait for GPHY to come out of reset */
 	msleep(50);
-	/* BCM84823 requires that XGXS links up first @ 10G for normal
-	behavior */
+	/*
+	 * BCM84823 requires that XGXS links up first @ 10G for normal behavior
+	 */
 	temp = vars->line_speed;
 	vars->line_speed = SPEED_10000;
 	bnx2x_set_autoneg(&params->phy[INT_PHY], params, vars, 0);
@@ -6131,7 +6256,7 @@
 	/* Set dual-media configuration according to configuration */
 
 	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
-			MDIO_CTL_REG_84823_MEDIA, &val);
+			MDIO_CTL_REG_84823_MEDIA + adj, &val);
 	val &= ~(MDIO_CTL_REG_84823_MEDIA_MAC_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_LINE_MASK |
 		 MDIO_CTL_REG_84823_MEDIA_COPPER_CORE_DOWN |
@@ -6144,7 +6269,7 @@
 
 	switch (actual_phy_selection) {
 	case PORT_HW_CFG_PHY_SELECTION_HARDWARE_DEFAULT:
-		/* Do nothing. Essentialy this is like the priority copper */
+		/* Do nothing. Essentially this is like the priority copper */
 		break;
 	case PORT_HW_CFG_PHY_SELECTION_FIRST_PHY_PRIORITY:
 		val |= MDIO_CTL_REG_84823_MEDIA_PRIORITY_COPPER;
@@ -6164,7 +6289,7 @@
 		val |= MDIO_CTL_REG_84823_MEDIA_FIBER_1G;
 
 	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
-			 MDIO_CTL_REG_84823_MEDIA, val);
+			 MDIO_CTL_REG_84823_MEDIA + adj, val);
 	DP(NETIF_MSG_LINK, "Multi_phy config = 0x%x, Media control = 0x%x\n",
 		   params->multi_phy_config, val);
 
@@ -6172,23 +6297,43 @@
 		rc = bnx2x_848xx_cmn_config_init(phy, params, vars);
 	else
 		bnx2x_save_848xx_spirom_version(phy, params);
+	cms_enable = REG_RD(bp, params->shmem_base +
+			offsetof(struct shmem_region,
+			dev_info.port_hw_config[params->port].default_cfg)) &
+			PORT_HW_CFG_ENABLE_CMS_MASK;
+
+	bnx2x_cl45_read(bp, phy, MDIO_CTL_DEVAD,
+		MDIO_CTL_REG_84823_USER_CTRL_REG, &val);
+	if (cms_enable)
+		val |= MDIO_CTL_REG_84823_USER_CTRL_CMS;
+	else
+		val &= ~MDIO_CTL_REG_84823_USER_CTRL_CMS;
+	bnx2x_cl45_write(bp, phy, MDIO_CTL_DEVAD,
+		MDIO_CTL_REG_84823_USER_CTRL_REG, val);
+
+
 	return rc;
 }
 
 static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy,
-				       struct link_params *params,
-				       struct link_vars *vars)
+				  struct link_params *params,
+				  struct link_vars *vars)
 {
 	struct bnx2x *bp = params->bp;
-	u16 val, val1, val2;
+	u16 val, val1, val2, adj;
 	u8 link_up = 0;
 
+	/* Reg offset adjustment for 84833 */
+	adj = 0;
+	if (phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833)
+		adj = -1;
+
 	/* Check 10G-BaseT link status */
 	/* Check PMD signal ok */
 	bnx2x_cl45_read(bp, phy,
 			MDIO_AN_DEVAD, 0xFFFA, &val1);
 	bnx2x_cl45_read(bp, phy,
-			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL,
+			MDIO_PMA_DEVAD, MDIO_PMA_REG_8481_PMD_SIGNAL + adj,
 			&val2);
 	DP(NETIF_MSG_LINK, "BCM848xx: PMD_SIGNAL 1.a811 = 0x%x\n", val2);
 
@@ -6273,9 +6418,9 @@
 				struct link_params *params)
 {
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 0);
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, 1);
 }
 
 static void bnx2x_8481_link_reset(struct bnx2x_phy *phy,
@@ -6297,8 +6442,8 @@
 	else
 		port = params->port;
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW,
-			    port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       port);
 }
 
 static void bnx2x_848xx_set_link_led(struct bnx2x_phy *phy,
@@ -6353,24 +6498,24 @@
 
 			/* Set LED masks */
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED2_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED5_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x20);
 
 		} else {
 			bnx2x_cl45_write(bp, phy,
@@ -6394,35 +6539,35 @@
 			val |= 0x2492;
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LINK_SIGNAL,
-					val);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LINK_SIGNAL,
+					 val);
 
 			/* Set LED masks */
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x0);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED2_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x20);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x20);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED5_MASK,
-					0x0);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x0);
 		} else {
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x20);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x20);
 		}
 		break;
 
@@ -6440,9 +6585,9 @@
 					&val);
 
 			if (!((val &
-			      MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
-			   >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)){
-				DP(NETIF_MSG_LINK, "Seting LINK_SIGNAL\n");
+			       MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_MASK)
+			  >> MDIO_PMA_REG_8481_LINK_SIGNAL_LED4_ENABLE_SHIFT)) {
+				DP(NETIF_MSG_LINK, "Setting LINK_SIGNAL\n");
 				bnx2x_cl45_write(bp, phy,
 						 MDIO_PMA_DEVAD,
 						 MDIO_PMA_REG_8481_LINK_SIGNAL,
@@ -6451,24 +6596,24 @@
 
 			/* Set LED masks */
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED1_MASK,
-					0x10);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED1_MASK,
+					 0x10);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED2_MASK,
-					0x80);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED2_MASK,
+					 0x80);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED3_MASK,
-					0x98);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED3_MASK,
+					 0x98);
 
 			bnx2x_cl45_write(bp, phy,
-					MDIO_PMA_DEVAD,
-					MDIO_PMA_REG_8481_LED5_MASK,
-					0x40);
+					 MDIO_PMA_DEVAD,
+					 MDIO_PMA_REG_8481_LED5_MASK,
+					 0x40);
 
 		} else {
 			bnx2x_cl45_write(bp, phy,
@@ -6513,10 +6658,10 @@
 
 	/* Restore normal power mode*/
 	bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port);
 	/* HW reset */
 	bnx2x_ext_phy_hw_reset(bp, params->port);
-	bnx2x_wait_reset_complete(bp, phy);
+	bnx2x_wait_reset_complete(bp, phy, params);
 
 	bnx2x_cl45_write(bp, phy,
 			 MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1);
@@ -6563,9 +6708,7 @@
 	DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n",
 		   val2, val1);
 	link_up = ((val1 & 4) == 4);
-	/* if link is up
-	 * print the AN outcome of the SFX7101 PHY
-	 */
+	/* if link is up print the AN outcome of the SFX7101 PHY */
 	if (link_up) {
 		bnx2x_cl45_read(bp, phy,
 				MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS,
@@ -6599,20 +6742,20 @@
 	u16 val, cnt;
 
 	bnx2x_cl45_read(bp, phy,
-		      MDIO_PMA_DEVAD,
-		      MDIO_PMA_REG_7101_RESET, &val);
+			MDIO_PMA_DEVAD,
+			MDIO_PMA_REG_7101_RESET, &val);
 
 	for (cnt = 0; cnt < 10; cnt++) {
 		msleep(50);
 		/* Writes a self-clearing reset */
 		bnx2x_cl45_write(bp, phy,
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_7101_RESET,
-			       (val | (1<<15)));
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_7101_RESET,
+				 (val | (1<<15)));
 		/* Wait for clear */
 		bnx2x_cl45_read(bp, phy,
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_7101_RESET, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_7101_RESET, &val);
 
 		if ((val & (1<<15)) == 0)
 			break;
@@ -6623,10 +6766,10 @@
 				struct link_params *params) {
 	/* Low power mode is controlled by GPIO 2 */
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_2,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
 	/* The PHY reset is controlled by GPIO 1 */
 	bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1,
-			    MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
+		       MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port);
 }
 
 static void bnx2x_7101_set_link_led(struct bnx2x_phy *phy,
@@ -6668,9 +6811,9 @@
 	.supported	= 0,
 	.media_type	= ETH_PHY_NOT_PRESENT,
 	.ver_addr	= 0,
-	.req_flow_ctrl  = 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)NULL,
@@ -6705,8 +6848,8 @@
 	.media_type	= ETH_PHY_UNSPECIFIED,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_init_serdes,
@@ -6742,8 +6885,8 @@
 	.media_type	= ETH_PHY_UNSPECIFIED,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_init_xgxs,
@@ -6773,8 +6916,8 @@
 	.media_type	= ETH_PHY_BASE_T,
 	.ver_addr	= 0,
 	.req_flow_ctrl	= 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_7101_config_init,
@@ -6804,9 +6947,9 @@
 			   SUPPORTED_Asym_Pause),
 	.media_type	= ETH_PHY_UNSPECIFIED,
 	.ver_addr	= 0,
-	.req_flow_ctrl  = 0,
-	.req_line_speed = 0,
-	.speed_cap_mask = 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
 	.req_duplex	= 0,
 	.rsrv		= 0,
 	.config_init	= (config_init_t)bnx2x_8073_config_init,
@@ -7015,6 +7158,43 @@
 	.phy_specific_func = (phy_specific_func_t)NULL
 };
 
+static struct bnx2x_phy phy_84833 = {
+	.type		= PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833,
+	.addr		= 0xff,
+	.flags		= FLAGS_FAN_FAILURE_DET_REQ |
+			    FLAGS_REARM_LATCH_SIGNAL,
+	.def_md_devad	= 0,
+	.reserved	= 0,
+	.rx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.tx_preemphasis	= {0xffff, 0xffff, 0xffff, 0xffff},
+	.mdio_ctrl	= 0,
+	.supported	= (SUPPORTED_10baseT_Half |
+			   SUPPORTED_10baseT_Full |
+			   SUPPORTED_100baseT_Half |
+			   SUPPORTED_100baseT_Full |
+			   SUPPORTED_1000baseT_Full |
+			   SUPPORTED_10000baseT_Full |
+			   SUPPORTED_TP |
+			   SUPPORTED_Autoneg |
+			   SUPPORTED_Pause |
+			   SUPPORTED_Asym_Pause),
+	.media_type	= ETH_PHY_BASE_T,
+	.ver_addr	= 0,
+	.req_flow_ctrl	= 0,
+	.req_line_speed	= 0,
+	.speed_cap_mask	= 0,
+	.req_duplex	= 0,
+	.rsrv		= 0,
+	.config_init	= (config_init_t)bnx2x_848x3_config_init,
+	.read_status	= (read_status_t)bnx2x_848xx_read_status,
+	.link_reset	= (link_reset_t)bnx2x_848x3_link_reset,
+	.config_loopback = (config_loopback_t)NULL,
+	.format_fw_ver	= (format_fw_ver_t)bnx2x_848xx_format_ver,
+	.hw_reset	= (hw_reset_t)NULL,
+	.set_link_led	= (set_link_led_t)bnx2x_848xx_set_link_led,
+	.phy_specific_func = (phy_specific_func_t)NULL
+};
+
 /*****************************************************************/
 /*                                                               */
 /* Populate the phy according. Main function: bnx2x_populate_phy   */
@@ -7028,7 +7208,7 @@
 	/* Get the 4 lanes xgxs config rx and tx */
 	u32 rx = 0, tx = 0, i;
 	for (i = 0; i < 2; i++) {
-		/**
+		/*
 		 * INT_PHY and EXT_PHY1 share the same value location in the
 		 * shmem. When num_phys is greater than 1, than this value
 		 * applies only to EXT_PHY1
@@ -7036,19 +7216,19 @@
 		if (phy_index == INT_PHY || phy_index == EXT_PHY1) {
 			rx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			   dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
+			  dev_info.port_hw_config[port].xgxs_config_rx[i<<1]));
 
 			tx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			   dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
+			  dev_info.port_hw_config[port].xgxs_config_tx[i<<1]));
 		} else {
 			rx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			  dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
+			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
 
 			tx = REG_RD(bp, shmem_base +
 				    offsetof(struct shmem_region,
-			  dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
+			 dev_info.port_hw_config[port].xgxs_config2_rx[i<<1]));
 		}
 
 		phy->rx_preemphasis[i << 1] = ((rx>>16) & 0xffff);
@@ -7168,6 +7348,9 @@
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823:
 		*phy = phy_84823;
 		break;
+	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84833:
+		*phy = phy_84833;
+		break;
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
 		*phy = phy_7101;
 		break;
@@ -7182,21 +7365,21 @@
 	phy->addr = XGXS_EXT_PHY_ADDR(ext_phy_config);
 	bnx2x_populate_preemphasis(bp, shmem_base, phy, port, phy_index);
 
-	/**
-	* The shmem address of the phy version is located on different
-	* structures. In case this structure is too old, do not set
-	* the address
-	*/
+	/*
+	 * The shmem address of the phy version is located on different
+	 * structures. In case this structure is too old, do not set
+	 * the address
+	 */
 	config2 = REG_RD(bp, shmem_base + offsetof(struct shmem_region,
 					dev_info.shared_hw_config.config2));
 	if (phy_index == EXT_PHY1) {
 		phy->ver_addr = shmem_base + offsetof(struct shmem_region,
 				port_mb[port].ext_phy_fw_version);
 
-	/* Check specific mdc mdio settings */
-	if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
-		mdc_mdio_access = config2 &
-		SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
+		/* Check specific mdc mdio settings */
+		if (config2 & SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK)
+			mdc_mdio_access = config2 &
+			SHARED_HW_CFG_MDC_MDIO_ACCESS1_MASK;
 	} else {
 		u32 size = REG_RD(bp, shmem2_base);
 
@@ -7215,7 +7398,7 @@
 	}
 	phy->mdio_ctrl = bnx2x_get_emac_base(bp, mdc_mdio_access, port);
 
-	/**
+	/*
 	 * In case mdc/mdio_access of the external phy is different than the
 	 * mdc/mdio access of the XGXS, a HW lock must be taken in each access
 	 * to prevent one port interfere with another port's CL45 operations.
@@ -7250,18 +7433,20 @@
 	/* Populate the default phy configuration for MF mode */
 	if (phy_index == EXT_PHY2) {
 		link_config = REG_RD(bp, params->shmem_base +
-					 offsetof(struct shmem_region, dev_info.
+				     offsetof(struct shmem_region, dev_info.
 			port_feature_config[params->port].link_config2));
 		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
-					offsetof(struct shmem_region, dev_info.
+					     offsetof(struct shmem_region,
+						      dev_info.
 			port_hw_config[params->port].speed_capability_mask2));
 	} else {
 		link_config = REG_RD(bp, params->shmem_base +
-				offsetof(struct shmem_region, dev_info.
+				     offsetof(struct shmem_region, dev_info.
 				port_feature_config[params->port].link_config));
 		phy->speed_cap_mask = REG_RD(bp, params->shmem_base +
-				offsetof(struct shmem_region, dev_info.
-			   port_hw_config[params->port].speed_capability_mask));
+					     offsetof(struct shmem_region,
+						      dev_info.
+			port_hw_config[params->port].speed_capability_mask));
 	}
 	DP(NETIF_MSG_LINK, "Default config phy idx %x cfg 0x%x speed_cap_mask"
 		       " 0x%x\n", phy_index, link_config, phy->speed_cap_mask);
@@ -7408,7 +7593,7 @@
 			else if (phy_index == EXT_PHY2)
 				actual_phy_idx = EXT_PHY1;
 		}
-		params->phy[actual_phy_idx].req_flow_ctrl  =
+		params->phy[actual_phy_idx].req_flow_ctrl =
 			params->req_flow_ctrl[link_cfg_idx];
 
 		params->phy[actual_phy_idx].req_line_speed =
@@ -7461,57 +7646,6 @@
 	set_phy_vars(params);
 
 	DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys);
-	if (CHIP_REV_IS_FPGA(bp)) {
-
-		vars->link_up = 1;
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
-		/* enable on E1.5 FPGA */
-		if (CHIP_IS_E1H(bp)) {
-			vars->flow_ctrl |=
-					(BNX2X_FLOW_CTRL_TX |
-					 BNX2X_FLOW_CTRL_RX);
-			vars->link_status |=
-					(LINK_STATUS_TX_FLOW_CONTROL_ENABLED |
-					 LINK_STATUS_RX_FLOW_CONTROL_ENABLED);
-		}
-
-		bnx2x_emac_enable(params, vars, 0);
-		if (!(CHIP_IS_E2(bp)))
-			bnx2x_pbf_update(params, vars->flow_ctrl,
-					 vars->line_speed);
-		/* disable drain */
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
-
-		/* update shared memory */
-		bnx2x_update_mng(params, vars->link_status);
-
-		return 0;
-
-	} else
-	if (CHIP_REV_IS_EMUL(bp)) {
-
-		vars->link_up = 1;
-		vars->line_speed = SPEED_10000;
-		vars->duplex = DUPLEX_FULL;
-		vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
-		vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD);
-
-		bnx2x_bmac_enable(params, vars, 0);
-
-		bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed);
-		/* Disable drain */
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE
-				    + params->port*4, 0);
-
-		/* update shared memory */
-		bnx2x_update_mng(params, vars->link_status);
-
-		return 0;
-
-	} else
 	if (params->loopback_mode == LOOPBACK_BMAC) {
 
 		vars->link_up = 1;
@@ -7527,8 +7661,7 @@
 		/* set bmac loopback */
 		bnx2x_bmac_enable(params, vars, 1);
 
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
-		    params->port*4, 0);
+		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 	} else if (params->loopback_mode == LOOPBACK_EMAC) {
 
@@ -7544,8 +7677,7 @@
 		/* set bmac loopback */
 		bnx2x_emac_enable(params, vars, 1);
 		bnx2x_emac_program(params, vars);
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
-		    params->port*4, 0);
+		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 	} else if ((params->loopback_mode == LOOPBACK_XGXS) ||
 		   (params->loopback_mode == LOOPBACK_EXT_PHY)) {
@@ -7568,8 +7700,7 @@
 			bnx2x_emac_program(params, vars);
 			bnx2x_emac_enable(params, vars, 0);
 		} else
-		bnx2x_bmac_enable(params, vars, 0);
-
+			bnx2x_bmac_enable(params, vars, 0);
 		if (params->loopback_mode == LOOPBACK_XGXS) {
 			/* set 10G XGXS loopback */
 			params->phy[INT_PHY].config_loopback(
@@ -7587,9 +7718,7 @@
 						params);
 			}
 		}
-
-		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE +
-			    params->port*4, 0);
+		REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0);
 
 		bnx2x_set_led(params, vars,
 			      LED_MODE_OPER, vars->line_speed);
@@ -7608,7 +7737,7 @@
 	return 0;
 }
 u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars,
-		  u8 reset_ext_phy)
+		    u8 reset_ext_phy)
 {
 	struct bnx2x *bp = params->bp;
 	u8 phy_index, port = params->port, clear_latch_ind = 0;
@@ -7617,10 +7746,10 @@
 	vars->link_status = 0;
 	bnx2x_update_mng(params, vars->link_status);
 	bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
-		     (NIG_MASK_XGXS0_LINK_STATUS |
-		      NIG_MASK_XGXS0_LINK10G |
-		      NIG_MASK_SERDES0_LINK_STATUS |
-		      NIG_MASK_MI_INT));
+		       (NIG_MASK_XGXS0_LINK_STATUS |
+			NIG_MASK_XGXS0_LINK10G |
+			NIG_MASK_SERDES0_LINK_STATUS |
+			NIG_MASK_MI_INT));
 
 	/* activate nig drain */
 	REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1);
@@ -7636,7 +7765,7 @@
 	REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0);
 
 	msleep(10);
-	/* The PHY reset is controled by GPIO 1
+	/* The PHY reset is controlled by GPIO 1
 	 * Hold it as vars low
 	 */
 	 /* clear link led */
@@ -7719,21 +7848,22 @@
 		/* disable attentions */
 		bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 +
 			       port_of_path*4,
-			     (NIG_MASK_XGXS0_LINK_STATUS |
-			      NIG_MASK_XGXS0_LINK10G |
-			      NIG_MASK_SERDES0_LINK_STATUS |
-			      NIG_MASK_MI_INT));
+			       (NIG_MASK_XGXS0_LINK_STATUS |
+				NIG_MASK_XGXS0_LINK10G |
+				NIG_MASK_SERDES0_LINK_STATUS |
+				NIG_MASK_MI_INT));
 
 		/* Need to take the phy out of low power mode in order
 			to write to access its registers */
 		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				  MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+			       MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+			       port);
 
 		/* Reset the phy */
 		bnx2x_cl45_write(bp, &phy[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_CTRL,
-			       1<<15);
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_CTRL,
+				 1<<15);
 	}
 
 	/* Add delay of 150ms after reset */
@@ -7762,18 +7892,20 @@
 
 		/* Only set bit 10 = 1 (Tx power down) */
 		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_TX_POWER_DOWN, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
 		/* Phase1 of TX_POWER_DOWN reset */
 		bnx2x_cl45_write(bp, phy_blk[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_TX_POWER_DOWN,
-			       (val | 1<<10));
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_TX_POWER_DOWN,
+				 (val | 1<<10));
 	}
 
-	/* Toggle Transmitter: Power down and then up with 600ms
-	   delay between */
+	/*
+	 * Toggle Transmitter: Power down and then up with 600ms delay
+	 * between
+	 */
 	msleep(600);
 
 	/* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
@@ -7781,25 +7913,25 @@
 		/* Phase2 of POWER_DOWN_RESET */
 		/* Release bit 10 (Release Tx power down) */
 		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_TX_POWER_DOWN, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_TX_POWER_DOWN, &val);
 
 		bnx2x_cl45_write(bp, phy_blk[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
 		msleep(15);
 
 		/* Read modify write the SPI-ROM version select register */
 		bnx2x_cl45_read(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_EDC_FFE_MAIN, &val);
+				MDIO_PMA_DEVAD,
+				MDIO_PMA_REG_EDC_FFE_MAIN, &val);
 		bnx2x_cl45_write(bp, phy_blk[port],
-			      MDIO_PMA_DEVAD,
-			      MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
+				 MDIO_PMA_DEVAD,
+				 MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
 
 		/* set GPIO2 back to LOW */
 		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
-				  MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+			       MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
 	}
 	return 0;
 }
@@ -7846,32 +7978,90 @@
 
 		/* Set fault module detected LED on */
 		bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0,
-				  MISC_REGISTERS_GPIO_HIGH,
-				  port);
+			       MISC_REGISTERS_GPIO_HIGH,
+			       port);
 	}
 
 	return 0;
 }
+static void bnx2x_get_ext_phy_reset_gpio(struct bnx2x *bp, u32 shmem_base,
+					 u8 *io_gpio, u8 *io_port)
+{
+
+	u32 phy_gpio_reset = REG_RD(bp, shmem_base +
+					  offsetof(struct shmem_region,
+				dev_info.port_hw_config[PORT_0].default_cfg));
+	switch (phy_gpio_reset) {
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0:
+		*io_gpio = 0;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0:
+		*io_gpio = 1;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0:
+		*io_gpio = 2;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0:
+		*io_gpio = 3;
+		*io_port = 0;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1:
+		*io_gpio = 0;
+		*io_port = 1;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1:
+		*io_gpio = 1;
+		*io_port = 1;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1:
+		*io_gpio = 2;
+		*io_port = 1;
+		break;
+	case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1:
+		*io_gpio = 3;
+		*io_port = 1;
+		break;
+	default:
+		/* Don't override the io_gpio and io_port */
+		break;
+	}
+}
 static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp,
 				     u32 shmem_base_path[],
 				     u32 shmem2_base_path[], u8 phy_index,
 				     u32 chip_id)
 {
-	s8 port;
+	s8 port, reset_gpio;
 	u32 swap_val, swap_override;
 	struct bnx2x_phy phy[PORT_MAX];
 	struct bnx2x_phy *phy_blk[PORT_MAX];
 	s8 port_of_path;
-	swap_val = REG_RD(bp,  NIG_REG_PORT_SWAP);
-	swap_override = REG_RD(bp,  NIG_REG_STRAP_OVERRIDE);
+	swap_val = REG_RD(bp, NIG_REG_PORT_SWAP);
+	swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE);
 
+	reset_gpio = MISC_REGISTERS_GPIO_1;
 	port = 1;
 
-	bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override));
+	/*
+	 * Retrieve the reset gpio/port which control the reset.
+	 * Default is GPIO1, PORT1
+	 */
+	bnx2x_get_ext_phy_reset_gpio(bp, shmem_base_path[0],
+				     (u8 *)&reset_gpio, (u8 *)&port);
 
 	/* Calculate the port based on port swap */
 	port ^= (swap_val && swap_override);
 
+	/* Initiate PHY reset*/
+	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW,
+		       port);
+	msleep(1);
+	bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH,
+		       port);
+
 	msleep(5);
 
 	/* PART1 - Reset both phys */
@@ -7907,9 +8097,7 @@
 
 		/* Reset the phy */
 		bnx2x_cl45_write(bp, &phy[port],
-			       MDIO_PMA_DEVAD,
-			       MDIO_PMA_REG_CTRL,
-			       1<<15);
+				 MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15);
 	}
 
 	/* Add delay of 150ms after reset */
@@ -7923,7 +8111,7 @@
 	}
 	/* PART2 - Download firmware to both phys */
 	for (port = PORT_MAX - 1; port >= PORT_0; port--) {
-		 if (CHIP_IS_E2(bp))
+		if (CHIP_IS_E2(bp))
 			port_of_path = 0;
 		else
 			port_of_path = port;
@@ -7958,8 +8146,10 @@
 		break;
 
 	case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726:
-		/* GPIO1 affects both ports, so there's need to pull
-		it for single port alone */
+		/*
+		 * GPIO1 affects both ports, so there's need to pull
+		 * it for single port alone
+		 */
 		rc = bnx2x_8726_common_init_phy(bp, shmem_base_path,
 						shmem2_base_path,
 						phy_index, chip_id);
@@ -7969,11 +8159,15 @@
 		break;
 	default:
 		DP(NETIF_MSG_LINK,
-			 "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
-			 ext_phy_type);
+			   "ext_phy 0x%x common init not required\n",
+			   ext_phy_type);
 		break;
 	}
 
+	if (rc != 0)
+		netdev_err(bp->dev,  "Warning: PHY was not initialized,"
+				      " Port %d\n",
+			 0);
 	return rc;
 }
 
@@ -7986,9 +8180,6 @@
 	u32 ext_phy_type, ext_phy_config;
 	DP(NETIF_MSG_LINK, "Begin common phy init\n");
 
-	if (CHIP_REV_IS_EMUL(bp))
-		return 0;
-
 	/* Check if common init was already done */
 	phy_ver = REG_RD(bp, shmem_base_path[0] +
 			 offsetof(struct shmem_region,
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_link.h linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_link.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_link.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_link.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,4 +1,4 @@
-/* Copyright 2008-2010 Broadcom Corporation
+/* Copyright 2008-2011 Broadcom Corporation
  *
  * Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
@@ -33,7 +33,7 @@
 #define BNX2X_FLOW_CTRL_BOTH		PORT_FEATURE_FLOW_CONTROL_BOTH
 #define BNX2X_FLOW_CTRL_NONE		PORT_FEATURE_FLOW_CONTROL_NONE
 
-#define SPEED_AUTO_NEG	    0
+#define SPEED_AUTO_NEG		0
 #define SPEED_12000		12000
 #define SPEED_12500		12500
 #define SPEED_13000		13000
@@ -44,8 +44,8 @@
 #define SFP_EEPROM_VENDOR_NAME_SIZE		16
 #define SFP_EEPROM_VENDOR_OUI_ADDR		0x25
 #define SFP_EEPROM_VENDOR_OUI_SIZE		3
-#define SFP_EEPROM_PART_NO_ADDR 		0x28
-#define SFP_EEPROM_PART_NO_SIZE		16
+#define SFP_EEPROM_PART_NO_ADDR			0x28
+#define SFP_EEPROM_PART_NO_SIZE			16
 #define PWR_FLT_ERR_MSG_LEN			250
 
 #define XGXS_EXT_PHY_TYPE(ext_phy_config) \
@@ -62,7 +62,7 @@
 #define SINGLE_MEDIA(params)		(params->num_phys == 2)
 /* Dual Media board contains two external phy with different media */
 #define DUAL_MEDIA(params)		(params->num_phys == 3)
-#define FW_PARAM_MDIO_CTRL_OFFSET 16
+#define FW_PARAM_MDIO_CTRL_OFFSET		16
 #define FW_PARAM_SET(phy_addr, phy_type, mdio_access) \
 	(phy_addr | phy_type | mdio_access << FW_PARAM_MDIO_CTRL_OFFSET)
 
@@ -201,12 +201,14 @@
 
 	/* Default / User Configuration */
 	u8 loopback_mode;
-#define LOOPBACK_NONE	0
-#define LOOPBACK_EMAC	1
-#define LOOPBACK_BMAC	2
+#define LOOPBACK_NONE		0
+#define LOOPBACK_EMAC		1
+#define LOOPBACK_BMAC		2
 #define LOOPBACK_XGXS		3
 #define LOOPBACK_EXT_PHY	4
-#define LOOPBACK_EXT 	5
+#define LOOPBACK_EXT		5
+#define LOOPBACK_UMAC		6
+#define LOOPBACK_XMAC		7
 
 	/* Device parameters */
 	u8 mac_addr[6];
@@ -230,10 +232,11 @@
 	/* Phy register parameter */
 	u32 chip_id;
 
+	/* features */
 	u32 feature_config_flags;
-#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0)
-#define FEATURE_CONFIG_PFC_ENABLED		(1<<1)
-#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY	(1<<2)
+#define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED	(1<<0)
+#define FEATURE_CONFIG_PFC_ENABLED			(1<<1)
+#define FEATURE_CONFIG_BC_SUPPORTS_OPT_MDL_VRFY		(1<<2)
 #define FEATURE_CONFIG_BC_SUPPORTS_DUAL_PHY_OPT_MDL_VRFY	(1<<3)
 	/* Will be populated during common init */
 	struct bnx2x_phy phy[MAX_PHYS];
@@ -334,6 +337,11 @@
 /* Reset the external of SFX7101 */
 void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy);
 
+/* Read "byte_cnt" bytes from address "addr" from the SFP+ EEPROM */
+u8 bnx2x_read_sfp_module_eeprom(struct bnx2x_phy *phy,
+				struct link_params *params, u16 addr,
+				u8 byte_cnt, u8 *o_buf);
+
 void bnx2x_hw_reset_phy(struct link_params *params);
 
 /* Checks if HW lock is required for this phy/board type */
@@ -379,7 +387,7 @@
 
 /* Used to configure the ETS to BW limited */
 void bnx2x_ets_bw_limit(const struct link_params *params, const u32 cos0_bw,
-						const u32 cos1_bw);
+			const u32 cos1_bw);
 
 /* Used to configure the ETS to strict */
 u8 bnx2x_ets_strict(const struct link_params *params, const u8 strict_cos);
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_main.c linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_main.c
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_main.c	2012-03-24 01:06:59.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_main.c	2012-03-24 03:30:21.000000000 -0400
@@ -142,13 +142,6 @@
 	{ "Broadcom NetXtreme II BCM57712E XGb" }
 };
 
-#ifndef PCI_DEVICE_ID_NX2_57712
-#define PCI_DEVICE_ID_NX2_57712		0x1662
-#endif
-#ifndef PCI_DEVICE_ID_NX2_57712E
-#define PCI_DEVICE_ID_NX2_57712E	0x1663
-#endif
-
 static DEFINE_PCI_DEVICE_TABLE(bnx2x_pci_tbl) = {
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57710), BCM57710 },
 	{ PCI_VDEVICE(BROADCOM, PCI_DEVICE_ID_NX2_57711), BCM57711 },
@@ -583,7 +576,7 @@
 	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
 	/* lock the dmae channel */
-	mutex_lock(&bp->dmae_mutex);
+	spin_lock_bh(&bp->dmae_lock);
 
 	/* reset completion */
 	*wb_comp = 0;
@@ -614,7 +607,7 @@
 	   bp->slowpath->wb_data[2], bp->slowpath->wb_data[3]);
 
 unlock:
-	mutex_unlock(&bp->dmae_mutex);
+	spin_unlock_bh(&bp->dmae_lock);
 	return rc;
 }
 
@@ -1394,7 +1387,7 @@
 	}
 
 	smp_mb__before_atomic_inc();
-	atomic_inc(&bp->spq_left);
+	atomic_inc(&bp->cq_spq_left);
 	/* push the change in fp->state and towards the memory */
 	smp_wmb();
 
@@ -2481,8 +2474,14 @@
 	rxq_init->sge_map = fp->rx_sge_mapping;
 	rxq_init->rcq_map = fp->rx_comp_mapping;
 	rxq_init->rcq_np_map = fp->rx_comp_mapping + BCM_PAGE_SIZE;
-	rxq_init->mtu = bp->dev->mtu;
-	rxq_init->buf_sz = bp->rx_buf_size;
+
+	/* Always use mini-jumbo MTU for FCoE L2 ring */
+	if (IS_FCOE_FP(fp))
+		rxq_init->mtu = BNX2X_FCOE_MINI_JUMBO_MTU;
+	else
+		rxq_init->mtu = bp->dev->mtu;
+
+	rxq_init->buf_sz = fp->rx_buf_size;
 	rxq_init->cl_qzone_id = fp->cl_qzone_id;
 	rxq_init->cl_id = fp->cl_id;
 	rxq_init->spcl_id = fp->cl_id;
@@ -2734,11 +2733,18 @@
 
 	spin_lock_bh(&bp->spq_lock);
 
-	if (!atomic_read(&bp->spq_left)) {
-		BNX2X_ERR("BUG! SPQ ring full!\n");
-		spin_unlock_bh(&bp->spq_lock);
-		bnx2x_panic();
-		return -EBUSY;
+	if (common) {
+		if (!atomic_read(&bp->eq_spq_left)) {
+			BNX2X_ERR("BUG! EQ ring full!\n");
+			spin_unlock_bh(&bp->spq_lock);
+			bnx2x_panic();
+			return -EBUSY;
+		}
+	} else if (!atomic_read(&bp->cq_spq_left)) {
+			BNX2X_ERR("BUG! SPQ ring full!\n");
+			spin_unlock_bh(&bp->spq_lock);
+			bnx2x_panic();
+			return -EBUSY;
 	}
 
 	spe = bnx2x_sp_get_next(bp);
@@ -2769,20 +2775,26 @@
 	spe->data.update_data_addr.lo = cpu_to_le32(data_lo);
 
 	/* stats ramrod has it's own slot on the spq */
-	if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY)
+	if (command != RAMROD_CMD_ID_COMMON_STAT_QUERY) {
 		/* It's ok if the actual decrement is issued towards the memory
 		 * somewhere between the spin_lock and spin_unlock. Thus no
 		 * more explict memory barrier is needed.
 		 */
-		atomic_dec(&bp->spq_left);
+		if (common)
+			atomic_dec(&bp->eq_spq_left);
+		else
+			atomic_dec(&bp->cq_spq_left);
+	}
+
 
 	DP(BNX2X_MSG_SP/*NETIF_MSG_TIMER*/,
 	   "SPQE[%x] (%x:%x)  command %d  hw_cid %x  data (%x:%x) "
-	   "type(0x%x) left %x\n",
+	   "type(0x%x) left (ETH, COMMON) (%x,%x)\n",
 	   bp->spq_prod_idx, (u32)U64_HI(bp->spq_mapping),
 	   (u32)(U64_LO(bp->spq_mapping) +
 	   (void *)bp->spq_prod_bd - (void *)bp->spq), command,
-	   HW_CID(bp, cid), data_hi, data_lo, type, atomic_read(&bp->spq_left));
+	   HW_CID(bp, cid), data_hi, data_lo, type,
+	   atomic_read(&bp->cq_spq_left), atomic_read(&bp->eq_spq_left));
 
 	bnx2x_sp_prod_update(bp);
 	spin_unlock_bh(&bp->spq_lock);
@@ -3687,15 +3699,15 @@
 	if ((hw_cons & EQ_DESC_MAX_PAGE) == EQ_DESC_MAX_PAGE)
 		hw_cons++;
 
-	/* This function may never run in parralel with itself for a
+	/* This function may never run in parallel with itself for a
 	 * specific bp, thus there is no need in "paired" read memory
 	 * barrier here.
 	 */
 	sw_cons = bp->eq_cons;
 	sw_prod = bp->eq_prod;
 
-	DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->spq_left %u\n",
-			hw_cons, sw_cons, atomic_read(&bp->spq_left));
+	DP(BNX2X_MSG_SP, "EQ:  hw_cons %u  sw_cons %u bp->cq_spq_left %u\n",
+			hw_cons, sw_cons, atomic_read(&bp->eq_spq_left));
 
 	for (; sw_cons != hw_cons;
 	      sw_prod = NEXT_EQ_IDX(sw_prod), sw_cons = NEXT_EQ_IDX(sw_cons)) {
@@ -3760,13 +3772,15 @@
 		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_OPEN):
 		case (EVENT_RING_OPCODE_SET_MAC | BNX2X_STATE_DIAG):
 			DP(NETIF_MSG_IFUP, "got set mac ramrod\n");
-			bp->set_mac_pending = 0;
+			if (elem->message.data.set_mac_event.echo)
+				bp->set_mac_pending = 0;
 			break;
 
 		case (EVENT_RING_OPCODE_SET_MAC |
 		      BNX2X_STATE_CLOSING_WAIT4_HALT):
 			DP(NETIF_MSG_IFDOWN, "got (un)set mac ramrod\n");
-			bp->set_mac_pending = 0;
+			if (elem->message.data.set_mac_event.echo)
+				bp->set_mac_pending = 0;
 			break;
 		default:
 			/* unknown event log error and continue */
@@ -3778,7 +3792,7 @@
 	} /* for */
 
 	smp_mb__before_atomic_inc();
-	atomic_add(spqe_cnt, &bp->spq_left);
+	atomic_add(spqe_cnt, &bp->eq_spq_left);
 
 	bp->eq_cons = sw_cons;
 	bp->eq_prod = sw_prod;
@@ -4205,13 +4219,13 @@
 
 	for_each_eth_queue(bp, i)
 		bnx2x_update_coalesce_sb(bp, bp->fp[i].fw_sb_id,
-					 bp->rx_ticks, bp->tx_ticks);
+					 bp->tx_ticks, bp->rx_ticks);
 }
 
 static void bnx2x_init_sp_ring(struct bnx2x *bp)
 {
 	spin_lock_init(&bp->spq_lock);
-	atomic_set(&bp->spq_left, MAX_SPQ_PENDING);
+	atomic_set(&bp->cq_spq_left, MAX_SPQ_PENDING);
 
 	bp->spq_prod_idx = 0;
 	bp->dsb_sp_prod = BNX2X_SP_DSB_INDEX;
@@ -4236,9 +4250,12 @@
 	bp->eq_cons = 0;
 	bp->eq_prod = NUM_EQ_DESC;
 	bp->eq_cons_sb = BNX2X_EQ_INDEX;
+	/* we want a warning message before it gets rought... */
+	atomic_set(&bp->eq_spq_left,
+		min_t(int, MAX_SP_DESC_CNT - MAX_SPQ_PENDING, NUM_EQ_DESC) - 1);
 }
 
-static void bnx2x_init_ind_table(struct bnx2x *bp)
+void bnx2x_push_indir_table(struct bnx2x *bp)
 {
 	int func = BP_FUNC(bp);
 	int i;
@@ -4246,13 +4263,20 @@
 	if (bp->multi_mode == ETH_RSS_MODE_DISABLED)
 		return;
 
-	DP(NETIF_MSG_IFUP,
-	   "Initializing indirection table  multi_mode %d\n", bp->multi_mode);
 	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
 		REG_WR8(bp, BAR_TSTRORM_INTMEM +
 			TSTORM_INDIRECTION_TABLE_OFFSET(func) + i,
-			bp->fp->cl_id + (i % (bp->num_queues -
-				NONE_ETH_CONTEXT_USE)));
+			bp->fp->cl_id + bp->rx_indir_table[i]);
+}
+
+static void bnx2x_init_ind_table(struct bnx2x *bp)
+{
+	int i;
+
+	for (i = 0; i < TSTORM_INDIRECTION_TABLE_SIZE; i++)
+		bp->rx_indir_table[i] = i % BNX2X_NUM_ETH_QUEUES(bp);
+
+	bnx2x_push_indir_table(bp);
 }
 
 void bnx2x_set_storm_rx_mode(struct bnx2x *bp)
@@ -5062,7 +5086,7 @@
 		/* Step 1: set zeroes to all ilt page entries with valid bit on
 		 * Step 2: set the timers first/last ilt entry to point
 		 * to the entire range to prevent ILT range error for 3rd/4th
-		 * vnic	(this code assumes existance of the vnic)
+		 * vnic	(this code assumes existence of the vnic)
 		 *
 		 * both steps performed by call to bnx2x_ilt_client_init_op()
 		 * with dummy TM client
@@ -5848,7 +5872,7 @@
 	   BP_ABS_FUNC(bp), load_code);
 
 	bp->dmae_ready = 0;
-	mutex_init(&bp->dmae_mutex);
+	spin_lock_init(&bp->dmae_lock);
 	rc = bnx2x_gunzip_init(bp);
 	if (rc)
 		return rc;
@@ -6000,6 +6024,8 @@
 	BNX2X_PCI_FREE(bp->eq_ring, bp->eq_mapping,
 		       BCM_PAGE_SIZE * NUM_EQ_PAGES);
 
+	BNX2X_FREE(bp->rx_indir_table);
+
 #undef BNX2X_PCI_FREE
 #undef BNX2X_KFREE
 }
@@ -6130,6 +6156,9 @@
 	/* EQ */
 	BNX2X_PCI_ALLOC(bp->eq_ring, &bp->eq_mapping,
 			BCM_PAGE_SIZE * NUM_EQ_PAGES);
+
+	BNX2X_ALLOC(bp->rx_indir_table, sizeof(bp->rx_indir_table[0]) *
+		    TSTORM_INDIRECTION_TABLE_SIZE);
 	return 0;
 
 alloc_mem_err:
@@ -6183,12 +6212,14 @@
 	int ramrod_flags = WAIT_RAMROD_COMMON;
 
 	bp->set_mac_pending = 1;
-	smp_wmb();
 
 	config->hdr.length = 1;
 	config->hdr.offset = cam_offset;
 	config->hdr.client_id = 0xff;
-	config->hdr.reserved1 = 0;
+	/* Mark the single MAC configuration ramrod as opposed to a
+	 * UC/MC list configuration).
+	 */
+	config->hdr.echo = 1;
 
 	/* primary MAC */
 	config->config_table[0].msb_mac_addr =
@@ -6220,6 +6251,8 @@
 	   config->config_table[0].middle_mac_addr,
 	   config->config_table[0].lsb_mac_addr, BP_FUNC(bp), cl_bit_vec);
 
+	mb();
+
 	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 		      U64_HI(bnx2x_sp_mapping(bp, mac_config)),
 		      U64_LO(bnx2x_sp_mapping(bp, mac_config)), 1);
@@ -6284,20 +6317,15 @@
 	if (CHIP_IS_E1H(bp))
 		return E1H_FUNC_MAX * rel_offset + BP_FUNC(bp);
 	else if (CHIP_MODE_IS_4_PORT(bp))
-		return BP_FUNC(bp) * 32  + rel_offset;
+		return E2_FUNC_MAX * rel_offset + BP_FUNC(bp);
 	else
-		return BP_VN(bp) * 32  + rel_offset;
+		return E2_FUNC_MAX * rel_offset + BP_VN(bp);
 }
 
 /**
  *  LLH CAM line allocations: currently only iSCSI and ETH macs are
  *  relevant. In addition, current implementation is tuned for a
  *  single ETH MAC.
- *
- *  When multiple unicast ETH MACs PF configuration in switch
- *  independent mode is required (NetQ, multiple netdev MACs,
- *  etc.), consider better utilisation of 16 per function MAC
- *  entries in the LLH memory.
  */
 enum {
 	LLH_CAM_ISCSI_ETH_LINE = 0,
@@ -6372,14 +6400,37 @@
 		bnx2x_set_mac_addr_gen(bp, set, bcast, 0, cam_offset + 1, 1);
 	}
 }
-static void bnx2x_set_e1_mc_list(struct bnx2x *bp, u8 offset)
+
+static inline u8 bnx2x_e1_cam_mc_offset(struct bnx2x *bp)
+{
+	return CHIP_REV_IS_SLOW(bp) ?
+		(BNX2X_MAX_EMUL_MULTI * (1 + BP_PORT(bp))) :
+		(BNX2X_MAX_MULTICAST * (1 + BP_PORT(bp)));
+}
+
+/* set mc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of a very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_e1_mc_list(struct bnx2x *bp)
 {
 	int i = 0, old;
 	struct net_device *dev = bp->dev;
+	u8 offset = bnx2x_e1_cam_mc_offset(bp);
 	struct netdev_hw_addr *ha;
 	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
 	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
 
+	if (netdev_mc_count(dev) > BNX2X_MAX_MULTICAST)
+		return -EINVAL;
+
 	netdev_for_each_mc_addr(ha, dev) {
 		/* copy mac */
 		config_cmd->config_table[i].msb_mac_addr =
@@ -6420,32 +6471,47 @@
 		}
 	}
 
+	wmb();
+
 	config_cmd->hdr.length = i;
 	config_cmd->hdr.offset = offset;
 	config_cmd->hdr.client_id = 0xff;
-	config_cmd->hdr.reserved1 = 0;
+	/* Mark that this ramrod doesn't use bp->set_mac_pending for
+	 * synchronization.
+	 */
+	config_cmd->hdr.echo = 0;
 
-	bp->set_mac_pending = 1;
-	smp_wmb();
+	mb();
 
-	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 		   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
 }
-static void bnx2x_invlidate_e1_mc_list(struct bnx2x *bp)
+
+void bnx2x_invalidate_e1_mc_list(struct bnx2x *bp)
 {
 	int i;
 	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, mcast_config);
 	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, mcast_config);
 	int ramrod_flags = WAIT_RAMROD_COMMON;
+	u8 offset = bnx2x_e1_cam_mc_offset(bp);
 
-	bp->set_mac_pending = 1;
-	smp_wmb();
-
-	for (i = 0; i < config_cmd->hdr.length; i++)
+	for (i = 0; i < BNX2X_MAX_MULTICAST; i++)
 		SET_FLAG(config_cmd->config_table[i].flags,
 			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
 			T_ETH_MAC_COMMAND_INVALIDATE);
 
+	wmb();
+
+	config_cmd->hdr.length = BNX2X_MAX_MULTICAST;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	/* We'll wait for a completion this time... */
+	config_cmd->hdr.echo = 1;
+
+	bp->set_mac_pending = 1;
+
+	mb();
+
 	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
 		      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
 
@@ -6455,6 +6521,44 @@
 
 }
 
+/* Accept one or more multicasts */
+static int bnx2x_set_e1h_mc_list(struct bnx2x *bp)
+{
+	struct net_device *dev = bp->dev;
+	struct netdev_hw_addr *ha;
+	u32 mc_filter[MC_HASH_SIZE];
+	u32 crc, bit, regidx;
+	int i;
+
+	memset(mc_filter, 0, 4 * MC_HASH_SIZE);
+
+	netdev_for_each_mc_addr(ha, dev) {
+		DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
+		   bnx2x_mc_addr(ha));
+
+		crc = crc32c_le(0, bnx2x_mc_addr(ha),
+				ETH_ALEN);
+		bit = (crc >> 24) & 0xff;
+		regidx = bit >> 5;
+		bit &= 0x1f;
+		mc_filter[regidx] |= (1 << bit);
+	}
+
+	for (i = 0; i < MC_HASH_SIZE; i++)
+		REG_WR(bp, MC_HASH_OFFSET(bp, i),
+		       mc_filter[i]);
+
+	return 0;
+}
+
+void bnx2x_invalidate_e1h_mc_list(struct bnx2x *bp)
+{
+	int i;
+
+	for (i = 0; i < MC_HASH_SIZE; i++)
+		REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+}
+
 #ifdef BCM_CNIC
 /**
  * Set iSCSI MAC(s) at the next enties in the CAM after the ETH
@@ -6473,12 +6577,13 @@
 	u32 iscsi_l2_cl_id = BNX2X_ISCSI_ETH_CL_ID +
 		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
 	u32 cl_bit_vec = (1 << iscsi_l2_cl_id);
+	u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
 
 	/* Send a SET_MAC ramrod */
-	bnx2x_set_mac_addr_gen(bp, set, bp->iscsi_mac, cl_bit_vec,
+	bnx2x_set_mac_addr_gen(bp, set, iscsi_mac, cl_bit_vec,
 			       cam_offset, 0);
 
-	bnx2x_set_mac_in_nig(bp, set, bp->iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
+	bnx2x_set_mac_in_nig(bp, set, iscsi_mac, LLH_CAM_ISCSI_ETH_LINE);
 
 	return 0;
 }
@@ -7120,20 +7225,15 @@
 	/* Give HW time to discard old tx messages */
 	msleep(1);
 
-	if (CHIP_IS_E1(bp)) {
-		/* invalidate mc list,
-		 * wait and poll (interrupts are off)
-		 */
-		bnx2x_invlidate_e1_mc_list(bp);
-		bnx2x_set_eth_mac(bp, 0);
-
-	} else {
-		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
+	bnx2x_set_eth_mac(bp, 0);
 
-		bnx2x_set_eth_mac(bp, 0);
+	bnx2x_invalidate_uc_list(bp);
 
-		for (i = 0; i < MC_HASH_SIZE; i++)
-			REG_WR(bp, MC_HASH_OFFSET(bp, i), 0);
+	if (CHIP_IS_E1(bp))
+		bnx2x_invalidate_e1_mc_list(bp);
+	else {
+		bnx2x_invalidate_e1h_mc_list(bp);
+		REG_WR(bp, NIG_REG_LLH0_FUNC_EN + port*8, 0);
 	}
 
 #ifdef BCM_CNIC
@@ -8402,11 +8502,47 @@
 							bp->common.shmem2_base);
 }
 
+#ifdef BCM_CNIC
+static void __devinit bnx2x_get_cnic_info(struct bnx2x *bp)
+{
+	u32 max_iscsi_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
+				drv_lic_key[BP_PORT(bp)].max_iscsi_conn);
+	u32 max_fcoe_conn = FW_ENCODE_32BIT_PATTERN ^ SHMEM_RD(bp,
+				drv_lic_key[BP_PORT(bp)].max_fcoe_conn);
+
+	/* Get the number of maximum allowed iSCSI and FCoE connections */
+	bp->cnic_eth_dev.max_iscsi_conn =
+		(max_iscsi_conn & BNX2X_MAX_ISCSI_INIT_CONN_MASK) >>
+		BNX2X_MAX_ISCSI_INIT_CONN_SHIFT;
+
+	bp->cnic_eth_dev.max_fcoe_conn =
+		(max_fcoe_conn & BNX2X_MAX_FCOE_INIT_CONN_MASK) >>
+		BNX2X_MAX_FCOE_INIT_CONN_SHIFT;
+
+	BNX2X_DEV_INFO("max_iscsi_conn 0x%x max_fcoe_conn 0x%x\n",
+		       bp->cnic_eth_dev.max_iscsi_conn,
+		       bp->cnic_eth_dev.max_fcoe_conn);
+
+	/* If mamimum allowed number of connections is zero -
+	 * disable the feature.
+	 */
+	if (!bp->cnic_eth_dev.max_iscsi_conn)
+		bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+
+	if (!bp->cnic_eth_dev.max_fcoe_conn)
+		bp->flags |= NO_FCOE_FLAG;
+}
+#endif
+
 static void __devinit bnx2x_get_mac_hwinfo(struct bnx2x *bp)
 {
 	u32 val, val2;
 	int func = BP_ABS_FUNC(bp);
 	int port = BP_PORT(bp);
+#ifdef BCM_CNIC
+	u8 *iscsi_mac = bp->cnic_eth_dev.iscsi_mac;
+	u8 *fip_mac = bp->fip_mac;
+#endif
 
 	if (BP_NOMCP(bp)) {
 		BNX2X_ERROR("warning: random MAC workaround active\n");
@@ -8419,7 +8555,9 @@
 			bnx2x_set_mac_buf(bp->dev->dev_addr, val, val2);
 
 #ifdef BCM_CNIC
-		/* iSCSI NPAR MAC */
+		/* iSCSI and FCoE NPAR MACs: if there is no either iSCSI or
+		 * FCoE MAC then the appropriate feature should be disabled.
+		 */
 		if (IS_MF_SI(bp)) {
 			u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
 			if (cfg & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD) {
@@ -8427,8 +8565,39 @@
 						     iscsi_mac_addr_upper);
 				val = MF_CFG_RD(bp, func_ext_config[func].
 						    iscsi_mac_addr_lower);
-				bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
-			}
+				BNX2X_DEV_INFO("Read iSCSI MAC: "
+					       "0x%x:0x%04x\n", val2, val);
+				bnx2x_set_mac_buf(iscsi_mac, val, val2);
+
+				/* Disable iSCSI OOO if MAC configuration is
+				 * invalid.
+				 */
+				if (!is_valid_ether_addr(iscsi_mac)) {
+					bp->flags |= NO_ISCSI_OOO_FLAG |
+						     NO_ISCSI_FLAG;
+					memset(iscsi_mac, 0, ETH_ALEN);
+				}
+			} else
+				bp->flags |= NO_ISCSI_OOO_FLAG | NO_ISCSI_FLAG;
+
+			if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD) {
+				val2 = MF_CFG_RD(bp, func_ext_config[func].
+						     fcoe_mac_addr_upper);
+				val = MF_CFG_RD(bp, func_ext_config[func].
+						    fcoe_mac_addr_lower);
+				BNX2X_DEV_INFO("Read FCoE MAC to "
+					       "0x%x:0x%04x\n", val2, val);
+				bnx2x_set_mac_buf(fip_mac, val, val2);
+
+				/* Disable FCoE if MAC configuration is
+				 * invalid.
+				 */
+				if (!is_valid_ether_addr(fip_mac)) {
+					bp->flags |= NO_FCOE_FLAG;
+					memset(bp->fip_mac, 0, ETH_ALEN);
+				}
+			} else
+				bp->flags |= NO_FCOE_FLAG;
 		}
 #endif
 	} else {
@@ -8442,7 +8611,7 @@
 				    iscsi_mac_upper);
 		val = SHMEM_RD(bp, dev_info.port_hw_config[port].
 				   iscsi_mac_lower);
-		bnx2x_set_mac_buf(bp->iscsi_mac, val, val2);
+		bnx2x_set_mac_buf(iscsi_mac, val, val2);
 #endif
 	}
 
@@ -8450,14 +8619,12 @@
 	memcpy(bp->dev->perm_addr, bp->dev->dev_addr, ETH_ALEN);
 
 #ifdef BCM_CNIC
-	/* Inform the upper layers about FCoE MAC */
+	/* Set the FCoE MAC in modes other then MF_SI */
 	if (!CHIP_IS_E1x(bp)) {
 		if (IS_MF_SD(bp))
-			memcpy(bp->fip_mac, bp->dev->dev_addr,
-			       sizeof(bp->fip_mac));
-		else
-			memcpy(bp->fip_mac, bp->iscsi_mac,
-			       sizeof(bp->fip_mac));
+			memcpy(fip_mac, bp->dev->dev_addr, ETH_ALEN);
+		else if (!IS_MF(bp))
+			memcpy(fip_mac, iscsi_mac, ETH_ALEN);
 	}
 #endif
 }
@@ -8515,7 +8682,7 @@
 				E1H_FUNC_MAX * sizeof(struct drv_func_mb);
 		/*
 		 * get mf configuration:
-		 * 1. existance of MF configuration
+		 * 1. existence of MF configuration
 		 * 2. MAC address must be legal (check only upper bytes)
 		 *    for  Switch-Independent mode;
 		 *    OVLAN must be legal for Switch-Dependent mode
@@ -8557,7 +8724,7 @@
 			default:
 				/* Unknown configuration: reset mf_config */
 				bp->mf_config[vn] = 0;
-				DP(NETIF_MSG_PROBE, "Unkown MF mode 0x%x\n",
+				DP(NETIF_MSG_PROBE, "Unknown MF mode 0x%x\n",
 				   val);
 			}
 		}
@@ -8620,6 +8787,10 @@
 	/* Get MAC addresses */
 	bnx2x_get_mac_hwinfo(bp);
 
+#ifdef BCM_CNIC
+	bnx2x_get_cnic_info(bp);
+#endif
+
 	return rc;
 }
 
@@ -8834,12 +9005,197 @@
 	return 0;
 }
 
+#define E1_MAX_UC_LIST	29
+#define E1H_MAX_UC_LIST	30
+#define E2_MAX_UC_LIST	14
+static inline u8 bnx2x_max_uc_list(struct bnx2x *bp)
+{
+	if (CHIP_IS_E1(bp))
+		return E1_MAX_UC_LIST;
+	else if (CHIP_IS_E1H(bp))
+		return E1H_MAX_UC_LIST;
+	else
+		return E2_MAX_UC_LIST;
+}
+
+
+static inline u8 bnx2x_uc_list_cam_offset(struct bnx2x *bp)
+{
+	if (CHIP_IS_E1(bp))
+		/* CAM Entries for Port0:
+		 *      0 - prim ETH MAC
+		 *      1 - BCAST MAC
+		 *      2 - iSCSI L2 ring ETH MAC
+		 *      3-31 - UC MACs
+		 *
+		 * Port1 entries are allocated the same way starting from
+		 * entry 32.
+		 */
+		return 3 + 32 * BP_PORT(bp);
+	else if (CHIP_IS_E1H(bp)) {
+		/* CAM Entries:
+		 *      0-7  - prim ETH MAC for each function
+		 *      8-15 - iSCSI L2 ring ETH MAC for each function
+		 *      16 till 255 UC MAC lists for each function
+		 *
+		 * Remark: There is no FCoE support for E1H, thus FCoE related
+		 *         MACs are not considered.
+		 */
+		return E1H_FUNC_MAX * (CAM_ISCSI_ETH_LINE + 1) +
+			bnx2x_max_uc_list(bp) * BP_FUNC(bp);
+	} else {
+		/* CAM Entries (there is a separate CAM per engine):
+		 *      0-4  - prim ETH MAC for each function
+		 *      4-7 - iSCSI L2 ring ETH MAC for each function
+		 *      8-11 - FIP ucast L2 MAC for each function
+		 *      12-15 - ALL_ENODE_MACS mcast MAC for each function
+		 *      16 till 71 UC MAC lists for each function
+		 */
+		u8 func_idx =
+			(CHIP_MODE_IS_4_PORT(bp) ? BP_FUNC(bp) : BP_VN(bp));
+
+		return E2_FUNC_MAX * (CAM_MAX_PF_LINE + 1) +
+			bnx2x_max_uc_list(bp) * func_idx;
+	}
+}
+
+/* set uc list, do not wait as wait implies sleep and
+ * set_rx_mode can be invoked from non-sleepable context.
+ *
+ * Instead we use the same ramrod data buffer each time we need
+ * to configure a list of addresses, and use the fact that the
+ * list of MACs is changed in an incremental way and that the
+ * function is called under the netif_addr_lock. A temporary
+ * inconsistent CAM configuration (possible in case of very fast
+ * sequence of add/del/add on the host side) will shortly be
+ * restored by the handler of the last ramrod.
+ */
+static int bnx2x_set_uc_list(struct bnx2x *bp)
+{
+	int i = 0, old;
+	struct net_device *dev = bp->dev;
+	u8 offset = bnx2x_uc_list_cam_offset(bp);
+	struct netdev_hw_addr *ha;
+	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+
+	if (netdev_uc_count(dev) > bnx2x_max_uc_list(bp))
+		return -EINVAL;
+
+	netdev_for_each_uc_addr(ha, dev) {
+		/* copy mac */
+		config_cmd->config_table[i].msb_mac_addr =
+			swab16(*(u16 *)&bnx2x_uc_addr(ha)[0]);
+		config_cmd->config_table[i].middle_mac_addr =
+			swab16(*(u16 *)&bnx2x_uc_addr(ha)[2]);
+		config_cmd->config_table[i].lsb_mac_addr =
+			swab16(*(u16 *)&bnx2x_uc_addr(ha)[4]);
+
+		config_cmd->config_table[i].vlan_id = 0;
+		config_cmd->config_table[i].pf_id = BP_FUNC(bp);
+		config_cmd->config_table[i].clients_bit_vector =
+			cpu_to_le32(1 << BP_L_ID(bp));
+
+		SET_FLAG(config_cmd->config_table[i].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_SET);
+
+		DP(NETIF_MSG_IFUP,
+		   "setting UCAST[%d] (%04x:%04x:%04x)\n", i,
+		   config_cmd->config_table[i].msb_mac_addr,
+		   config_cmd->config_table[i].middle_mac_addr,
+		   config_cmd->config_table[i].lsb_mac_addr);
+
+		i++;
+
+		/* Set uc MAC in NIG */
+		bnx2x_set_mac_in_nig(bp, 1, bnx2x_uc_addr(ha),
+				     LLH_CAM_ETH_LINE + i);
+	}
+	old = config_cmd->hdr.length;
+	if (old > i) {
+		for (; i < old; i++) {
+			if (CAM_IS_INVALID(config_cmd->
+					   config_table[i])) {
+				/* already invalidated */
+				break;
+			}
+			/* invalidate */
+			SET_FLAG(config_cmd->config_table[i].flags,
+				MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+				T_ETH_MAC_COMMAND_INVALIDATE);
+		}
+	}
+
+	wmb();
+
+	config_cmd->hdr.length = i;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	/* Mark that this ramrod doesn't use bp->set_mac_pending for
+	 * synchronization.
+	 */
+	config_cmd->hdr.echo = 0;
+
+	mb();
+
+	return bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+		   U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+}
+
+void bnx2x_invalidate_uc_list(struct bnx2x *bp)
+{
+	int i;
+	struct mac_configuration_cmd *config_cmd = bnx2x_sp(bp, uc_mac_config);
+	dma_addr_t config_cmd_map = bnx2x_sp_mapping(bp, uc_mac_config);
+	int ramrod_flags = WAIT_RAMROD_COMMON;
+	u8 offset = bnx2x_uc_list_cam_offset(bp);
+	u8 max_list_size = bnx2x_max_uc_list(bp);
+
+	for (i = 0; i < max_list_size; i++) {
+		SET_FLAG(config_cmd->config_table[i].flags,
+			MAC_CONFIGURATION_ENTRY_ACTION_TYPE,
+			T_ETH_MAC_COMMAND_INVALIDATE);
+		bnx2x_set_mac_in_nig(bp, 0, NULL, LLH_CAM_ETH_LINE + 1 + i);
+	}
+
+	wmb();
+
+	config_cmd->hdr.length = max_list_size;
+	config_cmd->hdr.offset = offset;
+	config_cmd->hdr.client_id = 0xff;
+	/* We'll wait for a completion this time... */
+	config_cmd->hdr.echo = 1;
+
+	bp->set_mac_pending = 1;
+
+	mb();
+
+	bnx2x_sp_post(bp, RAMROD_CMD_ID_COMMON_SET_MAC, 0,
+		      U64_HI(config_cmd_map), U64_LO(config_cmd_map), 1);
+
+	/* Wait for a completion */
+	bnx2x_wait_ramrod(bp, 0, 0, &bp->set_mac_pending,
+				ramrod_flags);
+
+}
+
+static inline int bnx2x_set_mc_list(struct bnx2x *bp)
+{
+	/* some multicasts */
+	if (CHIP_IS_E1(bp)) {
+		return bnx2x_set_e1_mc_list(bp);
+	} else { /* E1H and newer */
+		return bnx2x_set_e1h_mc_list(bp);
+	}
+}
+
 /* called with netif_tx_lock from dev_mcast.c */
 void bnx2x_set_rx_mode(struct net_device *dev)
 {
 	struct bnx2x *bp = netdev_priv(dev);
 	u32 rx_mode = BNX2X_RX_MODE_NORMAL;
-	int port = BP_PORT(bp);
 
 	if (bp->state != BNX2X_STATE_OPEN) {
 		DP(NETIF_MSG_IFUP, "state is %x, returning\n", bp->state);
@@ -8850,47 +9206,16 @@
 
 	if (dev->flags & IFF_PROMISC)
 		rx_mode = BNX2X_RX_MODE_PROMISC;
-	else if ((dev->flags & IFF_ALLMULTI) ||
-		 ((netdev_mc_count(dev) > BNX2X_MAX_MULTICAST) &&
-		  CHIP_IS_E1(bp)))
+	else if (dev->flags & IFF_ALLMULTI)
 		rx_mode = BNX2X_RX_MODE_ALLMULTI;
-	else { /* some multicasts */
-		if (CHIP_IS_E1(bp)) {
-			/*
-			 * set mc list, do not wait as wait implies sleep
-			 * and set_rx_mode can be invoked from non-sleepable
-			 * context
-			 */
-			u8 offset = (CHIP_REV_IS_SLOW(bp) ?
-				     BNX2X_MAX_EMUL_MULTI*(1 + port) :
-				     BNX2X_MAX_MULTICAST*(1 + port));
-
-			bnx2x_set_e1_mc_list(bp, offset);
-		} else { /* E1H */
-			/* Accept one or more multicasts */
-			struct netdev_hw_addr *ha;
-			u32 mc_filter[MC_HASH_SIZE];
-			u32 crc, bit, regidx;
-			int i;
-
-			memset(mc_filter, 0, 4 * MC_HASH_SIZE);
-
-			netdev_for_each_mc_addr(ha, dev) {
-				DP(NETIF_MSG_IFUP, "Adding mcast MAC: %pM\n",
-				   bnx2x_mc_addr(ha));
-
-				crc = crc32c_le(0, bnx2x_mc_addr(ha),
-						ETH_ALEN);
-				bit = (crc >> 24) & 0xff;
-				regidx = bit >> 5;
-				bit &= 0x1f;
-				mc_filter[regidx] |= (1 << bit);
-			}
+	else {
+		/* some multicasts */
+		if (bnx2x_set_mc_list(bp))
+			rx_mode = BNX2X_RX_MODE_ALLMULTI;
 
-			for (i = 0; i < MC_HASH_SIZE; i++)
-				REG_WR(bp, MC_HASH_OFFSET(bp, i),
-				       mc_filter[i]);
-		}
+		/* some unicasts */
+		if (bnx2x_set_uc_list(bp))
+			rx_mode = BNX2X_RX_MODE_PROMISC;
 	}
 
 	bp->rx_mode = rx_mode;
@@ -8971,7 +9296,7 @@
 	.ndo_stop		= bnx2x_close,
 	.ndo_start_xmit		= bnx2x_start_xmit,
 	.ndo_select_queue	= bnx2x_select_queue,
-	.ndo_set_multicast_list	= bnx2x_set_rx_mode,
+	.ndo_set_rx_mode	= bnx2x_set_rx_mode,
 	.ndo_set_mac_address	= bnx2x_change_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_do_ioctl		= bnx2x_ioctl,
@@ -9117,7 +9442,7 @@
 	dev->vlan_features |= (NETIF_F_TSO | NETIF_F_TSO_ECN);
 	dev->vlan_features |= NETIF_F_TSO6;
 
-#ifdef BCM_DCB
+#ifdef BCM_DCBNL
 	dev->dcbnl_ops = &bnx2x_dcbnl_ops;
 #endif
 
@@ -9390,7 +9715,7 @@
 
 #endif
 
-	/* Configure interupt mode: try to enable MSI-X/MSI if
+	/* Configure interrupt mode: try to enable MSI-X/MSI if
 	 * needed, set bp->num_queues appropriately.
 	 */
 	bnx2x_set_int_mode(bp);
@@ -9465,6 +9790,11 @@
 	}
 #endif
 
+#ifdef BCM_DCBNL
+	/* Delete app tlvs from dcbnl */
+	bnx2x_dcbnl_update_applist(bp, true);
+#endif
+
 	unregister_netdev(dev);
 
 	/* Delete all NAPI objects */
@@ -9738,15 +10068,21 @@
 					HW_CID(bp, BNX2X_ISCSI_ETH_CID));
 		}
 
-		/* There may be not more than 8 L2 and COMMON SPEs and not more
-		 * than 8 L5 SPEs in the air.
+		/* There may be not more than 8 L2 and not more than 8 L5 SPEs
+		 * We also check that the number of outstanding
+		 * COMMON ramrods is not more than the EQ and SPQ can
+		 * accommodate.
 		 */
-		if ((type == NONE_CONNECTION_TYPE) ||
-		    (type == ETH_CONNECTION_TYPE)) {
-			if (!atomic_read(&bp->spq_left))
+		if (type == ETH_CONNECTION_TYPE) {
+			if (!atomic_read(&bp->cq_spq_left))
 				break;
 			else
-				atomic_dec(&bp->spq_left);
+				atomic_dec(&bp->cq_spq_left);
+		} else if (type == NONE_CONNECTION_TYPE) {
+			if (!atomic_read(&bp->eq_spq_left))
+				break;
+			else
+				atomic_dec(&bp->eq_spq_left);
 		} else if ((type == ISCSI_CONNECTION_TYPE) ||
 			   (type == FCOE_CONNECTION_TYPE)) {
 			if (bp->cnic_spq_pending >=
@@ -9824,7 +10160,8 @@
 	int rc = 0;
 
 	mutex_lock(&bp->cnic_mutex);
-	c_ops = bp->cnic_ops;
+	c_ops = rcu_dereference_protected(bp->cnic_ops,
+					  lockdep_is_held(&bp->cnic_mutex));
 	if (c_ops)
 		rc = c_ops->cnic_ctl(bp->cnic_data, ctl);
 	mutex_unlock(&bp->cnic_mutex);
@@ -9938,7 +10275,7 @@
 		int count = ctl->data.credit.credit_count;
 
 		smp_mb__before_atomic_inc();
-		atomic_add(count, &bp->spq_left);
+		atomic_add(count, &bp->cq_spq_left);
 		smp_mb__after_atomic_inc();
 		break;
 	}
@@ -10034,6 +10371,13 @@
 	struct bnx2x *bp = netdev_priv(dev);
 	struct cnic_eth_dev *cp = &bp->cnic_eth_dev;
 
+	/* If both iSCSI and FCoE are disabled - return NULL in
+	 * order to indicate CNIC that it should not try to work
+	 * with this device.
+	 */
+	if (NO_ISCSI(bp) && NO_FCOE(bp))
+		return NULL;
+
 	cp->drv_owner = THIS_MODULE;
 	cp->chip_id = CHIP_ID(bp);
 	cp->pdev = bp->pdev;
@@ -10054,6 +10398,15 @@
 		BP_E1HVN(bp) * NONE_ETH_CONTEXT_USE;
 	cp->iscsi_l2_cid = BNX2X_ISCSI_ETH_CID;
 
+	if (NO_ISCSI_OOO(bp))
+		cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI_OOO;
+
+	if (NO_ISCSI(bp))
+		cp->drv_state |= CNIC_DRV_STATE_NO_ISCSI;
+
+	if (NO_FCOE(bp))
+		cp->drv_state |= CNIC_DRV_STATE_NO_FCOE;
+
 	DP(BNX2X_MSG_SP, "page_size %d, tbl_offset %d, tbl_lines %d, "
 			 "starting cid %d\n",
 	   cp->ctx_blk_size,
diff -druN linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_reg.h linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_reg.h
--- linux-libre-2.6.38-gnu/drivers/net/bnx2x/bnx2x_reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bnx2x/bnx2x_reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -175,9 +175,9 @@
    the initial credit value; read returns the current value of the credit
    counter. Must be initialized to 1 at start-up. */
 #define CCM_REG_CFC_INIT_CRD					 0xd0204
-/* [RW 2] Auxillary counter flag Q number 1. */
+/* [RW 2] Auxiliary counter flag Q number 1. */
 #define CCM_REG_CNT_AUX1_Q					 0xd00c8
-/* [RW 2] Auxillary counter flag Q number 2. */
+/* [RW 2] Auxiliary counter flag Q number 2. */
 #define CCM_REG_CNT_AUX2_Q					 0xd00cc
 /* [RW 28] The CM header value for QM request (primary). */
 #define CCM_REG_CQM_CCM_HDR_P					 0xd008c
@@ -457,13 +457,13 @@
 #define CSDM_REG_AGG_INT_MODE_9 				 0xc21dc
 /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
 #define CSDM_REG_CFC_RSP_START_ADDR				 0xc2008
-/* [RW 16] The maximum value of the competion counter #0 */
+/* [RW 16] The maximum value of the completion counter #0 */
 #define CSDM_REG_CMP_COUNTER_MAX0				 0xc201c
-/* [RW 16] The maximum value of the competion counter #1 */
+/* [RW 16] The maximum value of the completion counter #1 */
 #define CSDM_REG_CMP_COUNTER_MAX1				 0xc2020
-/* [RW 16] The maximum value of the competion counter #2 */
+/* [RW 16] The maximum value of the completion counter #2 */
 #define CSDM_REG_CMP_COUNTER_MAX2				 0xc2024
-/* [RW 16] The maximum value of the competion counter #3 */
+/* [RW 16] The maximum value of the completion counter #3 */
 #define CSDM_REG_CMP_COUNTER_MAX3				 0xc2028
 /* [RW 13] The start address in the internal RAM for the completion
    counters. */
@@ -851,7 +851,7 @@
 #define IGU_REG_ATTN_MSG_ADDR_L				 0x130120
 /* [R 4] Debug: [3] - attention write done message is pending (0-no pending;
  * 1-pending). [2:0] = PFID. Pending means attention message was sent; but
- * write done didnt receive. */
+ * write done didn't receive. */
 #define IGU_REG_ATTN_WRITE_DONE_PENDING			 0x130030
 #define IGU_REG_BLOCK_CONFIGURATION				 0x130000
 #define IGU_REG_COMMAND_REG_32LSB_DATA				 0x130124
@@ -862,7 +862,7 @@
 #define IGU_REG_CSTORM_TYPE_0_SB_CLEANUP			 0x130200
 /* [R 5] Debug: ctrl_fsm */
 #define IGU_REG_CTRL_FSM					 0x130064
-/* [R 1] data availble for error memory. If this bit is clear do not red
+/* [R 1] data available for error memory. If this bit is clear do not red
  * from error_handling_memory. */
 #define IGU_REG_ERROR_HANDLING_DATA_VALID			 0x130130
 /* [RW 11] Parity mask register #0 read/write */
@@ -3015,7 +3015,7 @@
    block. Should be used for close the gates. */
 #define PXP_REG_HST_DISCARD_DOORBELLS				 0x1030a4
 /* [R 1] debug only: '1' means this PSWHST is discarding doorbells. This bit
-   should update accoring to 'hst_discard_doorbells' register when the state
+   should update according to 'hst_discard_doorbells' register when the state
    machine is idle */
 #define PXP_REG_HST_DISCARD_DOORBELLS_STATUS			 0x1030a0
 /* [RW 1] When 1; new internal writes arriving to the block are discarded.
@@ -3023,7 +3023,7 @@
 #define PXP_REG_HST_DISCARD_INTERNAL_WRITES			 0x1030a8
 /* [R 6] debug only: A bit mask for all PSWHST internal write clients. '1'
    means this PSWHST is discarding inputs from this client. Each bit should
-   update accoring to 'hst_discard_internal_writes' register when the state
+   update according to 'hst_discard_internal_writes' register when the state
    machine is idle. */
 #define PXP_REG_HST_DISCARD_INTERNAL_WRITES_STATUS		 0x10309c
 /* [WB 160] Used for initialization of the inbound interrupts memory */
@@ -3822,13 +3822,13 @@
 #define TSDM_REG_AGG_INT_T_1					 0x420bc
 /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
 #define TSDM_REG_CFC_RSP_START_ADDR				 0x42008
-/* [RW 16] The maximum value of the competion counter #0 */
+/* [RW 16] The maximum value of the completion counter #0 */
 #define TSDM_REG_CMP_COUNTER_MAX0				 0x4201c
-/* [RW 16] The maximum value of the competion counter #1 */
+/* [RW 16] The maximum value of the completion counter #1 */
 #define TSDM_REG_CMP_COUNTER_MAX1				 0x42020
-/* [RW 16] The maximum value of the competion counter #2 */
+/* [RW 16] The maximum value of the completion counter #2 */
 #define TSDM_REG_CMP_COUNTER_MAX2				 0x42024
-/* [RW 16] The maximum value of the competion counter #3 */
+/* [RW 16] The maximum value of the completion counter #3 */
 #define TSDM_REG_CMP_COUNTER_MAX3				 0x42028
 /* [RW 13] The start address in the internal RAM for the completion
    counters. */
@@ -4284,13 +4284,13 @@
 #define USDM_REG_AGG_INT_T_6					 0xc40d0
 /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
 #define USDM_REG_CFC_RSP_START_ADDR				 0xc4008
-/* [RW 16] The maximum value of the competion counter #0 */
+/* [RW 16] The maximum value of the completion counter #0 */
 #define USDM_REG_CMP_COUNTER_MAX0				 0xc401c
-/* [RW 16] The maximum value of the competion counter #1 */
+/* [RW 16] The maximum value of the completion counter #1 */
 #define USDM_REG_CMP_COUNTER_MAX1				 0xc4020
-/* [RW 16] The maximum value of the competion counter #2 */
+/* [RW 16] The maximum value of the completion counter #2 */
 #define USDM_REG_CMP_COUNTER_MAX2				 0xc4024
-/* [RW 16] The maximum value of the competion counter #3 */
+/* [RW 16] The maximum value of the completion counter #3 */
 #define USDM_REG_CMP_COUNTER_MAX3				 0xc4028
 /* [RW 13] The start address in the internal RAM for the completion
    counters. */
@@ -4798,13 +4798,13 @@
 #define XSDM_REG_AGG_INT_MODE_1 				 0x1661bc
 /* [RW 13] The start address in the internal RAM for the cfc_rsp lcid */
 #define XSDM_REG_CFC_RSP_START_ADDR				 0x166008
-/* [RW 16] The maximum value of the competion counter #0 */
+/* [RW 16] The maximum value of the completion counter #0 */
 #define XSDM_REG_CMP_COUNTER_MAX0				 0x16601c
-/* [RW 16] The maximum value of the competion counter #1 */
+/* [RW 16] The maximum value of the completion counter #1 */
 #define XSDM_REG_CMP_COUNTER_MAX1				 0x166020
-/* [RW 16] The maximum value of the competion counter #2 */
+/* [RW 16] The maximum value of the completion counter #2 */
 #define XSDM_REG_CMP_COUNTER_MAX2				 0x166024
-/* [RW 16] The maximum value of the competion counter #3 */
+/* [RW 16] The maximum value of the completion counter #3 */
 #define XSDM_REG_CMP_COUNTER_MAX3				 0x166028
 /* [RW 13] The start address in the internal RAM for the completion
    counters. */
@@ -6083,6 +6083,7 @@
 #define MDIO_PMA_REG_8727_PCS_OPT_CTRL		0xc808
 #define MDIO_PMA_REG_8727_GPIO_CTRL		0xc80e
 #define MDIO_PMA_REG_8727_PCS_GP		0xc842
+#define MDIO_PMA_REG_8727_OPT_CFG_REG		0xc8e4
 
 #define MDIO_AN_REG_8727_MISC_CTRL		0x8309
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_3ad.c linux-libre-2.6.39-gnu/drivers/net/bonding/bond_3ad.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_3ad.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_3ad.c	2011-05-19 00:06:34.000000000 -0400
@@ -246,7 +246,7 @@
  */
 static inline int __port_is_enabled(struct port *port)
 {
-	return port->slave->state == BOND_STATE_ACTIVE;
+	return bond_is_active_slave(port->slave);
 }
 
 /**
@@ -1482,8 +1482,11 @@
 
 static int agg_device_up(const struct aggregator *agg)
 {
-	return (netif_running(agg->slave->dev) &&
-		netif_carrier_ok(agg->slave->dev));
+	struct port *port = agg->lag_ports;
+	if (!port)
+		return 0;
+	return (netif_running(port->slave->dev) &&
+		netif_carrier_ok(port->slave->dev));
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_3ad.h linux-libre-2.6.39-gnu/drivers/net/bonding/bond_3ad.h
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_3ad.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_3ad.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 
 typedef struct mac_addr {
 	u8 mac_addr_value[ETH_ALEN];
-} mac_addr_t;
+} __packed mac_addr_t;
 
 enum {
 	BOND_AD_STABLE = 0,
@@ -134,12 +134,12 @@
 	u8 tlv_type_terminator;	     // = terminator
 	u8 terminator_length;	     // = 0
 	u8 reserved_50[50];	     // = 0
-} lacpdu_t;
+} __packed lacpdu_t;
 
 typedef struct lacpdu_header {
 	struct ethhdr hdr;
 	struct lacpdu lacpdu;
-} lacpdu_header_t;
+} __packed lacpdu_header_t;
 
 // Marker Protocol Data Unit(PDU) structure(43.5.3.2 in the 802.3ad standard)
 typedef struct bond_marker {
@@ -155,12 +155,12 @@
 	u8 tlv_type_terminator;	     //  = 0x00
 	u8 terminator_length;	     //  = 0x00
 	u8 reserved_90[90];	     //  = 0
-} bond_marker_t;
+} __packed bond_marker_t;
 
 typedef struct bond_marker_header {
 	struct ethhdr hdr;
 	struct bond_marker marker;
-} bond_marker_header_t;
+} __packed bond_marker_header_t;
 
 #pragma pack()
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_alb.c linux-libre-2.6.39-gnu/drivers/net/bonding/bond_alb.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_alb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_alb.c	2011-05-19 00:06:34.000000000 -0400
@@ -176,7 +176,7 @@
 	bond_info->tx_hashtbl = new_hashtbl;
 
 	for (i = 0; i < TLB_HASH_TABLE_SIZE; i++) {
-		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 1);
+		tlb_init_table_entry(&bond_info->tx_hashtbl[i], 0);
 	}
 
 	_unlock_tx_hashtbl(bond);
@@ -604,7 +604,7 @@
 
 	_lock_rx_hashtbl(bond);
 
-	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_src));
+	hash_index = _simple_hash((u8 *)&arp->ip_dst, sizeof(arp->ip_dst));
 	client_info = &(bond_info->rx_hashtbl[hash_index]);
 
 	if (client_info->assigned) {
@@ -701,7 +701,7 @@
 		 */
 		rlb_choose_channel(skb, bond);
 
-		/* The ARP relpy packets must be delayed so that
+		/* The ARP reply packets must be delayed so that
 		 * they can cancel out the influence of the ARP request.
 		 */
 		bond->alb_info.rlb_update_delay_counter = RLB_UPDATE_DELAY;
@@ -1042,7 +1042,7 @@
  *
  * If the permanent hw address of @slave is @bond's hw address, we need to
  * find a different hw address to give @slave, that isn't in use by any other
- * slave in the bond. This address must be, of course, one of the premanent
+ * slave in the bond. This address must be, of course, one of the permanent
  * addresses of the other slaves.
  *
  * We go over the slave list, and for each slave there we compare its
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_alb.h linux-libre-2.6.39-gnu/drivers/net/bonding/bond_alb.h
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_alb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_alb.h	2011-05-19 00:06:34.000000000 -0400
@@ -74,9 +74,9 @@
 				 * packets to a Client that the Hash function
 				 * gave this entry index.
 				 */
-	u32 tx_bytes;		/* Each Client acumulates the BytesTx that
-				 * were tranmitted to it, and after each
-				 * CallBack the LoadHistory is devided
+	u32 tx_bytes;		/* Each Client accumulates the BytesTx that
+				 * were transmitted to it, and after each
+				 * CallBack the LoadHistory is divided
 				 * by the balance interval
 				 */
 	u32 load_history;	/* This field contains the amount of Bytes
@@ -122,7 +122,6 @@
 };
 
 struct alb_bond_info {
-	struct timer_list	alb_timer;
 	struct tlb_client_info	*tx_hashtbl; /* Dynamically allocated */
 	spinlock_t		tx_hashtbl_lock;
 	u32			unbalanced_load;
@@ -140,7 +139,6 @@
 	struct slave		*next_rx_slave;/* next slave to be assigned
 						* to a new rx client for
 						*/
-	u32			rlb_interval_counter;
 	u8			primary_is_promisc;	   /* boolean */
 	u32			rlb_promisc_timeout_counter;/* counts primary
 							     * promiscuity time
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bonding.h linux-libre-2.6.39-gnu/drivers/net/bonding/bonding.h
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bonding.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bonding.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,6 +20,7 @@
 #include <linux/if_bonding.h>
 #include <linux/cpumask.h>
 #include <linux/in6.h>
+#include <linux/netpoll.h>
 #include "bond_3ad.h"
 #include "bond_alb.h"
 
@@ -28,6 +29,8 @@
 #define DRV_NAME	"bonding"
 #define DRV_DESCRIPTION	"Ethernet Channel Bonding Driver"
 
+#define bond_version DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n"
+
 #define BOND_MAX_ARP_TARGETS	16
 
 #define IS_UP(dev)					   \
@@ -52,7 +55,7 @@
 		    (((slave)->dev->flags & IFF_UP)  && \
 		     netif_running((slave)->dev)     && \
 		     ((slave)->link == BOND_LINK_UP) && \
-		     ((slave)->state == BOND_STATE_ACTIVE))
+		     bond_is_active_slave(slave))
 
 
 #define USES_PRIMARY(mode)				\
@@ -132,7 +135,7 @@
 
 static inline int is_netpoll_tx_blocked(struct net_device *dev)
 {
-	if (unlikely(dev->priv_flags & IFF_IN_NETPOLL))
+	if (unlikely(netpoll_tx_running(dev)))
 		return atomic_read(&netpoll_block_tx);
 	return 0;
 }
@@ -184,12 +187,15 @@
 	struct net_device *dev; /* first - useful for panic debug */
 	struct slave *next;
 	struct slave *prev;
+	struct bonding *bond; /* our master */
 	int    delay;
 	unsigned long jiffies;
 	unsigned long last_arp_rx;
 	s8     link;    /* one of BOND_LINK_XXXX */
 	s8     new_link;
-	s8     state;   /* one of BOND_STATE_XXXX */
+	u8     backup:1,   /* indicates backup slave. Value corresponds with
+			      BOND_STATE_ACTIVE and BOND_STATE_BACKUP */
+	       inactive:1; /* indicates inactive slave */
 	u32    original_mtu;
 	u32    link_failure_count;
 	u8     perm_hwaddr[ETH_ALEN];
@@ -198,6 +204,9 @@
 	u16    queue_id;
 	struct ad_slave_info ad_info; /* HUGE - better to dynamically alloc */
 	struct tlb_slave_info tlb_info;
+#ifdef CONFIG_NET_POLL_CONTROLLER
+	struct netpoll *np;
+#endif
 };
 
 /*
@@ -260,12 +269,16 @@
 #endif /* CONFIG_DEBUG_FS */
 };
 
+#define bond_slave_get_rcu(dev) \
+	((struct slave *) rcu_dereference(dev->rx_handler_data))
+
 /**
  * Returns NULL if the net_device does not belong to any of the bond's slaves
  *
  * Caller must hold bond lock for read
  */
-static inline struct slave *bond_get_slave_by_dev(struct bonding *bond, struct net_device *slave_dev)
+static inline struct slave *bond_get_slave_by_dev(struct bonding *bond,
+						  struct net_device *slave_dev)
 {
 	struct slave *slave = NULL;
 	int i;
@@ -276,7 +289,7 @@
 		}
 	}
 
-	return 0;
+	return NULL;
 }
 
 static inline struct bonding *bond_get_bond_by_slave(struct slave *slave)
@@ -294,6 +307,26 @@
 		bond->params.mode == BOND_MODE_ALB);
 }
 
+static inline void bond_set_active_slave(struct slave *slave)
+{
+	slave->backup = 0;
+}
+
+static inline void bond_set_backup_slave(struct slave *slave)
+{
+	slave->backup = 1;
+}
+
+static inline int bond_slave_state(struct slave *slave)
+{
+	return slave->backup;
+}
+
+static inline bool bond_is_active_slave(struct slave *slave)
+{
+	return !bond_slave_state(slave);
+}
+
 #define BOND_PRI_RESELECT_ALWAYS	0
 #define BOND_PRI_RESELECT_BETTER	1
 #define BOND_PRI_RESELECT_FAILURE	2
@@ -311,7 +344,7 @@
 static inline int slave_do_arp_validate(struct bonding *bond,
 					struct slave *slave)
 {
-	return bond->params.arp_validate & (1 << slave->state);
+	return bond->params.arp_validate & (1 << bond_slave_state(slave));
 }
 
 static inline unsigned long slave_last_rx(struct bonding *bond,
@@ -323,41 +356,40 @@
 	return slave->dev->last_rx;
 }
 
-static inline void bond_set_slave_inactive_flags(struct slave *slave)
+#ifdef CONFIG_NET_POLL_CONTROLLER
+static inline void bond_netpoll_send_skb(const struct slave *slave,
+					 struct sk_buff *skb)
 {
-	struct bonding *bond = netdev_priv(slave->dev->master);
-	if (!bond_is_lb(bond))
-		slave->state = BOND_STATE_BACKUP;
-	if (!bond->params.all_slaves_active)
-		slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
-	if (slave_do_arp_validate(bond, slave))
-		slave->dev->priv_flags |= IFF_SLAVE_NEEDARP;
-}
+	struct netpoll *np = slave->np;
 
-static inline void bond_set_slave_active_flags(struct slave *slave)
-{
-	slave->state = BOND_STATE_ACTIVE;
-	slave->dev->priv_flags &= ~(IFF_SLAVE_INACTIVE | IFF_SLAVE_NEEDARP);
+	if (np)
+		netpoll_send_skb(np, skb);
 }
-
-static inline void bond_set_master_3ad_flags(struct bonding *bond)
+#else
+static inline void bond_netpoll_send_skb(const struct slave *slave,
+					 struct sk_buff *skb)
 {
-	bond->dev->priv_flags |= IFF_MASTER_8023AD;
 }
+#endif
 
-static inline void bond_unset_master_3ad_flags(struct bonding *bond)
+static inline void bond_set_slave_inactive_flags(struct slave *slave)
 {
-	bond->dev->priv_flags &= ~IFF_MASTER_8023AD;
+	struct bonding *bond = netdev_priv(slave->dev->master);
+	if (!bond_is_lb(bond))
+		bond_set_backup_slave(slave);
+	if (!bond->params.all_slaves_active)
+		slave->inactive = 1;
 }
 
-static inline void bond_set_master_alb_flags(struct bonding *bond)
+static inline void bond_set_slave_active_flags(struct slave *slave)
 {
-	bond->dev->priv_flags |= IFF_MASTER_ALB;
+	bond_set_active_slave(slave);
+	slave->inactive = 0;
 }
 
-static inline void bond_unset_master_alb_flags(struct bonding *bond)
+static inline bool bond_is_slave_inactive(struct slave *slave)
 {
-	bond->dev->priv_flags &= ~IFF_MASTER_ALB;
+	return slave->inactive;
 }
 
 struct vlan_entry *bond_next_vlan(struct bonding *bond, struct vlan_entry *curr);
@@ -393,6 +425,30 @@
 #endif
 };
 
+#ifdef CONFIG_PROC_FS
+void bond_create_proc_entry(struct bonding *bond);
+void bond_remove_proc_entry(struct bonding *bond);
+void bond_create_proc_dir(struct bond_net *bn);
+void bond_destroy_proc_dir(struct bond_net *bn);
+#else
+static inline void bond_create_proc_entry(struct bonding *bond)
+{
+}
+
+static inline void bond_remove_proc_entry(struct bonding *bond)
+{
+}
+
+static inline void bond_create_proc_dir(struct bond_net *bn)
+{
+}
+
+static inline void bond_destroy_proc_dir(struct bond_net *bn)
+{
+}
+#endif
+
+
 /* exported from bond_main.c */
 extern int bond_net_id;
 extern const struct bond_parm_tbl bond_lacp_tbl[];
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_main.c linux-libre-2.6.39-gnu/drivers/net/bonding/bond_main.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -59,15 +59,12 @@
 #include <linux/uaccess.h>
 #include <linux/errno.h>
 #include <linux/netdevice.h>
-#include <linux/netpoll.h>
 #include <linux/inetdevice.h>
 #include <linux/igmp.h>
 #include <linux/etherdevice.h>
 #include <linux/skbuff.h>
 #include <net/sock.h>
 #include <linux/rtnetlink.h>
-#include <linux/proc_fs.h>
-#include <linux/seq_file.h>
 #include <linux/smp.h>
 #include <linux/if_ether.h>
 #include <net/arp.h>
@@ -174,9 +171,6 @@
 atomic_t netpoll_block_tx = ATOMIC_INIT(0);
 #endif
 
-static const char * const version =
-	DRV_DESCRIPTION ": v" DRV_VERSION " (" DRV_RELDATE ")\n";
-
 int bond_net_id __read_mostly;
 
 static __be32 arp_target[BOND_MAX_ARP_TARGETS];
@@ -246,7 +240,7 @@
 
 /*---------------------------- General routines -----------------------------*/
 
-static const char *bond_mode_name(int mode)
+const char *bond_mode_name(int mode)
 {
 	static const char *names[] = {
 		[BOND_MODE_ROUNDROBIN] = "load balancing (round-robin)",
@@ -424,15 +418,9 @@
 {
 	skb->dev = slave_dev;
 	skb->priority = 1;
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	if (unlikely(bond->dev->priv_flags & IFF_IN_NETPOLL)) {
-		struct netpoll *np = bond->dev->npinfo->netpoll;
-		slave_dev->npinfo = bond->dev->npinfo;
-		slave_dev->priv_flags |= IFF_IN_NETPOLL;
-		netpoll_send_skb_on_dev(np, skb, slave_dev);
-		slave_dev->priv_flags &= ~IFF_IN_NETPOLL;
-	} else
-#endif
+	if (unlikely(netpoll_tx_running(slave_dev)))
+		bond_netpoll_send_skb(bond_get_slave_by_dev(bond, slave_dev), skb);
+	else
 		dev_queue_xmit(skb);
 
 	return 0;
@@ -1288,63 +1276,103 @@
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-/*
- * You must hold read lock on bond->lock before calling this.
- */
-static bool slaves_support_netpoll(struct net_device *bond_dev)
+static inline int slave_enable_netpoll(struct slave *slave)
 {
-	struct bonding *bond = netdev_priv(bond_dev);
-	struct slave *slave;
-	int i = 0;
-	bool ret = true;
+	struct netpoll *np;
+	int err = 0;
 
-	bond_for_each_slave(bond, slave, i) {
-		if ((slave->dev->priv_flags & IFF_DISABLE_NETPOLL) ||
-		    !slave->dev->netdev_ops->ndo_poll_controller)
-			ret = false;
+	np = kzalloc(sizeof(*np), GFP_KERNEL);
+	err = -ENOMEM;
+	if (!np)
+		goto out;
+
+	np->dev = slave->dev;
+	err = __netpoll_setup(np);
+	if (err) {
+		kfree(np);
+		goto out;
 	}
-	return i != 0 && ret;
+	slave->np = np;
+out:
+	return err;
+}
+static inline void slave_disable_netpoll(struct slave *slave)
+{
+	struct netpoll *np = slave->np;
+
+	if (!np)
+		return;
+
+	slave->np = NULL;
+	synchronize_rcu_bh();
+	__netpoll_cleanup(np);
+	kfree(np);
+}
+static inline bool slave_dev_support_netpoll(struct net_device *slave_dev)
+{
+	if (slave_dev->priv_flags & IFF_DISABLE_NETPOLL)
+		return false;
+	if (!slave_dev->netdev_ops->ndo_poll_controller)
+		return false;
+	return true;
 }
 
 static void bond_poll_controller(struct net_device *bond_dev)
 {
-	struct bonding *bond = netdev_priv(bond_dev);
+}
+
+static void __bond_netpoll_cleanup(struct bonding *bond)
+{
 	struct slave *slave;
 	int i;
 
-	bond_for_each_slave(bond, slave, i) {
-		if (slave->dev && IS_UP(slave->dev))
-			netpoll_poll_dev(slave->dev);
-	}
+	bond_for_each_slave(bond, slave, i)
+		if (IS_UP(slave->dev))
+			slave_disable_netpoll(slave);
 }
-
 static void bond_netpoll_cleanup(struct net_device *bond_dev)
 {
 	struct bonding *bond = netdev_priv(bond_dev);
+
+	read_lock(&bond->lock);
+	__bond_netpoll_cleanup(bond);
+	read_unlock(&bond->lock);
+}
+
+static int bond_netpoll_setup(struct net_device *dev, struct netpoll_info *ni)
+{
+	struct bonding *bond = netdev_priv(dev);
 	struct slave *slave;
-	const struct net_device_ops *ops;
-	int i;
+	int i, err = 0;
 
 	read_lock(&bond->lock);
-	bond_dev->npinfo = NULL;
 	bond_for_each_slave(bond, slave, i) {
-		if (slave->dev) {
-			ops = slave->dev->netdev_ops;
-			if (ops->ndo_netpoll_cleanup)
-				ops->ndo_netpoll_cleanup(slave->dev);
-			else
-				slave->dev->npinfo = NULL;
+		err = slave_enable_netpoll(slave);
+		if (err) {
+			__bond_netpoll_cleanup(bond);
+			break;
 		}
 	}
 	read_unlock(&bond->lock);
+	return err;
 }
 
-#else
+static struct netpoll_info *bond_netpoll_info(struct bonding *bond)
+{
+	return bond->dev->npinfo;
+}
 
+#else
+static inline int slave_enable_netpoll(struct slave *slave)
+{
+	return 0;
+}
+static inline void slave_disable_netpoll(struct slave *slave)
+{
+}
 static void bond_netpoll_cleanup(struct net_device *bond_dev)
 {
 }
-
 #endif
 
 /*---------------------------------- IOCTL ----------------------------------*/
@@ -1372,8 +1400,8 @@
 {
 	struct slave *slave;
 	struct net_device *bond_dev = bond->dev;
-	unsigned long features = bond_dev->features;
-	unsigned long vlan_features = 0;
+	u32 features = bond_dev->features;
+	u32 vlan_features = 0;
 	unsigned short max_hard_header_len = max((u16)ETH_HLEN,
 						bond_dev->hard_header_len);
 	int i;
@@ -1400,8 +1428,8 @@
 
 done:
 	features |= (bond_dev->features & BOND_VLAN_FEATURES);
-	bond_dev->features = netdev_fix_features(features, NULL);
-	bond_dev->vlan_features = netdev_fix_features(vlan_features, NULL);
+	bond_dev->features = netdev_fix_features(bond_dev, features);
+	bond_dev->vlan_features = netdev_fix_features(bond_dev, vlan_features);
 	bond_dev->hard_header_len = max_hard_header_len;
 
 	return 0;
@@ -1423,6 +1451,72 @@
 	bond->setup_by_slave = 1;
 }
 
+/* On bonding slaves other than the currently active slave, suppress
+ * duplicates except for 802.3ad ETH_P_SLOW, alb non-mcast/bcast, and
+ * ARP on active-backup slaves with arp_validate enabled.
+ */
+static bool bond_should_deliver_exact_match(struct sk_buff *skb,
+					    struct slave *slave,
+					    struct bonding *bond)
+{
+	if (bond_is_slave_inactive(slave)) {
+		if (slave_do_arp_validate(bond, slave) &&
+		    skb->protocol == __cpu_to_be16(ETH_P_ARP))
+			return false;
+
+		if (bond->params.mode == BOND_MODE_ALB &&
+		    skb->pkt_type != PACKET_BROADCAST &&
+		    skb->pkt_type != PACKET_MULTICAST)
+				return false;
+
+		if (bond->params.mode == BOND_MODE_8023AD &&
+		    skb->protocol == __cpu_to_be16(ETH_P_SLOW))
+			return false;
+
+		return true;
+	}
+	return false;
+}
+
+static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
+{
+	struct sk_buff *skb = *pskb;
+	struct slave *slave;
+	struct bonding *bond;
+
+	skb = skb_share_check(skb, GFP_ATOMIC);
+	if (unlikely(!skb))
+		return RX_HANDLER_CONSUMED;
+
+	*pskb = skb;
+
+	slave = bond_slave_get_rcu(skb->dev);
+	bond = slave->bond;
+
+	if (bond->params.arp_interval)
+		slave->dev->last_rx = jiffies;
+
+	if (bond_should_deliver_exact_match(skb, slave, bond)) {
+		return RX_HANDLER_EXACT;
+	}
+
+	skb->dev = bond->dev;
+
+	if (bond->params.mode == BOND_MODE_ALB &&
+	    bond->dev->priv_flags & IFF_BRIDGE_PORT &&
+	    skb->pkt_type == PACKET_HOST) {
+
+		if (unlikely(skb_cow_head(skb,
+					  skb->data - skb_mac_header(skb)))) {
+			kfree_skb(skb);
+			return RX_HANDLER_CONSUMED;
+		}
+		memcpy(eth_hdr(skb)->h_dest, bond->dev->dev_addr, ETH_ALEN);
+	}
+
+	return RX_HANDLER_ANOTHER;
+}
+
 /* enslave device <slave> to bond device <master> */
 int bond_enslave(struct net_device *bond_dev, struct net_device *slave_dev)
 {
@@ -1594,11 +1688,12 @@
 		}
 	}
 
-	res = netdev_set_master(slave_dev, bond_dev);
+	res = netdev_set_bond_master(slave_dev, bond_dev);
 	if (res) {
-		pr_debug("Error %d calling netdev_set_master\n", res);
+		pr_debug("Error %d calling netdev_set_bond_master\n", res);
 		goto err_restore_mac;
 	}
+
 	/* open the slave since the application closed it */
 	res = dev_open(slave_dev);
 	if (res) {
@@ -1606,6 +1701,7 @@
 		goto err_unset_master;
 	}
 
+	new_slave->bond = bond;
 	new_slave->dev = slave_dev;
 	slave_dev->priv_flags |= IFF_BONDING;
 
@@ -1757,7 +1853,7 @@
 		break;
 	case BOND_MODE_TLB:
 	case BOND_MODE_ALB:
-		new_slave->state = BOND_STATE_ACTIVE;
+		bond_set_active_slave(new_slave);
 		bond_set_slave_inactive_flags(new_slave);
 		bond_select_active_slave(bond);
 		break;
@@ -1765,7 +1861,7 @@
 		pr_debug("This slave is always active in trunk mode\n");
 
 		/* always active in trunk mode */
-		new_slave->state = BOND_STATE_ACTIVE;
+		bond_set_active_slave(new_slave);
 
 		/* In trunking mode there is little meaning to curr_active_slave
 		 * anyway (it holds no special properties of the bond device),
@@ -1782,37 +1878,49 @@
 	bond_set_carrier(bond);
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	if (slaves_support_netpoll(bond_dev)) {
-		bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
-		if (bond_dev->npinfo)
-			slave_dev->npinfo = bond_dev->npinfo;
-	} else if (!(bond_dev->priv_flags & IFF_DISABLE_NETPOLL)) {
-		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
-		pr_info("New slave device %s does not support netpoll\n",
-			slave_dev->name);
-		pr_info("Disabling netpoll support for %s\n", bond_dev->name);
+	slave_dev->npinfo = bond_netpoll_info(bond);
+	if (slave_dev->npinfo) {
+		if (slave_enable_netpoll(new_slave)) {
+			read_unlock(&bond->lock);
+			pr_info("Error, %s: master_dev is using netpoll, "
+				 "but new slave device does not support netpoll.\n",
+				 bond_dev->name);
+			res = -EBUSY;
+			goto err_close;
+		}
 	}
 #endif
+
 	read_unlock(&bond->lock);
 
 	res = bond_create_slave_symlinks(bond_dev, slave_dev);
 	if (res)
 		goto err_close;
 
+	res = netdev_rx_handler_register(slave_dev, bond_handle_frame,
+					 new_slave);
+	if (res) {
+		pr_debug("Error %d calling netdev_rx_handler_register\n", res);
+		goto err_dest_symlinks;
+	}
+
 	pr_info("%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",
+		bond_is_active_slave(new_slave) ? "n active" : " backup",
 		new_slave->link != BOND_LINK_DOWN ? "n up" : " down");
 
 	/* enslave is successful */
 	return 0;
 
 /* Undo stages on error */
+err_dest_symlinks:
+	bond_destroy_slave_symlinks(bond_dev, slave_dev);
+
 err_close:
 	dev_close(slave_dev);
 
 err_unset_master:
-	netdev_set_master(slave_dev, NULL);
+	netdev_set_bond_master(slave_dev, NULL);
 
 err_restore_mac:
 	if (!bond->params.fail_over_mac) {
@@ -1876,6 +1984,14 @@
 		return -EINVAL;
 	}
 
+	/* unregister rx_handler early so bond_handle_frame wouldn't be called
+	 * for this slave anymore.
+	 */
+	netdev_rx_handler_unregister(slave_dev);
+	write_unlock_bh(&bond->lock);
+	synchronize_net();
+	write_lock_bh(&bond->lock);
+
 	if (!bond->params.fail_over_mac) {
 		if (!compare_ether_addr(bond_dev->dev_addr, slave->perm_hwaddr) &&
 		    bond->slave_cnt > 1)
@@ -1895,7 +2011,7 @@
 
 	pr_info("%s: releasing %s interface %s\n",
 		bond_dev->name,
-		(slave->state == BOND_STATE_ACTIVE) ? "active" : "backup",
+		bond_is_active_slave(slave) ? "active" : "backup",
 		slave_dev->name);
 
 	oldcurrent = bond->curr_active_slave;
@@ -1992,19 +2108,9 @@
 		netif_addr_unlock_bh(bond_dev);
 	}
 
-	netdev_set_master(slave_dev, NULL);
-
-#ifdef CONFIG_NET_POLL_CONTROLLER
-	read_lock_bh(&bond->lock);
+	netdev_set_bond_master(slave_dev, NULL);
 
-	if (slaves_support_netpoll(bond_dev))
-		bond_dev->priv_flags &= ~IFF_DISABLE_NETPOLL;
-	read_unlock_bh(&bond->lock);
-	if (slave_dev->netdev_ops->ndo_netpoll_cleanup)
-		slave_dev->netdev_ops->ndo_netpoll_cleanup(slave_dev);
-	else
-		slave_dev->npinfo = NULL;
-#endif
+	slave_disable_netpoll(slave);
 
 	/* close slave before restoring its mac address */
 	dev_close(slave_dev);
@@ -2018,9 +2124,7 @@
 
 	dev_set_mtu(slave_dev, slave->original_mtu);
 
-	slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-				   IFF_SLAVE_INACTIVE | IFF_BONDING |
-				   IFF_SLAVE_NEEDARP);
+	slave_dev->priv_flags &= ~IFF_BONDING;
 
 	kfree(slave);
 
@@ -2028,7 +2132,7 @@
 }
 
 /*
-* First release a slave and than destroy the bond if no more slaves are left.
+* First release a slave and then destroy the bond if no more slaves are left.
 * Must be under rtnl_lock when this function is called.
 */
 static int  bond_release_and_destroy(struct net_device *bond_dev,
@@ -2039,6 +2143,7 @@
 
 	ret = bond_release(bond_dev, slave_dev);
 	if ((ret == 0) && (bond->slave_cnt == 0)) {
+		bond_dev->priv_flags |= IFF_DISABLE_NETPOLL;
 		pr_info("%s: destroying bond %s.\n",
 			bond_dev->name, bond_dev->name);
 		unregister_netdevice(bond_dev);
@@ -2083,6 +2188,12 @@
 		 */
 		write_unlock_bh(&bond->lock);
 
+		/* unregister rx_handler early so bond_handle_frame wouldn't
+		 * be called for this slave anymore.
+		 */
+		netdev_rx_handler_unregister(slave_dev);
+		synchronize_net();
+
 		if (bond_is_lb(bond)) {
 			/* must be called only after the slave
 			 * has been detached from the list
@@ -2114,7 +2225,9 @@
 			netif_addr_unlock_bh(bond_dev);
 		}
 
-		netdev_set_master(slave_dev, NULL);
+		netdev_set_bond_master(slave_dev, NULL);
+
+		slave_disable_netpoll(slave);
 
 		/* close slave before restoring its mac address */
 		dev_close(slave_dev);
@@ -2126,9 +2239,6 @@
 			dev_set_mac_address(slave_dev, &addr);
 		}
 
-		slave_dev->priv_flags &= ~(IFF_MASTER_8023AD | IFF_MASTER_ALB |
-					   IFF_SLAVE_INACTIVE);
-
 		kfree(slave);
 
 		/* re-acquire the lock before getting the next slave */
@@ -2242,7 +2352,7 @@
 			res = 0;
 			strcpy(info->slave_name, slave->dev->name);
 			info->link = slave->link;
-			info->state = slave->state;
+			info->state = bond_slave_state(slave);
 			info->link_failure_count = slave->link_failure_count;
 			break;
 		}
@@ -2281,7 +2391,7 @@
 					bond->dev->name,
 					(bond->params.mode ==
 					 BOND_MODE_ACTIVEBACKUP) ?
-					((slave->state == BOND_STATE_ACTIVE) ?
+					(bond_is_active_slave(slave) ?
 					 "active " : "backup ") : "",
 					slave->dev->name,
 					bond->params.downdelay * bond->params.miimon);
@@ -2372,13 +2482,13 @@
 
 			if (bond->params.mode == BOND_MODE_8023AD) {
 				/* prevent it from being the active one */
-				slave->state = BOND_STATE_BACKUP;
+				bond_set_backup_slave(slave);
 			} else if (bond->params.mode != BOND_MODE_ACTIVEBACKUP) {
 				/* make it immediately active */
-				slave->state = BOND_STATE_ACTIVE;
+				bond_set_active_slave(slave);
 			} else if (slave != bond->primary_slave) {
 				/* prevent it from being the active one */
-				slave->state = BOND_STATE_BACKUP;
+				bond_set_backup_slave(slave);
 			}
 
 			bond_update_speed_duplex(slave);
@@ -2571,11 +2681,10 @@
 
 static void bond_arp_send_all(struct bonding *bond, struct slave *slave)
 {
-	int i, vlan_id, rv;
+	int i, vlan_id;
 	__be32 *targets = bond->params.arp_targets;
 	struct vlan_entry *vlan;
 	struct net_device *vlan_dev;
-	struct flowi fl;
 	struct rtable *rt;
 
 	for (i = 0; (i < BOND_MAX_ARP_TARGETS); i++) {
@@ -2594,15 +2703,12 @@
 		 * determine which VLAN interface would be used, so we
 		 * can tag the ARP with the proper VLAN tag.
 		 */
-		memset(&fl, 0, sizeof(fl));
-		fl.fl4_dst = targets[i];
-		fl.fl4_tos = RTO_ONLINK;
-
-		rv = ip_route_output_key(dev_net(bond->dev), &rt, &fl);
-		if (rv) {
+		rt = ip_route_output(dev_net(bond->dev), targets[i], 0,
+				     RTO_ONLINK, 0);
+		if (IS_ERR(rt)) {
 			if (net_ratelimit()) {
 				pr_warning("%s: no route to arp_ip_target %pI4\n",
-					   bond->dev->name, &fl.fl4_dst);
+					   bond->dev->name, &targets[i]);
 			}
 			continue;
 		}
@@ -2638,7 +2744,7 @@
 
 		if (net_ratelimit()) {
 			pr_warning("%s: no path to arp_ip_target %pI4 via rt.dev %s\n",
-				   bond->dev->name, &fl.fl4_dst,
+				   bond->dev->name, &targets[i],
 				   rt->dst.dev ? rt->dst.dev->name : "NULL");
 		}
 		ip_rt_put(rt);
@@ -2756,7 +2862,7 @@
 	memcpy(&tip, arp_ptr, 4);
 
 	pr_debug("bond_arp_rcv: %s %s/%d av %d sv %d sip %pI4 tip %pI4\n",
-		 bond->dev->name, slave->dev->name, slave->state,
+		 bond->dev->name, slave->dev->name, bond_slave_state(slave),
 		 bond->params.arp_validate, slave_do_arp_validate(bond, slave),
 		 &sip, &tip);
 
@@ -2768,7 +2874,7 @@
 	 * the active, through one switch, the router, then the other
 	 * switch before reaching the backup.
 	 */
-	if (slave->state == BOND_STATE_ACTIVE)
+	if (bond_is_active_slave(slave))
 		bond_validate_arp(bond, slave, sip, tip);
 	else
 		bond_validate_arp(bond, slave, tip, sip);
@@ -2830,7 +2936,7 @@
 				slave->dev->last_rx + delta_in_ticks)) {
 
 				slave->link  = BOND_LINK_UP;
-				slave->state = BOND_STATE_ACTIVE;
+				bond_set_active_slave(slave);
 
 				/* primary_slave has no meaning in round-robin
 				 * mode. the window of a slave being up and
@@ -2863,7 +2969,7 @@
 				slave->dev->last_rx + 2 * delta_in_ticks)) {
 
 				slave->link  = BOND_LINK_DOWN;
-				slave->state = BOND_STATE_BACKUP;
+				bond_set_backup_slave(slave);
 
 				if (slave->link_failure_count < UINT_MAX)
 					slave->link_failure_count++;
@@ -2957,7 +3063,7 @@
 		 * gives each slave a chance to tx/rx traffic
 		 * before being taken out
 		 */
-		if (slave->state == BOND_STATE_BACKUP &&
+		if (!bond_is_active_slave(slave) &&
 		    !bond->current_arp_slave &&
 		    !time_in_range(jiffies,
 			slave_last_rx(bond, slave) - delta_in_ticks,
@@ -2974,7 +3080,7 @@
 		 *    the bond has an IP address)
 		 */
 		trans_start = dev_trans_start(slave->dev);
-		if ((slave->state == BOND_STATE_ACTIVE) &&
+		if (bond_is_active_slave(slave) &&
 		    (!time_in_range(jiffies,
 			trans_start - delta_in_ticks,
 			trans_start + 2 * delta_in_ticks) ||
@@ -3182,299 +3288,6 @@
 	read_unlock(&bond->lock);
 }
 
-/*------------------------------ proc/seq_file-------------------------------*/
-
-#ifdef CONFIG_PROC_FS
-
-static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
-	__acquires(RCU)
-	__acquires(&bond->lock)
-{
-	struct bonding *bond = seq->private;
-	loff_t off = 0;
-	struct slave *slave;
-	int i;
-
-	/* make sure the bond won't be taken away */
-	rcu_read_lock();
-	read_lock(&bond->lock);
-
-	if (*pos == 0)
-		return SEQ_START_TOKEN;
-
-	bond_for_each_slave(bond, slave, i) {
-		if (++off == *pos)
-			return slave;
-	}
-
-	return NULL;
-}
-
-static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
-{
-	struct bonding *bond = seq->private;
-	struct slave *slave = v;
-
-	++*pos;
-	if (v == SEQ_START_TOKEN)
-		return bond->first_slave;
-
-	slave = slave->next;
-
-	return (slave == bond->first_slave) ? NULL : slave;
-}
-
-static void bond_info_seq_stop(struct seq_file *seq, void *v)
-	__releases(&bond->lock)
-	__releases(RCU)
-{
-	struct bonding *bond = seq->private;
-
-	read_unlock(&bond->lock);
-	rcu_read_unlock();
-}
-
-static void bond_info_show_master(struct seq_file *seq)
-{
-	struct bonding *bond = seq->private;
-	struct slave *curr;
-	int i;
-
-	read_lock(&bond->curr_slave_lock);
-	curr = bond->curr_active_slave;
-	read_unlock(&bond->curr_slave_lock);
-
-	seq_printf(seq, "Bonding Mode: %s",
-		   bond_mode_name(bond->params.mode));
-
-	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
-	    bond->params.fail_over_mac)
-		seq_printf(seq, " (fail_over_mac %s)",
-		   fail_over_mac_tbl[bond->params.fail_over_mac].modename);
-
-	seq_printf(seq, "\n");
-
-	if (bond->params.mode == BOND_MODE_XOR ||
-		bond->params.mode == BOND_MODE_8023AD) {
-		seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
-			xmit_hashtype_tbl[bond->params.xmit_policy].modename,
-			bond->params.xmit_policy);
-	}
-
-	if (USES_PRIMARY(bond->params.mode)) {
-		seq_printf(seq, "Primary Slave: %s",
-			   (bond->primary_slave) ?
-			   bond->primary_slave->dev->name : "None");
-		if (bond->primary_slave)
-			seq_printf(seq, " (primary_reselect %s)",
-		   pri_reselect_tbl[bond->params.primary_reselect].modename);
-
-		seq_printf(seq, "\nCurrently Active Slave: %s\n",
-			   (curr) ? curr->dev->name : "None");
-	}
-
-	seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
-		   "up" : "down");
-	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
-	seq_printf(seq, "Up Delay (ms): %d\n",
-		   bond->params.updelay * bond->params.miimon);
-	seq_printf(seq, "Down Delay (ms): %d\n",
-		   bond->params.downdelay * bond->params.miimon);
-
-
-	/* ARP information */
-	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++) {
-			if (!bond->params.arp_targets[i])
-				break;
-			if (printed)
-				seq_printf(seq, ",");
-			seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
-			printed = 1;
-		}
-		seq_printf(seq, "\n");
-	}
-
-	if (bond->params.mode == BOND_MODE_8023AD) {
-		struct ad_info ad_info;
-
-		seq_puts(seq, "\n802.3ad info\n");
-		seq_printf(seq, "LACP rate: %s\n",
-			   (bond->params.lacp_fast) ? "fast" : "slow");
-		seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
-			   ad_select_tbl[bond->params.ad_select].modename);
-
-		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
-			seq_printf(seq, "bond %s has no active aggregator\n",
-				   bond->dev->name);
-		} else {
-			seq_printf(seq, "Active Aggregator Info:\n");
-
-			seq_printf(seq, "\tAggregator ID: %d\n",
-				   ad_info.aggregator_id);
-			seq_printf(seq, "\tNumber of ports: %d\n",
-				   ad_info.ports);
-			seq_printf(seq, "\tActor Key: %d\n",
-				   ad_info.actor_key);
-			seq_printf(seq, "\tPartner Key: %d\n",
-				   ad_info.partner_key);
-			seq_printf(seq, "\tPartner Mac Address: %pM\n",
-				   ad_info.partner_system);
-		}
-	}
-}
-
-static void bond_info_show_slave(struct seq_file *seq,
-				 const struct slave *slave)
-{
-	struct bonding *bond = seq->private;
-
-	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
-	seq_printf(seq, "MII Status: %s\n",
-		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
-	seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
-	seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
-	seq_printf(seq, "Link Failure Count: %u\n",
-		   slave->link_failure_count);
-
-	seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
-
-	if (bond->params.mode == BOND_MODE_8023AD) {
-		const struct aggregator *agg
-			= SLAVE_AD_INFO(slave).port.aggregator;
-
-		if (agg)
-			seq_printf(seq, "Aggregator ID: %d\n",
-				   agg->aggregator_identifier);
-		else
-			seq_puts(seq, "Aggregator ID: N/A\n");
-	}
-	seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
-}
-
-static int bond_info_seq_show(struct seq_file *seq, void *v)
-{
-	if (v == SEQ_START_TOKEN) {
-		seq_printf(seq, "%s\n", version);
-		bond_info_show_master(seq);
-	} else
-		bond_info_show_slave(seq, v);
-
-	return 0;
-}
-
-static const struct seq_operations bond_info_seq_ops = {
-	.start = bond_info_seq_start,
-	.next  = bond_info_seq_next,
-	.stop  = bond_info_seq_stop,
-	.show  = bond_info_seq_show,
-};
-
-static int bond_info_open(struct inode *inode, struct file *file)
-{
-	struct seq_file *seq;
-	struct proc_dir_entry *proc;
-	int res;
-
-	res = seq_open(file, &bond_info_seq_ops);
-	if (!res) {
-		/* recover the pointer buried in proc_dir_entry data */
-		seq = file->private_data;
-		proc = PDE(inode);
-		seq->private = proc->data;
-	}
-
-	return res;
-}
-
-static const struct file_operations bond_info_fops = {
-	.owner   = THIS_MODULE,
-	.open    = bond_info_open,
-	.read    = seq_read,
-	.llseek  = seq_lseek,
-	.release = seq_release,
-};
-
-static void bond_create_proc_entry(struct bonding *bond)
-{
-	struct net_device *bond_dev = bond->dev;
-	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
-
-	if (bn->proc_dir) {
-		bond->proc_entry = proc_create_data(bond_dev->name,
-						    S_IRUGO, bn->proc_dir,
-						    &bond_info_fops, bond);
-		if (bond->proc_entry == NULL)
-			pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
-				   DRV_NAME, bond_dev->name);
-		else
-			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
-	}
-}
-
-static void bond_remove_proc_entry(struct bonding *bond)
-{
-	struct net_device *bond_dev = bond->dev;
-	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
-
-	if (bn->proc_dir && bond->proc_entry) {
-		remove_proc_entry(bond->proc_file_name, bn->proc_dir);
-		memset(bond->proc_file_name, 0, IFNAMSIZ);
-		bond->proc_entry = NULL;
-	}
-}
-
-/* Create the bonding directory under /proc/net, if doesn't exist yet.
- * Caller must hold rtnl_lock.
- */
-static void __net_init bond_create_proc_dir(struct bond_net *bn)
-{
-	if (!bn->proc_dir) {
-		bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
-		if (!bn->proc_dir)
-			pr_warning("Warning: cannot create /proc/net/%s\n",
-				   DRV_NAME);
-	}
-}
-
-/* Destroy the bonding directory under /proc/net, if empty.
- * Caller must hold rtnl_lock.
- */
-static void __net_exit bond_destroy_proc_dir(struct bond_net *bn)
-{
-	if (bn->proc_dir) {
-		remove_proc_entry(DRV_NAME, bn->net->proc_net);
-		bn->proc_dir = NULL;
-	}
-}
-
-#else /* !CONFIG_PROC_FS */
-
-static void bond_create_proc_entry(struct bonding *bond)
-{
-}
-
-static void bond_remove_proc_entry(struct bonding *bond)
-{
-}
-
-static inline void bond_create_proc_dir(struct bond_net *bn)
-{
-}
-
-static inline void bond_destroy_proc_dir(struct bond_net *bn)
-{
-}
-
-#endif /* CONFIG_PROC_FS */
-
-
 /*-------------------------- netdev event handling --------------------------*/
 
 /*
@@ -4331,7 +4144,7 @@
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
-		    (slave->state == BOND_STATE_ACTIVE)) {
+		    bond_is_active_slave(slave)) {
 			res = bond_dev_queue_xmit(bond, skb, slave->dev);
 			break;
 		}
@@ -4408,7 +4221,7 @@
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
-		    (slave->state == BOND_STATE_ACTIVE)) {
+		    bond_is_active_slave(slave)) {
 			res = bond_dev_queue_xmit(bond, skb, slave->dev);
 			break;
 		}
@@ -4449,7 +4262,7 @@
 	bond_for_each_slave_from(bond, slave, i, start_at) {
 		if (IS_UP(slave->dev) &&
 		    (slave->link == BOND_LINK_UP) &&
-		    (slave->state == BOND_STATE_ACTIVE)) {
+		    bond_is_active_slave(slave)) {
 			if (tx_dev) {
 				struct sk_buff *skb2 = skb_clone(skb, GFP_ATOMIC);
 				if (!skb2) {
@@ -4537,11 +4350,18 @@
 {
 	/*
 	 * This helper function exists to help dev_pick_tx get the correct
-	 * destination queue.  Using a helper function skips the a call to
+	 * destination queue.  Using a helper function skips a call to
 	 * skb_tx_hash and will put the skbs in the queue we expect on their
 	 * way down to the bonding driver.
 	 */
-	return skb->queue_mapping;
+	u16 txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) : 0;
+
+	if (unlikely(txq >= dev->real_num_tx_queues)) {
+		do
+			txq -= dev->real_num_tx_queues;
+		while (txq >= dev->real_num_tx_queues);
+	}
+	return txq;
 }
 
 static netdev_tx_t bond_start_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -4603,11 +4423,9 @@
 	case BOND_MODE_BROADCAST:
 		break;
 	case BOND_MODE_8023AD:
-		bond_set_master_3ad_flags(bond);
 		bond_set_xmit_hash_policy(bond);
 		break;
 	case BOND_MODE_ALB:
-		bond_set_master_alb_flags(bond);
 		/* FALLTHRU */
 	case BOND_MODE_TLB:
 		break;
@@ -4654,9 +4472,12 @@
 	.ndo_vlan_rx_add_vid 	= bond_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= bond_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
+	.ndo_netpoll_setup	= bond_netpoll_setup,
 	.ndo_netpoll_cleanup	= bond_netpoll_cleanup,
 	.ndo_poll_controller	= bond_poll_controller,
 #endif
+	.ndo_add_slave		= bond_enslave,
+	.ndo_del_slave		= bond_release,
 };
 
 static void bond_destructor(struct net_device *bond_dev)
@@ -4695,9 +4516,6 @@
 	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;
-
 	/* At first, we block adding VLANs. That's the only way to
 	 * prevent problems that occur when adding VLANs over an
 	 * empty bond. The block will be removed once non-challenged
@@ -5166,8 +4984,6 @@
 
 	bond_set_lockdep_class(bond_dev);
 
-	netif_carrier_off(bond_dev);
-
 	bond_create_proc_entry(bond);
 	list_add_tail(&bond->bond_list, &bn->dev_list);
 
@@ -5237,6 +5053,8 @@
 
 	res = register_netdevice(bond_dev);
 
+	netif_carrier_off(bond_dev);
+
 out:
 	rtnl_unlock();
 	if (res < 0)
@@ -5275,7 +5093,7 @@
 	int i;
 	int res;
 
-	pr_info("%s", version);
+	pr_info("%s", bond_version);
 
 	res = bond_check_params(&bonding_defaults);
 	if (res)
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_procfs.c linux-libre-2.6.39-gnu/drivers/net/bonding/bond_procfs.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_procfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_procfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,275 @@
+#include <linux/proc_fs.h>
+#include <net/net_namespace.h>
+#include <net/netns/generic.h>
+#include "bonding.h"
+
+
+extern const char *bond_mode_name(int mode);
+
+static void *bond_info_seq_start(struct seq_file *seq, loff_t *pos)
+	__acquires(RCU)
+	__acquires(&bond->lock)
+{
+	struct bonding *bond = seq->private;
+	loff_t off = 0;
+	struct slave *slave;
+	int i;
+
+	/* make sure the bond won't be taken away */
+	rcu_read_lock();
+	read_lock(&bond->lock);
+
+	if (*pos == 0)
+		return SEQ_START_TOKEN;
+
+	bond_for_each_slave(bond, slave, i) {
+		if (++off == *pos)
+			return slave;
+	}
+
+	return NULL;
+}
+
+static void *bond_info_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+	struct bonding *bond = seq->private;
+	struct slave *slave = v;
+
+	++*pos;
+	if (v == SEQ_START_TOKEN)
+		return bond->first_slave;
+
+	slave = slave->next;
+
+	return (slave == bond->first_slave) ? NULL : slave;
+}
+
+static void bond_info_seq_stop(struct seq_file *seq, void *v)
+	__releases(&bond->lock)
+	__releases(RCU)
+{
+	struct bonding *bond = seq->private;
+
+	read_unlock(&bond->lock);
+	rcu_read_unlock();
+}
+
+static void bond_info_show_master(struct seq_file *seq)
+{
+	struct bonding *bond = seq->private;
+	struct slave *curr;
+	int i;
+
+	read_lock(&bond->curr_slave_lock);
+	curr = bond->curr_active_slave;
+	read_unlock(&bond->curr_slave_lock);
+
+	seq_printf(seq, "Bonding Mode: %s",
+		   bond_mode_name(bond->params.mode));
+
+	if (bond->params.mode == BOND_MODE_ACTIVEBACKUP &&
+	    bond->params.fail_over_mac)
+		seq_printf(seq, " (fail_over_mac %s)",
+		   fail_over_mac_tbl[bond->params.fail_over_mac].modename);
+
+	seq_printf(seq, "\n");
+
+	if (bond->params.mode == BOND_MODE_XOR ||
+		bond->params.mode == BOND_MODE_8023AD) {
+		seq_printf(seq, "Transmit Hash Policy: %s (%d)\n",
+			xmit_hashtype_tbl[bond->params.xmit_policy].modename,
+			bond->params.xmit_policy);
+	}
+
+	if (USES_PRIMARY(bond->params.mode)) {
+		seq_printf(seq, "Primary Slave: %s",
+			   (bond->primary_slave) ?
+			   bond->primary_slave->dev->name : "None");
+		if (bond->primary_slave)
+			seq_printf(seq, " (primary_reselect %s)",
+		   pri_reselect_tbl[bond->params.primary_reselect].modename);
+
+		seq_printf(seq, "\nCurrently Active Slave: %s\n",
+			   (curr) ? curr->dev->name : "None");
+	}
+
+	seq_printf(seq, "MII Status: %s\n", netif_carrier_ok(bond->dev) ?
+		   "up" : "down");
+	seq_printf(seq, "MII Polling Interval (ms): %d\n", bond->params.miimon);
+	seq_printf(seq, "Up Delay (ms): %d\n",
+		   bond->params.updelay * bond->params.miimon);
+	seq_printf(seq, "Down Delay (ms): %d\n",
+		   bond->params.downdelay * bond->params.miimon);
+
+
+	/* ARP information */
+	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++) {
+			if (!bond->params.arp_targets[i])
+				break;
+			if (printed)
+				seq_printf(seq, ",");
+			seq_printf(seq, " %pI4", &bond->params.arp_targets[i]);
+			printed = 1;
+		}
+		seq_printf(seq, "\n");
+	}
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		struct ad_info ad_info;
+
+		seq_puts(seq, "\n802.3ad info\n");
+		seq_printf(seq, "LACP rate: %s\n",
+			   (bond->params.lacp_fast) ? "fast" : "slow");
+		seq_printf(seq, "Aggregator selection policy (ad_select): %s\n",
+			   ad_select_tbl[bond->params.ad_select].modename);
+
+		if (bond_3ad_get_active_agg_info(bond, &ad_info)) {
+			seq_printf(seq, "bond %s has no active aggregator\n",
+				   bond->dev->name);
+		} else {
+			seq_printf(seq, "Active Aggregator Info:\n");
+
+			seq_printf(seq, "\tAggregator ID: %d\n",
+				   ad_info.aggregator_id);
+			seq_printf(seq, "\tNumber of ports: %d\n",
+				   ad_info.ports);
+			seq_printf(seq, "\tActor Key: %d\n",
+				   ad_info.actor_key);
+			seq_printf(seq, "\tPartner Key: %d\n",
+				   ad_info.partner_key);
+			seq_printf(seq, "\tPartner Mac Address: %pM\n",
+				   ad_info.partner_system);
+		}
+	}
+}
+
+static void bond_info_show_slave(struct seq_file *seq,
+				 const struct slave *slave)
+{
+	struct bonding *bond = seq->private;
+
+	seq_printf(seq, "\nSlave Interface: %s\n", slave->dev->name);
+	seq_printf(seq, "MII Status: %s\n",
+		   (slave->link == BOND_LINK_UP) ?  "up" : "down");
+	seq_printf(seq, "Speed: %d Mbps\n", slave->speed);
+	seq_printf(seq, "Duplex: %s\n", slave->duplex ? "full" : "half");
+	seq_printf(seq, "Link Failure Count: %u\n",
+		   slave->link_failure_count);
+
+	seq_printf(seq, "Permanent HW addr: %pM\n", slave->perm_hwaddr);
+
+	if (bond->params.mode == BOND_MODE_8023AD) {
+		const struct aggregator *agg
+			= SLAVE_AD_INFO(slave).port.aggregator;
+
+		if (agg)
+			seq_printf(seq, "Aggregator ID: %d\n",
+				   agg->aggregator_identifier);
+		else
+			seq_puts(seq, "Aggregator ID: N/A\n");
+	}
+	seq_printf(seq, "Slave queue ID: %d\n", slave->queue_id);
+}
+
+static int bond_info_seq_show(struct seq_file *seq, void *v)
+{
+	if (v == SEQ_START_TOKEN) {
+		seq_printf(seq, "%s\n", bond_version);
+		bond_info_show_master(seq);
+	} else
+		bond_info_show_slave(seq, v);
+
+	return 0;
+}
+
+static const struct seq_operations bond_info_seq_ops = {
+	.start = bond_info_seq_start,
+	.next  = bond_info_seq_next,
+	.stop  = bond_info_seq_stop,
+	.show  = bond_info_seq_show,
+};
+
+static int bond_info_open(struct inode *inode, struct file *file)
+{
+	struct seq_file *seq;
+	struct proc_dir_entry *proc;
+	int res;
+
+	res = seq_open(file, &bond_info_seq_ops);
+	if (!res) {
+		/* recover the pointer buried in proc_dir_entry data */
+		seq = file->private_data;
+		proc = PDE(inode);
+		seq->private = proc->data;
+	}
+
+	return res;
+}
+
+static const struct file_operations bond_info_fops = {
+	.owner   = THIS_MODULE,
+	.open    = bond_info_open,
+	.read    = seq_read,
+	.llseek  = seq_lseek,
+	.release = seq_release,
+};
+
+void bond_create_proc_entry(struct bonding *bond)
+{
+	struct net_device *bond_dev = bond->dev;
+	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
+
+	if (bn->proc_dir) {
+		bond->proc_entry = proc_create_data(bond_dev->name,
+						    S_IRUGO, bn->proc_dir,
+						    &bond_info_fops, bond);
+		if (bond->proc_entry == NULL)
+			pr_warning("Warning: Cannot create /proc/net/%s/%s\n",
+				   DRV_NAME, bond_dev->name);
+		else
+			memcpy(bond->proc_file_name, bond_dev->name, IFNAMSIZ);
+	}
+}
+
+void bond_remove_proc_entry(struct bonding *bond)
+{
+	struct net_device *bond_dev = bond->dev;
+	struct bond_net *bn = net_generic(dev_net(bond_dev), bond_net_id);
+
+	if (bn->proc_dir && bond->proc_entry) {
+		remove_proc_entry(bond->proc_file_name, bn->proc_dir);
+		memset(bond->proc_file_name, 0, IFNAMSIZ);
+		bond->proc_entry = NULL;
+	}
+}
+
+/* Create the bonding directory under /proc/net, if doesn't exist yet.
+ * Caller must hold rtnl_lock.
+ */
+void __net_init bond_create_proc_dir(struct bond_net *bn)
+{
+	if (!bn->proc_dir) {
+		bn->proc_dir = proc_mkdir(DRV_NAME, bn->net->proc_net);
+		if (!bn->proc_dir)
+			pr_warning("Warning: cannot create /proc/net/%s\n",
+				   DRV_NAME);
+	}
+}
+
+/* Destroy the bonding directory under /proc/net, if empty.
+ * Caller must hold rtnl_lock.
+ */
+void __net_exit bond_destroy_proc_dir(struct bond_net *bn)
+{
+	if (bn->proc_dir) {
+		remove_proc_entry(DRV_NAME, bn->net->proc_net);
+		bn->proc_dir = NULL;
+	}
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/bond_sysfs.c linux-libre-2.6.39-gnu/drivers/net/bonding/bond_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/net/bonding/bond_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/bond_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,10 @@
 		pr_info("%s is being created...\n", ifname);
 		rv = bond_create(net, ifname);
 		if (rv) {
-			pr_info("Bond creation failed.\n");
+			if (rv == -EEXIST)
+				pr_info("%s already exists.\n", ifname);
+			else
+				pr_info("%s creation failed.\n", ifname);
 			res = rv;
 		}
 	} else if (command[0] == '-') {
@@ -322,11 +325,6 @@
 		ret = -EINVAL;
 		goto out;
 	}
-	if (bond->params.mode == BOND_MODE_8023AD)
-		bond_unset_master_3ad_flags(bond);
-
-	if (bond->params.mode == BOND_MODE_ALB)
-		bond_unset_master_alb_flags(bond);
 
 	bond->params.mode = new_value;
 	bond_set_mode_ops(bond, bond->params.mode);
@@ -527,8 +525,6 @@
 	pr_info("%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) {
 		pr_info("%s: ARP monitoring cannot be used with MII monitoring. %s Disabling MII monitoring.\n",
 			bond->dev->name, bond->dev->name);
@@ -1004,7 +1000,6 @@
 			pr_info("%s: MII monitoring cannot be used with ARP monitoring. Disabling ARP monitoring...\n",
 				bond->dev->name);
 			bond->params.arp_interval = 0;
-			bond->dev->priv_flags &= ~IFF_MASTER_ARPMON;
 			if (bond->params.arp_validate) {
 				bond_unregister_arp(bond);
 				bond->params.arp_validate =
@@ -1198,7 +1193,7 @@
 			bond->dev->name, new_value);
 	}
 out:
-	return count;
+	return ret;
 }
 static DEVICE_ATTR(use_carrier, S_IRUGO | S_IWUSR,
 		   bonding_show_carrier, bonding_store_carrier);
@@ -1587,15 +1582,15 @@
 	}
 
 	bond_for_each_slave(bond, slave, i) {
-		if (slave->state == BOND_STATE_BACKUP) {
+		if (!bond_is_active_slave(slave)) {
 			if (new_value)
-				slave->dev->priv_flags &= ~IFF_SLAVE_INACTIVE;
+				slave->inactive = 0;
 			else
-				slave->dev->priv_flags |= IFF_SLAVE_INACTIVE;
+				slave->inactive = 1;
 		}
 	}
 out:
-	return count;
+	return ret;
 }
 static DEVICE_ATTR(all_slaves_active, S_IRUGO | S_IWUSR,
 		   bonding_show_slaves_active, bonding_store_slaves_active);
diff -druN linux-libre-2.6.38-gnu/drivers/net/bonding/Makefile linux-libre-2.6.39-gnu/drivers/net/bonding/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/bonding/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/bonding/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,9 @@
 
 bonding-objs := bond_main.o bond_3ad.o bond_alb.o bond_sysfs.o bond_debugfs.o
 
+proc-$(CONFIG_PROC_FS) += bond_procfs.o
+bonding-objs += $(proc-y)
+
 ipv6-$(subst m,y,$(CONFIG_IPV6)) += bond_ipv6.o
 bonding-objs += $(ipv6-y)
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/caif/caif_shmcore.c linux-libre-2.6.39-gnu/drivers/net/caif/caif_shmcore.c
--- linux-libre-2.6.38-gnu/drivers/net/caif/caif_shmcore.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/caif/caif_shmcore.c	2011-05-19 00:06:34.000000000 -0400
@@ -591,7 +591,7 @@
 			(NR_TX_BUF * TX_BUF_SZ + NR_RX_BUF * RX_BUF_SZ)) {
 
 		pr_warn("ERROR, Amount of available"
-				" Phys. SHM cannot accomodate current SHM "
+				" Phys. SHM cannot accommodate current SHM "
 				"driver configuration, Bailing out ...\n");
 		free_netdev(pshm_dev->pshm_netdev);
 		return -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/net/caif/caif_spi.c linux-libre-2.6.39-gnu/drivers/net/caif/caif_spi.c
--- linux-libre-2.6.38-gnu/drivers/net/caif/caif_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/caif/caif_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -397,7 +397,7 @@
 	int pkts = 0;
 
 	/*
-	 * Decommit previously commited frames.
+	 * Decommit previously committed frames.
 	 * skb_queue_splice_tail(&cfspi->chead,&cfspi->qhead)
 	 */
 	while (skb_peek(&cfspi->chead)) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/caif/caif_spi_slave.c linux-libre-2.6.39-gnu/drivers/net/caif/caif_spi_slave.c
--- linux-libre-2.6.38-gnu/drivers/net/caif/caif_spi_slave.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/caif/caif_spi_slave.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,7 +98,7 @@
 
 			cfspi_dbg_state(cfspi, CFSPI_STATE_FETCH_PKT);
 
-			/* Copy commited SPI frames after the SPI indication. */
+			/* Copy committed SPI frames after the SPI indication. */
 			ptr = (u8 *) cfspi->xfer.va_tx;
 			ptr += SPI_IND_SZ;
 			len = cfspi_xmitfrm(cfspi, ptr, cfspi->tx_cpck_len);
@@ -158,7 +158,7 @@
 
 		cfspi_dbg_state(cfspi, CFSPI_STATE_SIG_ACTIVE);
 
-		/* Signal that we are ready to recieve data. */
+		/* Signal that we are ready to receive data. */
 		cfspi->dev->sig_xfer(true, cfspi->dev);
 
 		cfspi_dbg_state(cfspi, CFSPI_STATE_WAIT_XFER_DONE);
diff -druN linux-libre-2.6.38-gnu/drivers/net/caif/Makefile linux-libre-2.6.39-gnu/drivers/net/caif/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/caif/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/caif/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,4 @@
-ifeq ($(CONFIG_CAIF_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_CAIF_DEBUG) := -DDEBUG
 
 # Serial interface
 obj-$(CONFIG_CAIF_TTY) += caif_serial.o
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/at91_can.c linux-libre-2.6.39-gnu/drivers/net/can/at91_can.c
--- linux-libre-2.6.38-gnu/drivers/net/can/at91_can.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/at91_can.c	2011-05-19 00:06:34.000000000 -0400
@@ -416,7 +416,7 @@
 
 	stats->tx_bytes += cf->can_dlc;
 
-	/* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */
+	/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
 	can_put_echo_skb(skb, dev, mb - AT91_MB_TX_FIRST);
 
 	/*
@@ -782,7 +782,7 @@
 		reg_msr = at91_read(priv, AT91_MSR(mb));
 		if (likely(reg_msr & AT91_MSR_MRDY &&
 			   ~reg_msr & AT91_MSR_MABT)) {
-			/* _NOTE_: substract AT91_MB_TX_FIRST offset from mb! */
+			/* _NOTE_: subtract AT91_MB_TX_FIRST offset from mb! */
 			can_get_echo_skb(dev, mb - AT91_MB_TX_FIRST);
 			dev->stats.tx_packets++;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/c_can/c_can.c linux-libre-2.6.39-gnu/drivers/net/can/c_can/c_can.c
--- linux-libre-2.6.38-gnu/drivers/net/can/c_can/c_can.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/can/c_can/c_can.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1152 @@
+/*
+ * CAN bus driver for Bosch C_CAN controller
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma@st.com>
+ *
+ * Borrowed heavily from the C_CAN driver originally written by:
+ * Copyright (C) 2007
+ * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
+ * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
+ *
+ * TX and RX NAPI implementation has been borrowed from at91 CAN driver
+ * written by:
+ * Copyright
+ * (C) 2007 by Hans J. Koch <hjk@hansjkoch.de>
+ * (C) 2008, 2009 by Marc Kleine-Budde <kernel@pengutronix.de>
+ *
+ * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
+ * Bosch C_CAN user manual can be obtained from:
+ * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
+ * users_manual_c_can.pdf
+ *
+ * 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/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+
+#include <linux/can.h>
+#include <linux/can/dev.h>
+#include <linux/can/error.h>
+
+#include "c_can.h"
+
+/* control register */
+#define CONTROL_TEST		BIT(7)
+#define CONTROL_CCE		BIT(6)
+#define CONTROL_DISABLE_AR	BIT(5)
+#define CONTROL_ENABLE_AR	(0 << 5)
+#define CONTROL_EIE		BIT(3)
+#define CONTROL_SIE		BIT(2)
+#define CONTROL_IE		BIT(1)
+#define CONTROL_INIT		BIT(0)
+
+/* test register */
+#define TEST_RX			BIT(7)
+#define TEST_TX1		BIT(6)
+#define TEST_TX2		BIT(5)
+#define TEST_LBACK		BIT(4)
+#define TEST_SILENT		BIT(3)
+#define TEST_BASIC		BIT(2)
+
+/* status register */
+#define STATUS_BOFF		BIT(7)
+#define STATUS_EWARN		BIT(6)
+#define STATUS_EPASS		BIT(5)
+#define STATUS_RXOK		BIT(4)
+#define STATUS_TXOK		BIT(3)
+
+/* error counter register */
+#define ERR_CNT_TEC_MASK	0xff
+#define ERR_CNT_TEC_SHIFT	0
+#define ERR_CNT_REC_SHIFT	8
+#define ERR_CNT_REC_MASK	(0x7f << ERR_CNT_REC_SHIFT)
+#define ERR_CNT_RP_SHIFT	15
+#define ERR_CNT_RP_MASK		(0x1 << ERR_CNT_RP_SHIFT)
+
+/* bit-timing register */
+#define BTR_BRP_MASK		0x3f
+#define BTR_BRP_SHIFT		0
+#define BTR_SJW_SHIFT		6
+#define BTR_SJW_MASK		(0x3 << BTR_SJW_SHIFT)
+#define BTR_TSEG1_SHIFT		8
+#define BTR_TSEG1_MASK		(0xf << BTR_TSEG1_SHIFT)
+#define BTR_TSEG2_SHIFT		12
+#define BTR_TSEG2_MASK		(0x7 << BTR_TSEG2_SHIFT)
+
+/* brp extension register */
+#define BRP_EXT_BRPE_MASK	0x0f
+#define BRP_EXT_BRPE_SHIFT	0
+
+/* IFx command request */
+#define IF_COMR_BUSY		BIT(15)
+
+/* IFx command mask */
+#define IF_COMM_WR		BIT(7)
+#define IF_COMM_MASK		BIT(6)
+#define IF_COMM_ARB		BIT(5)
+#define IF_COMM_CONTROL		BIT(4)
+#define IF_COMM_CLR_INT_PND	BIT(3)
+#define IF_COMM_TXRQST		BIT(2)
+#define IF_COMM_DATAA		BIT(1)
+#define IF_COMM_DATAB		BIT(0)
+#define IF_COMM_ALL		(IF_COMM_MASK | IF_COMM_ARB | \
+				IF_COMM_CONTROL | IF_COMM_TXRQST | \
+				IF_COMM_DATAA | IF_COMM_DATAB)
+
+/* IFx arbitration */
+#define IF_ARB_MSGVAL		BIT(15)
+#define IF_ARB_MSGXTD		BIT(14)
+#define IF_ARB_TRANSMIT		BIT(13)
+
+/* IFx message control */
+#define IF_MCONT_NEWDAT		BIT(15)
+#define IF_MCONT_MSGLST		BIT(14)
+#define IF_MCONT_CLR_MSGLST	(0 << 14)
+#define IF_MCONT_INTPND		BIT(13)
+#define IF_MCONT_UMASK		BIT(12)
+#define IF_MCONT_TXIE		BIT(11)
+#define IF_MCONT_RXIE		BIT(10)
+#define IF_MCONT_RMTEN		BIT(9)
+#define IF_MCONT_TXRQST		BIT(8)
+#define IF_MCONT_EOB		BIT(7)
+#define IF_MCONT_DLC_MASK	0xf
+
+/*
+ * IFx register masks:
+ * allow easy operation on 16-bit registers when the
+ * argument is 32-bit instead
+ */
+#define IFX_WRITE_LOW_16BIT(x)	((x) & 0xFFFF)
+#define IFX_WRITE_HIGH_16BIT(x)	(((x) & 0xFFFF0000) >> 16)
+
+/* message object split */
+#define C_CAN_NO_OF_OBJECTS	32
+#define C_CAN_MSG_OBJ_RX_NUM	16
+#define C_CAN_MSG_OBJ_TX_NUM	16
+
+#define C_CAN_MSG_OBJ_RX_FIRST	1
+#define C_CAN_MSG_OBJ_RX_LAST	(C_CAN_MSG_OBJ_RX_FIRST + \
+				C_CAN_MSG_OBJ_RX_NUM - 1)
+
+#define C_CAN_MSG_OBJ_TX_FIRST	(C_CAN_MSG_OBJ_RX_LAST + 1)
+#define C_CAN_MSG_OBJ_TX_LAST	(C_CAN_MSG_OBJ_TX_FIRST + \
+				C_CAN_MSG_OBJ_TX_NUM - 1)
+
+#define C_CAN_MSG_OBJ_RX_SPLIT	9
+#define C_CAN_MSG_RX_LOW_LAST	(C_CAN_MSG_OBJ_RX_SPLIT - 1)
+
+#define C_CAN_NEXT_MSG_OBJ_MASK	(C_CAN_MSG_OBJ_TX_NUM - 1)
+#define RECEIVE_OBJECT_BITS	0x0000ffff
+
+/* status interrupt */
+#define STATUS_INTERRUPT	0x8000
+
+/* global interrupt masks */
+#define ENABLE_ALL_INTERRUPTS	1
+#define DISABLE_ALL_INTERRUPTS	0
+
+/* minimum timeout for checking BUSY status */
+#define MIN_TIMEOUT_VALUE	6
+
+/* napi related */
+#define C_CAN_NAPI_WEIGHT	C_CAN_MSG_OBJ_RX_NUM
+
+/* c_can lec values */
+enum c_can_lec_type {
+	LEC_NO_ERROR = 0,
+	LEC_STUFF_ERROR,
+	LEC_FORM_ERROR,
+	LEC_ACK_ERROR,
+	LEC_BIT1_ERROR,
+	LEC_BIT0_ERROR,
+	LEC_CRC_ERROR,
+	LEC_UNUSED,
+};
+
+/*
+ * c_can error types:
+ * Bus errors (BUS_OFF, ERROR_WARNING, ERROR_PASSIVE) are supported
+ */
+enum c_can_bus_error_types {
+	C_CAN_NO_ERROR = 0,
+	C_CAN_BUS_OFF,
+	C_CAN_ERROR_WARNING,
+	C_CAN_ERROR_PASSIVE,
+};
+
+static struct can_bittiming_const c_can_bittiming_const = {
+	.name = KBUILD_MODNAME,
+	.tseg1_min = 2,		/* Time segment 1 = prop_seg + phase_seg1 */
+	.tseg1_max = 16,
+	.tseg2_min = 1,		/* Time segment 2 = phase_seg2 */
+	.tseg2_max = 8,
+	.sjw_max = 4,
+	.brp_min = 1,
+	.brp_max = 1024,	/* 6-bit BRP field + 4-bit BRPE field*/
+	.brp_inc = 1,
+};
+
+static inline int get_tx_next_msg_obj(const struct c_can_priv *priv)
+{
+	return (priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) +
+			C_CAN_MSG_OBJ_TX_FIRST;
+}
+
+static inline int get_tx_echo_msg_obj(const struct c_can_priv *priv)
+{
+	return (priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) +
+			C_CAN_MSG_OBJ_TX_FIRST;
+}
+
+static u32 c_can_read_reg32(struct c_can_priv *priv, void *reg)
+{
+	u32 val = priv->read_reg(priv, reg);
+	val |= ((u32) priv->read_reg(priv, reg + 2)) << 16;
+	return val;
+}
+
+static void c_can_enable_all_interrupts(struct c_can_priv *priv,
+						int enable)
+{
+	unsigned int cntrl_save = priv->read_reg(priv,
+						&priv->regs->control);
+
+	if (enable)
+		cntrl_save |= (CONTROL_SIE | CONTROL_EIE | CONTROL_IE);
+	else
+		cntrl_save &= ~(CONTROL_EIE | CONTROL_IE | CONTROL_SIE);
+
+	priv->write_reg(priv, &priv->regs->control, cntrl_save);
+}
+
+static inline int c_can_msg_obj_is_busy(struct c_can_priv *priv, int iface)
+{
+	int count = MIN_TIMEOUT_VALUE;
+
+	while (count && priv->read_reg(priv,
+				&priv->regs->ifregs[iface].com_req) &
+				IF_COMR_BUSY) {
+		count--;
+		udelay(1);
+	}
+
+	if (!count)
+		return 1;
+
+	return 0;
+}
+
+static inline void c_can_object_get(struct net_device *dev,
+					int iface, int objno, int mask)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/*
+	 * As per specs, after writting the message object number in the
+	 * IF command request register the transfer b/w interface
+	 * register and message RAM must be complete in 6 CAN-CLK
+	 * period.
+	 */
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_mask,
+			IFX_WRITE_LOW_16BIT(mask));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_req,
+			IFX_WRITE_LOW_16BIT(objno));
+
+	if (c_can_msg_obj_is_busy(priv, iface))
+		netdev_err(dev, "timed out in object get\n");
+}
+
+static inline void c_can_object_put(struct net_device *dev,
+					int iface, int objno, int mask)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/*
+	 * As per specs, after writting the message object number in the
+	 * IF command request register the transfer b/w interface
+	 * register and message RAM must be complete in 6 CAN-CLK
+	 * period.
+	 */
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_mask,
+			(IF_COMM_WR | IFX_WRITE_LOW_16BIT(mask)));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].com_req,
+			IFX_WRITE_LOW_16BIT(objno));
+
+	if (c_can_msg_obj_is_busy(priv, iface))
+		netdev_err(dev, "timed out in object put\n");
+}
+
+static void c_can_write_msg_object(struct net_device *dev,
+			int iface, struct can_frame *frame, int objno)
+{
+	int i;
+	u16 flags = 0;
+	unsigned int id;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	if (!(frame->can_id & CAN_RTR_FLAG))
+		flags |= IF_ARB_TRANSMIT;
+
+	if (frame->can_id & CAN_EFF_FLAG) {
+		id = frame->can_id & CAN_EFF_MASK;
+		flags |= IF_ARB_MSGXTD;
+	} else
+		id = ((frame->can_id & CAN_SFF_MASK) << 18);
+
+	flags |= IF_ARB_MSGVAL;
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
+				IFX_WRITE_LOW_16BIT(id));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, flags |
+				IFX_WRITE_HIGH_16BIT(id));
+
+	for (i = 0; i < frame->can_dlc; i += 2) {
+		priv->write_reg(priv, &priv->regs->ifregs[iface].data[i / 2],
+				frame->data[i] | (frame->data[i + 1] << 8));
+	}
+
+	/* enable interrupt for this message object */
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			IF_MCONT_TXIE | IF_MCONT_TXRQST | IF_MCONT_EOB |
+			frame->can_dlc);
+	c_can_object_put(dev, iface, objno, IF_COMM_ALL);
+}
+
+static inline void c_can_mark_rx_msg_obj(struct net_device *dev,
+						int iface, int ctrl_mask,
+						int obj)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			ctrl_mask & ~(IF_MCONT_MSGLST | IF_MCONT_INTPND));
+	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
+
+}
+
+static inline void c_can_activate_all_lower_rx_msg_obj(struct net_device *dev,
+						int iface,
+						int ctrl_mask)
+{
+	int i;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_MSG_RX_LOW_LAST; i++) {
+		priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+				ctrl_mask & ~(IF_MCONT_MSGLST |
+					IF_MCONT_INTPND | IF_MCONT_NEWDAT));
+		c_can_object_put(dev, iface, i, IF_COMM_CONTROL);
+	}
+}
+
+static inline void c_can_activate_rx_msg_obj(struct net_device *dev,
+						int iface, int ctrl_mask,
+						int obj)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			ctrl_mask & ~(IF_MCONT_MSGLST |
+				IF_MCONT_INTPND | IF_MCONT_NEWDAT));
+	c_can_object_put(dev, iface, obj, IF_COMM_CONTROL);
+}
+
+static void c_can_handle_lost_msg_obj(struct net_device *dev,
+					int iface, int objno)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	netdev_err(dev, "msg lost in buffer %d\n", objno);
+
+	c_can_object_get(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl,
+			IF_MCONT_CLR_MSGLST);
+
+	c_can_object_put(dev, 0, objno, IF_COMM_CONTROL);
+
+	/* create an error msg */
+	skb = alloc_can_err_skb(dev, &frame);
+	if (unlikely(!skb))
+		return;
+
+	frame->can_id |= CAN_ERR_CRTL;
+	frame->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
+	stats->rx_errors++;
+	stats->rx_over_errors++;
+
+	netif_receive_skb(skb);
+}
+
+static int c_can_read_msg_object(struct net_device *dev, int iface, int ctrl)
+{
+	u16 flags, data;
+	int i;
+	unsigned int val;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct sk_buff *skb;
+	struct can_frame *frame;
+
+	skb = alloc_can_skb(dev, &frame);
+	if (!skb) {
+		stats->rx_dropped++;
+		return -ENOMEM;
+	}
+
+	frame->can_dlc = get_can_dlc(ctrl & 0x0F);
+
+	flags =	priv->read_reg(priv, &priv->regs->ifregs[iface].arb2);
+	val = priv->read_reg(priv, &priv->regs->ifregs[iface].arb1) |
+		(flags << 16);
+
+	if (flags & IF_ARB_MSGXTD)
+		frame->can_id = (val & CAN_EFF_MASK) | CAN_EFF_FLAG;
+	else
+		frame->can_id = (val >> 18) & CAN_SFF_MASK;
+
+	if (flags & IF_ARB_TRANSMIT)
+		frame->can_id |= CAN_RTR_FLAG;
+	else {
+		for (i = 0; i < frame->can_dlc; i += 2) {
+			data = priv->read_reg(priv,
+				&priv->regs->ifregs[iface].data[i / 2]);
+			frame->data[i] = data;
+			frame->data[i + 1] = data >> 8;
+		}
+	}
+
+	netif_receive_skb(skb);
+
+	stats->rx_packets++;
+	stats->rx_bytes += frame->can_dlc;
+
+	return 0;
+}
+
+static void c_can_setup_receive_object(struct net_device *dev, int iface,
+					int objno, unsigned int mask,
+					unsigned int id, unsigned int mcont)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].mask1,
+			IFX_WRITE_LOW_16BIT(mask));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].mask2,
+			IFX_WRITE_HIGH_16BIT(mask));
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1,
+			IFX_WRITE_LOW_16BIT(id));
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2,
+			(IF_ARB_MSGVAL | IFX_WRITE_HIGH_16BIT(id)));
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, mcont);
+	c_can_object_put(dev, iface, objno, IF_COMM_ALL & ~IF_COMM_TXRQST);
+
+	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
+			c_can_read_reg32(priv, &priv->regs->msgval1));
+}
+
+static void c_can_inval_msg_object(struct net_device *dev, int iface, int objno)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb1, 0);
+	priv->write_reg(priv, &priv->regs->ifregs[iface].arb2, 0);
+	priv->write_reg(priv, &priv->regs->ifregs[iface].msg_cntrl, 0);
+
+	c_can_object_put(dev, iface, objno, IF_COMM_ARB | IF_COMM_CONTROL);
+
+	netdev_dbg(dev, "obj no:%d, msgval:0x%08x\n", objno,
+			c_can_read_reg32(priv, &priv->regs->msgval1));
+}
+
+static inline int c_can_is_next_tx_obj_busy(struct c_can_priv *priv, int objno)
+{
+	int val = c_can_read_reg32(priv, &priv->regs->txrqst1);
+
+	/*
+	 * as transmission request register's bit n-1 corresponds to
+	 * message object n, we need to handle the same properly.
+	 */
+	if (val & (1 << (objno - 1)))
+		return 1;
+
+	return 0;
+}
+
+static netdev_tx_t c_can_start_xmit(struct sk_buff *skb,
+					struct net_device *dev)
+{
+	u32 msg_obj_no;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct can_frame *frame = (struct can_frame *)skb->data;
+
+	if (can_dropped_invalid_skb(dev, skb))
+		return NETDEV_TX_OK;
+
+	msg_obj_no = get_tx_next_msg_obj(priv);
+
+	/* prepare message object for transmission */
+	c_can_write_msg_object(dev, 0, frame, msg_obj_no);
+	can_put_echo_skb(skb, dev, msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+
+	/*
+	 * we have to stop the queue in case of a wrap around or
+	 * if the next TX message object is still in use
+	 */
+	priv->tx_next++;
+	if (c_can_is_next_tx_obj_busy(priv, get_tx_next_msg_obj(priv)) ||
+			(priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) == 0)
+		netif_stop_queue(dev);
+
+	return NETDEV_TX_OK;
+}
+
+static int c_can_set_bittiming(struct net_device *dev)
+{
+	unsigned int reg_btr, reg_brpe, ctrl_save;
+	u8 brp, brpe, sjw, tseg1, tseg2;
+	u32 ten_bit_brp;
+	struct c_can_priv *priv = netdev_priv(dev);
+	const struct can_bittiming *bt = &priv->can.bittiming;
+
+	/* c_can provides a 6-bit brp and 4-bit brpe fields */
+	ten_bit_brp = bt->brp - 1;
+	brp = ten_bit_brp & BTR_BRP_MASK;
+	brpe = ten_bit_brp >> 6;
+
+	sjw = bt->sjw - 1;
+	tseg1 = bt->prop_seg + bt->phase_seg1 - 1;
+	tseg2 = bt->phase_seg2 - 1;
+	reg_btr = brp | (sjw << BTR_SJW_SHIFT) | (tseg1 << BTR_TSEG1_SHIFT) |
+			(tseg2 << BTR_TSEG2_SHIFT);
+	reg_brpe = brpe & BRP_EXT_BRPE_MASK;
+
+	netdev_info(dev,
+		"setting BTR=%04x BRPE=%04x\n", reg_btr, reg_brpe);
+
+	ctrl_save = priv->read_reg(priv, &priv->regs->control);
+	priv->write_reg(priv, &priv->regs->control,
+			ctrl_save | CONTROL_CCE | CONTROL_INIT);
+	priv->write_reg(priv, &priv->regs->btr, reg_btr);
+	priv->write_reg(priv, &priv->regs->brp_ext, reg_brpe);
+	priv->write_reg(priv, &priv->regs->control, ctrl_save);
+
+	return 0;
+}
+
+/*
+ * Configure C_CAN message objects for Tx and Rx purposes:
+ * C_CAN provides a total of 32 message objects that can be configured
+ * either for Tx or Rx purposes. Here the first 16 message objects are used as
+ * a reception FIFO. The end of reception FIFO is signified by the EoB bit
+ * being SET. The remaining 16 message objects are kept aside for Tx purposes.
+ * See user guide document for further details on configuring message
+ * objects.
+ */
+static void c_can_configure_msg_objects(struct net_device *dev)
+{
+	int i;
+
+	/* first invalidate all message objects */
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i <= C_CAN_NO_OF_OBJECTS; i++)
+		c_can_inval_msg_object(dev, 0, i);
+
+	/* setup receive message objects */
+	for (i = C_CAN_MSG_OBJ_RX_FIRST; i < C_CAN_MSG_OBJ_RX_LAST; i++)
+		c_can_setup_receive_object(dev, 0, i, 0, 0,
+			(IF_MCONT_RXIE | IF_MCONT_UMASK) & ~IF_MCONT_EOB);
+
+	c_can_setup_receive_object(dev, 0, C_CAN_MSG_OBJ_RX_LAST, 0, 0,
+			IF_MCONT_EOB | IF_MCONT_RXIE | IF_MCONT_UMASK);
+}
+
+/*
+ * Configure C_CAN chip:
+ * - enable/disable auto-retransmission
+ * - set operating mode
+ * - configure message objects
+ */
+static void c_can_chip_config(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* enable automatic retransmission */
+	priv->write_reg(priv, &priv->regs->control,
+			CONTROL_ENABLE_AR);
+
+	if (priv->can.ctrlmode & (CAN_CTRLMODE_LISTENONLY &
+					CAN_CTRLMODE_LOOPBACK)) {
+		/* loopback + silent mode : useful for hot self-test */
+		priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
+				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, &priv->regs->test,
+				TEST_LBACK | TEST_SILENT);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
+		/* loopback mode : useful for self-test function */
+		priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
+				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, &priv->regs->test, TEST_LBACK);
+	} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
+		/* silent mode : bus-monitoring mode */
+		priv->write_reg(priv, &priv->regs->control, CONTROL_EIE |
+				CONTROL_SIE | CONTROL_IE | CONTROL_TEST);
+		priv->write_reg(priv, &priv->regs->test, TEST_SILENT);
+	} else
+		/* normal mode*/
+		priv->write_reg(priv, &priv->regs->control,
+				CONTROL_EIE | CONTROL_SIE | CONTROL_IE);
+
+	/* configure message objects */
+	c_can_configure_msg_objects(dev);
+
+	/* set a `lec` value so that we can check for updates later */
+	priv->write_reg(priv, &priv->regs->status, LEC_UNUSED);
+
+	/* set bittiming params */
+	c_can_set_bittiming(dev);
+}
+
+static void c_can_start(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* basic c_can configuration */
+	c_can_chip_config(dev);
+
+	priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+	/* reset tx helper pointers */
+	priv->tx_next = priv->tx_echo = 0;
+
+	/* enable status change, error and module interrupts */
+	c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+}
+
+static void c_can_stop(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* disable all interrupts */
+	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+
+	/* set the state as STOPPED */
+	priv->can.state = CAN_STATE_STOPPED;
+}
+
+static int c_can_set_mode(struct net_device *dev, enum can_mode mode)
+{
+	switch (mode) {
+	case CAN_MODE_START:
+		c_can_start(dev);
+		netif_wake_queue(dev);
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	return 0;
+}
+
+static int c_can_get_berr_counter(const struct net_device *dev,
+					struct can_berr_counter *bec)
+{
+	unsigned int reg_err_counter;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	reg_err_counter = priv->read_reg(priv, &priv->regs->err_cnt);
+	bec->rxerr = (reg_err_counter & ERR_CNT_REC_MASK) >>
+				ERR_CNT_REC_SHIFT;
+	bec->txerr = reg_err_counter & ERR_CNT_TEC_MASK;
+
+	return 0;
+}
+
+/*
+ * theory of operation:
+ *
+ * priv->tx_echo holds the number of the oldest can_frame put for
+ * transmission into the hardware, but not yet ACKed by the CAN tx
+ * complete IRQ.
+ *
+ * We iterate from priv->tx_echo to priv->tx_next and check if the
+ * packet has been transmitted, echo it back to the CAN framework.
+ * If we discover a not yet transmitted package, stop looking for more.
+ */
+static void c_can_do_tx(struct net_device *dev)
+{
+	u32 val;
+	u32 msg_obj_no;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+
+	for (/* nix */; (priv->tx_next - priv->tx_echo) > 0; priv->tx_echo++) {
+		msg_obj_no = get_tx_echo_msg_obj(priv);
+		val = c_can_read_reg32(priv, &priv->regs->txrqst1);
+		if (!(val & (1 << msg_obj_no))) {
+			can_get_echo_skb(dev,
+					msg_obj_no - C_CAN_MSG_OBJ_TX_FIRST);
+			stats->tx_bytes += priv->read_reg(priv,
+					&priv->regs->ifregs[0].msg_cntrl)
+					& IF_MCONT_DLC_MASK;
+			stats->tx_packets++;
+			c_can_inval_msg_object(dev, 0, msg_obj_no);
+		}
+	}
+
+	/* restart queue if wrap-up or if queue stalled on last pkt */
+	if (((priv->tx_next & C_CAN_NEXT_MSG_OBJ_MASK) != 0) ||
+			((priv->tx_echo & C_CAN_NEXT_MSG_OBJ_MASK) == 0))
+		netif_wake_queue(dev);
+}
+
+/*
+ * theory of operation:
+ *
+ * c_can core saves a received CAN message into the first free message
+ * object it finds free (starting with the lowest). Bits NEWDAT and
+ * INTPND are set for this message object indicating that a new message
+ * has arrived. To work-around this issue, we keep two groups of message
+ * objects whose partitioning is defined by C_CAN_MSG_OBJ_RX_SPLIT.
+ *
+ * To ensure in-order frame reception we use the following
+ * approach while re-activating a message object to receive further
+ * frames:
+ * - if the current message object number is lower than
+ *   C_CAN_MSG_RX_LOW_LAST, do not clear the NEWDAT bit while clearing
+ *   the INTPND bit.
+ * - if the current message object number is equal to
+ *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of all lower
+ *   receive message objects.
+ * - if the current message object number is greater than
+ *   C_CAN_MSG_RX_LOW_LAST then clear the NEWDAT bit of
+ *   only this message object.
+ */
+static int c_can_do_rx_poll(struct net_device *dev, int quota)
+{
+	u32 num_rx_pkts = 0;
+	unsigned int msg_obj, msg_ctrl_save;
+	struct c_can_priv *priv = netdev_priv(dev);
+	u32 val = c_can_read_reg32(priv, &priv->regs->intpnd1);
+
+	for (msg_obj = C_CAN_MSG_OBJ_RX_FIRST;
+			msg_obj <= C_CAN_MSG_OBJ_RX_LAST && quota > 0;
+			val = c_can_read_reg32(priv, &priv->regs->intpnd1),
+			msg_obj++) {
+		/*
+		 * as interrupt pending register's bit n-1 corresponds to
+		 * message object n, we need to handle the same properly.
+		 */
+		if (val & (1 << (msg_obj - 1))) {
+			c_can_object_get(dev, 0, msg_obj, IF_COMM_ALL &
+					~IF_COMM_TXRQST);
+			msg_ctrl_save = priv->read_reg(priv,
+					&priv->regs->ifregs[0].msg_cntrl);
+
+			if (msg_ctrl_save & IF_MCONT_EOB)
+				return num_rx_pkts;
+
+			if (msg_ctrl_save & IF_MCONT_MSGLST) {
+				c_can_handle_lost_msg_obj(dev, 0, msg_obj);
+				num_rx_pkts++;
+				quota--;
+				continue;
+			}
+
+			if (!(msg_ctrl_save & IF_MCONT_NEWDAT))
+				continue;
+
+			/* read the data from the message object */
+			c_can_read_msg_object(dev, 0, msg_ctrl_save);
+
+			if (msg_obj < C_CAN_MSG_RX_LOW_LAST)
+				c_can_mark_rx_msg_obj(dev, 0,
+						msg_ctrl_save, msg_obj);
+			else if (msg_obj > C_CAN_MSG_RX_LOW_LAST)
+				/* activate this msg obj */
+				c_can_activate_rx_msg_obj(dev, 0,
+						msg_ctrl_save, msg_obj);
+			else if (msg_obj == C_CAN_MSG_RX_LOW_LAST)
+				/* activate all lower message objects */
+				c_can_activate_all_lower_rx_msg_obj(dev,
+						0, msg_ctrl_save);
+
+			num_rx_pkts++;
+			quota--;
+		}
+	}
+
+	return num_rx_pkts;
+}
+
+static inline int c_can_has_and_handle_berr(struct c_can_priv *priv)
+{
+	return (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) &&
+		(priv->current_status & LEC_UNUSED);
+}
+
+static int c_can_handle_state_change(struct net_device *dev,
+				enum c_can_bus_error_types error_type)
+{
+	unsigned int reg_err_counter;
+	unsigned int rx_err_passive;
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+	struct can_berr_counter bec;
+
+	/* propagate the error condition to the CAN stack */
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return 0;
+
+	c_can_get_berr_counter(dev, &bec);
+	reg_err_counter = priv->read_reg(priv, &priv->regs->err_cnt);
+	rx_err_passive = (reg_err_counter & ERR_CNT_RP_MASK) >>
+				ERR_CNT_RP_SHIFT;
+
+	switch (error_type) {
+	case C_CAN_ERROR_WARNING:
+		/* error warning state */
+		priv->can.can_stats.error_warning++;
+		priv->can.state = CAN_STATE_ERROR_WARNING;
+		cf->can_id |= CAN_ERR_CRTL;
+		cf->data[1] = (bec.txerr > bec.rxerr) ?
+			CAN_ERR_CRTL_TX_WARNING :
+			CAN_ERR_CRTL_RX_WARNING;
+		cf->data[6] = bec.txerr;
+		cf->data[7] = bec.rxerr;
+
+		break;
+	case C_CAN_ERROR_PASSIVE:
+		/* error passive state */
+		priv->can.can_stats.error_passive++;
+		priv->can.state = CAN_STATE_ERROR_PASSIVE;
+		cf->can_id |= CAN_ERR_CRTL;
+		if (rx_err_passive)
+			cf->data[1] |= CAN_ERR_CRTL_RX_PASSIVE;
+		if (bec.txerr > 127)
+			cf->data[1] |= CAN_ERR_CRTL_TX_PASSIVE;
+
+		cf->data[6] = bec.txerr;
+		cf->data[7] = bec.rxerr;
+		break;
+	case C_CAN_BUS_OFF:
+		/* bus-off state */
+		priv->can.state = CAN_STATE_BUS_OFF;
+		cf->can_id |= CAN_ERR_BUSOFF;
+		/*
+		 * disable all interrupts in bus-off mode to ensure that
+		 * the CPU is not hogged down
+		 */
+		c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+		can_bus_off(dev);
+		break;
+	default:
+		break;
+	}
+
+	netif_receive_skb(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 1;
+}
+
+static int c_can_handle_bus_err(struct net_device *dev,
+				enum c_can_lec_type lec_type)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct net_device_stats *stats = &dev->stats;
+	struct can_frame *cf;
+	struct sk_buff *skb;
+
+	/*
+	 * early exit if no lec update or no error.
+	 * no lec update means that no CAN bus event has been detected
+	 * since CPU wrote 0x7 value to status reg.
+	 */
+	if (lec_type == LEC_UNUSED || lec_type == LEC_NO_ERROR)
+		return 0;
+
+	/* propagate the error condition to the CAN stack */
+	skb = alloc_can_err_skb(dev, &cf);
+	if (unlikely(!skb))
+		return 0;
+
+	/*
+	 * check for 'last error code' which tells us the
+	 * type of the last error to occur on the CAN bus
+	 */
+
+	/* common for all type of bus errors */
+	priv->can.can_stats.bus_error++;
+	stats->rx_errors++;
+	cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
+	cf->data[2] |= CAN_ERR_PROT_UNSPEC;
+
+	switch (lec_type) {
+	case LEC_STUFF_ERROR:
+		netdev_dbg(dev, "stuff error\n");
+		cf->data[2] |= CAN_ERR_PROT_STUFF;
+		break;
+	case LEC_FORM_ERROR:
+		netdev_dbg(dev, "form error\n");
+		cf->data[2] |= CAN_ERR_PROT_FORM;
+		break;
+	case LEC_ACK_ERROR:
+		netdev_dbg(dev, "ack error\n");
+		cf->data[2] |= (CAN_ERR_PROT_LOC_ACK |
+				CAN_ERR_PROT_LOC_ACK_DEL);
+		break;
+	case LEC_BIT1_ERROR:
+		netdev_dbg(dev, "bit1 error\n");
+		cf->data[2] |= CAN_ERR_PROT_BIT1;
+		break;
+	case LEC_BIT0_ERROR:
+		netdev_dbg(dev, "bit0 error\n");
+		cf->data[2] |= CAN_ERR_PROT_BIT0;
+		break;
+	case LEC_CRC_ERROR:
+		netdev_dbg(dev, "CRC error\n");
+		cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+				CAN_ERR_PROT_LOC_CRC_DEL);
+		break;
+	default:
+		break;
+	}
+
+	/* set a `lec` value so that we can check for updates later */
+	priv->write_reg(priv, &priv->regs->status, LEC_UNUSED);
+
+	netif_receive_skb(skb);
+	stats->rx_packets++;
+	stats->rx_bytes += cf->can_dlc;
+
+	return 1;
+}
+
+static int c_can_poll(struct napi_struct *napi, int quota)
+{
+	u16 irqstatus;
+	int lec_type = 0;
+	int work_done = 0;
+	struct net_device *dev = napi->dev;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+	if (!irqstatus)
+		goto end;
+
+	/* status events have the highest priority */
+	if (irqstatus == STATUS_INTERRUPT) {
+		priv->current_status = priv->read_reg(priv,
+					&priv->regs->status);
+
+		/* handle Tx/Rx events */
+		if (priv->current_status & STATUS_TXOK)
+			priv->write_reg(priv, &priv->regs->status,
+					priv->current_status & ~STATUS_TXOK);
+
+		if (priv->current_status & STATUS_RXOK)
+			priv->write_reg(priv, &priv->regs->status,
+					priv->current_status & ~STATUS_RXOK);
+
+		/* handle state changes */
+		if ((priv->current_status & STATUS_EWARN) &&
+				(!(priv->last_status & STATUS_EWARN))) {
+			netdev_dbg(dev, "entered error warning state\n");
+			work_done += c_can_handle_state_change(dev,
+						C_CAN_ERROR_WARNING);
+		}
+		if ((priv->current_status & STATUS_EPASS) &&
+				(!(priv->last_status & STATUS_EPASS))) {
+			netdev_dbg(dev, "entered error passive state\n");
+			work_done += c_can_handle_state_change(dev,
+						C_CAN_ERROR_PASSIVE);
+		}
+		if ((priv->current_status & STATUS_BOFF) &&
+				(!(priv->last_status & STATUS_BOFF))) {
+			netdev_dbg(dev, "entered bus off state\n");
+			work_done += c_can_handle_state_change(dev,
+						C_CAN_BUS_OFF);
+		}
+
+		/* handle bus recovery events */
+		if ((!(priv->current_status & STATUS_BOFF)) &&
+				(priv->last_status & STATUS_BOFF)) {
+			netdev_dbg(dev, "left bus off state\n");
+			priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		}
+		if ((!(priv->current_status & STATUS_EPASS)) &&
+				(priv->last_status & STATUS_EPASS)) {
+			netdev_dbg(dev, "left error passive state\n");
+			priv->can.state = CAN_STATE_ERROR_ACTIVE;
+		}
+
+		priv->last_status = priv->current_status;
+
+		/* handle lec errors on the bus */
+		lec_type = c_can_has_and_handle_berr(priv);
+		if (lec_type)
+			work_done += c_can_handle_bus_err(dev, lec_type);
+	} else if ((irqstatus >= C_CAN_MSG_OBJ_RX_FIRST) &&
+			(irqstatus <= C_CAN_MSG_OBJ_RX_LAST)) {
+		/* handle events corresponding to receive message objects */
+		work_done += c_can_do_rx_poll(dev, (quota - work_done));
+	} else if ((irqstatus >= C_CAN_MSG_OBJ_TX_FIRST) &&
+			(irqstatus <= C_CAN_MSG_OBJ_TX_LAST)) {
+		/* handle events corresponding to transmit message objects */
+		c_can_do_tx(dev);
+	}
+
+end:
+	if (work_done < quota) {
+		napi_complete(napi);
+		/* enable all IRQs */
+		c_can_enable_all_interrupts(priv, ENABLE_ALL_INTERRUPTS);
+	}
+
+	return work_done;
+}
+
+static irqreturn_t c_can_isr(int irq, void *dev_id)
+{
+	u16 irqstatus;
+	struct net_device *dev = (struct net_device *)dev_id;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	irqstatus = priv->read_reg(priv, &priv->regs->interrupt);
+	if (!irqstatus)
+		return IRQ_NONE;
+
+	/* disable all interrupts and schedule the NAPI */
+	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+	napi_schedule(&priv->napi);
+
+	return IRQ_HANDLED;
+}
+
+static int c_can_open(struct net_device *dev)
+{
+	int err;
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* open the can device */
+	err = open_candev(dev);
+	if (err) {
+		netdev_err(dev, "failed to open can device\n");
+		return err;
+	}
+
+	/* register interrupt handler */
+	err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name,
+				dev);
+	if (err < 0) {
+		netdev_err(dev, "failed to request interrupt\n");
+		goto exit_irq_fail;
+	}
+
+	/* start the c_can controller */
+	c_can_start(dev);
+
+	napi_enable(&priv->napi);
+	netif_start_queue(dev);
+
+	return 0;
+
+exit_irq_fail:
+	close_candev(dev);
+	return err;
+}
+
+static int c_can_close(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	netif_stop_queue(dev);
+	napi_disable(&priv->napi);
+	c_can_stop(dev);
+	free_irq(dev->irq, dev);
+	close_candev(dev);
+
+	return 0;
+}
+
+struct net_device *alloc_c_can_dev(void)
+{
+	struct net_device *dev;
+	struct c_can_priv *priv;
+
+	dev = alloc_candev(sizeof(struct c_can_priv), C_CAN_MSG_OBJ_TX_NUM);
+	if (!dev)
+		return NULL;
+
+	priv = netdev_priv(dev);
+	netif_napi_add(dev, &priv->napi, c_can_poll, C_CAN_NAPI_WEIGHT);
+
+	priv->dev = dev;
+	priv->can.bittiming_const = &c_can_bittiming_const;
+	priv->can.do_set_mode = c_can_set_mode;
+	priv->can.do_get_berr_counter = c_can_get_berr_counter;
+	priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
+					CAN_CTRLMODE_LISTENONLY |
+					CAN_CTRLMODE_BERR_REPORTING;
+
+	return dev;
+}
+EXPORT_SYMBOL_GPL(alloc_c_can_dev);
+
+void free_c_can_dev(struct net_device *dev)
+{
+	free_candev(dev);
+}
+EXPORT_SYMBOL_GPL(free_c_can_dev);
+
+static const struct net_device_ops c_can_netdev_ops = {
+	.ndo_open = c_can_open,
+	.ndo_stop = c_can_close,
+	.ndo_start_xmit = c_can_start_xmit,
+};
+
+int register_c_can_dev(struct net_device *dev)
+{
+	dev->flags |= IFF_ECHO;	/* we support local echo */
+	dev->netdev_ops = &c_can_netdev_ops;
+
+	return register_candev(dev);
+}
+EXPORT_SYMBOL_GPL(register_c_can_dev);
+
+void unregister_c_can_dev(struct net_device *dev)
+{
+	struct c_can_priv *priv = netdev_priv(dev);
+
+	/* disable all interrupts */
+	c_can_enable_all_interrupts(priv, DISABLE_ALL_INTERRUPTS);
+
+	unregister_candev(dev);
+}
+EXPORT_SYMBOL_GPL(unregister_c_can_dev);
+
+MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CAN bus driver for Bosch C_CAN controller");
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/c_can/c_can.h linux-libre-2.6.39-gnu/drivers/net/can/c_can/c_can.h
--- linux-libre-2.6.38-gnu/drivers/net/can/c_can/c_can.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/can/c_can/c_can.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,86 @@
+/*
+ * CAN bus driver for Bosch C_CAN controller
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma@st.com>
+ *
+ * Borrowed heavily from the C_CAN driver originally written by:
+ * Copyright (C) 2007
+ * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
+ * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
+ *
+ * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
+ * Bosch C_CAN user manual can be obtained from:
+ * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
+ * users_manual_c_can.pdf
+ *
+ * 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 C_CAN_H
+#define C_CAN_H
+
+/* c_can IF registers */
+struct c_can_if_regs {
+	u16 com_req;
+	u16 com_mask;
+	u16 mask1;
+	u16 mask2;
+	u16 arb1;
+	u16 arb2;
+	u16 msg_cntrl;
+	u16 data[4];
+	u16 _reserved[13];
+};
+
+/* c_can hardware registers */
+struct c_can_regs {
+	u16 control;
+	u16 status;
+	u16 err_cnt;
+	u16 btr;
+	u16 interrupt;
+	u16 test;
+	u16 brp_ext;
+	u16 _reserved1;
+	struct c_can_if_regs ifregs[2]; /* [0] = IF1 and [1] = IF2 */
+	u16 _reserved2[8];
+	u16 txrqst1;
+	u16 txrqst2;
+	u16 _reserved3[6];
+	u16 newdat1;
+	u16 newdat2;
+	u16 _reserved4[6];
+	u16 intpnd1;
+	u16 intpnd2;
+	u16 _reserved5[6];
+	u16 msgval1;
+	u16 msgval2;
+	u16 _reserved6[6];
+};
+
+/* c_can private data structure */
+struct c_can_priv {
+	struct can_priv can;	/* must be the first member */
+	struct napi_struct napi;
+	struct net_device *dev;
+	int tx_object;
+	int current_status;
+	int last_status;
+	u16 (*read_reg) (struct c_can_priv *priv, void *reg);
+	void (*write_reg) (struct c_can_priv *priv, void *reg, u16 val);
+	struct c_can_regs __iomem *regs;
+	unsigned long irq_flags; /* for request_irq() */
+	unsigned int tx_next;
+	unsigned int tx_echo;
+	void *priv;		/* for board-specific data */
+};
+
+struct net_device *alloc_c_can_dev(void);
+void free_c_can_dev(struct net_device *dev);
+int register_c_can_dev(struct net_device *dev);
+void unregister_c_can_dev(struct net_device *dev);
+
+#endif /* C_CAN_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/c_can/c_can_platform.c linux-libre-2.6.39-gnu/drivers/net/can/c_can/c_can_platform.c
--- linux-libre-2.6.38-gnu/drivers/net/can/c_can/c_can_platform.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/can/c_can/c_can_platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,216 @@
+/*
+ * Platform CAN bus driver for Bosch C_CAN controller
+ *
+ * Copyright (C) 2010 ST Microelectronics
+ * Bhupesh Sharma <bhupesh.sharma@st.com>
+ *
+ * Borrowed heavily from the C_CAN driver originally written by:
+ * Copyright (C) 2007
+ * - Sascha Hauer, Marc Kleine-Budde, Pengutronix <s.hauer@pengutronix.de>
+ * - Simon Kallweit, intefo AG <simon.kallweit@intefo.ch>
+ *
+ * Bosch C_CAN controller is compliant to CAN protocol version 2.0 part A and B.
+ * Bosch C_CAN user manual can be obtained from:
+ * http://www.semiconductors.bosch.de/media/en/pdf/ipmodules_1/c_can/
+ * users_manual_c_can.pdf
+ *
+ * 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/version.h>
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/netdevice.h>
+#include <linux/if_arp.h>
+#include <linux/if_ether.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <linux/can/dev.h>
+
+#include "c_can.h"
+
+/*
+ * 16-bit c_can registers can be arranged differently in the memory
+ * architecture of different implementations. For example: 16-bit
+ * registers can be aligned to a 16-bit boundary or 32-bit boundary etc.
+ * Handle the same by providing a common read/write interface.
+ */
+static u16 c_can_plat_read_reg_aligned_to_16bit(struct c_can_priv *priv,
+						void *reg)
+{
+	return readw(reg);
+}
+
+static void c_can_plat_write_reg_aligned_to_16bit(struct c_can_priv *priv,
+						void *reg, u16 val)
+{
+	writew(val, reg);
+}
+
+static u16 c_can_plat_read_reg_aligned_to_32bit(struct c_can_priv *priv,
+						void *reg)
+{
+	return readw(reg + (long)reg - (long)priv->regs);
+}
+
+static void c_can_plat_write_reg_aligned_to_32bit(struct c_can_priv *priv,
+						void *reg, u16 val)
+{
+	writew(val, reg + (long)reg - (long)priv->regs);
+}
+
+static int __devinit c_can_plat_probe(struct platform_device *pdev)
+{
+	int ret;
+	void __iomem *addr;
+	struct net_device *dev;
+	struct c_can_priv *priv;
+	struct resource *mem;
+	int irq;
+#ifdef CONFIG_HAVE_CLK
+	struct clk *clk;
+
+	/* get the appropriate clk */
+	clk = clk_get(&pdev->dev, NULL);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "no clock defined\n");
+		ret = -ENODEV;
+		goto exit;
+	}
+#endif
+
+	/* get the platform data */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	irq = platform_get_irq(pdev, 0);
+	if (!mem || irq <= 0) {
+		ret = -ENODEV;
+		goto exit_free_clk;
+	}
+
+	if (!request_mem_region(mem->start, resource_size(mem),
+				KBUILD_MODNAME)) {
+		dev_err(&pdev->dev, "resource unavailable\n");
+		ret = -ENODEV;
+		goto exit_free_clk;
+	}
+
+	addr = ioremap(mem->start, resource_size(mem));
+	if (!addr) {
+		dev_err(&pdev->dev, "failed to map can port\n");
+		ret = -ENOMEM;
+		goto exit_release_mem;
+	}
+
+	/* allocate the c_can device */
+	dev = alloc_c_can_dev();
+	if (!dev) {
+		ret = -ENOMEM;
+		goto exit_iounmap;
+	}
+
+	priv = netdev_priv(dev);
+
+	dev->irq = irq;
+	priv->regs = addr;
+#ifdef CONFIG_HAVE_CLK
+	priv->can.clock.freq = clk_get_rate(clk);
+	priv->priv = clk;
+#endif
+
+	switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
+	case IORESOURCE_MEM_32BIT:
+		priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
+		priv->write_reg = c_can_plat_write_reg_aligned_to_32bit;
+		break;
+	case IORESOURCE_MEM_16BIT:
+	default:
+		priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
+		priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
+		break;
+	}
+
+	platform_set_drvdata(pdev, dev);
+	SET_NETDEV_DEV(dev, &pdev->dev);
+
+	ret = register_c_can_dev(dev);
+	if (ret) {
+		dev_err(&pdev->dev, "registering %s failed (err=%d)\n",
+			KBUILD_MODNAME, ret);
+		goto exit_free_device;
+	}
+
+	dev_info(&pdev->dev, "%s device registered (regs=%p, irq=%d)\n",
+		 KBUILD_MODNAME, priv->regs, dev->irq);
+	return 0;
+
+exit_free_device:
+	platform_set_drvdata(pdev, NULL);
+	free_c_can_dev(dev);
+exit_iounmap:
+	iounmap(addr);
+exit_release_mem:
+	release_mem_region(mem->start, resource_size(mem));
+exit_free_clk:
+#ifdef CONFIG_HAVE_CLK
+	clk_put(clk);
+exit:
+#endif
+	dev_err(&pdev->dev, "probe failed\n");
+
+	return ret;
+}
+
+static int __devexit c_can_plat_remove(struct platform_device *pdev)
+{
+	struct net_device *dev = platform_get_drvdata(pdev);
+	struct c_can_priv *priv = netdev_priv(dev);
+	struct resource *mem;
+
+	unregister_c_can_dev(dev);
+	platform_set_drvdata(pdev, NULL);
+
+	free_c_can_dev(dev);
+	iounmap(priv->regs);
+
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, resource_size(mem));
+
+#ifdef CONFIG_HAVE_CLK
+	clk_put(priv->priv);
+#endif
+
+	return 0;
+}
+
+static struct platform_driver c_can_plat_driver = {
+	.driver = {
+		.name = KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+	.probe = c_can_plat_probe,
+	.remove = __devexit_p(c_can_plat_remove),
+};
+
+static int __init c_can_plat_init(void)
+{
+	return platform_driver_register(&c_can_plat_driver);
+}
+module_init(c_can_plat_init);
+
+static void __exit c_can_plat_exit(void)
+{
+	platform_driver_unregister(&c_can_plat_driver);
+}
+module_exit(c_can_plat_exit);
+
+MODULE_AUTHOR("Bhupesh Sharma <bhupesh.sharma@st.com>");
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("Platform CAN bus driver for Bosch C_CAN controller");
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/c_can/Kconfig linux-libre-2.6.39-gnu/drivers/net/can/c_can/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/can/c_can/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/can/c_can/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,15 @@
+menuconfig CAN_C_CAN
+	tristate "Bosch C_CAN devices"
+	depends on CAN_DEV && HAS_IOMEM
+
+if CAN_C_CAN
+
+config CAN_C_CAN_PLATFORM
+	tristate "Generic Platform Bus based C_CAN driver"
+	---help---
+	  This driver adds support for the C_CAN chips connected to
+	  the "platform bus" (Linux abstraction for directly to the
+	  processor attached devices) which can be found on various
+	  boards from ST Microelectronics (http://www.st.com)
+	  like the SPEAr1310 and SPEAr320 evaluation boards.
+endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/c_can/Makefile linux-libre-2.6.39-gnu/drivers/net/can/c_can/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/can/c_can/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/can/c_can/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,8 @@
+#
+#  Makefile for the Bosch C_CAN controller drivers.
+#
+
+obj-$(CONFIG_CAN_C_CAN) += c_can.o
+obj-$(CONFIG_CAN_C_CAN_PLATFORM) += c_can_platform.o
+
+ccflags-$(CONFIG_CAN_DEBUG_DEVICES) := -DDEBUG
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/janz-ican3.c linux-libre-2.6.39-gnu/drivers/net/can/janz-ican3.c
--- linux-libre-2.6.38-gnu/drivers/net/can/janz-ican3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/janz-ican3.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/interrupt.h>
 #include <linux/delay.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 
 #include <linux/netdevice.h>
 #include <linux/can.h>
@@ -273,7 +274,7 @@
  */
 
 /*
- * Recieve a message from the ICAN3 "old-style" firmware interface
+ * Receive a message from the ICAN3 "old-style" firmware interface
  *
  * LOCKING: must hold mod->lock
  *
@@ -1049,7 +1050,7 @@
 		complete(&mod->termination_comp);
 		break;
 	default:
-		dev_err(mod->dev, "recieved an unknown inquiry response\n");
+		dev_err(mod->dev, "received an unknown inquiry response\n");
 		break;
 	}
 }
@@ -1057,7 +1058,7 @@
 static void ican3_handle_unknown_message(struct ican3_dev *mod,
 					struct ican3_msg *msg)
 {
-	dev_warn(mod->dev, "recieved unknown message: spec 0x%.2x length %d\n",
+	dev_warn(mod->dev, "received unknown message: spec 0x%.2x length %d\n",
 			   msg->spec, le16_to_cpu(msg->len));
 }
 
@@ -1112,7 +1113,7 @@
 }
 
 /*
- * Recieve one CAN frame from the hardware
+ * Receive one CAN frame from the hardware
  *
  * CONTEXT: must be called from user context
  */
@@ -1643,7 +1644,7 @@
 	struct device *dev;
 	int ret;
 
-	pdata = pdev->dev.platform_data;
+	pdata = mfd_get_data(pdev);
 	if (!pdata)
 		return -ENXIO;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/Kconfig linux-libre-2.6.39-gnu/drivers/net/can/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/can/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -115,6 +115,8 @@
 
 source "drivers/net/can/sja1000/Kconfig"
 
+source "drivers/net/can/c_can/Kconfig"
+
 source "drivers/net/can/usb/Kconfig"
 
 source "drivers/net/can/softing/Kconfig"
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/Makefile linux-libre-2.6.39-gnu/drivers/net/can/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/can/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -13,6 +13,7 @@
 
 obj-$(CONFIG_CAN_SJA1000)	+= sja1000/
 obj-$(CONFIG_CAN_MSCAN)		+= mscan/
+obj-$(CONFIG_CAN_C_CAN)		+= c_can/
 obj-$(CONFIG_CAN_AT91)		+= at91_can.o
 obj-$(CONFIG_CAN_TI_HECC)	+= ti_hecc.o
 obj-$(CONFIG_CAN_MCP251X)	+= mcp251x.o
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/mcp251x.c linux-libre-2.6.39-gnu/drivers/net/can/mcp251x.c
--- linux-libre-2.6.38-gnu/drivers/net/can/mcp251x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/mcp251x.c	2011-05-19 00:06:34.000000000 -0400
@@ -931,7 +931,8 @@
 	priv->tx_len = 0;
 
 	ret = request_threaded_irq(spi->irq, NULL, mcp251x_can_ist,
-			  IRQF_TRIGGER_FALLING, DEVICE_NAME, priv);
+		  pdata->irq_flags ? pdata->irq_flags : IRQF_TRIGGER_FALLING,
+		  DEVICE_NAME, priv);
 	if (ret) {
 		dev_err(&spi->dev, "failed to acquire irq %d\n", spi->irq);
 		if (pdata->transceiver_enable)
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/mscan/mpc5xxx_can.c linux-libre-2.6.39-gnu/drivers/net/can/mscan/mpc5xxx_can.c
--- linux-libre-2.6.38-gnu/drivers/net/can/mscan/mpc5xxx_can.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/mscan/mpc5xxx_can.c	2011-05-19 00:06:34.000000000 -0400
@@ -247,10 +247,11 @@
 }
 #endif /* CONFIG_PPC_MPC512x */
 
-static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev,
-				       const struct of_device_id *id)
+static struct of_device_id mpc5xxx_can_table[];
+static int __devinit mpc5xxx_can_probe(struct platform_device *ofdev)
 {
-	struct mpc5xxx_can_data *data = (struct mpc5xxx_can_data *)id->data;
+	const struct of_device_id *match;
+	struct mpc5xxx_can_data *data;
 	struct device_node *np = ofdev->dev.of_node;
 	struct net_device *dev;
 	struct mscan_priv *priv;
@@ -259,6 +260,11 @@
 	int irq, mscan_clksrc = 0;
 	int err = -ENOMEM;
 
+	match = of_match_device(mpc5xxx_can_table, &ofdev->dev);
+	if (!match)
+		return -EINVAL;
+	data = match->data;
+
 	base = of_iomap(np, 0);
 	if (!base) {
 		dev_err(&ofdev->dev, "couldn't ioremap\n");
@@ -391,7 +397,7 @@
 	{},
 };
 
-static struct of_platform_driver mpc5xxx_can_driver = {
+static struct platform_driver mpc5xxx_can_driver = {
 	.driver = {
 		.name = "mpc5xxx_can",
 		.owner = THIS_MODULE,
@@ -407,13 +413,13 @@
 
 static int __init mpc5xxx_can_init(void)
 {
-	return of_register_platform_driver(&mpc5xxx_can_driver);
+	return platform_driver_register(&mpc5xxx_can_driver);
 }
 module_init(mpc5xxx_can_init);
 
 static void __exit mpc5xxx_can_exit(void)
 {
-	return of_unregister_platform_driver(&mpc5xxx_can_driver);
+	platform_driver_unregister(&mpc5xxx_can_driver);
 };
 module_exit(mpc5xxx_can_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/mscan/mscan.c linux-libre-2.6.39-gnu/drivers/net/can/mscan/mscan.c
--- linux-libre-2.6.38-gnu/drivers/net/can/mscan/mscan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/mscan/mscan.c	2011-05-19 00:06:34.000000000 -0400
@@ -246,7 +246,7 @@
 		out_be16(&regs->tx.idr3_2, can_id);
 
 		can_id >>= 16;
-		/* EFF_FLAGS are inbetween the IDs :( */
+		/* EFF_FLAGS are between the IDs :( */
 		can_id = (can_id & 0x7) | ((can_id << 2) & 0xffe0)
 			 | MSCAN_EFF_FLAGS;
 	} else {
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/sja1000/sja1000.c linux-libre-2.6.39-gnu/drivers/net/can/sja1000/sja1000.c
--- linux-libre-2.6.38-gnu/drivers/net/can/sja1000/sja1000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/sja1000/sja1000.c	2011-05-19 00:06:34.000000000 -0400
@@ -346,10 +346,10 @@
 		    | (priv->read_reg(priv, REG_ID2) >> 5);
 	}
 
+	cf->can_dlc = get_can_dlc(fi & 0x0F);
 	if (fi & FI_RTR) {
 		id |= CAN_RTR_FLAG;
 	} else {
-		cf->can_dlc = get_can_dlc(fi & 0x0F);
 		for (i = 0; i < cf->can_dlc; i++)
 			cf->data[i] = priv->read_reg(priv, dreg++);
 	}
@@ -425,7 +425,7 @@
 			cf->data[3] = ecc & ECC_SEG;
 			break;
 		}
-		/* Error occured during transmission? */
+		/* Error occurred during transmission? */
 		if ((ecc & ECC_DIR) == 0)
 			cf->data[2] |= CAN_ERR_PROT_TX;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/sja1000/sja1000_of_platform.c linux-libre-2.6.39-gnu/drivers/net/can/sja1000/sja1000_of_platform.c
--- linux-libre-2.6.38-gnu/drivers/net/can/sja1000/sja1000_of_platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/sja1000/sja1000_of_platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,8 +87,7 @@
 	return 0;
 }
 
-static int __devinit sja1000_ofp_probe(struct platform_device *ofdev,
-				       const struct of_device_id *id)
+static int __devinit sja1000_ofp_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct net_device *dev;
@@ -210,7 +209,7 @@
 };
 MODULE_DEVICE_TABLE(of, sja1000_ofp_table);
 
-static struct of_platform_driver sja1000_ofp_driver = {
+static struct platform_driver sja1000_ofp_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = DRV_NAME,
@@ -222,12 +221,12 @@
 
 static int __init sja1000_ofp_init(void)
 {
-	return of_register_platform_driver(&sja1000_ofp_driver);
+	return platform_driver_register(&sja1000_ofp_driver);
 }
 module_init(sja1000_ofp_init);
 
 static void __exit sja1000_ofp_exit(void)
 {
-	return of_unregister_platform_driver(&sja1000_ofp_driver);
+	return platform_driver_unregister(&sja1000_ofp_driver);
 };
 module_exit(sja1000_ofp_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/slcan.c linux-libre-2.6.39-gnu/drivers/net/can/slcan.c
--- linux-libre-2.6.38-gnu/drivers/net/can/slcan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/slcan.c	2011-05-19 00:06:34.000000000 -0400
@@ -583,7 +583,9 @@
 	/* Done.  We have linked the TTY line to a channel. */
 	rtnl_unlock();
 	tty->receive_room = 65536;	/* We don't flow control */
-	return sl->dev->base_addr;
+
+	/* TTY layer expects 0 on success */
+	return 0;
 
 err_free_chan:
 	sl->tty = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/softing/softing.h linux-libre-2.6.39-gnu/drivers/net/can/softing/softing.h
--- linux-libre-2.6.38-gnu/drivers/net/can/softing/softing.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/softing/softing.h	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,7 @@
 	struct softing *card;
 	struct {
 		int pending;
-		/* variables wich hold the circular buffer */
+		/* variables which hold the circular buffer */
 		int echo_put;
 		int echo_get;
 	} tx;
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/softing/softing_main.c linux-libre-2.6.39-gnu/drivers/net/can/softing/softing_main.c
--- linux-libre-2.6.38-gnu/drivers/net/can/softing/softing_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/softing/softing_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -218,7 +218,7 @@
 	ptr = buf;
 	cmd = *ptr++;
 	if (cmd == 0xff)
-		/* not quite usefull, probably the card has got out */
+		/* not quite useful, probably the card has got out */
 		return 0;
 	netdev = card->net[0];
 	if (cmd & CMD_BUS2)
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/ti_hecc.c linux-libre-2.6.39-gnu/drivers/net/can/ti_hecc.c
--- linux-libre-2.6.38-gnu/drivers/net/can/ti_hecc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/ti_hecc.c	2011-05-19 00:06:34.000000000 -0400
@@ -663,7 +663,7 @@
 	struct can_frame *cf;
 	struct sk_buff *skb;
 
-	/* propogate the error condition to the can stack */
+	/* propagate the error condition to the can stack */
 	skb = alloc_can_err_skb(ndev, &cf);
 	if (!skb) {
 		if (printk_ratelimit())
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/usb/ems_usb.c linux-libre-2.6.39-gnu/drivers/net/can/usb/ems_usb.c
--- linux-libre-2.6.38-gnu/drivers/net/can/usb/ems_usb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/usb/ems_usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -386,7 +386,7 @@
 			break;
 		}
 
-		/* Error occured during transmission? */
+		/* Error occurred during transmission? */
 		if ((ecc & SJA1000_ECC_DIR) == 0)
 			cf->data[2] |= CAN_ERR_PROT_TX;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/can/usb/esd_usb2.c linux-libre-2.6.39-gnu/drivers/net/can/usb/esd_usb2.c
--- linux-libre-2.6.38-gnu/drivers/net/can/usb/esd_usb2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/can/usb/esd_usb2.c	2011-05-19 00:06:34.000000000 -0400
@@ -284,7 +284,7 @@
 				break;
 			}
 
-			/* Error occured during transmission? */
+			/* Error occurred during transmission? */
 			if (!(ecc & SJA1000_ECC_DIR))
 				cf->data[2] |= CAN_ERR_PROT_TX;
 
@@ -659,7 +659,7 @@
 static void unlink_all_urbs(struct esd_usb2 *dev)
 {
 	struct esd_usb2_net_priv *priv;
-	int i;
+	int i, j;
 
 	usb_kill_anchored_urbs(&dev->rx_submitted);
 	for (i = 0; i < dev->net_count; i++) {
@@ -668,8 +668,8 @@
 			usb_kill_anchored_urbs(&priv->tx_submitted);
 			atomic_set(&priv->active_tx_jobs, 0);
 
-			for (i = 0; i < MAX_TX_URBS; i++)
-				priv->tx_contexts[i].echo_index = MAX_TX_URBS;
+			for (j = 0; j < MAX_TX_URBS; j++)
+				priv->tx_contexts[j].echo_index = MAX_TX_URBS;
 		}
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/cassini.c linux-libre-2.6.39-gnu/drivers/net/cassini.c
--- linux-libre-2.6.38-gnu/drivers/net/cassini.c	2012-03-24 01:07:20.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cassini.c	2012-03-24 03:30:32.000000000 -0400
@@ -51,7 +51,7 @@
  * TX has 4 queues. currently these queues are used in a round-robin
  * fashion for load balancing. They can also be used for QoS. for that
  * to work, however, QoS information needs to be exposed down to the driver
- * level so that subqueues get targetted to particular transmit rings.
+ * level so that subqueues get targeted to particular transmit rings.
  * alternatively, the queues can be configured via use of the all-purpose
  * ioctl.
  *
@@ -5165,7 +5165,7 @@
 	pci_release_regions(pdev);
 
 err_write_cacheline:
-	/* Try to restore it in case the error occured after we
+	/* Try to restore it in case the error occurred after we
 	 * set it.
 	 */
 	pci_write_config_byte(pdev, PCI_CACHE_LINE_SIZE, orig_cacheline_size);
diff -druN linux-libre-2.6.38-gnu/drivers/net/cassini.h linux-libre-2.6.39-gnu/drivers/net/cassini.h
--- linux-libre-2.6.38-gnu/drivers/net/cassini.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cassini.h	2011-05-19 00:06:34.000000000 -0400
@@ -772,7 +772,7 @@
 #define    RX_DEBUG_INTR_WRITE_PTR_MASK    0xC0000000 /* interrupt write pointer
 							 of the interrupt queue */
 
-/* flow control frames are emmitted using two PAUSE thresholds:
+/* flow control frames are emitted using two PAUSE thresholds:
  * XOFF PAUSE uses pause time value pre-programmed in the Send PAUSE MAC reg
  * XON PAUSE uses a pause time of 0. granularity of threshold is 64bytes.
  * PAUSE thresholds defined in terms of FIFO occupancy and may be translated
diff -druN linux-libre-2.6.38-gnu/drivers/net/chelsio/mv88e1xxx.c linux-libre-2.6.39-gnu/drivers/net/chelsio/mv88e1xxx.c
--- linux-libre-2.6.38-gnu/drivers/net/chelsio/mv88e1xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/chelsio/mv88e1xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
  *
  * PARAMS: cphy     - Pointer to PHY instance data.
  *
- * RETURN:  0 - Successfull reset.
+ * RETURN:  0 - Successful reset.
  *         -1 - Timeout.
  */
 static int mv88e1xxx_reset(struct cphy *cphy, int wait)
diff -druN linux-libre-2.6.38-gnu/drivers/net/chelsio/pm3393.c linux-libre-2.6.39-gnu/drivers/net/chelsio/pm3393.c
--- linux-libre-2.6.38-gnu/drivers/net/chelsio/pm3393.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/chelsio/pm3393.c	2011-05-19 00:06:34.000000000 -0400
@@ -293,7 +293,7 @@
 	pm3393_enable(cmac, which);
 
 	/*
-	 * XXX This should be done by the PHY and preferrably not at all.
+	 * XXX This should be done by the PHY and preferably not at all.
 	 * The PHY doesn't give us link status indication on its own so have
 	 * the link management code query it instead.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/chelsio/sge.c linux-libre-2.6.39-gnu/drivers/net/chelsio/sge.c
--- linux-libre-2.6.38-gnu/drivers/net/chelsio/sge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/chelsio/sge.c	2011-05-19 00:06:34.000000000 -0400
@@ -1662,7 +1662,7 @@
  * The code figures out how many entries the sk_buff will require in the
  * cmdQ and updates the cmdQ data structure with the state once the enqueue
  * has complete. Then, it doesn't access the global structure anymore, but
- * uses the corresponding fields on the stack. In conjuction with a spinlock
+ * uses the corresponding fields on the stack. In conjunction with a spinlock
  * around that code, we can make the function reentrant without holding the
  * lock when we actually enqueue (which might be expensive, especially on
  * architectures with IO MMUs).
diff -druN linux-libre-2.6.38-gnu/drivers/net/chelsio/vsc7326.c linux-libre-2.6.39-gnu/drivers/net/chelsio/vsc7326.c
--- linux-libre-2.6.38-gnu/drivers/net/chelsio/vsc7326.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/chelsio/vsc7326.c	2011-05-19 00:06:34.000000000 -0400
@@ -566,7 +566,7 @@
 	for (i = 0; i <= 0x3a; ++i)
 		vsc_write(mac->adapter, CRA(4, port, i), 0);
 
-	/* Clear sofware counters */
+	/* Clear software counters */
 	memset(&mac->stats, 0, sizeof(struct cmac_statistics));
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/cnic.c linux-libre-2.6.39-gnu/drivers/net/cnic.c
--- linux-libre-2.6.38-gnu/drivers/net/cnic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cnic.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,14 @@
 static DEFINE_RWLOCK(cnic_dev_lock);
 static DEFINE_MUTEX(cnic_lock);
 
-static struct cnic_ulp_ops *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE];
+static struct cnic_ulp_ops __rcu *cnic_ulp_tbl[MAX_CNIC_ULP_TYPE];
+
+/* helper function, assuming cnic_lock is held */
+static inline struct cnic_ulp_ops *cnic_ulp_tbl_prot(int type)
+{
+	return rcu_dereference_protected(cnic_ulp_tbl[type],
+					 lockdep_is_held(&cnic_lock));
+}
 
 static int cnic_service_bnx2(void *, void *);
 static int cnic_service_bnx2x(void *, void *);
@@ -435,7 +442,7 @@
 		return -EINVAL;
 	}
 	mutex_lock(&cnic_lock);
-	if (cnic_ulp_tbl[ulp_type]) {
+	if (cnic_ulp_tbl_prot(ulp_type)) {
 		pr_err("%s: Type %d has already been registered\n",
 		       __func__, ulp_type);
 		mutex_unlock(&cnic_lock);
@@ -478,7 +485,7 @@
 		return -EINVAL;
 	}
 	mutex_lock(&cnic_lock);
-	ulp_ops = cnic_ulp_tbl[ulp_type];
+	ulp_ops = cnic_ulp_tbl_prot(ulp_type);
 	if (!ulp_ops) {
 		pr_err("%s: Type %d has not been registered\n",
 		       __func__, ulp_type);
@@ -529,7 +536,7 @@
 		return -EINVAL;
 	}
 	mutex_lock(&cnic_lock);
-	if (cnic_ulp_tbl[ulp_type] == NULL) {
+	if (cnic_ulp_tbl_prot(ulp_type) == NULL) {
 		pr_err("%s: Driver with type %d has not been registered\n",
 		       __func__, ulp_type);
 		mutex_unlock(&cnic_lock);
@@ -544,7 +551,7 @@
 
 	clear_bit(ULP_F_START, &cp->ulp_flags[ulp_type]);
 	cp->ulp_handle[ulp_type] = ulp_ctx;
-	ulp_ops = cnic_ulp_tbl[ulp_type];
+	ulp_ops = cnic_ulp_tbl_prot(ulp_type);
 	rcu_assign_pointer(cp->ulp_ops[ulp_type], ulp_ops);
 	cnic_hold(dev);
 
@@ -2970,7 +2977,8 @@
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cp->ulp_ops[if_type];
+		ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
+						    lockdep_is_held(&cnic_lock));
 		if (!ulp_ops) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -2994,7 +3002,8 @@
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cp->ulp_ops[if_type];
+		ulp_ops = rcu_dereference_protected(cp->ulp_ops[if_type],
+						    lockdep_is_held(&cnic_lock));
 		if (!ulp_ops || !ulp_ops->cnic_start) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -3058,7 +3067,7 @@
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cnic_ulp_tbl[i];
+		ulp_ops = cnic_ulp_tbl_prot(i);
 		if (!ulp_ops || !ulp_ops->cnic_init) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -3082,7 +3091,7 @@
 		struct cnic_ulp_ops *ulp_ops;
 
 		mutex_lock(&cnic_lock);
-		ulp_ops = cnic_ulp_tbl[i];
+		ulp_ops = cnic_ulp_tbl_prot(i);
 		if (!ulp_ops || !ulp_ops->cnic_exit) {
 			mutex_unlock(&cnic_lock);
 			continue;
@@ -3398,17 +3407,14 @@
 			     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)
+	rt = ip_route_output(&init_net, dst_addr->sin_addr.s_addr, 0, 0, 0);
+	if (!IS_ERR(rt)) {
 		*dst = &rt->dst;
-	return err;
+		return 0;
+	}
+	return PTR_ERR(rt);
 #else
 	return -ENETUNREACH;
 #endif
@@ -3418,14 +3424,14 @@
 			     struct dst_entry **dst)
 {
 #if defined(CONFIG_IPV6) || (defined(CONFIG_IPV6_MODULE) && defined(MODULE))
-	struct flowi fl;
+	struct flowi6 fl6;
 
-	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;
+	memset(&fl6, 0, sizeof(fl6));
+	ipv6_addr_copy(&fl6.daddr, &dst_addr->sin6_addr);
+	if (ipv6_addr_type(&fl6.daddr) & IPV6_ADDR_LINKLOCAL)
+		fl6.flowi6_oif = dst_addr->sin6_scope_id;
 
-	*dst = ip6_route_output(&init_net, NULL, &fl);
+	*dst = ip6_route_output(&init_net, NULL, &fl6);
 	if (*dst)
 		return 0;
 #endif
@@ -4187,6 +4193,14 @@
 		BNX2_PCICFG_INT_ACK_CMD_INDEX_VALID | cp->last_status_idx);
 }
 
+static void cnic_get_bnx2_iscsi_info(struct cnic_dev *dev)
+{
+	u32 max_conn;
+
+	max_conn = cnic_reg_rd_ind(dev, BNX2_FW_MAX_ISCSI_CONN);
+	dev->max_iscsi_conn = max_conn;
+}
+
 static void cnic_disable_bnx2_int_sync(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -4511,6 +4525,8 @@
 		return err;
 	}
 
+	cnic_get_bnx2_iscsi_info(dev);
+
 	return 0;
 }
 
@@ -4722,129 +4738,6 @@
 	cp->rx_cons = *cp->rx_cons_ptr;
 }
 
-static int cnic_read_bnx2x_iscsi_mac(struct cnic_dev *dev, u32 upper_addr,
-				     u32 lower_addr)
-{
-	u32 val;
-	u8 mac[6];
-
-	val = CNIC_RD(dev, upper_addr);
-
-	mac[0] = (u8) (val >> 8);
-	mac[1] = (u8) val;
-
-	val = CNIC_RD(dev, lower_addr);
-
-	mac[2] = (u8) (val >> 24);
-	mac[3] = (u8) (val >> 16);
-	mac[4] = (u8) (val >> 8);
-	mac[5] = (u8) val;
-
-	if (is_valid_ether_addr(mac)) {
-		memcpy(dev->mac_addr, mac, 6);
-		return 0;
-	} else {
-		return -EINVAL;
-	}
-}
-
-static void cnic_get_bnx2x_iscsi_info(struct cnic_dev *dev)
-{
-	struct cnic_local *cp = dev->cnic_priv;
-	u32 base, base2, addr, addr1, val;
-	int port = CNIC_PORT(cp);
-
-	dev->max_iscsi_conn = 0;
-	base = CNIC_RD(dev, MISC_REG_SHARED_MEM_ADDR);
-	if (base == 0)
-		return;
-
-	base2 = CNIC_RD(dev, (CNIC_PATH(cp) ? MISC_REG_GENERIC_CR_1 :
-					      MISC_REG_GENERIC_CR_0));
-	addr = BNX2X_SHMEM_ADDR(base,
-		dev_info.port_hw_config[port].iscsi_mac_upper);
-
-	addr1 = BNX2X_SHMEM_ADDR(base,
-		dev_info.port_hw_config[port].iscsi_mac_lower);
-
-	cnic_read_bnx2x_iscsi_mac(dev, addr, addr1);
-
-	addr = BNX2X_SHMEM_ADDR(base, validity_map[port]);
-	val = CNIC_RD(dev, addr);
-
-	if (!(val & SHR_MEM_VALIDITY_LIC_NO_KEY_IN_EFFECT)) {
-		u16 val16;
-
-		addr = BNX2X_SHMEM_ADDR(base,
-				drv_lic_key[port].max_iscsi_init_conn);
-		val16 = CNIC_RD16(dev, addr);
-
-		if (val16)
-			val16 ^= 0x1e1e;
-		dev->max_iscsi_conn = val16;
-	}
-
-	if (BNX2X_CHIP_IS_E2(cp->chip_id))
-		dev->max_fcoe_conn = BNX2X_FCOE_NUM_CONNECTIONS;
-
-	if (BNX2X_CHIP_IS_E1H(cp->chip_id) || BNX2X_CHIP_IS_E2(cp->chip_id)) {
-		int func = CNIC_FUNC(cp);
-		u32 mf_cfg_addr;
-
-		if (BNX2X_SHMEM2_HAS(base2, mf_cfg_addr))
-			mf_cfg_addr = CNIC_RD(dev, BNX2X_SHMEM2_ADDR(base2,
-					      mf_cfg_addr));
-		else
-			mf_cfg_addr = base + BNX2X_SHMEM_MF_BLK_OFFSET;
-
-		if (BNX2X_CHIP_IS_E2(cp->chip_id)) {
-			/* Must determine if the MF is SD vs SI mode */
-			addr = BNX2X_SHMEM_ADDR(base,
-					dev_info.shared_feature_config.config);
-			val = CNIC_RD(dev, addr);
-			if ((val & SHARED_FEAT_CFG_FORCE_SF_MODE_MASK) ==
-			    SHARED_FEAT_CFG_FORCE_SF_MODE_SWITCH_INDEPT) {
-				int rc;
-
-				/* MULTI_FUNCTION_SI mode */
-				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-					func_ext_config[func].func_cfg);
-				val = CNIC_RD(dev, addr);
-				if (!(val & MACP_FUNC_CFG_FLAGS_ISCSI_OFFLOAD))
-					dev->max_iscsi_conn = 0;
-
-				if (!(val & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD))
-					dev->max_fcoe_conn = 0;
-
-				addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-					func_ext_config[func].
-					iscsi_mac_addr_upper);
-				addr1 = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-					func_ext_config[func].
-					iscsi_mac_addr_lower);
-				rc = cnic_read_bnx2x_iscsi_mac(dev, addr,
-								addr1);
-				if (rc && func > 1)
-					dev->max_iscsi_conn = 0;
-
-				return;
-			}
-		}
-
-		addr = BNX2X_MF_CFG_ADDR(mf_cfg_addr,
-			func_mf_config[func].e1hov_tag);
-
-		val = CNIC_RD(dev, addr);
-		val &= FUNC_MF_CFG_E1HOV_TAG_MASK;
-		if (val != FUNC_MF_CFG_E1HOV_TAG_DEFAULT) {
-			dev->max_fcoe_conn = 0;
-			dev->max_iscsi_conn = 0;
-		}
-	}
-	if (!is_valid_ether_addr(dev->mac_addr))
-		dev->max_iscsi_conn = 0;
-}
-
 static void cnic_init_bnx2x_kcq(struct cnic_dev *dev)
 {
 	struct cnic_local *cp = dev->cnic_priv;
@@ -4926,8 +4819,6 @@
 
 	cnic_init_bnx2x_kcq(dev);
 
-	cnic_get_bnx2x_iscsi_info(dev);
-
 	/* Only 1 EQ */
 	CNIC_WR16(dev, cp->kcq1.io_addr, MAX_KCQ_IDX);
 	CNIC_WR(dev, BAR_CSTRORM_INTMEM +
@@ -5281,15 +5172,11 @@
 
 	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;
-		}
+	if ((pdev->device == PCI_DEVICE_ID_NX2_5709 ||
+	     pdev->device == PCI_DEVICE_ID_NX2_5709S) &&
+	    (pdev->revision < 0x10)) {
+		pci_dev_put(pdev);
+		goto cnic_err;
 	}
 	pci_dev_put(pdev);
 
@@ -5360,6 +5247,14 @@
 	cdev->pcidev = pdev;
 	cp->chip_id = ethdev->chip_id;
 
+	if (!(ethdev->drv_state & CNIC_DRV_STATE_NO_ISCSI))
+		cdev->max_iscsi_conn = ethdev->max_iscsi_conn;
+	if (BNX2X_CHIP_IS_E2(cp->chip_id) &&
+	    !(ethdev->drv_state & CNIC_DRV_STATE_NO_FCOE))
+		cdev->max_fcoe_conn = ethdev->max_fcoe_conn;
+
+	memcpy(cdev->mac_addr, ethdev->iscsi_mac, 6);
+
 	cp->cnic_ops = &cnic_bnx2x_ops;
 	cp->start_hw = cnic_start_bnx2x_hw;
 	cp->stop_hw = cnic_stop_bnx2x_hw;
diff -druN linux-libre-2.6.38-gnu/drivers/net/cnic.h linux-libre-2.6.39-gnu/drivers/net/cnic.h
--- linux-libre-2.6.38-gnu/drivers/net/cnic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cnic.h	2011-05-19 00:06:34.000000000 -0400
@@ -220,7 +220,7 @@
 #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];
+	struct cnic_ulp_ops __rcu *ulp_ops[MAX_CNIC_ULP_TYPE];
 
 	unsigned long cnic_local_flags;
 #define	CNIC_LCL_FL_KWQ_INIT		0x0
diff -druN linux-libre-2.6.38-gnu/drivers/net/cnic_if.h linux-libre-2.6.39-gnu/drivers/net/cnic_if.h
--- linux-libre-2.6.38-gnu/drivers/net/cnic_if.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cnic_if.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,8 +12,8 @@
 #ifndef CNIC_IF_H
 #define CNIC_IF_H
 
-#define CNIC_MODULE_VERSION	"2.2.12"
-#define CNIC_MODULE_RELDATE	"Jan 03, 2011"
+#define CNIC_MODULE_VERSION	"2.2.13"
+#define CNIC_MODULE_RELDATE	"Jan 31, 2011"
 
 #define CNIC_ULP_RDMA		0
 #define CNIC_ULP_ISCSI		1
@@ -159,6 +159,9 @@
 	u32		drv_state;
 #define CNIC_DRV_STATE_REGD		0x00000001
 #define CNIC_DRV_STATE_USING_MSIX	0x00000002
+#define CNIC_DRV_STATE_NO_ISCSI_OOO	0x00000004
+#define CNIC_DRV_STATE_NO_ISCSI		0x00000008
+#define CNIC_DRV_STATE_NO_FCOE		0x00000010
 	u32		chip_id;
 	u32		max_kwqe_pending;
 	struct pci_dev	*pdev;
@@ -176,6 +179,7 @@
 	u32		fcoe_init_cid;
 	u16		iscsi_l2_client_id;
 	u16		iscsi_l2_cid;
+	u8		iscsi_mac[ETH_ALEN];
 
 	int		num_irq;
 	struct cnic_irq	irq_arr[MAX_CNIC_VEC];
diff -druN linux-libre-2.6.38-gnu/drivers/net/cris/eth_v10.c linux-libre-2.6.39-gnu/drivers/net/cris/eth_v10.c
--- linux-libre-2.6.38-gnu/drivers/net/cris/eth_v10.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cris/eth_v10.c	2011-05-19 00:06:34.000000000 -0400
@@ -1383,7 +1383,7 @@
 	spin_lock(&np->lock); /* Preempt protection */
 	switch (cmd) {
 		/* The ioctls below should be considered obsolete but are */
-		/* still present for compatability with old scripts/apps  */
+		/* still present for compatibility with old scripts/apps  */
 		case SET_ETH_SPEED_10:                  /* 10 Mbps */
 			e100_set_speed(dev, 10);
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/net/cs89x0.c linux-libre-2.6.39-gnu/drivers/net/cs89x0.c
--- linux-libre-2.6.38-gnu/drivers/net/cs89x0.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cs89x0.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,6 +95,9 @@
   Dmitry Pervushin  : dpervushin@ru.mvista.com
                     : PNX010X platform support
 
+  Domenico Andreoli : cavokz@gmail.com
+                    : QQ2440 platform support
+
 */
 
 /* Always include 'config.h' first in case the user wants to turn on
@@ -176,6 +179,10 @@
 #elif defined(CONFIG_ARCH_IXDP2X01)
 static unsigned int netcard_portlist[] __used __initdata = {IXDP2X01_CS8900_VIRT_BASE, 0};
 static unsigned int cs8900_irq_map[] = {IRQ_IXDP2X01_CS8900, 0, 0, 0};
+#elif defined(CONFIG_MACH_QQ2440)
+#include <mach/qq2440.h>
+static unsigned int netcard_portlist[] __used __initdata = { QQ2440_CS8900_VIRT_BASE + 0x300, 0 };
+static unsigned int cs8900_irq_map[] = { QQ2440_CS8900_IRQ, 0, 0, 0 };
 #elif defined(CONFIG_MACH_MX31ADS)
 #include <mach/board-mx31ads.h>
 static unsigned int netcard_portlist[] __used __initdata = {
@@ -521,6 +528,10 @@
 #endif
 		lp->force = g_cs89x0_media__force;
 #endif
+
+#if defined(CONFIG_MACH_QQ2440)
+		lp->force |= FORCE_RJ45 | FORCE_FULL;
+#endif
         }
 
 	/* Grab the region so we can find another board if autoIRQ fails. */
@@ -943,10 +954,10 @@
 static void __init reset_chip(struct net_device *dev)
 {
 #if !defined(CONFIG_MACH_MX31ADS)
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
+#if !defined(CS89x0_NONISA_IRQ)
 	struct net_local *lp = netdev_priv(dev);
 	int ioaddr = dev->base_addr;
-#endif
+#endif /* CS89x0_NONISA_IRQ */
 	int reset_start_time;
 
 	writereg(dev, PP_SelfCTL, readreg(dev, PP_SelfCTL) | POWER_ON_RESET);
@@ -954,7 +965,7 @@
 	/* wait 30 ms */
 	msleep(30);
 
-#if !defined(CONFIG_MACH_IXDP2351) && !defined(CONFIG_ARCH_IXDP2X01)
+#if !defined(CS89x0_NONISA_IRQ)
 	if (lp->chip_type != CS8900) {
 		/* Hardware problem requires PNP registers to be reconfigured after a reset */
 		writeword(ioaddr, ADD_PORT, PP_CS8920_ISAINT);
@@ -965,7 +976,7 @@
 		outb((dev->mem_start >> 16) & 0xff, ioaddr + DATA_PORT);
 		outb((dev->mem_start >> 8) & 0xff,   ioaddr + DATA_PORT + 1);
 	}
-#endif	/* IXDP2x01 */
+#endif /* CS89x0_NONISA_IRQ */
 
 	/* Wait until the chip is reset */
 	reset_start_time = jiffies;
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb3/cxgb3_main.c linux-libre-2.6.39-gnu/drivers/net/cxgb3/cxgb3_main.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb3/cxgb3_main.c	2012-03-24 01:07:26.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb3/cxgb3_main.c	2012-03-24 03:30:36.000000000 -0400
@@ -1976,14 +1976,20 @@
 {
 	struct port_info *pi = netdev_priv(dev);
 	struct adapter *adapter = pi->adapter;
-	struct qset_params *qsp = &adapter->params.sge.qset[0];
-	struct sge_qset *qs = &adapter->sge.qs[0];
+	struct qset_params *qsp;
+	struct sge_qset *qs;
+	int i;
 
 	if (c->rx_coalesce_usecs * 10 > M_NEWTIMER)
 		return -EINVAL;
 
-	qsp->coalesce_usecs = c->rx_coalesce_usecs;
-	t3_update_qset_coalesce(qs, qsp);
+	for (i = 0; i < pi->nqsets; i++) {
+		qsp = &adapter->params.sge.qset[i];
+		qs = &adapter->sge.qs[i];
+		qsp->coalesce_usecs = c->rx_coalesce_usecs;
+		t3_update_qset_coalesce(qs, qsp);
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb3/cxgb3_offload.c linux-libre-2.6.39-gnu/drivers/net/cxgb3/cxgb3_offload.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb3/cxgb3_offload.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb3/cxgb3_offload.c	2011-05-19 00:06:34.000000000 -0400
@@ -186,9 +186,10 @@
 				dev = NULL;
 				if (grp)
 					dev = vlan_group_get_device(grp, vlan);
-			} else
+			} else if (netif_is_bond_slave(dev)) {
 				while (dev->master)
 					dev = dev->master;
+			}
 			return dev;
 		}
 	}
@@ -967,8 +968,6 @@
 		cxgb_neigh_update((struct neighbour *)ctx);
 		break;
 	}
-	case (NETEVENT_PMTU_UPDATE):
-		break;
 	case (NETEVENT_REDIRECT):{
 		struct netevent_redirect *nr = ctx;
 		cxgb_redirect(nr->old, nr->new);
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb3/sge.c linux-libre-2.6.39-gnu/drivers/net/cxgb3/sge.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb3/sge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb3/sge.c	2011-05-19 00:06:34.000000000 -0400
@@ -199,7 +199,7 @@
  *	need_skb_unmap - does the platform need unmapping of sk_buffs?
  *
  *	Returns true if the platform needs sk_buff unmapping.  The compiler
- *	optimizes away unecessary code if this returns true.
+ *	optimizes away unnecessary code if this returns true.
  */
 static inline int need_skb_unmap(void)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb3/t3_hw.c linux-libre-2.6.39-gnu/drivers/net/cxgb3/t3_hw.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb3/t3_hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb3/t3_hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -1386,11 +1386,11 @@
  *	@reg: the interrupt status register to process
  *	@mask: a mask to apply to the interrupt status
  *	@acts: table of interrupt actions
- *	@stats: statistics counters tracking interrupt occurences
+ *	@stats: statistics counters tracking interrupt occurrences
  *
  *	A table driven interrupt handler that applies a set of masks to an
  *	interrupt status word and performs the corresponding actions if the
- *	interrupts described by the mask have occured.  The actions include
+ *	interrupts described by the mask have occurred.  The actions include
  *	optionally printing a warning or alert message, and optionally
  *	incrementing a stat counter.  The table is terminated by an entry
  *	specifying mask 0.  Returns the number of fatal interrupt conditions.
@@ -2783,7 +2783,7 @@
 {
 	/*
 	 * See draft-mathis-plpmtud-00.txt for the values.  The min is 88 so
-	 * it can accomodate max size TCP/IP headers when SACK and timestamps
+	 * it can accommodate max size TCP/IP headers when SACK and timestamps
 	 * are enabled and still have at least 8 bytes of payload.
 	 */
 	mtus[0] = 88;
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb4/cxgb4_main.c linux-libre-2.6.39-gnu/drivers/net/cxgb4/cxgb4_main.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb4/cxgb4_main.c	2012-03-24 01:07:33.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb4/cxgb4_main.c	2012-03-24 03:30:39.000000000 -0400
@@ -2471,7 +2471,6 @@
 	case NETEVENT_NEIGH_UPDATE:
 		check_neigh_update(data);
 		break;
-	case NETEVENT_PMTU_UPDATE:
 	case NETEVENT_REDIRECT:
 	default:
 		break;
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb4/t4_hw.c linux-libre-2.6.39-gnu/drivers/net/cxgb4/t4_hw.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb4/t4_hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb4/t4_hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -883,7 +883,7 @@
  *
  *	A table driven interrupt handler that applies a set of masks to an
  *	interrupt status word and performs the corresponding actions if the
- *	interrupts described by the mask have occured.  The actions include
+ *	interrupts described by the mask have occurred.  The actions include
  *	optionally emitting a warning or alert message.  The table is terminated
  *	by an entry specifying mask 0.  Returns the number of fatal interrupt
  *	conditions.
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb4/t4_msg.h linux-libre-2.6.39-gnu/drivers/net/cxgb4/t4_msg.h
--- linux-libre-2.6.38-gnu/drivers/net/cxgb4/t4_msg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb4/t4_msg.h	2011-05-19 00:06:34.000000000 -0400
@@ -123,6 +123,7 @@
 	ULP_MODE_NONE          = 0,
 	ULP_MODE_ISCSI         = 2,
 	ULP_MODE_RDMA          = 4,
+	ULP_MODE_TCPDDP	       = 5,
 	ULP_MODE_FCOE          = 6,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c linux-libre-2.6.39-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb4vf/cxgb4vf_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -2738,7 +2738,7 @@
 	cfg_queues(adapter);
 
 	/*
-	 * Print a short notice on the existance and configuration of the new
+	 * Print a short notice on the existence and configuration of the new
 	 * VF network device ...
 	 */
 	for_each_port(adapter, pidx) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/cxgb4vf/sge.c linux-libre-2.6.39-gnu/drivers/net/cxgb4vf/sge.c
--- linux-libre-2.6.38-gnu/drivers/net/cxgb4vf/sge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/cxgb4vf/sge.c	2011-05-19 00:06:34.000000000 -0400
@@ -224,8 +224,8 @@
 /**
  *	need_skb_unmap - does the platform need unmapping of sk_buffs?
  *
- *	Returns true if the platfrom needs sk_buff unmapping.  The compiler
- *	optimizes away unecessary code if this returns true.
+ *	Returns true if the platform needs sk_buff unmapping.  The compiler
+ *	optimizes away unnecessary code if this returns true.
  */
 static inline int need_skb_unmap(void)
 {
@@ -267,7 +267,7 @@
  *
  *	Tests specified Free List to see whether the number of buffers
  *	available to the hardware has falled below our "starvation"
- *	threshhold.
+ *	threshold.
  */
 static inline bool fl_starving(const struct sge_fl *fl)
 {
@@ -1149,7 +1149,7 @@
 	if (unlikely(credits < ETHTXQ_STOP_THRES)) {
 		/*
 		 * After we're done injecting the Work Request for this
-		 * packet, we'll be below our "stop threshhold" so stop the TX
+		 * packet, we'll be below our "stop threshold" so stop the TX
 		 * Queue now and schedule a request for an SGE Egress Queue
 		 * Update message.  The queue will get started later on when
 		 * the firmware processes this Work Request and sends us an
diff -druN linux-libre-2.6.38-gnu/drivers/net/davinci_cpdma.c linux-libre-2.6.39-gnu/drivers/net/davinci_cpdma.c
--- linux-libre-2.6.38-gnu/drivers/net/davinci_cpdma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/davinci_cpdma.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,6 +76,7 @@
 
 struct cpdma_desc_pool {
 	u32			phys;
+	u32			hw_addr;
 	void __iomem		*iomap;		/* ioremap map */
 	void			*cpumap;	/* dma_alloc map */
 	int			desc_size, mem_size;
@@ -137,7 +138,8 @@
  * abstract out these details
  */
 static struct cpdma_desc_pool *
-cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
+cpdma_desc_pool_create(struct device *dev, u32 phys, u32 hw_addr,
+				int size, int align)
 {
 	int bitmap_size;
 	struct cpdma_desc_pool *pool;
@@ -161,10 +163,12 @@
 	if (phys) {
 		pool->phys  = phys;
 		pool->iomap = ioremap(phys, size);
+		pool->hw_addr = hw_addr;
 	} else {
 		pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
 						  GFP_KERNEL);
 		pool->iomap = (void __force __iomem *)pool->cpumap;
+		pool->hw_addr = pool->phys;
 	}
 
 	if (pool->iomap)
@@ -201,14 +205,14 @@
 {
 	if (!desc)
 		return 0;
-	return pool->phys + (__force dma_addr_t)desc -
+	return pool->hw_addr + (__force dma_addr_t)desc -
 			    (__force dma_addr_t)pool->iomap;
 }
 
 static inline struct cpdma_desc __iomem *
 desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
 {
-	return dma ? pool->iomap + dma - pool->phys : NULL;
+	return dma ? pool->iomap + dma - pool->hw_addr : NULL;
 }
 
 static struct cpdma_desc __iomem *
@@ -260,6 +264,7 @@
 
 	ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
 					    ctlr->params.desc_mem_phys,
+					    ctlr->params.desc_hw_addr,
 					    ctlr->params.desc_mem_size,
 					    ctlr->params.desc_align);
 	if (!ctlr->pool) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/davinci_cpdma.h linux-libre-2.6.39-gnu/drivers/net/davinci_cpdma.h
--- linux-libre-2.6.38-gnu/drivers/net/davinci_cpdma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/davinci_cpdma.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,6 +33,7 @@
 	bool			has_soft_reset;
 	int			min_packet_size;
 	u32			desc_mem_phys;
+	u32			desc_hw_addr;
 	int			desc_mem_size;
 	int			desc_align;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/davinci_emac.c linux-libre-2.6.39-gnu/drivers/net/davinci_emac.c
--- linux-libre-2.6.38-gnu/drivers/net/davinci_emac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/davinci_emac.c	2011-05-19 00:06:34.000000000 -0400
@@ -94,14 +94,14 @@
 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_PASS_CRC		(0) /* Do not pass CRC up to 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_PROM_EN		(0) /* Promiscuous disabled */
+#define EMAC_DEF_PROM_CH		(0) /* Promiscuous 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 */
@@ -1013,7 +1013,7 @@
 		return;
 	}
 
-	/* recycle on recieve error */
+	/* recycle on receive error */
 	if (status < 0) {
 		ndev->stats.rx_errors++;
 		goto recycle;
@@ -1730,7 +1730,7 @@
 		emac_read(EMAC_TXCARRIERSENSE);
 	emac_write(EMAC_TXCARRIERSENSE, stats_clear_mask);
 
-	ndev->stats.tx_fifo_errors = emac_read(EMAC_TXUNDERRUN);
+	ndev->stats.tx_fifo_errors += emac_read(EMAC_TXUNDERRUN);
 	emac_write(EMAC_TXUNDERRUN, stats_clear_mask);
 
 	return &ndev->stats;
@@ -1854,10 +1854,13 @@
 	dma_params.rxcp			= priv->emac_base + 0x660;
 	dma_params.num_chan		= EMAC_MAX_TXRX_CHANNELS;
 	dma_params.min_packet_size	= EMAC_DEF_MIN_ETHPKTSIZE;
-	dma_params.desc_mem_phys	= hw_ram_addr;
+	dma_params.desc_hw_addr		= hw_ram_addr;
 	dma_params.desc_mem_size	= pdata->ctrl_ram_size;
 	dma_params.desc_align		= 16;
 
+	dma_params.desc_mem_phys = pdata->no_bd_ram ? 0 :
+			(u32 __force)res->start + pdata->ctrl_ram_offset;
+
 	priv->dma = cpdma_ctlr_create(&dma_params);
 	if (!priv->dma) {
 		dev_err(emac_dev, "DaVinci EMAC: Error initializing DMA\n");
diff -druN linux-libre-2.6.38-gnu/drivers/net/dm9000.c linux-libre-2.6.39-gnu/drivers/net/dm9000.c
--- linux-libre-2.6.38-gnu/drivers/net/dm9000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/dm9000.c	2011-05-19 00:06:34.000000000 -0400
@@ -621,9 +621,9 @@
 		/* change in wol state, update IRQ state */
 
 		if (!dm->wake_state)
-			set_irq_wake(dm->irq_wake, 1);
+			irq_set_irq_wake(dm->irq_wake, 1);
 		else if (dm->wake_state & !opts)
-			set_irq_wake(dm->irq_wake, 0);
+			irq_set_irq_wake(dm->irq_wake, 0);
 	}
 
 	dm->wake_state = opts;
@@ -1424,13 +1424,13 @@
 		} else {
 
 			/* test to see if irq is really wakeup capable */
-			ret = set_irq_wake(db->irq_wake, 1);
+			ret = irq_set_irq_wake(db->irq_wake, 1);
 			if (ret) {
 				dev_err(db->dev, "irq %d cannot set wakeup (%d)\n",
 					db->irq_wake, ret);
 				ret = 0;
 			} else {
-				set_irq_wake(db->irq_wake, 0);
+				irq_set_irq_wake(db->irq_wake, 0);
 				db->wake_supported = 1;
 			}
 		}
@@ -1593,10 +1593,15 @@
 			ndev->dev_addr[i] = ior(db, i+DM9000_PAR);
 	}
 
-	if (!is_valid_ether_addr(ndev->dev_addr))
+	if (!is_valid_ether_addr(ndev->dev_addr)) {
 		dev_warn(db->dev, "%s: Invalid ethernet MAC address. Please "
 			 "set using ifconfig\n", ndev->name);
 
+		random_ether_addr(ndev->dev_addr);
+		mac_src = "random";
+	}
+
+
 	platform_set_drvdata(pdev, ndev);
 	ret = register_netdev(ndev);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000/e1000_ethtool.c linux-libre-2.6.39-gnu/drivers/net/e1000/e1000_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000/e1000_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000/e1000_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,7 +160,7 @@
 		                                   &adapter->link_duplex);
 		ecmd->speed = adapter->link_speed;
 
-		/* unfortunatly FULL_DUPLEX != DUPLEX_FULL
+		/* unfortunately FULL_DUPLEX != DUPLEX_FULL
 		 *          and HALF_DUPLEX != DUPLEX_HALF */
 
 		if (adapter->link_duplex == FULL_DUPLEX)
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000/e1000_hw.h linux-libre-2.6.39-gnu/drivers/net/e1000/e1000_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/e1000/e1000_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000/e1000_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -1026,7 +1026,7 @@
 
 #define E1000_KUMCTRLSTA 0x00034	/* MAC-PHY interface - RW */
 #define E1000_MDPHYA     0x0003C	/* PHY address - RW */
-#define E1000_MANC2H     0x05860	/* Managment Control To Host - RW */
+#define E1000_MANC2H     0x05860	/* Management Control To Host - RW */
 #define E1000_SW_FW_SYNC 0x05B5C	/* Software-Firmware Synchronization - RW */
 
 #define E1000_GCR       0x05B00	/* PCI-Ex Control */
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000/e1000_main.c linux-libre-2.6.39-gnu/drivers/net/e1000/e1000_main.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000/e1000_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000/e1000_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -205,7 +205,7 @@
 	.probe    = e1000_probe,
 	.remove   = __devexit_p(e1000_remove),
 #ifdef CONFIG_PM
-	/* Power Managment Hooks */
+	/* Power Management Hooks */
 	.suspend  = e1000_suspend,
 	.resume   = e1000_resume,
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/defines.h linux-libre-2.6.39-gnu/drivers/net/e1000e/defines.h
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/defines.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/defines.h	2011-05-19 00:06:34.000000000 -0400
@@ -86,6 +86,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_LSECCK         0x00001000
 #define E1000_CTRL_EXT_PHYPDEN        0x00100000
 
 /* Receive Descriptor bit definitions */
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/e1000.h linux-libre-2.6.39-gnu/drivers/net/e1000e/e1000.h
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/e1000.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/e1000.h	2011-05-19 00:06:34.000000000 -0400
@@ -364,6 +364,7 @@
 	/* structs defined in e1000_hw.h */
 	struct e1000_hw hw;
 
+	spinlock_t stats64_lock;
 	struct e1000_hw_stats stats;
 	struct e1000_phy_info phy_info;
 	struct e1000_phy_stats phy_stats;
@@ -494,7 +495,9 @@
 extern int e1000e_setup_tx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_rx_resources(struct e1000_adapter *adapter);
 extern void e1000e_free_tx_resources(struct e1000_adapter *adapter);
-extern void e1000e_update_stats(struct e1000_adapter *adapter);
+extern struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+                                                    struct rtnl_link_stats64
+                                                    *stats);
 extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter);
 extern void e1000e_get_hw_control(struct e1000_adapter *adapter);
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/ethtool.c linux-libre-2.6.39-gnu/drivers/net/e1000e/ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,15 +46,15 @@
 };
 
 #define E1000_STAT(str, m) { \
-			.stat_string = str, \
-			.type = E1000_STATS, \
-			.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
-			.stat_offset = offsetof(struct e1000_adapter, m) }
+		.stat_string = str, \
+		.type = E1000_STATS, \
+		.sizeof_stat = sizeof(((struct e1000_adapter *)0)->m), \
+		.stat_offset = offsetof(struct e1000_adapter, m) }
 #define E1000_NETDEV_STAT(str, m) { \
-			.stat_string = str, \
-			.type = NETDEV_STATS, \
-			.sizeof_stat = sizeof(((struct net_device *)0)->m), \
-			.stat_offset = offsetof(struct net_device, m) }
+		.stat_string = str, \
+		.type = NETDEV_STATS, \
+		.sizeof_stat = sizeof(((struct rtnl_link_stats64 *)0)->m), \
+		.stat_offset = offsetof(struct rtnl_link_stats64, m) }
 
 static const struct e1000_stats e1000_gstrings_stats[] = {
 	E1000_STAT("rx_packets", stats.gprc),
@@ -65,21 +65,21 @@
 	E1000_STAT("tx_broadcast", stats.bptc),
 	E1000_STAT("rx_multicast", stats.mprc),
 	E1000_STAT("tx_multicast", stats.mptc),
-	E1000_NETDEV_STAT("rx_errors", stats.rx_errors),
-	E1000_NETDEV_STAT("tx_errors", stats.tx_errors),
-	E1000_NETDEV_STAT("tx_dropped", stats.tx_dropped),
+	E1000_NETDEV_STAT("rx_errors", rx_errors),
+	E1000_NETDEV_STAT("tx_errors", tx_errors),
+	E1000_NETDEV_STAT("tx_dropped", tx_dropped),
 	E1000_STAT("multicast", stats.mprc),
 	E1000_STAT("collisions", stats.colc),
-	E1000_NETDEV_STAT("rx_length_errors", stats.rx_length_errors),
-	E1000_NETDEV_STAT("rx_over_errors", stats.rx_over_errors),
+	E1000_NETDEV_STAT("rx_length_errors", rx_length_errors),
+	E1000_NETDEV_STAT("rx_over_errors", rx_over_errors),
 	E1000_STAT("rx_crc_errors", stats.crcerrs),
-	E1000_NETDEV_STAT("rx_frame_errors", stats.rx_frame_errors),
+	E1000_NETDEV_STAT("rx_frame_errors", rx_frame_errors),
 	E1000_STAT("rx_no_buffer_count", stats.rnbc),
 	E1000_STAT("rx_missed_errors", stats.mpc),
 	E1000_STAT("tx_aborted_errors", stats.ecol),
 	E1000_STAT("tx_carrier_errors", stats.tncrs),
-	E1000_NETDEV_STAT("tx_fifo_errors", stats.tx_fifo_errors),
-	E1000_NETDEV_STAT("tx_heartbeat_errors", stats.tx_heartbeat_errors),
+	E1000_NETDEV_STAT("tx_fifo_errors", tx_fifo_errors),
+	E1000_NETDEV_STAT("tx_heartbeat_errors", tx_heartbeat_errors),
 	E1000_STAT("tx_window_errors", stats.latecol),
 	E1000_STAT("tx_abort_late_coll", stats.latecol),
 	E1000_STAT("tx_deferred_ok", stats.dc),
@@ -433,13 +433,11 @@
 	struct e1000_hw *hw = &adapter->hw;
 	u32 *regs_buff = p;
 	u16 phy_data;
-	u8 revision_id;
 
 	memset(p, 0, E1000_REGS_LEN * sizeof(u32));
 
-	pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
-
-	regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
+	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
+			adapter->pdev->device;
 
 	regs_buff[0]  = er32(CTRL);
 	regs_buff[1]  = er32(STATUS);
@@ -684,20 +682,13 @@
 	rx_old = adapter->rx_ring;
 
 	err = -ENOMEM;
-	tx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+	tx_ring = kmemdup(tx_old, sizeof(struct e1000_ring), GFP_KERNEL);
 	if (!tx_ring)
 		goto err_alloc_tx;
-	/*
-	 * use a memcpy to save any previously configured
-	 * items like napi structs from having to be
-	 * reinitialized
-	 */
-	memcpy(tx_ring, tx_old, sizeof(struct e1000_ring));
 
-	rx_ring = kzalloc(sizeof(struct e1000_ring), GFP_KERNEL);
+	rx_ring = kmemdup(rx_old, sizeof(struct e1000_ring), GFP_KERNEL);
 	if (!rx_ring)
 		goto err_alloc_rx;
-	memcpy(rx_ring, rx_old, sizeof(struct e1000_ring));
 
 	adapter->tx_ring = tx_ring;
 	adapter->rx_ring = rx_ring;
@@ -1255,7 +1246,6 @@
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 ctrl_reg = 0;
-	u32 stat_reg = 0;
 	u16 phy_reg = 0;
 	s32 ret_val = 0;
 
@@ -1363,8 +1353,7 @@
 		 * Set the ILOS bit on the fiber Nic if half duplex link is
 		 * detected.
 		 */
-		stat_reg = er32(STATUS);
-		if ((stat_reg & E1000_STATUS_FD) == 0)
+		if ((er32(STATUS) & E1000_STATUS_FD) == 0)
 			ctrl_reg |= (E1000_CTRL_ILOS | E1000_CTRL_SLU);
 	}
 
@@ -1677,10 +1666,13 @@
 	} else {
 		hw->mac.ops.check_for_link(hw);
 		if (hw->mac.autoneg)
-			msleep(4000);
+			/*
+			 * On some Phy/switch combinations, link establishment
+			 * can take a few seconds more than expected.
+			 */
+			msleep(5000);
 
-		if (!(er32(STATUS) &
-		      E1000_STATUS_LU))
+		if (!(er32(STATUS) & E1000_STATUS_LU))
 			*data = 1;
 	}
 	return *data;
@@ -1807,8 +1799,7 @@
 		return;
 
 	wol->supported = WAKE_UCAST | WAKE_MCAST |
-	                 WAKE_BCAST | WAKE_MAGIC |
-	                 WAKE_PHY | WAKE_ARP;
+	    WAKE_BCAST | WAKE_MAGIC | WAKE_PHY;
 
 	/* apply any specific unsupported masks here */
 	if (adapter->flags & FLAG_NO_WAKE_UCAST) {
@@ -1829,19 +1820,16 @@
 		wol->wolopts |= WAKE_MAGIC;
 	if (adapter->wol & E1000_WUFC_LNKC)
 		wol->wolopts |= WAKE_PHY;
-	if (adapter->wol & E1000_WUFC_ARP)
-		wol->wolopts |= WAKE_ARP;
 }
 
-static int e1000_set_wol(struct net_device *netdev,
-			 struct ethtool_wolinfo *wol)
+static int e1000_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
 
 	if (!(adapter->flags & FLAG_HAS_WOL) ||
 	    !device_can_wakeup(&adapter->pdev->dev) ||
 	    (wol->wolopts & ~(WAKE_UCAST | WAKE_MCAST | WAKE_BCAST |
-	                      WAKE_MAGIC | WAKE_PHY | WAKE_ARP)))
+			      WAKE_MAGIC | WAKE_PHY)))
 		return -EOPNOTSUPP;
 
 	/* these settings will always override what we currently have */
@@ -1857,8 +1845,6 @@
 		adapter->wol |= E1000_WUFC_MAG;
 	if (wol->wolopts & WAKE_PHY)
 		adapter->wol |= E1000_WUFC_LNKC;
-	if (wol->wolopts & WAKE_ARP)
-		adapter->wol |= E1000_WUFC_ARP;
 
 	device_set_wakeup_enable(&adapter->pdev->dev, adapter->wol);
 
@@ -1972,8 +1958,15 @@
 static int e1000_nway_reset(struct net_device *netdev)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	if (netif_running(netdev))
-		e1000e_reinit_locked(adapter);
+
+	if (!netif_running(netdev))
+		return -EAGAIN;
+
+	if (!adapter->hw.mac.autoneg)
+		return -EINVAL;
+
+	e1000e_reinit_locked(adapter);
+
 	return 0;
 }
 
@@ -1982,14 +1975,15 @@
 				    u64 *data)
 {
 	struct e1000_adapter *adapter = netdev_priv(netdev);
+	struct rtnl_link_stats64 net_stats;
 	int i;
 	char *p = NULL;
 
-	e1000e_update_stats(adapter);
+	e1000e_get_stats64(netdev, &net_stats);
 	for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
 		switch (e1000_gstrings_stats[i].type) {
 		case NETDEV_STATS:
-			p = (char *) netdev +
+			p = (char *) &net_stats +
 					e1000_gstrings_stats[i].stat_offset;
 			break;
 		case E1000_STATS:
@@ -2014,7 +2008,7 @@
 
 	switch (stringset) {
 	case ETH_SS_TEST:
-		memcpy(data, *e1000_gstrings_test, sizeof(e1000_gstrings_test));
+		memcpy(data, e1000_gstrings_test, sizeof(e1000_gstrings_test));
 		break;
 	case ETH_SS_STATS:
 		for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/hw.h linux-libre-2.6.39-gnu/drivers/net/e1000e/hw.h
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -812,9 +812,8 @@
 
 struct e1000_mac_info {
 	struct e1000_mac_operations ops;
-
-	u8 addr[6];
-	u8 perm_addr[6];
+	u8 addr[ETH_ALEN];
+	u8 perm_addr[ETH_ALEN];
 
 	enum e1000_mac_type type;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/ich8lan.c linux-libre-2.6.39-gnu/drivers/net/e1000e/ich8lan.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/ich8lan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/ich8lan.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,6 +140,11 @@
 #define I82579_LPI_CTRL			PHY_REG(772, 20)
 #define I82579_LPI_CTRL_ENABLE_MASK	0x6000
 
+/* EMI Registers */
+#define I82579_EMI_ADDR         0x10
+#define I82579_EMI_DATA         0x11
+#define I82579_LPI_UPDATE_TIMER 0x4805	/* in 40ns units + 40 ns base value */
+
 /* Strapping Option Register - RO */
 #define E1000_STRAP                     0x0000C
 #define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
@@ -302,9 +307,9 @@
 	 * the interconnect to PCIe mode.
 	 */
 	fwsm = er32(FWSM);
-	if (!(fwsm & E1000_ICH_FWSM_FW_VALID)) {
+	if (!(fwsm & E1000_ICH_FWSM_FW_VALID) && !e1000_check_reset_block(hw)) {
 		ctrl = er32(CTRL);
-		ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
+		ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
 		ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
 		ew32(CTRL, ctrl);
 		udelay(10);
@@ -331,7 +336,7 @@
 		goto out;
 
 	/* Ungate automatic PHY configuration on non-managed 82579 */
-	if ((hw->mac.type == e1000_pch2lan)  &&
+	if ((hw->mac.type == e1000_pch2lan) &&
 	    !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
 		msleep(10);
 		e1000_gate_hw_phy_config_ich8lan(hw, false);
@@ -366,7 +371,7 @@
 	case e1000_phy_82579:
 		phy->ops.check_polarity = e1000_check_polarity_82577;
 		phy->ops.force_speed_duplex =
-			e1000_phy_force_speed_duplex_82577;
+		    e1000_phy_force_speed_duplex_82577;
 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
 		phy->ops.get_info = e1000_get_phy_info_82577;
 		phy->ops.commit = e1000e_phy_sw_reset;
@@ -753,7 +758,13 @@
 	if (rc)
 		return rc;
 
-	if (adapter->hw.phy.type == e1000_phy_ife) {
+	/*
+	 * Disable Jumbo Frame support on parts with Intel 10/100 PHY or
+	 * on parts with MACsec enabled in NVM (reflected in CTRL_EXT).
+	 */
+	if ((adapter->hw.phy.type == e1000_phy_ife) ||
+	    ((adapter->hw.mac.type >= e1000_pch2lan) &&
+	     (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LSECCK)))) {
 		adapter->flags &= ~FLAG_HAS_JUMBO_FRAMES;
 		adapter->max_hw_frame_size = ETH_FRAME_LEN + ETH_FCS_LEN;
 	}
@@ -1723,11 +1734,25 @@
 	/* Configure the LCD with the OEM bits in NVM */
 	ret_val = e1000_oem_bits_config_ich8lan(hw, true);
 
-	/* Ungate automatic PHY configuration on non-managed 82579 */
-	if ((hw->mac.type == e1000_pch2lan) &&
-	    !(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
-		msleep(10);
-		e1000_gate_hw_phy_config_ich8lan(hw, false);
+	if (hw->mac.type == e1000_pch2lan) {
+		/* Ungate automatic PHY configuration on non-managed 82579 */
+		if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
+			msleep(10);
+			e1000_gate_hw_phy_config_ich8lan(hw, false);
+		}
+
+		/* Set EEE LPI Update Timer to 200usec */
+		ret_val = hw->phy.ops.acquire(hw);
+		if (ret_val)
+			goto out;
+		ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
+						       I82579_LPI_UPDATE_TIMER);
+		if (ret_val)
+			goto release;
+		ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA,
+						       0x1387);
+release:
+		hw->phy.ops.release(hw);
 	}
 
 out:
@@ -2104,7 +2129,6 @@
 {
 	union ich8_hws_flash_status hsfsts;
 	s32 ret_val = -E1000_ERR_NVM;
-	s32 i = 0;
 
 	hsfsts.regval = er16flash(ICH_FLASH_HSFSTS);
 
@@ -2140,6 +2164,8 @@
 		ew16flash(ICH_FLASH_HSFSTS, hsfsts.regval);
 		ret_val = 0;
 	} else {
+		s32 i = 0;
+
 		/*
 		 * Otherwise poll for sometime so the current
 		 * cycle has a chance to end before giving up.
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/lib.c linux-libre-2.6.39-gnu/drivers/net/e1000e/lib.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -1978,15 +1978,15 @@
 {
 	struct e1000_nvm_info *nvm = &hw->nvm;
 	u32 eecd = er32(EECD);
-	u16 timeout = 0;
 	u8 spi_stat_reg;
 
 	if (nvm->type == e1000_nvm_eeprom_spi) {
+		u16 timeout = NVM_MAX_RETRY_SPI;
+
 		/* Clear SK and CS */
 		eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
 		ew32(EECD, eecd);
 		udelay(1);
-		timeout = NVM_MAX_RETRY_SPI;
 
 		/*
 		 * Read "Status Register" repeatedly until the LSB is cleared.
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/netdev.c linux-libre-2.6.39-gnu/drivers/net/e1000e/netdev.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/netdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/netdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 
 #define DRV_EXTRAVERSION "-k2"
 
-#define DRV_VERSION "1.2.20" DRV_EXTRAVERSION
+#define DRV_VERSION "1.3.10" DRV_EXTRAVERSION
 char e1000e_driver_name[] = "e1000e";
 const char e1000e_driver_version[] = DRV_VERSION;
 
@@ -900,8 +900,6 @@
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1060,8 +1058,6 @@
 	}
 	adapter->total_tx_bytes += total_tx_bytes;
 	adapter->total_tx_packets += total_tx_packets;
-	netdev->stats.tx_bytes += total_tx_bytes;
-	netdev->stats.tx_packets += total_tx_packets;
 	return count < tx_ring->count;
 }
 
@@ -1248,8 +1244,6 @@
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1328,7 +1322,7 @@
 				/* an error means any chain goes out the window
 				 * too */
 				if (rx_ring->rx_skb_top)
-					dev_kfree_skb(rx_ring->rx_skb_top);
+					dev_kfree_skb_irq(rx_ring->rx_skb_top);
 				rx_ring->rx_skb_top = NULL;
 				goto next_desc;
 		}
@@ -1401,7 +1395,7 @@
 		/* eth type trans needs skb->data to point to something */
 		if (!pskb_may_pull(skb, ETH_HLEN)) {
 			e_err("pskb_may_pull failed.\n");
-			dev_kfree_skb(skb);
+			dev_kfree_skb_irq(skb);
 			goto next_desc;
 		}
 
@@ -1429,8 +1423,6 @@
 
 	adapter->total_rx_bytes += total_rx_bytes;
 	adapter->total_rx_packets += total_rx_packets;
-	netdev->stats.rx_bytes += total_rx_bytes;
-	netdev->stats.rx_packets += total_rx_packets;
 	return cleaned;
 }
 
@@ -1857,7 +1849,9 @@
 	int err = 0, vector = 0;
 
 	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		sprintf(adapter->rx_ring->name, "%s-rx-0", netdev->name);
+		snprintf(adapter->rx_ring->name,
+			 sizeof(adapter->rx_ring->name) - 1,
+			 "%s-rx-0", netdev->name);
 	else
 		memcpy(adapter->rx_ring->name, netdev->name, IFNAMSIZ);
 	err = request_irq(adapter->msix_entries[vector].vector,
@@ -1870,7 +1864,9 @@
 	vector++;
 
 	if (strlen(netdev->name) < (IFNAMSIZ - 5))
-		sprintf(adapter->tx_ring->name, "%s-tx-0", netdev->name);
+		snprintf(adapter->tx_ring->name,
+			 sizeof(adapter->tx_ring->name) - 1,
+			 "%s-tx-0", netdev->name);
 	else
 		memcpy(adapter->tx_ring->name, netdev->name, IFNAMSIZ);
 	err = request_irq(adapter->msix_entries[vector].vector,
@@ -2734,7 +2730,6 @@
 {
 	struct e1000_hw *hw = &adapter->hw;
 	u32 rctl, rfctl;
-	u32 psrctl = 0;
 	u32 pages = 0;
 
 	/* Workaround Si errata on 82579 - configure jumbo frame flow */
@@ -2833,6 +2828,8 @@
 		adapter->rx_ps_pages = 0;
 
 	if (adapter->rx_ps_pages) {
+		u32 psrctl = 0;
+
 		/* Configure extra packet-split registers */
 		rfctl = er32(RFCTL);
 		rfctl |= E1000_RFCTL_EXTEN;
@@ -3034,7 +3031,6 @@
 	struct netdev_hw_addr *ha;
 	u8  *mta_list;
 	u32 rctl;
-	int i;
 
 	/* Check for Promiscuous and All Multicast modes */
 
@@ -3057,12 +3053,13 @@
 	ew32(RCTL, rctl);
 
 	if (!netdev_mc_empty(netdev)) {
+		int i = 0;
+
 		mta_list = kmalloc(netdev_mc_count(netdev) * 6, GFP_ATOMIC);
 		if (!mta_list)
 			return;
 
 		/* prepare a packed array of only addresses. */
-		i = 0;
 		netdev_for_each_mc_addr(ha, netdev)
 			memcpy(mta_list + (i++ * ETH_ALEN), ha->addr, ETH_ALEN);
 
@@ -3359,6 +3356,8 @@
 	e1e_flush();
 }
 
+static void e1000e_update_stats(struct e1000_adapter *adapter);
+
 void e1000e_down(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
@@ -3393,6 +3392,11 @@
 	del_timer_sync(&adapter->phy_info_timer);
 
 	netif_carrier_off(netdev);
+
+	spin_lock(&adapter->stats64_lock);
+	e1000e_update_stats(adapter);
+	spin_unlock(&adapter->stats64_lock);
+
 	adapter->link_speed = 0;
 	adapter->link_duplex = 0;
 
@@ -3437,6 +3441,8 @@
 	adapter->max_frame_size = netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
 	adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
+	spin_lock_init(&adapter->stats64_lock);
+
 	e1000e_set_interrupt_capability(adapter);
 
 	if (e1000_alloc_queues(adapter))
@@ -3918,7 +3924,7 @@
  * e1000e_update_stats - Update the board statistics counters
  * @adapter: board private structure
  **/
-void e1000e_update_stats(struct e1000_adapter *adapter)
+static void e1000e_update_stats(struct e1000_adapter *adapter)
 {
 	struct net_device *netdev = adapter->netdev;
 	struct e1000_hw *hw = &adapter->hw;
@@ -4030,10 +4036,11 @@
 {
 	struct e1000_hw *hw = &adapter->hw;
 	struct e1000_phy_regs *phy = &adapter->phy_regs;
-	int ret_val;
 
 	if ((er32(STATUS) & E1000_STATUS_LU) &&
 	    (adapter->hw.phy.media_type == e1000_media_type_copper)) {
+		int ret_val;
+
 		ret_val  = e1e_rphy(hw, PHY_CONTROL, &phy->bmcr);
 		ret_val |= e1e_rphy(hw, PHY_STATUS, &phy->bmsr);
 		ret_val |= e1e_rphy(hw, PHY_AUTONEG_ADV, &phy->advertise);
@@ -4179,7 +4186,6 @@
 	struct e1000_ring *tx_ring = adapter->tx_ring;
 	struct e1000_hw *hw = &adapter->hw;
 	u32 link, tctl;
-	int tx_pending = 0;
 
 	if (test_bit(__E1000_DOWN, &adapter->state))
 		return;
@@ -4320,7 +4326,9 @@
 	}
 
 link_up:
+	spin_lock(&adapter->stats64_lock);
 	e1000e_update_stats(adapter);
+	spin_unlock(&adapter->stats64_lock);
 
 	mac->tx_packet_delta = adapter->stats.tpt - adapter->tpt_old;
 	adapter->tpt_old = adapter->stats.tpt;
@@ -4334,20 +4342,17 @@
 
 	e1000e_update_adaptive(&adapter->hw);
 
-	if (!netif_carrier_ok(netdev)) {
-		tx_pending = (e1000_desc_unused(tx_ring) + 1 <
-			       tx_ring->count);
-		if (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);
-			/* return immediately since reset is imminent */
-			return;
-		}
+	if (!netif_carrier_ok(netdev) &&
+	    (e1000_desc_unused(tx_ring) + 1 < tx_ring->count)) {
+		/*
+		 * 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);
+		/* return immediately since reset is imminent */
+		return;
 	}
 
 	/* Simple mode for Interrupt Throttle Rate (ITR) */
@@ -4411,13 +4416,13 @@
 	u32 cmd_length = 0;
 	u16 ipcse = 0, tucse, mss;
 	u8 ipcss, ipcso, tucss, tucso, hdr_len;
-	int err;
 
 	if (!skb_is_gso(skb))
 		return 0;
 
 	if (skb_header_cloned(skb)) {
-		err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+		int err = pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
+
 		if (err)
 			return err;
 	}
@@ -4881,7 +4886,7 @@
 	if (skb->protocol == htons(ETH_P_IP))
 		tx_flags |= E1000_TX_FLAGS_IPV4;
 
-	/* if count is 0 then mapping error has occured */
+	/* if count is 0 then mapping error has occurred */
 	count = e1000_tx_map(adapter, skb, first, max_per_txd, nr_frags, mss);
 	if (count) {
 		e1000_tx_queue(adapter, tx_flags, count);
@@ -4928,16 +4933,55 @@
 }
 
 /**
- * e1000_get_stats - Get System Network Statistics
+ * e1000_get_stats64 - Get System Network Statistics
  * @netdev: network interface device structure
+ * @stats: rtnl_link_stats64 pointer
  *
  * Returns the address of the device statistics structure.
- * The statistics are actually updated from the timer callback.
  **/
-static struct net_device_stats *e1000_get_stats(struct net_device *netdev)
+struct rtnl_link_stats64 *e1000e_get_stats64(struct net_device *netdev,
+                                             struct rtnl_link_stats64 *stats)
 {
-	/* only return the current stats */
-	return &netdev->stats;
+	struct e1000_adapter *adapter = netdev_priv(netdev);
+
+	memset(stats, 0, sizeof(struct rtnl_link_stats64));
+	spin_lock(&adapter->stats64_lock);
+	e1000e_update_stats(adapter);
+	/* Fill out the OS statistics structure */
+	stats->rx_bytes = adapter->stats.gorc;
+	stats->rx_packets = adapter->stats.gprc;
+	stats->tx_bytes = adapter->stats.gotc;
+	stats->tx_packets = adapter->stats.gptc;
+	stats->multicast = adapter->stats.mprc;
+	stats->collisions = adapter->stats.colc;
+
+	/* Rx Errors */
+
+	/*
+	 * RLEC on some newer hardware can be incorrect so build
+	 * our own version based on RUC and ROC
+	 */
+	stats->rx_errors = adapter->stats.rxerrc +
+		adapter->stats.crcerrs + adapter->stats.algnerrc +
+		adapter->stats.ruc + adapter->stats.roc +
+		adapter->stats.cexterr;
+	stats->rx_length_errors = adapter->stats.ruc +
+					      adapter->stats.roc;
+	stats->rx_crc_errors = adapter->stats.crcerrs;
+	stats->rx_frame_errors = adapter->stats.algnerrc;
+	stats->rx_missed_errors = adapter->stats.mpc;
+
+	/* Tx Errors */
+	stats->tx_errors = adapter->stats.ecol +
+				       adapter->stats.latecol;
+	stats->tx_aborted_errors = adapter->stats.ecol;
+	stats->tx_window_errors = adapter->stats.latecol;
+	stats->tx_carrier_errors = adapter->stats.tncrs;
+
+	/* Tx Dropped needs to be maintained elsewhere */
+
+	spin_unlock(&adapter->stats64_lock);
+	return stats;
 }
 
 /**
@@ -5338,7 +5382,7 @@
 	__e1000e_disable_aspm(pdev, state);
 }
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 static bool e1000e_pm_ready(struct e1000_adapter *adapter)
 {
 	return !!adapter->tx_ring->buffer_info;
@@ -5489,7 +5533,7 @@
 	return __e1000_resume(pdev);
 }
 #endif /* CONFIG_PM_RUNTIME */
-#endif /* CONFIG_PM_OPS */
+#endif /* CONFIG_PM */
 
 static void e1000_shutdown(struct pci_dev *pdev)
 {
@@ -5507,9 +5551,10 @@
 {
 	struct net_device *netdev = data;
 	struct e1000_adapter *adapter = netdev_priv(netdev);
-	int vector, msix_irq;
 
 	if (adapter->msix_entries) {
+		int vector, msix_irq;
+
 		vector = 0;
 		msix_irq = adapter->msix_entries[vector].vector;
 		disable_irq(msix_irq);
@@ -5706,7 +5751,7 @@
 	.ndo_open		= e1000_open,
 	.ndo_stop		= e1000_close,
 	.ndo_start_xmit		= e1000_xmit_frame,
-	.ndo_get_stats		= e1000_get_stats,
+	.ndo_get_stats64	= e1000e_get_stats64,
 	.ndo_set_multicast_list	= e1000_set_multi,
 	.ndo_set_mac_address	= e1000_set_mac,
 	.ndo_change_mtu		= e1000_change_mtu,
@@ -6196,7 +6241,7 @@
 };
 MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 static const struct dev_pm_ops e1000_pm_ops = {
 	SET_SYSTEM_SLEEP_PM_OPS(e1000_suspend, e1000_resume)
 	SET_RUNTIME_PM_OPS(e1000_runtime_suspend,
@@ -6210,7 +6255,7 @@
 	.id_table = e1000_pci_tbl,
 	.probe    = e1000_probe,
 	.remove   = __devexit_p(e1000_remove),
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 	.driver.pm = &e1000_pm_ops,
 #endif
 	.shutdown = e1000_shutdown,
diff -druN linux-libre-2.6.38-gnu/drivers/net/e1000e/phy.c linux-libre-2.6.39-gnu/drivers/net/e1000e/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/e1000e/phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/e1000e/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -2409,9 +2409,7 @@
 s32 e1000e_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 {
 	s32 ret_val;
-	u32 page_select = 0;
 	u32 page = offset >> IGP_PAGE_SHIFT;
-	u32 page_shift = 0;
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -2427,6 +2425,8 @@
 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+		u32 page_shift, page_select;
+
 		/*
 		 * Page select is register 31 for phy address 1 and 22 for
 		 * phy address 2 and 3. Page select is shifted only for
@@ -2468,9 +2468,7 @@
 s32 e1000e_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 {
 	s32 ret_val;
-	u32 page_select = 0;
 	u32 page = offset >> IGP_PAGE_SHIFT;
-	u32 page_shift = 0;
 
 	ret_val = hw->phy.ops.acquire(hw);
 	if (ret_val)
@@ -2486,6 +2484,8 @@
 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
+		u32 page_shift, page_select;
+
 		/*
 		 * Page select is register 31 for phy address 1 and 22 for
 		 * phy address 2 and 3. Page select is shifted only for
diff -druN linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_ethtool.c linux-libre-2.6.39-gnu/drivers/net/ehea/ehea_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ehea/ehea_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,15 +55,20 @@
 		cmd->duplex = -1;
 	}
 
-	cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_1000baseT_Full
-		       | SUPPORTED_100baseT_Full |  SUPPORTED_100baseT_Half
-		       | SUPPORTED_10baseT_Full | SUPPORTED_10baseT_Half
-		       | SUPPORTED_Autoneg | SUPPORTED_FIBRE);
-
-	cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_Autoneg
-			 | ADVERTISED_FIBRE);
+	if (cmd->speed == SPEED_10000) {
+		cmd->supported = (SUPPORTED_10000baseT_Full | SUPPORTED_FIBRE);
+		cmd->advertising = (ADVERTISED_10000baseT_Full | ADVERTISED_FIBRE);
+		cmd->port = PORT_FIBRE;
+	} else {
+		cmd->supported = (SUPPORTED_1000baseT_Full | SUPPORTED_100baseT_Full
+			       | SUPPORTED_100baseT_Half | SUPPORTED_10baseT_Full
+			       | SUPPORTED_10baseT_Half | SUPPORTED_Autoneg
+			       | SUPPORTED_TP);
+		cmd->advertising = (ADVERTISED_1000baseT_Full | ADVERTISED_Autoneg
+				 | ADVERTISED_TP);
+		cmd->port = PORT_TP;
+	}
 
-	cmd->port = PORT_FIBRE;
 	cmd->autoneg = port->autoneg == 1 ? AUTONEG_ENABLE : AUTONEG_DISABLE;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_main.c linux-libre-2.6.39-gnu/drivers/net/ehea/ehea_main.c
--- linux-libre-2.6.38-gnu/drivers/net/ehea/ehea_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ehea/ehea_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -2688,9 +2688,6 @@
 		netif_start_queue(dev);
 	}
 
-	init_waitqueue_head(&port->swqe_avail_wq);
-	init_waitqueue_head(&port->restart_wq);
-
 	mutex_unlock(&port->port_lock);
 
 	return ret;
@@ -3040,11 +3037,14 @@
 
 					if (dev->flags & IFF_UP) {
 						mutex_lock(&port->port_lock);
-						port_napi_enable(port);
 						ret = ehea_restart_qps(dev);
-						check_sqs(port);
-						if (!ret)
+						if (!ret) {
+							check_sqs(port);
+							port_napi_enable(port);
 							netif_wake_queue(dev);
+						} else {
+							netdev_err(dev, "Unable to restart QPS\n");
+						}
 						mutex_unlock(&port->port_lock);
 					}
 				}
@@ -3273,6 +3273,9 @@
 
 	INIT_WORK(&port->reset_task, ehea_reset_port);
 
+	init_waitqueue_head(&port->swqe_avail_wq);
+	init_waitqueue_head(&port->restart_wq);
+
 	ret = register_netdev(dev);
 	if (ret) {
 		pr_err("register_netdev failed. ret=%d\n", ret);
diff -druN linux-libre-2.6.38-gnu/drivers/net/enc28j60_hw.h linux-libre-2.6.39-gnu/drivers/net/enc28j60_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/enc28j60_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enc28j60_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -303,7 +303,7 @@
 /* maximum ethernet frame length */
 #define MAX_FRAMELEN		1518
 
-/* Prefered half duplex: LEDA: Link status LEDB: Rx/Tx activity */
+/* Preferred half duplex: LEDA: Link status LEDB: Rx/Tx activity */
 #define ENC28J60_LAMPS_MODE	0x3476
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/enic_dev.c linux-libre-2.6.39-gnu/drivers/net/enic/enic_dev.c
--- linux-libre-2.6.38-gnu/drivers/net/enic/enic_dev.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/enic/enic_dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,221 @@
+/*
+ * Copyright 2011 Cisco Systems, Inc.  All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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/pci.h>
+#include <linux/etherdevice.h>
+
+#include "vnic_dev.h"
+#include "vnic_vic.h"
+#include "enic_res.h"
+#include "enic.h"
+#include "enic_dev.h"
+
+int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_fw_info(enic->vdev, fw_info);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_stats_dump(enic->vdev, vstats);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_add_station_addr(struct enic *enic)
+{
+	int err;
+
+	if (!is_valid_ether_addr(enic->netdev->dev_addr))
+		return -EADDRNOTAVAIL;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_del_station_addr(struct enic *enic)
+{
+	int err;
+
+	if (!is_valid_ether_addr(enic->netdev->dev_addr))
+		return -EADDRNOTAVAIL;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_packet_filter(struct enic *enic, int directed, int multicast,
+	int broadcast, int promisc, int allmulti)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_packet_filter(enic->vdev, directed,
+		multicast, broadcast, promisc, allmulti);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_add_addr(struct enic *enic, u8 *addr)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_add_addr(enic->vdev, addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_del_addr(struct enic *enic, u8 *addr)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_del_addr(enic->vdev, addr);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_notify_unset(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_notify_unset(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_hang_notify(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_hang_notify(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
+		IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_enable(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_enable_wait(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_disable(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_disable(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_vnic_dev_deinit(struct enic *enic)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_deinit(enic->vdev);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_init_prov(enic->vdev,
+		(u8 *)vp, vic_provinfo_size(vp));
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+int enic_dev_init_done(struct enic *enic, int *done, int *error)
+{
+	int err;
+
+	spin_lock(&enic->devcmd_lock);
+	err = vnic_dev_init_done(enic->vdev, done, error);
+	spin_unlock(&enic->devcmd_lock);
+
+	return err;
+}
+
+/* rtnl lock is held */
+void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	spin_lock(&enic->devcmd_lock);
+	enic_add_vlan(enic, vid);
+	spin_unlock(&enic->devcmd_lock);
+}
+
+/* rtnl lock is held */
+void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
+{
+	struct enic *enic = netdev_priv(netdev);
+
+	spin_lock(&enic->devcmd_lock);
+	enic_del_vlan(enic, vid);
+	spin_unlock(&enic->devcmd_lock);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/enic_dev.h linux-libre-2.6.39-gnu/drivers/net/enic/enic_dev.h
--- linux-libre-2.6.38-gnu/drivers/net/enic/enic_dev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/enic/enic_dev.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 Cisco Systems, Inc.  All rights reserved.
+ *
+ * This program is free software; you may 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.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _ENIC_DEV_H_
+#define _ENIC_DEV_H_
+
+int enic_dev_fw_info(struct enic *enic, struct vnic_devcmd_fw_info **fw_info);
+int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats);
+int enic_dev_add_station_addr(struct enic *enic);
+int enic_dev_del_station_addr(struct enic *enic);
+int enic_dev_packet_filter(struct enic *enic, int directed, int multicast,
+	int broadcast, int promisc, int allmulti);
+int enic_dev_add_addr(struct enic *enic, u8 *addr);
+int enic_dev_del_addr(struct enic *enic, u8 *addr);
+void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
+void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
+int enic_dev_notify_unset(struct enic *enic);
+int enic_dev_hang_notify(struct enic *enic);
+int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic);
+int enic_dev_enable(struct enic *enic);
+int enic_dev_disable(struct enic *enic);
+int enic_vnic_dev_deinit(struct enic *enic);
+int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp);
+int enic_dev_init_done(struct enic *enic, int *done, int *error);
+
+#endif /* _ENIC_DEV_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/enic.h linux-libre-2.6.39-gnu/drivers/net/enic/enic.h
--- linux-libre-2.6.38-gnu/drivers/net/enic/enic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/enic.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,13 +32,13 @@
 
 #define DRV_NAME		"enic"
 #define DRV_DESCRIPTION		"Cisco VIC Ethernet NIC Driver"
-#define DRV_VERSION		"1.4.1.10"
-#define DRV_COPYRIGHT		"Copyright 2008-2010 Cisco Systems, Inc"
+#define DRV_VERSION		"2.1.1.12"
+#define DRV_COPYRIGHT		"Copyright 2008-2011 Cisco Systems, Inc"
 
 #define ENIC_BARS_MAX		6
 
-#define ENIC_WQ_MAX		8
-#define ENIC_RQ_MAX		8
+#define ENIC_WQ_MAX		1
+#define ENIC_RQ_MAX		1
 #define ENIC_CQ_MAX		(ENIC_WQ_MAX + ENIC_RQ_MAX)
 #define ENIC_INTR_MAX		(ENIC_CQ_MAX + 2)
 
@@ -49,7 +49,7 @@
 	void *devid;
 };
 
-#define ENIC_SET_APPLIED		(1 << 0)
+#define ENIC_PORT_REQUEST_APPLIED	(1 << 0)
 #define ENIC_SET_REQUEST		(1 << 1)
 #define ENIC_SET_NAME			(1 << 2)
 #define ENIC_SET_INSTANCE		(1 << 3)
@@ -101,7 +101,6 @@
 	/* receive queue cache line section */
 	____cacheline_aligned struct vnic_rq rq[ENIC_RQ_MAX];
 	unsigned int rq_count;
-	int (*rq_alloc_buf)(struct vnic_rq *rq);
 	u64 rq_truncated_pkts;
 	u64 rq_bad_fcs;
 	struct napi_struct napi[ENIC_RQ_MAX];
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/enic_main.c linux-libre-2.6.39-gnu/drivers/net/enic/enic_main.c
--- linux-libre-2.6.38-gnu/drivers/net/enic/enic_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/enic_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,6 +44,7 @@
 #include "vnic_vic.h"
 #include "enic_res.h"
 #include "enic.h"
+#include "enic_dev.h"
 
 #define ENIC_NOTIFY_TIMER_PERIOD	(2 * HZ)
 #define WQ_ENET_MAX_DESC_LEN		(1 << WQ_ENET_LEN_BITS)
@@ -190,18 +191,6 @@
 	return 0;
 }
 
-static int enic_dev_fw_info(struct enic *enic,
-	struct vnic_devcmd_fw_info **fw_info)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_fw_info(enic->vdev, fw_info);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_get_drvinfo(struct net_device *netdev,
 	struct ethtool_drvinfo *drvinfo)
 {
@@ -246,17 +235,6 @@
 	}
 }
 
-static int enic_dev_stats_dump(struct enic *enic, struct vnic_stats **vstats)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_stats_dump(enic->vdev, vstats);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_get_ethtool_stats(struct net_device *netdev,
 	struct ethtool_stats *stats, u64 *data)
 {
@@ -896,9 +874,10 @@
 	return net_stats;
 }
 
-static void enic_reset_multicast_list(struct enic *enic)
+static void enic_reset_addr_lists(struct enic *enic)
 {
 	enic->mc_count = 0;
+	enic->uc_count = 0;
 	enic->flags = 0;
 }
 
@@ -919,32 +898,6 @@
 	return 0;
 }
 
-static int enic_dev_add_station_addr(struct enic *enic)
-{
-	int err = 0;
-
-	if (is_valid_ether_addr(enic->netdev->dev_addr)) {
-		spin_lock(&enic->devcmd_lock);
-		err = vnic_dev_add_addr(enic->vdev, enic->netdev->dev_addr);
-		spin_unlock(&enic->devcmd_lock);
-	}
-
-	return err;
-}
-
-static int enic_dev_del_station_addr(struct enic *enic)
-{
-	int err = 0;
-
-	if (is_valid_ether_addr(enic->netdev->dev_addr)) {
-		spin_lock(&enic->devcmd_lock);
-		err = vnic_dev_del_addr(enic->vdev, enic->netdev->dev_addr);
-		spin_unlock(&enic->devcmd_lock);
-	}
-
-	return err;
-}
-
 static int enic_set_mac_address_dynamic(struct net_device *netdev, void *p)
 {
 	struct enic *enic = netdev_priv(netdev);
@@ -989,42 +942,7 @@
 	return enic_dev_add_station_addr(enic);
 }
 
-static int enic_dev_packet_filter(struct enic *enic, int directed,
-	int multicast, int broadcast, int promisc, int allmulti)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_packet_filter(enic->vdev, directed,
-		multicast, broadcast, promisc, allmulti);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_add_addr(struct enic *enic, u8 *addr)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_add_addr(enic->vdev, addr);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_del_addr(struct enic *enic, u8 *addr)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_del_addr(enic->vdev, addr);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static void enic_add_multicast_addr_list(struct enic *enic)
+static void enic_update_multicast_addr_list(struct enic *enic)
 {
 	struct net_device *netdev = enic->netdev;
 	struct netdev_hw_addr *ha;
@@ -1079,7 +997,7 @@
 	enic->mc_count = mc_count;
 }
 
-static void enic_add_unicast_addr_list(struct enic *enic)
+static void enic_update_unicast_addr_list(struct enic *enic)
 {
 	struct net_device *netdev = enic->netdev;
 	struct netdev_hw_addr *ha;
@@ -1156,9 +1074,9 @@
 	}
 
 	if (!promisc) {
-		enic_add_unicast_addr_list(enic);
+		enic_update_unicast_addr_list(enic);
 		if (!allmulti)
-			enic_add_multicast_addr_list(enic);
+			enic_update_multicast_addr_list(enic);
 	}
 }
 
@@ -1170,26 +1088,6 @@
 	enic->vlan_group = vlan_group;
 }
 
-/* rtnl lock is held */
-static void enic_vlan_rx_add_vid(struct net_device *netdev, u16 vid)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	spin_lock(&enic->devcmd_lock);
-	enic_add_vlan(enic, vid);
-	spin_unlock(&enic->devcmd_lock);
-}
-
-/* rtnl lock is held */
-static void enic_vlan_rx_kill_vid(struct net_device *netdev, u16 vid)
-{
-	struct enic *enic = netdev_priv(netdev);
-
-	spin_lock(&enic->devcmd_lock);
-	enic_del_vlan(enic, vid);
-	spin_unlock(&enic->devcmd_lock);
-}
-
 /* netif_tx_lock held, BHs disabled */
 static void enic_tx_timeout(struct net_device *netdev)
 {
@@ -1197,40 +1095,6 @@
 	schedule_work(&enic->reset);
 }
 
-static int enic_vnic_dev_deinit(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_deinit(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_init_prov(struct enic *enic, struct vic_provinfo *vp)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_init_prov(enic->vdev,
-		(u8 *)vp, vic_provinfo_size(vp));
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_init_done(struct enic *enic, int *done, int *error)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_init_done(enic->vdev, done, error);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static int enic_set_vf_mac(struct net_device *netdev, int vf, u8 *mac)
 {
 	struct enic *enic = netdev_priv(netdev);
@@ -1262,6 +1126,8 @@
 	if (err)
 		return err;
 
+	enic_reset_addr_lists(enic);
+
 	switch (enic->pp.request) {
 
 	case PORT_REQUEST_ASSOCIATE:
@@ -1318,18 +1184,20 @@
 		vic_provinfo_free(vp);
 		if (err)
 			return err;
-
-		enic->pp.set |= ENIC_SET_APPLIED;
 		break;
 
 	case PORT_REQUEST_DISASSOCIATE:
-		enic->pp.set &= ~ENIC_SET_APPLIED;
 		break;
 
 	default:
 		return -EINVAL;
 	}
 
+	/* Set flag to indicate that the port assoc/disassoc
+	 * request has been sent out to fw
+	 */
+	enic->pp.set |= ENIC_PORT_REQUEST_APPLIED;
+
 	return 0;
 }
 
@@ -1379,9 +1247,6 @@
 
 		if (is_zero_ether_addr(netdev->dev_addr))
 			random_ether_addr(netdev->dev_addr);
-	} else if (new_pp.request == PORT_REQUEST_DISASSOCIATE) {
-		if (!is_zero_ether_addr(enic->pp.mac_addr))
-			enic_dev_del_addr(enic, enic->pp.mac_addr);
 	}
 
 	memcpy(&enic->pp, &new_pp, sizeof(struct enic_port_profile));
@@ -1390,9 +1255,6 @@
 	if (err)
 		goto set_port_profile_cleanup;
 
-	if (!is_zero_ether_addr(enic->pp.mac_addr))
-		enic_dev_add_addr(enic, enic->pp.mac_addr);
-
 set_port_profile_cleanup:
 	memset(enic->pp.vf_mac, 0, ETH_ALEN);
 
@@ -1411,7 +1273,7 @@
 	int err, error, done;
 	u16 response = PORT_PROFILE_RESPONSE_SUCCESS;
 
-	if (!(enic->pp.set & ENIC_SET_APPLIED))
+	if (!(enic->pp.set & ENIC_PORT_REQUEST_APPLIED))
 		return -ENODATA;
 
 	err = enic_dev_init_done(enic, &done, &error);
@@ -1489,62 +1351,6 @@
 	return 0;
 }
 
-static int enic_rq_alloc_buf_a1(struct vnic_rq *rq)
-{
-	struct rq_enet_desc *desc = vnic_rq_next_desc(rq);
-
-	if (vnic_rq_posting_soon(rq)) {
-
-		/* SW workaround for A0 HW erratum: if we're just about
-		 * to write posted_index, insert a dummy desc
-		 * of type resvd
-		 */
-
-		rq_enet_desc_enc(desc, 0, RQ_ENET_TYPE_RESV2, 0);
-		vnic_rq_post(rq, 0, 0, 0, 0);
-	} else {
-		return enic_rq_alloc_buf(rq);
-	}
-
-	return 0;
-}
-
-static int enic_dev_hw_version(struct enic *enic,
-	enum vnic_dev_hw_version *hw_ver)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_hw_version(enic->vdev, hw_ver);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_set_rq_alloc_buf(struct enic *enic)
-{
-	enum vnic_dev_hw_version hw_ver;
-	int err;
-
-	err = enic_dev_hw_version(enic, &hw_ver);
-	if (err)
-		return err;
-
-	switch (hw_ver) {
-	case VNIC_DEV_HW_VER_A1:
-		enic->rq_alloc_buf = enic_rq_alloc_buf_a1;
-		break;
-	case VNIC_DEV_HW_VER_A2:
-	case VNIC_DEV_HW_VER_UNKNOWN:
-		enic->rq_alloc_buf = enic_rq_alloc_buf;
-		break;
-	default:
-		return -ENODEV;
-	}
-
-	return 0;
-}
-
 static void enic_rq_indicate_buf(struct vnic_rq *rq,
 	struct cq_desc *cq_desc, struct vnic_rq_buf *buf,
 	int skipped, void *opaque)
@@ -1681,7 +1487,7 @@
 			0 /* don't unmask intr */,
 			0 /* don't reset intr timer */);
 
-	err = vnic_rq_fill(&enic->rq[0], enic->rq_alloc_buf);
+	err = vnic_rq_fill(&enic->rq[0], enic_rq_alloc_buf);
 
 	/* Buffer allocation failed. Stay in polling
 	 * mode so we can try to fill the ring again.
@@ -1731,7 +1537,7 @@
 			0 /* don't unmask intr */,
 			0 /* don't reset intr timer */);
 
-	err = vnic_rq_fill(&enic->rq[rq], enic->rq_alloc_buf);
+	err = vnic_rq_fill(&enic->rq[rq], enic_rq_alloc_buf);
 
 	/* Buffer allocation failed. Stay in polling mode
 	 * so we can try to fill the ring again.
@@ -1901,39 +1707,6 @@
 	return err;
 }
 
-static int enic_dev_notify_unset(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_notify_unset(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_enable(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_enable_wait(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_disable(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_disable(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_notify_timer_start(struct enic *enic)
 {
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
@@ -1967,7 +1740,7 @@
 	}
 
 	for (i = 0; i < enic->rq_count; i++) {
-		vnic_rq_fill(&enic->rq[i], enic->rq_alloc_buf);
+		vnic_rq_fill(&enic->rq[i], enic_rq_alloc_buf);
 		/* Need at least one buffer on ring to get going */
 		if (vnic_rq_desc_used(&enic->rq[i]) == 0) {
 			netdev_err(netdev, "Unable to alloc receive buffers\n");
@@ -2285,29 +2058,6 @@
 		rss_hash_bits, rss_base_cpu, rss_enable);
 }
 
-static int enic_dev_hang_notify(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_hang_notify(enic->vdev);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
-static int enic_dev_set_ig_vlan_rewrite_mode(struct enic *enic)
-{
-	int err;
-
-	spin_lock(&enic->devcmd_lock);
-	err = vnic_dev_set_ig_vlan_rewrite_mode(enic->vdev,
-		IG_VLAN_REWRITE_MODE_PRIORITY_TAG_DEFAULT_VLAN);
-	spin_unlock(&enic->devcmd_lock);
-
-	return err;
-}
-
 static void enic_reset(struct work_struct *work)
 {
 	struct enic *enic = container_of(work, struct enic, reset);
@@ -2320,7 +2070,7 @@
 	enic_dev_hang_notify(enic);
 	enic_stop(enic->netdev);
 	enic_dev_hang_reset(enic);
-	enic_reset_multicast_list(enic);
+	enic_reset_addr_lists(enic);
 	enic_init_vnic_resources(enic);
 	enic_set_rss_nic_cfg(enic);
 	enic_dev_set_ig_vlan_rewrite_mode(enic);
@@ -2332,7 +2082,7 @@
 static int enic_set_intr_mode(struct enic *enic)
 {
 	unsigned int n = min_t(unsigned int, enic->rq_count, ENIC_RQ_MAX);
-	unsigned int m = 1;
+	unsigned int m = min_t(unsigned int, enic->wq_count, ENIC_WQ_MAX);
 	unsigned int i;
 
 	/* Set interrupt mode (INTx, MSI, MSI-X) depending
@@ -2475,9 +2225,7 @@
 	.ndo_tx_timeout		= enic_tx_timeout,
 	.ndo_set_vf_port	= enic_set_vf_port,
 	.ndo_get_vf_port	= enic_get_vf_port,
-#ifdef IFLA_VF_MAX
 	.ndo_set_vf_mac		= enic_set_vf_mac,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= enic_poll_controller,
 #endif
@@ -2556,25 +2304,12 @@
 
 	enic_init_vnic_resources(enic);
 
-	err = enic_set_rq_alloc_buf(enic);
-	if (err) {
-		dev_err(dev, "Failed to set RQ buffer allocator, aborting\n");
-		goto err_out_free_vnic_resources;
-	}
-
 	err = enic_set_rss_nic_cfg(enic);
 	if (err) {
 		dev_err(dev, "Failed to config nic, aborting\n");
 		goto err_out_free_vnic_resources;
 	}
 
-	err = enic_dev_set_ig_vlan_rewrite_mode(enic);
-	if (err) {
-		dev_err(dev,
-			"Failed to set ingress vlan rewrite mode, aborting.\n");
-		goto err_out_free_vnic_resources;
-	}
-
 	switch (vnic_dev_get_intr_mode(enic->vdev)) {
 	default:
 		netif_napi_add(netdev, &enic->napi[0], enic_poll, 64);
@@ -2713,6 +2448,22 @@
 		goto err_out_vnic_unregister;
 	}
 
+	/* Setup devcmd lock
+	 */
+
+	spin_lock_init(&enic->devcmd_lock);
+
+	/*
+	 * Set ingress vlan rewrite mode before vnic initialization
+	 */
+
+	err = enic_dev_set_ig_vlan_rewrite_mode(enic);
+	if (err) {
+		dev_err(dev,
+			"Failed to set ingress vlan rewrite mode, aborting.\n");
+		goto err_out_dev_close;
+	}
+
 	/* Issue device init to initialize the vnic-to-switch link.
 	 * We'll start with carrier off and wait for link UP
 	 * notification later to turn on carrier.  We don't need
@@ -2736,11 +2487,6 @@
 		}
 	}
 
-	/* Setup devcmd lock
-	 */
-
-	spin_lock_init(&enic->devcmd_lock);
-
 	err = enic_dev_init(enic);
 	if (err) {
 		dev_err(dev, "Device initialization failed, aborting\n");
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/Makefile linux-libre-2.6.39-gnu/drivers/net/enic/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/enic/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 obj-$(CONFIG_ENIC) := enic.o
 
 enic-y := enic_main.o vnic_cq.o vnic_intr.o vnic_wq.o \
-	enic_res.o vnic_dev.o vnic_rq.o vnic_vic.o
+	enic_res.o enic_dev.o vnic_dev.o vnic_rq.o vnic_vic.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/vnic_dev.c linux-libre-2.6.39-gnu/drivers/net/enic/vnic_dev.c
--- linux-libre-2.6.38-gnu/drivers/net/enic/vnic_dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/vnic_dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -408,10 +408,17 @@
 		if (!vdev->fw_info)
 			return -ENOMEM;
 
+		memset(vdev->fw_info, 0, sizeof(struct vnic_devcmd_fw_info));
+
 		a0 = vdev->fw_info_pa;
+		a1 = sizeof(struct vnic_devcmd_fw_info);
 
 		/* only get fw_info once and cache it */
 		err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO, &a0, &a1, wait);
+		if (err == ERR_ECMDUNKNOWN) {
+			err = vnic_dev_cmd(vdev, CMD_MCPU_FW_INFO_OLD,
+				&a0, &a1, wait);
+		}
 	}
 
 	*fw_info = vdev->fw_info;
@@ -419,25 +426,6 @@
 	return err;
 }
 
-int vnic_dev_hw_version(struct vnic_dev *vdev, enum vnic_dev_hw_version *hw_ver)
-{
-	struct vnic_devcmd_fw_info *fw_info;
-	int err;
-
-	err = vnic_dev_fw_info(vdev, &fw_info);
-	if (err)
-		return err;
-
-	if (strncmp(fw_info->hw_version, "A1", sizeof("A1")) == 0)
-		*hw_ver = VNIC_DEV_HW_VER_A1;
-	else if (strncmp(fw_info->hw_version, "A2", sizeof("A2")) == 0)
-		*hw_ver = VNIC_DEV_HW_VER_A2;
-	else
-		*hw_ver = VNIC_DEV_HW_VER_UNKNOWN;
-
-	return 0;
-}
-
 int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
 	void *value)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/vnic_devcmd.h linux-libre-2.6.39-gnu/drivers/net/enic/vnic_devcmd.h
--- linux-libre-2.6.38-gnu/drivers/net/enic/vnic_devcmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/vnic_devcmd.h	2011-05-19 00:06:34.000000000 -0400
@@ -80,8 +80,34 @@
 enum vnic_devcmd_cmd {
 	CMD_NONE                = _CMDC(_CMD_DIR_NONE, _CMD_VTYPE_NONE, 0),
 
-	/* mcpu fw info in mem: (u64)a0=paddr to struct vnic_devcmd_fw_info */
-	CMD_MCPU_FW_INFO        = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1),
+	/*
+	 * mcpu fw info in mem:
+	 * in:
+	 *   (u64)a0=paddr to struct vnic_devcmd_fw_info
+	 * action:
+	 *   Fills in struct vnic_devcmd_fw_info (128 bytes)
+	 * note:
+	 *   An old definition of CMD_MCPU_FW_INFO
+	 */
+	CMD_MCPU_FW_INFO_OLD    = _CMDC(_CMD_DIR_WRITE, _CMD_VTYPE_ALL, 1),
+
+	/*
+	 * mcpu fw info in mem:
+	 * in:
+	 *   (u64)a0=paddr to struct vnic_devcmd_fw_info
+	 *   (u16)a1=size of the structure
+	 * out:
+	 *	 (u16)a1=0                          for in:a1 = 0,
+	 *	         data size actually written for other values.
+	 * action:
+	 *   Fills in first 128 bytes of vnic_devcmd_fw_info for in:a1 = 0,
+	 *            first in:a1 bytes               for 0 < in:a1 <= 132,
+	 *            132 bytes                       for other values of in:a1.
+	 * note:
+	 *   CMD_MCPU_FW_INFO and CMD_MCPU_FW_INFO_OLD have the same enum 1
+	 *   for source compatibility.
+	 */
+	CMD_MCPU_FW_INFO        = _CMDC(_CMD_DIR_RW, _CMD_VTYPE_ALL, 1),
 
 	/* dev-specific block member:
 	 *    in: (u16)a0=offset,(u8)a1=size
@@ -291,11 +317,19 @@
 	ERR_EMAXRES = 10,
 };
 
+/*
+ * note: hw_version and asic_rev refer to the same thing,
+ *       but have different formats. hw_version is
+ *       a 32-byte string (e.g. "A2") and asic_rev is
+ *       a 16-bit integer (e.g. 0xA2).
+ */
 struct vnic_devcmd_fw_info {
 	char fw_version[32];
 	char fw_build[32];
 	char hw_version[32];
 	char hw_serial_number[32];
+	u16 asic_type;
+	u16 asic_rev;
 };
 
 struct vnic_devcmd_notify {
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/vnic_dev.h linux-libre-2.6.39-gnu/drivers/net/enic/vnic_dev.h
--- linux-libre-2.6.38-gnu/drivers/net/enic/vnic_dev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/vnic_dev.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,12 +44,6 @@
 #undef pr_fmt
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-enum vnic_dev_hw_version {
-	VNIC_DEV_HW_VER_UNKNOWN,
-	VNIC_DEV_HW_VER_A1,
-	VNIC_DEV_HW_VER_A2,
-};
-
 enum vnic_dev_intr_mode {
 	VNIC_DEV_INTR_MODE_UNKNOWN,
 	VNIC_DEV_INTR_MODE_INTX,
@@ -93,8 +87,6 @@
 	u64 *a0, u64 *a1, int wait);
 int vnic_dev_fw_info(struct vnic_dev *vdev,
 	struct vnic_devcmd_fw_info **fw_info);
-int vnic_dev_hw_version(struct vnic_dev *vdev,
-	enum vnic_dev_hw_version *hw_ver);
 int vnic_dev_spec(struct vnic_dev *vdev, unsigned int offset, unsigned int size,
 	void *value);
 int vnic_dev_stats_dump(struct vnic_dev *vdev, struct vnic_stats **stats);
diff -druN linux-libre-2.6.38-gnu/drivers/net/enic/vnic_rq.h linux-libre-2.6.39-gnu/drivers/net/enic/vnic_rq.h
--- linux-libre-2.6.38-gnu/drivers/net/enic/vnic_rq.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/enic/vnic_rq.h	2011-05-19 00:06:34.000000000 -0400
@@ -141,11 +141,6 @@
 	}
 }
 
-static inline int vnic_rq_posting_soon(struct vnic_rq *rq)
-{
-	return (rq->to_use->index & VNIC_RQ_RETURN_RATE) == 0;
-}
-
 static inline void vnic_rq_return_descs(struct vnic_rq *rq, unsigned int count)
 {
 	rq->ring.desc_avail += count;
diff -druN linux-libre-2.6.38-gnu/drivers/net/eql.c linux-libre-2.6.39-gnu/drivers/net/eql.c
--- linux-libre-2.6.38-gnu/drivers/net/eql.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/eql.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,6 +111,8 @@
  * Sorry, I had to rewrite most of this for 2.5.x -DaveM
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/capability.h>
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -162,7 +164,7 @@
 }
 
 static const char version[] __initconst =
-	"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)\n";
+	"Equalizer2002: Simon Janes (simon@ncm.com) and David S. Miller (davem@redhat.com)";
 
 static const struct net_device_ops eql_netdev_ops = {
 	.ndo_open	= eql_open,
@@ -204,8 +206,8 @@
 	equalizer_t *eql = netdev_priv(dev);
 
 	/* XXX We should force this off automatically for the user. */
-	printk(KERN_INFO "%s: remember to turn off Van-Jacobson compression on "
-	       "your slave devices.\n", dev->name);
+	netdev_info(dev,
+		    "remember to turn off Van-Jacobson compression on your slave devices\n");
 
 	BUG_ON(!list_empty(&eql->queue.all_slaves));
 
@@ -591,7 +593,7 @@
 {
 	int err;
 
-	printk(version);
+	pr_info("%s\n", version);
 
 	dev_eql = alloc_netdev(sizeof(equalizer_t), "eql", eql_setup);
 	if (!dev_eql)
diff -druN linux-libre-2.6.38-gnu/drivers/net/eth16i.c linux-libre-2.6.39-gnu/drivers/net/eth16i.c
--- linux-libre-2.6.38-gnu/drivers/net/eth16i.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/eth16i.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
    This driver supports following cards :
 	- ICL EtherTeam 16i
 	- ICL EtherTeam 32 EISA
-	  (Uses true 32 bit transfers rather than 16i compability mode)
+	  (Uses true 32 bit transfers rather than 16i compatibility mode)
 
    Example Module usage:
         insmod eth16i.o io=0x2a0 mediatype=bnc
diff -druN linux-libre-2.6.38-gnu/drivers/net/ethoc.c linux-libre-2.6.39-gnu/drivers/net/ethoc.c
--- linux-libre-2.6.38-gnu/drivers/net/ethoc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ethoc.c	2011-05-19 00:06:34.000000000 -0400
@@ -542,7 +542,7 @@
 
 	/* Figure out what triggered the interrupt...
 	 * The tricky bit here is that the interrupt source bits get
-	 * set in INT_SOURCE for an event irregardless of whether that
+	 * set in INT_SOURCE for an event regardless of whether that
 	 * event is masked or not.  Thus, in order to figure out what
 	 * triggered the interrupt, we need to remove the sources
 	 * for all events that are currently masked.  This behaviour
@@ -1163,15 +1163,11 @@
 # define ethoc_resume  NULL
 #endif
 
-#ifdef CONFIG_OF
 static struct of_device_id ethoc_match[] = {
-	{
-		.compatible = "opencores,ethoc",
-	},
+	{ .compatible = "opencores,ethoc", },
 	{},
 };
 MODULE_DEVICE_TABLE(of, ethoc_match);
-#endif
 
 static struct platform_driver ethoc_driver = {
 	.probe   = ethoc_probe,
@@ -1181,9 +1177,7 @@
 	.driver  = {
 		.name = "ethoc",
 		.owner = THIS_MODULE,
-#ifdef CONFIG_OF
 		.of_match_table = ethoc_match,
-#endif
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/fec.c linux-libre-2.6.39-gnu/drivers/net/fec.c
--- linux-libre-2.6.38-gnu/drivers/net/fec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fec.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 
 #include "fec.h"
 
-#if defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+#if defined(CONFIG_ARM)
 #define FEC_ALIGNMENT	0xf
 #else
 #define FEC_ALIGNMENT	0x3
@@ -148,8 +148,7 @@
  * account when setting it.
  */
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
-    defined(CONFIG_M520x) || defined(CONFIG_M532x) || \
-    defined(CONFIG_ARCH_MXC) || defined(CONFIG_SOC_IMX28)
+    defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM)
 #define	OPT_FRAME_SIZE	(PKT_MAXBUF_SIZE << 16)
 #else
 #define	OPT_FRAME_SIZE	0
@@ -184,7 +183,7 @@
 	struct bufdesc	*rx_bd_base;
 	struct bufdesc	*tx_bd_base;
 	/* The next free ring entry */
-	struct bufdesc	*cur_rx, *cur_tx; 
+	struct bufdesc	*cur_rx, *cur_tx;
 	/* The ring entries to be free()ed */
 	struct bufdesc	*dirty_tx;
 
@@ -192,28 +191,21 @@
 	/* hold while accessing the HW like ringbuffer for tx/rx but not MAC */
 	spinlock_t hw_lock;
 
-	struct  platform_device *pdev;
+	struct	platform_device *pdev;
 
 	int	opened;
 
 	/* Phylib and MDIO interface */
-	struct  mii_bus *mii_bus;
-	struct  phy_device *phy_dev;
-	int     mii_timeout;
-	uint    phy_speed;
+	struct	mii_bus *mii_bus;
+	struct	phy_device *phy_dev;
+	int	mii_timeout;
+	uint	phy_speed;
 	phy_interface_t	phy_interface;
 	int	link;
 	int	full_duplex;
 	struct	completion mdio_done;
 };
 
-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 fec_restart(struct net_device *dev, int duplex);
-static void fec_stop(struct net_device *dev);
-
 /* FEC MII MMFR bits definition */
 #define FEC_MMFR_ST		(1 << 30)
 #define FEC_MMFR_OP_READ	(2 << 28)
@@ -240,9 +232,9 @@
 }
 
 static netdev_tx_t
-fec_enet_start_xmit(struct sk_buff *skb, struct net_device *dev)
+fec_enet_start_xmit(struct sk_buff *skb, struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
@@ -263,9 +255,9 @@
 
 	if (status & BD_ENET_TX_READY) {
 		/* Ooops.  All transmit buffers are full.  Bail out.
-		 * This should not happen, since dev->tbusy should be set.
+		 * This should not happen, since ndev->tbusy should be set.
 		 */
-		printk("%s: tx queue full!.\n", dev->name);
+		printk("%s: tx queue full!.\n", ndev->name);
 		spin_unlock_irqrestore(&fep->hw_lock, flags);
 		return NETDEV_TX_BUSY;
 	}
@@ -285,7 +277,7 @@
 	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);
+		memcpy(fep->tx_bounce[index], skb->data, skb->len);
 		bufaddr = fep->tx_bounce[index];
 	}
 
@@ -300,13 +292,13 @@
 	/* Save skb pointer */
 	fep->tx_skbuff[fep->skb_cur] = skb;
 
-	dev->stats.tx_bytes += skb->len;
+	ndev->stats.tx_bytes += skb->len;
 	fep->skb_cur = (fep->skb_cur+1) & TX_RING_MOD_MASK;
 
 	/* Push the data cache so the CPM does not get stale memory
 	 * data.
 	 */
-	bdp->cbd_bufaddr = dma_map_single(&dev->dev, bufaddr,
+	bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, bufaddr,
 			FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 
 	/* Send it on its way.  Tell FEC it's ready, interrupt when done,
@@ -327,7 +319,7 @@
 
 	if (bdp == fep->dirty_tx) {
 		fep->tx_full = 1;
-		netif_stop_queue(dev);
+		netif_stop_queue(ndev);
 	}
 
 	fep->cur_tx = bdp;
@@ -337,62 +329,170 @@
 	return NETDEV_TX_OK;
 }
 
+/* This function is called to start or restart the FEC during a link
+ * change.  This only happens when switching between half and full
+ * duplex.
+ */
 static void
-fec_timeout(struct net_device *dev)
+fec_restart(struct net_device *ndev, int duplex)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	const struct platform_device_id *id_entry =
+				platform_get_device_id(fep->pdev);
+	int i;
+	u32 temp_mac[2];
+	u32 rcntl = OPT_FRAME_SIZE | 0x04;
 
-	dev->stats.tx_errors++;
+	/* Whack a reset.  We should wait for this. */
+	writel(1, fep->hwp + FEC_ECNTRL);
+	udelay(10);
 
-	fec_restart(dev, fep->full_duplex);
-	netif_wake_queue(dev);
-}
+	/*
+	 * enet-mac reset will reset mac address registers too,
+	 * so need to reconfigure it.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		memcpy(&temp_mac, ndev->dev_addr, ETH_ALEN);
+		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
+		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
+	}
 
-static irqreturn_t
-fec_enet_interrupt(int irq, void * dev_id)
-{
-	struct	net_device *dev = dev_id;
-	struct fec_enet_private *fep = netdev_priv(dev);
-	uint	int_events;
-	irqreturn_t ret = IRQ_NONE;
+	/* Clear any outstanding interrupt. */
+	writel(0xffc00000, fep->hwp + FEC_IEVENT);
 
-	do {
-		int_events = readl(fep->hwp + FEC_IEVENT);
-		writel(int_events, fep->hwp + FEC_IEVENT);
+	/* 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
 
-		if (int_events & FEC_ENET_RXF) {
-			ret = IRQ_HANDLED;
-			fec_enet_rx(dev);
-		}
+	/* Set maximum receive buffer size. */
+	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_SIZE);
 
-		/* Transmit OK, or non-fatal error. Update the buffer
-		 * 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);
+	/* 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. */
+	fep->skb_cur = fep->skb_dirty = 0;
+	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;
 		}
+	}
 
-		if (int_events & FEC_ENET_MII) {
-			ret = IRQ_HANDLED;
-			complete(&fep->mdio_done);
+	/* Enable MII mode */
+	if (duplex) {
+		/* FD enable */
+		writel(0x04, fep->hwp + FEC_X_CNTRL);
+	} else {
+		/* No Rcv on Xmit */
+		rcntl |= 0x02;
+		writel(0x0, fep->hwp + FEC_X_CNTRL);
+	}
+
+	fep->full_duplex = duplex;
+
+	/* Set MII speed */
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+
+	/*
+	 * The phy interface and speed need to get configured
+	 * differently on enet-mac.
+	 */
+	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
+		/* Enable flow control and length check */
+		rcntl |= 0x40000000 | 0x00000020;
+
+		/* MII or RMII */
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
+			rcntl |= (1 << 8);
+		else
+			rcntl &= ~(1 << 8);
+
+		/* 10M or 100M */
+		if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
+			rcntl &= ~(1 << 9);
+		else
+			rcntl |= (1 << 9);
+
+	} else {
+#ifdef FEC_MIIGSK_ENR
+		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
+			/* disable the gasket and wait */
+			writel(0, fep->hwp + FEC_MIIGSK_ENR);
+			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
+				udelay(1);
+
+			/*
+			 * configure the gasket:
+			 *   RMII, 50 MHz, no loopback, no echo
+			 */
+			writel(1, fep->hwp + FEC_MIIGSK_CFGR);
+
+			/* re-enable the gasket */
+			writel(2, fep->hwp + FEC_MIIGSK_ENR);
 		}
-	} while (int_events);
+#endif
+	}
+	writel(rcntl, fep->hwp + FEC_R_CNTRL);
 
-	return ret;
+	/* 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 */
+	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
+}
+
+static void
+fec_stop(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	/* 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 (!(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. */
+	writel(1, fep->hwp + FEC_ECNTRL);
+	udelay(10);
+	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
+	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
 }
 
 
 static void
-fec_enet_tx(struct net_device *dev)
+fec_timeout(struct net_device *ndev)
+{
+	struct fec_enet_private *fep = netdev_priv(ndev);
+
+	ndev->stats.tx_errors++;
+
+	fec_restart(ndev, fep->full_duplex);
+	netif_wake_queue(ndev);
+}
+
+static void
+fec_enet_tx(struct net_device *ndev)
 {
 	struct	fec_enet_private *fep;
 	struct bufdesc *bdp;
 	unsigned short status;
 	struct	sk_buff	*skb;
 
-	fep = netdev_priv(dev);
+	fep = netdev_priv(ndev);
 	spin_lock(&fep->hw_lock);
 	bdp = fep->dirty_tx;
 
@@ -400,7 +500,8 @@
 		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);
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				FEC_ENET_TX_FRSIZE, DMA_TO_DEVICE);
 		bdp->cbd_bufaddr = 0;
 
 		skb = fep->tx_skbuff[fep->skb_dirty];
@@ -408,19 +509,19 @@
 		if (status & (BD_ENET_TX_HB | BD_ENET_TX_LC |
 				   BD_ENET_TX_RL | BD_ENET_TX_UN |
 				   BD_ENET_TX_CSL)) {
-			dev->stats.tx_errors++;
+			ndev->stats.tx_errors++;
 			if (status & BD_ENET_TX_HB)  /* No heartbeat */
-				dev->stats.tx_heartbeat_errors++;
+				ndev->stats.tx_heartbeat_errors++;
 			if (status & BD_ENET_TX_LC)  /* Late collision */
-				dev->stats.tx_window_errors++;
+				ndev->stats.tx_window_errors++;
 			if (status & BD_ENET_TX_RL)  /* Retrans limit */
-				dev->stats.tx_aborted_errors++;
+				ndev->stats.tx_aborted_errors++;
 			if (status & BD_ENET_TX_UN)  /* Underrun */
-				dev->stats.tx_fifo_errors++;
+				ndev->stats.tx_fifo_errors++;
 			if (status & BD_ENET_TX_CSL) /* Carrier lost */
-				dev->stats.tx_carrier_errors++;
+				ndev->stats.tx_carrier_errors++;
 		} else {
-			dev->stats.tx_packets++;
+			ndev->stats.tx_packets++;
 		}
 
 		if (status & BD_ENET_TX_READY)
@@ -430,7 +531,7 @@
 		 * but we eventually sent the packet OK.
 		 */
 		if (status & BD_ENET_TX_DEF)
-			dev->stats.collisions++;
+			ndev->stats.collisions++;
 
 		/* Free the sk buffer associated with this last transmit */
 		dev_kfree_skb_any(skb);
@@ -447,8 +548,8 @@
 		 */
 		if (fep->tx_full) {
 			fep->tx_full = 0;
-			if (netif_queue_stopped(dev))
-				netif_wake_queue(dev);
+			if (netif_queue_stopped(ndev))
+				netif_wake_queue(ndev);
 		}
 	}
 	fep->dirty_tx = bdp;
@@ -462,9 +563,9 @@
  * effectively tossing the packet.
  */
 static void
-fec_enet_rx(struct net_device *dev)
+fec_enet_rx(struct net_device *ndev)
 {
-	struct	fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	struct bufdesc *bdp;
@@ -498,17 +599,17 @@
 		/* 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++;
+			ndev->stats.rx_errors++;
 			if (status & (BD_ENET_RX_LG | BD_ENET_RX_SH)) {
 				/* Frame too long or too short. */
-				dev->stats.rx_length_errors++;
+				ndev->stats.rx_length_errors++;
 			}
 			if (status & BD_ENET_RX_NO)	/* Frame alignment */
-				dev->stats.rx_frame_errors++;
+				ndev->stats.rx_frame_errors++;
 			if (status & BD_ENET_RX_CR)	/* CRC Error */
-				dev->stats.rx_crc_errors++;
+				ndev->stats.rx_crc_errors++;
 			if (status & BD_ENET_RX_OV)	/* FIFO overrun */
-				dev->stats.rx_fifo_errors++;
+				ndev->stats.rx_fifo_errors++;
 		}
 
 		/* Report late collisions as a frame error.
@@ -516,19 +617,19 @@
 		 * 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++;
+			ndev->stats.rx_errors++;
+			ndev->stats.rx_frame_errors++;
 			goto rx_processing_done;
 		}
 
 		/* Process the incoming frame. */
-		dev->stats.rx_packets++;
+		ndev->stats.rx_packets++;
 		pkt_len = bdp->cbd_datlen;
-		dev->stats.rx_bytes += pkt_len;
+		ndev->stats.rx_bytes += pkt_len;
 		data = (__u8*)__va(bdp->cbd_bufaddr);
 
-	        dma_unmap_single(NULL, bdp->cbd_bufaddr, bdp->cbd_datlen,
-        			DMA_FROM_DEVICE);
+		dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
+				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
 
 		if (id_entry->driver_data & FEC_QUIRK_SWAP_FRAME)
 			swap_buffer(data, pkt_len);
@@ -542,18 +643,18 @@
 
 		if (unlikely(!skb)) {
 			printk("%s: Memory squeeze, dropping packet.\n",
-					dev->name);
-			dev->stats.rx_dropped++;
+					ndev->name);
+			ndev->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);
+			skb->protocol = eth_type_trans(skb, ndev);
 			netif_rx(skb);
 		}
 
-        	bdp->cbd_bufaddr = dma_map_single(NULL, data, bdp->cbd_datlen,
-			DMA_FROM_DEVICE);
+		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, data,
+				FEC_ENET_TX_FRSIZE, DMA_FROM_DEVICE);
 rx_processing_done:
 		/* Clear the status flags for this buffer */
 		status &= ~BD_ENET_RX_STATS;
@@ -578,10 +679,47 @@
 	spin_unlock(&fep->hw_lock);
 }
 
+static irqreturn_t
+fec_enet_interrupt(int irq, void *dev_id)
+{
+	struct net_device *ndev = dev_id;
+	struct fec_enet_private *fep = netdev_priv(ndev);
+	uint int_events;
+	irqreturn_t ret = IRQ_NONE;
+
+	do {
+		int_events = readl(fep->hwp + FEC_IEVENT);
+		writel(int_events, fep->hwp + FEC_IEVENT);
+
+		if (int_events & FEC_ENET_RXF) {
+			ret = IRQ_HANDLED;
+			fec_enet_rx(ndev);
+		}
+
+		/* Transmit OK, or non-fatal error. Update the buffer
+		 * 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(ndev);
+		}
+
+		if (int_events & FEC_ENET_MII) {
+			ret = IRQ_HANDLED;
+			complete(&fep->mdio_done);
+		}
+	} while (int_events);
+
+	return ret;
+}
+
+
+
 /* ------------------------------------------------------------------------- */
-static void __inline__ fec_get_mac(struct net_device *dev)
+static void __inline__ fec_get_mac(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
 	unsigned char *iap, tmpaddr[ETH_ALEN];
 
@@ -617,11 +755,11 @@
 		iap = &tmpaddr[0];
 	}
 
-	memcpy(dev->dev_addr, iap, ETH_ALEN);
+	memcpy(ndev->dev_addr, iap, ETH_ALEN);
 
 	/* Adjust MAC if using macaddr */
 	if (iap == macaddr)
-		 dev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
+		 ndev->dev_addr[ETH_ALEN-1] = macaddr[ETH_ALEN-1] + fep->pdev->id;
 }
 
 /* ------------------------------------------------------------------------- */
@@ -629,9 +767,9 @@
 /*
  * Phy section
  */
-static void fec_enet_adjust_link(struct net_device *dev)
+static void fec_enet_adjust_link(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = fep->phy_dev;
 	unsigned long flags;
 
@@ -648,7 +786,7 @@
 	/* Duplex link change */
 	if (phy_dev->link) {
 		if (fep->full_duplex != phy_dev->duplex) {
-			fec_restart(dev, phy_dev->duplex);
+			fec_restart(ndev, phy_dev->duplex);
 			status_change = 1;
 		}
 	}
@@ -657,9 +795,9 @@
 	if (phy_dev->link != fep->link) {
 		fep->link = phy_dev->link;
 		if (phy_dev->link)
-			fec_restart(dev, phy_dev->duplex);
+			fec_restart(ndev, phy_dev->duplex);
 		else
-			fec_stop(dev);
+			fec_stop(ndev);
 		status_change = 1;
 	}
 
@@ -728,9 +866,9 @@
 	return 0;
 }
 
-static int fec_enet_mii_probe(struct net_device *dev)
+static int fec_enet_mii_probe(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phy_dev = NULL;
 	char mdio_bus_id[MII_BUS_ID_SIZE];
 	char phy_name[MII_BUS_ID_SIZE + 3];
@@ -755,16 +893,16 @@
 
 	if (phy_id >= PHY_MAX_ADDR) {
 		printk(KERN_INFO "%s: no PHY, assuming direct connection "
-			"to switch\n", dev->name);
+			"to switch\n", ndev->name);
 		strncpy(mdio_bus_id, "0", MII_BUS_ID_SIZE);
 		phy_id = 0;
 	}
 
 	snprintf(phy_name, MII_BUS_ID_SIZE, PHY_ID_FMT, mdio_bus_id, phy_id);
-	phy_dev = phy_connect(dev, phy_name, &fec_enet_adjust_link, 0,
+	phy_dev = phy_connect(ndev, phy_name, &fec_enet_adjust_link, 0,
 		PHY_INTERFACE_MODE_MII);
 	if (IS_ERR(phy_dev)) {
-		printk(KERN_ERR "%s: could not attach to PHY\n", dev->name);
+		printk(KERN_ERR "%s: could not attach to PHY\n", ndev->name);
 		return PTR_ERR(phy_dev);
 	}
 
@@ -777,7 +915,7 @@
 	fep->full_duplex = 0;
 
 	printk(KERN_INFO "%s: Freescale FEC PHY driver [%s] "
-		"(mii_bus:phy_addr=%s, irq=%d)\n", dev->name,
+		"(mii_bus:phy_addr=%s, irq=%d)\n", ndev->name,
 		fep->phy_dev->drv->name, dev_name(&fep->phy_dev->dev),
 		fep->phy_dev->irq);
 
@@ -787,8 +925,8 @@
 static int fec_enet_mii_init(struct platform_device *pdev)
 {
 	static struct mii_bus *fec0_mii_bus;
-	struct net_device *dev = platform_get_drvdata(pdev);
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	const struct platform_device_id *id_entry =
 				platform_get_device_id(fep->pdev);
 	int err = -ENXIO, i;
@@ -846,8 +984,6 @@
 	for (i = 0; i < PHY_MAX_ADDR; i++)
 		fep->mii_bus->irq[i] = PHY_POLL;
 
-	platform_set_drvdata(dev, fep->mii_bus);
-
 	if (mdiobus_register(fep->mii_bus))
 		goto err_out_free_mdio_irq;
 
@@ -874,10 +1010,10 @@
 	mdiobus_free(fep->mii_bus);
 }
 
-static int fec_enet_get_settings(struct net_device *dev,
+static int fec_enet_get_settings(struct net_device *ndev,
 				  struct ethtool_cmd *cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
 	if (!phydev)
@@ -886,10 +1022,10 @@
 	return phy_ethtool_gset(phydev, cmd);
 }
 
-static int fec_enet_set_settings(struct net_device *dev,
+static int fec_enet_set_settings(struct net_device *ndev,
 				 struct ethtool_cmd *cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
 	if (!phydev)
@@ -898,14 +1034,14 @@
 	return phy_ethtool_sset(phydev, cmd);
 }
 
-static void fec_enet_get_drvinfo(struct net_device *dev,
+static void fec_enet_get_drvinfo(struct net_device *ndev,
 				 struct ethtool_drvinfo *info)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	strcpy(info->driver, fep->pdev->dev.driver->name);
 	strcpy(info->version, "Revision: 1.0");
-	strcpy(info->bus_info, dev_name(&dev->dev));
+	strcpy(info->bus_info, dev_name(&ndev->dev));
 }
 
 static struct ethtool_ops fec_enet_ethtool_ops = {
@@ -915,12 +1051,12 @@
 	.get_link		= ethtool_op_get_link,
 };
 
-static int fec_enet_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct phy_device *phydev = fep->phy_dev;
 
-	if (!netif_running(dev))
+	if (!netif_running(ndev))
 		return -EINVAL;
 
 	if (!phydev)
@@ -929,9 +1065,9 @@
 	return phy_mii_ioctl(phydev, rq, cmd);
 }
 
-static void fec_enet_free_buffers(struct net_device *dev)
+static void fec_enet_free_buffers(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
 	struct bufdesc	*bdp;
@@ -941,7 +1077,7 @@
 		skb = fep->rx_skbuff[i];
 
 		if (bdp->cbd_bufaddr)
-			dma_unmap_single(&dev->dev, bdp->cbd_bufaddr,
+			dma_unmap_single(&fep->pdev->dev, bdp->cbd_bufaddr,
 					FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		if (skb)
 			dev_kfree_skb(skb);
@@ -953,9 +1089,9 @@
 		kfree(fep->tx_bounce[i]);
 }
 
-static int fec_enet_alloc_buffers(struct net_device *dev)
+static int fec_enet_alloc_buffers(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
 	struct bufdesc	*bdp;
@@ -964,12 +1100,12 @@
 	for (i = 0; i < RX_RING_SIZE; i++) {
 		skb = dev_alloc_skb(FEC_ENET_RX_FRSIZE);
 		if (!skb) {
-			fec_enet_free_buffers(dev);
+			fec_enet_free_buffers(ndev);
 			return -ENOMEM;
 		}
 		fep->rx_skbuff[i] = skb;
 
-		bdp->cbd_bufaddr = dma_map_single(&dev->dev, skb->data,
+		bdp->cbd_bufaddr = dma_map_single(&fep->pdev->dev, skb->data,
 				FEC_ENET_RX_FRSIZE, DMA_FROM_DEVICE);
 		bdp->cbd_sc = BD_ENET_RX_EMPTY;
 		bdp++;
@@ -996,45 +1132,47 @@
 }
 
 static int
-fec_enet_open(struct net_device *dev)
+fec_enet_open(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	int ret;
 
 	/* I should reset the ring buffers here, but I don't yet know
 	 * a simple way to do that.
 	 */
 
-	ret = fec_enet_alloc_buffers(dev);
+	ret = fec_enet_alloc_buffers(ndev);
 	if (ret)
 		return ret;
 
 	/* Probe and connect to PHY when open the interface */
-	ret = fec_enet_mii_probe(dev);
+	ret = fec_enet_mii_probe(ndev);
 	if (ret) {
-		fec_enet_free_buffers(dev);
+		fec_enet_free_buffers(ndev);
 		return ret;
 	}
 	phy_start(fep->phy_dev);
-	netif_start_queue(dev);
+	netif_start_queue(ndev);
 	fep->opened = 1;
 	return 0;
 }
 
 static int
-fec_enet_close(struct net_device *dev)
+fec_enet_close(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
 	/* Don't know what to do yet. */
 	fep->opened = 0;
-	netif_stop_queue(dev);
-	fec_stop(dev);
+	netif_stop_queue(ndev);
+	fec_stop(ndev);
 
-	if (fep->phy_dev)
+	if (fep->phy_dev) {
+		phy_stop(fep->phy_dev);
 		phy_disconnect(fep->phy_dev);
+	}
 
-        fec_enet_free_buffers(dev);
+	fec_enet_free_buffers(ndev);
 
 	return 0;
 }
@@ -1052,14 +1190,14 @@
 #define HASH_BITS	6		/* #bits in hash */
 #define CRC32_POLY	0xEDB88320
 
-static void set_multicast_list(struct net_device *dev)
+static void set_multicast_list(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct netdev_hw_addr *ha;
 	unsigned int i, bit, data, crc, tmp;
 	unsigned char hash;
 
-	if (dev->flags & IFF_PROMISC) {
+	if (ndev->flags & IFF_PROMISC) {
 		tmp = readl(fep->hwp + FEC_R_CNTRL);
 		tmp |= 0x8;
 		writel(tmp, fep->hwp + FEC_R_CNTRL);
@@ -1070,7 +1208,7 @@
 	tmp &= ~0x8;
 	writel(tmp, fep->hwp + FEC_R_CNTRL);
 
-	if (dev->flags & IFF_ALLMULTI) {
+	if (ndev->flags & IFF_ALLMULTI) {
 		/* Catch all multicast addresses, so set the
 		 * filter to all 1's
 		 */
@@ -1085,7 +1223,7 @@
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_HIGH);
 	writel(0, fep->hwp + FEC_GRP_HASH_TABLE_LOW);
 
-	netdev_for_each_mc_addr(ha, dev) {
+	netdev_for_each_mc_addr(ha, ndev) {
 		/* Only support group multicast for now */
 		if (!(ha->addr[0] & 1))
 			continue;
@@ -1093,7 +1231,7 @@
 		/* calculate crc32 value of mac address */
 		crc = 0xffffffff;
 
-		for (i = 0; i < dev->addr_len; i++) {
+		for (i = 0; i < ndev->addr_len; i++) {
 			data = ha->addr[i];
 			for (bit = 0; bit < 8; bit++, data >>= 1) {
 				crc = (crc >> 1) ^
@@ -1120,20 +1258,20 @@
 
 /* Set a MAC change in hardware. */
 static int
-fec_set_mac_address(struct net_device *dev, void *p)
+fec_set_mac_address(struct net_device *ndev, void *p)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct sockaddr *addr = p;
 
 	if (!is_valid_ether_addr(addr->sa_data))
 		return -EADDRNOTAVAIL;
 
-	memcpy(dev->dev_addr, addr->sa_data, dev->addr_len);
+	memcpy(ndev->dev_addr, addr->sa_data, ndev->addr_len);
 
-	writel(dev->dev_addr[3] | (dev->dev_addr[2] << 8) |
-		(dev->dev_addr[1] << 16) | (dev->dev_addr[0] << 24),
+	writel(ndev->dev_addr[3] | (ndev->dev_addr[2] << 8) |
+		(ndev->dev_addr[1] << 16) | (ndev->dev_addr[0] << 24),
 		fep->hwp + FEC_ADDR_LOW);
-	writel((dev->dev_addr[5] << 16) | (dev->dev_addr[4] << 24),
+	writel((ndev->dev_addr[5] << 16) | (ndev->dev_addr[4] << 24),
 		fep->hwp + FEC_ADDR_HIGH);
 	return 0;
 }
@@ -1147,16 +1285,16 @@
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_tx_timeout		= fec_timeout,
 	.ndo_set_mac_address	= fec_set_mac_address,
-	.ndo_do_ioctl           = fec_enet_ioctl,
+	.ndo_do_ioctl		= fec_enet_ioctl,
 };
 
  /*
   * XXX:  We need to clean up on failure exits here.
   *
   */
-static int fec_enet_init(struct net_device *dev)
+static int fec_enet_init(struct net_device *ndev)
 {
-	struct fec_enet_private *fep = netdev_priv(dev);
+	struct fec_enet_private *fep = netdev_priv(ndev);
 	struct bufdesc *cbd_base;
 	struct bufdesc *bdp;
 	int i;
@@ -1171,20 +1309,19 @@
 
 	spin_lock_init(&fep->hw_lock);
 
-	fep->hwp = (void __iomem *)dev->base_addr;
-	fep->netdev = dev;
+	fep->netdev = ndev;
 
 	/* Get the Ethernet address */
-	fec_get_mac(dev);
+	fec_get_mac(ndev);
 
 	/* Set receive and transmit descriptor base. */
 	fep->rx_bd_base = cbd_base;
 	fep->tx_bd_base = cbd_base + RX_RING_SIZE;
 
 	/* The FEC Ethernet specific entries in the device structure */
-	dev->watchdog_timeo = TX_TIMEOUT;
-	dev->netdev_ops = &fec_netdev_ops;
-	dev->ethtool_ops = &fec_enet_ethtool_ops;
+	ndev->watchdog_timeo = TX_TIMEOUT;
+	ndev->netdev_ops = &fec_netdev_ops;
+	ndev->ethtool_ops = &fec_enet_ethtool_ops;
 
 	/* Initialize the receive buffer descriptors. */
 	bdp = fep->rx_bd_base;
@@ -1213,152 +1350,11 @@
 	bdp--;
 	bdp->cbd_sc |= BD_SC_WRAP;
 
-	fec_restart(dev, 0);
+	fec_restart(ndev, 0);
 
 	return 0;
 }
 
-/* This function is called to start or restart the FEC during a link
- * change.  This only happens when switching between half and full
- * duplex.
- */
-static void
-fec_restart(struct net_device *dev, int duplex)
-{
-	struct fec_enet_private *fep = netdev_priv(dev);
-	const struct platform_device_id *id_entry =
-				platform_get_device_id(fep->pdev);
-	int i;
-	u32 val, temp_mac[2];
-
-	/* Whack a reset.  We should wait for this. */
-	writel(1, fep->hwp + FEC_ECNTRL);
-	udelay(10);
-
-	/*
-	 * enet-mac reset will reset mac address registers too,
-	 * so need to reconfigure it.
-	 */
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		memcpy(&temp_mac, dev->dev_addr, ETH_ALEN);
-		writel(cpu_to_be32(temp_mac[0]), fep->hwp + FEC_ADDR_LOW);
-		writel(cpu_to_be32(temp_mac[1]), fep->hwp + FEC_ADDR_HIGH);
-	}
-
-	/* Clear any outstanding interrupt. */
-	writel(0xffc00000, fep->hwp + FEC_IEVENT);
-
-	/* 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. */
-	writel(PKT_MAXBLR_SIZE, fep->hwp + FEC_R_BUFF_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. */
-	fep->skb_cur = fep->skb_dirty = 0;
-	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;
-		}
-	}
-
-	/* Enable MII mode */
-	if (duplex) {
-		/* 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 */
-		writel(OPT_FRAME_SIZE | 0x06, fep->hwp + FEC_R_CNTRL);
-		writel(0x0, fep->hwp + FEC_X_CNTRL);
-	}
-	fep->full_duplex = duplex;
-
-	/* Set MII speed */
-	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-
-	/*
-	 * The phy interface and speed need to get configured
-	 * differently on enet-mac.
-	 */
-	if (id_entry->driver_data & FEC_QUIRK_ENET_MAC) {
-		val = readl(fep->hwp + FEC_R_CNTRL);
-
-		/* MII or RMII */
-		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII)
-			val |= (1 << 8);
-		else
-			val &= ~(1 << 8);
-
-		/* 10M or 100M */
-		if (fep->phy_dev && fep->phy_dev->speed == SPEED_100)
-			val &= ~(1 << 9);
-		else
-			val |= (1 << 9);
-
-		writel(val, fep->hwp + FEC_R_CNTRL);
-	} else {
-#ifdef FEC_MIIGSK_ENR
-		if (fep->phy_interface == PHY_INTERFACE_MODE_RMII) {
-			/* disable the gasket and wait */
-			writel(0, fep->hwp + FEC_MIIGSK_ENR);
-			while (readl(fep->hwp + FEC_MIIGSK_ENR) & 4)
-				udelay(1);
-
-			/*
-			 * configure the gasket:
-			 *   RMII, 50 MHz, no loopback, no echo
-			 */
-			writel(1, fep->hwp + FEC_MIIGSK_CFGR);
-
-			/* re-enable the gasket */
-			writel(2, fep->hwp + FEC_MIIGSK_ENR);
-		}
-#endif
-	}
-
-	/* 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 */
-	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-}
-
-static void
-fec_stop(struct net_device *dev)
-{
-	struct fec_enet_private *fep = netdev_priv(dev);
-
-	/* 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 (!(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. */
-	writel(1, fep->hwp + FEC_ECNTRL);
-	udelay(10);
-	writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
-	writel(FEC_DEFAULT_IMASK, fep->hwp + FEC_IMASK);
-}
-
 static int __devinit
 fec_probe(struct platform_device *pdev)
 {
@@ -1378,19 +1374,20 @@
 
 	/* Init network device */
 	ndev = alloc_etherdev(sizeof(struct fec_enet_private));
-	if (!ndev)
-		return -ENOMEM;
+	if (!ndev) {
+		ret = -ENOMEM;
+		goto failed_alloc_etherdev;
+	}
 
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 
 	/* setup board info structure */
 	fep = netdev_priv(ndev);
-	memset(fep, 0, sizeof(*fep));
 
-	ndev->base_addr = (unsigned long)ioremap(r->start, resource_size(r));
+	fep->hwp = ioremap(r->start, resource_size(r));
 	fep->pdev = pdev;
 
-	if (!ndev->base_addr) {
+	if (!fep->hwp) {
 		ret = -ENOMEM;
 		goto failed_ioremap;
 	}
@@ -1408,10 +1405,9 @@
 			break;
 		ret = request_irq(irq, fec_enet_interrupt, IRQF_DISABLED, pdev->name, ndev);
 		if (ret) {
-			while (i >= 0) {
+			while (--i >= 0) {
 				irq = platform_get_irq(pdev, i);
 				free_irq(irq, ndev);
-				i--;
 			}
 			goto failed_irq;
 		}
@@ -1454,9 +1450,11 @@
 			free_irq(irq, ndev);
 	}
 failed_irq:
-	iounmap((void __iomem *)ndev->base_addr);
+	iounmap(fep->hwp);
 failed_ioremap:
 	free_netdev(ndev);
+failed_alloc_etherdev:
+	release_mem_region(r->start, resource_size(r));
 
 	return ret;
 }
@@ -1466,16 +1464,22 @@
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
 	struct fec_enet_private *fep = netdev_priv(ndev);
-
-	platform_set_drvdata(pdev, NULL);
+	struct resource *r;
 
 	fec_stop(ndev);
 	fec_enet_mii_remove(fep);
 	clk_disable(fep->clk);
 	clk_put(fep->clk);
-	iounmap((void __iomem *)ndev->base_addr);
+	iounmap(fep->hwp);
 	unregister_netdev(ndev);
 	free_netdev(ndev);
+
+	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	BUG_ON(!r);
+	release_mem_region(r->start, resource_size(r));
+
+	platform_set_drvdata(pdev, NULL);
+
 	return 0;
 }
 
@@ -1484,16 +1488,14 @@
 fec_suspend(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	if (ndev) {
-		fep = netdev_priv(ndev);
-		if (netif_running(ndev)) {
-			fec_stop(ndev);
-			netif_device_detach(ndev);
-		}
-		clk_disable(fep->clk);
+	if (netif_running(ndev)) {
+		fec_stop(ndev);
+		netif_device_detach(ndev);
 	}
+	clk_disable(fep->clk);
+
 	return 0;
 }
 
@@ -1501,16 +1503,14 @@
 fec_resume(struct device *dev)
 {
 	struct net_device *ndev = dev_get_drvdata(dev);
-	struct fec_enet_private *fep;
+	struct fec_enet_private *fep = netdev_priv(ndev);
 
-	if (ndev) {
-		fep = netdev_priv(ndev);
-		clk_enable(fep->clk);
-		if (netif_running(ndev)) {
-			fec_restart(ndev, fep->full_duplex);
-			netif_device_attach(ndev);
-		}
+	clk_enable(fep->clk);
+	if (netif_running(ndev)) {
+		fec_restart(ndev, fep->full_duplex);
+		netif_device_attach(ndev);
 	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/fec.h linux-libre-2.6.39-gnu/drivers/net/fec.h
--- linux-libre-2.6.38-gnu/drivers/net/fec.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fec.h	2011-05-19 00:06:34.000000000 -0400
@@ -97,11 +97,11 @@
  *	The following definitions courtesy of commproc.h, which where
  *	Copyright (c) 1997 Dan Malek (dmalek@jlc.net).
  */
-#define BD_SC_EMPTY     ((ushort)0x8000)        /* Recieve is empty */
+#define BD_SC_EMPTY     ((ushort)0x8000)        /* Receive is empty */
 #define BD_SC_READY     ((ushort)0x8000)        /* Transmit is ready */
 #define BD_SC_WRAP      ((ushort)0x2000)        /* Last buffer descriptor */
 #define BD_SC_INTRPT    ((ushort)0x1000)        /* Interrupt on change */
-#define BD_SC_CM        ((ushort)0x0200)        /* Continous mode */
+#define BD_SC_CM        ((ushort)0x0200)        /* Continuous mode */
 #define BD_SC_ID        ((ushort)0x0100)        /* Rec'd too many idles */
 #define BD_SC_P         ((ushort)0x0100)        /* xmt preamble */
 #define BD_SC_BR        ((ushort)0x0020)        /* Break received */
diff -druN linux-libre-2.6.38-gnu/drivers/net/fec_mpc52xx.c linux-libre-2.6.39-gnu/drivers/net/fec_mpc52xx.c
--- linux-libre-2.6.38-gnu/drivers/net/fec_mpc52xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fec_mpc52xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -840,8 +840,7 @@
 /* OF Driver                                                                */
 /* ======================================================================== */
 
-static int __devinit
-mpc52xx_fec_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit mpc52xx_fec_probe(struct platform_device *op)
 {
 	int rv;
 	struct net_device *ndev;
@@ -1049,7 +1048,7 @@
 
 MODULE_DEVICE_TABLE(of, mpc52xx_fec_match);
 
-static struct of_platform_driver mpc52xx_fec_driver = {
+static struct platform_driver mpc52xx_fec_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1073,21 +1072,21 @@
 {
 #ifdef CONFIG_FEC_MPC52xx_MDIO
 	int ret;
-	ret = of_register_platform_driver(&mpc52xx_fec_mdio_driver);
+	ret = platform_driver_register(&mpc52xx_fec_mdio_driver);
 	if (ret) {
 		printk(KERN_ERR DRIVER_NAME ": failed to register mdio driver\n");
 		return ret;
 	}
 #endif
-	return of_register_platform_driver(&mpc52xx_fec_driver);
+	return platform_driver_register(&mpc52xx_fec_driver);
 }
 
 static void __exit
 mpc52xx_fec_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_fec_driver);
+	platform_driver_unregister(&mpc52xx_fec_driver);
 #ifdef CONFIG_FEC_MPC52xx_MDIO
-	of_unregister_platform_driver(&mpc52xx_fec_mdio_driver);
+	platform_driver_unregister(&mpc52xx_fec_mdio_driver);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/fec_mpc52xx.h linux-libre-2.6.39-gnu/drivers/net/fec_mpc52xx.h
--- linux-libre-2.6.38-gnu/drivers/net/fec_mpc52xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fec_mpc52xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -289,6 +289,6 @@
 #define FEC_XMIT_FSM_ENABLE_CRC		0x01000000
 
 
-extern struct of_platform_driver mpc52xx_fec_mdio_driver;
+extern struct platform_driver mpc52xx_fec_mdio_driver;
 
 #endif	/* __DRIVERS_NET_MPC52XX_FEC_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/fec_mpc52xx_phy.c linux-libre-2.6.39-gnu/drivers/net/fec_mpc52xx_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/fec_mpc52xx_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fec_mpc52xx_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,8 +61,7 @@
 		data | FEC_MII_WRITE_FRAME);
 }
 
-static int mpc52xx_fec_mdio_probe(struct platform_device *of,
-		const struct of_device_id *match)
+static int mpc52xx_fec_mdio_probe(struct platform_device *of)
 {
 	struct device *dev = &of->dev;
 	struct device_node *np = of->dev.of_node;
@@ -145,7 +144,7 @@
 };
 MODULE_DEVICE_TABLE(of, mpc52xx_fec_mdio_match);
 
-struct of_platform_driver mpc52xx_fec_mdio_driver = {
+struct platform_driver mpc52xx_fec_mdio_driver = {
 	.driver = {
 		.name = "mpc5200b-fec-phy",
 		.owner = THIS_MODULE,
diff -druN linux-libre-2.6.38-gnu/drivers/net/forcedeth.c linux-libre-2.6.39-gnu/drivers/net/forcedeth.c
--- linux-libre-2.6.38-gnu/drivers/net/forcedeth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/forcedeth.c	2011-05-19 00:06:34.000000000 -0400
@@ -440,7 +440,7 @@
 #define NV_RX3_VLAN_TAG_PRESENT (1<<16)
 #define NV_RX3_VLAN_TAG_MASK	(0x0000FFFF)
 
-/* Miscelaneous hardware related defines: */
+/* Miscellaneous hardware related defines: */
 #define NV_PCI_REGSZ_VER1	0x270
 #define NV_PCI_REGSZ_VER2	0x2d4
 #define NV_PCI_REGSZ_VER3	0x604
@@ -1488,7 +1488,7 @@
 		}
 	}
 
-	/* some phys clear out pause advertisment on reset, set it back */
+	/* some phys clear out pause advertisement on reset, set it back */
 	mii_rw(dev, np->phyaddr, MII_ADVERTISE, reg);
 
 	/* restart auto negotiation, power down phy */
@@ -2535,7 +2535,7 @@
 	else
 		nv_tx_done_optimized(dev, np->tx_ring_size);
 
-	/* save current HW postion */
+	/* save current HW position */
 	if (np->tx_change_owner)
 		put_tx.ex = np->tx_change_owner->first_tx_desc;
 	else
@@ -4053,7 +4053,7 @@
 
 	} else if (ecmd->autoneg == AUTONEG_DISABLE) {
 		/* Note: autonegotiation disable, speed 1000 intentionally
-		 * forbidden - noone should need that. */
+		 * forbidden - no one should need that. */
 
 		if (ecmd->speed != SPEED_10 && ecmd->speed != SPEED_100)
 			return -EINVAL;
@@ -4103,7 +4103,7 @@
 			adv |= ADVERTISE_100HALF;
 		if (ecmd->advertising & ADVERTISED_100baseT_Full)
 			adv |= ADVERTISE_100FULL;
-		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ)  /* for rx we set both advertisments but disable tx pause */
+		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ)  /* for rx we set both advertisements but disable tx pause */
 			adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 		if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
 			adv |=  ADVERTISE_PAUSE_ASYM;
@@ -4148,7 +4148,7 @@
 		if (ecmd->speed == SPEED_100 && ecmd->duplex == DUPLEX_FULL)
 			adv |= ADVERTISE_100FULL;
 		np->pause_flags &= ~(NV_PAUSEFRAME_AUTONEG|NV_PAUSEFRAME_RX_ENABLE|NV_PAUSEFRAME_TX_ENABLE);
-		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisments but disable tx pause */
+		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) {/* for rx we set both advertisements but disable tx pause */
 			adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 			np->pause_flags |= NV_PAUSEFRAME_RX_ENABLE;
 		}
@@ -4449,7 +4449,7 @@
 
 		adv = mii_rw(dev, np->phyaddr, MII_ADVERTISE, MII_READ);
 		adv &= ~(ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM);
-		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisments but disable tx pause */
+		if (np->pause_flags & NV_PAUSEFRAME_RX_REQ) /* for rx we set both advertisements but disable tx pause */
 			adv |=  ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 		if (np->pause_flags & NV_PAUSEFRAME_TX_REQ)
 			adv |=  ADVERTISE_PAUSE_ASYM;
@@ -5744,7 +5744,7 @@
 	pci_set_drvdata(pci_dev, NULL);
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int nv_suspend(struct device *device)
 {
 	struct pci_dev *pdev = to_pci_dev(device);
@@ -5795,6 +5795,11 @@
 static SIMPLE_DEV_PM_OPS(nv_pm_ops, nv_suspend, nv_resume);
 #define NV_PM_OPS (&nv_pm_ops)
 
+#else
+#define NV_PM_OPS NULL
+#endif /* CONFIG_PM_SLEEP */
+
+#ifdef CONFIG_PM
 static void nv_shutdown(struct pci_dev *pdev)
 {
 	struct net_device *dev = pci_get_drvdata(pdev);
@@ -5822,7 +5827,6 @@
 	}
 }
 #else
-#define NV_PM_OPS NULL
 #define nv_shutdown NULL
 #endif /* CONFIG_PM */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/fs_enet/fs_enet-main.c linux-libre-2.6.39-gnu/drivers/net/fs_enet/fs_enet-main.c
--- linux-libre-2.6.38-gnu/drivers/net/fs_enet/fs_enet-main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fs_enet/fs_enet-main.c	2011-05-19 00:06:34.000000000 -0400
@@ -998,9 +998,10 @@
 #endif
 };
 
-static int __devinit fs_enet_probe(struct platform_device *ofdev,
-                                   const struct of_device_id *match)
+static struct of_device_id fs_enet_match[];
+static int __devinit fs_enet_probe(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
 	struct net_device *ndev;
 	struct fs_enet_private *fep;
 	struct fs_platform_info *fpi;
@@ -1008,6 +1009,10 @@
 	const u8 *mac_addr;
 	int privsize, len, ret = -ENODEV;
 
+	match = of_match_device(fs_enet_match, &ofdev->dev);
+	if (!match)
+		return -EINVAL;
+
 	fpi = kzalloc(sizeof(*fpi), GFP_KERNEL);
 	if (!fpi)
 		return -ENOMEM;
@@ -1156,7 +1161,7 @@
 };
 MODULE_DEVICE_TABLE(of, fs_enet_match);
 
-static struct of_platform_driver fs_enet_driver = {
+static struct platform_driver fs_enet_driver = {
 	.driver = {
 		.owner = THIS_MODULE,
 		.name = "fs_enet",
@@ -1168,12 +1173,12 @@
 
 static int __init fs_init(void)
 {
-	return of_register_platform_driver(&fs_enet_driver);
+	return platform_driver_register(&fs_enet_driver);
 }
 
 static void __exit fs_cleanup(void)
 {
-	of_unregister_platform_driver(&fs_enet_driver);
+	platform_driver_unregister(&fs_enet_driver);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druN linux-libre-2.6.38-gnu/drivers/net/fs_enet/mac-fec.c linux-libre-2.6.39-gnu/drivers/net/fs_enet/mac-fec.c
--- linux-libre-2.6.38-gnu/drivers/net/fs_enet/mac-fec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fs_enet/mac-fec.c	2011-05-19 00:06:34.000000000 -0400
@@ -226,8 +226,8 @@
 	}
 
 	FC(fecp, r_cntrl, FEC_RCNTRL_PROM);
-	FW(fecp, hash_table_high, fep->fec.hthi);
-	FW(fecp, hash_table_low, fep->fec.htlo);
+	FW(fecp, grp_hash_table_high, fep->fec.hthi);
+	FW(fecp, grp_hash_table_low, fep->fec.htlo);
 }
 
 static void set_multicast_list(struct net_device *dev)
@@ -273,8 +273,8 @@
 	/*
 	 * Reset all multicast.
 	 */
-	FW(fecp, hash_table_high, fep->fec.hthi);
-	FW(fecp, hash_table_low, fep->fec.htlo);
+	FW(fecp, grp_hash_table_high, fep->fec.hthi);
+	FW(fecp, grp_hash_table_low, fep->fec.htlo);
 
 	/*
 	 * Set maximum receive buffer size.
diff -druN linux-libre-2.6.38-gnu/drivers/net/fs_enet/mii-bitbang.c linux-libre-2.6.39-gnu/drivers/net/fs_enet/mii-bitbang.c
--- linux-libre-2.6.38-gnu/drivers/net/fs_enet/mii-bitbang.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fs_enet/mii-bitbang.c	2011-05-19 00:06:34.000000000 -0400
@@ -150,8 +150,7 @@
 	return 0;
 }
 
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 {
 	struct mii_bus *new_bus;
 	struct bb_info *bitbang;
@@ -223,7 +222,7 @@
 };
 MODULE_DEVICE_TABLE(of, fs_enet_mdio_bb_match);
 
-static struct of_platform_driver fs_enet_bb_mdio_driver = {
+static struct platform_driver fs_enet_bb_mdio_driver = {
 	.driver = {
 		.name = "fsl-bb-mdio",
 		.owner = THIS_MODULE,
@@ -235,12 +234,12 @@
 
 static int fs_enet_mdio_bb_init(void)
 {
-	return of_register_platform_driver(&fs_enet_bb_mdio_driver);
+	return platform_driver_register(&fs_enet_bb_mdio_driver);
 }
 
 static void fs_enet_mdio_bb_exit(void)
 {
-	of_unregister_platform_driver(&fs_enet_bb_mdio_driver);
+	platform_driver_unregister(&fs_enet_bb_mdio_driver);
 }
 
 module_init(fs_enet_mdio_bb_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/fs_enet/mii-fec.c linux-libre-2.6.39-gnu/drivers/net/fs_enet/mii-fec.c
--- linux-libre-2.6.38-gnu/drivers/net/fs_enet/mii-fec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fs_enet/mii-fec.c	2011-05-19 00:06:34.000000000 -0400
@@ -101,15 +101,21 @@
 	return 0;
 }
 
-static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static struct of_device_id fs_enet_mdio_fec_match[];
+static int __devinit fs_enet_mdio_probe(struct platform_device *ofdev)
 {
+	const struct of_device_id *match;
 	struct resource res;
 	struct mii_bus *new_bus;
 	struct fec_info *fec;
-	int (*get_bus_freq)(struct device_node *) = match->data;
+	int (*get_bus_freq)(struct device_node *);
 	int ret = -ENOMEM, clock, speed;
 
+	match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev);
+	if (!match)
+		return -EINVAL;
+	get_bus_freq = match->data;
+
 	new_bus = mdiobus_alloc();
 	if (!new_bus)
 		goto out;
@@ -221,7 +227,7 @@
 };
 MODULE_DEVICE_TABLE(of, fs_enet_mdio_fec_match);
 
-static struct of_platform_driver fs_enet_fec_mdio_driver = {
+static struct platform_driver fs_enet_fec_mdio_driver = {
 	.driver = {
 		.name = "fsl-fec-mdio",
 		.owner = THIS_MODULE,
@@ -233,12 +239,12 @@
 
 static int fs_enet_mdio_fec_init(void)
 {
-	return of_register_platform_driver(&fs_enet_fec_mdio_driver);
+	return platform_driver_register(&fs_enet_fec_mdio_driver);
 }
 
 static void fs_enet_mdio_fec_exit(void)
 {
-	of_unregister_platform_driver(&fs_enet_fec_mdio_driver);
+	platform_driver_unregister(&fs_enet_fec_mdio_driver);
 }
 
 module_init(fs_enet_mdio_fec_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/fsl_pq_mdio.c linux-libre-2.6.39-gnu/drivers/net/fsl_pq_mdio.c
--- linux-libre-2.6.38-gnu/drivers/net/fsl_pq_mdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/fsl_pq_mdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -265,8 +265,7 @@
 #endif
 
 
-static int fsl_pq_mdio_probe(struct platform_device *ofdev,
-		const struct of_device_id *match)
+static int fsl_pq_mdio_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct device_node *tbi;
@@ -471,7 +470,7 @@
 };
 MODULE_DEVICE_TABLE(of, fsl_pq_mdio_match);
 
-static struct of_platform_driver fsl_pq_mdio_driver = {
+static struct platform_driver fsl_pq_mdio_driver = {
 	.driver = {
 		.name = "fsl-pq_mdio",
 		.owner = THIS_MODULE,
@@ -483,13 +482,13 @@
 
 int __init fsl_pq_mdio_init(void)
 {
-	return of_register_platform_driver(&fsl_pq_mdio_driver);
+	return platform_driver_register(&fsl_pq_mdio_driver);
 }
 module_init(fsl_pq_mdio_init);
 
 void fsl_pq_mdio_exit(void)
 {
-	of_unregister_platform_driver(&fsl_pq_mdio_driver);
+	platform_driver_unregister(&fsl_pq_mdio_driver);
 }
 module_exit(fsl_pq_mdio_exit);
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/net/ftmac100.c linux-libre-2.6.39-gnu/drivers/net/ftmac100.c
--- linux-libre-2.6.38-gnu/drivers/net/ftmac100.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/ftmac100.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1198 @@
+/*
+ * Faraday FTMAC100 10/100 Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.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.
+ */
+
+#define pr_fmt(fmt)	KBUILD_MODNAME ": " fmt
+
+#include <linux/dma-mapping.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/mii.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/platform_device.h>
+
+#include "ftmac100.h"
+
+#define DRV_NAME	"ftmac100"
+#define DRV_VERSION	"0.2"
+
+#define RX_QUEUE_ENTRIES	128	/* must be power of 2 */
+#define TX_QUEUE_ENTRIES	16	/* must be power of 2 */
+
+#define MAX_PKT_SIZE		1518
+#define RX_BUF_SIZE		2044	/* must be smaller than 0x7ff */
+
+#if MAX_PKT_SIZE > 0x7ff
+#error invalid MAX_PKT_SIZE
+#endif
+
+#if RX_BUF_SIZE > 0x7ff || RX_BUF_SIZE > PAGE_SIZE
+#error invalid RX_BUF_SIZE
+#endif
+
+/******************************************************************************
+ * private data
+ *****************************************************************************/
+struct ftmac100_descs {
+	struct ftmac100_rxdes rxdes[RX_QUEUE_ENTRIES];
+	struct ftmac100_txdes txdes[TX_QUEUE_ENTRIES];
+};
+
+struct ftmac100 {
+	struct resource *res;
+	void __iomem *base;
+	int irq;
+
+	struct ftmac100_descs *descs;
+	dma_addr_t descs_dma_addr;
+
+	unsigned int rx_pointer;
+	unsigned int tx_clean_pointer;
+	unsigned int tx_pointer;
+	unsigned int tx_pending;
+
+	spinlock_t tx_lock;
+
+	struct net_device *netdev;
+	struct device *dev;
+	struct napi_struct napi;
+
+	struct mii_if_info mii;
+};
+
+static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
+				  struct ftmac100_rxdes *rxdes, gfp_t gfp);
+
+/******************************************************************************
+ * internal functions (hardware register access)
+ *****************************************************************************/
+#define INT_MASK_ALL_ENABLED	(FTMAC100_INT_RPKT_FINISH	| \
+				 FTMAC100_INT_NORXBUF		| \
+				 FTMAC100_INT_XPKT_OK		| \
+				 FTMAC100_INT_XPKT_LOST		| \
+				 FTMAC100_INT_RPKT_LOST		| \
+				 FTMAC100_INT_AHB_ERR		| \
+				 FTMAC100_INT_PHYSTS_CHG)
+
+#define INT_MASK_ALL_DISABLED	0
+
+static void ftmac100_enable_all_int(struct ftmac100 *priv)
+{
+	iowrite32(INT_MASK_ALL_ENABLED, priv->base + FTMAC100_OFFSET_IMR);
+}
+
+static void ftmac100_disable_all_int(struct ftmac100 *priv)
+{
+	iowrite32(INT_MASK_ALL_DISABLED, priv->base + FTMAC100_OFFSET_IMR);
+}
+
+static void ftmac100_set_rx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
+{
+	iowrite32(addr, priv->base + FTMAC100_OFFSET_RXR_BADR);
+}
+
+static void ftmac100_set_tx_ring_base(struct ftmac100 *priv, dma_addr_t addr)
+{
+	iowrite32(addr, priv->base + FTMAC100_OFFSET_TXR_BADR);
+}
+
+static void ftmac100_txdma_start_polling(struct ftmac100 *priv)
+{
+	iowrite32(1, priv->base + FTMAC100_OFFSET_TXPD);
+}
+
+static int ftmac100_reset(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	int i;
+
+	/* NOTE: reset clears all registers */
+	iowrite32(FTMAC100_MACCR_SW_RST, priv->base + FTMAC100_OFFSET_MACCR);
+
+	for (i = 0; i < 5; i++) {
+		unsigned int maccr;
+
+		maccr = ioread32(priv->base + FTMAC100_OFFSET_MACCR);
+		if (!(maccr & FTMAC100_MACCR_SW_RST)) {
+			/*
+			 * FTMAC100_MACCR_SW_RST cleared does not indicate
+			 * that hardware reset completed (what the f*ck).
+			 * We still need to wait for a while.
+			 */
+			udelay(500);
+			return 0;
+		}
+
+		udelay(1000);
+	}
+
+	netdev_err(netdev, "software reset failed\n");
+	return -EIO;
+}
+
+static void ftmac100_set_mac(struct ftmac100 *priv, const unsigned char *mac)
+{
+	unsigned int maddr = mac[0] << 8 | mac[1];
+	unsigned int laddr = mac[2] << 24 | mac[3] << 16 | mac[4] << 8 | mac[5];
+
+	iowrite32(maddr, priv->base + FTMAC100_OFFSET_MAC_MADR);
+	iowrite32(laddr, priv->base + FTMAC100_OFFSET_MAC_LADR);
+}
+
+#define MACCR_ENABLE_ALL	(FTMAC100_MACCR_XMT_EN	| \
+				 FTMAC100_MACCR_RCV_EN	| \
+				 FTMAC100_MACCR_XDMA_EN	| \
+				 FTMAC100_MACCR_RDMA_EN	| \
+				 FTMAC100_MACCR_CRC_APD	| \
+				 FTMAC100_MACCR_FULLDUP	| \
+				 FTMAC100_MACCR_RX_RUNT	| \
+				 FTMAC100_MACCR_RX_BROADPKT)
+
+static int ftmac100_start_hw(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+
+	if (ftmac100_reset(priv))
+		return -EIO;
+
+	/* setup ring buffer base registers */
+	ftmac100_set_rx_ring_base(priv,
+				  priv->descs_dma_addr +
+				  offsetof(struct ftmac100_descs, rxdes));
+	ftmac100_set_tx_ring_base(priv,
+				  priv->descs_dma_addr +
+				  offsetof(struct ftmac100_descs, txdes));
+
+	iowrite32(FTMAC100_APTC_RXPOLL_CNT(1), priv->base + FTMAC100_OFFSET_APTC);
+
+	ftmac100_set_mac(priv, netdev->dev_addr);
+
+	iowrite32(MACCR_ENABLE_ALL, priv->base + FTMAC100_OFFSET_MACCR);
+	return 0;
+}
+
+static void ftmac100_stop_hw(struct ftmac100 *priv)
+{
+	iowrite32(0, priv->base + FTMAC100_OFFSET_MACCR);
+}
+
+/******************************************************************************
+ * internal functions (receive descriptor)
+ *****************************************************************************/
+static bool ftmac100_rxdes_first_segment(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FRS);
+}
+
+static bool ftmac100_rxdes_last_segment(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_LRS);
+}
+
+static bool ftmac100_rxdes_owned_by_dma(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
+}
+
+static void ftmac100_rxdes_set_dma_own(struct ftmac100_rxdes *rxdes)
+{
+	/* clear status bits */
+	rxdes->rxdes0 = cpu_to_le32(FTMAC100_RXDES0_RXDMA_OWN);
+}
+
+static bool ftmac100_rxdes_rx_error(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ERR);
+}
+
+static bool ftmac100_rxdes_crc_error(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_CRC_ERR);
+}
+
+static bool ftmac100_rxdes_frame_too_long(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_FTL);
+}
+
+static bool ftmac100_rxdes_runt(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RUNT);
+}
+
+static bool ftmac100_rxdes_odd_nibble(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_RX_ODD_NB);
+}
+
+static unsigned int ftmac100_rxdes_frame_length(struct ftmac100_rxdes *rxdes)
+{
+	return le32_to_cpu(rxdes->rxdes0) & FTMAC100_RXDES0_RFL;
+}
+
+static bool ftmac100_rxdes_multicast(struct ftmac100_rxdes *rxdes)
+{
+	return rxdes->rxdes0 & cpu_to_le32(FTMAC100_RXDES0_MULTICAST);
+}
+
+static void ftmac100_rxdes_set_buffer_size(struct ftmac100_rxdes *rxdes,
+					   unsigned int size)
+{
+	rxdes->rxdes1 &= cpu_to_le32(FTMAC100_RXDES1_EDORR);
+	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_RXBUF_SIZE(size));
+}
+
+static void ftmac100_rxdes_set_end_of_ring(struct ftmac100_rxdes *rxdes)
+{
+	rxdes->rxdes1 |= cpu_to_le32(FTMAC100_RXDES1_EDORR);
+}
+
+static void ftmac100_rxdes_set_dma_addr(struct ftmac100_rxdes *rxdes,
+					dma_addr_t addr)
+{
+	rxdes->rxdes2 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftmac100_rxdes_get_dma_addr(struct ftmac100_rxdes *rxdes)
+{
+	return le32_to_cpu(rxdes->rxdes2);
+}
+
+/*
+ * rxdes3 is not used by hardware. We use it to keep track of page.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftmac100_rxdes_set_page(struct ftmac100_rxdes *rxdes, struct page *page)
+{
+	rxdes->rxdes3 = (unsigned int)page;
+}
+
+static struct page *ftmac100_rxdes_get_page(struct ftmac100_rxdes *rxdes)
+{
+	return (struct page *)rxdes->rxdes3;
+}
+
+/******************************************************************************
+ * internal functions (receive)
+ *****************************************************************************/
+static int ftmac100_next_rx_pointer(int pointer)
+{
+	return (pointer + 1) & (RX_QUEUE_ENTRIES - 1);
+}
+
+static void ftmac100_rx_pointer_advance(struct ftmac100 *priv)
+{
+	priv->rx_pointer = ftmac100_next_rx_pointer(priv->rx_pointer);
+}
+
+static struct ftmac100_rxdes *ftmac100_current_rxdes(struct ftmac100 *priv)
+{
+	return &priv->descs->rxdes[priv->rx_pointer];
+}
+
+static struct ftmac100_rxdes *
+ftmac100_rx_locate_first_segment(struct ftmac100 *priv)
+{
+	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
+
+	while (!ftmac100_rxdes_owned_by_dma(rxdes)) {
+		if (ftmac100_rxdes_first_segment(rxdes))
+			return rxdes;
+
+		ftmac100_rxdes_set_dma_own(rxdes);
+		ftmac100_rx_pointer_advance(priv);
+		rxdes = ftmac100_current_rxdes(priv);
+	}
+
+	return NULL;
+}
+
+static bool ftmac100_rx_packet_error(struct ftmac100 *priv,
+				     struct ftmac100_rxdes *rxdes)
+{
+	struct net_device *netdev = priv->netdev;
+	bool error = false;
+
+	if (unlikely(ftmac100_rxdes_rx_error(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx err\n");
+
+		netdev->stats.rx_errors++;
+		error = true;
+	}
+
+	if (unlikely(ftmac100_rxdes_crc_error(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx crc err\n");
+
+		netdev->stats.rx_crc_errors++;
+		error = true;
+	}
+
+	if (unlikely(ftmac100_rxdes_frame_too_long(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx frame too long\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	} else if (unlikely(ftmac100_rxdes_runt(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx runt\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	} else if (unlikely(ftmac100_rxdes_odd_nibble(rxdes))) {
+		if (net_ratelimit())
+			netdev_info(netdev, "rx odd nibble\n");
+
+		netdev->stats.rx_length_errors++;
+		error = true;
+	}
+
+	return error;
+}
+
+static void ftmac100_rx_drop_packet(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_rxdes *rxdes = ftmac100_current_rxdes(priv);
+	bool done = false;
+
+	if (net_ratelimit())
+		netdev_dbg(netdev, "drop packet %p\n", rxdes);
+
+	do {
+		if (ftmac100_rxdes_last_segment(rxdes))
+			done = true;
+
+		ftmac100_rxdes_set_dma_own(rxdes);
+		ftmac100_rx_pointer_advance(priv);
+		rxdes = ftmac100_current_rxdes(priv);
+	} while (!done && !ftmac100_rxdes_owned_by_dma(rxdes));
+
+	netdev->stats.rx_dropped++;
+}
+
+static bool ftmac100_rx_packet(struct ftmac100 *priv, int *processed)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_rxdes *rxdes;
+	struct sk_buff *skb;
+	struct page *page;
+	dma_addr_t map;
+	int length;
+
+	rxdes = ftmac100_rx_locate_first_segment(priv);
+	if (!rxdes)
+		return false;
+
+	if (unlikely(ftmac100_rx_packet_error(priv, rxdes))) {
+		ftmac100_rx_drop_packet(priv);
+		return true;
+	}
+
+	/*
+	 * It is impossible to get multi-segment packets
+	 * because we always provide big enough receive buffers.
+	 */
+	if (unlikely(!ftmac100_rxdes_last_segment(rxdes)))
+		BUG();
+
+	/* start processing */
+	skb = netdev_alloc_skb_ip_align(netdev, 128);
+	if (unlikely(!skb)) {
+		if (net_ratelimit())
+			netdev_err(netdev, "rx skb alloc failed\n");
+
+		ftmac100_rx_drop_packet(priv);
+		return true;
+	}
+
+	if (unlikely(ftmac100_rxdes_multicast(rxdes)))
+		netdev->stats.multicast++;
+
+	map = ftmac100_rxdes_get_dma_addr(rxdes);
+	dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+
+	length = ftmac100_rxdes_frame_length(rxdes);
+	page = ftmac100_rxdes_get_page(rxdes);
+	skb_fill_page_desc(skb, 0, page, 0, length);
+	skb->len += length;
+	skb->data_len += length;
+	skb->truesize += length;
+	__pskb_pull_tail(skb, min(length, 64));
+
+	ftmac100_alloc_rx_page(priv, rxdes, GFP_ATOMIC);
+
+	ftmac100_rx_pointer_advance(priv);
+
+	skb->protocol = eth_type_trans(skb, netdev);
+
+	netdev->stats.rx_packets++;
+	netdev->stats.rx_bytes += skb->len;
+
+	/* push packet to protocol stack */
+	netif_receive_skb(skb);
+
+	(*processed)++;
+	return true;
+}
+
+/******************************************************************************
+ * internal functions (transmit descriptor)
+ *****************************************************************************/
+static void ftmac100_txdes_reset(struct ftmac100_txdes *txdes)
+{
+	/* clear all except end of ring bit */
+	txdes->txdes0 = 0;
+	txdes->txdes1 &= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
+	txdes->txdes2 = 0;
+	txdes->txdes3 = 0;
+}
+
+static bool ftmac100_txdes_owned_by_dma(struct ftmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
+}
+
+static void ftmac100_txdes_set_dma_own(struct ftmac100_txdes *txdes)
+{
+	/*
+	 * Make sure dma own bit will not be set before any other
+	 * descriptor fields.
+	 */
+	wmb();
+	txdes->txdes0 |= cpu_to_le32(FTMAC100_TXDES0_TXDMA_OWN);
+}
+
+static bool ftmac100_txdes_excessive_collision(struct ftmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_EXSCOL);
+}
+
+static bool ftmac100_txdes_late_collision(struct ftmac100_txdes *txdes)
+{
+	return txdes->txdes0 & cpu_to_le32(FTMAC100_TXDES0_TXPKT_LATECOL);
+}
+
+static void ftmac100_txdes_set_end_of_ring(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_EDOTR);
+}
+
+static void ftmac100_txdes_set_first_segment(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_FTS);
+}
+
+static void ftmac100_txdes_set_last_segment(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_LTS);
+}
+
+static void ftmac100_txdes_set_txint(struct ftmac100_txdes *txdes)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXIC);
+}
+
+static void ftmac100_txdes_set_buffer_size(struct ftmac100_txdes *txdes,
+					   unsigned int len)
+{
+	txdes->txdes1 |= cpu_to_le32(FTMAC100_TXDES1_TXBUF_SIZE(len));
+}
+
+static void ftmac100_txdes_set_dma_addr(struct ftmac100_txdes *txdes,
+					dma_addr_t addr)
+{
+	txdes->txdes2 = cpu_to_le32(addr);
+}
+
+static dma_addr_t ftmac100_txdes_get_dma_addr(struct ftmac100_txdes *txdes)
+{
+	return le32_to_cpu(txdes->txdes2);
+}
+
+/*
+ * txdes3 is not used by hardware. We use it to keep track of socket buffer.
+ * Since hardware does not touch it, we can skip cpu_to_le32()/le32_to_cpu().
+ */
+static void ftmac100_txdes_set_skb(struct ftmac100_txdes *txdes, struct sk_buff *skb)
+{
+	txdes->txdes3 = (unsigned int)skb;
+}
+
+static struct sk_buff *ftmac100_txdes_get_skb(struct ftmac100_txdes *txdes)
+{
+	return (struct sk_buff *)txdes->txdes3;
+}
+
+/******************************************************************************
+ * internal functions (transmit)
+ *****************************************************************************/
+static int ftmac100_next_tx_pointer(int pointer)
+{
+	return (pointer + 1) & (TX_QUEUE_ENTRIES - 1);
+}
+
+static void ftmac100_tx_pointer_advance(struct ftmac100 *priv)
+{
+	priv->tx_pointer = ftmac100_next_tx_pointer(priv->tx_pointer);
+}
+
+static void ftmac100_tx_clean_pointer_advance(struct ftmac100 *priv)
+{
+	priv->tx_clean_pointer = ftmac100_next_tx_pointer(priv->tx_clean_pointer);
+}
+
+static struct ftmac100_txdes *ftmac100_current_txdes(struct ftmac100 *priv)
+{
+	return &priv->descs->txdes[priv->tx_pointer];
+}
+
+static struct ftmac100_txdes *ftmac100_current_clean_txdes(struct ftmac100 *priv)
+{
+	return &priv->descs->txdes[priv->tx_clean_pointer];
+}
+
+static bool ftmac100_tx_complete_packet(struct ftmac100 *priv)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_txdes *txdes;
+	struct sk_buff *skb;
+	dma_addr_t map;
+
+	if (priv->tx_pending == 0)
+		return false;
+
+	txdes = ftmac100_current_clean_txdes(priv);
+
+	if (ftmac100_txdes_owned_by_dma(txdes))
+		return false;
+
+	skb = ftmac100_txdes_get_skb(txdes);
+	map = ftmac100_txdes_get_dma_addr(txdes);
+
+	if (unlikely(ftmac100_txdes_excessive_collision(txdes) ||
+		     ftmac100_txdes_late_collision(txdes))) {
+		/*
+		 * packet transmitted to ethernet lost due to late collision
+		 * or excessive collision
+		 */
+		netdev->stats.tx_aborted_errors++;
+	} else {
+		netdev->stats.tx_packets++;
+		netdev->stats.tx_bytes += skb->len;
+	}
+
+	dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+	dev_kfree_skb(skb);
+
+	ftmac100_txdes_reset(txdes);
+
+	ftmac100_tx_clean_pointer_advance(priv);
+
+	spin_lock(&priv->tx_lock);
+	priv->tx_pending--;
+	spin_unlock(&priv->tx_lock);
+	netif_wake_queue(netdev);
+
+	return true;
+}
+
+static void ftmac100_tx_complete(struct ftmac100 *priv)
+{
+	while (ftmac100_tx_complete_packet(priv))
+		;
+}
+
+static int ftmac100_xmit(struct ftmac100 *priv, struct sk_buff *skb,
+			 dma_addr_t map)
+{
+	struct net_device *netdev = priv->netdev;
+	struct ftmac100_txdes *txdes;
+	unsigned int len = (skb->len < ETH_ZLEN) ? ETH_ZLEN : skb->len;
+
+	txdes = ftmac100_current_txdes(priv);
+	ftmac100_tx_pointer_advance(priv);
+
+	/* setup TX descriptor */
+	ftmac100_txdes_set_skb(txdes, skb);
+	ftmac100_txdes_set_dma_addr(txdes, map);
+
+	ftmac100_txdes_set_first_segment(txdes);
+	ftmac100_txdes_set_last_segment(txdes);
+	ftmac100_txdes_set_txint(txdes);
+	ftmac100_txdes_set_buffer_size(txdes, len);
+
+	spin_lock(&priv->tx_lock);
+	priv->tx_pending++;
+	if (priv->tx_pending == TX_QUEUE_ENTRIES)
+		netif_stop_queue(netdev);
+
+	/* start transmit */
+	ftmac100_txdes_set_dma_own(txdes);
+	spin_unlock(&priv->tx_lock);
+
+	ftmac100_txdma_start_polling(priv);
+	return NETDEV_TX_OK;
+}
+
+/******************************************************************************
+ * internal functions (buffer)
+ *****************************************************************************/
+static int ftmac100_alloc_rx_page(struct ftmac100 *priv,
+				  struct ftmac100_rxdes *rxdes, gfp_t gfp)
+{
+	struct net_device *netdev = priv->netdev;
+	struct page *page;
+	dma_addr_t map;
+
+	page = alloc_page(gfp);
+	if (!page) {
+		if (net_ratelimit())
+			netdev_err(netdev, "failed to allocate rx page\n");
+		return -ENOMEM;
+	}
+
+	map = dma_map_page(priv->dev, page, 0, RX_BUF_SIZE, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, map))) {
+		if (net_ratelimit())
+			netdev_err(netdev, "failed to map rx page\n");
+		__free_page(page);
+		return -ENOMEM;
+	}
+
+	ftmac100_rxdes_set_page(rxdes, page);
+	ftmac100_rxdes_set_dma_addr(rxdes, map);
+	ftmac100_rxdes_set_buffer_size(rxdes, RX_BUF_SIZE);
+	ftmac100_rxdes_set_dma_own(rxdes);
+	return 0;
+}
+
+static void ftmac100_free_buffers(struct ftmac100 *priv)
+{
+	int i;
+
+	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+		struct page *page = ftmac100_rxdes_get_page(rxdes);
+		dma_addr_t map = ftmac100_rxdes_get_dma_addr(rxdes);
+
+		if (!page)
+			continue;
+
+		dma_unmap_page(priv->dev, map, RX_BUF_SIZE, DMA_FROM_DEVICE);
+		__free_page(page);
+	}
+
+	for (i = 0; i < TX_QUEUE_ENTRIES; i++) {
+		struct ftmac100_txdes *txdes = &priv->descs->txdes[i];
+		struct sk_buff *skb = ftmac100_txdes_get_skb(txdes);
+		dma_addr_t map = ftmac100_txdes_get_dma_addr(txdes);
+
+		if (!skb)
+			continue;
+
+		dma_unmap_single(priv->dev, map, skb_headlen(skb), DMA_TO_DEVICE);
+		dev_kfree_skb(skb);
+	}
+
+	dma_free_coherent(priv->dev, sizeof(struct ftmac100_descs),
+			  priv->descs, priv->descs_dma_addr);
+}
+
+static int ftmac100_alloc_buffers(struct ftmac100 *priv)
+{
+	int i;
+
+	priv->descs = dma_alloc_coherent(priv->dev, sizeof(struct ftmac100_descs),
+					 &priv->descs_dma_addr, GFP_KERNEL);
+	if (!priv->descs)
+		return -ENOMEM;
+
+	memset(priv->descs, 0, sizeof(struct ftmac100_descs));
+
+	/* initialize RX ring */
+	ftmac100_rxdes_set_end_of_ring(&priv->descs->rxdes[RX_QUEUE_ENTRIES - 1]);
+
+	for (i = 0; i < RX_QUEUE_ENTRIES; i++) {
+		struct ftmac100_rxdes *rxdes = &priv->descs->rxdes[i];
+
+		if (ftmac100_alloc_rx_page(priv, rxdes, GFP_KERNEL))
+			goto err;
+	}
+
+	/* initialize TX ring */
+	ftmac100_txdes_set_end_of_ring(&priv->descs->txdes[TX_QUEUE_ENTRIES - 1]);
+	return 0;
+
+err:
+	ftmac100_free_buffers(priv);
+	return -ENOMEM;
+}
+
+/******************************************************************************
+ * struct mii_if_info functions
+ *****************************************************************************/
+static int ftmac100_mdio_read(struct net_device *netdev, int phy_id, int reg)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	unsigned int phycr;
+	int i;
+
+	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
+		FTMAC100_PHYCR_REGAD(reg) |
+		FTMAC100_PHYCR_MIIRD;
+
+	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
+
+	for (i = 0; i < 10; i++) {
+		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
+
+		if ((phycr & FTMAC100_PHYCR_MIIRD) == 0)
+			return phycr & FTMAC100_PHYCR_MIIRDATA;
+
+		udelay(100);
+	}
+
+	netdev_err(netdev, "mdio read timed out\n");
+	return 0;
+}
+
+static void ftmac100_mdio_write(struct net_device *netdev, int phy_id, int reg,
+				int data)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	unsigned int phycr;
+	int i;
+
+	phycr = FTMAC100_PHYCR_PHYAD(phy_id) |
+		FTMAC100_PHYCR_REGAD(reg) |
+		FTMAC100_PHYCR_MIIWR;
+
+	data = FTMAC100_PHYWDATA_MIIWDATA(data);
+
+	iowrite32(data, priv->base + FTMAC100_OFFSET_PHYWDATA);
+	iowrite32(phycr, priv->base + FTMAC100_OFFSET_PHYCR);
+
+	for (i = 0; i < 10; i++) {
+		phycr = ioread32(priv->base + FTMAC100_OFFSET_PHYCR);
+
+		if ((phycr & FTMAC100_PHYCR_MIIWR) == 0)
+			return;
+
+		udelay(100);
+	}
+
+	netdev_err(netdev, "mdio write timed out\n");
+}
+
+/******************************************************************************
+ * struct ethtool_ops functions
+ *****************************************************************************/
+static void ftmac100_get_drvinfo(struct net_device *netdev,
+				 struct ethtool_drvinfo *info)
+{
+	strcpy(info->driver, DRV_NAME);
+	strcpy(info->version, DRV_VERSION);
+	strcpy(info->bus_info, dev_name(&netdev->dev));
+}
+
+static int ftmac100_get_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_ethtool_gset(&priv->mii, cmd);
+}
+
+static int ftmac100_set_settings(struct net_device *netdev, struct ethtool_cmd *cmd)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_ethtool_sset(&priv->mii, cmd);
+}
+
+static int ftmac100_nway_reset(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_nway_restart(&priv->mii);
+}
+
+static u32 ftmac100_get_link(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	return mii_link_ok(&priv->mii);
+}
+
+static const struct ethtool_ops ftmac100_ethtool_ops = {
+	.set_settings		= ftmac100_set_settings,
+	.get_settings		= ftmac100_get_settings,
+	.get_drvinfo		= ftmac100_get_drvinfo,
+	.nway_reset		= ftmac100_nway_reset,
+	.get_link		= ftmac100_get_link,
+};
+
+/******************************************************************************
+ * interrupt handler
+ *****************************************************************************/
+static irqreturn_t ftmac100_interrupt(int irq, void *dev_id)
+{
+	struct net_device *netdev = dev_id;
+	struct ftmac100 *priv = netdev_priv(netdev);
+
+	if (likely(netif_running(netdev))) {
+		/* Disable interrupts for polling */
+		ftmac100_disable_all_int(priv);
+		napi_schedule(&priv->napi);
+	}
+
+	return IRQ_HANDLED;
+}
+
+/******************************************************************************
+ * struct napi_struct functions
+ *****************************************************************************/
+static int ftmac100_poll(struct napi_struct *napi, int budget)
+{
+	struct ftmac100 *priv = container_of(napi, struct ftmac100, napi);
+	struct net_device *netdev = priv->netdev;
+	unsigned int status;
+	bool completed = true;
+	int rx = 0;
+
+	status = ioread32(priv->base + FTMAC100_OFFSET_ISR);
+
+	if (status & (FTMAC100_INT_RPKT_FINISH | FTMAC100_INT_NORXBUF)) {
+		/*
+		 * FTMAC100_INT_RPKT_FINISH:
+		 *	RX DMA has received packets into RX buffer successfully
+		 *
+		 * FTMAC100_INT_NORXBUF:
+		 *	RX buffer unavailable
+		 */
+		bool retry;
+
+		do {
+			retry = ftmac100_rx_packet(priv, &rx);
+		} while (retry && rx < budget);
+
+		if (retry && rx == budget)
+			completed = false;
+	}
+
+	if (status & (FTMAC100_INT_XPKT_OK | FTMAC100_INT_XPKT_LOST)) {
+		/*
+		 * FTMAC100_INT_XPKT_OK:
+		 *	packet transmitted to ethernet successfully
+		 *
+		 * FTMAC100_INT_XPKT_LOST:
+		 *	packet transmitted to ethernet lost due to late
+		 *	collision or excessive collision
+		 */
+		ftmac100_tx_complete(priv);
+	}
+
+	if (status & (FTMAC100_INT_NORXBUF | FTMAC100_INT_RPKT_LOST |
+		      FTMAC100_INT_AHB_ERR | FTMAC100_INT_PHYSTS_CHG)) {
+		if (net_ratelimit())
+			netdev_info(netdev, "[ISR] = 0x%x: %s%s%s%s\n", status,
+				    status & FTMAC100_INT_NORXBUF ? "NORXBUF " : "",
+				    status & FTMAC100_INT_RPKT_LOST ? "RPKT_LOST " : "",
+				    status & FTMAC100_INT_AHB_ERR ? "AHB_ERR " : "",
+				    status & FTMAC100_INT_PHYSTS_CHG ? "PHYSTS_CHG" : "");
+
+		if (status & FTMAC100_INT_NORXBUF) {
+			/* RX buffer unavailable */
+			netdev->stats.rx_over_errors++;
+		}
+
+		if (status & FTMAC100_INT_RPKT_LOST) {
+			/* received packet lost due to RX FIFO full */
+			netdev->stats.rx_fifo_errors++;
+		}
+
+		if (status & FTMAC100_INT_PHYSTS_CHG) {
+			/* PHY link status change */
+			mii_check_link(&priv->mii);
+		}
+	}
+
+	if (completed) {
+		/* stop polling */
+		napi_complete(napi);
+		ftmac100_enable_all_int(priv);
+	}
+
+	return rx;
+}
+
+/******************************************************************************
+ * struct net_device_ops functions
+ *****************************************************************************/
+static int ftmac100_open(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	int err;
+
+	err = ftmac100_alloc_buffers(priv);
+	if (err) {
+		netdev_err(netdev, "failed to allocate buffers\n");
+		goto err_alloc;
+	}
+
+	err = request_irq(priv->irq, ftmac100_interrupt, 0, netdev->name, netdev);
+	if (err) {
+		netdev_err(netdev, "failed to request irq %d\n", priv->irq);
+		goto err_irq;
+	}
+
+	priv->rx_pointer = 0;
+	priv->tx_clean_pointer = 0;
+	priv->tx_pointer = 0;
+	priv->tx_pending = 0;
+
+	err = ftmac100_start_hw(priv);
+	if (err)
+		goto err_hw;
+
+	napi_enable(&priv->napi);
+	netif_start_queue(netdev);
+
+	ftmac100_enable_all_int(priv);
+
+	return 0;
+
+err_hw:
+	free_irq(priv->irq, netdev);
+err_irq:
+	ftmac100_free_buffers(priv);
+err_alloc:
+	return err;
+}
+
+static int ftmac100_stop(struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+
+	ftmac100_disable_all_int(priv);
+	netif_stop_queue(netdev);
+	napi_disable(&priv->napi);
+	ftmac100_stop_hw(priv);
+	free_irq(priv->irq, netdev);
+	ftmac100_free_buffers(priv);
+
+	return 0;
+}
+
+static int ftmac100_hard_start_xmit(struct sk_buff *skb, struct net_device *netdev)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	dma_addr_t map;
+
+	if (unlikely(skb->len > MAX_PKT_SIZE)) {
+		if (net_ratelimit())
+			netdev_dbg(netdev, "tx packet too big\n");
+
+		netdev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	map = dma_map_single(priv->dev, skb->data, skb_headlen(skb), DMA_TO_DEVICE);
+	if (unlikely(dma_mapping_error(priv->dev, map))) {
+		/* drop packet */
+		if (net_ratelimit())
+			netdev_err(netdev, "map socket buffer failed\n");
+
+		netdev->stats.tx_dropped++;
+		dev_kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+
+	return ftmac100_xmit(priv, skb, map);
+}
+
+/* optional */
+static int ftmac100_do_ioctl(struct net_device *netdev, struct ifreq *ifr, int cmd)
+{
+	struct ftmac100 *priv = netdev_priv(netdev);
+	struct mii_ioctl_data *data = if_mii(ifr);
+
+	return generic_mii_ioctl(&priv->mii, data, cmd, NULL);
+}
+
+static const struct net_device_ops ftmac100_netdev_ops = {
+	.ndo_open		= ftmac100_open,
+	.ndo_stop		= ftmac100_stop,
+	.ndo_start_xmit		= ftmac100_hard_start_xmit,
+	.ndo_set_mac_address	= eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_do_ioctl		= ftmac100_do_ioctl,
+};
+
+/******************************************************************************
+ * struct platform_driver functions
+ *****************************************************************************/
+static int ftmac100_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int irq;
+	struct net_device *netdev;
+	struct ftmac100 *priv;
+	int err;
+
+	if (!pdev)
+		return -ENODEV;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENXIO;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return irq;
+
+	/* setup net_device */
+	netdev = alloc_etherdev(sizeof(*priv));
+	if (!netdev) {
+		err = -ENOMEM;
+		goto err_alloc_etherdev;
+	}
+
+	SET_NETDEV_DEV(netdev, &pdev->dev);
+	SET_ETHTOOL_OPS(netdev, &ftmac100_ethtool_ops);
+	netdev->netdev_ops = &ftmac100_netdev_ops;
+
+	platform_set_drvdata(pdev, netdev);
+
+	/* setup private data */
+	priv = netdev_priv(netdev);
+	priv->netdev = netdev;
+	priv->dev = &pdev->dev;
+
+	spin_lock_init(&priv->tx_lock);
+
+	/* initialize NAPI */
+	netif_napi_add(netdev, &priv->napi, ftmac100_poll, 64);
+
+	/* map io memory */
+	priv->res = request_mem_region(res->start, resource_size(res),
+				       dev_name(&pdev->dev));
+	if (!priv->res) {
+		dev_err(&pdev->dev, "Could not reserve memory region\n");
+		err = -ENOMEM;
+		goto err_req_mem;
+	}
+
+	priv->base = ioremap(res->start, resource_size(res));
+	if (!priv->base) {
+		dev_err(&pdev->dev, "Failed to ioremap ethernet registers\n");
+		err = -EIO;
+		goto err_ioremap;
+	}
+
+	priv->irq = irq;
+
+	/* initialize struct mii_if_info */
+	priv->mii.phy_id	= 0;
+	priv->mii.phy_id_mask	= 0x1f;
+	priv->mii.reg_num_mask	= 0x1f;
+	priv->mii.dev		= netdev;
+	priv->mii.mdio_read	= ftmac100_mdio_read;
+	priv->mii.mdio_write	= ftmac100_mdio_write;
+
+	/* register network device */
+	err = register_netdev(netdev);
+	if (err) {
+		dev_err(&pdev->dev, "Failed to register netdev\n");
+		goto err_register_netdev;
+	}
+
+	netdev_info(netdev, "irq %d, mapped at %p\n", priv->irq, priv->base);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		random_ether_addr(netdev->dev_addr);
+		netdev_info(netdev, "generated random MAC address %pM\n",
+			    netdev->dev_addr);
+	}
+
+	return 0;
+
+err_register_netdev:
+	iounmap(priv->base);
+err_ioremap:
+	release_resource(priv->res);
+err_req_mem:
+	netif_napi_del(&priv->napi);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+err_alloc_etherdev:
+	return err;
+}
+
+static int __exit ftmac100_remove(struct platform_device *pdev)
+{
+	struct net_device *netdev;
+	struct ftmac100 *priv;
+
+	netdev = platform_get_drvdata(pdev);
+	priv = netdev_priv(netdev);
+
+	unregister_netdev(netdev);
+
+	iounmap(priv->base);
+	release_resource(priv->res);
+
+	netif_napi_del(&priv->napi);
+	platform_set_drvdata(pdev, NULL);
+	free_netdev(netdev);
+	return 0;
+}
+
+static struct platform_driver ftmac100_driver = {
+	.probe		= ftmac100_probe,
+	.remove		= __exit_p(ftmac100_remove),
+	.driver		= {
+		.name	= DRV_NAME,
+		.owner	= THIS_MODULE,
+	},
+};
+
+/******************************************************************************
+ * initialization / finalization
+ *****************************************************************************/
+static int __init ftmac100_init(void)
+{
+	pr_info("Loading version " DRV_VERSION " ...\n");
+	return platform_driver_register(&ftmac100_driver);
+}
+
+static void __exit ftmac100_exit(void)
+{
+	platform_driver_unregister(&ftmac100_driver);
+}
+
+module_init(ftmac100_init);
+module_exit(ftmac100_exit);
+
+MODULE_AUTHOR("Po-Yu Chuang <ratbert@faraday-tech.com>");
+MODULE_DESCRIPTION("FTMAC100 driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/net/ftmac100.h linux-libre-2.6.39-gnu/drivers/net/ftmac100.h
--- linux-libre-2.6.38-gnu/drivers/net/ftmac100.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/ftmac100.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,180 @@
+/*
+ * Faraday FTMAC100 10/100 Ethernet
+ *
+ * (C) Copyright 2009-2011 Faraday Technology
+ * Po-Yu Chuang <ratbert@faraday-tech.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 __FTMAC100_H
+#define __FTMAC100_H
+
+#define	FTMAC100_OFFSET_ISR		0x00
+#define	FTMAC100_OFFSET_IMR		0x04
+#define	FTMAC100_OFFSET_MAC_MADR	0x08
+#define	FTMAC100_OFFSET_MAC_LADR	0x0c
+#define	FTMAC100_OFFSET_MAHT0		0x10
+#define	FTMAC100_OFFSET_MAHT1		0x14
+#define	FTMAC100_OFFSET_TXPD		0x18
+#define	FTMAC100_OFFSET_RXPD		0x1c
+#define	FTMAC100_OFFSET_TXR_BADR	0x20
+#define	FTMAC100_OFFSET_RXR_BADR	0x24
+#define	FTMAC100_OFFSET_ITC		0x28
+#define	FTMAC100_OFFSET_APTC		0x2c
+#define	FTMAC100_OFFSET_DBLAC		0x30
+#define	FTMAC100_OFFSET_MACCR		0x88
+#define	FTMAC100_OFFSET_MACSR		0x8c
+#define	FTMAC100_OFFSET_PHYCR		0x90
+#define	FTMAC100_OFFSET_PHYWDATA	0x94
+#define	FTMAC100_OFFSET_FCR		0x98
+#define	FTMAC100_OFFSET_BPR		0x9c
+#define	FTMAC100_OFFSET_TS		0xc4
+#define	FTMAC100_OFFSET_DMAFIFOS	0xc8
+#define	FTMAC100_OFFSET_TM		0xcc
+#define	FTMAC100_OFFSET_TX_MCOL_SCOL	0xd4
+#define	FTMAC100_OFFSET_RPF_AEP		0xd8
+#define	FTMAC100_OFFSET_XM_PG		0xdc
+#define	FTMAC100_OFFSET_RUNT_TLCC	0xe0
+#define	FTMAC100_OFFSET_CRCER_FTL	0xe4
+#define	FTMAC100_OFFSET_RLC_RCC		0xe8
+#define	FTMAC100_OFFSET_BROC		0xec
+#define	FTMAC100_OFFSET_MULCA		0xf0
+#define	FTMAC100_OFFSET_RP		0xf4
+#define	FTMAC100_OFFSET_XP		0xf8
+
+/*
+ * Interrupt status register & interrupt mask register
+ */
+#define	FTMAC100_INT_RPKT_FINISH	(1 << 0)
+#define	FTMAC100_INT_NORXBUF		(1 << 1)
+#define	FTMAC100_INT_XPKT_FINISH	(1 << 2)
+#define	FTMAC100_INT_NOTXBUF		(1 << 3)
+#define	FTMAC100_INT_XPKT_OK		(1 << 4)
+#define	FTMAC100_INT_XPKT_LOST		(1 << 5)
+#define	FTMAC100_INT_RPKT_SAV		(1 << 6)
+#define	FTMAC100_INT_RPKT_LOST		(1 << 7)
+#define	FTMAC100_INT_AHB_ERR		(1 << 8)
+#define	FTMAC100_INT_PHYSTS_CHG		(1 << 9)
+
+/*
+ * Interrupt timer control register
+ */
+#define FTMAC100_ITC_RXINT_CNT(x)	(((x) & 0xf) << 0)
+#define FTMAC100_ITC_RXINT_THR(x)	(((x) & 0x7) << 4)
+#define FTMAC100_ITC_RXINT_TIME_SEL	(1 << 7)
+#define FTMAC100_ITC_TXINT_CNT(x)	(((x) & 0xf) << 8)
+#define FTMAC100_ITC_TXINT_THR(x)	(((x) & 0x7) << 12)
+#define FTMAC100_ITC_TXINT_TIME_SEL	(1 << 15)
+
+/*
+ * Automatic polling timer control register
+ */
+#define	FTMAC100_APTC_RXPOLL_CNT(x)	(((x) & 0xf) << 0)
+#define	FTMAC100_APTC_RXPOLL_TIME_SEL	(1 << 4)
+#define	FTMAC100_APTC_TXPOLL_CNT(x)	(((x) & 0xf) << 8)
+#define	FTMAC100_APTC_TXPOLL_TIME_SEL	(1 << 12)
+
+/*
+ * DMA burst length and arbitration control register
+ */
+#define FTMAC100_DBLAC_INCR4_EN		(1 << 0)
+#define FTMAC100_DBLAC_INCR8_EN		(1 << 1)
+#define FTMAC100_DBLAC_INCR16_EN	(1 << 2)
+#define FTMAC100_DBLAC_RXFIFO_LTHR(x)	(((x) & 0x7) << 3)
+#define FTMAC100_DBLAC_RXFIFO_HTHR(x)	(((x) & 0x7) << 6)
+#define FTMAC100_DBLAC_RX_THR_EN	(1 << 9)
+
+/*
+ * MAC control register
+ */
+#define	FTMAC100_MACCR_XDMA_EN		(1 << 0)
+#define	FTMAC100_MACCR_RDMA_EN		(1 << 1)
+#define	FTMAC100_MACCR_SW_RST		(1 << 2)
+#define	FTMAC100_MACCR_LOOP_EN		(1 << 3)
+#define	FTMAC100_MACCR_CRC_DIS		(1 << 4)
+#define	FTMAC100_MACCR_XMT_EN		(1 << 5)
+#define	FTMAC100_MACCR_ENRX_IN_HALFTX	(1 << 6)
+#define	FTMAC100_MACCR_RCV_EN		(1 << 8)
+#define	FTMAC100_MACCR_HT_MULTI_EN	(1 << 9)
+#define	FTMAC100_MACCR_RX_RUNT		(1 << 10)
+#define	FTMAC100_MACCR_RX_FTL		(1 << 11)
+#define	FTMAC100_MACCR_RCV_ALL		(1 << 12)
+#define	FTMAC100_MACCR_CRC_APD		(1 << 14)
+#define	FTMAC100_MACCR_FULLDUP		(1 << 15)
+#define	FTMAC100_MACCR_RX_MULTIPKT	(1 << 16)
+#define	FTMAC100_MACCR_RX_BROADPKT	(1 << 17)
+
+/*
+ * PHY control register
+ */
+#define FTMAC100_PHYCR_MIIRDATA		0xffff
+#define FTMAC100_PHYCR_PHYAD(x)		(((x) & 0x1f) << 16)
+#define FTMAC100_PHYCR_REGAD(x)		(((x) & 0x1f) << 21)
+#define FTMAC100_PHYCR_MIIRD		(1 << 26)
+#define FTMAC100_PHYCR_MIIWR		(1 << 27)
+
+/*
+ * PHY write data register
+ */
+#define FTMAC100_PHYWDATA_MIIWDATA(x)	((x) & 0xffff)
+
+/*
+ * Transmit descriptor, aligned to 16 bytes
+ */
+struct ftmac100_txdes {
+	unsigned int	txdes0;
+	unsigned int	txdes1;
+	unsigned int	txdes2;	/* TXBUF_BADR */
+	unsigned int	txdes3;	/* not used by HW */
+} __attribute__ ((aligned(16)));
+
+#define	FTMAC100_TXDES0_TXPKT_LATECOL	(1 << 0)
+#define	FTMAC100_TXDES0_TXPKT_EXSCOL	(1 << 1)
+#define	FTMAC100_TXDES0_TXDMA_OWN	(1 << 31)
+
+#define	FTMAC100_TXDES1_TXBUF_SIZE(x)	((x) & 0x7ff)
+#define	FTMAC100_TXDES1_LTS		(1 << 27)
+#define	FTMAC100_TXDES1_FTS		(1 << 28)
+#define	FTMAC100_TXDES1_TX2FIC		(1 << 29)
+#define	FTMAC100_TXDES1_TXIC		(1 << 30)
+#define	FTMAC100_TXDES1_EDOTR		(1 << 31)
+
+/*
+ * Receive descriptor, aligned to 16 bytes
+ */
+struct ftmac100_rxdes {
+	unsigned int	rxdes0;
+	unsigned int	rxdes1;
+	unsigned int	rxdes2;	/* RXBUF_BADR */
+	unsigned int	rxdes3;	/* not used by HW */
+} __attribute__ ((aligned(16)));
+
+#define	FTMAC100_RXDES0_RFL		0x7ff
+#define	FTMAC100_RXDES0_MULTICAST	(1 << 16)
+#define	FTMAC100_RXDES0_BROADCAST	(1 << 17)
+#define	FTMAC100_RXDES0_RX_ERR		(1 << 18)
+#define	FTMAC100_RXDES0_CRC_ERR		(1 << 19)
+#define	FTMAC100_RXDES0_FTL		(1 << 20)
+#define	FTMAC100_RXDES0_RUNT		(1 << 21)
+#define	FTMAC100_RXDES0_RX_ODD_NB	(1 << 22)
+#define	FTMAC100_RXDES0_LRS		(1 << 28)
+#define	FTMAC100_RXDES0_FRS		(1 << 29)
+#define	FTMAC100_RXDES0_RXDMA_OWN	(1 << 31)
+
+#define	FTMAC100_RXDES1_RXBUF_SIZE(x)	((x) & 0x7ff)
+#define	FTMAC100_RXDES1_EDORR		(1 << 31)
+
+#endif /* __FTMAC100_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/gianfar.c linux-libre-2.6.39-gnu/drivers/net/gianfar.c
--- linux-libre-2.6.38-gnu/drivers/net/gianfar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/gianfar.c	2011-05-19 00:06:34.000000000 -0400
@@ -123,8 +123,7 @@
 static void adjust_link(struct net_device *dev);
 static void init_registers(struct net_device *dev);
 static int init_phy(struct net_device *dev);
-static int gfar_probe(struct platform_device *ofdev,
-		const struct of_device_id *match);
+static int gfar_probe(struct platform_device *ofdev);
 static int gfar_remove(struct platform_device *ofdev);
 static void free_skb_resources(struct gfar_private *priv);
 static void gfar_set_multi(struct net_device *dev);
@@ -950,6 +949,11 @@
 			(pvr == 0x80861010 && (mod & 0xfff9) == 0x80c0))
 		priv->errata |= GFAR_ERRATA_A002;
 
+	/* MPC8313 Rev < 2.0, MPC8548 rev 2.0 */
+	if ((pvr == 0x80850010 && mod == 0x80b0 && rev < 0x0020) ||
+			(pvr == 0x80210020 && mod == 0x8030 && rev == 0x0020))
+		priv->errata |= GFAR_ERRATA_12;
+
 	if (priv->errata)
 		dev_info(dev, "enabled errata workarounds, flags: 0x%x\n",
 			 priv->errata);
@@ -957,8 +961,7 @@
 
 /* Set up the ethernet device structure, private data,
  * and anything else we need before we start */
-static int gfar_probe(struct platform_device *ofdev,
-		const struct of_device_id *match)
+static int gfar_probe(struct platform_device *ofdev)
 {
 	u32 tempval;
 	struct net_device *dev = NULL;
@@ -2156,8 +2159,15 @@
 	/* Set up checksumming */
 	if (CHECKSUM_PARTIAL == skb->ip_summed) {
 		fcb = gfar_add_fcb(skb);
-		lstatus |= BD_LFLAG(TXBD_TOE);
-		gfar_tx_checksum(skb, fcb);
+		/* as specified by errata */
+		if (unlikely(gfar_has_errata(priv, GFAR_ERRATA_12)
+			     && ((unsigned long)fcb % 0x20) > 0x18)) {
+			__skb_pull(skb, GMAC_FCB_LEN);
+			skb_checksum_help(skb);
+		} else {
+			lstatus |= BD_LFLAG(TXBD_TOE);
+			gfar_tx_checksum(skb, fcb);
+		}
 	}
 
 	if (vlan_tx_tag_present(skb)) {
@@ -3256,7 +3266,7 @@
 MODULE_DEVICE_TABLE(of, gfar_match);
 
 /* Structure for a device driver */
-static struct of_platform_driver gfar_driver = {
+static struct platform_driver gfar_driver = {
 	.driver = {
 		.name = "fsl-gianfar",
 		.owner = THIS_MODULE,
@@ -3269,12 +3279,12 @@
 
 static int __init gfar_init(void)
 {
-	return of_register_platform_driver(&gfar_driver);
+	return platform_driver_register(&gfar_driver);
 }
 
 static void __exit gfar_exit(void)
 {
-	of_unregister_platform_driver(&gfar_driver);
+	platform_driver_unregister(&gfar_driver);
 }
 
 module_init(gfar_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/gianfar.h linux-libre-2.6.39-gnu/drivers/net/gianfar.h
--- linux-libre-2.6.38-gnu/drivers/net/gianfar.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/gianfar.h	2011-05-19 00:06:34.000000000 -0400
@@ -1039,10 +1039,11 @@
 	GFAR_ERRATA_74		= 0x01,
 	GFAR_ERRATA_76		= 0x02,
 	GFAR_ERRATA_A002	= 0x04,
+	GFAR_ERRATA_12		= 0x08, /* a.k.a errata eTSEC49 */
 };
 
 /* Struct stolen almost completely (and shamelessly) from the FCC enet source
- * (Ok, that's not so true anymore, but there is a family resemblence)
+ * (Ok, that's not so true anymore, but there is a family resemblance)
  * The GFAR buffer descriptors track the ring buffers.  The rx_bd_base
  * and tx_bd_base always point to the currently available buffer.
  * The dirty_tx tracks the current buffer that is being sent by the
diff -druN linux-libre-2.6.38-gnu/drivers/net/greth.c linux-libre-2.6.39-gnu/drivers/net/greth.c
--- linux-libre-2.6.38-gnu/drivers/net/greth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/greth.c	2011-05-19 00:06:34.000000000 -0400
@@ -1411,7 +1411,7 @@
 }
 
 /* Initialize the GRETH MAC */
-static int __devinit greth_of_probe(struct platform_device *ofdev, const struct of_device_id *match)
+static int __devinit greth_of_probe(struct platform_device *ofdev)
 {
 	struct net_device *dev;
 	struct greth_private *greth;
@@ -1646,7 +1646,7 @@
 
 MODULE_DEVICE_TABLE(of, greth_of_match);
 
-static struct of_platform_driver greth_of_driver = {
+static struct platform_driver greth_of_driver = {
 	.driver = {
 		.name = "grlib-greth",
 		.owner = THIS_MODULE,
@@ -1658,12 +1658,12 @@
 
 static int __init greth_init(void)
 {
-	return of_register_platform_driver(&greth_of_driver);
+	return platform_driver_register(&greth_of_driver);
 }
 
 static void __exit greth_cleanup(void)
 {
-	of_unregister_platform_driver(&greth_of_driver);
+	platform_driver_unregister(&greth_of_driver);
 }
 
 module_init(greth_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/hamradio/bpqether.c linux-libre-2.6.39-gnu/drivers/net/hamradio/bpqether.c
--- linux-libre-2.6.38-gnu/drivers/net/hamradio/bpqether.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/hamradio/bpqether.c	2011-05-19 00:06:34.000000000 -0400
@@ -400,13 +400,14 @@
 static void *bpq_seq_next(struct seq_file *seq, void *v, loff_t *pos)
 {
 	struct list_head *p;
+	struct bpqdev *bpqdev = v;
 
 	++*pos;
 
 	if (v == SEQ_START_TOKEN)
-		p = rcu_dereference(bpq_devices.next);
+		p = rcu_dereference(list_next_rcu(&bpq_devices));
 	else
-		p = rcu_dereference(((struct bpqdev *)v)->bpq_list.next);
+		p = rcu_dereference(list_next_rcu(&bpqdev->bpq_list));
 
 	return (p == &bpq_devices) ? NULL 
 		: list_entry(p, struct bpqdev, bpq_list);
diff -druN linux-libre-2.6.38-gnu/drivers/net/hamradio/Makefile linux-libre-2.6.39-gnu/drivers/net/hamradio/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/hamradio/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/hamradio/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
 #
 #
 # 19971130 	Moved the amateur radio related network drivers from 
-#		drivers/net/ to drivers/hamradio for easier maintainance.
+#		drivers/net/ to drivers/hamradio for easier maintenance.
 #               Joerg Reuter DL1BKE <jreuter@yaina.de>
 #
 # 20000806	Rewritten to use lists instead of if-statements.
diff -druN linux-libre-2.6.38-gnu/drivers/net/hamradio/yam.c linux-libre-2.6.39-gnu/drivers/net/hamradio/yam.c
--- linux-libre-2.6.38-gnu/drivers/net/hamradio/yam.c	2012-03-24 01:09:36.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/hamradio/yam.c	2012-03-24 03:31:45.000000000 -0400
@@ -30,7 +30,7 @@
  *   0.1 F1OAT 07.06.98  Add timer polling routine for channel arbitration
  *   0.2 F6FBB 08.06.98  Added delay after FPGA programming
  *   0.3 F6FBB 29.07.98  Delayed PTT implementation for dupmode=2
- *   0.4 F6FBB 30.07.98  Added TxTail, Slottime and Persistance
+ *   0.4 F6FBB 30.07.98  Added TxTail, Slottime and Persistence
  *   0.5 F6FBB 01.08.98  Shared IRQs, /proc/net and network statistics
  *   0.6 F6FBB 25.08.98  Added 1200Bds format
  *   0.7 F6FBB 12.09.98  Added to the kernel configuration
diff -druN linux-libre-2.6.38-gnu/drivers/net/hp100.c linux-libre-2.6.39-gnu/drivers/net/hp100.c
--- linux-libre-2.6.38-gnu/drivers/net/hp100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/hp100.c	2011-05-19 00:06:34.000000000 -0400
@@ -180,8 +180,8 @@
 
 	u_int *page_vaddr_algn;	/* Aligned virtual address of allocated page */
 	u_long whatever_offset;	/* Offset to bus/phys/dma address */
-	int rxrcommit;		/* # Rx PDLs commited to adapter */
-	int txrcommit;		/* # Tx PDLs commited to adapter */
+	int rxrcommit;		/* # Rx PDLs committed to adapter */
+	int txrcommit;		/* # Tx PDLs committed to adapter */
 };
 
 /*
@@ -716,7 +716,7 @@
 	 * implemented/tested only with the lassen chip anyway... */
 	if (lp->mode == 1) {	/* busmaster */
 		dma_addr_t page_baddr;
-		/* Get physically continous memory for TX & RX PDLs    */
+		/* Get physically continuous memory for TX & RX PDLs    */
 		/* Conversion to new PCI API :
 		 * Pages are always aligned and zeroed, no need to it ourself.
 		 * Doc says should be OK for EISA bus as well - Jean II */
@@ -1596,7 +1596,7 @@
 
 /* clean_txring checks if packets have been sent by the card by reading
  * the TX_PDL register from the performance page and comparing it to the
- * number of commited packets. It then frees the skb's of the packets that
+ * number of committed packets. It then frees the skb's of the packets that
  * obviously have been sent to the network.
  *
  * Needs the PERFORMANCE page selected.
@@ -1617,7 +1617,7 @@
 
 #ifdef HP100_DEBUG
 	if (donecount > MAX_TX_PDL)
-		printk("hp100: %s: Warning: More PDLs transmitted than commited to card???\n", dev->name);
+		printk("hp100: %s: Warning: More PDLs transmitted than committed to card???\n", dev->name);
 #endif
 
 	for (; 0 != donecount; donecount--) {
@@ -1765,7 +1765,7 @@
  * Receive Function (Non-Busmaster mode)
  * Called when an "Receive Packet" interrupt occurs, i.e. the receive
  * packet counter is non-zero.
- * For non-busmaster, this function does the whole work of transfering
+ * For non-busmaster, this function does the whole work of transferring
  * the packet to the host memory and then up to higher layers via skb
  * and netif_rx.
  */
@@ -1892,7 +1892,7 @@
 		/* RX_PKT_CNT states how many PDLs are currently formatted and available to
 		 * the cards BM engine */
 	if ((hp100_inw(RX_PKT_CNT) & 0x00ff) >= lp->rxrcommit) {
-		printk("hp100: %s: More packets received than commited? RX_PKT_CNT=0x%x, commit=0x%x\n",
+		printk("hp100: %s: More packets received than committed? RX_PKT_CNT=0x%x, commit=0x%x\n",
 				     dev->name, hp100_inw(RX_PKT_CNT) & 0x00ff,
 				     lp->rxrcommit);
 		return;
@@ -2256,7 +2256,7 @@
 		if (lp->mode != 1)	/* non busmaster */
 			hp100_rx(dev);
 		else if (!(val & HP100_RX_PDL_FILL_COMPL)) {
-			/* Shouldnt happen - maybe we missed a RX_PDL_FILL Interrupt?  */
+			/* Shouldn't happen - maybe we missed a RX_PDL_FILL Interrupt?  */
 			hp100_rx_bm(dev);
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/hp100.h linux-libre-2.6.39-gnu/drivers/net/hp100.h
--- linux-libre-2.6.38-gnu/drivers/net/hp100.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/hp100.h	2011-05-19 00:06:34.000000000 -0400
@@ -109,7 +109,7 @@
 #define HP100_REG_MAC_CFG_2	0x0d	/* RW: (8) Misc MAC functions        */
 #define HP100_REG_MAC_CFG_3     0x0e	/* RW: (8) Misc MAC functions */
 #define HP100_REG_MAC_CFG_4     0x0f	/* R:  (8) Misc MAC states */
-#define HP100_REG_DROPPED	0x10	/* R:  (16),11:0 Pkts cant fit in mem */
+#define HP100_REG_DROPPED	0x10	/* R:  (16),11:0 Pkts can't fit in mem */
 #define HP100_REG_CRC		0x12	/* R:  (8) Pkts with CRC             */
 #define HP100_REG_ABORT		0x13	/* R:  (8) Aborted Tx pkts           */
 #define HP100_REG_TRAIN_REQUEST 0x14	/* RW: (16) Endnode MAC register. */
diff -druN linux-libre-2.6.38-gnu/drivers/net/hydra.c linux-libre-2.6.39-gnu/drivers/net/hydra.c
--- linux-libre-2.6.38-gnu/drivers/net/hydra.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/hydra.c	2011-05-19 00:06:34.000000000 -0400
@@ -98,15 +98,15 @@
 	.ndo_open		= hydra_open,
 	.ndo_stop		= hydra_close,
 
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
@@ -125,7 +125,7 @@
 	0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
     };
 
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
 	return -ENOMEM;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibmlana.c linux-libre-2.6.39-gnu/drivers/net/ibmlana.c
--- linux-libre-2.6.38-gnu/drivers/net/ibmlana.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibmlana.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,7 @@
 	still work with 2.0.x....
   Jan 28th, 2000
 	in Linux 2.2.13, the version.h file mysteriously didn't get
-	included.  Added a workaround for this.  Futhermore, it now
+	included.  Added a workaround for this.  Furthermore, it now
 	not only compiles as a modules ;-)
   Jan 30th, 2000
 	newer kernels automatically probe more than one board, so the
@@ -481,7 +481,7 @@
 	if ((dev->flags & IFF_ALLMULTI) || netdev_mc_count(dev) > camcnt)
 		rcrval |= RCREG_AMC;
 
-	/* promiscous mode ? */
+	/* promiscuous mode ? */
 
 	if (dev->flags & IFF_PROMISC)
 		rcrval |= RCREG_PRO;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibmlana.h linux-libre-2.6.39-gnu/drivers/net/ibmlana.h
--- linux-libre-2.6.38-gnu/drivers/net/ibmlana.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibmlana.h	2011-05-19 00:06:34.000000000 -0400
@@ -90,7 +90,7 @@
 #define RCREG_ERR        0x8000	/* accept damaged and collided pkts */
 #define RCREG_RNT        0x4000	/* accept packets that are < 64     */
 #define RCREG_BRD        0x2000	/* accept broadcasts                */
-#define RCREG_PRO        0x1000	/* promiscous mode                  */
+#define RCREG_PRO        0x1000	/* promiscuous mode                  */
 #define RCREG_AMC        0x0800	/* accept all multicasts            */
 #define RCREG_LB_NONE    0x0000	/* no loopback                      */
 #define RCREG_LB_MAC     0x0200	/* MAC loopback                     */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/core.c linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/core.c
--- linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -2719,8 +2719,7 @@
 	.ndo_change_mtu		= emac_change_mtu,
 };
 
-static int __devinit emac_probe(struct platform_device *ofdev,
-				const struct of_device_id *match)
+static int __devinit emac_probe(struct platform_device *ofdev)
 {
 	struct net_device *ndev;
 	struct emac_instance *dev;
@@ -2994,7 +2993,7 @@
 };
 MODULE_DEVICE_TABLE(of, emac_match);
 
-static struct of_platform_driver emac_driver = {
+static struct platform_driver emac_driver = {
 	.driver = {
 		.name = "emac",
 		.owner = THIS_MODULE,
@@ -3069,7 +3068,7 @@
 	rc = tah_init();
 	if (rc)
 		goto err_rgmii;
-	rc = of_register_platform_driver(&emac_driver);
+	rc = platform_driver_register(&emac_driver);
 	if (rc)
 		goto err_tah;
 
@@ -3091,7 +3090,7 @@
 {
 	int i;
 
-	of_unregister_platform_driver(&emac_driver);
+	platform_driver_unregister(&emac_driver);
 
 	tah_exit();
 	rgmii_exit();
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/mal.c linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/mal.c
--- linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/mal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/mal.c	2011-05-19 00:06:34.000000000 -0400
@@ -517,8 +517,7 @@
 	return regs + 1;
 }
 
-static int __devinit mal_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit mal_probe(struct platform_device *ofdev)
 {
 	struct mal_instance *mal;
 	int err = 0, i, bd_size;
@@ -789,7 +788,7 @@
 	{},
 };
 
-static struct of_platform_driver mal_of_driver = {
+static struct platform_driver mal_of_driver = {
 	.driver = {
 		.name = "mcmal",
 		.owner = THIS_MODULE,
@@ -801,10 +800,10 @@
 
 int __init mal_init(void)
 {
-	return of_register_platform_driver(&mal_of_driver);
+	return platform_driver_register(&mal_of_driver);
 }
 
 void mal_exit(void)
 {
-	of_unregister_platform_driver(&mal_of_driver);
+	platform_driver_unregister(&mal_of_driver);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/rgmii.c linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/rgmii.c
--- linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/rgmii.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/rgmii.c	2011-05-19 00:06:34.000000000 -0400
@@ -228,8 +228,7 @@
 }
 
 
-static int __devinit rgmii_probe(struct platform_device *ofdev,
-				 const struct of_device_id *match)
+static int __devinit rgmii_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct rgmii_instance *dev;
@@ -318,7 +317,7 @@
 	{},
 };
 
-static struct of_platform_driver rgmii_driver = {
+static struct platform_driver rgmii_driver = {
 	.driver = {
 		.name = "emac-rgmii",
 		.owner = THIS_MODULE,
@@ -330,10 +329,10 @@
 
 int __init rgmii_init(void)
 {
-	return of_register_platform_driver(&rgmii_driver);
+	return platform_driver_register(&rgmii_driver);
 }
 
 void rgmii_exit(void)
 {
-	of_unregister_platform_driver(&rgmii_driver);
+	platform_driver_unregister(&rgmii_driver);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/tah.c linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/tah.c
--- linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/tah.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/tah.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
 		printk(KERN_ERR "%s: reset timeout\n",
 			ofdev->dev.of_node->full_name);
 
-	/* 10KB TAH TX FIFO accomodates the max MTU of 9000 */
+	/* 10KB TAH TX FIFO accommodates the max MTU of 9000 */
 	out_be32(&p->mr,
 		 TAH_MR_CVR | TAH_MR_ST_768 | TAH_MR_TFS_10KB | TAH_MR_DTFP |
 		 TAH_MR_DIG);
@@ -87,8 +87,7 @@
 	return regs + 1;
 }
 
-static int __devinit tah_probe(struct platform_device *ofdev,
-			       const struct of_device_id *match)
+static int __devinit tah_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct tah_instance *dev;
@@ -165,7 +164,7 @@
 	{},
 };
 
-static struct of_platform_driver tah_driver = {
+static struct platform_driver tah_driver = {
 	.driver = {
 		.name = "emac-tah",
 		.owner = THIS_MODULE,
@@ -177,10 +176,10 @@
 
 int __init tah_init(void)
 {
-	return of_register_platform_driver(&tah_driver);
+	return platform_driver_register(&tah_driver);
 }
 
 void tah_exit(void)
 {
-	of_unregister_platform_driver(&tah_driver);
+	platform_driver_unregister(&tah_driver);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/zmii.c linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/zmii.c
--- linux-libre-2.6.38-gnu/drivers/net/ibm_newemac/zmii.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ibm_newemac/zmii.c	2011-05-19 00:06:34.000000000 -0400
@@ -231,8 +231,7 @@
 	return regs + 1;
 }
 
-static int __devinit zmii_probe(struct platform_device *ofdev,
-				const struct of_device_id *match)
+static int __devinit zmii_probe(struct platform_device *ofdev)
 {
 	struct device_node *np = ofdev->dev.of_node;
 	struct zmii_instance *dev;
@@ -312,7 +311,7 @@
 	{},
 };
 
-static struct of_platform_driver zmii_driver = {
+static struct platform_driver zmii_driver = {
 	.driver = {
 		.name = "emac-zmii",
 		.owner = THIS_MODULE,
@@ -324,10 +323,10 @@
 
 int __init zmii_init(void)
 {
-	return of_register_platform_driver(&zmii_driver);
+	return platform_driver_register(&zmii_driver);
 }
 
 void zmii_exit(void)
 {
-	of_unregister_platform_driver(&zmii_driver);
+	platform_driver_unregister(&zmii_driver);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_82575.c linux-libre-2.6.39-gnu/drivers/net/igb/e1000_82575.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_82575.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_82575.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,7 +64,14 @@
 static s32  igb_read_mac_addr_82575(struct e1000_hw *);
 static s32  igb_set_pcie_completion_timeout(struct e1000_hw *hw);
 static s32  igb_reset_mdicnfg_82580(struct e1000_hw *hw);
-
+static s32  igb_validate_nvm_checksum_82580(struct e1000_hw *hw);
+static s32  igb_update_nvm_checksum_82580(struct e1000_hw *hw);
+static s32  igb_update_nvm_checksum_with_offset(struct e1000_hw *hw,
+						u16 offset);
+static s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
+						u16 offset);
+static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw);
+static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw);
 static const u16 e1000_82580_rxpbs_table[] =
 	{ 36, 72, 144, 1, 2, 4, 8, 16,
 	  35, 70, 140 };
@@ -129,6 +136,7 @@
 		break;
 	case E1000_DEV_ID_82580_COPPER:
 	case E1000_DEV_ID_82580_FIBER:
+	case E1000_DEV_ID_82580_QUAD_FIBER:
 	case E1000_DEV_ID_82580_SERDES:
 	case E1000_DEV_ID_82580_SGMII:
 	case E1000_DEV_ID_82580_COPPER_DUAL:
@@ -194,7 +202,11 @@
 	mac->arc_subsystem_valid =
 		(rd32(E1000_FWSM) & E1000_FWSM_MODE_MASK)
 			? true : false;
-
+	/* enable EEE on i350 parts */
+	if (mac->type == e1000_i350)
+		dev_spec->eee_disable = false;
+	else
+		dev_spec->eee_disable = true;
 	/* physical interface link setup */
 	mac->ops.setup_physical_interface =
 		(hw->phy.media_type == e1000_media_type_copper)
@@ -232,14 +244,42 @@
 	 */
 	size += NVM_WORD_SIZE_BASE_SHIFT;
 
-	/* EEPROM access above 16k is unsupported */
-	if (size > 14)
-		size = 14;
 	nvm->word_size = 1 << size;
+	if (nvm->word_size == (1 << 15))
+		nvm->page_size = 128;
 
-	/* if 82576 then initialize mailbox parameters */
-	if (mac->type == e1000_82576)
+	/* NVM Function Pointers */
+	nvm->ops.acquire = igb_acquire_nvm_82575;
+	if (nvm->word_size < (1 << 15))
+		nvm->ops.read = igb_read_nvm_eerd;
+	else
+		nvm->ops.read = igb_read_nvm_spi;
+
+	nvm->ops.release = igb_release_nvm_82575;
+	switch (hw->mac.type) {
+	case e1000_82580:
+		nvm->ops.validate = igb_validate_nvm_checksum_82580;
+		nvm->ops.update = igb_update_nvm_checksum_82580;
+		break;
+	case e1000_i350:
+		nvm->ops.validate = igb_validate_nvm_checksum_i350;
+		nvm->ops.update = igb_update_nvm_checksum_i350;
+		break;
+	default:
+		nvm->ops.validate = igb_validate_nvm_checksum;
+		nvm->ops.update = igb_update_nvm_checksum;
+	}
+	nvm->ops.write = igb_write_nvm_spi;
+
+	/* if part supports SR-IOV then initialize mailbox parameters */
+	switch (mac->type) {
+	case e1000_82576:
+	case e1000_i350:
 		igb_init_mbx_params_pf(hw);
+		break;
+	default:
+		break;
+	}
 
 	/* setup PHY parameters */
 	if (phy->media_type != e1000_media_type_copper) {
@@ -1746,6 +1786,248 @@
 
 	return ret_val;
 }
+
+/**
+ *  igb_validate_nvm_checksum_with_offset - Validate EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Calculates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  and then verifies that the sum of the EEPROM is equal to 0xBABA.
+ **/
+s32 igb_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+	s32 ret_val = 0;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
+		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Read Error\n");
+			goto out;
+		}
+		checksum += nvm_data;
+	}
+
+	if (checksum != (u16) NVM_SUM) {
+		hw_dbg("NVM Checksum Invalid\n");
+		ret_val = -E1000_ERR_NVM;
+		goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_update_nvm_checksum_with_offset - Update EEPROM
+ *  checksum
+ *  @hw: pointer to the HW structure
+ *  @offset: offset in words of the checksum protected region
+ *
+ *  Updates the EEPROM checksum by reading/adding each word of the EEPROM
+ *  up to the checksum.  Then calculates the EEPROM checksum and writes the
+ *  value to the EEPROM.
+ **/
+s32 igb_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
+{
+	s32 ret_val;
+	u16 checksum = 0;
+	u16 i, nvm_data;
+
+	for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
+		ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Read Error while updating checksum.\n");
+			goto out;
+		}
+		checksum += nvm_data;
+	}
+	checksum = (u16) NVM_SUM - checksum;
+	ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
+				&checksum);
+	if (ret_val)
+		hw_dbg("NVM Write Error while updating checksum.\n");
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_validate_nvm_checksum_82580 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+static s32 igb_validate_nvm_checksum_82580(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 eeprom_regions_count = 1;
+	u16 j, nvm_data;
+	u16 nvm_offset;
+
+	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+	if (ret_val) {
+		hw_dbg("NVM Read Error\n");
+		goto out;
+	}
+
+	if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
+		/* if chekcsums compatibility bit is set validate checksums
+		 * for all 4 ports. */
+		eeprom_regions_count = 4;
+	}
+
+	for (j = 0; j < eeprom_regions_count; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_validate_nvm_checksum_with_offset(hw,
+								nvm_offset);
+		if (ret_val != 0)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_update_nvm_checksum_82580 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+static s32 igb_update_nvm_checksum_82580(struct e1000_hw *hw)
+{
+	s32 ret_val;
+	u16 j, nvm_data;
+	u16 nvm_offset;
+
+	ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
+	if (ret_val) {
+		hw_dbg("NVM Read Error while updating checksum"
+			" compatibility bit.\n");
+		goto out;
+	}
+
+	if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) {
+		/* set compatibility bit to validate checksums appropriately */
+		nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
+		ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
+					&nvm_data);
+		if (ret_val) {
+			hw_dbg("NVM Write Error while updating checksum"
+				" compatibility bit.\n");
+			goto out;
+		}
+	}
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset);
+		if (ret_val)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_validate_nvm_checksum_i350 - Validate EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Calculates the EEPROM section checksum by reading/adding each word of
+ *  the EEPROM and then verifies that the sum of the EEPROM is
+ *  equal to 0xBABA.
+ **/
+static s32 igb_validate_nvm_checksum_i350(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 j;
+	u16 nvm_offset;
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_validate_nvm_checksum_with_offset(hw,
+								nvm_offset);
+		if (ret_val != 0)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igb_update_nvm_checksum_i350 - Update EEPROM checksum
+ *  @hw: pointer to the HW structure
+ *
+ *  Updates the EEPROM section checksums for all 4 ports by reading/adding
+ *  each word of the EEPROM up to the checksum.  Then calculates the EEPROM
+ *  checksum and writes the value to the EEPROM.
+ **/
+static s32 igb_update_nvm_checksum_i350(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 j;
+	u16 nvm_offset;
+
+	for (j = 0; j < 4; j++) {
+		nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
+		ret_val = igb_update_nvm_checksum_with_offset(hw, nvm_offset);
+		if (ret_val != 0)
+			goto out;
+	}
+
+out:
+	return ret_val;
+}
+/**
+ *  igb_set_eee_i350 - Enable/disable EEE support
+ *  @hw: pointer to the HW structure
+ *
+ *  Enable/disable EEE based on setting in dev_spec structure.
+ *
+ **/
+s32 igb_set_eee_i350(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u32 ipcnfg, eeer, ctrl_ext;
+
+	ctrl_ext = rd32(E1000_CTRL_EXT);
+	if ((hw->mac.type != e1000_i350) ||
+	    (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK))
+		goto out;
+	ipcnfg = rd32(E1000_IPCNFG);
+	eeer = rd32(E1000_EEER);
+
+	/* enable or disable per user setting */
+	if (!(hw->dev_spec._82575.eee_disable)) {
+		ipcnfg |= (E1000_IPCNFG_EEE_1G_AN |
+			E1000_IPCNFG_EEE_100M_AN);
+		eeer |= (E1000_EEER_TX_LPI_EN |
+			E1000_EEER_RX_LPI_EN |
+			E1000_EEER_LPI_FC);
+
+	} else {
+		ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN |
+			E1000_IPCNFG_EEE_100M_AN);
+		eeer &= ~(E1000_EEER_TX_LPI_EN |
+			E1000_EEER_RX_LPI_EN |
+			E1000_EEER_LPI_FC);
+	}
+	wr32(E1000_IPCNFG, ipcnfg);
+	wr32(E1000_EEER, eeer);
+out:
+
+	return ret_val;
+}
 
 static struct e1000_mac_operations e1000_mac_ops_82575 = {
 	.init_hw              = igb_init_hw_82575,
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_82575.h linux-libre-2.6.39-gnu/drivers/net/igb/e1000_82575.h
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_82575.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_82575.h	2011-05-19 00:06:34.000000000 -0400
@@ -251,5 +251,6 @@
 void igb_vmdq_set_loopback_pf(struct e1000_hw *, bool);
 void igb_vmdq_set_replication_pf(struct e1000_hw *, bool);
 u16 igb_rxpbs_adjust_82580(u32 data);
+s32 igb_set_eee_i350(struct e1000_hw *);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_defines.h linux-libre-2.6.39-gnu/drivers/net/igb/e1000_defines.h
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_defines.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_defines.h	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,7 @@
 #define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES  0x00C00000
 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX  0x00400000
 #define E1000_CTRL_EXT_LINK_MODE_SGMII   0x00800000
+#define E1000_CTRL_EXT_LINK_MODE_GMII   0x00000000
 #define E1000_CTRL_EXT_EIAME          0x01000000
 #define E1000_CTRL_EXT_IRCA           0x00000001
 /* Interrupt delay cancellation */
@@ -110,6 +111,7 @@
 /* Management Control */
 #define E1000_MANC_SMBUS_EN      0x00000001 /* SMBus Enabled - RO */
 #define E1000_MANC_ASF_EN        0x00000002 /* ASF Enabled - RO */
+#define E1000_MANC_EN_BMC2OS     0x10000000 /* OSBMC is Enabled or not */
 /* Enable Neighbor Discovery Filtering */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
 #define E1000_MANC_BLK_PHY_RST_ON_IDE   0x00040000 /* Block phy resets */
@@ -286,7 +288,34 @@
 #define E1000_TCTL_COLD   0x003ff000    /* collision distance */
 #define E1000_TCTL_RTLC   0x01000000    /* Re-transmit on late collision */
 
-/* Transmit Arbitration Count */
+/* DMA Coalescing register fields */
+#define E1000_DMACR_DMACWT_MASK         0x00003FFF /* DMA Coalescing
+							* Watchdog Timer */
+#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Receive
+							* Threshold */
+#define E1000_DMACR_DMACTHR_SHIFT       16
+#define E1000_DMACR_DMAC_LX_MASK        0x30000000 /* Lx when no PCIe
+							* transactions */
+#define E1000_DMACR_DMAC_LX_SHIFT       28
+#define E1000_DMACR_DMAC_EN             0x80000000 /* Enable DMA Coalescing */
+
+#define E1000_DMCTXTH_DMCTTHR_MASK      0x00000FFF /* DMA Coalescing Transmit
+							* Threshold */
+
+#define E1000_DMCTLX_TTLX_MASK          0x00000FFF /* Time to LX request */
+
+#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Receive Traffic Rate
+							* Threshold */
+#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rcv packet rate in
+							* current window */
+
+#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rcv Traffic
+							* Current Cnt */
+
+#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rcv Threshold
+							* High val */
+#define E1000_FCRTC_RTH_COAL_SHIFT      4
+#define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision */
 
 /* SerDes Control */
 #define E1000_SCTL_DISABLE_SERDES_LOOPBACK 0x0400
@@ -565,6 +594,8 @@
 #define NVM_INIT_CONTROL3_PORT_A   0x0024
 #define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
+#define NVM_COMPATIBILITY_REG_3    0x0003
+#define NVM_COMPATIBILITY_BIT_MASK 0x8000
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
@@ -599,6 +630,7 @@
 /* NVM Commands - SPI */
 #define NVM_MAX_RETRY_SPI          5000 /* Max wait of 5ms, for RDY signal */
 #define NVM_WRITE_OPCODE_SPI       0x02 /* NVM write opcode */
+#define NVM_READ_OPCODE_SPI        0x03 /* NVM read opcode */
 #define NVM_A8_OPCODE_SPI          0x08 /* opcode bit-3 = address bit-8 */
 #define NVM_WREN_OPCODE_SPI        0x06 /* NVM set Write Enable latch */
 #define NVM_RDSR_OPCODE_SPI        0x05 /* NVM read Status register */
@@ -757,6 +789,17 @@
 #define E1000_MDIC_ERROR     0x40000000
 #define E1000_MDIC_DEST      0x80000000
 
+/* Thermal Sensor */
+#define E1000_THSTAT_PWR_DOWN       0x00000001 /* Power Down Event */
+#define E1000_THSTAT_LINK_THROTTLE  0x00000002 /* Link Speed Throttle Event */
+
+/* Energy Efficient Ethernet */
+#define E1000_IPCNFG_EEE_1G_AN       0x00000008  /* EEE Enable 1G AN */
+#define E1000_IPCNFG_EEE_100M_AN     0x00000004  /* EEE Enable 100M AN */
+#define E1000_EEER_TX_LPI_EN         0x00010000  /* EEE Tx LPI Enable */
+#define E1000_EEER_RX_LPI_EN         0x00020000  /* EEE Rx LPI Enable */
+#define E1000_EEER_LPI_FC            0x00040000  /* EEE Enable on FC */
+
 /* SerDes Control */
 #define E1000_GEN_CTL_READY             0x80000000
 #define E1000_GEN_CTL_ADDRESS_SHIFT     8
@@ -770,4 +813,11 @@
 #define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision based
                                                       on DMA coal */
 
+/* Tx Rate-Scheduler Config fields */
+#define E1000_RTTBCNRC_RS_ENA		0x80000000
+#define E1000_RTTBCNRC_RF_DEC_MASK	0x00003FFF
+#define E1000_RTTBCNRC_RF_INT_SHIFT	14
+#define E1000_RTTBCNRC_RF_INT_MASK	\
+	(E1000_RTTBCNRC_RF_DEC_MASK << E1000_RTTBCNRC_RF_INT_SHIFT)
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_hw.h linux-libre-2.6.39-gnu/drivers/net/igb/e1000_hw.h
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -54,6 +54,7 @@
 #define E1000_DEV_ID_82580_SERDES             0x1510
 #define E1000_DEV_ID_82580_SGMII              0x1511
 #define E1000_DEV_ID_82580_COPPER_DUAL        0x1516
+#define E1000_DEV_ID_82580_QUAD_FIBER         0x1527
 #define E1000_DEV_ID_DH89XXCC_SGMII           0x0438
 #define E1000_DEV_ID_DH89XXCC_SERDES          0x043A
 #define E1000_DEV_ID_DH89XXCC_BACKPLANE       0x043C
@@ -247,6 +248,10 @@
 	u64 scvpc;
 	u64 hrmpc;
 	u64 doosync;
+	u64 o2bgptc;
+	u64 o2bspc;
+	u64 b2ospc;
+	u64 b2ogprc;
 };
 
 struct e1000_phy_stats {
@@ -331,6 +336,8 @@
 	s32  (*read)(struct e1000_hw *, u16, u16, u16 *);
 	void (*release)(struct e1000_hw *);
 	s32  (*write)(struct e1000_hw *, u16, u16, u16 *);
+	s32  (*update)(struct e1000_hw *);
+	s32  (*validate)(struct e1000_hw *);
 };
 
 struct e1000_info {
@@ -417,7 +424,6 @@
 
 struct e1000_nvm_info {
 	struct e1000_nvm_operations ops;
-
 	enum e1000_nvm_type type;
 	enum e1000_nvm_override override;
 
@@ -483,6 +489,7 @@
 struct e1000_dev_spec_82575 {
 	bool sgmii_active;
 	bool global_device_reset;
+	bool eee_disable;
 };
 
 struct e1000_hw {
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_mac.c linux-libre-2.6.39-gnu/drivers/net/igb/e1000_mac.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,7 +181,7 @@
  *  address and must override the actual permanent MAC address.  If an
  *  alternate MAC address is fopund it is saved in the hw struct and
  *  prgrammed into RAR0 and the cuntion returns success, otherwise the
- *  fucntion returns an error.
+ *  function returns an error.
  **/
 s32 igb_check_alt_mac_addr(struct e1000_hw *hw)
 {
@@ -982,7 +982,7 @@
 }
 
 /**
- *  igb_get_speed_and_duplex_copper - Retreive current speed/duplex
+ *  igb_get_speed_and_duplex_copper - Retrieve current speed/duplex
  *  @hw: pointer to the HW structure
  *  @speed: stores the current speed
  *  @duplex: stores the current duplex
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_mbx.c linux-libre-2.6.39-gnu/drivers/net/igb/e1000_mbx.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_mbx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_mbx.c	2011-05-19 00:06:34.000000000 -0400
@@ -422,26 +422,24 @@
 {
 	struct e1000_mbx_info *mbx = &hw->mbx;
 
-	if (hw->mac.type == e1000_82576) {
-		mbx->timeout = 0;
-		mbx->usec_delay = 0;
+	mbx->timeout = 0;
+	mbx->usec_delay = 0;
 
-		mbx->size = E1000_VFMAILBOX_SIZE;
+	mbx->size = E1000_VFMAILBOX_SIZE;
 
-		mbx->ops.read = igb_read_mbx_pf;
-		mbx->ops.write = igb_write_mbx_pf;
-		mbx->ops.read_posted = igb_read_posted_mbx;
-		mbx->ops.write_posted = igb_write_posted_mbx;
-		mbx->ops.check_for_msg = igb_check_for_msg_pf;
-		mbx->ops.check_for_ack = igb_check_for_ack_pf;
-		mbx->ops.check_for_rst = igb_check_for_rst_pf;
+	mbx->ops.read = igb_read_mbx_pf;
+	mbx->ops.write = igb_write_mbx_pf;
+	mbx->ops.read_posted = igb_read_posted_mbx;
+	mbx->ops.write_posted = igb_write_posted_mbx;
+	mbx->ops.check_for_msg = igb_check_for_msg_pf;
+	mbx->ops.check_for_ack = igb_check_for_ack_pf;
+	mbx->ops.check_for_rst = igb_check_for_rst_pf;
 
-		mbx->stats.msgs_tx = 0;
-		mbx->stats.msgs_rx = 0;
-		mbx->stats.reqs = 0;
-		mbx->stats.acks = 0;
-		mbx->stats.rsts = 0;
-	}
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 0;
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_nvm.c linux-libre-2.6.39-gnu/drivers/net/igb/e1000_nvm.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_nvm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_nvm.c	2011-05-19 00:06:34.000000000 -0400
@@ -318,6 +318,68 @@
 }
 
 /**
+ *  igb_read_nvm_spi - Read EEPROM's using SPI
+ *  @hw: pointer to the HW structure
+ *  @offset: offset of word in the EEPROM to read
+ *  @words: number of words to read
+ *  @data: word read from the EEPROM
+ *
+ *  Reads a 16 bit word from the EEPROM.
+ **/
+s32 igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data)
+{
+	struct e1000_nvm_info *nvm = &hw->nvm;
+	u32 i = 0;
+	s32 ret_val;
+	u16 word_in;
+	u8 read_opcode = NVM_READ_OPCODE_SPI;
+
+	/*
+	 * A check for invalid values:  offset too large, too many words,
+	 * and not enough words.
+	 */
+	if ((offset >= nvm->word_size) || (words > (nvm->word_size - offset)) ||
+	    (words == 0)) {
+		hw_dbg("nvm parameter(s) out of bounds\n");
+		ret_val = -E1000_ERR_NVM;
+		goto out;
+	}
+
+	ret_val = nvm->ops.acquire(hw);
+	if (ret_val)
+		goto out;
+
+	ret_val = igb_ready_nvm_eeprom(hw);
+	if (ret_val)
+		goto release;
+
+	igb_standby_nvm(hw);
+
+	if ((nvm->address_bits == 8) && (offset >= 128))
+		read_opcode |= NVM_A8_OPCODE_SPI;
+
+	/* Send the READ command (opcode + addr) */
+	igb_shift_out_eec_bits(hw, read_opcode, nvm->opcode_bits);
+	igb_shift_out_eec_bits(hw, (u16)(offset*2), nvm->address_bits);
+
+	/*
+	 * Read the data.  SPI NVMs increment the address with each byte
+	 * read and will roll over if reading beyond the end.  This allows
+	 * us to read the whole NVM from any offset
+	 */
+	for (i = 0; i < words; i++) {
+		word_in = igb_shift_in_eec_bits(hw, 16);
+		data[i] = (word_in >> 8) | (word_in << 8);
+	}
+
+release:
+	nvm->ops.release(hw);
+
+out:
+	return ret_val;
+}
+
+/**
  *  igb_read_nvm_eerd - Reads EEPROM using EERD register
  *  @hw: pointer to the HW structure
  *  @offset: offset of word in the EEPROM to read
@@ -353,7 +415,7 @@
 			break;
 
 		data[i] = (rd32(E1000_EERD) >>
-			   E1000_NVM_RW_REG_DATA);
+			E1000_NVM_RW_REG_DATA);
 	}
 
 out:
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_nvm.h linux-libre-2.6.39-gnu/drivers/net/igb/e1000_nvm.h
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_nvm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_nvm.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,7 @@
 s32  igb_read_part_string(struct e1000_hw *hw, u8 *part_num,
                           u32 part_num_size);
 s32  igb_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
+s32  igb_read_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words, u16 *data);
 s32  igb_validate_nvm_checksum(struct e1000_hw *hw);
 s32  igb_update_nvm_checksum(struct e1000_hw *hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_phy.c linux-libre-2.6.39-gnu/drivers/net/igb/e1000_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1421,7 +1421,7 @@
 }
 
 /**
- *  igb_check_downshift - Checks whether a downshift in speed occured
+ *  igb_check_downshift - Checks whether a downshift in speed occurred
  *  @hw: pointer to the HW structure
  *
  *  Success returns 0, Failure returns 1
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/e1000_regs.h linux-libre-2.6.39-gnu/drivers/net/igb/e1000_regs.h
--- linux-libre-2.6.38-gnu/drivers/net/igb/e1000_regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/e1000_regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -106,6 +106,19 @@
 
 #define E1000_RQDPC(_n) (0x0C030 + ((_n) * 0x40))
 
+/* DMA Coalescing registers */
+#define E1000_DMACR             0x02508 /* Control Register */
+#define E1000_DMCTXTH           0x03550 /* Transmit Threshold */
+#define E1000_DMCTLX            0x02514 /* Time to Lx Request */
+#define E1000_DMCRTRH           0x05DD0 /* Receive Packet Rate Threshold */
+#define E1000_DMCCNT            0x05DD4 /* Current Rx Count */
+#define E1000_FCRTC             0x02170 /* Flow Control Rx high watermark */
+#define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */
+
+/* TX Rate Limit Registers */
+#define E1000_RTTDQSEL	0x3604	/* Tx Desc Plane Queue Select - WO */
+#define E1000_RTTBCNRC	0x36B0	/* Tx BCN Rate-Scheduler Config - WO */
+
 /* Split and Replication RX Control - RW */
 #define E1000_RXPBS    0x02404  /* Rx Packet Buffer Size - RW */
 /*
@@ -324,4 +337,18 @@
 
 /* DMA Coalescing registers */
 #define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */
+
+/* Energy Efficient Ethernet "EEE" register */
+#define E1000_IPCNFG  0x0E38  /* Internal PHY Configuration */
+#define E1000_EEER    0x0E30  /* Energy Efficient Ethernet */
+
+/* Thermal Sensor Register */
+#define E1000_THSTAT    0x08110 /* Thermal Sensor Status */
+
+/* OS2BMC Registers */
+#define E1000_B2OSPC    0x08FE0 /* BMC2OS packets sent by BMC */
+#define E1000_B2OGPRC   0x04158 /* BMC2OS packets received by host */
+#define E1000_O2BGPTC   0x08FE4 /* OS2BMC packets received by BMC */
+#define E1000_O2BSPC    0x0415C /* OS2BMC packets transmitted by host */
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/igb_ethtool.c linux-libre-2.6.39-gnu/drivers/net/igb/igb_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/igb_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/igb_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,6 +86,10 @@
 	IGB_STAT("tx_smbus", stats.mgptc),
 	IGB_STAT("rx_smbus", stats.mgprc),
 	IGB_STAT("dropped_smbus", stats.mgpdc),
+	IGB_STAT("os2bmc_rx_by_bmc", stats.o2bgptc),
+	IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
+	IGB_STAT("os2bmc_tx_by_host", stats.o2bspc),
+	IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc),
 };
 
 #define IGB_NETDEV_STAT(_net_stat) { \
@@ -603,7 +607,10 @@
 	regs_buff[548] = rd32(E1000_TDFT);
 	regs_buff[549] = rd32(E1000_TDFHS);
 	regs_buff[550] = rd32(E1000_TDFPC);
-
+	regs_buff[551] = adapter->stats.o2bgptc;
+	regs_buff[552] = adapter->stats.b2ospc;
+	regs_buff[553] = adapter->stats.o2bspc;
+	regs_buff[554] = adapter->stats.b2ogprc;
 }
 
 static int igb_get_eeprom_len(struct net_device *netdev)
@@ -714,7 +721,7 @@
 	/* Update the checksum over the first part of the EEPROM if needed
 	 * and flush shadow RAM for 82573 controllers */
 	if ((ret_val == 0) && ((first_word <= NVM_CHECKSUM_REG)))
-		igb_update_nvm_checksum(hw);
+		hw->nvm.ops.update(hw);
 
 	kfree(eeprom_buff);
 	return ret_val;
@@ -727,8 +734,9 @@
 	char firmware_version[32];
 	u16 eeprom_data;
 
-	strncpy(drvinfo->driver,  igb_driver_name, 32);
-	strncpy(drvinfo->version, igb_driver_version, 32);
+	strncpy(drvinfo->driver,  igb_driver_name, sizeof(drvinfo->driver) - 1);
+	strncpy(drvinfo->version, igb_driver_version,
+		sizeof(drvinfo->version) - 1);
 
 	/* EEPROM image version # is reported as firmware version # for
 	 * 82575 controllers */
@@ -738,8 +746,10 @@
 		(eeprom_data & 0x0FF0) >> 4,
 		eeprom_data & 0x000F);
 
-	strncpy(drvinfo->fw_version, firmware_version, 32);
-	strncpy(drvinfo->bus_info, pci_name(adapter->pdev), 32);
+	strncpy(drvinfo->fw_version, firmware_version,
+		sizeof(drvinfo->fw_version) - 1);
+	strncpy(drvinfo->bus_info, pci_name(adapter->pdev),
+		sizeof(drvinfo->bus_info) - 1);
 	drvinfo->n_stats = IGB_STATS_LEN;
 	drvinfo->testinfo_len = IGB_TEST_LEN;
 	drvinfo->regdump_len = igb_get_regs_len(netdev);
@@ -1070,7 +1080,7 @@
 		{0x5A5A5A5A, 0xA5A5A5A5, 0x00000000, 0xFFFFFFFF};
 	for (pat = 0; pat < ARRAY_SIZE(_test); pat++) {
 		wr32(reg, (_test[pat] & write));
-		val = rd32(reg);
+		val = rd32(reg) & mask;
 		if (val != (_test[pat] & write & mask)) {
 			dev_err(&adapter->pdev->dev, "pattern test reg %04X "
 				"failed: got 0x%08X expected 0x%08X\n",
@@ -1999,6 +2009,12 @@
 	if ((adapter->flags & IGB_FLAG_QUEUE_PAIRS) && ec->tx_coalesce_usecs)
 		return -EINVAL;
 
+	/* If ITR is disabled, disable DMAC */
+	if (ec->rx_coalesce_usecs == 0) {
+		if (adapter->flags & IGB_FLAG_DMAC)
+			adapter->flags &= ~IGB_FLAG_DMAC;
+	}
+
 	/* convert to rate of irq's per second */
 	if (ec->rx_coalesce_usecs && ec->rx_coalesce_usecs <= 3)
 		adapter->rx_itr_setting = ec->rx_coalesce_usecs;
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/igb.h linux-libre-2.6.39-gnu/drivers/net/igb/igb.h
--- linux-libre-2.6.38-gnu/drivers/net/igb/igb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/igb.h	2011-05-19 00:06:34.000000000 -0400
@@ -77,6 +77,7 @@
 	unsigned long last_nack;
 	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
 	u16 pf_qos;
+	u16 tx_rate;
 };
 
 #define IGB_VF_FLAG_CTS            0x00000001 /* VF is clear to send data */
@@ -323,6 +324,7 @@
 	u16 rx_ring_count;
 	unsigned int vfs_allocated_count;
 	struct vf_data_storage *vf_data;
+	int vf_rate_link_speed;
 	u32 rss_queues;
 	u32 wvbr;
 };
@@ -331,6 +333,12 @@
 #define IGB_FLAG_DCA_ENABLED       (1 << 1)
 #define IGB_FLAG_QUAD_PORT_A       (1 << 2)
 #define IGB_FLAG_QUEUE_PAIRS       (1 << 3)
+#define IGB_FLAG_DMAC              (1 << 4)
+
+/* DMA Coalescing defines */
+#define IGB_MIN_TXPBSIZE           20408
+#define IGB_TX_BUF_4096            4096
+#define IGB_DMCTLX_DCFLUSH_DIS     0x80000000  /* Disable DMA Coal Flush */
 
 #define IGB_82576_TSYNC_SHIFT 19
 #define IGB_82580_TSYNC_SHIFT 24
diff -druN linux-libre-2.6.38-gnu/drivers/net/igb/igb_main.c linux-libre-2.6.39-gnu/drivers/net/igb/igb_main.c
--- linux-libre-2.6.38-gnu/drivers/net/igb/igb_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igb/igb_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,12 +50,17 @@
 #endif
 #include "igb.h"
 
-#define DRV_VERSION "2.1.0-k2"
+#define MAJ 3
+#define MIN 0
+#define BUILD 6
+#define KFIX 2
+#define DRV_VERSION __stringify(MAJ) "." __stringify(MIN) "." \
+__stringify(BUILD) "-k" __stringify(KFIX)
 char igb_driver_name[] = "igb";
 char igb_driver_version[] = DRV_VERSION;
 static const char igb_driver_string[] =
 				"Intel(R) Gigabit Ethernet Network Driver";
-static const char igb_copyright[] = "Copyright (c) 2007-2009 Intel Corporation.";
+static const char igb_copyright[] = "Copyright (c) 2007-2011 Intel Corporation.";
 
 static const struct e1000_info *igb_info_tbl[] = {
 	[board_82575] = &e1000_82575_info,
@@ -68,6 +73,7 @@
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_I350_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_FIBER), board_82575 },
+	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_QUAD_FIBER), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SERDES), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_SGMII), board_82575 },
 	{ PCI_VDEVICE(INTEL, E1000_DEV_ID_82580_COPPER_DUAL), board_82575 },
@@ -100,6 +106,7 @@
 static void igb_setup_mrqc(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
 static void __devexit igb_remove(struct pci_dev *pdev);
+static void igb_init_hw_timer(struct igb_adapter *adapter);
 static int igb_sw_init(struct igb_adapter *);
 static int igb_open(struct net_device *);
 static int igb_close(struct net_device *);
@@ -149,6 +156,7 @@
 static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
 static int igb_ndo_get_vf_config(struct net_device *netdev, int vf,
 				 struct ifla_vf_info *ivi);
+static void igb_check_vf_rate_limit(struct igb_adapter *);
 
 #ifdef CONFIG_PM
 static int igb_suspend(struct pci_dev *, pm_message_t);
@@ -192,7 +200,7 @@
 	.probe    = igb_probe,
 	.remove   = __devexit_p(igb_remove),
 #ifdef CONFIG_PM
-	/* Power Managment Hooks */
+	/* Power Management Hooks */
 	.suspend  = igb_suspend,
 	.resume   = igb_resume,
 #endif
@@ -1672,7 +1680,58 @@
 
 	if (hw->mac.ops.init_hw(hw))
 		dev_err(&pdev->dev, "Hardware Error\n");
+	if (hw->mac.type > e1000_82580) {
+		if (adapter->flags & IGB_FLAG_DMAC) {
+			u32 reg;
+
+			/*
+			 * DMA Coalescing high water mark needs to be higher
+			 * than * the * Rx threshold.  The Rx threshold is
+			 * currently * pba - 6, so we * should use a high water
+			 * mark of pba * - 4. */
+			hwm = (pba - 4) << 10;
+
+			reg = (((pba-6) << E1000_DMACR_DMACTHR_SHIFT)
+			       & E1000_DMACR_DMACTHR_MASK);
+
+			/* transition to L0x or L1 if available..*/
+			reg |= (E1000_DMACR_DMAC_EN | E1000_DMACR_DMAC_LX_MASK);
+
+			/* watchdog timer= +-1000 usec in 32usec intervals */
+			reg |= (1000 >> 5);
+			wr32(E1000_DMACR, reg);
+
+			/* no lower threshold to disable coalescing(smart fifb)
+			 * -UTRESH=0*/
+			wr32(E1000_DMCRTRH, 0);
+
+			/* set hwm to PBA -  2 * max frame size */
+			wr32(E1000_FCRTC, hwm);
 
+			/*
+			 * This sets the time to wait before requesting tran-
+			 * sition to * low power state to number of usecs needed
+			 * to receive 1 512 * byte frame at gigabit line rate
+			 */
+			reg = rd32(E1000_DMCTLX);
+			reg |= IGB_DMCTLX_DCFLUSH_DIS;
+
+			/* Delay 255 usec before entering Lx state. */
+			reg |= 0xFF;
+			wr32(E1000_DMCTLX, reg);
+
+			/* free space in Tx packet buffer to wake from DMAC */
+			wr32(E1000_DMCTXTH,
+			     (IGB_MIN_TXPBSIZE -
+			     (IGB_TX_BUF_4096 + adapter->max_frame_size))
+			     >> 6);
+
+			/* make low power state decision controlled by DMAC */
+			reg = rd32(E1000_PCIEMISC);
+			reg |= E1000_PCIEMISC_LX_DECISION;
+			wr32(E1000_PCIEMISC, reg);
+		} /* end if IGB_FLAG_DMAC set */
+	}
 	if (hw->mac.type == e1000_82580) {
 		u32 reg = rd32(E1000_PCIEMISC);
 		wr32(E1000_PCIEMISC,
@@ -1882,7 +1941,7 @@
 	hw->mac.ops.reset_hw(hw);
 
 	/* make sure the NVM is good */
-	if (igb_validate_nvm_checksum(hw) < 0) {
+	if (hw->nvm.ops.validate(hw) < 0) {
 		dev_err(&pdev->dev, "The NVM Checksum Is Not Valid\n");
 		err = -EIO;
 		goto err_eeprom;
@@ -1990,6 +2049,9 @@
 	}
 
 #endif
+	/* do hw tstamp init after resetting */
+	igb_init_hw_timer(adapter);
+
 	dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
 	/* print bus type/speed/width info */
 	dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
@@ -2012,7 +2074,13 @@
 		adapter->msix_entries ? "MSI-X" :
 		(adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy",
 		adapter->num_rx_queues, adapter->num_tx_queues);
-
+	switch (hw->mac.type) {
+	case e1000_i350:
+		igb_set_eee_i350(hw);
+		break;
+	default:
+		break;
+	}
 	return 0;
 
 err_register:
@@ -2149,6 +2217,9 @@
 			random_ether_addr(mac_addr);
 			igb_set_vf_mac(adapter, i, mac_addr);
 		}
+		/* DMA Coalescing is not supported in IOV mode. */
+		if (adapter->flags & IGB_FLAG_DMAC)
+			adapter->flags &= ~IGB_FLAG_DMAC;
 	}
 #endif /* CONFIG_PCI_IOV */
 }
@@ -2221,7 +2292,7 @@
 		/**
 		 * Scale the NIC clock cycle by a large factor so that
 		 * relatively small clock corrections can be added or
-		 * substracted at each clock tick. The drawbacks of a large
+		 * subtracted at each clock tick. The drawbacks of a large
 		 * factor are a) that the clock register overflows more quickly
 		 * (not such a big deal) and b) that the increment per tick has
 		 * to fit into 24 bits.  As a result we need to use a shift of
@@ -2286,9 +2357,19 @@
 
 	spin_lock_init(&adapter->stats64_lock);
 #ifdef CONFIG_PCI_IOV
-	if (hw->mac.type == e1000_82576)
-		adapter->vfs_allocated_count = (max_vfs > 7) ? 7 : max_vfs;
-
+	switch (hw->mac.type) {
+	case e1000_82576:
+	case e1000_i350:
+		if (max_vfs > 7) {
+			dev_warn(&pdev->dev,
+				 "Maximum of 7 VFs per PF, using max\n");
+			adapter->vfs_allocated_count = 7;
+		} else
+			adapter->vfs_allocated_count = max_vfs;
+		break;
+	default:
+		break;
+	}
 #endif /* CONFIG_PCI_IOV */
 	adapter->rss_queues = min_t(u32, IGB_MAX_RX_QUEUES, num_online_cpus());
 
@@ -2307,12 +2388,14 @@
 		return -ENOMEM;
 	}
 
-	igb_init_hw_timer(adapter);
 	igb_probe_vfs(adapter);
 
 	/* Explicitly disable IRQ since the NIC can be in any state. */
 	igb_irq_disable(adapter);
 
+	if (hw->mac.type == e1000_i350)
+		adapter->flags &= ~IGB_FLAG_DMAC;
+
 	set_bit(__IGB_DOWN, &adapter->state);
 	return 0;
 }
@@ -3326,7 +3409,7 @@
 		} else {
 			/*
 			 * Write addresses to the MTA, if the attempt fails
-			 * then we should just turn on promiscous mode so
+			 * then we should just turn on promiscuous mode so
 			 * that we can at least receive multicast traffic
 			 */
 			count = igb_write_mc_addr_list(netdev);
@@ -3340,7 +3423,7 @@
 		/*
 		 * Write addresses to available RAR registers, if there is not
 		 * sufficient space to store all the addresses then enable
-		 * unicast promiscous mode
+		 * unicast promiscuous mode
 		 */
 		count = igb_write_uc_addr_list(netdev);
 		if (count < 0) {
@@ -3467,7 +3550,7 @@
                                                    watchdog_task);
 	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
-	u32 link;
+	u32 link, ctrl_ext, thstat;
 	int i;
 
 	link = igb_has_link(adapter);
@@ -3491,6 +3574,25 @@
 			       ((ctrl & E1000_CTRL_RFCE) ?  "RX" :
 			       ((ctrl & E1000_CTRL_TFCE) ?  "TX" : "None")));
 
+			/* check for thermal sensor event on i350,
+			 * copper only */
+			if (hw->mac.type == e1000_i350) {
+				thstat = rd32(E1000_THSTAT);
+				ctrl_ext = rd32(E1000_CTRL_EXT);
+				if ((hw->phy.media_type ==
+				     e1000_media_type_copper) && !(ctrl_ext &
+				     E1000_CTRL_EXT_LINK_MODE_SGMII)) {
+					if (thstat &
+					    E1000_THSTAT_LINK_THROTTLE) {
+						printk(KERN_INFO "igb: %s The "
+						       "network adapter link "
+						       "speed was downshifted "
+						       "because it "
+						       "overheated.\n",
+						       netdev->name);
+					}
+				}
+			}
 			/* adjust timeout factor according to speed/duplex */
 			adapter->tx_timeout_factor = 1;
 			switch (adapter->link_speed) {
@@ -3505,6 +3607,7 @@
 			netif_carrier_on(netdev);
 
 			igb_ping_all_vfs(adapter);
+			igb_check_vf_rate_limit(adapter);
 
 			/* link state has changed, schedule phy info update */
 			if (!test_bit(__IGB_DOWN, &adapter->state))
@@ -3515,6 +3618,22 @@
 		if (netif_carrier_ok(netdev)) {
 			adapter->link_speed = 0;
 			adapter->link_duplex = 0;
+			/* check for thermal sensor event on i350
+			 * copper only*/
+			if (hw->mac.type == e1000_i350) {
+				thstat = rd32(E1000_THSTAT);
+				ctrl_ext = rd32(E1000_CTRL_EXT);
+				if ((hw->phy.media_type ==
+				     e1000_media_type_copper) && !(ctrl_ext &
+				     E1000_CTRL_EXT_LINK_MODE_SGMII)) {
+					if (thstat & E1000_THSTAT_PWR_DOWN) {
+						printk(KERN_ERR "igb: %s The "
+						"network adapter was stopped "
+						"because it overheated.\n",
+						netdev->name);
+					}
+				}
+			}
 			/* Links status message must follow this format */
 			printk(KERN_INFO "igb: %s NIC Link is Down\n",
 			       netdev->name);
@@ -4198,7 +4317,7 @@
 
 	/*
 	 * count reflects descriptors mapped, if 0 or less then mapping error
-	 * has occured and we need to rewind the descriptor queue
+	 * has occurred and we need to rewind the descriptor queue
 	 */
 	count = igb_tx_map_adv(tx_ring, skb, first);
 	if (!count) {
@@ -4547,6 +4666,15 @@
 	adapter->stats.mgptc += rd32(E1000_MGTPTC);
 	adapter->stats.mgprc += rd32(E1000_MGTPRC);
 	adapter->stats.mgpdc += rd32(E1000_MGTPDC);
+
+	/* OS2BMC Stats */
+	reg = rd32(E1000_MANC);
+	if (reg & E1000_MANC_EN_BMC2OS) {
+		adapter->stats.o2bgptc += rd32(E1000_O2BGPTC);
+		adapter->stats.o2bspc += rd32(E1000_O2BSPC);
+		adapter->stats.b2ospc += rd32(E1000_B2OSPC);
+		adapter->stats.b2ogprc += rd32(E1000_B2OGPRC);
+	}
 }
 
 static irqreturn_t igb_msix_other(int irq, void *data)
@@ -5224,8 +5352,8 @@
  *  The unicast table address is a register array of 32-bit registers.
  *  The table is meant to be used in a way similar to how the MTA is used
  *  however due to certain limitations in the hardware it is necessary to
- *  set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscous
- *  enable bit to allow vlan tag stripping when promiscous mode is enabled
+ *  set all the hash bits to 1 and use the VMOLR ROPE bit as a promiscuous
+ *  enable bit to allow vlan tag stripping when promiscuous mode is enabled
  **/
 static void igb_set_uta(struct igb_adapter *adapter)
 {
@@ -6593,9 +6721,91 @@
 	return igb_set_vf_mac(adapter, vf, mac);
 }
 
+static int igb_link_mbps(int internal_link_speed)
+{
+	switch (internal_link_speed) {
+	case SPEED_100:
+		return 100;
+	case SPEED_1000:
+		return 1000;
+	default:
+		return 0;
+	}
+}
+
+static void igb_set_vf_rate_limit(struct e1000_hw *hw, int vf, int tx_rate,
+				  int link_speed)
+{
+	int rf_dec, rf_int;
+	u32 bcnrc_val;
+
+	if (tx_rate != 0) {
+		/* Calculate the rate factor values to set */
+		rf_int = link_speed / tx_rate;
+		rf_dec = (link_speed - (rf_int * tx_rate));
+		rf_dec = (rf_dec * (1<<E1000_RTTBCNRC_RF_INT_SHIFT)) / tx_rate;
+
+		bcnrc_val = E1000_RTTBCNRC_RS_ENA;
+		bcnrc_val |= ((rf_int<<E1000_RTTBCNRC_RF_INT_SHIFT) &
+		               E1000_RTTBCNRC_RF_INT_MASK);
+		bcnrc_val |= (rf_dec & E1000_RTTBCNRC_RF_DEC_MASK);
+	} else {
+		bcnrc_val = 0;
+	}
+
+	wr32(E1000_RTTDQSEL, vf); /* vf X uses queue X */
+	wr32(E1000_RTTBCNRC, bcnrc_val);
+}
+
+static void igb_check_vf_rate_limit(struct igb_adapter *adapter)
+{
+	int actual_link_speed, i;
+	bool reset_rate = false;
+
+	/* VF TX rate limit was not set or not supported */
+	if ((adapter->vf_rate_link_speed == 0) ||
+	    (adapter->hw.mac.type != e1000_82576))
+		return;
+
+	actual_link_speed = igb_link_mbps(adapter->link_speed);
+	if (actual_link_speed != adapter->vf_rate_link_speed) {
+		reset_rate = true;
+		adapter->vf_rate_link_speed = 0;
+		dev_info(&adapter->pdev->dev,
+		         "Link speed has been changed. VF Transmit "
+		         "rate is disabled\n");
+	}
+
+	for (i = 0; i < adapter->vfs_allocated_count; i++) {
+		if (reset_rate)
+			adapter->vf_data[i].tx_rate = 0;
+
+		igb_set_vf_rate_limit(&adapter->hw, i,
+		                      adapter->vf_data[i].tx_rate,
+		                      actual_link_speed);
+	}
+}
+
 static int igb_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
 {
-	return -EOPNOTSUPP;
+	struct igb_adapter *adapter = netdev_priv(netdev);
+	struct e1000_hw *hw = &adapter->hw;
+	int actual_link_speed;
+
+	if (hw->mac.type != e1000_82576)
+		return -EOPNOTSUPP;
+
+	actual_link_speed = igb_link_mbps(adapter->link_speed);
+	if ((vf >= adapter->vfs_allocated_count) ||
+	    (!(rd32(E1000_STATUS) & E1000_STATUS_LU)) ||
+	    (tx_rate < 0) || (tx_rate > actual_link_speed))
+		return -EINVAL;
+
+	adapter->vf_rate_link_speed = actual_link_speed;
+	adapter->vf_data[vf].tx_rate = (u16)tx_rate;
+	igb_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed);
+
+	return 0;
 }
 
 static int igb_ndo_get_vf_config(struct net_device *netdev,
@@ -6606,7 +6816,7 @@
 		return -EINVAL;
 	ivi->vf = vf;
 	memcpy(&ivi->mac, adapter->vf_data[vf].vf_mac_addresses, ETH_ALEN);
-	ivi->tx_rate = 0;
+	ivi->tx_rate = adapter->vf_data[vf].tx_rate;
 	ivi->vlan = adapter->vf_data[vf].pf_vlan;
 	ivi->qos = adapter->vf_data[vf].pf_qos;
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/igbvf/ethtool.c linux-libre-2.6.39-gnu/drivers/net/igbvf/ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/igbvf/ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igbvf/ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -201,13 +201,11 @@
 	struct igbvf_adapter *adapter = netdev_priv(netdev);
 	struct e1000_hw *hw = &adapter->hw;
 	u32 *regs_buff = p;
-	u8 revision_id;
 
 	memset(p, 0, IGBVF_REGS_LEN * sizeof(u32));
 
-	pci_read_config_byte(adapter->pdev, PCI_REVISION_ID, &revision_id);
-
-	regs->version = (1 << 24) | (revision_id << 16) | adapter->pdev->device;
+	regs->version = (1 << 24) | (adapter->pdev->revision << 16) |
+			adapter->pdev->device;
 
 	regs_buff[0] = er32(CTRL);
 	regs_buff[1] = er32(STATUS);
diff -druN linux-libre-2.6.38-gnu/drivers/net/igbvf/igbvf.h linux-libre-2.6.39-gnu/drivers/net/igbvf/igbvf.h
--- linux-libre-2.6.38-gnu/drivers/net/igbvf/igbvf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igbvf/igbvf.h	2011-05-19 00:06:34.000000000 -0400
@@ -201,9 +201,6 @@
 	unsigned int restart_queue;
 	u32 txd_cmd;
 
-	bool detect_tx_hung;
-	u8 tx_timeout_factor;
-
 	u32 tx_int_delay;
 	u32 tx_abs_int_delay;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/igbvf/netdev.c linux-libre-2.6.39-gnu/drivers/net/igbvf/netdev.c
--- linux-libre-2.6.38-gnu/drivers/net/igbvf/netdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/igbvf/netdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -396,35 +396,6 @@
 	buffer_info->time_stamp = 0;
 }
 
-static void igbvf_print_tx_hang(struct igbvf_adapter *adapter)
-{
-	struct igbvf_ring *tx_ring = adapter->tx_ring;
-	unsigned int i = tx_ring->next_to_clean;
-	unsigned int eop = tx_ring->buffer_info[i].next_to_watch;
-	union e1000_adv_tx_desc *eop_desc = IGBVF_TX_DESC_ADV(*tx_ring, eop);
-
-	/* detected Tx unit hang */
-	dev_err(&adapter->pdev->dev,
-	        "Detected Tx Unit Hang:\n"
-	        "  TDH                  <%x>\n"
-	        "  TDT                  <%x>\n"
-	        "  next_to_use          <%x>\n"
-	        "  next_to_clean        <%x>\n"
-	        "buffer_info[next_to_clean]:\n"
-	        "  time_stamp           <%lx>\n"
-	        "  next_to_watch        <%x>\n"
-	        "  jiffies              <%lx>\n"
-	        "  next_to_watch.status <%x>\n",
-	        readl(adapter->hw.hw_addr + tx_ring->head),
-	        readl(adapter->hw.hw_addr + tx_ring->tail),
-	        tx_ring->next_to_use,
-	        tx_ring->next_to_clean,
-	        tx_ring->buffer_info[eop].time_stamp,
-	        eop,
-	        jiffies,
-	        eop_desc->wb.status);
-}
-
 /**
  * igbvf_setup_tx_resources - allocate Tx resources (Descriptors)
  * @adapter: board private structure
@@ -771,7 +742,6 @@
 static bool igbvf_clean_tx_irq(struct igbvf_ring *tx_ring)
 {
 	struct igbvf_adapter *adapter = tx_ring->adapter;
-	struct e1000_hw *hw = &adapter->hw;
 	struct net_device *netdev = adapter->netdev;
 	struct igbvf_buffer *buffer_info;
 	struct sk_buff *skb;
@@ -832,22 +802,6 @@
 		}
 	}
 
-	if (adapter->detect_tx_hung) {
-		/* Detect a transmit hang in hardware, this serializes the
-		 * check with the clearing of time_stamp and movement of i */
-		adapter->detect_tx_hung = false;
-		if (tx_ring->buffer_info[i].time_stamp &&
-		    time_after(jiffies, tx_ring->buffer_info[i].time_stamp +
-		               (adapter->tx_timeout_factor * HZ)) &&
-		    !(er32(STATUS) & E1000_STATUS_TXOFF)) {
-
-			tx_desc = IGBVF_TX_DESC_ADV(*tx_ring, i);
-			/* detected Tx unit hang */
-			igbvf_print_tx_hang(adapter);
-
-			netif_stop_queue(netdev);
-		}
-	}
 	adapter->net_stats.tx_bytes += total_bytes;
 	adapter->net_stats.tx_packets += total_packets;
 	return count < tx_ring->count;
@@ -1863,17 +1817,6 @@
 			                          &adapter->link_duplex);
 			igbvf_print_link_info(adapter);
 
-			/* adjust timeout factor according to speed/duplex */
-			adapter->tx_timeout_factor = 1;
-			switch (adapter->link_speed) {
-			case SPEED_10:
-				adapter->tx_timeout_factor = 16;
-				break;
-			case SPEED_100:
-				/* maybe add some timeout factor ? */
-				break;
-			}
-
 			netif_carrier_on(netdev);
 			netif_wake_queue(netdev);
 		}
@@ -1907,9 +1850,6 @@
 	/* Cause software interrupt to ensure Rx ring is cleaned */
 	ew32(EICS, adapter->rx_ring->eims_value);
 
-	/* Force detection of hung controller every watchdog period */
-	adapter->detect_tx_hung = 1;
-
 	/* Reset the timer */
 	if (!test_bit(__IGBVF_DOWN, &adapter->state))
 		mod_timer(&adapter->watchdog_timer,
@@ -2287,7 +2227,7 @@
 
 	/*
 	 * count reflects descriptors mapped, if 0 then mapping error
-	 * has occured and we need to rewind the descriptor queue
+	 * has occurred and we need to rewind the descriptor queue
 	 */
 	count = igbvf_tx_map_adv(adapter, tx_ring, skb, first);
 
@@ -2699,8 +2639,7 @@
 	hw->device_id = pdev->device;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
-
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+	hw->revision_id = pdev->revision;
 
 	err = -EIO;
 	adapter->hw.hw_addr = ioremap(pci_resource_start(pdev, 0),
diff -druN linux-libre-2.6.38-gnu/drivers/net/ipg.c linux-libre-2.6.39-gnu/drivers/net/ipg.c
--- linux-libre-2.6.38-gnu/drivers/net/ipg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ipg.c	2011-05-19 00:06:34.000000000 -0400
@@ -486,14 +486,14 @@
 	phyctrl = ipg_r8(PHY_CTRL);
 	mac_ctrl_val = ipg_r32(MAC_CTRL);
 
-	/* Set flags for use in resolving auto-negotation, assuming
+	/* Set flags for use in resolving auto-negotiation, assuming
 	 * non-1000Mbps, half duplex, no flow control.
 	 */
 	fullduplex = 0;
 	txflowcontrol = 0;
 	rxflowcontrol = 0;
 
-	/* To accomodate a problem in 10Mbps operation,
+	/* To accommodate a problem in 10Mbps operation,
 	 * set a global flag if PHY running in 10Mbps mode.
 	 */
 	sp->tenmbpsmode = 0;
@@ -846,7 +846,7 @@
 }
 
 /*
- * Free all transmit buffers which have already been transfered
+ * Free all transmit buffers which have already been transferred
  * via DMA to the IPG.
  */
 static void ipg_nic_txfree(struct net_device *dev)
@@ -920,7 +920,7 @@
 
 /*
  * For TxComplete interrupts, free all transmit
- * buffers which have already been transfered via DMA
+ * buffers which have already been transferred via DMA
  * to the IPG.
  */
 static void ipg_nic_txcleanup(struct net_device *dev)
@@ -1141,13 +1141,13 @@
 
 		/* Increment detailed receive error statistics. */
 		if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
-			IPG_DEBUG_MSG("RX FIFO overrun occured.\n");
+			IPG_DEBUG_MSG("RX FIFO overrun occurred.\n");
 
 			sp->stats.rx_fifo_errors++;
 		}
 
 		if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
-			IPG_DEBUG_MSG("RX runt occured.\n");
+			IPG_DEBUG_MSG("RX runt occurred.\n");
 			sp->stats.rx_length_errors++;
 		}
 
@@ -1156,7 +1156,7 @@
 		 */
 
 		if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
-			IPG_DEBUG_MSG("RX alignment error occured.\n");
+			IPG_DEBUG_MSG("RX alignment error occurred.\n");
 			sp->stats.rx_frame_errors++;
 		}
 
@@ -1421,12 +1421,12 @@
 
 			/* Increment detailed receive error statistics. */
 			if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXFIFOOVERRUN) {
-				IPG_DEBUG_MSG("RX FIFO overrun occured.\n");
+				IPG_DEBUG_MSG("RX FIFO overrun occurred.\n");
 				sp->stats.rx_fifo_errors++;
 			}
 
 			if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXRUNTFRAME) {
-				IPG_DEBUG_MSG("RX runt occured.\n");
+				IPG_DEBUG_MSG("RX runt occurred.\n");
 				sp->stats.rx_length_errors++;
 			}
 
@@ -1436,7 +1436,7 @@
 			 */
 
 			if (le64_to_cpu(rxfd->rfs) & IPG_RFS_RXALIGNMENTERROR) {
-				IPG_DEBUG_MSG("RX alignment error occured.\n");
+				IPG_DEBUG_MSG("RX alignment error occurred.\n");
 				sp->stats.rx_frame_errors++;
 			}
 
@@ -1460,7 +1460,7 @@
 			}
 		} else {
 
-			/* Adjust the new buffer length to accomodate the size
+			/* Adjust the new buffer length to accommodate the size
 			 * of the received frame.
 			 */
 			skb_put(skb, framelen);
@@ -1488,7 +1488,7 @@
 	}
 
 	/*
-	 * If there are more RFDs to proces and the allocated amount of RFD
+	 * If there are more RFDs to process and the allocated amount of RFD
 	 * processing time has expired, assert Interrupt Requested to make
 	 * sure we come back to process the remaining RFDs.
 	 */
@@ -1886,7 +1886,7 @@
 	/* Request TxComplete interrupts at an interval defined
 	 * by the constant IPG_FRAMESBETWEENTXCOMPLETES.
 	 * Request TxComplete interrupt for every frame
-	 * if in 10Mbps mode to accomodate problem with 10Mbps
+	 * if in 10Mbps mode to accommodate problem with 10Mbps
 	 * processing.
 	 */
 	if (sp->tenmbpsmode)
@@ -2025,7 +2025,6 @@
 
 	if (phyaddr != 0x1f) {
 		u16 mii_phyctrl, mii_1000cr;
-		u8 revisionid = 0;
 
 		mii_1000cr  = mdio_read(dev, phyaddr, MII_CTRL1000);
 		mii_1000cr |= ADVERTISE_1000FULL | ADVERTISE_1000HALF |
@@ -2035,8 +2034,7 @@
 		mii_phyctrl = mdio_read(dev, phyaddr, MII_BMCR);
 
 		/* Set default phyparam */
-		pci_read_config_byte(sp->pdev, PCI_REVISION_ID, &revisionid);
-		ipg_set_phy_default_param(revisionid, dev, phyaddr);
+		ipg_set_phy_default_param(sp->pdev->revision, dev, phyaddr);
 
 		/* Reset PHY */
 		mii_phyctrl |= BMCR_RESET | BMCR_ANRESTART;
@@ -2100,7 +2098,7 @@
 	struct ipg_nic_private *sp = netdev_priv(dev);
 	int err;
 
-	/* Function to accomodate changes to Maximum Transfer Unit
+	/* Function to accommodate changes to Maximum Transfer Unit
 	 * (or MTU) of IPG NIC. Cannot use default function since
 	 * the default will not allow for MTU > 1500 bytes.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/ali-ircc.c linux-libre-2.6.39-gnu/drivers/net/irda/ali-ircc.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/ali-ircc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/ali-ircc.c	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
 static int  ali_ircc_init_43(ali_chip_t *chip, chipio_t *info);
 static int  ali_ircc_init_53(ali_chip_t *chip, chipio_t *info);
 
-/* These are the currently known ALi sourth-bridge chipsets, the only one difference
+/* These are the currently known ALi south-bridge chipsets, the only one difference
  * is that M1543C doesn't support HP HDSL-3600
  */
 static ali_chip_t chips[] =
@@ -1108,7 +1108,7 @@
 	outb(lcr,		  iobase+UART_LCR); /* Set 8N1	*/
 	outb(fcr,		  iobase+UART_FCR); /* Enable FIFO's */
 
-	/* without this, the conection will be broken after come back from FIR speed,
+	/* without this, the connection will be broken after come back from FIR speed,
 	   but with this, the SIR connection is harder to established */
 	outb((UART_MCR_DTR | UART_MCR_RTS | UART_MCR_OUT2), iobase+UART_MCR);
 	
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/donauboe.c linux-libre-2.6.39-gnu/drivers/net/irda/donauboe.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/donauboe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/donauboe.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
 /* do_probe module parameter Enable this code */
 /* Probe code is very useful for understanding how the hardware works */
 /* Use it with various combinations of TT_LEN, RX_LEN */
-/* Strongly recomended, disable if the probe fails on your machine */
+/* Strongly recommended, disable if the probe fails on your machine */
 /* and send me <james@fishsoup.dhs.org> the output of dmesg */
 #define USE_PROBE 1
 #undef  USE_PROBE
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/donauboe.h linux-libre-2.6.39-gnu/drivers/net/irda/donauboe.h
--- linux-libre-2.6.38-gnu/drivers/net/irda/donauboe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/donauboe.h	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
 
 /* The documentation for this chip is allegedly released         */
 /* However I have not seen it, not have I managed to contact     */
-/* anyone who has. HOWEVER the chip bears a striking resemblence */
+/* anyone who has. HOWEVER the chip bears a striking resemblance */
 /* to the IrDA controller in the Toshiba RISC TMPR3922 chip      */
 /* the documentation for this is freely available at             */
 /* http://www.madingley.org/james/resources/toshoboe/TMPR3922.pdf */
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/girbil-sir.c linux-libre-2.6.39-gnu/drivers/net/irda/girbil-sir.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/girbil-sir.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/girbil-sir.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 /* Control register 1 */
 #define GIRBIL_TXEN    0x01 /* Enable transmitter */
 #define GIRBIL_RXEN    0x02 /* Enable receiver */
-#define GIRBIL_ECAN    0x04 /* Cancel self emmited data */
+#define GIRBIL_ECAN    0x04 /* Cancel self emitted data */
 #define GIRBIL_ECHO    0x08 /* Echo control characters */
 
 /* LED Current Register (0x2) */
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/irda-usb.c linux-libre-2.6.39-gnu/drivers/net/irda/irda-usb.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/irda-usb.c	2012-03-24 01:09:42.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/irda-usb.c	2012-03-24 03:31:47.000000000 -0400
@@ -370,7 +370,7 @@
 	/* urb is now available */
 	//urb->status = 0; -> tested above
 
-	/* New speed and xbof is now commited in hardware */
+	/* New speed and xbof is now committed in hardware */
 	self->new_speed = -1;
 	self->new_xbofs = -1;
 
@@ -602,7 +602,7 @@
 			IRDA_DEBUG(1, "%s(), Changing speed now...\n", __func__);
 			irda_usb_change_speed_xbofs(self);
 		} else {
-			/* New speed and xbof is now commited in hardware */
+			/* New speed and xbof is now committed in hardware */
 			self->new_speed = -1;
 			self->new_xbofs = -1;
 			/* Done, waiting for next packet */
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/irtty-sir.c linux-libre-2.6.39-gnu/drivers/net/irda/irtty-sir.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/irtty-sir.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/irtty-sir.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 	 * let's be careful... Jean II
 	 */
 	IRDA_ASSERT(priv->tty->ops->tiocmset != NULL, return -1;);
-	priv->tty->ops->tiocmset(priv->tty, NULL, set, clear);
+	priv->tty->ops->tiocmset(priv->tty, set, clear);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/mcs7780.c linux-libre-2.6.39-gnu/drivers/net/irda/mcs7780.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/mcs7780.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/mcs7780.c	2011-05-19 00:06:34.000000000 -0400
@@ -588,7 +588,7 @@
 
 	mcs_get_reg(mcs, MCS_MODE_REG, &rval);
 
-	/* MINRXPW values recomended by MosChip */
+	/* MINRXPW values recommended by MosChip */
 	if (mcs->new_speed <= 115200) {
 		rval &= ~MCS_FIR;
 
@@ -799,7 +799,7 @@
 	ret = usb_submit_urb(urb, GFP_ATOMIC);
 }
 
-/* Transmit callback funtion.  */
+/* Transmit callback function.  */
 static void mcs_send_irq(struct urb *urb)
 {
 	struct mcs_cb *mcs = urb->context;
@@ -811,7 +811,7 @@
 		netif_wake_queue(ndev);
 }
 
-/* Transmit callback funtion.  */
+/* Transmit callback function.  */
 static netdev_tx_t mcs_hard_xmit(struct sk_buff *skb,
 				       struct net_device *ndev)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/nsc-ircc.c linux-libre-2.6.39-gnu/drivers/net/irda/nsc-ircc.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/nsc-ircc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/nsc-ircc.c	2011-05-19 00:06:34.000000000 -0400
@@ -716,7 +716,7 @@
 	int reg, com = 0;
 	int pnp;
 
-	/* Read funtion enable register (FER) */
+	/* Read function enable register (FER) */
 	outb(CFG_338_FER, cfg_base);
 	reg = inb(cfg_base+1);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/nsc-ircc.h linux-libre-2.6.39-gnu/drivers/net/irda/nsc-ircc.h
--- linux-libre-2.6.38-gnu/drivers/net/irda/nsc-ircc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/nsc-ircc.h	2011-05-19 00:06:34.000000000 -0400
@@ -135,7 +135,7 @@
 #define LSR_TXRDY       0x20 /* Transmitter ready */
 #define LSR_TXEMP       0x40 /* Transmitter empty */
 
-#define ASCR            0x07 /* Auxillary Status and Control Register */
+#define ASCR            0x07 /* Auxiliary Status and Control Register */
 #define ASCR_RXF_TOUT   0x01 /* Rx FIFO timeout */
 #define ASCR_FEND_INF   0x02 /* Frame end bytes in rx FIFO */
 #define ASCR_S_EOT      0x04 /* Set end of transmission */
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/pxaficp_ir.c linux-libre-2.6.39-gnu/drivers/net/irda/pxaficp_ir.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/pxaficp_ir.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/pxaficp_ir.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 
 #define ICCR0_AME	(1 << 7)	/* Address match enable */
 #define ICCR0_TIE	(1 << 6)	/* Transmit FIFO interrupt enable */
-#define ICCR0_RIE	(1 << 5)	/* Recieve FIFO interrupt enable */
+#define ICCR0_RIE	(1 << 5)	/* Receive FIFO interrupt enable */
 #define ICCR0_RXE	(1 << 4)	/* Receive enable */
 #define ICCR0_TXE	(1 << 3)	/* Transmit enable */
 #define ICCR0_TUS	(1 << 2)	/* Transmit FIFO underrun select */
@@ -483,7 +483,7 @@
 	}
 
 	if (icsr0 & ICSR0_EIF) {
-		/* An error in FIFO occured, or there is a end of frame */
+		/* An error in FIFO occurred, or there is a end of frame */
 		pxa_irda_fir_irq_eif(si, dev, icsr0);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/smsc-ircc2.c linux-libre-2.6.39-gnu/drivers/net/irda/smsc-ircc2.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/smsc-ircc2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/smsc-ircc2.c	2011-05-19 00:06:34.000000000 -0400
@@ -1582,7 +1582,7 @@
 	int iobase;
 	int iir, lsr;
 
-	/* Already locked comming here in smsc_ircc_interrupt() */
+	/* Already locked coming here in smsc_ircc_interrupt() */
 	/*spin_lock(&self->lock);*/
 
 	iobase = self->io.sir_base;
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/via-ircc.c linux-libre-2.6.39-gnu/drivers/net/irda/via-ircc.c
--- linux-libre-2.6.38-gnu/drivers/net/irda/via-ircc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/via-ircc.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
 
 2004-02-16: <sda@bdit.de>
 - Removed unneeded 'legacy' pci stuff.
-- Make sure SIR mode is set (hw_init()) before calling mode-dependant stuff.
+- Make sure SIR mode is set (hw_init()) before calling mode-dependent stuff.
 - On speed change from core, don't send SIR frame with new speed. 
   Use current speed and change speeds later.
 - Make module-param dongle_id actually work.
@@ -75,15 +75,9 @@
 /* We can't guess the type of connected dongle, user *must* supply it. */
 module_param(dongle_id, int, 0);
 
-/* FIXME : we should not need this, because instances should be automatically
- * managed by the PCI layer. Especially that we seem to only be using the
- * first entry. Jean II */
-/* Max 4 instances for now */
-static struct via_ircc_cb *dev_self[] = { NULL, NULL, NULL, NULL };
-
 /* Some prototypes */
-static int via_ircc_open(int i, chipio_t * info, unsigned int id);
-static int via_ircc_close(struct via_ircc_cb *self);
+static int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
+			 unsigned int id);
 static int via_ircc_dma_receive(struct via_ircc_cb *self);
 static int via_ircc_dma_receive_complete(struct via_ircc_cb *self,
 					 int iobase);
@@ -215,7 +209,7 @@
 			pci_write_config_byte(pcidev,0x42,(bTmp | 0xf0));
 			pci_write_config_byte(pcidev,0x5a,0xc0);
 			WriteLPCReg(0x28, 0x70 );
-			if (via_ircc_open(0, &info,0x3076) == 0)
+			if (via_ircc_open(pcidev, &info, 0x3076) == 0)
 				rc=0;
 		} else
 			rc = -ENODEV; //IR not turn on	 
@@ -254,7 +248,7 @@
 			info.irq=FirIRQ;
 			info.dma=FirDRQ1;
 			info.dma2=FirDRQ0;
-			if (via_ircc_open(0, &info,0x3096) == 0)
+			if (via_ircc_open(pcidev, &info, 0x3096) == 0)
 				rc=0;
 		} else
 			rc = -ENODEV; //IR not turn on !!!!!
@@ -264,48 +258,10 @@
 	return rc;
 }
 
-/*
- * Function via_ircc_clean ()
- *
- *    Close all configured chips
- *
- */
-static void via_ircc_clean(void)
-{
-	int i;
-
-	IRDA_DEBUG(3, "%s()\n", __func__);
-
-	for (i=0; i < ARRAY_SIZE(dev_self); i++) {
-		if (dev_self[i])
-			via_ircc_close(dev_self[i]);
-	}
-}
-
-static void __devexit via_remove_one (struct pci_dev *pdev)
-{
-	IRDA_DEBUG(3, "%s()\n", __func__);
-
-	/* FIXME : This is ugly. We should use pci_get_drvdata(pdev);
-	 * to get our driver instance and call directly via_ircc_close().
-	 * See vlsi_ir for details...
-	 * Jean II */
-	via_ircc_clean();
-
-	/* FIXME : This should be in via_ircc_close(), because here we may
-	 * theoritically disable still configured devices :-( - Jean II */
-	pci_disable_device(pdev);
-}
-
 static void __exit via_ircc_cleanup(void)
 {
 	IRDA_DEBUG(3, "%s()\n", __func__);
 
-	/* FIXME : This should be redundant, as pci_unregister_driver()
-	 * should call via_remove_one() on each device.
-	 * Jean II */
-	via_ircc_clean();
-
 	/* Cleanup all instances of the driver */
 	pci_unregister_driver (&via_driver); 
 }
@@ -324,12 +280,13 @@
 };
 
 /*
- * Function via_ircc_open (iobase, irq)
+ * Function via_ircc_open(pdev, iobase, irq)
  *
  *    Open driver instance
  *
  */
-static __devinit int via_ircc_open(int i, chipio_t * info, unsigned int id)
+static __devinit int via_ircc_open(struct pci_dev *pdev, chipio_t * info,
+				   unsigned int id)
 {
 	struct net_device *dev;
 	struct via_ircc_cb *self;
@@ -337,9 +294,6 @@
 
 	IRDA_DEBUG(3, "%s()\n", __func__);
 
-	if (i >= ARRAY_SIZE(dev_self))
-		return -ENOMEM;
-
 	/* Allocate new instance of the driver */
 	dev = alloc_irdadev(sizeof(struct via_ircc_cb));
 	if (dev == NULL) 
@@ -349,13 +303,8 @@
 	self->netdev = dev;
 	spin_lock_init(&self->lock);
 
-	/* FIXME : We should store our driver instance in the PCI layer,
-	 * using pci_set_drvdata(), not in this array.
-	 * See vlsi_ir for details... - Jean II */
-	/* FIXME : 'i' is always 0 (see via_init_one()) :-( - Jean II */
-	/* Need to store self somewhere */
-	dev_self[i] = self;
-	self->index = i;
+	pci_set_drvdata(pdev, self);
+
 	/* Initialize Resource */
 	self->io.cfg_base = info->cfg_base;
 	self->io.fir_base = info->fir_base;
@@ -385,7 +334,7 @@
 	self->io.dongle_id = dongle_id;
 
 	/* The only value we must override it the baudrate */
-	/* Maximum speeds and capabilities are dongle-dependant. */
+	/* Maximum speeds and capabilities are dongle-dependent. */
 	switch( self->io.dongle_id ){
 	case 0x0d:
 		self->qos.baud_rate.bits =
@@ -414,7 +363,7 @@
 
 	/* Allocate memory if needed */
 	self->rx_buff.head =
-		dma_alloc_coherent(NULL, self->rx_buff.truesize,
+		dma_alloc_coherent(&pdev->dev, self->rx_buff.truesize,
 				   &self->rx_buff_dma, GFP_KERNEL);
 	if (self->rx_buff.head == NULL) {
 		err = -ENOMEM;
@@ -423,7 +372,7 @@
 	memset(self->rx_buff.head, 0, self->rx_buff.truesize);
 
 	self->tx_buff.head =
-		dma_alloc_coherent(NULL, self->tx_buff.truesize,
+		dma_alloc_coherent(&pdev->dev, self->tx_buff.truesize,
 				   &self->tx_buff_dma, GFP_KERNEL);
 	if (self->tx_buff.head == NULL) {
 		err = -ENOMEM;
@@ -455,33 +404,32 @@
 	via_hw_init(self);
 	return 0;
  err_out4:
-	dma_free_coherent(NULL, self->tx_buff.truesize,
+	dma_free_coherent(&pdev->dev, self->tx_buff.truesize,
 			  self->tx_buff.head, self->tx_buff_dma);
  err_out3:
-	dma_free_coherent(NULL, self->rx_buff.truesize,
+	dma_free_coherent(&pdev->dev, self->rx_buff.truesize,
 			  self->rx_buff.head, self->rx_buff_dma);
  err_out2:
 	release_region(self->io.fir_base, self->io.fir_ext);
  err_out1:
+	pci_set_drvdata(pdev, NULL);
 	free_netdev(dev);
-	dev_self[i] = NULL;
 	return err;
 }
 
 /*
- * Function via_ircc_close (self)
+ * Function via_remove_one(pdev)
  *
  *    Close driver instance
  *
  */
-static int via_ircc_close(struct via_ircc_cb *self)
+static void __devexit via_remove_one(struct pci_dev *pdev)
 {
+	struct via_ircc_cb *self = pci_get_drvdata(pdev);
 	int iobase;
 
 	IRDA_DEBUG(3, "%s()\n", __func__);
 
-	IRDA_ASSERT(self != NULL, return -1;);
-
 	iobase = self->io.fir_base;
 
 	ResetChip(iobase, 5);	//hardware reset.
@@ -493,16 +441,16 @@
 		   __func__, self->io.fir_base);
 	release_region(self->io.fir_base, self->io.fir_ext);
 	if (self->tx_buff.head)
-		dma_free_coherent(NULL, self->tx_buff.truesize,
+		dma_free_coherent(&pdev->dev, self->tx_buff.truesize,
 				  self->tx_buff.head, self->tx_buff_dma);
 	if (self->rx_buff.head)
-		dma_free_coherent(NULL, self->rx_buff.truesize,
+		dma_free_coherent(&pdev->dev, self->rx_buff.truesize,
 				  self->rx_buff.head, self->rx_buff_dma);
-	dev_self[self->index] = NULL;
+	pci_set_drvdata(pdev, NULL);
 
 	free_netdev(self->netdev);
 
-	return 0;
+	pci_disable_device(pdev);
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/net/irda/vlsi_ir.h linux-libre-2.6.39-gnu/drivers/net/irda/vlsi_ir.h
--- linux-libre-2.6.38-gnu/drivers/net/irda/vlsi_ir.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/irda/vlsi_ir.h	2011-05-19 00:06:34.000000000 -0400
@@ -209,7 +209,7 @@
 	IRINTR_ACTEN	= 0x80,	/* activity interrupt enable */
 	IRINTR_ACTIVITY	= 0x40,	/* activity monitor (traffic detected) */
 	IRINTR_RPKTEN	= 0x20,	/* receive packet interrupt enable*/
-	IRINTR_RPKTINT	= 0x10,	/* rx-packet transfered from fifo to memory finished */
+	IRINTR_RPKTINT	= 0x10,	/* rx-packet transferred from fifo to memory finished */
 	IRINTR_TPKTEN	= 0x08,	/* transmit packet interrupt enable */
 	IRINTR_TPKTINT	= 0x04,	/* last bit of tx-packet+crc shifted to ir-pulser */
 	IRINTR_OE_EN	= 0x02,	/* UART rx fifo overrun error interrupt enable */
@@ -739,7 +739,7 @@
 /* the remapped error flags we use for returning from frame
  * post-processing in vlsi_process_tx/rx() after it was completed
  * by the hardware. These functions either return the >=0 number
- * of transfered bytes in case of success or the negative (-)
+ * of transferred bytes in case of success or the negative (-)
  * of the or'ed error flags.
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgb/ixgb_ethtool.c linux-libre-2.6.39-gnu/drivers/net/ixgb/ixgb_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgb/ixgb_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgb/ixgb_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -706,6 +706,43 @@
 	}
 }
 
+static int ixgb_set_flags(struct net_device *netdev, u32 data)
+{
+	struct ixgb_adapter *adapter = netdev_priv(netdev);
+	bool need_reset;
+	int rc;
+
+	/*
+	 * Tx VLAN insertion does not work per HW design when Rx stripping is
+	 * disabled.  Disable txvlan when rxvlan is turned off, and enable
+	 * rxvlan when txvlan is turned on.
+	 */
+	if (!(data & ETH_FLAG_RXVLAN) &&
+	    (netdev->features & NETIF_F_HW_VLAN_TX))
+		data &= ~ETH_FLAG_TXVLAN;
+	else if (data & ETH_FLAG_TXVLAN)
+		data |= ETH_FLAG_RXVLAN;
+
+	need_reset = (data & ETH_FLAG_RXVLAN) !=
+		     (netdev->features & NETIF_F_HW_VLAN_RX);
+
+	rc = ethtool_op_set_flags(netdev, data, ETH_FLAG_RXVLAN |
+						ETH_FLAG_TXVLAN);
+	if (rc)
+		return rc;
+
+	if (need_reset) {
+		if (netif_running(netdev)) {
+			ixgb_down(adapter, true);
+			ixgb_up(adapter);
+			ixgb_set_speed_duplex(netdev);
+		} else
+			ixgb_reset(adapter);
+	}
+
+	return 0;
+}
+
 static const struct ethtool_ops ixgb_ethtool_ops = {
 	.get_settings = ixgb_get_settings,
 	.set_settings = ixgb_set_settings,
@@ -732,6 +769,8 @@
 	.phys_id = ixgb_phys_id,
 	.get_sset_count = ixgb_get_sset_count,
 	.get_ethtool_stats = ixgb_get_ethtool_stats,
+	.get_flags = ethtool_op_get_flags,
+	.set_flags = ixgb_set_flags,
 };
 
 void ixgb_set_ethtool_ops(struct net_device *netdev)
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgb/ixgb.h linux-libre-2.6.39-gnu/drivers/net/ixgb/ixgb.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgb/ixgb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgb/ixgb.h	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
 
 struct ixgb_adapter {
 	struct timer_list watchdog_timer;
-	struct vlan_group *vlgrp;
+	unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
 	u32 bd_number;
 	u32 rx_buffer_len;
 	u32 part_num;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgb/ixgb_main.c linux-libre-2.6.39-gnu/drivers/net/ixgb/ixgb_main.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgb/ixgb_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgb/ixgb_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,8 +100,6 @@
 
 static void ixgb_vlan_strip_enable(struct ixgb_adapter *adapter);
 static void ixgb_vlan_strip_disable(struct ixgb_adapter *adapter);
-static void ixgb_vlan_rx_register(struct net_device *netdev,
-                                  struct vlan_group *grp);
 static void ixgb_vlan_rx_add_vid(struct net_device *netdev, u16 vid);
 static void ixgb_vlan_rx_kill_vid(struct net_device *netdev, u16 vid);
 static void ixgb_restore_vlan(struct ixgb_adapter *adapter);
@@ -336,7 +334,6 @@
 	.ndo_set_mac_address	= ixgb_set_mac,
 	.ndo_change_mtu		= ixgb_change_mtu,
 	.ndo_tx_timeout		= ixgb_tx_timeout,
-	.ndo_vlan_rx_register	= ixgb_vlan_rx_register,
 	.ndo_vlan_rx_add_vid	= ixgb_vlan_rx_add_vid,
 	.ndo_vlan_rx_kill_vid	= ixgb_vlan_rx_kill_vid,
 #ifdef CONFIG_NET_POLL_CONTROLLER
@@ -1508,7 +1505,7 @@
                      DESC_NEEDED)))
 		return NETDEV_TX_BUSY;
 
-	if (adapter->vlgrp && vlan_tx_tag_present(skb)) {
+	if (vlan_tx_tag_present(skb)) {
 		tx_flags |= IXGB_TX_FLAGS_VLAN;
 		vlan_id = vlan_tx_tag_get(skb);
 	}
@@ -2049,12 +2046,11 @@
 		ixgb_rx_checksum(adapter, rx_desc, skb);
 
 		skb->protocol = eth_type_trans(skb, netdev);
-		if (adapter->vlgrp && (status & IXGB_RX_DESC_STATUS_VP)) {
-			vlan_hwaccel_receive_skb(skb, adapter->vlgrp,
-			                        le16_to_cpu(rx_desc->special));
-		} else {
-			netif_receive_skb(skb);
-		}
+		if (status & IXGB_RX_DESC_STATUS_VP)
+			__vlan_hwaccel_put_tag(skb,
+					       le16_to_cpu(rx_desc->special));
+
+		netif_receive_skb(skb);
 
 rxdesc_done:
 		/* clean up descriptor, might be written over by hw */
@@ -2152,20 +2148,6 @@
 	}
 }
 
-/**
- * ixgb_vlan_rx_register - enables or disables vlan tagging/stripping.
- *
- * @param netdev network interface device structure
- * @param grp indicates to enable or disable tagging/stripping
- **/
-static void
-ixgb_vlan_rx_register(struct net_device *netdev, struct vlan_group *grp)
-{
-	struct ixgb_adapter *adapter = netdev_priv(netdev);
-
-	adapter->vlgrp = grp;
-}
-
 static void
 ixgb_vlan_strip_enable(struct ixgb_adapter *adapter)
 {
@@ -2200,6 +2182,7 @@
 	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta |= (1 << (vid & 0x1F));
 	ixgb_write_vfta(&adapter->hw, index, vfta);
+	set_bit(vid, adapter->active_vlans);
 }
 
 static void
@@ -2208,35 +2191,22 @@
 	struct ixgb_adapter *adapter = netdev_priv(netdev);
 	u32 vfta, index;
 
-	ixgb_irq_disable(adapter);
-
-	vlan_group_set_device(adapter->vlgrp, vid, NULL);
-
-	/* don't enable interrupts unless we are UP */
-	if (adapter->netdev->flags & IFF_UP)
-		ixgb_irq_enable(adapter);
-
 	/* remove VID from filter table */
 
 	index = (vid >> 5) & 0x7F;
 	vfta = IXGB_READ_REG_ARRAY(&adapter->hw, VFTA, index);
 	vfta &= ~(1 << (vid & 0x1F));
 	ixgb_write_vfta(&adapter->hw, index, vfta);
+	clear_bit(vid, adapter->active_vlans);
 }
 
 static void
 ixgb_restore_vlan(struct ixgb_adapter *adapter)
 {
-	ixgb_vlan_rx_register(adapter->netdev, adapter->vlgrp);
+	u16 vid;
 
-	if (adapter->vlgrp) {
-		u16 vid;
-		for (vid = 0; vid < VLAN_N_VID; vid++) {
-			if (!vlan_group_get_device(adapter->vlgrp, vid))
-				continue;
-			ixgb_vlan_rx_add_vid(adapter->netdev, vid);
-		}
-	}
+	for_each_set_bit(vid, adapter->active_vlans, VLAN_N_VID)
+		ixgb_vlan_rx_add_vid(adapter->netdev, vid);
 }
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_82598.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_82598.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_82598.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_82598.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -158,6 +158,7 @@
 
 	switch (hw->phy.type) {
 	case ixgbe_phy_tn:
+		phy->ops.setup_link = &ixgbe_setup_phy_link_tnx;
 		phy->ops.check_link = &ixgbe_check_phy_link_tnx;
 		phy->ops.get_firmware_version =
 		             &ixgbe_get_phy_firmware_version_tnx;
@@ -280,10 +281,22 @@
 {
 	enum ixgbe_media_type media_type;
 
+	/* Detect if there is a copper PHY attached. */
+	switch (hw->phy.type) {
+	case ixgbe_phy_cu_unknown:
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
+		media_type = ixgbe_media_type_copper;
+		goto out;
+	default:
+		break;
+	}
+
 	/* Media type for I82598 is based on device ID */
 	switch (hw->device_id) {
 	case IXGBE_DEV_ID_82598:
 	case IXGBE_DEV_ID_82598_BX:
+		/* Default device ID is mezzanine card KX/KX4 */
 		media_type = ixgbe_media_type_backplane;
 		break;
 	case IXGBE_DEV_ID_82598AF_DUAL_PORT:
@@ -306,7 +319,7 @@
 		media_type = ixgbe_media_type_unknown;
 		break;
 	}
-
+out:
 	return media_type;
 }
 
@@ -354,7 +367,7 @@
 
 	/* Negotiate the fc mode to use */
 	ret_val = ixgbe_fc_autoneg(hw);
-	if (ret_val)
+	if (ret_val == IXGBE_ERR_FLOW_CONTROL)
 		goto out;
 
 	/* Disable any previous flow control settings */
@@ -372,10 +385,10 @@
 	 * 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
+	 * other: Invalid.
 	 */
 	switch (hw->fc.current_mode) {
 	case ixgbe_fc_none:
@@ -432,9 +445,10 @@
 		reg = (rx_pba_size - hw->fc.low_water) << 6;
 		if (hw->fc.send_xon)
 			reg |= IXGBE_FCRTL_XONE;
+
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(packetbuf_num), reg);
 
-		reg = (rx_pba_size - hw->fc.high_water) << 10;
+		reg = (rx_pba_size - hw->fc.high_water) << 6;
 		reg |= IXGBE_FCRTH_FCEN;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(packetbuf_num), reg);
@@ -627,13 +641,12 @@
 	return 0;
 }
 
-
 /**
  *  ixgbe_setup_mac_link_82598 - Set MAC link speed
  *  @hw: pointer to hardware structure
  *  @speed: new link speed
  *  @autoneg: true if auto-negotiation enabled
- *  @autoneg_wait_to_complete: true if waiting is needed to complete
+ *  @autoneg_wait_to_complete: true when waiting for completion is needed
  *
  *  Set the link speed in the AUTOC register and restarts link.
  **/
@@ -672,7 +685,8 @@
 		 * ixgbe_hw This will write the AUTOC register based on the new
 		 * stored values
 		 */
-		status = ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
+		status = ixgbe_start_mac_link_82598(hw,
+						    autoneg_wait_to_complete);
 	}
 
 	return status;
@@ -698,7 +712,6 @@
 	/* Setup the PHY according to input speed */
 	status = hw->phy.ops.setup_link_speed(hw, speed, autoneg,
 	                                      autoneg_wait_to_complete);
-
 	/* Set up MAC */
 	ixgbe_start_mac_link_82598(hw, autoneg_wait_to_complete);
 
@@ -770,7 +783,6 @@
 		else if (phy_status == IXGBE_ERR_SFP_NOT_PRESENT)
 			goto no_phy_reset;
 
-
 		hw->phy.ops.reset(hw);
 	}
 
@@ -779,12 +791,9 @@
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	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");
-	}
+	ixgbe_disable_pcie_master(hw);
 
+mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  This needs to be a SW reset.
 	 * If link reset is used, it might reset the MAC when mng is using it
@@ -805,6 +814,19 @@
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
+	/*
+	 * Double resets are required for recovery from certain error
+	 * conditions.  Between resets, it is necessary to stall to allow time
+	 * for any pending HW events to complete.  We use 1usec since that is
+	 * what is needed for ixgbe_disable_pcie_master().  The second reset
+	 * then clears out any effects of those events.
+	 */
+	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+		udelay(1);
+		goto mac_reset_top;
+	}
+
 	msleep(50);
 
 	gheccr = IXGBE_READ_REG(hw, IXGBE_GHECCR);
@@ -824,15 +846,15 @@
 		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, hw->mac.orig_autoc);
 	}
 
+	/* Store the permanent mac address */
+	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
 	/*
 	 * 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;
@@ -849,6 +871,13 @@
 static s32 ixgbe_set_vmdq_82598(struct ixgbe_hw *hw, u32 rar, u32 vmdq)
 {
 	u32 rar_high;
+	u32 rar_entries = hw->mac.num_rar_entries;
+
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
+		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
 
 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
 	rar_high &= ~IXGBE_RAH_VIND_MASK;
@@ -868,14 +897,17 @@
 	u32 rar_high;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
-	if (rar < rar_entries) {
-		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
-		if (rar_high & IXGBE_RAH_VIND_MASK) {
-			rar_high &= ~IXGBE_RAH_VIND_MASK;
-			IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
-		}
-	} else {
+
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
+
+	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(rar));
+	if (rar_high & IXGBE_RAH_VIND_MASK) {
+		rar_high &= ~IXGBE_RAH_VIND_MASK;
+		IXGBE_WRITE_REG(hw, IXGBE_RAH(rar), rar_high);
 	}
 
 	return 0;
@@ -994,13 +1026,12 @@
 }
 
 /**
- *  ixgbe_read_i2c_eeprom_82598 - Read 8 bit EEPROM word of an SFP+ module
- *  over I2C interface through an intermediate phy.
+ *  ixgbe_read_i2c_eeprom_82598 - Reads 8 bit word over I2C interface.
  *  @hw: pointer to hardware structure
  *  @byte_offset: EEPROM byte offset to read
  *  @eeprom_data: value read
  *
- *  Performs byte read operation to SFP module's EEPROM over I2C interface.
+ *  Performs 8 byte read operation to SFP module's EEPROM over I2C interface.
  **/
 static s32 ixgbe_read_i2c_eeprom_82598(struct ixgbe_hw *hw, u8 byte_offset,
 				       u8 *eeprom_data)
@@ -1074,10 +1105,12 @@
 
 	/* 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);
+	switch (hw->phy.type) {
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
+	case 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)
@@ -1085,6 +1118,8 @@
 		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
 		goto out;
+	default:
+		break;
 	}
 
 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -1179,13 +1214,14 @@
 	.set_vmdq		= &ixgbe_set_vmdq_82598,
 	.clear_vmdq		= &ixgbe_clear_vmdq_82598,
 	.init_rx_addrs		= &ixgbe_init_rx_addrs_generic,
-	.update_uc_addr_list	= &ixgbe_update_uc_addr_list_generic,
 	.update_mc_addr_list	= &ixgbe_update_mc_addr_list_generic,
 	.enable_mc		= &ixgbe_enable_mc_generic,
 	.disable_mc		= &ixgbe_disable_mc_generic,
 	.clear_vfta		= &ixgbe_clear_vfta_82598,
 	.set_vfta		= &ixgbe_set_vfta_82598,
 	.fc_enable		= &ixgbe_fc_enable_82598,
+	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
+	.release_swfw_sync      = &ixgbe_release_swfw_sync,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82598 = {
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_82599.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_82599.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_82599.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_82599.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -112,7 +112,8 @@
 			goto setup_sfp_out;
 
 		/* PHY config will finish before releasing the semaphore */
-		ret_val = ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_MAC_CSR_SM);
+		ret_val = hw->mac.ops.acquire_swfw_sync(hw,
+		                                        IXGBE_GSSR_MAC_CSR_SM);
 		if (ret_val != 0) {
 			ret_val = IXGBE_ERR_SWFW_SYNC;
 			goto setup_sfp_out;
@@ -329,11 +330,14 @@
 	enum ixgbe_media_type media_type;
 
 	/* Detect if there is a copper PHY attached. */
-	if (hw->phy.type == ixgbe_phy_cu_unknown ||
-	    hw->phy.type == ixgbe_phy_tn ||
-	    hw->phy.type == ixgbe_phy_aq) {
+	switch (hw->phy.type) {
+	case ixgbe_phy_cu_unknown:
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
 		media_type = ixgbe_media_type_copper;
 		goto out;
+	default:
+		break;
 	}
 
 	switch (hw->device_id) {
@@ -354,6 +358,9 @@
 	case IXGBE_DEV_ID_82599_CX4:
 		media_type = ixgbe_media_type_cx4;
 		break;
+	case IXGBE_DEV_ID_82599_T3_LOM:
+		media_type = ixgbe_media_type_copper;
+		break;
 	default:
 		media_type = ixgbe_media_type_unknown;
 		break;
@@ -411,14 +418,14 @@
 	return status;
 }
 
- /**
-  *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
-  *  @hw: pointer to hardware structure
-  *
-  *  The base drivers may require better control over SFP+ module
-  *  PHY states.  This includes selectively shutting down the Tx
-  *  laser on the PHY, effectively halting physical link.
-  **/
+/**
+ *  ixgbe_disable_tx_laser_multispeed_fiber - Disable Tx laser
+ *  @hw: pointer to hardware structure
+ *
+ *  The base drivers may require better control over SFP+ module
+ *  PHY states.  This includes selectively shutting down the Tx
+ *  laser on the PHY, effectively halting physical link.
+ **/
 static void ixgbe_disable_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
@@ -463,8 +470,6 @@
  **/
 static void ixgbe_flap_tx_laser_multispeed_fiber(struct ixgbe_hw *hw)
 {
-	hw_dbg(hw, "ixgbe_flap_tx_laser_multispeed_fiber\n");
-
 	if (hw->mac.autotry_restart) {
 		ixgbe_disable_tx_laser_multispeed_fiber(hw);
 		ixgbe_enable_tx_laser_multispeed_fiber(hw);
@@ -487,17 +492,21 @@
                                           bool autoneg_wait_to_complete)
 {
 	s32 status = 0;
-	ixgbe_link_speed phy_link_speed;
+	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	ixgbe_link_speed highest_link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	u32 speedcnt = 0;
 	u32 esdp_reg = IXGBE_READ_REG(hw, IXGBE_ESDP);
+	u32 i = 0;
 	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;
+	status = hw->mac.ops.get_link_capabilities(hw, &link_speed,
+						   &negotiation);
+	if (status != 0)
+		return status;
+
+	speed &= link_speed;
 
 	/*
 	 * Try each speed one by one, highest priority first.  We do this in
@@ -508,9 +517,12 @@
 		highest_link_speed = IXGBE_LINK_SPEED_10GB_FULL;
 
 		/* If we already have link at this speed, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+						false);
+		if (status != 0)
+			return status;
 
-		if ((phy_link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
+		if ((link_speed == IXGBE_LINK_SPEED_10GB_FULL) && link_up)
 			goto out;
 
 		/* Set the module link speed */
@@ -522,9 +534,9 @@
 		msleep(40);
 
 		status = ixgbe_setup_mac_link_82599(hw,
-		                               IXGBE_LINK_SPEED_10GB_FULL,
-		                               autoneg,
-		                               autoneg_wait_to_complete);
+						    IXGBE_LINK_SPEED_10GB_FULL,
+						    autoneg,
+						    autoneg_wait_to_complete);
 		if (status != 0)
 			return status;
 
@@ -536,14 +548,16 @@
 		 * Section 73.10.2, we may have to wait up to 500ms if KR is
 		 * attempted.  82599 uses the same timing for 10g SFI.
 		 */
-
 		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);
+			status = hw->mac.ops.check_link(hw, &link_speed,
+							&link_up, false);
+			if (status != 0)
+				return status;
+
 			if (link_up)
 				goto out;
 		}
@@ -555,9 +569,12 @@
 			highest_link_speed = IXGBE_LINK_SPEED_1GB_FULL;
 
 		/* If we already have link at this speed, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+						false);
+		if (status != 0)
+			return status;
 
-		if ((phy_link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
+		if ((link_speed == IXGBE_LINK_SPEED_1GB_FULL) && link_up)
 			goto out;
 
 		/* Set the module link speed */
@@ -570,9 +587,9 @@
 		msleep(40);
 
 		status = ixgbe_setup_mac_link_82599(hw,
-		                                      IXGBE_LINK_SPEED_1GB_FULL,
-		                                      autoneg,
-		                                      autoneg_wait_to_complete);
+						    IXGBE_LINK_SPEED_1GB_FULL,
+						    autoneg,
+						    autoneg_wait_to_complete);
 		if (status != 0)
 			return status;
 
@@ -583,7 +600,11 @@
 		msleep(100);
 
 		/* If we have link, just jump out */
-		hw->mac.ops.check_link(hw, &phy_link_speed, &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed, &link_up,
+						false);
+		if (status != 0)
+			return status;
+
 		if (link_up)
 			goto out;
 	}
@@ -626,13 +647,10 @@
 				     bool autoneg_wait_to_complete)
 {
 	s32 status = 0;
-	ixgbe_link_speed link_speed;
+	ixgbe_link_speed link_speed = IXGBE_LINK_SPEED_UNKNOWN;
 	s32 i, j;
 	bool link_up = false;
 	u32 autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-	struct ixgbe_adapter *adapter = hw->back;
-
-	hw_dbg(hw, "ixgbe_setup_mac_link_smartspeed.\n");
 
 	 /* Set autoneg_advertised value based on input link speed */
 	hw->phy.autoneg_advertised = 0;
@@ -658,7 +676,7 @@
 	for (j = 0; j < IXGBE_SMARTSPEED_MAX_RETRIES; j++) {
 		status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
 						    autoneg_wait_to_complete);
-		if (status)
+		if (status != 0)
 			goto out;
 
 		/*
@@ -671,8 +689,11 @@
 			mdelay(100);
 
 			/* If we have link, just jump out */
-			hw->mac.ops.check_link(hw, &link_speed,
-			                       &link_up, false);
+			status = hw->mac.ops.check_link(hw, &link_speed,
+							&link_up, false);
+			if (status != 0)
+				goto out;
+
 			if (link_up)
 				goto out;
 		}
@@ -690,7 +711,7 @@
 	hw->phy.smart_speed_active = true;
 	status = ixgbe_setup_mac_link_82599(hw, speed, autoneg,
 					    autoneg_wait_to_complete);
-	if (status)
+	if (status != 0)
 		goto out;
 
 	/*
@@ -703,8 +724,11 @@
 		mdelay(100);
 
 		/* If we have link, just jump out */
-		hw->mac.ops.check_link(hw, &link_speed,
-		                       &link_up, false);
+		status = hw->mac.ops.check_link(hw, &link_speed,
+						&link_up, false);
+		if (status != 0)
+			goto out;
+
 		if (link_up)
 			goto out;
 	}
@@ -716,7 +740,7 @@
 
 out:
 	if (link_up && (link_speed == IXGBE_LINK_SPEED_1GB_FULL))
-		e_info(hw, "Smartspeed has downgraded the link speed from "
+		hw_dbg(hw, "Smartspeed has downgraded the link speed from "
 		       "the maximum advertised\n");
 	return status;
 }
@@ -748,6 +772,9 @@
 
 	/* Check to see if speed passed in is supported. */
 	hw->mac.ops.get_link_capabilities(hw, &link_capabilities, &autoneg);
+	if (status != 0)
+		goto out;
+
 	speed &= link_capabilities;
 
 	if (speed == IXGBE_LINK_SPEED_UNKNOWN) {
@@ -761,7 +788,6 @@
 	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) {
@@ -878,7 +904,7 @@
 
 	/* PHY ops must be identified and initialized prior to reset */
 
-	/* Init PHY and function pointers, perform SFP setup */
+	/* Identify PHY and related function pointers */
 	status = hw->phy.ops.init(hw);
 
 	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
@@ -890,6 +916,9 @@
 		hw->phy.sfp_setup_needed = false;
 	}
 
+	if (status == IXGBE_ERR_SFP_NOT_SUPPORTED)
+		goto reset_hw_out;
+
 	/* Reset PHY */
 	if (hw->phy.reset_disable == false && hw->phy.ops.reset != NULL)
 		hw->phy.ops.reset(hw);
@@ -898,12 +927,9 @@
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	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");
-	}
+	ixgbe_disable_pcie_master(hw);
 
+mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  This needs to be a SW reset.
 	 * If link reset is used, it might reset the MAC when mng is using it
@@ -924,6 +950,19 @@
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
+	/*
+	 * Double resets are required for recovery from certain error
+	 * conditions.  Between resets, it is necessary to stall to allow time
+	 * for any pending HW events to complete.  We use 1usec since that is
+	 * what is needed for ixgbe_disable_pcie_master().  The second reset
+	 * then clears out any effects of those events.
+	 */
+	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+		udelay(1);
+		goto mac_reset_top;
+	}
+
 	msleep(50);
 
 	/*
@@ -951,6 +990,9 @@
 		}
 	}
 
+	/* Store the permanent mac address */
+	hw->mac.ops.get_mac_addr(hw, hw->mac.perm_addr);
+
 	/*
 	 * Store MAC address from RAR0, clear receive address registers, and
 	 * clear the multicast table.  Also reset num_rar_entries to 128,
@@ -959,9 +1001,6 @@
 	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);
 
@@ -1733,13 +1772,34 @@
  *  @hw: pointer to hardware structure
  *
  *  Determines the physical layer module found on the current adapter.
+ *  If PHY already detected, maintains current PHY type in hw struct,
+ *  otherwise executes the PHY detection routine.
  **/
-static s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
+s32 ixgbe_identify_phy_82599(struct ixgbe_hw *hw)
 {
 	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
+
+	/* Detect PHY if not unknown - returns success if already detected. */
 	status = ixgbe_identify_phy_generic(hw);
-	if (status != 0)
-		status = ixgbe_identify_sfp_module_generic(hw);
+	if (status != 0) {
+		/* 82599 10GBASE-T requires an external PHY */
+		if (hw->mac.ops.get_media_type(hw) == ixgbe_media_type_copper)
+			goto out;
+		else
+			status = ixgbe_identify_sfp_module_generic(hw);
+	}
+
+	/* Set PHY type none if no PHY detected */
+	if (hw->phy.type == ixgbe_phy_unknown) {
+		hw->phy.type = ixgbe_phy_none;
+		status = 0;
+	}
+
+	/* Return error if SFP module has been detected but is not supported */
+	if (hw->phy.type == ixgbe_phy_sfp_unsupported)
+		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+
+out:
 	return status;
 }
 
@@ -1763,11 +1823,12 @@
 
 	hw->phy.ops.identify(hw);
 
-	if (hw->phy.type == ixgbe_phy_tn ||
-	    hw->phy.type == ixgbe_phy_aq ||
-	    hw->phy.type == ixgbe_phy_cu_unknown) {
+	switch (hw->phy.type) {
+	case ixgbe_phy_tn:
+	case ixgbe_phy_aq:
+	case ixgbe_phy_cu_unknown:
 		hw->phy.ops.read_reg(hw, MDIO_PMA_EXTABLE, MDIO_MMD_PMAPMD,
-				     &ext_ability);
+							 &ext_ability);
 		if (ext_ability & MDIO_PMA_EXTABLE_10GBT)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_10GBASE_T;
 		if (ext_ability & MDIO_PMA_EXTABLE_1000BT)
@@ -1775,6 +1836,8 @@
 		if (ext_ability & MDIO_PMA_EXTABLE_100BTX)
 			physical_layer |= IXGBE_PHYSICAL_LAYER_100BASE_TX;
 		goto out;
+	default:
+		break;
 	}
 
 	switch (autoc & IXGBE_AUTOC_LMS_MASK) {
@@ -1886,6 +1949,7 @@
 		if (secrxreg & IXGBE_SECRXSTAT_SECRX_RDY)
 			break;
 		else
+			/* Use interrupt-safe sleep just in case */
 			udelay(10);
 	}
 
@@ -1995,7 +2059,6 @@
 	.set_vmdq               = &ixgbe_set_vmdq_generic,
 	.clear_vmdq             = &ixgbe_clear_vmdq_generic,
 	.init_rx_addrs          = &ixgbe_init_rx_addrs_generic,
-	.update_uc_addr_list    = &ixgbe_update_uc_addr_list_generic,
 	.update_mc_addr_list    = &ixgbe_update_mc_addr_list_generic,
 	.enable_mc              = &ixgbe_enable_mc_generic,
 	.disable_mc             = &ixgbe_disable_mc_generic,
@@ -2006,31 +2069,34 @@
 	.setup_sfp              = &ixgbe_setup_sfp_modules_82599,
 	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
 	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
+	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync,
+	.release_swfw_sync      = &ixgbe_release_swfw_sync,
+
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_82599 = {
-	.init_params            = &ixgbe_init_eeprom_params_generic,
-	.read                   = &ixgbe_read_eerd_generic,
-	.write                  = &ixgbe_write_eeprom_generic,
-	.calc_checksum          = &ixgbe_calc_eeprom_checksum_generic,
-	.validate_checksum      = &ixgbe_validate_eeprom_checksum_generic,
-	.update_checksum        = &ixgbe_update_eeprom_checksum_generic,
+	.init_params		= &ixgbe_init_eeprom_params_generic,
+	.read			= &ixgbe_read_eerd_generic,
+	.write			= &ixgbe_write_eeprom_generic,
+	.calc_checksum		= &ixgbe_calc_eeprom_checksum_generic,
+	.validate_checksum	= &ixgbe_validate_eeprom_checksum_generic,
+	.update_checksum	= &ixgbe_update_eeprom_checksum_generic,
 };
 
 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,
-	.setup_link             = &ixgbe_setup_phy_link_generic,
-	.setup_link_speed       = &ixgbe_setup_phy_link_speed_generic,
-	.read_i2c_byte          = &ixgbe_read_i2c_byte_generic,
-	.write_i2c_byte         = &ixgbe_write_i2c_byte_generic,
-	.read_i2c_eeprom        = &ixgbe_read_i2c_eeprom_generic,
-	.write_i2c_eeprom       = &ixgbe_write_i2c_eeprom_generic,
-	.check_overtemp         = &ixgbe_tn_check_overtemp,
+	.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,
+	.setup_link		= &ixgbe_setup_phy_link_generic,
+	.setup_link_speed	= &ixgbe_setup_phy_link_speed_generic,
+	.read_i2c_byte		= &ixgbe_read_i2c_byte_generic,
+	.write_i2c_byte		= &ixgbe_write_i2c_byte_generic,
+	.read_i2c_eeprom	= &ixgbe_read_i2c_eeprom_generic,
+	.write_i2c_eeprom	= &ixgbe_write_i2c_eeprom_generic,
+	.check_overtemp		= &ixgbe_tn_check_overtemp,
 };
 
 struct ixgbe_info ixgbe_82599_info = {
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_common.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_common.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -46,10 +46,13 @@
 static void ixgbe_lower_eeprom_clk(struct ixgbe_hw *hw, u32 *eec);
 static void ixgbe_release_eeprom(struct ixgbe_hw *hw);
 
-static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index);
-static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index);
 static s32 ixgbe_mta_vector(struct ixgbe_hw *hw, u8 *mc_addr);
-static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq);
+static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw);
+static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw);
+static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw);
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw);
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm);
 static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num);
 
 /**
@@ -139,17 +142,29 @@
 	IXGBE_READ_REG(hw, IXGBE_MRFC);
 	IXGBE_READ_REG(hw, IXGBE_RLEC);
 	IXGBE_READ_REG(hw, IXGBE_LXONTXC);
-	IXGBE_READ_REG(hw, IXGBE_LXONRXC);
 	IXGBE_READ_REG(hw, IXGBE_LXOFFTXC);
-	IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+	if (hw->mac.type >= ixgbe_mac_82599EB) {
+		IXGBE_READ_REG(hw, IXGBE_LXONRXCNT);
+		IXGBE_READ_REG(hw, IXGBE_LXOFFRXCNT);
+	} else {
+		IXGBE_READ_REG(hw, IXGBE_LXONRXC);
+		IXGBE_READ_REG(hw, IXGBE_LXOFFRXC);
+	}
 
 	for (i = 0; i < 8; i++) {
 		IXGBE_READ_REG(hw, IXGBE_PXONTXC(i));
-		IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
 		IXGBE_READ_REG(hw, IXGBE_PXOFFTXC(i));
-		IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+		if (hw->mac.type >= ixgbe_mac_82599EB) {
+			IXGBE_READ_REG(hw, IXGBE_PXONRXCNT(i));
+			IXGBE_READ_REG(hw, IXGBE_PXOFFRXCNT(i));
+		} else {
+			IXGBE_READ_REG(hw, IXGBE_PXONRXC(i));
+			IXGBE_READ_REG(hw, IXGBE_PXOFFRXC(i));
+		}
 	}
-
+	if (hw->mac.type >= ixgbe_mac_82599EB)
+		for (i = 0; i < 8; i++)
+			IXGBE_READ_REG(hw, IXGBE_PXON2OFFCNT(i));
 	IXGBE_READ_REG(hw, IXGBE_PRC64);
 	IXGBE_READ_REG(hw, IXGBE_PRC127);
 	IXGBE_READ_REG(hw, IXGBE_PRC255);
@@ -187,9 +202,26 @@
 	IXGBE_READ_REG(hw, IXGBE_BPTC);
 	for (i = 0; i < 16; i++) {
 		IXGBE_READ_REG(hw, IXGBE_QPRC(i));
-		IXGBE_READ_REG(hw, IXGBE_QBRC(i));
 		IXGBE_READ_REG(hw, IXGBE_QPTC(i));
-		IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+		if (hw->mac.type >= ixgbe_mac_82599EB) {
+			IXGBE_READ_REG(hw, IXGBE_QBRC_L(i));
+			IXGBE_READ_REG(hw, IXGBE_QBRC_H(i));
+			IXGBE_READ_REG(hw, IXGBE_QBTC_L(i));
+			IXGBE_READ_REG(hw, IXGBE_QBTC_H(i));
+			IXGBE_READ_REG(hw, IXGBE_QPRDC(i));
+		} else {
+			IXGBE_READ_REG(hw, IXGBE_QBRC(i));
+			IXGBE_READ_REG(hw, IXGBE_QBTC(i));
+		}
+	}
+
+	if (hw->mac.type == ixgbe_mac_X540) {
+		if (hw->phy.id == 0)
+			hw->phy.ops.identify(hw);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_PCRC8ECL, &i);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_PCRC8ECH, &i);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_LDPCECL, &i);
+		hw->phy.ops.read_reg(hw, 0x3, IXGBE_LDPCECH, &i);
 	}
 
 	return 0;
@@ -454,8 +486,7 @@
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests
 	 */
-	if (ixgbe_disable_pcie_master(hw) != 0)
-		hw_dbg(hw, "PCI-E Master disable polling has failed.\n");
+	ixgbe_disable_pcie_master(hw);
 
 	return 0;
 }
@@ -603,7 +634,6 @@
 		ixgbe_shift_out_eeprom_bits(hw, data, 16);
 		ixgbe_standby_eeprom(hw);
 
-		msleep(hw->eeprom.semaphore_delay);
 		/* Done with writing - release the EEPROM */
 		ixgbe_release_eeprom(hw);
 	}
@@ -747,10 +777,10 @@
 static s32 ixgbe_acquire_eeprom(struct ixgbe_hw *hw)
 {
 	s32 status = 0;
-	u32 eec = 0;
+	u32 eec;
 	u32 i;
 
-	if (ixgbe_acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) != 0)
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == 0) {
@@ -773,18 +803,18 @@
 			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
 			hw_dbg(hw, "Could not acquire EEPROM grant\n");
 
-			ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+			hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
 			status = IXGBE_ERR_EEPROM;
 		}
-	}
 
-	/* Setup EEPROM for Read/Write */
-	if (status == 0) {
-		/* Clear CS and SK */
-		eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
-		IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
-		IXGBE_WRITE_FLUSH(hw);
-		udelay(1);
+		/* Setup EEPROM for Read/Write */
+		if (status == 0) {
+			/* Clear CS and SK */
+			eec &= ~(IXGBE_EEC_CS | IXGBE_EEC_SK);
+			IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
+			IXGBE_WRITE_FLUSH(hw);
+			udelay(1);
+		}
 	}
 	return status;
 }
@@ -798,13 +828,10 @@
 static s32 ixgbe_get_eeprom_semaphore(struct ixgbe_hw *hw)
 {
 	s32 status = IXGBE_ERR_EEPROM;
-	u32 timeout;
+	u32 timeout = 2000;
 	u32 i;
 	u32 swsm;
 
-	/* Set timeout value based on size of EEPROM */
-	timeout = hw->eeprom.word_size + 1;
-
 	/* Get SMBI software semaphore between device drivers first */
 	for (i = 0; i < timeout; i++) {
 		/*
@@ -816,7 +843,7 @@
 			status = 0;
 			break;
 		}
-		msleep(1);
+		udelay(50);
 	}
 
 	/* Now get the semaphore between SW/FW through the SWESMBI bit */
@@ -844,11 +871,14 @@
 		 * was not granted because we don't have access to the EEPROM
 		 */
 		if (i >= timeout) {
-			hw_dbg(hw, "Driver can't access the Eeprom - Semaphore "
+			hw_dbg(hw, "SWESMBI Software EEPROM semaphore "
 			       "not granted.\n");
 			ixgbe_release_eeprom_semaphore(hw);
 			status = IXGBE_ERR_EEPROM;
 		}
+	} else {
+		hw_dbg(hw, "Software semaphore SMBI between device drivers "
+		       "not granted.\n");
 	}
 
 	return status;
@@ -1080,11 +1110,14 @@
 	eec &= ~IXGBE_EEC_REQ;
 	IXGBE_WRITE_REG(hw, IXGBE_EEC, eec);
 
-	ixgbe_release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+	hw->mac.ops.release_swfw_sync(hw, IXGBE_GSSR_EEP_SM);
+
+	/* Delay before attempt to obtain semaphore again to allow FW access */
+	msleep(hw->eeprom.semaphore_delay);
 }
 
 /**
- *  ixgbe_calc_eeprom_checksum - Calculates and returns the checksum
+ *  ixgbe_calc_eeprom_checksum_generic - Calculates and returns the checksum
  *  @hw: pointer to hardware structure
  **/
 u16 ixgbe_calc_eeprom_checksum_generic(struct ixgbe_hw *hw)
@@ -1190,7 +1223,7 @@
 	if (status == 0) {
 		checksum = hw->eeprom.ops.calc_checksum(hw);
 		status = hw->eeprom.ops.write(hw, IXGBE_EEPROM_CHECKSUM,
-		                            checksum);
+					      checksum);
 	} else {
 		hw_dbg(hw, "EEPROM read failed\n");
 	}
@@ -1238,37 +1271,37 @@
 	u32 rar_low, rar_high;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
+	/* Make sure we are using a valid rar index range */
+	if (index >= rar_entries) {
+		hw_dbg(hw, "RAR index %d is out of range.\n", index);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
+
 	/* setup VMDq pool selection before this RAR gets enabled */
 	hw->mac.ops.set_vmdq(hw, index, vmdq);
 
-	/* Make sure we are using a valid rar index range */
-	if (index < rar_entries) {
-		/*
-		 * HW expects these in little endian so we reverse the byte
-		 * order from network order (big endian) to little endian
-		 */
-		rar_low = ((u32)addr[0] |
-		           ((u32)addr[1] << 8) |
-		           ((u32)addr[2] << 16) |
-		           ((u32)addr[3] << 24));
-		/*
-		 * Some parts put the VMDq setting in the extra RAH bits,
-		 * so save everything except the lower 16 bits that hold part
-		 * of the address and the address valid bit.
-		 */
-		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
-		rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
+	/*
+	 * HW expects these in little endian so we reverse the byte
+	 * order from network order (big endian) to little endian
+	 */
+	rar_low = ((u32)addr[0] |
+		   ((u32)addr[1] << 8) |
+		   ((u32)addr[2] << 16) |
+		   ((u32)addr[3] << 24));
+	/*
+	 * Some parts put the VMDq setting in the extra RAH bits,
+	 * so save everything except the lower 16 bits that hold part
+	 * of the address and the address valid bit.
+	 */
+	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
+	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+	rar_high |= ((u32)addr[4] | ((u32)addr[5] << 8));
 
-		if (enable_addr != 0)
-			rar_high |= IXGBE_RAH_AV;
+	if (enable_addr != 0)
+		rar_high |= IXGBE_RAH_AV;
 
-		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
-		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-	} else {
-		hw_dbg(hw, "RAR index %d is out of range.\n", index);
-		return IXGBE_ERR_RAR_INDEX;
-	}
+	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), rar_low);
+	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
 
 	return 0;
 }
@@ -1286,58 +1319,26 @@
 	u32 rar_entries = hw->mac.num_rar_entries;
 
 	/* Make sure we are using a valid rar index range */
-	if (index < rar_entries) {
-		/*
-		 * Some parts put the VMDq setting in the extra RAH bits,
-		 * so save everything except the lower 16 bits that hold part
-		 * of the address and the address valid bit.
-		 */
-		rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-		rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
-
-		IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-	} else {
+	if (index >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", index);
-		return IXGBE_ERR_RAR_INDEX;
+		return IXGBE_ERR_INVALID_ARGUMENT;
 	}
 
-	/* clear VMDq pool/queue selection for this RAR */
-	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
-
-	return 0;
-}
-
-/**
- *  ixgbe_enable_rar - Enable Rx address register
- *  @hw: pointer to hardware structure
- *  @index: index into the RAR table
- *
- *  Enables the select receive address register.
- **/
-static void ixgbe_enable_rar(struct ixgbe_hw *hw, u32 index)
-{
-	u32 rar_high;
-
+	/*
+	 * Some parts put the VMDq setting in the extra RAH bits,
+	 * so save everything except the lower 16 bits that hold part
+	 * of the address and the address valid bit.
+	 */
 	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-	rar_high |= IXGBE_RAH_AV;
+	rar_high &= ~(0x0000FFFF | IXGBE_RAH_AV);
+
+	IXGBE_WRITE_REG(hw, IXGBE_RAL(index), 0);
 	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
-}
 
-/**
- *  ixgbe_disable_rar - Disable Rx address register
- *  @hw: pointer to hardware structure
- *  @index: index into the RAR table
- *
- *  Disables the select receive address register.
- **/
-static void ixgbe_disable_rar(struct ixgbe_hw *hw, u32 index)
-{
-	u32 rar_high;
+	/* clear VMDq pool/queue selection for this RAR */
+	hw->mac.ops.clear_vmdq(hw, index, IXGBE_CLEAR_VMDQ_ALL);
 
-	rar_high = IXGBE_READ_REG(hw, IXGBE_RAH(index));
-	rar_high &= (~IXGBE_RAH_AV);
-	IXGBE_WRITE_REG(hw, IXGBE_RAH(index), rar_high);
+	return 0;
 }
 
 /**
@@ -1386,7 +1387,6 @@
 	}
 
 	/* Clear the MTA */
-	hw->addr_ctrl.mc_addr_in_rar_count = 0;
 	hw->addr_ctrl.mta_in_use = 0;
 	IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
 
@@ -1401,105 +1401,6 @@
 }
 
 /**
- *  ixgbe_add_uc_addr - Adds a secondary unicast address.
- *  @hw: pointer to hardware structure
- *  @addr: new address
- *
- *  Adds it to unused receive address register or goes into promiscuous mode.
- **/
-static void ixgbe_add_uc_addr(struct ixgbe_hw *hw, u8 *addr, u32 vmdq)
-{
-	u32 rar_entries = hw->mac.num_rar_entries;
-	u32 rar;
-
-	hw_dbg(hw, " UC Addr = %.2X %.2X %.2X %.2X %.2X %.2X\n",
-	          addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
-
-	/*
-	 * Place this address in the RAR if there is room,
-	 * else put the controller into promiscuous mode
-	 */
-	if (hw->addr_ctrl.rar_used_count < rar_entries) {
-		rar = hw->addr_ctrl.rar_used_count -
-		      hw->addr_ctrl.mc_addr_in_rar_count;
-		hw->mac.ops.set_rar(hw, rar, addr, vmdq, IXGBE_RAH_AV);
-		hw_dbg(hw, "Added a secondary address to RAR[%d]\n", rar);
-		hw->addr_ctrl.rar_used_count++;
-	} else {
-		hw->addr_ctrl.overflow_promisc++;
-	}
-
-	hw_dbg(hw, "ixgbe_add_uc_addr Complete\n");
-}
-
-/**
- *  ixgbe_update_uc_addr_list_generic - Updates MAC list of secondary addresses
- *  @hw: pointer to hardware structure
- *  @netdev: pointer to net device structure
- *
- *  The given list replaces any existing list.  Clears the secondary addrs from
- *  receive address registers.  Uses unused receive address registers for the
- *  first secondary addresses, and falls back to promiscuous mode as needed.
- *
- *  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,
-				      struct net_device *netdev)
-{
-	u32 i;
-	u32 old_promisc_setting = hw->addr_ctrl.overflow_promisc;
-	u32 uc_addr_in_use;
-	u32 fctrl;
-	struct netdev_hw_addr *ha;
-
-	/*
-	 * Clear accounting of old secondary address list,
-	 * don't count RAR[0]
-	 */
-	uc_addr_in_use = hw->addr_ctrl.rar_used_count - 1;
-	hw->addr_ctrl.rar_used_count -= uc_addr_in_use;
-	hw->addr_ctrl.overflow_promisc = 0;
-
-	/* Zero out the other receive addresses */
-	hw_dbg(hw, "Clearing RAR[1-%d]\n", uc_addr_in_use + 1);
-	for (i = 0; i < uc_addr_in_use; i++) {
-		IXGBE_WRITE_REG(hw, IXGBE_RAL(1+i), 0);
-		IXGBE_WRITE_REG(hw, IXGBE_RAH(1+i), 0);
-	}
-
-	/* Add the new addresses */
-	netdev_for_each_uc_addr(ha, netdev) {
-		hw_dbg(hw, " Adding the secondary addresses:\n");
-		ixgbe_add_uc_addr(hw, ha->addr, 0);
-	}
-
-	if (hw->addr_ctrl.overflow_promisc) {
-		/* enable promisc if not already in overflow or set by user */
-		if (!old_promisc_setting && !hw->addr_ctrl.user_set_promisc) {
-			hw_dbg(hw, " Entering address overflow promisc mode\n");
-			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-			fctrl |= IXGBE_FCTRL_UPE;
-			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
-			hw->addr_ctrl.uc_set_promisc = true;
-		}
-	} else {
-		/* only disable if set by overflow, not by user */
-		if ((old_promisc_setting && hw->addr_ctrl.uc_set_promisc) &&
-		   !(hw->addr_ctrl.user_set_promisc)) {
-			hw_dbg(hw, " Leaving address overflow promisc mode\n");
-			fctrl = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-			fctrl &= ~IXGBE_FCTRL_UPE;
-			IXGBE_WRITE_REG(hw, IXGBE_FCTRL, fctrl);
-			hw->addr_ctrl.uc_set_promisc = false;
-		}
-	}
-
-	hw_dbg(hw, "ixgbe_update_uc_addr_list_generic Complete\n");
-	return 0;
-}
-
-/**
  *  ixgbe_mta_vector - Determines bit-vector in multicast table to set
  *  @hw: pointer to hardware structure
  *  @mc_addr: the multicast address
@@ -1550,7 +1451,6 @@
 	u32 vector;
 	u32 vector_bit;
 	u32 vector_reg;
-	u32 mta_reg;
 
 	hw->addr_ctrl.mta_in_use++;
 
@@ -1568,9 +1468,7 @@
 	 */
 	vector_reg = (vector >> 5) & 0x7F;
 	vector_bit = vector & 0x1F;
-	mta_reg = IXGBE_READ_REG(hw, IXGBE_MTA(vector_reg));
-	mta_reg |= (1 << vector_bit);
-	IXGBE_WRITE_REG(hw, IXGBE_MTA(vector_reg), mta_reg);
+	hw->mac.mta_shadow[vector_reg] |= (1 << vector_bit);
 }
 
 /**
@@ -1596,18 +1494,21 @@
 	hw->addr_ctrl.num_mc_addrs = netdev_mc_count(netdev);
 	hw->addr_ctrl.mta_in_use = 0;
 
-	/* Clear the MTA */
+	/* Clear mta_shadow */
 	hw_dbg(hw, " Clearing MTA\n");
-	for (i = 0; i < hw->mac.mcft_size; i++)
-		IXGBE_WRITE_REG(hw, IXGBE_MTA(i), 0);
+	memset(&hw->mac.mta_shadow, 0, sizeof(hw->mac.mta_shadow));
 
-	/* Add the new addresses */
+	/* Update mta shadow */
 	netdev_for_each_mc_addr(ha, netdev) {
 		hw_dbg(hw, " Adding the multicast addresses:\n");
 		ixgbe_set_mta(hw, ha->addr);
 	}
 
 	/* Enable mta */
+	for (i = 0; i < hw->mac.mcft_size; i++)
+		IXGBE_WRITE_REG_ARRAY(hw, IXGBE_MTA(0), i,
+				      hw->mac.mta_shadow[i]);
+
 	if (hw->addr_ctrl.mta_in_use > 0)
 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL,
 		                IXGBE_MCSTCTRL_MFE | hw->mac.mc_filter_type);
@@ -1624,15 +1525,8 @@
  **/
 s32 ixgbe_enable_mc_generic(struct ixgbe_hw *hw)
 {
-	u32 i;
-	u32 rar_entries = hw->mac.num_rar_entries;
 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
 
-	if (a->mc_addr_in_rar_count > 0)
-		for (i = (rar_entries - a->mc_addr_in_rar_count);
-		     i < rar_entries; i++)
-			ixgbe_enable_rar(hw, i);
-
 	if (a->mta_in_use > 0)
 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, IXGBE_MCSTCTRL_MFE |
 		                hw->mac.mc_filter_type);
@@ -1648,15 +1542,8 @@
  **/
 s32 ixgbe_disable_mc_generic(struct ixgbe_hw *hw)
 {
-	u32 i;
-	u32 rar_entries = hw->mac.num_rar_entries;
 	struct ixgbe_addr_filter_info *a = &hw->addr_ctrl;
 
-	if (a->mc_addr_in_rar_count > 0)
-		for (i = (rar_entries - a->mc_addr_in_rar_count);
-		     i < rar_entries; i++)
-			ixgbe_disable_rar(hw, i);
-
 	if (a->mta_in_use > 0)
 		IXGBE_WRITE_REG(hw, IXGBE_MCSTCTRL, hw->mac.mc_filter_type);
 
@@ -1685,7 +1572,7 @@
 #endif /* CONFIG_DCB */
 	/* Negotiate the fc mode to use */
 	ret_val = ixgbe_fc_autoneg(hw);
-	if (ret_val)
+	if (ret_val == IXGBE_ERR_FLOW_CONTROL)
 		goto out;
 
 	/* Disable any previous flow control settings */
@@ -1703,7 +1590,9 @@
 	 * 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.current_mode) {
@@ -1791,12 +1680,13 @@
  **/
 s32 ixgbe_fc_autoneg(struct ixgbe_hw *hw)
 {
-	s32 ret_val = 0;
+	s32 ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 	ixgbe_link_speed speed;
-	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
-	u32 links2, anlp1_reg, autoc_reg, links;
 	bool link_up;
 
+	if (hw->fc.disable_fc_autoneg)
+		goto out;
+
 	/*
 	 * AN should have completed when the cable was plugged in.
 	 * Look for reasons to bail out.  Bail out if:
@@ -1807,153 +1697,199 @@
 	 * So use link_up_wait_to_complete=false.
 	 */
 	hw->mac.ops.check_link(hw, &speed, &link_up, false);
-
-	if (hw->fc.disable_fc_autoneg || (!link_up)) {
-		hw->fc.fc_was_autonegged = false;
-		hw->fc.current_mode = hw->fc.requested_mode;
+	if (!link_up) {
+		ret_val = IXGBE_ERR_FLOW_CONTROL;
 		goto out;
 	}
 
-	/*
-	 * On backplane, bail out if
-	 * - backplane autoneg was not completed, or if
-	 * - we are 82599 and link partner is not AN enabled
-	 */
-	if (hw->phy.media_type == ixgbe_media_type_backplane) {
-		links = IXGBE_READ_REG(hw, IXGBE_LINKS);
-		if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
-			hw->fc.fc_was_autonegged = false;
-			hw->fc.current_mode = hw->fc.requested_mode;
-			goto out;
-		}
+	switch (hw->phy.media_type) {
+	/* Autoneg flow control on fiber adapters */
+	case ixgbe_media_type_fiber:
+		if (speed == IXGBE_LINK_SPEED_1GB_FULL)
+			ret_val = ixgbe_fc_autoneg_fiber(hw);
+		break;
 
-		if (hw->mac.type == ixgbe_mac_82599EB) {
-			links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
-			if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
-				hw->fc.fc_was_autonegged = false;
-				hw->fc.current_mode = hw->fc.requested_mode;
-				goto out;
-			}
-		}
+	/* Autoneg flow control on backplane adapters */
+	case ixgbe_media_type_backplane:
+		ret_val = ixgbe_fc_autoneg_backplane(hw);
+		break;
+
+	/* Autoneg flow control on copper adapters */
+	case ixgbe_media_type_copper:
+		if (ixgbe_device_supports_autoneg_fc(hw) == 0)
+			ret_val = ixgbe_fc_autoneg_copper(hw);
+		break;
+
+	default:
+		break;
 	}
 
+out:
+	if (ret_val == 0) {
+		hw->fc.fc_was_autonegged = true;
+	} else {
+		hw->fc.fc_was_autonegged = false;
+		hw->fc.current_mode = hw->fc.requested_mode;
+	}
+	return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg_fiber - Enable flow control on 1 gig fiber
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according on 1 gig fiber.
+ **/
+static s32 ixgbe_fc_autoneg_fiber(struct ixgbe_hw *hw)
+{
+	u32 pcs_anadv_reg, pcs_lpab_reg, linkstat;
+	s32 ret_val;
+
 	/*
 	 * On multispeed fiber at 1g, bail out if
 	 * - link is up but AN did not complete, or if
 	 * - link is up and AN completed but timed out
 	 */
-	if (hw->phy.multispeed_fiber && (speed == IXGBE_LINK_SPEED_1GB_FULL)) {
-		linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
-		if (((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;
-			goto out;
-		}
+
+	linkstat = IXGBE_READ_REG(hw, IXGBE_PCS1GLSTA);
+	if (((linkstat & IXGBE_PCS1GLSTA_AN_COMPLETE) == 0) ||
+	    ((linkstat & IXGBE_PCS1GLSTA_AN_TIMED_OUT) == 1)) {
+		ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+		goto out;
 	}
 
+	pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+	pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
+
+	ret_val =  ixgbe_negotiate_fc(hw, pcs_anadv_reg,
+			       pcs_lpab_reg, IXGBE_PCS1GANA_SYM_PAUSE,
+			       IXGBE_PCS1GANA_ASM_PAUSE,
+			       IXGBE_PCS1GANA_SYM_PAUSE,
+			       IXGBE_PCS1GANA_ASM_PAUSE);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg_backplane - Enable flow control IEEE clause 37
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according to IEEE clause 37.
+ **/
+static s32 ixgbe_fc_autoneg_backplane(struct ixgbe_hw *hw)
+{
+	u32 links2, anlp1_reg, autoc_reg, links;
+	s32 ret_val;
+
 	/*
-	 * Bail out on
-	 * - copper or CX4 adapters
-	 * - fiber adapters running at 10gig
+	 * On backplane, bail out if
+	 * - backplane autoneg was not completed, or if
+	 * - we are 82599 and link partner is not AN enabled
 	 */
-	if ((hw->phy.media_type == ixgbe_media_type_copper) ||
-	     (hw->phy.media_type == ixgbe_media_type_cx4) ||
-	     ((hw->phy.media_type == ixgbe_media_type_fiber) &&
-	     (speed == IXGBE_LINK_SPEED_10GB_FULL))) {
+	links = IXGBE_READ_REG(hw, IXGBE_LINKS);
+	if ((links & IXGBE_LINKS_KX_AN_COMP) == 0) {
 		hw->fc.fc_was_autonegged = false;
 		hw->fc.current_mode = hw->fc.requested_mode;
+		ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
 		goto out;
 	}
 
+	if (hw->mac.type == ixgbe_mac_82599EB) {
+		links2 = IXGBE_READ_REG(hw, IXGBE_LINKS2);
+		if ((links2 & IXGBE_LINKS2_AN_SUPPORTED) == 0) {
+			hw->fc.fc_was_autonegged = false;
+			hw->fc.current_mode = hw->fc.requested_mode;
+			ret_val = IXGBE_ERR_FC_NOT_NEGOTIATED;
+			goto out;
+		}
+	}
 	/*
-	 * Read the AN advertisement and LP ability registers and resolve
+	 * Read the 10g AN autoc and LP ability registers and resolve
 	 * local flow control settings accordingly
 	 */
-	if ((speed == IXGBE_LINK_SPEED_1GB_FULL) &&
-	    (hw->phy.media_type != ixgbe_media_type_backplane)) {
-		pcs_anadv_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
-		pcs_lpab_reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANLP);
-		if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-		    (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE)) {
-			/*
-			 * Now we need to check if the user selected Rx ONLY
-			 * of pause frames.  In this case, we had to advertise
-			 * FULL flow control because we could not advertise RX
-			 * ONLY. Hence, we must now check to see if we need to
-			 * turn OFF the TRANSMISSION of PAUSE frames.
-			 */
-			if (hw->fc.requested_mode == ixgbe_fc_full) {
-				hw->fc.current_mode = ixgbe_fc_full;
-				hw_dbg(hw, "Flow Control = FULL.\n");
-			} else {
-				hw->fc.current_mode = ixgbe_fc_rx_pause;
-				hw_dbg(hw, "Flow Control=RX PAUSE only\n");
-			}
-		} else if (!(pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-			   (pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_tx_pause;
-			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
-		} else if ((pcs_anadv_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_anadv_reg & IXGBE_PCS1GANA_ASM_PAUSE) &&
-			   !(pcs_lpab_reg & IXGBE_PCS1GANA_SYM_PAUSE) &&
-			   (pcs_lpab_reg & IXGBE_PCS1GANA_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_rx_pause;
-			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
-		} else {
-			hw->fc.current_mode = ixgbe_fc_none;
-			hw_dbg(hw, "Flow Control = NONE.\n");
-		}
-	}
+	autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+	anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
 
-	if (hw->phy.media_type == ixgbe_media_type_backplane) {
+	ret_val = ixgbe_negotiate_fc(hw, autoc_reg,
+		anlp1_reg, IXGBE_AUTOC_SYM_PAUSE, IXGBE_AUTOC_ASM_PAUSE,
+		IXGBE_ANLP1_SYM_PAUSE, IXGBE_ANLP1_ASM_PAUSE);
+
+out:
+	return ret_val;
+}
+
+/**
+ *  ixgbe_fc_autoneg_copper - Enable flow control IEEE clause 37
+ *  @hw: pointer to hardware structure
+ *
+ *  Enable flow control according to IEEE clause 37.
+ **/
+static s32 ixgbe_fc_autoneg_copper(struct ixgbe_hw *hw)
+{
+	u16 technology_ability_reg = 0;
+	u16 lp_technology_ability_reg = 0;
+
+	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+			     MDIO_MMD_AN,
+			     &technology_ability_reg);
+	hw->phy.ops.read_reg(hw, MDIO_AN_LPA,
+			     MDIO_MMD_AN,
+			     &lp_technology_ability_reg);
+
+	return ixgbe_negotiate_fc(hw, (u32)technology_ability_reg,
+				  (u32)lp_technology_ability_reg,
+				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE,
+				  IXGBE_TAF_SYM_PAUSE, IXGBE_TAF_ASM_PAUSE);
+}
+
+/**
+ *  ixgbe_negotiate_fc - Negotiate flow control
+ *  @hw: pointer to hardware structure
+ *  @adv_reg: flow control advertised settings
+ *  @lp_reg: link partner's flow control settings
+ *  @adv_sym: symmetric pause bit in advertisement
+ *  @adv_asm: asymmetric pause bit in advertisement
+ *  @lp_sym: symmetric pause bit in link partner advertisement
+ *  @lp_asm: asymmetric pause bit in link partner advertisement
+ *
+ *  Find the intersection between advertised settings and link partner's
+ *  advertised settings
+ **/
+static s32 ixgbe_negotiate_fc(struct ixgbe_hw *hw, u32 adv_reg, u32 lp_reg,
+			      u32 adv_sym, u32 adv_asm, u32 lp_sym, u32 lp_asm)
+{
+	if ((!(adv_reg)) ||  (!(lp_reg)))
+		return IXGBE_ERR_FC_NOT_NEGOTIATED;
+
+	if ((adv_reg & adv_sym) && (lp_reg & lp_sym)) {
 		/*
-		 * Read the 10g AN autoc and LP ability registers and resolve
-		 * local flow control settings accordingly
+		 * Now we need to check if the user selected Rx ONLY
+		 * of pause frames.  In this case, we had to advertise
+		 * FULL flow control because we could not advertise RX
+		 * ONLY. Hence, we must now check to see if we need to
+		 * turn OFF the TRANSMISSION of PAUSE frames.
 		 */
-		autoc_reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
-		anlp1_reg = IXGBE_READ_REG(hw, IXGBE_ANLP1);
-
-		if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
-		    (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE)) {
-			/*
-			 * Now we need to check if the user selected Rx ONLY
-			 * of pause frames.  In this case, we had to advertise
-			 * FULL flow control because we could not advertise RX
-			 * ONLY. Hence, we must now check to see if we need to
-			 * turn OFF the TRANSMISSION of PAUSE frames.
-			 */
-			if (hw->fc.requested_mode == ixgbe_fc_full) {
-				hw->fc.current_mode = ixgbe_fc_full;
-				hw_dbg(hw, "Flow Control = FULL.\n");
-			} else {
-				hw->fc.current_mode = ixgbe_fc_rx_pause;
-				hw_dbg(hw, "Flow Control=RX PAUSE only\n");
-			}
-		} else if (!(autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
-			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
-			   (anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
-			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_tx_pause;
-			hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
-		} else if ((autoc_reg & IXGBE_AUTOC_SYM_PAUSE) &&
-			   (autoc_reg & IXGBE_AUTOC_ASM_PAUSE) &&
-			   !(anlp1_reg & IXGBE_ANLP1_SYM_PAUSE) &&
-			   (anlp1_reg & IXGBE_ANLP1_ASM_PAUSE)) {
-			hw->fc.current_mode = ixgbe_fc_rx_pause;
-			hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+		if (hw->fc.requested_mode == ixgbe_fc_full) {
+			hw->fc.current_mode = ixgbe_fc_full;
+			hw_dbg(hw, "Flow Control = FULL.\n");
 		} else {
-			hw->fc.current_mode = ixgbe_fc_none;
-			hw_dbg(hw, "Flow Control = NONE.\n");
+			hw->fc.current_mode = ixgbe_fc_rx_pause;
+			hw_dbg(hw, "Flow Control=RX PAUSE frames only\n");
 		}
+	} else if (!(adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+		   (lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+		hw->fc.current_mode = ixgbe_fc_tx_pause;
+		hw_dbg(hw, "Flow Control = TX PAUSE frames only.\n");
+	} else if ((adv_reg & adv_sym) && (adv_reg & adv_asm) &&
+		   !(lp_reg & lp_sym) && (lp_reg & lp_asm)) {
+		hw->fc.current_mode = ixgbe_fc_rx_pause;
+		hw_dbg(hw, "Flow Control = RX PAUSE frames only.\n");
+	} else {
+		hw->fc.current_mode = ixgbe_fc_none;
+		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;
+	return 0;
 }
 
 /**
@@ -1965,7 +1901,8 @@
 static s32 ixgbe_setup_fc(struct ixgbe_hw *hw, s32 packetbuf_num)
 {
 	s32 ret_val = 0;
-	u32 reg;
+	u32 reg = 0, reg_bp = 0;
+	u16 reg_cu = 0;
 
 #ifdef CONFIG_DCB
 	if (hw->fc.requested_mode == ixgbe_fc_pfc) {
@@ -1973,7 +1910,7 @@
 		goto out;
 	}
 
-#endif
+#endif /* CONFIG_DCB */
 	/* Validate the packetbuf configuration */
 	if (packetbuf_num < 0 || packetbuf_num > 7) {
 		hw_dbg(hw, "Invalid packet buffer number [%d], expected range "
@@ -2011,11 +1948,26 @@
 		hw->fc.requested_mode = ixgbe_fc_full;
 
 	/*
-	 * 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.
+	 * Set up the 1G and 10G flow control advertisement registers so the
+	 * HW will be able to do fc autoneg once the cable is plugged in.  If
+	 * we link at 10G, the 1G advertisement is harmless and vice versa.
 	 */
-	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+
+	switch (hw->phy.media_type) {
+	case ixgbe_media_type_fiber:
+	case ixgbe_media_type_backplane:
+		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GANA);
+		reg_bp = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+		break;
+
+	case ixgbe_media_type_copper:
+		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+					MDIO_MMD_AN, &reg_cu);
+		break;
+
+	default:
+		;
+	}
 
 	/*
 	 * The possible values of fc.requested_mode are:
@@ -2034,6 +1986,11 @@
 	case ixgbe_fc_none:
 		/* Flow control completely disabled by software override. */
 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane)
+			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE |
+				    IXGBE_AUTOC_ASM_PAUSE);
+		else if (hw->phy.media_type == ixgbe_media_type_copper)
+			reg_cu &= ~(IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
 		break;
 	case ixgbe_fc_rx_pause:
 		/*
@@ -2045,6 +2002,11 @@
 		 * disable the adapter's ability to send PAUSE frames.
 		 */
 		reg |= (IXGBE_PCS1GANA_SYM_PAUSE | IXGBE_PCS1GANA_ASM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane)
+			reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+				   IXGBE_AUTOC_ASM_PAUSE);
+		else if (hw->phy.media_type == ixgbe_media_type_copper)
+			reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
 		break;
 	case ixgbe_fc_tx_pause:
 		/*
@@ -2053,10 +2015,22 @@
 		 */
 		reg |= (IXGBE_PCS1GANA_ASM_PAUSE);
 		reg &= ~(IXGBE_PCS1GANA_SYM_PAUSE);
+		if (hw->phy.media_type == ixgbe_media_type_backplane) {
+			reg_bp |= (IXGBE_AUTOC_ASM_PAUSE);
+			reg_bp &= ~(IXGBE_AUTOC_SYM_PAUSE);
+		} else if (hw->phy.media_type == ixgbe_media_type_copper) {
+			reg_cu |= (IXGBE_TAF_ASM_PAUSE);
+			reg_cu &= ~(IXGBE_TAF_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);
+		if (hw->phy.media_type == ixgbe_media_type_backplane)
+			reg_bp |= (IXGBE_AUTOC_SYM_PAUSE |
+				   IXGBE_AUTOC_ASM_PAUSE);
+		else if (hw->phy.media_type == ixgbe_media_type_copper)
+			reg_cu |= (IXGBE_TAF_SYM_PAUSE | IXGBE_TAF_ASM_PAUSE);
 		break;
 #ifdef CONFIG_DCB
 	case ixgbe_fc_pfc:
@@ -2070,80 +2044,37 @@
 		break;
 	}
 
-	IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
-	reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
-
-	/* Disable AN timeout */
-	if (hw->fc.strict_ieee)
-		reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
+	if (hw->mac.type != ixgbe_mac_X540) {
+		/*
+		 * Enable auto-negotiation between the MAC & PHY;
+		 * the MAC will advertise clause 37 flow control.
+		 */
+		IXGBE_WRITE_REG(hw, IXGBE_PCS1GANA, reg);
+		reg = IXGBE_READ_REG(hw, IXGBE_PCS1GLCTL);
 
-	IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
-	hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+		/* Disable AN timeout */
+		if (hw->fc.strict_ieee)
+			reg &= ~IXGBE_PCS1GLCTL_AN_1G_TIMEOUT_EN;
 
-	/*
-	 * Set up the 10G flow control advertisement registers so the HW
-	 * can do fc autoneg once the cable is plugged in.  If we end up
-	 * using 1g instead, this is harmless.
-	 */
-	reg = IXGBE_READ_REG(hw, IXGBE_AUTOC);
+		IXGBE_WRITE_REG(hw, IXGBE_PCS1GLCTL, reg);
+		hw_dbg(hw, "Set up FC; PCS1GLCTL = 0x%08X\n", reg);
+	}
 
 	/*
-	 * 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.
-	 * other: Invalid.
+	 * AUTOC restart handles negotiation of 1G and 10G on backplane
+	 * and copper. There is no need to set the PCS1GCTL register.
+	 *
 	 */
-	switch (hw->fc.requested_mode) {
-	case ixgbe_fc_none:
-		/* Flow control completely disabled by software override. */
-		reg &= ~(IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_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_AUTOC_SYM_PAUSE | IXGBE_AUTOC_ASM_PAUSE);
-		break;
-	case ixgbe_fc_tx_pause:
-		/*
-		 * Tx Flow control is enabled, and Rx Flow control is
-		 * disabled by software override.
-		 */
-		reg |= (IXGBE_AUTOC_ASM_PAUSE);
-		reg &= ~(IXGBE_AUTOC_SYM_PAUSE);
-		break;
-	case ixgbe_fc_full:
-		/* Flow control (both Rx and Tx) is enabled by SW override. */
-		reg |= (IXGBE_AUTOC_SYM_PAUSE | IXGBE_AUTOC_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;
+	if (hw->phy.media_type == ixgbe_media_type_backplane) {
+		reg_bp |= IXGBE_AUTOC_AN_RESTART;
+		IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg_bp);
+	} else if ((hw->phy.media_type == ixgbe_media_type_copper) &&
+		    (ixgbe_device_supports_autoneg_fc(hw) == 0)) {
+		hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE,
+				      MDIO_MMD_AN, reg_cu);
 	}
-	/*
-	 * AUTOC restart handles negotiation of 1G and 10G. There is
-	 * no need to set the PCS1GCTL register.
-	 */
-	reg |= IXGBE_AUTOC_AN_RESTART;
-	IXGBE_WRITE_REG(hw, IXGBE_AUTOC, reg);
-	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
 
+	hw_dbg(hw, "Set up FC; IXGBE_AUTOC = 0x%08X\n", reg);
 out:
 	return ret_val;
 }
@@ -2159,10 +2090,16 @@
  **/
 s32 ixgbe_disable_pcie_master(struct ixgbe_hw *hw)
 {
+	struct ixgbe_adapter *adapter = hw->back;
 	u32 i;
 	u32 reg_val;
 	u32 number_of_queues;
-	s32 status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+	s32 status = 0;
+	u16 dev_status = 0;
+
+	/* Just jump out if bus mastering is already disabled */
+	if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+		goto out;
 
 	/* Disable the receive unit by stopping each queue */
 	number_of_queues = hw->mac.max_rx_queues;
@@ -2179,13 +2116,43 @@
 	IXGBE_WRITE_REG(hw, IXGBE_CTRL, reg_val);
 
 	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
-		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO)) {
-			status = 0;
+		if (!(IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_GIO))
+			goto check_device_status;
+		udelay(100);
+	}
+
+	hw_dbg(hw, "GIO Master Disable bit didn't clear - requesting resets\n");
+	status = IXGBE_ERR_MASTER_REQUESTS_PENDING;
+
+	/*
+	 * Before proceeding, make sure that the PCIe block does not have
+	 * transactions pending.
+	 */
+check_device_status:
+	for (i = 0; i < IXGBE_PCI_MASTER_DISABLE_TIMEOUT; i++) {
+		pci_read_config_word(adapter->pdev, IXGBE_PCI_DEVICE_STATUS,
+							 &dev_status);
+		if (!(dev_status & IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING))
 			break;
-		}
 		udelay(100);
 	}
 
+	if (i == IXGBE_PCI_MASTER_DISABLE_TIMEOUT)
+		hw_dbg(hw, "PCIe transaction pending bit also did not clear.\n");
+	else
+		goto out;
+
+	/*
+	 * Two consecutive resets are required via CTRL.RST per datasheet
+	 * 5.2.5.3.2 Master Disable.  We set a flag to inform the reset routine
+	 * of this need.  The first reset prevents new master requests from
+	 * being issued by our device.  We then must wait 1usec for any
+	 * remaining completions from the PCIe bus to trickle in, and then reset
+	 * again to clear out any effects they may have had on our device.
+	 */
+	 hw->mac.flags |= IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+
+out:
 	return status;
 }
 
@@ -2195,7 +2162,7 @@
  *  @hw: pointer to hardware structure
  *  @mask: Mask to specify which semaphore to acquire
  *
- *  Acquires the SWFW semaphore thought the GSSR register for the specified
+ *  Acquires the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
 s32 ixgbe_acquire_swfw_sync(struct ixgbe_hw *hw, u16 mask)
@@ -2206,6 +2173,10 @@
 	s32 timeout = 200;
 
 	while (timeout) {
+		/*
+		 * SW EEPROM semaphore bit is used for access to all
+		 * SW_FW_SYNC/GSSR bits (not just EEPROM)
+		 */
 		if (ixgbe_get_eeprom_semaphore(hw))
 			return IXGBE_ERR_SWFW_SYNC;
 
@@ -2223,7 +2194,7 @@
 	}
 
 	if (!timeout) {
-		hw_dbg(hw, "Driver can't access resource, GSSR timeout.\n");
+		hw_dbg(hw, "Driver can't access resource, SW_FW_SYNC timeout.\n");
 		return IXGBE_ERR_SWFW_SYNC;
 	}
 
@@ -2239,7 +2210,7 @@
  *  @hw: pointer to hardware structure
  *  @mask: Mask to specify which semaphore to release
  *
- *  Releases the SWFW semaphore thought the GSSR register for the specified
+ *  Releases the SWFW semaphore through the GSSR register for the specified
  *  function (CSR, PHY0, PHY1, EEPROM, Flash)
  **/
 void ixgbe_release_swfw_sync(struct ixgbe_hw *hw, u16 mask)
@@ -2427,37 +2398,38 @@
 	u32 mpsar_lo, mpsar_hi;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
-	if (rar < rar_entries) {
-		mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
-		mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
+		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
 
-		if (!mpsar_lo && !mpsar_hi)
-			goto done;
+	mpsar_lo = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+	mpsar_hi = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
 
-		if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
-			if (mpsar_lo) {
-				IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
-				mpsar_lo = 0;
-			}
-			if (mpsar_hi) {
-				IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
-				mpsar_hi = 0;
-			}
-		} else if (vmdq < 32) {
-			mpsar_lo &= ~(1 << vmdq);
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
-		} else {
-			mpsar_hi &= ~(1 << (vmdq - 32));
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
-		}
+	if (!mpsar_lo && !mpsar_hi)
+		goto done;
 
-		/* was that the last pool using this rar? */
-		if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
-			hw->mac.ops.clear_rar(hw, rar);
+	if (vmdq == IXGBE_CLEAR_VMDQ_ALL) {
+		if (mpsar_lo) {
+			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), 0);
+			mpsar_lo = 0;
+		}
+		if (mpsar_hi) {
+			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), 0);
+			mpsar_hi = 0;
+		}
+	} else if (vmdq < 32) {
+		mpsar_lo &= ~(1 << vmdq);
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar_lo);
 	} else {
-		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		mpsar_hi &= ~(1 << (vmdq - 32));
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar_hi);
 	}
 
+	/* was that the last pool using this rar? */
+	if (mpsar_lo == 0 && mpsar_hi == 0 && rar != 0)
+		hw->mac.ops.clear_rar(hw, rar);
 done:
 	return 0;
 }
@@ -2473,18 +2445,20 @@
 	u32 mpsar;
 	u32 rar_entries = hw->mac.num_rar_entries;
 
-	if (rar < rar_entries) {
-		if (vmdq < 32) {
-			mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
-			mpsar |= 1 << vmdq;
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
-		} else {
-			mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
-			mpsar |= 1 << (vmdq - 32);
-			IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
-		}
-	} else {
+	/* Make sure we are using a valid rar index range */
+	if (rar >= rar_entries) {
 		hw_dbg(hw, "RAR index %d is out of range.\n", rar);
+		return IXGBE_ERR_INVALID_ARGUMENT;
+	}
+
+	if (vmdq < 32) {
+		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_LO(rar));
+		mpsar |= 1 << vmdq;
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_LO(rar), mpsar);
+	} else {
+		mpsar = IXGBE_READ_REG(hw, IXGBE_MPSAR_HI(rar));
+		mpsar |= 1 << (vmdq - 32);
+		IXGBE_WRITE_REG(hw, IXGBE_MPSAR_HI(rar), mpsar);
 	}
 	return 0;
 }
@@ -2497,7 +2471,6 @@
 {
 	int i;
 
-
 	for (i = 0; i < 128; i++)
 		IXGBE_WRITE_REG(hw, IXGBE_UTA(i), 0);
 
@@ -2726,12 +2699,21 @@
  *  Reads the links register to determine if link is up and the current speed
  **/
 s32 ixgbe_check_mac_link_generic(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
-                               bool *link_up, bool link_up_wait_to_complete)
+				 bool *link_up, bool link_up_wait_to_complete)
 {
-	u32 links_reg;
+	u32 links_reg, links_orig;
 	u32 i;
 
+	/* clear the old state */
+	links_orig = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
 	links_reg = IXGBE_READ_REG(hw, IXGBE_LINKS);
+
+	if (links_orig != links_reg) {
+		hw_dbg(hw, "LINKS changed from %08X to %08X\n",
+		       links_orig, links_reg);
+	}
+
 	if (link_up_wait_to_complete) {
 		for (i = 0; i < IXGBE_LINK_UP_TIME; i++) {
 			if (links_reg & IXGBE_LINKS_UP) {
@@ -2754,10 +2736,13 @@
 	    IXGBE_LINKS_SPEED_10G_82599)
 		*speed = IXGBE_LINK_SPEED_10GB_FULL;
 	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
-	         IXGBE_LINKS_SPEED_1G_82599)
+		 IXGBE_LINKS_SPEED_1G_82599)
 		*speed = IXGBE_LINK_SPEED_1GB_FULL;
-	else
+	else if ((links_reg & IXGBE_LINKS_SPEED_82599) ==
+		 IXGBE_LINKS_SPEED_100_82599)
 		*speed = IXGBE_LINK_SPEED_100_FULL;
+	else
+		*speed = IXGBE_LINK_SPEED_UNKNOWN;
 
 	/* if link is down, zero out the current_mode */
 	if (*link_up == false) {
@@ -2814,6 +2799,28 @@
 }
 
 /**
+ *  ixgbe_device_supports_autoneg_fc - Check if phy supports autoneg flow
+ *  control
+ *  @hw: pointer to hardware structure
+ *
+ *  There are several phys that do not support autoneg flow control. This
+ *  function check the device id to see if the associated phy supports
+ *  autoneg flow control.
+ **/
+static s32 ixgbe_device_supports_autoneg_fc(struct ixgbe_hw *hw)
+{
+
+	switch (hw->device_id) {
+	case IXGBE_DEV_ID_X540T:
+		return 0;
+	case IXGBE_DEV_ID_82599_T3_LOM:
+		return 0;
+	default:
+		return IXGBE_ERR_FC_NOT_SUPPORTED;
+	}
+}
+
+/**
  *  ixgbe_set_mac_anti_spoofing - Enable/Disable MAC anti-spoofing
  *  @hw: pointer to hardware structure
  *  @enable: enable or disable switch for anti-spoofing
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_common.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_common.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -29,6 +29,7 @@
 #define _IXGBE_COMMON_H_
 
 #include "ixgbe_type.h"
+#include "ixgbe.h"
 
 u32 ixgbe_get_pcie_msix_count_generic(struct ixgbe_hw *hw);
 s32 ixgbe_init_ops_generic(struct ixgbe_hw *hw);
@@ -62,8 +63,6 @@
 s32 ixgbe_init_rx_addrs_generic(struct ixgbe_hw *hw);
 s32 ixgbe_update_mc_addr_list_generic(struct ixgbe_hw *hw,
 				      struct net_device *netdev);
-s32 ixgbe_update_uc_addr_list_generic(struct ixgbe_hw *hw,
-				      struct net_device *netdev);
 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);
@@ -110,9 +109,8 @@
 
 #define IXGBE_WRITE_FLUSH(a) IXGBE_READ_REG(a, IXGBE_STATUS)
 
-extern struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw);
 #define hw_dbg(hw, format, arg...) \
-	netdev_dbg(ixgbe_get_hw_dev(hw), format, ##arg)
+	netdev_dbg(((struct ixgbe_adapter *)(hw->back))->netdev, format, ##arg)
 #define e_dev_info(format, arg...) \
 	dev_info(&adapter->pdev->dev, format, ## arg)
 #define e_dev_warn(format, arg...) \
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -38,15 +38,14 @@
  *
  * Configure packet buffers for DCB mode.
  */
-static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw,
-						 struct ixgbe_dcb_config *dcb_config)
+static s32 ixgbe_dcb_config_packet_buffers_82598(struct ixgbe_hw *hw, u8 rx_pba)
 {
 	s32 ret_val = 0;
 	u32 value = IXGBE_RXPBSIZE_64KB;
 	u8  i = 0;
 
 	/* Setup Rx packet buffer sizes */
-	switch (dcb_config->rx_pba_cfg) {
+	switch (rx_pba) {
 	case pba_80_48:
 		/* Setup the first four at 80KB */
 		value = IXGBE_RXPBSIZE_80KB;
@@ -78,10 +77,11 @@
  *
  * Configure Rx Data Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
-                                      struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+					u16 *refill,
+					u16 *max,
+					u8 *prio_type)
 {
-	struct tc_bw_alloc    *p;
 	u32    reg           = 0;
 	u32    credit_refill = 0;
 	u32    credit_max    = 0;
@@ -102,13 +102,12 @@
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG];
-		credit_refill = p->data_credits_refill;
-		credit_max    = p->data_credits_max;
+		credit_refill = refill[i];
+		credit_max    = max[i];
 
 		reg = credit_refill | (credit_max << IXGBE_RT2CR_MCL_SHIFT);
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RT2CR_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RT2CR(i), reg);
@@ -135,10 +134,12 @@
  *
  * Configure Tx Descriptor Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type)
 {
-	struct tc_bw_alloc *p;
 	u32    reg, max_credits;
 	u8     i;
 
@@ -146,10 +147,8 @@
 
 	/* Enable arbiter */
 	reg &= ~IXGBE_DPMCS_ARBDIS;
-	if (!(dcb_config->round_robin_enable)) {
-		/* Enable DFP and Recycle mode */
-		reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
-	}
+	/* Enable DFP and Recycle mode */
+	reg |= (IXGBE_DPMCS_TDPAC | IXGBE_DPMCS_TRM);
 	reg |= IXGBE_DPMCS_TSOEF;
 	/* Configure Max TSO packet size 34KB including payload and headers */
 	reg |= (0x4 << IXGBE_DPMCS_MTSOS_SHIFT);
@@ -158,16 +157,15 @@
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		max_credits = dcb_config->tc_config[i].desc_credits_max;
+		max_credits = max[i];
 		reg = max_credits << IXGBE_TDTQ2TCCR_MCL_SHIFT;
-		reg |= p->data_credits_refill;
-		reg |= (u32)(p->bwg_id) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
+		reg |= refill[i];
+		reg |= (u32)(bwg_id[i]) << IXGBE_TDTQ2TCCR_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_TDTQ2TCCR_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_TDTQ2TCCR_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_TDTQ2TCCR(i), reg);
@@ -183,10 +181,12 @@
  *
  * Configure Tx Data Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type)
 {
-	struct tc_bw_alloc *p;
 	u32 reg;
 	u8 i;
 
@@ -200,15 +200,14 @@
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		reg = p->data_credits_refill;
-		reg |= (u32)(p->data_credits_max) << IXGBE_TDPT2TCCR_MCL_SHIFT;
-		reg |= (u32)(p->bwg_id) << IXGBE_TDPT2TCCR_BWG_SHIFT;
+		reg = refill[i];
+		reg |= (u32)(max[i]) << IXGBE_TDPT2TCCR_MCL_SHIFT;
+		reg |= (u32)(bwg_id[i]) << IXGBE_TDPT2TCCR_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_TDPT2TCCR_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_TDPT2TCCR_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_TDPT2TCCR(i), reg);
@@ -229,59 +228,57 @@
  *
  * Configure Priority Flow Control for each traffic class.
  */
-s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw,
-                               struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *hw, u8 pfc_en)
 {
 	u32 reg, rx_pba_size;
 	u8  i;
 
-	if (!dcb_config->pfc_mode_enable)
-		goto out;
+	if (pfc_en) {
+		/* Enable Transmit Priority Flow Control */
+		reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
+		reg &= ~IXGBE_RMCS_TFCE_802_3X;
+		/* correct the reporting of our flow control status */
+		reg |= IXGBE_RMCS_TFCE_PRIORITY;
+		IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
 
-	/* Enable Transmit Priority Flow Control */
-	reg = IXGBE_READ_REG(hw, IXGBE_RMCS);
-	reg &= ~IXGBE_RMCS_TFCE_802_3X;
-	/* correct the reporting of our flow control status */
-	reg |= IXGBE_RMCS_TFCE_PRIORITY;
-	IXGBE_WRITE_REG(hw, IXGBE_RMCS, reg);
+		/* Enable Receive Priority Flow Control */
+		reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
+		reg &= ~IXGBE_FCTRL_RFCE;
+		reg |= IXGBE_FCTRL_RPFCE;
+		IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
 
-	/* Enable Receive Priority Flow Control */
-	reg = IXGBE_READ_REG(hw, IXGBE_FCTRL);
-	reg &= ~IXGBE_FCTRL_RFCE;
-	reg |= IXGBE_FCTRL_RPFCE;
-	IXGBE_WRITE_REG(hw, IXGBE_FCTRL, reg);
+		/* Configure pause time */
+		for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
+			IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
+
+		/* Configure flow control refresh threshold value */
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
+	}
 
 	/*
 	 * Configure flow control thresholds and enable priority flow control
 	 * for each traffic class.
 	 */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		int enabled = pfc_en & (1 << i);
 		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
 		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 		reg = (rx_pba_size - hw->fc.low_water) << 10;
 
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
+		if (enabled == pfc_enabled_tx ||
+		    enabled == pfc_enabled_full)
 			reg |= IXGBE_FCRTL_XONE;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL(i), reg);
 
 		reg = (rx_pba_size - hw->fc.high_water) << 10;
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full)
+		if (enabled == pfc_enabled_tx ||
+		    enabled == pfc_enabled_full)
 			reg |= IXGBE_FCRTH_FCEN;
 
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH(i), reg);
 	}
 
-	/* Configure pause time */
-	for (i = 0; i < (MAX_TRAFFIC_CLASS >> 1); i++)
-		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), 0x68006800);
-
-	/* Configure flow control refresh threshold value */
-	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, 0x3400);
-
-out:
 	return 0;
 }
 
@@ -292,7 +289,7 @@
  * Configure queue statistics registers, all queues belonging to same traffic
  * class uses a single set of queue statistics counters.
  */
-static s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
+s32 ixgbe_dcb_config_tc_stats_82598(struct ixgbe_hw *hw)
 {
 	u32 reg = 0;
 	u8  i   = 0;
@@ -325,13 +322,16 @@
  * Configure dcb settings and enable dcb mode.
  */
 s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
-                              struct ixgbe_dcb_config *dcb_config)
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type)
 {
-	ixgbe_dcb_config_packet_buffers_82598(hw, dcb_config);
-	ixgbe_dcb_config_rx_arbiter_82598(hw, dcb_config);
-	ixgbe_dcb_config_tx_desc_arbiter_82598(hw, dcb_config);
-	ixgbe_dcb_config_tx_data_arbiter_82598(hw, dcb_config);
-	ixgbe_dcb_config_pfc_82598(hw, dcb_config);
+	ixgbe_dcb_config_packet_buffers_82598(hw, rx_pba);
+	ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max, prio_type);
+	ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
+					       bwg_id, prio_type);
+	ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
+					       bwg_id, prio_type);
+	ixgbe_dcb_config_pfc_82598(hw, pfc_en);
 	ixgbe_dcb_config_tc_stats_82598(hw);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82598.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -71,9 +71,28 @@
 /* DCB hardware-specific driver APIs */
 
 /* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_pfc_82598(struct ixgbe_hw *, u8 pfc_en);
 
 /* DCB hw initialization */
-s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *, struct ixgbe_dcb_config *);
+s32 ixgbe_dcb_config_rx_arbiter_82598(struct ixgbe_hw *hw,
+					u16 *refill,
+					u16 *max,
+					u8 *prio_type);
+
+s32 ixgbe_dcb_config_tx_desc_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type);
+
+s32 ixgbe_dcb_config_tx_data_arbiter_82598(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type);
+
+s32 ixgbe_dcb_hw_config_82598(struct ixgbe_hw *hw,
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type);
 
 #endif /* _DCB_82598_CONFIG_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -33,19 +33,18 @@
 /**
  * ixgbe_dcb_config_packet_buffers_82599 - Configure DCB packet buffers
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @rx_pba: method to distribute packet buffer
  *
  * Configure packet buffers for DCB mode.
  */
-static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw,
-                                          struct ixgbe_dcb_config *dcb_config)
+static s32 ixgbe_dcb_config_packet_buffers_82599(struct ixgbe_hw *hw, u8 rx_pba)
 {
 	s32 ret_val = 0;
 	u32 value = IXGBE_RXPBSIZE_64KB;
 	u8  i = 0;
 
 	/* Setup Rx packet buffer sizes */
-	switch (dcb_config->rx_pba_cfg) {
+	switch (rx_pba) {
 	case pba_80_48:
 		/* Setup the first four at 80KB */
 		value = IXGBE_RXPBSIZE_80KB;
@@ -75,14 +74,20 @@
 /**
  * ixgbe_dcb_config_rx_arbiter_82599 - Config Rx Data arbiter
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
  *
  * Configure Rx Packet Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
-                                      struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
+				      u16 *refill,
+				      u16 *max,
+				      u8 *bwg_id,
+				      u8 *prio_type,
+				      u8 *prio_tc)
 {
-	struct tc_bw_alloc    *p;
 	u32    reg           = 0;
 	u32    credit_refill = 0;
 	u32    credit_max    = 0;
@@ -98,20 +103,18 @@
 	/* Map all traffic classes to their UP, 1 to 1 */
 	reg = 0;
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
-		reg |= (i << (i * IXGBE_RTRUP2TC_UP_SHIFT));
+		reg |= (prio_tc[i] << (i * IXGBE_RTRUP2TC_UP_SHIFT));
 	IXGBE_WRITE_REG(hw, IXGBE_RTRUP2TC, reg);
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_RX_CONFIG];
-
-		credit_refill = p->data_credits_refill;
-		credit_max    = p->data_credits_max;
+		credit_refill = refill[i];
+		credit_max    = max[i];
 		reg = credit_refill | (credit_max << IXGBE_RTRPT4C_MCL_SHIFT);
 
-		reg |= (u32)(p->bwg_id) << IXGBE_RTRPT4C_BWG_SHIFT;
+		reg |= (u32)(bwg_id[i]) << IXGBE_RTRPT4C_BWG_SHIFT;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RTRPT4C_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RTRPT4C(i), reg);
@@ -130,14 +133,19 @@
 /**
  * ixgbe_dcb_config_tx_desc_arbiter_82599 - Config Tx Desc. arbiter
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
  *
  * Configure Tx Descriptor Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
+					   u16 *refill,
+					   u16 *max,
+					   u8 *bwg_id,
+					   u8 *prio_type)
 {
-	struct tc_bw_alloc *p;
 	u32    reg, max_credits;
 	u8     i;
 
@@ -149,16 +157,15 @@
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		max_credits = dcb_config->tc_config[i].desc_credits_max;
+		max_credits = max[i];
 		reg = max_credits << IXGBE_RTTDT2C_MCL_SHIFT;
-		reg |= p->data_credits_refill;
-		reg |= (u32)(p->bwg_id) << IXGBE_RTTDT2C_BWG_SHIFT;
+		reg |= refill[i];
+		reg |= (u32)(bwg_id[i]) << IXGBE_RTTDT2C_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_RTTDT2C_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RTTDT2C_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RTTDT2C(i), reg);
@@ -177,14 +184,20 @@
 /**
  * ixgbe_dcb_config_tx_data_arbiter_82599 - Config Tx Data arbiter
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
  *
  * Configure Tx Packet Arbiter and credits for each traffic class.
  */
-static s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
-                                           struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
+					   u16 *refill,
+					   u16 *max,
+					   u8 *bwg_id,
+					   u8 *prio_type,
+					   u8 *prio_tc)
 {
-	struct tc_bw_alloc *p;
 	u32 reg;
 	u8 i;
 
@@ -200,20 +213,19 @@
 	/* Map all traffic classes to their UP, 1 to 1 */
 	reg = 0;
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
-		reg |= (i << (i * IXGBE_RTTUP2TC_UP_SHIFT));
+		reg |= (prio_tc[i] << (i * IXGBE_RTTUP2TC_UP_SHIFT));
 	IXGBE_WRITE_REG(hw, IXGBE_RTTUP2TC, reg);
 
 	/* Configure traffic class credits and priority */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
-		p = &dcb_config->tc_config[i].path[DCB_TX_CONFIG];
-		reg = p->data_credits_refill;
-		reg |= (u32)(p->data_credits_max) << IXGBE_RTTPT2C_MCL_SHIFT;
-		reg |= (u32)(p->bwg_id) << IXGBE_RTTPT2C_BWG_SHIFT;
+		reg = refill[i];
+		reg |= (u32)(max[i]) << IXGBE_RTTPT2C_MCL_SHIFT;
+		reg |= (u32)(bwg_id[i]) << IXGBE_RTTPT2C_BWG_SHIFT;
 
-		if (p->prio_type == prio_group)
+		if (prio_type[i] == prio_group)
 			reg |= IXGBE_RTTPT2C_GSP;
 
-		if (p->prio_type == prio_link)
+		if (prio_type[i] == prio_link)
 			reg |= IXGBE_RTTPT2C_LSP;
 
 		IXGBE_WRITE_REG(hw, IXGBE_RTTPT2C(i), reg);
@@ -233,63 +245,59 @@
 /**
  * ixgbe_dcb_config_pfc_82599 - Configure priority flow control
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @pfc_en: enabled pfc bitmask
  *
  * Configure Priority Flow Control (PFC) for each traffic class.
  */
-s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw,
-                               struct ixgbe_dcb_config *dcb_config)
+s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en)
 {
 	u32 i, reg, rx_pba_size;
 
-	/* 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.fc_enable(hw, i);
-		goto out;
-	}
-
 	/* Configure PFC Tx thresholds per TC */
 	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		int enabled = pfc_en & (1 << i);
 		rx_pba_size = IXGBE_READ_REG(hw, IXGBE_RXPBSIZE(i));
 		rx_pba_size >>= IXGBE_RXPBSIZE_SHIFT;
 
 		reg = (rx_pba_size - hw->fc.low_water) << 10;
 
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx)
+		if (enabled)
 			reg |= IXGBE_FCRTL_XONE;
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTL_82599(i), reg);
 
 		reg = (rx_pba_size - hw->fc.high_water) << 10;
-		if (dcb_config->tc_config[i].dcb_pfc == pfc_enabled_full ||
-		    dcb_config->tc_config[i].dcb_pfc == pfc_enabled_tx)
+		if (enabled)
 			reg |= IXGBE_FCRTH_FCEN;
 		IXGBE_WRITE_REG(hw, IXGBE_FCRTH_82599(i), reg);
 	}
 
-	/* Configure pause time (2 TCs per register) */
-	reg = hw->fc.pause_time | (hw->fc.pause_time << 16);
-	for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
-		IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
+	if (pfc_en) {
+		/* Configure pause time (2 TCs per register) */
+		reg = hw->fc.pause_time | (hw->fc.pause_time << 16);
+		for (i = 0; i < (MAX_TRAFFIC_CLASS / 2); i++)
+			IXGBE_WRITE_REG(hw, IXGBE_FCTTV(i), reg);
 
-	/* Configure flow control refresh threshold value */
-	IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
+		/* Configure flow control refresh threshold value */
+		IXGBE_WRITE_REG(hw, IXGBE_FCRTV, hw->fc.pause_time / 2);
 
-	/* Enable Transmit PFC */
-	reg = IXGBE_FCCFG_TFCE_PRIORITY;
-	IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg);
 
-	/*
-	 * Enable Receive PFC
-	 * We will always honor XOFF frames we receive when
-	 * we are in PFC mode.
-	 */
-	reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
-	reg &= ~IXGBE_MFLCN_RFCE;
-	reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
-	IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
-out:
+		reg = IXGBE_FCCFG_TFCE_PRIORITY;
+		IXGBE_WRITE_REG(hw, IXGBE_FCCFG, reg);
+		/*
+		 * Enable Receive PFC
+		 * We will always honor XOFF frames we receive when
+		 * we are in PFC mode.
+		 */
+		reg = IXGBE_READ_REG(hw, IXGBE_MFLCN);
+		reg &= ~IXGBE_MFLCN_RFCE;
+		reg |= IXGBE_MFLCN_RPFCE | IXGBE_MFLCN_DPF;
+		IXGBE_WRITE_REG(hw, IXGBE_MFLCN, reg);
+
+	} else {
+		for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+			hw->mac.ops.fc_enable(hw, i);
+	}
+
 	return 0;
 }
 
@@ -349,7 +357,6 @@
 /**
  * ixgbe_dcb_config_82599 - Configure general DCB parameters
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
  *
  * Configure general DCB parameters.
  */
@@ -406,19 +413,28 @@
 /**
  * ixgbe_dcb_hw_config_82599 - Configure and enable DCB
  * @hw: pointer to hardware structure
- * @dcb_config: pointer to ixgbe_dcb_config structure
+ * @rx_pba: method to distribute packet buffer
+ * @refill: refill credits index by traffic class
+ * @max: max credits index by traffic class
+ * @bwg_id: bandwidth grouping indexed by traffic class
+ * @prio_type: priority type indexed by traffic class
+ * @pfc_en: enabled pfc bitmask
  *
  * Configure dcb settings and enable dcb mode.
  */
 s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
-                              struct ixgbe_dcb_config *dcb_config)
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type, u8 *prio_tc)
 {
-	ixgbe_dcb_config_packet_buffers_82599(hw, dcb_config);
+	ixgbe_dcb_config_packet_buffers_82599(hw, rx_pba);
 	ixgbe_dcb_config_82599(hw);
-	ixgbe_dcb_config_rx_arbiter_82599(hw, dcb_config);
-	ixgbe_dcb_config_tx_desc_arbiter_82599(hw, dcb_config);
-	ixgbe_dcb_config_tx_data_arbiter_82599(hw, dcb_config);
-	ixgbe_dcb_config_pfc_82599(hw, dcb_config);
+	ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max, bwg_id,
+					  prio_type, prio_tc);
+	ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
+					       bwg_id, prio_type);
+	ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max,
+					       bwg_id, prio_type, prio_tc);
+	ixgbe_dcb_config_pfc_82599(hw, pfc_en);
 	ixgbe_dcb_config_tc_stats_82599(hw);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_82599.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -102,11 +102,32 @@
 /* DCB hardware-specific driver APIs */
 
 /* DCB PFC functions */
-s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw,
-                               struct ixgbe_dcb_config *dcb_config);
+s32 ixgbe_dcb_config_pfc_82599(struct ixgbe_hw *hw, u8 pfc_en);
 
 /* DCB hw initialization */
+s32 ixgbe_dcb_config_rx_arbiter_82599(struct ixgbe_hw *hw,
+					u16 *refill,
+					u16 *max,
+					u8 *bwg_id,
+					u8 *prio_type,
+					u8 *prio_tc);
+
+s32 ixgbe_dcb_config_tx_desc_arbiter_82599(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type);
+
+s32 ixgbe_dcb_config_tx_data_arbiter_82599(struct ixgbe_hw *hw,
+						u16 *refill,
+						u16 *max,
+						u8 *bwg_id,
+						u8 *prio_type,
+						u8 *prio_tc);
+
 s32 ixgbe_dcb_hw_config_82599(struct ixgbe_hw *hw,
-                              struct ixgbe_dcb_config *config);
+			      u8 rx_pba, u8 pfc_en, u16 *refill,
+			      u16 *max, u8 *bwg_id, u8 *prio_type,
+			      u8 *prio_tc);
 
 #endif /* _DCB_82599_CONFIG_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -34,6 +34,42 @@
 #include "ixgbe_dcb_82599.h"
 
 /**
+ * ixgbe_ieee_credits - This calculates the ieee traffic class
+ * credits from the configured bandwidth percentages. Credits
+ * are the smallest unit programmable into the underlying
+ * hardware. The IEEE 802.1Qaz specification do not use bandwidth
+ * groups so this is much simplified from the CEE case.
+ */
+s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame)
+{
+	int min_percent = 100;
+	int min_credit, multiplier;
+	int i;
+
+	min_credit = ((max_frame / 2) + DCB_CREDIT_QUANTUM - 1) /
+			DCB_CREDIT_QUANTUM;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		if (bw[i] < min_percent && bw[i])
+			min_percent = bw[i];
+	}
+
+	multiplier = (min_credit / min_percent) + 1;
+
+	/* Find out the hw credits for each TC */
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		int val = min(bw[i] * multiplier, MAX_CREDIT_REFILL);
+
+		if (val < min_credit)
+			val = min_credit;
+		refill[i] = val;
+
+		max[i] = bw[i] ? (bw[i] * MAX_CREDIT)/100 : min_credit;
+	}
+	return 0;
+}
+
+/**
  * ixgbe_dcb_calculate_tc_credits - Calculates traffic class credits
  * @ixgbe_dcb_config: Struct containing DCB settings.
  * @direction: Configuring either Tx or Rx.
@@ -141,6 +177,59 @@
 	return ret_val;
 }
 
+void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en)
+{
+	int i;
+
+	*pfc_en = 0;
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+		*pfc_en |= (cfg->tc_config[i].dcb_pfc & 0xF) << i;
+}
+
+void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *cfg, int direction,
+			     u16 *refill)
+{
+	struct tc_bw_alloc *p;
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		p = &cfg->tc_config[i].path[direction];
+		refill[i] = p->data_credits_refill;
+	}
+}
+
+void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *cfg, u16 *max)
+{
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++)
+		max[i] = cfg->tc_config[i].desc_credits_max;
+}
+
+void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *cfg, int direction,
+			    u8 *bwgid)
+{
+	struct tc_bw_alloc *p;
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		p = &cfg->tc_config[i].path[direction];
+		bwgid[i] = p->bwg_id;
+	}
+}
+
+void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *cfg, int direction,
+			    u8 *ptype)
+{
+	struct tc_bw_alloc *p;
+	int i;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		p = &cfg->tc_config[i].path[direction];
+		ptype[i] = p->prio_type;
+	}
+}
+
 /**
  * ixgbe_dcb_hw_config - Config and enable DCB
  * @hw: pointer to hardware structure
@@ -152,13 +241,51 @@
                         struct ixgbe_dcb_config *dcb_config)
 {
 	s32 ret = 0;
+	u8 pfc_en;
+	u8 ptype[MAX_TRAFFIC_CLASS];
+	u8 bwgid[MAX_TRAFFIC_CLASS];
+	u16 refill[MAX_TRAFFIC_CLASS];
+	u16 max[MAX_TRAFFIC_CLASS];
+	/* CEE does not define a priority to tc mapping so map 1:1 */
+	u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+	/* Unpack CEE standard containers */
+	ixgbe_dcb_unpack_pfc(dcb_config, &pfc_en);
+	ixgbe_dcb_unpack_refill(dcb_config, DCB_TX_CONFIG, refill);
+	ixgbe_dcb_unpack_max(dcb_config, max);
+	ixgbe_dcb_unpack_bwgid(dcb_config, DCB_TX_CONFIG, bwgid);
+	ixgbe_dcb_unpack_prio(dcb_config, DCB_TX_CONFIG, ptype);
+
 	switch (hw->mac.type) {
 	case ixgbe_mac_82598EB:
-		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config);
+		ret = ixgbe_dcb_hw_config_82598(hw, dcb_config->rx_pba_cfg,
+						pfc_en, refill, max, bwgid,
+						ptype);
 		break;
 	case ixgbe_mac_82599EB:
 	case ixgbe_mac_X540:
-		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config);
+		ret = ixgbe_dcb_hw_config_82599(hw, dcb_config->rx_pba_cfg,
+						pfc_en, refill, max, bwgid,
+						ptype, prio_tc);
+		break;
+	default:
+		break;
+	}
+	return ret;
+}
+
+/* Helper routines to abstract HW specifics from DCB netlink ops */
+s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en)
+{
+	int ret = -EINVAL;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		ret = ixgbe_dcb_config_pfc_82598(hw, pfc_en);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		ret = ixgbe_dcb_config_pfc_82599(hw, pfc_en);
 		break;
 	default:
 		break;
@@ -166,3 +293,30 @@
 	return ret;
 }
 
+s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw,
+			    u16 *refill, u16 *max, u8 *bwg_id,
+			    u8 *prio_type, u8 *prio_tc)
+{
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		ixgbe_dcb_config_rx_arbiter_82598(hw, refill, max,
+							prio_type);
+		ixgbe_dcb_config_tx_desc_arbiter_82598(hw, refill, max,
+							     bwg_id, prio_type);
+		ixgbe_dcb_config_tx_data_arbiter_82598(hw, refill, max,
+							     bwg_id, prio_type);
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		ixgbe_dcb_config_rx_arbiter_82599(hw, refill, max,
+						  bwg_id, prio_type, prio_tc);
+		ixgbe_dcb_config_tx_desc_arbiter_82599(hw, refill, max,
+						       bwg_id, prio_type);
+		ixgbe_dcb_config_tx_data_arbiter_82599(hw, refill, max, bwg_id,
+						       prio_type, prio_tc);
+		break;
+	default:
+		break;
+	}
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -139,7 +139,6 @@
 	struct tc_configuration tc_config[MAX_TRAFFIC_CLASS];
 	u8     bw_percentage[2][MAX_BW_GROUP]; /* One each for Tx/Rx */
 	bool   pfc_mode_enable;
-	bool   round_robin_enable;
 
 	enum dcb_rx_pba_cfg rx_pba_cfg;
 
@@ -148,12 +147,21 @@
 };
 
 /* DCB driver APIs */
+void ixgbe_dcb_unpack_pfc(struct ixgbe_dcb_config *cfg, u8 *pfc_en);
+void ixgbe_dcb_unpack_refill(struct ixgbe_dcb_config *, int, u16 *);
+void ixgbe_dcb_unpack_max(struct ixgbe_dcb_config *, u16 *);
+void ixgbe_dcb_unpack_bwgid(struct ixgbe_dcb_config *, int, u8 *);
+void ixgbe_dcb_unpack_prio(struct ixgbe_dcb_config *, int, u8 *);
 
 /* DCB credits calculation */
+s32 ixgbe_ieee_credits(__u8 *bw, __u16 *refill, __u16 *max, int max_frame);
 s32 ixgbe_dcb_calculate_tc_credits(struct ixgbe_hw *,
 				   struct ixgbe_dcb_config *, int, u8);
 
 /* DCB hw initialization */
+s32 ixgbe_dcb_hw_ets_config(struct ixgbe_hw *hw, u16 *refill, u16 *max,
+			    u8 *bwg_id, u8 *prio_type, u8 *tc_prio);
+s32 ixgbe_dcb_hw_pfc_config(struct ixgbe_hw *hw, u8 pfc_en);
 s32 ixgbe_dcb_hw_config(struct ixgbe_hw *, struct ixgbe_dcb_config *);
 
 /* DCB definitions for credit calculation */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_dcb_nl.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -37,7 +37,6 @@
 #define BIT_PG_RX	0x04
 #define BIT_PG_TX	0x08
 #define BIT_APP_UPCHG	0x10
-#define BIT_RESETLINK   0x40
 #define BIT_LINKSPEED   0x80
 
 /* Responses for the DCB_C_SET_ALL command */
@@ -130,7 +129,6 @@
 			netdev->netdev_ops->ndo_stop(netdev);
 		ixgbe_clear_interrupt_scheme(adapter);
 
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
 		switch (adapter->hw.mac.type) {
 		case ixgbe_mac_82598EB:
 			adapter->last_lfc_mode = adapter->hw.fc.current_mode;
@@ -146,6 +144,9 @@
 		}
 
 		adapter->flags |= IXGBE_FLAG_DCB_ENABLED;
+		if (!netdev_get_num_tc(netdev))
+			ixgbe_setup_tc(netdev, MAX_TRAFFIC_CLASS);
+
 		ixgbe_init_interrupt_scheme(adapter);
 		if (netif_running(netdev))
 			netdev->netdev_ops->ndo_open(netdev);
@@ -160,7 +161,6 @@
 			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;
 			switch (adapter->hw.mac.type) {
 			case ixgbe_mac_82599EB:
 			case ixgbe_mac_X540:
@@ -170,6 +170,8 @@
 				break;
 			}
 
+			ixgbe_setup_tc(netdev, 0);
+
 			ixgbe_init_interrupt_scheme(adapter);
 			if (netif_running(netdev))
 				netdev->netdev_ops->ndo_open(netdev);
@@ -225,10 +227,8 @@
 	    (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,
@@ -239,10 +239,8 @@
 	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_TX;
-		adapter->dcb_set_bitmap |= BIT_RESETLINK;
-	}
 }
 
 static void ixgbe_dcbnl_set_pg_tc_cfg_rx(struct net_device *netdev, int tc,
@@ -269,10 +267,8 @@
 	    (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,
@@ -283,10 +279,8 @@
 	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,
@@ -355,31 +349,28 @@
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	int ret;
 
-	if (!adapter->dcb_set_bitmap)
+	if (!adapter->dcb_set_bitmap ||
+	    !(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
 		return DCB_NO_HW_CHG;
 
 	ret = ixgbe_copy_dcb_cfg(&adapter->temp_dcb_cfg, &adapter->dcb_cfg,
-				 adapter->ring_feature[RING_F_DCB].indices);
+				 MAX_TRAFFIC_CLASS);
 
 	if (ret)
 		return DCB_NO_HW_CHG;
 
 	/*
-	 * Only take down the adapter if the configuration change
-	 * requires a reset.
+	 * Only take down the adapter if an app change occurred. FCoE
+	 * may shuffle tx rings in this case and this can not be done
+	 * without a reset currently.
 	 */
-	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
+	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
 		while (test_and_set_bit(__IXGBE_RESETTING, &adapter->state))
 			msleep(1);
 
-		if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
-			if (netif_running(netdev))
-				netdev->netdev_ops->ndo_stop(netdev);
-			ixgbe_clear_interrupt_scheme(adapter);
-		} else {
-			if (netif_running(netdev))
-				ixgbe_down(adapter);
-		}
+		if (netif_running(netdev))
+			netdev->netdev_ops->ndo_stop(netdev);
+		ixgbe_clear_interrupt_scheme(adapter);
 	}
 
 	if (adapter->dcb_cfg.pfc_mode_enable) {
@@ -408,29 +399,53 @@
 		}
 	}
 
-	if (adapter->dcb_set_bitmap & BIT_RESETLINK) {
-		if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
-			ixgbe_init_interrupt_scheme(adapter);
-			if (netif_running(netdev))
-				netdev->netdev_ops->ndo_open(netdev);
-		} else {
-			if (netif_running(netdev))
-				ixgbe_up(adapter);
-		}
+	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG) {
+		ixgbe_init_interrupt_scheme(adapter);
+		if (netif_running(netdev))
+			netdev->netdev_ops->ndo_open(netdev);
 		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);
+	}
+
+	if (adapter->dcb_set_bitmap & BIT_PFC) {
+		u8 pfc_en;
+		ixgbe_dcb_unpack_pfc(&adapter->dcb_cfg, &pfc_en);
+		ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc_en);
 		ret = DCB_HW_CHG;
 	}
+
+	if (adapter->dcb_set_bitmap & (BIT_PG_TX|BIT_PG_RX)) {
+		u16 refill[MAX_TRAFFIC_CLASS], max[MAX_TRAFFIC_CLASS];
+		u8 bwg_id[MAX_TRAFFIC_CLASS], prio_type[MAX_TRAFFIC_CLASS];
+		/* Priority to TC mapping in CEE case default to 1:1 */
+		u8 prio_tc[MAX_TRAFFIC_CLASS] = {0, 1, 2, 3, 4, 5, 6, 7};
+		int max_frame = adapter->netdev->mtu + ETH_HLEN + ETH_FCS_LEN;
+
+#ifdef CONFIG_FCOE
+		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
+#endif
+
+		ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg,
+					       max_frame, DCB_TX_CONFIG);
+		ixgbe_dcb_calculate_tc_credits(&adapter->hw, &adapter->dcb_cfg,
+					       max_frame, DCB_RX_CONFIG);
+
+		ixgbe_dcb_unpack_refill(&adapter->dcb_cfg,
+					DCB_TX_CONFIG, refill);
+		ixgbe_dcb_unpack_max(&adapter->dcb_cfg, max);
+		ixgbe_dcb_unpack_bwgid(&adapter->dcb_cfg,
+				       DCB_TX_CONFIG, bwg_id);
+		ixgbe_dcb_unpack_prio(&adapter->dcb_cfg,
+				      DCB_TX_CONFIG, prio_type);
+
+		ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
+					bwg_id, prio_type, prio_tc);
+	}
+
 	if (adapter->dcb_cfg.pfc_mode_enable)
 		adapter->hw.fc.current_mode = ixgbe_fc_pfc;
 
-	if (adapter->dcb_set_bitmap & BIT_RESETLINK)
+	if (adapter->dcb_set_bitmap & BIT_APP_UPCHG)
 		clear_bit(__IXGBE_RESETTING, &adapter->state);
 	adapter->dcb_set_bitmap = 0x00;
 	return ret;
@@ -439,40 +454,38 @@
 static u8 ixgbe_dcbnl_getcap(struct net_device *netdev, int capid, u8 *cap)
 {
 	struct ixgbe_adapter *adapter = netdev_priv(netdev);
-	u8 rval = 0;
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		switch (capid) {
-		case DCB_CAP_ATTR_PG:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_PFC:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_UP2TC:
-			*cap = false;
-			break;
-		case DCB_CAP_ATTR_PG_TCS:
-			*cap = 0x80;
-			break;
-		case DCB_CAP_ATTR_PFC_TCS:
-			*cap = 0x80;
-			break;
-		case DCB_CAP_ATTR_GSP:
-			*cap = true;
-			break;
-		case DCB_CAP_ATTR_BCN:
-			*cap = false;
-			break;
-		default:
-			rval = -EINVAL;
-			break;
-		}
-	} else {
-		rval = -EINVAL;
+	switch (capid) {
+	case DCB_CAP_ATTR_PG:
+		*cap = true;
+		break;
+	case DCB_CAP_ATTR_PFC:
+		*cap = true;
+		break;
+	case DCB_CAP_ATTR_UP2TC:
+		*cap = false;
+		break;
+	case DCB_CAP_ATTR_PG_TCS:
+		*cap = 0x80;
+		break;
+	case DCB_CAP_ATTR_PFC_TCS:
+		*cap = 0x80;
+		break;
+	case DCB_CAP_ATTR_GSP:
+		*cap = true;
+		break;
+	case DCB_CAP_ATTR_BCN:
+		*cap = false;
+		break;
+	case DCB_CAP_ATTR_DCBX:
+		*cap = adapter->dcbx_cap;
+		break;
+	default:
+		*cap = false;
+		break;
 	}
 
-	return rval;
+	return 0;
 }
 
 static u8 ixgbe_dcbnl_getnumtcs(struct net_device *netdev, int tcid, u8 *num)
@@ -533,21 +546,16 @@
  */
 static u8 ixgbe_dcbnl_getapp(struct net_device *netdev, u8 idtype, u16 id)
 {
-	u8 rval = 0;
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct dcb_app app = {
+				.selector = idtype,
+				.protocol = id,
+			     };
 
-	switch (idtype) {
-	case DCB_APP_IDTYPE_ETHTYPE:
-#ifdef IXGBE_FCOE
-		if (id == ETH_P_FCOE)
-			rval = ixgbe_fcoe_getapp(netdev_priv(netdev));
-#endif
-		break;
-	case DCB_APP_IDTYPE_PORTNUM:
-		break;
-	default:
-		break;
-	}
-	return rval;
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
+		return 0;
+
+	return dcb_getapp(netdev, &app);
 }
 
 /**
@@ -562,24 +570,45 @@
 static u8 ixgbe_dcbnl_setapp(struct net_device *netdev,
                              u8 idtype, u16 id, u8 up)
 {
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
 	u8 rval = 1;
+	struct dcb_app app = {
+			      .selector = idtype,
+			      .protocol = id,
+			      .priority = up
+			     };
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_CEE))
+		return rval;
+
+	rval = dcb_setapp(netdev, &app);
 
 	switch (idtype) {
 	case DCB_APP_IDTYPE_ETHTYPE:
 #ifdef IXGBE_FCOE
 		if (id == ETH_P_FCOE) {
-			u8 tc;
-			struct ixgbe_adapter *adapter;
+			u8 old_tc;
 
-			adapter = netdev_priv(netdev);
-			tc = adapter->fcoe.tc;
+			/* Get current programmed tc */
+			old_tc = adapter->fcoe.tc;
 			rval = ixgbe_fcoe_setapp(adapter, up);
-			if ((!rval) && (tc != adapter->fcoe.tc) &&
-			    (adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
-			    (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
+
+			if (rval ||
+			   !(adapter->flags & IXGBE_FLAG_DCB_ENABLED) ||
+			   !(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
+				break;
+
+			/* The FCoE application priority may be changed multiple
+			 * times in quick succession with switches that build up
+			 * TLVs. To avoid creating uneeded device resets this
+			 * checks the actual HW configuration and clears
+			 * BIT_APP_UPCHG if a HW configuration change is not
+			 * need
+			 */
+			if (old_tc == adapter->fcoe.tc)
+				adapter->dcb_set_bitmap &= ~BIT_APP_UPCHG;
+			else
 				adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
-				adapter->dcb_set_bitmap |= BIT_RESETLINK;
-			}
 		}
 #endif
 		break;
@@ -591,7 +620,204 @@
 	return rval;
 }
 
+static int ixgbe_dcbnl_ieee_getets(struct net_device *dev,
+				   struct ieee_ets *ets)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ieee_ets *my_ets = adapter->ixgbe_ieee_ets;
+
+	/* No IEEE PFC settings available */
+	if (!my_ets)
+		return -EINVAL;
+
+	ets->ets_cap = MAX_TRAFFIC_CLASS;
+	ets->cbs = my_ets->cbs;
+	memcpy(ets->tc_tx_bw, my_ets->tc_tx_bw, sizeof(ets->tc_tx_bw));
+	memcpy(ets->tc_rx_bw, my_ets->tc_rx_bw, sizeof(ets->tc_rx_bw));
+	memcpy(ets->tc_tsa, my_ets->tc_tsa, sizeof(ets->tc_tsa));
+	memcpy(ets->prio_tc, my_ets->prio_tc, sizeof(ets->prio_tc));
+	return 0;
+}
+
+static int ixgbe_dcbnl_ieee_setets(struct net_device *dev,
+				   struct ieee_ets *ets)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	__u16 refill[IEEE_8021QAZ_MAX_TCS], max[IEEE_8021QAZ_MAX_TCS];
+	__u8 prio_type[IEEE_8021QAZ_MAX_TCS];
+	int max_frame = dev->mtu + ETH_HLEN + ETH_FCS_LEN;
+	int i, err;
+	__u64 *p = (__u64 *) ets->prio_tc;
+	/* naively give each TC a bwg to map onto CEE hardware */
+	__u8 bwg_id[IEEE_8021QAZ_MAX_TCS] = {0, 1, 2, 3, 4, 5, 6, 7};
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+
+	if (!adapter->ixgbe_ieee_ets) {
+		adapter->ixgbe_ieee_ets = kmalloc(sizeof(struct ieee_ets),
+						  GFP_KERNEL);
+		if (!adapter->ixgbe_ieee_ets)
+			return -ENOMEM;
+	}
+
+	memcpy(adapter->ixgbe_ieee_ets, ets, sizeof(*adapter->ixgbe_ieee_ets));
+
+	/* Map TSA onto CEE prio type */
+	for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
+		switch (ets->tc_tsa[i]) {
+		case IEEE_8021QAZ_TSA_STRICT:
+			prio_type[i] = 2;
+			break;
+		case IEEE_8021QAZ_TSA_ETS:
+			prio_type[i] = 0;
+			break;
+		default:
+			/* Hardware only supports priority strict or
+			 * ETS transmission selection algorithms if
+			 * we receive some other value from dcbnl
+			 * throw an error
+			 */
+			return -EINVAL;
+		}
+	}
+
+	if (*p)
+		ixgbe_dcbnl_set_state(dev, 1);
+	else
+		ixgbe_dcbnl_set_state(dev, 0);
+
+	ixgbe_ieee_credits(ets->tc_tx_bw, refill, max, max_frame);
+	err = ixgbe_dcb_hw_ets_config(&adapter->hw, refill, max,
+				      bwg_id, prio_type, ets->prio_tc);
+	return err;
+}
+
+static int ixgbe_dcbnl_ieee_getpfc(struct net_device *dev,
+				   struct ieee_pfc *pfc)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ieee_pfc *my_pfc = adapter->ixgbe_ieee_pfc;
+	int i;
+
+	/* No IEEE PFC settings available */
+	if (!my_pfc)
+		return -EINVAL;
+
+	pfc->pfc_cap = MAX_TRAFFIC_CLASS;
+	pfc->pfc_en = my_pfc->pfc_en;
+	pfc->mbc = my_pfc->mbc;
+	pfc->delay = my_pfc->delay;
+
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		pfc->requests[i] = adapter->stats.pxoffrxc[i];
+		pfc->indications[i] = adapter->stats.pxofftxc[i];
+	}
+
+	return 0;
+}
+
+static int ixgbe_dcbnl_ieee_setpfc(struct net_device *dev,
+				   struct ieee_pfc *pfc)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	int err;
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+
+	if (!adapter->ixgbe_ieee_pfc) {
+		adapter->ixgbe_ieee_pfc = kmalloc(sizeof(struct ieee_pfc),
+						  GFP_KERNEL);
+		if (!adapter->ixgbe_ieee_pfc)
+			return -ENOMEM;
+	}
+
+	memcpy(adapter->ixgbe_ieee_pfc, pfc, sizeof(*adapter->ixgbe_ieee_pfc));
+	err = ixgbe_dcb_hw_pfc_config(&adapter->hw, pfc->pfc_en);
+	return err;
+}
+
+static int ixgbe_dcbnl_ieee_setapp(struct net_device *dev,
+				   struct dcb_app *app)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+	if (!(adapter->dcbx_cap & DCB_CAP_DCBX_VER_IEEE))
+		return -EINVAL;
+#ifdef IXGBE_FCOE
+	if (app->selector == 1 && app->protocol == ETH_P_FCOE) {
+		if (adapter->fcoe.tc == app->priority)
+			goto setapp;
+
+		/* In IEEE mode map up to tc 1:1 */
+		adapter->fcoe.tc = app->priority;
+		adapter->fcoe.up = app->priority;
+
+		/* Force hardware reset required to push FCoE
+		 * setup on {tx|rx}_rings
+		 */
+		adapter->dcb_set_bitmap |= BIT_APP_UPCHG;
+		ixgbe_dcbnl_set_all(dev);
+	}
+
+setapp:
+#endif
+	dcb_setapp(dev, app);
+	return 0;
+}
+
+static u8 ixgbe_dcbnl_getdcbx(struct net_device *dev)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	return adapter->dcbx_cap;
+}
+
+static u8 ixgbe_dcbnl_setdcbx(struct net_device *dev, u8 mode)
+{
+	struct ixgbe_adapter *adapter = netdev_priv(dev);
+	struct ieee_ets ets = {0};
+	struct ieee_pfc pfc = {0};
+
+	/* no support for LLD_MANAGED modes or CEE+IEEE */
+	if ((mode & DCB_CAP_DCBX_LLD_MANAGED) ||
+	    ((mode & DCB_CAP_DCBX_VER_IEEE) && (mode & DCB_CAP_DCBX_VER_CEE)) ||
+	    !(mode & DCB_CAP_DCBX_HOST))
+		return 1;
+
+	if (mode == adapter->dcbx_cap)
+		return 0;
+
+	adapter->dcbx_cap = mode;
+
+	/* ETS and PFC defaults */
+	ets.ets_cap = 8;
+	pfc.pfc_cap = 8;
+
+	if (mode & DCB_CAP_DCBX_VER_IEEE) {
+		ixgbe_dcbnl_ieee_setets(dev, &ets);
+		ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
+	} else if (mode & DCB_CAP_DCBX_VER_CEE) {
+		adapter->dcb_set_bitmap |= (BIT_PFC & BIT_PG_TX & BIT_PG_RX);
+		ixgbe_dcbnl_set_all(dev);
+	} else {
+		/* Drop into single TC mode strict priority as this
+		 * indicates CEE and IEEE versions are disabled
+		 */
+		ixgbe_dcbnl_ieee_setets(dev, &ets);
+		ixgbe_dcbnl_ieee_setpfc(dev, &pfc);
+		ixgbe_dcbnl_set_state(dev, 0);
+	}
+
+	return 0;
+}
+
 const struct dcbnl_rtnl_ops dcbnl_ops = {
+	.ieee_getets	= ixgbe_dcbnl_ieee_getets,
+	.ieee_setets	= ixgbe_dcbnl_ieee_setets,
+	.ieee_getpfc	= ixgbe_dcbnl_ieee_getpfc,
+	.ieee_setpfc	= ixgbe_dcbnl_ieee_setpfc,
+	.ieee_setapp	= ixgbe_dcbnl_ieee_setapp,
 	.getstate	= ixgbe_dcbnl_get_state,
 	.setstate	= ixgbe_dcbnl_set_state,
 	.getpermhwaddr	= ixgbe_dcbnl_get_perm_hw_addr,
@@ -613,5 +839,6 @@
 	.setpfcstate	= ixgbe_dcbnl_setpfcstate,
 	.getapp		= ixgbe_dcbnl_getapp,
 	.setapp		= ixgbe_dcbnl_setapp,
+	.getdcbx	= ixgbe_dcbnl_getdcbx,
+	.setdcbx	= ixgbe_dcbnl_setdcbx,
 };
-
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_ethtool.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -152,20 +152,35 @@
 		ecmd->supported |= (SUPPORTED_1000baseT_Full |
 		                    SUPPORTED_Autoneg);
 
+		switch (hw->mac.type) {
+		case ixgbe_mac_X540:
+			ecmd->supported |= SUPPORTED_100baseT_Full;
+			break;
+		default:
+			break;
+		}
+
 		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)
-			ecmd->advertising |= ADVERTISED_1000baseT_Full;
-		/*
-		 * It's possible that phy.autoneg_advertised may not be
-		 * set yet.  If so display what the default would be -
-		 * both 1G and 10G supported.
-		 */
-		if (!(ecmd->advertising & (ADVERTISED_1000baseT_Full |
-					   ADVERTISED_10000baseT_Full)))
+		if (hw->phy.autoneg_advertised) {
+			if (hw->phy.autoneg_advertised &
+			    IXGBE_LINK_SPEED_100_FULL)
+				ecmd->advertising |= ADVERTISED_100baseT_Full;
+			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)
+				ecmd->advertising |= ADVERTISED_1000baseT_Full;
+		} else {
+			/*
+			 * Default advertised modes in case
+			 * phy.autoneg_advertised isn't set.
+			 */
 			ecmd->advertising |= (ADVERTISED_10000baseT_Full |
 					      ADVERTISED_1000baseT_Full);
+			if (hw->mac.type == ixgbe_mac_X540)
+				ecmd->advertising |= ADVERTISED_100baseT_Full;
+		}
 
 		if (hw->phy.media_type == ixgbe_media_type_copper) {
 			ecmd->supported |= SUPPORTED_TP;
@@ -271,8 +286,19 @@
 
 	hw->mac.ops.check_link(hw, &link_speed, &link_up, false);
 	if (link_up) {
-		ecmd->speed = (link_speed == IXGBE_LINK_SPEED_10GB_FULL) ?
-		               SPEED_10000 : SPEED_1000;
+		switch (link_speed) {
+		case IXGBE_LINK_SPEED_10GB_FULL:
+			ecmd->speed = SPEED_10000;
+			break;
+		case IXGBE_LINK_SPEED_1GB_FULL:
+			ecmd->speed = SPEED_1000;
+			break;
+		case IXGBE_LINK_SPEED_100_FULL:
+			ecmd->speed = SPEED_100;
+			break;
+		default:
+			break;
+		}
 		ecmd->duplex = DUPLEX_FULL;
 	} else {
 		ecmd->speed = -1;
@@ -306,6 +332,9 @@
 		if (ecmd->advertising & ADVERTISED_1000baseT_Full)
 			advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
+		if (ecmd->advertising & ADVERTISED_100baseT_Full)
+			advertised |= IXGBE_LINK_SPEED_100_FULL;
+
 		if (old == advertised)
 			return err;
 		/* this sets the link speed and restarts auto-neg */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_fcoe.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_fcoe.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_fcoe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_fcoe.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -135,22 +135,19 @@
 	return len;
 }
 
+
 /**
- * ixgbe_fcoe_ddp_get - called to set up ddp context
+ * ixgbe_fcoe_ddp_setup - 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)
+static int ixgbe_fcoe_ddp_setup(struct net_device *netdev, u16 xid,
+				struct scatterlist *sgl, unsigned int sgc,
+				int target_mode)
 {
 	struct ixgbe_adapter *adapter;
 	struct ixgbe_hw *hw;
@@ -164,7 +161,7 @@
 	unsigned int lastsize;
 	unsigned int thisoff = 0;
 	unsigned int thislen = 0;
-	u32 fcbuff, fcdmarw, fcfltrw;
+	u32 fcbuff, fcdmarw, fcfltrw, fcrxctl;
 	dma_addr_t addr = 0;
 
 	if (!netdev || !sgl)
@@ -275,6 +272,9 @@
 	fcbuff = (IXGBE_FCBUFF_4KB << IXGBE_FCBUFF_BUFFSIZE_SHIFT);
 	fcbuff |= ((j & 0xff) << IXGBE_FCBUFF_BUFFCNT_SHIFT);
 	fcbuff |= (firstoff << IXGBE_FCBUFF_OFFSET_SHIFT);
+	/* Set WRCONTX bit to allow DDP for target */
+	if (target_mode)
+		fcbuff |= (IXGBE_FCBUFF_WRCONTX);
 	fcbuff |= (IXGBE_FCBUFF_VALID);
 
 	fcdmarw = xid;
@@ -287,6 +287,16 @@
 	/* program DMA context */
 	hw = &adapter->hw;
 	spin_lock_bh(&fcoe->lock);
+
+	/* turn on last frame indication for target mode as FCP_RSPtarget is
+	 * supposed to send FCP_RSP when it is done. */
+	if (target_mode && !test_bit(__IXGBE_FCOE_TARGET, &fcoe->mode)) {
+		set_bit(__IXGBE_FCOE_TARGET, &fcoe->mode);
+		fcrxctl = IXGBE_READ_REG(hw, IXGBE_FCRXCTRL);
+		fcrxctl |= IXGBE_FCRXCTRL_LASTSEQH;
+		IXGBE_WRITE_REG(hw, IXGBE_FCRXCTRL, fcrxctl);
+	}
+
 	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);
@@ -295,6 +305,7 @@
 	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;
@@ -309,6 +320,47 @@
 }
 
 /**
+ * ixgbe_fcoe_ddp_get - called to set up ddp context in initiator mode
+ * @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)
+{
+	return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 0);
+}
+
+/**
+ * ixgbe_fcoe_ddp_target - called to set up ddp context in target mode
+ * @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_target
+ * 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. The DDP in target mode is a write I/O request
+ * from the initiator.
+ *
+ * Returns : 1 for success and 0 for no ddp
+ */
+int ixgbe_fcoe_ddp_target(struct net_device *netdev, u16 xid,
+			    struct scatterlist *sgl, unsigned int sgc)
+{
+	return ixgbe_fcoe_ddp_setup(netdev, xid, sgl, sgc, 1);
+}
+
+/**
  * ixgbe_fcoe_ddp - check ddp status and mark it done
  * @adapter: ixgbe adapter
  * @rx_desc: advanced rx descriptor
@@ -331,6 +383,7 @@
 	struct ixgbe_fcoe *fcoe;
 	struct ixgbe_fcoe_ddp *ddp;
 	struct fc_frame_header *fh;
+	struct fcoe_crc_eof *crc;
 
 	if (!ixgbe_rx_is_fcoe(rx_desc))
 		goto ddp_out;
@@ -384,7 +437,18 @@
 		else if (ddp->len)
 			rc = ddp->len;
 	}
-
+	/* In target mode, check the last data frame of the sequence.
+	 * For DDP in target mode, data is already DDPed but the header
+	 * indication of the last data frame ould allow is to tell if we
+	 * got all the data and the ULP can send FCP_RSP back, as this is
+	 * not a full fcoe frame, we fill the trailer here so it won't be
+	 * dropped by the ULP stack.
+	 */
+	if ((fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA) &&
+	    (fctl & FC_FC_END_SEQ)) {
+		crc = (struct fcoe_crc_eof *)skb_put(skb, sizeof(*crc));
+		crc->fcoe_eof = FC_EOF_T;
+	}
 ddp_out:
 	return rc;
 }
@@ -749,21 +813,6 @@
 
 #ifdef CONFIG_IXGBE_DCB
 /**
- * ixgbe_fcoe_getapp - retrieves current user priority bitmap for FCoE
- * @adapter : ixgbe adapter
- *
- * Finds out the corresponding user priority bitmap from the current
- * traffic class that FCoE belongs to. Returns 0 as the invalid user
- * priority bitmap to indicate an error.
- *
- * Returns : 802.1p user priority bitmap for FCoE
- */
-u8 ixgbe_fcoe_getapp(struct ixgbe_adapter *adapter)
-{
-	return 1 << adapter->fcoe.up;
-}
-
-/**
  * ixgbe_fcoe_setapp - sets the user priority bitmap for FCoE
  * @adapter : ixgbe adapter
  * @up : 802.1p user priority bitmap
@@ -840,5 +889,3 @@
 	}
 	return rc;
 }
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_fcoe.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_fcoe.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_fcoe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_fcoe.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -52,6 +52,9 @@
 /* fcerr */
 #define IXGBE_FCERR_BADCRC       0x00100000
 
+/* FCoE DDP for target mode */
+#define __IXGBE_FCOE_TARGET	1
+
 struct ixgbe_fcoe_ddp {
 	int len;
 	u32 err;
@@ -66,6 +69,7 @@
 	u8 tc;
 	u8 up;
 #endif
+	unsigned long mode;
 	atomic_t refcnt;
 	spinlock_t lock;
 	struct pci_pool *pool;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -118,6 +118,7 @@
 	bool pf_set_mac;
 	u16 pf_vlan; /* When set, guest VLAN config not allowed. */
 	u16 pf_qos;
+	u16 tx_rate;
 };
 
 /* wrapper around a pointer to a socket buffer,
@@ -209,6 +210,7 @@
 					 * associated with this ring, which is
 					 * different for DCB and RSS modes
 					 */
+	u8 dcb_tc;
 
 	u16 work_limit;			/* max work per interrupt */
 
@@ -243,7 +245,7 @@
 	RING_F_ARRAY_SIZE      /* must be last in enum set */
 };
 
-#define IXGBE_MAX_DCB_INDICES   8
+#define IXGBE_MAX_DCB_INDICES  64
 #define IXGBE_MAX_RSS_INDICES  16
 #define IXGBE_MAX_VMDQ_INDICES 64
 #define IXGBE_MAX_FDIR_INDICES 64
@@ -334,9 +336,14 @@
 	u16 bd_number;
 	struct work_struct reset_task;
 	struct ixgbe_q_vector *q_vector[MAX_MSIX_Q_VECTORS];
+
+	/* DCB parameters */
+	struct ieee_pfc *ixgbe_ieee_pfc;
+	struct ieee_ets *ixgbe_ieee_ets;
 	struct ixgbe_dcb_config dcb_cfg;
 	struct ixgbe_dcb_config temp_dcb_cfg;
 	u8 dcb_set_bitmap;
+	u8 dcbx_cap;
 	enum ixgbe_fc_mode last_lfc_mode;
 
 	/* Interrupt Throttle Rate */
@@ -462,6 +469,7 @@
 	DECLARE_BITMAP(active_vfs, IXGBE_MAX_VF_FUNCTIONS);
 	unsigned int num_vfs;
 	struct vf_data_storage *vfinfo;
+	int vf_rate_link_speed;
 };
 
 enum ixbge_state_t {
@@ -521,7 +529,6 @@
 extern void ixgbe_alloc_rx_buffers(struct ixgbe_ring *, u16);
 extern void ixgbe_write_eitr(struct ixgbe_q_vector *);
 extern int ethtool_ioctl(struct ifreq *ifr);
-extern u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 index);
 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);
@@ -538,6 +545,7 @@
 extern void ixgbe_clear_rscctl(struct ixgbe_adapter *adapter,
                                struct ixgbe_ring *ring);
 extern void ixgbe_set_rx_mode(struct net_device *netdev);
+extern int ixgbe_setup_tc(struct net_device *dev, u8 tc);
 #ifdef IXGBE_FCOE
 extern void ixgbe_configure_fcoe(struct ixgbe_adapter *adapter);
 extern int ixgbe_fso(struct ixgbe_adapter *adapter,
@@ -549,6 +557,8 @@
                           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_target(struct net_device *netdev, u16 xid,
+				 struct scatterlist *sgl, unsigned int sgc);
 extern int ixgbe_fcoe_ddp_put(struct net_device *netdev, u16 xid);
 extern int ixgbe_fcoe_enable(struct net_device *netdev);
 extern int ixgbe_fcoe_disable(struct net_device *netdev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_main.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_main.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -54,7 +54,8 @@
 
 #define DRV_VERSION "3.2.9-k2"
 const char ixgbe_driver_version[] = DRV_VERSION;
-static char ixgbe_copyright[] = "Copyright (c) 1999-2010 Intel Corporation.";
+static const char ixgbe_copyright[] =
+				"Copyright (c) 1999-2011 Intel Corporation.";
 
 static const struct ixgbe_info *ixgbe_info_tbl[] = {
 	[board_82598] = &ixgbe_82598_info,
@@ -643,15 +644,15 @@
  * @adapter: driver private struct
  * @index: reg idx of queue to query (0-127)
  *
- * Helper function to determine the traffic index for a paticular
+ * Helper function to determine the traffic index for a particular
  * register index.
  *
  * Returns : a tc index for use in range 0-7, or 0-3
  */
-u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
+static u8 ixgbe_dcb_txq_to_tc(struct ixgbe_adapter *adapter, u8 reg_idx)
 {
 	int tc = -1;
-	int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+	int dcb_i = netdev_get_num_tc(adapter->netdev);
 
 	/* if DCB is not enabled the queues have no TC */
 	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
@@ -2597,6 +2598,11 @@
 
 		i--;
 		for (; i >= 0; i--) {
+			/* free only the irqs that were actually requested */
+			if (!adapter->q_vector[i]->rxr_count &&
+			    !adapter->q_vector[i]->txr_count)
+				continue;
+
 			free_irq(adapter->msix_entries[i].vector,
 				 adapter->q_vector[i]);
 		}
@@ -2886,17 +2892,20 @@
 					);
 
 	switch (mask) {
+#ifdef CONFIG_IXGBE_DCB
+	case (IXGBE_FLAG_DCB_ENABLED | IXGBE_FLAG_RSS_ENABLED):
+		mrqc = IXGBE_MRQC_RTRSS8TCEN;
+		break;
+	case (IXGBE_FLAG_DCB_ENABLED):
+		mrqc = IXGBE_MRQC_RT8TCEN;
+		break;
+#endif /* CONFIG_IXGBE_DCB */
 	case (IXGBE_FLAG_RSS_ENABLED):
 		mrqc = IXGBE_MRQC_RSSEN;
 		break;
 	case (IXGBE_FLAG_SRIOV_ENABLED):
 		mrqc = IXGBE_MRQC_VMDQEN;
 		break;
-#ifdef CONFIG_IXGBE_DCB
-	case (IXGBE_FLAG_DCB_ENABLED):
-		mrqc = IXGBE_MRQC_RT8TCEN;
-		break;
-#endif /* CONFIG_IXGBE_DCB */
 	default:
 		break;
 	}
@@ -3077,6 +3086,14 @@
 	ixgbe_configure_srrctl(adapter, ring);
 	ixgbe_configure_rscctl(adapter, ring);
 
+	/* If operating in IOV mode set RLPML for X540 */
+	if ((adapter->flags & IXGBE_FLAG_SRIOV_ENABLED) &&
+	    hw->mac.type == ixgbe_mac_X540) {
+		rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
+		rxdctl |= ((ring->netdev->mtu + ETH_HLEN +
+			    ETH_FCS_LEN + VLAN_HLEN) | IXGBE_RXDCTL_RLPML_EN);
+	}
+
 	if (hw->mac.type == ixgbe_mac_82598EB) {
 		/*
 		 * enable cache line friendly hardware writes:
@@ -3539,7 +3556,7 @@
 		} else {
 			/*
 			 * Write addresses to the MTA, if the attempt fails
-			 * then we should just turn on promiscous mode so
+			 * then we should just turn on promiscuous mode so
 			 * that we can at least receive multicast traffic
 			 */
 			hw->mac.ops.update_mc_addr_list(hw, netdev);
@@ -3550,7 +3567,7 @@
 		/*
 		 * Write addresses to available RAR registers, if there is not
 		 * sufficient space to store all the addresses then enable
-		 * unicast promiscous mode
+		 * unicast promiscuous mode
 		 */
 		count = ixgbe_write_uc_addr_list(netdev);
 		if (count < 0) {
@@ -3641,15 +3658,6 @@
 	if (hw->mac.type == ixgbe_mac_82598EB)
 		netif_set_gso_max_size(adapter->netdev, 32768);
 
-#ifdef CONFIG_FCOE
-	if (adapter->netdev->features & NETIF_F_FCOE_MTU)
-		max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
-#endif
-
-	ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
-					DCB_TX_CONFIG);
-	ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
-					DCB_RX_CONFIG);
 
 	/* Enable VLAN tag insert/strip */
 	adapter->netdev->features |= NETIF_F_HW_VLAN_RX;
@@ -3657,7 +3665,43 @@
 	hw->mac.ops.set_vfta(&adapter->hw, 0, 0, true);
 
 	/* reconfigure the hardware */
-	ixgbe_dcb_hw_config(hw, &adapter->dcb_cfg);
+	if (adapter->dcbx_cap & (DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE)) {
+#ifdef CONFIG_FCOE
+		if (adapter->netdev->features & NETIF_F_FCOE_MTU)
+			max_frame = max(max_frame, IXGBE_FCOE_JUMBO_FRAME_SIZE);
+#endif
+		ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
+						DCB_TX_CONFIG);
+		ixgbe_dcb_calculate_tc_credits(hw, &adapter->dcb_cfg, max_frame,
+						DCB_RX_CONFIG);
+		ixgbe_dcb_hw_config(hw, &adapter->dcb_cfg);
+	} else {
+		struct net_device *dev = adapter->netdev;
+
+		if (adapter->ixgbe_ieee_ets)
+			dev->dcbnl_ops->ieee_setets(dev,
+						    adapter->ixgbe_ieee_ets);
+		if (adapter->ixgbe_ieee_pfc)
+			dev->dcbnl_ops->ieee_setpfc(dev,
+						    adapter->ixgbe_ieee_pfc);
+	}
+
+	/* Enable RSS Hash per TC */
+	if (hw->mac.type != ixgbe_mac_82598EB) {
+		int i;
+		u32 reg = 0;
+
+		for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+			u8 msb = 0;
+			u8 cnt = adapter->netdev->tc_to_txq[i].count;
+
+			while (cnt >>= 1)
+				msb++;
+
+			reg |= msb << IXGBE_RQTC_SHIFT_TC(i);
+		}
+		IXGBE_WRITE_REG(hw, IXGBE_RQTC, reg);
+	}
 }
 
 #endif
@@ -3761,7 +3805,8 @@
 	if (ret)
 		goto link_cfg_out;
 
-	if (hw->mac.ops.get_link_capabilities)
+	autoneg = hw->phy.autoneg_advertised;
+	if ((!autoneg) && (hw->mac.ops.get_link_capabilities))
 		ret = hw->mac.ops.get_link_capabilities(hw, &autoneg,
 							&negotiation);
 	if (ret)
@@ -3876,7 +3921,7 @@
 	 * If we're not hot-pluggable SFP+, we just need to configure link
 	 * and bring it up.
 	 */
-	if (hw->phy.type == ixgbe_phy_unknown)
+	if (hw->phy.type == ixgbe_phy_none)
 		schedule_work(&adapter->sfp_config_module_task);
 
 	/* enable transmits */
@@ -4243,24 +4288,6 @@
 	ixgbe_reinit_locked(adapter);
 }
 
-#ifdef CONFIG_IXGBE_DCB
-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))
-		return ret;
-
-	f->mask = 0x7 << 3;
-	adapter->num_rx_queues = f->indices;
-	adapter->num_tx_queues = f->indices;
-	ret = true;
-
-	return ret;
-}
-#endif
-
 /**
  * ixgbe_set_rss_queues: Allocate queues for RSS
  * @adapter: board private structure to initialize
@@ -4331,19 +4358,26 @@
  **/
 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) {
-		adapter->num_rx_queues = 1;
-		adapter->num_tx_queues = 1;
+	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
+		return false;
+
+	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 #ifdef CONFIG_IXGBE_DCB
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			e_info(probe, "FCoE enabled with DCB\n");
-			ixgbe_set_dcb_queues(adapter);
-		}
+		int tc;
+		struct net_device *dev = adapter->netdev;
+
+		tc = netdev_get_prio_tc_map(dev, adapter->fcoe.up);
+		f->indices = dev->tc_to_txq[tc].count;
+		f->mask = dev->tc_to_txq[tc].offset;
 #endif
+	} else {
+		f->indices = min((int)num_online_cpus(), f->indices);
+
+		adapter->num_rx_queues = 1;
+		adapter->num_tx_queues = 1;
+
 		if (adapter->flags & IXGBE_FLAG_RSS_ENABLED) {
 			e_info(probe, "FCoE enabled with RSS\n");
 			if ((adapter->flags & IXGBE_FLAG_FDIR_HASH_CAPABLE) ||
@@ -4356,14 +4390,45 @@
 		f->mask = adapter->num_rx_queues;
 		adapter->num_rx_queues += f->indices;
 		adapter->num_tx_queues += f->indices;
+	}
 
-		ret = true;
+	return true;
+}
+#endif /* IXGBE_FCOE */
+
+#ifdef CONFIG_IXGBE_DCB
+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];
+	int i, q;
+
+	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
+		return ret;
+
+	f->indices = 0;
+	for (i = 0; i < MAX_TRAFFIC_CLASS; i++) {
+		q = min((int)num_online_cpus(), MAX_TRAFFIC_CLASS);
+		f->indices += q;
 	}
 
+	f->mask = 0x7 << 3;
+	adapter->num_rx_queues = f->indices;
+	adapter->num_tx_queues = f->indices;
+	ret = true;
+
+#ifdef IXGBE_FCOE
+	/* FCoE enabled queues require special configuration done through
+	 * configure_fcoe() and others. Here we map FCoE indices onto the
+	 * DCB queue pairs allowing FCoE to own configuration later.
+	 */
+	ixgbe_set_fcoe_queues(adapter);
+#endif
+
 	return ret;
 }
+#endif
 
-#endif /* IXGBE_FCOE */
 /**
  * ixgbe_set_sriov_queues: Allocate queues for IOV use
  * @adapter: board private structure to initialize
@@ -4378,7 +4443,7 @@
 }
 
 /*
- * ixgbe_set_num_queues: Allocate queues for device, feature dependant
+ * ixgbe_set_num_queues: Allocate queues for device, feature dependent
  * @adapter: board private structure to initialize
  *
  * This is the top level queue allocation routine.  The order here is very
@@ -4399,16 +4464,16 @@
 	if (ixgbe_set_sriov_queues(adapter))
 		goto done;
 
-#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
+#ifdef IXGBE_FCOE
+	if (ixgbe_set_fcoe_queues(adapter))
+		goto done;
+
+#endif /* IXGBE_FCOE */
 	if (ixgbe_set_fdir_queues(adapter))
 		goto done;
 
@@ -4500,6 +4565,110 @@
 }
 
 #ifdef CONFIG_IXGBE_DCB
+
+/* ixgbe_get_first_reg_idx - Return first register index associated with ring */
+void ixgbe_get_first_reg_idx(struct ixgbe_adapter *adapter, u8 tc,
+			     unsigned int *tx, unsigned int *rx)
+{
+	struct net_device *dev = adapter->netdev;
+	struct ixgbe_hw *hw = &adapter->hw;
+	u8 num_tcs = netdev_get_num_tc(dev);
+
+	*tx = 0;
+	*rx = 0;
+
+	switch (hw->mac.type) {
+	case ixgbe_mac_82598EB:
+		*tx = tc << 3;
+		*rx = tc << 2;
+		break;
+	case ixgbe_mac_82599EB:
+	case ixgbe_mac_X540:
+		if (num_tcs == 8) {
+			if (tc < 3) {
+				*tx = tc << 5;
+				*rx = tc << 4;
+			} else if (tc <  5) {
+				*tx = ((tc + 2) << 4);
+				*rx = tc << 4;
+			} else if (tc < num_tcs) {
+				*tx = ((tc + 8) << 3);
+				*rx = tc << 4;
+			}
+		} else if (num_tcs == 4) {
+			*rx =  tc << 5;
+			switch (tc) {
+			case 0:
+				*tx =  0;
+				break;
+			case 1:
+				*tx = 64;
+				break;
+			case 2:
+				*tx = 96;
+				break;
+			case 3:
+				*tx = 112;
+				break;
+			default:
+				break;
+			}
+		}
+		break;
+	default:
+		break;
+	}
+}
+
+#define IXGBE_MAX_Q_PER_TC	(IXGBE_MAX_DCB_INDICES / MAX_TRAFFIC_CLASS)
+
+/* ixgbe_setup_tc - routine to configure net_device for multiple traffic
+ * classes.
+ *
+ * @netdev: net device to configure
+ * @tc: number of traffic classes to enable
+ */
+int ixgbe_setup_tc(struct net_device *dev, u8 tc)
+{
+	int i;
+	unsigned int q, offset = 0;
+
+	if (!tc) {
+		netdev_reset_tc(dev);
+	} else {
+		struct ixgbe_adapter *adapter = netdev_priv(dev);
+
+		/* Hardware supports up to 8 traffic classes */
+		if (tc > MAX_TRAFFIC_CLASS || netdev_set_num_tc(dev, tc))
+			return -EINVAL;
+
+		/* Partition Tx queues evenly amongst traffic classes */
+		for (i = 0; i < tc; i++) {
+			q = min((int)num_online_cpus(), IXGBE_MAX_Q_PER_TC);
+			netdev_set_prio_tc_map(dev, i, i);
+			netdev_set_tc_queue(dev, i, q, offset);
+			offset += q;
+		}
+
+		/* This enables multiple traffic class support in the hardware
+		 * which defaults to strict priority transmission by default.
+		 * If traffic classes are already enabled perhaps through DCB
+		 * code path then existing configuration will be used.
+		 */
+		if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED) &&
+		    dev->dcbnl_ops && dev->dcbnl_ops->setdcbx) {
+			struct ieee_ets ets = {
+					.prio_tc = {0, 1, 2, 3, 4, 5, 6, 7},
+					      };
+			u8 mode = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_IEEE;
+
+			dev->dcbnl_ops->setdcbx(dev, mode);
+			dev->dcbnl_ops->ieee_setets(dev, &ets);
+		}
+	}
+	return 0;
+}
+
 /**
  * ixgbe_cache_ring_dcb - Descriptor ring to register mapping for DCB
  * @adapter: board private structure to initialize
@@ -4509,72 +4678,27 @@
  **/
 static inline bool ixgbe_cache_ring_dcb(struct ixgbe_adapter *adapter)
 {
-	int i;
-	bool ret = false;
-	int dcb_i = adapter->ring_feature[RING_F_DCB].indices;
+	struct net_device *dev = adapter->netdev;
+	int i, j, k;
+	u8 num_tcs = netdev_get_num_tc(dev);
 
 	if (!(adapter->flags & IXGBE_FLAG_DCB_ENABLED))
 		return false;
 
-	/* the number of queues is assumed to be symmetric */
-	switch (adapter->hw.mac.type) {
-	case ixgbe_mac_82598EB:
-		for (i = 0; i < dcb_i; i++) {
-			adapter->rx_ring[i]->reg_idx = i << 3;
-			adapter->tx_ring[i]->reg_idx = i << 2;
-		}
-		ret = true;
-		break;
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		if (dcb_i == 8) {
-			/*
-			 * Tx TC0 starts at: descriptor queue 0
-			 * Tx TC1 starts at: descriptor queue 32
-			 * Tx TC2 starts at: descriptor queue 64
-			 * Tx TC3 starts at: descriptor queue 80
-			 * Tx TC4 starts at: descriptor queue 96
-			 * Tx TC5 starts at: descriptor queue 104
-			 * Tx TC6 starts at: descriptor queue 112
-			 * Tx TC7 starts at: descriptor queue 120
-			 *
-			 * Rx TC0-TC7 are offset by 16 queues each
-			 */
-			for (i = 0; i < 3; i++) {
-				adapter->tx_ring[i]->reg_idx = i << 5;
-				adapter->rx_ring[i]->reg_idx = i << 4;
-			}
-			for ( ; i < 5; i++) {
-				adapter->tx_ring[i]->reg_idx = ((i + 2) << 4);
-				adapter->rx_ring[i]->reg_idx = i << 4;
-			}
-			for ( ; i < dcb_i; i++) {
-				adapter->tx_ring[i]->reg_idx = ((i + 8) << 3);
-				adapter->rx_ring[i]->reg_idx = i << 4;
-			}
-			ret = true;
-		} else if (dcb_i == 4) {
-			/*
-			 * Tx TC0 starts at: descriptor queue 0
-			 * Tx TC1 starts at: descriptor queue 64
-			 * Tx TC2 starts at: descriptor queue 96
-			 * Tx TC3 starts at: descriptor queue 112
-			 *
-			 * Rx TC0-TC3 are offset by 32 queues each
-			 */
-			adapter->tx_ring[0]->reg_idx = 0;
-			adapter->tx_ring[1]->reg_idx = 64;
-			adapter->tx_ring[2]->reg_idx = 96;
-			adapter->tx_ring[3]->reg_idx = 112;
-			for (i = 0 ; i < dcb_i; i++)
-				adapter->rx_ring[i]->reg_idx = i << 5;
-			ret = true;
+	for (i = 0, k = 0; i < num_tcs; i++) {
+		unsigned int tx_s, rx_s;
+		u16 count = dev->tc_to_txq[i].count;
+
+		ixgbe_get_first_reg_idx(adapter, i, &tx_s, &rx_s);
+		for (j = 0; j < count; j++, k++) {
+			adapter->tx_ring[k]->reg_idx = tx_s + j;
+			adapter->rx_ring[k]->reg_idx = rx_s + j;
+			adapter->tx_ring[k]->dcb_tc = i;
+			adapter->rx_ring[k]->dcb_tc = i;
 		}
-		break;
-	default:
-		break;
 	}
-	return ret;
+
+	return true;
 }
 #endif
 
@@ -4620,33 +4744,6 @@
 	if (!(adapter->flags & IXGBE_FLAG_FCOE_ENABLED))
 		return false;
 
-#ifdef CONFIG_IXGBE_DCB
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		struct ixgbe_fcoe *fcoe = &adapter->fcoe;
-
-		ixgbe_cache_ring_dcb(adapter);
-		/* find out queues in TC for FCoE */
-		fcoe_rx_i = adapter->rx_ring[fcoe->tc]->reg_idx + 1;
-		fcoe_tx_i = adapter->tx_ring[fcoe->tc]->reg_idx + 1;
-		/*
-		 * In 82599, the number of Tx queues for each traffic
-		 * class for both 8-TC and 4-TC modes are:
-		 * TCs  : TC0 TC1 TC2 TC3 TC4 TC5 TC6 TC7
-		 * 8 TCs:  32  32  16  16   8   8   8   8
-		 * 4 TCs:  64  64  32  32
-		 * We have max 8 queues for FCoE, where 8 the is
-		 * FCoE redirection table size. If TC for FCoE is
-		 * less than or equal to TC3, we have enough queues
-		 * to add max of 8 queues for FCoE, so we start FCoE
-		 * Tx queue from the next one, i.e., reg_idx + 1.
-		 * If TC for FCoE is above TC3, implying 8 TC mode,
-		 * and we need 8 for FCoE, we have to take all queues
-		 * in that traffic class for FCoE.
-		 */
-		if ((f->indices == IXGBE_FCRETA_SIZE) && (fcoe->tc > 3))
-			fcoe_tx_i--;
-	}
-#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))
@@ -4703,16 +4800,16 @@
 	if (ixgbe_cache_ring_sriov(adapter))
 		return;
 
+#ifdef CONFIG_IXGBE_DCB
+	if (ixgbe_cache_ring_dcb(adapter))
+		return;
+#endif
+
 #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;
 
@@ -5174,10 +5271,10 @@
 	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;
+	adapter->dcbx_cap = DCB_CAP_DCBX_HOST | DCB_CAP_DCBX_VER_CEE;
 	ixgbe_copy_dcb_cfg(&adapter->dcb_cfg, &adapter->temp_dcb_cfg,
-			   adapter->ring_feature[RING_F_DCB].indices);
+			   MAX_TRAFFIC_CLASS);
 
 #endif
 
@@ -5442,8 +5539,14 @@
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
 
 	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
-		return -EINVAL;
+	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED &&
+	    hw->mac.type != ixgbe_mac_X540) {
+		if ((new_mtu < 68) || (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
+			return -EINVAL;
+	} else {
+		if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE))
+			return -EINVAL;
+	}
 
 	e_info(probe, "changing MTU from %d to %d\n", netdev->mtu, new_mtu);
 	/* must set new MTU before calling down or up */
@@ -5611,6 +5714,10 @@
 	}
 
 	ixgbe_clear_interrupt_scheme(adapter);
+#ifdef CONFIG_DCB
+	kfree(adapter->ixgbe_ieee_pfc);
+	kfree(adapter->ixgbe_ieee_ets);
+#endif
 
 #ifdef CONFIG_PM
 	retval = pci_save_state(pdev);
@@ -6101,12 +6208,16 @@
 			       (link_speed == IXGBE_LINK_SPEED_10GB_FULL ?
 			       "10 Gbps" :
 			       (link_speed == IXGBE_LINK_SPEED_1GB_FULL ?
-			       "1 Gbps" : "unknown speed")),
+			       "1 Gbps" :
+			       (link_speed == IXGBE_LINK_SPEED_100_FULL ?
+			       "100 Mbps" :
+			       "unknown speed"))),
 			       ((flow_rx && flow_tx) ? "RX/TX" :
 			       (flow_rx ? "RX" :
 			       (flow_tx ? "TX" : "None"))));
 
 			netif_carrier_on(netdev);
+			ixgbe_check_vf_rate_limit(adapter);
 		} else {
 			/* Force detection of hung controller */
 			for (i = 0; i < adapter->num_tx_queues; i++) {
@@ -6636,18 +6747,12 @@
 
 	protocol = vlan_get_protocol(skb);
 
-	if ((protocol == htons(ETH_P_FCOE)) ||
-	    (protocol == htons(ETH_P_FIP))) {
-		if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED) {
-			txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1);
-			txq += adapter->ring_feature[RING_F_FCOE].mask;
-			return txq;
-#ifdef CONFIG_IXGBE_DCB
-		} else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			txq = adapter->fcoe.up;
-			return txq;
-#endif
-		}
+	if (((protocol == htons(ETH_P_FCOE)) ||
+	    (protocol == htons(ETH_P_FIP))) &&
+	    (adapter->flags & IXGBE_FLAG_FCOE_ENABLED)) {
+		txq &= (adapter->ring_feature[RING_F_FCOE].indices - 1);
+		txq += adapter->ring_feature[RING_F_FCOE].mask;
+		return txq;
 	}
 #endif
 
@@ -6657,15 +6762,6 @@
 		return txq;
 	}
 
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-		if (skb->priority == TC_PRIO_CONTROL)
-			txq = adapter->ring_feature[RING_F_DCB].indices-1;
-		else
-			txq = (skb->vlan_tci & IXGBE_TX_FLAGS_VLAN_PRIO_MASK)
-			       >> 13;
-		return txq;
-	}
-
 	return skb_tx_hash(dev, skb);
 }
 
@@ -6687,13 +6783,13 @@
 		tx_flags |= vlan_tx_tag_get(skb);
 		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
 			tx_flags &= ~IXGBE_TX_FLAGS_VLAN_PRIO_MASK;
-			tx_flags |= ((skb->queue_mapping & 0x7) << 13);
+			tx_flags |= tx_ring->dcb_tc << 13;
 		}
 		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 	} else if (adapter->flags & IXGBE_FLAG_DCB_ENABLED &&
 		   skb->priority != TC_PRIO_CONTROL) {
-		tx_flags |= ((skb->queue_mapping & 0x7) << 13);
+		tx_flags |= tx_ring->dcb_tc << 13;
 		tx_flags <<= IXGBE_TX_FLAGS_VLAN_SHIFT;
 		tx_flags |= IXGBE_TX_FLAGS_VLAN;
 	}
@@ -6702,20 +6798,8 @@
 	/* for FCoE with DCB, we force the priority to what
 	 * was specified by the switch */
 	if (adapter->flags & IXGBE_FLAG_FCOE_ENABLED &&
-	    (protocol == htons(ETH_P_FCOE) ||
-	     protocol == htons(ETH_P_FIP))) {
-#ifdef CONFIG_IXGBE_DCB
-		if (adapter->flags & IXGBE_FLAG_DCB_ENABLED) {
-			tx_flags &= ~(IXGBE_TX_FLAGS_VLAN_PRIO_MASK
-				      << IXGBE_TX_FLAGS_VLAN_SHIFT);
-			tx_flags |= ((adapter->fcoe.up << 13)
-				      << IXGBE_TX_FLAGS_VLAN_SHIFT);
-		}
-#endif
-		/* flag for FCoE offloads */
-		if (protocol == htons(ETH_P_FCOE))
-			tx_flags |= IXGBE_TX_FLAGS_FCOE;
-	}
+	    (protocol == htons(ETH_P_FCOE)))
+		tx_flags |= IXGBE_TX_FLAGS_FCOE;
 #endif
 
 	/* four things can cause us to need a context descriptor */
@@ -6988,11 +7072,15 @@
 	.ndo_set_vf_tx_rate	= ixgbe_ndo_set_vf_bw,
 	.ndo_get_vf_config	= ixgbe_ndo_get_vf_config,
 	.ndo_get_stats64	= ixgbe_get_stats64,
+#ifdef CONFIG_IXGBE_DCB
+	.ndo_setup_tc		= ixgbe_setup_tc,
+#endif
 #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_target = ixgbe_fcoe_ddp_target,
 	.ndo_fcoe_ddp_done = ixgbe_fcoe_ddp_put,
 	.ndo_fcoe_enable = ixgbe_fcoe_enable,
 	.ndo_fcoe_disable = ixgbe_fcoe_disable,
@@ -7128,8 +7216,9 @@
 	else
 		indices = min_t(unsigned int, indices, IXGBE_MAX_FDIR_INDICES);
 
+#if defined(CONFIG_DCB)
 	indices = max_t(unsigned int, indices, IXGBE_MAX_DCB_INDICES);
-#ifdef IXGBE_FCOE
+#elif defined(IXGBE_FCOE)
 	indices += min_t(unsigned int, num_possible_cpus(),
 			 IXGBE_MAX_FCOE_INDICES);
 #endif
@@ -7285,8 +7374,6 @@
 	if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
 		adapter->flags &= ~(IXGBE_FLAG_RSS_ENABLED |
 				    IXGBE_FLAG_DCB_ENABLED);
-	if (adapter->flags & IXGBE_FLAG_DCB_ENABLED)
-		adapter->flags &= ~IXGBE_FLAG_RSS_ENABLED;
 
 #ifdef CONFIG_IXGBE_DCB
 	netdev->dcbnl_ops = &dcbnl_ops;
@@ -7706,16 +7793,6 @@
 
 #endif /* CONFIG_IXGBE_DCA */
 
-/**
- * ixgbe_get_hw_dev return device
- * used by hardware layer to print debugging information
- **/
-struct net_device *ixgbe_get_hw_dev(struct ixgbe_hw *hw)
-{
-	struct ixgbe_adapter *adapter = hw->back;
-	return adapter->netdev;
-}
-
 module_exit(ixgbe_exit_module);
 
 /* ixgbe_main.c */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_mbx.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_mbx.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_mbx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_mbx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -154,9 +154,6 @@
 		udelay(mbx->usec_delay);
 	}
 
-	/* if we failed, all future posted messages fail until reset */
-	if (!countdown)
-		mbx->timeout = 0;
 out:
 	return countdown ? 0 : IXGBE_ERR_MBX;
 }
@@ -183,9 +180,6 @@
 		udelay(mbx->usec_delay);
 	}
 
-	/* if we failed, all future posted messages fail until reset */
-	if (!countdown)
-		mbx->timeout = 0;
 out:
 	return countdown ? 0 : IXGBE_ERR_MBX;
 }
@@ -437,6 +431,7 @@
 	return ret_val;
 }
 
+#ifdef CONFIG_PCI_IOV
 /**
  *  ixgbe_init_mbx_params_pf - set initial values for pf mailbox
  *  @hw: pointer to the HW structure
@@ -447,24 +442,22 @@
 {
 	struct ixgbe_mbx_info *mbx = &hw->mbx;
 
-	switch (hw->mac.type) {
-	case ixgbe_mac_82599EB:
-	case ixgbe_mac_X540:
-		mbx->timeout = 0;
-		mbx->usec_delay = 0;
+	if (hw->mac.type != ixgbe_mac_82599EB &&
+	    hw->mac.type != ixgbe_mac_X540)
+		return;
 
-		mbx->size = IXGBE_VFMAILBOX_SIZE;
+	mbx->timeout = 0;
+	mbx->usec_delay = 0;
 
-		mbx->stats.msgs_tx = 0;
-		mbx->stats.msgs_rx = 0;
-		mbx->stats.reqs = 0;
-		mbx->stats.acks = 0;
-		mbx->stats.rsts = 0;
-		break;
-	default:
-		break;
-	}
+	mbx->stats.msgs_tx = 0;
+	mbx->stats.msgs_rx = 0;
+	mbx->stats.reqs = 0;
+	mbx->stats.acks = 0;
+	mbx->stats.rsts = 0;
+
+	mbx->size = IXGBE_VFMAILBOX_SIZE;
 }
+#endif /* CONFIG_PCI_IOV */
 
 struct ixgbe_mbx_operations mbx_ops_generic = {
 	.read                   = ixgbe_read_mbx_pf,
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_mbx.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_mbx.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_mbx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_mbx.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -86,7 +86,9 @@
 s32 ixgbe_check_for_msg(struct ixgbe_hw *, u16);
 s32 ixgbe_check_for_ack(struct ixgbe_hw *, u16);
 s32 ixgbe_check_for_rst(struct ixgbe_hw *, u16);
+#ifdef CONFIG_PCI_IOV
 void ixgbe_init_mbx_params_pf(struct ixgbe_hw *);
+#endif /* CONFIG_PCI_IOV */
 
 extern struct ixgbe_mbx_operations mbx_ops_generic;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_phy.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -57,6 +57,7 @@
 {
 	s32 status = IXGBE_ERR_PHY_ADDR_INVALID;
 	u32 phy_addr;
+	u16 ext_ability = 0;
 
 	if (hw->phy.type == ixgbe_phy_unknown) {
 		for (phy_addr = 0; phy_addr < IXGBE_MAX_PHY_ADDR; phy_addr++) {
@@ -65,12 +66,29 @@
 				ixgbe_get_phy_id(hw);
 				hw->phy.type =
 				        ixgbe_get_phy_type_from_id(hw->phy.id);
+
+				if (hw->phy.type == ixgbe_phy_unknown) {
+					hw->phy.ops.read_reg(hw,
+							     MDIO_PMA_EXTABLE,
+							     MDIO_MMD_PMAPMD,
+							     &ext_ability);
+					if (ext_ability &
+					    (MDIO_PMA_EXTABLE_10GBT |
+					     MDIO_PMA_EXTABLE_1000BT))
+						hw->phy.type =
+							 ixgbe_phy_cu_unknown;
+					else
+						hw->phy.type =
+							 ixgbe_phy_generic;
+				}
+
 				status = 0;
 				break;
 			}
 		}
 		/* clear value if nothing found */
-		hw->phy.mdio.prtad = 0;
+		if (status != 0)
+			hw->phy.mdio.prtad = 0;
 	} else {
 		status = 0;
 	}
@@ -138,17 +156,51 @@
  **/
 s32 ixgbe_reset_phy_generic(struct ixgbe_hw *hw)
 {
+	u32 i;
+	u16 ctrl = 0;
+	s32 status = 0;
+
+	if (hw->phy.type == ixgbe_phy_unknown)
+		status = ixgbe_identify_phy_generic(hw);
+
+	if (status != 0 || hw->phy.type == ixgbe_phy_none)
+		goto out;
+
 	/* Don't reset PHY if it's shut down due to overtemp. */
 	if (!hw->phy.reset_if_overtemp &&
 	    (IXGBE_ERR_OVERTEMP == hw->phy.ops.check_overtemp(hw)))
-		return 0;
+		goto out;
 
 	/*
 	 * Perform soft PHY reset to the PHY_XS.
 	 * This will cause a soft reset to the PHY
 	 */
-	return hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_PHYXS,
-				     MDIO_CTRL1_RESET);
+	hw->phy.ops.write_reg(hw, MDIO_CTRL1,
+			      MDIO_MMD_PHYXS,
+			      MDIO_CTRL1_RESET);
+
+	/*
+	 * Poll for reset bit to self-clear indicating reset is complete.
+	 * Some PHYs could take up to 3 seconds to complete and need about
+	 * 1.7 usec delay after the reset is complete.
+	 */
+	for (i = 0; i < 30; i++) {
+		msleep(100);
+		hw->phy.ops.read_reg(hw, MDIO_CTRL1,
+				     MDIO_MMD_PHYXS, &ctrl);
+		if (!(ctrl & MDIO_CTRL1_RESET)) {
+			udelay(2);
+			break;
+		}
+	}
+
+	if (ctrl & MDIO_CTRL1_RESET) {
+		status = IXGBE_ERR_RESET_FAILED;
+		hw_dbg(hw, "PHY reset polling failed to complete.\n");
+	}
+
+out:
+	return status;
 }
 
 /**
@@ -171,7 +223,7 @@
 	else
 		gssr = IXGBE_GSSR_PHY0_SM;
 
-	if (ixgbe_acquire_swfw_sync(hw, gssr) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == 0) {
@@ -243,7 +295,7 @@
 			}
 		}
 
-		ixgbe_release_swfw_sync(hw, gssr);
+		hw->mac.ops.release_swfw_sync(hw, gssr);
 	}
 
 	return status;
@@ -269,7 +321,7 @@
 	else
 		gssr = IXGBE_GSSR_PHY0_SM;
 
-	if (ixgbe_acquire_swfw_sync(hw, gssr) != 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, gssr) != 0)
 		status = IXGBE_ERR_SWFW_SYNC;
 
 	if (status == 0) {
@@ -336,7 +388,7 @@
 			}
 		}
 
-		ixgbe_release_swfw_sync(hw, gssr);
+		hw->mac.ops.release_swfw_sync(hw, gssr);
 	}
 
 	return status;
@@ -350,49 +402,89 @@
  **/
 s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw)
 {
-	s32 status = IXGBE_NOT_IMPLEMENTED;
+	s32 status = 0;
 	u32 time_out;
 	u32 max_time_out = 10;
-	u16 autoneg_reg;
+	u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+	bool autoneg = false;
+	ixgbe_link_speed speed;
 
-	/*
-	 * Set advertisement settings in PHY based on autoneg_advertised
-	 * settings. If autoneg_advertised = 0, then advertise default values
-	 * tnx devices cannot be "forced" to a autoneg 10G and fail.  But can
-	 * for a 1G.
-	 */
-	hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg);
+	ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
+
+	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+		/* Set or unset auto-negotiation 10G advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
 
-	if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL)
 		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
-	else
-		autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+			autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
 
-	hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg);
+		hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+		/* Set or unset auto-negotiation 1G advertisement */
+		hw->phy.ops.read_reg(hw,
+				     IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+			autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE;
+
+		hw->phy.ops.write_reg(hw,
+				      IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_100_FULL) {
+		/* Set or unset auto-negotiation 100M advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~ADVERTISE_100FULL;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
+			autoneg_reg |= ADVERTISE_100FULL;
+
+		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, MDIO_CTRL1, MDIO_MMD_AN, &autoneg_reg);
+	hw->phy.ops.read_reg(hw, MDIO_CTRL1,
+			     MDIO_MMD_AN, &autoneg_reg);
 
 	autoneg_reg |= MDIO_AN_CTRL1_RESTART;
 
-	hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, 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, MDIO_STAT1, MDIO_MMD_AN,
-		                              &autoneg_reg);
+		status = hw->phy.ops.read_reg(hw, MDIO_STAT1,
+					      MDIO_MMD_AN,
+					      &autoneg_reg);
 
 		autoneg_reg &= MDIO_AN_STAT1_COMPLETE;
 		if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) {
-			status = 0;
 			break;
 		}
 	}
 
-	if (time_out == max_time_out)
+	if (time_out == max_time_out) {
 		status = IXGBE_ERR_LINK_SETUP;
+		hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out");
+	}
 
 	return status;
 }
@@ -421,6 +513,9 @@
 	if (speed & IXGBE_LINK_SPEED_1GB_FULL)
 		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
+	if (speed & IXGBE_LINK_SPEED_100_FULL)
+		hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL;
+
 	/* Setup link based on the new speed settings */
 	hw->phy.ops.setup_link(hw);
 
@@ -461,6 +556,180 @@
 }
 
 /**
+ *  ixgbe_check_phy_link_tnx - Determine link and speed status
+ *  @hw: pointer to hardware structure
+ *
+ *  Reads the VS1 register to determine if link is up and the current speed for
+ *  the PHY.
+ **/
+s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
+			     bool *link_up)
+{
+	s32 status = 0;
+	u32 time_out;
+	u32 max_time_out = 10;
+	u16 phy_link = 0;
+	u16 phy_speed = 0;
+	u16 phy_data = 0;
+
+	/* Initialize speed and link to default case */
+	*link_up = false;
+	*speed = IXGBE_LINK_SPEED_10GB_FULL;
+
+	/*
+	 * Check current speed and link status of the PHY register.
+	 * This is a vendor specific register and may have to
+	 * be changed for other copper PHYs.
+	 */
+	for (time_out = 0; time_out < max_time_out; time_out++) {
+		udelay(10);
+		status = hw->phy.ops.read_reg(hw,
+					      MDIO_STAT1,
+					      MDIO_MMD_VEND1,
+					      &phy_data);
+		phy_link = phy_data &
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
+		phy_speed = phy_data &
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
+		if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
+			*link_up = true;
+			if (phy_speed ==
+			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
+				*speed = IXGBE_LINK_SPEED_1GB_FULL;
+			break;
+		}
+	}
+
+	return status;
+}
+
+/**
+ *	ixgbe_setup_phy_link_tnx - Set and restart autoneg
+ *	@hw: pointer to hardware structure
+ *
+ *	Restart autonegotiation and PHY and waits for completion.
+ **/
+s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw)
+{
+	s32 status = 0;
+	u32 time_out;
+	u32 max_time_out = 10;
+	u16 autoneg_reg = IXGBE_MII_AUTONEG_REG;
+	bool autoneg = false;
+	ixgbe_link_speed speed;
+
+	ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg);
+
+	if (speed & IXGBE_LINK_SPEED_10GB_FULL) {
+		/* Set or unset auto-negotiation 10G advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
+			autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G;
+
+		hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_1GB_FULL) {
+		/* Set or unset auto-negotiation 1G advertisement */
+		hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL)
+			autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX;
+
+		hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG,
+				      MDIO_MMD_AN,
+				      autoneg_reg);
+	}
+
+	if (speed & IXGBE_LINK_SPEED_100_FULL) {
+		/* Set or unset auto-negotiation 100M advertisement */
+		hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE,
+				     MDIO_MMD_AN,
+				     &autoneg_reg);
+
+		autoneg_reg &= ~ADVERTISE_100FULL;
+		if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
+			autoneg_reg |= ADVERTISE_100FULL;
+
+		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, MDIO_CTRL1,
+			     MDIO_MMD_AN, &autoneg_reg);
+
+	autoneg_reg |= MDIO_AN_CTRL1_RESTART;
+
+	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, MDIO_STAT1,
+					      MDIO_MMD_AN,
+					      &autoneg_reg);
+
+		autoneg_reg &= MDIO_AN_STAT1_COMPLETE;
+		if (autoneg_reg == MDIO_AN_STAT1_COMPLETE)
+			break;
+	}
+
+	if (time_out == max_time_out) {
+		status = IXGBE_ERR_LINK_SETUP;
+		hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out");
+	}
+
+	return status;
+}
+
+/**
+ *  ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
+ *  @hw: pointer to hardware structure
+ *  @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
+				       u16 *firmware_version)
+{
+	s32 status = 0;
+
+	status = hw->phy.ops.read_reg(hw, TNX_FW_REV,
+				      MDIO_MMD_VEND1,
+				      firmware_version);
+
+	return status;
+}
+
+/**
+ *  ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
+ *  @hw: pointer to hardware structure
+ *  @firmware_version: pointer to the PHY Firmware Version
+ **/
+s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
+					   u16 *firmware_version)
+{
+	s32 status = 0;
+
+	status = hw->phy.ops.read_reg(hw, AQ_FW_REV,
+				      MDIO_MMD_VEND1,
+				      firmware_version);
+
+	return status;
+}
+
+/**
  *  ixgbe_reset_phy_nl - Performs a PHY reset
  *  @hw: pointer to hardware structure
  **/
@@ -556,11 +825,10 @@
 }
 
 /**
- *  ixgbe_identify_sfp_module_generic - Identifies SFP module and assigns
- *                                      the PHY type.
+ *  ixgbe_identify_sfp_module_generic - Identifies SFP modules
  *  @hw: pointer to hardware structure
  *
- *  Searches for and indentifies the SFP module.  Assings appropriate PHY type.
+ *  Searches for and identifies the SFP module and assigns appropriate PHY type.
  **/
 s32 ixgbe_identify_sfp_module_generic(struct ixgbe_hw *hw)
 {
@@ -581,41 +849,62 @@
 		goto out;
 	}
 
-	status = hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_IDENTIFIER,
+	status = hw->phy.ops.read_i2c_eeprom(hw,
+					     IXGBE_SFF_IDENTIFIER,
 	                                     &identifier);
 
-	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;
-	}
+	if (status == IXGBE_ERR_SWFW_SYNC ||
+	    status == IXGBE_ERR_I2C ||
+	    status == IXGBE_ERR_SFP_NOT_PRESENT)
+		goto err_read_i2c_eeprom;
 
-	if (identifier == IXGBE_SFF_IDENTIFIER_SFP) {
-		hw->phy.ops.read_i2c_eeprom(hw, IXGBE_SFF_1GBE_COMP_CODES,
-		                            &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_CABLE_TECHNOLOGY,
-		                            &cable_tech);
+	/* LAN ID is needed for sfp_type determination */
+	hw->mac.ops.set_lan_id(hw);
 
-		/* ID Module
-		 * =========
-		 * 0    SFP_DA_CU
-		 * 1    SFP_SR
-		 * 2    SFP_LR
-		 * 3    SFP_DA_CORE0 - 82599-specific
-		 * 4    SFP_DA_CORE1 - 82599-specific
-		 * 5    SFP_SR/LR_CORE0 - 82599-specific
-		 * 6    SFP_SR/LR_CORE1 - 82599-specific
-		 * 7    SFP_act_lmt_DA_CORE0 - 82599-specific
-		 * 8    SFP_act_lmt_DA_CORE1 - 82599-specific
-		 * 9    SFP_1g_cu_CORE0 - 82599-specific
-		 * 10   SFP_1g_cu_CORE1 - 82599-specific
-		 */
+	if (identifier != IXGBE_SFF_IDENTIFIER_SFP) {
+		hw->phy.type = ixgbe_phy_sfp_unsupported;
+		status = IXGBE_ERR_SFP_NOT_SUPPORTED;
+	} else {
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+						     IXGBE_SFF_1GBE_COMP_CODES,
+						     &comp_codes_1g);
+
+		if (status == IXGBE_ERR_SWFW_SYNC ||
+		    status == IXGBE_ERR_I2C ||
+		    status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto err_read_i2c_eeprom;
+
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+						     IXGBE_SFF_10GBE_COMP_CODES,
+						     &comp_codes_10g);
+
+		if (status == IXGBE_ERR_SWFW_SYNC ||
+		    status == IXGBE_ERR_I2C ||
+		    status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto err_read_i2c_eeprom;
+		status = hw->phy.ops.read_i2c_eeprom(hw,
+						     IXGBE_SFF_CABLE_TECHNOLOGY,
+						     &cable_tech);
+
+		if (status == IXGBE_ERR_SWFW_SYNC ||
+		    status == IXGBE_ERR_I2C ||
+		    status == IXGBE_ERR_SFP_NOT_PRESENT)
+			goto err_read_i2c_eeprom;
+
+		 /* ID Module
+		  * =========
+		  * 0   SFP_DA_CU
+		  * 1   SFP_SR
+		  * 2   SFP_LR
+		  * 3   SFP_DA_CORE0 - 82599-specific
+		  * 4   SFP_DA_CORE1 - 82599-specific
+		  * 5   SFP_SR/LR_CORE0 - 82599-specific
+		  * 6   SFP_SR/LR_CORE1 - 82599-specific
+		  * 7   SFP_act_lmt_DA_CORE0 - 82599-specific
+		  * 8   SFP_act_lmt_DA_CORE1 - 82599-specific
+		  * 9   SFP_1g_cu_CORE0 - 82599-specific
+		  * 10  SFP_1g_cu_CORE1 - 82599-specific
+		  */
 		if (hw->mac.type == ixgbe_mac_82598EB) {
 			if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 				hw->phy.sfp_type = ixgbe_sfp_type_da_cu;
@@ -647,31 +936,27 @@
 						ixgbe_sfp_type_da_act_lmt_core1;
 				} else {
 					hw->phy.sfp_type =
-						ixgbe_sfp_type_unknown;
+							ixgbe_sfp_type_unknown;
 				}
-			} else if (comp_codes_10g & IXGBE_SFF_10GBASESR_CAPABLE)
-				if (hw->bus.lan_id == 0)
-					hw->phy.sfp_type =
-					              ixgbe_sfp_type_srlr_core0;
-				else
-					hw->phy.sfp_type =
-					              ixgbe_sfp_type_srlr_core1;
-			else if (comp_codes_10g & IXGBE_SFF_10GBASELR_CAPABLE)
+			} else if (comp_codes_10g &
+				   (IXGBE_SFF_10GBASESR_CAPABLE |
+				    IXGBE_SFF_10GBASELR_CAPABLE)) {
 				if (hw->bus.lan_id == 0)
 					hw->phy.sfp_type =
 					              ixgbe_sfp_type_srlr_core0;
 				else
 					hw->phy.sfp_type =
 					              ixgbe_sfp_type_srlr_core1;
-			else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE)
+			} else if (comp_codes_1g & IXGBE_SFF_1GBASET_CAPABLE) {
 				if (hw->bus.lan_id == 0)
 					hw->phy.sfp_type =
 						ixgbe_sfp_type_1g_cu_core0;
 				else
 					hw->phy.sfp_type =
 						ixgbe_sfp_type_1g_cu_core1;
-			else
+			} else {
 				hw->phy.sfp_type = ixgbe_sfp_type_unknown;
+			}
 		}
 
 		if (hw->phy.sfp_type != stored_sfp_type)
@@ -688,16 +973,33 @@
 		/* Determine PHY vendor */
 		if (hw->phy.type != ixgbe_phy_nl) {
 			hw->phy.id = identifier;
-			hw->phy.ops.read_i2c_eeprom(hw,
+			status = hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE0,
 			                            &oui_bytes[0]);
-			hw->phy.ops.read_i2c_eeprom(hw,
+
+			if (status == IXGBE_ERR_SWFW_SYNC ||
+			    status == IXGBE_ERR_I2C ||
+			    status == IXGBE_ERR_SFP_NOT_PRESENT)
+				goto err_read_i2c_eeprom;
+
+			status = hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE1,
 			                            &oui_bytes[1]);
-			hw->phy.ops.read_i2c_eeprom(hw,
+
+			if (status == IXGBE_ERR_SWFW_SYNC ||
+			    status == IXGBE_ERR_I2C ||
+			    status == IXGBE_ERR_SFP_NOT_PRESENT)
+				goto err_read_i2c_eeprom;
+
+			status = hw->phy.ops.read_i2c_eeprom(hw,
 			                            IXGBE_SFF_VENDOR_OUI_BYTE2,
 			                            &oui_bytes[2]);
 
+			if (status == IXGBE_ERR_SWFW_SYNC ||
+			    status == IXGBE_ERR_I2C ||
+			    status == IXGBE_ERR_SFP_NOT_PRESENT)
+				goto err_read_i2c_eeprom;
+
 			vendor_oui =
 			  ((oui_bytes[0] << IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT) |
 			   (oui_bytes[1] << IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT) |
@@ -707,7 +1009,7 @@
 			case IXGBE_SFF_VENDOR_OUI_TYCO:
 				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 					hw->phy.type =
-						ixgbe_phy_sfp_passive_tyco;
+						    ixgbe_phy_sfp_passive_tyco;
 				break;
 			case IXGBE_SFF_VENDOR_OUI_FTL:
 				if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
@@ -724,7 +1026,7 @@
 			default:
 				if (cable_tech & IXGBE_SFF_DA_PASSIVE_CABLE)
 					hw->phy.type =
-						ixgbe_phy_sfp_passive_unknown;
+						 ixgbe_phy_sfp_passive_unknown;
 				else if (cable_tech & IXGBE_SFF_DA_ACTIVE_CABLE)
 					hw->phy.type =
 						ixgbe_phy_sfp_active_unknown;
@@ -734,7 +1036,7 @@
 			}
 		}
 
-		/* All passive DA cables are supported */
+		/* Allow any DA cable vendor */
 		if (cable_tech & (IXGBE_SFF_DA_PASSIVE_CABLE |
 		    IXGBE_SFF_DA_ACTIVE_CABLE)) {
 			status = 0;
@@ -756,7 +1058,6 @@
 			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) &&
 		    !((hw->phy.sfp_type == ixgbe_sfp_type_1g_cu_core0) ||
@@ -776,15 +1077,24 @@
 
 out:
 	return status;
+
+err_read_i2c_eeprom:
+	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;
+	}
+	return IXGBE_ERR_SFP_NOT_PRESENT;
 }
 
 /**
- *  ixgbe_get_sfp_init_sequence_offsets - Checks the MAC's EEPROM to see
- *  if it supports a given SFP+ module type, if so it returns the offsets to the
- *  phy init sequence block.
+ *  ixgbe_get_sfp_init_sequence_offsets - Provides offset of PHY init sequence
  *  @hw: pointer to hardware structure
  *  @list_offset: offset to the SFP ID list
  *  @data_offset: offset to the SFP data block
+ *
+ *  Checks the MAC's EEPROM to see if it supports a given SFP+ module type, if
+ *  so it returns the offsets to the phy init sequence block.
  **/
 s32 ixgbe_get_sfp_init_sequence_offsets(struct ixgbe_hw *hw,
                                         u16 *list_offset,
@@ -899,11 +1209,22 @@
                                 u8 dev_addr, u8 *data)
 {
 	s32 status = 0;
-	u32 max_retry = 1;
+	u32 max_retry = 10;
 	u32 retry = 0;
+	u16 swfw_mask = 0;
 	bool nack = 1;
 
+	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+		swfw_mask = IXGBE_GSSR_PHY1_SM;
+	else
+		swfw_mask = IXGBE_GSSR_PHY0_SM;
+
 	do {
+		if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) {
+			status = IXGBE_ERR_SWFW_SYNC;
+			goto read_byte_out;
+		}
+
 		ixgbe_i2c_start(hw);
 
 		/* Device Address and write indication */
@@ -946,6 +1267,8 @@
 		break;
 
 fail:
+		ixgbe_release_swfw_sync(hw, swfw_mask);
+		msleep(100);
 		ixgbe_i2c_bus_clear(hw);
 		retry++;
 		if (retry < max_retry)
@@ -955,6 +1278,9 @@
 
 	} while (retry < max_retry);
 
+	ixgbe_release_swfw_sync(hw, swfw_mask);
+
+read_byte_out:
 	return status;
 }
 
@@ -973,6 +1299,17 @@
 	s32 status = 0;
 	u32 max_retry = 1;
 	u32 retry = 0;
+	u16 swfw_mask = 0;
+
+	if (IXGBE_READ_REG(hw, IXGBE_STATUS) & IXGBE_STATUS_LAN_ID_1)
+		swfw_mask = IXGBE_GSSR_PHY1_SM;
+	else
+		swfw_mask = IXGBE_GSSR_PHY0_SM;
+
+	if (ixgbe_acquire_swfw_sync(hw, swfw_mask) != 0) {
+		status = IXGBE_ERR_SWFW_SYNC;
+		goto write_byte_out;
+	}
 
 	do {
 		ixgbe_i2c_start(hw);
@@ -1013,6 +1350,9 @@
 			hw_dbg(hw, "I2C byte write error.\n");
 	} while (retry < max_retry);
 
+	ixgbe_release_swfw_sync(hw, swfw_mask);
+
+write_byte_out:
 	return status;
 }
 
@@ -1331,6 +1671,8 @@
 	u32 i2cctl = IXGBE_READ_REG(hw, IXGBE_I2CCTL);
 	u32 i;
 
+	ixgbe_i2c_start(hw);
+
 	ixgbe_set_i2c_data(hw, &i2cctl, 1);
 
 	for (i = 0; i < 9; i++) {
@@ -1345,92 +1687,14 @@
 		udelay(IXGBE_I2C_T_LOW);
 	}
 
+	ixgbe_i2c_start(hw);
+
 	/* Put the i2c bus back to default state */
 	ixgbe_i2c_stop(hw);
 }
 
 /**
- *  ixgbe_check_phy_link_tnx - Determine link and speed status
- *  @hw: pointer to hardware structure
- *
- *  Reads the VS1 register to determine if link is up and the current speed for
- *  the PHY.
- **/
-s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed,
-                             bool *link_up)
-{
-	s32 status = 0;
-	u32 time_out;
-	u32 max_time_out = 10;
-	u16 phy_link = 0;
-	u16 phy_speed = 0;
-	u16 phy_data = 0;
-
-	/* Initialize speed and link to default case */
-	*link_up = false;
-	*speed = IXGBE_LINK_SPEED_10GB_FULL;
-
-	/*
-	 * Check current speed and link status of the PHY register.
-	 * This is a vendor specific register and may have to
-	 * be changed for other copper PHYs.
-	 */
-	for (time_out = 0; time_out < max_time_out; time_out++) {
-		udelay(10);
-		status = hw->phy.ops.read_reg(hw,
-		                        IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS,
-					MDIO_MMD_VEND1,
-		                        &phy_data);
-		phy_link = phy_data &
-		           IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS;
-		phy_speed = phy_data &
-		            IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS;
-		if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) {
-			*link_up = true;
-			if (phy_speed ==
-			    IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS)
-				*speed = IXGBE_LINK_SPEED_1GB_FULL;
-			break;
-		}
-	}
-
-	return status;
-}
-
-/**
- *  ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version
- *  @hw: pointer to hardware structure
- *  @firmware_version: pointer to the PHY Firmware Version
- **/
-s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
-                                       u16 *firmware_version)
-{
-	s32 status = 0;
-
-	status = hw->phy.ops.read_reg(hw, TNX_FW_REV, MDIO_MMD_VEND1,
-	                              firmware_version);
-
-	return status;
-}
-
-/**
- *  ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version
- *  @hw: pointer to hardware structure
- *  @firmware_version: pointer to the PHY Firmware Version
-**/
-s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
-                                           u16 *firmware_version)
-{
-	s32 status = 0;
-
-	status = hw->phy.ops.read_reg(hw, AQ_FW_REV, MDIO_MMD_VEND1,
-	                              firmware_version);
-
-	return status;
-}
-
-/**
- *  ixgbe_tn_check_overtemp - Checks if an overtemp occured.
+ *  ixgbe_tn_check_overtemp - Checks if an overtemp occurred.
  *  @hw: pointer to hardware structure
  *
  *  Checks if the LASI temp alarm status was triggered due to overtemp
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_phy.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_phy.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_phy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_phy.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -58,6 +58,10 @@
 #define IXGBE_I2C_EEPROM_STATUS_FAIL         0x2
 #define IXGBE_I2C_EEPROM_STATUS_IN_PROGRESS  0x3
 
+/* Flow control defines */
+#define IXGBE_TAF_SYM_PAUSE                  0x400
+#define IXGBE_TAF_ASM_PAUSE                  0x800
+
 /* Bit-shift macros */
 #define IXGBE_SFF_VENDOR_OUI_BYTE0_SHIFT    24
 #define IXGBE_SFF_VENDOR_OUI_BYTE1_SHIFT    16
@@ -104,6 +108,7 @@
 s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw,
                              ixgbe_link_speed *speed,
                              bool *link_up);
+s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw);
 s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw,
                                        u16 *firmware_version);
 s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw,
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_sriov.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_sriov.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_sriov.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_sriov.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -110,6 +110,33 @@
 	return adapter->hw.mac.ops.set_vfta(&adapter->hw, vid, vf, (bool)add);
 }
 
+void ixgbe_set_vf_lpe(struct ixgbe_adapter *adapter, u32 *msgbuf)
+{
+	struct ixgbe_hw *hw = &adapter->hw;
+	int new_mtu = msgbuf[1];
+	u32 max_frs;
+	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+
+	/* Only X540 supports jumbo frames in IOV mode */
+	if (adapter->hw.mac.type != ixgbe_mac_X540)
+		return;
+
+	/* MTU < 68 is an error and causes problems on some kernels */
+	if ((new_mtu < 68) || (max_frame > IXGBE_MAX_JUMBO_FRAME_SIZE)) {
+		e_err(drv, "VF mtu %d out of range\n", new_mtu);
+		return;
+	}
+
+	max_frs = (IXGBE_READ_REG(hw, IXGBE_MAXFRS) &
+		   IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
+	if (max_frs < new_mtu) {
+		max_frs = new_mtu << IXGBE_MHADD_MFS_SHIFT;
+		IXGBE_WRITE_REG(hw, IXGBE_MAXFRS, max_frs);
+	}
+
+	e_info(hw, "VF requests change max MTU to %d\n", new_mtu);
+}
+
 static void ixgbe_set_vmolr(struct ixgbe_hw *hw, u32 vf, bool aupe)
 {
 	u32 vmolr = IXGBE_READ_REG(hw, IXGBE_VMOLR(vf));
@@ -302,7 +329,7 @@
 		                                 hash_list, vf);
 		break;
 	case IXGBE_VF_SET_LPE:
-		WARN_ON((msgbuf[0] & 0xFFFF) == IXGBE_VF_SET_LPE);
+		ixgbe_set_vf_lpe(adapter, msgbuf);
 		break;
 	case IXGBE_VF_SET_VLAN:
 		add = (msgbuf[0] & IXGBE_VT_MSGINFO_MASK)
@@ -451,9 +478,90 @@
        return err;
 }
 
+static int ixgbe_link_mbps(int internal_link_speed)
+{
+	switch (internal_link_speed) {
+	case IXGBE_LINK_SPEED_100_FULL:
+		return 100;
+	case IXGBE_LINK_SPEED_1GB_FULL:
+		return 1000;
+	case IXGBE_LINK_SPEED_10GB_FULL:
+		return 10000;
+	default:
+		return 0;
+	}
+}
+
+static void ixgbe_set_vf_rate_limit(struct ixgbe_hw *hw, int vf, int tx_rate,
+				    int link_speed)
+{
+	int rf_dec, rf_int;
+	u32 bcnrc_val;
+
+	if (tx_rate != 0) {
+		/* Calculate the rate factor values to set */
+		rf_int = link_speed / tx_rate;
+		rf_dec = (link_speed - (rf_int * tx_rate));
+		rf_dec = (rf_dec * (1<<IXGBE_RTTBCNRC_RF_INT_SHIFT)) / tx_rate;
+
+		bcnrc_val = IXGBE_RTTBCNRC_RS_ENA;
+		bcnrc_val |= ((rf_int<<IXGBE_RTTBCNRC_RF_INT_SHIFT) &
+		               IXGBE_RTTBCNRC_RF_INT_MASK);
+		bcnrc_val |= (rf_dec & IXGBE_RTTBCNRC_RF_DEC_MASK);
+	} else {
+		bcnrc_val = 0;
+	}
+
+	IXGBE_WRITE_REG(hw, IXGBE_RTTDQSEL, 2*vf); /* vf Y uses queue 2*Y */
+	IXGBE_WRITE_REG(hw, IXGBE_RTTBCNRC, bcnrc_val);
+}
+
+void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter)
+{
+	int actual_link_speed, i;
+	bool reset_rate = false;
+
+	/* VF Tx rate limit was not set */
+	if (adapter->vf_rate_link_speed == 0)
+		return;
+
+	actual_link_speed = ixgbe_link_mbps(adapter->link_speed);
+	if (actual_link_speed != adapter->vf_rate_link_speed) {
+		reset_rate = true;
+		adapter->vf_rate_link_speed = 0;
+		dev_info(&adapter->pdev->dev,
+		         "Link speed has been changed. VF Transmit rate "
+		         "is disabled\n");
+	}
+
+	for (i = 0; i < adapter->num_vfs; i++) {
+		if (reset_rate)
+			adapter->vfinfo[i].tx_rate = 0;
+
+		ixgbe_set_vf_rate_limit(&adapter->hw, i,
+					adapter->vfinfo[i].tx_rate,
+					actual_link_speed);
+	}
+}
+
 int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate)
 {
-	return -EOPNOTSUPP;
+	struct ixgbe_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
+	int actual_link_speed;
+
+	actual_link_speed = ixgbe_link_mbps(adapter->link_speed);
+	if ((vf >= adapter->num_vfs) || (!adapter->link_up) ||
+	    (tx_rate > actual_link_speed) || (actual_link_speed != 10000) ||
+	    ((tx_rate != 0) && (tx_rate <= 10)))
+	    /* rate limit cannot be set to 10Mb or less in 10Gb adapters */
+		return -EINVAL;
+
+	adapter->vf_rate_link_speed = actual_link_speed;
+	adapter->vfinfo[vf].tx_rate = (u16)tx_rate;
+	ixgbe_set_vf_rate_limit(hw, vf, tx_rate, actual_link_speed);
+
+	return 0;
 }
 
 int ixgbe_ndo_get_vf_config(struct net_device *netdev,
@@ -464,7 +572,7 @@
 		return -EINVAL;
 	ivi->vf = vf;
 	memcpy(&ivi->mac, adapter->vfinfo[vf].vf_mac_addresses, ETH_ALEN);
-	ivi->tx_rate = 0;
+	ivi->tx_rate = adapter->vfinfo[vf].tx_rate;
 	ivi->vlan = adapter->vfinfo[vf].pf_vlan;
 	ivi->qos = adapter->vfinfo[vf].pf_qos;
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_sriov.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_sriov.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_sriov.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_sriov.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -40,6 +40,7 @@
 int ixgbe_ndo_set_vf_bw(struct net_device *netdev, int vf, int tx_rate);
 int ixgbe_ndo_get_vf_config(struct net_device *netdev,
 			    int vf, struct ifla_vf_info *ivi);
+void ixgbe_check_vf_rate_limit(struct ixgbe_adapter *adapter);
 
 #endif /* _IXGBE_SRIOV_H_ */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_type.h linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_type.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_type.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_type.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -91,7 +91,7 @@
 
 /* General Receive Control */
 #define IXGBE_GRC_MNG  0x00000001 /* Manageability Enable */
-#define IXGBE_GRC_APME 0x00000002 /* Advanced Power Management Enable */
+#define IXGBE_GRC_APME 0x00000002 /* APM enabled in EEPROM */
 
 #define IXGBE_VPDDIAG0  0x10204
 #define IXGBE_VPDDIAG1  0x10208
@@ -342,7 +342,7 @@
 /* Wake Up Control */
 #define IXGBE_WUC_PME_EN     0x00000002 /* PME Enable */
 #define IXGBE_WUC_PME_STATUS 0x00000004 /* PME Status */
-#define IXGBE_WUC_ADVD3WUC   0x00000010 /* D3Cold wake up cap. enable*/
+#define IXGBE_WUC_WKEN       0x00000010 /* Enable PE_WAKE_N pin assertion  */
 
 /* Wake Up Filter Control */
 #define IXGBE_WUFC_LNKC 0x00000001 /* Link Status Change Wakeup Enable */
@@ -533,6 +533,12 @@
 #define IXGBE_RTTDTECC    0x04990
 #define IXGBE_RTTDTECC_NO_BCN   0x00000100
 #define IXGBE_RTTBCNRC    0x04984
+#define IXGBE_RTTBCNRC_RS_ENA	0x80000000
+#define IXGBE_RTTBCNRC_RF_DEC_MASK	0x00003FFF
+#define IXGBE_RTTBCNRC_RF_INT_SHIFT	14
+#define IXGBE_RTTBCNRC_RF_INT_MASK	\
+	(IXGBE_RTTBCNRC_RF_DEC_MASK << IXGBE_RTTBCNRC_RF_INT_SHIFT)
+
 
 /* FCoE registers */
 #define IXGBE_FCPTRL    0x02410 /* FC User Desc. PTR Low */
@@ -659,6 +665,8 @@
 #define IXGBE_QPTC(_i) (0x06030 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QBRC(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
 #define IXGBE_QBTC(_i) (0x06034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBRC_L(_i) (0x01034 + ((_i) * 0x40)) /* 16 of these */
+#define IXGBE_QBRC_H(_i) (0x01038 + ((_i) * 0x40)) /* 16 of these */
 #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 */
@@ -669,6 +677,11 @@
 #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 */
+#define IXGBE_PCRC8ECL  0x0E810
+#define IXGBE_PCRC8ECH  0x0E811
+#define IXGBE_PCRC8ECH_MASK     0x1F
+#define IXGBE_LDPCECL   0x0E820
+#define IXGBE_LDPCECH   0x0E821
 
 /* Management */
 #define IXGBE_MAVTV(_i) (0x05010 + ((_i) * 4)) /* 8 of these (0-7) */
@@ -1002,6 +1015,13 @@
 #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_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */
+#define IXGBE_MII_AUTONEG_XNP_TX_REG             0x17   /* 1G XNP Transmit */
+#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX      0x4000 /* full duplex, bit:14*/
+#define IXGBE_MII_1GBASE_T_ADVERTISE             0x8000 /* full duplex, bit:15*/
+#define IXGBE_MII_AUTONEG_REG                    0x0
+
 #define IXGBE_PHY_REVISION_MASK        0xFFFFFFF0
 #define IXGBE_MAX_PHY_ADDR             32
 
@@ -1614,6 +1634,8 @@
 #define IXGBE_ALT_SAN_MAC_ADDR_CAPS_ALTWWN  0x1 /* Alt. WWN base exists */
 
 /* PCI Bus Info */
+#define IXGBE_PCI_DEVICE_STATUS   0xAA
+#define IXGBE_PCI_DEVICE_STATUS_TRANSACTION_PENDING   0x0020
 #define IXGBE_PCI_LINK_STATUS     0xB2
 #define IXGBE_PCI_DEVICE_CONTROL2 0xC8
 #define IXGBE_PCI_LINK_WIDTH      0x3F0
@@ -1680,6 +1702,8 @@
 #define IXGBE_RXCTRL_DMBYPS     0x00000002  /* Descriptor Monitor Bypass */
 #define IXGBE_RXDCTL_ENABLE     0x02000000  /* Enable specific Rx Queue */
 #define IXGBE_RXDCTL_VME        0x40000000  /* VLAN mode enable */
+#define IXGBE_RXDCTL_RLPMLMASK  0x00003FFF  /* Only supported on the X540 */
+#define IXGBE_RXDCTL_RLPML_EN   0x00008000
 
 #define IXGBE_FCTRL_SBP 0x00000002 /* Store Bad Packet */
 #define IXGBE_FCTRL_MPE 0x00000100 /* Multicast Promiscuous Ena*/
@@ -2240,6 +2264,7 @@
 
 enum ixgbe_phy_type {
 	ixgbe_phy_unknown = 0,
+	ixgbe_phy_none,
 	ixgbe_phy_tn,
 	ixgbe_phy_aq,
 	ixgbe_phy_cu_unknown,
@@ -2328,32 +2353,31 @@
 /* PCI bus speeds */
 enum ixgbe_bus_speed {
 	ixgbe_bus_speed_unknown = 0,
-	ixgbe_bus_speed_33,
-	ixgbe_bus_speed_66,
-	ixgbe_bus_speed_100,
-	ixgbe_bus_speed_120,
-	ixgbe_bus_speed_133,
-	ixgbe_bus_speed_2500,
-	ixgbe_bus_speed_5000,
+	ixgbe_bus_speed_33      = 33,
+	ixgbe_bus_speed_66      = 66,
+	ixgbe_bus_speed_100     = 100,
+	ixgbe_bus_speed_120     = 120,
+	ixgbe_bus_speed_133     = 133,
+	ixgbe_bus_speed_2500    = 2500,
+	ixgbe_bus_speed_5000    = 5000,
 	ixgbe_bus_speed_reserved
 };
 
 /* PCI bus widths */
 enum ixgbe_bus_width {
 	ixgbe_bus_width_unknown = 0,
-	ixgbe_bus_width_pcie_x1,
-	ixgbe_bus_width_pcie_x2,
+	ixgbe_bus_width_pcie_x1 = 1,
+	ixgbe_bus_width_pcie_x2 = 2,
 	ixgbe_bus_width_pcie_x4 = 4,
 	ixgbe_bus_width_pcie_x8 = 8,
-	ixgbe_bus_width_32,
-	ixgbe_bus_width_64,
+	ixgbe_bus_width_32      = 32,
+	ixgbe_bus_width_64      = 64,
 	ixgbe_bus_width_reserved
 };
 
 struct ixgbe_addr_filter_info {
 	u32 num_mc_addrs;
 	u32 rar_used_count;
-	u32 mc_addr_in_rar_count;
 	u32 mta_in_use;
 	u32 overflow_promisc;
 	bool uc_set_promisc;
@@ -2491,6 +2515,8 @@
 	s32 (*write_analog_reg8)(struct ixgbe_hw*, u32, u8);
 	s32 (*setup_sfp)(struct ixgbe_hw *);
 	s32 (*enable_rx_dma)(struct ixgbe_hw *, u32);
+	s32 (*acquire_swfw_sync)(struct ixgbe_hw *, u16);
+	void (*release_swfw_sync)(struct ixgbe_hw *, u16);
 
 	/* Link */
 	void (*disable_tx_laser)(struct ixgbe_hw *);
@@ -2513,7 +2539,6 @@
 	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 *, struct net_device *);
 	s32 (*update_mc_addr_list)(struct ixgbe_hw *, struct net_device *);
 	s32 (*enable_mc)(struct ixgbe_hw *);
 	s32 (*disable_mc)(struct ixgbe_hw *);
@@ -2554,6 +2579,7 @@
 	u16                             address_bits;
 };
 
+#define IXGBE_FLAGS_DOUBLE_RESET_REQUIRED	0x01
 struct ixgbe_mac_info {
 	struct ixgbe_mac_operations     ops;
 	enum ixgbe_mac_type             type;
@@ -2564,6 +2590,8 @@
 	u16                             wwnn_prefix;
 	/* prefix for World Wide Port Name (WWPN) */
 	u16                             wwpn_prefix;
+#define IXGBE_MAX_MTA			128
+	u32				mta_shadow[IXGBE_MAX_MTA];
 	s32                             mc_filter_type;
 	u32                             mcft_size;
 	u32                             vft_size;
@@ -2576,6 +2604,7 @@
 	u32                             orig_autoc2;
 	bool                            orig_link_settings_stored;
 	bool                            autotry_restart;
+	u8                              flags;
 };
 
 struct ixgbe_phy_info {
@@ -2682,7 +2711,9 @@
 #define IXGBE_ERR_EEPROM_VERSION                -24
 #define IXGBE_ERR_NO_SPACE                      -25
 #define IXGBE_ERR_OVERTEMP                      -26
-#define IXGBE_ERR_RAR_INDEX                     -27
+#define IXGBE_ERR_FC_NOT_NEGOTIATED             -27
+#define IXGBE_ERR_FC_NOT_SUPPORTED              -28
+#define IXGBE_ERR_FLOW_CONTROL                  -29
 #define IXGBE_ERR_SFP_SETUP_NOT_COMPLETE        -30
 #define IXGBE_ERR_PBA_SECTION                   -31
 #define IXGBE_ERR_INVALID_ARGUMENT              -32
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_x540.c linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_x540.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbe/ixgbe_x540.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbe/ixgbe_x540.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************************
 
   Intel 10 Gigabit PCI Express Linux driver
-  Copyright(c) 1999 - 2010 Intel Corporation.
+  Copyright(c) 1999 - 2011 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,
@@ -31,7 +31,6 @@
 
 #include "ixgbe.h"
 #include "ixgbe_phy.h"
-//#include "ixgbe_mbx.h"
 
 #define IXGBE_X540_MAX_TX_QUEUES 128
 #define IXGBE_X540_MAX_RX_QUEUES 128
@@ -110,12 +109,9 @@
 	 * Prevent the PCI-E bus from from hanging by disabling PCI-E master
 	 * access and verify no pending requests before reset
 	 */
-	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");
-	}
+	ixgbe_disable_pcie_master(hw);
 
+mac_reset_top:
 	/*
 	 * Issue global reset to the MAC.  Needs to be SW reset if link is up.
 	 * If link reset is used when link is up, it might reset the PHY when
@@ -148,6 +144,19 @@
 		hw_dbg(hw, "Reset polling failed to complete.\n");
 	}
 
+	/*
+	 * Double resets are required for recovery from certain error
+	 * conditions.  Between resets, it is necessary to stall to allow time
+	 * for any pending HW events to complete.  We use 1usec since that is
+	 * what is needed for ixgbe_disable_pcie_master().  The second reset
+	 * then clears out any effects of those events.
+	 */
+	if (hw->mac.flags & IXGBE_FLAGS_DOUBLE_RESET_REQUIRED) {
+		hw->mac.flags &= ~IXGBE_FLAGS_DOUBLE_RESET_REQUIRED;
+		udelay(1);
+		goto mac_reset_top;
+	}
+
 	/* Clear PF Reset Done bit so PF/VF Mail Ops can work */
 	ctrl_ext = IXGBE_READ_REG(hw, IXGBE_CTRL_EXT);
 	ctrl_ext |= IXGBE_CTRL_EXT_PFRSTD;
@@ -191,7 +200,7 @@
 	 * 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.num_rar_entries = IXGBE_X540_MAX_TX_QUEUES;
 	hw->mac.ops.init_rx_addrs(hw);
 
 	/* Store the permanent mac address */
@@ -242,8 +251,11 @@
 }
 
 /**
- * ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
- * @hw: pointer to hardware structure
+ *  ixgbe_init_eeprom_params_X540 - Initialize EEPROM params
+ *  @hw: pointer to hardware structure
+ *
+ *  Initializes the EEPROM parameters ixgbe_eeprom_info within the
+ *  ixgbe_hw struct in order to set up EEPROM access.
  **/
 static s32 ixgbe_init_eeprom_params_X540(struct ixgbe_hw *hw)
 {
@@ -262,7 +274,7 @@
 		                          IXGBE_EEPROM_WORD_SIZE_SHIFT);
 
 		hw_dbg(hw, "Eeprom params: type = %d, size = %d\n",
-		        eeprom->type, eeprom->word_size);
+		       eeprom->type, eeprom->word_size);
 	}
 
 	return 0;
@@ -278,7 +290,7 @@
 {
 	s32 status;
 
-	if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM) == 0)
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0)
 		status = ixgbe_read_eerd_generic(hw, offset, data);
 	else
 		status = IXGBE_ERR_SWFW_SYNC;
@@ -311,7 +323,7 @@
 	       (data << IXGBE_EEPROM_RW_REG_DATA) |
 	       IXGBE_EEPROM_RW_REG_START;
 
-	if (ixgbe_acquire_swfw_sync_X540(hw, IXGBE_GSSR_EEP_SM) == 0) {
+	if (hw->mac.ops.acquire_swfw_sync(hw, IXGBE_GSSR_EEP_SM) == 0) {
 		status = ixgbe_poll_eerd_eewr_done(hw, IXGBE_NVM_POLL_WRITE);
 		if (status != 0) {
 			hw_dbg(hw, "Eeprom write EEWR timed out\n");
@@ -561,7 +573,7 @@
  * @hw: pointer to hardware structure
  * @mask: Mask to specify which semaphore to release
  *
- * Releases the SWFW semaphore throught the SW_FW_SYNC register
+ * Releases the SWFW semaphore through the SW_FW_SYNC register
  * for the specified function (CSR, PHY0, PHY1, EVM, Flash)
  **/
 static void ixgbe_release_swfw_sync_X540(struct ixgbe_hw *hw, u16 mask)
@@ -676,7 +688,6 @@
 	.set_vmdq               = &ixgbe_set_vmdq_generic,
 	.clear_vmdq             = &ixgbe_clear_vmdq_generic,
 	.init_rx_addrs          = &ixgbe_init_rx_addrs_generic,
-	.update_uc_addr_list    = &ixgbe_update_uc_addr_list_generic,
 	.update_mc_addr_list    = &ixgbe_update_mc_addr_list_generic,
 	.enable_mc              = &ixgbe_enable_mc_generic,
 	.disable_mc             = &ixgbe_disable_mc_generic,
@@ -687,6 +698,8 @@
 	.setup_sfp              = NULL,
 	.set_mac_anti_spoofing  = &ixgbe_set_mac_anti_spoofing,
 	.set_vlan_anti_spoofing = &ixgbe_set_vlan_anti_spoofing,
+	.acquire_swfw_sync      = &ixgbe_acquire_swfw_sync_X540,
+	.release_swfw_sync      = &ixgbe_release_swfw_sync_X540,
 };
 
 static struct ixgbe_eeprom_operations eeprom_ops_X540 = {
@@ -702,7 +715,7 @@
 	.identify               = &ixgbe_identify_phy_generic,
 	.identify_sfp           = &ixgbe_identify_sfp_module_generic,
 	.init			= NULL,
-	.reset                  = &ixgbe_reset_phy_generic,
+	.reset                  = NULL,
 	.read_reg               = &ixgbe_read_phy_reg_generic,
 	.write_reg              = &ixgbe_write_phy_reg_generic,
 	.setup_link             = &ixgbe_setup_phy_link_generic,
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbevf/defines.h linux-libre-2.6.39-gnu/drivers/net/ixgbevf/defines.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbevf/defines.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbevf/defines.h	2011-05-19 00:06:34.000000000 -0400
@@ -65,6 +65,8 @@
 #define IXGBE_RXCTRL_DMBYPS     0x00000002  /* Descriptor Monitor Bypass */
 #define IXGBE_RXDCTL_ENABLE     0x02000000  /* Enable specific Rx Queue */
 #define IXGBE_RXDCTL_VME        0x40000000  /* VLAN mode enable */
+#define IXGBE_RXDCTL_RLPMLMASK  0x00003FFF  /* Only supported on the X540 */
+#define IXGBE_RXDCTL_RLPML_EN   0x00008000
 
 /* DCA Control */
 #define IXGBE_DCA_TXCTRL_TX_WB_RO_EN (1 << 11) /* Tx Desc writeback RO bit */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbevf/ethtool.c linux-libre-2.6.39-gnu/drivers/net/ixgbevf/ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbevf/ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbevf/ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -172,7 +172,7 @@
 	"IXGBE_VFSTATUS",
 	"IXGBE_VFLINKS",
 	"IXGBE_VFRXMEMWRAP",
-	"IXGBE_VFRTIMER",
+	"IXGBE_VFFRTIMER",
 	"IXGBE_VTEICR",
 	"IXGBE_VTEICS",
 	"IXGBE_VTEIMS",
@@ -240,7 +240,7 @@
 	regs_buff[1] = IXGBE_READ_REG(hw, IXGBE_VFSTATUS);
 	regs_buff[2] = IXGBE_READ_REG(hw, IXGBE_VFLINKS);
 	regs_buff[3] = IXGBE_READ_REG(hw, IXGBE_VFRXMEMWRAP);
-	regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFRTIMER);
+	regs_buff[4] = IXGBE_READ_REG(hw, IXGBE_VFFRTIMER);
 
 	/* Interrupt */
 	/* don't read EICR because it can clear interrupt causes, instead
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbevf/ixgbevf.h linux-libre-2.6.39-gnu/drivers/net/ixgbevf/ixgbevf.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbevf/ixgbevf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbevf/ixgbevf.h	2011-05-19 00:06:34.000000000 -0400
@@ -207,7 +207,6 @@
 	u64 hw_tso_ctxt;
 	u64 hw_tso6_ctxt;
 	u32 tx_timeout_count;
-	bool detect_tx_hung;
 
 	/* RX */
 	struct ixgbevf_ring *rx_ring;	/* One per active queue */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbevf/ixgbevf_main.c linux-libre-2.6.39-gnu/drivers/net/ixgbevf/ixgbevf_main.c
--- linux-libre-2.6.38-gnu/drivers/net/ixgbevf/ixgbevf_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbevf/ixgbevf_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,9 +49,9 @@
 
 char ixgbevf_driver_name[] = "ixgbevf";
 static const char ixgbevf_driver_string[] =
-	"Intel(R) 82599 Virtual Function";
+	"Intel(R) 10 Gigabit PCI Express Virtual Function Network Driver";
 
-#define DRV_VERSION "1.0.19-k0"
+#define DRV_VERSION "2.0.0-k2"
 const char ixgbevf_driver_version[] = DRV_VERSION;
 static char ixgbevf_copyright[] =
 	"Copyright (c) 2009 - 2010 Intel Corporation.";
@@ -107,7 +107,7 @@
 }
 
 /*
- * ixgbe_set_ivar - set the IVAR registers, mapping interrupt causes to vectors
+ * ixgbevf_set_ivar - set IVAR registers - maps interrupt causes to vectors
  * @adapter: pointer to adapter struct
  * @direction: 0 for Rx, 1 for Tx, -1 for other causes
  * @queue: queue to map the corresponding interrupt to
@@ -162,42 +162,6 @@
 	/* tx_buffer_info must be completely set up in the transmit path */
 }
 
-static inline bool ixgbevf_check_tx_hang(struct ixgbevf_adapter *adapter,
-					 struct ixgbevf_ring *tx_ring,
-					 unsigned int eop)
-{
-	struct ixgbe_hw *hw = &adapter->hw;
-	u32 head, tail;
-
-	/* Detect a transmit hang in hardware, this serializes the
-	 * check with the clearing of time_stamp and movement of eop */
-	head = readl(hw->hw_addr + tx_ring->head);
-	tail = readl(hw->hw_addr + tx_ring->tail);
-	adapter->detect_tx_hung = false;
-	if ((head != tail) &&
-	    tx_ring->tx_buffer_info[eop].time_stamp &&
-	    time_after(jiffies, tx_ring->tx_buffer_info[eop].time_stamp + HZ)) {
-		/* detected Tx unit hang */
-		union ixgbe_adv_tx_desc *tx_desc;
-		tx_desc = IXGBE_TX_DESC_ADV(*tx_ring, eop);
-		printk(KERN_ERR "Detected Tx Unit Hang\n"
-		       "  Tx Queue             <%d>\n"
-		       "  TDH, TDT             <%x>, <%x>\n"
-		       "  next_to_use          <%x>\n"
-		       "  next_to_clean        <%x>\n"
-		       "tx_buffer_info[next_to_clean]\n"
-		       "  time_stamp           <%lx>\n"
-		       "  jiffies              <%lx>\n",
-		       tx_ring->queue_index,
-		       head, tail,
-		       tx_ring->next_to_use, eop,
-		       tx_ring->tx_buffer_info[eop].time_stamp, jiffies);
-		return true;
-	}
-
-	return false;
-}
-
 #define IXGBE_MAX_TXD_PWR	14
 #define IXGBE_MAX_DATA_PER_TXD	(1 << IXGBE_MAX_TXD_PWR)
 
@@ -293,16 +257,6 @@
 #endif
 	}
 
-	if (adapter->detect_tx_hung) {
-		if (ixgbevf_check_tx_hang(adapter, tx_ring, i)) {
-			/* schedule immediate reset if we believe we hung */
-			printk(KERN_INFO
-			       "tx hang %d detected, resetting adapter\n",
-			       adapter->tx_timeout_count + 1);
-			ixgbevf_tx_timeout(adapter->netdev);
-		}
-	}
-
 	/* re-arm the interrupt */
 	if ((count >= tx_ring->work_limit) &&
 	    (!test_bit(__IXGBEVF_DOWN, &adapter->state))) {
@@ -334,7 +288,6 @@
 	struct ixgbevf_adapter *adapter = q_vector->adapter;
 	bool is_vlan = (status & IXGBE_RXD_STAT_VP);
 	u16 tag = le16_to_cpu(rx_desc->wb.upper.vlan);
-	int ret;
 
 	if (!(adapter->flags & IXGBE_FLAG_IN_NETPOLL)) {
 		if (adapter->vlgrp && is_vlan)
@@ -345,9 +298,9 @@
 			napi_gro_receive(&q_vector->napi, skb);
 	} else {
 		if (adapter->vlgrp && is_vlan)
-			ret = vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
+			vlan_hwaccel_rx(skb, adapter->vlgrp, tag);
 		else
-			ret = netif_rx(skb);
+			netif_rx(skb);
 	}
 }
 
@@ -1017,7 +970,7 @@
 }
 
 /**
- * ixgbe_msix_clean_rx - single unshared vector rx clean (all queues)
+ * ixgbevf_msix_clean_rx - single unshared vector rx clean (all queues)
  * @irq: unused
  * @data: pointer to our q_vector struct for this interrupt vector
  **/
@@ -1665,6 +1618,11 @@
 		j = adapter->rx_ring[i].reg_idx;
 		rxdctl = IXGBE_READ_REG(hw, IXGBE_VFRXDCTL(j));
 		rxdctl |= IXGBE_RXDCTL_ENABLE;
+		if (hw->mac.type == ixgbe_mac_X540_vf) {
+			rxdctl &= ~IXGBE_RXDCTL_RLPMLMASK;
+			rxdctl |= ((netdev->mtu + ETH_HLEN + ETH_FCS_LEN) |
+				   IXGBE_RXDCTL_RLPML_EN);
+		}
 		IXGBE_WRITE_REG(hw, IXGBE_VFRXDCTL(j), rxdctl);
 		ixgbevf_rx_desc_queue_enable(adapter, i);
 	}
@@ -1967,7 +1925,7 @@
 }
 
 /*
- * ixgbe_set_num_queues: Allocate queues for device, feature dependant
+ * ixgbevf_set_num_queues: Allocate queues for device, feature dependent
  * @adapter: board private structure to initialize
  *
  * This is the top level queue allocation routine.  The order here is very
@@ -2216,7 +2174,7 @@
 
 	hw->vendor_id = pdev->vendor;
 	hw->device_id = pdev->device;
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &hw->revision_id);
+	hw->revision_id = pdev->revision;
 	hw->subsystem_vendor_id = pdev->subsystem_vendor;
 	hw->subsystem_device_id = pdev->subsystem_device;
 
@@ -2410,9 +2368,6 @@
 			       10 : 1);
 			netif_carrier_on(netdev);
 			netif_tx_wake_all_queues(netdev);
-		} else {
-			/* Force detection of hung controller */
-			adapter->detect_tx_hung = true;
 		}
 	} else {
 		adapter->link_up = false;
@@ -2427,9 +2382,6 @@
 	ixgbevf_update_stats(adapter);
 
 pf_has_reset:
-	/* Force detection of hung controller every watchdog period */
-	adapter->detect_tx_hung = true;
-
 	/* Reset the timer */
 	if (!test_bit(__IXGBEVF_DOWN, &adapter->state))
 		mod_timer(&adapter->watchdog_timer,
@@ -3217,10 +3169,16 @@
 static int ixgbevf_change_mtu(struct net_device *netdev, int new_mtu)
 {
 	struct ixgbevf_adapter *adapter = netdev_priv(netdev);
+	struct ixgbe_hw *hw = &adapter->hw;
 	int max_frame = new_mtu + ETH_HLEN + ETH_FCS_LEN;
+	int max_possible_frame = MAXIMUM_ETHERNET_VLAN_SIZE;
+	u32 msg[2];
+
+	if (adapter->hw.mac.type == ixgbe_mac_X540_vf)
+		max_possible_frame = IXGBE_MAX_JUMBO_FRAME_SIZE;
 
 	/* MTU < 68 is an error and causes problems on some kernels */
-	if ((new_mtu < 68) || (max_frame > MAXIMUM_ETHERNET_VLAN_SIZE))
+	if ((new_mtu < 68) || (max_frame > max_possible_frame))
 		return -EINVAL;
 
 	hw_dbg(&adapter->hw, "changing MTU from %d to %d\n",
@@ -3228,6 +3186,10 @@
 	/* must set new MTU before calling down or up */
 	netdev->mtu = new_mtu;
 
+	msg[0] = IXGBE_VF_SET_LPE;
+	msg[1] = max_frame;
+	hw->mbx.ops.write_posted(hw, msg, 2);
+
 	if (netif_running(netdev))
 		ixgbevf_reinit_locked(adapter);
 
@@ -3272,8 +3234,6 @@
 
 static void ixgbevf_assign_netdev_ops(struct net_device *dev)
 {
-	struct ixgbevf_adapter *adapter;
-	adapter = netdev_priv(dev);
 	dev->netdev_ops = &ixgbe_netdev_ops;
 	ixgbevf_set_ethtool_ops(dev);
 	dev->watchdog_timeo = 5 * HZ;
@@ -3519,9 +3479,9 @@
 };
 
 /**
- * ixgbe_init_module - Driver Registration Routine
+ * ixgbevf_init_module - Driver Registration Routine
  *
- * ixgbe_init_module is the first routine called when the driver is
+ * ixgbevf_init_module is the first routine called when the driver is
  * loaded. All it does is register with the PCI subsystem.
  **/
 static int __init ixgbevf_init_module(void)
@@ -3539,9 +3499,9 @@
 module_init(ixgbevf_init_module);
 
 /**
- * ixgbe_exit_module - Driver Exit Cleanup Routine
+ * ixgbevf_exit_module - Driver Exit Cleanup Routine
  *
- * ixgbe_exit_module is called just before the driver is removed
+ * ixgbevf_exit_module is called just before the driver is removed
  * from memory.
  **/
 static void __exit ixgbevf_exit_module(void)
@@ -3551,7 +3511,7 @@
 
 #ifdef DEBUG
 /**
- * ixgbe_get_hw_dev_name - return device name string
+ * ixgbevf_get_hw_dev_name - return device name string
  * used by hardware layer to print debugging information
  **/
 char *ixgbevf_get_hw_dev_name(struct ixgbe_hw *hw)
diff -druN linux-libre-2.6.38-gnu/drivers/net/ixgbevf/regs.h linux-libre-2.6.39-gnu/drivers/net/ixgbevf/regs.h
--- linux-libre-2.6.38-gnu/drivers/net/ixgbevf/regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ixgbevf/regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #define IXGBE_VFCTRL           0x00000
 #define IXGBE_VFSTATUS         0x00008
 #define IXGBE_VFLINKS          0x00010
-#define IXGBE_VFRTIMER         0x00048
+#define IXGBE_VFFRTIMER        0x00048
 #define IXGBE_VFRXMEMWRAP      0x03190
 #define IXGBE_VTEICR           0x00100
 #define IXGBE_VTEICS           0x00104
diff -druN linux-libre-2.6.38-gnu/drivers/net/jme.c linux-libre-2.6.39-gnu/drivers/net/jme.c
--- linux-libre-2.6.38-gnu/drivers/net/jme.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/jme.c	2011-05-19 00:06:34.000000000 -0400
@@ -161,6 +161,67 @@
 }
 
 static inline void
+jme_mac_rxclk_off(struct jme_adapter *jme)
+{
+	jme->reg_gpreg1 |= GPREG1_RXCLKOFF;
+	jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1);
+}
+
+static inline void
+jme_mac_rxclk_on(struct jme_adapter *jme)
+{
+	jme->reg_gpreg1 &= ~GPREG1_RXCLKOFF;
+	jwrite32f(jme, JME_GPREG1, jme->reg_gpreg1);
+}
+
+static inline void
+jme_mac_txclk_off(struct jme_adapter *jme)
+{
+	jme->reg_ghc &= ~(GHC_TO_CLK_SRC | GHC_TXMAC_CLK_SRC);
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_mac_txclk_on(struct jme_adapter *jme)
+{
+	u32 speed = jme->reg_ghc & GHC_SPEED;
+	if (speed == GHC_SPEED_1000M)
+		jme->reg_ghc |= GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
+	else
+		jme->reg_ghc |= GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_reset_ghc_speed(struct jme_adapter *jme)
+{
+	jme->reg_ghc &= ~(GHC_SPEED | GHC_DPX);
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_reset_250A2_workaround(struct jme_adapter *jme)
+{
+	jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH |
+			     GPREG1_RSSPATCH);
+	jwrite32(jme, JME_GPREG1, jme->reg_gpreg1);
+}
+
+static inline void
+jme_assert_ghc_reset(struct jme_adapter *jme)
+{
+	jme->reg_ghc |= GHC_SWRST;
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
+jme_clear_ghc_reset(struct jme_adapter *jme)
+{
+	jme->reg_ghc &= ~GHC_SWRST;
+	jwrite32f(jme, JME_GHC, jme->reg_ghc);
+}
+
+static inline void
 jme_reset_mac_processor(struct jme_adapter *jme)
 {
 	static const u32 mask[WAKEUP_FRAME_MASK_DWNR] = {0, 0, 0, 0};
@@ -168,9 +229,24 @@
 	u32 gpreg0;
 	int i;
 
-	jwrite32(jme, JME_GHC, jme->reg_ghc | GHC_SWRST);
-	udelay(2);
-	jwrite32(jme, JME_GHC, jme->reg_ghc);
+	jme_reset_ghc_speed(jme);
+	jme_reset_250A2_workaround(jme);
+
+	jme_mac_rxclk_on(jme);
+	jme_mac_txclk_on(jme);
+	udelay(1);
+	jme_assert_ghc_reset(jme);
+	udelay(1);
+	jme_mac_rxclk_off(jme);
+	jme_mac_txclk_off(jme);
+	udelay(1);
+	jme_clear_ghc_reset(jme);
+	udelay(1);
+	jme_mac_rxclk_on(jme);
+	jme_mac_txclk_on(jme);
+	udelay(1);
+	jme_mac_rxclk_off(jme);
+	jme_mac_txclk_off(jme);
 
 	jwrite32(jme, JME_RXDBA_LO, 0x00000000);
 	jwrite32(jme, JME_RXDBA_HI, 0x00000000);
@@ -190,14 +266,6 @@
 	else
 		gpreg0 = GPREG0_DEFAULT;
 	jwrite32(jme, JME_GPREG0, gpreg0);
-	jwrite32(jme, JME_GPREG1, GPREG1_DEFAULT);
-}
-
-static inline void
-jme_reset_ghc_speed(struct jme_adapter *jme)
-{
-	jme->reg_ghc &= ~(GHC_SPEED_1000M | GHC_DPX);
-	jwrite32(jme, JME_GHC, jme->reg_ghc);
 }
 
 static inline void
@@ -205,7 +273,7 @@
 {
 	jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
 	pci_set_power_state(jme->pdev, PCI_D0);
-	pci_enable_wake(jme->pdev, PCI_D0, false);
+	device_set_wakeup_enable(&jme->pdev->dev, false);
 }
 
 static int
@@ -336,13 +404,13 @@
 }
 
 static inline void
-jme_set_phyfifoa(struct jme_adapter *jme)
+jme_set_phyfifo_5level(struct jme_adapter *jme)
 {
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0004);
 }
 
 static inline void
-jme_set_phyfifob(struct jme_adapter *jme)
+jme_set_phyfifo_8level(struct jme_adapter *jme)
 {
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, 27, 0x0000);
 }
@@ -351,7 +419,7 @@
 jme_check_link(struct net_device *netdev, int testonly)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
-	u32 phylink, ghc, cnt = JME_SPDRSV_TIMEOUT, bmcr, gpreg1;
+	u32 phylink, cnt = JME_SPDRSV_TIMEOUT, bmcr;
 	char linkmsg[64];
 	int rc = 0;
 
@@ -414,23 +482,21 @@
 
 		jme->phylink = phylink;
 
-		ghc = jme->reg_ghc & ~(GHC_SPEED | GHC_DPX |
-				GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE |
-				GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY);
+		/*
+		 * The speed/duplex setting of jme->reg_ghc already cleared
+		 * by jme_reset_mac_processor()
+		 */
 		switch (phylink & PHY_LINK_SPEED_MASK) {
 		case PHY_LINK_SPEED_10M:
-			ghc |= GHC_SPEED_10M |
-				GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+			jme->reg_ghc |= GHC_SPEED_10M;
 			strcat(linkmsg, "10 Mbps, ");
 			break;
 		case PHY_LINK_SPEED_100M:
-			ghc |= GHC_SPEED_100M |
-				GHC_TO_CLK_PCIE | GHC_TXMAC_CLK_PCIE;
+			jme->reg_ghc |= GHC_SPEED_100M;
 			strcat(linkmsg, "100 Mbps, ");
 			break;
 		case PHY_LINK_SPEED_1000M:
-			ghc |= GHC_SPEED_1000M |
-				GHC_TO_CLK_GPHY | GHC_TXMAC_CLK_GPHY;
+			jme->reg_ghc |= GHC_SPEED_1000M;
 			strcat(linkmsg, "1000 Mbps, ");
 			break;
 		default:
@@ -439,42 +505,40 @@
 
 		if (phylink & PHY_LINK_DUPLEX) {
 			jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT);
-			ghc |= GHC_DPX;
+			jwrite32(jme, JME_TXTRHD, TXTRHD_FULLDUPLEX);
+			jme->reg_ghc |= GHC_DPX;
 		} else {
 			jwrite32(jme, JME_TXMCS, TXMCS_DEFAULT |
 						TXMCS_BACKOFF |
 						TXMCS_CARRIERSENSE |
 						TXMCS_COLLISION);
-			jwrite32(jme, JME_TXTRHD, TXTRHD_TXPEN |
-				((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
-				TXTRHD_TXREN |
-				((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL));
+			jwrite32(jme, JME_TXTRHD, TXTRHD_HALFDUPLEX);
 		}
 
-		gpreg1 = GPREG1_DEFAULT;
+		jwrite32(jme, JME_GHC, jme->reg_ghc);
+
 		if (is_buggy250(jme->pdev->device, jme->chiprev)) {
+			jme->reg_gpreg1 &= ~(GPREG1_HALFMODEPATCH |
+					     GPREG1_RSSPATCH);
 			if (!(phylink & PHY_LINK_DUPLEX))
-				gpreg1 |= GPREG1_HALFMODEPATCH;
+				jme->reg_gpreg1 |= GPREG1_HALFMODEPATCH;
 			switch (phylink & PHY_LINK_SPEED_MASK) {
 			case PHY_LINK_SPEED_10M:
-				jme_set_phyfifoa(jme);
-				gpreg1 |= GPREG1_RSSPATCH;
+				jme_set_phyfifo_8level(jme);
+				jme->reg_gpreg1 |= GPREG1_RSSPATCH;
 				break;
 			case PHY_LINK_SPEED_100M:
-				jme_set_phyfifob(jme);
-				gpreg1 |= GPREG1_RSSPATCH;
+				jme_set_phyfifo_5level(jme);
+				jme->reg_gpreg1 |= GPREG1_RSSPATCH;
 				break;
 			case PHY_LINK_SPEED_1000M:
-				jme_set_phyfifoa(jme);
+				jme_set_phyfifo_8level(jme);
 				break;
 			default:
 				break;
 			}
 		}
-
-		jwrite32(jme, JME_GPREG1, gpreg1);
-		jwrite32(jme, JME_GHC, ghc);
-		jme->reg_ghc = ghc;
+		jwrite32(jme, JME_GPREG1, jme->reg_gpreg1);
 
 		strcat(linkmsg, (phylink & PHY_LINK_DUPLEX) ?
 					"Full-Duplex, " :
@@ -613,10 +677,14 @@
 	 * Enable TX Engine
 	 */
 	wmb();
-	jwrite32(jme, JME_TXCS, jme->reg_txcs |
+	jwrite32f(jme, JME_TXCS, jme->reg_txcs |
 				TXCS_SELECT_QUEUE0 |
 				TXCS_ENABLE);
 
+	/*
+	 * Start clock for TX MAC Processor
+	 */
+	jme_mac_txclk_on(jme);
 }
 
 static inline void
@@ -651,6 +719,11 @@
 
 	if (!i)
 		pr_err("Disable TX engine timeout\n");
+
+	/*
+	 * Stop clock for TX MAC Processor
+	 */
+	jme_mac_txclk_off(jme);
 }
 
 static void
@@ -825,16 +898,22 @@
 	/*
 	 * Setup Unicast Filter
 	 */
+	jme_set_unicastaddr(jme->dev);
 	jme_set_multi(jme->dev);
 
 	/*
 	 * Enable RX Engine
 	 */
 	wmb();
-	jwrite32(jme, JME_RXCS, jme->reg_rxcs |
+	jwrite32f(jme, JME_RXCS, jme->reg_rxcs |
 				RXCS_QUEUESEL_Q0 |
 				RXCS_ENABLE |
 				RXCS_QST);
+
+	/*
+	 * Start clock for RX MAC Processor
+	 */
+	jme_mac_rxclk_on(jme);
 }
 
 static inline void
@@ -871,10 +950,40 @@
 	if (!i)
 		pr_err("Disable RX engine timeout\n");
 
+	/*
+	 * Stop clock for RX MAC Processor
+	 */
+	jme_mac_rxclk_off(jme);
+}
+
+static u16
+jme_udpsum(struct sk_buff *skb)
+{
+	u16 csum = 0xFFFFu;
+
+	if (skb->len < (ETH_HLEN + sizeof(struct iphdr)))
+		return csum;
+	if (skb->protocol != htons(ETH_P_IP))
+		return csum;
+	skb_set_network_header(skb, ETH_HLEN);
+	if ((ip_hdr(skb)->protocol != IPPROTO_UDP) ||
+	    (skb->len < (ETH_HLEN +
+			(ip_hdr(skb)->ihl << 2) +
+			sizeof(struct udphdr)))) {
+		skb_reset_network_header(skb);
+		return csum;
+	}
+	skb_set_transport_header(skb,
+			ETH_HLEN + (ip_hdr(skb)->ihl << 2));
+	csum = udp_hdr(skb)->check;
+	skb_reset_transport_header(skb);
+	skb_reset_network_header(skb);
+
+	return csum;
 }
 
 static int
-jme_rxsum_ok(struct jme_adapter *jme, u16 flags)
+jme_rxsum_ok(struct jme_adapter *jme, u16 flags, struct sk_buff *skb)
 {
 	if (!(flags & (RXWBFLAG_TCPON | RXWBFLAG_UDPON | RXWBFLAG_IPV4)))
 		return false;
@@ -887,7 +996,7 @@
 	}
 
 	if (unlikely((flags & (RXWBFLAG_MF | RXWBFLAG_UDPON | RXWBFLAG_UDPCS))
-			== RXWBFLAG_UDPON)) {
+			== RXWBFLAG_UDPON) && jme_udpsum(skb)) {
 		if (flags & RXWBFLAG_IPV4)
 			netif_err(jme, rx_err, jme->dev, "UDP Checksum error\n");
 		return false;
@@ -935,7 +1044,7 @@
 		skb_put(skb, framesize);
 		skb->protocol = eth_type_trans(skb, jme->dev);
 
-		if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags)))
+		if (jme_rxsum_ok(jme, le16_to_cpu(rxdesc->descwb.flags), skb))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 		else
 			skb_checksum_none_assert(skb);
@@ -1207,7 +1316,6 @@
 	tasklet_disable(&jme->rxempty_task);
 
 	if (netif_carrier_ok(netdev)) {
-		jme_reset_ghc_speed(jme);
 		jme_disable_rx_engine(jme);
 		jme_disable_tx_engine(jme);
 		jme_reset_mac_processor(jme);
@@ -1577,6 +1685,38 @@
 }
 
 static inline void
+jme_new_phy_on(struct jme_adapter *jme)
+{
+	u32 reg;
+
+	reg = jread32(jme, JME_PHY_PWR);
+	reg &= ~(PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW |
+		 PHY_PWR_DWN2 | PHY_PWR_CLKSEL);
+	jwrite32(jme, JME_PHY_PWR, reg);
+
+	pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, &reg);
+	reg &= ~PE1_GPREG0_PBG;
+	reg |= PE1_GPREG0_ENBG;
+	pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
+}
+
+static inline void
+jme_new_phy_off(struct jme_adapter *jme)
+{
+	u32 reg;
+
+	reg = jread32(jme, JME_PHY_PWR);
+	reg |= PHY_PWR_DWN1SEL | PHY_PWR_DWN1SW |
+	       PHY_PWR_DWN2 | PHY_PWR_CLKSEL;
+	jwrite32(jme, JME_PHY_PWR, reg);
+
+	pci_read_config_dword(jme->pdev, PCI_PRIV_PE1, &reg);
+	reg &= ~PE1_GPREG0_PBG;
+	reg |= PE1_GPREG0_PDD3COLD;
+	pci_write_config_dword(jme->pdev, PCI_PRIV_PE1, reg);
+}
+
+static inline void
 jme_phy_on(struct jme_adapter *jme)
 {
 	u32 bmcr;
@@ -1584,6 +1724,22 @@
 	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
 	bmcr &= ~BMCR_PDOWN;
 	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+
+	if (new_phy_power_ctrl(jme->chip_main_rev))
+		jme_new_phy_on(jme);
+}
+
+static inline void
+jme_phy_off(struct jme_adapter *jme)
+{
+	u32 bmcr;
+
+	bmcr = jme_mdio_read(jme->dev, jme->mii_if.phy_id, MII_BMCR);
+	bmcr |= BMCR_PDOWN;
+	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, bmcr);
+
+	if (new_phy_power_ctrl(jme->chip_main_rev))
+		jme_new_phy_off(jme);
 }
 
 static int
@@ -1606,12 +1762,11 @@
 
 	jme_start_irq(jme);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
-		jme_phy_on(jme);
+	jme_phy_on(jme);
+	if (test_bit(JME_FLAG_SSET, &jme->flags))
 		jme_set_settings(netdev, &jme->old_ecmd);
-	} else {
+	else
 		jme_reset_phy_processor(jme);
-	}
 
 	jme_reset_link(jme);
 
@@ -1657,12 +1812,6 @@
 	}
 }
 
-static inline void
-jme_phy_off(struct jme_adapter *jme)
-{
-	jme_mdio_write(jme->dev, jme->mii_if.phy_id, MII_BMCR, BMCR_PDOWN);
-}
-
 static void
 jme_powersave_phy(struct jme_adapter *jme)
 {
@@ -1696,7 +1845,6 @@
 	tasklet_disable(&jme->rxclean_task);
 	tasklet_disable(&jme->rxempty_task);
 
-	jme_reset_ghc_speed(jme);
 	jme_disable_rx_engine(jme);
 	jme_disable_tx_engine(jme);
 	jme_reset_mac_processor(jme);
@@ -1993,27 +2141,34 @@
 	return NETDEV_TX_OK;
 }
 
+static void
+jme_set_unicastaddr(struct net_device *netdev)
+{
+	struct jme_adapter *jme = netdev_priv(netdev);
+	u32 val;
+
+	val = (netdev->dev_addr[3] & 0xff) << 24 |
+	      (netdev->dev_addr[2] & 0xff) << 16 |
+	      (netdev->dev_addr[1] & 0xff) <<  8 |
+	      (netdev->dev_addr[0] & 0xff);
+	jwrite32(jme, JME_RXUMA_LO, val);
+	val = (netdev->dev_addr[5] & 0xff) << 8 |
+	      (netdev->dev_addr[4] & 0xff);
+	jwrite32(jme, JME_RXUMA_HI, val);
+}
+
 static int
 jme_set_macaddr(struct net_device *netdev, void *p)
 {
 	struct jme_adapter *jme = netdev_priv(netdev);
 	struct sockaddr *addr = p;
-	u32 val;
 
 	if (netif_running(netdev))
 		return -EBUSY;
 
 	spin_lock_bh(&jme->macaddr_lock);
 	memcpy(netdev->dev_addr, addr->sa_data, netdev->addr_len);
-
-	val = (addr->sa_data[3] & 0xff) << 24 |
-	      (addr->sa_data[2] & 0xff) << 16 |
-	      (addr->sa_data[1] & 0xff) <<  8 |
-	      (addr->sa_data[0] & 0xff);
-	jwrite32(jme, JME_RXUMA_LO, val);
-	val = (addr->sa_data[5] & 0xff) << 8 |
-	      (addr->sa_data[4] & 0xff);
-	jwrite32(jme, JME_RXUMA_HI, val);
+	jme_set_unicastaddr(netdev);
 	spin_unlock_bh(&jme->macaddr_lock);
 
 	return 0;
@@ -2383,6 +2538,8 @@
 
 	jwrite32(jme, JME_PMCS, jme->reg_pmcs);
 
+	device_set_wakeup_enable(&jme->pdev->dev, jme->reg_pmcs);
+
 	return 0;
 }
 
@@ -2731,6 +2888,8 @@
 
 	jme->fpgaver = (chipmode & CM_FPGAVER_MASK) >> CM_FPGAVER_SHIFT;
 	jme->chiprev = (chipmode & CM_CHIPREV_MASK) >> CM_CHIPREV_SHIFT;
+	jme->chip_main_rev = jme->chiprev & 0xF;
+	jme->chip_sub_rev = (jme->chiprev >> 4) & 0xF;
 }
 
 static const struct net_device_ops jme_netdev_ops = {
@@ -2880,6 +3039,7 @@
 	jme->reg_rxmcs = RXMCS_DEFAULT;
 	jme->reg_txpfc = 0;
 	jme->reg_pmcs = PMCS_MFEN;
+	jme->reg_gpreg1 = GPREG1_DEFAULT;
 	set_bit(JME_FLAG_TXCSUM, &jme->flags);
 	set_bit(JME_FLAG_TSO, &jme->flags);
 
@@ -2936,8 +3096,8 @@
 	jme->mii_if.mdio_write = jme_mdio_write;
 
 	jme_clear_pm(jme);
-	jme_set_phyfifoa(jme);
-	pci_read_config_byte(pdev, PCI_REVISION_ID, &jme->rev);
+	jme_set_phyfifo_5level(jme);
+	jme->pcirev = pdev->revision;
 	if (!jme->fpgaver)
 		jme_phy_init(jme);
 	jme_phy_off(jme);
@@ -2964,14 +3124,14 @@
 		goto err_out_unmap;
 	}
 
-	netif_info(jme, probe, jme->dev, "%s%s ver:%x rev:%x macaddr:%pM\n",
+	netif_info(jme, probe, jme->dev, "%s%s chiprev:%x pcirev:%x macaddr:%pM\n",
 		   (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC250) ?
 		   "JMC250 Gigabit Ethernet" :
 		   (jme->pdev->device == PCI_DEVICE_ID_JMICRON_JMC260) ?
 		   "JMC260 Fast Ethernet" : "Unknown",
 		   (jme->fpgaver != 0) ? " (FPGA)" : "",
 		   (jme->fpgaver != 0) ? jme->fpgaver : jme->chiprev,
-		   jme->rev, netdev->dev_addr);
+		   jme->pcirev, netdev->dev_addr);
 
 	return 0;
 
@@ -3014,9 +3174,9 @@
 }
 
 #ifdef CONFIG_PM
-static int
-jme_suspend(struct pci_dev *pdev, pm_message_t state)
+static int jme_suspend(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct jme_adapter *jme = netdev_priv(netdev);
 
@@ -3035,7 +3195,6 @@
 			jme_polling_mode(jme);
 
 		jme_stop_pcc_timer(jme);
-		jme_reset_ghc_speed(jme);
 		jme_disable_rx_engine(jme);
 		jme_disable_tx_engine(jme);
 		jme_reset_mac_processor(jme);
@@ -3049,29 +3208,24 @@
 	tasklet_hi_enable(&jme->rxclean_task);
 	tasklet_hi_enable(&jme->rxempty_task);
 
-	pci_save_state(pdev);
 	jme_powersave_phy(jme);
-	pci_enable_wake(jme->pdev, PCI_D3hot, true);
-	pci_set_power_state(pdev, PCI_D3hot);
 
 	return 0;
 }
 
-static int
-jme_resume(struct pci_dev *pdev)
+static int jme_resume(struct device *dev)
 {
+	struct pci_dev *pdev = to_pci_dev(dev);
 	struct net_device *netdev = pci_get_drvdata(pdev);
 	struct jme_adapter *jme = netdev_priv(netdev);
 
-	jme_clear_pm(jme);
-	pci_restore_state(pdev);
+	jwrite32(jme, JME_PMCS, 0xFFFF0000 | jme->reg_pmcs);
 
-	if (test_bit(JME_FLAG_SSET, &jme->flags)) {
-		jme_phy_on(jme);
+	jme_phy_on(jme);
+	if (test_bit(JME_FLAG_SSET, &jme->flags))
 		jme_set_settings(netdev, &jme->old_ecmd);
-	} else {
+	else
 		jme_reset_phy_processor(jme);
-	}
 
 	jme_start_irq(jme);
 	netif_device_attach(netdev);
@@ -3082,6 +3236,13 @@
 
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(jme_pm_ops, jme_suspend, jme_resume);
+#define JME_PM_OPS (&jme_pm_ops)
+
+#else
+
+#define JME_PM_OPS NULL
 #endif
 
 static DEFINE_PCI_DEVICE_TABLE(jme_pci_tbl) = {
@@ -3095,11 +3256,8 @@
 	.id_table       = jme_pci_tbl,
 	.probe          = jme_init_one,
 	.remove         = __devexit_p(jme_remove_one),
-#ifdef CONFIG_PM
-	.suspend        = jme_suspend,
-	.resume         = jme_resume,
-#endif /* CONFIG_PM */
 	.shutdown       = jme_shutdown,
+	.driver.pm	= JME_PM_OPS,
 };
 
 static int __init
diff -druN linux-libre-2.6.38-gnu/drivers/net/jme.h linux-libre-2.6.39-gnu/drivers/net/jme.h
--- linux-libre-2.6.38-gnu/drivers/net/jme.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/jme.h	2011-05-19 00:06:34.000000000 -0400
@@ -26,7 +26,7 @@
 #define __JME_H_INCLUDED__
 
 #define DRV_NAME	"jme"
-#define DRV_VERSION	"1.0.7"
+#define DRV_VERSION	"1.0.8"
 #define PFX		DRV_NAME ": "
 
 #define PCI_DEVICE_ID_JMICRON_JMC250	0x0250
@@ -103,6 +103,37 @@
 #define HALF_US 500	/* 500 ns */
 #define JMESPIIOCTL	SIOCDEVPRIVATE
 
+#define PCI_PRIV_PE1		0xE4
+
+enum pci_priv_pe1_bit_masks {
+	PE1_ASPMSUPRT	= 0x00000003, /*
+				       * RW:
+				       * Aspm_support[1:0]
+				       * (R/W Port of 5C[11:10])
+				       */
+	PE1_MULTIFUN	= 0x00000004, /* RW: Multi_fun_bit */
+	PE1_RDYDMA	= 0x00000008, /* RO: ~link.rdy_for_dma */
+	PE1_ASPMOPTL	= 0x00000030, /* RW: link.rx10s_option[1:0] */
+	PE1_ASPMOPTH	= 0x000000C0, /* RW: 10_req=[3]?HW:[2] */
+	PE1_GPREG0	= 0x0000FF00, /*
+				       * SRW:
+				       * Cfg_gp_reg0
+				       * [7:6] phy_giga BG control
+				       * [5] CREQ_N as CREQ_N1 (CPPE# as CREQ#)
+				       * [4:0] Reserved
+				       */
+	PE1_GPREG0_PBG	= 0x0000C000, /* phy_giga BG control */
+	PE1_GPREG1	= 0x00FF0000, /* RW: Cfg_gp_reg1 */
+	PE1_REVID	= 0xFF000000, /* RO: Rev ID */
+};
+
+enum pci_priv_pe1_values {
+	PE1_GPREG0_ENBG		= 0x00000000, /* en BG */
+	PE1_GPREG0_PDD3COLD	= 0x00004000, /* giga_PD + d3cold */
+	PE1_GPREG0_PDPCIESD	= 0x00008000, /* giga_PD + pcie_shutdown */
+	PE1_GPREG0_PDPCIEIDDQ	= 0x0000C000, /* giga_PD + pcie_iddq */
+};
+
 /*
  * Dynamic(adaptive)/Static PCC values
  */
@@ -403,6 +434,7 @@
 	u32			reg_rxmcs;
 	u32			reg_ghc;
 	u32			reg_pmcs;
+	u32			reg_gpreg1;
 	u32			phylink;
 	u32			tx_ring_size;
 	u32			tx_ring_mask;
@@ -411,8 +443,10 @@
 	u32			rx_ring_mask;
 	u8			mrrs;
 	unsigned int		fpgaver;
-	unsigned int		chiprev;
-	u8			rev;
+	u8			chiprev;
+	u8			chip_main_rev;
+	u8			chip_sub_rev;
+	u8			pcirev;
 	u32			msg_enable;
 	struct ethtool_cmd	old_ecmd;
 	unsigned int		old_mtu;
@@ -497,6 +531,7 @@
 	JME_PMCS	= JME_MAC | 0x60, /* Power Management Control/Stat */
 
 
+	JME_PHY_PWR	= JME_PHY | 0x24, /* New PHY Power Ctrl Register */
 	JME_PHY_CS	= JME_PHY | 0x28, /* PHY Ctrl and Status Register */
 	JME_PHY_LINK	= JME_PHY | 0x30, /* PHY Link Status Register */
 	JME_SMBCSR	= JME_PHY | 0x40, /* SMB Control and Status */
@@ -624,6 +659,14 @@
 	TXTRHD_TXRL_SHIFT	= 0,
 };
 
+enum jme_txtrhd_values {
+	TXTRHD_FULLDUPLEX	= 0x00000000,
+	TXTRHD_HALFDUPLEX	= TXTRHD_TXPEN |
+				  ((0x2000 << TXTRHD_TXP_SHIFT) & TXTRHD_TXP) |
+				  TXTRHD_TXREN |
+				  ((8 << TXTRHD_TXRL_SHIFT) & TXTRHD_TXRL),
+};
+
 /*
  * RX Control/Status Bits
  */
@@ -779,6 +822,8 @@
  */
 enum jme_ghc_bit_mask {
 	GHC_SWRST		= 0x40000000,
+	GHC_TO_CLK_SRC		= 0x00C00000,
+	GHC_TXMAC_CLK_SRC	= 0x00300000,
 	GHC_DPX			= 0x00000040,
 	GHC_SPEED		= 0x00000030,
 	GHC_LINK_POLL		= 0x00000001,
@@ -833,6 +878,21 @@
 };
 
 /*
+ * New PHY Power Control Register
+ */
+enum jme_phy_pwr_bit_masks {
+	PHY_PWR_DWN1SEL	= 0x01000000, /* Phy_giga.p_PWR_DOWN1_SEL */
+	PHY_PWR_DWN1SW	= 0x02000000, /* Phy_giga.p_PWR_DOWN1_SW */
+	PHY_PWR_DWN2	= 0x04000000, /* Phy_giga.p_PWR_DOWN2 */
+	PHY_PWR_CLKSEL	= 0x08000000, /*
+				       * XTL_OUT Clock select
+				       * (an internal free-running clock)
+				       * 0: xtl_out = phy_giga.A_XTL25_O
+				       * 1: xtl_out = phy_giga.PD_OSC
+				       */
+};
+
+/*
  * Giga PHY Status Registers
  */
 enum jme_phy_link_bit_mask {
@@ -942,18 +1002,17 @@
 
 /*
  * General Purpose REG-1
- * Note: All theses bits defined here are for
- *       Chip mode revision 0x11 only
  */
-enum jme_gpreg1_masks {
+enum jme_gpreg1_bit_masks {
+	GPREG1_RXCLKOFF		= 0x04000000,
+	GPREG1_PCREQN		= 0x00020000,
+	GPREG1_HALFMODEPATCH	= 0x00000040, /* For Chip revision 0x11 only */
+	GPREG1_RSSPATCH		= 0x00000020, /* For Chip revision 0x11 only */
 	GPREG1_INTRDELAYUNIT	= 0x00000018,
 	GPREG1_INTRDELAYENABLE	= 0x00000007,
 };
 
 enum jme_gpreg1_vals {
-	GPREG1_RSSPATCH		= 0x00000040,
-	GPREG1_HALFMODEPATCH	= 0x00000020,
-
 	GPREG1_INTDLYUNIT_16NS	= 0x00000000,
 	GPREG1_INTDLYUNIT_256NS	= 0x00000008,
 	GPREG1_INTDLYUNIT_1US	= 0x00000010,
@@ -967,7 +1026,7 @@
 	GPREG1_INTDLYEN_6U	= 0x00000006,
 	GPREG1_INTDLYEN_7U	= 0x00000007,
 
-	GPREG1_DEFAULT		= 0x00000000,
+	GPREG1_DEFAULT		= GPREG1_PCREQN,
 };
 
 /*
@@ -1184,16 +1243,22 @@
 /*
  * Workaround
  */
-static inline int is_buggy250(unsigned short device, unsigned int chiprev)
+static inline int is_buggy250(unsigned short device, u8 chiprev)
 {
 	return device == PCI_DEVICE_ID_JMICRON_JMC250 && chiprev == 0x11;
 }
 
+static inline int new_phy_power_ctrl(u8 chip_main_rev)
+{
+	return chip_main_rev >= 5;
+}
+
 /*
  * Function prototypes
  */
 static int jme_set_settings(struct net_device *netdev,
 				struct ethtool_cmd *ecmd);
+static void jme_set_unicastaddr(struct net_device *netdev);
 static void jme_set_multi(struct net_device *netdev);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/Kconfig linux-libre-2.6.39-gnu/drivers/net/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -238,8 +238,8 @@
 config AX88796
 	tristate "ASIX AX88796 NE2000 clone support"
 	depends on ARM || MIPS || SUPERH
-	select CRC32
-	select MII
+	select PHYLIB
+	select MDIO_BITBANG
 	help
 	  AX88796 driver, using platform bus to provide
 	  chip detection and resources
@@ -1498,7 +1498,7 @@
 config CS89x0
 	tristate "CS89x0 support"
 	depends on NET_ETHERNET && (ISA || EISA || MACH_IXDP2351 \
-		|| ARCH_IXDP2X01 || MACH_MX31ADS)
+		|| ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440)
 	---help---
 	  Support for CS89x0 chipset based Ethernet cards. If you have a
 	  network (Ethernet) card of this type, say Y and read the
@@ -1512,7 +1512,7 @@
 config CS89x0_NONISA_IRQ
 	def_bool y
 	depends on CS89x0 != n
-	depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS
+	depends on MACH_IXDP2351 || ARCH_IXDP2X01 || MACH_MX31ADS || MACH_QQ2440
 
 config TC35815
 	tristate "TOSHIBA TC35815 Ethernet support"
@@ -1944,7 +1944,8 @@
 config FEC
 	bool "FEC ethernet controller (of ColdFire and some i.MX CPUs)"
 	depends on M523x || M527x || M5272 || M528x || M520x || M532x || \
-		MACH_MX27 || ARCH_MX35 || ARCH_MX25 || ARCH_MX5 || SOC_IMX28
+		IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC
+	default IMX_HAVE_PLATFORM_FEC || MXS_HAVE_PLATFORM_FEC if ARM
 	select PHYLIB
 	help
 	  Say Y here if you want to use the built-in 10/100 Fast ethernet
@@ -2007,6 +2008,15 @@
 	  This driver supports the ethernet MACs in the Broadcom 63xx
 	  MIPS chipset family (BCM63XX).
 
+config FTMAC100
+	tristate "Faraday FTMAC100 10/100 Ethernet support"
+	depends on ARM
+	select MII
+	help
+	  This driver supports the FTMAC100 10/100 Ethernet controller
+	  from Faraday. It is used on Faraday A320, Andes AG101 and some
+	  other ARM/NDS32 SoC's.
+
 source "drivers/net/fs_enet/Kconfig"
 
 source "drivers/net/octeon/Kconfig"
@@ -2098,7 +2108,9 @@
 
 config E1000E
 	tristate "Intel(R) PRO/1000 PCI-Express Gigabit Ethernet support"
+	select CRC32
 	depends on PCI && (!SPARC32 || BROKEN)
+	select CRC32
 	---help---
 	  This driver supports the PCI-Express Intel(R) PRO/1000 gigabit
 	  ethernet family of adapters. For PCI or PCI-X e1000 adapters,
@@ -2235,15 +2247,6 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called r8169.  This is recommended.
 
-config R8169_VLAN
-	bool "VLAN support"
-	depends on R8169 && VLAN_8021Q
-	---help---
-	  Say Y here for the r8169 driver to support the functions required
-	  by the kernel 802.1Q code.
-
-	  If in doubt, say Y.
-
 config SB1250_MAC
 	tristate "SB1250 Gigabit Ethernet support"
 	depends on SIBYTE_SB1xxx_SOC
@@ -2533,7 +2536,7 @@
 source "drivers/net/stmmac/Kconfig"
 
 config PCH_GBE
-	tristate "PCH Gigabit Ethernet"
+	tristate "Intel EG20T PCH / OKI SEMICONDUCTOR ML7223 IOH GbE"
 	depends on PCI
 	select MII
 	---help---
@@ -2545,6 +2548,12 @@
 	  to Gigabit Ethernet.
 	  This driver enables Gigabit Ethernet function.
 
+	  This driver also can be used for OKI SEMICONDUCTOR IOH(Input/
+	  Output Hub), ML7223.
+	  ML7223 IOH is for MP(Media Phone) use.
+	  ML7223 is companion chip for Intel Atom E6xx series.
+	  ML7223 is completely compatible for Intel EG20T PCH.
+
 endif # NETDEV_1000
 
 #
@@ -2594,14 +2603,9 @@
 	  Enables support for Chelsio's gigabit Ethernet PCI cards.  If you
 	  are using only 10G cards say 'N' here.
 
-config CHELSIO_T3_DEPENDS
-	tristate
-	depends on PCI && INET
-	default y
-
 config CHELSIO_T3
 	tristate "Chelsio Communications T3 10Gb Ethernet support"
-	depends on CHELSIO_T3_DEPENDS
+	depends on PCI && INET
 	select FW_LOADER
 	select MDIO
 	help
@@ -2619,14 +2623,9 @@
 	  To compile this driver as a module, choose M here: the module
 	  will be called cxgb3.
 
-config CHELSIO_T4_DEPENDS
-	tristate
-	depends on PCI && INET
-	default y
-
 config CHELSIO_T4
 	tristate "Chelsio Communications T4 Ethernet support"
-	depends on CHELSIO_T4_DEPENDS
+	depends on PCI
 	select FW_LOADER
 	select MDIO
 	help
@@ -2644,14 +2643,9 @@
 	  To compile this driver as a module choose M here; the module
 	  will be called cxgb4.
 
-config CHELSIO_T4VF_DEPENDS
-	tristate
-	depends on PCI && INET
-	default y
-
 config CHELSIO_T4VF
 	tristate "Chelsio Communications T4 Virtual Function Ethernet support"
-	depends on CHELSIO_T4VF_DEPENDS
+	depends on PCI
 	help
 	  This driver supports Chelsio T4-based gigabit and 10Gb Ethernet
 	  adapters with PCI-E SR-IOV Virtual Functions.
@@ -2966,12 +2960,38 @@
 	select XEN_XENBUS_FRONTEND
 	default y
 	help
-	  The network device frontend driver allows the kernel to
-	  access network devices exported exported by a virtual
-	  machine containing a physical network device driver. The
-	  frontend driver is intended for unprivileged guest domains;
-	  if you are compiling a kernel for a Xen guest, you almost
-	  certainly want to enable this.
+	  This driver provides support for Xen paravirtual network
+	  devices exported by a Xen network driver domain (often
+	  domain 0).
+
+	  The corresponding Linux backend driver is enabled by the
+	  CONFIG_XEN_NETDEV_BACKEND option.
+
+	  If you are compiling a kernel for use as Xen guest, you
+	  should say Y here. To compile this driver as a module, chose
+	  M here: the module will be called xen-netfront.
+
+config XEN_NETDEV_BACKEND
+	tristate "Xen backend network device"
+	depends on XEN_BACKEND
+	help
+	  This driver allows the kernel to act as a Xen network driver
+	  domain which exports paravirtual network devices to other
+	  Xen domains. These devices can be accessed by any operating
+	  system that implements a compatible front end.
+
+	  The corresponding Linux frontend driver is enabled by the
+	  CONFIG_XEN_NETDEV_FRONTEND configuration option.
+
+	  The backend driver presents a standard network device
+	  endpoint for each paravirtual network device to the driver
+	  domain network stack. These can then be bridged or routed
+	  etc in order to provide full network connectivity.
+
+	  If you are compiling a kernel to run in a Xen network driver
+	  domain (often this is domain 0) you should say Y here. To
+	  compile this driver as a module, chose M here: the module
+	  will be called xen-netback.
 
 config ISERIES_VETH
 	tristate "iSeries Virtual Ethernet driver support"
diff -druN linux-libre-2.6.38-gnu/drivers/net/ks8842.c linux-libre-2.6.39-gnu/drivers/net/ks8842.c
--- linux-libre-2.6.38-gnu/drivers/net/ks8842.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ks8842.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
 #include <linux/ethtool.h>
@@ -320,7 +321,7 @@
 	/* RX 2 kb high watermark */
 	ks8842_write16(adapter, 0, 0x1000, REG_QRFCR);
 
-	/* aggresive back off in half duplex */
+	/* aggressive back off in half duplex */
 	ks8842_enable_bits(adapter, 32, 1 << 8, REG_SGCR1);
 
 	/* enable no excessive collison drop */
@@ -1145,7 +1146,7 @@
 	struct resource *iomem;
 	struct net_device *netdev;
 	struct ks8842_adapter *adapter;
-	struct ks8842_platform_data *pdata = pdev->dev.platform_data;
+	struct ks8842_platform_data *pdata = mfd_get_data(pdev);
 	u16 id;
 	unsigned i;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ks8851.c linux-libre-2.6.39-gnu/drivers/net/ks8851.c
--- linux-libre-2.6.38-gnu/drivers/net/ks8851.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ks8851.c	2011-05-19 00:06:34.000000000 -0400
@@ -141,7 +141,7 @@
  *
  * 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).
+ * chip is busy transferring packet data (RX/TX FIFO accesses).
  */
 
 /**
@@ -483,7 +483,7 @@
 	 *
 	 * 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.
+	 * reset to the data stream coming from the chip.
 	 */
 
 	for (; rxfc != 0; rxfc--) {
@@ -634,7 +634,7 @@
 
 /**
  * calc_txlen - calculate size of message to send packet
- * @len: Lenght of data
+ * @len: Length of data
  *
  * Returns the size of the TXFIFO message needed to send
  * this packet.
@@ -1472,7 +1472,7 @@
  * @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
+ * device does not support all the MII registers, the non-existent values
  * are always returned as zero.
  *
  * We return zero for unsupported registers as the MII code does not check
diff -druN linux-libre-2.6.38-gnu/drivers/net/ks8851_mll.c linux-libre-2.6.39-gnu/drivers/net/ks8851_mll.c
--- linux-libre-2.6.38-gnu/drivers/net/ks8851_mll.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ks8851_mll.c	2011-05-19 00:06:34.000000000 -0400
@@ -470,7 +470,7 @@
  *
  * All these calls issue 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).
+ * chip is busy transferring packet data (RX/TX FIFO accesses).
  */
 
 /**
@@ -1364,7 +1364,7 @@
  * @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
+ * device does not support all the MII registers, the non-existent values
  * are always returned as zero.
  *
  * We return zero for unsupported registers as the MII code does not check
diff -druN linux-libre-2.6.38-gnu/drivers/net/ksz884x.c linux-libre-2.6.39-gnu/drivers/net/ksz884x.c
--- linux-libre-2.6.38-gnu/drivers/net/ksz884x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ksz884x.c	2011-05-19 00:06:34.000000000 -0400
@@ -4898,7 +4898,7 @@
 				goto unlock;
 			}
 			skb_copy_and_csum_dev(org_skb, skb->data);
-			org_skb->ip_summed = 0;
+			org_skb->ip_summed = CHECKSUM_NONE;
 			skb->len = org_skb->len;
 			copy_old_skb(org_skb, skb);
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/net/lib8390.c linux-libre-2.6.39-gnu/drivers/net/lib8390.c
--- linux-libre-2.6.38-gnu/drivers/net/lib8390.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/lib8390.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
   Alexey Kuznetsov	: use the 8390's six bit hash multicast filter.
   Paul Gortmaker	: tweak ANK's above multicast changes a bit.
   Paul Gortmaker	: update packet statistics for v2.1.x
-  Alan Cox		: support arbitary stupid port mappings on the
+  Alan Cox		: support arbitrary stupid port mappings on the
   			  68K Macintosh. Support >16bit I/O spaces
   Paul Gortmaker	: add kmod support for auto-loading of the 8390
 			  module by all drivers that require it.
@@ -121,7 +121,7 @@
 /*
  *	SMP and the 8390 setup.
  *
- *	The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
+ *	The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
  *	a page register that controls bank and packet buffer access. We guard
  *	this with ei_local->page_lock. Nobody should assume or set the page other
  *	than zero when the lock is not held. Lock holders must restore page 0
diff -druN linux-libre-2.6.38-gnu/drivers/net/ll_temac_main.c linux-libre-2.6.39-gnu/drivers/net/ll_temac_main.c
--- linux-libre-2.6.38-gnu/drivers/net/ll_temac_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ll_temac_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -952,8 +952,7 @@
 	.attrs = temac_device_attrs,
 };
 
-static int __devinit
-temac_of_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit temac_of_probe(struct platform_device *op)
 {
 	struct device_node *np;
 	struct temac_local *lp;
@@ -1123,7 +1122,7 @@
 };
 MODULE_DEVICE_TABLE(of, temac_of_match);
 
-static struct of_platform_driver temac_of_driver = {
+static struct platform_driver temac_of_driver = {
 	.probe = temac_of_probe,
 	.remove = __devexit_p(temac_of_remove),
 	.driver = {
@@ -1135,13 +1134,13 @@
 
 static int __init temac_init(void)
 {
-	return of_register_platform_driver(&temac_of_driver);
+	return platform_driver_register(&temac_of_driver);
 }
 module_init(temac_init);
 
 static void __exit temac_exit(void)
 {
-	of_unregister_platform_driver(&temac_of_driver);
+	platform_driver_unregister(&temac_of_driver);
 }
 module_exit(temac_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/loopback.c linux-libre-2.6.39-gnu/drivers/net/loopback.c
--- linux-libre-2.6.38-gnu/drivers/net/loopback.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/loopback.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,10 +129,6 @@
 
 static const struct ethtool_ops loopback_ethtool_ops = {
 	.get_link		= always_on,
-	.set_tso		= ethtool_op_set_tso,
-	.get_tx_csum		= always_on,
-	.get_sg			= always_on,
-	.get_rx_csum		= always_on,
 };
 
 static int loopback_dev_init(struct net_device *dev)
@@ -169,12 +165,16 @@
 	dev->type		= ARPHRD_LOOPBACK;	/* 0x0001*/
 	dev->flags		= IFF_LOOPBACK;
 	dev->priv_flags	       &= ~IFF_XMIT_DST_RELEASE;
+	dev->hw_features	= NETIF_F_ALL_TSO | NETIF_F_UFO;
 	dev->features 		= NETIF_F_SG | NETIF_F_FRAGLIST
-		| NETIF_F_TSO
+		| NETIF_F_ALL_TSO
+		| NETIF_F_UFO
 		| NETIF_F_NO_CSUM
+		| NETIF_F_RXCSUM
 		| NETIF_F_HIGHDMA
 		| NETIF_F_LLTX
-		| NETIF_F_NETNS_LOCAL;
+		| NETIF_F_NETNS_LOCAL
+		| NETIF_F_VLAN_CHALLENGED;
 	dev->ethtool_ops	= &loopback_ethtool_ops;
 	dev->header_ops		= &eth_header_ops;
 	dev->netdev_ops		= &loopback_ops;
diff -druN linux-libre-2.6.38-gnu/drivers/net/lp486e.c linux-libre-2.6.39-gnu/drivers/net/lp486e.c
--- linux-libre-2.6.38-gnu/drivers/net/lp486e.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/lp486e.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 
 	Credits:
 	Thanks to Murphy Software BV for letting me write this in their time.
-	Well, actually, I get payed doing this...
+	Well, actually, I get paid doing this...
 	(Also: see http://www.murphy.nl for murphy, and my homepage ~ard for
 	more information on the Professional Workstation)
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/macvlan.c linux-libre-2.6.39-gnu/drivers/net/macvlan.c
--- linux-libre-2.6.38-gnu/drivers/net/macvlan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/macvlan.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,8 +39,11 @@
 	struct list_head	vlans;
 	struct rcu_head		rcu;
 	bool 			passthru;
+	int			count;
 };
 
+static void macvlan_port_destroy(struct net_device *dev);
+
 #define macvlan_port_get_rcu(dev) \
 	((struct macvlan_port *) rcu_dereference(dev->rx_handler_data))
 #define macvlan_port_get(dev) ((struct macvlan_port *) dev->rx_handler_data)
@@ -152,9 +155,10 @@
 }
 
 /* called under rcu_read_lock() from netif_receive_skb */
-static struct sk_buff *macvlan_handle_frame(struct sk_buff *skb)
+static rx_handler_result_t macvlan_handle_frame(struct sk_buff **pskb)
 {
 	struct macvlan_port *port;
+	struct sk_buff *skb = *pskb;
 	const struct ethhdr *eth = eth_hdr(skb);
 	const struct macvlan_dev *vlan;
 	const struct macvlan_dev *src;
@@ -184,7 +188,7 @@
 			 */
 			macvlan_broadcast(skb, port, src->dev,
 					  MACVLAN_MODE_VEPA);
-		return skb;
+		return RX_HANDLER_PASS;
 	}
 
 	if (port->passthru)
@@ -192,12 +196,12 @@
 	else
 		vlan = macvlan_hash_lookup(port, eth->h_dest);
 	if (vlan == NULL)
-		return skb;
+		return RX_HANDLER_PASS;
 
 	dev = vlan->dev;
 	if (unlikely(!(dev->flags & IFF_UP))) {
 		kfree_skb(skb);
-		return NULL;
+		return RX_HANDLER_CONSUMED;
 	}
 	len = skb->len + ETH_HLEN;
 	skb = skb_share_check(skb, GFP_ATOMIC);
@@ -211,7 +215,7 @@
 
 out:
 	macvlan_count_rx(vlan, len, ret == NET_RX_SUCCESS, 0);
-	return NULL;
+	return RX_HANDLER_CONSUMED;
 }
 
 static int macvlan_queue_xmit(struct sk_buff *skb, struct net_device *dev)
@@ -219,9 +223,11 @@
 	const struct macvlan_dev *vlan = netdev_priv(dev);
 	const struct macvlan_port *port = vlan->port;
 	const struct macvlan_dev *dest;
+	__u8 ip_summed = skb->ip_summed;
 
 	if (vlan->mode == MACVLAN_MODE_BRIDGE) {
 		const struct ethhdr *eth = (void *)skb->data;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		/* send to other bridge ports directly */
 		if (is_multicast_ether_addr(eth->h_dest)) {
@@ -241,6 +247,7 @@
 	}
 
 xmit_world:
+	skb->ip_summed = ip_summed;
 	skb_set_dev(skb, vlan->lowerdev);
 	return dev_queue_xmit(skb);
 }
@@ -453,8 +460,13 @@
 static void macvlan_uninit(struct net_device *dev)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
+	struct macvlan_port *port = vlan->port;
 
 	free_percpu(vlan->pcpu_stats);
+
+	port->count -= 1;
+	if (!port->count)
+		macvlan_port_destroy(port->dev);
 }
 
 static struct rtnl_link_stats64 *macvlan_dev_get_stats64(struct net_device *dev,
@@ -687,12 +699,13 @@
 		vlan->mode = nla_get_u32(data[IFLA_MACVLAN_MODE]);
 
 	if (vlan->mode == MACVLAN_MODE_PASSTHRU) {
-		if (!list_empty(&port->vlans))
+		if (port->count)
 			return -EINVAL;
 		port->passthru = true;
 		memcpy(dev->dev_addr, lowerdev->dev_addr, ETH_ALEN);
 	}
 
+	port->count += 1;
 	err = register_netdevice(dev);
 	if (err < 0)
 		goto destroy_port;
@@ -703,7 +716,8 @@
 	return 0;
 
 destroy_port:
-	if (list_empty(&port->vlans))
+	port->count -= 1;
+	if (!port->count)
 		macvlan_port_destroy(lowerdev);
 
 	return err;
@@ -721,13 +735,9 @@
 void macvlan_dellink(struct net_device *dev, struct list_head *head)
 {
 	struct macvlan_dev *vlan = netdev_priv(dev);
-	struct macvlan_port *port = vlan->port;
 
 	list_del(&vlan->list);
 	unregister_netdevice_queue(dev, head);
-
-	if (list_empty(&port->vlans))
-		macvlan_port_destroy(port->dev);
 }
 EXPORT_SYMBOL_GPL(macvlan_dellink);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/macvtap.c linux-libre-2.6.39-gnu/drivers/net/macvtap.c
--- linux-libre-2.6.38-gnu/drivers/net/macvtap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/macvtap.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 	struct socket sock;
 	struct socket_wq wq;
 	int vnet_hdr_sz;
-	struct macvlan_dev *vlan;
+	struct macvlan_dev __rcu *vlan;
 	struct file *file;
 	unsigned int flags;
 };
@@ -141,7 +141,8 @@
 	struct macvlan_dev *vlan;
 
 	spin_lock(&macvtap_lock);
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_protected(q->vlan,
+					 lockdep_is_held(&macvtap_lock));
 	if (vlan) {
 		int index = get_slot(vlan, q);
 
@@ -219,7 +220,8 @@
 	/* macvtap_put_queue can free some slots, so go through all slots */
 	spin_lock(&macvtap_lock);
 	for (i = 0; i < MAX_MACVTAP_QUEUES && vlan->numvtaps; i++) {
-		q = rcu_dereference(vlan->taps[i]);
+		q = rcu_dereference_protected(vlan->taps[i],
+					      lockdep_is_held(&macvtap_lock));
 		if (q) {
 			qlist[j++] = q;
 			rcu_assign_pointer(vlan->taps[i], NULL);
@@ -570,7 +572,7 @@
 	}
 
 	rcu_read_lock_bh();
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_bh(q->vlan);
 	if (vlan)
 		macvlan_start_xmit(skb, vlan->dev);
 	else
@@ -584,7 +586,7 @@
 
 err:
 	rcu_read_lock_bh();
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_bh(q->vlan);
 	if (vlan)
 		vlan->dev->stats.tx_dropped++;
 	rcu_read_unlock_bh();
@@ -632,7 +634,7 @@
 	ret = skb_copy_datagram_const_iovec(skb, 0, iv, vnet_hdr_len, len);
 
 	rcu_read_lock_bh();
-	vlan = rcu_dereference(q->vlan);
+	vlan = rcu_dereference_bh(q->vlan);
 	if (vlan)
 		macvlan_count_rx(vlan, len, ret == 0, 0);
 	rcu_read_unlock_bh();
@@ -728,7 +730,7 @@
 
 	case TUNGETIFF:
 		rcu_read_lock_bh();
-		vlan = rcu_dereference(q->vlan);
+		vlan = rcu_dereference_bh(q->vlan);
 		if (vlan)
 			dev_hold(vlan->dev);
 		rcu_read_unlock_bh();
@@ -737,7 +739,7 @@
 			return -ENOLINK;
 
 		ret = 0;
-		if (copy_to_user(&ifr->ifr_name, q->vlan->dev->name, IFNAMSIZ) ||
+		if (copy_to_user(&ifr->ifr_name, vlan->dev->name, IFNAMSIZ) ||
 		    put_user(q->flags, &ifr->ifr_flags))
 			ret = -EFAULT;
 		dev_put(vlan->dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/Makefile linux-libre-2.6.39-gnu/drivers/net/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -144,9 +144,10 @@
 obj-$(CONFIG_SB1250_MAC) += sb1250-mac.o
 obj-$(CONFIG_B44) += b44.o
 obj-$(CONFIG_FORCEDETH) += forcedeth.o
-obj-$(CONFIG_NE_H8300) += ne-h8300.o 8390.o
+obj-$(CONFIG_NE_H8300) += ne-h8300.o
 obj-$(CONFIG_AX88796) += ax88796.o
 obj-$(CONFIG_BCM63XX_ENET) += bcm63xx_enet.o
+obj-$(CONFIG_FTMAC100) += ftmac100.o
 
 obj-$(CONFIG_TSI108_ETH) += tsi108_eth.o
 obj-$(CONFIG_MV643XX_ETH) += mv643xx_eth.o
@@ -171,6 +172,7 @@
 obj-$(CONFIG_SLHC) += slhc.o
 
 obj-$(CONFIG_XEN_NETDEV_FRONTEND) += xen-netfront.o
+obj-$(CONFIG_XEN_NETDEV_BACKEND) += xen-netback/
 
 obj-$(CONFIG_DUMMY) += dummy.o
 obj-$(CONFIG_IFB) += ifb.o
@@ -217,7 +219,7 @@
 obj-$(CONFIG_LP486E) += lp486e.o
 
 obj-$(CONFIG_ETH16I) += eth16i.o
-obj-$(CONFIG_ZORRO8390) += zorro8390.o 8390.o
+obj-$(CONFIG_ZORRO8390) += zorro8390.o
 obj-$(CONFIG_HPLANCE) += hplance.o 7990.o
 obj-$(CONFIG_MVME147_NET) += mvme147.o 7990.o
 obj-$(CONFIG_EQUALIZER) += eql.o
@@ -229,7 +231,7 @@
 obj-$(CONFIG_DECLANCE) += declance.o
 obj-$(CONFIG_ATARILANCE) += atarilance.o
 obj-$(CONFIG_A2065) += a2065.o
-obj-$(CONFIG_HYDRA) += hydra.o 8390.o
+obj-$(CONFIG_HYDRA) += hydra.o
 obj-$(CONFIG_ARIADNE) += ariadne.o
 obj-$(CONFIG_CS89x0) += cs89x0.o
 obj-$(CONFIG_MACSONIC) += macsonic.o
diff -druN linux-libre-2.6.38-gnu/drivers/net/meth.h linux-libre-2.6.39-gnu/drivers/net/meth.h
--- linux-libre-2.6.38-gnu/drivers/net/meth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/meth.h	2011-05-19 00:06:34.000000000 -0400
@@ -144,7 +144,7 @@
 				       /* Bits 22 through 28 are used to determine IPGR2 */
 
 #define METH_REV_SHIFT 29       /* Bits 29 through 31 are used to determine the revision */
-				       /* 000: Inital revision */
+				       /* 000: Initial revision */
 				       /* 001: First revision, Improved TX concatenation */
 
 
@@ -193,7 +193,7 @@
 					      	/* 1: A TX message had the INT request bit set, the packet has been sent. */
 #define METH_INT_TX_LINK_FAIL	BIT(2)	/* 0: No interrupt pending, 1: PHY has reported a link failure */
 #define METH_INT_MEM_ERROR	BIT(3)	/* 0: No interrupt pending */
-						/* 1: A memory error occurred durring DMA, DMA stopped, Fatal */
+						/* 1: A memory error occurred during DMA, DMA stopped, Fatal */
 #define METH_INT_TX_ABORT		BIT(4)	/* 0: No interrupt pending, 1: The TX aborted operation, DMA stopped, FATAL */
 #define METH_INT_RX_THRESHOLD	BIT(5)	/* 0: No interrupt pending, 1: Selected receive threshold condition Valid */
 #define METH_INT_RX_UNDERFLOW	BIT(6)	/* 0: No interrupt pending, 1: FIFO was empty, packet could not be queued */
diff -druN linux-libre-2.6.38-gnu/drivers/net/mii.c linux-libre-2.6.39-gnu/drivers/net/mii.c
--- linux-libre-2.6.38-gnu/drivers/net/mii.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mii.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,6 +49,10 @@
 		result |= ADVERTISED_100baseT_Half;
 	if (advert & ADVERTISE_100FULL)
 		result |= ADVERTISED_100baseT_Full;
+	if (advert & ADVERTISE_PAUSE_CAP)
+		result |= ADVERTISED_Pause;
+	if (advert & ADVERTISE_PAUSE_ASYM)
+		result |= ADVERTISED_Asym_Pause;
 
 	return result;
 }
@@ -354,7 +358,7 @@
 	if (!new_carrier) {
 		netif_carrier_off(mii->dev);
 		if (ok_to_print)
-			printk(KERN_INFO "%s: link down\n", mii->dev->name);
+			netdev_info(mii->dev, "link down\n");
 		return 0; /* duplex did not change */
 	}
 
@@ -381,12 +385,12 @@
 		duplex = 1;
 
 	if (ok_to_print)
-		printk(KERN_INFO "%s: link up, %sMbps, %s-duplex, lpa 0x%04X\n",
-		       mii->dev->name,
-		       lpa2 & (LPA_1000FULL | LPA_1000HALF) ? "1000" :
-		       media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ? "100" : "10",
-		       duplex ? "full" : "half",
-		       lpa);
+		netdev_info(mii->dev, "link up, %uMbps, %s-duplex, lpa 0x%04X\n",
+			    lpa2 & (LPA_1000FULL | LPA_1000HALF) ? 1000 :
+			    media & (ADVERTISE_100FULL | ADVERTISE_100HALF) ?
+			    100 : 10,
+			    duplex ? "full" : "half",
+			    lpa);
 
 	if ((init_media) || (mii->full_duplex != duplex)) {
 		mii->full_duplex = duplex;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/alloc.c linux-libre-2.6.39-gnu/drivers/net/mlx4/alloc.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/alloc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/alloc.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,6 +62,9 @@
 	} else
 		obj = -1;
 
+	if (obj != -1)
+		--bitmap->avail;
+
 	spin_unlock(&bitmap->lock);
 
 	return obj;
@@ -101,11 +104,19 @@
 	} else
 		obj = -1;
 
+	if (obj != -1)
+		bitmap->avail -= cnt;
+
 	spin_unlock(&bitmap->lock);
 
 	return obj;
 }
 
+u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap)
+{
+	return bitmap->avail;
+}
+
 void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt)
 {
 	obj &= bitmap->max + bitmap->reserved_top - 1;
@@ -115,6 +126,7 @@
 	bitmap->last = min(bitmap->last, obj);
 	bitmap->top = (bitmap->top + bitmap->max + bitmap->reserved_top)
 			& bitmap->mask;
+	bitmap->avail += cnt;
 	spin_unlock(&bitmap->lock);
 }
 
@@ -130,6 +142,7 @@
 	bitmap->max  = num - reserved_top;
 	bitmap->mask = mask;
 	bitmap->reserved_top = reserved_top;
+	bitmap->avail = num - reserved_top - reserved_bot;
 	spin_lock_init(&bitmap->lock);
 	bitmap->table = kzalloc(BITS_TO_LONGS(bitmap->max) *
 				sizeof (long), GFP_KERNEL);
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/cq.c linux-libre-2.6.39-gnu/drivers/net/mlx4/cq.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/cq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/cq.c	2011-05-19 00:06:34.000000000 -0400
@@ -198,7 +198,7 @@
 	u64 mtt_addr;
 	int err;
 
-	if (vector >= dev->caps.num_comp_vectors)
+	if (vector > dev->caps.num_comp_vectors + dev->caps.comp_pool)
 		return -EINVAL;
 
 	cq->vector = vector;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_cq.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_cq.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_cq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_cq.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,13 +51,10 @@
 	int err;
 
 	cq->size = entries;
-	if (mode == RX) {
+	if (mode == RX)
 		cq->buf_size = cq->size * sizeof(struct mlx4_cqe);
-		cq->vector   = ring % mdev->dev->caps.num_comp_vectors;
-	} else {
+	else
 		cq->buf_size = sizeof(struct mlx4_cqe);
-		cq->vector   = 0;
-	}
 
 	cq->ring = ring;
 	cq->is_tx = mode;
@@ -80,7 +77,8 @@
 int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
-	int err;
+	int err = 0;
+	char name[25];
 
 	cq->dev = mdev->pndev[priv->port];
 	cq->mcq.set_ci_db  = cq->wqres.db.db;
@@ -89,6 +87,29 @@
 	*cq->mcq.arm_db    = 0;
 	memset(cq->buf, 0, cq->buf_size);
 
+	if (cq->is_tx == RX) {
+		if (mdev->dev->caps.comp_pool) {
+			if (!cq->vector) {
+				sprintf(name , "%s-rx-%d", priv->dev->name, cq->ring);
+				if (mlx4_assign_eq(mdev->dev, name, &cq->vector)) {
+					cq->vector = (cq->ring + 1 + priv->port) %
+						mdev->dev->caps.num_comp_vectors;
+					mlx4_warn(mdev, "Failed Assigning an EQ to "
+						  "%s_rx-%d ,Falling back to legacy EQ's\n",
+						  priv->dev->name, cq->ring);
+				}
+			}
+		} else {
+			cq->vector = (cq->ring + 1 + priv->port) %
+				mdev->dev->caps.num_comp_vectors;
+		}
+	} else {
+		if (!cq->vector || !mdev->dev->caps.comp_pool) {
+			/*Fallback to legacy pool in case of error*/
+			cq->vector   = 0;
+		}
+	}
+
 	if (!cq->is_tx)
 		cq->size = priv->rx_ring[cq->ring].actual_size;
 
@@ -112,12 +133,15 @@
 	return 0;
 }
 
-void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq)
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+			bool reserve_vectors)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
 
 	mlx4_en_unmap_buffer(&cq->wqres.buf);
 	mlx4_free_hwq_res(mdev->dev, &cq->wqres, cq->buf_size);
+	if (priv->mdev->dev->caps.comp_pool && cq->vector && !reserve_vectors)
+		mlx4_release_eq(priv->mdev->dev, cq->vector);
 	cq->buf_size = 0;
 	cq->buf = NULL;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_ethtool.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 	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->driver, DRV_NAME, 32);
 	strncpy(drvinfo->version, DRV_VERSION " (" DRV_RELDATE ")", 32);
 	sprintf(drvinfo->fw_version, "%d.%d.%d",
 		(u16) (mdev->dev->caps.fw_ver >> 32),
@@ -131,8 +131,65 @@
 static void mlx4_en_get_wol(struct net_device *netdev,
 			    struct ethtool_wolinfo *wol)
 {
-	wol->supported = 0;
-	wol->wolopts = 0;
+	struct mlx4_en_priv *priv = netdev_priv(netdev);
+	int err = 0;
+	u64 config = 0;
+
+	if (!priv->mdev->dev->caps.wol) {
+		wol->supported = 0;
+		wol->wolopts = 0;
+		return;
+	}
+
+	err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+	if (err) {
+		en_err(priv, "Failed to get WoL information\n");
+		return;
+	}
+
+	if (config & MLX4_EN_WOL_MAGIC)
+		wol->supported = WAKE_MAGIC;
+	else
+		wol->supported = 0;
+
+	if (config & MLX4_EN_WOL_ENABLED)
+		wol->wolopts = WAKE_MAGIC;
+	else
+		wol->wolopts = 0;
+}
+
+static int mlx4_en_set_wol(struct net_device *netdev,
+			    struct ethtool_wolinfo *wol)
+{
+	struct mlx4_en_priv *priv = netdev_priv(netdev);
+	u64 config = 0;
+	int err = 0;
+
+	if (!priv->mdev->dev->caps.wol)
+		return -EOPNOTSUPP;
+
+	if (wol->supported & ~WAKE_MAGIC)
+		return -EINVAL;
+
+	err = mlx4_wol_read(priv->mdev->dev, &config, priv->port);
+	if (err) {
+		en_err(priv, "Failed to get WoL info, unable to modify\n");
+		return err;
+	}
+
+	if (wol->wolopts & WAKE_MAGIC) {
+		config |= MLX4_EN_WOL_DO_MODIFY | MLX4_EN_WOL_ENABLED |
+				MLX4_EN_WOL_MAGIC;
+	} else {
+		config &= ~(MLX4_EN_WOL_ENABLED | MLX4_EN_WOL_MAGIC);
+		config |= MLX4_EN_WOL_DO_MODIFY;
+	}
+
+	err = mlx4_wol_write(priv->mdev->dev, config, priv->port);
+	if (err)
+		en_err(priv, "Failed to set WoL information\n");
+
+	return err;
 }
 
 static int mlx4_en_get_sset_count(struct net_device *dev, int sset)
@@ -388,7 +445,7 @@
 		mlx4_en_stop_port(dev);
 	}
 
-	mlx4_en_free_resources(priv);
+	mlx4_en_free_resources(priv, true);
 
 	priv->prof->tx_ring_size = tx_size;
 	priv->prof->rx_ring_size = rx_size;
@@ -442,6 +499,7 @@
 	.get_ethtool_stats = mlx4_en_get_ethtool_stats,
 	.self_test = mlx4_en_self_test,
 	.get_wol = mlx4_en_get_wol,
+	.set_wol = mlx4_en_set_wol,
 	.get_msglevel = mlx4_en_get_msglevel,
 	.set_msglevel = mlx4_en_set_msglevel,
 	.get_coalesce = mlx4_en_get_coalesce,
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_main.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_main.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -236,21 +236,23 @@
 		goto err_mr;
 	}
 
-	/* Configure wich ports to start according to module parameters */
+	/* Configure which ports to start according to module parameters */
 	mdev->port_cnt = 0;
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH)
 		mdev->port_cnt++;
 
-	/* If we did not receive an explicit number of Rx rings, default to
-	 * the number of completion vectors populated by the mlx4_core */
 	mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_ETH) {
-		mlx4_info(mdev, "Using %d tx rings for port:%d\n",
-			  mdev->profile.prof[i].tx_ring_num, i);
-		mdev->profile.prof[i].rx_ring_num = min_t(int,
-			roundup_pow_of_two(dev->caps.num_comp_vectors),
-			MAX_RX_RINGS);
-		mlx4_info(mdev, "Defaulting to %d rx rings for port:%d\n",
-			  mdev->profile.prof[i].rx_ring_num, i);
+		if (!dev->caps.comp_pool) {
+			mdev->profile.prof[i].rx_ring_num =
+				rounddown_pow_of_two(max_t(int, MIN_RX_RINGS,
+							   min_t(int,
+								 dev->caps.num_comp_vectors,
+								 MAX_RX_RINGS)));
+		} else {
+			mdev->profile.prof[i].rx_ring_num = rounddown_pow_of_two(
+				min_t(int, dev->caps.comp_pool/
+				      dev->caps.num_ports - 1 , MAX_MSIX_P_PORT - 1));
+		}
 	}
 
 	/* Create our own workqueue for reset/multicast tasks
@@ -294,7 +296,7 @@
 	.remove		= mlx4_en_remove,
 	.event		= mlx4_en_event,
 	.get_dev	= mlx4_en_get_netdev,
-	.protocol	= MLX4_PROTOCOL_EN,
+	.protocol	= MLX4_PROT_ETH,
 };
 
 static int __init mlx4_en_init(void)
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_netdev.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_netdev.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_netdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_netdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -156,9 +156,8 @@
 	mutex_lock(&mdev->state_lock);
 	if (priv->port_up) {
 		/* Remove old MAC and insert the new one */
-		mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
-		err = mlx4_register_mac(mdev->dev, priv->port,
-					priv->mac, &priv->mac_index);
+		err = mlx4_replace_mac(mdev->dev, priv->port,
+				       priv->base_qpn, priv->mac, 0);
 		if (err)
 			en_err(priv, "Failed changing HW MAC address\n");
 	} else
@@ -214,6 +213,7 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 	struct net_device *dev = priv->dev;
 	u64 mcast_addr = 0;
+	u8 mc_list[16] = {0};
 	int err;
 
 	mutex_lock(&mdev->state_lock);
@@ -239,11 +239,15 @@
 			priv->flags |= MLX4_EN_FLAG_PROMISC;
 
 			/* Enable promiscouos mode */
-			err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
-						     priv->base_qpn, 1);
+			if (!mdev->dev->caps.vep_uc_steering)
+				err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
+							     priv->base_qpn, 1);
+			else
+				err = mlx4_unicast_promisc_add(mdev->dev, priv->base_qpn,
+							       priv->port);
 			if (err)
 				en_err(priv, "Failed enabling "
-					     "promiscous mode\n");
+					     "promiscuous mode\n");
 
 			/* Disable port multicast filter (unconditionally) */
 			err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
@@ -252,16 +256,27 @@
 				en_err(priv, "Failed disabling "
 					     "multicast filter\n");
 
-			/* Disable port VLAN filter */
-			err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
-			if (err)
-				en_err(priv, "Failed disabling VLAN filter\n");
+			/* Add the default qp number as multicast promisc */
+			if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
+				err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
+								 priv->port);
+				if (err)
+					en_err(priv, "Failed entering multicast promisc mode\n");
+				priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
+			}
+
+			if (priv->vlgrp) {
+				/* Disable port VLAN filter */
+				err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, NULL);
+				if (err)
+					en_err(priv, "Failed disabling VLAN filter\n");
+			}
 		}
 		goto out;
 	}
 
 	/*
-	 * Not in promiscous mode
+	 * Not in promiscuous mode
 	 */
 
 	if (priv->flags & MLX4_EN_FLAG_PROMISC) {
@@ -270,10 +285,23 @@
 		priv->flags &= ~MLX4_EN_FLAG_PROMISC;
 
 		/* Disable promiscouos mode */
-		err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
-					     priv->base_qpn, 0);
+		if (!mdev->dev->caps.vep_uc_steering)
+			err = mlx4_SET_PORT_qpn_calc(mdev->dev, priv->port,
+						     priv->base_qpn, 0);
+		else
+			err = mlx4_unicast_promisc_remove(mdev->dev, priv->base_qpn,
+							  priv->port);
 		if (err)
-			en_err(priv, "Failed disabling promiscous mode\n");
+			en_err(priv, "Failed disabling promiscuous mode\n");
+
+		/* Disable Multicast promisc */
+		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
+			err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
+							    priv->port);
+			if (err)
+				en_err(priv, "Failed disabling multicast promiscuous mode\n");
+			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
+		}
 
 		/* Enable port VLAN filter */
 		err = mlx4_SET_VLAN_FLTR(mdev->dev, priv->port, priv->vlgrp);
@@ -287,14 +315,38 @@
 					  0, MLX4_MCAST_DISABLE);
 		if (err)
 			en_err(priv, "Failed disabling multicast filter\n");
+
+		/* Add the default qp number as multicast promisc */
+		if (!(priv->flags & MLX4_EN_FLAG_MC_PROMISC)) {
+			err = mlx4_multicast_promisc_add(mdev->dev, priv->base_qpn,
+							 priv->port);
+			if (err)
+				en_err(priv, "Failed entering multicast promisc mode\n");
+			priv->flags |= MLX4_EN_FLAG_MC_PROMISC;
+		}
 	} else {
 		int i;
+		/* Disable Multicast promisc */
+		if (priv->flags & MLX4_EN_FLAG_MC_PROMISC) {
+			err = mlx4_multicast_promisc_remove(mdev->dev, priv->base_qpn,
+							    priv->port);
+			if (err)
+				en_err(priv, "Failed disabling multicast promiscuous mode\n");
+			priv->flags &= ~MLX4_EN_FLAG_MC_PROMISC;
+		}
 
 		err = mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0,
 					  0, MLX4_MCAST_DISABLE);
 		if (err)
 			en_err(priv, "Failed disabling multicast filter\n");
 
+		/* Detach our qp from all the multicast addresses */
+		for (i = 0; i < priv->mc_addrs_cnt; i++) {
+			memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
+			mc_list[5] = priv->port;
+			mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
+					      mc_list, MLX4_PROT_ETH);
+		}
 		/* Flush mcast filter and init it with broadcast address */
 		mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, ETH_BCAST,
 				    1, MLX4_MCAST_CONFIG);
@@ -307,6 +359,10 @@
 		for (i = 0; i < priv->mc_addrs_cnt; i++) {
 			mcast_addr =
 			      mlx4_en_mac_to_u64(priv->mc_addrs + i * ETH_ALEN);
+			memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
+			mc_list[5] = priv->port;
+			mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp,
+					      mc_list, 0, MLX4_PROT_ETH);
 			mlx4_SET_MCAST_FLTR(mdev->dev, priv->port,
 					    mcast_addr, 0, MLX4_MCAST_CONFIG);
 		}
@@ -314,8 +370,6 @@
 					  0, MLX4_MCAST_ENABLE);
 		if (err)
 			en_err(priv, "Failed enabling multicast filter\n");
-
-		mlx4_en_clear_list(dev);
 	}
 out:
 	mutex_unlock(&mdev->state_lock);
@@ -417,7 +471,6 @@
 	unsigned long avg_pkt_size;
 	unsigned long rx_packets;
 	unsigned long rx_bytes;
-	unsigned long rx_byte_diff;
 	unsigned long tx_packets;
 	unsigned long tx_pkt_diff;
 	unsigned long rx_pkt_diff;
@@ -441,25 +494,20 @@
 	rx_pkt_diff = ((unsigned long) (rx_packets -
 					priv->last_moder_packets));
 	packets = max(tx_pkt_diff, rx_pkt_diff);
-	rx_byte_diff = rx_bytes - priv->last_moder_bytes;
-	rx_byte_diff = rx_byte_diff ? rx_byte_diff : 1;
 	rate = packets * HZ / period;
 	avg_pkt_size = packets ? ((unsigned long) (rx_bytes -
 				 priv->last_moder_bytes)) / packets : 0;
 
 	/* Apply auto-moderation only when packet rate exceeds a rate that
 	 * it matters */
-	if (rate > MLX4_EN_RX_RATE_THRESH) {
+	if (rate > MLX4_EN_RX_RATE_THRESH && avg_pkt_size > MLX4_EN_AVG_PKT_SMALL) {
 		/* If tx and rx packet rates are not balanced, assume that
 		 * traffic is mainly BW bound and apply maximum moderation.
 		 * Otherwise, moderate according to packet rate */
-		if (2 * tx_pkt_diff > 3 * rx_pkt_diff &&
-		    rx_pkt_diff / rx_byte_diff <
-		    MLX4_EN_SMALL_PKT_SIZE)
-			moder_time = priv->rx_usecs_low;
-		else if (2 * rx_pkt_diff > 3 * tx_pkt_diff)
+		if (2 * tx_pkt_diff > 3 * rx_pkt_diff ||
+		    2 * rx_pkt_diff > 3 * tx_pkt_diff) {
 			moder_time = priv->rx_usecs_high;
-		else {
+		} else {
 			if (rate < priv->pkt_rate_low)
 				moder_time = priv->rx_usecs_low;
 			else if (rate > priv->pkt_rate_high)
@@ -471,9 +519,7 @@
 					priv->rx_usecs_low;
 		}
 	} else {
-		/* When packet rate is low, use default moderation rather than
-		 * 0 to prevent interrupt storms if traffic suddenly increases */
-		moder_time = priv->rx_usecs;
+		moder_time = priv->rx_usecs_low;
 	}
 
 	en_dbg(INTR, priv, "tx rate:%lu rx_rate:%lu\n",
@@ -565,6 +611,8 @@
 	int err = 0;
 	int i;
 	int j;
+	u8 mc_list[16] = {0};
+	char name[32];
 
 	if (priv->port_up) {
 		en_dbg(DRV, priv, "start port called while port already up\n");
@@ -603,16 +651,35 @@
 		++rx_index;
 	}
 
+	/* Set port mac number */
+	en_dbg(DRV, priv, "Setting mac for port %d\n", priv->port);
+	err = mlx4_register_mac(mdev->dev, priv->port,
+				priv->mac, &priv->base_qpn, 0);
+	if (err) {
+		en_err(priv, "Failed setting port mac\n");
+		goto cq_err;
+	}
+	mdev->mac_removed[priv->port] = 0;
+
 	err = mlx4_en_config_rss_steer(priv);
 	if (err) {
 		en_err(priv, "Failed configuring rss steering\n");
-		goto cq_err;
+		goto mac_err;
 	}
 
+	if (mdev->dev->caps.comp_pool && !priv->tx_vector) {
+		sprintf(name , "%s-tx", priv->dev->name);
+		if (mlx4_assign_eq(mdev->dev , name, &priv->tx_vector)) {
+			mlx4_warn(mdev, "Failed Assigning an EQ to "
+					"%s_tx ,Falling back to legacy "
+					"EQ's\n", priv->dev->name);
+		}
+	}
 	/* Configure tx cq's and rings */
 	for (i = 0; i < priv->tx_ring_num; i++) {
 		/* Configure cq */
 		cq = &priv->tx_cq[i];
+		cq->vector = priv->tx_vector;
 		err = mlx4_en_activate_cq(priv, cq);
 		if (err) {
 			en_err(priv, "Failed allocating Tx CQ\n");
@@ -659,24 +726,25 @@
 		en_err(priv, "Failed setting default qp numbers\n");
 		goto tx_err;
 	}
-	/* Set port mac number */
-	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) {
-		en_err(priv, "Failed setting port mac\n");
-		goto tx_err;
-	}
-	mdev->mac_removed[priv->port] = 0;
 
 	/* Init port */
 	en_dbg(HW, priv, "Initializing port\n");
 	err = mlx4_INIT_PORT(mdev->dev, priv->port);
 	if (err) {
 		en_err(priv, "Failed Initializing port\n");
-		goto mac_err;
+		goto tx_err;
 	}
 
+	/* Attach rx QP to bradcast address */
+	memset(&mc_list[10], 0xff, ETH_ALEN);
+	mc_list[5] = priv->port;
+	if (mlx4_multicast_attach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
+				  0, MLX4_PROT_ETH))
+		mlx4_warn(mdev, "Failed Attaching Broadcast\n");
+
+	/* Must redo promiscuous mode setup. */
+	priv->flags &= ~(MLX4_EN_FLAG_PROMISC | MLX4_EN_FLAG_MC_PROMISC);
+
 	/* Schedule multicast task to populate multicast list */
 	queue_work(mdev->workqueue, &priv->mcast_task);
 
@@ -684,8 +752,6 @@
 	netif_tx_start_all_queues(dev);
 	return 0;
 
-mac_err:
-	mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
 tx_err:
 	while (tx_index--) {
 		mlx4_en_deactivate_tx_ring(priv, &priv->tx_ring[tx_index]);
@@ -693,6 +759,8 @@
 	}
 
 	mlx4_en_release_rss_steer(priv);
+mac_err:
+	mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
 cq_err:
 	while (rx_index--)
 		mlx4_en_deactivate_cq(priv, &priv->rx_cq[rx_index]);
@@ -708,6 +776,7 @@
 	struct mlx4_en_priv *priv = netdev_priv(dev);
 	struct mlx4_en_dev *mdev = priv->mdev;
 	int i;
+	u8 mc_list[16] = {0};
 
 	if (!priv->port_up) {
 		en_dbg(DRV, priv, "stop port called while port already down\n");
@@ -722,8 +791,23 @@
 	/* Set port as not active */
 	priv->port_up = false;
 
+	/* Detach All multicasts */
+	memset(&mc_list[10], 0xff, ETH_ALEN);
+	mc_list[5] = priv->port;
+	mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp, mc_list,
+			      MLX4_PROT_ETH);
+	for (i = 0; i < priv->mc_addrs_cnt; i++) {
+		memcpy(&mc_list[10], priv->mc_addrs + i * ETH_ALEN, ETH_ALEN);
+		mc_list[5] = priv->port;
+		mlx4_multicast_detach(mdev->dev, &priv->rss_map.indir_qp,
+				      mc_list, MLX4_PROT_ETH);
+	}
+	mlx4_en_clear_list(dev);
+	/* Flush multicast filter */
+	mlx4_SET_MCAST_FLTR(mdev->dev, priv->port, 0, 1, MLX4_MCAST_CONFIG);
+
 	/* Unregister Mac address for the port */
-	mlx4_unregister_mac(mdev->dev, priv->port, priv->mac_index);
+	mlx4_unregister_mac(mdev->dev, priv->port, priv->base_qpn);
 	mdev->mac_removed[priv->port] = 1;
 
 	/* Free TX Rings */
@@ -801,7 +885,6 @@
 		priv->rx_ring[i].packets = 0;
 	}
 
-	mlx4_en_set_default_moderation(priv);
 	err = mlx4_en_start_port(dev);
 	if (err)
 		en_err(priv, "Failed starting port:%d\n", priv->port);
@@ -828,7 +911,7 @@
 	return 0;
 }
 
-void mlx4_en_free_resources(struct mlx4_en_priv *priv)
+void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors)
 {
 	int i;
 
@@ -836,14 +919,14 @@
 		if (priv->tx_ring[i].tx_info)
 			mlx4_en_destroy_tx_ring(priv, &priv->tx_ring[i]);
 		if (priv->tx_cq[i].buf)
-			mlx4_en_destroy_cq(priv, &priv->tx_cq[i]);
+			mlx4_en_destroy_cq(priv, &priv->tx_cq[i], reserve_vectors);
 	}
 
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		if (priv->rx_ring[i].rx_info)
 			mlx4_en_destroy_rx_ring(priv, &priv->rx_ring[i]);
 		if (priv->rx_cq[i].buf)
-			mlx4_en_destroy_cq(priv, &priv->rx_cq[i]);
+			mlx4_en_destroy_cq(priv, &priv->rx_cq[i], reserve_vectors);
 	}
 }
 
@@ -851,6 +934,13 @@
 {
 	struct mlx4_en_port_profile *prof = priv->prof;
 	int i;
+	int base_tx_qpn, err;
+
+	err = mlx4_qp_reserve_range(priv->mdev->dev, priv->tx_ring_num, 256, &base_tx_qpn);
+	if (err) {
+		en_err(priv, "failed reserving range for TX rings\n");
+		return err;
+	}
 
 	/* Create tx Rings */
 	for (i = 0; i < priv->tx_ring_num; i++) {
@@ -858,7 +948,7 @@
 				      prof->tx_ring_size, i, TX))
 			goto err;
 
-		if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i],
+		if (mlx4_en_create_tx_ring(priv, &priv->tx_ring[i], base_tx_qpn + i,
 					   prof->tx_ring_size, TXBB_SIZE))
 			goto err;
 	}
@@ -878,6 +968,7 @@
 
 err:
 	en_err(priv, "Failed to allocate NIC resources\n");
+	mlx4_qp_release_range(priv->mdev->dev, base_tx_qpn, priv->tx_ring_num);
 	return -ENOMEM;
 }
 
@@ -905,7 +996,7 @@
 	mdev->pndev[priv->port] = NULL;
 	mutex_unlock(&mdev->state_lock);
 
-	mlx4_en_free_resources(priv);
+	mlx4_en_free_resources(priv, false);
 	free_netdev(dev);
 }
 
@@ -932,7 +1023,6 @@
 			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) {
 				en_err(priv, "Failed restarting port:%d\n",
@@ -1079,7 +1169,25 @@
 	en_warn(priv, "Using %d TX rings\n", prof->tx_ring_num);
 	en_warn(priv, "Using %d RX rings\n", prof->rx_ring_num);
 
+	/* Configure port */
+	err = mlx4_SET_PORT_general(mdev->dev, priv->port,
+				    MLX4_EN_MIN_MTU,
+				    0, 0, 0, 0);
+	if (err) {
+		en_err(priv, "Failed setting port general configurations "
+		       "for port %d, with error %d\n", priv->port, err);
+		goto out;
+	}
+
+	/* Init port */
+	en_warn(priv, "Initializing port\n");
+	err = mlx4_INIT_PORT(mdev->dev, priv->port);
+	if (err) {
+		en_err(priv, "Failed Initializing port\n");
+		goto out;
+	}
 	priv->registered = 1;
+	mlx4_en_set_default_moderation(priv);
 	queue_delayed_work(mdev->workqueue, &priv->stats_task, STATS_DELAY);
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_port.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_port.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_port.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_port.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,6 +119,10 @@
 	struct mlx4_set_port_rqp_calc_context *context;
 	int err;
 	u32 in_mod;
+	u32 m_promisc = (dev->caps.vep_mc_steering) ? MCAST_DIRECT : MCAST_DEFAULT;
+
+	if (dev->caps.vep_mc_steering && dev->caps.vep_uc_steering)
+		return 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -127,8 +131,11 @@
 	memset(context, 0, sizeof *context);
 
 	context->base_qpn = cpu_to_be32(base_qpn);
-	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_EN_SHIFT | base_qpn);
-	context->mcast = cpu_to_be32(1 << SET_PORT_PROMISC_MODE_SHIFT | base_qpn);
+	context->n_mac = 0x7;
+	context->promisc = cpu_to_be32(promisc << SET_PORT_PROMISC_SHIFT |
+				       base_qpn);
+	context->mcast = cpu_to_be32(m_promisc << SET_PORT_MC_PROMISC_SHIFT |
+				     base_qpn);
 	context->intra_no_vlan = 0;
 	context->no_vlan = MLX4_NO_VLAN_IDX;
 	context->intra_vlan_miss = 0;
@@ -206,7 +213,7 @@
 	}
 	stats->tx_packets = 0;
 	stats->tx_bytes = 0;
-	for (i = 0; i <= priv->tx_ring_num; i++) {
+	for (i = 0; i < priv->tx_ring_num; i++) {
 		stats->tx_packets += priv->tx_ring[i].packets;
 		stats->tx_bytes += priv->tx_ring[i].bytes;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_port.h linux-libre-2.6.39-gnu/drivers/net/mlx4/en_port.h
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_port.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_port.h	2011-05-19 00:06:34.000000000 -0400
@@ -36,8 +36,8 @@
 
 
 #define SET_PORT_GEN_ALL_VALID	0x7
-#define SET_PORT_PROMISC_EN_SHIFT	31
-#define SET_PORT_PROMISC_MODE_SHIFT	30
+#define SET_PORT_PROMISC_SHIFT	31
+#define SET_PORT_MC_PROMISC_SHIFT	30
 
 enum {
 	MLX4_CMD_SET_VLAN_FLTR  = 0x47,
@@ -45,6 +45,12 @@
 	MLX4_CMD_DUMP_ETH_STATS = 0x49,
 };
 
+enum {
+	MCAST_DIRECT_ONLY       = 0,
+	MCAST_DIRECT            = 1,
+	MCAST_DEFAULT           = 2
+};
+
 struct mlx4_set_port_general_context {
 	u8 reserved[3];
 	u8 flags;
@@ -60,14 +66,17 @@
 
 struct mlx4_set_port_rqp_calc_context {
 	__be32 base_qpn;
-	__be32 flags;
-	u8 reserved[3];
+	u8 rererved;
+	u8 n_mac;
+	u8 n_vlan;
+	u8 n_prio;
+	u8 reserved2[3];
 	u8 mac_miss;
 	u8 intra_no_vlan;
 	u8 no_vlan;
 	u8 intra_vlan_miss;
 	u8 vlan_miss;
-	u8 reserved2[3];
+	u8 reserved3[3];
 	u8 no_vlan_prio;
 	__be32 promisc;
 	__be32 mcast;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_rx.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_rx.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -345,6 +345,8 @@
 		err = mlx4_en_init_allocator(priv, ring);
 		if (err) {
 			en_err(priv, "Failed initializing ring allocator\n");
+			if (ring->stride <= TXBB_SIZE)
+				ring->buf -= TXBB_SIZE;
 			ring_ind--;
 			goto err_allocator;
 		}
@@ -369,6 +371,8 @@
 	ring_ind = priv->rx_ring_num - 1;
 err_allocator:
 	while (ring_ind >= 0) {
+		if (priv->rx_ring[ring_ind].stride <= TXBB_SIZE)
+			priv->rx_ring[ring_ind].buf -= TXBB_SIZE;
 		mlx4_en_destroy_allocator(priv, &priv->rx_ring[ring_ind]);
 		ring_ind--;
 	}
@@ -706,7 +710,7 @@
 }
 
 
-/* Calculate the last offset position that accomodates a full fragment
+/* Calculate the last offset position that accommodates a full fragment
  * (assuming fagment size = stride-align) */
 static int mlx4_en_last_alloc_offset(struct mlx4_en_priv *priv, u16 stride, u16 align)
 {
@@ -845,16 +849,10 @@
 	}
 
 	/* Configure RSS indirection qp */
-	err = mlx4_qp_reserve_range(mdev->dev, 1, 1, &priv->base_qpn);
-	if (err) {
-		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) {
 		en_err(priv, "Failed to allocate RSS indirection QP\n");
-		goto reserve_err;
+		goto rss_err;
 	}
 	rss_map->indir_qp.event = mlx4_en_sqp_event;
 	mlx4_en_fill_qp_context(priv, 0, 0, 0, 1, priv->base_qpn,
@@ -881,8 +879,6 @@
 		       MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
 	mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
 	mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
-reserve_err:
-	mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
 rss_err:
 	for (i = 0; i < good_qps; i++) {
 		mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
@@ -904,7 +900,6 @@
 		       MLX4_QP_STATE_RST, NULL, 0, 0, &rss_map->indir_qp);
 	mlx4_qp_remove(mdev->dev, &rss_map->indir_qp);
 	mlx4_qp_free(mdev->dev, &rss_map->indir_qp);
-	mlx4_qp_release_range(mdev->dev, priv->base_qpn, 1);
 
 	for (i = 0; i < priv->rx_ring_num; i++) {
 		mlx4_qp_modify(mdev->dev, NULL, rss_map->state[i],
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_selftest.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_selftest.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_selftest.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_selftest.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
 
 		netif_carrier_off(dev);
 retry_tx:
-		/* Wait untill all tx queues are empty.
+		/* Wait until all tx queues are empty.
 		 * there should not be any additional incoming traffic
 		 * since we turned the carrier off */
 		msleep(200);
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/en_tx.c linux-libre-2.6.39-gnu/drivers/net/mlx4/en_tx.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/en_tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/en_tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,6 +44,7 @@
 
 enum {
 	MAX_INLINE = 104, /* 128 - 16 - 4 - 4 */
+	MAX_BF = 256,
 };
 
 static int inline_thold __read_mostly = MAX_INLINE;
@@ -52,7 +53,7 @@
 MODULE_PARM_DESC(inline_thold, "threshold for using inline data");
 
 int mlx4_en_create_tx_ring(struct mlx4_en_priv *priv,
-			   struct mlx4_en_tx_ring *ring, u32 size,
+			   struct mlx4_en_tx_ring *ring, int qpn, u32 size,
 			   u16 stride)
 {
 	struct mlx4_en_dev *mdev = priv->mdev;
@@ -103,23 +104,25 @@
 	       "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) {
-		en_err(priv, "Failed reserving qp for tx ring.\n");
-		goto err_map;
-	}
-
+	ring->qpn = qpn;
 	err = mlx4_qp_alloc(mdev->dev, ring->qpn, &ring->qp);
 	if (err) {
 		en_err(priv, "Failed allocating qp %d\n", ring->qpn);
-		goto err_reserve;
+		goto err_map;
 	}
 	ring->qp.event = mlx4_en_sqp_event;
 
+	err = mlx4_bf_alloc(mdev->dev, &ring->bf);
+	if (err) {
+		en_dbg(DRV, priv, "working without blueflame (%d)", err);
+		ring->bf.uar = &mdev->priv_uar;
+		ring->bf.uar->map = mdev->uar_map;
+		ring->bf_enabled = false;
+	} else
+		ring->bf_enabled = true;
+
 	return 0;
 
-err_reserve:
-	mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
 err_map:
 	mlx4_en_unmap_buffer(&ring->wqres.buf);
 err_hwq_res:
@@ -139,6 +142,8 @@
 	struct mlx4_en_dev *mdev = priv->mdev;
 	en_dbg(DRV, priv, "Destroying tx ring, qpn: %d\n", ring->qpn);
 
+	if (ring->bf_enabled)
+		mlx4_bf_free(mdev->dev, &ring->bf);
 	mlx4_qp_remove(mdev->dev, &ring->qp);
 	mlx4_qp_free(mdev->dev, &ring->qp);
 	mlx4_qp_release_range(mdev->dev, ring->qpn, 1);
@@ -171,6 +176,8 @@
 
 	mlx4_en_fill_qp_context(priv, ring->size, ring->stride, 1, 0, ring->qpn,
 				ring->cqn, &ring->context);
+	if (ring->bf_enabled)
+		ring->context.usr_page = cpu_to_be32(ring->bf.uar->index);
 
 	err = mlx4_qp_to_ready(mdev->dev, &ring->wqres.mtt, &ring->context,
 			       &ring->qp, &ring->qp_state);
@@ -591,6 +598,11 @@
 	return skb_tx_hash(dev, skb);
 }
 
+static void mlx4_bf_copy(unsigned long *dst, unsigned long *src, unsigned bytecnt)
+{
+	__iowrite64_copy(dst, src, bytecnt / 8);
+}
+
 netdev_tx_t mlx4_en_xmit(struct sk_buff *skb, struct net_device *dev)
 {
 	struct mlx4_en_priv *priv = netdev_priv(dev);
@@ -609,12 +621,13 @@
 	int desc_size;
 	int real_size;
 	dma_addr_t dma;
-	u32 index;
+	u32 index, bf_index;
 	__be32 op_own;
 	u16 vlan_tag = 0;
 	int i;
 	int lso_header_size;
 	void *fragptr;
+	bool bounce = false;
 
 	if (!priv->port_up)
 		goto tx_drop;
@@ -623,7 +636,7 @@
 	if (unlikely(!real_size))
 		goto tx_drop;
 
-	/* Allign descriptor to TXBB size */
+	/* Align descriptor to TXBB size */
 	desc_size = ALIGN(real_size, TXBB_SIZE);
 	nr_txbb = desc_size / TXBB_SIZE;
 	if (unlikely(nr_txbb > MAX_DESC_TXBBS)) {
@@ -657,13 +670,16 @@
 
 	/* Packet is good - grab an index and transmit it */
 	index = ring->prod & ring->size_mask;
+	bf_index = ring->prod;
 
 	/* See if we have enough space for whole descriptor TXBB for setting
 	 * SW ownership on next descriptor; if not, use a bounce buffer. */
 	if (likely(index + nr_txbb <= ring->size))
 		tx_desc = ring->buf + index * TXBB_SIZE;
-	else
+	else {
 		tx_desc = (struct mlx4_en_tx_desc *) ring->bounce_buf;
+		bounce = true;
+	}
 
 	/* Save skb in tx_info ring */
 	tx_info = &ring->tx_info[index];
@@ -768,21 +784,37 @@
 	ring->prod += nr_txbb;
 
 	/* If we used a bounce buffer then copy descriptor back into place */
-	if (tx_desc == (struct mlx4_en_tx_desc *) ring->bounce_buf)
+	if (bounce)
 		tx_desc = mlx4_en_bounce_to_desc(priv, ring, index, desc_size);
 
 	/* Run destructor before passing skb to HW */
 	if (likely(!skb_shared(skb)))
 		skb_orphan(skb);
 
-	/* Ensure new descirptor hits memory
-	 * before setting ownership of this descriptor to HW */
-	wmb();
-	tx_desc->ctrl.owner_opcode = op_own;
+	if (ring->bf_enabled && desc_size <= MAX_BF && !bounce && !vlan_tag) {
+		*(u32 *) (&tx_desc->ctrl.vlan_tag) |= ring->doorbell_qpn;
+		op_own |= htonl((bf_index & 0xffff) << 8);
+		/* Ensure new descirptor hits memory
+		* before setting ownership of this descriptor to HW */
+		wmb();
+		tx_desc->ctrl.owner_opcode = op_own;
 
-	/* Ring doorbell! */
-	wmb();
-	writel(ring->doorbell_qpn, mdev->uar_map + MLX4_SEND_DOORBELL);
+		wmb();
+
+		mlx4_bf_copy(ring->bf.reg + ring->bf.offset, (unsigned long *) &tx_desc->ctrl,
+		     desc_size);
+
+		wmb();
+
+		ring->bf.offset ^= ring->bf.buf_size;
+	} else {
+		/* Ensure new descirptor hits memory
+		* before setting ownership of this descriptor to HW */
+		wmb();
+		tx_desc->ctrl.owner_opcode = op_own;
+		wmb();
+		writel(ring->doorbell_qpn, ring->bf.uar->map + MLX4_SEND_DOORBELL);
+	}
 
 	/* Poll CQ here */
 	mlx4_en_xmit_poll(priv, tx_ind);
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/eq.c linux-libre-2.6.39-gnu/drivers/net/mlx4/eq.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/eq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/eq.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,7 @@
 #include "fw.h"
 
 enum {
-	MLX4_IRQNAME_SIZE	= 64
+	MLX4_IRQNAME_SIZE	= 32
 };
 
 enum {
@@ -317,8 +317,8 @@
 	 * we need to map, take the difference of highest index and
 	 * the lowest index we'll use and add 1.
 	 */
-	return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs) / 4 -
-		dev->caps.reserved_eqs / 4 + 1;
+	return (dev->caps.num_comp_vectors + 1 + dev->caps.reserved_eqs +
+		 dev->caps.comp_pool)/4 - dev->caps.reserved_eqs/4 + 1;
 }
 
 static void __iomem *mlx4_get_eq_uar(struct mlx4_dev *dev, struct mlx4_eq *eq)
@@ -496,16 +496,32 @@
 static void mlx4_free_irqs(struct mlx4_dev *dev)
 {
 	struct mlx4_eq_table *eq_table = &mlx4_priv(dev)->eq_table;
-	int i;
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int	i, vec;
 
 	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) {
 			free_irq(eq_table->eq[i].irq, eq_table->eq + i);
 			eq_table->eq[i].have_irq = 0;
 		}
 
+	for (i = 0; i < dev->caps.comp_pool; i++) {
+		/*
+		 * Freeing the assigned irq's
+		 * all bits should be 0, but we need to validate
+		 */
+		if (priv->msix_ctl.pool_bm & 1ULL << i) {
+			/* NO need protecting*/
+			vec = dev->caps.num_comp_vectors + 1 + i;
+			free_irq(priv->eq_table.eq[vec].irq,
+				 &priv->eq_table.eq[vec]);
+		}
+	}
+
+
 	kfree(eq_table->irq_names);
 }
 
@@ -578,7 +594,8 @@
 		(priv->eq_table.inta_pin < 32 ? 4 : 0);
 
 	priv->eq_table.irq_names =
-		kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1),
+		kmalloc(MLX4_IRQNAME_SIZE * (dev->caps.num_comp_vectors + 1 +
+					     dev->caps.comp_pool),
 			GFP_KERNEL);
 	if (!priv->eq_table.irq_names) {
 		err = -ENOMEM;
@@ -586,7 +603,9 @@
 	}
 
 	for (i = 0; i < dev->caps.num_comp_vectors; ++i) {
-		err = mlx4_create_eq(dev, dev->caps.num_cqs + MLX4_NUM_SPARE_EQE,
+		err = mlx4_create_eq(dev, dev->caps.num_cqs -
+					  dev->caps.reserved_cqs +
+					  MLX4_NUM_SPARE_EQE,
 				     (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
 				     &priv->eq_table.eq[i]);
 		if (err) {
@@ -601,6 +620,22 @@
 	if (err)
 		goto err_out_comp;
 
+	/*if additional completion vectors poolsize is 0 this loop will not run*/
+	for (i = dev->caps.num_comp_vectors + 1;
+	      i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i) {
+
+		err = mlx4_create_eq(dev, dev->caps.num_cqs -
+					  dev->caps.reserved_cqs +
+					  MLX4_NUM_SPARE_EQE,
+				     (dev->flags & MLX4_FLAG_MSI_X) ? i : 0,
+				     &priv->eq_table.eq[i]);
+		if (err) {
+			--i;
+			goto err_out_unmap;
+		}
+	}
+
+
 	if (dev->flags & MLX4_FLAG_MSI_X) {
 		const char *eq_name;
 
@@ -686,7 +721,7 @@
 
 	mlx4_free_irqs(dev);
 
-	for (i = 0; i < dev->caps.num_comp_vectors + 1; ++i)
+	for (i = 0; i < dev->caps.num_comp_vectors + dev->caps.comp_pool + 1; ++i)
 		mlx4_free_eq(dev, &priv->eq_table.eq[i]);
 
 	mlx4_unmap_clr_int(dev);
@@ -743,3 +778,65 @@
 	return err;
 }
 EXPORT_SYMBOL(mlx4_test_interrupts);
+
+int mlx4_assign_eq(struct mlx4_dev *dev, char* name, int * vector)
+{
+
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int vec = 0, err = 0, i;
+
+	spin_lock(&priv->msix_ctl.pool_lock);
+	for (i = 0; !vec && i < dev->caps.comp_pool; i++) {
+		if (~priv->msix_ctl.pool_bm & 1ULL << i) {
+			priv->msix_ctl.pool_bm |= 1ULL << i;
+			vec = dev->caps.num_comp_vectors + 1 + i;
+			snprintf(priv->eq_table.irq_names +
+					vec * MLX4_IRQNAME_SIZE,
+					MLX4_IRQNAME_SIZE, "%s", name);
+			err = request_irq(priv->eq_table.eq[vec].irq,
+					  mlx4_msi_x_interrupt, 0,
+					  &priv->eq_table.irq_names[vec<<5],
+					  priv->eq_table.eq + vec);
+			if (err) {
+				/*zero out bit by fliping it*/
+				priv->msix_ctl.pool_bm ^= 1 << i;
+				vec = 0;
+				continue;
+				/*we dont want to break here*/
+			}
+			eq_set_ci(&priv->eq_table.eq[vec], 1);
+		}
+	}
+	spin_unlock(&priv->msix_ctl.pool_lock);
+
+	if (vec) {
+		*vector = vec;
+	} else {
+		*vector = 0;
+		err = (i == dev->caps.comp_pool) ? -ENOSPC : err;
+	}
+	return err;
+}
+EXPORT_SYMBOL(mlx4_assign_eq);
+
+void mlx4_release_eq(struct mlx4_dev *dev, int vec)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	/*bm index*/
+	int i = vec - dev->caps.num_comp_vectors - 1;
+
+	if (likely(i >= 0)) {
+		/*sanity check , making sure were not trying to free irq's
+		  Belonging to a legacy EQ*/
+		spin_lock(&priv->msix_ctl.pool_lock);
+		if (priv->msix_ctl.pool_bm & 1ULL << i) {
+			free_irq(priv->eq_table.eq[vec].irq,
+				 &priv->eq_table.eq[vec]);
+			priv->msix_ctl.pool_bm &= ~(1ULL << i);
+		}
+		spin_unlock(&priv->msix_ctl.pool_lock);
+	}
+
+}
+EXPORT_SYMBOL(mlx4_release_eq);
+
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/fw.c linux-libre-2.6.39-gnu/drivers/net/mlx4/fw.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/fw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/fw.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,8 +274,11 @@
 	dev_cap->stat_rate_support = stat_rate;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_UDP_RSS_OFFSET);
 	dev_cap->udp_rss = field & 0x1;
+	dev_cap->vep_uc_steering = field & 0x2;
+	dev_cap->vep_mc_steering = field & 0x4;
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_ETH_UC_LOOPBACK_OFFSET);
 	dev_cap->loopback_support = field & 0x1;
+	dev_cap->wol = field & 0x40;
 	MLX4_GET(dev_cap->flags, outbox, QUERY_DEV_CAP_FLAGS_OFFSET);
 	MLX4_GET(field, outbox, QUERY_DEV_CAP_RSVD_UAR_OFFSET);
 	dev_cap->reserved_uars = field >> 4;
@@ -737,6 +740,7 @@
 #define	 INIT_HCA_MC_BASE_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x00)
 #define	 INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x12)
 #define	 INIT_HCA_LOG_MC_HASH_SZ_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x16)
+#define  INIT_HCA_UC_STEERING_OFFSET	 (INIT_HCA_MCAST_OFFSET + 0x18)
 #define	 INIT_HCA_LOG_MC_TABLE_SZ_OFFSET (INIT_HCA_MCAST_OFFSET + 0x1b)
 #define INIT_HCA_TPT_OFFSET		 0x0f0
 #define	 INIT_HCA_DMPT_BASE_OFFSET	 (INIT_HCA_TPT_OFFSET + 0x00)
@@ -797,6 +801,8 @@
 	MLX4_PUT(inbox, param->mc_base,		INIT_HCA_MC_BASE_OFFSET);
 	MLX4_PUT(inbox, param->log_mc_entry_sz, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
 	MLX4_PUT(inbox, param->log_mc_hash_sz,  INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+	if (dev->caps.vep_mc_steering)
+		MLX4_PUT(inbox, (u8) (1 << 3),	INIT_HCA_UC_STEERING_OFFSET);
 	MLX4_PUT(inbox, param->log_mc_table_sz, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
 
 	/* TPT attributes */
@@ -908,3 +914,22 @@
 	/* Input modifier of 0x1f means "finish as soon as possible." */
 	return mlx4_cmd(dev, 0, 0x1f, 0, MLX4_CMD_NOP, 100);
 }
+
+#define MLX4_WOL_SETUP_MODE (5 << 28)
+int mlx4_wol_read(struct mlx4_dev *dev, u64 *config, int port)
+{
+	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
+
+	return mlx4_cmd_imm(dev, 0, config, in_mod, 0x3,
+			    MLX4_CMD_MOD_STAT_CFG, MLX4_CMD_TIME_CLASS_A);
+}
+EXPORT_SYMBOL_GPL(mlx4_wol_read);
+
+int mlx4_wol_write(struct mlx4_dev *dev, u64 config, int port)
+{
+	u32 in_mod = MLX4_WOL_SETUP_MODE | port << 8;
+
+	return mlx4_cmd(dev, config, in_mod, 0x1, MLX4_CMD_MOD_STAT_CFG,
+					MLX4_CMD_TIME_CLASS_A);
+}
+EXPORT_SYMBOL_GPL(mlx4_wol_write);
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/fw.h linux-libre-2.6.39-gnu/drivers/net/mlx4/fw.h
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/fw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/fw.h	2011-05-19 00:06:34.000000000 -0400
@@ -80,6 +80,9 @@
 	u16 stat_rate_support;
 	int udp_rss;
 	int loopback_support;
+	int vep_uc_steering;
+	int vep_mc_steering;
+	int wol;
 	u32 flags;
 	int reserved_uars;
 	int uar_size;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/main.c linux-libre-2.6.39-gnu/drivers/net/mlx4/main.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/slab.h>
+#include <linux/io-mapping.h>
 
 #include <linux/mlx4/device.h>
 #include <linux/mlx4/doorbell.h>
@@ -227,6 +228,9 @@
 	dev->caps.stat_rate_support  = dev_cap->stat_rate_support;
 	dev->caps.udp_rss	     = dev_cap->udp_rss;
 	dev->caps.loopback_support   = dev_cap->loopback_support;
+	dev->caps.vep_uc_steering    = dev_cap->vep_uc_steering;
+	dev->caps.vep_mc_steering    = dev_cap->vep_mc_steering;
+	dev->caps.wol		     = dev_cap->wol;
 	dev->caps.max_gso_sz	     = dev_cap->max_gso_sz;
 
 	dev->caps.log_num_macs  = log_num_mac;
@@ -718,8 +722,31 @@
 	mlx4_free_icm(dev, priv->fw.aux_icm, 0);
 }
 
+static int map_bf_area(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	resource_size_t bf_start;
+	resource_size_t bf_len;
+	int err = 0;
+
+	bf_start = pci_resource_start(dev->pdev, 2) + (dev->caps.num_uars << PAGE_SHIFT);
+	bf_len = pci_resource_len(dev->pdev, 2) - (dev->caps.num_uars << PAGE_SHIFT);
+	priv->bf_mapping = io_mapping_create_wc(bf_start, bf_len);
+	if (!priv->bf_mapping)
+		err = -ENOMEM;
+
+	return err;
+}
+
+static void unmap_bf_area(struct mlx4_dev *dev)
+{
+	if (mlx4_priv(dev)->bf_mapping)
+		io_mapping_free(mlx4_priv(dev)->bf_mapping);
+}
+
 static void mlx4_close_hca(struct mlx4_dev *dev)
 {
+	unmap_bf_area(dev);
 	mlx4_CLOSE_HCA(dev, 0);
 	mlx4_free_icms(dev);
 	mlx4_UNMAP_FA(dev);
@@ -772,6 +799,9 @@
 		goto err_stop_fw;
 	}
 
+	if (map_bf_area(dev))
+		mlx4_dbg(dev, "Failed to map blue flame area\n");
+
 	init_hca.log_uar_sz = ilog2(dev->caps.num_uars);
 
 	err = mlx4_init_icm(dev, &dev_cap, &init_hca, icm_size);
@@ -802,6 +832,7 @@
 	mlx4_free_icms(dev);
 
 err_stop_fw:
+	unmap_bf_area(dev);
 	mlx4_UNMAP_FA(dev);
 	mlx4_free_icm(dev, priv->fw.fw_icm, 0);
 
@@ -913,6 +944,10 @@
 	}
 
 	for (port = 1; port <= dev->caps.num_ports; port++) {
+		enum mlx4_port_type port_type = 0;
+		mlx4_SENSE_PORT(dev, port, &port_type);
+		if (port_type)
+			dev->caps.port_type[port] = port_type;
 		ib_port_default_caps = 0;
 		err = mlx4_get_port_ib_caps(dev, port, &ib_port_default_caps);
 		if (err)
@@ -927,6 +962,7 @@
 			goto err_mcg_table_free;
 		}
 	}
+	mlx4_set_port_mask(dev);
 
 	return 0;
 
@@ -969,13 +1005,15 @@
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct msix_entry *entries;
-	int nreq;
+	int nreq = min_t(int, dev->caps.num_ports *
+			 min_t(int, num_online_cpus() + 1, MAX_MSIX_P_PORT)
+				+ MSIX_LEGACY_SZ, MAX_MSIX);
 	int err;
 	int i;
 
 	if (msi_x) {
 		nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
-			     num_possible_cpus() + 1);
+			     nreq);
 		entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
 		if (!entries)
 			goto no_msi;
@@ -998,7 +1036,15 @@
 			goto no_msi;
 		}
 
-		dev->caps.num_comp_vectors = nreq - 1;
+		if (nreq <
+		    MSIX_LEGACY_SZ + dev->caps.num_ports * MIN_MSIX_P_PORT) {
+			/*Working in legacy mode , all EQ's shared*/
+			dev->caps.comp_pool           = 0;
+			dev->caps.num_comp_vectors = nreq - 1;
+		} else {
+			dev->caps.comp_pool           = nreq - MSIX_LEGACY_SZ;
+			dev->caps.num_comp_vectors = MSIX_LEGACY_SZ - 1;
+		}
 		for (i = 0; i < nreq; ++i)
 			priv->eq_table.eq[i].irq = entries[i].vector;
 
@@ -1010,6 +1056,7 @@
 
 no_msi:
 	dev->caps.num_comp_vectors = 1;
+	dev->caps.comp_pool	   = 0;
 
 	for (i = 0; i < 2; ++i)
 		priv->eq_table.eq[i].irq = dev->pdev->irq;
@@ -1049,6 +1096,59 @@
 	device_remove_file(&info->dev->pdev->dev, &info->port_attr);
 }
 
+static int mlx4_init_steering(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int num_entries = dev->caps.num_ports;
+	int i, j;
+
+	priv->steer = kzalloc(sizeof(struct mlx4_steer) * num_entries, GFP_KERNEL);
+	if (!priv->steer)
+		return -ENOMEM;
+
+	for (i = 0; i < num_entries; i++) {
+		for (j = 0; j < MLX4_NUM_STEERS; j++) {
+			INIT_LIST_HEAD(&priv->steer[i].promisc_qps[j]);
+			INIT_LIST_HEAD(&priv->steer[i].steer_entries[j]);
+		}
+		INIT_LIST_HEAD(&priv->steer[i].high_prios);
+	}
+	return 0;
+}
+
+static void mlx4_clear_steering(struct mlx4_dev *dev)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	struct mlx4_steer_index *entry, *tmp_entry;
+	struct mlx4_promisc_qp *pqp, *tmp_pqp;
+	int num_entries = dev->caps.num_ports;
+	int i, j;
+
+	for (i = 0; i < num_entries; i++) {
+		for (j = 0; j < MLX4_NUM_STEERS; j++) {
+			list_for_each_entry_safe(pqp, tmp_pqp,
+						 &priv->steer[i].promisc_qps[j],
+						 list) {
+				list_del(&pqp->list);
+				kfree(pqp);
+			}
+			list_for_each_entry_safe(entry, tmp_entry,
+						 &priv->steer[i].steer_entries[j],
+						 list) {
+				list_del(&entry->list);
+				list_for_each_entry_safe(pqp, tmp_pqp,
+							 &entry->duplicates,
+							 list) {
+					list_del(&pqp->list);
+					kfree(pqp);
+				}
+				kfree(entry);
+			}
+		}
+	}
+	kfree(priv->steer);
+}
+
 static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
 	struct mlx4_priv *priv;
@@ -1109,6 +1209,9 @@
 		}
 	}
 
+	/* Allow large DMA segments, up to the firmware limit of 1 GB */
+	dma_set_max_seg_size(&pdev->dev, 1024 * 1024 * 1024);
+
 	priv = kzalloc(sizeof *priv, GFP_KERNEL);
 	if (!priv) {
 		dev_err(&pdev->dev, "Device struct alloc failed, "
@@ -1127,6 +1230,11 @@
 	INIT_LIST_HEAD(&priv->pgdir_list);
 	mutex_init(&priv->pgdir_mutex);
 
+	pci_read_config_byte(pdev, PCI_REVISION_ID, &dev->rev_id);
+
+	INIT_LIST_HEAD(&priv->bf_list);
+	mutex_init(&priv->bf_mutex);
+
 	/*
 	 * Now reset the HCA before we touch the PCI capabilities or
 	 * attempt a firmware command, since a boot ROM may have left
@@ -1151,8 +1259,15 @@
 	if (err)
 		goto err_close;
 
+	priv->msix_ctl.pool_bm = 0;
+	spin_lock_init(&priv->msix_ctl.pool_lock);
+
 	mlx4_enable_msi_x(dev);
 
+	err = mlx4_init_steering(dev);
+	if (err)
+		goto err_free_eq;
+
 	err = mlx4_setup_hca(dev);
 	if (err == -EBUSY && (dev->flags & MLX4_FLAG_MSI_X)) {
 		dev->flags &= ~MLX4_FLAG_MSI_X;
@@ -1161,7 +1276,7 @@
 	}
 
 	if (err)
-		goto err_free_eq;
+		goto err_steer;
 
 	for (port = 1; port <= dev->caps.num_ports; port++) {
 		err = mlx4_init_port_info(dev, port);
@@ -1194,6 +1309,9 @@
 	mlx4_cleanup_pd_table(dev);
 	mlx4_cleanup_uar_table(dev);
 
+err_steer:
+	mlx4_clear_steering(dev);
+
 err_free_eq:
 	mlx4_free_eq_table(dev);
 
@@ -1253,6 +1371,7 @@
 		iounmap(priv->kar);
 		mlx4_uar_free(dev, &priv->driver_uar);
 		mlx4_cleanup_uar_table(dev);
+		mlx4_clear_steering(dev);
 		mlx4_free_eq_table(dev);
 		mlx4_close_hca(dev);
 		mlx4_cmd_cleanup(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/mcg.c linux-libre-2.6.39-gnu/drivers/net/mlx4/mcg.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/mcg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/mcg.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
  */
 
 #include <linux/string.h>
+#include <linux/etherdevice.h>
 
 #include <linux/mlx4/cmd.h>
 
@@ -40,38 +41,40 @@
 #define MGM_QPN_MASK       0x00FFFFFF
 #define MGM_BLCK_LB_BIT    30
 
-struct mlx4_mgm {
-	__be32			next_gid_index;
-	__be32			members_count;
-	u32			reserved[2];
-	u8			gid[16];
-	__be32			qp[MLX4_QP_PER_MGM];
-};
-
 static const u8 zero_gid[16];	/* automatically initialized to 0 */
 
-static int mlx4_READ_MCG(struct mlx4_dev *dev, int index,
-			 struct mlx4_cmd_mailbox *mailbox)
+static int mlx4_READ_ENTRY(struct mlx4_dev *dev, int index,
+			   struct mlx4_cmd_mailbox *mailbox)
 {
 	return mlx4_cmd_box(dev, 0, mailbox->dma, index, 0, MLX4_CMD_READ_MCG,
 			    MLX4_CMD_TIME_CLASS_A);
 }
 
-static int mlx4_WRITE_MCG(struct mlx4_dev *dev, int index,
-			  struct mlx4_cmd_mailbox *mailbox)
+static int mlx4_WRITE_ENTRY(struct mlx4_dev *dev, int index,
+			    struct mlx4_cmd_mailbox *mailbox)
 {
 	return mlx4_cmd(dev, mailbox->dma, index, 0, MLX4_CMD_WRITE_MCG,
 			MLX4_CMD_TIME_CLASS_A);
 }
 
-static int mlx4_MGID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
-			  u16 *hash)
+static int mlx4_WRITE_PROMISC(struct mlx4_dev *dev, u8 vep_num, u8 port, u8 steer,
+			      struct mlx4_cmd_mailbox *mailbox)
+{
+	u32 in_mod;
+
+	in_mod = (u32) vep_num << 24 | (u32) port << 16 | steer << 1;
+	return mlx4_cmd(dev, mailbox->dma, in_mod, 0x1,
+			MLX4_CMD_WRITE_MCG, MLX4_CMD_TIME_CLASS_A);
+}
+
+static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
+			 u16 *hash, u8 op_mod)
 {
 	u64 imm;
 	int err;
 
-	err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, 0, MLX4_CMD_MGID_HASH,
-			   MLX4_CMD_TIME_CLASS_A);
+	err = mlx4_cmd_imm(dev, mailbox->dma, &imm, 0, op_mod,
+			   MLX4_CMD_MGID_HASH, MLX4_CMD_TIME_CLASS_A);
 
 	if (!err)
 		*hash = imm;
@@ -79,6 +82,458 @@
 	return err;
 }
 
+static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
+					      enum mlx4_steer_type steer,
+					      u32 qpn)
+{
+	struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num];
+	struct mlx4_promisc_qp *pqp;
+
+	list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
+		if (pqp->qpn == qpn)
+			return pqp;
+	}
+	/* not found */
+	return NULL;
+}
+
+/*
+ * Add new entry to steering data structure.
+ * All promisc QPs should be added as well
+ */
+static int new_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
+			      enum mlx4_steer_type steer,
+			      unsigned int index, u32 qpn)
+{
+	struct mlx4_steer *s_steer;
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_mgm *mgm;
+	u32 members_count;
+	struct mlx4_steer_index *new_entry;
+	struct mlx4_promisc_qp *pqp;
+	struct mlx4_promisc_qp *dqp = NULL;
+	u32 prot;
+	int err;
+	u8 pf_num;
+
+	pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
+	s_steer = &mlx4_priv(dev)->steer[pf_num];
+	new_entry = kzalloc(sizeof *new_entry, GFP_KERNEL);
+	if (!new_entry)
+		return -ENOMEM;
+
+	INIT_LIST_HEAD(&new_entry->duplicates);
+	new_entry->index = index;
+	list_add_tail(&new_entry->list, &s_steer->steer_entries[steer]);
+
+	/* If the given qpn is also a promisc qp,
+	 * it should be inserted to duplicates list
+	 */
+	pqp = get_promisc_qp(dev, pf_num, steer, qpn);
+	if (pqp) {
+		dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
+		if (!dqp) {
+			err = -ENOMEM;
+			goto out_alloc;
+		}
+		dqp->qpn = qpn;
+		list_add_tail(&dqp->list, &new_entry->duplicates);
+	}
+
+	/* if no promisc qps for this vep, we are done */
+	if (list_empty(&s_steer->promisc_qps[steer]))
+		return 0;
+
+	/* now need to add all the promisc qps to the new
+	 * steering entry, as they should also receive the packets
+	 * destined to this address */
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox)) {
+		err = -ENOMEM;
+		goto out_alloc;
+	}
+	mgm = mailbox->buf;
+
+	err = mlx4_READ_ENTRY(dev, index, mailbox);
+	if (err)
+		goto out_mailbox;
+
+	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+	prot = be32_to_cpu(mgm->members_count) >> 30;
+	list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
+		/* don't add already existing qpn */
+		if (pqp->qpn == qpn)
+			continue;
+		if (members_count == MLX4_QP_PER_MGM) {
+			/* out of space */
+			err = -ENOMEM;
+			goto out_mailbox;
+		}
+
+		/* add the qpn */
+		mgm->qp[members_count++] = cpu_to_be32(pqp->qpn & MGM_QPN_MASK);
+	}
+	/* update the qps count and update the entry with all the promisc qps*/
+	mgm->members_count = cpu_to_be32(members_count | (prot << 30));
+	err = mlx4_WRITE_ENTRY(dev, index, mailbox);
+
+out_mailbox:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	if (!err)
+		return 0;
+out_alloc:
+	if (dqp) {
+		list_del(&dqp->list);
+		kfree(dqp);
+	}
+	list_del(&new_entry->list);
+	kfree(new_entry);
+	return err;
+}
+
+/* update the data structures with existing steering entry */
+static int existing_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
+				   enum mlx4_steer_type steer,
+				   unsigned int index, u32 qpn)
+{
+	struct mlx4_steer *s_steer;
+	struct mlx4_steer_index *tmp_entry, *entry = NULL;
+	struct mlx4_promisc_qp *pqp;
+	struct mlx4_promisc_qp *dqp;
+	u8 pf_num;
+
+	pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
+	s_steer = &mlx4_priv(dev)->steer[pf_num];
+
+	pqp = get_promisc_qp(dev, pf_num, steer, qpn);
+	if (!pqp)
+		return 0; /* nothing to do */
+
+	list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
+		if (tmp_entry->index == index) {
+			entry = tmp_entry;
+			break;
+		}
+	}
+	if (unlikely(!entry)) {
+		mlx4_warn(dev, "Steering entry at index %x is not registered\n", index);
+		return -EINVAL;
+	}
+
+	/* the given qpn is listed as a promisc qpn
+	 * we need to add it as a duplicate to this entry
+	 * for future references */
+	list_for_each_entry(dqp, &entry->duplicates, list) {
+		if (qpn == dqp->qpn)
+			return 0; /* qp is already duplicated */
+	}
+
+	/* add the qp as a duplicate on this index */
+	dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
+	if (!dqp)
+		return -ENOMEM;
+	dqp->qpn = qpn;
+	list_add_tail(&dqp->list, &entry->duplicates);
+
+	return 0;
+}
+
+/* Check whether a qpn is a duplicate on steering entry
+ * If so, it should not be removed from mgm */
+static bool check_duplicate_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
+				  enum mlx4_steer_type steer,
+				  unsigned int index, u32 qpn)
+{
+	struct mlx4_steer *s_steer;
+	struct mlx4_steer_index *tmp_entry, *entry = NULL;
+	struct mlx4_promisc_qp *dqp, *tmp_dqp;
+	u8 pf_num;
+
+	pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
+	s_steer = &mlx4_priv(dev)->steer[pf_num];
+
+	/* if qp is not promisc, it cannot be duplicated */
+	if (!get_promisc_qp(dev, pf_num, steer, qpn))
+		return false;
+
+	/* The qp is promisc qp so it is a duplicate on this index
+	 * Find the index entry, and remove the duplicate */
+	list_for_each_entry(tmp_entry, &s_steer->steer_entries[steer], list) {
+		if (tmp_entry->index == index) {
+			entry = tmp_entry;
+			break;
+		}
+	}
+	if (unlikely(!entry)) {
+		mlx4_warn(dev, "Steering entry for index %x is not registered\n", index);
+		return false;
+	}
+	list_for_each_entry_safe(dqp, tmp_dqp, &entry->duplicates, list) {
+		if (dqp->qpn == qpn) {
+			list_del(&dqp->list);
+			kfree(dqp);
+		}
+	}
+	return true;
+}
+
+/* I a steering entry contains only promisc QPs, it can be removed. */
+static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 vep_num, u8 port,
+				      enum mlx4_steer_type steer,
+				      unsigned int index, u32 tqpn)
+{
+	struct mlx4_steer *s_steer;
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_mgm *mgm;
+	struct mlx4_steer_index *entry = NULL, *tmp_entry;
+	u32 qpn;
+	u32 members_count;
+	bool ret = false;
+	int i;
+	u8 pf_num;
+
+	pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
+	s_steer = &mlx4_priv(dev)->steer[pf_num];
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox))
+		return false;
+	mgm = mailbox->buf;
+
+	if (mlx4_READ_ENTRY(dev, index, mailbox))
+		goto out;
+	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+	for (i = 0;  i < members_count; i++) {
+		qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
+		if (!get_promisc_qp(dev, pf_num, steer, qpn) && qpn != tqpn) {
+			/* the qp is not promisc, the entry can't be removed */
+			goto out;
+		}
+	}
+	 /* All the qps currently registered for this entry are promiscuous,
+	  * Checking for duplicates */
+	ret = true;
+	list_for_each_entry_safe(entry, tmp_entry, &s_steer->steer_entries[steer], list) {
+		if (entry->index == index) {
+			if (list_empty(&entry->duplicates)) {
+				list_del(&entry->list);
+				kfree(entry);
+			} else {
+				/* This entry contains duplicates so it shouldn't be removed */
+				ret = false;
+				goto out;
+			}
+		}
+	}
+
+out:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	return ret;
+}
+
+static int add_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
+			  enum mlx4_steer_type steer, u32 qpn)
+{
+	struct mlx4_steer *s_steer;
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_mgm *mgm;
+	struct mlx4_steer_index *entry;
+	struct mlx4_promisc_qp *pqp;
+	struct mlx4_promisc_qp *dqp;
+	u32 members_count;
+	u32 prot;
+	int i;
+	bool found;
+	int last_index;
+	int err;
+	u8 pf_num;
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
+	s_steer = &mlx4_priv(dev)->steer[pf_num];
+
+	mutex_lock(&priv->mcg_table.mutex);
+
+	if (get_promisc_qp(dev, pf_num, steer, qpn)) {
+		err = 0;  /* Noting to do, already exists */
+		goto out_mutex;
+	}
+
+	pqp = kmalloc(sizeof *pqp, GFP_KERNEL);
+	if (!pqp) {
+		err = -ENOMEM;
+		goto out_mutex;
+	}
+	pqp->qpn = qpn;
+
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox)) {
+		err = -ENOMEM;
+		goto out_alloc;
+	}
+	mgm = mailbox->buf;
+
+	/* the promisc qp needs to be added for each one of the steering
+	 * entries, if it already exists, needs to be added as a duplicate
+	 * for this entry */
+	list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
+		err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
+		if (err)
+			goto out_mailbox;
+
+		members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+		prot = be32_to_cpu(mgm->members_count) >> 30;
+		found = false;
+		for (i = 0; i < members_count; i++) {
+			if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn) {
+				/* Entry already exists, add to duplicates */
+				dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
+				if (!dqp)
+					goto out_mailbox;
+				dqp->qpn = qpn;
+				list_add_tail(&dqp->list, &entry->duplicates);
+				found = true;
+			}
+		}
+		if (!found) {
+			/* Need to add the qpn to mgm */
+			if (members_count == MLX4_QP_PER_MGM) {
+				/* entry is full */
+				err = -ENOMEM;
+				goto out_mailbox;
+			}
+			mgm->qp[members_count++] = cpu_to_be32(qpn & MGM_QPN_MASK);
+			mgm->members_count = cpu_to_be32(members_count | (prot << 30));
+			err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
+			if (err)
+				goto out_mailbox;
+		}
+		last_index = entry->index;
+	}
+
+	/* add the new qpn to list of promisc qps */
+	list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
+	/* now need to add all the promisc qps to default entry */
+	memset(mgm, 0, sizeof *mgm);
+	members_count = 0;
+	list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
+		mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
+	mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
+
+	err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
+	if (err)
+		goto out_list;
+
+	mlx4_free_cmd_mailbox(dev, mailbox);
+	mutex_unlock(&priv->mcg_table.mutex);
+	return 0;
+
+out_list:
+	list_del(&pqp->list);
+out_mailbox:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+out_alloc:
+	kfree(pqp);
+out_mutex:
+	mutex_unlock(&priv->mcg_table.mutex);
+	return err;
+}
+
+static int remove_promisc_qp(struct mlx4_dev *dev, u8 vep_num, u8 port,
+			     enum mlx4_steer_type steer, u32 qpn)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	struct mlx4_steer *s_steer;
+	struct mlx4_cmd_mailbox *mailbox;
+	struct mlx4_mgm *mgm;
+	struct mlx4_steer_index *entry;
+	struct mlx4_promisc_qp *pqp;
+	struct mlx4_promisc_qp *dqp;
+	u32 members_count;
+	bool found;
+	bool back_to_list = false;
+	int loc, i;
+	int err;
+	u8 pf_num;
+
+	pf_num = (dev->caps.num_ports == 1) ? vep_num : (vep_num << 1) | (port - 1);
+	s_steer = &mlx4_priv(dev)->steer[pf_num];
+	mutex_lock(&priv->mcg_table.mutex);
+
+	pqp = get_promisc_qp(dev, pf_num, steer, qpn);
+	if (unlikely(!pqp)) {
+		mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
+		/* nothing to do */
+		err = 0;
+		goto out_mutex;
+	}
+
+	/*remove from list of promisc qps */
+	list_del(&pqp->list);
+
+	/* set the default entry not to include the removed one */
+	mailbox = mlx4_alloc_cmd_mailbox(dev);
+	if (IS_ERR(mailbox)) {
+		err = -ENOMEM;
+		back_to_list = true;
+		goto out_list;
+	}
+	mgm = mailbox->buf;
+	members_count = 0;
+	list_for_each_entry(dqp, &s_steer->promisc_qps[steer], list)
+		mgm->qp[members_count++] = cpu_to_be32(dqp->qpn & MGM_QPN_MASK);
+	mgm->members_count = cpu_to_be32(members_count | MLX4_PROT_ETH << 30);
+
+	err = mlx4_WRITE_PROMISC(dev, vep_num, port, steer, mailbox);
+	if (err)
+		goto out_mailbox;
+
+	/* remove the qp from all the steering entries*/
+	list_for_each_entry(entry, &s_steer->steer_entries[steer], list) {
+		found = false;
+		list_for_each_entry(dqp, &entry->duplicates, list) {
+			if (dqp->qpn == qpn) {
+				found = true;
+				break;
+			}
+		}
+		if (found) {
+			/* a duplicate, no need to change the mgm,
+			 * only update the duplicates list */
+			list_del(&dqp->list);
+			kfree(dqp);
+		} else {
+			err = mlx4_READ_ENTRY(dev, entry->index, mailbox);
+				if (err)
+					goto out_mailbox;
+			members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
+			for (loc = -1, i = 0; i < members_count; ++i)
+				if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qpn)
+					loc = i;
+
+			mgm->members_count = cpu_to_be32(--members_count |
+							 (MLX4_PROT_ETH << 30));
+			mgm->qp[loc] = mgm->qp[i - 1];
+			mgm->qp[i - 1] = 0;
+
+			err = mlx4_WRITE_ENTRY(dev, entry->index, mailbox);
+				if (err)
+					goto out_mailbox;
+		}
+
+	}
+
+out_mailbox:
+	mlx4_free_cmd_mailbox(dev, mailbox);
+out_list:
+	if (back_to_list)
+		list_add_tail(&pqp->list, &s_steer->promisc_qps[steer]);
+	else
+		kfree(pqp);
+out_mutex:
+	mutex_unlock(&priv->mcg_table.mutex);
+	return err;
+}
+
 /*
  * Caller must hold MCG table semaphore.  gid and mgm parameters must
  * be properly aligned for command interface.
@@ -94,15 +549,17 @@
  * If no AMGM exists for given gid, *index = -1, *prev = index of last
  * entry in hash chain and *mgm holds end of hash chain.
  */
-static int find_mgm(struct mlx4_dev *dev,
-		    u8 *gid, enum mlx4_protocol protocol,
-		    struct mlx4_cmd_mailbox *mgm_mailbox,
-		    u16 *hash, int *prev, int *index)
+static int find_entry(struct mlx4_dev *dev, u8 port,
+		      u8 *gid, enum mlx4_protocol prot,
+		      enum mlx4_steer_type steer,
+		      struct mlx4_cmd_mailbox *mgm_mailbox,
+		      u16 *hash, int *prev, int *index)
 {
 	struct mlx4_cmd_mailbox *mailbox;
 	struct mlx4_mgm *mgm = mgm_mailbox->buf;
 	u8 *mgid;
 	int err;
+	u8 op_mod = (prot == MLX4_PROT_ETH) ? !!(dev->caps.vep_mc_steering) : 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -111,7 +568,7 @@
 
 	memcpy(mgid, gid, 16);
 
-	err = mlx4_MGID_HASH(dev, mailbox, hash);
+	err = mlx4_GID_HASH(dev, mailbox, hash, op_mod);
 	mlx4_free_cmd_mailbox(dev, mailbox);
 	if (err)
 		return err;
@@ -123,11 +580,11 @@
 	*prev  = -1;
 
 	do {
-		err = mlx4_READ_MCG(dev, *index, mgm_mailbox);
+		err = mlx4_READ_ENTRY(dev, *index, mgm_mailbox);
 		if (err)
 			return err;
 
-		if (!memcmp(mgm->gid, zero_gid, 16)) {
+		if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
 			if (*index != *hash) {
 				mlx4_err(dev, "Found zero MGID in AMGM.\n");
 				err = -EINVAL;
@@ -136,7 +593,7 @@
 		}
 
 		if (!memcmp(mgm->gid, gid, 16) &&
-		    be32_to_cpu(mgm->members_count) >> 30 == protocol)
+		    be32_to_cpu(mgm->members_count) >> 30 == prot)
 			return err;
 
 		*prev = *index;
@@ -147,8 +604,9 @@
 	return err;
 }
 
-int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
-			  int block_mcast_loopback, enum mlx4_protocol protocol)
+int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  int block_mcast_loopback, enum mlx4_protocol prot,
+			  enum mlx4_steer_type steer)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_cmd_mailbox *mailbox;
@@ -159,6 +617,8 @@
 	int link = 0;
 	int i;
 	int err;
+	u8 port = gid[5];
+	u8 new_entry = 0;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -166,14 +626,16 @@
 	mgm = mailbox->buf;
 
 	mutex_lock(&priv->mcg_table.mutex);
-
-	err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
+	err = find_entry(dev, port, gid, prot, steer,
+			 mailbox, &hash, &prev, &index);
 	if (err)
 		goto out;
 
 	if (index != -1) {
-		if (!memcmp(mgm->gid, zero_gid, 16))
+		if (!(be32_to_cpu(mgm->members_count) & 0xffffff)) {
+			new_entry = 1;
 			memcpy(mgm->gid, gid, 16);
+		}
 	} else {
 		link = 1;
 
@@ -209,26 +671,34 @@
 	else
 		mgm->qp[members_count++] = cpu_to_be32(qp->qpn & MGM_QPN_MASK);
 
-	mgm->members_count = cpu_to_be32(members_count | (u32) protocol << 30);
+	mgm->members_count = cpu_to_be32(members_count | (u32) prot << 30);
 
-	err = mlx4_WRITE_MCG(dev, index, mailbox);
+	err = mlx4_WRITE_ENTRY(dev, index, mailbox);
 	if (err)
 		goto out;
 
 	if (!link)
 		goto out;
 
-	err = mlx4_READ_MCG(dev, prev, mailbox);
+	err = mlx4_READ_ENTRY(dev, prev, mailbox);
 	if (err)
 		goto out;
 
 	mgm->next_gid_index = cpu_to_be32(index << 6);
 
-	err = mlx4_WRITE_MCG(dev, prev, mailbox);
+	err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
 	if (err)
 		goto out;
 
 out:
+	if (prot == MLX4_PROT_ETH) {
+		/* manage the steering entry for promisc mode */
+		if (new_entry)
+			new_steering_entry(dev, 0, port, steer, index, qp->qpn);
+		else
+			existing_steering_entry(dev, 0, port, steer,
+						index, qp->qpn);
+	}
 	if (err && link && index != -1) {
 		if (index < dev->caps.num_mgms)
 			mlx4_warn(dev, "Got AMGM index %d < %d",
@@ -242,10 +712,9 @@
 	mlx4_free_cmd_mailbox(dev, mailbox);
 	return err;
 }
-EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
 
-int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
-			  enum mlx4_protocol protocol)
+int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  enum mlx4_protocol prot, enum mlx4_steer_type steer)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
 	struct mlx4_cmd_mailbox *mailbox;
@@ -255,6 +724,8 @@
 	int prev, index;
 	int i, loc;
 	int err;
+	u8 port = gid[5];
+	bool removed_entry = false;
 
 	mailbox = mlx4_alloc_cmd_mailbox(dev);
 	if (IS_ERR(mailbox))
@@ -263,7 +734,8 @@
 
 	mutex_lock(&priv->mcg_table.mutex);
 
-	err = find_mgm(dev, gid, protocol, mailbox, &hash, &prev, &index);
+	err = find_entry(dev, port, gid, prot, steer,
+			 mailbox, &hash, &prev, &index);
 	if (err)
 		goto out;
 
@@ -273,6 +745,11 @@
 		goto out;
 	}
 
+	/* if this pq is also a promisc qp, it shouldn't be removed */
+	if (prot == MLX4_PROT_ETH &&
+	    check_duplicate_entry(dev, 0, port, steer, index, qp->qpn))
+		goto out;
+
 	members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
 	for (loc = -1, i = 0; i < members_count; ++i)
 		if ((be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK) == qp->qpn)
@@ -285,26 +762,31 @@
 	}
 
 
-	mgm->members_count = cpu_to_be32(--members_count | (u32) protocol << 30);
+	mgm->members_count = cpu_to_be32(--members_count | (u32) prot << 30);
 	mgm->qp[loc]       = mgm->qp[i - 1];
 	mgm->qp[i - 1]     = 0;
 
-	if (i != 1) {
-		err = mlx4_WRITE_MCG(dev, index, mailbox);
+	if (prot == MLX4_PROT_ETH)
+		removed_entry = can_remove_steering_entry(dev, 0, port, steer, index, qp->qpn);
+	if (i != 1 && (prot != MLX4_PROT_ETH || !removed_entry)) {
+		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
 		goto out;
 	}
 
+	/* We are going to delete the entry, members count should be 0 */
+	mgm->members_count = cpu_to_be32((u32) prot << 30);
+
 	if (prev == -1) {
 		/* Remove entry from MGM */
 		int amgm_index = be32_to_cpu(mgm->next_gid_index) >> 6;
 		if (amgm_index) {
-			err = mlx4_READ_MCG(dev, amgm_index, mailbox);
+			err = mlx4_READ_ENTRY(dev, amgm_index, mailbox);
 			if (err)
 				goto out;
 		} else
 			memset(mgm->gid, 0, 16);
 
-		err = mlx4_WRITE_MCG(dev, index, mailbox);
+		err = mlx4_WRITE_ENTRY(dev, index, mailbox);
 		if (err)
 			goto out;
 
@@ -319,13 +801,13 @@
 	} else {
 		/* Remove entry from AMGM */
 		int cur_next_index = be32_to_cpu(mgm->next_gid_index) >> 6;
-		err = mlx4_READ_MCG(dev, prev, mailbox);
+		err = mlx4_READ_ENTRY(dev, prev, mailbox);
 		if (err)
 			goto out;
 
 		mgm->next_gid_index = cpu_to_be32(cur_next_index << 6);
 
-		err = mlx4_WRITE_MCG(dev, prev, mailbox);
+		err = mlx4_WRITE_ENTRY(dev, prev, mailbox);
 		if (err)
 			goto out;
 
@@ -343,8 +825,85 @@
 	mlx4_free_cmd_mailbox(dev, mailbox);
 	return err;
 }
+
+
+int mlx4_multicast_attach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  int block_mcast_loopback, enum mlx4_protocol prot)
+{
+	enum mlx4_steer_type steer;
+
+	steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
+
+	if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
+		return 0;
+
+	if (prot == MLX4_PROT_ETH)
+		gid[7] |= (steer << 1);
+
+	return mlx4_qp_attach_common(dev, qp, gid,
+				     block_mcast_loopback, prot,
+				     steer);
+}
+EXPORT_SYMBOL_GPL(mlx4_multicast_attach);
+
+int mlx4_multicast_detach(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  enum mlx4_protocol prot)
+{
+	enum mlx4_steer_type steer;
+
+	steer = (is_valid_ether_addr(&gid[10])) ? MLX4_UC_STEER : MLX4_MC_STEER;
+
+	if (prot == MLX4_PROT_ETH && !dev->caps.vep_mc_steering)
+		return 0;
+
+	if (prot == MLX4_PROT_ETH) {
+		gid[7] |= (steer << 1);
+	}
+
+	return mlx4_qp_detach_common(dev, qp, gid, prot, steer);
+}
 EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
 
+
+int mlx4_multicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
+{
+	if (!dev->caps.vep_mc_steering)
+		return 0;
+
+
+	return add_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
+}
+EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_add);
+
+int mlx4_multicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
+{
+	if (!dev->caps.vep_mc_steering)
+		return 0;
+
+
+	return remove_promisc_qp(dev, 0, port, MLX4_MC_STEER, qpn);
+}
+EXPORT_SYMBOL_GPL(mlx4_multicast_promisc_remove);
+
+int mlx4_unicast_promisc_add(struct mlx4_dev *dev, u32 qpn, u8 port)
+{
+	if (!dev->caps.vep_mc_steering)
+		return 0;
+
+
+	return add_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
+}
+EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_add);
+
+int mlx4_unicast_promisc_remove(struct mlx4_dev *dev, u32 qpn, u8 port)
+{
+	if (!dev->caps.vep_mc_steering)
+		return 0;
+
+	return remove_promisc_qp(dev, 0, port, MLX4_UC_STEER, qpn);
+}
+EXPORT_SYMBOL_GPL(mlx4_unicast_promisc_remove);
+
 int mlx4_init_mcg_table(struct mlx4_dev *dev)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/mlx4_en.h linux-libre-2.6.39-gnu/drivers/net/mlx4/mlx4_en.h
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/mlx4_en.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/mlx4_en.h	2011-05-19 00:06:34.000000000 -0400
@@ -49,8 +49,8 @@
 #include "en_port.h"
 
 #define DRV_NAME	"mlx4_en"
-#define DRV_VERSION	"1.5.1.6"
-#define DRV_RELDATE	"August 2010"
+#define DRV_VERSION	"1.5.4.1"
+#define DRV_RELDATE	"March 2011"
 
 #define MLX4_EN_MSG_LEVEL	(NETIF_MSG_LINK | NETIF_MSG_IFDOWN)
 
@@ -62,6 +62,7 @@
 #define MLX4_EN_PAGE_SHIFT	12
 #define MLX4_EN_PAGE_SIZE	(1 << MLX4_EN_PAGE_SHIFT)
 #define MAX_RX_RINGS		16
+#define MIN_RX_RINGS		4
 #define TXBB_SIZE		64
 #define HEADROOM		(2048 / TXBB_SIZE + 1)
 #define STAMP_STRIDE		64
@@ -124,6 +125,7 @@
 #define MLX4_EN_RX_SIZE_THRESH		1024
 #define MLX4_EN_RX_RATE_THRESH		(1000000 / MLX4_EN_RX_COAL_TIME_HIGH)
 #define MLX4_EN_SAMPLE_INTERVAL		0
+#define MLX4_EN_AVG_PKT_SMALL		256
 
 #define MLX4_EN_AUTO_CONF	0xffff
 
@@ -214,6 +216,9 @@
 
 #define MLX4_EN_USE_SRQ		0x01000000
 
+#define MLX4_EN_CX3_LOW_ID	0x1000
+#define MLX4_EN_CX3_HIGH_ID	0x1005
+
 struct mlx4_en_rx_alloc {
 	struct page *page;
 	u16 offset;
@@ -243,6 +248,8 @@
 	unsigned long bytes;
 	unsigned long packets;
 	spinlock_t comp_lock;
+	struct mlx4_bf bf;
+	bool bf_enabled;
 };
 
 struct mlx4_en_rx_desc {
@@ -453,6 +460,7 @@
 	struct mlx4_en_rss_map rss_map;
 	u32 flags;
 #define MLX4_EN_FLAG_PROMISC	0x1
+#define MLX4_EN_FLAG_MC_PROMISC	0x2
 	u32 tx_ring_num;
 	u32 rx_ring_num;
 	u32 rx_skb_size;
@@ -461,6 +469,7 @@
 	u16 log_rx_info;
 
 	struct mlx4_en_tx_ring tx_ring[MAX_TX_RINGS];
+	int tx_vector;
 	struct mlx4_en_rx_ring rx_ring[MAX_RX_RINGS];
 	struct mlx4_en_cq tx_cq[MAX_TX_RINGS];
 	struct mlx4_en_cq rx_cq[MAX_RX_RINGS];
@@ -476,6 +485,13 @@
 	int mc_addrs_cnt;
 	struct mlx4_en_stat_out_mbox hw_stats;
 	int vids[128];
+	bool wol;
+};
+
+enum mlx4_en_wol {
+	MLX4_EN_WOL_MAGIC = (1ULL << 61),
+	MLX4_EN_WOL_ENABLED = (1ULL << 62),
+	MLX4_EN_WOL_DO_MODIFY = (1ULL << 63),
 };
 
 
@@ -486,12 +502,13 @@
 int mlx4_en_start_port(struct net_device *dev);
 void mlx4_en_stop_port(struct net_device *dev);
 
-void mlx4_en_free_resources(struct mlx4_en_priv *priv);
+void mlx4_en_free_resources(struct mlx4_en_priv *priv, bool reserve_vectors);
 int mlx4_en_alloc_resources(struct mlx4_en_priv *priv);
 
 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);
+void mlx4_en_destroy_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq,
+			bool reserve_vectors);
 int mlx4_en_activate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 void mlx4_en_deactivate_cq(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
 int mlx4_en_set_cq_moder(struct mlx4_en_priv *priv, struct mlx4_en_cq *cq);
@@ -503,7 +520,7 @@
 netdev_tx_t 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,
-			   u32 size, u16 stride);
+			   int qpn, u32 size, u16 stride);
 void mlx4_en_destroy_tx_ring(struct mlx4_en_priv *priv, struct mlx4_en_tx_ring *ring);
 int mlx4_en_activate_tx_ring(struct mlx4_en_priv *priv,
 			     struct mlx4_en_tx_ring *ring,
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/mlx4.h linux-libre-2.6.39-gnu/drivers/net/mlx4/mlx4.h
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/mlx4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/mlx4.h	2011-05-19 00:06:34.000000000 -0400
@@ -105,6 +105,7 @@
 	u32			max;
 	u32                     reserved_top;
 	u32			mask;
+	u32			avail;
 	spinlock_t		lock;
 	unsigned long	       *table;
 };
@@ -162,6 +163,27 @@
 	u8			catas_bar;
 };
 
+#define MGM_QPN_MASK       0x00FFFFFF
+#define MGM_BLCK_LB_BIT    30
+
+struct mlx4_promisc_qp {
+	struct list_head list;
+	u32 qpn;
+};
+
+struct mlx4_steer_index {
+	struct list_head list;
+	unsigned int index;
+	struct list_head duplicates;
+};
+
+struct mlx4_mgm {
+	__be32			next_gid_index;
+	__be32			members_count;
+	u32			reserved[2];
+	u8			gid[16];
+	__be32			qp[MLX4_QP_PER_MGM];
+};
 struct mlx4_cmd {
 	struct pci_pool	       *pool;
 	void __iomem	       *hcr;
@@ -265,6 +287,10 @@
 	int			max;
 };
 
+struct mlx4_mac_entry {
+	u64 mac;
+};
+
 struct mlx4_port_info {
 	struct mlx4_dev	       *dev;
 	int			port;
@@ -272,7 +298,9 @@
 	struct device_attribute port_attr;
 	enum mlx4_port_type	tmp_type;
 	struct mlx4_mac_table	mac_table;
+	struct radix_tree_root	mac_tree;
 	struct mlx4_vlan_table	vlan_table;
+	int			base_qpn;
 };
 
 struct mlx4_sense {
@@ -282,6 +310,17 @@
 	struct delayed_work	sense_poll;
 };
 
+struct mlx4_msix_ctl {
+	u64		pool_bm;
+	spinlock_t	pool_lock;
+};
+
+struct mlx4_steer {
+	struct list_head promisc_qps[MLX4_NUM_STEERS];
+	struct list_head steer_entries[MLX4_NUM_STEERS];
+	struct list_head high_prios;
+};
+
 struct mlx4_priv {
 	struct mlx4_dev		dev;
 
@@ -313,6 +352,11 @@
 	struct mlx4_port_info	port[MLX4_MAX_PORTS + 1];
 	struct mlx4_sense       sense;
 	struct mutex		port_mutex;
+	struct mlx4_msix_ctl	msix_ctl;
+	struct mlx4_steer	*steer;
+	struct list_head	bf_list;
+	struct mutex		bf_mutex;
+	struct io_mapping	*bf_mapping;
 };
 
 static inline struct mlx4_priv *mlx4_priv(struct mlx4_dev *dev)
@@ -328,6 +372,7 @@
 void mlx4_bitmap_free(struct mlx4_bitmap *bitmap, u32 obj);
 u32 mlx4_bitmap_alloc_range(struct mlx4_bitmap *bitmap, int cnt, int align);
 void mlx4_bitmap_free_range(struct mlx4_bitmap *bitmap, u32 obj, int cnt);
+u32 mlx4_bitmap_avail(struct mlx4_bitmap *bitmap);
 int mlx4_bitmap_init(struct mlx4_bitmap *bitmap, u32 num, u32 mask,
 		     u32 reserved_bot, u32 resetrved_top);
 void mlx4_bitmap_cleanup(struct mlx4_bitmap *bitmap);
@@ -386,6 +431,8 @@
 
 void mlx4_handle_catas_err(struct mlx4_dev *dev);
 
+int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
+		    enum mlx4_port_type *type);
 void mlx4_do_sense_ports(struct mlx4_dev *dev,
 			 enum mlx4_port_type *stype,
 			 enum mlx4_port_type *defaults);
@@ -403,4 +450,9 @@
 int mlx4_SET_PORT(struct mlx4_dev *dev, u8 port);
 int mlx4_get_port_ib_caps(struct mlx4_dev *dev, u8 port, __be32 *caps);
 
+int mlx4_qp_detach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  enum mlx4_protocol prot, enum mlx4_steer_type steer);
+int mlx4_qp_attach_common(struct mlx4_dev *dev, struct mlx4_qp *qp, u8 gid[16],
+			  int block_mcast_loopback, enum mlx4_protocol prot,
+			  enum mlx4_steer_type steer);
 #endif /* MLX4_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/pd.c linux-libre-2.6.39-gnu/drivers/net/mlx4/pd.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/pd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/pd.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,12 +32,17 @@
  */
 
 #include <linux/errno.h>
+#include <linux/io-mapping.h>
 
 #include <asm/page.h>
 
 #include "mlx4.h"
 #include "icm.h"
 
+enum {
+	MLX4_NUM_RESERVED_UARS = 8
+};
+
 int mlx4_pd_alloc(struct mlx4_dev *dev, u32 *pdn)
 {
 	struct mlx4_priv *priv = mlx4_priv(dev);
@@ -77,6 +82,7 @@
 		return -ENOMEM;
 
 	uar->pfn = (pci_resource_start(dev->pdev, 2) >> PAGE_SHIFT) + uar->index;
+	uar->map = NULL;
 
 	return 0;
 }
@@ -88,6 +94,102 @@
 }
 EXPORT_SYMBOL_GPL(mlx4_uar_free);
 
+int mlx4_bf_alloc(struct mlx4_dev *dev, struct mlx4_bf *bf)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	struct mlx4_uar *uar;
+	int err = 0;
+	int idx;
+
+	if (!priv->bf_mapping)
+		return -ENOMEM;
+
+	mutex_lock(&priv->bf_mutex);
+	if (!list_empty(&priv->bf_list))
+		uar = list_entry(priv->bf_list.next, struct mlx4_uar, bf_list);
+	else {
+		if (mlx4_bitmap_avail(&priv->uar_table.bitmap) < MLX4_NUM_RESERVED_UARS) {
+			err = -ENOMEM;
+			goto out;
+		}
+		uar = kmalloc(sizeof *uar, GFP_KERNEL);
+		if (!uar) {
+			err = -ENOMEM;
+			goto out;
+		}
+		err = mlx4_uar_alloc(dev, uar);
+		if (err)
+			goto free_kmalloc;
+
+		uar->map = ioremap(uar->pfn << PAGE_SHIFT, PAGE_SIZE);
+		if (!uar->map) {
+			err = -ENOMEM;
+			goto free_uar;
+		}
+
+		uar->bf_map = io_mapping_map_wc(priv->bf_mapping, uar->index << PAGE_SHIFT);
+		if (!uar->bf_map) {
+			err = -ENOMEM;
+			goto unamp_uar;
+		}
+		uar->free_bf_bmap = 0;
+		list_add(&uar->bf_list, &priv->bf_list);
+	}
+
+	bf->uar = uar;
+	idx = ffz(uar->free_bf_bmap);
+	uar->free_bf_bmap |= 1 << idx;
+	bf->uar = uar;
+	bf->offset = 0;
+	bf->buf_size = dev->caps.bf_reg_size / 2;
+	bf->reg = uar->bf_map + idx * dev->caps.bf_reg_size;
+	if (uar->free_bf_bmap == (1 << dev->caps.bf_regs_per_page) - 1)
+		list_del_init(&uar->bf_list);
+
+	goto out;
+
+unamp_uar:
+	bf->uar = NULL;
+	iounmap(uar->map);
+
+free_uar:
+	mlx4_uar_free(dev, uar);
+
+free_kmalloc:
+	kfree(uar);
+
+out:
+	mutex_unlock(&priv->bf_mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_bf_alloc);
+
+void mlx4_bf_free(struct mlx4_dev *dev, struct mlx4_bf *bf)
+{
+	struct mlx4_priv *priv = mlx4_priv(dev);
+	int idx;
+
+	if (!bf->uar || !bf->uar->bf_map)
+		return;
+
+	mutex_lock(&priv->bf_mutex);
+	idx = (bf->reg - bf->uar->bf_map) / dev->caps.bf_reg_size;
+	bf->uar->free_bf_bmap &= ~(1 << idx);
+	if (!bf->uar->free_bf_bmap) {
+		if (!list_empty(&bf->uar->bf_list))
+			list_del(&bf->uar->bf_list);
+
+		io_mapping_unmap(bf->uar->bf_map);
+		iounmap(bf->uar->map);
+		mlx4_uar_free(dev, bf->uar);
+		kfree(bf->uar);
+	} else if (list_empty(&bf->uar->bf_list))
+		list_add(&bf->uar->bf_list, &priv->bf_list);
+
+	mutex_unlock(&priv->bf_mutex);
+}
+EXPORT_SYMBOL_GPL(mlx4_bf_free);
+
 int mlx4_init_uar_table(struct mlx4_dev *dev)
 {
 	if (dev->caps.num_uars <= 128) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/port.c linux-libre-2.6.39-gnu/drivers/net/mlx4/port.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/port.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/port.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,12 +90,79 @@
 	return err;
 }
 
-int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *index)
+static int mlx4_uc_steer_add(struct mlx4_dev *dev, u8 port,
+			     u64 mac, int *qpn, u8 reserve)
 {
-	struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
+	struct mlx4_qp qp;
+	u8 gid[16] = {0};
+	int err;
+
+	if (reserve) {
+		err = mlx4_qp_reserve_range(dev, 1, 1, qpn);
+		if (err) {
+			mlx4_err(dev, "Failed to reserve qp for mac registration\n");
+			return err;
+		}
+	}
+	qp.qpn = *qpn;
+
+	mac &= 0xffffffffffffULL;
+	mac = cpu_to_be64(mac << 16);
+	memcpy(&gid[10], &mac, ETH_ALEN);
+	gid[5] = port;
+	gid[7] = MLX4_UC_STEER << 1;
+
+	err = mlx4_qp_attach_common(dev, &qp, gid, 0,
+				    MLX4_PROT_ETH, MLX4_UC_STEER);
+	if (err && reserve)
+		mlx4_qp_release_range(dev, *qpn, 1);
+
+	return err;
+}
+
+static void mlx4_uc_steer_release(struct mlx4_dev *dev, u8 port,
+				  u64 mac, int qpn, u8 free)
+{
+	struct mlx4_qp qp;
+	u8 gid[16] = {0};
+
+	qp.qpn = qpn;
+	mac &= 0xffffffffffffULL;
+	mac = cpu_to_be64(mac << 16);
+	memcpy(&gid[10], &mac, ETH_ALEN);
+	gid[5] = port;
+	gid[7] = MLX4_UC_STEER << 1;
+
+	mlx4_qp_detach_common(dev, &qp, gid, MLX4_PROT_ETH, MLX4_UC_STEER);
+	if (free)
+		mlx4_qp_release_range(dev, qpn, 1);
+}
+
+int mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac, int *qpn, u8 wrap)
+{
+	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+	struct mlx4_mac_table *table = &info->mac_table;
+	struct mlx4_mac_entry *entry;
 	int i, err = 0;
 	int free = -1;
 
+	if (dev->caps.vep_uc_steering) {
+		err = mlx4_uc_steer_add(dev, port, mac, qpn, 1);
+		if (!err) {
+			entry = kmalloc(sizeof *entry, GFP_KERNEL);
+			if (!entry) {
+				mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
+				return -ENOMEM;
+			}
+			entry->mac = mac;
+			err = radix_tree_insert(&info->mac_tree, *qpn, entry);
+			if (err) {
+				mlx4_uc_steer_release(dev, port, mac, *qpn, 1);
+				return err;
+			}
+		} else
+			return err;
+	}
 	mlx4_dbg(dev, "Registering MAC: 0x%llx\n", (unsigned long long) mac);
 	mutex_lock(&table->mutex);
 	for (i = 0; i < MLX4_MAX_MAC_NUM - 1; i++) {
@@ -105,8 +172,7 @@
 		}
 
 		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) {
-			/* MAC already registered, increase refernce count */
-			*index = i;
+			/* MAC already registered, increase references count */
 			++table->refs[i];
 			goto out;
 		}
@@ -137,7 +203,8 @@
 		goto out;
 	}
 
-	*index = free;
+	if (!dev->caps.vep_uc_steering)
+		*qpn = info->base_qpn + free;
 	++table->total;
 out:
 	mutex_unlock(&table->mutex);
@@ -145,20 +212,52 @@
 }
 EXPORT_SYMBOL_GPL(mlx4_register_mac);
 
-void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int index)
+static int validate_index(struct mlx4_dev *dev,
+			  struct mlx4_mac_table *table, int index)
 {
-	struct mlx4_mac_table *table = &mlx4_priv(dev)->port[port].mac_table;
+	int err = 0;
 
-	mutex_lock(&table->mutex);
-	if (!table->refs[index]) {
-		mlx4_warn(dev, "No MAC entry for index %d\n", index);
-		goto out;
+	if (index < 0 || index >= table->max || !table->entries[index]) {
+		mlx4_warn(dev, "No valid Mac entry for the given index\n");
+		err = -EINVAL;
 	}
-	if (--table->refs[index]) {
-		mlx4_warn(dev, "Have more references for index %d,"
-			  "no need to modify MAC table\n", index);
-		goto out;
+	return err;
+}
+
+static int find_index(struct mlx4_dev *dev,
+		      struct mlx4_mac_table *table, u64 mac)
+{
+	int i;
+	for (i = 0; i < MLX4_MAX_MAC_NUM; i++) {
+		if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i])))
+			return i;
+	}
+	/* Mac not found */
+	return -EINVAL;
+}
+
+void mlx4_unregister_mac(struct mlx4_dev *dev, u8 port, int qpn)
+{
+	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+	struct mlx4_mac_table *table = &info->mac_table;
+	int index = qpn - info->base_qpn;
+	struct mlx4_mac_entry *entry;
+
+	if (dev->caps.vep_uc_steering) {
+		entry = radix_tree_lookup(&info->mac_tree, qpn);
+		if (entry) {
+			mlx4_uc_steer_release(dev, port, entry->mac, qpn, 1);
+			radix_tree_delete(&info->mac_tree, qpn);
+			index = find_index(dev, table, entry->mac);
+			kfree(entry);
+		}
 	}
+
+	mutex_lock(&table->mutex);
+
+	if (validate_index(dev, table, index))
+		goto out;
+
 	table->entries[index] = 0;
 	mlx4_set_port_mac_table(dev, port, table->entries);
 	--table->total;
@@ -167,6 +266,44 @@
 }
 EXPORT_SYMBOL_GPL(mlx4_unregister_mac);
 
+int mlx4_replace_mac(struct mlx4_dev *dev, u8 port, int qpn, u64 new_mac, u8 wrap)
+{
+	struct mlx4_port_info *info = &mlx4_priv(dev)->port[port];
+	struct mlx4_mac_table *table = &info->mac_table;
+	int index = qpn - info->base_qpn;
+	struct mlx4_mac_entry *entry;
+	int err;
+
+	if (dev->caps.vep_uc_steering) {
+		entry = radix_tree_lookup(&info->mac_tree, qpn);
+		if (!entry)
+			return -EINVAL;
+		index = find_index(dev, table, entry->mac);
+		mlx4_uc_steer_release(dev, port, entry->mac, qpn, 0);
+		entry->mac = new_mac;
+		err = mlx4_uc_steer_add(dev, port, entry->mac, &qpn, 0);
+		if (err || index < 0)
+			return err;
+	}
+
+	mutex_lock(&table->mutex);
+
+	err = validate_index(dev, table, index);
+	if (err)
+		goto out;
+
+	table->entries[index] = cpu_to_be64(new_mac | MLX4_MAC_VALID);
+
+	err = mlx4_set_port_mac_table(dev, port, table->entries);
+	if (unlikely(err)) {
+		mlx4_err(dev, "Failed adding MAC: 0x%llx\n", (unsigned long long) new_mac);
+		table->entries[index] = 0;
+	}
+out:
+	mutex_unlock(&table->mutex);
+	return err;
+}
+EXPORT_SYMBOL_GPL(mlx4_replace_mac);
 static int mlx4_set_port_vlan_table(struct mlx4_dev *dev, u8 port,
 				    __be32 *entries)
 {
@@ -223,7 +360,7 @@
 		if (table->refs[i] &&
 		    (vlan == (MLX4_VLAN_MASK &
 			      be32_to_cpu(table->entries[i])))) {
-			/* Vlan already registered, increase refernce count */
+			/* Vlan already registered, increase references count */
 			*index = i;
 			++table->refs[i];
 			goto out;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/profile.c linux-libre-2.6.39-gnu/drivers/net/mlx4/profile.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/profile.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/profile.c	2011-05-19 00:06:34.000000000 -0400
@@ -107,9 +107,7 @@
 	profile[MLX4_RES_AUXC].num    = request->num_qp;
 	profile[MLX4_RES_SRQ].num     = request->num_srq;
 	profile[MLX4_RES_CQ].num      = request->num_cq;
-	profile[MLX4_RES_EQ].num      = min_t(unsigned, dev_cap->max_eqs,
-					      dev_cap->reserved_eqs +
-					      num_possible_cpus() + 1);
+	profile[MLX4_RES_EQ].num      = min_t(unsigned, dev_cap->max_eqs, MAX_MSIX);
 	profile[MLX4_RES_DMPT].num    = request->num_mpt;
 	profile[MLX4_RES_CMPT].num    = MLX4_NUM_CMPTS;
 	profile[MLX4_RES_MTT].num     = request->num_mtt;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mlx4/sense.c linux-libre-2.6.39-gnu/drivers/net/mlx4/sense.c
--- linux-libre-2.6.38-gnu/drivers/net/mlx4/sense.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mlx4/sense.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,8 +38,8 @@
 
 #include "mlx4.h"
 
-static int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
-			   enum mlx4_port_type *type)
+int mlx4_SENSE_PORT(struct mlx4_dev *dev, int port,
+		    enum mlx4_port_type *type)
 {
 	u64 out_param;
 	int err = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/mv643xx_eth.c linux-libre-2.6.39-gnu/drivers/net/mv643xx_eth.c
--- linux-libre-2.6.38-gnu/drivers/net/mv643xx_eth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/mv643xx_eth.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,8 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/init.h>
 #include <linux/dma-mapping.h>
 #include <linux/in.h>
@@ -627,9 +629,8 @@
 		if ((cmd_sts & (RX_FIRST_DESC | RX_LAST_DESC)) !=
 			(RX_FIRST_DESC | RX_LAST_DESC)) {
 			if (net_ratelimit())
-				dev_printk(KERN_ERR, &mp->dev->dev,
-					   "received packet spanning "
-					   "multiple descriptors\n");
+				netdev_err(mp->dev,
+					   "received packet spanning multiple descriptors\n");
 		}
 
 		if (cmd_sts & ERROR_SUMMARY)
@@ -868,15 +869,14 @@
 
 	if (has_tiny_unaligned_frags(skb) && __skb_linearize(skb)) {
 		txq->tx_dropped++;
-		dev_printk(KERN_DEBUG, &dev->dev,
-			   "failed to linearize skb with tiny "
-			   "unaligned fragment\n");
+		netdev_printk(KERN_DEBUG, dev,
+			      "failed to linearize skb with tiny unaligned fragment\n");
 		return NETDEV_TX_BUSY;
 	}
 
 	if (txq->tx_ring_size - txq->tx_desc_count < MAX_SKB_FRAGS + 1) {
 		if (net_ratelimit())
-			dev_printk(KERN_ERR, &dev->dev, "tx queue full?!\n");
+			netdev_err(dev, "tx queue full?!\n");
 		kfree_skb(skb);
 		return NETDEV_TX_OK;
 	}
@@ -959,7 +959,7 @@
 			skb = __skb_dequeue(&txq->tx_skb);
 
 		if (cmd_sts & ERROR_SUMMARY) {
-			dev_printk(KERN_INFO, &mp->dev->dev, "tx error\n");
+			netdev_info(mp->dev, "tx error\n");
 			mp->dev->stats.tx_errors++;
 		}
 
@@ -1122,20 +1122,20 @@
 	int ret;
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
 	writel(SMI_OPCODE_READ | (reg << 21) | (addr << 16), smi_reg);
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
 	ret = readl(smi_reg);
 	if (!(ret & SMI_READ_VALID)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus read not valid\n");
+		pr_warn("SMI bus read not valid\n");
 		return -ENODEV;
 	}
 
@@ -1148,7 +1148,7 @@
 	void __iomem *smi_reg = msp->base + SMI_REG;
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
@@ -1156,7 +1156,7 @@
 		(addr << 16) | (val & 0xffff), smi_reg);
 
 	if (smi_wait_ready(msp)) {
-		printk(KERN_WARNING "mv643xx_eth: SMI bus busy timeout\n");
+		pr_warn("SMI bus busy timeout\n");
 		return -ETIMEDOUT;
 	}
 
@@ -1566,9 +1566,8 @@
 	if (netif_running(dev)) {
 		mv643xx_eth_stop(dev);
 		if (mv643xx_eth_open(dev)) {
-			dev_printk(KERN_ERR, &dev->dev,
-				   "fatal error on re-opening device after "
-				   "ring param change\n");
+			netdev_err(dev,
+				   "fatal error on re-opening device after ring param change\n");
 			return -ENOMEM;
 		}
 	}
@@ -1874,7 +1873,7 @@
 	}
 
 	if (rxq->rx_desc_area == NULL) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
+		netdev_err(mp->dev,
 			   "can't allocate rx ring (%d bytes)\n", size);
 		goto out;
 	}
@@ -1884,8 +1883,7 @@
 	rxq->rx_skb = kmalloc(rxq->rx_ring_size * sizeof(*rxq->rx_skb),
 								GFP_KERNEL);
 	if (rxq->rx_skb == NULL) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
-			   "can't allocate rx skb ring\n");
+		netdev_err(mp->dev, "can't allocate rx skb ring\n");
 		goto out_free;
 	}
 
@@ -1944,8 +1942,7 @@
 	}
 
 	if (rxq->rx_desc_count) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
-			   "error freeing rx ring -- %d skbs stuck\n",
+		netdev_err(mp->dev, "error freeing rx ring -- %d skbs stuck\n",
 			   rxq->rx_desc_count);
 	}
 
@@ -1987,7 +1984,7 @@
 	}
 
 	if (txq->tx_desc_area == NULL) {
-		dev_printk(KERN_ERR, &mp->dev->dev,
+		netdev_err(mp->dev,
 			   "can't allocate tx ring (%d bytes)\n", size);
 		return -ENOMEM;
 	}
@@ -2093,7 +2090,7 @@
 		if (netif_carrier_ok(dev)) {
 			int i;
 
-			printk(KERN_INFO "%s: link down\n", dev->name);
+			netdev_info(dev, "link down\n");
 
 			netif_carrier_off(dev);
 
@@ -2124,10 +2121,8 @@
 	duplex = (port_status & FULL_DUPLEX) ? 1 : 0;
 	fc = (port_status & FLOW_CONTROL_ENABLED) ? 1 : 0;
 
-	printk(KERN_INFO "%s: link up, %d Mb/s, %s duplex, "
-			 "flow control %sabled\n", dev->name,
-			 speed, duplex ? "full" : "half",
-			 fc ? "en" : "dis");
+	netdev_info(dev, "link up, %d Mb/s, %s duplex, flow control %sabled\n",
+		    speed, duplex ? "full" : "half", fc ? "en" : "dis");
 
 	if (!netif_carrier_ok(dev))
 		netif_carrier_on(dev);
@@ -2337,7 +2332,7 @@
 	err = request_irq(dev->irq, mv643xx_eth_irq,
 			  IRQF_SHARED, dev->name, dev);
 	if (err) {
-		dev_printk(KERN_ERR, &dev->dev, "can't assign irq\n");
+		netdev_err(dev, "can't assign irq\n");
 		return -EAGAIN;
 	}
 
@@ -2483,9 +2478,8 @@
 	 */
 	mv643xx_eth_stop(dev);
 	if (mv643xx_eth_open(dev)) {
-		dev_printk(KERN_ERR, &dev->dev,
-			   "fatal error on re-opening device after "
-			   "MTU change\n");
+		netdev_err(dev,
+			   "fatal error on re-opening device after MTU change\n");
 	}
 
 	return 0;
@@ -2508,7 +2502,7 @@
 {
 	struct mv643xx_eth_private *mp = netdev_priv(dev);
 
-	dev_printk(KERN_INFO, &dev->dev, "tx timeout\n");
+	netdev_info(dev, "tx timeout\n");
 
 	schedule_work(&mp->tx_timeout_task);
 }
@@ -2603,8 +2597,8 @@
 	int ret;
 
 	if (!mv643xx_eth_version_printed++)
-		printk(KERN_NOTICE "MV-643xx 10/100/1000 ethernet "
-			"driver version %s\n", mv643xx_eth_driver_version);
+		pr_notice("MV-643xx 10/100/1000 ethernet driver version %s\n",
+			  mv643xx_eth_driver_version);
 
 	ret = -EINVAL;
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -2871,14 +2865,12 @@
 
 	pd = pdev->dev.platform_data;
 	if (pd == NULL) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "no mv643xx_eth_platform_data\n");
+		dev_err(&pdev->dev, "no mv643xx_eth_platform_data\n");
 		return -ENODEV;
 	}
 
 	if (pd->shared == NULL) {
-		dev_printk(KERN_ERR, &pdev->dev,
-			   "no mv643xx_eth_platform_data->shared\n");
+		dev_err(&pdev->dev, "no mv643xx_eth_platform_data->shared\n");
 		return -ENODEV;
 	}
 
@@ -2957,11 +2949,11 @@
 	if (err)
 		goto out;
 
-	dev_printk(KERN_NOTICE, &dev->dev, "port %d with MAC address %pM\n",
-		   mp->port_num, dev->dev_addr);
+	netdev_notice(dev, "port %d with MAC address %pM\n",
+		      mp->port_num, dev->dev_addr);
 
 	if (mp->tx_desc_sram_size > 0)
-		dev_printk(KERN_NOTICE, &dev->dev, "configured with sram\n");
+		netdev_notice(dev, "configured with sram\n");
 
 	return 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/myri10ge/myri10ge.c linux-libre-2.6.39-gnu/drivers/net/myri10ge/myri10ge.c
--- linux-libre-2.6.38-gnu/drivers/net/myri10ge/myri10ge.c	2012-03-24 01:08:05.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/myri10ge/myri10ge.c	2012-03-24 03:30:56.000000000 -0400
@@ -253,7 +253,7 @@
 	unsigned long serial_number;
 	int vendor_specific_offset;
 	int fw_multicast_support;
-	unsigned long features;
+	u32 features;
 	u32 max_tso6;
 	u32 read_dma;
 	u32 write_dma;
@@ -1309,17 +1309,26 @@
 				 * page into an skb */
 
 static inline int
-myri10ge_rx_done(struct myri10ge_slice_state *ss, struct myri10ge_rx_buf *rx,
-		 int bytes, int len, __wsum csum)
+myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum,
+		 int lro_enabled)
 {
 	struct myri10ge_priv *mgp = ss->mgp;
 	struct sk_buff *skb;
 	struct skb_frag_struct rx_frags[MYRI10GE_MAX_FRAGS_PER_FRAME];
-	int i, idx, hlen, remainder;
+	struct myri10ge_rx_buf *rx;
+	int i, idx, hlen, remainder, bytes;
 	struct pci_dev *pdev = mgp->pdev;
 	struct net_device *dev = mgp->dev;
 	u8 *va;
 
+	if (len <= mgp->small_bytes) {
+		rx = &ss->rx_small;
+		bytes = mgp->small_bytes;
+	} else {
+		rx = &ss->rx_big;
+		bytes = mgp->big_bytes;
+	}
+
 	len += MXGEFW_PAD;
 	idx = rx->cnt & rx->mask;
 	va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
@@ -1338,7 +1347,7 @@
 		remainder -= MYRI10GE_ALLOC_SIZE;
 	}
 
-	if (dev->features & NETIF_F_LRO) {
+	if (lro_enabled) {
 		rx_frags[0].page_offset += MXGEFW_PAD;
 		rx_frags[0].size -= MXGEFW_PAD;
 		len -= MXGEFW_PAD;
@@ -1460,7 +1469,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;
@@ -1471,18 +1480,18 @@
 	u16 length;
 	__wsum checksum;
 
+	/*
+	 * Prevent compiler from generating more than one ->features memory
+	 * access to avoid theoretical race condition with functions that
+	 * change NETIF_F_LRO flag at runtime.
+	 */
+	bool lro_enabled = ACCESS_ONCE(mgp->dev->features) & NETIF_F_LRO;
+
 	while (rx_done->entry[idx].length != 0 && work_done < budget) {
 		length = ntohs(rx_done->entry[idx].length);
 		rx_done->entry[idx].length = 0;
 		checksum = csum_unfold(rx_done->entry[idx].checksum);
-		if (length <= mgp->small_bytes)
-			rx_ok = myri10ge_rx_done(ss, &ss->rx_small,
-						 mgp->small_bytes,
-						 length, checksum);
-		else
-			rx_ok = myri10ge_rx_done(ss, &ss->rx_big,
-						 mgp->big_bytes,
-						 length, checksum);
+		rx_ok = myri10ge_rx_done(ss, length, checksum, lro_enabled);
 		rx_packets += rx_ok;
 		rx_bytes += rx_ok * (unsigned long)length;
 		cnt++;
@@ -1494,7 +1503,7 @@
 	ss->stats.rx_packets += rx_packets;
 	ss->stats.rx_bytes += rx_bytes;
 
-	if (netdev->features & NETIF_F_LRO)
+	if (lro_enabled)
 		lro_flush_all(&rx_done->lro_mgr);
 
 	/* restock receive rings if needed */
@@ -1773,7 +1782,7 @@
 static int myri10ge_set_tso(struct net_device *netdev, u32 tso_enabled)
 {
 	struct myri10ge_priv *mgp = netdev_priv(netdev);
-	unsigned long flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
+	u32 flags = mgp->features & (NETIF_F_TSO6 | NETIF_F_TSO);
 
 	if (tso_enabled)
 		netdev->features |= flags;
@@ -3635,6 +3644,7 @@
 			dma_free_coherent(&pdev->dev, bytes,
 					  ss->fw_stats, ss->fw_stats_bus);
 			ss->fw_stats = NULL;
+			netif_napi_del(&ss->napi);
 		}
 	}
 	kfree(mgp->ss);
@@ -3682,7 +3692,7 @@
 
 /*
  * This function determines the number of slices supported.
- * The number slices is the minumum of the number of CPUS,
+ * The number slices is the minimum of the number of CPUS,
  * the number of MSI-X irqs supported, the number of slices
  * supported by the firmware
  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/myri_sbus.c linux-libre-2.6.39-gnu/drivers/net/myri_sbus.c
--- linux-libre-2.6.38-gnu/drivers/net/myri_sbus.c	2012-03-24 01:07:57.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/myri_sbus.c	2012-03-24 03:30:52.000000000 -0400
@@ -926,7 +926,7 @@
 	.ndo_validate_addr	= eth_validate_addr,
 };
 
-static int __devinit myri_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit myri_sbus_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	static unsigned version_printed;
@@ -1009,7 +1009,7 @@
 
 	/* Map in the MyriCOM register/localram set. */
 	if (mp->eeprom.cpuvers < CPUVERS_4_0) {
-		/* XXX Makes no sense, if control reg is non-existant this
+		/* XXX Makes no sense, if control reg is non-existent this
 		 * XXX driver cannot function at all... maybe pre-4.0 is
 		 * XXX only a valid version for PCI cards?  Ask feldy...
 		 */
@@ -1160,7 +1160,7 @@
 
 MODULE_DEVICE_TABLE(of, myri_sbus_match);
 
-static struct of_platform_driver myri_sbus_driver = {
+static struct platform_driver myri_sbus_driver = {
 	.driver = {
 		.name = "myri",
 		.owner = THIS_MODULE,
@@ -1172,12 +1172,12 @@
 
 static int __init myri_sbus_init(void)
 {
-	return of_register_platform_driver(&myri_sbus_driver);
+	return platform_driver_register(&myri_sbus_driver);
 }
 
 static void __exit myri_sbus_exit(void)
 {
-	of_unregister_platform_driver(&myri_sbus_driver);
+	platform_driver_unregister(&myri_sbus_driver);
 }
 
 module_init(myri_sbus_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/natsemi.c linux-libre-2.6.39-gnu/drivers/net/natsemi.c
--- linux-libre-2.6.38-gnu/drivers/net/natsemi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/natsemi.c	2011-05-19 00:06:34.000000000 -0400
@@ -203,7 +203,7 @@
 IIId. Synchronization
 
 Most operations are synchronized on the np->lock irq spinlock, except the
-recieve and transmit paths which are synchronised using a combination of
+receive and transmit paths which are synchronised using a combination of
 hardware descriptor ownership, disabling interrupts and NAPI poll scheduling.
 
 IVb. References
@@ -726,7 +726,7 @@
 	 * There are two addresses we must avoid:
 	 * - the address on the external phy that is used for transmission.
 	 * - the address that we want to access. User space can access phys
-	 *   on the mii bus with SIOCGMIIREG/SIOCSMIIREG, independant from the
+	 *   on the mii bus with SIOCGMIIREG/SIOCSMIIREG, independent from the
 	 *   phy that is used for transmission.
 	 */
 
@@ -860,6 +860,9 @@
 		prev_eedata = eedata;
 	}
 
+	/* Store MAC Address in perm_addr */
+	memcpy(dev->perm_addr, dev->dev_addr, ETH_ALEN);
+
 	dev->base_addr = (unsigned long __force) ioaddr;
 	dev->irq = irq;
 
@@ -1982,7 +1985,7 @@
 
 	np->rx_head_desc = &np->rx_ring[0];
 
-	/* Please be carefull before changing this loop - at least gcc-2.95.1
+	/* Please be careful before changing this loop - at least gcc-2.95.1
 	 * miscompiles it otherwise.
 	 */
 	/* Initialize all Rx descriptors. */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ne-h8300.c linux-libre-2.6.39-gnu/drivers/net/ne-h8300.c
--- linux-libre-2.6.38-gnu/drivers/net/ne-h8300.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ne-h8300.c	2011-05-19 00:06:34.000000000 -0400
@@ -167,7 +167,7 @@
 #ifndef MODULE
 struct net_device * __init ne_probe(int unit)
 {
-	struct net_device *dev = alloc_ei_netdev();
+	struct net_device *dev = ____alloc_ei_netdev(0);
 	int err;
 
 	if (!dev)
@@ -197,15 +197,15 @@
 	.ndo_open		= ne_open,
 	.ndo_stop		= ne_close,
 
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
@@ -637,7 +637,7 @@
 	int err;
 
 	for (this_dev = 0; this_dev < MAX_NE_CARDS; this_dev++) {
-		struct net_device *dev = alloc_ei_netdev();
+		struct net_device *dev = ____alloc_ei_netdev(0);
 		if (!dev)
 			break;
 		if (io[this_dev]) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/netconsole.c linux-libre-2.6.39-gnu/drivers/net/netconsole.c
--- linux-libre-2.6.38-gnu/drivers/net/netconsole.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/netconsole.c	2011-05-19 00:06:34.000000000 -0400
@@ -671,6 +671,7 @@
 		goto done;
 
 	spin_lock_irqsave(&target_list_lock, flags);
+restart:
 	list_for_each_entry(nt, &target_list, list) {
 		netconsole_target_get(nt);
 		if (nt->np.dev == dev) {
@@ -683,9 +684,16 @@
 				 * rtnl_lock already held
 				 */
 				if (nt->np.dev) {
+					spin_unlock_irqrestore(
+							      &target_list_lock,
+							      flags);
 					__netpoll_cleanup(&nt->np);
+					spin_lock_irqsave(&target_list_lock,
+							  flags);
 					dev_put(nt->np.dev);
 					nt->np.dev = NULL;
+					netconsole_target_put(nt);
+					goto restart;
 				}
 				/* Fall through */
 			case NETDEV_GOING_DOWN:
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_ctx.c linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_ctx.c
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_ctx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_ctx.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,6 +112,21 @@
 	return 0;
 }
 
+int
+nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
+			u32 speed, u32 duplex, u32 autoneg)
+{
+
+	return netxen_issue_cmd(adapter,
+				adapter->ahw.pci_func,
+				NXHAL_VERSION,
+				speed,
+				duplex,
+				autoneg,
+				NX_CDRP_CMD_CONFIG_GBE_PORT);
+
+}
+
 static int
 nx_fw_cmd_create_rx_ctx(struct netxen_adapter *adapter)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_ethtool.c linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,7 +214,6 @@
 			check_sfp_module = netif_running(dev) &&
 				adapter->has_link_events;
 		} else {
-			ecmd->autoneg = AUTONEG_ENABLE;
 			ecmd->supported |= (SUPPORTED_TP |SUPPORTED_Autoneg);
 			ecmd->advertising |=
 				(ADVERTISED_TP | ADVERTISED_Autoneg);
@@ -252,53 +251,24 @@
 netxen_nic_set_settings(struct net_device *dev, struct ethtool_cmd *ecmd)
 {
 	struct netxen_adapter *adapter = netdev_priv(dev);
-	__u32 status;
+	int ret;
 
-	/* read which mode */
-	if (adapter->ahw.port_type == NETXEN_NIC_GBE) {
-		/* autonegotiation */
-		if (adapter->phy_write &&
-		    adapter->phy_write(adapter,
-				       NETXEN_NIU_GB_MII_MGMT_ADDR_AUTONEG,
-				       ecmd->autoneg) != 0)
-			return -EIO;
-		else
-			adapter->link_autoneg = ecmd->autoneg;
+	if (adapter->ahw.port_type != NETXEN_NIC_GBE)
+		return -EOPNOTSUPP;
 
-		if (adapter->phy_read &&
-		    adapter->phy_read(adapter,
-				      NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-				      &status) != 0)
-			return -EIO;
+	if (!(adapter->capabilities & NX_FW_CAPABILITY_GBE_LINK_CFG))
+		return -EOPNOTSUPP;
 
-		/* speed */
-		switch (ecmd->speed) {
-		case SPEED_10:
-			netxen_set_phy_speed(status, 0);
-			break;
-		case SPEED_100:
-			netxen_set_phy_speed(status, 1);
-			break;
-		case SPEED_1000:
-			netxen_set_phy_speed(status, 2);
-			break;
-		}
-		/* set duplex mode */
-		if (ecmd->duplex == DUPLEX_HALF)
-			netxen_clear_phy_duplex(status);
-		if (ecmd->duplex == DUPLEX_FULL)
-			netxen_set_phy_duplex(status);
-		if (adapter->phy_write &&
-		    adapter->phy_write(adapter,
-				       NETXEN_NIU_GB_MII_MGMT_ADDR_PHY_STATUS,
-				       *((int *)&status)) != 0)
-			return -EIO;
-		else {
-			adapter->link_speed = ecmd->speed;
-			adapter->link_duplex = ecmd->duplex;
-		}
-	} else
+	ret = nx_fw_cmd_set_gbe_port(adapter, ecmd->speed, ecmd->duplex,
+				     ecmd->autoneg);
+	if (ret == NX_RCODE_NOT_SUPPORTED)
 		return -EOPNOTSUPP;
+	else if (ret)
+		return -EIO;
+
+	adapter->link_speed = ecmd->speed;
+	adapter->link_duplex = ecmd->duplex;
+	adapter->link_autoneg = ecmd->autoneg;
 
 	if (!netif_running(dev))
 		return 0;
@@ -901,7 +871,7 @@
 	struct netxen_adapter *adapter = netdev_priv(netdev);
 	int hw_lro;
 
-	if (data & ~ETH_FLAG_LRO)
+	if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
 		return -EINVAL;
 
 	if (!(adapter->capabilities & NX_FW_CAPABILITY_HW_LRO))
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic.h linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic.h
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic.h	2012-03-24 01:08:10.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic.h	2012-03-24 03:30:58.000000000 -0400
@@ -174,7 +174,7 @@
 
 #define	MAX_NUM_CARDS		4
 
-#define MAX_BUFFERS_PER_CMD	32
+#define NETXEN_MAX_FRAGS_PER_TX	14
 #define MAX_TSO_HEADER_DESC	2
 #define MGMT_CMD_DESC_RESV	4
 #define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
@@ -558,7 +558,7 @@
  */
 struct netxen_cmd_buffer {
 	struct sk_buff *skb;
-	struct netxen_skb_frag frag_array[MAX_BUFFERS_PER_CMD + 1];
+	struct netxen_skb_frag frag_array[MAX_SKB_FRAGS + 1];
 	u32 frag_count;
 };
 
@@ -739,7 +739,8 @@
 #define NX_CDRP_CMD_READ_PEXQ_PARAMETERS	0x0000001c
 #define NX_CDRP_CMD_GET_LIC_CAPABILITIES	0x0000001d
 #define NX_CDRP_CMD_READ_MAX_LRO_PER_BOARD	0x0000001e
-#define NX_CDRP_CMD_MAX				0x0000001f
+#define NX_CDRP_CMD_CONFIG_GBE_PORT		0x0000001f
+#define NX_CDRP_CMD_MAX				0x00000020
 
 #define NX_RCODE_SUCCESS		0
 #define NX_RCODE_NO_HOST_MEM		1
@@ -1054,6 +1055,7 @@
 #define NX_FW_CAPABILITY_BDG			(1 << 8)
 #define NX_FW_CAPABILITY_FVLANTX		(1 << 9)
 #define NX_FW_CAPABILITY_HW_LRO			(1 << 10)
+#define NX_FW_CAPABILITY_GBE_LINK_CFG		(1 << 11)
 
 /* module types */
 #define LINKEVENT_MODULE_NOT_PRESENT			1
@@ -1349,6 +1351,8 @@
 void netxen_pci_camqm_read_2M(struct netxen_adapter *, u64, u64 *);
 void netxen_pci_camqm_write_2M(struct netxen_adapter *, u64, u64);
 
+int nx_fw_cmd_set_gbe_port(struct netxen_adapter *adapter,
+				u32 speed, u32 duplex, u32 autoneg);
 int nx_fw_cmd_set_mtu(struct netxen_adapter *adapter, int mtu);
 int netxen_nic_change_mtu(struct net_device *netdev, int new_mtu);
 int netxen_config_hw_lro(struct netxen_adapter *adapter, int enable);
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_hdr.h linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_hdr.h
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_hdr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_hdr.h	2011-05-19 00:06:34.000000000 -0400
@@ -780,7 +780,7 @@
 
 /*
  * capabilities register, can be used to selectively enable/disable features
- * for backward compability
+ * for backward compatibility
  */
 #define CRB_NIC_CAPABILITIES_HOST	NETXEN_NIC_REG(0x1a8)
 #define CRB_NIC_MSI_MODE_HOST		NETXEN_NIC_REG(0x270)
diff -druN linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_main.c linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_main.c
--- linux-libre-2.6.38-gnu/drivers/net/netxen/netxen_nic_main.c	2012-03-24 01:08:16.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/netxen/netxen_nic_main.c	2012-03-24 03:31:02.000000000 -0400
@@ -1032,6 +1032,9 @@
 	netif_carrier_off(netdev);
 	netif_tx_disable(netdev);
 
+	if (adapter->capabilities & NX_FW_CAPABILITY_LINK_NOTIFICATION)
+		netxen_linkevent_request(adapter, 0);
+
 	if (adapter->stop_port)
 		adapter->stop_port(adapter);
 
@@ -1841,6 +1844,8 @@
 	struct cmd_desc_type0 *hwdesc, *first_desc;
 	struct pci_dev *pdev;
 	int i, k;
+	int delta = 0;
+	struct skb_frag_struct *frag;
 
 	u32 producer;
 	int frag_count, no_of_desc;
@@ -1848,6 +1853,21 @@
 
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
 
+	/* 14 frags supported for normal packet and
+	 * 32 frags supported for TSO packet
+	 */
+	if (!skb_is_gso(skb) && frag_count > NETXEN_MAX_FRAGS_PER_TX) {
+
+		for (i = 0; i < (frag_count - NETXEN_MAX_FRAGS_PER_TX); i++) {
+			frag = &skb_shinfo(skb)->frags[i];
+			delta += frag->size;
+		}
+
+		if (!__pskb_pull_tail(skb, delta))
+			goto drop_packet;
+
+		frag_count = 1 + skb_shinfo(skb)->nr_frags;
+	}
 	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/niu.c linux-libre-2.6.39-gnu/drivers/net/niu.c
--- linux-libre-2.6.38-gnu/drivers/net/niu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/niu.c	2011-05-19 00:06:34.000000000 -0400
@@ -9501,7 +9501,7 @@
 	struct niu_parent *p;
 	int i;
 
-	plat_dev = platform_device_register_simple("niu", niu_parent_index,
+	plat_dev = platform_device_register_simple("niu-board", niu_parent_index,
 						   NULL, 0);
 	if (IS_ERR(plat_dev))
 		return NULL;
@@ -10062,8 +10062,7 @@
 	.unmap_single	= niu_phys_unmap_single,
 };
 
-static int __devinit niu_of_probe(struct platform_device *op,
-				  const struct of_device_id *match)
+static int __devinit niu_of_probe(struct platform_device *op)
 {
 	union niu_parent_id parent_id;
 	struct net_device *dev;
@@ -10223,7 +10222,7 @@
 };
 MODULE_DEVICE_TABLE(of, niu_match);
 
-static struct of_platform_driver niu_of_driver = {
+static struct platform_driver niu_of_driver = {
 	.driver = {
 		.name = "niu",
 		.owner = THIS_MODULE,
@@ -10244,14 +10243,14 @@
 	niu_debug = netif_msg_init(debug, NIU_MSG_DEFAULT);
 
 #ifdef CONFIG_SPARC64
-	err = of_register_platform_driver(&niu_of_driver);
+	err = platform_driver_register(&niu_of_driver);
 #endif
 
 	if (!err) {
 		err = pci_register_driver(&niu_pci_driver);
 #ifdef CONFIG_SPARC64
 		if (err)
-			of_unregister_platform_driver(&niu_of_driver);
+			platform_driver_unregister(&niu_of_driver);
 #endif
 	}
 
@@ -10262,7 +10261,7 @@
 {
 	pci_unregister_driver(&niu_pci_driver);
 #ifdef CONFIG_SPARC64
-	of_unregister_platform_driver(&niu_of_driver);
+	platform_driver_unregister(&niu_of_driver);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ns83820.c linux-libre-2.6.39-gnu/drivers/net/ns83820.c
--- linux-libre-2.6.38-gnu/drivers/net/ns83820.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ns83820.c	2011-05-19 00:06:34.000000000 -0400
@@ -512,7 +512,7 @@
 /* Packet Receiver
  *
  * The hardware supports linked lists of receive descriptors for
- * which ownership is transfered back and forth by means of an
+ * which ownership is transferred back and forth by means of an
  * ownership bit.  While the hardware does support the use of a
  * ring for receive descriptors, we only make use of a chain in
  * an attempt to reduce bus traffic under heavy load scenarios.
@@ -1147,7 +1147,7 @@
 #ifdef NS83820_VLAN_ACCEL_SUPPORT
 	if(vlan_tx_tag_present(skb)) {
 		/* fetch the vlan tag info out of the
-		 * ancilliary data if the vlan code
+		 * ancillary data if the vlan code
 		 * is using hw vlan acceleration
 		 */
 		short tag = vlan_tx_tag_get(skb);
diff -druN linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe_ethtool.c linux-libre-2.6.39-gnu/drivers/net/pch_gbe/pch_gbe_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pch_gbe/pch_gbe_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 #include "pch_gbe_api.h"
 
 /**
- * pch_gbe_stats - Stats item infomation
+ * pch_gbe_stats - Stats item information
  */
 struct pch_gbe_stats {
 	char string[ETH_GSTRING_LEN];
diff -druN linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe.h linux-libre-2.6.39-gnu/drivers/net/pch_gbe/pch_gbe.h
--- linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pch_gbe/pch_gbe.h	2011-05-19 00:06:34.000000000 -0400
@@ -351,7 +351,7 @@
 };
 
 /**
- * struct pch_gbe_mac_info - MAC infomation
+ * struct pch_gbe_mac_info - MAC information
  * @addr[6]:		Store the MAC address
  * @fc:			Mode of flow control
  * @fc_autoneg:		Auto negotiation enable for flow control setting
@@ -375,7 +375,7 @@
 };
 
 /**
- * struct pch_gbe_phy_info - PHY infomation
+ * struct pch_gbe_phy_info - PHY information
  * @addr:		PHY address
  * @id:			PHY's identifier
  * @revision:		PHY's revision
@@ -393,7 +393,7 @@
 /*!
  * @ingroup Gigabit Ether driver Layer
  * @struct  pch_gbe_bus_info
- * @brief   Bus infomation
+ * @brief   Bus information
  */
 struct pch_gbe_bus_info {
 	u8 type;
@@ -404,7 +404,7 @@
 /*!
  * @ingroup Gigabit Ether driver Layer
  * @struct  pch_gbe_hw
- * @brief   Hardware infomation
+ * @brief   Hardware information
  */
 struct pch_gbe_hw {
 	void *back;
@@ -462,7 +462,7 @@
 
 
 /**
- * struct pch_gbe_buffer - Buffer infomation
+ * struct pch_gbe_buffer - Buffer information
  * @skb:	pointer to a socket buffer
  * @dma:	DMA address
  * @time_stamp:	time stamp
@@ -477,7 +477,7 @@
 };
 
 /**
- * struct pch_gbe_tx_ring - tx ring infomation
+ * struct pch_gbe_tx_ring - tx ring information
  * @tx_lock:	spinlock structs
  * @desc:	pointer to the descriptor ring memory
  * @dma:	physical address of the descriptor ring
@@ -499,7 +499,7 @@
 };
 
 /**
- * struct pch_gbe_rx_ring - rx ring infomation
+ * struct pch_gbe_rx_ring - rx ring information
  * @desc:	pointer to the descriptor ring memory
  * @dma:	physical address of the descriptor ring
  * @size:	length of descriptor ring in bytes
diff -druN linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe_main.c linux-libre-2.6.39-gnu/drivers/net/pch_gbe/pch_gbe_main.c
--- linux-libre-2.6.38-gnu/drivers/net/pch_gbe/pch_gbe_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pch_gbe/pch_gbe_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,10 @@
 #define PCH_GBE_COPYBREAK_DEFAULT	256
 #define PCH_GBE_PCI_BAR			1
 
+/* Macros for ML7223 */
+#define PCI_VENDOR_ID_ROHM			0x10db
+#define PCI_DEVICE_ID_ROHM_ML7223_GBE		0x8013
+
 #define PCH_GBE_TX_WEIGHT         64
 #define PCH_GBE_RX_WEIGHT         64
 #define PCH_GBE_RX_BUFFER_WRITE   16
@@ -43,8 +47,7 @@
 
 #define PCH_GBE_MAC_RGMII_CTRL_SETTING ( \
 	PCH_GBE_CHIP_TYPE_INTERNAL | \
-	PCH_GBE_RGMII_MODE_RGMII   | \
-	PCH_GBE_CRS_SEL              \
+	PCH_GBE_RGMII_MODE_RGMII     \
 	)
 
 /* Ethertype field values */
@@ -1011,7 +1014,7 @@
 	tmp_skb->len = skb->len;
 	memcpy(&tmp_skb->data[ETH_HLEN + 2], &skb->data[ETH_HLEN],
 	       (skb->len - ETH_HLEN));
-	/*-- Set Buffer infomation --*/
+	/*-- Set Buffer information --*/
 	buffer_info->length = tmp_skb->len;
 	buffer_info->dma = dma_map_single(&adapter->pdev->dev, tmp_skb->data,
 					  buffer_info->length,
@@ -1494,12 +1497,11 @@
 			/* Write meta date of skb */
 			skb_put(skb, length);
 			skb->protocol = eth_type_trans(skb, netdev);
-			if ((tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK) ==
-			    PCH_GBE_RXD_ACC_STAT_TCPIPOK) {
-				skb->ip_summed = CHECKSUM_UNNECESSARY;
-			} else {
+			if (tcp_ip_status & PCH_GBE_RXD_ACC_STAT_TCPIPOK)
 				skb->ip_summed = CHECKSUM_NONE;
-			}
+			else
+				skb->ip_summed = CHECKSUM_UNNECESSARY;
+
 			napi_gro_receive(&adapter->napi, skb);
 			(*work_done)++;
 			pr_debug("Receive skb->ip_summed: %d length: %d\n",
@@ -1540,7 +1542,7 @@
 	size = (int)sizeof(struct pch_gbe_buffer) * tx_ring->count;
 	tx_ring->buffer_info = vzalloc(size);
 	if (!tx_ring->buffer_info) {
-		pr_err("Unable to allocate memory for the buffer infomation\n");
+		pr_err("Unable to allocate memory for the buffer information\n");
 		return -ENOMEM;
 	}
 
@@ -2420,6 +2422,13 @@
 	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
 	 .class_mask = (0xFFFF00)
 	 },
+	{.vendor = PCI_VENDOR_ID_ROHM,
+	 .device = PCI_DEVICE_ID_ROHM_ML7223_GBE,
+	 .subvendor = PCI_ANY_ID,
+	 .subdevice = PCI_ANY_ID,
+	 .class = (PCI_CLASS_NETWORK_ETHERNET << 8),
+	 .class_mask = (0xFFFF00)
+	 },
 	/* required last entry */
 	{0}
 };
@@ -2441,12 +2450,12 @@
 	.resume = pch_gbe_io_resume
 };
 
-static struct pci_driver pch_gbe_pcidev = {
+static struct pci_driver pch_gbe_driver = {
 	.name = KBUILD_MODNAME,
 	.id_table = pch_gbe_pcidev_id,
 	.probe = pch_gbe_probe,
 	.remove = pch_gbe_remove,
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 	.driver.pm = &pch_gbe_pm_ops,
 #endif
 	.shutdown = pch_gbe_shutdown,
@@ -2458,7 +2467,7 @@
 {
 	int ret;
 
-	ret = pci_register_driver(&pch_gbe_pcidev);
+	ret = pci_register_driver(&pch_gbe_driver);
 	if (copybreak != PCH_GBE_COPYBREAK_DEFAULT) {
 		if (copybreak == 0) {
 			pr_info("copybreak disabled\n");
@@ -2472,7 +2481,7 @@
 
 static void __exit pch_gbe_exit_module(void)
 {
-	pci_unregister_driver(&pch_gbe_pcidev);
+	pci_unregister_driver(&pch_gbe_driver);
 }
 
 module_init(pch_gbe_init_module);
diff -druN linux-libre-2.6.38-gnu/drivers/net/pci-skeleton.c linux-libre-2.6.39-gnu/drivers/net/pci-skeleton.c
--- linux-libre-2.6.38-gnu/drivers/net/pci-skeleton.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pci-skeleton.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,7 +214,7 @@
 	{ "SMC1211TX EZCard 10/100 (RealTek RTL8139)" },
 /*	{ MPX5030, "Accton MPX5030 (RealTek RTL8139)" },*/
 	{ "Delta Electronics 8139 10/100BaseTX" },
-	{ "Addtron Technolgy 8139 10/100BaseTX" },
+	{ "Addtron Technology 8139 10/100BaseTX" },
 };
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/pcmcia/3c574_cs.c linux-libre-2.6.39-gnu/drivers/net/pcmcia/3c574_cs.c
--- linux-libre-2.6.38-gnu/drivers/net/pcmcia/3c574_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pcmcia/3c574_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -950,7 +950,7 @@
 }
 
 /*  Update statistics.
-	Suprisingly this need not be run single-threaded, but it effectively is.
+	Surprisingly this need not be run single-threaded, but it effectively is.
 	The counters clear when read, so the adds must merely be atomic.
  */
 static void update_stats(struct net_device *dev)
diff -druN linux-libre-2.6.38-gnu/drivers/net/pcmcia/axnet_cs.c linux-libre-2.6.39-gnu/drivers/net/pcmcia/axnet_cs.c
--- linux-libre-2.6.38-gnu/drivers/net/pcmcia/axnet_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pcmcia/axnet_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -780,7 +780,7 @@
   Alexey Kuznetsov	: use the 8390's six bit hash multicast filter.
   Paul Gortmaker	: tweak ANK's above multicast changes a bit.
   Paul Gortmaker	: update packet statistics for v2.1.x
-  Alan Cox		: support arbitary stupid port mappings on the
+  Alan Cox		: support arbitrary stupid port mappings on the
   			  68K Macintosh. Support >16bit I/O spaces
   Paul Gortmaker	: add kmod support for auto-loading of the 8390
 			  module by all drivers that require it.
@@ -842,7 +842,7 @@
 /*
  *	SMP and the 8390 setup.
  *
- *	The 8390 isnt exactly designed to be multithreaded on RX/TX. There is
+ *	The 8390 isn't exactly designed to be multithreaded on RX/TX. There is
  *	a page register that controls bank and packet buffer access. We guard
  *	this with ei_local->page_lock. Nobody should assume or set the page other
  *	than zero when the lock is not held. Lock holders must restore page 0
diff -druN linux-libre-2.6.38-gnu/drivers/net/pcmcia/smc91c92_cs.c linux-libre-2.6.39-gnu/drivers/net/pcmcia/smc91c92_cs.c
--- linux-libre-2.6.38-gnu/drivers/net/pcmcia/smc91c92_cs.c	2012-03-24 01:09:48.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pcmcia/smc91c92_cs.c	2012-03-24 03:31:50.000000000 -0400
@@ -1264,7 +1264,7 @@
 
 /*======================================================================
 
-    Handle a Tx anomolous event.  Entered while in Window 2.
+    Handle a Tx anomalous event.  Entered while in Window 2.
 
 ======================================================================*/
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/pcnet32.c linux-libre-2.6.39-gnu/drivers/net/pcnet32.c
--- linux-libre-2.6.38-gnu/drivers/net/pcnet32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pcnet32.c	2011-05-19 00:06:34.000000000 -0400
@@ -1651,7 +1651,7 @@
 	/*
 	 *  On selected chips turn on the BCR18:NOUFLO bit. This stops transmit
 	 *  starting until the packet is loaded. Strike one for reliability, lose
-	 *  one for latency - although on PCI this isnt a big loss. Older chips
+	 *  one for latency - although on PCI this isn't a big loss. Older chips
 	 *  have FIFO's smaller than a packet, so you can't do this.
 	 *  Turn on BCR18:BurstRdEn and BCR18:BurstWrEn.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/phy/Kconfig linux-libre-2.6.39-gnu/drivers/net/phy/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/phy/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/phy/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -77,7 +77,6 @@
 	  Currently supports the DP83865 PHY.
 
 config STE10XP
-	depends on PHYLIB
 	tristate "Driver for STMicroelectronics STe10Xp PHYs"
 	---help---
 	  This is the driver for the STe100p and STe101p PHYs.
diff -druN linux-libre-2.6.38-gnu/drivers/net/phy/mdio-gpio.c linux-libre-2.6.39-gnu/drivers/net/phy/mdio-gpio.c
--- linux-libre-2.6.38-gnu/drivers/net/phy/mdio-gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/phy/mdio-gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -188,8 +188,7 @@
 
 #ifdef CONFIG_OF_GPIO
 
-static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev,
-                                        const struct of_device_id *match)
+static int __devinit mdio_ofgpio_probe(struct platform_device *ofdev)
 {
 	struct mdio_gpio_platform_data *pdata;
 	struct mii_bus *new_bus;
@@ -240,7 +239,7 @@
 };
 MODULE_DEVICE_TABLE(of, mdio_ofgpio_match);
 
-static struct of_platform_driver mdio_ofgpio_driver = {
+static struct platform_driver mdio_ofgpio_driver = {
 	.driver = {
 		.name = "mdio-gpio",
 		.owner = THIS_MODULE,
@@ -252,12 +251,12 @@
 
 static inline int __init mdio_ofgpio_init(void)
 {
-	return of_register_platform_driver(&mdio_ofgpio_driver);
+	return platform_driver_register(&mdio_ofgpio_driver);
 }
 
 static inline void __exit mdio_ofgpio_exit(void)
 {
-	of_unregister_platform_driver(&mdio_ofgpio_driver);
+	platform_driver_unregister(&mdio_ofgpio_driver);
 }
 #else
 static inline int __init mdio_ofgpio_init(void) { return 0; }
diff -druN linux-libre-2.6.38-gnu/drivers/net/phy/micrel.c linux-libre-2.6.39-gnu/drivers/net/phy/micrel.c
--- linux-libre-2.6.38-gnu/drivers/net/phy/micrel.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/phy/micrel.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,13 +19,7 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/phy.h>
-
-#define	PHY_ID_KSZ9021			0x00221611
-#define	PHY_ID_KS8737			0x00221720
-#define	PHY_ID_KS8041			0x00221510
-#define	PHY_ID_KS8051			0x00221550
-/* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
-#define	PHY_ID_KS8001			0x0022161A
+#include <linux/micrel_phy.h>
 
 /* general Interrupt control/status reg in vendor specific block. */
 #define MII_KSZPHY_INTCS			0x1B
@@ -46,6 +40,7 @@
 #define KSZPHY_CTRL_INT_ACTIVE_HIGH		(1 << 9)
 #define KSZ9021_CTRL_INT_ACTIVE_HIGH		(1 << 14)
 #define KS8737_CTRL_INT_ACTIVE_HIGH		(1 << 14)
+#define KSZ8051_RMII_50MHZ_CLK			(1 << 7)
 
 static int kszphy_ack_interrupt(struct phy_device *phydev)
 {
@@ -106,6 +101,19 @@
 	return 0;
 }
 
+static int ks8051_config_init(struct phy_device *phydev)
+{
+	int regval;
+
+	if (phydev->dev_flags & MICREL_PHY_50MHZ_CLK) {
+		regval = phy_read(phydev, MII_KSZPHY_CTRL);
+		regval |= KSZ8051_RMII_50MHZ_CLK;
+		phy_write(phydev, MII_KSZPHY_CTRL, regval);
+	}
+
+	return 0;
+}
+
 static struct phy_driver ks8737_driver = {
 	.phy_id		= PHY_ID_KS8737,
 	.phy_id_mask	= 0x00fffff0,
@@ -142,7 +150,7 @@
 	.features	= (PHY_BASIC_FEATURES | SUPPORTED_Pause
 				| SUPPORTED_Asym_Pause),
 	.flags		= PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
-	.config_init	= kszphy_config_init,
+	.config_init	= ks8051_config_init,
 	.config_aneg	= genphy_config_aneg,
 	.read_status	= genphy_read_status,
 	.ack_interrupt	= kszphy_ack_interrupt,
diff -druN linux-libre-2.6.38-gnu/drivers/net/phy/phy.c linux-libre-2.6.39-gnu/drivers/net/phy/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/phy/phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/phy/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -319,7 +319,8 @@
 		/* fall through */
 
 	case SIOCGMIIREG:
-		mii_data->val_out = phy_read(phydev, mii_data->reg_num);
+		mii_data->val_out = mdiobus_read(phydev->bus, mii_data->phy_id,
+						 mii_data->reg_num);
 		break;
 
 	case SIOCSMIIREG:
@@ -350,8 +351,9 @@
 			}
 		}
 
-		phy_write(phydev, mii_data->reg_num, val);
-		
+		mdiobus_write(phydev->bus, mii_data->phy_id,
+			      mii_data->reg_num, val);
+
 		if (mii_data->reg_num == MII_BMCR &&
 		    val & BMCR_RESET &&
 		    phydev->drv->config_init) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/phy/phy_device.c linux-libre-2.6.39-gnu/drivers/net/phy/phy_device.c
--- linux-libre-2.6.38-gnu/drivers/net/phy/phy_device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/phy/phy_device.c	2011-05-19 00:06:34.000000000 -0400
@@ -442,11 +442,11 @@
 			     u32 flags, phy_interface_t interface)
 {
 	struct device *d = &phydev->dev;
+	int err;
 
 	/* Assume that if there is no driver, that it doesn't
 	 * exist, and we should use the genphy driver. */
 	if (NULL == d->driver) {
-		int err;
 		d->driver = &genphy_driver.driver;
 
 		err = d->driver->probe(d);
@@ -474,7 +474,11 @@
 	/* Do initial configuration here, now that
 	 * we have certain key parameters
 	 * (dev_flags and interface) */
-	return phy_init_hw(phydev);
+	err = phy_init_hw(phydev);
+	if (err)
+		phy_detach(phydev);
+
+	return err;
 }
 
 /**
@@ -534,7 +538,7 @@
 /* Generic PHY support and helper functions */
 
 /**
- * genphy_config_advert - sanitize and advertise auto-negotation parameters
+ * genphy_config_advert - sanitize and advertise auto-negotiation parameters
  * @phydev: target phy_device struct
  *
  * Description: Writes MII_ADVERTISE with the appropriate values,
@@ -683,7 +687,7 @@
 		return result;
 
 	if (result == 0) {
-		/* Advertisment hasn't changed, but maybe aneg was never on to
+		/* Advertisement hasn't changed, but maybe aneg was never on to
 		 * begin with?  Or maybe phy was isolated? */
 		int ctl = phy_read(phydev, MII_BMCR);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ppp_deflate.c linux-libre-2.6.39-gnu/drivers/net/ppp_deflate.c
--- linux-libre-2.6.38-gnu/drivers/net/ppp_deflate.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ppp_deflate.c	2011-05-19 00:06:34.000000000 -0400
@@ -129,7 +129,7 @@
 
 	state->strm.next_in   = NULL;
 	state->w_size         = w_size;
-	state->strm.workspace = vmalloc(zlib_deflate_workspacesize());
+	state->strm.workspace = vmalloc(zlib_deflate_workspacesize(-w_size, 8));
 	if (state->strm.workspace == NULL)
 		goto out_free;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/ppp_generic.c linux-libre-2.6.39-gnu/drivers/net/ppp_generic.c
--- linux-libre-2.6.38-gnu/drivers/net/ppp_generic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ppp_generic.c	2011-05-19 00:06:34.000000000 -0400
@@ -592,8 +592,8 @@
 			ppp_release(NULL, file);
 			err = 0;
 		} else
-			printk(KERN_DEBUG "PPPIOCDETACH file->f_count=%ld\n",
-			       atomic_long_read(&file->f_count));
+			pr_warn("PPPIOCDETACH file->f_count=%ld\n",
+				atomic_long_read(&file->f_count));
 		mutex_unlock(&ppp_mutex);
 		return err;
 	}
@@ -630,7 +630,7 @@
 
 	if (pf->kind != INTERFACE) {
 		/* can't happen */
-		printk(KERN_ERR "PPP: not interface or channel??\n");
+		pr_err("PPP: not interface or channel??\n");
 		return -EINVAL;
 	}
 
@@ -704,7 +704,8 @@
 		}
 		vj = slhc_init(val2+1, val+1);
 		if (!vj) {
-			printk(KERN_ERR "PPP: no memory (VJ compressor)\n");
+			netdev_err(ppp->dev,
+				   "PPP: no memory (VJ compressor)\n");
 			err = -ENOMEM;
 			break;
 		}
@@ -898,17 +899,17 @@
 {
 	int err;
 
-	printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
+	pr_info("PPP generic driver version " PPP_VERSION "\n");
 
 	err = register_pernet_device(&ppp_net_ops);
 	if (err) {
-		printk(KERN_ERR "failed to register PPP pernet device (%d)\n", err);
+		pr_err("failed to register PPP pernet device (%d)\n", err);
 		goto out;
 	}
 
 	err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
 	if (err) {
-		printk(KERN_ERR "failed to register PPP device (%d)\n", err);
+		pr_err("failed to register PPP device (%d)\n", err);
 		goto out_net;
 	}
 
@@ -1078,7 +1079,7 @@
 	new_skb = alloc_skb(new_skb_size, GFP_ATOMIC);
 	if (!new_skb) {
 		if (net_ratelimit())
-			printk(KERN_ERR "PPP: no memory (comp pkt)\n");
+			netdev_err(ppp->dev, "PPP: no memory (comp pkt)\n");
 		return NULL;
 	}
 	if (ppp->dev->hard_header_len > PPP_HDRLEN)
@@ -1108,7 +1109,7 @@
 		 * the same number.
 		 */
 		if (net_ratelimit())
-			printk(KERN_ERR "ppp: compressor dropped pkt\n");
+			netdev_err(ppp->dev, "ppp: compressor dropped pkt\n");
 		kfree_skb(skb);
 		kfree_skb(new_skb);
 		new_skb = NULL;
@@ -1138,7 +1139,9 @@
 		if (ppp->pass_filter &&
 		    sk_run_filter(skb, ppp->pass_filter) == 0) {
 			if (ppp->debug & 1)
-				printk(KERN_DEBUG "PPP: outbound frame not passed\n");
+				netdev_printk(KERN_DEBUG, ppp->dev,
+					      "PPP: outbound frame "
+					      "not passed\n");
 			kfree_skb(skb);
 			return;
 		}
@@ -1164,7 +1167,7 @@
 		new_skb = alloc_skb(skb->len + ppp->dev->hard_header_len - 2,
 				    GFP_ATOMIC);
 		if (!new_skb) {
-			printk(KERN_ERR "PPP: no memory (VJ comp pkt)\n");
+			netdev_err(ppp->dev, "PPP: no memory (VJ comp pkt)\n");
 			goto drop;
 		}
 		skb_reserve(new_skb, ppp->dev->hard_header_len - 2);
@@ -1202,7 +1205,9 @@
 	    proto != PPP_LCP && proto != PPP_CCP) {
 		if (!(ppp->flags & SC_CCP_UP) && (ppp->flags & SC_MUST_COMP)) {
 			if (net_ratelimit())
-				printk(KERN_ERR "ppp: compression required but down - pkt dropped.\n");
+				netdev_err(ppp->dev,
+					   "ppp: compression required but "
+					   "down - pkt dropped.\n");
 			goto drop;
 		}
 		skb = pad_compress_skb(ppp, skb);
@@ -1443,7 +1448,7 @@
 
 		/*
 		 *check if we are on the last channel or
-		 *we exceded the lenght of the data to
+		 *we exceded the length of the data to
 		 *fragment
 		 */
 		if ((nfree <= 0) || (flen > len))
@@ -1505,7 +1510,7 @@
  noskb:
 	spin_unlock_bh(&pch->downl);
 	if (ppp->debug & 1)
-		printk(KERN_ERR "PPP: no memory (fragment)\n");
+		netdev_err(ppp->dev, "PPP: no memory (fragment)\n");
 	++ppp->dev->stats.tx_errors;
 	++ppp->nxseq;
 	return 1;	/* abandon the frame */
@@ -1686,7 +1691,8 @@
 			/* copy to a new sk_buff with more tailroom */
 			ns = dev_alloc_skb(skb->len + 128);
 			if (!ns) {
-				printk(KERN_ERR"PPP: no memory (VJ decomp)\n");
+				netdev_err(ppp->dev, "PPP: no memory "
+					   "(VJ decomp)\n");
 				goto err;
 			}
 			skb_reserve(ns, 2);
@@ -1699,7 +1705,8 @@
 
 		len = slhc_uncompress(ppp->vj, skb->data + 2, skb->len - 2);
 		if (len <= 0) {
-			printk(KERN_DEBUG "PPP: VJ decompression error\n");
+			netdev_printk(KERN_DEBUG, ppp->dev,
+				      "PPP: VJ decompression error\n");
 			goto err;
 		}
 		len += 2;
@@ -1721,7 +1728,7 @@
 			goto err;
 
 		if (slhc_remember(ppp->vj, skb->data + 2, skb->len - 2) <= 0) {
-			printk(KERN_ERR "PPP: VJ uncompressed error\n");
+			netdev_err(ppp->dev, "PPP: VJ uncompressed error\n");
 			goto err;
 		}
 		proto = PPP_IP;
@@ -1762,8 +1769,9 @@
 			if (ppp->pass_filter &&
 			    sk_run_filter(skb, ppp->pass_filter) == 0) {
 				if (ppp->debug & 1)
-					printk(KERN_DEBUG "PPP: inbound frame "
-					       "not passed\n");
+					netdev_printk(KERN_DEBUG, ppp->dev,
+						      "PPP: inbound frame "
+						      "not passed\n");
 				kfree_skb(skb);
 				return;
 			}
@@ -1821,7 +1829,8 @@
 
 		ns = dev_alloc_skb(obuff_size);
 		if (!ns) {
-			printk(KERN_ERR "ppp_decompress_frame: no memory\n");
+			netdev_err(ppp->dev, "ppp_decompress_frame: "
+				   "no memory\n");
 			goto err;
 		}
 		/* the decompressor still expects the A/C bytes in the hdr */
@@ -1989,7 +1998,7 @@
 	u32 seq = ppp->nextseq;
 	u32 minseq = ppp->minseq;
 	struct sk_buff_head *list = &ppp->mrq;
-	struct sk_buff *p, *next;
+	struct sk_buff *p, *tmp;
 	struct sk_buff *head, *tail;
 	struct sk_buff *skb = NULL;
 	int lost = 0, len = 0;
@@ -1998,13 +2007,15 @@
 		return NULL;
 	head = list->next;
 	tail = NULL;
-	for (p = head; p != (struct sk_buff *) list; p = next) {
-		next = p->next;
+	skb_queue_walk_safe(list, p, tmp) {
+	again:
 		if (seq_before(PPP_MP_CB(p)->sequence, seq)) {
 			/* this can't happen, anyway ignore the skb */
-			printk(KERN_ERR "ppp_mp_reconstruct bad seq %u < %u\n",
-			       PPP_MP_CB(p)->sequence, seq);
-			head = next;
+			netdev_err(ppp->dev, "ppp_mp_reconstruct bad "
+				   "seq %u < %u\n",
+				   PPP_MP_CB(p)->sequence, seq);
+			__skb_unlink(p, list);
+			kfree_skb(p);
 			continue;
 		}
 		if (PPP_MP_CB(p)->sequence != seq) {
@@ -2016,8 +2027,7 @@
 			lost = 1;
 			seq = seq_before(minseq, PPP_MP_CB(p)->sequence)?
 				minseq + 1: PPP_MP_CB(p)->sequence;
-			next = p;
-			continue;
+			goto again;
 		}
 
 		/*
@@ -2042,17 +2052,9 @@
 		    (PPP_MP_CB(head)->BEbits & B)) {
 			if (len > ppp->mrru + 2) {
 				++ppp->dev->stats.rx_length_errors;
-				printk(KERN_DEBUG "PPP: reconstructed packet"
-				       " is too long (%d)\n", len);
-			} else if (p == head) {
-				/* fragment is complete packet - reuse skb */
-				tail = p;
-				skb = skb_get(p);
-				break;
-			} else if ((skb = dev_alloc_skb(len)) == NULL) {
-				++ppp->dev->stats.rx_missed_errors;
-				printk(KERN_DEBUG "PPP: no memory for "
-				       "reconstructed packet");
+				netdev_printk(KERN_DEBUG, ppp->dev,
+					      "PPP: reconstructed packet"
+					      " is too long (%d)\n", len);
 			} else {
 				tail = p;
 				break;
@@ -2065,9 +2067,17 @@
 		 * and we haven't found a complete valid packet yet,
 		 * we can discard up to and including this fragment.
 		 */
-		if (PPP_MP_CB(p)->BEbits & E)
-			head = next;
+		if (PPP_MP_CB(p)->BEbits & E) {
+			struct sk_buff *tmp2;
 
+			skb_queue_reverse_walk_from_safe(list, p, tmp2) {
+				__skb_unlink(p, list);
+				kfree_skb(p);
+			}
+			head = skb_peek(list);
+			if (!head)
+				break;
+		}
 		++seq;
 	}
 
@@ -2077,26 +2087,37 @@
 		   signal a receive error. */
 		if (PPP_MP_CB(head)->sequence != ppp->nextseq) {
 			if (ppp->debug & 1)
-				printk(KERN_DEBUG "  missed pkts %u..%u\n",
-				       ppp->nextseq,
-				       PPP_MP_CB(head)->sequence-1);
+				netdev_printk(KERN_DEBUG, ppp->dev,
+					      "  missed pkts %u..%u\n",
+					      ppp->nextseq,
+					      PPP_MP_CB(head)->sequence-1);
 			++ppp->dev->stats.rx_dropped;
 			ppp_receive_error(ppp);
 		}
 
-		if (head != tail)
-			/* copy to a single skb */
-			for (p = head; p != tail->next; p = p->next)
-				skb_copy_bits(p, 0, skb_put(skb, p->len), p->len);
-		ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
-		head = tail->next;
-	}
+		skb = head;
+		if (head != tail) {
+			struct sk_buff **fragpp = &skb_shinfo(skb)->frag_list;
+			p = skb_queue_next(list, head);
+			__skb_unlink(skb, list);
+			skb_queue_walk_from_safe(list, p, tmp) {
+				__skb_unlink(p, list);
+				*fragpp = p;
+				p->next = NULL;
+				fragpp = &p->next;
 
-	/* Discard all the skbuffs that we have copied the data out of
-	   or that we can't use. */
-	while ((p = list->next) != head) {
-		__skb_unlink(p, list);
-		kfree_skb(p);
+				skb->len += p->len;
+				skb->data_len += p->len;
+				skb->truesize += p->len;
+
+				if (p == tail)
+					break;
+			}
+		} else {
+			__skb_unlink(skb, list);
+		}
+
+		ppp->nextseq = PPP_MP_CB(tail)->sequence + 1;
 	}
 
 	return skb;
@@ -2617,8 +2638,8 @@
 	ret = register_netdev(dev);
 	if (ret != 0) {
 		unit_put(&pn->units_idr, unit);
-		printk(KERN_ERR "PPP: couldn't register device %s (%d)\n",
-		       dev->name, ret);
+		netdev_err(ppp->dev, "PPP: couldn't register device %s (%d)\n",
+			   dev->name, ret);
 		goto out2;
 	}
 
@@ -2690,9 +2711,9 @@
 
 	if (!ppp->file.dead || ppp->n_channels) {
 		/* "can't happen" */
-		printk(KERN_ERR "ppp: destroying ppp struct %p but dead=%d "
-		       "n_channels=%d !\n", ppp, ppp->file.dead,
-		       ppp->n_channels);
+		netdev_err(ppp->dev, "ppp: destroying ppp struct %p "
+			   "but dead=%d n_channels=%d !\n",
+			   ppp, ppp->file.dead, ppp->n_channels);
 		return;
 	}
 
@@ -2834,8 +2855,7 @@
 
 	if (!pch->file.dead) {
 		/* "can't happen" */
-		printk(KERN_ERR "ppp: destroying undead channel %p !\n",
-		       pch);
+		pr_err("ppp: destroying undead channel %p !\n", pch);
 		return;
 	}
 	skb_queue_purge(&pch->file.xq);
@@ -2847,7 +2867,7 @@
 {
 	/* should never happen */
 	if (atomic_read(&ppp_unit_count) || atomic_read(&channel_count))
-		printk(KERN_ERR "PPP: removing module but units remain!\n");
+		pr_err("PPP: removing module but units remain!\n");
 	unregister_chrdev(PPP_MAJOR, "ppp");
 	device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
 	class_destroy(ppp_class);
@@ -2865,7 +2885,7 @@
 
 again:
 	if (!idr_pre_get(p, GFP_KERNEL)) {
-		printk(KERN_ERR "PPP: No free memory for idr\n");
+		pr_err("PPP: No free memory for idr\n");
 		return -ENOMEM;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/pppoe.c linux-libre-2.6.39-gnu/drivers/net/pppoe.c
--- linux-libre-2.6.38-gnu/drivers/net/pppoe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pppoe.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,7 @@
  * 2) Session stage (MAC and SID are known)
  *
  * Ethernet frames have a special tag for this but
- * we use simplier approach based on session id
+ * we use simpler approach based on session id
  */
 static inline bool stage_session(__be16 sid)
 {
@@ -317,7 +317,7 @@
 			lock_sock(sk);
 
 			if (po->pppoe_dev == dev &&
-			    sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+			    sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
 				pppox_unbind_sock(sk);
 				sk->sk_state = PPPOX_ZOMBIE;
 				sk->sk_state_change(sk);
diff -druN linux-libre-2.6.38-gnu/drivers/net/ppp_synctty.c linux-libre-2.6.39-gnu/drivers/net/ppp_synctty.c
--- linux-libre-2.6.38-gnu/drivers/net/ppp_synctty.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ppp_synctty.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,7 @@
  * way to fix this is to use a rwlock in the tty struct, but for now
  * we use a single global rwlock for all ttys in ppp line discipline.
  *
- * FIXME: Fixed in tty_io nowdays.
+ * FIXME: Fixed in tty_io nowadays.
  */
 static DEFINE_RWLOCK(disc_data_lock);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/pptp.c linux-libre-2.6.39-gnu/drivers/net/pptp.c
--- linux-libre-2.6.38-gnu/drivers/net/pptp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pptp.c	2011-05-19 00:06:34.000000000 -0400
@@ -175,7 +175,6 @@
 	struct pptp_opt *opt = &po->proto.pptp;
 	struct pptp_gre_header *hdr;
 	unsigned int header_len = sizeof(*hdr);
-	int err = 0;
 	int islcp;
 	int len;
 	unsigned char *data;
@@ -190,18 +189,14 @@
 	if (sk_pppox(po)->sk_state & PPPOX_DEAD)
 		goto tx_error;
 
-	{
-		struct flowi fl = { .oif = 0,
-			.nl_u = {
-				.ip4_u = {
-					.daddr = opt->dst_addr.sin_addr.s_addr,
-					.saddr = opt->src_addr.sin_addr.s_addr,
-					.tos = RT_TOS(0) } },
-			.proto = IPPROTO_GRE };
-		err = ip_route_output_key(&init_net, &rt, &fl);
-		if (err)
-			goto tx_error;
-	}
+	rt = ip_route_output_ports(&init_net, NULL,
+				   opt->dst_addr.sin_addr.s_addr,
+				   opt->src_addr.sin_addr.s_addr,
+				   0, 0, IPPROTO_GRE,
+				   RT_TOS(0), 0);
+	if (IS_ERR(rt))
+		goto tx_error;
+
 	tdev = rt->dst.dev;
 
 	max_headroom = LL_RESERVED_SPACE(tdev) + sizeof(*iph) + sizeof(*hdr) + 2;
@@ -468,21 +463,17 @@
 	po->chan.private = sk;
 	po->chan.ops = &pptp_chan_ops;
 
-	{
-		struct flowi fl = {
-			.nl_u = {
-				.ip4_u = {
-					.daddr = opt->dst_addr.sin_addr.s_addr,
-					.saddr = opt->src_addr.sin_addr.s_addr,
-					.tos = RT_CONN_FLAGS(sk) } },
-			.proto = IPPROTO_GRE };
-		security_sk_classify_flow(sk, &fl);
-		if (ip_route_output_key(&init_net, &rt, &fl)) {
-			error = -EHOSTUNREACH;
-			goto end;
-		}
-		sk_setup_caps(sk, &rt->dst);
+	rt = ip_route_output_ports(&init_net, sk,
+				   opt->dst_addr.sin_addr.s_addr,
+				   opt->src_addr.sin_addr.s_addr,
+				   0, 0,
+				   IPPROTO_GRE, RT_CONN_FLAGS(sk), 0);
+	if (IS_ERR(rt)) {
+		error = -EHOSTUNREACH;
+		goto end;
 	}
+	sk_setup_caps(sk, &rt->dst);
+
 	po->chan.mtu = dst_mtu(&rt->dst);
 	if (!po->chan.mtu)
 		po->chan.mtu = PPP_MTU;
diff -druN linux-libre-2.6.38-gnu/drivers/net/ps3_gelic_net.c linux-libre-2.6.39-gnu/drivers/net/ps3_gelic_net.c
--- linux-libre-2.6.38-gnu/drivers/net/ps3_gelic_net.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ps3_gelic_net.c	2011-05-19 00:06:34.000000000 -0400
@@ -632,7 +632,7 @@
  * @card: card structure
  *
  * gelic_card_disable_rxdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
+ * turing off DMA and issuing a force end
  */
 static inline void gelic_card_disable_rxdmac(struct gelic_card *card)
 {
@@ -650,7 +650,7 @@
  * @card: card structure
  *
  * gelic_card_disable_txdmac terminates processing on the DMA controller by
- * turing off DMA and issueing a force end
+ * turing off DMA and issuing a force end
  */
 static inline void gelic_card_disable_txdmac(struct gelic_card *card)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/ps3_gelic_net.h linux-libre-2.6.39-gnu/drivers/net/ps3_gelic_net.h
--- linux-libre-2.6.38-gnu/drivers/net/ps3_gelic_net.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ps3_gelic_net.h	2011-05-19 00:06:34.000000000 -0400
@@ -117,7 +117,7 @@
 	GELIC_DESCR_RXDATAERR	= 0x00020000, /* IP packet format error */
 	GELIC_DESCR_RXCALERR	= 0x00010000, /* cariier extension length
 					      * error */
-	GELIC_DESCR_RXCREXERR	= 0x00008000, /* carrier extention error */
+	GELIC_DESCR_RXCREXERR	= 0x00008000, /* carrier extension error */
 	GELIC_DESCR_RXMLTCST	= 0x00004000, /* multicast address frame */
 	/* bit 13..0 reserved */
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/ps3_gelic_wireless.c linux-libre-2.6.39-gnu/drivers/net/ps3_gelic_wireless.c
--- linux-libre-2.6.38-gnu/drivers/net/ps3_gelic_wireless.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ps3_gelic_wireless.c	2011-05-19 00:06:34.000000000 -0400
@@ -814,7 +814,7 @@
 			 * you will not decide suitable cipher from
 			 * its beacon.
 			 * You should have knowledge about the AP's
-			 * cipher infomation in other method prior to
+			 * cipher information in other method prior to
 			 * the association.
 			 */
 			if (!precise_ie())
diff -druN linux-libre-2.6.38-gnu/drivers/net/pxa168_eth.c linux-libre-2.6.39-gnu/drivers/net/pxa168_eth.c
--- linux-libre-2.6.38-gnu/drivers/net/pxa168_eth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/pxa168_eth.c	2011-05-19 00:06:34.000000000 -0400
@@ -462,7 +462,7 @@
  * pep - ETHERNET .
  * mac_addr - MAC address.
  * skip - if 1, skip this address.Used in case of deleting an entry which is a
- *	  part of chain in the hash table.We cant just delete the entry since
+ *	  part of chain in the hash table.We can't just delete the entry since
  *	  that will break the chain.We need to defragment the tables time to
  *	  time.
  * rd   - 0 Discard packet upon match.
diff -druN linux-libre-2.6.38-gnu/drivers/net/qla3xxx.c linux-libre-2.6.39-gnu/drivers/net/qla3xxx.c
--- linux-libre-2.6.38-gnu/drivers/net/qla3xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/qla3xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -379,7 +379,7 @@
 {
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_1;
 	ql_write_nvram_reg(qdev, spir, ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
@@ -398,7 +398,7 @@
 	u32 previousBit;
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	/* Clock in a zero, then do the start bit */
 	ql_write_nvram_reg(qdev, spir,
@@ -467,7 +467,7 @@
 {
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	qdev->eeprom_cmd_data = AUBURN_EEPROM_CS_0;
 	ql_write_nvram_reg(qdev, spir, ISP_NVRAM_MASK | qdev->eeprom_cmd_data);
@@ -483,7 +483,7 @@
 	u32 dataBit;
 	struct ql3xxx_port_registers __iomem *port_regs =
 			qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 
 	/* Read the data bits */
 	/* The first bit is a dummy.  Clock right over it. */
@@ -2460,7 +2460,7 @@
  * The 3032 supports sglists by using the 3 addr/len pairs (ALP)
  * in the IOCB plus a chain of outbound address lists (OAL) that
  * each contain 5 ALPs.  The last ALP of the IOCB (3rd) or OAL (5th)
- * will used to point to an OAL when more ALP entries are required.
+ * will be used to point to an OAL when more ALP entries are required.
  * The IOCB is always the top of the chain followed by one or more
  * OALs (when necessary).
  */
@@ -3011,7 +3011,7 @@
 	u32 value;
 	struct ql3xxx_port_registers __iomem *port_regs =
 		qdev->mem_map_registers;
-	u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
+	__iomem u32 *spir = &port_regs->CommonRegs.serialPortInterfaceReg;
 	struct ql3xxx_host_memory_registers __iomem *hmem_regs =
 		(void __iomem *)port_regs;
 	u32 delay = 10;
diff -druN linux-libre-2.6.38-gnu/drivers/net/qla3xxx.h linux-libre-2.6.39-gnu/drivers/net/qla3xxx.h
--- linux-libre-2.6.38-gnu/drivers/net/qla3xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/qla3xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -770,7 +770,7 @@
 	FM93C56A_WDS = 0x0,
 	FM93C56A_ERASE = 0x3,
 	FM93C56A_ERASE_ALL = 0x0,
-/* Command Extentions */
+/* Command Extensions */
 	FM93C56A_WEN_EXT = 0x3,
 	FM93C56A_WRITE_ALL_EXT = 0x1,
 	FM93C56A_WDS_EXT = 0x0,
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_ethtool.c linux-libre-2.6.39-gnu/drivers/net/qlcnic/qlcnic_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/qlcnic/qlcnic_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -1003,7 +1003,7 @@
 	struct qlcnic_adapter *adapter = netdev_priv(netdev);
 	int hw_lro;
 
-	if (data & ~ETH_FLAG_LRO)
+	if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
 		return -EINVAL;
 
 	if (!(adapter->capabilities & QLCNIC_FW_CAPABILITY_HW_LRO))
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic.h linux-libre-2.6.39-gnu/drivers/net/qlcnic/qlcnic.h
--- linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic.h	2012-03-24 01:08:21.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/qlcnic/qlcnic.h	2012-03-24 03:31:04.000000000 -0400
@@ -99,6 +99,7 @@
 #define TX_UDPV6_PKT	0x0c
 
 /* Tx defines */
+#define QLCNIC_MAX_FRAGS_PER_TX	14
 #define MAX_TSO_HEADER_DESC	2
 #define MGMT_CMD_DESC_RESV	4
 #define TX_STOP_THRESH		((MAX_SKB_FRAGS >> 2) + MAX_TSO_HEADER_DESC \
@@ -867,7 +868,6 @@
 #define LINKEVENT_LINKSPEED_MBPS	0
 #define LINKEVENT_LINKSPEED_ENCODED	1
 
-#define AUTO_FW_RESET_ENABLED	0x01
 /* firmware response header:
  *	63:58 - message type
  *	57:56 - owner
@@ -1133,14 +1133,10 @@
 #define MAX_BW			100	/* % of link speed */
 #define MAX_VLAN_ID		4095
 #define MIN_VLAN_ID		2
-#define MAX_TX_QUEUES		1
-#define MAX_RX_QUEUES		4
 #define DEFAULT_MAC_LEARN	1
 
 #define IS_VALID_VLAN(vlan)	(vlan >= MIN_VLAN_ID && vlan < MAX_VLAN_ID)
 #define IS_VALID_BW(bw)		(bw <= MAX_BW)
-#define IS_VALID_TX_QUEUES(que)	(que > 0 && que <= MAX_TX_QUEUES)
-#define IS_VALID_RX_QUEUES(que)	(que > 0 && que <= MAX_RX_QUEUES)
 
 struct qlcnic_pci_func_cfg {
 	u16	func_type;
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_main.c linux-libre-2.6.39-gnu/drivers/net/qlcnic/qlcnic_main.c
--- linux-libre-2.6.38-gnu/drivers/net/qlcnic/qlcnic_main.c	2012-03-24 01:08:27.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/qlcnic/qlcnic_main.c	2012-03-24 03:31:08.000000000 -0400
@@ -42,7 +42,7 @@
 module_param(use_msi_x, int, 0444);
 MODULE_PARM_DESC(use_msi_x, "MSI-X interrupt (0=disabled, 1=enabled");
 
-static int auto_fw_reset = AUTO_FW_RESET_ENABLED;
+static int auto_fw_reset = 1;
 module_param(auto_fw_reset, int, 0644);
 MODULE_PARM_DESC(auto_fw_reset, "Auto firmware reset (0=disabled, 1=enabled");
 
@@ -2099,6 +2099,7 @@
 	struct cmd_desc_type0 *hwdesc, *first_desc;
 	struct pci_dev *pdev;
 	struct ethhdr *phdr;
+	int delta = 0;
 	int i, k;
 
 	u32 producer;
@@ -2118,6 +2119,19 @@
 	}
 
 	frag_count = skb_shinfo(skb)->nr_frags + 1;
+	/* 14 frags supported for normal packet and
+	 * 32 frags supported for TSO packet
+	 */
+	if (!skb_is_gso(skb) && frag_count > QLCNIC_MAX_FRAGS_PER_TX) {
+
+		for (i = 0; i < (frag_count - QLCNIC_MAX_FRAGS_PER_TX); i++)
+			delta += skb_shinfo(skb)->frags[i].size;
+
+		if (!__pskb_pull_tail(skb, delta))
+			goto drop_packet;
+
+		frag_count = 1 + skb_shinfo(skb)->nr_frags;
+	}
 
 	/* 4 fragments per cmd des */
 	no_of_desc = (frag_count + 3) >> 2;
@@ -2959,8 +2973,7 @@
 		if (adapter->need_fw_reset)
 			goto detach;
 
-		if (adapter->reset_context &&
-		    auto_fw_reset == AUTO_FW_RESET_ENABLED) {
+		if (adapter->reset_context && auto_fw_reset) {
 			qlcnic_reset_hw_context(adapter);
 			adapter->netdev->trans_start = jiffies;
 		}
@@ -2973,7 +2986,7 @@
 
 	qlcnic_dev_request_reset(adapter);
 
-	if ((auto_fw_reset == AUTO_FW_RESET_ENABLED))
+	if (auto_fw_reset)
 		clear_bit(__QLCNIC_FW_ATTACHED, &adapter->state);
 
 	dev_info(&netdev->dev, "firmware hang detected\n");
@@ -2982,7 +2995,7 @@
 	adapter->dev_state = (state == QLCNIC_DEV_NEED_QUISCENT) ? state :
 		QLCNIC_DEV_NEED_RESET;
 
-	if ((auto_fw_reset == AUTO_FW_RESET_ENABLED) &&
+	if (auto_fw_reset &&
 		!test_and_set_bit(__QLCNIC_RESETTING, &adapter->state)) {
 
 		qlcnic_schedule_work(adapter, qlcnic_detach_work, 0);
@@ -3654,10 +3667,8 @@
 		if (adapter->npars[pci_func].type != QLCNIC_TYPE_NIC)
 			return QL_STATUS_INVALID_PARAM;
 
-		if (!IS_VALID_BW(np_cfg[i].min_bw)
-				|| !IS_VALID_BW(np_cfg[i].max_bw)
-				|| !IS_VALID_RX_QUEUES(np_cfg[i].max_rx_queues)
-				|| !IS_VALID_TX_QUEUES(np_cfg[i].max_tx_queues))
+		if (!IS_VALID_BW(np_cfg[i].min_bw) ||
+		    !IS_VALID_BW(np_cfg[i].max_bw))
 			return QL_STATUS_INVALID_PARAM;
 	}
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/qlge/qlge_main.c linux-libre-2.6.39-gnu/drivers/net/qlge/qlge_main.c
--- linux-libre-2.6.38-gnu/drivers/net/qlge/qlge_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/qlge/qlge_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -660,7 +660,7 @@
 /* If we're running with multiple MSI-X vectors then we enable on the fly.
  * Otherwise, we may have multiple outstanding workers and don't want to
  * enable until the last one finishes. In this case, the irq_cnt gets
- * incremented everytime we queue a worker and decremented everytime
+ * incremented every time we queue a worker and decremented every time
  * a worker finishes.  Once it hits zero we enable the interrupt.
  */
 u32 ql_enable_completion_interrupt(struct ql_adapter *qdev, u32 intr)
@@ -3299,7 +3299,7 @@
  * will service it.  An example would be if there are
  * 2 vectors (so 2 RSS rings) and 8 TX completion rings.
  * This would mean that vector 0 would service RSS ring 0
- * and TX competion rings 0,1,2 and 3.  Vector 1 would
+ * and TX completion rings 0,1,2 and 3.  Vector 1 would
  * service RSS ring 1 and TX completion rings 4,5,6 and 7.
  */
 static void ql_set_tx_vect(struct ql_adapter *qdev)
@@ -4152,7 +4152,7 @@
 	int i, status;
 	u32 lbq_buf_len;
 
-	/* Wait for an oustanding reset to complete. */
+	/* Wait for an outstanding reset to complete. */
 	if (!test_bit(QL_ADAPTER_UP, &qdev->flags)) {
 		int i = 3;
 		while (i-- && !test_bit(QL_ADAPTER_UP, &qdev->flags)) {
@@ -4281,7 +4281,7 @@
 			if (ql_set_routing_reg
 			    (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 1)) {
 				netif_err(qdev, hw, qdev->ndev,
-					  "Failed to set promiscous mode.\n");
+					  "Failed to set promiscuous mode.\n");
 			} else {
 				set_bit(QL_PROMISCUOUS, &qdev->flags);
 			}
@@ -4291,7 +4291,7 @@
 			if (ql_set_routing_reg
 			    (qdev, RT_IDX_PROMISCUOUS_SLOT, RT_IDX_VALID, 0)) {
 				netif_err(qdev, hw, qdev->ndev,
-					  "Failed to clear promiscous mode.\n");
+					  "Failed to clear promiscuous mode.\n");
 			} else {
 				clear_bit(QL_PROMISCUOUS, &qdev->flags);
 			}
diff -druN linux-libre-2.6.38-gnu/drivers/net/r6040.c linux-libre-2.6.39-gnu/drivers/net/r6040.c
--- linux-libre-2.6.38-gnu/drivers/net/r6040.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/r6040.c	2011-05-19 00:06:34.000000000 -0400
@@ -535,7 +535,7 @@
 			/* RX dribble */
 			if (err & DSC_RX_ERR_DRI)
 				dev->stats.rx_frame_errors++;
-			/* Buffer lenght exceeded */
+			/* Buffer length exceeded */
 			if (err & DSC_RX_ERR_BUF)
 				dev->stats.rx_length_errors++;
 			/* Packet too long */
diff -druN linux-libre-2.6.38-gnu/drivers/net/r8169.c linux-libre-2.6.39-gnu/drivers/net/r8169.c
--- linux-libre-2.6.38-gnu/drivers/net/r8169.c	2012-03-24 01:08:35.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/r8169.c	2012-03-24 03:31:12.000000000 -0400
@@ -37,6 +37,7 @@
 
 #define FIRMWARE_8168D_1	"/*(DEBLOBBED)*/"
 #define FIRMWARE_8168D_2	"/*(DEBLOBBED)*/"
+#define FIRMWARE_8105E_1	"/*(DEBLOBBED)*/"
 
 #ifdef RTL8169_DEBUG
 #define assert(expr) \
@@ -124,6 +125,8 @@
 	RTL_GIGA_MAC_VER_26 = 0x1a, // 8168D
 	RTL_GIGA_MAC_VER_27 = 0x1b, // 8168DP
 	RTL_GIGA_MAC_VER_28 = 0x1c, // 8168DP
+	RTL_GIGA_MAC_VER_29 = 0x1d, // 8105E
+	RTL_GIGA_MAC_VER_30 = 0x1e, // 8105E
 };
 
 #define _R(NAME,MAC,MASK) \
@@ -161,10 +164,22 @@
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_25, 0xff7e1880), // PCI-E
 	_R("RTL8168d/8111d",	RTL_GIGA_MAC_VER_26, 0xff7e1880), // PCI-E
 	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_27, 0xff7e1880), // PCI-E
-	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880)  // PCI-E
+	_R("RTL8168dp/8111dp",	RTL_GIGA_MAC_VER_28, 0xff7e1880), // PCI-E
+	_R("RTL8105e",		RTL_GIGA_MAC_VER_29, 0xff7e1880), // PCI-E
+	_R("RTL8105e",		RTL_GIGA_MAC_VER_30, 0xff7e1880)  // PCI-E
 };
 #undef _R
 
+static const struct rtl_firmware_info {
+	int mac_version;
+	const char *fw_name;
+} rtl_firmware_infos[] = {
+	{ .mac_version = RTL_GIGA_MAC_VER_25, .fw_name = FIRMWARE_8168D_1 },
+	{ .mac_version = RTL_GIGA_MAC_VER_26, .fw_name = FIRMWARE_8168D_2 },
+	{ .mac_version = RTL_GIGA_MAC_VER_29, .fw_name = FIRMWARE_8105E_1 },
+	{ .mac_version = RTL_GIGA_MAC_VER_30, .fw_name = FIRMWARE_8105E_1 }
+};
+
 enum cfg_version {
 	RTL_CFG_0 = 0x00,
 	RTL_CFG_1,
@@ -268,9 +283,15 @@
 #define	EPHYAR_REG_MASK			0x1f
 #define	EPHYAR_REG_SHIFT		16
 #define	EPHYAR_DATA_MASK		0xffff
+	DLLPR			= 0xd0,
+#define	PM_SWITCH			(1 << 6)
 	DBG_REG			= 0xd1,
 #define	FIX_NAK_1			(1 << 4)
 #define	FIX_NAK_2			(1 << 3)
+	TWSI			= 0xd2,
+	MCU			= 0xd3,
+#define	EN_NDP				(1 << 3)
+#define	EN_OOB_RESET			(1 << 2)
 	EFUSEAR			= 0xdc,
 #define	EFUSEAR_FLAG			0x80000000
 #define	EFUSEAR_WRITE_CMD		0x80000000
@@ -527,9 +548,6 @@
 	u16 napi_event;
 	u16 intr_mask;
 	int phy_1000_ctrl_reg;
-#ifdef CONFIG_R8169_VLAN
-	struct vlan_group *vlgrp;
-#endif
 
 	struct mdio_ops {
 		void (*write)(void __iomem *, int, int);
@@ -541,7 +559,7 @@
 		void (*up)(struct rtl8169_private *);
 	} pll_power_ops;
 
-	int (*set_speed)(struct net_device *, u8 autoneg, u16 speed, u8 duplex);
+	int (*set_speed)(struct net_device *, u8 aneg, u16 sp, u8 dpx, u32 adv);
 	int (*get_settings)(struct net_device *, struct ethtool_cmd *);
 	void (*phy_reset_enable)(struct rtl8169_private *tp);
 	void (*hw_start)(struct net_device *);
@@ -557,6 +575,7 @@
 	u32 saved_wolopts;
 
 	const struct firmware *fw;
+#define RTL_FIRMWARE_UNKNOWN	ERR_PTR(-EAGAIN);
 };
 
 MODULE_AUTHOR("Realtek and the Linux r8169 crew <netdev@vger.kernel.org>");
@@ -1097,7 +1116,7 @@
 }
 
 static int rtl8169_set_speed_tbi(struct net_device *dev,
-				 u8 autoneg, u16 speed, u8 duplex)
+				 u8 autoneg, u16 speed, u8 duplex, u32 ignored)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
@@ -1120,17 +1139,30 @@
 }
 
 static int rtl8169_set_speed_xmii(struct net_device *dev,
-				  u8 autoneg, u16 speed, u8 duplex)
+				  u8 autoneg, u16 speed, u8 duplex, u32 adv)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int giga_ctrl, bmcr;
+	int rc = -EINVAL;
+
+	rtl_writephy(tp, 0x1f, 0x0000);
 
 	if (autoneg == AUTONEG_ENABLE) {
 		int auto_nego;
 
 		auto_nego = rtl_readphy(tp, MII_ADVERTISE);
-		auto_nego |= (ADVERTISE_10HALF | ADVERTISE_10FULL |
-			      ADVERTISE_100HALF | ADVERTISE_100FULL);
+		auto_nego &= ~(ADVERTISE_10HALF | ADVERTISE_10FULL |
+				ADVERTISE_100HALF | ADVERTISE_100FULL);
+
+		if (adv & ADVERTISED_10baseT_Half)
+			auto_nego |= ADVERTISE_10HALF;
+		if (adv & ADVERTISED_10baseT_Full)
+			auto_nego |= ADVERTISE_10FULL;
+		if (adv & ADVERTISED_100baseT_Half)
+			auto_nego |= ADVERTISE_100HALF;
+		if (adv & ADVERTISED_100baseT_Full)
+			auto_nego |= ADVERTISE_100FULL;
+
 		auto_nego |= ADVERTISE_PAUSE_CAP | ADVERTISE_PAUSE_ASYM;
 
 		giga_ctrl = rtl_readphy(tp, MII_CTRL1000);
@@ -1144,27 +1176,22 @@
 		    (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 {
+		    (tp->mac_version != RTL_GIGA_MAC_VER_16) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_29) &&
+		    (tp->mac_version != RTL_GIGA_MAC_VER_30)) {
+			if (adv & ADVERTISED_1000baseT_Half)
+				giga_ctrl |= ADVERTISE_1000HALF;
+			if (adv & ADVERTISED_1000baseT_Full)
+				giga_ctrl |= ADVERTISE_1000FULL;
+		} else if (adv & (ADVERTISED_1000baseT_Half |
+				  ADVERTISED_1000baseT_Full)) {
 			netif_info(tp, link, dev,
 				   "PHY does not support 1000Mbps\n");
+			goto out;
 		}
 
 		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.
-			 */
-			rtl_writephy(tp, 0x1f, 0x0000);
-			rtl_writephy(tp, 0x0e, 0x0000);
-		}
-
 		rtl_writephy(tp, MII_ADVERTISE, auto_nego);
 		rtl_writephy(tp, MII_CTRL1000, giga_ctrl);
 	} else {
@@ -1175,12 +1202,10 @@
 		else if (speed == SPEED_100)
 			bmcr = BMCR_SPEED100;
 		else
-			return -EINVAL;
+			goto out;
 
 		if (duplex == DUPLEX_FULL)
 			bmcr |= BMCR_FULLDPLX;
-
-		rtl_writephy(tp, 0x1f, 0x0000);
 	}
 
 	tp->phy_1000_ctrl_reg = giga_ctrl;
@@ -1198,16 +1223,18 @@
 		}
 	}
 
-	return 0;
+	rc = 0;
+out:
+	return rc;
 }
 
 static int rtl8169_set_speed(struct net_device *dev,
-			     u8 autoneg, u16 speed, u8 duplex)
+			     u8 autoneg, u16 speed, u8 duplex, u32 advertising)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	int ret;
 
-	ret = tp->set_speed(dev, autoneg, speed, duplex);
+	ret = tp->set_speed(dev, autoneg, speed, duplex, advertising);
 
 	if (netif_running(dev) && (tp->phy_1000_ctrl_reg & ADVERTISE_1000FULL))
 		mod_timer(&tp->timer, jiffies + RTL8169_PHY_TIMEOUT);
@@ -1222,7 +1249,8 @@
 	int ret;
 
 	spin_lock_irqsave(&tp->lock, flags);
-	ret = rtl8169_set_speed(dev, cmd->autoneg, cmd->speed, cmd->duplex);
+	ret = rtl8169_set_speed(dev,
+		cmd->autoneg, cmd->speed, cmd->duplex, cmd->advertising);
 	spin_unlock_irqrestore(&tp->lock, flags);
 
 	return ret;
@@ -1256,8 +1284,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_R8169_VLAN
-
 static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
 				      struct sk_buff *skb)
 {
@@ -1265,64 +1291,37 @@
 		TxVlanTag | swab16(vlan_tx_tag_get(skb)) : 0x00;
 }
 
-static void rtl8169_vlan_rx_register(struct net_device *dev,
-				     struct vlan_group *grp)
+#define NETIF_F_HW_VLAN_TX_RX	(NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX)
+
+static void rtl8169_vlan_mode(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
 	void __iomem *ioaddr = tp->mmio_addr;
 	unsigned long flags;
 
 	spin_lock_irqsave(&tp->lock, flags);
-	tp->vlgrp = grp;
-	/*
-	 * Do not disable RxVlan on 8110SCd.
-	 */
-	if (tp->vlgrp || (tp->mac_version == RTL_GIGA_MAC_VER_05))
+	if (dev->features & NETIF_F_HW_VLAN_RX)
 		tp->cp_cmd |= RxVlan;
 	else
 		tp->cp_cmd &= ~RxVlan;
 	RTL_W16(CPlusCmd, tp->cp_cmd);
+	/* PCI commit */
 	RTL_R16(CPlusCmd);
 	spin_unlock_irqrestore(&tp->lock, flags);
+
+	dev->vlan_features = dev->features &~ NETIF_F_HW_VLAN_TX_RX;
 }
 
-static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
-			       struct sk_buff *skb, int polling)
+static void rtl8169_rx_vlan_tag(struct RxDesc *desc, struct sk_buff *skb)
 {
 	u32 opts2 = le32_to_cpu(desc->opts2);
-	struct vlan_group *vlgrp = tp->vlgrp;
-	int ret;
 
-	if (vlgrp && (opts2 & RxVlanTag)) {
-		u16 vtag = swab16(opts2 & 0xffff);
+	if (opts2 & RxVlanTag)
+		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
 
-		if (likely(polling))
-			vlan_gro_receive(&tp->napi, vlgrp, vtag, skb);
-		else
-			__vlan_hwaccel_rx(skb, vlgrp, vtag, polling);
-		ret = 0;
-	} else
-		ret = -1;
 	desc->opts2 = 0;
-	return ret;
 }
 
-#else /* !CONFIG_R8169_VLAN */
-
-static inline u32 rtl8169_tx_vlan_tag(struct rtl8169_private *tp,
-				      struct sk_buff *skb)
-{
-	return 0;
-}
-
-static int rtl8169_rx_vlan_skb(struct rtl8169_private *tp, struct RxDesc *desc,
-			       struct sk_buff *skb, int polling)
-{
-	return -1;
-}
-
-#endif
-
 static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -1493,6 +1492,28 @@
 	}
 }
 
+static int rtl8169_set_flags(struct net_device *dev, u32 data)
+{
+	struct rtl8169_private *tp = netdev_priv(dev);
+	unsigned long old_feat = dev->features;
+	int rc;
+
+	if ((tp->mac_version == RTL_GIGA_MAC_VER_05) &&
+	    !(data & ETH_FLAG_RXVLAN)) {
+		netif_info(tp, drv, dev, "8110SCd requires hardware Rx VLAN\n");
+		return -EINVAL;
+	}
+
+	rc = ethtool_op_set_flags(dev, data, ETH_FLAG_TXVLAN | ETH_FLAG_RXVLAN);
+	if (rc)
+		return rc;
+
+	if ((old_feat ^ dev->features) & NETIF_F_HW_VLAN_RX)
+		rtl8169_vlan_mode(dev);
+
+	return 0;
+}
+
 static const struct ethtool_ops rtl8169_ethtool_ops = {
 	.get_drvinfo		= rtl8169_get_drvinfo,
 	.get_regs_len		= rtl8169_get_regs_len,
@@ -1512,6 +1533,8 @@
 	.get_strings		= rtl8169_get_strings,
 	.get_sset_count		= rtl8169_get_sset_count,
 	.get_ethtool_stats	= rtl8169_get_ethtool_stats,
+	.set_flags		= rtl8169_set_flags,
+	.get_flags		= ethtool_op_get_flags,
 };
 
 static void rtl8169_get_mac_version(struct rtl8169_private *tp,
@@ -1560,6 +1583,9 @@
 		{ 0x7c800000, 0x30000000,	RTL_GIGA_MAC_VER_11 },
 
 		/* 8101 family. */
+		{ 0x7cf00000, 0x40a00000,	RTL_GIGA_MAC_VER_30 },
+		{ 0x7cf00000, 0x40900000,	RTL_GIGA_MAC_VER_29 },
+		{ 0x7c800000, 0x40800000,	RTL_GIGA_MAC_VER_30 },
 		{ 0x7cf00000, 0x34a00000,	RTL_GIGA_MAC_VER_09 },
 		{ 0x7cf00000, 0x24a00000,	RTL_GIGA_MAC_VER_09 },
 		{ 0x7cf00000, 0x34900000,	RTL_GIGA_MAC_VER_08 },
@@ -1772,25 +1798,26 @@
 
 static void rtl_release_firmware(struct rtl8169_private *tp)
 {
-	release_firmware(tp->fw);
-	tp->fw = NULL;
+	if (!IS_ERR_OR_NULL(tp->fw))
+		release_firmware(tp->fw);
+	tp->fw = RTL_FIRMWARE_UNKNOWN;
 }
 
-static int rtl_apply_firmware(struct rtl8169_private *tp, const char *fw_name)
+static void rtl_apply_firmware(struct rtl8169_private *tp)
 {
-	const struct firmware **fw = &tp->fw;
-	int rc = !*fw;
-
-	if (rc) {
-		rc = reject_firmware(fw, fw_name, &tp->pci_dev->dev);
-		if (rc < 0)
-			goto out;
-	}
+	const struct firmware *fw = tp->fw;
 
 	/* TODO: release firmware once rtl_phy_write_fw signals failures. */
-	rtl_phy_write_fw(tp, *fw);
-out:
-	return rc;
+	if (!IS_ERR_OR_NULL(fw))
+		rtl_phy_write_fw(tp, fw);
+}
+
+static void rtl_apply_firmware_cond(struct rtl8169_private *tp, u8 reg, u16 val)
+{
+	if (rtl_readphy(tp, reg) != val)
+		netif_warn(tp, hw, tp->dev, "chipset not ready for firmware\n");
+	else
+		rtl_apply_firmware(tp);
 }
 
 static void rtl8169s_hw_phy_config(struct rtl8169_private *tp)
@@ -2229,10 +2256,8 @@
 
 	rtl_writephy(tp, 0x1f, 0x0005);
 	rtl_writephy(tp, 0x05, 0x001b);
-	if ((rtl_readphy(tp, 0x06) != 0xbf00) ||
-	    (rtl_apply_firmware(tp, FIRMWARE_8168D_1) < 0)) {
-		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
-	}
+
+	rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xbf00);
 
 	rtl_writephy(tp, 0x1f, 0x0000);
 }
@@ -2334,10 +2359,8 @@
 
 	rtl_writephy(tp, 0x1f, 0x0005);
 	rtl_writephy(tp, 0x05, 0x001b);
-	if ((rtl_readphy(tp, 0x06) != 0xb300) ||
-	    (rtl_apply_firmware(tp, FIRMWARE_8168D_2) < 0)) {
-		netif_warn(tp, probe, tp->dev, "unable to apply firmware patch\n");
-	}
+
+	rtl_apply_firmware_cond(tp, MII_EXPANSION, 0xb300);
 
 	rtl_writephy(tp, 0x1f, 0x0000);
 }
@@ -2436,6 +2459,32 @@
 	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
 }
 
+static void rtl8105e_hw_phy_config(struct rtl8169_private *tp)
+{
+	static const struct phy_reg phy_reg_init[] = {
+		{ 0x1f, 0x0005 },
+		{ 0x1a, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0004 },
+		{ 0x1c, 0x0000 },
+		{ 0x1f, 0x0000 },
+
+		{ 0x1f, 0x0001 },
+		{ 0x15, 0x7701 },
+		{ 0x1f, 0x0000 }
+	};
+
+	/* Disable ALDPS before ram code */
+	rtl_writephy(tp, 0x1f, 0x0000);
+	rtl_writephy(tp, 0x18, 0x0310);
+	msleep(100);
+
+	rtl_apply_firmware(tp);
+
+	rtl_writephy_batch(tp, phy_reg_init, ARRAY_SIZE(phy_reg_init));
+}
+
 static void rtl_hw_phy_config(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -2503,6 +2552,10 @@
 	case RTL_GIGA_MAC_VER_28:
 		rtl8168d_4_hw_phy_config(tp);
 		break;
+	case RTL_GIGA_MAC_VER_29:
+	case RTL_GIGA_MAC_VER_30:
+		rtl8105e_hw_phy_config(tp);
+		break;
 
 	default:
 		break;
@@ -2634,11 +2687,12 @@
 
 	rtl8169_phy_reset(dev, tp);
 
-	/*
-	 * rtl8169_set_speed_xmii takes good care of the Fast Ethernet
-	 * only 8101. Don't panic.
-	 */
-	rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL);
+	rtl8169_set_speed(dev, AUTONEG_ENABLE, SPEED_1000, DUPLEX_FULL,
+		ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
+		ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
+		(tp->mii.supports_gmii ?
+			ADVERTISED_1000baseT_Half |
+			ADVERTISED_1000baseT_Full : 0));
 
 	if (RTL_R8(PHYstatus) & TBI_Enable)
 		netif_info(tp, link, dev, "TBI auto-negotiating\n");
@@ -2794,9 +2848,6 @@
 	.ndo_set_mac_address	= rtl_set_mac_address,
 	.ndo_do_ioctl		= rtl8169_ioctl,
 	.ndo_set_multicast_list	= rtl_set_rx_mode,
-#ifdef CONFIG_R8169_VLAN
-	.ndo_vlan_rx_register	= rtl8169_vlan_rx_register,
-#endif
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller	= rtl8169_netpoll,
 #endif
@@ -2951,6 +3002,8 @@
 	case RTL_GIGA_MAC_VER_09:
 	case RTL_GIGA_MAC_VER_10:
 	case RTL_GIGA_MAC_VER_16:
+	case RTL_GIGA_MAC_VER_29:
+	case RTL_GIGA_MAC_VER_30:
 		ops->down	= r810x_pll_power_down;
 		ops->up		= r810x_pll_power_up;
 		break;
@@ -3103,6 +3156,13 @@
 	/* Identify chip attached to board */
 	rtl8169_get_mac_version(tp, ioaddr);
 
+	/*
+	 * Pretend we are using VLANs; This bypasses a nasty bug where
+	 * Interrupts stop flowing on high load on 8110SCd controllers.
+	 */
+	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
+		tp->cp_cmd |= RxVlan;
+
 	rtl_init_mdio_ops(tp);
 	rtl_init_pll_power_ops(tp);
 
@@ -3171,10 +3231,7 @@
 
 	netif_napi_add(dev, &tp->napi, rtl8169_poll, R8169_NAPI_WEIGHT);
 
-#ifdef CONFIG_R8169_VLAN
-	dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-#endif
-	dev->features |= NETIF_F_GRO;
+	dev->features |= NETIF_F_HW_VLAN_TX_RX | NETIF_F_GRO;
 
 	tp->intr_mask = 0xffff;
 	tp->hw_start = cfg->hw_start;
@@ -3185,6 +3242,8 @@
 	tp->timer.data = (unsigned long) dev;
 	tp->timer.function = rtl8169_phy_timer;
 
+	tp->fw = RTL_FIRMWARE_UNKNOWN;
+
 	rc = register_netdev(dev);
 	if (rc < 0)
 		goto err_out_msi_4;
@@ -3236,10 +3295,10 @@
 
 	cancel_delayed_work_sync(&tp->task);
 
-	rtl_release_firmware(tp);
-
 	unregister_netdev(dev);
 
+	rtl_release_firmware(tp);
+
 	if (pci_dev_run_wake(pdev))
 		pm_runtime_get_noresume(&pdev->dev);
 
@@ -3251,6 +3310,37 @@
 	pci_set_drvdata(pdev, NULL);
 }
 
+static void rtl_reject_firmware(struct rtl8169_private *tp)
+{
+	int i;
+
+	/* Return early if the firmware is already loaded / cached. */
+	if (!IS_ERR(tp->fw))
+		goto out;
+
+	for (i = 0; i < ARRAY_SIZE(rtl_firmware_infos); i++) {
+		const struct rtl_firmware_info *info = rtl_firmware_infos + i;
+
+		if (info->mac_version == tp->mac_version) {
+			const char *name = info->fw_name;
+			int rc;
+
+			rc = reject_firmware(&tp->fw, name, &tp->pci_dev->dev);
+			if (rc < 0) {
+				netif_warn(tp, ifup, tp->dev, "unable to load "
+					"firmware patch %s (%d)\n", name, rc);
+				goto out_disable_reject_firmware;
+			}
+			goto out;
+		}
+	}
+
+out_disable_reject_firmware:
+	tp->fw = NULL;
+out:
+	return;
+}
+
 static int rtl8169_open(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -3282,22 +3372,19 @@
 
 	smp_mb();
 
+	rtl_reject_firmware(tp);
+
 	retval = request_irq(dev->irq, rtl8169_interrupt,
 			     (tp->features & RTL_FEATURE_MSI) ? 0 : IRQF_SHARED,
 			     dev->name, dev);
 	if (retval < 0)
-		goto err_release_ring_2;
+		goto err_release_fw_2;
 
 	napi_enable(&tp->napi);
 
 	rtl8169_init_phy(dev, tp);
 
-	/*
-	 * Pretend we are using VLANs; This bypasses a nasty bug where
-	 * Interrupts stop flowing on high load on 8110SCd controllers.
-	 */
-	if (tp->mac_version == RTL_GIGA_MAC_VER_05)
-		RTL_W16(CPlusCmd, RTL_R16(CPlusCmd) | RxVlan);
+	rtl8169_vlan_mode(dev);
 
 	rtl_pll_power_up(tp);
 
@@ -3312,7 +3399,8 @@
 out:
 	return retval;
 
-err_release_ring_2:
+err_release_fw_2:
+	rtl_release_firmware(tp);
 	rtl8169_rx_clear(tp);
 err_free_rx_1:
 	dma_free_coherent(&pdev->dev, R8169_RX_RING_BYTES, tp->RxDescArray,
@@ -3914,6 +4002,37 @@
 	rtl_ephy_write(ioaddr, 0x03, 0xc2f9);
 }
 
+static void rtl_hw_start_8105e_1(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	static const struct ephy_info e_info_8105e_1[] = {
+		{ 0x07,	0, 0x4000 },
+		{ 0x19,	0, 0x0200 },
+		{ 0x19,	0, 0x0020 },
+		{ 0x1e,	0, 0x2000 },
+		{ 0x03,	0, 0x0001 },
+		{ 0x19,	0, 0x0100 },
+		{ 0x19,	0, 0x0004 },
+		{ 0x0a,	0, 0x0020 }
+	};
+
+	/* Force LAN exit from ASPM if Rx/Tx are not idel */
+	RTL_W32(FuncEvent, RTL_R32(FuncEvent) | 0x002800);
+
+	/* disable Early Tally Counter */
+	RTL_W32(FuncEvent, RTL_R32(FuncEvent) & ~0x010000);
+
+	RTL_W8(MCU, RTL_R8(MCU) | EN_NDP | EN_OOB_RESET);
+	RTL_W8(DLLPR, RTL_R8(DLLPR) | PM_SWITCH);
+
+	rtl_ephy_init(ioaddr, e_info_8105e_1, ARRAY_SIZE(e_info_8105e_1));
+}
+
+static void rtl_hw_start_8105e_2(void __iomem *ioaddr, struct pci_dev *pdev)
+{
+	rtl_hw_start_8105e_1(ioaddr, pdev);
+	rtl_ephy_write(ioaddr, 0x1e, rtl_ephy_read(ioaddr, 0x1e) | 0x8000);
+}
+
 static void rtl_hw_start_8101(struct net_device *dev)
 {
 	struct rtl8169_private *tp = netdev_priv(dev);
@@ -3944,6 +4063,13 @@
 	case RTL_GIGA_MAC_VER_09:
 		rtl_hw_start_8102e_2(ioaddr, pdev);
 		break;
+
+	case RTL_GIGA_MAC_VER_29:
+		rtl_hw_start_8105e_1(ioaddr, pdev);
+		break;
+	case RTL_GIGA_MAC_VER_30:
+		rtl_hw_start_8105e_2(ioaddr, pdev);
+		break;
 	}
 
 	RTL_W8(Cfg9346, Cfg9346_Lock);
@@ -4602,12 +4728,12 @@
 			skb_put(skb, pkt_size);
 			skb->protocol = eth_type_trans(skb, dev);
 
-			if (rtl8169_rx_vlan_skb(tp, desc, skb, polling) < 0) {
-				if (likely(polling))
-					napi_gro_receive(&tp->napi, skb);
-				else
-					netif_rx(skb);
-			}
+			rtl8169_rx_vlan_tag(desc, skb);
+
+			if (likely(polling))
+				napi_gro_receive(&tp->napi, skb);
+			else
+				netif_rx(skb);
 
 			dev->stats.rx_bytes += pkt_size;
 			dev->stats.rx_packets++;
diff -druN linux-libre-2.6.38-gnu/drivers/net/rionet.c linux-libre-2.6.39-gnu/drivers/net/rionet.c
--- linux-libre-2.6.38-gnu/drivers/net/rionet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/rionet.c	2011-05-19 00:06:34.000000000 -0400
@@ -382,7 +382,7 @@
 	struct rionet_peer *peer, *tmp;
 
 	free_pages((unsigned long)rionet_active, rdev->net->hport->sys_size ?
-					__ilog2(sizeof(void *)) + 4 : 0);
+					__fls(sizeof(void *)) + 4 : 0);
 	unregister_netdev(ndev);
 	free_netdev(ndev);
 
@@ -450,7 +450,7 @@
 	}
 
 	rionet_active = (struct rio_dev **)__get_free_pages(GFP_KERNEL,
-			mport->sys_size ? __ilog2(sizeof(void *)) + 4 : 0);
+			mport->sys_size ? __fls(sizeof(void *)) + 4 : 0);
 	if (!rionet_active) {
 		rc = -ENOMEM;
 		goto out;
@@ -571,5 +571,5 @@
 	rio_unregister_driver(&rionet_driver);
 }
 
-module_init(rionet_init);
+late_initcall(rionet_init);
 module_exit(rionet_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/net/s2io.c linux-libre-2.6.39-gnu/drivers/net/s2io.c
--- linux-libre-2.6.38-gnu/drivers/net/s2io.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/s2io.c	2011-05-19 00:06:34.000000000 -0400
@@ -2353,7 +2353,7 @@
 
 	if (s2io_link_fault_indication(nic) == MAC_RMAC_ERR_TIMER) {
 		/*
-		 * Dont see link state interrupts initally on some switches,
+		 * Dont see link state interrupts initially on some switches,
 		 * so directly scheduling the link state task here.
 		 */
 		schedule_work(&nic->set_link_task);
@@ -3563,7 +3563,7 @@
 	}
 
 	/*
-	 * Clear spurious ECC interrupts that would have occured on
+	 * Clear spurious ECC interrupts that would have occurred on
 	 * XFRAME II cards after reset.
 	 */
 	if (sp->device_type == XFRAME_II_DEVICE) {
@@ -4065,7 +4065,7 @@
  *  Description :
  *  This function is the Tx entry point of the driver. S2IO NIC supports
  *  certain protocol assist features on Tx side, namely  CSO, S/G, LSO.
- *  NOTE: when device cant queue the pkt,just the trans_start variable will
+ *  NOTE: when device can't queue the pkt,just the trans_start variable will
  *  not be upadted.
  *  Return value:
  *  0 on success & 1 on failure.
@@ -6726,7 +6726,7 @@
 	int rc = 0;
 	int changed = 0;
 
-	if (data & ~ETH_FLAG_LRO)
+	if (ethtool_invalid_flags(dev, data, ETH_FLAG_LRO))
 		return -EINVAL;
 
 	if (data & ETH_FLAG_LRO) {
@@ -7556,7 +7556,7 @@
 			 */
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 			if (ring_data->lro) {
-				u32 tcp_len;
+				u32 tcp_len = 0;
 				u8 *tcp;
 				int ret = 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/s2io.h linux-libre-2.6.39-gnu/drivers/net/s2io.h
--- linux-libre-2.6.38-gnu/drivers/net/s2io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/s2io.h	2011-05-19 00:06:34.000000000 -0400
@@ -376,7 +376,7 @@
 /* Maintains Per FIFO related information. */
 struct tx_fifo_config {
 #define	MAX_AVAILABLE_TXDS	8192
-	u32 fifo_len;		/* specifies len of FIFO upto 8192, ie no of TxDLs */
+	u32 fifo_len;		/* specifies len of FIFO up to 8192, ie no of TxDLs */
 /* Priority definition */
 #define TX_FIFO_PRI_0               0	/*Highest */
 #define TX_FIFO_PRI_1               1
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/efx.c linux-libre-2.6.39-gnu/drivers/net/sfc/efx.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/efx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/efx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2011 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
@@ -21,6 +21,7 @@
 #include <linux/ethtool.h>
 #include <linux/topology.h>
 #include <linux/gfp.h>
+#include <linux/cpu_rmap.h>
 #include "net_driver.h"
 #include "efx.h"
 #include "nic.h"
@@ -307,6 +308,8 @@
 			channel->irq_mod_score = 0;
 		}
 
+		efx_filter_rfs_expire(channel);
+
 		/* There is no race here; although napi_disable() will
 		 * only wait for napi_complete(), this isn't a problem
 		 * since efx_channel_processed() will have no effect if
@@ -325,7 +328,8 @@
  * processing to finish, then directly poll (and ack ) the eventq.
  * Finally reenable NAPI and interrupts.
  *
- * Since we are touching interrupts the caller should hold the suspend lock
+ * This is for use only during a loopback self-test.  It must not
+ * deliver any packets up the stack as this can result in deadlock.
  */
 void efx_process_channel_now(struct efx_channel *channel)
 {
@@ -333,6 +337,7 @@
 
 	BUG_ON(channel->channel >= efx->n_channels);
 	BUG_ON(!channel->enabled);
+	BUG_ON(!efx->loopback_selftest);
 
 	/* Disable interrupts and wait for ISRs to complete */
 	efx_nic_disable_interrupts(efx);
@@ -673,7 +678,7 @@
 
 		efx_for_each_channel_rx_queue(rx_queue, channel)
 			efx_fini_rx_queue(rx_queue);
-		efx_for_each_channel_tx_queue(tx_queue, channel)
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel)
 			efx_fini_tx_queue(tx_queue);
 		efx_fini_eventq(channel);
 	}
@@ -689,7 +694,7 @@
 
 	efx_for_each_channel_rx_queue(rx_queue, channel)
 		efx_remove_rx_queue(rx_queue);
-	efx_for_each_channel_tx_queue(tx_queue, channel)
+	efx_for_each_possible_channel_tx_queue(tx_queue, channel)
 		efx_remove_tx_queue(tx_queue);
 	efx_remove_eventq(channel);
 }
@@ -1051,6 +1056,7 @@
 {
 	struct pci_dev *pci_dev = efx->pci_dev;
 	dma_addr_t dma_mask = efx->type->max_dma_mask;
+	bool use_wc;
 	int rc;
 
 	netif_dbg(efx, probe, efx->net_dev, "initialising I/O\n");
@@ -1101,8 +1107,21 @@
 		rc = -EIO;
 		goto fail3;
 	}
-	efx->membase = ioremap_nocache(efx->membase_phys,
-				       efx->type->mem_map_size);
+
+	/* bug22643: If SR-IOV is enabled then tx push over a write combined
+	 * mapping is unsafe. We need to disable write combining in this case.
+	 * MSI is unsupported when SR-IOV is enabled, and the firmware will
+	 * have removed the MSI capability. So write combining is safe if
+	 * there is an MSI capability.
+	 */
+	use_wc = (!EFX_WORKAROUND_22643(efx) ||
+		  pci_find_capability(pci_dev, PCI_CAP_ID_MSI));
+	if (use_wc)
+		efx->membase = ioremap_wc(efx->membase_phys,
+					  efx->type->mem_map_size);
+	else
+		efx->membase = ioremap_nocache(efx->membase_phys,
+					       efx->type->mem_map_size);
 	if (!efx->membase) {
 		netif_err(efx, probe, efx->net_dev,
 			  "could not map memory BAR at %llx+%x\n",
@@ -1175,10 +1194,32 @@
 	return count;
 }
 
+static int
+efx_init_rx_cpu_rmap(struct efx_nic *efx, struct msix_entry *xentries)
+{
+#ifdef CONFIG_RFS_ACCEL
+	int i, rc;
+
+	efx->net_dev->rx_cpu_rmap = alloc_irq_cpu_rmap(efx->n_rx_channels);
+	if (!efx->net_dev->rx_cpu_rmap)
+		return -ENOMEM;
+	for (i = 0; i < efx->n_rx_channels; i++) {
+		rc = irq_cpu_rmap_add(efx->net_dev->rx_cpu_rmap,
+				      xentries[i].vector);
+		if (rc) {
+			free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
+			efx->net_dev->rx_cpu_rmap = NULL;
+			return rc;
+		}
+	}
+#endif
+	return 0;
+}
+
 /* Probe the number and type of interrupts we are able to obtain, and
  * the resulting numbers of channels and RX queues.
  */
-static void efx_probe_interrupts(struct efx_nic *efx)
+static int efx_probe_interrupts(struct efx_nic *efx)
 {
 	int max_channels =
 		min_t(int, efx->type->phys_addr_channels, EFX_MAX_CHANNELS);
@@ -1220,6 +1261,11 @@
 				efx->n_tx_channels = efx->n_channels;
 				efx->n_rx_channels = efx->n_channels;
 			}
+			rc = efx_init_rx_cpu_rmap(efx, xentries);
+			if (rc) {
+				pci_disable_msix(efx->pci_dev);
+				return rc;
+			}
 			for (i = 0; i < n_channels; i++)
 				efx_get_channel(efx, i)->irq =
 					xentries[i].vector;
@@ -1253,6 +1299,8 @@
 		efx->n_tx_channels = 1;
 		efx->legacy_irq = efx->pci_dev->irq;
 	}
+
+	return 0;
 }
 
 static void efx_remove_interrupts(struct efx_nic *efx)
@@ -1271,21 +1319,8 @@
 
 static void efx_set_channels(struct efx_nic *efx)
 {
-	struct efx_channel *channel;
-	struct efx_tx_queue *tx_queue;
-
 	efx->tx_channel_offset =
 		separate_tx_channels ? efx->n_channels - efx->n_tx_channels : 0;
-
-	/* Channel pointers were set in efx_init_struct() but we now
-	 * need to clear them for TX queues in any RX-only channels. */
-	efx_for_each_channel(channel, efx) {
-		if (channel->channel - efx->tx_channel_offset >=
-		    efx->n_tx_channels) {
-			efx_for_each_channel_tx_queue(tx_queue, channel)
-				tx_queue->channel = NULL;
-		}
-	}
 }
 
 static int efx_probe_nic(struct efx_nic *efx)
@@ -1302,7 +1337,9 @@
 
 	/* Determine the number of channels and queues by trying to hook
 	 * in MSI-X interrupts. */
-	efx_probe_interrupts(efx);
+	rc = efx_probe_interrupts(efx);
+	if (rc)
+		goto fail;
 
 	if (efx->n_channels > 1)
 		get_random_bytes(&efx->rx_hash_key, sizeof(efx->rx_hash_key));
@@ -1317,6 +1354,10 @@
 	efx_init_irq_moderation(efx, tx_irq_mod_usec, rx_irq_mod_usec, true);
 
 	return 0;
+
+fail:
+	efx->type->remove(efx);
+	return rc;
 }
 
 static void efx_remove_nic(struct efx_nic *efx)
@@ -1397,7 +1438,7 @@
 	 * restart the transmit interface early so the watchdog timer stops */
 	efx_start_port(efx);
 
-	if (efx_dev_registered(efx))
+	if (efx_dev_registered(efx) && !efx->port_inhibited)
 		netif_tx_wake_all_queues(efx->net_dev);
 
 	efx_for_each_channel(channel, efx)
@@ -1531,9 +1572,9 @@
 	efx->irq_rx_adaptive = rx_adaptive;
 	efx->irq_rx_moderation = rx_ticks;
 	efx_for_each_channel(channel, efx) {
-		if (efx_channel_get_rx_queue(channel))
+		if (efx_channel_has_rx_queue(channel))
 			channel->irq_moderation = rx_ticks;
-		else if (efx_channel_get_tx_queue(channel, 0))
+		else if (efx_channel_has_tx_queues(channel))
 			channel->irq_moderation = tx_ticks;
 	}
 }
@@ -1849,6 +1890,10 @@
 #ifdef CONFIG_NET_POLL_CONTROLLER
 	.ndo_poll_controller = efx_netpoll,
 #endif
+	.ndo_setup_tc		= efx_setup_tc,
+#ifdef CONFIG_RFS_ACCEL
+	.ndo_rx_flow_steer	= efx_filter_rfs,
+#endif
 };
 
 static void efx_update_name(struct efx_nic *efx)
@@ -1910,10 +1955,8 @@
 
 	efx_for_each_channel(channel, efx) {
 		struct efx_tx_queue *tx_queue;
-		efx_for_each_channel_tx_queue(tx_queue, channel) {
-			tx_queue->core_txq = netdev_get_tx_queue(
-				efx->net_dev, tx_queue->queue / EFX_TXQ_TYPES);
-		}
+		efx_for_each_channel_tx_queue(tx_queue, channel)
+			efx_init_tx_queue_core_txq(tx_queue);
 	}
 
 	/* Always start with carrier off; PHY events will detect the link */
@@ -2288,6 +2331,10 @@
  */
 static void efx_pci_remove_main(struct efx_nic *efx)
 {
+#ifdef CONFIG_RFS_ACCEL
+	free_irq_cpu_rmap(efx->net_dev->rx_cpu_rmap);
+	efx->net_dev->rx_cpu_rmap = NULL;
+#endif
 	efx_nic_fini_interrupt(efx);
 	efx_fini_channels(efx);
 	efx_fini_port(efx);
@@ -2401,7 +2448,8 @@
 	int i, rc;
 
 	/* Allocate and initialise a struct net_device and struct efx_nic */
-	net_dev = alloc_etherdev_mq(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES);
+	net_dev = alloc_etherdev_mqs(sizeof(*efx), EFX_MAX_CORE_TX_QUEUES,
+				     EFX_MAX_RX_QUEUES);
 	if (!net_dev)
 		return -ENOMEM;
 	net_dev->features |= (type->offload_features | NETIF_F_SG |
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/efx.h linux-libre-2.6.39-gnu/drivers/net/sfc/efx.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/efx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/efx.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -29,6 +29,7 @@
 extern int efx_probe_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_remove_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_init_tx_queue(struct efx_tx_queue *tx_queue);
+extern void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue);
 extern void efx_fini_tx_queue(struct efx_tx_queue *tx_queue);
 extern void efx_release_tx_buffers(struct efx_tx_queue *tx_queue);
 extern netdev_tx_t
@@ -36,6 +37,7 @@
 extern netdev_tx_t
 efx_enqueue_skb(struct efx_tx_queue *tx_queue, struct sk_buff *skb);
 extern void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index);
+extern int efx_setup_tc(struct net_device *net_dev, u8 num_tc);
 
 /* RX */
 extern int efx_probe_rx_queue(struct efx_rx_queue *rx_queue);
@@ -74,6 +76,21 @@
 				    struct efx_filter_spec *spec);
 extern void efx_filter_clear_rx(struct efx_nic *efx,
 				enum efx_filter_priority priority);
+#ifdef CONFIG_RFS_ACCEL
+extern int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+			  u16 rxq_index, u32 flow_id);
+extern bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota);
+static inline void efx_filter_rfs_expire(struct efx_channel *channel)
+{
+	if (channel->rfs_filters_added >= 60 &&
+	    __efx_filter_rfs_expire(channel->efx, 100))
+		channel->rfs_filters_added -= 60;
+}
+#define efx_filter_rfs_enabled() 1
+#else
+static inline void efx_filter_rfs_expire(struct efx_channel *channel) {}
+#define efx_filter_rfs_enabled() 0
+#endif
 
 /* Channels */
 extern void efx_process_channel_now(struct efx_channel *channel);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/ethtool.c linux-libre-2.6.39-gnu/drivers/net/sfc/ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -28,7 +28,8 @@
 	enum {
 		EFX_ETHTOOL_STAT_SOURCE_mac_stats,
 		EFX_ETHTOOL_STAT_SOURCE_nic,
-		EFX_ETHTOOL_STAT_SOURCE_channel
+		EFX_ETHTOOL_STAT_SOURCE_channel,
+		EFX_ETHTOOL_STAT_SOURCE_tx_queue
 	} source;
 	unsigned offset;
 	u64(*get_stat) (void *field); /* Reader function */
@@ -86,6 +87,10 @@
 	EFX_ETHTOOL_STAT(field, channel, n_##field,		\
 			 unsigned int, efx_get_uint_stat)
 
+#define EFX_ETHTOOL_UINT_TXQ_STAT(field)			\
+	EFX_ETHTOOL_STAT(tx_##field, tx_queue, field,		\
+			 unsigned int, efx_get_uint_stat)
+
 static struct efx_ethtool_stat efx_ethtool_stats[] = {
 	EFX_ETHTOOL_U64_MAC_STAT(tx_bytes),
 	EFX_ETHTOOL_U64_MAC_STAT(tx_good_bytes),
@@ -116,6 +121,10 @@
 	EFX_ETHTOOL_ULONG_MAC_STAT(tx_non_tcpudp),
 	EFX_ETHTOOL_ULONG_MAC_STAT(tx_mac_src_error),
 	EFX_ETHTOOL_ULONG_MAC_STAT(tx_ip_src_error),
+	EFX_ETHTOOL_UINT_TXQ_STAT(tso_bursts),
+	EFX_ETHTOOL_UINT_TXQ_STAT(tso_long_headers),
+	EFX_ETHTOOL_UINT_TXQ_STAT(tso_packets),
+	EFX_ETHTOOL_UINT_TXQ_STAT(pushes),
 	EFX_ETHTOOL_U64_MAC_STAT(rx_bytes),
 	EFX_ETHTOOL_U64_MAC_STAT(rx_good_bytes),
 	EFX_ETHTOOL_U64_MAC_STAT(rx_bad_bytes),
@@ -237,8 +246,8 @@
 	strlcpy(info->driver, KBUILD_MODNAME, sizeof(info->driver));
 	strlcpy(info->version, EFX_DRIVER_VERSION, sizeof(info->version));
 	if (efx_nic_rev(efx) >= EFX_REV_SIENA_A0)
-		siena_print_fwver(efx, info->fw_version,
-				  sizeof(info->fw_version));
+		efx_mcdi_print_fwver(efx, info->fw_version,
+				     sizeof(info->fw_version));
 	strlcpy(info->bus_info, pci_name(efx->pci_dev), sizeof(info->bus_info));
 }
 
@@ -470,6 +479,7 @@
 	struct efx_mac_stats *mac_stats = &efx->mac_stats;
 	struct efx_ethtool_stat *stat;
 	struct efx_channel *channel;
+	struct efx_tx_queue *tx_queue;
 	struct rtnl_link_stats64 temp;
 	int i;
 
@@ -495,6 +505,15 @@
 				data[i] += stat->get_stat((void *)channel +
 							  stat->offset);
 			break;
+		case EFX_ETHTOOL_STAT_SOURCE_tx_queue:
+			data[i] = 0;
+			efx_for_each_channel(channel, efx) {
+				efx_for_each_channel_tx_queue(tx_queue, channel)
+					data[i] +=
+						stat->get_stat((void *)tx_queue
+							       + stat->offset);
+			}
+			break;
 		}
 	}
 }
@@ -502,7 +521,7 @@
 static int efx_ethtool_set_tso(struct net_device *net_dev, u32 enable)
 {
 	struct efx_nic *efx __attribute__ ((unused)) = netdev_priv(net_dev);
-	unsigned long features;
+	u32 features;
 
 	features = NETIF_F_TSO;
 	if (efx->type->offload_features & NETIF_F_V6_CSUM)
@@ -519,7 +538,7 @@
 static int efx_ethtool_set_tx_csum(struct net_device *net_dev, u32 enable)
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
-	unsigned long features = efx->type->offload_features & NETIF_F_ALL_CSUM;
+	u32 features = efx->type->offload_features & NETIF_F_ALL_CSUM;
 
 	if (enable)
 		net_dev->features |= features;
@@ -635,7 +654,7 @@
 	/* Find lowest IRQ moderation across all used TX queues */
 	coalesce->tx_coalesce_usecs_irq = ~((u32) 0);
 	efx_for_each_channel(channel, efx) {
-		if (!efx_channel_get_tx_queue(channel, 0))
+		if (!efx_channel_has_tx_queues(channel))
 			continue;
 		if (channel->irq_moderation < coalesce->tx_coalesce_usecs_irq) {
 			if (channel->channel < efx->n_rx_channels)
@@ -680,8 +699,8 @@
 
 	/* If the channel is shared only allow RX parameters to be set */
 	efx_for_each_channel(channel, efx) {
-		if (efx_channel_get_rx_queue(channel) &&
-		    efx_channel_get_tx_queue(channel, 0) &&
+		if (efx_channel_has_rx_queue(channel) &&
+		    efx_channel_has_tx_queues(channel) &&
 		    tx_usecs) {
 			netif_err(efx, drv, efx->net_dev, "Channel is shared. "
 				  "Only RX coalescing may be set\n");
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/falcon_boards.c linux-libre-2.6.39-gnu/drivers/net/sfc/falcon_boards.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/falcon_boards.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/falcon_boards.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2009 Solarflare Communications Inc.
+ * Copyright 2007-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/falcon.c linux-libre-2.6.39-gnu/drivers/net/sfc/falcon.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/falcon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/falcon.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -692,7 +692,7 @@
 	efx_oword_t md_stat;
 	int count;
 
-	/* wait upto 50ms - taken max from datasheet */
+	/* wait up to 50ms - taken max from datasheet */
 	for (count = 0; count < 5000; count++) {
 		efx_reado(efx, &md_stat, FR_AB_MD_STAT);
 		if (EFX_OWORD_FIELD(md_stat, FRF_AB_MD_BSY) == 0) {
@@ -1221,7 +1221,7 @@
 
 			return 0;
 		}
-	} while (++count < 20);	/* wait upto 0.4 sec */
+	} while (++count < 20);	/* wait up to 0.4 sec */
 
 	netif_err(efx, hw, efx->net_dev, "timed out waiting for SRAM reset\n");
 	return -ETIMEDOUT;
@@ -1478,36 +1478,26 @@
 	/* RX control FIFO thresholds (32 entries) */
 	const unsigned ctrl_xon_thr = 20;
 	const unsigned ctrl_xoff_thr = 25;
-	/* RX data FIFO thresholds (256-byte units; size varies) */
-	int data_xon_thr = efx_nic_rx_xon_thresh >> 8;
-	int data_xoff_thr = efx_nic_rx_xoff_thresh >> 8;
 	efx_oword_t reg;
 
 	efx_reado(efx, &reg, FR_AZ_RX_CFG);
 	if (efx_nic_rev(efx) <= EFX_REV_FALCON_A1) {
 		/* Data FIFO size is 5.5K */
-		if (data_xon_thr < 0)
-			data_xon_thr = 512 >> 8;
-		if (data_xoff_thr < 0)
-			data_xoff_thr = 2048 >> 8;
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_DESC_PUSH_EN, 0);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_USR_BUF_SIZE,
 				    huge_buf_size);
-		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, data_xon_thr);
-		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, data_xoff_thr);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_MAC_TH, 512 >> 8);
+		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_MAC_TH, 2048 >> 8);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XON_TX_TH, ctrl_xon_thr);
 		EFX_SET_OWORD_FIELD(reg, FRF_AA_RX_XOFF_TX_TH, ctrl_xoff_thr);
 	} else {
 		/* Data FIFO size is 80K; register fields moved */
-		if (data_xon_thr < 0)
-			data_xon_thr = 27648 >> 8; /* ~3*max MTU */
-		if (data_xoff_thr < 0)
-			data_xoff_thr = 54272 >> 8; /* ~80Kb - 3*max MTU */
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_DESC_PUSH_EN, 0);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_USR_BUF_SIZE,
 				    huge_buf_size);
-		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, data_xon_thr);
-		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, data_xoff_thr);
+		/* Send XON and XOFF at ~3 * max MTU away from empty/full */
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_MAC_TH, 27648 >> 8);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_MAC_TH, 54272 >> 8);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XON_TX_TH, ctrl_xon_thr);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_XOFF_TX_TH, ctrl_xoff_thr);
 		EFX_SET_OWORD_FIELD(reg, FRF_BZ_RX_INGR_EN, 1);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/falcon_xmac.c linux-libre-2.6.39-gnu/drivers/net/sfc/falcon_xmac.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/falcon_xmac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/falcon_xmac.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/filter.c linux-libre-2.6.39-gnu/drivers/net/sfc/filter.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/filter.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/filter.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,6 +8,7 @@
  */
 
 #include <linux/in.h>
+#include <net/ip.h>
 #include "efx.h"
 #include "filter.h"
 #include "io.h"
@@ -27,6 +28,10 @@
  */
 #define FILTER_CTL_SRCH_MAX 200
 
+/* Don't try very hard to find space for performance hints, as this is
+ * counter-productive. */
+#define FILTER_CTL_SRCH_HINT_MAX 5
+
 enum efx_filter_table_id {
 	EFX_FILTER_TABLE_RX_IP = 0,
 	EFX_FILTER_TABLE_RX_MAC,
@@ -47,6 +52,10 @@
 struct efx_filter_state {
 	spinlock_t	lock;
 	struct efx_filter_table table[EFX_FILTER_TABLE_COUNT];
+#ifdef CONFIG_RFS_ACCEL
+	u32		*rps_flow_id;
+	unsigned	rps_expire_index;
+#endif
 };
 
 /* The filter hash function is LFSR polynomial x^16 + x^3 + 1 of a 32-bit
@@ -325,15 +334,16 @@
 			     struct efx_filter_spec *spec, u32 key,
 			     bool for_insert, int *depth_required)
 {
-	unsigned hash, incr, filter_idx, depth;
+	unsigned hash, incr, filter_idx, depth, depth_max;
 	struct efx_filter_spec *cmp;
 
 	hash = efx_filter_hash(key);
 	incr = efx_filter_increment(key);
+	depth_max = (spec->priority <= EFX_FILTER_PRI_HINT ?
+		     FILTER_CTL_SRCH_HINT_MAX : FILTER_CTL_SRCH_MAX);
 
 	for (depth = 1, filter_idx = hash & (table->size - 1);
-	     depth <= FILTER_CTL_SRCH_MAX &&
-		     test_bit(filter_idx, table->used_bitmap);
+	     depth <= depth_max && test_bit(filter_idx, table->used_bitmap);
 	     ++depth) {
 		cmp = &table->spec[filter_idx];
 		if (efx_filter_equal(spec, cmp))
@@ -342,7 +352,7 @@
 	}
 	if (!for_insert)
 		return -ENOENT;
-	if (depth > FILTER_CTL_SRCH_MAX)
+	if (depth > depth_max)
 		return -EBUSY;
 found:
 	*depth_required = depth;
@@ -562,6 +572,13 @@
 	spin_lock_init(&state->lock);
 
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+#ifdef CONFIG_RFS_ACCEL
+		state->rps_flow_id = kcalloc(FR_BZ_RX_FILTER_TBL0_ROWS,
+					     sizeof(*state->rps_flow_id),
+					     GFP_KERNEL);
+		if (!state->rps_flow_id)
+			goto fail;
+#endif
 		table = &state->table[EFX_FILTER_TABLE_RX_IP];
 		table->id = EFX_FILTER_TABLE_RX_IP;
 		table->offset = FR_BZ_RX_FILTER_TBL0;
@@ -607,5 +624,97 @@
 		kfree(state->table[table_id].used_bitmap);
 		vfree(state->table[table_id].spec);
 	}
+#ifdef CONFIG_RFS_ACCEL
+	kfree(state->rps_flow_id);
+#endif
 	kfree(state);
 }
+
+#ifdef CONFIG_RFS_ACCEL
+
+int efx_filter_rfs(struct net_device *net_dev, const struct sk_buff *skb,
+		   u16 rxq_index, u32 flow_id)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	struct efx_channel *channel;
+	struct efx_filter_state *state = efx->filter_state;
+	struct efx_filter_spec spec;
+	const struct iphdr *ip;
+	const __be16 *ports;
+	int nhoff;
+	int rc;
+
+	nhoff = skb_network_offset(skb);
+
+	if (skb->protocol != htons(ETH_P_IP))
+		return -EPROTONOSUPPORT;
+
+	/* RFS must validate the IP header length before calling us */
+	EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + sizeof(*ip)));
+	ip = (const struct iphdr *)(skb->data + nhoff);
+	if (ip->frag_off & htons(IP_MF | IP_OFFSET))
+		return -EPROTONOSUPPORT;
+	EFX_BUG_ON_PARANOID(!pskb_may_pull(skb, nhoff + 4 * ip->ihl + 4));
+	ports = (const __be16 *)(skb->data + nhoff + 4 * ip->ihl);
+
+	efx_filter_init_rx(&spec, EFX_FILTER_PRI_HINT, 0, rxq_index);
+	rc = efx_filter_set_ipv4_full(&spec, ip->protocol,
+				      ip->daddr, ports[1], ip->saddr, ports[0]);
+	if (rc)
+		return rc;
+
+	rc = efx_filter_insert_filter(efx, &spec, true);
+	if (rc < 0)
+		return rc;
+
+	/* Remember this so we can check whether to expire the filter later */
+	state->rps_flow_id[rc] = flow_id;
+	channel = efx_get_channel(efx, skb_get_rx_queue(skb));
+	++channel->rfs_filters_added;
+
+	netif_info(efx, rx_status, efx->net_dev,
+		   "steering %s %pI4:%u:%pI4:%u to queue %u [flow %u filter %d]\n",
+		   (ip->protocol == IPPROTO_TCP) ? "TCP" : "UDP",
+		   &ip->saddr, ntohs(ports[0]), &ip->daddr, ntohs(ports[1]),
+		   rxq_index, flow_id, rc);
+
+	return rc;
+}
+
+bool __efx_filter_rfs_expire(struct efx_nic *efx, unsigned quota)
+{
+	struct efx_filter_state *state = efx->filter_state;
+	struct efx_filter_table *table = &state->table[EFX_FILTER_TABLE_RX_IP];
+	unsigned mask = table->size - 1;
+	unsigned index;
+	unsigned stop;
+
+	if (!spin_trylock_bh(&state->lock))
+		return false;
+
+	index = state->rps_expire_index;
+	stop = (index + quota) & mask;
+
+	while (index != stop) {
+		if (test_bit(index, table->used_bitmap) &&
+		    table->spec[index].priority == EFX_FILTER_PRI_HINT &&
+		    rps_may_expire_flow(efx->net_dev,
+					table->spec[index].dmaq_id,
+					state->rps_flow_id[index], index)) {
+			netif_info(efx, rx_status, efx->net_dev,
+				   "expiring filter %d [flow %u]\n",
+				   index, state->rps_flow_id[index]);
+			efx_filter_table_clear_entry(efx, table, index);
+		}
+		index = (index + 1) & mask;
+	}
+
+	state->rps_expire_index = stop;
+	if (table->used == 0)
+		efx_filter_table_reset_search_depth(table);
+
+	spin_unlock_bh(&state->lock);
+	return true;
+}
+
+#endif /* CONFIG_RFS_ACCEL */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/io.h linux-libre-2.6.39-gnu/drivers/net/sfc/io.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -48,9 +48,9 @@
  *   replacing the low 96 bits with zero does not affect functionality.
  * - If the host writes to the last dword address of such a register
  *   (i.e. the high 32 bits) the underlying register will always be
- *   written.  If the collector does not hold values for the low 96
- *   bits of the register, they will be written as zero.  Writing to
- *   the last qword does not have this effect and must not be done.
+ *   written.  If the collector and the current write together do not
+ *   provide values for all 128 bits of the register, the low 96 bits
+ *   will be written as zero.
  * - If the host writes to the address of any other part of such a
  *   register while the collector already holds values for some other
  *   register, the write is discarded and the collector maintains its
@@ -103,6 +103,7 @@
 	_efx_writed(efx, value->u32[2], reg + 8);
 	_efx_writed(efx, value->u32[3], reg + 12);
 #endif
+	wmb();
 	mmiowb();
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
 }
@@ -125,6 +126,7 @@
 	__raw_writel((__force u32)value->u32[0], membase + addr);
 	__raw_writel((__force u32)value->u32[1], membase + addr + 4);
 #endif
+	wmb();
 	mmiowb();
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
 }
@@ -139,6 +141,7 @@
 
 	/* No lock required */
 	_efx_writed(efx, value->u32[0], reg);
+	wmb();
 }
 
 /* Read a 128-bit CSR, locking as appropriate. */
@@ -149,6 +152,7 @@
 
 	spin_lock_irqsave(&efx->biu_lock, flags);
 	value->u32[0] = _efx_readd(efx, reg + 0);
+	rmb();
 	value->u32[1] = _efx_readd(efx, reg + 4);
 	value->u32[2] = _efx_readd(efx, reg + 8);
 	value->u32[3] = _efx_readd(efx, reg + 12);
@@ -171,6 +175,7 @@
 	value->u64[0] = (__force __le64)__raw_readq(membase + addr);
 #else
 	value->u32[0] = (__force __le32)__raw_readl(membase + addr);
+	rmb();
 	value->u32[1] = (__force __le32)__raw_readl(membase + addr + 4);
 #endif
 	spin_unlock_irqrestore(&efx->biu_lock, flags);
@@ -237,12 +242,14 @@
 
 #ifdef EFX_USE_QWORD_IO
 	_efx_writeq(efx, value->u64[0], reg + 0);
+	_efx_writeq(efx, value->u64[1], reg + 8);
 #else
 	_efx_writed(efx, value->u32[0], reg + 0);
 	_efx_writed(efx, value->u32[1], reg + 4);
-#endif
 	_efx_writed(efx, value->u32[2], reg + 8);
 	_efx_writed(efx, value->u32[3], reg + 12);
+#endif
+	wmb();
 }
 #define efx_writeo_page(efx, value, reg, page)				\
 	_efx_writeo_page(efx, value,					\
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi.c linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2008-2009 Solarflare Communications Inc.
+ * Copyright 2008-2011 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
@@ -50,6 +50,20 @@
 	return &nic_data->mcdi;
 }
 
+static inline void
+efx_mcdi_readd(struct efx_nic *efx, efx_dword_t *value, unsigned reg)
+{
+	struct siena_nic_data *nic_data = efx->nic_data;
+	value->u32[0] = (__force __le32)__raw_readl(nic_data->mcdi_smem + reg);
+}
+
+static inline void
+efx_mcdi_writed(struct efx_nic *efx, const efx_dword_t *value, unsigned reg)
+{
+	struct siena_nic_data *nic_data = efx->nic_data;
+	__raw_writel((__force u32)value->u32[0], nic_data->mcdi_smem + reg);
+}
+
 void efx_mcdi_init(struct efx_nic *efx)
 {
 	struct efx_mcdi_iface *mcdi;
@@ -70,8 +84,8 @@
 			    const u8 *inbuf, size_t inlen)
 {
 	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
-	unsigned pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
-	unsigned doorbell = FR_CZ_MC_TREG_SMEM + MCDI_DOORBELL(efx);
+	unsigned pdu = MCDI_PDU(efx);
+	unsigned doorbell = MCDI_DOORBELL(efx);
 	unsigned int i;
 	efx_dword_t hdr;
 	u32 xflags, seqno;
@@ -92,29 +106,28 @@
 			     MCDI_HEADER_SEQ, seqno,
 			     MCDI_HEADER_XFLAGS, xflags);
 
-	efx_writed(efx, &hdr, pdu);
+	efx_mcdi_writed(efx, &hdr, pdu);
 
 	for (i = 0; i < inlen; i += 4)
-		_efx_writed(efx, *((__le32 *)(inbuf + i)), pdu + 4 + i);
-
-	/* Ensure the payload is written out before the header */
-	wmb();
+		efx_mcdi_writed(efx, (const efx_dword_t *)(inbuf + i),
+				pdu + 4 + i);
 
 	/* ring the doorbell with a distinctive value */
-	_efx_writed(efx, (__force __le32) 0x45789abc, doorbell);
+	EFX_POPULATE_DWORD_1(hdr, EFX_DWORD_0, 0x45789abc);
+	efx_mcdi_writed(efx, &hdr, doorbell);
 }
 
 static void efx_mcdi_copyout(struct efx_nic *efx, u8 *outbuf, size_t outlen)
 {
 	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
-	unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+	unsigned int pdu = MCDI_PDU(efx);
 	int i;
 
 	BUG_ON(atomic_read(&mcdi->state) == MCDI_STATE_QUIESCENT);
 	BUG_ON(outlen & 3 || outlen >= 0x100);
 
 	for (i = 0; i < outlen; i += 4)
-		*((__le32 *)(outbuf + i)) = _efx_readd(efx, pdu + 4 + i);
+		efx_mcdi_readd(efx, (efx_dword_t *)(outbuf + i), pdu + 4 + i);
 }
 
 static int efx_mcdi_poll(struct efx_nic *efx)
@@ -122,7 +135,7 @@
 	struct efx_mcdi_iface *mcdi = efx_mcdi(efx);
 	unsigned int time, finish;
 	unsigned int respseq, respcmd, error;
-	unsigned int pdu = FR_CZ_MC_TREG_SMEM + MCDI_PDU(efx);
+	unsigned int pdu = MCDI_PDU(efx);
 	unsigned int rc, spins;
 	efx_dword_t reg;
 
@@ -148,8 +161,7 @@
 
 		time = get_seconds();
 
-		rmb();
-		efx_readd(efx, &reg, pdu);
+		efx_mcdi_readd(efx, &reg, pdu);
 
 		/* All 1's indicates that shared memory is in reset (and is
 		 * not a valid header). Wait for it to come out reset before
@@ -176,7 +188,7 @@
 			  respseq, mcdi->seqno);
 		rc = EIO;
 	} else if (error) {
-		efx_readd(efx, &reg, pdu + 4);
+		efx_mcdi_readd(efx, &reg, pdu + 4);
 		switch (EFX_DWORD_FIELD(reg, EFX_DWORD_0)) {
 #define TRANSLATE_ERROR(name)					\
 		case MC_CMD_ERR_ ## name:			\
@@ -210,21 +222,21 @@
 /* Test and clear MC-rebooted flag for this port/function */
 int efx_mcdi_poll_reboot(struct efx_nic *efx)
 {
-	unsigned int addr = FR_CZ_MC_TREG_SMEM + MCDI_REBOOT_FLAG(efx);
+	unsigned int addr = MCDI_REBOOT_FLAG(efx);
 	efx_dword_t reg;
 	uint32_t value;
 
 	if (efx_nic_rev(efx) < EFX_REV_SIENA_A0)
 		return false;
 
-	efx_readd(efx, &reg, addr);
+	efx_mcdi_readd(efx, &reg, addr);
 	value = EFX_DWORD_FIELD(reg, EFX_DWORD_0);
 
 	if (value == 0)
 		return 0;
 
 	EFX_ZERO_DWORD(reg);
-	efx_writed(efx, &reg, addr);
+	efx_mcdi_writed(efx, &reg, addr);
 
 	if (value == MC_STATUS_DWORD_ASSERT)
 		return -EINTR;
@@ -452,7 +464,7 @@
 	 *
 	 * There's a race here with efx_mcdi_rpc(), because we might receive
 	 * a REBOOT event *before* the request has been copied out. In polled
-	 * mode (during startup) this is irrelevent, because efx_mcdi_complete()
+	 * mode (during startup) this is irrelevant, because efx_mcdi_complete()
 	 * is ignored. In event mode, this condition is just an edge-case of
 	 * receiving a REBOOT event after posting the MCDI request. Did the mc
 	 * reboot before or after the copyout? The best we can do always is
@@ -602,7 +614,7 @@
  **************************************************************************
  */
 
-int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build)
+void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len)
 {
 	u8 outbuf[ALIGN(MC_CMD_GET_VERSION_V1_OUT_LEN, 4)];
 	size_t outlength;
@@ -616,29 +628,20 @@
 	if (rc)
 		goto fail;
 
-	if (outlength == MC_CMD_GET_VERSION_V0_OUT_LEN) {
-		*version = 0;
-		*build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
-		return 0;
-	}
-
 	if (outlength < MC_CMD_GET_VERSION_V1_OUT_LEN) {
 		rc = -EIO;
 		goto fail;
 	}
 
 	ver_words = (__le16 *)MCDI_PTR(outbuf, GET_VERSION_OUT_VERSION);
-	*version = (((u64)le16_to_cpu(ver_words[0]) << 48) |
-		    ((u64)le16_to_cpu(ver_words[1]) << 32) |
-		    ((u64)le16_to_cpu(ver_words[2]) << 16) |
-		    le16_to_cpu(ver_words[3]));
-	*build = MCDI_DWORD(outbuf, GET_VERSION_OUT_FIRMWARE);
-
-	return 0;
+	snprintf(buf, len, "%u.%u.%u.%u",
+		 le16_to_cpu(ver_words[0]), le16_to_cpu(ver_words[1]),
+		 le16_to_cpu(ver_words[2]), le16_to_cpu(ver_words[3]));
+	return;
 
 fail:
 	netif_err(efx, probe, efx->net_dev, "%s: failed rc=%d\n", __func__, rc);
-	return rc;
+	buf[0] = 0;
 }
 
 int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi.h linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2008-2009 Solarflare Communications Inc.
+ * Copyright 2008-2010 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
@@ -93,7 +93,7 @@
 #define MCDI_EVENT_FIELD(_ev, _field)			\
 	EFX_QWORD_FIELD(_ev, MCDI_EVENT_ ## _field)
 
-extern int efx_mcdi_fwver(struct efx_nic *efx, u64 *version, u32 *build);
+extern void efx_mcdi_print_fwver(struct efx_nic *efx, char *buf, size_t len);
 extern int efx_mcdi_drv_attach(struct efx_nic *efx, bool driver_operating,
 			       bool *was_attached_out);
 extern int efx_mcdi_get_board_cfg(struct efx_nic *efx, u8 *mac_address,
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi_mac.c linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi_mac.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi_mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi_mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2009 Solarflare Communications Inc.
+ * Copyright 2009-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi_pcol.h linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi_pcol.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi_pcol.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi_pcol.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2009 Solarflare Communications Inc.
+ * Copyright 2009-2011 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
@@ -103,7 +103,7 @@
  *
  * If Code==CMDDONE, then the fields are further interpreted as:
  *
- *   - LEVEL==INFO    Command succeded
+ *   - LEVEL==INFO    Command succeeded
  *   - LEVEL==ERR     Command failed
  *
  *    0     8         16      24     32
@@ -572,7 +572,7 @@
   (4*(_numwords))
 
 /* MC_CMD_SET_RAND_SEED:
- * Set the 16byte seed for the MC psuedo-random generator
+ * Set the 16byte seed for the MC pseudo-random generator
  */
 #define MC_CMD_SET_RAND_SEED 0x1a
 #define MC_CMD_SET_RAND_SEED_IN_LEN 16
@@ -1162,7 +1162,7 @@
 #define MC_CMD_MAC_STATS_CMD_CLEAR_WIDTH 1
 #define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_LBN 2
 #define MC_CMD_MAC_STATS_CMD_PERIODIC_CHANGE_WIDTH 1
-/* Remaining PERIOD* fields only relevent when PERIODIC_CHANGE is set */
+/* Remaining PERIOD* fields only relevant when PERIODIC_CHANGE is set */
 #define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_LBN 3
 #define MC_CMD_MAC_STATS_CMD_PERIODIC_ENABLE_WIDTH 1
 #define MC_CMD_MAC_STATS_CMD_PERIODIC_CLEAR_LBN 4
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi_phy.c linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mcdi_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mcdi_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2009 Solarflare Communications Inc.
+ * Copyright 2009-2010 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
@@ -449,7 +449,7 @@
 	struct efx_mcdi_phy_data *phy_cfg = efx->phy_data;
 	u32 rmtadv;
 
-	/* The link partner capabilities are only relevent if the
+	/* The link partner capabilities are only relevant if the
 	 * link supports flow control autonegotiation */
 	if (~phy_cfg->supported_cap & (1 << MC_CMD_PHY_CAP_AN_LBN))
 		return;
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mdio_10g.c linux-libre-2.6.39-gnu/drivers/net/sfc/mdio_10g.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mdio_10g.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mdio_10g.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 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
@@ -51,13 +51,10 @@
 	return spins ? spins : -ETIMEDOUT;
 }
 
-static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd, int fault_fatal)
+static int efx_mdio_check_mmd(struct efx_nic *efx, int mmd)
 {
 	int status;
 
-	if (LOOPBACK_INTERNAL(efx))
-		return 0;
-
 	if (mmd != MDIO_MMD_AN) {
 		/* Read MMD STATUS2 to check it is responding. */
 		status = efx_mdio_read(efx, mmd, MDIO_STAT2);
@@ -68,20 +65,6 @@
 		}
 	}
 
-	/* Read MMD STATUS 1 to check for fault. */
-	status = efx_mdio_read(efx, mmd, MDIO_STAT1);
-	if (status & MDIO_STAT1_FAULT) {
-		if (fault_fatal) {
-			netif_err(efx, hw, efx->net_dev,
-				  "PHY MMD %d reporting fatal"
-				  " fault: status %x\n", mmd, status);
-			return -EIO;
-		} else {
-			netif_dbg(efx, hw, efx->net_dev,
-				  "PHY MMD %d reporting status"
-				  " %x (expected)\n", mmd, status);
-		}
-	}
 	return 0;
 }
 
@@ -130,8 +113,7 @@
 	return rc;
 }
 
-int efx_mdio_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)
 {
 	int mmd = 0, probe_mmd, devs1, devs2;
 	u32 devices;
@@ -161,13 +143,9 @@
 
 	/* Check all required MMDs are responding and happy. */
 	while (mmd_mask) {
-		if (mmd_mask & 1) {
-			int fault_fatal = fatal_mask & 1;
-			if (efx_mdio_check_mmd(efx, mmd, fault_fatal))
-				return -EIO;
-		}
+		if ((mmd_mask & 1) && efx_mdio_check_mmd(efx, mmd))
+			return -EIO;
 		mmd_mask = mmd_mask >> 1;
-		fatal_mask = fatal_mask >> 1;
 		mmd++;
 	}
 
@@ -337,7 +315,7 @@
 			  "no MDIO PHY present with ID %d\n", efx->mdio.prtad);
 		rc = -EINVAL;
 	} else {
-		rc = efx_mdio_check_mmds(efx, efx->mdio.mmds, 0);
+		rc = efx_mdio_check_mmds(efx, efx->mdio.mmds);
 	}
 
 	mutex_unlock(&efx->mac_lock);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mdio_10g.h linux-libre-2.6.39-gnu/drivers/net/sfc/mdio_10g.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mdio_10g.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mdio_10g.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 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
@@ -68,8 +68,7 @@
 			      int spins, int spintime);
 
 /* 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);
+int efx_mdio_check_mmds(struct efx_nic *efx, unsigned int mmd_mask);
 
 /* Check the link status of specified mmds in bit mask */
 extern bool efx_mdio_links_ok(struct efx_nic *efx, unsigned int mmd_mask);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/mtd.c linux-libre-2.6.39-gnu/drivers/net/sfc/mtd.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/mtd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/mtd.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/net_driver.h linux-libre-2.6.39-gnu/drivers/net/sfc/net_driver.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/net_driver.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/net_driver.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2011 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
@@ -41,7 +41,7 @@
  *
  **************************************************************************/
 
-#define EFX_DRIVER_VERSION	"3.0"
+#define EFX_DRIVER_VERSION	"3.1"
 
 #ifdef EFX_ENABLE_DEBUG
 #define EFX_BUG_ON_PARANOID(x) BUG_ON(x)
@@ -63,10 +63,12 @@
 /* Checksum generation is a per-queue option in hardware, so each
  * queue visible to the networking core is backed by two hardware TX
  * queues. */
-#define EFX_MAX_CORE_TX_QUEUES	EFX_MAX_CHANNELS
-#define EFX_TXQ_TYPE_OFFLOAD	1
-#define EFX_TXQ_TYPES		2
-#define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CORE_TX_QUEUES)
+#define EFX_MAX_TX_TC		2
+#define EFX_MAX_CORE_TX_QUEUES	(EFX_MAX_TX_TC * EFX_MAX_CHANNELS)
+#define EFX_TXQ_TYPE_OFFLOAD	1	/* flag */
+#define EFX_TXQ_TYPE_HIGHPRI	2	/* flag */
+#define EFX_TXQ_TYPES		4
+#define EFX_MAX_TX_QUEUES	(EFX_TXQ_TYPES * EFX_MAX_CHANNELS)
 
 /**
  * struct efx_special_buffer - An Efx special buffer
@@ -140,6 +142,7 @@
  * @buffer: The software buffer ring
  * @txd: The hardware descriptor ring
  * @ptr_mask: The size of the ring minus 1.
+ * @initialised: Has hardware queue been initialised?
  * @flushed: Used when handling queue flushing
  * @read_count: Current read pointer.
  *	This is the number of buffers that have been removed from both rings.
@@ -182,6 +185,7 @@
 	struct efx_tx_buffer *buffer;
 	struct efx_special_buffer txd;
 	unsigned int ptr_mask;
+	bool initialised;
 	enum efx_flush_state flushed;
 
 	/* Members used mainly on the completion path */
@@ -210,15 +214,17 @@
  *	If both this and page are %NULL, the buffer slot is currently free.
  * @page: The associated page buffer, if any.
  *	If both this and skb are %NULL, the buffer slot is currently free.
- * @data: Pointer to ethernet header
  * @len: Buffer length, in bytes.
+ * @is_page: Indicates if @page is valid. If false, @skb is valid.
  */
 struct efx_rx_buffer {
 	dma_addr_t dma_addr;
-	struct sk_buff *skb;
-	struct page *page;
-	char *data;
+	union {
+		struct sk_buff *skb;
+		struct page *page;
+	} u;
 	unsigned int len;
+	bool is_page;
 };
 
 /**
@@ -324,7 +330,6 @@
  * @eventq_mask: Event queue pointer mask
  * @eventq_read_ptr: Event queue read pointer
  * @last_eventq_read_ptr: Last event queue read pointer value.
- * @magic_count: Event queue test event count
  * @irq_count: Number of IRQs since last adaptive moderation decision
  * @irq_mod_score: IRQ moderation score
  * @rx_alloc_level: Watermark based heuristic counter for pushing descriptors
@@ -354,10 +359,12 @@
 	unsigned int eventq_mask;
 	unsigned int eventq_read_ptr;
 	unsigned int last_eventq_read_ptr;
-	unsigned int magic_count;
 
 	unsigned int irq_count;
 	unsigned int irq_mod_score;
+#ifdef CONFIG_RFS_ACCEL
+	unsigned int rfs_filters_added;
+#endif
 
 	int rx_alloc_level;
 	int rx_alloc_push_pages;
@@ -377,7 +384,7 @@
 	bool rx_pkt_csummed;
 
 	struct efx_rx_queue rx_queue;
-	struct efx_tx_queue tx_queue[2];
+	struct efx_tx_queue tx_queue[EFX_TXQ_TYPES];
 };
 
 enum efx_led_mode {
@@ -661,7 +668,7 @@
  * @irq_zero_count: Number of legacy IRQs seen with queue flags == 0
  * @fatal_irq_level: IRQ level (bit number) used for serious errors
  * @mtd_list: List of MTDs attached to the NIC
- * @nic_data: Hardware dependant state
+ * @nic_data: Hardware dependent state
  * @mac_lock: MAC access lock. Protects @port_enabled, @phy_mode,
  *	@port_inhibited, efx_monitor() and efx_reconfigure_port()
  * @port_enabled: Port enabled indicator.
@@ -906,7 +913,7 @@
 	unsigned int phys_addr_channels;
 	unsigned int tx_dc_base;
 	unsigned int rx_dc_base;
-	unsigned long offload_features;
+	u32 offload_features;
 	u32 reset_world_flags;
 };
 
@@ -938,18 +945,40 @@
 	return &efx->channel[efx->tx_channel_offset + index]->tx_queue[type];
 }
 
+static inline bool efx_channel_has_tx_queues(struct efx_channel *channel)
+{
+	return channel->channel - channel->efx->tx_channel_offset <
+		channel->efx->n_tx_channels;
+}
+
 static inline struct efx_tx_queue *
 efx_channel_get_tx_queue(struct efx_channel *channel, unsigned type)
 {
-	struct efx_tx_queue *tx_queue = channel->tx_queue;
-	EFX_BUG_ON_PARANOID(type >= EFX_TXQ_TYPES);
-	return tx_queue->channel ? tx_queue + type : NULL;
+	EFX_BUG_ON_PARANOID(!efx_channel_has_tx_queues(channel) ||
+			    type >= EFX_TXQ_TYPES);
+	return &channel->tx_queue[type];
+}
+
+static inline bool efx_tx_queue_used(struct efx_tx_queue *tx_queue)
+{
+	return !(tx_queue->efx->net_dev->num_tc < 2 &&
+		 tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI);
 }
 
 /* Iterate over all TX queues belonging to a channel */
 #define efx_for_each_channel_tx_queue(_tx_queue, _channel)		\
-	for (_tx_queue = efx_channel_get_tx_queue(channel, 0);		\
-	     _tx_queue && _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES; \
+	if (!efx_channel_has_tx_queues(_channel))			\
+		;							\
+	else								\
+		for (_tx_queue = (_channel)->tx_queue;			\
+		     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES && \
+			     efx_tx_queue_used(_tx_queue);		\
+		     _tx_queue++)
+
+/* Iterate over all possible TX queues belonging to a channel */
+#define efx_for_each_possible_channel_tx_queue(_tx_queue, _channel)	\
+	for (_tx_queue = (_channel)->tx_queue;				\
+	     _tx_queue < (_channel)->tx_queue + EFX_TXQ_TYPES;		\
 	     _tx_queue++)
 
 static inline struct efx_rx_queue *
@@ -959,18 +988,26 @@
 	return &efx->channel[index]->rx_queue;
 }
 
+static inline bool efx_channel_has_rx_queue(struct efx_channel *channel)
+{
+	return channel->channel < channel->efx->n_rx_channels;
+}
+
 static inline struct efx_rx_queue *
 efx_channel_get_rx_queue(struct efx_channel *channel)
 {
-	return channel->channel < channel->efx->n_rx_channels ?
-		&channel->rx_queue : NULL;
+	EFX_BUG_ON_PARANOID(!efx_channel_has_rx_queue(channel));
+	return &channel->rx_queue;
 }
 
 /* Iterate over all RX queues belonging to a channel */
 #define efx_for_each_channel_rx_queue(_rx_queue, _channel)		\
-	for (_rx_queue = efx_channel_get_rx_queue(channel);		\
-	     _rx_queue;							\
-	     _rx_queue = NULL)
+	if (!efx_channel_has_rx_queue(_channel))			\
+		;							\
+	else								\
+		for (_rx_queue = &(_channel)->rx_queue;			\
+		     _rx_queue;						\
+		     _rx_queue = NULL)
 
 static inline struct efx_channel *
 efx_rx_queue_channel(struct efx_rx_queue *rx_queue)
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/nic.c linux-libre-2.6.39-gnu/drivers/net/sfc/nic.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/nic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/nic.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 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
@@ -41,26 +41,6 @@
 #define RX_DC_ENTRIES 64
 #define RX_DC_ENTRIES_ORDER 3
 
-/* RX FIFO XOFF watermark
- *
- * When the amount of the RX FIFO increases used increases past this
- * watermark send XOFF. Only used if RX flow control is enabled (ethtool -A)
- * This also has an effect on RX/TX arbitration
- */
-int efx_nic_rx_xoff_thresh = -1;
-module_param_named(rx_xoff_thresh_bytes, efx_nic_rx_xoff_thresh, int, 0644);
-MODULE_PARM_DESC(rx_xoff_thresh_bytes, "RX fifo XOFF threshold");
-
-/* RX FIFO XON watermark
- *
- * When the amount of the RX FIFO used decreases below this
- * watermark send XON. Only used if TX flow control is enabled (ethtool -A)
- * This also has an effect on RX/TX arbitration
- */
-int efx_nic_rx_xon_thresh = -1;
-module_param_named(rx_xon_thresh_bytes, efx_nic_rx_xon_thresh, int, 0644);
-MODULE_PARM_DESC(rx_xon_thresh_bytes, "RX fifo XON threshold");
-
 /* If EFX_MAX_INT_ERRORS internal errors occur within
  * EFX_INT_ERROR_EXPIRE seconds, we consider the NIC broken and
  * disable it.
@@ -104,7 +84,8 @@
 static inline efx_qword_t *efx_event(struct efx_channel *channel,
 				     unsigned int index)
 {
-	return ((efx_qword_t *) (channel->eventq.addr)) + index;
+	return ((efx_qword_t *) (channel->eventq.addr)) +
+		(index & channel->eventq_mask);
 }
 
 /* See if an event is present
@@ -445,8 +426,8 @@
 
 void efx_nic_init_tx(struct efx_tx_queue *tx_queue)
 {
-	efx_oword_t tx_desc_ptr;
 	struct efx_nic *efx = tx_queue->efx;
+	efx_oword_t reg;
 
 	tx_queue->flushed = FLUSH_NONE;
 
@@ -454,7 +435,7 @@
 	efx_init_special_buffer(efx, &tx_queue->txd);
 
 	/* Push TX descriptor ring to card */
-	EFX_POPULATE_OWORD_10(tx_desc_ptr,
+	EFX_POPULATE_OWORD_10(reg,
 			      FRF_AZ_TX_DESCQ_EN, 1,
 			      FRF_AZ_TX_ISCSI_DDIG_EN, 0,
 			      FRF_AZ_TX_ISCSI_HDIG_EN, 0,
@@ -470,17 +451,15 @@
 
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
 		int csum = tx_queue->queue & EFX_TXQ_TYPE_OFFLOAD;
-		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
-		EFX_SET_OWORD_FIELD(tx_desc_ptr, FRF_BZ_TX_TCP_CHKSM_DIS,
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_IP_CHKSM_DIS, !csum);
+		EFX_SET_OWORD_FIELD(reg, FRF_BZ_TX_TCP_CHKSM_DIS,
 				    !csum);
 	}
 
-	efx_writeo_table(efx, &tx_desc_ptr, efx->type->txd_ptr_tbl_base,
+	efx_writeo_table(efx, &reg, efx->type->txd_ptr_tbl_base,
 			 tx_queue->queue);
 
 	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0) {
-		efx_oword_t reg;
-
 		/* Only 128 bits in this register */
 		BUILD_BUG_ON(EFX_MAX_TX_QUEUES > 128);
 
@@ -491,6 +470,16 @@
 			set_bit_le(tx_queue->queue, (void *)&reg);
 		efx_writeo(efx, &reg, FR_AA_TX_CHKSM_CFG);
 	}
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_1(reg,
+				     FRF_BZ_TX_PACE,
+				     (tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+				     FFE_BZ_TX_PACE_OFF :
+				     FFE_BZ_TX_PACE_RESERVED);
+		efx_writeo_table(efx, &reg, FR_BZ_TX_PACE_TBL,
+				 tx_queue->queue);
+	}
 }
 
 static void efx_flush_tx_queue(struct efx_tx_queue *tx_queue)
@@ -685,7 +674,8 @@
 	efx_dword_t reg;
 	struct efx_nic *efx = channel->efx;
 
-	EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR, channel->eventq_read_ptr);
+	EFX_POPULATE_DWORD_1(reg, FRF_AZ_EVQ_RPTR,
+			     channel->eventq_read_ptr & channel->eventq_mask);
 	efx_writed_table(efx, &reg, efx->type->evq_rptr_tbl_base,
 			 channel->channel);
 }
@@ -920,7 +910,7 @@
 
 	code = EFX_QWORD_FIELD(*event, FSF_AZ_DRV_GEN_EV_MAGIC);
 	if (code == EFX_CHANNEL_MAGIC_TEST(channel))
-		++channel->magic_count;
+		; /* ignore */
 	else if (code == EFX_CHANNEL_MAGIC_FILL(channel))
 		/* The queue must be empty, so we won't receive any rx
 		 * events, so efx_process_channel() won't refill the
@@ -1027,8 +1017,7 @@
 		/* Clear this event by marking it all ones */
 		EFX_SET_QWORD(*p_event);
 
-		/* Increment read pointer */
-		read_ptr = (read_ptr + 1) & channel->eventq_mask;
+		++read_ptr;
 
 		ev_code = EFX_QWORD_FIELD(event, FSF_AZ_EV_CODE);
 
@@ -1072,6 +1061,13 @@
 	return spent;
 }
 
+/* Check whether an event is present in the eventq at the current
+ * read pointer.  Only useful for self-test.
+ */
+bool efx_nic_event_present(struct efx_channel *channel)
+{
+	return efx_event_present(efx_event(channel, channel->eventq_read_ptr));
+}
 
 /* Allocate buffer table entries for event queue */
 int efx_nic_probe_eventq(struct efx_channel *channel)
@@ -1177,7 +1173,7 @@
 	struct efx_tx_queue *tx_queue;
 	struct efx_rx_queue *rx_queue;
 	unsigned int read_ptr = channel->eventq_read_ptr;
-	unsigned int end_ptr = (read_ptr - 1) & channel->eventq_mask;
+	unsigned int end_ptr = read_ptr + channel->eventq_mask - 1;
 
 	do {
 		efx_qword_t *event = efx_event(channel, read_ptr);
@@ -1217,7 +1213,7 @@
 		 * it's ok to throw away every non-flush event */
 		EFX_SET_QWORD(*event);
 
-		read_ptr = (read_ptr + 1) & channel->eventq_mask;
+		++read_ptr;
 	} while (read_ptr != end_ptr);
 
 	channel->eventq_read_ptr = read_ptr;
@@ -1238,8 +1234,10 @@
 
 	/* Flush all tx queues in parallel */
 	efx_for_each_channel(channel, efx) {
-		efx_for_each_channel_tx_queue(tx_queue, channel)
-			efx_flush_tx_queue(tx_queue);
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->initialised)
+				efx_flush_tx_queue(tx_queue);
+		}
 	}
 
 	/* The hardware supports four concurrent rx flushes, each of which may
@@ -1262,8 +1260,9 @@
 					++rx_pending;
 				}
 			}
-			efx_for_each_channel_tx_queue(tx_queue, channel) {
-				if (tx_queue->flushed != FLUSH_DONE)
+			efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+				if (tx_queue->initialised &&
+				    tx_queue->flushed != FLUSH_DONE)
 					++tx_pending;
 			}
 		}
@@ -1278,8 +1277,9 @@
 	/* Mark the queues as all flushed. We're going to return failure
 	 * leading to a reset, or fake up success anyway */
 	efx_for_each_channel(channel, efx) {
-		efx_for_each_channel_tx_queue(tx_queue, channel) {
-			if (tx_queue->flushed != FLUSH_DONE)
+		efx_for_each_possible_channel_tx_queue(tx_queue, channel) {
+			if (tx_queue->initialised &&
+			    tx_queue->flushed != FLUSH_DONE)
 				netif_err(efx, hw, efx->net_dev,
 					  "tx queue %d flush command timed out\n",
 					  tx_queue->queue);
@@ -1682,6 +1682,19 @@
 	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0)
 		EFX_SET_OWORD_FIELD(temp, FRF_BZ_TX_FLUSH_MIN_LEN_EN, 1);
 	efx_writeo(efx, &temp, FR_AZ_TX_RESERVED);
+
+	if (efx_nic_rev(efx) >= EFX_REV_FALCON_B0) {
+		EFX_POPULATE_OWORD_4(temp,
+				     /* Default values */
+				     FRF_BZ_TX_PACE_SB_NOT_AF, 0x15,
+				     FRF_BZ_TX_PACE_SB_AF, 0xb,
+				     FRF_BZ_TX_PACE_FB_BASE, 0,
+				     /* Allow large pace values in the
+				      * fast bin. */
+				     FRF_BZ_TX_PACE_BIN_TH,
+				     FFE_BZ_TX_PACE_RESERVED);
+		efx_writeo(efx, &temp, FR_BZ_TX_PACE);
+	}
 }
 
 /* Register dump */
@@ -1924,6 +1937,13 @@
 
 		size = min_t(size_t, table->step, 16);
 
+		if (table->offset >= efx->type->mem_map_size) {
+			/* No longer mapped; return dummy data */
+			memcpy(buf, "\xde\xc0\xad\xde", 4);
+			buf += table->rows * size;
+			continue;
+		}
+
 		for (i = 0; i < table->rows; i++) {
 			switch (table->step) {
 			case 4: /* 32-bit register or SRAM */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/nic.h linux-libre-2.6.39-gnu/drivers/net/sfc/nic.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/nic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/nic.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2011 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
@@ -142,20 +142,16 @@
 
 /**
  * struct siena_nic_data - Siena NIC state
- * @fw_version: Management controller firmware version
- * @fw_build: Firmware build number
  * @mcdi: Management-Controller-to-Driver Interface
+ * @mcdi_smem: MCDI shared memory mapping. The mapping is always uncacheable.
  * @wol_filter_id: Wake-on-LAN packet filter id
  */
 struct siena_nic_data {
-	u64 fw_version;
-	u32 fw_build;
 	struct efx_mcdi_iface mcdi;
+	void __iomem *mcdi_smem;
 	int wol_filter_id;
 };
 
-extern void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len);
-
 extern struct efx_nic_type falcon_a1_nic_type;
 extern struct efx_nic_type falcon_b0_nic_type;
 extern struct efx_nic_type siena_a0_nic_type;
@@ -190,11 +186,11 @@
 extern void efx_nic_remove_eventq(struct efx_channel *channel);
 extern int efx_nic_process_eventq(struct efx_channel *channel, int rx_quota);
 extern void efx_nic_eventq_read_ack(struct efx_channel *channel);
+extern bool efx_nic_event_present(struct efx_channel *channel);
 
 /* MAC/PHY */
 extern void falcon_drain_tx_fifo(struct efx_nic *efx);
 extern void falcon_reconfigure_mac_wrapper(struct efx_nic *efx);
-extern int efx_nic_rx_xoff_thresh, efx_nic_rx_xon_thresh;
 
 /* Interrupts and test events */
 extern int efx_nic_init_interrupt(struct efx_nic *efx);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/phy.h linux-libre-2.6.39-gnu/drivers/net/sfc/phy.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/phy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/phy.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2009 Solarflare Communications Inc.
+ * Copyright 2007-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/qt202x_phy.c linux-libre-2.6.39-gnu/drivers/net/sfc/qt202x_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/qt202x_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/qt202x_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/regs.h linux-libre-2.6.39-gnu/drivers/net/sfc/regs.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/regs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/regs.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -2907,6 +2907,12 @@
 #define FRF_CZ_TMFT_SRC_MAC_HI_LBN 44
 #define FRF_CZ_TMFT_SRC_MAC_HI_WIDTH 16
 
+/* TX_PACE_TBL */
+/* Values >20 are documented as reserved, but will result in a queue going
+ * into the fast bin with a pace value of zero. */
+#define FFE_BZ_TX_PACE_OFF 0
+#define FFE_BZ_TX_PACE_RESERVED 21
+
 /* DRIVER_EV */
 /* Sub-fields of an RX flush completion event */
 #define FSF_AZ_DRIVER_EV_RX_FLUSH_FAIL_LBN 12
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/rx.c linux-libre-2.6.39-gnu/drivers/net/sfc/rx.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2011 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
@@ -89,24 +89,37 @@
  */
 #define EFX_RXD_HEAD_ROOM 2
 
-static inline unsigned int efx_rx_buf_offset(struct efx_rx_buffer *buf)
+/* Offset of ethernet header within page */
+static inline unsigned int efx_rx_buf_offset(struct efx_nic *efx,
+					     struct efx_rx_buffer *buf)
 {
 	/* Offset is always within one page, so we don't need to consider
 	 * the page order.
 	 */
-	return (__force unsigned long) buf->data & (PAGE_SIZE - 1);
+	return (((__force unsigned long) buf->dma_addr & (PAGE_SIZE - 1)) +
+		efx->type->rx_buffer_hash_size);
 }
 static inline unsigned int efx_rx_buf_size(struct efx_nic *efx)
 {
 	return PAGE_SIZE << efx->rx_buffer_order;
 }
 
-static inline u32 efx_rx_buf_hash(struct efx_rx_buffer *buf)
+static u8 *efx_rx_buf_eh(struct efx_nic *efx, struct efx_rx_buffer *buf)
+{
+	if (buf->is_page)
+		return page_address(buf->u.page) + efx_rx_buf_offset(efx, buf);
+	else
+		return ((u8 *)buf->u.skb->data +
+			efx->type->rx_buffer_hash_size);
+}
+
+static inline u32 efx_rx_buf_hash(const u8 *eh)
 {
+	/* The ethernet header is always directly after any hash. */
 #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) || NET_IP_ALIGN % 4 == 0
-	return __le32_to_cpup((const __le32 *)(buf->data - 4));
+	return __le32_to_cpup((const __le32 *)(eh - 4));
 #else
-	const u8 *data = (const u8 *)(buf->data - 4);
+	const u8 *data = eh - 4;
 	return ((u32)data[0]       |
 		(u32)data[1] << 8  |
 		(u32)data[2] << 16 |
@@ -129,6 +142,7 @@
 	struct efx_nic *efx = rx_queue->efx;
 	struct net_device *net_dev = efx->net_dev;
 	struct efx_rx_buffer *rx_buf;
+	struct sk_buff *skb;
 	int skb_len = efx->rx_buffer_len;
 	unsigned index, count;
 
@@ -136,24 +150,23 @@
 		index = rx_queue->added_count & rx_queue->ptr_mask;
 		rx_buf = efx_rx_buffer(rx_queue, index);
 
-		rx_buf->skb = netdev_alloc_skb(net_dev, skb_len);
-		if (unlikely(!rx_buf->skb))
+		rx_buf->u.skb = skb = netdev_alloc_skb(net_dev, skb_len);
+		if (unlikely(!skb))
 			return -ENOMEM;
-		rx_buf->page = NULL;
 
 		/* Adjust the SKB for padding and checksum */
-		skb_reserve(rx_buf->skb, NET_IP_ALIGN);
+		skb_reserve(skb, NET_IP_ALIGN);
 		rx_buf->len = skb_len - NET_IP_ALIGN;
-		rx_buf->data = (char *)rx_buf->skb->data;
-		rx_buf->skb->ip_summed = CHECKSUM_UNNECESSARY;
+		rx_buf->is_page = false;
+		skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		rx_buf->dma_addr = pci_map_single(efx->pci_dev,
-						  rx_buf->data, rx_buf->len,
+						  skb->data, rx_buf->len,
 						  PCI_DMA_FROMDEVICE);
 		if (unlikely(pci_dma_mapping_error(efx->pci_dev,
 						   rx_buf->dma_addr))) {
-			dev_kfree_skb_any(rx_buf->skb);
-			rx_buf->skb = NULL;
+			dev_kfree_skb_any(skb);
+			rx_buf->u.skb = NULL;
 			return -EIO;
 		}
 
@@ -211,10 +224,9 @@
 		index = rx_queue->added_count & rx_queue->ptr_mask;
 		rx_buf = efx_rx_buffer(rx_queue, index);
 		rx_buf->dma_addr = dma_addr + EFX_PAGE_IP_ALIGN;
-		rx_buf->skb = NULL;
-		rx_buf->page = page;
-		rx_buf->data = page_addr + EFX_PAGE_IP_ALIGN;
+		rx_buf->u.page = page;
 		rx_buf->len = efx->rx_buffer_len - EFX_PAGE_IP_ALIGN;
+		rx_buf->is_page = true;
 		++rx_queue->added_count;
 		++rx_queue->alloc_page_count;
 		++state->refcnt;
@@ -235,19 +247,17 @@
 static void efx_unmap_rx_buffer(struct efx_nic *efx,
 				struct efx_rx_buffer *rx_buf)
 {
-	if (rx_buf->page) {
+	if (rx_buf->is_page && rx_buf->u.page) {
 		struct efx_rx_page_state *state;
 
-		EFX_BUG_ON_PARANOID(rx_buf->skb);
-
-		state = page_address(rx_buf->page);
+		state = page_address(rx_buf->u.page);
 		if (--state->refcnt == 0) {
 			pci_unmap_page(efx->pci_dev,
 				       state->dma_addr,
 				       efx_rx_buf_size(efx),
 				       PCI_DMA_FROMDEVICE);
 		}
-	} else if (likely(rx_buf->skb)) {
+	} else if (!rx_buf->is_page && rx_buf->u.skb) {
 		pci_unmap_single(efx->pci_dev, rx_buf->dma_addr,
 				 rx_buf->len, PCI_DMA_FROMDEVICE);
 	}
@@ -256,12 +266,12 @@
 static void efx_free_rx_buffer(struct efx_nic *efx,
 			       struct efx_rx_buffer *rx_buf)
 {
-	if (rx_buf->page) {
-		__free_pages(rx_buf->page, efx->rx_buffer_order);
-		rx_buf->page = NULL;
-	} else if (likely(rx_buf->skb)) {
-		dev_kfree_skb_any(rx_buf->skb);
-		rx_buf->skb = NULL;
+	if (rx_buf->is_page && rx_buf->u.page) {
+		__free_pages(rx_buf->u.page, efx->rx_buffer_order);
+		rx_buf->u.page = NULL;
+	} else if (!rx_buf->is_page && rx_buf->u.skb) {
+		dev_kfree_skb_any(rx_buf->u.skb);
+		rx_buf->u.skb = NULL;
 	}
 }
 
@@ -277,7 +287,7 @@
 static void efx_resurrect_rx_buffer(struct efx_rx_queue *rx_queue,
 				    struct efx_rx_buffer *rx_buf)
 {
-	struct efx_rx_page_state *state = page_address(rx_buf->page);
+	struct efx_rx_page_state *state = page_address(rx_buf->u.page);
 	struct efx_rx_buffer *new_buf;
 	unsigned fill_level, index;
 
@@ -292,16 +302,14 @@
 	}
 
 	++state->refcnt;
-	get_page(rx_buf->page);
+	get_page(rx_buf->u.page);
 
 	index = rx_queue->added_count & rx_queue->ptr_mask;
 	new_buf = efx_rx_buffer(rx_queue, index);
 	new_buf->dma_addr = rx_buf->dma_addr ^ (PAGE_SIZE >> 1);
-	new_buf->skb = NULL;
-	new_buf->page = rx_buf->page;
-	new_buf->data = (void *)
-		((__force unsigned long)rx_buf->data ^ (PAGE_SIZE >> 1));
+	new_buf->u.page = rx_buf->u.page;
 	new_buf->len = rx_buf->len;
+	new_buf->is_page = true;
 	++rx_queue->added_count;
 }
 
@@ -315,16 +323,15 @@
 	struct efx_rx_buffer *new_buf;
 	unsigned index;
 
-	if (rx_buf->page != NULL && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
-	    page_count(rx_buf->page) == 1)
+	if (rx_buf->is_page && efx->rx_buffer_len <= EFX_RX_HALF_PAGE &&
+	    page_count(rx_buf->u.page) == 1)
 		efx_resurrect_rx_buffer(rx_queue, rx_buf);
 
 	index = rx_queue->added_count & rx_queue->ptr_mask;
 	new_buf = efx_rx_buffer(rx_queue, index);
 
 	memcpy(new_buf, rx_buf, sizeof(*new_buf));
-	rx_buf->page = NULL;
-	rx_buf->skb = NULL;
+	rx_buf->u.page = NULL;
 	++rx_queue->added_count;
 }
 
@@ -428,7 +435,7 @@
 		 * data at the end of the skb will be trashed. So
 		 * we have no choice but to leak the fragment.
 		 */
-		*leak_packet = (rx_buf->skb != NULL);
+		*leak_packet = !rx_buf->is_page;
 		efx_schedule_reset(efx, RESET_TYPE_RX_RECOVERY);
 	} else {
 		if (net_ratelimit())
@@ -448,19 +455,18 @@
  */
 static void efx_rx_packet_gro(struct efx_channel *channel,
 			      struct efx_rx_buffer *rx_buf,
-			      bool checksummed)
+			      const u8 *eh, bool checksummed)
 {
 	struct napi_struct *napi = &channel->napi_str;
 	gro_result_t gro_result;
 
 	/* Pass the skb/page into the GRO engine */
-	if (rx_buf->page) {
+	if (rx_buf->is_page) {
 		struct efx_nic *efx = channel->efx;
-		struct page *page = rx_buf->page;
+		struct page *page = rx_buf->u.page;
 		struct sk_buff *skb;
 
-		EFX_BUG_ON_PARANOID(rx_buf->skb);
-		rx_buf->page = NULL;
+		rx_buf->u.page = NULL;
 
 		skb = napi_get_frags(napi);
 		if (!skb) {
@@ -469,11 +475,11 @@
 		}
 
 		if (efx->net_dev->features & NETIF_F_RXHASH)
-			skb->rxhash = efx_rx_buf_hash(rx_buf);
+			skb->rxhash = efx_rx_buf_hash(eh);
 
 		skb_shinfo(skb)->frags[0].page = page;
 		skb_shinfo(skb)->frags[0].page_offset =
-			efx_rx_buf_offset(rx_buf);
+			efx_rx_buf_offset(efx, rx_buf);
 		skb_shinfo(skb)->frags[0].size = rx_buf->len;
 		skb_shinfo(skb)->nr_frags = 1;
 
@@ -487,11 +493,10 @@
 
 		gro_result = napi_gro_frags(napi);
 	} else {
-		struct sk_buff *skb = rx_buf->skb;
+		struct sk_buff *skb = rx_buf->u.skb;
 
-		EFX_BUG_ON_PARANOID(!skb);
 		EFX_BUG_ON_PARANOID(!checksummed);
-		rx_buf->skb = NULL;
+		rx_buf->u.skb = NULL;
 
 		gro_result = napi_gro_receive(napi, skb);
 	}
@@ -513,9 +518,6 @@
 	bool leak_packet = false;
 
 	rx_buf = efx_rx_buffer(rx_queue, index);
-	EFX_BUG_ON_PARANOID(!rx_buf->data);
-	EFX_BUG_ON_PARANOID(rx_buf->skb && rx_buf->page);
-	EFX_BUG_ON_PARANOID(!(rx_buf->skb || rx_buf->page));
 
 	/* This allows the refill path to post another buffer.
 	 * EFX_RXD_HEAD_ROOM ensures that the slot we are using
@@ -554,12 +556,12 @@
 	/* Prefetch nice and early so data will (hopefully) be in cache by
 	 * the time we look at it.
 	 */
-	prefetch(rx_buf->data);
+	prefetch(efx_rx_buf_eh(efx, rx_buf));
 
 	/* Pipeline receives so that we give time for packet headers to be
 	 * prefetched into cache.
 	 */
-	rx_buf->len = len;
+	rx_buf->len = len - efx->type->rx_buffer_hash_size;
 out:
 	if (channel->rx_pkt)
 		__efx_rx_packet(channel,
@@ -574,45 +576,43 @@
 {
 	struct efx_nic *efx = channel->efx;
 	struct sk_buff *skb;
-
-	rx_buf->data += efx->type->rx_buffer_hash_size;
-	rx_buf->len -= efx->type->rx_buffer_hash_size;
+	u8 *eh = efx_rx_buf_eh(efx, rx_buf);
 
 	/* If we're in loopback test, then pass the packet directly to the
 	 * loopback layer, and free the rx_buf here
 	 */
 	if (unlikely(efx->loopback_selftest)) {
-		efx_loopback_rx_packet(efx, rx_buf->data, rx_buf->len);
+		efx_loopback_rx_packet(efx, eh, rx_buf->len);
 		efx_free_rx_buffer(efx, rx_buf);
 		return;
 	}
 
-	if (rx_buf->skb) {
-		prefetch(skb_shinfo(rx_buf->skb));
+	if (!rx_buf->is_page) {
+		skb = rx_buf->u.skb;
 
-		skb_reserve(rx_buf->skb, efx->type->rx_buffer_hash_size);
-		skb_put(rx_buf->skb, rx_buf->len);
+		prefetch(skb_shinfo(skb));
+
+		skb_reserve(skb, efx->type->rx_buffer_hash_size);
+		skb_put(skb, rx_buf->len);
 
 		if (efx->net_dev->features & NETIF_F_RXHASH)
-			rx_buf->skb->rxhash = efx_rx_buf_hash(rx_buf);
+			skb->rxhash = efx_rx_buf_hash(eh);
 
 		/* Move past the ethernet header. rx_buf->data still points
 		 * at the ethernet header */
-		rx_buf->skb->protocol = eth_type_trans(rx_buf->skb,
-						       efx->net_dev);
+		skb->protocol = eth_type_trans(skb, efx->net_dev);
 
-		skb_record_rx_queue(rx_buf->skb, channel->channel);
+		skb_record_rx_queue(skb, channel->channel);
 	}
 
-	if (likely(checksummed || rx_buf->page)) {
-		efx_rx_packet_gro(channel, rx_buf, checksummed);
+	if (likely(checksummed || rx_buf->is_page)) {
+		efx_rx_packet_gro(channel, rx_buf, eh, checksummed);
 		return;
 	}
 
 	/* We now own the SKB */
-	skb = rx_buf->skb;
-	rx_buf->skb = NULL;
-	EFX_BUG_ON_PARANOID(!skb);
+	skb = rx_buf->u.skb;
+	rx_buf->u.skb = NULL;
 
 	/* Set the SKB flags */
 	skb_checksum_none_assert(skb);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/selftest.c linux-libre-2.6.39-gnu/drivers/net/sfc/selftest.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/selftest.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/selftest.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -131,8 +131,6 @@
 static int efx_test_interrupts(struct efx_nic *efx,
 			       struct efx_self_tests *tests)
 {
-	struct efx_channel *channel;
-
 	netif_dbg(efx, drv, efx->net_dev, "testing interrupts\n");
 	tests->interrupt = -1;
 
@@ -140,15 +138,6 @@
 	efx->last_irq_cpu = -1;
 	smp_wmb();
 
-	/* ACK each interrupting event queue. Receiving an interrupt due to
-	 * traffic before a test event is raised is considered a pass */
-	efx_for_each_channel(channel, efx) {
-		if (channel->work_pending)
-			efx_process_channel_now(channel);
-		if (efx->last_irq_cpu >= 0)
-			goto success;
-	}
-
 	efx_nic_generate_interrupt(efx);
 
 	/* Wait for arrival of test interrupt. */
@@ -173,13 +162,13 @@
 			       struct efx_self_tests *tests)
 {
 	struct efx_nic *efx = channel->efx;
-	unsigned int magic_count, count;
+	unsigned int read_ptr, count;
 
 	tests->eventq_dma[channel->channel] = -1;
 	tests->eventq_int[channel->channel] = -1;
 	tests->eventq_poll[channel->channel] = -1;
 
-	magic_count = channel->magic_count;
+	read_ptr = channel->eventq_read_ptr;
 	channel->efx->last_irq_cpu = -1;
 	smp_wmb();
 
@@ -190,10 +179,7 @@
 	do {
 		schedule_timeout_uninterruptible(HZ / 100);
 
-		if (channel->work_pending)
-			efx_process_channel_now(channel);
-
-		if (channel->magic_count != magic_count)
+		if (ACCESS_ONCE(channel->eventq_read_ptr) != read_ptr)
 			goto eventq_ok;
 	} while (++count < 2);
 
@@ -211,8 +197,7 @@
 	}
 
 	/* Check to see if event was received even if interrupt wasn't */
-	efx_process_channel_now(channel);
-	if (channel->magic_count != magic_count) {
+	if (efx_nic_event_present(channel)) {
 		netif_err(efx, drv, efx->net_dev,
 			  "channel %d event was generated, but "
 			  "failed to trigger an interrupt\n", channel->channel);
@@ -644,7 +629,7 @@
 			goto out;
 		}
 
-		/* Test both types of TX queue */
+		/* Test all enabled types of TX queue */
 		efx_for_each_channel_tx_queue(tx_queue, channel) {
 			state->offload_csum = (tx_queue->queue &
 					       EFX_TXQ_TYPE_OFFLOAD);
@@ -770,6 +755,8 @@
 	__efx_reconfigure_port(efx);
 	mutex_unlock(&efx->mac_lock);
 
+	netif_tx_wake_all_queues(efx->net_dev);
+
 	return rc_test;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/selftest.h linux-libre-2.6.39-gnu/drivers/net/sfc/selftest.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/selftest.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/selftest.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2008 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/siena.c linux-libre-2.6.39-gnu/drivers/net/sfc/siena.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/siena.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/siena.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -220,19 +220,26 @@
 	efx_reado(efx, &reg, FR_AZ_CS_DEBUG);
 	efx->net_dev->dev_id = EFX_OWORD_FIELD(reg, FRF_CZ_CS_PORT_NUM) - 1;
 
+	/* Initialise MCDI */
+	nic_data->mcdi_smem = ioremap_nocache(efx->membase_phys +
+					      FR_CZ_MC_TREG_SMEM,
+					      FR_CZ_MC_TREG_SMEM_STEP *
+					      FR_CZ_MC_TREG_SMEM_ROWS);
+	if (!nic_data->mcdi_smem) {
+		netif_err(efx, probe, efx->net_dev,
+			  "could not map MCDI at %llx+%x\n",
+			  (unsigned long long)efx->membase_phys +
+			  FR_CZ_MC_TREG_SMEM,
+			  FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS);
+		rc = -ENOMEM;
+		goto fail1;
+	}
 	efx_mcdi_init(efx);
 
 	/* Recover from a failed assertion before probing */
 	rc = efx_mcdi_handle_assertion(efx);
 	if (rc)
-		goto fail1;
-
-	rc = efx_mcdi_fwver(efx, &nic_data->fw_version, &nic_data->fw_build);
-	if (rc) {
-		netif_err(efx, probe, efx->net_dev,
-			  "Failed to read MCPU firmware version - rc %d\n", rc);
-		goto fail1; /* MCPU absent? */
-	}
+		goto fail2;
 
 	/* Let the BMC know that the driver is now in charge of link and
 	 * filter settings. We must do this before we reset the NIC */
@@ -287,6 +294,7 @@
 fail3:
 	efx_mcdi_drv_attach(efx, false, NULL);
 fail2:
+	iounmap(nic_data->mcdi_smem);
 fail1:
 	kfree(efx->nic_data);
 	return rc;
@@ -348,11 +356,6 @@
 	       FRF_CZ_RX_RSS_IPV6_TKEY_HI_WIDTH / 8);
 	efx_writeo(efx, &temp, FR_CZ_RX_RSS_IPV6_REG3);
 
-	if (efx_nic_rx_xoff_thresh >= 0 || efx_nic_rx_xon_thresh >= 0)
-		/* No MCDI operation has been defined to set thresholds */
-		netif_err(efx, hw, efx->net_dev,
-			  "ignoring RX flow control thresholds\n");
-
 	/* Enable event logging */
 	rc = efx_mcdi_log_ctrl(efx, true, false, 0);
 	if (rc)
@@ -371,6 +374,8 @@
 
 static void siena_remove_nic(struct efx_nic *efx)
 {
+	struct siena_nic_data *nic_data = efx->nic_data;
+
 	efx_nic_free_buffer(efx, &efx->irq_status);
 
 	siena_reset_hw(efx, RESET_TYPE_ALL);
@@ -380,7 +385,8 @@
 		efx_mcdi_drv_attach(efx, false, NULL);
 
 	/* Tear down the private nic state */
-	kfree(efx->nic_data);
+	iounmap(nic_data->mcdi_smem);
+	kfree(nic_data);
 	efx->nic_data = NULL;
 }
 
@@ -514,16 +520,6 @@
 	efx_mcdi_mac_stats(efx, efx->stats_buffer.dma_addr, 0, 0, 0);
 }
 
-void siena_print_fwver(struct efx_nic *efx, char *buf, size_t len)
-{
-	struct siena_nic_data *nic_data = efx->nic_data;
-	snprintf(buf, len, "%u.%u.%u.%u",
-		 (unsigned int)(nic_data->fw_version >> 48),
-		 (unsigned int)(nic_data->fw_version >> 32 & 0xffff),
-		 (unsigned int)(nic_data->fw_version >> 16 & 0xffff),
-		 (unsigned int)(nic_data->fw_version & 0xffff));
-}
-
 /**************************************************************************
  *
  * Wake on LAN
@@ -628,8 +624,7 @@
 	.default_mac_ops = &efx_mcdi_mac_operations,
 
 	.revision = EFX_REV_SIENA_A0,
-	.mem_map_size = (FR_CZ_MC_TREG_SMEM +
-			 FR_CZ_MC_TREG_SMEM_STEP * FR_CZ_MC_TREG_SMEM_ROWS),
+	.mem_map_size = FR_CZ_MC_TREG_SMEM, /* MC_TREG_SMEM mapped separately */
 	.txd_ptr_tbl_base = FR_BZ_TX_DESC_PTR_TBL,
 	.rxd_ptr_tbl_base = FR_BZ_RX_DESC_PTR_TBL,
 	.buf_tbl_base = FR_BZ_BUF_FULL_TBL,
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/spi.h linux-libre-2.6.39-gnu/drivers/net/sfc/spi.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/spi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/spi.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005 Fen Systems Ltd.
- * Copyright 2006 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/tenxpress.c linux-libre-2.6.39-gnu/drivers/net/sfc/tenxpress.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/tenxpress.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/tenxpress.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2007-2009 Solarflare Communications Inc.
+ * Copyright 2007-2011 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
@@ -196,7 +196,7 @@
 		if (rc < 0)
 			return rc;
 
-		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS, 0);
+		rc = efx_mdio_check_mmds(efx, TENXPRESS_REQUIRED_DEVS);
 		if (rc < 0)
 			return rc;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/tx.c linux-libre-2.6.39-gnu/drivers/net/sfc/tx.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
  * Copyright 2005-2006 Fen Systems Ltd.
- * Copyright 2005-2009 Solarflare Communications Inc.
+ * Copyright 2005-2010 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
@@ -336,17 +336,91 @@
 {
 	struct efx_nic *efx = netdev_priv(net_dev);
 	struct efx_tx_queue *tx_queue;
+	unsigned index, type;
 
 	if (unlikely(efx->port_inhibited))
 		return NETDEV_TX_BUSY;
 
-	tx_queue = efx_get_tx_queue(efx, skb_get_queue_mapping(skb),
-				    skb->ip_summed == CHECKSUM_PARTIAL ?
-				    EFX_TXQ_TYPE_OFFLOAD : 0);
+	index = skb_get_queue_mapping(skb);
+	type = skb->ip_summed == CHECKSUM_PARTIAL ? EFX_TXQ_TYPE_OFFLOAD : 0;
+	if (index >= efx->n_tx_channels) {
+		index -= efx->n_tx_channels;
+		type |= EFX_TXQ_TYPE_HIGHPRI;
+	}
+	tx_queue = efx_get_tx_queue(efx, index, type);
 
 	return efx_enqueue_skb(tx_queue, skb);
 }
 
+void efx_init_tx_queue_core_txq(struct efx_tx_queue *tx_queue)
+{
+	struct efx_nic *efx = tx_queue->efx;
+
+	/* Must be inverse of queue lookup in efx_hard_start_xmit() */
+	tx_queue->core_txq =
+		netdev_get_tx_queue(efx->net_dev,
+				    tx_queue->queue / EFX_TXQ_TYPES +
+				    ((tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI) ?
+				     efx->n_tx_channels : 0));
+}
+
+int efx_setup_tc(struct net_device *net_dev, u8 num_tc)
+{
+	struct efx_nic *efx = netdev_priv(net_dev);
+	struct efx_channel *channel;
+	struct efx_tx_queue *tx_queue;
+	unsigned tc;
+	int rc;
+
+	if (efx_nic_rev(efx) < EFX_REV_FALCON_B0 || num_tc > EFX_MAX_TX_TC)
+		return -EINVAL;
+
+	if (num_tc == net_dev->num_tc)
+		return 0;
+
+	for (tc = 0; tc < num_tc; tc++) {
+		net_dev->tc_to_txq[tc].offset = tc * efx->n_tx_channels;
+		net_dev->tc_to_txq[tc].count = efx->n_tx_channels;
+	}
+
+	if (num_tc > net_dev->num_tc) {
+		/* Initialise high-priority queues as necessary */
+		efx_for_each_channel(channel, efx) {
+			efx_for_each_possible_channel_tx_queue(tx_queue,
+							       channel) {
+				if (!(tx_queue->queue & EFX_TXQ_TYPE_HIGHPRI))
+					continue;
+				if (!tx_queue->buffer) {
+					rc = efx_probe_tx_queue(tx_queue);
+					if (rc)
+						return rc;
+				}
+				if (!tx_queue->initialised)
+					efx_init_tx_queue(tx_queue);
+				efx_init_tx_queue_core_txq(tx_queue);
+			}
+		}
+	} else {
+		/* Reduce number of classes before number of queues */
+		net_dev->num_tc = num_tc;
+	}
+
+	rc = netif_set_real_num_tx_queues(net_dev,
+					  max_t(int, num_tc, 1) *
+					  efx->n_tx_channels);
+	if (rc)
+		return rc;
+
+	/* Do not destroy high-priority queues when they become
+	 * unused.  We would have to flush them first, and it is
+	 * fairly difficult to flush a subset of TX queues.  Leave
+	 * it to efx_fini_channels().
+	 */
+
+	net_dev->num_tc = num_tc;
+	return 0;
+}
+
 void efx_xmit_done(struct efx_tx_queue *tx_queue, unsigned int index)
 {
 	unsigned fill_level;
@@ -361,7 +435,8 @@
 	 * queue state. */
 	smp_mb();
 	if (unlikely(netif_tx_queue_stopped(tx_queue->core_txq)) &&
-	    likely(efx->port_enabled)) {
+	    likely(efx->port_enabled) &&
+	    likely(!efx->port_inhibited)) {
 		fill_level = tx_queue->insert_count - tx_queue->read_count;
 		if (fill_level < EFX_TXQ_THRESHOLD(efx)) {
 			EFX_BUG_ON_PARANOID(!efx_dev_registered(efx));
@@ -430,6 +505,8 @@
 
 	/* Set up TX descriptor ring */
 	efx_nic_init_tx(tx_queue);
+
+	tx_queue->initialised = true;
 }
 
 void efx_release_tx_buffers(struct efx_tx_queue *tx_queue)
@@ -452,9 +529,14 @@
 
 void efx_fini_tx_queue(struct efx_tx_queue *tx_queue)
 {
+	if (!tx_queue->initialised)
+		return;
+
 	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
 		  "shutting down TX queue %d\n", tx_queue->queue);
 
+	tx_queue->initialised = false;
+
 	/* Flush TX queue, remove descriptor ring */
 	efx_nic_fini_tx(tx_queue);
 
@@ -466,6 +548,9 @@
 
 void efx_remove_tx_queue(struct efx_tx_queue *tx_queue)
 {
+	if (!tx_queue->buffer)
+		return;
+
 	netif_dbg(tx_queue->efx, drv, tx_queue->efx->net_dev,
 		  "destroying TX queue %d\n", tx_queue->queue);
 	efx_nic_remove_tx(tx_queue);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/txc43128_phy.c linux-libre-2.6.39-gnu/drivers/net/sfc/txc43128_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/sfc/txc43128_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/txc43128_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2010 Solarflare Communications Inc.
+ * Copyright 2006-2011 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
@@ -193,7 +193,7 @@
 		goto fail;
 
 	/* Check that all the MMDs we expect are present and responding. */
-	rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS, 0);
+	rc = efx_mdio_check_mmds(efx, TXC_REQUIRED_DEVS);
 	if (rc < 0)
 		goto fail;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/sfc/workarounds.h linux-libre-2.6.39-gnu/drivers/net/sfc/workarounds.h
--- linux-libre-2.6.38-gnu/drivers/net/sfc/workarounds.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sfc/workarounds.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /****************************************************************************
  * Driver for Solarflare Solarstorm network controllers and boards
- * Copyright 2006-2009 Solarflare Communications Inc.
+ * Copyright 2006-2010 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
@@ -38,6 +38,8 @@
 #define EFX_WORKAROUND_15783 EFX_WORKAROUND_ALWAYS
 /* Legacy interrupt storm when interrupt fifo fills */
 #define EFX_WORKAROUND_17213 EFX_WORKAROUND_SIENA
+/* Write combining and sriov=enabled are incompatible */
+#define EFX_WORKAROUND_22643 EFX_WORKAROUND_SIENA
 
 /* Spurious parity errors in TSORT buffers */
 #define EFX_WORKAROUND_5129 EFX_WORKAROUND_FALCON_A
diff -druN linux-libre-2.6.38-gnu/drivers/net/sgiseeq.c linux-libre-2.6.39-gnu/drivers/net/sgiseeq.c
--- linux-libre-2.6.38-gnu/drivers/net/sgiseeq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sgiseeq.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
  * with that in mind, I've decided to make this driver look completely like a
  * stupid Lance from a driver architecture perspective.  Only difference is that
  * here our "ring buffer" looks and acts like a real Lance one does but is
- * layed out like how the HPC DMA and the Seeq want it to.  You'd be surprised
+ * laid out like how the HPC DMA and the Seeq want it to.  You'd be surprised
  * how a stupid idea like this can pay off in performance, not to mention
  * making this driver 2,000 times easier to write. ;-)
  */
@@ -77,7 +77,7 @@
 };
 
 /*
- * Warning: This structure is layed out in a certain way because HPC dma
+ * Warning: This structure is laid out in a certain way because HPC dma
  *          descriptors must be 8-byte aligned.  So don't touch this without
  *          some care.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sh_eth.c linux-libre-2.6.39-gnu/drivers/net/sh_eth.c
--- linux-libre-2.6.38-gnu/drivers/net/sh_eth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sh_eth.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,35 +32,40 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/ethtool.h>
 #include <asm/cacheflush.h>
 
 #include "sh_eth.h"
 
+#define SH_ETH_DEF_MSG_ENABLE \
+		(NETIF_MSG_LINK	| \
+		NETIF_MSG_TIMER	| \
+		NETIF_MSG_RX_ERR| \
+		NETIF_MSG_TX_ERR)
+
 /* 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 */
-		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
 	else		/* Half */
-		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, 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 */
-		writel(readl(ioaddr + ECMR) & ~ECMR_RTM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_RTM, ECMR);
 		break;
 	case 100:/* 100BASE */
-		writel(readl(ioaddr + ECMR) | ECMR_RTM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_RTM, ECMR);
 		break;
 	default:
 		break;
@@ -89,29 +94,28 @@
 	.rpadir_value	= 0x00020000, /* NET_IP_ALIGN assumed to be 2 */
 };
 #elif defined(CONFIG_CPU_SUBTYPE_SH7757)
-#define SH_ETH_RESET_DEFAULT	1
+#define SH_ETH_HAS_BOTH_MODULES	1
+#define SH_ETH_HAS_TSU	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 */
-		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
 	else		/* Half */
-		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, 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 */
-		writel(0, ioaddr + RTRATE);
+		sh_eth_write(ndev, 0, RTRATE);
 		break;
 	case 100:/* 100BASE */
-		writel(1, ioaddr + RTRATE);
+		sh_eth_write(ndev, 1, RTRATE);
 		break;
 	default:
 		break;
@@ -138,24 +142,154 @@
 	.no_ade		= 1,
 };
 
+#define SH_GIGA_ETH_BASE	0xfee00000
+#define GIGA_MALR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c8)
+#define GIGA_MAHR(port)		(SH_GIGA_ETH_BASE + 0x800 * (port) + 0x05c0)
+static void sh_eth_chip_reset_giga(struct net_device *ndev)
+{
+	int i;
+	unsigned long mahr[2], malr[2];
+
+	/* save MAHR and MALR */
+	for (i = 0; i < 2; i++) {
+		malr[i] = readl(GIGA_MALR(i));
+		mahr[i] = readl(GIGA_MAHR(i));
+	}
+
+	/* reset device */
+	writel(ARSTR_ARSTR, SH_GIGA_ETH_BASE + 0x1800);
+	mdelay(1);
+
+	/* restore MAHR and MALR */
+	for (i = 0; i < 2; i++) {
+		writel(malr[i], GIGA_MALR(i));
+		writel(mahr[i], GIGA_MAHR(i));
+	}
+}
+
+static int sh_eth_is_gether(struct sh_eth_private *mdp);
+static void sh_eth_reset(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int cnt = 100;
+
+	if (sh_eth_is_gether(mdp)) {
+		sh_eth_write(ndev, 0x03, EDSR);
+		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER,
+				EDMR);
+		while (cnt > 0) {
+			if (!(sh_eth_read(ndev, EDMR) & 0x3))
+				break;
+			mdelay(1);
+			cnt--;
+		}
+		if (cnt < 0)
+			printk(KERN_ERR "Device reset fail\n");
+
+		/* Table Init */
+		sh_eth_write(ndev, 0x0, TDLAR);
+		sh_eth_write(ndev, 0x0, TDFAR);
+		sh_eth_write(ndev, 0x0, TDFXR);
+		sh_eth_write(ndev, 0x0, TDFFR);
+		sh_eth_write(ndev, 0x0, RDLAR);
+		sh_eth_write(ndev, 0x0, RDFAR);
+		sh_eth_write(ndev, 0x0, RDFXR);
+		sh_eth_write(ndev, 0x0, RDFFR);
+	} else {
+		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER,
+				EDMR);
+		mdelay(3);
+		sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER,
+				EDMR);
+	}
+}
+
+static void sh_eth_set_duplex_giga(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	if (mdp->duplex) /* Full */
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
+	else		/* Half */
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, ECMR);
+}
+
+static void sh_eth_set_rate_giga(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	switch (mdp->speed) {
+	case 10: /* 10BASE */
+		sh_eth_write(ndev, 0x00000000, GECMR);
+		break;
+	case 100:/* 100BASE */
+		sh_eth_write(ndev, 0x00000010, GECMR);
+		break;
+	case 1000: /* 1000BASE */
+		sh_eth_write(ndev, 0x00000020, GECMR);
+		break;
+	default:
+		break;
+	}
+}
+
+/* SH7757(GETHERC) */
+static struct sh_eth_cpu_data sh_eth_my_cpu_data_giga = {
+	.chip_reset	= sh_eth_chip_reset_giga,
+	.set_duplex	= sh_eth_set_duplex_giga,
+	.set_rate	= sh_eth_set_rate_giga,
+
+	.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,
+	.fdr_value	= 0x0000072f,
+	.rmcr_value	= 0x00000001,
+
+	.apr		= 1,
+	.mpr		= 1,
+	.tpauser	= 1,
+	.bculr		= 1,
+	.hw_swap	= 1,
+	.rpadir		= 1,
+	.rpadir_value   = 2 << 16,
+	.no_trimd	= 1,
+	.no_ade		= 1,
+};
+
+static struct sh_eth_cpu_data *sh_eth_get_cpu_data(struct sh_eth_private *mdp)
+{
+	if (sh_eth_is_gether(mdp))
+		return &sh_eth_my_cpu_data_giga;
+	else
+		return &sh_eth_my_cpu_data;
+}
+
 #elif defined(CONFIG_CPU_SUBTYPE_SH7763)
 #define SH_ETH_HAS_TSU	1
 static void sh_eth_chip_reset(struct net_device *ndev)
 {
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
 	/* reset device */
-	writel(ARSTR_ARSTR, ARSTR);
+	sh_eth_tsu_write(mdp, ARSTR_ARSTR, ARSTR);
 	mdelay(1);
 }
 
 static void sh_eth_reset(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
 	int cnt = 100;
 
-	writel(EDSR_ENALL, ioaddr + EDSR);
-	writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	sh_eth_write(ndev, EDSR_ENALL, EDSR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_GETHER, EDMR);
 	while (cnt > 0) {
-		if (!(readl(ioaddr + EDMR) & 0x3))
+		if (!(sh_eth_read(ndev, EDMR) & 0x3))
 			break;
 		mdelay(1);
 		cnt--;
@@ -164,41 +298,39 @@
 		printk(KERN_ERR "Device reset fail\n");
 
 	/* Table Init */
-	writel(0x0, ioaddr + TDLAR);
-	writel(0x0, ioaddr + TDFAR);
-	writel(0x0, ioaddr + TDFXR);
-	writel(0x0, ioaddr + TDFFR);
-	writel(0x0, ioaddr + RDLAR);
-	writel(0x0, ioaddr + RDFAR);
-	writel(0x0, ioaddr + RDFXR);
-	writel(0x0, ioaddr + RDFFR);
+	sh_eth_write(ndev, 0x0, TDLAR);
+	sh_eth_write(ndev, 0x0, TDFAR);
+	sh_eth_write(ndev, 0x0, TDFXR);
+	sh_eth_write(ndev, 0x0, TDFFR);
+	sh_eth_write(ndev, 0x0, RDLAR);
+	sh_eth_write(ndev, 0x0, RDFAR);
+	sh_eth_write(ndev, 0x0, RDFXR);
+	sh_eth_write(ndev, 0x0, 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 */
-		writel(readl(ioaddr + ECMR) | ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) | ECMR_DM, ECMR);
 	else		/* Half */
-		writel(readl(ioaddr + ECMR) & ~ECMR_DM, ioaddr + ECMR);
+		sh_eth_write(ndev, sh_eth_read(ndev, ECMR) & ~ECMR_DM, 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 */
-		writel(GECMR_10, ioaddr + GECMR);
+		sh_eth_write(ndev, GECMR_10, GECMR);
 		break;
 	case 100:/* 100BASE */
-		writel(GECMR_100, ioaddr + GECMR);
+		sh_eth_write(ndev, GECMR_100, GECMR);
 		break;
 	case 1000: /* 1000BASE */
-		writel(GECMR_1000, ioaddr + GECMR);
+		sh_eth_write(ndev, GECMR_1000, GECMR);
 		break;
 	default:
 		break;
@@ -229,6 +361,7 @@
 	.hw_swap	= 1,
 	.no_trimd	= 1,
 	.no_ade		= 1,
+	.tsu		= 1,
 };
 
 #elif defined(CONFIG_CPU_SUBTYPE_SH7619)
@@ -246,6 +379,7 @@
 #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,
+	.tsu		= 1,
 };
 #endif
 
@@ -281,11 +415,9 @@
 /* Chip Reset */
 static void sh_eth_reset(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
-
-	writel(readl(ioaddr + EDMR) | EDMR_SRST, ioaddr + EDMR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) | EDMR_SRST_ETHER, EDMR);
 	mdelay(3);
-	writel(readl(ioaddr + EDMR) & ~EDMR_SRST, ioaddr + EDMR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EDMR) & ~EDMR_SRST_ETHER, EDMR);
 }
 #endif
 
@@ -334,13 +466,11 @@
  */
 static void update_mac_address(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
-
-	writel((ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
-		  (ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]),
-		  ioaddr + MAHR);
-	writel((ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]),
-		  ioaddr + MALR);
+	sh_eth_write(ndev,
+		(ndev->dev_addr[0] << 24) | (ndev->dev_addr[1] << 16) |
+		(ndev->dev_addr[2] << 8) | (ndev->dev_addr[3]), MAHR);
+	sh_eth_write(ndev,
+		(ndev->dev_addr[4] << 8) | (ndev->dev_addr[5]), MALR);
 }
 
 /*
@@ -353,21 +483,36 @@
  */
 static void read_mac_address(struct net_device *ndev, unsigned char *mac)
 {
-	u32 ioaddr = ndev->base_addr;
-
 	if (mac[0] || mac[1] || mac[2] || mac[3] || mac[4] || mac[5]) {
 		memcpy(ndev->dev_addr, mac, 6);
 	} else {
-		ndev->dev_addr[0] = (readl(ioaddr + MAHR) >> 24);
-		ndev->dev_addr[1] = (readl(ioaddr + MAHR) >> 16) & 0xFF;
-		ndev->dev_addr[2] = (readl(ioaddr + MAHR) >> 8) & 0xFF;
-		ndev->dev_addr[3] = (readl(ioaddr + MAHR) & 0xFF);
-		ndev->dev_addr[4] = (readl(ioaddr + MALR) >> 8) & 0xFF;
-		ndev->dev_addr[5] = (readl(ioaddr + MALR) & 0xFF);
+		ndev->dev_addr[0] = (sh_eth_read(ndev, MAHR) >> 24);
+		ndev->dev_addr[1] = (sh_eth_read(ndev, MAHR) >> 16) & 0xFF;
+		ndev->dev_addr[2] = (sh_eth_read(ndev, MAHR) >> 8) & 0xFF;
+		ndev->dev_addr[3] = (sh_eth_read(ndev, MAHR) & 0xFF);
+		ndev->dev_addr[4] = (sh_eth_read(ndev, MALR) >> 8) & 0xFF;
+		ndev->dev_addr[5] = (sh_eth_read(ndev, MALR) & 0xFF);
 	}
 }
 
+static int sh_eth_is_gether(struct sh_eth_private *mdp)
+{
+	if (mdp->reg_offset == sh_eth_offset_gigabit)
+		return 1;
+	else
+		return 0;
+}
+
+static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
+{
+	if (sh_eth_is_gether(mdp))
+		return EDTRR_TRNS_GETHER;
+	else
+		return EDTRR_TRNS_ETHER;
+}
+
 struct bb_info {
+	void (*set_gate)(unsigned long addr);
 	struct mdiobb_ctrl ctrl;
 	u32 addr;
 	u32 mmd_msk;/* MMD */
@@ -398,6 +543,10 @@
 static void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	if (bit)
 		bb_set(bitbang->addr, bitbang->mmd_msk);
 	else
@@ -409,6 +558,9 @@
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
 
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	if (bit)
 		bb_set(bitbang->addr, bitbang->mdo_msk);
 	else
@@ -419,6 +571,10 @@
 static int sh_get_mdio(struct mdiobb_ctrl *ctrl)
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
+
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	return bb_read(bitbang->addr, bitbang->mdi_msk);
 }
 
@@ -427,6 +583,9 @@
 {
 	struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
 
+	if (bitbang->set_gate)
+		bitbang->set_gate(bitbang->addr);
+
 	if (bit)
 		bb_set(bitbang->addr, bitbang->mdc_msk);
 	else
@@ -470,7 +629,6 @@
 /* format skb and descriptor buffer */
 static void sh_eth_ring_format(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	int i;
 	struct sk_buff *skb;
@@ -506,10 +664,9 @@
 		rxdesc->buffer_length = ALIGN(mdp->rx_buf_sz, 16);
 		/* Rx descriptor address set */
 		if (i == 0) {
-			writel(mdp->rx_desc_dma, ioaddr + RDLAR);
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			writel(mdp->rx_desc_dma, ioaddr + RDFAR);
-#endif
+			sh_eth_write(ndev, mdp->rx_desc_dma, RDLAR);
+			if (sh_eth_is_gether(mdp))
+				sh_eth_write(ndev, mdp->rx_desc_dma, RDFAR);
 		}
 	}
 
@@ -528,10 +685,9 @@
 		txdesc->buffer_length = 0;
 		if (i == 0) {
 			/* Tx descriptor address set */
-			writel(mdp->tx_desc_dma, ioaddr + TDLAR);
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-			writel(mdp->tx_desc_dma, ioaddr + TDFAR);
-#endif
+			sh_eth_write(ndev, mdp->tx_desc_dma, TDLAR);
+			if (sh_eth_is_gether(mdp))
+				sh_eth_write(ndev, mdp->tx_desc_dma, TDFAR);
 		}
 	}
 
@@ -613,7 +769,6 @@
 {
 	int ret = 0;
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	u_int32_t rx_int_var, tx_int_var;
 	u32 val;
 
@@ -623,71 +778,71 @@
 	/* Descriptor format */
 	sh_eth_ring_format(ndev);
 	if (mdp->cd->rpadir)
-		writel(mdp->cd->rpadir_value, ioaddr + RPADIR);
+		sh_eth_write(ndev, mdp->cd->rpadir_value, RPADIR);
 
 	/* all sh_eth int mask */
-	writel(0, ioaddr + EESIPR);
+	sh_eth_write(ndev, 0, EESIPR);
 
 #if defined(__LITTLE_ENDIAN__)
 	if (mdp->cd->hw_swap)
-		writel(EDMR_EL, ioaddr + EDMR);
+		sh_eth_write(ndev, EDMR_EL, EDMR);
 	else
 #endif
-		writel(0, ioaddr + EDMR);
+		sh_eth_write(ndev, 0, EDMR);
 
 	/* FIFO size set */
-	writel(mdp->cd->fdr_value, ioaddr + FDR);
-	writel(0, ioaddr + TFTR);
+	sh_eth_write(ndev, mdp->cd->fdr_value, FDR);
+	sh_eth_write(ndev, 0, TFTR);
 
 	/* Frame recv control */
-	writel(mdp->cd->rmcr_value, ioaddr + RMCR);
+	sh_eth_write(ndev, mdp->cd->rmcr_value, RMCR);
 
 	rx_int_var = mdp->rx_int_var = DESC_I_RINT8 | DESC_I_RINT5;
 	tx_int_var = mdp->tx_int_var = DESC_I_TINT2;
-	writel(rx_int_var | tx_int_var, ioaddr + TRSCER);
+	sh_eth_write(ndev, rx_int_var | tx_int_var, TRSCER);
 
 	if (mdp->cd->bculr)
-		writel(0x800, ioaddr + BCULR);	/* Burst sycle set */
+		sh_eth_write(ndev, 0x800, BCULR);	/* Burst sycle set */
 
-	writel(mdp->cd->fcftr_value, ioaddr + FCFTR);
+	sh_eth_write(ndev, mdp->cd->fcftr_value, FCFTR);
 
 	if (!mdp->cd->no_trimd)
-		writel(0, ioaddr + TRIMD);
+		sh_eth_write(ndev, 0, TRIMD);
 
 	/* Recv frame limit set register */
-	writel(RFLR_VALUE, ioaddr + RFLR);
+	sh_eth_write(ndev, RFLR_VALUE, RFLR);
 
-	writel(readl(ioaddr + EESR), ioaddr + EESR);
-	writel(mdp->cd->eesipr_value, ioaddr + EESIPR);
+	sh_eth_write(ndev, sh_eth_read(ndev, EESR), EESR);
+	sh_eth_write(ndev, mdp->cd->eesipr_value, EESIPR);
 
 	/* PAUSE Prohibition */
-	val = (readl(ioaddr + ECMR) & ECMR_DM) |
+	val = (sh_eth_read(ndev, ECMR) & ECMR_DM) |
 		ECMR_ZPF | (mdp->duplex ? ECMR_DM : 0) | ECMR_TE | ECMR_RE;
 
-	writel(val, ioaddr + ECMR);
+	sh_eth_write(ndev, val, ECMR);
 
 	if (mdp->cd->set_rate)
 		mdp->cd->set_rate(ndev);
 
 	/* E-MAC Status Register clear */
-	writel(mdp->cd->ecsr_value, ioaddr + ECSR);
+	sh_eth_write(ndev, mdp->cd->ecsr_value, ECSR);
 
 	/* E-MAC Interrupt Enable register */
-	writel(mdp->cd->ecsipr_value, ioaddr + ECSIPR);
+	sh_eth_write(ndev, mdp->cd->ecsipr_value, ECSIPR);
 
 	/* Set MAC address */
 	update_mac_address(ndev);
 
 	/* mask reset */
 	if (mdp->cd->apr)
-		writel(APR_AP, ioaddr + APR);
+		sh_eth_write(ndev, APR_AP, APR);
 	if (mdp->cd->mpr)
-		writel(MPR_MP, ioaddr + MPR);
+		sh_eth_write(ndev, MPR_MP, MPR);
 	if (mdp->cd->tpauser)
-		writel(TPAUSER_UNLIMITED, ioaddr + TPAUSER);
+		sh_eth_write(ndev, TPAUSER_UNLIMITED, TPAUSER);
 
 	/* Setting the Rx mode will start the Rx process. */
-	writel(EDRRR_R, ioaddr + EDRRR);
+	sh_eth_write(ndev, EDRRR_R, EDRRR);
 
 	netif_start_queue(ndev);
 
@@ -811,24 +966,37 @@
 
 	/* Restart Rx engine if stopped. */
 	/* If we don't need to check status, don't. -KDU */
-	if (!(readl(ndev->base_addr + EDRRR) & EDRRR_R))
-		writel(EDRRR_R, ndev->base_addr + EDRRR);
+	if (!(sh_eth_read(ndev, EDRRR) & EDRRR_R))
+		sh_eth_write(ndev, EDRRR_R, EDRRR);
 
 	return 0;
 }
 
+static void sh_eth_rcv_snd_disable(struct net_device *ndev)
+{
+	/* disable tx and rx */
+	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) &
+		~(ECMR_RE | ECMR_TE), ECMR);
+}
+
+static void sh_eth_rcv_snd_enable(struct net_device *ndev)
+{
+	/* enable tx and rx */
+	sh_eth_write(ndev, sh_eth_read(ndev, ECMR) |
+		(ECMR_RE | ECMR_TE), ECMR);
+}
+
 /* error control function */
 static void sh_eth_error(struct net_device *ndev, int intr_status)
 {
 	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 = readl(ioaddr + ECSR);
-		writel(felic_stat, ioaddr + ECSR);	/* clear int */
+		felic_stat = sh_eth_read(ndev, ECSR);
+		sh_eth_write(ndev, felic_stat, ECSR);	/* clear int */
 		if (felic_stat & ECSR_ICD)
 			mdp->stats.tx_carrier_errors++;
 		if (felic_stat & ECSR_LCHNG) {
@@ -839,26 +1007,23 @@
 				else
 					link_stat = PHY_ST_LINK;
 			} else {
-				link_stat = (readl(ioaddr + PSR));
+				link_stat = (sh_eth_read(ndev, PSR));
 				if (mdp->ether_link_active_low)
 					link_stat = ~link_stat;
 			}
-			if (!(link_stat & PHY_ST_LINK)) {
-				/* Link Down : disable tx and rx */
-				writel(readl(ioaddr + ECMR) &
-					  ~(ECMR_RE | ECMR_TE), ioaddr + ECMR);
-			} else {
+			if (!(link_stat & PHY_ST_LINK))
+				sh_eth_rcv_snd_disable(ndev);
+			else {
 				/* Link Up */
-				writel(readl(ioaddr + EESIPR) &
-					  ~DMAC_M_ECI, ioaddr + EESIPR);
+				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) &
+					  ~DMAC_M_ECI, EESIPR);
 				/*clear int */
-				writel(readl(ioaddr + ECSR),
-					  ioaddr + ECSR);
-				writel(readl(ioaddr + EESIPR) |
-					  DMAC_M_ECI, ioaddr + EESIPR);
+				sh_eth_write(ndev, sh_eth_read(ndev, ECSR),
+					  ECSR);
+				sh_eth_write(ndev, sh_eth_read(ndev, EESIPR) |
+					  DMAC_M_ECI, EESIPR);
 				/* enable tx and rx */
-				writel(readl(ioaddr + ECMR) |
-					  (ECMR_RE | ECMR_TE), ioaddr + ECMR);
+				sh_eth_rcv_snd_enable(ndev);
 			}
 		}
 	}
@@ -867,6 +1032,8 @@
 		/* Write buck end. unused write back interrupt */
 		if (intr_status & EESR_TABT)	/* Transmit Abort int */
 			mdp->stats.tx_aborted_errors++;
+			if (netif_msg_tx_err(mdp))
+				dev_err(&ndev->dev, "Transmit Abort\n");
 	}
 
 	if (intr_status & EESR_RABT) {
@@ -874,28 +1041,47 @@
 		if (intr_status & EESR_RFRMER) {
 			/* Receive Frame Overflow int */
 			mdp->stats.rx_frame_errors++;
-			dev_err(&ndev->dev, "Receive Frame Overflow\n");
+			if (netif_msg_rx_err(mdp))
+				dev_err(&ndev->dev, "Receive Abort\n");
 		}
 	}
 
-	if (!mdp->cd->no_ade) {
-		if (intr_status & EESR_ADE && intr_status & EESR_TDE &&
-		    intr_status & EESR_TFE)
-			mdp->stats.tx_fifo_errors++;
+	if (intr_status & EESR_TDE) {
+		/* Transmit Descriptor Empty int */
+		mdp->stats.tx_fifo_errors++;
+		if (netif_msg_tx_err(mdp))
+			dev_err(&ndev->dev, "Transmit Descriptor Empty\n");
+	}
+
+	if (intr_status & EESR_TFE) {
+		/* FIFO under flow */
+		mdp->stats.tx_fifo_errors++;
+		if (netif_msg_tx_err(mdp))
+			dev_err(&ndev->dev, "Transmit FIFO Under flow\n");
 	}
 
 	if (intr_status & EESR_RDE) {
 		/* Receive Descriptor Empty int */
 		mdp->stats.rx_over_errors++;
 
-		if (readl(ioaddr + EDRRR) ^ EDRRR_R)
-			writel(EDRRR_R, ioaddr + EDRRR);
-		dev_err(&ndev->dev, "Receive Descriptor Empty\n");
+		if (sh_eth_read(ndev, EDRRR) ^ EDRRR_R)
+			sh_eth_write(ndev, EDRRR_R, EDRRR);
+		if (netif_msg_rx_err(mdp))
+			dev_err(&ndev->dev, "Receive Descriptor Empty\n");
 	}
+
 	if (intr_status & EESR_RFE) {
 		/* Receive FIFO Overflow int */
 		mdp->stats.rx_fifo_errors++;
-		dev_err(&ndev->dev, "Receive FIFO Overflow\n");
+		if (netif_msg_rx_err(mdp))
+			dev_err(&ndev->dev, "Receive FIFO Overflow\n");
+	}
+
+	if (!mdp->cd->no_ade && (intr_status & EESR_ADE)) {
+		/* Address Error */
+		mdp->stats.tx_fifo_errors++;
+		if (netif_msg_tx_err(mdp))
+			dev_err(&ndev->dev, "Address Error\n");
 	}
 
 	mask = EESR_TWB | EESR_TABT | EESR_ADE | EESR_TDE | EESR_TFE;
@@ -903,7 +1089,7 @@
 		mask &= ~EESR_ADE;
 	if (intr_status & mask) {
 		/* Tx error */
-		u32 edtrr = readl(ndev->base_addr + EDTRR);
+		u32 edtrr = sh_eth_read(ndev, EDTRR);
 		/* dmesg */
 		dev_err(&ndev->dev, "TX error. status=%8.8x cur_tx=%8.8x ",
 				intr_status, mdp->cur_tx);
@@ -913,9 +1099,9 @@
 		sh_eth_txfree(ndev);
 
 		/* SH7712 BUG */
-		if (edtrr ^ EDTRR_TRNS) {
+		if (edtrr ^ sh_eth_get_edtrr_trns(mdp)) {
 			/* tx dma start */
-			writel(EDTRR_TRNS, ndev->base_addr + EDTRR);
+			sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
 		}
 		/* wakeup */
 		netif_wake_queue(ndev);
@@ -928,18 +1114,17 @@
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct sh_eth_cpu_data *cd = mdp->cd;
 	irqreturn_t ret = IRQ_NONE;
-	u32 ioaddr, intr_status = 0;
+	u32 intr_status = 0;
 
-	ioaddr = ndev->base_addr;
 	spin_lock(&mdp->lock);
 
 	/* Get interrpt stat */
-	intr_status = readl(ioaddr + EESR);
+	intr_status = sh_eth_read(ndev, EESR);
 	/* Clear interrupt */
 	if (intr_status & (EESR_FRC | EESR_RMAF | EESR_RRF |
 			EESR_RTLF | EESR_RTSF | EESR_PRE | EESR_CERF |
 			cd->tx_check | cd->eesr_err_check)) {
-		writel(intr_status, ioaddr + EESR);
+		sh_eth_write(ndev, intr_status, EESR);
 		ret = IRQ_HANDLED;
 	} else
 		goto other_irq;
@@ -982,7 +1167,6 @@
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
 	struct phy_device *phydev = mdp->phydev;
-	u32 ioaddr = ndev->base_addr;
 	int new_state = 0;
 
 	if (phydev->link != PHY_DOWN) {
@@ -1000,8 +1184,8 @@
 				mdp->cd->set_rate(ndev);
 		}
 		if (mdp->link == PHY_DOWN) {
-			writel((readl(ioaddr + ECMR) & ~ECMR_TXF)
-					| ECMR_DM, ioaddr + ECMR);
+			sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_TXF)
+					| ECMR_DM, ECMR);
 			new_state = 1;
 			mdp->link = phydev->link;
 		}
@@ -1012,7 +1196,7 @@
 		mdp->duplex = -1;
 	}
 
-	if (new_state)
+	if (new_state && netif_msg_link(mdp))
 		phy_print_status(phydev);
 }
 
@@ -1032,7 +1216,7 @@
 
 	/* Try connect to PHY */
 	phydev = phy_connect(ndev, phy_id, sh_eth_adjust_link,
-				0, PHY_INTERFACE_MODE_MII);
+				0, mdp->phy_interface);
 	if (IS_ERR(phydev)) {
 		dev_err(&ndev->dev, "phy_connect failed\n");
 		return PTR_ERR(phydev);
@@ -1063,6 +1247,131 @@
 	return 0;
 }
 
+static int sh_eth_get_settings(struct net_device *ndev,
+			struct ethtool_cmd *ecmd)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+	ret = phy_ethtool_gset(mdp->phydev, ecmd);
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	return ret;
+}
+
+static int sh_eth_set_settings(struct net_device *ndev,
+		struct ethtool_cmd *ecmd)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+
+	/* disable tx and rx */
+	sh_eth_rcv_snd_disable(ndev);
+
+	ret = phy_ethtool_sset(mdp->phydev, ecmd);
+	if (ret)
+		goto error_exit;
+
+	if (ecmd->duplex == DUPLEX_FULL)
+		mdp->duplex = 1;
+	else
+		mdp->duplex = 0;
+
+	if (mdp->cd->set_duplex)
+		mdp->cd->set_duplex(ndev);
+
+error_exit:
+	mdelay(1);
+
+	/* enable tx and rx */
+	sh_eth_rcv_snd_enable(ndev);
+
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	return ret;
+}
+
+static int sh_eth_nway_reset(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	unsigned long flags;
+	int ret;
+
+	spin_lock_irqsave(&mdp->lock, flags);
+	ret = phy_start_aneg(mdp->phydev);
+	spin_unlock_irqrestore(&mdp->lock, flags);
+
+	return ret;
+}
+
+static u32 sh_eth_get_msglevel(struct net_device *ndev)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	return mdp->msg_enable;
+}
+
+static void sh_eth_set_msglevel(struct net_device *ndev, u32 value)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	mdp->msg_enable = value;
+}
+
+static const char sh_eth_gstrings_stats[][ETH_GSTRING_LEN] = {
+	"rx_current", "tx_current",
+	"rx_dirty", "tx_dirty",
+};
+#define SH_ETH_STATS_LEN  ARRAY_SIZE(sh_eth_gstrings_stats)
+
+static int sh_eth_get_sset_count(struct net_device *netdev, int sset)
+{
+	switch (sset) {
+	case ETH_SS_STATS:
+		return SH_ETH_STATS_LEN;
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+static void sh_eth_get_ethtool_stats(struct net_device *ndev,
+			struct ethtool_stats *stats, u64 *data)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+	int i = 0;
+
+	/* device-specific stats */
+	data[i++] = mdp->cur_rx;
+	data[i++] = mdp->cur_tx;
+	data[i++] = mdp->dirty_rx;
+	data[i++] = mdp->dirty_tx;
+}
+
+static void sh_eth_get_strings(struct net_device *ndev, u32 stringset, u8 *data)
+{
+	switch (stringset) {
+	case ETH_SS_STATS:
+		memcpy(data, *sh_eth_gstrings_stats,
+					sizeof(sh_eth_gstrings_stats));
+		break;
+	}
+}
+
+static struct ethtool_ops sh_eth_ethtool_ops = {
+	.get_settings	= sh_eth_get_settings,
+	.set_settings	= sh_eth_set_settings,
+	.nway_reset		= sh_eth_nway_reset,
+	.get_msglevel	= sh_eth_get_msglevel,
+	.set_msglevel	= sh_eth_set_msglevel,
+	.get_link		= ethtool_op_get_link,
+	.get_strings	= sh_eth_get_strings,
+	.get_ethtool_stats  = sh_eth_get_ethtool_stats,
+	.get_sset_count     = sh_eth_get_sset_count,
+};
+
 /* network device open function */
 static int sh_eth_open(struct net_device *ndev)
 {
@@ -1073,8 +1382,8 @@
 
 	ret = request_irq(ndev->irq, sh_eth_interrupt,
 #if defined(CONFIG_CPU_SUBTYPE_SH7763) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7764) || \
-    defined(CONFIG_CPU_SUBTYPE_SH7757)
+	defined(CONFIG_CPU_SUBTYPE_SH7764) || \
+	defined(CONFIG_CPU_SUBTYPE_SH7757)
 				IRQF_SHARED,
 #else
 				0,
@@ -1117,15 +1426,14 @@
 static void sh_eth_tx_timeout(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	struct sh_eth_rxdesc *rxdesc;
 	int i;
 
 	netif_stop_queue(ndev);
 
-	/* worning message out. */
-	printk(KERN_WARNING "%s: transmit timed out, status %8.8x,"
-	       " resetting...\n", ndev->name, (int)readl(ioaddr + EESR));
+	if (netif_msg_timer(mdp))
+		dev_err(&ndev->dev, "%s: transmit timed out, status %8.8x,"
+	       " resetting...\n", ndev->name, (int)sh_eth_read(ndev, EESR));
 
 	/* tx_errors count up */
 	mdp->stats.tx_errors++;
@@ -1167,6 +1475,8 @@
 	spin_lock_irqsave(&mdp->lock, flags);
 	if ((mdp->cur_tx - mdp->dirty_tx) >= (TX_RING_SIZE - 4)) {
 		if (!sh_eth_txfree(ndev)) {
+			if (netif_msg_tx_queued(mdp))
+				dev_warn(&ndev->dev, "TxFD exhausted.\n");
 			netif_stop_queue(ndev);
 			spin_unlock_irqrestore(&mdp->lock, flags);
 			return NETDEV_TX_BUSY;
@@ -1196,8 +1506,8 @@
 
 	mdp->cur_tx++;
 
-	if (!(readl(ndev->base_addr + EDTRR) & EDTRR_TRNS))
-		writel(EDTRR_TRNS, ndev->base_addr + EDTRR);
+	if (!(sh_eth_read(ndev, EDTRR) & sh_eth_get_edtrr_trns(mdp)))
+		sh_eth_write(ndev, sh_eth_get_edtrr_trns(mdp), EDTRR);
 
 	return NETDEV_TX_OK;
 }
@@ -1206,17 +1516,16 @@
 static int sh_eth_close(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 	int ringsize;
 
 	netif_stop_queue(ndev);
 
 	/* Disable interrupts by clearing the interrupt mask. */
-	writel(0x0000, ioaddr + EESIPR);
+	sh_eth_write(ndev, 0x0000, EESIPR);
 
 	/* Stop the chip's Tx and Rx processes. */
-	writel(0, ioaddr + EDTRR);
-	writel(0, ioaddr + EDRRR);
+	sh_eth_write(ndev, 0, EDTRR);
+	sh_eth_write(ndev, 0, EDRRR);
 
 	/* PHY Disconnect */
 	if (mdp->phydev) {
@@ -1247,25 +1556,24 @@
 static struct net_device_stats *sh_eth_get_stats(struct net_device *ndev)
 {
 	struct sh_eth_private *mdp = netdev_priv(ndev);
-	u32 ioaddr = ndev->base_addr;
 
 	pm_runtime_get_sync(&mdp->pdev->dev);
 
-	mdp->stats.tx_dropped += readl(ioaddr + TROCR);
-	writel(0, ioaddr + TROCR);	/* (write clear) */
-	mdp->stats.collisions += readl(ioaddr + CDCR);
-	writel(0, ioaddr + CDCR);	/* (write clear) */
-	mdp->stats.tx_carrier_errors += readl(ioaddr + LCCR);
-	writel(0, ioaddr + LCCR);	/* (write clear) */
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	mdp->stats.tx_carrier_errors += readl(ioaddr + CERCR);/* CERCR */
-	writel(0, ioaddr + CERCR);	/* (write clear) */
-	mdp->stats.tx_carrier_errors += readl(ioaddr + CEECR);/* CEECR */
-	writel(0, ioaddr + CEECR);	/* (write clear) */
-#else
-	mdp->stats.tx_carrier_errors += readl(ioaddr + CNDCR);
-	writel(0, ioaddr + CNDCR);	/* (write clear) */
-#endif
+	mdp->stats.tx_dropped += sh_eth_read(ndev, TROCR);
+	sh_eth_write(ndev, 0, TROCR);	/* (write clear) */
+	mdp->stats.collisions += sh_eth_read(ndev, CDCR);
+	sh_eth_write(ndev, 0, CDCR);	/* (write clear) */
+	mdp->stats.tx_carrier_errors += sh_eth_read(ndev, LCCR);
+	sh_eth_write(ndev, 0, LCCR);	/* (write clear) */
+	if (sh_eth_is_gether(mdp)) {
+		mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CERCR);
+		sh_eth_write(ndev, 0, CERCR);	/* (write clear) */
+		mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CEECR);
+		sh_eth_write(ndev, 0, CEECR);	/* (write clear) */
+	} else {
+		mdp->stats.tx_carrier_errors += sh_eth_read(ndev, CNDCR);
+		sh_eth_write(ndev, 0, CNDCR);	/* (write clear) */
+	}
 	pm_runtime_put_sync(&mdp->pdev->dev);
 
 	return &mdp->stats;
@@ -1291,48 +1599,46 @@
 /* Multicast reception directions set */
 static void sh_eth_set_multicast_list(struct net_device *ndev)
 {
-	u32 ioaddr = ndev->base_addr;
-
 	if (ndev->flags & IFF_PROMISC) {
 		/* Set promiscuous. */
-		writel((readl(ioaddr + ECMR) & ~ECMR_MCT) | ECMR_PRM,
-			  ioaddr + ECMR);
+		sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_MCT) |
+				ECMR_PRM, ECMR);
 	} else {
 		/* Normal, unicast/broadcast-only mode. */
-		writel((readl(ioaddr + ECMR) & ~ECMR_PRM) | ECMR_MCT,
-			  ioaddr + ECMR);
+		sh_eth_write(ndev, (sh_eth_read(ndev, ECMR) & ~ECMR_PRM) |
+				ECMR_MCT, ECMR);
 	}
 }
+#endif /* SH_ETH_HAS_TSU */
 
 /* SuperH's TSU register init function */
-static void sh_eth_tsu_init(u32 ioaddr)
+static void sh_eth_tsu_init(struct sh_eth_private *mdp)
 {
-	writel(0, ioaddr + TSU_FWEN0);	/* Disable forward(0->1) */
-	writel(0, ioaddr + TSU_FWEN1);	/* Disable forward(1->0) */
-	writel(0, ioaddr + TSU_FCM);	/* forward fifo 3k-3k */
-	writel(0xc, ioaddr + TSU_BSYSL0);
-	writel(0xc, ioaddr + TSU_BSYSL1);
-	writel(0, ioaddr + TSU_PRISL0);
-	writel(0, ioaddr + TSU_PRISL1);
-	writel(0, ioaddr + TSU_FWSL0);
-	writel(0, ioaddr + TSU_FWSL1);
-	writel(TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, ioaddr + TSU_FWSLC);
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-	writel(0, ioaddr + TSU_QTAG0);	/* Disable QTAG(0->1) */
-	writel(0, ioaddr + TSU_QTAG1);	/* Disable QTAG(1->0) */
-#else
-	writel(0, ioaddr + TSU_QTAGM0);	/* Disable QTAG(0->1) */
-	writel(0, ioaddr + TSU_QTAGM1);	/* Disable QTAG(1->0) */
-#endif
-	writel(0, ioaddr + TSU_FWSR);	/* all interrupt status clear */
-	writel(0, ioaddr + TSU_FWINMK);	/* Disable all interrupt */
-	writel(0, ioaddr + TSU_TEN);	/* Disable all CAM entry */
-	writel(0, ioaddr + TSU_POST1);	/* Disable CAM entry [ 0- 7] */
-	writel(0, ioaddr + TSU_POST2);	/* Disable CAM entry [ 8-15] */
-	writel(0, ioaddr + TSU_POST3);	/* Disable CAM entry [16-23] */
-	writel(0, ioaddr + TSU_POST4);	/* Disable CAM entry [24-31] */
+	sh_eth_tsu_write(mdp, 0, TSU_FWEN0);	/* Disable forward(0->1) */
+	sh_eth_tsu_write(mdp, 0, TSU_FWEN1);	/* Disable forward(1->0) */
+	sh_eth_tsu_write(mdp, 0, TSU_FCM);	/* forward fifo 3k-3k */
+	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL0);
+	sh_eth_tsu_write(mdp, 0xc, TSU_BSYSL1);
+	sh_eth_tsu_write(mdp, 0, TSU_PRISL0);
+	sh_eth_tsu_write(mdp, 0, TSU_PRISL1);
+	sh_eth_tsu_write(mdp, 0, TSU_FWSL0);
+	sh_eth_tsu_write(mdp, 0, TSU_FWSL1);
+	sh_eth_tsu_write(mdp, TSU_FWSLC_POSTENU | TSU_FWSLC_POSTENL, TSU_FWSLC);
+	if (sh_eth_is_gether(mdp)) {
+		sh_eth_tsu_write(mdp, 0, TSU_QTAG0);	/* Disable QTAG(0->1) */
+		sh_eth_tsu_write(mdp, 0, TSU_QTAG1);	/* Disable QTAG(1->0) */
+	} else {
+		sh_eth_tsu_write(mdp, 0, TSU_QTAGM0);	/* Disable QTAG(0->1) */
+		sh_eth_tsu_write(mdp, 0, TSU_QTAGM1);	/* Disable QTAG(1->0) */
+	}
+	sh_eth_tsu_write(mdp, 0, TSU_FWSR);	/* all interrupt status clear */
+	sh_eth_tsu_write(mdp, 0, TSU_FWINMK);	/* Disable all interrupt */
+	sh_eth_tsu_write(mdp, 0, TSU_TEN);	/* Disable all CAM entry */
+	sh_eth_tsu_write(mdp, 0, TSU_POST1);	/* Disable CAM entry [ 0- 7] */
+	sh_eth_tsu_write(mdp, 0, TSU_POST2);	/* Disable CAM entry [ 8-15] */
+	sh_eth_tsu_write(mdp, 0, TSU_POST3);	/* Disable CAM entry [16-23] */
+	sh_eth_tsu_write(mdp, 0, 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)
@@ -1355,7 +1661,8 @@
 }
 
 /* MDIO bus init function */
-static int sh_mdio_init(struct net_device *ndev, int id)
+static int sh_mdio_init(struct net_device *ndev, int id,
+			struct sh_eth_plat_data *pd)
 {
 	int ret, i;
 	struct bb_info *bitbang;
@@ -1369,7 +1676,8 @@
 	}
 
 	/* bitbang init */
-	bitbang->addr = ndev->base_addr + PIR;
+	bitbang->addr = ndev->base_addr + mdp->reg_offset[PIR];
+	bitbang->set_gate = pd->set_mdio_gate;
 	bitbang->mdi_msk = 0x08;
 	bitbang->mdo_msk = 0x04;
 	bitbang->mmd_msk = 0x02;/* MMD */
@@ -1420,6 +1728,28 @@
 	return ret;
 }
 
+static const u16 *sh_eth_get_register_offset(int register_type)
+{
+	const u16 *reg_offset = NULL;
+
+	switch (register_type) {
+	case SH_ETH_REG_GIGABIT:
+		reg_offset = sh_eth_offset_gigabit;
+		break;
+	case SH_ETH_REG_FAST_SH4:
+		reg_offset = sh_eth_offset_fast_sh4;
+		break;
+	case SH_ETH_REG_FAST_SH3_SH2:
+		reg_offset = sh_eth_offset_fast_sh3_sh2;
+		break;
+	default:
+		printk(KERN_ERR "Unknown register type (%d)\n", register_type);
+		break;
+	}
+
+	return reg_offset;
+}
+
 static const struct net_device_ops sh_eth_netdev_ops = {
 	.ndo_open		= sh_eth_open,
 	.ndo_stop		= sh_eth_close,
@@ -1486,19 +1816,28 @@
 	pd = (struct sh_eth_plat_data *)(pdev->dev.platform_data);
 	/* get PHY ID */
 	mdp->phy_id = pd->phy;
+	mdp->phy_interface = pd->phy_interface;
 	/* EDMAC endian */
 	mdp->edmac_endian = pd->edmac_endian;
 	mdp->no_ether_link = pd->no_ether_link;
 	mdp->ether_link_active_low = pd->ether_link_active_low;
+	mdp->reg_offset = sh_eth_get_register_offset(pd->register_type);
 
 	/* set cpu data */
+#if defined(SH_ETH_HAS_BOTH_MODULES)
+	mdp->cd = sh_eth_get_cpu_data(mdp);
+#else
 	mdp->cd = &sh_eth_my_cpu_data;
+#endif
 	sh_eth_set_default_cpu_data(mdp->cd);
 
 	/* set function */
 	ndev->netdev_ops = &sh_eth_netdev_ops;
+	SET_ETHTOOL_OPS(ndev, &sh_eth_ethtool_ops);
 	ndev->watchdog_timeo = TX_TIMEOUT;
 
+	/* debug message level */
+	mdp->msg_enable = SH_ETH_DEF_MSG_ENABLE;
 	mdp->post_rx = POST_RX >> (devno << 1);
 	mdp->post_fw = POST_FW >> (devno << 1);
 
@@ -1507,13 +1846,23 @@
 
 	/* First device only init */
 	if (!devno) {
+		if (mdp->cd->tsu) {
+			struct resource *rtsu;
+			rtsu = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+			if (!rtsu) {
+				dev_err(&pdev->dev, "Not found TSU resource\n");
+				goto out_release;
+			}
+			mdp->tsu_addr = ioremap(rtsu->start,
+						resource_size(rtsu));
+		}
 		if (mdp->cd->chip_reset)
 			mdp->cd->chip_reset(ndev);
 
-#if defined(SH_ETH_HAS_TSU)
-		/* TSU init (Init only)*/
-		sh_eth_tsu_init(SH_TSU_ADDR);
-#endif
+		if (mdp->cd->tsu) {
+			/* TSU init (Init only)*/
+			sh_eth_tsu_init(mdp);
+		}
 	}
 
 	/* network device register */
@@ -1522,11 +1871,11 @@
 		goto out_release;
 
 	/* mdio bus init */
-	ret = sh_mdio_init(ndev, pdev->id);
+	ret = sh_mdio_init(ndev, pdev->id, pd);
 	if (ret)
 		goto out_unregister;
 
-	/* print device infomation */
+	/* print device information */
 	pr_info("Base address at 0x%x, %pM, IRQ %d.\n",
 	       (u32)ndev->base_addr, ndev->dev_addr, ndev->irq);
 
@@ -1539,6 +1888,8 @@
 
 out_release:
 	/* net_dev free */
+	if (mdp->tsu_addr)
+		iounmap(mdp->tsu_addr);
 	if (ndev)
 		free_netdev(ndev);
 
@@ -1549,7 +1900,9 @@
 static int sh_eth_drv_remove(struct platform_device *pdev)
 {
 	struct net_device *ndev = platform_get_drvdata(pdev);
+	struct sh_eth_private *mdp = netdev_priv(ndev);
 
+	iounmap(mdp->tsu_addr);
 	sh_mdio_release(ndev);
 	unregister_netdev(ndev);
 	pm_runtime_disable(&pdev->dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sh_eth.h linux-libre-2.6.39-gnu/drivers/net/sh_eth.h
--- linux-libre-2.6.38-gnu/drivers/net/sh_eth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sh_eth.h	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  *  SuperH Ethernet device driver
  *
  *  Copyright (C) 2006-2008 Nobuhiro Iwamatsu
- *  Copyright (C) 2008-2009 Renesas Solutions Corp.
+ *  Copyright (C) 2008-2011 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,
@@ -38,278 +38,340 @@
 #define ETHERSMALL		60
 #define PKT_BUF_SZ		1538
 
-#if defined(CONFIG_CPU_SUBTYPE_SH7763)
-/* This CPU register maps is very difference by other SH4 CPU */
+enum {
+	/* E-DMAC registers */
+	EDSR = 0,
+	EDMR,
+	EDTRR,
+	EDRRR,
+	EESR,
+	EESIPR,
+	TDLAR,
+	TDFAR,
+	TDFXR,
+	TDFFR,
+	RDLAR,
+	RDFAR,
+	RDFXR,
+	RDFFR,
+	TRSCER,
+	RMFCR,
+	TFTR,
+	FDR,
+	RMCR,
+	EDOCR,
+	TFUCR,
+	RFOCR,
+	FCFTR,
+	RPADIR,
+	TRIMD,
+	RBWAR,
+	TBRAR,
 
-/* Chip Base Address */
-# define SH_TSU_ADDR	0xFEE01800
-# define ARSTR		SH_TSU_ADDR
+	/* Ether registers */
+	ECMR,
+	ECSR,
+	ECSIPR,
+	PIR,
+	PSR,
+	RDMLR,
+	PIPR,
+	RFLR,
+	IPGR,
+	APR,
+	MPR,
+	PFTCR,
+	PFRCR,
+	RFCR,
+	RFCF,
+	TPAUSER,
+	TPAUSECR,
+	BCFR,
+	BCFRR,
+	GECMR,
+	BCULR,
+	MAHR,
+	MALR,
+	TROCR,
+	CDCR,
+	LCCR,
+	CNDCR,
+	CEFCR,
+	FRECR,
+	TSFRCR,
+	TLFRCR,
+	CERCR,
+	CEECR,
+	MAFCR,
+	RTRATE,
 
-/* Chip Registers */
-/* E-DMAC */
-# define EDSR    0x000
-# define EDMR    0x400
-# define EDTRR   0x408
-# define EDRRR   0x410
-# define EESR    0x428
-# define EESIPR  0x430
-# define TDLAR   0x010
-# define TDFAR   0x014
-# define TDFXR   0x018
-# define TDFFR   0x01C
-# define RDLAR   0x030
-# define RDFAR   0x034
-# define RDFXR   0x038
-# define RDFFR   0x03C
-# define TRSCER  0x438
-# define RMFCR   0x440
-# define TFTR    0x448
-# define FDR     0x450
-# define RMCR    0x458
-# define RPADIR  0x460
-# define FCFTR   0x468
+	/* TSU Absolute address */
+	ARSTR,
+	TSU_CTRST,
+	TSU_FWEN0,
+	TSU_FWEN1,
+	TSU_FCM,
+	TSU_BSYSL0,
+	TSU_BSYSL1,
+	TSU_PRISL0,
+	TSU_PRISL1,
+	TSU_FWSL0,
+	TSU_FWSL1,
+	TSU_FWSLC,
+	TSU_QTAG0,
+	TSU_QTAG1,
+	TSU_QTAGM0,
+	TSU_QTAGM1,
+	TSU_FWSR,
+	TSU_FWINMK,
+	TSU_ADQT0,
+	TSU_ADQT1,
+	TSU_VTAG0,
+	TSU_VTAG1,
+	TSU_ADSBSY,
+	TSU_TEN,
+	TSU_POST1,
+	TSU_POST2,
+	TSU_POST3,
+	TSU_POST4,
+	TSU_ADRH0,
+	TSU_ADRL0,
+	TSU_ADRH31,
+	TSU_ADRL31,
 
-/* Ether Register */
-# define ECMR    0x500
-# define ECSR    0x510
-# define ECSIPR  0x518
-# define PIR     0x520
-# define PSR     0x528
-# define PIPR    0x52C
-# define RFLR    0x508
-# define APR     0x554
-# define MPR     0x558
-# define PFTCR	 0x55C
-# define PFRCR	 0x560
-# define TPAUSER 0x564
-# define GECMR   0x5B0
-# define BCULR   0x5B4
-# define MAHR    0x5C0
-# define MALR    0x5C8
-# define TROCR   0x700
-# define CDCR    0x708
-# define LCCR    0x710
-# define CEFCR   0x740
-# define FRECR   0x748
-# define TSFRCR  0x750
-# define TLFRCR  0x758
-# define RFCR    0x760
-# define CERCR   0x768
-# define CEECR   0x770
-# define MAFCR   0x778
+	TXNLCR0,
+	TXALCR0,
+	RXNLCR0,
+	RXALCR0,
+	FWNLCR0,
+	FWALCR0,
+	TXNLCR1,
+	TXALCR1,
+	RXNLCR1,
+	RXALCR1,
+	FWNLCR1,
+	FWALCR1,
 
-/* TSU Absolute Address */
-# define TSU_CTRST       0x004
-# define TSU_FWEN0       0x010
-# define TSU_FWEN1       0x014
-# define TSU_FCM         0x18
-# define TSU_BSYSL0      0x20
-# define TSU_BSYSL1      0x24
-# define TSU_PRISL0      0x28
-# define TSU_PRISL1      0x2C
-# define TSU_FWSL0       0x30
-# define TSU_FWSL1       0x34
-# define TSU_FWSLC       0x38
-# define TSU_QTAG0       0x40
-# define TSU_QTAG1       0x44
-# define TSU_FWSR        0x50
-# define TSU_FWINMK      0x54
-# define TSU_ADQT0       0x48
-# define TSU_ADQT1       0x4C
-# define TSU_VTAG0       0x58
-# define TSU_VTAG1       0x5C
-# define TSU_ADSBSY      0x60
-# define TSU_TEN         0x64
-# define TSU_POST1       0x70
-# define TSU_POST2       0x74
-# define TSU_POST3       0x78
-# define TSU_POST4       0x7C
-# define TSU_ADRH0       0x100
-# define TSU_ADRL0       0x104
-# define TSU_ADRH31      0x1F8
-# define TSU_ADRL31      0x1FC
+	/* This value must be written at last. */
+	SH_ETH_MAX_REGISTER_OFFSET,
+};
 
-# define TXNLCR0         0x80
-# define TXALCR0         0x84
-# define RXNLCR0         0x88
-# define RXALCR0         0x8C
-# define FWNLCR0         0x90
-# define FWALCR0         0x94
-# define TXNLCR1         0xA0
-# define TXALCR1         0xA4
-# define RXNLCR1         0xA8
-# define RXALCR1         0xAC
-# define FWNLCR1         0xB0
-# define FWALCR1         0x40
+static const u16 sh_eth_offset_gigabit[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[EDSR]	= 0x0000,
+	[EDMR]	= 0x0400,
+	[EDTRR]	= 0x0408,
+	[EDRRR]	= 0x0410,
+	[EESR]	= 0x0428,
+	[EESIPR]	= 0x0430,
+	[TDLAR]	= 0x0010,
+	[TDFAR]	= 0x0014,
+	[TDFXR]	= 0x0018,
+	[TDFFR]	= 0x001c,
+	[RDLAR]	= 0x0030,
+	[RDFAR]	= 0x0034,
+	[RDFXR]	= 0x0038,
+	[RDFFR]	= 0x003c,
+	[TRSCER]	= 0x0438,
+	[RMFCR]	= 0x0440,
+	[TFTR]	= 0x0448,
+	[FDR]	= 0x0450,
+	[RMCR]	= 0x0458,
+	[RPADIR]	= 0x0460,
+	[FCFTR]	= 0x0468,
 
-#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
+	[ECMR]	= 0x0500,
+	[ECSR]	= 0x0510,
+	[ECSIPR]	= 0x0518,
+	[PIR]	= 0x0520,
+	[PSR]	= 0x0528,
+	[PIPR]	= 0x052c,
+	[RFLR]	= 0x0508,
+	[APR]	= 0x0554,
+	[MPR]	= 0x0558,
+	[PFTCR]	= 0x055c,
+	[PFRCR]	= 0x0560,
+	[TPAUSER]	= 0x0564,
+	[GECMR]	= 0x05b0,
+	[BCULR]	= 0x05b4,
+	[MAHR]	= 0x05c0,
+	[MALR]	= 0x05c8,
+	[TROCR]	= 0x0700,
+	[CDCR]	= 0x0708,
+	[LCCR]	= 0x0710,
+	[CEFCR]	= 0x0740,
+	[FRECR]	= 0x0748,
+	[TSFRCR]	= 0x0750,
+	[TLFRCR]	= 0x0758,
+	[RFCR]	= 0x0760,
+	[CERCR]	= 0x0768,
+	[CEECR]	= 0x0770,
+	[MAFCR]	= 0x0778,
 
-/* 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
-# define ARSTR		  0xA7000800
-#endif
-/* Chip Registers */
-/* E-DMAC */
-# define EDMR	0x0000
-# define EDTRR	0x0004
-# define EDRRR	0x0008
-# define TDLAR	0x000C
-# define RDLAR	0x0010
-# define EESR	0x0014
-# define EESIPR	0x0018
-# define TRSCER	0x001C
-# define RMFCR	0x0020
-# define TFTR	0x0024
-# define FDR	0x0028
-# define RMCR	0x002C
-# define EDOCR	0x0030
-# define FCFTR	0x0034
-# define RPADIR	0x0038
-# define TRIMD	0x003C
-# define RBWAR	0x0040
-# define RDFAR	0x0044
-# define TBRAR	0x004C
-# define TDFAR	0x0050
+	[ARSTR]	= 0x0000,
+	[TSU_CTRST]	= 0x0004,
+	[TSU_FWEN0]	= 0x0010,
+	[TSU_FWEN1]	= 0x0014,
+	[TSU_FCM]	= 0x0018,
+	[TSU_BSYSL0]	= 0x0020,
+	[TSU_BSYSL1]	= 0x0024,
+	[TSU_PRISL0]	= 0x0028,
+	[TSU_PRISL1]	= 0x002c,
+	[TSU_FWSL0]	= 0x0030,
+	[TSU_FWSL1]	= 0x0034,
+	[TSU_FWSLC]	= 0x0038,
+	[TSU_QTAG0]	= 0x0040,
+	[TSU_QTAG1]	= 0x0044,
+	[TSU_FWSR]	= 0x0050,
+	[TSU_FWINMK]	= 0x0054,
+	[TSU_ADQT0]	= 0x0048,
+	[TSU_ADQT1]	= 0x004c,
+	[TSU_VTAG0]	= 0x0058,
+	[TSU_VTAG1]	= 0x005c,
+	[TSU_ADSBSY]	= 0x0060,
+	[TSU_TEN]	= 0x0064,
+	[TSU_POST1]	= 0x0070,
+	[TSU_POST2]	= 0x0074,
+	[TSU_POST3]	= 0x0078,
+	[TSU_POST4]	= 0x007c,
+	[TSU_ADRH0]	= 0x0100,
+	[TSU_ADRL0]	= 0x0104,
+	[TSU_ADRH31]	= 0x01f8,
+	[TSU_ADRL31]	= 0x01fc,
 
-/* Ether Register */
-# define ECMR	0x0160
-# define ECSR	0x0164
-# define ECSIPR	0x0168
-# define PIR	0x016C
-# define MAHR	0x0170
-# define MALR	0x0174
-# define RFLR	0x0178
-# define PSR	0x017C
-# define TROCR	0x0180
-# define CDCR	0x0184
-# define LCCR	0x0188
-# define CNDCR	0x018C
-# define CEFCR	0x0194
-# define FRECR	0x0198
-# define TSFRCR	0x019C
-# define TLFRCR	0x01A0
-# define RFCR	0x01A4
-# define MAFCR	0x01A8
-# define IPGR	0x01B4
-# if defined(CONFIG_CPU_SUBTYPE_SH7710)
-# define APR	0x01B8
-# define MPR 	0x01BC
-# define TPAUSER 0x1C4
-# define BCFR	0x1CC
-# endif /* CONFIG_CPU_SH7710 */
+	[TXNLCR0]	= 0x0080,
+	[TXALCR0]	= 0x0084,
+	[RXNLCR0]	= 0x0088,
+	[RXALCR0]	= 0x008c,
+	[FWNLCR0]	= 0x0090,
+	[FWALCR0]	= 0x0094,
+	[TXNLCR1]	= 0x00a0,
+	[TXALCR1]	= 0x00a0,
+	[RXNLCR1]	= 0x00a8,
+	[RXALCR1]	= 0x00ac,
+	[FWNLCR1]	= 0x00b0,
+	[FWALCR1]	= 0x00b4,
+};
 
-/* TSU */
-# define TSU_CTRST	0x004
-# define TSU_FWEN0	0x010
-# define TSU_FWEN1	0x014
-# define TSU_FCM	0x018
-# define TSU_BSYSL0	0x020
-# define TSU_BSYSL1	0x024
-# define TSU_PRISL0	0x028
-# define TSU_PRISL1	0x02C
-# define TSU_FWSL0	0x030
-# define TSU_FWSL1	0x034
-# define TSU_FWSLC	0x038
-# define TSU_QTAGM0	0x040
-# define TSU_QTAGM1	0x044
-# define TSU_ADQT0 	0x048
-# define TSU_ADQT1	0x04C
-# define TSU_FWSR	0x050
-# define TSU_FWINMK	0x054
-# define TSU_ADSBSY	0x060
-# define TSU_TEN	0x064
-# define TSU_POST1	0x070
-# define TSU_POST2	0x074
-# define TSU_POST3	0x078
-# define TSU_POST4	0x07C
-# define TXNLCR0	0x080
-# define TXALCR0	0x084
-# define RXNLCR0	0x088
-# define RXALCR0	0x08C
-# define FWNLCR0	0x090
-# define FWALCR0	0x094
-# define TXNLCR1	0x0A0
-# define TXALCR1	0x0A4
-# define RXNLCR1	0x0A8
-# define RXALCR1	0x0AC
-# define FWNLCR1	0x0B0
-# define FWALCR1	0x0B4
+static const u16 sh_eth_offset_fast_sh4[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[ECMR]	= 0x0100,
+	[RFLR]	= 0x0108,
+	[ECSR]	= 0x0110,
+	[ECSIPR]	= 0x0118,
+	[PIR]	= 0x0120,
+	[PSR]	= 0x0128,
+	[RDMLR]	= 0x0140,
+	[IPGR]	= 0x0150,
+	[APR]	= 0x0154,
+	[MPR]	= 0x0158,
+	[TPAUSER]	= 0x0164,
+	[RFCF]	= 0x0160,
+	[TPAUSECR]	= 0x0168,
+	[BCFRR]	= 0x016c,
+	[MAHR]	= 0x01c0,
+	[MALR]	= 0x01c8,
+	[TROCR]	= 0x01d0,
+	[CDCR]	= 0x01d4,
+	[LCCR]	= 0x01d8,
+	[CNDCR]	= 0x01dc,
+	[CEFCR]	= 0x01e4,
+	[FRECR]	= 0x01e8,
+	[TSFRCR]	= 0x01ec,
+	[TLFRCR]	= 0x01f0,
+	[RFCR]	= 0x01f4,
+	[MAFCR]	= 0x01f8,
+	[RTRATE]	= 0x01fc,
 
-#define TSU_ADRH0	0x0100
-#define TSU_ADRL0	0x0104
-#define TSU_ADRL31	0x01FC
+	[EDMR]	= 0x0000,
+	[EDTRR]	= 0x0008,
+	[EDRRR]	= 0x0010,
+	[TDLAR]	= 0x0018,
+	[RDLAR]	= 0x0020,
+	[EESR]	= 0x0028,
+	[EESIPR]	= 0x0030,
+	[TRSCER]	= 0x0038,
+	[RMFCR]	= 0x0040,
+	[TFTR]	= 0x0048,
+	[FDR]	= 0x0050,
+	[RMCR]	= 0x0058,
+	[TFUCR]	= 0x0064,
+	[RFOCR]	= 0x0068,
+	[FCFTR]	= 0x0070,
+	[RPADIR]	= 0x0078,
+	[TRIMD]	= 0x007c,
+	[RBWAR]	= 0x00c8,
+	[RDFAR]	= 0x00cc,
+	[TBRAR]	= 0x00d4,
+	[TDFAR]	= 0x00d8,
+};
 
-#endif /* CONFIG_CPU_SUBTYPE_SH7763 */
+static const u16 sh_eth_offset_fast_sh3_sh2[SH_ETH_MAX_REGISTER_OFFSET] = {
+	[ECMR]	= 0x0160,
+	[ECSR]	= 0x0164,
+	[ECSIPR]	= 0x0168,
+	[PIR]	= 0x016c,
+	[MAHR]	= 0x0170,
+	[MALR]	= 0x0174,
+	[RFLR]	= 0x0178,
+	[PSR]	= 0x017c,
+	[TROCR]	= 0x0180,
+	[CDCR]	= 0x0184,
+	[LCCR]	= 0x0188,
+	[CNDCR]	= 0x018c,
+	[CEFCR]	= 0x0194,
+	[FRECR]	= 0x0198,
+	[TSFRCR]	= 0x019c,
+	[TLFRCR]	= 0x01a0,
+	[RFCR]	= 0x01a4,
+	[MAFCR]	= 0x01a8,
+	[IPGR]	= 0x01b4,
+	[APR]	= 0x01b8,
+	[MPR]	= 0x01bc,
+	[TPAUSER]	= 0x01c4,
+	[BCFR]	= 0x01cc,
 
-/* 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
+	[ARSTR]	= 0x0000,
+	[TSU_CTRST]	= 0x0004,
+	[TSU_FWEN0]	= 0x0010,
+	[TSU_FWEN1]	= 0x0014,
+	[TSU_FCM]	= 0x0018,
+	[TSU_BSYSL0]	= 0x0020,
+	[TSU_BSYSL1]	= 0x0024,
+	[TSU_PRISL0]	= 0x0028,
+	[TSU_PRISL1]	= 0x002c,
+	[TSU_FWSL0]	= 0x0030,
+	[TSU_FWSL1]	= 0x0034,
+	[TSU_FWSLC]	= 0x0038,
+	[TSU_QTAGM0]	= 0x0040,
+	[TSU_QTAGM1]	= 0x0044,
+	[TSU_ADQT0]	= 0x0048,
+	[TSU_ADQT1]	= 0x004c,
+	[TSU_FWSR]	= 0x0050,
+	[TSU_FWINMK]	= 0x0054,
+	[TSU_ADSBSY]	= 0x0060,
+	[TSU_TEN]	= 0x0064,
+	[TSU_POST1]	= 0x0070,
+	[TSU_POST2]	= 0x0074,
+	[TSU_POST3]	= 0x0078,
+	[TSU_POST4]	= 0x007c,
+
+	[TXNLCR0]	= 0x0080,
+	[TXALCR0]	= 0x0084,
+	[RXNLCR0]	= 0x0088,
+	[RXALCR0]	= 0x008c,
+	[FWNLCR0]	= 0x0090,
+	[FWALCR0]	= 0x0094,
+	[TXNLCR1]	= 0x00a0,
+	[TXALCR1]	= 0x00a0,
+	[RXNLCR1]	= 0x00a8,
+	[RXALCR1]	= 0x00ac,
+	[FWNLCR1]	= 0x00b0,
+	[FWALCR1]	= 0x00b4,
+
+	[TSU_ADRH0]	= 0x0100,
+	[TSU_ADRL0]	= 0x0104,
+	[TSU_ADRL31]	= 0x01fc,
+
+};
 
 /* Driver's parameters */
 #if defined(CONFIG_CPU_SH4)
@@ -338,20 +400,14 @@
 enum DMAC_M_BIT {
 	EDMR_EL = 0x40, /* Litte endian */
 	EDMR_DL1 = 0x20, EDMR_DL0 = 0x10,
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-	EDMR_SRST = 0x03,
-#else /* CONFIG_CPU_SUBTYPE_SH7763 */
-	EDMR_SRST = 0x01,
-#endif
+	EDMR_SRST_GETHER = 0x03,
+	EDMR_SRST_ETHER = 0x01,
 };
 
 /* EDTRR */
 enum DMAC_T_BIT {
-#ifdef CONFIG_CPU_SUBTYPE_SH7763
-	EDTRR_TRNS = 0x03,
-#else
-	EDTRR_TRNS = 0x01,
-#endif
+	EDTRR_TRNS_GETHER = 0x03,
+	EDTRR_TRNS_ETHER = 0x01,
 };
 
 /* EDRRR*/
@@ -695,6 +751,7 @@
 	unsigned mpr:1;			/* EtherC have MPR */
 	unsigned tpauser:1;		/* EtherC have TPAUSER */
 	unsigned bculr:1;		/* EtherC have BCULR */
+	unsigned tsu:1;			/* EtherC have TSU */
 	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 */
@@ -704,6 +761,8 @@
 struct sh_eth_private {
 	struct platform_device *pdev;
 	struct sh_eth_cpu_data *cd;
+	const u16 *reg_offset;
+	void __iomem *tsu_addr;
 	dma_addr_t rx_desc_dma;
 	dma_addr_t tx_desc_dma;
 	struct sh_eth_rxdesc *rx_ring;
@@ -722,6 +781,7 @@
 	struct mii_bus *mii_bus;	/* MDIO bus control */
 	struct phy_device *phydev;	/* PHY device control */
 	enum phy_state link;
+	phy_interface_t phy_interface;
 	int msg_enable;
 	int speed;
 	int duplex;
@@ -746,4 +806,32 @@
 #endif
 }
 
+static inline void sh_eth_write(struct net_device *ndev, unsigned long data,
+				int enum_index)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	writel(data, ndev->base_addr + mdp->reg_offset[enum_index]);
+}
+
+static inline unsigned long sh_eth_read(struct net_device *ndev,
+					int enum_index)
+{
+	struct sh_eth_private *mdp = netdev_priv(ndev);
+
+	return readl(ndev->base_addr + mdp->reg_offset[enum_index]);
+}
+
+static inline void sh_eth_tsu_write(struct sh_eth_private *mdp,
+				unsigned long data, int enum_index)
+{
+	writel(data, mdp->tsu_addr + mdp->reg_offset[enum_index]);
+}
+
+static inline unsigned long sh_eth_tsu_read(struct sh_eth_private *mdp,
+					int enum_index)
+{
+	return readl(mdp->tsu_addr + mdp->reg_offset[enum_index]);
+}
+
 #endif	/* #ifndef __SH_ETH_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sis190.c linux-libre-2.6.39-gnu/drivers/net/sis190.c
--- linux-libre-2.6.38-gnu/drivers/net/sis190.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sis190.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 	IntrStatus		= 0x20,
 	IntrMask		= 0x24,
 	IntrControl		= 0x28,
-	IntrTimer		= 0x2c,	// unused (Interupt Timer)
+	IntrTimer		= 0x2c,	// unused (Interrupt Timer)
 	PMControl		= 0x30,	// unused (Power Mgmt Control/Status)
 	rsv2			= 0x34,	// reserved
 	ROMControl		= 0x38,
@@ -234,7 +234,7 @@
 	RxSizeMask	= 0x0000ffff
 	/*
 	 * The asic could apparently do vlan, TSO, jumbo (sis191 only) and
-	 * provide two (unused with Linux) Tx queues. No publically
+	 * provide two (unused with Linux) Tx queues. No publicly
 	 * available documentation alas.
 	 */
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/sis900.c linux-libre-2.6.39-gnu/drivers/net/sis900.c
--- linux-libre-2.6.38-gnu/drivers/net/sis900.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sis900.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,7 +240,8 @@
  *	@net_dev: the net device to get address for
  *
  *	Older SiS900 and friends, use EEPROM to store MAC address.
- *	MAC address is read from read_eeprom() into @net_dev->dev_addr.
+ *	MAC address is read from read_eeprom() into @net_dev->dev_addr and
+ *	@net_dev->perm_addr.
  */
 
 static int __devinit sis900_get_mac_addr(struct pci_dev * pci_dev, struct net_device *net_dev)
@@ -261,6 +262,9 @@
 	for (i = 0; i < 3; i++)
 	        ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
 
+	/* Store MAC Address in perm_addr */
+	memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
 	return 1;
 }
 
@@ -271,7 +275,8 @@
  *
  *	SiS630E model, use APC CMOS RAM to store MAC address.
  *	APC CMOS RAM is accessed through ISA bridge.
- *	MAC address is read into @net_dev->dev_addr.
+ *	MAC address is read into @net_dev->dev_addr and
+ *	@net_dev->perm_addr.
  */
 
 static int __devinit sis630e_get_mac_addr(struct pci_dev * pci_dev,
@@ -296,6 +301,10 @@
 		outb(0x09 + i, 0x70);
 		((u8 *)(net_dev->dev_addr))[i] = inb(0x71);
 	}
+
+	/* Store MAC Address in perm_addr */
+	memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
 	pci_write_config_byte(isa_bridge, 0x48, reg & ~0x40);
 	pci_dev_put(isa_bridge);
 
@@ -310,7 +319,7 @@
  *
  *	SiS635 model, set MAC Reload Bit to load Mac address from APC
  *	to rfdr. rfdr is accessed through rfcr. MAC address is read into
- *	@net_dev->dev_addr.
+ *	@net_dev->dev_addr and @net_dev->perm_addr.
  */
 
 static int __devinit sis635_get_mac_addr(struct pci_dev * pci_dev,
@@ -334,6 +343,9 @@
 		*( ((u16 *)net_dev->dev_addr) + i) = inw(ioaddr + rfdr);
 	}
 
+	/* Store MAC Address in perm_addr */
+	memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
 	/* enable packet filtering */
 	outl(rfcrSave | RFEN, rfcr + ioaddr);
 
@@ -353,7 +365,7 @@
  *	EEDONE signal to refuse EEPROM access by LAN.
  *	The EEPROM map of SiS962 or SiS963 is different to SiS900.
  *	The signature field in SiS962 or SiS963 spec is meaningless.
- *	MAC address is read into @net_dev->dev_addr.
+ *	MAC address is read into @net_dev->dev_addr and @net_dev->perm_addr.
  */
 
 static int __devinit sis96x_get_mac_addr(struct pci_dev * pci_dev,
@@ -372,6 +384,9 @@
 			for (i = 0; i < 3; i++)
 			        ((u16 *)(net_dev->dev_addr))[i] = read_eeprom(ioaddr, i+EEPROMMACAddr);
 
+			/* Store MAC Address in perm_addr */
+			memcpy(net_dev->perm_addr, net_dev->dev_addr, ETH_ALEN);
+
 			outl(EEDONE, ee_addr);
 			return 1;
 		} else {
@@ -495,7 +510,7 @@
 	sis_priv->mii_info.reg_num_mask = 0x1f;
 
 	/* Get Mac address according to the chip revision */
-	pci_read_config_byte(pci_dev, PCI_CLASS_REVISION, &(sis_priv->chipset_rev));
+	sis_priv->chipset_rev = pci_dev->revision;
 	if(netif_msg_probe(sis_priv))
 		printk(KERN_DEBUG "%s: detected revision %2.2x, "
 				"trying to get MAC address...\n",
@@ -532,7 +547,7 @@
 	/* save our host bridge revision */
 	dev = pci_get_device(PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_630, NULL);
 	if (dev) {
-		pci_read_config_byte(dev, PCI_CLASS_REVISION, &sis_priv->host_bridge_rev);
+		sis_priv->host_bridge_rev = dev->revision;
 		pci_dev_put(dev);
 	}
 
@@ -1180,7 +1195,7 @@
  *
  *	630E equalizer workaround rule(Cyrus Huang 08/15)
  *	PHY register 14h(Test)
- *	Bit 14: 0 -- Automatically dectect (default)
+ *	Bit 14: 0 -- Automatically detect (default)
  *		1 -- Manually set Equalizer filter
  *	Bit 13: 0 -- (Default)
  *		1 -- Speed up convergence of equalizer setting
@@ -1192,7 +1207,7 @@
  *	Then set equalizer value, and set Bit 14 to 1, Bit 9 to 0
  *	Link Off:Set Bit 13 to 1, Bit 14 to 0
  *	Calculate Equalizer value:
- *	When Link is ON and Bit 14 is 0, SIS900PHY will auto-dectect proper equalizer value.
+ *	When Link is ON and Bit 14 is 0, SIS900PHY will auto-detect proper equalizer value.
  *	When the equalizer is stable, this value is not a fixed value. It will be within
  *	a small range(eg. 7~9). Then we get a minimum and a maximum value(eg. min=7, max=9)
  *	0 <= max <= 4  --> set equalizer to max
@@ -1723,7 +1738,7 @@
 		rx_size = data_size - CRC_SIZE;
 
 #if defined(CONFIG_VLAN_8021Q) || defined(CONFIG_VLAN_8021Q_MODULE)
-		/* ``TOOLONG'' flag means jumbo packet recived. */
+		/* ``TOOLONG'' flag means jumbo packet received. */
 		if ((rx_status & TOOLONG) && data_size <= MAX_FRAME_SIZE)
 			rx_status &= (~ ((unsigned int)TOOLONG));
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/ess.c linux-libre-2.6.39-gnu/drivers/net/skfp/ess.c
--- linux-libre-2.6.38-gnu/drivers/net/skfp/ess.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/ess.c	2011-05-19 00:06:34.000000000 -0400
@@ -241,7 +241,7 @@
 			!= SMT_RDF_SUCCESS) ||
 			(sm->smt_tid != smc->ess.alloc_trans_id)) {
 
-			DB_ESS("ESS: Allocation Responce not accepted\n",0,0) ;
+			DB_ESS("ESS: Allocation Response not accepted\n",0,0) ;
 			return fs;
 		}
 
@@ -393,7 +393,7 @@
 	 *		      |	 T-NEG	|
 	 *		       -       -
  	 *
-	 * T-NEG is discribed by the equation:
+	 * T-NEG is described by the equation:
 	 *
 	 *		     (-) fddiMACT-NEG
 	 *	T-NEG =	    -------------------
@@ -479,7 +479,7 @@
 	void			*p ;
 
 	/*
-	 * get and initialize the responce frame
+	 * get and initialize the response frame
 	 */
 	if (sba_cmd == CHANGE_ALLOCATION) {
 		if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REPLY,
@@ -578,7 +578,7 @@
 	}
 	
 	/*
-	 * get and initialize the responce frame
+	 * get and initialize the response frame
 	 */
 	if (!(mb=smt_build_frame(smc,SMT_RAF,SMT_REQUEST,
 			sizeof(struct smt_sba_alc_req))))
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/fplustm.c linux-libre-2.6.39-gnu/drivers/net/skfp/fplustm.c
--- linux-libre-2.6.38-gnu/drivers/net/skfp/fplustm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/fplustm.c	2011-05-19 00:06:34.000000000 -0400
@@ -340,7 +340,7 @@
 	outpw(FM_A(FM_LCNTR),0) ;
 	outpw(FM_A(FM_ECNTR),0) ;
 	/*
-	 * clear internal error counter stucture
+	 * clear internal error counter structure
 	 */
 	ec = (u_long *)&smc->hw.fp.err_stats ;
 	for (i = (sizeof(struct err_st)/sizeof(long)) ; i ; i--)
@@ -1262,8 +1262,8 @@
 
 Para	mode =	1	RX_ENABLE_ALLMULTI	enable all multicasts
 		2	RX_DISABLE_ALLMULTI	disable "enable all multicasts"
-		3	RX_ENABLE_PROMISC	enable promiscous
-		4	RX_DISABLE_PROMISC	disable promiscous
+		3	RX_ENABLE_PROMISC	enable promiscuous
+		4	RX_DISABLE_PROMISC	disable promiscuous
 		5	RX_ENABLE_NSA		enable reception of NSA frames
 		6	RX_DISABLE_NSA		disable reception of NSA frames
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/h/cmtdef.h linux-libre-2.6.39-gnu/drivers/net/skfp/h/cmtdef.h
--- linux-libre-2.6.38-gnu/drivers/net/skfp/h/cmtdef.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/h/cmtdef.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,7 @@
 
 /*
  * implementation specific constants
- * MODIIFY THE FOLLWOING THREE DEFINES
+ * MODIIFY THE FOLLOWING THREE DEFINES
  */
 #define AMDPLC			/* if Amd PLC chip used */
 #ifdef	CONC
@@ -456,7 +456,7 @@
 	u_long soft_err ;		/* error counter */
 	u_long parity_err ;		/* error counter */
 	u_long ebuf_err ;		/* error counter */
-	u_long ebuf_cont ;		/* continous error counter */
+	u_long ebuf_cont ;		/* continuous error counter */
 	u_long phyinv ;			/* error counter */
 	u_long vsym_ctr ;		/* error counter */
 	u_long mini_ctr ;		/* error counter */
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/h/fplustm.h linux-libre-2.6.39-gnu/drivers/net/skfp/h/fplustm.h
--- linux-libre-2.6.38-gnu/drivers/net/skfp/h/fplustm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/h/fplustm.h	2011-05-19 00:06:34.000000000 -0400
@@ -237,8 +237,8 @@
  */
 #define RX_ENABLE_ALLMULTI	1	/* enable all multicasts */
 #define RX_DISABLE_ALLMULTI	2	/* disable "enable all multicasts" */
-#define RX_ENABLE_PROMISC	3	/* enable promiscous */
-#define RX_DISABLE_PROMISC	4	/* disable promiscous */
+#define RX_ENABLE_PROMISC	3	/* enable promiscuous */
+#define RX_DISABLE_PROMISC	4	/* disable promiscuous */
 #define RX_ENABLE_NSA		5	/* enable reception of NSA frames */
 #define RX_DISABLE_NSA		6	/* disable reception of NSA frames */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/h/smc.h linux-libre-2.6.39-gnu/drivers/net/skfp/h/smc.h
--- linux-libre-2.6.38-gnu/drivers/net/skfp/h/smc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/h/smc.h	2011-05-19 00:06:34.000000000 -0400
@@ -388,7 +388,7 @@
 	u_long	rmt_t_poll ;		/* RMT : claim/beacon poller */
 	u_long  rmt_dup_mac_behavior ;  /* Flag for the beavior of SMT if
 					 * a Duplicate MAC Address was detected.
-					 * FALSE: SMT will leave finaly the ring
+					 * FALSE: SMT will leave finally the ring
 					 * TRUE:  SMT will reinstert into the ring
 					 */
 	u_long	mac_d_max ;		/* MAC : D_Max timer value */
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/h/smt.h linux-libre-2.6.39-gnu/drivers/net/skfp/h/smt.h
--- linux-libre-2.6.38-gnu/drivers/net/skfp/h/smt.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/h/smt.h	2011-05-19 00:06:34.000000000 -0400
@@ -793,7 +793,7 @@
 } ;
 
 /*
- * SBA Request Allocation Responce Frame
+ * SBA Request Allocation Response Frame
  */
 struct smt_sba_alc_res {
 	struct smt_header	smt ;		/* generic header */
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/h/supern_2.h linux-libre-2.6.39-gnu/drivers/net/skfp/h/supern_2.h
--- linux-libre-2.6.38-gnu/drivers/net/skfp/h/supern_2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/h/supern_2.h	2011-05-19 00:06:34.000000000 -0400
@@ -14,7 +14,7 @@
 
 /*
 	defines for AMD Supernet II chip set
-	the chips are refered to as
+	the chips are referred to as
 		FPLUS	Formac Plus
 		PLC	Physical Layer
 
@@ -386,7 +386,7 @@
 #define	FM_MDISRCV	(4<<8)		/* disable receive function */
 #define	FM_MRES0	(5<<8)		/* reserve */
 #define	FM_MLIMPROM	(6<<8)		/* limited-promiscuous mode */
-#define FM_MPROMISCOUS	(7<<8)		/* address detection : promiscous */
+#define FM_MPROMISCOUS	(7<<8)		/* address detection : promiscuous */
 
 #define FM_SELSA	0x0800		/* select-short-address bit */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/hwmtm.c linux-libre-2.6.39-gnu/drivers/net/skfp/hwmtm.c
--- linux-libre-2.6.38-gnu/drivers/net/skfp/hwmtm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/hwmtm.c	2011-05-19 00:06:34.000000000 -0400
@@ -691,7 +691,7 @@
  *		interrupt service routine, handles the interrupt requests
  *		generated by the FDDI adapter.
  *
- * NOTE:	The operating system dependent module must garantee that the
+ * NOTE:	The operating system dependent module must guarantee that the
  *		interrupts of the adapter are disabled when it calls fddi_isr.
  *
  *	About the USE_BREAK_ISR mechanismn:
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/Makefile linux-libre-2.6.39-gnu/drivers/net/skfp/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/skfp/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -17,4 +17,4 @@
 #   projects. To keep the source common for all those drivers (and
 #   thus simplify fixes to it), please do not clean it up!
 
-EXTRA_CFLAGS += -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes 
+ccflags-y := -Idrivers/net/skfp -DPCI -DMEM_MAPPED_IO -Wno-strict-prototypes
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/pcmplc.c linux-libre-2.6.39-gnu/drivers/net/skfp/pcmplc.c
--- linux-libre-2.6.38-gnu/drivers/net/skfp/pcmplc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/pcmplc.c	2011-05-19 00:06:34.000000000 -0400
@@ -1680,7 +1680,7 @@
 			 * Prevent counter from being wrapped after
 			 * hanging years in that interrupt.
 			 */
-			plc->ebuf_cont++ ;	/* Ebuf continous error */
+			plc->ebuf_cont++ ;	/* Ebuf continuous error */
 		}
 
 #ifdef	SUPERNET_3
@@ -1717,8 +1717,8 @@
 		}
 #endif	/* SUPERNET_3 */
 	} else {
-		/* Reset the continous error variable */
-		plc->ebuf_cont = 0 ;	/* reset Ebuf continous error */
+		/* Reset the continuous error variable */
+		plc->ebuf_cont = 0 ;	/* reset Ebuf continuous error */
 	}
 	if (cmd & PL_PHYINV) {		/* physical layer invalid signal */
 		plc->phyinv++ ;
diff -druN linux-libre-2.6.38-gnu/drivers/net/skfp/smt.c linux-libre-2.6.39-gnu/drivers/net/skfp/smt.c
--- linux-libre-2.6.38-gnu/drivers/net/skfp/smt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skfp/smt.c	2011-05-19 00:06:34.000000000 -0400
@@ -219,7 +219,7 @@
 
 	/*
 	 * Only when ring is up we will have a token count. The
-	 * flag is unfortunatly a single instance value. This
+	 * flag is unfortunately a single instance value. This
 	 * doesn't matter now, because we currently have only
 	 * one MAC instance.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/skge.h linux-libre-2.6.39-gnu/drivers/net/skge.h
--- linux-libre-2.6.38-gnu/drivers/net/skge.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/skge.h	2011-05-19 00:06:34.000000000 -0400
@@ -1038,7 +1038,7 @@
 
 	PHY_ST_PRE_SUP	= 1<<6, /* Bit  6:	Preamble Suppression */
 	PHY_ST_AN_OVER	= 1<<5, /* Bit  5:	Auto-Negotiation Over */
-	PHY_ST_REM_FLT	= 1<<4, /* Bit  4:	Remote Fault Condition Occured */
+	PHY_ST_REM_FLT	= 1<<4, /* Bit  4:	Remote Fault Condition Occurred */
 	PHY_ST_AN_CAP	= 1<<3, /* Bit  3:	Auto-Negotiation Capability */
 	PHY_ST_LSYNC	= 1<<2, /* Bit  2:	Link Synchronized */
 	PHY_ST_JAB_DET	= 1<<1, /* Bit  1:	Jabber Detected */
@@ -1721,8 +1721,8 @@
 	GM_GPSR_LINK_UP		= 1<<12, /* Bit 12:	Link Up Status */
 	GM_GPSR_PAUSE		= 1<<11, /* Bit 11:	Pause State */
 	GM_GPSR_TX_ACTIVE	= 1<<10, /* Bit 10:	Tx in Progress */
-	GM_GPSR_EXC_COL		= 1<<9,	/* Bit  9:	Excessive Collisions Occured */
-	GM_GPSR_LAT_COL		= 1<<8,	/* Bit  8:	Late Collisions Occured */
+	GM_GPSR_EXC_COL		= 1<<9,	/* Bit  9:	Excessive Collisions Occurred */
+	GM_GPSR_LAT_COL		= 1<<8,	/* Bit  8:	Late Collisions Occurred */
 
 	GM_GPSR_PHY_ST_CH	= 1<<5,	/* Bit  5:	PHY Status Change */
 	GM_GPSR_GIG_SPEED	= 1<<4,	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
@@ -2227,7 +2227,7 @@
 	XM_ST_BC	= 1<<7,		/* Bit  7:	Broadcast packet */
 	XM_ST_MC	= 1<<6,		/* Bit  6:	Multicast packet */
 	XM_ST_UC	= 1<<5,		/* Bit  5:	Unicast packet */
-	XM_ST_TX_UR	= 1<<4,		/* Bit  4:	FIFO Underrun occured */
+	XM_ST_TX_UR	= 1<<4,		/* Bit  4:	FIFO Underrun occurred */
 	XM_ST_CS_ERR	= 1<<3,		/* Bit  3:	Carrier Sense Error */
 	XM_ST_LAT_COL	= 1<<2,		/* Bit  2:	Late Collision Error */
 	XM_ST_MUL_COL	= 1<<1,		/* Bit  1:	Multiple Collisions */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sky2.c linux-libre-2.6.39-gnu/drivers/net/sky2.c
--- linux-libre-2.6.38-gnu/drivers/net/sky2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sky2.c	2011-05-19 00:06:34.000000000 -0400
@@ -932,7 +932,7 @@
 	sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
 	sky2_write16(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_OPER_ON);
 
-	/* On chips without ram buffer, pause is controled by MAC level */
+	/* On chips without ram buffer, pause is controlled by MAC level */
 	if (!(hw->flags & SKY2_HW_RAM_BUFFER)) {
 		/* Pause threshold is scaled by 8 in bytes */
 		if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
@@ -3255,7 +3255,7 @@
 
 /* Take device down (offline).
  * Equivalent to doing dev_stop() but this does not
- * inform upper layers of the transistion.
+ * inform upper layers of the transition.
  */
 static void sky2_detach(struct net_device *dev)
 {
@@ -4983,7 +4983,7 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int sky2_resume(struct device *dev)
 {
 	struct pci_dev *pdev = to_pci_dev(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sky2.h linux-libre-2.6.39-gnu/drivers/net/sky2.h
--- linux-libre-2.6.38-gnu/drivers/net/sky2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sky2.h	2011-05-19 00:06:34.000000000 -0400
@@ -1194,7 +1194,7 @@
 
 	PHY_ST_PRE_SUP	= 1<<6, /* Bit  6:	Preamble Suppression */
 	PHY_ST_AN_OVER	= 1<<5, /* Bit  5:	Auto-Negotiation Over */
-	PHY_ST_REM_FLT	= 1<<4, /* Bit  4:	Remote Fault Condition Occured */
+	PHY_ST_REM_FLT	= 1<<4, /* Bit  4:	Remote Fault Condition Occurred */
 	PHY_ST_AN_CAP	= 1<<3, /* Bit  3:	Auto-Negotiation Capability */
 	PHY_ST_LSYNC	= 1<<2, /* Bit  2:	Link Synchronized */
 	PHY_ST_JAB_DET	= 1<<1, /* Bit  1:	Jabber Detected */
@@ -1725,8 +1725,8 @@
 	GM_GPSR_LINK_UP		= 1<<12, /* Bit 12:	Link Up Status */
 	GM_GPSR_PAUSE		= 1<<11, /* Bit 11:	Pause State */
 	GM_GPSR_TX_ACTIVE	= 1<<10, /* Bit 10:	Tx in Progress */
-	GM_GPSR_EXC_COL		= 1<<9,	/* Bit  9:	Excessive Collisions Occured */
-	GM_GPSR_LAT_COL		= 1<<8,	/* Bit  8:	Late Collisions Occured */
+	GM_GPSR_EXC_COL		= 1<<9,	/* Bit  9:	Excessive Collisions Occurred */
+	GM_GPSR_LAT_COL		= 1<<8,	/* Bit  8:	Late Collisions Occurred */
 
 	GM_GPSR_PHY_ST_CH	= 1<<5,	/* Bit  5:	PHY Status Change */
 	GM_GPSR_GIG_SPEED	= 1<<4,	/* Bit  4:	Gigabit Speed (1 = 1000 Mbps) */
diff -druN linux-libre-2.6.38-gnu/drivers/net/slip.c linux-libre-2.6.39-gnu/drivers/net/slip.c
--- linux-libre-2.6.38-gnu/drivers/net/slip.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/slip.c	2011-05-19 00:06:34.000000000 -0400
@@ -853,7 +853,9 @@
 	/* Done.  We have linked the TTY line to a channel. */
 	rtnl_unlock();
 	tty->receive_room = 65536;	/* We don't flow control */
-	return sl->dev->base_addr;
+
+	/* TTY layer expects 0 on success */
+	return 0;
 
 err_free_bufs:
 	sl_free_bufs(sl);
diff -druN linux-libre-2.6.38-gnu/drivers/net/smc91x.c linux-libre-2.6.39-gnu/drivers/net/smc91x.c
--- linux-libre-2.6.38-gnu/drivers/net/smc91x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/smc91x.c	2011-05-19 00:06:34.000000000 -0400
@@ -81,6 +81,7 @@
 #include <linux/ethtool.h>
 #include <linux/mii.h>
 #include <linux/workqueue.h>
+#include <linux/of.h>
 
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
@@ -2394,6 +2395,15 @@
 	return 0;
 }
 
+#ifdef CONFIG_OF
+static const struct of_device_id smc91x_match[] = {
+	{ .compatible = "smsc,lan91c94", },
+	{ .compatible = "smsc,lan91c111", },
+	{},
+}
+MODULE_DEVICE_TABLE(of, smc91x_match);
+#endif
+
 static struct dev_pm_ops smc_drv_pm_ops = {
 	.suspend	= smc_drv_suspend,
 	.resume		= smc_drv_resume,
@@ -2406,6 +2416,9 @@
 		.name	= CARDNAME,
 		.owner	= THIS_MODULE,
 		.pm	= &smc_drv_pm_ops,
+#ifdef CONFIG_OF
+		.of_match_table = smc91x_match,
+#endif
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/smc91x.h linux-libre-2.6.39-gnu/drivers/net/smc91x.h
--- linux-libre-2.6.38-gnu/drivers/net/smc91x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/smc91x.h	2011-05-19 00:06:34.000000000 -0400
@@ -206,68 +206,6 @@
 #define RPC_LSA_DEFAULT		RPC_LED_TX_RX
 #define RPC_LSB_DEFAULT		RPC_LED_100_10
 
-#elif   defined(CONFIG_MACH_LPD79520) ||	\
-	defined(CONFIG_MACH_LPD7A400) ||	\
-	defined(CONFIG_MACH_LPD7A404)
-
-/* The LPD7X_IOBARRIER is necessary to overcome a mismatch between the
- * way that the CPU handles chip selects and the way that the SMC chip
- * expects the chip select to operate.  Refer to
- * Documentation/arm/Sharp-LH/IOBarrier for details.  The read from
- * IOBARRIER is a byte, in order that we read the least-common
- * denominator.  It would be wasteful to read 32 bits from an 8-bit
- * accessible region.
- *
- * There is no explicit protection against interrupts intervening
- * between the writew and the IOBARRIER.  In SMC ISR there is a
- * preamble that performs an IOBARRIER in the extremely unlikely event
- * that the driver interrupts itself between a writew to the chip an
- * the IOBARRIER that follows *and* the cache is large enough that the
- * first off-chip access while handing the interrupt is to the SMC
- * chip.  Other devices in the same address space as the SMC chip must
- * be aware of the potential for trouble and perform a similar
- * IOBARRIER on entry to their ISR.
- */
-
-#include <mach/constants.h>	/* IOBARRIER_VIRT */
-
-#define SMC_CAN_USE_8BIT	0
-#define SMC_CAN_USE_16BIT	1
-#define SMC_CAN_USE_32BIT	0
-#define SMC_NOWAIT		0
-#define LPD7X_IOBARRIER		readb (IOBARRIER_VIRT)
-
-#define SMC_inw(a,r)\
-   ({ unsigned short v = readw ((void*) ((a) + (r))); LPD7X_IOBARRIER; v; })
-#define SMC_outw(v,a,r)	  ({ writew ((v), (a) + (r)); LPD7X_IOBARRIER; })
-
-#define SMC_insw		LPD7_SMC_insw
-static inline void LPD7_SMC_insw (unsigned char* a, int r,
-				  unsigned char* p, int l)
-{
-	unsigned short* ps = (unsigned short*) p;
-	while (l-- > 0) {
-		*ps++ = readw (a + r);
-		LPD7X_IOBARRIER;
-	}
-}
-
-#define SMC_outsw		LPD7_SMC_outsw
-static inline void LPD7_SMC_outsw (unsigned char* a, int r,
-				   unsigned char* p, int l)
-{
-	unsigned short* ps = (unsigned short*) p;
-	while (l-- > 0) {
-		writew (*ps++, a + r);
-		LPD7X_IOBARRIER;
-	}
-}
-
-#define SMC_INTERRUPT_PREAMBLE	LPD7X_IOBARRIER
-
-#define RPC_LSA_DEFAULT		RPC_LED_TX_RX
-#define RPC_LSB_DEFAULT		RPC_LED_100_10
-
 #elif	defined(CONFIG_ARCH_VERSATILE)
 
 #define SMC_CAN_USE_8BIT	1
@@ -983,7 +921,7 @@
  * Hack Alert: Some setups just can't write 8 or 16 bits reliably when not
  * aligned to a 32 bit boundary.  I tell you that does exist!
  * Fortunately the affected register accesses can be easily worked around
- * since we can write zeroes to the preceeding 16 bits without adverse
+ * since we can write zeroes to the preceding 16 bits without adverse
  * effects and use a 32-bit access.
  *
  * Enforce it on any 32-bit capable setup for now.
diff -druN linux-libre-2.6.38-gnu/drivers/net/smsc911x.c linux-libre-2.6.39-gnu/drivers/net/smsc911x.c
--- linux-libre-2.6.38-gnu/drivers/net/smsc911x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/smsc911x.c	2011-05-19 00:06:34.000000000 -0400
@@ -791,8 +791,8 @@
 		return -ENODEV;
 	}
 
-	SMSC_TRACE(PROBE, "PHY %d: addr %d, phy_id 0x%08X",
-			phy_addr, phydev->addr, phydev->phy_id);
+	SMSC_TRACE(PROBE, "PHY: addr %d, phy_id 0x%08X",
+			phydev->addr, phydev->phy_id);
 
 	ret = phy_connect_direct(dev, phydev,
 			&smsc911x_phy_adjust_link, 0,
@@ -1669,7 +1669,7 @@
 	}
 
 	if (e2cmd & E2P_CMD_EPC_TIMEOUT_) {
-		SMSC_TRACE(DRV, "Error occured during eeprom operation");
+		SMSC_TRACE(DRV, "Error occurred during eeprom operation");
 		return -EINVAL;
 	}
 
@@ -1818,6 +1818,7 @@
 	SMSC_TRACE(PROBE, "PHY will be autodetected.");
 
 	spin_lock_init(&pdata->dev_lock);
+	spin_lock_init(&pdata->mac_lock);
 
 	if (pdata->ioaddr == 0) {
 		SMSC_WARNING(PROBE, "pdata->ioaddr: 0x00000000");
@@ -1895,8 +1896,11 @@
 	/* workaround for platforms without an eeprom, where the mac address
 	 * is stored elsewhere and set by the bootloader.  This saves the
 	 * mac address before resetting the device */
-	if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS)
+	if (pdata->config.flags & SMSC911X_SAVE_MAC_ADDRESS) {
+		spin_lock_irq(&pdata->mac_lock);
 		smsc911x_read_mac_address(dev);
+		spin_unlock_irq(&pdata->mac_lock);
+	}
 
 	/* Reset the LAN911x */
 	if (smsc911x_soft_reset(pdata))
@@ -2059,8 +2063,6 @@
 		SMSC_TRACE(PROBE, "Network interface: \"%s\"", dev->name);
 	}
 
-	spin_lock_init(&pdata->mac_lock);
-
 	retval = smsc911x_mii_init(pdev, dev);
 	if (retval) {
 		SMSC_WARNING(PROBE,
diff -druN linux-libre-2.6.38-gnu/drivers/net/smsc9420.c linux-libre-2.6.39-gnu/drivers/net/smsc9420.c
--- linux-libre-2.6.38-gnu/drivers/net/smsc9420.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/smsc9420.c	2011-05-19 00:06:34.000000000 -0400
@@ -364,7 +364,7 @@
 	}
 
 	if (e2cmd & E2P_CMD_EPC_TIMEOUT_) {
-		smsc_info(HW, "Error occured during eeprom operation");
+		smsc_info(HW, "Error occurred during eeprom operation");
 		return -EINVAL;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/starfire.c linux-libre-2.6.39-gnu/drivers/net/starfire.c
--- linux-libre-2.6.38-gnu/drivers/net/starfire.c	2012-03-24 01:06:23.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/starfire.c	2012-03-24 03:29:58.000000000 -0400
@@ -144,11 +144,7 @@
 /* Time in jiffies before concluding the transmitter is hung. */
 #define TX_TIMEOUT	(2 * HZ)
 
-/*
- * This SUCKS.
- * We need a much better method to determine if dma_addr_t is 64-bit.
- */
-#if (defined(__i386__) && defined(CONFIG_HIGHMEM64G)) || defined(__x86_64__) || defined (__ia64__) || defined(__alpha__) || (defined(CONFIG_MIPS) && ((defined(CONFIG_HIGHMEM) && defined(CONFIG_64BIT_PHYS_ADDR)) || defined(CONFIG_64BIT))) || (defined(__powerpc64__) || defined(CONFIG_PHYS_64BIT))
+#ifdef CONFIG_ARCH_DMA_ADDR_T_64BIT
 /* 64-bit dma_addr_t */
 #define ADDR_64BITS	/* This chip uses 64 bit addresses. */
 #define netdrv_addr_t __le64
diff -druN linux-libre-2.6.38-gnu/drivers/net/stmmac/dwmac_lib.c linux-libre-2.6.39-gnu/drivers/net/stmmac/dwmac_lib.c
--- linux-libre-2.6.38-gnu/drivers/net/stmmac/dwmac_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/stmmac/dwmac_lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,9 +26,9 @@
 
 #undef DWMAC_DMA_DEBUG
 #ifdef DWMAC_DMA_DEBUG
-#define DBG(fmt, args...)  printk(fmt, ## args)
+#define DWMAC_LIB_DBG(fmt, args...)  printk(fmt, ## args)
 #else
-#define DBG(fmt, args...)  do { } while (0)
+#define DWMAC_LIB_DBG(fmt, args...)  do { } while (0)
 #endif
 
 /* CSR1 enables the transmit DMA to check for new descriptor */
@@ -152,7 +152,7 @@
 	/* read the status register (CSR5) */
 	u32 intr_status = readl(ioaddr + DMA_STATUS);
 
-	DBG(INFO, "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
+	DWMAC_LIB_DBG(KERN_INFO "%s: [CSR5: 0x%08x]\n", __func__, intr_status);
 #ifdef DWMAC_DMA_DEBUG
 	/* It displays the DMA process states (CSR5 register) */
 	show_tx_process_state(intr_status);
@@ -160,43 +160,43 @@
 #endif
 	/* ABNORMAL interrupts */
 	if (unlikely(intr_status & DMA_STATUS_AIS)) {
-		DBG(INFO, "CSR5[15] DMA ABNORMAL IRQ: ");
+		DWMAC_LIB_DBG(KERN_INFO "CSR5[15] DMA ABNORMAL IRQ: ");
 		if (unlikely(intr_status & DMA_STATUS_UNF)) {
-			DBG(INFO, "transmit underflow\n");
+			DWMAC_LIB_DBG(KERN_INFO "transmit underflow\n");
 			ret = tx_hard_error_bump_tc;
 			x->tx_undeflow_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_TJT)) {
-			DBG(INFO, "transmit jabber\n");
+			DWMAC_LIB_DBG(KERN_INFO "transmit jabber\n");
 			x->tx_jabber_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_OVF)) {
-			DBG(INFO, "recv overflow\n");
+			DWMAC_LIB_DBG(KERN_INFO "recv overflow\n");
 			x->rx_overflow_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_RU)) {
-			DBG(INFO, "receive buffer unavailable\n");
+			DWMAC_LIB_DBG(KERN_INFO "receive buffer unavailable\n");
 			x->rx_buf_unav_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_RPS)) {
-			DBG(INFO, "receive process stopped\n");
+			DWMAC_LIB_DBG(KERN_INFO "receive process stopped\n");
 			x->rx_process_stopped_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_RWT)) {
-			DBG(INFO, "receive watchdog\n");
+			DWMAC_LIB_DBG(KERN_INFO "receive watchdog\n");
 			x->rx_watchdog_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_ETI)) {
-			DBG(INFO, "transmit early interrupt\n");
+			DWMAC_LIB_DBG(KERN_INFO "transmit early interrupt\n");
 			x->tx_early_irq++;
 		}
 		if (unlikely(intr_status & DMA_STATUS_TPS)) {
-			DBG(INFO, "transmit process stopped\n");
+			DWMAC_LIB_DBG(KERN_INFO "transmit process stopped\n");
 			x->tx_process_stopped_irq++;
 			ret = tx_hard_error;
 		}
 		if (unlikely(intr_status & DMA_STATUS_FBI)) {
-			DBG(INFO, "fatal bus error\n");
+			DWMAC_LIB_DBG(KERN_INFO "fatal bus error\n");
 			x->fatal_bus_error_irq++;
 			ret = tx_hard_error;
 		}
@@ -215,7 +215,7 @@
 	/* Clear the interrupt by writing a logic 1 to the CSR5[15-0] */
 	writel((intr_status & 0x1ffff), ioaddr + DMA_STATUS);
 
-	DBG(INFO, "\n\n");
+	DWMAC_LIB_DBG(KERN_INFO "\n\n");
 	return ret;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/stmmac/norm_desc.c linux-libre-2.6.39-gnu/drivers/net/stmmac/norm_desc.c
--- linux-libre-2.6.38-gnu/drivers/net/stmmac/norm_desc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/stmmac/norm_desc.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,7 @@
 
 /* This function verifies if each incoming frame has some errors
  * and, if required, updates the multicast statistics.
- * In case of success, it returns csum_none becasue the device
+ * In case of success, it returns csum_none because the device
  * is not able to compute the csum in HW. */
 static int ndesc_get_rx_status(void *data, struct stmmac_extra_stats *x,
 			       struct dma_desc *p)
diff -druN linux-libre-2.6.38-gnu/drivers/net/stmmac/stmmac_main.c linux-libre-2.6.39-gnu/drivers/net/stmmac/stmmac_main.c
--- linux-libre-2.6.38-gnu/drivers/net/stmmac/stmmac_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/stmmac/stmmac_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -750,7 +750,6 @@
 			priv->hw->dma->dma_mode(priv->ioaddr, tc, SF_DMA_MODE);
 			priv->xstats.threshold = tc;
 		}
-		stmmac_tx_err(priv);
 	} else if (unlikely(status == tx_hard_error))
 		stmmac_tx_err(priv);
 }
@@ -781,21 +780,6 @@
 
 	stmmac_verify_args();
 
-	ret = stmmac_init_phy(dev);
-	if (unlikely(ret)) {
-		pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
-		return ret;
-	}
-
-	/* Request the IRQ lines */
-	ret = request_irq(dev->irq, stmmac_interrupt,
-			  IRQF_SHARED, dev->name, dev);
-	if (unlikely(ret < 0)) {
-		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
-		       __func__, dev->irq, ret);
-		return ret;
-	}
-
 #ifdef CONFIG_STMMAC_TIMER
 	priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
 	if (unlikely(priv->tm == NULL)) {
@@ -814,6 +798,11 @@
 	} else
 		priv->tm->enable = 1;
 #endif
+	ret = stmmac_init_phy(dev);
+	if (unlikely(ret)) {
+		pr_err("%s: Cannot attach to PHY (error: %d)\n", __func__, ret);
+		goto open_error;
+	}
 
 	/* Create and initialize the TX/RX descriptors chains. */
 	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);
@@ -822,12 +811,11 @@
 	init_dma_desc_rings(dev);
 
 	/* DMA initialization and SW reset */
-	if (unlikely(priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
-					 priv->dma_tx_phy,
-					 priv->dma_rx_phy) < 0)) {
-
+	ret = priv->hw->dma->init(priv->ioaddr, priv->plat->pbl,
+				  priv->dma_tx_phy, priv->dma_rx_phy);
+	if (ret < 0) {
 		pr_err("%s: DMA initialization failed\n", __func__);
-		return -1;
+		goto open_error;
 	}
 
 	/* Copy the MAC addr into the HW  */
@@ -848,6 +836,15 @@
 	writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
 	writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
 
+	/* Request the IRQ lines */
+	ret = request_irq(dev->irq, stmmac_interrupt,
+			 IRQF_SHARED, dev->name, dev);
+	if (unlikely(ret < 0)) {
+		pr_err("%s: ERROR: allocating the IRQ %d (error: %d)\n",
+		       __func__, dev->irq, ret);
+		goto open_error;
+	}
+
 	/* Enable the MAC Rx/Tx */
 	stmmac_enable_mac(priv->ioaddr);
 
@@ -878,7 +875,17 @@
 	napi_enable(&priv->napi);
 	skb_queue_head_init(&priv->rx_recycle);
 	netif_start_queue(dev);
+
 	return 0;
+
+open_error:
+#ifdef CONFIG_STMMAC_TIMER
+	kfree(priv->tm);
+#endif
+	if (priv->phydev)
+		phy_disconnect(priv->phydev);
+
+	return ret;
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/net/sunbmac.c linux-libre-2.6.39-gnu/drivers/net/sunbmac.c
--- linux-libre-2.6.38-gnu/drivers/net/sunbmac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sunbmac.c	2011-05-19 00:06:34.000000000 -0400
@@ -1242,8 +1242,7 @@
 /* QEC can be the parent of either QuadEthernet or a BigMAC.  We want
  * the latter.
  */
-static int __devinit bigmac_sbus_probe(struct platform_device *op,
-				       const struct of_device_id *match)
+static int __devinit bigmac_sbus_probe(struct platform_device *op)
 {
 	struct device *parent = op->dev.parent;
 	struct platform_device *qec_op;
@@ -1289,7 +1288,7 @@
 
 MODULE_DEVICE_TABLE(of, bigmac_sbus_match);
 
-static struct of_platform_driver bigmac_sbus_driver = {
+static struct platform_driver bigmac_sbus_driver = {
 	.driver = {
 		.name = "sunbmac",
 		.owner = THIS_MODULE,
@@ -1301,12 +1300,12 @@
 
 static int __init bigmac_init(void)
 {
-	return of_register_platform_driver(&bigmac_sbus_driver);
+	return platform_driver_register(&bigmac_sbus_driver);
 }
 
 static void __exit bigmac_exit(void)
 {
-	of_unregister_platform_driver(&bigmac_sbus_driver);
+	platform_driver_unregister(&bigmac_sbus_driver);
 }
 
 module_init(bigmac_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sunbmac.h linux-libre-2.6.39-gnu/drivers/net/sunbmac.h
--- linux-libre-2.6.38-gnu/drivers/net/sunbmac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sunbmac.h	2011-05-19 00:06:34.000000000 -0400
@@ -185,7 +185,7 @@
 #define BIGMAC_RXCFG_ENABLE    0x00000001 /* Enable the receiver                      */
 #define BIGMAC_RXCFG_FIFO      0x0000000e /* Default rx fthresh...                    */
 #define BIGMAC_RXCFG_PSTRIP    0x00000020 /* Pad byte strip enable                    */
-#define BIGMAC_RXCFG_PMISC     0x00000040 /* Enable promiscous mode                   */
+#define BIGMAC_RXCFG_PMISC     0x00000040 /* Enable promiscuous mode                   */
 #define BIGMAC_RXCFG_DERR      0x00000080 /* Disable error checking                   */
 #define BIGMAC_RXCFG_DCRCS     0x00000100 /* Disable CRC stripping                    */
 #define BIGMAC_RXCFG_ME        0x00000200 /* Receive packets addressed to me          */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sungem.c linux-libre-2.6.39-gnu/drivers/net/sungem.c
--- linux-libre-2.6.38-gnu/drivers/net/sungem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sungem.c	2011-05-19 00:06:34.000000000 -0400
@@ -320,28 +320,28 @@
 
 	if (txmac_stat & MAC_TXSTAT_URUN) {
 		netdev_err(dev, "TX MAC xmit underrun\n");
-		gp->net_stats.tx_fifo_errors++;
+		dev->stats.tx_fifo_errors++;
 	}
 
 	if (txmac_stat & MAC_TXSTAT_MPE) {
 		netdev_err(dev, "TX MAC max packet size error\n");
-		gp->net_stats.tx_errors++;
+		dev->stats.tx_errors++;
 	}
 
 	/* The rest are all cases of one of the 16-bit TX
 	 * counters expiring.
 	 */
 	if (txmac_stat & MAC_TXSTAT_NCE)
-		gp->net_stats.collisions += 0x10000;
+		dev->stats.collisions += 0x10000;
 
 	if (txmac_stat & MAC_TXSTAT_ECE) {
-		gp->net_stats.tx_aborted_errors += 0x10000;
-		gp->net_stats.collisions += 0x10000;
+		dev->stats.tx_aborted_errors += 0x10000;
+		dev->stats.collisions += 0x10000;
 	}
 
 	if (txmac_stat & MAC_TXSTAT_LCE) {
-		gp->net_stats.tx_aborted_errors += 0x10000;
-		gp->net_stats.collisions += 0x10000;
+		dev->stats.tx_aborted_errors += 0x10000;
+		dev->stats.collisions += 0x10000;
 	}
 
 	/* We do not keep track of MAC_TXSTAT_FCE and
@@ -469,20 +469,20 @@
 		u32 smac = readl(gp->regs + MAC_SMACHINE);
 
 		netdev_err(dev, "RX MAC fifo overflow smac[%08x]\n", smac);
-		gp->net_stats.rx_over_errors++;
-		gp->net_stats.rx_fifo_errors++;
+		dev->stats.rx_over_errors++;
+		dev->stats.rx_fifo_errors++;
 
 		ret = gem_rxmac_reset(gp);
 	}
 
 	if (rxmac_stat & MAC_RXSTAT_ACE)
-		gp->net_stats.rx_frame_errors += 0x10000;
+		dev->stats.rx_frame_errors += 0x10000;
 
 	if (rxmac_stat & MAC_RXSTAT_CCE)
-		gp->net_stats.rx_crc_errors += 0x10000;
+		dev->stats.rx_crc_errors += 0x10000;
 
 	if (rxmac_stat & MAC_RXSTAT_LCE)
-		gp->net_stats.rx_length_errors += 0x10000;
+		dev->stats.rx_length_errors += 0x10000;
 
 	/* We do not track MAC_RXSTAT_FCE and MAC_RXSTAT_VCE
 	 * events.
@@ -594,7 +594,7 @@
 		if (netif_msg_rx_err(gp))
 			printk(KERN_DEBUG "%s: no buffer for rx frame\n",
 				gp->dev->name);
-		gp->net_stats.rx_dropped++;
+		dev->stats.rx_dropped++;
 	}
 
 	if (gem_status & GREG_STAT_RXTAGERR) {
@@ -602,7 +602,7 @@
 		if (netif_msg_rx_err(gp))
 			printk(KERN_DEBUG "%s: corrupt rx tag framing\n",
 				gp->dev->name);
-		gp->net_stats.rx_errors++;
+		dev->stats.rx_errors++;
 
 		goto do_reset;
 	}
@@ -684,7 +684,7 @@
 				break;
 		}
 		gp->tx_skbs[entry] = NULL;
-		gp->net_stats.tx_bytes += skb->len;
+		dev->stats.tx_bytes += skb->len;
 
 		for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) {
 			txd = &gp->init_block->txd[entry];
@@ -696,7 +696,7 @@
 			entry = NEXT_TX(entry);
 		}
 
-		gp->net_stats.tx_packets++;
+		dev->stats.tx_packets++;
 		dev_kfree_skb_irq(skb);
 	}
 	gp->tx_old = entry;
@@ -738,6 +738,7 @@
 
 static int gem_rx(struct gem *gp, int work_to_do)
 {
+	struct net_device *dev = gp->dev;
 	int entry, drops, work_done = 0;
 	u32 done;
 	__sum16 csum;
@@ -782,15 +783,15 @@
 
 		len = (status & RXDCTRL_BUFSZ) >> 16;
 		if ((len < ETH_ZLEN) || (status & RXDCTRL_BAD)) {
-			gp->net_stats.rx_errors++;
+			dev->stats.rx_errors++;
 			if (len < ETH_ZLEN)
-				gp->net_stats.rx_length_errors++;
+				dev->stats.rx_length_errors++;
 			if (len & RXDCTRL_BAD)
-				gp->net_stats.rx_crc_errors++;
+				dev->stats.rx_crc_errors++;
 
 			/* We'll just return it to GEM. */
 		drop_it:
-			gp->net_stats.rx_dropped++;
+			dev->stats.rx_dropped++;
 			goto next;
 		}
 
@@ -843,8 +844,8 @@
 
 		netif_receive_skb(skb);
 
-		gp->net_stats.rx_packets++;
-		gp->net_stats.rx_bytes += len;
+		dev->stats.rx_packets++;
+		dev->stats.rx_bytes += len;
 
 	next:
 		entry = NEXT_RX(entry);
@@ -1149,7 +1150,7 @@
 	val &= ~(PCS_CFG_ENABLE | PCS_CFG_TO);
 	writel(val, gp->regs + PCS_CFG);
 
-	/* Advertise all capabilities except assymetric
+	/* Advertise all capabilities except asymmetric
 	 * pause.
 	 */
 	val = readl(gp->regs + PCS_MIIADV);
@@ -2472,7 +2473,6 @@
 static struct net_device_stats *gem_get_stats(struct net_device *dev)
 {
 	struct gem *gp = netdev_priv(dev);
-	struct net_device_stats *stats = &gp->net_stats;
 
 	spin_lock_irq(&gp->lock);
 	spin_lock(&gp->tx_lock);
@@ -2481,17 +2481,17 @@
 	 * so we shield against this
 	 */
 	if (gp->running) {
-		stats->rx_crc_errors += readl(gp->regs + MAC_FCSERR);
+		dev->stats.rx_crc_errors += readl(gp->regs + MAC_FCSERR);
 		writel(0, gp->regs + MAC_FCSERR);
 
-		stats->rx_frame_errors += readl(gp->regs + MAC_AERR);
+		dev->stats.rx_frame_errors += readl(gp->regs + MAC_AERR);
 		writel(0, gp->regs + MAC_AERR);
 
-		stats->rx_length_errors += readl(gp->regs + MAC_LERR);
+		dev->stats.rx_length_errors += readl(gp->regs + MAC_LERR);
 		writel(0, gp->regs + MAC_LERR);
 
-		stats->tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
-		stats->collisions +=
+		dev->stats.tx_aborted_errors += readl(gp->regs + MAC_ECOLL);
+		dev->stats.collisions +=
 			(readl(gp->regs + MAC_ECOLL) +
 			 readl(gp->regs + MAC_LCOLL));
 		writel(0, gp->regs + MAC_ECOLL);
@@ -2501,7 +2501,7 @@
 	spin_unlock(&gp->tx_lock);
 	spin_unlock_irq(&gp->lock);
 
-	return &gp->net_stats;
+	return &dev->stats;
 }
 
 static int gem_set_mac_address(struct net_device *dev, void *addr)
diff -druN linux-libre-2.6.38-gnu/drivers/net/sungem.h linux-libre-2.6.39-gnu/drivers/net/sungem.h
--- linux-libre-2.6.38-gnu/drivers/net/sungem.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sungem.h	2011-05-19 00:06:34.000000000 -0400
@@ -843,7 +843,7 @@
 
 /* GEM requires that RX descriptors are provided four at a time,
  * aligned.  Also, the RX ring may not wrap around.  This means that
- * there will be at least 4 unused desciptor entries in the middle
+ * there will be at least 4 unused descriptor entries in the middle
  * of the RX ring at all times.
  *
  * Similar to HME, GEM assumes that it can write garbage bytes before
@@ -994,7 +994,6 @@
 	u32			status;
 
 	struct napi_struct	napi;
-	struct net_device_stats net_stats;
 
 	int			tx_fifo_sz;
 	int			rx_fifo_sz;
diff -druN linux-libre-2.6.38-gnu/drivers/net/sunhme.c linux-libre-2.6.39-gnu/drivers/net/sunhme.c
--- linux-libre-2.6.38-gnu/drivers/net/sunhme.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sunhme.c	2011-05-19 00:06:34.000000000 -0400
@@ -3237,11 +3237,18 @@
 #endif
 
 #ifdef CONFIG_SBUS
-static int __devinit hme_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static const struct of_device_id hme_sbus_match[];
+static int __devinit hme_sbus_probe(struct platform_device *op)
 {
+	const struct of_device_id *match;
 	struct device_node *dp = op->dev.of_node;
 	const char *model = of_get_property(dp, "model", NULL);
-	int is_qfe = (match->data != NULL);
+	int is_qfe;
+
+	match = of_match_device(hme_sbus_match, &op->dev);
+	if (!match)
+		return -EINVAL;
+	is_qfe = (match->data != NULL);
 
 	if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe"))
 		is_qfe = 1;
@@ -3292,7 +3299,7 @@
 
 MODULE_DEVICE_TABLE(of, hme_sbus_match);
 
-static struct of_platform_driver hme_sbus_driver = {
+static struct platform_driver hme_sbus_driver = {
 	.driver = {
 		.name = "hme",
 		.owner = THIS_MODULE,
@@ -3306,7 +3313,7 @@
 {
 	int err;
 
-	err = of_register_platform_driver(&hme_sbus_driver);
+	err = platform_driver_register(&hme_sbus_driver);
 	if (!err)
 		err = quattro_sbus_register_irqs();
 
@@ -3315,7 +3322,7 @@
 
 static void happy_meal_sbus_exit(void)
 {
-	of_unregister_platform_driver(&hme_sbus_driver);
+	platform_driver_unregister(&hme_sbus_driver);
 	quattro_sbus_free_irqs();
 
 	while (qfe_sbus_list) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/sunhme.h linux-libre-2.6.39-gnu/drivers/net/sunhme.h
--- linux-libre-2.6.38-gnu/drivers/net/sunhme.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sunhme.h	2011-05-19 00:06:34.000000000 -0400
@@ -223,7 +223,7 @@
 /* BigMac receive config register. */
 #define BIGMAC_RXCFG_ENABLE   0x00000001 /* Enable the receiver             */
 #define BIGMAC_RXCFG_PSTRIP   0x00000020 /* Pad byte strip enable           */
-#define BIGMAC_RXCFG_PMISC    0x00000040 /* Enable promiscous mode          */
+#define BIGMAC_RXCFG_PMISC    0x00000040 /* Enable promiscuous mode          */
 #define BIGMAC_RXCFG_DERR     0x00000080 /* Disable error checking          */
 #define BIGMAC_RXCFG_DCRCS    0x00000100 /* Disable CRC stripping           */
 #define BIGMAC_RXCFG_REJME    0x00000200 /* Reject packets addressed to me  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/sunlance.c linux-libre-2.6.39-gnu/drivers/net/sunlance.c
--- linux-libre-2.6.38-gnu/drivers/net/sunlance.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sunlance.c	2011-05-19 00:06:34.000000000 -0400
@@ -1495,7 +1495,7 @@
 	return -ENODEV;
 }
 
-static int __devinit sunlance_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit sunlance_sbus_probe(struct platform_device *op)
 {
 	struct platform_device *parent = to_platform_device(op->dev.parent);
 	struct device_node *parent_dp = parent->dev.of_node;
@@ -1536,7 +1536,7 @@
 
 MODULE_DEVICE_TABLE(of, sunlance_sbus_match);
 
-static struct of_platform_driver sunlance_sbus_driver = {
+static struct platform_driver sunlance_sbus_driver = {
 	.driver = {
 		.name = "sunlance",
 		.owner = THIS_MODULE,
@@ -1550,12 +1550,12 @@
 /* Find all the lance cards on the system and initialize them */
 static int __init sparc_lance_init(void)
 {
-	return of_register_platform_driver(&sunlance_sbus_driver);
+	return platform_driver_register(&sunlance_sbus_driver);
 }
 
 static void __exit sparc_lance_exit(void)
 {
-	of_unregister_platform_driver(&sunlance_sbus_driver);
+	platform_driver_unregister(&sunlance_sbus_driver);
 }
 
 module_init(sparc_lance_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/sunqe.c linux-libre-2.6.39-gnu/drivers/net/sunqe.c
--- linux-libre-2.6.38-gnu/drivers/net/sunqe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/sunqe.c	2011-05-19 00:06:34.000000000 -0400
@@ -941,7 +941,7 @@
 	return res;
 }
 
-static int __devinit qec_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit qec_sbus_probe(struct platform_device *op)
 {
 	return qec_ether_init(op);
 }
@@ -976,7 +976,7 @@
 
 MODULE_DEVICE_TABLE(of, qec_sbus_match);
 
-static struct of_platform_driver qec_sbus_driver = {
+static struct platform_driver qec_sbus_driver = {
 	.driver = {
 		.name = "qec",
 		.owner = THIS_MODULE,
@@ -988,12 +988,12 @@
 
 static int __init qec_init(void)
 {
-	return of_register_platform_driver(&qec_sbus_driver);
+	return platform_driver_register(&qec_sbus_driver);
 }
 
 static void __exit qec_exit(void)
 {
-	of_unregister_platform_driver(&qec_sbus_driver);
+	platform_driver_unregister(&qec_sbus_driver);
 
 	while (root_qec_dev) {
 		struct sunqec *next = root_qec_dev->next_module;
diff -druN linux-libre-2.6.38-gnu/drivers/net/tc35815.c linux-libre-2.6.39-gnu/drivers/net/tc35815.c
--- linux-libre-2.6.38-gnu/drivers/net/tc35815.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tc35815.c	2011-05-19 00:06:34.000000000 -0400
@@ -119,13 +119,13 @@
 /*
  * Bit assignments
  */
-/* DMA_Ctl bit asign ------------------------------------------------------- */
+/* DMA_Ctl bit assign ------------------------------------------------------- */
 #define DMA_RxAlign	       0x00c00000 /* 1:Reception Alignment	     */
 #define DMA_RxAlign_1	       0x00400000
 #define DMA_RxAlign_2	       0x00800000
 #define DMA_RxAlign_3	       0x00c00000
 #define DMA_M66EnStat	       0x00080000 /* 1:66MHz Enable State	     */
-#define DMA_IntMask	       0x00040000 /* 1:Interupt mask		     */
+#define DMA_IntMask	       0x00040000 /* 1:Interrupt mask		     */
 #define DMA_SWIntReq	       0x00020000 /* 1:Software Interrupt request    */
 #define DMA_TxWakeUp	       0x00010000 /* 1:Transmit Wake Up		     */
 #define DMA_RxBigE	       0x00008000 /* 1:Receive Big Endian	     */
@@ -134,11 +134,11 @@
 #define DMA_PowrMgmnt	       0x00001000 /* 1:Power Management		     */
 #define DMA_DmBurst_Mask       0x000001fc /* DMA Burst size		     */
 
-/* RxFragSize bit asign ---------------------------------------------------- */
+/* RxFragSize bit assign ---------------------------------------------------- */
 #define RxFrag_EnPack	       0x00008000 /* 1:Enable Packing		     */
 #define RxFrag_MinFragMask     0x00000ffc /* Minimum Fragment		     */
 
-/* MAC_Ctl bit asign ------------------------------------------------------- */
+/* MAC_Ctl bit assign ------------------------------------------------------- */
 #define MAC_Link10	       0x00008000 /* 1:Link Status 10Mbits	     */
 #define MAC_EnMissRoll	       0x00002000 /* 1:Enable Missed Roll	     */
 #define MAC_MissRoll	       0x00000400 /* 1:Missed Roll		     */
@@ -152,7 +152,7 @@
 #define MAC_HaltImm	       0x00000002 /* 1:Halt Immediate		     */
 #define MAC_HaltReq	       0x00000001 /* 1:Halt request		     */
 
-/* PROM_Ctl bit asign ------------------------------------------------------ */
+/* PROM_Ctl bit assign ------------------------------------------------------ */
 #define PROM_Busy	       0x00008000 /* 1:Busy (Start Operation)	     */
 #define PROM_Read	       0x00004000 /*10:Read operation		     */
 #define PROM_Write	       0x00002000 /*01:Write operation		     */
@@ -162,7 +162,7 @@
 #define PROM_Addr_Ena	       0x00000030 /*11xxxx:PROM Write enable	     */
 					  /*00xxxx:	      disable	     */
 
-/* CAM_Ctl bit asign ------------------------------------------------------- */
+/* CAM_Ctl bit assign ------------------------------------------------------- */
 #define CAM_CompEn	       0x00000010 /* 1:CAM Compare Enable	     */
 #define CAM_NegCAM	       0x00000008 /* 1:Reject packets CAM recognizes,*/
 					  /*			accept other */
@@ -170,7 +170,7 @@
 #define CAM_GroupAcc	       0x00000002 /* 1:Multicast assept		     */
 #define CAM_StationAcc	       0x00000001 /* 1:unicast accept		     */
 
-/* CAM_Ena bit asign ------------------------------------------------------- */
+/* CAM_Ena bit assign ------------------------------------------------------- */
 #define CAM_ENTRY_MAX		       21   /* CAM Data entry max count	     */
 #define CAM_Ena_Mask ((1<<CAM_ENTRY_MAX)-1) /* CAM Enable bits (Max 21bits)  */
 #define CAM_Ena_Bit(index)	(1 << (index))
@@ -178,7 +178,7 @@
 #define CAM_ENTRY_SOURCE	1
 #define CAM_ENTRY_MACCTL	20
 
-/* Tx_Ctl bit asign -------------------------------------------------------- */
+/* Tx_Ctl bit assign -------------------------------------------------------- */
 #define Tx_En		       0x00000001 /* 1:Transmit enable		     */
 #define Tx_TxHalt	       0x00000002 /* 1:Transmit Halt Request	     */
 #define Tx_NoPad	       0x00000004 /* 1:Suppress Padding		     */
@@ -192,7 +192,7 @@
 #define Tx_EnTxPar	       0x00002000 /* 1:Enable Transmit Parity	     */
 #define Tx_EnComp	       0x00004000 /* 1:Enable Completion	     */
 
-/* Tx_Stat bit asign ------------------------------------------------------- */
+/* Tx_Stat bit assign ------------------------------------------------------- */
 #define Tx_TxColl_MASK	       0x0000000F /* Tx Collision Count		     */
 #define Tx_ExColl	       0x00000010 /* Excessive Collision	     */
 #define Tx_TXDefer	       0x00000020 /* Transmit Defered		     */
@@ -208,7 +208,7 @@
 #define Tx_Halted	       0x00008000 /* Tx Halted			     */
 #define Tx_SQErr	       0x00010000 /* Signal Quality Error(SQE)	     */
 
-/* Rx_Ctl bit asign -------------------------------------------------------- */
+/* Rx_Ctl bit assign -------------------------------------------------------- */
 #define Rx_EnGood	       0x00004000 /* 1:Enable Good		     */
 #define Rx_EnRxPar	       0x00002000 /* 1:Enable Receive Parity	     */
 #define Rx_EnLongErr	       0x00000800 /* 1:Enable Long Error	     */
@@ -222,7 +222,7 @@
 #define Rx_RxHalt	       0x00000002 /* 1:Receive Halt Request	     */
 #define Rx_RxEn		       0x00000001 /* 1:Receive Intrrupt Enable	     */
 
-/* Rx_Stat bit asign ------------------------------------------------------- */
+/* Rx_Stat bit assign ------------------------------------------------------- */
 #define Rx_Halted	       0x00008000 /* Rx Halted			     */
 #define Rx_Good		       0x00004000 /* Rx Good			     */
 #define Rx_RxPar	       0x00002000 /* Rx Parity Error		     */
@@ -238,7 +238,7 @@
 
 #define Rx_Stat_Mask	       0x0000FFF0 /* Rx All Status Mask		     */
 
-/* Int_En bit asign -------------------------------------------------------- */
+/* Int_En bit assign -------------------------------------------------------- */
 #define Int_NRAbtEn	       0x00000800 /* 1:Non-recoverable Abort Enable  */
 #define Int_TxCtlCmpEn	       0x00000400 /* 1:Transmit Ctl Complete Enable  */
 #define Int_DmParErrEn	       0x00000200 /* 1:DMA Parity Error Enable	     */
@@ -253,7 +253,7 @@
 #define Int_FDAExEn	       0x00000001 /* 1:Free Descriptor Area	     */
 					  /*		   Exhausted Enable  */
 
-/* Int_Src bit asign ------------------------------------------------------- */
+/* Int_Src bit assign ------------------------------------------------------- */
 #define Int_NRabt	       0x00004000 /* 1:Non Recoverable error	     */
 #define Int_DmParErrStat       0x00002000 /* 1:DMA Parity Error & Clear	     */
 #define Int_BLEx	       0x00001000 /* 1:Buffer List Empty & Clear     */
@@ -270,8 +270,8 @@
 #define Int_IntMacRx	       0x00000002 /* 1:Rx controller & Clear	     */
 #define Int_IntMacTx	       0x00000001 /* 1:Tx controller & Clear	     */
 
-/* MD_CA bit asign --------------------------------------------------------- */
-#define MD_CA_PreSup	       0x00001000 /* 1:Preamble Supress		     */
+/* MD_CA bit assign --------------------------------------------------------- */
+#define MD_CA_PreSup	       0x00001000 /* 1:Preamble Suppress		     */
 #define MD_CA_Busy	       0x00000800 /* 1:Busy (Start Operation)	     */
 #define MD_CA_Wr	       0x00000400 /* 1:Write 0:Read		     */
 
@@ -296,7 +296,7 @@
 
 #define FD_ALIGN	16
 
-/* Frame Descripter bit asign ---------------------------------------------- */
+/* Frame Descripter bit assign ---------------------------------------------- */
 #define FD_FDLength_MASK       0x0000FFFF /* Length MASK		     */
 #define FD_BDCnt_MASK	       0x001F0000 /* BD count MASK in FD	     */
 #define FD_FrmOpt_MASK	       0x7C000000 /* Frame option MASK		     */
@@ -309,8 +309,8 @@
 #define FD_Next_EOL	       0x00000001 /* FD EOL indicator		     */
 #define FD_BDCnt_SHIFT	       16
 
-/* Buffer Descripter bit asign --------------------------------------------- */
-#define BD_BuffLength_MASK     0x0000FFFF /* Recieve Data Size		     */
+/* Buffer Descripter bit assign --------------------------------------------- */
+#define BD_BuffLength_MASK     0x0000FFFF /* Receive Data Size		     */
 #define BD_RxBDID_MASK	       0x00FF0000 /* BD ID Number MASK		     */
 #define BD_RxBDSeqN_MASK       0x7F000000 /* Rx BD Sequence Number	     */
 #define BD_CownsBD	       0x80000000 /* BD Controller owner bit	     */
@@ -339,7 +339,7 @@
 #define TX_THRESHOLD	1024
 /* used threshold with packet max byte for low pci transfer ability.*/
 #define TX_THRESHOLD_MAX 1536
-/* setting threshold max value when overrun error occured this count. */
+/* setting threshold max value when overrun error occurred this count. */
 #define TX_THRESHOLD_KEEP_LIMIT 10
 
 /* 16 + RX_BUF_NUM * 8 + RX_FD_NUM * 16 + TX_FD_NUM * 32 <= PAGE_SIZE*FD_PAGE_NUM */
diff -druN linux-libre-2.6.38-gnu/drivers/net/tehuti.c linux-libre-2.6.39-gnu/drivers/net/tehuti.c
--- linux-libre-2.6.38-gnu/drivers/net/tehuti.c	2012-03-24 01:08:58.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tehuti.c	2012-03-24 03:31:24.000000000 -0400
@@ -645,7 +645,7 @@
 	if (cmd != SIOCDEVPRIVATE) {
 		error = copy_from_user(data, ifr->ifr_data, sizeof(data));
 		if (error) {
-			pr_err("cant copy from user\n");
+			pr_err("can't copy from user\n");
 			RET(-EFAULT);
 		}
 		DBG("%d 0x%x 0x%x\n", data[0], data[1], data[2]);
@@ -999,7 +999,7 @@
  *
  * RxD fifo is smaller than RxF fifo by design. Upon high load, RxD will be
  * filled and packets will be dropped by nic without getting into host or
- * cousing interrupt. Anyway, in that condition, host has no chance to proccess
+ * cousing interrupt. Anyway, in that condition, host has no chance to process
  * all packets, but dropping in nic is cheaper, since it takes 0 cpu cycles
  */
 
@@ -1200,8 +1200,8 @@
 	RET();
 }
 
-/* bdx_rx_receive - recieves full packets from RXD fifo and pass them to OS
- * NOTE: a special treatment is given to non-continous descriptors
+/* bdx_rx_receive - receives full packets from RXD fifo and pass them to OS
+ * NOTE: a special treatment is given to non-continuous descriptors
  * that start near the end, wraps around and continue at the beginning. a second
  * part is copied right after the first, and then descriptor is interpreted as
  * normal. fifo has an extra space to allow such operations
@@ -1584,9 +1584,9 @@
 }
 
 /*
- * bdx_tx_space - calculates avalable space in TX fifo
+ * bdx_tx_space - calculates available space in TX fifo
  * @priv - NIC private structure
- * Returns avaliable space in TX fifo in bytes
+ * Returns available space in TX fifo in bytes
  */
 static inline int bdx_tx_space(struct bdx_priv *priv)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/tehuti.h linux-libre-2.6.39-gnu/drivers/net/tehuti.h
--- linux-libre-2.6.38-gnu/drivers/net/tehuti.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tehuti.h	2011-05-19 00:06:34.000000000 -0400
@@ -502,7 +502,7 @@
 #define  GMAC_RX_FILTER_ACRC  0x0010	/* accept crc error */
 #define  GMAC_RX_FILTER_AM    0x0008	/* accept multicast */
 #define  GMAC_RX_FILTER_AB    0x0004	/* accept broadcast */
-#define  GMAC_RX_FILTER_PRM   0x0001	/* [0:1] promiscous mode */
+#define  GMAC_RX_FILTER_PRM   0x0001	/* [0:1] promiscuous mode */
 
 #define  MAX_FRAME_AB_VAL       0x3fff	/* 13:0 */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/tg3.c linux-libre-2.6.39-gnu/drivers/net/tg3.c
--- linux-libre-2.6.38-gnu/drivers/net/tg3.c	2012-03-24 01:09:12.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tg3.c	2012-03-24 03:31:33.000000000 -0400
@@ -4,7 +4,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001, 2002, 2003 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2005-2010 Broadcom Corporation.
+ * Copyright (C) 2005-2011 Broadcom Corporation.
  *
 /*(DEBLOBBED)*/
 
@@ -41,9 +41,9 @@
 #include <net/ip.h>
 
 #include <asm/system.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <asm/byteorder.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #ifdef CONFIG_SPARC
 #include <asm/idprom.h>
@@ -57,10 +57,10 @@
 
 #define DRV_MODULE_NAME		"tg3"
 #define TG3_MAJ_NUM			3
-#define TG3_MIN_NUM			116
+#define TG3_MIN_NUM			117
 #define DRV_MODULE_VERSION	\
 	__stringify(TG3_MAJ_NUM) "." __stringify(TG3_MIN_NUM)
-#define DRV_MODULE_RELDATE	"December 3, 2010"
+#define DRV_MODULE_RELDATE	"January 25, 2011"
 
 #define TG3_DEF_MAC_MODE	0
 #define TG3_DEF_RX_MODE		0
@@ -1767,9 +1767,29 @@
 		tg3_phy_cl45_read(tp, MDIO_MMD_AN,
 				  TG3_CL45_D7_EEERES_STAT, &val);
 
-		if (val == TG3_CL45_D7_EEERES_STAT_LP_1000T ||
-		    val == TG3_CL45_D7_EEERES_STAT_LP_100TX)
+		switch (val) {
+		case TG3_CL45_D7_EEERES_STAT_LP_1000T:
+			switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+			case ASIC_REV_5717:
+			case ASIC_REV_5719:
+			case ASIC_REV_57765:
+				/* Enable SM_DSP clock and tx 6dB coding. */
+				val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+				      MII_TG3_AUXCTL_ACTL_SMDSP_ENA |
+				      MII_TG3_AUXCTL_ACTL_TX_6DB;
+				tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+
+				tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
+
+				/* Turn off SM_DSP clock. */
+				val = MII_TG3_AUXCTL_SHDWSEL_AUXCTL |
+				      MII_TG3_AUXCTL_ACTL_TX_6DB;
+				tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
+			}
+			/* Fallthrough */
+		case TG3_CL45_D7_EEERES_STAT_LP_100TX:
 			tp->setlpicnt = 2;
+		}
 	}
 
 	if (!tp->setlpicnt) {
@@ -2091,7 +2111,7 @@
 
 static void tg3_frob_aux_power(struct tg3 *tp)
 {
-	struct tg3 *tp_peer = tp;
+	bool need_vaux = false;
 
 	/* The GPIOs do something completely different on 57765. */
 	if ((tp->tg3_flags2 & TG3_FLG2_IS_NIC) == 0 ||
@@ -2099,23 +2119,32 @@
 	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765)
 		return;
 
-	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) {
+	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5704 ||
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5714 ||
+	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717) &&
+	    tp->pdev_peer != tp->pdev) {
 		struct net_device *dev_peer;
 
 		dev_peer = pci_get_drvdata(tp->pdev_peer);
+
 		/* remove_one() may have been run on the peer. */
-		if (!dev_peer)
-			tp_peer = tp;
-		else
-			tp_peer = netdev_priv(dev_peer);
+		if (dev_peer) {
+			struct tg3 *tp_peer = netdev_priv(dev_peer);
+
+			if (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE)
+				return;
+
+			if ((tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) ||
+			    (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF))
+				need_vaux = true;
+		}
 	}
 
-	if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
-	    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0 ||
-	    (tp_peer->tg3_flags & TG3_FLAG_WOL_ENABLE) != 0 ||
-	    (tp_peer->tg3_flags & TG3_FLAG_ENABLE_ASF) != 0) {
+	if ((tp->tg3_flags & TG3_FLAG_WOL_ENABLE) ||
+	    (tp->tg3_flags & TG3_FLAG_ENABLE_ASF))
+		need_vaux = true;
+
+	if (need_vaux) {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5700 ||
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5701) {
 			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
@@ -2145,10 +2174,6 @@
 			u32 no_gpio2;
 			u32 grc_local_ctrl = 0;
 
-			if (tp_peer != tp &&
-			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
-				return;
-
 			/* Workaround to prevent overdrawing Amps. */
 			if (GET_ASIC_REV(tp->pci_chip_rev_id) ==
 			    ASIC_REV_5714) {
@@ -2187,10 +2212,6 @@
 	} else {
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5700 &&
 		    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5701) {
-			if (tp_peer != tp &&
-			    (tp_peer->tg3_flags & TG3_FLAG_INIT_COMPLETE) != 0)
-				return;
-
 			tw32_wait_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl |
 				    (GRC_LCLCTRL_GPIO_OE1 |
 				     GRC_LCLCTRL_GPIO_OUTPUT1), 100);
@@ -2959,11 +2980,19 @@
 		      MII_TG3_AUXCTL_ACTL_TX_6DB;
 		tg3_writephy(tp, MII_TG3_AUX_CTRL, val);
 
-		if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
-		     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_57765) &&
-		    !tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
-			tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2,
-					 val | MII_TG3_DSP_CH34TP2_HIBW01);
+		switch (GET_ASIC_REV(tp->pci_chip_rev_id)) {
+		case ASIC_REV_5717:
+		case ASIC_REV_57765:
+			if (!tg3_phydsp_read(tp, MII_TG3_DSP_CH34TP2, &val))
+				tg3_phydsp_write(tp, MII_TG3_DSP_CH34TP2, val |
+						 MII_TG3_DSP_CH34TP2_HIBW01);
+			/* Fall through */
+		case ASIC_REV_5719:
+			val = MII_TG3_DSP_TAP26_ALNOKO |
+			      MII_TG3_DSP_TAP26_RMRXSTO |
+			      MII_TG3_DSP_TAP26_OPCSINPT;
+			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
+		}
 
 		val = 0;
 		if (tp->link_config.autoneg == AUTONEG_ENABLE) {
@@ -7792,7 +7821,7 @@
 		       TG3_CPMU_DBTMR1_LNKIDLE_2047US);
 
 		tw32_f(TG3_CPMU_EEE_DBTMR2,
-		       TG3_CPMU_DBTMR1_APE_TX_2047US |
+		       TG3_CPMU_DBTMR2_APE_TX_2047US |
 		       TG3_CPMU_DBTMR2_TXIDXEQ_2047US);
 	}
 
@@ -8066,8 +8095,9 @@
 	/* Program the jumbo buffer descriptor ring control
 	 * blocks on those devices that have them.
 	 */
-	if ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
-	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS)) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
+	    ((tp->tg3_flags & TG3_FLAG_JUMBO_CAPABLE) &&
+	    !(tp->tg3_flags2 & TG3_FLG2_5780_CLASS))) {
 		/* Setup replenish threshold. */
 		tw32(RCVBDI_JUMBO_THRESH, tp->rx_jumbo_pending / 8);
 
@@ -8154,10 +8184,8 @@
 			      RDMAC_MODE_MBUF_RBD_CRPT_ENAB |
 			      RDMAC_MODE_MBUF_SBD_CRPT_ENAB;
 
-	/* If statement applies to 5705 and 5750 PCI devices only */
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
-	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750)) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
 		if (tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE &&
 		    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705) {
 			rdmac_mode |= RDMAC_MODE_FIFO_SIZE_128;
@@ -8185,8 +8213,12 @@
 	    (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)) {
 		val = tr32(TG3_RDMA_RSRVCTRL_REG);
 		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
-			val &= ~TG3_RDMA_RSRVCTRL_TXMRGN_MASK;
-			val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B;
+			val &= ~(TG3_RDMA_RSRVCTRL_TXMRGN_MASK |
+				 TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK |
+				 TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK);
+			val |= TG3_RDMA_RSRVCTRL_TXMRGN_320B |
+			       TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K |
+			       TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K;
 		}
 		tw32(TG3_RDMA_RSRVCTRL_REG,
 		     val | TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX);
@@ -8308,7 +8340,8 @@
 	tw32_f(GRC_LOCAL_CTRL, tp->grc_local_ctrl);
 	udelay(100);
 
-	if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX) {
+	if ((tp->tg3_flags2 & TG3_FLG2_USING_MSIX) &&
+		tp->irq_cnt > 1) {
 		val = tr32(MSGINT_MODE);
 		val |= MSGINT_MODE_MULTIVEC_EN | MSGINT_MODE_ENABLE;
 		tw32(MSGINT_MODE, val);
@@ -8325,17 +8358,14 @@
 	       WDMAC_MODE_FIFOURUN_ENAB | WDMAC_MODE_FIFOOREAD_ENAB |
 	       WDMAC_MODE_LNGREAD_ENAB);
 
-	/* If statement applies to 5705 and 5750 PCI devices only */
-	if ((GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
-	     tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) ||
-	    GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5750) {
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5705 &&
+	    tp->pci_chip_rev_id != CHIPREV_ID_5705_A0) {
 		if ((tp->tg3_flags2 & TG3_FLG2_TSO_CAPABLE) &&
 		    (tp->pci_chip_rev_id == CHIPREV_ID_5705_A1 ||
 		     tp->pci_chip_rev_id == CHIPREV_ID_5705_A2)) {
 			/* nothing */
 		} else if (!(tr32(TG3PCI_PCISTATE) & PCISTATE_BUS_SPEED_HIGH) &&
-			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788) &&
-			   !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS)) {
+			   !(tp->tg3_flags2 & TG3_FLG2_IS_5788)) {
 			val |= WDMAC_MODE_RX_ACCEL;
 		}
 	}
@@ -9048,7 +9078,8 @@
 
 	if (tp->tg3_flags2 & TG3_FLG2_USING_MSI_OR_MSIX) {
 		u32 msi_mode = tr32(MSGINT_MODE);
-		if (tp->tg3_flags2 & TG3_FLG2_USING_MSIX)
+		if ((tp->tg3_flags2 & TG3_FLG2_USING_MSIX) &&
+		    tp->irq_cnt > 1)
 			msi_mode |= MSGINT_MODE_MULTIVEC_EN;
 		tw32(MSGINT_MODE, msi_mode | MSGINT_MODE_ENABLE);
 	}
@@ -9672,7 +9703,7 @@
 		eeprom->len += b_count;
 	}
 
-	/* read bytes upto the last 4 byte boundary */
+	/* read bytes up to the last 4 byte boundary */
 	pd = &data[eeprom->len];
 	for (i = 0; i < (len - (len & 3)); i += 4) {
 		ret = tg3_nvram_read_be32(tp, offset + i, &val);
@@ -10443,16 +10474,53 @@
 		goto out;
 	}
 
+	err = -EIO;
+
 	/* Bootstrap checksum at offset 0x10 */
 	csum = calc_crc((unsigned char *) buf, 0x10);
-	if (csum != be32_to_cpu(buf[0x10/4]))
+	if (csum != le32_to_cpu(buf[0x10/4]))
 		goto out;
 
 	/* Manufacturing block starts at offset 0x74, checksum at 0xfc */
 	csum = calc_crc((unsigned char *) &buf[0x74/4], 0x88);
-	if (csum != be32_to_cpu(buf[0xfc/4]))
+	if (csum != le32_to_cpu(buf[0xfc/4]))
 		goto out;
 
+	for (i = 0; i < TG3_NVM_VPD_LEN; i += 4) {
+		/* The data is in little-endian format in NVRAM.
+		 * Use the big-endian read routines to preserve
+		 * the byte order as it exists in NVRAM.
+		 */
+		if (tg3_nvram_read_be32(tp, TG3_NVM_VPD_OFF + i, &buf[i/4]))
+			goto out;
+	}
+
+	i = pci_vpd_find_tag((u8 *)buf, 0, TG3_NVM_VPD_LEN,
+			     PCI_VPD_LRDT_RO_DATA);
+	if (i > 0) {
+		j = pci_vpd_lrdt_size(&((u8 *)buf)[i]);
+		if (j < 0)
+			goto out;
+
+		if (i + PCI_VPD_LRDT_TAG_SIZE + j > TG3_NVM_VPD_LEN)
+			goto out;
+
+		i += PCI_VPD_LRDT_TAG_SIZE;
+		j = pci_vpd_find_info_keyword((u8 *)buf, i, j,
+					      PCI_VPD_RO_KEYWORD_CHKSUM);
+		if (j > 0) {
+			u8 csum8 = 0;
+
+			j += PCI_VPD_INFO_FLD_HDR_SIZE;
+
+			for (i = 0; i <= j; i++)
+				csum8 += ((u8 *)buf)[i];
+
+			if (csum8)
+				goto out;
+		}
+	}
+
 	err = 0;
 
 out:
@@ -10824,13 +10892,16 @@
 	if (loopback_mode == TG3_MAC_LOOPBACK) {
 		/* HW errata - mac loopback fails in some cases on 5780.
 		 * Normal traffic and PHY loopback are not affected by
-		 * errata.
+		 * errata.  Also, the MAC loopback test is deprecated for
+		 * all newer ASIC revisions.
 		 */
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780)
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5780 ||
+		    (tp->tg3_flags & TG3_FLAG_CPMU_PRESENT))
 			return 0;
 
-		mac_mode = (tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK) |
-			   MAC_MODE_PORT_INT_LPBACK;
+		mac_mode = tp->mac_mode &
+			   ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
+		mac_mode |= MAC_MODE_PORT_INT_LPBACK;
 		if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS))
 			mac_mode |= MAC_MODE_LINK_POLARITY;
 		if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
@@ -10852,7 +10923,8 @@
 		tg3_writephy(tp, MII_BMCR, val);
 		udelay(40);
 
-		mac_mode = tp->mac_mode & ~MAC_MODE_PORT_MODE_MASK;
+		mac_mode = tp->mac_mode &
+			   ~(MAC_MODE_PORT_MODE_MASK | MAC_MODE_HALF_DUPLEX);
 		if (tp->phy_flags & TG3_PHYFLG_IS_FET) {
 			tg3_writephy(tp, MII_TG3_FET_PTEST,
 				     MII_TG3_FET_PTEST_FRC_TX_LINK |
@@ -10880,6 +10952,13 @@
 				     MII_TG3_EXT_CTRL_LNK3_LED_MODE);
 		}
 		tw32(MAC_MODE, mac_mode);
+
+		/* Wait for link */
+		for (i = 0; i < 100; i++) {
+			if (tr32(MAC_TX_STATUS) & TX_STATUS_LINK_UP)
+				break;
+			mdelay(1);
+		}
 	} else {
 		return -EINVAL;
 	}
@@ -10986,14 +11065,19 @@
 static int tg3_test_loopback(struct tg3 *tp)
 {
 	int err = 0;
-	u32 cpmuctrl = 0;
+	u32 eee_cap, cpmuctrl = 0;
 
 	if (!netif_running(tp->dev))
 		return TG3_LOOPBACK_FAILED;
 
+	eee_cap = tp->phy_flags & TG3_PHYFLG_EEE_CAP;
+	tp->phy_flags &= ~TG3_PHYFLG_EEE_CAP;
+
 	err = tg3_reset_hw(tp, 1);
-	if (err)
-		return TG3_LOOPBACK_FAILED;
+	if (err) {
+		err = TG3_LOOPBACK_FAILED;
+		goto done;
+	}
 
 	/* Turn off gphy autopowerdown. */
 	if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
@@ -11013,8 +11097,10 @@
 			udelay(10);
 		}
 
-		if (status != CPMU_MUTEX_GNT_DRIVER)
-			return TG3_LOOPBACK_FAILED;
+		if (status != CPMU_MUTEX_GNT_DRIVER) {
+			err = TG3_LOOPBACK_FAILED;
+			goto done;
+		}
 
 		/* Turn off link-based power management. */
 		cpmuctrl = tr32(TG3_CPMU_CTRL);
@@ -11043,6 +11129,9 @@
 	if (tp->phy_flags & TG3_PHYFLG_ENABLE_APD)
 		tg3_phy_toggle_apd(tp, true);
 
+done:
+	tp->phy_flags |= eee_cap;
+
 	return err;
 }
 
@@ -12229,8 +12318,10 @@
 		if (val & VCPU_CFGSHDW_ASPM_DBNC)
 			tp->tg3_flags |= TG3_FLAG_ASPM_WORKAROUND;
 		if ((val & VCPU_CFGSHDW_WOL_ENABLE) &&
-		    (val & VCPU_CFGSHDW_WOL_MAGPKT))
+		    (val & VCPU_CFGSHDW_WOL_MAGPKT)) {
 			tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+			device_set_wakeup_enable(&tp->pdev->dev, true);
+		}
 		goto done;
 	}
 
@@ -12363,8 +12454,10 @@
 			tp->tg3_flags &= ~TG3_FLAG_WOL_CAP;
 
 		if ((tp->tg3_flags & TG3_FLAG_WOL_CAP) &&
-		    (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE))
+		    (nic_cfg & NIC_SRAM_DATA_CFG_WOL_ENABLE)) {
 			tp->tg3_flags |= TG3_FLAG_WOL_ENABLE;
+			device_set_wakeup_enable(&tp->pdev->dev, true);
+		}
 
 		if (cfg2 & (1 << 17))
 			tp->phy_flags |= TG3_PHYFLG_CAPACITIVE_COUPLING;
@@ -12398,9 +12491,11 @@
 			tp->tg3_flags3 |= TG3_FLG3_RGMII_EXT_IBND_TX_EN;
 	}
 done:
-	device_init_wakeup(&tp->pdev->dev, tp->tg3_flags & TG3_FLAG_WOL_CAP);
-	device_set_wakeup_enable(&tp->pdev->dev,
+	if (tp->tg3_flags & TG3_FLAG_WOL_CAP)
+		device_set_wakeup_enable(&tp->pdev->dev,
 				 tp->tg3_flags & TG3_FLAG_WOL_ENABLE);
+	else
+		device_set_wakeup_capable(&tp->pdev->dev, false);
 }
 
 static int __devinit tg3_issue_otp_command(struct tg3 *tp, u32 cmd)
@@ -12452,12 +12547,45 @@
 	return ((thalf_otp & 0x0000ffff) << 16) | (bhalf_otp >> 16);
 }
 
+static void __devinit tg3_phy_init_link_config(struct tg3 *tp)
+{
+	u32 adv = ADVERTISED_Autoneg |
+		  ADVERTISED_Pause;
+
+	if (!(tp->phy_flags & TG3_PHYFLG_10_100_ONLY))
+		adv |= ADVERTISED_1000baseT_Half |
+		       ADVERTISED_1000baseT_Full;
+
+	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES))
+		adv |= ADVERTISED_100baseT_Half |
+		       ADVERTISED_100baseT_Full |
+		       ADVERTISED_10baseT_Half |
+		       ADVERTISED_10baseT_Full |
+		       ADVERTISED_TP;
+	else
+		adv |= ADVERTISED_FIBRE;
+
+	tp->link_config.advertising = adv;
+	tp->link_config.speed = SPEED_INVALID;
+	tp->link_config.duplex = DUPLEX_INVALID;
+	tp->link_config.autoneg = AUTONEG_ENABLE;
+	tp->link_config.active_speed = SPEED_INVALID;
+	tp->link_config.active_duplex = DUPLEX_INVALID;
+	tp->link_config.orig_speed = SPEED_INVALID;
+	tp->link_config.orig_duplex = DUPLEX_INVALID;
+	tp->link_config.orig_autoneg = AUTONEG_INVALID;
+}
+
 static int __devinit tg3_phy_probe(struct tg3 *tp)
 {
 	u32 hw_phy_id_1, hw_phy_id_2;
 	u32 hw_phy_id, hw_phy_id_masked;
 	int err;
 
+	/* flow control autonegotiation is default behavior */
+	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
+	tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
+
 	if (tp->tg3_flags3 & TG3_FLG3_USE_PHYLIB)
 		return tg3_phy_init(tp);
 
@@ -12519,6 +12647,8 @@
 	      tp->pci_chip_rev_id != CHIPREV_ID_57765_A0)))
 		tp->phy_flags |= TG3_PHYFLG_EEE_CAP;
 
+	tg3_phy_init_link_config(tp);
+
 	if (!(tp->phy_flags & TG3_PHYFLG_ANY_SERDES) &&
 	    !(tp->tg3_flags3 & TG3_FLG3_ENABLE_APE) &&
 	    !(tp->tg3_flags & TG3_FLAG_ENABLE_ASF)) {
@@ -12574,17 +12704,6 @@
 		err = tg3_init_5401phy_dsp(tp);
 	}
 
-	if (tp->phy_flags & TG3_PHYFLG_ANY_SERDES)
-		tp->link_config.advertising =
-			(ADVERTISED_1000baseT_Half |
-			 ADVERTISED_1000baseT_Full |
-			 ADVERTISED_Autoneg |
-			 ADVERTISED_FIBRE);
-	if (tp->phy_flags & TG3_PHYFLG_10_100_ONLY)
-		tp->link_config.advertising &=
-			~(ADVERTISED_1000baseT_Half |
-			  ADVERTISED_1000baseT_Full);
-
 	return err;
 }
 
@@ -12994,7 +13113,7 @@
 
 static struct pci_dev * __devinit tg3_find_peer(struct tg3 *);
 
-static void inline vlan_features_add(struct net_device *dev, unsigned long flags)
+static inline void vlan_features_add(struct net_device *dev, unsigned long flags)
 {
 	dev->vlan_features |= flags;
 }
@@ -13011,7 +13130,7 @@
 		return 512;
 }
 
-DEFINE_PCI_DEVICE_TABLE(write_reorder_chipsets) = {
+static DEFINE_PCI_DEVICE_TABLE(tg3_write_reorder_chipsets) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_8131_BRIDGE) },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8385_0) },
@@ -13253,7 +13372,9 @@
 	}
 
 	/* Determine TSO capabilities */
-	if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
+	if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+		; /* Do nothing. HW bug. */
+	else if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
 		tp->tg3_flags2 |= TG3_FLG2_HW_TSO_3;
 	else if ((tp->tg3_flags3 & TG3_FLG3_5755_PLUS) ||
 		 GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5906)
@@ -13304,7 +13425,8 @@
 		tp->tg3_flags3 |= TG3_FLG3_40BIT_DMA_LIMIT_BUG;
 	}
 
-	if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS)
+	if ((tp->tg3_flags3 & TG3_FLG3_5717_PLUS) &&
+	    GET_ASIC_REV(tp->pci_chip_rev_id) != ASIC_REV_5719)
 		tp->tg3_flags3 |= TG3_FLG3_USE_JUMBO_BDFLAG;
 
 	if (!(tp->tg3_flags2 & TG3_FLG2_5705_PLUS) ||
@@ -13322,42 +13444,8 @@
 		tp->tg3_flags2 |= TG3_FLG2_PCI_EXPRESS;
 
 		tp->pcie_readrq = 4096;
-		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719) {
-			u16 word;
-
-			pci_read_config_word(tp->pdev,
-					     tp->pcie_cap + PCI_EXP_LNKSTA,
-					     &word);
-			switch (word & PCI_EXP_LNKSTA_CLS) {
-			case PCI_EXP_LNKSTA_CLS_2_5GB:
-				word &= PCI_EXP_LNKSTA_NLW;
-				word >>= PCI_EXP_LNKSTA_NLW_SHIFT;
-				switch (word) {
-				case 2:
-					tp->pcie_readrq = 2048;
-					break;
-				case 4:
-					tp->pcie_readrq = 1024;
-					break;
-				}
-				break;
-
-			case PCI_EXP_LNKSTA_CLS_5_0GB:
-				word &= PCI_EXP_LNKSTA_NLW;
-				word >>= PCI_EXP_LNKSTA_NLW_SHIFT;
-				switch (word) {
-				case 1:
-					tp->pcie_readrq = 2048;
-					break;
-				case 2:
-					tp->pcie_readrq = 1024;
-					break;
-				case 4:
-					tp->pcie_readrq = 512;
-					break;
-				}
-			}
-		}
+		if (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719)
+			tp->pcie_readrq = 2048;
 
 		pcie_set_readrq(tp->pdev, tp->pcie_readrq);
 
@@ -13396,7 +13484,7 @@
 	 * every mailbox register write to force the writes to be
 	 * posted to the chip in order.
 	 */
-	if (pci_dev_present(write_reorder_chipsets) &&
+	if (pci_dev_present(tg3_write_reorder_chipsets) &&
 	    !(tp->tg3_flags2 & TG3_FLG2_PCI_EXPRESS))
 		tp->tg3_flags |= TG3_FLAG_MBOX_WRITE_REORDER;
 
@@ -14152,7 +14240,7 @@
 
 #define TEST_BUFFER_SIZE	0x2000
 
-DEFINE_PCI_DEVICE_TABLE(dma_wait_state_chipsets) = {
+static DEFINE_PCI_DEVICE_TABLE(tg3_dma_wait_state_chipsets) = {
 	{ PCI_DEVICE(PCI_VENDOR_ID_APPLE, PCI_DEVICE_ID_APPLE_UNI_N_PCI15) },
 	{ },
 };
@@ -14331,7 +14419,7 @@
 		 * now look for chipsets that are known to expose the
 		 * DMA bug without failing the test.
 		 */
-		if (pci_dev_present(dma_wait_state_chipsets)) {
+		if (pci_dev_present(tg3_dma_wait_state_chipsets)) {
 			tp->dma_rwctrl &= ~DMA_RWCTRL_WRITE_BNDRY_MASK;
 			tp->dma_rwctrl |= DMA_RWCTRL_WRITE_BNDRY_16;
 		} else {
@@ -14348,23 +14436,6 @@
 	return ret;
 }
 
-static void __devinit tg3_init_link_config(struct tg3 *tp)
-{
-	tp->link_config.advertising =
-		(ADVERTISED_10baseT_Half | ADVERTISED_10baseT_Full |
-		 ADVERTISED_100baseT_Half | ADVERTISED_100baseT_Full |
-		 ADVERTISED_1000baseT_Half | ADVERTISED_1000baseT_Full |
-		 ADVERTISED_Autoneg | ADVERTISED_MII);
-	tp->link_config.speed = SPEED_INVALID;
-	tp->link_config.duplex = DUPLEX_INVALID;
-	tp->link_config.autoneg = AUTONEG_ENABLE;
-	tp->link_config.active_speed = SPEED_INVALID;
-	tp->link_config.active_duplex = DUPLEX_INVALID;
-	tp->link_config.orig_speed = SPEED_INVALID;
-	tp->link_config.orig_duplex = DUPLEX_INVALID;
-	tp->link_config.orig_autoneg = AUTONEG_INVALID;
-}
-
 static void __devinit tg3_init_bufmgr_config(struct tg3 *tp)
 {
 	if (tp->tg3_flags3 & TG3_FLG3_5717_PLUS) {
@@ -14668,8 +14739,6 @@
 		goto err_out_free_dev;
 	}
 
-	tg3_init_link_config(tp);
-
 	tp->rx_pending = TG3_DEF_RX_RING_PENDING;
 	tp->rx_jumbo_pending = TG3_DEF_RX_JUMBO_RING_PENDING;
 
@@ -14817,10 +14886,6 @@
 		goto err_out_apeunmap;
 	}
 
-	/* flow control autonegotiation is default behavior */
-	tp->tg3_flags |= TG3_FLAG_PAUSE_AUTONEG;
-	tp->link_config.flowctrl = FLOW_CTRL_TX | FLOW_CTRL_RX;
-
 	intmbx = MAILBOX_INTERRUPT_0 + TG3_64BIT_REG_LOW;
 	rcvmbx = MAILBOX_RCVRET_CON_IDX_0 + TG3_64BIT_REG_LOW;
 	sndmbx = MAILBOX_SNDHOST_PROD_IDX_0 + TG3_64BIT_REG_LOW;
diff -druN linux-libre-2.6.38-gnu/drivers/net/tg3.h linux-libre-2.6.39-gnu/drivers/net/tg3.h
--- linux-libre-2.6.38-gnu/drivers/net/tg3.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tg3.h	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * Copyright (C) 2001, 2002, 2003, 2004 David S. Miller (davem@redhat.com)
  * Copyright (C) 2001 Jeff Garzik (jgarzik@pobox.com)
  * Copyright (C) 2004 Sun Microsystems Inc.
- * Copyright (C) 2007-2010 Broadcom Corporation.
+ * Copyright (C) 2007-2011 Broadcom Corporation.
  */
 
 #ifndef _T3_H
@@ -141,6 +141,7 @@
 #define  CHIPREV_ID_57780_A1		 0x57780001
 #define  CHIPREV_ID_5717_A0		 0x05717000
 #define  CHIPREV_ID_57765_A0		 0x57785000
+#define  CHIPREV_ID_5719_A0		 0x05719000
 #define  GET_ASIC_REV(CHIP_REV_ID)	((CHIP_REV_ID) >> 12)
 #define   ASIC_REV_5700			 0x07
 #define   ASIC_REV_5701			 0x00
@@ -1105,7 +1106,7 @@
 #define  TG3_CPMU_DBTMR1_PCIEXIT_2047US	 0x07ff0000
 #define  TG3_CPMU_DBTMR1_LNKIDLE_2047US	 0x000070ff
 #define TG3_CPMU_EEE_DBTMR2		0x000036b8
-#define  TG3_CPMU_DBTMR1_APE_TX_2047US	 0x07ff0000
+#define  TG3_CPMU_DBTMR2_APE_TX_2047US	 0x07ff0000
 #define  TG3_CPMU_DBTMR2_TXIDXEQ_2047US	 0x000070ff
 #define TG3_CPMU_EEE_LNKIDL_CTRL	0x000036bc
 #define  TG3_CPMU_EEE_LNKIDL_PCIE_NL0	 0x01000000
@@ -1333,6 +1334,10 @@
 
 #define TG3_RDMA_RSRVCTRL_REG		0x00004900
 #define TG3_RDMA_RSRVCTRL_FIFO_OFLW_FIX	 0x00000004
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_1_5K	 0x00000c00
+#define TG3_RDMA_RSRVCTRL_FIFO_LWM_MASK	 0x00000ff0
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_1_5K	 0x000c0000
+#define TG3_RDMA_RSRVCTRL_FIFO_HWM_MASK	 0x000ff000
 #define TG3_RDMA_RSRVCTRL_TXMRGN_320B	 0x28000000
 #define TG3_RDMA_RSRVCTRL_TXMRGN_MASK	 0xffe00000
 /* 0x4904 --> 0x4910 unused */
@@ -2108,6 +2113,10 @@
 
 #define MII_TG3_DSP_TAP1		0x0001
 #define  MII_TG3_DSP_TAP1_AGCTGT_DFLT	0x0007
+#define MII_TG3_DSP_TAP26		0x001a
+#define  MII_TG3_DSP_TAP26_ALNOKO	0x0001
+#define  MII_TG3_DSP_TAP26_RMRXSTO	0x0002
+#define  MII_TG3_DSP_TAP26_OPCSINPT	0x0004
 #define MII_TG3_DSP_AADJ1CH0		0x001f
 #define MII_TG3_DSP_CH34TP2		0x4022
 #define MII_TG3_DSP_CH34TP2_HIBW01	0x0010
@@ -2121,7 +2130,7 @@
 #define MII_TG3_DSP_EXP96		0x0f96
 #define MII_TG3_DSP_EXP97		0x0f97
 
-#define MII_TG3_AUX_CTRL		0x18 /* auxilliary control register */
+#define MII_TG3_AUX_CTRL		0x18 /* auxiliary control register */
 
 #define MII_TG3_AUXCTL_PCTL_100TX_LPWR	0x0010
 #define MII_TG3_AUXCTL_PCTL_SPR_ISOLATE	0x0020
@@ -2137,7 +2146,7 @@
 #define MII_TG3_AUXCTL_ACTL_TX_6DB	0x0400
 #define MII_TG3_AUXCTL_SHDWSEL_AUXCTL	0x0000
 
-#define MII_TG3_AUX_STAT		0x19 /* auxilliary status register */
+#define MII_TG3_AUX_STAT		0x19 /* auxiliary status register */
 #define MII_TG3_AUX_STAT_LPASS		0x0004
 #define MII_TG3_AUX_STAT_SPDMASK	0x0700
 #define MII_TG3_AUX_STAT_10HALF		0x0100
diff -druN linux-libre-2.6.38-gnu/drivers/net/tile/tilepro.c linux-libre-2.6.39-gnu/drivers/net/tile/tilepro.c
--- linux-libre-2.6.38-gnu/drivers/net/tile/tilepro.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tile/tilepro.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright 2010 Tilera Corporation. All Rights Reserved.
+ * Copyright 2011 Tilera 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
@@ -44,10 +44,6 @@
 #include <linux/tcp.h>
 
 
-/* There is no singlethread_cpu, so schedule work on the current cpu. */
-#define singlethread_cpu -1
-
-
 /*
  * First, "tile_net_init_module()" initializes all four "devices" which
  * can be used by linux.
@@ -73,15 +69,16 @@
  * return, knowing we will be called again later.  Otherwise, we
  * reenable the ingress interrupt, and call "napi_complete()".
  *
+ * HACK: Since disabling the ingress interrupt is not reliable, we
+ * ignore the interrupt if the global "active" flag is false.
+ *
  *
  * NOTE: The use of "native_driver" ensures that EPP exists, and that
- * "epp_sendv" is legal, and that "LIPP" is being used.
+ * we are using "LIPP" and "LEPP".
  *
  * NOTE: Failing to free completions for an arbitrarily long time
  * (which is defined to be illegal) does in fact cause bizarre
  * problems.  The "egress_timer" helps prevent this from happening.
- *
- * NOTE: The egress code can be interrupted by the interrupt handler.
  */
 
 
@@ -142,6 +139,7 @@
 MODULE_AUTHOR("Tilera");
 MODULE_LICENSE("GPL");
 
+
 /*
  * Queue of incoming packets for a specific cpu and device.
  *
@@ -177,7 +175,7 @@
 	struct tile_netio_queue queue;
 	/* Statistics. */
 	struct tile_net_stats_t stats;
-	/* ISSUE: Is this needed? */
+	/* True iff NAPI is enabled. */
 	bool napi_enabled;
 	/* True if this tile has succcessfully registered with the IPP. */
 	bool registered;
@@ -200,20 +198,20 @@
 struct tile_net_priv {
 	/* Our network device. */
 	struct net_device *dev;
-	/* The actual egress queue. */
-	lepp_queue_t *epp_queue;
-	/* Protects "epp_queue->cmd_tail" and "epp_queue->comp_tail" */
-	spinlock_t cmd_lock;
-	/* Protects "epp_queue->comp_head". */
-	spinlock_t comp_lock;
+	/* Pages making up the egress queue. */
+	struct page *eq_pages;
+	/* Address of the actual egress queue. */
+	lepp_queue_t *eq;
+	/* Protects "eq". */
+	spinlock_t eq_lock;
 	/* The hypervisor handle for this interface. */
 	int hv_devhdl;
 	/* The intr bit mask that IDs this device. */
 	u32 intr_id;
 	/* True iff "tile_net_open_aux()" has succeeded. */
-	int partly_opened;
-	/* True iff "tile_net_open_inner()" has succeeded. */
-	int fully_opened;
+	bool partly_opened;
+	/* True iff the device is "active". */
+	bool active;
 	/* Effective network cpus. */
 	struct cpumask network_cpus_map;
 	/* Number of network cpus. */
@@ -228,6 +226,10 @@
 	struct tile_net_cpu *cpu[NR_CPUS];
 };
 
+/* Log2 of the number of small pages needed for the egress queue. */
+#define EQ_ORDER  get_order(sizeof(lepp_queue_t))
+/* Size of the egress queue's pages. */
+#define EQ_SIZE   (1 << (PAGE_SHIFT + EQ_ORDER))
 
 /*
  * The actual devices (xgbe0, xgbe1, gbe0, gbe1).
@@ -284,7 +286,11 @@
  */
 static void dump_packet(unsigned char *data, unsigned long length, char *s)
 {
+	int my_cpu = smp_processor_id();
+
 	unsigned long i;
+	char buf[128];
+
 	static unsigned int count;
 
 	pr_info("dump_packet(data %p, length 0x%lx s %s count 0x%x)\n",
@@ -294,10 +300,12 @@
 
 	for (i = 0; i < length; i++) {
 		if ((i & 0xf) == 0)
-			sprintf(buf, "%8.8lx:", i);
+			sprintf(buf, "[%02d] %8.8lx:", my_cpu, i);
 		sprintf(buf + strlen(buf), " %2.2x", data[i]);
-		if ((i & 0xf) == 0xf || i == length - 1)
-			pr_info("%s\n", buf);
+		if ((i & 0xf) == 0xf || i == length - 1) {
+			strcat(buf, "\n");
+			pr_info("%s", buf);
+		}
 	}
 }
 #endif
@@ -351,60 +359,109 @@
 
 /*
  * Provide a linux buffer for LIPP.
+ *
+ * Note that the ACTUAL allocation for each buffer is a "struct sk_buff",
+ * plus a chunk of memory that includes not only the requested bytes, but
+ * also NET_SKB_PAD bytes of initial padding, and a "struct skb_shared_info".
+ *
+ * Note that "struct skb_shared_info" is 88 bytes with 64K pages and
+ * 268 bytes with 4K pages (since the frags[] array needs 18 entries).
+ *
+ * Without jumbo packets, the maximum packet size will be 1536 bytes,
+ * and we use 2 bytes (NET_IP_ALIGN) of padding.  ISSUE: If we told
+ * the hardware to clip at 1518 bytes instead of 1536 bytes, then we
+ * could save an entire cache line, but in practice, we don't need it.
+ *
+ * Since CPAs are 38 bits, and we can only encode the high 31 bits in
+ * a "linux_buffer_t", the low 7 bits must be zero, and thus, we must
+ * align the actual "va" mod 128.
+ *
+ * We assume that the underlying "head" will be aligned mod 64.  Note
+ * that in practice, we have seen "head" NOT aligned mod 128 even when
+ * using 2048 byte allocations, which is surprising.
+ *
+ * If "head" WAS always aligned mod 128, we could change LIPP to
+ * assume that the low SIX bits are zero, and the 7th bit is one, that
+ * is, align the actual "va" mod 128 plus 64, which would be "free".
+ *
+ * For now, the actual "head" pointer points at NET_SKB_PAD bytes of
+ * padding, plus 28 or 92 bytes of extra padding, plus the sk_buff
+ * pointer, plus the NET_IP_ALIGN padding, plus 126 or 1536 bytes for
+ * the actual packet, plus 62 bytes of empty padding, plus some
+ * padding and the "struct skb_shared_info".
+ *
+ * With 64K pages, a large buffer thus needs 32+92+4+2+1536+62+88
+ * bytes, or 1816 bytes, which fits comfortably into 2048 bytes.
+ *
+ * With 64K pages, a small buffer thus needs 32+92+4+2+126+88
+ * bytes, or 344 bytes, which means we are wasting 64+ bytes, and
+ * could presumably increase the size of small buffers.
+ *
+ * With 4K pages, a large buffer thus needs 32+92+4+2+1536+62+268
+ * bytes, or 1996 bytes, which fits comfortably into 2048 bytes.
+ *
+ * With 4K pages, a small buffer thus needs 32+92+4+2+126+268
+ * bytes, or 524 bytes, which is annoyingly wasteful.
+ *
+ * Maybe we should increase LIPP_SMALL_PACKET_SIZE to 192?
+ *
+ * ISSUE: Maybe we should increase "NET_SKB_PAD" to 64?
  */
 static bool tile_net_provide_needed_buffer(struct tile_net_cpu *info,
 					   bool small)
 {
-	/* ISSUE: What should we use here? */
+#if TILE_NET_MTU <= 1536
+	/* Without "jumbo", 2 + 1536 should be sufficient. */
+	unsigned int large_size = NET_IP_ALIGN + 1536;
+#else
+	/* ISSUE: This has not been tested. */
 	unsigned int large_size = NET_IP_ALIGN + TILE_NET_MTU + 100;
+#endif
 
-	/* Round up to ensure to avoid "false sharing" with last cache line. */
-	unsigned int buffer_size =
+	/* Avoid "false sharing" with last cache line. */
+	/* ISSUE: This is already done by "dev_alloc_skb()". */
+	unsigned int len =
 		 (((small ? LIPP_SMALL_PACKET_SIZE : large_size) +
 		   CHIP_L2_LINE_SIZE() - 1) & -CHIP_L2_LINE_SIZE());
 
-	/*
-	 * ISSUE: Since CPAs are 38 bits, and we can only encode the
-	 * high 31 bits in a "linux_buffer_t", the low 7 bits must be
-	 * zero, and thus, we must align the actual "va" mod 128.
-	 */
-	const unsigned long align = 128;
+	unsigned int padding = 128 - NET_SKB_PAD;
+	unsigned int align;
 
 	struct sk_buff *skb;
 	void *va;
 
 	struct sk_buff **skb_ptr;
 
-	/* Note that "dev_alloc_skb()" adds NET_SKB_PAD more bytes, */
-	/* and also "reserves" that many bytes. */
-	/* ISSUE: Can we "share" the NET_SKB_PAD bytes with "skb_ptr"? */
-	int len = sizeof(*skb_ptr) + align + buffer_size;
-
-	while (1) {
-
-		/* Allocate (or fail). */
-		skb = dev_alloc_skb(len);
-		if (skb == NULL)
-			return false;
-
-		/* Make room for a back-pointer to 'skb'. */
-		skb_reserve(skb, sizeof(*skb_ptr));
+	/* Request 96 extra bytes for alignment purposes. */
+	skb = dev_alloc_skb(len + padding);
+	if (skb == NULL)
+		return false;
 
-		/* Make sure we are aligned. */
-		skb_reserve(skb, -(long)skb->data & (align - 1));
+	/* Skip 32 or 96 bytes to align "data" mod 128. */
+	align = -(long)skb->data & (128 - 1);
+	BUG_ON(align > padding);
+	skb_reserve(skb, align);
 
-		/* This address is given to IPP. */
-		va = skb->data;
+	/* This address is given to IPP. */
+	va = skb->data;
 
-		if (small)
-			break;
+	/* Buffers must not span a huge page. */
+	BUG_ON(((((long)va & ~HPAGE_MASK) + len) & HPAGE_MASK) != 0);
 
-		/* ISSUE: This has never been observed! */
-		/* Large buffers must not span a huge page. */
-		if (((((long)va & ~HPAGE_MASK) + 1535) & HPAGE_MASK) == 0)
-			break;
-		pr_err("Leaking unaligned linux buffer at %p.\n", va);
+#ifdef TILE_NET_PARANOIA
+#if CHIP_HAS_CBOX_HOME_MAP()
+	if (hash_default) {
+		HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va);
+		if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
+			panic("Non-HFH ingress buffer! VA=%p Mode=%d PTE=%llx",
+			      va, hv_pte_get_mode(pte), hv_pte_val(pte));
 	}
+#endif
+#endif
+
+	/* Invalidate the packet buffer. */
+	if (!hash_default)
+		__inv_buffer(va, len);
 
 	/* Skip two bytes to satisfy LIPP assumptions. */
 	/* Note that this aligns IP on a 16 byte boundary. */
@@ -415,23 +472,9 @@
 	skb_ptr = va - sizeof(*skb_ptr);
 	*skb_ptr = skb;
 
-	/* Invalidate the packet buffer. */
-	if (!hash_default)
-		__inv_buffer(skb->data, buffer_size);
-
 	/* Make sure "skb_ptr" has been flushed. */
 	__insn_mf();
 
-#ifdef TILE_NET_PARANOIA
-#if CHIP_HAS_CBOX_HOME_MAP()
-	if (hash_default) {
-		HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)va);
-		if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
-			panic("Non-coherent ingress buffer!");
-	}
-#endif
-#endif
-
 	/* Provide the new buffer. */
 	tile_net_provide_linux_buffer(info, va, small);
 
@@ -469,48 +512,64 @@
  * Grab some LEPP completions, and store them in "comps", of size
  * "comps_size", and return the number of completions which were
  * stored, so the caller can free them.
- *
- * If "pending" is not NULL, it will be set to true if there might
- * still be some pending completions caused by this tile, else false.
  */
-static unsigned int tile_net_lepp_grab_comps(struct net_device *dev,
+static unsigned int tile_net_lepp_grab_comps(lepp_queue_t *eq,
 					     struct sk_buff *comps[],
 					     unsigned int comps_size,
-					     bool *pending)
+					     unsigned int min_size)
 {
-	struct tile_net_priv *priv = netdev_priv(dev);
-
-	lepp_queue_t *eq = priv->epp_queue;
-
 	unsigned int n = 0;
 
-	unsigned int comp_head;
-	unsigned int comp_busy;
-	unsigned int comp_tail;
-
-	spin_lock(&priv->comp_lock);
-
-	comp_head = eq->comp_head;
-	comp_busy = eq->comp_busy;
-	comp_tail = eq->comp_tail;
+	unsigned int comp_head = eq->comp_head;
+	unsigned int comp_busy = eq->comp_busy;
 
 	while (comp_head != comp_busy && n < comps_size) {
 		comps[n++] = eq->comps[comp_head];
 		LEPP_QINC(comp_head);
 	}
 
-	if (pending != NULL)
-		*pending = (comp_head != comp_tail);
+	if (n < min_size)
+		return 0;
 
 	eq->comp_head = comp_head;
 
-	spin_unlock(&priv->comp_lock);
-
 	return n;
 }
 
 
 /*
+ * Free some comps, and return true iff there are still some pending.
+ */
+static bool tile_net_lepp_free_comps(struct net_device *dev, bool all)
+{
+	struct tile_net_priv *priv = netdev_priv(dev);
+
+	lepp_queue_t *eq = priv->eq;
+
+	struct sk_buff *olds[64];
+	unsigned int wanted = 64;
+	unsigned int i, n;
+	bool pending;
+
+	spin_lock(&priv->eq_lock);
+
+	if (all)
+		eq->comp_busy = eq->comp_tail;
+
+	n = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+
+	pending = (eq->comp_head != eq->comp_tail);
+
+	spin_unlock(&priv->eq_lock);
+
+	for (i = 0; i < n; i++)
+		kfree_skb(olds[i]);
+
+	return pending;
+}
+
+
+/*
  * Make sure the egress timer is scheduled.
  *
  * Note that we use "schedule if not scheduled" logic instead of the more
@@ -544,21 +603,11 @@
 	struct tile_net_cpu *info = (struct tile_net_cpu *)arg;
 	struct net_device *dev = info->napi.dev;
 
-	struct sk_buff *olds[32];
-	unsigned int wanted = 32;
-	unsigned int i, nolds = 0;
-	bool pending;
-
 	/* The timer is no longer scheduled. */
 	info->egress_timer_scheduled = false;
 
-	nolds = tile_net_lepp_grab_comps(dev, olds, wanted, &pending);
-
-	for (i = 0; i < nolds; i++)
-		kfree_skb(olds[i]);
-
-	/* Reschedule timer if needed. */
-	if (pending)
+	/* Free comps, and reschedule timer if more are pending. */
+	if (tile_net_lepp_free_comps(dev, false))
 		tile_net_schedule_egress_timer(info);
 }
 
@@ -636,8 +685,39 @@
 
 
 
+static void tile_net_discard_aux(struct tile_net_cpu *info, int index)
+{
+	struct tile_netio_queue *queue = &info->queue;
+	netio_queue_impl_t *qsp = queue->__system_part;
+	netio_queue_user_impl_t *qup = &queue->__user_part;
+
+	int index2_aux = index + sizeof(netio_pkt_t);
+	int index2 =
+		((index2_aux ==
+		  qsp->__packet_receive_queue.__last_packet_plus_one) ?
+		 0 : index2_aux);
+
+	netio_pkt_t *pkt = (netio_pkt_t *)((unsigned long) &qsp[1] + index);
+
+	/* Extract the "linux_buffer_t". */
+	unsigned int buffer = pkt->__packet.word;
+
+	/* Convert "linux_buffer_t" to "va". */
+	void *va = __va((phys_addr_t)(buffer >> 1) << 7);
+
+	/* Acquire the associated "skb". */
+	struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
+	struct sk_buff *skb = *skb_ptr;
+
+	kfree_skb(skb);
+
+	/* Consume this packet. */
+	qup->__packet_receive_read = index2;
+}
+
+
 /*
- * Like "tile_net_handle_packets()", but just discard packets.
+ * Like "tile_net_poll()", but just discard packets.
  */
 static void tile_net_discard_packets(struct net_device *dev)
 {
@@ -650,32 +730,8 @@
 
 	while (qup->__packet_receive_read !=
 	       qsp->__packet_receive_queue.__packet_write) {
-
 		int index = qup->__packet_receive_read;
-
-		int index2_aux = index + sizeof(netio_pkt_t);
-		int index2 =
-			((index2_aux ==
-			  qsp->__packet_receive_queue.__last_packet_plus_one) ?
-			 0 : index2_aux);
-
-		netio_pkt_t *pkt = (netio_pkt_t *)
-			((unsigned long) &qsp[1] + index);
-
-		/* Extract the "linux_buffer_t". */
-		unsigned int buffer = pkt->__packet.word;
-
-		/* Convert "linux_buffer_t" to "va". */
-		void *va = __va((phys_addr_t)(buffer >> 1) << 7);
-
-		/* Acquire the associated "skb". */
-		struct sk_buff **skb_ptr = va - sizeof(*skb_ptr);
-		struct sk_buff *skb = *skb_ptr;
-
-		kfree_skb(skb);
-
-		/* Consume this packet. */
-		qup->__packet_receive_read = index2;
+		tile_net_discard_aux(info, index);
 	}
 }
 
@@ -704,7 +760,8 @@
 
 	netio_pkt_metadata_t *metadata = NETIO_PKT_METADATA(pkt);
 
-	/* Extract the packet size. */
+	/* Extract the packet size.  FIXME: Shouldn't the second line */
+	/* get subtracted?  Mostly moot, since it should be "zero". */
 	unsigned long len =
 		(NETIO_PKT_CUSTOM_LENGTH(pkt) +
 		 NET_IP_ALIGN - NETIO_PACKET_PADDING);
@@ -722,15 +779,6 @@
 	/* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
 	unsigned char *buf = va + NET_IP_ALIGN;
 
-#ifdef IGNORE_DUP_ACKS
-
-	static int other;
-	static int final;
-	static int keep;
-	static int skip;
-
-#endif
-
 	/* Invalidate the packet buffer. */
 	if (!hash_default)
 		__inv_buffer(buf, len);
@@ -745,16 +793,8 @@
 #ifdef TILE_NET_VERIFY_INGRESS
 	if (!NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt) &&
 	    NETIO_PKT_L4_CSUM_CALCULATED_M(metadata, pkt)) {
-		/*
-		 * FIXME: This complains about UDP packets
-		 * with a "zero" checksum (bug 6624).
-		 */
-#ifdef TILE_NET_PANIC_ON_BAD
-		dump_packet(buf, len, "rx");
-		panic("Bad L4 checksum.");
-#else
+		/* Bug 6624: Includes UDP packets with a "zero" checksum. */
 		pr_warning("Bad L4 checksum on %d byte packet.\n", len);
-#endif
 	}
 	if (!NETIO_PKT_L3_CSUM_CORRECT_M(metadata, pkt) &&
 	    NETIO_PKT_L3_CSUM_CALCULATED_M(metadata, pkt)) {
@@ -769,90 +809,29 @@
 		}
 		break;
 	case NETIO_PKT_STATUS_BAD:
-#ifdef TILE_NET_PANIC_ON_BAD
-		dump_packet(buf, len, "rx");
-		panic("Unexpected BAD packet.");
-#else
-		pr_warning("Unexpected BAD %d byte packet.\n", len);
-#endif
+		pr_warning("Unexpected BAD %ld byte packet.\n", len);
 	}
 #endif
 
 	filter = 0;
 
+	/* ISSUE: Filter TCP packets with "bad" checksums? */
+
 	if (!(dev->flags & IFF_UP)) {
 		/* Filter packets received before we're up. */
 		filter = 1;
+	} else if (NETIO_PKT_STATUS_M(metadata, pkt) == NETIO_PKT_STATUS_BAD) {
+		/* Filter "truncated" packets. */
+		filter = 1;
 	} else if (!(dev->flags & IFF_PROMISC)) {
-		/*
-		 * FIXME: Implement HW multicast filter.
-		 */
-		if (is_unicast_ether_addr(buf)) {
+		/* FIXME: Implement HW multicast filter. */
+		if (!is_multicast_ether_addr(buf)) {
 			/* Filter packets not for our address. */
 			const u8 *mine = dev->dev_addr;
 			filter = compare_ether_addr(mine, buf);
 		}
 	}
 
-#ifdef IGNORE_DUP_ACKS
-
-	if (len != 66) {
-		/* FIXME: Must check "is_tcp_ack(buf, len)" somehow. */
-
-		other++;
-
-	} else if (index2 ==
-		   qsp->__packet_receive_queue.__packet_write) {
-
-		final++;
-
-	} else {
-
-		netio_pkt_t *pkt2 = (netio_pkt_t *)
-			((unsigned long) &qsp[1] + index2);
-
-		netio_pkt_metadata_t *metadata2 =
-			NETIO_PKT_METADATA(pkt2);
-
-		/* Extract the packet size. */
-		unsigned long len2 =
-			(NETIO_PKT_CUSTOM_LENGTH(pkt2) +
-			 NET_IP_ALIGN - NETIO_PACKET_PADDING);
-
-		if (len2 == 66 &&
-		    NETIO_PKT_FLOW_HASH_M(metadata, pkt) ==
-		    NETIO_PKT_FLOW_HASH_M(metadata2, pkt2)) {
-
-			/* Extract the "linux_buffer_t". */
-			unsigned int buffer2 = pkt2->__packet.word;
-
-			/* Convert "linux_buffer_t" to "va". */
-			void *va2 =
-				__va((phys_addr_t)(buffer2 >> 1) << 7);
-
-			/* Extract the packet data pointer. */
-			/* Compare to "NETIO_PKT_CUSTOM_DATA(pkt)". */
-			unsigned char *buf2 = va2 + NET_IP_ALIGN;
-
-			/* Invalidate the packet buffer. */
-			if (!hash_default)
-				__inv_buffer(buf2, len2);
-
-			if (is_dup_ack(buf, buf2, len)) {
-				skip++;
-				filter = 1;
-			} else {
-				keep++;
-			}
-		}
-	}
-
-	if (net_ratelimit())
-		pr_info("Other %d Final %d Keep %d Skip %d.\n",
-			other, final, keep, skip);
-
-#endif
-
 	if (filter) {
 
 		/* ISSUE: Update "drop" statistics? */
@@ -877,10 +856,7 @@
 		/* NOTE: This call also sets "skb->dev = dev". */
 		skb->protocol = eth_type_trans(skb, dev);
 
-		/* ISSUE: Discard corrupt packets? */
-		/* ISSUE: Discard packets with bad checksums? */
-
-		/* Avoid recomputing TCP/UDP checksums. */
+		/* Avoid recomputing "good" TCP/UDP checksums. */
 		if (NETIO_PKT_L4_CSUM_CORRECT_M(metadata, pkt))
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
@@ -912,9 +888,14 @@
 /*
  * Handle some packets for the given device on the current CPU.
  *
- * ISSUE: The "rotting packet" race condition occurs if a packet
- * arrives after the queue appears to be empty, and before the
- * hypervisor interrupt is re-enabled.
+ * If "tile_net_stop()" is called on some other tile while this
+ * function is running, we will return, hopefully before that
+ * other tile asks us to call "napi_disable()".
+ *
+ * The "rotting packet" race condition occurs if a packet arrives
+ * during the extremely narrow window between the queue appearing to
+ * be empty, and the ingress interrupt being re-enabled.  This happens
+ * a LOT under heavy network load.
  */
 static int tile_net_poll(struct napi_struct *napi, int budget)
 {
@@ -928,7 +909,7 @@
 
 	unsigned int work = 0;
 
-	while (1) {
+	while (priv->active) {
 		int index = qup->__packet_receive_read;
 		if (index == qsp->__packet_receive_queue.__packet_write)
 			break;
@@ -941,19 +922,24 @@
 
 	napi_complete(&info->napi);
 
-	/* Re-enable hypervisor interrupts. */
+	if (!priv->active)
+		goto done;
+
+	/* Re-enable the ingress interrupt. */
 	enable_percpu_irq(priv->intr_id);
 
-	/* HACK: Avoid the "rotting packet" problem. */
+	/* HACK: Avoid the "rotting packet" problem (see above). */
 	if (qup->__packet_receive_read !=
-	    qsp->__packet_receive_queue.__packet_write)
-		napi_schedule(&info->napi);
-
-	/* ISSUE: Handle completions? */
+	    qsp->__packet_receive_queue.__packet_write) {
+		/* ISSUE: Sometimes this returns zero, presumably */
+		/* because an interrupt was handled for this tile. */
+		(void)napi_reschedule(&info->napi);
+	}
 
 done:
 
-	tile_net_provide_needed_buffers(info);
+	if (priv->active)
+		tile_net_provide_needed_buffers(info);
 
 	return work;
 }
@@ -961,6 +947,12 @@
 
 /*
  * Handle an ingress interrupt for the given device on the current cpu.
+ *
+ * ISSUE: Sometimes this gets called after "disable_percpu_irq()" has
+ * been called!  This is probably due to "pending hypervisor downcalls".
+ *
+ * ISSUE: Is there any race condition between the "napi_schedule()" here
+ * and the "napi_complete()" call above?
  */
 static irqreturn_t tile_net_handle_ingress_interrupt(int irq, void *dev_ptr)
 {
@@ -969,9 +961,15 @@
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	/* Disable hypervisor interrupt. */
+	/* Disable the ingress interrupt. */
 	disable_percpu_irq(priv->intr_id);
 
+	/* Ignore unwanted interrupts. */
+	if (!priv->active)
+		return IRQ_HANDLED;
+
+	/* ISSUE: Sometimes "info->napi_enabled" is false here. */
+
 	napi_schedule(&info->napi);
 
 	return IRQ_HANDLED;
@@ -1005,8 +1003,7 @@
 	 */
 	{
 		int epp_home = hv_lotar_to_cpu(epp_lotar);
-		struct page *page = virt_to_page(priv->epp_queue);
-		homecache_change_page_home(page, 0, epp_home);
+		homecache_change_page_home(priv->eq_pages, EQ_ORDER, epp_home);
 	}
 
 	/*
@@ -1015,9 +1012,9 @@
 	{
 		netio_ipp_address_t ea = {
 			.va = 0,
-			.pa = __pa(priv->epp_queue),
+			.pa = __pa(priv->eq),
 			.pte = hv_pte(0),
-			.size = PAGE_SIZE,
+			.size = EQ_SIZE,
 		};
 		ea.pte = hv_pte_set_lotar(ea.pte, epp_lotar);
 		ea.pte = hv_pte_set_mode(ea.pte, HV_PTE_MODE_CACHE_TILE_L3);
@@ -1043,7 +1040,7 @@
 
 
 /*
- * Register with hypervisor on each CPU.
+ * Register with hypervisor on the current CPU.
  *
  * Strangely, this function does important things even if it "fails",
  * which is especially common if the link is not up yet.  Hopefully
@@ -1092,7 +1089,8 @@
 	priv->cpu[my_cpu] = info;
 
 	/*
-	 * Register ourselves with the IPP.
+	 * Register ourselves with LIPP.  This does a lot of stuff,
+	 * including invoking the LIPP registration code.
 	 */
 	ret = hv_dev_pwrite(priv->hv_devhdl, 0,
 			    (HV_VirtAddr)&config,
@@ -1101,8 +1099,11 @@
 	PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_REGISTER_OFF) returned %d\n",
 	       ret);
 	if (ret < 0) {
-		printk(KERN_DEBUG "hv_dev_pwrite NETIO_IPP_INPUT_REGISTER_OFF"
-		       " failure %d\n", ret);
+		if (ret != NETIO_LINK_DOWN) {
+			printk(KERN_DEBUG "hv_dev_pwrite "
+			       "NETIO_IPP_INPUT_REGISTER_OFF failure %d\n",
+			       ret);
+		}
 		info->link_down = (ret == NETIO_LINK_DOWN);
 		return;
 	}
@@ -1145,15 +1146,47 @@
 			   NETIO_IPP_GET_FASTIO_OFF);
 	PDEBUG("hv_dev_pread(NETIO_IPP_GET_FASTIO_OFF) returned %d\n", ret);
 
-	netif_napi_add(dev, &info->napi, tile_net_poll, 64);
-
 	/* Now we are registered. */
 	info->registered = true;
 }
 
 
 /*
- * Unregister with hypervisor on each CPU.
+ * Deregister with hypervisor on the current CPU.
+ *
+ * This simply discards all our credits, so no more packets will be
+ * delivered to this tile.  There may still be packets in our queue.
+ *
+ * Also, disable the ingress interrupt.
+ */
+static void tile_net_deregister(void *dev_ptr)
+{
+	struct net_device *dev = (struct net_device *)dev_ptr;
+	struct tile_net_priv *priv = netdev_priv(dev);
+	int my_cpu = smp_processor_id();
+	struct tile_net_cpu *info = priv->cpu[my_cpu];
+
+	/* Disable the ingress interrupt. */
+	disable_percpu_irq(priv->intr_id);
+
+	/* Do nothing else if not registered. */
+	if (info == NULL || !info->registered)
+		return;
+
+	{
+		struct tile_netio_queue *queue = &info->queue;
+		netio_queue_user_impl_t *qup = &queue->__user_part;
+
+		/* Discard all our credits. */
+		__netio_fastio_return_credits(qup->__fastio_index, -1);
+	}
+}
+
+
+/*
+ * Unregister with hypervisor on the current CPU.
+ *
+ * Also, disable the ingress interrupt.
  */
 static void tile_net_unregister(void *dev_ptr)
 {
@@ -1162,35 +1195,23 @@
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	int ret = 0;
+	int ret;
 	int dummy = 0;
 
-	/* Do nothing if never registered. */
-	if (info == NULL)
-		return;
+	/* Disable the ingress interrupt. */
+	disable_percpu_irq(priv->intr_id);
 
-	/* Do nothing if already unregistered. */
-	if (!info->registered)
+	/* Do nothing else if not registered. */
+	if (info == NULL || !info->registered)
 		return;
 
-	/*
-	 * Unregister ourselves with LIPP.
-	 */
+	/* Unregister ourselves with LIPP/LEPP. */
 	ret = hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
 			    sizeof(dummy), NETIO_IPP_INPUT_UNREGISTER_OFF);
-	PDEBUG("hv_dev_pwrite(NETIO_IPP_INPUT_UNREGISTER_OFF) returned %d\n",
-	       ret);
-	if (ret < 0) {
-		/* FIXME: Just panic? */
-		pr_err("hv_dev_pwrite NETIO_IPP_INPUT_UNREGISTER_OFF"
-		       " failure %d\n", ret);
-	}
+	if (ret < 0)
+		panic("Failed to unregister with LIPP/LEPP!\n");
 
-	/*
-	 * Discard all packets still in our NetIO queue.  Hopefully,
-	 * once the unregister call is complete, there will be no
-	 * packets still in flight on the IDN.
-	 */
+	/* Discard all packets still in our NetIO queue. */
 	tile_net_discard_packets(dev);
 
 	/* Reset state. */
@@ -1200,11 +1221,6 @@
 	/* Cancel egress timer. */
 	del_timer(&info->egress_timer);
 	info->egress_timer_scheduled = false;
-
-	netif_napi_del(&info->napi);
-
-	/* Now we are unregistered. */
-	info->registered = false;
 }
 
 
@@ -1212,18 +1228,28 @@
  * Helper function for "tile_net_stop()".
  *
  * Also used to handle registration failure in "tile_net_open_inner()",
- * when "fully_opened" is known to be false, and the various extra
- * steps in "tile_net_stop()" are not necessary.  ISSUE: It might be
- * simpler if we could just call "tile_net_stop()" anyway.
+ * when the various extra steps in "tile_net_stop()" are not necessary.
  */
 static void tile_net_stop_aux(struct net_device *dev)
 {
 	struct tile_net_priv *priv = netdev_priv(dev);
+	int i;
 
 	int dummy = 0;
 
-	/* Unregister all tiles, so LIPP will stop delivering packets. */
+	/*
+	 * Unregister all tiles, so LIPP will stop delivering packets.
+	 * Also, delete all the "napi" objects (sequentially, to protect
+	 * "dev->napi_list").
+	 */
 	on_each_cpu(tile_net_unregister, (void *)dev, 1);
+	for_each_online_cpu(i) {
+		struct tile_net_cpu *info = priv->cpu[i];
+		if (info != NULL && info->registered) {
+			netif_napi_del(&info->napi);
+			info->registered = false;
+		}
+	}
 
 	/* Stop LIPP/LEPP. */
 	if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
@@ -1235,18 +1261,15 @@
 
 
 /*
- * Disable ingress interrupts for the given device on the current cpu.
+ * Disable NAPI for the given device on the current cpu.
  */
-static void tile_net_disable_intr(void *dev_ptr)
+static void tile_net_stop_disable(void *dev_ptr)
 {
 	struct net_device *dev = (struct net_device *)dev_ptr;
 	struct tile_net_priv *priv = netdev_priv(dev);
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	/* Disable hypervisor interrupt. */
-	disable_percpu_irq(priv->intr_id);
-
 	/* Disable NAPI if needed. */
 	if (info != NULL && info->napi_enabled) {
 		napi_disable(&info->napi);
@@ -1256,21 +1279,24 @@
 
 
 /*
- * Enable ingress interrupts for the given device on the current cpu.
+ * Enable NAPI and the ingress interrupt for the given device
+ * on the current cpu.
+ *
+ * ISSUE: Only do this for "network cpus"?
  */
-static void tile_net_enable_intr(void *dev_ptr)
+static void tile_net_open_enable(void *dev_ptr)
 {
 	struct net_device *dev = (struct net_device *)dev_ptr;
 	struct tile_net_priv *priv = netdev_priv(dev);
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info = priv->cpu[my_cpu];
 
-	/* Enable hypervisor interrupt. */
-	enable_percpu_irq(priv->intr_id);
-
 	/* Enable NAPI. */
 	napi_enable(&info->napi);
 	info->napi_enabled = true;
+
+	/* Enable the ingress interrupt. */
+	enable_percpu_irq(priv->intr_id);
 }
 
 
@@ -1288,8 +1314,9 @@
 	int my_cpu = smp_processor_id();
 	struct tile_net_cpu *info;
 	struct tile_netio_queue *queue;
-	unsigned int irq;
+	int result = 0;
 	int i;
+	int dummy = 0;
 
 	/*
 	 * First try to register just on the local CPU, and handle any
@@ -1307,42 +1334,52 @@
 	/*
 	 * Now register everywhere else.  If any registration fails,
 	 * even for "link down" (which might not be possible), we
-	 * clean up using "tile_net_stop_aux()".
+	 * clean up using "tile_net_stop_aux()".  Also, add all the
+	 * "napi" objects (sequentially, to protect "dev->napi_list").
+	 * ISSUE: Only use "netif_napi_add()" for "network cpus"?
 	 */
 	smp_call_function(tile_net_register, (void *)dev, 1);
 	for_each_online_cpu(i) {
-		if (!priv->cpu[i]->registered) {
-			tile_net_stop_aux(dev);
-			return -EAGAIN;
-		}
+		struct tile_net_cpu *info = priv->cpu[i];
+		if (info->registered)
+			netif_napi_add(dev, &info->napi, tile_net_poll, 64);
+		else
+			result = -EAGAIN;
+	}
+	if (result != 0) {
+		tile_net_stop_aux(dev);
+		return result;
 	}
 
 	queue = &info->queue;
 
-	/*
-	 * Set the device intr bit mask.
-	 * The tile_net_register above sets per tile __intr_id.
-	 */
-	priv->intr_id = queue->__system_part->__intr_id;
-	BUG_ON(!priv->intr_id);
-
-	/*
-	 * Register the device interrupt handler.
-	 * The __ffs() function returns the index into the interrupt handler
-	 * table from the interrupt bit mask which should have one bit
-	 * and one bit only set.
-	 */
-	irq = __ffs(priv->intr_id);
-	tile_irq_activate(irq, TILE_IRQ_PERCPU);
-	BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt,
-			   0, dev->name, (void *)dev) != 0);
-
-	/* ISSUE: How could "priv->fully_opened" ever be "true" here? */
+	if (priv->intr_id == 0) {
+		unsigned int irq;
 
-	if (!priv->fully_opened) {
+		/*
+		 * Acquire the irq allocated by the hypervisor.  Every
+		 * queue gets the same irq.  The "__intr_id" field is
+		 * "1 << irq", so we use "__ffs()" to extract "irq".
+		 */
+		priv->intr_id = queue->__system_part->__intr_id;
+		BUG_ON(priv->intr_id == 0);
+		irq = __ffs(priv->intr_id);
 
-		int dummy = 0;
+		/*
+		 * Register the ingress interrupt handler for this
+		 * device, permanently.
+		 *
+		 * We used to call "free_irq()" in "tile_net_stop()",
+		 * and then re-register the handler here every time,
+		 * but that caused DNP errors in "handle_IRQ_event()"
+		 * because "desc->action" was NULL.  See bug 9143.
+		 */
+		tile_irq_activate(irq, TILE_IRQ_PERCPU);
+		BUG_ON(request_irq(irq, tile_net_handle_ingress_interrupt,
+				   0, dev->name, (void *)dev) != 0);
+	}
 
+	{
 		/* Allocate initial buffers. */
 
 		int max_buffers =
@@ -1359,18 +1396,21 @@
 		if (info->num_needed_small_buffers != 0 ||
 		    info->num_needed_large_buffers != 0)
 			panic("Insufficient memory for buffer stack!");
+	}
 
-		/* Start LIPP/LEPP and activate "ingress" at the shim. */
-		if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
-				  sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0)
-			panic("Failed to activate the LIPP Shim!\n");
+	/* We are about to be active. */
+	priv->active = true;
 
-		priv->fully_opened = 1;
-	}
+	/* Make sure "active" is visible to all tiles. */
+	mb();
 
-	/* On each tile, enable the hypervisor to trigger interrupts. */
-	/* ISSUE: Do this before starting LIPP/LEPP? */
-	on_each_cpu(tile_net_enable_intr, (void *)dev, 1);
+	/* On each tile, enable NAPI and the ingress interrupt. */
+	on_each_cpu(tile_net_open_enable, (void *)dev, 1);
+
+	/* Start LIPP/LEPP and activate "ingress" at the shim. */
+	if (hv_dev_pwrite(priv->hv_devhdl, 0, (HV_VirtAddr)&dummy,
+			  sizeof(dummy), NETIO_IPP_INPUT_INIT_OFF) < 0)
+		panic("Failed to activate the LIPP Shim!\n");
 
 	/* Start our transmit queue. */
 	netif_start_queue(dev);
@@ -1396,9 +1436,9 @@
 	 * ourselves to try again later; otherwise, tell Linux we now have
 	 * a working link.  ISSUE: What if the return value is negative?
 	 */
-	if (tile_net_open_inner(priv->dev))
-		schedule_delayed_work_on(singlethread_cpu, &priv->retry_work,
-					 TILE_NET_RETRY_INTERVAL);
+	if (tile_net_open_inner(priv->dev) != 0)
+		schedule_delayed_work(&priv->retry_work,
+				      TILE_NET_RETRY_INTERVAL);
 	else
 		netif_carrier_on(priv->dev);
 }
@@ -1412,8 +1452,8 @@
  * The open entry point is called when a network interface is made
  * active by the system (IFF_UP).  At this point all resources needed
  * for transmit and receive operations are allocated, the interrupt
- * handler is registered with the OS, the watchdog timer is started,
- * and the stack is notified that the interface is ready.
+ * handler is registered with the OS (if needed), the watchdog timer
+ * is started, and the stack is notified that the interface is ready.
  *
  * If the actual link is not available yet, then we tell Linux that
  * we have no carrier, and we keep checking until the link comes up.
@@ -1468,6 +1508,10 @@
 #endif
 
 		priv->partly_opened = 1;
+
+	} else {
+		/* FIXME: Is this possible? */
+		/* printk("Already partly opened.\n"); */
 	}
 
 	/*
@@ -1487,57 +1531,17 @@
 	 * and then remember to try again later.
 	 */
 	netif_carrier_off(dev);
-	schedule_delayed_work_on(singlethread_cpu, &priv->retry_work,
-				 TILE_NET_RETRY_INTERVAL);
+	schedule_delayed_work(&priv->retry_work, TILE_NET_RETRY_INTERVAL);
 
 	return 0;
 }
 
 
-/*
- * Disables a network interface.
- *
- * Returns 0, this is not allowed to fail.
- *
- * The close entry point is called when an interface is de-activated
- * by the OS.  The hardware is still under the drivers control, but
- * needs to be disabled.  A global MAC reset is issued to stop the
- * hardware, and all transmit and receive resources are freed.
- *
- * ISSUE: Can this can be called while "tile_net_poll()" is running?
- */
-static int tile_net_stop(struct net_device *dev)
+static int tile_net_drain_lipp_buffers(struct tile_net_priv *priv)
 {
-	struct tile_net_priv *priv = netdev_priv(dev);
-
-	bool pending = true;
-
-	PDEBUG("tile_net_stop()\n");
-
-	/* ISSUE: Only needed if not yet fully open. */
-	cancel_delayed_work_sync(&priv->retry_work);
-
-	/* Can't transmit any more. */
-	netif_stop_queue(dev);
-
-	/*
-	 * Disable hypervisor interrupts on each tile.
-	 */
-	on_each_cpu(tile_net_disable_intr, (void *)dev, 1);
-
-	/*
-	 * Unregister the interrupt handler.
-	 * The __ffs() function returns the index into the interrupt handler
-	 * table from the interrupt bit mask which should have one bit
-	 * and one bit only set.
-	 */
-	if (priv->intr_id)
-		free_irq(__ffs(priv->intr_id), dev);
-
-	/*
-	 * Drain all the LIPP buffers.
-	 */
+	int n = 0;
 
+	/* Drain all the LIPP buffers. */
 	while (true) {
 		int buffer;
 
@@ -1560,43 +1564,105 @@
 
 			kfree_skb(skb);
 		}
+
+		n++;
 	}
 
-	/* Stop LIPP/LEPP. */
-	tile_net_stop_aux(dev);
+	return n;
+}
 
 
-	priv->fully_opened = 0;
+/*
+ * Disables a network interface.
+ *
+ * Returns 0, this is not allowed to fail.
+ *
+ * The close entry point is called when an interface is de-activated
+ * by the OS.  The hardware is still under the drivers control, but
+ * needs to be disabled.  A global MAC reset is issued to stop the
+ * hardware, and all transmit and receive resources are freed.
+ *
+ * ISSUE: How closely does "netif_running(dev)" mirror "priv->active"?
+ *
+ * Before we are called by "__dev_close()", "netif_running()" will
+ * have been cleared, so no NEW calls to "tile_net_poll()" will be
+ * made by "netpoll_poll_dev()".
+ *
+ * Often, this can cause some tiles to still have packets in their
+ * queues, so we must call "tile_net_discard_packets()" later.
+ *
+ * Note that some other tile may still be INSIDE "tile_net_poll()",
+ * and in fact, many will be, if there is heavy network load.
+ *
+ * Calling "on_each_cpu(tile_net_stop_disable, (void *)dev, 1)" when
+ * any tile is still "napi_schedule()"'d will induce a horrible crash
+ * when "msleep()" is called.  This includes tiles which are inside
+ * "tile_net_poll()" which have not yet called "napi_complete()".
+ *
+ * So, we must first try to wait long enough for other tiles to finish
+ * with any current "tile_net_poll()" call, and, hopefully, to clear
+ * the "scheduled" flag.  ISSUE: It is unclear what happens to tiles
+ * which have called "napi_schedule()" but which had not yet tried to
+ * call "tile_net_poll()", or which exhausted their budget inside
+ * "tile_net_poll()" just before this function was called.
+ */
+static int tile_net_stop(struct net_device *dev)
+{
+	struct tile_net_priv *priv = netdev_priv(dev);
+
+	PDEBUG("tile_net_stop()\n");
+
+	/* Start discarding packets. */
+	priv->active = false;
 
+	/* Make sure "active" is visible to all tiles. */
+	mb();
 
 	/*
-	 * XXX: ISSUE: It appears that, in practice anyway, by the
-	 * time we get here, there are no pending completions.
+	 * On each tile, make sure no NEW packets get delivered, and
+	 * disable the ingress interrupt.
+	 *
+	 * Note that the ingress interrupt can fire AFTER this,
+	 * presumably due to packets which were recently delivered,
+	 * but it will have no effect.
 	 */
-	while (pending) {
+	on_each_cpu(tile_net_deregister, (void *)dev, 1);
 
-		struct sk_buff *olds[32];
-		unsigned int wanted = 32;
-		unsigned int i, nolds = 0;
+	/* Optimistically drain LIPP buffers. */
+	(void)tile_net_drain_lipp_buffers(priv);
 
-		nolds = tile_net_lepp_grab_comps(dev, olds,
-						 wanted, &pending);
+	/* ISSUE: Only needed if not yet fully open. */
+	cancel_delayed_work_sync(&priv->retry_work);
 
-		/* ISSUE: We have never actually seen this debug spew. */
-		if (nolds != 0)
-			pr_info("During tile_net_stop(), grabbed %d comps.\n",
-			       nolds);
+	/* Can't transmit any more. */
+	netif_stop_queue(dev);
 
-		for (i = 0; i < nolds; i++)
-			kfree_skb(olds[i]);
-	}
+	/* Disable NAPI on each tile. */
+	on_each_cpu(tile_net_stop_disable, (void *)dev, 1);
+
+	/*
+	 * Drain any remaining LIPP buffers.  NOTE: This "printk()"
+	 * has never been observed, but in theory it could happen.
+	 */
+	if (tile_net_drain_lipp_buffers(priv) != 0)
+		printk("Had to drain some extra LIPP buffers!\n");
 
+	/* Stop LIPP/LEPP. */
+	tile_net_stop_aux(dev);
+
+	/*
+	 * ISSUE: It appears that, in practice anyway, by the time we
+	 * get here, there are no pending completions, but just in case,
+	 * we free (all of) them anyway.
+	 */
+	while (tile_net_lepp_free_comps(dev, true))
+		/* loop */;
 
 	/* Wipe the EPP queue. */
-	memset(priv->epp_queue, 0, sizeof(lepp_queue_t));
+	memset(priv->eq, 0, sizeof(lepp_queue_t));
 
 	/* Evict the EPP queue. */
-	finv_buffer(priv->epp_queue, PAGE_SIZE);
+	finv_buffer(priv->eq, EQ_SIZE);
 
 	return 0;
 }
@@ -1620,7 +1686,7 @@
 	if (b_len != 0) {
 
 		if (!hash_default)
-			finv_buffer_remote(b_data, b_len);
+			finv_buffer_remote(b_data, b_len, 0);
 
 		cpa = __pa(b_data);
 		frags[n].cpa_lo = cpa;
@@ -1643,7 +1709,7 @@
 		if (!hash_default) {
 			void *va = pfn_to_kaddr(pfn) + f->page_offset;
 			BUG_ON(PageHighMem(f->page));
-			finv_buffer_remote(va, f->size);
+			finv_buffer_remote(va, f->size, 0);
 		}
 
 		cpa = ((phys_addr_t)pfn << PAGE_SHIFT) + f->page_offset;
@@ -1742,17 +1808,15 @@
 
 	unsigned long irqflags;
 
-	lepp_queue_t *eq = priv->epp_queue;
+	lepp_queue_t *eq = priv->eq;
 
-	struct sk_buff *olds[4];
-	unsigned int wanted = 4;
+	struct sk_buff *olds[8];
+	unsigned int wanted = 8;
 	unsigned int i, nolds = 0;
 
 	unsigned int cmd_head, cmd_tail, cmd_next;
 	unsigned int comp_tail;
 
-	unsigned int free_slots;
-
 
 	/* Paranoia. */
 	BUG_ON(skb->protocol != htons(ETH_P_IP));
@@ -1780,34 +1844,32 @@
 
 	/* Enqueue the command. */
 
-	spin_lock_irqsave(&priv->cmd_lock, irqflags);
+	spin_lock_irqsave(&priv->eq_lock, irqflags);
 
 	/*
 	 * Handle completions if needed to make room.
 	 * HACK: Spin until there is sufficient room.
 	 */
-	free_slots = lepp_num_free_comp_slots(eq);
-	if (free_slots < 1) {
-spin:
-		nolds += tile_net_lepp_grab_comps(dev, olds + nolds,
-						  wanted - nolds, NULL);
-		if (lepp_num_free_comp_slots(eq) < 1)
-			goto spin;
+	if (lepp_num_free_comp_slots(eq) == 0) {
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+		if (nolds == 0) {
+busy:
+			spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+			return NETDEV_TX_BUSY;
+		}
 	}
 
 	cmd_head = eq->cmd_head;
 	cmd_tail = eq->cmd_tail;
 
-	/* NOTE: The "gotos" below are untested. */
-
 	/* Prepare to advance, detecting full queue. */
 	cmd_next = cmd_tail + cmd_size;
 	if (cmd_tail < cmd_head && cmd_next >= cmd_head)
-		goto spin;
+		goto busy;
 	if (cmd_next > LEPP_CMD_LIMIT) {
 		cmd_next = 0;
 		if (cmd_next == cmd_head)
-			goto spin;
+			goto busy;
 	}
 
 	/* Copy the command. */
@@ -1823,14 +1885,18 @@
 	eq->comp_tail = comp_tail;
 
 	/* Flush before allowing LEPP to handle the command. */
+	/* ISSUE: Is this the optimal location for the flush? */
 	__insn_mf();
 
 	eq->cmd_tail = cmd_tail;
 
-	spin_unlock_irqrestore(&priv->cmd_lock, irqflags);
-
+	/* NOTE: Using "4" here is more efficient than "0" or "2", */
+	/* and, strangely, more efficient than pre-checking the number */
+	/* of available completions, and comparing it to 4. */
 	if (nolds == 0)
-		nolds = tile_net_lepp_grab_comps(dev, olds, wanted, NULL);
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4);
+
+	spin_unlock_irqrestore(&priv->eq_lock, irqflags);
 
 	/* Handle completions. */
 	for (i = 0; i < nolds; i++)
@@ -1870,10 +1936,10 @@
 
 	unsigned int num_frags;
 
-	lepp_queue_t *eq = priv->epp_queue;
+	lepp_queue_t *eq = priv->eq;
 
-	struct sk_buff *olds[4];
-	unsigned int wanted = 4;
+	struct sk_buff *olds[8];
+	unsigned int wanted = 8;
 	unsigned int i, nolds = 0;
 
 	unsigned int cmd_size = sizeof(lepp_cmd_t);
@@ -1883,8 +1949,6 @@
 
 	lepp_cmd_t cmds[LEPP_MAX_FRAGS];
 
-	unsigned int free_slots;
-
 
 	/*
 	 * This is paranoia, since we think that if the link doesn't come
@@ -1905,7 +1969,8 @@
 	if (hash_default) {
 		HV_PTE pte = *virt_to_pte(current->mm, (unsigned long)data);
 		if (hv_pte_get_mode(pte) != HV_PTE_MODE_CACHE_HASH_L3)
-			panic("Non-coherent egress buffer!");
+			panic("Non-HFH egress buffer! VA=%p Mode=%d PTE=%llx",
+			      data, hv_pte_get_mode(pte), hv_pte_val(pte));
 	}
 #endif
 #endif
@@ -1958,37 +2023,35 @@
 
 	/* Enqueue the commands. */
 
-	spin_lock_irqsave(&priv->cmd_lock, irqflags);
+	spin_lock_irqsave(&priv->eq_lock, irqflags);
 
 	/*
 	 * Handle completions if needed to make room.
 	 * HACK: Spin until there is sufficient room.
 	 */
-	free_slots = lepp_num_free_comp_slots(eq);
-	if (free_slots < 1) {
-spin:
-		nolds += tile_net_lepp_grab_comps(dev, olds + nolds,
-						  wanted - nolds, NULL);
-		if (lepp_num_free_comp_slots(eq) < 1)
-			goto spin;
+	if (lepp_num_free_comp_slots(eq) == 0) {
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 0);
+		if (nolds == 0) {
+busy:
+			spin_unlock_irqrestore(&priv->eq_lock, irqflags);
+			return NETDEV_TX_BUSY;
+		}
 	}
 
 	cmd_head = eq->cmd_head;
 	cmd_tail = eq->cmd_tail;
 
-	/* NOTE: The "gotos" below are untested. */
-
 	/* Copy the commands, or fail. */
 	for (i = 0; i < num_frags; i++) {
 
 		/* Prepare to advance, detecting full queue. */
 		cmd_next = cmd_tail + cmd_size;
 		if (cmd_tail < cmd_head && cmd_next >= cmd_head)
-			goto spin;
+			goto busy;
 		if (cmd_next > LEPP_CMD_LIMIT) {
 			cmd_next = 0;
 			if (cmd_next == cmd_head)
-				goto spin;
+				goto busy;
 		}
 
 		/* Copy the command. */
@@ -2005,14 +2068,18 @@
 	eq->comp_tail = comp_tail;
 
 	/* Flush before allowing LEPP to handle the command. */
+	/* ISSUE: Is this the optimal location for the flush? */
 	__insn_mf();
 
 	eq->cmd_tail = cmd_tail;
 
-	spin_unlock_irqrestore(&priv->cmd_lock, irqflags);
-
+	/* NOTE: Using "4" here is more efficient than "0" or "2", */
+	/* and, strangely, more efficient than pre-checking the number */
+	/* of available completions, and comparing it to 4. */
 	if (nolds == 0)
-		nolds = tile_net_lepp_grab_comps(dev, olds, wanted, NULL);
+		nolds = tile_net_lepp_grab_comps(eq, olds, wanted, 4);
+
+	spin_unlock_irqrestore(&priv->eq_lock, irqflags);
 
 	/* Handle completions. */
 	for (i = 0; i < nolds; i++)
@@ -2261,7 +2328,6 @@
 	int ret;
 	struct net_device *dev;
 	struct tile_net_priv *priv;
-	struct page *page;
 
 	/*
 	 * Allocate the device structure.  This allocates "priv", calls
@@ -2285,23 +2351,21 @@
 
 	INIT_DELAYED_WORK(&priv->retry_work, tile_net_open_retry);
 
-	spin_lock_init(&priv->cmd_lock);
-	spin_lock_init(&priv->comp_lock);
+	spin_lock_init(&priv->eq_lock);
 
-	/* Allocate "epp_queue". */
-	BUG_ON(get_order(sizeof(lepp_queue_t)) != 0);
-	page = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
-	if (!page) {
+	/* Allocate "eq". */
+	priv->eq_pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, EQ_ORDER);
+	if (!priv->eq_pages) {
 		free_netdev(dev);
 		return NULL;
 	}
-	priv->epp_queue = page_address(page);
+	priv->eq = page_address(priv->eq_pages);
 
 	/* Register the network device. */
 	ret = register_netdev(dev);
 	if (ret) {
 		pr_err("register_netdev %s failed %d\n", dev->name, ret);
-		free_page((unsigned long)priv->epp_queue);
+		__free_pages(priv->eq_pages, EQ_ORDER);
 		free_netdev(dev);
 		return NULL;
 	}
@@ -2310,7 +2374,7 @@
 	ret = tile_net_get_mac(dev);
 	if (ret < 0) {
 		unregister_netdev(dev);
-		free_page((unsigned long)priv->epp_queue);
+		__free_pages(priv->eq_pages, EQ_ORDER);
 		free_netdev(dev);
 		return NULL;
 	}
@@ -2321,6 +2385,9 @@
 
 /*
  * Module cleanup.
+ *
+ * FIXME: If compiled as a module, this module cannot be "unloaded",
+ * because the "ingress interrupt handler" is registered permanently.
  */
 static void tile_net_cleanup(void)
 {
@@ -2331,8 +2398,8 @@
 			struct net_device *dev = tile_net_devs[i];
 			struct tile_net_priv *priv = netdev_priv(dev);
 			unregister_netdev(dev);
-			finv_buffer(priv->epp_queue, PAGE_SIZE);
-			free_page((unsigned long)priv->epp_queue);
+			finv_buffer(priv->eq, EQ_SIZE);
+			__free_pages(priv->eq_pages, EQ_ORDER);
 			free_netdev(dev);
 		}
 	}
@@ -2355,7 +2422,12 @@
 }
 
 
+module_init(tile_net_init_module);
+module_exit(tile_net_cleanup);
+
+
 #ifndef MODULE
+
 /*
  * The "network_cpus" boot argument specifies the cpus that are dedicated
  * to handle ingress packets.
@@ -2391,8 +2463,5 @@
 	return 0;
 }
 __setup("network_cpus=", network_cpus_setup);
-#endif
-
 
-module_init(tile_net_init_module);
-module_exit(tile_net_cleanup);
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/tlan.c linux-libre-2.6.39-gnu/drivers/net/tlan.c
--- linux-libre-2.6.38-gnu/drivers/net/tlan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tlan.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,150 +25,9 @@
  *		Microchip Technology, 24C01A/02A/04A Data Sheet
  *			available in PDF format from www.microchip.com
  *
- * Change History
- *
- *	Tigran Aivazian <tigran@sco.com>:	TLan_PciProbe() now uses
- *						new PCI BIOS interface.
- *	Alan Cox	<alan@lxorguk.ukuu.org.uk>:
- *						Fixed the out of memory
- *						handling.
- *
- *	Torben Mathiasen <torben.mathiasen@compaq.com> New Maintainer!
- *
- *	v1.1 Dec 20, 1999    - Removed linux version checking
- *			       Patch from Tigran Aivazian.
- *			     - v1.1 includes Alan's SMP updates.
- *			     - We still have problems on SMP though,
- *			       but I'm looking into that.
- *
- *	v1.2 Jan 02, 2000    - Hopefully fixed the SMP deadlock.
- *			     - Removed dependency of HZ being 100.
- *			     - We now allow higher priority timers to
- *			       overwrite timers like TLAN_TIMER_ACTIVITY
- *			       Patch from John Cagle <john.cagle@compaq.com>.
- *			     - Fixed a few compiler warnings.
- *
- *	v1.3 Feb 04, 2000    - Fixed the remaining HZ issues.
- *			     - Removed call to pci_present().
- *			     - Removed SA_INTERRUPT flag from irq handler.
- *			     - Added __init and __initdata to reduce resisdent
- *			       code size.
- *			     - Driver now uses module_init/module_exit.
- *			     - Rewrote init_module and tlan_probe to
- *			       share a lot more code. We now use tlan_probe
- *			       with builtin and module driver.
- *			     - Driver ported to new net API.
- *			     - tlan.txt has been reworked to reflect current
- *			       driver (almost)
- *			     - Other minor stuff
- *
- *	v1.4 Feb 10, 2000    - Updated with more changes required after Dave's
- *	                       network cleanup in 2.3.43pre7 (Tigran & myself)
- *	                     - Minor stuff.
- *
- *	v1.5 March 22, 2000  - Fixed another timer bug that would hang the driver
- *			       if no cable/link were present.
- *			     - Cosmetic changes.
- *			     - TODO: Port completely to new PCI/DMA API
- *			     	     Auto-Neg fallback.
- *
- * 	v1.6 April 04, 2000  - Fixed driver support for kernel-parameters. Haven't
- * 			       tested it though, as the kernel support is currently
- * 			       broken (2.3.99p4p3).
- * 			     - Updated tlan.txt accordingly.
- * 			     - Adjusted minimum/maximum frame length.
- * 			     - There is now a TLAN website up at
- * 			       http://hp.sourceforge.net/ 
- *
- * 	v1.7 April 07, 2000  - Started to implement custom ioctls. Driver now
- * 			       reports PHY information when used with Donald
- * 			       Beckers userspace MII diagnostics utility.
- *
- * 	v1.8 April 23, 2000  - Fixed support for forced speed/duplex settings.
- * 			     - Added link information to Auto-Neg and forced
- * 			       modes. When NIC operates with auto-neg the driver
- * 			       will report Link speed & duplex modes as well as
- * 			       link partner abilities. When forced link is used,
- * 			       the driver will report status of the established
- * 			       link.
- * 			       Please read tlan.txt for additional information.
- * 			     - Removed call to check_region(), and used
- * 			       return value of request_region() instead.
- *
- *	v1.8a May 28, 2000   - Minor updates.
- *
- *	v1.9 July 25, 2000   - Fixed a few remaining Full-Duplex issues.
- *	                     - Updated with timer fixes from Andrew Morton.
- *	                     - Fixed module race in TLan_Open.
- *	                     - Added routine to monitor PHY status.
- *	                     - Added activity led support for Proliant devices.
- *
- *	v1.10 Aug 30, 2000   - Added support for EISA based tlan controllers
- *			       like the Compaq NetFlex3/E.
- *			     - Rewrote tlan_probe to better handle multiple
- *			       bus probes. Probing and device setup is now
- *			       done through TLan_Probe and TLan_init_one. Actual
- *			       hardware probe is done with kernel API and
- *			       TLan_EisaProbe.
- *			     - Adjusted debug information for probing.
- *			     - Fixed bug that would cause general debug information
- *			       to be printed after driver removal.
- *			     - Added transmit timeout handling.
- *			     - Fixed OOM return values in tlan_probe.
- *			     - Fixed possible mem leak in tlan_exit
- *			       (now tlan_remove_one).
- *			     - Fixed timer bug in TLan_phyMonitor.
- *			     - This driver version is alpha quality, please
- *			       send me any bug issues you may encounter.
- *
- *	v1.11 Aug 31, 2000   - Do not try to register irq 0 if no irq line was
- *			       set for EISA cards.
- *			     - Added support for NetFlex3/E with nibble-rate
- *			       10Base-T PHY. This is untestet as I haven't got
- *			       one of these cards.
- *			     - Fixed timer being added twice.
- *			     - Disabled PhyMonitoring by default as this is
- *			       work in progress. Define MONITOR to enable it.
- *			     - Now we don't display link info with PHYs that
- *			       doesn't support it (level1).
- *			     - Incresed tx_timeout beacuse of auto-neg.
- *			     - Adjusted timers for forced speeds.
- *
- *	v1.12 Oct 12, 2000   - Minor fixes (memleak, init, etc.)
- *
- * 	v1.13 Nov 28, 2000   - Stop flooding console with auto-neg issues
- * 			       when link can't be established.
- *			     - Added the bbuf option as a kernel parameter.
- *			     - Fixed ioaddr probe bug.
- *			     - Fixed stupid deadlock with MII interrupts.
- *			     - Added support for speed/duplex selection with
- *			       multiple nics.
- *			     - Added partly fix for TX Channel lockup with
- *			       TLAN v1.0 silicon. This needs to be investigated
- *			       further.
- *
- * 	v1.14 Dec 16, 2000   - Added support for servicing multiple frames per.
- * 			       interrupt. Thanks goes to
- * 			       Adam Keys <adam@ti.com>
- * 			       Denis Beaudoin <dbeaudoin@ti.com>
- * 			       for providing the patch.
- * 			     - Fixed auto-neg output when using multiple
- * 			       adapters.
- * 			     - Converted to use new taskq interface.
- *
- * 	v1.14a Jan 6, 2001   - Minor adjustments (spinlocks, etc.)
- *
- *	Samuel Chessman <chessman@tux.org> New Maintainer!
- *
- *	v1.15 Apr 4, 2002    - Correct operation when aui=1 to be
- *	                       10T half duplex no loopback
- *	                       Thanks to Gunnar Eikman
- *
- *	Sakari Ailus <sakari.ailus@iki.fi>:
- *
- *	v1.15a Dec 15 2008   - Remove bbuf support, it doesn't work anyway.
- *
- *******************************************************************************/
+ ******************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/module.h>
 #include <linux/init.h>
@@ -185,13 +44,11 @@
 
 #include "tlan.h"
 
-typedef u32 (TLanIntVectorFunc)( struct net_device *, u16 );
-
 
 /* For removing EISA devices */
-static	struct net_device	*TLan_Eisa_Devices;
+static	struct net_device	*tlan_eisa_devices;
 
-static	int		TLanDevicesInstalled;
+static	int		tlan_devices_installed;
 
 /* Set speed, duplex and aui settings */
 static  int aui[MAX_TLAN_BOARDS];
@@ -202,8 +59,9 @@
 module_param_array(duplex, int, NULL, 0);
 module_param_array(speed, int, NULL, 0);
 MODULE_PARM_DESC(aui, "ThunderLAN use AUI port(s) (0-1)");
-MODULE_PARM_DESC(duplex, "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
-MODULE_PARM_DESC(speed, "ThunderLAN port speen setting(s) (0,10,100)");
+MODULE_PARM_DESC(duplex,
+		 "ThunderLAN duplex setting(s) (0-default, 1-half, 2-full)");
+MODULE_PARM_DESC(speed, "ThunderLAN port speed setting(s) (0,10,100)");
 
 MODULE_AUTHOR("Maintainer: Samuel Chessman <chessman@tux.org>");
 MODULE_DESCRIPTION("Driver for TI ThunderLAN based ethernet PCI adapters");
@@ -218,139 +76,144 @@
 module_param(debug, int, 0);
 MODULE_PARM_DESC(debug, "ThunderLAN debug mask");
 
-static	const char TLanSignature[] = "TLAN";
-static  const char tlan_banner[] = "ThunderLAN driver v1.15a\n";
+static	const char tlan_signature[] = "TLAN";
+static  const char tlan_banner[] = "ThunderLAN driver v1.17\n";
 static  int tlan_have_pci;
 static  int tlan_have_eisa;
 
-static const char *media[] = {
-	"10BaseT-HD ", "10BaseT-FD ","100baseTx-HD ",
-	"100baseTx-FD", "100baseT4", NULL
+static const char * const media[] = {
+	"10BaseT-HD", "10BaseT-FD", "100baseTx-HD",
+	"100BaseTx-FD", "100BaseT4", NULL
 };
 
 static struct board {
-	const char	*deviceLabel;
-	u32	   	flags;
-	u16	   	addrOfs;
+	const char	*device_label;
+	u32		flags;
+	u16		addr_ofs;
 } board_info[] = {
 	{ "Compaq Netelligent 10 T PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
-	{ "Compaq Netelligent 10/100 TX PCI UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
+	{ "Compaq Netelligent 10/100 TX PCI UTP",
+	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
 	{ "Compaq Integrated NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq NetFlex-3/P",
 	  TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
 	{ "Compaq NetFlex-3/P", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq Netelligent Integrated 10/100 TX UTP",
 	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
-	{ "Compaq Netelligent Dual 10/100 TX PCI UTP", TLAN_ADAPTER_NONE, 0x83 },
-	{ "Compaq Netelligent 10/100 TX Embedded UTP", TLAN_ADAPTER_NONE, 0x83 },
+	{ "Compaq Netelligent Dual 10/100 TX PCI UTP",
+	  TLAN_ADAPTER_NONE, 0x83 },
+	{ "Compaq Netelligent 10/100 TX Embedded UTP",
+	  TLAN_ADAPTER_NONE, 0x83 },
 	{ "Olicom OC-2183/2185", TLAN_ADAPTER_USE_INTERN_10, 0x83 },
-	{ "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xF8 },
-	{ "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xF8 },
+	{ "Olicom OC-2325", TLAN_ADAPTER_UNMANAGED_PHY, 0xf8 },
+	{ "Olicom OC-2326", TLAN_ADAPTER_USE_INTERN_10, 0xf8 },
 	{ "Compaq Netelligent 10/100 TX UTP", TLAN_ADAPTER_ACTIVITY_LED, 0x83 },
-	{ "Compaq Netelligent 10 T/2 PCI UTP/Coax", TLAN_ADAPTER_NONE, 0x83 },
+	{ "Compaq Netelligent 10 T/2 PCI UTP/coax", TLAN_ADAPTER_NONE, 0x83 },
 	{ "Compaq NetFlex-3/E",
-	  TLAN_ADAPTER_ACTIVITY_LED | 	/* EISA card */
+	  TLAN_ADAPTER_ACTIVITY_LED |	/* EISA card */
 	  TLAN_ADAPTER_UNMANAGED_PHY | TLAN_ADAPTER_BIT_RATE_PHY, 0x83 },
-	{ "Compaq NetFlex-3/E", TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
+	{ "Compaq NetFlex-3/E",
+	  TLAN_ADAPTER_ACTIVITY_LED, 0x83 }, /* EISA card */
 };
 
 static DEFINE_PCI_DEVICE_TABLE(tlan_pci_tbl) = {
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL10,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 1 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3I,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 2 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_THUNDER,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 3 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETFLEX3B,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 4 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100PI,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 5 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100D,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 6 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_COMPAQ_NETEL100I,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 7 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2183,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 8 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2325,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 9 },
 	{ PCI_VENDOR_ID_OLICOM, PCI_DEVICE_ID_OLICOM_OC2326,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 10 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_100_WS_5100,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 11 },
 	{ PCI_VENDOR_ID_COMPAQ, PCI_DEVICE_ID_NETELLIGENT_10_T2,
-		PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
+	  PCI_ANY_ID, PCI_ANY_ID, 0, 0, 12 },
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, tlan_pci_tbl);
 
-static void	TLan_EisaProbe( void );
-static void	TLan_Eisa_Cleanup( void );
-static int      TLan_Init( struct net_device * );
-static int	TLan_Open( struct net_device *dev );
-static netdev_tx_t TLan_StartTx( struct sk_buff *, struct net_device *);
-static irqreturn_t TLan_HandleInterrupt( int, void *);
-static int	TLan_Close( struct net_device *);
-static struct	net_device_stats *TLan_GetStats( struct net_device *);
-static void	TLan_SetMulticastList( struct net_device *);
-static int	TLan_ioctl( struct net_device *dev, struct ifreq *rq, int cmd);
-static int      TLan_probe1( struct pci_dev *pdev, long ioaddr,
-			     int irq, int rev, const struct pci_device_id *ent);
-static void	TLan_tx_timeout( struct net_device *dev);
-static void	TLan_tx_timeout_work(struct work_struct *work);
-static int 	tlan_init_one( struct pci_dev *pdev, const struct pci_device_id *ent);
+static void	tlan_eisa_probe(void);
+static void	tlan_eisa_cleanup(void);
+static int      tlan_init(struct net_device *);
+static int	tlan_open(struct net_device *dev);
+static netdev_tx_t tlan_start_tx(struct sk_buff *, struct net_device *);
+static irqreturn_t tlan_handle_interrupt(int, void *);
+static int	tlan_close(struct net_device *);
+static struct	net_device_stats *tlan_get_stats(struct net_device *);
+static void	tlan_set_multicast_list(struct net_device *);
+static int	tlan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
+static int      tlan_probe1(struct pci_dev *pdev, long ioaddr,
+			    int irq, int rev, const struct pci_device_id *ent);
+static void	tlan_tx_timeout(struct net_device *dev);
+static void	tlan_tx_timeout_work(struct work_struct *work);
+static int	tlan_init_one(struct pci_dev *pdev,
+			      const struct pci_device_id *ent);
 
-static u32	TLan_HandleTxEOF( struct net_device *, u16 );
-static u32	TLan_HandleStatOverflow( struct net_device *, u16 );
-static u32	TLan_HandleRxEOF( struct net_device *, u16 );
-static u32	TLan_HandleDummy( struct net_device *, u16 );
-static u32	TLan_HandleTxEOC( struct net_device *, u16 );
-static u32	TLan_HandleStatusCheck( struct net_device *, u16 );
-static u32	TLan_HandleRxEOC( struct net_device *, u16 );
+static u32	tlan_handle_tx_eof(struct net_device *, u16);
+static u32	tlan_handle_stat_overflow(struct net_device *, u16);
+static u32	tlan_handle_rx_eof(struct net_device *, u16);
+static u32	tlan_handle_dummy(struct net_device *, u16);
+static u32	tlan_handle_tx_eoc(struct net_device *, u16);
+static u32	tlan_handle_status_check(struct net_device *, u16);
+static u32	tlan_handle_rx_eoc(struct net_device *, u16);
 
-static void	TLan_Timer( unsigned long );
+static void	tlan_timer(unsigned long);
 
-static void	TLan_ResetLists( struct net_device * );
-static void	TLan_FreeLists( struct net_device * );
-static void	TLan_PrintDio( u16 );
-static void	TLan_PrintList( TLanList *, char *, int );
-static void	TLan_ReadAndClearStats( struct net_device *, int );
-static void	TLan_ResetAdapter( struct net_device * );
-static void	TLan_FinishReset( struct net_device * );
-static void	TLan_SetMac( struct net_device *, int areg, char *mac );
+static void	tlan_reset_lists(struct net_device *);
+static void	tlan_free_lists(struct net_device *);
+static void	tlan_print_dio(u16);
+static void	tlan_print_list(struct tlan_list *, char *, int);
+static void	tlan_read_and_clear_stats(struct net_device *, int);
+static void	tlan_reset_adapter(struct net_device *);
+static void	tlan_finish_reset(struct net_device *);
+static void	tlan_set_mac(struct net_device *, int areg, char *mac);
 
-static void	TLan_PhyPrint( struct net_device * );
-static void	TLan_PhyDetect( struct net_device * );
-static void	TLan_PhyPowerDown( struct net_device * );
-static void	TLan_PhyPowerUp( struct net_device * );
-static void	TLan_PhyReset( struct net_device * );
-static void	TLan_PhyStartLink( struct net_device * );
-static void	TLan_PhyFinishAutoNeg( struct net_device * );
+static void	tlan_phy_print(struct net_device *);
+static void	tlan_phy_detect(struct net_device *);
+static void	tlan_phy_power_down(struct net_device *);
+static void	tlan_phy_power_up(struct net_device *);
+static void	tlan_phy_reset(struct net_device *);
+static void	tlan_phy_start_link(struct net_device *);
+static void	tlan_phy_finish_auto_neg(struct net_device *);
 #ifdef MONITOR
-static void     TLan_PhyMonitor( struct net_device * );
+static void     tlan_phy_monitor(struct net_device *);
 #endif
 
 /*
-static int	TLan_PhyNop( struct net_device * );
-static int	TLan_PhyInternalCheck( struct net_device * );
-static int	TLan_PhyInternalService( struct net_device * );
-static int	TLan_PhyDp83840aCheck( struct net_device * );
+  static int	tlan_phy_nop(struct net_device *);
+  static int	tlan_phy_internal_check(struct net_device *);
+  static int	tlan_phy_internal_service(struct net_device *);
+  static int	tlan_phy_dp83840a_check(struct net_device *);
 */
 
-static bool	TLan_MiiReadReg( struct net_device *, u16, u16, u16 * );
-static void	TLan_MiiSendData( u16, u32, unsigned );
-static void	TLan_MiiSync( u16 );
-static void	TLan_MiiWriteReg( struct net_device *, u16, u16, u16 );
+static bool	tlan_mii_read_reg(struct net_device *, u16, u16, u16 *);
+static void	tlan_mii_send_data(u16, u32, unsigned);
+static void	tlan_mii_sync(u16);
+static void	tlan_mii_write_reg(struct net_device *, u16, u16, u16);
 
-static void	TLan_EeSendStart( u16 );
-static int	TLan_EeSendByte( u16, u8, int );
-static void	TLan_EeReceiveByte( u16, u8 *, int );
-static int	TLan_EeReadByte( struct net_device *, u8, u8 * );
+static void	tlan_ee_send_start(u16);
+static int	tlan_ee_send_byte(u16, u8, int);
+static void	tlan_ee_receive_byte(u16, u8 *, int);
+static int	tlan_ee_read_byte(struct net_device *, u8, u8 *);
 
 
 static inline void
-TLan_StoreSKB( struct tlan_list_tag *tag, struct sk_buff *skb)
+tlan_store_skb(struct tlan_list *tag, struct sk_buff *skb)
 {
 	unsigned long addr = (unsigned long)skb;
 	tag->buffer[9].address = addr;
@@ -358,7 +221,7 @@
 }
 
 static inline struct sk_buff *
-TLan_GetSKB( const struct tlan_list_tag *tag)
+tlan_get_skb(const struct tlan_list *tag)
 {
 	unsigned long addr;
 
@@ -367,50 +230,50 @@
 	return (struct sk_buff *) addr;
 }
 
-
-static TLanIntVectorFunc *TLanIntVector[TLAN_INT_NUMBER_OF_INTS] = {
+static u32
+(*tlan_int_vector[TLAN_INT_NUMBER_OF_INTS])(struct net_device *, u16) = {
 	NULL,
-	TLan_HandleTxEOF,
-	TLan_HandleStatOverflow,
-	TLan_HandleRxEOF,
-	TLan_HandleDummy,
-	TLan_HandleTxEOC,
-	TLan_HandleStatusCheck,
-	TLan_HandleRxEOC
+	tlan_handle_tx_eof,
+	tlan_handle_stat_overflow,
+	tlan_handle_rx_eof,
+	tlan_handle_dummy,
+	tlan_handle_tx_eoc,
+	tlan_handle_status_check,
+	tlan_handle_rx_eoc
 };
 
 static inline void
-TLan_SetTimer( struct net_device *dev, u32 ticks, u32 type )
+tlan_set_timer(struct net_device *dev, u32 ticks, u32 type)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	unsigned long flags = 0;
 
 	if (!in_irq())
 		spin_lock_irqsave(&priv->lock, flags);
-	if ( priv->timer.function != NULL &&
-		priv->timerType != TLAN_TIMER_ACTIVITY ) {
+	if (priv->timer.function != NULL &&
+	    priv->timer_type != TLAN_TIMER_ACTIVITY) {
 		if (!in_irq())
 			spin_unlock_irqrestore(&priv->lock, flags);
 		return;
 	}
-	priv->timer.function = TLan_Timer;
+	priv->timer.function = tlan_timer;
 	if (!in_irq())
 		spin_unlock_irqrestore(&priv->lock, flags);
 
 	priv->timer.data = (unsigned long) dev;
-	priv->timerSetAt = jiffies;
-	priv->timerType = type;
+	priv->timer_set_at = jiffies;
+	priv->timer_type = type;
 	mod_timer(&priv->timer, jiffies + ticks);
 
-} /* TLan_SetTimer */
+}
 
 
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Primary Functions
+ThunderLAN driver primary functions
 
-	These functions are more or less common to all Linux network drivers.
+these functions are more or less common to all linux network drivers.
 
 ******************************************************************************
 *****************************************************************************/
@@ -419,56 +282,124 @@
 
 
 
-	/***************************************************************
-	 *	tlan_remove_one
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		None
-	 *
-	 *	Goes through the TLanDevices list and frees the device
-	 *	structs and memory associated with each device (lists
-	 *	and buffers).  It also ureserves the IO port regions
-	 *	associated with this device.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_remove_one
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		None
+ *
+ *	Goes through the TLanDevices list and frees the device
+ *	structs and memory associated with each device (lists
+ *	and buffers).  It also ureserves the IO port regions
+ *	associated with this device.
+ *
+ **************************************************************/
 
 
-static void __devexit tlan_remove_one( struct pci_dev *pdev)
+static void __devexit tlan_remove_one(struct pci_dev *pdev)
 {
-	struct net_device *dev = pci_get_drvdata( pdev );
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct net_device *dev = pci_get_drvdata(pdev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 
-	unregister_netdev( dev );
+	unregister_netdev(dev);
 
-	if ( priv->dmaStorage ) {
-		pci_free_consistent(priv->pciDev,
-				    priv->dmaSize, priv->dmaStorage,
-				    priv->dmaStorageDMA );
+	if (priv->dma_storage) {
+		pci_free_consistent(priv->pci_dev,
+				    priv->dma_size, priv->dma_storage,
+				    priv->dma_storage_dma);
 	}
 
 #ifdef CONFIG_PCI
 	pci_release_regions(pdev);
 #endif
 
-	free_netdev( dev );
+	free_netdev(dev);
 
-	pci_set_drvdata( pdev, NULL );
+	pci_set_drvdata(pdev, NULL);
+}
+
+static void tlan_start(struct net_device *dev)
+{
+	tlan_reset_lists(dev);
+	/* NOTE: It might not be necessary to read the stats before a
+	   reset if you don't care what the values are.
+	*/
+	tlan_read_and_clear_stats(dev, TLAN_IGNORE);
+	tlan_reset_adapter(dev);
+	netif_wake_queue(dev);
+}
+
+static void tlan_stop(struct net_device *dev)
+{
+	struct tlan_priv *priv = netdev_priv(dev);
+
+	tlan_read_and_clear_stats(dev, TLAN_RECORD);
+	outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
+	/* Reset and power down phy */
+	tlan_reset_adapter(dev);
+	if (priv->timer.function != NULL) {
+		del_timer_sync(&priv->timer);
+		priv->timer.function = NULL;
+	}
+}
+
+#ifdef CONFIG_PM
+
+static int tlan_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	if (netif_running(dev))
+		tlan_stop(dev);
+
+	netif_device_detach(dev);
+	pci_save_state(pdev);
+	pci_disable_device(pdev);
+	pci_wake_from_d3(pdev, false);
+	pci_set_power_state(pdev, PCI_D3hot);
+
+	return 0;
 }
 
+static int tlan_resume(struct pci_dev *pdev)
+{
+	struct net_device *dev = pci_get_drvdata(pdev);
+
+	pci_set_power_state(pdev, PCI_D0);
+	pci_restore_state(pdev);
+	pci_enable_wake(pdev, 0, 0);
+	netif_device_attach(dev);
+
+	if (netif_running(dev))
+		tlan_start(dev);
+
+	return 0;
+}
+
+#else /* CONFIG_PM */
+
+#define tlan_suspend   NULL
+#define tlan_resume    NULL
+
+#endif /* CONFIG_PM */
+
+
 static struct pci_driver tlan_driver = {
 	.name		= "tlan",
 	.id_table	= tlan_pci_tbl,
 	.probe		= tlan_init_one,
 	.remove		= __devexit_p(tlan_remove_one),
+	.suspend	= tlan_suspend,
+	.resume		= tlan_resume,
 };
 
 static int __init tlan_probe(void)
 {
 	int rc = -ENODEV;
 
-	printk(KERN_INFO "%s", tlan_banner);
+	pr_info("%s", tlan_banner);
 
 	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting PCI Probe....\n");
 
@@ -477,18 +408,18 @@
 	rc = pci_register_driver(&tlan_driver);
 
 	if (rc != 0) {
-		printk(KERN_ERR "TLAN: Could not register pci driver.\n");
+		pr_err("Could not register pci driver\n");
 		goto err_out_pci_free;
 	}
 
 	TLAN_DBG(TLAN_DEBUG_PROBE, "Starting EISA Probe....\n");
-	TLan_EisaProbe();
+	tlan_eisa_probe();
 
-	printk(KERN_INFO "TLAN: %d device%s installed, PCI: %d  EISA: %d\n",
-		 TLanDevicesInstalled, TLanDevicesInstalled == 1 ? "" : "s",
-		 tlan_have_pci, tlan_have_eisa);
+	pr_info("%d device%s installed, PCI: %d  EISA: %d\n",
+		tlan_devices_installed, tlan_devices_installed == 1 ? "" : "s",
+		tlan_have_pci, tlan_have_eisa);
 
-	if (TLanDevicesInstalled == 0) {
+	if (tlan_devices_installed == 0) {
 		rc = -ENODEV;
 		goto  err_out_pci_unreg;
 	}
@@ -501,39 +432,39 @@
 }
 
 
-static int __devinit tlan_init_one( struct pci_dev *pdev,
-				    const struct pci_device_id *ent)
+static int __devinit tlan_init_one(struct pci_dev *pdev,
+				   const struct pci_device_id *ent)
 {
-	return TLan_probe1( pdev, -1, -1, 0, ent);
+	return tlan_probe1(pdev, -1, -1, 0, ent);
 }
 
 
 /*
-	***************************************************************
-	 *	tlan_probe1
-	 *
-	 *	Returns:
-	 *		0 on success, error code on error
-	 *	Parms:
-	 *		none
-	 *
-	 *	The name is lower case to fit in with all the rest of
-	 *	the netcard_probe names.  This function looks for
-	 *	another TLan based adapter, setting it up with the
-	 *	allocated device struct if one is found.
-	 *	tlan_probe has been ported to the new net API and
-	 *	now allocates its own device structure. This function
-	 *	is also used by modules.
-	 *
-	 **************************************************************/
+***************************************************************
+*	tlan_probe1
+*
+*	Returns:
+*		0 on success, error code on error
+*	Parms:
+*		none
+*
+*	The name is lower case to fit in with all the rest of
+*	the netcard_probe names.  This function looks for
+*	another TLan based adapter, setting it up with the
+*	allocated device struct if one is found.
+*	tlan_probe has been ported to the new net API and
+*	now allocates its own device structure. This function
+*	is also used by modules.
+*
+**************************************************************/
 
-static int __devinit TLan_probe1(struct pci_dev *pdev,
+static int __devinit tlan_probe1(struct pci_dev *pdev,
 				 long ioaddr, int irq, int rev,
-				 const struct pci_device_id *ent )
+				 const struct pci_device_id *ent)
 {
 
 	struct net_device  *dev;
-	TLanPrivateInfo    *priv;
+	struct tlan_priv  *priv;
 	u16		   device_id;
 	int		   reg, rc = -ENODEV;
 
@@ -543,17 +474,17 @@
 		if (rc)
 			return rc;
 
-		rc = pci_request_regions(pdev, TLanSignature);
+		rc = pci_request_regions(pdev, tlan_signature);
 		if (rc) {
-			printk(KERN_ERR "TLAN: Could not reserve IO regions\n");
+			pr_err("Could not reserve IO regions\n");
 			goto err_out;
 		}
 	}
 #endif  /*  CONFIG_PCI  */
 
-	dev = alloc_etherdev(sizeof(TLanPrivateInfo));
+	dev = alloc_etherdev(sizeof(struct tlan_priv));
 	if (dev == NULL) {
-		printk(KERN_ERR "TLAN: Could not allocate memory for device.\n");
+		pr_err("Could not allocate memory for device\n");
 		rc = -ENOMEM;
 		goto err_out_regions;
 	}
@@ -561,38 +492,39 @@
 
 	priv = netdev_priv(dev);
 
-	priv->pciDev = pdev;
+	priv->pci_dev = pdev;
 	priv->dev = dev;
 
 	/* Is this a PCI device? */
 	if (pdev) {
-		u32 		   pci_io_base = 0;
+		u32		   pci_io_base = 0;
 
 		priv->adapter = &board_info[ent->driver_data];
 
 		rc = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
 		if (rc) {
-			printk(KERN_ERR "TLAN: No suitable PCI mapping available.\n");
+			pr_err("No suitable PCI mapping available\n");
 			goto err_out_free_dev;
 		}
 
-		for ( reg= 0; reg <= 5; reg ++ ) {
+		for (reg = 0; reg <= 5; reg++) {
 			if (pci_resource_flags(pdev, reg) & IORESOURCE_IO) {
 				pci_io_base = pci_resource_start(pdev, reg);
-				TLAN_DBG( TLAN_DEBUG_GNRL, "IO mapping is available at %x.\n",
-						pci_io_base);
+				TLAN_DBG(TLAN_DEBUG_GNRL,
+					 "IO mapping is available at %x.\n",
+					 pci_io_base);
 				break;
 			}
 		}
 		if (!pci_io_base) {
-			printk(KERN_ERR "TLAN: No IO mappings available\n");
+			pr_err("No IO mappings available\n");
 			rc = -EIO;
 			goto err_out_free_dev;
 		}
 
 		dev->base_addr = pci_io_base;
 		dev->irq = pdev->irq;
-		priv->adapterRev = pdev->revision;
+		priv->adapter_rev = pdev->revision;
 		pci_set_master(pdev);
 		pci_set_drvdata(pdev, dev);
 
@@ -602,11 +534,11 @@
 		device_id = inw(ioaddr + EISA_ID2);
 		priv->is_eisa = 1;
 		if (device_id == 0x20F1) {
-			priv->adapter = &board_info[13]; 	/* NetFlex-3/E */
-			priv->adapterRev = 23;			/* TLAN 2.3 */
+			priv->adapter = &board_info[13]; /* NetFlex-3/E */
+			priv->adapter_rev = 23;		/* TLAN 2.3 */
 		} else {
 			priv->adapter = &board_info[14];
-			priv->adapterRev = 10;			/* TLAN 1.0 */
+			priv->adapter_rev = 10;		/* TLAN 1.0 */
 		}
 		dev->base_addr = ioaddr;
 		dev->irq = irq;
@@ -620,11 +552,11 @@
 		priv->speed  = ((dev->mem_start & 0x18) == 0x18) ? 0
 			: (dev->mem_start & 0x18) >> 3;
 
-		if (priv->speed == 0x1) {
+		if (priv->speed == 0x1)
 			priv->speed = TLAN_SPEED_10;
-		} else if (priv->speed == 0x2) {
+		else if (priv->speed == 0x2)
 			priv->speed = TLAN_SPEED_100;
-		}
+
 		debug = priv->debug = dev->mem_end;
 	} else {
 		priv->aui    = aui[boards_found];
@@ -635,46 +567,45 @@
 
 	/* This will be used when we get an adapter error from
 	 * within our irq handler */
-	INIT_WORK(&priv->tlan_tqueue, TLan_tx_timeout_work);
+	INIT_WORK(&priv->tlan_tqueue, tlan_tx_timeout_work);
 
 	spin_lock_init(&priv->lock);
 
-	rc = TLan_Init(dev);
+	rc = tlan_init(dev);
 	if (rc) {
-		printk(KERN_ERR "TLAN: Could not set up device.\n");
+		pr_err("Could not set up device\n");
 		goto err_out_free_dev;
 	}
 
 	rc = register_netdev(dev);
 	if (rc) {
-		printk(KERN_ERR "TLAN: Could not register device.\n");
+		pr_err("Could not register device\n");
 		goto err_out_uninit;
 	}
 
 
-	TLanDevicesInstalled++;
+	tlan_devices_installed++;
 	boards_found++;
 
 	/* pdev is NULL if this is an EISA device */
 	if (pdev)
 		tlan_have_pci++;
 	else {
-		priv->nextDevice = TLan_Eisa_Devices;
-		TLan_Eisa_Devices = dev;
+		priv->next_device = tlan_eisa_devices;
+		tlan_eisa_devices = dev;
 		tlan_have_eisa++;
 	}
 
-	printk(KERN_INFO "TLAN: %s irq=%2d, io=%04x, %s, Rev. %d\n",
-			dev->name,
-			(int) dev->irq,
-			(int) dev->base_addr,
-			priv->adapter->deviceLabel,
-			priv->adapterRev);
+	netdev_info(dev, "irq=%2d, io=%04x, %s, Rev. %d\n",
+		    (int)dev->irq,
+		    (int)dev->base_addr,
+		    priv->adapter->device_label,
+		    priv->adapter_rev);
 	return 0;
 
 err_out_uninit:
-	pci_free_consistent(priv->pciDev, priv->dmaSize, priv->dmaStorage,
-			    priv->dmaStorageDMA );
+	pci_free_consistent(priv->pci_dev, priv->dma_size, priv->dma_storage,
+			    priv->dma_storage_dma);
 err_out_free_dev:
 	free_netdev(dev);
 err_out_regions:
@@ -689,22 +620,23 @@
 }
 
 
-static void TLan_Eisa_Cleanup(void)
+static void tlan_eisa_cleanup(void)
 {
 	struct net_device *dev;
-	TLanPrivateInfo *priv;
+	struct tlan_priv *priv;
 
-	while( tlan_have_eisa ) {
-		dev = TLan_Eisa_Devices;
+	while (tlan_have_eisa) {
+		dev = tlan_eisa_devices;
 		priv = netdev_priv(dev);
-		if (priv->dmaStorage) {
-			pci_free_consistent(priv->pciDev, priv->dmaSize,
-					    priv->dmaStorage, priv->dmaStorageDMA );
+		if (priv->dma_storage) {
+			pci_free_consistent(priv->pci_dev, priv->dma_size,
+					    priv->dma_storage,
+					    priv->dma_storage_dma);
 		}
-		release_region( dev->base_addr, 0x10);
-		unregister_netdev( dev );
-		TLan_Eisa_Devices = priv->nextDevice;
-		free_netdev( dev );
+		release_region(dev->base_addr, 0x10);
+		unregister_netdev(dev);
+		tlan_eisa_devices = priv->next_device;
+		free_netdev(dev);
 		tlan_have_eisa--;
 	}
 }
@@ -715,7 +647,7 @@
 	pci_unregister_driver(&tlan_driver);
 
 	if (tlan_have_eisa)
-		TLan_Eisa_Cleanup();
+		tlan_eisa_cleanup();
 
 }
 
@@ -726,24 +658,24 @@
 
 
 
-	/**************************************************************
-	 * 	TLan_EisaProbe
-	 *
-	 *  	Returns: 0 on success, 1 otherwise
-	 *
-	 *  	Parms:	 None
-	 *
-	 *
-	 *  	This functions probes for EISA devices and calls
-	 *  	TLan_probe1 when one is found.
-	 *
-	 *************************************************************/
+/**************************************************************
+ *	tlan_eisa_probe
+ *
+ *	Returns: 0 on success, 1 otherwise
+ *
+ *	Parms:	 None
+ *
+ *
+ *	This functions probes for EISA devices and calls
+ *	TLan_probe1 when one is found.
+ *
+ *************************************************************/
 
-static void  __init TLan_EisaProbe (void)
+static void  __init tlan_eisa_probe(void)
 {
-	long 	ioaddr;
-	int 	rc = -ENODEV;
-	int 	irq;
+	long	ioaddr;
+	int	rc = -ENODEV;
+	int	irq;
 	u16	device_id;
 
 	if (!EISA_bus) {
@@ -754,15 +686,16 @@
 	/* Loop through all slots of the EISA bus */
 	for (ioaddr = 0x1000; ioaddr < 0x9000; ioaddr += 0x1000) {
 
-	TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
-		 (int) ioaddr + 0xC80, inw(ioaddr + EISA_ID));
-	TLAN_DBG(TLAN_DEBUG_PROBE,"EISA_ID 0x%4x: 0x%4x\n",
-		 (int) ioaddr + 0xC82, inw(ioaddr + EISA_ID2));
+		TLAN_DBG(TLAN_DEBUG_PROBE, "EISA_ID 0x%4x: 0x%4x\n",
+			 (int) ioaddr + 0xc80, inw(ioaddr + EISA_ID));
+		TLAN_DBG(TLAN_DEBUG_PROBE, "EISA_ID 0x%4x: 0x%4x\n",
+			 (int) ioaddr + 0xc82, inw(ioaddr + EISA_ID2));
 
 
-		TLAN_DBG(TLAN_DEBUG_PROBE, "Probing for EISA adapter at IO: 0x%4x : ",
-				   	(int) ioaddr);
-		if (request_region(ioaddr, 0x10, TLanSignature) == NULL)
+		TLAN_DBG(TLAN_DEBUG_PROBE,
+			 "Probing for EISA adapter at IO: 0x%4x : ",
+			 (int) ioaddr);
+		if (request_region(ioaddr, 0x10, tlan_signature) == NULL)
 			goto out;
 
 		if (inw(ioaddr + EISA_ID) != 0x110E) {
@@ -772,326 +705,324 @@
 
 		device_id = inw(ioaddr + EISA_ID2);
 		if (device_id !=  0x20F1 && device_id != 0x40F1) {
-			release_region (ioaddr, 0x10);
+			release_region(ioaddr, 0x10);
 			goto out;
 		}
 
-	 	if (inb(ioaddr + EISA_CR) != 0x1) { 	/* Check if adapter is enabled */
-			release_region (ioaddr, 0x10);
+		/* check if adapter is enabled */
+		if (inb(ioaddr + EISA_CR) != 0x1) {
+			release_region(ioaddr, 0x10);
 			goto out2;
 		}
 
 		if (debug == 0x10)
-			printk("Found one\n");
+			pr_info("Found one\n");
 
 
 		/* Get irq from board */
-		switch (inb(ioaddr + 0xCC0)) {
-			case(0x10):
-				irq=5;
-				break;
-			case(0x20):
-				irq=9;
-				break;
-			case(0x40):
-				irq=10;
-				break;
-			case(0x80):
-				irq=11;
-				break;
-			default:
-				goto out;
+		switch (inb(ioaddr + 0xcc0)) {
+		case(0x10):
+			irq = 5;
+			break;
+		case(0x20):
+			irq = 9;
+			break;
+		case(0x40):
+			irq = 10;
+			break;
+		case(0x80):
+			irq = 11;
+			break;
+		default:
+			goto out;
 		}
 
 
 		/* Setup the newly found eisa adapter */
-		rc = TLan_probe1( NULL, ioaddr, irq,
-					12, NULL);
+		rc = tlan_probe1(NULL, ioaddr, irq,
+				 12, NULL);
 		continue;
 
-		out:
-			if (debug == 0x10)
-				printk("None found\n");
-			continue;
+out:
+		if (debug == 0x10)
+			pr_info("None found\n");
+		continue;
 
-		out2:	if (debug == 0x10)
-				printk("Card found but it is not enabled, skipping\n");
-			continue;
+out2:
+		if (debug == 0x10)
+			pr_info("Card found but it is not enabled, skipping\n");
+		continue;
 
 	}
 
-} /* TLan_EisaProbe */
+}
 
 #ifdef CONFIG_NET_POLL_CONTROLLER
-static void TLan_Poll(struct net_device *dev)
+static void tlan_poll(struct net_device *dev)
 {
 	disable_irq(dev->irq);
-	TLan_HandleInterrupt(dev->irq, dev);
+	tlan_handle_interrupt(dev->irq, dev);
 	enable_irq(dev->irq);
 }
 #endif
 
-static const struct net_device_ops TLan_netdev_ops = {
-	.ndo_open 		= TLan_Open,
-	.ndo_stop		= TLan_Close,
-	.ndo_start_xmit		= TLan_StartTx,
-	.ndo_tx_timeout		= TLan_tx_timeout,
-	.ndo_get_stats		= TLan_GetStats,
-	.ndo_set_multicast_list = TLan_SetMulticastList,
-	.ndo_do_ioctl		= TLan_ioctl,
+static const struct net_device_ops tlan_netdev_ops = {
+	.ndo_open		= tlan_open,
+	.ndo_stop		= tlan_close,
+	.ndo_start_xmit		= tlan_start_tx,
+	.ndo_tx_timeout		= tlan_tx_timeout,
+	.ndo_get_stats		= tlan_get_stats,
+	.ndo_set_multicast_list = tlan_set_multicast_list,
+	.ndo_do_ioctl		= tlan_ioctl,
 	.ndo_change_mtu		= eth_change_mtu,
-	.ndo_set_mac_address 	= eth_mac_addr,
+	.ndo_set_mac_address	= eth_mac_addr,
 	.ndo_validate_addr	= eth_validate_addr,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	 = TLan_Poll,
+	.ndo_poll_controller	 = tlan_poll,
 #endif
 };
 
 
 
-	/***************************************************************
-	 *	TLan_Init
-	 *
-	 *	Returns:
-	 *		0 on success, error code otherwise.
-	 *	Parms:
-	 *		dev	The structure of the device to be
-	 *			init'ed.
-	 *
-	 *	This function completes the initialization of the
-	 *	device structure and driver.  It reserves the IO
-	 *	addresses, allocates memory for the lists and bounce
-	 *	buffers, retrieves the MAC address from the eeprom
-	 *	and assignes the device's methods.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_init
+ *
+ *	Returns:
+ *		0 on success, error code otherwise.
+ *	Parms:
+ *		dev	The structure of the device to be
+ *			init'ed.
+ *
+ *	This function completes the initialization of the
+ *	device structure and driver.  It reserves the IO
+ *	addresses, allocates memory for the lists and bounce
+ *	buffers, retrieves the MAC address from the eeprom
+ *	and assignes the device's methods.
+ *
+ **************************************************************/
 
-static int TLan_Init( struct net_device *dev )
+static int tlan_init(struct net_device *dev)
 {
 	int		dma_size;
-	int 		err;
+	int		err;
 	int		i;
-	TLanPrivateInfo	*priv;
+	struct tlan_priv	*priv;
 
 	priv = netdev_priv(dev);
 
-	dma_size = ( TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS )
-		* ( sizeof(TLanList) );
-	priv->dmaStorage = pci_alloc_consistent(priv->pciDev,
-						dma_size, &priv->dmaStorageDMA);
-	priv->dmaSize = dma_size;
+	dma_size = (TLAN_NUM_RX_LISTS + TLAN_NUM_TX_LISTS)
+		* (sizeof(struct tlan_list));
+	priv->dma_storage = pci_alloc_consistent(priv->pci_dev,
+						 dma_size,
+						 &priv->dma_storage_dma);
+	priv->dma_size = dma_size;
 
-	if ( priv->dmaStorage == NULL ) {
-		printk(KERN_ERR "TLAN:  Could not allocate lists and buffers for %s.\n",
-			dev->name );
+	if (priv->dma_storage == NULL) {
+		pr_err("Could not allocate lists and buffers for %s\n",
+		       dev->name);
 		return -ENOMEM;
 	}
-	memset( priv->dmaStorage, 0, dma_size );
-	priv->rxList = (TLanList *) ALIGN((unsigned long)priv->dmaStorage, 8);
-	priv->rxListDMA = ALIGN(priv->dmaStorageDMA, 8);
-	priv->txList = priv->rxList + TLAN_NUM_RX_LISTS;
-	priv->txListDMA = priv->rxListDMA + sizeof(TLanList) * TLAN_NUM_RX_LISTS;
+	memset(priv->dma_storage, 0, dma_size);
+	priv->rx_list = (struct tlan_list *)
+		ALIGN((unsigned long)priv->dma_storage, 8);
+	priv->rx_list_dma = ALIGN(priv->dma_storage_dma, 8);
+	priv->tx_list = priv->rx_list + TLAN_NUM_RX_LISTS;
+	priv->tx_list_dma =
+		priv->rx_list_dma + sizeof(struct tlan_list)*TLAN_NUM_RX_LISTS;
 
 	err = 0;
-	for ( i = 0;  i < 6 ; i++ )
-		err |= TLan_EeReadByte( dev,
-					(u8) priv->adapter->addrOfs + i,
-					(u8 *) &dev->dev_addr[i] );
-	if ( err ) {
-		printk(KERN_ERR "TLAN: %s: Error reading MAC from eeprom: %d\n",
-			dev->name,
-			err );
+	for (i = 0;  i < 6 ; i++)
+		err |= tlan_ee_read_byte(dev,
+					 (u8) priv->adapter->addr_ofs + i,
+					 (u8 *) &dev->dev_addr[i]);
+	if (err) {
+		pr_err("%s: Error reading MAC from eeprom: %d\n",
+		       dev->name, err);
 	}
 	dev->addr_len = 6;
 
 	netif_carrier_off(dev);
 
 	/* Device methods */
-	dev->netdev_ops = &TLan_netdev_ops;
+	dev->netdev_ops = &tlan_netdev_ops;
 	dev->watchdog_timeo = TX_TIMEOUT;
 
 	return 0;
 
-} /* TLan_Init */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_Open
-	 *
-	 *	Returns:
-	 *		0 on success, error code otherwise.
-	 *	Parms:
-	 *		dev	Structure of device to be opened.
-	 *
-	 *	This routine puts the driver and TLAN adapter in a
-	 *	state where it is ready to send and receive packets.
-	 *	It allocates the IRQ, resets and brings the adapter
-	 *	out of reset, and allows interrupts.  It also delays
-	 *	the startup for autonegotiation or sends a Rx GO
-	 *	command to the adapter, as appropriate.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_open
+ *
+ *	Returns:
+ *		0 on success, error code otherwise.
+ *	Parms:
+ *		dev	Structure of device to be opened.
+ *
+ *	This routine puts the driver and TLAN adapter in a
+ *	state where it is ready to send and receive packets.
+ *	It allocates the IRQ, resets and brings the adapter
+ *	out of reset, and allows interrupts.  It also delays
+ *	the startup for autonegotiation or sends a Rx GO
+ *	command to the adapter, as appropriate.
+ *
+ **************************************************************/
 
-static int TLan_Open( struct net_device *dev )
+static int tlan_open(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int		err;
 
-	priv->tlanRev = TLan_DioRead8( dev->base_addr, TLAN_DEF_REVISION );
-	err = request_irq( dev->irq, TLan_HandleInterrupt, IRQF_SHARED,
-			   dev->name, dev );
+	priv->tlan_rev = tlan_dio_read8(dev->base_addr, TLAN_DEF_REVISION);
+	err = request_irq(dev->irq, tlan_handle_interrupt, IRQF_SHARED,
+			  dev->name, dev);
 
-	if ( err ) {
-		pr_err("TLAN:  Cannot open %s because IRQ %d is already in use.\n",
-		       dev->name, dev->irq );
+	if (err) {
+		netdev_err(dev, "Cannot open because IRQ %d is already in use\n",
+			   dev->irq);
 		return err;
 	}
 
 	init_timer(&priv->timer);
-	netif_start_queue(dev);
 
-	/* NOTE: It might not be necessary to read the stats before a
-			 reset if you don't care what the values are.
-	*/
-	TLan_ResetLists( dev );
-	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
-	TLan_ResetAdapter( dev );
+	tlan_start(dev);
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Opened.  TLAN Chip Rev: %x\n",
-		  dev->name, priv->tlanRev );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Opened.  TLAN Chip Rev: %x\n",
+		 dev->name, priv->tlan_rev);
 
 	return 0;
 
-} /* TLan_Open */
+}
 
 
 
-	/**************************************************************
-	 *	TLan_ioctl
-	 *
-	 *	Returns:
-	 *		0 on success, error code otherwise
-	 *	Params:
-	 *		dev	structure of device to receive ioctl.
-	 *
-	 *		rq	ifreq structure to hold userspace data.
-	 *
-	 *		cmd	ioctl command.
-	 *
-	 *
-	 *************************************************************/
+/**************************************************************
+ *	tlan_ioctl
+ *
+ *	Returns:
+ *		0 on success, error code otherwise
+ *	Params:
+ *		dev	structure of device to receive ioctl.
+ *
+ *		rq	ifreq structure to hold userspace data.
+ *
+ *		cmd	ioctl command.
+ *
+ *
+ *************************************************************/
 
-static int TLan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
+static int tlan_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	struct mii_ioctl_data *data = if_mii(rq);
-	u32 phy   = priv->phy[priv->phyNum];
+	u32 phy   = priv->phy[priv->phy_num];
 
-	if (!priv->phyOnline)
+	if (!priv->phy_online)
 		return -EAGAIN;
 
-	switch(cmd) {
-	case SIOCGMIIPHY:		/* Get address of MII PHY in use. */
-			data->phy_id = phy;
+	switch (cmd) {
+	case SIOCGMIIPHY:		/* get address of MII PHY in use. */
+		data->phy_id = phy;
 
 
-	case SIOCGMIIREG:		/* Read MII PHY register. */
-			TLan_MiiReadReg(dev, data->phy_id & 0x1f,
-					data->reg_num & 0x1f, &data->val_out);
-			return 0;
+	case SIOCGMIIREG:		/* read MII PHY register. */
+		tlan_mii_read_reg(dev, data->phy_id & 0x1f,
+				  data->reg_num & 0x1f, &data->val_out);
+		return 0;
 
 
-	case SIOCSMIIREG:		/* Write MII PHY register. */
-			TLan_MiiWriteReg(dev, data->phy_id & 0x1f,
-					 data->reg_num & 0x1f, data->val_in);
-			return 0;
-		default:
-			return -EOPNOTSUPP;
+	case SIOCSMIIREG:		/* write MII PHY register. */
+		tlan_mii_write_reg(dev, data->phy_id & 0x1f,
+				   data->reg_num & 0x1f, data->val_in);
+		return 0;
+	default:
+		return -EOPNOTSUPP;
 	}
-} /* tlan_ioctl */
+}
 
 
-	/***************************************************************
-	 * 	TLan_tx_timeout
-	 *
-	 * 	Returns: nothing
-	 *
-	 * 	Params:
-	 * 		dev	structure of device which timed out
-	 * 			during transmit.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_tx_timeout
+ *
+ *	Returns: nothing
+ *
+ *	Params:
+ *		dev	structure of device which timed out
+ *			during transmit.
+ *
+ **************************************************************/
 
-static void TLan_tx_timeout(struct net_device *dev)
+static void tlan_tx_timeout(struct net_device *dev)
 {
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Transmit timed out.\n", dev->name);
 
 	/* Ok so we timed out, lets see what we can do about it...*/
-	TLan_FreeLists( dev );
-	TLan_ResetLists( dev );
-	TLan_ReadAndClearStats( dev, TLAN_IGNORE );
-	TLan_ResetAdapter( dev );
+	tlan_free_lists(dev);
+	tlan_reset_lists(dev);
+	tlan_read_and_clear_stats(dev, TLAN_IGNORE);
+	tlan_reset_adapter(dev);
 	dev->trans_start = jiffies; /* prevent tx timeout */
-	netif_wake_queue( dev );
+	netif_wake_queue(dev);
 
 }
 
 
-	/***************************************************************
-	 * 	TLan_tx_timeout_work
-	 *
-	 * 	Returns: nothing
-	 *
-	 * 	Params:
-	 * 		work	work item of device which timed out
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_tx_timeout_work
+ *
+ *	Returns: nothing
+ *
+ *	Params:
+ *		work	work item of device which timed out
+ *
+ **************************************************************/
 
-static void TLan_tx_timeout_work(struct work_struct *work)
+static void tlan_tx_timeout_work(struct work_struct *work)
 {
-	TLanPrivateInfo	*priv =
-		container_of(work, TLanPrivateInfo, tlan_tqueue);
+	struct tlan_priv	*priv =
+		container_of(work, struct tlan_priv, tlan_tqueue);
 
-	TLan_tx_timeout(priv->dev);
+	tlan_tx_timeout(priv->dev);
 }
 
 
 
-	/***************************************************************
-	 *	TLan_StartTx
-	 *
-	 *	Returns:
-	 *		0 on success, non-zero on failure.
-	 *	Parms:
-	 *		skb	A pointer to the sk_buff containing the
-	 *			frame to be sent.
-	 *		dev	The device to send the data on.
-	 *
-	 *	This function adds a frame to the Tx list to be sent
-	 *	ASAP.  First it	verifies that the adapter is ready and
-	 *	there is room in the queue.  Then it sets up the next
-	 *	available list, copies the frame to the	corresponding
-	 *	buffer.  If the adapter Tx channel is idle, it gives
-	 *	the adapter a Tx Go command on the list, otherwise it
-	 *	sets the forward address of the previous list to point
-	 *	to this one.  Then it frees the sk_buff.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_start_tx
+ *
+ *	Returns:
+ *		0 on success, non-zero on failure.
+ *	Parms:
+ *		skb	A pointer to the sk_buff containing the
+ *			frame to be sent.
+ *		dev	The device to send the data on.
+ *
+ *	This function adds a frame to the Tx list to be sent
+ *	ASAP.  First it	verifies that the adapter is ready and
+ *	there is room in the queue.  Then it sets up the next
+ *	available list, copies the frame to the	corresponding
+ *	buffer.  If the adapter Tx channel is idle, it gives
+ *	the adapter a Tx Go command on the list, otherwise it
+ *	sets the forward address of the previous list to point
+ *	to this one.  Then it frees the sk_buff.
+ *
+ **************************************************************/
 
-static netdev_tx_t TLan_StartTx( struct sk_buff *skb, struct net_device *dev )
+static netdev_tx_t tlan_start_tx(struct sk_buff *skb, struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	dma_addr_t	tail_list_phys;
-	TLanList	*tail_list;
+	struct tlan_list	*tail_list;
 	unsigned long	flags;
 	unsigned int    txlen;
 
-	if ( ! priv->phyOnline ) {
-		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n",
-			  dev->name );
+	if (!priv->phy_online) {
+		TLAN_DBG(TLAN_DEBUG_TX, "TRANSMIT:  %s PHY is not ready\n",
+			 dev->name);
 		dev_kfree_skb_any(skb);
 		return NETDEV_TX_OK;
 	}
@@ -1100,218 +1031,214 @@
 		return NETDEV_TX_OK;
 	txlen = max(skb->len, (unsigned int)TLAN_MIN_FRAME_SIZE);
 
-	tail_list = priv->txList + priv->txTail;
-	tail_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txTail;
+	tail_list = priv->tx_list + priv->tx_tail;
+	tail_list_phys =
+		priv->tx_list_dma + sizeof(struct tlan_list)*priv->tx_tail;
 
-	if ( tail_list->cStat != TLAN_CSTAT_UNUSED ) {
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n",
-			  dev->name, priv->txHead, priv->txTail );
+	if (tail_list->c_stat != TLAN_CSTAT_UNUSED) {
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  %s is busy (Head=%d Tail=%d)\n",
+			 dev->name, priv->tx_head, priv->tx_tail);
 		netif_stop_queue(dev);
-		priv->txBusyCount++;
+		priv->tx_busy_count++;
 		return NETDEV_TX_BUSY;
 	}
 
 	tail_list->forward = 0;
 
-	tail_list->buffer[0].address = pci_map_single(priv->pciDev,
+	tail_list->buffer[0].address = pci_map_single(priv->pci_dev,
 						      skb->data, txlen,
 						      PCI_DMA_TODEVICE);
-	TLan_StoreSKB(tail_list, skb);
+	tlan_store_skb(tail_list, skb);
 
-	tail_list->frameSize = (u16) txlen;
+	tail_list->frame_size = (u16) txlen;
 	tail_list->buffer[0].count = TLAN_LAST_BUFFER | (u32) txlen;
 	tail_list->buffer[1].count = 0;
 	tail_list->buffer[1].address = 0;
 
 	spin_lock_irqsave(&priv->lock, flags);
-	tail_list->cStat = TLAN_CSTAT_READY;
-	if ( ! priv->txInProgress ) {
-		priv->txInProgress = 1;
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  Starting TX on buffer %d\n", priv->txTail );
-		outl( tail_list_phys, dev->base_addr + TLAN_CH_PARM );
-		outl( TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD );
+	tail_list->c_stat = TLAN_CSTAT_READY;
+	if (!priv->tx_in_progress) {
+		priv->tx_in_progress = 1;
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  Starting TX on buffer %d\n",
+			 priv->tx_tail);
+		outl(tail_list_phys, dev->base_addr + TLAN_CH_PARM);
+		outl(TLAN_HC_GO, dev->base_addr + TLAN_HOST_CMD);
 	} else {
-		TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Adding buffer %d to TX channel\n",
-			  priv->txTail );
-		if ( priv->txTail == 0 ) {
-			( priv->txList + ( TLAN_NUM_TX_LISTS - 1 ) )->forward
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  Adding buffer %d to TX channel\n",
+			 priv->tx_tail);
+		if (priv->tx_tail == 0) {
+			(priv->tx_list + (TLAN_NUM_TX_LISTS - 1))->forward
 				= tail_list_phys;
 		} else {
-			( priv->txList + ( priv->txTail - 1 ) )->forward
+			(priv->tx_list + (priv->tx_tail - 1))->forward
 				= tail_list_phys;
 		}
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
 
-	CIRC_INC( priv->txTail, TLAN_NUM_TX_LISTS );
+	CIRC_INC(priv->tx_tail, TLAN_NUM_TX_LISTS);
 
 	return NETDEV_TX_OK;
 
-} /* TLan_StartTx */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleInterrupt
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		irq	The line on which the interrupt
-	 *			occurred.
-	 *		dev_id	A pointer to the device assigned to
-	 *			this irq line.
-	 *
-	 *	This function handles an interrupt generated by its
-	 *	assigned TLAN adapter.  The function deactivates
-	 *	interrupts on its adapter, records the type of
-	 *	interrupt, executes the appropriate subhandler, and
-	 *	acknowdges the interrupt to the adapter (thus
-	 *	re-enabling adapter interrupts.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_interrupt
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		irq	The line on which the interrupt
+ *			occurred.
+ *		dev_id	A pointer to the device assigned to
+ *			this irq line.
+ *
+ *	This function handles an interrupt generated by its
+ *	assigned TLAN adapter.  The function deactivates
+ *	interrupts on its adapter, records the type of
+ *	interrupt, executes the appropriate subhandler, and
+ *	acknowdges the interrupt to the adapter (thus
+ *	re-enabling adapter interrupts.
+ *
+ **************************************************************/
 
-static irqreturn_t TLan_HandleInterrupt(int irq, void *dev_id)
+static irqreturn_t tlan_handle_interrupt(int irq, void *dev_id)
 {
 	struct net_device	*dev = dev_id;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16		host_int;
 	u16		type;
 
 	spin_lock(&priv->lock);
 
-	host_int = inw( dev->base_addr + TLAN_HOST_INT );
-	type = ( host_int & TLAN_HI_IT_MASK ) >> 2;
-	if ( type ) {
+	host_int = inw(dev->base_addr + TLAN_HOST_INT);
+	type = (host_int & TLAN_HI_IT_MASK) >> 2;
+	if (type) {
 		u32	ack;
 		u32	host_cmd;
 
-		outw( host_int, dev->base_addr + TLAN_HOST_INT );
-		ack = TLanIntVector[type]( dev, host_int );
+		outw(host_int, dev->base_addr + TLAN_HOST_INT);
+		ack = tlan_int_vector[type](dev, host_int);
 
-		if ( ack ) {
-			host_cmd = TLAN_HC_ACK | ack | ( type << 18 );
-			outl( host_cmd, dev->base_addr + TLAN_HOST_CMD );
+		if (ack) {
+			host_cmd = TLAN_HC_ACK | ack | (type << 18);
+			outl(host_cmd, dev->base_addr + TLAN_HOST_CMD);
 		}
 	}
 
 	spin_unlock(&priv->lock);
 
 	return IRQ_RETVAL(type);
-} /* TLan_HandleInterrupts */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_Close
-	 *
-	 * 	Returns:
-	 *		An error code.
-	 *	Parms:
-	 *		dev	The device structure of the device to
-	 *			close.
-	 *
-	 *	This function shuts down the adapter.  It records any
-	 *	stats, puts the adapter into reset state, deactivates
-	 *	its time as needed, and	frees the irq it is using.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_close
+ *
+ *	Returns:
+ *		An error code.
+ *	Parms:
+ *		dev	The device structure of the device to
+ *			close.
+ *
+ *	This function shuts down the adapter.  It records any
+ *	stats, puts the adapter into reset state, deactivates
+ *	its time as needed, and	frees the irq it is using.
+ *
+ **************************************************************/
 
-static int TLan_Close(struct net_device *dev)
+static int tlan_close(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 
-	netif_stop_queue(dev);
 	priv->neg_be_verbose = 0;
+	tlan_stop(dev);
 
-	TLan_ReadAndClearStats( dev, TLAN_RECORD );
-	outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
-	if ( priv->timer.function != NULL ) {
-		del_timer_sync( &priv->timer );
-		priv->timer.function = NULL;
-	}
-
-	free_irq( dev->irq, dev );
-	TLan_FreeLists( dev );
-	TLAN_DBG( TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name );
+	free_irq(dev->irq, dev);
+	tlan_free_lists(dev);
+	TLAN_DBG(TLAN_DEBUG_GNRL, "Device %s closed.\n", dev->name);
 
 	return 0;
 
-} /* TLan_Close */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_GetStats
-	 *
-	 *	Returns:
-	 *		A pointer to the device's statistics structure.
-	 *	Parms:
-	 *		dev	The device structure to return the
-	 *			stats for.
-	 *
-	 *	This function updates the devices statistics by reading
-	 *	the TLAN chip's onboard registers.  Then it returns the
-	 *	address of the statistics structure.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_get_stats
+ *
+ *	Returns:
+ *		A pointer to the device's statistics structure.
+ *	Parms:
+ *		dev	The device structure to return the
+ *			stats for.
+ *
+ *	This function updates the devices statistics by reading
+ *	the TLAN chip's onboard registers.  Then it returns the
+ *	address of the statistics structure.
+ *
+ **************************************************************/
 
-static struct net_device_stats *TLan_GetStats( struct net_device *dev )
+static struct net_device_stats *tlan_get_stats(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int i;
 
 	/* Should only read stats if open ? */
-	TLan_ReadAndClearStats( dev, TLAN_RECORD );
+	tlan_read_and_clear_stats(dev, TLAN_RECORD);
 
-	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  %s EOC count = %d\n", dev->name,
-		  priv->rxEocCount );
-	TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  %s Busy count = %d\n", dev->name,
-		  priv->txBusyCount );
-	if ( debug & TLAN_DEBUG_GNRL ) {
-		TLan_PrintDio( dev->base_addr );
-		TLan_PhyPrint( dev );
+	TLAN_DBG(TLAN_DEBUG_RX, "RECEIVE:  %s EOC count = %d\n", dev->name,
+		 priv->rx_eoc_count);
+	TLAN_DBG(TLAN_DEBUG_TX, "TRANSMIT:  %s Busy count = %d\n", dev->name,
+		 priv->tx_busy_count);
+	if (debug & TLAN_DEBUG_GNRL) {
+		tlan_print_dio(dev->base_addr);
+		tlan_phy_print(dev);
 	}
-	if ( debug & TLAN_DEBUG_LIST ) {
-		for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ )
-			TLan_PrintList( priv->rxList + i, "RX", i );
-		for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ )
-			TLan_PrintList( priv->txList + i, "TX", i );
+	if (debug & TLAN_DEBUG_LIST) {
+		for (i = 0; i < TLAN_NUM_RX_LISTS; i++)
+			tlan_print_list(priv->rx_list + i, "RX", i);
+		for (i = 0; i < TLAN_NUM_TX_LISTS; i++)
+			tlan_print_list(priv->tx_list + i, "TX", i);
 	}
 
 	return &dev->stats;
 
-} /* TLan_GetStats */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_SetMulticastList
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	The device structure to set the
-	 *			multicast list for.
-	 *
-	 *	This function sets the TLAN adaptor to various receive
-	 *	modes.  If the IFF_PROMISC flag is set, promiscuous
-	 *	mode is acitviated.  Otherwise,	promiscuous mode is
-	 *	turned off.  If the IFF_ALLMULTI flag is set, then
-	 *	the hash table is set to receive all group addresses.
-	 *	Otherwise, the first three multicast addresses are
-	 *	stored in AREG_1-3, and the rest are selected via the
-	 *	hash table, as necessary.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_set_multicast_list
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	The device structure to set the
+ *			multicast list for.
+ *
+ *	This function sets the TLAN adaptor to various receive
+ *	modes.  If the IFF_PROMISC flag is set, promiscuous
+ *	mode is acitviated.  Otherwise,	promiscuous mode is
+ *	turned off.  If the IFF_ALLMULTI flag is set, then
+ *	the hash table is set to receive all group addresses.
+ *	Otherwise, the first three multicast addresses are
+ *	stored in AREG_1-3, and the rest are selected via the
+ *	hash table, as necessary.
+ *
+ **************************************************************/
 
-static void TLan_SetMulticastList( struct net_device *dev )
+static void tlan_set_multicast_list(struct net_device *dev)
 {
 	struct netdev_hw_addr *ha;
 	u32			hash1 = 0;
@@ -1320,53 +1247,56 @@
 	u32			offset;
 	u8			tmp;
 
-	if ( dev->flags & IFF_PROMISC ) {
-		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF );
+	if (dev->flags & IFF_PROMISC) {
+		tmp = tlan_dio_read8(dev->base_addr, TLAN_NET_CMD);
+		tlan_dio_write8(dev->base_addr,
+				TLAN_NET_CMD, tmp | TLAN_NET_CMD_CAF);
 	} else {
-		tmp = TLan_DioRead8( dev->base_addr, TLAN_NET_CMD );
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF );
-		if ( dev->flags & IFF_ALLMULTI ) {
-			for ( i = 0; i < 3; i++ )
-				TLan_SetMac( dev, i + 1, NULL );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, 0xFFFFFFFF );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, 0xFFFFFFFF );
+		tmp = tlan_dio_read8(dev->base_addr, TLAN_NET_CMD);
+		tlan_dio_write8(dev->base_addr,
+				TLAN_NET_CMD, tmp & ~TLAN_NET_CMD_CAF);
+		if (dev->flags & IFF_ALLMULTI) {
+			for (i = 0; i < 3; i++)
+				tlan_set_mac(dev, i + 1, NULL);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_1,
+					 0xffffffff);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_2,
+					 0xffffffff);
 		} else {
 			i = 0;
 			netdev_for_each_mc_addr(ha, dev) {
-				if ( i < 3 ) {
-					TLan_SetMac( dev, i + 1,
+				if (i < 3) {
+					tlan_set_mac(dev, i + 1,
 						     (char *) &ha->addr);
 				} else {
-					offset = TLan_HashFunc((u8 *)&ha->addr);
-					if ( offset < 32 )
-						hash1 |= ( 1 << offset );
+					offset =
+						tlan_hash_func((u8 *)&ha->addr);
+					if (offset < 32)
+						hash1 |= (1 << offset);
 					else
-						hash2 |= ( 1 << ( offset - 32 ) );
+						hash2 |= (1 << (offset - 32));
 				}
 				i++;
 			}
-			for ( ; i < 3; i++ )
-				TLan_SetMac( dev, i + 1, NULL );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_1, hash1 );
-			TLan_DioWrite32( dev->base_addr, TLAN_HASH_2, hash2 );
+			for ( ; i < 3; i++)
+				tlan_set_mac(dev, i + 1, NULL);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_1, hash1);
+			tlan_dio_write32(dev->base_addr, TLAN_HASH_2, hash2);
 		}
 	}
 
-} /* TLan_SetMulticastList */
+}
 
 
 
 /*****************************************************************************
 ******************************************************************************
 
-        ThunderLAN Driver Interrupt Vectors and Table
+ThunderLAN driver interrupt vectors and table
 
-	Please see Chap. 4, "Interrupt Handling" of the "ThunderLAN
-	Programmer's Guide" for more informations on handling interrupts
-	generated by TLAN based adapters.
+please see chap. 4, "Interrupt Handling" of the "ThunderLAN
+Programmer's Guide" for more informations on handling interrupts
+generated by TLAN based adapters.
 
 ******************************************************************************
 *****************************************************************************/
@@ -1374,46 +1304,48 @@
 
 
 
-	/***************************************************************
-	 *	TLan_HandleTxEOF
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles Tx EOF interrupts which are raised
-	 *	by the adapter when it has completed sending the
-	 *	contents of a buffer.  If detemines which list/buffer
-	 *	was completed and resets it.  If the buffer was the last
-	 *	in the channel (EOC), then the function checks to see if
-	 *	another buffer is ready to send, and if so, sends a Tx
-	 *	Go command.  Finally, the driver activates/continues the
-	 *	activity LED.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_tx_eof
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles Tx EOF interrupts which are raised
+ *	by the adapter when it has completed sending the
+ *	contents of a buffer.  If detemines which list/buffer
+ *	was completed and resets it.  If the buffer was the last
+ *	in the channel (EOC), then the function checks to see if
+ *	another buffer is ready to send, and if so, sends a Tx
+ *	Go command.  Finally, the driver activates/continues the
+ *	activity LED.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleTxEOF( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_tx_eof(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int		eoc = 0;
-	TLanList	*head_list;
+	struct tlan_list	*head_list;
 	dma_addr_t	head_list_phys;
 	u32		ack = 0;
-	u16		tmpCStat;
+	u16		tmp_c_stat;
 
-	TLAN_DBG( TLAN_DEBUG_TX, "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n",
-		  priv->txHead, priv->txTail );
-	head_list = priv->txList + priv->txHead;
+	TLAN_DBG(TLAN_DEBUG_TX,
+		 "TRANSMIT:  Handling TX EOF (Head=%d Tail=%d)\n",
+		 priv->tx_head, priv->tx_tail);
+	head_list = priv->tx_list + priv->tx_head;
 
-	while (((tmpCStat = head_list->cStat ) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
-		struct sk_buff *skb = TLan_GetSKB(head_list);
+	while (((tmp_c_stat = head_list->c_stat) & TLAN_CSTAT_FRM_CMP)
+	       && (ack < 255)) {
+		struct sk_buff *skb = tlan_get_skb(head_list);
 
 		ack++;
-		pci_unmap_single(priv->pciDev, head_list->buffer[0].address,
+		pci_unmap_single(priv->pci_dev, head_list->buffer[0].address,
 				 max(skb->len,
 				     (unsigned int)TLAN_MIN_FRAME_SIZE),
 				 PCI_DMA_TODEVICE);
@@ -1421,304 +1353,313 @@
 		head_list->buffer[8].address = 0;
 		head_list->buffer[9].address = 0;
 
-		if ( tmpCStat & TLAN_CSTAT_EOC )
+		if (tmp_c_stat & TLAN_CSTAT_EOC)
 			eoc = 1;
 
-		dev->stats.tx_bytes += head_list->frameSize;
+		dev->stats.tx_bytes += head_list->frame_size;
 
-		head_list->cStat = TLAN_CSTAT_UNUSED;
+		head_list->c_stat = TLAN_CSTAT_UNUSED;
 		netif_start_queue(dev);
-		CIRC_INC( priv->txHead, TLAN_NUM_TX_LISTS );
-		head_list = priv->txList + priv->txHead;
+		CIRC_INC(priv->tx_head, TLAN_NUM_TX_LISTS);
+		head_list = priv->tx_list + priv->tx_head;
 	}
 
 	if (!ack)
-		printk(KERN_INFO "TLAN: Received interrupt for uncompleted TX frame.\n");
+		netdev_info(dev,
+			    "Received interrupt for uncompleted TX frame\n");
 
-	if ( eoc ) {
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d)\n",
-			  priv->txHead, priv->txTail );
-		head_list = priv->txList + priv->txHead;
-		head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
-		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
-			outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
+	if (eoc) {
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  handling TX EOC (Head=%d Tail=%d)\n",
+			 priv->tx_head, priv->tx_tail);
+		head_list = priv->tx_list + priv->tx_head;
+		head_list_phys = priv->tx_list_dma
+			+ sizeof(struct tlan_list)*priv->tx_head;
+		if ((head_list->c_stat & TLAN_CSTAT_READY)
+		    == TLAN_CSTAT_READY) {
+			outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 			ack |= TLAN_HC_GO;
 		} else {
-			priv->txInProgress = 0;
+			priv->tx_in_progress = 0;
 		}
 	}
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
-		if ( priv->timer.function == NULL ) {
-			 priv->timer.function = TLan_Timer;
-			 priv->timer.data = (unsigned long) dev;
-			 priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
-			 priv->timerSetAt = jiffies;
-			 priv->timerType = TLAN_TIMER_ACTIVITY;
-			 add_timer(&priv->timer);
-		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
-			priv->timerSetAt = jiffies;
+	if (priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED) {
+		tlan_dio_write8(dev->base_addr,
+				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT);
+		if (priv->timer.function == NULL) {
+			priv->timer.function = tlan_timer;
+			priv->timer.data = (unsigned long) dev;
+			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
+			priv->timer_set_at = jiffies;
+			priv->timer_type = TLAN_TIMER_ACTIVITY;
+			add_timer(&priv->timer);
+		} else if (priv->timer_type == TLAN_TIMER_ACTIVITY) {
+			priv->timer_set_at = jiffies;
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleTxEOF */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleStatOverflow
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles the Statistics Overflow interrupt
-	 *	which means that one or more of the TLAN statistics
-	 *	registers has reached 1/2 capacity and needs to be read.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_HandleStatOverflow
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles the Statistics Overflow interrupt
+ *	which means that one or more of the TLAN statistics
+ *	registers has reached 1/2 capacity and needs to be read.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleStatOverflow( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_stat_overflow(struct net_device *dev, u16 host_int)
 {
-	TLan_ReadAndClearStats( dev, TLAN_RECORD );
+	tlan_read_and_clear_stats(dev, TLAN_RECORD);
 
 	return 1;
 
-} /* TLan_HandleStatOverflow */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleRxEOF
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles the Rx EOF interrupt which
-	 *	indicates a frame has been received by the adapter from
-	 *	the net and the frame has been transferred to memory.
-	 *	The function determines the bounce buffer the frame has
-	 *	been loaded into, creates a new sk_buff big enough to
-	 *	hold the frame, and sends it to protocol stack.  It
-	 *	then resets the used buffer and appends it to the end
-	 *	of the list.  If the frame was the last in the Rx
-	 *	channel (EOC), the function restarts the receive channel
-	 *	by sending an Rx Go command to the adapter.  Then it
-	 *	activates/continues the activity LED.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_HandleRxEOF
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles the Rx EOF interrupt which
+ *	indicates a frame has been received by the adapter from
+ *	the net and the frame has been transferred to memory.
+ *	The function determines the bounce buffer the frame has
+ *	been loaded into, creates a new sk_buff big enough to
+ *	hold the frame, and sends it to protocol stack.  It
+ *	then resets the used buffer and appends it to the end
+ *	of the list.  If the frame was the last in the Rx
+ *	channel (EOC), the function restarts the receive channel
+ *	by sending an Rx Go command to the adapter.  Then it
+ *	activates/continues the activity LED.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleRxEOF( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_rx_eof(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u32		ack = 0;
 	int		eoc = 0;
-	TLanList	*head_list;
+	struct tlan_list	*head_list;
 	struct sk_buff	*skb;
-	TLanList	*tail_list;
-	u16		tmpCStat;
+	struct tlan_list	*tail_list;
+	u16		tmp_c_stat;
 	dma_addr_t	head_list_phys;
 
-	TLAN_DBG( TLAN_DEBUG_RX, "RECEIVE:  Handling RX EOF (Head=%d Tail=%d)\n",
-		  priv->rxHead, priv->rxTail );
-	head_list = priv->rxList + priv->rxHead;
-	head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
+	TLAN_DBG(TLAN_DEBUG_RX, "RECEIVE:  handling RX EOF (Head=%d Tail=%d)\n",
+		 priv->rx_head, priv->rx_tail);
+	head_list = priv->rx_list + priv->rx_head;
+	head_list_phys =
+		priv->rx_list_dma + sizeof(struct tlan_list)*priv->rx_head;
 
-	while (((tmpCStat = head_list->cStat) & TLAN_CSTAT_FRM_CMP) && (ack < 255)) {
-		dma_addr_t frameDma = head_list->buffer[0].address;
-		u32 frameSize = head_list->frameSize;
+	while (((tmp_c_stat = head_list->c_stat) & TLAN_CSTAT_FRM_CMP)
+	       && (ack < 255)) {
+		dma_addr_t frame_dma = head_list->buffer[0].address;
+		u32 frame_size = head_list->frame_size;
 		struct sk_buff *new_skb;
 
 		ack++;
-		if (tmpCStat & TLAN_CSTAT_EOC)
+		if (tmp_c_stat & TLAN_CSTAT_EOC)
 			eoc = 1;
 
 		new_skb = netdev_alloc_skb_ip_align(dev,
 						    TLAN_MAX_FRAME_SIZE + 5);
-		if ( !new_skb )
+		if (!new_skb)
 			goto drop_and_reuse;
 
-		skb = TLan_GetSKB(head_list);
-		pci_unmap_single(priv->pciDev, frameDma,
+		skb = tlan_get_skb(head_list);
+		pci_unmap_single(priv->pci_dev, frame_dma,
 				 TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
-		skb_put( skb, frameSize );
+		skb_put(skb, frame_size);
 
-		dev->stats.rx_bytes += frameSize;
+		dev->stats.rx_bytes += frame_size;
 
-		skb->protocol = eth_type_trans( skb, dev );
-		netif_rx( skb );
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_rx(skb);
 
-		head_list->buffer[0].address = pci_map_single(priv->pciDev,
-							      new_skb->data,
-							      TLAN_MAX_FRAME_SIZE,
-							      PCI_DMA_FROMDEVICE);
+		head_list->buffer[0].address =
+			pci_map_single(priv->pci_dev, new_skb->data,
+				       TLAN_MAX_FRAME_SIZE, PCI_DMA_FROMDEVICE);
 
-		TLan_StoreSKB(head_list, new_skb);
+		tlan_store_skb(head_list, new_skb);
 drop_and_reuse:
 		head_list->forward = 0;
-		head_list->cStat = 0;
-		tail_list = priv->rxList + priv->rxTail;
+		head_list->c_stat = 0;
+		tail_list = priv->rx_list + priv->rx_tail;
 		tail_list->forward = head_list_phys;
 
-		CIRC_INC( priv->rxHead, TLAN_NUM_RX_LISTS );
-		CIRC_INC( priv->rxTail, TLAN_NUM_RX_LISTS );
-		head_list = priv->rxList + priv->rxHead;
-		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
+		CIRC_INC(priv->rx_head, TLAN_NUM_RX_LISTS);
+		CIRC_INC(priv->rx_tail, TLAN_NUM_RX_LISTS);
+		head_list = priv->rx_list + priv->rx_head;
+		head_list_phys = priv->rx_list_dma
+			+ sizeof(struct tlan_list)*priv->rx_head;
 	}
 
 	if (!ack)
-		printk(KERN_INFO "TLAN: Received interrupt for uncompleted RX frame.\n");
+		netdev_info(dev,
+			    "Received interrupt for uncompleted RX frame\n");
 
 
-	if ( eoc ) {
-		TLAN_DBG( TLAN_DEBUG_RX,
-			  "RECEIVE:  Handling RX EOC (Head=%d Tail=%d)\n",
-			  priv->rxHead, priv->rxTail );
-		head_list = priv->rxList + priv->rxHead;
-		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
-		outl(head_list_phys, dev->base_addr + TLAN_CH_PARM );
+	if (eoc) {
+		TLAN_DBG(TLAN_DEBUG_RX,
+			 "RECEIVE:  handling RX EOC (Head=%d Tail=%d)\n",
+			 priv->rx_head, priv->rx_tail);
+		head_list = priv->rx_list + priv->rx_head;
+		head_list_phys = priv->rx_list_dma
+			+ sizeof(struct tlan_list)*priv->rx_head;
+		outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
-		priv->rxEocCount++;
+		priv->rx_eoc_count++;
 	}
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED ) {
-		TLan_DioWrite8( dev->base_addr,
-				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT );
-		if ( priv->timer.function == NULL )  {
-			priv->timer.function = TLan_Timer;
+	if (priv->adapter->flags & TLAN_ADAPTER_ACTIVITY_LED) {
+		tlan_dio_write8(dev->base_addr,
+				TLAN_LED_REG, TLAN_LED_LINK | TLAN_LED_ACT);
+		if (priv->timer.function == NULL)  {
+			priv->timer.function = tlan_timer;
 			priv->timer.data = (unsigned long) dev;
 			priv->timer.expires = jiffies + TLAN_TIMER_ACT_DELAY;
-			priv->timerSetAt = jiffies;
-			priv->timerType = TLAN_TIMER_ACTIVITY;
+			priv->timer_set_at = jiffies;
+			priv->timer_type = TLAN_TIMER_ACTIVITY;
 			add_timer(&priv->timer);
-		} else if ( priv->timerType == TLAN_TIMER_ACTIVITY ) {
-			priv->timerSetAt = jiffies;
+		} else if (priv->timer_type == TLAN_TIMER_ACTIVITY) {
+			priv->timer_set_at = jiffies;
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleRxEOF */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleDummy
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles the Dummy interrupt, which is
-	 *	raised whenever a test interrupt is generated by setting
-	 *	the Req_Int bit of HOST_CMD to 1.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_dummy
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles the Dummy interrupt, which is
+ *	raised whenever a test interrupt is generated by setting
+ *	the Req_Int bit of HOST_CMD to 1.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleDummy( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_dummy(struct net_device *dev, u16 host_int)
 {
-	printk( "TLAN:  Test interrupt on %s.\n", dev->name );
+	netdev_info(dev, "Test interrupt\n");
 	return 1;
 
-} /* TLan_HandleDummy */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleTxEOC
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This driver is structured to determine EOC occurrences by
-	 *	reading the CSTAT member of the list structure.  Tx EOC
-	 *	interrupts are disabled via the DIO INTDIS register.
-	 *	However, TLAN chips before revision 3.0 didn't have this
-	 *	functionality, so process EOC events if this is the
-	 *	case.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_tx_eoc
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This driver is structured to determine EOC occurrences by
+ *	reading the CSTAT member of the list structure.  Tx EOC
+ *	interrupts are disabled via the DIO INTDIS register.
+ *	However, TLAN chips before revision 3.0 didn't have this
+ *	functionality, so process EOC events if this is the
+ *	case.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleTxEOC( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_tx_eoc(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
-	TLanList		*head_list;
+	struct tlan_priv	*priv = netdev_priv(dev);
+	struct tlan_list		*head_list;
 	dma_addr_t		head_list_phys;
 	u32			ack = 1;
 
 	host_int = 0;
-	if ( priv->tlanRev < 0x30 ) {
-		TLAN_DBG( TLAN_DEBUG_TX,
-			  "TRANSMIT:  Handling TX EOC (Head=%d Tail=%d) -- IRQ\n",
-			  priv->txHead, priv->txTail );
-		head_list = priv->txList + priv->txHead;
-		head_list_phys = priv->txListDMA + sizeof(TLanList) * priv->txHead;
-		if ( ( head_list->cStat & TLAN_CSTAT_READY ) == TLAN_CSTAT_READY ) {
+	if (priv->tlan_rev < 0x30) {
+		TLAN_DBG(TLAN_DEBUG_TX,
+			 "TRANSMIT:  handling TX EOC (Head=%d Tail=%d) -- IRQ\n",
+			 priv->tx_head, priv->tx_tail);
+		head_list = priv->tx_list + priv->tx_head;
+		head_list_phys = priv->tx_list_dma
+			+ sizeof(struct tlan_list)*priv->tx_head;
+		if ((head_list->c_stat & TLAN_CSTAT_READY)
+		    == TLAN_CSTAT_READY) {
 			netif_stop_queue(dev);
-			outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
+			outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 			ack |= TLAN_HC_GO;
 		} else {
-			priv->txInProgress = 0;
+			priv->tx_in_progress = 0;
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleTxEOC */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleStatusCheck
-	 *
-	 *	Returns:
-	 *		0 if Adapter check, 1 if Network Status check.
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This function handles Adapter Check/Network Status
-	 *	interrupts generated by the adapter.  It checks the
-	 *	vector in the HOST_INT register to determine if it is
-	 *	an Adapter Check interrupt.  If so, it resets the
-	 *	adapter.  Otherwise it clears the status registers
-	 *	and services the PHY.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_status_check
+ *
+ *	Returns:
+ *		0 if Adapter check, 1 if Network Status check.
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This function handles Adapter Check/Network Status
+ *	interrupts generated by the adapter.  It checks the
+ *	vector in the HOST_INT register to determine if it is
+ *	an Adapter Check interrupt.  If so, it resets the
+ *	adapter.  Otherwise it clears the status registers
+ *	and services the PHY.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleStatusCheck( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_status_check(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u32		ack;
 	u32		error;
 	u8		net_sts;
@@ -1727,92 +1668,94 @@
 	u16		tlphy_sts;
 
 	ack = 1;
-	if ( host_int & TLAN_HI_IV_MASK ) {
-		netif_stop_queue( dev );
-		error = inl( dev->base_addr + TLAN_CH_PARM );
-		printk( "TLAN:  %s: Adaptor Error = 0x%x\n", dev->name, error );
-		TLan_ReadAndClearStats( dev, TLAN_RECORD );
-		outl( TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD );
+	if (host_int & TLAN_HI_IV_MASK) {
+		netif_stop_queue(dev);
+		error = inl(dev->base_addr + TLAN_CH_PARM);
+		netdev_info(dev, "Adaptor Error = 0x%x\n", error);
+		tlan_read_and_clear_stats(dev, TLAN_RECORD);
+		outl(TLAN_HC_AD_RST, dev->base_addr + TLAN_HOST_CMD);
 
 		schedule_work(&priv->tlan_tqueue);
 
 		netif_wake_queue(dev);
 		ack = 0;
 	} else {
-		TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name );
-		phy = priv->phy[priv->phyNum];
+		TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Status Check\n", dev->name);
+		phy = priv->phy[priv->phy_num];
 
-		net_sts = TLan_DioRead8( dev->base_addr, TLAN_NET_STS );
-		if ( net_sts ) {
-			TLan_DioWrite8( dev->base_addr, TLAN_NET_STS, net_sts );
-			TLAN_DBG( TLAN_DEBUG_GNRL, "%s:    Net_Sts = %x\n",
-				  dev->name, (unsigned) net_sts );
+		net_sts = tlan_dio_read8(dev->base_addr, TLAN_NET_STS);
+		if (net_sts) {
+			tlan_dio_write8(dev->base_addr, TLAN_NET_STS, net_sts);
+			TLAN_DBG(TLAN_DEBUG_GNRL, "%s:    Net_Sts = %x\n",
+				 dev->name, (unsigned) net_sts);
 		}
-		if ( ( net_sts & TLAN_NET_STS_MIRQ ) &&  ( priv->phyNum == 0 ) ) {
-			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_STS, &tlphy_sts );
-			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
-        		if ( ! ( tlphy_sts & TLAN_TS_POLOK ) &&
-			     ! ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
-                		tlphy_ctl |= TLAN_TC_SWAPOL;
-                		TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
-			} else if ( ( tlphy_sts & TLAN_TS_POLOK ) &&
-				    ( tlphy_ctl & TLAN_TC_SWAPOL ) ) {
-                		tlphy_ctl &= ~TLAN_TC_SWAPOL;
-                		TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
-        		}
-
-			if (debug) {
-				TLan_PhyPrint( dev );
+		if ((net_sts & TLAN_NET_STS_MIRQ) &&  (priv->phy_num == 0)) {
+			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_STS, &tlphy_sts);
+			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
+			if (!(tlphy_sts & TLAN_TS_POLOK) &&
+			    !(tlphy_ctl & TLAN_TC_SWAPOL)) {
+				tlphy_ctl |= TLAN_TC_SWAPOL;
+				tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL,
+						   tlphy_ctl);
+			} else if ((tlphy_sts & TLAN_TS_POLOK) &&
+				   (tlphy_ctl & TLAN_TC_SWAPOL)) {
+				tlphy_ctl &= ~TLAN_TC_SWAPOL;
+				tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL,
+						   tlphy_ctl);
 			}
+
+			if (debug)
+				tlan_phy_print(dev);
 		}
 	}
 
 	return ack;
 
-} /* TLan_HandleStatusCheck */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_HandleRxEOC
-	 *
-	 *	Returns:
-	 *		1
-	 *	Parms:
-	 *		dev		Device assigned the IRQ that was
-	 *				raised.
-	 *		host_int	The contents of the HOST_INT
-	 *				port.
-	 *
-	 *	This driver is structured to determine EOC occurrences by
-	 *	reading the CSTAT member of the list structure.  Rx EOC
-	 *	interrupts are disabled via the DIO INTDIS register.
-	 *	However, TLAN chips before revision 3.0 didn't have this
-	 *	CSTAT member or a INTDIS register, so if this chip is
-	 *	pre-3.0, process EOC interrupts normally.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_handle_rx_eoc
+ *
+ *	Returns:
+ *		1
+ *	Parms:
+ *		dev		Device assigned the IRQ that was
+ *				raised.
+ *		host_int	The contents of the HOST_INT
+ *				port.
+ *
+ *	This driver is structured to determine EOC occurrences by
+ *	reading the CSTAT member of the list structure.  Rx EOC
+ *	interrupts are disabled via the DIO INTDIS register.
+ *	However, TLAN chips before revision 3.0 didn't have this
+ *	CSTAT member or a INTDIS register, so if this chip is
+ *	pre-3.0, process EOC interrupts normally.
+ *
+ **************************************************************/
 
-static u32 TLan_HandleRxEOC( struct net_device *dev, u16 host_int )
+static u32 tlan_handle_rx_eoc(struct net_device *dev, u16 host_int)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	dma_addr_t	head_list_phys;
 	u32		ack = 1;
 
-	if (  priv->tlanRev < 0x30 ) {
-		TLAN_DBG( TLAN_DEBUG_RX,
-			  "RECEIVE:  Handling RX EOC (Head=%d Tail=%d) -- IRQ\n",
-			  priv->rxHead, priv->rxTail );
-		head_list_phys = priv->rxListDMA + sizeof(TLanList) * priv->rxHead;
-		outl( head_list_phys, dev->base_addr + TLAN_CH_PARM );
+	if (priv->tlan_rev < 0x30) {
+		TLAN_DBG(TLAN_DEBUG_RX,
+			 "RECEIVE:  Handling RX EOC (head=%d tail=%d) -- IRQ\n",
+			 priv->rx_head, priv->rx_tail);
+		head_list_phys = priv->rx_list_dma
+			+ sizeof(struct tlan_list)*priv->rx_head;
+		outl(head_list_phys, dev->base_addr + TLAN_CH_PARM);
 		ack |= TLAN_HC_GO | TLAN_HC_RT;
-		priv->rxEocCount++;
+		priv->rx_eoc_count++;
 	}
 
 	return ack;
 
-} /* TLan_HandleRxEOC */
+}
 
 
 
@@ -1820,98 +1763,98 @@
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Timer Function
+ThunderLAN driver timer function
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_Timer
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		data	A value given to add timer when
-	 *			add_timer was called.
-	 *
-	 *	This function handles timed functionality for the
-	 *	TLAN driver.  The two current timer uses are for
-	 *	delaying for autonegotionation and driving the ACT LED.
-	 *	-	Autonegotiation requires being allowed about
-	 *		2 1/2 seconds before attempting to transmit a
-	 *		packet.  It would be a very bad thing to hang
-	 *		the kernel this long, so the driver doesn't
-	 *		allow transmission 'til after this time, for
-	 *		certain PHYs.  It would be much nicer if all
-	 *		PHYs were interrupt-capable like the internal
-	 *		PHY.
-	 *	-	The ACT LED, which shows adapter activity, is
-	 *		driven by the driver, and so must be left on
-	 *		for a short period to power up the LED so it
-	 *		can be seen.  This delay can be changed by
-	 *		changing the TLAN_TIMER_ACT_DELAY in tlan.h,
-	 *		if desired.  100 ms  produces a slightly
-	 *		sluggish response.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_timer
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		data	A value given to add timer when
+ *			add_timer was called.
+ *
+ *	This function handles timed functionality for the
+ *	TLAN driver.  The two current timer uses are for
+ *	delaying for autonegotionation and driving the ACT LED.
+ *	-	Autonegotiation requires being allowed about
+ *		2 1/2 seconds before attempting to transmit a
+ *		packet.  It would be a very bad thing to hang
+ *		the kernel this long, so the driver doesn't
+ *		allow transmission 'til after this time, for
+ *		certain PHYs.  It would be much nicer if all
+ *		PHYs were interrupt-capable like the internal
+ *		PHY.
+ *	-	The ACT LED, which shows adapter activity, is
+ *		driven by the driver, and so must be left on
+ *		for a short period to power up the LED so it
+ *		can be seen.  This delay can be changed by
+ *		changing the TLAN_TIMER_ACT_DELAY in tlan.h,
+ *		if desired.  100 ms  produces a slightly
+ *		sluggish response.
+ *
+ **************************************************************/
 
-static void TLan_Timer( unsigned long data )
+static void tlan_timer(unsigned long data)
 {
 	struct net_device	*dev = (struct net_device *) data;
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u32		elapsed;
 	unsigned long	flags = 0;
 
 	priv->timer.function = NULL;
 
-	switch ( priv->timerType ) {
+	switch (priv->timer_type) {
 #ifdef MONITOR
-		case TLAN_TIMER_LINK_BEAT:
-			TLan_PhyMonitor( dev );
-			break;
+	case TLAN_TIMER_LINK_BEAT:
+		tlan_phy_monitor(dev);
+		break;
 #endif
-		case TLAN_TIMER_PHY_PDOWN:
-			TLan_PhyPowerDown( dev );
-			break;
-		case TLAN_TIMER_PHY_PUP:
-			TLan_PhyPowerUp( dev );
-			break;
-		case TLAN_TIMER_PHY_RESET:
-			TLan_PhyReset( dev );
-			break;
-		case TLAN_TIMER_PHY_START_LINK:
-			TLan_PhyStartLink( dev );
-			break;
-		case TLAN_TIMER_PHY_FINISH_AN:
-			TLan_PhyFinishAutoNeg( dev );
-			break;
-		case TLAN_TIMER_FINISH_RESET:
-			TLan_FinishReset( dev );
-			break;
-		case TLAN_TIMER_ACTIVITY:
-			spin_lock_irqsave(&priv->lock, flags);
-			if ( priv->timer.function == NULL ) {
-				elapsed = jiffies - priv->timerSetAt;
-				if ( elapsed >= TLAN_TIMER_ACT_DELAY ) {
-					TLan_DioWrite8( dev->base_addr,
-							TLAN_LED_REG, TLAN_LED_LINK );
-				} else  {
-					priv->timer.function = TLan_Timer;
-					priv->timer.expires = priv->timerSetAt
-						+ TLAN_TIMER_ACT_DELAY;
-					spin_unlock_irqrestore(&priv->lock, flags);
-					add_timer( &priv->timer );
-					break;
-				}
+	case TLAN_TIMER_PHY_PDOWN:
+		tlan_phy_power_down(dev);
+		break;
+	case TLAN_TIMER_PHY_PUP:
+		tlan_phy_power_up(dev);
+		break;
+	case TLAN_TIMER_PHY_RESET:
+		tlan_phy_reset(dev);
+		break;
+	case TLAN_TIMER_PHY_START_LINK:
+		tlan_phy_start_link(dev);
+		break;
+	case TLAN_TIMER_PHY_FINISH_AN:
+		tlan_phy_finish_auto_neg(dev);
+		break;
+	case TLAN_TIMER_FINISH_RESET:
+		tlan_finish_reset(dev);
+		break;
+	case TLAN_TIMER_ACTIVITY:
+		spin_lock_irqsave(&priv->lock, flags);
+		if (priv->timer.function == NULL) {
+			elapsed = jiffies - priv->timer_set_at;
+			if (elapsed >= TLAN_TIMER_ACT_DELAY) {
+				tlan_dio_write8(dev->base_addr,
+						TLAN_LED_REG, TLAN_LED_LINK);
+			} else  {
+				priv->timer.function = tlan_timer;
+				priv->timer.expires = priv->timer_set_at
+					+ TLAN_TIMER_ACT_DELAY;
+				spin_unlock_irqrestore(&priv->lock, flags);
+				add_timer(&priv->timer);
+				break;
 			}
-			spin_unlock_irqrestore(&priv->lock, flags);
-			break;
-		default:
-			break;
+		}
+		spin_unlock_irqrestore(&priv->lock, flags);
+		break;
+	default:
+		break;
 	}
 
-} /* TLan_Timer */
+}
 
 
 
@@ -1919,39 +1862,39 @@
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Adapter Related Routines
+ThunderLAN driver adapter related routines
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_ResetLists
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	The device structure with the list
-	 *			stuctures to be reset.
-	 *
-	 *	This routine sets the variables associated with managing
-	 *	the TLAN lists to their initial values.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_reset_lists
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	The device structure with the list
+ *			stuctures to be reset.
+ *
+ *	This routine sets the variables associated with managing
+ *	the TLAN lists to their initial values.
+ *
+ **************************************************************/
 
-static void TLan_ResetLists( struct net_device *dev )
+static void tlan_reset_lists(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	int		i;
-	TLanList	*list;
+	struct tlan_list	*list;
 	dma_addr_t	list_phys;
 	struct sk_buff	*skb;
 
-	priv->txHead = 0;
-	priv->txTail = 0;
-	for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
-		list = priv->txList + i;
-		list->cStat = TLAN_CSTAT_UNUSED;
+	priv->tx_head = 0;
+	priv->tx_tail = 0;
+	for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
+		list = priv->tx_list + i;
+		list->c_stat = TLAN_CSTAT_UNUSED;
 		list->buffer[0].address = 0;
 		list->buffer[2].count = 0;
 		list->buffer[2].address = 0;
@@ -1959,169 +1902,169 @@
 		list->buffer[9].address = 0;
 	}
 
-	priv->rxHead = 0;
-	priv->rxTail = TLAN_NUM_RX_LISTS - 1;
-	for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
-		list = priv->rxList + i;
-		list_phys = priv->rxListDMA + sizeof(TLanList) * i;
-		list->cStat = TLAN_CSTAT_READY;
-		list->frameSize = TLAN_MAX_FRAME_SIZE;
+	priv->rx_head = 0;
+	priv->rx_tail = TLAN_NUM_RX_LISTS - 1;
+	for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
+		list = priv->rx_list + i;
+		list_phys = priv->rx_list_dma + sizeof(struct tlan_list)*i;
+		list->c_stat = TLAN_CSTAT_READY;
+		list->frame_size = TLAN_MAX_FRAME_SIZE;
 		list->buffer[0].count = TLAN_MAX_FRAME_SIZE | TLAN_LAST_BUFFER;
 		skb = netdev_alloc_skb_ip_align(dev, TLAN_MAX_FRAME_SIZE + 5);
-		if ( !skb ) {
-			pr_err("TLAN: out of memory for received data.\n" );
+		if (!skb) {
+			netdev_err(dev, "Out of memory for received data\n");
 			break;
 		}
 
-		list->buffer[0].address = pci_map_single(priv->pciDev,
+		list->buffer[0].address = pci_map_single(priv->pci_dev,
 							 skb->data,
 							 TLAN_MAX_FRAME_SIZE,
 							 PCI_DMA_FROMDEVICE);
-		TLan_StoreSKB(list, skb);
+		tlan_store_skb(list, skb);
 		list->buffer[1].count = 0;
 		list->buffer[1].address = 0;
-		list->forward = list_phys + sizeof(TLanList);
+		list->forward = list_phys + sizeof(struct tlan_list);
 	}
 
 	/* in case ran out of memory early, clear bits */
 	while (i < TLAN_NUM_RX_LISTS) {
-		TLan_StoreSKB(priv->rxList + i, NULL);
+		tlan_store_skb(priv->rx_list + i, NULL);
 		++i;
 	}
 	list->forward = 0;
 
-} /* TLan_ResetLists */
+}
 
 
-static void TLan_FreeLists( struct net_device *dev )
+static void tlan_free_lists(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	int		i;
-	TLanList	*list;
+	struct tlan_list	*list;
 	struct sk_buff	*skb;
 
-	for ( i = 0; i < TLAN_NUM_TX_LISTS; i++ ) {
-		list = priv->txList + i;
-		skb = TLan_GetSKB(list);
-		if ( skb ) {
+	for (i = 0; i < TLAN_NUM_TX_LISTS; i++) {
+		list = priv->tx_list + i;
+		skb = tlan_get_skb(list);
+		if (skb) {
 			pci_unmap_single(
-				priv->pciDev,
+				priv->pci_dev,
 				list->buffer[0].address,
 				max(skb->len,
 				    (unsigned int)TLAN_MIN_FRAME_SIZE),
 				PCI_DMA_TODEVICE);
-			dev_kfree_skb_any( skb );
+			dev_kfree_skb_any(skb);
 			list->buffer[8].address = 0;
 			list->buffer[9].address = 0;
 		}
 	}
 
-	for ( i = 0; i < TLAN_NUM_RX_LISTS; i++ ) {
-		list = priv->rxList + i;
-		skb = TLan_GetSKB(list);
-		if ( skb ) {
-			pci_unmap_single(priv->pciDev,
+	for (i = 0; i < TLAN_NUM_RX_LISTS; i++) {
+		list = priv->rx_list + i;
+		skb = tlan_get_skb(list);
+		if (skb) {
+			pci_unmap_single(priv->pci_dev,
 					 list->buffer[0].address,
 					 TLAN_MAX_FRAME_SIZE,
 					 PCI_DMA_FROMDEVICE);
-			dev_kfree_skb_any( skb );
+			dev_kfree_skb_any(skb);
 			list->buffer[8].address = 0;
 			list->buffer[9].address = 0;
 		}
 	}
-} /* TLan_FreeLists */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_PrintDio
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		io_base		Base IO port of the device of
-	 *				which to print DIO registers.
-	 *
-	 *	This function prints out all the internal (DIO)
-	 *	registers of a TLAN chip.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_print_dio
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		io_base		Base IO port of the device of
+ *				which to print DIO registers.
+ *
+ *	This function prints out all the internal (DIO)
+ *	registers of a TLAN chip.
+ *
+ **************************************************************/
 
-static void TLan_PrintDio( u16 io_base )
+static void tlan_print_dio(u16 io_base)
 {
 	u32 data0, data1;
 	int	i;
 
-	printk( "TLAN:   Contents of internal registers for io base 0x%04hx.\n",
-		io_base );
-	printk( "TLAN:      Off.  +0         +4\n" );
-	for ( i = 0; i < 0x4C; i+= 8 ) {
-		data0 = TLan_DioRead32( io_base, i );
-		data1 = TLan_DioRead32( io_base, i + 0x4 );
-		printk( "TLAN:      0x%02x  0x%08x 0x%08x\n", i, data0, data1 );
+	pr_info("Contents of internal registers for io base 0x%04hx\n",
+		io_base);
+	pr_info("Off.  +0        +4\n");
+	for (i = 0; i < 0x4C; i += 8) {
+		data0 = tlan_dio_read32(io_base, i);
+		data1 = tlan_dio_read32(io_base, i + 0x4);
+		pr_info("0x%02x  0x%08x 0x%08x\n", i, data0, data1);
 	}
 
-} /* TLan_PrintDio */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_PrintList
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		list	A pointer to the TLanList structure to
-	 *			be printed.
-	 *		type	A string to designate type of list,
-	 *			"Rx" or "Tx".
-	 *		num	The index of the list.
-	 *
-	 *	This function prints out the contents of the list
-	 *	pointed to by the list parameter.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_PrintList
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		list	A pointer to the struct tlan_list structure to
+ *			be printed.
+ *		type	A string to designate type of list,
+ *			"Rx" or "Tx".
+ *		num	The index of the list.
+ *
+ *	This function prints out the contents of the list
+ *	pointed to by the list parameter.
+ *
+ **************************************************************/
 
-static void TLan_PrintList( TLanList *list, char *type, int num)
+static void tlan_print_list(struct tlan_list *list, char *type, int num)
 {
 	int i;
 
-	printk( "TLAN:   %s List %d at %p\n", type, num, list );
-	printk( "TLAN:      Forward    = 0x%08x\n",  list->forward );
-	printk( "TLAN:      CSTAT      = 0x%04hx\n", list->cStat );
-	printk( "TLAN:      Frame Size = 0x%04hx\n", list->frameSize );
-	/* for ( i = 0; i < 10; i++ ) { */
-	for ( i = 0; i < 2; i++ ) {
-		printk( "TLAN:      Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
-			i, list->buffer[i].count, list->buffer[i].address );
+	pr_info("%s List %d at %p\n", type, num, list);
+	pr_info("   Forward    = 0x%08x\n",  list->forward);
+	pr_info("   CSTAT      = 0x%04hx\n", list->c_stat);
+	pr_info("   Frame Size = 0x%04hx\n", list->frame_size);
+	/* for (i = 0; i < 10; i++) { */
+	for (i = 0; i < 2; i++) {
+		pr_info("   Buffer[%d].count, addr = 0x%08x, 0x%08x\n",
+			i, list->buffer[i].count, list->buffer[i].address);
 	}
 
-} /* TLan_PrintList */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_ReadAndClearStats
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	Pointer to device structure of adapter
-	 *			to which to read stats.
-	 *		record	Flag indicating whether to add
-	 *
-	 *	This functions reads all the internal status registers
-	 *	of the TLAN chip, which clears them as a side effect.
-	 *	It then either adds the values to the device's status
-	 *	struct, or discards them, depending on whether record
-	 *	is TLAN_RECORD (!=0)  or TLAN_IGNORE (==0).
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_read_and_clear_stats
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	Pointer to device structure of adapter
+ *			to which to read stats.
+ *		record	Flag indicating whether to add
+ *
+ *	This functions reads all the internal status registers
+ *	of the TLAN chip, which clears them as a side effect.
+ *	It then either adds the values to the device's status
+ *	struct, or discards them, depending on whether record
+ *	is TLAN_RECORD (!=0)  or TLAN_IGNORE (==0).
+ *
+ **************************************************************/
 
-static void TLan_ReadAndClearStats( struct net_device *dev, int record )
+static void tlan_read_and_clear_stats(struct net_device *dev, int record)
 {
 	u32		tx_good, tx_under;
 	u32		rx_good, rx_over;
@@ -2129,41 +2072,42 @@
 	u32		multi_col, single_col;
 	u32		excess_col, late_col, loss;
 
-	outw( TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	tx_good  = inb( dev->base_addr + TLAN_DIO_DATA );
-	tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	tx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
-	tx_under = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
+	outw(TLAN_GOOD_TX_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	tx_good  = inb(dev->base_addr + TLAN_DIO_DATA);
+	tx_good += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	tx_good += inb(dev->base_addr + TLAN_DIO_DATA + 2) << 16;
+	tx_under = inb(dev->base_addr + TLAN_DIO_DATA + 3);
 
-	outw( TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	rx_good  = inb( dev->base_addr + TLAN_DIO_DATA );
-	rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	rx_good += inb( dev->base_addr + TLAN_DIO_DATA + 2 ) << 16;
-	rx_over  = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
+	outw(TLAN_GOOD_RX_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	rx_good  = inb(dev->base_addr + TLAN_DIO_DATA);
+	rx_good += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	rx_good += inb(dev->base_addr + TLAN_DIO_DATA + 2) << 16;
+	rx_over  = inb(dev->base_addr + TLAN_DIO_DATA + 3);
 
-	outw( TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR );
-	def_tx  = inb( dev->base_addr + TLAN_DIO_DATA );
-	def_tx += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	crc     = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
-	code    = inb( dev->base_addr + TLAN_DIO_DATA + 3 );
+	outw(TLAN_DEFERRED_TX, dev->base_addr + TLAN_DIO_ADR);
+	def_tx  = inb(dev->base_addr + TLAN_DIO_DATA);
+	def_tx += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	crc     = inb(dev->base_addr + TLAN_DIO_DATA + 2);
+	code    = inb(dev->base_addr + TLAN_DIO_DATA + 3);
 
-	outw( TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	multi_col   = inb( dev->base_addr + TLAN_DIO_DATA );
-	multi_col  += inb( dev->base_addr + TLAN_DIO_DATA + 1 ) << 8;
-	single_col  = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
-	single_col += inb( dev->base_addr + TLAN_DIO_DATA + 3 ) << 8;
+	outw(TLAN_MULTICOL_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	multi_col   = inb(dev->base_addr + TLAN_DIO_DATA);
+	multi_col  += inb(dev->base_addr + TLAN_DIO_DATA + 1) << 8;
+	single_col  = inb(dev->base_addr + TLAN_DIO_DATA + 2);
+	single_col += inb(dev->base_addr + TLAN_DIO_DATA + 3) << 8;
 
-	outw( TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR );
-	excess_col = inb( dev->base_addr + TLAN_DIO_DATA );
-	late_col   = inb( dev->base_addr + TLAN_DIO_DATA + 1 );
-	loss       = inb( dev->base_addr + TLAN_DIO_DATA + 2 );
+	outw(TLAN_EXCESSCOL_FRMS, dev->base_addr + TLAN_DIO_ADR);
+	excess_col = inb(dev->base_addr + TLAN_DIO_DATA);
+	late_col   = inb(dev->base_addr + TLAN_DIO_DATA + 1);
+	loss       = inb(dev->base_addr + TLAN_DIO_DATA + 2);
 
-	if ( record ) {
+	if (record) {
 		dev->stats.rx_packets += rx_good;
 		dev->stats.rx_errors  += rx_over + crc + code;
 		dev->stats.tx_packets += tx_good;
 		dev->stats.tx_errors  += tx_under + loss;
-		dev->stats.collisions += multi_col + single_col + excess_col + late_col;
+		dev->stats.collisions += multi_col
+			+ single_col + excess_col + late_col;
 
 		dev->stats.rx_over_errors    += rx_over;
 		dev->stats.rx_crc_errors     += crc;
@@ -2173,39 +2117,39 @@
 		dev->stats.tx_carrier_errors += loss;
 	}
 
-} /* TLan_ReadAndClearStats */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_Reset
-	 *
-	 *	Returns:
-	 *		0
-	 *	Parms:
-	 *		dev	Pointer to device structure of adapter
-	 *			to be reset.
-	 *
-	 *	This function resets the adapter and it's physical
-	 *	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN
-	 *	Programmer's Guide" for details.  The routine tries to
-	 *	implement what is detailed there, though adjustments
-	 *	have been made.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_Reset
+ *
+ *	Returns:
+ *		0
+ *	Parms:
+ *		dev	Pointer to device structure of adapter
+ *			to be reset.
+ *
+ *	This function resets the adapter and it's physical
+ *	device.  See Chap. 3, pp. 9-10 of the "ThunderLAN
+ *	Programmer's Guide" for details.  The routine tries to
+ *	implement what is detailed there, though adjustments
+ *	have been made.
+ *
+ **************************************************************/
 
 static void
-TLan_ResetAdapter( struct net_device *dev )
+tlan_reset_adapter(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	int		i;
 	u32		addr;
 	u32		data;
 	u8		data8;
 
-	priv->tlanFullDuplex = false;
-	priv->phyOnline=0;
+	priv->tlan_full_duplex = false;
+	priv->phy_online = 0;
 	netif_carrier_off(dev);
 
 /*  1.	Assert reset bit. */
@@ -2216,7 +2160,7 @@
 
 	udelay(1000);
 
-/*  2.	Turn off interrupts. ( Probably isn't necessary ) */
+/*  2.	Turn off interrupts. (Probably isn't necessary) */
 
 	data = inl(dev->base_addr + TLAN_HOST_CMD);
 	data |= TLAN_HC_INT_OFF;
@@ -2224,207 +2168,204 @@
 
 /*  3.	Clear AREGs and HASHs. */
 
- 	for ( i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4 ) {
-		TLan_DioWrite32( dev->base_addr, (u16) i, 0 );
-	}
+	for (i = TLAN_AREG_0; i <= TLAN_HASH_2; i += 4)
+		tlan_dio_write32(dev->base_addr, (u16) i, 0);
 
 /*  4.	Setup NetConfig register. */
 
 	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
-	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
+	tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
 
 /*  5.	Load Ld_Tmr and Ld_Thr in HOST_CMD. */
 
- 	outl( TLAN_HC_LD_TMR | 0x3f, dev->base_addr + TLAN_HOST_CMD );
- 	outl( TLAN_HC_LD_THR | 0x9, dev->base_addr + TLAN_HOST_CMD );
+	outl(TLAN_HC_LD_TMR | 0x3f, dev->base_addr + TLAN_HOST_CMD);
+	outl(TLAN_HC_LD_THR | 0x9, dev->base_addr + TLAN_HOST_CMD);
 
 /*  6.	Unreset the MII by setting NMRST (in NetSio) to 1. */
 
-	outw( TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
 	addr = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
-	TLan_SetBit( TLAN_NET_SIO_NMRST, addr );
+	tlan_set_bit(TLAN_NET_SIO_NMRST, addr);
 
 /*  7.	Setup the remaining registers. */
 
-	if ( priv->tlanRev >= 0x30 ) {
+	if (priv->tlan_rev >= 0x30) {
 		data8 = TLAN_ID_TX_EOC | TLAN_ID_RX_EOC;
-		TLan_DioWrite8( dev->base_addr, TLAN_INT_DIS, data8 );
+		tlan_dio_write8(dev->base_addr, TLAN_INT_DIS, data8);
 	}
-	TLan_PhyDetect( dev );
+	tlan_phy_detect(dev);
 	data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN;
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY ) {
+	if (priv->adapter->flags & TLAN_ADAPTER_BIT_RATE_PHY) {
 		data |= TLAN_NET_CFG_BIT;
-		if ( priv->aui == 1 ) {
-			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x0a );
-		} else if ( priv->duplex == TLAN_DUPLEX_FULL ) {
-			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x00 );
-			priv->tlanFullDuplex = true;
+		if (priv->aui == 1) {
+			tlan_dio_write8(dev->base_addr, TLAN_ACOMMIT, 0x0a);
+		} else if (priv->duplex == TLAN_DUPLEX_FULL) {
+			tlan_dio_write8(dev->base_addr, TLAN_ACOMMIT, 0x00);
+			priv->tlan_full_duplex = true;
 		} else {
-			TLan_DioWrite8( dev->base_addr, TLAN_ACOMMIT, 0x08 );
+			tlan_dio_write8(dev->base_addr, TLAN_ACOMMIT, 0x08);
 		}
 	}
 
-	if ( priv->phyNum == 0 ) {
+	if (priv->phy_num == 0)
 		data |= TLAN_NET_CFG_PHY_EN;
-	}
-	TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, (u16) data );
+	tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, (u16) data);
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
-		TLan_FinishReset( dev );
-	} else {
-		TLan_PhyPowerDown( dev );
-	}
+	if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY)
+		tlan_finish_reset(dev);
+	else
+		tlan_phy_power_down(dev);
 
-} /* TLan_ResetAdapter */
+}
 
 
 
 
 static void
-TLan_FinishReset( struct net_device *dev )
+tlan_finish_reset(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u8		data;
 	u32		phy;
 	u8		sio;
 	u16		status;
 	u16		partner;
 	u16		tlphy_ctl;
-	u16 		tlphy_par;
+	u16		tlphy_par;
 	u16		tlphy_id1, tlphy_id2;
-	int 		i;
+	int		i;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
 	data = TLAN_NET_CMD_NRESET | TLAN_NET_CMD_NWRAP;
-	if ( priv->tlanFullDuplex ) {
+	if (priv->tlan_full_duplex)
 		data |= TLAN_NET_CMD_DUPLEX;
-	}
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_CMD, data );
+	tlan_dio_write8(dev->base_addr, TLAN_NET_CMD, data);
 	data = TLAN_NET_MASK_MASK4 | TLAN_NET_MASK_MASK5;
-	if ( priv->phyNum == 0 ) {
+	if (priv->phy_num == 0)
 		data |= TLAN_NET_MASK_MASK7;
-	}
-	TLan_DioWrite8( dev->base_addr, TLAN_NET_MASK, data );
-	TLan_DioWrite16( dev->base_addr, TLAN_MAX_RX, ((1536)+7)&~7 );
-	TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &tlphy_id1 );
-	TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &tlphy_id2 );
+	tlan_dio_write8(dev->base_addr, TLAN_NET_MASK, data);
+	tlan_dio_write16(dev->base_addr, TLAN_MAX_RX, ((1536)+7)&~7);
+	tlan_mii_read_reg(dev, phy, MII_GEN_ID_HI, &tlphy_id1);
+	tlan_mii_read_reg(dev, phy, MII_GEN_ID_LO, &tlphy_id2);
 
-	if ( ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) ||
-	     ( priv->aui ) ) {
+	if ((priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY) ||
+	    (priv->aui)) {
 		status = MII_GS_LINK;
-		printk( "TLAN:  %s: Link forced.\n", dev->name );
+		netdev_info(dev, "Link forced\n");
 	} else {
-		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-		udelay( 1000 );
-		TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-		if ( (status & MII_GS_LINK) &&
-		     /* We only support link info on Nat.Sem. PHY's */
-			(tlphy_id1 == NAT_SEM_ID1) &&
-			(tlphy_id2 == NAT_SEM_ID2) ) {
-			TLan_MiiReadReg( dev, phy, MII_AN_LPA, &partner );
-			TLan_MiiReadReg( dev, phy, TLAN_TLPHY_PAR, &tlphy_par );
+		tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+		udelay(1000);
+		tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+		if ((status & MII_GS_LINK) &&
+		    /* We only support link info on Nat.Sem. PHY's */
+		    (tlphy_id1 == NAT_SEM_ID1) &&
+		    (tlphy_id2 == NAT_SEM_ID2)) {
+			tlan_mii_read_reg(dev, phy, MII_AN_LPA, &partner);
+			tlan_mii_read_reg(dev, phy, TLAN_TLPHY_PAR, &tlphy_par);
 
-			printk( "TLAN: %s: Link active with ", dev->name );
-			if (!(tlphy_par & TLAN_PHY_AN_EN_STAT)) {
-			      	 printk( "forced 10%sMbps %s-Duplex\n",
-					 tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
-					 tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
-			} else {
-				printk( "AutoNegotiation enabled, at 10%sMbps %s-Duplex\n",
-					tlphy_par & TLAN_PHY_SPEED_100 ? "" : "0",
-					tlphy_par & TLAN_PHY_DUPLEX_FULL ? "Full" : "Half");
-				printk("TLAN: Partner capability: ");
-					for (i = 5; i <= 10; i++)
-						if (partner & (1<<i))
-							printk("%s",media[i-5]);
-				printk("\n");
+			netdev_info(dev,
+				    "Link active with %s %uMbps %s-Duplex\n",
+				    !(tlphy_par & TLAN_PHY_AN_EN_STAT)
+				    ? "forced" : "Autonegotiation enabled,",
+				    tlphy_par & TLAN_PHY_SPEED_100
+				    ? 100 : 10,
+				    tlphy_par & TLAN_PHY_DUPLEX_FULL
+				    ? "Full" : "Half");
+
+			if (tlphy_par & TLAN_PHY_AN_EN_STAT) {
+				netdev_info(dev, "Partner capability:");
+				for (i = 5; i < 10; i++)
+					if (partner & (1 << i))
+						pr_cont(" %s", media[i-5]);
+				pr_cont("\n");
 			}
 
-			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
+			tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
+					TLAN_LED_LINK);
 #ifdef MONITOR
 			/* We have link beat..for now anyway */
-	        	priv->link = 1;
-	        	/*Enabling link beat monitoring */
-			TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_LINK_BEAT );
+			priv->link = 1;
+			/*Enabling link beat monitoring */
+			tlan_set_timer(dev, (10*HZ), TLAN_TIMER_LINK_BEAT);
 #endif
 		} else if (status & MII_GS_LINK)  {
-			printk( "TLAN: %s: Link active\n", dev->name );
-			TLan_DioWrite8( dev->base_addr, TLAN_LED_REG, TLAN_LED_LINK );
+			netdev_info(dev, "Link active\n");
+			tlan_dio_write8(dev->base_addr, TLAN_LED_REG,
+					TLAN_LED_LINK);
 		}
 	}
 
-	if ( priv->phyNum == 0 ) {
-        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl );
-        	tlphy_ctl |= TLAN_TC_INTEN;
-        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tlphy_ctl );
-        	sio = TLan_DioRead8( dev->base_addr, TLAN_NET_SIO );
-        	sio |= TLAN_NET_SIO_MINTEN;
-        	TLan_DioWrite8( dev->base_addr, TLAN_NET_SIO, sio );
+	if (priv->phy_num == 0) {
+		tlan_mii_read_reg(dev, phy, TLAN_TLPHY_CTL, &tlphy_ctl);
+		tlphy_ctl |= TLAN_TC_INTEN;
+		tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL, tlphy_ctl);
+		sio = tlan_dio_read8(dev->base_addr, TLAN_NET_SIO);
+		sio |= TLAN_NET_SIO_MINTEN;
+		tlan_dio_write8(dev->base_addr, TLAN_NET_SIO, sio);
 	}
 
-	if ( status & MII_GS_LINK ) {
-		TLan_SetMac( dev, 0, dev->dev_addr );
-		priv->phyOnline = 1;
-		outb( ( TLAN_HC_INT_ON >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
-		if ( debug >= 1 && debug != TLAN_DEBUG_PROBE ) {
-			outb( ( TLAN_HC_REQ_INT >> 8 ), dev->base_addr + TLAN_HOST_CMD + 1 );
-		}
-		outl( priv->rxListDMA, dev->base_addr + TLAN_CH_PARM );
-		outl( TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD );
+	if (status & MII_GS_LINK) {
+		tlan_set_mac(dev, 0, dev->dev_addr);
+		priv->phy_online = 1;
+		outb((TLAN_HC_INT_ON >> 8), dev->base_addr + TLAN_HOST_CMD + 1);
+		if (debug >= 1 && debug != TLAN_DEBUG_PROBE)
+			outb((TLAN_HC_REQ_INT >> 8),
+			     dev->base_addr + TLAN_HOST_CMD + 1);
+		outl(priv->rx_list_dma, dev->base_addr + TLAN_CH_PARM);
+		outl(TLAN_HC_GO | TLAN_HC_RT, dev->base_addr + TLAN_HOST_CMD);
 		netif_carrier_on(dev);
 	} else {
-		printk( "TLAN: %s: Link inactive, will retry in 10 secs...\n",
-			dev->name );
-		TLan_SetTimer( dev, (10*HZ), TLAN_TIMER_FINISH_RESET );
+		netdev_info(dev, "Link inactive, will retry in 10 secs...\n");
+		tlan_set_timer(dev, (10*HZ), TLAN_TIMER_FINISH_RESET);
 		return;
 	}
-	TLan_SetMulticastList(dev);
+	tlan_set_multicast_list(dev);
 
-} /* TLan_FinishReset */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_SetMac
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	Pointer to device structure of adapter
-	 *			on which to change the AREG.
-	 *		areg	The AREG to set the address in (0 - 3).
-	 *		mac	A pointer to an array of chars.  Each
-	 *			element stores one byte of the address.
-	 *			IE, it isn't in ascii.
-	 *
-	 *	This function transfers a MAC address to one of the
-	 *	TLAN AREGs (address registers).  The TLAN chip locks
-	 *	the register on writing to offset 0 and unlocks the
-	 *	register after writing to offset 5.  If NULL is passed
-	 *	in mac, then the AREG is filled with 0's.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_set_mac
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	Pointer to device structure of adapter
+ *			on which to change the AREG.
+ *		areg	The AREG to set the address in (0 - 3).
+ *		mac	A pointer to an array of chars.  Each
+ *			element stores one byte of the address.
+ *			IE, it isn't in ascii.
+ *
+ *	This function transfers a MAC address to one of the
+ *	TLAN AREGs (address registers).  The TLAN chip locks
+ *	the register on writing to offset 0 and unlocks the
+ *	register after writing to offset 5.  If NULL is passed
+ *	in mac, then the AREG is filled with 0's.
+ *
+ **************************************************************/
 
-static void TLan_SetMac( struct net_device *dev, int areg, char *mac )
+static void tlan_set_mac(struct net_device *dev, int areg, char *mac)
 {
 	int i;
 
 	areg *= 6;
 
-	if ( mac != NULL ) {
-		for ( i = 0; i < 6; i++ )
-			TLan_DioWrite8( dev->base_addr,
-					TLAN_AREG_0 + areg + i, mac[i] );
+	if (mac != NULL) {
+		for (i = 0; i < 6; i++)
+			tlan_dio_write8(dev->base_addr,
+					TLAN_AREG_0 + areg + i, mac[i]);
 	} else {
-		for ( i = 0; i < 6; i++ )
-			TLan_DioWrite8( dev->base_addr,
-					TLAN_AREG_0 + areg + i, 0 );
+		for (i = 0; i < 6; i++)
+			tlan_dio_write8(dev->base_addr,
+					TLAN_AREG_0 + areg + i, 0);
 	}
 
-} /* TLan_SetMac */
+}
 
 
 
@@ -2432,205 +2373,199 @@
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver PHY Layer Routines
+ThunderLAN driver PHY layer routines
 
 ******************************************************************************
 *****************************************************************************/
 
 
 
-	/*********************************************************************
-	 *	TLan_PhyPrint
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to the device structure of the
-	 *			TLAN device having the PHYs to be detailed.
-	 *
-	 *	This function prints the registers a PHY (aka transceiver).
-	 *
-	 ********************************************************************/
+/*********************************************************************
+ *	tlan_phy_print
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	A pointer to the device structure of the
+ *			TLAN device having the PHYs to be detailed.
+ *
+ *	This function prints the registers a PHY (aka transceiver).
+ *
+ ********************************************************************/
 
-static void TLan_PhyPrint( struct net_device *dev )
+static void tlan_phy_print(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16 i, data0, data1, data2, data3, phy;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
-		printk( "TLAN:   Device %s, Unmanaged PHY.\n", dev->name );
-	} else if ( phy <= TLAN_PHY_MAX_ADDR ) {
-		printk( "TLAN:   Device %s, PHY 0x%02x.\n", dev->name, phy );
-		printk( "TLAN:      Off.  +0     +1     +2     +3\n" );
-                for ( i = 0; i < 0x20; i+= 4 ) {
-			printk( "TLAN:      0x%02x", i );
-			TLan_MiiReadReg( dev, phy, i, &data0 );
-			printk( " 0x%04hx", data0 );
-			TLan_MiiReadReg( dev, phy, i + 1, &data1 );
-			printk( " 0x%04hx", data1 );
-			TLan_MiiReadReg( dev, phy, i + 2, &data2 );
-			printk( " 0x%04hx", data2 );
-			TLan_MiiReadReg( dev, phy, i + 3, &data3 );
-			printk( " 0x%04hx\n", data3 );
+	if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+		netdev_info(dev, "Unmanaged PHY\n");
+	} else if (phy <= TLAN_PHY_MAX_ADDR) {
+		netdev_info(dev, "PHY 0x%02x\n", phy);
+		pr_info("   Off.  +0     +1     +2     +3\n");
+		for (i = 0; i < 0x20; i += 4) {
+			tlan_mii_read_reg(dev, phy, i, &data0);
+			tlan_mii_read_reg(dev, phy, i + 1, &data1);
+			tlan_mii_read_reg(dev, phy, i + 2, &data2);
+			tlan_mii_read_reg(dev, phy, i + 3, &data3);
+			pr_info("   0x%02x 0x%04hx 0x%04hx 0x%04hx 0x%04hx\n",
+				i, data0, data1, data2, data3);
 		}
 	} else {
-		printk( "TLAN:   Device %s, Invalid PHY.\n", dev->name );
+		netdev_info(dev, "Invalid PHY\n");
 	}
 
-} /* TLan_PhyPrint */
+}
 
 
 
 
-	/*********************************************************************
-	 *	TLan_PhyDetect
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev	A pointer to the device structure of the adapter
-	 *			for which the PHY needs determined.
-	 *
-	 *	So far I've found that adapters which have external PHYs
-	 *	may also use the internal PHY for part of the functionality.
-	 *	(eg, AUI/Thinnet).  This function finds out if this TLAN
-	 *	chip has an internal PHY, and then finds the first external
-	 *	PHY (starting from address 0) if it exists).
-	 *
-	 ********************************************************************/
+/*********************************************************************
+ *	tlan_phy_detect
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev	A pointer to the device structure of the adapter
+ *			for which the PHY needs determined.
+ *
+ *	So far I've found that adapters which have external PHYs
+ *	may also use the internal PHY for part of the functionality.
+ *	(eg, AUI/Thinnet).  This function finds out if this TLAN
+ *	chip has an internal PHY, and then finds the first external
+ *	PHY (starting from address 0) if it exists).
+ *
+ ********************************************************************/
 
-static void TLan_PhyDetect( struct net_device *dev )
+static void tlan_phy_detect(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16		control;
 	u16		hi;
 	u16		lo;
 	u32		phy;
 
-	if ( priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY ) {
-		priv->phyNum = 0xFFFF;
+	if (priv->adapter->flags & TLAN_ADAPTER_UNMANAGED_PHY) {
+		priv->phy_num = 0xffff;
 		return;
 	}
 
-	TLan_MiiReadReg( dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi );
+	tlan_mii_read_reg(dev, TLAN_PHY_MAX_ADDR, MII_GEN_ID_HI, &hi);
 
-	if ( hi != 0xFFFF ) {
+	if (hi != 0xffff)
 		priv->phy[0] = TLAN_PHY_MAX_ADDR;
-	} else {
+	else
 		priv->phy[0] = TLAN_PHY_NONE;
-	}
 
 	priv->phy[1] = TLAN_PHY_NONE;
-	for ( phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++ ) {
-		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &control );
-		TLan_MiiReadReg( dev, phy, MII_GEN_ID_HI, &hi );
-		TLan_MiiReadReg( dev, phy, MII_GEN_ID_LO, &lo );
-		if ( ( control != 0xFFFF ) ||
-		     ( hi != 0xFFFF ) || ( lo != 0xFFFF ) ) {
-			TLAN_DBG( TLAN_DEBUG_GNRL,
-				  "PHY found at %02x %04x %04x %04x\n",
-				  phy, control, hi, lo );
-			if ( ( priv->phy[1] == TLAN_PHY_NONE ) &&
-			     ( phy != TLAN_PHY_MAX_ADDR ) ) {
+	for (phy = 0; phy <= TLAN_PHY_MAX_ADDR; phy++) {
+		tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &control);
+		tlan_mii_read_reg(dev, phy, MII_GEN_ID_HI, &hi);
+		tlan_mii_read_reg(dev, phy, MII_GEN_ID_LO, &lo);
+		if ((control != 0xffff) ||
+		    (hi != 0xffff) || (lo != 0xffff)) {
+			TLAN_DBG(TLAN_DEBUG_GNRL,
+				 "PHY found at %02x %04x %04x %04x\n",
+				 phy, control, hi, lo);
+			if ((priv->phy[1] == TLAN_PHY_NONE) &&
+			    (phy != TLAN_PHY_MAX_ADDR)) {
 				priv->phy[1] = phy;
 			}
 		}
 	}
 
-	if ( priv->phy[1] != TLAN_PHY_NONE ) {
-		priv->phyNum = 1;
-	} else if ( priv->phy[0] != TLAN_PHY_NONE ) {
-		priv->phyNum = 0;
-	} else {
-		printk( "TLAN:  Cannot initialize device, no PHY was found!\n" );
-	}
+	if (priv->phy[1] != TLAN_PHY_NONE)
+		priv->phy_num = 1;
+	else if (priv->phy[0] != TLAN_PHY_NONE)
+		priv->phy_num = 0;
+	else
+		netdev_info(dev, "Cannot initialize device, no PHY was found!\n");
 
-} /* TLan_PhyDetect */
+}
 
 
 
 
-static void TLan_PhyPowerDown( struct net_device *dev )
+static void tlan_phy_power_down(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		value;
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Powering down PHY(s).\n", dev->name);
 	value = MII_GC_PDOWN | MII_GC_LOOPBK | MII_GC_ISOLATE;
-	TLan_MiiSync( dev->base_addr );
-	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
-	if ( ( priv->phyNum == 0 ) &&
-	     ( priv->phy[1] != TLAN_PHY_NONE ) &&
-	     ( ! ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) ) ) {
-		TLan_MiiSync( dev->base_addr );
-		TLan_MiiWriteReg( dev, priv->phy[1], MII_GEN_CTL, value );
+	tlan_mii_sync(dev->base_addr);
+	tlan_mii_write_reg(dev, priv->phy[priv->phy_num], MII_GEN_CTL, value);
+	if ((priv->phy_num == 0) &&
+	    (priv->phy[1] != TLAN_PHY_NONE) &&
+	    (!(priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10))) {
+		tlan_mii_sync(dev->base_addr);
+		tlan_mii_write_reg(dev, priv->phy[1], MII_GEN_CTL, value);
 	}
 
 	/* Wait for 50 ms and powerup
 	 * This is abitrary.  It is intended to make sure the
 	 * transceiver settles.
 	 */
-	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_PUP );
+	tlan_set_timer(dev, (HZ/20), TLAN_TIMER_PHY_PUP);
 
-} /* TLan_PhyPowerDown */
+}
 
 
 
 
-static void TLan_PhyPowerUp( struct net_device *dev )
+static void tlan_phy_power_up(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		value;
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name );
-	TLan_MiiSync( dev->base_addr );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Powering up PHY.\n", dev->name);
+	tlan_mii_sync(dev->base_addr);
 	value = MII_GC_LOOPBK;
-	TLan_MiiWriteReg( dev, priv->phy[priv->phyNum], MII_GEN_CTL, value );
-	TLan_MiiSync(dev->base_addr);
+	tlan_mii_write_reg(dev, priv->phy[priv->phy_num], MII_GEN_CTL, value);
+	tlan_mii_sync(dev->base_addr);
 	/* Wait for 500 ms and reset the
 	 * transceiver.  The TLAN docs say both 50 ms and
 	 * 500 ms, so do the longer, just in case.
 	 */
-	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_RESET );
+	tlan_set_timer(dev, (HZ/20), TLAN_TIMER_PHY_RESET);
 
-} /* TLan_PhyPowerUp */
+}
 
 
 
 
-static void TLan_PhyReset( struct net_device *dev )
+static void tlan_phy_reset(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		phy;
 	u16		value;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name );
-	TLan_MiiSync( dev->base_addr );
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Reseting PHY.\n", dev->name);
+	tlan_mii_sync(dev->base_addr);
 	value = MII_GC_LOOPBK | MII_GC_RESET;
-	TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, value );
-	TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
-	while ( value & MII_GC_RESET ) {
-		TLan_MiiReadReg( dev, phy, MII_GEN_CTL, &value );
-	}
+	tlan_mii_write_reg(dev, phy, MII_GEN_CTL, value);
+	tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
+	while (value & MII_GC_RESET)
+		tlan_mii_read_reg(dev, phy, MII_GEN_CTL, &value);
 
 	/* Wait for 500 ms and initialize.
 	 * I don't remember why I wait this long.
 	 * I've changed this to 50ms, as it seems long enough.
 	 */
-	TLan_SetTimer( dev, (HZ/20), TLAN_TIMER_PHY_START_LINK );
+	tlan_set_timer(dev, (HZ/20), TLAN_TIMER_PHY_START_LINK);
 
-} /* TLan_PhyReset */
+}
 
 
 
 
-static void TLan_PhyStartLink( struct net_device *dev )
+static void tlan_phy_start_link(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		ability;
 	u16		control;
 	u16		data;
@@ -2638,86 +2573,87 @@
 	u16		status;
 	u16		tctl;
 
-	phy = priv->phy[priv->phyNum];
-	TLAN_DBG( TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name );
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &ability );
+	phy = priv->phy[priv->phy_num];
+	TLAN_DBG(TLAN_DEBUG_GNRL, "%s: Trying to activate link.\n", dev->name);
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &ability);
 
-	if ( ( status & MII_GS_AUTONEG ) &&
-	     ( ! priv->aui ) ) {
+	if ((status & MII_GS_AUTONEG) &&
+	    (!priv->aui)) {
 		ability = status >> 11;
-		if ( priv->speed  == TLAN_SPEED_10 &&
-		     priv->duplex == TLAN_DUPLEX_HALF) {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0000);
-		} else if ( priv->speed == TLAN_SPEED_10 &&
-			    priv->duplex == TLAN_DUPLEX_FULL) {
-			priv->tlanFullDuplex = true;
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x0100);
-		} else if ( priv->speed == TLAN_SPEED_100 &&
-			    priv->duplex == TLAN_DUPLEX_HALF) {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2000);
-		} else if ( priv->speed == TLAN_SPEED_100 &&
-			    priv->duplex == TLAN_DUPLEX_FULL) {
-			priv->tlanFullDuplex = true;
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x2100);
+		if (priv->speed  == TLAN_SPEED_10 &&
+		    priv->duplex == TLAN_DUPLEX_HALF) {
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x0000);
+		} else if (priv->speed == TLAN_SPEED_10 &&
+			   priv->duplex == TLAN_DUPLEX_FULL) {
+			priv->tlan_full_duplex = true;
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x0100);
+		} else if (priv->speed == TLAN_SPEED_100 &&
+			   priv->duplex == TLAN_DUPLEX_HALF) {
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x2000);
+		} else if (priv->speed == TLAN_SPEED_100 &&
+			   priv->duplex == TLAN_DUPLEX_FULL) {
+			priv->tlan_full_duplex = true;
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x2100);
 		} else {
 
 			/* Set Auto-Neg advertisement */
-			TLan_MiiWriteReg( dev, phy, MII_AN_ADV, (ability << 5) | 1);
+			tlan_mii_write_reg(dev, phy, MII_AN_ADV,
+					   (ability << 5) | 1);
 			/* Enablee Auto-Neg */
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1000 );
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x1000);
 			/* Restart Auto-Neg */
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, 0x1200 );
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL, 0x1200);
 			/* Wait for 4 sec for autonegotiation
-		 	* to complete.  The max spec time is less than this
-		 	* but the card need additional time to start AN.
-		 	* .5 sec should be plenty extra.
-		 	*/
-			printk( "TLAN: %s: Starting autonegotiation.\n", dev->name );
-			TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN );
+			 * to complete.  The max spec time is less than this
+			 * but the card need additional time to start AN.
+			 * .5 sec should be plenty extra.
+			 */
+			netdev_info(dev, "Starting autonegotiation\n");
+			tlan_set_timer(dev, (2*HZ), TLAN_TIMER_PHY_FINISH_AN);
 			return;
 		}
 
 	}
 
-	if ( ( priv->aui ) && ( priv->phyNum != 0 ) ) {
-		priv->phyNum = 0;
-		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
-		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN );
+	if ((priv->aui) && (priv->phy_num != 0)) {
+		priv->phy_num = 0;
+		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN
+			| TLAN_NET_CFG_PHY_EN;
+		tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, data);
+		tlan_set_timer(dev, (40*HZ/1000), TLAN_TIMER_PHY_PDOWN);
 		return;
-	}  else if ( priv->phyNum == 0 ) {
+	} else if (priv->phy_num == 0) {
 		control = 0;
-        	TLan_MiiReadReg( dev, phy, TLAN_TLPHY_CTL, &tctl );
-		if ( priv->aui ) {
-                	tctl |= TLAN_TC_AUISEL;
+		tlan_mii_read_reg(dev, phy, TLAN_TLPHY_CTL, &tctl);
+		if (priv->aui) {
+			tctl |= TLAN_TC_AUISEL;
 		} else {
-                	tctl &= ~TLAN_TC_AUISEL;
-			if ( priv->duplex == TLAN_DUPLEX_FULL ) {
+			tctl &= ~TLAN_TC_AUISEL;
+			if (priv->duplex == TLAN_DUPLEX_FULL) {
 				control |= MII_GC_DUPLEX;
-				priv->tlanFullDuplex = true;
+				priv->tlan_full_duplex = true;
 			}
-			if ( priv->speed == TLAN_SPEED_100 ) {
+			if (priv->speed == TLAN_SPEED_100)
 				control |= MII_GC_SPEEDSEL;
-			}
 		}
-		TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, control );
-        	TLan_MiiWriteReg( dev, phy, TLAN_TLPHY_CTL, tctl );
+		tlan_mii_write_reg(dev, phy, MII_GEN_CTL, control);
+		tlan_mii_write_reg(dev, phy, TLAN_TLPHY_CTL, tctl);
 	}
 
 	/* Wait for 2 sec to give the transceiver time
 	 * to establish link.
 	 */
-	TLan_SetTimer( dev, (4*HZ), TLAN_TIMER_FINISH_RESET );
+	tlan_set_timer(dev, (4*HZ), TLAN_TIMER_FINISH_RESET);
 
-} /* TLan_PhyStartLink */
+}
 
 
 
 
-static void TLan_PhyFinishAutoNeg( struct net_device *dev )
+static void tlan_phy_finish_auto_neg(struct net_device *dev)
 {
-	TLanPrivateInfo	*priv = netdev_priv(dev);
+	struct tlan_priv	*priv = netdev_priv(dev);
 	u16		an_adv;
 	u16		an_lpa;
 	u16		data;
@@ -2725,115 +2661,118 @@
 	u16		phy;
 	u16		status;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
-	udelay( 1000 );
-	TLan_MiiReadReg( dev, phy, MII_GEN_STS, &status );
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
+	udelay(1000);
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &status);
 
-	if ( ! ( status & MII_GS_AUTOCMPLT ) ) {
+	if (!(status & MII_GS_AUTOCMPLT)) {
 		/* Wait for 8 sec to give the process
 		 * more time.  Perhaps we should fail after a while.
 		 */
-		 if (!priv->neg_be_verbose++) {
-			 pr_info("TLAN:  Giving autonegotiation more time.\n");
-		 	 pr_info("TLAN:  Please check that your adapter has\n");
-		 	 pr_info("TLAN:  been properly connected to a HUB or Switch.\n");
-			 pr_info("TLAN:  Trying to establish link in the background...\n");
-		 }
-		TLan_SetTimer( dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN );
+		if (!priv->neg_be_verbose++) {
+			pr_info("Giving autonegotiation more time.\n");
+			pr_info("Please check that your adapter has\n");
+			pr_info("been properly connected to a HUB or Switch.\n");
+			pr_info("Trying to establish link in the background...\n");
+		}
+		tlan_set_timer(dev, (8*HZ), TLAN_TIMER_PHY_FINISH_AN);
 		return;
 	}
 
-	printk( "TLAN: %s: Autonegotiation complete.\n", dev->name );
-	TLan_MiiReadReg( dev, phy, MII_AN_ADV, &an_adv );
-	TLan_MiiReadReg( dev, phy, MII_AN_LPA, &an_lpa );
+	netdev_info(dev, "Autonegotiation complete\n");
+	tlan_mii_read_reg(dev, phy, MII_AN_ADV, &an_adv);
+	tlan_mii_read_reg(dev, phy, MII_AN_LPA, &an_lpa);
 	mode = an_adv & an_lpa & 0x03E0;
-	if ( mode & 0x0100 ) {
-		priv->tlanFullDuplex = true;
-	} else if ( ! ( mode & 0x0080 ) && ( mode & 0x0040 ) ) {
-		priv->tlanFullDuplex = true;
-	}
+	if (mode & 0x0100)
+		priv->tlan_full_duplex = true;
+	else if (!(mode & 0x0080) && (mode & 0x0040))
+		priv->tlan_full_duplex = true;
 
-	if ( ( ! ( mode & 0x0180 ) ) &&
-	     ( priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10 ) &&
-	     ( priv->phyNum != 0 ) ) {
-		priv->phyNum = 0;
-		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN | TLAN_NET_CFG_PHY_EN;
-		TLan_DioWrite16( dev->base_addr, TLAN_NET_CONFIG, data );
-		TLan_SetTimer( dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN );
+	if ((!(mode & 0x0180)) &&
+	    (priv->adapter->flags & TLAN_ADAPTER_USE_INTERN_10) &&
+	    (priv->phy_num != 0)) {
+		priv->phy_num = 0;
+		data = TLAN_NET_CFG_1FRAG | TLAN_NET_CFG_1CHAN
+			| TLAN_NET_CFG_PHY_EN;
+		tlan_dio_write16(dev->base_addr, TLAN_NET_CONFIG, data);
+		tlan_set_timer(dev, (400*HZ/1000), TLAN_TIMER_PHY_PDOWN);
 		return;
 	}
 
-	if ( priv->phyNum == 0 ) {
-		if ( ( priv->duplex == TLAN_DUPLEX_FULL ) ||
-		     ( an_adv & an_lpa & 0x0040 ) ) {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL,
-					  MII_GC_AUTOENB | MII_GC_DUPLEX );
-			pr_info("TLAN:  Starting internal PHY with FULL-DUPLEX\n" );
+	if (priv->phy_num == 0) {
+		if ((priv->duplex == TLAN_DUPLEX_FULL) ||
+		    (an_adv & an_lpa & 0x0040)) {
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL,
+					   MII_GC_AUTOENB | MII_GC_DUPLEX);
+			netdev_info(dev, "Starting internal PHY with FULL-DUPLEX\n");
 		} else {
-			TLan_MiiWriteReg( dev, phy, MII_GEN_CTL, MII_GC_AUTOENB );
-			pr_info( "TLAN:  Starting internal PHY with HALF-DUPLEX\n" );
+			tlan_mii_write_reg(dev, phy, MII_GEN_CTL,
+					   MII_GC_AUTOENB);
+			netdev_info(dev, "Starting internal PHY with HALF-DUPLEX\n");
 		}
 	}
 
 	/* Wait for 100 ms.  No reason in partiticular.
 	 */
-	TLan_SetTimer( dev, (HZ/10), TLAN_TIMER_FINISH_RESET );
+	tlan_set_timer(dev, (HZ/10), TLAN_TIMER_FINISH_RESET);
 
-} /* TLan_PhyFinishAutoNeg */
+}
 
 #ifdef MONITOR
 
-        /*********************************************************************
-        *
-        *      TLan_phyMonitor
-        *
-        *      Returns:
-        *              None
-        *
-        *      Params:
-        *              dev             The device structure of this device.
-        *
-        *
-        *      This function monitors PHY condition by reading the status
-        *      register via the MII bus. This can be used to give info
-        *      about link changes (up/down), and possible switch to alternate
-        *      media.
-        *
-        * ******************************************************************/
+/*********************************************************************
+ *
+ *     tlan_phy_monitor
+ *
+ *     Returns:
+ *	      None
+ *
+ *     Params:
+ *	      dev	     The device structure of this device.
+ *
+ *
+ *     This function monitors PHY condition by reading the status
+ *     register via the MII bus. This can be used to give info
+ *     about link changes (up/down), and possible switch to alternate
+ *     media.
+ *
+ *******************************************************************/
 
-void TLan_PhyMonitor( struct net_device *dev )
+void tlan_phy_monitor(struct net_device *dev)
 {
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	u16     phy;
 	u16     phy_status;
 
-	phy = priv->phy[priv->phyNum];
+	phy = priv->phy[priv->phy_num];
 
-        /* Get PHY status register */
-        TLan_MiiReadReg( dev, phy, MII_GEN_STS, &phy_status );
+	/* Get PHY status register */
+	tlan_mii_read_reg(dev, phy, MII_GEN_STS, &phy_status);
 
-        /* Check if link has been lost */
-        if (!(phy_status & MII_GS_LINK)) {
- 	       if (priv->link) {
-		      priv->link = 0;
-	              printk(KERN_DEBUG "TLAN: %s has lost link\n", dev->name);
-		      netif_carrier_off(dev);
-		      TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
-		      return;
+	/* Check if link has been lost */
+	if (!(phy_status & MII_GS_LINK)) {
+		if (priv->link) {
+			priv->link = 0;
+			printk(KERN_DEBUG "TLAN: %s has lost link\n",
+			       dev->name);
+			netif_carrier_off(dev);
+			tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
+			return;
 		}
 	}
 
-        /* Link restablished? */
-        if ((phy_status & MII_GS_LINK) && !priv->link) {
- 		priv->link = 1;
-        	printk(KERN_DEBUG "TLAN: %s has reestablished link\n", dev->name);
+	/* Link restablished? */
+	if ((phy_status & MII_GS_LINK) && !priv->link) {
+		priv->link = 1;
+		printk(KERN_DEBUG "TLAN: %s has reestablished link\n",
+		       dev->name);
 		netif_carrier_on(dev);
-        }
+	}
 
 	/* Setup a new monitor */
-	TLan_SetTimer( dev, (2*HZ), TLAN_TIMER_LINK_BEAT );
+	tlan_set_timer(dev, (2*HZ), TLAN_TIMER_LINK_BEAT);
 }
 
 #endif /* MONITOR */
@@ -2842,47 +2781,48 @@
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver MII Routines
+ThunderLAN driver MII routines
 
-	These routines are based on the information in Chap. 2 of the
-	"ThunderLAN Programmer's Guide", pp. 15-24.
+these routines are based on the information in chap. 2 of the
+"ThunderLAN Programmer's Guide", pp. 15-24.
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_MiiReadReg
-	 *
-	 *	Returns:
-	 *		false	if ack received ok
-	 *		true	if no ack received or other error
-	 *
-	 *	Parms:
-	 *		dev		The device structure containing
-	 *				The io address and interrupt count
-	 *				for this device.
-	 *		phy		The address of the PHY to be queried.
-	 *		reg		The register whose contents are to be
-	 *				retrieved.
-	 *		val		A pointer to a variable to store the
-	 *				retrieved value.
-	 *
-	 *	This function uses the TLAN's MII bus to retrieve the contents
-	 *	of a given register on a PHY.  It sends the appropriate info
-	 *	and then reads the 16-bit register value from the MII bus via
-	 *	the TLAN SIO register.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_mii_read_reg
+ *
+ *	Returns:
+ *		false	if ack received ok
+ *		true	if no ack received or other error
+ *
+ *	Parms:
+ *		dev		The device structure containing
+ *				The io address and interrupt count
+ *				for this device.
+ *		phy		The address of the PHY to be queried.
+ *		reg		The register whose contents are to be
+ *				retrieved.
+ *		val		A pointer to a variable to store the
+ *				retrieved value.
+ *
+ *	This function uses the TLAN's MII bus to retrieve the contents
+ *	of a given register on a PHY.  It sends the appropriate info
+ *	and then reads the 16-bit register value from the MII bus via
+ *	the TLAN SIO register.
+ *
+ **************************************************************/
 
-static bool TLan_MiiReadReg( struct net_device *dev, u16 phy, u16 reg, u16 *val )
+static bool
+tlan_mii_read_reg(struct net_device *dev, u16 phy, u16 reg, u16 *val)
 {
 	u8	nack;
 	u16	sio, tmp;
- 	u32	i;
+	u32	i;
 	bool	err;
 	int	minten;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	unsigned long flags = 0;
 
 	err = false;
@@ -2892,48 +2832,48 @@
 	if (!in_irq())
 		spin_lock_irqsave(&priv->lock, flags);
 
-	TLan_MiiSync(dev->base_addr);
+	tlan_mii_sync(dev->base_addr);
 
-	minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
-	if ( minten )
-		TLan_ClearBit(TLAN_NET_SIO_MINTEN, sio);
+	minten = tlan_get_bit(TLAN_NET_SIO_MINTEN, sio);
+	if (minten)
+		tlan_clear_bit(TLAN_NET_SIO_MINTEN, sio);
 
-	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Start ( 01b ) */
-	TLan_MiiSendData( dev->base_addr, 0x2, 2 );	/* Read  ( 10b ) */
-	TLan_MiiSendData( dev->base_addr, phy, 5 );	/* Device #      */
-	TLan_MiiSendData( dev->base_addr, reg, 5 );	/* Register #    */
+	tlan_mii_send_data(dev->base_addr, 0x1, 2);	/* start (01b) */
+	tlan_mii_send_data(dev->base_addr, 0x2, 2);	/* read  (10b) */
+	tlan_mii_send_data(dev->base_addr, phy, 5);	/* device #      */
+	tlan_mii_send_data(dev->base_addr, reg, 5);	/* register #    */
 
 
-	TLan_ClearBit(TLAN_NET_SIO_MTXEN, sio);		/* Change direction */
+	tlan_clear_bit(TLAN_NET_SIO_MTXEN, sio);	/* change direction */
 
-	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);		/* Clock Idle bit */
-	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
-	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);		/* Wait 300ns */
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);		/* clock idle bit */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);		/* wait 300ns */
 
-	nack = TLan_GetBit(TLAN_NET_SIO_MDATA, sio);	/* Check for ACK */
-	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);		/* Finish ACK */
-	if (nack) {					/* No ACK, so fake it */
+	nack = tlan_get_bit(TLAN_NET_SIO_MDATA, sio);	/* check for ACK */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);		/* finish ACK */
+	if (nack) {					/* no ACK, so fake it */
 		for (i = 0; i < 16; i++) {
-			TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
-			TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+			tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+			tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 		}
 		tmp = 0xffff;
 		err = true;
 	} else {					/* ACK, so read data */
 		for (tmp = 0, i = 0x8000; i; i >>= 1) {
-			TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);
-			if (TLan_GetBit(TLAN_NET_SIO_MDATA, sio))
+			tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+			if (tlan_get_bit(TLAN_NET_SIO_MDATA, sio))
 				tmp |= i;
-			TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+			tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 		}
 	}
 
 
-	TLan_ClearBit(TLAN_NET_SIO_MCLK, sio);		/* Idle cycle */
-	TLan_SetBit(TLAN_NET_SIO_MCLK, sio);
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);		/* idle cycle */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 
-	if ( minten )
-		TLan_SetBit(TLAN_NET_SIO_MINTEN, sio);
+	if (minten)
+		tlan_set_bit(TLAN_NET_SIO_MINTEN, sio);
 
 	*val = tmp;
 
@@ -2942,116 +2882,117 @@
 
 	return err;
 
-} /* TLan_MiiReadReg */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_MiiSendData
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		base_port	The base IO port of the adapter	in
-	 *				question.
-	 *		dev		The address of the PHY to be queried.
-	 *		data		The value to be placed on the MII bus.
-	 *		num_bits	The number of bits in data that are to
-	 *				be placed on the MII bus.
-	 *
-	 *	This function sends on sequence of bits on the MII
-	 *	configuration bus.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_mii_send_data
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		base_port	The base IO port of the adapter	in
+ *				question.
+ *		dev		The address of the PHY to be queried.
+ *		data		The value to be placed on the MII bus.
+ *		num_bits	The number of bits in data that are to
+ *				be placed on the MII bus.
+ *
+ *	This function sends on sequence of bits on the MII
+ *	configuration bus.
+ *
+ **************************************************************/
 
-static void TLan_MiiSendData( u16 base_port, u32 data, unsigned num_bits )
+static void tlan_mii_send_data(u16 base_port, u32 data, unsigned num_bits)
 {
 	u16 sio;
 	u32 i;
 
-	if ( num_bits == 0 )
+	if (num_bits == 0)
 		return;
 
-	outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
 	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
-	TLan_SetBit( TLAN_NET_SIO_MTXEN, sio );
+	tlan_set_bit(TLAN_NET_SIO_MTXEN, sio);
 
-	for ( i = ( 0x1 << ( num_bits - 1 ) ); i; i >>= 1 ) {
-		TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
-		(void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
-		if ( data & i )
-			TLan_SetBit( TLAN_NET_SIO_MDATA, sio );
+	for (i = (0x1 << (num_bits - 1)); i; i >>= 1) {
+		tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+		(void) tlan_get_bit(TLAN_NET_SIO_MCLK, sio);
+		if (data & i)
+			tlan_set_bit(TLAN_NET_SIO_MDATA, sio);
 		else
-			TLan_ClearBit( TLAN_NET_SIO_MDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
-		(void) TLan_GetBit( TLAN_NET_SIO_MCLK, sio );
+			tlan_clear_bit(TLAN_NET_SIO_MDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
+		(void) tlan_get_bit(TLAN_NET_SIO_MCLK, sio);
 	}
 
-} /* TLan_MiiSendData */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_MiiSync
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		base_port	The base IO port of the adapter in
-	 *				question.
-	 *
-	 *	This functions syncs all PHYs in terms of the MII configuration
-	 *	bus.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	TLan_MiiSync
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		base_port	The base IO port of the adapter in
+ *				question.
+ *
+ *	This functions syncs all PHYs in terms of the MII configuration
+ *	bus.
+ *
+ **************************************************************/
 
-static void TLan_MiiSync( u16 base_port )
+static void tlan_mii_sync(u16 base_port)
 {
 	int i;
 	u16 sio;
 
-	outw( TLAN_NET_SIO, base_port + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, base_port + TLAN_DIO_ADR);
 	sio = base_port + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	TLan_ClearBit( TLAN_NET_SIO_MTXEN, sio );
-	for ( i = 0; i < 32; i++ ) {
-		TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );
-		TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
+	tlan_clear_bit(TLAN_NET_SIO_MTXEN, sio);
+	for (i = 0; i < 32; i++) {
+		tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);
+		tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 	}
 
-} /* TLan_MiiSync */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_MiiWriteReg
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		dev		The device structure for the device
-	 *				to write to.
-	 *		phy		The address of the PHY to be written to.
-	 *		reg		The register whose contents are to be
-	 *				written.
-	 *		val		The value to be written to the register.
-	 *
-	 *	This function uses the TLAN's MII bus to write the contents of a
-	 *	given register on a PHY.  It sends the appropriate info and then
-	 *	writes the 16-bit register value from the MII configuration bus
-	 *	via the TLAN SIO register.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_mii_write_reg
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		dev		The device structure for the device
+ *				to write to.
+ *		phy		The address of the PHY to be written to.
+ *		reg		The register whose contents are to be
+ *				written.
+ *		val		The value to be written to the register.
+ *
+ *	This function uses the TLAN's MII bus to write the contents of a
+ *	given register on a PHY.  It sends the appropriate info and then
+ *	writes the 16-bit register value from the MII configuration bus
+ *	via the TLAN SIO register.
+ *
+ **************************************************************/
 
-static void TLan_MiiWriteReg( struct net_device *dev, u16 phy, u16 reg, u16 val )
+static void
+tlan_mii_write_reg(struct net_device *dev, u16 phy, u16 reg, u16 val)
 {
 	u16	sio;
 	int	minten;
 	unsigned long flags = 0;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 
 	outw(TLAN_NET_SIO, dev->base_addr + TLAN_DIO_ADR);
 	sio = dev->base_addr + TLAN_DIO_DATA + TLAN_NET_SIO;
@@ -3059,30 +3000,30 @@
 	if (!in_irq())
 		spin_lock_irqsave(&priv->lock, flags);
 
-	TLan_MiiSync( dev->base_addr );
+	tlan_mii_sync(dev->base_addr);
 
-	minten = TLan_GetBit( TLAN_NET_SIO_MINTEN, sio );
-	if ( minten )
-		TLan_ClearBit( TLAN_NET_SIO_MINTEN, sio );
+	minten = tlan_get_bit(TLAN_NET_SIO_MINTEN, sio);
+	if (minten)
+		tlan_clear_bit(TLAN_NET_SIO_MINTEN, sio);
 
-	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Start ( 01b ) */
-	TLan_MiiSendData( dev->base_addr, 0x1, 2 );	/* Write ( 01b ) */
-	TLan_MiiSendData( dev->base_addr, phy, 5 );	/* Device #      */
-	TLan_MiiSendData( dev->base_addr, reg, 5 );	/* Register #    */
+	tlan_mii_send_data(dev->base_addr, 0x1, 2);	/* start (01b) */
+	tlan_mii_send_data(dev->base_addr, 0x1, 2);	/* write (01b) */
+	tlan_mii_send_data(dev->base_addr, phy, 5);	/* device #      */
+	tlan_mii_send_data(dev->base_addr, reg, 5);	/* register #    */
 
-	TLan_MiiSendData( dev->base_addr, 0x2, 2 );	/* Send ACK */
-	TLan_MiiSendData( dev->base_addr, val, 16 );	/* Send Data */
+	tlan_mii_send_data(dev->base_addr, 0x2, 2);	/* send ACK */
+	tlan_mii_send_data(dev->base_addr, val, 16);	/* send data */
 
-	TLan_ClearBit( TLAN_NET_SIO_MCLK, sio );	/* Idle cycle */
-	TLan_SetBit( TLAN_NET_SIO_MCLK, sio );
+	tlan_clear_bit(TLAN_NET_SIO_MCLK, sio);	/* idle cycle */
+	tlan_set_bit(TLAN_NET_SIO_MCLK, sio);
 
-	if ( minten )
-		TLan_SetBit( TLAN_NET_SIO_MINTEN, sio );
+	if (minten)
+		tlan_set_bit(TLAN_NET_SIO_MINTEN, sio);
 
 	if (!in_irq())
 		spin_unlock_irqrestore(&priv->lock, flags);
 
-} /* TLan_MiiWriteReg */
+}
 
 
 
@@ -3090,229 +3031,226 @@
 /*****************************************************************************
 ******************************************************************************
 
-	ThunderLAN Driver Eeprom routines
+ThunderLAN driver eeprom routines
 
-	The Compaq Netelligent 10 and 10/100 cards use a Microchip 24C02A
-	EEPROM.  These functions are based on information in Microchip's
-	data sheet.  I don't know how well this functions will work with
-	other EEPROMs.
+the Compaq netelligent 10 and 10/100 cards use a microchip 24C02A
+EEPROM.  these functions are based on information in microchip's
+data sheet.  I don't know how well this functions will work with
+other Eeproms.
 
 ******************************************************************************
 *****************************************************************************/
 
 
-	/***************************************************************
-	 *	TLan_EeSendStart
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *
-	 *	This function sends a start cycle to an EEPROM attached
-	 *	to a TLAN chip.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_ee_send_start
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *
+ *	This function sends a start cycle to an EEPROM attached
+ *	to a TLAN chip.
+ *
+ **************************************************************/
 
-static void TLan_EeSendStart( u16 io_base )
+static void tlan_ee_send_start(u16 io_base)
 {
 	u16	sio;
 
-	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
 
-	TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-	TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
-	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
-	TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-	TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+	tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+	tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
+	tlan_set_bit(TLAN_NET_SIO_ETXEN, sio);
+	tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+	tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 
-} /* TLan_EeSendStart */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_EeSendByte
-	 *
-	 *	Returns:
-	 *		If the correct ack was received, 0, otherwise 1
-	 *	Parms:	io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *		data		The 8 bits of information to
-	 *				send to the EEPROM.
-	 *		stop		If TLAN_EEPROM_STOP is passed, a
-	 *				stop cycle is sent after the
-	 *				byte is sent after the ack is
-	 *				read.
-	 *
-	 *	This function sends a byte on the serial EEPROM line,
-	 *	driving the clock to send each bit. The function then
-	 *	reverses transmission direction and reads an acknowledge
-	 *	bit.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_ee_send_byte
+ *
+ *	Returns:
+ *		If the correct ack was received, 0, otherwise 1
+ *	Parms:	io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *		data		The 8 bits of information to
+ *				send to the EEPROM.
+ *		stop		If TLAN_EEPROM_STOP is passed, a
+ *				stop cycle is sent after the
+ *				byte is sent after the ack is
+ *				read.
+ *
+ *	This function sends a byte on the serial EEPROM line,
+ *	driving the clock to send each bit. The function then
+ *	reverses transmission direction and reads an acknowledge
+ *	bit.
+ *
+ **************************************************************/
 
-static int TLan_EeSendByte( u16 io_base, u8 data, int stop )
+static int tlan_ee_send_byte(u16 io_base, u8 data, int stop)
 {
 	int	err;
 	u8	place;
 	u16	sio;
 
-	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
 
 	/* Assume clock is low, tx is enabled; */
-	for ( place = 0x80; place != 0; place >>= 1 ) {
-		if ( place & data )
-			TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
+	for (place = 0x80; place != 0; place >>= 1) {
+		if (place & data)
+			tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
 		else
-			TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+			tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 	}
-	TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
-	TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-	err = TLan_GetBit( TLAN_NET_SIO_EDATA, sio );
-	TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
-	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
+	tlan_clear_bit(TLAN_NET_SIO_ETXEN, sio);
+	tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+	err = tlan_get_bit(TLAN_NET_SIO_EDATA, sio);
+	tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
+	tlan_set_bit(TLAN_NET_SIO_ETXEN, sio);
 
-	if ( ( ! err ) && stop ) {
+	if ((!err) && stop) {
 		/* STOP, raise data while clock is high */
-		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
+		tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
 	}
 
 	return err;
 
-} /* TLan_EeSendByte */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_EeReceiveByte
-	 *
-	 *	Returns:
-	 *		Nothing
-	 *	Parms:
-	 *		io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *		data		An address to a char to hold the
-	 *				data sent from the EEPROM.
-	 *		stop		If TLAN_EEPROM_STOP is passed, a
-	 *				stop cycle is sent after the
-	 *				byte is received, and no ack is
-	 *				sent.
-	 *
-	 *	This function receives 8 bits of data from the EEPROM
-	 *	over the serial link.  It then sends and ack bit, or no
-	 *	ack and a stop bit.  This function is used to retrieve
-	 *	data after the address of a byte in the EEPROM has been
-	 *	sent.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_ee_receive_byte
+ *
+ *	Returns:
+ *		Nothing
+ *	Parms:
+ *		io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *		data		An address to a char to hold the
+ *				data sent from the EEPROM.
+ *		stop		If TLAN_EEPROM_STOP is passed, a
+ *				stop cycle is sent after the
+ *				byte is received, and no ack is
+ *				sent.
+ *
+ *	This function receives 8 bits of data from the EEPROM
+ *	over the serial link.  It then sends and ack bit, or no
+ *	ack and a stop bit.  This function is used to retrieve
+ *	data after the address of a byte in the EEPROM has been
+ *	sent.
+ *
+ **************************************************************/
 
-static void TLan_EeReceiveByte( u16 io_base, u8 *data, int stop )
+static void tlan_ee_receive_byte(u16 io_base, u8 *data, int stop)
 {
 	u8  place;
 	u16 sio;
 
-	outw( TLAN_NET_SIO, io_base + TLAN_DIO_ADR );
+	outw(TLAN_NET_SIO, io_base + TLAN_DIO_ADR);
 	sio = io_base + TLAN_DIO_DATA + TLAN_NET_SIO;
 	*data = 0;
 
 	/* Assume clock is low, tx is enabled; */
-	TLan_ClearBit( TLAN_NET_SIO_ETXEN, sio );
-	for ( place = 0x80; place; place >>= 1 ) {
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		if ( TLan_GetBit( TLAN_NET_SIO_EDATA, sio ) )
+	tlan_clear_bit(TLAN_NET_SIO_ETXEN, sio);
+	for (place = 0x80; place; place >>= 1) {
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		if (tlan_get_bit(TLAN_NET_SIO_EDATA, sio))
 			*data |= place;
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 	}
 
-	TLan_SetBit( TLAN_NET_SIO_ETXEN, sio );
-	if ( ! stop ) {
-		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );	/* Ack = 0 */
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+	tlan_set_bit(TLAN_NET_SIO_ETXEN, sio);
+	if (!stop) {
+		tlan_clear_bit(TLAN_NET_SIO_EDATA, sio); /* ack = 0 */
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 	} else {
-		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );		/* No ack = 1 (?) */
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_ClearBit( TLAN_NET_SIO_ECLOK, sio );
+		tlan_set_bit(TLAN_NET_SIO_EDATA, sio);	/* no ack = 1 (?) */
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_clear_bit(TLAN_NET_SIO_ECLOK, sio);
 		/* STOP, raise data while clock is high */
-		TLan_ClearBit( TLAN_NET_SIO_EDATA, sio );
-		TLan_SetBit( TLAN_NET_SIO_ECLOK, sio );
-		TLan_SetBit( TLAN_NET_SIO_EDATA, sio );
+		tlan_clear_bit(TLAN_NET_SIO_EDATA, sio);
+		tlan_set_bit(TLAN_NET_SIO_ECLOK, sio);
+		tlan_set_bit(TLAN_NET_SIO_EDATA, sio);
 	}
 
-} /* TLan_EeReceiveByte */
+}
 
 
 
 
-	/***************************************************************
-	 *	TLan_EeReadByte
-	 *
-	 *	Returns:
-	 *		No error = 0, else, the stage at which the error
-	 *		occurred.
-	 *	Parms:
-	 *		io_base		The IO port base address for the
-	 *				TLAN device with the EEPROM to
-	 *				use.
-	 *		ee_addr		The address of the byte in the
-	 *				EEPROM whose contents are to be
-	 *				retrieved.
-	 *		data		An address to a char to hold the
-	 *				data obtained from the EEPROM.
-	 *
-	 *	This function reads a byte of information from an byte
-	 *	cell in the EEPROM.
-	 *
-	 **************************************************************/
+/***************************************************************
+ *	tlan_ee_read_byte
+ *
+ *	Returns:
+ *		No error = 0, else, the stage at which the error
+ *		occurred.
+ *	Parms:
+ *		io_base		The IO port base address for the
+ *				TLAN device with the EEPROM to
+ *				use.
+ *		ee_addr		The address of the byte in the
+ *				EEPROM whose contents are to be
+ *				retrieved.
+ *		data		An address to a char to hold the
+ *				data obtained from the EEPROM.
+ *
+ *	This function reads a byte of information from an byte
+ *	cell in the EEPROM.
+ *
+ **************************************************************/
 
-static int TLan_EeReadByte( struct net_device *dev, u8 ee_addr, u8 *data )
+static int tlan_ee_read_byte(struct net_device *dev, u8 ee_addr, u8 *data)
 {
 	int err;
-	TLanPrivateInfo *priv = netdev_priv(dev);
+	struct tlan_priv *priv = netdev_priv(dev);
 	unsigned long flags = 0;
-	int ret=0;
+	int ret = 0;
 
 	spin_lock_irqsave(&priv->lock, flags);
 
-	TLan_EeSendStart( dev->base_addr );
-	err = TLan_EeSendByte( dev->base_addr, 0xA0, TLAN_EEPROM_ACK );
-	if (err)
-	{
-		ret=1;
+	tlan_ee_send_start(dev->base_addr);
+	err = tlan_ee_send_byte(dev->base_addr, 0xa0, TLAN_EEPROM_ACK);
+	if (err) {
+		ret = 1;
 		goto fail;
 	}
-	err = TLan_EeSendByte( dev->base_addr, ee_addr, TLAN_EEPROM_ACK );
-	if (err)
-	{
-		ret=2;
+	err = tlan_ee_send_byte(dev->base_addr, ee_addr, TLAN_EEPROM_ACK);
+	if (err) {
+		ret = 2;
 		goto fail;
 	}
-	TLan_EeSendStart( dev->base_addr );
-	err = TLan_EeSendByte( dev->base_addr, 0xA1, TLAN_EEPROM_ACK );
-	if (err)
-	{
-		ret=3;
+	tlan_ee_send_start(dev->base_addr);
+	err = tlan_ee_send_byte(dev->base_addr, 0xa1, TLAN_EEPROM_ACK);
+	if (err) {
+		ret = 3;
 		goto fail;
 	}
-	TLan_EeReceiveByte( dev->base_addr, data, TLAN_EEPROM_STOP );
+	tlan_ee_receive_byte(dev->base_addr, data, TLAN_EEPROM_STOP);
 fail:
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	return ret;
 
-} /* TLan_EeReadByte */
+}
 
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/tlan.h linux-libre-2.6.39-gnu/drivers/net/tlan.h
--- linux-libre-2.6.38-gnu/drivers/net/tlan.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tlan.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,8 +20,8 @@
  ********************************************************************/
 
 
-#include <asm/io.h>
-#include <asm/types.h>
+#include <linux/io.h>
+#include <linux/types.h>
 #include <linux/netdevice.h>
 
 
@@ -40,8 +40,11 @@
 #define TLAN_IGNORE		0
 #define TLAN_RECORD		1
 
-#define TLAN_DBG(lvl, format, args...)	\
-	do { if (debug&lvl) printk(KERN_DEBUG "TLAN: " format, ##args ); } while(0)
+#define TLAN_DBG(lvl, format, args...)					\
+	do {								\
+		if (debug&lvl)						\
+			printk(KERN_DEBUG "TLAN: " format, ##args);	\
+	} while (0)
 
 #define TLAN_DEBUG_GNRL		0x0001
 #define TLAN_DEBUG_TX		0x0002
@@ -50,7 +53,8 @@
 #define TLAN_DEBUG_PROBE	0x0010
 
 #define TX_TIMEOUT		(10*HZ)	 /* We need time for auto-neg */
-#define MAX_TLAN_BOARDS		8	 /* Max number of boards installed at a time */
+#define MAX_TLAN_BOARDS		8	 /* Max number of boards installed
+					    at a time */
 
 
 	/*****************************************************************
@@ -70,13 +74,13 @@
 #define PCI_DEVICE_ID_OLICOM_OC2326			0x0014
 #endif
 
-typedef struct tlan_adapter_entry {
-	u16	vendorId;
-	u16	deviceId;
-	char	*deviceLabel;
+struct tlan_adapter_entry {
+	u16	vendor_id;
+	u16	device_id;
+	char	*device_label;
 	u32	flags;
-	u16	addrOfs;
-} TLanAdapterEntry;
+	u16	addr_ofs;
+};
 
 #define TLAN_ADAPTER_NONE		0x00000000
 #define TLAN_ADAPTER_UNMANAGED_PHY	0x00000001
@@ -129,18 +133,18 @@
 #define TLAN_CSTAT_DP_PR	0x0100
 
 
-typedef struct tlan_buffer_ref_tag {
+struct tlan_buffer {
 	u32	count;
 	u32	address;
-} TLanBufferRef;
+};
 
 
-typedef struct tlan_list_tag {
+struct tlan_list {
 	u32		forward;
-	u16		cStat;
-	u16		frameSize;
-	TLanBufferRef	buffer[TLAN_BUFFERS_PER_LIST];
-} TLanList;
+	u16		c_stat;
+	u16		frame_size;
+	struct tlan_buffer buffer[TLAN_BUFFERS_PER_LIST];
+};
 
 
 typedef u8 TLanBuffer[TLAN_MAX_FRAME_SIZE];
@@ -164,49 +168,49 @@
 	 *
 	 ****************************************************************/
 
-typedef struct tlan_private_tag {
-	struct net_device       *nextDevice;
-	struct pci_dev		*pciDev;
+struct tlan_priv {
+	struct net_device       *next_device;
+	struct pci_dev		*pci_dev;
 	struct net_device       *dev;
-	void			*dmaStorage;
-	dma_addr_t		dmaStorageDMA;
-	unsigned int		dmaSize;
-	u8			*padBuffer;
-	TLanList                *rxList;
-	dma_addr_t		rxListDMA;
-	u8			*rxBuffer;
-	dma_addr_t		rxBufferDMA;
-	u32                     rxHead;
-	u32                     rxTail;
-	u32			rxEocCount;
-	TLanList                *txList;
-	dma_addr_t		txListDMA;
-	u8			*txBuffer;
-	dma_addr_t		txBufferDMA;
-	u32                     txHead;
-	u32                     txInProgress;
-	u32                     txTail;
-	u32			txBusyCount;
-	u32                     phyOnline;
-	u32			timerSetAt;
-	u32			timerType;
+	void			*dma_storage;
+	dma_addr_t		dma_storage_dma;
+	unsigned int		dma_size;
+	u8			*pad_buffer;
+	struct tlan_list	*rx_list;
+	dma_addr_t		rx_list_dma;
+	u8			*rx_buffer;
+	dma_addr_t		rx_buffer_dma;
+	u32			rx_head;
+	u32			rx_tail;
+	u32			rx_eoc_count;
+	struct tlan_list	*tx_list;
+	dma_addr_t		tx_list_dma;
+	u8			*tx_buffer;
+	dma_addr_t		tx_buffer_dma;
+	u32			tx_head;
+	u32			tx_in_progress;
+	u32			tx_tail;
+	u32			tx_busy_count;
+	u32			phy_online;
+	u32			timer_set_at;
+	u32			timer_type;
 	struct timer_list	timer;
 	struct board		*adapter;
-	u32			adapterRev;
+	u32			adapter_rev;
 	u32			aui;
 	u32			debug;
 	u32			duplex;
 	u32			phy[2];
-	u32			phyNum;
+	u32			phy_num;
 	u32			speed;
-	u8			tlanRev;
-	u8			tlanFullDuplex;
+	u8			tlan_rev;
+	u8			tlan_full_duplex;
 	spinlock_t		lock;
 	u8			link;
 	u8			is_eisa;
 	struct work_struct			tlan_tqueue;
 	u8			neg_be_verbose;
-} TLanPrivateInfo;
+};
 
 
 
@@ -247,7 +251,7 @@
 	 ****************************************************************/
 
 #define TLAN_HOST_CMD			0x00
-#define 	TLAN_HC_GO		0x80000000
+#define	TLAN_HC_GO		0x80000000
 #define		TLAN_HC_STOP		0x40000000
 #define		TLAN_HC_ACK		0x20000000
 #define		TLAN_HC_CS_MASK		0x1FE00000
@@ -283,7 +287,7 @@
 #define		TLAN_NET_CMD_TRFRAM	0x02
 #define		TLAN_NET_CMD_TXPACE	0x01
 #define TLAN_NET_SIO			0x01
-#define 	TLAN_NET_SIO_MINTEN	0x80
+#define	TLAN_NET_SIO_MINTEN	0x80
 #define		TLAN_NET_SIO_ECLOK	0x40
 #define		TLAN_NET_SIO_ETXEN	0x20
 #define		TLAN_NET_SIO_EDATA	0x10
@@ -304,7 +308,7 @@
 #define		TLAN_NET_MASK_MASK4	0x10
 #define		TLAN_NET_MASK_RSRVD	0x0F
 #define TLAN_NET_CONFIG			0x04
-#define 	TLAN_NET_CFG_RCLK	0x8000
+#define	TLAN_NET_CFG_RCLK	0x8000
 #define		TLAN_NET_CFG_TCLK	0x4000
 #define		TLAN_NET_CFG_BIT	0x2000
 #define		TLAN_NET_CFG_RXCRC	0x1000
@@ -372,7 +376,7 @@
 /* Generic MII/PHY Registers */
 
 #define MII_GEN_CTL			0x00
-#define 	MII_GC_RESET		0x8000
+#define	MII_GC_RESET		0x8000
 #define		MII_GC_LOOPBK		0x4000
 #define		MII_GC_SPEEDSEL		0x2000
 #define		MII_GC_AUTOENB		0x1000
@@ -397,9 +401,9 @@
 #define		MII_GS_EXTCAP		0x0001
 #define MII_GEN_ID_HI			0x02
 #define MII_GEN_ID_LO			0x03
-#define 	MII_GIL_OUI		0xFC00
-#define 	MII_GIL_MODEL		0x03F0
-#define 	MII_GIL_REVISION	0x000F
+#define	MII_GIL_OUI		0xFC00
+#define	MII_GIL_MODEL		0x03F0
+#define	MII_GIL_REVISION	0x000F
 #define MII_AN_ADV			0x04
 #define MII_AN_LPA			0x05
 #define MII_AN_EXP			0x06
@@ -408,7 +412,7 @@
 
 #define TLAN_TLPHY_ID			0x10
 #define TLAN_TLPHY_CTL			0x11
-#define 	TLAN_TC_IGLINK		0x8000
+#define	TLAN_TC_IGLINK		0x8000
 #define		TLAN_TC_SWAPOL		0x4000
 #define		TLAN_TC_AUISEL		0x2000
 #define		TLAN_TC_SQEEN		0x1000
@@ -435,41 +439,41 @@
 #define LEVEL1_ID1			0x7810
 #define LEVEL1_ID2			0x0000
 
-#define CIRC_INC( a, b ) if ( ++a >= b ) a = 0
+#define CIRC_INC(a, b) if (++a >= b) a = 0
 
 /* Routines to access internal registers. */
 
-static inline u8 TLan_DioRead8(u16 base_addr, u16 internal_addr)
+static inline u8 tlan_dio_read8(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	return inb((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x3));
 
-} /* TLan_DioRead8 */
+}
 
 
 
 
-static inline u16 TLan_DioRead16(u16 base_addr, u16 internal_addr)
+static inline u16 tlan_dio_read16(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	return inw((base_addr + TLAN_DIO_DATA) + (internal_addr & 0x2));
 
-} /* TLan_DioRead16 */
+}
 
 
 
 
-static inline u32 TLan_DioRead32(u16 base_addr, u16 internal_addr)
+static inline u32 tlan_dio_read32(u16 base_addr, u16 internal_addr)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	return inl(base_addr + TLAN_DIO_DATA);
 
-} /* TLan_DioRead32 */
+}
 
 
 
 
-static inline void TLan_DioWrite8(u16 base_addr, u16 internal_addr, u8 data)
+static inline void tlan_dio_write8(u16 base_addr, u16 internal_addr, u8 data)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	outb(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x3));
@@ -479,7 +483,7 @@
 
 
 
-static inline void TLan_DioWrite16(u16 base_addr, u16 internal_addr, u16 data)
+static inline void tlan_dio_write16(u16 base_addr, u16 internal_addr, u16 data)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	outw(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
@@ -489,16 +493,16 @@
 
 
 
-static inline void TLan_DioWrite32(u16 base_addr, u16 internal_addr, u32 data)
+static inline void tlan_dio_write32(u16 base_addr, u16 internal_addr, u32 data)
 {
 	outw(internal_addr, base_addr + TLAN_DIO_ADR);
 	outl(data, base_addr + TLAN_DIO_DATA + (internal_addr & 0x2));
 
 }
 
-#define TLan_ClearBit( bit, port )	outb_p(inb_p(port) & ~bit, port)
-#define TLan_GetBit( bit, port )	((int) (inb_p(port) & bit))
-#define TLan_SetBit( bit, port )	outb_p(inb_p(port) | bit, port)
+#define tlan_clear_bit(bit, port)	outb_p(inb_p(port) & ~bit, port)
+#define tlan_get_bit(bit, port)	((int) (inb_p(port) & bit))
+#define tlan_set_bit(bit, port)	outb_p(inb_p(port) | bit, port)
 
 /*
  * given 6 bytes, view them as 8 6-bit numbers and return the XOR of those
@@ -506,37 +510,37 @@
  *
  * The original code was:
  *
- * u32	xor( u32 a, u32 b ) {	return ( ( a && ! b ) || ( ! a && b ) ); }
+ * u32	xor(u32 a, u32 b) {	return ((a && !b ) || (! a && b )); }
  *
- * #define XOR8( a, b, c, d, e, f, g, h )	\
- * 	xor( a, xor( b, xor( c, xor( d, xor( e, xor( f, xor( g, h ) ) ) ) ) ) )
- * #define DA( a, bit )		( ( (u8) a[bit/8] ) & ( (u8) ( 1 << bit%8 ) ) )
+ * #define XOR8(a, b, c, d, e, f, g, h)	\
+ *	xor(a, xor(b, xor(c, xor(d, xor(e, xor(f, xor(g, h)) ) ) ) ) )
+ * #define DA(a, bit)		(( (u8) a[bit/8] ) & ( (u8) (1 << bit%8)) )
  *
- * 	hash  = XOR8( DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24),
- * 	              DA(a,30), DA(a,36), DA(a,42) );
- * 	hash |= XOR8( DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25),
- * 		      DA(a,31), DA(a,37), DA(a,43) ) << 1;
- * 	hash |= XOR8( DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26),
- * 		      DA(a,32), DA(a,38), DA(a,44) ) << 2;
- * 	hash |= XOR8( DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27),
- * 		      DA(a,33), DA(a,39), DA(a,45) ) << 3;
- * 	hash |= XOR8( DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28),
- * 	              DA(a,34), DA(a,40), DA(a,46) ) << 4;
- * 	hash |= XOR8( DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29),
- * 	              DA(a,35), DA(a,41), DA(a,47) ) << 5;
+ *	hash  = XOR8(DA(a,0), DA(a, 6), DA(a,12), DA(a,18), DA(a,24),
+ *		      DA(a,30), DA(a,36), DA(a,42));
+ *	hash |= XOR8(DA(a,1), DA(a, 7), DA(a,13), DA(a,19), DA(a,25),
+ *		      DA(a,31), DA(a,37), DA(a,43)) << 1;
+ *	hash |= XOR8(DA(a,2), DA(a, 8), DA(a,14), DA(a,20), DA(a,26),
+ *		      DA(a,32), DA(a,38), DA(a,44)) << 2;
+ *	hash |= XOR8(DA(a,3), DA(a, 9), DA(a,15), DA(a,21), DA(a,27),
+ *		      DA(a,33), DA(a,39), DA(a,45)) << 3;
+ *	hash |= XOR8(DA(a,4), DA(a,10), DA(a,16), DA(a,22), DA(a,28),
+ *		      DA(a,34), DA(a,40), DA(a,46)) << 4;
+ *	hash |= XOR8(DA(a,5), DA(a,11), DA(a,17), DA(a,23), DA(a,29),
+ *		      DA(a,35), DA(a,41), DA(a,47)) << 5;
  *
  */
-static inline u32 TLan_HashFunc( const u8 *a )
+static inline u32 tlan_hash_func(const u8 *a)
 {
-        u8     hash;
+	u8     hash;
 
-        hash = (a[0]^a[3]);             /* & 077 */
-        hash ^= ((a[0]^a[3])>>6);       /* & 003 */
-        hash ^= ((a[1]^a[4])<<2);       /* & 074 */
-        hash ^= ((a[1]^a[4])>>4);       /* & 017 */
-        hash ^= ((a[2]^a[5])<<4);       /* & 060 */
-        hash ^= ((a[2]^a[5])>>2);       /* & 077 */
+	hash = (a[0]^a[3]);		/* & 077 */
+	hash ^= ((a[0]^a[3])>>6);	/* & 003 */
+	hash ^= ((a[1]^a[4])<<2);	/* & 074 */
+	hash ^= ((a[1]^a[4])>>4);	/* & 017 */
+	hash ^= ((a[2]^a[5])<<4);	/* & 060 */
+	hash ^= ((a[2]^a[5])>>2);	/* & 077 */
 
-        return hash & 077;
+	return hash & 077;
 }
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/tokenring/3c359.c linux-libre-2.6.39-gnu/drivers/net/tokenring/3c359.c
--- linux-libre-2.6.38-gnu/drivers/net/tokenring/3c359.c	2012-03-24 01:09:54.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tokenring/3c359.c	2012-03-24 03:31:54.000000000 -0400
@@ -208,7 +208,7 @@
  *	passing/getting the next value from the nic. As with all requests
  *	on this nic it has to be done in two stages, a) tell the nic which
  *	memory address you want to access and b) pass/get the value from the nic.
- *	With the EEProm, you have to wait before and inbetween access a) and b).
+ *	With the EEProm, you have to wait before and between access a) and b).
  *	As this is only read at initialization time and the wait period is very 
  *	small we shouldn't have to worry about scheduling issues.
  */
@@ -1251,7 +1251,7 @@
 /* 
  * The NIC has told us that a packet has been downloaded onto the card, we must
  * find out which packet it has done, clear the skb and information for the packet
- * then advance around the ring for all tranmitted packets
+ * then advance around the ring for all transmitted packets
  */
 
 static void xl_dn_comp(struct net_device *dev) 
@@ -1568,7 +1568,7 @@
 			if (lan_status_diff & LSC_SOFT_ERR)
 					printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n",dev->name);
 			if (lan_status_diff & LSC_TRAN_BCN) 
-					printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+					printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n",dev->name);
 			if (lan_status_diff & LSC_SS) 
 					printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
 			if (lan_status_diff & LSC_RING_REC)
diff -druN linux-libre-2.6.38-gnu/drivers/net/tokenring/lanstreamer.c linux-libre-2.6.39-gnu/drivers/net/tokenring/lanstreamer.c
--- linux-libre-2.6.38-gnu/drivers/net/tokenring/lanstreamer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tokenring/lanstreamer.c	2011-05-19 00:06:34.000000000 -0400
@@ -1675,7 +1675,7 @@
 			if (lan_status_diff & LSC_SOFT_ERR)
 				printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n", dev->name);
 			if (lan_status_diff & LSC_TRAN_BCN)
-				printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n", dev->name);
+				printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n", dev->name);
 			if (lan_status_diff & LSC_SS)
 				printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
 			if (lan_status_diff & LSC_RING_REC)
diff -druN linux-libre-2.6.38-gnu/drivers/net/tokenring/madgemc.c linux-libre-2.6.39-gnu/drivers/net/tokenring/madgemc.c
--- linux-libre-2.6.38-gnu/drivers/net/tokenring/madgemc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tokenring/madgemc.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
 static irqreturn_t madgemc_interrupt(int irq, void *dev_id);
 
 /*
- * These work around paging, however they don't guarentee you're on the
+ * These work around paging, however they don't guarantee you're on the
  * right page.
  */
 #define SIFREADB(reg) (inb(dev->base_addr + ((reg<0x8)?reg:reg-0x8)))
@@ -387,7 +387,7 @@
  * both with their own disadvantages...
  *
  * 1)  	Read in the SIFSTS register from the TMS controller.  This
- *	is guarenteed to be accurate, however, there's a fairly
+ *	is guaranteed to be accurate, however, there's a fairly
  *	large performance penalty for doing so: the Madge chips
  *	must request the register from the Eagle, the Eagle must
  *	read them from its internal bus, and then take the route
@@ -454,7 +454,7 @@
 }
 
 /*
- * Set the card to the prefered ring speed.
+ * Set the card to the preferred ring speed.
  *
  * Unlike newer cards, the MC16/32 have their speed selection
  * circuit connected to the Madge ASICs and not to the TMS380
diff -druN linux-libre-2.6.38-gnu/drivers/net/tokenring/olympic.c linux-libre-2.6.39-gnu/drivers/net/tokenring/olympic.c
--- linux-libre-2.6.38-gnu/drivers/net/tokenring/olympic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tokenring/olympic.c	2011-05-19 00:06:34.000000000 -0400
@@ -1500,7 +1500,7 @@
 			if (lan_status_diff & LSC_SOFT_ERR)
 					printk(KERN_WARNING "%s: Adapter transmitted Soft Error Report Mac Frame\n",dev->name);
 			if (lan_status_diff & LSC_TRAN_BCN) 
-					printk(KERN_INFO "%s: We are tranmitting the beacon, aaah\n",dev->name);
+					printk(KERN_INFO "%s: We are transmitting the beacon, aaah\n",dev->name);
 			if (lan_status_diff & LSC_SS) 
 					printk(KERN_INFO "%s: Single Station on the ring\n", dev->name);
 			if (lan_status_diff & LSC_RING_REC)
diff -druN linux-libre-2.6.38-gnu/drivers/net/tokenring/smctr.c linux-libre-2.6.39-gnu/drivers/net/tokenring/smctr.c
--- linux-libre-2.6.38-gnu/drivers/net/tokenring/smctr.c	2012-03-24 01:10:06.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tokenring/smctr.c	2012-03-24 03:31:59.000000000 -0400
@@ -393,7 +393,7 @@
         tp->rx_bdb_end[NON_MAC_QUEUE] = (BDBlock *)smctr_malloc(dev, 0);
 
         /* Allocate MAC transmit buffers.
-         * MAC Tx Buffers doen't have to be on an ODD Boundry.
+         * MAC Tx Buffers doen't have to be on an ODD Boundary.
          */
         tp->tx_buff_head[MAC_QUEUE]
                 = (__u16 *)smctr_malloc(dev, tp->tx_buff_size[MAC_QUEUE]);
@@ -415,7 +415,7 @@
 
         /* Allocate Non-MAC transmit buffers.
          * ?? For maximum Netware performance, put Tx Buffers on
-         * ODD Boundry and then restore malloc to Even Boundrys.
+         * ODD Boundary and then restore malloc to Even Boundrys.
          */
         smctr_malloc(dev, 1L);
         tp->tx_buff_head[NON_MAC_QUEUE]
@@ -1311,7 +1311,7 @@
         mem_used += sizeof(BDBlock) * tp->num_rx_bdbs[MAC_QUEUE];
 
         /* Allocate MAC transmit buffers.
-         * MAC transmit buffers don't have to be on an ODD Boundry.
+         * MAC transmit buffers don't have to be on an ODD Boundary.
          */
         mem_used += tp->tx_buff_size[MAC_QUEUE];
 
@@ -1325,7 +1325,7 @@
 
         /* Allocate Non-MAC transmit buffers.
          * For maximum Netware performance, put Tx Buffers on
-         * ODD Boundry,and then restore malloc to Even Boundrys.
+         * ODD Boundary,and then restore malloc to Even Boundrys.
          */
         mem_used += 1L;
         mem_used += tp->tx_buff_size[NON_MAC_QUEUE];
@@ -3069,8 +3069,8 @@
  * disabled.!?
  *
  * NOTE 2: If the monitor_state is MS_BEACON_TEST_STATE and the receive_mask
- * has any multi-cast or promiscous bits set, the receive_mask needs to
- * be changed to clear the multi-cast or promiscous mode bits, the lobe_test
+ * has any multi-cast or promiscuous bits set, the receive_mask needs to
+ * be changed to clear the multi-cast or promiscuous mode bits, the lobe_test
  * run, and then the receive mask set back to its original value if the test
  * is successful.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/tokenring/tms380tr.h linux-libre-2.6.39-gnu/drivers/net/tokenring/tms380tr.h
--- linux-libre-2.6.38-gnu/drivers/net/tokenring/tms380tr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tokenring/tms380tr.h	2011-05-19 00:06:34.000000000 -0400
@@ -442,7 +442,7 @@
 #define PASS_FIRST_BUF_ONLY	0x0100	/* Passes only first internal buffer
 					 * of each received frame; FrameSize
 					 * of RPLs must contain internal
-					 * BUFFER_SIZE bits for promiscous mode.
+					 * BUFFER_SIZE bits for promiscuous mode.
 					 */
 #define ENABLE_FULL_DUPLEX_SELECTION	0x2000 
  					/* Enable the use of full-duplex
diff -druN linux-libre-2.6.38-gnu/drivers/net/tsi108_eth.h linux-libre-2.6.39-gnu/drivers/net/tsi108_eth.h
--- linux-libre-2.6.38-gnu/drivers/net/tsi108_eth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tsi108_eth.h	2011-05-19 00:06:34.000000000 -0400
@@ -305,9 +305,9 @@
 #define TSI108_TX_CRC	(1 << 5)	/* Generate CRC for this packet */
 #define TSI108_TX_INT	(1 << 14)	/* Generate an IRQ after frag. processed */
 #define TSI108_TX_RETRY	(0xf << 16)	/* 4 bit field indicating num. of retries */
-#define TSI108_TX_COL	(1 << 20)	/* Set if a collision occured */
-#define TSI108_TX_LCOL	(1 << 24)	/* Set if a late collision occured */
-#define TSI108_TX_UNDER	(1 << 25)	/* Set if a FIFO underrun occured */
+#define TSI108_TX_COL	(1 << 20)	/* Set if a collision occurred */
+#define TSI108_TX_LCOL	(1 << 24)	/* Set if a late collision occurred */
+#define TSI108_TX_UNDER	(1 << 25)	/* Set if a FIFO underrun occurred */
 #define TSI108_TX_RLIM	(1 << 26)	/* Set if the retry limit was reached */
 #define TSI108_TX_OK	(1 << 30)	/* Set if the frame TX was successful */
 #define TSI108_TX_OWN	(1 << 31)	/* Set if the device owns the descriptor */
@@ -332,7 +332,7 @@
 #define TSI108_RX_RUNT	(1 << 4)/* Packet is less than minimum size */
 #define TSI108_RX_HASH	(1 << 7)/* Hash table match */
 #define TSI108_RX_BAD	(1 << 8)	/* Bad frame */
-#define TSI108_RX_OVER	(1 << 9)	/* FIFO overrun occured */
+#define TSI108_RX_OVER	(1 << 9)	/* FIFO overrun occurred */
 #define TSI108_RX_TRUNC	(1 << 11)	/* Packet truncated due to excess length */
 #define TSI108_RX_CRC	(1 << 12)	/* Packet had a CRC error */
 #define TSI108_RX_INT	(1 << 13)	/* Generate an IRQ after frag. processed */
diff -druN linux-libre-2.6.38-gnu/drivers/net/tulip/de4x5.c linux-libre-2.6.39-gnu/drivers/net/tulip/de4x5.c
--- linux-libre-2.6.38-gnu/drivers/net/tulip/de4x5.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tulip/de4x5.c	2011-05-19 00:06:34.000000000 -0400
@@ -79,7 +79,7 @@
     every  usable DECchip board,  I  pinched Donald's 'next_module' field to
     link my modules together.
 
-    Upto 15 EISA cards can be supported under this driver, limited primarily
+    Up to 15 EISA cards can be supported under this driver, limited primarily
     by the available IRQ lines.  I have  checked different configurations of
     multiple depca, EtherWORKS 3 cards and de4x5 cards and  have not found a
     problem yet (provided you have at least depca.c v0.38) ...
@@ -517,7 +517,7 @@
     u_int mci;              /* 21142 MII Connector Interrupt info        */
 };
 
-#define DE4X5_MAX_PHY 8     /* Allow upto 8 attached PHY devices per board */
+#define DE4X5_MAX_PHY 8     /* Allow up to 8 attached PHY devices per board */
 
 struct sia_phy {
     u_char mc;              /* Media Code                                */
@@ -1436,7 +1436,7 @@
 
     /* Poll for setup frame completion (adapter interrupts are disabled now) */
 
-    for (j=0, i=0;(i<500) && (j==0);i++) {       /* Upto 500ms delay */
+    for (j=0, i=0;(i<500) && (j==0);i++) {       /* Up to 500ms delay */
 	mdelay(1);
 	if ((s32)le32_to_cpu(lp->tx_ring[lp->tx_new].status) >= 0) j=1;
     }
diff -druN linux-libre-2.6.38-gnu/drivers/net/tulip/dmfe.c linux-libre-2.6.39-gnu/drivers/net/tulip/dmfe.c
--- linux-libre-2.6.38-gnu/drivers/net/tulip/dmfe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tulip/dmfe.c	2011-05-19 00:06:34.000000000 -0400
@@ -1224,7 +1224,7 @@
 
 
 	/* If chip reports that link is failed it could be because external
-		PHY link status pin is not conected correctly to chip
+		PHY link status pin is not connected correctly to chip
 		To be sure ask PHY too.
 	*/
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/tulip/eeprom.c linux-libre-2.6.39-gnu/drivers/net/tulip/eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/tulip/eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tulip/eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,7 @@
 			  0x02,       /* phy reset sequence length */
 			  0x01, 0x00, /* phy reset sequence */
 			  0x00, 0x78, /* media capabilities */
-			  0x00, 0xe0, /* nway advertisment */
+			  0x00, 0xe0, /* nway advertisement */
 			  0x00, 0x05, /* fdx bit map */
 			  0x00, 0x06  /* ttm bit map */
 			};
diff -druN linux-libre-2.6.38-gnu/drivers/net/tun.c linux-libre-2.6.39-gnu/drivers/net/tun.c
--- linux-libre-2.6.38-gnu/drivers/net/tun.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/tun.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,8 @@
  *    Modifications for 2.3.99-pre5 kernel.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define DRV_NAME	"tun"
 #define DRV_VERSION	"1.6"
 #define DRV_DESCRIPTION	"Universal TUN/TAP device driver"
@@ -76,11 +78,27 @@
 #ifdef TUN_DEBUG
 static int debug;
 
-#define DBG  if(tun->debug)printk
-#define DBG1 if(debug==2)printk
+#define tun_debug(level, tun, fmt, args...)			\
+do {								\
+	if (tun->debug)						\
+		netdev_printk(level, tun->dev, fmt, ##args);	\
+} while (0)
+#define DBG1(level, fmt, args...)				\
+do {								\
+	if (debug == 2)						\
+		printk(level fmt, ##args);			\
+} while (0)
 #else
-#define DBG( a... )
-#define DBG1( a... )
+#define tun_debug(level, tun, fmt, args...)			\
+do {								\
+	if (0)							\
+		netdev_printk(level, tun->dev, fmt, ##args);	\
+} while (0)
+#define DBG1(level, fmt, args...)				\
+do {								\
+	if (0)							\
+		printk(level fmt, ##args);			\
+} while (0)
 #endif
 
 #define FLT_EXACT_COUNT 8
@@ -205,7 +223,7 @@
 		tun_detach(tfile->tun);
 }
 
-/* TAP filterting */
+/* TAP filtering */
 static void addr_hash_set(u32 *mask, const u8 *addr)
 {
 	int n = ether_crc(ETH_ALEN, addr) >> 26;
@@ -360,7 +378,7 @@
 {
 	struct tun_struct *tun = netdev_priv(dev);
 
-	DBG(KERN_INFO "%s: tun_net_xmit %d\n", tun->dev->name, skb->len);
+	tun_debug(KERN_INFO, tun, "tun_net_xmit %d\n", skb->len);
 
 	/* Drop packet if interface is not attached */
 	if (!tun->tfile)
@@ -499,7 +517,7 @@
 
 	sk = tun->socket.sk;
 
-	DBG(KERN_INFO "%s: tun_chr_poll\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_chr_poll\n");
 
 	poll_wait(file, &tun->wq.wait, wait);
 
@@ -690,7 +708,7 @@
 	if (!tun)
 		return -EBADFD;
 
-	DBG(KERN_INFO "%s: tun_chr_write %ld\n", tun->dev->name, count);
+	tun_debug(KERN_INFO, tun, "tun_chr_write %ld\n", count);
 
 	result = tun_get_user(tun, iv, iov_length(iv, count),
 			      file->f_flags & O_NONBLOCK);
@@ -739,7 +757,7 @@
 			else if (sinfo->gso_type & SKB_GSO_UDP)
 				gso.gso_type = VIRTIO_NET_HDR_GSO_UDP;
 			else {
-				printk(KERN_ERR "tun: unexpected GSO type: "
+				pr_err("unexpected GSO type: "
 				       "0x%x, gso_size %d, hdr_len %d\n",
 				       sinfo->gso_type, gso.gso_size,
 				       gso.hdr_len);
@@ -786,7 +804,7 @@
 	struct sk_buff *skb;
 	ssize_t ret = 0;
 
-	DBG(KERN_INFO "%s: tun_chr_read\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_chr_read\n");
 
 	add_wait_queue(&tun->wq.wait, &wait);
 	while (len) {
@@ -1083,7 +1101,7 @@
 		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");
+			pr_err("Failed to create tun sysfs files\n");
 
 		sk->sk_destruct = tun_sock_destruct;
 
@@ -1092,7 +1110,7 @@
 			goto failed;
 	}
 
-	DBG(KERN_INFO "%s: tun_set_iff\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_set_iff\n");
 
 	if (ifr->ifr_flags & IFF_NO_PI)
 		tun->flags |= TUN_NO_PI;
@@ -1129,7 +1147,7 @@
 static int tun_get_iff(struct net *net, struct tun_struct *tun,
 		       struct ifreq *ifr)
 {
-	DBG(KERN_INFO "%s: tun_get_iff\n", tun->dev->name);
+	tun_debug(KERN_INFO, tun, "tun_get_iff\n");
 
 	strcpy(ifr->ifr_name, tun->dev->name);
 
@@ -1142,7 +1160,7 @@
  * privs required. */
 static int set_offload(struct net_device *dev, unsigned long arg)
 {
-	unsigned int old_features, features;
+	u32 old_features, features;
 
 	old_features = dev->features;
 	/* Unset features, set them as we chew on the arg. */
@@ -1229,7 +1247,7 @@
 	if (!tun)
 		goto unlock;
 
-	DBG(KERN_INFO "%s: tun_chr_ioctl cmd %d\n", tun->dev->name, cmd);
+	tun_debug(KERN_INFO, tun, "tun_chr_ioctl cmd %d\n", cmd);
 
 	ret = 0;
 	switch (cmd) {
@@ -1249,8 +1267,8 @@
 		else
 			tun->flags &= ~TUN_NOCHECKSUM;
 
-		DBG(KERN_INFO "%s: checksum %s\n",
-		    tun->dev->name, arg ? "disabled" : "enabled");
+		tun_debug(KERN_INFO, tun, "checksum %s\n",
+			  arg ? "disabled" : "enabled");
 		break;
 
 	case TUNSETPERSIST:
@@ -1260,33 +1278,34 @@
 		else
 			tun->flags &= ~TUN_PERSIST;
 
-		DBG(KERN_INFO "%s: persist %s\n",
-		    tun->dev->name, arg ? "enabled" : "disabled");
+		tun_debug(KERN_INFO, tun, "persist %s\n",
+			  arg ? "enabled" : "disabled");
 		break;
 
 	case TUNSETOWNER:
 		/* Set owner of the device */
 		tun->owner = (uid_t) arg;
 
-		DBG(KERN_INFO "%s: owner set to %d\n", tun->dev->name, tun->owner);
+		tun_debug(KERN_INFO, tun, "owner set to %d\n", tun->owner);
 		break;
 
 	case TUNSETGROUP:
 		/* Set group of the device */
 		tun->group= (gid_t) arg;
 
-		DBG(KERN_INFO "%s: group set to %d\n", tun->dev->name, tun->group);
+		tun_debug(KERN_INFO, tun, "group set to %d\n", tun->group);
 		break;
 
 	case TUNSETLINK:
 		/* Only allow setting the type when the interface is down */
 		if (tun->dev->flags & IFF_UP) {
-			DBG(KERN_INFO "%s: Linktype set failed because interface is up\n",
-				tun->dev->name);
+			tun_debug(KERN_INFO, tun,
+				  "Linktype set failed because interface is up\n");
 			ret = -EBUSY;
 		} else {
 			tun->dev->type = (int) arg;
-			DBG(KERN_INFO "%s: linktype set to %d\n", tun->dev->name, tun->dev->type);
+			tun_debug(KERN_INFO, tun, "linktype set to %d\n",
+				  tun->dev->type);
 			ret = 0;
 		}
 		break;
@@ -1318,8 +1337,8 @@
 
 	case SIOCSIFHWADDR:
 		/* Set hw address */
-		DBG(KERN_DEBUG "%s: set hw address: %pM\n",
-			tun->dev->name, ifr.ifr_hwaddr.sa_data);
+		tun_debug(KERN_DEBUG, tun, "set hw address: %pM\n",
+			  ifr.ifr_hwaddr.sa_data);
 
 		ret = dev_set_mac_address(tun->dev, &ifr.ifr_hwaddr);
 		break;
@@ -1433,7 +1452,7 @@
 	if (!tun)
 		return -EBADFD;
 
-	DBG(KERN_INFO "%s: tun_chr_fasync %d\n", tun->dev->name, on);
+	tun_debug(KERN_INFO, tun, "tun_chr_fasync %d\n", on);
 
 	if ((ret = fasync_helper(fd, file, on, &tun->fasync)) < 0)
 		goto out;
@@ -1455,7 +1474,7 @@
 {
 	struct tun_file *tfile;
 
-	DBG1(KERN_INFO "tunX: tun_chr_open\n");
+	DBG1(KERN_INFO, "tunX: tun_chr_open\n");
 
 	tfile = kmalloc(sizeof(*tfile), GFP_KERNEL);
 	if (!tfile)
@@ -1476,7 +1495,7 @@
 	if (tun) {
 		struct net_device *dev = tun->dev;
 
-		DBG(KERN_INFO "%s: tun_chr_close\n", dev->name);
+		tun_debug(KERN_INFO, tun, "tun_chr_close\n");
 
 		__tun_detach(tun);
 
@@ -1607,18 +1626,18 @@
 {
 	int ret = 0;
 
-	printk(KERN_INFO "tun: %s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
-	printk(KERN_INFO "tun: %s\n", DRV_COPYRIGHT);
+	pr_info("%s, %s\n", DRV_DESCRIPTION, DRV_VERSION);
+	pr_info("%s\n", DRV_COPYRIGHT);
 
 	ret = rtnl_link_register(&tun_link_ops);
 	if (ret) {
-		printk(KERN_ERR "tun: Can't register link_ops\n");
+		pr_err("Can't register link_ops\n");
 		goto err_linkops;
 	}
 
 	ret = misc_register(&tun_miscdev);
 	if (ret) {
-		printk(KERN_ERR "tun: Can't register misc device %d\n", TUN_MINOR);
+		pr_err("Can't register misc device %d\n", TUN_MINOR);
 		goto err_misc;
 	}
 	return  0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/typhoon.c linux-libre-2.6.39-gnu/drivers/net/typhoon.c
--- linux-libre-2.6.38-gnu/drivers/net/typhoon.c	2012-03-24 01:09:18.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/typhoon.c	2012-03-24 03:31:36.000000000 -0400
@@ -123,12 +123,11 @@
 #include <linux/in6.h>
 #include <linux/dma-mapping.h>
 #include <linux/firmware.h>
-#include <generated/utsrelease.h>
 
 #include "typhoon.h"
 
 MODULE_AUTHOR("David Dillow <dave@thedillows.org>");
-MODULE_VERSION(UTS_RELEASE);
+MODULE_VERSION("1.0");
 MODULE_LICENSE("GPL");
 /*(DEBLOBBED)*/
 MODULE_DESCRIPTION("3Com Typhoon Family (3C990, 3CR990, and variants)");
@@ -847,7 +846,7 @@
 	if(typhoon_num_free_tx(txRing) < (numDesc + 2)) {
 		netif_stop_queue(dev);
 
-		/* A Tx complete IRQ could have gotten inbetween, making
+		/* A Tx complete IRQ could have gotten between, making
 		 * the ring free again. Only need to recheck here, since
 		 * Tx is serialized.
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/ucc_geth.c linux-libre-2.6.39-gnu/drivers/net/ucc_geth.c
--- linux-libre-2.6.38-gnu/drivers/net/ucc_geth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ucc_geth.c	2011-05-19 00:06:34.000000000 -0400
@@ -3740,7 +3740,7 @@
 #endif
 };
 
-static int ucc_geth_probe(struct platform_device* ofdev, const struct of_device_id *match)
+static int ucc_geth_probe(struct platform_device* ofdev)
 {
 	struct device *device = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -3986,7 +3986,7 @@
 
 MODULE_DEVICE_TABLE(of, ucc_geth_match);
 
-static struct of_platform_driver ucc_geth_driver = {
+static struct platform_driver ucc_geth_driver = {
 	.driver = {
 		.name = DRV_NAME,
 		.owner = THIS_MODULE,
@@ -4008,14 +4008,14 @@
 		memcpy(&(ugeth_info[i]), &ugeth_primary_info,
 		       sizeof(ugeth_primary_info));
 
-	ret = of_register_platform_driver(&ucc_geth_driver);
+	ret = platform_driver_register(&ucc_geth_driver);
 
 	return ret;
 }
 
 static void __exit ucc_geth_exit(void)
 {
-	of_unregister_platform_driver(&ucc_geth_driver);
+	platform_driver_unregister(&ucc_geth_driver);
 }
 
 module_init(ucc_geth_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/ucc_geth.h linux-libre-2.6.39-gnu/drivers/net/ucc_geth.h
--- linux-libre-2.6.38-gnu/drivers/net/ucc_geth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/ucc_geth.h	2011-05-19 00:06:34.000000000 -0400
@@ -80,7 +80,7 @@
 				   frames) received that were between 128
 				   (Including FCS length==4) and 255 octets */
 	u32 txok;		/* Total number of octets residing in frames
-				   that where involved in successfull
+				   that where involved in successful
 				   transmission */
 	u16 txcf;		/* Total number of PAUSE control frames
 				   transmitted by this MAC */
@@ -759,7 +759,7 @@
 				   frames) received that were between 128
 				   (Including FCS length==4) and 255 octets */
 	u32 txok;		/* Total number of octets residing in frames
-				   that where involved in successfull
+				   that where involved in successful
 				   transmission */
 	u16 txcf;		/* Total number of PAUSE control frames
 				   transmitted by this MAC */
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc_eem.c linux-libre-2.6.39-gnu/drivers/net/usb/cdc_eem.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc_eem.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/cdc_eem.c	2011-05-19 00:06:34.000000000 -0400
@@ -190,7 +190,7 @@
 
 		/*
 		 * EEM packet header format:
-		 * b0..14:	EEM type dependant (Data or Command)
+		 * b0..14:	EEM type dependent (Data or Command)
 		 * b15:		bmType
 		 */
 		header = get_unaligned_le16(skb->data);
@@ -340,7 +340,7 @@
 
 static const struct driver_info eem_info = {
 	.description =	"CDC EEM Device",
-	.flags =	FLAG_ETHER,
+	.flags =	FLAG_ETHER | FLAG_POINTTOPOINT,
 	.bind =		eem_bind,
 	.rx_fixup =	eem_rx_fixup,
 	.tx_fixup =	eem_tx_fixup,
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc_ether.c linux-libre-2.6.39-gnu/drivers/net/usb/cdc_ether.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc_ether.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/cdc_ether.c	2011-05-19 00:06:34.000000000 -0400
@@ -378,7 +378,7 @@
 		   __le32_to_cpu(speeds[1]) / 1000);
 }
 
-static void cdc_status(struct usbnet *dev, struct urb *urb)
+void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
 {
 	struct usb_cdc_notification	*event;
 
@@ -418,8 +418,9 @@
 		break;
 	}
 }
+EXPORT_SYMBOL_GPL(usbnet_cdc_status);
 
-static int cdc_bind(struct usbnet *dev, struct usb_interface *intf)
+int usbnet_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int				status;
 	struct cdc_state		*info = (void *) &dev->data;
@@ -441,6 +442,7 @@
 	 */
 	return 0;
 }
+EXPORT_SYMBOL_GPL(usbnet_cdc_bind);
 
 static int cdc_manage_power(struct usbnet *dev, int on)
 {
@@ -450,25 +452,26 @@
 
 static const struct driver_info	cdc_info = {
 	.description =	"CDC Ethernet Device",
-	.flags =	FLAG_ETHER,
+	.flags =	FLAG_ETHER | FLAG_POINTTOPOINT,
 	// .check_connect = cdc_check_connect,
-	.bind =		cdc_bind,
+	.bind =		usbnet_cdc_bind,
 	.unbind =	usbnet_cdc_unbind,
-	.status =	cdc_status,
+	.status =	usbnet_cdc_status,
 	.manage_power =	cdc_manage_power,
 };
 
-static const struct driver_info mbm_info = {
+static const struct driver_info wwan_info = {
 	.description =	"Mobile Broadband Network Device",
 	.flags =	FLAG_WWAN,
-	.bind = 	cdc_bind,
+	.bind =		usbnet_cdc_bind,
 	.unbind =	usbnet_cdc_unbind,
-	.status =	cdc_status,
+	.status =	usbnet_cdc_status,
 	.manage_power =	cdc_manage_power,
 };
 
 /*-------------------------------------------------------------------------*/
 
+#define HUAWEI_VENDOR_ID	0x12D1
 
 static const struct usb_device_id	products [] = {
 /*
@@ -560,6 +563,13 @@
 	.driver_info		= 0,
 },
 
+/* LG Electronics VL600 wants additional headers on every frame */
+{
+	USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
+			USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+	.driver_info = (unsigned long)&wwan_info,
+},
+
 /*
  * WHITELIST!!!
  *
@@ -578,8 +588,17 @@
 }, {
 	USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MDLM,
 			USB_CDC_PROTO_NONE),
-	.driver_info = (unsigned long)&mbm_info,
+	.driver_info = (unsigned long)&wwan_info,
 
+}, {
+	/* Various Huawei modems with a network port like the UMG1831 */
+	.match_flags    =   USB_DEVICE_ID_MATCH_VENDOR
+		 | USB_DEVICE_ID_MATCH_INT_INFO,
+	.idVendor               = HUAWEI_VENDOR_ID,
+	.bInterfaceClass	= USB_CLASS_COMM,
+	.bInterfaceSubClass	= USB_CDC_SUBCLASS_ETHERNET,
+	.bInterfaceProtocol	= 255,
+	.driver_info = (unsigned long)&wwan_info,
 },
 	{ },		// END
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc_ncm.c linux-libre-2.6.39-gnu/drivers/net/usb/cdc_ncm.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc_ncm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/cdc_ncm.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,13 +54,13 @@
 #include <linux/usb/usbnet.h>
 #include <linux/usb/cdc.h>
 
-#define	DRIVER_VERSION				"7-Feb-2011"
+#define	DRIVER_VERSION				"23-Apr-2011"
 
 /* CDC NCM subclass 3.2.1 */
 #define USB_CDC_NCM_NDP16_LENGTH_MIN		0x10
 
 /* Maximum NTB length */
-#define	CDC_NCM_NTB_MAX_SIZE_TX			16384	/* bytes */
+#define	CDC_NCM_NTB_MAX_SIZE_TX			(16384 + 4) /* bytes, must be short terminated */
 #define	CDC_NCM_NTB_MAX_SIZE_RX			16384	/* bytes */
 
 /* Minimum value for MaxDatagramSize, ch. 6.2.9 */
@@ -1237,7 +1237,7 @@
 
 static const struct driver_info cdc_ncm_info = {
 	.description = "CDC NCM",
-	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET,
+	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET,
 	.bind = cdc_ncm_bind,
 	.unbind = cdc_ncm_unbind,
 	.check_connect = cdc_ncm_check_connect,
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc-phonet.c linux-libre-2.6.39-gnu/drivers/net/usb/cdc-phonet.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc-phonet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/cdc-phonet.c	2011-05-19 00:06:34.000000000 -0400
@@ -328,13 +328,13 @@
 {
 	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 phonet = 0;
 	int len, err;
 
 	data = intf->altsetting->extra;
@@ -355,10 +355,7 @@
 					(struct usb_cdc_union_desc *)data;
 				break;
 			case 0xAB:
-				if (phonet_header || dlen < 5)
-					break;
-				phonet_header =
-					(struct usb_cdc_header_desc *)data;
+				phonet = 1;
 				break;
 			}
 		}
@@ -366,7 +363,7 @@
 		len -= dlen;
 	}
 
-	if (!union_header || !phonet_header)
+	if (!union_header || !phonet)
 		return -EINVAL;
 
 	data_intf = usb_ifnum_to_if(usbdev, union_header->bSlaveInterface0);
@@ -392,7 +389,6 @@
 
 	pnd = netdev_priv(dev);
 	SET_NETDEV_DEV(dev, &intf->dev);
-	netif_stop_queue(dev);
 
 	pnd->dev = dev;
 	pnd->usb = usb_get_dev(usbdev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/cdc_subset.c linux-libre-2.6.39-gnu/drivers/net/usb/cdc_subset.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/cdc_subset.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/cdc_subset.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,6 +89,7 @@
 
 static const struct driver_info	ali_m5632_info = {
 	.description =	"ALi M5632",
+	.flags       = FLAG_POINTTOPOINT,
 };
 
 #endif
@@ -110,6 +111,7 @@
 
 static const struct driver_info	an2720_info = {
 	.description =	"AnchorChips/Cypress 2720",
+	.flags       = FLAG_POINTTOPOINT,
 	// no reset available!
 	// no check_connect available!
 
@@ -132,6 +134,7 @@
 
 static const struct driver_info	belkin_info = {
 	.description =	"Belkin, eTEK, or compatible",
+	.flags       = FLAG_POINTTOPOINT,
 };
 
 #endif	/* CONFIG_USB_BELKIN */
@@ -157,6 +160,7 @@
 static const struct driver_info	epson2888_info = {
 	.description =	"Epson USB Device",
 	.check_connect = always_connected,
+	.flags = FLAG_POINTTOPOINT,
 
 	.in = 4, .out = 3,
 };
@@ -173,6 +177,7 @@
 #define HAVE_HARDWARE
 static const struct driver_info kc2190_info = {
 	.description =  "KC Technology KC-190",
+	.flags = FLAG_POINTTOPOINT,
 };
 #endif /* CONFIG_USB_KC2190 */
 
@@ -200,16 +205,19 @@
 static const struct driver_info	linuxdev_info = {
 	.description =	"Linux Device",
 	.check_connect = always_connected,
+	.flags = FLAG_POINTTOPOINT,
 };
 
 static const struct driver_info	yopy_info = {
 	.description =	"Yopy",
 	.check_connect = always_connected,
+	.flags = FLAG_POINTTOPOINT,
 };
 
 static const struct driver_info	blob_info = {
 	.description =	"Boot Loader OBject",
 	.check_connect = always_connected,
+	.flags = FLAG_POINTTOPOINT,
 };
 
 #endif	/* CONFIG_USB_ARMLINUX */
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/gl620a.c linux-libre-2.6.39-gnu/drivers/net/usb/gl620a.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/gl620a.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/gl620a.c	2011-05-19 00:06:34.000000000 -0400
@@ -193,7 +193,7 @@
 
 static const struct driver_info	genelink_info = {
 	.description =	"Genesys GeneLink",
-	.flags =	FLAG_FRAMING_GL | FLAG_NO_SETINT,
+	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_GL | FLAG_NO_SETINT,
 	.bind =		genelink_bind,
 	.rx_fixup =	genelink_rx_fixup,
 	.tx_fixup =	genelink_tx_fixup,
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/hso.c linux-libre-2.6.39-gnu/drivers/net/usb/hso.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/hso.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/hso.c	2011-05-19 00:06:34.000000000 -0400
@@ -324,7 +324,7 @@
 /* Prototypes                                                                */
 /*****************************************************************************/
 /* Serial driver functions */
-static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
+static int hso_serial_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear);
 static void ctrl_callback(struct urb *urb);
 static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial);
@@ -1335,7 +1335,7 @@
 
 	/* done */
 	if (result)
-		hso_serial_tiocmset(tty, NULL, TIOCM_RTS | TIOCM_DTR, 0);
+		hso_serial_tiocmset(tty, TIOCM_RTS | TIOCM_DTR, 0);
 err_out:
 	mutex_unlock(&serial->parent->mutex);
 	return result;
@@ -1656,7 +1656,7 @@
 }
 
 
-static int hso_serial_tiocmget(struct tty_struct *tty, struct file *file)
+static int hso_serial_tiocmget(struct tty_struct *tty)
 {
 	int retval;
 	struct hso_serial *serial = get_serial_by_tty(tty);
@@ -1687,7 +1687,7 @@
 	return retval;
 }
 
-static int hso_serial_tiocmset(struct tty_struct *tty, struct file *file,
+static int hso_serial_tiocmset(struct tty_struct *tty,
 			       unsigned int set, unsigned int clear)
 {
 	int val = 0;
@@ -1730,7 +1730,7 @@
 			       USB_CTRL_SET_TIMEOUT);
 }
 
-static int hso_serial_ioctl(struct tty_struct *tty, struct file *file,
+static int hso_serial_ioctl(struct tty_struct *tty,
 			    unsigned int cmd, unsigned long arg)
 {
 	struct hso_serial *serial =  get_serial_by_tty(tty);
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/ipheth.c linux-libre-2.6.39-gnu/drivers/net/usb/ipheth.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/ipheth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/ipheth.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,6 +65,7 @@
 #define IPHETH_USBINTF_PROTO    1
 
 #define IPHETH_BUF_SIZE         1516
+#define IPHETH_IP_ALIGN		2	/* padding at front of URB */
 #define IPHETH_TX_TIMEOUT       (5 * HZ)
 
 #define IPHETH_INTFNUM          2
@@ -202,18 +203,21 @@
 		return;
 	}
 
-	len = urb->actual_length;
-	buf = urb->transfer_buffer;
+	if (urb->actual_length <= IPHETH_IP_ALIGN) {
+		dev->net->stats.rx_length_errors++;
+		return;
+	}
+	len = urb->actual_length - IPHETH_IP_ALIGN;
+	buf = urb->transfer_buffer + IPHETH_IP_ALIGN;
 
-	skb = dev_alloc_skb(NET_IP_ALIGN + len);
+	skb = dev_alloc_skb(len);
 	if (!skb) {
 		err("%s: dev_alloc_skb: -ENOMEM", __func__);
 		dev->net->stats.rx_dropped++;
 		return;
 	}
 
-	skb_reserve(skb, NET_IP_ALIGN);
-	memcpy(skb_put(skb, len), buf + NET_IP_ALIGN, len - NET_IP_ALIGN);
+	memcpy(skb_put(skb, len), buf, len);
 	skb->dev = dev->net;
 	skb->protocol = eth_type_trans(skb, dev->net);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/kaweth.c linux-libre-2.6.39-gnu/drivers/net/usb/kaweth.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/kaweth.c	2012-03-24 01:10:17.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/kaweth.c	2012-03-24 03:32:05.000000000 -0400
@@ -1218,7 +1218,7 @@
 
 	usb_set_intfdata(intf, NULL);
 	if (!kaweth) {
-		dev_warn(&intf->dev, "unregistering non-existant device\n");
+		dev_warn(&intf->dev, "unregistering non-existent device\n");
 		return;
 	}
 	netdev = kaweth->net;
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/Kconfig linux-libre-2.6.39-gnu/drivers/net/usb/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/usb/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -433,4 +433,19 @@
 	  To compile this driver as a module, choose M here: the
 	  module will be called sierra_net.
 
+config USB_VL600
+	tristate "LG VL600 modem dongle"
+	depends on USB_NET_CDCETHER
+	select USB_ACM
+	help
+	  Select this if you want to use an LG Electronics 4G/LTE usb modem
+	  called VL600.  This driver only handles the ethernet
+	  interface exposed by the modem firmware.  To establish a connection
+	  you will first need a userspace program that sends the right
+	  command to the modem through its CDC ACM port, and most
+	  likely also a DHCP client.  See this thread about using the
+	  4G modem from Verizon:
+
+	  http://ubuntuforums.org/showpost.php?p=10589647&postcount=17
+
 endmenu
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/lg-vl600.c linux-libre-2.6.39-gnu/drivers/net/usb/lg-vl600.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/lg-vl600.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/usb/lg-vl600.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,346 @@
+/*
+ * Ethernet interface part of the LG VL600 LTE modem (4G dongle)
+ *
+ * Copyright (C) 2011 Intel Corporation
+ * Author: Andrzej Zaborowski <balrogg@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/mii.h>
+#include <linux/usb.h>
+#include <linux/usb/cdc.h>
+#include <linux/usb/usbnet.h>
+#include <linux/if_ether.h>
+#include <linux/if_arp.h>
+#include <linux/inetdevice.h>
+
+/*
+ * The device has a CDC ACM port for modem control (it claims to be
+ * CDC ACM anyway) and a CDC Ethernet port for actual network data.
+ * It will however ignore data on both ports that is not encapsulated
+ * in a specific way, any data returned is also encapsulated the same
+ * way.  The headers don't seem to follow any popular standard.
+ *
+ * This driver adds and strips these headers from the ethernet frames
+ * sent/received from the CDC Ethernet port.  The proprietary header
+ * replaces the standard ethernet header in a packet so only actual
+ * ethernet frames are allowed.  The headers allow some form of
+ * multiplexing by using non standard values of the .h_proto field.
+ * Windows/Mac drivers do send a couple of such frames to the device
+ * during initialisation, with protocol set to 0x0906 or 0x0b06 and (what
+ * seems to be) a flag in the .dummy_flags.  This doesn't seem necessary
+ * for modem operation but can possibly be used for GPS or other funcitons.
+ */
+
+struct vl600_frame_hdr {
+	__le32 len;
+	__le32 serial;
+	__le32 pkt_cnt;
+	__le32 dummy_flags;
+	__le32 dummy;
+	__le32 magic;
+} __attribute__((packed));
+
+struct vl600_pkt_hdr {
+	__le32 dummy[2];
+	__le32 len;
+	__be16 h_proto;
+} __attribute__((packed));
+
+struct vl600_state {
+	struct sk_buff *current_rx_buf;
+};
+
+static int vl600_bind(struct usbnet *dev, struct usb_interface *intf)
+{
+	int ret;
+	struct vl600_state *s = kzalloc(sizeof(struct vl600_state), GFP_KERNEL);
+
+	if (!s)
+		return -ENOMEM;
+
+	ret = usbnet_cdc_bind(dev, intf);
+	if (ret) {
+		kfree(s);
+		return ret;
+	}
+
+	dev->driver_priv = s;
+
+	/* ARP packets don't go through, but they're also of no use.  The
+	 * subnet has only two hosts anyway: us and the gateway / DHCP
+	 * server (probably simulated by modem firmware or network operator)
+	 * whose address changes everytime we connect to the intarwebz and
+	 * who doesn't bother answering ARP requests either.  So hardware
+	 * addresses have no meaning, the destination and the source of every
+	 * packet depend only on whether it is on the IN or OUT endpoint.  */
+	dev->net->flags |= IFF_NOARP;
+
+	return ret;
+}
+
+static void vl600_unbind(struct usbnet *dev, struct usb_interface *intf)
+{
+	struct vl600_state *s = dev->driver_priv;
+
+	if (s->current_rx_buf)
+		dev_kfree_skb(s->current_rx_buf);
+
+	kfree(s);
+
+	return usbnet_cdc_unbind(dev, intf);
+}
+
+static int vl600_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
+{
+	struct vl600_frame_hdr *frame;
+	struct vl600_pkt_hdr *packet;
+	struct ethhdr *ethhdr;
+	int packet_len, count;
+	struct sk_buff *buf = skb;
+	struct sk_buff *clone;
+	struct vl600_state *s = dev->driver_priv;
+
+	/* Frame lengths are generally 4B multiplies but every couple of
+	 * hours there's an odd number of bytes sized yet correct frame,
+	 * so don't require this.  */
+
+	/* Allow a packet (or multiple packets batched together) to be
+	 * split across many frames.  We don't allow a new batch to
+	 * begin in the same frame another one is ending however, and no
+	 * leading or trailing pad bytes.  */
+	if (s->current_rx_buf) {
+		frame = (struct vl600_frame_hdr *) s->current_rx_buf->data;
+		if (skb->len + s->current_rx_buf->len >
+				le32_to_cpup(&frame->len)) {
+			netif_err(dev, ifup, dev->net, "Fragment too long\n");
+			dev->net->stats.rx_length_errors++;
+			goto error;
+		}
+
+		buf = s->current_rx_buf;
+		memcpy(skb_put(buf, skb->len), skb->data, skb->len);
+	} else if (skb->len < 4) {
+		netif_err(dev, ifup, dev->net, "Frame too short\n");
+		dev->net->stats.rx_length_errors++;
+		goto error;
+	}
+
+	frame = (struct vl600_frame_hdr *) buf->data;
+	/* NOTE: Should check that frame->magic == 0x53544448?
+	 * Otherwise if we receive garbage at the beginning of the frame
+	 * we may end up allocating a huge buffer and saving all the
+	 * future incoming data into it.  */
+
+	if (buf->len < sizeof(*frame) ||
+			buf->len != le32_to_cpup(&frame->len)) {
+		/* Save this fragment for later assembly */
+		if (s->current_rx_buf)
+			return 0;
+
+		s->current_rx_buf = skb_copy_expand(skb, 0,
+				le32_to_cpup(&frame->len), GFP_ATOMIC);
+		if (!s->current_rx_buf) {
+			netif_err(dev, ifup, dev->net, "Reserving %i bytes "
+					"for packet assembly failed.\n",
+					le32_to_cpup(&frame->len));
+			dev->net->stats.rx_errors++;
+		}
+
+		return 0;
+	}
+
+	count = le32_to_cpup(&frame->pkt_cnt);
+
+	skb_pull(buf, sizeof(*frame));
+
+	while (count--) {
+		if (buf->len < sizeof(*packet)) {
+			netif_err(dev, ifup, dev->net, "Packet too short\n");
+			goto error;
+		}
+
+		packet = (struct vl600_pkt_hdr *) buf->data;
+		packet_len = sizeof(*packet) + le32_to_cpup(&packet->len);
+		if (packet_len > buf->len) {
+			netif_err(dev, ifup, dev->net,
+					"Bad packet length stored in header\n");
+			goto error;
+		}
+
+		/* Packet header is same size as the ethernet header
+		 * (sizeof(*packet) == sizeof(*ethhdr)), additionally
+		 * the h_proto field is in the same place so we just leave it
+		 * alone and fill in the remaining fields.
+		 */
+		ethhdr = (struct ethhdr *) skb->data;
+		if (be16_to_cpup(&ethhdr->h_proto) == ETH_P_ARP &&
+				buf->len > 0x26) {
+			/* Copy the addresses from packet contents */
+			memcpy(ethhdr->h_source,
+					&buf->data[sizeof(*ethhdr) + 0x8],
+					ETH_ALEN);
+			memcpy(ethhdr->h_dest,
+					&buf->data[sizeof(*ethhdr) + 0x12],
+					ETH_ALEN);
+		} else {
+			memset(ethhdr->h_source, 0, ETH_ALEN);
+			memcpy(ethhdr->h_dest, dev->net->dev_addr, ETH_ALEN);
+		}
+
+		if (count) {
+			/* Not the last packet in this batch */
+			clone = skb_clone(buf, GFP_ATOMIC);
+			if (!clone)
+				goto error;
+
+			skb_trim(clone, packet_len);
+			usbnet_skb_return(dev, clone);
+
+			skb_pull(buf, (packet_len + 3) & ~3);
+		} else {
+			skb_trim(buf, packet_len);
+
+			if (s->current_rx_buf) {
+				usbnet_skb_return(dev, buf);
+				s->current_rx_buf = NULL;
+				return 0;
+			}
+
+			return 1;
+		}
+	}
+
+error:
+	if (s->current_rx_buf) {
+		dev_kfree_skb_any(s->current_rx_buf);
+		s->current_rx_buf = NULL;
+	}
+	dev->net->stats.rx_errors++;
+	return 0;
+}
+
+static struct sk_buff *vl600_tx_fixup(struct usbnet *dev,
+		struct sk_buff *skb, gfp_t flags)
+{
+	struct sk_buff *ret;
+	struct vl600_frame_hdr *frame;
+	struct vl600_pkt_hdr *packet;
+	static uint32_t serial = 1;
+	int orig_len = skb->len - sizeof(struct ethhdr);
+	int full_len = (skb->len + sizeof(struct vl600_frame_hdr) + 3) & ~3;
+
+	frame = (struct vl600_frame_hdr *) skb->data;
+	if (skb->len > sizeof(*frame) && skb->len == le32_to_cpup(&frame->len))
+		return skb; /* Already encapsulated? */
+
+	if (skb->len < sizeof(struct ethhdr))
+		/* Drop, device can only deal with ethernet packets */
+		return NULL;
+
+	if (!skb_cloned(skb)) {
+		int headroom = skb_headroom(skb);
+		int tailroom = skb_tailroom(skb);
+
+		if (tailroom >= full_len - skb->len - sizeof(*frame) &&
+				headroom >= sizeof(*frame))
+			/* There's enough head and tail room */
+			goto encapsulate;
+
+		if (headroom + tailroom + skb->len >= full_len) {
+			/* There's enough total room, just readjust */
+			skb->data = memmove(skb->head + sizeof(*frame),
+					skb->data, skb->len);
+			skb_set_tail_pointer(skb, skb->len);
+			goto encapsulate;
+		}
+	}
+
+	/* Alloc a new skb with the required size */
+	ret = skb_copy_expand(skb, sizeof(struct vl600_frame_hdr), full_len -
+			skb->len - sizeof(struct vl600_frame_hdr), flags);
+	dev_kfree_skb_any(skb);
+	if (!ret)
+		return ret;
+	skb = ret;
+
+encapsulate:
+	/* Packet header is same size as ethernet packet header
+	 * (sizeof(*packet) == sizeof(struct ethhdr)), additionally the
+	 * h_proto field is in the same place so we just leave it alone and
+	 * overwrite the remaining fields.
+	 */
+	packet = (struct vl600_pkt_hdr *) skb->data;
+	memset(&packet->dummy, 0, sizeof(packet->dummy));
+	packet->len = cpu_to_le32(orig_len);
+
+	frame = (struct vl600_frame_hdr *) skb_push(skb, sizeof(*frame));
+	memset(frame, 0, sizeof(*frame));
+	frame->len = cpu_to_le32(full_len);
+	frame->serial = cpu_to_le32(serial++);
+	frame->pkt_cnt = cpu_to_le32(1);
+
+	if (skb->len < full_len) /* Pad */
+		skb_put(skb, full_len - skb->len);
+
+	return skb;
+}
+
+static const struct driver_info	vl600_info = {
+	.description	= "LG VL600 modem",
+	.flags		= FLAG_ETHER | FLAG_RX_ASSEMBLE,
+	.bind		= vl600_bind,
+	.unbind		= vl600_unbind,
+	.status		= usbnet_cdc_status,
+	.rx_fixup	= vl600_rx_fixup,
+	.tx_fixup	= vl600_tx_fixup,
+};
+
+static const struct usb_device_id products[] = {
+	{
+		USB_DEVICE_AND_INTERFACE_INFO(0x1004, 0x61aa, USB_CLASS_COMM,
+				USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+		.driver_info	= (unsigned long) &vl600_info,
+	},
+	{},	/* End */
+};
+MODULE_DEVICE_TABLE(usb, products);
+
+static struct usb_driver lg_vl600_driver = {
+	.name		= "lg-vl600",
+	.id_table	= products,
+	.probe		= usbnet_probe,
+	.disconnect	= usbnet_disconnect,
+	.suspend	= usbnet_suspend,
+	.resume		= usbnet_resume,
+};
+
+static int __init vl600_init(void)
+{
+	return usb_register(&lg_vl600_driver);
+}
+module_init(vl600_init);
+
+static void __exit vl600_exit(void)
+{
+	usb_deregister(&lg_vl600_driver);
+}
+module_exit(vl600_exit);
+
+MODULE_AUTHOR("Anrzej Zaborowski");
+MODULE_DESCRIPTION("LG-VL600 modem's ethernet link");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/Makefile linux-libre-2.6.39-gnu/drivers/net/usb/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/usb/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -27,4 +27,5 @@
 obj-$(CONFIG_USB_SIERRA_NET)	+= sierra_net.o
 obj-$(CONFIG_USB_NET_CX82310_ETH)	+= cx82310_eth.o
 obj-$(CONFIG_USB_NET_CDC_NCM)	+= cdc_ncm.o
+obj-$(CONFIG_USB_VL600)		+= lg-vl600.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/net1080.c linux-libre-2.6.39-gnu/drivers/net/usb/net1080.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/net1080.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/net1080.c	2011-05-19 00:06:34.000000000 -0400
@@ -560,7 +560,7 @@
 
 static const struct driver_info	net1080_info = {
 	.description =	"NetChip TurboCONNECT",
-	.flags =	FLAG_FRAMING_NC,
+	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_NC,
 	.bind =		net1080_bind,
 	.reset =	net1080_reset,
 	.check_connect = net1080_check_connect,
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/plusb.c linux-libre-2.6.39-gnu/drivers/net/usb/plusb.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/plusb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/plusb.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,7 +96,7 @@
 
 static const struct driver_info	prolific_info = {
 	.description =	"Prolific PL-2301/PL-2302",
-	.flags =	FLAG_NO_SETINT,
+	.flags =	FLAG_POINTTOPOINT | FLAG_NO_SETINT,
 		/* some PL-2302 versions seem to fail usb_set_interface() */
 	.reset =	pl_reset,
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/rndis_host.c linux-libre-2.6.39-gnu/drivers/net/usb/rndis_host.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/rndis_host.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/rndis_host.c	2011-05-19 00:06:34.000000000 -0400
@@ -573,7 +573,7 @@
 
 static const struct driver_info	rndis_info = {
 	.description =	"RNDIS device",
-	.flags =	FLAG_ETHER | FLAG_FRAMING_RN | FLAG_NO_SETINT,
+	.flags =	FLAG_ETHER | FLAG_POINTTOPOINT | FLAG_FRAMING_RN | FLAG_NO_SETINT,
 	.bind =		rndis_bind,
 	.unbind =	rndis_unbind,
 	.status =	rndis_status,
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/smsc95xx.c linux-libre-2.6.39-gnu/drivers/net/usb/smsc95xx.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/smsc95xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/smsc95xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,6 +49,8 @@
 
 struct smsc95xx_priv {
 	u32 mac_cr;
+	u32 hash_hi;
+	u32 hash_lo;
 	spinlock_t mac_cr_lock;
 	bool use_tx_csum;
 	bool use_rx_csum;
@@ -370,10 +372,11 @@
 {
 	struct usbnet *dev = netdev_priv(netdev);
 	struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]);
-	u32 hash_hi = 0;
-	u32 hash_lo = 0;
 	unsigned long flags;
 
+	pdata->hash_hi = 0;
+	pdata->hash_lo = 0;
+
 	spin_lock_irqsave(&pdata->mac_cr_lock, flags);
 
 	if (dev->net->flags & IFF_PROMISC) {
@@ -394,13 +397,13 @@
 			u32 bitnum = smsc95xx_hash(ha->addr);
 			u32 mask = 0x01 << (bitnum & 0x1F);
 			if (bitnum & 0x20)
-				hash_hi |= mask;
+				pdata->hash_hi |= mask;
 			else
-				hash_lo |= mask;
+				pdata->hash_lo |= mask;
 		}
 
 		netif_dbg(dev, drv, dev->net, "HASHH=0x%08X, HASHL=0x%08X\n",
-				   hash_hi, hash_lo);
+				   pdata->hash_hi, pdata->hash_lo);
 	} else {
 		netif_dbg(dev, drv, dev->net, "receive own packets only\n");
 		pdata->mac_cr &=
@@ -410,8 +413,8 @@
 	spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
 
 	/* Initiate async writes, as we can't wait for completion here */
-	smsc95xx_write_reg_async(dev, HASHH, &hash_hi);
-	smsc95xx_write_reg_async(dev, HASHL, &hash_lo);
+	smsc95xx_write_reg_async(dev, HASHH, &pdata->hash_hi);
+	smsc95xx_write_reg_async(dev, HASHL, &pdata->hash_lo);
 	smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr);
 }
 
@@ -727,7 +730,7 @@
 		msleep(10);
 		bmcr = smsc95xx_mdio_read(dev->net, dev->mii.phy_id, MII_BMCR);
 		timeout++;
-	} while ((bmcr & MII_BMCR) && (timeout < 100));
+	} while ((bmcr & BMCR_RESET) && (timeout < 100));
 
 	if (timeout >= 100) {
 		netdev_warn(dev->net, "timeout on PHY Reset");
@@ -1310,6 +1313,21 @@
 		USB_DEVICE(0x0424, 0x9909),
 		.driver_info = (unsigned long) &smsc95xx_info,
 	},
+	{
+		/* SMSC LAN9530 USB Ethernet Device */
+		USB_DEVICE(0x0424, 0x9530),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC LAN9730 USB Ethernet Device */
+		USB_DEVICE(0x0424, 0x9730),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
+	{
+		/* SMSC LAN89530 USB Ethernet Device */
+		USB_DEVICE(0x0424, 0x9E08),
+		.driver_info = (unsigned long) &smsc95xx_info,
+	},
 	{ },		/* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/usbnet.c linux-libre-2.6.39-gnu/drivers/net/usb/usbnet.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/usbnet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/usbnet.c	2011-05-19 00:06:34.000000000 -0400
@@ -387,8 +387,12 @@
 static inline void rx_process (struct usbnet *dev, struct sk_buff *skb)
 {
 	if (dev->driver_info->rx_fixup &&
-	    !dev->driver_info->rx_fixup (dev, skb))
-		goto error;
+	    !dev->driver_info->rx_fixup (dev, skb)) {
+		/* With RX_ASSEMBLE, rx_fixup() must update counters */
+		if (!(dev->driver_info->flags & FLAG_RX_ASSEMBLE))
+			dev->net->stats.rx_errors++;
+		goto done;
+	}
 	// else network stack removes extra byte if we forced a short packet
 
 	if (skb->len) {
@@ -401,8 +405,8 @@
 	}
 
 	netif_dbg(dev, rx_err, dev->net, "drop\n");
-error:
 	dev->net->stats.rx_errors++;
+done:
 	skb_queue_tail(&dev->done, skb);
 }
 
@@ -641,6 +645,7 @@
 	struct driver_info	*info = dev->driver_info;
 	int			retval;
 
+	clear_bit(EVENT_DEV_OPEN, &dev->flags);
 	netif_stop_queue (net);
 
 	netif_info(dev, ifdown, dev->net,
@@ -732,6 +737,7 @@
 		}
 	}
 
+	set_bit(EVENT_DEV_OPEN, &dev->flags);
 	netif_start_queue (net);
 	netif_info(dev, ifup, dev->net,
 		   "open: enable queueing (rx %d, tx %d) mtu %d %s framing\n",
@@ -1255,6 +1261,9 @@
 	if (dev->driver_info->unbind)
 		dev->driver_info->unbind (dev, intf);
 
+	usb_kill_urb(dev->interrupt);
+	usb_free_urb(dev->interrupt);
+
 	free_netdev(net);
 	usb_put_dev (xdev);
 }
@@ -1376,7 +1385,8 @@
 		// else "eth%d" when there's reasonable doubt.  userspace
 		// can rename the link if it knows better.
 		if ((dev->driver_info->flags & FLAG_ETHER) != 0 &&
-		    (net->dev_addr [0] & 0x02) == 0)
+		    ((dev->driver_info->flags & FLAG_POINTTOPOINT) == 0 ||
+		     (net->dev_addr [0] & 0x02) == 0))
 			strcpy (net->name, "eth%d");
 		/* WLAN devices should always be named "wlan%d" */
 		if ((dev->driver_info->flags & FLAG_WLAN) != 0)
@@ -1493,6 +1503,10 @@
 	int                     retval;
 
 	if (!--dev->suspend_count) {
+		/* resume interrupt URBs */
+		if (dev->interrupt && test_bit(EVENT_DEV_OPEN, &dev->flags))
+			usb_submit_urb(dev->interrupt, GFP_NOIO);
+
 		spin_lock_irq(&dev->txq.lock);
 		while ((res = usb_get_from_anchor(&dev->deferred))) {
 
@@ -1511,9 +1525,12 @@
 		smp_mb();
 		clear_bit(EVENT_DEV_ASLEEP, &dev->flags);
 		spin_unlock_irq(&dev->txq.lock);
-		if (!(dev->txq.qlen >= TX_QLEN(dev)))
-			netif_start_queue(dev->net);
-		tasklet_schedule (&dev->bh);
+
+		if (test_bit(EVENT_DEV_OPEN, &dev->flags)) {
+			if (!(dev->txq.qlen >= TX_QLEN(dev)))
+				netif_start_queue(dev->net);
+			tasklet_schedule (&dev->bh);
+		}
 	}
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/usb/zaurus.c linux-libre-2.6.39-gnu/drivers/net/usb/zaurus.c
--- linux-libre-2.6.38-gnu/drivers/net/usb/zaurus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/usb/zaurus.c	2011-05-19 00:06:34.000000000 -0400
@@ -102,7 +102,7 @@
 
 static const struct driver_info	zaurus_sl5x00_info = {
 	.description =	"Sharp Zaurus SL-5x00",
-	.flags =	FLAG_FRAMING_Z,
+	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
 	.check_connect = always_connected,
 	.bind =		zaurus_bind,
 	.unbind =	usbnet_cdc_unbind,
@@ -112,7 +112,7 @@
 
 static const struct driver_info	zaurus_pxa_info = {
 	.description =	"Sharp Zaurus, PXA-2xx based",
-	.flags =	FLAG_FRAMING_Z,
+	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
 	.check_connect = always_connected,
 	.bind =		zaurus_bind,
 	.unbind =	usbnet_cdc_unbind,
@@ -122,7 +122,7 @@
 
 static const struct driver_info	olympus_mxl_info = {
 	.description =	"Olympus R1000",
-	.flags =	FLAG_FRAMING_Z,
+	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
 	.check_connect = always_connected,
 	.bind =		zaurus_bind,
 	.unbind =	usbnet_cdc_unbind,
@@ -258,7 +258,7 @@
 
 static const struct driver_info	bogus_mdlm_info = {
 	.description =	"pseudo-MDLM (BLAN) device",
-	.flags =	FLAG_FRAMING_Z,
+	.flags =	FLAG_POINTTOPOINT | FLAG_FRAMING_Z,
 	.check_connect = always_connected,
 	.tx_fixup =	zaurus_tx_fixup,
 	.bind =		blan_mdlm_bind,
diff -druN linux-libre-2.6.38-gnu/drivers/net/veth.c linux-libre-2.6.39-gnu/drivers/net/veth.c
--- linux-libre-2.6.38-gnu/drivers/net/veth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/veth.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,7 +171,7 @@
 	if (skb->ip_summed == CHECKSUM_NONE)
 		skb->ip_summed = rcv_priv->ip_summed;
 
-	length = skb->len + ETH_HLEN;
+	length = skb->len;
 	if (dev_forward_skb(rcv, skb) != NET_RX_SUCCESS)
 		goto rx_drop;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/via-rhine.c linux-libre-2.6.39-gnu/drivers/net/via-rhine.c
--- linux-libre-2.6.38-gnu/drivers/net/via-rhine.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/via-rhine.c	2011-05-19 00:06:34.000000000 -0400
@@ -1861,7 +1861,7 @@
 	u32 intr_status;
 
 	/*
-	 * If new errors occured, we need to sort them out before doing Tx.
+	 * If new errors occurred, we need to sort them out before doing Tx.
 	 * In that case the ISR will be back here RSN anyway.
 	 */
 	intr_status = get_intr_status(dev);
@@ -1887,7 +1887,7 @@
 		/* This should never happen */
 		if (debug > 1)
 			printk(KERN_WARNING "%s: rhine_restart_tx() "
-			       "Another error occured %8.8x.\n",
+			       "Another error occurred %8.8x.\n",
 			       dev->name, intr_status);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/via-velocity.c linux-libre-2.6.39-gnu/drivers/net/via-velocity.c
--- linux-libre-2.6.38-gnu/drivers/net/via-velocity.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/via-velocity.c	2011-05-19 00:06:34.000000000 -0400
@@ -292,7 +292,7 @@
 /* IP_byte_align[] is used for IP header DWORD byte aligned
    0: indicate the IP header won't be DWORD byte aligned.(Default) .
    1: indicate the IP header will be DWORD byte aligned.
-      In some enviroment, the IP header should be DWORD byte aligned,
+      In some environment, the IP header should be DWORD byte aligned,
       or the packet will be droped when we receive it. (eg: IPVS)
 */
 VELOCITY_PARAM(IP_byte_align, "Enable IP header dword aligned");
@@ -1994,7 +1994,7 @@
  *	@dev: network device
  *
  *	Replace the current skb that is scheduled for Rx processing by a
- *	shorter, immediatly allocated skb, if the received packet is small
+ *	shorter, immediately allocated skb, if the received packet is small
  *	enough. This function returns a negative value if the received
  *	packet is too big or if memory is exhausted.
  */
@@ -2923,6 +2923,7 @@
 static int velocity_set_wol(struct velocity_info *vptr)
 {
 	struct mac_regs __iomem *regs = vptr->mac_regs;
+	enum speed_opt spd_dpx = vptr->options.spd_dpx;
 	static u8 buf[256];
 	int i;
 
@@ -2968,6 +2969,12 @@
 
 	writew(0x0FFF, &regs->WOLSRClr);
 
+	if (spd_dpx == SPD_DPX_1000_FULL)
+		goto mac_done;
+
+	if (spd_dpx != SPD_DPX_AUTO)
+		goto advertise_done;
+
 	if (vptr->mii_status & VELOCITY_AUTONEG_ENABLE) {
 		if (PHYID_GET_PHY_ID(vptr->phy_id) == PHYID_CICADA_CS8201)
 			MII_REG_BITS_ON(AUXCR_MDPPS, MII_NCONFIG, vptr->mac_regs);
@@ -2978,6 +2985,7 @@
 	if (vptr->mii_status & VELOCITY_SPEED_1000)
 		MII_REG_BITS_ON(BMCR_ANRESTART, MII_BMCR, vptr->mac_regs);
 
+advertise_done:
 	BYTE_REG_BITS_ON(CHIPGCR_FCMODE, &regs->CHIPGCR);
 
 	{
@@ -2987,6 +2995,7 @@
 		writeb(GCR, &regs->CHIPGCR);
 	}
 
+mac_done:
 	BYTE_REG_BITS_OFF(ISR_PWEI, &regs->ISR);
 	/* Turn on SWPTAG just before entering power mode */
 	BYTE_REG_BITS_ON(STICKHW_SWPTAG, &regs->STICKHW);
diff -druN linux-libre-2.6.38-gnu/drivers/net/via-velocity.h linux-libre-2.6.39-gnu/drivers/net/via-velocity.h
--- linux-libre-2.6.38-gnu/drivers/net/via-velocity.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/via-velocity.h	2011-05-19 00:06:34.000000000 -0400
@@ -361,7 +361,7 @@
 #define MAC_REG_CHIPGSR     0x9C
 #define MAC_REG_TESTCFG     0x9D
 #define MAC_REG_DEBUG       0x9E
-#define MAC_REG_CHIPGCR     0x9F
+#define MAC_REG_CHIPGCR     0x9F	/* Chip Operation and Diagnostic Control */
 #define MAC_REG_WOLCR0_SET  0xA0
 #define MAC_REG_WOLCR1_SET  0xA1
 #define MAC_REG_PWCFG_SET   0xA2
@@ -848,10 +848,10 @@
  *	Bits in CHIPGCR register
  */
 
-#define CHIPGCR_FCGMII      0x80	/* enable GMII mode */
-#define CHIPGCR_FCFDX       0x40
+#define CHIPGCR_FCGMII      0x80	/* force GMII (else MII only) */
+#define CHIPGCR_FCFDX       0x40	/* force full duplex */
 #define CHIPGCR_FCRESV      0x20
-#define CHIPGCR_FCMODE      0x10
+#define CHIPGCR_FCMODE      0x10	/* enable MAC forced mode */
 #define CHIPGCR_LPSOPT      0x08
 #define CHIPGCR_TM1US       0x04
 #define CHIPGCR_TM0US       0x02
diff -druN linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_drv.c linux-libre-2.6.39-gnu/drivers/net/vmxnet3/vmxnet3_drv.c
--- linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vmxnet3/vmxnet3_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,6 +178,7 @@
 vmxnet3_process_events(struct vmxnet3_adapter *adapter)
 {
 	int i;
+	unsigned long flags;
 	u32 events = le32_to_cpu(adapter->shared->ecr);
 	if (!events)
 		return;
@@ -190,10 +191,10 @@
 
 	/* Check if there is an error on xmit/recv queues */
 	if (events & (VMXNET3_ECR_TQERR | VMXNET3_ECR_RQERR)) {
-		spin_lock(&adapter->cmd_lock);
+		spin_lock_irqsave(&adapter->cmd_lock, flags);
 		VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 				       VMXNET3_CMD_GET_QUEUE_STATUS);
-		spin_unlock(&adapter->cmd_lock);
+		spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 
 		for (i = 0; i < adapter->num_tx_queues; i++)
 			if (adapter->tqd_start[i].status.stopped)
@@ -892,7 +893,7 @@
  * Transmits a pkt thru a given tq
  * Returns:
  *    NETDEV_TX_OK:      descriptors are setup successfully
- *    NETDEV_TX_OK:      error occured, the pkt is dropped
+ *    NETDEV_TX_OK:      error occurred, the pkt is dropped
  *    NETDEV_TX_BUSY:    tx ring is full, queue is stopped
  *
  * Side-effects:
@@ -2685,7 +2686,7 @@
  * Enable MSIx vectors.
  * Returns :
  *	0 on successful enabling of required vectors,
- *	VMXNET3_LINUX_MIN_MSIX_VECT when only minumum number of vectors required
+ *	VMXNET3_LINUX_MIN_MSIX_VECT when only minimum number of vectors required
  *	 could be enabled.
  *	number of vectors which can be enabled otherwise (this number is smaller
  *	 than VMXNET3_LINUX_MIN_MSIX_VECT)
@@ -2733,13 +2734,14 @@
 vmxnet3_alloc_intr_resources(struct vmxnet3_adapter *adapter)
 {
 	u32 cfg;
+	unsigned long flags;
 
 	/* intr settings */
-	spin_lock(&adapter->cmd_lock);
+	spin_lock_irqsave(&adapter->cmd_lock, flags);
 	VMXNET3_WRITE_BAR1_REG(adapter, VMXNET3_REG_CMD,
 			       VMXNET3_CMD_GET_CONF_INTR);
 	cfg = VMXNET3_READ_BAR1_REG(adapter, VMXNET3_REG_CMD);
-	spin_unlock(&adapter->cmd_lock);
+	spin_unlock_irqrestore(&adapter->cmd_lock, flags);
 	adapter->intr.type = cfg & 0x3;
 	adapter->intr.mask_mode = (cfg >> 2) & 0x3;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c linux-libre-2.6.39-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vmxnet3/vmxnet3_ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -304,13 +304,16 @@
 	u8 lro_present = (netdev->features & NETIF_F_LRO) == 0 ? 0 : 1;
 	unsigned long flags;
 
-	if (data & ~ETH_FLAG_LRO)
-		return -EOPNOTSUPP;
+	if (ethtool_invalid_flags(netdev, data, ETH_FLAG_LRO))
+		return -EINVAL;
 
 	if (lro_requested ^ lro_present) {
 		/* toggle the LRO feature*/
 		netdev->features ^= NETIF_F_LRO;
 
+		/* Update private LRO flag */
+		adapter->lro = lro_requested;
+
 		/* update harware LRO capability accordingly */
 		if (lro_requested)
 			adapter->shared->devRead.misc.uptFeatures |=
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-config.c linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-config.c
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-config.c	2011-05-19 00:06:34.000000000 -0400
@@ -187,7 +187,7 @@
 					   VXGE_HW_DEF_DEVICE_POLL_MILLIS);
 
 	/* The __vxge_hw_device_register_poll can udelay for a significant
-	 * amount of time, blocking other proccess from the CPU.  If it delays
+	 * amount of time, blocking other process from the CPU.  If it delays
 	 * for ~5secs, a NMI error can occur.  A way around this is to give up
 	 * the processor via msleep, but this is not allowed is under lock.
 	 * So, only allow it to sleep for ~4secs if open.  Otherwise, delay for
@@ -387,8 +387,8 @@
 		data1 = steer_ctrl = 0;
 
 		status = vxge_hw_vpath_fw_api(vpath,
-			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
 			VXGE_HW_FW_API_GET_EPROM_REV,
+			VXGE_HW_RTS_ACCESS_STEER_CTRL_DATA_STRUCT_SEL_FW_MEMO,
 			0, &data0, &data1, &steer_ctrl);
 		if (status != VXGE_HW_OK)
 			break;
@@ -2868,6 +2868,8 @@
 	ring->rxd_init = attr->rxd_init;
 	ring->rxd_term = attr->rxd_term;
 	ring->buffer_mode = config->buffer_mode;
+	ring->tim_rti_cfg1_saved = vp->vpath->tim_rti_cfg1_saved;
+	ring->tim_rti_cfg3_saved = vp->vpath->tim_rti_cfg3_saved;
 	ring->rxds_limit = config->rxds_limit;
 
 	ring->rxd_size = vxge_hw_ring_rxd_size_get(config->buffer_mode);
@@ -3511,6 +3513,8 @@
 
 	/* apply "interrupts per txdl" attribute */
 	fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_UTILZ;
+	fifo->tim_tti_cfg1_saved = vpath->tim_tti_cfg1_saved;
+	fifo->tim_tti_cfg3_saved = vpath->tim_tti_cfg3_saved;
 
 	if (fifo->config->intr)
 		fifo->interrupt_type = VXGE_HW_FIFO_TXD_INT_TYPE_PER_LIST;
@@ -4377,6 +4381,8 @@
 		}
 
 		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+		vpath->tim_tti_cfg1_saved = val64;
+
 		val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_TX]);
 
 		if (config->tti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
@@ -4433,6 +4439,7 @@
 		}
 
 		writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
+		vpath->tim_tti_cfg3_saved = val64;
 	}
 
 	if (config->ring.enable == VXGE_HW_RING_ENABLE) {
@@ -4481,6 +4488,8 @@
 		}
 
 		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
+		vpath->tim_rti_cfg1_saved = val64;
+
 		val64 = readq(&vp_reg->tim_cfg2_int_num[VXGE_HW_VPATH_INTR_RX]);
 
 		if (config->rti.uec_a != VXGE_HW_USE_FLASH_DEFAULT) {
@@ -4537,6 +4546,7 @@
 		}
 
 		writeq(val64, &vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
+		vpath->tim_rti_cfg3_saved = val64;
 	}
 
 	val64 = 0;
@@ -4555,26 +4565,6 @@
 	return status;
 }
 
-void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id)
-{
-	struct __vxge_hw_virtualpath *vpath;
-	struct vxge_hw_vpath_reg __iomem *vp_reg;
-	struct vxge_hw_vp_config *config;
-	u64 val64;
-
-	vpath = &hldev->virtual_paths[vp_id];
-	vp_reg = vpath->vp_reg;
-	config = vpath->vp_config;
-
-	if (config->fifo.enable == VXGE_HW_FIFO_ENABLE &&
-	    config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
-		config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
-		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
-		val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
-		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
-	}
-}
-
 /*
  * __vxge_hw_vpath_initialize
  * This routine is the final phase of init which initializes the
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-config.h linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-config.h
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-config.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-config.h	2011-05-19 00:06:34.000000000 -0400
@@ -682,6 +682,10 @@
 	u32				vsport_number;
 	u32				max_kdfc_db;
 	u32				max_nofl_db;
+	u64				tim_tti_cfg1_saved;
+	u64				tim_tti_cfg3_saved;
+	u64				tim_rti_cfg1_saved;
+	u64				tim_rti_cfg3_saved;
 
 	struct __vxge_hw_ring *____cacheline_aligned ringh;
 	struct __vxge_hw_fifo *____cacheline_aligned fifoh;
@@ -921,6 +925,9 @@
 	u32					doorbell_cnt;
 	u32					total_db_cnt;
 	u64					rxds_limit;
+	u32					rtimer;
+	u64					tim_rti_cfg1_saved;
+	u64					tim_rti_cfg3_saved;
 
 	enum vxge_hw_status (*callback)(
 			struct __vxge_hw_ring *ringh,
@@ -1000,6 +1007,9 @@
 	u32					per_txdl_space;
 	u32					vp_id;
 	u32					tx_intr_num;
+	u32					rtimer;
+	u64					tim_tti_cfg1_saved;
+	u64					tim_tti_cfg3_saved;
 
 	enum vxge_hw_status (*callback)(
 			struct __vxge_hw_fifo *fifo_handle,
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-ethtool.c linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-ethtool.c
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-ethtool.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-ethtool.c	2011-05-19 00:06:34.000000000 -0400
@@ -1117,8 +1117,8 @@
 	struct vxgedev *vdev = netdev_priv(dev);
 	enum vxge_hw_status status;
 
-	if (data & ~ETH_FLAG_RXHASH)
-		return -EOPNOTSUPP;
+	if (ethtool_invalid_flags(dev, data, ETH_FLAG_RXHASH))
+		return -EINVAL;
 
 	if (!!(data & ETH_FLAG_RXHASH) == vdev->devh->config.rth_en)
 		return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-main.c linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-main.c
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-main.c	2012-03-24 01:09:26.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-main.c	2012-03-24 03:31:40.000000000 -0400
@@ -371,9 +371,6 @@
 	struct vxge_hw_ring_rxd_info ext_info;
 	vxge_debug_entryexit(VXGE_TRACE, "%s: %s:%d",
 		ring->ndev->name, __func__, __LINE__);
-	ring->pkts_processed = 0;
-
-	vxge_hw_ring_replenish(ringh);
 
 	do {
 		prefetch((char *)dtr + L1_CACHE_BYTES);
@@ -1588,6 +1585,36 @@
 	return ret;
 }
 
+/* Configure CI */
+static void vxge_config_ci_for_tti_rti(struct vxgedev *vdev)
+{
+	int i = 0;
+
+	/* Enable CI for RTI */
+	if (vdev->config.intr_type == MSI_X) {
+		for (i = 0; i < vdev->no_of_vpath; i++) {
+			struct __vxge_hw_ring *hw_ring;
+
+			hw_ring = vdev->vpaths[i].ring.handle;
+			vxge_hw_vpath_dynamic_rti_ci_set(hw_ring);
+		}
+	}
+
+	/* Enable CI for TTI */
+	for (i = 0; i < vdev->no_of_vpath; i++) {
+		struct __vxge_hw_fifo *hw_fifo = vdev->vpaths[i].fifo.handle;
+		vxge_hw_vpath_tti_ci_set(hw_fifo);
+		/*
+		 * For Inta (with or without napi), Set CI ON for only one
+		 * vpath. (Have only one free running timer).
+		 */
+		if ((vdev->config.intr_type == INTA) && (i == 0))
+			break;
+	}
+
+	return;
+}
+
 static int do_vxge_reset(struct vxgedev *vdev, int event)
 {
 	enum vxge_hw_status status;
@@ -1753,6 +1780,9 @@
 		netif_tx_wake_all_queues(vdev->ndev);
 	}
 
+	/* configure CI */
+	vxge_config_ci_for_tti_rti(vdev);
+
 out:
 	vxge_debug_entryexit(VXGE_TRACE,
 		"%s:%d  Exiting...", __func__, __LINE__);
@@ -1793,22 +1823,29 @@
  */
 static int vxge_poll_msix(struct napi_struct *napi, int budget)
 {
-	struct vxge_ring *ring =
-		container_of(napi, struct vxge_ring, napi);
+	struct vxge_ring *ring = container_of(napi, struct vxge_ring, napi);
+	int pkts_processed;
 	int budget_org = budget;
-	ring->budget = budget;
 
+	ring->budget = budget;
+	ring->pkts_processed = 0;
 	vxge_hw_vpath_poll_rx(ring->handle);
+	pkts_processed = ring->pkts_processed;
 
 	if (ring->pkts_processed < budget_org) {
 		napi_complete(napi);
+
 		/* Re enable the Rx interrupts for the vpath */
 		vxge_hw_channel_msix_unmask(
 				(struct __vxge_hw_channel *)ring->handle,
 				ring->rx_vector_no);
+		mmiowb();
 	}
 
-	return ring->pkts_processed;
+	/* We are copying and returning the local variable, in case if after
+	 * clearing the msix interrupt above, if the interrupt fires right
+	 * away which can preempt this NAPI thread */
+	return pkts_processed;
 }
 
 static int vxge_poll_inta(struct napi_struct *napi, int budget)
@@ -1824,6 +1861,7 @@
 	for (i = 0; i < vdev->no_of_vpath; i++) {
 		ring = &vdev->vpaths[i].ring;
 		ring->budget = budget;
+		ring->pkts_processed = 0;
 		vxge_hw_vpath_poll_rx(ring->handle);
 		pkts_processed += ring->pkts_processed;
 		budget -= ring->pkts_processed;
@@ -2054,6 +2092,7 @@
 					netdev_get_tx_queue(vdev->ndev, 0);
 			vpath->fifo.indicate_max_pkts =
 				vdev->config.fifo_indicate_max_pkts;
+			vpath->fifo.tx_vector_no = 0;
 			vpath->ring.rx_vector_no = 0;
 			vpath->ring.rx_csum = vdev->rx_csum;
 			vpath->ring.rx_hwts = vdev->rx_hwts;
@@ -2079,6 +2118,61 @@
 	return VXGE_HW_OK;
 }
 
+/**
+ *  adaptive_coalesce_tx_interrupts - Changes the interrupt coalescing
+ *  if the interrupts are not within a range
+ *  @fifo: pointer to transmit fifo structure
+ *  Description: The function changes boundary timer and restriction timer
+ *  value depends on the traffic
+ *  Return Value: None
+ */
+static void adaptive_coalesce_tx_interrupts(struct vxge_fifo *fifo)
+{
+	fifo->interrupt_count++;
+	if (jiffies > fifo->jiffies + HZ / 100) {
+		struct __vxge_hw_fifo *hw_fifo = fifo->handle;
+
+		fifo->jiffies = jiffies;
+		if (fifo->interrupt_count > VXGE_T1A_MAX_TX_INTERRUPT_COUNT &&
+		    hw_fifo->rtimer != VXGE_TTI_RTIMER_ADAPT_VAL) {
+			hw_fifo->rtimer = VXGE_TTI_RTIMER_ADAPT_VAL;
+			vxge_hw_vpath_dynamic_tti_rtimer_set(hw_fifo);
+		} else if (hw_fifo->rtimer != 0) {
+			hw_fifo->rtimer = 0;
+			vxge_hw_vpath_dynamic_tti_rtimer_set(hw_fifo);
+		}
+		fifo->interrupt_count = 0;
+	}
+}
+
+/**
+ *  adaptive_coalesce_rx_interrupts - Changes the interrupt coalescing
+ *  if the interrupts are not within a range
+ *  @ring: pointer to receive ring structure
+ *  Description: The function increases of decreases the packet counts within
+ *  the ranges of traffic utilization, if the interrupts due to this ring are
+ *  not within a fixed range.
+ *  Return Value: Nothing
+ */
+static void adaptive_coalesce_rx_interrupts(struct vxge_ring *ring)
+{
+	ring->interrupt_count++;
+	if (jiffies > ring->jiffies + HZ / 100) {
+		struct __vxge_hw_ring *hw_ring = ring->handle;
+
+		ring->jiffies = jiffies;
+		if (ring->interrupt_count > VXGE_T1A_MAX_INTERRUPT_COUNT &&
+		    hw_ring->rtimer != VXGE_RTI_RTIMER_ADAPT_VAL) {
+			hw_ring->rtimer = VXGE_RTI_RTIMER_ADAPT_VAL;
+			vxge_hw_vpath_dynamic_rti_rtimer_set(hw_ring);
+		} else if (hw_ring->rtimer != 0) {
+			hw_ring->rtimer = 0;
+			vxge_hw_vpath_dynamic_rti_rtimer_set(hw_ring);
+		}
+		ring->interrupt_count = 0;
+	}
+}
+
 /*
  *  vxge_isr_napi
  *  @irq: the irq of the device.
@@ -2139,24 +2233,39 @@
 
 #ifdef CONFIG_PCI_MSI
 
-static irqreturn_t
-vxge_tx_msix_handle(int irq, void *dev_id)
+static irqreturn_t vxge_tx_msix_handle(int irq, void *dev_id)
 {
 	struct vxge_fifo *fifo = (struct vxge_fifo *)dev_id;
 
+	adaptive_coalesce_tx_interrupts(fifo);
+
+	vxge_hw_channel_msix_mask((struct __vxge_hw_channel *)fifo->handle,
+				  fifo->tx_vector_no);
+
+	vxge_hw_channel_msix_clear((struct __vxge_hw_channel *)fifo->handle,
+				   fifo->tx_vector_no);
+
 	VXGE_COMPLETE_VPATH_TX(fifo);
 
+	vxge_hw_channel_msix_unmask((struct __vxge_hw_channel *)fifo->handle,
+				    fifo->tx_vector_no);
+
+	mmiowb();
+
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t
-vxge_rx_msix_napi_handle(int irq, void *dev_id)
+static irqreturn_t vxge_rx_msix_napi_handle(int irq, void *dev_id)
 {
 	struct vxge_ring *ring = (struct vxge_ring *)dev_id;
 
-	/* MSIX_IDX for Rx is 1 */
+	adaptive_coalesce_rx_interrupts(ring);
+
 	vxge_hw_channel_msix_mask((struct __vxge_hw_channel *)ring->handle,
-					ring->rx_vector_no);
+				  ring->rx_vector_no);
+
+	vxge_hw_channel_msix_clear((struct __vxge_hw_channel *)ring->handle,
+				   ring->rx_vector_no);
 
 	napi_schedule(&ring->napi);
 	return IRQ_HANDLED;
@@ -2173,14 +2282,20 @@
 		VXGE_HW_VPATH_MSIX_ACTIVE) + VXGE_ALARM_MSIX_ID;
 
 	for (i = 0; i < vdev->no_of_vpath; i++) {
+		/* Reduce the chance of losing alarm interrupts by masking
+		 * the vector. A pending bit will be set if an alarm is
+		 * generated and on unmask the interrupt will be fired.
+		 */
 		vxge_hw_vpath_msix_mask(vdev->vpaths[i].handle, msix_id);
+		vxge_hw_vpath_msix_clear(vdev->vpaths[i].handle, msix_id);
+		mmiowb();
 
 		status = vxge_hw_vpath_alarm_process(vdev->vpaths[i].handle,
 			vdev->exec_mode);
 		if (status == VXGE_HW_OK) {
-
 			vxge_hw_vpath_msix_unmask(vdev->vpaths[i].handle,
-					msix_id);
+						  msix_id);
+			mmiowb();
 			continue;
 		}
 		vxge_debug_intr(VXGE_ERR,
@@ -2299,6 +2414,9 @@
 			vpath->ring.rx_vector_no = (vpath->device_id *
 						VXGE_HW_VPATH_MSIX_ACTIVE) + 1;
 
+			vpath->fifo.tx_vector_no = (vpath->device_id *
+						VXGE_HW_VPATH_MSIX_ACTIVE);
+
 			vxge_hw_vpath_msix_set(vpath->handle, tim_msix_id,
 					       VXGE_ALARM_MSIX_ID);
 		}
@@ -2474,8 +2592,9 @@
 			"%s:vxge:INTA", vdev->ndev->name);
 		vxge_hw_device_set_intr_type(vdev->devh,
 			VXGE_HW_INTR_MODE_IRQLINE);
-		vxge_hw_vpath_tti_ci_set(vdev->devh,
-			vdev->vpaths[0].device_id);
+
+		vxge_hw_vpath_tti_ci_set(vdev->vpaths[0].fifo.handle);
+
 		ret = request_irq((int) vdev->pdev->irq,
 			vxge_isr_napi,
 			IRQF_SHARED, vdev->desc[0], vdev);
@@ -2669,7 +2788,7 @@
 	}
 
 	/* Enable vpath to sniff all unicast/multicast traffic that not
-	 * addressed to them. We allow promiscous mode for PF only
+	 * addressed to them. We allow promiscuous mode for PF only
 	 */
 
 	val64 = 0;
@@ -2745,6 +2864,10 @@
 	}
 
 	netif_tx_start_all_queues(vdev->ndev);
+
+	/* configure CI */
+	vxge_config_ci_for_tti_rti(vdev);
+
 	goto out0;
 
 out2:
@@ -2767,7 +2890,7 @@
 	return ret;
 }
 
-/* Loop throught the mac address list and delete all the entries */
+/* Loop through the mac address list and delete all the entries */
 static void vxge_free_mac_add_list(struct vxge_vpath *vpath)
 {
 
@@ -2834,7 +2957,7 @@
 					val64);
 		}
 
-		/* Remove the function 0 from promiscous mode */
+		/* Remove the function 0 from promiscuous mode */
 		vxge_hw_mgmt_reg_write(vdev->devh,
 			vxge_hw_mgmt_reg_type_mrpcim,
 			0,
@@ -3264,19 +3387,6 @@
 #endif
 };
 
-static int __devinit vxge_device_revision(struct vxgedev *vdev)
-{
-	int ret;
-	u8 revision;
-
-	ret = pci_read_config_byte(vdev->pdev, PCI_REVISION_ID, &revision);
-	if (ret)
-		return -EIO;
-
-	vdev->titan1 = (revision == VXGE_HW_TITAN1_PCI_REVISION);
-	return 0;
-}
-
 static int __devinit vxge_device_register(struct __vxge_hw_device *hldev,
 					  struct vxge_config *config,
 					  int high_dma, int no_of_vpath,
@@ -3316,10 +3426,7 @@
 	memcpy(&vdev->config, config, sizeof(struct vxge_config));
 	vdev->rx_csum = 1;	/* Enable Rx CSUM by default. */
 	vdev->rx_hwts = 0;
-
-	ret = vxge_device_revision(vdev);
-	if (ret < 0)
-		goto _out1;
+	vdev->titan1 = (vdev->pdev->revision == VXGE_HW_TITAN1_PCI_REVISION);
 
 	SET_NETDEV_DEV(ndev, &vdev->pdev->dev);
 
@@ -3348,7 +3455,7 @@
 		vxge_debug_init(VXGE_ERR,
 			"%s: vpath memory allocation failed",
 			vdev->ndev->name);
-		ret = -ENODEV;
+		ret = -ENOMEM;
 		goto _out1;
 	}
 
@@ -3369,11 +3476,11 @@
 	if (vdev->config.gro_enable)
 		ndev->features |= NETIF_F_GRO;
 
-	if (register_netdev(ndev)) {
+	ret = register_netdev(ndev);
+	if (ret) {
 		vxge_debug_init(vxge_hw_device_trace_level_get(hldev),
 			"%s: %s : device registration failed!",
 			ndev->name, __func__);
-		ret = -ENODEV;
 		goto _out2;
 	}
 
@@ -3444,6 +3551,11 @@
 	/* in 2.6 will call stop() if device is up */
 	unregister_netdev(dev);
 
+	kfree(vdev->vpaths);
+
+	/* we are safe to free it now */
+	free_netdev(dev);
+
 	vxge_debug_init(vdev->level_trace, "%s: ethernet device unregistered",
 			buf);
 	vxge_debug_entryexit(vdev->level_trace,	"%s: %s:%d  Exiting...", buf,
@@ -3799,7 +3911,7 @@
 		break;
 
 	case MSI_X:
-		device_config->intr_mode = VXGE_HW_INTR_MODE_MSIX;
+		device_config->intr_mode = VXGE_HW_INTR_MODE_MSIX_ONE_SHOT;
 		break;
 	}
 
@@ -4335,10 +4447,10 @@
 		goto _exit1;
 	}
 
-	if (pci_request_region(pdev, 0, VXGE_DRIVER_NAME)) {
+	ret = pci_request_region(pdev, 0, VXGE_DRIVER_NAME);
+	if (ret) {
 		vxge_debug_init(VXGE_ERR,
 			"%s : request regions failed", __func__);
-		ret = -ENODEV;
 		goto _exit1;
 	}
 
@@ -4446,7 +4558,7 @@
 			if (!img[i].is_valid)
 				break;
 			vxge_debug_init(VXGE_TRACE, "%s: EPROM %d, version "
-					"%d.%d.%d.%d\n", VXGE_DRIVER_NAME, i,
+					"%d.%d.%d.%d", VXGE_DRIVER_NAME, i,
 					VXGE_EPROM_IMG_MAJOR(img[i].version),
 					VXGE_EPROM_IMG_MINOR(img[i].version),
 					VXGE_EPROM_IMG_FIX(img[i].version),
@@ -4643,8 +4755,9 @@
 _exit5:
 	vxge_device_unregister(hldev);
 _exit4:
-	pci_disable_sriov(pdev);
+	pci_set_drvdata(pdev, NULL);
 	vxge_hw_device_terminate(hldev);
+	pci_disable_sriov(pdev);
 _exit3:
 	iounmap(attr.bar0);
 _exit2:
@@ -4655,7 +4768,7 @@
 	kfree(ll_config);
 	kfree(device_config);
 	driver_config->config_dev_cnt--;
-	pci_set_drvdata(pdev, NULL);
+	driver_config->total_dev_cnt--;
 	return ret;
 }
 
@@ -4668,45 +4781,34 @@
 static void __devexit vxge_remove(struct pci_dev *pdev)
 {
 	struct __vxge_hw_device *hldev;
-	struct vxgedev *vdev = NULL;
-	struct net_device *dev;
-	int i = 0;
+	struct vxgedev *vdev;
+	int i;
 
 	hldev = pci_get_drvdata(pdev);
-
 	if (hldev == NULL)
 		return;
 
-	dev = hldev->ndev;
-	vdev = netdev_priv(dev);
+	vdev = netdev_priv(hldev->ndev);
 
 	vxge_debug_entryexit(vdev->level_trace,	"%s:%d", __func__, __LINE__);
-
 	vxge_debug_init(vdev->level_trace, "%s : removing PCI device...",
 			__func__);
-	vxge_device_unregister(hldev);
 
-	for (i = 0; i < vdev->no_of_vpath; i++) {
+	for (i = 0; i < vdev->no_of_vpath; i++)
 		vxge_free_mac_add_list(&vdev->vpaths[i]);
-		vdev->vpaths[i].mcast_addr_cnt = 0;
-		vdev->vpaths[i].mac_addr_cnt = 0;
-	}
-
-	kfree(vdev->vpaths);
 
+	vxge_device_unregister(hldev);
+	pci_set_drvdata(pdev, NULL);
+	/* Do not call pci_disable_sriov here, as it will break child devices */
+	vxge_hw_device_terminate(hldev);
 	iounmap(vdev->bar0);
-
-	/* we are safe to free it now */
-	free_netdev(dev);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	driver_config->config_dev_cnt--;
+	driver_config->total_dev_cnt--;
 
 	vxge_debug_init(vdev->level_trace, "%s:%d Device unregistered",
 			__func__, __LINE__);
-
-	vxge_hw_device_terminate(hldev);
-
-	pci_disable_device(pdev);
-	pci_release_region(pdev, 0);
-	pci_set_drvdata(pdev, NULL);
 	vxge_debug_entryexit(vdev->level_trace,	"%s:%d  Exiting...", __func__,
 			     __LINE__);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-main.h linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-main.h
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-main.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-main.h	2011-05-19 00:06:34.000000000 -0400
@@ -59,11 +59,13 @@
 #define VXGE_TTI_LTIMER_VAL	1000
 #define VXGE_T1A_TTI_LTIMER_VAL	80
 #define VXGE_TTI_RTIMER_VAL	0
+#define VXGE_TTI_RTIMER_ADAPT_VAL	10
 #define VXGE_T1A_TTI_RTIMER_VAL	400
 #define VXGE_RTI_BTIMER_VAL	250
 #define VXGE_RTI_LTIMER_VAL	100
 #define VXGE_RTI_RTIMER_VAL	0
-#define VXGE_FIFO_INDICATE_MAX_PKTS VXGE_DEF_FIFO_LENGTH
+#define VXGE_RTI_RTIMER_ADAPT_VAL	15
+#define VXGE_FIFO_INDICATE_MAX_PKTS	VXGE_DEF_FIFO_LENGTH
 #define VXGE_ISR_POLLING_CNT 	8
 #define VXGE_MAX_CONFIG_DEV	0xFF
 #define VXGE_EXEC_MODE_DISABLE	0
@@ -107,6 +109,14 @@
 #define RTI_T1A_RX_UFC_C	50
 #define RTI_T1A_RX_UFC_D	60
 
+/*
+ * The interrupt rate is maintained at 3k per second with the moderation
+ * parameters for most traffic but not all. This is the maximum interrupt
+ * count allowed per function with INTA or per vector in the case of
+ * MSI-X in a 10 millisecond time period. Enabled only for Titan 1A.
+ */
+#define VXGE_T1A_MAX_INTERRUPT_COUNT	100
+#define VXGE_T1A_MAX_TX_INTERRUPT_COUNT	200
 
 /* Milli secs timer period */
 #define VXGE_TIMER_DELAY		10000
@@ -247,6 +257,11 @@
 	int tx_steering_type;
 	int indicate_max_pkts;
 
+	/* Adaptive interrupt moderation parameters used in T1A */
+	unsigned long interrupt_count;
+	unsigned long jiffies;
+
+	u32 tx_vector_no;
 	/* Tx stats */
 	struct vxge_fifo_stats stats;
 } ____cacheline_aligned;
@@ -271,6 +286,10 @@
 	 */
 	int driver_id;
 
+	/* Adaptive interrupt moderation parameters used in T1A */
+	unsigned long interrupt_count;
+	unsigned long jiffies;
+
 	/* copy of the flag indicating whether rx_csum is to be used */
 	u32 rx_csum:1,
 	    rx_hwts:1;
@@ -286,7 +305,7 @@
 
 	int vlan_tag_strip;
 	struct vlan_group *vlgrp;
-	int rx_vector_no;
+	u32 rx_vector_no;
 	enum vxge_hw_status last_status;
 
 	/* Rx stats */
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-traffic.c linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-traffic.c
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-traffic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-traffic.c	2011-05-19 00:06:34.000000000 -0400
@@ -218,6 +218,68 @@
 	return status;
 }
 
+void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_fifo *fifo)
+{
+	struct vxge_hw_vpath_reg __iomem *vp_reg;
+	struct vxge_hw_vp_config *config;
+	u64 val64;
+
+	if (fifo->config->enable != VXGE_HW_FIFO_ENABLE)
+		return;
+
+	vp_reg = fifo->vp_reg;
+	config = container_of(fifo->config, struct vxge_hw_vp_config, fifo);
+
+	if (config->tti.timer_ci_en != VXGE_HW_TIM_TIMER_CI_ENABLE) {
+		config->tti.timer_ci_en = VXGE_HW_TIM_TIMER_CI_ENABLE;
+		val64 = readq(&vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+		val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
+		fifo->tim_tti_cfg1_saved = val64;
+		writeq(val64, &vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_TX]);
+	}
+}
+
+void vxge_hw_vpath_dynamic_rti_ci_set(struct __vxge_hw_ring *ring)
+{
+	u64 val64 = ring->tim_rti_cfg1_saved;
+
+	val64 |= VXGE_HW_TIM_CFG1_INT_NUM_TIMER_CI;
+	ring->tim_rti_cfg1_saved = val64;
+	writeq(val64, &ring->vp_reg->tim_cfg1_int_num[VXGE_HW_VPATH_INTR_RX]);
+}
+
+void vxge_hw_vpath_dynamic_tti_rtimer_set(struct __vxge_hw_fifo *fifo)
+{
+	u64 val64 = fifo->tim_tti_cfg3_saved;
+	u64 timer = (fifo->rtimer * 1000) / 272;
+
+	val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(0x3ffffff);
+	if (timer)
+		val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(timer) |
+			VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(5);
+
+	writeq(val64, &fifo->vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_TX]);
+	/* tti_cfg3_saved is not updated again because it is
+	 * initialized at one place only - init time.
+	 */
+}
+
+void vxge_hw_vpath_dynamic_rti_rtimer_set(struct __vxge_hw_ring *ring)
+{
+	u64 val64 = ring->tim_rti_cfg3_saved;
+	u64 timer = (ring->rtimer * 1000) / 272;
+
+	val64 &= ~VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(0x3ffffff);
+	if (timer)
+		val64 |= VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_VAL(timer) |
+			VXGE_HW_TIM_CFG3_INT_NUM_RTIMER_EVENT_SF(4);
+
+	writeq(val64, &ring->vp_reg->tim_cfg3_int_num[VXGE_HW_VPATH_INTR_RX]);
+	/* rti_cfg3_saved is not updated again because it is
+	 * initialized at one place only - init time.
+	 */
+}
+
 /**
  * vxge_hw_channel_msix_mask - Mask MSIX Vector.
  * @channeh: Channel for rx or tx handle
@@ -254,6 +316,23 @@
 }
 
 /**
+ * vxge_hw_channel_msix_clear - Unmask the MSIX Vector.
+ * @channel: Channel for rx or tx handle
+ * @msix_id:  MSI ID
+ *
+ * The function unmasks the msix interrupt for the given msix_id
+ * if configured in MSIX oneshot mode
+ *
+ * Returns: 0
+ */
+void vxge_hw_channel_msix_clear(struct __vxge_hw_channel *channel, int msix_id)
+{
+	__vxge_hw_pio_mem_write32_upper(
+		(u32) vxge_bVALn(vxge_mBIT(msix_id >> 2), 0, 32),
+		&channel->common_reg->clr_msix_one_shot_vec[msix_id % 4]);
+}
+
+/**
  * vxge_hw_device_set_intr_type - Updates the configuration
  *		with new interrupt type.
  * @hldev: HW device handle.
@@ -1032,7 +1111,7 @@
  * vxge_hw_channel_dtr_count
  * @channel: Channel handle. Obtained via vxge_hw_channel_open().
  *
- * Retreive number of DTRs available. This function can not be called
+ * Retrieve number of DTRs available. This function can not be called
  * from data path. ring_initial_replenishi() is the only user.
  */
 int vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel)
@@ -1981,7 +2060,7 @@
 
 	vpath = vp->vpath;
 
-	/* Enable promiscous mode for function 0 only */
+	/* Enable promiscuous mode for function 0 only */
 	if (!(vpath->hldev->access_rights &
 		VXGE_HW_DEVICE_ACCESS_RIGHT_MRPCIM))
 		return VXGE_HW_OK;
@@ -2191,19 +2270,14 @@
 	if (vpath->hldev->config.intr_mode ==
 					VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
 		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
+				VXGE_HW_ONE_SHOT_VECT0_EN_ONE_SHOT_VECT0_EN,
+				0, 32), &vp_reg->one_shot_vect0_en);
+		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
 				VXGE_HW_ONE_SHOT_VECT1_EN_ONE_SHOT_VECT1_EN,
 				0, 32), &vp_reg->one_shot_vect1_en);
-	}
-
-	if (vpath->hldev->config.intr_mode ==
-		VXGE_HW_INTR_MODE_MSIX_ONE_SHOT) {
 		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
 				VXGE_HW_ONE_SHOT_VECT2_EN_ONE_SHOT_VECT2_EN,
 				0, 32), &vp_reg->one_shot_vect2_en);
-
-		__vxge_hw_pio_mem_write32_upper((u32)vxge_bVALn(
-				VXGE_HW_ONE_SHOT_VECT3_EN_ONE_SHOT_VECT3_EN,
-				0, 32), &vp_reg->one_shot_vect3_en);
 	}
 }
 
@@ -2229,6 +2303,32 @@
 }
 
 /**
+ * vxge_hw_vpath_msix_clear - Clear MSIX Vector.
+ * @vp: Virtual Path handle.
+ * @msix_id:  MSI ID
+ *
+ * The function clears the msix interrupt for the given msix_id
+ *
+ * Returns: 0,
+ * Otherwise, VXGE_HW_ERR_WRONG_IRQ if the msix index is out of range
+ * status.
+ * See also:
+ */
+void vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id)
+{
+	struct __vxge_hw_device *hldev = vp->vpath->hldev;
+
+	if ((hldev->config.intr_mode == VXGE_HW_INTR_MODE_MSIX_ONE_SHOT))
+		__vxge_hw_pio_mem_write32_upper(
+			(u32) vxge_bVALn(vxge_mBIT((msix_id >> 2)), 0, 32),
+			&hldev->common_reg->clr_msix_one_shot_vec[msix_id % 4]);
+	else
+		__vxge_hw_pio_mem_write32_upper(
+			(u32) vxge_bVALn(vxge_mBIT((msix_id >> 2)), 0, 32),
+			&hldev->common_reg->clear_msix_mask_vect[msix_id % 4]);
+}
+
+/**
  * vxge_hw_vpath_msix_unmask - Unmask the MSIX Vector.
  * @vp: Virtual Path handle.
  * @msix_id:  MSI ID
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-traffic.h linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-traffic.h
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-traffic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-traffic.h	2011-05-19 00:06:34.000000000 -0400
@@ -681,7 +681,7 @@
  * @rx_red_discard: Count of received frames that are discarded because of RED
  *            (Random Early Discard).
  * @rx_xgmii_ctrl_err_cnt: Maintains a count of unexpected or misplaced control
- *            characters occuring between times of normal data transmission
+ *            characters occurring between times of normal data transmission
  *            (i.e. not included in RX_XGMII_DATA_ERR_CNT). This counter is
  *            incremented when either -
  *            1) The Reconciliation Sublayer (RS) is expecting one control
@@ -2142,6 +2142,10 @@
  *  Virtual Paths
  */
 
+void vxge_hw_vpath_dynamic_rti_rtimer_set(struct __vxge_hw_ring *ring);
+
+void vxge_hw_vpath_dynamic_tti_rtimer_set(struct __vxge_hw_fifo *fifo);
+
 u32 vxge_hw_vpath_id(
 	struct __vxge_hw_vpath_handle *vpath_handle);
 
@@ -2245,6 +2249,8 @@
 vxge_hw_vpath_msix_mask(struct __vxge_hw_vpath_handle *vpath_handle,
 			int msix_id);
 
+void vxge_hw_vpath_msix_clear(struct __vxge_hw_vpath_handle *vp, int msix_id);
+
 void vxge_hw_device_flush_io(struct __vxge_hw_device *devh);
 
 void
@@ -2270,6 +2276,9 @@
 vxge_hw_channel_msix_unmask(struct __vxge_hw_channel *channelh, int msix_id);
 
 void
+vxge_hw_channel_msix_clear(struct __vxge_hw_channel *channelh, int msix_id);
+
+void
 vxge_hw_channel_dtr_try_complete(struct __vxge_hw_channel *channel,
 				 void **dtrh);
 
@@ -2282,7 +2291,8 @@
 int
 vxge_hw_channel_dtr_count(struct __vxge_hw_channel *channel);
 
-void
-vxge_hw_vpath_tti_ci_set(struct __vxge_hw_device *hldev, u32 vp_id);
+void vxge_hw_vpath_tti_ci_set(struct __vxge_hw_fifo *fifo);
+
+void vxge_hw_vpath_dynamic_rti_ci_set(struct __vxge_hw_ring *ring);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-version.h linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-version.h
--- linux-libre-2.6.38-gnu/drivers/net/vxge/vxge-version.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/vxge/vxge-version.h	2011-05-19 00:06:34.000000000 -0400
@@ -16,8 +16,8 @@
 
 #define VXGE_VERSION_MAJOR	"2"
 #define VXGE_VERSION_MINOR	"5"
-#define VXGE_VERSION_FIX	"1"
-#define VXGE_VERSION_BUILD	"22082"
+#define VXGE_VERSION_FIX	"2"
+#define VXGE_VERSION_BUILD	"22259"
 #define VXGE_VERSION_FOR	"k"
 
 #define VXGE_FW_VER(maj, min, bld) (((maj) << 16) + ((min) << 8) + (bld))
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/cosa.c linux-libre-2.6.39-gnu/drivers/net/wan/cosa.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/cosa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/cosa.c	2011-05-19 00:06:34.000000000 -0400
@@ -329,7 +329,7 @@
 static int readmem(struct cosa_data *cosa, char __user *data, int addr, int len);
 static int cosa_reset_and_read_id(struct cosa_data *cosa, char *id);
 
-/* Auxilliary functions */
+/* Auxiliary functions */
 static int get_wait_data(struct cosa_data *cosa);
 static int put_wait_data(struct cosa_data *cosa, int data);
 static int puthexnumber(struct cosa_data *cosa, int number);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/dscc4.c linux-libre-2.6.39-gnu/drivers/net/wan/dscc4.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/dscc4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/dscc4.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,7 +56,7 @@
  * IV. Notes
  * The current error (XDU, RFO) recovery code is untested.
  * So far, RDO takes his RX channel down and the right sequence to enable it
- * again is still a mistery. If RDO happens, plan a reboot. More details
+ * again is still a mystery. If RDO happens, plan a reboot. More details
  * in the code (NB: as this happens, TX still works).
  * Don't mess the cables during operation, especially on DTE ports. I don't
  * suggest it for DCE either but at least one can get some messages instead
@@ -1065,7 +1065,7 @@
 
 	/*
 	 * Due to various bugs, there is no way to reliably reset a
-	 * specific port (manufacturer's dependant special PCI #RST wiring
+	 * specific port (manufacturer's dependent special PCI #RST wiring
 	 * apart: it affects all ports). Thus the device goes in the best
 	 * silent mode possible at dscc4_close() time and simply claims to
 	 * be up if it's opened again. It still isn't possible to change
@@ -1230,9 +1230,9 @@
  *   scaling. Of course some rounding may take place.
  * - no high speed mode (40Mb/s). May be trivial to do but I don't have an
  *   appropriate external clocking device for testing.
- * - no time-slot/clock mode 5: shameless lazyness.
+ * - no time-slot/clock mode 5: shameless laziness.
  *
- * The clock signals wiring can be (is ?) manufacturer dependant. Good luck.
+ * The clock signals wiring can be (is ?) manufacturer dependent. Good luck.
  *
  * BIG FAT WARNING: if the device isn't provided enough clocking signal, it
  * won't pass the init sequence. For example, straight back-to-back DTE without
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/hostess_sv11.c linux-libre-2.6.39-gnu/drivers/net/wan/hostess_sv11.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/hostess_sv11.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/hostess_sv11.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,7 @@
  *	The hardware does the bus handling to avoid the need for delays between
  *	touching control registers.
  *
- *	Port B isnt wired (why - beats me)
+ *	Port B isn't wired (why - beats me)
  *
  *	Generic HDLC port Copyright (C) 2008 Krzysztof Halasa <khc@pm.waw.pl>
  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/ixp4xx_hss.c linux-libre-2.6.39-gnu/drivers/net/wan/ixp4xx_hss.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/ixp4xx_hss.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/ixp4xx_hss.c	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,7 @@
  *
  * The resulting average clock frequency (assuming 33.333 MHz oscillator) is:
  * freq = 66.666 MHz / (A + (B + 1) / (C + 1))
- * minumum freq = 66.666 MHz / (A + 1)
+ * minimum freq = 66.666 MHz / (A + 1)
  * maximum freq = 66.666 MHz / A
  *
  * Example: A = 2, B = 2, C = 7, CLOCK_CR register = 2 << 22 | 2 << 12 | 7
@@ -230,7 +230,7 @@
 #define PKT_PIPE_MODE_WRITE		0x57
 
 /* HDLC packet status values - desc->status */
-#define ERR_SHUTDOWN		1 /* stop or shutdown occurrance */
+#define ERR_SHUTDOWN		1 /* stop or shutdown occurrence */
 #define ERR_HDLC_ALIGN		2 /* HDLC alignment error */
 #define ERR_HDLC_FCS		3 /* HDLC Frame Check Sum error */
 #define ERR_RXFREE_Q_EMPTY	4 /* RX-free queue became empty while receiving
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/lmc/lmc_main.c linux-libre-2.6.39-gnu/drivers/net/wan/lmc/lmc_main.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/lmc/lmc_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/lmc/lmc_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
   *
   * Linux driver notes:
   * Linux uses the device struct lmc_private to pass private information
-  * arround.
+  * around.
   *
   * The initialization portion of this driver (the lmc_reset() and the
   * lmc_dec_reset() functions, as well as the led controls and the
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/lmc/lmc_var.h linux-libre-2.6.39-gnu/drivers/net/wan/lmc/lmc_var.h
--- linux-libre-2.6.38-gnu/drivers/net/wan/lmc/lmc_var.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/lmc/lmc_var.h	2011-05-19 00:06:34.000000000 -0400
@@ -180,7 +180,7 @@
 
 
 /*
- * Carefull, look at the data sheet, there's more to this
+ * Careful, look at the data sheet, there's more to this
  * structure than meets the eye.  It should probably be:
  *
  * struct tulip_desc_t {
@@ -380,7 +380,7 @@
 /* CSR6 settings */
 #define OPERATION_MODE  0x00000200 /* Full Duplex      */
 #define PROMISC_MODE    0x00000040 /* Promiscuous Mode */
-#define RECIEVE_ALL     0x40000000 /* Recieve All      */
+#define RECIEVE_ALL     0x40000000 /* Receive All      */
 #define PASS_BAD_FRAMES 0x00000008 /* Pass Bad Frames  */
 
 /* Dec control registers  CSR6 as well */
@@ -398,7 +398,7 @@
 #define TULIP_CMD_RECEIVEALL    0x40000000L /* (RW)  Receivel all frames? */
 #define TULIP_CMD_MUSTBEONE     0x02000000L /* (RW)  Must Be One (21140) */
 #define TULIP_CMD_TXTHRSHLDCTL  0x00400000L /* (RW)  Transmit Threshold Mode (21140) */
-#define TULIP_CMD_STOREFWD      0x00200000L /* (RW)  Store and Foward (21140) */
+#define TULIP_CMD_STOREFWD      0x00200000L /* (RW)  Store and Forward (21140) */
 #define TULIP_CMD_NOHEARTBEAT   0x00080000L /* (RW)  No Heartbeat (21140) */
 #define TULIP_CMD_PORTSELECT    0x00040000L /* (RW)  Post Select (100Mb) (21140) */
 #define TULIP_CMD_FULLDUPLEX    0x00000200L /* (RW)  Full Duplex Mode */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/lmc/Makefile linux-libre-2.6.39-gnu/drivers/net/wan/lmc/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wan/lmc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/lmc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -14,4 +14,4 @@
 # -DDEBUG \
 # -DLMC_PACKET_LOG
 
-EXTRA_CFLAGS += -I. $(DBGDEF)
+ccflags-y := -I. $(DBGDEF)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/pc300_tty.c linux-libre-2.6.39-gnu/drivers/net/wan/pc300_tty.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/pc300_tty.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/pc300_tty.c	2011-05-19 00:06:34.000000000 -0400
@@ -131,9 +131,8 @@
 static void cpc_tty_signal_off(pc300dev_t *pc300dev, unsigned char);
 static void cpc_tty_signal_on(pc300dev_t *pc300dev, unsigned char);
 
-static int pc300_tiocmset(struct tty_struct *, struct file *,
-			  unsigned int, unsigned int);
-static int pc300_tiocmget(struct tty_struct *, struct file *);
+static int pc300_tiocmset(struct tty_struct *, unsigned int, unsigned int);
+static int pc300_tiocmget(struct tty_struct *);
 
 /* functions called by PC300 driver */
 void cpc_tty_init(pc300dev_t *dev);
@@ -543,7 +542,7 @@
 	return 0;
 } 
 
-static int pc300_tiocmset(struct tty_struct *tty, struct file *file,
+static int pc300_tiocmset(struct tty_struct *tty,
 			  unsigned int set, unsigned int clear)
 {
 	st_cpc_tty_area    *cpc_tty; 
@@ -570,7 +569,7 @@
 	return 0;
 }
 
-static int pc300_tiocmget(struct tty_struct *tty, struct file *file)
+static int pc300_tiocmget(struct tty_struct *tty)
 {
 	unsigned int result;
 	unsigned char status;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wan/z85230.c linux-libre-2.6.39-gnu/drivers/net/wan/z85230.c
--- linux-libre-2.6.38-gnu/drivers/net/wan/z85230.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wan/z85230.c	2011-05-19 00:06:34.000000000 -0400
@@ -542,7 +542,7 @@
 		z8530_tx(chan);
 		return;
 	}
-	/* This shouldnt occur in DMA mode */
+	/* This shouldn't occur in DMA mode */
 	printk(KERN_ERR "DMA tx - bogus event!\n");
 	z8530_tx(chan);
 }
@@ -1219,7 +1219,7 @@
  *	@io: the port value in question
  *
  *	Describe a Z8530 in a standard format. We must pass the I/O as
- *	the port offset isnt predictable. The main reason for this function
+ *	the port offset isn't predictable. The main reason for this function
  *	is to try and get a common format of report.
  */
 
@@ -1588,7 +1588,7 @@
 		unsigned long flags;
 		
 		/*
-		 *	Complete this DMA. Neccessary to find the length
+		 *	Complete this DMA. Necessary to find the length
 		 */		
 		 
 		flags=claim_dma_lock();
@@ -1657,7 +1657,7 @@
 		 *	fifo length for this. Thus we want to flip to the new
 		 *	buffer and then mess around copying and allocating
 		 *	things. For the current case it doesn't matter but
-		 *	if you build a system where the sync irq isnt blocked
+		 *	if you build a system where the sync irq isn't blocked
 		 *	by the kernel IRQ disable then you need only block the
 		 *	sync IRQ for the RT_LOCK area.
 		 *
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/control.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/control.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/control.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/control.c	2011-05-19 00:06:34.000000000 -0400
@@ -378,7 +378,7 @@
  * the device's state as sometimes we need to do a link-renew (the BS
  * wants us to renew a DHCP lease, for example).
  *
- * In fact, doc says that everytime we get a link-up, we should do a
+ * In fact, doc says that every time we get a link-up, we should do a
  * DHCP negotiation...
  */
 static
@@ -675,7 +675,7 @@
  *  - the ack message wasn't formatted correctly
  *
  * The returned skb has been allocated with wimax_msg_to_user_alloc(),
- * it contains the reponse in a netlink attribute and is ready to be
+ * it contains the response in a netlink attribute and is ready to be
  * passed up to user space with wimax_msg_to_user_send(). To access
  * the payload and its length, use wimax_msg_{data,len}() on the skb.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/driver.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/driver.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -654,7 +654,7 @@
 	if (result == -EUCLEAN) {
 		/*
 		 * We come here because the reset during operational mode
-		 * wasn't successully done and need to proceed to a bus
+		 * wasn't successfully done and need to proceed to a bus
 		 * reset. For the dev_reset_handle() to be able to handle
 		 * the reset event later properly, we restore boot_mode back
 		 * to the state before previous reset. ie: just like we are
@@ -755,7 +755,7 @@
  * Alloc the command and ack buffers for boot mode
  *
  * Get the buffers needed to deal with boot mode messages.  These
- * buffers need to be allocated before the sdio recieve irq is setup.
+ * buffers need to be allocated before the sdio receive irq is setup.
  */
 static
 int i2400m_bm_buf_alloc(struct i2400m *i2400m)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/fw.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/fw.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/fw.c	2012-03-24 01:16:16.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/fw.c	2012-03-24 03:35:28.000000000 -0400
@@ -54,7 +54,7 @@
  * endpoint and read from it in the notification endpoint. In SDIO we
  * talk to it via the write address and read from the read address.
  *
- * Upon entrance to boot mode, the device sends (preceeded with a few
+ * Upon entrance to boot mode, the device sends (preceded with a few
  * zero length packets (ZLPs) on the notification endpoint in USB) a
  * reboot barker (4 le32 words with the same value). We ack it by
  * sending the same barker to the device. The device acks with a
@@ -1589,7 +1589,7 @@
 		i2400m->fw_name = fw_name;
 		ret = i2400m_fw_bootstrap(i2400m, fw, flags);
 		release_firmware(fw);
-		if (ret >= 0)	/* firmware loaded succesfully */
+		if (ret >= 0)	/* firmware loaded successfully */
 			break;
 		i2400m->fw_name = NULL;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/i2400m.h linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/i2400m.h
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/i2400m.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/i2400m.h	2011-05-19 00:06:34.000000000 -0400
@@ -526,7 +526,7 @@
  *
  * @barker: barker type that the device uses; this is initialized by
  *     i2400m_is_boot_barker() the first time it is called. Then it
- *     won't change during the life cycle of the device and everytime
+ *     won't change during the life cycle of the device and every time
  *     a boot barker is received, it is just verified for it being the
  *     same.
  *
@@ -928,7 +928,7 @@
 	struct i2400m *, const struct i2400m_tlv_rf_switches_status *);
 
 /*
- * Helpers for firmware backwards compability
+ * Helpers for firmware backwards compatibility
  *
  * As we aim to support at least the firmware version that was
  * released with the previous kernel/driver release, some code will be
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/i2400m-usb.h linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/i2400m-usb.h
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/i2400m-usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/i2400m-usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -105,14 +105,14 @@
  *
  * @edc: pointer to error density counter.
  * @max_err: maximum number of errors we can accept over the timeframe
- * @timeframe: lenght of the timeframe (in jiffies).
+ * @timeframe: length of the timeframe (in jiffies).
  *
  * Returns: !0 1 if maximum acceptable errors per timeframe has been
  *     exceeded. 0 otherwise.
  *
  * This is way to determine if the number of acceptable errors per time
  * period has been exceeded. It is not accurate as there are cases in which
- * this scheme will not work, for example if there are periodic occurences
+ * this scheme will not work, for example if there are periodic occurrences
  * of errors that straddle updates to the start time. This scheme is
  * sufficient for our usage.
  *
@@ -204,7 +204,7 @@
  *     usb_autopm_get/put_interface() barriers when executing
  *     commands. See doc in i2400mu_suspend() for more information.
  *
- * @rx_size_auto_shrink: if true, the rx_size is shrinked
+ * @rx_size_auto_shrink: if true, the rx_size is shrunk
  *     automatically based on the average size of the received
  *     transactions. This allows the receive code to allocate smaller
  *     chunks of memory and thus reduce pressure on the memory
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/netdev.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/netdev.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/netdev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/netdev.c	2011-05-19 00:06:34.000000000 -0400
@@ -166,7 +166,7 @@
 	d_fnstart(3, dev, "(ws %p i2400m %p skb %p)\n", ws, i2400m, skb);
 	result = -EINVAL;
 	if (skb == NULL) {
-		dev_err(dev, "WAKE&TX: skb dissapeared!\n");
+		dev_err(dev, "WAKE&TX: skb disappeared!\n");
 		goto out_put;
 	}
 	/* If we have, somehow, lost the connection after this was
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/op-rfkill.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/op-rfkill.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/op-rfkill.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/op-rfkill.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
  * - report changes in the HW RF Kill switch [with
  *   wimax_rfkill_{sw,hw}_report(), which happens when we detect those
  *   indications coming through hardware reports]. We also do it on
- *   initialization to let the stack know the intial HW state.
+ *   initialization to let the stack know the initial HW state.
  *
  * - implement indications from the stack to change the SW RF Kill
  *   switch (coming from sysfs, the wimax stack or user space).
@@ -73,7 +73,7 @@
  * Generic Netlink will call this function when a message is sent from
  * userspace to change the software RF-Kill switch status.
  *
- * This function will set the device's sofware RF-Kill switch state to
+ * This function will set the device's software RF-Kill switch state to
  * match what is requested.
  *
  * NOTE: the i2400m has a strict state machine; we can only set the
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/rx.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -349,7 +349,7 @@
  *
  * For reports: We can't clone the original skb where the data is
  * because we need to send this up via netlink; netlink has to add
- * headers and we can't overwrite what's preceeding the payload...as
+ * headers and we can't overwrite what's preceding the payload...as
  * it is another message. So we just dup them.
  */
 static
@@ -425,7 +425,7 @@
  *
  * As in i2400m_rx_ctl(), we can't clone the original skb where the
  * data is because we need to send this up via netlink; netlink has to
- * add headers and we can't overwrite what's preceeding the
+ * add headers and we can't overwrite what's preceding the
  * payload...as it is another message. So we just dup them.
  */
 static
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/tx.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -149,7 +149,7 @@
  * (with a moved message header to make sure it is size-aligned to
  * 16), TAIL room that was unusable (and thus is marked with a message
  * header that says 'skip this') and at the head of the buffer, an
- * imcomplete message with a couple of payloads.
+ * incomplete message with a couple of payloads.
  *
  * N   ___________________________________________________
  *    |                                                   |
@@ -819,7 +819,7 @@
  * the FIF that is ready for transmission.
  *
  * It sets the state in @i2400m to indicate the bus-specific driver is
- * transfering that message (i2400m->tx_msg_size).
+ * transferring that message (i2400m->tx_msg_size).
  *
  * Once the transfer is completed, call i2400m_tx_msg_sent().
  *
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/usb-fw.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/usb-fw.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/usb-fw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/usb-fw.c	2011-05-19 00:06:34.000000000 -0400
@@ -169,7 +169,7 @@
  *
  * Command can be a raw command, which requires no preparation (and
  * which might not even be following the command format). Checks that
- * the right amount of data was transfered.
+ * the right amount of data was transferred.
  *
  * To satisfy USB requirements (no onstack, vmalloc or in data segment
  * buffers), we copy the command to i2400m->bm_cmd_buf and send it from
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/usb-rx.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/usb-rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/usb-rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/usb-rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,7 +58,7 @@
  *    a zillion reads; by serializing, we are throttling.
  *
  *  - RX data processing can get heavy enough so that it is not
- *    appropiate for doing it in the USB callback; thus we run it in a
+ *    appropriate for doing it in the USB callback; thus we run it in a
  *    process context.
  *
  * We provide a read buffer of an arbitrary size (short of a page); if
diff -druN linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/usb-tx.c linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/usb-tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wimax/i2400m/usb-tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wimax/i2400m/usb-tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -168,7 +168,7 @@
 /*
  * Get the next TX message in the TX FIFO and send it to the device
  *
- * Note we exit the loop if i2400mu_tx() fails; that funtion only
+ * Note we exit the loop if i2400mu_tx() fails; that function only
  * fails on hard error (failing to tx a buffer not being one of them,
  * see its doc).
  *
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/adm8211.c linux-libre-2.6.39-gnu/drivers/net/wireless/adm8211.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/adm8211.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/adm8211.c	2011-05-19 00:06:34.000000000 -0400
@@ -1658,7 +1658,7 @@
 }
 
 /* Put adm8211_tx_hdr on skb and transmit */
-static int adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void adm8211_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct adm8211_tx_hdr *txhdr;
 	size_t payload_len, hdrlen;
@@ -1707,8 +1707,6 @@
 	txhdr->retry_limit = info->control.rates[0].count;
 
 	adm8211_tx_raw(dev, skb, plcp_signal, hdrlen);
-
-	return NETDEV_TX_OK;
 }
 
 static int adm8211_alloc_rings(struct ieee80211_hw *dev)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/airo.c linux-libre-2.6.39-gnu/drivers/net/wireless/airo.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/airo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/airo.c	2011-05-19 00:06:34.000000000 -0400
@@ -1884,7 +1884,7 @@
 	/* Make sure the card is configured.
 	 * Wireless Extensions may postpone config changes until the card
 	 * is open (to pipeline changes and speed-up card setup). If
-	 * those changes are not yet commited, do it now - Jean II */
+	 * those changes are not yet committed, do it now - Jean II */
 	if (test_bit(FLAG_COMMIT, &ai->flags)) {
 		disable_MAC(ai, 1);
 		writeConfigRid(ai, 1);
@@ -1992,7 +1992,7 @@
 /*
  * Magic, the cards firmware needs a length count (2 bytes) in the host buffer
  * right after  TXFID_HDR.The TXFID_HDR contains the status short so payloadlen
- * is immediatly after it. ------------------------------------------------
+ * is immediately after it. ------------------------------------------------
  *                         |TXFIDHDR+STATUS|PAYLOADLEN|802.3HDR|PACKETDATA|
  *                         ------------------------------------------------
  */
@@ -2006,7 +2006,7 @@
 		sizeof(wifictlhdr8023) + 2 ;
 
 	/*
-	 * Firmware automaticly puts 802 header on so
+	 * Firmware automatically puts 802 header on so
 	 * we don't need to account for it in the length
 	 */
 	if (test_bit(FLAG_MIC_CAPABLE, &ai->flags) && ai->micstats.enabled &&
@@ -2531,7 +2531,7 @@
 /*
  * We are setting up three things here:
  * 1) Map AUX memory for descriptors: Rid, TxFid, or RxFid.
- * 2) Map PCI memory for issueing commands.
+ * 2) Map PCI memory for issuing commands.
  * 3) Allocate memory (shared) to send and receive ethernet frames.
  */
 static int mpi_map_card(struct airo_info *ai, struct pci_dev *pci)
@@ -3947,7 +3947,7 @@
 
 	if ( max_tries == -1 ) {
 		airo_print_err(ai->dev->name,
-			"Max tries exceeded when issueing command");
+			"Max tries exceeded when issuing command");
 		if (IN4500(ai, COMMAND) & COMMAND_BUSY)
 			OUT4500(ai, EVACK, EV_CLEARCOMMANDBUSY);
 		return ERROR;
@@ -4173,7 +4173,7 @@
 }
 
 /*  Note, that we are using BAP1 which is also used by transmit, so
- *  make sure this isnt called when a transmit is happening */
+ *  make sure this isn't called when a transmit is happening */
 static int PC4500_writerid(struct airo_info *ai, u16 rid,
 			   const void *pBuf, int len, int lock)
 {
@@ -4776,7 +4776,7 @@
 		if (!statsLabels[i]) continue;
 		if (j+strlen(statsLabels[i])+16>4096) {
 			airo_print_warn(apriv->dev->name,
-			       "Potentially disasterous buffer overflow averted!");
+			       "Potentially disastrous buffer overflow averted!");
 			break;
 		}
 		j+=sprintf(data->rbuffer+j, "%s: %u\n", statsLabels[i],
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/at76c50x-usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/at76c50x-usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/at76c50x-usb.c	2012-03-24 01:10:29.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/at76c50x-usb.c	2012-03-24 03:32:12.000000000 -0400
@@ -1721,7 +1721,7 @@
 	ieee80211_wake_queues(priv->hw);
 }
 
-static int at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void at76_mac80211_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct at76_priv *priv = hw->priv;
 	struct at76_tx_buffer *tx_buffer = priv->bulk_out_buffer;
@@ -1734,7 +1734,8 @@
 	if (priv->tx_urb->status == -EINPROGRESS) {
 		wiphy_err(priv->hw->wiphy,
 			  "%s called while tx urb is pending\n", __func__);
-		return NETDEV_TX_BUSY;
+		dev_kfree_skb_any(skb);
+		return;
 	}
 
 	/* The following code lines are important when the device is going to
@@ -1748,7 +1749,8 @@
 		if (compare_ether_addr(priv->bssid, mgmt->bssid)) {
 			memcpy(priv->bssid, mgmt->bssid, ETH_ALEN);
 			ieee80211_queue_work(hw, &priv->work_join_bssid);
-			return NETDEV_TX_BUSY;
+			dev_kfree_skb_any(skb);
+			return;
 		}
 	}
 
@@ -1788,8 +1790,6 @@
 				  priv->tx_urb,
 				  priv->tx_urb->hcpriv, priv->tx_urb->complete);
 	}
-
-	return 0;
 }
 
 static int at76_mac80211_start(struct ieee80211_hw *hw)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/at76c50x-usb.h linux-libre-2.6.39-gnu/drivers/net/wireless/at76c50x-usb.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/at76c50x-usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/at76c50x-usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
 	u8 res;
 	u8 multi_domain_capability_implemented;
 	u8 multi_domain_capability_enabled;
-	u8 country_string[3];
+	u8 country_string[IEEE80211_COUNTRY_STRING_LEN];
 	u8 reserved[3];
 } __packed;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/ar9170.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/ar9170.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/ar9170.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/ar9170.h	2011-05-19 00:06:34.000000000 -0400
@@ -224,7 +224,7 @@
 int ar9170_nag_limiter(struct ar9170 *ar);
 
 /* MAC */
-int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void 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, const u64 mc_hast);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,10 @@
 config AR9170_USB
-	tristate "Atheros AR9170 802.11n USB support"
+	tristate "Atheros AR9170 802.11n USB support (OBSOLETE)"
 	depends on USB && MAC80211
 	select FW_LOADER
 	help
+	  This driver is going to get replaced by carl9170.
+
 	  This is a driver for the Atheros "otus" 802.11n USB devices.
 
 	  These devices require additional firmware (2 files).
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -974,7 +974,7 @@
 			if (ar->rx_failover_missing <= 0) {
 				/*
 				 * nested ar9170_rx call!
-				 * termination is guranteed, even when the
+				 * termination is guaranteed, even when the
 				 * combined frame also have a element with
 				 * a bad tag.
 				 */
@@ -1475,7 +1475,7 @@
 				     msecs_to_jiffies(AR9170_JANITOR_DELAY));
 }
 
-int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ar9170 *ar = hw->priv;
 	struct ieee80211_tx_info *info;
@@ -1493,11 +1493,10 @@
 	skb_queue_tail(&ar->tx_pending[queue], skb);
 
 	ar9170_tx(ar);
-	return NETDEV_TX_OK;
+	return;
 
 err_free:
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 static int ar9170_op_add_interface(struct ieee80211_hw *hw,
@@ -1945,7 +1944,8 @@
 static int ar9170_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ar9170/phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ar9170/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -424,7 +424,7 @@
 
 /*
  * initialize some phy regs from eeprom values in modal_header[]
- * acc. to band and bandwith
+ * acc. to band and bandwidth
  */
 static int ar9170_init_phy_from_eeprom(struct ar9170 *ar,
 				bool is_2ghz, bool is_40mhz)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/ahb.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/ahb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/ahb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/ahb.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,8 @@
 	*csz = L1_CACHE_BYTES >> 2;
 }
 
-bool ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
+static bool
+ath5k_ahb_eeprom_read(struct ath_common *common, u32 off, u16 *data)
 {
 	struct ath5k_softc *sc = common->priv;
 	struct platform_device *pdev = to_platform_device(sc->dev);
@@ -46,10 +47,10 @@
 
 	eeprom += off;
 	if (eeprom > eeprom_end)
-		return -EINVAL;
+		return false;
 
 	*data = *eeprom;
-	return 0;
+	return true;
 }
 
 int ath5k_hw_read_srev(struct ath5k_hw *ah)
@@ -92,7 +93,7 @@
 		goto err_out;
 	}
 
-	mem = ioremap_nocache(res->start, res->end - res->start + 1);
+	mem = ioremap_nocache(res->start, resource_size(res));
 	if (mem == NULL) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/ani.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/ani.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/ani.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/ani.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 #define ATH5K_ANI_RSSI_THR_HIGH		40
 #define ATH5K_ANI_RSSI_THR_LOW		7
 
-/* maximum availabe levels */
+/* maximum available levels */
 #define ATH5K_ANI_MAX_FIRSTEP_LVL	2
 #define ATH5K_ANI_MAX_NOISE_IMM_LVL	1
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/ath5k.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/ath5k.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/ath5k.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/ath5k.h	2011-05-19 00:06:34.000000000 -0400
@@ -210,14 +210,9 @@
 /* Initial values */
 #define	AR5K_INIT_CYCRSSI_THR1			2
 
-/* Tx retry limits */
-#define AR5K_INIT_SH_RETRY			10
-#define AR5K_INIT_LG_RETRY			AR5K_INIT_SH_RETRY
-/* For station mode */
-#define AR5K_INIT_SSH_RETRY			32
-#define AR5K_INIT_SLG_RETRY			AR5K_INIT_SSH_RETRY
-#define AR5K_INIT_TX_RETRY			10
-
+/* Tx retry limit defaults from standard */
+#define AR5K_INIT_RETRY_SHORT			7
+#define AR5K_INIT_RETRY_LONG			4
 
 /* Slot time */
 #define AR5K_INIT_SLOT_TIME_TURBO		6
@@ -518,7 +513,7 @@
 	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_MAX	= 3, /*IEEE80211_TX_QUEUE_DATA3*/
 	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*/
@@ -1057,7 +1052,9 @@
 #define ah_modes		ah_capabilities.cap_mode
 #define ah_ee_version		ah_capabilities.cap_eeprom.ee_version
 
-	u32			ah_limit_tx_retries;
+	u8			ah_retry_long;
+	u8			ah_retry_short;
+
 	u8			ah_coverage_class;
 	bool			ah_ack_bitrate_high;
 	u8			ah_bwmode;
@@ -1067,7 +1064,6 @@
 	u8			ah_ant_mode;
 	u8			ah_tx_ant;
 	u8			ah_def_ant;
-	bool			ah_software_retry;
 
 	struct ath5k_capabilities ah_capabilities;
 
@@ -1162,6 +1158,26 @@
 int ath5k_sysfs_register(struct ath5k_softc *sc);
 void ath5k_sysfs_unregister(struct ath5k_softc *sc);
 
+/* base.c */
+struct ath5k_buf;
+struct ath5k_txq;
+
+void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
+bool ath_any_vif_assoc(struct ath5k_softc *sc);
+void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
+		    struct ath5k_txq *txq);
+int ath5k_init_hw(struct ath5k_softc *sc);
+int ath5k_stop_hw(struct ath5k_softc *sc);
+void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
+void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
+					struct ieee80211_vif *vif);
+int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
+void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
+int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
+void ath5k_beacon_config(struct ath5k_softc *sc);
+void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
+
 /*Chip id helper functions */
 const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
 int ath5k_hw_read_srev(struct ath5k_hw *ah);
@@ -1250,6 +1266,8 @@
 int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah,
 			    enum ath5k_tx_queue queue_type,
 			    struct ath5k_txq_info *queue_info);
+void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
+				  unsigned int queue);
 u32 ath5k_hw_num_tx_pending(struct ath5k_hw *ah, unsigned int queue);
 void ath5k_hw_release_tx_queue(struct ath5k_hw *ah, unsigned int queue);
 int ath5k_hw_reset_tx_queue(struct ath5k_hw *ah, unsigned int queue);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/attach.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/attach.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/attach.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/attach.c	2011-05-19 00:06:34.000000000 -0400
@@ -118,8 +118,8 @@
 	ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
 	ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
 	ah->ah_imr = 0;
-	ah->ah_limit_tx_retries = AR5K_INIT_TX_RETRY;
-	ah->ah_software_retry = false;
+	ah->ah_retry_short = AR5K_INIT_RETRY_SHORT;
+	ah->ah_retry_long = AR5K_INIT_RETRY_LONG;
 	ah->ah_ant_mode = AR5K_ANTMODE_DEFAULT;
 	ah->ah_noise_floor = -95;	/* until first NF calibration is run */
 	sc->ani_state.ani_mode = ATH5K_ANI_MODE_AUTO;
@@ -220,7 +220,8 @@
 			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)) {
+		} else if (ah->ah_mac_version == (AR5K_SREV_AR2415 >> 4) ||
+			ah->ah_mac_version == (AR5K_SREV_AR2315_R6 >> 4)) {
 			ah->ah_radio = AR5K_RF2316;
 			ah->ah_single_chip = true;
 			ah->ah_radio_5ghz_revision = AR5K_SREV_RAD_2316;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/base.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/base.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/base.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,6 +61,9 @@
 #include "debug.h"
 #include "ani.h"
 
+#define CREATE_TRACE_POINTS
+#include "trace.h"
+
 int ath5k_modparam_nohwcrypt;
 module_param_named(nohwcrypt, ath5k_modparam_nohwcrypt, bool, S_IRUGO);
 MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
@@ -242,73 +245,68 @@
 \********************/
 
 /*
- * 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)
+static bool ath5k_is_standard_channel(short chan, enum ieee80211_band band)
 {
-	return ((chan <= 14) ||
-		/* UNII 1,2 */
-		((chan & 3) == 0 && chan >= 36 && chan <= 64) ||
+	if (band == IEEE80211_BAND_2GHZ && chan <= 14)
+		return true;
+
+	return	/* 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));
+		((chan & 3) == 1 && chan >= 149 && chan <= 165) ||
+		/* 802.11j 5.030-5.080 GHz (20MHz) */
+		(chan == 8 || chan == 12 || chan == 16) ||
+		/* 802.11j 4.9GHz (20MHz) */
+		(chan == 184 || chan == 188 || chan == 192 || chan == 196));
 }
 
 static unsigned int
-ath5k_copy_channels(struct ath5k_hw *ah,
-		struct ieee80211_channel *channels,
-		unsigned int mode,
-		unsigned int max)
+ath5k_setup_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;
+	unsigned int count, size, chfreq, freq, ch;
+	enum ieee80211_band band;
 
 	switch (mode) {
 	case AR5K_MODE_11A:
 		/* 1..220, but 2GHz frequencies are filtered by check_channel */
-		size = 220 ;
+		size = 220;
 		chfreq = CHANNEL_5GHZ;
+		band = IEEE80211_BAND_5GHZ;
 		break;
 	case AR5K_MODE_11B:
 	case AR5K_MODE_11G:
 		size = 26;
 		chfreq = CHANNEL_2GHZ;
+		band = IEEE80211_BAND_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);
+	count = 0;
+	for (ch = 1; ch <= size && count < max; ch++) {
+		freq = ieee80211_channel_to_frequency(ch, band);
+
+		if (freq == 0) /* mapping failed - not a standard channel */
+			continue;
 
 		/* 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))
+		if (!modparam_all_channels &&
+		    !ath5k_is_standard_channel(ch, band))
 			continue;
 
 		/* Write channel info and increment counter */
 		channels[count].center_freq = freq;
-		channels[count].band = (chfreq == CHANNEL_2GHZ) ?
-			IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+		channels[count].band = band;
 		switch (mode) {
 		case AR5K_MODE_11A:
 		case AR5K_MODE_11G:
@@ -319,7 +317,6 @@
 		}
 
 		count++;
-		max--;
 	}
 
 	return count;
@@ -364,7 +361,7 @@
 		sband->n_bitrates = 12;
 
 		sband->channels = sc->channels;
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11G, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
@@ -390,7 +387,7 @@
 		}
 
 		sband->channels = sc->channels;
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11B, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_2GHZ] = sband;
@@ -410,7 +407,7 @@
 		sband->n_bitrates = 8;
 
 		sband->channels = &sc->channels[count_c];
-		sband->n_channels = ath5k_copy_channels(ah, sband->channels,
+		sband->n_channels = ath5k_setup_channels(ah, sband->channels,
 					AR5K_MODE_11A, max_c);
 
 		hw->wiphy->bands[IEEE80211_BAND_5GHZ] = sband;
@@ -445,31 +442,9 @@
 	return ath5k_reset(sc, chan, true);
 }
 
-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];
-	}
-}
-
-struct ath_vif_iter_data {
-	const u8	*hw_macaddr;
-	u8		mask[ETH_ALEN];
-	u8		active_mac[ETH_ALEN]; /* first active MAC */
-	bool		need_set_hw_addr;
-	bool		found_active;
-	bool		any_assoc;
-	enum nl80211_iftype opmode;
-};
-
-static void ath_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
 {
-	struct ath_vif_iter_data *iter_data = data;
+	struct ath5k_vif_iter_data *iter_data = data;
 	int i;
 	struct ath5k_vif *avf = (void *)vif->drv_priv;
 
@@ -499,9 +474,12 @@
 	 */
 	if (avf->opmode == NL80211_IFTYPE_AP)
 		iter_data->opmode = NL80211_IFTYPE_AP;
-	else
+	else {
+		if (avf->opmode == NL80211_IFTYPE_STATION)
+			iter_data->n_stas++;
 		if (iter_data->opmode == NL80211_IFTYPE_UNSPECIFIED)
 			iter_data->opmode = avf->opmode;
+	}
 }
 
 void
@@ -509,7 +487,8 @@
 				   struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath5k_hw_common(sc->ah);
-	struct ath_vif_iter_data iter_data;
+	struct ath5k_vif_iter_data iter_data;
+	u32 rfilt;
 
 	/*
 	 * Use the hardware MAC address as reference, the hardware uses it
@@ -520,12 +499,13 @@
 	iter_data.found_active = false;
 	iter_data.need_set_hw_addr = true;
 	iter_data.opmode = NL80211_IFTYPE_UNSPECIFIED;
+	iter_data.n_stas = 0;
 
 	if (vif)
-		ath_vif_iter(&iter_data, vif->addr, vif);
+		ath5k_vif_iter(&iter_data, vif->addr, vif);
 
 	/* Get list of all active MAC addresses */
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
 						   &iter_data);
 	memcpy(sc->bssidmask, iter_data.mask, ETH_ALEN);
 
@@ -543,20 +523,19 @@
 
 	if (ath5k_hw_hasbssidmask(sc->ah))
 		ath5k_hw_set_bssid_mask(sc->ah, sc->bssidmask);
-}
 
-void
-ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif)
-{
-	struct ath5k_hw *ah = sc->ah;
-	u32 rfilt;
+	/* Set up RX Filter */
+	if (iter_data.n_stas > 1) {
+		/* If you have multiple STA interfaces connected to
+		 * different APs, ARPs are not received (most of the time?)
+		 * Enabling PROMISC appears to fix that probem.
+		 */
+		sc->filter_flags |= AR5K_RX_FILTER_PROM;
+	}
 
-	/* configure rx filter */
 	rfilt = sc->filter_flags;
-	ath5k_hw_set_rx_filter(ah, rfilt);
+	ath5k_hw_set_rx_filter(sc->ah, rfilt);
 	ATH5K_DBG(sc, ATH5K_DEBUG_MODE, "RX filter 0x%x\n", rfilt);
-
-	ath5k_update_bssid_mask_and_opmode(sc, vif);
 }
 
 static inline int
@@ -569,7 +548,7 @@
 			"hw_rix out of bounds: %x\n", hw_rix))
 		return 0;
 
-	rix = sc->rate_idx[sc->curband->band][hw_rix];
+	rix = sc->rate_idx[sc->curchan->band][hw_rix];
 	if (WARN(rix < 0, "invalid hw_rix: %x\n", hw_rix))
 		rix = 0;
 
@@ -964,6 +943,7 @@
 		spin_lock_init(&txq->lock);
 		txq->setup = true;
 		txq->txq_len = 0;
+		txq->txq_max = ATH5K_TXQ_LEN_MAX;
 		txq->txq_poll_mark = false;
 		txq->txq_stuck = 0;
 	}
@@ -1132,7 +1112,7 @@
 	spin_unlock_bh(&sc->rxbuflock);
 
 	ath5k_hw_start_rx_dma(ah);	/* enable recv descriptors */
-	ath5k_mode_setup(sc, NULL);		/* set filters, etc. */
+	ath5k_update_bssid_mask_and_opmode(sc, NULL); /* set filters, etc. */
 	ath5k_hw_start_rx_pcu(ah);	/* re-enable PCU/DMA engine */
 
 	return 0;
@@ -1376,10 +1356,10 @@
 	 * right now, so it's not too bad...
 	 */
 	rxs->mactime = ath5k_extend_tsf(sc->ah, rs->rs_tstamp);
-	rxs->flag |= RX_FLAG_TSFT;
+	rxs->flag |= RX_FLAG_MACTIME_MPDU;
 
 	rxs->freq = sc->curchan->center_freq;
-	rxs->band = sc->curband->band;
+	rxs->band = sc->curchan->band;
 
 	rxs->signal = sc->ah->ah_noise_floor + rs->rs_rssi;
 
@@ -1394,10 +1374,10 @@
 	rxs->flag |= ath5k_rx_decrypted(sc, skb, rs);
 
 	if (rxs->rate_idx >= 0 && rs->rs_rate ==
-	    sc->curband->bitrates[rxs->rate_idx].hw_value_short)
+	    sc->sbands[sc->curchan->band].bitrates[rxs->rate_idx].hw_value_short)
 		rxs->flag |= RX_FLAG_SHORTPRE;
 
-	ath5k_debug_dump_skb(sc, skb, "RX  ", 0);
+	trace_ath5k_rx(sc, skb);
 
 	ath5k_update_beacon_rssi(sc, skb, rs->rs_rssi);
 
@@ -1533,7 +1513,7 @@
 * TX Handling *
 \*************/
 
-int
+void
 ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
 	       struct ath5k_txq *txq)
 {
@@ -1542,7 +1522,7 @@
 	unsigned long flags;
 	int padsize;
 
-	ath5k_debug_dump_skb(sc, skb, "TX  ", 1);
+	trace_ath5k_tx(sc, skb, txq);
 
 	/*
 	 * The hardware expects the header padded to 4 byte boundaries.
@@ -1555,7 +1535,7 @@
 		goto drop_packet;
 	}
 
-	if (txq->txq_len >= ATH5K_TXQ_LEN_MAX)
+	if (txq->txq_len >= txq->txq_max)
 		ieee80211_stop_queue(hw, txq->qnum);
 
 	spin_lock_irqsave(&sc->txbuflock, flags);
@@ -1582,16 +1562,15 @@
 		spin_unlock_irqrestore(&sc->txbuflock, flags);
 		goto drop_packet;
 	}
-	return NETDEV_TX_OK;
+	return;
 
 drop_packet:
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 static void
 ath5k_tx_frame_completed(struct ath5k_softc *sc, struct sk_buff *skb,
-			 struct ath5k_tx_status *ts)
+			 struct ath5k_txq *txq, struct ath5k_tx_status *ts)
 {
 	struct ieee80211_tx_info *info;
 	int i;
@@ -1643,6 +1622,7 @@
 	else
 		sc->stats.antenna_tx[0]++; /* invalid */
 
+	trace_ath5k_tx_complete(sc, skb, txq, ts);
 	ieee80211_tx_status(sc->hw, skb);
 }
 
@@ -1679,7 +1659,7 @@
 
 			dma_unmap_single(sc->dev, bf->skbaddr, skb->len,
 					DMA_TO_DEVICE);
-			ath5k_tx_frame_completed(sc, skb, &ts);
+			ath5k_tx_frame_completed(sc, skb, txq, &ts);
 		}
 
 		/*
@@ -1821,8 +1801,6 @@
 		goto out;
 	}
 
-	ath5k_debug_dump_skb(sc, skb, "BC  ", 1);
-
 	ath5k_txbuf_free_skb(sc, avf->bbuf);
 	avf->bbuf->skb = skb;
 	ret = ath5k_beacon_setup(sc, avf->bbuf);
@@ -1917,6 +1895,8 @@
 			sc->opmode == NL80211_IFTYPE_MESH_POINT)
 		ath5k_beacon_update(sc->hw, vif);
 
+	trace_ath5k_tx(sc, bf->skb, &sc->txqs[sc->bhalq]);
+
 	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",
@@ -1973,7 +1953,7 @@
 
 #define FUDGE AR5K_TUNE_SW_BEACON_RESP + 3
 	/* We use FUDGE to make sure the next TBTT is ahead of the current TU.
-	 * Since we later substract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
+	 * Since we later subtract AR5K_TUNE_SW_BEACON_RESP (10) in the timer
 	 * configuration we need to make sure it is bigger than that. */
 
 	if (bc_tsf == -1) {
@@ -1991,7 +1971,7 @@
 		intval |= AR5K_BEACON_RESET_TSF;
 	} else if (bc_tsf > hw_tsf) {
 		/*
-		 * beacon received, SW merge happend but HW TSF not yet updated.
+		 * beacon received, SW merge happened 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
@@ -2417,7 +2397,8 @@
 	/* set up multi-rate retry capabilities */
 	if (sc->ah->ah_version == AR5K_AR5212) {
 		hw->max_rates = 4;
-		hw->max_rate_tries = 11;
+		hw->max_rate_tries = max(AR5K_INIT_RETRY_SHORT,
+					 AR5K_INIT_RETRY_LONG);
 	}
 
 	hw->vif_data_size = sizeof(struct ath5k_vif);
@@ -2554,7 +2535,6 @@
 	 * 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 | AR5K_INT_MIB;
@@ -2671,7 +2651,7 @@
 	synchronize_irq(sc->irq);
 	stop_tasklets(sc);
 
-	/* Save ani mode and disable ANI durring
+	/* Save ani mode and disable ANI during
 	 * reset. If we don't we might get false
 	 * PHY error interrupts. */
 	ani_mode = ah->ah_sc->ani_state.ani_mode;
@@ -2681,10 +2661,8 @@
 	 * so we should also free any remaining
 	 * tx buffers */
 	ath5k_drain_tx_buffs(sc);
-	if (chan) {
+	if (chan)
 		sc->curchan = chan;
-		sc->curband = &sc->sbands[chan->band];
-	}
 	ret = ath5k_hw_reset(ah, sc->opmode, sc->curchan, chan != NULL,
 								skip_pcu);
 	if (ret) {
@@ -2782,12 +2760,6 @@
 		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.
 	 */
@@ -2946,13 +2918,13 @@
 bool
 ath_any_vif_assoc(struct ath5k_softc *sc)
 {
-	struct ath_vif_iter_data iter_data;
+	struct ath5k_vif_iter_data iter_data;
 	iter_data.hw_macaddr = NULL;
 	iter_data.any_assoc = false;
 	iter_data.need_set_hw_addr = false;
 	iter_data.found_active = true;
 
-	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath_vif_iter,
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
 						   &iter_data);
 	return iter_data.any_assoc;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/base.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/base.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/base.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/base.h	2011-05-19 00:06:34.000000000 -0400
@@ -86,6 +86,7 @@
 	spinlock_t		lock;	/* lock on q and link */
 	bool			setup;
 	int			txq_len; /* number of queued buffers */
+	int			txq_max; /* max allowed num of queued buffers */
 	bool			txq_poll_mark;
 	unsigned int		txq_stuck;	/* informational counter */
 };
@@ -183,8 +184,6 @@
 	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 */
@@ -202,7 +201,6 @@
 #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 */
 
 	u16			nvifs;
@@ -262,6 +260,19 @@
 	struct survey_info	survey;		/* collected survey info */
 };
 
+struct ath5k_vif_iter_data {
+	const u8	*hw_macaddr;
+	u8		mask[ETH_ALEN];
+	u8		active_mac[ETH_ALEN]; /* first active MAC */
+	bool		need_set_hw_addr;
+	bool		found_active;
+	bool		any_assoc;
+	enum nl80211_iftype opmode;
+	int n_stas;
+};
+void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
+
+
 #define ath5k_hw_hasbssidmask(_ah) \
 	(ath5k_hw_get_capability(_ah, AR5K_CAP_BSSIDMASK, 0, NULL) == 0)
 #define ath5k_hw_hasveol(_ah) \
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/caps.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/caps.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/caps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/caps.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,23 +32,24 @@
  */
 int ath5k_hw_set_capabilities(struct ath5k_hw *ah)
 {
+	struct ath5k_capabilities *caps = &ah->ah_capabilities;
 	u16 ee_header;
 
 	/* Capabilities stored in the EEPROM */
-	ee_header = ah->ah_capabilities.cap_eeprom.ee_header;
+	ee_header = caps->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;
+		caps->cap_range.range_5ghz_min = 5120;
+		caps->cap_range.range_5ghz_max = 5430;
+		caps->cap_range.range_2ghz_min = 0;
+		caps->cap_range.range_2ghz_max = 0;
 
 		/* Set supported modes */
-		__set_bit(AR5K_MODE_11A, ah->ah_capabilities.cap_mode);
+		__set_bit(AR5K_MODE_11A, caps->cap_mode);
 	} else {
 		/*
 		 * XXX The tranceiver supports frequencies from 4920 to 6100GHz
@@ -56,9 +57,8 @@
 		 * 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.
+		 * XXX doesn't matter because these channels are out of the
+		 * XXX legal range.
 		 */
 
 		/*
@@ -66,13 +66,14 @@
 		 */
 
 		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;
+			if (ath_is_49ghz_allowed(caps->cap_eeprom.ee_regdomain))
+				caps->cap_range.range_5ghz_min = 4920;
+			else
+				caps->cap_range.range_5ghz_min = 5005;
+			caps->cap_range.range_5ghz_max = 6100;
 
 			/* Set supported modes */
-			__set_bit(AR5K_MODE_11A,
-					ah->ah_capabilities.cap_mode);
+			__set_bit(AR5K_MODE_11A, caps->cap_mode);
 		}
 
 		/* Enable  802.11b if a 2GHz capable radio (2111/5112) is
@@ -81,32 +82,29 @@
 		    (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;
+			caps->cap_range.range_2ghz_min = 2412;
+			caps->cap_range.range_2ghz_max = 2732;
 
 			if (AR5K_EEPROM_HDR_11B(ee_header))
-				__set_bit(AR5K_MODE_11B,
-						ah->ah_capabilities.cap_mode);
+				__set_bit(AR5K_MODE_11B, caps->cap_mode);
 
 			if (AR5K_EEPROM_HDR_11G(ee_header) &&
 			    ah->ah_version != AR5K_AR5211)
-				__set_bit(AR5K_MODE_11G,
-						ah->ah_capabilities.cap_mode);
+				__set_bit(AR5K_MODE_11G, caps->cap_mode);
 		}
 	}
 
 	/* 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;
+		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES_NOQCU;
 	else
-		ah->ah_capabilities.cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
+		caps->cap_queues.q_tx_num = AR5K_NUM_TX_QUEUES;
 
 	/* newer hardware has PHY error counters */
 	if (ah->ah_mac_srev >= AR5K_SREV_AR5213A)
-		ah->ah_capabilities.cap_has_phyerr_counters = true;
+		caps->cap_has_phyerr_counters = true;
 	else
-		ah->ah_capabilities.cap_has_phyerr_counters = false;
+		caps->cap_has_phyerr_counters = false;
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/debug.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/debug.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -308,8 +308,6 @@
 	{ 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_DMA,	"dma",		"dma start/stop" },
 	{ ATH5K_DEBUG_ANI,	"ani",		"adaptive noise immunity" },
@@ -1036,24 +1034,6 @@
 }
 
 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;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/debug.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/debug.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/debug.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -116,8 +116,6 @@
 	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_DMA		= 0x00000800,
 	ATH5K_DEBUG_ANI		= 0x00002000,
@@ -152,10 +150,6 @@
 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 */
@@ -182,10 +176,6 @@
 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 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/desc.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/desc.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/desc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/desc.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
 	/*
 	 * Validate input
 	 * - Zero retries don't make sense.
-	 * - A zero rate will put the HW into a mode where it continously sends
+	 * - A zero rate will put the HW into a mode where it continuously sends
 	 *   noise on the channel, so it is important to avoid this.
 	 */
 	if (unlikely(tx_tries0 == 0)) {
@@ -190,7 +190,7 @@
 	/*
 	 * Validate input
 	 * - Zero retries don't make sense.
-	 * - A zero rate will put the HW into a mode where it continously sends
+	 * - A zero rate will put the HW into a mode where it continuously sends
 	 *   noise on the channel, so it is important to avoid this.
 	 */
 	if (unlikely(tx_tries0 == 0)) {
@@ -300,7 +300,7 @@
 	/*
 	 * 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
+	 * it continuously sends noise on the channel, so it is important to
 	 * avoid this.
 	 */
 	if (unlikely((tx_rate1 == 0 && tx_tries1 != 0) ||
@@ -342,7 +342,7 @@
 \***********************/
 
 /*
- * Proccess the tx status descriptor on 5210/5211
+ * Process 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)
@@ -394,7 +394,7 @@
 }
 
 /*
- * Proccess a tx status descriptor on 5212
+ * Process 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)
@@ -519,7 +519,7 @@
 }
 
 /*
- * Proccess the rx status descriptor on 5210/5211
+ * Process 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)
@@ -602,7 +602,7 @@
 }
 
 /*
- * Proccess the rx status descriptor on 5212
+ * Process the rx status descriptor on 5212
  */
 static int ath5k_hw_proc_5212_rx_status(struct ath5k_hw *ah,
 					struct ath5k_desc *desc,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -72,7 +72,6 @@
 ath5k_eeprom_init_header(struct ath5k_hw *ah)
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
-	int ret;
 	u16 val;
 	u32 cksum, offset, eep_max = AR5K_EEPROM_INFO_MAX;
 
@@ -192,7 +191,7 @@
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	u32 o = *offset;
 	u16 val;
-	int ret, i = 0;
+	int i = 0;
 
 	AR5K_EEPROM_READ(o++, val);
 	ee->ee_switch_settling[mode]	= (val >> 8) & 0x7f;
@@ -252,7 +251,6 @@
 	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);
@@ -515,7 +513,6 @@
 	int o = *offset;
 	int i = 0;
 	u8 freq1, freq2;
-	int ret;
 	u16 val;
 
 	ee->ee_n_piers[mode] = 0;
@@ -551,7 +548,7 @@
 {
 	struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
 	struct ath5k_chan_pcal_info *pcal = ee->ee_pwr_cal_a;
-	int i, ret;
+	int i;
 	u16 val;
 	u8 mask;
 
@@ -970,7 +967,6 @@
 	u32 offset;
 	u8 i, c;
 	u16 val;
-	int ret;
 	u8 pd_gains = 0;
 
 	/* Count how many curves we have and
@@ -1084,7 +1080,7 @@
  *
  * 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
+ * used (like RF5112) but vendors have the opportunity to include all
  * 4 curves on eeprom. The final curve (higher power) has an extra
  * point for better accuracy like RF5112.
  */
@@ -1228,7 +1224,7 @@
 	struct ath5k_chan_pcal_info *chinfo;
 	u8 *pdgain_idx = ee->ee_pdc_to_idx[mode];
 	u32 offset;
-	int idx, i, ret;
+	int idx, i;
 	u16 val;
 	u8 pd_gains = 0;
 
@@ -1306,7 +1302,7 @@
 			/*
 			 * Pd gain 0 is not the last pd gain
 			 * so it only has 2 pd points.
-			 * Continue wih pd gain 1.
+			 * Continue with pd gain 1.
 			 */
 			pcinfo->pwr_i[1] = (val >> 10) & 0x1f;
 
@@ -1419,7 +1415,7 @@
 	u8 *rate_target_pwr_num;
 	u32 offset;
 	u16 val;
-	int ret, i;
+	int i;
 
 	offset = AR5K_EEPROM_TARGET_PWRSTART(ee->ee_misc1);
 	rate_target_pwr_num = &ee->ee_rate_target_pwr_num[mode];
@@ -1593,7 +1589,7 @@
 	struct ath5k_edge_power *rep;
 	unsigned int fmask, pmask;
 	unsigned int ctl_mode;
-	int ret, i, j;
+	int i, j;
 	u32 offset;
 	u16 val;
 
@@ -1733,16 +1729,12 @@
 	u8 mac_d[ETH_ALEN] = {};
 	u32 total, offset;
 	u16 data;
-	int octet, ret;
+	int octet;
 
-	ret = ath5k_hw_nvram_read(ah, 0x20, &data);
-	if (ret)
-		return ret;
+	AR5K_EEPROM_READ(0x20, data);
 
 	for (offset = 0x1f, octet = 0, total = 0; offset >= 0x1d; offset--) {
-		ret = ath5k_hw_nvram_read(ah, offset, &data);
-		if (ret)
-			return ret;
+		AR5K_EEPROM_READ(offset, data);
 
 		total += data;
 		mac_d[octet + 1] = data & 0xff;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/eeprom.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -241,9 +241,8 @@
 #define	AR5K_SPUR_SYMBOL_WIDTH_TURBO_100Hz	6250
 
 #define AR5K_EEPROM_READ(_o, _v) do {			\
-	ret = ath5k_hw_nvram_read(ah, (_o), &(_v));	\
-	if (ret)					\
-		return ret;				\
+	if (!ath5k_hw_nvram_read(ah, (_o), &(_v)))	\
+		return -EIO;				\
 } while (0)
 
 #define AR5K_EEPROM_READ_HDR(_o, _v)					\
@@ -269,29 +268,6 @@
 	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
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,17 @@
 
 	  modprobe ath5k debug=0x00000400
 
+config ATH5K_TRACER
+	bool "Atheros 5xxx tracer"
+	depends on ATH5K
+	depends on EVENT_TRACING
+	---help---
+	  Say Y here to enable tracepoints for the ath5k driver
+	  using the kernel tracing infrastructure.  Select this
+	  option if you are interested in debugging the driver.
+
+	  If unsure, say N.
+
 config ATH5K_AHB
 	bool "Atheros 5xxx AHB bus support"
 	depends on (ATHEROS_AR231X && !PCI)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/mac80211-ops.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,28 +48,11 @@
 
 extern int ath5k_modparam_nohwcrypt;
 
-/* functions used from base.c */
-void set_beacon_filter(struct ieee80211_hw *hw, bool enable);
-bool ath_any_vif_assoc(struct ath5k_softc *sc);
-int ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
-		   struct ath5k_txq *txq);
-int ath5k_init_hw(struct ath5k_softc *sc);
-int ath5k_stop_hw(struct ath5k_softc *sc);
-void ath5k_mode_setup(struct ath5k_softc *sc, struct ieee80211_vif *vif);
-void ath5k_update_bssid_mask_and_opmode(struct ath5k_softc *sc,
-					struct ieee80211_vif *vif);
-int ath5k_chan_set(struct ath5k_softc *sc, struct ieee80211_channel *chan);
-void ath5k_beacon_update_timers(struct ath5k_softc *sc, u64 bc_tsf);
-int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-void ath5k_beacon_config(struct ath5k_softc *sc);
-void ath5k_txbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-void ath5k_rxbuf_free_skb(struct ath5k_softc *sc, struct ath5k_buf *bf);
-
 /********************\
 * Mac80211 functions *
 \********************/
 
-static int
+static void
 ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ath5k_softc *sc = hw->priv;
@@ -77,10 +60,10 @@
 
 	if (WARN_ON(qnum >= sc->ah->ah_capabilities.cap_queues.q_tx_num)) {
 		dev_kfree_skb_any(skb);
-		return 0;
+		return;
 	}
 
-	return ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
+	ath5k_tx_queue(hw, skb, &sc->txqs[qnum]);
 }
 
 
@@ -175,8 +158,7 @@
 
 	memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
 
-	ath5k_mode_setup(sc, vif);
-
+	ath5k_update_bssid_mask_and_opmode(sc, vif);
 	ret = 0;
 end:
 	mutex_unlock(&sc->lock);
@@ -226,6 +208,7 @@
 	struct ath5k_hw *ah = sc->ah;
 	struct ieee80211_conf *conf = &hw->conf;
 	int ret = 0;
+	int i;
 
 	mutex_lock(&sc->lock);
 
@@ -243,6 +226,14 @@
 		ath5k_hw_set_txpower_limit(ah, (conf->power_level * 2));
 	}
 
+	if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
+		ah->ah_retry_long = conf->long_frame_max_tx_count;
+		ah->ah_retry_short = conf->short_frame_max_tx_count;
+
+		for (i = 0; i < ah->ah_capabilities.cap_queues.q_tx_num; i++)
+			ath5k_hw_set_tx_retry_limits(ah, i);
+	}
+
 	/* TODO:
 	 * 1) Move this on config_interface and handle each case
 	 * separately eg. when we have only one STA vif, use
@@ -389,6 +380,7 @@
 	struct ath5k_softc *sc = hw->priv;
 	struct ath5k_hw *ah = sc->ah;
 	u32 mfilt[2], rfilt;
+	struct ath5k_vif_iter_data iter_data; /* to count STA interfaces */
 
 	mutex_lock(&sc->lock);
 
@@ -462,6 +454,21 @@
 		break;
 	}
 
+	iter_data.hw_macaddr = NULL;
+	iter_data.n_stas = 0;
+	iter_data.need_set_hw_addr = false;
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath5k_vif_iter,
+						   &iter_data);
+
+	/* Set up RX Filter */
+	if (iter_data.n_stas > 1) {
+		/* If you have multiple STA interfaces connected to
+		 * different APs, ARPs are not received (most of the time?)
+		 * Enabling PROMISC appears to fix that probem.
+		 */
+		rfilt |= AR5K_RX_FILTER_PROM;
+	}
+
 	/* Set filters */
 	ath5k_hw_set_rx_filter(ah, rfilt);
 
@@ -733,6 +740,47 @@
 }
 
 
+static void ath5k_get_ringparam(struct ieee80211_hw *hw,
+				u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
+{
+	struct ath5k_softc *sc = hw->priv;
+
+	*tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
+
+	*tx_max = ATH5K_TXQ_LEN_MAX;
+	*rx = *rx_max = ATH_RXBUF;
+}
+
+
+static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
+{
+	struct ath5k_softc *sc = hw->priv;
+	u16 qnum;
+
+	/* only support setting tx ring size for now */
+	if (rx != ATH_RXBUF)
+		return -EINVAL;
+
+	/* restrict tx ring size min/max */
+	if (!tx || tx > ATH5K_TXQ_LEN_MAX)
+		return -EINVAL;
+
+	for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) {
+		if (!sc->txqs[qnum].setup)
+			continue;
+		if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
+		    sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
+			continue;
+
+		sc->txqs[qnum].txq_max = tx;
+		if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max)
+			ieee80211_stop_queue(hw, sc->txqs[qnum].qnum);
+	}
+
+	return 0;
+}
+
+
 const struct ieee80211_ops ath5k_hw_ops = {
 	.tx			= ath5k_tx,
 	.start			= ath5k_start,
@@ -771,4 +819,6 @@
 	/* .napi_poll		= not implemented */
 	.set_antenna		= ath5k_set_antenna,
 	.get_antenna		= ath5k_get_antenna,
+	.set_ringparam		= ath5k_set_ringparam,
+	.get_ringparam		= ath5k_get_ringparam,
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 	*csz = (int)u8tmp;
 
 	/*
-	 * This check was put in to avoid "unplesant" consequences if
+	 * This check was put in to avoid "unpleasant" consequences if
 	 * the bootrom has not fully initialized all PCI devices.
 	 * Sometimes the cache line size register is not set
 	 */
@@ -69,7 +69,8 @@
 /*
  * Read from eeprom
  */
-bool ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
+static bool
+ath5k_pci_eeprom_read(struct ath_common *common, u32 offset, u16 *data)
 {
 	struct ath5k_hw *ah = (struct ath5k_hw *) common->ah;
 	u32 status, timeout;
@@ -90,15 +91,15 @@
 		status = ath5k_hw_reg_read(ah, AR5K_EEPROM_STATUS);
 		if (status & AR5K_EEPROM_STAT_RDDONE) {
 			if (status & AR5K_EEPROM_STAT_RDERR)
-				return -EIO;
+				return false;
 			*data = (u16)(ath5k_hw_reg_read(ah, AR5K_EEPROM_DATA) &
 					0xffff);
-			return 0;
+			return true;
 		}
 		udelay(15);
 	}
 
-	return -ETIMEDOUT;
+	return false;
 }
 
 int ath5k_hw_read_srev(struct ath5k_hw *ah)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/pcu.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/pcu.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/pcu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/pcu.c	2011-05-19 00:06:34.000000000 -0400
@@ -472,7 +472,7 @@
 	}
 
 	/*
-	 * The AR5210 uses promiscous mode to detect radar activity
+	 * The AR5210 uses promiscuous mode to detect radar activity
 	 */
 	if (ah->ah_version == AR5K_AR5210 &&
 			(filter & AR5K_RX_FILTER_RADARERR)) {
@@ -706,8 +706,8 @@
  * The need for this function arises from the fact that we have 4 separate
  * HW timer registers (TIMER0 - TIMER3), which are closely related to the
  * next beacon target time (NBTT), and that the HW updates these timers
- * seperately based on the current TSF value. The hardware increments each
- * timer by the beacon interval, when the local TSF coverted to TU is equal
+ * separately based on the current TSF value. The hardware increments each
+ * timer by the beacon interval, when the local TSF converted to TU is equal
  * to the value stored in the timer.
  *
  * The reception of a beacon with the same BSSID can update the local HW TSF
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -335,11 +335,11 @@
  * http://madwifi-project.org/ticket/1659
  * with various measurements and diagrams
  *
- * TODO: Deal with power drops due to probes by setting an apropriate
+ * TODO: Deal with power drops due to probes by setting an appropriate
  * tx power on the probe packets ! Make this part of the calibration process.
  */
 
-/* Initialize ah_gain durring attach */
+/* Initialize ah_gain during attach */
 int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah)
 {
 	/* Initialize the gain optimization values */
@@ -1049,7 +1049,7 @@
 \**************************/
 
 /*
- * Convertion needed for RF5110
+ * Conversion needed for RF5110
  */
 static u32 ath5k_hw_rf5110_chan2athchan(struct ieee80211_channel *channel)
 {
@@ -1088,7 +1088,7 @@
 }
 
 /*
- * Convertion needed for 5111
+ * Conversion needed for 5111
  */
 static int ath5k_hw_rf5111_chan2athchan(unsigned int ieee,
 		struct ath5k_athchan_2ghz *athchan)
@@ -2201,7 +2201,7 @@
 /*
  * 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
+ * them and come up with an appropriate dataset for our current
  * channel.
  */
 static void
@@ -2618,7 +2618,7 @@
 /*
  * 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
+ * We can have up to 4 pd curves, we need to do a similar 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.
  */
@@ -2826,13 +2826,13 @@
 	u32 target = channel->center_freq;
 	int pdg, i;
 
-	/* Get surounding freq piers for this channel */
+	/* Get surrounding 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 */
+	 * surrounding freq piers by index */
 	for (pdg = 0; pdg < ee->ee_pd_gains[ee_mode]; pdg++) {
 
 		/* Fill curves in reverse order
@@ -2923,7 +2923,7 @@
 		}
 
 		/* Interpolate between curves
-		 * of surounding freq piers to
+		 * of surrounding freq piers to
 		 * get the final curve for this
 		 * pd gain. Re-use tmpL for interpolation
 		 * output */
@@ -2947,7 +2947,7 @@
 
 	/* Fill min and max power levels for this
 	 * channel by interpolating the values on
-	 * surounding channels to complete the dataset */
+	 * surrounding channels to complete the dataset */
 	ah->ah_txpower.txp_min_pwr = ath5k_get_interpolated_value(target,
 					(s16) pcinfo_L->freq,
 					(s16) pcinfo_R->freq,
@@ -3179,7 +3179,7 @@
 
 	/* FIXME: TPC scale reduction */
 
-	/* Get surounding channels for per-rate power table
+	/* Get surrounding channels for per-rate power table
 	 * calibration */
 	ath5k_get_rate_pcal_data(ah, channel, &rate_info);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/qcu.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/qcu.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/qcu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/qcu.c	2011-05-19 00:06:34.000000000 -0400
@@ -228,24 +228,9 @@
 /*
  * Set tx retry limits on DCU
  */
-static void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
-					unsigned int queue)
+void ath5k_hw_set_tx_retry_limits(struct ath5k_hw *ah,
+				  unsigned int queue)
 {
-	u32 retry_lg, retry_sh;
-
-	/*
-	 * 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;
-	}
-
 	/* Single data queue on AR5210 */
 	if (ah->ah_version == AR5K_AR5210) {
 		struct ath5k_txq_info *tq = &ah->ah_txq[queue];
@@ -255,25 +240,26 @@
 
 		ath5k_hw_reg_write(ah,
 			(tq->tqi_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_REG_SM(ah->ah_retry_long,
+				      AR5K_NODCU_RETRY_LMT_SLG_RETRY)
+			| AR5K_REG_SM(ah->ah_retry_short,
+				      AR5K_NODCU_RETRY_LMT_SSH_RETRY)
+			| AR5K_REG_SM(ah->ah_retry_long,
+				      AR5K_NODCU_RETRY_LMT_LG_RETRY)
+			| AR5K_REG_SM(ah->ah_retry_short,
+				      AR5K_NODCU_RETRY_LMT_SH_RETRY),
 			AR5K_NODCU_RETRY_LMT);
 	/* DCU on AR5211+ */
 	} else {
 		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_REG_SM(ah->ah_retry_long,
+				    AR5K_DCU_RETRY_LMT_RTS)
+			| AR5K_REG_SM(ah->ah_retry_long,
+				      AR5K_DCU_RETRY_LMT_STA_RTS)
+			| AR5K_REG_SM(max(ah->ah_retry_long, ah->ah_retry_short),
+				      AR5K_DCU_RETRY_LMT_STA_DATA),
 			AR5K_QUEUE_DFS_RETRY_LIMIT(queue));
 	}
-	return;
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/reg.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/reg.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -132,8 +132,8 @@
  * 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
+ * So SNAPPEDBCRVALID should also stand for "snapped BCR -values- valid", so i
+ * renamed it to SNAPSHOTSVALID to make more sense. I really have no idea what
  * else can it be. I also renamed SNPBCMD to SNPADHOC to match BCR.
  */
 #define AR5K_BSR		0x002c			/* Register Address */
@@ -283,7 +283,7 @@
  */
 #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_RXOK		0x00000001	/* Frame successfuly received */
 #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) */
@@ -372,12 +372,12 @@
 /*
  * Interrupt Mask Registers
  *
- * As whith ISRs 5210 has one IMR (AR5K_IMR) and 5211/5212 has one primary
+ * As with 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_RXOK		0x00000001	/* Frame successfuly received*/
 #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)*/
@@ -686,16 +686,15 @@
 
 /*
  * DCU retry limit registers
+ * all these fields don't allow zero values
  */
 #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_DCU_RETRY_LMT_RTS		0x0000000f	/* RTS failure limit. Transmission fails if no CTS is received for this number of times */
+#define AR5K_DCU_RETRY_LMT_RTS_S	0
+#define AR5K_DCU_RETRY_LMT_STA_RTS	0x00003f00	/* STA RTS failure limit. If exceeded CW reset */
+#define AR5K_DCU_RETRY_LMT_STA_RTS_S	8
+#define AR5K_DCU_RETRY_LMT_STA_DATA	0x000fc000	/* STA data failure limit. If exceeded CW reset. */
+#define AR5K_DCU_RETRY_LMT_STA_DATA_S	14
 #define	AR5K_QUEUE_DFS_RETRY_LIMIT(_q)	AR5K_QUEUE_REG(AR5K_DCU_RETRY_LMT_BASE, _q)
 
 /*
@@ -896,7 +895,7 @@
 #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_SL_INPEN		0x00002000	/* Sleep even with 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+] */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/trace.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/trace.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath5k/trace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath5k/trace.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,107 @@
+#if !defined(__TRACE_ATH5K_H) || defined(TRACE_HEADER_MULTI_READ)
+#define __TRACE_ATH5K_H
+
+#include <linux/tracepoint.h>
+#include "base.h"
+
+#ifndef CONFIG_ATH5K_TRACER
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+struct sk_buff;
+
+#define PRIV_ENTRY  __field(struct ath5k_softc *, priv)
+#define PRIV_ASSIGN __entry->priv = priv
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM ath5k
+
+TRACE_EVENT(ath5k_rx,
+	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb),
+	TP_ARGS(priv, skb),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(unsigned long, skbaddr)
+		__dynamic_array(u8, frame, skb->len)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->skbaddr = (unsigned long) skb;
+		memcpy(__get_dynamic_array(frame), skb->data, skb->len);
+	),
+	TP_printk(
+		"[%p] RX skb=%lx", __entry->priv, __entry->skbaddr
+	)
+);
+
+TRACE_EVENT(ath5k_tx,
+	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+		 struct ath5k_txq *q),
+
+	TP_ARGS(priv, skb, q),
+
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(unsigned long, skbaddr)
+		__field(u8, qnum)
+		__dynamic_array(u8, frame, skb->len)
+	),
+
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->skbaddr = (unsigned long) skb;
+		__entry->qnum = (u8) q->qnum;
+		memcpy(__get_dynamic_array(frame), skb->data, skb->len);
+	),
+
+	TP_printk(
+		"[%p] TX skb=%lx q=%d", __entry->priv, __entry->skbaddr,
+		__entry->qnum
+	)
+);
+
+TRACE_EVENT(ath5k_tx_complete,
+	TP_PROTO(struct ath5k_softc *priv, struct sk_buff *skb,
+		 struct ath5k_txq *q, struct ath5k_tx_status *ts),
+
+	TP_ARGS(priv, skb, q, ts),
+
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(unsigned long, skbaddr)
+		__field(u8, qnum)
+		__field(u8, ts_status)
+		__field(s8, ts_rssi)
+		__field(u8, ts_antenna)
+	),
+
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->skbaddr = (unsigned long) skb;
+		__entry->qnum = (u8) q->qnum;
+		__entry->ts_status = ts->ts_status;
+		__entry->ts_rssi =  ts->ts_rssi;
+		__entry->ts_antenna = ts->ts_antenna;
+	),
+
+	TP_printk(
+		"[%p] TX end skb=%lx q=%d stat=%x rssi=%d ant=%x",
+		__entry->priv, __entry->skbaddr, __entry->qnum,
+		__entry->ts_status, __entry->ts_rssi, __entry->ts_antenna
+	)
+);
+
+#endif /* __TRACE_ATH5K_H */
+
+#ifdef CONFIG_ATH5K_TRACER
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH ../../drivers/net/wireless/ath/ath5k
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE trace
+
+#include <trace/define_trace.h>
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ahb.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ahb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ahb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ahb.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,6 @@
 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;
@@ -76,7 +75,7 @@
 		goto err_out;
 	}
 
-	mem = ioremap_nocache(res->start, res->end - res->start + 1);
+	mem = ioremap_nocache(res->start, resource_size(res));
 	if (mem == NULL) {
 		dev_err(&pdev->dev, "ioremap failed\n");
 		ret = -ENOMEM;
@@ -92,8 +91,7 @@
 
 	irq = res->start;
 
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
-				sizeof(struct ath_softc), &ath9k_ops);
+	hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
 	if (hw == NULL) {
 		dev_err(&pdev->dev, "no memory for ieee80211_hw\n");
 		ret = -ENOMEM;
@@ -103,11 +101,7 @@
 	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->priv;
 	sc->hw = hw;
 	sc->dev = &pdev->dev;
 	sc->mem = mem;
@@ -151,8 +145,7 @@
 	struct ieee80211_hw *hw = platform_get_drvdata(pdev);
 
 	if (hw) {
-		struct ath_wiphy *aphy = hw->priv;
-		struct ath_softc *sc = aphy->sc;
+		struct ath_softc *sc = hw->priv;
 		void __iomem *mem = sc->mem;
 
 		ath9k_deinit_device(sc);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar5008_phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar5008_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar5008_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar5008_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -142,7 +142,7 @@
 
 /**
  * ar5008_hw_set_channel - tune to a channel on the external AR2133/AR5133 radios
- * @ah: atheros hardware stucture
+ * @ah: atheros hardware structure
  * @chan:
  *
  * For the external AR2133/AR5133 radios, takes the MHz channel value and set
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9002_calib.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9002_calib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9002_calib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9002_calib.c	2011-05-19 00:06:34.000000000 -0400
@@ -805,7 +805,10 @@
 {
 	struct ath_common *common = ath9k_hw_common(ah);
 
-	if (AR_SREV_9271(ah) || AR_SREV_9285_12_OR_LATER(ah)) {
+	if (AR_SREV_9271(ah)) {
+		if (!ar9285_hw_cl_cal(ah, chan))
+			return false;
+	} else if (AR_SREV_9285_12_OR_LATER(ah)) {
 		if (!ar9285_hw_clc(ah, chan))
 			return false;
 	} else {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -3240,7 +3240,7 @@
 			eep = ar9003_eeprom_struct_find_by_id(reference);
 			if (eep == NULL) {
 				ath_dbg(common, ATH_DBG_EEPROM,
-					"cant find reference eeprom struct %d\n",
+					"can't find reference eeprom struct %d\n",
 					reference);
 				return -1;
 			}
@@ -3673,7 +3673,7 @@
 				return;
 
 			reg_pmu_set = (5 << 1) | (7 << 4) | (1 << 8) |
-				      (7 << 14) | (6 << 17) | (1 << 20) |
+				      (2 << 14) | (6 << 17) | (1 << 20) |
 				      (3 << 24) | (1 << 28);
 
 			REG_WRITE(ah, AR_PHY_PMU1, reg_pmu_set);
@@ -3959,19 +3959,19 @@
 {
 #define POW_SM(_r, _s)     (((_r) & 0x3f) << (_s))
 	/* make sure forced gain is not set */
-	REG_WRITE(ah, 0xa458, 0);
+	REG_WRITE(ah, AR_PHY_TX_FORCED_GAIN, 0);
 
 	/* Write the OFDM power per rate set */
 
 	/* 6 (LSB), 9, 12, 18 (MSB) */
-	REG_WRITE(ah, 0xa3c0,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(0),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 0));
 
 	/* 24 (LSB), 36, 48, 54 (MSB) */
-	REG_WRITE(ah, 0xa3c4,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(1),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_54], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_48], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_36], 8) |
@@ -3980,14 +3980,14 @@
 	/* Write the CCK power per rate set */
 
 	/* 1L (LSB), reserved, 2L, 2S (MSB) */
-	REG_WRITE(ah, 0xa3c8,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(2),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
 		  /* POW_SM(txPowerTimes2,  8) | this is reserved for AR9003 */
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 0));
 
 	/* 5.5L (LSB), 5.5S, 11L, 11S (MSB) */
-	REG_WRITE(ah, 0xa3cc,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(3),
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_11S], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_11L], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_LEGACY_5S], 8) |
@@ -3997,7 +3997,7 @@
 	/* Write the HT20 power per rate set */
 
 	/* 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB) */
-	REG_WRITE(ah, 0xa3d0,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(4),
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_5], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_4], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_1_3_9_11_17_19], 8) |
@@ -4005,7 +4005,7 @@
 	    );
 
 	/* 6 (LSB), 7, 12, 13 (MSB) */
-	REG_WRITE(ah, 0xa3d4,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(5),
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_13], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_12], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_7], 8) |
@@ -4013,7 +4013,7 @@
 	    );
 
 	/* 14 (LSB), 15, 20, 21 */
-	REG_WRITE(ah, 0xa3e4,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(9),
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_21], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_20], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_15], 8) |
@@ -4023,7 +4023,7 @@
 	/* Mixed HT20 and HT40 rates */
 
 	/* HT20 22 (LSB), HT20 23, HT40 22, HT40 23 (MSB) */
-	REG_WRITE(ah, 0xa3e8,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(10),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_23], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_22], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT20_23], 8) |
@@ -4035,7 +4035,7 @@
 	 * correct PAR difference between HT40 and HT20/LEGACY
 	 * 0/8/16 (LSB), 1-3/9-11/17-19, 4, 5 (MSB)
 	 */
-	REG_WRITE(ah, 0xa3d8,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(6),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_5], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_4], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_1_3_9_11_17_19], 8) |
@@ -4043,7 +4043,7 @@
 	    );
 
 	/* 6 (LSB), 7, 12, 13 (MSB) */
-	REG_WRITE(ah, 0xa3dc,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(7),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_13], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_12], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_7], 8) |
@@ -4051,7 +4051,7 @@
 	    );
 
 	/* 14 (LSB), 15, 20, 21 */
-	REG_WRITE(ah, 0xa3ec,
+	REG_WRITE(ah, AR_PHY_POWER_TX_RATE(11),
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_21], 24) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_20], 16) |
 		  POW_SM(pPwrArray[ALL_TARGET_HT40_15], 8) |
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,67 @@
  */
 static void ar9003_hw_init_mode_regs(struct ath_hw *ah)
 {
-	if (AR_SREV_9485(ah)) {
+	if (AR_SREV_9485_11(ah)) {
+		/* mac */
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
+				ar9485_1_1_mac_core,
+				ARRAY_SIZE(ar9485_1_1_mac_core), 2);
+		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_POST],
+				ar9485_1_1_mac_postamble,
+				ARRAY_SIZE(ar9485_1_1_mac_postamble), 5);
+
+		/* bb */
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_PRE], ar9485_1_1,
+				ARRAY_SIZE(ar9485_1_1), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_CORE],
+				ar9485_1_1_baseband_core,
+				ARRAY_SIZE(ar9485_1_1_baseband_core), 2);
+		INIT_INI_ARRAY(&ah->iniBB[ATH_INI_POST],
+				ar9485_1_1_baseband_postamble,
+				ARRAY_SIZE(ar9485_1_1_baseband_postamble), 5);
+
+		/* radio */
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_PRE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_CORE],
+				ar9485_1_1_radio_core,
+				ARRAY_SIZE(ar9485_1_1_radio_core), 2);
+		INIT_INI_ARRAY(&ah->iniRadio[ATH_INI_POST],
+				ar9485_1_1_radio_postamble,
+				ARRAY_SIZE(ar9485_1_1_radio_postamble), 2);
+
+		/* soc */
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_PRE],
+				ar9485_1_1_soc_preamble,
+				ARRAY_SIZE(ar9485_1_1_soc_preamble), 2);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_CORE], NULL, 0, 0);
+		INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], NULL, 0, 0);
+
+		/* rx/tx gain */
+		INIT_INI_ARRAY(&ah->iniModesRxGain,
+				ar9485_common_rx_gain_1_1,
+				ARRAY_SIZE(ar9485_common_rx_gain_1_1), 2);
+		INIT_INI_ARRAY(&ah->iniModesTxGain,
+				ar9485_modes_lowest_ob_db_tx_gain_1_1,
+				ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+				5);
+
+		/* Load PCIE SERDES settings from INI */
+
+		/* Awake Setting */
+
+		INIT_INI_ARRAY(&ah->iniPcieSerdes,
+				ar9485_1_1_pcie_phy_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+				2);
+
+		/* Sleep Setting */
+
+		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
+				ar9485_1_1_pcie_phy_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_1_pcie_phy_clkreq_disable_L1),
+				2);
+	} else if (AR_SREV_9485(ah)) {
 		/* mac */
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_PRE], NULL, 0, 0);
 		INIT_INI_ARRAY(&ah->iniMac[ATH_INI_CORE],
@@ -85,8 +145,8 @@
 		/* Sleep Setting */
 
 		INIT_INI_ARRAY(&ah->iniPcieSerdesLowPower,
-				ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1,
-				ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_enable_L1),
+				ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1,
+				ARRAY_SIZE(ar9485_1_0_pcie_phy_pll_on_clkreq_disable_L1),
 				2);
 	} else {
 		/* mac */
@@ -163,7 +223,12 @@
 	switch (ar9003_hw_get_tx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485_modes_lowest_ob_db_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485_modes_lowest_ob_db_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_lowest_ob_db_tx_gain_1_0,
 				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
@@ -175,10 +240,15 @@
 				       5);
 		break;
 	case 1:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_high_ob_db_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_high_ob_db_tx_gain_1_0,
-				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       ARRAY_SIZE(ar9485Modes_high_ob_db_tx_gain_1_0),
 				       5);
 		else
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
@@ -187,10 +257,15 @@
 				       5);
 		break;
 	case 2:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_low_ob_db_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_low_ob_db_tx_gain_1_0,
-				       ARRAY_SIZE(ar9485Modes_lowest_ob_db_tx_gain_1_0),
+				       ARRAY_SIZE(ar9485Modes_low_ob_db_tx_gain_1_0),
 				       5);
 		else
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
@@ -199,7 +274,12 @@
 				       5);
 		break;
 	case 3:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesTxGain,
+				       ar9485Modes_high_power_tx_gain_1_1,
+				       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_1),
+				       5);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesTxGain,
 				       ar9485Modes_high_power_tx_gain_1_0,
 				       ARRAY_SIZE(ar9485Modes_high_power_tx_gain_1_0),
@@ -218,7 +298,12 @@
 	switch (ar9003_hw_get_rx_gain_idx(ah)) {
 	case 0:
 	default:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9485_common_rx_gain_1_1,
+				       ARRAY_SIZE(ar9485_common_rx_gain_1_1),
+				       2);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesRxGain,
 				       ar9485Common_rx_gain_1_0,
 				       ARRAY_SIZE(ar9485Common_rx_gain_1_0),
@@ -230,7 +315,12 @@
 				       2);
 		break;
 	case 1:
-		if (AR_SREV_9485(ah))
+		if (AR_SREV_9485_11(ah))
+			INIT_INI_ARRAY(&ah->iniModesRxGain,
+				       ar9485Common_wo_xlna_rx_gain_1_1,
+				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_1),
+				       2);
+		else if (AR_SREV_9485(ah))
 			INIT_INI_ARRAY(&ah->iniModesRxGain,
 				       ar9485Common_wo_xlna_rx_gain_1_0,
 				       ARRAY_SIZE(ar9485Common_wo_xlna_rx_gain_1_0),
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -615,7 +615,7 @@
 		 */
 		if (rxsp->status11 & AR_CRCErr)
 			rxs->rs_status |= ATH9K_RXERR_CRC;
-		if (rxsp->status11 & AR_PHYErr) {
+		else if (rxsp->status11 & AR_PHYErr) {
 			phyerr = MS(rxsp->status11, AR_PHYErrCode);
 			/*
 			 * If we reach a point here where AR_PostDelimCRCErr is
@@ -638,11 +638,11 @@
 				rxs->rs_phyerr = phyerr;
 			}
 
-		}
-		if (rxsp->status11 & AR_DecryptCRCErr)
+		} else if (rxsp->status11 & AR_DecryptCRCErr)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
-		if (rxsp->status11 & AR_MichaelErr)
+		else if (rxsp->status11 & AR_MichaelErr)
 			rxs->rs_status |= ATH9K_RXERR_MIC;
+
 		if (rxsp->status11 & AR_KeyMiss)
 			rxs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1020,28 +1020,29 @@
 static void ar9003_hw_do_getnf(struct ath_hw *ah,
 			      int16_t nfarray[NUM_NF_READINGS])
 {
-	int16_t nf;
-
-	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
-	nfarray[0] = sign_extend32(nf, 8);
-
-	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
-	nfarray[1] = sign_extend32(nf, 8);
-
-	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
-	nfarray[2] = sign_extend32(nf, 8);
+#define AR_PHY_CH_MINCCA_PWR	0x1FF00000
+#define AR_PHY_CH_MINCCA_PWR_S	20
+#define AR_PHY_CH_EXT_MINCCA_PWR 0x01FF0000
+#define AR_PHY_CH_EXT_MINCCA_PWR_S 16
 
-	if (!IS_CHAN_HT40(ah->curchan))
-		return;
+	int16_t nf;
+	int i;
 
-	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
-	nfarray[3] = sign_extend32(nf, 8);
+	for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+		if (ah->rxchainmask & BIT(i)) {
+			nf = MS(REG_READ(ah, ah->nf_regs[i]),
+					 AR_PHY_CH_MINCCA_PWR);
+			nfarray[i] = sign_extend32(nf, 8);
 
-	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
-	nfarray[4] = sign_extend32(nf, 8);
+			if (IS_CHAN_HT40(ah->curchan)) {
+				u8 ext_idx = AR9300_MAX_CHAINS + i;
 
-	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
-	nfarray[5] = sign_extend32(nf, 8);
+				nf = MS(REG_READ(ah, ah->nf_regs[ext_idx]),
+						 AR_PHY_CH_EXT_MINCCA_PWR);
+				nfarray[ext_idx] = sign_extend32(nf, 8);
+			}
+		}
+	}
 }
 
 static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9003_phy.h	2011-05-19 00:06:34.000000000 -0400
@@ -486,6 +486,8 @@
 #define AR_PHY_HEAVYCLIP_40      (AR_SM_BASE + 0x1ac)
 #define AR_PHY_ILLEGAL_TXRATE    (AR_SM_BASE + 0x1b0)
 
+#define AR_PHY_POWER_TX_RATE(_d) (AR_SM_BASE + 0x1c0 + ((_d) << 2))
+
 #define AR_PHY_PWRTX_MAX         (AR_SM_BASE + 0x1f0)
 #define AR_PHY_POWER_TX_SUB      (AR_SM_BASE + 0x1f4)
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9485_initvals.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ar9485_initvals.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ar9485_initvals.h	2011-05-19 00:06:34.000000000 -0400
@@ -667,6 +667,7 @@
 
 static const u32 ar9485_1_0_soc_preamble[][2] = {
 	/*   Addr     allmodes */
+	{0x00004090, 0x00aa10aa},
 	{0x000040a4, 0x00a0c9c9},
 	{0x00007048, 0x00000004},
 };
@@ -940,4 +941,1146 @@
 	{0x000083cc, 0x00000200},
 	{0x000083d0, 0x000301ff},
 };
+
+static const u32 ar9485_1_1_mac_core[][2] = {
+	/*  Addr       allmodes */
+	{0x00000008, 0x00000000},
+	{0x00000030, 0x00020085},
+	{0x00000034, 0x00000005},
+	{0x00000040, 0x00000000},
+	{0x00000044, 0x00000000},
+	{0x00000048, 0x00000008},
+	{0x0000004c, 0x00000010},
+	{0x00000050, 0x00000000},
+	{0x00001040, 0x002ffc0f},
+	{0x00001044, 0x002ffc0f},
+	{0x00001048, 0x002ffc0f},
+	{0x0000104c, 0x002ffc0f},
+	{0x00001050, 0x002ffc0f},
+	{0x00001054, 0x002ffc0f},
+	{0x00001058, 0x002ffc0f},
+	{0x0000105c, 0x002ffc0f},
+	{0x00001060, 0x002ffc0f},
+	{0x00001064, 0x002ffc0f},
+	{0x000010f0, 0x00000100},
+	{0x00001270, 0x00000000},
+	{0x000012b0, 0x00000000},
+	{0x000012f0, 0x00000000},
+	{0x0000143c, 0x00000000},
+	{0x0000147c, 0x00000000},
+	{0x00008000, 0x00000000},
+	{0x00008004, 0x00000000},
+	{0x00008008, 0x00000000},
+	{0x0000800c, 0x00000000},
+	{0x00008018, 0x00000000},
+	{0x00008020, 0x00000000},
+	{0x00008038, 0x00000000},
+	{0x0000803c, 0x00000000},
+	{0x00008040, 0x00000000},
+	{0x00008044, 0x00000000},
+	{0x00008048, 0x00000000},
+	{0x0000804c, 0xffffffff},
+	{0x00008054, 0x00000000},
+	{0x00008058, 0x00000000},
+	{0x0000805c, 0x000fc78f},
+	{0x00008060, 0x0000000f},
+	{0x00008064, 0x00000000},
+	{0x00008070, 0x00000310},
+	{0x00008074, 0x00000020},
+	{0x00008078, 0x00000000},
+	{0x0000809c, 0x0000000f},
+	{0x000080a0, 0x00000000},
+	{0x000080a4, 0x02ff0000},
+	{0x000080a8, 0x0e070605},
+	{0x000080ac, 0x0000000d},
+	{0x000080b0, 0x00000000},
+	{0x000080b4, 0x00000000},
+	{0x000080b8, 0x00000000},
+	{0x000080bc, 0x00000000},
+	{0x000080c0, 0x2a800000},
+	{0x000080c4, 0x06900168},
+	{0x000080c8, 0x13881c22},
+	{0x000080cc, 0x01f40000},
+	{0x000080d0, 0x00252500},
+	{0x000080d4, 0x00a00000},
+	{0x000080d8, 0x00400000},
+	{0x000080dc, 0x00000000},
+	{0x000080e0, 0xffffffff},
+	{0x000080e4, 0x0000ffff},
+	{0x000080e8, 0x3f3f3f3f},
+	{0x000080ec, 0x00000000},
+	{0x000080f0, 0x00000000},
+	{0x000080f4, 0x00000000},
+	{0x000080fc, 0x00020000},
+	{0x00008100, 0x00000000},
+	{0x00008108, 0x00000052},
+	{0x0000810c, 0x00000000},
+	{0x00008110, 0x00000000},
+	{0x00008114, 0x000007ff},
+	{0x00008118, 0x000000aa},
+	{0x0000811c, 0x00003210},
+	{0x00008124, 0x00000000},
+	{0x00008128, 0x00000000},
+	{0x0000812c, 0x00000000},
+	{0x00008130, 0x00000000},
+	{0x00008134, 0x00000000},
+	{0x00008138, 0x00000000},
+	{0x0000813c, 0x0000ffff},
+	{0x00008144, 0xffffffff},
+	{0x00008168, 0x00000000},
+	{0x0000816c, 0x00000000},
+	{0x00008170, 0x18486200},
+	{0x00008174, 0x33332210},
+	{0x00008178, 0x00000000},
+	{0x0000817c, 0x00020000},
+	{0x000081c0, 0x00000000},
+	{0x000081c4, 0x33332210},
+	{0x000081d4, 0x00000000},
+	{0x000081ec, 0x00000000},
+	{0x000081f0, 0x00000000},
+	{0x000081f4, 0x00000000},
+	{0x000081f8, 0x00000000},
+	{0x000081fc, 0x00000000},
+	{0x00008240, 0x00100000},
+	{0x00008244, 0x0010f400},
+	{0x00008248, 0x00000800},
+	{0x0000824c, 0x0001e800},
+	{0x00008250, 0x00000000},
+	{0x00008254, 0x00000000},
+	{0x00008258, 0x00000000},
+	{0x0000825c, 0x40000000},
+	{0x00008260, 0x00080922},
+	{0x00008264, 0x9ca00010},
+	{0x00008268, 0xffffffff},
+	{0x0000826c, 0x0000ffff},
+	{0x00008270, 0x00000000},
+	{0x00008274, 0x40000000},
+	{0x00008278, 0x003e4180},
+	{0x0000827c, 0x00000004},
+	{0x00008284, 0x0000002c},
+	{0x00008288, 0x0000002c},
+	{0x0000828c, 0x000000ff},
+	{0x00008294, 0x00000000},
+	{0x00008298, 0x00000000},
+	{0x0000829c, 0x00000000},
+	{0x00008300, 0x00000140},
+	{0x00008314, 0x00000000},
+	{0x0000831c, 0x0000010d},
+	{0x00008328, 0x00000000},
+	{0x0000832c, 0x00000007},
+	{0x00008330, 0x00000302},
+	{0x00008334, 0x00000700},
+	{0x00008338, 0x00ff0000},
+	{0x0000833c, 0x02400000},
+	{0x00008340, 0x000107ff},
+	{0x00008344, 0xa248105b},
+	{0x00008348, 0x008f0000},
+	{0x0000835c, 0x00000000},
+	{0x00008360, 0xffffffff},
+	{0x00008364, 0xffffffff},
+	{0x00008368, 0x00000000},
+	{0x00008370, 0x00000000},
+	{0x00008374, 0x000000ff},
+	{0x00008378, 0x00000000},
+	{0x0000837c, 0x00000000},
+	{0x00008380, 0xffffffff},
+	{0x00008384, 0xffffffff},
+	{0x00008390, 0xffffffff},
+	{0x00008394, 0xffffffff},
+	{0x00008398, 0x00000000},
+	{0x0000839c, 0x00000000},
+	{0x000083a0, 0x00000000},
+	{0x000083a4, 0x0000fa14},
+	{0x000083a8, 0x000f0c00},
+	{0x000083ac, 0x33332210},
+	{0x000083b0, 0x33332210},
+	{0x000083b4, 0x33332210},
+	{0x000083b8, 0x33332210},
+	{0x000083bc, 0x00000000},
+	{0x000083c0, 0x00000000},
+	{0x000083c4, 0x00000000},
+	{0x000083c8, 0x00000000},
+	{0x000083cc, 0x00000200},
+	{0x000083d0, 0x000301ff},
+};
+
+static const u32 ar9485_1_1_baseband_core[][2] = {
+	/* Addr       allmodes */
+	{0x00009800, 0xafe68e30},
+	{0x00009804, 0xfd14e000},
+	{0x00009808, 0x9c0a8f6b},
+	{0x0000980c, 0x04800000},
+	{0x00009814, 0x9280c00a},
+	{0x00009818, 0x00000000},
+	{0x0000981c, 0x00020028},
+	{0x00009834, 0x5f3ca3de},
+	{0x00009838, 0x0108ecff},
+	{0x0000983c, 0x14750600},
+	{0x00009880, 0x201fff00},
+	{0x00009884, 0x00001042},
+	{0x000098a4, 0x00200400},
+	{0x000098b0, 0x52440bbe},
+	{0x000098d0, 0x004b6a8e},
+	{0x000098d4, 0x00000820},
+	{0x000098dc, 0x00000000},
+	{0x000098f0, 0x00000000},
+	{0x000098f4, 0x00000000},
+	{0x00009c04, 0x00000000},
+	{0x00009c08, 0x03200000},
+	{0x00009c0c, 0x00000000},
+	{0x00009c10, 0x00000000},
+	{0x00009c14, 0x00046384},
+	{0x00009c18, 0x05b6b440},
+	{0x00009c1c, 0x00b6b440},
+	{0x00009d00, 0xc080a333},
+	{0x00009d04, 0x40206c10},
+	{0x00009d08, 0x009c4060},
+	{0x00009d0c, 0x1883800a},
+	{0x00009d10, 0x01834061},
+	{0x00009d14, 0x00c00400},
+	{0x00009d18, 0x00000000},
+	{0x00009d1c, 0x00000000},
+	{0x00009e08, 0x0038233c},
+	{0x00009e24, 0x9927b515},
+	{0x00009e28, 0x12ef0200},
+	{0x00009e30, 0x06336f77},
+	{0x00009e34, 0x6af6532f},
+	{0x00009e38, 0x0cc80c00},
+	{0x00009e40, 0x0d261820},
+	{0x00009e4c, 0x00001004},
+	{0x00009e50, 0x00ff03f1},
+	{0x00009fc0, 0x80be4788},
+	{0x00009fc4, 0x0001efb5},
+	{0x00009fcc, 0x40000014},
+	{0x0000a20c, 0x00000000},
+	{0x0000a210, 0x00000000},
+	{0x0000a220, 0x00000000},
+	{0x0000a224, 0x00000000},
+	{0x0000a228, 0x10002310},
+	{0x0000a23c, 0x00000000},
+	{0x0000a244, 0x0c000000},
+	{0x0000a2a0, 0x00000001},
+	{0x0000a2c0, 0x00000001},
+	{0x0000a2c8, 0x00000000},
+	{0x0000a2cc, 0x18c43433},
+	{0x0000a2d4, 0x00000000},
+	{0x0000a2dc, 0x00000000},
+	{0x0000a2e0, 0x00000000},
+	{0x0000a2e4, 0x00000000},
+	{0x0000a2e8, 0x00000000},
+	{0x0000a2ec, 0x00000000},
+	{0x0000a2f0, 0x00000000},
+	{0x0000a2f4, 0x00000000},
+	{0x0000a2f8, 0x00000000},
+	{0x0000a344, 0x00000000},
+	{0x0000a34c, 0x00000000},
+	{0x0000a350, 0x0000a000},
+	{0x0000a364, 0x00000000},
+	{0x0000a370, 0x00000000},
+	{0x0000a390, 0x00000001},
+	{0x0000a394, 0x00000444},
+	{0x0000a398, 0x001f0e0f},
+	{0x0000a39c, 0x0075393f},
+	{0x0000a3a0, 0xb79f6427},
+	{0x0000a3a4, 0x000000ff},
+	{0x0000a3a8, 0x3b3b3b3b},
+	{0x0000a3ac, 0x2f2f2f2f},
+	{0x0000a3c0, 0x20202020},
+	{0x0000a3c4, 0x22222220},
+	{0x0000a3c8, 0x20200020},
+	{0x0000a3cc, 0x20202020},
+	{0x0000a3d0, 0x20202020},
+	{0x0000a3d4, 0x20202020},
+	{0x0000a3d8, 0x20202020},
+	{0x0000a3dc, 0x20202020},
+	{0x0000a3e0, 0x20202020},
+	{0x0000a3e4, 0x20202020},
+	{0x0000a3e8, 0x20202020},
+	{0x0000a3ec, 0x20202020},
+	{0x0000a3f0, 0x00000000},
+	{0x0000a3f4, 0x00000006},
+	{0x0000a3f8, 0x0cdbd380},
+	{0x0000a3fc, 0x000f0f01},
+	{0x0000a400, 0x8fa91f01},
+	{0x0000a404, 0x00000000},
+	{0x0000a408, 0x0e79e5c6},
+	{0x0000a40c, 0x00820820},
+	{0x0000a414, 0x1ce739cf},
+	{0x0000a418, 0x2d0019ce},
+	{0x0000a41c, 0x1ce739ce},
+	{0x0000a420, 0x000001ce},
+	{0x0000a424, 0x1ce739ce},
+	{0x0000a428, 0x000001ce},
+	{0x0000a42c, 0x1ce739ce},
+	{0x0000a430, 0x1ce739ce},
+	{0x0000a434, 0x00000000},
+	{0x0000a438, 0x00001801},
+	{0x0000a43c, 0x00000000},
+	{0x0000a440, 0x00000000},
+	{0x0000a444, 0x00000000},
+	{0x0000a448, 0x04000000},
+	{0x0000a44c, 0x00000001},
+	{0x0000a450, 0x00010000},
+	{0x0000a5c4, 0xbfad9d74},
+	{0x0000a5c8, 0x0048060a},
+	{0x0000a5cc, 0x00000637},
+	{0x0000a760, 0x03020100},
+	{0x0000a764, 0x09080504},
+	{0x0000a768, 0x0d0c0b0a},
+	{0x0000a76c, 0x13121110},
+	{0x0000a770, 0x31301514},
+	{0x0000a774, 0x35343332},
+	{0x0000a778, 0x00000036},
+	{0x0000a780, 0x00000838},
+	{0x0000a7c0, 0x00000000},
+	{0x0000a7c4, 0xfffffffc},
+	{0x0000a7c8, 0x00000000},
+	{0x0000a7cc, 0x00000000},
+	{0x0000a7d0, 0x00000000},
+	{0x0000a7d4, 0x00000004},
+	{0x0000a7dc, 0x00000000},
+};
+
+static const u32 ar9485Common_1_1[][2] = {
+	/*  Addr      allmodes */
+	{0x00007010, 0x00000022},
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000004c2},
+};
+
+static const u32 ar9485_1_1_baseband_postamble[][5] = {
+	/* Addr       5G_HT20        5G_HT40       2G_HT40       2G_HT20 */
+	{0x00009810, 0xd00a8005, 0xd00a8005, 0xd00a8005, 0xd00a8005},
+	{0x00009820, 0x206a002e, 0x206a002e, 0x206a002e, 0x206a002e},
+	{0x00009824, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0, 0x5ac640d0},
+	{0x00009828, 0x06903081, 0x06903081, 0x06903881, 0x06903881},
+	{0x0000982c, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4, 0x05eea6d4},
+	{0x00009830, 0x0000059c, 0x0000059c, 0x0000059c, 0x0000059c},
+	{0x00009c00, 0x00000044, 0x00000044, 0x00000044, 0x00000044},
+	{0x00009e00, 0x0372161e, 0x0372161e, 0x037216a0, 0x037216a0},
+	{0x00009e04, 0x00182020, 0x00182020, 0x00182020, 0x00182020},
+	{0x00009e0c, 0x6c4000e2, 0x6d4000e2, 0x6d4000e2, 0x6c4000e2},
+	{0x00009e10, 0x7ec88d2e, 0x7ec88d2e, 0x7ec80d2e, 0x7ec80d2e},
+	{0x00009e14, 0x31395d5e, 0x3139605e, 0x3139605e, 0x31395d5e},
+	{0x00009e18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00009e1c, 0x0001cf9c, 0x0001cf9c, 0x00021f9c, 0x00021f9c},
+	{0x00009e20, 0x000003b5, 0x000003b5, 0x000003ce, 0x000003ce},
+	{0x00009e2c, 0x0000001c, 0x0000001c, 0x00000021, 0x00000021},
+	{0x00009e3c, 0xcf946220, 0xcf946220, 0xcf946222, 0xcf946222},
+	{0x00009e44, 0x02321e27, 0x02321e27, 0x02282324, 0x02282324},
+	{0x00009e48, 0x5030201a, 0x5030201a, 0x50302010, 0x50302010},
+	{0x00009fc8, 0x0003f000, 0x0003f000, 0x0001a000, 0x0001a000},
+	{0x0000a204, 0x01303fc0, 0x01303fc4, 0x01303fc4, 0x01303fc0},
+	{0x0000a208, 0x00000104, 0x00000104, 0x00000004, 0x00000004},
+	{0x0000a230, 0x0000400a, 0x00004014, 0x00004016, 0x0000400b},
+	{0x0000a234, 0x10000fff, 0x10000fff, 0x10000fff, 0x10000fff},
+	{0x0000a238, 0xffb81018, 0xffb81018, 0xffb81018, 0xffb81018},
+	{0x0000a250, 0x00000000, 0x00000000, 0x00000210, 0x00000108},
+	{0x0000a254, 0x000007d0, 0x00000fa0, 0x00001130, 0x00000898},
+	{0x0000a258, 0x02020002, 0x02020002, 0x02020002, 0x02020002},
+	{0x0000a25c, 0x01000e0e, 0x01000e0e, 0x01000e0e, 0x01000e0e},
+	{0x0000a260, 0x3a021501, 0x3a021501, 0x3a021501, 0x3a021501},
+	{0x0000a264, 0x00000e0e, 0x00000e0e, 0x00000e0e, 0x00000e0e},
+	{0x0000a280, 0x00000007, 0x00000007, 0x0000000b, 0x0000000b},
+	{0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0},
+	{0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18},
+	{0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982},
+	{0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a},
+	{0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000be04, 0x00802020, 0x00802020, 0x00802020, 0x00802020},
+	{0x0000be18, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+};
+
+static const u32 ar9485Modes_high_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_modes_lowest_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20  */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1_radio_postamble[][2] = {
+	/* Addr        allmodes */
+	{0x0001609c, 0x0b283f31},
+	{0x000160ac, 0x24611800},
+	{0x000160b0, 0x03284f3e},
+	{0x0001610c, 0x00170000},
+	{0x00016140, 0x10804008},
+};
+
+static const u32 ar9485_1_1_mac_postamble[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x00001030, 0x00000230, 0x00000460, 0x000002c0, 0x00000160},
+	{0x00001070, 0x00000168, 0x000002d0, 0x00000318, 0x0000018c},
+	{0x000010b0, 0x00000e60, 0x00001cc0, 0x00007c70, 0x00003e38},
+	{0x00008014, 0x03e803e8, 0x07d007d0, 0x10801600, 0x08400b00},
+	{0x0000801c, 0x128d8027, 0x128d804f, 0x12e00057, 0x12e0002b},
+	{0x00008120, 0x08f04800, 0x08f04800, 0x08f04810, 0x08f04810},
+	{0x000081d0, 0x00003210, 0x00003210, 0x0000320a, 0x0000320a},
+	{0x00008318, 0x00003e80, 0x00007d00, 0x00006880, 0x00003440},
+};
+
+static const u32 ar9485_1_1_radio_core[][2] = {
+	/* Addr        allmodes */
+	{0x00016000, 0x36db6db6},
+	{0x00016004, 0x6db6db40},
+	{0x00016008, 0x73800000},
+	{0x0001600c, 0x00000000},
+	{0x00016040, 0x7f80fff8},
+	{0x0001604c, 0x000f0278},
+	{0x00016050, 0x4db6db8c},
+	{0x00016054, 0x6db60000},
+	{0x00016080, 0x00080000},
+	{0x00016084, 0x0e48048c},
+	{0x00016088, 0x14214514},
+	{0x0001608c, 0x119f081e},
+	{0x00016090, 0x24926490},
+	{0x00016098, 0xd28b3330},
+	{0x000160a0, 0xc2108ffe},
+	{0x000160a4, 0x812fc370},
+	{0x000160a8, 0x423c8000},
+	{0x000160b4, 0x92480040},
+	{0x000160c0, 0x006db6db},
+	{0x000160c4, 0x0186db60},
+	{0x000160c8, 0x6db6db6c},
+	{0x000160cc, 0x6de6fbe0},
+	{0x000160d0, 0xf7dfcf3c},
+	{0x00016100, 0x04cb0001},
+	{0x00016104, 0xfff80015},
+	{0x00016108, 0x00080010},
+	{0x00016144, 0x01884080},
+	{0x00016148, 0x00008040},
+	{0x00016240, 0x08400000},
+	{0x00016244, 0x1bf90f00},
+	{0x00016248, 0x00000000},
+	{0x0001624c, 0x00000000},
+	{0x00016280, 0x01000015},
+	{0x00016284, 0x00d30000},
+	{0x00016288, 0x00318000},
+	{0x0001628c, 0x50000000},
+	{0x00016290, 0x4b96210f},
+	{0x00016380, 0x00000000},
+	{0x00016384, 0x00000000},
+	{0x00016388, 0x00800700},
+	{0x0001638c, 0x00800700},
+	{0x00016390, 0x00800700},
+	{0x00016394, 0x00000000},
+	{0x00016398, 0x00000000},
+	{0x0001639c, 0x00000000},
+	{0x000163a0, 0x00000001},
+	{0x000163a4, 0x00000001},
+	{0x000163a8, 0x00000000},
+	{0x000163ac, 0x00000000},
+	{0x000163b0, 0x00000000},
+	{0x000163b4, 0x00000000},
+	{0x000163b8, 0x00000000},
+	{0x000163bc, 0x00000000},
+	{0x000163c0, 0x000000a0},
+	{0x000163c4, 0x000c0000},
+	{0x000163c8, 0x14021402},
+	{0x000163cc, 0x00001402},
+	{0x000163d0, 0x00000000},
+	{0x000163d4, 0x00000000},
+	{0x00016c40, 0x13188278},
+	{0x00016c44, 0x12000000},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_enable_L1[][2] = {
+	/* Addr        allmodes */
+	{0x00018c00, 0x10052e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Modes_high_power_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1[][2] = {
+	/* Addr        allmodes */
+	{0x0000a580, 0x00000000},
+	{0x0000a584, 0x00000000},
+	{0x0000a588, 0x00000000},
+	{0x0000a58c, 0x00000000},
+	{0x0000a590, 0x00000000},
+	{0x0000a594, 0x00000000},
+	{0x0000a598, 0x00000000},
+	{0x0000a59c, 0x00000000},
+	{0x0000a5a0, 0x00000000},
+	{0x0000a5a4, 0x00000000},
+	{0x0000a5a8, 0x00000000},
+	{0x0000a5ac, 0x00000000},
+	{0x0000a5b0, 0x00000000},
+	{0x0000a5b4, 0x00000000},
+	{0x0000a5b8, 0x00000000},
+	{0x0000a5bc, 0x00000000},
+};
+
+static const u32 ar9485_modes_green_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20 */
+	{0x000098bc, 0x00000003, 0x00000003, 0x00000003, 0x00000003},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x80000000, 0x80000000, 0x80000000, 0x80000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000006, 0x00000006},
+	{0x0000a504, 0x05062002, 0x05062002, 0x03000201, 0x03000201},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x06000203, 0x06000203},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0a000401, 0x0a000401},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x0e000403, 0x0e000403},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x12000405, 0x12000405},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x15000604, 0x15000604},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x18000605, 0x18000605},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x1c000a04, 0x1c000a04},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x21000a06, 0x21000a06},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x29000a24, 0x29000a24},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2f000e21, 0x2f000e21},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x31000e20, 0x31000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x33000e20, 0x33000e20},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b504, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b508, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b50c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b510, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b514, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b518, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b51c, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b520, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b524, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b528, 0x0000001a, 0x0000001a, 0x0000001a, 0x0000001a},
+	{0x0000b52c, 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a},
+	{0x0000b530, 0x0000003a, 0x0000003a, 0x0000003a, 0x0000003a},
+	{0x0000b534, 0x0000004a, 0x0000004a, 0x0000004a, 0x0000004a},
+	{0x0000b538, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b53c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b540, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b544, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b548, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b54c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b550, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b554, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b558, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b55c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b560, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b564, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b568, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b56c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b570, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b574, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b578, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x0000b57c, 0x0000005b, 0x0000005b, 0x0000005b, 0x0000005b},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
+	/* Addr        allmodes */
+	{0x00018c00, 0x10013e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_1_1_soc_preamble[][2] = {
+	/* Addr        allmodes */
+	{0x00004014, 0xba280400},
+	{0x00004090, 0x00aa10aa},
+	{0x000040a4, 0x00a0c9c9},
+	{0x00007010, 0x00000022},
+	{0x00007020, 0x00000000},
+	{0x00007034, 0x00000002},
+	{0x00007038, 0x000004c2},
+	{0x00007048, 0x00000002},
+};
+
+static const u32 ar9485_1_1_baseband_core_txfir_coeff_japan_2484[][2] = {
+	/* Addr        allmodes */
+	{0x0000a398, 0x00000000},
+	{0x0000a39c, 0x6f7f0301},
+	{0x0000a3a0, 0xca9228ee},
+};
+
+static const u32 ar9485Modes_low_ob_db_tx_gain_1_1[][5] = {
+	/* Addr        5G_HT20       5G_HT40       2G_HT40       2G_HT20  */
+	{0x000098bc, 0x00000002, 0x00000002, 0x00000002, 0x00000002},
+	{0x0000a410, 0x000050d9, 0x000050d9, 0x000050d8, 0x000050d8},
+	{0x0000a458, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000a500, 0x00022200, 0x00022200, 0x00000000, 0x00000000},
+	{0x0000a504, 0x05062002, 0x05062002, 0x04000002, 0x04000002},
+	{0x0000a508, 0x0c002e00, 0x0c002e00, 0x08000004, 0x08000004},
+	{0x0000a50c, 0x11062202, 0x11062202, 0x0d000200, 0x0d000200},
+	{0x0000a510, 0x17022e00, 0x17022e00, 0x11000202, 0x11000202},
+	{0x0000a514, 0x1d000ec2, 0x1d000ec2, 0x15000400, 0x15000400},
+	{0x0000a518, 0x25020ec0, 0x25020ec0, 0x19000402, 0x19000402},
+	{0x0000a51c, 0x2b020ec3, 0x2b020ec3, 0x1d000404, 0x1d000404},
+	{0x0000a520, 0x2f001f04, 0x2f001f04, 0x21000603, 0x21000603},
+	{0x0000a524, 0x35001fc4, 0x35001fc4, 0x25000605, 0x25000605},
+	{0x0000a528, 0x3c022f04, 0x3c022f04, 0x2a000a03, 0x2a000a03},
+	{0x0000a52c, 0x41023e85, 0x41023e85, 0x2c000a04, 0x2c000a04},
+	{0x0000a530, 0x48023ec6, 0x48023ec6, 0x34000e20, 0x34000e20},
+	{0x0000a534, 0x4d023f01, 0x4d023f01, 0x35000e21, 0x35000e21},
+	{0x0000a538, 0x53023f4b, 0x53023f4b, 0x43000e62, 0x43000e62},
+	{0x0000a53c, 0x5a027f09, 0x5a027f09, 0x45000e63, 0x45000e63},
+	{0x0000a540, 0x5f027fc9, 0x5f027fc9, 0x49000e65, 0x49000e65},
+	{0x0000a544, 0x6502feca, 0x6502feca, 0x4b000e66, 0x4b000e66},
+	{0x0000a548, 0x6b02ff4a, 0x6b02ff4a, 0x4d001645, 0x4d001645},
+	{0x0000a54c, 0x7203feca, 0x7203feca, 0x51001865, 0x51001865},
+	{0x0000a550, 0x7703ff0b, 0x7703ff0b, 0x55001a86, 0x55001a86},
+	{0x0000a554, 0x7d06ffcb, 0x7d06ffcb, 0x57001ce9, 0x57001ce9},
+	{0x0000a558, 0x8407ff0b, 0x8407ff0b, 0x5a001eeb, 0x5a001eeb},
+	{0x0000a55c, 0x8907ffcb, 0x8907ffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a560, 0x900fff0b, 0x900fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a564, 0x960fffcb, 0x960fffcb, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a568, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a56c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a570, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a574, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a578, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000a57c, 0x9c1fff0b, 0x9c1fff0b, 0x5e001eeb, 0x5e001eeb},
+	{0x0000b500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b504, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b508, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b50c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b510, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b514, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b518, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b51c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b520, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b524, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b528, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b52c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b530, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b534, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b538, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b53c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b540, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b544, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b548, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b54c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b550, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b554, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b558, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b55c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b560, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b564, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b568, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b56c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b570, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b574, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b578, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x0000b57c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
+	{0x00016044, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db, 0x05d6b2db},
+	{0x00016048, 0x6c924260, 0x6c924260, 0x6c924260, 0x6c924260},
+};
+
+static const u32 ar9485_fast_clock_1_1_baseband_postamble[][3] = {
+	/* Addr        5G_HT2        5G_HT40  */
+	{0x00009e00, 0x03721821, 0x03721821},
+	{0x0000a230, 0x0000400b, 0x00004016},
+	{0x0000a254, 0x00000898, 0x00001130},
+};
+
+static const u32 ar9485_1_1_pcie_phy_pll_on_clkreq_disable_L1[][2] = {
+	/* Addr        allmodes  */
+	{0x00018c00, 0x10012e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485_common_rx_gain_1_1[][2] = {
+	/* Addr        allmodes */
+	{0x0000a000, 0x00010000},
+	{0x0000a004, 0x00030002},
+	{0x0000a008, 0x00050004},
+	{0x0000a00c, 0x00810080},
+	{0x0000a010, 0x01800082},
+	{0x0000a014, 0x01820181},
+	{0x0000a018, 0x01840183},
+	{0x0000a01c, 0x01880185},
+	{0x0000a020, 0x018a0189},
+	{0x0000a024, 0x02850284},
+	{0x0000a028, 0x02890288},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x21212128},
+	{0x0000a098, 0x171c1c1c},
+	{0x0000a09c, 0x02020212},
+	{0x0000a0a0, 0x00000202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x001f0000},
+	{0x0000a0c4, 0x111f1100},
+	{0x0000a0c8, 0x111d111e},
+	{0x0000a0cc, 0x111b111c},
+	{0x0000a0d0, 0x22032204},
+	{0x0000a0d4, 0x22012202},
+	{0x0000a0d8, 0x221f2200},
+	{0x0000a0dc, 0x221d221e},
+	{0x0000a0e0, 0x33013302},
+	{0x0000a0e4, 0x331f3300},
+	{0x0000a0e8, 0x4402331e},
+	{0x0000a0ec, 0x44004401},
+	{0x0000a0f0, 0x441e441f},
+	{0x0000a0f4, 0x55015502},
+	{0x0000a0f8, 0x551f5500},
+	{0x0000a0fc, 0x6602551e},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
+static const u32 ar9485_1_1_pcie_phy_clkreq_enable_L1[][2] = {
+	/* Addr        allmodes */
+	{0x00018c00, 0x10053e5e},
+	{0x00018c04, 0x000801d8},
+	{0x00018c08, 0x0000080c},
+};
+
+static const u32 ar9485Common_wo_xlna_rx_gain_1_1[][2] = {
+	/* Addr        allmodes */
+	{0x0000a000, 0x00060005},
+	{0x0000a004, 0x00810080},
+	{0x0000a008, 0x00830082},
+	{0x0000a00c, 0x00850084},
+	{0x0000a010, 0x01820181},
+	{0x0000a014, 0x01840183},
+	{0x0000a018, 0x01880185},
+	{0x0000a01c, 0x018a0189},
+	{0x0000a020, 0x02850284},
+	{0x0000a024, 0x02890288},
+	{0x0000a028, 0x028b028a},
+	{0x0000a02c, 0x03850384},
+	{0x0000a030, 0x03890388},
+	{0x0000a034, 0x038b038a},
+	{0x0000a038, 0x038d038c},
+	{0x0000a03c, 0x03910390},
+	{0x0000a040, 0x03930392},
+	{0x0000a044, 0x03950394},
+	{0x0000a048, 0x00000396},
+	{0x0000a04c, 0x00000000},
+	{0x0000a050, 0x00000000},
+	{0x0000a054, 0x00000000},
+	{0x0000a058, 0x00000000},
+	{0x0000a05c, 0x00000000},
+	{0x0000a060, 0x00000000},
+	{0x0000a064, 0x00000000},
+	{0x0000a068, 0x00000000},
+	{0x0000a06c, 0x00000000},
+	{0x0000a070, 0x00000000},
+	{0x0000a074, 0x00000000},
+	{0x0000a078, 0x00000000},
+	{0x0000a07c, 0x00000000},
+	{0x0000a080, 0x28282828},
+	{0x0000a084, 0x28282828},
+	{0x0000a088, 0x28282828},
+	{0x0000a08c, 0x28282828},
+	{0x0000a090, 0x28282828},
+	{0x0000a094, 0x24242428},
+	{0x0000a098, 0x171e1e1e},
+	{0x0000a09c, 0x02020b0b},
+	{0x0000a0a0, 0x02020202},
+	{0x0000a0a4, 0x00000000},
+	{0x0000a0a8, 0x00000000},
+	{0x0000a0ac, 0x00000000},
+	{0x0000a0b0, 0x00000000},
+	{0x0000a0b4, 0x00000000},
+	{0x0000a0b8, 0x00000000},
+	{0x0000a0bc, 0x00000000},
+	{0x0000a0c0, 0x22072208},
+	{0x0000a0c4, 0x22052206},
+	{0x0000a0c8, 0x22032204},
+	{0x0000a0cc, 0x22012202},
+	{0x0000a0d0, 0x221f2200},
+	{0x0000a0d4, 0x221d221e},
+	{0x0000a0d8, 0x33023303},
+	{0x0000a0dc, 0x33003301},
+	{0x0000a0e0, 0x331e331f},
+	{0x0000a0e4, 0x4402331d},
+	{0x0000a0e8, 0x44004401},
+	{0x0000a0ec, 0x441e441f},
+	{0x0000a0f0, 0x55025503},
+	{0x0000a0f4, 0x55005501},
+	{0x0000a0f8, 0x551e551f},
+	{0x0000a0fc, 0x6602551d},
+	{0x0000a100, 0x66006601},
+	{0x0000a104, 0x661e661f},
+	{0x0000a108, 0x7703661d},
+	{0x0000a10c, 0x77017702},
+	{0x0000a110, 0x00007700},
+	{0x0000a114, 0x00000000},
+	{0x0000a118, 0x00000000},
+	{0x0000a11c, 0x00000000},
+	{0x0000a120, 0x00000000},
+	{0x0000a124, 0x00000000},
+	{0x0000a128, 0x00000000},
+	{0x0000a12c, 0x00000000},
+	{0x0000a130, 0x00000000},
+	{0x0000a134, 0x00000000},
+	{0x0000a138, 0x00000000},
+	{0x0000a13c, 0x00000000},
+	{0x0000a140, 0x001f0000},
+	{0x0000a144, 0x111f1100},
+	{0x0000a148, 0x111d111e},
+	{0x0000a14c, 0x111b111c},
+	{0x0000a150, 0x22032204},
+	{0x0000a154, 0x22012202},
+	{0x0000a158, 0x221f2200},
+	{0x0000a15c, 0x221d221e},
+	{0x0000a160, 0x33013302},
+	{0x0000a164, 0x331f3300},
+	{0x0000a168, 0x4402331e},
+	{0x0000a16c, 0x44004401},
+	{0x0000a170, 0x441e441f},
+	{0x0000a174, 0x55015502},
+	{0x0000a178, 0x551f5500},
+	{0x0000a17c, 0x6602551e},
+	{0x0000a180, 0x66006601},
+	{0x0000a184, 0x661e661f},
+	{0x0000a188, 0x7703661d},
+	{0x0000a18c, 0x77017702},
+	{0x0000a190, 0x00007700},
+	{0x0000a194, 0x00000000},
+	{0x0000a198, 0x00000000},
+	{0x0000a19c, 0x00000000},
+	{0x0000a1a0, 0x00000000},
+	{0x0000a1a4, 0x00000000},
+	{0x0000a1a8, 0x00000000},
+	{0x0000a1ac, 0x00000000},
+	{0x0000a1b0, 0x00000000},
+	{0x0000a1b4, 0x00000000},
+	{0x0000a1b8, 0x00000000},
+	{0x0000a1bc, 0x00000000},
+	{0x0000a1c0, 0x00000000},
+	{0x0000a1c4, 0x00000000},
+	{0x0000a1c8, 0x00000000},
+	{0x0000a1cc, 0x00000000},
+	{0x0000a1d0, 0x00000000},
+	{0x0000a1d4, 0x00000000},
+	{0x0000a1d8, 0x00000000},
+	{0x0000a1dc, 0x00000000},
+	{0x0000a1e0, 0x00000000},
+	{0x0000a1e4, 0x00000000},
+	{0x0000a1e8, 0x00000000},
+	{0x0000a1ec, 0x00000000},
+	{0x0000a1f0, 0x00000396},
+	{0x0000a1f4, 0x00000396},
+	{0x0000a1f8, 0x00000396},
+	{0x0000a1fc, 0x00000296},
+};
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ath9k.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ath9k.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/ath9k.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/ath9k.h	2011-05-19 00:06:34.000000000 -0400
@@ -92,9 +92,9 @@
  * @BUF_XRETRY: To denote excessive retries of the buffer
  */
 enum buffer_type {
-	BUF_AMPDU		= BIT(2),
-	BUF_AGGR		= BIT(3),
-	BUF_XRETRY		= BIT(5),
+	BUF_AMPDU		= BIT(0),
+	BUF_AGGR		= BIT(1),
+	BUF_XRETRY		= BIT(2),
 };
 
 #define bf_isampdu(bf)		(bf->bf_state.bf_type & BUF_AMPDU)
@@ -134,7 +134,6 @@
 	 (((_tid) == 4) || ((_tid) == 5)) ? WME_AC_VI :	\
 	 WME_AC_VO)
 
-#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 */
@@ -181,7 +180,8 @@
 
 #define ATH_TXFIFO_DEPTH 8
 struct ath_txq {
-	u32 axq_qnum;
+	int mac80211_qnum; /* mac80211 queue number, -1 means not mac80211 Q */
+	u32 axq_qnum; /* ath9k hardware queue number */
 	u32 *axq_link;
 	struct list_head axq_q;
 	spinlock_t axq_lock;
@@ -231,7 +231,6 @@
 	bool bf_stale;
 	u16 bf_flags;
 	struct ath_buf_state bf_state;
-	struct ath_wiphy *aphy;
 };
 
 struct ath_atx_tid {
@@ -252,7 +251,10 @@
 };
 
 struct ath_node {
-	struct ath_common *common;
+#ifdef CONFIG_ATH9K_DEBUGFS
+	struct list_head list; /* for sc->nodes */
+	struct ieee80211_sta *sta; /* station struct we're part of */
+#endif
 	struct ath_atx_tid tid[WME_NUM_TID];
 	struct ath_atx_ac ac[WME_NUM_AC];
 	u16 maxampdu;
@@ -275,6 +277,11 @@
 #define ATH_TX_XRETRY       0x02
 #define ATH_TX_BAR          0x04
 
+/**
+ * @txq_map:  Index is mac80211 queue number.  This is
+ *  not necessarily the same as the hardware queue number
+ *  (axq_qnum).
+ */
 struct ath_tx {
 	u16 seq_no;
 	u32 txqsetup;
@@ -301,6 +308,8 @@
 	struct ath_descdma rxdma;
 	struct ath_buf *rx_bufptr;
 	struct ath_rx_edma rx_edma[ATH9K_RX_QUEUE_MAX];
+
+	struct sk_buff *frag;
 };
 
 int ath_startrecv(struct ath_softc *sc);
@@ -337,10 +346,10 @@
 
 struct ath_vif {
 	int av_bslot;
+	bool is_bslot_active;
 	__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 */
 };
 
@@ -360,7 +369,7 @@
 #define IEEE80211_MS_TO_TU(x)           (((x) * 1000) / 1024)
 
 struct ath_beacon_config {
-	u16 beacon_interval;
+	int beacon_interval;
 	u16 listen_interval;
 	u16 dtim_period;
 	u16 bmiss_timeout;
@@ -379,7 +388,6 @@
 	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;
@@ -390,9 +398,10 @@
 
 void ath_beacon_tasklet(unsigned long data);
 void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
-int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
+int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif);
 void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
 int ath_beaconq_config(struct ath_softc *sc);
+void ath9k_set_beaconing_status(struct ath_softc *sc, bool status);
 
 /*******/
 /* ANI */
@@ -439,26 +448,21 @@
 
 #define ATH_LED_PIN_DEF 		1
 #define ATH_LED_PIN_9287		8
-#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;
-};
+#define ATH_LED_PIN_9485		6
 
+#ifdef CONFIG_MAC80211_LEDS
 void ath_init_leds(struct ath_softc *sc);
 void ath_deinit_leds(struct ath_softc *sc);
+#else
+static inline void ath_init_leds(struct ath_softc *sc)
+{
+}
+
+static inline void ath_deinit_leds(struct ath_softc *sc)
+{
+}
+#endif
+
 
 /* Antenna diversity/combining */
 #define ATH_ANT_RX_CURRENT_SHIFT 4
@@ -527,7 +531,6 @@
 #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 */
 
 #define ATH_TXPOWER_MAX         100     /* .5 dBm units */
 #define ATH_RATE_DUMMY_MARKER   0
@@ -555,27 +558,28 @@
 #define PS_WAIT_FOR_TX_ACK        BIT(3)
 #define PS_BEACON_SYNC            BIT(4)
 
-struct ath_wiphy;
 struct ath_rate_table;
 
+struct ath9k_vif_iter_data {
+	const u8 *hw_macaddr; /* phy's hardware address, set
+			       * before starting iteration for
+			       * valid bssid mask.
+			       */
+	u8 mask[ETH_ALEN]; /* bssid mask */
+	int naps;      /* number of AP vifs */
+	int nmeshes;   /* number of mesh vifs */
+	int nstations; /* number of station vifs */
+	int nwds;      /* number of nwd vifs */
+	int nadhocs;   /* number of adhoc vifs */
+	int nothers;   /* number of vifs not specified above. */
+};
+
 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 survey_info *cur_survey;
 	struct survey_info survey[ATH9K_NUM_CHANNELS];
 
@@ -592,14 +596,16 @@
 	struct work_struct hw_check_work;
 	struct completion paprd_complete;
 
+	unsigned int hw_busy_count;
+
 	u32 intrstatus;
 	u32 sc_flags; /* SC_OP_* */
 	u16 ps_flags; /* PS_* */
 	u16 curtxpow;
-	u8 nbcnvifs;
-	u16 nvifs;
 	bool ps_enabled;
 	bool ps_idle;
+	short nbcnvifs;
+	short nvifs;
 	unsigned long ps_usecount;
 
 	struct ath_config config;
@@ -608,23 +614,24 @@
 	struct ath_beacon beacon;
 	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;
+#ifdef CONFIG_MAC80211_LEDS
+	bool led_registered;
+	char led_name[32];
+	struct led_classdev led_cdev;
+#endif
 
-	int beacon_interval;
+	struct ath9k_hw_cal_data caldata;
+	int last_rssi;
 
 #ifdef CONFIG_ATH9K_DEBUGFS
 	struct ath9k_debug debug;
+	spinlock_t nodes_lock;
+	struct list_head nodes; /* basically, stations */
+	unsigned int tx_complete_poll_work_seen;
 #endif
 	struct ath_beacon_config cur_beacon_conf;
 	struct delayed_work tx_complete_work;
+	struct delayed_work hw_pll_work;
 	struct ath_btcoex btcoex;
 
 	struct ath_descdma txsdma;
@@ -632,23 +639,6 @@
 	struct ath_ant_comb ant_comb;
 };
 
-struct ath_wiphy {
-	struct ath_softc *sc; /* shared for all virtual wiphys */
-	struct ieee80211_hw *hw;
-	struct ath9k_hw_cal_data caldata;
-	enum ath_wiphy_state {
-		ATH_WIPHY_INACTIVE,
-		ATH_WIPHY_ACTIVE,
-		ATH_WIPHY_PAUSING,
-		ATH_WIPHY_PAUSED,
-		ATH_WIPHY_SCAN,
-	} state;
-	bool idle;
-	int chan_idx;
-	int chan_is_ht;
-	int last_rssi;
-};
-
 void ath9k_tasklet(unsigned long data);
 int ath_reset(struct ath_softc *sc, bool retry_tx);
 int ath_cabq_update(struct ath_softc *);
@@ -669,14 +659,13 @@
 		    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
 void ath9k_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);
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan);
 
 void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw);
 void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw);
 bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode);
+bool ath9k_uses_beacons(int type);
 
 #ifdef CONFIG_PCI
 int ath_pci_init(void);
@@ -700,26 +689,12 @@
 u8 ath_txchainmask_reduction(struct ath_softc *sc, u8 chainmask, u32 rate);
 
 void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
-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 ftype);
-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);
-bool ath9k_all_wiphys_idle(struct ath_softc *sc);
-void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle);
-
-void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue);
-bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue);
 
 void ath_start_rfkill_poll(struct ath_softc *sc);
 extern void ath9k_rfkill_poll_state(struct ieee80211_hw *hw);
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ath9k_vif_iter_data *iter_data);
+
 
 #endif /* ATH9K_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/beacon.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/beacon.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/beacon.c	2011-05-19 00:06:34.000000000 -0400
@@ -112,8 +112,7 @@
 
 static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_tx_control txctl;
 
@@ -132,8 +131,7 @@
 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_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_buf *bf;
 	struct ath_vif *avp;
@@ -142,13 +140,10 @@
 	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)
+	if ((avp->av_bcbuf == NULL) || !avp->is_bslot_active)
 		return NULL;
 
 	/* Release the old beacon first */
@@ -225,13 +220,13 @@
 	return bf;
 }
 
-int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
+int ath_beacon_alloc(struct ath_softc *sc, struct ieee80211_vif *vif)
 {
-	struct ath_softc *sc = aphy->sc;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_vif *avp;
 	struct ath_buf *bf;
 	struct sk_buff *skb;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	__le64 tstamp;
 
 	avp = (void *)vif->drv_priv;
@@ -244,9 +239,7 @@
 						 struct ath_buf, list);
 		list_del(&avp->av_bcbuf->list);
 
-		if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
-		    sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC ||
-		    sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) {
+		if (ath9k_uses_beacons(vif->type)) {
 			int slot;
 			/*
 			 * Assign the vif to a beacon xmit slot. As
@@ -256,6 +249,7 @@
 			for (slot = 0; slot < ATH_BCBUF; slot++)
 				if (sc->beacon.bslot[slot] == NULL) {
 					avp->av_bslot = slot;
+					avp->is_bslot_active = false;
 
 					/* NB: keep looking for a double slot */
 					if (slot == 0 || !sc->beacon.bslot[slot-1])
@@ -263,7 +257,6 @@
 				}
 			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++;
 		}
 	}
@@ -281,10 +274,8 @@
 
 	/* NB: the beacon data buffer must be 32-bit aligned. */
 	skb = ieee80211_beacon_get(sc->hw, vif);
-	if (skb == NULL) {
-		ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n");
+	if (skb == NULL)
 		return -ENOMEM;
-	}
 
 	tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
 	sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
@@ -293,7 +284,7 @@
 		u64 tsfadjust;
 		int intval;
 
-		intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+		intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 
 		/*
 		 * Calculate the TSF offset for this beacon slot, i.e., the
@@ -325,6 +316,7 @@
 		ath_err(common, "dma_mapping_error on beacon alloc\n");
 		return -ENOMEM;
 	}
+	avp->is_bslot_active = true;
 
 	return 0;
 }
@@ -336,7 +328,6 @@
 
 		if (avp->av_bslot != -1) {
 			sc->beacon.bslot[avp->av_bslot] = NULL;
-			sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
 			sc->nbcnvifs--;
 		}
 
@@ -358,11 +349,11 @@
 void ath_beacon_tasklet(unsigned long data)
 {
 	struct ath_softc *sc = (struct ath_softc *)data;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_buf *bf = NULL;
 	struct ieee80211_vif *vif;
-	struct ath_wiphy *aphy;
 	int slot;
 	u32 bfaddr, bc = 0, tsftu;
 	u64 tsf;
@@ -382,6 +373,7 @@
 			ath_dbg(common, ATH_DBG_BSTUCK,
 				"missed %u consecutive beacons\n",
 				sc->beacon.bmisscnt);
+			ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
 			ath9k_hw_bstuck_nfcal(ah);
 		} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
 			ath_dbg(common, ATH_DBG_BSTUCK,
@@ -406,7 +398,7 @@
 	 * on the tsf to safeguard against missing an swba.
 	 */
 
-	intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
+	intval = cur_conf->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 
 	tsf = ath9k_hw_gettsf64(ah);
 	tsftu = TSF_TO_TU(tsf>>32, tsf);
@@ -420,7 +412,6 @@
 	 */
 	slot = ATH_BCBUF - slot - 1;
 	vif = sc->beacon.bslot[slot];
-	aphy = sc->beacon.bslot_aphy[slot];
 
 	ath_dbg(common, ATH_DBG_BEACON,
 		"slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
@@ -428,7 +419,7 @@
 
 	bfaddr = 0;
 	if (vif) {
-		bf = ath_beacon_generate(aphy->hw, vif);
+		bf = ath_beacon_generate(sc->hw, vif);
 		if (bf != NULL) {
 			bfaddr = bf->bf_daddr;
 			bc = 1;
@@ -460,16 +451,6 @@
 		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)) {
-			ath_err(common, "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);
@@ -720,10 +701,10 @@
 		iftype = sc->sc_ah->opmode;
 	}
 
-		cur_conf->listen_interval = 1;
-		cur_conf->dtim_count = 1;
-		cur_conf->bmiss_timeout =
-			ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+	cur_conf->listen_interval = 1;
+	cur_conf->dtim_count = 1;
+	cur_conf->bmiss_timeout =
+		ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
 
 	/*
 	 * It looks like mac80211 may end up using beacon interval of zero in
@@ -735,8 +716,9 @@
 		cur_conf->beacon_interval = 100;
 
 	/*
-	 * Some times we dont parse dtim period from mac80211, in that case
-	 * use a default value
+	 * We don't parse dtim period from mac80211 during the driver
+	 * initialization as it breaks association with hidden-ssid
+	 * AP and it causes latency in roaming
 	 */
 	if (cur_conf->dtim_period == 0)
 		cur_conf->dtim_period = 1;
@@ -760,3 +742,36 @@
 
 	sc->sc_flags |= SC_OP_BEACONS;
 }
+
+void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
+{
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_vif *avp;
+	int slot;
+	bool found = false;
+
+	ath9k_ps_wakeup(sc);
+	if (status) {
+		for (slot = 0; slot < ATH_BCBUF; slot++) {
+			if (sc->beacon.bslot[slot]) {
+				avp = (void *)sc->beacon.bslot[slot]->drv_priv;
+				if (avp->is_bslot_active) {
+					found = true;
+					break;
+				}
+			}
+		}
+		if (found) {
+			/* Re-enable beaconing */
+			ah->imask |= ATH9K_INT_SWBA;
+			ath9k_hw_set_interrupts(ah, ah->imask);
+		}
+	} else {
+		/* Disable SWBA interrupt */
+		ah->imask &= ~ATH9K_INT_SWBA;
+		ath9k_hw_set_interrupts(ah, ah->imask);
+		tasklet_kill(&sc->bcon_tasklet);
+		ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
+	}
+	ath9k_ps_restore(sc);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/calib.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/calib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/calib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/calib.c	2011-05-19 00:06:34.000000000 -0400
@@ -262,7 +262,7 @@
 	 * since 250us often results in NF load timeout and causes deaf
 	 * condition during stress testing 12/12/2009
 	 */
-	for (j = 0; j < 1000; j++) {
+	for (j = 0; j < 10000; j++) {
 		if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
 		     AR_PHY_AGC_CONTROL_NF) == 0)
 			break;
@@ -278,7 +278,7 @@
 	 * here, the baseband nf cal will just be capped by our present
 	 * noisefloor until the next calibration timer.
 	 */
-	if (j == 1000) {
+	if (j == 10000) {
 		ath_dbg(common, ATH_DBG_ANY,
 			"Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
 			REG_READ(ah, AR_PHY_AGC_CONTROL));
@@ -382,9 +382,8 @@
 	s16 default_nf;
 	int i, j;
 
-	if (!ah->caldata)
-		return;
-
+	ah->caldata->channel = chan->channel;
+	ah->caldata->channelFlags = chan->channelFlags & ~CHANNEL_CW_INT;
 	h = ah->caldata->nfCalHist;
 	default_nf = ath9k_hw_get_default_nf(ah, chan);
 	for (i = 0; i < NUM_NF_READINGS; i++) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/common.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/common.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/common.c	2011-05-19 00:06:34.000000000 -0400
@@ -189,6 +189,17 @@
 }
 EXPORT_SYMBOL(ath9k_cmn_btcoex_bt_stomp);
 
+void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+			    u16 new_txpow, u16 *txpower)
+{
+	if (cur_txpow != new_txpow) {
+		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
+		/* read back in case value is clamped */
+		*txpower = ath9k_hw_regulatory(ah)->power_limit;
+	}
+}
+EXPORT_SYMBOL(ath9k_cmn_update_txpow);
+
 static int __init ath9k_cmn_init(void)
 {
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/common.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/common.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -23,8 +23,6 @@
 
 /* Common header for Atheros 802.11n base driver cores */
 
-#define IEEE80211_WEP_NKID 4
-
 #define WME_NUM_TID             16
 #define WME_BA_BMP_SIZE         64
 #define WME_MAX_BA              WME_BA_BMP_SIZE
@@ -70,3 +68,5 @@
 int ath9k_cmn_count_streams(unsigned int chainmask, int max);
 void ath9k_cmn_btcoex_bt_stomp(struct ath_common *common,
 				  enum ath_stomp_type stomp_type);
+void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
+			    u16 new_txpow, u16 *txpower);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/debug.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/debug.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
  */
 
 #include <linux/slab.h>
+#include <linux/vmalloc.h>
 #include <asm/unaligned.h>
 
 #include "ath9k.h"
@@ -30,6 +31,19 @@
 	return 0;
 }
 
+static ssize_t ath9k_debugfs_read_buf(struct file *file, char __user *user_buf,
+				      size_t count, loff_t *ppos)
+{
+	u8 *buf = file->private_data;
+	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
+}
+
+static int ath9k_debugfs_release_buf(struct inode *inode, struct file *file)
+{
+	vfree(file->private_data);
+	return 0;
+}
+
 #ifdef CONFIG_ATH_DEBUG
 
 static ssize_t read_file_debug(struct file *file, char __user *user_buf,
@@ -381,41 +395,40 @@
 	.llseek = default_llseek,
 };
 
-static const char * ath_wiphy_state_str(enum ath_wiphy_state state)
+static const char *channel_type_str(enum nl80211_channel_type t)
 {
-	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";
+	switch (t) {
+	case NL80211_CHAN_NO_HT:
+		return "no ht";
+	case NL80211_CHAN_HT20:
+		return "ht20";
+	case NL80211_CHAN_HT40MINUS:
+		return "ht40-";
+	case NL80211_CHAN_HT40PLUS:
+		return "ht40+";
+	default:
+		return "???";
 	}
-	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;
-	struct ath_wiphy *aphy = sc->pri_wiphy;
-	struct ieee80211_channel *chan = aphy->hw->conf.channel;
+	struct ieee80211_channel *chan = sc->hw->conf.channel;
+	struct ieee80211_conf *conf = &(sc->hw->conf);
 	char buf[512];
 	unsigned int len = 0;
-	int i;
 	u8 addr[ETH_ALEN];
 	u32 tmp;
 
 	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),
+			"%s (chan=%d  center-freq: %d MHz  channel-type: %d (%s))\n",
+			wiphy_name(sc->hw->wiphy),
 			ieee80211_frequency_to_channel(chan->center_freq),
-			aphy->chan_is_ht);
+			chan->center_freq,
+			conf->channel_type,
+			channel_type_str(conf->channel_type));
 
 	put_unaligned_le32(REG_READ_D(sc->sc_ah, AR_STA_ID0), addr);
 	put_unaligned_le16(REG_READ_D(sc->sc_ah, AR_STA_ID1) & 0xffff, addr + 4);
@@ -457,156 +470,82 @@
 	else
 		len += snprintf(buf + len, sizeof(buf) - len, "\n");
 
-	/* Put variable-length stuff down here, and check for overflows. */
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy_tmp = sc->sec_wiphy[i];
-		if (aphy_tmp == NULL)
-			continue;
-		chan = aphy_tmp->hw->conf.channel;
-		len += snprintf(buf + len, sizeof(buf) - len,
-			"secondary: %s (%s chan=%d ht=%d)\n",
-			wiphy_name(aphy_tmp->hw->wiphy),
-			ath_wiphy_state_str(aphy_tmp->state),
-			ieee80211_frequency_to_channel(chan->center_freq),
-						       aphy_tmp->chan_is_ht);
-	}
 	if (len > sizeof(buf))
 		len = sizeof(buf);
 
 	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,
 	.llseek = default_llseek,
 };
 
+#define PR_QNUM(_n) sc->tx.txq_map[_n]->axq_qnum
 #define PR(str, elem)							\
 	do {								\
 		len += snprintf(buf + len, size - len,			\
 				"%s%13u%11u%10u%10u\n", str,		\
-		sc->debug.stats.txstats[WME_AC_BE].elem, \
-		sc->debug.stats.txstats[WME_AC_BK].elem, \
-		sc->debug.stats.txstats[WME_AC_VI].elem, \
-		sc->debug.stats.txstats[WME_AC_VO].elem); \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_BE)].elem, \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_BK)].elem, \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_VI)].elem, \
+		sc->debug.stats.txstats[PR_QNUM(WME_AC_VO)].elem); \
+		if (len >= size)			  \
+			goto done;			  \
 } while(0)
 
+#define PRX(str, elem)							\
+do {									\
+	len += snprintf(buf + len, size - len,				\
+			"%s%13u%11u%10u%10u\n", str,			\
+			(unsigned int)(sc->tx.txq_map[WME_AC_BE]->elem),	\
+			(unsigned int)(sc->tx.txq_map[WME_AC_BK]->elem),	\
+			(unsigned int)(sc->tx.txq_map[WME_AC_VI]->elem),	\
+			(unsigned int)(sc->tx.txq_map[WME_AC_VO]->elem));	\
+	if (len >= size)						\
+		goto done;						\
+} while(0)
+
+#define PRQLE(str, elem)						\
+do {									\
+	len += snprintf(buf + len, size - len,				\
+			"%s%13i%11i%10i%10i\n", str,			\
+			list_empty(&sc->tx.txq_map[WME_AC_BE]->elem),	\
+			list_empty(&sc->tx.txq_map[WME_AC_BK]->elem),	\
+			list_empty(&sc->tx.txq_map[WME_AC_VI]->elem),	\
+			list_empty(&sc->tx.txq_map[WME_AC_VO]->elem));	\
+	if (len >= size)						\
+		goto done;						\
+} while (0)
+
 static ssize_t read_file_xmit(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, size = 2048;
+	unsigned int len = 0, size = 8000;
+	int i;
 	ssize_t retval = 0;
+	char tmp[32];
 
 	buf = kzalloc(size, GFP_KERNEL);
 	if (buf == NULL)
 		return -ENOMEM;
 
-	len += sprintf(buf, "%30s %10s%10s%10s\n\n", "BE", "BK", "VI", "VO");
+	len += sprintf(buf, "Num-Tx-Queues: %i  tx-queues-setup: 0x%x"
+		       " poll-work-seen: %u\n"
+		       "%30s %10s%10s%10s\n\n",
+		       ATH9K_NUM_TX_QUEUES, sc->tx.txqsetup,
+		       sc->tx_complete_poll_work_seen,
+		       "BE", "BK", "VI", "VO");
 
 	PR("MPDUs Queued:    ", queued);
 	PR("MPDUs Completed: ", completed);
 	PR("Aggregates:      ", a_aggr);
-	PR("AMPDUs Queued:   ", a_queued);
+	PR("AMPDUs Queued HW:", a_queued_hw);
+	PR("AMPDUs Queued SW:", a_queued_sw);
 	PR("AMPDUs Completed:", a_completed);
 	PR("AMPDUs Retried:  ", a_retries);
 	PR("AMPDUs XRetried: ", a_xretries);
@@ -618,6 +557,223 @@
 	PR("DELIM Underrun:  ", delim_underrun);
 	PR("TX-Pkts-All:     ", tx_pkts_all);
 	PR("TX-Bytes-All:    ", tx_bytes_all);
+	PR("hw-put-tx-buf:   ", puttxbuf);
+	PR("hw-tx-start:     ", txstart);
+	PR("hw-tx-proc-desc: ", txprocdesc);
+	len += snprintf(buf + len, size - len,
+			"%s%11p%11p%10p%10p\n", "txq-memory-address:",
+			sc->tx.txq_map[WME_AC_BE],
+			sc->tx.txq_map[WME_AC_BK],
+			sc->tx.txq_map[WME_AC_VI],
+			sc->tx.txq_map[WME_AC_VO]);
+	if (len >= size)
+		goto done;
+
+	PRX("axq-qnum:        ", axq_qnum);
+	PRX("axq-depth:       ", axq_depth);
+	PRX("axq-ampdu_depth: ", axq_ampdu_depth);
+	PRX("axq-stopped      ", stopped);
+	PRX("tx-in-progress   ", axq_tx_inprogress);
+	PRX("pending-frames   ", pending_frames);
+	PRX("txq_headidx:     ", txq_headidx);
+	PRX("txq_tailidx:     ", txq_headidx);
+
+	PRQLE("axq_q empty:       ", axq_q);
+	PRQLE("axq_acq empty:     ", axq_acq);
+	PRQLE("txq_fifo_pending:  ", txq_fifo_pending);
+	for (i = 0; i < ATH_TXFIFO_DEPTH; i++) {
+		snprintf(tmp, sizeof(tmp) - 1, "txq_fifo[%i] empty: ", i);
+		PRQLE(tmp, txq_fifo[i]);
+	}
+
+	/* Print out more detailed queue-info */
+	for (i = 0; i <= WME_AC_BK; i++) {
+		struct ath_txq *txq = &(sc->tx.txq[i]);
+		struct ath_atx_ac *ac;
+		struct ath_atx_tid *tid;
+		if (len >= size)
+			goto done;
+		spin_lock_bh(&txq->axq_lock);
+		if (!list_empty(&txq->axq_acq)) {
+			ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac,
+					      list);
+			len += snprintf(buf + len, size - len,
+					"txq[%i] first-ac: %p sched: %i\n",
+					i, ac, ac->sched);
+			if (list_empty(&ac->tid_q) || (len >= size))
+				goto done_for;
+			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+					       list);
+			len += snprintf(buf + len, size - len,
+					" first-tid: %p sched: %i paused: %i\n",
+					tid, tid->sched, tid->paused);
+		}
+	done_for:
+		spin_unlock_bh(&txq->axq_lock);
+	}
+
+done:
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static ssize_t read_file_stations(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, size = 64000;
+	struct ath_node *an = NULL;
+	ssize_t retval = 0;
+	int q;
+
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	len += snprintf(buf + len, size - len,
+			"Stations:\n"
+			" tid: addr sched paused buf_q-empty an ac\n"
+			" ac: addr sched tid_q-empty txq\n");
+
+	spin_lock(&sc->nodes_lock);
+	list_for_each_entry(an, &sc->nodes, list) {
+		len += snprintf(buf + len, size - len,
+				"%pM\n", an->sta->addr);
+		if (len >= size)
+			goto done;
+
+		for (q = 0; q < WME_NUM_TID; q++) {
+			struct ath_atx_tid *tid = &(an->tid[q]);
+			len += snprintf(buf + len, size - len,
+					" tid: %p %s %s %i %p %p\n",
+					tid, tid->sched ? "sched" : "idle",
+					tid->paused ? "paused" : "running",
+					list_empty(&tid->buf_q),
+					tid->an, tid->ac);
+			if (len >= size)
+				goto done;
+		}
+
+		for (q = 0; q < WME_NUM_AC; q++) {
+			struct ath_atx_ac *ac = &(an->ac[q]);
+			len += snprintf(buf + len, size - len,
+					" ac: %p %s %i %p\n",
+					ac, ac->sched ? "sched" : "idle",
+					list_empty(&ac->tid_q), ac->txq);
+			if (len >= size)
+				goto done;
+		}
+	}
+
+done:
+	spin_unlock(&sc->nodes_lock);
+	if (len > size)
+		len = size;
+
+	retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+	kfree(buf);
+
+	return retval;
+}
+
+static ssize_t read_file_misc(struct file *file, char __user *user_buf,
+			      size_t count, loff_t *ppos)
+{
+	struct ath_softc *sc = file->private_data;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	struct ath_hw *ah = sc->sc_ah;
+	struct ieee80211_hw *hw = sc->hw;
+	char *buf;
+	unsigned int len = 0, size = 8000;
+	ssize_t retval = 0;
+	const char *tmp;
+	unsigned int reg;
+	struct ath9k_vif_iter_data iter_data;
+
+	ath9k_calculate_iter_data(hw, NULL, &iter_data);
+	
+	buf = kzalloc(size, GFP_KERNEL);
+	if (buf == NULL)
+		return -ENOMEM;
+
+	switch (sc->sc_ah->opmode) {
+	case  NL80211_IFTYPE_ADHOC:
+		tmp = "ADHOC";
+		break;
+	case  NL80211_IFTYPE_MESH_POINT:
+		tmp = "MESH";
+		break;
+	case  NL80211_IFTYPE_AP:
+		tmp = "AP";
+		break;
+	case  NL80211_IFTYPE_STATION:
+		tmp = "STATION";
+		break;
+	default:
+		tmp = "???";
+		break;
+	}
+
+	len += snprintf(buf + len, size - len,
+			"curbssid: %pM\n"
+			"OP-Mode: %s(%i)\n"
+			"Beacon-Timer-Register: 0x%x\n",
+			common->curbssid,
+			tmp, (int)(sc->sc_ah->opmode),
+			REG_READ(ah, AR_BEACON_PERIOD));
+
+	reg = REG_READ(ah, AR_TIMER_MODE);
+	len += snprintf(buf + len, size - len, "Timer-Mode-Register: 0x%x (",
+			reg);
+	if (reg & AR_TBTT_TIMER_EN)
+		len += snprintf(buf + len, size - len, "TBTT ");
+	if (reg & AR_DBA_TIMER_EN)
+		len += snprintf(buf + len, size - len, "DBA ");
+	if (reg & AR_SWBA_TIMER_EN)
+		len += snprintf(buf + len, size - len, "SWBA ");
+	if (reg & AR_HCF_TIMER_EN)
+		len += snprintf(buf + len, size - len, "HCF ");
+	if (reg & AR_TIM_TIMER_EN)
+		len += snprintf(buf + len, size - len, "TIM ");
+	if (reg & AR_DTIM_TIMER_EN)
+		len += snprintf(buf + len, size - len, "DTIM ");
+	len += snprintf(buf + len, size - len, ")\n");
+
+	reg = sc->sc_ah->imask;
+	len += snprintf(buf + len, size - len, "imask: 0x%x (", reg);
+	if (reg & ATH9K_INT_SWBA)
+		len += snprintf(buf + len, size - len, "SWBA ");
+	if (reg & ATH9K_INT_BMISS)
+		len += snprintf(buf + len, size - len, "BMISS ");
+	if (reg & ATH9K_INT_CST)
+		len += snprintf(buf + len, size - len, "CST ");
+	if (reg & ATH9K_INT_RX)
+		len += snprintf(buf + len, size - len, "RX ");
+	if (reg & ATH9K_INT_RXHP)
+		len += snprintf(buf + len, size - len, "RXHP ");
+	if (reg & ATH9K_INT_RXLP)
+		len += snprintf(buf + len, size - len, "RXLP ");
+	if (reg & ATH9K_INT_BB_WATCHDOG)
+		len += snprintf(buf + len, size - len, "BB_WATCHDOG ");
+	/* there are other IRQs if one wanted to add them. */
+	len += snprintf(buf + len, size - len, ")\n");
+
+	len += snprintf(buf + len, size - len,
+			"VIF Counts: AP: %i STA: %i MESH: %i WDS: %i"
+			" ADHOC: %i OTHER: %i nvifs: %hi beacon-vifs: %hi\n",
+			iter_data.naps, iter_data.nstations, iter_data.nmeshes,
+			iter_data.nwds, iter_data.nadhocs, iter_data.nothers,
+			sc->nvifs, sc->nbcnvifs);
+
+	len += snprintf(buf + len, size - len,
+			"Calculated-BSSID-Mask: %pM\n",
+			iter_data.mask);
 
 	if (len > size)
 		len = size;
@@ -629,9 +785,9 @@
 }
 
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-		       struct ath_tx_status *ts)
+		       struct ath_tx_status *ts, struct ath_txq *txq)
 {
-	int qnum = skb_get_queue_mapping(bf->bf_mpdu);
+	int qnum = txq->axq_qnum;
 
 	TX_STAT_INC(qnum, tx_pkts_all);
 	sc->debug.stats.txstats[qnum].tx_bytes_all += bf->bf_mpdu->len;
@@ -666,6 +822,20 @@
 	.llseek = default_llseek,
 };
 
+static const struct file_operations fops_stations = {
+	.read = read_file_stations,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
+static const struct file_operations fops_misc = {
+	.read = read_file_misc,
+	.open = ath9k_debugfs_open,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,
+};
+
 static ssize_t read_file_recv(struct file *file, char __user *user_buf,
 			      size_t count, loff_t *ppos)
 {
@@ -871,6 +1041,42 @@
 	.llseek = default_llseek,
 };
 
+#define REGDUMP_LINE_SIZE	20
+
+static int open_file_regdump(struct inode *inode, struct file *file)
+{
+	struct ath_softc *sc = inode->i_private;
+	unsigned int len = 0;
+	u8 *buf;
+	int i;
+	unsigned long num_regs, regdump_len, max_reg_offset;
+
+	max_reg_offset = AR_SREV_9300_20_OR_LATER(sc->sc_ah) ? 0x16bd4 : 0xb500;
+	num_regs = max_reg_offset / 4 + 1;
+	regdump_len = num_regs * REGDUMP_LINE_SIZE + 1;
+	buf = vmalloc(regdump_len);
+	if (!buf)
+		return -ENOMEM;
+
+	ath9k_ps_wakeup(sc);
+	for (i = 0; i < num_regs; i++)
+		len += scnprintf(buf + len, regdump_len - len,
+			"0x%06x 0x%08x\n", i << 2, REG_READ(sc->sc_ah, i << 2));
+	ath9k_ps_restore(sc);
+
+	file->private_data = buf;
+
+	return 0;
+}
+
+static const struct file_operations fops_regdump = {
+	.open = open_file_regdump,
+	.read = ath9k_debugfs_read_buf,
+	.release = ath9k_debugfs_release_buf,
+	.owner = THIS_MODULE,
+	.llseek = default_llseek,/* read accesses f_pos */
+};
+
 int ath9k_init_debug(struct ath_hw *ah)
 {
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -903,6 +1109,14 @@
 			sc, &fops_xmit))
 		goto err;
 
+	if (!debugfs_create_file("stations", S_IRUSR, sc->debug.debugfs_phy,
+			sc, &fops_stations))
+		goto err;
+
+	if (!debugfs_create_file("misc", S_IRUSR, sc->debug.debugfs_phy,
+			sc, &fops_misc))
+		goto err;
+
 	if (!debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy,
 			sc, &fops_recv))
 		goto err;
@@ -927,6 +1141,10 @@
 			sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
 		goto err;
 
+	if (!debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy,
+			sc, &fops_regdump))
+		goto err;
+
 	sc->debug.regidx = 0;
 	return 0;
 err:
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/debug.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/debug.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/debug.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -89,7 +89,8 @@
  * @queued: Total MPDUs (non-aggr) queued
  * @completed: Total MPDUs (non-aggr) completed
  * @a_aggr: Total no. of aggregates queued
- * @a_queued: Total AMPDUs queued
+ * @a_queued_hw: Total AMPDUs queued to hardware
+ * @a_queued_sw: Total AMPDUs queued to software queues
  * @a_completed: Total AMPDUs completed
  * @a_retries: No. of AMPDUs retried (SW)
  * @a_xretries: No. of AMPDUs dropped due to xretries
@@ -102,6 +103,9 @@
  * @desc_cfg_err: Descriptor configuration errors
  * @data_urn: TX data underrun errors
  * @delim_urn: TX delimiter underrun errors
+ * @puttxbuf: Number of times hardware was given txbuf to write.
+ * @txstart:  Number of times hardware was told to start tx.
+ * @txprocdesc:  Number of times tx descriptor was processed
  */
 struct ath_tx_stats {
 	u32 tx_pkts_all;
@@ -109,7 +113,8 @@
 	u32 queued;
 	u32 completed;
 	u32 a_aggr;
-	u32 a_queued;
+	u32 a_queued_hw;
+	u32 a_queued_sw;
 	u32 a_completed;
 	u32 a_retries;
 	u32 a_xretries;
@@ -119,6 +124,9 @@
 	u32 desc_cfg_err;
 	u32 data_underrun;
 	u32 delim_underrun;
+	u32 puttxbuf;
+	u32 txstart;
+	u32 txprocdesc;
 };
 
 /**
@@ -167,7 +175,7 @@
 
 void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
 void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf,
-		       struct ath_tx_status *ts);
+		       struct ath_tx_status *ts, struct ath_txq *txq);
 void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs);
 
 #else
@@ -184,7 +192,8 @@
 
 static inline void ath_debug_stat_tx(struct ath_softc *sc,
 				     struct ath_buf *bf,
-				     struct ath_tx_status *ts)
+				     struct ath_tx_status *ts,
+				     struct ath_txq *txq)
 {
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom_4k.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom_4k.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom_4k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom_4k.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,19 +27,13 @@
 	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))
+
+static bool __ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
-	int addr, eep_start_loc = 0;
-
-	eep_start_loc = 64;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		ath_dbg(common, ATH_DBG_EEPROM,
-			"Reading from EEPROM, not flash\n");
-	}
+	int addr, eep_start_loc = 64;
 
 	for (addr = 0; addr < SIZE_EEPROM_4K; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + eep_start_loc, eep_data)) {
@@ -51,9 +45,34 @@
 	}
 
 	return true;
-#undef SIZE_EEPROM_4K
 }
 
+static bool __ath9k_hw_usb_4k_fill_eeprom(struct ath_hw *ah)
+{
+	u16 *eep_data = (u16 *)&ah->eeprom.map4k;
+
+	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data, 64, SIZE_EEPROM_4K);
+
+	return true;
+}
+
+static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	if (common->bus_ops->ath_bus_type == ATH_USB)
+		return __ath9k_hw_usb_4k_fill_eeprom(ah);
+	else
+		return __ath9k_hw_4k_fill_eeprom(ah);
+}
+
+#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))
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom_9287.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom_9287.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom_9287.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom_9287.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,7 @@
 #include "hw.h"
 #include "ar9002_phy.h"
 
-#define NUM_EEP_WORDS (sizeof(struct ar9287_eeprom) / sizeof(u16))
+#define SIZE_EEPROM_AR9287 (sizeof(struct ar9287_eeprom) / sizeof(u16))
 
 static int ath9k_hw_ar9287_get_eeprom_ver(struct ath_hw *ah)
 {
@@ -29,25 +29,15 @@
 	return (ah->eeprom.map9287.baseEepHeader.version) & 0xFFF;
 }
 
-static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+static bool __ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
 {
 	struct ar9287_eeprom *eep = &ah->eeprom.map9287;
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 *eep_data;
-	int addr, eep_start_loc;
+	int addr, eep_start_loc = AR9287_EEP_START_LOC;
 	eep_data = (u16 *)eep;
 
-	if (common->bus_ops->ath_bus_type == ATH_USB)
-		eep_start_loc = AR9287_HTC_EEP_START_LOC;
-	else
-		eep_start_loc = AR9287_EEP_START_LOC;
-
-	if (!ath9k_hw_use_flash(ah)) {
-		ath_dbg(common, ATH_DBG_EEPROM,
-			"Reading from EEPROM, not flash\n");
-	}
-
-	for (addr = 0; addr < NUM_EEP_WORDS; addr++) {
+	for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
 		if (!ath9k_hw_nvram_read(common, addr + eep_start_loc,
 					 eep_data)) {
 			ath_dbg(common, ATH_DBG_EEPROM,
@@ -60,6 +50,31 @@
 	return true;
 }
 
+static bool __ath9k_hw_usb_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+	u16 *eep_data = (u16 *)&ah->eeprom.map9287;
+
+	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+				     AR9287_HTC_EEP_START_LOC,
+				     SIZE_EEPROM_AR9287);
+	return true;
+}
+
+static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	if (common->bus_ops->ath_bus_type == ATH_USB)
+		return __ath9k_hw_usb_ar9287_fill_eeprom(ah);
+	else
+		return __ath9k_hw_ar9287_fill_eeprom(ah);
+}
+
 static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
 {
 	u32 sum = 0, el, integer;
@@ -86,7 +101,7 @@
 				need_swap = true;
 				eepdata = (u16 *)(&ah->eeprom);
 
-				for (addr = 0; addr < NUM_EEP_WORDS; addr++) {
+				for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) {
 					temp = swab16(*eepdata);
 					*eepdata = temp;
 					eepdata++;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,6 +89,38 @@
 	return false;
 }
 
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+				  int eep_start_loc, int size)
+{
+	int i = 0, j, addr;
+	u32 addrdata[8];
+	u32 data[8];
+
+	for (addr = 0; addr < size; addr++) {
+		addrdata[i] = AR5416_EEPROM_OFFSET +
+			((addr + eep_start_loc) << AR5416_EEPROM_S);
+		i++;
+		if (i == 8) {
+			REG_READ_MULTI(ah, addrdata, data, i);
+
+			for (j = 0; j < i; j++) {
+				*eep_data = data[j];
+				eep_data++;
+			}
+			i = 0;
+		}
+	}
+
+	if (i != 0) {
+		REG_READ_MULTI(ah, addrdata, data, i);
+
+		for (j = 0; j < i; j++) {
+			*eep_data = data[j];
+			eep_data++;
+		}
+	}
+}
+
 bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data)
 {
 	return common->bus_ops->eeprom_read(common, off, data);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom_def.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom_def.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom_def.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom_def.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,9 +86,10 @@
 	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))
+
+static bool __ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
 	struct ath_common *common = ath9k_hw_common(ah);
 	u16 *eep_data = (u16 *)&ah->eeprom.def;
 	int addr, ar5416_eep_start_loc = 0x100;
@@ -103,9 +104,34 @@
 		eep_data++;
 	}
 	return true;
-#undef SIZE_EEPROM_DEF
 }
 
+static bool __ath9k_hw_usb_def_fill_eeprom(struct ath_hw *ah)
+{
+	u16 *eep_data = (u16 *)&ah->eeprom.def;
+
+	ath9k_hw_usb_gen_fill_eeprom(ah, eep_data,
+				     0x100, SIZE_EEPROM_DEF);
+	return true;
+}
+
+static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
+{
+	struct ath_common *common = ath9k_hw_common(ah);
+
+	if (!ath9k_hw_use_flash(ah)) {
+		ath_dbg(common, ATH_DBG_EEPROM,
+			"Reading from EEPROM, not flash\n");
+	}
+
+	if (common->bus_ops->ath_bus_type == ATH_USB)
+		return __ath9k_hw_usb_def_fill_eeprom(ah);
+	else
+		return __ath9k_hw_def_fill_eeprom(ah);
+}
+
+#undef SIZE_EEPROM_DEF
+
 static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
 {
 	struct ar5416_eeprom_def *eep =
@@ -221,9 +247,9 @@
 	}
 
 	/* Enable fixup for AR_AN_TOP2 if necessary */
-	if (AR_SREV_9280_20_OR_LATER(ah) &&
-	    (eep->baseEepHeader.version & 0xff) > 0x0a &&
-	    eep->baseEepHeader.pwdclkind == 0)
+	if ((ah->hw_version.devid == AR9280_DEVID_PCI) &&
+	    ((eep->baseEepHeader.version & 0xff) > 0x0a) &&
+	    (eep->baseEepHeader.pwdclkind == 0))
 		ah->need_an_top2_fixup = 1;
 
 	if ((common->bus_ops->ath_bus_type == ATH_USB) &&
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -665,6 +665,8 @@
 bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize,
 				    u16 *indexL, u16 *indexR);
 bool ath9k_hw_nvram_read(struct ath_common *common, u32 off, u16 *data);
+void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data,
+				  int eep_start_loc, int size);
 void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList,
 			     u8 *pVpdList, u16 numIntercepts,
 			     u8 *pRetVpdList);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/gpio.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/gpio.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,121 +20,31 @@
 /*	 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, sc->sc_ah->led_pin, 0);
-	else
-		ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
-				  (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
-
-	ieee80211_queue_delayed_work(sc->hw,
-				     &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;
-}
-
+#ifdef CONFIG_MAC80211_LEDS
 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, sc->sc_ah->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;
-			if (led_blink)
-				ieee80211_queue_delayed_work(sc->hw,
-						     &sc->ath_led_blink_work, 0);
-		} else if (led->led_type == ATH_LED_RADIO) {
-			ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->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)
-		ath_err(ath9k_hw_common(sc->sc_ah),
-			"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;
-	}
+	struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
+	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
 }
 
 void ath_deinit_leds(struct ath_softc *sc)
 {
-	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, sc->sc_ah->led_pin, 1);
+	if (!sc->led_registered)
+		return;
+
+	ath_led_brightness(&sc->led_cdev, LED_OFF);
+	led_classdev_unregister(&sc->led_cdev);
 }
 
 void ath_init_leds(struct ath_softc *sc)
 {
-	char *trigger;
 	int ret;
 
 	if (AR_SREV_9287(sc->sc_ah))
 		sc->sc_ah->led_pin = ATH_LED_PIN_9287;
+	else if (AR_SREV_9485(sc->sc_ah))
+		sc->sc_ah->led_pin = ATH_LED_PIN_9485;
 	else
 		sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
 
@@ -144,48 +54,22 @@
 	/* LED off, active low */
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
-	if (led_blink)
-		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;
+	if (!led_blink)
+		sc->led_cdev.default_trigger =
+			ieee80211_get_radio_led_name(sc->hw);
 
-	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;
+	snprintf(sc->led_name, sizeof(sc->led_name),
+		"ath9k-%s", wiphy_name(sc->hw->wiphy));
+	sc->led_cdev.name = sc->led_name;
+	sc->led_cdev.brightness_set = ath_led_brightness;
 
-	return;
+	ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
+	if (ret < 0)
+		return;
 
-fail:
-	if (led_blink)
-		cancel_delayed_work_sync(&sc->ath_led_blink_work);
-	ath_deinit_leds(sc);
+	sc->led_registered = true;
 }
+#endif
 
 /*******************/
 /*	Rfkill	   */
@@ -201,8 +85,7 @@
 
 void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	bool blocked = !!ath_is_rfkill_set(sc);
 
 	wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hif_usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/hif_usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hif_usb.c	2012-03-24 01:13:28.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/hif_usb.c	2012-03-24 03:33:53.000000000 -0400
@@ -50,6 +50,9 @@
 	{ USB_DEVICE(0x083A, 0xA704),
 	  .driver_info = AR9280_USB },  /* SMC Networks */
 
+	{ USB_DEVICE(0x0cf3, 0x20ff),
+	  .driver_info = STORAGE_DEVICE },
+
 	{ },
 };
 
@@ -912,13 +915,11 @@
 	if (ret) {
 		dev_err(&hif_dev->udev->dev,
 			"ath9k_htc: Unable to allocate URBs\n");
-		goto err_urb;
+		goto err_fw_download;
 	}
 
 	return 0;
 
-err_urb:
-	ath9k_hif_usb_dealloc_urbs(hif_dev);
 err_fw_download:
 	release_firmware(hif_dev->firmware);
 err_fw_req:
@@ -933,6 +934,61 @@
 		release_firmware(hif_dev->firmware);
 }
 
+/*
+ * An exact copy of the function from zd1211rw.
+ */
+static int send_eject_command(struct usb_interface *interface)
+{
+	struct usb_device *udev = interface_to_usbdev(interface);
+	struct usb_host_interface *iface_desc = &interface->altsetting[0];
+	struct usb_endpoint_descriptor *endpoint;
+	unsigned char *cmd;
+	u8 bulk_out_ep;
+	int r;
+
+	/* Find bulk out endpoint */
+	for (r = 1; r >= 0; r--) {
+		endpoint = &iface_desc->endpoint[r].desc;
+		if (usb_endpoint_dir_out(endpoint) &&
+		    usb_endpoint_xfer_bulk(endpoint)) {
+			bulk_out_ep = endpoint->bEndpointAddress;
+			break;
+		}
+	}
+	if (r == -1) {
+		dev_err(&udev->dev,
+			"ath9k_htc: Could not find bulk out endpoint\n");
+		return -ENODEV;
+	}
+
+	cmd = kzalloc(31, GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENODEV;
+
+	/* USB bulk command block */
+	cmd[0] = 0x55;	/* bulk command signature */
+	cmd[1] = 0x53;	/* bulk command signature */
+	cmd[2] = 0x42;	/* bulk command signature */
+	cmd[3] = 0x43;	/* bulk command signature */
+	cmd[14] = 6;	/* command length */
+
+	cmd[15] = 0x1b;	/* SCSI command: START STOP UNIT */
+	cmd[19] = 0x2;	/* eject disc */
+
+	dev_info(&udev->dev, "Ejecting storage device...\n");
+	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, bulk_out_ep),
+		cmd, 31, NULL, 2000);
+	kfree(cmd);
+	if (r)
+		return r;
+
+	/* At this point, the device disconnects and reconnects with the real
+	 * ID numbers. */
+
+	usb_set_intfdata(interface, NULL);
+	return 0;
+}
+
 static int ath9k_hif_usb_probe(struct usb_interface *interface,
 			       const struct usb_device_id *id)
 {
@@ -940,6 +996,9 @@
 	struct hif_device_usb *hif_dev;
 	int ret = 0;
 
+	if (id->driver_info == STORAGE_DEVICE)
+		return send_eject_command(interface);
+
 	hif_dev = kzalloc(sizeof(struct hif_device_usb), GFP_KERNEL);
 	if (!hif_dev) {
 		ret = -ENOMEM;
@@ -979,7 +1038,7 @@
 	}
 
 	ret = ath9k_htc_hw_init(hif_dev->htc_handle,
-				&hif_dev->udev->dev, hif_dev->device_id,
+				&interface->dev, hif_dev->device_id,
 				hif_dev->udev->product, id->driver_info);
 	if (ret) {
 		ret = -EINVAL;
@@ -1026,12 +1085,13 @@
 	struct hif_device_usb *hif_dev = usb_get_intfdata(interface);
 	bool unplugged = (udev->state == USB_STATE_NOTATTACHED) ? true : false;
 
-	if (hif_dev) {
-		ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
-		ath9k_htc_hw_free(hif_dev->htc_handle);
-		ath9k_hif_usb_dev_deinit(hif_dev);
-		usb_set_intfdata(interface, NULL);
-	}
+	if (!hif_dev)
+		return;
+
+	ath9k_htc_hw_deinit(hif_dev->htc_handle, unplugged);
+	ath9k_htc_hw_free(hif_dev->htc_handle);
+	ath9k_hif_usb_dev_deinit(hif_dev);
+	usb_set_intfdata(interface, NULL);
 
 	if (!unplugged && (hif_dev->flags & HIF_USB_START))
 		ath9k_hif_usb_reboot(udev);
@@ -1096,7 +1156,7 @@
 #endif
 
 static struct usb_driver ath9k_hif_usb_driver = {
-	.name = "ath9k_hif_usb",
+	.name = KBUILD_MODNAME,
 	.probe = ath9k_hif_usb_probe,
 	.disconnect = ath9k_hif_usb_disconnect,
 #ifdef CONFIG_PM
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_beacon.c	2011-05-19 00:06:34.000000000 -0400
@@ -123,8 +123,9 @@
 	/* TSF out of range threshold fixed at 1 second */
 	bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-	ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-	ath_dbg(common, ATH_DBG_BEACON,
+	ath_dbg(common, ATH_DBG_CONFIG, "intval: %u tsf: %llu tsftu: %u\n",
+		intval, tsf, tsftu);
+	ath_dbg(common, ATH_DBG_CONFIG,
 		"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);
@@ -138,25 +139,81 @@
 	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
 }
 
+static void ath9k_htc_beacon_config_ap(struct ath9k_htc_priv *priv,
+				       struct htc_beacon_config *bss_conf)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	enum ath9k_int imask = 0;
+	u32 nexttbtt, intval, tsftu;
+	__be32 htc_imask = 0;
+	int ret;
+	u8 cmd_rsp;
+	u64 tsf;
+
+	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
+	intval /= ATH9K_HTC_MAX_BCN_VIF;
+	nexttbtt = intval;
+
+	if (priv->op_flags & OP_TSF_RESET) {
+		intval |= ATH9K_BEACON_RESET_TSF;
+		priv->op_flags &= ~OP_TSF_RESET;
+	} else {
+		/*
+		 * Pull nexttbtt forward to reflect the current TSF.
+		 */
+		tsf = ath9k_hw_gettsf64(priv->ah);
+		tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
+		do {
+			nexttbtt += intval;
+		} while (nexttbtt < tsftu);
+	}
+
+	intval |= ATH9K_BEACON_ENA;
+
+	if (priv->op_flags & OP_ENABLE_BEACON)
+		imask |= ATH9K_INT_SWBA;
+
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"AP Beacon config, intval: %d, nexttbtt: %u imask: 0x%x\n",
+		bss_conf->beacon_interval, nexttbtt, imask);
+
+	WMI_CMD(WMI_DISABLE_INTR_CMDID);
+	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
+	priv->bmiss_cnt = 0;
+	htc_imask = cpu_to_be32(imask);
+	WMI_CMD_BUF(WMI_ENABLE_INTR_CMDID, &htc_imask);
+}
+
 static void ath9k_htc_beacon_config_adhoc(struct ath9k_htc_priv *priv,
 					  struct htc_beacon_config *bss_conf)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	enum ath9k_int imask = 0;
-	u32 nexttbtt, intval;
+	u32 nexttbtt, intval, tsftu;
 	__be32 htc_imask = 0;
 	int ret;
 	u8 cmd_rsp;
+	u64 tsf;
 
 	intval = bss_conf->beacon_interval & ATH9K_BEACON_PERIOD;
 	nexttbtt = intval;
+
+	/*
+	 * Pull nexttbtt forward to reflect the current TSF.
+	 */
+	tsf = ath9k_hw_gettsf64(priv->ah);
+	tsftu = TSF_TO_TU(tsf >> 32, tsf) + FUDGE;
+	do {
+		nexttbtt += intval;
+	} while (nexttbtt < tsftu);
+
 	intval |= ATH9K_BEACON_ENA;
 	if (priv->op_flags & OP_ENABLE_BEACON)
 		imask |= ATH9K_INT_SWBA;
 
-	ath_dbg(common, ATH_DBG_BEACON,
-		"IBSS Beacon config, intval: %d, imask: 0x%x\n",
-		bss_conf->beacon_interval, imask);
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"IBSS Beacon config, intval: %d, nexttbtt: %u, imask: 0x%x\n",
+		bss_conf->beacon_interval, nexttbtt, imask);
 
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	ath9k_hw_beaconinit(priv->ah, nexttbtt, intval);
@@ -207,9 +264,9 @@
 	if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 		struct ieee80211_hdr *hdr =
 			(struct ieee80211_hdr *) beacon->data;
-		priv->seq_no += 0x10;
+		avp->seq_no += 0x10;
 		hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
-		hdr->seq_ctrl |= cpu_to_le16(priv->seq_no);
+		hdr->seq_ctrl |= cpu_to_le16(avp->seq_no);
 	}
 
 	tx_ctl.type = ATH9K_HTC_NORMAL;
@@ -253,30 +310,123 @@
 	}
 }
 
+static void ath9k_htc_beacon_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	bool *beacon_configured = (bool *)data;
+	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
+
+	if (vif->type == NL80211_IFTYPE_STATION &&
+	    avp->beacon_configured)
+		*beacon_configured = true;
+}
+
+static bool ath9k_htc_check_beacon_config(struct ath9k_htc_priv *priv,
+					  struct ieee80211_vif *vif)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	bool beacon_configured;
+
+	/*
+	 * Changing the beacon interval when multiple AP interfaces
+	 * are configured will affect beacon transmission of all
+	 * of them.
+	 */
+	if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+	    (priv->num_ap_vif > 1) &&
+	    (vif->type == NL80211_IFTYPE_AP) &&
+	    (cur_conf->beacon_interval != bss_conf->beacon_int)) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Changing beacon interval of multiple AP interfaces !\n");
+		return false;
+	}
+
+	/*
+	 * If the HW is operating in AP mode, any new station interfaces that
+	 * are added cannot change the beacon parameters.
+	 */
+	if (priv->num_ap_vif &&
+	    (vif->type != NL80211_IFTYPE_AP)) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"HW in AP mode, cannot set STA beacon parameters\n");
+		return false;
+	}
+
+	/*
+	 * The beacon parameters are configured only for the first
+	 * station interface.
+	 */
+	if ((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
+	    (priv->num_sta_vif > 1) &&
+	    (vif->type == NL80211_IFTYPE_STATION)) {
+		beacon_configured = false;
+		ieee80211_iterate_active_interfaces_atomic(priv->hw,
+							   ath9k_htc_beacon_iter,
+							   &beacon_configured);
+
+		if (beacon_configured) {
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Beacon already configured for a station interface\n");
+			return false;
+		}
+	}
+
+	return true;
+}
+
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
 	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
+
+	if (!ath9k_htc_check_beacon_config(priv, vif))
+		return;
 
 	cur_conf->beacon_interval = bss_conf->beacon_int;
 	if (cur_conf->beacon_interval == 0)
 		cur_conf->beacon_interval = 100;
 
 	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;
 
 	switch (vif->type) {
 	case NL80211_IFTYPE_STATION:
 		ath9k_htc_beacon_config_sta(priv, cur_conf);
+		avp->beacon_configured = true;
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ath9k_htc_beacon_config_adhoc(priv, cur_conf);
+		break;
+	case NL80211_IFTYPE_AP:
+		ath9k_htc_beacon_config_ap(priv, cur_conf);
+		break;
+	default:
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Unsupported beaconing mode\n");
+		return;
+	}
+}
+
+void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct htc_beacon_config *cur_conf = &priv->cur_beacon_conf;
+
+	switch (priv->ah->opmode) {
+	case NL80211_IFTYPE_STATION:
+		ath9k_htc_beacon_config_sta(priv, cur_conf);
 		break;
 	case NL80211_IFTYPE_ADHOC:
 		ath9k_htc_beacon_config_adhoc(priv, cur_conf);
 		break;
+	case NL80211_IFTYPE_AP:
+		ath9k_htc_beacon_config_ap(priv, cur_conf);
+		break;
 	default:
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Unsupported beaconing mode\n");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -389,7 +389,8 @@
 			ret, ah->curchan->channel);
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	/* Start RX */
 	WMI_CMD(WMI_START_RECV_CMDID);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_init.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_init.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -294,6 +294,34 @@
 	return be32_to_cpu(val);
 }
 
+static void ath9k_multi_regread(void *hw_priv, u32 *addr,
+				u32 *val, u16 count)
+{
+	struct ath_hw *ah = (struct ath_hw *) hw_priv;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *) common->priv;
+	__be32 tmpaddr[8];
+	__be32 tmpval[8];
+	int i, ret;
+
+       for (i = 0; i < count; i++) {
+	       tmpaddr[i] = cpu_to_be32(addr[i]);
+       }
+
+       ret = ath9k_wmi_cmd(priv->wmi, WMI_REG_READ_CMDID,
+			   (u8 *)tmpaddr , sizeof(u32) * count,
+			   (u8 *)tmpval, sizeof(u32) * count,
+			   100);
+	if (unlikely(ret)) {
+		ath_dbg(common, ATH_DBG_WMI,
+			"Multiple REGISTER READ FAILED (count: %d)\n", count);
+	}
+
+       for (i = 0; i < count; i++) {
+	       val[i] = be32_to_cpu(tmpval[i]);
+       }
+}
+
 static void ath9k_regwrite_single(void *hw_priv, u32 val, u32 reg_offset)
 {
 	struct ath_hw *ah = (struct ath_hw *) hw_priv;
@@ -404,6 +432,7 @@
 
 static const struct ath_ops ath9k_common_ops = {
 	.read = ath9k_regread,
+	.multi_read = ath9k_multi_regread,
 	.write = ath9k_regwrite,
 	.enable_write_buffer = ath9k_enable_regwrite_buffer,
 	.write_flush = ath9k_regwrite_flush,
@@ -650,7 +679,7 @@
 		     (unsigned long)priv);
 	tasklet_init(&priv->tx_tasklet, ath9k_tx_tasklet,
 		     (unsigned long)priv);
-	INIT_DELAYED_WORK(&priv->ath9k_ani_work, ath9k_ani_work);
+	INIT_DELAYED_WORK(&priv->ani_work, ath9k_htc_ani_work);
 	INIT_WORK(&priv->ps_work, ath9k_ps_work);
 	INIT_WORK(&priv->fatal_work, ath9k_fatal_work);
 
@@ -758,6 +787,7 @@
 	struct ath_hw *ah;
 	int error = 0;
 	struct ath_regulatory *reg;
+	char hw_name[64];
 
 	/* Bring up device */
 	error = ath9k_init_priv(priv, devid, product, drv_info);
@@ -798,6 +828,22 @@
 			goto err_world;
 	}
 
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"WMI:%d, BCN:%d, CAB:%d, UAPSD:%d, MGMT:%d, "
+		"BE:%d, BK:%d, VI:%d, VO:%d\n",
+		priv->wmi_cmd_ep,
+		priv->beacon_ep,
+		priv->cab_ep,
+		priv->uapsd_ep,
+		priv->mgmt_ep,
+		priv->data_be_ep,
+		priv->data_bk_ep,
+		priv->data_vi_ep,
+		priv->data_vo_ep);
+
+	ath9k_hw_name(priv->ah, hw_name, sizeof(hw_name));
+	wiphy_info(hw->wiphy, "%s\n", hw_name);
+
 	ath9k_init_leds(priv);
 	ath9k_start_rfkill_poll(priv);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,17 +24,6 @@
 /* Utilities */
 /*************/
 
-void ath_update_txpow(struct ath9k_htc_priv *priv)
-{
-	struct ath_hw *ah = priv->ah;
-
-	if (priv->curtxpow != priv->txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, priv->txpowlimit, false);
-		/* read back in case value is clamped */
-		priv->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
-	}
-}
-
 /* HACK Alert: Use 11NG for 2.4, use 11NA for 5 */
 static enum htc_phymode ath9k_htc_get_curmode(struct ath9k_htc_priv *priv,
 					      struct ath9k_channel *ichan)
@@ -116,12 +105,88 @@
 	ath9k_htc_setpower(priv, ATH9K_PM_NETWORK_SLEEP);
 }
 
+static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_htc_priv *priv = data;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+
+	if ((vif->type == NL80211_IFTYPE_AP) && bss_conf->enable_beacon)
+		priv->reconfig_beacon = true;
+
+	if (bss_conf->assoc) {
+		priv->rearm_ani = true;
+		priv->reconfig_beacon = true;
+	}
+}
+
+static void ath9k_htc_vif_reconfig(struct ath9k_htc_priv *priv)
+{
+	priv->rearm_ani = false;
+	priv->reconfig_beacon = false;
+
+	ieee80211_iterate_active_interfaces_atomic(priv->hw,
+						   ath9k_htc_vif_iter, priv);
+	if (priv->rearm_ani)
+		ath9k_htc_start_ani(priv);
+
+	if (priv->reconfig_beacon) {
+		ath9k_htc_ps_wakeup(priv);
+		ath9k_htc_beacon_reconfig(priv);
+		ath9k_htc_ps_restore(priv);
+	}
+}
+
+static void ath9k_htc_bssid_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_vif_iter_data *iter_data = data;
+	int i;
+
+	for (i = 0; i < ETH_ALEN; i++)
+		iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
+}
+
+static void ath9k_htc_set_bssid_mask(struct ath9k_htc_priv *priv,
+				     struct ieee80211_vif *vif)
+{
+	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath9k_vif_iter_data iter_data;
+
+	/*
+	 * Use the hardware MAC address as reference, the hardware uses it
+	 * together with the BSSID mask when matching addresses.
+	 */
+	iter_data.hw_macaddr = common->macaddr;
+	memset(&iter_data.mask, 0xff, ETH_ALEN);
+
+	if (vif)
+		ath9k_htc_bssid_iter(&iter_data, vif->addr, vif);
+
+	/* Get list of all active MAC addresses */
+	ieee80211_iterate_active_interfaces_atomic(priv->hw, ath9k_htc_bssid_iter,
+						   &iter_data);
+
+	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+	ath_hw_setbssidmask(common);
+}
+
+static void ath9k_htc_set_opmode(struct ath9k_htc_priv *priv)
+{
+	if (priv->num_ibss_vif)
+		priv->ah->opmode = NL80211_IFTYPE_ADHOC;
+	else if (priv->num_ap_vif)
+		priv->ah->opmode = NL80211_IFTYPE_AP;
+	else
+		priv->ah->opmode = NL80211_IFTYPE_STATION;
+
+	ath9k_hw_setopmode(priv->ah);
+}
+
 void ath9k_htc_reset(struct ath9k_htc_priv *priv)
 {
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_channel *channel = priv->hw->conf.channel;
-	struct ath9k_hw_cal_data *caldata;
+	struct ath9k_hw_cal_data *caldata = NULL;
 	enum htc_phymode mode;
 	__be16 htc_mode;
 	u8 cmd_rsp;
@@ -130,16 +195,14 @@
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
 
-	if (priv->op_flags & OP_ASSOCIATED)
-		cancel_delayed_work_sync(&priv->ath9k_ani_work);
-
+	ath9k_htc_stop_ani(priv);
 	ieee80211_stop_queues(priv->hw);
 	htc_stop(priv->htc);
 	WMI_CMD(WMI_DISABLE_INTR_CMDID);
 	WMI_CMD(WMI_DRAIN_TXQ_ALL_CMDID);
 	WMI_CMD(WMI_STOP_RECV_CMDID);
 
-	caldata = &priv->caldata[channel->hw_value];
+	caldata = &priv->caldata;
 	ret = ath9k_hw_reset(ah, ah->curchan, caldata, false);
 	if (ret) {
 		ath_err(common,
@@ -147,7 +210,8 @@
 			channel->center_freq, ret);
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	WMI_CMD(WMI_START_RECV_CMDID);
 	ath9k_host_rx_init(priv);
@@ -158,12 +222,7 @@
 
 	WMI_CMD(WMI_ENABLE_INTR_CMDID);
 	htc_start(priv->htc);
-
-	if (priv->op_flags & OP_ASSOCIATED) {
-		ath9k_htc_beacon_config(priv, priv->vif);
-		ath_start_ani(priv);
-	}
-
+	ath9k_htc_vif_reconfig(priv);
 	ieee80211_wake_queues(priv->hw);
 
 	ath9k_htc_ps_restore(priv);
@@ -179,7 +238,7 @@
 	struct ieee80211_conf *conf = &common->hw->conf;
 	bool fastcc;
 	struct ieee80211_channel *channel = hw->conf.channel;
-	struct ath9k_hw_cal_data *caldata;
+	struct ath9k_hw_cal_data *caldata = NULL;
 	enum htc_phymode mode;
 	__be16 htc_mode;
 	u8 cmd_rsp;
@@ -202,7 +261,8 @@
 		channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf),
 		fastcc);
 
-	caldata = &priv->caldata[channel->hw_value];
+	if (!fastcc)
+		caldata = &priv->caldata;
 	ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
 	if (ret) {
 		ath_err(common,
@@ -211,7 +271,8 @@
 		goto err;
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	WMI_CMD(WMI_START_RECV_CMDID);
 	if (ret)
@@ -230,11 +291,23 @@
 		goto err;
 
 	htc_start(priv->htc);
+
+	if (!(priv->op_flags & OP_SCANNING) &&
+	    !(hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
+		ath9k_htc_vif_reconfig(priv);
+
 err:
 	ath9k_htc_ps_restore(priv);
 	return ret;
 }
 
+/*
+ * Monitor mode handling is a tad complicated because the firmware requires
+ * an interface to be created exclusively, while mac80211 doesn't associate
+ * an interface with the mode.
+ *
+ * So, for now, only one monitor interface can be configured.
+ */
 static void __ath9k_htc_remove_monitor_interface(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
@@ -244,9 +317,10 @@
 
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
-	hvif.index = 0; /* Should do for now */
+	hvif.index = priv->mon_vif_idx;
 	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
 	priv->nvifs--;
+	priv->vif_slot &= ~(1 << priv->mon_vif_idx);
 }
 
 static int ath9k_htc_add_monitor_interface(struct ath9k_htc_priv *priv)
@@ -254,70 +328,87 @@
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	struct ath9k_htc_target_vif hvif;
 	struct ath9k_htc_target_sta tsta;
-	int ret = 0;
+	int ret = 0, sta_idx;
 	u8 cmd_rsp;
 
-	if (priv->nvifs > 0)
-		return -ENOBUFS;
+	if ((priv->nvifs >= ATH9K_HTC_MAX_VIF) ||
+	    (priv->nstations >= ATH9K_HTC_MAX_STA)) {
+		ret = -ENOBUFS;
+		goto err_vif;
+	}
 
-	if (priv->nstations >= ATH9K_HTC_MAX_STA)
-		return -ENOBUFS;
+	sta_idx = ffz(priv->sta_slot);
+	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA)) {
+		ret = -ENOBUFS;
+		goto err_vif;
+	}
 
 	/*
 	 * Add an interface.
 	 */
-
 	memset(&hvif, 0, sizeof(struct ath9k_htc_target_vif));
 	memcpy(&hvif.myaddr, common->macaddr, ETH_ALEN);
 
 	hvif.opmode = cpu_to_be32(HTC_M_MONITOR);
-	priv->ah->opmode = NL80211_IFTYPE_MONITOR;
-	hvif.index = priv->nvifs;
+	hvif.index = ffz(priv->vif_slot);
 
 	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
 	if (ret)
-		return ret;
+		goto err_vif;
+
+	/*
+	 * Assign the monitor interface index as a special case here.
+	 * This is needed when the interface is brought down.
+	 */
+	priv->mon_vif_idx = hvif.index;
+	priv->vif_slot |= (1 << hvif.index);
+
+	/*
+	 * Set the hardware mode to monitor only if there are no
+	 * other interfaces.
+	 */
+	if (!priv->nvifs)
+		priv->ah->opmode = NL80211_IFTYPE_MONITOR;
 
 	priv->nvifs++;
 
 	/*
 	 * Associate a station with the interface for packet injection.
 	 */
-
 	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
 
 	memcpy(&tsta.macaddr, common->macaddr, ETH_ALEN);
 
 	tsta.is_vif_sta = 1;
-	tsta.sta_index = priv->nstations;
+	tsta.sta_index = sta_idx;
 	tsta.vif_index = hvif.index;
 	tsta.maxampdu = 0xffff;
 
 	WMI_CMD_BUF(WMI_NODE_CREATE_CMDID, &tsta);
 	if (ret) {
 		ath_err(common, "Unable to add station entry for monitor mode\n");
-		goto err_vif;
+		goto err_sta;
 	}
 
+	priv->sta_slot |= (1 << sta_idx);
 	priv->nstations++;
-
-	/*
-	 * Set chainmask etc. on the target.
-	 */
-	ret = ath9k_htc_update_cap_target(priv);
-	if (ret)
-		ath_dbg(common, ATH_DBG_CONFIG,
-			"Failed to update capability in target\n");
-
+	priv->vif_sta_pos[priv->mon_vif_idx] = sta_idx;
 	priv->ah->is_monitoring = true;
 
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attached a monitor interface at idx: %d, sta idx: %d\n",
+		priv->mon_vif_idx, sta_idx);
+
 	return 0;
 
-err_vif:
+err_sta:
 	/*
 	 * Remove the interface from the target.
 	 */
 	__ath9k_htc_remove_monitor_interface(priv);
+err_vif:
+	ath_dbg(common, ATH_DBG_FATAL, "Unable to attach a monitor interface\n");
+
 	return ret;
 }
 
@@ -329,7 +420,7 @@
 
 	__ath9k_htc_remove_monitor_interface(priv);
 
-	sta_idx = 0; /* Only single interface, for now */
+	sta_idx = priv->vif_sta_pos[priv->mon_vif_idx];
 
 	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
 	if (ret) {
@@ -337,9 +428,14 @@
 		return ret;
 	}
 
+	priv->sta_slot &= ~(1 << sta_idx);
 	priv->nstations--;
 	priv->ah->is_monitoring = false;
 
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Removed a monitor interface at idx: %d, sta idx: %d\n",
+		priv->mon_vif_idx, sta_idx);
+
 	return 0;
 }
 
@@ -351,12 +447,16 @@
 	struct ath9k_htc_target_sta tsta;
 	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
 	struct ath9k_htc_sta *ista;
-	int ret;
+	int ret, sta_idx;
 	u8 cmd_rsp;
 
 	if (priv->nstations >= ATH9K_HTC_MAX_STA)
 		return -ENOBUFS;
 
+	sta_idx = ffz(priv->sta_slot);
+	if ((sta_idx < 0) || (sta_idx > ATH9K_HTC_MAX_STA))
+		return -ENOBUFS;
+
 	memset(&tsta, 0, sizeof(struct ath9k_htc_target_sta));
 
 	if (sta) {
@@ -366,13 +466,13 @@
 		tsta.associd = common->curaid;
 		tsta.is_vif_sta = 0;
 		tsta.valid = true;
-		ista->index = priv->nstations;
+		ista->index = sta_idx;
 	} else {
 		memcpy(&tsta.macaddr, vif->addr, ETH_ALEN);
 		tsta.is_vif_sta = 1;
 	}
 
-	tsta.sta_index = priv->nstations;
+	tsta.sta_index = sta_idx;
 	tsta.vif_index = avp->index;
 	tsta.maxampdu = 0xffff;
 	if (sta && sta->ht_cap.ht_supported)
@@ -387,12 +487,21 @@
 		return ret;
 	}
 
-	if (sta)
+	if (sta) {
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Added a station entry for: %pM (idx: %d)\n",
 			sta->addr, tsta.sta_index);
+	} else {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Added a station entry for VIF %d (idx: %d)\n",
+			avp->index, tsta.sta_index);
+	}
 
+	priv->sta_slot |= (1 << sta_idx);
 	priv->nstations++;
+	if (!sta)
+		priv->vif_sta_pos[avp->index] = sta_idx;
+
 	return 0;
 }
 
@@ -401,6 +510,7 @@
 				    struct ieee80211_sta *sta)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
+	struct ath9k_htc_vif *avp = (struct ath9k_htc_vif *) vif->drv_priv;
 	struct ath9k_htc_sta *ista;
 	int ret;
 	u8 cmd_rsp, sta_idx;
@@ -409,7 +519,7 @@
 		ista = (struct ath9k_htc_sta *) sta->drv_priv;
 		sta_idx = ista->index;
 	} else {
-		sta_idx = 0;
+		sta_idx = priv->vif_sta_pos[avp->index];
 	}
 
 	WMI_CMD_BUF(WMI_NODE_REMOVE_CMDID, &sta_idx);
@@ -421,12 +531,19 @@
 		return ret;
 	}
 
-	if (sta)
+	if (sta) {
 		ath_dbg(common, ATH_DBG_CONFIG,
 			"Removed a station entry for: %pM (idx: %d)\n",
 			sta->addr, sta_idx);
+	} else {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Removed a station entry for VIF %d (idx: %d)\n",
+			avp->index, sta_idx);
+	}
 
+	priv->sta_slot &= ~(1 << sta_idx);
 	priv->nstations--;
+
 	return 0;
 }
 
@@ -808,7 +925,7 @@
 /* ANI */
 /*******/
 
-void ath_start_ani(struct ath9k_htc_priv *priv)
+void ath9k_htc_start_ani(struct ath9k_htc_priv *priv)
 {
 	struct ath_common *common = ath9k_hw_common(priv->ah);
 	unsigned long timestamp = jiffies_to_msecs(jiffies);
@@ -817,15 +934,22 @@
 	common->ani.shortcal_timer = timestamp;
 	common->ani.checkani_timer = timestamp;
 
-	ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work,
+	priv->op_flags |= OP_ANI_RUNNING;
+
+	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
 				     msecs_to_jiffies(ATH_ANI_POLLINTERVAL));
 }
 
-void ath9k_ani_work(struct work_struct *work)
+void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv)
+{
+	cancel_delayed_work_sync(&priv->ani_work);
+	priv->op_flags &= ~OP_ANI_RUNNING;
+}
+
+void ath9k_htc_ani_work(struct work_struct *work)
 {
 	struct ath9k_htc_priv *priv =
-		container_of(work, struct ath9k_htc_priv,
-			     ath9k_ani_work.work);
+		container_of(work, struct ath9k_htc_priv, ani_work.work);
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	bool longcal = false;
@@ -834,7 +958,8 @@
 	unsigned int timestamp = jiffies_to_msecs(jiffies);
 	u32 cal_interval, short_cal_interval;
 
-	short_cal_interval = ATH_STA_SHORT_CALINTERVAL;
+	short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
+		ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
 
 	/* Only calibrate if awake */
 	if (ah->power_mode != ATH9K_PM_AWAKE)
@@ -903,7 +1028,7 @@
 	if (!common->ani.caldone)
 		cal_interval = min(cal_interval, (u32)short_cal_interval);
 
-	ieee80211_queue_delayed_work(common->hw, &priv->ath9k_ani_work,
+	ieee80211_queue_delayed_work(common->hw, &priv->ani_work,
 				     msecs_to_jiffies(cal_interval));
 }
 
@@ -911,7 +1036,7 @@
 /* mac80211 Callbacks */
 /**********************/
 
-static int ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void ath9k_htc_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ieee80211_hdr *hdr;
 	struct ath9k_htc_priv *priv = hw->priv;
@@ -924,7 +1049,7 @@
 	padsize = padpos & 3;
 	if (padsize && skb->len > padpos) {
 		if (skb_headroom(skb) < padsize)
-			return -1;
+			goto fail_tx;
 		skb_push(skb, padsize);
 		memmove(skb->data, skb->data + padsize, padpos);
 	}
@@ -945,11 +1070,10 @@
 		goto fail_tx;
 	}
 
-	return 0;
+	return;
 
 fail_tx:
 	dev_kfree_skb_any(skb);
-	return 0;
 }
 
 static int ath9k_htc_start(struct ieee80211_hw *hw)
@@ -987,7 +1111,8 @@
 		return ret;
 	}
 
-	ath_update_txpow(priv);
+	ath9k_cmn_update_txpow(ah, priv->curtxpow, priv->txpowlimit,
+			       &priv->curtxpow);
 
 	mode = ath9k_htc_get_curmode(priv, init_channel);
 	htc_mode = cpu_to_be16(mode);
@@ -997,6 +1122,11 @@
 
 	ath9k_host_rx_init(priv);
 
+	ret = ath9k_htc_update_cap_target(priv);
+	if (ret)
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Failed to update capability in target\n");
+
 	priv->op_flags &= ~OP_INVALID;
 	htc_start(priv->htc);
 
@@ -1051,25 +1181,21 @@
 	cancel_work_sync(&priv->fatal_work);
 	cancel_work_sync(&priv->ps_work);
 	cancel_delayed_work_sync(&priv->ath9k_led_blink_work);
+	ath9k_htc_stop_ani(priv);
 	ath9k_led_stop_brightness(priv);
 
 	mutex_lock(&priv->mutex);
 
-	/* Remove monitor interface here */
-	if (ah->opmode == NL80211_IFTYPE_MONITOR) {
-		if (ath9k_htc_remove_monitor_interface(priv))
-			ath_err(common, "Unable to remove monitor interface\n");
-		else
-			ath_dbg(common, ATH_DBG_CONFIG,
-				"Monitor interface removed\n");
-	}
-
 	if (ah->btcoex_hw.enabled) {
 		ath9k_hw_btcoex_disable(ah);
 		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
 			ath_htc_cancel_btcoex_work(priv);
 	}
 
+	/* Remove a monitor interface if it's present. */
+	if (priv->ah->is_monitoring)
+		ath9k_htc_remove_monitor_interface(priv);
+
 	ath9k_hw_phy_disable(ah);
 	ath9k_hw_disable(ah);
 	ath9k_htc_ps_restore(priv);
@@ -1093,10 +1219,24 @@
 
 	mutex_lock(&priv->mutex);
 
-	/* Only one interface for now */
-	if (priv->nvifs > 0) {
-		ret = -ENOBUFS;
-		goto out;
+	if (priv->nvifs >= ATH9K_HTC_MAX_VIF) {
+		mutex_unlock(&priv->mutex);
+		return -ENOBUFS;
+	}
+
+	if (priv->num_ibss_vif ||
+	    (priv->nvifs && vif->type == NL80211_IFTYPE_ADHOC)) {
+		ath_err(common, "IBSS coexistence with other modes is not allowed\n");
+		mutex_unlock(&priv->mutex);
+		return -ENOBUFS;
+	}
+
+	if (((vif->type == NL80211_IFTYPE_AP) ||
+	     (vif->type == NL80211_IFTYPE_ADHOC)) &&
+	    ((priv->num_ap_vif + priv->num_ibss_vif) >= ATH9K_HTC_MAX_BCN_VIF)) {
+		ath_err(common, "Max. number of beaconing interfaces reached\n");
+		mutex_unlock(&priv->mutex);
+		return -ENOBUFS;
 	}
 
 	ath9k_htc_ps_wakeup(priv);
@@ -1110,6 +1250,9 @@
 	case NL80211_IFTYPE_ADHOC:
 		hvif.opmode = cpu_to_be32(HTC_M_IBSS);
 		break;
+	case NL80211_IFTYPE_AP:
+		hvif.opmode = cpu_to_be32(HTC_M_HOSTAP);
+		break;
 	default:
 		ath_err(common,
 			"Interface type %d not yet supported\n", vif->type);
@@ -1117,34 +1260,39 @@
 		goto out;
 	}
 
-	ath_dbg(common, ATH_DBG_CONFIG,
-		"Attach a VIF of type: %d\n", vif->type);
-
-	priv->ah->opmode = vif->type;
-
 	/* Index starts from zero on the target */
-	avp->index = hvif.index = priv->nvifs;
+	avp->index = hvif.index = ffz(priv->vif_slot);
 	hvif.rtsthreshold = cpu_to_be16(2304);
 	WMI_CMD_BUF(WMI_VAP_CREATE_CMDID, &hvif);
 	if (ret)
 		goto out;
 
-	priv->nvifs++;
-
 	/*
 	 * We need a node in target to tx mgmt frames
 	 * before association.
 	 */
 	ret = ath9k_htc_add_station(priv, vif, NULL);
-	if (ret)
+	if (ret) {
+		WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
 		goto out;
+	}
 
-	ret = ath9k_htc_update_cap_target(priv);
-	if (ret)
-		ath_dbg(common, ATH_DBG_CONFIG,
-			"Failed to update capability in target\n");
+	ath9k_htc_set_bssid_mask(priv, vif);
 
+	priv->vif_slot |= (1 << avp->index);
+	priv->nvifs++;
 	priv->vif = vif;
+
+	INC_VIF(priv, vif->type);
+	ath9k_htc_set_opmode(priv);
+
+	if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+	    !(priv->op_flags & OP_ANI_RUNNING))
+		ath9k_htc_start_ani(priv);
+
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attach a VIF of type: %d at idx: %d\n", vif->type, avp->index);
+
 out:
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
@@ -1162,8 +1310,6 @@
 	int ret = 0;
 	u8 cmd_rsp;
 
-	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
-
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
 
@@ -1172,10 +1318,27 @@
 	hvif.index = avp->index;
 	WMI_CMD_BUF(WMI_VAP_REMOVE_CMDID, &hvif);
 	priv->nvifs--;
+	priv->vif_slot &= ~(1 << avp->index);
 
 	ath9k_htc_remove_station(priv, vif, NULL);
 	priv->vif = NULL;
 
+	DEC_VIF(priv, vif->type);
+	ath9k_htc_set_opmode(priv);
+
+	/*
+	 * Stop ANI only if there are no associated station interfaces.
+	 */
+	if ((vif->type == NL80211_IFTYPE_AP) && (priv->num_ap_vif == 0)) {
+		priv->rearm_ani = false;
+		ieee80211_iterate_active_interfaces_atomic(priv->hw,
+						   ath9k_htc_vif_iter, priv);
+		if (!priv->rearm_ani)
+			ath9k_htc_stop_ani(priv);
+	}
+
+	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface at idx: %d\n", avp->index);
+
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
@@ -1211,13 +1374,11 @@
 	 * IEEE80211_CONF_CHANGE_CHANNEL is handled.
 	 */
 	if (changed & IEEE80211_CONF_CHANGE_MONITOR) {
-		if (conf->flags & IEEE80211_CONF_MONITOR) {
-			if (ath9k_htc_add_monitor_interface(priv))
-				ath_err(common, "Failed to set monitor mode\n");
-			else
-				ath_dbg(common, ATH_DBG_CONFIG,
-					"HW opmode set to Monitor mode\n");
-		}
+		if ((conf->flags & IEEE80211_CONF_MONITOR) &&
+		    !priv->ah->is_monitoring)
+			ath9k_htc_add_monitor_interface(priv);
+		else if (priv->ah->is_monitoring)
+			ath9k_htc_remove_monitor_interface(priv);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
@@ -1252,7 +1413,8 @@
 
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
 		priv->txpowlimit = 2 * conf->power_level;
-		ath_update_txpow(priv);
+		ath9k_cmn_update_txpow(priv->ah, priv->curtxpow,
+				       priv->txpowlimit, &priv->curtxpow);
 	}
 
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
@@ -1439,66 +1601,81 @@
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath_hw *ah = priv->ah;
 	struct ath_common *common = ath9k_hw_common(ah);
+	bool set_assoc;
 
 	mutex_lock(&priv->mutex);
 	ath9k_htc_ps_wakeup(priv);
 
+	/*
+	 * Set the HW AID/BSSID only for the first station interface
+	 * or in IBSS mode.
+	 */
+	set_assoc = !!((priv->ah->opmode == NL80211_IFTYPE_ADHOC) ||
+		       ((priv->ah->opmode == NL80211_IFTYPE_STATION) &&
+			(priv->num_sta_vif == 1)));
+
+
 	if (changed & BSS_CHANGED_ASSOC) {
-		common->curaid = bss_conf->assoc ?
-				 bss_conf->aid : 0;
-		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
-			bss_conf->assoc);
+		if (set_assoc) {
+			ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n",
+				bss_conf->assoc);
 
-		if (bss_conf->assoc) {
-			priv->op_flags |= OP_ASSOCIATED;
-			ath_start_ani(priv);
-		} else {
-			priv->op_flags &= ~OP_ASSOCIATED;
-			cancel_delayed_work_sync(&priv->ath9k_ani_work);
+			common->curaid = bss_conf->assoc ?
+				bss_conf->aid : 0;
+
+			if (bss_conf->assoc)
+				ath9k_htc_start_ani(priv);
+			else
+				ath9k_htc_stop_ani(priv);
 		}
 	}
 
 	if (changed & BSS_CHANGED_BSSID) {
-		/* Set BSSID */
-		memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
-		ath9k_hw_write_associd(ah);
+		if (set_assoc) {
+			memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
+			ath9k_hw_write_associd(ah);
 
-		ath_dbg(common, ATH_DBG_CONFIG,
-			"BSSID: %pM aid: 0x%x\n",
-			common->curbssid, common->curaid);
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"BSSID: %pM aid: 0x%x\n",
+				common->curbssid, common->curaid);
+		}
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_INT) ||
-	    (changed & BSS_CHANGED_BEACON) ||
-	    ((changed & BSS_CHANGED_BEACON_ENABLED) &&
-	    bss_conf->enable_beacon)) {
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Beacon enabled for BSS: %pM\n", bss_conf->bssid);
 		priv->op_flags |= OP_ENABLE_BEACON;
 		ath9k_htc_beacon_config(priv, vif);
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
-	    !bss_conf->enable_beacon) {
-		priv->op_flags &= ~OP_ENABLE_BEACON;
-		ath9k_htc_beacon_config(priv, vif);
-	}
-
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		ath_dbg(common, ATH_DBG_CONFIG, "BSS Changed PREAMBLE %d\n",
-			bss_conf->use_short_preamble);
-		if (bss_conf->use_short_preamble)
-			priv->op_flags |= OP_PREAMBLE_SHORT;
-		else
-			priv->op_flags &= ~OP_PREAMBLE_SHORT;
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon) {
+		/*
+		 * Disable SWBA interrupt only if there are no
+		 * AP/IBSS interfaces.
+		 */
+		if ((priv->num_ap_vif <= 1) || priv->num_ibss_vif) {
+			ath_dbg(common, ATH_DBG_CONFIG,
+				"Beacon disabled for BSS: %pM\n",
+				bss_conf->bssid);
+			priv->op_flags &= ~OP_ENABLE_BEACON;
+			ath9k_htc_beacon_config(priv, vif);
+		}
 	}
 
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		ath_dbg(common, 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)
-			priv->op_flags |= OP_PROTECT_ENABLE;
-		else
-			priv->op_flags &= ~OP_PROTECT_ENABLE;
+	if (changed & BSS_CHANGED_BEACON_INT) {
+		/*
+		 * Reset the HW TSF for the first AP interface.
+		 */
+		if ((priv->ah->opmode == NL80211_IFTYPE_AP) &&
+		    (priv->nvifs == 1) &&
+		    (priv->num_ap_vif == 1) &&
+		    (vif->type == NL80211_IFTYPE_AP)) {
+			priv->op_flags |= OP_TSF_RESET;
+		}
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Beacon interval changed for BSS: %pM\n",
+			bss_conf->bssid);
+		ath9k_htc_beacon_config(priv, vif);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1557,12 +1734,14 @@
 				  struct ieee80211_vif *vif,
 				  enum ieee80211_ampdu_mlme_action action,
 				  struct ieee80211_sta *sta,
-				  u16 tid, u16 *ssn)
+				  u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ath9k_htc_priv *priv = hw->priv;
 	struct ath9k_htc_sta *ista;
 	int ret = 0;
 
+	mutex_lock(&priv->mutex);
+
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
 		break;
@@ -1587,6 +1766,8 @@
 		ath_err(ath9k_hw_common(priv->ah), "Unknown AMPDU action\n");
 	}
 
+	mutex_unlock(&priv->mutex);
+
 	return ret;
 }
 
@@ -1599,8 +1780,7 @@
 	priv->op_flags |= OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
 	cancel_work_sync(&priv->ps_work);
-	if (priv->op_flags & OP_ASSOCIATED)
-		cancel_delayed_work_sync(&priv->ath9k_ani_work);
+	ath9k_htc_stop_ani(priv);
 	mutex_unlock(&priv->mutex);
 }
 
@@ -1609,14 +1789,11 @@
 	struct ath9k_htc_priv *priv = hw->priv;
 
 	mutex_lock(&priv->mutex);
-	ath9k_htc_ps_wakeup(priv);
 	spin_lock_bh(&priv->beacon_lock);
 	priv->op_flags &= ~OP_SCANNING;
 	spin_unlock_bh(&priv->beacon_lock);
-	if (priv->op_flags & OP_ASSOCIATED) {
-		ath9k_htc_beacon_config(priv, priv->vif);
-		ath_start_ani(priv);
-	}
+	ath9k_htc_ps_wakeup(priv);
+	ath9k_htc_vif_reconfig(priv);
 	ath9k_htc_ps_restore(priv);
 	mutex_unlock(&priv->mutex);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,9 @@
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = tx_info->control.sta;
+	struct ieee80211_vif *vif = tx_info->control.vif;
 	struct ath9k_htc_sta *ista;
+	struct ath9k_htc_vif *avp;
 	struct ath9k_htc_tx_ctl tx_ctl;
 	enum htc_endpoint_id epid;
 	u16 qnum;
@@ -95,18 +97,31 @@
 	hdr = (struct ieee80211_hdr *) skb->data;
 	fc = hdr->frame_control;
 
-	if (tx_info->control.vif &&
-			(struct ath9k_htc_vif *) tx_info->control.vif->drv_priv)
-		vif_idx = ((struct ath9k_htc_vif *)
-				tx_info->control.vif->drv_priv)->index;
-	else
-		vif_idx = priv->nvifs;
+	/*
+	 * Find out on which interface this packet has to be
+	 * sent out.
+	 */
+	if (vif) {
+		avp = (struct ath9k_htc_vif *) vif->drv_priv;
+		vif_idx = avp->index;
+	} else {
+		if (!priv->ah->is_monitoring) {
+			ath_dbg(ath9k_hw_common(priv->ah), ATH_DBG_XMIT,
+				"VIF is null, but no monitor interface !\n");
+			return -EINVAL;
+		}
 
+		vif_idx = priv->mon_vif_idx;
+	}
+
+	/*
+	 * Find out which station this packet is destined for.
+	 */
 	if (sta) {
 		ista = (struct ath9k_htc_sta *) sta->drv_priv;
 		sta_idx = ista->index;
 	} else {
-		sta_idx = 0;
+		sta_idx = priv->vif_sta_pos[vif_idx];
 	}
 
 	memset(&tx_ctl, 0, sizeof(struct ath9k_htc_tx_ctl));
@@ -141,7 +156,7 @@
 
 		/* CTS-to-self */
 		if (!(flags & ATH9K_HTC_TX_RTSCTS) &&
-		    (priv->op_flags & OP_PROTECT_ENABLE))
+		    (vif && vif->bss_conf.use_cts_prot))
 			flags |= ATH9K_HTC_TX_CTSONLY;
 
 		tx_hdr.flags = cpu_to_be32(flags);
@@ -217,6 +232,7 @@
 void ath9k_tx_tasklet(unsigned long data)
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
+	struct ieee80211_vif *vif;
 	struct ieee80211_sta *sta;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *tx_info;
@@ -228,12 +244,16 @@
 		hdr = (struct ieee80211_hdr *) skb->data;
 		fc = hdr->frame_control;
 		tx_info = IEEE80211_SKB_CB(skb);
+		vif = tx_info->control.vif;
 
 		memset(&tx_info->status, 0, sizeof(tx_info->status));
 
+		if (!vif)
+			goto send_mac80211;
+
 		rcu_read_lock();
 
-		sta = ieee80211_find_sta(priv->vif, hdr->addr1);
+		sta = ieee80211_find_sta(vif, hdr->addr1);
 		if (!sta) {
 			rcu_read_unlock();
 			ieee80211_tx_status(priv->hw, skb);
@@ -263,6 +283,7 @@
 
 		rcu_read_unlock();
 
+	send_mac80211:
 		/* Send status to mac80211 */
 		ieee80211_tx_status(priv->hw, skb);
 	}
@@ -386,7 +407,7 @@
 	 */
 	if (((ah->opmode != NL80211_IFTYPE_AP) &&
 	     (priv->rxfilter & FIF_PROMISC_IN_BSS)) ||
-	    (ah->opmode == NL80211_IFTYPE_MONITOR))
+	    ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
 	if (priv->rxfilter & FIF_CONTROL)
@@ -398,8 +419,13 @@
 	else
 		rfilt |= ATH9K_RX_FILTER_BEACON;
 
-	if (conf_is_ht(&priv->hw->conf))
+	if (conf_is_ht(&priv->hw->conf)) {
 		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
+		rfilt |= ATH9K_RX_FILTER_UNCOMP_BA_BAR;
+	}
+
+	if (priv->rxfilter & FIF_PSPOLL)
+		rfilt |= ATH9K_RX_FILTER_PSPOLL;
 
 	return rfilt;
 
@@ -412,20 +438,12 @@
 static void ath9k_htc_opmode_init(struct ath9k_htc_priv *priv)
 {
 	struct ath_hw *ah = priv->ah;
-	struct ath_common *common = ath9k_hw_common(ah);
-
 	u32 rfilt, mfilt[2];
 
 	/* configure rx filter */
 	rfilt = ath9k_htc_calcrxfilter(priv);
 	ath9k_hw_setrxfilter(ah, rfilt);
 
-	/* configure bssid mask */
-	ath_hw_setbssidmask(common);
-
-	/* configure operational mode */
-	ath9k_hw_setopmode(ah);
-
 	/* calculate and install multicast filter */
 	mfilt[0] = mfilt[1] = ~0;
 	ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]);
@@ -576,31 +594,29 @@
 	ath9k_process_rate(hw, rx_status, rxbuf->rxstatus.rs_rate,
 			   rxbuf->rxstatus.rs_flags);
 
-	if (priv->op_flags & OP_ASSOCIATED) {
-		if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
-		    !rxbuf->rxstatus.rs_moreaggr)
-			ATH_RSSI_LPF(priv->rx.last_rssi,
-				     rxbuf->rxstatus.rs_rssi);
+	if (rxbuf->rxstatus.rs_rssi != ATH9K_RSSI_BAD &&
+	    !rxbuf->rxstatus.rs_moreaggr)
+		ATH_RSSI_LPF(priv->rx.last_rssi,
+			     rxbuf->rxstatus.rs_rssi);
 
-		last_rssi = priv->rx.last_rssi;
+	last_rssi = priv->rx.last_rssi;
 
-		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
-			rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
-							     ATH_RSSI_EP_MULTIPLIER);
+	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
+		rxbuf->rxstatus.rs_rssi = ATH_EP_RND(last_rssi,
+						     ATH_RSSI_EP_MULTIPLIER);
 
-		if (rxbuf->rxstatus.rs_rssi < 0)
-			rxbuf->rxstatus.rs_rssi = 0;
+	if (rxbuf->rxstatus.rs_rssi < 0)
+		rxbuf->rxstatus.rs_rssi = 0;
 
-		if (ieee80211_is_beacon(fc))
-			priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
-	}
+	if (ieee80211_is_beacon(fc))
+		priv->ah->stats.avgbrssi = rxbuf->rxstatus.rs_rssi;
 
 	rx_status->mactime = be64_to_cpu(rxbuf->rxstatus.rs_tstamp);
 	rx_status->band = hw->conf.channel->band;
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->signal =  rxbuf->rxstatus.rs_rssi + ATH_DEFAULT_NOISE_FLOOR;
 	rx_status->antenna = rxbuf->rxstatus.rs_antenna;
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	return true;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include "wmi.h"
 
 #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 */
@@ -204,8 +205,50 @@
 	__be32 ht_tx_xretries;
 } __packed;
 
+#define ATH9K_HTC_MAX_VIF 2
+#define ATH9K_HTC_MAX_BCN_VIF 2
+
+#define INC_VIF(_priv, _type) do {		\
+		switch (_type) {		\
+		case NL80211_IFTYPE_STATION:	\
+			_priv->num_sta_vif++;	\
+			break;			\
+		case NL80211_IFTYPE_ADHOC:	\
+			_priv->num_ibss_vif++;	\
+			break;			\
+		case NL80211_IFTYPE_AP:		\
+			_priv->num_ap_vif++;	\
+			break;			\
+		default:			\
+			break;			\
+		}				\
+	} while (0)
+
+#define DEC_VIF(_priv, _type) do {		\
+		switch (_type) {		\
+		case NL80211_IFTYPE_STATION:	\
+			_priv->num_sta_vif--;	\
+			break;			\
+		case NL80211_IFTYPE_ADHOC:	\
+			_priv->num_ibss_vif--;	\
+			break;			\
+		case NL80211_IFTYPE_AP:		\
+			_priv->num_ap_vif--;	\
+			break;			\
+		default:			\
+			break;			\
+		}				\
+	} while (0)
+
 struct ath9k_htc_vif {
 	u8 index;
+	u16 seq_no;
+	bool beacon_configured;
+};
+
+struct ath9k_vif_iter_data {
+	const u8 *hw_macaddr;
+	u8 mask[ETH_ALEN];
 };
 
 #define ATH9K_HTC_MAX_STA 8
@@ -310,10 +353,8 @@
 
 struct htc_beacon_config {
 	u16 beacon_interval;
-	u16 listen_interval;
 	u16 dtim_period;
 	u16 bmiss_timeout;
-	u8 dtim_count;
 };
 
 struct ath_btcoex {
@@ -333,13 +374,12 @@
 #define OP_SCANNING		   BIT(1)
 #define OP_LED_ASSOCIATED	   BIT(2)
 #define OP_LED_ON		   BIT(3)
-#define OP_PREAMBLE_SHORT	   BIT(4)
-#define OP_PROTECT_ENABLE	   BIT(5)
-#define OP_ASSOCIATED		   BIT(6)
-#define OP_ENABLE_BEACON	   BIT(7)
-#define OP_LED_DEINIT		   BIT(8)
-#define OP_BT_PRIORITY_DETECTED    BIT(9)
-#define OP_BT_SCAN                 BIT(10)
+#define OP_ENABLE_BEACON	   BIT(4)
+#define OP_LED_DEINIT		   BIT(5)
+#define OP_BT_PRIORITY_DETECTED    BIT(6)
+#define OP_BT_SCAN                 BIT(7)
+#define OP_ANI_RUNNING             BIT(8)
+#define OP_TSF_RESET               BIT(9)
 
 struct ath9k_htc_priv {
 	struct device *dev;
@@ -358,15 +398,24 @@
 	enum htc_endpoint_id data_vi_ep;
 	enum htc_endpoint_id data_vo_ep;
 
+	u8 vif_slot;
+	u8 mon_vif_idx;
+	u8 sta_slot;
+	u8 vif_sta_pos[ATH9K_HTC_MAX_VIF];
+	u8 num_ibss_vif;
+	u8 num_sta_vif;
+	u8 num_ap_vif;
+
 	u16 op_flags;
 	u16 curtxpow;
 	u16 txpowlimit;
 	u16 nvifs;
 	u16 nstations;
-	u16 seq_no;
 	u32 bmiss_cnt;
+	bool rearm_ani;
+	bool reconfig_beacon;
 
-	struct ath9k_hw_cal_data caldata[ATH9K_NUM_CHANNELS];
+	struct ath9k_hw_cal_data caldata;
 
 	spinlock_t beacon_lock;
 
@@ -382,7 +431,7 @@
 	struct ath9k_htc_rx rx;
 	struct tasklet_struct tx_tasklet;
 	struct sk_buff_head tx_queue;
-	struct delayed_work ath9k_ani_work;
+	struct delayed_work ani_work;
 	struct work_struct ps_work;
 	struct work_struct fatal_work;
 
@@ -424,6 +473,7 @@
 void ath9k_htc_beaconq_config(struct ath9k_htc_priv *priv);
 void ath9k_htc_beacon_config(struct ath9k_htc_priv *priv,
 			     struct ieee80211_vif *vif);
+void ath9k_htc_beacon_reconfig(struct ath9k_htc_priv *priv);
 void ath9k_htc_swba(struct ath9k_htc_priv *priv, u8 beacon_pending);
 
 void ath9k_htc_rxep(void *priv, struct sk_buff *skb,
@@ -436,8 +486,9 @@
 int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv);
 void ath9k_htc_station_work(struct work_struct *work);
 void ath9k_htc_aggr_work(struct work_struct *work);
-void ath9k_ani_work(struct work_struct *work);;
-void ath_start_ani(struct ath9k_htc_priv *priv);
+void ath9k_htc_ani_work(struct work_struct *work);
+void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
+void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
 
 int ath9k_tx_init(struct ath9k_htc_priv *priv);
 void ath9k_tx_tasklet(unsigned long data);
@@ -460,7 +511,6 @@
 void ath9k_ps_work(struct work_struct *work);
 bool ath9k_htc_setpower(struct ath9k_htc_priv *priv,
 			enum ath9k_power_mode mode);
-void ath_update_txpow(struct ath9k_htc_priv *priv);
 
 void ath9k_start_rfkill_poll(struct ath9k_htc_priv *priv);
 void ath9k_htc_rfkill_poll_state(struct ieee80211_hw *hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_hst.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_hst.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/htc_hst.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/htc_hst.c	2011-05-19 00:06:34.000000000 -0400
@@ -360,7 +360,7 @@
  * HTC Messages are handled directly here and the obtained SKB
  * is freed.
  *
- * Sevice messages (Data, WMI) passed to the corresponding
+ * Service messages (Data, WMI) passed to the corresponding
  * endpoint RX handlers, which have to free the SKB.
  */
 void ath9k_htc_rx_msg(struct htc_target *htc_handle,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hw.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -495,6 +495,17 @@
 	if (ah->hw_version.devid == AR5416_AR9100_DEVID)
 		ah->hw_version.macVersion = AR_SREV_VERSION_9100;
 
+	ath9k_hw_read_revisions(ah);
+
+	/*
+	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
+	 * We need to do this to avoid RMW of this register. We cannot
+	 * read the reg when chip is asleep.
+	 */
+	ah->WARegVal = REG_READ(ah, AR_WA);
+	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
+			 AR_WA_ASPM_TIMER_BASED_DISABLE);
+
 	if (!ath9k_hw_set_reset_reg(ah, ATH9K_RESET_POWER_ON)) {
 		ath_err(common, "Couldn't reset chip\n");
 		return -EIO;
@@ -563,14 +574,6 @@
 
 	ath9k_hw_init_mode_regs(ah);
 
-	/*
-	 * Read back AR_WA into a permanent copy and set bits 14 and 17.
-	 * We need to do this to avoid RMW of this register. We cannot
-	 * read the reg when chip is asleep.
-	 */
-	ah->WARegVal = REG_READ(ah, AR_WA);
-	ah->WARegVal |= (AR_WA_D3_L1_DISABLE |
-			 AR_WA_ASPM_TIMER_BASED_DISABLE);
 
 	if (ah->is_pciexpress)
 		ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -668,13 +671,50 @@
 	REGWRITE_BUFFER_FLUSH(ah);
 }
 
+unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah)
+{
+		REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) & ~(PLL3_DO_MEAS_MASK)));
+		udelay(100);
+		REG_WRITE(ah, PLL3, (REG_READ(ah, PLL3) | PLL3_DO_MEAS_MASK));
+
+		while ((REG_READ(ah, PLL4) & PLL4_MEAS_DONE) == 0)
+			udelay(100);
+
+		return (REG_READ(ah, PLL3) & SQSUM_DVC_MASK) >> 3;
+}
+EXPORT_SYMBOL(ar9003_get_pll_sqsum_dvc);
+
+#define DPLL2_KD_VAL            0x3D
+#define DPLL2_KI_VAL            0x06
+#define DPLL3_PHASE_SHIFT_VAL   0x1
+
 static void ath9k_hw_init_pll(struct ath_hw *ah,
 			      struct ath9k_channel *chan)
 {
 	u32 pll;
 
-	if (AR_SREV_9485(ah))
+	if (AR_SREV_9485(ah)) {
 		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
+		REG_WRITE(ah, AR_CH0_DDR_DPLL2, 0x19e82f01);
+
+		REG_RMW_FIELD(ah, AR_CH0_DDR_DPLL3,
+			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
+
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
+		udelay(1000);
+
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
+
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+			      AR_CH0_DPLL2_KD, DPLL2_KD_VAL);
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL2,
+			      AR_CH0_DPLL2_KI, DPLL2_KI_VAL);
+
+		REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
+			      AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
+		REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
+		udelay(1000);
+	}
 
 	pll = ath9k_hw_compute_pll_control(ah, chan);
 
@@ -1060,7 +1100,6 @@
 		REG_WRITE(ah, AR_RC, AR_RC_AHB);
 
 	REG_WRITE(ah, AR_RTC_RESET, 0);
-	udelay(2);
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
@@ -1082,8 +1121,6 @@
 		return false;
 	}
 
-	ath9k_hw_read_revisions(ah);
-
 	return ath9k_hw_set_reset(ah, ATH9K_RESET_WARM);
 }
 
@@ -1217,15 +1254,6 @@
 	ah->txchainmask = common->tx_chainmask;
 	ah->rxchainmask = common->rx_chainmask;
 
-	if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) {
-		ath9k_hw_abortpcurecv(ah);
-		if (!ath9k_hw_stopdmarecv(ah)) {
-			ath_dbg(common, ATH_DBG_XMIT,
-				"Failed to stop receive dma\n");
-			bChannelChange = false;
-		}
-	}
-
 	if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
 		return -EIO;
 
@@ -1348,8 +1376,6 @@
 	ath9k_hw_spur_mitigate_freq(ah, chan);
 	ah->eep_ops->set_board_values(ah, chan);
 
-	ath9k_hw_set_operating_mode(ah, ah->opmode);
-
 	ENABLE_REGWRITE_BUFFER(ah);
 
 	REG_WRITE(ah, AR_STA_ID0, get_unaligned_le32(common->macaddr));
@@ -1367,6 +1393,8 @@
 
 	REGWRITE_BUFFER_FLUSH(ah);
 
+	ath9k_hw_set_operating_mode(ah, ah->opmode);
+
 	r = ath9k_hw_rf_set_freq(ah, chan);
 	if (r)
 		return r;
@@ -2509,6 +2537,7 @@
 	{ AR_SREV_VERSION_9287,         "9287" },
 	{ AR_SREV_VERSION_9271,         "9271" },
 	{ AR_SREV_VERSION_9300,         "9300" },
+	{ AR_SREV_VERSION_9485,         "9485" },
 };
 
 /* For devices with external radios */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -70,6 +70,9 @@
 #define REG_READ(_ah, _reg) \
 	ath9k_hw_common(_ah)->ops->read((_ah), (_reg))
 
+#define REG_READ_MULTI(_ah, _addr, _val, _cnt)		\
+	ath9k_hw_common(_ah)->ops->multi_read((_ah), (_addr), (_val), (_cnt))
+
 #define ENABLE_REGWRITE_BUFFER(_ah)					\
 	do {								\
 		if (ath9k_hw_common(_ah)->ops->enable_write_buffer)	\
@@ -92,9 +95,9 @@
 #define REG_READ_FIELD(_a, _r, _f) \
 	(((REG_READ(_a, _r) & _f) >> _f##_S))
 #define REG_SET_BIT(_a, _r, _f) \
-	REG_WRITE(_a, _r, REG_READ(_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)
+	REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
 
 #define DO_DELAY(x) do {			\
 		if ((++(x) % 64) == 0)          \
@@ -926,6 +929,7 @@
 void ath9k_hw_reset_tsf(struct ath_hw *ah);
 void ath9k_hw_set_tsfadjust(struct ath_hw *ah, u32 setting);
 void ath9k_hw_init_global_settings(struct ath_hw *ah);
+unsigned long ar9003_get_pll_sqsum_dvc(struct ath_hw *ah);
 void ath9k_hw_set11nmac2040(struct ath_hw *ah);
 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,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/init.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/init.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -140,6 +140,21 @@
 	RATE(540, 0x0c, 0),
 };
 
+#ifdef CONFIG_MAC80211_LEDS
+static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
+	{ .throughput = 0 * 1024, .blink_time = 334 },
+	{ .throughput = 1 * 1024, .blink_time = 260 },
+	{ .throughput = 5 * 1024, .blink_time = 220 },
+	{ .throughput = 10 * 1024, .blink_time = 190 },
+	{ .throughput = 20 * 1024, .blink_time = 170 },
+	{ .throughput = 50 * 1024, .blink_time = 150 },
+	{ .throughput = 70 * 1024, .blink_time = 130 },
+	{ .throughput = 100 * 1024, .blink_time = 110 },
+	{ .throughput = 200 * 1024, .blink_time = 80 },
+	{ .throughput = 300 * 1024, .blink_time = 50 },
+};
+#endif
+
 static void ath9k_deinit_softc(struct ath_softc *sc);
 
 /*
@@ -250,8 +265,7 @@
 			      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_softc *sc = hw->priv;
 	struct ath_regulatory *reg = ath9k_hw_regulatory(sc->sc_ah);
 
 	return ath_reg_notifier_apply(wiphy, request, reg);
@@ -438,9 +452,10 @@
 	sc->config.cabqReadytime = ATH_CABQ_READY_TIME;
 	ath_cabq_update(sc);
 
-	for (i = 0; i < WME_NUM_AC; i++)
+	for (i = 0; i < WME_NUM_AC; i++) {
 		sc->tx.txq_map[i] = ath_txq_setup(sc, ATH9K_TX_QUEUE_DATA, i);
-
+		sc->tx.txq_map[i]->mac80211_qnum = i;
+	}
 	return 0;
 }
 
@@ -512,10 +527,8 @@
 
 	sc->beacon.slottime = ATH9K_SLOT_TIME_9;
 
-	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++) {
+	for (i = 0; i < ARRAY_SIZE(sc->beacon.bslot); i++)
 		sc->beacon.bslot[i] = NULL;
-		sc->beacon.bslot_aphy[i] = NULL;
-	}
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
 		sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
@@ -533,6 +546,7 @@
 	if (!ah)
 		return -ENOMEM;
 
+	ah->hw = sc->hw;
 	ah->hw_version.devid = devid;
 	ah->hw_version.subsysid = subsysid;
 	sc->sc_ah = ah;
@@ -550,10 +564,13 @@
 	common->btcoex_enabled = ath9k_btcoex_enable == 1;
 	spin_lock_init(&common->cc_lock);
 
-	spin_lock_init(&sc->wiphy_lock);
 	spin_lock_init(&sc->sc_serial_rw);
 	spin_lock_init(&sc->sc_pm_lock);
 	mutex_init(&sc->mutex);
+#ifdef CONFIG_ATH9K_DEBUGFS
+	spin_lock_init(&sc->nodes_lock);
+	INIT_LIST_HEAD(&sc->nodes);
+#endif
 	tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
 	tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
 		     (unsigned long)sc);
@@ -695,7 +712,6 @@
 		    const struct ath_bus_ops *bus_ops)
 {
 	struct ieee80211_hw *hw = sc->hw;
-	struct ath_wiphy *aphy = hw->priv;
 	struct ath_common *common;
 	struct ath_hw *ah;
 	int error = 0;
@@ -730,6 +746,13 @@
 
 	ath9k_init_txpower_limits(sc);
 
+#ifdef CONFIG_MAC80211_LEDS
+	/* must be initialized before ieee80211_register_hw */
+	sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
+		IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
+		ARRAY_SIZE(ath9k_tpt_blink));
+#endif
+
 	/* Register with mac80211 */
 	error = ieee80211_register_hw(hw);
 	if (error)
@@ -750,10 +773,7 @@
 
 	INIT_WORK(&sc->hw_check_work, ath_hw_check);
 	INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
-	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);
-	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+	sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
 
 	ath_init_leds(sc);
 	ath_start_rfkill_poll(sc);
@@ -805,7 +825,6 @@
 void ath9k_deinit_device(struct ath_softc *sc)
 {
 	struct ieee80211_hw *hw = sc->hw;
-	int i = 0;
 
 	ath9k_ps_wakeup(sc);
 
@@ -814,20 +833,10 @@
 
 	ath9k_ps_restore(sc);
 
-	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);
 	ath9k_deinit_softc(sc);
-	kfree(sc->sec_wiphy);
 }
 
 void ath_descdma_cleanup(struct ath_softc *sc,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -143,84 +143,59 @@
 }
 EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
 
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
 {
-#define ATH9K_TX_STOP_DMA_TIMEOUT	4000    /* usec */
-#define ATH9K_TIME_QUANTUM		100     /* usec */
-	struct ath_common *common = ath9k_hw_common(ah);
-	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;
+	int i, q;
 
-	if (q >= pCap->total_queues) {
-		ath_dbg(common, ATH_DBG_QUEUE,
-			"Stopping TX DMA, invalid queue: %u\n", q);
-		return false;
-	}
+	REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
 
-	qi = &ah->txq[q];
-	if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
-		ath_dbg(common, ATH_DBG_QUEUE,
-			"Stopping TX DMA, inactive queue: %u\n", q);
-		return false;
-	}
+	REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+	REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+	REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
 
-	REG_WRITE(ah, AR_Q_TXD, 1 << q);
+	for (q = 0; q < AR_NUM_QCU; q++) {
+		for (i = 0; i < 1000; i++) {
+			if (i)
+				udelay(5);
 
-	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))
+				break;
+		}
 	}
 
-	if (ath9k_hw_numtxpending(ah, q)) {
-		ath_dbg(common, 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;
+	REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
+	REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+	REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
 
-			ath_dbg(common, ATH_DBG_QUEUE,
-				"TSF has moved while trying to set quiet time TSF: 0x%08x\n",
-				tsfLow);
-		}
+	REG_WRITE(ah, AR_Q_TXD, 0);
+}
+EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
 
-		REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
+{
+#define ATH9K_TX_STOP_DMA_TIMEOUT	1000    /* usec */
+#define ATH9K_TIME_QUANTUM		100     /* usec */
+	int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
+	int wait;
 
-		udelay(200);
-		REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
+	REG_WRITE(ah, AR_Q_TXD, 1 << q);
 
-		wait = wait_time;
-		while (ath9k_hw_numtxpending(ah, q)) {
-			if ((--wait) == 0) {
-				ath_err(common,
-					"Failed to stop TX DMA in 100 msec after killing last frame\n");
-				break;
-			}
+	for (wait = wait_time; wait != 0; wait--) {
+		if (wait != wait_time)
 			udelay(ATH9K_TIME_QUANTUM);
-		}
 
-		REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
+		if (ath9k_hw_numtxpending(ah, q) == 0)
+			break;
 	}
 
 	REG_WRITE(ah, AR_Q_TXD, 0);
+
 	return wait != 0;
 
 #undef ATH9K_TX_STOP_DMA_TIMEOUT
 #undef ATH9K_TIME_QUANTUM
 }
-EXPORT_SYMBOL(ath9k_hw_stoptxdma);
+EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
 
 void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
 {
@@ -690,17 +665,23 @@
 		rs->rs_flags |= ATH9K_RX_DECRYPT_BUSY;
 
 	if ((ads.ds_rxstatus8 & AR_RxFrameOK) == 0) {
+		/*
+		 * Treat these errors as mutually exclusive to avoid spurious
+		 * extra error reports from the hardware. If a CRC error is
+		 * reported, then decryption and MIC errors are irrelevant,
+		 * the frame is going to be dropped either way
+		 */
 		if (ads.ds_rxstatus8 & AR_CRCErr)
 			rs->rs_status |= ATH9K_RXERR_CRC;
-		if (ads.ds_rxstatus8 & AR_PHYErr) {
+		else if (ads.ds_rxstatus8 & AR_PHYErr) {
 			rs->rs_status |= ATH9K_RXERR_PHY;
 			phyerr = MS(ads.ds_rxstatus8, AR_PHYErrCode);
 			rs->rs_phyerr = phyerr;
-		}
-		if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
+		} else if (ads.ds_rxstatus8 & AR_DecryptCRCErr)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
-		if (ads.ds_rxstatus8 & AR_MichaelErr)
+		else if (ads.ds_rxstatus8 & AR_MichaelErr)
 			rs->rs_status |= ATH9K_RXERR_MIC;
+
 		if (ads.ds_rxstatus8 & AR_KeyMiss)
 			rs->rs_status |= ATH9K_RXERR_DECRYPT;
 	}
@@ -770,28 +751,47 @@
 }
 EXPORT_SYMBOL(ath9k_hw_abortpcurecv);
 
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah)
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset)
 {
 #define AH_RX_STOP_DMA_TIMEOUT 10000   /* usec */
 #define AH_RX_TIME_QUANTUM     100     /* usec */
 	struct ath_common *common = ath9k_hw_common(ah);
+	u32 mac_status, last_mac_status = 0;
 	int i;
 
+	/* Enable access to the DMA observation bus */
+	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)));
+
 	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;
+
+		if (!AR_SREV_9300_20_OR_LATER(ah)) {
+			mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0;
+			if (mac_status == 0x1c0 && mac_status == last_mac_status) {
+				*reset = true;
+				break;
+			}
+
+			last_mac_status = mac_status;
+		}
+
 		udelay(AH_TIME_QUANTUM);
 	}
 
 	if (i == 0) {
 		ath_err(common,
-			"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n",
+			"DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n",
 			AH_RX_STOP_DMA_TIMEOUT / 1000,
 			REG_READ(ah, AR_CR),
-			REG_READ(ah, AR_DIAG_SW));
+			REG_READ(ah, AR_DIAG_SW),
+			REG_READ(ah, AR_DMADBG_7));
 		return false;
 	} else {
 		return true;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/mac.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/mac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/mac.h	2011-05-19 00:06:34.000000000 -0400
@@ -639,6 +639,8 @@
 	ATH9K_RX_FILTER_PHYERR = 0x00000100,
 	ATH9K_RX_FILTER_MYBEACON = 0x00000200,
 	ATH9K_RX_FILTER_COMP_BAR = 0x00000400,
+	ATH9K_RX_FILTER_COMP_BA = 0x00000800,
+	ATH9K_RX_FILTER_UNCOMP_BA_BAR = 0x00001000,
 	ATH9K_RX_FILTER_PSPOLL = 0x00004000,
 	ATH9K_RX_FILTER_PHYRADAR = 0x00002000,
 	ATH9K_RX_FILTER_MCAST_BCAST_ALL = 0x00008000,
@@ -674,7 +676,8 @@
 void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
 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_stop_dma_queue(struct ath_hw *ah, u32 q);
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
 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);
@@ -692,7 +695,7 @@
 void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp);
 void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
 void ath9k_hw_abortpcurecv(struct ath_hw *ah);
-bool ath9k_hw_stopdmarecv(struct ath_hw *ah);
+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset);
 int ath9k_hw_beaconq_setup(struct ath_hw *ah);
 
 /* Interrupt Handling */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,20 +15,10 @@
  */
 
 #include <linux/nl80211.h>
+#include <linux/delay.h>
 #include "ath9k.h"
 #include "btcoex.h"
 
-static void ath_update_txpow(struct ath_softc *sc)
-{
-	struct ath_hw *ah = sc->sc_ah;
-
-	if (sc->curtxpow != sc->config.txpowlimit) {
-		ath9k_hw_set_txpowerlimit(ah, sc->config.txpowlimit, false);
-		/* read back in case value is clamped */
-		sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit;
-	}
-}
-
 static u8 parse_mpdudensity(u8 mpdudensity)
 {
 	/*
@@ -64,17 +54,19 @@
 	}
 }
 
-static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
-						struct ieee80211_hw *hw)
+static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq)
 {
-	struct ieee80211_channel *curchan = hw->conf.channel;
-	struct ath9k_channel *channel;
-	u8 chan_idx;
+	bool pending = false;
 
-	chan_idx = curchan->hw_value;
-	channel = &sc->sc_ah->channels[chan_idx];
-	ath9k_update_ichannel(sc, hw, channel);
-	return channel;
+	spin_lock_bh(&txq->axq_lock);
+
+	if (txq->axq_depth || !list_empty(&txq->axq_acq))
+		pending = true;
+	else if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+		pending = !list_empty(&txq->txq_fifo_pending);
+
+	spin_unlock_bh(&txq->axq_lock);
+	return pending;
 }
 
 bool ath9k_setpower(struct ath_softc *sc, enum ath9k_power_mode mode)
@@ -177,7 +169,12 @@
 	}
 }
 
-static void ath_update_survey_stats(struct ath_softc *sc)
+/*
+ * Updates the survey statistics and returns the busy time since last
+ * update in %, if the measurement duration was long enough for the
+ * result to be useful, -1 otherwise.
+ */
+static int ath_update_survey_stats(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -185,9 +182,10 @@
 	struct survey_info *survey = &sc->survey[pos];
 	struct ath_cycle_counters *cc = &common->cc_survey;
 	unsigned int div = common->clockrate * 1000;
+	int ret = 0;
 
 	if (!ah->curchan)
-		return;
+		return -1;
 
 	if (ah->power_mode == ATH9K_PM_AWAKE)
 		ath_hw_cycle_counters_update(common);
@@ -202,9 +200,18 @@
 		survey->channel_time_rx += cc->rx_frame / div;
 		survey->channel_time_tx += cc->tx_frame / div;
 	}
+
+	if (cc->cycles < div)
+		return -1;
+
+	if (cc->cycles > 0)
+		ret = cc->rx_busy * 100 / cc->cycles;
+
 	memset(cc, 0, sizeof(*cc));
 
 	ath_update_survey_nf(sc, pos);
+
+	return ret;
 }
 
 /*
@@ -215,7 +222,6 @@
 int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
 		    struct ath9k_channel *hchan)
 {
-	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &common->hw->conf;
@@ -227,10 +233,13 @@
 	if (sc->sc_flags & SC_OP_INVALID)
 		return -EIO;
 
+	sc->hw_busy_count = 0;
+
 	del_timer_sync(&common->ani.timer);
 	cancel_work_sync(&sc->paprd_work);
 	cancel_work_sync(&sc->hw_check_work);
 	cancel_delayed_work_sync(&sc->tx_complete_work);
+	cancel_delayed_work_sync(&sc->hw_pll_work);
 
 	ath9k_ps_wakeup(sc);
 
@@ -251,6 +260,9 @@
 	if (!ath_stoprecv(sc))
 		stopped = false;
 
+	if (!ath9k_hw_check_alive(ah))
+		stopped = false;
+
 	/* XXX: do not flush receive queue here. We don't want
 	 * to flush data frames already in queue because of
 	 * changing channel. */
@@ -259,7 +271,7 @@
 		fastcc = false;
 
 	if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
-		caldata = &aphy->caldata;
+		caldata = &sc->caldata;
 
 	ath_dbg(common, ATH_DBG_CONFIG,
 		"(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n",
@@ -281,17 +293,21 @@
 		goto ps_restore;
 	}
 
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->config.txpowlimit, &sc->curtxpow);
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
 	if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
 		if (sc->sc_flags & SC_OP_BEACONS)
 			ath_beacon_config(sc, NULL);
 		ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
+		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2);
 		ath_start_ani(common);
 	}
 
  ps_restore:
+	ieee80211_wake_queues(hw);
+
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
 	ath9k_ps_restore(sc);
@@ -549,6 +565,12 @@
 	struct ath_hw *ah = sc->sc_ah;
 	an = (struct ath_node *)sta->drv_priv;
 
+#ifdef CONFIG_ATH9K_DEBUGFS
+	spin_lock(&sc->nodes_lock);
+	list_add(&an->list, &sc->nodes);
+	spin_unlock(&sc->nodes_lock);
+	an->sta = sta;
+#endif
 	if ((ah->caps.hw_caps) & ATH9K_HW_CAP_APM)
 		sc->sc_flags |= SC_OP_ENABLE_APM;
 
@@ -564,6 +586,13 @@
 {
 	struct ath_node *an = (struct ath_node *)sta->drv_priv;
 
+#ifdef CONFIG_ATH9K_DEBUGFS
+	spin_lock(&sc->nodes_lock);
+	list_del(&an->list);
+	spin_unlock(&sc->nodes_lock);
+	an->sta = NULL;
+#endif
+
 	if (sc->sc_flags & SC_OP_TXAGGR)
 		ath_tx_node_cleanup(sc, an);
 }
@@ -571,17 +600,25 @@
 void ath_hw_check(struct work_struct *work)
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc, hw_check_work);
-	int i;
+	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+	unsigned long flags;
+	int busy;
 
 	ath9k_ps_wakeup(sc);
+	if (ath9k_hw_check_alive(sc->sc_ah))
+		goto out;
 
-	for (i = 0; i < 3; i++) {
-		if (ath9k_hw_check_alive(sc->sc_ah))
-			goto out;
+	spin_lock_irqsave(&common->cc_lock, flags);
+	busy = ath_update_survey_stats(sc);
+	spin_unlock_irqrestore(&common->cc_lock, flags);
 
-		msleep(1);
-	}
-	ath_reset(sc, true);
+	ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, "
+		"busy=%d (try %d)\n", busy, sc->hw_busy_count + 1);
+	if (busy >= 99) {
+		if (++sc->hw_busy_count >= 3)
+			ath_reset(sc, true);
+	} else if (busy >= 0)
+		sc->hw_busy_count = 0;
 
 out:
 	ath9k_ps_restore(sc);
@@ -604,7 +641,15 @@
 	ath9k_ps_wakeup(sc);
 	spin_lock(&sc->sc_pcu_lock);
 
-	if (!ath9k_hw_check_alive(ah))
+	/*
+	 * Only run the baseband hang check if beacons stop working in AP or
+	 * IBSS mode, because it has a high false positive rate. For station
+	 * mode it should not be necessary, since the upper layers will detect
+	 * this through a beacon miss automatically and the following channel
+	 * change will trigger a hardware reset anyway
+	 */
+	if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0 &&
+	    !ath9k_hw_check_alive(ah))
 		ieee80211_queue_work(sc->hw, &sc->hw_check_work);
 
 	if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
@@ -783,54 +828,11 @@
 #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 void ath9k_bss_assoc_info(struct ath_softc *sc,
 				 struct ieee80211_hw *hw,
 				 struct ieee80211_vif *vif,
 				 struct ieee80211_bss_conf *bss_conf)
 {
-	struct ath_wiphy *aphy = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 
@@ -854,7 +856,7 @@
 		ath_beacon_config(sc, vif);
 
 		/* Reset rssi stats */
-		aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
+		sc->last_rssi = ATH_RSSI_DUMMY_MARKER;
 		sc->sc_ah->stats.avgbrssi = ATH_RSSI_DUMMY_MARKER;
 
 		sc->sc_flags |= SC_OP_ANI_RUN;
@@ -881,7 +883,7 @@
 	ath9k_hw_configpcipowersave(ah, 0, 0);
 
 	if (!ah->curchan)
-		ah->curchan = ath_get_curchannel(sc, sc->hw);
+		ah->curchan = ath9k_cmn_get_curchannel(sc->hw, ah);
 
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
@@ -890,7 +892,8 @@
 			channel->center_freq, r);
 	}
 
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->config.txpowlimit, &sc->curtxpow);
 	if (ath_startrecv(sc) != 0) {
 		ath_err(common, "Unable to restart recv logic\n");
 		goto out;
@@ -907,6 +910,8 @@
 	ath9k_hw_set_gpio(ah, ah->led_pin, 0);
 
 	ieee80211_wake_queues(hw);
+	ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2);
+
 out:
 	spin_unlock_bh(&sc->sc_pcu_lock);
 
@@ -920,6 +925,8 @@
 	int r;
 
 	ath9k_ps_wakeup(sc);
+	cancel_delayed_work_sync(&sc->hw_pll_work);
+
 	spin_lock_bh(&sc->sc_pcu_lock);
 
 	ieee80211_stop_queues(hw);
@@ -942,7 +949,7 @@
 	ath_flushrecv(sc);		/* flush recv queue */
 
 	if (!ah->curchan)
-		ah->curchan = ath_get_curchannel(sc, hw);
+		ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
 
 	r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
 	if (r) {
@@ -966,6 +973,8 @@
 	struct ieee80211_hw *hw = sc->hw;
 	int r;
 
+	sc->hw_busy_count = 0;
+
 	/* Stop ANI */
 	del_timer_sync(&common->ani.timer);
 
@@ -993,7 +1002,8 @@
 	 * that changes the channel so update any state that
 	 * might change as a result.
 	 */
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			       sc->config.txpowlimit, &sc->curtxpow);
 
 	if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL)))
 		ath_beacon_config(sc, NULL);	/* restart beacons */
@@ -1021,38 +1031,13 @@
 	return r;
 }
 
-/* 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 | CHANNEL_G;
-	} else {
-		ichan->chanmode = CHANNEL_A;
-		ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM;
-	}
-
-	if (conf_is_ht(conf))
-		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 ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_channel *curchan = hw->conf.channel;
@@ -1063,34 +1048,14 @@
 		"Starting driver with initial channel: %d MHz\n",
 		curchan->center_freq);
 
-	mutex_lock(&sc->mutex);
+	ath9k_ps_wakeup(sc);
 
-	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;
+	mutex_lock(&sc->mutex);
 
 	/* setup initial channel */
-
 	sc->chan_idx = curchan->hw_value;
 
-	init_channel = ath_get_curchannel(sc, hw);
+	init_channel = ath9k_cmn_get_curchannel(hw, ah);
 
 	/* Reset SERDES registers */
 	ath9k_hw_configpcipowersave(ah, 0, 0);
@@ -1116,7 +1081,8 @@
 	 * This is needed only to setup initial state
 	 * but it's best done after a reset.
 	 */
-	ath_update_txpow(sc);
+	ath9k_cmn_update_txpow(ah, sc->curtxpow,
+			sc->config.txpowlimit, &sc->curtxpow);
 
 	/*
 	 * Setup the hardware after reset:
@@ -1179,25 +1145,18 @@
 mutex_unlock:
 	mutex_unlock(&sc->mutex);
 
+	ath9k_ps_restore(sc);
+
 	return r;
 }
 
-static int ath9k_tx(struct ieee80211_hw *hw,
-		    struct sk_buff *skb)
+static void ath9k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_tx_control txctl;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 
-	if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
-		ath_dbg(common, ATH_DBG_XMIT,
-			"ath9k: %s: TX in unexpected wiphy state %d\n",
-			wiphy_name(hw->wiphy), aphy->state);
-		goto exit;
-	}
-
 	if (sc->ps_enabled) {
 		/*
 		 * mac80211 does not set PM field for normal data frames, so we
@@ -1248,52 +1207,30 @@
 		goto exit;
 	}
 
-	return 0;
+	return;
 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;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
-	int i;
 
 	mutex_lock(&sc->mutex);
 
-	aphy->state = ATH_WIPHY_INACTIVE;
-
-	if (led_blink)
-		cancel_delayed_work_sync(&sc->ath_led_blink_work);
-
 	cancel_delayed_work_sync(&sc->tx_complete_work);
+	cancel_delayed_work_sync(&sc->hw_pll_work);
 	cancel_work_sync(&sc->paprd_work);
 	cancel_work_sync(&sc->hw_check_work);
 
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		if (sc->sec_wiphy[i])
-			break;
-	}
-
-	if (i == sc->num_sec_wiphy) {
-		cancel_delayed_work_sync(&sc->wiphy_work);
-		cancel_work_sync(&sc->chan_work);
-	}
-
 	if (sc->sc_flags & SC_OP_INVALID) {
 		ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
 		mutex_unlock(&sc->mutex);
 		return;
 	}
 
-	if (ath9k_wiphy_started(sc)) {
-		mutex_unlock(&sc->mutex);
-		return; /* another wiphy still in use */
-	}
-
 	/* Ensure HW is awake when we try to shut it down. */
 	ath9k_ps_wakeup(sc);
 
@@ -1319,6 +1256,11 @@
 	} else
 		sc->rx.rxlink = NULL;
 
+	if (sc->rx.frag) {
+		dev_kfree_skb_any(sc->rx.frag);
+		sc->rx.frag = NULL;
+	}
+
 	/* disable HAL and put h/w to sleep */
 	ath9k_hw_disable(ah);
 	ath9k_hw_configpcipowersave(ah, 1, 1);
@@ -1334,7 +1276,6 @@
 	ath9k_ps_restore(sc);
 
 	sc->ps_idle = true;
-	ath9k_set_wiphy_idle(aphy, true);
 	ath_radio_disable(sc, hw);
 
 	sc->sc_flags |= SC_OP_INVALID;
@@ -1344,112 +1285,225 @@
 	ath_dbg(common, ATH_DBG_CONFIG, "Driver halt\n");
 }
 
-static int ath9k_add_interface(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif)
+bool ath9k_uses_beacons(int type)
+{
+	switch (type) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_MESH_POINT:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static void ath9k_reclaim_beacon(struct ath_softc *sc,
+				 struct ieee80211_vif *vif)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
-	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
-	enum nl80211_iftype ic_opmode = NL80211_IFTYPE_UNSPECIFIED;
-	int ret = 0;
 
-	mutex_lock(&sc->mutex);
+	ath9k_set_beaconing_status(sc, false);
+	ath_beacon_return(sc, avp);
+	ath9k_set_beaconing_status(sc, true);
+	sc->sc_flags &= ~SC_OP_BEACONS;
+}
+
+static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
+{
+	struct ath9k_vif_iter_data *iter_data = data;
+	int i;
+
+	if (iter_data->hw_macaddr)
+		for (i = 0; i < ETH_ALEN; i++)
+			iter_data->mask[i] &=
+				~(iter_data->hw_macaddr[i] ^ mac[i]);
 
 	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		ic_opmode = NL80211_IFTYPE_STATION;
+	case NL80211_IFTYPE_AP:
+		iter_data->naps++;
 		break;
-	case NL80211_IFTYPE_WDS:
-		ic_opmode = NL80211_IFTYPE_WDS;
+	case NL80211_IFTYPE_STATION:
+		iter_data->nstations++;
 		break;
 	case NL80211_IFTYPE_ADHOC:
-	case NL80211_IFTYPE_AP:
+		iter_data->nadhocs++;
+		break;
 	case NL80211_IFTYPE_MESH_POINT:
-		if (sc->nbcnvifs >= ATH_BCBUF) {
-			ret = -ENOBUFS;
-			goto out;
-		}
-		ic_opmode = vif->type;
+		iter_data->nmeshes++;
+		break;
+	case NL80211_IFTYPE_WDS:
+		iter_data->nwds++;
 		break;
 	default:
-		ath_err(common, "Interface type %d not yet supported\n",
-			vif->type);
-		ret = -EOPNOTSUPP;
-		goto out;
+		iter_data->nothers++;
+		break;
 	}
+}
 
-	ath_dbg(common, ATH_DBG_CONFIG,
-		"Attach a VIF of type: %d\n", ic_opmode);
+/* Called with sc->mutex held. */
+void ath9k_calculate_iter_data(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ath9k_vif_iter_data *iter_data)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 
-	/* Set the VIF opmode */
-	avp->av_opmode = ic_opmode;
-	avp->av_bslot = -1;
+	/*
+	 * Use the hardware MAC address as reference, the hardware uses it
+	 * together with the BSSID mask when matching addresses.
+	 */
+	memset(iter_data, 0, sizeof(*iter_data));
+	iter_data->hw_macaddr = common->macaddr;
+	memset(&iter_data->mask, 0xff, ETH_ALEN);
 
-	sc->nvifs++;
+	if (vif)
+		ath9k_vif_iter(iter_data, vif->addr, vif);
 
-	ath9k_set_bssid_mask(hw, vif);
+	/* Get list of all active MAC addresses */
+	ieee80211_iterate_active_interfaces_atomic(sc->hw, ath9k_vif_iter,
+						   iter_data);
+}
 
-	if (sc->nvifs > 1)
-		goto out; /* skip global settings for secondary vif */
+/* Called with sc->mutex held. */
+static void ath9k_calculate_summary_state(struct ieee80211_hw *hw,
+					  struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	struct ath9k_vif_iter_data iter_data;
 
-	if (ic_opmode == NL80211_IFTYPE_AP) {
+	ath9k_calculate_iter_data(hw, vif, &iter_data);
+
+	/* Set BSSID mask. */
+	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
+	ath_hw_setbssidmask(common);
+
+	/* Set op-mode & TSF */
+	if (iter_data.naps > 0) {
 		ath9k_hw_set_tsfadjust(ah, 1);
 		sc->sc_flags |= SC_OP_TSF_RESET;
-	}
+		ah->opmode = NL80211_IFTYPE_AP;
+	} else {
+		ath9k_hw_set_tsfadjust(ah, 0);
+		sc->sc_flags &= ~SC_OP_TSF_RESET;
 
-	/* Set the device opmode */
-	ah->opmode = ic_opmode;
+		if (iter_data.nwds + iter_data.nmeshes)
+			ah->opmode = NL80211_IFTYPE_AP;
+		else if (iter_data.nadhocs)
+			ah->opmode = NL80211_IFTYPE_ADHOC;
+		else
+			ah->opmode = NL80211_IFTYPE_STATION;
+	}
 
 	/*
 	 * Enable MIB interrupts when there are hardware phy counters.
-	 * Note we only do this (at the moment) for station mode.
 	 */
-	if ((vif->type == NL80211_IFTYPE_STATION) ||
-	    (vif->type == NL80211_IFTYPE_ADHOC) ||
-	    (vif->type == NL80211_IFTYPE_MESH_POINT)) {
+	if ((iter_data.nstations + iter_data.nadhocs + iter_data.nmeshes) > 0) {
 		if (ah->config.enable_ani)
 			ah->imask |= ATH9K_INT_MIB;
 		ah->imask |= ATH9K_INT_TSFOOR;
+	} else {
+		ah->imask &= ~ATH9K_INT_MIB;
+		ah->imask &= ~ATH9K_INT_TSFOOR;
 	}
 
 	ath9k_hw_set_interrupts(ah, ah->imask);
 
-	if (vif->type == NL80211_IFTYPE_AP    ||
-	    vif->type == NL80211_IFTYPE_ADHOC) {
+	/* Set up ANI */
+	if ((iter_data.naps + iter_data.nadhocs) > 0) {
 		sc->sc_flags |= SC_OP_ANI_RUN;
 		ath_start_ani(common);
+	} else {
+		sc->sc_flags &= ~SC_OP_ANI_RUN;
+		del_timer_sync(&common->ani.timer);
 	}
+}
 
-out:
-	mutex_unlock(&sc->mutex);
-	return ret;
+/* Called with sc->mutex held, vif counts set up properly. */
+static void ath9k_do_vif_add_setup(struct ieee80211_hw *hw,
+				   struct ieee80211_vif *vif)
+{
+	struct ath_softc *sc = hw->priv;
+
+	ath9k_calculate_summary_state(hw, vif);
+
+	if (ath9k_uses_beacons(vif->type)) {
+		int error;
+		/* This may fail because upper levels do not have beacons
+		 * properly configured yet.  That's OK, we assume it
+		 * will be properly configured and then we will be notified
+		 * in the info_changed method and set up beacons properly
+		 * there.
+		 */
+		ath9k_set_beaconing_status(sc, false);
+		error = ath_beacon_alloc(sc, vif);
+		if (!error)
+			ath_beacon_config(sc, vif);
+		ath9k_set_beaconing_status(sc, true);
+	}
 }
 
-static void ath9k_reclaim_beacon(struct ath_softc *sc,
-				 struct ieee80211_vif *vif)
+
+static int ath9k_add_interface(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif)
 {
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
+	int ret = 0;
 
-	/* Disable SWBA interrupt */
-	sc->sc_ah->imask &= ~ATH9K_INT_SWBA;
 	ath9k_ps_wakeup(sc);
-	ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
-	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-	tasklet_kill(&sc->bcon_tasklet);
-	ath9k_ps_restore(sc);
+	mutex_lock(&sc->mutex);
 
-	ath_beacon_return(sc, avp);
-	sc->sc_flags &= ~SC_OP_BEACONS;
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_WDS:
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_MESH_POINT:
+		break;
+	default:
+		ath_err(common, "Interface type %d not yet supported\n",
+			vif->type);
+		ret = -EOPNOTSUPP;
+		goto out;
+	}
 
-	if (sc->nbcnvifs > 0) {
-		/* Re-enable beaconing */
-		sc->sc_ah->imask |= ATH9K_INT_SWBA;
-		ath9k_ps_wakeup(sc);
-		ath9k_hw_set_interrupts(sc->sc_ah, sc->sc_ah->imask);
-		ath9k_ps_restore(sc);
+	if (ath9k_uses_beacons(vif->type)) {
+		if (sc->nbcnvifs >= ATH_BCBUF) {
+			ath_err(common, "Not enough beacon buffers when adding"
+				" new interface of type: %i\n",
+				vif->type);
+			ret = -ENOBUFS;
+			goto out;
+		}
+	}
+
+	if ((vif->type == NL80211_IFTYPE_ADHOC) &&
+	    sc->nvifs > 0) {
+		ath_err(common, "Cannot create ADHOC interface when other"
+			" interfaces already exist.\n");
+		ret = -EINVAL;
+		goto out;
 	}
+
+	ath_dbg(common, ATH_DBG_CONFIG,
+		"Attach a VIF of type: %d\n", vif->type);
+
+	/* Set the VIF opmode */
+	avp->av_opmode = vif->type;
+	avp->av_bslot = -1;
+
+	sc->nvifs++;
+
+	ath9k_do_vif_add_setup(hw, vif);
+out:
+	mutex_unlock(&sc->mutex);
+	ath9k_ps_restore(sc);
+	return ret;
 }
 
 static int ath9k_change_interface(struct ieee80211_hw *hw,
@@ -1457,41 +1511,43 @@
 				  enum nl80211_iftype new_type,
 				  bool p2p)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int ret = 0;
 
 	ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n");
 	mutex_lock(&sc->mutex);
+	ath9k_ps_wakeup(sc);
 
-	switch (new_type) {
-	case NL80211_IFTYPE_AP:
-	case NL80211_IFTYPE_ADHOC:
+	/* See if new interface type is valid. */
+	if ((new_type == NL80211_IFTYPE_ADHOC) &&
+	    (sc->nvifs > 1)) {
+		ath_err(common, "When using ADHOC, it must be the only"
+			" interface.\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (ath9k_uses_beacons(new_type) &&
+	    !ath9k_uses_beacons(vif->type)) {
 		if (sc->nbcnvifs >= ATH_BCBUF) {
 			ath_err(common, "No beacon slot available\n");
 			ret = -ENOBUFS;
 			goto out;
 		}
-		break;
-	case NL80211_IFTYPE_STATION:
-		/* Stop ANI */
-		sc->sc_flags &= ~SC_OP_ANI_RUN;
-		del_timer_sync(&common->ani.timer);
-		if ((vif->type == NL80211_IFTYPE_AP) ||
-		    (vif->type == NL80211_IFTYPE_ADHOC))
-			ath9k_reclaim_beacon(sc, vif);
-		break;
-	default:
-		ath_err(common, "Interface type %d not yet supported\n",
-				vif->type);
-		ret = -ENOTSUPP;
-		goto out;
 	}
+
+	/* Clean up old vif stuff */
+	if (ath9k_uses_beacons(vif->type))
+		ath9k_reclaim_beacon(sc, vif);
+
+	/* Add new settings */
 	vif->type = new_type;
 	vif->p2p = p2p;
 
+	ath9k_do_vif_add_setup(hw, vif);
 out:
+	ath9k_ps_restore(sc);
 	mutex_unlock(&sc->mutex);
 	return ret;
 }
@@ -1499,27 +1555,24 @@
 static void ath9k_remove_interface(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 
 	ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n");
 
+	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
 
-	/* Stop ANI */
-	sc->sc_flags &= ~SC_OP_ANI_RUN;
-	del_timer_sync(&common->ani.timer);
+	sc->nvifs--;
 
 	/* 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))
+	if (ath9k_uses_beacons(vif->type))
 		ath9k_reclaim_beacon(sc, vif);
 
-	sc->nvifs--;
+	ath9k_calculate_summary_state(hw, NULL);
 
 	mutex_unlock(&sc->mutex);
+	ath9k_ps_restore(sc);
 }
 
 static void ath9k_enable_ps(struct ath_softc *sc)
@@ -1558,12 +1611,11 @@
 
 static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ieee80211_conf *conf = &hw->conf;
-	bool disable_radio;
+	bool disable_radio = false;
 
 	mutex_lock(&sc->mutex);
 
@@ -1574,29 +1626,13 @@
 	 * the end.
 	 */
 	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
-		bool enable_radio;
-		bool all_wiphys_idle;
-		bool idle = !!(conf->flags & IEEE80211_CONF_IDLE);
-
-		spin_lock_bh(&sc->wiphy_lock);
-		all_wiphys_idle =  ath9k_all_wiphys_idle(sc);
-		ath9k_set_wiphy_idle(aphy, idle);
-
-		enable_radio = (!idle && all_wiphys_idle);
-
-		/*
-		 * After we unlock here its possible another wiphy
-		 * can be re-renabled so to account for that we will
-		 * only disable the radio toward the end of this routine
-		 * if by then all wiphys are still idle.
-		 */
-		spin_unlock_bh(&sc->wiphy_lock);
-
-		if (enable_radio) {
-			sc->ps_idle = false;
+		sc->ps_idle = !!(conf->flags & IEEE80211_CONF_IDLE);
+		if (!sc->ps_idle) {
 			ath_radio_enable(sc, hw);
 			ath_dbg(common, ATH_DBG_CONFIG,
 				"not-idle: enabling radio\n");
+		} else {
+			disable_radio = true;
 		}
 	}
 
@@ -1637,29 +1673,17 @@
 		if (ah->curchan)
 			old_pos = ah->curchan - &ah->channels[0];
 
-		aphy->chan_idx = pos;
-		aphy->chan_is_ht = conf_is_ht(conf);
 		if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)
 			sc->sc_flags |= SC_OP_OFFCHANNEL;
 		else
 			sc->sc_flags &= ~SC_OP_OFFCHANNEL;
 
-		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;
-		}
-
-		ath_dbg(common, ATH_DBG_CONFIG, "Set channel: %d MHz\n",
-			curchan->center_freq);
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Set channel: %d MHz type: %d\n",
+			curchan->center_freq, conf->channel_type);
 
-		/* XXX: remove me eventualy */
-		ath9k_update_ichannel(sc, hw, &sc->sc_ah->channels[pos]);
+		ath9k_cmn_update_ichannel(&sc->sc_ah->channels[pos],
+					  curchan, conf->channel_type);
 
 		/* update survey stats for the old channel before switching */
 		spin_lock_irqsave(&common->cc_lock, flags);
@@ -1701,21 +1725,18 @@
 			ath_update_survey_nf(sc, old_pos);
 	}
 
-skip_chan_change:
 	if (changed & IEEE80211_CONF_CHANGE_POWER) {
+		ath_dbg(common, ATH_DBG_CONFIG,
+			"Set power: %d\n", conf->power_level);
 		sc->config.txpowlimit = 2 * conf->power_level;
 		ath9k_ps_wakeup(sc);
-		ath_update_txpow(sc);
+		ath9k_cmn_update_txpow(ah, sc->curtxpow,
+				       sc->config.txpowlimit, &sc->curtxpow);
 		ath9k_ps_restore(sc);
 	}
 
-	spin_lock_bh(&sc->wiphy_lock);
-	disable_radio = ath9k_all_wiphys_idle(sc);
-	spin_unlock_bh(&sc->wiphy_lock);
-
 	if (disable_radio) {
 		ath_dbg(common, ATH_DBG_CONFIG, "idle: disabling radio\n");
-		sc->ps_idle = true;
 		ath_radio_disable(sc, hw);
 	}
 
@@ -1740,8 +1761,7 @@
 				   unsigned int *total_flags,
 				   u64 multicast)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	u32 rfilt;
 
 	changed_flags &= SUPPORTED_FILTERS;
@@ -1761,8 +1781,7 @@
 			 struct ieee80211_vif *vif,
 			 struct ieee80211_sta *sta)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	ath_node_attach(sc, sta);
 
@@ -1773,8 +1792,7 @@
 			    struct ieee80211_vif *vif,
 			    struct ieee80211_sta *sta)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	ath_node_detach(sc, sta);
 
@@ -1784,8 +1802,7 @@
 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 ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_txq *txq;
 	struct ath9k_tx_queue_info qi;
@@ -1796,6 +1813,7 @@
 
 	txq = sc->tx.txq_map[queue];
 
+	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
 
 	memset(&qi, 0, sizeof(struct ath9k_tx_queue_info));
@@ -1819,6 +1837,7 @@
 			ath_beaconq_config(sc);
 
 	mutex_unlock(&sc->mutex);
+	ath9k_ps_restore(sc);
 
 	return ret;
 }
@@ -1829,8 +1848,7 @@
 			 struct ieee80211_sta *sta,
 			 struct ieee80211_key_conf *key)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	int ret = 0;
 
@@ -1874,14 +1892,15 @@
 				   struct ieee80211_bss_conf *bss_conf,
 				   u32 changed)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath_vif *avp = (void *)vif->drv_priv;
 	int slottime;
 	int error;
 
+	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
 
 	if (changed & BSS_CHANGED_BSSID) {
@@ -1904,10 +1923,11 @@
 	/* Enable transmission of beacons (AP, IBSS, MESH) */
 	if ((changed & BSS_CHANGED_BEACON) ||
 	    ((changed & BSS_CHANGED_BEACON_ENABLED) && bss_conf->enable_beacon)) {
-		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-		error = ath_beacon_alloc(aphy, vif);
+		ath9k_set_beaconing_status(sc, false);
+		error = ath_beacon_alloc(sc, vif);
 		if (!error)
 			ath_beacon_config(sc, vif);
+		ath9k_set_beaconing_status(sc, true);
 	}
 
 	if (changed & BSS_CHANGED_ERP_SLOT) {
@@ -1930,21 +1950,26 @@
 	}
 
 	/* Disable transmission of beacons */
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) && !bss_conf->enable_beacon)
-		ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
+	    !bss_conf->enable_beacon) {
+		ath9k_set_beaconing_status(sc, false);
+		avp->is_bslot_active = false;
+		ath9k_set_beaconing_status(sc, true);
+	}
 
 	if (changed & BSS_CHANGED_BEACON_INT) {
-		sc->beacon_interval = bss_conf->beacon_int;
+		cur_conf->beacon_interval = bss_conf->beacon_int;
 		/*
 		 * In case of AP mode, the HW TSF has to be reset
 		 * when the beacon interval changes.
 		 */
 		if (vif->type == NL80211_IFTYPE_AP) {
 			sc->sc_flags |= SC_OP_TSF_RESET;
-			ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
-			error = ath_beacon_alloc(aphy, vif);
+			ath9k_set_beaconing_status(sc, false);
+			error = ath_beacon_alloc(sc, vif);
 			if (!error)
 				ath_beacon_config(sc, vif);
+			ath9k_set_beaconing_status(sc, true);
 		} else {
 			ath_beacon_config(sc, vif);
 		}
@@ -1976,13 +2001,13 @@
 	}
 
 	mutex_unlock(&sc->mutex);
+	ath9k_ps_restore(sc);
 }
 
 static u64 ath9k_get_tsf(struct ieee80211_hw *hw)
 {
+	struct ath_softc *sc = hw->priv;
 	u64 tsf;
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
 
 	mutex_lock(&sc->mutex);
 	ath9k_ps_wakeup(sc);
@@ -1995,8 +2020,7 @@
 
 static void ath9k_set_tsf(struct ieee80211_hw *hw, u64 tsf)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	mutex_lock(&sc->mutex);
 	ath9k_ps_wakeup(sc);
@@ -2007,8 +2031,7 @@
 
 static void ath9k_reset_tsf(struct ieee80211_hw *hw)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	mutex_lock(&sc->mutex);
 
@@ -2023,10 +2046,9 @@
 			      struct ieee80211_vif *vif,
 			      enum ieee80211_ampdu_mlme_action action,
 			      struct ieee80211_sta *sta,
-			      u16 tid, u16 *ssn)
+			      u16 tid, u16 *ssn, u8 buf_size)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	int ret = 0;
 
 	local_bh_disable();
@@ -2071,8 +2093,7 @@
 static int ath9k_get_survey(struct ieee80211_hw *hw, int idx,
 			     struct survey_info *survey)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ieee80211_supported_band *sband;
 	struct ieee80211_channel *chan;
@@ -2106,53 +2127,65 @@
 	return 0;
 }
 
-static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
+static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
 
 	mutex_lock(&sc->mutex);
-	if (ath9k_wiphy_scanning(sc)) {
-		/*
-		 * There is a race here in mac80211 but fixing it requires
-		 * we revisit how we handle the scan complete callback.
-		 * After mac80211 fixes we will not have configured hardware
-		 * to the home channel nor would we have configured the RX
-		 * filter yet.
-		 */
-		mutex_unlock(&sc->mutex);
-		return;
-	}
-
-	aphy->state = ATH_WIPHY_SCAN;
-	ath9k_wiphy_pause_all_forced(sc, aphy);
+	ah->coverage_class = coverage_class;
+	ath9k_hw_init_global_settings(ah);
 	mutex_unlock(&sc->mutex);
 }
 
-/*
- * XXX: this requires a revisit after the driver
- * scan_complete gets moved to another place/removed in mac80211.
- */
-static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
+static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
+	struct ath_hw *ah = sc->sc_ah;
+	struct ath_common *common = ath9k_hw_common(ah);
+	int timeout = 200; /* ms */
+	int i, j;
 
+	ath9k_ps_wakeup(sc);
 	mutex_lock(&sc->mutex);
-	aphy->state = ATH_WIPHY_ACTIVE;
-	mutex_unlock(&sc->mutex);
-}
 
-static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_hw *ah = sc->sc_ah;
+	cancel_delayed_work_sync(&sc->tx_complete_work);
 
-	mutex_lock(&sc->mutex);
-	ah->coverage_class = coverage_class;
-	ath9k_hw_init_global_settings(ah);
+	if (sc->sc_flags & SC_OP_INVALID) {
+		ath_dbg(common, ATH_DBG_ANY, "Device not present\n");
+		mutex_unlock(&sc->mutex);
+		return;
+	}
+
+	if (drop)
+		timeout = 1;
+
+	for (j = 0; j < timeout; j++) {
+		int npend = 0;
+
+		if (j)
+			usleep_range(1000, 2000);
+
+		for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+			if (!ATH_TXQ_SETUP(sc, i))
+				continue;
+
+			npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+		}
+
+		if (!npend)
+		    goto out;
+	}
+
+	if (!ath_drain_all_txq(sc, false))
+		ath_reset(sc, false);
+
+	ieee80211_wake_queues(hw);
+
+out:
+	ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
 	mutex_unlock(&sc->mutex);
+	ath9k_ps_restore(sc);
 }
 
 struct ieee80211_ops ath9k_ops = {
@@ -2174,8 +2207,7 @@
 	.reset_tsf 	    = ath9k_reset_tsf,
 	.ampdu_action       = ath9k_ampdu_action,
 	.get_survey	    = ath9k_get_survey,
-	.sw_scan_start      = ath9k_sw_scan_start,
-	.sw_scan_complete   = ath9k_sw_scan_complete,
 	.rfkill_poll        = ath9k_rfkill_poll_state,
 	.set_coverage_class = ath9k_set_coverage_class,
+	.flush		    = ath9k_flush,
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,6 @@
 		main.o \
 		recv.o \
 		xmit.o \
-		virtual.o \
 
 ath9k-$(CONFIG_ATH9K_RATE_CONTROL) += rc.o
 ath9k-$(CONFIG_PCI) += pci.o
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,7 @@
 	*csz = (int)u8tmp;
 
 	/*
-	 * This check was put in to avoid "unplesant" consequences if
+	 * This check was put in to avoid "unpleasant" consequences if
 	 * the bootrom has not fully initialized all PCI devices.
 	 * Sometimes the cache line size register is not set
 	 */
@@ -126,7 +126,6 @@
 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;
@@ -198,8 +197,7 @@
 		goto err_iomap;
 	}
 
-	hw = ieee80211_alloc_hw(sizeof(struct ath_wiphy) +
-				sizeof(struct ath_softc), &ath9k_ops);
+	hw = ieee80211_alloc_hw(sizeof(struct ath_softc), &ath9k_ops);
 	if (!hw) {
 		dev_err(&pdev->dev, "No memory for ieee80211_hw\n");
 		ret = -ENOMEM;
@@ -209,11 +207,7 @@
 	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->priv;
 	sc->hw = hw;
 	sc->dev = &pdev->dev;
 	sc->mem = mem;
@@ -260,8 +254,7 @@
 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;
+	struct ath_softc *sc = hw->priv;
 	void __iomem *mem = sc->mem;
 
 	if (!is_ath9k_unloaded)
@@ -281,8 +274,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 
 	ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
@@ -293,8 +285,7 @@
 {
 	struct pci_dev *pdev = to_pci_dev(device);
 	struct ieee80211_hw *hw = pci_get_drvdata(pdev);
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	u32 val;
 
 	/*
@@ -320,7 +311,6 @@
 	ath9k_ps_restore(sc);
 
 	sc->ps_idle = true;
-	ath9k_set_wiphy_idle(aphy, true);
 	ath_radio_disable(sc, hw);
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/rc.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/rc.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/rc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/rc.c	2011-05-19 00:06:34.000000000 -0400
@@ -792,7 +792,7 @@
 
 		tx_info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 	} else {
-		/* Set the choosen rate. No RTS for first series entry. */
+		/* Set the chosen rate. No RTS for first series entry. */
 		ath_rc_rate_set_series(rate_table, &rates[i++], txrc,
 				       try_per_rate, rix, 0);
 	}
@@ -1328,7 +1328,7 @@
 
 	hdr = (struct ieee80211_hdr *)skb->data;
 	fc = hdr->frame_control;
-	for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
+	for (i = 0; i < sc->hw->max_rates; i++) {
 		struct ieee80211_tx_rate *rate = &tx_info->status.rates[i];
 		if (!rate->count)
 			break;
@@ -1560,8 +1560,7 @@
 
 static void *ath_rate_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	return aphy->sc;
+	return hw->priv;
 }
 
 static void ath_rate_free(void *priv)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/recv.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/recv.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/recv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/recv.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,27 +34,6 @@
 	       (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_AUTOSLEEP);
 }
 
-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.
  *
@@ -230,11 +209,6 @@
 	int error = 0, i;
 	u32 size;
 
-
-	common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN +
-				     ah->caps.rx_status_len,
-				     min(common->cachelsz, (u16)64));
-
 	ath9k_hw_set_rx_bufsize(ah, common->rx_bufsize -
 				    ah->caps.rx_status_len);
 
@@ -321,12 +295,12 @@
 	sc->sc_flags &= ~SC_OP_RXFLUSH;
 	spin_lock_init(&sc->rx.rxbuflock);
 
+	common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
+			     sc->sc_ah->caps.rx_status_len;
+
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 		return ath_rx_edma_init(sc, nbufs);
 	} else {
-		common->rx_bufsize = roundup(IEEE80211_MAX_MPDU_LEN,
-				min(common->cachelsz, (u16)64));
-
 		ath_dbg(common, ATH_DBG_CONFIG, "cachelsz %u rxbufsize %u\n",
 			common->cachelsz, common->rx_bufsize);
 
@@ -439,9 +413,7 @@
 	 * 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->is_monitoring))
+	if (sc->sc_ah->is_monitoring)
 		rfilt |= ATH9K_RX_FILTER_PROM;
 
 	if (sc->rx.rxfilter & FIF_CONTROL)
@@ -463,8 +435,7 @@
 	if (conf_is_ht(&sc->hw->conf))
 		rfilt |= ATH9K_RX_FILTER_COMP_BAR;
 
-	if (sc->sec_wiphy || (sc->nvifs > 1) ||
-	    (sc->rx.rxfilter & FIF_OTHER_BSS)) {
+	if (sc->nvifs > 1 || (sc->rx.rxfilter & FIF_OTHER_BSS)) {
 		/* The following may also be needed for other older chips */
 		if (sc->sc_ah->hw_version.macVersion == AR_SREV_VERSION_9160)
 			rfilt |= ATH9K_RX_FILTER_PROM;
@@ -515,12 +486,12 @@
 bool ath_stoprecv(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
-	bool stopped;
+	bool stopped, reset = false;
 
 	spin_lock_bh(&sc->rx.rxbuflock);
 	ath9k_hw_abortpcurecv(ah);
 	ath9k_hw_setrxfilter(ah, 0);
-	stopped = ath9k_hw_stopdmarecv(ah);
+	stopped = ath9k_hw_stopdmarecv(ah, &reset);
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
 		ath_edma_stop_recv(sc);
@@ -535,7 +506,7 @@
 			"confusing the DMA engine when we start RX up\n");
 		ATH_DBG_WARN_ON_ONCE(!stopped);
 	}
-	return stopped;
+	return stopped && !reset;
 }
 
 void ath_flushrecv(struct ath_softc *sc)
@@ -588,8 +559,14 @@
 		return;
 
 	mgmt = (struct ieee80211_mgmt *)skb->data;
-	if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0)
+	if (memcmp(common->curbssid, mgmt->bssid, ETH_ALEN) != 0) {
+		/* TODO:  This doesn't work well if you have stations
+		 * associated to two different APs because curbssid
+		 * is just the last AP that any of the stations associated
+		 * with.
+		 */
 		return; /* not from our current AP */
+	}
 
 	sc->ps_flags &= ~PS_WAIT_FOR_BEACON;
 
@@ -662,37 +639,6 @@
 	}
 }
 
-static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
-				    struct ath_softc *sc, struct sk_buff *skb)
-{
-	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)
-				continue;
-			ieee80211_rx(aphy->hw, nskb);
-		}
-		ieee80211_rx(sc->hw, skb);
-	} else
-		/* Deliver unicast frames based on receiver address */
-		ieee80211_rx(hw, skb);
-}
-
 static bool ath_edma_get_buffers(struct ath_softc *sc,
 				 enum ath9k_rx_qtype qtype)
 {
@@ -862,15 +808,9 @@
 	if (rx_stats->rs_datalen > (common->rx_bufsize - rx_status_len))
 		return false;
 
-	/*
-	 * rs_more indicates chained descriptors which can be used
-	 * to link buffers together for a sort of scatter-gather
-	 * operation.
-	 * reject the frame, we don't support scatter-gather yet and
-	 * the frame is probably corrupt anyway
-	 */
+	/* Only use error bits from the last fragment */
 	if (rx_stats->rs_more)
-		return false;
+		return true;
 
 	/*
 	 * The rx_stats->rs_status will not be set until the end of the
@@ -974,7 +914,7 @@
 			       struct ieee80211_hdr *hdr,
 			       struct ath_rx_status *rx_stats)
 {
-	struct ath_wiphy *aphy = hw->priv;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = common->ah;
 	int last_rssi;
 	__le16 fc;
@@ -984,13 +924,19 @@
 
 	fc = hdr->frame_control;
 	if (!ieee80211_is_beacon(fc) ||
-	    compare_ether_addr(hdr->addr3, common->curbssid))
+	    compare_ether_addr(hdr->addr3, common->curbssid)) {
+		/* TODO:  This doesn't work well if you have stations
+		 * associated to two different APs because curbssid
+		 * is just the last AP that any of the stations associated
+		 * with.
+		 */
 		return;
+	}
 
 	if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
-		ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
+		ATH_RSSI_LPF(sc->last_rssi, rx_stats->rs_rssi);
 
-	last_rssi = aphy->last_rssi;
+	last_rssi = sc->last_rssi;
 	if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
 		rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
 					      ATH_RSSI_EP_MULTIPLIER);
@@ -1022,6 +968,10 @@
 	if (!ath9k_rx_accept(common, hdr, rx_status, rx_stats, decrypt_error))
 		return -EINVAL;
 
+	/* Only use status info from the last fragment */
+	if (rx_stats->rs_more)
+		return 0;
+
 	ath9k_process_rssi(common, hw, hdr, rx_stats);
 
 	if (ath9k_process_rate(common, hw, rx_stats, rx_status))
@@ -1031,7 +981,7 @@
 	rx_status->freq = hw->conf.channel->center_freq;
 	rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
 	rx_status->antenna = rx_stats->rs_antenna;
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	return 0;
 }
@@ -1623,7 +1573,7 @@
 int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
 {
 	struct ath_buf *bf;
-	struct sk_buff *skb = NULL, *requeue_skb;
+	struct sk_buff *skb = NULL, *requeue_skb, *hdr_skb;
 	struct ieee80211_rx_status *rxs;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(ah);
@@ -1632,7 +1582,7 @@
 	 * virtual wiphy so to account for that we iterate over the active
 	 * wiphys and find the appropriate wiphy and therefore hw.
 	 */
-	struct ieee80211_hw *hw = NULL;
+	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_hdr *hdr;
 	int retval;
 	bool decrypt_error = false;
@@ -1674,10 +1624,17 @@
 		if (!skb)
 			continue;
 
-		hdr = (struct ieee80211_hdr *) (skb->data + rx_status_len);
-		rxs =  IEEE80211_SKB_RXCB(skb);
+		/*
+		 * Take frame header from the first fragment and RX status from
+		 * the last one.
+		 */
+		if (sc->rx.frag)
+			hdr_skb = sc->rx.frag;
+		else
+			hdr_skb = skb;
 
-		hw = ath_get_virt_hw(sc, hdr);
+		hdr = (struct ieee80211_hdr *) (hdr_skb->data + rx_status_len);
+		rxs = IEEE80211_SKB_RXCB(hdr_skb);
 
 		ath_debug_stat_rx(sc, &rs);
 
@@ -1686,12 +1643,12 @@
 		 * chain it back at the queue without processing it.
 		 */
 		if (flush)
-			goto requeue;
+			goto requeue_drop_frag;
 
 		retval = ath9k_rx_skb_preprocess(common, hw, hdr, &rs,
 						 rxs, &decrypt_error);
 		if (retval)
-			goto requeue;
+			goto requeue_drop_frag;
 
 		rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
 		if (rs.rs_tstamp > tsf_lower &&
@@ -1711,7 +1668,7 @@
 		 * skb and put it at the tail of the sc->rx.rxbuf list for
 		 * processing. */
 		if (!requeue_skb)
-			goto requeue;
+			goto requeue_drop_frag;
 
 		/* Unmap the frame */
 		dma_unmap_single(sc->dev, bf->bf_buf_addr,
@@ -1722,8 +1679,9 @@
 		if (ah->caps.rx_status_len)
 			skb_pull(skb, ah->caps.rx_status_len);
 
-		ath9k_rx_skb_postprocess(common, skb, &rs,
-					 rxs, decrypt_error);
+		if (!rs.rs_more)
+			ath9k_rx_skb_postprocess(common, hdr_skb, &rs,
+						 rxs, decrypt_error);
 
 		/* We will now give hardware our shiny new allocated skb */
 		bf->bf_mpdu = requeue_skb;
@@ -1736,10 +1694,42 @@
 			bf->bf_mpdu = NULL;
 			bf->bf_buf_addr = 0;
 			ath_err(common, "dma_mapping_error() on RX\n");
-			ath_rx_send_to_mac80211(hw, sc, skb);
+			ieee80211_rx(hw, skb);
 			break;
 		}
 
+		if (rs.rs_more) {
+			/*
+			 * rs_more indicates chained descriptors which can be
+			 * used to link buffers together for a sort of
+			 * scatter-gather operation.
+			 */
+			if (sc->rx.frag) {
+				/* too many fragments - cannot handle frame */
+				dev_kfree_skb_any(sc->rx.frag);
+				dev_kfree_skb_any(skb);
+				skb = NULL;
+			}
+			sc->rx.frag = skb;
+			goto requeue;
+		}
+
+		if (sc->rx.frag) {
+			int space = skb->len - skb_tailroom(hdr_skb);
+
+			sc->rx.frag = NULL;
+
+			if (pskb_expand_head(hdr_skb, 0, space, GFP_ATOMIC) < 0) {
+				dev_kfree_skb(skb);
+				goto requeue_drop_frag;
+			}
+
+			skb_copy_from_linear_data(skb, skb_put(hdr_skb, skb->len),
+						  skb->len);
+			dev_kfree_skb_any(skb);
+			skb = hdr_skb;
+		}
+
 		/*
 		 * change the default rx antenna if rx diversity chooses the
 		 * other antenna 3 times in a row.
@@ -1763,8 +1753,13 @@
 		if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
 			ath_ant_comb_scan(sc, &rs);
 
-		ath_rx_send_to_mac80211(hw, sc, skb);
+		ieee80211_rx(hw, skb);
 
+requeue_drop_frag:
+		if (sc->rx.frag) {
+			dev_kfree_skb_any(sc->rx.frag);
+			sc->rx.frag = NULL;
+		}
 requeue:
 		if (edma) {
 			list_add_tail(&bf->list, &sc->rx.rxbuf);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/reg.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/reg.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -789,6 +789,7 @@
 #define AR_SREV_REVISION_9300_20	2 /* 2.0 and 2.1 */
 #define AR_SREV_VERSION_9485		0x240
 #define AR_SREV_REVISION_9485_10	0
+#define AR_SREV_REVISION_9485_11        1
 
 #define AR_SREV_5416(_ah) \
 	(((_ah)->hw_version.macVersion == AR_SREV_VERSION_5416_PCI) || \
@@ -866,6 +867,9 @@
 #define AR_SREV_9485_10(_ah) \
 	(AR_SREV_9485(_ah) && \
 	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_10))
+#define AR_SREV_9485_11(_ah) \
+	(AR_SREV_9485(_ah) && \
+	 ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11))
 
 #define AR_SREV_9285E_20(_ah) \
     (AR_SREV_9285_12_OR_LATER(_ah) && \
@@ -874,6 +878,7 @@
 enum ath_usb_dev {
 	AR9280_USB = 1, /* AR7010 + AR9280, UB94 */
 	AR9287_USB = 2, /* AR7010 + AR9287, UB95 */
+	STORAGE_DEVICE = 3,
 };
 
 #define AR_DEVID_7010(_ah) \
@@ -1083,6 +1088,17 @@
 #define AR_ENT_OTP		  0x40d8
 #define AR_ENT_OTP_CHAIN2_DISABLE               0x00020000
 #define AR_ENT_OTP_MPSD		0x00800000
+#define AR_CH0_BB_DPLL2          0x16184
+#define AR_CH0_BB_DPLL3          0x16188
+#define AR_CH0_DDR_DPLL2         0x16244
+#define AR_CH0_DDR_DPLL3         0x16248
+#define AR_CH0_DPLL2_KD              0x03F80000
+#define AR_CH0_DPLL2_KD_S            19
+#define AR_CH0_DPLL2_KI              0x3C000000
+#define AR_CH0_DPLL2_KI_S            26
+#define AR_CH0_DPLL3_PHASE_SHIFT     0x3F800000
+#define AR_CH0_DPLL3_PHASE_SHIFT_S   23
+#define AR_PHY_CCA_NOM_VAL_2GHZ      -118
 
 #define AR_RTC_9300_PLL_DIV          0x000003ff
 #define AR_RTC_9300_PLL_DIV_S        0
@@ -1129,6 +1145,12 @@
 #define AR_RTC_PLL_CLKSEL       0x00000300
 #define AR_RTC_PLL_CLKSEL_S     8
 
+#define PLL3 0x16188
+#define PLL3_DO_MEAS_MASK 0x40000000
+#define PLL4 0x1618c
+#define PLL4_MEAS_DONE    0x8
+#define SQSUM_DVC_MASK 0x007ffff8
+
 #define AR_RTC_RESET \
 	((AR_SREV_9100(ah)) ? (AR_RTC_BASE + 0x0040) : 0x7040)
 #define AR_RTC_RESET_EN		(0x00000001)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/virtual.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/virtual.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/virtual.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/virtual.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,717 +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/slab.h>
-
-#include "ath9k.h"
-
-struct ath9k_vif_iter_data {
-	const u8 *hw_macaddr;
-	u8 mask[ETH_ALEN];
-};
-
-static void ath9k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
-{
-	struct ath9k_vif_iter_data *iter_data = data;
-	int i;
-
-	for (i = 0; i < ETH_ALEN; i++)
-		iter_data->mask[i] &= ~(iter_data->hw_macaddr[i] ^ mac[i]);
-}
-
-void ath9k_set_bssid_mask(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	struct ath9k_vif_iter_data iter_data;
-	int i;
-
-	/*
-	 * Use the hardware MAC address as reference, the hardware uses it
-	 * together with the BSSID mask when matching addresses.
-	 */
-	iter_data.hw_macaddr = common->macaddr;
-	memset(&iter_data.mask, 0xff, ETH_ALEN);
-
-	if (vif)
-		ath9k_vif_iter(&iter_data, vif->addr, vif);
-
-	/* 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);
-
-	memcpy(common->bssidmask, iter_data.mask, ETH_ALEN);
-	ath_hw_setbssidmask(common);
-}
-
-int ath9k_wiphy_add(struct ath_softc *sc)
-{
-	int i, error;
-	struct ath_wiphy *aphy;
-	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
-	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;
-	aphy->last_rssi = ATH_RSSI_DUMMY_MARKER;
-	spin_unlock_bh(&sc->wiphy_lock);
-
-	memcpy(addr, common->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);
-
-	ath9k_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_map[WME_AC_VO];
-	txctl.frame_type = ps ? ATH9K_IFT_PAUSE : ATH9K_IFT_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_common *common = ath9k_hw_common(sc->sc_ah);
-	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]);
-
-	/* sync hw configuration for hw code */
-	common->hw = aphy->hw;
-
-	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, int ftype)
-{
-	struct ath_wiphy *aphy = hw->priv;
-	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
-
-	if (ftype == ATH9K_IFT_PAUSE && aphy->state == ATH_WIPHY_PAUSING) {
-		if (!(tx_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.
-			 */
-			ieee80211_queue_work(aphy->sc->hw,
-				   &aphy->sc->chan_work);
-		}
-	}
-
-	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))
-		ieee80211_queue_work(sc->hw, &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, aphy->hw);
-			ath_radio_enable(sc, aphy->hw);
-			/* Only the primary wiphy hw is used for queuing work */
-			ieee80211_queue_work(aphy->sc->hw,
-				   &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 */
-		ieee80211_queue_work(aphy->sc->hw, &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");
-	}
-
-	ieee80211_queue_delayed_work(sc->hw,
-				     &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)
-		ieee80211_queue_delayed_work(sc->hw, &sc->wiphy_work,
-					     sc->wiphy_scheduler_int);
-}
-
-/* caller must hold wiphy_lock */
-bool ath9k_all_wiphys_idle(struct ath_softc *sc)
-{
-	unsigned int i;
-	if (!sc->pri_wiphy->idle)
-		return false;
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (!aphy)
-			continue;
-		if (!aphy->idle)
-			return false;
-	}
-	return true;
-}
-
-/* caller must hold wiphy_lock */
-void ath9k_set_wiphy_idle(struct ath_wiphy *aphy, bool idle)
-{
-	struct ath_softc *sc = aphy->sc;
-
-	aphy->idle = idle;
-	ath_dbg(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
-		"Marking %s as %sidle\n",
-		wiphy_name(aphy->hw->wiphy), idle ? "" : "not-");
-}
-/* Only bother starting a queue on an active virtual wiphy */
-bool ath_mac80211_start_queue(struct ath_softc *sc, u16 skb_queue)
-{
-	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
-	unsigned int i;
-	bool txq_started = false;
-
-	spin_lock_bh(&sc->wiphy_lock);
-
-	/* Start the primary wiphy */
-	if (sc->pri_wiphy->state == ATH_WIPHY_ACTIVE) {
-		ieee80211_wake_queue(hw, skb_queue);
-		txq_started = true;
-		goto unlock;
-	}
-
-	/* Now start the secondary wiphy queues */
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (!aphy)
-			continue;
-		if (aphy->state != ATH_WIPHY_ACTIVE)
-			continue;
-
-		hw = aphy->hw;
-		ieee80211_wake_queue(hw, skb_queue);
-		txq_started = true;
-		break;
-	}
-
-unlock:
-	spin_unlock_bh(&sc->wiphy_lock);
-	return txq_started;
-}
-
-/* Go ahead and propagate information to all virtual wiphys, it won't hurt */
-void ath_mac80211_stop_queue(struct ath_softc *sc, u16 skb_queue)
-{
-	struct ieee80211_hw *hw = sc->pri_wiphy->hw;
-	unsigned int i;
-
-	spin_lock_bh(&sc->wiphy_lock);
-
-	/* Stop the primary wiphy */
-	ieee80211_stop_queue(hw, skb_queue);
-
-	/* Now stop the secondary wiphy queues */
-	for (i = 0; i < sc->num_sec_wiphy; i++) {
-		struct ath_wiphy *aphy = sc->sec_wiphy[i];
-		if (!aphy)
-			continue;
-		hw = aphy->hw;
-		ieee80211_stop_queue(hw, skb_queue);
-	}
-	spin_unlock_bh(&sc->wiphy_lock);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/wmi.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/wmi.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -123,12 +123,8 @@
 void ath9k_swba_tasklet(unsigned long data)
 {
 	struct ath9k_htc_priv *priv = (struct ath9k_htc_priv *)data;
-	struct ath_common *common = ath9k_hw_common(priv->ah);
-
-	ath_dbg(common, ATH_DBG_WMI, "SWBA Event received\n");
 
 	ath9k_htc_swba(priv, priv->wmi->beacon_pending);
-
 }
 
 void ath9k_fatal_work(struct work_struct *work)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/xmit.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/xmit.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath9k/xmit.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,6 @@
 
 #define BITS_PER_BYTE           8
 #define OFDM_PLCP_BITS          22
-#define HT_RC_2_MCS(_rc)        ((_rc) & 0x1f)
 #define HT_RC_2_STREAMS(_rc)    ((((_rc) & 0x78) >> 3) + 1)
 #define L_STF                   8
 #define L_LTF                   8
@@ -32,7 +31,6 @@
 #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 u16 bits_per_symbol[][2] = {
 	/* 20MHz 40MHz */
@@ -57,8 +55,9 @@
 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, int len);
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
-			     int nframes, int nbad, int txok, bool update_rc);
+static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+			     struct ath_tx_status *ts, int nframes, int nbad,
+			     int txok, bool update_rc);
 static void ath_tx_update_baw(struct ath_softc *sc, struct ath_atx_tid *tid,
 			      int seqno);
 
@@ -167,9 +166,9 @@
 		fi = get_frame_info(bf->bf_mpdu);
 		if (fi->retries) {
 			ath_tx_update_baw(sc, tid, fi->seqno);
-			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
+			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
 		} else {
-			ath_tx_send_normal(sc, txq, tid, &bf_head);
+			ath_tx_send_normal(sc, txq, NULL, &bf_head);
 		}
 		spin_lock_bh(&txq->axq_lock);
 	}
@@ -297,7 +296,6 @@
 
 	ATH_TXBUF_RESET(tbf);
 
-	tbf->aphy = bf->aphy;
 	tbf->bf_mpdu = bf->bf_mpdu;
 	tbf->bf_buf_addr = bf->bf_buf_addr;
 	memcpy(tbf->bf_desc, bf->bf_desc, sc->sc_ah->caps.tx_desc_len);
@@ -345,7 +343,7 @@
 	struct ath_node *an = NULL;
 	struct sk_buff *skb;
 	struct ieee80211_sta *sta;
-	struct ieee80211_hw *hw;
+	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_hdr *hdr;
 	struct ieee80211_tx_info *tx_info;
 	struct ath_atx_tid *tid = NULL;
@@ -364,7 +362,6 @@
 	hdr = (struct ieee80211_hdr *)skb->data;
 
 	tx_info = IEEE80211_SKB_CB(skb);
-	hw = bf->aphy->hw;
 
 	memcpy(rates, tx_info->control.rates, sizeof(rates));
 
@@ -383,7 +380,7 @@
 			    !bf->bf_stale || bf_next != NULL)
 				list_move_tail(&bf->list, &bf_head);
 
-			ath_tx_rc_status(bf, ts, 1, 1, 0, false);
+			ath_tx_rc_status(sc, bf, ts, 1, 1, 0, false);
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
 				0, 0);
 
@@ -429,7 +426,7 @@
 
 	ath_tx_count_frames(sc, bf, ts, txok, &nframes, &nbad);
 	while (bf) {
-		txfail = txpending = 0;
+		txfail = txpending = sendbar = 0;
 		bf_next = bf->bf_next;
 
 		skb = bf->bf_mpdu;
@@ -489,10 +486,10 @@
 
 			if (rc_update && (acked_cnt == 1 || txfail_cnt == 1)) {
 				memcpy(tx_info->control.rates, rates, sizeof(rates));
-				ath_tx_rc_status(bf, ts, nframes, nbad, txok, true);
+				ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, true);
 				rc_update = false;
 			} else {
-				ath_tx_rc_status(bf, ts, nframes, nbad, txok, false);
+				ath_tx_rc_status(sc, bf, ts, nframes, nbad, txok, false);
 			}
 
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, ts,
@@ -516,7 +513,7 @@
 
 						bf->bf_state.bf_type |=
 							BUF_XRETRY;
-						ath_tx_rc_status(bf, ts, nframes,
+						ath_tx_rc_status(sc, bf, ts, nframes,
 								nbad, 0, false);
 						ath_tx_complete_buf(sc, bf, txq,
 								    &bf_head,
@@ -566,8 +563,11 @@
 
 	rcu_read_unlock();
 
-	if (needreset)
+	if (needreset) {
+		spin_unlock_bh(&sc->sc_pcu_lock);
 		ath_reset(sc, false);
+		spin_lock_bh(&sc->sc_pcu_lock);
+	}
 }
 
 static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
@@ -628,8 +628,8 @@
 				 (u32)ATH_AMPDU_LIMIT_MAX);
 
 	/*
-	 * h/w can accept aggregates upto 16 bit lengths (65535).
-	 * The IE, however can hold upto 65536, which shows up here
+	 * h/w can accept aggregates up to 16 bit lengths (65535).
+	 * The IE, however can hold up to 65536, which shows up here
 	 * as zero. Ignore 65536 since we  are constrained by hw.
 	 */
 	if (tid->an->maxampdu)
@@ -856,7 +856,10 @@
 
 	txtid->state |= AGGR_ADDBA_PROGRESS;
 	txtid->paused = true;
-	*ssn = txtid->seq_start;
+	*ssn = txtid->seq_start = txtid->seq_next;
+
+	memset(txtid->tx_buf, 0, sizeof(txtid->tx_buf));
+	txtid->baw_head = txtid->baw_tail = 0;
 
 	return 0;
 }
@@ -942,7 +945,7 @@
 		[WME_AC_VI] = ATH_TXQ_AC_VI,
 		[WME_AC_VO] = ATH_TXQ_AC_VO,
 	};
-	int qnum, i;
+	int axq_qnum, i;
 
 	memset(&qi, 0, sizeof(qi));
 	qi.tqi_subtype = subtype_txq_to_hwq[subtype];
@@ -976,24 +979,25 @@
 			qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
 					TXQ_FLAG_TXDESCINT_ENABLE;
 	}
-	qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
-	if (qnum == -1) {
+	axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
+	if (axq_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)) {
+	if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
 		ath_err(common, "qnum %u out of range, max %zu!\n",
-			qnum, ARRAY_SIZE(sc->tx.txq));
-		ath9k_hw_releasetxqueue(ah, qnum);
+			axq_qnum, ARRAY_SIZE(sc->tx.txq));
+		ath9k_hw_releasetxqueue(ah, axq_qnum);
 		return NULL;
 	}
-	if (!ATH_TXQ_SETUP(sc, qnum)) {
-		struct ath_txq *txq = &sc->tx.txq[qnum];
+	if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
+		struct ath_txq *txq = &sc->tx.txq[axq_qnum];
 
-		txq->axq_qnum = qnum;
+		txq->axq_qnum = axq_qnum;
+		txq->mac80211_qnum = -1;
 		txq->axq_link = NULL;
 		INIT_LIST_HEAD(&txq->axq_q);
 		INIT_LIST_HEAD(&txq->axq_acq);
@@ -1001,14 +1005,14 @@
 		txq->axq_depth = 0;
 		txq->axq_ampdu_depth = 0;
 		txq->axq_tx_inprogress = false;
-		sc->tx.txqsetup |= 1<<qnum;
+		sc->tx.txqsetup |= 1<<axq_qnum;
 
 		txq->txq_headidx = txq->txq_tailidx = 0;
 		for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
 			INIT_LIST_HEAD(&txq->txq_fifo[i]);
 		INIT_LIST_HEAD(&txq->txq_fifo_pending);
 	}
-	return &sc->tx.txq[qnum];
+	return &sc->tx.txq[axq_qnum];
 }
 
 int ath_txq_update(struct ath_softc *sc, int qnum,
@@ -1051,6 +1055,7 @@
 int ath_cabq_update(struct ath_softc *sc)
 {
 	struct ath9k_tx_queue_info qi;
+	struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 	int qnum = sc->beacon.cabq->axq_qnum;
 
 	ath9k_hw_get_txq_props(sc->sc_ah, qnum, &qi);
@@ -1062,7 +1067,7 @@
 	else if (sc->config.cabqReadytime > ATH9K_READY_TIME_HI_BOUND)
 		sc->config.cabqReadytime = ATH9K_READY_TIME_HI_BOUND;
 
-	qi.tqi_readyTime = (sc->beacon_interval *
+	qi.tqi_readyTime = (cur_conf->beacon_interval *
 			    sc->config.cabqReadytime) / 100;
 	ath_txq_update(sc, qnum, &qi);
 
@@ -1189,24 +1194,31 @@
 	if (sc->sc_flags & SC_OP_INVALID)
 		return true;
 
-	/* Stop beacon queue */
-	ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
+	ath9k_hw_abort_tx_dma(ah);
 
-	/* Stop data queues */
+	/* Check if any queue remains active */
 	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 (!ATH_TXQ_SETUP(sc, i))
+			continue;
+
+		npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
 	}
 
 	if (npend)
 		ath_err(common, "Failed to stop TX DMA!\n");
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
-		if (ATH_TXQ_SETUP(sc, i))
-			ath_draintxq(sc, &sc->tx.txq[i], retry_tx);
+		if (!ATH_TXQ_SETUP(sc, i))
+			continue;
+
+		/*
+		 * The caller will resume queues with ieee80211_wake_queues.
+		 * Mark the queue as not stopped to prevent ath_tx_complete
+		 * from waking the queue too early.
+		 */
+		txq = &sc->tx.txq[i];
+		txq->stopped = false;
+		ath_draintxq(sc, txq, retry_tx);
 	}
 
 	return !npend;
@@ -1218,46 +1230,59 @@
 	sc->tx.txqsetup &= ~(1<<txq->axq_qnum);
 }
 
+/* For each axq_acq entry, for each tid, try to schedule packets
+ * for transmit until ampdu_depth has reached min Q depth.
+ */
 void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
 {
-	struct ath_atx_ac *ac;
-	struct ath_atx_tid *tid;
+	struct ath_atx_ac *ac, *ac_tmp, *last_ac;
+	struct ath_atx_tid *tid, *last_tid;
 
-	if (list_empty(&txq->axq_acq))
+	if (list_empty(&txq->axq_acq) ||
+	    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
 		return;
 
 	ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list);
-	list_del(&ac->list);
-	ac->sched = false;
+	last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list);
 
-	do {
-		if (list_empty(&ac->tid_q))
-			return;
+	list_for_each_entry_safe(ac, ac_tmp, &txq->axq_acq, list) {
+		last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list);
+		list_del(&ac->list);
+		ac->sched = false;
 
-		tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, list);
-		list_del(&tid->list);
-		tid->sched = false;
+		while (!list_empty(&ac->tid_q)) {
+			tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
+					       list);
+			list_del(&tid->list);
+			tid->sched = false;
 
-		if (tid->paused)
-			continue;
+			if (tid->paused)
+				continue;
 
-		ath_tx_sched_aggr(sc, txq, tid);
+			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);
+			/*
+			 * 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 (tid == last_tid ||
+			    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+				break;
+		}
 
-	if (!list_empty(&ac->tid_q)) {
-		if (!ac->sched) {
-			ac->sched = true;
-			list_add_tail(&ac->list, &txq->axq_acq);
+		if (!list_empty(&ac->tid_q)) {
+			if (!ac->sched) {
+				ac->sched = true;
+				list_add_tail(&ac->list, &txq->axq_acq);
+			}
 		}
+
+		if (ac == last_ac ||
+		    txq->axq_ampdu_depth >= ATH_AGGR_MIN_QDEPTH)
+			return;
 	}
 }
 
@@ -1301,6 +1326,7 @@
 		INIT_LIST_HEAD(&txq->txq_fifo[txq->txq_headidx]);
 		list_splice_init(head, &txq->txq_fifo[txq->txq_headidx]);
 		INCR(txq->txq_headidx, ATH_TXFIFO_DEPTH);
+		TX_STAT_INC(txq->axq_qnum, puttxbuf);
 		ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
 		ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
 			txq->axq_qnum, ito64(bf->bf_daddr), bf->bf_desc);
@@ -1308,6 +1334,7 @@
 		list_splice_tail_init(head, &txq->axq_q);
 
 		if (txq->axq_link == NULL) {
+			TX_STAT_INC(txq->axq_qnum, puttxbuf);
 			ath9k_hw_puttxbuf(ah, txq->axq_qnum, bf->bf_daddr);
 			ath_dbg(common, ATH_DBG_XMIT, "TXDP[%u] = %llx (%p)\n",
 				txq->axq_qnum, ito64(bf->bf_daddr),
@@ -1321,6 +1348,7 @@
 		}
 		ath9k_hw_get_desc_link(ah, bf->bf_lastbf->bf_desc,
 				       &txq->axq_link);
+		TX_STAT_INC(txq->axq_qnum, txstart);
 		ath9k_hw_txstart(ah, txq->axq_qnum);
 	}
 	txq->axq_depth++;
@@ -1335,7 +1363,6 @@
 	struct list_head bf_head;
 
 	bf->bf_state.bf_type |= BUF_AMPDU;
-	TX_STAT_INC(txctl->txq->axq_qnum, a_queued);
 
 	/*
 	 * Do not queue to h/w when any of the following conditions is true:
@@ -1351,6 +1378,7 @@
 		 * Add this frame to software queue for scheduling later
 		 * for aggregation.
 		 */
+		TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
 		list_add_tail(&bf->list, &tid->buf_q);
 		ath_tx_queue_tid(txctl->txq, tid);
 		return;
@@ -1364,6 +1392,7 @@
 		ath_tx_addto_baw(sc, tid, fi->seqno);
 
 	/* Queue to h/w without aggregation */
+	TX_STAT_INC(txctl->txq->axq_qnum, a_queued_hw);
 	bf->bf_lastbf = bf;
 	ath_buf_set_rate(sc, bf, fi->framelen);
 	ath_tx_txqaddbuf(sc, txctl->txq, &bf_head);
@@ -1416,8 +1445,7 @@
 static void setup_frame_info(struct ieee80211_hw *hw, struct sk_buff *skb,
 			     int framelen)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = tx_info->control.sta;
 	struct ieee80211_key_conf *hw_key = tx_info->control.hw_key;
@@ -1635,8 +1663,7 @@
 					   struct ath_txq *txq,
 					   struct sk_buff *skb)
 {
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_hw *ah = sc->sc_ah;
 	struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 	struct ath_frame_info *fi = get_frame_info(skb);
@@ -1652,7 +1679,6 @@
 
 	ATH_TXBUF_RESET(bf);
 
-	bf->aphy = aphy;
 	bf->bf_flags = setup_tx_flags(skb);
 	bf->bf_mpdu = skb;
 
@@ -1699,8 +1725,8 @@
 	u8 tidno;
 
 	spin_lock_bh(&txctl->txq->axq_lock);
-
-	if (ieee80211_is_data_qos(hdr->frame_control) && txctl->an) {
+	if ((sc->sc_flags & SC_OP_TXAGGR) && txctl->an &&
+		ieee80211_is_data_qos(hdr->frame_control)) {
 		tidno = ieee80211_get_qos_ctl(hdr)[0] &
 			IEEE80211_QOS_CTL_TID_MASK;
 		tid = ATH_AN_2_TID(txctl->an, tidno);
@@ -1741,8 +1767,7 @@
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_sta *sta = info->control.sta;
-	struct ath_wiphy *aphy = hw->priv;
-	struct ath_softc *sc = aphy->sc;
+	struct ath_softc *sc = hw->priv;
 	struct ath_txq *txq = txctl->txq;
 	struct ath_buf *bf;
 	int padpos, padsize;
@@ -1794,7 +1819,7 @@
 	spin_lock_bh(&txq->axq_lock);
 	if (txq == sc->tx.txq_map[q] &&
 	    ++txq->pending_frames > ATH_MAX_QDEPTH && !txq->stopped) {
-		ath_mac80211_stop_queue(sc, q);
+		ieee80211_stop_queue(sc->hw, q);
 		txq->stopped = 1;
 	}
 	spin_unlock_bh(&txq->axq_lock);
@@ -1809,8 +1834,7 @@
 /*****************/
 
 static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
-			    struct ath_wiphy *aphy, int tx_flags, int ftype,
-			    struct ath_txq *txq)
+			    int tx_flags, int ftype, struct ath_txq *txq)
 {
 	struct ieee80211_hw *hw = sc->hw;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1820,9 +1844,6 @@
 
 	ath_dbg(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);
 
-	if (aphy)
-		hw = aphy->hw;
-
 	if (tx_flags & ATH_TX_BAR)
 		tx_info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
 
@@ -1852,19 +1873,20 @@
 					PS_WAIT_FOR_TX_ACK));
 	}
 
-	if (unlikely(ftype))
-		ath9k_tx_status(hw, skb, ftype);
-	else {
-		q = skb_get_queue_mapping(skb);
-		if (txq == sc->tx.txq_map[q]) {
-			spin_lock_bh(&txq->axq_lock);
-			if (WARN_ON(--txq->pending_frames < 0))
-				txq->pending_frames = 0;
-			spin_unlock_bh(&txq->axq_lock);
-		}
+	q = skb_get_queue_mapping(skb);
+	if (txq == sc->tx.txq_map[q]) {
+		spin_lock_bh(&txq->axq_lock);
+		if (WARN_ON(--txq->pending_frames < 0))
+			txq->pending_frames = 0;
 
-		ieee80211_tx_status(hw, skb);
+		if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
+			ieee80211_wake_queue(sc->hw, q);
+			txq->stopped = 0;
+		}
+		spin_unlock_bh(&txq->axq_lock);
 	}
+
+	ieee80211_tx_status(hw, skb);
 }
 
 static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
@@ -1896,8 +1918,8 @@
 		else
 			complete(&sc->paprd_complete);
 	} else {
-		ath_debug_stat_tx(sc, bf, ts);
-		ath_tx_complete(sc, skb, bf->aphy, tx_flags,
+		ath_debug_stat_tx(sc, bf, ts, txq);
+		ath_tx_complete(sc, skb, tx_flags,
 				bf->bf_state.bfs_ftype, txq);
 	}
 	/* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
@@ -1913,14 +1935,14 @@
 	spin_unlock_irqrestore(&sc->tx.txbuflock, flags);
 }
 
-static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
-			     int nframes, int nbad, int txok, bool update_rc)
+static void ath_tx_rc_status(struct ath_softc *sc, struct ath_buf *bf,
+			     struct ath_tx_status *ts, int nframes, 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 ieee80211_hw *hw = bf->aphy->hw;
-	struct ath_softc *sc = bf->aphy->sc;
+	struct ieee80211_hw *hw = sc->hw;
 	struct ath_hw *ah = sc->sc_ah;
 	u8 i, tx_rateindex;
 
@@ -1971,19 +1993,6 @@
 	tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
 }
 
-static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum)
-{
-	struct ath_txq *txq;
-
-	txq = sc->tx.txq_map[qnum];
-	spin_lock_bh(&txq->axq_lock);
-	if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
-		if (ath_mac80211_start_queue(sc, 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;
@@ -1994,7 +2003,6 @@
 	struct ath_tx_status ts;
 	int txok;
 	int status;
-	int qnum;
 
 	ath_dbg(common, ATH_DBG_QUEUE, "tx queue %d (%x), link %p\n",
 		txq->axq_qnum, ath9k_hw_gettxbuf(sc->sc_ah, txq->axq_qnum),
@@ -2004,6 +2012,8 @@
 		spin_lock_bh(&txq->axq_lock);
 		if (list_empty(&txq->axq_q)) {
 			txq->axq_link = NULL;
+			if (sc->sc_flags & SC_OP_TXAGGR)
+				ath_txq_schedule(sc, txq);
 			spin_unlock_bh(&txq->axq_lock);
 			break;
 		}
@@ -2038,6 +2048,7 @@
 			spin_unlock_bh(&txq->axq_lock);
 			break;
 		}
+		TX_STAT_INC(txq->axq_qnum, txprocdesc);
 
 		/*
 		 * Remove ath_buf's of the same transmit unit from txq,
@@ -2058,6 +2069,7 @@
 
 		if (bf_is_ampdu_not_probing(bf))
 			txq->axq_ampdu_depth--;
+
 		spin_unlock_bh(&txq->axq_lock);
 
 		if (bf_held)
@@ -2070,27 +2082,45 @@
 			 */
 			if (ts.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &ts, 1, txok ? 0 : 1, txok, true);
+			ath_tx_rc_status(sc, bf, &ts, 1, txok ? 0 : 1, txok, true);
 		}
 
-		qnum = skb_get_queue_mapping(bf->bf_mpdu);
-
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &ts, txok,
 					     true);
 		else
 			ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
 
-		if (txq == sc->tx.txq_map[qnum])
-			ath_wake_mac80211_queue(sc, qnum);
-
 		spin_lock_bh(&txq->axq_lock);
+
 		if (sc->sc_flags & SC_OP_TXAGGR)
 			ath_txq_schedule(sc, txq);
 		spin_unlock_bh(&txq->axq_lock);
 	}
 }
 
+static void ath_hw_pll_work(struct work_struct *work)
+{
+	struct ath_softc *sc = container_of(work, struct ath_softc,
+					    hw_pll_work.work);
+	static int count;
+
+	if (AR_SREV_9485(sc->sc_ah)) {
+		if (ar9003_get_pll_sqsum_dvc(sc->sc_ah) >= 0x40000) {
+			count++;
+
+			if (count == 3) {
+				/* Rx is hung for more than 500ms. Reset it */
+				ath_reset(sc, true);
+				count = 0;
+			}
+		} else
+			count = 0;
+
+		ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/5);
+	}
+}
+
 static void ath_tx_complete_poll_work(struct work_struct *work)
 {
 	struct ath_softc *sc = container_of(work, struct ath_softc,
@@ -2098,6 +2128,9 @@
 	struct ath_txq *txq;
 	int i;
 	bool needreset = false;
+#ifdef CONFIG_ATH9K_DEBUGFS
+	sc->tx_complete_poll_work_seen++;
+#endif
 
 	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
 		if (ATH_TXQ_SETUP(sc, i)) {
@@ -2111,6 +2144,33 @@
 				} else {
 					txq->axq_tx_inprogress = true;
 				}
+			} else {
+				/* If the queue has pending buffers, then it
+				 * should be doing tx work (and have axq_depth).
+				 * Shouldn't get to this state I think..but
+				 * we do.
+				 */
+				if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
+				    (txq->pending_frames > 0 ||
+				     !list_empty(&txq->axq_acq) ||
+				     txq->stopped)) {
+					ath_err(ath9k_hw_common(sc->sc_ah),
+						"txq: %p axq_qnum: %u,"
+						" mac80211_qnum: %i"
+						" axq_link: %p"
+						" pending frames: %i"
+						" axq_acq empty: %i"
+						" stopped: %i"
+						" axq_depth: 0  Attempting to"
+						" restart tx logic.\n",
+						txq, txq->axq_qnum,
+						txq->mac80211_qnum,
+						txq->axq_link,
+						txq->pending_frames,
+						list_empty(&txq->axq_acq),
+						txq->stopped);
+					ath_txq_schedule(sc, txq);
+				}
 			}
 			spin_unlock_bh(&txq->axq_lock);
 		}
@@ -2150,7 +2210,6 @@
 	struct list_head bf_head;
 	int status;
 	int txok;
-	int qnum;
 
 	for (;;) {
 		status = ath9k_hw_txprocdesc(ah, NULL, (void *)&txs);
@@ -2193,11 +2252,9 @@
 		if (!bf_isampdu(bf)) {
 			if (txs.ts_status & ATH9K_TXERR_XRETRY)
 				bf->bf_state.bf_type |= BUF_XRETRY;
-			ath_tx_rc_status(bf, &txs, 1, txok ? 0 : 1, txok, true);
+			ath_tx_rc_status(sc, bf, &txs, 1, txok ? 0 : 1, txok, true);
 		}
 
-		qnum = skb_get_queue_mapping(bf->bf_mpdu);
-
 		if (bf_isampdu(bf))
 			ath_tx_complete_aggr(sc, txq, bf, &bf_head, &txs,
 					     txok, true);
@@ -2205,19 +2262,19 @@
 			ath_tx_complete_buf(sc, bf, txq, &bf_head,
 					    &txs, txok, 0);
 
-		if (txq == sc->tx.txq_map[qnum])
-			ath_wake_mac80211_queue(sc, qnum);
-
 		spin_lock_bh(&txq->axq_lock);
+
 		if (!list_empty(&txq->txq_fifo_pending)) {
 			INIT_LIST_HEAD(&bf_head);
 			bf = list_first_entry(&txq->txq_fifo_pending,
-				struct ath_buf, list);
-			list_cut_position(&bf_head, &txq->txq_fifo_pending,
-				&bf->bf_lastbf->list);
+					      struct ath_buf, list);
+			list_cut_position(&bf_head,
+					  &txq->txq_fifo_pending,
+					  &bf->bf_lastbf->list);
 			ath_tx_txqaddbuf(sc, txq, &bf_head);
 		} else if (sc->sc_flags & SC_OP_TXAGGR)
 			ath_txq_schedule(sc, txq);
+
 		spin_unlock_bh(&txq->axq_lock);
 	}
 }
@@ -2285,6 +2342,7 @@
 	}
 
 	INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
+	INIT_DELAYED_WORK(&sc->hw_pll_work, ath_hw_pll_work);
 
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
 		error = ath_tx_edma_init(sc);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/ath.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/ath.h	2011-05-19 00:06:34.000000000 -0400
@@ -108,12 +108,14 @@
  * struct ath_ops - Register read/write operations
  *
  * @read: Register read
+ * @multi_read: Multiple register read
  * @write: Register write
  * @enable_write_buffer: Enable multiple register writes
  * @write_flush: flush buffered register writes and disable buffering
  */
 struct ath_ops {
 	unsigned int (*read)(void *, u32 reg_offset);
+	void (*multi_read)(void *, u32 *addr, u32 *val, u16 count);
 	void (*write)(void *, u32 val, u32 reg_offset);
 	void (*enable_write_buffer)(void *);
 	void (*write_flush) (void *);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/carl9170.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/carl9170.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/carl9170.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/carl9170.h	2011-05-19 00:06:34.000000000 -0400
@@ -161,7 +161,7 @@
  * Naturally: The higher the limit, the faster the device CAN send.
  * However, even a slight over-commitment at the wrong time and the
  * hardware is doomed to send all already-queued frames at suboptimal
- * rates. This in turn leads to an enourmous amount of unsuccessful
+ * rates. This in turn leads to an enormous amount of unsuccessful
  * retries => Latency goes up, whereas the throughput goes down. CRASH!
  */
 #define CARL9170_NUM_TX_LIMIT_HARD	((AR9170_TXQ_DEPTH * 3) / 2)
@@ -283,6 +283,7 @@
 		unsigned int mem_blocks;
 		unsigned int mem_block_size;
 		unsigned int rx_size;
+		unsigned int tx_seq_table;
 	} fw;
 
 	/* reset / stuck frames/queue detection */
@@ -442,6 +443,7 @@
 	u8 ampdu_len;
 	u8 ampdu_ack_len;
 	bool clear;
+	bool req;
 };
 
 struct carl9170_sta_info {
@@ -533,7 +535,7 @@
 void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len);
 
 /* TX */
-int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 void carl9170_tx_janitor(struct work_struct *work);
 void carl9170_tx_process_status(struct ar9170 *ar,
 				const struct carl9170_rsp *cmd);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/fw.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/fw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/fw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/fw.c	2011-05-19 00:06:34.000000000 -0400
@@ -150,6 +150,7 @@
 	const struct carl9170fw_otus_desc *otus_desc;
 	const struct carl9170fw_chk_desc *chk_desc;
 	const struct carl9170fw_last_desc *last_desc;
+	const struct carl9170fw_txsq_desc *txsq_desc;
 
 	last_desc = carl9170_fw_find_desc(ar, LAST_MAGIC,
 		sizeof(*last_desc), CARL9170FW_LAST_DESC_CUR_VER);
@@ -264,6 +265,9 @@
 			FIF_PROMISC_IN_BSS;
 	}
 
+	if (SUPP(CARL9170FW_WOL))
+		device_set_wakeup_enable(&ar->udev->dev, true);
+
 	ar->fw.vif_num = otus_desc->vif_num;
 	ar->fw.cmd_bufs = otus_desc->cmd_bufs;
 	ar->fw.address = le32_to_cpu(otus_desc->fw_address);
@@ -296,6 +300,17 @@
 		}
 	}
 
+	txsq_desc = carl9170_fw_find_desc(ar, TXSQ_MAGIC,
+		sizeof(*txsq_desc), CARL9170FW_TXSQ_DESC_CUR_VER);
+
+	if (txsq_desc) {
+		ar->fw.tx_seq_table = le32_to_cpu(txsq_desc->seq_table_addr);
+		if (!valid_cpu_addr(ar->fw.tx_seq_table))
+			return -EINVAL;
+	} else {
+		ar->fw.tx_seq_table = 0;
+	}
+
 #undef SUPPORTED
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/fwcmd.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/fwcmd.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/fwcmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/fwcmd.h	2011-05-19 00:06:34.000000000 -0400
@@ -167,6 +167,7 @@
 #define CARL9170_RX_FILTER_CTL_BACKR	0x20
 #define CARL9170_RX_FILTER_MGMT		0x40
 #define CARL9170_RX_FILTER_DATA		0x80
+#define CARL9170_RX_FILTER_EVERYTHING	(~0)
 
 struct carl9170_bcn_ctrl_cmd {
 	__le32		vif_id;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/fwdesc.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/fwdesc.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/fwdesc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/fwdesc.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,6 +69,9 @@
 	/* Firmware RX filter | CARL9170_CMD_RX_FILTER */
 	CARL9170FW_RX_FILTER,
 
+	/* Wake up on WLAN */
+	CARL9170FW_WOL,
+
 	/* KEEP LAST */
 	__CARL9170FW_FEATURE_NUM
 };
@@ -78,6 +81,7 @@
 #define FIX_MAGIC	"FIX\0"
 #define DBG_MAGIC	"DBG\0"
 #define CHK_MAGIC	"CHK\0"
+#define TXSQ_MAGIC	"TXSQ"
 #define LAST_MAGIC	"LAST"
 
 #define CARL9170FW_SET_DAY(d) (((d) - 1) % 31)
@@ -88,8 +92,10 @@
 #define CARL9170FW_GET_MONTH(m) ((((m) / 31) % 12) + 1)
 #define CARL9170FW_GET_YEAR(y) ((y) / 372 + 10)
 
+#define CARL9170FW_MAGIC_SIZE			4
+
 struct carl9170fw_desc_head {
-	u8	magic[4];
+	u8	magic[CARL9170FW_MAGIC_SIZE];
 	__le16 length;
 	u8 min_ver;
 	u8 cur_ver;
@@ -170,6 +176,16 @@
 #define CARL9170FW_CHK_DESC_SIZE			\
 	(sizeof(struct carl9170fw_chk_desc))
 
+#define CARL9170FW_TXSQ_DESC_MIN_VER			1
+#define CARL9170FW_TXSQ_DESC_CUR_VER			1
+struct carl9170fw_txsq_desc {
+	struct carl9170fw_desc_head head;
+
+	__le32 seq_table_addr;
+} __packed;
+#define CARL9170FW_TXSQ_DESC_SIZE			\
+	(sizeof(struct carl9170fw_txsq_desc))
+
 #define CARL9170FW_LAST_DESC_MIN_VER			1
 #define CARL9170FW_LAST_DESC_CUR_VER			2
 struct carl9170fw_last_desc {
@@ -189,8 +205,8 @@
 	}
 
 static inline void carl9170fw_fill_desc(struct carl9170fw_desc_head *head,
-					 u8 magic[4], __le16 length,
-					 u8 min_ver, u8 cur_ver)
+					 u8 magic[CARL9170FW_MAGIC_SIZE],
+					 __le16 length, u8 min_ver, u8 cur_ver)
 {
 	head->magic[0] = magic[0];
 	head->magic[1] = magic[1];
@@ -204,7 +220,7 @@
 
 #define carl9170fw_for_each_hdr(desc, fw_desc)				\
 	for (desc = fw_desc;						\
-	     memcmp(desc->magic, LAST_MAGIC, 4) &&			\
+	     memcmp(desc->magic, LAST_MAGIC, CARL9170FW_MAGIC_SIZE) &&	\
 	     le16_to_cpu(desc->length) >= CARL9170FW_DESC_HEAD_SIZE &&	\
 	     le16_to_cpu(desc->length) < CARL9170FW_DESC_MAX_LENGTH;	\
 	     desc = (void *)((unsigned long)desc + le16_to_cpu(desc->length)))
@@ -218,8 +234,8 @@
 }
 
 static inline bool carl9170fw_desc_cmp(const struct carl9170fw_desc_head *head,
-				       const u8 descid[4], u16 min_len,
-				       u8 compatible_revision)
+				       const u8 descid[CARL9170FW_MAGIC_SIZE],
+				       u16 min_len, u8 compatible_revision)
 {
 	if (descid[0] == head->magic[0] && descid[1] == head->magic[1] &&
 	    descid[2] == head->magic[2] && descid[3] == head->magic[3] &&
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -463,6 +463,8 @@
 
 #define	AR9170_PWR_REG_CHIP_REVISION		(AR9170_PWR_REG_BASE + 0x010)
 #define AR9170_PWR_REG_PLL_ADDAC		(AR9170_PWR_REG_BASE + 0x014)
+#define		AR9170_PWR_PLL_ADDAC_DIV_S		2
+#define		AR9170_PWR_PLL_ADDAC_DIV		0xffc
 #define	AR9170_PWR_REG_WATCH_DOG_MAGIC		(AR9170_PWR_REG_BASE + 0x020)
 
 /* Faraday USB Controller */
@@ -471,6 +473,9 @@
 #define	AR9170_USB_REG_MAIN_CTRL		(AR9170_USB_REG_BASE + 0x000)
 #define		AR9170_USB_MAIN_CTRL_REMOTE_WAKEUP	BIT(0)
 #define		AR9170_USB_MAIN_CTRL_ENABLE_GLOBAL_INT	BIT(2)
+#define		AR9170_USB_MAIN_CTRL_GO_TO_SUSPEND	BIT(3)
+#define		AR9170_USB_MAIN_CTRL_RESET		BIT(4)
+#define		AR9170_USB_MAIN_CTRL_CHIP_ENABLE	BIT(5)
 #define		AR9170_USB_MAIN_CTRL_HIGHSPEED		BIT(6)
 
 #define	AR9170_USB_REG_DEVICE_ADDRESS		(AR9170_USB_REG_BASE + 0x001)
@@ -499,6 +504,13 @@
 #define	AR9170_USB_REG_INTR_GROUP		(AR9170_USB_REG_BASE + 0x020)
 
 #define	AR9170_USB_REG_INTR_SOURCE_0		(AR9170_USB_REG_BASE + 0x021)
+#define		AR9170_USB_INTR_SRC0_SETUP		BIT(0)
+#define		AR9170_USB_INTR_SRC0_IN			BIT(1)
+#define		AR9170_USB_INTR_SRC0_OUT		BIT(2)
+#define		AR9170_USB_INTR_SRC0_FAIL		BIT(3) /* ??? */
+#define		AR9170_USB_INTR_SRC0_END		BIT(4) /* ??? */
+#define		AR9170_USB_INTR_SRC0_ABORT		BIT(7)
+
 #define	AR9170_USB_REG_INTR_SOURCE_1		(AR9170_USB_REG_BASE + 0x022)
 #define	AR9170_USB_REG_INTR_SOURCE_2		(AR9170_USB_REG_BASE + 0x023)
 #define	AR9170_USB_REG_INTR_SOURCE_3		(AR9170_USB_REG_BASE + 0x024)
@@ -506,6 +518,15 @@
 #define	AR9170_USB_REG_INTR_SOURCE_5		(AR9170_USB_REG_BASE + 0x026)
 #define	AR9170_USB_REG_INTR_SOURCE_6		(AR9170_USB_REG_BASE + 0x027)
 #define	AR9170_USB_REG_INTR_SOURCE_7		(AR9170_USB_REG_BASE + 0x028)
+#define		AR9170_USB_INTR_SRC7_USB_RESET		BIT(1)
+#define		AR9170_USB_INTR_SRC7_USB_SUSPEND	BIT(2)
+#define		AR9170_USB_INTR_SRC7_USB_RESUME		BIT(3)
+#define		AR9170_USB_INTR_SRC7_ISO_SEQ_ERR	BIT(4)
+#define		AR9170_USB_INTR_SRC7_ISO_SEQ_ABORT	BIT(5)
+#define		AR9170_USB_INTR_SRC7_TX0BYTE		BIT(6)
+#define		AR9170_USB_INTR_SRC7_RX0BYTE		BIT(7)
+
+#define	AR9170_USB_REG_IDLE_COUNT		(AR9170_USB_REG_BASE + 0x02f)
 
 #define	AR9170_USB_REG_EP_MAP			(AR9170_USB_REG_BASE + 0x030)
 #define	AR9170_USB_REG_EP1_MAP			(AR9170_USB_REG_BASE + 0x030)
@@ -581,6 +602,10 @@
 
 #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_USB_REG_WAKE_UP			(AR9170_USB_REG_BASE + 0x120)
+#define		AR9170_USB_WAKE_UP_WAKE			BIT(0)
+
 #define	AR9170_USB_REG_CBUS_CTRL		(AR9170_USB_REG_BASE + 0x1f0)
 #define		AR9170_USB_CBUS_CTRL_BUFFER_END		(BIT(1))
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -662,6 +662,13 @@
 			goto unlock;
 	}
 
+	if (ar->fw.tx_seq_table) {
+		err = carl9170_write_reg(ar, ar->fw.tx_seq_table + vif_id * 4,
+					 0);
+		if (err)
+			goto unlock;
+	}
+
 unlock:
 	if (err && (vif_id >= 0)) {
 		vif_priv->active = false;
@@ -1279,7 +1286,7 @@
 				    struct ieee80211_vif *vif,
 				    enum ieee80211_ampdu_mlme_action action,
 				    struct ieee80211_sta *sta,
-				    u16 tid, u16 *ssn)
+				    u16 tid, u16 *ssn, u8 buf_size)
 {
 	struct ar9170 *ar = hw->priv;
 	struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
@@ -1348,6 +1355,7 @@
 		tid_info = rcu_dereference(sta_info->agg[tid]);
 
 		sta_info->stats[tid].clear = true;
+		sta_info->stats[tid].req = false;
 
 		if (tid_info) {
 			bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -427,7 +427,7 @@
 
 /*
  * initialize some phy regs from eeprom values in modal_header[]
- * acc. to band and bandwith
+ * acc. to band and bandwidth
  */
 static int carl9170_init_phy_from_eeprom(struct ar9170 *ar,
 				bool is_2ghz, bool is_40mhz)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -849,7 +849,7 @@
 				/*
 				 * nested carl9170_rx_stream call!
 				 *
-				 * termination is guranteed, even when the
+				 * termination is guaranteed, even when the
 				 * combined frame also have an element with
 				 * a bad tag.
 				 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -383,6 +383,7 @@
 
 	if (sta_info->stats[tid].clear) {
 		sta_info->stats[tid].clear = false;
+		sta_info->stats[tid].req = false;
 		sta_info->stats[tid].ampdu_len = 0;
 		sta_info->stats[tid].ampdu_ack_len = 0;
 	}
@@ -391,10 +392,16 @@
 	if (txinfo->status.rates[0].count == 1)
 		sta_info->stats[tid].ampdu_ack_len++;
 
+	if (!(txinfo->flags & IEEE80211_TX_STAT_ACK))
+		sta_info->stats[tid].req = true;
+
 	if (super->f.mac_control & cpu_to_le16(AR9170_TX_MAC_IMM_BA)) {
 		super->s.rix = sta_info->stats[tid].ampdu_len;
 		super->s.cnt = sta_info->stats[tid].ampdu_ack_len;
 		txinfo->flags |= IEEE80211_TX_STAT_AMPDU;
+		if (sta_info->stats[tid].req)
+			txinfo->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+
 		sta_info->stats[tid].clear = true;
 	}
 	spin_unlock_bh(&tid_info->lock);
@@ -862,6 +869,9 @@
 	if (unlikely(info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM))
 		txc->s.misc |= CARL9170_TX_SUPER_MISC_CAB;
 
+	if (unlikely(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+		txc->s.misc |= CARL9170_TX_SUPER_MISC_ASSIGN_SEQ;
+
 	if (unlikely(ieee80211_is_probe_resp(hdr->frame_control)))
 		txc->s.misc |= CARL9170_TX_SUPER_MISC_FILL_IN_TSF;
 
@@ -1336,7 +1346,7 @@
 	return false;
 }
 
-int carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void carl9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct ar9170 *ar = hw->priv;
 	struct ieee80211_tx_info *info;
@@ -1370,12 +1380,11 @@
 	}
 
 	carl9170_tx(ar);
-	return NETDEV_TX_OK;
+	return;
 
 err_free:
 	ar->tx_dropped++;
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 void carl9170_tx_scheduler(struct ar9170 *ar)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/usb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -430,7 +430,7 @@
 			 * The system is too slow to cope with
 			 * the enormous workload. We have simply
 			 * run out of active rx urbs and this
-			 * unfortunatly leads to an unpredictable
+			 * unfortunately leads to an unpredictable
 			 * device.
 			 */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/version.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/version.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/version.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/version.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 #ifndef __CARL9170_SHARED_VERSION_H
 #define __CARL9170_SHARED_VERSION_H
-#define CARL9170FW_VERSION_YEAR 10
-#define CARL9170FW_VERSION_MONTH 10
-#define CARL9170FW_VERSION_DAY 29
-#define CARL9170FW_VERSION_GIT "1.9.0"
+#define CARL9170FW_VERSION_YEAR 11
+#define CARL9170FW_VERSION_MONTH 1
+#define CARL9170FW_VERSION_DAY 22
+#define CARL9170FW_VERSION_GIT "1.9.2"
 #endif /* __CARL9170_SHARED_VERSION_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/wlan.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/wlan.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/carl9170/wlan.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/carl9170/wlan.h	2011-05-19 00:06:34.000000000 -0400
@@ -251,7 +251,7 @@
 	u8 ampdu_commit_factor:1;
 	u8 ampdu_unused_bit:1;
 	u8 queue:2;
-	u8 reserved:1;
+	u8 assign_seq:1;
 	u8 vif_id:3;
 	u8 fill_in_tsf:1;
 	u8 cab:1;
@@ -299,6 +299,7 @@
 
 #define CARL9170_TX_SUPER_MISC_QUEUE			0x3
 #define CARL9170_TX_SUPER_MISC_QUEUE_S			0
+#define CARL9170_TX_SUPER_MISC_ASSIGN_SEQ		0x4
 #define	CARL9170_TX_SUPER_MISC_VIF_ID			0x38
 #define	CARL9170_TX_SUPER_MISC_VIF_ID_S			3
 #define	CARL9170_TX_SUPER_MISC_FILL_IN_TSF		0x40
@@ -413,6 +414,23 @@
 	__AR9170_NUM_TXQ,
 };
 
+/*
+ * This is an workaround for several undocumented bugs.
+ * Don't mess with the QoS/AC <-> HW Queue map, if you don't
+ * know what you are doing.
+ *
+ * Known problems [hardware]:
+ *  * The MAC does not aggregate frames on anything other
+ *    than the first HW queue.
+ *  * when an AMPDU is placed [in the first hw queue] and
+ *    additional frames are already queued on a different
+ *    hw queue, the MAC will ALWAYS freeze.
+ *
+ * In a nutshell: The hardware can either do QoS or
+ * Aggregation but not both at the same time. As a
+ * result, this makes the device pretty much useless
+ * for any serious 802.11n setup.
+ */
 static const u8 ar9170_qmap[__AR9170_NUM_TXQ] = { 2, 1, 0, 3 };
 
 #define	AR9170_TXQ_DEPTH			32
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/hw.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
  * 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
+ * will not pass our check. This is because 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.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/key.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/key.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/key.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/key.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,8 +58,11 @@
 		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 (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED)
+		if (common->crypt_caps & ATH_CRYPT_CAP_MIC_COMBINED) {
 			REG_WRITE(ah, AR_KEYTABLE_KEY4(micentry), 0);
+			REG_WRITE(ah, AR_KEYTABLE_TYPE(micentry),
+				  AR_KEYTABLE_TYPE_CLR);
+		}
 
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd.c linux-libre-2.6.39-gnu/drivers/net/wireless/ath/regd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/regd.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,6 +158,13 @@
 	}
 }
 
+bool ath_is_49ghz_allowed(u16 regdomain)
+{
+	/* possibly more */
+	return regdomain == MKK9_MKKC;
+}
+EXPORT_SYMBOL(ath_is_49ghz_allowed);
+
 /* Frequency is one where radar detection is required */
 static bool ath_is_radar_freq(u16 center_freq)
 {
@@ -261,7 +268,7 @@
 	}
 
 	/*
-	 * If a country IE has been recieved check its rule for this
+	 * If a country IE has been received 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.
@@ -469,7 +476,7 @@
 		wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
 	} else {
 		/*
-		 * This gets applied in the case of the absense of CRDA,
+		 * This gets applied in the case of the absence of CRDA,
 		 * it's our own custom world regulatory domain, similar to
 		 * cfg80211's but we enable passive scanning.
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd_common.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/regd_common.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/regd_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -195,6 +195,7 @@
 	{APL9_WORLD, CTL_ETSI, CTL_ETSI},
 
 	{APL3_FCCA, CTL_FCC, CTL_FCC},
+	{APL7_FCCA, CTL_FCC, CTL_FCC},
 	{APL1_ETSIC, CTL_FCC, CTL_ETSI},
 	{APL2_ETSIC, CTL_FCC, CTL_ETSI},
 	{APL2_APLD, CTL_FCC, NO_CTL},
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd.h linux-libre-2.6.39-gnu/drivers/net/wireless/ath/regd.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ath/regd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ath/regd.h	2011-05-19 00:06:34.000000000 -0400
@@ -250,6 +250,7 @@
 };
 
 bool ath_is_world_regd(struct ath_regulatory *reg);
+bool ath_is_49ghz_allowed(u16 redomain);
 int ath_regd_init(struct ath_regulatory *reg, struct wiphy *wiphy,
 		  int (*reg_notifier)(struct wiphy *wiphy,
 		  struct regulatory_request *request));
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/atmel.c linux-libre-2.6.39-gnu/drivers/net/wireless/atmel.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/atmel.c	2012-03-24 01:10:23.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/atmel.c	2012-03-24 03:32:09.000000000 -0400
@@ -424,7 +424,7 @@
 };
 
 struct atmel_private {
-	void *card; /* Bus dependent stucture varies for PCcard */
+	void *card; /* Bus dependent structure varies for PCcard */
 	int (*present_callback)(void *); /* And callback which uses it */
 	char firmware_id[32];
 	AtmelFWType firmware_type;
@@ -3880,7 +3880,7 @@
 
 	   This routine is also responsible for initialising some
 	   hardware-specific fields in the atmel_private structure,
-	   including a copy of the firmware's hostinfo stucture
+	   including a copy of the firmware's hostinfo structure
 	   which is the route into the rest of the firmware datastructures. */
 
 	struct atmel_private *priv = netdev_priv(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/atmel_cs.c linux-libre-2.6.39-gnu/drivers/net/wireless/atmel_cs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/atmel_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/atmel_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 }
 
 /* Call-back function to interrogate PCMCIA-specific information
-   about the current existance of the card */
+   about the current existence of the card */
 static int card_present(void *arg)
 {
 	struct pcmcia_device *link = (struct pcmcia_device *)arg;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/b43.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43/b43.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/b43.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/b43.h	2011-05-19 00:06:34.000000000 -0400
@@ -648,7 +648,7 @@
 	char errors[B43_NR_FWTYPES][128];
 	/* Temporary buffer for storing the firmware name. */
 	char fwname[64];
-	/* A fatal error occured while requesting. Firmware reqest
+	/* A fatal error occurred while requesting. Firmware reqest
 	 * can not continue, as any other reqest will also fail. */
 	int fatal_failure;
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43/dma.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/dma.c	2011-05-19 00:06:34.000000000 -0400
@@ -1536,7 +1536,7 @@
 		dmaaddr = meta->dmaaddr;
 		goto drop_recycle_buffer;
 	}
-	if (unlikely(len > ring->rx_buffersize)) {
+	if (unlikely(len + ring->frameoffset > ring->rx_buffersize)) {
 		/* The data did not fit into one descriptor buffer
 		 * and is split over multiple buffers.
 		 * This should never happen, as we try to allocate buffers
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43/dma.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/dma.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/dma.h	2011-05-19 00:06:34.000000000 -0400
@@ -163,7 +163,7 @@
 /* DMA engine tuning knobs */
 #define B43_TXRING_SLOTS		256
 #define B43_RXRING_SLOTS		64
-#define B43_DMA0_RX_BUFFERSIZE		IEEE80211_MAX_FRAME_LEN
+#define B43_DMA0_RX_BUFFERSIZE		(B43_DMA0_RX_FRAMEOFFSET + IEEE80211_MAX_FRAME_LEN)
 
 /* Pointer poison */
 #define B43_DMA_PTR_POISON		((void *)ERR_PTR(-ENOMEM))
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/b43/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -92,7 +92,7 @@
 	---help---
 	  Support for the N-PHY.
 
-	  This enables support for devices with N-PHY revision up to 2.
+	  This enables support for devices with N-PHY.
 
 	  Say N if you expect high stability and performance. Saying Y will not
 	  affect other devices support and may provide support for basic needs.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/main.c	2012-03-24 01:10:37.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/main.c	2012-03-24 03:32:16.000000000 -0400
@@ -3199,7 +3199,7 @@
 	mutex_unlock(&wl->mutex);
 }
 
-static int b43_op_tx(struct ieee80211_hw *hw,
+static void b43_op_tx(struct ieee80211_hw *hw,
 		     struct sk_buff *skb)
 {
 	struct b43_wl *wl = hw_to_b43_wl(hw);
@@ -3207,14 +3207,12 @@
 	if (unlikely(skb->len < 2 + 2 + 6)) {
 		/* Too short, this can't be a valid frame. */
 		dev_kfree_skb_any(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 	B43_WARN_ON(skb_shinfo(skb)->nr_frags);
 
 	skb_queue_tail(&wl->tx_queue, skb);
 	ieee80211_queue_work(wl->hw, &wl->tx_work);
-
-	return NETDEV_TX_OK;
 }
 
 static void b43_qos_params_upload(struct b43_wldev *dev,
@@ -4008,7 +4006,7 @@
 	b43_mac_enable(dev);
 	b43_write32(dev, B43_MMIO_GEN_IRQ_MASK, dev->irq_mask);
 
-	/* Start maintainance work */
+	/* Start maintenance work */
 	b43_periodic_tasks_setup(dev);
 
 	b43_leds_init(dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/phy_g.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43/phy_g.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/phy_g.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/phy_g.h	2011-05-19 00:06:34.000000000 -0400
@@ -164,7 +164,7 @@
 	/* Current Interference Mitigation mode */
 	int interfmode;
 	/* Stack of saved values from the Interference Mitigation code.
-	 * Each value in the stack is layed out as follows:
+	 * Each value in the stack is laid out as follows:
 	 * bit 0-11:  offset
 	 * bit 12-15: register ID
 	 * bit 16-32: value
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/phy_n.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43/phy_n.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/phy_n.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/phy_n.c	2011-05-19 00:06:34.000000000 -0400
@@ -430,9 +430,9 @@
 	bool workaround = false;
 
 	if (sprom->revision < 4)
-		workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM ||
-				binfo->type != 0x46D ||
-				binfo->rev < 0x41);
+		workaround = (binfo->vendor != PCI_VENDOR_ID_BROADCOM &&
+				binfo->type == 0x46D &&
+				binfo->rev >= 0x41);
 	else
 		workaround =
 			!(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
@@ -1168,23 +1168,98 @@
 static void b43_nphy_gain_ctrl_workarounds(struct b43_wldev *dev)
 {
 	struct b43_phy_n *nphy = dev->phy.n;
+	struct ssb_sprom *sprom = &(dev->dev->bus->sprom);
+
+	/* PHY rev 0, 1, 2 */
 	u8 i, j;
 	u8 code;
 	u16 tmp;
+	u8 rfseq_events[3] = { 6, 8, 7 };
+	u8 rfseq_delays[3] = { 10, 30, 1 };
 
-	/* TODO: for PHY >= 3
-	s8 *lna1_gain, *lna2_gain;
-	u8 *gain_db, *gain_bits;
-	u16 *rfseq_init;
+	/* PHY rev >= 3 */
+	bool ghz5;
+	bool ext_lna;
+	u16 rssi_gain;
+	struct nphy_gain_ctl_workaround_entry *e;
 	u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
 	u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
-	*/
-
-	u8 rfseq_events[3] = { 6, 8, 7 };
-	u8 rfseq_delays[3] = { 10, 30, 1 };
 
 	if (dev->phy.rev >= 3) {
-		/* TODO */
+		/* Prepare values */
+		ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
+			& B43_NPHY_BANDCTL_5GHZ;
+		ext_lna = sprom->boardflags_lo & B43_BFL_EXTLNA;
+		e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
+		if (ghz5 && dev->phy.rev >= 5)
+			rssi_gain = 0x90;
+		else
+			rssi_gain = 0x50;
+
+		b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
+
+		/* Set Clip 2 detect */
+		b43_phy_set(dev, B43_NPHY_C1_CGAINI,
+				B43_NPHY_C1_CGAINI_CL2DETECT);
+		b43_phy_set(dev, B43_NPHY_C2_CGAINI,
+				B43_NPHY_C2_CGAINI_CL2DETECT);
+
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
+				rssi_gain);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
+				rssi_gain);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
+				0x17);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
+
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
+		b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
+		b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
+		b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
+		b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
+
+		b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
+		b43_phy_write(dev, 0x2A7, e->init_gain);
+		b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
+					e->rfseq_init);
+		b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
+
+		/* TODO: check defines. Do not match variables names */
+		b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
+		b43_phy_write(dev, 0x2A9, e->cliphi_gain);
+		b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
+		b43_phy_write(dev, 0x2AB, e->clipmd_gain);
+		b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
+		b43_phy_write(dev, 0x2AD, e->cliplo_gain);
+
+		b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
+		b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
+		b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
+		b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
+		b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
+		b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
+				~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
+		b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
+				~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
+		b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
 	} else {
 		/* Set Clip 2 detect */
 		b43_phy_set(dev, B43_NPHY_C1_CGAINI,
@@ -1281,17 +1356,17 @@
 						B43_NPHY_TABLE_DATALO, tmp);
 				}
 			}
+		}
 
-			b43_nphy_set_rf_sequence(dev, 5,
-					rfseq_events, rfseq_delays, 3);
-			b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
-				~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
-				0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
+		b43_nphy_set_rf_sequence(dev, 5,
+				rfseq_events, rfseq_delays, 3);
+		b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
+			~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
+			0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
 
-			if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
-				b43_phy_maskset(dev, B43_PHY_N(0xC5D),
-						0xFF80, 4);
-		}
+		if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
+			b43_phy_maskset(dev, B43_PHY_N(0xC5D),
+					0xFF80, 4);
 	}
 }
 
@@ -1308,6 +1383,9 @@
 	u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
 	u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
 
+	u16 tmp16;
+	u32 tmp32;
+
 	if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
 		b43_nphy_classifier(dev, 1, 0);
 	else
@@ -1320,7 +1398,82 @@
 		    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
 
 	if (dev->phy.rev >= 3) {
+		tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
+		tmp32 &= 0xffffff;
+		b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
+
+		b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
+		b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
+		b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
+		b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
+		b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
+		b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
+
+		b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
+		b43_phy_write(dev, 0x2AE, 0x000C);
+
+		/* TODO */
+
+		tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
+			0x2 : 0x9C40;
+		b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
+
+		b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
+
+		b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
+		b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
+
+		b43_nphy_gain_ctrl_workarounds(dev);
+
+		b43_ntab_write(dev, B43_NTAB32(8, 0), 2);
+		b43_ntab_write(dev, B43_NTAB32(8, 16), 2);
+
 		/* TODO */
+
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
+		b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+		b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
+
+		/* N PHY WAR TX Chain Update with hw_phytxchain as argument */
+
+		if ((bus->sprom.boardflags2_lo & B43_BFL2_APLL_WAR &&
+		    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
+		    (bus->sprom.boardflags2_lo & B43_BFL2_GPLL_WAR &&
+		    b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
+			tmp32 = 0x00088888;
+		else
+			tmp32 = 0x88888888;
+		b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
+		b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
+		b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
+
+		if (dev->phy.rev == 4 &&
+		    b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
+			b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
+					0x70);
+			b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
+					0x70);
+		}
+
+		b43_phy_write(dev, 0x224, 0x039C);
+		b43_phy_write(dev, 0x225, 0x0357);
+		b43_phy_write(dev, 0x226, 0x0317);
+		b43_phy_write(dev, 0x227, 0x02D7);
+		b43_phy_write(dev, 0x228, 0x039C);
+		b43_phy_write(dev, 0x229, 0x0357);
+		b43_phy_write(dev, 0x22A, 0x0317);
+		b43_phy_write(dev, 0x22B, 0x02D7);
+		b43_phy_write(dev, 0x22C, 0x039C);
+		b43_phy_write(dev, 0x22D, 0x0357);
+		b43_phy_write(dev, 0x22E, 0x0317);
+		b43_phy_write(dev, 0x22F, 0x02D7);
 	} else {
 		if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
 		    nphy->band5g_pwrgain) {
@@ -2128,7 +2281,7 @@
 		save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
 		save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
 		save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
-	} else if (dev->phy.rev == 2) {
+	} else {
 		save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
 		save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
 		save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
@@ -2179,7 +2332,7 @@
 		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
 		b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
-	} else if (dev->phy.rev == 2) {
+	} else {
 		b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
 		b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
 		b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
@@ -3878,10 +4031,14 @@
 	}
 }
 
+/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
 {
-	b43_phy_write(dev, B43_NPHY_AFECTL_OVER,
-		      on ? 0 : 0x7FFF);
+	u16 val = on ? 0 : 0x7FFF;
+
+	if (dev->phy.rev >= 3)
+		b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, val);
+	b43_phy_write(dev, B43_NPHY_AFECTL_OVER, val);
 }
 
 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/phy_n.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43/phy_n.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/phy_n.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/phy_n.h	2011-05-19 00:06:34.000000000 -0400
@@ -703,7 +703,7 @@
 #define B43_NPHY_CHAN_ESTHANG			B43_PHY_N(0x21D) /* Channel estimate hang */
 #define B43_NPHY_FINERX2_CGC			B43_PHY_N(0x221) /* Fine RX 2 clock gate control */
 #define  B43_NPHY_FINERX2_CGC_DECGC		0x0008 /* Decode gated clocks */
-#define B43_NPHY_TXPCTL_INIT			B43_PHY_N(0x222) /* TX power controll init */
+#define B43_NPHY_TXPCTL_INIT			B43_PHY_N(0x222) /* TX power control init */
 #define  B43_NPHY_TXPCTL_INIT_PIDXI1		0x00FF /* Power index init 1 */
 #define  B43_NPHY_TXPCTL_INIT_PIDXI1_SHIFT	0
 #define B43_NPHY_PAPD_EN0			B43_PHY_N(0x297) /* PAPD Enable0 TBD */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/tables_nphy.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43/tables_nphy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/tables_nphy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/tables_nphy.c	2011-05-19 00:06:34.000000000 -0400
@@ -1097,6 +1097,1080 @@
 	0x00000000, 0x00000000, 0x00000000, 0x00000000,
 };
 
+/* static tables, PHY revision >= 3 */
+static const u32 b43_ntab_framestruct_r3[] = {
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x09804506, 0x00100030, 0x09804507, 0x00100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a0c, 0x00100004, 0x01000a0d, 0x00100024,
+	0x0980450e, 0x00100034, 0x0980450f, 0x00100034,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a04, 0x00100000, 0x11008a05, 0x00100020,
+	0x1980c506, 0x00100030, 0x21810506, 0x00100030,
+	0x21810506, 0x00100030, 0x01800504, 0x00100030,
+	0x11808505, 0x00100030, 0x29814507, 0x01100030,
+	0x00000a04, 0x00100000, 0x11008a05, 0x00100020,
+	0x21810506, 0x00100030, 0x21810506, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x1980c50e, 0x00100038, 0x2181050e, 0x00100038,
+	0x2181050e, 0x00100038, 0x0180050c, 0x00100038,
+	0x1180850d, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x2181050e, 0x00100038, 0x2181050e, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x1980c506, 0x00100030, 0x1980c506, 0x00100030,
+	0x11808504, 0x00100030, 0x3981ca05, 0x00100030,
+	0x29814507, 0x01100030, 0x00000000, 0x00000000,
+	0x10008a04, 0x00100000, 0x3981ca05, 0x00100030,
+	0x1980c506, 0x00100030, 0x29814507, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a0c, 0x00100008, 0x01000a0d, 0x00100028,
+	0x1980c50e, 0x00100038, 0x1980c50e, 0x00100038,
+	0x1180850c, 0x00100038, 0x3981ca0d, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x10008a0c, 0x00100008, 0x3981ca0d, 0x00100038,
+	0x1980c50e, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x02001405, 0x00100040,
+	0x0b004a06, 0x01900060, 0x13008a06, 0x01900060,
+	0x13008a06, 0x01900060, 0x43020a04, 0x00100060,
+	0x1b00ca05, 0x00100060, 0x23010a07, 0x01500060,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x13008a06, 0x01900060, 0x13008a06, 0x01900060,
+	0x23010a07, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x0200140d, 0x00100050,
+	0x0b004a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x13008a0e, 0x01900070, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x23010a0f, 0x01500070,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x13008a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x0b004a06, 0x01900060, 0x0b004a06, 0x01900060,
+	0x5b02ca04, 0x00100060, 0x3b01d405, 0x00100060,
+	0x23010a07, 0x01500060, 0x00000000, 0x00000000,
+	0x5802d404, 0x00100000, 0x3b01d405, 0x00100060,
+	0x0b004a06, 0x01900060, 0x23010a07, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x5002940c, 0x00100010, 0x3201940d, 0x00100050,
+	0x0b004a0e, 0x01900070, 0x0b004a0e, 0x01900070,
+	0x5b02ca0c, 0x00100070, 0x3b01d40d, 0x00100070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x5802d40c, 0x00100010, 0x3b01d40d, 0x00100070,
+	0x0b004a0e, 0x01900070, 0x23010a0f, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x000f4800, 0x62031405, 0x00100040,
+	0x53028a06, 0x01900060, 0x53028a07, 0x01900060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x000f4808, 0x6203140d, 0x00100048,
+	0x53028a0e, 0x01900068, 0x53028a0f, 0x01900068,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100004, 0x11008a0d, 0x00100024,
+	0x1980c50e, 0x00100034, 0x2181050e, 0x00100034,
+	0x2181050e, 0x00100034, 0x0180050c, 0x00100038,
+	0x1180850d, 0x00100038, 0x1181850d, 0x00100038,
+	0x2981450f, 0x01100038, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000a0c, 0x00100008, 0x11008a0d, 0x00100028,
+	0x2181050e, 0x00100038, 0x2181050e, 0x00100038,
+	0x1181850d, 0x00100038, 0x2981450f, 0x01100038,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x08004a04, 0x00100000, 0x01000a05, 0x00100020,
+	0x0180c506, 0x00100030, 0x0180c506, 0x00100030,
+	0x2180c50c, 0x00100030, 0x49820a0d, 0x0016a130,
+	0x41824a0d, 0x0016a130, 0x2981450f, 0x01100030,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x2000ca0c, 0x00100000, 0x49820a0d, 0x0016a130,
+	0x1980c50e, 0x00100030, 0x41824a0d, 0x0016a130,
+	0x2981450f, 0x01100030, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100008, 0x0200140d, 0x00100048,
+	0x0b004a0e, 0x01900068, 0x13008a0e, 0x01900068,
+	0x13008a0e, 0x01900068, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x1b014a0d, 0x00100070,
+	0x23010a0f, 0x01500070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x13008a0e, 0x01900070, 0x13008a0e, 0x01900070,
+	0x1b014a0d, 0x00100070, 0x23010a0f, 0x01500070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x50029404, 0x00100000, 0x32019405, 0x00100040,
+	0x03004a06, 0x01900060, 0x03004a06, 0x01900060,
+	0x6b030a0c, 0x00100060, 0x4b02140d, 0x0016a160,
+	0x4302540d, 0x0016a160, 0x23010a0f, 0x01500060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x6b03140c, 0x00100060, 0x4b02140d, 0x0016a160,
+	0x0b004a0e, 0x01900060, 0x4302540d, 0x0016a160,
+	0x23010a0f, 0x01500060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x53028a06, 0x01900060, 0x5b02ca06, 0x01900060,
+	0x5b02ca06, 0x01900060, 0x43020a04, 0x00100060,
+	0x1b00ca05, 0x00100060, 0x53028a07, 0x0190c060,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x53028a0e, 0x01900070, 0x5b02ca0e, 0x01900070,
+	0x5b02ca0e, 0x01900070, 0x43020a0c, 0x00100070,
+	0x1b00ca0d, 0x00100070, 0x53028a0f, 0x0190c070,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x40021404, 0x00100000, 0x1a00d405, 0x00100040,
+	0x5b02ca06, 0x01900060, 0x5b02ca06, 0x01900060,
+	0x53028a07, 0x0190c060, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x4002140c, 0x00100010, 0x1a00d40d, 0x00100050,
+	0x5b02ca0e, 0x01900070, 0x5b02ca0e, 0x01900070,
+	0x53028a0f, 0x0190c070, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_ntab_pilot_r3[] = {
+	0xff08, 0xff08, 0xff08, 0xff08, 0xff08, 0xff08,
+	0xff08, 0xff08, 0x80d5, 0x80d5, 0x80d5, 0x80d5,
+	0x80d5, 0x80d5, 0x80d5, 0x80d5, 0xff0a, 0xff82,
+	0xffa0, 0xff28, 0xffff, 0xffff, 0xffff, 0xffff,
+	0xff82, 0xffa0, 0xff28, 0xff0a, 0xffff, 0xffff,
+	0xffff, 0xffff, 0xf83f, 0xfa1f, 0xfa97, 0xfab5,
+	0xf2bd, 0xf0bf, 0xffff, 0xffff, 0xf017, 0xf815,
+	0xf215, 0xf095, 0xf035, 0xf01d, 0xffff, 0xffff,
+	0xff08, 0xff02, 0xff80, 0xff20, 0xff08, 0xff02,
+	0xff80, 0xff20, 0xf01f, 0xf817, 0xfa15, 0xf295,
+	0xf0b5, 0xf03d, 0xffff, 0xffff, 0xf82a, 0xfa0a,
+	0xfa82, 0xfaa0, 0xf2a8, 0xf0aa, 0xffff, 0xffff,
+	0xf002, 0xf800, 0xf200, 0xf080, 0xf020, 0xf008,
+	0xffff, 0xffff, 0xf00a, 0xf802, 0xfa00, 0xf280,
+	0xf0a0, 0xf028, 0xffff, 0xffff,
+};
+
+static const u32 b43_ntab_tmap_r3[] = {
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x000aa888,
+	0x88880000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00011111,
+	0x11110000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00088aaa,
+	0xaaaa0000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xaaa8aaa0, 0x8aaa8aaa, 0xaa8a8a8a, 0x000aaa88,
+	0x8aaa0000, 0xaaa8a888, 0x8aa88a8a, 0x8a88a888,
+	0x08080a00, 0x0a08080a, 0x080a0a08, 0x00080808,
+	0x080a0000, 0x080a0808, 0x080a0808, 0x0a0a0a08,
+	0xa0a0a0a0, 0x80a0a080, 0x8080a0a0, 0x00008080,
+	0x80a00000, 0x80a080a0, 0xa080a0a0, 0x8080a0a0,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x99999000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x22000000, 0x2222b222, 0x22222222, 0x222222b2,
+	0xb2222220, 0x22222222, 0x22d22222, 0x00000222,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x33000000, 0x3333b333, 0x33333333, 0x333333b3,
+	0xb3333330, 0x33333333, 0x33d33333, 0x00000333,
+	0x22000000, 0x2222a222, 0x22222222, 0x222222a2,
+	0xa2222220, 0x22222222, 0x22c22222, 0x00000222,
+	0x99b99b00, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb99, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x22222200, 0x2222f222, 0x22222222, 0x222222f2,
+	0x22222222, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x11111111,
+	0xf1111111, 0x11111111, 0x11f11111, 0x01111111,
+	0xbb9bb900, 0xb9b9bb99, 0xb99bbbbb, 0xbbbb9b9b,
+	0xb9bb99bb, 0xb99999b9, 0xb9b9b99b, 0x00000bbb,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88aa, 0xa88888a8, 0xa8a8a88a, 0x0a888aaa,
+	0xaa000000, 0xa8a8aa88, 0xa88aaaaa, 0xaaaa8a8a,
+	0xa8aa88a0, 0xa88888a8, 0xa8a8a88a, 0x00000aaa,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0xbbbbbb00, 0x999bbbbb, 0x9bb99b9b, 0xb9b9b9bb,
+	0xb9b99bbb, 0xb9b9b9bb, 0xb9bb9b99, 0x00000999,
+	0x8a000000, 0xaa88a888, 0xa88888aa, 0xa88a8a88,
+	0xa88aa88a, 0x88a8aaaa, 0xa8aa8aaa, 0x0888a88a,
+	0x0b0b0b00, 0x090b0b0b, 0x0b090b0b, 0x0909090b,
+	0x09090b0b, 0x09090b0b, 0x09090b09, 0x00000909,
+	0x0a000000, 0x0a080808, 0x080a080a, 0x080a0a08,
+	0x080a080a, 0x0808080a, 0x0a0a0a08, 0x0808080a,
+	0xb0b0b000, 0x9090b0b0, 0x90b09090, 0xb0b0b090,
+	0xb0b090b0, 0x90b0b0b0, 0xb0b09090, 0x00000090,
+	0x80000000, 0xa080a080, 0xa08080a0, 0xa0808080,
+	0xa080a080, 0x80a0a0a0, 0xa0a080a0, 0x00a0a0a0,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x11000000, 0x1111f111, 0x11111111, 0x111111f1,
+	0xf1111110, 0x11111111, 0x11f11111, 0x00000111,
+	0x33000000, 0x3333f333, 0x33333333, 0x333333f3,
+	0xf3333330, 0x33333333, 0x33f33333, 0x00000333,
+	0x22000000, 0x2222f222, 0x22222222, 0x222222f2,
+	0xf2222220, 0x22222222, 0x22f22222, 0x00000222,
+	0x99000000, 0x9b9b99bb, 0x9bb99999, 0x9999b9b9,
+	0x9b99bb90, 0x9bbbbb9b, 0x9b9b9bb9, 0x00000999,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88888000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00aaa888,
+	0x88a88a00, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa88, 0x8aaaaa8a, 0x8a8a8aa8, 0x08aaa888,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x11000000, 0x1111a111, 0x11111111, 0x111111a1,
+	0xa1111110, 0x11111111, 0x11c11111, 0x00000111,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x88000000, 0x8a8a88aa, 0x8aa88888, 0x8888a8a8,
+	0x8a88aa80, 0x8aaaaa8a, 0x8a8a8aa8, 0x00000888,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_intlevel_r3[] = {
+	0x00802070, 0x0671188d, 0x0a60192c, 0x0a300e46,
+	0x00c1188d, 0x080024d2, 0x00000070,
+};
+
+static const u32 b43_ntab_tdtrn_r3[] = {
+	0x061c061c, 0x0050ee68, 0xf592fe36, 0xfe5212f6,
+	0x00000c38, 0xfe5212f6, 0xf592fe36, 0x0050ee68,
+	0x061c061c, 0xee680050, 0xfe36f592, 0x12f6fe52,
+	0x0c380000, 0x12f6fe52, 0xfe36f592, 0xee680050,
+	0x061c061c, 0x0050ee68, 0xf592fe36, 0xfe5212f6,
+	0x00000c38, 0xfe5212f6, 0xf592fe36, 0x0050ee68,
+	0x061c061c, 0xee680050, 0xfe36f592, 0x12f6fe52,
+	0x0c380000, 0x12f6fe52, 0xfe36f592, 0xee680050,
+	0x05e305e3, 0x004def0c, 0xf5f3fe47, 0xfe611246,
+	0x00000bc7, 0xfe611246, 0xf5f3fe47, 0x004def0c,
+	0x05e305e3, 0xef0c004d, 0xfe47f5f3, 0x1246fe61,
+	0x0bc70000, 0x1246fe61, 0xfe47f5f3, 0xef0c004d,
+	0x05e305e3, 0x004def0c, 0xf5f3fe47, 0xfe611246,
+	0x00000bc7, 0xfe611246, 0xf5f3fe47, 0x004def0c,
+	0x05e305e3, 0xef0c004d, 0xfe47f5f3, 0x1246fe61,
+	0x0bc70000, 0x1246fe61, 0xfe47f5f3, 0xef0c004d,
+	0xfa58fa58, 0xf895043b, 0xff4c09c0, 0xfbc6ffa8,
+	0xfb84f384, 0x0798f6f9, 0x05760122, 0x058409f6,
+	0x0b500000, 0x05b7f542, 0x08860432, 0x06ddfee7,
+	0xfb84f384, 0xf9d90664, 0xf7e8025c, 0x00fff7bd,
+	0x05a805a8, 0xf7bd00ff, 0x025cf7e8, 0x0664f9d9,
+	0xf384fb84, 0xfee706dd, 0x04320886, 0xf54205b7,
+	0x00000b50, 0x09f60584, 0x01220576, 0xf6f90798,
+	0xf384fb84, 0xffa8fbc6, 0x09c0ff4c, 0x043bf895,
+	0x02d402d4, 0x07de0270, 0xfc96079c, 0xf90afe94,
+	0xfe00ff2c, 0x02d4065d, 0x092a0096, 0x0014fbb8,
+	0xfd2cfd2c, 0x076afb3c, 0x0096f752, 0xf991fd87,
+	0xfb2c0200, 0xfeb8f960, 0x08e0fc96, 0x049802a8,
+	0xfd2cfd2c, 0x02a80498, 0xfc9608e0, 0xf960feb8,
+	0x0200fb2c, 0xfd87f991, 0xf7520096, 0xfb3c076a,
+	0xfd2cfd2c, 0xfbb80014, 0x0096092a, 0x065d02d4,
+	0xff2cfe00, 0xfe94f90a, 0x079cfc96, 0x027007de,
+	0x02d402d4, 0x027007de, 0x079cfc96, 0xfe94f90a,
+	0xff2cfe00, 0x065d02d4, 0x0096092a, 0xfbb80014,
+	0xfd2cfd2c, 0xfb3c076a, 0xf7520096, 0xfd87f991,
+	0x0200fb2c, 0xf960feb8, 0xfc9608e0, 0x02a80498,
+	0xfd2cfd2c, 0x049802a8, 0x08e0fc96, 0xfeb8f960,
+	0xfb2c0200, 0xf991fd87, 0x0096f752, 0x076afb3c,
+	0xfd2cfd2c, 0x0014fbb8, 0x092a0096, 0x02d4065d,
+	0xfe00ff2c, 0xf90afe94, 0xfc96079c, 0x07de0270,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x062a0000, 0xfefa0759, 0x08b80908, 0xf396fc2d,
+	0xf9d6045c, 0xfc4ef608, 0xf748f596, 0x07b207bf,
+	0x062a062a, 0xf84ef841, 0xf748f596, 0x03b209f8,
+	0xf9d6045c, 0x0c6a03d3, 0x08b80908, 0x0106f8a7,
+	0x062a0000, 0xfefaf8a7, 0x08b8f6f8, 0xf39603d3,
+	0xf9d6fba4, 0xfc4e09f8, 0xf7480a6a, 0x07b2f841,
+	0x062af9d6, 0xf84e07bf, 0xf7480a6a, 0x03b2f608,
+	0xf9d6fba4, 0x0c6afc2d, 0x08b8f6f8, 0x01060759,
+	0x062a0000, 0xfefa0759, 0x08b80908, 0xf396fc2d,
+	0xf9d6045c, 0xfc4ef608, 0xf748f596, 0x07b207bf,
+	0x062a062a, 0xf84ef841, 0xf748f596, 0x03b209f8,
+	0xf9d6045c, 0x0c6a03d3, 0x08b80908, 0x0106f8a7,
+	0x062a0000, 0xfefaf8a7, 0x08b8f6f8, 0xf39603d3,
+	0xf9d6fba4, 0xfc4e09f8, 0xf7480a6a, 0x07b2f841,
+	0x062af9d6, 0xf84e07bf, 0xf7480a6a, 0x03b2f608,
+	0xf9d6fba4, 0x0c6afc2d, 0x08b8f6f8, 0x01060759,
+	0x061c061c, 0xff30009d, 0xffb21141, 0xfd87fb54,
+	0xf65dfe59, 0x02eef99e, 0x0166f03c, 0xfff809b6,
+	0x000008a4, 0x000af42b, 0x00eff577, 0xfa840bf2,
+	0xfc02ff51, 0x08260f67, 0xfff0036f, 0x0842f9c3,
+	0x00000000, 0x063df7be, 0xfc910010, 0xf099f7da,
+	0x00af03fe, 0xf40e057c, 0x0a89ff11, 0x0bd5fff6,
+	0xf75c0000, 0xf64a0008, 0x0fc4fe9a, 0x0662fd12,
+	0x01a709a3, 0x04ac0279, 0xeebf004e, 0xff6300d0,
+	0xf9e4f9e4, 0x00d0ff63, 0x004eeebf, 0x027904ac,
+	0x09a301a7, 0xfd120662, 0xfe9a0fc4, 0x0008f64a,
+	0x0000f75c, 0xfff60bd5, 0xff110a89, 0x057cf40e,
+	0x03fe00af, 0xf7daf099, 0x0010fc91, 0xf7be063d,
+	0x00000000, 0xf9c30842, 0x036ffff0, 0x0f670826,
+	0xff51fc02, 0x0bf2fa84, 0xf57700ef, 0xf42b000a,
+	0x08a40000, 0x09b6fff8, 0xf03c0166, 0xf99e02ee,
+	0xfe59f65d, 0xfb54fd87, 0x1141ffb2, 0x009dff30,
+	0x05e30000, 0xff060705, 0x085408a0, 0xf425fc59,
+	0xfa1d042a, 0xfc78f67a, 0xf7acf60e, 0x075a0766,
+	0x05e305e3, 0xf8a6f89a, 0xf7acf60e, 0x03880986,
+	0xfa1d042a, 0x0bdb03a7, 0x085408a0, 0x00faf8fb,
+	0x05e30000, 0xff06f8fb, 0x0854f760, 0xf42503a7,
+	0xfa1dfbd6, 0xfc780986, 0xf7ac09f2, 0x075af89a,
+	0x05e3fa1d, 0xf8a60766, 0xf7ac09f2, 0x0388f67a,
+	0xfa1dfbd6, 0x0bdbfc59, 0x0854f760, 0x00fa0705,
+	0x05e30000, 0xff060705, 0x085408a0, 0xf425fc59,
+	0xfa1d042a, 0xfc78f67a, 0xf7acf60e, 0x075a0766,
+	0x05e305e3, 0xf8a6f89a, 0xf7acf60e, 0x03880986,
+	0xfa1d042a, 0x0bdb03a7, 0x085408a0, 0x00faf8fb,
+	0x05e30000, 0xff06f8fb, 0x0854f760, 0xf42503a7,
+	0xfa1dfbd6, 0xfc780986, 0xf7ac09f2, 0x075af89a,
+	0x05e3fa1d, 0xf8a60766, 0xf7ac09f2, 0x0388f67a,
+	0xfa1dfbd6, 0x0bdbfc59, 0x0854f760, 0x00fa0705,
+	0xfa58fa58, 0xf8f0fe00, 0x0448073d, 0xfdc9fe46,
+	0xf9910258, 0x089d0407, 0xfd5cf71a, 0x02affde0,
+	0x083e0496, 0xff5a0740, 0xff7afd97, 0x00fe01f1,
+	0x0009082e, 0xfa94ff75, 0xfecdf8ea, 0xffb0f693,
+	0xfd2cfa58, 0x0433ff16, 0xfba405dd, 0xfa610341,
+	0x06a606cb, 0x0039fd2d, 0x0677fa97, 0x01fa05e0,
+	0xf896003e, 0x075a068b, 0x012cfc3e, 0xfa23f98d,
+	0xfc7cfd43, 0xff90fc0d, 0x01c10982, 0x00c601d6,
+	0xfd2cfd2c, 0x01d600c6, 0x098201c1, 0xfc0dff90,
+	0xfd43fc7c, 0xf98dfa23, 0xfc3e012c, 0x068b075a,
+	0x003ef896, 0x05e001fa, 0xfa970677, 0xfd2d0039,
+	0x06cb06a6, 0x0341fa61, 0x05ddfba4, 0xff160433,
+	0xfa58fd2c, 0xf693ffb0, 0xf8eafecd, 0xff75fa94,
+	0x082e0009, 0x01f100fe, 0xfd97ff7a, 0x0740ff5a,
+	0x0496083e, 0xfde002af, 0xf71afd5c, 0x0407089d,
+	0x0258f991, 0xfe46fdc9, 0x073d0448, 0xfe00f8f0,
+	0xfd2cfd2c, 0xfce00500, 0xfc09fddc, 0xfe680157,
+	0x04c70571, 0xfc3aff21, 0xfcd70228, 0x056d0277,
+	0x0200fe00, 0x0022f927, 0xfe3c032b, 0xfc44ff3c,
+	0x03e9fbdb, 0x04570313, 0x04c9ff5c, 0x000d03b8,
+	0xfa580000, 0xfbe900d2, 0xf9d0fe0b, 0x0125fdf9,
+	0x042501bf, 0x0328fa2b, 0xffa902f0, 0xfa250157,
+	0x0200fe00, 0x03740438, 0xff0405fd, 0x030cfe52,
+	0x0037fb39, 0xff6904c5, 0x04f8fd23, 0xfd31fc1b,
+	0xfd2cfd2c, 0xfc1bfd31, 0xfd2304f8, 0x04c5ff69,
+	0xfb390037, 0xfe52030c, 0x05fdff04, 0x04380374,
+	0xfe000200, 0x0157fa25, 0x02f0ffa9, 0xfa2b0328,
+	0x01bf0425, 0xfdf90125, 0xfe0bf9d0, 0x00d2fbe9,
+	0x0000fa58, 0x03b8000d, 0xff5c04c9, 0x03130457,
+	0xfbdb03e9, 0xff3cfc44, 0x032bfe3c, 0xf9270022,
+	0xfe000200, 0x0277056d, 0x0228fcd7, 0xff21fc3a,
+	0x057104c7, 0x0157fe68, 0xfddcfc09, 0x0500fce0,
+	0xfd2cfd2c, 0x0500fce0, 0xfddcfc09, 0x0157fe68,
+	0x057104c7, 0xff21fc3a, 0x0228fcd7, 0x0277056d,
+	0xfe000200, 0xf9270022, 0x032bfe3c, 0xff3cfc44,
+	0xfbdb03e9, 0x03130457, 0xff5c04c9, 0x03b8000d,
+	0x0000fa58, 0x00d2fbe9, 0xfe0bf9d0, 0xfdf90125,
+	0x01bf0425, 0xfa2b0328, 0x02f0ffa9, 0x0157fa25,
+	0xfe000200, 0x04380374, 0x05fdff04, 0xfe52030c,
+	0xfb390037, 0x04c5ff69, 0xfd2304f8, 0xfc1bfd31,
+	0xfd2cfd2c, 0xfd31fc1b, 0x04f8fd23, 0xff6904c5,
+	0x0037fb39, 0x030cfe52, 0xff0405fd, 0x03740438,
+	0x0200fe00, 0xfa250157, 0xffa902f0, 0x0328fa2b,
+	0x042501bf, 0x0125fdf9, 0xf9d0fe0b, 0xfbe900d2,
+	0xfa580000, 0x000d03b8, 0x04c9ff5c, 0x04570313,
+	0x03e9fbdb, 0xfc44ff3c, 0xfe3c032b, 0x0022f927,
+	0x0200fe00, 0x056d0277, 0xfcd70228, 0xfc3aff21,
+	0x04c70571, 0xfe680157, 0xfc09fddc, 0xfce00500,
+	0x05a80000, 0xff1006be, 0x0800084a, 0xf49cfc7e,
+	0xfa580400, 0xfc9cf6da, 0xf800f672, 0x0710071c,
+	0x05a805a8, 0xf8f0f8e4, 0xf800f672, 0x03640926,
+	0xfa580400, 0x0b640382, 0x0800084a, 0x00f0f942,
+	0x05a80000, 0xff10f942, 0x0800f7b6, 0xf49c0382,
+	0xfa58fc00, 0xfc9c0926, 0xf800098e, 0x0710f8e4,
+	0x05a8fa58, 0xf8f0071c, 0xf800098e, 0x0364f6da,
+	0xfa58fc00, 0x0b64fc7e, 0x0800f7b6, 0x00f006be,
+	0x05a80000, 0xff1006be, 0x0800084a, 0xf49cfc7e,
+	0xfa580400, 0xfc9cf6da, 0xf800f672, 0x0710071c,
+	0x05a805a8, 0xf8f0f8e4, 0xf800f672, 0x03640926,
+	0xfa580400, 0x0b640382, 0x0800084a, 0x00f0f942,
+	0x05a80000, 0xff10f942, 0x0800f7b6, 0xf49c0382,
+	0xfa58fc00, 0xfc9c0926, 0xf800098e, 0x0710f8e4,
+	0x05a8fa58, 0xf8f0071c, 0xf800098e, 0x0364f6da,
+	0xfa58fc00, 0x0b64fc7e, 0x0800f7b6, 0x00f006be,
+};
+
+static const u32 b43_ntab_noisevar0_r3[] = {
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+};
+
+static const u32 b43_ntab_noisevar1_r3[] = {
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+	0x02110211, 0x0000014d, 0x02110211, 0x0000014d,
+};
+
+static const u16 b43_ntab_mcs_r3[] = {
+	0x0000, 0x0008, 0x000a, 0x0010, 0x0012, 0x0019,
+	0x001a, 0x001c, 0x0080, 0x0088, 0x008a, 0x0090,
+	0x0092, 0x0099, 0x009a, 0x009c, 0x0100, 0x0108,
+	0x010a, 0x0110, 0x0112, 0x0119, 0x011a, 0x011c,
+	0x0180, 0x0188, 0x018a, 0x0190, 0x0192, 0x0199,
+	0x019a, 0x019c, 0x0000, 0x0098, 0x00a0, 0x00a8,
+	0x009a, 0x00a2, 0x00aa, 0x0120, 0x0128, 0x0128,
+	0x0130, 0x0138, 0x0138, 0x0140, 0x0122, 0x012a,
+	0x012a, 0x0132, 0x013a, 0x013a, 0x0142, 0x01a8,
+	0x01b0, 0x01b8, 0x01b0, 0x01b8, 0x01c0, 0x01c8,
+	0x01c0, 0x01c8, 0x01d0, 0x01d0, 0x01d8, 0x01aa,
+	0x01b2, 0x01ba, 0x01b2, 0x01ba, 0x01c2, 0x01ca,
+	0x01c2, 0x01ca, 0x01d2, 0x01d2, 0x01da, 0x0001,
+	0x0002, 0x0004, 0x0009, 0x000c, 0x0011, 0x0014,
+	0x0018, 0x0020, 0x0021, 0x0022, 0x0024, 0x0081,
+	0x0082, 0x0084, 0x0089, 0x008c, 0x0091, 0x0094,
+	0x0098, 0x00a0, 0x00a1, 0x00a2, 0x00a4, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007, 0x0007, 0x0007, 0x0007, 0x0007,
+	0x0007, 0x0007,
+};
+
+static const u32 b43_ntab_tdi20a0_r3[] = {
+	0x00091226, 0x000a1429, 0x000b56ad, 0x000c58b0,
+	0x000d5ab3, 0x000e9cb6, 0x000f9eba, 0x0000c13d,
+	0x00020301, 0x00030504, 0x00040708, 0x0005090b,
+	0x00064b8e, 0x00095291, 0x000a5494, 0x000b9718,
+	0x000c9927, 0x000d9b2a, 0x000edd2e, 0x000fdf31,
+	0x000101b4, 0x000243b7, 0x000345bb, 0x000447be,
+	0x00058982, 0x00068c05, 0x00099309, 0x000a950c,
+	0x000bd78f, 0x000cd992, 0x000ddb96, 0x000f1d99,
+	0x00005fa8, 0x0001422c, 0x0002842f, 0x00038632,
+	0x00048835, 0x0005ca38, 0x0006ccbc, 0x0009d3bf,
+	0x000b1603, 0x000c1806, 0x000d1a0a, 0x000e1c0d,
+	0x000f5e10, 0x00008093, 0x00018297, 0x0002c49a,
+	0x0003c680, 0x0004c880, 0x00060b00, 0x00070d00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi20a1_r3[] = {
+	0x00014b26, 0x00028d29, 0x000393ad, 0x00049630,
+	0x0005d833, 0x0006da36, 0x00099c3a, 0x000a9e3d,
+	0x000bc081, 0x000cc284, 0x000dc488, 0x000f068b,
+	0x0000488e, 0x00018b91, 0x0002d214, 0x0003d418,
+	0x0004d6a7, 0x000618aa, 0x00071aae, 0x0009dcb1,
+	0x000b1eb4, 0x000c0137, 0x000d033b, 0x000e053e,
+	0x000f4702, 0x00008905, 0x00020c09, 0x0003128c,
+	0x0004148f, 0x00051712, 0x00065916, 0x00091b19,
+	0x000a1d28, 0x000b5f2c, 0x000c41af, 0x000d43b2,
+	0x000e85b5, 0x000f87b8, 0x0000c9bc, 0x00024cbf,
+	0x00035303, 0x00045506, 0x0005978a, 0x0006998d,
+	0x00095b90, 0x000a5d93, 0x000b9f97, 0x000c821a,
+	0x000d8400, 0x000ec600, 0x000fc800, 0x00010a00,
+	0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a0_r3[] = {
+	0x0011a346, 0x00136ccf, 0x0014f5d9, 0x001641e2,
+	0x0017cb6b, 0x00195475, 0x001b2383, 0x001cad0c,
+	0x001e7616, 0x0000821f, 0x00020ba8, 0x0003d4b2,
+	0x00056447, 0x00072dd0, 0x0008b6da, 0x000a02e3,
+	0x000b8c6c, 0x000d15f6, 0x0011e484, 0x0013ae0d,
+	0x00153717, 0x00168320, 0x00180ca9, 0x00199633,
+	0x001b6548, 0x001ceed1, 0x001eb7db, 0x0000c3e4,
+	0x00024d6d, 0x000416f7, 0x0005a585, 0x00076f0f,
+	0x0008f818, 0x000a4421, 0x000bcdab, 0x000d9734,
+	0x00122649, 0x0013efd2, 0x001578dc, 0x0016c4e5,
+	0x00184e6e, 0x001a17f8, 0x001ba686, 0x001d3010,
+	0x001ef999, 0x00010522, 0x00028eac, 0x00045835,
+	0x0005e74a, 0x0007b0d3, 0x00093a5d, 0x000a85e6,
+	0x000c0f6f, 0x000dd8f9, 0x00126787, 0x00143111,
+	0x0015ba9a, 0x00170623, 0x00188fad, 0x001a5936,
+	0x001be84b, 0x001db1d4, 0x001f3b5e, 0x000146e7,
+	0x00031070, 0x000499fa, 0x00062888, 0x0007f212,
+	0x00097b9b, 0x000ac7a4, 0x000c50ae, 0x000e1a37,
+	0x0012a94c, 0x001472d5, 0x0015fc5f, 0x00174868,
+	0x0018d171, 0x001a9afb, 0x001c2989, 0x001df313,
+	0x001f7c9c, 0x000188a5, 0x000351af, 0x0004db38,
+	0x0006aa4d, 0x000833d7, 0x0009bd60, 0x000b0969,
+	0x000c9273, 0x000e5bfc, 0x00132a8a, 0x0014b414,
+	0x00163d9d, 0x001789a6, 0x001912b0, 0x001adc39,
+	0x001c6bce, 0x001e34d8, 0x001fbe61, 0x0001ca6a,
+	0x00039374, 0x00051cfd, 0x0006ec0b, 0x00087515,
+	0x0009fe9e, 0x000b4aa7, 0x000cd3b1, 0x000e9d3a,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_tdi40a1_r3[] = {
+	0x001edb36, 0x000129ca, 0x0002b353, 0x00047cdd,
+	0x0005c8e6, 0x000791ef, 0x00091bf9, 0x000aaa07,
+	0x000c3391, 0x000dfd1a, 0x00120923, 0x0013d22d,
+	0x00155c37, 0x0016eacb, 0x00187454, 0x001a3dde,
+	0x001b89e7, 0x001d12f0, 0x001f1cfa, 0x00016b88,
+	0x00033492, 0x0004be1b, 0x00060a24, 0x0007d32e,
+	0x00095d38, 0x000aec4c, 0x000c7555, 0x000e3edf,
+	0x00124ae8, 0x001413f1, 0x0015a37b, 0x00172c89,
+	0x0018b593, 0x001a419c, 0x001bcb25, 0x001d942f,
+	0x001f63b9, 0x0001ad4d, 0x00037657, 0x0004c260,
+	0x00068be9, 0x000814f3, 0x0009a47c, 0x000b2d8a,
+	0x000cb694, 0x000e429d, 0x00128c26, 0x001455b0,
+	0x0015e4ba, 0x00176e4e, 0x0018f758, 0x001a8361,
+	0x001c0cea, 0x001dd674, 0x001fa57d, 0x0001ee8b,
+	0x0003b795, 0x0005039e, 0x0006cd27, 0x000856b1,
+	0x0009e5c6, 0x000b6f4f, 0x000cf859, 0x000e8462,
+	0x00130deb, 0x00149775, 0x00162603, 0x0017af8c,
+	0x00193896, 0x001ac49f, 0x001c4e28, 0x001e17b2,
+	0x0000a6c7, 0x00023050, 0x0003f9da, 0x00054563,
+	0x00070eec, 0x00089876, 0x000a2704, 0x000bb08d,
+	0x000d3a17, 0x001185a0, 0x00134f29, 0x0014d8b3,
+	0x001667c8, 0x0017f151, 0x00197adb, 0x001b0664,
+	0x001c8fed, 0x001e5977, 0x0000e805, 0x0002718f,
+	0x00043b18, 0x000586a1, 0x0007502b, 0x0008d9b4,
+	0x000a68c9, 0x000bf252, 0x000dbbdc, 0x0011c7e5,
+	0x001390ee, 0x00151a78, 0x0016a906, 0x00183290,
+	0x0019bc19, 0x001b4822, 0x001cd12c, 0x001e9ab5,
+	0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_pilotlt_r3[] = {
+	0x76540213, 0x62407351, 0x76543210, 0x76540213,
+	0x76540213, 0x76430521,
+};
+
+static const u32 b43_ntab_channelest_r3[] = {
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x44444444, 0x44444444, 0x44444444, 0x44444444,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+	0x10101010, 0x10101010, 0x10101010, 0x10101010,
+};
+
+static const u8 b43_ntab_framelookup_r3[] = {
+	0x02, 0x04, 0x14, 0x14, 0x03, 0x05, 0x16, 0x16,
+	0x0a, 0x0c, 0x1c, 0x1c, 0x0b, 0x0d, 0x1e, 0x1e,
+	0x06, 0x08, 0x18, 0x18, 0x07, 0x09, 0x1a, 0x1a,
+	0x0e, 0x10, 0x20, 0x28, 0x0f, 0x11, 0x22, 0x2a,
+};
+
+static const u8 b43_ntab_estimatepowerlt0_r3[] = {
+	0x55, 0x54, 0x54, 0x53, 0x52, 0x52, 0x51, 0x51,
+	0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4c, 0x4c,
+	0x4b, 0x4a, 0x49, 0x49, 0x48, 0x47, 0x46, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x33, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b,
+	0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a,
+	0x18, 0x15, 0x12, 0x0e, 0x0b, 0x07, 0x02, 0xfd,
+};
+
+static const u8 b43_ntab_estimatepowerlt1_r3[] = {
+	0x55, 0x54, 0x54, 0x53, 0x52, 0x52, 0x51, 0x51,
+	0x50, 0x4f, 0x4f, 0x4e, 0x4e, 0x4d, 0x4c, 0x4c,
+	0x4b, 0x4a, 0x49, 0x49, 0x48, 0x47, 0x46, 0x46,
+	0x45, 0x44, 0x43, 0x42, 0x41, 0x40, 0x40, 0x3f,
+	0x3e, 0x3d, 0x3c, 0x3a, 0x39, 0x38, 0x37, 0x36,
+	0x35, 0x33, 0x32, 0x31, 0x2f, 0x2e, 0x2c, 0x2b,
+	0x29, 0x27, 0x25, 0x23, 0x21, 0x1f, 0x1d, 0x1a,
+	0x18, 0x15, 0x12, 0x0e, 0x0b, 0x07, 0x02, 0xfd,
+};
+
+static const u8 b43_ntab_adjustpower0_r3[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u8 b43_ntab_adjustpower1_r3[] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+static const u32 b43_ntab_gainctl0_r3[] = {
+	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_ntab_gainctl1_r3[] = {
+	0x5bf70044, 0x5bf70042, 0x5bf70040, 0x5bf7003e,
+	0x5bf7003c, 0x5bf7003b, 0x5bf70039, 0x5bf70037,
+	0x5bf70036, 0x5bf70034, 0x5bf70033, 0x5bf70031,
+	0x5bf70030, 0x5ba70044, 0x5ba70042, 0x5ba70040,
+	0x5ba7003e, 0x5ba7003c, 0x5ba7003b, 0x5ba70039,
+	0x5ba70037, 0x5ba70036, 0x5ba70034, 0x5ba70033,
+	0x5b770044, 0x5b770042, 0x5b770040, 0x5b77003e,
+	0x5b77003c, 0x5b77003b, 0x5b770039, 0x5b770037,
+	0x5b770036, 0x5b770034, 0x5b770033, 0x5b770031,
+	0x5b770030, 0x5b77002f, 0x5b77002d, 0x5b77002c,
+	0x5b470044, 0x5b470042, 0x5b470040, 0x5b47003e,
+	0x5b47003c, 0x5b47003b, 0x5b470039, 0x5b470037,
+	0x5b470036, 0x5b470034, 0x5b470033, 0x5b470031,
+	0x5b470030, 0x5b47002f, 0x5b47002d, 0x5b47002c,
+	0x5b47002b, 0x5b47002a, 0x5b270044, 0x5b270042,
+	0x5b270040, 0x5b27003e, 0x5b27003c, 0x5b27003b,
+	0x5b270039, 0x5b270037, 0x5b270036, 0x5b270034,
+	0x5b270033, 0x5b270031, 0x5b270030, 0x5b27002f,
+	0x5b170044, 0x5b170042, 0x5b170040, 0x5b17003e,
+	0x5b17003c, 0x5b17003b, 0x5b170039, 0x5b170037,
+	0x5b170036, 0x5b170034, 0x5b170033, 0x5b170031,
+	0x5b170030, 0x5b17002f, 0x5b17002d, 0x5b17002c,
+	0x5b17002b, 0x5b17002a, 0x5b170028, 0x5b170027,
+	0x5b170026, 0x5b170025, 0x5b170024, 0x5b170023,
+	0x5b070044, 0x5b070042, 0x5b070040, 0x5b07003e,
+	0x5b07003c, 0x5b07003b, 0x5b070039, 0x5b070037,
+	0x5b070036, 0x5b070034, 0x5b070033, 0x5b070031,
+	0x5b070030, 0x5b07002f, 0x5b07002d, 0x5b07002c,
+	0x5b07002b, 0x5b07002a, 0x5b070028, 0x5b070027,
+	0x5b070026, 0x5b070025, 0x5b070024, 0x5b070023,
+	0x5b070022, 0x5b070021, 0x5b070020, 0x5b07001f,
+	0x5b07001e, 0x5b07001d, 0x5b07001d, 0x5b07001c,
+};
+
+static const u32 b43_ntab_iqlt0_r3[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u32 b43_ntab_iqlt1_r3[] = {
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+	0x00000000, 0x00000000, 0x00000000, 0x00000000,
+};
+
+static const u16 b43_ntab_loftlt0_r3[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+static const u16 b43_ntab_loftlt1_r3[] = {
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+	0x0000, 0x0000,
+};
+
+/* TX gain tables */
 const u32 b43_ntab_tx_gain_rev0_1_2[] = {
 	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
 	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
@@ -1635,6 +2709,79 @@
 	{ 0x00C0,  6, 0xE7, 0xF9, 0xEC, 0xFB }  /* field == 0x4000 (fls 15) */
 };
 
+struct nphy_gain_ctl_workaround_entry nphy_gain_ctl_workaround[2][3] = {
+	{ /* 2GHz */
+		{ /* PHY rev 3 */
+			{ 7, 11, 16, 23 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x627E,
+			{ 0x613F, 0x613F, 0x613F, 0x613F },
+			0x107E, 0x0066, 0x0074,
+			0x18, 0x18, 0x18,
+			0x020D, 0x5,
+		},
+		{ /* PHY rev 4 */
+			{ 8, 12, 17, 25 },
+			{ -5, 6, 10, 14 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x527E,
+			{ 0x513F, 0x513F, 0x513F, 0x513F },
+			0x007E, 0x0066, 0x0074,
+			0x18, 0x18, 0x18,
+			0x01A1, 0x5,
+		},
+		{ /* PHY rev 5+ */
+			{ 9, 13, 18, 26 },
+			{ -3, 7, 11, 16 },
+			{ 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA, 0xA },
+			{ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 },
+			0x427E, /* invalid for external LNA! */
+			{ 0x413F, 0x413F, 0x413F, 0x413F }, /* invalid for external LNA! */
+			0x1076, 0x0066, 0x106A,
+			0xC, 0xC, 0xC,
+			0x01D0, 0x5,
+		},
+	},
+	{ /* 5GHz */
+		{ /* PHY rev 3 */
+			{ 7, 11, 17, 23 },
+			{ -6, 2, 6, 10 },
+			{ 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 },
+			{ 6, 6, 6, 6, 6, 6, 6, 6, 6, 6 },
+			0x52DE,
+			{ 0x516F, 0x516F, 0x516F, 0x516F },
+			0x00DE, 0x00CA, 0x00CC,
+			0x1E, 0x1E, 0x1E,
+			0x01A1, 25,
+		},
+		{ /* PHY rev 4 */
+			{ 8, 12, 18, 23 },
+			{ -5, 2, 6, 10 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x629E,
+			{ 0x614F, 0x614F, 0x614F, 0x614F },
+			0x029E, 0x1084, 0x0086,
+			0x24, 0x24, 0x24,
+			0x0107, 25,
+		},
+		{ /* PHY rev 5+ */
+			{ 6, 10, 16, 21 },
+			{ -7, 0, 4, 8 },
+			{ 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD, 0xD },
+			{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 4 },
+			0x729E,
+			{ 0x714F, 0x714F, 0x714F, 0x714F },
+			0x029E, 0x2084, 0x2086,
+			0x24, 0x24, 0x24,
+			0x00A9, 25,
+		},
+	},
+};
+
 static inline void assert_ntab_array_sizes(void)
 {
 #undef check
@@ -1813,7 +2960,6 @@
 #define ntab_upload(dev, offset, data) do { \
 		b43_ntab_write_bulk(dev, offset, offset##_SIZE, data);	\
 	} while (0)
-
 void b43_nphy_rev0_1_2_tables_init(struct b43_wldev *dev)
 {
 	/* Static tables */
@@ -1847,11 +2993,70 @@
 	ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
 }
 
+#define ntab_upload_r3(dev, offset, data) do { \
+		b43_ntab_write_bulk(dev, offset, ARRAY_SIZE(data), data); \
+	} while (0)
 void b43_nphy_rev3plus_tables_init(struct b43_wldev *dev)
 {
 	/* Static tables */
-	/* TODO */
+	ntab_upload_r3(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+	ntab_upload_r3(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+	ntab_upload_r3(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
+	ntab_upload_r3(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+	ntab_upload_r3(dev, B43_NTAB_NOISEVAR0_R3, b43_ntab_noisevar0_r3);
+	ntab_upload_r3(dev, B43_NTAB_NOISEVAR1_R3, b43_ntab_noisevar1_r3);
+	ntab_upload_r3(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+	ntab_upload_r3(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+	ntab_upload_r3(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+	ntab_upload_r3(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+	ntab_upload_r3(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_ESTPLT_R3,
+		       b43_ntab_estimatepowerlt0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_ESTPLT_R3,
+		       b43_ntab_estimatepowerlt1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+	ntab_upload_r3(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+	ntab_upload_r3(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
 
 	/* Volatile tables */
 	/* TODO */
 }
+
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+	struct b43_wldev *dev, bool ghz5, bool ext_lna)
+{
+	struct nphy_gain_ctl_workaround_entry *e;
+	u8 phy_idx;
+
+	B43_WARN_ON(dev->phy.rev < 3);
+	if (dev->phy.rev >= 5)
+		phy_idx = 2;
+	else if (dev->phy.rev == 4)
+		phy_idx = 1;
+	else
+		phy_idx = 0;
+
+	e = &nphy_gain_ctl_workaround[ghz5][phy_idx];
+
+	/* Only one entry differs for external LNA, so instead making whole
+	 * table 2 times bigger, hack is here
+	 */
+	if (!ghz5 && dev->phy.rev >= 5 && ext_lna) {
+		e->rfseq_init[0] &= 0x0FFF;
+		e->rfseq_init[1] &= 0x0FFF;
+		e->rfseq_init[2] &= 0x0FFF;
+		e->rfseq_init[3] &= 0x0FFF;
+		e->init_gain &= 0x0FFF;
+	}
+
+	return e;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/tables_nphy.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43/tables_nphy.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/tables_nphy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/tables_nphy.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,31 @@
 	u8 val_addr1;
 };
 
+struct nphy_gain_ctl_workaround_entry {
+	s8 lna1_gain[4];
+	s8 lna2_gain[4];
+	u8 gain_db[10];
+	u8 gain_bits[10];
+
+	u16 init_gain;
+	u16 rfseq_init[4];
+
+	u16 cliphi_gain;
+	u16 clipmd_gain;
+	u16 cliplo_gain;
+
+	u16 crsmin;
+	u16 crsminl;
+	u16 crsminu;
+
+	u16 nbclip;
+	u16 wlclip;
+};
+
+/* Get entry with workaround values for gain ctl. Does not return NULL. */
+struct nphy_gain_ctl_workaround_entry *b43_nphy_get_gain_ctl_workaround_ent(
+	struct b43_wldev *dev, bool ghz5, bool ext_lna);
+
 /* Get the NPHY Channel Switch Table entry for a channel.
  * Returns NULL on failure to find an entry. */
 const struct b43_nphy_channeltab_entry_rev2 *
@@ -109,6 +134,33 @@
 #define B43_NTAB_C1_LOFEEDTH		B43_NTAB16(0x1B, 0x1C0) /* Local Oscillator Feed Through Lookup Table Core 1 */
 #define B43_NTAB_C1_LOFEEDTH_SIZE	128
 
+/* Static N-PHY tables, PHY revision >= 3 */
+#define B43_NTAB_FRAMESTRUCT_R3		B43_NTAB32(10, 000) /* frame struct  */
+#define B43_NTAB_PILOT_R3		B43_NTAB16(11, 000) /* pilot  */
+#define B43_NTAB_TMAP_R3		B43_NTAB32(12, 000) /* TM AP  */
+#define B43_NTAB_INTLEVEL_R3		B43_NTAB32(13, 000) /* INT LV  */
+#define B43_NTAB_TDTRN_R3		B43_NTAB32(14, 000) /* TD TRN  */
+#define B43_NTAB_NOISEVAR0_R3		B43_NTAB32(16, 000) /* noise variance 0  */
+#define B43_NTAB_NOISEVAR1_R3		B43_NTAB32(16, 128) /* noise variance 1  */
+#define B43_NTAB_MCS_R3			B43_NTAB16(18, 000) /* MCS  */
+#define B43_NTAB_TDI20A0_R3		B43_NTAB32(19, 128) /* TDI 20/0  */
+#define B43_NTAB_TDI20A1_R3		B43_NTAB32(19, 256) /* TDI 20/1  */
+#define B43_NTAB_TDI40A0_R3		B43_NTAB32(19, 640) /* TDI 40/0  */
+#define B43_NTAB_TDI40A1_R3		B43_NTAB32(19, 768) /* TDI 40/1  */
+#define B43_NTAB_PILOTLT_R3		B43_NTAB32(20, 000) /* PLT lookup  */
+#define B43_NTAB_CHANEST_R3		B43_NTAB32(22, 000) /* channel estimate  */
+#define B43_NTAB_FRAMELT_R3		B43_NTAB8 (24, 000) /* frame lookup  */
+#define B43_NTAB_C0_ESTPLT_R3		B43_NTAB8 (26, 000) /* estimated power lookup 0  */
+#define B43_NTAB_C1_ESTPLT_R3		B43_NTAB8 (27, 000) /* estimated power lookup 1  */
+#define B43_NTAB_C0_ADJPLT_R3		B43_NTAB8 (26, 064) /* adjusted power lookup 0  */
+#define B43_NTAB_C1_ADJPLT_R3		B43_NTAB8 (27, 064) /* adjusted power lookup 1  */
+#define B43_NTAB_C0_GAINCTL_R3		B43_NTAB32(26, 192) /* gain control lookup 0  */
+#define B43_NTAB_C1_GAINCTL_R3		B43_NTAB32(27, 192) /* gain control lookup 1  */
+#define B43_NTAB_C0_IQLT_R3		B43_NTAB32(26, 320) /* I/Q lookup 0  */
+#define B43_NTAB_C1_IQLT_R3		B43_NTAB32(27, 320) /* I/Q lookup 1  */
+#define B43_NTAB_C0_LOFEEDTH_R3		B43_NTAB16(26, 448) /* Local Oscillator Feed Through lookup 0  */
+#define B43_NTAB_C1_LOFEEDTH_R3		B43_NTAB16(27, 448) /* Local Oscillator Feed Through lookup 1 */
+
 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_40_SIZE	18
 #define B43_NTAB_TX_IQLO_CAL_LOFT_LADDER_20_SIZE	18
 #define B43_NTAB_TX_IQLO_CAL_IQIMB_LADDER_40_SIZE	18
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/xmit.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43/xmit.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/xmit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/xmit.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,36 @@
 #include "dma.h"
 #include "pio.h"
 
+static const struct b43_tx_legacy_rate_phy_ctl_entry b43_tx_legacy_rate_phy_ctl[] = {
+	{ B43_CCK_RATE_1MB,	0x0,			0x0 },
+	{ B43_CCK_RATE_2MB,	0x0,			0x1 },
+	{ B43_CCK_RATE_5MB,	0x0,			0x2 },
+	{ B43_CCK_RATE_11MB,	0x0,			0x3 },
+	{ B43_OFDM_RATE_6MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_BPSK },
+	{ B43_OFDM_RATE_9MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_BPSK },
+	{ B43_OFDM_RATE_12MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QPSK },
+	{ B43_OFDM_RATE_18MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QPSK },
+	{ B43_OFDM_RATE_24MB,	B43_TXH_PHY1_CRATE_1_2,	B43_TXH_PHY1_MODUL_QAM16 },
+	{ B43_OFDM_RATE_36MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM16 },
+	{ B43_OFDM_RATE_48MB,	B43_TXH_PHY1_CRATE_2_3,	B43_TXH_PHY1_MODUL_QAM64 },
+	{ B43_OFDM_RATE_54MB,	B43_TXH_PHY1_CRATE_3_4,	B43_TXH_PHY1_MODUL_QAM64 },
+};
+
+static const struct b43_tx_legacy_rate_phy_ctl_entry *
+b43_tx_legacy_rate_phy_ctl_ent(u8 bitrate)
+{
+	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
+	unsigned int i;
+
+	for (i = 0; i < ARRAY_SIZE(b43_tx_legacy_rate_phy_ctl); i++) {
+		e = &(b43_tx_legacy_rate_phy_ctl[i]);
+		if (e->bitrate == bitrate)
+			return e;
+	}
+
+	B43_WARN_ON(1);
+	return NULL;
+}
 
 /* Extract the bitrate index out of a CCK PLCP header. */
 static int b43_plcp_get_bitrate_idx_cck(struct b43_plcp_hdr6 *plcp)
@@ -145,6 +175,34 @@
 	}
 }
 
+static u16 b43_generate_tx_phy_ctl1(struct b43_wldev *dev, u8 bitrate)
+{
+	const struct b43_phy *phy = &dev->phy;
+	const struct b43_tx_legacy_rate_phy_ctl_entry *e;
+	u16 control = 0;
+	u16 bw;
+
+	if (phy->type == B43_PHYTYPE_LP)
+		bw = B43_TXH_PHY1_BW_20;
+	else /* FIXME */
+		bw = B43_TXH_PHY1_BW_20;
+
+	if (0) { /* FIXME: MIMO */
+	} else if (b43_is_cck_rate(bitrate) && phy->type != B43_PHYTYPE_LP) {
+		control = bw;
+	} else {
+		control = bw;
+		e = b43_tx_legacy_rate_phy_ctl_ent(bitrate);
+		if (e) {
+			control |= e->coding_rate;
+			control |= e->modulation;
+		}
+		control |= B43_TXH_PHY1_MODE_SISO;
+	}
+
+	return control;
+}
+
 static u8 b43_calc_fallback_rate(u8 bitrate)
 {
 	switch (bitrate) {
@@ -437,6 +495,14 @@
 			extra_ft |= B43_TXH_EFT_RTSFB_OFDM;
 		else
 			extra_ft |= B43_TXH_EFT_RTSFB_CCK;
+
+		if (rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS &&
+		    phy->type == B43_PHYTYPE_N) {
+			txhdr->phy_ctl1_rts = cpu_to_le16(
+				b43_generate_tx_phy_ctl1(dev, rts_rate));
+			txhdr->phy_ctl1_rts_fb = cpu_to_le16(
+				b43_generate_tx_phy_ctl1(dev, rts_rate_fb));
+		}
 	}
 
 	/* Magic cookie */
@@ -445,6 +511,13 @@
 	else
 		txhdr->new_format.cookie = cpu_to_le16(cookie);
 
+	if (phy->type == B43_PHYTYPE_N) {
+		txhdr->phy_ctl1 =
+			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate));
+		txhdr->phy_ctl1_fb =
+			cpu_to_le16(b43_generate_tx_phy_ctl1(dev, rate_fb));
+	}
+
 	/* Apply the bitfields */
 	txhdr->mac_ctl = cpu_to_le32(mac_ctl);
 	txhdr->phy_ctl = cpu_to_le16(phy_ctl);
@@ -652,7 +725,7 @@
 		status.mactime += mactime;
 		if (low_mactime_now <= mactime)
 			status.mactime -= 0x10000;
-		status.flag |= RX_FLAG_TSFT;
+		status.flag |= RX_FLAG_MACTIME_MPDU;
 	}
 
 	chanid = (chanstat & B43_RX_CHAN_ID) >> B43_RX_CHAN_ID_SHIFT;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43/xmit.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43/xmit.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43/xmit.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43/xmit.h	2011-05-19 00:06:34.000000000 -0400
@@ -73,6 +73,12 @@
 	} __packed;
 } __packed;
 
+struct b43_tx_legacy_rate_phy_ctl_entry {
+	u8 bitrate;
+	u16 coding_rate;
+	u16 modulation;
+};
+
 /* MAC TX control */
 #define B43_TXH_MAC_USEFBR		0x10000000 /* Use fallback rate for this AMPDU */
 #define B43_TXH_MAC_KEYIDX		0x0FF00000 /* Security key index */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43legacy/b43legacy.h linux-libre-2.6.39-gnu/drivers/net/wireless/b43legacy/b43legacy.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43legacy/b43legacy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43legacy/b43legacy.h	2011-05-19 00:06:34.000000000 -0400
@@ -488,7 +488,7 @@
 	/* Current Interference Mitigation mode */
 	int interfmode;
 	/* Stack of saved values from the Interference Mitigation code.
-	 * Each value in the stack is layed out as follows:
+	 * Each value in the stack is laid out as follows:
 	 * bit 0-11:  offset
 	 * bit 12-15: register ID
 	 * bit 16-32: value
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43legacy/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43legacy/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43legacy/main.c	2012-03-24 01:10:46.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43legacy/main.c	2012-03-24 03:32:20.000000000 -0400
@@ -2438,8 +2438,8 @@
 	return err;
 }
 
-static int b43legacy_op_tx(struct ieee80211_hw *hw,
-			   struct sk_buff *skb)
+static void b43legacy_op_tx(struct ieee80211_hw *hw,
+			    struct sk_buff *skb)
 {
 	struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw);
 	struct b43legacy_wldev *dev = wl->current_dev;
@@ -2462,7 +2462,6 @@
 		/* Drop the packet. */
 		dev_kfree_skb_any(skb);
 	}
-	return NETDEV_TX_OK;
 }
 
 static int b43legacy_op_conf_tx(struct ieee80211_hw *hw, u16 queue,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/b43legacy/xmit.c linux-libre-2.6.39-gnu/drivers/net/wireless/b43legacy/xmit.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/b43legacy/xmit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/b43legacy/xmit.c	2011-05-19 00:06:34.000000000 -0400
@@ -572,7 +572,7 @@
 		status.mactime += mactime;
 		if (low_mactime_now <= mactime)
 			status.mactime -= 0x10000;
-		status.flag |= RX_FLAG_TSFT;
+		status.flag |= RX_FLAG_MACTIME_MPDU;
 	}
 
 	chanid = (chanstat & B43legacy_RX_CHAN_ID) >>
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_ap.c linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_ap.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_ap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_ap.c	2011-05-19 00:06:34.000000000 -0400
@@ -2359,7 +2359,7 @@
 }
 
 
-/* Translate our list of Access Points & Stations to a card independant
+/* Translate our list of Access Points & Stations to a card independent
  * format that the Wireless Tools will understand - Jean II */
 int prism2_ap_translate_scan(struct net_device *dev,
 			     struct iw_request_info *info, char *buffer)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_ap.h linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_ap.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_ap.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_ap.h	2011-05-19 00:06:34.000000000 -0400
@@ -114,7 +114,7 @@
  * has passed since last received frame from the station, a nullfunc data
  * frame is sent to the station. If this frame is not acknowledged and no other
  * frames have been received, the station will be disassociated after
- * AP_DISASSOC_DELAY. Similarily, a the station will be deauthenticated after
+ * AP_DISASSOC_DELAY. Similarly, a the station will be deauthenticated after
  * AP_DEAUTH_DELAY. AP_TIMEOUT_RESOLUTION is the resolution that is used with
  * max inactivity timer. */
 #define AP_MAX_INACTIVITY_SEC (5 * 60)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_config.h linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_config.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_config.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_config.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,9 +30,9 @@
 
 /* Following defines can be used to remove unneeded parts of the driver, e.g.,
  * to limit the size of the kernel module. Definitions can be added here in
- * hostap_config.h or they can be added to make command with EXTRA_CFLAGS,
+ * hostap_config.h or they can be added to make command with ccflags-y,
  * e.g.,
- * 'make pccard EXTRA_CFLAGS="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
+ * 'make pccard ccflags-y="-DPRISM2_NO_DEBUG -DPRISM2_NO_PROCFS_DEBUG"'
  */
 
 /* Do not include debug messages into the driver */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_ioctl.c linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_ioctl.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -1945,7 +1945,7 @@
 }
 
 
-/* Translate scan data returned from the card to a card independant
+/* Translate scan data returned from the card to a card independent
  * format that the Wireless Tools will understand - Jean II */
 static inline int prism2_translate_scan(local_info_t *local,
 					struct iw_request_info *info,
@@ -2043,7 +2043,7 @@
 		 * until results are ready for various reasons.
 		 * First, managing wait queues is complex and racy
 		 * (there may be multiple simultaneous callers).
-		 * Second, we grab some rtnetlink lock before comming
+		 * Second, we grab some rtnetlink lock before coming
 		 * here (in dev_ioctl()).
 		 * Third, the caller can wait on the Wireless Event
 		 * - Jean II */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_wlan.h linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_wlan.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/hostap/hostap_wlan.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/hostap/hostap_wlan.h	2011-05-19 00:06:34.000000000 -0400
@@ -853,7 +853,7 @@
 	struct work_struct comms_qual_update;
 
 	/* RSSI to dBm adjustment (for RX descriptor fields) */
-	int rssi_to_dBm; /* substract from RSSI to get approximate dBm value */
+	int rssi_to_dBm; /* subtract from RSSI to get approximate dBm value */
 
 	/* BSS list / protected by local->lock */
 	struct list_head bss_list;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2100.c linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2100.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2100.c	2012-03-24 01:11:47.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2100.c	2012-03-24 03:32:51.000000000 -0400
@@ -63,7 +63,7 @@
 firmware if a Command or Data is being sent.  If it is Command, all of the
 command information is contained within the physical address referred to by the
 TBD.  If it is Data, the first TBD indicates the type of data packet, number
-of fragments, etc.  The next TBD then referrs to the actual packet location.
+of fragments, etc.  The next TBD then refers to the actual packet location.
 
 The Tx flow cycle is as follows:
 
@@ -706,11 +706,10 @@
 		netif_stop_queue(priv->net_dev);
 		priv->status |= STATUS_RESET_PENDING;
 		if (priv->reset_backoff)
-			queue_delayed_work(priv->workqueue, &priv->reset_work,
-					   priv->reset_backoff * HZ);
+			schedule_delayed_work(&priv->reset_work,
+					      priv->reset_backoff * HZ);
 		else
-			queue_delayed_work(priv->workqueue, &priv->reset_work,
-					   0);
+			schedule_delayed_work(&priv->reset_work, 0);
 
 		if (priv->reset_backoff < MAX_RESET_BACKOFF)
 			priv->reset_backoff++;
@@ -1397,7 +1396,7 @@
 }
 
 /*
- * Send the CARD_DISABLE_PHY_OFF comamnd to the card to disable it
+ * Send the CARD_DISABLE_PHY_OFF command to the card to disable it
  *
  * After disabling, if the card was associated, a STATUS_ASSN_LOST will be sent.
  *
@@ -1474,7 +1473,7 @@
 
 	if (priv->stop_hang_check) {
 		priv->stop_hang_check = 0;
-		queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+		schedule_delayed_work(&priv->hang_check, HZ / 2);
 	}
 
       fail_up:
@@ -1808,8 +1807,8 @@
 
 		if (priv->stop_rf_kill) {
 			priv->stop_rf_kill = 0;
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(HZ));
 		}
 
 		deferred = 1;
@@ -2086,7 +2085,7 @@
 	priv->status |= STATUS_ASSOCIATING;
 	priv->connect_start = get_seconds();
 
-	queue_delayed_work(priv->workqueue, &priv->wx_event_work, HZ / 10);
+	schedule_delayed_work(&priv->wx_event_work, HZ / 10);
 }
 
 static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid,
@@ -2166,9 +2165,9 @@
 		return;
 
 	if (priv->status & STATUS_SECURITY_UPDATED)
-		queue_delayed_work(priv->workqueue, &priv->security_work, 0);
+		schedule_delayed_work(&priv->security_work, 0);
 
-	queue_delayed_work(priv->workqueue, &priv->wx_event_work, 0);
+	schedule_delayed_work(&priv->wx_event_work, 0);
 }
 
 static void isr_indicate_rf_kill(struct ipw2100_priv *priv, u32 status)
@@ -2183,8 +2182,7 @@
 	/* Make sure the RF Kill check timer is running */
 	priv->stop_rf_kill = 0;
 	cancel_delayed_work(&priv->rf_kill);
-	queue_delayed_work(priv->workqueue, &priv->rf_kill,
-			   round_jiffies_relative(HZ));
+	schedule_delayed_work(&priv->rf_kill, round_jiffies_relative(HZ));
 }
 
 static void send_scan_event(void *data)
@@ -2219,13 +2217,12 @@
 	/* Only userspace-requested scan completion events go out immediately */
 	if (!priv->user_requested_scan) {
 		if (!delayed_work_pending(&priv->scan_event_later))
-			queue_delayed_work(priv->workqueue,
-					&priv->scan_event_later,
-					round_jiffies_relative(msecs_to_jiffies(4000)));
+			schedule_delayed_work(&priv->scan_event_later,
+					      round_jiffies_relative(msecs_to_jiffies(4000)));
 	} else {
 		priv->user_requested_scan = 0;
 		cancel_delayed_work(&priv->scan_event_later);
-		queue_work(priv->workqueue, &priv->scan_event_now);
+		schedule_work(&priv->scan_event_now);
 	}
 }
 
@@ -4329,8 +4326,8 @@
 			/* Make sure the RF_KILL check timer is running */
 			priv->stop_rf_kill = 0;
 			cancel_delayed_work(&priv->rf_kill);
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(HZ));
 		} else
 			schedule_reset(priv);
 	}
@@ -4461,20 +4458,17 @@
 	IPW_DEBUG_INFO("exit\n");
 }
 
-static void ipw2100_kill_workqueue(struct ipw2100_priv *priv)
+static void ipw2100_kill_works(struct ipw2100_priv *priv)
 {
-	if (priv->workqueue) {
-		priv->stop_rf_kill = 1;
-		priv->stop_hang_check = 1;
-		cancel_delayed_work(&priv->reset_work);
-		cancel_delayed_work(&priv->security_work);
-		cancel_delayed_work(&priv->wx_event_work);
-		cancel_delayed_work(&priv->hang_check);
-		cancel_delayed_work(&priv->rf_kill);
-		cancel_delayed_work(&priv->scan_event_later);
-		destroy_workqueue(priv->workqueue);
-		priv->workqueue = NULL;
-	}
+	priv->stop_rf_kill = 1;
+	priv->stop_hang_check = 1;
+	cancel_delayed_work_sync(&priv->reset_work);
+	cancel_delayed_work_sync(&priv->security_work);
+	cancel_delayed_work_sync(&priv->wx_event_work);
+	cancel_delayed_work_sync(&priv->hang_check);
+	cancel_delayed_work_sync(&priv->rf_kill);
+	cancel_work_sync(&priv->scan_event_now);
+	cancel_delayed_work_sync(&priv->scan_event_later);
 }
 
 static int ipw2100_tx_allocate(struct ipw2100_priv *priv)
@@ -6046,7 +6040,7 @@
 	priv->last_rtc = rtc;
 
 	if (!priv->stop_hang_check)
-		queue_delayed_work(priv->workqueue, &priv->hang_check, HZ / 2);
+		schedule_delayed_work(&priv->hang_check, HZ / 2);
 
 	spin_unlock_irqrestore(&priv->low_lock, flags);
 }
@@ -6062,8 +6056,8 @@
 	if (rf_kill_active(priv)) {
 		IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
 		if (!priv->stop_rf_kill)
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(HZ));
 		goto exit_unlock;
 	}
 
@@ -6209,8 +6203,6 @@
 	INIT_LIST_HEAD(&priv->fw_pend_list);
 	INIT_STAT(&priv->fw_pend_stat);
 
-	priv->workqueue = create_workqueue(DRV_NAME);
-
 	INIT_DELAYED_WORK(&priv->reset_work, ipw2100_reset_adapter);
 	INIT_DELAYED_WORK(&priv->security_work, ipw2100_security_work);
 	INIT_DELAYED_WORK(&priv->wx_event_work, ipw2100_wx_event_work);
@@ -6410,7 +6402,7 @@
 		if (dev->irq)
 			free_irq(dev->irq, priv);
 
-		ipw2100_kill_workqueue(priv);
+		ipw2100_kill_works(priv);
 
 		/* These are safe to call even if they weren't allocated */
 		ipw2100_queues_free(priv);
@@ -6460,9 +6452,7 @@
 		 * first, then close() will crash. */
 		unregister_netdev(dev);
 
-		/* ipw2100_down will ensure that there is no more pending work
-		 * in the workqueue's, so we can safely remove them now. */
-		ipw2100_kill_workqueue(priv);
+		ipw2100_kill_works(priv);
 
 		ipw2100_queues_free(priv);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2100.h linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2100.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2100.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2100.h	2011-05-19 00:06:34.000000000 -0400
@@ -580,7 +580,6 @@
 
 	struct tasklet_struct irq_tasklet;
 
-	struct workqueue_struct *workqueue;
 	struct delayed_work reset_work;
 	struct delayed_work security_work;
 	struct delayed_work wx_event_work;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2200.c linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2200.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2200.c	2012-03-24 01:12:01.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2200.c	2012-03-24 03:32:58.000000000 -0400
@@ -894,9 +894,8 @@
 
 		/* If we aren't associated, schedule turning the LED off */
 		if (!(priv->status & STATUS_ASSOCIATED))
-			queue_delayed_work(priv->workqueue,
-					   &priv->led_link_off,
-					   LD_TIME_LINK_ON);
+			schedule_delayed_work(&priv->led_link_off,
+					      LD_TIME_LINK_ON);
 	}
 
 	spin_unlock_irqrestore(&priv->lock, flags);
@@ -939,8 +938,8 @@
 		 * turning the LED on (blink while unassociated) */
 		if (!(priv->status & STATUS_RF_KILL_MASK) &&
 		    !(priv->status & STATUS_ASSOCIATED))
-			queue_delayed_work(priv->workqueue, &priv->led_link_on,
-					   LD_TIME_LINK_OFF);
+			schedule_delayed_work(&priv->led_link_on,
+					      LD_TIME_LINK_OFF);
 
 	}
 
@@ -980,13 +979,11 @@
 		priv->status |= STATUS_LED_ACT_ON;
 
 		cancel_delayed_work(&priv->led_act_off);
-		queue_delayed_work(priv->workqueue, &priv->led_act_off,
-				   LD_TIME_ACT_ON);
+		schedule_delayed_work(&priv->led_act_off, LD_TIME_ACT_ON);
 	} else {
 		/* Reschedule LED off for full time period */
 		cancel_delayed_work(&priv->led_act_off);
-		queue_delayed_work(priv->workqueue, &priv->led_act_off,
-				   LD_TIME_ACT_ON);
+		schedule_delayed_work(&priv->led_act_off, LD_TIME_ACT_ON);
 	}
 }
 
@@ -1184,7 +1181,7 @@
 /*
  * The following adds a new attribute to the sysfs representation
  * of this device driver (i.e. a new file in /sys/bus/pci/drivers/ipw/)
- * used for controling the debug level.
+ * used for controlling the debug level.
  *
  * See the level definitions in ipw for details.
  */
@@ -1795,13 +1792,11 @@
 	if (disable_radio) {
 		priv->status |= STATUS_RF_KILL_SW;
 
-		if (priv->workqueue) {
-			cancel_delayed_work(&priv->request_scan);
-			cancel_delayed_work(&priv->request_direct_scan);
-			cancel_delayed_work(&priv->request_passive_scan);
-			cancel_delayed_work(&priv->scan_event);
-		}
-		queue_work(priv->workqueue, &priv->down);
+		cancel_delayed_work(&priv->request_scan);
+		cancel_delayed_work(&priv->request_direct_scan);
+		cancel_delayed_work(&priv->request_passive_scan);
+		cancel_delayed_work(&priv->scan_event);
+		schedule_work(&priv->down);
 	} else {
 		priv->status &= ~STATUS_RF_KILL_SW;
 		if (rf_kill_active(priv)) {
@@ -1809,10 +1804,10 @@
 					  "disabled by HW switch\n");
 			/* Make sure the RF_KILL check timer is running */
 			cancel_delayed_work(&priv->rf_kill);
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   round_jiffies_relative(2 * HZ));
+			schedule_delayed_work(&priv->rf_kill,
+					      round_jiffies_relative(2 * HZ));
 		} else
-			queue_work(priv->workqueue, &priv->up);
+			schedule_work(&priv->up);
 	}
 
 	return 1;
@@ -2063,7 +2058,7 @@
 		cancel_delayed_work(&priv->request_passive_scan);
 		cancel_delayed_work(&priv->scan_event);
 		schedule_work(&priv->link_down);
-		queue_delayed_work(priv->workqueue, &priv->rf_kill, 2 * HZ);
+		schedule_delayed_work(&priv->rf_kill, 2 * HZ);
 		handled |= IPW_INTA_BIT_RF_KILL_DONE;
 	}
 
@@ -2103,7 +2098,7 @@
 		priv->status &= ~STATUS_HCMD_ACTIVE;
 		wake_up_interruptible(&priv->wait_command_queue);
 
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 		handled |= IPW_INTA_BIT_FATAL_ERROR;
 	}
 
@@ -2323,11 +2318,6 @@
 	return ipw_send_cmd_pdu(priv, IPW_CMD_ADAPTER_ADDRESS, ETH_ALEN, mac);
 }
 
-/*
- * NOTE: This must be executed from our workqueue as it results in udelay
- * being called which may corrupt the keyboard if executed on default
- * workqueue
- */
 static void ipw_adapter_restart(void *adapter)
 {
 	struct ipw_priv *priv = adapter;
@@ -2368,13 +2358,13 @@
 		IPW_DEBUG_SCAN("Scan completion watchdog resetting "
 			       "adapter after (%dms).\n",
 			       jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 	} else if (priv->status & STATUS_SCANNING) {
 		IPW_DEBUG_SCAN("Scan completion watchdog aborting scan "
 			       "after (%dms).\n",
 			       jiffies_to_msecs(IPW_SCAN_CHECK_WATCHDOG));
 		ipw_abort_scan(priv);
-		queue_delayed_work(priv->workqueue, &priv->scan_check, HZ);
+		schedule_delayed_work(&priv->scan_check, HZ);
 	}
 }
 
@@ -3773,7 +3763,7 @@
 
 	q->txb = kmalloc(sizeof(q->txb[0]) * count, GFP_KERNEL);
 	if (!q->txb) {
-		IPW_ERROR("vmalloc for auxilary BD structures failed\n");
+		IPW_ERROR("vmalloc for auxiliary BD structures failed\n");
 		return -ENOMEM;
 	}
 
@@ -3943,7 +3933,7 @@
 
 	if (priv->status & STATUS_ASSOCIATING) {
 		IPW_DEBUG_ASSOC("Disassociating while associating.\n");
-		queue_work(priv->workqueue, &priv->disassociate);
+		schedule_work(&priv->disassociate);
 		return;
 	}
 
@@ -4360,8 +4350,7 @@
 
 	priv->quality = quality;
 
-	queue_delayed_work(priv->workqueue, &priv->gather_stats,
-			   IPW_STATS_INTERVAL);
+	schedule_delayed_work(&priv->gather_stats, IPW_STATS_INTERVAL);
 }
 
 static void ipw_bg_gather_stats(struct work_struct *work)
@@ -4396,10 +4385,10 @@
 			IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF |
 				  IPW_DL_STATE,
 				  "Aborting scan with missed beacon.\n");
-			queue_work(priv->workqueue, &priv->abort_scan);
+			schedule_work(&priv->abort_scan);
 		}
 
-		queue_work(priv->workqueue, &priv->disassociate);
+		schedule_work(&priv->disassociate);
 		return;
 	}
 
@@ -4425,8 +4414,7 @@
 		if (!(priv->status & STATUS_ROAMING)) {
 			priv->status |= STATUS_ROAMING;
 			if (!(priv->status & STATUS_SCANNING))
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 		}
 		return;
 	}
@@ -4439,7 +4427,7 @@
 		 * channels..) */
 		IPW_DEBUG(IPW_DL_INFO | IPW_DL_NOTIF | IPW_DL_STATE,
 			  "Aborting scan with missed beacon.\n");
-		queue_work(priv->workqueue, &priv->abort_scan);
+		schedule_work(&priv->abort_scan);
 	}
 
 	IPW_DEBUG_NOTIF("Missed beacon: %d\n", missed_count);
@@ -4462,8 +4450,8 @@
 	/* Only userspace-requested scan completion events go out immediately */
 	if (!priv->user_requested_scan) {
 		if (!delayed_work_pending(&priv->scan_event))
-			queue_delayed_work(priv->workqueue, &priv->scan_event,
-					 round_jiffies_relative(msecs_to_jiffies(4000)));
+			schedule_delayed_work(&priv->scan_event,
+					      round_jiffies_relative(msecs_to_jiffies(4000)));
 	} else {
 		union iwreq_data wrqu;
 
@@ -4516,20 +4504,17 @@
 
 						IPW_DEBUG_ASSOC
 						    ("queueing adhoc check\n");
-						queue_delayed_work(priv->
-								   workqueue,
-								   &priv->
-								   adhoc_check,
-								   le16_to_cpu(priv->
-								   assoc_request.
-								   beacon_interval));
+						schedule_delayed_work(
+							&priv->adhoc_check,
+							le16_to_cpu(priv->
+							assoc_request.
+							beacon_interval));
 						break;
 					}
 
 					priv->status &= ~STATUS_ASSOCIATING;
 					priv->status |= STATUS_ASSOCIATED;
-					queue_work(priv->workqueue,
-						   &priv->system_config);
+					schedule_work(&priv->system_config);
 
 #ifdef CONFIG_IPW2200_QOS
 #define IPW_GET_PACKET_STYPE(x) WLAN_FC_GET_STYPE( \
@@ -4792,43 +4777,37 @@
 #ifdef CONFIG_IPW2200_MONITOR
 			if (priv->ieee->iw_mode == IW_MODE_MONITOR) {
 				priv->status |= STATUS_SCAN_FORCED;
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 				break;
 			}
 			priv->status &= ~STATUS_SCAN_FORCED;
 #endif				/* CONFIG_IPW2200_MONITOR */
 
 			/* Do queued direct scans first */
-			if (priv->status & STATUS_DIRECT_SCAN_PENDING) {
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_direct_scan, 0);
-			}
+			if (priv->status & STATUS_DIRECT_SCAN_PENDING)
+				schedule_delayed_work(&priv->request_direct_scan, 0);
 
 			if (!(priv->status & (STATUS_ASSOCIATED |
 					      STATUS_ASSOCIATING |
 					      STATUS_ROAMING |
 					      STATUS_DISASSOCIATING)))
-				queue_work(priv->workqueue, &priv->associate);
+				schedule_work(&priv->associate);
 			else if (priv->status & STATUS_ROAMING) {
 				if (x->status == SCAN_COMPLETED_STATUS_COMPLETE)
 					/* If a scan completed and we are in roam mode, then
 					 * the scan that completed was the one requested as a
 					 * result of entering roam... so, schedule the
 					 * roam work */
-					queue_work(priv->workqueue,
-						   &priv->roam);
+					schedule_work(&priv->roam);
 				else
 					/* Don't schedule if we aborted the scan */
 					priv->status &= ~STATUS_ROAMING;
 			} else if (priv->status & STATUS_SCAN_PENDING)
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 			else if (priv->config & CFG_BACKGROUND_SCAN
 				 && priv->status & STATUS_ASSOCIATED)
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan,
-						   round_jiffies_relative(HZ));
+				schedule_delayed_work(&priv->request_scan,
+						      round_jiffies_relative(HZ));
 
 			/* Send an empty event to user space.
 			 * We don't send the received data on the event because
@@ -5192,7 +5171,7 @@
 	/* If the pre-allocated buffer pool is dropping low, schedule to
 	 * refill it */
 	if (rxq->free_count <= RX_LOW_WATERMARK)
-		queue_work(priv->workqueue, &priv->rx_replenish);
+		schedule_work(&priv->rx_replenish);
 
 	/* If we've added more space for the firmware to place data, tell it */
 	if (write != rxq->write)
@@ -5602,7 +5581,7 @@
 		return 0;
 	}
 
-	/* Verify privacy compatability */
+	/* Verify privacy compatibility */
 	if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
 	    ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
 		IPW_DEBUG_MERGE("Network '%s (%pM)' excluded "
@@ -5829,7 +5808,7 @@
 		return 0;
 	}
 
-	/* Verify privacy compatability */
+	/* Verify privacy compatibility */
 	if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) !=
 	    ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) {
 		IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded "
@@ -6133,8 +6112,8 @@
 		return;
 	}
 
-	queue_delayed_work(priv->workqueue, &priv->adhoc_check,
-			   le16_to_cpu(priv->assoc_request.beacon_interval));
+	schedule_delayed_work(&priv->adhoc_check,
+			      le16_to_cpu(priv->assoc_request.beacon_interval));
 }
 
 static void ipw_bg_adhoc_check(struct work_struct *work)
@@ -6523,8 +6502,7 @@
 	} else
 		priv->status &= ~STATUS_SCAN_PENDING;
 
-	queue_delayed_work(priv->workqueue, &priv->scan_check,
-			   IPW_SCAN_CHECK_WATCHDOG);
+	schedule_delayed_work(&priv->scan_check, IPW_SCAN_CHECK_WATCHDOG);
 done:
 	mutex_unlock(&priv->mutex);
 	return err;
@@ -6994,8 +6972,7 @@
 				    !memcmp(network->ssid,
 					    priv->assoc_network->ssid,
 					    network->ssid_len)) {
-					queue_work(priv->workqueue,
-						   &priv->merge_networks);
+					schedule_work(&priv->merge_networks);
 				}
 	}
 
@@ -7663,7 +7640,7 @@
 	if (priv->status & STATUS_DISASSOCIATING) {
 		IPW_DEBUG_ASSOC("Not attempting association (in "
 				"disassociating)\n ");
-		queue_work(priv->workqueue, &priv->associate);
+		schedule_work(&priv->associate);
 		return 0;
 	}
 
@@ -7731,12 +7708,10 @@
 
 		if (!(priv->status & STATUS_SCANNING)) {
 			if (!(priv->config & CFG_SPEED_SCAN))
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan,
-						   SCAN_INTERVAL);
+				schedule_delayed_work(&priv->request_scan,
+						      SCAN_INTERVAL);
 			else
-				queue_delayed_work(priv->workqueue,
-						   &priv->request_scan, 0);
+				schedule_delayed_work(&priv->request_scan, 0);
 		}
 
 		return 0;
@@ -8209,7 +8184,7 @@
 static int is_network_packet(struct ipw_priv *priv,
 				    struct libipw_hdr_4addr *header)
 {
-	/* Filter incoming packets to determine if they are targetted toward
+	/* Filter incoming packets to determine if they are targeted toward
 	 * this network, discarding packets coming from ourselves */
 	switch (priv->ieee->iw_mode) {
 	case IW_MODE_ADHOC:	/* Header: Dest. | Source    | BSSID */
@@ -8365,9 +8340,9 @@
 }
 
 /*
- * Main entry function for recieving a packet with 80211 headers.  This
+ * Main entry function for receiving a packet with 80211 headers.  This
  * should be called when ever the FW has notified us that there is a new
- * skb in the recieve queue.
+ * skb in the receive queue.
  */
 static void ipw_rx(struct ipw_priv *priv)
 {
@@ -8708,7 +8683,7 @@
  * functions defined in ipw_main to provide the HW interaction.
  *
  * The exception to this is the use of the ipw_get_ordinal()
- * function used to poll the hardware vs. making unecessary calls.
+ * function used to poll the hardware vs. making unnecessary calls.
  *
  */
 
@@ -8899,7 +8874,7 @@
 
 	priv->ieee->iw_mode = wrqu->mode;
 
-	queue_work(priv->workqueue, &priv->adapter_restart);
+	schedule_work(&priv->adapter_restart);
 	mutex_unlock(&priv->mutex);
 	return err;
 }
@@ -9598,7 +9573,7 @@
 
 	IPW_DEBUG_WX("Start scan\n");
 
-	queue_delayed_work(priv->workqueue, work, 0);
+	schedule_delayed_work(work, 0);
 
 	return 0;
 }
@@ -9937,7 +9912,7 @@
 #else
 			priv->net_dev->type = ARPHRD_IEEE80211;
 #endif
-			queue_work(priv->workqueue, &priv->adapter_restart);
+			schedule_work(&priv->adapter_restart);
 		}
 
 		ipw_set_channel(priv, parms[1]);
@@ -9947,7 +9922,7 @@
 			return 0;
 		}
 		priv->net_dev->type = ARPHRD_ETHER;
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 	}
 	mutex_unlock(&priv->mutex);
 	return 0;
@@ -9961,7 +9936,7 @@
 {
 	struct ipw_priv *priv = libipw_priv(dev);
 	IPW_DEBUG_WX("RESET\n");
-	queue_work(priv->workqueue, &priv->adapter_restart);
+	schedule_work(&priv->adapter_restart);
 	return 0;
 }
 
@@ -10444,7 +10419,7 @@
 
 	memset(&dummystats, 0, sizeof(dummystats));
 
-	/* Filtering of fragment chains is done agains the first fragment */
+	/* Filtering of fragment chains is done against the first fragment */
 	hdr = (void *)txb->fragments[0]->data;
 	if (libipw_is_management(le16_to_cpu(hdr->frame_control))) {
 		if (filter & IPW_PROM_NO_MGMT)
@@ -10551,7 +10526,7 @@
 	memcpy(priv->mac_addr, addr->sa_data, ETH_ALEN);
 	printk(KERN_INFO "%s: Setting MAC to %pM\n",
 	       priv->net_dev->name, priv->mac_addr);
-	queue_work(priv->workqueue, &priv->adapter_restart);
+	schedule_work(&priv->adapter_restart);
 	mutex_unlock(&priv->mutex);
 	return 0;
 }
@@ -10684,9 +10659,7 @@
 
 	if (rf_kill_active(priv)) {
 		IPW_DEBUG_RF_KILL("RF Kill active, rescheduling GPIO check\n");
-		if (priv->workqueue)
-			queue_delayed_work(priv->workqueue,
-					   &priv->rf_kill, 2 * HZ);
+		schedule_delayed_work(&priv->rf_kill, 2 * HZ);
 		goto exit_unlock;
 	}
 
@@ -10697,7 +10670,7 @@
 				  "device\n");
 
 		/* we can not do an adapter restart while inside an irq lock */
-		queue_work(priv->workqueue, &priv->adapter_restart);
+		schedule_work(&priv->adapter_restart);
 	} else
 		IPW_DEBUG_RF_KILL("HW RF Kill deactivated.  SW RF Kill still "
 				  "enabled\n");
@@ -10735,7 +10708,7 @@
 	notify_wx_assoc_event(priv);
 
 	if (priv->config & CFG_BACKGROUND_SCAN)
-		queue_delayed_work(priv->workqueue, &priv->request_scan, HZ);
+		schedule_delayed_work(&priv->request_scan, HZ);
 }
 
 static void ipw_bg_link_up(struct work_struct *work)
@@ -10764,7 +10737,7 @@
 
 	if (!(priv->status & STATUS_EXIT_PENDING)) {
 		/* Queue up another scan... */
-		queue_delayed_work(priv->workqueue, &priv->request_scan, 0);
+		schedule_delayed_work(&priv->request_scan, 0);
 	} else
 		cancel_delayed_work(&priv->scan_event);
 }
@@ -10782,7 +10755,6 @@
 {
 	int ret = 0;
 
-	priv->workqueue = create_workqueue(DRV_NAME);
 	init_waitqueue_head(&priv->wait_command_queue);
 	init_waitqueue_head(&priv->wait_state);
 
@@ -11339,8 +11311,7 @@
 			IPW_WARNING("Radio Frequency Kill Switch is On:\n"
 				    "Kill switch must be turned off for "
 				    "wireless networking to work.\n");
-			queue_delayed_work(priv->workqueue, &priv->rf_kill,
-					   2 * HZ);
+			schedule_delayed_work(&priv->rf_kill, 2 * HZ);
 			return 0;
 		}
 
@@ -11350,8 +11321,7 @@
 
 			/* If configure to try and auto-associate, kick
 			 * off a scan. */
-			queue_delayed_work(priv->workqueue,
-					   &priv->request_scan, 0);
+			schedule_delayed_work(&priv->request_scan, 0);
 
 			return 0;
 		}
@@ -11817,7 +11787,7 @@
 	err = request_irq(pdev->irq, ipw_isr, IRQF_SHARED, DRV_NAME, priv);
 	if (err) {
 		IPW_ERROR("Error allocating IRQ %d\n", pdev->irq);
-		goto out_destroy_workqueue;
+		goto out_iounmap;
 	}
 
 	SET_NETDEV_DEV(net_dev, &pdev->dev);
@@ -11885,9 +11855,6 @@
 	sysfs_remove_group(&pdev->dev.kobj, &ipw_attribute_group);
       out_release_irq:
 	free_irq(pdev->irq, priv);
-      out_destroy_workqueue:
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
       out_iounmap:
 	iounmap(priv->hw_base);
       out_pci_release_regions:
@@ -11930,18 +11897,31 @@
 		kfree(priv->cmdlog);
 		priv->cmdlog = NULL;
 	}
-	/* ipw_down will ensure that there is no more pending work
-	 * in the workqueue's, so we can safely remove them now. */
-	cancel_delayed_work(&priv->adhoc_check);
-	cancel_delayed_work(&priv->gather_stats);
-	cancel_delayed_work(&priv->request_scan);
-	cancel_delayed_work(&priv->request_direct_scan);
-	cancel_delayed_work(&priv->request_passive_scan);
-	cancel_delayed_work(&priv->scan_event);
-	cancel_delayed_work(&priv->rf_kill);
-	cancel_delayed_work(&priv->scan_check);
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
+
+	/* make sure all works are inactive */
+	cancel_delayed_work_sync(&priv->adhoc_check);
+	cancel_work_sync(&priv->associate);
+	cancel_work_sync(&priv->disassociate);
+	cancel_work_sync(&priv->system_config);
+	cancel_work_sync(&priv->rx_replenish);
+	cancel_work_sync(&priv->adapter_restart);
+	cancel_delayed_work_sync(&priv->rf_kill);
+	cancel_work_sync(&priv->up);
+	cancel_work_sync(&priv->down);
+	cancel_delayed_work_sync(&priv->request_scan);
+	cancel_delayed_work_sync(&priv->request_direct_scan);
+	cancel_delayed_work_sync(&priv->request_passive_scan);
+	cancel_delayed_work_sync(&priv->scan_event);
+	cancel_delayed_work_sync(&priv->gather_stats);
+	cancel_work_sync(&priv->abort_scan);
+	cancel_work_sync(&priv->roam);
+	cancel_delayed_work_sync(&priv->scan_check);
+	cancel_work_sync(&priv->link_up);
+	cancel_work_sync(&priv->link_down);
+	cancel_delayed_work_sync(&priv->led_link_on);
+	cancel_delayed_work_sync(&priv->led_link_off);
+	cancel_delayed_work_sync(&priv->led_act_off);
+	cancel_work_sync(&priv->merge_networks);
 
 	/* Free MAC hash list for ADHOC */
 	for (i = 0; i < IPW_IBSS_MAC_HASH_SIZE; i++) {
@@ -12029,7 +12009,7 @@
 	priv->suspend_time = get_seconds() - priv->suspend_at;
 
 	/* Bring the device back up */
-	queue_work(priv->workqueue, &priv->up);
+	schedule_work(&priv->up);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2200.h linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2200.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/ipw2200.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/ipw2200.h	2011-05-19 00:06:34.000000000 -0400
@@ -961,7 +961,7 @@
 struct ipw_country_info {
 	u8 id;
 	u8 length;
-	u8 country_str[3];
+	u8 country_str[IEEE80211_COUNTRY_STRING_LEN];
 	struct ipw_country_channel_info groups[7];
 } __packed;
 
@@ -1299,8 +1299,6 @@
 	u8 direct_scan_ssid[IW_ESSID_MAX_SIZE];
 	u8 direct_scan_ssid_len;
 
-	struct workqueue_struct *workqueue;
-
 	struct delayed_work adhoc_check;
 	struct work_struct associate;
 	struct work_struct disassociate;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/libipw_rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/libipw_rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/ipw2x00/libipw_rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/ipw2x00/libipw_rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -925,7 +925,7 @@
 static u8 qos_oui[QOS_OUI_LEN] = { 0x00, 0x50, 0xF2 };
 
 /*
-* Make ther structure we read from the beacon packet has
+* Make the structure we read from the beacon packet to have
 * the right values
 */
 static int libipw_verify_qos_info(struct libipw_qos_information_element
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl3945-base.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl3945-base.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl3945-base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl3945-base.c	2012-03-24 03:33:03.000000000 -0400
@@ -0,0 +1,4288 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/ieee80211_radiotap.h>
+#include <net/mac80211.h>
+
+#include <asm/div64.h>
+
+#define DRV_NAME	"iwl3945"
+
+#include "iwl-fh.h"
+#include "iwl-3945-fh.h"
+#include "iwl-commands.h"
+#include "iwl-sta.h"
+#include "iwl-3945.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-dev.h"
+#include "iwl-spectrum.h"
+
+/*
+ * module name, copyright, version, etc.
+ */
+
+#define DRV_DESCRIPTION	\
+"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+/*
+ * add "s" to indicate spectrum measurement included.
+ * we add it here to be consistent with previous releases in which
+ * this was configurable.
+ */
+#define DRV_VERSION  IWLWIFI_VERSION VD "s"
+#define DRV_COPYRIGHT	"Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR     "<ilw@linux.intel.com>"
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+
+ /* module parameters */
+struct iwl_mod_params iwl3945_mod_params = {
+	.sw_crypto = 1,
+	.restart_fw = 1,
+	.disable_hw_scan = 1,
+	/* the rest are 0 by default */
+};
+
+/**
+ * iwl3945_get_antenna_flags - Get antenna flags for RXON command
+ * @priv: eeprom and antenna fields are used to determine antenna flags
+ *
+ * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
+ * iwl3945_mod_params.antenna specifies the antenna diversity mode:
+ *
+ * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
+ * IWL_ANTENNA_MAIN      - Force MAIN antenna
+ * IWL_ANTENNA_AUX       - Force AUX antenna
+ */
+__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+
+	switch (iwl3945_mod_params.antenna) {
+	case IWL_ANTENNA_DIVERSITY:
+		return 0;
+
+	case IWL_ANTENNA_MAIN:
+		if (eeprom->antenna_switch_type)
+			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+
+	case IWL_ANTENNA_AUX:
+		if (eeprom->antenna_switch_type)
+			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
+		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
+	}
+
+	/* bad antenna selector value */
+	IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
+		iwl3945_mod_params.antenna);
+
+	return 0;		/* "diversity" is default if error */
+}
+
+static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+				   struct ieee80211_key_conf *keyconf,
+				   u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	int ret;
+
+	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+
+	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	keyconf->hw_key_idx = keyconf->keyidx;
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+	       keyconf->keylen);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+	       keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	* in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	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_legacy_send_add_sta(priv,
+				&priv->stations[sta_id].sta, CMD_ASYNC);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
+}
+
+static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+				  struct ieee80211_key_conf *keyconf,
+				  u8 sta_id)
+{
+	return -EOPNOTSUPP;
+}
+
+static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
+				  struct ieee80211_key_conf *keyconf,
+				  u8 sta_id)
+{
+	return -EOPNOTSUPP;
+}
+
+static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
+{
+	unsigned long flags;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	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[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;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
+			struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+	int ret = 0;
+
+	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
+		break;
+	default:
+		IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
+			keyconf->cipher);
+		ret = -EINVAL;
+	}
+
+	IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
+		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
+		      sta_id, ret);
+
+	return ret;
+}
+
+static int iwl3945_remove_static_key(struct iwl_priv *priv)
+{
+	int ret = -EOPNOTSUPP;
+
+	return ret;
+}
+
+static int iwl3945_set_static_key(struct iwl_priv *priv,
+				struct ieee80211_key_conf *key)
+{
+	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	    key->cipher == WLAN_CIPHER_SUITE_WEP104)
+		return -EOPNOTSUPP;
+
+	IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
+	return -EINVAL;
+}
+
+static void iwl3945_clear_free_frames(struct iwl_priv *priv)
+{
+	struct list_head *element;
+
+	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
+		       priv->frames_count);
+
+	while (!list_empty(&priv->free_frames)) {
+		element = priv->free_frames.next;
+		list_del(element);
+		kfree(list_entry(element, struct iwl3945_frame, list));
+		priv->frames_count--;
+	}
+
+	if (priv->frames_count) {
+		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
+			    priv->frames_count);
+		priv->frames_count = 0;
+	}
+}
+
+static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
+{
+	struct iwl3945_frame *frame;
+	struct list_head *element;
+	if (list_empty(&priv->free_frames)) {
+		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
+		if (!frame) {
+			IWL_ERR(priv, "Could not allocate frame!\n");
+			return NULL;
+		}
+
+		priv->frames_count++;
+		return frame;
+	}
+
+	element = priv->free_frames.next;
+	list_del(element);
+	return list_entry(element, struct iwl3945_frame, list);
+}
+
+static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
+{
+	memset(frame, 0, sizeof(*frame));
+	list_add(&frame->list, &priv->free_frames);
+}
+
+unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
+				struct ieee80211_hdr *hdr,
+				int left)
+{
+
+	if (!iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
+		return 0;
+
+	if (priv->beacon_skb->len > left)
+		return 0;
+
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
+
+	return priv->beacon_skb->len;
+}
+
+static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
+{
+	struct iwl3945_frame *frame;
+	unsigned int frame_size;
+	int rc;
+	u8 rate;
+
+	frame = iwl3945_get_free_frame(priv);
+
+	if (!frame) {
+		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
+			  "command.\n");
+		return -ENOMEM;
+	}
+
+	rate = iwl_legacy_get_lowest_plcp(priv,
+				&priv->contexts[IWL_RXON_CTX_BSS]);
+
+	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
+
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+			      &frame->u.cmd[0]);
+
+	iwl3945_free_frame(priv, frame);
+
+	return rc;
+}
+
+static void iwl3945_unset_hw_params(struct iwl_priv *priv)
+{
+	if (priv->_3945.shared_virt)
+		dma_free_coherent(&priv->pci_dev->dev,
+				  sizeof(struct iwl3945_shared),
+				  priv->_3945.shared_virt,
+				  priv->_3945.shared_phys);
+}
+
+static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
+				      struct ieee80211_tx_info *info,
+				      struct iwl_device_cmd *cmd,
+				      struct sk_buff *skb_frag,
+				      int sta_id)
+{
+	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
+
+	tx_cmd->sec_ctl = 0;
+
+	switch (keyinfo->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+		memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
+		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
+		break;
+
+	case WLAN_CIPHER_SUITE_TKIP:
+		break;
+
+	case WLAN_CIPHER_SUITE_WEP104:
+		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+		/* fall through */
+	case WLAN_CIPHER_SUITE_WEP40:
+		tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
+		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
+
+		memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
+
+		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
+			     "with key %d\n", info->control.hw_key->hw_key_idx);
+		break;
+
+	default:
+		IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
+		break;
+	}
+}
+
+/*
+ * handle build REPLY_TX command notification.
+ */
+static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
+				  struct iwl_device_cmd *cmd,
+				  struct ieee80211_tx_info *info,
+				  struct ieee80211_hdr *hdr, u8 std_id)
+{
+	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+	__le32 tx_flags = tx_cmd->tx_flags;
+	__le16 fc = hdr->frame_control;
+
+	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+		tx_flags |= TX_CMD_FLG_ACK_MSK;
+		if (ieee80211_is_mgmt(fc))
+			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+		if (ieee80211_is_probe_resp(fc) &&
+		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
+			tx_flags |= TX_CMD_FLG_TSF_MSK;
+	} else {
+		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	tx_cmd->sta_id = std_id;
+	if (ieee80211_has_morefrags(fc))
+		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tx_cmd->tid_tspec = qc[0] & 0xf;
+		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+	} else {
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	iwl_legacy_tx_cmd_protection(priv, info, fc, &tx_flags);
+
+	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+	if (ieee80211_is_mgmt(fc)) {
+		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+		else
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+	} else {
+		tx_cmd->timeout.pm_frame_timeout = 0;
+	}
+
+	tx_cmd->driver_txop = 0;
+	tx_cmd->tx_flags = tx_flags;
+	tx_cmd->next_frame_len = 0;
+}
+
+/*
+ * start REPLY_TX command process
+ */
+static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct iwl3945_tx_cmd *tx_cmd;
+	struct iwl_tx_queue *txq = NULL;
+	struct iwl_queue *q = NULL;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	dma_addr_t phys_addr;
+	dma_addr_t txcmd_phys;
+	int txq_id = skb_get_queue_mapping(skb);
+	u16 len, idx, hdr_len;
+	u8 id;
+	u8 unicast;
+	u8 sta_id;
+	u8 tid = 0;
+	__le16 fc;
+	u8 wait_write_ptr = 0;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
+		goto drop_unlock;
+	}
+
+	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
+		IWL_ERR(priv, "ERROR: No TX rate available.\n");
+		goto drop_unlock;
+	}
+
+	unicast = !is_multicast_ether_addr(hdr->addr1);
+	id = 0;
+
+	fc = hdr->frame_control;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (ieee80211_is_auth(fc))
+		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
+	else if (ieee80211_is_assoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
+	else if (ieee80211_is_reassoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	hdr_len = ieee80211_hdrlen(fc);
+
+	/* Find index into station table for destination station */
+	sta_id = iwl_legacy_sta_id_or_broadcast(
+			priv, &priv->contexts[IWL_RXON_CTX_BSS],
+			info->control.sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+			       hdr->addr1);
+		goto drop;
+	}
+
+	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
+
+	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		if (unlikely(tid >= MAX_TID_COUNT))
+			goto drop;
+	}
+
+	/* Descriptor for chosen Tx queue */
+	txq = &priv->txq[txq_id];
+	q = &txq->q;
+
+	if ((iwl_legacy_queue_space(q) < q->high_mark))
+		goto drop;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0);
+
+	/* Set up driver data for this TFD */
+	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
+	txq->txb[q->write_ptr].skb = skb;
+	txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	/* Init first empty entry in queue's array of Tx/cmd buffers */
+	out_cmd = txq->cmd[idx];
+	out_meta = &txq->meta[idx];
+	tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
+	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+	memset(tx_cmd, 0, sizeof(*tx_cmd));
+
+	/*
+	 * Set up the Tx-command (not MAC!) header.
+	 * Store the chosen Tx queue and TFD index within the sequence field;
+	 * after Tx, uCode's Tx response will return this value so driver can
+	 * locate the frame within the tx queue and do post-tx processing.
+	 */
+	out_cmd->hdr.cmd = REPLY_TX;
+	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+				INDEX_TO_SEQ(q->write_ptr)));
+
+	/* Copy MAC header from skb into command buffer */
+	memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+
+	if (info->control.hw_key)
+		iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
+
+	/* TODO need this for burst mode later on */
+	iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
+
+	/* set is_hcca to 0; it probably will never be implemented */
+	iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
+
+	/* Total # bytes to be transmitted */
+	len = (u16)skb->len;
+	tx_cmd->len = cpu_to_le16(len);
+
+	iwl_legacy_dbg_log_tx_data_frame(priv, len, hdr);
+	iwl_legacy_update_stats(priv, true, fc, len);
+	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
+	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
+
+	if (!ieee80211_has_morefrags(hdr->frame_control)) {
+		txq->need_update = 1;
+	} else {
+		wait_write_ptr = 1;
+		txq->need_update = 0;
+	}
+
+	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
+		     le16_to_cpu(out_cmd->hdr.sequence));
+	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+	iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
+			   ieee80211_hdrlen(fc));
+
+	/*
+	 * Use the first empty entry in this queue's command buffer array
+	 * to contain the Tx command and MAC header concatenated together
+	 * (payload data will be in another buffer).
+	 * Size of this varies, due to varying MAC header length.
+	 * If end is not dword aligned, we'll have 2 extra bytes at the end
+	 * of the MAC header (device reads on dword boundaries).
+	 * We'll tell device about this padding later.
+	 */
+	len = sizeof(struct iwl3945_tx_cmd) +
+			sizeof(struct iwl_cmd_header) + hdr_len;
+	len = (len + 3) & ~3;
+
+	/* Physical address of this Tx command's header (not MAC header!),
+	 * within command buffer array. */
+	txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+				    len, PCI_DMA_TODEVICE);
+	/* we do not map meta data ... so we can safely access address to
+	 * provide to unmap command*/
+	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+	dma_unmap_len_set(out_meta, len, len);
+
+	/* Add buffer containing Tx command and MAC(!) header to TFD's
+	 * first entry */
+	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+						   txcmd_phys, len, 1, 0);
+
+
+	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+	 * if any (802.11 null frames have no payload). */
+	len = skb->len - hdr_len;
+	if (len) {
+		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
+					   len, PCI_DMA_TODEVICE);
+		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+							   phys_addr, len,
+							   0, U32_PAD(len));
+	}
+
+
+	/* Tell device the write index *just past* this latest filled TFD */
+	q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_legacy_txq_update_write_ptr(priv, txq);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if ((iwl_legacy_queue_space(q) < q->high_mark)
+	    && priv->mac80211_registered) {
+		if (wait_write_ptr) {
+			spin_lock_irqsave(&priv->lock, flags);
+			txq->need_update = 1;
+			iwl_legacy_txq_update_write_ptr(priv, txq);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		}
+
+		iwl_legacy_stop_queue(priv, txq);
+	}
+
+	return 0;
+
+drop_unlock:
+	spin_unlock_irqrestore(&priv->lock, flags);
+drop:
+	return -1;
+}
+
+static int iwl3945_get_measurement(struct iwl_priv *priv,
+			       struct ieee80211_measurement_params *params,
+			       u8 type)
+{
+	struct iwl_spectrum_cmd spectrum;
+	struct iwl_rx_packet *pkt;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
+		.data = (void *)&spectrum,
+		.flags = CMD_WANT_SKB,
+	};
+	u32 add_time = le64_to_cpu(params->start_time);
+	int rc;
+	int spectrum_resp_status;
+	int duration = le16_to_cpu(params->duration);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))
+		add_time = iwl_legacy_usecs_to_beacons(priv,
+			le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
+			le16_to_cpu(ctx->timing.beacon_interval));
+
+	memset(&spectrum, 0, sizeof(spectrum));
+
+	spectrum.channel_count = cpu_to_le16(1);
+	spectrum.flags =
+	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
+	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
+	cmd.len = sizeof(spectrum);
+	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))
+		spectrum.start_time =
+			iwl_legacy_add_beacon_time(priv,
+				priv->_3945.last_beacon_time, add_time,
+				le16_to_cpu(ctx->timing.beacon_interval));
+	else
+		spectrum.start_time = 0;
+
+	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
+	spectrum.channels[0].channel = params->channel;
+	spectrum.channels[0].type = type;
+	if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
+		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
+		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
+
+	rc = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (rc)
+		return rc;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
+		rc = -EIO;
+	}
+
+	spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
+	switch (spectrum_resp_status) {
+	case 0:		/* Command will be handled */
+		if (pkt->u.spectrum.id != 0xff) {
+			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
+						pkt->u.spectrum.id);
+			priv->measurement_status &= ~MEASUREMENT_READY;
+		}
+		priv->measurement_status |= MEASUREMENT_ACTIVE;
+		rc = 0;
+		break;
+
+	case 1:		/* Command will not be handled */
+		rc = -EAGAIN;
+		break;
+	}
+
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return rc;
+}
+
+static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
+			       struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_alive_resp *palive;
+	struct delayed_work *pwork;
+
+	palive = &pkt->u.alive_frame;
+
+	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+		       "0x%01X 0x%01X\n",
+		       palive->is_valid, palive->ver_type,
+		       palive->ver_subtype);
+
+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
+		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->init_alive_start;
+	} else {
+		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->alive_start;
+		iwl3945_disable_events(priv);
+	}
+
+	/* We delay the ALIVE response by 5ms to
+	 * give the HW RF Kill time to activate... */
+	if (palive->is_valid == UCODE_VALID_OK)
+		queue_delayed_work(priv->workqueue, pwork,
+				   msecs_to_jiffies(5));
+	else
+		IWL_WARN(priv, "uCode did not respond OK.\n");
+}
+
+static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
+				 struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+#endif
+
+	IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
+}
+
+static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	u8 rate = beacon->beacon_notify_hdr.rate;
+
+	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
+		"tsf %d %d rate %d\n",
+		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+#endif
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+	unsigned long status = priv->status;
+
+	IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
+
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	if (flags & HW_CARD_DISABLED)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+
+	iwl_legacy_scan_cancel(priv);
+
+	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
+	     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);
+}
+
+/**
+ * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
+ *
+ * Setup the RX handlers for each of the reply types sent from the uCode
+ * to the host.
+ *
+ * This function chains into the hardware specific files for them to setup
+ * any hardware specific handlers as well.
+ */
+static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
+{
+	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
+	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
+	priv->rx_handlers[REPLY_ERROR] = iwl_legacy_rx_reply_error;
+	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_legacy_rx_csa;
+	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+			iwl_legacy_rx_spectrum_measure_notif;
+	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_legacy_rx_pm_sleep_notif;
+	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
+	    iwl_legacy_rx_pm_debug_statistics_notif;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
+
+	/*
+	 * The same handler is used for both the REPLY to a discrete
+	 * statistics request from the host as well as for the periodic
+	 * statistics notifications (after received beacons) from the uCode.
+	 */
+	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
+	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
+
+	iwl_legacy_setup_rx_scan_handlers(priv);
+	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
+
+	/* Set up hardware specific Rx handlers */
+	iwl3945_hw_rx_handler_setup(priv);
+}
+
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * The host allocates 32 DMA target addresses and passes the host address
+ * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
+ * 0 to 31
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt.  The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ INDEX is updated (updating the
+ *   'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            iwl3945_rx_queue_restock
+ * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE index.  If insufficient rx_free buffers
+ *                            are available, schedules iwl3945_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ *                            READ INDEX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls iwl3945_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
+					  dma_addr_t dma_addr)
+{
+	return cpu_to_le32((u32)dma_addr);
+}
+
+/**
+ * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	unsigned long flags;
+	int write;
+
+	spin_lock_irqsave(&rxq->lock, flags);
+	write = rxq->write & ~0x7;
+	while ((iwl_legacy_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+		/* Get next free Rx buffer, remove from free list */
+		element = rxq->rx_free.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		/* Point to Rx buffer via next RBD in circular buffer */
+		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
+		rxq->queue[rxq->write] = rxb;
+		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+		rxq->free_count--;
+	}
+	spin_unlock_irqrestore(&rxq->lock, flags);
+	/* If the pre-allocated buffer pool is dropping low, schedule to
+	 * refill it */
+	if (rxq->free_count <= RX_LOW_WATERMARK)
+		queue_work(priv->workqueue, &priv->rx_replenish);
+
+
+	/* If we've added more space for the firmware to place data, tell it.
+	 * Increment device's write pointer in multiples of 8. */
+	if ((rxq->write_actual != (rxq->write & ~0x7))
+	    || (abs(rxq->write - rxq->read) > 7)) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		rxq->need_update = 1;
+		spin_unlock_irqrestore(&rxq->lock, flags);
+		iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+	}
+}
+
+/**
+ * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * 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, gfp_t priority)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct list_head *element;
+	struct iwl_rx_mem_buffer *rxb;
+	struct page *page;
+	unsigned long flags;
+	gfp_t gfp_mask = priority;
+
+	while (1) {
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			return;
+		}
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			gfp_mask |= __GFP_NOWARN;
+
+		if (priv->hw_params.rx_page_order > 0)
+			gfp_mask |= __GFP_COMP;
+
+		/* Alloc a new receive buffer */
+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
+		if (!page) {
+			if (net_ratelimit())
+				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
+			/* We don't reschedule replenish work here -- we will
+			 * call the restock method and if it still needs
+			 * more buffers it will schedule replenish */
+			break;
+		}
+
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			__free_pages(page, priv->hw_params.rx_page_order);
+			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);
+
+		rxb->page = page;
+		/* Get physical address of RB/SKB */
+		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		list_add_tail(&rxb->list, &rxq->rx_free);
+		rxq->free_count++;
+		priv->alloc_rxb_page++;
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+	}
+}
+
+void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	unsigned long flags;
+	int i;
+	spin_lock_irqsave(&rxq->lock, flags);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+		/* In the reset function, these buffers may have been allocated
+		 * to an SKB, so we need to unmap and free potential storage */
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+	}
+
+	/* 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);
+}
+
+void iwl3945_rx_replenish(void *data)
+{
+	struct iwl_priv *priv = data;
+	unsigned long flags;
+
+	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
+ * non NULL it is unmapped and freed
+ */
+static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	int i;
+	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+	}
+
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->bd_dma);
+	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+			  rxq->rb_stts, rxq->rb_stts_dma);
+	rxq->bd = NULL;
+	rxq->rb_stts  = NULL;
+}
+
+
+/* Convert linear signal-to-noise ratio into dB */
+static u8 ratio2dB[100] = {
+/*	 0   1   2   3   4   5   6   7   8   9 */
+	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
+	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
+	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
+	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
+	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
+	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
+	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
+	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
+	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
+	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
+};
+
+/* Calculates a relative dB value from a ratio of linear
+ *   (i.e. not dB) signal levels.
+ * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
+int iwl3945_calc_db_from_ratio(int sig_ratio)
+{
+	/* 1000:1 or higher just report as 60 dB */
+	if (sig_ratio >= 1000)
+		return 60;
+
+	/* 100:1 or higher, divide by 10 and use table,
+	 *   add 20 dB to make up for divide by 10 */
+	if (sig_ratio >= 100)
+		return 20 + (int)ratio2dB[sig_ratio/10];
+
+	/* We shouldn't see this */
+	if (sig_ratio < 1)
+		return 0;
+
+	/* Use table for ratios 1:1 - 99:1 */
+	return (int)ratio2dB[sig_ratio];
+}
+
+/**
+ * iwl3945_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the priv->rx_handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+static void iwl3945_rx_handle(struct iwl_priv *priv)
+{
+	struct iwl_rx_mem_buffer *rxb;
+	struct iwl_rx_packet *pkt;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	u32 r, i;
+	int reclaim;
+	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;
+
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - 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)
+		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
+
+	while (i != r) {
+		int len;
+
+		rxb = rxq->queue[i];
+
+		/* If an RXB doesn't have a Rx queue slot associated with it,
+		 * then a bug has been introduced in the queue refilling
+		 * routines -- catch it here */
+		BUG_ON(rxb == NULL);
+
+		rxq->queue[i] = NULL;
+
+		pci_unmap_page(priv->pci_dev, rxb->page_dma,
+			       PAGE_SIZE << priv->hw_params.rx_page_order,
+			       PCI_DMA_FROMDEVICE);
+		pkt = rxb_addr(rxb);
+
+		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+		len += sizeof(u32); /* account for status word */
+		trace_iwlwifi_legacy_dev_rx(priv, pkt, len);
+
+		/* Reclaim a command buffer only if this packet is a response
+		 *   to a (driver-originated) command.
+		 * If the packet (e.g. Rx frame) originated from uCode,
+		 *   there is no command buffer to reclaim.
+		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+		 *   but apparently a few don't get set; catch them here. */
+		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+			(pkt->hdr.cmd != REPLY_TX);
+
+		/* Based on type of command response or notification,
+		 *   handle those that need handling via function in
+		 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
+		if (priv->rx_handlers[pkt->hdr.cmd]) {
+			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
+			iwl_legacy_get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
+			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+		} else {
+			/* No handling needed */
+			IWL_DEBUG_RX(priv,
+				"r %d i %d No handler needed for %s, 0x%02x\n",
+				r, i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+		}
+
+		/*
+		 * XXX: After here, we should always check rxb->page
+		 * against NULL before touching it or its virtual
+		 * memory (pkt). Because some rx_handler might have
+		 * already taken or freed the pages.
+		 */
+
+		if (reclaim) {
+			/* Invoke any callbacks, transfer the buffer to caller,
+			 * and fire off the (possibly) blocking iwl_legacy_send_cmd()
+			 * as we reclaim the driver command queue */
+			if (rxb->page)
+				iwl_legacy_tx_cmd_complete(priv, rxb);
+			else
+				IWL_WARN(priv, "Claim null rxb?\n");
+		}
+
+		/* Reuse the page if possible. For notification packets and
+		 * SKBs that fail to Rx correctly, add them back into the
+		 * rx_free list for reuse later. */
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (rxb->page != NULL) {
+			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+				0, PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			list_add_tail(&rxb->list, &rxq->rx_free);
+			rxq->free_count++;
+		} else
+			list_add_tail(&rxb->list, &rxq->rx_used);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		i = (i + 1) & RX_QUEUE_MASK;
+		/* If there are a lot of unused frames,
+		 * restock the Rx queue so ucode won't assert. */
+		if (fill_rx) {
+			count++;
+			if (count >= 8) {
+				rxq->read = i;
+				iwl3945_rx_replenish_now(priv);
+				count = 0;
+			}
+		}
+	}
+
+	/* Backtrack one entry */
+	rxq->read = i;
+	if (fill_rx)
+		iwl3945_rx_replenish_now(priv);
+	else
+		iwl3945_rx_queue_restock(priv);
+}
+
+/* call this function to flush any scheduled tasklet */
+static inline void iwl3945_synchronize_irq(struct iwl_priv *priv)
+{
+	/* wait to make sure we flush pending tasklet*/
+	synchronize_irq(priv->pci_dev->irq);
+	tasklet_kill(&priv->irq_tasklet);
+}
+
+static const char *iwl3945_desc_lookup(int i)
+{
+	switch (i) {
+	case 1:
+		return "FAIL";
+	case 2:
+		return "BAD_PARAM";
+	case 3:
+		return "BAD_CHECKSUM";
+	case 4:
+		return "NMI_INTERRUPT";
+	case 5:
+		return "SYSASSERT";
+	case 6:
+		return "FATAL_ERROR";
+	}
+
+	return "UNKNOWN";
+}
+
+#define ERROR_START_OFFSET  (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+
+void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
+{
+	u32 i;
+	u32 desc, time, count, base, data1;
+	u32 blink1, blink2, ilink1, ilink2;
+
+	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+
+	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
+		return;
+	}
+
+
+	count = iwl_legacy_read_targ_mem(priv, base);
+
+	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+			priv->status, count);
+	}
+
+	IWL_ERR(priv, "Desc       Time       asrtPC  blink2 "
+		  "ilink1  nmiPC   Line\n");
+	for (i = ERROR_START_OFFSET;
+	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
+	     i += ERROR_ELEM_SIZE) {
+		desc = iwl_legacy_read_targ_mem(priv, base + i);
+		time =
+		    iwl_legacy_read_targ_mem(priv, base + i + 1 * sizeof(u32));
+		blink1 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 2 * sizeof(u32));
+		blink2 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 3 * sizeof(u32));
+		ilink1 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 4 * sizeof(u32));
+		ilink2 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 5 * sizeof(u32));
+		data1 =
+		    iwl_legacy_read_targ_mem(priv, base + i + 6 * sizeof(u32));
+
+		IWL_ERR(priv,
+			"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
+			iwl3945_desc_lookup(desc), desc, time, blink1, blink2,
+			ilink1, ilink2, data1);
+		trace_iwlwifi_legacy_dev_ucode_error(priv, desc, time, data1, 0,
+					0, blink1, blink2, ilink1, ilink2);
+	}
+}
+
+#define EVENT_START_OFFSET  (6 * sizeof(u32))
+
+/**
+ * iwl3945_print_event_log - Dump error event log to syslog
+ *
+ */
+static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
+				  u32 num_events, u32 mode,
+				  int pos, char **buf, size_t bufsz)
+{
+	u32 i;
+	u32 base;       /* SRAM byte address of event log header */
+	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
+	u32 ptr;        /* SRAM byte address of log data */
+	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
+
+	if (num_events == 0)
+		return pos;
+
+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+
+	if (mode == 0)
+		event_size = 2 * sizeof(u32);
+	else
+		event_size = 3 * sizeof(u32);
+
+	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
+	/* "time" is actually "data" for mode 0 (no timestamp).
+	 * place event id # at far right for easier visual parsing. */
+	for (i = 0; i < num_events; i++) {
+		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (mode == 0) {
+			/* data, ev */
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"0x%08x:%04u\n",
+						time, ev);
+			} else {
+				IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
+				trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
+							      time, ev);
+			}
+		} else {
+			data = _iwl_legacy_read_direct32(priv,
+							HBUS_TARG_MEM_RDAT);
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"%010u:0x%08x:%04u\n",
+						 time, data, ev);
+			} else {
+				IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
+					time, data, ev);
+				trace_iwlwifi_legacy_dev_ucode_event(priv, time,
+							      data, ev);
+			}
+		}
+	}
+
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return pos;
+}
+
+/**
+ * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
+ */
+static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+				      u32 num_wraps, u32 next_entry,
+				      u32 size, u32 mode,
+				      int pos, char **buf, size_t bufsz)
+{
+	/*
+	 * display the newest DEFAULT_LOG_ENTRIES entries
+	 * i.e the entries just before the next ont that uCode would fill.
+	 */
+	if (num_wraps) {
+		if (next_entry < size) {
+			pos = iwl3945_print_event_log(priv,
+					     capacity - (size - next_entry),
+					     size - next_entry, mode,
+					     pos, buf, bufsz);
+			pos = iwl3945_print_event_log(priv, 0,
+						      next_entry, mode,
+						      pos, buf, bufsz);
+		} else
+			pos = iwl3945_print_event_log(priv, next_entry - size,
+						      size, mode,
+						      pos, buf, bufsz);
+	} else {
+		if (next_entry < size)
+			pos = iwl3945_print_event_log(priv, 0,
+						      next_entry, mode,
+						      pos, buf, bufsz);
+		else
+			pos = iwl3945_print_event_log(priv, next_entry - size,
+						      size, mode,
+						      pos, buf, bufsz);
+	}
+	return pos;
+}
+
+#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
+
+int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
+			    char **buf, bool display)
+{
+	u32 base;       /* SRAM byte address of event log header */
+	u32 capacity;   /* event log capacity in # entries */
+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+	u32 num_wraps;  /* # times uCode wrapped to top of log */
+	u32 next_entry; /* index of next entry to be written by uCode */
+	u32 size;       /* # entries that we'll print */
+	int pos = 0;
+	size_t bufsz = 0;
+
+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+		return  -EINVAL;
+	}
+
+	/* event log header */
+	capacity = iwl_legacy_read_targ_mem(priv, base);
+	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
+	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
+	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+	if (capacity > priv->cfg->base_params->max_event_log_size) {
+		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
+			capacity, priv->cfg->base_params->max_event_log_size);
+		capacity = priv->cfg->base_params->max_event_log_size;
+	}
+
+	if (next_entry > priv->cfg->base_params->max_event_log_size) {
+		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
+			next_entry, priv->cfg->base_params->max_event_log_size);
+		next_entry = priv->cfg->base_params->max_event_log_size;
+	}
+
+	size = num_wraps ? capacity : next_entry;
+
+	/* bail out if nothing in log */
+	if (size == 0) {
+		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+		return pos;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
+		size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
+			? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
+#else
+	size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
+		? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
+#endif
+
+	IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
+		  size);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (display) {
+		if (full_log)
+			bufsz = capacity * 48;
+		else
+			bufsz = size * 48;
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+	}
+	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
+		/* if uCode has wrapped back to top of log,
+		 * start at the oldest entry,
+		 * i.e the next one that uCode would fill.
+		 */
+		if (num_wraps)
+			pos = iwl3945_print_event_log(priv, next_entry,
+						capacity - next_entry, mode,
+						pos, buf, bufsz);
+
+		/* (then/else) start at top of log */
+		pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
+					      pos, buf, bufsz);
+	} else
+		pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+						    next_entry, size, mode,
+						    pos, buf, bufsz);
+#else
+	pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
+					    next_entry, size, mode,
+					    pos, buf, bufsz);
+#endif
+	return pos;
+}
+
+static void iwl3945_irq_tasklet(struct iwl_priv *priv)
+{
+	u32 inta, handled = 0;
+	u32 inta_fh;
+	unsigned long flags;
+#ifdef CONFIG_IWLWIFI_LEGACY_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,
+	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
+	inta = iwl_read32(priv, CSR_INT);
+	iwl_write32(priv, CSR_INT, inta);
+
+	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
+	 * Any new interrupts that happen after this, either while we're
+	 * in this tasklet, or later, will show up in next ISR/tasklet. */
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & IWL_DL_ISR) {
+		/* just for debug */
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+			      inta, inta_mask, inta_fh);
+	}
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
+	 * atomic, make sure that inta covers all the interrupts that
+	 * we've discovered, even if FH interrupt came in just after
+	 * reading CSR_INT. */
+	if (inta_fh & CSR39_FH_INT_RX_MASK)
+		inta |= CSR_INT_BIT_FH_RX;
+	if (inta_fh & CSR39_FH_INT_TX_MASK)
+		inta |= CSR_INT_BIT_FH_TX;
+
+	/* Now service all interrupt bits discovered above. */
+	if (inta & CSR_INT_BIT_HW_ERR) {
+		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
+
+		/* Tell the device to stop sending interrupts */
+		iwl_legacy_disable_interrupts(priv);
+
+		priv->isr_stats.hw++;
+		iwl_legacy_irq_handle_error(priv);
+
+		handled |= CSR_INT_BIT_HW_ERR;
+
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (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);
+
+	/* 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++;
+		iwl_legacy_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_legacy_rx_queue_update_write_ptr(priv, &priv->rxq);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[0]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[1]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[2]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[3]);
+		iwl_legacy_txq_update_write_ptr(priv, &priv->txq[4]);
+		iwl_legacy_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)) {
+		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));
+		iwl_legacy_write_direct32(priv, FH39_TCSR_CREDIT
+					(FH39_SRVC_CHNL), 0x0);
+		handled |= CSR_INT_BIT_FH_TX;
+	}
+
+	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);
+		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
+	}
+
+	/* Re-enable all interrupts */
+	/* only Re-enable if disabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_legacy_enable_interrupts(priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
+		inta = iwl_read32(priv, CSR_INT);
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+		IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+	}
+#endif
+}
+
+static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
+					       struct ieee80211_vif *vif,
+					       enum ieee80211_band band,
+					       struct iwl3945_scan_channel *scan_ch)
+{
+	const struct ieee80211_supported_band *sband;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added = 0;
+	u8 channel = 0;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband) {
+		IWL_ERR(priv, "invalid band\n");
+		return added;
+	}
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+
+	channel = iwl_legacy_get_single_channel_number(priv, band);
+
+	if (channel) {
+		scan_ch->channel = channel;
+		scan_ch->type = 0;	/* passive */
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* Set txpower levels to defaults */
+		scan_ch->tpc.dsp_atten = 110;
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+		added++;
+	} else
+		IWL_ERR(priv, "no valid channel found\n");
+	return added;
+}
+
+static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
+					 enum ieee80211_band band,
+				     u8 is_active, u8 n_probes,
+				     struct iwl3945_scan_channel *scan_ch,
+				     struct ieee80211_vif *vif)
+{
+	struct ieee80211_channel *chan;
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added, i;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband)
+		return 0;
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, n_probes);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+		chan = priv->scan_request->channels[i];
+
+		if (chan->band != band)
+			continue;
+
+		scan_ch->channel = chan->hw_value;
+
+		ch_info = iwl_legacy_get_channel_info(priv, band,
+							scan_ch->channel);
+		if (!iwl_legacy_is_channel_valid(ch_info)) {
+			IWL_DEBUG_SCAN(priv,
+				"Channel %d is INVALID for this band.\n",
+			       scan_ch->channel);
+			continue;
+		}
+
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* If passive , set up for auto-switch
+		 *  and use long active_dwell time.
+		 */
+		if (!is_active || iwl_legacy_is_channel_passive(ch_info) ||
+		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
+			scan_ch->type = 0;	/* passive */
+			if (IWL_UCODE_API(priv->ucode_ver) == 1)
+				scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
+		} else {
+			scan_ch->type = 1;	/* active */
+		}
+
+		/* Set direct probe bits. These may be used both for active
+		 * scan channels (probes gets sent right away),
+		 * or for passive channels (probes get se sent only after
+		 * hearing clear Rx packet).*/
+		if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+			if (n_probes)
+				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
+		} else {
+			/* uCode v1 does not allow setting direct probe bits on
+			 * passive channel. */
+			if ((scan_ch->type & 1) && n_probes)
+				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
+		}
+
+		/* Set txpower levels to defaults */
+		scan_ch->tpc.dsp_atten = 110;
+		/* scan_pwr_info->tpc.dsp_atten; */
+
+		/*scan_pwr_info->tpc.tx_gain; */
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else {
+			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
+			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+			 * power level:
+			 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
+			 */
+		}
+
+		IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n",
+			       scan_ch->channel,
+			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
+			       (scan_ch->type & 1) ?
+			       active_dwell : passive_dwell);
+
+		scan_ch++;
+		added++;
+	}
+
+	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+	return added;
+}
+
+static void iwl3945_init_hw_rates(struct iwl_priv *priv,
+			      struct ieee80211_rate *rates)
+{
+	int i;
+
+	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
+		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
+		rates[i].hw_value = i; /* Rate scaling will work on indexes */
+		rates[i].hw_value_short = i;
+		rates[i].flags = 0;
+		if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
+			/*
+			 * If CCK != 1M then set short preamble rate flag.
+			 */
+			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
+				0 : IEEE80211_RATE_SHORT_PREAMBLE;
+		}
+	}
+}
+
+/******************************************************************************
+ *
+ * uCode download functions
+ *
+ ******************************************************************************/
+
+static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv)
+{
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
+}
+
+/**
+ * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
+ *     looking at all data.
+ */
+static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len)
+{
+	u32 val;
+	u32 save_len = len;
+	int rc = 0;
+	u32 errcnt;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			       IWL39_RTC_INST_LOWER_BOUND);
+
+	errcnt = 0;
+	for (; len > 0; len -= sizeof(u32), image++) {
+		/* read data comes through single port, auto-incr addr */
+		/* NOTE: Use the debugless read so we don't flood kernel log
+		 * if IWL_DL_IO is set */
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "uCode INST section is invalid at "
+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+				  save_len - len, val, le32_to_cpu(*image));
+			rc = -EIO;
+			errcnt++;
+			if (errcnt >= 20)
+				break;
+		}
+	}
+
+
+	if (!errcnt)
+		IWL_DEBUG_INFO(priv,
+			"ucode image in INSTRUCTION memory is good\n");
+
+	return rc;
+}
+
+
+/**
+ * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
+ *   using sample data 100 bytes apart.  If these sample points are good,
+ *   it's a pretty good bet that everything between them is good, too.
+ */
+static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+{
+	u32 val;
+	int rc = 0;
+	u32 errcnt = 0;
+	u32 i;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	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
+		 * if IWL_DL_IO is set */
+		iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			i + IWL39_RTC_INST_LOWER_BOUND);
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+#if 0 /* Enable this if you want to see details */
+			IWL_ERR(priv, "uCode INST section is invalid at "
+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+				  i, val, *image);
+#endif
+			rc = -EIO;
+			errcnt++;
+			if (errcnt >= 3)
+				break;
+		}
+	}
+
+	return rc;
+}
+
+
+/**
+ * iwl3945_verify_ucode - determine which instruction image is in SRAM,
+ *    and verify its contents
+ */
+static int iwl3945_verify_ucode(struct iwl_priv *priv)
+{
+	__le32 *image;
+	u32 len;
+	int rc = 0;
+
+	/* Try bootstrap */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	rc = iwl3945_verify_inst_sparse(priv, image, len);
+	if (rc == 0) {
+		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try initialize */
+	image = (__le32 *)priv->ucode_init.v_addr;
+	len = priv->ucode_init.len;
+	rc = iwl3945_verify_inst_sparse(priv, image, len);
+	if (rc == 0) {
+		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try runtime/protocol */
+	image = (__le32 *)priv->ucode_code.v_addr;
+	len = priv->ucode_code.len;
+	rc = iwl3945_verify_inst_sparse(priv, image, len);
+	if (rc == 0) {
+		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+
+	/* Since nothing seems to match, show first several data entries in
+	 * instruction SRAM, so maybe visual inspection will give a clue.
+	 * Selection of bootstrap image (vs. other images) is arbitrary. */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	rc = iwl3945_verify_inst_full(priv, image, len);
+
+	return rc;
+}
+
+static void iwl3945_nic_start(struct iwl_priv *priv)
+{
+	/* Remove all resets to allow NIC to operate */
+	iwl_write32(priv, CSR_RESET, 0);
+}
+
+#define IWL3945_UCODE_GET(item)						\
+static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
+{									\
+	return le32_to_cpu(ucode->v1.item);				\
+}
+
+static u32 iwl3945_ucode_get_header_size(u32 api_ver)
+{
+	return 24;
+}
+
+static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
+{
+	return (u8 *) ucode->v1.data;
+}
+
+IWL3945_UCODE_GET(inst_size);
+IWL3945_UCODE_GET(data_size);
+IWL3945_UCODE_GET(init_size);
+IWL3945_UCODE_GET(init_data_size);
+IWL3945_UCODE_GET(boot_size);
+
+/**
+ * iwl3945_read_ucode - Read uCode images from disk file.
+ *
+ * Copy into buffers for card to fetch via bus-mastering
+ */
+static int iwl3945_read_ucode(struct iwl_priv *priv)
+{
+	const struct iwl_ucode_header *ucode;
+	int ret = -EINVAL, index;
+	const struct firmware *ucode_raw;
+	/* firmware file name contains uCode/driver compatibility version */
+	const char *name_pre = priv->cfg->fw_name_pre;
+	const unsigned int api_max = priv->cfg->ucode_api_max;
+	const unsigned int api_min = priv->cfg->ucode_api_min;
+	char buf[25];
+	u8 *src;
+	size_t len;
+	u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
+
+	/* Ask kernel firmware_class module to get the boot firmware off disk.
+	 * reject_firmware() is synchronous, file is in memory on return. */
+	for (index = api_max; index >= api_min; index--) {
+		sprintf(buf, "/*(DEBLOBBED)*/");
+		ret = reject_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
+		if (ret < 0) {
+			IWL_ERR(priv, "%s firmware file req failed: %d\n",
+				  buf, ret);
+			if (ret == -ENOENT)
+				continue;
+			else
+				goto error;
+		} else {
+			if (index < api_max)
+				IWL_ERR(priv, "Loaded firmware %s, "
+					"which is deprecated. "
+					" Please use API v%u instead.\n",
+					  buf, api_max);
+			IWL_DEBUG_INFO(priv, "Got firmware '%s' file "
+				       "(%zd bytes) from disk\n",
+				       buf, ucode_raw->size);
+			break;
+		}
+	}
+
+	if (ret < 0)
+		goto error;
+
+	/* Make sure that we got at least our header! */
+	if (ucode_raw->size <  iwl3945_ucode_get_header_size(1)) {
+		IWL_ERR(priv, "File size way too small!\n");
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	/* Data from ucode file:  header followed by uCode images */
+	ucode = (struct iwl_ucode_header *)ucode_raw->data;
+
+	priv->ucode_ver = le32_to_cpu(ucode->ver);
+	api_ver = IWL_UCODE_API(priv->ucode_ver);
+	inst_size = iwl3945_ucode_get_inst_size(ucode);
+	data_size = iwl3945_ucode_get_data_size(ucode);
+	init_size = iwl3945_ucode_get_init_size(ucode);
+	init_data_size = iwl3945_ucode_get_init_data_size(ucode);
+	boot_size = iwl3945_ucode_get_boot_size(ucode);
+	src = iwl3945_ucode_get_data(ucode);
+
+	/* api_ver should match the api version forming part of the
+	 * firmware filename ... but we don't check for that and only rely
+	 * on the API version read from firmware header from here on forward */
+
+	if (api_ver < api_min || api_ver > api_max) {
+		IWL_ERR(priv, "Driver unable to support your firmware API. "
+			  "Driver supports v%u, firmware is v%u.\n",
+			  api_max, api_ver);
+		priv->ucode_ver = 0;
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (api_ver != api_max)
+		IWL_ERR(priv, "Firmware has old API version. Expected %u, "
+			  "got %u. New firmware can be obtained "
+			  "from http://www.intellinuxwireless.org.\n",
+			  api_max, api_ver);
+
+	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
+		IWL_UCODE_MAJOR(priv->ucode_ver),
+		IWL_UCODE_MINOR(priv->ucode_ver),
+		IWL_UCODE_API(priv->ucode_ver),
+		IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	snprintf(priv->hw->wiphy->fw_version,
+		 sizeof(priv->hw->wiphy->fw_version),
+		 "%u.%u.%u.%u",
+		 IWL_UCODE_MAJOR(priv->ucode_ver),
+		 IWL_UCODE_MINOR(priv->ucode_ver),
+		 IWL_UCODE_API(priv->ucode_ver),
+		 IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
+		       priv->ucode_ver);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
+		       inst_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
+		       data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
+		       init_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
+		       init_data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
+		       boot_size);
+
+
+	/* Verify size of file vs. image size info in file's header */
+	if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
+		inst_size + data_size + init_size +
+		init_data_size + boot_size) {
+
+		IWL_DEBUG_INFO(priv,
+			"uCode file size %zd does not match expected size\n",
+			ucode_raw->size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	/* Verify that uCode images will fit in card's SRAM */
+	if (inst_size > IWL39_MAX_INST_SIZE) {
+		IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
+			       inst_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	if (data_size > IWL39_MAX_DATA_SIZE) {
+		IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
+			       data_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (init_size > IWL39_MAX_INST_SIZE) {
+		IWL_DEBUG_INFO(priv,
+				"uCode init instr len %d too large to fit in\n",
+				init_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (init_data_size > IWL39_MAX_DATA_SIZE) {
+		IWL_DEBUG_INFO(priv,
+				"uCode init data len %d too large to fit in\n",
+				init_data_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+	if (boot_size > IWL39_MAX_BSM_SIZE) {
+		IWL_DEBUG_INFO(priv,
+				"uCode boot instr len %d too large to fit in\n",
+				boot_size);
+		ret = -EINVAL;
+		goto err_release;
+	}
+
+	/* Allocate ucode buffers for card's bus-master loading ... */
+
+	/* Runtime instructions and 2 copies of data:
+	 * 1) unmodified from disk
+	 * 2) backup cache for save/restore during power-downs */
+	priv->ucode_code.len = inst_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
+
+	priv->ucode_data.len = data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
+
+	priv->ucode_data_backup.len = data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+
+	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+	    !priv->ucode_data_backup.v_addr)
+		goto err_pci_alloc;
+
+	/* Initialization instructions and data */
+	if (init_size && init_data_size) {
+		priv->ucode_init.len = init_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+		priv->ucode_init_data.len = init_data_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+
+		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Bootstrap (instructions only, no data) */
+	if (boot_size) {
+		priv->ucode_boot.len = boot_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
+
+		if (!priv->ucode_boot.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Copy images into buffers for card's bus-master reads ... */
+
+	/* Runtime instructions (first block of data in file) */
+	len = inst_size;
+	IWL_DEBUG_INFO(priv,
+		"Copying (but not loading) uCode instr len %zd\n", len);
+	memcpy(priv->ucode_code.v_addr, src, len);
+	src += len;
+
+	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
+		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
+
+	/* Runtime data (2nd block)
+	 * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
+	len = data_size;
+	IWL_DEBUG_INFO(priv,
+		"Copying (but not loading) uCode data len %zd\n", len);
+	memcpy(priv->ucode_data.v_addr, src, len);
+	memcpy(priv->ucode_data_backup.v_addr, src, len);
+	src += len;
+
+	/* Initialization instructions (3rd block) */
+	if (init_size) {
+		len = init_size;
+		IWL_DEBUG_INFO(priv,
+			"Copying (but not loading) init instr len %zd\n", len);
+		memcpy(priv->ucode_init.v_addr, src, len);
+		src += len;
+	}
+
+	/* Initialization data (4th block) */
+	if (init_data_size) {
+		len = init_data_size;
+		IWL_DEBUG_INFO(priv,
+			"Copying (but not loading) init data len %zd\n", len);
+		memcpy(priv->ucode_init_data.v_addr, src, len);
+		src += len;
+	}
+
+	/* Bootstrap instructions (5th block) */
+	len = boot_size;
+	IWL_DEBUG_INFO(priv,
+		"Copying (but not loading) boot instr len %zd\n", len);
+	memcpy(priv->ucode_boot.v_addr, src, len);
+
+	/* We have our copies now, allow OS release its copies */
+	release_firmware(ucode_raw);
+	return 0;
+
+ err_pci_alloc:
+	IWL_ERR(priv, "failed to allocate pci memory\n");
+	ret = -ENOMEM;
+	iwl3945_dealloc_ucode_pci(priv);
+
+ err_release:
+	release_firmware(ucode_raw);
+
+ error:
+	return ret;
+}
+
+
+/**
+ * iwl3945_set_ucode_ptrs - Set uCode address location
+ *
+ * Tell initialization uCode where to find runtime uCode.
+ *
+ * BSM registers initially contain pointers to initialization uCode.
+ * We need to replace them to load runtime uCode inst and data,
+ * and to save runtime data when powering down.
+ */
+static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
+{
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+
+	/* bits 31:0 for 3945 */
+	pinst = priv->ucode_code.p_addr;
+	pdata = priv->ucode_data_backup.p_addr;
+
+	/* Tell bootstrap uCode where to find image to load */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+				 priv->ucode_data.len);
+
+	/* Inst byte count must be last to set up, bit 31 signals uCode
+	 *   that all new ptr/size info is in place */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+
+	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
+
+	return 0;
+}
+
+/**
+ * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
+ *
+ * Called after REPLY_ALIVE notification received from "initialize" uCode.
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+ */
+static void iwl3945_init_alive_start(struct iwl_priv *priv)
+{
+	/* Check alive response for "valid" sign from uCode */
+	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
+		/* We had an error bringing up the hardware, so take it
+		 * all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
+		goto restart;
+	}
+
+	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "initialize" alive if code weren't properly loaded.  */
+	if (iwl3945_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
+		goto restart;
+	}
+
+	/* Send pointers to protocol/runtime uCode image ... init code will
+	 * load and launch runtime uCode, which will send us another "Alive"
+	 * notification. */
+	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+	if (iwl3945_set_ucode_ptrs(priv)) {
+		/* Runtime instruction load won't happen;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
+		goto restart;
+	}
+	return;
+
+ restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+/**
+ * iwl3945_alive_start - called after REPLY_ALIVE notification received
+ *                   from protocol/runtime uCode (initialization uCode's
+ *                   Alive gets handled by iwl3945_init_alive_start()).
+ */
+static void iwl3945_alive_start(struct iwl_priv *priv)
+{
+	int thermal_spin = 0;
+	u32 rfkill;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+
+	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
+		/* We had an error bringing up the hardware, so take it
+		 * all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Alive failed.\n");
+		goto restart;
+	}
+
+	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "runtime" alive if code weren't properly loaded.  */
+	if (iwl3945_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
+		goto restart;
+	}
+
+	rfkill = iwl_legacy_read_prph(priv, APMG_RFKILL_REG);
+	IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
+
+	if (rfkill & 0x1) {
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+		/* if RFKILL is not on, then wait for thermal
+		 * sensor in adapter to kick in */
+		while (iwl3945_hw_get_temperature(priv) == 0) {
+			thermal_spin++;
+			udelay(10);
+		}
+
+		if (thermal_spin)
+			IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n",
+				       thermal_spin * 10);
+	} else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	/* After the ALIVE response, we can send commands to 3945 uCode */
+	set_bit(STATUS_ALIVE, &priv->status);
+
+	/* Enable watchdog to monitor the driver tx queues */
+	iwl_legacy_setup_watchdog(priv);
+
+	if (iwl_legacy_is_rfkill(priv))
+		return;
+
+	ieee80211_wake_queues(priv->hw);
+
+	priv->active_rate = IWL_RATES_MASK_3945;
+
+	iwl_legacy_power_update_mode(priv, true);
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+		struct iwl3945_rxon_cmd *active_rxon =
+				(struct iwl3945_rxon_cmd *)(&ctx->active);
+
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	} else {
+		/* Initialize our rx_config data */
+		iwl_legacy_connection_init_rx_config(priv, ctx);
+	}
+
+	/* Configure Bluetooth device coexistence support */
+	iwl_legacy_send_bt_config(priv);
+
+	set_bit(STATUS_READY, &priv->status);
+
+	/* Configure the adapter for unassociated operation */
+	iwl3945_commit_rxon(priv, ctx);
+
+	iwl3945_reg_txpower_periodic(priv);
+
+	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
+	wake_up_interruptible(&priv->wait_command_queue);
+
+	return;
+
+ restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
+
+static void __iwl3945_down(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	int exit_pending;
+
+	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+	 * to prevent rearm timer */
+	del_timer_sync(&priv->watchdog);
+
+	/* Station information will now be cleared in device */
+	iwl_legacy_clear_ucode_stations(priv, NULL);
+	iwl_legacy_dealloc_bcast_stations(priv);
+	iwl_legacy_clear_driver_stations(priv);
+
+	/* Unblock any waiting calls */
+	wake_up_interruptible_all(&priv->wait_command_queue);
+
+	/* Wipe out the EXIT_PENDING status bit if we are not actually
+	 * exiting the module */
+	if (!exit_pending)
+		clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* stop and reset the on-board processor */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/* tell the device to stop sending interrupts */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	iwl3945_synchronize_irq(priv);
+
+	if (priv->mac80211_registered)
+		ieee80211_stop_queues(priv->hw);
+
+	/* If we have not previously called iwl3945_init() then
+	 * clear all bits but the RF Kill bits and return */
+	if (!iwl_legacy_is_init(priv)) {
+		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+					STATUS_RF_KILL_HW |
+			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+					STATUS_GEO_CONFIGURED |
+				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+					STATUS_EXIT_PENDING;
+		goto exit;
+	}
+
+	/* ...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_GEO_CONFIGURED, &priv->status) <<
+				STATUS_GEO_CONFIGURED |
+			test_bit(STATUS_FW_ERROR, &priv->status) <<
+				STATUS_FW_ERROR |
+			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+				STATUS_EXIT_PENDING;
+
+	iwl3945_hw_txq_ctx_stop(priv);
+	iwl3945_hw_rxq_stop(priv);
+
+	/* Power-down device's busmaster DMA clocks */
+	iwl_legacy_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+	udelay(5);
+
+	/* Stop the device, and put it in low power state */
+	iwl_legacy_apm_stop(priv);
+
+ exit:
+	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
+
+	/* clear out any free frames */
+	iwl3945_clear_free_frames(priv);
+}
+
+static void iwl3945_down(struct iwl_priv *priv)
+{
+	mutex_lock(&priv->mutex);
+	__iwl3945_down(priv);
+	mutex_unlock(&priv->mutex);
+
+	iwl3945_cancel_deferred_work(priv);
+}
+
+#define MAX_HW_RESTARTS 5
+
+static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	unsigned long flags;
+	u8 sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	sta_id = iwl_legacy_prep_station(priv, ctx,
+					iwlegacy_bcast_addr, false, NULL);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Unable to prepare broadcast station\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+		return -EINVAL;
+	}
+
+	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+	priv->stations[sta_id].used |= IWL_STA_BCAST;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+static int __iwl3945_up(struct iwl_priv *priv)
+{
+	int rc, i;
+
+	rc = iwl3945_alloc_bcast_station(priv);
+	if (rc)
+		return rc;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
+		return -EIO;
+	}
+
+	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;
+	}
+
+	/* 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);
+	else {
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+		return -ENODEV;
+	}
+
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+	rc = iwl3945_hw_nic_init(priv);
+	if (rc) {
+		IWL_ERR(priv, "Unable to int nic\n");
+		return rc;
+	}
+
+	/* make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	/* clear (again), then enable host interrupts */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_legacy_enable_interrupts(priv);
+
+	/* really make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+	/* Copy original ucode data image from disk into backup cache.
+	 * This will be used to initialize the on-board processor's
+	 * data SRAM for a clean start when the runtime program first loads. */
+	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
+	       priv->ucode_data.len);
+
+	/* We return success when we resume from suspend and rf_kill is on. */
+	if (test_bit(STATUS_RF_KILL_HW, &priv->status))
+		return 0;
+
+	for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+		/* load bootstrap state machine,
+		 * load bootstrap program into processor's memory,
+		 * prepare to load the "initialize" uCode */
+		rc = priv->cfg->ops->lib->load_ucode(priv);
+
+		if (rc) {
+			IWL_ERR(priv,
+				"Unable to set up bootstrap uCode: %d\n", rc);
+			continue;
+		}
+
+		/* start card; "initialize" will load runtime ucode */
+		iwl3945_nic_start(priv);
+
+		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
+
+		return 0;
+	}
+
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+	__iwl3945_down(priv);
+	clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* tried to restart and config the device for as long as our
+	 * patience could withstand */
+	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
+	return -EIO;
+}
+
+
+/*****************************************************************************
+ *
+ * Workqueue callbacks
+ *
+ *****************************************************************************/
+
+static void iwl3945_bg_init_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, init_alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_init_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl3945_bg_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/*
+ * 3945 cannot interrupt driver when hardware rf kill switch toggles;
+ * driver must poll CSR_GP_CNTRL_REG register for change.  This register
+ * *is* readable even when device has been SW_RESET into low power mode
+ * (e.g. during RF KILL).
+ */
+static void iwl3945_rfkill_poll(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
+	bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
+	bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
+			& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
+
+	if (new_rfkill != old_rfkill) {
+		if (new_rfkill)
+			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, new_rfkill);
+
+		IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
+				new_rfkill ? "disable radio" : "enable radio");
+	}
+
+	/* Keep this running, even if radio now enabled.  This will be
+	 * cancelled in mac_start() if system decides to start again */
+	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
+			   round_jiffies_relative(2 * HZ));
+
+}
+
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_CMD,
+		.len = sizeof(struct iwl3945_scan_cmd),
+		.flags = CMD_SIZE_HUGE,
+	};
+	struct iwl3945_scan_cmd *scan;
+	u8 n_probes = 0;
+	enum ieee80211_band band;
+	bool is_active = false;
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
+			IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
+			return -ENOMEM;
+		}
+	}
+	scan = priv->scan_cmd;
+	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+	if (iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+		u16 interval = 0;
+		u32 extra;
+		u32 suspend_time = 100;
+		u32 scan_suspend_time = 100;
+
+		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+
+		if (priv->is_internal_short_scan)
+			interval = 0;
+		else
+			interval = vif->bss_conf.beacon_int;
+
+		scan->suspend_time = 0;
+		scan->max_out_time = cpu_to_le32(200 * 1024);
+		if (!interval)
+			interval = suspend_time;
+		/*
+		 * suspend time format:
+		 *  0-19: beacon interval in usec (time before exec.)
+		 * 20-23: 0
+		 * 24-31: number of beacons (suspend between channels)
+		 */
+
+		extra = (suspend_time / interval) << 24;
+		scan_suspend_time = 0xFF0FFFFF &
+		    (extra | ((suspend_time % interval) * 1024));
+
+		scan->suspend_time = cpu_to_le32(scan_suspend_time);
+		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+			       scan_suspend_time, interval);
+	}
+
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+	} else 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 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 */
+	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
+	scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
+	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	/* flags + rate selection */
+
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
+		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
+		band = IEEE80211_BAND_2GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
+		band = IEEE80211_BAND_5GHZ;
+		break;
+	default:
+		IWL_WARN(priv, "Invalid scan band\n");
+		return -EIO;
+	}
+
+	/*
+	 * 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_DEFAULT :
+					IWL_GOOD_CRC_TH_DISABLED;
+
+	if (!priv->is_internal_short_scan) {
+		scan->tx_cmd.len = cpu_to_le16(
+			iwl_legacy_fill_probe_req(priv,
+				(struct ieee80211_mgmt *)scan->data,
+				vif->addr,
+				priv->scan_request->ie,
+				priv->scan_request->ie_len,
+				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+	} else {
+		/* use bcast addr, will not be transmitted but must be valid */
+		scan->tx_cmd.len = cpu_to_le16(
+			iwl_legacy_fill_probe_req(priv,
+				(struct ieee80211_mgmt *)scan->data,
+				iwlegacy_bcast_addr, NULL, 0,
+				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
+	}
+	/* select Rx antennas */
+	scan->flags |= iwl3945_get_antenna_flags(priv);
+
+	if (priv->is_internal_short_scan) {
+		scan->channel_count =
+			iwl3945_get_single_channel_for_scan(priv, vif, band,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	} else {
+		scan->channel_count =
+			iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
+				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
+	}
+
+	if (scan->channel_count == 0) {
+		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+		return -EIO;
+	}
+
+	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+	    scan->channel_count * sizeof(struct iwl3945_scan_channel);
+	cmd.data = scan;
+	scan->len = cpu_to_le16(cmd.len);
+
+	set_bit(STATUS_SCAN_HW, &priv->status);
+	ret = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (ret)
+		clear_bit(STATUS_SCAN_HW, &priv->status);
+	return ret;
+}
+
+void iwl3945_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+		iwl3945_commit_rxon(priv, ctx);
+}
+
+static void iwl3945_bg_restart(struct work_struct *data)
+{
+	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		struct iwl_rxon_context *ctx;
+		mutex_lock(&priv->mutex);
+		for_each_context(priv, ctx)
+			ctx->vif = NULL;
+		priv->is_open = 0;
+		mutex_unlock(&priv->mutex);
+		iwl3945_down(priv);
+		ieee80211_restart_hw(priv->hw);
+	} else {
+		iwl3945_down(priv);
+
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			return;
+
+		mutex_lock(&priv->mutex);
+		__iwl3945_up(priv);
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+static void iwl3945_bg_rx_replenish(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, rx_replenish);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_rx_replenish(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+void iwl3945_post_associate(struct iwl_priv *priv)
+{
+	int rc = 0;
+	struct ieee80211_conf *conf = NULL;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (!ctx->vif || !priv->is_open)
+		return;
+
+	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
+			ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
+
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl3945_commit_rxon(priv, ctx);
+
+	rc = iwl_legacy_send_rxon_timing(priv, ctx);
+	if (rc)
+		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+			    "Attempting to continue.\n");
+
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+	ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
+
+	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
+			ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
+
+	if (ctx->vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+		if (ctx->vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+	}
+
+	iwl3945_commit_rxon(priv, ctx);
+
+	switch (ctx->vif->type) {
+	case NL80211_IFTYPE_STATION:
+		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwl3945_send_beacon_cmd(priv);
+		break;
+	default:
+		IWL_ERR(priv, "%s Should not be called in %d mode\n",
+			__func__, ctx->vif->type);
+		break;
+	}
+}
+
+/*****************************************************************************
+ *
+ * mac80211 entry point functions
+ *
+ *****************************************************************************/
+
+#define UCODE_READY_TIMEOUT	(2 * HZ)
+
+static int iwl3945_mac_start(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	/* we should be verifying the device is ready to be opened */
+	mutex_lock(&priv->mutex);
+
+	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
+	 * ucode filename and max sizes are card-specific. */
+
+	if (!priv->ucode_code.len) {
+		ret = iwl3945_read_ucode(priv);
+		if (ret) {
+			IWL_ERR(priv, "Could not read microcode: %d\n", ret);
+			mutex_unlock(&priv->mutex);
+			goto out_release_irq;
+		}
+	}
+
+	ret = __iwl3945_up(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	if (ret)
+		goto out_release_irq;
+
+	IWL_DEBUG_INFO(priv, "Start UP work.\n");
+
+	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
+	 * mac80211 will not be run successfully. */
+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+			test_bit(STATUS_READY, &priv->status),
+			UCODE_READY_TIMEOUT);
+	if (!ret) {
+		if (!test_bit(STATUS_READY, &priv->status)) {
+			IWL_ERR(priv,
+				"Wait for START_ALIVE timeout after %dms.\n",
+				jiffies_to_msecs(UCODE_READY_TIMEOUT));
+			ret = -ETIMEDOUT;
+			goto out_release_irq;
+		}
+	}
+
+	/* ucode is running and will send rfkill notifications,
+	 * no need to poll the killswitch state anymore */
+	cancel_delayed_work(&priv->_3945.rfkill_poll);
+
+	priv->is_open = 1;
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+
+out_release_irq:
+	priv->is_open = 0;
+	IWL_DEBUG_MAC80211(priv, "leave - failed\n");
+	return ret;
+}
+
+static void iwl3945_mac_stop(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!priv->is_open) {
+		IWL_DEBUG_MAC80211(priv, "leave - skip\n");
+		return;
+	}
+
+	priv->is_open = 0;
+
+	iwl3945_down(priv);
+
+	flush_workqueue(priv->workqueue);
+
+	/* start polling the killswitch state again */
+	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
+			   round_jiffies_relative(2 * HZ));
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+static void iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+	if (iwl3945_tx_skb(priv, skb))
+		dev_kfree_skb_any(skb);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+void iwl3945_config_ap(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	int rc = 0;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* The following should be done only at AP bring up */
+	if (!(iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS))) {
+
+		/* RXON - unassoc (to set timing command) */
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwl3945_commit_rxon(priv, ctx);
+
+		/* RXON Timing */
+		rc = iwl_legacy_send_rxon_timing(priv, ctx);
+		if (rc)
+			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
+					"Attempting to continue.\n");
+
+		ctx->staging.assoc_id = 0;
+
+		if (vif->bss_conf.use_short_preamble)
+			ctx->staging.flags |=
+				RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &=
+				~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+			if (vif->bss_conf.use_short_slot)
+				ctx->staging.flags |=
+					RXON_FLG_SHORT_SLOT_MSK;
+			else
+				ctx->staging.flags &=
+					~RXON_FLG_SHORT_SLOT_MSK;
+		}
+		/* restore RXON assoc */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwl3945_commit_rxon(priv, ctx);
+	}
+	iwl3945_send_beacon_cmd(priv);
+}
+
+static int iwl3945_mac_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 iwl_priv *priv = hw->priv;
+	int ret = 0;
+	u8 sta_id = IWL_INVALID_STATION;
+	u8 static_key;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (iwl3945_mod_params.sw_crypto) {
+		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
+		return -EOPNOTSUPP;
+	}
+
+	/*
+	 * To support IBSS RSN, don't program group keys in IBSS, the
+	 * hardware will then not attempt to decrypt the frames.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
+	static_key = !iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS);
+
+	if (!static_key) {
+		sta_id = iwl_legacy_sta_id_or_broadcast(
+				priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
+		if (sta_id == IWL_INVALID_STATION)
+			return -EINVAL;
+	}
+
+	mutex_lock(&priv->mutex);
+	iwl_legacy_scan_cancel_timeout(priv, 100);
+
+	switch (cmd) {
+	case SET_KEY:
+		if (static_key)
+			ret = iwl3945_set_static_key(priv, key);
+		else
+			ret = iwl3945_set_dynamic_key(priv, key, sta_id);
+		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
+		break;
+	case DISABLE_KEY:
+		if (static_key)
+			ret = iwl3945_remove_static_key(priv);
+		else
+			ret = iwl3945_clear_sta_key_info(priv, sta_id);
+		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+	return ret;
+}
+
+static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
+			       struct ieee80211_vif *vif,
+			       struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
+	int ret;
+	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
+	u8 sta_id;
+
+	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
+			sta->addr);
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+			sta->addr);
+	sta_priv->common.sta_id = IWL_INVALID_STATION;
+
+
+	ret = iwl_legacy_add_station_common(priv,
+				&priv->contexts[IWL_RXON_CTX_BSS],
+				     sta->addr, is_ap, sta, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
+			sta->addr, ret);
+		/* Should we return success if return code is EEXIST ? */
+		mutex_unlock(&priv->mutex);
+		return ret;
+	}
+
+	sta_priv->common.sta_id = sta_id;
+
+	/* Initialize rate scaling */
+	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
+		       sta->addr);
+	iwl3945_rs_rate_init(priv, sta, sta_id);
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+
+static void iwl3945_configure_filter(struct ieee80211_hw *hw,
+				     unsigned int changed_flags,
+				     unsigned int *total_flags,
+				     u64 multicast)
+{
+	struct iwl_priv *priv = hw->priv;
+	__le32 filter_or = 0, filter_nand = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+#define CHK(test, flag)	do { \
+	if (*total_flags & (test))		\
+		filter_or |= (flag);		\
+	else					\
+		filter_nand |= (flag);		\
+	} while (0)
+
+	IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+			changed_flags, *total_flags);
+
+	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
+	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+	mutex_lock(&priv->mutex);
+
+	ctx->staging.filter_flags &= ~filter_nand;
+	ctx->staging.filter_flags |= filter_or;
+
+	/*
+	 * Not committing directly because hardware can perform a scan,
+	 * but even if hw is ready, committing here breaks for some reason,
+	 * we'll eventually commit the filter flags change anyway.
+	 */
+
+	mutex_unlock(&priv->mutex);
+
+	/*
+	 * Receiving all multicast frames is always enabled by the
+	 * default flags setup in iwl_legacy_connection_init_rx_config()
+	 * since we currently do not support programming multicast
+	 * filters into the device.
+	 */
+	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t iwl3945_show_debug_level(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%08X\n", iwl_legacy_get_debug_level(priv));
+}
+static ssize_t iwl3945_store_debug_level(struct device *d,
+				struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 0, &val);
+	if (ret)
+		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
+	else {
+		priv->debug_level = val;
+		if (iwl_legacy_alloc_traffic_mem(priv))
+			IWL_ERR(priv,
+				"Not enough memory to generate traffic log\n");
+	}
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+			iwl3945_show_debug_level, iwl3945_store_debug_level);
+
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
+
+static ssize_t iwl3945_show_temperature(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, iwl3945_show_temperature, NULL);
+
+static ssize_t iwl3945_show_tx_power(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t iwl3945_store_tx_power(struct device *d,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	char *p = (char *)buf;
+	u32 val;
+
+	val = simple_strtoul(p, &p, 10);
+	if (p == buf)
+		IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
+	else
+		iwl3945_hw_reg_set_txpower(priv, val);
+
+	return count;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, iwl3945_show_tx_power, iwl3945_store_tx_power);
+
+static ssize_t iwl3945_show_flags(struct device *d,
+			  struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	return sprintf(buf, "0x%04X\n", ctx->active.flags);
+}
+
+static ssize_t iwl3945_store_flags(struct device *d,
+			   struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	u32 flags = simple_strtoul(buf, NULL, 0);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	mutex_lock(&priv->mutex);
+	if (le32_to_cpu(ctx->staging.flags) != flags) {
+		/* Cancel any currently running scans... */
+		if (iwl_legacy_scan_cancel_timeout(priv, 100))
+			IWL_WARN(priv, "Could not cancel scan.\n");
+		else {
+			IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
+				       flags);
+			ctx->staging.flags = cpu_to_le32(flags);
+			iwl3945_commit_rxon(priv, ctx);
+		}
+	}
+	mutex_unlock(&priv->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, iwl3945_show_flags, iwl3945_store_flags);
+
+static ssize_t iwl3945_show_filter_flags(struct device *d,
+				 struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	return sprintf(buf, "0x%04X\n",
+		le32_to_cpu(ctx->active.filter_flags));
+}
+
+static ssize_t iwl3945_store_filter_flags(struct device *d,
+				  struct device_attribute *attr,
+				  const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	u32 filter_flags = simple_strtoul(buf, NULL, 0);
+
+	mutex_lock(&priv->mutex);
+	if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
+		/* Cancel any currently running scans... */
+		if (iwl_legacy_scan_cancel_timeout(priv, 100))
+			IWL_WARN(priv, "Could not cancel scan.\n");
+		else {
+			IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
+				       "0x%04X\n", filter_flags);
+			ctx->staging.filter_flags =
+				cpu_to_le32(filter_flags);
+			iwl3945_commit_rxon(priv, ctx);
+		}
+	}
+	mutex_unlock(&priv->mutex);
+
+	return count;
+}
+
+static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, iwl3945_show_filter_flags,
+		   iwl3945_store_filter_flags);
+
+static ssize_t iwl3945_show_measurement(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_spectrum_notification measure_report;
+	u32 size = sizeof(measure_report), len = 0, ofs = 0;
+	u8 *data = (u8 *)&measure_report;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (!(priv->measurement_status & MEASUREMENT_READY)) {
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return 0;
+	}
+	memcpy(&measure_report, &priv->measure_report, size);
+	priv->measurement_status = 0;
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	while (size && (PAGE_SIZE - len)) {
+		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
+				   PAGE_SIZE - len, 1);
+		len = strlen(buf);
+		if (PAGE_SIZE - len)
+			buf[len++] = '\n';
+
+		ofs += 16;
+		size -= min(size, 16U);
+	}
+
+	return len;
+}
+
+static ssize_t iwl3945_store_measurement(struct device *d,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_measurement_params params = {
+		.channel = le16_to_cpu(ctx->active.channel),
+		.start_time = cpu_to_le64(priv->_3945.last_tsf),
+		.duration = cpu_to_le16(1),
+	};
+	u8 type = IWL_MEASURE_BASIC;
+	u8 buffer[32];
+	u8 channel;
+
+	if (count) {
+		char *p = buffer;
+		strncpy(buffer, buf, min(sizeof(buffer), count));
+		channel = simple_strtoul(p, NULL, 0);
+		if (channel)
+			params.channel = channel;
+
+		p = buffer;
+		while (*p && *p != ' ')
+			p++;
+		if (*p)
+			type = simple_strtoul(p + 1, NULL, 0);
+	}
+
+	IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on "
+		       "channel %d (for '%s')\n", type, params.channel, buf);
+	iwl3945_get_measurement(priv, &params, type);
+
+	return count;
+}
+
+static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
+		   iwl3945_show_measurement, iwl3945_store_measurement);
+
+static ssize_t iwl3945_store_retry_rate(struct device *d,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	priv->retry_rate = simple_strtoul(buf, NULL, 0);
+	if (priv->retry_rate <= 0)
+		priv->retry_rate = 1;
+
+	return count;
+}
+
+static ssize_t iwl3945_show_retry_rate(struct device *d,
+			       struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "%d", priv->retry_rate);
+}
+
+static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, iwl3945_show_retry_rate,
+		   iwl3945_store_retry_rate);
+
+
+static ssize_t iwl3945_show_channels(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	/* all this shit doesn't belong into sysfs anyway */
+	return 0;
+}
+
+static DEVICE_ATTR(channels, S_IRUSR, iwl3945_show_channels, NULL);
+
+static ssize_t iwl3945_show_antenna(struct device *d,
+			    struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
+}
+
+static ssize_t iwl3945_store_antenna(struct device *d,
+			     struct device_attribute *attr,
+			     const char *buf, size_t count)
+{
+	struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d);
+	int ant;
+
+	if (count == 0)
+		return 0;
+
+	if (sscanf(buf, "%1i", &ant) != 1) {
+		IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n");
+		return count;
+	}
+
+	if ((ant >= 0) && (ant <= 2)) {
+		IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant);
+		iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
+	} else
+		IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant);
+
+
+	return count;
+}
+
+static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, iwl3945_show_antenna, iwl3945_store_antenna);
+
+static ssize_t iwl3945_show_status(struct device *d,
+			   struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+	return sprintf(buf, "0x%08x\n", (int)priv->status);
+}
+
+static DEVICE_ATTR(status, S_IRUGO, iwl3945_show_status, NULL);
+
+static ssize_t iwl3945_dump_error_log(struct device *d,
+			      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(priv);
+
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, iwl3945_dump_error_log);
+
+/*****************************************************************************
+ *
+ * driver setup and tear down
+ *
+ *****************************************************************************/
+
+static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
+{
+	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
+
+	init_waitqueue_head(&priv->wait_command_queue);
+
+	INIT_WORK(&priv->restart, iwl3945_bg_restart);
+	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
+	INIT_DELAYED_WORK(&priv->init_alive_start, iwl3945_bg_init_alive_start);
+	INIT_DELAYED_WORK(&priv->alive_start, iwl3945_bg_alive_start);
+	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
+
+	iwl_legacy_setup_scan_deferred_work(priv);
+
+	iwl3945_hw_setup_deferred_work(priv);
+
+	init_timer(&priv->watchdog);
+	priv->watchdog.data = (unsigned long)priv;
+	priv->watchdog.function = iwl_legacy_bg_watchdog;
+
+	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+		     iwl3945_irq_tasklet, (unsigned long)priv);
+}
+
+static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
+{
+	iwl3945_hw_cancel_deferred_work(priv);
+
+	cancel_delayed_work_sync(&priv->init_alive_start);
+	cancel_delayed_work(&priv->alive_start);
+
+	iwl_legacy_cancel_scan_deferred_work(priv);
+}
+
+static struct attribute *iwl3945_sysfs_entries[] = {
+	&dev_attr_antenna.attr,
+	&dev_attr_channels.attr,
+	&dev_attr_dump_errors.attr,
+	&dev_attr_flags.attr,
+	&dev_attr_filter_flags.attr,
+	&dev_attr_measurement.attr,
+	&dev_attr_retry_rate.attr,
+	&dev_attr_status.attr,
+	&dev_attr_temperature.attr,
+	&dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	&dev_attr_debug_level.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group iwl3945_attribute_group = {
+	.name = NULL,		/* put in device directory */
+	.attrs = iwl3945_sysfs_entries,
+};
+
+struct ieee80211_ops iwl3945_hw_ops = {
+	.tx = iwl3945_mac_tx,
+	.start = iwl3945_mac_start,
+	.stop = iwl3945_mac_stop,
+	.add_interface = iwl_legacy_mac_add_interface,
+	.remove_interface = iwl_legacy_mac_remove_interface,
+	.change_interface = iwl_legacy_mac_change_interface,
+	.config = iwl_legacy_mac_config,
+	.configure_filter = iwl3945_configure_filter,
+	.set_key = iwl3945_mac_set_key,
+	.conf_tx = iwl_legacy_mac_conf_tx,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
+	.hw_scan = iwl_legacy_mac_hw_scan,
+	.sta_add = iwl3945_mac_sta_add,
+	.sta_remove = iwl_legacy_mac_sta_remove,
+	.tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
+};
+
+static int iwl3945_init_drv(struct iwl_priv *priv)
+{
+	int ret;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+
+	priv->retry_rate = 1;
+	priv->beacon_skb = NULL;
+
+	spin_lock_init(&priv->sta_lock);
+	spin_lock_init(&priv->hcmd_lock);
+
+	INIT_LIST_HEAD(&priv->free_frames);
+
+	mutex_init(&priv->mutex);
+	mutex_init(&priv->sync_cmd_mutex);
+
+	priv->ieee_channels = NULL;
+	priv->ieee_rates = NULL;
+	priv->band = IEEE80211_BAND_2GHZ;
+
+	priv->iw_mode = NL80211_IFTYPE_STATION;
+	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+
+	/* initialize force reset */
+	priv->force_reset[IWL_RF_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_RF_RESET;
+	priv->force_reset[IWL_FW_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
+		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
+			 eeprom->version);
+		ret = -EINVAL;
+		goto err;
+	}
+	ret = iwl_legacy_init_channel_map(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
+		goto err;
+	}
+
+	/* Set up txpower settings in driver for all channels */
+	if (iwl3945_txpower_set_from_eeprom(priv)) {
+		ret = -EIO;
+		goto err_free_channel_map;
+	}
+
+	ret = iwl_legacy_init_geos(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
+		goto err_free_channel_map;
+	}
+	iwl3945_init_hw_rates(priv, priv->ieee_rates);
+
+	return 0;
+
+err_free_channel_map:
+	iwl_legacy_free_channel_map(priv);
+err:
+	return ret;
+}
+
+#define IWL3945_MAX_PROBE_REQUEST	200
+
+static int iwl3945_setup_mac(struct iwl_priv *priv)
+{
+	int ret;
+	struct ieee80211_hw *hw = priv->hw;
+
+	hw->rate_control_algorithm = "iwl-3945-rs";
+	hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
+	hw->vif_data_size = sizeof(struct iwl_vif_priv);
+
+	/* Tell mac80211 our characteristics */
+	hw->flags = IEEE80211_HW_SIGNAL_DBM |
+		    IEEE80211_HW_SPECTRUM_MGMT;
+
+	hw->wiphy->interface_modes =
+		priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
+
+	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
+			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
+			    WIPHY_FLAG_IBSS_RSN;
+
+	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 = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
+
+	/* Default value; 4 EDCA QOS priorities */
+	hw->queues = 4;
+
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&priv->bands[IEEE80211_BAND_2GHZ];
+
+	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&priv->bands[IEEE80211_BAND_5GHZ];
+
+	iwl_legacy_leds_init(priv);
+
+	ret = ieee80211_register_hw(priv->hw);
+	if (ret) {
+		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
+		return ret;
+	}
+	priv->mac80211_registered = 1;
+
+	return 0;
+}
+
+static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err = 0, i;
+	struct iwl_priv *priv;
+	struct ieee80211_hw *hw;
+	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	struct iwl3945_eeprom *eeprom;
+	unsigned long flags;
+
+	/***********************
+	 * 1. Allocating HW data
+	 * ********************/
+
+	/* mac80211 allocates memory for this device instance, including
+	 *   space for this driver's private structure */
+	hw = iwl_legacy_alloc_all(cfg);
+	if (hw == NULL) {
+		pr_err("Can not allocate network device\n");
+		err = -ENOMEM;
+		goto out;
+	}
+	priv = hw->priv;
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
+
+	/* 3945 has only one valid context */
+	priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+	for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+		priv->contexts[i].ctxid = i;
+
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+	priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+	priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+		BIT(NL80211_IFTYPE_STATION) |
+		BIT(NL80211_IFTYPE_ADHOC);
+	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
+	/*
+	 * Disabling hardware scan means that mac80211 will perform scans
+	 * "the hard way", rather than using device's scan.
+	 */
+	if (iwl3945_mod_params.disable_hw_scan) {
+		IWL_DEBUG_INFO(priv, "Disabling hw_scan\n");
+		iwl3945_hw_ops.hw_scan = NULL;
+	}
+
+	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
+	priv->cfg = cfg;
+	priv->pci_dev = pdev;
+	priv->inta_mask = CSR_INI_SET_MASK;
+
+	if (iwl_legacy_alloc_traffic_mem(priv))
+		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
+
+	/***************************
+	 * 2. Initializing PCI bus
+	 * *************************/
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				PCIE_LINK_STATE_CLKPM);
+
+	if (pci_enable_device(pdev)) {
+		err = -ENODEV;
+		goto out_ieee80211_free_hw;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
+	if (err) {
+		IWL_WARN(priv, "No suitable DMA available.\n");
+		goto out_pci_disable_device;
+	}
+
+	pci_set_drvdata(pdev, priv);
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err)
+		goto out_pci_disable_device;
+
+	/***********************
+	 * 3. Read REV Register
+	 * ********************/
+	priv->hw_base = pci_iomap(pdev, 0, 0);
+	if (!priv->hw_base) {
+		err = -ENODEV;
+		goto out_pci_release_regions;
+	}
+
+	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
+			(unsigned long long) pci_resource_len(pdev, 0));
+	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
+
+	/* We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state */
+	pci_write_config_byte(pdev, 0x41, 0x00);
+
+	/* these spin locks will be used in apm_ops.init and EEPROM access
+	 * we should init now
+	 */
+	spin_lock_init(&priv->reg_lock);
+	spin_lock_init(&priv->lock);
+
+	/*
+	 * stop and reset the on-board processor just in case it is in a
+	 * strange state ... like being left stranded by a primary kernel
+	 * and this is now the kdump kernel trying to start up
+	 */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/***********************
+	 * 4. Read EEPROM
+	 * ********************/
+
+	/* Read the EEPROM */
+	err = iwl_legacy_eeprom_init(priv);
+	if (err) {
+		IWL_ERR(priv, "Unable to init EEPROM\n");
+		goto out_iounmap;
+	}
+	/* MAC Address location in EEPROM same for 3945/4965 */
+	eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
+	SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
+
+	/***********************
+	 * 5. Setup HW Constants
+	 * ********************/
+	/* Device-specific setup */
+	if (iwl3945_hw_set_hw_params(priv)) {
+		IWL_ERR(priv, "failed to set hw settings\n");
+		goto out_eeprom_free;
+	}
+
+	/***********************
+	 * 6. Setup priv
+	 * ********************/
+
+	err = iwl3945_init_drv(priv);
+	if (err) {
+		IWL_ERR(priv, "initializing driver failed\n");
+		goto out_unset_hw_params;
+	}
+
+	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
+		priv->cfg->name);
+
+	/***********************
+	 * 7. Setup Services
+	 * ********************/
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	pci_enable_msi(priv->pci_dev);
+
+	err = request_irq(priv->pci_dev->irq, iwl_legacy_isr,
+			  IRQF_SHARED, DRV_NAME, priv);
+	if (err) {
+		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
+		goto out_disable_msi;
+	}
+
+	err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+	if (err) {
+		IWL_ERR(priv, "failed to create sysfs device attributes\n");
+		goto out_release_irq;
+	}
+
+	iwl_legacy_set_rxon_channel(priv,
+			     &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
+			     &priv->contexts[IWL_RXON_CTX_BSS]);
+	iwl3945_setup_deferred_work(priv);
+	iwl3945_setup_rx_handlers(priv);
+	iwl_legacy_power_initialize(priv);
+
+	/*********************************
+	 * 8. Setup and Register mac80211
+	 * *******************************/
+
+	iwl_legacy_enable_interrupts(priv);
+
+	err = iwl3945_setup_mac(priv);
+	if (err)
+		goto  out_remove_sysfs;
+
+	err = iwl_legacy_dbgfs_register(priv, DRV_NAME);
+	if (err)
+		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
+
+	/* Start monitoring the killswitch */
+	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
+			   2 * HZ);
+
+	return 0;
+
+ out_remove_sysfs:
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+ out_release_irq:
+	free_irq(priv->pci_dev->irq, priv);
+ out_disable_msi:
+	pci_disable_msi(priv->pci_dev);
+	iwl_legacy_free_geos(priv);
+	iwl_legacy_free_channel_map(priv);
+ out_unset_hw_params:
+	iwl3945_unset_hw_params(priv);
+ out_eeprom_free:
+	iwl_legacy_eeprom_free(priv);
+ out_iounmap:
+	pci_iounmap(pdev, priv->hw_base);
+ out_pci_release_regions:
+	pci_release_regions(pdev);
+ out_pci_disable_device:
+	pci_set_drvdata(pdev, NULL);
+	pci_disable_device(pdev);
+ out_ieee80211_free_hw:
+	iwl_legacy_free_traffic_mem(priv);
+	ieee80211_free_hw(priv->hw);
+ out:
+	return err;
+}
+
+static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
+{
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	if (!priv)
+		return;
+
+	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
+
+	iwl_legacy_dbgfs_unregister(priv);
+
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	iwl_legacy_leds_exit(priv);
+
+	if (priv->mac80211_registered) {
+		ieee80211_unregister_hw(priv->hw);
+		priv->mac80211_registered = 0;
+	} else {
+		iwl3945_down(priv);
+	}
+
+	/*
+	 * Make sure device is reset to low power before unloading driver.
+	 * This may be redundant with iwl_down(), but there are paths to
+	 * run iwl_down() without calling apm_ops.stop(), and there are
+	 * paths to avoid running iwl_down() at all before leaving driver.
+	 * This (inexpensive) call *makes sure* device is reset.
+	 */
+	iwl_legacy_apm_stop(priv);
+
+	/* make sure we flush any pending irq or
+	 * tasklet for the driver
+	 */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl3945_synchronize_irq(priv);
+
+	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
+
+	cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
+
+	iwl3945_dealloc_ucode_pci(priv);
+
+	if (priv->rxq.bd)
+		iwl3945_rx_queue_free(priv, &priv->rxq);
+	iwl3945_hw_txq_ctx_free(priv);
+
+	iwl3945_unset_hw_params(priv);
+
+	/*netif_stop_queue(dev); */
+	flush_workqueue(priv->workqueue);
+
+	/* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
+	 * priv->workqueue... so we can't take down the workqueue
+	 * until now... */
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	iwl_legacy_free_traffic_mem(priv);
+
+	free_irq(pdev->irq, priv);
+	pci_disable_msi(pdev);
+
+	pci_iounmap(pdev, priv->hw_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+
+	iwl_legacy_free_channel_map(priv);
+	iwl_legacy_free_geos(priv);
+	kfree(priv->scan_cmd);
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	ieee80211_free_hw(priv->hw);
+}
+
+
+/*****************************************************************************
+ *
+ * driver and module entry point
+ *
+ *****************************************************************************/
+
+static struct pci_driver iwl3945_driver = {
+	.name = DRV_NAME,
+	.id_table = iwl3945_hw_card_ids,
+	.probe = iwl3945_pci_probe,
+	.remove = __devexit_p(iwl3945_pci_remove),
+	.driver.pm = IWL_LEGACY_PM_OPS,
+};
+
+static int __init iwl3945_init(void)
+{
+
+	int ret;
+	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	pr_info(DRV_COPYRIGHT "\n");
+
+	ret = iwl3945_rate_control_register();
+	if (ret) {
+		pr_err("Unable to register rate control algorithm: %d\n", ret);
+		return ret;
+	}
+
+	ret = pci_register_driver(&iwl3945_driver);
+	if (ret) {
+		pr_err("Unable to initialize PCI module\n");
+		goto error_register;
+	}
+
+	return ret;
+
+error_register:
+	iwl3945_rate_control_unregister();
+	return ret;
+}
+
+static void __exit iwl3945_exit(void)
+{
+	pci_unregister_driver(&iwl3945_driver);
+	iwl3945_rate_control_unregister();
+}
+
+/*(DEBLOBBED)*/
+
+module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO);
+MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
+module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO);
+MODULE_PARM_DESC(swcrypto,
+		"using software crypto (default 1 [software])");
+module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
+		int, S_IRUGO);
+MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 1)");
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+module_param_named(fw_restart, iwl3945_mod_params.restart_fw, int, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
+
+module_exit(iwl3945_exit);
+module_init(iwl3945_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2742 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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 <linux/slab.h>
+#include <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+#include <net/mac80211.h>
+
+#include "iwl-fh.h"
+#include "iwl-3945-fh.h"
+#include "iwl-commands.h"
+#include "iwl-sta.h"
+#include "iwl-3945.h"
+#include "iwl-eeprom.h"
+#include "iwl-core.h"
+#include "iwl-helpers.h"
+#include "iwl-led.h"
+#include "iwl-3945-led.h"
+#include "iwl-3945-debugfs.h"
+
+#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
+	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
+				    IWL_RATE_##r##M_IEEE,   \
+				    IWL_RATE_##ip##M_INDEX, \
+				    IWL_RATE_##in##M_INDEX, \
+				    IWL_RATE_##rp##M_INDEX, \
+				    IWL_RATE_##rn##M_INDEX, \
+				    IWL_RATE_##pp##M_INDEX, \
+				    IWL_RATE_##np##M_INDEX, \
+				    IWL_RATE_##r##M_INDEX_TABLE, \
+				    IWL_RATE_##ip##M_INDEX_TABLE }
+
+/*
+ * Parameter order:
+ *   rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to IWL_RATE_INVALID
+ *
+ */
+const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
+	IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),    /*  1mbps */
+	IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),          /*  2mbps */
+	IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
+	IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),      /* 11mbps */
+	IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
+	IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),       /*  9mbps */
+	IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
+	IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
+	IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
+	IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
+	IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
+	IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
+};
+
+static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
+{
+	u8 rate = iwl3945_rates[rate_index].prev_ieee;
+
+	if (rate == IWL_RATE_INVALID)
+		rate = rate_index;
+	return rate;
+}
+
+/* 1 = enable the iwl3945_disable_events() function */
+#define IWL_EVT_DISABLE (0)
+#define IWL_EVT_DISABLE_SIZE (1532/32)
+
+/**
+ * iwl3945_disable_events - Disable selected events in uCode event log
+ *
+ * Disable an event by writing "1"s into "disable"
+ *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
+ *   Default values of 0 enable uCode events to be logged.
+ * Use for only special debugging.  This function is just a placeholder as-is,
+ *   you'll need to provide the special bits! ...
+ *   ... and set IWL_EVT_DISABLE to 1. */
+void iwl3945_disable_events(struct iwl_priv *priv)
+{
+	int i;
+	u32 base;		/* SRAM address of event log header */
+	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
+	u32 array_size;		/* # of u32 entries in array */
+	static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
+		0x00000000,	/*   31 -    0  Event id numbers */
+		0x00000000,	/*   63 -   32 */
+		0x00000000,	/*   95 -   64 */
+		0x00000000,	/*  127 -   96 */
+		0x00000000,	/*  159 -  128 */
+		0x00000000,	/*  191 -  160 */
+		0x00000000,	/*  223 -  192 */
+		0x00000000,	/*  255 -  224 */
+		0x00000000,	/*  287 -  256 */
+		0x00000000,	/*  319 -  288 */
+		0x00000000,	/*  351 -  320 */
+		0x00000000,	/*  383 -  352 */
+		0x00000000,	/*  415 -  384 */
+		0x00000000,	/*  447 -  416 */
+		0x00000000,	/*  479 -  448 */
+		0x00000000,	/*  511 -  480 */
+		0x00000000,	/*  543 -  512 */
+		0x00000000,	/*  575 -  544 */
+		0x00000000,	/*  607 -  576 */
+		0x00000000,	/*  639 -  608 */
+		0x00000000,	/*  671 -  640 */
+		0x00000000,	/*  703 -  672 */
+		0x00000000,	/*  735 -  704 */
+		0x00000000,	/*  767 -  736 */
+		0x00000000,	/*  799 -  768 */
+		0x00000000,	/*  831 -  800 */
+		0x00000000,	/*  863 -  832 */
+		0x00000000,	/*  895 -  864 */
+		0x00000000,	/*  927 -  896 */
+		0x00000000,	/*  959 -  928 */
+		0x00000000,	/*  991 -  960 */
+		0x00000000,	/* 1023 -  992 */
+		0x00000000,	/* 1055 - 1024 */
+		0x00000000,	/* 1087 - 1056 */
+		0x00000000,	/* 1119 - 1088 */
+		0x00000000,	/* 1151 - 1120 */
+		0x00000000,	/* 1183 - 1152 */
+		0x00000000,	/* 1215 - 1184 */
+		0x00000000,	/* 1247 - 1216 */
+		0x00000000,	/* 1279 - 1248 */
+		0x00000000,	/* 1311 - 1280 */
+		0x00000000,	/* 1343 - 1312 */
+		0x00000000,	/* 1375 - 1344 */
+		0x00000000,	/* 1407 - 1376 */
+		0x00000000,	/* 1439 - 1408 */
+		0x00000000,	/* 1471 - 1440 */
+		0x00000000,	/* 1503 - 1472 */
+	};
+
+	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
+		return;
+	}
+
+	disable_ptr = iwl_legacy_read_targ_mem(priv, base + (4 * sizeof(u32)));
+	array_size = iwl_legacy_read_targ_mem(priv, base + (5 * sizeof(u32)));
+
+	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);
+		for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
+			iwl_legacy_write_targ_mem(priv,
+					   disable_ptr + (i * sizeof(u32)),
+					   evt_disable[i]);
+
+	} 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");
+		IWL_DEBUG_INFO(priv, "  in SRAM at 0x%x, size %d u32s\n",
+			       disable_ptr, array_size);
+	}
+
+}
+
+static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
+{
+	int idx;
+
+	for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++)
+		if (iwl3945_rates[idx].plcp == plcp)
+			return idx;
+	return -1;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
+
+static const char *iwl3945_get_tx_fail_reason(u32 status)
+{
+	switch (status & TX_STATUS_MSK) {
+	case TX_3945_STATUS_SUCCESS:
+		return "SUCCESS";
+		TX_STATUS_ENTRY(SHORT_LIMIT);
+		TX_STATUS_ENTRY(LONG_LIMIT);
+		TX_STATUS_ENTRY(FIFO_UNDERRUN);
+		TX_STATUS_ENTRY(MGMNT_ABORT);
+		TX_STATUS_ENTRY(NEXT_FRAG);
+		TX_STATUS_ENTRY(LIFE_EXPIRE);
+		TX_STATUS_ENTRY(DEST_PS);
+		TX_STATUS_ENTRY(ABORTED);
+		TX_STATUS_ENTRY(BT_RETRY);
+		TX_STATUS_ENTRY(STA_INVALID);
+		TX_STATUS_ENTRY(FRAG_DROPPED);
+		TX_STATUS_ENTRY(TID_DISABLE);
+		TX_STATUS_ENTRY(FRAME_FLUSHED);
+		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
+		TX_STATUS_ENTRY(TX_LOCKED);
+		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
+	}
+
+	return "UNKNOWN";
+}
+#else
+static inline const char *iwl3945_get_tx_fail_reason(u32 status)
+{
+	return "";
+}
+#endif
+
+/*
+ * get ieee prev rate from rate scale table.
+ * for A and B mode we need to overright prev
+ * value
+ */
+int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
+{
+	int next_rate = iwl3945_get_prev_ieee_rate(rate);
+
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
+		if (rate == IWL_RATE_12M_INDEX)
+			next_rate = IWL_RATE_9M_INDEX;
+		else if (rate == IWL_RATE_6M_INDEX)
+			next_rate = IWL_RATE_6M_INDEX;
+		break;
+	case IEEE80211_BAND_2GHZ:
+		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+		    iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+			if (rate == IWL_RATE_11M_INDEX)
+				next_rate = IWL_RATE_5M_INDEX;
+		}
+		break;
+
+	default:
+		break;
+	}
+
+	return next_rate;
+}
+
+
+/**
+ * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms. If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
+				     int txq_id, int index)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_tx_info *tx_info;
+
+	BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
+
+	for (index = iwl_legacy_queue_inc_wrap(index, q->n_bd);
+		q->read_ptr != index;
+		q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		tx_info = &txq->txb[txq->q.read_ptr];
+		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
+		tx_info->skb = NULL;
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+	}
+
+	if (iwl_legacy_queue_space(q) > q->low_mark && (txq_id >= 0) &&
+			(txq_id != IWL39_CMD_QUEUE_NUM) &&
+			priv->mac80211_registered)
+		iwl_legacy_wake_queue(priv, txq);
+}
+
+/**
+ * iwl3945_rx_reply_tx - Handle Tx response
+ */
+static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct ieee80211_tx_info *info;
+	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	u32  status = le32_to_cpu(tx_resp->status);
+	int rate_idx;
+	int fail;
+
+	if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
+			  "is out of range [0-%d] %d %d\n", txq_id,
+			  index, txq->q.n_bd, txq->q.write_ptr,
+			  txq->q.read_ptr);
+		return;
+	}
+
+	txq->time_stamp = jiffies;
+	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+	ieee80211_tx_info_clear_status(info);
+
+	/* Fill the MRR chain with some info about on-chip retransmissions */
+	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
+	if (info->band == IEEE80211_BAND_5GHZ)
+		rate_idx -= IWL_FIRST_OFDM_RATE;
+
+	fail = tx_resp->failure_frame;
+
+	info->status.rates[0].idx = rate_idx;
+	info->status.rates[0].count = fail + 1; /* add final attempt */
+
+	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
+	info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
+				IEEE80211_TX_STAT_ACK : 0;
+
+	IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
+			txq_id, iwl3945_get_tx_fail_reason(status), status,
+			tx_resp->rate, tx_resp->failure_frame);
+
+	IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
+	iwl3945_tx_queue_reclaim(priv, txq_id, index);
+
+	if (status & TX_ABORT_REQUIRED_MSK)
+		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
+}
+
+
+
+/*****************************************************************************
+ *
+ * Intel PRO/Wireless 3945ABG/BG Network Connection
+ *
+ *  RX handler implementations
+ *
+ *****************************************************************************/
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
+					    __le32 *stats)
+{
+	int i;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+
+	prev_stats = (__le32 *)&priv->_3945.statistics;
+	accum_stats = (u32 *)&priv->_3945.accum_statistics;
+	delta = (u32 *)&priv->_3945.delta_statistics;
+	max_delta = (u32 *)&priv->_3945.max_delta;
+
+	for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
+		}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	priv->_3945.accum_statistics.general.temperature =
+		priv->_3945.statistics.general.temperature;
+	priv->_3945.accum_statistics.general.ttl_timestamp =
+		priv->_3945.statistics.general.ttl_timestamp;
+}
+#endif
+
+void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+		struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
+		     (int)sizeof(struct iwl3945_notif_statistics),
+		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
+#endif
+	iwl_legacy_recover_from_statistics(priv, pkt);
+
+	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
+}
+
+void iwl3945_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	__le32 *flag = (__le32 *)&pkt->u.raw;
+
+	if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+		memset(&priv->_3945.accum_statistics, 0,
+			sizeof(struct iwl3945_notif_statistics));
+		memset(&priv->_3945.delta_statistics, 0,
+			sizeof(struct iwl3945_notif_statistics));
+		memset(&priv->_3945.max_delta, 0,
+			sizeof(struct iwl3945_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl3945_hw_rx_statistics(priv, rxb);
+}
+
+
+/******************************************************************************
+ *
+ * Misc. internal state and helper functions
+ *
+ ******************************************************************************/
+
+/* This is necessary only for a number of statistics, see the caller. */
+static int iwl3945_is_network_packet(struct iwl_priv *priv,
+		struct ieee80211_hdr *header)
+{
+	/* Filter incoming packets to determine if they are targeted toward
+	 * this network, discarding packets coming from ourselves */
+	switch (priv->iw_mode) {
+	case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source    | BSSID */
+		/* packets to our IBSS update information */
+		return !compare_ether_addr(header->addr3, priv->bssid);
+	case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
+		/* packets to our IBSS update information */
+		return !compare_ether_addr(header->addr2, priv->bssid);
+	default:
+		return 1;
+	}
+}
+
+static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
+				   struct iwl_rx_mem_buffer *rxb,
+				   struct ieee80211_rx_status *stats)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
+	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+	u16 len = le16_to_cpu(rx_hdr->len);
+	struct sk_buff *skb;
+	__le16 fc = hdr->frame_control;
+
+	/* We received data from the HW, so stop the watchdog */
+	if (unlikely(len + IWL39_RX_FRAME_SIZE >
+		     PAGE_SIZE << priv->hw_params.rx_page_order)) {
+		IWL_DEBUG_DROP(priv, "Corruption detected!\n");
+		return;
+	}
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!priv->is_open)) {
+		IWL_DEBUG_DROP_LIMIT(priv,
+			"Dropping packet while interface is not open.\n");
+		return;
+	}
+
+	skb = dev_alloc_skb(128);
+	if (!skb) {
+		IWL_ERR(priv, "dev_alloc_skb failed\n");
+		return;
+	}
+
+	if (!iwl3945_mod_params.sw_crypto)
+		iwl_legacy_set_decrypted_flag(priv,
+				       (struct ieee80211_hdr *)rxb_addr(rxb),
+				       le32_to_cpu(rx_end->status), stats);
+
+	skb_add_rx_frag(skb, 0, rxb->page,
+			(void *)rx_hdr->payload - (void *)pkt, len);
+
+	iwl_legacy_update_stats(priv, false, fc, len);
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+	ieee80211_rx(priv->hw, skb);
+	priv->alloc_rxb_page--;
+	rxb->page = NULL;
+}
+
+#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
+
+static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct ieee80211_hdr *header;
+	struct ieee80211_rx_status rx_status;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
+	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
+	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
+	u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
+	u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
+	u8 network_packet;
+
+	rx_status.flag = 0;
+	rx_status.mactime = le64_to_cpu(rx_end->timestamp);
+	rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	rx_status.freq =
+		ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel),
+					       rx_status.band);
+
+	rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
+	if (rx_status.band == IEEE80211_BAND_5GHZ)
+		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
+
+	rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
+					RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
+
+	/* set the preamble flag if appropriate */
+	if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+		rx_status.flag |= RX_FLAG_SHORTPRE;
+
+	if ((unlikely(rx_stats->phy_count > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				rx_stats->phy_count);
+		return;
+	}
+
+	if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR)
+	    || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
+		return;
+	}
+
+
+
+	/* Convert 3945's rssi indicator to dBm */
+	rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
+
+	IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
+			rx_status.signal, rx_stats_sig_avg,
+			rx_stats_noise_diff);
+
+	header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
+
+	network_packet = iwl3945_is_network_packet(priv, header);
+
+	IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
+			      network_packet ? '*' : ' ',
+			      le16_to_cpu(rx_hdr->channel),
+			      rx_status.signal, rx_status.signal,
+			      rx_status.rate_idx);
+
+	iwl_legacy_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len),
+						header);
+
+	if (network_packet) {
+		priv->_3945.last_beacon_time =
+			le32_to_cpu(rx_end->beacon_timestamp);
+		priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
+		priv->_3945.last_rx_rssi = rx_status.signal;
+	}
+
+	iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
+}
+
+int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				     struct iwl_tx_queue *txq,
+				     dma_addr_t addr, u16 len, u8 reset, u8 pad)
+{
+	int count;
+	struct iwl_queue *q;
+	struct iwl3945_tfd *tfd, *tfd_tmp;
+
+	q = &txq->q;
+	tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
+	tfd = &tfd_tmp[q->write_ptr];
+
+	if (reset)
+		memset(tfd, 0, sizeof(*tfd));
+
+	count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
+
+	if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
+		IWL_ERR(priv, "Error can not send more than %d chunks\n",
+			  NUM_TFD_CHUNKS);
+		return -EINVAL;
+	}
+
+	tfd->tbs[count].addr = cpu_to_le32(addr);
+	tfd->tbs[count].len = cpu_to_le32(len);
+
+	count++;
+
+	tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) |
+					 TFD_CTL_PAD_SET(pad));
+
+	return 0;
+}
+
+/**
+ * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr]
+ *
+ * Does NOT advance any indexes
+ */
+void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
+	int index = txq->q.read_ptr;
+	struct iwl3945_tfd *tfd = &tfd_tmp[index];
+	struct pci_dev *dev = priv->pci_dev;
+	int i;
+	int counter;
+
+	/* sanity check */
+	counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
+	if (counter > NUM_TFD_CHUNKS) {
+		IWL_ERR(priv, "Too many chunks: %i\n", counter);
+		/* @todo issue fatal error, it is quite serious situation */
+		return;
+	}
+
+	/* Unmap tx_cmd */
+	if (counter)
+		pci_unmap_single(dev,
+				dma_unmap_addr(&txq->meta[index], mapping),
+				dma_unmap_len(&txq->meta[index], len),
+				PCI_DMA_TODEVICE);
+
+	/* unmap chunks if any */
+
+	for (i = 1; i < counter; i++)
+		pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
+			 le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
+
+	/* free SKB */
+	if (txq->txb) {
+		struct sk_buff *skb;
+
+		skb = txq->txb[txq->q.read_ptr].skb;
+
+		/* can be called from irqs-disabled context */
+		if (skb) {
+			dev_kfree_skb_any(skb);
+			txq->txb[txq->q.read_ptr].skb = NULL;
+		}
+	}
+}
+
+/**
+ * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
+ *
+*/
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+				  struct iwl_device_cmd *cmd,
+				  struct ieee80211_tx_info *info,
+				  struct ieee80211_hdr *hdr,
+				  int sta_id, int tx_id)
+{
+	u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
+	u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945);
+	u16 rate_mask;
+	int rate;
+	u8 rts_retry_limit;
+	u8 data_retry_limit;
+	__le32 tx_flags;
+	__le16 fc = hdr->frame_control;
+	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
+
+	rate = iwl3945_rates[rate_index].plcp;
+	tx_flags = tx_cmd->tx_flags;
+
+	/* We need to figure out how to get the sta->supp_rates while
+	 * in this running context */
+	rate_mask = IWL_RATES_MASK_3945;
+
+	/* Set retry limit on DATA packets and Probe Responses*/
+	if (ieee80211_is_probe_resp(fc))
+		data_retry_limit = 3;
+	else
+		data_retry_limit = IWL_DEFAULT_TX_RETRY;
+	tx_cmd->data_retry_limit = data_retry_limit;
+
+	if (tx_id >= IWL39_CMD_QUEUE_NUM)
+		rts_retry_limit = 3;
+	else
+		rts_retry_limit = 7;
+
+	if (data_retry_limit < rts_retry_limit)
+		rts_retry_limit = data_retry_limit;
+	tx_cmd->rts_retry_limit = rts_retry_limit;
+
+	tx_cmd->rate = rate;
+	tx_cmd->tx_flags = tx_flags;
+
+	/* OFDM */
+	tx_cmd->supp_rates[0] =
+	   ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
+
+	/* CCK */
+	tx_cmd->supp_rates[1] = (rate_mask & 0xF);
+
+	IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
+		       "cck/ofdm mask: 0x%x/0x%x\n", sta_id,
+		       tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags),
+		       tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
+}
+
+static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
+{
+	unsigned long flags_spin;
+	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[sta_id];
+
+	station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
+	station->sta.rate_n_flags = cpu_to_le16(tx_rate);
+	station->sta.mode = STA_CONTROL_MODIFY_MSK;
+	iwl_legacy_send_add_sta(priv, &station->sta, CMD_ASYNC);
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
+			sta_id, tx_rate);
+	return sta_id;
+}
+
+static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do
+
+		if (pci_pme_capable(priv->pci_dev, PCI_D3cold)) {
+			iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+					APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+					~APMG_PS_CTRL_MSK_PWR_SRC);
+
+			iwl_poll_bit(priv, CSR_GPIO_IN,
+				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
+				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
+		}
+ */
+
+	iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			~APMG_PS_CTRL_MSK_PWR_SRC);
+
+	iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
+		     CSR_GPIO_IN_BIT_AUX_POWER, 5000);	/* uS */
+}
+
+static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	iwl_legacy_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
+	iwl_legacy_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0),
+					rxq->rb_stts_dma);
+	iwl_legacy_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
+	iwl_legacy_write_direct32(priv, FH39_RCSR_CONFIG(0),
+		FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
+		FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
+		FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
+		FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
+		(RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
+		FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
+		(1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
+		FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
+
+	/* fake read to flush all prev I/O */
+	iwl_legacy_read_direct32(priv, FH39_RSSR_CTRL);
+
+	return 0;
+}
+
+static int iwl3945_tx_reset(struct iwl_priv *priv)
+{
+
+	/* bypass mode */
+	iwl_legacy_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
+
+	/* RA 0 is active */
+	iwl_legacy_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
+
+	/* all 6 fifo are active */
+	iwl_legacy_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
+
+	iwl_legacy_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
+	iwl_legacy_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
+	iwl_legacy_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
+	iwl_legacy_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
+
+	iwl_legacy_write_direct32(priv, FH39_TSSR_CBB_BASE,
+			     priv->_3945.shared_phys);
+
+	iwl_legacy_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
+		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
+
+
+	return 0;
+}
+
+/**
+ * iwl3945_txq_ctx_reset - Reset TX queue context
+ *
+ * Destroys all DMA structures and initialize them again
+ */
+static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
+{
+	int rc;
+	int txq_id, slots_num;
+
+	iwl3945_hw_txq_ctx_free(priv);
+
+	/* allocate tx queue structure */
+	rc = iwl_legacy_alloc_txq_mem(priv);
+	if (rc)
+		return rc;
+
+	/* Tx CMD queue */
+	rc = iwl3945_tx_reset(priv);
+	if (rc)
+		goto error;
+
+	/* Tx queue(s) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
+				TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		rc = iwl_legacy_tx_queue_init(priv, &priv->txq[txq_id],
+						slots_num, txq_id);
+		if (rc) {
+			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return rc;
+
+ error:
+	iwl3945_hw_txq_ctx_free(priv);
+	return rc;
+}
+
+
+/*
+ * Start up 3945's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via iwl_legacy_apm_stop())
+ * NOTE:  This does not load uCode nor start the embedded processor
+ */
+static int iwl3945_apm_init(struct iwl_priv *priv)
+{
+	int ret = iwl_legacy_apm_init(priv);
+
+	/* Clear APMG (NIC's internal power management) interrupts */
+	iwl_legacy_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
+	iwl_legacy_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
+
+	/* Reset radio chip */
+	iwl_legacy_set_bits_prph(priv, APMG_PS_CTRL_REG,
+				APMG_PS_CTRL_VAL_RESET_REQ);
+	udelay(5);
+	iwl_legacy_clear_bits_prph(priv, APMG_PS_CTRL_REG,
+				APMG_PS_CTRL_VAL_RESET_REQ);
+
+	return ret;
+}
+
+static void iwl3945_nic_config(struct iwl_priv *priv)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	unsigned long flags;
+	u8 rev_id = priv->pci_dev->revision;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Determine HW type */
+	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) {
+		IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
+	} else {
+		IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n");
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
+	}
+
+	if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
+		IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n");
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
+	} else
+		IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n");
+
+	if ((eeprom->board_revision & 0xF0) == 0xD0) {
+		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
+			       eeprom->board_revision);
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+	} else {
+		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
+			       eeprom->board_revision);
+		iwl_legacy_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+			      CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
+	}
+
+	if (eeprom->almgor_m_version <= 1) {
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
+		IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n",
+			       eeprom->almgor_m_version);
+	} else {
+		IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n",
+			       eeprom->almgor_m_version);
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
+		IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n");
+
+	if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
+		IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n");
+}
+
+int iwl3945_hw_nic_init(struct iwl_priv *priv)
+{
+	int rc;
+	unsigned long flags;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->cfg->ops->lib->apm_ops.init(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl3945_set_pwr_vmain(priv);
+
+	priv->cfg->ops->lib->apm_ops.config(priv);
+
+	/* Allocate the RX queue, or reset if it is already allocated */
+	if (!rxq->bd) {
+		rc = iwl_legacy_rx_queue_alloc(priv);
+		if (rc) {
+			IWL_ERR(priv, "Unable to initialize Rx queue\n");
+			return -ENOMEM;
+		}
+	} else
+		iwl3945_rx_queue_reset(priv, rxq);
+
+	iwl3945_rx_replenish(priv);
+
+	iwl3945_rx_init(priv, rxq);
+
+
+	/* Look at using this instead:
+	rxq->need_update = 1;
+	iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+	*/
+
+	iwl_legacy_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
+
+	rc = iwl3945_txq_ctx_reset(priv);
+	if (rc)
+		return rc;
+
+	set_bit(STATUS_INIT, &priv->status);
+
+	return 0;
+}
+
+/**
+ * iwl3945_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* Tx queues */
+	if (priv->txq)
+		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
+		     txq_id++)
+			if (txq_id == IWL39_CMD_QUEUE_NUM)
+				iwl_legacy_cmd_queue_free(priv);
+			else
+				iwl_legacy_tx_queue_free(priv, txq_id);
+
+	/* free tx queue structure */
+	iwl_legacy_txq_mem(priv);
+}
+
+void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* stop SCD */
+	iwl_legacy_write_prph(priv, ALM_SCD_MODE_REG, 0);
+	iwl_legacy_write_prph(priv, ALM_SCD_TXFACT_REG, 0);
+
+	/* reset TFD queues */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		iwl_legacy_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
+		iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
+				FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
+				1000);
+	}
+
+	iwl3945_hw_txq_ctx_free(priv);
+}
+
+/**
+ * iwl3945_hw_reg_adjust_power_by_temp
+ * return index delta into power gain settings table
+*/
+static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
+{
+	return (new_reading - old_reading) * (-11) / 100;
+}
+
+/**
+ * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range
+ */
+static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
+{
+	return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
+}
+
+int iwl3945_hw_get_temperature(struct iwl_priv *priv)
+{
+	return iwl_read32(priv, CSR_UCODE_DRV_GP2);
+}
+
+/**
+ * iwl3945_hw_reg_txpower_get_temperature
+ * get the current temperature by reading from NIC
+*/
+static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	int temperature;
+
+	temperature = iwl3945_hw_get_temperature(priv);
+
+	/* driver's okay range is -260 to +25.
+	 *   human readable okay range is 0 to +285 */
+	IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT);
+
+	/* handle insane temp reading */
+	if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
+		IWL_ERR(priv, "Error bad temperature value  %d\n", temperature);
+
+		/* if really really hot(?),
+		 *   substitute the 3rd band/group's temp measured at factory */
+		if (priv->last_temperature > 100)
+			temperature = eeprom->groups[2].temperature;
+		else /* else use most recent "sane" value from driver */
+			temperature = priv->last_temperature;
+	}
+
+	return temperature;	/* raw, not "human readable" */
+}
+
+/* Adjust Txpower only if temperature variance is greater than threshold.
+ *
+ * Both are lower than older versions' 9 degrees */
+#define IWL_TEMPERATURE_LIMIT_TIMER   6
+
+/**
+ * iwl3945_is_temp_calib_needed - determines if new calibration is needed
+ *
+ * records new temperature in tx_mgr->temperature.
+ * replaces tx_mgr->last_temperature *only* if calib needed
+ *    (assumes caller will actually do the calibration!). */
+static int iwl3945_is_temp_calib_needed(struct iwl_priv *priv)
+{
+	int temp_diff;
+
+	priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
+	temp_diff = priv->temperature - priv->last_temperature;
+
+	/* get absolute value */
+	if (temp_diff < 0) {
+		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff);
+		temp_diff = -temp_diff;
+	} else if (temp_diff == 0)
+		IWL_DEBUG_POWER(priv, "Same temp,\n");
+	else
+		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff);
+
+	/* if we don't need calibration, *don't* update last_temperature */
+	if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) {
+		IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n");
+		return 0;
+	}
+
+	IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n");
+
+	/* assume that caller will actually do calib ...
+	 *   update the "last temperature" value */
+	priv->last_temperature = priv->temperature;
+	return 1;
+}
+
+#define IWL_MAX_GAIN_ENTRIES 78
+#define IWL_CCK_FROM_OFDM_POWER_DIFF  -5
+#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10)
+
+/* radio and DSP power table, each step is 1/2 dB.
+ * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
+static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
+	{
+	 {251, 127},		/* 2.4 GHz, highest power */
+	 {251, 127},
+	 {251, 127},
+	 {251, 127},
+	 {251, 125},
+	 {251, 110},
+	 {251, 105},
+	 {251, 98},
+	 {187, 125},
+	 {187, 115},
+	 {187, 108},
+	 {187, 99},
+	 {243, 119},
+	 {243, 111},
+	 {243, 105},
+	 {243, 97},
+	 {243, 92},
+	 {211, 106},
+	 {211, 100},
+	 {179, 120},
+	 {179, 113},
+	 {179, 107},
+	 {147, 125},
+	 {147, 119},
+	 {147, 112},
+	 {147, 106},
+	 {147, 101},
+	 {147, 97},
+	 {147, 91},
+	 {115, 107},
+	 {235, 121},
+	 {235, 115},
+	 {235, 109},
+	 {203, 127},
+	 {203, 121},
+	 {203, 115},
+	 {203, 108},
+	 {203, 102},
+	 {203, 96},
+	 {203, 92},
+	 {171, 110},
+	 {171, 104},
+	 {171, 98},
+	 {139, 116},
+	 {227, 125},
+	 {227, 119},
+	 {227, 113},
+	 {227, 107},
+	 {227, 101},
+	 {227, 96},
+	 {195, 113},
+	 {195, 106},
+	 {195, 102},
+	 {195, 95},
+	 {163, 113},
+	 {163, 106},
+	 {163, 102},
+	 {163, 95},
+	 {131, 113},
+	 {131, 106},
+	 {131, 102},
+	 {131, 95},
+	 {99, 113},
+	 {99, 106},
+	 {99, 102},
+	 {99, 95},
+	 {67, 113},
+	 {67, 106},
+	 {67, 102},
+	 {67, 95},
+	 {35, 113},
+	 {35, 106},
+	 {35, 102},
+	 {35, 95},
+	 {3, 113},
+	 {3, 106},
+	 {3, 102},
+	 {3, 95} },		/* 2.4 GHz, lowest power */
+	{
+	 {251, 127},		/* 5.x GHz, highest power */
+	 {251, 120},
+	 {251, 114},
+	 {219, 119},
+	 {219, 101},
+	 {187, 113},
+	 {187, 102},
+	 {155, 114},
+	 {155, 103},
+	 {123, 117},
+	 {123, 107},
+	 {123, 99},
+	 {123, 92},
+	 {91, 108},
+	 {59, 125},
+	 {59, 118},
+	 {59, 109},
+	 {59, 102},
+	 {59, 96},
+	 {59, 90},
+	 {27, 104},
+	 {27, 98},
+	 {27, 92},
+	 {115, 118},
+	 {115, 111},
+	 {115, 104},
+	 {83, 126},
+	 {83, 121},
+	 {83, 113},
+	 {83, 105},
+	 {83, 99},
+	 {51, 118},
+	 {51, 111},
+	 {51, 104},
+	 {51, 98},
+	 {19, 116},
+	 {19, 109},
+	 {19, 102},
+	 {19, 98},
+	 {19, 93},
+	 {171, 113},
+	 {171, 107},
+	 {171, 99},
+	 {139, 120},
+	 {139, 113},
+	 {139, 107},
+	 {139, 99},
+	 {107, 120},
+	 {107, 113},
+	 {107, 107},
+	 {107, 99},
+	 {75, 120},
+	 {75, 113},
+	 {75, 107},
+	 {75, 99},
+	 {43, 120},
+	 {43, 113},
+	 {43, 107},
+	 {43, 99},
+	 {11, 120},
+	 {11, 113},
+	 {11, 107},
+	 {11, 99},
+	 {131, 107},
+	 {131, 99},
+	 {99, 120},
+	 {99, 113},
+	 {99, 107},
+	 {99, 99},
+	 {67, 120},
+	 {67, 113},
+	 {67, 107},
+	 {67, 99},
+	 {35, 120},
+	 {35, 113},
+	 {35, 107},
+	 {35, 99},
+	 {3, 120} }		/* 5.x GHz, lowest power */
+};
+
+static inline u8 iwl3945_hw_reg_fix_power_index(int index)
+{
+	if (index < 0)
+		return 0;
+	if (index >= IWL_MAX_GAIN_ENTRIES)
+		return IWL_MAX_GAIN_ENTRIES - 1;
+	return (u8) index;
+}
+
+/* Kick off thermal recalibration check every 60 seconds */
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
+ *
+ * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
+ * or 6 Mbit (OFDM) rates.
+ */
+static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
+			       s32 rate_index, const s8 *clip_pwrs,
+			       struct iwl_channel_info *ch_info,
+			       int band_index)
+{
+	struct iwl3945_scan_power_info *scan_power_info;
+	s8 power;
+	u8 power_index;
+
+	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index];
+
+	/* use this channel group's 6Mbit clipping/saturation pwr,
+	 *   but cap at regulatory scan power restriction (set during init
+	 *   based on eeprom channel data) for this channel.  */
+	power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
+
+	power = min(power, priv->tx_power_user_lmt);
+	scan_power_info->requested_power = power;
+
+	/* find difference between new scan *power* and current "normal"
+	 *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
+	 *   current "normal" temperature-compensated Tx power *index* for
+	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
+	 *   *index*. */
+	power_index = ch_info->power_info[rate_index].power_table_index
+	    - (power - ch_info->power_info
+	       [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
+
+	/* store reference index that we use when adjusting *all* scan
+	 *   powers.  So we can accommodate user (all channel) or spectrum
+	 *   management (single channel) power changes "between" temperature
+	 *   feedback compensation procedures.
+	 * don't force fit this reference index into gain table; it may be a
+	 *   negative number.  This will help avoid errors when we're at
+	 *   the lower bounds (highest gains, for warmest temperatures)
+	 *   of the table. */
+
+	/* don't exceed table bounds for "real" setting */
+	power_index = iwl3945_hw_reg_fix_power_index(power_index);
+
+	scan_power_info->power_table_index = power_index;
+	scan_power_info->tpc.tx_gain =
+	    power_gain_table[band_index][power_index].tx_gain;
+	scan_power_info->tpc.dsp_atten =
+	    power_gain_table[band_index][power_index].dsp_atten;
+}
+
+/**
+ * iwl3945_send_tx_power - fill in Tx Power command with gain settings
+ *
+ * Configures power settings for all rates for the current channel,
+ * using values from channel info struct, and send to NIC
+ */
+static int iwl3945_send_tx_power(struct iwl_priv *priv)
+{
+	int rate_idx, i;
+	const struct iwl_channel_info *ch_info = NULL;
+	struct iwl3945_txpowertable_cmd txpower = {
+		.channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
+	};
+	u16 chan;
+
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
+	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
+
+	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band, chan);
+	if (!ch_info) {
+		IWL_ERR(priv,
+			"Failed to get channel info for channel %d [%d]\n",
+			chan, priv->band);
+		return -EINVAL;
+	}
+
+	if (!iwl_legacy_is_channel_valid(ch_info)) {
+		IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on "
+				"non-Tx channel.\n");
+		return 0;
+	}
+
+	/* fill cmd with power settings for all rates for current channel */
+	/* Fill OFDM rate */
+	for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
+	     rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) {
+
+		txpower.power[i].tpc = ch_info->power_info[i].tpc;
+		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
+
+		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+				le16_to_cpu(txpower.channel),
+				txpower.band,
+				txpower.power[i].tpc.tx_gain,
+				txpower.power[i].tpc.dsp_atten,
+				txpower.power[i].rate);
+	}
+	/* Fill CCK rates */
+	for (rate_idx = IWL_FIRST_CCK_RATE;
+	     rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
+		txpower.power[i].tpc = ch_info->power_info[i].tpc;
+		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
+
+		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
+				le16_to_cpu(txpower.channel),
+				txpower.band,
+				txpower.power[i].tpc.tx_gain,
+				txpower.power[i].tpc.dsp_atten,
+				txpower.power[i].rate);
+	}
+
+	return iwl_legacy_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
+				sizeof(struct iwl3945_txpowertable_cmd),
+				&txpower);
+
+}
+
+/**
+ * iwl3945_hw_reg_set_new_power - Configures power tables at new levels
+ * @ch_info: Channel to update.  Uses power_info.requested_power.
+ *
+ * Replace requested_power and base_power_index ch_info fields for
+ * one channel.
+ *
+ * Called if user or spectrum management changes power preferences.
+ * Takes into account h/w and modulation limitations (clip power).
+ *
+ * This does *not* send anything to NIC, just sets up ch_info for one channel.
+ *
+ * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
+ *	 properly fill out the scan powers, and actual h/w gain settings,
+ *	 and send changes to NIC
+ */
+static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
+			     struct iwl_channel_info *ch_info)
+{
+	struct iwl3945_channel_power_info *power_info;
+	int power_changed = 0;
+	int i;
+	const s8 *clip_pwrs;
+	int power;
+
+	/* Get this chnlgrp's rate-to-max/clip-powers table */
+	clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
+
+	/* Get this channel's rate-to-current-power settings table */
+	power_info = ch_info->power_info;
+
+	/* update OFDM Txpower settings */
+	for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
+	     i++, ++power_info) {
+		int delta_idx;
+
+		/* limit new power to be no more than h/w capability */
+		power = min(ch_info->curr_txpow, clip_pwrs[i]);
+		if (power == power_info->requested_power)
+			continue;
+
+		/* find difference between old and new requested powers,
+		 *    update base (non-temp-compensated) power index */
+		delta_idx = (power - power_info->requested_power) * 2;
+		power_info->base_power_index -= delta_idx;
+
+		/* save new requested power value */
+		power_info->requested_power = power;
+
+		power_changed = 1;
+	}
+
+	/* update CCK Txpower settings, based on OFDM 12M setting ...
+	 *    ... all CCK power settings for a given channel are the *same*. */
+	if (power_changed) {
+		power =
+		    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
+		    requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
+
+		/* do all CCK rates' iwl3945_channel_power_info structures */
+		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
+			power_info->requested_power = power;
+			power_info->base_power_index =
+			    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
+			    base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
+			++power_info;
+		}
+	}
+
+	return 0;
+}
+
+/**
+ * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
+ *
+ * NOTE: Returned power limit may be less (but not more) than requested,
+ *	 based strictly on regulatory (eeprom and spectrum mgt) limitations
+ *	 (no consideration for h/w clipping limitations).
+ */
+static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
+{
+	s8 max_power;
+
+#if 0
+	/* if we're using TGd limits, use lower of TGd or EEPROM */
+	if (ch_info->tgd_data.max_power != 0)
+		max_power = min(ch_info->tgd_data.max_power,
+				ch_info->eeprom.max_power_avg);
+
+	/* else just use EEPROM limits */
+	else
+#endif
+		max_power = ch_info->eeprom.max_power_avg;
+
+	return min(max_power, ch_info->max_power_avg);
+}
+
+/**
+ * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature
+ *
+ * Compensate txpower settings of *all* channels for temperature.
+ * This only accounts for the difference between current temperature
+ *   and the factory calibration temperatures, and bases the new settings
+ *   on the channel's base_power_index.
+ *
+ * If RxOn is "associated", this sends the new Txpower to NIC!
+ */
+static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
+{
+	struct iwl_channel_info *ch_info = NULL;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	int delta_index;
+	const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
+	u8 a_band;
+	u8 rate_index;
+	u8 scan_tbl_index;
+	u8 i;
+	int ref_temp;
+	int temperature = priv->temperature;
+
+	if (priv->disable_tx_power_cal ||
+	    test_bit(STATUS_SCANNING, &priv->status)) {
+		/* do not perform tx power calibration */
+		return 0;
+	}
+	/* set up new Tx power info for each and every channel, 2.4 and 5.x */
+	for (i = 0; i < priv->channel_count; i++) {
+		ch_info = &priv->channel_info[i];
+		a_band = iwl_legacy_is_channel_a_band(ch_info);
+
+		/* Get this chnlgrp's factory calibration temperature */
+		ref_temp = (s16)eeprom->groups[ch_info->group_index].
+		    temperature;
+
+		/* get power index adjustment based on current and factory
+		 * temps */
+		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
+							      ref_temp);
+
+		/* set tx power value for all rates, OFDM and CCK */
+		for (rate_index = 0; rate_index < IWL_RATE_COUNT_3945;
+		     rate_index++) {
+			int power_idx =
+			    ch_info->power_info[rate_index].base_power_index;
+
+			/* temperature compensate */
+			power_idx += delta_index;
+
+			/* stay within table range */
+			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
+			ch_info->power_info[rate_index].
+			    power_table_index = (u8) power_idx;
+			ch_info->power_info[rate_index].tpc =
+			    power_gain_table[a_band][power_idx];
+		}
+
+		/* Get this chnlgrp's rate-to-max/clip-powers table */
+		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
+
+		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
+		for (scan_tbl_index = 0;
+		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
+			s32 actual_index = (scan_tbl_index == 0) ?
+			    IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
+			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
+					   actual_index, clip_pwrs,
+					   ch_info, a_band);
+		}
+	}
+
+	/* send Txpower command for current channel to ucode */
+	return priv->cfg->ops->lib->send_tx_power(priv);
+}
+
+int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
+{
+	struct iwl_channel_info *ch_info;
+	s8 max_power;
+	u8 a_band;
+	u8 i;
+
+	if (priv->tx_power_user_lmt == power) {
+		IWL_DEBUG_POWER(priv, "Requested Tx power same as current "
+				"limit: %ddBm.\n", power);
+		return 0;
+	}
+
+	IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power);
+	priv->tx_power_user_lmt = power;
+
+	/* set up new Tx powers for each and every channel, 2.4 and 5.x */
+
+	for (i = 0; i < priv->channel_count; i++) {
+		ch_info = &priv->channel_info[i];
+		a_band = iwl_legacy_is_channel_a_band(ch_info);
+
+		/* find minimum power of all user and regulatory constraints
+		 *    (does not consider h/w clipping limitations) */
+		max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info);
+		max_power = min(power, max_power);
+		if (max_power != ch_info->curr_txpow) {
+			ch_info->curr_txpow = max_power;
+
+			/* this considers the h/w clipping limitations */
+			iwl3945_hw_reg_set_new_power(priv, ch_info);
+		}
+	}
+
+	/* update txpower settings for all channels,
+	 *   send to NIC if associated. */
+	iwl3945_is_temp_calib_needed(priv);
+	iwl3945_hw_reg_comp_txpower_temp(priv);
+
+	return 0;
+}
+
+static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
+{
+	int rc = 0;
+	struct iwl_rx_packet *pkt;
+	struct iwl3945_rxon_assoc_cmd rxon_assoc;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_RXON_ASSOC,
+		.len = sizeof(rxon_assoc),
+		.flags = CMD_WANT_SKB,
+		.data = &rxon_assoc,
+	};
+	const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
+	const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
+
+	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 = ctx->staging.flags;
+	rxon_assoc.filter_flags = ctx->staging.filter_flags;
+	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
+	rxon_assoc.reserved = 0;
+
+	rc = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (rc)
+		return rc;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
+		rc = -EIO;
+	}
+
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	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.
+ */
+int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
+	struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
+	int rc = 0;
+	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EINVAL;
+
+	if (!iwl_legacy_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_legacy_check_rxon_cmd(priv, ctx);
+	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_legacy_full_rxon_required(priv,
+			&priv->contexts[IWL_RXON_CTX_BSS])) {
+		rc = iwl_legacy_send_rxon_assoc(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+		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_legacy_is_associated(priv, IWL_RXON_CTX_BSS) && 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_legacy_send_cmd_pdu(priv, REPLY_RXON,
+				      sizeof(struct iwl3945_rxon_cmd),
+				      &priv->contexts[IWL_RXON_CTX_BSS].active);
+
+		/* 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_legacy_clear_ucode_stations(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+		iwl_legacy_restore_stations(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+	}
+
+	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_legacy_set_rxon_hwcrypto(priv, ctx, !iwl3945_mod_params.sw_crypto);
+
+	/* Apply the new configuration */
+	rc = iwl_legacy_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));
+
+	if (!new_assoc) {
+		iwl_legacy_clear_ucode_stations(priv,
+					 &priv->contexts[IWL_RXON_CTX_BSS]);
+		iwl_legacy_restore_stations(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
+	}
+
+	/* 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 = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
+	if (rc) {
+		IWL_ERR(priv, "Error setting Tx power (%d).\n", rc);
+		return rc;
+	}
+
+	/* 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;
+}
+
+/**
+ * iwl3945_reg_txpower_periodic -  called when time to check our temperature.
+ *
+ * -- reset periodic timer
+ * -- see if temp has changed enough to warrant re-calibration ... if so:
+ *     -- correct coeffs for temp (can reset temp timer)
+ *     -- save this temp as "last",
+ *     -- send new set of gain settings to NIC
+ * NOTE:  This should continue working, even when we're not associated,
+ *   so we can keep our internal table of scan powers current. */
+void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
+{
+	/* This will kick in the "brute force"
+	 * iwl3945_hw_reg_comp_txpower_temp() below */
+	if (!iwl3945_is_temp_calib_needed(priv))
+		goto reschedule;
+
+	/* Set up a new set of temp-adjusted TxPowers, send to NIC.
+	 * This is based *only* on current temperature,
+	 * ignoring any previous power measurements */
+	iwl3945_hw_reg_comp_txpower_temp(priv);
+
+ reschedule:
+	queue_delayed_work(priv->workqueue,
+			   &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
+}
+
+static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+					     _3945.thermal_periodic.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl3945_reg_txpower_periodic(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/**
+ * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
+ * 				   for the channel.
+ *
+ * This function is used when initializing channel-info structs.
+ *
+ * NOTE: These channel groups do *NOT* match the bands above!
+ *	 These channel groups are based on factory-tested channels;
+ *	 on A-band, EEPROM's "group frequency" entries represent the top
+ *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0.
+ */
+static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
+				       const struct iwl_channel_info *ch_info)
+{
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
+	u8 group;
+	u16 group_index = 0;	/* based on factory calib frequencies */
+	u8 grp_channel;
+
+	/* Find the group index for the channel ... don't use index 1(?) */
+	if (iwl_legacy_is_channel_a_band(ch_info)) {
+		for (group = 1; group < 5; group++) {
+			grp_channel = ch_grp[group].group_channel;
+			if (ch_info->channel <= grp_channel) {
+				group_index = group;
+				break;
+			}
+		}
+		/* group 4 has a few channels *above* its factory cal freq */
+		if (group == 5)
+			group_index = 4;
+	} else
+		group_index = 0;	/* 2.4 GHz, group 0 */
+
+	IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel,
+			group_index);
+	return group_index;
+}
+
+/**
+ * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index
+ *
+ * Interpolate to get nominal (i.e. at factory calibration temperature) index
+ *   into radio/DSP gain settings table for requested power.
+ */
+static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv,
+				       s8 requested_power,
+				       s32 setting_index, s32 *new_index)
+{
+	const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	s32 index0, index1;
+	s32 power = 2 * requested_power;
+	s32 i;
+	const struct iwl3945_eeprom_txpower_sample *samples;
+	s32 gains0, gains1;
+	s32 res;
+	s32 denominator;
+
+	chnl_grp = &eeprom->groups[setting_index];
+	samples = chnl_grp->samples;
+	for (i = 0; i < 5; i++) {
+		if (power == samples[i].power) {
+			*new_index = samples[i].gain_index;
+			return 0;
+		}
+	}
+
+	if (power > samples[1].power) {
+		index0 = 0;
+		index1 = 1;
+	} else if (power > samples[2].power) {
+		index0 = 1;
+		index1 = 2;
+	} else if (power > samples[3].power) {
+		index0 = 2;
+		index1 = 3;
+	} else {
+		index0 = 3;
+		index1 = 4;
+	}
+
+	denominator = (s32) samples[index1].power - (s32) samples[index0].power;
+	if (denominator == 0)
+		return -EINVAL;
+	gains0 = (s32) samples[index0].gain_index * (1 << 19);
+	gains1 = (s32) samples[index1].gain_index * (1 << 19);
+	res = gains0 + (gains1 - gains0) *
+	    ((s32) power - (s32) samples[index0].power) / denominator +
+	    (1 << 18);
+	*new_index = res >> 19;
+	return 0;
+}
+
+static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
+{
+	u32 i;
+	s32 rate_index;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	const struct iwl3945_eeprom_txpower_group *group;
+
+	IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n");
+
+	for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {
+		s8 *clip_pwrs;	/* table of power levels for each rate */
+		s8 satur_pwr;	/* saturation power for each chnl group */
+		group = &eeprom->groups[i];
+
+		/* sanity check on factory saturation power value */
+		if (group->saturation_power < 40) {
+			IWL_WARN(priv, "Error: saturation power is %d, "
+				    "less than minimum expected 40\n",
+				    group->saturation_power);
+			return;
+		}
+
+		/*
+		 * Derive requested power levels for each rate, based on
+		 *   hardware capabilities (saturation power for band).
+		 * Basic value is 3dB down from saturation, with further
+		 *   power reductions for highest 3 data rates.  These
+		 *   backoffs provide headroom for high rate modulation
+		 *   power peaks, without too much distortion (clipping).
+		 */
+		/* we'll fill in this array with h/w max power levels */
+		clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
+
+		/* divide factory saturation power by 2 to find -3dB level */
+		satur_pwr = (s8) (group->saturation_power >> 1);
+
+		/* fill in channel group's nominal powers for each rate */
+		for (rate_index = 0;
+		     rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) {
+			switch (rate_index) {
+			case IWL_RATE_36M_INDEX_TABLE:
+				if (i == 0)	/* B/G */
+					*clip_pwrs = satur_pwr;
+				else	/* A */
+					*clip_pwrs = satur_pwr - 5;
+				break;
+			case IWL_RATE_48M_INDEX_TABLE:
+				if (i == 0)
+					*clip_pwrs = satur_pwr - 7;
+				else
+					*clip_pwrs = satur_pwr - 10;
+				break;
+			case IWL_RATE_54M_INDEX_TABLE:
+				if (i == 0)
+					*clip_pwrs = satur_pwr - 9;
+				else
+					*clip_pwrs = satur_pwr - 12;
+				break;
+			default:
+				*clip_pwrs = satur_pwr;
+				break;
+			}
+		}
+	}
+}
+
+/**
+ * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
+ *
+ * Second pass (during init) to set up priv->channel_info
+ *
+ * Set up Tx-power settings in our channel info database for each VALID
+ * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
+ * and current temperature.
+ *
+ * Since this is based on current temperature (at init time), these values may
+ * not be valid for very long, but it gives us a starting/default point,
+ * and allows us to active (i.e. using Tx) scan.
+ *
+ * This does *not* write values to NIC, just sets up our internal table.
+ */
+int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
+{
+	struct iwl_channel_info *ch_info = NULL;
+	struct iwl3945_channel_power_info *pwr_info;
+	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
+	int delta_index;
+	u8 rate_index;
+	u8 scan_tbl_index;
+	const s8 *clip_pwrs;	/* array of power levels for each rate */
+	u8 gain, dsp_atten;
+	s8 power;
+	u8 pwr_index, base_pwr_index, a_band;
+	u8 i;
+	int temperature;
+
+	/* save temperature reference,
+	 *   so we can determine next time to calibrate */
+	temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
+	priv->last_temperature = temperature;
+
+	iwl3945_hw_reg_init_channel_groups(priv);
+
+	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
+	for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
+	     i++, ch_info++) {
+		a_band = iwl_legacy_is_channel_a_band(ch_info);
+		if (!iwl_legacy_is_channel_valid(ch_info))
+			continue;
+
+		/* find this channel's channel group (*not* "band") index */
+		ch_info->group_index =
+			iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
+
+		/* Get this chnlgrp's rate->max/clip-powers table */
+		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
+
+		/* calculate power index *adjustment* value according to
+		 *  diff between current temperature and factory temperature */
+		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
+				eeprom->groups[ch_info->group_index].
+				temperature);
+
+		IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n",
+				ch_info->channel, delta_index, temperature +
+				IWL_TEMP_CONVERT);
+
+		/* set tx power value for all OFDM rates */
+		for (rate_index = 0; rate_index < IWL_OFDM_RATES;
+		     rate_index++) {
+			s32 uninitialized_var(power_idx);
+			int rc;
+
+			/* use channel group's clip-power table,
+			 *   but don't exceed channel's max power */
+			s8 pwr = min(ch_info->max_power_avg,
+				     clip_pwrs[rate_index]);
+
+			pwr_info = &ch_info->power_info[rate_index];
+
+			/* get base (i.e. at factory-measured temperature)
+			 *    power table index for this rate's power */
+			rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr,
+							 ch_info->group_index,
+							 &power_idx);
+			if (rc) {
+				IWL_ERR(priv, "Invalid power index\n");
+				return rc;
+			}
+			pwr_info->base_power_index = (u8) power_idx;
+
+			/* temperature compensate */
+			power_idx += delta_index;
+
+			/* stay within range of gain table */
+			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
+
+			/* fill 1 OFDM rate's iwl3945_channel_power_info struct */
+			pwr_info->requested_power = pwr;
+			pwr_info->power_table_index = (u8) power_idx;
+			pwr_info->tpc.tx_gain =
+			    power_gain_table[a_band][power_idx].tx_gain;
+			pwr_info->tpc.dsp_atten =
+			    power_gain_table[a_band][power_idx].dsp_atten;
+		}
+
+		/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
+		pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
+		power = pwr_info->requested_power +
+			IWL_CCK_FROM_OFDM_POWER_DIFF;
+		pwr_index = pwr_info->power_table_index +
+			IWL_CCK_FROM_OFDM_INDEX_DIFF;
+		base_pwr_index = pwr_info->base_power_index +
+			IWL_CCK_FROM_OFDM_INDEX_DIFF;
+
+		/* stay within table range */
+		pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index);
+		gain = power_gain_table[a_band][pwr_index].tx_gain;
+		dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;
+
+		/* fill each CCK rate's iwl3945_channel_power_info structure
+		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
+		 * NOTE:  CCK rates start at end of OFDM rates! */
+		for (rate_index = 0;
+		     rate_index < IWL_CCK_RATES; rate_index++) {
+			pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
+			pwr_info->requested_power = power;
+			pwr_info->power_table_index = pwr_index;
+			pwr_info->base_power_index = base_pwr_index;
+			pwr_info->tpc.tx_gain = gain;
+			pwr_info->tpc.dsp_atten = dsp_atten;
+		}
+
+		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
+		for (scan_tbl_index = 0;
+		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
+			s32 actual_index = (scan_tbl_index == 0) ?
+				IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
+			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
+				actual_index, clip_pwrs, ch_info, a_band);
+		}
+	}
+
+	return 0;
+}
+
+int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
+{
+	int rc;
+
+	iwl_legacy_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
+	rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
+			FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
+	if (rc < 0)
+		IWL_ERR(priv, "Can't stop Rx DMA.\n");
+
+	return 0;
+}
+
+int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	int txq_id = txq->q.id;
+
+	struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
+
+	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
+
+	iwl_legacy_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
+	iwl_legacy_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
+
+	iwl_legacy_write_direct32(priv, FH39_TCSR_CONFIG(txq_id),
+		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
+		FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
+		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);
+
+	/* fake read to flush all prev. writes */
+	iwl_read32(priv, FH39_TSSR_CBB_BASE);
+
+	return 0;
+}
+
+/*
+ * HCMD utils
+ */
+static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
+{
+	switch (cmd_id) {
+	case REPLY_RXON:
+		return sizeof(struct iwl3945_rxon_cmd);
+	case POWER_TABLE_CMD:
+		return sizeof(struct iwl3945_powertable_cmd);
+	default:
+		return len;
+	}
+}
+
+
+static u16 iwl3945_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
+								u8 *data)
+{
+	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);
+}
+
+static int iwl3945_add_bssid_station(struct iwl_priv *priv,
+				     const u8 *addr, u8 *sta_id_r)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	int ret;
+	u8 sta_id;
+	unsigned long flags;
+
+	if (sta_id_r)
+		*sta_id_r = IWL_INVALID_STATION;
+
+	ret = iwl_legacy_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM\n", addr);
+		return ret;
+	}
+
+	if (sta_id_r)
+		*sta_id_r = sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].used |= IWL_STA_LOCAL;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
+				       struct ieee80211_vif *vif, bool add)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	int ret;
+
+	if (add) {
+		ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
+						&vif_priv->ibss_bssid_sta_id);
+		if (ret)
+			return ret;
+
+		iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
+				 (priv->band == IEEE80211_BAND_5GHZ) ?
+				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
+		iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
+
+		return 0;
+	}
+
+	return iwl_legacy_remove_station(priv, vif_priv->ibss_bssid_sta_id,
+				  vif->bss_conf.bssid);
+}
+
+/**
+ * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
+ */
+int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
+{
+	int rc, i, index, prev_index;
+	struct iwl3945_rate_scaling_cmd rate_cmd = {
+		.reserved = {0, 0, 0},
+	};
+	struct iwl3945_rate_scaling_info *table = rate_cmd.table;
+
+	for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) {
+		index = iwl3945_rates[i].table_rs_index;
+
+		table[index].rate_n_flags =
+			iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
+		table[index].try_cnt = priv->retry_rate;
+		prev_index = iwl3945_get_prev_ieee_rate(i);
+		table[index].next_rate_index =
+				iwl3945_rates[prev_index].table_rs_index;
+	}
+
+	switch (priv->band) {
+	case IEEE80211_BAND_5GHZ:
+		IWL_DEBUG_RATE(priv, "Select A mode rate scale\n");
+		/* If one of the following CCK rates is used,
+		 * have it fall back to the 6M OFDM rate */
+		for (i = IWL_RATE_1M_INDEX_TABLE;
+			i <= IWL_RATE_11M_INDEX_TABLE; i++)
+			table[i].next_rate_index =
+			  iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+
+		/* Don't fall back to CCK rates */
+		table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
+						IWL_RATE_9M_INDEX_TABLE;
+
+		/* Don't drop out of OFDM rates */
+		table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
+		    iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
+		break;
+
+	case IEEE80211_BAND_2GHZ:
+		IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n");
+		/* If an OFDM rate is used, have it fall back to the
+		 * 1M CCK rates */
+
+		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
+		    iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS)) {
+
+			index = IWL_FIRST_CCK_RATE;
+			for (i = IWL_RATE_6M_INDEX_TABLE;
+			     i <= IWL_RATE_54M_INDEX_TABLE; i++)
+				table[i].next_rate_index =
+					iwl3945_rates[index].table_rs_index;
+
+			index = IWL_RATE_11M_INDEX_TABLE;
+			/* CCK shouldn't fall back to OFDM... */
+			table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
+		}
+		break;
+
+	default:
+		WARN_ON(1);
+		break;
+	}
+
+	/* Update the rate scaling for control frame Tx */
+	rate_cmd.table_id = 0;
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+			      &rate_cmd);
+	if (rc)
+		return rc;
+
+	/* Update the rate scaling for data frame Tx */
+	rate_cmd.table_id = 1;
+	return iwl_legacy_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
+				&rate_cmd);
+}
+
+/* Called when initializing driver */
+int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
+{
+	memset((void *)&priv->hw_params, 0,
+	       sizeof(struct iwl_hw_params));
+
+	priv->_3945.shared_virt =
+		dma_alloc_coherent(&priv->pci_dev->dev,
+				   sizeof(struct iwl3945_shared),
+				   &priv->_3945.shared_phys, GFP_KERNEL);
+	if (!priv->_3945.shared_virt) {
+		IWL_ERR(priv, "failed to allocate pci memory\n");
+		return -ENOMEM;
+	}
+
+	/* Assign number of Usable TX queues */
+	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
+
+	priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
+	priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
+	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+	priv->hw_params.max_stations = IWL3945_STATION_COUNT;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
+
+	priv->sta_key_max_num = STA_KEY_MAX_NUM;
+
+	priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
+	priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
+	priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;
+
+	return 0;
+}
+
+unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
+			  struct iwl3945_frame *frame, u8 rate)
+{
+	struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
+	unsigned int frame_size;
+
+	tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
+	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+	tx_beacon_cmd->tx.sta_id =
+		priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
+	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	frame_size = iwl3945_fill_beacon_frame(priv,
+				tx_beacon_cmd->frame,
+				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+
+	BUG_ON(frame_size > MAX_MPDU_SIZE);
+	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
+
+	tx_beacon_cmd->tx.rate = rate;
+	tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
+				      TX_CMD_FLG_TSF_MSK);
+
+	/* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
+	tx_beacon_cmd->tx.supp_rates[0] =
+		(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+
+	tx_beacon_cmd->tx.supp_rates[1] =
+		(IWL_CCK_BASIC_RATES_MASK & 0xF);
+
+	return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
+}
+
+void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
+{
+	priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
+	priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
+}
+
+void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
+{
+	INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
+			  iwl3945_bg_reg_txpower_periodic);
+}
+
+void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
+{
+	cancel_delayed_work(&priv->_3945.thermal_periodic);
+}
+
+/* check contents of special bootstrap uCode SRAM */
+static int iwl3945_verify_bsm(struct iwl_priv *priv)
+ {
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	u32 reg;
+	u32 val;
+
+	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
+
+	/* verify BSM SRAM contents */
+	val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
+	for (reg = BSM_SRAM_LOWER_BOUND;
+	     reg < BSM_SRAM_LOWER_BOUND + len;
+	     reg += sizeof(u32), image++) {
+		val = iwl_legacy_read_prph(priv, reg);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "BSM uCode verification failed at "
+				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+				  BSM_SRAM_LOWER_BOUND,
+				  reg - BSM_SRAM_LOWER_BOUND, len,
+				  val, le32_to_cpu(*image));
+			return -EIO;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
+
+	return 0;
+}
+
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+ ******************************************************************************/
+
+/*
+ * Clear the OWNER_MSK, to establish driver (instead of uCode running on
+ * embedded controller) as EEPROM reader; each read is a series of pulses
+ * to/from the EEPROM chip, not a single event, so even reads could conflict
+ * if they weren't arbitrated by some ownership mechanism.  Here, the driver
+ * simply claims ownership, which should be safe when this function is called
+ * (i.e. before loading uCode!).
+ */
+static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+	_iwl_legacy_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
+	return 0;
+}
+
+
+static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+	return;
+}
+
+ /**
+  * iwl3945_load_bsm - Load bootstrap instructions
+  *
+  * BSM operation:
+  *
+  * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+  * in special SRAM that does not power down during RFKILL.  When powering back
+  * up after power-saving sleeps (or during initial uCode load), the BSM loads
+  * the bootstrap program into the on-board processor, and starts it.
+  *
+  * The bootstrap program loads (via DMA) instructions and data for a new
+  * program from host DRAM locations indicated by the host driver in the
+  * BSM_DRAM_* registers.  Once the new program is loaded, it starts
+  * automatically.
+  *
+  * When initializing the NIC, the host driver points the BSM to the
+  * "initialize" uCode image.  This uCode sets up some internal data, then
+  * notifies host via "initialize alive" that it is complete.
+  *
+  * The host then replaces the BSM_DRAM_* pointer values to point to the
+  * normal runtime uCode instructions and a backup uCode data cache buffer
+  * (filled initially with starting data values for the on-board processor),
+  * then triggers the "initialize" uCode to load and launch the runtime uCode,
+  * which begins normal operation.
+  *
+  * When doing a power-save shutdown, runtime uCode saves data SRAM into
+  * the backup data cache in DRAM before SRAM is powered down.
+  *
+  * When powering back up, the BSM loads the bootstrap program.  This reloads
+  * the runtime uCode instructions and the backup data cache into SRAM,
+  * and re-launches the runtime uCode from where it left off.
+  */
+static int iwl3945_load_bsm(struct iwl_priv *priv)
+{
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+	u32 inst_len;
+	u32 data_len;
+	int rc;
+	int i;
+	u32 done;
+	u32 reg_offset;
+
+	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
+
+	/* make sure bootstrap program is no larger than BSM's SRAM size */
+	if (len > IWL39_MAX_BSM_SIZE)
+		return -EINVAL;
+
+	/* Tell bootstrap uCode where to find the "Initialize" uCode
+	*   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
+	* NOTE:  iwl3945_initialize_alive_start() will replace these values,
+	*        after the "initialize" uCode has run, to point to
+	*        runtime/protocol instructions and backup data cache. */
+	pinst = priv->ucode_init.p_addr;
+	pdata = priv->ucode_init_data.p_addr;
+	inst_len = priv->ucode_init.len;
+	data_len = priv->ucode_init_data.len;
+
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+
+	/* Fill BSM memory with bootstrap instructions */
+	for (reg_offset = BSM_SRAM_LOWER_BOUND;
+	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
+	     reg_offset += sizeof(u32), image++)
+		_iwl_legacy_write_prph(priv, reg_offset,
+					  le32_to_cpu(*image));
+
+	rc = iwl3945_verify_bsm(priv);
+	if (rc)
+		return rc;
+
+	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+	iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+	iwl_legacy_write_prph(priv, BSM_WR_MEM_DST_REG,
+				 IWL39_RTC_INST_LOWER_BOUND);
+	iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+	/* Load bootstrap code into instruction SRAM now,
+	 *   to prepare to load "initialize" uCode */
+	iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG,
+		BSM_WR_CTRL_REG_BIT_START);
+
+	/* Wait for load of bootstrap uCode to finish */
+	for (i = 0; i < 100; i++) {
+		done = iwl_legacy_read_prph(priv, BSM_WR_CTRL_REG);
+		if (!(done & BSM_WR_CTRL_REG_BIT_START))
+			break;
+		udelay(10);
+	}
+	if (i < 100)
+		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
+	else {
+		IWL_ERR(priv, "BSM write did not complete!\n");
+		return -EIO;
+	}
+
+	/* Enable future boot loads whenever power management unit triggers it
+	 *   (e.g. when powering back up after power-save shutdown) */
+	iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG,
+		BSM_WR_CTRL_REG_BIT_START_EN);
+
+	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,
+	.txq_init = iwl3945_hw_tx_queue_init,
+	.load_ucode = iwl3945_load_bsm,
+	.dump_nic_event_log = iwl3945_dump_nic_event_log,
+	.dump_nic_error_log = iwl3945_dump_nic_error_log,
+	.apm_ops = {
+		.init = iwl3945_apm_init,
+		.config = iwl3945_nic_config,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REGULATORY_BAND_1_CHANNELS,
+			EEPROM_REGULATORY_BAND_2_CHANNELS,
+			EEPROM_REGULATORY_BAND_3_CHANNELS,
+			EEPROM_REGULATORY_BAND_4_CHANNELS,
+			EEPROM_REGULATORY_BAND_5_CHANNELS,
+			EEPROM_REGULATORY_BAND_NO_HT40,
+			EEPROM_REGULATORY_BAND_NO_HT40,
+		},
+		.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
+		.release_semaphore = iwl3945_eeprom_release_semaphore,
+	},
+	.send_tx_power	= iwl3945_send_tx_power,
+	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
+
+	.debugfs_ops = {
+		.rx_stats_read = iwl3945_ucode_rx_stats_read,
+		.tx_stats_read = iwl3945_ucode_tx_stats_read,
+		.general_stats_read = iwl3945_ucode_general_stats_read,
+	},
+};
+
+static const struct iwl_legacy_ops iwl3945_legacy_ops = {
+	.post_associate = iwl3945_post_associate,
+	.config_ap = iwl3945_config_ap,
+	.manage_ibss_station = iwl3945_manage_ibss_station,
+};
+
+static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
+	.get_hcmd_size = iwl3945_get_hcmd_size,
+	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
+	.request_scan = iwl3945_request_scan,
+	.post_scan = iwl3945_post_scan,
+};
+
+static const struct iwl_ops iwl3945_ops = {
+	.lib = &iwl3945_lib,
+	.hcmd = &iwl3945_hcmd,
+	.utils = &iwl3945_hcmd_utils,
+	.led = &iwl3945_led_ops,
+	.legacy = &iwl3945_legacy_ops,
+	.ieee80211_ops = &iwl3945_hw_ops,
+};
+
+static struct iwl_base_params iwl3945_base_params = {
+	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
+	.num_of_queues = IWL39_NUM_QUEUES,
+	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
+	.set_l0s = false,
+	.use_bsm = true,
+	.led_compensation = 64,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.max_event_log_size = 512,
+};
+
+static struct iwl_cfg iwl3945_bg_cfg = {
+	.name = "3945BG",
+	.fw_name_pre = IWL3945_FW_PRE,
+	.ucode_api_max = IWL3945_UCODE_API_MAX,
+	.ucode_api_min = IWL3945_UCODE_API_MIN,
+	.sku = IWL_SKU_G,
+	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+	.ops = &iwl3945_ops,
+	.mod_params = &iwl3945_mod_params,
+	.base_params = &iwl3945_base_params,
+	.led_mode = IWL_LED_BLINK,
+};
+
+static struct iwl_cfg iwl3945_abg_cfg = {
+	.name = "3945ABG",
+	.fw_name_pre = IWL3945_FW_PRE,
+	.ucode_api_max = IWL3945_UCODE_API_MAX,
+	.ucode_api_min = IWL3945_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G,
+	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
+	.ops = &iwl3945_ops,
+	.mod_params = &iwl3945_mod_params,
+	.base_params = &iwl3945_base_params,
+	.led_mode = IWL_LED_BLINK,
+};
+
+DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
+	{IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
+	{IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
+	{IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
+	{0}
+};
+
+MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,523 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "iwl-3945-debugfs.h"
+
+
+static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
+{
+	int p = 0;
+
+	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
+		       le32_to_cpu(priv->_3945.statistics.flag));
+	if (le32_to_cpu(priv->_3945.statistics.flag) &
+			UCODE_STATISTICS_CLEAR_MSK)
+		p += scnprintf(buf + p, bufsz - p,
+			       "\tStatistics have been cleared\n");
+	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
+		       (le32_to_cpu(priv->_3945.statistics.flag) &
+			UCODE_STATISTICS_FREQUENCY_MSK)
+			? "2.4 GHz" : "5.2 GHz");
+	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
+		       (le32_to_cpu(priv->_3945.statistics.flag) &
+			UCODE_STATISTICS_NARROW_BAND_MSK)
+			? "enabled" : "disabled");
+	return p;
+}
+
+ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
+				    char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
+		    sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
+	ssize_t ret;
+	struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm,
+					*max_ofdm;
+	struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+	struct iwl39_statistics_rx_non_phy *general, *accum_general;
+	struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	ofdm = &priv->_3945.statistics.rx.ofdm;
+	cck = &priv->_3945.statistics.rx.cck;
+	general = &priv->_3945.statistics.rx.general;
+	accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_3945.accum_statistics.rx.cck;
+	accum_general = &priv->_3945.accum_statistics.rx.general;
+	delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_3945.delta_statistics.rx.cck;
+	delta_general = &priv->_3945.delta_statistics.rx.general;
+	max_ofdm = &priv->_3945.max_delta.rx.ofdm;
+	max_cck = &priv->_3945.max_delta.rx.cck;
+	max_general = &priv->_3945.max_delta.rx.general;
+
+	pos += iwl3945_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - OFDM:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
+			 accum_ofdm->ina_cnt,
+			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_cnt:",
+			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
+			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:",
+			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
+			 le32_to_cpu(ofdm->overrun_err),
+			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
+			 max_ofdm->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "early_overrun_err:",
+			 le32_to_cpu(ofdm->early_overrun_err),
+			 accum_ofdm->early_overrun_err,
+			 delta_ofdm->early_overrun_err,
+			 max_ofdm->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_good:", le32_to_cpu(ofdm->crc32_good),
+			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
+			 max_ofdm->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
+			 le32_to_cpu(ofdm->false_alarm_cnt),
+			 accum_ofdm->false_alarm_cnt,
+			 delta_ofdm->false_alarm_cnt,
+			 max_ofdm->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_sync_err_cnt:",
+			 le32_to_cpu(ofdm->fina_sync_err_cnt),
+			 accum_ofdm->fina_sync_err_cnt,
+			 delta_ofdm->fina_sync_err_cnt,
+			 max_ofdm->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sfd_timeout:",
+			 le32_to_cpu(ofdm->sfd_timeout),
+			 accum_ofdm->sfd_timeout,
+			 delta_ofdm->sfd_timeout,
+			 max_ofdm->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_timeout:",
+			 le32_to_cpu(ofdm->fina_timeout),
+			 accum_ofdm->fina_timeout,
+			 delta_ofdm->fina_timeout,
+			 max_ofdm->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "unresponded_rts:",
+			 le32_to_cpu(ofdm->unresponded_rts),
+			 accum_ofdm->unresponded_rts,
+			 delta_ofdm->unresponded_rts,
+			 max_ofdm->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+			 accum_ofdm->rxe_frame_limit_overrun,
+			 delta_ofdm->rxe_frame_limit_overrun,
+			 max_ofdm->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_ack_cnt:",
+			 le32_to_cpu(ofdm->sent_ack_cnt),
+			 accum_ofdm->sent_ack_cnt,
+			 delta_ofdm->sent_ack_cnt,
+			 max_ofdm->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_cts_cnt:",
+			 le32_to_cpu(ofdm->sent_cts_cnt),
+			 accum_ofdm->sent_cts_cnt,
+			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - CCK:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ina_cnt:",
+			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+			 delta_cck->ina_cnt, max_cck->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_cnt:",
+			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+			 delta_cck->fina_cnt, max_cck->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "plcp_err:",
+			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+			 delta_cck->plcp_err, max_cck->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_err:",
+			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+			 delta_cck->crc32_err, max_cck->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "overrun_err:",
+			 le32_to_cpu(cck->overrun_err),
+			 accum_cck->overrun_err,
+			 delta_cck->overrun_err, max_cck->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "early_overrun_err:",
+			 le32_to_cpu(cck->early_overrun_err),
+			 accum_cck->early_overrun_err,
+			 delta_cck->early_overrun_err,
+			 max_cck->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "crc32_good:",
+			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+			 delta_cck->crc32_good,
+			 max_cck->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "false_alarm_cnt:",
+			 le32_to_cpu(cck->false_alarm_cnt),
+			 accum_cck->false_alarm_cnt,
+			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_sync_err_cnt:",
+			 le32_to_cpu(cck->fina_sync_err_cnt),
+			 accum_cck->fina_sync_err_cnt,
+			 delta_cck->fina_sync_err_cnt,
+			 max_cck->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sfd_timeout:",
+			 le32_to_cpu(cck->sfd_timeout),
+			 accum_cck->sfd_timeout,
+			 delta_cck->sfd_timeout, max_cck->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "fina_timeout:",
+			 le32_to_cpu(cck->fina_timeout),
+			 accum_cck->fina_timeout,
+			 delta_cck->fina_timeout, max_cck->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "unresponded_rts:",
+			 le32_to_cpu(cck->unresponded_rts),
+			 accum_cck->unresponded_rts,
+			 delta_cck->unresponded_rts,
+			 max_cck->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(cck->rxe_frame_limit_overrun),
+			 accum_cck->rxe_frame_limit_overrun,
+			 delta_cck->rxe_frame_limit_overrun,
+			 max_cck->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_ack_cnt:",
+			 le32_to_cpu(cck->sent_ack_cnt),
+			 accum_cck->sent_ack_cnt,
+			 delta_cck->sent_ack_cnt,
+			 max_cck->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sent_cts_cnt:",
+			 le32_to_cpu(cck->sent_cts_cnt),
+			 accum_cck->sent_cts_cnt,
+			 delta_cck->sent_cts_cnt,
+			 max_cck->sent_cts_cnt);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Rx - GENERAL:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bogus_cts:",
+			 le32_to_cpu(general->bogus_cts),
+			 accum_general->bogus_cts,
+			 delta_general->bogus_cts, max_general->bogus_cts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bogus_ack:",
+			 le32_to_cpu(general->bogus_ack),
+			 accum_general->bogus_ack,
+			 delta_general->bogus_ack, max_general->bogus_ack);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "non_bssid_frames:",
+			 le32_to_cpu(general->non_bssid_frames),
+			 accum_general->non_bssid_frames,
+			 delta_general->non_bssid_frames,
+			 max_general->non_bssid_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "filtered_frames:",
+			 le32_to_cpu(general->filtered_frames),
+			 accum_general->filtered_frames,
+			 delta_general->filtered_frames,
+			 max_general->filtered_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "non_channel_beacons:",
+			 le32_to_cpu(general->non_channel_beacons),
+			 accum_general->non_channel_beacons,
+			 delta_general->non_channel_beacons,
+			 max_general->non_channel_beacons);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
+				    char __user *user_buf,
+				    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
+	ssize_t ret;
+	struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	tx = &priv->_3945.statistics.tx;
+	accum_tx = &priv->_3945.accum_statistics.tx;
+	delta_tx = &priv->_3945.delta_statistics.tx;
+	max_tx = &priv->_3945.max_delta.tx;
+	pos += iwl3945_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_Tx:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "preamble:",
+			 le32_to_cpu(tx->preamble_cnt),
+			 accum_tx->preamble_cnt,
+			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "rx_detected_cnt:",
+			 le32_to_cpu(tx->rx_detected_cnt),
+			 accum_tx->rx_detected_cnt,
+			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bt_prio_defer_cnt:",
+			 le32_to_cpu(tx->bt_prio_defer_cnt),
+			 accum_tx->bt_prio_defer_cnt,
+			 delta_tx->bt_prio_defer_cnt,
+			 max_tx->bt_prio_defer_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "bt_prio_kill_cnt:",
+			 le32_to_cpu(tx->bt_prio_kill_cnt),
+			 accum_tx->bt_prio_kill_cnt,
+			 delta_tx->bt_prio_kill_cnt,
+			 max_tx->bt_prio_kill_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "few_bytes_cnt:",
+			 le32_to_cpu(tx->few_bytes_cnt),
+			 accum_tx->few_bytes_cnt,
+			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "cts_timeout:",
+			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+			 delta_tx->cts_timeout, max_tx->cts_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "ack_timeout:",
+			 le32_to_cpu(tx->ack_timeout),
+			 accum_tx->ack_timeout,
+			 delta_tx->ack_timeout, max_tx->ack_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "expected_ack_cnt:",
+			 le32_to_cpu(tx->expected_ack_cnt),
+			 accum_tx->expected_ack_cnt,
+			 delta_tx->expected_ack_cnt,
+			 max_tx->expected_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "actual_ack_cnt:",
+			 le32_to_cpu(tx->actual_ack_cnt),
+			 accum_tx->actual_ack_cnt,
+			 delta_tx->actual_ack_cnt,
+			 max_tx->actual_ack_cnt);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
+	ssize_t ret;
+	struct iwl39_statistics_general *general, *accum_general;
+	struct iwl39_statistics_general *delta_general, *max_general;
+	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+	struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * The statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	general = &priv->_3945.statistics.general;
+	dbg = &priv->_3945.statistics.general.dbg;
+	div = &priv->_3945.statistics.general.div;
+	accum_general = &priv->_3945.accum_statistics.general;
+	delta_general = &priv->_3945.delta_statistics.general;
+	max_general = &priv->_3945.max_delta.general;
+	accum_dbg = &priv->_3945.accum_statistics.general.dbg;
+	delta_dbg = &priv->_3945.delta_statistics.general.dbg;
+	max_dbg = &priv->_3945.max_delta.general.dbg;
+	accum_div = &priv->_3945.accum_statistics.general.div;
+	delta_div = &priv->_3945.delta_statistics.general.div;
+	max_div = &priv->_3945.max_delta.general.div;
+	pos += iwl3945_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
+			 "acumulative       delta         max\n",
+			 "Statistics_General:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "burst_check:",
+			 le32_to_cpu(dbg->burst_check),
+			 accum_dbg->burst_check,
+			 delta_dbg->burst_check, max_dbg->burst_check);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "burst_count:",
+			 le32_to_cpu(dbg->burst_count),
+			 accum_dbg->burst_count,
+			 delta_dbg->burst_count, max_dbg->burst_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "sleep_time:",
+			 le32_to_cpu(general->sleep_time),
+			 accum_general->sleep_time,
+			 delta_general->sleep_time, max_general->sleep_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "slots_out:",
+			 le32_to_cpu(general->slots_out),
+			 accum_general->slots_out,
+			 delta_general->slots_out, max_general->slots_out);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "slots_idle:",
+			 le32_to_cpu(general->slots_idle),
+			 accum_general->slots_idle,
+			 delta_general->slots_idle, max_general->slots_idle);
+	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
+			 le32_to_cpu(general->ttl_timestamp));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "tx_on_a:",
+			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+			 delta_div->tx_on_a, max_div->tx_on_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "tx_on_b:",
+			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+			 delta_div->tx_on_b, max_div->tx_on_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "exec_time:",
+			 le32_to_cpu(div->exec_time), accum_div->exec_time,
+			 delta_div->exec_time, max_div->exec_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 "  %-30s %10u  %10u  %10u  %10u\n",
+			 "probe_time:",
+			 le32_to_cpu(div->probe_time), accum_div->probe_time,
+			 delta_div->probe_time, max_div->probe_time);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-debugfs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,60 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos);
+ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				    size_t count, loff_t *ppos);
+ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+					 char __user *user_buf, size_t count,
+					 loff_t *ppos);
+#else
+static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
+					   char __user *user_buf, size_t count,
+					   loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos)
+{
+	return 0;
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-fh.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-fh.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-fh.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-fh.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,187 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+#ifndef __iwl_3945_fh_h__
+#define __iwl_3945_fh_h__
+
+/************************************/
+/* iwl3945 Flow Handler Definitions */
+/************************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH39_MEM_LOWER_BOUND                   (0x0800)
+#define FH39_MEM_UPPER_BOUND                   (0x1000)
+
+#define FH39_CBCC_TABLE		(FH39_MEM_LOWER_BOUND + 0x140)
+#define FH39_TFDB_TABLE		(FH39_MEM_LOWER_BOUND + 0x180)
+#define FH39_RCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x400)
+#define FH39_RSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x4c0)
+#define FH39_TCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x500)
+#define FH39_TSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x680)
+
+/* TFDB (Transmit Frame Buffer Descriptor) */
+#define FH39_TFDB(_ch, buf)			(FH39_TFDB_TABLE + \
+						 ((_ch) * 2 + (buf)) * 0x28)
+#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)	(FH39_TFDB_TABLE + 0x50 * (_ch))
+
+/* CBCC channel is [0,2] */
+#define FH39_CBCC(_ch)		(FH39_CBCC_TABLE + (_ch) * 0x8)
+#define FH39_CBCC_CTRL(_ch)	(FH39_CBCC(_ch) + 0x00)
+#define FH39_CBCC_BASE(_ch)	(FH39_CBCC(_ch) + 0x04)
+
+/* RCSR channel is [0,2] */
+#define FH39_RCSR(_ch)			(FH39_RCSR_TABLE + (_ch) * 0x40)
+#define FH39_RCSR_CONFIG(_ch)		(FH39_RCSR(_ch) + 0x00)
+#define FH39_RCSR_RBD_BASE(_ch)		(FH39_RCSR(_ch) + 0x04)
+#define FH39_RCSR_WPTR(_ch)		(FH39_RCSR(_ch) + 0x20)
+#define FH39_RCSR_RPTR_ADDR(_ch)	(FH39_RCSR(_ch) + 0x24)
+
+#define FH39_RSCSR_CHNL0_WPTR		(FH39_RCSR_WPTR(0))
+
+/* RSSR */
+#define FH39_RSSR_CTRL			(FH39_RSSR_TABLE + 0x000)
+#define FH39_RSSR_STATUS		(FH39_RSSR_TABLE + 0x004)
+
+/* TCSR */
+#define FH39_TCSR(_ch)			(FH39_TCSR_TABLE + (_ch) * 0x20)
+#define FH39_TCSR_CONFIG(_ch)		(FH39_TCSR(_ch) + 0x00)
+#define FH39_TCSR_CREDIT(_ch)		(FH39_TCSR(_ch) + 0x04)
+#define FH39_TCSR_BUFF_STTS(_ch)	(FH39_TCSR(_ch) + 0x08)
+
+/* TSSR */
+#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TABLE + 0x000)
+#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TABLE + 0x008)
+#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TABLE + 0x010)
+
+
+/* DBM */
+
+#define FH39_SRVC_CHNL                            (6)
+
+#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
+#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
+
+#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128		(0x01000000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST		(0x00001000)
+
+#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH			(0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER		(0x00000001)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL	(0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL	(0x00000008)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD		(0x00200000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT		(0x00000000)
+
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE		(0x00000000)
+#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE		(0x80000000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID		(0x00004000)
+
+#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR		(0x00000001)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON	(0xFF000000)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON	(0x00FF0000)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B	(0x00000400)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON		(0x00000100)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON		(0x00000080)
+
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH	(0x00000020)
+#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH		(0x00000005)
+
+#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)	(BIT(_ch) << 24)
+#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)	(BIT(_ch) << 16)
+
+#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
+	(FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
+	 FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
+
+#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE			(0x01000000)
+
+struct iwl3945_tfd_tb {
+	__le32 addr;
+	__le32 len;
+} __packed;
+
+struct iwl3945_tfd {
+	__le32 control_flags;
+	struct iwl3945_tfd_tb tbs[4];
+	u8 __pad[28];
+} __packed;
+
+
+#endif /* __iwl_3945_fh_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945.h	2012-03-24 03:33:05.000000000 -0400
@@ -0,0 +1,308 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-3945.h) for driver implementation definitions.
+ * Please use iwl-3945-commands.h for uCode API definitions.
+ * Please use iwl-3945-hw.h for hardware-related definitions.
+ */
+
+#ifndef __iwl_3945_h__
+#define __iwl_3945_h__
+
+#include <linux/pci.h> /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <net/ieee80211_radiotap.h>
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+extern const struct pci_device_id iwl3945_hw_card_ids[];
+
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-fh.h"
+#include "iwl-3945-hw.h"
+#include "iwl-debug.h"
+#include "iwl-power.h"
+#include "iwl-dev.h"
+#include "iwl-led.h"
+
+/* Highest firmware API version supported */
+#define IWL3945_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IWL3945_UCODE_API_MIN 1
+
+#define IWL3945_FW_PRE	"/*(DEBLOBBED)*/"
+#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE /*(DEBLOBBED)*/
+#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
+
+/* Default noise level to report when noise measurement is not available.
+ *   This may be because we're:
+ *   1)  Not associated (4965, no beacon statistics being sent to driver)
+ *   2)  Scanning (noise measurement does not apply to associated channel)
+ *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Also, -127 works better than 0 when averaging frames with/without
+ *   noise info (e.g. averaging might be done in app); measured dBm values are
+ *   always negative ... using a negative value as the default keeps all
+ *   averages within an s8's (used in some apps) range of negative values. */
+#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/* Module parameters accessible from iwl-*.c */
+extern struct iwl_mod_params iwl3945_mod_params;
+
+struct iwl3945_rate_scale_data {
+	u64 data;
+	s32 success_counter;
+	s32 success_ratio;
+	s32 counter;
+	s32 average_tpt;
+	unsigned long stamp;
+};
+
+struct iwl3945_rs_sta {
+	spinlock_t lock;
+	struct iwl_priv *priv;
+	s32 *expected_tpt;
+	unsigned long last_partial_flush;
+	unsigned long last_flush;
+	u32 flush_time;
+	u32 last_tx_packets;
+	u32 tx_packets;
+	u8 tgg;
+	u8 flush_pending;
+	u8 start_rate;
+	struct timer_list rate_scale_flush;
+	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
+#ifdef CONFIG_MAC80211_DEBUGFS
+	struct dentry *rs_sta_dbgfs_stats_table_file;
+#endif
+
+	/* used to be in sta_info */
+	int last_txrate_idx;
+};
+
+
+/*
+ * The common struct MUST be first because it is shared between
+ * 3945 and 4965!
+ */
+struct iwl3945_sta_priv {
+	struct iwl_station_priv_common common;
+	struct iwl3945_rs_sta rs_sta;
+};
+
+enum iwl3945_antenna {
+	IWL_ANTENNA_DIVERSITY,
+	IWL_ANTENNA_MAIN,
+	IWL_ANTENNA_AUX
+};
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ *   a value of 0 means RTS on all data/management packets
+ *   a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ *   than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD     2347U
+#define MIN_RTS_THRESHOLD         0U
+#define MAX_RTS_THRESHOLD         2347U
+#define MAX_MSDU_SIZE		  2304U
+#define MAX_MPDU_SIZE		  2346U
+#define DEFAULT_BEACON_INTERVAL   100U
+#define	DEFAULT_SHORT_RETRY_LIMIT 7U
+#define	DEFAULT_LONG_RETRY_LIMIT  4U
+
+#define IWL_TX_FIFO_AC0	0
+#define IWL_TX_FIFO_AC1	1
+#define IWL_TX_FIFO_AC2	2
+#define IWL_TX_FIFO_AC3	3
+#define IWL_TX_FIFO_HCCA_1	5
+#define IWL_TX_FIFO_HCCA_2	6
+#define IWL_TX_FIFO_NONE	7
+
+#define IEEE80211_DATA_LEN              2304
+#define IEEE80211_4ADDR_LEN             30
+#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct iwl3945_frame {
+	union {
+		struct ieee80211_hdr frame;
+		struct iwl3945_tx_beacon_cmd beacon;
+		u8 raw[IEEE80211_FRAME_LEN];
+		u8 cmd[360];
+	} u;
+	struct list_head list;
+};
+
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+#define IWL_SUPPORTED_RATES_IE_LEN         8
+
+#define SCAN_INTERVAL 100
+
+#define MAX_TID_COUNT        9
+
+#define IWL_INVALID_RATE     0xFF
+#define IWL_INVALID_VALUE    -1
+
+#define STA_PS_STATUS_WAKE             0
+#define STA_PS_STATUS_SLEEP            1
+
+struct iwl3945_ibss_seq {
+	u8 mac[ETH_ALEN];
+	u16 seq_num;
+	u16 frag_num;
+	unsigned long packet_time;
+	struct list_head list;
+};
+
+#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
+		       x->u.rx_frame.stats.payload + \
+		       x->u.rx_frame.stats.phy_count))
+#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
+		       IWL_RX_HDR(x)->payload + \
+		       le16_to_cpu(IWL_RX_HDR(x)->len)))
+#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
+#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
+
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl3945-base.c which are forward declared here
+ * for use by iwl-*.c
+ *
+ *****************************************************************************/
+extern int iwl3945_calc_db_from_ratio(int sig_ratio);
+extern void iwl3945_rx_replenish(void *data);
+extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
+					struct ieee80211_hdr *hdr, int left);
+extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
+				       char **buf, bool display);
+extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
+
+/******************************************************************************
+ *
+ * Functions implemented in iwl-[34]*.c which are forward declared here
+ * for use by iwl3945-base.c
+ *
+ * NOTE:  The implementation of these functions are hardware specific
+ * which is why they are in the hardware specific files (vs. iwl-base.c)
+ *
+ * Naming convention --
+ * iwl3945_         <-- Its part of iwlwifi (should be changed to iwl3945_)
+ * iwl3945_hw_      <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
+ * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * iwl3945_bg_      <-- Called from work queue context
+ * iwl3945_mac_     <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
+extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
+extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
+extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
+extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
+extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
+extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
+extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
+extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+					    struct iwl_tx_queue *txq,
+					    dma_addr_t addr, u16 len,
+					    u8 reset, u8 pad);
+extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
+				    struct iwl_tx_queue *txq);
+extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
+extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
+				struct iwl_tx_queue *txq);
+extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
+				 struct iwl3945_frame *frame, u8 rate);
+void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
+				  struct iwl_device_cmd *cmd,
+				  struct ieee80211_tx_info *info,
+				  struct ieee80211_hdr *hdr,
+				  int sta_id, int tx_id);
+extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
+extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
+extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
+				 struct iwl_rx_mem_buffer *rxb);
+void iwl3945_reply_statistics(struct iwl_priv *priv,
+			      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);
+
+extern int iwl3945_commit_rxon(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+
+/**
+ * iwl3945_hw_find_station - Find station id for a given BSSID
+ * @bssid: MAC address of station ID to find
+ *
+ * NOTE:  This should not be hardware specific but the code has
+ * not yet been merged into a single common layer for managing the
+ * station tables.
+ */
+extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
+
+extern struct ieee80211_ops iwl3945_hw_ops;
+
+/*
+ * Forward declare iwl-3945.c functions for iwl3945-base.c
+ */
+extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
+extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
+extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
+extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
+
+extern const struct iwl_channel_info *iwl3945_get_channel_info(
+	const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
+
+extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
+
+/* scanning */
+int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+void iwl3945_post_scan(struct iwl_priv *priv);
+
+/* rates */
+extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
+
+/* Requires full declaration of iwl_priv before including */
+#include "iwl-io.h"
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
+ * Please use iwl-commands.h for uCode API definitions.
+ * Please use iwl-3945.h for driver implementation definitions.
+ */
+
+#ifndef __iwl_3945_hw__
+#define __iwl_3945_hw__
+
+#include "iwl-eeprom.h"
+
+/* RSSI to dBm */
+#define IWL39_RSSI_OFFSET	95
+
+/*
+ * EEPROM related constants, enums, and structures.
+ */
+#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
+
+/*
+ * Mapping of a Tx power level, at factory calibration temperature,
+ *   to a radio/DSP gain table index.
+ * One for each of 5 "sample" power levels in each band.
+ * v_det is measured at the factory, using the 3945's built-in power amplifier
+ *   (PA) output voltage detector.  This same detector is used during Tx of
+ *   long packets in normal operation to provide feedback as to proper output
+ *   level.
+ * Data copied from EEPROM.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct iwl3945_eeprom_txpower_sample {
+	u8 gain_index;		/* index into power (gain) setup table ... */
+	s8 power;		/* ... for this pwr level for this chnl group */
+	u16 v_det;		/* PA output voltage */
+} __packed;
+
+/*
+ * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
+ * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
+ * Tx power setup code interpolates between the 5 "sample" power levels
+ *    to determine the nominal setup for a requested power level.
+ * Data copied from EEPROM.
+ * DO NOT ALTER THIS STRUCTURE!!!
+ */
+struct iwl3945_eeprom_txpower_group {
+	struct iwl3945_eeprom_txpower_sample samples[5];  /* 5 power levels */
+	s32 a, b, c, d, e;	/* coefficients for voltage->power
+				 * formula (signed) */
+	s32 Fa, Fb, Fc, Fd, Fe;	/* these modify coeffs based on
+				 * frequency (signed) */
+	s8 saturation_power;	/* highest power possible by h/w in this
+				 * band */
+	u8 group_channel;	/* "representative" channel # in this band */
+	s16 temperature;	/* h/w temperature at factory calib this band
+				 * (signed) */
+} __packed;
+
+/*
+ * Temperature-based Tx-power compensation data, not band-specific.
+ * These coefficients are use to modify a/b/c/d/e coeffs based on
+ *   difference between current temperature and factory calib temperature.
+ * Data copied from EEPROM.
+ */
+struct iwl3945_eeprom_temperature_corr {
+	u32 Ta;
+	u32 Tb;
+	u32 Tc;
+	u32 Td;
+	u32 Te;
+} __packed;
+
+/*
+ * EEPROM map
+ */
+struct iwl3945_eeprom {
+	u8 reserved0[16];
+	u16 device_id;	/* abs.ofs: 16 */
+	u8 reserved1[2];
+	u16 pmc;		/* abs.ofs: 20 */
+	u8 reserved2[20];
+	u8 mac_address[6];	/* abs.ofs: 42 */
+	u8 reserved3[58];
+	u16 board_revision;	/* abs.ofs: 106 */
+	u8 reserved4[11];
+	u8 board_pba_number[9];	/* abs.ofs: 119 */
+	u8 reserved5[8];
+	u16 version;		/* abs.ofs: 136 */
+	u8 sku_cap;		/* abs.ofs: 138 */
+	u8 leds_mode;		/* abs.ofs: 139 */
+	u16 oem_mode;
+	u16 wowlan_mode;	/* abs.ofs: 142 */
+	u16 leds_time_interval;	/* abs.ofs: 144 */
+	u8 leds_off_time;	/* abs.ofs: 146 */
+	u8 leds_on_time;	/* abs.ofs: 147 */
+	u8 almgor_m_version;	/* abs.ofs: 148 */
+	u8 antenna_switch_type;	/* abs.ofs: 149 */
+	u8 reserved6[42];
+	u8 sku_id[4];		/* abs.ofs: 192 */
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by 3945 has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+	u16 band_1_count;	/* abs.ofs: 196 */
+	struct iwl_eeprom_channel band_1_channels[14];  /* abs.ofs: 198 */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+	u16 band_2_count;	/* abs.ofs: 226 */
+	struct iwl_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+	u16 band_3_count;	/* abs.ofs: 254 */
+	struct iwl_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+	u16 band_4_count;	/* abs.ofs: 280 */
+	struct iwl_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+	u16 band_5_count;	/* abs.ofs: 304 */
+	struct iwl_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
+
+	u8 reserved9[194];
+
+/*
+ * 3945 Txpower calibration data.
+ */
+#define IWL_NUM_TX_CALIB_GROUPS 5
+	struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
+/* abs.ofs: 512 */
+	struct iwl3945_eeprom_temperature_corr corrections;  /* abs.ofs: 832 */
+	u8 reserved16[172];	/* fill out to full 1024 byte block */
+} __packed;
+
+#define IWL3945_EEPROM_IMG_SIZE 1024
+
+/* End of EEPROM */
+
+#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)	/* bit 6    */
+#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)	/* bit 7    */
+
+/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
+#define IWL39_NUM_QUEUES        5
+#define IWL39_CMD_QUEUE_NUM	4
+
+#define IWL_DEFAULT_TX_RETRY  15
+
+/*********************************************/
+
+#define RFD_SIZE                              4
+#define NUM_TFD_CHUNKS                        4
+
+#define RX_QUEUE_SIZE                         256
+#define RX_QUEUE_MASK                         255
+#define RX_QUEUE_SIZE_LOG                     8
+
+#define U32_PAD(n)		((4-(n))&0x3)
+
+#define TFD_CTL_COUNT_SET(n)       (n << 24)
+#define TFD_CTL_COUNT_GET(ctl)     ((ctl >> 24) & 7)
+#define TFD_CTL_PAD_SET(n)         (n << 28)
+#define TFD_CTL_PAD_GET(ctl)       (ctl >> 28)
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+#define IWL39_RTC_INST_LOWER_BOUND		(0x000000)
+#define IWL39_RTC_INST_UPPER_BOUND		(0x014000)
+
+#define IWL39_RTC_DATA_LOWER_BOUND		(0x800000)
+#define IWL39_RTC_DATA_UPPER_BOUND		(0x808000)
+
+#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
+				IWL39_RTC_INST_LOWER_BOUND)
+#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
+				IWL39_RTC_DATA_LOWER_BOUND)
+
+#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
+#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
+
+static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
+{
+	return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
+	       (addr < IWL39_RTC_DATA_UPPER_BOUND);
+}
+
+/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
+ * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
+struct iwl3945_shared {
+	__le32 tx_base_ptr[8];
+} __packed;
+
+static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
+{
+	return le16_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
+{
+	return le16_to_cpu(rate_n_flags);
+}
+
+static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
+{
+	return cpu_to_le16((u16)rate|flags);
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,64 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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 <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-commands.h"
+#include "iwl-3945.h"
+#include "iwl-core.h"
+#include "iwl-dev.h"
+#include "iwl-3945-led.h"
+
+
+/* Send led command */
+static int iwl3945_send_led_cmd(struct iwl_priv *priv,
+				struct iwl_led_cmd *led_cmd)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_LEDS_CMD,
+		.len = sizeof(struct iwl_led_cmd),
+		.data = led_cmd,
+		.flags = CMD_ASYNC,
+		.callback = NULL,
+	};
+
+	return iwl_legacy_send_cmd(priv, &cmd);
+}
+
+const struct iwl_led_ops iwl3945_led_ops = {
+	.cmd = iwl3945_send_led_cmd,
+};
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-led.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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_3945_led_h__
+#define __iwl_3945_led_h__
+
+extern const struct iwl_led_ops iwl3945_led_ops;
+
+#endif /* __iwl_3945_led_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-rs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-3945-rs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-3945-rs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,994 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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/init.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "iwl-commands.h"
+#include "iwl-3945.h"
+#include "iwl-sta.h"
+
+#define RS_NAME "iwl-3945-rs"
+
+static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
+	7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
+};
+
+static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
+	7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
+};
+
+static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
+	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
+};
+
+static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
+	7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
+};
+
+struct iwl3945_tpt_entry {
+	s8 min_rssi;
+	u8 index;
+};
+
+static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
+	{-60, IWL_RATE_54M_INDEX},
+	{-64, IWL_RATE_48M_INDEX},
+	{-72, IWL_RATE_36M_INDEX},
+	{-80, IWL_RATE_24M_INDEX},
+	{-84, IWL_RATE_18M_INDEX},
+	{-85, IWL_RATE_12M_INDEX},
+	{-87, IWL_RATE_9M_INDEX},
+	{-89, IWL_RATE_6M_INDEX}
+};
+
+static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
+	{-60, IWL_RATE_54M_INDEX},
+	{-64, IWL_RATE_48M_INDEX},
+	{-68, IWL_RATE_36M_INDEX},
+	{-80, IWL_RATE_24M_INDEX},
+	{-84, IWL_RATE_18M_INDEX},
+	{-85, IWL_RATE_12M_INDEX},
+	{-86, IWL_RATE_11M_INDEX},
+	{-88, IWL_RATE_5M_INDEX},
+	{-90, IWL_RATE_2M_INDEX},
+	{-92, IWL_RATE_1M_INDEX}
+};
+
+#define IWL_RATE_MAX_WINDOW          62
+#define IWL_RATE_FLUSH		(3*HZ)
+#define IWL_RATE_WIN_FLUSH       (HZ/2)
+#define IWL39_RATE_HIGH_TH          11520
+#define IWL_SUCCESS_UP_TH	   8960
+#define IWL_SUCCESS_DOWN_TH	  10880
+#define IWL_RATE_MIN_FAILURE_TH       6
+#define IWL_RATE_MIN_SUCCESS_TH       8
+#define IWL_RATE_DECREASE_TH       1920
+#define IWL_RATE_RETRY_TH	     15
+
+static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
+{
+	u32 index = 0;
+	u32 table_size = 0;
+	struct iwl3945_tpt_entry *tpt_table = NULL;
+
+	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
+		rssi = IWL_MIN_RSSI_VAL;
+
+	switch (band) {
+	case IEEE80211_BAND_2GHZ:
+		tpt_table = iwl3945_tpt_table_g;
+		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
+		break;
+
+	case IEEE80211_BAND_5GHZ:
+		tpt_table = iwl3945_tpt_table_a;
+		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
+		break;
+
+	default:
+		BUG();
+		break;
+	}
+
+	while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
+		index++;
+
+	index = min(index, (table_size - 1));
+
+	return tpt_table[index].index;
+}
+
+static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
+{
+	window->data = 0;
+	window->success_counter = 0;
+	window->success_ratio = -1;
+	window->counter = 0;
+	window->average_tpt = IWL_INVALID_VALUE;
+	window->stamp = 0;
+}
+
+/**
+ * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
+ *
+ * Returns the number of windows that have gathered data but were
+ * not flushed.  If there were any that were not flushed, then
+ * reschedule the rate flushing routine.
+ */
+static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
+{
+	int unflushed = 0;
+	int i;
+	unsigned long flags;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+
+	/*
+	 * For each rate, if we have collected data on that rate
+	 * and it has been more than IWL_RATE_WIN_FLUSH
+	 * since we flushed, clear out the gathered statistics
+	 */
+	for (i = 0; i < IWL_RATE_COUNT_3945; i++) {
+		if (!rs_sta->win[i].counter)
+			continue;
+
+		spin_lock_irqsave(&rs_sta->lock, flags);
+		if (time_after(jiffies, rs_sta->win[i].stamp +
+			       IWL_RATE_WIN_FLUSH)) {
+			IWL_DEBUG_RATE(priv, "flushing %d samples of rate "
+				       "index %d\n",
+				       rs_sta->win[i].counter, i);
+			iwl3945_clear_window(&rs_sta->win[i]);
+		} else
+			unflushed++;
+		spin_unlock_irqrestore(&rs_sta->lock, flags);
+	}
+
+	return unflushed;
+}
+
+#define IWL_RATE_FLUSH_MAX              5000	/* msec */
+#define IWL_RATE_FLUSH_MIN              50	/* msec */
+#define IWL_AVERAGE_PACKETS             1500
+
+static void iwl3945_bg_rate_scale_flush(unsigned long data)
+{
+	struct iwl3945_rs_sta *rs_sta = (void *)data;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+	int unflushed = 0;
+	unsigned long flags;
+	u32 packet_count, duration, pps;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	/* Number of packets Rx'd since last time this timer ran */
+	packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
+
+	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
+
+	if (unflushed) {
+		duration =
+		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
+
+		IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n",
+			       packet_count, duration);
+
+		/* Determine packets per second */
+		if (duration)
+			pps = (packet_count * 1000) / duration;
+		else
+			pps = 0;
+
+		if (pps) {
+			duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
+			if (duration < IWL_RATE_FLUSH_MIN)
+				duration = IWL_RATE_FLUSH_MIN;
+			else if (duration > IWL_RATE_FLUSH_MAX)
+				duration = IWL_RATE_FLUSH_MAX;
+		} else
+			duration = IWL_RATE_FLUSH_MAX;
+
+		rs_sta->flush_time = msecs_to_jiffies(duration);
+
+		IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n",
+			       duration, packet_count);
+
+		mod_timer(&rs_sta->rate_scale_flush, jiffies +
+			  rs_sta->flush_time);
+
+		rs_sta->last_partial_flush = jiffies;
+	} else {
+		rs_sta->flush_time = IWL_RATE_FLUSH;
+		rs_sta->flush_pending = 0;
+	}
+	/* If there weren't any unflushed entries, we don't schedule the timer
+	 * to run again */
+
+	rs_sta->last_flush = jiffies;
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	IWL_DEBUG_RATE(priv, "leave\n");
+}
+
+/**
+ * iwl3945_collect_tx_data - Update the success/failure sliding window
+ *
+ * We keep a sliding window of the last 64 packets transmitted
+ * at this rate.  window->data contains the bitmask of successful
+ * packets.
+ */
+static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
+				struct iwl3945_rate_scale_data *window,
+				int success, int retries, int index)
+{
+	unsigned long flags;
+	s32 fail_count;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+
+	if (!retries) {
+		IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n");
+		return;
+	}
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	/*
+	 * Keep track of only the latest 62 tx frame attempts in this rate's
+	 * history window; anything older isn't really relevant any more.
+	 * If we have filled up the sliding window, drop the oldest attempt;
+	 * if the oldest attempt (highest bit in bitmap) shows "success",
+	 * subtract "1" from the success counter (this is the main reason
+	 * we keep these bitmaps!).
+	 * */
+	while (retries > 0) {
+		if (window->counter >= IWL_RATE_MAX_WINDOW) {
+
+			/* remove earliest */
+			window->counter = IWL_RATE_MAX_WINDOW - 1;
+
+			if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) {
+				window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1));
+				window->success_counter--;
+			}
+		}
+
+		/* Increment frames-attempted counter */
+		window->counter++;
+
+		/* Shift bitmap by one frame (throw away oldest history),
+		 * OR in "1", and increment "success" if this
+		 * frame was successful. */
+		window->data <<= 1;
+		if (success > 0) {
+			window->success_counter++;
+			window->data |= 0x1;
+			success--;
+		}
+
+		retries--;
+	}
+
+	/* Calculate current success ratio, avoid divide-by-0! */
+	if (window->counter > 0)
+		window->success_ratio = 128 * (100 * window->success_counter)
+					/ window->counter;
+	else
+		window->success_ratio = IWL_INVALID_VALUE;
+
+	fail_count = window->counter - window->success_counter;
+
+	/* Calculate average throughput, if we have enough history. */
+	if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
+	    (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
+		window->average_tpt = ((window->success_ratio *
+				rs_sta->expected_tpt[index] + 64) / 128);
+	else
+		window->average_tpt = IWL_INVALID_VALUE;
+
+	/* Tag this window as having been updated */
+	window->stamp = jiffies;
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+}
+
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
+{
+	struct ieee80211_hw *hw = priv->hw;
+	struct ieee80211_conf *conf = &priv->hw->conf;
+	struct iwl3945_sta_priv *psta;
+	struct iwl3945_rs_sta *rs_sta;
+	struct ieee80211_supported_band *sband;
+	int i;
+
+	IWL_DEBUG_INFO(priv, "enter\n");
+	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
+		goto out;
+
+	psta = (struct iwl3945_sta_priv *) sta->drv_priv;
+	rs_sta = &psta->rs_sta;
+	sband = hw->wiphy->bands[conf->channel->band];
+
+	rs_sta->priv = priv;
+
+	rs_sta->start_rate = IWL_RATE_INVALID;
+
+	/* default to just 802.11b */
+	rs_sta->expected_tpt = iwl3945_expected_tpt_b;
+
+	rs_sta->last_partial_flush = jiffies;
+	rs_sta->last_flush = jiffies;
+	rs_sta->flush_time = IWL_RATE_FLUSH;
+	rs_sta->last_tx_packets = 0;
+
+	rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
+	rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;
+
+	for (i = 0; i < IWL_RATE_COUNT_3945; i++)
+		iwl3945_clear_window(&rs_sta->win[i]);
+
+	/* TODO: what is a good starting rate for STA? About middle? Maybe not
+	 * the lowest or the highest rate.. Could consider using RSSI from
+	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
+	 * after assoc.. */
+
+	for (i = sband->n_bitrates - 1; i >= 0; i--) {
+		if (sta->supp_rates[sband->band] & (1 << i)) {
+			rs_sta->last_txrate_idx = i;
+			break;
+		}
+	}
+
+	priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
+	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
+	if (sband->band == IEEE80211_BAND_5GHZ) {
+		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+		priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
+						IWL_FIRST_OFDM_RATE;
+	}
+
+out:
+	priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+
+	IWL_DEBUG_INFO(priv, "leave\n");
+}
+
+static void *iwl3945_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+	return hw->priv;
+}
+
+/* rate scale requires free function to be implemented */
+static void iwl3945_rs_free(void *priv)
+{
+	return;
+}
+
+static void *iwl3945_rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
+{
+	struct iwl3945_rs_sta *rs_sta;
+	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
+	struct iwl_priv *priv __maybe_unused = iwl_priv;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	rs_sta = &psta->rs_sta;
+
+	spin_lock_init(&rs_sta->lock);
+	init_timer(&rs_sta->rate_scale_flush);
+
+	IWL_DEBUG_RATE(priv, "leave\n");
+
+	return rs_sta;
+}
+
+static void iwl3945_rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
+			void *priv_sta)
+{
+	struct iwl3945_rs_sta *rs_sta = priv_sta;
+
+	/*
+	 * Be careful not to use any members of iwl3945_rs_sta (like trying
+	 * to use iwl_priv to print out debugging) since it may not be fully
+	 * initialized at this point.
+	 */
+	del_timer_sync(&rs_sta->rate_scale_flush);
+}
+
+
+/**
+ * iwl3945_rs_tx_status - Update rate control values based on Tx results
+ *
+ * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
+ * the hardware for each rate.
+ */
+static void iwl3945_rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
+			 struct ieee80211_sta *sta, void *priv_sta,
+			 struct sk_buff *skb)
+{
+	s8 retries = 0, current_count;
+	int scale_rate_index, first_index, last_index;
+	unsigned long flags;
+	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
+	struct iwl3945_rs_sta *rs_sta = priv_sta;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	retries = info->status.rates[0].count;
+	/* Sanity Check for retries */
+	if (retries > IWL_RATE_RETRY_TH)
+		retries = IWL_RATE_RETRY_TH;
+
+	first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
+	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
+		IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index);
+		return;
+	}
+
+	if (!priv_sta) {
+		IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
+		return;
+	}
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (!rs_sta->priv) {
+		IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
+		return;
+	}
+
+
+	rs_sta->tx_packets++;
+
+	scale_rate_index = first_index;
+	last_index = first_index;
+
+	/*
+	 * Update the window for each rate.  We determine which rates
+	 * were Tx'd based on the total number of retries vs. the number
+	 * of retries configured for each rate -- currently set to the
+	 * priv value 'retry_rate' vs. rate specific
+	 *
+	 * On exit from this while loop last_index indicates the rate
+	 * at which the frame was finally transmitted (or failed if no
+	 * ACK)
+	 */
+	while (retries > 1) {
+		if ((retries - 1) < priv->retry_rate) {
+			current_count = (retries - 1);
+			last_index = scale_rate_index;
+		} else {
+			current_count = priv->retry_rate;
+			last_index = iwl3945_rs_next_rate(priv,
+							 scale_rate_index);
+		}
+
+		/* Update this rate accounting for as many retries
+		 * as was used for it (per current_count) */
+		iwl3945_collect_tx_data(rs_sta,
+				    &rs_sta->win[scale_rate_index],
+				    0, current_count, scale_rate_index);
+		IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n",
+			       scale_rate_index, current_count);
+
+		retries -= current_count;
+
+		scale_rate_index = last_index;
+	}
+
+
+	/* Update the last index window with success/failure based on ACK */
+	IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n",
+		       last_index,
+		       (info->flags & IEEE80211_TX_STAT_ACK) ?
+		       "success" : "failure");
+	iwl3945_collect_tx_data(rs_sta,
+			    &rs_sta->win[last_index],
+			    info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
+
+	/* We updated the rate scale window -- if its been more than
+	 * flush_time since the last run, schedule the flush
+	 * again */
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	if (!rs_sta->flush_pending &&
+	    time_after(jiffies, rs_sta->last_flush +
+		       rs_sta->flush_time)) {
+
+		rs_sta->last_partial_flush = jiffies;
+		rs_sta->flush_pending = 1;
+		mod_timer(&rs_sta->rate_scale_flush,
+			  jiffies + rs_sta->flush_time);
+	}
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	IWL_DEBUG_RATE(priv, "leave\n");
+}
+
+static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
+				 u8 index, u16 rate_mask, enum ieee80211_band band)
+{
+	u8 high = IWL_RATE_INVALID;
+	u8 low = IWL_RATE_INVALID;
+	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
+
+	/* 802.11A walks to the next literal adjacent rate in
+	 * the rate table */
+	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
+		int i;
+		u32 mask;
+
+		/* Find the previous rate that is in the rate mask */
+		i = index - 1;
+		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
+			if (rate_mask & mask) {
+				low = i;
+				break;
+			}
+		}
+
+		/* Find the next rate that is in the rate mask */
+		i = index + 1;
+		for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
+		     i++, mask <<= 1) {
+			if (rate_mask & mask) {
+				high = i;
+				break;
+			}
+		}
+
+		return (high << 8) | low;
+	}
+
+	low = index;
+	while (low != IWL_RATE_INVALID) {
+		if (rs_sta->tgg)
+			low = iwl3945_rates[low].prev_rs_tgg;
+		else
+			low = iwl3945_rates[low].prev_rs;
+		if (low == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << low))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
+	}
+
+	high = index;
+	while (high != IWL_RATE_INVALID) {
+		if (rs_sta->tgg)
+			high = iwl3945_rates[high].next_rs_tgg;
+		else
+			high = iwl3945_rates[high].next_rs;
+		if (high == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << high))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
+	}
+
+	return (high << 8) | low;
+}
+
+/**
+ * iwl3945_rs_get_rate - find the rate for the requested packet
+ *
+ * Returns the ieee80211_rate structure allocated by the driver.
+ *
+ * The rate control algorithm has no internal mapping between hw_mode's
+ * rate ordering and the rate ordering used by the rate control algorithm.
+ *
+ * The rate control algorithm uses a single table of rates that goes across
+ * the entire A/B/G spectrum vs. being limited to just one particular
+ * hw_mode.
+ *
+ * As such, we can't convert the index obtained below into the hw_mode's
+ * rate table and must reference the driver allocated rate table
+ *
+ */
+static void iwl3945_rs_get_rate(void *priv_r, 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;
+	u8 low = IWL_RATE_INVALID;
+	u8 high = IWL_RATE_INVALID;
+	u16 high_low;
+	int index;
+	struct iwl3945_rs_sta *rs_sta = priv_sta;
+	struct iwl3945_rate_scale_data *window = NULL;
+	int current_tpt = IWL_INVALID_VALUE;
+	int low_tpt = IWL_INVALID_VALUE;
+	int high_tpt = IWL_INVALID_VALUE;
+	u32 fail_count;
+	s8 scale_action = 0;
+	unsigned long flags;
+	u16 rate_mask;
+	s8 max_rate_idx = -1;
+	struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (rs_sta && !rs_sta->priv) {
+		IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
+		priv_sta = NULL;
+	}
+
+	if (rate_control_send_low(sta, priv_sta, txrc))
+		return;
+
+	rate_mask = sta->supp_rates[sband->band];
+
+	/* get user max rate if set */
+	max_rate_idx = txrc->max_rate_idx;
+	if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
+		max_rate_idx += IWL_FIRST_OFDM_RATE;
+	if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
+		max_rate_idx = -1;
+
+	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
+
+	if (sband->band == IEEE80211_BAND_5GHZ)
+		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	/* for recent assoc, choose best rate regarding
+	 * to rssi value
+	 */
+	if (rs_sta->start_rate != IWL_RATE_INVALID) {
+		if (rs_sta->start_rate < index &&
+		   (rate_mask & (1 << rs_sta->start_rate)))
+			index = rs_sta->start_rate;
+		rs_sta->start_rate = IWL_RATE_INVALID;
+	}
+
+	/* force user max rate if set by user */
+	if ((max_rate_idx != -1) && (max_rate_idx < index)) {
+		if (rate_mask & (1 << max_rate_idx))
+			index = max_rate_idx;
+	}
+
+	window = &(rs_sta->win[index]);
+
+	fail_count = window->counter - window->success_counter;
+
+	if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
+	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
+		spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+		IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: "
+			       "counter: %d, success_counter: %d, "
+			       "expected_tpt is %sNULL\n",
+			       index,
+			       window->counter,
+			       window->success_counter,
+			       rs_sta->expected_tpt ? "not " : "");
+
+	   /* Can't calculate this yet; not enough history */
+		window->average_tpt = IWL_INVALID_VALUE;
+		goto out;
+
+	}
+
+	current_tpt = window->average_tpt;
+
+	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
+					     sband->band);
+	low = high_low & 0xff;
+	high = (high_low >> 8) & 0xff;
+
+	/* If user set max rate, dont allow higher than user constrain */
+	if ((max_rate_idx != -1) && (max_rate_idx < high))
+		high = IWL_RATE_INVALID;
+
+	/* Collect Measured throughputs of adjacent rates */
+	if (low != IWL_RATE_INVALID)
+		low_tpt = rs_sta->win[low].average_tpt;
+
+	if (high != IWL_RATE_INVALID)
+		high_tpt = rs_sta->win[high].average_tpt;
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	scale_action = 0;
+
+	/* Low success ratio , need to drop the rate */
+	if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
+		IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n");
+		scale_action = -1;
+	/* No throughput measured yet for adjacent rates,
+	 * try increase */
+	} else if ((low_tpt == IWL_INVALID_VALUE) &&
+		   (high_tpt == IWL_INVALID_VALUE)) {
+
+		if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH)
+			scale_action = 1;
+		else if (low != IWL_RATE_INVALID)
+			scale_action = 0;
+
+	/* Both adjacent throughputs are measured, but neither one has
+	 * better throughput; we're using the best rate, don't change
+	 * it! */
+	} else if ((low_tpt != IWL_INVALID_VALUE) &&
+		 (high_tpt != IWL_INVALID_VALUE) &&
+		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
+
+		IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < "
+			       "current_tpt [%d]\n",
+			       low_tpt, high_tpt, current_tpt);
+		scale_action = 0;
+
+	/* At least one of the rates has better throughput */
+	} else {
+		if (high_tpt != IWL_INVALID_VALUE) {
+
+			/* High rate has better throughput, Increase
+			 * rate */
+			if (high_tpt > current_tpt &&
+				window->success_ratio >= IWL_RATE_INCREASE_TH)
+				scale_action = 1;
+			else {
+				IWL_DEBUG_RATE(priv,
+				    "decrease rate because of high tpt\n");
+				scale_action = 0;
+			}
+		} else if (low_tpt != IWL_INVALID_VALUE) {
+			if (low_tpt > current_tpt) {
+				IWL_DEBUG_RATE(priv,
+				    "decrease rate because of low tpt\n");
+				scale_action = -1;
+			} else if (window->success_ratio >= IWL_RATE_INCREASE_TH) {
+				/* Lower rate has better
+				 * throughput,decrease rate */
+				scale_action = 1;
+			}
+		}
+	}
+
+	/* Sanity check; asked for decrease, but success rate or throughput
+	 * has been good at old rate.  Don't change it. */
+	if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
+		    ((window->success_ratio > IWL_RATE_HIGH_TH) ||
+		     (current_tpt > (100 * rs_sta->expected_tpt[low]))))
+		scale_action = 0;
+
+	switch (scale_action) {
+	case -1:
+
+		/* Decrese rate */
+		if (low != IWL_RATE_INVALID)
+			index = low;
+		break;
+
+	case 1:
+		/* Increase rate */
+		if (high != IWL_RATE_INVALID)
+			index = high;
+
+		break;
+
+	case 0:
+	default:
+		/* No change */
+		break;
+	}
+
+	IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n",
+		       index, scale_action, low, high);
+
+ out:
+
+	rs_sta->last_txrate_idx = index;
+	if (sband->band == IEEE80211_BAND_5GHZ)
+		info->control.rates[0].idx = rs_sta->last_txrate_idx -
+				IWL_FIRST_OFDM_RATE;
+	else
+		info->control.rates[0].idx = rs_sta->last_txrate_idx;
+
+	IWL_DEBUG_RATE(priv, "leave: %d\n", index);
+}
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
+						  char __user *user_buf,
+						  size_t count, loff_t *ppos)
+{
+	char *buff;
+	int desc = 0;
+	int j;
+	ssize_t ret;
+	struct iwl3945_rs_sta *lq_sta = file->private_data;
+
+	buff = kmalloc(1024, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
+			"rate=0x%X flush time %d\n",
+			lq_sta->tx_packets,
+			lq_sta->last_txrate_idx,
+			lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
+	for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
+		desc += sprintf(buff+desc,
+				"counter=%d success=%d %%=%d\n",
+				lq_sta->win[j].counter,
+				lq_sta->win[j].success_counter,
+				lq_sta->win[j].success_ratio);
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	kfree(buff);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+	.read = iwl3945_sta_dbgfs_stats_table_read,
+	.open = iwl3945_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static void iwl3945_add_debugfs(void *priv, void *priv_sta,
+				struct dentry *dir)
+{
+	struct iwl3945_rs_sta *lq_sta = priv_sta;
+
+	lq_sta->rs_sta_dbgfs_stats_table_file =
+		debugfs_create_file("rate_stats_table", 0600, dir,
+		lq_sta, &rs_sta_dbgfs_stats_table_ops);
+
+}
+
+static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
+{
+	struct iwl3945_rs_sta *lq_sta = priv_sta;
+	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
+}
+#endif
+
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void iwl3945_rs_rate_init_stub(void *priv_r,
+				struct ieee80211_supported_band *sband,
+			      struct ieee80211_sta *sta, void *priv_sta)
+{
+}
+
+static struct rate_control_ops rs_ops = {
+	.module = NULL,
+	.name = RS_NAME,
+	.tx_status = iwl3945_rs_tx_status,
+	.get_rate = iwl3945_rs_get_rate,
+	.rate_init = iwl3945_rs_rate_init_stub,
+	.alloc = iwl3945_rs_alloc,
+	.free = iwl3945_rs_free,
+	.alloc_sta = iwl3945_rs_alloc_sta,
+	.free_sta = iwl3945_rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+	.add_sta_debugfs = iwl3945_add_debugfs,
+	.remove_sta_debugfs = iwl3945_remove_debugfs,
+#endif
+
+};
+void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
+{
+	struct iwl_priv *priv = hw->priv;
+	s32 rssi = 0;
+	unsigned long flags;
+	struct iwl3945_rs_sta *rs_sta;
+	struct ieee80211_sta *sta;
+	struct iwl3945_sta_priv *psta;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+
+	rcu_read_lock();
+
+	sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
+				 priv->stations[sta_id].sta.sta.addr);
+	if (!sta) {
+		IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
+		rcu_read_unlock();
+		return;
+	}
+
+	psta = (void *) sta->drv_priv;
+	rs_sta = &psta->rs_sta;
+
+	spin_lock_irqsave(&rs_sta->lock, flags);
+
+	rs_sta->tgg = 0;
+	switch (priv->band) {
+	case IEEE80211_BAND_2GHZ:
+		/* TODO: this always does G, not a regression */
+		if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
+						RXON_FLG_TGG_PROTECT_MSK) {
+			rs_sta->tgg = 1;
+			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
+		} else
+			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
+		break;
+
+	case IEEE80211_BAND_5GHZ:
+		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
+		break;
+	case IEEE80211_NUM_BANDS:
+		BUG();
+		break;
+	}
+
+	spin_unlock_irqrestore(&rs_sta->lock, flags);
+
+	rssi = priv->_3945.last_rx_rssi;
+	if (rssi == 0)
+		rssi = IWL_MIN_RSSI_VAL;
+
+	IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi);
+
+	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
+
+	IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: "
+		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
+		       iwl3945_rates[rs_sta->start_rate].plcp);
+	rcu_read_unlock();
+}
+
+int iwl3945_rate_control_register(void)
+{
+	return ieee80211_rate_control_register(&rs_ops);
+}
+
+void iwl3945_rate_control_unregister(void)
+{
+	ieee80211_rate_control_unregister(&rs_ops);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl4965-base.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl4965-base.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl4965-base.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl4965-base.c	2012-03-24 03:33:23.000000000 -0400
@@ -0,0 +1,3626 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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
+ *
+ *****************************************************************************/
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci-aspm.h>
+#include <linux/slab.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <linux/firmware.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+
+#include <net/mac80211.h>
+
+#include <asm/div64.h>
+
+#define DRV_NAME        "iwl4965"
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-sta.h"
+#include "iwl-4965-calib.h"
+#include "iwl-4965.h"
+#include "iwl-4965-led.h"
+
+
+/******************************************************************************
+ *
+ * module boiler plate
+ *
+ ******************************************************************************/
+
+/*
+ * module name, copyright, version, etc.
+ */
+#define DRV_DESCRIPTION	"Intel(R) Wireless WiFi 4965 driver for Linux"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define VD "d"
+#else
+#define VD
+#endif
+
+#define DRV_VERSION     IWLWIFI_VERSION VD
+
+
+MODULE_DESCRIPTION(DRV_DESCRIPTION);
+MODULE_VERSION(DRV_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("iwl4965");
+
+void iwl4965_update_chain_flags(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain) {
+		for_each_context(priv, ctx) {
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+			if (ctx->active.rx_chain != ctx->staging.rx_chain)
+				iwl_legacy_commit_rxon(priv, ctx);
+		}
+	}
+}
+
+static void iwl4965_clear_free_frames(struct iwl_priv *priv)
+{
+	struct list_head *element;
+
+	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
+		       priv->frames_count);
+
+	while (!list_empty(&priv->free_frames)) {
+		element = priv->free_frames.next;
+		list_del(element);
+		kfree(list_entry(element, struct iwl_frame, list));
+		priv->frames_count--;
+	}
+
+	if (priv->frames_count) {
+		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
+			    priv->frames_count);
+		priv->frames_count = 0;
+	}
+}
+
+static struct iwl_frame *iwl4965_get_free_frame(struct iwl_priv *priv)
+{
+	struct iwl_frame *frame;
+	struct list_head *element;
+	if (list_empty(&priv->free_frames)) {
+		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
+		if (!frame) {
+			IWL_ERR(priv, "Could not allocate frame!\n");
+			return NULL;
+		}
+
+		priv->frames_count++;
+		return frame;
+	}
+
+	element = priv->free_frames.next;
+	list_del(element);
+	return list_entry(element, struct iwl_frame, list);
+}
+
+static void iwl4965_free_frame(struct iwl_priv *priv, struct iwl_frame *frame)
+{
+	memset(frame, 0, sizeof(*frame));
+	list_add(&frame->list, &priv->free_frames);
+}
+
+static u32 iwl4965_fill_beacon_frame(struct iwl_priv *priv,
+				 struct ieee80211_hdr *hdr,
+				 int left)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_skb)
+		return 0;
+
+	if (priv->beacon_skb->len > left)
+		return 0;
+
+	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
+
+	return priv->beacon_skb->len;
+}
+
+/* Parse the beacon frame to find the TIM element and set tim_idx & tim_size */
+static void iwl4965_set_beacon_tim(struct iwl_priv *priv,
+			       struct iwl_tx_beacon_cmd *tx_beacon_cmd,
+			       u8 *beacon, u32 frame_size)
+{
+	u16 tim_idx;
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)beacon;
+
+	/*
+	 * The index is relative to frame start but we start looking at the
+	 * variable-length part of the beacon.
+	 */
+	tim_idx = mgmt->u.beacon.variable - beacon;
+
+	/* Parse variable-length elements of beacon to find WLAN_EID_TIM */
+	while ((tim_idx < (frame_size - 2)) &&
+			(beacon[tim_idx] != WLAN_EID_TIM))
+		tim_idx += beacon[tim_idx+1] + 2;
+
+	/* If TIM field was found, set variables */
+	if ((tim_idx < (frame_size - 1)) && (beacon[tim_idx] == WLAN_EID_TIM)) {
+		tx_beacon_cmd->tim_idx = cpu_to_le16(tim_idx);
+		tx_beacon_cmd->tim_size = beacon[tim_idx+1];
+	} else
+		IWL_WARN(priv, "Unable to find TIM Element in beacon\n");
+}
+
+static unsigned int iwl4965_hw_get_beacon_cmd(struct iwl_priv *priv,
+				       struct iwl_frame *frame)
+{
+	struct iwl_tx_beacon_cmd *tx_beacon_cmd;
+	u32 frame_size;
+	u32 rate_flags;
+	u32 rate;
+	/*
+	 * We have to set up the TX command, the TX Beacon command, and the
+	 * beacon contents.
+	 */
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "trying to build beacon w/o beacon context!\n");
+		return 0;
+	}
+
+	/* Initialize memory */
+	tx_beacon_cmd = &frame->u.beacon;
+	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
+
+	/* Set up TX beacon contents */
+	frame_size = iwl4965_fill_beacon_frame(priv, tx_beacon_cmd->frame,
+				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
+	if (WARN_ON_ONCE(frame_size > MAX_MPDU_SIZE))
+		return 0;
+	if (!frame_size)
+		return 0;
+
+	/* Set up TX command fields */
+	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
+	tx_beacon_cmd->tx.sta_id = priv->beacon_ctx->bcast_sta_id;
+	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+	tx_beacon_cmd->tx.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK |
+		TX_CMD_FLG_TSF_MSK | TX_CMD_FLG_STA_RATE_MSK;
+
+	/* Set up TX beacon command fields */
+	iwl4965_set_beacon_tim(priv, tx_beacon_cmd, (u8 *)tx_beacon_cmd->frame,
+			   frame_size);
+
+	/* Set up packet rate and flags */
+	rate = iwl_legacy_get_lowest_plcp(priv, priv->beacon_ctx);
+	priv->mgmt_tx_ant = iwl4965_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+					      priv->hw_params.valid_tx_ant);
+	rate_flags = iwl4965_ant_idx_to_flags(priv->mgmt_tx_ant);
+	if ((rate >= IWL_FIRST_CCK_RATE) && (rate <= IWL_LAST_CCK_RATE))
+		rate_flags |= RATE_MCS_CCK_MSK;
+	tx_beacon_cmd->tx.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate,
+			rate_flags);
+
+	return sizeof(*tx_beacon_cmd) + frame_size;
+}
+
+int iwl4965_send_beacon_cmd(struct iwl_priv *priv)
+{
+	struct iwl_frame *frame;
+	unsigned int frame_size;
+	int rc;
+
+	frame = iwl4965_get_free_frame(priv);
+	if (!frame) {
+		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
+			  "command.\n");
+		return -ENOMEM;
+	}
+
+	frame_size = iwl4965_hw_get_beacon_cmd(priv, frame);
+	if (!frame_size) {
+		IWL_ERR(priv, "Error configuring the beacon command\n");
+		iwl4965_free_frame(priv, frame);
+		return -EINVAL;
+	}
+
+	rc = iwl_legacy_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
+			      &frame->u.cmd[0]);
+
+	iwl4965_free_frame(priv, frame);
+
+	return rc;
+}
+
+static inline dma_addr_t iwl4965_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	dma_addr_t addr = get_unaligned_le32(&tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		addr |=
+		((dma_addr_t)(le16_to_cpu(tb->hi_n_len) & 0xF) << 16) << 16;
+
+	return addr;
+}
+
+static inline u16 iwl4965_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+	return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
+static inline void iwl4965_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
+				  dma_addr_t addr, u16 len)
+{
+	struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+	u16 hi_n_len = len << 4;
+
+	put_unaligned_le32(addr, &tb->lo);
+	if (sizeof(dma_addr_t) > sizeof(u32))
+		hi_n_len |= ((addr >> 16) >> 16) & 0xF;
+
+	tb->hi_n_len = cpu_to_le16(hi_n_len);
+
+	tfd->num_tbs = idx + 1;
+}
+
+static inline u8 iwl4965_tfd_get_num_tbs(struct iwl_tfd *tfd)
+{
+	return tfd->num_tbs & 0x1f;
+}
+
+/**
+ * iwl4965_hw_txq_free_tfd - Free all chunks referenced by TFD [txq->q.read_ptr]
+ * @priv - driver private data
+ * @txq - tx queue
+ *
+ * Does NOT advance any TFD circular buffer read/write indexes
+ * Does NOT free the TFD itself (which is within circular buffer)
+ */
+void iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	struct iwl_tfd *tfd_tmp = (struct iwl_tfd *)txq->tfds;
+	struct iwl_tfd *tfd;
+	struct pci_dev *dev = priv->pci_dev;
+	int index = txq->q.read_ptr;
+	int i;
+	int num_tbs;
+
+	tfd = &tfd_tmp[index];
+
+	/* Sanity check on number of chunks */
+	num_tbs = iwl4965_tfd_get_num_tbs(tfd);
+
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERR(priv, "Too many chunks: %i\n", num_tbs);
+		/* @todo issue fatal error, it is quite serious situation */
+		return;
+	}
+
+	/* Unmap tx_cmd */
+	if (num_tbs)
+		pci_unmap_single(dev,
+				dma_unmap_addr(&txq->meta[index], mapping),
+				dma_unmap_len(&txq->meta[index], len),
+				PCI_DMA_BIDIRECTIONAL);
+
+	/* Unmap chunks, if any. */
+	for (i = 1; i < num_tbs; i++)
+		pci_unmap_single(dev, iwl4965_tfd_tb_get_addr(tfd, i),
+				iwl4965_tfd_tb_get_len(tfd, i),
+				PCI_DMA_TODEVICE);
+
+	/* free SKB */
+	if (txq->txb) {
+		struct sk_buff *skb;
+
+		skb = txq->txb[txq->q.read_ptr].skb;
+
+		/* can be called from irqs-disabled context */
+		if (skb) {
+			dev_kfree_skb_any(skb);
+			txq->txb[txq->q.read_ptr].skb = NULL;
+		}
+	}
+}
+
+int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				 struct iwl_tx_queue *txq,
+				 dma_addr_t addr, u16 len,
+				 u8 reset, u8 pad)
+{
+	struct iwl_queue *q;
+	struct iwl_tfd *tfd, *tfd_tmp;
+	u32 num_tbs;
+
+	q = &txq->q;
+	tfd_tmp = (struct iwl_tfd *)txq->tfds;
+	tfd = &tfd_tmp[q->write_ptr];
+
+	if (reset)
+		memset(tfd, 0, sizeof(*tfd));
+
+	num_tbs = iwl4965_tfd_get_num_tbs(tfd);
+
+	/* Each TFD can point to a maximum 20 Tx buffers */
+	if (num_tbs >= IWL_NUM_OF_TBS) {
+		IWL_ERR(priv, "Error can not send more than %d chunks\n",
+			  IWL_NUM_OF_TBS);
+		return -EINVAL;
+	}
+
+	BUG_ON(addr & ~DMA_BIT_MASK(36));
+	if (unlikely(addr & ~IWL_TX_DMA_MASK))
+		IWL_ERR(priv, "Unaligned address = %llx\n",
+			  (unsigned long long)addr);
+
+	iwl4965_tfd_set_tb(tfd, num_tbs, addr, len);
+
+	return 0;
+}
+
+/*
+ * Tell nic where to find circular buffer of Tx Frame Descriptors for
+ * given Tx queue, and enable the DMA channel used for that queue.
+ *
+ * 4965 supports up to 16 Tx queues in DRAM, mapped to up to 8 Tx DMA
+ * channels supported in hardware.
+ */
+int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
+			 struct iwl_tx_queue *txq)
+{
+	int txq_id = txq->q.id;
+
+	/* Circular buffer (TFD queue in DRAM) physical base address */
+	iwl_legacy_write_direct32(priv, FH_MEM_CBBC_QUEUE(txq_id),
+			     txq->q.dma_addr >> 8);
+
+	return 0;
+}
+
+/******************************************************************************
+ *
+ * Generic RX handler implementations
+ *
+ ******************************************************************************/
+static void iwl4965_rx_reply_alive(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_alive_resp *palive;
+	struct delayed_work *pwork;
+
+	palive = &pkt->u.alive_frame;
+
+	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+		       "0x%01X 0x%01X\n",
+		       palive->is_valid, palive->ver_type,
+		       palive->ver_subtype);
+
+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
+		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		memcpy(&priv->card_alive_init,
+		       &pkt->u.alive_frame,
+		       sizeof(struct iwl_init_alive_resp));
+		pwork = &priv->init_alive_start;
+	} else {
+		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->alive_start;
+	}
+
+	/* We delay the ALIVE response by 5ms to
+	 * give the HW RF Kill time to activate... */
+	if (palive->is_valid == UCODE_VALID_OK)
+		queue_delayed_work(priv->workqueue, pwork,
+				   msecs_to_jiffies(5));
+	else
+		IWL_WARN(priv, "uCode did not respond OK.\n");
+}
+
+/**
+ * iwl4965_bg_statistics_periodic - Timer callback to queue statistics
+ *
+ * This callback is provided in order to send a statistics request.
+ *
+ * This timer function is continually reset to execute within
+ * REG_RECALIB_PERIOD seconds since the last STATISTICS_NOTIFICATION
+ * was received.  We need to ensure we receive the statistics in order
+ * to update the temperature used for calibrating the TXPOWER.
+ */
+static void iwl4965_bg_statistics_periodic(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* dont send host command if rf-kill is on */
+	if (!iwl_legacy_is_ready_rf(priv))
+		return;
+
+	iwl_legacy_send_statistics_request(priv, CMD_ASYNC, false);
+}
+
+
+static void iwl4965_print_cont_event_trace(struct iwl_priv *priv, u32 base,
+					u32 start_idx, u32 num_events,
+					u32 mode)
+{
+	u32 i;
+	u32 ptr;        /* SRAM byte address of log data */
+	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
+
+	if (mode == 0)
+		ptr = base + (4 * sizeof(u32)) + (start_idx * 2 * sizeof(u32));
+	else
+		ptr = base + (4 * sizeof(u32)) + (start_idx * 3 * sizeof(u32));
+
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (iwl_grab_nic_access(priv)) {
+		spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+		return;
+	}
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
+	/*
+	 * "time" is actually "data" for mode 0 (no timestamp).
+	 * place event id # at far right for easier visual parsing.
+	 */
+	for (i = 0; i < num_events; i++) {
+		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (mode == 0) {
+			trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
+							0, time, ev);
+		} else {
+			data = _iwl_legacy_read_direct32(priv,
+						HBUS_TARG_MEM_RDAT);
+			trace_iwlwifi_legacy_dev_ucode_cont_event(priv,
+						time, data, ev);
+		}
+	}
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static void iwl4965_continuous_event_trace(struct iwl_priv *priv)
+{
+	u32 capacity;   /* event log capacity in # entries */
+	u32 base;       /* SRAM byte address of event log header */
+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+	u32 num_wraps;  /* # times uCode wrapped to top of log */
+	u32 next_entry; /* index of next entry to be written by uCode */
+
+	if (priv->ucode_type == UCODE_INIT)
+		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+	else
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	if (priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+		capacity = iwl_legacy_read_targ_mem(priv, base);
+		num_wraps = iwl_legacy_read_targ_mem(priv,
+						base + (2 * sizeof(u32)));
+		mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
+		next_entry = iwl_legacy_read_targ_mem(priv,
+						base + (3 * sizeof(u32)));
+	} else
+		return;
+
+	if (num_wraps == priv->event_log.num_wraps) {
+		iwl4965_print_cont_event_trace(priv,
+				       base, priv->event_log.next_entry,
+				       next_entry - priv->event_log.next_entry,
+				       mode);
+		priv->event_log.non_wraps_count++;
+	} else {
+		if ((num_wraps - priv->event_log.num_wraps) > 1)
+			priv->event_log.wraps_more_count++;
+		else
+			priv->event_log.wraps_once_count++;
+		trace_iwlwifi_legacy_dev_ucode_wrap_event(priv,
+				num_wraps - priv->event_log.num_wraps,
+				next_entry, priv->event_log.next_entry);
+		if (next_entry < priv->event_log.next_entry) {
+			iwl4965_print_cont_event_trace(priv, base,
+			       priv->event_log.next_entry,
+			       capacity - priv->event_log.next_entry,
+			       mode);
+
+			iwl4965_print_cont_event_trace(priv, base, 0,
+				next_entry, mode);
+		} else {
+			iwl4965_print_cont_event_trace(priv, base,
+			       next_entry, capacity - next_entry,
+			       mode);
+
+			iwl4965_print_cont_event_trace(priv, base, 0,
+				next_entry, mode);
+		}
+	}
+	priv->event_log.num_wraps = num_wraps;
+	priv->event_log.next_entry = next_entry;
+}
+
+/**
+ * iwl4965_bg_ucode_trace - Timer callback to log ucode event
+ *
+ * The timer is continually set to execute every
+ * UCODE_TRACE_PERIOD milliseconds after the last timer expired
+ * this function is to perform continuous uCode event logging operation
+ * if enabled
+ */
+static void iwl4965_bg_ucode_trace(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (priv->event_log.ucode_trace) {
+		iwl4965_continuous_event_trace(priv);
+		/* Reschedule the timer to occur in UCODE_TRACE_PERIOD */
+		mod_timer(&priv->ucode_trace,
+			 jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
+	}
+}
+
+static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl4965_beacon_notif *beacon =
+		(struct iwl4965_beacon_notif *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	u8 rate = iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
+		"tsf %d %d rate %d\n",
+		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+#endif
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+}
+
+static void iwl4965_perform_ct_kill_task(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	IWL_DEBUG_POWER(priv, "Stop all queues\n");
+
+	if (priv->mac80211_registered)
+		ieee80211_stop_queues(priv->hw);
+
+	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, flags);
+	if (!iwl_grab_nic_access(priv))
+		iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, flags);
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void iwl4965_rx_card_state_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+	unsigned long status = priv->status;
+
+	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & CT_CARD_DISABLED) ?
+			  "Reached" : "Not reached");
+
+	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
+		     CT_CARD_DISABLED)) {
+
+		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+		iwl_legacy_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);
+			iwl_legacy_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
+		}
+	}
+
+	if (flags & CT_CARD_DISABLED)
+		iwl4965_perform_ct_kill_task(priv);
+
+	if (flags & HW_CARD_DISABLED)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	if (!(flags & RXON_CARD_DISABLED))
+		iwl_legacy_scan_cancel(priv);
+
+	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
+	     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);
+}
+
+/**
+ * iwl4965_setup_rx_handlers - Initialize Rx handler callbacks
+ *
+ * Setup the RX handlers for each of the reply types sent from the uCode
+ * to the host.
+ *
+ * This function chains into the hardware specific files for them to setup
+ * any hardware specific handlers as well.
+ */
+static void iwl4965_setup_rx_handlers(struct iwl_priv *priv)
+{
+	priv->rx_handlers[REPLY_ALIVE] = iwl4965_rx_reply_alive;
+	priv->rx_handlers[REPLY_ERROR] = iwl_legacy_rx_reply_error;
+	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_legacy_rx_csa;
+	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
+			iwl_legacy_rx_spectrum_measure_notif;
+	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_legacy_rx_pm_sleep_notif;
+	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
+	    iwl_legacy_rx_pm_debug_statistics_notif;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+
+	/*
+	 * The same handler is used for both the REPLY to a discrete
+	 * statistics request from the host as well as for the periodic
+	 * statistics notifications (after received beacons) from the uCode.
+	 */
+	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl4965_reply_statistics;
+	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl4965_rx_statistics;
+
+	iwl_legacy_setup_rx_scan_handlers(priv);
+
+	/* status change handler */
+	priv->rx_handlers[CARD_STATE_NOTIFICATION] =
+					iwl4965_rx_card_state_notif;
+
+	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
+	    iwl4965_rx_missed_beacon_notif;
+	/* Rx handlers */
+	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwl4965_rx_reply_rx_phy;
+	priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwl4965_rx_reply_rx;
+	/* block ack */
+	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwl4965_rx_reply_compressed_ba;
+	/* Set up hardware specific Rx handlers */
+	priv->cfg->ops->lib->rx_handler_setup(priv);
+}
+
+/**
+ * iwl4965_rx_handle - Main entry function for receiving responses from uCode
+ *
+ * Uses the priv->rx_handlers callback function array to invoke
+ * the appropriate handlers, including command responses,
+ * frame-received notifications, and other notifications.
+ */
+void iwl4965_rx_handle(struct iwl_priv *priv)
+{
+	struct iwl_rx_mem_buffer *rxb;
+	struct iwl_rx_packet *pkt;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	u32 r, i;
+	int reclaim;
+	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). */
+	r = le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF;
+	i = rxq->read;
+
+	/* Rx interrupt, but nothing sent from uCode */
+	if (i == r)
+		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
+
+	/* calculate total frames need to be restock after handling RX */
+	total_empty = r - 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) {
+		int len;
+
+		rxb = rxq->queue[i];
+
+		/* If an RXB doesn't have a Rx queue slot associated with it,
+		 * then a bug has been introduced in the queue refilling
+		 * routines -- catch it here */
+		BUG_ON(rxb == NULL);
+
+		rxq->queue[i] = NULL;
+
+		pci_unmap_page(priv->pci_dev, rxb->page_dma,
+			       PAGE_SIZE << priv->hw_params.rx_page_order,
+			       PCI_DMA_FROMDEVICE);
+		pkt = rxb_addr(rxb);
+
+		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+		len += sizeof(u32); /* account for status word */
+		trace_iwlwifi_legacy_dev_rx(priv, pkt, len);
+
+		/* Reclaim a command buffer only if this packet is a response
+		 *   to a (driver-originated) command.
+		 * If the packet (e.g. Rx frame) originated from uCode,
+		 *   there is no command buffer to reclaim.
+		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
+		 *   but apparently a few don't get set; catch them here. */
+		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
+			(pkt->hdr.cmd != REPLY_RX_PHY_CMD) &&
+			(pkt->hdr.cmd != REPLY_RX) &&
+			(pkt->hdr.cmd != REPLY_RX_MPDU_CMD) &&
+			(pkt->hdr.cmd != REPLY_COMPRESSED_BA) &&
+			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
+			(pkt->hdr.cmd != REPLY_TX);
+
+		/* Based on type of command response or notification,
+		 *   handle those that need handling via function in
+		 *   rx_handlers table.  See iwl4965_setup_rx_handlers() */
+		if (priv->rx_handlers[pkt->hdr.cmd]) {
+			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r,
+				i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
+			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
+		} else {
+			/* No handling needed */
+			IWL_DEBUG_RX(priv,
+				"r %d i %d No handler needed for %s, 0x%02x\n",
+				r, i, iwl_legacy_get_cmd_string(pkt->hdr.cmd),
+				pkt->hdr.cmd);
+		}
+
+		/*
+		 * XXX: After here, we should always check rxb->page
+		 * against NULL before touching it or its virtual
+		 * memory (pkt). Because some rx_handler might have
+		 * already taken or freed the pages.
+		 */
+
+		if (reclaim) {
+			/* Invoke any callbacks, transfer the buffer to caller,
+			 * and fire off the (possibly) blocking iwl_legacy_send_cmd()
+			 * as we reclaim the driver command queue */
+			if (rxb->page)
+				iwl_legacy_tx_cmd_complete(priv, rxb);
+			else
+				IWL_WARN(priv, "Claim null rxb?\n");
+		}
+
+		/* Reuse the page if possible. For notification packets and
+		 * SKBs that fail to Rx correctly, add them back into the
+		 * rx_free list for reuse later. */
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (rxb->page != NULL) {
+			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
+				0, PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			list_add_tail(&rxb->list, &rxq->rx_free);
+			rxq->free_count++;
+		} else
+			list_add_tail(&rxb->list, &rxq->rx_used);
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		i = (i + 1) & RX_QUEUE_MASK;
+		/* If there are a lot of unused frames,
+		 * restock the Rx queue so ucode wont assert. */
+		if (fill_rx) {
+			count++;
+			if (count >= 8) {
+				rxq->read = i;
+				iwl4965_rx_replenish_now(priv);
+				count = 0;
+			}
+		}
+	}
+
+	/* Backtrack one entry */
+	rxq->read = i;
+	if (fill_rx)
+		iwl4965_rx_replenish_now(priv);
+	else
+		iwl4965_rx_queue_restock(priv);
+}
+
+/* call this function to flush any scheduled tasklet */
+static inline void iwl4965_synchronize_irq(struct iwl_priv *priv)
+{
+	/* wait to make sure we flush pending tasklet*/
+	synchronize_irq(priv->pci_dev->irq);
+	tasklet_kill(&priv->irq_tasklet);
+}
+
+static void iwl4965_irq_tasklet(struct iwl_priv *priv)
+{
+	u32 inta, handled = 0;
+	u32 inta_fh;
+	unsigned long flags;
+	u32 i;
+#ifdef CONFIG_IWLWIFI_LEGACY_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,
+	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
+	inta = iwl_read32(priv, CSR_INT);
+	iwl_write32(priv, CSR_INT, inta);
+
+	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
+	 * Any new interrupts that happen after this, either while we're
+	 * in this tasklet, or later, will show up in next ISR/tasklet. */
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & IWL_DL_ISR) {
+		/* just for debug */
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+			      inta, inta_mask, inta_fh);
+	}
+#endif
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
+	 * atomic, make sure that inta covers all the interrupts that
+	 * we've discovered, even if FH interrupt came in just after
+	 * reading CSR_INT. */
+	if (inta_fh & CSR49_FH_INT_RX_MASK)
+		inta |= CSR_INT_BIT_FH_RX;
+	if (inta_fh & CSR49_FH_INT_TX_MASK)
+		inta |= CSR_INT_BIT_FH_TX;
+
+	/* Now service all interrupt bits discovered above. */
+	if (inta & CSR_INT_BIT_HW_ERR) {
+		IWL_ERR(priv, "Hardware error detected.  Restarting.\n");
+
+		/* Tell the device to stop sending interrupts */
+		iwl_legacy_disable_interrupts(priv);
+
+		priv->isr_stats.hw++;
+		iwl_legacy_irq_handle_error(priv);
+
+		handled |= CSR_INT_BIT_HW_ERR;
+
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (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_WARN(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++;
+		iwl_legacy_irq_handle_error(priv);
+		handled |= CSR_INT_BIT_SW_ERR;
+	}
+
+	/*
+	 * uCode wakes up after power-down sleep.
+	 * Tell device about any new tx or host commands enqueued,
+	 * and about any Rx buffers made available while asleep.
+	 */
+	if (inta & CSR_INT_BIT_WAKEUP) {
+		IWL_DEBUG_ISR(priv, "Wakeup interrupt\n");
+		iwl_legacy_rx_queue_update_write_ptr(priv, &priv->rxq);
+		for (i = 0; i < priv->hw_params.max_txq_num; i++)
+			iwl_legacy_txq_update_write_ptr(priv, &priv->txq[i]);
+		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)) {
+		iwl4965_rx_handle(priv);
+		priv->isr_stats.rx++;
+		handled |= (CSR_INT_BIT_FH_RX | CSR_INT_BIT_SW_RX);
+	}
+
+	/* This "Tx" DMA channel is used only for loading uCode */
+	if (inta & CSR_INT_BIT_FH_TX) {
+		IWL_DEBUG_ISR(priv, "uCode load interrupt\n");
+		priv->isr_stats.tx++;
+		handled |= CSR_INT_BIT_FH_TX;
+		/* Wake up uCode load routine, now that load is complete */
+		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);
+		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
+	}
+
+	/* Re-enable all interrupts */
+	/* only Re-enable if diabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_legacy_enable_interrupts(priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & (IWL_DL_ISR)) {
+		inta = iwl_read32(priv, CSR_INT);
+		inta_mask = iwl_read32(priv, CSR_INT_MASK);
+		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+		IWL_DEBUG_ISR(priv,
+			"End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
+			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
+	}
+#endif
+}
+
+/*****************************************************************************
+ *
+ * sysfs attributes
+ *
+ *****************************************************************************/
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+
+/*
+ * The following adds a new attribute to the sysfs representation
+ * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/)
+ * used for controlling the debug level.
+ *
+ * See the level definitions in iwl for details.
+ *
+ * The debug_level being managed using sysfs below is a per device debug
+ * level that is used instead of the global debug level if it (the per
+ * device debug level) is set.
+ */
+static ssize_t iwl4965_show_debug_level(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	return sprintf(buf, "0x%08X\n", iwl_legacy_get_debug_level(priv));
+}
+static ssize_t iwl4965_store_debug_level(struct device *d,
+				struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 0, &val);
+	if (ret)
+		IWL_ERR(priv, "%s is not in hex or decimal form.\n", buf);
+	else {
+		priv->debug_level = val;
+		if (iwl_legacy_alloc_traffic_mem(priv))
+			IWL_ERR(priv,
+				"Not enough memory to generate traffic log\n");
+	}
+	return strnlen(buf, count);
+}
+
+static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
+			iwl4965_show_debug_level, iwl4965_store_debug_level);
+
+
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
+
+
+static ssize_t iwl4965_show_temperature(struct device *d,
+				struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	return sprintf(buf, "%d\n", priv->temperature);
+}
+
+static DEVICE_ATTR(temperature, S_IRUGO, iwl4965_show_temperature, NULL);
+
+static ssize_t iwl4965_show_tx_power(struct device *d,
+			     struct device_attribute *attr, char *buf)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+
+	if (!iwl_legacy_is_ready_rf(priv))
+		return sprintf(buf, "off\n");
+	else
+		return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
+}
+
+static ssize_t iwl4965_store_tx_power(struct device *d,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct iwl_priv *priv = dev_get_drvdata(d);
+	unsigned long val;
+	int ret;
+
+	ret = strict_strtoul(buf, 10, &val);
+	if (ret)
+		IWL_INFO(priv, "%s is not in decimal form.\n", buf);
+	else {
+		ret = iwl_legacy_set_tx_power(priv, val, false);
+		if (ret)
+			IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+				ret);
+		else
+			ret = count;
+	}
+	return ret;
+}
+
+static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO,
+			iwl4965_show_tx_power, iwl4965_store_tx_power);
+
+static struct attribute *iwl_sysfs_entries[] = {
+	&dev_attr_temperature.attr,
+	&dev_attr_tx_power.attr,
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	&dev_attr_debug_level.attr,
+#endif
+	NULL
+};
+
+static struct attribute_group iwl_attribute_group = {
+	.name = NULL,		/* put in device directory */
+	.attrs = iwl_sysfs_entries,
+};
+
+/******************************************************************************
+ *
+ * uCode download functions
+ *
+ ******************************************************************************/
+
+static void iwl4965_dealloc_ucode_pci(struct iwl_priv *priv)
+{
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_code);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+	iwl_legacy_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
+}
+
+static void iwl4965_nic_start(struct iwl_priv *priv)
+{
+	/* Remove all resets to allow NIC to operate */
+	iwl_write32(priv, CSR_RESET, 0);
+}
+
+static void iwl4965_ucode_callback(const struct firmware *ucode_raw,
+					void *context);
+static int iwl4965_mac_setup_register(struct iwl_priv *priv,
+						u32 max_probe_length);
+
+static int __must_check iwl4965_reject_firmware(struct iwl_priv *priv, bool first)
+{
+	const char *name_pre = priv->cfg->fw_name_pre;
+	char tag[8];
+
+	if (first) {
+		priv->fw_index = priv->cfg->ucode_api_max;
+		sprintf(tag, "%d", priv->fw_index);
+	} else {
+		priv->fw_index--;
+		sprintf(tag, "%d", priv->fw_index);
+	}
+
+	if (priv->fw_index < priv->cfg->ucode_api_min) {
+		IWL_ERR(priv, "no suitable firmware found!\n");
+		return -ENOENT;
+	}
+
+	sprintf(priv->firmware_name, "/*(DEBLOBBED)*/");
+
+	IWL_DEBUG_INFO(priv, "attempting to load firmware '%s'\n",
+		       priv->firmware_name);
+
+	return reject_firmware_nowait(THIS_MODULE, 1, priv->firmware_name,
+				       &priv->pci_dev->dev, GFP_KERNEL, priv,
+				       iwl4965_ucode_callback);
+}
+
+struct iwl4965_firmware_pieces {
+	const void *inst, *data, *init, *init_data, *boot;
+	size_t inst_size, data_size, init_size, init_data_size, boot_size;
+};
+
+static int iwl4965_load_firmware(struct iwl_priv *priv,
+				       const struct firmware *ucode_raw,
+				       struct iwl4965_firmware_pieces *pieces)
+{
+	struct iwl_ucode_header *ucode = (void *)ucode_raw->data;
+	u32 api_ver, hdr_size;
+	const u8 *src;
+
+	priv->ucode_ver = le32_to_cpu(ucode->ver);
+	api_ver = IWL_UCODE_API(priv->ucode_ver);
+
+	switch (api_ver) {
+	default:
+	case 0:
+	case 1:
+	case 2:
+		hdr_size = 24;
+		if (ucode_raw->size < hdr_size) {
+			IWL_ERR(priv, "File size too small!\n");
+			return -EINVAL;
+		}
+		pieces->inst_size = le32_to_cpu(ucode->v1.inst_size);
+		pieces->data_size = le32_to_cpu(ucode->v1.data_size);
+		pieces->init_size = le32_to_cpu(ucode->v1.init_size);
+		pieces->init_data_size =
+				le32_to_cpu(ucode->v1.init_data_size);
+		pieces->boot_size = le32_to_cpu(ucode->v1.boot_size);
+		src = ucode->v1.data;
+		break;
+	}
+
+	/* Verify size of file vs. image size info in file's header */
+	if (ucode_raw->size != hdr_size + pieces->inst_size +
+				pieces->data_size + pieces->init_size +
+				pieces->init_data_size + pieces->boot_size) {
+
+		IWL_ERR(priv,
+			"uCode file size %d does not match expected size\n",
+			(int)ucode_raw->size);
+		return -EINVAL;
+	}
+
+	pieces->inst = src;
+	src += pieces->inst_size;
+	pieces->data = src;
+	src += pieces->data_size;
+	pieces->init = src;
+	src += pieces->init_size;
+	pieces->init_data = src;
+	src += pieces->init_data_size;
+	pieces->boot = src;
+	src += pieces->boot_size;
+
+	return 0;
+}
+
+/**
+ * iwl4965_ucode_callback - callback when firmware was loaded
+ *
+ * If loaded successfully, copies the firmware into buffers
+ * for the card to fetch (via DMA).
+ */
+static void
+iwl4965_ucode_callback(const struct firmware *ucode_raw, void *context)
+{
+	struct iwl_priv *priv = context;
+	struct iwl_ucode_header *ucode;
+	int err;
+	struct iwl4965_firmware_pieces pieces;
+	const unsigned int api_max = priv->cfg->ucode_api_max;
+	const unsigned int api_min = priv->cfg->ucode_api_min;
+	u32 api_ver;
+
+	u32 max_probe_length = 200;
+	u32 standard_phy_calibration_size =
+			IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE;
+
+	memset(&pieces, 0, sizeof(pieces));
+
+	if (!ucode_raw) {
+		if (priv->fw_index <= priv->cfg->ucode_api_max)
+			IWL_ERR(priv,
+				"request for firmware file '%s' failed.\n",
+				priv->firmware_name);
+		goto try_again;
+	}
+
+	IWL_DEBUG_INFO(priv, "Loaded firmware file '%s' (%zd bytes).\n",
+		       priv->firmware_name, ucode_raw->size);
+
+	/* Make sure that we got at least the API version number */
+	if (ucode_raw->size < 4) {
+		IWL_ERR(priv, "File size way too small!\n");
+		goto try_again;
+	}
+
+	/* Data from ucode file:  header followed by uCode images */
+	ucode = (struct iwl_ucode_header *)ucode_raw->data;
+
+	err = iwl4965_load_firmware(priv, ucode_raw, &pieces);
+
+	if (err)
+		goto try_again;
+
+	api_ver = IWL_UCODE_API(priv->ucode_ver);
+
+	/*
+	 * api_ver should match the api version forming part of the
+	 * firmware filename ... but we don't check for that and only rely
+	 * on the API version read from firmware header from here on forward
+	 */
+	if (api_ver < api_min || api_ver > api_max) {
+		IWL_ERR(priv,
+			"Driver unable to support your firmware API. "
+			"Driver supports v%u, firmware is v%u.\n",
+			api_max, api_ver);
+		goto try_again;
+	}
+
+	if (api_ver != api_max)
+		IWL_ERR(priv,
+			"Firmware has old API version. Expected v%u, "
+			"got v%u. New firmware can be obtained "
+			"from http://www.intellinuxwireless.org.\n",
+			api_max, api_ver);
+
+	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
+		 IWL_UCODE_MAJOR(priv->ucode_ver),
+		 IWL_UCODE_MINOR(priv->ucode_ver),
+		 IWL_UCODE_API(priv->ucode_ver),
+		 IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	snprintf(priv->hw->wiphy->fw_version,
+		 sizeof(priv->hw->wiphy->fw_version),
+		 "%u.%u.%u.%u",
+		 IWL_UCODE_MAJOR(priv->ucode_ver),
+		 IWL_UCODE_MINOR(priv->ucode_ver),
+		 IWL_UCODE_API(priv->ucode_ver),
+		 IWL_UCODE_SERIAL(priv->ucode_ver));
+
+	/*
+	 * For any of the failures below (before allocating pci memory)
+	 * we will try to load a version with a smaller API -- maybe the
+	 * user just got a corrupted version of the latest API.
+	 */
+
+	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
+		       priv->ucode_ver);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %Zd\n",
+		       pieces.inst_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %Zd\n",
+		       pieces.data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %Zd\n",
+		       pieces.init_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %Zd\n",
+		       pieces.init_data_size);
+	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %Zd\n",
+		       pieces.boot_size);
+
+	/* Verify that uCode images will fit in card's SRAM */
+	if (pieces.inst_size > priv->hw_params.max_inst_size) {
+		IWL_ERR(priv, "uCode instr len %Zd too large to fit in\n",
+			pieces.inst_size);
+		goto try_again;
+	}
+
+	if (pieces.data_size > priv->hw_params.max_data_size) {
+		IWL_ERR(priv, "uCode data len %Zd too large to fit in\n",
+			pieces.data_size);
+		goto try_again;
+	}
+
+	if (pieces.init_size > priv->hw_params.max_inst_size) {
+		IWL_ERR(priv, "uCode init instr len %Zd too large to fit in\n",
+			pieces.init_size);
+		goto try_again;
+	}
+
+	if (pieces.init_data_size > priv->hw_params.max_data_size) {
+		IWL_ERR(priv, "uCode init data len %Zd too large to fit in\n",
+			pieces.init_data_size);
+		goto try_again;
+	}
+
+	if (pieces.boot_size > priv->hw_params.max_bsm_size) {
+		IWL_ERR(priv, "uCode boot instr len %Zd too large to fit in\n",
+			pieces.boot_size);
+		goto try_again;
+	}
+
+	/* Allocate ucode buffers for card's bus-master loading ... */
+
+	/* Runtime instructions and 2 copies of data:
+	 * 1) unmodified from disk
+	 * 2) backup cache for save/restore during power-downs */
+	priv->ucode_code.len = pieces.inst_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
+
+	priv->ucode_data.len = pieces.data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
+
+	priv->ucode_data_backup.len = pieces.data_size;
+	iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
+
+	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
+	    !priv->ucode_data_backup.v_addr)
+		goto err_pci_alloc;
+
+	/* Initialization instructions and data */
+	if (pieces.init_size && pieces.init_data_size) {
+		priv->ucode_init.len = pieces.init_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
+
+		priv->ucode_init_data.len = pieces.init_data_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
+
+		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Bootstrap (instructions only, no data) */
+	if (pieces.boot_size) {
+		priv->ucode_boot.len = pieces.boot_size;
+		iwl_legacy_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
+
+		if (!priv->ucode_boot.v_addr)
+			goto err_pci_alloc;
+	}
+
+	/* Now that we can no longer fail, copy information */
+
+	priv->sta_key_max_num = STA_KEY_MAX_NUM;
+
+	/* Copy images into buffers for card's bus-master reads ... */
+
+	/* Runtime instructions (first block of data in file) */
+	IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode instr len %Zd\n",
+			pieces.inst_size);
+	memcpy(priv->ucode_code.v_addr, pieces.inst, pieces.inst_size);
+
+	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
+		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
+
+	/*
+	 * Runtime data
+	 * NOTE:  Copy into backup buffer will be done in iwl_up()
+	 */
+	IWL_DEBUG_INFO(priv, "Copying (but not loading) uCode data len %Zd\n",
+			pieces.data_size);
+	memcpy(priv->ucode_data.v_addr, pieces.data, pieces.data_size);
+	memcpy(priv->ucode_data_backup.v_addr, pieces.data, pieces.data_size);
+
+	/* Initialization instructions */
+	if (pieces.init_size) {
+		IWL_DEBUG_INFO(priv,
+				"Copying (but not loading) init instr len %Zd\n",
+				pieces.init_size);
+		memcpy(priv->ucode_init.v_addr, pieces.init, pieces.init_size);
+	}
+
+	/* Initialization data */
+	if (pieces.init_data_size) {
+		IWL_DEBUG_INFO(priv,
+				"Copying (but not loading) init data len %Zd\n",
+			       pieces.init_data_size);
+		memcpy(priv->ucode_init_data.v_addr, pieces.init_data,
+		       pieces.init_data_size);
+	}
+
+	/* Bootstrap instructions */
+	IWL_DEBUG_INFO(priv, "Copying (but not loading) boot instr len %Zd\n",
+			pieces.boot_size);
+	memcpy(priv->ucode_boot.v_addr, pieces.boot, pieces.boot_size);
+
+	/*
+	 * figure out the offset of chain noise reset and gain commands
+	 * base on the size of standard phy calibration commands table size
+	 */
+	priv->_4965.phy_calib_chain_noise_reset_cmd =
+		standard_phy_calibration_size;
+	priv->_4965.phy_calib_chain_noise_gain_cmd =
+		standard_phy_calibration_size + 1;
+
+	/**************************************************
+	 * This is still part of probe() in a sense...
+	 *
+	 * 9. Setup and register with mac80211 and debugfs
+	 **************************************************/
+	err = iwl4965_mac_setup_register(priv, max_probe_length);
+	if (err)
+		goto out_unbind;
+
+	err = iwl_legacy_dbgfs_register(priv, DRV_NAME);
+	if (err)
+		IWL_ERR(priv,
+		"failed to create debugfs files. Ignoring error: %d\n", err);
+
+	err = sysfs_create_group(&priv->pci_dev->dev.kobj,
+					&iwl_attribute_group);
+	if (err) {
+		IWL_ERR(priv, "failed to create sysfs device attributes\n");
+		goto out_unbind;
+	}
+
+	/* We have our copies now, allow OS release its copies */
+	release_firmware(ucode_raw);
+	complete(&priv->_4965.firmware_loading_complete);
+	return;
+
+ try_again:
+	/* try next, if any */
+	if (iwl4965_reject_firmware(priv, false))
+		goto out_unbind;
+	release_firmware(ucode_raw);
+	return;
+
+ err_pci_alloc:
+	IWL_ERR(priv, "failed to allocate pci memory\n");
+	iwl4965_dealloc_ucode_pci(priv);
+ out_unbind:
+	complete(&priv->_4965.firmware_loading_complete);
+	device_release_driver(&priv->pci_dev->dev);
+	release_firmware(ucode_raw);
+}
+
+static const char * const desc_lookup_text[] = {
+	"OK",
+	"FAIL",
+	"BAD_PARAM",
+	"BAD_CHECKSUM",
+	"NMI_INTERRUPT_WDG",
+	"SYSASSERT",
+	"FATAL_ERROR",
+	"BAD_COMMAND",
+	"HW_ERROR_TUNE_LOCK",
+	"HW_ERROR_TEMPERATURE",
+	"ILLEGAL_CHAN_FREQ",
+	"VCC_NOT_STABLE",
+	"FH_ERROR",
+	"NMI_INTERRUPT_HOST",
+	"NMI_INTERRUPT_ACTION_PT",
+	"NMI_INTERRUPT_UNKNOWN",
+	"UCODE_VERSION_MISMATCH",
+	"HW_ERROR_ABS_LOCK",
+	"HW_ERROR_CAL_LOCK_FAIL",
+	"NMI_INTERRUPT_INST_ACTION_PT",
+	"NMI_INTERRUPT_DATA_ACTION_PT",
+	"NMI_TRM_HW_ER",
+	"NMI_INTERRUPT_TRM",
+	"NMI_INTERRUPT_BREAK_POINT"
+	"DEBUG_0",
+	"DEBUG_1",
+	"DEBUG_2",
+	"DEBUG_3",
+};
+
+static struct { char *name; u8 num; } advanced_lookup[] = {
+	{ "NMI_INTERRUPT_WDG", 0x34 },
+	{ "SYSASSERT", 0x35 },
+	{ "UCODE_VERSION_MISMATCH", 0x37 },
+	{ "BAD_COMMAND", 0x38 },
+	{ "NMI_INTERRUPT_DATA_ACTION_PT", 0x3C },
+	{ "FATAL_ERROR", 0x3D },
+	{ "NMI_TRM_HW_ERR", 0x46 },
+	{ "NMI_INTERRUPT_TRM", 0x4C },
+	{ "NMI_INTERRUPT_BREAK_POINT", 0x54 },
+	{ "NMI_INTERRUPT_WDG_RXF_FULL", 0x5C },
+	{ "NMI_INTERRUPT_WDG_NO_RBD_RXF_FULL", 0x64 },
+	{ "NMI_INTERRUPT_HOST", 0x66 },
+	{ "NMI_INTERRUPT_ACTION_PT", 0x7C },
+	{ "NMI_INTERRUPT_UNKNOWN", 0x84 },
+	{ "NMI_INTERRUPT_INST_ACTION_PT", 0x86 },
+	{ "ADVANCED_SYSASSERT", 0 },
+};
+
+static const char *iwl4965_desc_lookup(u32 num)
+{
+	int i;
+	int max = ARRAY_SIZE(desc_lookup_text);
+
+	if (num < max)
+		return desc_lookup_text[num];
+
+	max = ARRAY_SIZE(advanced_lookup) - 1;
+	for (i = 0; i < max; i++) {
+		if (advanced_lookup[i].num == num)
+			break;
+	}
+	return advanced_lookup[i].name;
+}
+
+#define ERROR_START_OFFSET  (1 * sizeof(u32))
+#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
+
+void iwl4965_dump_nic_error_log(struct iwl_priv *priv)
+{
+	u32 data2, line;
+	u32 desc, time, count, base, data1;
+	u32 blink1, blink2, ilink1, ilink2;
+	u32 pc, hcmd;
+
+	if (priv->ucode_type == UCODE_INIT) {
+		base = le32_to_cpu(priv->card_alive_init.error_event_table_ptr);
+	} else {
+		base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
+	}
+
+	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv,
+			"Not valid error log pointer 0x%08X for %s uCode\n",
+			base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
+		return;
+	}
+
+	count = iwl_legacy_read_targ_mem(priv, base);
+
+	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
+		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
+		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
+			priv->status, count);
+	}
+
+	desc = iwl_legacy_read_targ_mem(priv, base + 1 * sizeof(u32));
+	priv->isr_stats.err_code = desc;
+	pc = iwl_legacy_read_targ_mem(priv, base + 2 * sizeof(u32));
+	blink1 = iwl_legacy_read_targ_mem(priv, base + 3 * sizeof(u32));
+	blink2 = iwl_legacy_read_targ_mem(priv, base + 4 * sizeof(u32));
+	ilink1 = iwl_legacy_read_targ_mem(priv, base + 5 * sizeof(u32));
+	ilink2 = iwl_legacy_read_targ_mem(priv, base + 6 * sizeof(u32));
+	data1 = iwl_legacy_read_targ_mem(priv, base + 7 * sizeof(u32));
+	data2 = iwl_legacy_read_targ_mem(priv, base + 8 * sizeof(u32));
+	line = iwl_legacy_read_targ_mem(priv, base + 9 * sizeof(u32));
+	time = iwl_legacy_read_targ_mem(priv, base + 11 * sizeof(u32));
+	hcmd = iwl_legacy_read_targ_mem(priv, base + 22 * sizeof(u32));
+
+	trace_iwlwifi_legacy_dev_ucode_error(priv, desc,
+					time, data1, data2, line,
+				      blink1, blink2, ilink1, ilink2);
+
+	IWL_ERR(priv, "Desc                                  Time       "
+		"data1      data2      line\n");
+	IWL_ERR(priv, "%-28s (0x%04X) %010u 0x%08X 0x%08X %u\n",
+		iwl4965_desc_lookup(desc), desc, time, data1, data2, line);
+	IWL_ERR(priv, "pc      blink1  blink2  ilink1  ilink2  hcmd\n");
+	IWL_ERR(priv, "0x%05X 0x%05X 0x%05X 0x%05X 0x%05X 0x%05X\n",
+		pc, blink1, blink2, ilink1, ilink2, hcmd);
+}
+
+#define EVENT_START_OFFSET  (4 * sizeof(u32))
+
+/**
+ * iwl4965_print_event_log - Dump error event log to syslog
+ *
+ */
+static int iwl4965_print_event_log(struct iwl_priv *priv, u32 start_idx,
+			       u32 num_events, u32 mode,
+			       int pos, char **buf, size_t bufsz)
+{
+	u32 i;
+	u32 base;       /* SRAM byte address of event log header */
+	u32 event_size; /* 2 u32s, or 3 u32s if timestamp recorded */
+	u32 ptr;        /* SRAM byte address of log data */
+	u32 ev, time, data; /* event log data */
+	unsigned long reg_flags;
+
+	if (num_events == 0)
+		return pos;
+
+	if (priv->ucode_type == UCODE_INIT) {
+		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+	} else {
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	}
+
+	if (mode == 0)
+		event_size = 2 * sizeof(u32);
+	else
+		event_size = 3 * sizeof(u32);
+
+	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
+
+	/* Make sure device is powered up for SRAM reads */
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	/* Set starting address; reads will auto-increment */
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
+	rmb();
+
+	/* "time" is actually "data" for mode 0 (no timestamp).
+	* place event id # at far right for easier visual parsing. */
+	for (i = 0; i < num_events; i++) {
+		ev = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		time = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (mode == 0) {
+			/* data, ev */
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"EVT_LOG:0x%08x:%04u\n",
+						time, ev);
+			} else {
+				trace_iwlwifi_legacy_dev_ucode_event(priv, 0,
+					time, ev);
+				IWL_ERR(priv, "EVT_LOG:0x%08x:%04u\n",
+					time, ev);
+			}
+		} else {
+			data = _iwl_legacy_read_direct32(priv,
+						HBUS_TARG_MEM_RDAT);
+			if (bufsz) {
+				pos += scnprintf(*buf + pos, bufsz - pos,
+						"EVT_LOGT:%010u:0x%08x:%04u\n",
+						 time, data, ev);
+			} else {
+				IWL_ERR(priv, "EVT_LOGT:%010u:0x%08x:%04u\n",
+					time, data, ev);
+				trace_iwlwifi_legacy_dev_ucode_event(priv, time,
+					data, ev);
+			}
+		}
+	}
+
+	/* Allow device to power down */
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return pos;
+}
+
+/**
+ * iwl4965_print_last_event_logs - Dump the newest # of event log to syslog
+ */
+static int iwl4965_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
+				    u32 num_wraps, u32 next_entry,
+				    u32 size, u32 mode,
+				    int pos, char **buf, size_t bufsz)
+{
+	/*
+	 * display the newest DEFAULT_LOG_ENTRIES entries
+	 * i.e the entries just before the next ont that uCode would fill.
+	 */
+	if (num_wraps) {
+		if (next_entry < size) {
+			pos = iwl4965_print_event_log(priv,
+						capacity - (size - next_entry),
+						size - next_entry, mode,
+						pos, buf, bufsz);
+			pos = iwl4965_print_event_log(priv, 0,
+						  next_entry, mode,
+						  pos, buf, bufsz);
+		} else
+			pos = iwl4965_print_event_log(priv, next_entry - size,
+						  size, mode, pos, buf, bufsz);
+	} else {
+		if (next_entry < size) {
+			pos = iwl4965_print_event_log(priv, 0, next_entry,
+						  mode, pos, buf, bufsz);
+		} else {
+			pos = iwl4965_print_event_log(priv, next_entry - size,
+						  size, mode, pos, buf, bufsz);
+		}
+	}
+	return pos;
+}
+
+#define DEFAULT_DUMP_EVENT_LOG_ENTRIES (20)
+
+int iwl4965_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
+			    char **buf, bool display)
+{
+	u32 base;       /* SRAM byte address of event log header */
+	u32 capacity;   /* event log capacity in # entries */
+	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
+	u32 num_wraps;  /* # times uCode wrapped to top of log */
+	u32 next_entry; /* index of next entry to be written by uCode */
+	u32 size;       /* # entries that we'll print */
+	int pos = 0;
+	size_t bufsz = 0;
+
+	if (priv->ucode_type == UCODE_INIT) {
+		base = le32_to_cpu(priv->card_alive_init.log_event_table_ptr);
+	} else {
+		base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
+	}
+
+	if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
+		IWL_ERR(priv,
+			"Invalid event log pointer 0x%08X for %s uCode\n",
+			base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
+		return -EINVAL;
+	}
+
+	/* event log header */
+	capacity = iwl_legacy_read_targ_mem(priv, base);
+	mode = iwl_legacy_read_targ_mem(priv, base + (1 * sizeof(u32)));
+	num_wraps = iwl_legacy_read_targ_mem(priv, base + (2 * sizeof(u32)));
+	next_entry = iwl_legacy_read_targ_mem(priv, base + (3 * sizeof(u32)));
+
+	size = num_wraps ? capacity : next_entry;
+
+	/* bail out if nothing in log */
+	if (size == 0) {
+		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
+		return pos;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (!(iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
+		size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+			? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#else
+	size = (size > DEFAULT_DUMP_EVENT_LOG_ENTRIES)
+		? DEFAULT_DUMP_EVENT_LOG_ENTRIES : size;
+#endif
+	IWL_ERR(priv, "Start IWL Event Log Dump: display last %u entries\n",
+		size);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (display) {
+		if (full_log)
+			bufsz = capacity * 48;
+		else
+			bufsz = size * 48;
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+	}
+	if ((iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
+		/*
+		 * if uCode has wrapped back to top of log,
+		 * start at the oldest entry,
+		 * i.e the next one that uCode would fill.
+		 */
+		if (num_wraps)
+			pos = iwl4965_print_event_log(priv, next_entry,
+						capacity - next_entry, mode,
+						pos, buf, bufsz);
+		/* (then/else) start at top of log */
+		pos = iwl4965_print_event_log(priv, 0,
+					  next_entry, mode, pos, buf, bufsz);
+	} else
+		pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
+						next_entry, size, mode,
+						pos, buf, bufsz);
+#else
+	pos = iwl4965_print_last_event_logs(priv, capacity, num_wraps,
+					next_entry, size, mode,
+					pos, buf, bufsz);
+#endif
+	return pos;
+}
+
+static void iwl4965_rf_kill_ct_config(struct iwl_priv *priv)
+{
+	struct iwl_ct_kill_config cmd;
+	unsigned long flags;
+	int ret = 0;
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	cmd.critical_temperature_R =
+		cpu_to_le32(priv->hw_params.ct_kill_threshold);
+
+	ret = iwl_legacy_send_cmd_pdu(priv, REPLY_CT_KILL_CONFIG_CMD,
+			       sizeof(cmd), &cmd);
+	if (ret)
+		IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
+	else
+		IWL_DEBUG_INFO(priv, "REPLY_CT_KILL_CONFIG_CMD "
+				"succeeded, "
+				"critical temperature is %d\n",
+				priv->hw_params.ct_kill_threshold);
+}
+
+static const s8 default_queue_to_tx_fifo[] = {
+	IWL_TX_FIFO_VO,
+	IWL_TX_FIFO_VI,
+	IWL_TX_FIFO_BE,
+	IWL_TX_FIFO_BK,
+	IWL49_CMD_FIFO_NUM,
+	IWL_TX_FIFO_UNUSED,
+	IWL_TX_FIFO_UNUSED,
+};
+
+static int iwl4965_alive_notify(struct iwl_priv *priv)
+{
+	u32 a;
+	unsigned long flags;
+	int i, chan;
+	u32 reg_val;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Clear 4965's internal Tx Scheduler data base */
+	priv->scd_base_addr = iwl_legacy_read_prph(priv,
+					IWL49_SCD_SRAM_BASE_ADDR);
+	a = priv->scd_base_addr + IWL49_SCD_CONTEXT_DATA_OFFSET;
+	for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
+		iwl_legacy_write_targ_mem(priv, a, 0);
+	for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
+		iwl_legacy_write_targ_mem(priv, a, 0);
+	for (; a < priv->scd_base_addr +
+	       IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
+		iwl_legacy_write_targ_mem(priv, a, 0);
+
+	/* Tel 4965 where to find Tx byte count tables */
+	iwl_legacy_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
+			priv->scd_bc_tbls.dma >> 10);
+
+	/* Enable DMA channel */
+	for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
+		iwl_legacy_write_direct32(priv,
+				FH_TCSR_CHNL_TX_CONFIG_REG(chan),
+				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
+
+	/* Update FH chicken bits */
+	reg_val = iwl_legacy_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
+	iwl_legacy_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
+			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
+
+	/* Disable chain mode for all queues */
+	iwl_legacy_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
+
+	/* Initialize each Tx queue (including the command queue) */
+	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
+
+		/* TFD circular buffer read/write indexes */
+		iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
+		iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
+
+		/* Max Tx Window size for Scheduler-ACK mode */
+		iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
+				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i),
+				(SCD_WIN_SIZE <<
+				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+		/* Frame limit */
+		iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
+				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
+				sizeof(u32),
+				(SCD_FRAME_LIMIT <<
+				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
+				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+	}
+	iwl_legacy_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
+				 (1 << priv->hw_params.max_txq_num) - 1);
+
+	/* Activate all Tx DMA/FIFO channels */
+	iwl4965_txq_set_sched(priv, IWL_MASK(0, 6));
+
+	iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
+
+	/* make sure all queue are not stopped */
+	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
+	for (i = 0; i < 4; i++)
+		atomic_set(&priv->queue_stop_count[i], 0);
+
+	/* reset to 0 to enable all the queue first */
+	priv->txq_ctx_active_msk = 0;
+	/* Map each Tx/cmd queue to its corresponding fifo */
+	BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
+
+	for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
+		int ac = default_queue_to_tx_fifo[i];
+
+		iwl_txq_ctx_activate(priv, i);
+
+		if (ac == IWL_TX_FIFO_UNUSED)
+			continue;
+
+		iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+/**
+ * iwl4965_alive_start - called after REPLY_ALIVE notification received
+ *                   from protocol/runtime uCode (initialization uCode's
+ *                   Alive gets handled by iwl_init_alive_start()).
+ */
+static void iwl4965_alive_start(struct iwl_priv *priv)
+{
+	int ret = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+
+	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
+		/* We had an error bringing up the hardware, so take it
+		 * all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Alive failed.\n");
+		goto restart;
+	}
+
+	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "runtime" alive if code weren't properly loaded.  */
+	if (iwl4965_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
+		goto restart;
+	}
+
+	ret = iwl4965_alive_notify(priv);
+	if (ret) {
+		IWL_WARN(priv,
+			"Could not complete ALIVE transition [ntf]: %d\n", ret);
+		goto restart;
+	}
+
+
+	/* After the ALIVE response, we can send host commands to the uCode */
+	set_bit(STATUS_ALIVE, &priv->status);
+
+	/* Enable watchdog to monitor the driver tx queues */
+	iwl_legacy_setup_watchdog(priv);
+
+	if (iwl_legacy_is_rfkill(priv))
+		return;
+
+	ieee80211_wake_queues(priv->hw);
+
+	priv->active_rate = IWL_RATES_MASK;
+
+	if (iwl_legacy_is_associated_ctx(ctx)) {
+		struct iwl_legacy_rxon_cmd *active_rxon =
+				(struct iwl_legacy_rxon_cmd *)&ctx->active;
+		/* apply any changes in staging */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	} else {
+		struct iwl_rxon_context *tmp;
+		/* Initialize our rx_config data */
+		for_each_context(priv, tmp)
+			iwl_legacy_connection_init_rx_config(priv, tmp);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	/* Configure bluetooth coexistence if enabled */
+	iwl_legacy_send_bt_config(priv);
+
+	iwl4965_reset_run_time_calib(priv);
+
+	set_bit(STATUS_READY, &priv->status);
+
+	/* Configure the adapter for unassociated operation */
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	/* At this point, the NIC is initialized and operational */
+	iwl4965_rf_kill_ct_config(priv);
+
+	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
+	wake_up_interruptible(&priv->wait_command_queue);
+
+	iwl_legacy_power_update_mode(priv, true);
+	IWL_DEBUG_INFO(priv, "Updated power mode\n");
+
+	return;
+
+ restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+static void iwl4965_cancel_deferred_work(struct iwl_priv *priv);
+
+static void __iwl4965_down(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	int exit_pending = test_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
+	 * to prevent rearm timer */
+	del_timer_sync(&priv->watchdog);
+
+	iwl_legacy_clear_ucode_stations(priv, NULL);
+	iwl_legacy_dealloc_bcast_stations(priv);
+	iwl_legacy_clear_driver_stations(priv);
+
+	/* Unblock any waiting calls */
+	wake_up_interruptible_all(&priv->wait_command_queue);
+
+	/* Wipe out the EXIT_PENDING status bit if we are not actually
+	 * exiting the module */
+	if (!exit_pending)
+		clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* stop and reset the on-board processor */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	/* tell the device to stop sending interrupts */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	iwl4965_synchronize_irq(priv);
+
+	if (priv->mac80211_registered)
+		ieee80211_stop_queues(priv->hw);
+
+	/* If we have not previously called iwl_init() then
+	 * clear all bits but the RF Kill bit and return */
+	if (!iwl_legacy_is_init(priv)) {
+		priv->status = test_bit(STATUS_RF_KILL_HW, &priv->status) <<
+					STATUS_RF_KILL_HW |
+			       test_bit(STATUS_GEO_CONFIGURED, &priv->status) <<
+					STATUS_GEO_CONFIGURED |
+			       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+					STATUS_EXIT_PENDING;
+		goto exit;
+	}
+
+	/* ...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_GEO_CONFIGURED, &priv->status) <<
+				STATUS_GEO_CONFIGURED |
+			test_bit(STATUS_FW_ERROR, &priv->status) <<
+				STATUS_FW_ERROR |
+		       test_bit(STATUS_EXIT_PENDING, &priv->status) <<
+				STATUS_EXIT_PENDING;
+
+	iwl4965_txq_ctx_stop(priv);
+	iwl4965_rxq_stop(priv);
+
+	/* Power-down device's busmaster DMA clocks */
+	iwl_legacy_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
+	udelay(5);
+
+	/* Make sure (redundant) we've released our request to stay awake */
+	iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+	/* Stop the device, and put it in low power state */
+	iwl_legacy_apm_stop(priv);
+
+ exit:
+	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
+
+	dev_kfree_skb(priv->beacon_skb);
+	priv->beacon_skb = NULL;
+
+	/* clear out any free frames */
+	iwl4965_clear_free_frames(priv);
+}
+
+static void iwl4965_down(struct iwl_priv *priv)
+{
+	mutex_lock(&priv->mutex);
+	__iwl4965_down(priv);
+	mutex_unlock(&priv->mutex);
+
+	iwl4965_cancel_deferred_work(priv);
+}
+
+#define HW_READY_TIMEOUT (50)
+
+static int iwl4965_set_hw_ready(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	iwl_legacy_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 iwl4965_prepare_card_hw(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	IWL_DEBUG_INFO(priv, "iwl4965_prepare_card_hw enter\n");
+
+	ret = iwl4965_set_hw_ready(priv);
+	if (priv->hw_ready)
+		return ret;
+
+	/* If HW is not ready, prepare the conditions to check again */
+	iwl_legacy_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);
+
+	/* HW should be ready by now, check again. */
+	if (ret != -ETIMEDOUT)
+		iwl4965_set_hw_ready(priv);
+
+	return ret;
+}
+
+#define MAX_HW_RESTARTS 5
+
+static int __iwl4965_up(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+	int i;
+	int ret;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
+		return -EIO;
+	}
+
+	if (!priv->ucode_data_backup.v_addr || !priv->ucode_data.v_addr) {
+		IWL_ERR(priv, "ucode not available for device bringup\n");
+		return -EIO;
+	}
+
+	for_each_context(priv, ctx) {
+		ret = iwl4965_alloc_bcast_station(priv, ctx);
+		if (ret) {
+			iwl_legacy_dealloc_bcast_stations(priv);
+			return ret;
+		}
+	}
+
+	iwl4965_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);
+	else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	if (iwl_legacy_is_rfkill(priv)) {
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy, true);
+
+		iwl_legacy_enable_interrupts(priv);
+		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
+		return 0;
+	}
+
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+
+	/* must be initialised before iwl_hw_nic_init */
+	priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
+
+	ret = iwl4965_hw_nic_init(priv);
+	if (ret) {
+		IWL_ERR(priv, "Unable to init nic\n");
+		return ret;
+	}
+
+	/* make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
+		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+	/* clear (again), then enable host interrupts */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_legacy_enable_interrupts(priv);
+
+	/* really make sure rfkill handshake bits are cleared */
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
+
+	/* Copy original ucode data image from disk into backup cache.
+	 * This will be used to initialize the on-board processor's
+	 * data SRAM for a clean start when the runtime program first loads. */
+	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
+	       priv->ucode_data.len);
+
+	for (i = 0; i < MAX_HW_RESTARTS; i++) {
+
+		/* load bootstrap state machine,
+		 * load bootstrap program into processor's memory,
+		 * prepare to load the "initialize" uCode */
+		ret = priv->cfg->ops->lib->load_ucode(priv);
+
+		if (ret) {
+			IWL_ERR(priv, "Unable to set up bootstrap uCode: %d\n",
+				ret);
+			continue;
+		}
+
+		/* start card; "initialize" will load runtime ucode */
+		iwl4965_nic_start(priv);
+
+		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
+
+		return 0;
+	}
+
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+	__iwl4965_down(priv);
+	clear_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	/* tried to restart and config the device for as long as our
+	 * patience could withstand */
+	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
+	return -EIO;
+}
+
+
+/*****************************************************************************
+ *
+ * Workqueue callbacks
+ *
+ *****************************************************************************/
+
+static void iwl4965_bg_init_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, init_alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	priv->cfg->ops->lib->init_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_bg_alive_start(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, alive_start.work);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl4965_alive_start(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_bg_run_time_calib_work(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+			run_time_calib_work);
+
+	mutex_lock(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status)) {
+		mutex_unlock(&priv->mutex);
+		return;
+	}
+
+	if (priv->start_calib) {
+		iwl4965_chain_noise_calibration(priv,
+				(void *)&priv->_4965.statistics);
+		iwl4965_sensitivity_calibration(priv,
+				(void *)&priv->_4965.statistics);
+	}
+
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_bg_restart(struct work_struct *data)
+{
+	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
+		struct iwl_rxon_context *ctx;
+
+		mutex_lock(&priv->mutex);
+		for_each_context(priv, ctx)
+			ctx->vif = NULL;
+		priv->is_open = 0;
+
+		__iwl4965_down(priv);
+
+		mutex_unlock(&priv->mutex);
+		iwl4965_cancel_deferred_work(priv);
+		ieee80211_restart_hw(priv->hw);
+	} else {
+		iwl4965_down(priv);
+
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			return;
+
+		mutex_lock(&priv->mutex);
+		__iwl4965_up(priv);
+		mutex_unlock(&priv->mutex);
+	}
+}
+
+static void iwl4965_bg_rx_replenish(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, rx_replenish);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	mutex_lock(&priv->mutex);
+	iwl4965_rx_replenish(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/*****************************************************************************
+ *
+ * mac80211 entry point functions
+ *
+ *****************************************************************************/
+
+#define UCODE_READY_TIMEOUT	(4 * HZ)
+
+/*
+ * Not a mac80211 entry point function, but it fits in with all the
+ * other mac80211 functions grouped here.
+ */
+static int iwl4965_mac_setup_register(struct iwl_priv *priv,
+				  u32 max_probe_length)
+{
+	int ret;
+	struct ieee80211_hw *hw = priv->hw;
+	struct iwl_rxon_context *ctx;
+
+	hw->rate_control_algorithm = "iwl-4965-rs";
+
+	/* Tell mac80211 our characteristics */
+	hw->flags = IEEE80211_HW_SIGNAL_DBM |
+		    IEEE80211_HW_AMPDU_AGGREGATION |
+		    IEEE80211_HW_NEED_DTIM_PERIOD |
+		    IEEE80211_HW_SPECTRUM_MGMT |
+		    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
+
+	if (priv->cfg->sku & IWL_SKU_N)
+		hw->flags |= IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
+			     IEEE80211_HW_SUPPORTS_STATIC_SMPS;
+
+	hw->sta_data_size = sizeof(struct iwl_station_priv);
+	hw->vif_data_size = sizeof(struct iwl_vif_priv);
+
+	for_each_context(priv, ctx) {
+		hw->wiphy->interface_modes |= ctx->interface_modes;
+		hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
+	}
+
+	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
+			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
+
+	/*
+	 * For now, disable PS by default because it affects
+	 * RX performance significantly.
+	 */
+	hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
+
+	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 = max_probe_length - 24 - 2;
+
+	/* Default value; 4 EDCA QOS priorities */
+	hw->queues = 4;
+
+	hw->max_listen_interval = IWL_CONN_MAX_LISTEN_INTERVAL;
+
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+			&priv->bands[IEEE80211_BAND_2GHZ];
+	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
+		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+			&priv->bands[IEEE80211_BAND_5GHZ];
+
+	iwl_legacy_leds_init(priv);
+
+	ret = ieee80211_register_hw(priv->hw);
+	if (ret) {
+		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
+		return ret;
+	}
+	priv->mac80211_registered = 1;
+
+	return 0;
+}
+
+
+int iwl4965_mac_start(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	/* we should be verifying the device is ready to be opened */
+	mutex_lock(&priv->mutex);
+	ret = __iwl4965_up(priv);
+	mutex_unlock(&priv->mutex);
+
+	if (ret)
+		return ret;
+
+	if (iwl_legacy_is_rfkill(priv))
+		goto out;
+
+	IWL_DEBUG_INFO(priv, "Start UP work done.\n");
+
+	/* 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,
+			test_bit(STATUS_READY, &priv->status),
+			UCODE_READY_TIMEOUT);
+	if (!ret) {
+		if (!test_bit(STATUS_READY, &priv->status)) {
+			IWL_ERR(priv, "START_ALIVE timeout after %dms.\n",
+				jiffies_to_msecs(UCODE_READY_TIMEOUT));
+			return -ETIMEDOUT;
+		}
+	}
+
+	iwl4965_led_enable(priv);
+
+out:
+	priv->is_open = 1;
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+}
+
+void iwl4965_mac_stop(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!priv->is_open)
+		return;
+
+	priv->is_open = 0;
+
+	iwl4965_down(priv);
+
+	flush_workqueue(priv->workqueue);
+
+	/* enable interrupts again in order to receive rfkill changes */
+	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
+	iwl_legacy_enable_interrupts(priv);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+void iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	IWL_DEBUG_MACDUMP(priv, "enter\n");
+
+	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
+		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
+
+	if (iwl4965_tx_skb(priv, skb))
+		dev_kfree_skb_any(skb);
+
+	IWL_DEBUG_MACDUMP(priv, "leave\n");
+}
+
+void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	iwl4965_update_tkip_key(priv, vif_priv->ctx, keyconf, sta,
+			    iv32, phase1key);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+int iwl4965_mac_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 iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	struct iwl_rxon_context *ctx = vif_priv->ctx;
+	int ret;
+	u8 sta_id;
+	bool is_default_wep_key = false;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (priv->cfg->mod_params->sw_crypto) {
+		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
+		return -EOPNOTSUPP;
+	}
+
+	sta_id = iwl_legacy_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return -EINVAL;
+
+	mutex_lock(&priv->mutex);
+	iwl_legacy_scan_cancel_timeout(priv, 100);
+
+	/*
+	 * If we are getting WEP group key and we didn't receive any key mapping
+	 * so far, we are in legacy wep mode (group key only), otherwise we are
+	 * in 1X mode.
+	 * In legacy wep mode, we use another host command to the uCode.
+	 */
+	if ((key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+	     key->cipher == WLAN_CIPHER_SUITE_WEP104) &&
+	    !sta) {
+		if (cmd == SET_KEY)
+			is_default_wep_key = !ctx->key_mapping_keys;
+		else
+			is_default_wep_key =
+					(key->hw_key_idx == HW_KEY_DEFAULT);
+	}
+
+	switch (cmd) {
+	case SET_KEY:
+		if (is_default_wep_key)
+			ret = iwl4965_set_default_wep_key(priv,
+							vif_priv->ctx, key);
+		else
+			ret = iwl4965_set_dynamic_key(priv, vif_priv->ctx,
+						  key, sta_id);
+
+		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
+		break;
+	case DISABLE_KEY:
+		if (is_default_wep_key)
+			ret = iwl4965_remove_default_wep_key(priv, ctx, key);
+		else
+			ret = iwl4965_remove_dynamic_key(priv, ctx,
+							key, sta_id);
+
+		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
+		break;
+	default:
+		ret = -EINVAL;
+	}
+
+	mutex_unlock(&priv->mutex);
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+	return ret;
+}
+
+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret = -EINVAL;
+
+	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
+		     sta->addr, tid);
+
+	if (!(priv->cfg->sku & IWL_SKU_N))
+		return -EACCES;
+
+	mutex_lock(&priv->mutex);
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		IWL_DEBUG_HT(priv, "start Rx\n");
+		ret = iwl4965_sta_rx_agg_start(priv, sta, tid, *ssn);
+		break;
+	case IEEE80211_AMPDU_RX_STOP:
+		IWL_DEBUG_HT(priv, "stop Rx\n");
+		ret = iwl4965_sta_rx_agg_stop(priv, sta, tid);
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			ret = 0;
+		break;
+	case IEEE80211_AMPDU_TX_START:
+		IWL_DEBUG_HT(priv, "start Tx\n");
+		ret = iwl4965_tx_agg_start(priv, vif, sta, tid, ssn);
+		if (ret == 0) {
+			priv->_4965.agg_tids_count++;
+			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
+				     priv->_4965.agg_tids_count);
+		}
+		break;
+	case IEEE80211_AMPDU_TX_STOP:
+		IWL_DEBUG_HT(priv, "stop Tx\n");
+		ret = iwl4965_tx_agg_stop(priv, vif, sta, tid);
+		if ((ret == 0) && (priv->_4965.agg_tids_count > 0)) {
+			priv->_4965.agg_tids_count--;
+			IWL_DEBUG_HT(priv, "priv->_4965.agg_tids_count = %u\n",
+				     priv->_4965.agg_tids_count);
+		}
+		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+			ret = 0;
+		break;
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		ret = 0;
+		break;
+	}
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+
+int iwl4965_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
+	int ret;
+	u8 sta_id;
+
+	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
+			sta->addr);
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
+			sta->addr);
+	sta_priv->common.sta_id = IWL_INVALID_STATION;
+
+	atomic_set(&sta_priv->pending_frames, 0);
+
+	ret = iwl_legacy_add_station_common(priv, vif_priv->ctx, sta->addr,
+				     is_ap, sta, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
+			sta->addr, ret);
+		/* Should we return success if return code is EEXIST ? */
+		mutex_unlock(&priv->mutex);
+		return ret;
+	}
+
+	sta_priv->common.sta_id = sta_id;
+
+	/* Initialize rate scaling */
+	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
+		       sta->addr);
+	iwl4965_rs_rate_init(priv, sta, sta_id);
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+
+void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch)
+{
+	struct iwl_priv *priv = hw->priv;
+	const struct iwl_channel_info *ch_info;
+	struct ieee80211_conf *conf = &hw->conf;
+	struct ieee80211_channel *channel = ch_switch->channel;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	u16 ch;
+	unsigned long flags = 0;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (iwl_legacy_is_rfkill(priv))
+		goto out_exit;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status))
+		goto out_exit;
+
+	if (!iwl_legacy_is_associated_ctx(ctx))
+		goto out_exit;
+
+	/* channel switch in progress */
+	if (priv->switch_rxon.switch_in_progress == true)
+		goto out_exit;
+
+	mutex_lock(&priv->mutex);
+	if (priv->cfg->ops->lib->set_channel_switch) {
+
+		ch = channel->hw_value;
+		if (le16_to_cpu(ctx->active.channel) != ch) {
+			ch_info = iwl_legacy_get_channel_info(priv,
+						       channel->band,
+						       ch);
+			if (!iwl_legacy_is_channel_valid(ch_info)) {
+				IWL_DEBUG_MAC80211(priv, "invalid channel\n");
+				goto out;
+			}
+			spin_lock_irqsave(&priv->lock, flags);
+
+			priv->current_ht_config.smps = conf->smps_mode;
+
+			/* Configure HT40 channels */
+			ctx->ht.enabled = conf_is_ht(conf);
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+						IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			if ((le16_to_cpu(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
+
+			iwl_legacy_set_rxon_channel(priv, channel, ctx);
+			iwl_legacy_set_rxon_ht(priv, ht_conf);
+			iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+			spin_unlock_irqrestore(&priv->lock, flags);
+
+			iwl_legacy_set_rate(priv);
+			/*
+			 * at this point, staging_rxon has the
+			 * configuration for channel switch
+			 */
+			if (priv->cfg->ops->lib->set_channel_switch(priv,
+								    ch_switch))
+				priv->switch_rxon.switch_in_progress = false;
+		}
+	}
+out:
+	mutex_unlock(&priv->mutex);
+out_exit:
+	if (!priv->switch_rxon.switch_in_progress)
+		ieee80211_chswitch_done(ctx->vif, false);
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+
+void iwl4965_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast)
+{
+	struct iwl_priv *priv = hw->priv;
+	__le32 filter_or = 0, filter_nand = 0;
+	struct iwl_rxon_context *ctx;
+
+#define CHK(test, flag)	do { \
+	if (*total_flags & (test))		\
+		filter_or |= (flag);		\
+	else					\
+		filter_nand |= (flag);		\
+	} while (0)
+
+	IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
+			changed_flags, *total_flags);
+
+	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
+	/* Setting _just_ RXON_FILTER_CTL2HOST_MSK causes FH errors */
+	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK | RXON_FILTER_PROMISC_MSK);
+	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
+
+#undef CHK
+
+	mutex_lock(&priv->mutex);
+
+	for_each_context(priv, ctx) {
+		ctx->staging.filter_flags &= ~filter_nand;
+		ctx->staging.filter_flags |= filter_or;
+
+		/*
+		 * Not committing directly because hardware can perform a scan,
+		 * but we'll eventually commit the filter flags change anyway.
+		 */
+	}
+
+	mutex_unlock(&priv->mutex);
+
+	/*
+	 * Receiving all multicast frames is always enabled by the
+	 * default flags setup in iwl_legacy_connection_init_rx_config()
+	 * since we currently do not support programming multicast
+	 * filters into the device.
+	 */
+	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
+			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
+}
+
+/*****************************************************************************
+ *
+ * driver setup and teardown
+ *
+ *****************************************************************************/
+
+static void iwl4965_bg_txpower_work(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+			txpower_work);
+
+	mutex_lock(&priv->mutex);
+
+	/* If a scan happened to start before we got here
+	 * then just return; the statistics notification will
+	 * kick off another scheduled work to compensate for
+	 * any temperature delta we missed here. */
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
+	    test_bit(STATUS_SCANNING, &priv->status))
+		goto out;
+
+	/* Regardless of if we are associated, we must reconfigure the
+	 * TX power since frames can be sent on non-radar channels while
+	 * not associated */
+	priv->cfg->ops->lib->send_tx_power(priv);
+
+	/* Update last_temperature to keep is_calib_needed from running
+	 * when it isn't needed... */
+	priv->last_temperature = priv->temperature;
+out:
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
+{
+	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
+
+	init_waitqueue_head(&priv->wait_command_queue);
+
+	INIT_WORK(&priv->restart, iwl4965_bg_restart);
+	INIT_WORK(&priv->rx_replenish, iwl4965_bg_rx_replenish);
+	INIT_WORK(&priv->run_time_calib_work, iwl4965_bg_run_time_calib_work);
+	INIT_DELAYED_WORK(&priv->init_alive_start, iwl4965_bg_init_alive_start);
+	INIT_DELAYED_WORK(&priv->alive_start, iwl4965_bg_alive_start);
+
+	iwl_legacy_setup_scan_deferred_work(priv);
+
+	INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
+
+	init_timer(&priv->statistics_periodic);
+	priv->statistics_periodic.data = (unsigned long)priv;
+	priv->statistics_periodic.function = iwl4965_bg_statistics_periodic;
+
+	init_timer(&priv->ucode_trace);
+	priv->ucode_trace.data = (unsigned long)priv;
+	priv->ucode_trace.function = iwl4965_bg_ucode_trace;
+
+	init_timer(&priv->watchdog);
+	priv->watchdog.data = (unsigned long)priv;
+	priv->watchdog.function = iwl_legacy_bg_watchdog;
+
+	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
+		iwl4965_irq_tasklet, (unsigned long)priv);
+}
+
+static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
+{
+	cancel_work_sync(&priv->txpower_work);
+	cancel_delayed_work_sync(&priv->init_alive_start);
+	cancel_delayed_work(&priv->alive_start);
+	cancel_work_sync(&priv->run_time_calib_work);
+
+	iwl_legacy_cancel_scan_deferred_work(priv);
+
+	del_timer_sync(&priv->statistics_periodic);
+	del_timer_sync(&priv->ucode_trace);
+}
+
+static void iwl4965_init_hw_rates(struct iwl_priv *priv,
+			      struct ieee80211_rate *rates)
+{
+	int i;
+
+	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
+		rates[i].bitrate = iwlegacy_rates[i].ieee * 5;
+		rates[i].hw_value = i; /* Rate scaling will work on indexes */
+		rates[i].hw_value_short = i;
+		rates[i].flags = 0;
+		if ((i >= IWL_FIRST_CCK_RATE) && (i <= IWL_LAST_CCK_RATE)) {
+			/*
+			 * If CCK != 1M then set short preamble rate flag.
+			 */
+			rates[i].flags |=
+				(iwlegacy_rates[i].plcp == IWL_RATE_1M_PLCP) ?
+					0 : IEEE80211_RATE_SHORT_PREAMBLE;
+		}
+	}
+}
+/*
+ * Acquire priv->lock before calling this function !
+ */
+void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
+{
+	iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR,
+			     (index & 0xff) | (txq_id << 8));
+	iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
+}
+
+void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					int tx_fifo_id, int scd_retry)
+{
+	int txq_id = txq->q.id;
+
+	/* Find out whether to activate Tx queue */
+	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
+
+	/* Set up and activate */
+	iwl_legacy_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
+			 (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
+			 (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) |
+			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) |
+			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
+			 IWL49_SCD_QUEUE_STTS_REG_MSK);
+
+	txq->sched_retry = scd_retry;
+
+	IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
+		       active ? "Activate" : "Deactivate",
+		       scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
+}
+
+
+static int iwl4965_init_drv(struct iwl_priv *priv)
+{
+	int ret;
+
+	spin_lock_init(&priv->sta_lock);
+	spin_lock_init(&priv->hcmd_lock);
+
+	INIT_LIST_HEAD(&priv->free_frames);
+
+	mutex_init(&priv->mutex);
+	mutex_init(&priv->sync_cmd_mutex);
+
+	priv->ieee_channels = NULL;
+	priv->ieee_rates = NULL;
+	priv->band = IEEE80211_BAND_2GHZ;
+
+	priv->iw_mode = NL80211_IFTYPE_STATION;
+	priv->current_ht_config.smps = IEEE80211_SMPS_STATIC;
+	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
+	priv->_4965.agg_tids_count = 0;
+
+	/* initialize force reset */
+	priv->force_reset[IWL_RF_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_RF_RESET;
+	priv->force_reset[IWL_FW_RESET].reset_duration =
+		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
+
+	/* Choose which receivers/antennas to use */
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
+
+	iwl_legacy_init_scan_params(priv);
+
+	ret = iwl_legacy_init_channel_map(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
+		goto err;
+	}
+
+	ret = iwl_legacy_init_geos(priv);
+	if (ret) {
+		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
+		goto err_free_channel_map;
+	}
+	iwl4965_init_hw_rates(priv, priv->ieee_rates);
+
+	return 0;
+
+err_free_channel_map:
+	iwl_legacy_free_channel_map(priv);
+err:
+	return ret;
+}
+
+static void iwl4965_uninit_drv(struct iwl_priv *priv)
+{
+	iwl4965_calib_free_results(priv);
+	iwl_legacy_free_geos(priv);
+	iwl_legacy_free_channel_map(priv);
+	kfree(priv->scan_cmd);
+}
+
+static void iwl4965_hw_detect(struct iwl_priv *priv)
+{
+	priv->hw_rev = _iwl_legacy_read32(priv, CSR_HW_REV);
+	priv->hw_wa_rev = _iwl_legacy_read32(priv, CSR_HW_REV_WA_REG);
+	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
+}
+
+static int iwl4965_set_hw_params(struct iwl_priv *priv)
+{
+	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
+	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_8K);
+	else
+		priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_4K);
+
+	priv->hw_params.max_beacon_itrvl = IWL_MAX_UCODE_BEACON_INTERVAL;
+
+	if (priv->cfg->mod_params->disable_11n)
+		priv->cfg->sku &= ~IWL_SKU_N;
+
+	/* Device-specific setup */
+	return priv->cfg->ops->lib->set_hw_params(priv);
+}
+
+static const u8 iwl4965_bss_ac_to_fifo[] = {
+	IWL_TX_FIFO_VO,
+	IWL_TX_FIFO_VI,
+	IWL_TX_FIFO_BE,
+	IWL_TX_FIFO_BK,
+};
+
+static const u8 iwl4965_bss_ac_to_queue[] = {
+	0, 1, 2, 3,
+};
+
+static int
+iwl4965_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
+{
+	int err = 0, i;
+	struct iwl_priv *priv;
+	struct ieee80211_hw *hw;
+	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
+	unsigned long flags;
+	u16 pci_cmd;
+
+	/************************
+	 * 1. Allocating HW data
+	 ************************/
+
+	hw = iwl_legacy_alloc_all(cfg);
+	if (!hw) {
+		err = -ENOMEM;
+		goto out;
+	}
+	priv = hw->priv;
+	/* At this point both hw and priv are allocated. */
+
+	/*
+	 * The default context is always valid,
+	 * more may be discovered when firmware
+	 * is loaded.
+	 */
+	priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
+
+	for (i = 0; i < NUM_IWL_RXON_CTX; i++)
+		priv->contexts[i].ctxid = i;
+
+	priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
+	priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
+	priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
+	priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
+	priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
+	priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
+	priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwl4965_bss_ac_to_fifo;
+	priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwl4965_bss_ac_to_queue;
+	priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
+		BIT(NL80211_IFTYPE_ADHOC);
+	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
+		BIT(NL80211_IFTYPE_STATION);
+	priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
+	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
+	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
+	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
+
+	BUILD_BUG_ON(NUM_IWL_RXON_CTX != 1);
+
+	SET_IEEE80211_DEV(hw, &pdev->dev);
+
+	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
+	priv->cfg = cfg;
+	priv->pci_dev = pdev;
+	priv->inta_mask = CSR_INI_SET_MASK;
+
+	if (iwl_legacy_alloc_traffic_mem(priv))
+		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
+
+	/**************************
+	 * 2. Initializing PCI bus
+	 **************************/
+	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
+				PCIE_LINK_STATE_CLKPM);
+
+	if (pci_enable_device(pdev)) {
+		err = -ENODEV;
+		goto out_ieee80211_free_hw;
+	}
+
+	pci_set_master(pdev);
+
+	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (!err)
+		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(36));
+	if (err) {
+		err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
+		if (!err)
+			err = pci_set_consistent_dma_mask(pdev,
+							DMA_BIT_MASK(32));
+		/* both attempts failed: */
+		if (err) {
+			IWL_WARN(priv, "No suitable DMA available.\n");
+			goto out_pci_disable_device;
+		}
+	}
+
+	err = pci_request_regions(pdev, DRV_NAME);
+	if (err)
+		goto out_pci_disable_device;
+
+	pci_set_drvdata(pdev, priv);
+
+
+	/***********************
+	 * 3. Read REV register
+	 ***********************/
+	priv->hw_base = pci_iomap(pdev, 0, 0);
+	if (!priv->hw_base) {
+		err = -ENODEV;
+		goto out_pci_release_regions;
+	}
+
+	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
+		(unsigned long long) pci_resource_len(pdev, 0));
+	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
+
+	/* these spin locks will be used in apm_ops.init and EEPROM access
+	 * we should init now
+	 */
+	spin_lock_init(&priv->reg_lock);
+	spin_lock_init(&priv->lock);
+
+	/*
+	 * stop and reset the on-board processor just in case it is in a
+	 * strange state ... like being left stranded by a primary kernel
+	 * and this is now the kdump kernel trying to start up
+	 */
+	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
+
+	iwl4965_hw_detect(priv);
+	IWL_INFO(priv, "Detected %s, REV=0x%X\n",
+		priv->cfg->name, priv->hw_rev);
+
+	/* We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+	iwl4965_prepare_card_hw(priv);
+	if (!priv->hw_ready) {
+		IWL_WARN(priv, "Failed, HW not ready\n");
+		goto out_iounmap;
+	}
+
+	/*****************
+	 * 4. Read EEPROM
+	 *****************/
+	/* Read the EEPROM */
+	err = iwl_legacy_eeprom_init(priv);
+	if (err) {
+		IWL_ERR(priv, "Unable to init EEPROM\n");
+		goto out_iounmap;
+	}
+	err = iwl4965_eeprom_check_version(priv);
+	if (err)
+		goto out_free_eeprom;
+
+	if (err)
+		goto out_free_eeprom;
+
+	/* extract MAC Address */
+	iwl4965_eeprom_get_mac(priv, priv->addresses[0].addr);
+	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", priv->addresses[0].addr);
+	priv->hw->wiphy->addresses = priv->addresses;
+	priv->hw->wiphy->n_addresses = 1;
+
+	/************************
+	 * 5. Setup HW constants
+	 ************************/
+	if (iwl4965_set_hw_params(priv)) {
+		IWL_ERR(priv, "failed to set hw parameters\n");
+		goto out_free_eeprom;
+	}
+
+	/*******************
+	 * 6. Setup priv
+	 *******************/
+
+	err = iwl4965_init_drv(priv);
+	if (err)
+		goto out_free_eeprom;
+	/* At this point both hw and priv are initialized. */
+
+	/********************
+	 * 7. Setup services
+	 ********************/
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	pci_enable_msi(priv->pci_dev);
+
+	err = request_irq(priv->pci_dev->irq, iwl_legacy_isr,
+			  IRQF_SHARED, DRV_NAME, priv);
+	if (err) {
+		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
+		goto out_disable_msi;
+	}
+
+	iwl4965_setup_deferred_work(priv);
+	iwl4965_setup_rx_handlers(priv);
+
+	/*********************************************
+	 * 8. Enable interrupts and read RFKILL state
+	 *********************************************/
+
+	/* enable interrupts if needed: hw bug w/a */
+	pci_read_config_word(priv->pci_dev, PCI_COMMAND, &pci_cmd);
+	if (pci_cmd & PCI_COMMAND_INTX_DISABLE) {
+		pci_cmd &= ~PCI_COMMAND_INTX_DISABLE;
+		pci_write_config_word(priv->pci_dev, PCI_COMMAND, pci_cmd);
+	}
+
+	iwl_legacy_enable_interrupts(priv);
+
+	/* 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);
+	else
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+
+	wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+		test_bit(STATUS_RF_KILL_HW, &priv->status));
+
+	iwl_legacy_power_initialize(priv);
+
+	init_completion(&priv->_4965.firmware_loading_complete);
+
+	err = iwl4965_reject_firmware(priv, true);
+	if (err)
+		goto out_destroy_workqueue;
+
+	return 0;
+
+ out_destroy_workqueue:
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	free_irq(priv->pci_dev->irq, priv);
+ out_disable_msi:
+	pci_disable_msi(priv->pci_dev);
+	iwl4965_uninit_drv(priv);
+ out_free_eeprom:
+	iwl_legacy_eeprom_free(priv);
+ out_iounmap:
+	pci_iounmap(pdev, priv->hw_base);
+ out_pci_release_regions:
+	pci_set_drvdata(pdev, NULL);
+	pci_release_regions(pdev);
+ out_pci_disable_device:
+	pci_disable_device(pdev);
+ out_ieee80211_free_hw:
+	iwl_legacy_free_traffic_mem(priv);
+	ieee80211_free_hw(priv->hw);
+ out:
+	return err;
+}
+
+static void __devexit iwl4965_pci_remove(struct pci_dev *pdev)
+{
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	unsigned long flags;
+
+	if (!priv)
+		return;
+
+	wait_for_completion(&priv->_4965.firmware_loading_complete);
+
+	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
+
+	iwl_legacy_dbgfs_unregister(priv);
+	sysfs_remove_group(&pdev->dev.kobj, &iwl_attribute_group);
+
+	/* ieee80211_unregister_hw call wil cause iwl_mac_stop to
+	 * to be called and iwl4965_down since we are removing the device
+	 * we need to set STATUS_EXIT_PENDING bit.
+	 */
+	set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	iwl_legacy_leds_exit(priv);
+
+	if (priv->mac80211_registered) {
+		ieee80211_unregister_hw(priv->hw);
+		priv->mac80211_registered = 0;
+	} else {
+		iwl4965_down(priv);
+	}
+
+	/*
+	 * Make sure device is reset to low power before unloading driver.
+	 * This may be redundant with iwl4965_down(), but there are paths to
+	 * run iwl4965_down() without calling apm_ops.stop(), and there are
+	 * paths to avoid running iwl4965_down() at all before leaving driver.
+	 * This (inexpensive) call *makes sure* device is reset.
+	 */
+	iwl_legacy_apm_stop(priv);
+
+	/* make sure we flush any pending irq or
+	 * tasklet for the driver
+	 */
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl_legacy_disable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl4965_synchronize_irq(priv);
+
+	iwl4965_dealloc_ucode_pci(priv);
+
+	if (priv->rxq.bd)
+		iwl4965_rx_queue_free(priv, &priv->rxq);
+	iwl4965_hw_txq_ctx_free(priv);
+
+	iwl_legacy_eeprom_free(priv);
+
+
+	/*netif_stop_queue(dev); */
+	flush_workqueue(priv->workqueue);
+
+	/* ieee80211_unregister_hw calls iwl_mac_stop, which flushes
+	 * priv->workqueue... so we can't take down the workqueue
+	 * until now... */
+	destroy_workqueue(priv->workqueue);
+	priv->workqueue = NULL;
+	iwl_legacy_free_traffic_mem(priv);
+
+	free_irq(priv->pci_dev->irq, priv);
+	pci_disable_msi(priv->pci_dev);
+	pci_iounmap(pdev, priv->hw_base);
+	pci_release_regions(pdev);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+
+	iwl4965_uninit_drv(priv);
+
+	dev_kfree_skb(priv->beacon_skb);
+
+	ieee80211_free_hw(priv->hw);
+}
+
+/*
+ * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
+ * must be called under priv->lock and mac access
+ */
+void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
+{
+	iwl_legacy_write_prph(priv, IWL49_SCD_TXFACT, mask);
+}
+
+/*****************************************************************************
+ *
+ * driver and module entry point
+ *
+ *****************************************************************************/
+
+/* Hardware specific file defines the PCI IDs table for that hardware module */
+static DEFINE_PCI_DEVICE_TABLE(iwl4965_hw_card_ids) = {
+#if defined(CONFIG_IWL4965_MODULE) || defined(CONFIG_IWL4965)
+	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_cfg)},
+	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_cfg)},
+#endif /* CONFIG_IWL4965 */
+
+	{0}
+};
+MODULE_DEVICE_TABLE(pci, iwl4965_hw_card_ids);
+
+static struct pci_driver iwl4965_driver = {
+	.name = DRV_NAME,
+	.id_table = iwl4965_hw_card_ids,
+	.probe = iwl4965_pci_probe,
+	.remove = __devexit_p(iwl4965_pci_remove),
+	.driver.pm = IWL_LEGACY_PM_OPS,
+};
+
+static int __init iwl4965_init(void)
+{
+
+	int ret;
+	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
+	pr_info(DRV_COPYRIGHT "\n");
+
+	ret = iwl4965_rate_control_register();
+	if (ret) {
+		pr_err("Unable to register rate control algorithm: %d\n", ret);
+		return ret;
+	}
+
+	ret = pci_register_driver(&iwl4965_driver);
+	if (ret) {
+		pr_err("Unable to initialize PCI module\n");
+		goto error_register;
+	}
+
+	return ret;
+
+error_register:
+	iwl4965_rate_control_unregister();
+	return ret;
+}
+
+static void __exit iwl4965_exit(void)
+{
+	pci_unregister_driver(&iwl4965_driver);
+	iwl4965_rate_control_unregister();
+}
+
+module_exit(iwl4965_exit);
+module_init(iwl4965_init);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+module_param_named(debug, iwlegacy_debug_level, uint, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "debug output mask");
+#endif
+
+module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, S_IRUGO);
+MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])");
+module_param_named(queues_num, iwl4965_mod_params.num_of_queues, int, S_IRUGO);
+MODULE_PARM_DESC(queues_num, "number of hw queues.");
+module_param_named(11n_disable, iwl4965_mod_params.disable_11n, int, S_IRUGO);
+MODULE_PARM_DESC(11n_disable, "disable 11n functionality");
+module_param_named(amsdu_size_8K, iwl4965_mod_params.amsdu_size_8K,
+		   int, S_IRUGO);
+MODULE_PARM_DESC(amsdu_size_8K, "enable 8K amsdu size");
+module_param_named(fw_restart, iwl4965_mod_params.restart_fw, int, S_IRUGO);
+MODULE_PARM_DESC(fw_restart, "restart firmware in case of error");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965.c	2012-03-24 03:33:26.000000000 -0400
@@ -0,0 +1,2188 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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 <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-calib.h"
+#include "iwl-sta.h"
+#include "iwl-4965-led.h"
+#include "iwl-4965.h"
+#include "iwl-4965-debugfs.h"
+
+static int iwl4965_send_tx_power(struct iwl_priv *priv);
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
+
+/* Highest firmware API version supported */
+#define IWL4965_UCODE_API_MAX 2
+
+/* Lowest firmware API version supported */
+#define IWL4965_UCODE_API_MIN 2
+
+#define IWL4965_FW_PRE "/*(DEBLOBBED)*/"
+#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE /*(DEBLOBBED)*/
+#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
+
+/* check contents of special bootstrap uCode SRAM */
+static int iwl4965_verify_bsm(struct iwl_priv *priv)
+{
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	u32 reg;
+	u32 val;
+
+	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
+
+	/* verify BSM SRAM contents */
+	val = iwl_legacy_read_prph(priv, BSM_WR_DWCOUNT_REG);
+	for (reg = BSM_SRAM_LOWER_BOUND;
+	     reg < BSM_SRAM_LOWER_BOUND + len;
+	     reg += sizeof(u32), image++) {
+		val = iwl_legacy_read_prph(priv, reg);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "BSM uCode verification failed at "
+				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
+				  BSM_SRAM_LOWER_BOUND,
+				  reg - BSM_SRAM_LOWER_BOUND, len,
+				  val, le32_to_cpu(*image));
+			return -EIO;
+		}
+	}
+
+	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
+
+	return 0;
+}
+
+/**
+ * iwl4965_load_bsm - Load bootstrap instructions
+ *
+ * BSM operation:
+ *
+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+ * in special SRAM that does not power down during RFKILL.  When powering back
+ * up after power-saving sleeps (or during initial uCode load), the BSM loads
+ * the bootstrap program into the on-board processor, and starts it.
+ *
+ * The bootstrap program loads (via DMA) instructions and data for a new
+ * program from host DRAM locations indicated by the host driver in the
+ * BSM_DRAM_* registers.  Once the new program is loaded, it starts
+ * automatically.
+ *
+ * When initializing the NIC, the host driver points the BSM to the
+ * "initialize" uCode image.  This uCode sets up some internal data, then
+ * notifies host via "initialize alive" that it is complete.
+ *
+ * The host then replaces the BSM_DRAM_* pointer values to point to the
+ * normal runtime uCode instructions and a backup uCode data cache buffer
+ * (filled initially with starting data values for the on-board processor),
+ * then triggers the "initialize" uCode to load and launch the runtime uCode,
+ * which begins normal operation.
+ *
+ * When doing a power-save shutdown, runtime uCode saves data SRAM into
+ * the backup data cache in DRAM before SRAM is powered down.
+ *
+ * When powering back up, the BSM loads the bootstrap program.  This reloads
+ * the runtime uCode instructions and the backup data cache into SRAM,
+ * and re-launches the runtime uCode from where it left off.
+ */
+static int iwl4965_load_bsm(struct iwl_priv *priv)
+{
+	__le32 *image = priv->ucode_boot.v_addr;
+	u32 len = priv->ucode_boot.len;
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+	u32 inst_len;
+	u32 data_len;
+	int i;
+	u32 done;
+	u32 reg_offset;
+	int ret;
+
+	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
+
+	priv->ucode_type = UCODE_RT;
+
+	/* make sure bootstrap program is no larger than BSM's SRAM size */
+	if (len > IWL49_MAX_BSM_SIZE)
+		return -EINVAL;
+
+	/* Tell bootstrap uCode where to find the "Initialize" uCode
+	 *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
+	 * NOTE:  iwl_init_alive_start() will replace these values,
+	 *        after the "initialize" uCode has run, to point to
+	 *        runtime/protocol instructions and backup data cache.
+	 */
+	pinst = priv->ucode_init.p_addr >> 4;
+	pdata = priv->ucode_init_data.p_addr >> 4;
+	inst_len = priv->ucode_init.len;
+	data_len = priv->ucode_init_data.len;
+
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG, inst_len);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
+
+	/* Fill BSM memory with bootstrap instructions */
+	for (reg_offset = BSM_SRAM_LOWER_BOUND;
+	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
+	     reg_offset += sizeof(u32), image++)
+		_iwl_legacy_write_prph(priv, reg_offset, le32_to_cpu(*image));
+
+	ret = iwl4965_verify_bsm(priv);
+	if (ret)
+		return ret;
+
+	/* Tell BSM to copy from BSM SRAM into instruction SRAM, when asked */
+	iwl_legacy_write_prph(priv, BSM_WR_MEM_SRC_REG, 0x0);
+	iwl_legacy_write_prph(priv,
+			BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
+	iwl_legacy_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
+
+	/* Load bootstrap code into instruction SRAM now,
+	 *   to prepare to load "initialize" uCode */
+	iwl_legacy_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
+
+	/* Wait for load of bootstrap uCode to finish */
+	for (i = 0; i < 100; i++) {
+		done = iwl_legacy_read_prph(priv, BSM_WR_CTRL_REG);
+		if (!(done & BSM_WR_CTRL_REG_BIT_START))
+			break;
+		udelay(10);
+	}
+	if (i < 100)
+		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
+	else {
+		IWL_ERR(priv, "BSM write did not complete!\n");
+		return -EIO;
+	}
+
+	/* Enable future boot loads whenever power management unit triggers it
+	 *   (e.g. when powering back up after power-save shutdown) */
+	iwl_legacy_write_prph(priv,
+			BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START_EN);
+
+
+	return 0;
+}
+
+/**
+ * iwl4965_set_ucode_ptrs - Set uCode address location
+ *
+ * Tell initialization uCode where to find runtime uCode.
+ *
+ * BSM registers initially contain pointers to initialization uCode.
+ * We need to replace them to load runtime uCode inst and data,
+ * and to save runtime data when powering down.
+ */
+static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
+{
+	dma_addr_t pinst;
+	dma_addr_t pdata;
+	int ret = 0;
+
+	/* bits 35:4 for 4965 */
+	pinst = priv->ucode_code.p_addr >> 4;
+	pdata = priv->ucode_data_backup.p_addr >> 4;
+
+	/* Tell bootstrap uCode where to find image to load */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_PTR_REG, pinst);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_PTR_REG, pdata);
+	iwl_legacy_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
+				 priv->ucode_data.len);
+
+	/* Inst byte count must be last to set up, bit 31 signals uCode
+	 *   that all new ptr/size info is in place */
+	iwl_legacy_write_prph(priv, BSM_DRAM_INST_BYTECOUNT_REG,
+				 priv->ucode_code.len | BSM_DRAM_INST_LOAD);
+	IWL_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
+
+	return ret;
+}
+
+/**
+ * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
+ *
+ * Called after REPLY_ALIVE notification received from "initialize" uCode.
+ *
+ * The 4965 "initialize" ALIVE reply contains calibration data for:
+ *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
+ *   (3945 does not contain this data).
+ *
+ * Tell "initialize" uCode to go ahead and load the runtime uCode.
+*/
+static void iwl4965_init_alive_start(struct iwl_priv *priv)
+{
+	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
+	 * This is a paranoid check, because we would not have gotten the
+	 * "initialize" alive if code weren't properly loaded.  */
+	if (iwl4965_verify_ucode(priv)) {
+		/* Runtime instruction load was bad;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
+		goto restart;
+	}
+
+	/* Calculate temperature */
+	priv->temperature = iwl4965_hw_get_temperature(priv);
+
+	/* Send pointers to protocol/runtime uCode image ... init code will
+	 * load and launch runtime uCode, which will send us another "Alive"
+	 * notification. */
+	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+	if (iwl4965_set_ucode_ptrs(priv)) {
+		/* Runtime instruction load won't happen;
+		 * take it all the way back down so we can try again */
+		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
+		goto restart;
+	}
+	return;
+
+restart:
+	queue_work(priv->workqueue, &priv->restart);
+}
+
+static bool iw4965_is_ht40_channel(__le32 rxon_flags)
+{
+	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));
+}
+
+static void iwl4965_nic_config(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	u16 radio_cfg;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	radio_cfg = iwl_legacy_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+	/* write radio config values to register */
+	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+
+	/* set CSR_HW_CONFIG_REG for uCode use */
+	iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+
+	priv->calib_info = (struct iwl_eeprom_calib_info *)
+		iwl_legacy_eeprom_query_addr(priv,
+				EEPROM_4965_CALIB_TXPOWER_OFFSET);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
+ * Called after every association, but this runs only once!
+ *  ... once chain noise is calibrated the first time, it's good forever.  */
+static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
+{
+	struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
+
+	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
+	    iwl_legacy_is_any_associated(priv)) {
+		struct iwl_calib_diff_gain_cmd cmd;
+
+		/* clear data for chain noise calibration algorithm */
+		data->chain_noise_a = 0;
+		data->chain_noise_b = 0;
+		data->chain_noise_c = 0;
+		data->chain_signal_a = 0;
+		data->chain_signal_b = 0;
+		data->chain_signal_c = 0;
+		data->beacon_count = 0;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
+		cmd.diff_gain_a = 0;
+		cmd.diff_gain_b = 0;
+		cmd.diff_gain_c = 0;
+		if (iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+				 sizeof(cmd), &cmd))
+			IWL_ERR(priv,
+				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
+		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
+		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
+	}
+}
+
+static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
+	.min_nrg_cck = 97,
+	.max_nrg_cck = 0, /* not used, set to 0 */
+
+	.auto_corr_min_ofdm = 85,
+	.auto_corr_min_ofdm_mrc = 170,
+	.auto_corr_min_ofdm_x1 = 105,
+	.auto_corr_min_ofdm_mrc_x1 = 220,
+
+	.auto_corr_max_ofdm = 120,
+	.auto_corr_max_ofdm_mrc = 210,
+	.auto_corr_max_ofdm_x1 = 140,
+	.auto_corr_max_ofdm_mrc_x1 = 270,
+
+	.auto_corr_min_cck = 125,
+	.auto_corr_max_cck = 200,
+	.auto_corr_min_cck_mrc = 200,
+	.auto_corr_max_cck_mrc = 400,
+
+	.nrg_th_cck = 100,
+	.nrg_th_ofdm = 100,
+
+	.barker_corr_th_min = 190,
+	.barker_corr_th_min_mrc = 390,
+	.nrg_th_cca = 62,
+};
+
+static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
+{
+	/* want Kelvin */
+	priv->hw_params.ct_kill_threshold =
+		CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
+}
+
+/**
+ * iwl4965_hw_set_hw_params
+ *
+ * Called when initializing driver
+ */
+static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
+{
+	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
+	    priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
+		priv->cfg->base_params->num_of_queues =
+			priv->cfg->mod_params->num_of_queues;
+
+	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
+	priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
+	priv->hw_params.scd_bc_tbls_size =
+			priv->cfg->base_params->num_of_queues *
+			sizeof(struct iwl4965_scd_bc_tbl);
+	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
+	priv->hw_params.max_stations = IWL4965_STATION_COUNT;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
+	priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
+	priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
+	priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
+	priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
+
+	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
+	priv->hw_params.tx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_tx_ant);
+	priv->hw_params.rx_chains_num = iwl4965_num_of_ant(priv->cfg->valid_rx_ant);
+	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
+	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+
+	iwl4965_set_ct_threshold(priv);
+
+	priv->hw_params.sens = &iwl4965_sensitivity;
+	priv->hw_params.beacon_time_tsf_bits = IWL4965_EXT_BEACON_TIME_POS;
+
+	return 0;
+}
+
+static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
+{
+	s32 sign = 1;
+
+	if (num < 0) {
+		sign = -sign;
+		num = -num;
+	}
+	if (denom < 0) {
+		sign = -sign;
+		denom = -denom;
+	}
+	*res = 1;
+	*res = ((num * 2 + denom) / (denom * 2)) * sign;
+
+	return 1;
+}
+
+/**
+ * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
+ *
+ * Determines power supply voltage compensation for txpower calculations.
+ * Returns number of 1/2-dB steps to subtract from gain table index,
+ * to compensate for difference between power supply voltage during
+ * factory measurements, vs. current power supply voltage.
+ *
+ * Voltage indication is higher for lower voltage.
+ * Lower voltage requires more gain (lower gain table index).
+ */
+static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
+					    s32 current_voltage)
+{
+	s32 comp = 0;
+
+	if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) ||
+	    (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage))
+		return 0;
+
+	iwl4965_math_div_round(current_voltage - eeprom_voltage,
+			       TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp);
+
+	if (current_voltage > eeprom_voltage)
+		comp *= 2;
+	if ((comp < -2) || (comp > 2))
+		comp = 0;
+
+	return comp;
+}
+
+static s32 iwl4965_get_tx_atten_grp(u16 channel)
+{
+	if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR5_LCH)
+		return CALIB_CH_GROUP_5;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR1_LCH)
+		return CALIB_CH_GROUP_1;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR2_LCH)
+		return CALIB_CH_GROUP_2;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR3_LCH)
+		return CALIB_CH_GROUP_3;
+
+	if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH &&
+	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
+		return CALIB_CH_GROUP_4;
+
+	return -1;
+}
+
+static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
+{
+	s32 b = -1;
+
+	for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
+		if (priv->calib_info->band_info[b].ch_from == 0)
+			continue;
+
+		if ((channel >= priv->calib_info->band_info[b].ch_from)
+		    && (channel <= priv->calib_info->band_info[b].ch_to))
+			break;
+	}
+
+	return b;
+}
+
+static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
+{
+	s32 val;
+
+	if (x2 == x1)
+		return y1;
+	else {
+		iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
+		return val + y2;
+	}
+}
+
+/**
+ * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
+ *
+ * Interpolates factory measurements from the two sample channels within a
+ * sub-band, to apply to channel of interest.  Interpolation is proportional to
+ * differences in channel frequencies, which is proportional to differences
+ * in channel number.
+ */
+static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
+				    struct iwl_eeprom_calib_ch_info *chan_info)
+{
+	s32 s = -1;
+	u32 c;
+	u32 m;
+	const struct iwl_eeprom_calib_measure *m1;
+	const struct iwl_eeprom_calib_measure *m2;
+	struct iwl_eeprom_calib_measure *omeas;
+	u32 ch_i1;
+	u32 ch_i2;
+
+	s = iwl4965_get_sub_band(priv, channel);
+	if (s >= EEPROM_TX_POWER_BANDS) {
+		IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
+		return -1;
+	}
+
+	ch_i1 = priv->calib_info->band_info[s].ch1.ch_num;
+	ch_i2 = priv->calib_info->band_info[s].ch2.ch_num;
+	chan_info->ch_num = (u8) channel;
+
+	IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n",
+			  channel, s, ch_i1, ch_i2);
+
+	for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
+		for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
+			m1 = &(priv->calib_info->band_info[s].ch1.
+			       measurements[c][m]);
+			m2 = &(priv->calib_info->band_info[s].ch2.
+			       measurements[c][m]);
+			omeas = &(chan_info->measurements[c][m]);
+
+			omeas->actual_pow =
+			    (u8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->actual_pow,
+							   ch_i2,
+							   m2->actual_pow);
+			omeas->gain_idx =
+			    (u8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->gain_idx, ch_i2,
+							   m2->gain_idx);
+			omeas->temperature =
+			    (u8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->temperature,
+							   ch_i2,
+							   m2->temperature);
+			omeas->pa_det =
+			    (s8) iwl4965_interpolate_value(channel, ch_i1,
+							   m1->pa_det, ch_i2,
+							   m2->pa_det);
+
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m,
+				m1->actual_pow, m2->actual_pow, omeas->actual_pow);
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m,
+				m1->gain_idx, m2->gain_idx, omeas->gain_idx);
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m,
+				m1->pa_det, m2->pa_det, omeas->pa_det);
+			IWL_DEBUG_TXPOWER(priv,
+				"chain %d meas %d  T1=%d  T2=%d  T=%d\n", c, m,
+				m1->temperature, m2->temperature,
+				omeas->temperature);
+		}
+	}
+
+	return 0;
+}
+
+/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
+ * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
+static s32 back_off_table[] = {
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 20 MHz */
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 20 MHz */
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 40 MHz */
+	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 40 MHz */
+	10			/* CCK */
+};
+
+/* Thermal compensation values for txpower for various frequency ranges ...
+ *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
+static struct iwl4965_txpower_comp_entry {
+	s32 degrees_per_05db_a;
+	s32 degrees_per_05db_a_denom;
+} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
+	{9, 2},			/* group 0 5.2, ch  34-43 */
+	{4, 1},			/* group 1 5.2, ch  44-70 */
+	{4, 1},			/* group 2 5.2, ch  71-124 */
+	{4, 1},			/* group 3 5.2, ch 125-200 */
+	{3, 1}			/* group 4 2.4, ch   all */
+};
+
+static s32 get_min_power_index(s32 rate_power_index, u32 band)
+{
+	if (!band) {
+		if ((rate_power_index & 7) <= 4)
+			return MIN_TX_GAIN_INDEX_52GHZ_EXT;
+	}
+	return MIN_TX_GAIN_INDEX;
+}
+
+struct gain_entry {
+	u8 dsp;
+	u8 radio;
+};
+
+static const struct gain_entry gain_table[2][108] = {
+	/* 5.2GHz power gain index table */
+	{
+	 {123, 0x3F},		/* highest txpower */
+	 {117, 0x3F},
+	 {110, 0x3F},
+	 {104, 0x3F},
+	 {98, 0x3F},
+	 {110, 0x3E},
+	 {104, 0x3E},
+	 {98, 0x3E},
+	 {110, 0x3D},
+	 {104, 0x3D},
+	 {98, 0x3D},
+	 {110, 0x3C},
+	 {104, 0x3C},
+	 {98, 0x3C},
+	 {110, 0x3B},
+	 {104, 0x3B},
+	 {98, 0x3B},
+	 {110, 0x3A},
+	 {104, 0x3A},
+	 {98, 0x3A},
+	 {110, 0x39},
+	 {104, 0x39},
+	 {98, 0x39},
+	 {110, 0x38},
+	 {104, 0x38},
+	 {98, 0x38},
+	 {110, 0x37},
+	 {104, 0x37},
+	 {98, 0x37},
+	 {110, 0x36},
+	 {104, 0x36},
+	 {98, 0x36},
+	 {110, 0x35},
+	 {104, 0x35},
+	 {98, 0x35},
+	 {110, 0x34},
+	 {104, 0x34},
+	 {98, 0x34},
+	 {110, 0x33},
+	 {104, 0x33},
+	 {98, 0x33},
+	 {110, 0x32},
+	 {104, 0x32},
+	 {98, 0x32},
+	 {110, 0x31},
+	 {104, 0x31},
+	 {98, 0x31},
+	 {110, 0x30},
+	 {104, 0x30},
+	 {98, 0x30},
+	 {110, 0x25},
+	 {104, 0x25},
+	 {98, 0x25},
+	 {110, 0x24},
+	 {104, 0x24},
+	 {98, 0x24},
+	 {110, 0x23},
+	 {104, 0x23},
+	 {98, 0x23},
+	 {110, 0x22},
+	 {104, 0x18},
+	 {98, 0x18},
+	 {110, 0x17},
+	 {104, 0x17},
+	 {98, 0x17},
+	 {110, 0x16},
+	 {104, 0x16},
+	 {98, 0x16},
+	 {110, 0x15},
+	 {104, 0x15},
+	 {98, 0x15},
+	 {110, 0x14},
+	 {104, 0x14},
+	 {98, 0x14},
+	 {110, 0x13},
+	 {104, 0x13},
+	 {98, 0x13},
+	 {110, 0x12},
+	 {104, 0x08},
+	 {98, 0x08},
+	 {110, 0x07},
+	 {104, 0x07},
+	 {98, 0x07},
+	 {110, 0x06},
+	 {104, 0x06},
+	 {98, 0x06},
+	 {110, 0x05},
+	 {104, 0x05},
+	 {98, 0x05},
+	 {110, 0x04},
+	 {104, 0x04},
+	 {98, 0x04},
+	 {110, 0x03},
+	 {104, 0x03},
+	 {98, 0x03},
+	 {110, 0x02},
+	 {104, 0x02},
+	 {98, 0x02},
+	 {110, 0x01},
+	 {104, 0x01},
+	 {98, 0x01},
+	 {110, 0x00},
+	 {104, 0x00},
+	 {98, 0x00},
+	 {93, 0x00},
+	 {88, 0x00},
+	 {83, 0x00},
+	 {78, 0x00},
+	 },
+	/* 2.4GHz power gain index table */
+	{
+	 {110, 0x3f},		/* highest txpower */
+	 {104, 0x3f},
+	 {98, 0x3f},
+	 {110, 0x3e},
+	 {104, 0x3e},
+	 {98, 0x3e},
+	 {110, 0x3d},
+	 {104, 0x3d},
+	 {98, 0x3d},
+	 {110, 0x3c},
+	 {104, 0x3c},
+	 {98, 0x3c},
+	 {110, 0x3b},
+	 {104, 0x3b},
+	 {98, 0x3b},
+	 {110, 0x3a},
+	 {104, 0x3a},
+	 {98, 0x3a},
+	 {110, 0x39},
+	 {104, 0x39},
+	 {98, 0x39},
+	 {110, 0x38},
+	 {104, 0x38},
+	 {98, 0x38},
+	 {110, 0x37},
+	 {104, 0x37},
+	 {98, 0x37},
+	 {110, 0x36},
+	 {104, 0x36},
+	 {98, 0x36},
+	 {110, 0x35},
+	 {104, 0x35},
+	 {98, 0x35},
+	 {110, 0x34},
+	 {104, 0x34},
+	 {98, 0x34},
+	 {110, 0x33},
+	 {104, 0x33},
+	 {98, 0x33},
+	 {110, 0x32},
+	 {104, 0x32},
+	 {98, 0x32},
+	 {110, 0x31},
+	 {104, 0x31},
+	 {98, 0x31},
+	 {110, 0x30},
+	 {104, 0x30},
+	 {98, 0x30},
+	 {110, 0x6},
+	 {104, 0x6},
+	 {98, 0x6},
+	 {110, 0x5},
+	 {104, 0x5},
+	 {98, 0x5},
+	 {110, 0x4},
+	 {104, 0x4},
+	 {98, 0x4},
+	 {110, 0x3},
+	 {104, 0x3},
+	 {98, 0x3},
+	 {110, 0x2},
+	 {104, 0x2},
+	 {98, 0x2},
+	 {110, 0x1},
+	 {104, 0x1},
+	 {98, 0x1},
+	 {110, 0x0},
+	 {104, 0x0},
+	 {98, 0x0},
+	 {97, 0},
+	 {96, 0},
+	 {95, 0},
+	 {94, 0},
+	 {93, 0},
+	 {92, 0},
+	 {91, 0},
+	 {90, 0},
+	 {89, 0},
+	 {88, 0},
+	 {87, 0},
+	 {86, 0},
+	 {85, 0},
+	 {84, 0},
+	 {83, 0},
+	 {82, 0},
+	 {81, 0},
+	 {80, 0},
+	 {79, 0},
+	 {78, 0},
+	 {77, 0},
+	 {76, 0},
+	 {75, 0},
+	 {74, 0},
+	 {73, 0},
+	 {72, 0},
+	 {71, 0},
+	 {70, 0},
+	 {69, 0},
+	 {68, 0},
+	 {67, 0},
+	 {66, 0},
+	 {65, 0},
+	 {64, 0},
+	 {63, 0},
+	 {62, 0},
+	 {61, 0},
+	 {60, 0},
+	 {59, 0},
+	 }
+};
+
+static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
+				    u8 is_ht40, u8 ctrl_chan_high,
+				    struct iwl4965_tx_power_db *tx_power_tbl)
+{
+	u8 saturation_power;
+	s32 target_power;
+	s32 user_target_power;
+	s32 power_limit;
+	s32 current_temp;
+	s32 reg_limit;
+	s32 current_regulatory;
+	s32 txatten_grp = CALIB_CH_GROUP_MAX;
+	int i;
+	int c;
+	const struct iwl_channel_info *ch_info = NULL;
+	struct iwl_eeprom_calib_ch_info ch_eeprom_info;
+	const struct iwl_eeprom_calib_measure *measurement;
+	s16 voltage;
+	s32 init_voltage;
+	s32 voltage_compensation;
+	s32 degrees_per_05db_num;
+	s32 degrees_per_05db_denom;
+	s32 factory_temp;
+	s32 temperature_comp[2];
+	s32 factory_gain_index[2];
+	s32 factory_actual_pwr[2];
+	s32 power_index;
+
+	/* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
+	 *   are used for indexing into txpower table) */
+	user_target_power = 2 * priv->tx_power_user_lmt;
+
+	/* Get current (RXON) channel, band, width */
+	IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
+			  is_ht40);
+
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band, channel);
+
+	if (!iwl_legacy_is_channel_valid(ch_info))
+		return -EINVAL;
+
+	/* get txatten group, used to select 1) thermal txpower adjustment
+	 *   and 2) mimo txpower balance between Tx chains. */
+	txatten_grp = iwl4965_get_tx_atten_grp(channel);
+	if (txatten_grp < 0) {
+		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
+			  channel);
+		return -EINVAL;
+	}
+
+	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
+			  channel, txatten_grp);
+
+	if (is_ht40) {
+		if (ctrl_chan_high)
+			channel -= 2;
+		else
+			channel += 2;
+	}
+
+	/* hardware txpower limits ...
+	 * saturation (clipping distortion) txpowers are in half-dBm */
+	if (band)
+		saturation_power = priv->calib_info->saturation_power24;
+	else
+		saturation_power = priv->calib_info->saturation_power52;
+
+	if (saturation_power < IWL_TX_POWER_SATURATION_MIN ||
+	    saturation_power > IWL_TX_POWER_SATURATION_MAX) {
+		if (band)
+			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24;
+		else
+			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52;
+	}
+
+	/* regulatory txpower limits ... reg_limit values are in half-dBm,
+	 *   max_power_avg values are in dBm, convert * 2 */
+	if (is_ht40)
+		reg_limit = ch_info->ht40_max_power_avg * 2;
+	else
+		reg_limit = ch_info->max_power_avg * 2;
+
+	if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) ||
+	    (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) {
+		if (band)
+			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24;
+		else
+			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52;
+	}
+
+	/* Interpolate txpower calibration values for this channel,
+	 *   based on factory calibration tests on spaced channels. */
+	iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
+
+	/* calculate tx gain adjustment based on power supply voltage */
+	voltage = le16_to_cpu(priv->calib_info->voltage);
+	init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
+	voltage_compensation =
+	    iwl4965_get_voltage_compensation(voltage, init_voltage);
+
+	IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n",
+			  init_voltage,
+			  voltage, voltage_compensation);
+
+	/* get current temperature (Celsius) */
+	current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN);
+	current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX);
+	current_temp = KELVIN_TO_CELSIUS(current_temp);
+
+	/* select thermal txpower adjustment params, based on channel group
+	 *   (same frequency group used for mimo txatten adjustment) */
+	degrees_per_05db_num =
+	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
+	degrees_per_05db_denom =
+	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
+
+	/* get per-chain txpower values from factory measurements */
+	for (c = 0; c < 2; c++) {
+		measurement = &ch_eeprom_info.measurements[c][1];
+
+		/* txgain adjustment (in half-dB steps) based on difference
+		 *   between factory and current temperature */
+		factory_temp = measurement->temperature;
+		iwl4965_math_div_round((current_temp - factory_temp) *
+				       degrees_per_05db_denom,
+				       degrees_per_05db_num,
+				       &temperature_comp[c]);
+
+		factory_gain_index[c] = measurement->gain_idx;
+		factory_actual_pwr[c] = measurement->actual_pow;
+
+		IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c);
+		IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, "
+				  "curr tmp %d, comp %d steps\n",
+				  factory_temp, current_temp,
+				  temperature_comp[c]);
+
+		IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n",
+				  factory_gain_index[c],
+				  factory_actual_pwr[c]);
+	}
+
+	/* for each of 33 bit-rates (including 1 for CCK) */
+	for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
+		u8 is_mimo_rate;
+		union iwl4965_tx_power_dual_stream tx_power;
+
+		/* for mimo, reduce each chain's txpower by half
+		 * (3dB, 6 steps), so total output power is regulatory
+		 * compliant. */
+		if (i & 0x8) {
+			current_regulatory = reg_limit -
+			    IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
+			is_mimo_rate = 1;
+		} else {
+			current_regulatory = reg_limit;
+			is_mimo_rate = 0;
+		}
+
+		/* find txpower limit, either hardware or regulatory */
+		power_limit = saturation_power - back_off_table[i];
+		if (power_limit > current_regulatory)
+			power_limit = current_regulatory;
+
+		/* reduce user's txpower request if necessary
+		 * for this rate on this channel */
+		target_power = user_target_power;
+		if (target_power > power_limit)
+			target_power = power_limit;
+
+		IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n",
+				  i, saturation_power - back_off_table[i],
+				  current_regulatory, user_target_power,
+				  target_power);
+
+		/* for each of 2 Tx chains (radio transmitters) */
+		for (c = 0; c < 2; c++) {
+			s32 atten_value;
+
+			if (is_mimo_rate)
+				atten_value =
+				    (s32)le32_to_cpu(priv->card_alive_init.
+				    tx_atten[txatten_grp][c]);
+			else
+				atten_value = 0;
+
+			/* calculate index; higher index means lower txpower */
+			power_index = (u8) (factory_gain_index[c] -
+					    (target_power -
+					     factory_actual_pwr[c]) -
+					    temperature_comp[c] -
+					    voltage_compensation +
+					    atten_value);
+
+/*			IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n",
+						power_index); */
+
+			if (power_index < get_min_power_index(i, band))
+				power_index = get_min_power_index(i, band);
+
+			/* adjust 5 GHz index to support negative indexes */
+			if (!band)
+				power_index += 9;
+
+			/* CCK, rate 32, reduce txpower for CCK */
+			if (i == POWER_TABLE_CCK_ENTRY)
+				power_index +=
+				    IWL_TX_POWER_CCK_COMPENSATION_C_STEP;
+
+			/* stay within the table! */
+			if (power_index > 107) {
+				IWL_WARN(priv, "txpower index %d > 107\n",
+					    power_index);
+				power_index = 107;
+			}
+			if (power_index < 0) {
+				IWL_WARN(priv, "txpower index %d < 0\n",
+					    power_index);
+				power_index = 0;
+			}
+
+			/* fill txpower command for this rate/chain */
+			tx_power.s.radio_tx_gain[c] =
+				gain_table[band][power_index].radio;
+			tx_power.s.dsp_predis_atten[c] =
+				gain_table[band][power_index].dsp;
+
+			IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d "
+					  "gain 0x%02x dsp %d\n",
+					  c, atten_value, power_index,
+					tx_power.s.radio_tx_gain[c],
+					tx_power.s.dsp_predis_atten[c]);
+		} /* for each chain */
+
+		tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
+
+	} /* for each rate */
+
+	return 0;
+}
+
+/**
+ * iwl4965_send_tx_power - Configure the TXPOWER level user limit
+ *
+ * Uses the active RXON for channel, band, and characteristics (ht40, high)
+ * The power limit is taken from priv->tx_power_user_lmt.
+ */
+static int iwl4965_send_tx_power(struct iwl_priv *priv)
+{
+	struct iwl4965_txpowertable_cmd cmd = { 0 };
+	int ret;
+	u8 band = 0;
+	bool is_ht40 = false;
+	u8 ctrl_chan_high = 0;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
+		      "TX Power requested while scanning!\n"))
+		return -EAGAIN;
+
+	band = priv->band == IEEE80211_BAND_2GHZ;
+
+	is_ht40 = iw4965_is_ht40_channel(ctx->active.flags);
+
+	if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+		ctrl_chan_high = 1;
+
+	cmd.band = band;
+	cmd.channel = ctx->active.channel;
+
+	ret = iwl4965_fill_txpower_tbl(priv, band,
+				le16_to_cpu(ctx->active.channel),
+				is_ht40, ctrl_chan_high, &cmd.tx_power);
+	if (ret)
+		goto out;
+
+	ret = iwl_legacy_send_cmd_pdu(priv,
+			 REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
+
+out:
+	return ret;
+}
+
+static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
+{
+	int ret = 0;
+	struct iwl4965_rxon_assoc_cmd rxon_assoc;
+	const struct iwl_legacy_rxon_cmd *rxon1 = &ctx->staging;
+	const struct iwl_legacy_rxon_cmd *rxon2 = &ctx->active;
+
+	if ((rxon1->flags == rxon2->flags) &&
+	    (rxon1->filter_flags == rxon2->filter_flags) &&
+	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
+	    (rxon1->ofdm_ht_single_stream_basic_rates ==
+	     rxon2->ofdm_ht_single_stream_basic_rates) &&
+	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
+	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
+	    (rxon1->rx_chain == rxon2->rx_chain) &&
+	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
+		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
+		return 0;
+	}
+
+	rxon_assoc.flags = ctx->staging.flags;
+	rxon_assoc.filter_flags = ctx->staging.filter_flags;
+	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
+	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
+	rxon_assoc.reserved = 0;
+	rxon_assoc.ofdm_ht_single_stream_basic_rates =
+	    ctx->staging.ofdm_ht_single_stream_basic_rates;
+	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
+	    ctx->staging.ofdm_ht_dual_stream_basic_rates;
+	rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
+
+	ret = iwl_legacy_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
+				     sizeof(rxon_assoc), &rxon_assoc, NULL);
+	if (ret)
+		return ret;
+
+	return ret;
+}
+
+static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	/* cast away the const for active_rxon in this function */
+	struct iwl_legacy_rxon_cmd *active_rxon = (void *)&ctx->active;
+	int ret;
+	bool new_assoc =
+		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EBUSY;
+
+	if (!ctx->is_active)
+		return 0;
+
+	/* always get timestamp with Rx frame */
+	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
+
+	ret = iwl_legacy_check_rxon_cmd(priv, ctx);
+	if (ret) {
+		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * receive commit_rxon request
+	 * abort any previous channel switch if still in process
+	 */
+	if (priv->switch_rxon.switch_in_progress &&
+	    (priv->switch_rxon.channel != ctx->staging.channel)) {
+		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
+		      le16_to_cpu(priv->switch_rxon.channel));
+		iwl_legacy_chswitch_done(priv, false);
+	}
+
+	/* If we don't need to send a full RXON, we can use
+	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
+	 * and other flags for the current radio configuration. */
+	if (!iwl_legacy_full_rxon_required(priv, ctx)) {
+		ret = iwl_legacy_send_rxon_assoc(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
+			return ret;
+		}
+
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_legacy_print_rx_config_cmd(priv, ctx);
+		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_legacy_is_associated_ctx(ctx) && new_assoc) {
+		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
+		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+
+		ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
+				       sizeof(struct iwl_legacy_rxon_cmd),
+				       active_rxon);
+
+		/* If the mask clearing failed then we set
+		 * active_rxon back to what it was previously */
+		if (ret) {
+			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
+			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
+			return ret;
+		}
+		iwl_legacy_clear_ucode_stations(priv, ctx);
+		iwl_legacy_restore_stations(priv, ctx);
+		ret = iwl4965_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+
+	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(ctx->staging.channel),
+		       ctx->staging.bssid_addr);
+
+	iwl_legacy_set_rxon_hwcrypto(priv, ctx,
+				!priv->cfg->mod_params->sw_crypto);
+
+	/* Apply the new configuration
+	 * RXON unassoc clears the station table in uCode so restoration of
+	 * stations is needed after it (the RXON command) completes
+	 */
+	if (!new_assoc) {
+		ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+		iwl_legacy_clear_ucode_stations(priv, ctx);
+		iwl_legacy_restore_stations(priv, ctx);
+		ret = iwl4965_restore_default_wep_keys(priv, ctx);
+		if (ret) {
+			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
+			return ret;
+		}
+	}
+	if (new_assoc) {
+		priv->start_calib = 0;
+		/* Apply the new configuration
+		 * RXON assoc doesn't clear the station table in uCode,
+		 */
+		ret = iwl_legacy_send_cmd_pdu(priv, ctx->rxon_cmd,
+			      sizeof(struct iwl_legacy_rxon_cmd), &ctx->staging);
+		if (ret) {
+			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
+			return ret;
+		}
+		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
+	}
+	iwl_legacy_print_rx_config_cmd(priv, ctx);
+
+	iwl4965_init_sensitivity(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 */
+	ret = iwl_legacy_set_tx_power(priv, priv->tx_power_next, true);
+	if (ret) {
+		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
+				     struct ieee80211_channel_switch *ch_switch)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	int rc;
+	u8 band = 0;
+	bool is_ht40 = false;
+	u8 ctrl_chan_high = 0;
+	struct iwl4965_channel_switch_cmd cmd;
+	const struct iwl_channel_info *ch_info;
+	u32 switch_time_in_usec, ucode_switch_time;
+	u16 ch;
+	u32 tsf_low;
+	u8 switch_count;
+	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+	struct ieee80211_vif *vif = ctx->vif;
+	band = priv->band == IEEE80211_BAND_2GHZ;
+
+	is_ht40 = iw4965_is_ht40_channel(ctx->staging.flags);
+
+	if (is_ht40 &&
+	    (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
+		ctrl_chan_high = 1;
+
+	cmd.band = band;
+	cmd.expect_beacon = 0;
+	ch = ch_switch->channel->hw_value;
+	cmd.channel = cpu_to_le16(ch);
+	cmd.rxon_flags = ctx->staging.flags;
+	cmd.rxon_filter_flags = ctx->staging.filter_flags;
+	switch_count = ch_switch->count;
+	tsf_low = ch_switch->timestamp & 0x0ffffffff;
+	/*
+	 * calculate the ucode channel switch time
+	 * adding TSF as one of the factor for when to switch
+	 */
+	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
+		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
+		    beacon_interval)) {
+			switch_count -= (priv->ucode_beacon_time -
+				tsf_low) / beacon_interval;
+		} else
+			switch_count = 0;
+	}
+	if (switch_count <= 1)
+		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+	else {
+		switch_time_in_usec =
+			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+		ucode_switch_time = iwl_legacy_usecs_to_beacons(priv,
+							 switch_time_in_usec,
+							 beacon_interval);
+		cmd.switch_time = iwl_legacy_add_beacon_time(priv,
+						      priv->ucode_beacon_time,
+						      ucode_switch_time,
+						      beacon_interval);
+	}
+	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
+		      cmd.switch_time);
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band, ch);
+	if (ch_info)
+		cmd.expect_beacon = iwl_legacy_is_channel_radar(ch_info);
+	else {
+		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
+			ctx->active.channel, ch);
+		return -EFAULT;
+	}
+
+	rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
+				      ctrl_chan_high, &cmd.tx_power);
+	if (rc) {
+		IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
+		return rc;
+	}
+
+	priv->switch_rxon.channel = cmd.channel;
+	priv->switch_rxon.switch_in_progress = true;
+
+	return iwl_legacy_send_cmd_pdu(priv,
+			 REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
+}
+
+/**
+ * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
+ */
+static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
+					    struct iwl_tx_queue *txq,
+					    u16 byte_cnt)
+{
+	struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
+	int txq_id = txq->q.id;
+	int write_ptr = txq->q.write_ptr;
+	int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
+	__le16 bc_ent;
+
+	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
+
+	bc_ent = cpu_to_le16(len & 0xFFF);
+	/* Set up byte count within first 256 entries */
+	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
+
+	/* If within first 64 entries, duplicate at end */
+	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
+		scd_bc_tbl[txq_id].
+			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
+}
+
+/**
+ * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
+ * @statistics: Provides the temperature reading from the uCode
+ *
+ * A return of <0 indicates bogus data in the statistics
+ */
+static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
+{
+	s32 temperature;
+	s32 vt;
+	s32 R1, R2, R3;
+	u32 R4;
+
+	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
+	    (priv->_4965.statistics.flag &
+			STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
+		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
+		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
+		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
+		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
+		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]);
+	} else {
+		IWL_DEBUG_TEMP(priv, "Running temperature calibration\n");
+		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]);
+		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]);
+		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]);
+		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]);
+	}
+
+	/*
+	 * Temperature is only 23 bits, so sign extend out to 32.
+	 *
+	 * NOTE If we haven't received a statistics notification yet
+	 * with an updated temperature, use R4 provided to us in the
+	 * "initialize" ALIVE response.
+	 */
+	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
+		vt = sign_extend32(R4, 23);
+	else
+		vt = sign_extend32(le32_to_cpu(priv->_4965.statistics.
+				 general.common.temperature), 23);
+
+	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
+
+	if (R3 == R1) {
+		IWL_ERR(priv, "Calibration conflict R1 == R3\n");
+		return -1;
+	}
+
+	/* Calculate temperature in degrees Kelvin, adjust by 97%.
+	 * Add offset to center the adjustment around 0 degrees Centigrade. */
+	temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
+	temperature /= (R3 - R1);
+	temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
+
+	IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n",
+			temperature, KELVIN_TO_CELSIUS(temperature));
+
+	return temperature;
+}
+
+/* Adjust Txpower only if temperature variance is greater than threshold. */
+#define IWL_TEMPERATURE_THRESHOLD   3
+
+/**
+ * iwl4965_is_temp_calib_needed - determines if new calibration is needed
+ *
+ * If the temperature changed has changed sufficiently, then a recalibration
+ * is needed.
+ *
+ * Assumes caller will replace priv->last_temperature once calibration
+ * executed.
+ */
+static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
+{
+	int temp_diff;
+
+	if (!test_bit(STATUS_STATISTICS, &priv->status)) {
+		IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n");
+		return 0;
+	}
+
+	temp_diff = priv->temperature - priv->last_temperature;
+
+	/* get absolute value */
+	if (temp_diff < 0) {
+		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
+		temp_diff = -temp_diff;
+	} else if (temp_diff == 0)
+		IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
+	else
+		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
+
+	if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
+		IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
+		return 0;
+	}
+
+	IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
+
+	return 1;
+}
+
+static void iwl4965_temperature_calib(struct iwl_priv *priv)
+{
+	s32 temp;
+
+	temp = iwl4965_hw_get_temperature(priv);
+	if (temp < 0)
+		return;
+
+	if (priv->temperature != temp) {
+		if (priv->temperature)
+			IWL_DEBUG_TEMP(priv, "Temperature changed "
+				       "from %dC to %dC\n",
+				       KELVIN_TO_CELSIUS(priv->temperature),
+				       KELVIN_TO_CELSIUS(temp));
+		else
+			IWL_DEBUG_TEMP(priv, "Temperature "
+				       "initialized to %dC\n",
+				       KELVIN_TO_CELSIUS(temp));
+	}
+
+	priv->temperature = temp;
+	set_bit(STATUS_TEMPERATURE, &priv->status);
+
+	if (!priv->disable_tx_power_cal &&
+	     unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	     iwl4965_is_temp_calib_needed(priv))
+		queue_work(priv->workqueue, &priv->txpower_work);
+}
+
+static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
+{
+	switch (cmd_id) {
+	case REPLY_RXON:
+		return (u16) sizeof(struct iwl4965_rxon_cmd);
+	default:
+		return len;
+	}
+}
+
+static u16 iwl4965_build_addsta_hcmd(const struct iwl_legacy_addsta_cmd *cmd,
+								u8 *data)
+{
+	struct iwl4965_addsta_cmd *addsta = (struct iwl4965_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 = cmd->tid_disable_tx;
+	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;
+	addsta->sleep_tx_count = cmd->sleep_tx_count;
+	addsta->reserved1 = cpu_to_le16(0);
+	addsta->reserved2 = cpu_to_le16(0);
+
+	return (u16)sizeof(struct iwl4965_addsta_cmd);
+}
+
+static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
+{
+	return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
+}
+
+/**
+ * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
+ */
+static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
+				      struct iwl_ht_agg *agg,
+				      struct iwl4965_tx_resp *tx_resp,
+				      int txq_id, u16 start_idx)
+{
+	u16 status;
+	struct agg_tx_status *frame_status = tx_resp->u.agg_status;
+	struct ieee80211_tx_info *info = NULL;
+	struct ieee80211_hdr *hdr = NULL;
+	u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
+	int i, sh, idx;
+	u16 seq;
+	if (agg->wait_for_ba)
+		IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
+
+	agg->frame_count = tx_resp->frame_count;
+	agg->start_idx = start_idx;
+	agg->rate_n_flags = rate_n_flags;
+	agg->bitmap = 0;
+
+	/* num frames attempted by Tx command */
+	if (agg->frame_count == 1) {
+		/* Only one frame was attempted; no block-ack will arrive */
+		status = le16_to_cpu(frame_status[0].status);
+		idx = start_idx;
+
+		IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
+				   agg->frame_count, agg->start_idx, idx);
+
+		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
+		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+		info->flags |= iwl4965_tx_status_to_mac80211(status);
+		iwl4965_hwrate_to_tx_control(priv, rate_n_flags, info);
+
+		IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
+				    status & 0xff, tx_resp->failure_frame);
+		IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
+
+		agg->wait_for_ba = 0;
+	} else {
+		/* Two or more frames were attempted; expect block-ack */
+		u64 bitmap = 0;
+		int start = agg->start_idx;
+
+		/* Construct bit-map of pending frames within Tx window */
+		for (i = 0; i < agg->frame_count; i++) {
+			u16 sc;
+			status = le16_to_cpu(frame_status[i].status);
+			seq  = le16_to_cpu(frame_status[i].sequence);
+			idx = SEQ_TO_INDEX(seq);
+			txq_id = SEQ_TO_QUEUE(seq);
+
+			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
+				      AGG_TX_STATE_ABORT_MSK))
+				continue;
+
+			IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
+					   agg->frame_count, txq_id, idx);
+
+			hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, idx);
+			if (!hdr) {
+				IWL_ERR(priv,
+					"BUG_ON idx doesn't point to valid skb"
+					" idx=%d, txq_id=%d\n", idx, txq_id);
+				return -1;
+			}
+
+			sc = le16_to_cpu(hdr->seq_ctrl);
+			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
+				IWL_ERR(priv,
+					"BUG_ON idx doesn't match seq control"
+					" idx=%d, seq_idx=%d, seq=%d\n",
+					idx, SEQ_TO_SN(sc), hdr->seq_ctrl);
+				return -1;
+			}
+
+			IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
+					   i, idx, SEQ_TO_SN(sc));
+
+			sh = idx - start;
+			if (sh > 64) {
+				sh = (start - idx) + 0xff;
+				bitmap = bitmap << sh;
+				sh = 0;
+				start = idx;
+			} else if (sh < -64)
+				sh  = 0xff - (start - idx);
+			else if (sh < 0) {
+				sh = start - idx;
+				start = idx;
+				bitmap = bitmap << sh;
+				sh = 0;
+			}
+			bitmap |= 1ULL << sh;
+			IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
+					   start, (unsigned long long)bitmap);
+		}
+
+		agg->bitmap = bitmap;
+		agg->start_idx = start;
+		IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
+				   agg->frame_count, agg->start_idx,
+				   (unsigned long long)agg->bitmap);
+
+		if (bitmap)
+			agg->wait_for_ba = 1;
+	}
+	return 0;
+}
+
+static u8 iwl4965_find_station(struct iwl_priv *priv, const u8 *addr)
+{
+	int i;
+	int start = 0;
+	int ret = IWL_INVALID_STATION;
+	unsigned long flags;
+
+	if ((priv->iw_mode == NL80211_IFTYPE_ADHOC))
+		start = IWL_STA_ID;
+
+	if (is_broadcast_ether_addr(addr))
+		return priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	for (i = start; i < priv->hw_params.max_stations; i++)
+		if (priv->stations[i].used &&
+		    (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+					 addr))) {
+			ret = i;
+			goto out;
+		}
+
+	IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
+			      addr, priv->num_stations);
+
+ out:
+	/*
+	 * It may be possible that more commands interacting with stations
+	 * arrive before we completed processing the adding of
+	 * station
+	 */
+	if (ret != IWL_INVALID_STATION &&
+	    (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
+	     ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
+	      (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
+		IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
+			ret);
+		ret = IWL_INVALID_STATION;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	return ret;
+}
+
+static int iwl4965_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
+{
+	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
+		return IWL_AP_ID;
+	} else {
+		u8 *da = ieee80211_get_DA(hdr);
+		return iwl4965_find_station(priv, da);
+	}
+}
+
+/**
+ * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
+ */
+static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct ieee80211_hdr *hdr;
+	struct ieee80211_tx_info *info;
+	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
+	u32  status = le32_to_cpu(tx_resp->u.status);
+	int uninitialized_var(tid);
+	int sta_id;
+	int freed;
+	u8 *qc = NULL;
+	unsigned long flags;
+
+	if ((index >= txq->q.n_bd) || (iwl_legacy_queue_used(&txq->q, index) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
+			  "is out of range [0-%d] %d %d\n", txq_id,
+			  index, txq->q.n_bd, txq->q.write_ptr,
+			  txq->q.read_ptr);
+		return;
+	}
+
+	txq->time_stamp = jiffies;
+	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
+	memset(&info->status, 0, sizeof(info->status));
+
+	hdr = iwl_legacy_tx_queue_get_hdr(priv, txq_id, index);
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & 0xf;
+	}
+
+	sta_id = iwl4965_get_ra_sta_id(priv, hdr);
+	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
+		IWL_ERR(priv, "Station not known\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	if (txq->sched_retry) {
+		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
+		struct iwl_ht_agg *agg = NULL;
+		WARN_ON(!qc);
+
+		agg = &priv->stations[sta_id].tid[tid].agg;
+
+		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
+
+		/* check if BAR is needed */
+		if ((tx_resp->frame_count == 1) && !iwl4965_is_tx_success(status))
+			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
+
+		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
+			index = iwl_legacy_queue_dec_wrap(scd_ssn & 0xff,
+								txq->q.n_bd);
+			IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
+					   "%d index %d\n", scd_ssn , index);
+			freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+			if (qc)
+				iwl4965_free_tfds_in_queue(priv, sta_id,
+						       tid, freed);
+
+			if (priv->mac80211_registered &&
+			    (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark)
+				 && (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+				iwl_legacy_wake_queue(priv, txq);
+		}
+	} else {
+		info->status.rates[0].count = tx_resp->failure_frame + 1;
+		info->flags |= iwl4965_tx_status_to_mac80211(status);
+		iwl4965_hwrate_to_tx_control(priv,
+					le32_to_cpu(tx_resp->rate_n_flags),
+					info);
+
+		IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) "
+				   "rate_n_flags 0x%x retries %d\n",
+				   txq_id,
+				   iwl4965_get_tx_fail_reason(status), status,
+				   le32_to_cpu(tx_resp->rate_n_flags),
+				   tx_resp->failure_frame);
+
+		freed = iwl4965_tx_queue_reclaim(priv, txq_id, index);
+		if (qc && likely(sta_id != IWL_INVALID_STATION))
+			iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
+		else if (sta_id == IWL_INVALID_STATION)
+			IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
+
+		if (priv->mac80211_registered &&
+		    (iwl_legacy_queue_space(&txq->q) > txq->q.low_mark))
+			iwl_legacy_wake_queue(priv, txq);
+	}
+	if (qc && likely(sta_id != IWL_INVALID_STATION))
+		iwl4965_txq_check_empty(priv, sta_id, tid, txq_id);
+
+	iwl4965_check_abort_status(priv, tx_resp->frame_count, status);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
+static void iwl4965_rx_beacon_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl4965_beacon_notif *beacon = (void *)pkt->u.raw;
+	u8 rate __maybe_unused =
+		iwl4965_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+	IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
+		"tsf:0x%.8x%.8x rate:%d\n",
+		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+}
+
+/* Set up 4965-specific Rx frame reply handlers */
+static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
+{
+	/* Legacy Rx frames */
+	priv->rx_handlers[REPLY_RX] = iwl4965_rx_reply_rx;
+	/* Tx response */
+	priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
+	priv->rx_handlers[BEACON_NOTIFICATION] = iwl4965_rx_beacon_notif;
+}
+
+static struct iwl_hcmd_ops iwl4965_hcmd = {
+	.rxon_assoc = iwl4965_send_rxon_assoc,
+	.commit_rxon = iwl4965_commit_rxon,
+	.set_rxon_chain = iwl4965_set_rxon_chain,
+};
+
+static void iwl4965_post_scan(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	/*
+	 * Since setting the RXON may have been deferred while
+	 * performing the scan, fire one off if needed
+	 */
+	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
+		iwl_legacy_commit_rxon(priv, ctx);
+}
+
+static void iwl4965_post_associate(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	struct ieee80211_conf *conf = NULL;
+	int ret = 0;
+
+	if (!vif || !priv->is_open)
+		return;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+
+	conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
+
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	ret = iwl_legacy_send_rxon_timing(priv, ctx);
+	if (ret)
+		IWL_WARN(priv, "RXON timing - "
+			    "Attempting to continue.\n");
+
+	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+
+	iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
+
+	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
+			vif->bss_conf.aid, vif->bss_conf.beacon_int);
+
+	if (vif->bss_conf.use_short_preamble)
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+		if (vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+	}
+
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
+			vif->bss_conf.aid, ctx->active.bssid_addr);
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		iwl4965_send_beacon_cmd(priv);
+		break;
+	default:
+		IWL_ERR(priv, "%s Should not be called in %d mode\n",
+			  __func__, vif->type);
+		break;
+	}
+
+	/* the chain noise calibration will enabled PM upon completion
+	 * 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_legacy_power_update_mode(priv, false);
+
+	/* Enable Rx differential gain and sensitivity calibrations */
+	iwl4965_chain_noise_reset(priv);
+	priv->start_calib = 1;
+}
+
+static void iwl4965_config_ap(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct ieee80211_vif *vif = ctx->vif;
+	int ret = 0;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	/* The following should be done only at AP bring up */
+	if (!iwl_legacy_is_associated_ctx(ctx)) {
+
+		/* RXON - unassoc (to set timing command) */
+		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+		iwl_legacy_commit_rxon(priv, ctx);
+
+		/* RXON Timing */
+		ret = iwl_legacy_send_rxon_timing(priv, ctx);
+		if (ret)
+			IWL_WARN(priv, "RXON timing failed - "
+					"Attempting to continue.\n");
+
+		/* AP has all antennas */
+		priv->chain_noise_data.active_chains =
+			priv->hw_params.valid_rx_ant;
+		iwl_legacy_set_rxon_ht(priv, &priv->current_ht_config);
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+		ctx->staging.assoc_id = 0;
+
+		if (vif->bss_conf.use_short_preamble)
+			ctx->staging.flags |=
+				RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.flags &=
+				~RXON_FLG_SHORT_PREAMBLE_MSK;
+
+		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
+			if (vif->bss_conf.use_short_slot)
+				ctx->staging.flags |=
+					RXON_FLG_SHORT_SLOT_MSK;
+			else
+				ctx->staging.flags &=
+					~RXON_FLG_SHORT_SLOT_MSK;
+		}
+		/* need to send beacon cmd before committing assoc RXON! */
+		iwl4965_send_beacon_cmd(priv);
+		/* restore RXON assoc */
+		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
+		iwl_legacy_commit_rxon(priv, ctx);
+	}
+	iwl4965_send_beacon_cmd(priv);
+}
+
+static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
+	.get_hcmd_size = iwl4965_get_hcmd_size,
+	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
+	.request_scan = iwl4965_request_scan,
+	.post_scan = iwl4965_post_scan,
+};
+
+static struct iwl_lib_ops iwl4965_lib = {
+	.set_hw_params = iwl4965_hw_set_hw_params,
+	.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
+	.txq_attach_buf_to_tfd = iwl4965_hw_txq_attach_buf_to_tfd,
+	.txq_free_tfd = iwl4965_hw_txq_free_tfd,
+	.txq_init = iwl4965_hw_tx_queue_init,
+	.rx_handler_setup = iwl4965_rx_handler_setup,
+	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
+	.init_alive_start = iwl4965_init_alive_start,
+	.load_ucode = iwl4965_load_bsm,
+	.dump_nic_event_log = iwl4965_dump_nic_event_log,
+	.dump_nic_error_log = iwl4965_dump_nic_error_log,
+	.dump_fh = iwl4965_dump_fh,
+	.set_channel_switch = iwl4965_hw_channel_switch,
+	.apm_ops = {
+		.init = iwl_legacy_apm_init,
+		.config = iwl4965_nic_config,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REGULATORY_BAND_1_CHANNELS,
+			EEPROM_REGULATORY_BAND_2_CHANNELS,
+			EEPROM_REGULATORY_BAND_3_CHANNELS,
+			EEPROM_REGULATORY_BAND_4_CHANNELS,
+			EEPROM_REGULATORY_BAND_5_CHANNELS,
+			EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
+			EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
+		},
+		.acquire_semaphore = iwl4965_eeprom_acquire_semaphore,
+		.release_semaphore = iwl4965_eeprom_release_semaphore,
+	},
+	.send_tx_power	= iwl4965_send_tx_power,
+	.update_chain_flags = iwl4965_update_chain_flags,
+	.temp_ops = {
+		.temperature = iwl4965_temperature_calib,
+	},
+	.debugfs_ops = {
+		.rx_stats_read = iwl4965_ucode_rx_stats_read,
+		.tx_stats_read = iwl4965_ucode_tx_stats_read,
+		.general_stats_read = iwl4965_ucode_general_stats_read,
+	},
+	.check_plcp_health = iwl4965_good_plcp_health,
+};
+
+static const struct iwl_legacy_ops iwl4965_legacy_ops = {
+	.post_associate = iwl4965_post_associate,
+	.config_ap = iwl4965_config_ap,
+	.manage_ibss_station = iwl4965_manage_ibss_station,
+	.update_bcast_stations = iwl4965_update_bcast_stations,
+};
+
+struct ieee80211_ops iwl4965_hw_ops = {
+	.tx = iwl4965_mac_tx,
+	.start = iwl4965_mac_start,
+	.stop = iwl4965_mac_stop,
+	.add_interface = iwl_legacy_mac_add_interface,
+	.remove_interface = iwl_legacy_mac_remove_interface,
+	.change_interface = iwl_legacy_mac_change_interface,
+	.config = iwl_legacy_mac_config,
+	.configure_filter = iwl4965_configure_filter,
+	.set_key = iwl4965_mac_set_key,
+	.update_tkip_key = iwl4965_mac_update_tkip_key,
+	.conf_tx = iwl_legacy_mac_conf_tx,
+	.reset_tsf = iwl_legacy_mac_reset_tsf,
+	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
+	.ampdu_action = iwl4965_mac_ampdu_action,
+	.hw_scan = iwl_legacy_mac_hw_scan,
+	.sta_add = iwl4965_mac_sta_add,
+	.sta_remove = iwl_legacy_mac_sta_remove,
+	.channel_switch = iwl4965_mac_channel_switch,
+	.tx_last_beacon = iwl_legacy_mac_tx_last_beacon,
+};
+
+static const struct iwl_ops iwl4965_ops = {
+	.lib = &iwl4965_lib,
+	.hcmd = &iwl4965_hcmd,
+	.utils = &iwl4965_hcmd_utils,
+	.led = &iwl4965_led_ops,
+	.legacy = &iwl4965_legacy_ops,
+	.ieee80211_ops = &iwl4965_hw_ops,
+};
+
+static struct iwl_base_params iwl4965_base_params = {
+	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
+	.num_of_queues = IWL49_NUM_QUEUES,
+	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = true,
+	.led_compensation = 61,
+	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.temperature_kelvin = true,
+	.max_event_log_size = 512,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+};
+
+struct iwl_cfg iwl4965_cfg = {
+	.name = "Intel(R) Wireless WiFi Link 4965AGN",
+	.fw_name_pre = IWL4965_FW_PRE,
+	.ucode_api_max = IWL4965_UCODE_API_MAX,
+	.ucode_api_min = IWL4965_UCODE_API_MIN,
+	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
+	.valid_tx_ant = ANT_AB,
+	.valid_rx_ant = ANT_ABC,
+	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
+	.ops = &iwl4965_ops,
+	.mod_params = &iwl4965_mod_params,
+	.base_params = &iwl4965_base_params,
+	.led_mode = IWL_LED_BLINK,
+	/*
+	 * Force use of chains B and C for scan RX on 5 GHz band
+	 * because the device has off-channel reception on chain A.
+	 */
+	.scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
+};
+
+/* Module firmware */
+/*(DEBLOBBED)*/
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,967 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-4965-calib.h"
+
+/*****************************************************************************
+ * INIT calibrations framework
+ *****************************************************************************/
+
+struct statistics_general_data {
+	u32 beacon_silence_rssi_a;
+	u32 beacon_silence_rssi_b;
+	u32 beacon_silence_rssi_c;
+	u32 beacon_energy_a;
+	u32 beacon_energy_b;
+	u32 beacon_energy_c;
+};
+
+void iwl4965_calib_free_results(struct iwl_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < IWL_CALIB_MAX; i++) {
+		kfree(priv->calib_results[i].buf);
+		priv->calib_results[i].buf = NULL;
+		priv->calib_results[i].buf_len = 0;
+	}
+}
+
+/*****************************************************************************
+ * RUNTIME calibrations framework
+ *****************************************************************************/
+
+/* "false alarms" are signals that our DSP tries to lock onto,
+ *   but then determines that they are either noise, or transmissions
+ *   from a distant wireless network (also "noise", really) that get
+ *   "stepped on" by stronger transmissions within our own network.
+ * This algorithm attempts to set a sensitivity level that is high
+ *   enough to receive all of our own network traffic, but not so
+ *   high that our DSP gets too busy trying to lock onto non-network
+ *   activity/noise. */
+static int iwl4965_sens_energy_cck(struct iwl_priv *priv,
+				   u32 norm_fa,
+				   u32 rx_enable_time,
+				   struct statistics_general_data *rx_info)
+{
+	u32 max_nrg_cck = 0;
+	int i = 0;
+	u8 max_silence_rssi = 0;
+	u32 silence_ref = 0;
+	u8 silence_rssi_a = 0;
+	u8 silence_rssi_b = 0;
+	u8 silence_rssi_c = 0;
+	u32 val;
+
+	/* "false_alarms" values below are cross-multiplications to assess the
+	 *   numbers of false alarms within the measured period of actual Rx
+	 *   (Rx is off when we're txing), vs the min/max expected false alarms
+	 *   (some should be expected if rx is sensitive enough) in a
+	 *   hypothetical listening period of 200 time units (TU), 204.8 msec:
+	 *
+	 * MIN_FA/fixed-time < false_alarms/actual-rx-time < MAX_FA/beacon-time
+	 *
+	 * */
+	u32 false_alarms = norm_fa * 200 * 1024;
+	u32 max_false_alarms = MAX_FA_CCK * rx_enable_time;
+	u32 min_false_alarms = MIN_FA_CCK * rx_enable_time;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	data = &(priv->sensitivity_data);
+
+	data->nrg_auto_corr_silence_diff = 0;
+
+	/* Find max silence rssi among all 3 receivers.
+	 * This is background noise, which may include transmissions from other
+	 *    networks, measured during silence before our network's beacon */
+	silence_rssi_a = (u8)((rx_info->beacon_silence_rssi_a &
+			    ALL_BAND_FILTER) >> 8);
+	silence_rssi_b = (u8)((rx_info->beacon_silence_rssi_b &
+			    ALL_BAND_FILTER) >> 8);
+	silence_rssi_c = (u8)((rx_info->beacon_silence_rssi_c &
+			    ALL_BAND_FILTER) >> 8);
+
+	val = max(silence_rssi_b, silence_rssi_c);
+	max_silence_rssi = max(silence_rssi_a, (u8) val);
+
+	/* Store silence rssi in 20-beacon history table */
+	data->nrg_silence_rssi[data->nrg_silence_idx] = max_silence_rssi;
+	data->nrg_silence_idx++;
+	if (data->nrg_silence_idx >= NRG_NUM_PREV_STAT_L)
+		data->nrg_silence_idx = 0;
+
+	/* Find max silence rssi across 20 beacon history */
+	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++) {
+		val = data->nrg_silence_rssi[i];
+		silence_ref = max(silence_ref, val);
+	}
+	IWL_DEBUG_CALIB(priv, "silence a %u, b %u, c %u, 20-bcn max %u\n",
+			silence_rssi_a, silence_rssi_b, silence_rssi_c,
+			silence_ref);
+
+	/* Find max rx energy (min value!) among all 3 receivers,
+	 *   measured during beacon frame.
+	 * Save it in 10-beacon history table. */
+	i = data->nrg_energy_idx;
+	val = min(rx_info->beacon_energy_b, rx_info->beacon_energy_c);
+	data->nrg_value[i] = min(rx_info->beacon_energy_a, val);
+
+	data->nrg_energy_idx++;
+	if (data->nrg_energy_idx >= 10)
+		data->nrg_energy_idx = 0;
+
+	/* Find min rx energy (max value) across 10 beacon history.
+	 * This is the minimum signal level that we want to receive well.
+	 * Add backoff (margin so we don't miss slightly lower energy frames).
+	 * This establishes an upper bound (min value) for energy threshold. */
+	max_nrg_cck = data->nrg_value[0];
+	for (i = 1; i < 10; i++)
+		max_nrg_cck = (u32) max(max_nrg_cck, (data->nrg_value[i]));
+	max_nrg_cck += 6;
+
+	IWL_DEBUG_CALIB(priv, "rx energy a %u, b %u, c %u, 10-bcn max/min %u\n",
+			rx_info->beacon_energy_a, rx_info->beacon_energy_b,
+			rx_info->beacon_energy_c, max_nrg_cck - 6);
+
+	/* Count number of consecutive beacons with fewer-than-desired
+	 *   false alarms. */
+	if (false_alarms < min_false_alarms)
+		data->num_in_cck_no_fa++;
+	else
+		data->num_in_cck_no_fa = 0;
+	IWL_DEBUG_CALIB(priv, "consecutive bcns with few false alarms = %u\n",
+			data->num_in_cck_no_fa);
+
+	/* If we got too many false alarms this time, reduce sensitivity */
+	if ((false_alarms > max_false_alarms) &&
+		(data->auto_corr_cck > AUTO_CORR_MAX_TH_CCK)) {
+		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u\n",
+		     false_alarms, max_false_alarms);
+		IWL_DEBUG_CALIB(priv, "... reducing sensitivity\n");
+		data->nrg_curr_state = IWL_FA_TOO_MANY;
+		/* Store for "fewer than desired" on later beacon */
+		data->nrg_silence_ref = silence_ref;
+
+		/* increase energy threshold (reduce nrg value)
+		 *   to decrease sensitivity */
+		data->nrg_th_cck = data->nrg_th_cck - NRG_STEP_CCK;
+	/* Else if we got fewer than desired, increase sensitivity */
+	} else if (false_alarms < min_false_alarms) {
+		data->nrg_curr_state = IWL_FA_TOO_FEW;
+
+		/* Compare silence level with silence level for most recent
+		 *   healthy number or too many false alarms */
+		data->nrg_auto_corr_silence_diff = (s32)data->nrg_silence_ref -
+						   (s32)silence_ref;
+
+		IWL_DEBUG_CALIB(priv,
+			 "norm FA %u < min FA %u, silence diff %d\n",
+			 false_alarms, min_false_alarms,
+			 data->nrg_auto_corr_silence_diff);
+
+		/* Increase value to increase sensitivity, but only if:
+		 * 1a) previous beacon did *not* have *too many* false alarms
+		 * 1b) AND there's a significant difference in Rx levels
+		 *      from a previous beacon with too many, or healthy # FAs
+		 * OR 2) We've seen a lot of beacons (100) with too few
+		 *       false alarms */
+		if ((data->nrg_prev_state != IWL_FA_TOO_MANY) &&
+			((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
+			(data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+
+			IWL_DEBUG_CALIB(priv, "... increasing sensitivity\n");
+			/* Increase nrg value to increase sensitivity */
+			val = data->nrg_th_cck + NRG_STEP_CCK;
+			data->nrg_th_cck = min((u32)ranges->min_nrg_cck, val);
+		} else {
+			IWL_DEBUG_CALIB(priv,
+					 "... but not changing sensitivity\n");
+		}
+
+	/* Else we got a healthy number of false alarms, keep status quo */
+	} else {
+		IWL_DEBUG_CALIB(priv, " FA in safe zone\n");
+		data->nrg_curr_state = IWL_FA_GOOD_RANGE;
+
+		/* Store for use in "fewer than desired" with later beacon */
+		data->nrg_silence_ref = silence_ref;
+
+		/* If previous beacon had too many false alarms,
+		 *   give it some extra margin by reducing sensitivity again
+		 *   (but don't go below measured energy of desired Rx) */
+		if (IWL_FA_TOO_MANY == data->nrg_prev_state) {
+			IWL_DEBUG_CALIB(priv, "... increasing margin\n");
+			if (data->nrg_th_cck > (max_nrg_cck + NRG_MARGIN))
+				data->nrg_th_cck -= NRG_MARGIN;
+			else
+				data->nrg_th_cck = max_nrg_cck;
+		}
+	}
+
+	/* Make sure the energy threshold does not go above the measured
+	 * energy of the desired Rx signals (reduced by backoff margin),
+	 * or else we might start missing Rx frames.
+	 * Lower value is higher energy, so we use max()!
+	 */
+	data->nrg_th_cck = max(max_nrg_cck, data->nrg_th_cck);
+	IWL_DEBUG_CALIB(priv, "new nrg_th_cck %u\n", data->nrg_th_cck);
+
+	data->nrg_prev_state = data->nrg_curr_state;
+
+	/* Auto-correlation CCK algorithm */
+	if (false_alarms > min_false_alarms) {
+
+		/* increase auto_corr values to decrease sensitivity
+		 * so the DSP won't be disturbed by the noise
+		 */
+		if (data->auto_corr_cck < AUTO_CORR_MAX_TH_CCK)
+			data->auto_corr_cck = AUTO_CORR_MAX_TH_CCK + 1;
+		else {
+			val = data->auto_corr_cck + AUTO_CORR_STEP_CCK;
+			data->auto_corr_cck =
+				min((u32)ranges->auto_corr_max_cck, val);
+		}
+		val = data->auto_corr_cck_mrc + AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck_mrc =
+			min((u32)ranges->auto_corr_max_cck_mrc, val);
+	} else if ((false_alarms < min_false_alarms) &&
+	   ((data->nrg_auto_corr_silence_diff > NRG_DIFF) ||
+	   (data->num_in_cck_no_fa > MAX_NUMBER_CCK_NO_FA))) {
+
+		/* Decrease auto_corr values to increase sensitivity */
+		val = data->auto_corr_cck - AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck =
+			max((u32)ranges->auto_corr_min_cck, val);
+		val = data->auto_corr_cck_mrc - AUTO_CORR_STEP_CCK;
+		data->auto_corr_cck_mrc =
+			max((u32)ranges->auto_corr_min_cck_mrc, val);
+	}
+
+	return 0;
+}
+
+
+static int iwl4965_sens_auto_corr_ofdm(struct iwl_priv *priv,
+				       u32 norm_fa,
+				       u32 rx_enable_time)
+{
+	u32 val;
+	u32 false_alarms = norm_fa * 200 * 1024;
+	u32 max_false_alarms = MAX_FA_OFDM * rx_enable_time;
+	u32 min_false_alarms = MIN_FA_OFDM * rx_enable_time;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	data = &(priv->sensitivity_data);
+
+	/* If we got too many false alarms this time, reduce sensitivity */
+	if (false_alarms > max_false_alarms) {
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u > max FA %u)\n",
+			     false_alarms, max_false_alarms);
+
+		val = data->auto_corr_ofdm + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm =
+			min((u32)ranges->auto_corr_max_ofdm, val);
+
+		val = data->auto_corr_ofdm_mrc + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc =
+			min((u32)ranges->auto_corr_max_ofdm_mrc, val);
+
+		val = data->auto_corr_ofdm_x1 + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_x1 =
+			min((u32)ranges->auto_corr_max_ofdm_x1, val);
+
+		val = data->auto_corr_ofdm_mrc_x1 + AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc_x1 =
+			min((u32)ranges->auto_corr_max_ofdm_mrc_x1, val);
+	}
+
+	/* Else if we got fewer than desired, increase sensitivity */
+	else if (false_alarms < min_false_alarms) {
+
+		IWL_DEBUG_CALIB(priv, "norm FA %u < min FA %u\n",
+			     false_alarms, min_false_alarms);
+
+		val = data->auto_corr_ofdm - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm =
+			max((u32)ranges->auto_corr_min_ofdm, val);
+
+		val = data->auto_corr_ofdm_mrc - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc =
+			max((u32)ranges->auto_corr_min_ofdm_mrc, val);
+
+		val = data->auto_corr_ofdm_x1 - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_x1 =
+			max((u32)ranges->auto_corr_min_ofdm_x1, val);
+
+		val = data->auto_corr_ofdm_mrc_x1 - AUTO_CORR_STEP_OFDM;
+		data->auto_corr_ofdm_mrc_x1 =
+			max((u32)ranges->auto_corr_min_ofdm_mrc_x1, val);
+	} else {
+		IWL_DEBUG_CALIB(priv, "min FA %u < norm FA %u < max FA %u OK\n",
+			 min_false_alarms, false_alarms, max_false_alarms);
+	}
+	return 0;
+}
+
+static void iwl4965_prepare_legacy_sensitivity_tbl(struct iwl_priv *priv,
+				struct iwl_sensitivity_data *data,
+				__le16 *tbl)
+{
+	tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm);
+	tbl[HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_mrc);
+	tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_x1);
+	tbl[HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_ofdm_mrc_x1);
+
+	tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_cck);
+	tbl[HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16((u16)data->auto_corr_cck_mrc);
+
+	tbl[HD_MIN_ENERGY_CCK_DET_INDEX] =
+				cpu_to_le16((u16)data->nrg_th_cck);
+	tbl[HD_MIN_ENERGY_OFDM_DET_INDEX] =
+				cpu_to_le16((u16)data->nrg_th_ofdm);
+
+	tbl[HD_BARKER_CORR_TH_ADD_MIN_INDEX] =
+				cpu_to_le16(data->barker_corr_th_min);
+	tbl[HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX] =
+				cpu_to_le16(data->barker_corr_th_min_mrc);
+	tbl[HD_OFDM_ENERGY_TH_IN_INDEX] =
+				cpu_to_le16(data->nrg_th_cca);
+
+	IWL_DEBUG_CALIB(priv, "ofdm: ac %u mrc %u x1 %u mrc_x1 %u thresh %u\n",
+			data->auto_corr_ofdm, data->auto_corr_ofdm_mrc,
+			data->auto_corr_ofdm_x1, data->auto_corr_ofdm_mrc_x1,
+			data->nrg_th_ofdm);
+
+	IWL_DEBUG_CALIB(priv, "cck: ac %u mrc %u thresh %u\n",
+			data->auto_corr_cck, data->auto_corr_cck_mrc,
+			data->nrg_th_cck);
+}
+
+/* Prepare a SENSITIVITY_CMD, send to uCode if values have changed */
+static int iwl4965_sensitivity_write(struct iwl_priv *priv)
+{
+	struct iwl_sensitivity_cmd cmd;
+	struct iwl_sensitivity_data *data = NULL;
+	struct iwl_host_cmd cmd_out = {
+		.id = SENSITIVITY_CMD,
+		.len = sizeof(struct iwl_sensitivity_cmd),
+		.flags = CMD_ASYNC,
+		.data = &cmd,
+	};
+
+	data = &(priv->sensitivity_data);
+
+	memset(&cmd, 0, sizeof(cmd));
+
+	iwl4965_prepare_legacy_sensitivity_tbl(priv, data, &cmd.table[0]);
+
+	/* Update uCode's "work" table, and copy it to DSP */
+	cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
+
+	/* Don't send command to uCode if nothing has changed */
+	if (!memcmp(&cmd.table[0], &(priv->sensitivity_tbl[0]),
+		    sizeof(u16)*HD_TABLE_SIZE)) {
+		IWL_DEBUG_CALIB(priv, "No change in SENSITIVITY_CMD\n");
+		return 0;
+	}
+
+	/* Copy table for comparison next time */
+	memcpy(&(priv->sensitivity_tbl[0]), &(cmd.table[0]),
+	       sizeof(u16)*HD_TABLE_SIZE);
+
+	return iwl_legacy_send_cmd(priv, &cmd_out);
+}
+
+void iwl4965_init_sensitivity(struct iwl_priv *priv)
+{
+	int ret = 0;
+	int i;
+	struct iwl_sensitivity_data *data = NULL;
+	const struct iwl_sensitivity_ranges *ranges = priv->hw_params.sens;
+
+	if (priv->disable_sens_cal)
+		return;
+
+	IWL_DEBUG_CALIB(priv, "Start iwl4965_init_sensitivity\n");
+
+	/* Clear driver's sensitivity algo data */
+	data = &(priv->sensitivity_data);
+
+	if (ranges == NULL)
+		return;
+
+	memset(data, 0, sizeof(struct iwl_sensitivity_data));
+
+	data->num_in_cck_no_fa = 0;
+	data->nrg_curr_state = IWL_FA_TOO_MANY;
+	data->nrg_prev_state = IWL_FA_TOO_MANY;
+	data->nrg_silence_ref = 0;
+	data->nrg_silence_idx = 0;
+	data->nrg_energy_idx = 0;
+
+	for (i = 0; i < 10; i++)
+		data->nrg_value[i] = 0;
+
+	for (i = 0; i < NRG_NUM_PREV_STAT_L; i++)
+		data->nrg_silence_rssi[i] = 0;
+
+	data->auto_corr_ofdm =  ranges->auto_corr_min_ofdm;
+	data->auto_corr_ofdm_mrc = ranges->auto_corr_min_ofdm_mrc;
+	data->auto_corr_ofdm_x1  = ranges->auto_corr_min_ofdm_x1;
+	data->auto_corr_ofdm_mrc_x1 = ranges->auto_corr_min_ofdm_mrc_x1;
+	data->auto_corr_cck = AUTO_CORR_CCK_MIN_VAL_DEF;
+	data->auto_corr_cck_mrc = ranges->auto_corr_min_cck_mrc;
+	data->nrg_th_cck = ranges->nrg_th_cck;
+	data->nrg_th_ofdm = ranges->nrg_th_ofdm;
+	data->barker_corr_th_min = ranges->barker_corr_th_min;
+	data->barker_corr_th_min_mrc = ranges->barker_corr_th_min_mrc;
+	data->nrg_th_cca = ranges->nrg_th_cca;
+
+	data->last_bad_plcp_cnt_ofdm = 0;
+	data->last_fa_cnt_ofdm = 0;
+	data->last_bad_plcp_cnt_cck = 0;
+	data->last_fa_cnt_cck = 0;
+
+	ret |= iwl4965_sensitivity_write(priv);
+	IWL_DEBUG_CALIB(priv, "<<return 0x%X\n", ret);
+}
+
+void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp)
+{
+	u32 rx_enable_time;
+	u32 fa_cck;
+	u32 fa_ofdm;
+	u32 bad_plcp_cck;
+	u32 bad_plcp_ofdm;
+	u32 norm_fa_ofdm;
+	u32 norm_fa_cck;
+	struct iwl_sensitivity_data *data = NULL;
+	struct statistics_rx_non_phy *rx_info;
+	struct statistics_rx_phy *ofdm, *cck;
+	unsigned long flags;
+	struct statistics_general_data statis;
+
+	if (priv->disable_sens_cal)
+		return;
+
+	data = &(priv->sensitivity_data);
+
+	if (!iwl_legacy_is_any_associated(priv)) {
+		IWL_DEBUG_CALIB(priv, "<< - not associated\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rx_info = &(((struct iwl_notif_statistics *)resp)->rx.general);
+	ofdm = &(((struct iwl_notif_statistics *)resp)->rx.ofdm);
+	cck = &(((struct iwl_notif_statistics *)resp)->rx.cck);
+
+	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
+		IWL_DEBUG_CALIB(priv, "<< invalid data.\n");
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	/* Extract Statistics: */
+	rx_enable_time = le32_to_cpu(rx_info->channel_load);
+	fa_cck = le32_to_cpu(cck->false_alarm_cnt);
+	fa_ofdm = le32_to_cpu(ofdm->false_alarm_cnt);
+	bad_plcp_cck = le32_to_cpu(cck->plcp_err);
+	bad_plcp_ofdm = le32_to_cpu(ofdm->plcp_err);
+
+	statis.beacon_silence_rssi_a =
+			le32_to_cpu(rx_info->beacon_silence_rssi_a);
+	statis.beacon_silence_rssi_b =
+			le32_to_cpu(rx_info->beacon_silence_rssi_b);
+	statis.beacon_silence_rssi_c =
+			le32_to_cpu(rx_info->beacon_silence_rssi_c);
+	statis.beacon_energy_a =
+			le32_to_cpu(rx_info->beacon_energy_a);
+	statis.beacon_energy_b =
+			le32_to_cpu(rx_info->beacon_energy_b);
+	statis.beacon_energy_c =
+			le32_to_cpu(rx_info->beacon_energy_c);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	IWL_DEBUG_CALIB(priv, "rx_enable_time = %u usecs\n", rx_enable_time);
+
+	if (!rx_enable_time) {
+		IWL_DEBUG_CALIB(priv, "<< RX Enable Time == 0!\n");
+		return;
+	}
+
+	/* These statistics increase monotonically, and do not reset
+	 *   at each beacon.  Calculate difference from last value, or just
+	 *   use the new statistics value if it has reset or wrapped around. */
+	if (data->last_bad_plcp_cnt_cck > bad_plcp_cck)
+		data->last_bad_plcp_cnt_cck = bad_plcp_cck;
+	else {
+		bad_plcp_cck -= data->last_bad_plcp_cnt_cck;
+		data->last_bad_plcp_cnt_cck += bad_plcp_cck;
+	}
+
+	if (data->last_bad_plcp_cnt_ofdm > bad_plcp_ofdm)
+		data->last_bad_plcp_cnt_ofdm = bad_plcp_ofdm;
+	else {
+		bad_plcp_ofdm -= data->last_bad_plcp_cnt_ofdm;
+		data->last_bad_plcp_cnt_ofdm += bad_plcp_ofdm;
+	}
+
+	if (data->last_fa_cnt_ofdm > fa_ofdm)
+		data->last_fa_cnt_ofdm = fa_ofdm;
+	else {
+		fa_ofdm -= data->last_fa_cnt_ofdm;
+		data->last_fa_cnt_ofdm += fa_ofdm;
+	}
+
+	if (data->last_fa_cnt_cck > fa_cck)
+		data->last_fa_cnt_cck = fa_cck;
+	else {
+		fa_cck -= data->last_fa_cnt_cck;
+		data->last_fa_cnt_cck += fa_cck;
+	}
+
+	/* Total aborted signal locks */
+	norm_fa_ofdm = fa_ofdm + bad_plcp_ofdm;
+	norm_fa_cck = fa_cck + bad_plcp_cck;
+
+	IWL_DEBUG_CALIB(priv,
+			 "cck: fa %u badp %u  ofdm: fa %u badp %u\n", fa_cck,
+			bad_plcp_cck, fa_ofdm, bad_plcp_ofdm);
+
+	iwl4965_sens_auto_corr_ofdm(priv, norm_fa_ofdm, rx_enable_time);
+	iwl4965_sens_energy_cck(priv, norm_fa_cck, rx_enable_time, &statis);
+
+	iwl4965_sensitivity_write(priv);
+}
+
+static inline u8 iwl4965_find_first_chain(u8 mask)
+{
+	if (mask & ANT_A)
+		return CHAIN_A;
+	if (mask & ANT_B)
+		return CHAIN_B;
+	return CHAIN_C;
+}
+
+/**
+ * Run disconnected antenna algorithm to find out which antennas are
+ * disconnected.
+ */
+static void
+iwl4965_find_disconn_antenna(struct iwl_priv *priv, u32* average_sig,
+				     struct iwl_chain_noise_data *data)
+{
+	u32 active_chains = 0;
+	u32 max_average_sig;
+	u16 max_average_sig_antenna_i;
+	u8 num_tx_chains;
+	u8 first_chain;
+	u16 i = 0;
+
+	average_sig[0] = data->chain_signal_a /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[1] = data->chain_signal_b /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+	average_sig[2] = data->chain_signal_c /
+			 priv->cfg->base_params->chain_noise_num_beacons;
+
+	if (average_sig[0] >= average_sig[1]) {
+		max_average_sig = average_sig[0];
+		max_average_sig_antenna_i = 0;
+		active_chains = (1 << max_average_sig_antenna_i);
+	} else {
+		max_average_sig = average_sig[1];
+		max_average_sig_antenna_i = 1;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	if (average_sig[2] >= max_average_sig) {
+		max_average_sig = average_sig[2];
+		max_average_sig_antenna_i = 2;
+		active_chains = (1 << max_average_sig_antenna_i);
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_sig: a %d b %d c %d\n",
+		     average_sig[0], average_sig[1], average_sig[2]);
+	IWL_DEBUG_CALIB(priv, "max_average_sig = %d, antenna %d\n",
+		     max_average_sig, max_average_sig_antenna_i);
+
+	/* Compare signal strengths for all 3 receivers. */
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (i != max_average_sig_antenna_i) {
+			s32 rssi_delta = (max_average_sig - average_sig[i]);
+
+			/* If signal is very weak, compared with
+			 * strongest, mark it as disconnected. */
+			if (rssi_delta > MAXIMUM_ALLOWED_PATHLOSS)
+				data->disconn_array[i] = 1;
+			else
+				active_chains |= (1 << i);
+			IWL_DEBUG_CALIB(priv, "i = %d  rssiDelta = %d  "
+			     "disconn_array[i] = %d\n",
+			     i, rssi_delta, data->disconn_array[i]);
+		}
+	}
+
+	/*
+	 * The above algorithm sometimes fails when the ucode
+	 * reports 0 for all chains. It's not clear why that
+	 * happens to start with, but it is then causing trouble
+	 * because this can make us enable more chains than the
+	 * hardware really has.
+	 *
+	 * To be safe, simply mask out any chains that we know
+	 * are not on the device.
+	 */
+	active_chains &= priv->hw_params.valid_rx_ant;
+
+	num_tx_chains = 0;
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		/* loops on all the bits of
+		 * priv->hw_setting.valid_tx_ant */
+		u8 ant_msk = (1 << i);
+		if (!(priv->hw_params.valid_tx_ant & ant_msk))
+			continue;
+
+		num_tx_chains++;
+		if (data->disconn_array[i] == 0)
+			/* there is a Tx antenna connected */
+			break;
+		if (num_tx_chains == priv->hw_params.tx_chains_num &&
+		    data->disconn_array[i]) {
+			/*
+			 * If all chains are disconnected
+			 * connect the first valid tx chain
+			 */
+			first_chain =
+			iwl4965_find_first_chain(priv->cfg->valid_tx_ant);
+			data->disconn_array[first_chain] = 0;
+			active_chains |= BIT(first_chain);
+			IWL_DEBUG_CALIB(priv, "All Tx chains are disconnected \
+					W/A - declare %d as connected\n",
+					first_chain);
+			break;
+		}
+	}
+
+	if (active_chains != priv->hw_params.valid_rx_ant &&
+	    active_chains != priv->chain_noise_data.active_chains)
+		IWL_DEBUG_CALIB(priv,
+				"Detected that not all antennas are connected! "
+				"Connected: %#x, valid: %#x.\n",
+				active_chains, priv->hw_params.valid_rx_ant);
+
+	/* Save for use within RXON, TX, SCAN commands, etc. */
+	data->active_chains = active_chains;
+	IWL_DEBUG_CALIB(priv, "active_chains (bitwise) = 0x%x\n",
+			active_chains);
+}
+
+static void iwl4965_gain_computation(struct iwl_priv *priv,
+		u32 *average_noise,
+		u16 min_average_noise_antenna_i,
+		u32 min_average_noise,
+		u8 default_chain)
+{
+	int i, ret;
+	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
+
+	data->delta_gain_code[min_average_noise_antenna_i] = 0;
+
+	for (i = default_chain; i < NUM_RX_CHAINS; i++) {
+		s32 delta_g = 0;
+
+		if (!(data->disconn_array[i]) &&
+		    (data->delta_gain_code[i] ==
+			     CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
+			delta_g = average_noise[i] - min_average_noise;
+			data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
+			data->delta_gain_code[i] =
+				min(data->delta_gain_code[i],
+				(u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
+
+			data->delta_gain_code[i] =
+				(data->delta_gain_code[i] | (1 << 2));
+		} else {
+			data->delta_gain_code[i] = 0;
+		}
+	}
+	IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n",
+		     data->delta_gain_code[0],
+		     data->delta_gain_code[1],
+		     data->delta_gain_code[2]);
+
+	/* Differential gain gets sent to uCode only once */
+	if (!data->radio_write) {
+		struct iwl_calib_diff_gain_cmd cmd;
+		data->radio_write = 1;
+
+		memset(&cmd, 0, sizeof(cmd));
+		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
+		cmd.diff_gain_a = data->delta_gain_code[0];
+		cmd.diff_gain_b = data->delta_gain_code[1];
+		cmd.diff_gain_c = data->delta_gain_code[2];
+		ret = iwl_legacy_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
+				      sizeof(cmd), &cmd);
+		if (ret)
+			IWL_DEBUG_CALIB(priv, "fail sending cmd "
+				     "REPLY_PHY_CALIBRATION_CMD\n");
+
+		/* TODO we might want recalculate
+		 * rx_chain in rxon cmd */
+
+		/* Mark so we run this algo only once! */
+		data->state = IWL_CHAIN_NOISE_CALIBRATED;
+	}
+}
+
+
+
+/*
+ * Accumulate 16 beacons of signal and noise statistics for each of
+ *   3 receivers/antennas/rx-chains, then figure out:
+ * 1)  Which antennas are connected.
+ * 2)  Differential rx gain settings to balance the 3 receivers.
+ */
+void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp)
+{
+	struct iwl_chain_noise_data *data = NULL;
+
+	u32 chain_noise_a;
+	u32 chain_noise_b;
+	u32 chain_noise_c;
+	u32 chain_sig_a;
+	u32 chain_sig_b;
+	u32 chain_sig_c;
+	u32 average_sig[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+	u32 average_noise[NUM_RX_CHAINS] = {INITIALIZATION_VALUE};
+	u32 min_average_noise = MIN_AVERAGE_NOISE_MAX_VALUE;
+	u16 min_average_noise_antenna_i = INITIALIZATION_VALUE;
+	u16 i = 0;
+	u16 rxon_chnum = INITIALIZATION_VALUE;
+	u16 stat_chnum = INITIALIZATION_VALUE;
+	u8 rxon_band24;
+	u8 stat_band24;
+	unsigned long flags;
+	struct statistics_rx_non_phy *rx_info;
+
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (priv->disable_chain_noise_cal)
+		return;
+
+	data = &(priv->chain_noise_data);
+
+	/*
+	 * Accumulate just the first "chain_noise_num_beacons" after
+	 * the first association, then we're done forever.
+	 */
+	if (data->state != IWL_CHAIN_NOISE_ACCUMULATE) {
+		if (data->state == IWL_CHAIN_NOISE_ALIVE)
+			IWL_DEBUG_CALIB(priv, "Wait for noise calib reset\n");
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rx_info = &(((struct iwl_notif_statistics *)stat_resp)->
+		      rx.general);
+
+	if (rx_info->interference_data_flag != INTERFERENCE_DATA_AVAILABLE) {
+		IWL_DEBUG_CALIB(priv, " << Interference data unavailable\n");
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
+	rxon_chnum = le16_to_cpu(ctx->staging.channel);
+
+	stat_band24 = !!(((struct iwl_notif_statistics *)
+			 stat_resp)->flag &
+			 STATISTICS_REPLY_FLG_BAND_24G_MSK);
+	stat_chnum = le32_to_cpu(((struct iwl_notif_statistics *)
+				 stat_resp)->flag) >> 16;
+
+	/* Make sure we accumulate data for just the associated channel
+	 *   (even if scanning). */
+	if ((rxon_chnum != stat_chnum) || (rxon_band24 != stat_band24)) {
+		IWL_DEBUG_CALIB(priv, "Stats not from chan=%d, band24=%d\n",
+				rxon_chnum, rxon_band24);
+		spin_unlock_irqrestore(&priv->lock, flags);
+		return;
+	}
+
+	/*
+	 *  Accumulate beacon statistics values across
+	 * "chain_noise_num_beacons"
+	 */
+	chain_noise_a = le32_to_cpu(rx_info->beacon_silence_rssi_a) &
+				IN_BAND_FILTER;
+	chain_noise_b = le32_to_cpu(rx_info->beacon_silence_rssi_b) &
+				IN_BAND_FILTER;
+	chain_noise_c = le32_to_cpu(rx_info->beacon_silence_rssi_c) &
+				IN_BAND_FILTER;
+
+	chain_sig_a = le32_to_cpu(rx_info->beacon_rssi_a) & IN_BAND_FILTER;
+	chain_sig_b = le32_to_cpu(rx_info->beacon_rssi_b) & IN_BAND_FILTER;
+	chain_sig_c = le32_to_cpu(rx_info->beacon_rssi_c) & IN_BAND_FILTER;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	data->beacon_count++;
+
+	data->chain_noise_a = (chain_noise_a + data->chain_noise_a);
+	data->chain_noise_b = (chain_noise_b + data->chain_noise_b);
+	data->chain_noise_c = (chain_noise_c + data->chain_noise_c);
+
+	data->chain_signal_a = (chain_sig_a + data->chain_signal_a);
+	data->chain_signal_b = (chain_sig_b + data->chain_signal_b);
+	data->chain_signal_c = (chain_sig_c + data->chain_signal_c);
+
+	IWL_DEBUG_CALIB(priv, "chan=%d, band24=%d, beacon=%d\n",
+			rxon_chnum, rxon_band24, data->beacon_count);
+	IWL_DEBUG_CALIB(priv, "chain_sig: a %d b %d c %d\n",
+			chain_sig_a, chain_sig_b, chain_sig_c);
+	IWL_DEBUG_CALIB(priv, "chain_noise: a %d b %d c %d\n",
+			chain_noise_a, chain_noise_b, chain_noise_c);
+
+	/* If this is the "chain_noise_num_beacons", determine:
+	 * 1)  Disconnected antennas (using signal strengths)
+	 * 2)  Differential gain (using silence noise) to balance receivers */
+	if (data->beacon_count !=
+		priv->cfg->base_params->chain_noise_num_beacons)
+		return;
+
+	/* Analyze signal for disconnected antenna */
+	iwl4965_find_disconn_antenna(priv, average_sig, data);
+
+	/* Analyze noise for rx balance */
+	average_noise[0] = data->chain_noise_a /
+			   priv->cfg->base_params->chain_noise_num_beacons;
+	average_noise[1] = data->chain_noise_b /
+			   priv->cfg->base_params->chain_noise_num_beacons;
+	average_noise[2] = data->chain_noise_c /
+			   priv->cfg->base_params->chain_noise_num_beacons;
+
+	for (i = 0; i < NUM_RX_CHAINS; i++) {
+		if (!(data->disconn_array[i]) &&
+		   (average_noise[i] <= min_average_noise)) {
+			/* This means that chain i is active and has
+			 * lower noise values so far: */
+			min_average_noise = average_noise[i];
+			min_average_noise_antenna_i = i;
+		}
+	}
+
+	IWL_DEBUG_CALIB(priv, "average_noise: a %d b %d c %d\n",
+			average_noise[0], average_noise[1],
+			average_noise[2]);
+
+	IWL_DEBUG_CALIB(priv, "min_average_noise = %d, antenna %d\n",
+			min_average_noise, min_average_noise_antenna_i);
+
+	iwl4965_gain_computation(priv, average_noise,
+			min_average_noise_antenna_i, min_average_noise,
+			iwl4965_find_first_chain(priv->cfg->valid_rx_ant));
+
+	/* Some power changes may have been made during the calibration.
+	 * Update and commit the RXON
+	 */
+	if (priv->cfg->ops->lib->update_chain_flags)
+		priv->cfg->ops->lib->update_chain_flags(priv);
+
+	data->state = IWL_CHAIN_NOISE_DONE;
+	iwl_legacy_power_update_mode(priv, false);
+}
+
+void iwl4965_reset_run_time_calib(struct iwl_priv *priv)
+{
+	int i;
+	memset(&(priv->sensitivity_data), 0,
+	       sizeof(struct iwl_sensitivity_data));
+	memset(&(priv->chain_noise_data), 0,
+	       sizeof(struct iwl_chain_noise_data));
+	for (i = 0; i < NUM_RX_CHAINS; i++)
+		priv->chain_noise_data.delta_gain_code[i] =
+				CHAIN_NOISE_DELTA_GAIN_INIT_VAL;
+
+	/* Ask for statistics now, the uCode will send notification
+	 * periodically after association */
+	iwl_legacy_send_statistics_request(priv, CMD_ASYNC, true);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-calib.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,75 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+#ifndef __iwl_4965_calib_h__
+#define __iwl_4965_calib_h__
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-commands.h"
+
+void iwl4965_chain_noise_calibration(struct iwl_priv *priv, void *stat_resp);
+void iwl4965_sensitivity_calibration(struct iwl_priv *priv, void *resp);
+void iwl4965_init_sensitivity(struct iwl_priv *priv);
+void iwl4965_reset_run_time_calib(struct iwl_priv *priv);
+void iwl4965_calib_free_results(struct iwl_priv *priv);
+
+#endif /* __iwl_4965_calib_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,774 @@
+/******************************************************************************
+*
+* GPL LICENSE SUMMARY
+*
+* Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+*
+* 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.GPL.
+*
+* Contact Information:
+*  Intel Linux Wireless <ilw@linux.intel.com>
+* Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+*****************************************************************************/
+#include "iwl-4965.h"
+#include "iwl-4965-debugfs.h"
+
+static const char *fmt_value = "  %-30s %10u\n";
+static const char *fmt_table = "  %-30s %10u  %10u  %10u  %10u\n";
+static const char *fmt_header =
+	"%-32s    current  cumulative       delta         max\n";
+
+static int iwl4965_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
+{
+	int p = 0;
+	u32 flag;
+
+	flag = le32_to_cpu(priv->_4965.statistics.flag);
+
+	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n", flag);
+	if (flag & UCODE_STATISTICS_CLEAR_MSK)
+		p += scnprintf(buf + p, bufsz - p,
+		"\tStatistics have been cleared\n");
+	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
+		(flag & UCODE_STATISTICS_FREQUENCY_MSK)
+		? "2.4 GHz" : "5.2 GHz");
+	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
+		(flag & UCODE_STATISTICS_NARROW_BAND_MSK)
+		 ? "enabled" : "disabled");
+
+	return p;
+}
+
+ssize_t iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct statistics_rx_phy) * 40 +
+		    sizeof(struct statistics_rx_non_phy) * 40 +
+		    sizeof(struct statistics_rx_ht_phy) * 40 + 400;
+	ssize_t ret;
+	struct statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
+	struct statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
+	struct statistics_rx_non_phy *general, *accum_general;
+	struct statistics_rx_non_phy *delta_general, *max_general;
+	struct statistics_rx_ht_phy *ht, *accum_ht, *delta_ht, *max_ht;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/*
+	 * the statistic information display here is based on
+	 * the last statistics notification from uCode
+	 * might not reflect the current uCode activity
+	 */
+	ofdm = &priv->_4965.statistics.rx.ofdm;
+	cck = &priv->_4965.statistics.rx.cck;
+	general = &priv->_4965.statistics.rx.general;
+	ht = &priv->_4965.statistics.rx.ofdm_ht;
+	accum_ofdm = &priv->_4965.accum_statistics.rx.ofdm;
+	accum_cck = &priv->_4965.accum_statistics.rx.cck;
+	accum_general = &priv->_4965.accum_statistics.rx.general;
+	accum_ht = &priv->_4965.accum_statistics.rx.ofdm_ht;
+	delta_ofdm = &priv->_4965.delta_statistics.rx.ofdm;
+	delta_cck = &priv->_4965.delta_statistics.rx.cck;
+	delta_general = &priv->_4965.delta_statistics.rx.general;
+	delta_ht = &priv->_4965.delta_statistics.rx.ofdm_ht;
+	max_ofdm = &priv->_4965.max_delta.rx.ofdm;
+	max_cck = &priv->_4965.max_delta.rx.cck;
+	max_general = &priv->_4965.max_delta.rx.general;
+	max_ht = &priv->_4965.max_delta.rx.ofdm_ht;
+
+	pos += iwl4965_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - OFDM:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ina_cnt:",
+			 le32_to_cpu(ofdm->ina_cnt),
+			 accum_ofdm->ina_cnt,
+			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_cnt:",
+			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
+			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "plcp_err:",
+			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
+			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_err:",
+			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
+			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "overrun_err:",
+			 le32_to_cpu(ofdm->overrun_err),
+			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
+			 max_ofdm->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "early_overrun_err:",
+			 le32_to_cpu(ofdm->early_overrun_err),
+			 accum_ofdm->early_overrun_err,
+			 delta_ofdm->early_overrun_err,
+			 max_ofdm->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_good:",
+			 le32_to_cpu(ofdm->crc32_good),
+			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
+			 max_ofdm->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "false_alarm_cnt:",
+			 le32_to_cpu(ofdm->false_alarm_cnt),
+			 accum_ofdm->false_alarm_cnt,
+			 delta_ofdm->false_alarm_cnt,
+			 max_ofdm->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_sync_err_cnt:",
+			 le32_to_cpu(ofdm->fina_sync_err_cnt),
+			 accum_ofdm->fina_sync_err_cnt,
+			 delta_ofdm->fina_sync_err_cnt,
+			 max_ofdm->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sfd_timeout:",
+			 le32_to_cpu(ofdm->sfd_timeout),
+			 accum_ofdm->sfd_timeout, delta_ofdm->sfd_timeout,
+			 max_ofdm->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_timeout:",
+			 le32_to_cpu(ofdm->fina_timeout),
+			 accum_ofdm->fina_timeout, delta_ofdm->fina_timeout,
+			 max_ofdm->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "unresponded_rts:",
+			 le32_to_cpu(ofdm->unresponded_rts),
+			 accum_ofdm->unresponded_rts,
+			 delta_ofdm->unresponded_rts,
+			 max_ofdm->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
+			 accum_ofdm->rxe_frame_limit_overrun,
+			 delta_ofdm->rxe_frame_limit_overrun,
+			 max_ofdm->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ack_cnt:",
+			 le32_to_cpu(ofdm->sent_ack_cnt),
+			 accum_ofdm->sent_ack_cnt, delta_ofdm->sent_ack_cnt,
+			 max_ofdm->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_cts_cnt:",
+			 le32_to_cpu(ofdm->sent_cts_cnt),
+			 accum_ofdm->sent_cts_cnt, delta_ofdm->sent_cts_cnt,
+			 max_ofdm->sent_cts_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ba_rsp_cnt:",
+			 le32_to_cpu(ofdm->sent_ba_rsp_cnt),
+			 accum_ofdm->sent_ba_rsp_cnt,
+			 delta_ofdm->sent_ba_rsp_cnt,
+			 max_ofdm->sent_ba_rsp_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dsp_self_kill:",
+			 le32_to_cpu(ofdm->dsp_self_kill),
+			 accum_ofdm->dsp_self_kill,
+			 delta_ofdm->dsp_self_kill,
+			 max_ofdm->dsp_self_kill);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "mh_format_err:",
+			 le32_to_cpu(ofdm->mh_format_err),
+			 accum_ofdm->mh_format_err,
+			 delta_ofdm->mh_format_err,
+			 max_ofdm->mh_format_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "re_acq_main_rssi_sum:",
+			 le32_to_cpu(ofdm->re_acq_main_rssi_sum),
+			 accum_ofdm->re_acq_main_rssi_sum,
+			 delta_ofdm->re_acq_main_rssi_sum,
+			 max_ofdm->re_acq_main_rssi_sum);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - CCK:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ina_cnt:",
+			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
+			 delta_cck->ina_cnt, max_cck->ina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_cnt:",
+			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
+			 delta_cck->fina_cnt, max_cck->fina_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "plcp_err:",
+			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
+			 delta_cck->plcp_err, max_cck->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_err:",
+			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
+			 delta_cck->crc32_err, max_cck->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "overrun_err:",
+			 le32_to_cpu(cck->overrun_err),
+			 accum_cck->overrun_err, delta_cck->overrun_err,
+			 max_cck->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "early_overrun_err:",
+			 le32_to_cpu(cck->early_overrun_err),
+			 accum_cck->early_overrun_err,
+			 delta_cck->early_overrun_err,
+			 max_cck->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_good:",
+			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
+			 delta_cck->crc32_good, max_cck->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "false_alarm_cnt:",
+			 le32_to_cpu(cck->false_alarm_cnt),
+			 accum_cck->false_alarm_cnt,
+			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_sync_err_cnt:",
+			 le32_to_cpu(cck->fina_sync_err_cnt),
+			 accum_cck->fina_sync_err_cnt,
+			 delta_cck->fina_sync_err_cnt,
+			 max_cck->fina_sync_err_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sfd_timeout:",
+			 le32_to_cpu(cck->sfd_timeout),
+			 accum_cck->sfd_timeout, delta_cck->sfd_timeout,
+			 max_cck->sfd_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "fina_timeout:",
+			 le32_to_cpu(cck->fina_timeout),
+			 accum_cck->fina_timeout, delta_cck->fina_timeout,
+			 max_cck->fina_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "unresponded_rts:",
+			 le32_to_cpu(cck->unresponded_rts),
+			 accum_cck->unresponded_rts, delta_cck->unresponded_rts,
+			 max_cck->unresponded_rts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rxe_frame_lmt_ovrun:",
+			 le32_to_cpu(cck->rxe_frame_limit_overrun),
+			 accum_cck->rxe_frame_limit_overrun,
+			 delta_cck->rxe_frame_limit_overrun,
+			 max_cck->rxe_frame_limit_overrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ack_cnt:",
+			 le32_to_cpu(cck->sent_ack_cnt),
+			 accum_cck->sent_ack_cnt, delta_cck->sent_ack_cnt,
+			 max_cck->sent_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_cts_cnt:",
+			 le32_to_cpu(cck->sent_cts_cnt),
+			 accum_cck->sent_cts_cnt, delta_cck->sent_cts_cnt,
+			 max_cck->sent_cts_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sent_ba_rsp_cnt:",
+			 le32_to_cpu(cck->sent_ba_rsp_cnt),
+			 accum_cck->sent_ba_rsp_cnt,
+			 delta_cck->sent_ba_rsp_cnt,
+			 max_cck->sent_ba_rsp_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dsp_self_kill:",
+			 le32_to_cpu(cck->dsp_self_kill),
+			 accum_cck->dsp_self_kill, delta_cck->dsp_self_kill,
+			 max_cck->dsp_self_kill);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "mh_format_err:",
+			 le32_to_cpu(cck->mh_format_err),
+			 accum_cck->mh_format_err, delta_cck->mh_format_err,
+			 max_cck->mh_format_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "re_acq_main_rssi_sum:",
+			 le32_to_cpu(cck->re_acq_main_rssi_sum),
+			 accum_cck->re_acq_main_rssi_sum,
+			 delta_cck->re_acq_main_rssi_sum,
+			 max_cck->re_acq_main_rssi_sum);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - GENERAL:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bogus_cts:",
+			 le32_to_cpu(general->bogus_cts),
+			 accum_general->bogus_cts, delta_general->bogus_cts,
+			 max_general->bogus_cts);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bogus_ack:",
+			 le32_to_cpu(general->bogus_ack),
+			 accum_general->bogus_ack, delta_general->bogus_ack,
+			 max_general->bogus_ack);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "non_bssid_frames:",
+			 le32_to_cpu(general->non_bssid_frames),
+			 accum_general->non_bssid_frames,
+			 delta_general->non_bssid_frames,
+			 max_general->non_bssid_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "filtered_frames:",
+			 le32_to_cpu(general->filtered_frames),
+			 accum_general->filtered_frames,
+			 delta_general->filtered_frames,
+			 max_general->filtered_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "non_channel_beacons:",
+			 le32_to_cpu(general->non_channel_beacons),
+			 accum_general->non_channel_beacons,
+			 delta_general->non_channel_beacons,
+			 max_general->non_channel_beacons);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "channel_beacons:",
+			 le32_to_cpu(general->channel_beacons),
+			 accum_general->channel_beacons,
+			 delta_general->channel_beacons,
+			 max_general->channel_beacons);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "num_missed_bcon:",
+			 le32_to_cpu(general->num_missed_bcon),
+			 accum_general->num_missed_bcon,
+			 delta_general->num_missed_bcon,
+			 max_general->num_missed_bcon);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "adc_rx_saturation_time:",
+			 le32_to_cpu(general->adc_rx_saturation_time),
+			 accum_general->adc_rx_saturation_time,
+			 delta_general->adc_rx_saturation_time,
+			 max_general->adc_rx_saturation_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ina_detect_search_tm:",
+			 le32_to_cpu(general->ina_detection_search_time),
+			 accum_general->ina_detection_search_time,
+			 delta_general->ina_detection_search_time,
+			 max_general->ina_detection_search_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_silence_rssi_a:",
+			 le32_to_cpu(general->beacon_silence_rssi_a),
+			 accum_general->beacon_silence_rssi_a,
+			 delta_general->beacon_silence_rssi_a,
+			 max_general->beacon_silence_rssi_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_silence_rssi_b:",
+			 le32_to_cpu(general->beacon_silence_rssi_b),
+			 accum_general->beacon_silence_rssi_b,
+			 delta_general->beacon_silence_rssi_b,
+			 max_general->beacon_silence_rssi_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_silence_rssi_c:",
+			 le32_to_cpu(general->beacon_silence_rssi_c),
+			 accum_general->beacon_silence_rssi_c,
+			 delta_general->beacon_silence_rssi_c,
+			 max_general->beacon_silence_rssi_c);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "interference_data_flag:",
+			 le32_to_cpu(general->interference_data_flag),
+			 accum_general->interference_data_flag,
+			 delta_general->interference_data_flag,
+			 max_general->interference_data_flag);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "channel_load:",
+			 le32_to_cpu(general->channel_load),
+			 accum_general->channel_load,
+			 delta_general->channel_load,
+			 max_general->channel_load);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dsp_false_alarms:",
+			 le32_to_cpu(general->dsp_false_alarms),
+			 accum_general->dsp_false_alarms,
+			 delta_general->dsp_false_alarms,
+			 max_general->dsp_false_alarms);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_rssi_a:",
+			 le32_to_cpu(general->beacon_rssi_a),
+			 accum_general->beacon_rssi_a,
+			 delta_general->beacon_rssi_a,
+			 max_general->beacon_rssi_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_rssi_b:",
+			 le32_to_cpu(general->beacon_rssi_b),
+			 accum_general->beacon_rssi_b,
+			 delta_general->beacon_rssi_b,
+			 max_general->beacon_rssi_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_rssi_c:",
+			 le32_to_cpu(general->beacon_rssi_c),
+			 accum_general->beacon_rssi_c,
+			 delta_general->beacon_rssi_c,
+			 max_general->beacon_rssi_c);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_energy_a:",
+			 le32_to_cpu(general->beacon_energy_a),
+			 accum_general->beacon_energy_a,
+			 delta_general->beacon_energy_a,
+			 max_general->beacon_energy_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_energy_b:",
+			 le32_to_cpu(general->beacon_energy_b),
+			 accum_general->beacon_energy_b,
+			 delta_general->beacon_energy_b,
+			 max_general->beacon_energy_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "beacon_energy_c:",
+			 le32_to_cpu(general->beacon_energy_c),
+			 accum_general->beacon_energy_c,
+			 delta_general->beacon_energy_c,
+			 max_general->beacon_energy_c);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Rx - OFDM_HT:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "plcp_err:",
+			 le32_to_cpu(ht->plcp_err), accum_ht->plcp_err,
+			 delta_ht->plcp_err, max_ht->plcp_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "overrun_err:",
+			 le32_to_cpu(ht->overrun_err), accum_ht->overrun_err,
+			 delta_ht->overrun_err, max_ht->overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "early_overrun_err:",
+			 le32_to_cpu(ht->early_overrun_err),
+			 accum_ht->early_overrun_err,
+			 delta_ht->early_overrun_err,
+			 max_ht->early_overrun_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_good:",
+			 le32_to_cpu(ht->crc32_good), accum_ht->crc32_good,
+			 delta_ht->crc32_good, max_ht->crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "crc32_err:",
+			 le32_to_cpu(ht->crc32_err), accum_ht->crc32_err,
+			 delta_ht->crc32_err, max_ht->crc32_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "mh_format_err:",
+			 le32_to_cpu(ht->mh_format_err),
+			 accum_ht->mh_format_err,
+			 delta_ht->mh_format_err, max_ht->mh_format_err);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg_crc32_good:",
+			 le32_to_cpu(ht->agg_crc32_good),
+			 accum_ht->agg_crc32_good,
+			 delta_ht->agg_crc32_good, max_ht->agg_crc32_good);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg_mpdu_cnt:",
+			 le32_to_cpu(ht->agg_mpdu_cnt),
+			 accum_ht->agg_mpdu_cnt,
+			 delta_ht->agg_mpdu_cnt, max_ht->agg_mpdu_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg_cnt:",
+			 le32_to_cpu(ht->agg_cnt), accum_ht->agg_cnt,
+			 delta_ht->agg_cnt, max_ht->agg_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "unsupport_mcs:",
+			 le32_to_cpu(ht->unsupport_mcs),
+			 accum_ht->unsupport_mcs,
+			 delta_ht->unsupport_mcs, max_ht->unsupport_mcs);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t iwl4965_ucode_tx_stats_read(struct file *file,
+				char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = (sizeof(struct statistics_tx) * 48) + 250;
+	ssize_t ret;
+	struct statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	  * the last statistics notification from uCode
+	  * might not reflect the current uCode activity
+	  */
+	tx = &priv->_4965.statistics.tx;
+	accum_tx = &priv->_4965.accum_statistics.tx;
+	delta_tx = &priv->_4965.delta_statistics.tx;
+	max_tx = &priv->_4965.max_delta.tx;
+
+	pos += iwl4965_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_Tx:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "preamble:",
+			 le32_to_cpu(tx->preamble_cnt),
+			 accum_tx->preamble_cnt,
+			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rx_detected_cnt:",
+			 le32_to_cpu(tx->rx_detected_cnt),
+			 accum_tx->rx_detected_cnt,
+			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bt_prio_defer_cnt:",
+			 le32_to_cpu(tx->bt_prio_defer_cnt),
+			 accum_tx->bt_prio_defer_cnt,
+			 delta_tx->bt_prio_defer_cnt,
+			 max_tx->bt_prio_defer_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "bt_prio_kill_cnt:",
+			 le32_to_cpu(tx->bt_prio_kill_cnt),
+			 accum_tx->bt_prio_kill_cnt,
+			 delta_tx->bt_prio_kill_cnt,
+			 max_tx->bt_prio_kill_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "few_bytes_cnt:",
+			 le32_to_cpu(tx->few_bytes_cnt),
+			 accum_tx->few_bytes_cnt,
+			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "cts_timeout:",
+			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
+			 delta_tx->cts_timeout, max_tx->cts_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ack_timeout:",
+			 le32_to_cpu(tx->ack_timeout),
+			 accum_tx->ack_timeout,
+			 delta_tx->ack_timeout, max_tx->ack_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "expected_ack_cnt:",
+			 le32_to_cpu(tx->expected_ack_cnt),
+			 accum_tx->expected_ack_cnt,
+			 delta_tx->expected_ack_cnt,
+			 max_tx->expected_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "actual_ack_cnt:",
+			 le32_to_cpu(tx->actual_ack_cnt),
+			 accum_tx->actual_ack_cnt,
+			 delta_tx->actual_ack_cnt,
+			 max_tx->actual_ack_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "dump_msdu_cnt:",
+			 le32_to_cpu(tx->dump_msdu_cnt),
+			 accum_tx->dump_msdu_cnt,
+			 delta_tx->dump_msdu_cnt,
+			 max_tx->dump_msdu_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "abort_nxt_frame_mismatch:",
+			 le32_to_cpu(tx->burst_abort_next_frame_mismatch_cnt),
+			 accum_tx->burst_abort_next_frame_mismatch_cnt,
+			 delta_tx->burst_abort_next_frame_mismatch_cnt,
+			 max_tx->burst_abort_next_frame_mismatch_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "abort_missing_nxt_frame:",
+			 le32_to_cpu(tx->burst_abort_missing_next_frame_cnt),
+			 accum_tx->burst_abort_missing_next_frame_cnt,
+			 delta_tx->burst_abort_missing_next_frame_cnt,
+			 max_tx->burst_abort_missing_next_frame_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "cts_timeout_collision:",
+			 le32_to_cpu(tx->cts_timeout_collision),
+			 accum_tx->cts_timeout_collision,
+			 delta_tx->cts_timeout_collision,
+			 max_tx->cts_timeout_collision);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "ack_ba_timeout_collision:",
+			 le32_to_cpu(tx->ack_or_ba_timeout_collision),
+			 accum_tx->ack_or_ba_timeout_collision,
+			 delta_tx->ack_or_ba_timeout_collision,
+			 max_tx->ack_or_ba_timeout_collision);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg ba_timeout:",
+			 le32_to_cpu(tx->agg.ba_timeout),
+			 accum_tx->agg.ba_timeout,
+			 delta_tx->agg.ba_timeout,
+			 max_tx->agg.ba_timeout);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg ba_resched_frames:",
+			 le32_to_cpu(tx->agg.ba_reschedule_frames),
+			 accum_tx->agg.ba_reschedule_frames,
+			 delta_tx->agg.ba_reschedule_frames,
+			 max_tx->agg.ba_reschedule_frames);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_agg_frame:",
+			 le32_to_cpu(tx->agg.scd_query_agg_frame_cnt),
+			 accum_tx->agg.scd_query_agg_frame_cnt,
+			 delta_tx->agg.scd_query_agg_frame_cnt,
+			 max_tx->agg.scd_query_agg_frame_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_no_agg:",
+			 le32_to_cpu(tx->agg.scd_query_no_agg),
+			 accum_tx->agg.scd_query_no_agg,
+			 delta_tx->agg.scd_query_no_agg,
+			 max_tx->agg.scd_query_no_agg);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_agg:",
+			 le32_to_cpu(tx->agg.scd_query_agg),
+			 accum_tx->agg.scd_query_agg,
+			 delta_tx->agg.scd_query_agg,
+			 max_tx->agg.scd_query_agg);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg scd_query_mismatch:",
+			 le32_to_cpu(tx->agg.scd_query_mismatch),
+			 accum_tx->agg.scd_query_mismatch,
+			 delta_tx->agg.scd_query_mismatch,
+			 max_tx->agg.scd_query_mismatch);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg frame_not_ready:",
+			 le32_to_cpu(tx->agg.frame_not_ready),
+			 accum_tx->agg.frame_not_ready,
+			 delta_tx->agg.frame_not_ready,
+			 max_tx->agg.frame_not_ready);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg underrun:",
+			 le32_to_cpu(tx->agg.underrun),
+			 accum_tx->agg.underrun,
+			 delta_tx->agg.underrun, max_tx->agg.underrun);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg bt_prio_kill:",
+			 le32_to_cpu(tx->agg.bt_prio_kill),
+			 accum_tx->agg.bt_prio_kill,
+			 delta_tx->agg.bt_prio_kill,
+			 max_tx->agg.bt_prio_kill);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "agg rx_ba_rsp_cnt:",
+			 le32_to_cpu(tx->agg.rx_ba_rsp_cnt),
+			 accum_tx->agg.rx_ba_rsp_cnt,
+			 delta_tx->agg.rx_ba_rsp_cnt,
+			 max_tx->agg.rx_ba_rsp_cnt);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+ssize_t
+iwl4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
+				     size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char *buf;
+	int bufsz = sizeof(struct statistics_general) * 10 + 300;
+	ssize_t ret;
+	struct statistics_general_common *general, *accum_general;
+	struct statistics_general_common *delta_general, *max_general;
+	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
+	struct statistics_div *div, *accum_div, *delta_div, *max_div;
+
+	if (!iwl_legacy_is_alive(priv))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	/* the statistic information display here is based on
+	  * the last statistics notification from uCode
+	  * might not reflect the current uCode activity
+	  */
+	general = &priv->_4965.statistics.general.common;
+	dbg = &priv->_4965.statistics.general.common.dbg;
+	div = &priv->_4965.statistics.general.common.div;
+	accum_general = &priv->_4965.accum_statistics.general.common;
+	accum_dbg = &priv->_4965.accum_statistics.general.common.dbg;
+	accum_div = &priv->_4965.accum_statistics.general.common.div;
+	delta_general = &priv->_4965.delta_statistics.general.common;
+	max_general = &priv->_4965.max_delta.general.common;
+	delta_dbg = &priv->_4965.delta_statistics.general.common.dbg;
+	max_dbg = &priv->_4965.max_delta.general.common.dbg;
+	delta_div = &priv->_4965.delta_statistics.general.common.div;
+	max_div = &priv->_4965.max_delta.general.common.div;
+
+	pos += iwl4965_statistics_flag(priv, buf, bufsz);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_header, "Statistics_General:");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_value, "temperature:",
+			 le32_to_cpu(general->temperature));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_value, "ttl_timestamp:",
+			 le32_to_cpu(general->ttl_timestamp));
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "burst_check:",
+			 le32_to_cpu(dbg->burst_check),
+			 accum_dbg->burst_check,
+			 delta_dbg->burst_check, max_dbg->burst_check);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "burst_count:",
+			 le32_to_cpu(dbg->burst_count),
+			 accum_dbg->burst_count,
+			 delta_dbg->burst_count, max_dbg->burst_count);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "wait_for_silence_timeout_count:",
+			 le32_to_cpu(dbg->wait_for_silence_timeout_cnt),
+			 accum_dbg->wait_for_silence_timeout_cnt,
+			 delta_dbg->wait_for_silence_timeout_cnt,
+			 max_dbg->wait_for_silence_timeout_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "sleep_time:",
+			 le32_to_cpu(general->sleep_time),
+			 accum_general->sleep_time,
+			 delta_general->sleep_time, max_general->sleep_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "slots_out:",
+			 le32_to_cpu(general->slots_out),
+			 accum_general->slots_out,
+			 delta_general->slots_out, max_general->slots_out);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "slots_idle:",
+			 le32_to_cpu(general->slots_idle),
+			 accum_general->slots_idle,
+			 delta_general->slots_idle, max_general->slots_idle);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "tx_on_a:",
+			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
+			 delta_div->tx_on_a, max_div->tx_on_a);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "tx_on_b:",
+			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
+			 delta_div->tx_on_b, max_div->tx_on_b);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "exec_time:",
+			 le32_to_cpu(div->exec_time), accum_div->exec_time,
+			 delta_div->exec_time, max_div->exec_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "probe_time:",
+			 le32_to_cpu(div->probe_time), accum_div->probe_time,
+			 delta_div->probe_time, max_div->probe_time);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "rx_enable_counter:",
+			 le32_to_cpu(general->rx_enable_counter),
+			 accum_general->rx_enable_counter,
+			 delta_general->rx_enable_counter,
+			 max_general->rx_enable_counter);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			 fmt_table, "num_of_sos_states:",
+			 le32_to_cpu(general->num_of_sos_states),
+			 accum_general->num_of_sos_states,
+			 delta_general->num_of_sos_states,
+			 max_general->num_of_sos_states);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-debugfs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,59 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+ssize_t iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos);
+ssize_t iwl4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos);
+ssize_t iwl4965_ucode_general_stats_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos);
+#else
+static ssize_t
+iwl4965_ucode_rx_stats_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t
+iwl4965_ucode_tx_stats_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	return 0;
+}
+static ssize_t
+iwl4965_ucode_general_stats_read(struct file *file, char __user *user_buf,
+					    size_t count, loff_t *ppos)
+{
+	return 0;
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,154 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-4965.h"
+#include "iwl-io.h"
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+/*
+ * 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
+ * EEPROM chip, not a single event, so even reads could conflict if they
+ * weren't arbitrated by the semaphore.
+ */
+int iwl4965_eeprom_acquire_semaphore(struct iwl_priv *priv)
+{
+	u16 count;
+	int ret;
+
+	for (count = 0; count < EEPROM_SEM_RETRY_LIMIT; count++) {
+		/* Request semaphore */
+		iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			    CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+		/* See if we got it */
+		ret = iwl_poll_bit(priv, CSR_HW_IF_CONFIG_REG,
+				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+				CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM,
+				EEPROM_SEM_TIMEOUT);
+		if (ret >= 0) {
+			IWL_DEBUG_IO(priv,
+				"Acquired semaphore after %d tries.\n",
+				count+1);
+			return ret;
+		}
+	}
+
+	return ret;
+}
+
+void iwl4965_eeprom_release_semaphore(struct iwl_priv *priv)
+{
+	iwl_legacy_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
+		CSR_HW_IF_CONFIG_REG_BIT_EEPROM_OWN_SEM);
+
+}
+
+int iwl4965_eeprom_check_version(struct iwl_priv *priv)
+{
+	u16 eeprom_ver;
+	u16 calib_ver;
+
+	eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
+	calib_ver = iwl_legacy_eeprom_query16(priv,
+			EEPROM_4965_CALIB_VERSION_OFFSET);
+
+	if (eeprom_ver < priv->cfg->eeprom_ver ||
+	    calib_ver < priv->cfg->eeprom_calib_ver)
+		goto err;
+
+	IWL_INFO(priv, "device EEPROM VER=0x%x, CALIB=0x%x\n",
+		 eeprom_ver, calib_ver);
+
+	return 0;
+err:
+	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;
+
+}
+
+void iwl4965_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac)
+{
+	const u8 *addr = iwl_legacy_eeprom_query_addr(priv,
+					EEPROM_MAC_ADDRESS);
+	memcpy(mac, addr, ETH_ALEN);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,282 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+#ifndef __iwl_4965_h__
+#define __iwl_4965_h__
+
+#include "iwl-dev.h"
+
+/* configuration for the _4965 devices */
+extern struct iwl_cfg iwl4965_cfg;
+
+extern struct iwl_mod_params iwl4965_mod_params;
+
+extern struct ieee80211_ops iwl4965_hw_ops;
+
+/* tx queue */
+void iwl4965_free_tfds_in_queue(struct iwl_priv *priv,
+			    int sta_id, int tid, int freed);
+
+/* RXON */
+void iwl4965_set_rxon_chain(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx);
+
+/* uCode */
+int iwl4965_verify_ucode(struct iwl_priv *priv);
+
+/* lib */
+void iwl4965_check_abort_status(struct iwl_priv *priv,
+			    u8 frame_count, u32 status);
+
+void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl4965_hw_nic_init(struct iwl_priv *priv);
+int iwl4965_dump_fh(struct iwl_priv *priv, char **buf, bool display);
+
+/* rx */
+void iwl4965_rx_queue_restock(struct iwl_priv *priv);
+void iwl4965_rx_replenish(struct iwl_priv *priv);
+void iwl4965_rx_replenish_now(struct iwl_priv *priv);
+void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
+int iwl4965_rxq_stop(struct iwl_priv *priv);
+int iwl4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
+void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+		     struct iwl_rx_mem_buffer *rxb);
+void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+			 struct iwl_rx_mem_buffer *rxb);
+void iwl4965_rx_handle(struct iwl_priv *priv);
+
+/* tx */
+void iwl4965_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
+int iwl4965_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
+				 struct iwl_tx_queue *txq,
+				 dma_addr_t addr, u16 len, u8 reset, u8 pad);
+int iwl4965_hw_tx_queue_init(struct iwl_priv *priv,
+			 struct iwl_tx_queue *txq);
+void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
+			      struct ieee80211_tx_info *info);
+int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb);
+int iwl4965_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+int iwl4965_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta, u16 tid);
+int iwl4965_txq_check_empty(struct iwl_priv *priv,
+			   int sta_id, u8 tid, int txq_id);
+void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index);
+void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv);
+int iwl4965_txq_ctx_alloc(struct iwl_priv *priv);
+void iwl4965_txq_ctx_reset(struct iwl_priv *priv);
+void iwl4965_txq_ctx_stop(struct iwl_priv *priv);
+void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask);
+
+/*
+ * Acquire priv->lock before calling this function !
+ */
+void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index);
+/**
+ * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
+ * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
+ * @scd_retry: (1) Indicates queue will be used in aggregation mode
+ *
+ * NOTE:  Acquire priv->lock before calling this function !
+ */
+void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					int tx_fifo_id, int scd_retry);
+
+static inline u32 iwl4965_tx_status_to_mac80211(u32 status)
+{
+	status &= TX_STATUS_MSK;
+
+	switch (status) {
+	case TX_STATUS_SUCCESS:
+	case TX_STATUS_DIRECT_DONE:
+		return IEEE80211_TX_STAT_ACK;
+	case TX_STATUS_FAIL_DEST_PS:
+		return IEEE80211_TX_STAT_TX_FILTERED;
+	default:
+		return 0;
+	}
+}
+
+static inline bool iwl4965_is_tx_success(u32 status)
+{
+	status &= TX_STATUS_MSK;
+	return (status == TX_STATUS_SUCCESS) ||
+	       (status == TX_STATUS_DIRECT_DONE);
+}
+
+u8 iwl4965_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
+
+/* rx */
+void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+bool iwl4965_good_plcp_health(struct iwl_priv *priv,
+			  struct iwl_rx_packet *pkt);
+void iwl4965_rx_statistics(struct iwl_priv *priv,
+		       struct iwl_rx_mem_buffer *rxb);
+void iwl4965_reply_statistics(struct iwl_priv *priv,
+			  struct iwl_rx_mem_buffer *rxb);
+
+/* scan */
+int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
+
+/* station mgmt */
+int iwl4965_manage_ibss_station(struct iwl_priv *priv,
+			       struct ieee80211_vif *vif, bool add);
+
+/* hcmd */
+int iwl4965_send_beacon_cmd(struct iwl_priv *priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+const char *iwl4965_get_tx_fail_reason(u32 status);
+#else
+static inline const char *
+iwl4965_get_tx_fail_reason(u32 status) { return ""; }
+#endif
+
+/* station management */
+int iwl4965_alloc_bcast_station(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+int iwl4965_add_bssid_station(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx,
+			     const u8 *addr, u8 *sta_id_r);
+int iwl4965_remove_default_wep_key(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx,
+			       struct ieee80211_key_conf *key);
+int iwl4965_set_default_wep_key(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_key_conf *key);
+int iwl4965_restore_default_wep_keys(struct iwl_priv *priv,
+				 struct iwl_rxon_context *ctx);
+int iwl4965_set_dynamic_key(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *key, u8 sta_id);
+int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *key, u8 sta_id);
+void iwl4965_update_tkip_key(struct iwl_priv *priv,
+			 struct iwl_rxon_context *ctx,
+			 struct ieee80211_key_conf *keyconf,
+			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key);
+int iwl4965_sta_tx_modify_enable_tid(struct iwl_priv *priv,
+			int sta_id, int tid);
+int iwl4965_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			 int tid, u16 ssn);
+int iwl4965_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			int tid);
+void iwl4965_sta_modify_sleep_tx_count(struct iwl_priv *priv,
+			int sta_id, int cnt);
+int iwl4965_update_bcast_stations(struct iwl_priv *priv);
+
+/* rate */
+static inline u32 iwl4965_ant_idx_to_flags(u8 ant_idx)
+{
+	return BIT(ant_idx) << RATE_MCS_ANT_POS;
+}
+
+static inline u8 iwl4965_hw_get_rate(__le32 rate_n_flags)
+{
+	return le32_to_cpu(rate_n_flags) & 0xFF;
+}
+
+static inline __le32 iwl4965_hw_set_rate_n_flags(u8 rate, u32 flags)
+{
+	return cpu_to_le32(flags|(u32)rate);
+}
+
+/* eeprom */
+void iwl4965_eeprom_get_mac(const struct iwl_priv *priv, u8 *mac);
+int iwl4965_eeprom_acquire_semaphore(struct iwl_priv *priv);
+void iwl4965_eeprom_release_semaphore(struct iwl_priv *priv);
+int  iwl4965_eeprom_check_version(struct iwl_priv *priv);
+
+/* mac80211 handlers (for 4965) */
+void iwl4965_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+int iwl4965_mac_start(struct ieee80211_hw *hw);
+void iwl4965_mac_stop(struct ieee80211_hw *hw);
+void iwl4965_configure_filter(struct ieee80211_hw *hw,
+			     unsigned int changed_flags,
+			     unsigned int *total_flags,
+			     u64 multicast);
+int iwl4965_mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
+		       struct ieee80211_vif *vif, struct ieee80211_sta *sta,
+		       struct ieee80211_key_conf *key);
+void iwl4965_mac_update_tkip_key(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_key_conf *keyconf,
+				struct ieee80211_sta *sta,
+				u32 iv32, u16 *phase1key);
+int iwl4965_mac_ampdu_action(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    enum ieee80211_ampdu_mlme_action action,
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
+int iwl4965_mac_sta_add(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta);
+void iwl4965_mac_channel_switch(struct ieee80211_hw *hw,
+			       struct ieee80211_channel_switch *ch_switch);
+
+#endif /* __iwl_4965_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,811 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
+ * Use iwl-commands.h for uCode API definitions.
+ * Use iwl-dev.h for driver implementation definitions.
+ */
+
+#ifndef __iwl_4965_hw_h__
+#define __iwl_4965_hw_h__
+
+#include "iwl-fh.h"
+
+/* EEPROM */
+#define IWL4965_EEPROM_IMG_SIZE			1024
+
+/*
+ * uCode queue management definitions ...
+ * The first queue used for block-ack aggregation is #7 (4965 only).
+ * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
+ */
+#define IWL49_FIRST_AMPDU_QUEUE	7
+
+/* Sizes and addresses for instruction and data memory (SRAM) in
+ * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
+#define IWL49_RTC_INST_LOWER_BOUND		(0x000000)
+#define IWL49_RTC_INST_UPPER_BOUND		(0x018000)
+
+#define IWL49_RTC_DATA_LOWER_BOUND		(0x800000)
+#define IWL49_RTC_DATA_UPPER_BOUND		(0x80A000)
+
+#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - \
+				IWL49_RTC_INST_LOWER_BOUND)
+#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - \
+				IWL49_RTC_DATA_LOWER_BOUND)
+
+#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
+#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
+
+/* Size of uCode instruction memory in bootstrap state machine */
+#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
+
+static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
+{
+	return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
+	       (addr < IWL49_RTC_DATA_UPPER_BOUND);
+}
+
+/********************* START TEMPERATURE *************************************/
+
+/**
+ * 4965 temperature calculation.
+ *
+ * The driver must calculate the device temperature before calculating
+ * a txpower setting (amplifier gain is temperature dependent).  The
+ * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
+ * values used for the life of the driver, and one of which (R4) is the
+ * real-time temperature indicator.
+ *
+ * uCode provides all 4 values to the driver via the "initialize alive"
+ * notification (see struct iwl4965_init_alive_resp).  After the runtime uCode
+ * image loads, uCode updates the R4 value via statistics notifications
+ * (see STATISTICS_NOTIFICATION), which occur after each received beacon
+ * when associated, or can be requested via REPLY_STATISTICS_CMD.
+ *
+ * NOTE:  uCode provides the R4 value as a 23-bit signed value.  Driver
+ *        must sign-extend to 32 bits before applying formula below.
+ *
+ * Formula:
+ *
+ * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
+ *
+ * NOTE:  The basic formula is 259 * (R4-R2) / (R3-R1).  The 97/100 is
+ * an additional correction, which should be centered around 0 degrees
+ * Celsius (273 degrees Kelvin).  The 8 (3 percent of 273) compensates for
+ * centering the 97/100 correction around 0 degrees K.
+ *
+ * Add 273 to Kelvin value to find degrees Celsius, for comparing current
+ * temperature with factory-measured temperatures when calculating txpower
+ * settings.
+ */
+#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
+#define TEMPERATURE_CALIB_A_VAL 259
+
+/* Limit range of calculated temperature to be between these Kelvin values */
+#define IWL_TX_POWER_TEMPERATURE_MIN  (263)
+#define IWL_TX_POWER_TEMPERATURE_MAX  (410)
+
+#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
+	(((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
+	 ((t) > IWL_TX_POWER_TEMPERATURE_MAX))
+
+/********************* END TEMPERATURE ***************************************/
+
+/********************* START TXPOWER *****************************************/
+
+/**
+ * 4965 txpower calculations rely on information from three sources:
+ *
+ *     1) EEPROM
+ *     2) "initialize" alive notification
+ *     3) statistics notifications
+ *
+ * EEPROM data consists of:
+ *
+ * 1)  Regulatory information (max txpower and channel usage flags) is provided
+ *     separately for each channel that can possibly supported by 4965.
+ *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
+ *     (legacy) channels.
+ *
+ *     See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
+ *     for locations in EEPROM.
+ *
+ * 2)  Factory txpower calibration information is provided separately for
+ *     sub-bands of contiguous channels.  2.4GHz has just one sub-band,
+ *     but 5 GHz has several sub-bands.
+ *
+ *     In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
+ *
+ *     See struct iwl4965_eeprom_calib_info (and the tree of structures
+ *     contained within it) for format, and struct iwl4965_eeprom for
+ *     locations in EEPROM.
+ *
+ * "Initialization alive" notification (see struct iwl4965_init_alive_resp)
+ * consists of:
+ *
+ * 1)  Temperature calculation parameters.
+ *
+ * 2)  Power supply voltage measurement.
+ *
+ * 3)  Tx gain compensation to balance 2 transmitters for MIMO use.
+ *
+ * Statistics notifications deliver:
+ *
+ * 1)  Current values for temperature param R4.
+ */
+
+/**
+ * To calculate a txpower setting for a given desired target txpower, channel,
+ * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
+ * support MIMO and transmit diversity), driver must do the following:
+ *
+ * 1)  Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
+ *     Do not exceed regulatory limit; reduce target txpower if necessary.
+ *
+ *     If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
+ *     2 transmitters will be used simultaneously; driver must reduce the
+ *     regulatory limit by 3 dB (half-power) for each transmitter, so the
+ *     combined total output of the 2 transmitters is within regulatory limits.
+ *
+ *
+ * 2)  Compare target txpower vs. (EEPROM) saturation txpower *reduced by
+ *     backoff for this bit rate*.  Do not exceed (saturation - backoff[rate]);
+ *     reduce target txpower if necessary.
+ *
+ *     Backoff values below are in 1/2 dB units (equivalent to steps in
+ *     txpower gain tables):
+ *
+ *     OFDM 6 - 36 MBit:  10 steps (5 dB)
+ *     OFDM 48 MBit:      15 steps (7.5 dB)
+ *     OFDM 54 MBit:      17 steps (8.5 dB)
+ *     OFDM 60 MBit:      20 steps (10 dB)
+ *     CCK all rates:     10 steps (5 dB)
+ *
+ *     Backoff values apply to saturation txpower on a per-transmitter basis;
+ *     when using MIMO (2 transmitters), each transmitter uses the same
+ *     saturation level provided in EEPROM, and the same backoff values;
+ *     no reduction (such as with regulatory txpower limits) is required.
+ *
+ *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
+ *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
+ *     factory measurement for ht40 channels.
+ *
+ *     The result of this step is the final target txpower.  The rest of
+ *     the steps figure out the proper settings for the device to achieve
+ *     that target txpower.
+ *
+ *
+ * 3)  Determine (EEPROM) calibration sub band for the target channel, by
+ *     comparing against first and last channels in each sub band
+ *     (see struct iwl4965_eeprom_calib_subband_info).
+ *
+ *
+ * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
+ *     referencing the 2 factory-measured (sample) channels within the sub band.
+ *
+ *     Interpolation is based on difference between target channel's frequency
+ *     and the sample channels' frequencies.  Since channel numbers are based
+ *     on frequency (5 MHz between each channel number), this is equivalent
+ *     to interpolating based on channel number differences.
+ *
+ *     Note that the sample channels may or may not be the channels at the
+ *     edges of the sub band.  The target channel may be "outside" of the
+ *     span of the sampled channels.
+ *
+ *     Driver may choose the pair (for 2 Tx chains) of measurements (see
+ *     struct iwl4965_eeprom_calib_ch_info) for which the actual measured
+ *     txpower comes closest to the desired txpower.  Usually, though,
+ *     the middle set of measurements is closest to the regulatory limits,
+ *     and is therefore a good choice for all txpower calculations (this
+ *     assumes that high accuracy is needed for maximizing legal txpower,
+ *     while lower txpower configurations do not need as much accuracy).
+ *
+ *     Driver should interpolate both members of the chosen measurement pair,
+ *     i.e. for both Tx chains (radio transmitters), unless the driver knows
+ *     that only one of the chains will be used (e.g. only one tx antenna
+ *     connected, but this should be unusual).  The rate scaling algorithm
+ *     switches antennas to find best performance, so both Tx chains will
+ *     be used (although only one at a time) even for non-MIMO transmissions.
+ *
+ *     Driver should interpolate factory values for temperature, gain table
+ *     index, and actual power.  The power amplifier detector values are
+ *     not used by the driver.
+ *
+ *     Sanity check:  If the target channel happens to be one of the sample
+ *     channels, the results should agree with the sample channel's
+ *     measurements!
+ *
+ *
+ * 5)  Find difference between desired txpower and (interpolated)
+ *     factory-measured txpower.  Using (interpolated) factory gain table index
+ *     (shown elsewhere) as a starting point, adjust this index lower to
+ *     increase txpower, or higher to decrease txpower, until the target
+ *     txpower is reached.  Each step in the gain table is 1/2 dB.
+ *
+ *     For example, if factory measured txpower is 16 dBm, and target txpower
+ *     is 13 dBm, add 6 steps to the factory gain index to reduce txpower
+ *     by 3 dB.
+ *
+ *
+ * 6)  Find difference between current device temperature and (interpolated)
+ *     factory-measured temperature for sub-band.  Factory values are in
+ *     degrees Celsius.  To calculate current temperature, see comments for
+ *     "4965 temperature calculation".
+ *
+ *     If current temperature is higher than factory temperature, driver must
+ *     increase gain (lower gain table index), and vice verse.
+ *
+ *     Temperature affects gain differently for different channels:
+ *
+ *     2.4 GHz all channels:  3.5 degrees per half-dB step
+ *     5 GHz channels 34-43:  4.5 degrees per half-dB step
+ *     5 GHz channels >= 44:  4.0 degrees per half-dB step
+ *
+ *     NOTE:  Temperature can increase rapidly when transmitting, especially
+ *            with heavy traffic at high txpowers.  Driver should update
+ *            temperature calculations often under these conditions to
+ *            maintain strong txpower in the face of rising temperature.
+ *
+ *
+ * 7)  Find difference between current power supply voltage indicator
+ *     (from "initialize alive") and factory-measured power supply voltage
+ *     indicator (EEPROM).
+ *
+ *     If the current voltage is higher (indicator is lower) than factory
+ *     voltage, gain should be reduced (gain table index increased) by:
+ *
+ *     (eeprom - current) / 7
+ *
+ *     If the current voltage is lower (indicator is higher) than factory
+ *     voltage, gain should be increased (gain table index decreased) by:
+ *
+ *     2 * (current - eeprom) / 7
+ *
+ *     If number of index steps in either direction turns out to be > 2,
+ *     something is wrong ... just use 0.
+ *
+ *     NOTE:  Voltage compensation is independent of band/channel.
+ *
+ *     NOTE:  "Initialize" uCode measures current voltage, which is assumed
+ *            to be constant after this initial measurement.  Voltage
+ *            compensation for txpower (number of steps in gain table)
+ *            may be calculated once and used until the next uCode bootload.
+ *
+ *
+ * 8)  If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
+ *     adjust txpower for each transmitter chain, so txpower is balanced
+ *     between the two chains.  There are 5 pairs of tx_atten[group][chain]
+ *     values in "initialize alive", one pair for each of 5 channel ranges:
+ *
+ *     Group 0:  5 GHz channel 34-43
+ *     Group 1:  5 GHz channel 44-70
+ *     Group 2:  5 GHz channel 71-124
+ *     Group 3:  5 GHz channel 125-200
+ *     Group 4:  2.4 GHz all channels
+ *
+ *     Add the tx_atten[group][chain] value to the index for the target chain.
+ *     The values are signed, but are in pairs of 0 and a non-negative number,
+ *     so as to reduce gain (if necessary) of the "hotter" channel.  This
+ *     avoids any need to double-check for regulatory compliance after
+ *     this step.
+ *
+ *
+ * 9)  If setting up for a CCK rate, lower the gain by adding a CCK compensation
+ *     value to the index:
+ *
+ *     Hardware rev B:  9 steps (4.5 dB)
+ *     Hardware rev C:  5 steps (2.5 dB)
+ *
+ *     Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ *     bits [3:2], 1 = B, 2 = C.
+ *
+ *     NOTE:  This compensation is in addition to any saturation backoff that
+ *            might have been applied in an earlier step.
+ *
+ *
+ * 10) Select the gain table, based on band (2.4 vs 5 GHz).
+ *
+ *     Limit the adjusted index to stay within the table!
+ *
+ *
+ * 11) Read gain table entries for DSP and radio gain, place into appropriate
+ *     location(s) in command (struct iwl4965_txpowertable_cmd).
+ */
+
+/**
+ * When MIMO is used (2 transmitters operating simultaneously), driver should
+ * limit each transmitter to deliver a max of 3 dB below the regulatory limit
+ * for the device.  That is, use half power for each transmitter, so total
+ * txpower is within regulatory limits.
+ *
+ * The value "6" represents number of steps in gain table to reduce power 3 dB.
+ * Each step is 1/2 dB.
+ */
+#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
+
+/**
+ * CCK gain compensation.
+ *
+ * When calculating txpowers for CCK, after making sure that the target power
+ * is within regulatory and saturation limits, driver must additionally
+ * back off gain by adding these values to the gain table index.
+ *
+ * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
+ * bits [3:2], 1 = B, 2 = C.
+ */
+#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
+#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
+
+/*
+ * 4965 power supply voltage compensation for txpower
+ */
+#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V   (7)
+
+/**
+ * Gain tables.
+ *
+ * The following tables contain pair of values for setting txpower, i.e.
+ * gain settings for the output of the device's digital signal processor (DSP),
+ * and for the analog gain structure of the transmitter.
+ *
+ * Each entry in the gain tables represents a step of 1/2 dB.  Note that these
+ * are *relative* steps, not indications of absolute output power.  Output
+ * power varies with temperature, voltage, and channel frequency, and also
+ * requires consideration of average power (to satisfy regulatory constraints),
+ * and peak power (to avoid distortion of the output signal).
+ *
+ * Each entry contains two values:
+ * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
+ *     linear value that multiplies the output of the digital signal processor,
+ *     before being sent to the analog radio.
+ * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
+ *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * EEPROM contains factory calibration data for txpower.  This maps actual
+ * measured txpower levels to gain settings in the "well known" tables
+ * below ("well-known" means here that both factory calibration *and* the
+ * driver work with the same table).
+ *
+ * There are separate tables for 2.4 GHz and 5 GHz bands.  The 5 GHz table
+ * has an extension (into negative indexes), in case the driver needs to
+ * boost power setting for high device temperatures (higher than would be
+ * present during factory calibration).  A 5 Ghz EEPROM index of "40"
+ * corresponds to the 49th entry in the table used by the driver.
+ */
+#define MIN_TX_GAIN_INDEX		(0)  /* highest gain, lowest idx, 2.4 */
+#define MIN_TX_GAIN_INDEX_52GHZ_EXT	(-9) /* highest gain, lowest idx, 5 */
+
+/**
+ * 2.4 GHz gain table
+ *
+ * Index    Dsp gain   Radio gain
+ *   0        110         0x3f      (highest gain)
+ *   1        104         0x3f
+ *   2         98         0x3f
+ *   3        110         0x3e
+ *   4        104         0x3e
+ *   5         98         0x3e
+ *   6        110         0x3d
+ *   7        104         0x3d
+ *   8         98         0x3d
+ *   9        110         0x3c
+ *  10        104         0x3c
+ *  11         98         0x3c
+ *  12        110         0x3b
+ *  13        104         0x3b
+ *  14         98         0x3b
+ *  15        110         0x3a
+ *  16        104         0x3a
+ *  17         98         0x3a
+ *  18        110         0x39
+ *  19        104         0x39
+ *  20         98         0x39
+ *  21        110         0x38
+ *  22        104         0x38
+ *  23         98         0x38
+ *  24        110         0x37
+ *  25        104         0x37
+ *  26         98         0x37
+ *  27        110         0x36
+ *  28        104         0x36
+ *  29         98         0x36
+ *  30        110         0x35
+ *  31        104         0x35
+ *  32         98         0x35
+ *  33        110         0x34
+ *  34        104         0x34
+ *  35         98         0x34
+ *  36        110         0x33
+ *  37        104         0x33
+ *  38         98         0x33
+ *  39        110         0x32
+ *  40        104         0x32
+ *  41         98         0x32
+ *  42        110         0x31
+ *  43        104         0x31
+ *  44         98         0x31
+ *  45        110         0x30
+ *  46        104         0x30
+ *  47         98         0x30
+ *  48        110          0x6
+ *  49        104          0x6
+ *  50         98          0x6
+ *  51        110          0x5
+ *  52        104          0x5
+ *  53         98          0x5
+ *  54        110          0x4
+ *  55        104          0x4
+ *  56         98          0x4
+ *  57        110          0x3
+ *  58        104          0x3
+ *  59         98          0x3
+ *  60        110          0x2
+ *  61        104          0x2
+ *  62         98          0x2
+ *  63        110          0x1
+ *  64        104          0x1
+ *  65         98          0x1
+ *  66        110          0x0
+ *  67        104          0x0
+ *  68         98          0x0
+ *  69         97            0
+ *  70         96            0
+ *  71         95            0
+ *  72         94            0
+ *  73         93            0
+ *  74         92            0
+ *  75         91            0
+ *  76         90            0
+ *  77         89            0
+ *  78         88            0
+ *  79         87            0
+ *  80         86            0
+ *  81         85            0
+ *  82         84            0
+ *  83         83            0
+ *  84         82            0
+ *  85         81            0
+ *  86         80            0
+ *  87         79            0
+ *  88         78            0
+ *  89         77            0
+ *  90         76            0
+ *  91         75            0
+ *  92         74            0
+ *  93         73            0
+ *  94         72            0
+ *  95         71            0
+ *  96         70            0
+ *  97         69            0
+ *  98         68            0
+ */
+
+/**
+ * 5 GHz gain table
+ *
+ * Index    Dsp gain   Radio gain
+ *  -9 	      123         0x3F      (highest gain)
+ *  -8 	      117         0x3F
+ *  -7        110         0x3F
+ *  -6        104         0x3F
+ *  -5         98         0x3F
+ *  -4        110         0x3E
+ *  -3        104         0x3E
+ *  -2         98         0x3E
+ *  -1        110         0x3D
+ *   0        104         0x3D
+ *   1         98         0x3D
+ *   2        110         0x3C
+ *   3        104         0x3C
+ *   4         98         0x3C
+ *   5        110         0x3B
+ *   6        104         0x3B
+ *   7         98         0x3B
+ *   8        110         0x3A
+ *   9        104         0x3A
+ *  10         98         0x3A
+ *  11        110         0x39
+ *  12        104         0x39
+ *  13         98         0x39
+ *  14        110         0x38
+ *  15        104         0x38
+ *  16         98         0x38
+ *  17        110         0x37
+ *  18        104         0x37
+ *  19         98         0x37
+ *  20        110         0x36
+ *  21        104         0x36
+ *  22         98         0x36
+ *  23        110         0x35
+ *  24        104         0x35
+ *  25         98         0x35
+ *  26        110         0x34
+ *  27        104         0x34
+ *  28         98         0x34
+ *  29        110         0x33
+ *  30        104         0x33
+ *  31         98         0x33
+ *  32        110         0x32
+ *  33        104         0x32
+ *  34         98         0x32
+ *  35        110         0x31
+ *  36        104         0x31
+ *  37         98         0x31
+ *  38        110         0x30
+ *  39        104         0x30
+ *  40         98         0x30
+ *  41        110         0x25
+ *  42        104         0x25
+ *  43         98         0x25
+ *  44        110         0x24
+ *  45        104         0x24
+ *  46         98         0x24
+ *  47        110         0x23
+ *  48        104         0x23
+ *  49         98         0x23
+ *  50        110         0x22
+ *  51        104         0x18
+ *  52         98         0x18
+ *  53        110         0x17
+ *  54        104         0x17
+ *  55         98         0x17
+ *  56        110         0x16
+ *  57        104         0x16
+ *  58         98         0x16
+ *  59        110         0x15
+ *  60        104         0x15
+ *  61         98         0x15
+ *  62        110         0x14
+ *  63        104         0x14
+ *  64         98         0x14
+ *  65        110         0x13
+ *  66        104         0x13
+ *  67         98         0x13
+ *  68        110         0x12
+ *  69        104         0x08
+ *  70         98         0x08
+ *  71        110         0x07
+ *  72        104         0x07
+ *  73         98         0x07
+ *  74        110         0x06
+ *  75        104         0x06
+ *  76         98         0x06
+ *  77        110         0x05
+ *  78        104         0x05
+ *  79         98         0x05
+ *  80        110         0x04
+ *  81        104         0x04
+ *  82         98         0x04
+ *  83        110         0x03
+ *  84        104         0x03
+ *  85         98         0x03
+ *  86        110         0x02
+ *  87        104         0x02
+ *  88         98         0x02
+ *  89        110         0x01
+ *  90        104         0x01
+ *  91         98         0x01
+ *  92        110         0x00
+ *  93        104         0x00
+ *  94         98         0x00
+ *  95         93         0x00
+ *  96         88         0x00
+ *  97         83         0x00
+ *  98         78         0x00
+ */
+
+
+/**
+ * Sanity checks and default values for EEPROM regulatory levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Regulatory limits refer to the maximum average txpower allowed by
+ * regulatory agencies in the geographies in which the device is meant
+ * to be operated.  These limits are SKU-specific (i.e. geography-specific),
+ * and channel-specific; each channel has an individual regulatory limit
+ * listed in the EEPROM.
+ *
+ * Units are in half-dBm (i.e. "34" means 17 dBm).
+ */
+#define IWL_TX_POWER_DEFAULT_REGULATORY_24   (34)
+#define IWL_TX_POWER_DEFAULT_REGULATORY_52   (34)
+#define IWL_TX_POWER_REGULATORY_MIN          (0)
+#define IWL_TX_POWER_REGULATORY_MAX          (34)
+
+/**
+ * Sanity checks and default values for EEPROM saturation levels.
+ * If EEPROM values fall outside MIN/MAX range, use default values.
+ *
+ * Saturation is the highest level that the output power amplifier can produce
+ * without significant clipping distortion.  This is a "peak" power level.
+ * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
+ * require differing amounts of backoff, relative to their average power output,
+ * in order to avoid clipping distortion.
+ *
+ * Driver must make sure that it is violating neither the saturation limit,
+ * nor the regulatory limit, when calculating Tx power settings for various
+ * rates.
+ *
+ * Units are in half-dBm (i.e. "38" means 19 dBm).
+ */
+#define IWL_TX_POWER_DEFAULT_SATURATION_24   (38)
+#define IWL_TX_POWER_DEFAULT_SATURATION_52   (38)
+#define IWL_TX_POWER_SATURATION_MIN          (20)
+#define IWL_TX_POWER_SATURATION_MAX          (50)
+
+/**
+ * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
+ * and thermal Txpower calibration.
+ *
+ * When calculating txpower, driver must compensate for current device
+ * temperature; higher temperature requires higher gain.  Driver must calculate
+ * current temperature (see "4965 temperature calculation"), then compare vs.
+ * factory calibration temperature in EEPROM; if current temperature is higher
+ * than factory temperature, driver must *increase* gain by proportions shown
+ * in table below.  If current temperature is lower than factory, driver must
+ * *decrease* gain.
+ *
+ * Different frequency ranges require different compensation, as shown below.
+ */
+/* Group 0, 5.2 GHz ch 34-43:  4.5 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
+#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
+
+/* Group 1, 5.3 GHz ch 44-70:  4.0 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
+#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
+
+/* Group 2, 5.5 GHz ch 71-124:  4.0 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
+#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
+
+/* Group 3, 5.7 GHz ch 125-200:  4.0 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
+#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
+
+/* Group 4, 2.4 GHz all channels:  3.5 degrees per 1/2 dB. */
+#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
+#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
+
+enum {
+	CALIB_CH_GROUP_1 = 0,
+	CALIB_CH_GROUP_2 = 1,
+	CALIB_CH_GROUP_3 = 2,
+	CALIB_CH_GROUP_4 = 3,
+	CALIB_CH_GROUP_5 = 4,
+	CALIB_CH_GROUP_MAX
+};
+
+/********************* END TXPOWER *****************************************/
+
+
+/**
+ * Tx/Rx Queues
+ *
+ * Most communication between driver and 4965 is via queues of data buffers.
+ * For example, all commands that the driver issues to device's embedded
+ * controller (uCode) are via the command queue (one of the Tx queues).  All
+ * uCode command responses/replies/notifications, including Rx frames, are
+ * conveyed from uCode to driver via the Rx queue.
+ *
+ * Most support for these queues, including handshake support, resides in
+ * structures in host DRAM, shared between the driver and the device.  When
+ * allocating this memory, the driver must make sure that data written by
+ * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
+ * cache memory), so DRAM and cache are consistent, and the device can
+ * immediately see changes made by the driver.
+ *
+ * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
+ * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
+ * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
+ */
+#define IWL49_NUM_FIFOS 	7
+#define IWL49_CMD_FIFO_NUM	4
+#define IWL49_NUM_QUEUES	16
+#define IWL49_NUM_AMPDU_QUEUES	8
+
+
+/**
+ * struct iwl4965_schedq_bc_tbl
+ *
+ * Byte Count table
+ *
+ * Each Tx queue uses a byte-count table containing 320 entries:
+ * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
+ * duplicate the first 64 entries (to avoid wrap-around within a Tx window;
+ * max Tx window is 64 TFDs).
+ *
+ * When driver sets up a new TFD, it must also enter the total byte count
+ * of the frame to be transmitted into the corresponding entry in the byte
+ * count table for the chosen Tx queue.  If the TFD index is 0-63, the driver
+ * must duplicate the byte count entry in corresponding index 256-319.
+ *
+ * padding puts each byte count table on a 1024-byte boundary;
+ * 4965 assumes tables are separated by 1024 bytes.
+ */
+struct iwl4965_scd_bc_tbl {
+	__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
+	u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
+} __packed;
+
+
+#define IWL4965_RTC_INST_LOWER_BOUND		(0x000000)
+
+/* RSSI to dBm */
+#define IWL4965_RSSI_OFFSET	44
+
+/* PCI registers */
+#define PCI_CFG_RETRY_TIMEOUT	0x041
+
+/* PCI register values */
+#define PCI_CFG_LINK_CTRL_VAL_L0S_EN	0x01
+#define PCI_CFG_LINK_CTRL_VAL_L1_EN	0x02
+
+#define IWL4965_DEFAULT_TX_RETRY  15
+
+/* EEPROM */
+#define IWL4965_FIRST_AMPDU_QUEUE	10
+
+
+#endif /* !__iwl_4965_hw_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,74 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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 <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-4965-led.h"
+
+/* Send led command */
+static int
+iwl4965_send_led_cmd(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_LEDS_CMD,
+		.len = sizeof(struct iwl_led_cmd),
+		.data = led_cmd,
+		.flags = CMD_ASYNC,
+		.callback = NULL,
+	};
+	u32 reg;
+
+	reg = iwl_read32(priv, CSR_LED_REG);
+	if (reg != (reg & CSR_LED_BSM_CTRL_MSK))
+		iwl_write32(priv, CSR_LED_REG, reg & CSR_LED_BSM_CTRL_MSK);
+
+	return iwl_legacy_send_cmd(priv, &cmd);
+}
+
+/* Set led register off */
+void iwl4965_led_enable(struct iwl_priv *priv)
+{
+	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
+}
+
+const struct iwl_led_ops iwl4965_led_ops = {
+	.cmd = iwl4965_send_led_cmd,
+};
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-led.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,33 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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_4965_led_h__
+#define __iwl_4965_led_h__
+
+extern const struct iwl_led_ops iwl4965_led_ops;
+void iwl4965_led_enable(struct iwl_priv *priv);
+
+#endif /* __iwl_4965_led_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-lib.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-lib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-lib.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1260 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ *****************************************************************************/
+#include <linux/etherdevice.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+#include "iwl-sta.h"
+
+void iwl4965_check_abort_status(struct iwl_priv *priv,
+			    u8 frame_count, u32 status)
+{
+	if (frame_count == 1 && status == TX_STATUS_FAIL_RFKILL_FLUSH) {
+		IWL_ERR(priv, "Tx flush command to flush out all frames\n");
+		if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+			queue_work(priv->workqueue, &priv->tx_flush);
+	}
+}
+
+/*
+ * EEPROM
+ */
+struct iwl_mod_params iwl4965_mod_params = {
+	.amsdu_size_8K = 1,
+	.restart_fw = 1,
+	/* the rest are 0 by default */
+};
+
+void iwl4965_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	unsigned long flags;
+	int i;
+	spin_lock_irqsave(&rxq->lock, flags);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
+		/* In the reset function, these buffers may have been allocated
+		 * to an SKB, so we need to unmap and free potential storage */
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+	}
+
+	for (i = 0; i < RX_QUEUE_SIZE; i++)
+		rxq->queue[i] = NULL;
+
+	/* 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);
+}
+
+int iwl4965_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	u32 rb_size;
+	const u32 rfdnlog = RX_QUEUE_SIZE_LOG; /* 256 RBDs */
+	u32 rb_timeout = 0;
+
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K;
+	else
+		rb_size = FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K;
+
+	/* Stop Rx DMA */
+	iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG, 0);
+
+	/* Reset driver's Rx queue write index */
+	iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_WPTR_REG, 0);
+
+	/* Tell device where to find RBD circular buffer in DRAM */
+	iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+			   (u32)(rxq->bd_dma >> 8));
+
+	/* Tell device where in DRAM to update its Rx status */
+	iwl_legacy_write_direct32(priv, FH_RSCSR_CHNL0_STTS_WPTR_REG,
+			   rxq->rb_stts_dma >> 4);
+
+	/* Enable Rx DMA
+	 * Direct rx interrupts to hosts
+	 * Rx buffer size 4 or 8k
+	 * RB timeout 0x10
+	 * 256 RBDs
+	 */
+	iwl_legacy_write_direct32(priv, FH_MEM_RCSR_CHNL0_CONFIG_REG,
+			   FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL |
+			   FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL |
+			   FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK |
+			   rb_size|
+			   (rb_timeout << FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS)|
+			   (rfdnlog << FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS));
+
+	/* Set interrupt coalescing timer to default (2048 usecs) */
+	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_TIMEOUT_DEF);
+
+	return 0;
+}
+
+static void iwl4965_set_pwr_vmain(struct iwl_priv *priv)
+{
+/*
+ * (for documentation purposes)
+ * to set power to V_AUX, do:
+
+		if (pci_pme_capable(priv->pci_dev, PCI_D3cold))
+			iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+					       APMG_PS_CTRL_VAL_PWR_SRC_VAUX,
+					       ~APMG_PS_CTRL_MSK_PWR_SRC);
+ */
+
+	iwl_legacy_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
+			       APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
+			       ~APMG_PS_CTRL_MSK_PWR_SRC);
+}
+
+int iwl4965_hw_nic_init(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	int ret;
+
+	/* nic_init */
+	spin_lock_irqsave(&priv->lock, flags);
+	priv->cfg->ops->lib->apm_ops.init(priv);
+
+	/* Set interrupt coalescing calibration timer to default (512 usecs) */
+	iwl_write8(priv, CSR_INT_COALESCING, IWL_HOST_INT_CALIB_TIMEOUT_DEF);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl4965_set_pwr_vmain(priv);
+
+	priv->cfg->ops->lib->apm_ops.config(priv);
+
+	/* Allocate the RX queue, or reset if it is already allocated */
+	if (!rxq->bd) {
+		ret = iwl_legacy_rx_queue_alloc(priv);
+		if (ret) {
+			IWL_ERR(priv, "Unable to initialize Rx queue\n");
+			return -ENOMEM;
+		}
+	} else
+		iwl4965_rx_queue_reset(priv, rxq);
+
+	iwl4965_rx_replenish(priv);
+
+	iwl4965_rx_init(priv, rxq);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	rxq->need_update = 1;
+	iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Allocate or reset and init all Tx and Command queues */
+	if (!priv->txq) {
+		ret = iwl4965_txq_ctx_alloc(priv);
+		if (ret)
+			return ret;
+	} else
+		iwl4965_txq_ctx_reset(priv);
+
+	set_bit(STATUS_INIT, &priv->status);
+
+	return 0;
+}
+
+/**
+ * iwl4965_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
+ */
+static inline __le32 iwl4965_dma_addr2rbd_ptr(struct iwl_priv *priv,
+					  dma_addr_t dma_addr)
+{
+	return cpu_to_le32((u32)(dma_addr >> 8));
+}
+
+/**
+ * iwl4965_rx_queue_restock - refill RX queue from pre-allocated pool
+ *
+ * If there are slots in the RX queue that need to be restocked,
+ * and we have free pre-allocated buffers, fill the ranks as much
+ * as we can, pulling from rx_free.
+ *
+ * This moves the 'write' index forward to catch up with 'processed', and
+ * also updates the memory address in the firmware to reference the new
+ * target buffer.
+ */
+void iwl4965_rx_queue_restock(struct iwl_priv *priv)
+{
+	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 ((iwl_legacy_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
+		/* The overwritten rxb must be a used one */
+		rxb = rxq->queue[rxq->write];
+		BUG_ON(rxb && rxb->page);
+
+		/* Get next free Rx buffer, remove from free list */
+		element = rxq->rx_free.next;
+		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
+		list_del(element);
+
+		/* Point to Rx buffer via next RBD in circular buffer */
+		rxq->bd[rxq->write] = iwl4965_dma_addr2rbd_ptr(priv,
+							      rxb->page_dma);
+		rxq->queue[rxq->write] = rxb;
+		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
+		rxq->free_count--;
+	}
+	spin_unlock_irqrestore(&rxq->lock, flags);
+	/* If the pre-allocated buffer pool is dropping low, schedule to
+	 * refill it */
+	if (rxq->free_count <= RX_LOW_WATERMARK)
+		queue_work(priv->workqueue, &priv->rx_replenish);
+
+
+	/* If we've added more space for the firmware to place data, tell it.
+	 * Increment device's write pointer in multiples of 8. */
+	if (rxq->write_actual != (rxq->write & ~0x7)) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		rxq->need_update = 1;
+		spin_unlock_irqrestore(&rxq->lock, flags);
+		iwl_legacy_rx_queue_update_write_ptr(priv, rxq);
+	}
+}
+
+/**
+ * iwl4965_rx_replenish - Move all used packet from rx_used to rx_free
+ *
+ * When moving to rx_free an SKB is allocated for the slot.
+ *
+ * Also restock the Rx queue via iwl_rx_queue_restock.
+ * This is called as a scheduled work item (except for during initialization)
+ */
+static void iwl4965_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;
+	struct page *page;
+	unsigned long flags;
+	gfp_t gfp_mask = priority;
+
+	while (1) {
+		spin_lock_irqsave(&rxq->lock, flags);
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			return;
+		}
+		spin_unlock_irqrestore(&rxq->lock, flags);
+
+		if (rxq->free_count > RX_LOW_WATERMARK)
+			gfp_mask |= __GFP_NOWARN;
+
+		if (priv->hw_params.rx_page_order > 0)
+			gfp_mask |= __GFP_COMP;
+
+		/* Alloc a new receive buffer */
+		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
+		if (!page) {
+			if (net_ratelimit())
+				IWL_DEBUG_INFO(priv, "alloc_pages failed, "
+					       "order: %d\n",
+					       priv->hw_params.rx_page_order);
+
+			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
+			    net_ratelimit())
+				IWL_CRIT(priv,
+					"Failed to alloc_pages with %s. "
+					"Only %u free buffers remaining.\n",
+					 priority == GFP_ATOMIC ?
+						 "GFP_ATOMIC" : "GFP_KERNEL",
+					 rxq->free_count);
+			/* We don't reschedule replenish work here -- we will
+			 * call the restock method and if it still needs
+			 * more buffers it will schedule replenish */
+			return;
+		}
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		if (list_empty(&rxq->rx_used)) {
+			spin_unlock_irqrestore(&rxq->lock, flags);
+			__free_pages(page, priv->hw_params.rx_page_order);
+			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);
+
+		BUG_ON(rxb->page);
+		rxb->page = page;
+		/* Get physical address of the RB */
+		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+		/* dma address must be no more than 36 bits */
+		BUG_ON(rxb->page_dma & ~DMA_BIT_MASK(36));
+		/* and also 256 byte aligned! */
+		BUG_ON(rxb->page_dma & DMA_BIT_MASK(8));
+
+		spin_lock_irqsave(&rxq->lock, flags);
+
+		list_add_tail(&rxb->list, &rxq->rx_free);
+		rxq->free_count++;
+		priv->alloc_rxb_page++;
+
+		spin_unlock_irqrestore(&rxq->lock, flags);
+	}
+}
+
+void iwl4965_rx_replenish(struct iwl_priv *priv)
+{
+	unsigned long flags;
+
+	iwl4965_rx_allocate(priv, GFP_KERNEL);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	iwl4965_rx_queue_restock(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+}
+
+void iwl4965_rx_replenish_now(struct iwl_priv *priv)
+{
+	iwl4965_rx_allocate(priv, GFP_ATOMIC);
+
+	iwl4965_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
+ * non NULL it is unmapped and freed
+ */
+void iwl4965_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
+{
+	int i;
+	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
+		if (rxq->pool[i].page != NULL) {
+			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
+				PAGE_SIZE << priv->hw_params.rx_page_order,
+				PCI_DMA_FROMDEVICE);
+			__iwl_legacy_free_pages(priv, rxq->pool[i].page);
+			rxq->pool[i].page = NULL;
+		}
+	}
+
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->bd_dma);
+	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
+			  rxq->rb_stts, rxq->rb_stts_dma);
+	rxq->bd = NULL;
+	rxq->rb_stts  = NULL;
+}
+
+int iwl4965_rxq_stop(struct iwl_priv *priv)
+{
+
+	/* stop Rx DMA */
+	iwl_legacy_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);
+
+	return 0;
+}
+
+int iwl4965_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
+{
+	int idx = 0;
+	int band_offset = 0;
+
+	/* HT rate format: mac80211 wants an MCS number, which is just LSB */
+	if (rate_n_flags & RATE_MCS_HT_MSK) {
+		idx = (rate_n_flags & 0xff);
+		return idx;
+	/* Legacy rate format, search for match in table */
+	} else {
+		if (band == IEEE80211_BAND_5GHZ)
+			band_offset = IWL_FIRST_OFDM_RATE;
+		for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
+			if (iwlegacy_rates[idx].plcp == (rate_n_flags & 0xFF))
+				return idx - band_offset;
+	}
+
+	return -1;
+}
+
+static int iwl4965_calc_rssi(struct iwl_priv *priv,
+			     struct iwl_rx_phy_res *rx_resp)
+{
+	/* data from PHY/DSP regarding signal strength, etc.,
+	 *   contents are always there, not configurable by host.  */
+	struct iwl4965_rx_non_cfg_phy *ncphy =
+	    (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
+	u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK)
+			>> IWL49_AGC_DB_POS;
+
+	u32 valid_antennae =
+	    (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK)
+			>> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
+	u8 max_rssi = 0;
+	u32 i;
+
+	/* Find max rssi among 3 possible receivers.
+	 * These values are measured by the digital signal processor (DSP).
+	 * They should stay fairly constant even as the signal strength varies,
+	 *   if the radio's automatic gain control (AGC) is working right.
+	 * AGC value (see below) will provide the "interesting" info. */
+	for (i = 0; i < 3; i++)
+		if (valid_antennae & (1 << i))
+			max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
+
+	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
+		ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
+		max_rssi, agc);
+
+	/* dBm = max_rssi dB - agc dB - constant.
+	 * Higher AGC (higher radio gain) means lower signal. */
+	return max_rssi - agc - IWL4965_RSSI_OFFSET;
+}
+
+
+static u32 iwl4965_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
+{
+	u32 decrypt_out = 0;
+
+	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
+					RX_RES_STATUS_STATION_FOUND)
+		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
+				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
+
+	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
+
+	/* packet was not encrypted */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_NONE)
+		return decrypt_out;
+
+	/* packet was encrypted with unknown alg */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_ERR)
+		return decrypt_out;
+
+	/* decryption was not done in HW */
+	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
+					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
+		return decrypt_out;
+
+	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
+
+	case RX_RES_STATUS_SEC_TYPE_CCMP:
+		/* alg is CCM: check MIC only */
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
+			/* Bad MIC */
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+
+		break;
+
+	case RX_RES_STATUS_SEC_TYPE_TKIP:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
+			/* Bad TTAK */
+			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
+			break;
+		}
+		/* fall through if TTAK OK */
+	default:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+		break;
+	}
+
+	IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
+					decrypt_in, decrypt_out);
+
+	return decrypt_out;
+}
+
+static void iwl4965_pass_packet_to_mac80211(struct iwl_priv *priv,
+					struct ieee80211_hdr *hdr,
+					u16 len,
+					u32 ampdu_status,
+					struct iwl_rx_mem_buffer *rxb,
+					struct ieee80211_rx_status *stats)
+{
+	struct sk_buff *skb;
+	__le16 fc = hdr->frame_control;
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!priv->is_open)) {
+		IWL_DEBUG_DROP_LIMIT(priv,
+		    "Dropping packet while interface is not open.\n");
+		return;
+	}
+
+	/* In case of HW accelerated crypto and bad decryption, drop */
+	if (!priv->cfg->mod_params->sw_crypto &&
+	    iwl_legacy_set_decrypted_flag(priv, hdr, ampdu_status, stats))
+		return;
+
+	skb = dev_alloc_skb(128);
+	if (!skb) {
+		IWL_ERR(priv, "dev_alloc_skb failed\n");
+		return;
+	}
+
+	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+
+	iwl_legacy_update_stats(priv, false, fc, len);
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+	ieee80211_rx(priv->hw, skb);
+	priv->alloc_rxb_page--;
+	rxb->page = NULL;
+}
+
+/* Called for REPLY_RX (legacy ABG frames), or
+ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+void iwl4965_rx_reply_rx(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct ieee80211_hdr *header;
+	struct ieee80211_rx_status rx_status;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_rx_phy_res *phy_res;
+	__le32 rx_pkt_status;
+	struct iwl_rx_mpdu_res_start *amsdu;
+	u32 len;
+	u32 ampdu_status;
+	u32 rate_n_flags;
+
+	/**
+	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
+	 *	REPLY_RX: physical layer info is in this buffer
+	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
+	 *		command and cached in priv->last_phy_res
+	 *
+	 * Here we set up local variables depending on which command is
+	 * received.
+	 */
+	if (pkt->hdr.cmd == REPLY_RX) {
+		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+				+ phy_res->cfg_phy_cnt);
+
+		len = le16_to_cpu(phy_res->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+				phy_res->cfg_phy_cnt + len);
+		ampdu_status = le32_to_cpu(rx_pkt_status);
+	} else {
+		if (!priv->_4965.last_phy_res_valid) {
+			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
+			return;
+		}
+		phy_res = &priv->_4965.last_phy_res;
+		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+		len = le16_to_cpu(amsdu->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+		ampdu_status = iwl4965_translate_rx_status(priv,
+				le32_to_cpu(rx_pkt_status));
+	}
+
+	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				phy_res->cfg_phy_cnt);
+		return;
+	}
+
+	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
+				le32_to_cpu(rx_pkt_status));
+		return;
+	}
+
+	/* This will be used in several places later */
+	rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
+
+	/* rx_status carries information about the packet to mac80211 */
+	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
+	rx_status.freq =
+		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+							rx_status.band);
+	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	rx_status.rate_idx =
+		iwl4965_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
+	rx_status.flag = 0;
+
+	/* TSF isn't reliable. In order to allow smooth user experience,
+	 * this W/A doesn't propagate it to the mac80211 */
+	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+
+	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
+
+	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
+	rx_status.signal = iwl4965_calc_rssi(priv, phy_res);
+
+	iwl_legacy_dbg_log_rx_data_frame(priv, len, header);
+	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
+		rx_status.signal, (unsigned long long)rx_status.mactime);
+
+	/*
+	 * "antenna number"
+	 *
+	 * It seems that the antenna field in the phy flags value
+	 * is actually a bit field. This is undefined by radiotap,
+	 * it wants an actual antenna number but I always get "7"
+	 * for most legacy frames I receive indicating that the
+	 * same frame was received on all three RX chains.
+	 *
+	 * I think this field should be removed in favor of a
+	 * new 802.11n radiotap field "RX chains" that is defined
+	 * as a bitmask.
+	 */
+	rx_status.antenna =
+		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
+
+	/* set the preamble flag if appropriate */
+	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+		rx_status.flag |= RX_FLAG_SHORTPRE;
+
+	/* Set up the HT phy flags */
+	if (rate_n_flags & RATE_MCS_HT_MSK)
+		rx_status.flag |= RX_FLAG_HT;
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
+		rx_status.flag |= RX_FLAG_40MHZ;
+	if (rate_n_flags & RATE_MCS_SGI_MSK)
+		rx_status.flag |= RX_FLAG_SHORT_GI;
+
+	iwl4965_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+				    rxb, &rx_status);
+}
+
+/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+void iwl4965_rx_reply_rx_phy(struct iwl_priv *priv,
+			    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	priv->_4965.last_phy_res_valid = true;
+	memcpy(&priv->_4965.last_phy_res, pkt->u.raw,
+	       sizeof(struct iwl_rx_phy_res));
+}
+
+static int iwl4965_get_single_channel_for_scan(struct iwl_priv *priv,
+					   struct ieee80211_vif *vif,
+					   enum ieee80211_band band,
+					   struct iwl_scan_channel *scan_ch)
+{
+	const struct ieee80211_supported_band *sband;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added = 0;
+	u16 channel = 0;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband) {
+		IWL_ERR(priv, "invalid band\n");
+		return added;
+	}
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, 0);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	channel = iwl_legacy_get_single_channel_number(priv, band);
+	if (channel) {
+		scan_ch->channel = cpu_to_le16(channel);
+		scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+		added++;
+	} else
+		IWL_ERR(priv, "no valid channel found\n");
+	return added;
+}
+
+static int iwl4965_get_channels_for_scan(struct iwl_priv *priv,
+				     struct ieee80211_vif *vif,
+				     enum ieee80211_band band,
+				     u8 is_active, u8 n_probes,
+				     struct iwl_scan_channel *scan_ch)
+{
+	struct ieee80211_channel *chan;
+	const struct ieee80211_supported_band *sband;
+	const struct iwl_channel_info *ch_info;
+	u16 passive_dwell = 0;
+	u16 active_dwell = 0;
+	int added, i;
+	u16 channel;
+
+	sband = iwl_get_hw_mode(priv, band);
+	if (!sband)
+		return 0;
+
+	active_dwell = iwl_legacy_get_active_dwell_time(priv, band, n_probes);
+	passive_dwell = iwl_legacy_get_passive_dwell_time(priv, band, vif);
+
+	if (passive_dwell <= active_dwell)
+		passive_dwell = active_dwell + 1;
+
+	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
+		chan = priv->scan_request->channels[i];
+
+		if (chan->band != band)
+			continue;
+
+		channel = chan->hw_value;
+		scan_ch->channel = cpu_to_le16(channel);
+
+		ch_info = iwl_legacy_get_channel_info(priv, band, channel);
+		if (!iwl_legacy_is_channel_valid(ch_info)) {
+			IWL_DEBUG_SCAN(priv,
+				 "Channel %d is INVALID for this band.\n",
+					channel);
+			continue;
+		}
+
+		if (!is_active || iwl_legacy_is_channel_passive(ch_info) ||
+		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN))
+			scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
+		else
+			scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+
+		if (n_probes)
+			scan_ch->type |= IWL_SCAN_PROBE_MASK(n_probes);
+
+		scan_ch->active_dwell = cpu_to_le16(active_dwell);
+		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
+
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+
+		/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+		 * power level:
+		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+		 */
+		if (band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+
+		IWL_DEBUG_SCAN(priv, "Scanning ch=%d prob=0x%X [%s %d]\n",
+			       channel, le32_to_cpu(scan_ch->type),
+			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+				"ACTIVE" : "PASSIVE",
+			       (scan_ch->type & SCAN_CHANNEL_TYPE_ACTIVE) ?
+			       active_dwell : passive_dwell);
+
+		scan_ch++;
+		added++;
+	}
+
+	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
+	return added;
+}
+
+int iwl4965_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
+{
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_CMD,
+		.len = sizeof(struct iwl_scan_cmd),
+		.flags = CMD_SIZE_HUGE,
+	};
+	struct iwl_scan_cmd *scan;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	u32 rate_flags = 0;
+	u16 cmd_len;
+	u16 rx_chain = 0;
+	enum ieee80211_band band;
+	u8 n_probes = 0;
+	u8 rx_ant = priv->hw_params.valid_rx_ant;
+	u8 rate;
+	bool is_active = false;
+	int  chan_mod;
+	u8 active_chains;
+	u8 scan_tx_antennas = priv->hw_params.valid_tx_ant;
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (vif)
+		ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	if (!priv->scan_cmd) {
+		priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) +
+					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
+		if (!priv->scan_cmd) {
+			IWL_DEBUG_SCAN(priv,
+				       "fail to allocate memory for scan\n");
+			return -ENOMEM;
+		}
+	}
+	scan = priv->scan_cmd;
+	memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE);
+
+	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
+	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
+
+	if (iwl_legacy_is_any_associated(priv)) {
+		u16 interval = 0;
+		u32 extra;
+		u32 suspend_time = 100;
+		u32 scan_suspend_time = 100;
+
+		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
+		if (priv->is_internal_short_scan)
+			interval = 0;
+		else
+			interval = vif->bss_conf.beacon_int;
+
+		scan->suspend_time = 0;
+		scan->max_out_time = cpu_to_le32(200 * 1024);
+		if (!interval)
+			interval = suspend_time;
+
+		extra = (suspend_time / interval) << 22;
+		scan_suspend_time = (extra |
+		    ((suspend_time % interval) * 1024));
+		scan->suspend_time = cpu_to_le32(scan_suspend_time);
+		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
+			       scan_suspend_time, interval);
+	}
+
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
+	} else 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 = ctx->bcast_sta_id;
+	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+
+	switch (priv->scan_band) {
+	case IEEE80211_BAND_2GHZ:
+		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
+		chan_mod = le32_to_cpu(
+			priv->contexts[IWL_RXON_CTX_BSS].active.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;
+			rate_flags = RATE_MCS_CCK_MSK;
+		}
+		break;
+	case IEEE80211_BAND_5GHZ:
+		rate = IWL_RATE_6M_PLCP;
+		break;
+	default:
+		IWL_WARN(priv, "Invalid scan band\n");
+		return -EIO;
+	}
+
+	/*
+	 * If active scanning is requested but a certain channel is
+	 * marked passive, we can do active scanning if we detect
+	 * transmissions.
+	 *
+	 * There is an issue with some firmware versions that triggers
+	 * a sysassert on a "good CRC threshold" of zero (== disabled),
+	 * on a radar channel even though this means that we should NOT
+	 * send probes.
+	 *
+	 * The "good CRC threshold" is the number of frames that we
+	 * need to receive during our dwell time on a channel before
+	 * sending out probes -- setting this to a huge value will
+	 * mean we never reach it, but at the same time work around
+	 * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER
+	 * here instead of IWL_GOOD_CRC_TH_DISABLED.
+	 */
+	scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT :
+					IWL_GOOD_CRC_TH_NEVER;
+
+	band = priv->scan_band;
+
+	if (priv->cfg->scan_rx_antennas[band])
+		rx_ant = priv->cfg->scan_rx_antennas[band];
+
+	if (priv->cfg->scan_tx_antennas[band])
+		scan_tx_antennas = priv->cfg->scan_tx_antennas[band];
+
+	priv->scan_tx_ant[band] = iwl4965_toggle_tx_ant(priv,
+						priv->scan_tx_ant[band],
+						    scan_tx_antennas);
+	rate_flags |= iwl4965_ant_idx_to_flags(priv->scan_tx_ant[band]);
+	scan->tx_cmd.rate_n_flags = iwl4965_hw_set_rate_n_flags(rate, rate_flags);
+
+	/* In power save mode use one chain, otherwise use all chains */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		/* rx_ant has been set to all valid chains previously */
+		active_chains = rx_ant &
+				((u8)(priv->chain_noise_data.active_chains));
+		if (!active_chains)
+			active_chains = rx_ant;
+
+		IWL_DEBUG_SCAN(priv, "chain_noise_data.active_chains: %u\n",
+				priv->chain_noise_data.active_chains);
+
+		rx_ant = iwl4965_first_antenna(active_chains);
+	}
+
+	/* MIMO is not used here, but value is required */
+	rx_chain |= priv->hw_params.valid_rx_ant << RXON_RX_CHAIN_VALID_POS;
+	rx_chain |= rx_ant << 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);
+	if (!priv->is_internal_short_scan) {
+		cmd_len = iwl_legacy_fill_probe_req(priv,
+					(struct ieee80211_mgmt *)scan->data,
+					vif->addr,
+					priv->scan_request->ie,
+					priv->scan_request->ie_len,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+	} else {
+		/* use bcast addr, will not be transmitted but must be valid */
+		cmd_len = iwl_legacy_fill_probe_req(priv,
+					(struct ieee80211_mgmt *)scan->data,
+					iwlegacy_bcast_addr, NULL, 0,
+					IWL_MAX_SCAN_SIZE - sizeof(*scan));
+
+	}
+	scan->tx_cmd.len = cpu_to_le16(cmd_len);
+
+	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
+			       RXON_FILTER_BCON_AWARE_MSK);
+
+	if (priv->is_internal_short_scan) {
+		scan->channel_count =
+			iwl4965_get_single_channel_for_scan(priv, vif, band,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	} else {
+		scan->channel_count =
+			iwl4965_get_channels_for_scan(priv, vif, band,
+				is_active, n_probes,
+				(void *)&scan->data[le16_to_cpu(
+				scan->tx_cmd.len)]);
+	}
+	if (scan->channel_count == 0) {
+		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
+		return -EIO;
+	}
+
+	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
+	    scan->channel_count * sizeof(struct iwl_scan_channel);
+	cmd.data = scan;
+	scan->len = cpu_to_le16(cmd.len);
+
+	set_bit(STATUS_SCAN_HW, &priv->status);
+
+	ret = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (ret)
+		clear_bit(STATUS_SCAN_HW, &priv->status);
+
+	return ret;
+}
+
+int iwl4965_manage_ibss_station(struct iwl_priv *priv,
+			       struct ieee80211_vif *vif, bool add)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+	if (add)
+		return iwl4965_add_bssid_station(priv, vif_priv->ctx,
+						vif->bss_conf.bssid,
+						&vif_priv->ibss_bssid_sta_id);
+	return iwl_legacy_remove_station(priv, vif_priv->ibss_bssid_sta_id,
+				  vif->bss_conf.bssid);
+}
+
+void iwl4965_free_tfds_in_queue(struct iwl_priv *priv,
+			    int sta_id, int tid, int freed)
+{
+	lockdep_assert_held(&priv->sta_lock);
+
+	if (priv->stations[sta_id].tid[tid].tfds_in_queue >= freed)
+		priv->stations[sta_id].tid[tid].tfds_in_queue -= freed;
+	else {
+		IWL_DEBUG_TX(priv, "free more than tfds_in_queue (%u:%d)\n",
+			priv->stations[sta_id].tid[tid].tfds_in_queue,
+			freed);
+		priv->stations[sta_id].tid[tid].tfds_in_queue = 0;
+	}
+}
+
+#define IWL_TX_QUEUE_MSK	0xfffff
+
+static bool iwl4965_is_single_rx_stream(struct iwl_priv *priv)
+{
+	return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
+	       priv->current_ht_config.single_chain_sufficient;
+}
+
+#define IWL_NUM_RX_CHAINS_MULTIPLE	3
+#define IWL_NUM_RX_CHAINS_SINGLE	2
+#define IWL_NUM_IDLE_CHAINS_DUAL	2
+#define IWL_NUM_IDLE_CHAINS_SINGLE	1
+
+/*
+ * Determine how many receiver/antenna chains to use.
+ *
+ * More provides better reception via diversity.  Fewer saves power
+ * at the expense of throughput, but only when not in powersave to
+ * start with.
+ *
+ * MIMO (dual stream) requires at least 2, but works better with 3.
+ * This does not determine *which* chains to use, just how many.
+ */
+static int iwl4965_get_active_rx_chain_count(struct iwl_priv *priv)
+{
+	/* # of Rx chains to use when expecting MIMO. */
+	if (iwl4965_is_single_rx_stream(priv))
+		return IWL_NUM_RX_CHAINS_SINGLE;
+	else
+		return IWL_NUM_RX_CHAINS_MULTIPLE;
+}
+
+/*
+ * When we are in power saving mode, unless device support spatial
+ * multiplexing power save, use the active count for rx chain count.
+ */
+static int
+iwl4965_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
+{
+	/* # Rx chains when idling, depending on SMPS mode */
+	switch (priv->current_ht_config.smps) {
+	case IEEE80211_SMPS_STATIC:
+	case IEEE80211_SMPS_DYNAMIC:
+		return IWL_NUM_IDLE_CHAINS_SINGLE;
+	case IEEE80211_SMPS_OFF:
+		return active_cnt;
+	default:
+		WARN(1, "invalid SMPS mode %d",
+		     priv->current_ht_config.smps);
+		return active_cnt;
+	}
+}
+
+/* up to 4 chains */
+static u8 iwl4965_count_chain_bitmap(u32 chain_bitmap)
+{
+	u8 res;
+	res = (chain_bitmap & BIT(0)) >> 0;
+	res += (chain_bitmap & BIT(1)) >> 1;
+	res += (chain_bitmap & BIT(2)) >> 2;
+	res += (chain_bitmap & BIT(3)) >> 3;
+	return res;
+}
+
+/**
+ * iwl4965_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
+ *
+ * Selects how many and which Rx receivers/antennas/chains to use.
+ * This should not be used for scan command ... it puts data in wrong place.
+ */
+void iwl4965_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	bool is_single = iwl4965_is_single_rx_stream(priv);
+	bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->status);
+	u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
+	u32 active_chains;
+	u16 rx_chain;
+
+	/* Tell uCode which antennas are actually connected.
+	 * Before first association, we assume all antennas are connected.
+	 * Just after first association, iwl4965_chain_noise_calibration()
+	 *    checks which antennas actually *are* connected. */
+	if (priv->chain_noise_data.active_chains)
+		active_chains = priv->chain_noise_data.active_chains;
+	else
+		active_chains = priv->hw_params.valid_rx_ant;
+
+	rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
+
+	/* How many receivers should we use? */
+	active_rx_cnt = iwl4965_get_active_rx_chain_count(priv);
+	idle_rx_cnt = iwl4965_get_idle_rx_chain_count(priv, active_rx_cnt);
+
+
+	/* correct rx chain count according hw settings
+	 * and chain noise calibration
+	 */
+	valid_rx_cnt = iwl4965_count_chain_bitmap(active_chains);
+	if (valid_rx_cnt < active_rx_cnt)
+		active_rx_cnt = valid_rx_cnt;
+
+	if (valid_rx_cnt < idle_rx_cnt)
+		idle_rx_cnt = valid_rx_cnt;
+
+	rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
+	rx_chain |= idle_rx_cnt  << RXON_RX_CHAIN_CNT_POS;
+
+	ctx->staging.rx_chain = cpu_to_le16(rx_chain);
+
+	if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
+		ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
+	else
+		ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
+
+	IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
+			ctx->staging.rx_chain,
+			active_rx_cnt, idle_rx_cnt);
+
+	WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
+		active_rx_cnt < idle_rx_cnt);
+}
+
+u8 iwl4965_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
+{
+	int i;
+	u8 ind = ant;
+
+	for (i = 0; i < RATE_ANT_NUM - 1; i++) {
+		ind = (ind + 1) < RATE_ANT_NUM ?  ind + 1 : 0;
+		if (valid & BIT(ind))
+			return ind;
+	}
+	return ant;
+}
+
+static const char *iwl4965_get_fh_string(int cmd)
+{
+	switch (cmd) {
+	IWL_CMD(FH_RSCSR_CHNL0_STTS_WPTR_REG);
+	IWL_CMD(FH_RSCSR_CHNL0_RBDCB_BASE_REG);
+	IWL_CMD(FH_RSCSR_CHNL0_WPTR);
+	IWL_CMD(FH_MEM_RCSR_CHNL0_CONFIG_REG);
+	IWL_CMD(FH_MEM_RSSR_SHARED_CTRL_REG);
+	IWL_CMD(FH_MEM_RSSR_RX_STATUS_REG);
+	IWL_CMD(FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV);
+	IWL_CMD(FH_TSSR_TX_STATUS_REG);
+	IWL_CMD(FH_TSSR_TX_ERROR_REG);
+	default:
+		return "UNKNOWN";
+	}
+}
+
+int iwl4965_dump_fh(struct iwl_priv *priv, char **buf, bool display)
+{
+	int i;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	int pos = 0;
+	size_t bufsz = 0;
+#endif
+	static const u32 fh_tbl[] = {
+		FH_RSCSR_CHNL0_STTS_WPTR_REG,
+		FH_RSCSR_CHNL0_RBDCB_BASE_REG,
+		FH_RSCSR_CHNL0_WPTR,
+		FH_MEM_RCSR_CHNL0_CONFIG_REG,
+		FH_MEM_RSSR_SHARED_CTRL_REG,
+		FH_MEM_RSSR_RX_STATUS_REG,
+		FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV,
+		FH_TSSR_TX_STATUS_REG,
+		FH_TSSR_TX_ERROR_REG
+	};
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (display) {
+		bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+		*buf = kmalloc(bufsz, GFP_KERNEL);
+		if (!*buf)
+			return -ENOMEM;
+		pos += scnprintf(*buf + pos, bufsz - pos,
+				"FH register values:\n");
+		for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+			pos += scnprintf(*buf + pos, bufsz - pos,
+				"  %34s: 0X%08x\n",
+				iwl4965_get_fh_string(fh_tbl[i]),
+				iwl_legacy_read_direct32(priv, fh_tbl[i]));
+		}
+		return pos;
+	}
+#endif
+	IWL_ERR(priv, "FH register values:\n");
+	for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++) {
+		IWL_ERR(priv, "  %34s: 0X%08x\n",
+			iwl4965_get_fh_string(fh_tbl[i]),
+			iwl_legacy_read_direct32(priv, fh_tbl[i]));
+	}
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2870 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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/init.h>
+#include <linux/skbuff.h>
+#include <linux/slab.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/delay.h>
+
+#include <linux/workqueue.h>
+
+#include "iwl-dev.h"
+#include "iwl-sta.h"
+#include "iwl-core.h"
+#include "iwl-4965.h"
+
+#define IWL4965_RS_NAME "iwl-4965-rs"
+
+#define NUM_TRY_BEFORE_ANT_TOGGLE 1
+#define IWL_NUMBER_TRY      1
+#define IWL_HT_NUMBER_TRY   3
+
+#define IWL_RATE_MAX_WINDOW		62	/* # tx in history window */
+#define IWL_RATE_MIN_FAILURE_TH		6	/* min failures to calc tpt */
+#define IWL_RATE_MIN_SUCCESS_TH		8	/* min successes to calc tpt */
+
+/* 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   (3*HZ)
+
+static u8 rs_ht_to_legacy[] = {
+	IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
+	IWL_RATE_6M_INDEX, IWL_RATE_6M_INDEX,
+	IWL_RATE_6M_INDEX,
+	IWL_RATE_6M_INDEX, IWL_RATE_9M_INDEX,
+	IWL_RATE_12M_INDEX, IWL_RATE_18M_INDEX,
+	IWL_RATE_24M_INDEX, IWL_RATE_36M_INDEX,
+	IWL_RATE_48M_INDEX, IWL_RATE_54M_INDEX
+};
+
+static const u8 ant_toggle_lookup[] = {
+	/*ANT_NONE -> */ ANT_NONE,
+	/*ANT_A    -> */ ANT_B,
+	/*ANT_B    -> */ ANT_C,
+	/*ANT_AB   -> */ ANT_BC,
+	/*ANT_C    -> */ ANT_A,
+	/*ANT_AC   -> */ ANT_AB,
+	/*ANT_BC   -> */ ANT_AC,
+	/*ANT_ABC  -> */ ANT_ABC,
+};
+
+#define IWL_DECLARE_RATE_INFO(r, s, ip, in, rp, rn, pp, np)    \
+	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,      \
+				    IWL_RATE_SISO_##s##M_PLCP, \
+				    IWL_RATE_MIMO2_##s##M_PLCP,\
+				    IWL_RATE_##r##M_IEEE,      \
+				    IWL_RATE_##ip##M_INDEX,    \
+				    IWL_RATE_##in##M_INDEX,    \
+				    IWL_RATE_##rp##M_INDEX,    \
+				    IWL_RATE_##rn##M_INDEX,    \
+				    IWL_RATE_##pp##M_INDEX,    \
+				    IWL_RATE_##np##M_INDEX }
+
+/*
+ * Parameter order:
+ *   rate, ht rate, prev rate, next rate, prev tgg rate, next tgg rate
+ *
+ * If there isn't a valid next or previous rate then INV is used which
+ * maps to IWL_RATE_INVALID
+ *
+ */
+const struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT] = {
+	IWL_DECLARE_RATE_INFO(1, INV, INV, 2, INV, 2, INV, 2),    /*  1mbps */
+	IWL_DECLARE_RATE_INFO(2, INV, 1, 5, 1, 5, 1, 5),          /*  2mbps */
+	IWL_DECLARE_RATE_INFO(5, INV, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
+	IWL_DECLARE_RATE_INFO(11, INV, 9, 12, 9, 12, 5, 18),      /* 11mbps */
+	IWL_DECLARE_RATE_INFO(6, 6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
+	IWL_DECLARE_RATE_INFO(9, 6, 6, 11, 6, 11, 5, 11),       /*  9mbps */
+	IWL_DECLARE_RATE_INFO(12, 12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
+	IWL_DECLARE_RATE_INFO(18, 18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
+	IWL_DECLARE_RATE_INFO(24, 24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
+	IWL_DECLARE_RATE_INFO(36, 36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
+	IWL_DECLARE_RATE_INFO(48, 48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
+	IWL_DECLARE_RATE_INFO(54, 54, 48, INV, 48, INV, 48, INV),/* 54mbps */
+	IWL_DECLARE_RATE_INFO(60, 60, 48, INV, 48, INV, 48, INV),/* 60mbps */
+};
+
+static int iwl4965_hwrate_to_plcp_idx(u32 rate_n_flags)
+{
+	int idx = 0;
+
+	/* HT rate format */
+	if (rate_n_flags & RATE_MCS_HT_MSK) {
+		idx = (rate_n_flags & 0xff);
+
+		if (idx >= IWL_RATE_MIMO2_6M_PLCP)
+			idx = idx - IWL_RATE_MIMO2_6M_PLCP;
+
+		idx += IWL_FIRST_OFDM_RATE;
+		/* skip 9M not supported in ht*/
+		if (idx >= IWL_RATE_9M_INDEX)
+			idx += 1;
+		if ((idx >= IWL_FIRST_OFDM_RATE) && (idx <= IWL_LAST_OFDM_RATE))
+			return idx;
+
+	/* legacy rate format, search for match in table */
+	} else {
+		for (idx = 0; idx < ARRAY_SIZE(iwlegacy_rates); idx++)
+			if (iwlegacy_rates[idx].plcp == (rate_n_flags & 0xFF))
+				return idx;
+	}
+
+	return -1;
+}
+
+static void iwl4965_rs_rate_scale_perform(struct iwl_priv *priv,
+				   struct sk_buff *skb,
+				   struct ieee80211_sta *sta,
+				   struct iwl_lq_sta *lq_sta);
+static void iwl4965_rs_fill_link_cmd(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta, u32 rate_n_flags);
+static void iwl4965_rs_stay_in_table(struct iwl_lq_sta *lq_sta,
+					bool force_search);
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
+			     u32 *rate_n_flags, int index);
+#else
+static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
+			     u32 *rate_n_flags, int index)
+{}
+#endif
+
+/**
+ * The following tables contain the expected throughput metrics for all rates
+ *
+ *	1, 2, 5.5, 11, 6, 9, 12, 18, 24, 36, 48, 54, 60 MBits
+ *
+ * where invalid entries are zeros.
+ *
+ * CCK rates are only valid in legacy table and will only be used in G
+ * (2.4 GHz) band.
+ */
+
+static s32 expected_tpt_legacy[IWL_RATE_COUNT] = {
+	7, 13, 35, 58, 40, 57, 72, 98, 121, 154, 177, 186, 0
+};
+
+static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0, 42, 0,  76, 102, 124, 158, 183, 193, 202}, /* Norm */
+	{0, 0, 0, 0, 46, 0,  82, 110, 132, 167, 192, 202, 210}, /* SGI */
+	{0, 0, 0, 0, 48, 0,  93, 135, 176, 251, 319, 351, 381}, /* AGG */
+	{0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
+};
+
+static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
+	{0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
+	{0, 0, 0, 0,  96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
+	{0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
+};
+
+static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
+	{0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
+	{0, 0, 0, 0,  92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
+	{0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
+};
+
+static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
+	{0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
+	{0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
+	{0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
+	{0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
+};
+
+/* mbps, mcs */
+static const struct iwl_rate_mcs_info iwl_rate_mcs[IWL_RATE_COUNT] = {
+	{  "1", "BPSK DSSS"},
+	{  "2", "QPSK DSSS"},
+	{"5.5", "BPSK CCK"},
+	{ "11", "QPSK CCK"},
+	{  "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 iwl4965_rs_extract_rate(u32 rate_n_flags)
+{
+	return (u8)(rate_n_flags & 0xFF);
+}
+
+static void
+iwl4965_rs_rate_scale_clear_window(struct iwl_rate_scale_data *window)
+{
+	window->data = 0;
+	window->success_counter = 0;
+	window->success_ratio = IWL_INVALID_VALUE;
+	window->counter = 0;
+	window->average_tpt = IWL_INVALID_VALUE;
+	window->stamp = 0;
+}
+
+static inline u8 iwl4965_rs_is_valid_ant(u8 valid_antenna, u8 ant_type)
+{
+	return (ant_type & valid_antenna) == ant_type;
+}
+
+/*
+ *	removes the old data from the statistics. All data that is older than
+ *	TID_MAX_TIME_DIFF, will be deleted.
+ */
+static void
+iwl4965_rs_tl_rm_old_stats(struct iwl_traffic_load *tl, u32 curr_time)
+{
+	/* The oldest age we want to keep */
+	u32 oldest_time = curr_time - TID_MAX_TIME_DIFF;
+
+	while (tl->queue_count &&
+	       (tl->time_stamp < oldest_time)) {
+		tl->total -= tl->packet_count[tl->head];
+		tl->packet_count[tl->head] = 0;
+		tl->time_stamp += TID_QUEUE_CELL_SPACING;
+		tl->queue_count--;
+		tl->head++;
+		if (tl->head >= TID_QUEUE_MAX_SIZE)
+			tl->head = 0;
+	}
+}
+
+/*
+ *	increment traffic load value for tid and also remove
+ *	any old values if passed the certain time period
+ */
+static u8 iwl4965_rs_tl_add_packet(struct iwl_lq_sta *lq_data,
+			   struct ieee80211_hdr *hdr)
+{
+	u32 curr_time = jiffies_to_msecs(jiffies);
+	u32 time_diff;
+	s32 index;
+	struct iwl_traffic_load *tl = NULL;
+	u8 tid;
+
+	if (ieee80211_is_data_qos(hdr->frame_control)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & 0xf;
+	} else
+		return MAX_TID_COUNT;
+
+	if (unlikely(tid >= TID_MAX_LOAD_COUNT))
+		return MAX_TID_COUNT;
+
+	tl = &lq_data->load[tid];
+
+	curr_time -= curr_time % TID_ROUND_VALUE;
+
+	/* Happens only for the first packet. Initialize the data */
+	if (!(tl->queue_count)) {
+		tl->total = 1;
+		tl->time_stamp = curr_time;
+		tl->queue_count = 1;
+		tl->head = 0;
+		tl->packet_count[0] = 1;
+		return MAX_TID_COUNT;
+	}
+
+	time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
+	index = time_diff / TID_QUEUE_CELL_SPACING;
+
+	/* The history is too long: remove data that is older than */
+	/* TID_MAX_TIME_DIFF */
+	if (index >= TID_QUEUE_MAX_SIZE)
+		iwl4965_rs_tl_rm_old_stats(tl, curr_time);
+
+	index = (tl->head + index) % TID_QUEUE_MAX_SIZE;
+	tl->packet_count[index] = tl->packet_count[index] + 1;
+	tl->total = tl->total + 1;
+
+	if ((index + 1) > tl->queue_count)
+		tl->queue_count = index + 1;
+
+	return tid;
+}
+
+/*
+	get the traffic load value for tid
+*/
+static u32 iwl4965_rs_tl_get_load(struct iwl_lq_sta *lq_data, u8 tid)
+{
+	u32 curr_time = jiffies_to_msecs(jiffies);
+	u32 time_diff;
+	s32 index;
+	struct iwl_traffic_load *tl = NULL;
+
+	if (tid >= TID_MAX_LOAD_COUNT)
+		return 0;
+
+	tl = &(lq_data->load[tid]);
+
+	curr_time -= curr_time % TID_ROUND_VALUE;
+
+	if (!(tl->queue_count))
+		return 0;
+
+	time_diff = TIME_WRAP_AROUND(tl->time_stamp, curr_time);
+	index = time_diff / TID_QUEUE_CELL_SPACING;
+
+	/* The history is too long: remove data that is older than */
+	/* TID_MAX_TIME_DIFF */
+	if (index >= TID_QUEUE_MAX_SIZE)
+		iwl4965_rs_tl_rm_old_stats(tl, curr_time);
+
+	return tl->total;
+}
+
+static int iwl4965_rs_tl_turn_on_agg_for_tid(struct iwl_priv *priv,
+				      struct iwl_lq_sta *lq_data, u8 tid,
+				      struct ieee80211_sta *sta)
+{
+	int ret = -EAGAIN;
+	u32 load;
+
+	load = iwl4965_rs_tl_get_load(lq_data, tid);
+
+	if (load > IWL_AGG_LOAD_THRESHOLD) {
+		IWL_DEBUG_HT(priv, "Starting Tx agg: STA: %pM tid: %d\n",
+				sta->addr, tid);
+		ret = ieee80211_start_tx_ba_session(sta, tid, 5000);
+		if (ret == -EAGAIN) {
+			/*
+			 * driver and mac80211 is out of sync
+			 * this might be cause by reloading firmware
+			 * stop the tx ba session here
+			 */
+			IWL_ERR(priv, "Fail start Tx agg on tid: %d\n",
+				tid);
+			ieee80211_stop_tx_ba_session(sta, tid);
+		}
+	} else {
+		IWL_ERR(priv, "Aggregation not enabled for tid %d "
+			"because load = %u\n", tid, load);
+	}
+	return ret;
+}
+
+static void iwl4965_rs_tl_turn_on_agg(struct iwl_priv *priv, u8 tid,
+			      struct iwl_lq_sta *lq_data,
+			      struct ieee80211_sta *sta)
+{
+	if (tid < TID_MAX_LOAD_COUNT)
+		iwl4965_rs_tl_turn_on_agg_for_tid(priv, lq_data, tid, sta);
+	else
+		IWL_ERR(priv, "tid exceeds max load count: %d/%d\n",
+			tid, TID_MAX_LOAD_COUNT);
+}
+
+static inline int iwl4965_get_iwl4965_num_of_ant_from_rate(u32 rate_n_flags)
+{
+	return !!(rate_n_flags & RATE_MCS_ANT_A_MSK) +
+	       !!(rate_n_flags & RATE_MCS_ANT_B_MSK) +
+	       !!(rate_n_flags & RATE_MCS_ANT_C_MSK);
+}
+
+/*
+ * Static function to get the expected throughput from an iwl_scale_tbl_info
+ * that wraps a NULL pointer check
+ */
+static s32
+iwl4965_get_expected_tpt(struct iwl_scale_tbl_info *tbl, int rs_index)
+{
+	if (tbl->expected_tpt)
+		return tbl->expected_tpt[rs_index];
+	return 0;
+}
+
+/**
+ * iwl4965_rs_collect_tx_data - Update the success/failure sliding window
+ *
+ * We keep a sliding window of the last 62 packets transmitted
+ * at this rate.  window->data contains the bitmask of successful
+ * packets.
+ */
+static int iwl4965_rs_collect_tx_data(struct iwl_scale_tbl_info *tbl,
+			      int scale_index, int attempts, int successes)
+{
+	struct iwl_rate_scale_data *window = NULL;
+	static const u64 mask = (((u64)1) << (IWL_RATE_MAX_WINDOW - 1));
+	s32 fail_count, tpt;
+
+	if (scale_index < 0 || scale_index >= IWL_RATE_COUNT)
+		return -EINVAL;
+
+	/* Select window for current tx bit rate */
+	window = &(tbl->win[scale_index]);
+
+	/* Get expected throughput */
+	tpt = iwl4965_get_expected_tpt(tbl, scale_index);
+
+	/*
+	 * Keep track of only the latest 62 tx frame attempts in this rate's
+	 * history window; anything older isn't really relevant any more.
+	 * If we have filled up the sliding window, drop the oldest attempt;
+	 * if the oldest attempt (highest bit in bitmap) shows "success",
+	 * subtract "1" from the success counter (this is the main reason
+	 * we keep these bitmaps!).
+	 */
+	while (attempts > 0) {
+		if (window->counter >= IWL_RATE_MAX_WINDOW) {
+
+			/* remove earliest */
+			window->counter = IWL_RATE_MAX_WINDOW - 1;
+
+			if (window->data & mask) {
+				window->data &= ~mask;
+				window->success_counter--;
+			}
+		}
+
+		/* Increment frames-attempted counter */
+		window->counter++;
+
+		/* Shift bitmap by one frame to throw away oldest history */
+		window->data <<= 1;
+
+		/* Mark the most recent #successes attempts as successful */
+		if (successes > 0) {
+			window->success_counter++;
+			window->data |= 0x1;
+			successes--;
+		}
+
+		attempts--;
+	}
+
+	/* Calculate current success ratio, avoid divide-by-0! */
+	if (window->counter > 0)
+		window->success_ratio = 128 * (100 * window->success_counter)
+					/ window->counter;
+	else
+		window->success_ratio = IWL_INVALID_VALUE;
+
+	fail_count = window->counter - window->success_counter;
+
+	/* Calculate average throughput, if we have enough history. */
+	if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
+	    (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
+		window->average_tpt = (window->success_ratio * tpt + 64) / 128;
+	else
+		window->average_tpt = IWL_INVALID_VALUE;
+
+	/* Tag this window as having been updated */
+	window->stamp = jiffies;
+
+	return 0;
+}
+
+/*
+ * Fill uCode API rate_n_flags field, based on "search" or "active" table.
+ */
+static u32 iwl4965_rate_n_flags_from_tbl(struct iwl_priv *priv,
+				 struct iwl_scale_tbl_info *tbl,
+				 int index, u8 use_green)
+{
+	u32 rate_n_flags = 0;
+
+	if (is_legacy(tbl->lq_type)) {
+		rate_n_flags = iwlegacy_rates[index].plcp;
+		if (index >= IWL_FIRST_CCK_RATE && index <= IWL_LAST_CCK_RATE)
+			rate_n_flags |= RATE_MCS_CCK_MSK;
+
+	} else if (is_Ht(tbl->lq_type)) {
+		if (index > IWL_LAST_OFDM_RATE) {
+			IWL_ERR(priv, "Invalid HT rate index %d\n", index);
+			index = IWL_LAST_OFDM_RATE;
+		}
+		rate_n_flags = RATE_MCS_HT_MSK;
+
+		if (is_siso(tbl->lq_type))
+			rate_n_flags |=	iwlegacy_rates[index].plcp_siso;
+		else
+			rate_n_flags |=	iwlegacy_rates[index].plcp_mimo2;
+	} else {
+		IWL_ERR(priv, "Invalid tbl->lq_type %d\n", tbl->lq_type);
+	}
+
+	rate_n_flags |= ((tbl->ant_type << RATE_MCS_ANT_POS) &
+						     RATE_MCS_ANT_ABC_MSK);
+
+	if (is_Ht(tbl->lq_type)) {
+		if (tbl->is_ht40) {
+			if (tbl->is_dup)
+				rate_n_flags |= RATE_MCS_DUP_MSK;
+			else
+				rate_n_flags |= RATE_MCS_HT40_MSK;
+		}
+		if (tbl->is_SGI)
+			rate_n_flags |= RATE_MCS_SGI_MSK;
+
+		if (use_green) {
+			rate_n_flags |= RATE_MCS_GF_MSK;
+			if (is_siso(tbl->lq_type) && tbl->is_SGI) {
+				rate_n_flags &= ~RATE_MCS_SGI_MSK;
+				IWL_ERR(priv, "GF was set with SGI:SISO\n");
+			}
+		}
+	}
+	return rate_n_flags;
+}
+
+/*
+ * Interpret uCode API's rate_n_flags format,
+ * fill "search" or "active" tx mode table.
+ */
+static int iwl4965_rs_get_tbl_info_from_mcs(const u32 rate_n_flags,
+				    enum ieee80211_band band,
+				    struct iwl_scale_tbl_info *tbl,
+				    int *rate_idx)
+{
+	u32 ant_msk = (rate_n_flags & RATE_MCS_ANT_ABC_MSK);
+	u8 iwl4965_num_of_ant = iwl4965_get_iwl4965_num_of_ant_from_rate(rate_n_flags);
+	u8 mcs;
+
+	memset(tbl, 0, sizeof(struct iwl_scale_tbl_info));
+	*rate_idx = iwl4965_hwrate_to_plcp_idx(rate_n_flags);
+
+	if (*rate_idx  == IWL_RATE_INVALID) {
+		*rate_idx = -1;
+		return -EINVAL;
+	}
+	tbl->is_SGI = 0;	/* default legacy setup */
+	tbl->is_ht40 = 0;
+	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)) {
+		if (iwl4965_num_of_ant == 1) {
+			if (band == IEEE80211_BAND_5GHZ)
+				tbl->lq_type = LQ_A;
+			else
+				tbl->lq_type = LQ_G;
+		}
+	/* HT rate format */
+	} else {
+		if (rate_n_flags & RATE_MCS_SGI_MSK)
+			tbl->is_SGI = 1;
+
+		if ((rate_n_flags & RATE_MCS_HT40_MSK) ||
+		    (rate_n_flags & RATE_MCS_DUP_MSK))
+			tbl->is_ht40 = 1;
+
+		if (rate_n_flags & RATE_MCS_DUP_MSK)
+			tbl->is_dup = 1;
+
+		mcs = iwl4965_rs_extract_rate(rate_n_flags);
+
+		/* SISO */
+		if (mcs <= IWL_RATE_SISO_60M_PLCP) {
+			if (iwl4965_num_of_ant == 1)
+				tbl->lq_type = LQ_SISO; /*else NONE*/
+		/* MIMO2 */
+		} else {
+			if (iwl4965_num_of_ant == 2)
+				tbl->lq_type = LQ_MIMO2;
+		}
+	}
+	return 0;
+}
+
+/* switch to another antenna/antennas and return 1 */
+/* if no other valid antenna found, return 0 */
+static int iwl4965_rs_toggle_antenna(u32 valid_ant, u32 *rate_n_flags,
+			     struct iwl_scale_tbl_info *tbl)
+{
+	u8 new_ant_type;
+
+	if (!tbl->ant_type || tbl->ant_type > ANT_ABC)
+		return 0;
+
+	if (!iwl4965_rs_is_valid_ant(valid_ant, tbl->ant_type))
+		return 0;
+
+	new_ant_type = ant_toggle_lookup[tbl->ant_type];
+
+	while ((new_ant_type != tbl->ant_type) &&
+	       !iwl4965_rs_is_valid_ant(valid_ant, new_ant_type))
+		new_ant_type = ant_toggle_lookup[new_ant_type];
+
+	if (new_ant_type == tbl->ant_type)
+		return 0;
+
+	tbl->ant_type = new_ant_type;
+	*rate_n_flags &= ~RATE_MCS_ANT_ABC_MSK;
+	*rate_n_flags |= new_ant_type << RATE_MCS_ANT_POS;
+	return 1;
+}
+
+/**
+ * Green-field mode is valid if the station supports it and
+ * there are no non-GF stations present in the BSS.
+ */
+static bool iwl4965_rs_use_green(struct ieee80211_sta *sta)
+{
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	return (sta->ht_cap.cap & IEEE80211_HT_CAP_GRN_FLD) &&
+		!(ctx->ht.non_gf_sta_present);
+}
+
+/**
+ * iwl4965_rs_get_supported_rates - get the available rates
+ *
+ * if management frame or broadcast frame only return
+ * basic available rates.
+ *
+ */
+static u16 iwl4965_rs_get_supported_rates(struct iwl_lq_sta *lq_sta,
+				  struct ieee80211_hdr *hdr,
+				  enum iwl_table_type rate_type)
+{
+	if (is_legacy(rate_type)) {
+		return lq_sta->active_legacy_rate;
+	} else {
+		if (is_siso(rate_type))
+			return lq_sta->active_siso_rate;
+		else
+			return lq_sta->active_mimo2_rate;
+	}
+}
+
+static u16
+iwl4965_rs_get_adjacent_rate(struct iwl_priv *priv, u8 index, u16 rate_mask,
+				int rate_type)
+{
+	u8 high = IWL_RATE_INVALID;
+	u8 low = IWL_RATE_INVALID;
+
+	/* 802.11A or ht walks to the next literal adjacent rate in
+	 * the rate table */
+	if (is_a_band(rate_type) || !is_legacy(rate_type)) {
+		int i;
+		u32 mask;
+
+		/* Find the previous rate that is in the rate mask */
+		i = index - 1;
+		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
+			if (rate_mask & mask) {
+				low = i;
+				break;
+			}
+		}
+
+		/* Find the next rate that is in the rate mask */
+		i = index + 1;
+		for (mask = (1 << i); i < IWL_RATE_COUNT; i++, mask <<= 1) {
+			if (rate_mask & mask) {
+				high = i;
+				break;
+			}
+		}
+
+		return (high << 8) | low;
+	}
+
+	low = index;
+	while (low != IWL_RATE_INVALID) {
+		low = iwlegacy_rates[low].prev_rs;
+		if (low == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << low))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
+	}
+
+	high = index;
+	while (high != IWL_RATE_INVALID) {
+		high = iwlegacy_rates[high].next_rs;
+		if (high == IWL_RATE_INVALID)
+			break;
+		if (rate_mask & (1 << high))
+			break;
+		IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
+	}
+
+	return (high << 8) | low;
+}
+
+static u32 iwl4965_rs_get_lower_rate(struct iwl_lq_sta *lq_sta,
+			     struct iwl_scale_tbl_info *tbl,
+			     u8 scale_index, u8 ht_possible)
+{
+	s32 low;
+	u16 rate_mask;
+	u16 high_low;
+	u8 switch_to_legacy = 0;
+	u8 is_green = lq_sta->is_green;
+	struct iwl_priv *priv = lq_sta->drv;
+
+	/* check if we need to switch from HT to legacy rates.
+	 * assumption is that mandatory rates (1Mbps or 6Mbps)
+	 * are always supported (spec demand) */
+	if (!is_legacy(tbl->lq_type) && (!ht_possible || !scale_index)) {
+		switch_to_legacy = 1;
+		scale_index = rs_ht_to_legacy[scale_index];
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+			tbl->lq_type = LQ_A;
+		else
+			tbl->lq_type = LQ_G;
+
+		if (iwl4965_num_of_ant(tbl->ant_type) > 1)
+			tbl->ant_type =
+				iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+
+		tbl->is_ht40 = 0;
+		tbl->is_SGI = 0;
+		tbl->max_search = IWL_MAX_SEARCH;
+	}
+
+	rate_mask = iwl4965_rs_get_supported_rates(lq_sta, NULL, tbl->lq_type);
+
+	/* Mask with station rate restriction */
+	if (is_legacy(tbl->lq_type)) {
+		/* supp_rates has no CCK bits in A mode */
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+			rate_mask  = (u16)(rate_mask &
+			   (lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+		else
+			rate_mask = (u16)(rate_mask & lq_sta->supp_rates);
+	}
+
+	/* If we switched from HT to legacy, check current rate */
+	if (switch_to_legacy && (rate_mask & (1 << scale_index))) {
+		low = scale_index;
+		goto out;
+	}
+
+	high_low = iwl4965_rs_get_adjacent_rate(lq_sta->drv,
+					scale_index, rate_mask,
+					tbl->lq_type);
+	low = high_low & 0xff;
+
+	if (low == IWL_RATE_INVALID)
+		low = scale_index;
+
+out:
+	return iwl4965_rate_n_flags_from_tbl(lq_sta->drv, tbl, low, is_green);
+}
+
+/*
+ * Simple function to compare two rate scale table types
+ */
+static bool iwl4965_table_type_matches(struct iwl_scale_tbl_info *a,
+			       struct iwl_scale_tbl_info *b)
+{
+	return (a->lq_type == b->lq_type) && (a->ant_type == b->ant_type) &&
+		(a->is_SGI == b->is_SGI);
+}
+
+/*
+ * mac80211 sends us Tx status
+ */
+static void
+iwl4965_rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband,
+			 struct ieee80211_sta *sta, void *priv_sta,
+			 struct sk_buff *skb)
+{
+	int legacy_success;
+	int retries;
+	int rs_index, mac_index, i;
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	struct iwl_link_quality_cmd *table;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct iwl_priv *priv = (struct iwl_priv *)priv_r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	enum mac80211_rate_control_flags mac_flags;
+	u32 tx_rate;
+	struct iwl_scale_tbl_info tbl_type;
+	struct iwl_scale_tbl_info *curr_tbl, *other_tbl, *tmp_tbl;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	IWL_DEBUG_RATE_LIMIT(priv,
+		"get frame ack response, update rate scale window\n");
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (!lq_sta) {
+		IWL_DEBUG_RATE(priv, "Station rate scaling not created yet.\n");
+		return;
+	} else if (!lq_sta->drv) {
+		IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
+		return;
+	}
+
+	if (!ieee80211_is_data(hdr->frame_control) ||
+	    info->flags & IEEE80211_TX_CTL_NO_ACK)
+		return;
+
+	/* This packet was aggregated but doesn't carry status info */
+	if ((info->flags & IEEE80211_TX_CTL_AMPDU) &&
+	    !(info->flags & IEEE80211_TX_STAT_AMPDU))
+		return;
+
+	/*
+	 * Ignore this Tx frame response if its initial rate doesn't match
+	 * that of latest Link Quality command.  There may be stragglers
+	 * from a previous Link Quality command, but we're no longer interested
+	 * in those; they're either from the "active" mode while we're trying
+	 * to check "search" mode, or a prior "search" mode after we've moved
+	 * to a new "search" mode (which might become the new "active" mode).
+	 */
+	table = &lq_sta->lq;
+	tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
+	iwl4965_rs_get_tbl_info_from_mcs(tx_rate,
+			 priv->band, &tbl_type, &rs_index);
+	if (priv->band == IEEE80211_BAND_5GHZ)
+		rs_index -= IWL_FIRST_OFDM_RATE;
+	mac_flags = info->status.rates[0].flags;
+	mac_index = info->status.rates[0].idx;
+	/* For HT packets, map MCS to PLCP */
+	if (mac_flags & IEEE80211_TX_RC_MCS) {
+		mac_index &= RATE_MCS_CODE_MSK;	/* Remove # of streams */
+		if (mac_index >= (IWL_RATE_9M_INDEX - IWL_FIRST_OFDM_RATE))
+			mac_index++;
+		/*
+		 * mac80211 HT index is always zero-indexed; we need to move
+		 * HT OFDM rates after CCK rates in 2.4 GHz band
+		 */
+		if (priv->band == IEEE80211_BAND_2GHZ)
+			mac_index += IWL_FIRST_OFDM_RATE;
+	}
+	/* Here we actually compare this rate to the latest LQ command */
+	if ((mac_index < 0) ||
+	    (tbl_type.is_SGI !=
+			!!(mac_flags & IEEE80211_TX_RC_SHORT_GI)) ||
+	    (tbl_type.is_ht40 !=
+			!!(mac_flags & IEEE80211_TX_RC_40_MHZ_WIDTH)) ||
+	    (tbl_type.is_dup !=
+			!!(mac_flags & IEEE80211_TX_RC_DUP_DATA)) ||
+	    (tbl_type.ant_type != info->antenna_sel_tx) ||
+	    (!!(tx_rate & RATE_MCS_HT_MSK) !=
+			!!(mac_flags & IEEE80211_TX_RC_MCS)) ||
+	    (!!(tx_rate & RATE_MCS_GF_MSK) !=
+			!!(mac_flags & IEEE80211_TX_RC_GREEN_FIELD)) ||
+	    (rs_index != mac_index)) {
+		IWL_DEBUG_RATE(priv,
+		"initial rate %d does not match %d (0x%x)\n",
+			 mac_index, rs_index, tx_rate);
+		/*
+		 * Since rates mis-match, the last LQ command may have failed.
+		 * After IWL_MISSED_RATE_MAX mis-matches, resync the uCode with
+		 * ... driver.
+		 */
+		lq_sta->missed_rate_counter++;
+		if (lq_sta->missed_rate_counter > IWL_MISSED_RATE_MAX) {
+			lq_sta->missed_rate_counter = 0;
+			iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq,
+							CMD_ASYNC, false);
+		}
+		/* Regardless, ignore this status info for outdated rate */
+		return;
+	} else
+		/* Rate did match, so reset the missed_rate_counter */
+		lq_sta->missed_rate_counter = 0;
+
+	/* Figure out if rate scale algorithm is in active or search table */
+	if (iwl4965_table_type_matches(&tbl_type,
+				&(lq_sta->lq_info[lq_sta->active_tbl]))) {
+		curr_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+		other_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+	} else if (iwl4965_table_type_matches(&tbl_type,
+				&lq_sta->lq_info[1 - lq_sta->active_tbl])) {
+		curr_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+		other_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+	} else {
+		IWL_DEBUG_RATE(priv,
+			"Neither active nor search matches tx rate\n");
+		tmp_tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+		IWL_DEBUG_RATE(priv, "active- lq:%x, ant:%x, SGI:%d\n",
+			tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
+		tmp_tbl = &(lq_sta->lq_info[1 - lq_sta->active_tbl]);
+		IWL_DEBUG_RATE(priv, "search- lq:%x, ant:%x, SGI:%d\n",
+			tmp_tbl->lq_type, tmp_tbl->ant_type, tmp_tbl->is_SGI);
+		IWL_DEBUG_RATE(priv, "actual- lq:%x, ant:%x, SGI:%d\n",
+			tbl_type.lq_type, tbl_type.ant_type, tbl_type.is_SGI);
+		/*
+		 * no matching table found, let's by-pass the data collection
+		 * and continue to perform rate scale to find the rate table
+		 */
+		iwl4965_rs_stay_in_table(lq_sta, true);
+		goto done;
+	}
+
+	/*
+	 * Updating the frame history depends on whether packets were
+	 * aggregated.
+	 *
+	 * For aggregation, all packets were transmitted at the same rate, the
+	 * first index into rate scale table.
+	 */
+	if (info->flags & IEEE80211_TX_STAT_AMPDU) {
+		tx_rate = le32_to_cpu(table->rs_table[0].rate_n_flags);
+		iwl4965_rs_get_tbl_info_from_mcs(tx_rate, priv->band, &tbl_type,
+				&rs_index);
+		iwl4965_rs_collect_tx_data(curr_tbl, rs_index,
+				   info->status.ampdu_len,
+				   info->status.ampdu_ack_len);
+
+		/* Update success/fail counts if not searching for new mode */
+		if (lq_sta->stay_in_tbl) {
+			lq_sta->total_success += info->status.ampdu_ack_len;
+			lq_sta->total_failed += (info->status.ampdu_len -
+					info->status.ampdu_ack_len);
+		}
+	} else {
+	/*
+	 * For legacy, update frame history with for each Tx retry.
+	 */
+		retries = info->status.rates[0].count - 1;
+		/* HW doesn't send more than 15 retries */
+		retries = min(retries, 15);
+
+		/* The last transmission may have been successful */
+		legacy_success = !!(info->flags & IEEE80211_TX_STAT_ACK);
+		/* Collect data for each rate used during failed TX attempts */
+		for (i = 0; i <= retries; ++i) {
+			tx_rate = le32_to_cpu(table->rs_table[i].rate_n_flags);
+			iwl4965_rs_get_tbl_info_from_mcs(tx_rate, priv->band,
+					&tbl_type, &rs_index);
+			/*
+			 * Only collect stats if retried rate is in the same RS
+			 * table as active/search.
+			 */
+			if (iwl4965_table_type_matches(&tbl_type, curr_tbl))
+				tmp_tbl = curr_tbl;
+			else if (iwl4965_table_type_matches(&tbl_type,
+								 other_tbl))
+				tmp_tbl = other_tbl;
+			else
+				continue;
+			iwl4965_rs_collect_tx_data(tmp_tbl, rs_index, 1,
+					   i < retries ? 0 : legacy_success);
+		}
+
+		/* Update success/fail counts if not searching for new mode */
+		if (lq_sta->stay_in_tbl) {
+			lq_sta->total_success += legacy_success;
+			lq_sta->total_failed += retries + (1 - legacy_success);
+		}
+	}
+	/* The last TX rate is cached in lq_sta; it's set in if/else above */
+	lq_sta->last_rate_n_flags = tx_rate;
+done:
+	/* See if there's a better rate or modulation mode to try. */
+	if (sta && sta->supp_rates[sband->band])
+		iwl4965_rs_rate_scale_perform(priv, skb, sta, lq_sta);
+}
+
+/*
+ * Begin a period of staying with a selected modulation mode.
+ * Set "stay_in_tbl" flag to prevent any mode switches.
+ * Set frame tx success limits according to legacy vs. high-throughput,
+ * and reset overall (spanning all rates) tx success history statistics.
+ * These control how long we stay using same modulation mode before
+ * searching for a new mode.
+ */
+static void iwl4965_rs_set_stay_in_table(struct iwl_priv *priv, u8 is_legacy,
+				 struct iwl_lq_sta *lq_sta)
+{
+	IWL_DEBUG_RATE(priv, "we are staying in the same table\n");
+	lq_sta->stay_in_tbl = 1;	/* only place this gets set */
+	if (is_legacy) {
+		lq_sta->table_count_limit = IWL_LEGACY_TABLE_COUNT;
+		lq_sta->max_failure_limit = IWL_LEGACY_FAILURE_LIMIT;
+		lq_sta->max_success_limit = IWL_LEGACY_SUCCESS_LIMIT;
+	} else {
+		lq_sta->table_count_limit = IWL_NONE_LEGACY_TABLE_COUNT;
+		lq_sta->max_failure_limit = IWL_NONE_LEGACY_FAILURE_LIMIT;
+		lq_sta->max_success_limit = IWL_NONE_LEGACY_SUCCESS_LIMIT;
+	}
+	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;
+}
+
+/*
+ * Find correct throughput table for given mode of modulation
+ */
+static void iwl4965_rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
+				      struct iwl_scale_tbl_info *tbl)
+{
+	/* Used to choose among HT tables */
+	s32 (*ht_tbl_pointer)[IWL_RATE_COUNT];
+
+	/* Check for invalid LQ type */
+	if (WARN_ON_ONCE(!is_legacy(tbl->lq_type) && !is_Ht(tbl->lq_type))) {
+		tbl->expected_tpt = expected_tpt_legacy;
+		return;
+	}
+
+	/* Legacy rates have only one table */
+	if (is_legacy(tbl->lq_type)) {
+		tbl->expected_tpt = expected_tpt_legacy;
+		return;
+	}
+
+	/* Choose among many HT tables depending on number of streams
+	 * (SISO/MIMO2), channel width (20/40), SGI, and aggregation
+	 * status */
+	if (is_siso(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
+		ht_tbl_pointer = expected_tpt_siso20MHz;
+	else if (is_siso(tbl->lq_type))
+		ht_tbl_pointer = expected_tpt_siso40MHz;
+	else if (is_mimo2(tbl->lq_type) && (!tbl->is_ht40 || lq_sta->is_dup))
+		ht_tbl_pointer = expected_tpt_mimo2_20MHz;
+	else /* if (is_mimo2(tbl->lq_type)) <-- must be true */
+		ht_tbl_pointer = expected_tpt_mimo2_40MHz;
+
+	if (!tbl->is_SGI && !lq_sta->is_agg)		/* Normal */
+		tbl->expected_tpt = ht_tbl_pointer[0];
+	else if (tbl->is_SGI && !lq_sta->is_agg)	/* SGI */
+		tbl->expected_tpt = ht_tbl_pointer[1];
+	else if (!tbl->is_SGI && lq_sta->is_agg)	/* AGG */
+		tbl->expected_tpt = ht_tbl_pointer[2];
+	else						/* AGG+SGI */
+		tbl->expected_tpt = ht_tbl_pointer[3];
+}
+
+/*
+ * Find starting rate for new "search" high-throughput mode of modulation.
+ * Goal is to find lowest expected rate (under perfect conditions) that is
+ * above the current measured throughput of "active" mode, to give new mode
+ * a fair chance to prove itself without too many challenges.
+ *
+ * This gets called when transitioning to more aggressive modulation
+ * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
+ * (i.e. MIMO to SISO).  When moving to MIMO, bit rate will typically need
+ * to decrease to match "active" throughput.  When moving from MIMO to SISO,
+ * bit rate will typically need to increase, but not if performance was bad.
+ */
+static s32 iwl4965_rs_get_best_rate(struct iwl_priv *priv,
+			    struct iwl_lq_sta *lq_sta,
+			    struct iwl_scale_tbl_info *tbl,	/* "search" */
+			    u16 rate_mask, s8 index)
+{
+	/* "active" values */
+	struct iwl_scale_tbl_info *active_tbl =
+	    &(lq_sta->lq_info[lq_sta->active_tbl]);
+	s32 active_sr = active_tbl->win[index].success_ratio;
+	s32 active_tpt = active_tbl->expected_tpt[index];
+
+	/* expected "search" throughput */
+	s32 *tpt_tbl = tbl->expected_tpt;
+
+	s32 new_rate, high, low, start_hi;
+	u16 high_low;
+	s8 rate = index;
+
+	new_rate = high = low = start_hi = IWL_RATE_INVALID;
+
+	for (; ;) {
+		high_low = iwl4965_rs_get_adjacent_rate(priv, rate, rate_mask,
+						tbl->lq_type);
+
+		low = high_low & 0xff;
+		high = (high_low >> 8) & 0xff;
+
+		/*
+		 * Lower the "search" bit rate, to give new "search" mode
+		 * approximately the same throughput as "active" if:
+		 *
+		 * 1) "Active" mode has been working modestly well (but not
+		 *    great), and expected "search" throughput (under perfect
+		 *    conditions) at candidate rate is above the actual
+		 *    measured "active" throughput (but less than expected
+		 *    "active" throughput under perfect conditions).
+		 * OR
+		 * 2) "Active" mode has been working perfectly or very well
+		 *    and expected "search" throughput (under perfect
+		 *    conditions) at candidate rate is above expected
+		 *    "active" throughput (under perfect conditions).
+		 */
+		if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
+		     ((active_sr > IWL_RATE_DECREASE_TH) &&
+		      (active_sr <= IWL_RATE_HIGH_TH) &&
+		      (tpt_tbl[rate] <= active_tpt))) ||
+		    ((active_sr >= IWL_RATE_SCALE_SWITCH) &&
+		     (tpt_tbl[rate] > active_tpt))) {
+
+			/* (2nd or later pass)
+			 * If we've already tried to raise the rate, and are
+			 * now trying to lower it, use the higher rate. */
+			if (start_hi != IWL_RATE_INVALID) {
+				new_rate = start_hi;
+				break;
+			}
+
+			new_rate = rate;
+
+			/* Loop again with lower rate */
+			if (low != IWL_RATE_INVALID)
+				rate = low;
+
+			/* Lower rate not available, use the original */
+			else
+				break;
+
+		/* Else try to raise the "search" rate to match "active" */
+		} else {
+			/* (2nd or later pass)
+			 * If we've already tried to lower the rate, and are
+			 * now trying to raise it, use the lower rate. */
+			if (new_rate != IWL_RATE_INVALID)
+				break;
+
+			/* Loop again with higher rate */
+			else if (high != IWL_RATE_INVALID) {
+				start_hi = high;
+				rate = high;
+
+			/* Higher rate not available, use the original */
+			} else {
+				new_rate = rate;
+				break;
+			}
+		}
+	}
+
+	return new_rate;
+}
+
+/*
+ * Set up search table for MIMO2
+ */
+static int iwl4965_rs_switch_to_mimo2(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;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	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 < 2)
+		return -1;
+
+	IWL_DEBUG_RATE(priv, "LQ: try to switch to MIMO2\n");
+
+	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 (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+		tbl->is_ht40 = 1;
+	else
+		tbl->is_ht40 = 0;
+
+	iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
+
+	rate = iwl4965_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 = iwl4965_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 SISO
+ */
+static int iwl4965_rs_switch_to_siso(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;
+	u8 is_green = lq_sta->is_green;
+	s32 rate;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	if (!conf_is_ht(conf) || !sta->ht_cap.ht_supported)
+		return -1;
+
+	IWL_DEBUG_RATE(priv, "LQ: try to switch to SISO\n");
+
+	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 (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+		tbl->is_ht40 = 1;
+	else
+		tbl->is_ht40 = 0;
+
+	if (is_green)
+		tbl->is_SGI = 0; /*11n spec: no SGI in SISO+Greenfield*/
+
+	iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
+	rate = iwl4965_rs_get_best_rate(priv, lq_sta, tbl, rate_mask, index);
+
+	IWL_DEBUG_RATE(priv, "LQ: get best rate %d mask %X\n", rate, rate_mask);
+	if ((rate == IWL_RATE_INVALID) || !((1 << rate) & rate_mask)) {
+		IWL_DEBUG_RATE(priv,
+			"can not switch with index %d rate mask %x\n",
+			     rate, rate_mask);
+		return -1;
+	}
+	tbl->current_rate = iwl4965_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;
+}
+
+/*
+ * Try to switch to new modulation mode from legacy
+ */
+static int iwl4965_rs_move_legacy_other(struct iwl_priv *priv,
+				struct iwl_lq_sta *lq_sta,
+				struct ieee80211_conf *conf,
+				struct ieee80211_sta *sta,
+				int index)
+{
+	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;
+	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;
+
+	tbl->action = IWL_LEGACY_SWITCH_SISO;
+
+	start_action = tbl->action;
+	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");
+
+			if ((tbl->action == IWL_LEGACY_SWITCH_ANTENNA1 &&
+							tx_chains_num <= 1) ||
+			    (tbl->action == IWL_LEGACY_SWITCH_ANTENNA2 &&
+							tx_chains_num <= 2))
+				break;
+
+			/* Don't change antenna if success has been great */
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			/* Set up search table to try other antenna */
+			memcpy(search_tbl, tbl, sz);
+
+			if (iwl4965_rs_toggle_antenna(valid_tx_ant,
+				&search_tbl->current_rate, search_tbl)) {
+				update_search_tbl_counter = 1;
+				iwl4965_rs_set_expected_tpt_table(lq_sta,
+								search_tbl);
+				goto out;
+			}
+			break;
+		case IWL_LEGACY_SWITCH_SISO:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy switch to SISO\n");
+
+			/* Set up search table to try SISO */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+			ret = iwl4965_rs_switch_to_siso(priv, lq_sta, conf, sta,
+						 search_tbl, index);
+			if (!ret) {
+				lq_sta->action_counter = 0;
+				goto out;
+			}
+
+			break;
+		case IWL_LEGACY_SWITCH_MIMO2_AB:
+		case IWL_LEGACY_SWITCH_MIMO2_AC:
+		case IWL_LEGACY_SWITCH_MIMO2_BC:
+			IWL_DEBUG_RATE(priv, "LQ: Legacy switch to MIMO2\n");
+
+			/* Set up search table to try MIMO */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+
+			if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AB)
+				search_tbl->ant_type = ANT_AB;
+			else if (tbl->action == IWL_LEGACY_SWITCH_MIMO2_AC)
+				search_tbl->ant_type = ANT_AC;
+			else
+				search_tbl->ant_type = ANT_BC;
+
+			if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
+						search_tbl->ant_type))
+				break;
+
+			ret = iwl4965_rs_switch_to_mimo2(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)
+			tbl->action = IWL_LEGACY_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_LEGACY_SWITCH_MIMO2_BC)
+		tbl->action = IWL_LEGACY_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+	return 0;
+
+}
+
+/*
+ * Try to switch to new modulation mode from SISO
+ */
+static int iwl4965_rs_move_siso_to_other(struct iwl_priv *priv,
+				 struct iwl_lq_sta *lq_sta,
+				 struct ieee80211_conf *conf,
+				 struct ieee80211_sta *sta, int index)
+{
+	u8 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]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_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;
+
+	start_action = tbl->action;
+
+	for (;;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_SISO_SWITCH_ANTENNA1:
+		case IWL_SISO_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: SISO toggle Antenna\n");
+			if ((tbl->action == IWL_SISO_SWITCH_ANTENNA1 &&
+						tx_chains_num <= 1) ||
+			    (tbl->action == IWL_SISO_SWITCH_ANTENNA2 &&
+						tx_chains_num <= 2))
+				break;
+
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			memcpy(search_tbl, tbl, sz);
+			if (iwl4965_rs_toggle_antenna(valid_tx_ant,
+				       &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:
+		case IWL_SISO_SWITCH_MIMO2_BC:
+			IWL_DEBUG_RATE(priv, "LQ: SISO switch to MIMO2\n");
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = 0;
+
+			if (tbl->action == IWL_SISO_SWITCH_MIMO2_AB)
+				search_tbl->ant_type = ANT_AB;
+			else if (tbl->action == IWL_SISO_SWITCH_MIMO2_AC)
+				search_tbl->ant_type = ANT_AC;
+			else
+				search_tbl->ant_type = ANT_BC;
+
+			if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
+						 search_tbl->ant_type))
+				break;
+
+			ret = iwl4965_rs_switch_to_mimo2(priv, lq_sta,
+						conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+			break;
+		case IWL_SISO_SWITCH_GI:
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
+				break;
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
+				break;
+
+			IWL_DEBUG_RATE(priv, "LQ: SISO toggle SGI/NGI\n");
+
+			memcpy(search_tbl, tbl, sz);
+			if (is_green) {
+				if (!tbl->is_SGI)
+					break;
+				else
+					IWL_ERR(priv,
+						"SGI was set in GF+SISO\n");
+			}
+			search_tbl->is_SGI = !tbl->is_SGI;
+			iwl4965_rs_set_expected_tpt_table(lq_sta, search_tbl);
+			if (tbl->is_SGI) {
+				s32 tpt = lq_sta->last_tpt / 100;
+				if (tpt >= search_tbl->expected_tpt[index])
+					break;
+			}
+			search_tbl->current_rate =
+				iwl4965_rate_n_flags_from_tbl(priv, search_tbl,
+						      index, is_green);
+			update_search_tbl_counter = 1;
+			goto out;
+		}
+		tbl->action++;
+		if (tbl->action > IWL_SISO_SWITCH_GI)
+			tbl->action = IWL_SISO_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_SISO_SWITCH_GI)
+		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 MIMO2
+ */
+static int iwl4965_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)
+{
+	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]);
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+	u32 sz = (sizeof(struct iwl_scale_tbl_info) -
+		  (sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
+	u8 start_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;
+
+	start_action = tbl->action;
+	for (;;) {
+		lq_sta->action_counter++;
+		switch (tbl->action) {
+		case IWL_MIMO2_SWITCH_ANTENNA1:
+		case IWL_MIMO2_SWITCH_ANTENNA2:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle Antennas\n");
+
+			if (tx_chains_num <= 2)
+				break;
+
+			if (window->success_ratio >= IWL_RS_GOOD_RATIO)
+				break;
+
+			memcpy(search_tbl, tbl, sz);
+			if (iwl4965_rs_toggle_antenna(valid_tx_ant,
+				       &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:
+		case IWL_MIMO2_SWITCH_SISO_C:
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 switch to SISO\n");
+
+			/* Set up new search table for SISO */
+			memcpy(search_tbl, tbl, sz);
+
+			if (tbl->action == IWL_MIMO2_SWITCH_SISO_A)
+				search_tbl->ant_type = ANT_A;
+			else if (tbl->action == IWL_MIMO2_SWITCH_SISO_B)
+				search_tbl->ant_type = ANT_B;
+			else
+				search_tbl->ant_type = ANT_C;
+
+			if (!iwl4965_rs_is_valid_ant(valid_tx_ant,
+						search_tbl->ant_type))
+				break;
+
+			ret = iwl4965_rs_switch_to_siso(priv, lq_sta,
+						conf, sta,
+						 search_tbl, index);
+			if (!ret)
+				goto out;
+
+			break;
+
+		case IWL_MIMO2_SWITCH_GI:
+			if (!tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_20))
+				break;
+			if (tbl->is_ht40 && !(ht_cap->cap &
+						IEEE80211_HT_CAP_SGI_40))
+				break;
+
+			IWL_DEBUG_RATE(priv, "LQ: MIMO2 toggle SGI/NGI\n");
+
+			/* Set up new search table for MIMO2 */
+			memcpy(search_tbl, tbl, sz);
+			search_tbl->is_SGI = !tbl->is_SGI;
+			iwl4965_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 =
+				iwl4965_rate_n_flags_from_tbl(priv, search_tbl,
+						      index, is_green);
+			update_search_tbl_counter = 1;
+			goto out;
+
+		}
+		tbl->action++;
+		if (tbl->action > IWL_MIMO2_SWITCH_GI)
+			tbl->action = IWL_MIMO2_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_MIMO2_SWITCH_GI)
+		tbl->action = IWL_MIMO2_SWITCH_ANTENNA1;
+	if (update_search_tbl_counter)
+		search_tbl->action = tbl->action;
+
+	return 0;
+
+}
+
+/*
+ * Check whether we should continue using same modulation mode, or
+ * begin search for a new mode, based on:
+ * 1) # tx successes or failures while using this mode
+ * 2) # times calling this function
+ * 3) elapsed time in this mode (not used, for now)
+ */
+static void
+iwl4965_rs_stay_in_table(struct iwl_lq_sta *lq_sta, bool force_search)
+{
+	struct iwl_scale_tbl_info *tbl;
+	int i;
+	int active_tbl;
+	int flush_interval_passed = 0;
+	struct iwl_priv *priv;
+
+	priv = lq_sta->drv;
+	active_tbl = lq_sta->active_tbl;
+
+	tbl = &(lq_sta->lq_info[active_tbl]);
+
+	/* If we've been disallowing search, see if we should now allow it */
+	if (lq_sta->stay_in_tbl) {
+
+		/* Elapsed time using current modulation mode */
+		if (lq_sta->flush_timer)
+			flush_interval_passed =
+			time_after(jiffies,
+					(unsigned long)(lq_sta->flush_timer +
+					IWL_RATE_SCALE_FLUSH_INTVL));
+
+		/*
+		 * Check if we should allow search for new modulation mode.
+		 * If many frames have failed or succeeded, or we've used
+		 * this same modulation for a long time, allow search, and
+		 * reset history stats that keep track of whether we should
+		 * allow a new search.  Also (below) reset all bitmaps and
+		 * stats in active history.
+		 */
+		if (force_search ||
+		    (lq_sta->total_failed > lq_sta->max_failure_limit) ||
+		    (lq_sta->total_success > lq_sta->max_success_limit) ||
+		    ((!lq_sta->search_better_tbl) && (lq_sta->flush_timer)
+		     && (flush_interval_passed))) {
+			IWL_DEBUG_RATE(priv, "LQ: stay is expired %d %d %d\n:",
+				     lq_sta->total_failed,
+				     lq_sta->total_success,
+				     flush_interval_passed);
+
+			/* Allow search for new mode */
+			lq_sta->stay_in_tbl = 0;	/* only place reset */
+			lq_sta->total_failed = 0;
+			lq_sta->total_success = 0;
+			lq_sta->flush_timer = 0;
+
+		/*
+		 * Else if we've used this modulation mode enough repetitions
+		 * (regardless of elapsed time or success/failure), reset
+		 * history bitmaps and rate-specific stats for all rates in
+		 * active table.
+		 */
+		} else {
+			lq_sta->table_count++;
+			if (lq_sta->table_count >=
+			    lq_sta->table_count_limit) {
+				lq_sta->table_count = 0;
+
+				IWL_DEBUG_RATE(priv,
+					"LQ: stay in table clear win\n");
+				for (i = 0; i < IWL_RATE_COUNT; i++)
+					iwl4965_rs_rate_scale_clear_window(
+						&(tbl->win[i]));
+			}
+		}
+
+		/* If transitioning to allow "search", reset all history
+		 * bitmaps and stats in active table (this will become the new
+		 * "search" table). */
+		if (!lq_sta->stay_in_tbl) {
+			for (i = 0; i < IWL_RATE_COUNT; i++)
+				iwl4965_rs_rate_scale_clear_window(
+							&(tbl->win[i]));
+		}
+	}
+}
+
+/*
+ * setup rate table in uCode
+ * return rate_n_flags as used in the table
+ */
+static u32 iwl4965_rs_update_rate_tbl(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+				struct iwl_lq_sta *lq_sta,
+				struct iwl_scale_tbl_info *tbl,
+				int index, u8 is_green)
+{
+	u32 rate;
+
+	/* Update uCode's rate table. */
+	rate = iwl4965_rate_n_flags_from_tbl(priv, tbl, index, is_green);
+	iwl4965_rs_fill_link_cmd(priv, lq_sta, rate);
+	iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_ASYNC, false);
+
+	return rate;
+}
+
+/*
+ * Do rate scaling and search for new modulation mode.
+ */
+static void iwl4965_rs_rate_scale_perform(struct iwl_priv *priv,
+				  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;
+	int i;
+	struct iwl_rate_scale_data *window = NULL;
+	int current_tpt = IWL_INVALID_VALUE;
+	int low_tpt = IWL_INVALID_VALUE;
+	int high_tpt = IWL_INVALID_VALUE;
+	u32 fail_count;
+	s8 scale_action = 0;
+	u16 rate_mask;
+	u8 update_lq = 0;
+	struct iwl_scale_tbl_info *tbl, *tbl1;
+	u16 rate_scale_index_msk = 0;
+	u32 rate;
+	u8 is_green = 0;
+	u8 active_tbl = 0;
+	u8 done_search = 0;
+	u16 high_low;
+	s32 sr;
+	u8 tid = MAX_TID_COUNT;
+	struct iwl_tid_data *tid_data;
+	struct iwl_station_priv *sta_priv = (void *)sta->drv_priv;
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	IWL_DEBUG_RATE(priv, "rate scale calculate new rate for skb\n");
+
+	/* Send management frames and NO_ACK data using lowest rate. */
+	/* TODO: this could probably be improved.. */
+	if (!ieee80211_is_data(hdr->frame_control) ||
+	    info->flags & IEEE80211_TX_CTL_NO_ACK)
+		return;
+
+	if (!sta || !lq_sta)
+		return;
+
+	lq_sta->supp_rates = sta->supp_rates[lq_sta->band];
+
+	tid = iwl4965_rs_tl_add_packet(lq_sta, hdr);
+	if ((tid != MAX_TID_COUNT) && (lq_sta->tx_agg_tid_en & (1 << tid))) {
+		tid_data = &priv->stations[lq_sta->lq.sta_id].tid[tid];
+		if (tid_data->agg.state == IWL_AGG_OFF)
+			lq_sta->is_agg = 0;
+		else
+			lq_sta->is_agg = 1;
+	} else
+		lq_sta->is_agg = 0;
+
+	/*
+	 * Select rate-scale / modulation-mode table to work with in
+	 * the rest of this function:  "search" if searching for better
+	 * modulation mode, or "active" if doing rate scaling within a mode.
+	 */
+	if (!lq_sta->search_better_tbl)
+		active_tbl = lq_sta->active_tbl;
+	else
+		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 = iwl4965_rs_use_green(sta);
+	is_green = lq_sta->is_green;
+
+	/* current tx rate */
+	index = lq_sta->last_txrate_idx;
+
+	IWL_DEBUG_RATE(priv, "Rate scale index %d for type %d\n", index,
+		       tbl->lq_type);
+
+	/* rates available for this association, and for modulation mode */
+	rate_mask = iwl4965_rs_get_supported_rates(lq_sta, hdr, tbl->lq_type);
+
+	IWL_DEBUG_RATE(priv, "mask 0x%04X\n", rate_mask);
+
+	/* mask with station rate restriction */
+	if (is_legacy(tbl->lq_type)) {
+		if (lq_sta->band == IEEE80211_BAND_5GHZ)
+			/* supp_rates has no CCK bits in A mode */
+			rate_scale_index_msk = (u16) (rate_mask &
+				(lq_sta->supp_rates << IWL_FIRST_OFDM_RATE));
+		else
+			rate_scale_index_msk = (u16) (rate_mask &
+						      lq_sta->supp_rates);
+
+	} else
+		rate_scale_index_msk = rate_mask;
+
+	if (!rate_scale_index_msk)
+		rate_scale_index_msk = rate_mask;
+
+	if (!((1 << index) & rate_scale_index_msk)) {
+		IWL_ERR(priv, "Current Rate is not valid\n");
+		if (lq_sta->search_better_tbl) {
+			/* revert to active table if search table is not valid*/
+			tbl->lq_type = LQ_NONE;
+			lq_sta->search_better_tbl = 0;
+			tbl = &(lq_sta->lq_info[lq_sta->active_tbl]);
+			/* get "active" rate info */
+			index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
+			rate = iwl4965_rs_update_rate_tbl(priv, ctx, lq_sta,
+						  tbl, index, is_green);
+		}
+		return;
+	}
+
+	/* Get expected throughput table and history window for current rate */
+	if (!tbl->expected_tpt) {
+		IWL_ERR(priv, "tbl->expected_tpt is NULL\n");
+		return;
+	}
+
+	/* force user max rate if set by user */
+	if ((lq_sta->max_rate_idx != -1) &&
+	    (lq_sta->max_rate_idx < index)) {
+		index = lq_sta->max_rate_idx;
+		update_lq = 1;
+		window = &(tbl->win[index]);
+		goto lq_update;
+	}
+
+	window = &(tbl->win[index]);
+
+	/*
+	 * If there is not enough history to calculate actual average
+	 * throughput, keep analyzing results of more tx frames, without
+	 * changing rate or mode (bypass most of the rest of this function).
+	 * Set up new rate table in uCode only if old rate is not supported
+	 * in current association (use new rate found above).
+	 */
+	fail_count = window->counter - window->success_counter;
+	if ((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
+			(window->success_counter < IWL_RATE_MIN_SUCCESS_TH)) {
+		IWL_DEBUG_RATE(priv, "LQ: still below TH. succ=%d total=%d "
+			       "for index %d\n",
+			       window->success_counter, window->counter, index);
+
+		/* Can't calculate this yet; not enough history */
+		window->average_tpt = IWL_INVALID_VALUE;
+
+		/* Should we stay with this modulation mode,
+		 * or search for a new one? */
+		iwl4965_rs_stay_in_table(lq_sta, false);
+
+		goto out;
+	}
+	/* Else we have enough samples; calculate estimate of
+	 * actual average throughput */
+	if (window->average_tpt != ((window->success_ratio *
+			tbl->expected_tpt[index] + 64) / 128)) {
+		IWL_ERR(priv,
+			 "expected_tpt should have been calculated by now\n");
+		window->average_tpt = ((window->success_ratio *
+					tbl->expected_tpt[index] + 64) / 128);
+	}
+
+	/* If we are searching for better modulation mode, check success. */
+	if (lq_sta->search_better_tbl) {
+		/* If good success, continue using the "search" mode;
+		 * no need to send new link quality command, since we're
+		 * continuing to use the setup that we've been trying. */
+		if (window->average_tpt > lq_sta->last_tpt) {
+
+			IWL_DEBUG_RATE(priv, "LQ: SWITCHING TO NEW TABLE "
+					"suc=%d cur-tpt=%d old-tpt=%d\n",
+					window->success_ratio,
+					window->average_tpt,
+					lq_sta->last_tpt);
+
+			if (!is_legacy(tbl->lq_type))
+				lq_sta->enable_counter = 1;
+
+			/* Swap tables; "search" becomes "active" */
+			lq_sta->active_tbl = active_tbl;
+			current_tpt = window->average_tpt;
+
+		/* Else poor success; go back to mode in "active" table */
+		} else {
+
+			IWL_DEBUG_RATE(priv, "LQ: GOING BACK TO THE OLD TABLE "
+					"suc=%d cur-tpt=%d old-tpt=%d\n",
+					window->success_ratio,
+					window->average_tpt,
+					lq_sta->last_tpt);
+
+			/* Nullify "search" table */
+			tbl->lq_type = LQ_NONE;
+
+			/* Revert to "active" table */
+			active_tbl = lq_sta->active_tbl;
+			tbl = &(lq_sta->lq_info[active_tbl]);
+
+			/* Revert to "active" rate and throughput info */
+			index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
+			current_tpt = lq_sta->last_tpt;
+
+			/* Need to set up a new rate table in uCode */
+			update_lq = 1;
+		}
+
+		/* Either way, we've made a decision; modulation mode
+		 * search is done, allow rate adjustment next time. */
+		lq_sta->search_better_tbl = 0;
+		done_search = 1;	/* Don't switch modes below! */
+		goto lq_update;
+	}
+
+	/* (Else) not in search of better modulation mode, try for better
+	 * starting rate, while staying in this mode. */
+	high_low = iwl4965_rs_get_adjacent_rate(priv, index,
+					rate_scale_index_msk,
+					tbl->lq_type);
+	low = high_low & 0xff;
+	high = (high_low >> 8) & 0xff;
+
+	/* If user set max rate, dont allow higher than user constrain */
+	if ((lq_sta->max_rate_idx != -1) &&
+	    (lq_sta->max_rate_idx < high))
+		high = IWL_RATE_INVALID;
+
+	sr = window->success_ratio;
+
+	/* Collect measured throughputs for current and adjacent rates */
+	current_tpt = window->average_tpt;
+	if (low != IWL_RATE_INVALID)
+		low_tpt = tbl->win[low].average_tpt;
+	if (high != IWL_RATE_INVALID)
+		high_tpt = tbl->win[high].average_tpt;
+
+	scale_action = 0;
+
+	/* Too many failures, decrease rate */
+	if ((sr <= IWL_RATE_DECREASE_TH) || (current_tpt == 0)) {
+		IWL_DEBUG_RATE(priv,
+			"decrease rate because of low success_ratio\n");
+		scale_action = -1;
+
+	/* No throughput measured yet for adjacent rates; try increase. */
+	} else if ((low_tpt == IWL_INVALID_VALUE) &&
+		   (high_tpt == IWL_INVALID_VALUE)) {
+
+		if (high != IWL_RATE_INVALID && sr >= IWL_RATE_INCREASE_TH)
+			scale_action = 1;
+		else if (low != IWL_RATE_INVALID)
+			scale_action = 0;
+	}
+
+	/* Both adjacent throughputs are measured, but neither one has better
+	 * throughput; we're using the best rate, don't change it! */
+	else if ((low_tpt != IWL_INVALID_VALUE) &&
+		 (high_tpt != IWL_INVALID_VALUE) &&
+		 (low_tpt < current_tpt) &&
+		 (high_tpt < current_tpt))
+		scale_action = 0;
+
+	/* At least one adjacent rate's throughput is measured,
+	 * and may have better performance. */
+	else {
+		/* Higher adjacent rate's throughput is measured */
+		if (high_tpt != IWL_INVALID_VALUE) {
+			/* Higher rate has better throughput */
+			if (high_tpt > current_tpt &&
+					sr >= IWL_RATE_INCREASE_TH) {
+				scale_action = 1;
+			} else {
+				scale_action = 0;
+			}
+
+		/* Lower adjacent rate's throughput is measured */
+		} else if (low_tpt != IWL_INVALID_VALUE) {
+			/* Lower rate has better throughput */
+			if (low_tpt > current_tpt) {
+				IWL_DEBUG_RATE(priv,
+				    "decrease rate because of low tpt\n");
+				scale_action = -1;
+			} else if (sr >= IWL_RATE_INCREASE_TH) {
+				scale_action = 1;
+			}
+		}
+	}
+
+	/* Sanity check; asked for decrease, but success rate or throughput
+	 * has been good at old rate.  Don't change it. */
+	if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
+		    ((sr > IWL_RATE_HIGH_TH) ||
+		     (current_tpt > (100 * tbl->expected_tpt[low]))))
+		scale_action = 0;
+
+	switch (scale_action) {
+	case -1:
+		/* Decrease starting rate, update uCode's rate table */
+		if (low != IWL_RATE_INVALID) {
+			update_lq = 1;
+			index = low;
+		}
+
+		break;
+	case 1:
+		/* Increase starting rate, update uCode's rate table */
+		if (high != IWL_RATE_INVALID) {
+			update_lq = 1;
+			index = high;
+		}
+
+		break;
+	case 0:
+		/* No change */
+	default:
+		break;
+	}
+
+	IWL_DEBUG_RATE(priv, "choose rate scale index %d action %d low %d "
+		    "high %d type %d\n",
+		     index, scale_action, low, high, tbl->lq_type);
+
+lq_update:
+	/* Replace uCode's rate table for the destination station. */
+	if (update_lq)
+		rate = iwl4965_rs_update_rate_tbl(priv, ctx, lq_sta,
+					  tbl, index, is_green);
+
+	/* Should we stay with this modulation mode,
+	 * or search for a new one? */
+	 iwl4965_rs_stay_in_table(lq_sta, false);
+
+	/*
+	 * Search for new modulation mode if we're:
+	 * 1)  Not changing rates right now
+	 * 2)  Not just finishing up a search
+	 * 3)  Allowing a new search
+	 */
+	if (!update_lq && !done_search &&
+		!lq_sta->stay_in_tbl && window->counter) {
+		/* Save current throughput to compare with "search" throughput*/
+		lq_sta->last_tpt = current_tpt;
+
+		/* Select a new "search" modulation mode to try.
+		 * If one is found, set up the new "search" table. */
+		if (is_legacy(tbl->lq_type))
+			iwl4965_rs_move_legacy_other(priv, lq_sta,
+							conf, sta, index);
+		else if (is_siso(tbl->lq_type))
+			iwl4965_rs_move_siso_to_other(priv, lq_sta,
+							conf, sta, index);
+		else /* (is_mimo2(tbl->lq_type)) */
+			iwl4965_rs_move_mimo2_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) {
+			/* Access the "search" table, clear its history. */
+			tbl = &(lq_sta->lq_info[(1 - lq_sta->active_tbl)]);
+			for (i = 0; i < IWL_RATE_COUNT; i++)
+				iwl4965_rs_rate_scale_clear_window(
+							&(tbl->win[i]));
+
+			/* Use new "search" start rate */
+			index = iwl4965_hwrate_to_plcp_idx(tbl->current_rate);
+
+			IWL_DEBUG_RATE(priv,
+				"Switch current  mcs: %X index: %d\n",
+				     tbl->current_rate, index);
+			iwl4965_rs_fill_link_cmd(priv, lq_sta,
+						tbl->current_rate);
+			iwl_legacy_send_lq_cmd(priv, ctx,
+						&lq_sta->lq, CMD_ASYNC, false);
+		} 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),
+		 * stay with best antenna legacy modulation for a while
+		 * 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 > tbl1->max_search) {
+			IWL_DEBUG_RATE(priv, "LQ: STAY in legacy table\n");
+			iwl4965_rs_set_stay_in_table(priv, 1, lq_sta);
+		}
+
+		/* If we're in an HT mode, and all 3 mode switch actions
+		 * 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 >= tbl1->max_search)) {
+			if ((lq_sta->last_tpt > IWL_AGG_TPT_THREHOLD) &&
+			    (lq_sta->tx_agg_tid_en & (1 << tid)) &&
+			    (tid != MAX_TID_COUNT)) {
+				tid_data =
+				   &priv->stations[lq_sta->lq.sta_id].tid[tid];
+				if (tid_data->agg.state == IWL_AGG_OFF) {
+					IWL_DEBUG_RATE(priv,
+						       "try to aggregate tid %d\n",
+						       tid);
+					iwl4965_rs_tl_turn_on_agg(priv, tid,
+							  lq_sta, sta);
+				}
+			}
+			iwl4965_rs_set_stay_in_table(priv, 0, lq_sta);
+		}
+	}
+
+out:
+	tbl->current_rate = iwl4965_rate_n_flags_from_tbl(priv, tbl,
+							index, is_green);
+	i = index;
+	lq_sta->last_txrate_idx = i;
+}
+
+/**
+ * iwl4965_rs_initialize_lq - Initialize a station's hardware rate table
+ *
+ * The uCode's station table contains a table of fallback rates
+ * for automatic fallback during transmission.
+ *
+ * NOTE: This sets up a default set of values.  These will be replaced later
+ *       if the driver's iwl-4965-rs rate scaling algorithm is used, instead of
+ *       rc80211_simple.
+ *
+ * NOTE: Run REPLY_ADD_STA command to set up station table entry, before
+ *       calling this function (which runs REPLY_TX_LINK_QUALITY_CMD,
+ *       which requires station table entry to exist).
+ */
+static void iwl4965_rs_initialize_lq(struct iwl_priv *priv,
+			     struct ieee80211_conf *conf,
+			     struct ieee80211_sta *sta,
+			     struct iwl_lq_sta *lq_sta)
+{
+	struct iwl_scale_tbl_info *tbl;
+	int rate_idx;
+	int i;
+	u32 rate;
+	u8 use_green = iwl4965_rs_use_green(sta);
+	u8 active_tbl = 0;
+	u8 valid_tx_ant;
+	struct iwl_station_priv *sta_priv;
+	struct iwl_rxon_context *ctx;
+
+	if (!sta || !lq_sta)
+		return;
+
+	sta_priv = (void *)sta->drv_priv;
+	ctx = sta_priv->common.ctx;
+
+	i = lq_sta->last_txrate_idx;
+
+	valid_tx_ant = priv->hw_params.valid_tx_ant;
+
+	if (!lq_sta->search_better_tbl)
+		active_tbl = lq_sta->active_tbl;
+	else
+		active_tbl = 1 - lq_sta->active_tbl;
+
+	tbl = &(lq_sta->lq_info[active_tbl]);
+
+	if ((i < 0) || (i >= IWL_RATE_COUNT))
+		i = 0;
+
+	rate = iwlegacy_rates[i].plcp;
+	tbl->ant_type = iwl4965_first_antenna(valid_tx_ant);
+	rate |= tbl->ant_type << RATE_MCS_ANT_POS;
+
+	if (i >= IWL_FIRST_CCK_RATE && i <= IWL_LAST_CCK_RATE)
+		rate |= RATE_MCS_CCK_MSK;
+
+	iwl4965_rs_get_tbl_info_from_mcs(rate, priv->band, tbl, &rate_idx);
+	if (!iwl4965_rs_is_valid_ant(valid_tx_ant, tbl->ant_type))
+		iwl4965_rs_toggle_antenna(valid_tx_ant, &rate, tbl);
+
+	rate = iwl4965_rate_n_flags_from_tbl(priv, tbl, rate_idx, use_green);
+	tbl->current_rate = rate;
+	iwl4965_rs_set_expected_tpt_table(lq_sta, tbl);
+	iwl4965_rs_fill_link_cmd(NULL, lq_sta, rate);
+	priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
+	iwl_legacy_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
+}
+
+static void
+iwl4965_rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
+			struct ieee80211_tx_rate_control *txrc)
+{
+
+	struct sk_buff *skb = txrc->skb;
+	struct ieee80211_supported_band *sband = txrc->sband;
+	struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	int rate_idx;
+
+	IWL_DEBUG_RATE_LIMIT(priv, "rate scale calculate new rate for skb\n");
+
+	/* Get max rate if user set max rate */
+	if (lq_sta) {
+		lq_sta->max_rate_idx = txrc->max_rate_idx;
+		if ((sband->band == IEEE80211_BAND_5GHZ) &&
+		    (lq_sta->max_rate_idx != -1))
+			lq_sta->max_rate_idx += IWL_FIRST_OFDM_RATE;
+		if ((lq_sta->max_rate_idx < 0) ||
+		    (lq_sta->max_rate_idx >= IWL_RATE_COUNT))
+			lq_sta->max_rate_idx = -1;
+	}
+
+	/* Treat uninitialized rate scaling data same as non-existing. */
+	if (lq_sta && !lq_sta->drv) {
+		IWL_DEBUG_RATE(priv, "Rate scaling not initialized yet.\n");
+		priv_sta = NULL;
+	}
+
+	/* Send management frames and NO_ACK data using lowest rate. */
+	if (rate_control_send_low(sta, priv_sta, txrc))
+		return;
+
+	rate_idx  = lq_sta->last_txrate_idx;
+
+	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 (iwl4965_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_HT40_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 {
+		/* Check for invalid rates */
+		if ((rate_idx < 0) || (rate_idx >= IWL_RATE_COUNT_LEGACY) ||
+				((sband->band == IEEE80211_BAND_5GHZ) &&
+				 (rate_idx < IWL_FIRST_OFDM_RATE)))
+			rate_idx = rate_lowest_index(sband, sta);
+		/* On valid 5 GHz rate, adjust index */
+		else if (sband->band == IEEE80211_BAND_5GHZ)
+			rate_idx -= IWL_FIRST_OFDM_RATE;
+		info->control.rates[0].flags = 0;
+	}
+	info->control.rates[0].idx = rate_idx;
+
+}
+
+static void *iwl4965_rs_alloc_sta(void *priv_rate, struct ieee80211_sta *sta,
+			  gfp_t gfp)
+{
+	struct iwl_lq_sta *lq_sta;
+	struct iwl_station_priv *sta_priv =
+				(struct iwl_station_priv *) sta->drv_priv;
+	struct iwl_priv *priv;
+
+	priv = (struct iwl_priv *)priv_rate;
+	IWL_DEBUG_RATE(priv, "create station rate scale window\n");
+
+	lq_sta = &sta_priv->lq_sta;
+
+	return lq_sta;
+}
+
+/*
+ * Called after adding a new station to initialize rate scaling
+ */
+void
+iwl4965_rs_rate_init(struct iwl_priv *priv,
+			struct ieee80211_sta *sta,
+			u8 sta_id)
+{
+	int i, j;
+	struct ieee80211_hw *hw = priv->hw;
+	struct ieee80211_conf *conf = &priv->hw->conf;
+	struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+	struct iwl_station_priv *sta_priv;
+	struct iwl_lq_sta *lq_sta;
+	struct ieee80211_supported_band *sband;
+
+	sta_priv = (struct iwl_station_priv *) sta->drv_priv;
+	lq_sta = &sta_priv->lq_sta;
+	sband = hw->wiphy->bands[conf->channel->band];
+
+
+	lq_sta->lq.sta_id = sta_id;
+
+	for (j = 0; j < LQ_SIZE; j++)
+		for (i = 0; i < IWL_RATE_COUNT; i++)
+			iwl4965_rs_rate_scale_clear_window(
+					&lq_sta->lq_info[j].win[i]);
+
+	lq_sta->flush_timer = 0;
+	lq_sta->supp_rates = sta->supp_rates[sband->band];
+	for (j = 0; j < LQ_SIZE; j++)
+		for (i = 0; i < IWL_RATE_COUNT; i++)
+			iwl4965_rs_rate_scale_clear_window(
+					&lq_sta->lq_info[j].win[i]);
+
+	IWL_DEBUG_RATE(priv, "LQ:"
+			"*** rate scale station global init for station %d ***\n",
+		       sta_id);
+	/* TODO: what is a good starting rate for STA? About middle? Maybe not
+	 * the lowest or the highest rate.. Could consider using RSSI from
+	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
+	 * after assoc.. */
+
+	lq_sta->is_dup = 0;
+	lq_sta->max_rate_idx = -1;
+	lq_sta->missed_rate_counter = IWL_MISSED_RATE_MAX;
+	lq_sta->is_green = iwl4965_rs_use_green(sta);
+	lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000);
+	lq_sta->band = priv->band;
+	/*
+	 * active_siso_rate mask includes 9 MBits (bit 5), and CCK (bits 0-3),
+	 * supp_rates[] does not; shift to convert format, force 9 MBits off.
+	 */
+	lq_sta->active_siso_rate = ht_cap->mcs.rx_mask[0] << 1;
+	lq_sta->active_siso_rate |= ht_cap->mcs.rx_mask[0] & 0x1;
+	lq_sta->active_siso_rate &= ~((u16)0x2);
+	lq_sta->active_siso_rate <<= IWL_FIRST_OFDM_RATE;
+
+	/* Same here */
+	lq_sta->active_mimo2_rate = ht_cap->mcs.rx_mask[1] << 1;
+	lq_sta->active_mimo2_rate |= ht_cap->mcs.rx_mask[1] & 0x1;
+	lq_sta->active_mimo2_rate &= ~((u16)0x2);
+	lq_sta->active_mimo2_rate <<= IWL_FIRST_OFDM_RATE;
+
+	/* These values will be overridden later */
+	lq_sta->lq.general_params.single_stream_ant_msk =
+		iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+	lq_sta->lq.general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+	if (!lq_sta->lq.general_params.dual_stream_ant_msk) {
+		lq_sta->lq.general_params.dual_stream_ant_msk = ANT_AB;
+	} else if (iwl4965_num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+		lq_sta->lq.general_params.dual_stream_ant_msk =
+			priv->hw_params.valid_tx_ant;
+	}
+
+	/* as default allow aggregation for all tids */
+	lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID;
+	lq_sta->drv = priv;
+
+	/* Set last_txrate_idx to lowest rate */
+	lq_sta->last_txrate_idx = rate_lowest_index(sband, sta);
+	if (sband->band == IEEE80211_BAND_5GHZ)
+		lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
+	lq_sta->is_agg = 0;
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+	lq_sta->dbg_fixed_rate = 0;
+#endif
+
+	iwl4965_rs_initialize_lq(priv, conf, sta, lq_sta);
+}
+
+static void iwl4965_rs_fill_link_cmd(struct iwl_priv *priv,
+			     struct iwl_lq_sta *lq_sta, u32 new_rate)
+{
+	struct iwl_scale_tbl_info tbl_type;
+	int index = 0;
+	int rate_idx;
+	int repeat_rate = 0;
+	u8 ant_toggle_cnt = 0;
+	u8 use_ht_possible = 1;
+	u8 valid_tx_ant = 0;
+	struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
+
+	/* Override starting rate (index 0) if needed for debug purposes */
+	iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+	/* Interpret new_rate (rate_n_flags) */
+	iwl4965_rs_get_tbl_info_from_mcs(new_rate, lq_sta->band,
+				  &tbl_type, &rate_idx);
+
+	/* How many times should we repeat the initial rate? */
+	if (is_legacy(tbl_type.lq_type)) {
+		ant_toggle_cnt = 1;
+		repeat_rate = IWL_NUMBER_TRY;
+	} else {
+		repeat_rate = IWL_HT_NUMBER_TRY;
+	}
+
+	lq_cmd->general_params.mimo_delimiter =
+			is_mimo(tbl_type.lq_type) ? 1 : 0;
+
+	/* Fill 1st table entry (index 0) */
+	lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
+
+	if (iwl4965_num_of_ant(tbl_type.ant_type) == 1) {
+		lq_cmd->general_params.single_stream_ant_msk =
+						tbl_type.ant_type;
+	} else if (iwl4965_num_of_ant(tbl_type.ant_type) == 2) {
+		lq_cmd->general_params.dual_stream_ant_msk =
+						tbl_type.ant_type;
+	} /* otherwise we don't modify the existing value */
+
+	index++;
+	repeat_rate--;
+	if (priv)
+		valid_tx_ant = priv->hw_params.valid_tx_ant;
+
+	/* Fill rest of rate table */
+	while (index < LINK_QUAL_MAX_RETRY_NUM) {
+		/* Repeat initial/next rate.
+		 * For legacy IWL_NUMBER_TRY == 1, this loop will not execute.
+		 * For HT IWL_HT_NUMBER_TRY == 3, this executes twice. */
+		while (repeat_rate > 0 && (index < LINK_QUAL_MAX_RETRY_NUM)) {
+			if (is_legacy(tbl_type.lq_type)) {
+				if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+					ant_toggle_cnt++;
+				else if (priv &&
+					 iwl4965_rs_toggle_antenna(valid_tx_ant,
+							&new_rate, &tbl_type))
+					ant_toggle_cnt = 1;
+			}
+
+			/* Override next rate if needed for debug purposes */
+			iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+			/* Fill next table entry */
+			lq_cmd->rs_table[index].rate_n_flags =
+					cpu_to_le32(new_rate);
+			repeat_rate--;
+			index++;
+		}
+
+		iwl4965_rs_get_tbl_info_from_mcs(new_rate,
+						lq_sta->band, &tbl_type,
+						&rate_idx);
+
+		/* Indicate to uCode which entries might be MIMO.
+		 * If initial rate was MIMO, this will finally end up
+		 * as (IWL_HT_NUMBER_TRY * 2), after 2nd pass, otherwise 0. */
+		if (is_mimo(tbl_type.lq_type))
+			lq_cmd->general_params.mimo_delimiter = index;
+
+		/* Get next rate */
+		new_rate = iwl4965_rs_get_lower_rate(lq_sta,
+					&tbl_type, rate_idx,
+					     use_ht_possible);
+
+		/* How many times should we repeat the next rate? */
+		if (is_legacy(tbl_type.lq_type)) {
+			if (ant_toggle_cnt < NUM_TRY_BEFORE_ANT_TOGGLE)
+				ant_toggle_cnt++;
+			else if (priv &&
+				 iwl4965_rs_toggle_antenna(valid_tx_ant,
+						   &new_rate, &tbl_type))
+				ant_toggle_cnt = 1;
+
+			repeat_rate = IWL_NUMBER_TRY;
+		} else {
+			repeat_rate = IWL_HT_NUMBER_TRY;
+		}
+
+		/* Don't allow HT rates after next pass.
+		 * iwl4965_rs_get_lower_rate() will change type to LQ_A or LQ_G. */
+		use_ht_possible = 0;
+
+		/* Override next rate if needed for debug purposes */
+		iwl4965_rs_dbgfs_set_mcs(lq_sta, &new_rate, index);
+
+		/* Fill next table entry */
+		lq_cmd->rs_table[index].rate_n_flags = cpu_to_le32(new_rate);
+
+		index++;
+		repeat_rate--;
+	}
+
+	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+	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
+*iwl4965_rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
+{
+	return hw->priv;
+}
+/* rate scale requires free function to be implemented */
+static void iwl4965_rs_free(void *priv_rate)
+{
+	return;
+}
+
+static void iwl4965_rs_free_sta(void *priv_r, struct ieee80211_sta *sta,
+			void *priv_sta)
+{
+	struct iwl_priv *priv __maybe_unused = priv_r;
+
+	IWL_DEBUG_RATE(priv, "enter\n");
+	IWL_DEBUG_RATE(priv, "leave\n");
+}
+
+
+#ifdef CONFIG_MAC80211_DEBUGFS
+static int iwl4965_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+static void iwl4965_rs_dbgfs_set_mcs(struct iwl_lq_sta *lq_sta,
+			     u32 *rate_n_flags, int index)
+{
+	struct iwl_priv *priv;
+	u8 valid_tx_ant;
+	u8 ant_sel_tx;
+
+	priv = lq_sta->drv;
+	valid_tx_ant = priv->hw_params.valid_tx_ant;
+	if (lq_sta->dbg_fixed_rate) {
+		ant_sel_tx =
+		  ((lq_sta->dbg_fixed_rate & RATE_MCS_ANT_ABC_MSK)
+		  >> RATE_MCS_ANT_POS);
+		if ((valid_tx_ant & ant_sel_tx) == ant_sel_tx) {
+			*rate_n_flags = lq_sta->dbg_fixed_rate;
+			IWL_DEBUG_RATE(priv, "Fixed rate ON\n");
+		} else {
+			lq_sta->dbg_fixed_rate = 0;
+			IWL_ERR(priv,
+			    "Invalid antenna selection 0x%X, Valid is 0x%X\n",
+			    ant_sel_tx, valid_tx_ant);
+			IWL_DEBUG_RATE(priv, "Fixed rate OFF\n");
+		}
+	} else {
+		IWL_DEBUG_RATE(priv, "Fixed rate OFF\n");
+	}
+}
+
+static ssize_t iwl4965_rs_sta_dbgfs_scale_table_write(struct file *file,
+			const char __user *user_buf, size_t count, loff_t *ppos)
+{
+	struct iwl_lq_sta *lq_sta = file->private_data;
+	struct iwl_priv *priv;
+	char buf[64];
+	int buf_size;
+	u32 parsed_rate;
+	struct iwl_station_priv *sta_priv =
+		container_of(lq_sta, struct iwl_station_priv, lq_sta);
+	struct iwl_rxon_context *ctx = sta_priv->common.ctx;
+
+	priv = lq_sta->drv;
+	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", &parsed_rate) == 1)
+		lq_sta->dbg_fixed_rate = parsed_rate;
+	else
+		lq_sta->dbg_fixed_rate = 0;
+
+	lq_sta->active_legacy_rate = 0x0FFF;	/* 1 - 54 MBits, includes CCK */
+	lq_sta->active_siso_rate   = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
+	lq_sta->active_mimo2_rate  = 0x1FD0;	/* 6 - 60 MBits, no 9, no CCK */
+
+	IWL_DEBUG_RATE(priv, "sta_id %d rate 0x%X\n",
+		lq_sta->lq.sta_id, lq_sta->dbg_fixed_rate);
+
+	if (lq_sta->dbg_fixed_rate) {
+		iwl4965_rs_fill_link_cmd(NULL, lq_sta, lq_sta->dbg_fixed_rate);
+		iwl_legacy_send_lq_cmd(lq_sta->drv, ctx, &lq_sta->lq, CMD_ASYNC,
+				false);
+	}
+
+	return count;
+}
+
+static ssize_t iwl4965_rs_sta_dbgfs_scale_table_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char *buff;
+	int desc = 0;
+	int i = 0;
+	int index = 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;
+	buff = kmalloc(1024, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	desc += sprintf(buff+desc, "sta_id %d\n", lq_sta->lq.sta_id);
+	desc += sprintf(buff+desc, "failed=%d success=%d rate=0%X\n",
+			lq_sta->total_failed, lq_sta->total_success,
+			lq_sta->active_legacy_rate);
+	desc += sprintf(buff+desc, "fixed rate 0x%X\n",
+			lq_sta->dbg_fixed_rate);
+	desc += sprintf(buff+desc, "valid_tx_ant %s%s%s\n",
+	    (priv->hw_params.valid_tx_ant & ANT_A) ? "ANT_A," : "",
+	    (priv->hw_params.valid_tx_ant & ANT_B) ? "ANT_B," : "",
+	    (priv->hw_params.valid_tx_ant & ANT_C) ? "ANT_C" : "");
+	desc += sprintf(buff+desc, "lq type %s\n",
+	   (is_legacy(tbl->lq_type)) ? "legacy" : "HT");
+	if (is_Ht(tbl->lq_type)) {
+		desc += sprintf(buff+desc, " %s",
+		   (is_siso(tbl->lq_type)) ? "SISO" : "MIMO2");
+		   desc += sprintf(buff+desc, " %s",
+		   (tbl->is_ht40) ? "40MHz" : "20MHz");
+		   desc += sprintf(buff+desc, " %s %s %s\n",
+			(tbl->is_SGI) ? "SGI" : "",
+		   (lq_sta->is_green) ? "GF enabled" : "",
+		   (lq_sta->is_agg) ? "AGG on" : "");
+	}
+	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,
+		lq_sta->lq.general_params.mimo_delimiter,
+		lq_sta->lq.general_params.single_stream_ant_msk,
+		lq_sta->lq.general_params.dual_stream_ant_msk);
+
+	desc += sprintf(buff+desc, "agg:"
+			"time_limit=%d dist_start_th=%d frame_cnt_limit=%d\n",
+			le16_to_cpu(lq_sta->lq.agg_params.agg_time_limit),
+			lq_sta->lq.agg_params.agg_dis_start_th,
+			lq_sta->lq.agg_params.agg_frame_cnt_limit);
+
+	desc += sprintf(buff+desc,
+			"Start idx [0]=0x%x [1]=0x%x [2]=0x%x [3]=0x%x\n",
+			lq_sta->lq.general_params.start_rate_index[0],
+			lq_sta->lq.general_params.start_rate_index[1],
+			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++) {
+		index = iwl4965_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);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_scale_table_ops = {
+	.write = iwl4965_rs_sta_dbgfs_scale_table_write,
+	.read = iwl4965_rs_sta_dbgfs_scale_table_read,
+	.open = iwl4965_open_file_generic,
+	.llseek = default_llseek,
+};
+static ssize_t iwl4965_rs_sta_dbgfs_stats_table_read(struct file *file,
+			char __user *user_buf, size_t count, loff_t *ppos)
+{
+	char *buff;
+	int desc = 0;
+	int i, j;
+	ssize_t ret;
+
+	struct iwl_lq_sta *lq_sta = file->private_data;
+
+	buff = kmalloc(1024, GFP_KERNEL);
+	if (!buff)
+		return -ENOMEM;
+
+	for (i = 0; i < LQ_SIZE; i++) {
+		desc += sprintf(buff+desc,
+				"%s type=%d SGI=%d HT40=%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_ht40,
+				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,
+				"counter=%d success=%d %%=%d\n",
+				lq_sta->lq_info[i].win[j].counter,
+				lq_sta->lq_info[i].win[j].success_counter,
+				lq_sta->lq_info[i].win[j].success_ratio);
+		}
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
+	kfree(buff);
+	return ret;
+}
+
+static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
+	.read = iwl4965_rs_sta_dbgfs_stats_table_read,
+	.open = iwl4965_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static ssize_t iwl4965_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",
+				iwlegacy_rates[lq_sta->last_txrate_idx].ieee >> 1);
+
+	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 = iwl4965_rs_sta_dbgfs_rate_scale_data_read,
+	.open = iwl4965_open_file_generic,
+	.llseek = default_llseek,
+};
+
+static void iwl4965_rs_add_debugfs(void *priv, void *priv_sta,
+					struct dentry *dir)
+{
+	struct iwl_lq_sta *lq_sta = priv_sta;
+	lq_sta->rs_sta_dbgfs_scale_table_file =
+		debugfs_create_file("rate_scale_table", S_IRUSR | S_IWUSR, dir,
+				lq_sta, &rs_sta_dbgfs_scale_table_ops);
+	lq_sta->rs_sta_dbgfs_stats_table_file =
+		debugfs_create_file("rate_stats_table", S_IRUSR, dir,
+			lq_sta, &rs_sta_dbgfs_stats_table_ops);
+	lq_sta->rs_sta_dbgfs_rate_scale_data_file =
+		debugfs_create_file("rate_scale_data", S_IRUSR, 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", S_IRUSR | S_IWUSR, dir,
+		&lq_sta->tx_agg_tid_en);
+
+}
+
+static void iwl4965_rs_remove_debugfs(void *priv, void *priv_sta)
+{
+	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
+
+/*
+ * Initialization of rate scaling information is done by driver after
+ * the station is added. Since mac80211 calls this function before a
+ * station is added we ignore it.
+ */
+static void
+iwl4965_rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
+			 struct ieee80211_sta *sta, void *priv_sta)
+{
+}
+static struct rate_control_ops rs_4965_ops = {
+	.module = NULL,
+	.name = IWL4965_RS_NAME,
+	.tx_status = iwl4965_rs_tx_status,
+	.get_rate = iwl4965_rs_get_rate,
+	.rate_init = iwl4965_rs_rate_init_stub,
+	.alloc = iwl4965_rs_alloc,
+	.free = iwl4965_rs_free,
+	.alloc_sta = iwl4965_rs_alloc_sta,
+	.free_sta = iwl4965_rs_free_sta,
+#ifdef CONFIG_MAC80211_DEBUGFS
+	.add_sta_debugfs = iwl4965_rs_add_debugfs,
+	.remove_sta_debugfs = iwl4965_rs_remove_debugfs,
+#endif
+};
+
+int iwl4965_rate_control_register(void)
+{
+	pr_err("Registering 4965 rate control operations\n");
+	return ieee80211_rate_control_register(&rs_4965_ops);
+}
+
+void iwl4965_rate_control_unregister(void)
+{
+	ieee80211_rate_control_unregister(&rs_4965_ops);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,291 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * 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 <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-4965-calib.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+
+void iwl4965_rx_missed_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_missed_beacon_notif *missed_beacon;
+
+	missed_beacon = &pkt->u.missed_beacon;
+	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+	    priv->missed_beacon_threshold) {
+		IWL_DEBUG_CALIB(priv,
+		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+		    le32_to_cpu(missed_beacon->total_missed_becons),
+		    le32_to_cpu(missed_beacon->num_recvd_beacons),
+		    le32_to_cpu(missed_beacon->num_expected_beacons));
+		if (!test_bit(STATUS_SCANNING, &priv->status))
+			iwl4965_init_sensitivity(priv);
+	}
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void iwl4965_rx_calc_noise(struct iwl_priv *priv)
+{
+	struct statistics_rx_non_phy *rx_info;
+	int num_active_rx = 0;
+	int total_silence = 0;
+	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
+	int last_rx_noise;
+
+	rx_info = &(priv->_4965.statistics.rx.general);
+	bcn_silence_a =
+		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+	bcn_silence_b =
+		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+	bcn_silence_c =
+		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+
+	if (bcn_silence_a) {
+		total_silence += bcn_silence_a;
+		num_active_rx++;
+	}
+	if (bcn_silence_b) {
+		total_silence += bcn_silence_b;
+		num_active_rx++;
+	}
+	if (bcn_silence_c) {
+		total_silence += bcn_silence_c;
+		num_active_rx++;
+	}
+
+	/* Average among active antennas */
+	if (num_active_rx)
+		last_rx_noise = (total_silence / num_active_rx) - 107;
+	else
+		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
+			bcn_silence_a, bcn_silence_b, bcn_silence_c,
+			last_rx_noise);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+/*
+ *  based on the assumption of all statistics counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void iwl4965_accumulative_statistics(struct iwl_priv *priv,
+					__le32 *stats)
+{
+	int i, size;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+	struct statistics_general_common *general, *accum_general;
+	struct statistics_tx *tx, *accum_tx;
+
+	prev_stats = (__le32 *)&priv->_4965.statistics;
+	accum_stats = (u32 *)&priv->_4965.accum_statistics;
+	size = sizeof(struct iwl_notif_statistics);
+	general = &priv->_4965.statistics.general.common;
+	accum_general = &priv->_4965.accum_statistics.general.common;
+	tx = &priv->_4965.statistics.tx;
+	accum_tx = &priv->_4965.accum_statistics.tx;
+	delta = (u32 *)&priv->_4965.delta_statistics;
+	max_delta = (u32 *)&priv->_4965.max_delta;
+
+	for (i = sizeof(__le32); i < size;
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
+		}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	accum_general->temperature = general->temperature;
+	accum_general->ttl_timestamp = general->ttl_timestamp;
+}
+#endif
+
+#define REG_RECALIB_PERIOD (60)
+
+/**
+ * iwl4965_good_plcp_health - checks for plcp error.
+ *
+ * When the plcp error is exceeding the thresholds, reset the radio
+ * to improve the throughput.
+ */
+bool iwl4965_good_plcp_health(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt)
+{
+	bool rc = true;
+	int combined_plcp_delta;
+	unsigned int plcp_msec;
+	unsigned long plcp_received_jiffies;
+
+	if (priv->cfg->base_params->plcp_delta_threshold ==
+	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
+		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
+		return rc;
+	}
+
+	/*
+	 * check for plcp_err and trigger radio reset if it exceeds
+	 * the plcp error threshold plcp_delta.
+	 */
+	plcp_received_jiffies = jiffies;
+	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
+					(long) priv->plcp_jiffies);
+	priv->plcp_jiffies = plcp_received_jiffies;
+	/*
+	 * check to make sure plcp_msec is not 0 to prevent division
+	 * by zero.
+	 */
+	if (plcp_msec) {
+		struct statistics_rx_phy *ofdm;
+		struct statistics_rx_ht_phy *ofdm_ht;
+
+		ofdm = &pkt->u.stats.rx.ofdm;
+		ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
+		combined_plcp_delta =
+		    (le32_to_cpu(ofdm->plcp_err) -
+		    le32_to_cpu(priv->_4965.statistics.
+				rx.ofdm.plcp_err)) +
+		    (le32_to_cpu(ofdm_ht->plcp_err) -
+		    le32_to_cpu(priv->_4965.statistics.
+				rx.ofdm_ht.plcp_err));
+
+		if ((combined_plcp_delta > 0) &&
+		    ((combined_plcp_delta * 100) / plcp_msec) >
+			priv->cfg->base_params->plcp_delta_threshold) {
+			/*
+			 * if plcp_err exceed the threshold,
+			 * the following data is printed in csv format:
+			 *    Text: plcp_err exceeded %d,
+			 *    Received ofdm.plcp_err,
+			 *    Current ofdm.plcp_err,
+			 *    Received ofdm_ht.plcp_err,
+			 *    Current ofdm_ht.plcp_err,
+			 *    combined_plcp_delta,
+			 *    plcp_msec
+			 */
+			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
+				"%u, %u, %u, %u, %d, %u mSecs\n",
+				priv->cfg->base_params->plcp_delta_threshold,
+				le32_to_cpu(ofdm->plcp_err),
+				le32_to_cpu(ofdm->plcp_err),
+				le32_to_cpu(ofdm_ht->plcp_err),
+				le32_to_cpu(ofdm_ht->plcp_err),
+				combined_plcp_delta, plcp_msec);
+
+			rc = false;
+		}
+	}
+	return rc;
+}
+
+void iwl4965_rx_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	int change;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	IWL_DEBUG_RX(priv,
+		     "Statistics notification received (%d vs %d).\n",
+		     (int)sizeof(struct iwl_notif_statistics),
+		     le32_to_cpu(pkt->len_n_flags) &
+		     FH_RSCSR_FRAME_SIZE_MSK);
+
+	change = ((priv->_4965.statistics.general.common.temperature !=
+		   pkt->u.stats.general.common.temperature) ||
+		   ((priv->_4965.statistics.flag &
+		   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+		   (pkt->u.stats.flag &
+		   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	iwl4965_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+#endif
+
+	iwl_legacy_recover_from_statistics(priv, pkt);
+
+	memcpy(&priv->_4965.statistics, &pkt->u.stats,
+		sizeof(priv->_4965.statistics));
+
+	set_bit(STATUS_STATISTICS, &priv->status);
+
+	/* Reschedule the statistics timer to occur in
+	 * REG_RECALIB_PERIOD seconds to ensure we get a
+	 * thermal update even if the uCode doesn't give
+	 * us one */
+	mod_timer(&priv->statistics_periodic, jiffies +
+		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
+
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+		iwl4965_rx_calc_noise(priv);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
+	}
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
+}
+
+void iwl4965_reply_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+		memset(&priv->_4965.accum_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_4965.delta_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_4965.max_delta, 0,
+			sizeof(struct iwl_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl4965_rx_statistics(priv, rxb);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-sta.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-sta.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-sta.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-sta.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,721 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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 <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-4965.h"
+
+static struct iwl_link_quality_cmd *
+iwl4965_sta_alloc_lq(struct iwl_priv *priv, u8 sta_id)
+{
+	int i, r;
+	struct iwl_link_quality_cmd *link_cmd;
+	u32 rate_flags = 0;
+	__le32 rate_n_flags;
+
+	link_cmd = kzalloc(sizeof(struct iwl_link_quality_cmd), GFP_KERNEL);
+	if (!link_cmd) {
+		IWL_ERR(priv, "Unable to allocate memory for LQ cmd.\n");
+		return NULL;
+	}
+	/* Set up the rate scaling to start at selected rate, fall back
+	 * all the way down to 1M in IEEE order, and then spin on 1M */
+	if (priv->band == IEEE80211_BAND_5GHZ)
+		r = IWL_RATE_6M_INDEX;
+	else
+		r = IWL_RATE_1M_INDEX;
+
+	if (r >= IWL_FIRST_CCK_RATE && r <= IWL_LAST_CCK_RATE)
+		rate_flags |= RATE_MCS_CCK_MSK;
+
+	rate_flags |= iwl4965_first_antenna(priv->hw_params.valid_tx_ant) <<
+				RATE_MCS_ANT_POS;
+	rate_n_flags = iwl4965_hw_set_rate_n_flags(iwlegacy_rates[r].plcp,
+						   rate_flags);
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+		link_cmd->rs_table[i].rate_n_flags = rate_n_flags;
+
+	link_cmd->general_params.single_stream_ant_msk =
+				iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+
+	link_cmd->general_params.dual_stream_ant_msk =
+		priv->hw_params.valid_tx_ant &
+		~iwl4965_first_antenna(priv->hw_params.valid_tx_ant);
+	if (!link_cmd->general_params.dual_stream_ant_msk) {
+		link_cmd->general_params.dual_stream_ant_msk = ANT_AB;
+	} else if (iwl4965_num_of_ant(priv->hw_params.valid_tx_ant) == 2) {
+		link_cmd->general_params.dual_stream_ant_msk =
+			priv->hw_params.valid_tx_ant;
+	}
+
+	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);
+
+	link_cmd->sta_id = sta_id;
+
+	return link_cmd;
+}
+
+/*
+ * iwl4965_add_bssid_station - Add the special IBSS BSSID station
+ *
+ * Function sleeps.
+ */
+int
+iwl4965_add_bssid_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			     const u8 *addr, u8 *sta_id_r)
+{
+	int ret;
+	u8 sta_id;
+	struct iwl_link_quality_cmd *link_cmd;
+	unsigned long flags;
+
+	if (sta_id_r)
+		*sta_id_r = IWL_INVALID_STATION;
+
+	ret = iwl_legacy_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
+	if (ret) {
+		IWL_ERR(priv, "Unable to add station %pM\n", addr);
+		return ret;
+	}
+
+	if (sta_id_r)
+		*sta_id_r = sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].used |= IWL_STA_LOCAL;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	/* Set up default rate scaling table in device's station table */
+	link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv,
+			"Unable to initialize rate scaling for station %pM.\n",
+			addr);
+		return -ENOMEM;
+	}
+
+	ret = iwl_legacy_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
+	if (ret)
+		IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+static int iwl4965_static_wepkey_cmd(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx,
+				      bool send_if_empty)
+{
+	int i, not_empty = 0;
+	u8 buff[sizeof(struct iwl_wep_cmd) +
+		sizeof(struct iwl_wep_key) * WEP_KEYS_MAX];
+	struct iwl_wep_cmd *wep_cmd = (struct iwl_wep_cmd *)buff;
+	size_t cmd_size  = sizeof(struct iwl_wep_cmd);
+	struct iwl_host_cmd cmd = {
+		.id = ctx->wep_key_cmd,
+		.data = wep_cmd,
+		.flags = CMD_SYNC,
+	};
+
+	might_sleep();
+
+	memset(wep_cmd, 0, cmd_size +
+			(sizeof(struct iwl_wep_key) * WEP_KEYS_MAX));
+
+	for (i = 0; i < WEP_KEYS_MAX ; i++) {
+		wep_cmd->key[i].key_index = i;
+		if (ctx->wep_keys[i].key_size) {
+			wep_cmd->key[i].key_offset = i;
+			not_empty = 1;
+		} else {
+			wep_cmd->key[i].key_offset = WEP_INVALID_OFFSET;
+		}
+
+		wep_cmd->key[i].key_size = ctx->wep_keys[i].key_size;
+		memcpy(&wep_cmd->key[i].key[3], ctx->wep_keys[i].key,
+				ctx->wep_keys[i].key_size);
+	}
+
+	wep_cmd->global_key_type = WEP_KEY_WEP_TYPE;
+	wep_cmd->num_keys = WEP_KEYS_MAX;
+
+	cmd_size += sizeof(struct iwl_wep_key) * WEP_KEYS_MAX;
+
+	cmd.len = cmd_size;
+
+	if (not_empty || send_if_empty)
+		return iwl_legacy_send_cmd(priv, &cmd);
+	else
+		return 0;
+}
+
+int iwl4965_restore_default_wep_keys(struct iwl_priv *priv,
+				 struct iwl_rxon_context *ctx)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	return iwl4965_static_wepkey_cmd(priv, ctx, false);
+}
+
+int iwl4965_remove_default_wep_key(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx,
+			       struct ieee80211_key_conf *keyconf)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	IWL_DEBUG_WEP(priv, "Removing default WEP key: idx=%d\n",
+		      keyconf->keyidx);
+
+	memset(&ctx->wep_keys[keyconf->keyidx], 0, sizeof(ctx->wep_keys[0]));
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_WEP(priv,
+		"Not sending REPLY_WEPKEY command due to RFKILL.\n");
+		/* but keys in device are clear anyway so return success */
+		return 0;
+	}
+	ret = iwl4965_static_wepkey_cmd(priv, ctx, 1);
+	IWL_DEBUG_WEP(priv, "Remove default WEP key: idx=%d ret=%d\n",
+		      keyconf->keyidx, ret);
+
+	return ret;
+}
+
+int iwl4965_set_default_wep_key(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_key_conf *keyconf)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (keyconf->keylen != WEP_KEY_LEN_128 &&
+	    keyconf->keylen != WEP_KEY_LEN_64) {
+		IWL_DEBUG_WEP(priv, "Bad WEP key length %d\n", keyconf->keylen);
+		return -EINVAL;
+	}
+
+	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+	keyconf->hw_key_idx = HW_KEY_DEFAULT;
+	priv->stations[ctx->ap_sta_id].keyinfo.cipher = keyconf->cipher;
+
+	ctx->wep_keys[keyconf->keyidx].key_size = keyconf->keylen;
+	memcpy(&ctx->wep_keys[keyconf->keyidx].key, &keyconf->key,
+							keyconf->keylen);
+
+	ret = iwl4965_static_wepkey_cmd(priv, ctx, false);
+	IWL_DEBUG_WEP(priv, "Set default WEP key: len=%d idx=%d ret=%d\n",
+		keyconf->keylen, keyconf->keyidx, ret);
+
+	return ret;
+}
+
+static int iwl4965_set_wep_dynamic_key_info(struct iwl_priv *priv,
+					struct iwl_rxon_context *ctx,
+					struct ieee80211_key_conf *keyconf,
+					u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	keyconf->flags &= ~IEEE80211_KEY_FLAG_GENERATE_IV;
+
+	key_flags |= (STA_KEY_FLG_WEP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (keyconf->keylen == WEP_KEY_LEN_128)
+		key_flags |= STA_KEY_FLG_KEY_SIZE_MSK;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+	priv->stations[sta_id].keyinfo.keyidx = keyconf->keyidx;
+
+	memcpy(priv->stations[sta_id].keyinfo.key,
+				keyconf->key, keyconf->keylen);
+
+	memcpy(&priv->stations[sta_id].sta.key.key[3],
+				keyconf->key, keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	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;
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+			sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl4965_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
+					 struct iwl_rxon_context *ctx,
+					 struct ieee80211_key_conf *keyconf,
+					 u8 sta_id)
+{
+	unsigned long flags;
+	__le16 key_flags = 0;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
+
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
+	       keyconf->keylen);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
+	       keyconf->keylen);
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	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;
+
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+			 sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+static int iwl4965_set_tkip_dynamic_key_info(struct iwl_priv *priv,
+					 struct iwl_rxon_context *ctx,
+					 struct ieee80211_key_conf *keyconf,
+					 u8 sta_id)
+{
+	unsigned long flags;
+	int ret = 0;
+	__le16 key_flags = 0;
+
+	key_flags |= (STA_KEY_FLG_TKIP | STA_KEY_FLG_MAP_KEY_MSK);
+	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
+	key_flags &= ~STA_KEY_FLG_INVALID;
+
+	if (sta_id == ctx->bcast_sta_id)
+		key_flags |= STA_KEY_MULTICAST_MSK;
+
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
+	priv->stations[sta_id].keyinfo.keylen = 16;
+
+	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
+			== STA_KEY_FLG_NO_ENC)
+		priv->stations[sta_id].sta.key.key_offset =
+				 iwl_legacy_get_free_ucode_key_index(priv);
+	/* else, we are overriding an existing key => no need to allocated room
+	 * in uCode. */
+
+	WARN(priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
+		"no space for a new key");
+
+	priv->stations[sta_id].sta.key.key_flags = key_flags;
+
+
+	/* This copy is acutally not needed: we get the key with each TX */
+	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key, 16);
+
+	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key, 16);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
+}
+
+void iwl4965_update_tkip_key(struct iwl_priv *priv,
+			 struct iwl_rxon_context *ctx,
+			 struct ieee80211_key_conf *keyconf,
+			 struct ieee80211_sta *sta, u32 iv32, u16 *phase1key)
+{
+	u8 sta_id;
+	unsigned long flags;
+	int i;
+
+	if (iwl_legacy_scan_cancel(priv)) {
+		/* cancel scan failed, just live w/ bad key and rely
+		   briefly on SW decryption */
+		return;
+	}
+
+	sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	priv->stations[sta_id].sta.key.tkip_rx_tsc_byte2 = (u8) iv32;
+
+	for (i = 0; i < 5; i++)
+		priv->stations[sta_id].sta.key.tkip_rx_ttak[i] =
+			cpu_to_le16(phase1key[i]);
+
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	iwl_legacy_send_add_sta(priv, &priv->stations[sta_id].sta, CMD_ASYNC);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
+
+int iwl4965_remove_dynamic_key(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx,
+			   struct ieee80211_key_conf *keyconf,
+			   u8 sta_id)
+{
+	unsigned long flags;
+	u16 key_flags;
+	u8 keyidx;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	ctx->key_mapping_keys--;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	key_flags = le16_to_cpu(priv->stations[sta_id].sta.key.key_flags);
+	keyidx = (key_flags >> STA_KEY_FLG_KEYID_POS) & 0x3;
+
+	IWL_DEBUG_WEP(priv, "Remove dynamic key: idx=%d sta=%d\n",
+		      keyconf->keyidx, sta_id);
+
+	if (keyconf->keyidx != keyidx) {
+		/* We need to remove a key with index different that the one
+		 * in the uCode. This means that the key we need to remove has
+		 * been replaced by another one with different index.
+		 * Don't do anything and return ok
+		 */
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+
+	if (priv->stations[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET) {
+		IWL_WARN(priv, "Removing wrong key %d 0x%x\n",
+			    keyconf->keyidx, key_flags);
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+
+	if (!test_and_clear_bit(priv->stations[sta_id].sta.key.key_offset,
+		&priv->ucode_key_table))
+		IWL_ERR(priv, "index %d not used in uCode key table.\n",
+			priv->stations[sta_id].sta.key.key_offset);
+	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[sta_id].sta.key.key_flags =
+			STA_KEY_FLG_NO_ENC | STA_KEY_FLG_INVALID;
+	priv->stations[sta_id].sta.key.key_offset = WEP_INVALID_OFFSET;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_KEY_MASK;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+
+	if (iwl_legacy_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;
+	}
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+			sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl4965_set_dynamic_key(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+			struct ieee80211_key_conf *keyconf, u8 sta_id)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	ctx->key_mapping_keys++;
+	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
+
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		ret = iwl4965_set_ccmp_dynamic_key_info(priv, ctx,
+							keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		ret = iwl4965_set_tkip_dynamic_key_info(priv, ctx,
+							keyconf, sta_id);
+		break;
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		ret = iwl4965_set_wep_dynamic_key_info(priv, ctx,
+							keyconf, sta_id);
+		break;
+	default:
+		IWL_ERR(priv,
+			"Unknown alg: %s cipher = %x\n", __func__,
+			keyconf->cipher);
+		ret = -EINVAL;
+	}
+
+	IWL_DEBUG_WEP(priv,
+		"Set dynamic key: cipher=%x len=%d idx=%d sta=%d ret=%d\n",
+		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
+		      sta_id, ret);
+
+	return ret;
+}
+
+/**
+ * iwl4965_alloc_bcast_station - add broadcast station into driver's station table.
+ *
+ * This adds the broadcast station into the driver's station table
+ * and marks it driver active, so that it will be restored to the
+ * device at the next best time.
+ */
+int iwl4965_alloc_bcast_station(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx)
+{
+	struct iwl_link_quality_cmd *link_cmd;
+	unsigned long flags;
+	u8 sta_id;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	sta_id = iwl_legacy_prep_station(priv, ctx, iwlegacy_bcast_addr,
+								false, NULL);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Unable to prepare broadcast station\n");
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+		return -EINVAL;
+	}
+
+	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
+	priv->stations[sta_id].used |= IWL_STA_BCAST;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv,
+			"Unable to initialize rate scaling for bcast station.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+/**
+ * iwl4965_update_bcast_station - update broadcast station's LQ command
+ *
+ * Only used by iwl4965. Placed here to have all bcast station management
+ * code together.
+ */
+static int iwl4965_update_bcast_station(struct iwl_priv *priv,
+				    struct iwl_rxon_context *ctx)
+{
+	unsigned long flags;
+	struct iwl_link_quality_cmd *link_cmd;
+	u8 sta_id = ctx->bcast_sta_id;
+
+	link_cmd = iwl4965_sta_alloc_lq(priv, sta_id);
+	if (!link_cmd) {
+		IWL_ERR(priv,
+		"Unable to initialize rate scaling for bcast station.\n");
+		return -ENOMEM;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	if (priv->stations[sta_id].lq)
+		kfree(priv->stations[sta_id].lq);
+	else
+		IWL_DEBUG_INFO(priv,
+		"Bcast station rate scaling has not been initialized yet.\n");
+	priv->stations[sta_id].lq = link_cmd;
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return 0;
+}
+
+int iwl4965_update_bcast_stations(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx;
+	int ret = 0;
+
+	for_each_context(priv, ctx) {
+		ret = iwl4965_update_bcast_station(priv, ctx);
+		if (ret)
+			break;
+	}
+
+	return ret;
+}
+
+/**
+ * iwl4965_sta_tx_modify_enable_tid - Enable Tx for this TID in station table
+ */
+int iwl4965_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
+{
+	unsigned long flags;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/* Remove "disable" flag, to enable Tx for this TID */
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_TID_DISABLE_TX;
+	priv->stations[sta_id].sta.tid_disable_tx &= cpu_to_le16(~(1 << tid));
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+					sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl4965_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			 int tid, u16 ssn)
+{
+	unsigned long flags;
+	int sta_id;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	sta_id = iwl_legacy_sta_id(sta);
+	if (sta_id == IWL_INVALID_STATION)
+		return -ENXIO;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.station_flags_msk = 0;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_ADDBA_TID_MSK;
+	priv->stations[sta_id].sta.add_immediate_ba_tid = (u8)tid;
+	priv->stations[sta_id].sta.add_immediate_ba_ssn = cpu_to_le16(ssn);
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+					sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+int iwl4965_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
+			int tid)
+{
+	unsigned long flags;
+	int sta_id;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	lockdep_assert_held(&priv->mutex);
+
+	sta_id = iwl_legacy_sta_id(sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
+		return -ENXIO;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.station_flags_msk = 0;
+	priv->stations[sta_id].sta.sta.modify_mask = STA_MODIFY_DELBA_TID_MSK;
+	priv->stations[sta_id].sta.remove_immediate_ba_tid = (u8)tid;
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+				sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+}
+
+void
+iwl4965_sta_modify_sleep_tx_count(struct iwl_priv *priv, int sta_id, int cnt)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	priv->stations[sta_id].sta.station_flags |= STA_FLG_PWR_SAVE_MSK;
+	priv->stations[sta_id].sta.station_flags_msk = STA_FLG_PWR_SAVE_MSK;
+	priv->stations[sta_id].sta.sta.modify_mask =
+					STA_MODIFY_SLEEP_TX_COUNT_MSK;
+	priv->stations[sta_id].sta.sleep_tx_count = cpu_to_le16(cnt);
+	priv->stations[sta_id].sta.mode = STA_CONTROL_MODIFY_MSK;
+	iwl_legacy_send_add_sta(priv,
+				&priv->stations[sta_id].sta, CMD_ASYNC);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-tx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1379 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * 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 <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+
+/*
+ * mac80211 queues, ACs, hardware queues, FIFOs.
+ *
+ * Cf. http://wireless.kernel.org/en/developers/Documentation/mac80211/queues
+ *
+ * Mac80211 uses the following numbers, which we get as from it
+ * by way of skb_get_queue_mapping(skb):
+ *
+ *	VO	0
+ *	VI	1
+ *	BE	2
+ *	BK	3
+ *
+ *
+ * Regular (not A-MPDU) frames are put into hardware queues corresponding
+ * to the FIFOs, see comments in iwl-prph.h. Aggregated frames get their
+ * own queue per aggregation session (RA/TID combination), such queues are
+ * set up to map into FIFOs too, for which we need an AC->FIFO mapping. In
+ * order to map frames to the right queue, we also need an AC->hw queue
+ * mapping. This is implemented here.
+ *
+ * Due to the way hw queues are set up (by the hw specific modules like
+ * iwl-4965.c), the AC->hw queue mapping is the identity
+ * mapping.
+ */
+
+static const u8 tid_to_ac[] = {
+	IEEE80211_AC_BE,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BK,
+	IEEE80211_AC_BE,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VI,
+	IEEE80211_AC_VO,
+	IEEE80211_AC_VO
+};
+
+static inline int iwl4965_get_ac_from_tid(u16 tid)
+{
+	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+		return tid_to_ac[tid];
+
+	/* no support for TIDs 8-15 yet */
+	return -EINVAL;
+}
+
+static inline int
+iwl4965_get_fifo_from_tid(struct iwl_rxon_context *ctx, u16 tid)
+{
+	if (likely(tid < ARRAY_SIZE(tid_to_ac)))
+		return ctx->ac_to_fifo[tid_to_ac[tid]];
+
+	/* no support for TIDs 8-15 yet */
+	return -EINVAL;
+}
+
+/*
+ * handle build REPLY_TX command notification.
+ */
+static void iwl4965_tx_cmd_build_basic(struct iwl_priv *priv,
+					struct sk_buff *skb,
+					struct iwl_tx_cmd *tx_cmd,
+					struct ieee80211_tx_info *info,
+					struct ieee80211_hdr *hdr,
+					u8 std_id)
+{
+	__le16 fc = hdr->frame_control;
+	__le32 tx_flags = tx_cmd->tx_flags;
+
+	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
+	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
+		tx_flags |= TX_CMD_FLG_ACK_MSK;
+		if (ieee80211_is_mgmt(fc))
+			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+		if (ieee80211_is_probe_resp(fc) &&
+		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
+			tx_flags |= TX_CMD_FLG_TSF_MSK;
+	} else {
+		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	if (ieee80211_is_back_req(fc))
+		tx_flags |= TX_CMD_FLG_ACK_MSK | TX_CMD_FLG_IMM_BA_RSP_MASK;
+
+	tx_cmd->sta_id = std_id;
+	if (ieee80211_has_morefrags(fc))
+		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
+
+	if (ieee80211_is_data_qos(fc)) {
+		u8 *qc = ieee80211_get_qos_ctl(hdr);
+		tx_cmd->tid_tspec = qc[0] & 0xf;
+		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
+	} else {
+		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
+	}
+
+	iwl_legacy_tx_cmd_protection(priv, info, fc, &tx_flags);
+
+	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
+	if (ieee80211_is_mgmt(fc)) {
+		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
+		else
+			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
+	} else {
+		tx_cmd->timeout.pm_frame_timeout = 0;
+	}
+
+	tx_cmd->driver_txop = 0;
+	tx_cmd->tx_flags = tx_flags;
+	tx_cmd->next_frame_len = 0;
+}
+
+#define RTS_DFAULT_RETRY_LIMIT		60
+
+static void iwl4965_tx_cmd_build_rate(struct iwl_priv *priv,
+			      struct iwl_tx_cmd *tx_cmd,
+			      struct ieee80211_tx_info *info,
+			      __le16 fc)
+{
+	u32 rate_flags;
+	int rate_idx;
+	u8 rts_retry_limit;
+	u8 data_retry_limit;
+	u8 rate_plcp;
+
+	/* Set retry limit on DATA packets and Probe Responses*/
+	if (ieee80211_is_probe_resp(fc))
+		data_retry_limit = 3;
+	else
+		data_retry_limit = IWL4965_DEFAULT_TX_RETRY;
+	tx_cmd->data_retry_limit = data_retry_limit;
+
+	/* Set retry limit on RTS packets */
+	rts_retry_limit = RTS_DFAULT_RETRY_LIMIT;
+	if (data_retry_limit < rts_retry_limit)
+		rts_retry_limit = data_retry_limit;
+	tx_cmd->rts_retry_limit = rts_retry_limit;
+
+	/* DATA packets will use the uCode station table for rate/antenna
+	 * selection */
+	if (ieee80211_is_data(fc)) {
+		tx_cmd->initial_rate_index = 0;
+		tx_cmd->tx_flags |= TX_CMD_FLG_STA_RATE_MSK;
+		return;
+	}
+
+	/**
+	 * If the current TX rate stored in mac80211 has the MCS bit set, it's
+	 * not really a TX rate.  Thus, we use the lowest supported rate for
+	 * this band.  Also use the lowest supported rate if the stored rate
+	 * index is invalid.
+	 */
+	rate_idx = info->control.rates[0].idx;
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS ||
+			(rate_idx < 0) || (rate_idx > IWL_RATE_COUNT_LEGACY))
+		rate_idx = rate_lowest_index(&priv->bands[info->band],
+				info->control.sta);
+	/* For 5 GHZ band, remap mac80211 rate indices into driver indices */
+	if (info->band == IEEE80211_BAND_5GHZ)
+		rate_idx += IWL_FIRST_OFDM_RATE;
+	/* Get PLCP rate for tx_cmd->rate_n_flags */
+	rate_plcp = iwlegacy_rates[rate_idx].plcp;
+	/* Zero out flags for this packet */
+	rate_flags = 0;
+
+	/* Set CCK flag as needed */
+	if ((rate_idx >= IWL_FIRST_CCK_RATE) && (rate_idx <= IWL_LAST_CCK_RATE))
+		rate_flags |= RATE_MCS_CCK_MSK;
+
+	/* Set up antennas */
+	priv->mgmt_tx_ant = iwl4965_toggle_tx_ant(priv, priv->mgmt_tx_ant,
+				      priv->hw_params.valid_tx_ant);
+
+	rate_flags |= iwl4965_ant_idx_to_flags(priv->mgmt_tx_ant);
+
+	/* Set the rate in the TX cmd */
+	tx_cmd->rate_n_flags = iwl4965_hw_set_rate_n_flags(rate_plcp, rate_flags);
+}
+
+static void iwl4965_tx_cmd_build_hwcrypto(struct iwl_priv *priv,
+				      struct ieee80211_tx_info *info,
+				      struct iwl_tx_cmd *tx_cmd,
+				      struct sk_buff *skb_frag,
+				      int sta_id)
+{
+	struct ieee80211_key_conf *keyconf = info->control.hw_key;
+
+	switch (keyconf->cipher) {
+	case WLAN_CIPHER_SUITE_CCMP:
+		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
+		memcpy(tx_cmd->key, keyconf->key, keyconf->keylen);
+		if (info->flags & IEEE80211_TX_CTL_AMPDU)
+			tx_cmd->tx_flags |= TX_CMD_FLG_AGG_CCMP_MSK;
+		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
+		break;
+
+	case WLAN_CIPHER_SUITE_TKIP:
+		tx_cmd->sec_ctl = TX_CMD_SEC_TKIP;
+		ieee80211_get_tkip_key(keyconf, skb_frag,
+			IEEE80211_TKIP_P2_KEY, tx_cmd->key);
+		IWL_DEBUG_TX(priv, "tx_cmd with tkip hwcrypto\n");
+		break;
+
+	case WLAN_CIPHER_SUITE_WEP104:
+		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
+		/* fall through */
+	case WLAN_CIPHER_SUITE_WEP40:
+		tx_cmd->sec_ctl |= (TX_CMD_SEC_WEP |
+			(keyconf->keyidx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT);
+
+		memcpy(&tx_cmd->key[3], keyconf->key, keyconf->keylen);
+
+		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
+			     "with key %d\n", keyconf->keyidx);
+		break;
+
+	default:
+		IWL_ERR(priv, "Unknown encode cipher %x\n", keyconf->cipher);
+		break;
+	}
+}
+
+/*
+ * start REPLY_TX command process
+ */
+int iwl4965_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct ieee80211_sta *sta = info->control.sta;
+	struct iwl_station_priv *sta_priv = NULL;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	struct iwl_tx_cmd *tx_cmd;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	int txq_id;
+	dma_addr_t phys_addr;
+	dma_addr_t txcmd_phys;
+	dma_addr_t scratch_phys;
+	u16 len, firstlen, secondlen;
+	u16 seq_number = 0;
+	__le16 fc;
+	u8 hdr_len;
+	u8 sta_id;
+	u8 wait_write_ptr = 0;
+	u8 tid = 0;
+	u8 *qc = NULL;
+	unsigned long flags;
+	bool is_agg = false;
+
+	if (info->control.vif)
+		ctx = iwl_legacy_rxon_ctx_from_vif(info->control.vif);
+
+	spin_lock_irqsave(&priv->lock, flags);
+	if (iwl_legacy_is_rfkill(priv)) {
+		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
+		goto drop_unlock;
+	}
+
+	fc = hdr->frame_control;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (ieee80211_is_auth(fc))
+		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
+	else if (ieee80211_is_assoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
+	else if (ieee80211_is_reassoc_req(fc))
+		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
+#endif
+
+	hdr_len = ieee80211_hdrlen(fc);
+
+	/* For management frames use broadcast id to do not break aggregation */
+	if (!ieee80211_is_data(fc))
+		sta_id = ctx->bcast_sta_id;
+	else {
+		/* Find index into station table for destination station */
+		sta_id = iwl_legacy_sta_id_or_broadcast(priv, ctx, info->control.sta);
+
+		if (sta_id == IWL_INVALID_STATION) {
+			IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+				       hdr->addr1);
+			goto drop_unlock;
+		}
+	}
+
+	IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
+
+	if (sta)
+		sta_priv = (void *)sta->drv_priv;
+
+	if (sta_priv && sta_priv->asleep &&
+	    (info->flags & IEEE80211_TX_CTL_PSPOLL_RESPONSE)) {
+		/*
+		 * This sends an asynchronous command to the device,
+		 * but we can rely on it being processed before the
+		 * next frame is processed -- and the next frame to
+		 * this station is the one that will consume this
+		 * counter.
+		 * For now set the counter to just 1 since we do not
+		 * support uAPSD yet.
+		 */
+		iwl4965_sta_modify_sleep_tx_count(priv, sta_id, 1);
+	}
+
+	/*
+	 * Send this frame after DTIM -- there's a special queue
+	 * reserved for this for contexts that support AP mode.
+	 */
+	if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
+		txq_id = ctx->mcast_queue;
+		/*
+		 * The microcode will clear the more data
+		 * bit in the last frame it transmits.
+		 */
+		hdr->frame_control |=
+			cpu_to_le16(IEEE80211_FCTL_MOREDATA);
+	} else
+		txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
+
+	/* irqs already disabled/saved above when locking priv->lock */
+	spin_lock(&priv->sta_lock);
+
+	if (ieee80211_is_data_qos(fc)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		if (WARN_ON_ONCE(tid >= MAX_TID_COUNT)) {
+			spin_unlock(&priv->sta_lock);
+			goto drop_unlock;
+		}
+		seq_number = priv->stations[sta_id].tid[tid].seq_number;
+		seq_number &= IEEE80211_SCTL_SEQ;
+		hdr->seq_ctrl = hdr->seq_ctrl &
+				cpu_to_le16(IEEE80211_SCTL_FRAG);
+		hdr->seq_ctrl |= cpu_to_le16(seq_number);
+		seq_number += 0x10;
+		/* aggregation is on for this <sta,tid> */
+		if (info->flags & IEEE80211_TX_CTL_AMPDU &&
+		    priv->stations[sta_id].tid[tid].agg.state == IWL_AGG_ON) {
+			txq_id = priv->stations[sta_id].tid[tid].agg.txq_id;
+			is_agg = true;
+		}
+	}
+
+	txq = &priv->txq[txq_id];
+	q = &txq->q;
+
+	if (unlikely(iwl_legacy_queue_space(q) < q->high_mark)) {
+		spin_unlock(&priv->sta_lock);
+		goto drop_unlock;
+	}
+
+	if (ieee80211_is_data_qos(fc)) {
+		priv->stations[sta_id].tid[tid].tfds_in_queue++;
+		if (!ieee80211_has_morefrags(fc))
+			priv->stations[sta_id].tid[tid].seq_number = seq_number;
+	}
+
+	spin_unlock(&priv->sta_lock);
+
+	/* Set up driver data for this TFD */
+	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
+	txq->txb[q->write_ptr].skb = skb;
+	txq->txb[q->write_ptr].ctx = ctx;
+
+	/* Set up first empty entry in queue's array of Tx/cmd buffers */
+	out_cmd = txq->cmd[q->write_ptr];
+	out_meta = &txq->meta[q->write_ptr];
+	tx_cmd = &out_cmd->cmd.tx;
+	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
+	memset(tx_cmd, 0, sizeof(struct iwl_tx_cmd));
+
+	/*
+	 * Set up the Tx-command (not MAC!) header.
+	 * Store the chosen Tx queue and TFD index within the sequence field;
+	 * after Tx, uCode's Tx response will return this value so driver can
+	 * locate the frame within the tx queue and do post-tx processing.
+	 */
+	out_cmd->hdr.cmd = REPLY_TX;
+	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
+				INDEX_TO_SEQ(q->write_ptr)));
+
+	/* Copy MAC header from skb into command buffer */
+	memcpy(tx_cmd->hdr, hdr, hdr_len);
+
+
+	/* Total # bytes to be transmitted */
+	len = (u16)skb->len;
+	tx_cmd->len = cpu_to_le16(len);
+
+	if (info->control.hw_key)
+		iwl4965_tx_cmd_build_hwcrypto(priv, info, tx_cmd, skb, sta_id);
+
+	/* TODO need this for burst mode later on */
+	iwl4965_tx_cmd_build_basic(priv, skb, tx_cmd, info, hdr, sta_id);
+	iwl_legacy_dbg_log_tx_data_frame(priv, len, hdr);
+
+	iwl4965_tx_cmd_build_rate(priv, tx_cmd, info, fc);
+
+	iwl_legacy_update_stats(priv, true, fc, len);
+	/*
+	 * Use the first empty entry in this queue's command buffer array
+	 * to contain the Tx command and MAC header concatenated together
+	 * (payload data will be in another buffer).
+	 * Size of this varies, due to varying MAC header length.
+	 * If end is not dword aligned, we'll have 2 extra bytes at the end
+	 * of the MAC header (device reads on dword boundaries).
+	 * We'll tell device about this padding later.
+	 */
+	len = sizeof(struct iwl_tx_cmd) +
+		sizeof(struct iwl_cmd_header) + hdr_len;
+	firstlen = (len + 3) & ~3;
+
+	/* Tell NIC about any 2-byte padding after MAC header */
+	if (firstlen != len)
+		tx_cmd->tx_flags |= TX_CMD_FLG_MH_PAD_MSK;
+
+	/* Physical address of this Tx command's header (not MAC header!),
+	 * within command buffer array. */
+	txcmd_phys = pci_map_single(priv->pci_dev,
+				    &out_cmd->hdr, firstlen,
+				    PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
+	dma_unmap_len_set(out_meta, len, firstlen);
+	/* Add buffer containing Tx command and MAC(!) header to TFD's
+	 * first entry */
+	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+						   txcmd_phys, firstlen, 1, 0);
+
+	if (!ieee80211_has_morefrags(hdr->frame_control)) {
+		txq->need_update = 1;
+	} else {
+		wait_write_ptr = 1;
+		txq->need_update = 0;
+	}
+
+	/* Set up TFD's 2nd entry to point directly to remainder of skb,
+	 * if any (802.11 null frames have no payload). */
+	secondlen = skb->len - hdr_len;
+	if (secondlen > 0) {
+		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
+					   secondlen, PCI_DMA_TODEVICE);
+		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+							   phys_addr, secondlen,
+							   0, 0);
+	}
+
+	scratch_phys = txcmd_phys + sizeof(struct iwl_cmd_header) +
+				offsetof(struct iwl_tx_cmd, scratch);
+
+	/* take back ownership of DMA buffer to enable update */
+	pci_dma_sync_single_for_cpu(priv->pci_dev, txcmd_phys,
+				    firstlen, PCI_DMA_BIDIRECTIONAL);
+	tx_cmd->dram_lsb_ptr = cpu_to_le32(scratch_phys);
+	tx_cmd->dram_msb_ptr = iwl_legacy_get_dma_hi_addr(scratch_phys);
+
+	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
+		     le16_to_cpu(out_cmd->hdr.sequence));
+	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
+	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd, sizeof(*tx_cmd));
+	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 */
+	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,
+				       firstlen, PCI_DMA_BIDIRECTIONAL);
+
+	trace_iwlwifi_legacy_dev_tx(priv,
+			     &((struct iwl_tfd *)txq->tfds)[txq->q.write_ptr],
+			     sizeof(struct iwl_tfd),
+			     &out_cmd->hdr, firstlen,
+			     skb->data + hdr_len, secondlen);
+
+	/* Tell device the write index *just past* this latest filled TFD */
+	q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_legacy_txq_update_write_ptr(priv, txq);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/*
+	 * At this point the frame is "transmitted" successfully
+	 * and we will get a TX status notification eventually,
+	 * regardless of the value of ret. "ret" only indicates
+	 * whether or not we should update the write pointer.
+	 */
+
+	/*
+	 * Avoid atomic ops if it isn't an associated client.
+	 * Also, if this is a packet for aggregation, don't
+	 * increase the counter because the ucode will stop
+	 * aggregation queues when their respective station
+	 * goes to sleep.
+	 */
+	if (sta_priv && sta_priv->client && !is_agg)
+		atomic_inc(&sta_priv->pending_frames);
+
+	if ((iwl_legacy_queue_space(q) < q->high_mark) &&
+			priv->mac80211_registered) {
+		if (wait_write_ptr) {
+			spin_lock_irqsave(&priv->lock, flags);
+			txq->need_update = 1;
+			iwl_legacy_txq_update_write_ptr(priv, txq);
+			spin_unlock_irqrestore(&priv->lock, flags);
+		} else {
+			iwl_legacy_stop_queue(priv, txq);
+		}
+	}
+
+	return 0;
+
+drop_unlock:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return -1;
+}
+
+static inline int iwl4965_alloc_dma_ptr(struct iwl_priv *priv,
+				    struct iwl_dma_ptr *ptr, size_t size)
+{
+	ptr->addr = dma_alloc_coherent(&priv->pci_dev->dev, size, &ptr->dma,
+				       GFP_KERNEL);
+	if (!ptr->addr)
+		return -ENOMEM;
+	ptr->size = size;
+	return 0;
+}
+
+static inline void iwl4965_free_dma_ptr(struct iwl_priv *priv,
+				    struct iwl_dma_ptr *ptr)
+{
+	if (unlikely(!ptr->addr))
+		return;
+
+	dma_free_coherent(&priv->pci_dev->dev, ptr->size, ptr->addr, ptr->dma);
+	memset(ptr, 0, sizeof(*ptr));
+}
+
+/**
+ * iwl4965_hw_txq_ctx_free - Free TXQ Context
+ *
+ * Destroy all TX DMA queues and structures
+ */
+void iwl4965_hw_txq_ctx_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	/* Tx queues */
+	if (priv->txq) {
+		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+			if (txq_id == priv->cmd_queue)
+				iwl_legacy_cmd_queue_free(priv);
+			else
+				iwl_legacy_tx_queue_free(priv, txq_id);
+	}
+	iwl4965_free_dma_ptr(priv, &priv->kw);
+
+	iwl4965_free_dma_ptr(priv, &priv->scd_bc_tbls);
+
+	/* free tx queue structure */
+	iwl_legacy_txq_mem(priv);
+}
+
+/**
+ * iwl4965_txq_ctx_alloc - allocate TX queue context
+ * Allocate all Tx DMA structures and initialize them
+ *
+ * @param priv
+ * @return error code
+ */
+int iwl4965_txq_ctx_alloc(struct iwl_priv *priv)
+{
+	int ret;
+	int txq_id, slots_num;
+	unsigned long flags;
+
+	/* Free all tx/cmd queues and keep-warm buffer */
+	iwl4965_hw_txq_ctx_free(priv);
+
+	ret = iwl4965_alloc_dma_ptr(priv, &priv->scd_bc_tbls,
+				priv->hw_params.scd_bc_tbls_size);
+	if (ret) {
+		IWL_ERR(priv, "Scheduler BC Table allocation failed\n");
+		goto error_bc_tbls;
+	}
+	/* Alloc keep-warm buffer */
+	ret = iwl4965_alloc_dma_ptr(priv, &priv->kw, IWL_KW_SIZE);
+	if (ret) {
+		IWL_ERR(priv, "Keep Warm allocation failed\n");
+		goto error_kw;
+	}
+
+	/* allocate tx queue structure */
+	ret = iwl_legacy_alloc_txq_mem(priv);
+	if (ret)
+		goto error;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Turn off all Tx DMA fifos */
+	iwl4965_txq_set_sched(priv, 0);
+
+	/* Tell NIC where to find the "keep warm" buffer */
+	iwl_legacy_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Alloc and init all Tx queues, including the command queue (#4/#9) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = (txq_id == priv->cmd_queue) ?
+					TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		ret = iwl_legacy_tx_queue_init(priv,
+					&priv->txq[txq_id], slots_num,
+				       txq_id);
+		if (ret) {
+			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
+			goto error;
+		}
+	}
+
+	return ret;
+
+ error:
+	iwl4965_hw_txq_ctx_free(priv);
+	iwl4965_free_dma_ptr(priv, &priv->kw);
+ error_kw:
+	iwl4965_free_dma_ptr(priv, &priv->scd_bc_tbls);
+ error_bc_tbls:
+	return ret;
+}
+
+void iwl4965_txq_ctx_reset(struct iwl_priv *priv)
+{
+	int txq_id, slots_num;
+	unsigned long flags;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Turn off all Tx DMA fifos */
+	iwl4965_txq_set_sched(priv, 0);
+
+	/* Tell NIC where to find the "keep warm" buffer */
+	iwl_legacy_write_direct32(priv, FH_KW_MEM_ADDR_REG, priv->kw.dma >> 4);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	/* Alloc and init all Tx queues, including the command queue (#4) */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
+		slots_num = txq_id == priv->cmd_queue ?
+			    TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
+		iwl_legacy_tx_queue_reset(priv, &priv->txq[txq_id],
+						slots_num, txq_id);
+	}
+}
+
+/**
+ * iwl4965_txq_ctx_stop - Stop all Tx DMA channels
+ */
+void iwl4965_txq_ctx_stop(struct iwl_priv *priv)
+{
+	int ch, txq_id;
+	unsigned long flags;
+
+	/* Turn off all Tx DMA fifos */
+	spin_lock_irqsave(&priv->lock, flags);
+
+	iwl4965_txq_set_sched(priv, 0);
+
+	/* Stop each Tx DMA channel, and wait for it to be idle */
+	for (ch = 0; ch < priv->hw_params.dma_chnl_num; ch++) {
+		iwl_legacy_write_direct32(priv,
+				FH_TCSR_CHNL_TX_CONFIG_REG(ch), 0x0);
+		if (iwl_poll_direct_bit(priv, FH_TSSR_TX_STATUS_REG,
+				    FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(ch),
+				    1000))
+			IWL_ERR(priv, "Failing on timeout while stopping"
+			    " DMA channel %d [0x%08x]", ch,
+			    iwl_legacy_read_direct32(priv,
+					FH_TSSR_TX_STATUS_REG));
+	}
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!priv->txq)
+		return;
+
+	/* Unmap DMA from host system and free skb's */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		if (txq_id == priv->cmd_queue)
+			iwl_legacy_cmd_queue_unmap(priv);
+		else
+			iwl_legacy_tx_queue_unmap(priv, txq_id);
+}
+
+/*
+ * Find first available (lowest unused) Tx Queue, mark it "active".
+ * Called only when finding queue for aggregation.
+ * Should never return anything < 7, because they should already
+ * be in use as EDCA AC (0-3), Command (4), reserved (5, 6)
+ */
+static int iwl4965_txq_ctx_activate_free(struct iwl_priv *priv)
+{
+	int txq_id;
+
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		if (!test_and_set_bit(txq_id, &priv->txq_ctx_active_msk))
+			return txq_id;
+	return -1;
+}
+
+/**
+ * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
+ */
+static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
+					    u16 txq_id)
+{
+	/* Simply stop the queue, but don't change any configuration;
+	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
+	iwl_legacy_write_prph(priv,
+		IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
+		(0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
+		(1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
+}
+
+/**
+ * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
+ */
+static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
+					u16 txq_id)
+{
+	u32 tbl_dw_addr;
+	u32 tbl_dw;
+	u16 scd_q2ratid;
+
+	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
+
+	tbl_dw_addr = priv->scd_base_addr +
+			IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
+
+	tbl_dw = iwl_legacy_read_targ_mem(priv, tbl_dw_addr);
+
+	if (txq_id & 0x1)
+		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
+	else
+		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
+
+	iwl_legacy_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
+
+	return 0;
+}
+
+/**
+ * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
+ *
+ * NOTE:  txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE,
+ *        i.e. it must be one of the higher queues used for aggregation
+ */
+static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
+				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
+{
+	unsigned long flags;
+	u16 ra_tid;
+	int ret;
+
+	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
+	    (IWL49_FIRST_AMPDU_QUEUE +
+		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+		IWL_WARN(priv,
+			"queue number out of range: %d, must be %d to %d\n",
+			txq_id, IWL49_FIRST_AMPDU_QUEUE,
+			IWL49_FIRST_AMPDU_QUEUE +
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
+		return -EINVAL;
+	}
+
+	ra_tid = BUILD_RAxTID(sta_id, tid);
+
+	/* Modify device's station table to Tx this TID */
+	ret = iwl4965_sta_tx_modify_enable_tid(priv, sta_id, tid);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* Stop this Tx queue before configuring it */
+	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+
+	/* Map receiver-address / traffic-ID to this queue */
+	iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
+
+	/* Set this queue as a chain-building queue */
+	iwl_legacy_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+	/* Place first TFD at index corresponding to start sequence number.
+	 * Assumes that ssn_idx is valid (!= 0xFFF) */
+	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+	/* Set up Tx window size and frame limit for this queue */
+	iwl_legacy_write_targ_mem(priv,
+		priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
+		(SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
+		IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
+
+	iwl_legacy_write_targ_mem(priv, priv->scd_base_addr +
+		IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
+		(SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
+		& IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
+
+	iwl_legacy_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+
+	/* 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);
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	return 0;
+}
+
+
+int iwl4965_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+{
+	int sta_id;
+	int tx_fifo;
+	int txq_id;
+	int ret;
+	unsigned long flags;
+	struct iwl_tid_data *tid_data;
+
+	tx_fifo = iwl4965_get_fifo_from_tid(iwl_legacy_rxon_ctx_from_vif(vif), tid);
+	if (unlikely(tx_fifo < 0))
+		return tx_fifo;
+
+	IWL_WARN(priv, "%s on ra = %pM tid = %d\n",
+			__func__, sta->addr, tid);
+
+	sta_id = iwl_legacy_sta_id(sta);
+	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");
+		return -ENXIO;
+	}
+
+	txq_id = iwl4965_txq_ctx_activate_free(priv);
+	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];
+	*ssn = SEQ_TO_SN(tid_data->seq_number);
+	tid_data->agg.txq_id = txq_id;
+	iwl_legacy_set_swq_id(&priv->txq[txq_id],
+				iwl4965_get_ac_from_tid(tid), txq_id);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	ret = iwl4965_txq_agg_enable(priv, txq_id, tx_fifo,
+						  sta_id, tid, *ssn);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	tid_data = &priv->stations[sta_id].tid[tid];
+	if (tid_data->tfds_in_queue == 0) {
+		IWL_DEBUG_HT(priv, "HW queue is empty\n");
+		tid_data->agg.state = IWL_AGG_ON;
+		ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+	} else {
+		IWL_DEBUG_HT(priv,
+			"HW queue is NOT empty: %d packets in HW queue\n",
+			     tid_data->tfds_in_queue);
+		tid_data->agg.state = IWL_EMPTYING_HW_QUEUE_ADDBA;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	return ret;
+}
+
+/**
+ * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE
+ * priv->lock must be held by the caller
+ */
+static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
+				   u16 ssn_idx, u8 tx_fifo)
+{
+	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
+	    (IWL49_FIRST_AMPDU_QUEUE +
+		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
+		IWL_WARN(priv,
+			"queue number out of range: %d, must be %d to %d\n",
+			txq_id, IWL49_FIRST_AMPDU_QUEUE,
+			IWL49_FIRST_AMPDU_QUEUE +
+			priv->cfg->base_params->num_of_ampdu_queues - 1);
+		return -EINVAL;
+	}
+
+	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
+
+	iwl_legacy_clear_bits_prph(priv,
+			IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
+
+	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
+	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
+	/* supposes that ssn_idx is valid (!= 0xFFF) */
+	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
+
+	iwl_legacy_clear_bits_prph(priv,
+			 IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
+	iwl_txq_ctx_deactivate(priv, txq_id);
+	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
+
+	return 0;
+}
+
+int iwl4965_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta, u16 tid)
+{
+	int tx_fifo_id, txq_id, sta_id, ssn;
+	struct iwl_tid_data *tid_data;
+	int write_ptr, read_ptr;
+	unsigned long flags;
+
+	tx_fifo_id = iwl4965_get_fifo_from_tid(iwl_legacy_rxon_ctx_from_vif(vif), tid);
+	if (unlikely(tx_fifo_id < 0))
+		return tx_fifo_id;
+
+	sta_id = iwl_legacy_sta_id(sta);
+
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Invalid station for AGG tid %d\n", tid);
+		return -ENXIO;
+	}
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	tid_data = &priv->stations[sta_id].tid[tid];
+	ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
+	txq_id = tid_data->agg.txq_id;
+
+	switch (priv->stations[sta_id].tid[tid].agg.state) {
+	case IWL_EMPTYING_HW_QUEUE_ADDBA:
+		/*
+		 * This can happen if the peer stops aggregation
+		 * again before we've had a chance to drain the
+		 * queue we selected previously, i.e. before the
+		 * session was really started completely.
+		 */
+		IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
+		goto turn_off;
+	case IWL_AGG_ON:
+		break;
+	default:
+		IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
+	}
+
+	write_ptr = priv->txq[txq_id].q.write_ptr;
+	read_ptr = priv->txq[txq_id].q.read_ptr;
+
+	/* The queue is not empty */
+	if (write_ptr != read_ptr) {
+		IWL_DEBUG_HT(priv, "Stopping a non empty AGG HW QUEUE\n");
+		priv->stations[sta_id].tid[tid].agg.state =
+				IWL_EMPTYING_HW_QUEUE_DELBA;
+		spin_unlock_irqrestore(&priv->sta_lock, flags);
+		return 0;
+	}
+
+	IWL_DEBUG_HT(priv, "HW queue is empty\n");
+ turn_off:
+	priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
+
+	/* do not restore/save irqs */
+	spin_unlock(&priv->sta_lock);
+	spin_lock(&priv->lock);
+
+	/*
+	 * the only reason this call can fail is queue number out of range,
+	 * which can happen if uCode is reloaded and all the station
+	 * information are lost. if it is outside the range, there is no need
+	 * to deactivate the uCode queue, just return "success" to allow
+	 *  mac80211 to clean up it own data.
+	 */
+	iwl4965_txq_agg_disable(priv, txq_id, ssn, tx_fifo_id);
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+
+	return 0;
+}
+
+int iwl4965_txq_check_empty(struct iwl_priv *priv,
+			   int sta_id, u8 tid, int txq_id)
+{
+	struct iwl_queue *q = &priv->txq[txq_id].q;
+	u8 *addr = priv->stations[sta_id].sta.sta.addr;
+	struct iwl_tid_data *tid_data = &priv->stations[sta_id].tid[tid];
+	struct iwl_rxon_context *ctx;
+
+	ctx = &priv->contexts[priv->stations[sta_id].ctxid];
+
+	lockdep_assert_held(&priv->sta_lock);
+
+	switch (priv->stations[sta_id].tid[tid].agg.state) {
+	case IWL_EMPTYING_HW_QUEUE_DELBA:
+		/* We are reclaiming the last packet of the */
+		/* aggregated HW queue */
+		if ((txq_id  == tid_data->agg.txq_id) &&
+		    (q->read_ptr == q->write_ptr)) {
+			u16 ssn = SEQ_TO_SN(tid_data->seq_number);
+			int tx_fifo = iwl4965_get_fifo_from_tid(ctx, tid);
+			IWL_DEBUG_HT(priv,
+				"HW queue empty: continue DELBA flow\n");
+			iwl4965_txq_agg_disable(priv, txq_id, ssn, tx_fifo);
+			tid_data->agg.state = IWL_AGG_OFF;
+			ieee80211_stop_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
+		}
+		break;
+	case IWL_EMPTYING_HW_QUEUE_ADDBA:
+		/* We are reclaiming the last packet of the queue */
+		if (tid_data->tfds_in_queue == 0) {
+			IWL_DEBUG_HT(priv,
+				"HW queue empty: continue ADDBA flow\n");
+			tid_data->agg.state = IWL_AGG_ON;
+			ieee80211_start_tx_ba_cb_irqsafe(ctx->vif, addr, tid);
+		}
+		break;
+	}
+
+	return 0;
+}
+
+static void iwl4965_non_agg_tx_status(struct iwl_priv *priv,
+				     struct iwl_rxon_context *ctx,
+				     const u8 *addr1)
+{
+	struct ieee80211_sta *sta;
+	struct iwl_station_priv *sta_priv;
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(ctx->vif, addr1);
+	if (sta) {
+		sta_priv = (void *)sta->drv_priv;
+		/* avoid atomic ops if this isn't a client */
+		if (sta_priv->client &&
+		    atomic_dec_return(&sta_priv->pending_frames) == 0)
+			ieee80211_sta_block_awake(priv->hw, sta, false);
+	}
+	rcu_read_unlock();
+}
+
+static void
+iwl4965_tx_status(struct iwl_priv *priv, struct iwl_tx_info *tx_info,
+			     bool is_agg)
+{
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) tx_info->skb->data;
+
+	if (!is_agg)
+		iwl4965_non_agg_tx_status(priv, tx_info->ctx, hdr->addr1);
+
+	ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
+}
+
+int iwl4965_tx_queue_reclaim(struct iwl_priv *priv, int txq_id, int index)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_tx_info *tx_info;
+	int nfreed = 0;
+	struct ieee80211_hdr *hdr;
+
+	if ((index >= q->n_bd) || (iwl_legacy_queue_used(q, index) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
+			  "is out of range [0-%d] %d %d.\n", txq_id,
+			  index, q->n_bd, q->write_ptr, q->read_ptr);
+		return 0;
+	}
+
+	for (index = iwl_legacy_queue_inc_wrap(index, q->n_bd);
+	     q->read_ptr != index;
+	     q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		tx_info = &txq->txb[txq->q.read_ptr];
+
+		if (WARN_ON_ONCE(tx_info->skb == NULL))
+			continue;
+
+		hdr = (struct ieee80211_hdr *)tx_info->skb->data;
+		if (ieee80211_is_data_qos(hdr->frame_control))
+			nfreed++;
+
+		iwl4965_tx_status(priv, tx_info,
+				 txq_id >= IWL4965_FIRST_AMPDU_QUEUE);
+		tx_info->skb = NULL;
+
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+	}
+	return nfreed;
+}
+
+/**
+ * iwl4965_tx_status_reply_compressed_ba - Update tx status from block-ack
+ *
+ * Go through block-ack's bitmap of ACK'd frames, update driver's record of
+ * ACK vs. not.  This gets sent to mac80211, then to rate scaling algo.
+ */
+static int iwl4965_tx_status_reply_compressed_ba(struct iwl_priv *priv,
+				 struct iwl_ht_agg *agg,
+				 struct iwl_compressed_ba_resp *ba_resp)
+
+{
+	int i, sh, ack;
+	u16 seq_ctl = le16_to_cpu(ba_resp->seq_ctl);
+	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+	int successes = 0;
+	struct ieee80211_tx_info *info;
+	u64 bitmap, sent_bitmap;
+
+	if (unlikely(!agg->wait_for_ba))  {
+		if (unlikely(ba_resp->bitmap))
+			IWL_ERR(priv, "Received BA when not expected\n");
+		return -EINVAL;
+	}
+
+	/* Mark that the expected block-ack response arrived */
+	agg->wait_for_ba = 0;
+	IWL_DEBUG_TX_REPLY(priv, "BA %d %d\n", agg->start_idx,
+							ba_resp->seq_ctl);
+
+	/* Calculate shift to align block-ack bits with our Tx window bits */
+	sh = agg->start_idx - SEQ_TO_INDEX(seq_ctl >> 4);
+	if (sh < 0) /* tbw something is wrong with indices */
+		sh += 0x100;
+
+	if (agg->frame_count > (64 - sh)) {
+		IWL_DEBUG_TX_REPLY(priv, "more frames than bitmap size");
+		return -1;
+	}
+
+	/* don't use 64-bit values for now */
+	bitmap = le64_to_cpu(ba_resp->bitmap) >> sh;
+
+	/* check for success or failure according to the
+	 * transmitted bitmap and block-ack bitmap */
+	sent_bitmap = bitmap & agg->bitmap;
+
+	/* For each frame attempted in aggregation,
+	 * update driver's record of tx frame's status. */
+	i = 0;
+	while (sent_bitmap) {
+		ack = sent_bitmap & 1ULL;
+		successes += ack;
+		IWL_DEBUG_TX_REPLY(priv, "%s ON i=%d idx=%d raw=%d\n",
+			ack ? "ACK" : "NACK", i,
+			(agg->start_idx + i) & 0xff,
+			agg->start_idx + i);
+		sent_bitmap >>= 1;
+		++i;
+	}
+
+	IWL_DEBUG_TX_REPLY(priv, "Bitmap %llx\n",
+				   (unsigned long long)bitmap);
+
+	info = IEEE80211_SKB_CB(priv->txq[scd_flow].txb[agg->start_idx].skb);
+	memset(&info->status, 0, sizeof(info->status));
+	info->flags |= IEEE80211_TX_STAT_ACK;
+	info->flags |= IEEE80211_TX_STAT_AMPDU;
+	info->status.ampdu_ack_len = successes;
+	info->status.ampdu_len = agg->frame_count;
+	iwl4965_hwrate_to_tx_control(priv, agg->rate_n_flags, info);
+
+	return 0;
+}
+
+/**
+ * translate ucode response to mac80211 tx status control values
+ */
+void iwl4965_hwrate_to_tx_control(struct iwl_priv *priv, u32 rate_n_flags,
+				  struct ieee80211_tx_info *info)
+{
+	struct ieee80211_tx_rate *r = &info->control.rates[0];
+
+	info->antenna_sel_tx =
+		((rate_n_flags & RATE_MCS_ANT_ABC_MSK) >> RATE_MCS_ANT_POS);
+	if (rate_n_flags & RATE_MCS_HT_MSK)
+		r->flags |= IEEE80211_TX_RC_MCS;
+	if (rate_n_flags & RATE_MCS_GF_MSK)
+		r->flags |= IEEE80211_TX_RC_GREEN_FIELD;
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
+		r->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
+	if (rate_n_flags & RATE_MCS_DUP_MSK)
+		r->flags |= IEEE80211_TX_RC_DUP_DATA;
+	if (rate_n_flags & RATE_MCS_SGI_MSK)
+		r->flags |= IEEE80211_TX_RC_SHORT_GI;
+	r->idx = iwl4965_hwrate_to_mac80211_idx(rate_n_flags, info->band);
+}
+
+/**
+ * iwl4965_rx_reply_compressed_ba - Handler for REPLY_COMPRESSED_BA
+ *
+ * Handles block-acknowledge notification from device, which reports success
+ * of frames sent via aggregation.
+ */
+void iwl4965_rx_reply_compressed_ba(struct iwl_priv *priv,
+					   struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_compressed_ba_resp *ba_resp = &pkt->u.compressed_ba;
+	struct iwl_tx_queue *txq = NULL;
+	struct iwl_ht_agg *agg;
+	int index;
+	int sta_id;
+	int tid;
+	unsigned long flags;
+
+	/* "flow" corresponds to Tx queue */
+	u16 scd_flow = le16_to_cpu(ba_resp->scd_flow);
+
+	/* "ssn" is start of block-ack Tx window, corresponds to index
+	 * (in Tx queue's circular buffer) of first TFD/frame in window */
+	u16 ba_resp_scd_ssn = le16_to_cpu(ba_resp->scd_ssn);
+
+	if (scd_flow >= priv->hw_params.max_txq_num) {
+		IWL_ERR(priv,
+			"BUG_ON scd_flow is bigger than number of queues\n");
+		return;
+	}
+
+	txq = &priv->txq[scd_flow];
+	sta_id = ba_resp->sta_id;
+	tid = ba_resp->tid;
+	agg = &priv->stations[sta_id].tid[tid].agg;
+	if (unlikely(agg->txq_id != scd_flow)) {
+		/*
+		 * FIXME: this is a uCode bug which need to be addressed,
+		 * log the information and return for now!
+		 * since it is possible happen very often and in order
+		 * not to fill the syslog, don't enable the logging by default
+		 */
+		IWL_DEBUG_TX_REPLY(priv,
+			"BA scd_flow %d does not match txq_id %d\n",
+			scd_flow, agg->txq_id);
+		return;
+	}
+
+	/* Find index just before block-ack window */
+	index = iwl_legacy_queue_dec_wrap(ba_resp_scd_ssn & 0xff, txq->q.n_bd);
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	IWL_DEBUG_TX_REPLY(priv, "REPLY_COMPRESSED_BA [%d] Received from %pM, "
+			   "sta_id = %d\n",
+			   agg->wait_for_ba,
+			   (u8 *) &ba_resp->sta_addr_lo32,
+			   ba_resp->sta_id);
+	IWL_DEBUG_TX_REPLY(priv, "TID = %d, SeqCtl = %d, bitmap = 0x%llx,"
+			"scd_flow = "
+			   "%d, scd_ssn = %d\n",
+			   ba_resp->tid,
+			   ba_resp->seq_ctl,
+			   (unsigned long long)le64_to_cpu(ba_resp->bitmap),
+			   ba_resp->scd_flow,
+			   ba_resp->scd_ssn);
+	IWL_DEBUG_TX_REPLY(priv, "DAT start_idx = %d, bitmap = 0x%llx\n",
+			   agg->start_idx,
+			   (unsigned long long)agg->bitmap);
+
+	/* Update driver's record of ACK vs. not for each frame in window */
+	iwl4965_tx_status_reply_compressed_ba(priv, agg, ba_resp);
+
+	/* Release all TFDs before the SSN, i.e. all TFDs in front of
+	 * block-ack window (we assume that they've been successfully
+	 * transmitted ... if not, it's too late anyway). */
+	if (txq->q.read_ptr != (ba_resp_scd_ssn & 0xff)) {
+		/* calculate mac80211 ampdu sw queue to wake */
+		int freed = iwl4965_tx_queue_reclaim(priv, scd_flow, index);
+		iwl4965_free_tfds_in_queue(priv, sta_id, tid, freed);
+
+		if ((iwl_legacy_queue_space(&txq->q) > txq->q.low_mark) &&
+		    priv->mac80211_registered &&
+		    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
+			iwl_legacy_wake_queue(priv, txq);
+
+		iwl4965_txq_check_empty(priv, sta_id, tid, scd_flow);
+	}
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+const char *iwl4965_get_tx_fail_reason(u32 status)
+{
+#define TX_STATUS_FAIL(x) case TX_STATUS_FAIL_ ## x: return #x
+#define TX_STATUS_POSTPONE(x) case TX_STATUS_POSTPONE_ ## x: return #x
+
+	switch (status & TX_STATUS_MSK) {
+	case TX_STATUS_SUCCESS:
+		return "SUCCESS";
+	TX_STATUS_POSTPONE(DELAY);
+	TX_STATUS_POSTPONE(FEW_BYTES);
+	TX_STATUS_POSTPONE(QUIET_PERIOD);
+	TX_STATUS_POSTPONE(CALC_TTAK);
+	TX_STATUS_FAIL(INTERNAL_CROSSED_RETRY);
+	TX_STATUS_FAIL(SHORT_LIMIT);
+	TX_STATUS_FAIL(LONG_LIMIT);
+	TX_STATUS_FAIL(FIFO_UNDERRUN);
+	TX_STATUS_FAIL(DRAIN_FLOW);
+	TX_STATUS_FAIL(RFKILL_FLUSH);
+	TX_STATUS_FAIL(LIFE_EXPIRE);
+	TX_STATUS_FAIL(DEST_PS);
+	TX_STATUS_FAIL(HOST_ABORTED);
+	TX_STATUS_FAIL(BT_RETRY);
+	TX_STATUS_FAIL(STA_INVALID);
+	TX_STATUS_FAIL(FRAG_DROPPED);
+	TX_STATUS_FAIL(TID_DISABLE);
+	TX_STATUS_FAIL(FIFO_FLUSHED);
+	TX_STATUS_FAIL(INSUFFICIENT_CF_POLL);
+	TX_STATUS_FAIL(PASSIVE_NO_RX);
+	TX_STATUS_FAIL(NO_BEACON_ON_RADAR);
+	}
+
+	return "UNKNOWN";
+
+#undef TX_STATUS_FAIL
+#undef TX_STATUS_POSTPONE
+}
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-4965-ucode.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,166 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * 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 <linux/sched.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+#include "iwl-4965-hw.h"
+#include "iwl-4965.h"
+#include "iwl-4965-calib.h"
+
+#define IWL_AC_UNSET -1
+
+/**
+ * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
+ *   using sample data 100 bytes apart.  If these sample points are good,
+ *   it's a pretty good bet that everything between them is good, too.
+ */
+static int
+iwl4965_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
+{
+	u32 val;
+	int ret = 0;
+	u32 errcnt = 0;
+	u32 i;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	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
+		 * if IWL_DL_IO is set */
+		iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			i + IWL4965_RTC_INST_LOWER_BOUND);
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+			ret = -EIO;
+			errcnt++;
+			if (errcnt >= 3)
+				break;
+		}
+	}
+
+	return ret;
+}
+
+/**
+ * iwl4965_verify_inst_full - verify runtime uCode image in card vs. host,
+ *     looking at all data.
+ */
+static int iwl4965_verify_inst_full(struct iwl_priv *priv, __le32 *image,
+				 u32 len)
+{
+	u32 val;
+	u32 save_len = len;
+	int ret = 0;
+	u32 errcnt;
+
+	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
+
+	iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR,
+			   IWL4965_RTC_INST_LOWER_BOUND);
+
+	errcnt = 0;
+	for (; len > 0; len -= sizeof(u32), image++) {
+		/* read data comes through single port, auto-incr addr */
+		/* NOTE: Use the debugless read so we don't flood kernel log
+		 * if IWL_DL_IO is set */
+		val = _iwl_legacy_read_direct32(priv, HBUS_TARG_MEM_RDAT);
+		if (val != le32_to_cpu(*image)) {
+			IWL_ERR(priv, "uCode INST section is invalid at "
+				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
+				  save_len - len, val, le32_to_cpu(*image));
+			ret = -EIO;
+			errcnt++;
+			if (errcnt >= 20)
+				break;
+		}
+	}
+
+	if (!errcnt)
+		IWL_DEBUG_INFO(priv,
+		    "ucode image in INSTRUCTION memory is good\n");
+
+	return ret;
+}
+
+/**
+ * iwl4965_verify_ucode - determine which instruction image is in SRAM,
+ *    and verify its contents
+ */
+int iwl4965_verify_ucode(struct iwl_priv *priv)
+{
+	__le32 *image;
+	u32 len;
+	int ret;
+
+	/* Try bootstrap */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	ret = iwl4965_verify_inst_sparse(priv, image, len);
+	if (!ret) {
+		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try initialize */
+	image = (__le32 *)priv->ucode_init.v_addr;
+	len = priv->ucode_init.len;
+	ret = iwl4965_verify_inst_sparse(priv, image, len);
+	if (!ret) {
+		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	/* Try runtime/protocol */
+	image = (__le32 *)priv->ucode_code.v_addr;
+	len = priv->ucode_code.len;
+	ret = iwl4965_verify_inst_sparse(priv, image, len);
+	if (!ret) {
+		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
+		return 0;
+	}
+
+	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
+
+	/* Since nothing seems to match, show first several data entries in
+	 * instruction SRAM, so maybe visual inspection will give a clue.
+	 * Selection of bootstrap image (vs. other images) is arbitrary. */
+	image = (__le32 *)priv->ucode_boot.v_addr;
+	len = priv->ucode_boot.len;
+	ret = iwl4965_verify_inst_full(priv, image, len);
+
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-commands.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-commands.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-commands.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-commands.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3405 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-commands.h) only for uCode API definitions.
+ * Please use iwl-xxxx-hw.h for hardware-related definitions.
+ * Please use iwl-dev.h for driver implementation definitions.
+ */
+
+#ifndef __iwl_legacy_commands_h__
+#define __iwl_legacy_commands_h__
+
+struct iwl_priv;
+
+/* uCode version contains 4 values: Major/Minor/API/Serial */
+#define IWL_UCODE_MAJOR(ver)	(((ver) & 0xFF000000) >> 24)
+#define IWL_UCODE_MINOR(ver)	(((ver) & 0x00FF0000) >> 16)
+#define IWL_UCODE_API(ver)	(((ver) & 0x0000FF00) >> 8)
+#define IWL_UCODE_SERIAL(ver)	((ver) & 0x000000FF)
+
+
+/* Tx rates */
+#define IWL_CCK_RATES	4
+#define IWL_OFDM_RATES	8
+#define IWL_MAX_RATES	(IWL_CCK_RATES + IWL_OFDM_RATES)
+
+enum {
+	REPLY_ALIVE = 0x1,
+	REPLY_ERROR = 0x2,
+
+	/* RXON and QOS commands */
+	REPLY_RXON = 0x10,
+	REPLY_RXON_ASSOC = 0x11,
+	REPLY_QOS_PARAM = 0x13,
+	REPLY_RXON_TIMING = 0x14,
+
+	/* Multi-Station support */
+	REPLY_ADD_STA = 0x18,
+	REPLY_REMOVE_STA = 0x19,
+
+	/* Security */
+	REPLY_WEPKEY = 0x20,
+
+	/* RX, TX, LEDs */
+	REPLY_3945_RX = 0x1b,           /* 3945 only */
+	REPLY_TX = 0x1c,
+	REPLY_RATE_SCALE = 0x47,	/* 3945 only */
+	REPLY_LEDS_CMD = 0x48,
+	REPLY_TX_LINK_QUALITY_CMD = 0x4e, /* for 4965 and up */
+
+	/* 802.11h related */
+	REPLY_CHANNEL_SWITCH = 0x72,
+	CHANNEL_SWITCH_NOTIFICATION = 0x73,
+	REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74,
+	SPECTRUM_MEASURE_NOTIFICATION = 0x75,
+
+	/* Power Management */
+	POWER_TABLE_CMD = 0x77,
+	PM_SLEEP_NOTIFICATION = 0x7A,
+	PM_DEBUG_STATISTIC_NOTIFIC = 0x7B,
+
+	/* Scan commands and notifications */
+	REPLY_SCAN_CMD = 0x80,
+	REPLY_SCAN_ABORT_CMD = 0x81,
+	SCAN_START_NOTIFICATION = 0x82,
+	SCAN_RESULTS_NOTIFICATION = 0x83,
+	SCAN_COMPLETE_NOTIFICATION = 0x84,
+
+	/* IBSS/AP commands */
+	BEACON_NOTIFICATION = 0x90,
+	REPLY_TX_BEACON = 0x91,
+
+	/* Miscellaneous commands */
+	REPLY_TX_PWR_TABLE_CMD = 0x97,
+
+	/* Bluetooth device coexistence config command */
+	REPLY_BT_CONFIG = 0x9b,
+
+	/* Statistics */
+	REPLY_STATISTICS_CMD = 0x9c,
+	STATISTICS_NOTIFICATION = 0x9d,
+
+	/* RF-KILL commands and notifications */
+	CARD_STATE_NOTIFICATION = 0xa1,
+
+	/* Missed beacons notification */
+	MISSED_BEACONS_NOTIFICATION = 0xa2,
+
+	REPLY_CT_KILL_CONFIG_CMD = 0xa4,
+	SENSITIVITY_CMD = 0xa8,
+	REPLY_PHY_CALIBRATION_CMD = 0xb0,
+	REPLY_RX_PHY_CMD = 0xc0,
+	REPLY_RX_MPDU_CMD = 0xc1,
+	REPLY_RX = 0xc3,
+	REPLY_COMPRESSED_BA = 0xc5,
+
+	REPLY_MAX = 0xff
+};
+
+/******************************************************************************
+ * (0)
+ * Commonly used structures and definitions:
+ * Command header, rate_n_flags, txpower
+ *
+ *****************************************************************************/
+
+/* iwl_cmd_header flags value */
+#define IWL_CMD_FAILED_MSK 0x40
+
+#define SEQ_TO_QUEUE(s)	(((s) >> 8) & 0x1f)
+#define QUEUE_TO_SEQ(q)	(((q) & 0x1f) << 8)
+#define SEQ_TO_INDEX(s)	((s) & 0xff)
+#define INDEX_TO_SEQ(i)	((i) & 0xff)
+#define SEQ_HUGE_FRAME	cpu_to_le16(0x4000)
+#define SEQ_RX_FRAME	cpu_to_le16(0x8000)
+
+/**
+ * struct iwl_cmd_header
+ *
+ * This header format appears in the beginning of each command sent from the
+ * driver, and each response/notification received from uCode.
+ */
+struct iwl_cmd_header {
+	u8 cmd;		/* Command ID:  REPLY_RXON, etc. */
+	u8 flags;	/* 0:5 reserved, 6 abort, 7 internal */
+	/*
+	 * The driver sets up the sequence number to values of its choosing.
+	 * uCode does not use this value, but passes it back to the driver
+	 * when sending the response to each driver-originated command, so
+	 * the driver can match the response to the command.  Since the values
+	 * don't get used by uCode, the driver may set up an arbitrary format.
+	 *
+	 * There is one exception:  uCode sets bit 15 when it originates
+	 * the response/notification, i.e. when the response/notification
+	 * is not a direct response to a command sent by the driver.  For
+	 * example, uCode issues REPLY_3945_RX when it sends a received frame
+	 * to the driver; it is not a direct response to any driver command.
+	 *
+	 * The Linux driver uses the following format:
+	 *
+	 *  0:7		tfd index - position within TX queue
+	 *  8:12	TX queue id
+	 *  13		reserved
+	 *  14		huge - driver sets this to indicate command is in the
+	 *  		'huge' storage at the end of the command buffers
+	 *  15		unsolicited RX or uCode-originated notification
+	*/
+	__le16 sequence;
+
+	/* command or response/notification data follows immediately */
+	u8 data[0];
+} __packed;
+
+
+/**
+ * struct iwl3945_tx_power
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_SCAN_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Each entry contains two values:
+ * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
+ *     linear value that multiplies the output of the digital signal processor,
+ *     before being sent to the analog radio.
+ * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
+ *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
+ *
+ * Driver obtains values from struct iwl3945_tx_power power_gain_table[][].
+ */
+struct iwl3945_tx_power {
+	u8 tx_gain;		/* gain for analog radio */
+	u8 dsp_atten;		/* gain for DSP */
+} __packed;
+
+/**
+ * struct iwl3945_power_per_rate
+ *
+ * Used in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl3945_power_per_rate {
+	u8 rate;		/* plcp */
+	struct iwl3945_tx_power tpc;
+	u8 reserved;
+} __packed;
+
+/**
+ * iwl4965 rate_n_flags bit fields
+ *
+ * rate_n_flags format is used in following iwl4965 commands:
+ *  REPLY_RX (response only)
+ *  REPLY_RX_MPDU (response only)
+ *  REPLY_TX (both command and response)
+ *  REPLY_TX_LINK_QUALITY_CMD
+ *
+ * High-throughput (HT) rate format for bits 7:0 (bit 8 must be "1"):
+ *  2-0:  0)   6 Mbps
+ *        1)  12 Mbps
+ *        2)  18 Mbps
+ *        3)  24 Mbps
+ *        4)  36 Mbps
+ *        5)  48 Mbps
+ *        6)  54 Mbps
+ *        7)  60 Mbps
+ *
+ *  4-3:  0)  Single stream (SISO)
+ *        1)  Dual stream (MIMO)
+ *        2)  Triple stream (MIMO)
+ *
+ *    5:  Value of 0x20 in bits 7:0 indicates 6 Mbps HT40 duplicate data
+ *
+ * Legacy OFDM rate format for bits 7:0 (bit 8 must be "0", bit 9 "0"):
+ *  3-0:  0xD)   6 Mbps
+ *        0xF)   9 Mbps
+ *        0x5)  12 Mbps
+ *        0x7)  18 Mbps
+ *        0x9)  24 Mbps
+ *        0xB)  36 Mbps
+ *        0x1)  48 Mbps
+ *        0x3)  54 Mbps
+ *
+ * Legacy CCK rate format for bits 7:0 (bit 8 must be "0", bit 9 "1"):
+ *  6-0:   10)  1 Mbps
+ *         20)  2 Mbps
+ *         55)  5.5 Mbps
+ *        110)  11 Mbps
+ */
+#define RATE_MCS_CODE_MSK 0x7
+#define RATE_MCS_SPATIAL_POS 3
+#define RATE_MCS_SPATIAL_MSK 0x18
+#define RATE_MCS_HT_DUP_POS 5
+#define RATE_MCS_HT_DUP_MSK 0x20
+
+/* Bit 8: (1) HT format, (0) legacy format in bits 7:0 */
+#define RATE_MCS_FLAGS_POS 8
+#define RATE_MCS_HT_POS 8
+#define RATE_MCS_HT_MSK 0x100
+
+/* Bit 9: (1) CCK, (0) OFDM.  HT (bit 8) must be "0" for this bit to be valid */
+#define RATE_MCS_CCK_POS 9
+#define RATE_MCS_CCK_MSK 0x200
+
+/* Bit 10: (1) Use Green Field preamble */
+#define RATE_MCS_GF_POS 10
+#define RATE_MCS_GF_MSK 0x400
+
+/* Bit 11: (1) Use 40Mhz HT40 chnl width, (0) use 20 MHz legacy chnl width */
+#define RATE_MCS_HT40_POS 11
+#define RATE_MCS_HT40_MSK 0x800
+
+/* Bit 12: (1) Duplicate data on both 20MHz chnls. HT40 (bit 11) must be set. */
+#define RATE_MCS_DUP_POS 12
+#define RATE_MCS_DUP_MSK 0x1000
+
+/* Bit 13: (1) Short guard interval (0.4 usec), (0) normal GI (0.8 usec) */
+#define RATE_MCS_SGI_POS 13
+#define RATE_MCS_SGI_MSK 0x2000
+
+/**
+ * rate_n_flags Tx antenna masks
+ * 4965 has 2 transmitters
+ * bit14:16
+ */
+#define RATE_MCS_ANT_POS	14
+#define RATE_MCS_ANT_A_MSK	0x04000
+#define RATE_MCS_ANT_B_MSK	0x08000
+#define RATE_MCS_ANT_C_MSK	0x10000
+#define RATE_MCS_ANT_AB_MSK	(RATE_MCS_ANT_A_MSK | RATE_MCS_ANT_B_MSK)
+#define RATE_MCS_ANT_ABC_MSK	(RATE_MCS_ANT_AB_MSK | RATE_MCS_ANT_C_MSK)
+#define RATE_ANT_NUM 3
+
+#define POWER_TABLE_NUM_ENTRIES			33
+#define POWER_TABLE_NUM_HT_OFDM_ENTRIES		32
+#define POWER_TABLE_CCK_ENTRY			32
+
+#define IWL_PWR_NUM_HT_OFDM_ENTRIES		24
+#define IWL_PWR_CCK_ENTRIES			2
+
+/**
+ * union iwl4965_tx_power_dual_stream
+ *
+ * Host format used for REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ * Use __le32 version (struct tx_power_dual_stream) when building command.
+ *
+ * Driver provides radio gain and DSP attenuation settings to device in pairs,
+ * one value for each transmitter chain.  The first value is for transmitter A,
+ * second for transmitter B.
+ *
+ * For SISO bit rates, both values in a pair should be identical.
+ * For MIMO rates, one value may be different from the other,
+ * in order to balance the Tx output between the two transmitters.
+ *
+ * See more details in doc for TXPOWER in iwl-4965-hw.h.
+ */
+union iwl4965_tx_power_dual_stream {
+	struct {
+		u8 radio_tx_gain[2];
+		u8 dsp_predis_atten[2];
+	} s;
+	u32 dw;
+};
+
+/**
+ * struct tx_power_dual_stream
+ *
+ * Table entries in REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ *
+ * Same format as iwl_tx_power_dual_stream, but __le32
+ */
+struct tx_power_dual_stream {
+	__le32 dw;
+} __packed;
+
+/**
+ * struct iwl4965_tx_power_db
+ *
+ * Entire table within REPLY_TX_PWR_TABLE_CMD, REPLY_CHANNEL_SWITCH
+ */
+struct iwl4965_tx_power_db {
+	struct tx_power_dual_stream power_tbl[POWER_TABLE_NUM_ENTRIES];
+} __packed;
+
+/******************************************************************************
+ * (0a)
+ * Alive and Error Commands & Responses:
+ *
+ *****************************************************************************/
+
+#define UCODE_VALID_OK	cpu_to_le32(0x1)
+#define INITIALIZE_SUBTYPE    (9)
+
+/*
+ * ("Initialize") REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "initialize alive" notification once the initialization
+ * uCode image has completed its work, and is ready to load the runtime image.
+ * This is the *first* "alive" notification that the driver will receive after
+ * rebooting uCode; the "initialize" alive is indicated by subtype field == 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * For 4965, this notification contains important calibration data for
+ * calculating txpower settings:
+ *
+ * 1)  Power supply voltage indication.  The voltage sensor outputs higher
+ *     values for lower voltage, and vice verse.
+ *
+ * 2)  Temperature measurement parameters, for each of two channel widths
+ *     (20 MHz and 40 MHz) supported by the radios.  Temperature sensing
+ *     is done via one of the receiver chains, and channel width influences
+ *     the results.
+ *
+ * 3)  Tx gain compensation to balance 4965's 2 Tx chains for MIMO operation,
+ *     for each of 5 frequency ranges.
+ */
+struct iwl_init_alive_resp {
+	u8 ucode_minor;
+	u8 ucode_major;
+	__le16 reserved1;
+	u8 sw_rev[8];
+	u8 ver_type;
+	u8 ver_subtype;		/* "9" for initialize alive */
+	__le16 reserved2;
+	__le32 log_event_table_ptr;
+	__le32 error_event_table_ptr;
+	__le32 timestamp;
+	__le32 is_valid;
+
+	/* calibration values from "initialize" uCode */
+	__le32 voltage;		/* signed, higher value is lower voltage */
+	__le32 therm_r1[2];	/* signed, 1st for normal, 2nd for HT40 */
+	__le32 therm_r2[2];	/* signed */
+	__le32 therm_r3[2];	/* signed */
+	__le32 therm_r4[2];	/* signed */
+	__le32 tx_atten[5][2];	/* signed MIMO gain comp, 5 freq groups,
+				 * 2 Tx chains */
+} __packed;
+
+
+/**
+ * REPLY_ALIVE = 0x1 (response only, not a command)
+ *
+ * uCode issues this "alive" notification once the runtime image is ready
+ * to receive commands from the driver.  This is the *second* "alive"
+ * notification that the driver will receive after rebooting uCode;
+ * this "alive" is indicated by subtype field != 9.
+ *
+ * See comments documenting "BSM" (bootstrap state machine).
+ *
+ * This response includes two pointers to structures within the device's
+ * data SRAM (access via HBUS_TARG_MEM_* regs) that are useful for debugging:
+ *
+ * 1)  log_event_table_ptr indicates base of the event log.  This traces
+ *     a 256-entry history of uCode execution within a circular buffer.
+ *     Its header format is:
+ *
+ *	__le32 log_size;     log capacity (in number of entries)
+ *	__le32 type;         (1) timestamp with each entry, (0) no timestamp
+ *	__le32 wraps;        # times uCode has wrapped to top of circular buffer
+ *      __le32 write_index;  next circular buffer entry that uCode would fill
+ *
+ *     The header is followed by the circular buffer of log entries.  Entries
+ *     with timestamps have the following format:
+ *
+ *	__le32 event_id;     range 0 - 1500
+ *	__le32 timestamp;    low 32 bits of TSF (of network, if associated)
+ *	__le32 data;         event_id-specific data value
+ *
+ *     Entries without timestamps contain only event_id and data.
+ *
+ *
+ * 2)  error_event_table_ptr indicates base of the error log.  This contains
+ *     information about any uCode error that occurs.  For 4965, the format
+ *     of the error log is:
+ *
+ *	__le32 valid;        (nonzero) valid, (0) log is empty
+ *	__le32 error_id;     type of error
+ *	__le32 pc;           program counter
+ *	__le32 blink1;       branch link
+ *	__le32 blink2;       branch link
+ *	__le32 ilink1;       interrupt link
+ *	__le32 ilink2;       interrupt link
+ *	__le32 data1;        error-specific data
+ *	__le32 data2;        error-specific data
+ *	__le32 line;         source code line of error
+ *	__le32 bcon_time;    beacon timer
+ *	__le32 tsf_low;      network timestamp function timer
+ *	__le32 tsf_hi;       network timestamp function timer
+ *	__le32 gp1;          GP1 timer register
+ *	__le32 gp2;          GP2 timer register
+ *	__le32 gp3;          GP3 timer register
+ *	__le32 ucode_ver;    uCode version
+ *	__le32 hw_ver;       HW Silicon version
+ *	__le32 brd_ver;      HW board version
+ *	__le32 log_pc;       log program counter
+ *	__le32 frame_ptr;    frame pointer
+ *	__le32 stack_ptr;    stack pointer
+ *	__le32 hcmd;         last host command
+ *	__le32 isr0;         isr status register LMPM_NIC_ISR0: rxtx_flag
+ *	__le32 isr1;         isr status register LMPM_NIC_ISR1: host_flag
+ *	__le32 isr2;         isr status register LMPM_NIC_ISR2: enc_flag
+ *	__le32 isr3;         isr status register LMPM_NIC_ISR3: time_flag
+ *	__le32 isr4;         isr status register LMPM_NIC_ISR4: wico interrupt
+ *	__le32 isr_pref;     isr status register LMPM_NIC_PREF_STAT
+ *	__le32 wait_event;   wait event() caller address
+ *	__le32 l2p_control;  L2pControlField
+ *	__le32 l2p_duration; L2pDurationField
+ *	__le32 l2p_mhvalid;  L2pMhValidBits
+ *	__le32 l2p_addr_match; L2pAddrMatchStat
+ *	__le32 lmpm_pmg_sel; indicate which clocks are turned on (LMPM_PMG_SEL)
+ *	__le32 u_timestamp;  indicate when the date and time of the compilation
+ *	__le32 reserved;
+ *
+ * The Linux driver can print both logs to the system log when a uCode error
+ * occurs.
+ */
+struct iwl_alive_resp {
+	u8 ucode_minor;
+	u8 ucode_major;
+	__le16 reserved1;
+	u8 sw_rev[8];
+	u8 ver_type;
+	u8 ver_subtype;			/* not "9" for runtime alive */
+	__le16 reserved2;
+	__le32 log_event_table_ptr;	/* SRAM address for event log */
+	__le32 error_event_table_ptr;	/* SRAM address for error log */
+	__le32 timestamp;
+	__le32 is_valid;
+} __packed;
+
+/*
+ * REPLY_ERROR = 0x2 (response only, not a command)
+ */
+struct iwl_error_resp {
+	__le32 error_type;
+	u8 cmd_id;
+	u8 reserved1;
+	__le16 bad_cmd_seq_num;
+	__le32 error_info;
+	__le64 timestamp;
+} __packed;
+
+/******************************************************************************
+ * (1)
+ * RXON Commands & Responses:
+ *
+ *****************************************************************************/
+
+/*
+ * Rx config defines & structure
+ */
+/* rx_config device types  */
+enum {
+	RXON_DEV_TYPE_AP = 1,
+	RXON_DEV_TYPE_ESS = 3,
+	RXON_DEV_TYPE_IBSS = 4,
+	RXON_DEV_TYPE_SNIFFER = 6,
+};
+
+
+#define RXON_RX_CHAIN_DRIVER_FORCE_MSK		cpu_to_le16(0x1 << 0)
+#define RXON_RX_CHAIN_DRIVER_FORCE_POS		(0)
+#define RXON_RX_CHAIN_VALID_MSK			cpu_to_le16(0x7 << 1)
+#define RXON_RX_CHAIN_VALID_POS			(1)
+#define RXON_RX_CHAIN_FORCE_SEL_MSK		cpu_to_le16(0x7 << 4)
+#define RXON_RX_CHAIN_FORCE_SEL_POS		(4)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_MSK	cpu_to_le16(0x7 << 7)
+#define RXON_RX_CHAIN_FORCE_MIMO_SEL_POS	(7)
+#define RXON_RX_CHAIN_CNT_MSK			cpu_to_le16(0x3 << 10)
+#define RXON_RX_CHAIN_CNT_POS			(10)
+#define RXON_RX_CHAIN_MIMO_CNT_MSK		cpu_to_le16(0x3 << 12)
+#define RXON_RX_CHAIN_MIMO_CNT_POS		(12)
+#define RXON_RX_CHAIN_MIMO_FORCE_MSK		cpu_to_le16(0x1 << 14)
+#define RXON_RX_CHAIN_MIMO_FORCE_POS		(14)
+
+/* rx_config flags */
+/* band & modulation selection */
+#define RXON_FLG_BAND_24G_MSK           cpu_to_le32(1 << 0)
+#define RXON_FLG_CCK_MSK                cpu_to_le32(1 << 1)
+/* auto detection enable */
+#define RXON_FLG_AUTO_DETECT_MSK        cpu_to_le32(1 << 2)
+/* TGg protection when tx */
+#define RXON_FLG_TGG_PROTECT_MSK        cpu_to_le32(1 << 3)
+/* cck short slot & preamble */
+#define RXON_FLG_SHORT_SLOT_MSK          cpu_to_le32(1 << 4)
+#define RXON_FLG_SHORT_PREAMBLE_MSK     cpu_to_le32(1 << 5)
+/* antenna selection */
+#define RXON_FLG_DIS_DIV_MSK            cpu_to_le32(1 << 7)
+#define RXON_FLG_ANT_SEL_MSK            cpu_to_le32(0x0f00)
+#define RXON_FLG_ANT_A_MSK              cpu_to_le32(1 << 8)
+#define RXON_FLG_ANT_B_MSK              cpu_to_le32(1 << 9)
+/* radar detection enable */
+#define RXON_FLG_RADAR_DETECT_MSK       cpu_to_le32(1 << 12)
+#define RXON_FLG_TGJ_NARROW_BAND_MSK    cpu_to_le32(1 << 13)
+/* rx response to host with 8-byte TSF
+* (according to ON_AIR deassertion) */
+#define RXON_FLG_TSF2HOST_MSK           cpu_to_le32(1 << 15)
+
+
+/* HT flags */
+#define RXON_FLG_CTRL_CHANNEL_LOC_POS		(22)
+#define RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK	cpu_to_le32(0x1 << 22)
+
+#define RXON_FLG_HT_OPERATING_MODE_POS		(23)
+
+#define RXON_FLG_HT_PROT_MSK			cpu_to_le32(0x1 << 23)
+#define RXON_FLG_HT40_PROT_MSK			cpu_to_le32(0x2 << 23)
+
+#define RXON_FLG_CHANNEL_MODE_POS		(25)
+#define RXON_FLG_CHANNEL_MODE_MSK		cpu_to_le32(0x3 << 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)
+
+/* rx_config filter flags */
+/* accept all data frames */
+#define RXON_FILTER_PROMISC_MSK         cpu_to_le32(1 << 0)
+/* pass control & management to host */
+#define RXON_FILTER_CTL2HOST_MSK        cpu_to_le32(1 << 1)
+/* accept multi-cast */
+#define RXON_FILTER_ACCEPT_GRP_MSK      cpu_to_le32(1 << 2)
+/* don't decrypt uni-cast frames */
+#define RXON_FILTER_DIS_DECRYPT_MSK     cpu_to_le32(1 << 3)
+/* don't decrypt multi-cast frames */
+#define RXON_FILTER_DIS_GRP_DECRYPT_MSK cpu_to_le32(1 << 4)
+/* STA is associated */
+#define RXON_FILTER_ASSOC_MSK           cpu_to_le32(1 << 5)
+/* transfer to host non bssid beacons in associated state */
+#define RXON_FILTER_BCON_AWARE_MSK      cpu_to_le32(1 << 6)
+
+/**
+ * REPLY_RXON = 0x10 (command, has simple generic response)
+ *
+ * RXON tunes the radio tuner to a service channel, and sets up a number
+ * of parameters that are used primarily for Rx, but also for Tx operations.
+ *
+ * NOTE:  When tuning to a new channel, driver must set the
+ *        RXON_FILTER_ASSOC_MSK to 0.  This will clear station-dependent
+ *        info within the device, including the station tables, tx retry
+ *        rate tables, and txpower tables.  Driver must build a new station
+ *        table and txpower table before transmitting anything on the RXON
+ *        channel.
+ *
+ * NOTE:  All RXONs wipe clean the internal txpower table.  Driver must
+ *        issue a new REPLY_TX_PWR_TABLE_CMD after each REPLY_RXON (0x10),
+ *        regardless of whether RXON_FILTER_ASSOC_MSK is set.
+ */
+
+struct iwl3945_rxon_cmd {
+	u8 node_addr[6];
+	__le16 reserved1;
+	u8 bssid_addr[6];
+	__le16 reserved2;
+	u8 wlap_bssid_addr[6];
+	__le16 reserved3;
+	u8 dev_type;
+	u8 air_propagation;
+	__le16 reserved4;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 assoc_id;
+	__le32 flags;
+	__le32 filter_flags;
+	__le16 channel;
+	__le16 reserved5;
+} __packed;
+
+struct iwl4965_rxon_cmd {
+	u8 node_addr[6];
+	__le16 reserved1;
+	u8 bssid_addr[6];
+	__le16 reserved2;
+	u8 wlap_bssid_addr[6];
+	__le16 reserved3;
+	u8 dev_type;
+	u8 air_propagation;
+	__le16 rx_chain;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 assoc_id;
+	__le32 flags;
+	__le32 filter_flags;
+	__le16 channel;
+	u8 ofdm_ht_single_stream_basic_rates;
+	u8 ofdm_ht_dual_stream_basic_rates;
+} __packed;
+
+/* Create a common rxon cmd which will be typecast into the 3945 or 4965
+ * specific rxon cmd, depending on where it is called from.
+ */
+struct iwl_legacy_rxon_cmd {
+	u8 node_addr[6];
+	__le16 reserved1;
+	u8 bssid_addr[6];
+	__le16 reserved2;
+	u8 wlap_bssid_addr[6];
+	__le16 reserved3;
+	u8 dev_type;
+	u8 air_propagation;
+	__le16 rx_chain;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 assoc_id;
+	__le32 flags;
+	__le32 filter_flags;
+	__le16 channel;
+	u8 ofdm_ht_single_stream_basic_rates;
+	u8 ofdm_ht_dual_stream_basic_rates;
+	u8 reserved4;
+	u8 reserved5;
+} __packed;
+
+
+/*
+ * REPLY_RXON_ASSOC = 0x11 (command, has simple generic response)
+ */
+struct iwl3945_rxon_assoc_cmd {
+	__le32 flags;
+	__le32 filter_flags;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	__le16 reserved;
+} __packed;
+
+struct iwl4965_rxon_assoc_cmd {
+	__le32 flags;
+	__le32 filter_flags;
+	u8 ofdm_basic_rates;
+	u8 cck_basic_rates;
+	u8 ofdm_ht_single_stream_basic_rates;
+	u8 ofdm_ht_dual_stream_basic_rates;
+	__le16 rx_chain_select_flags;
+	__le16 reserved;
+} __packed;
+
+#define IWL_CONN_MAX_LISTEN_INTERVAL	10
+#define IWL_MAX_UCODE_BEACON_INTERVAL	4 /* 4096 */
+#define IWL39_MAX_UCODE_BEACON_INTERVAL	1 /* 1024 */
+
+/*
+ * REPLY_RXON_TIMING = 0x14 (command, has simple generic response)
+ */
+struct iwl_rxon_time_cmd {
+	__le64 timestamp;
+	__le16 beacon_interval;
+	__le16 atim_window;
+	__le32 beacon_init_val;
+	__le16 listen_interval;
+	u8 dtim_period;
+	u8 delta_cp_bss_tbtts;
+} __packed;
+
+/*
+ * REPLY_CHANNEL_SWITCH = 0x72 (command, has simple generic response)
+ */
+struct iwl3945_channel_switch_cmd {
+	u8 band;
+	u8 expect_beacon;
+	__le16 channel;
+	__le32 rxon_flags;
+	__le32 rxon_filter_flags;
+	__le32 switch_time;
+	struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+} __packed;
+
+struct iwl4965_channel_switch_cmd {
+	u8 band;
+	u8 expect_beacon;
+	__le16 channel;
+	__le32 rxon_flags;
+	__le32 rxon_filter_flags;
+	__le32 switch_time;
+	struct iwl4965_tx_power_db tx_power;
+} __packed;
+
+/*
+ * CHANNEL_SWITCH_NOTIFICATION = 0x73 (notification only, not a command)
+ */
+struct iwl_csa_notification {
+	__le16 band;
+	__le16 channel;
+	__le32 status;		/* 0 - OK, 1 - fail */
+} __packed;
+
+/******************************************************************************
+ * (2)
+ * Quality-of-Service (QOS) Commands & Responses:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl_ac_qos -- QOS timing params for REPLY_QOS_PARAM
+ * One for each of 4 EDCA access categories in struct iwl_qosparam_cmd
+ *
+ * @cw_min: Contention window, start value in numbers of slots.
+ *          Should be a power-of-2, minus 1.  Device's default is 0x0f.
+ * @cw_max: Contention window, max value in numbers of slots.
+ *          Should be a power-of-2, minus 1.  Device's default is 0x3f.
+ * @aifsn:  Number of slots in Arbitration Interframe Space (before
+ *          performing random backoff timing prior to Tx).  Device default 1.
+ * @edca_txop:  Length of Tx opportunity, in uSecs.  Device default is 0.
+ *
+ * Device will automatically increase contention window by (2*CW) + 1 for each
+ * transmission retry.  Device uses cw_max as a bit mask, ANDed with new CW
+ * value, to cap the CW value.
+ */
+struct iwl_ac_qos {
+	__le16 cw_min;
+	__le16 cw_max;
+	u8 aifsn;
+	u8 reserved1;
+	__le16 edca_txop;
+} __packed;
+
+/* QoS flags defines */
+#define QOS_PARAM_FLG_UPDATE_EDCA_MSK	cpu_to_le32(0x01)
+#define QOS_PARAM_FLG_TGN_MSK		cpu_to_le32(0x02)
+#define QOS_PARAM_FLG_TXOP_TYPE_MSK	cpu_to_le32(0x10)
+
+/* Number of Access Categories (AC) (EDCA), queues 0..3 */
+#define AC_NUM                4
+
+/*
+ * REPLY_QOS_PARAM = 0x13 (command, has simple generic response)
+ *
+ * This command sets up timings for each of the 4 prioritized EDCA Tx FIFOs
+ * 0: Background, 1: Best Effort, 2: Video, 3: Voice.
+ */
+struct iwl_qosparam_cmd {
+	__le32 qos_flags;
+	struct iwl_ac_qos ac[AC_NUM];
+} __packed;
+
+/******************************************************************************
+ * (3)
+ * Add/Modify Stations Commands & Responses:
+ *
+ *****************************************************************************/
+/*
+ * Multi station support
+ */
+
+/* Special, dedicated locations within device's station table */
+#define	IWL_AP_ID		0
+#define	IWL_STA_ID		2
+#define	IWL3945_BROADCAST_ID	24
+#define IWL3945_STATION_COUNT	25
+#define IWL4965_BROADCAST_ID	31
+#define	IWL4965_STATION_COUNT	32
+
+#define	IWL_STATION_COUNT	32 	/* MAX(3945,4965)*/
+#define	IWL_INVALID_STATION	255
+
+#define STA_FLG_TX_RATE_MSK		cpu_to_le32(1 << 2)
+#define STA_FLG_PWR_SAVE_MSK		cpu_to_le32(1 << 8)
+#define STA_FLG_RTS_MIMO_PROT_MSK	cpu_to_le32(1 << 17)
+#define STA_FLG_AGG_MPDU_8US_MSK	cpu_to_le32(1 << 18)
+#define STA_FLG_MAX_AGG_SIZE_POS	(19)
+#define STA_FLG_MAX_AGG_SIZE_MSK	cpu_to_le32(3 << 19)
+#define STA_FLG_HT40_EN_MSK		cpu_to_le32(1 << 21)
+#define STA_FLG_MIMO_DIS_MSK		cpu_to_le32(1 << 22)
+#define STA_FLG_AGG_MPDU_DENSITY_POS	(23)
+#define STA_FLG_AGG_MPDU_DENSITY_MSK	cpu_to_le32(7 << 23)
+
+/* Use in mode field.  1: modify existing entry, 0: add new station entry */
+#define STA_CONTROL_MODIFY_MSK		0x01
+
+/* key flags __le16*/
+#define STA_KEY_FLG_ENCRYPT_MSK	cpu_to_le16(0x0007)
+#define STA_KEY_FLG_NO_ENC	cpu_to_le16(0x0000)
+#define STA_KEY_FLG_WEP		cpu_to_le16(0x0001)
+#define STA_KEY_FLG_CCMP	cpu_to_le16(0x0002)
+#define STA_KEY_FLG_TKIP	cpu_to_le16(0x0003)
+
+#define STA_KEY_FLG_KEYID_POS	8
+#define STA_KEY_FLG_INVALID	cpu_to_le16(0x0800)
+/* wep key is either from global key (0) or from station info array (1) */
+#define STA_KEY_FLG_MAP_KEY_MSK	cpu_to_le16(0x0008)
+
+/* wep key in STA: 5-bytes (0) or 13-bytes (1) */
+#define STA_KEY_FLG_KEY_SIZE_MSK	cpu_to_le16(0x1000)
+#define STA_KEY_MULTICAST_MSK		cpu_to_le16(0x4000)
+#define STA_KEY_MAX_NUM		8
+
+/* Flags indicate whether to modify vs. don't change various station params */
+#define	STA_MODIFY_KEY_MASK		0x01
+#define	STA_MODIFY_TID_DISABLE_TX	0x02
+#define	STA_MODIFY_TX_RATE_MSK		0x04
+#define STA_MODIFY_ADDBA_TID_MSK	0x08
+#define STA_MODIFY_DELBA_TID_MSK	0x10
+#define STA_MODIFY_SLEEP_TX_COUNT_MSK	0x20
+
+/* Receiver address (actually, Rx station's index into station table),
+ * combined with Traffic ID (QOS priority), in format used by Tx Scheduler */
+#define BUILD_RAxTID(sta_id, tid)	(((sta_id) << 4) + (tid))
+
+struct iwl4965_keyinfo {
+	__le16 key_flags;
+	u8 tkip_rx_tsc_byte2;	/* TSC[2] for key mix ph1 detection */
+	u8 reserved1;
+	__le16 tkip_rx_ttak[5];	/* 10-byte unicast TKIP TTAK */
+	u8 key_offset;
+	u8 reserved2;
+	u8 key[16];		/* 16-byte unicast decryption key */
+} __packed;
+
+/**
+ * struct sta_id_modify
+ * @addr[ETH_ALEN]: station's MAC address
+ * @sta_id: index of station in uCode's station table
+ * @modify_mask: STA_MODIFY_*, 1: modify, 0: don't change
+ *
+ * Driver selects unused table index when adding new station,
+ * or the index to a pre-existing station entry when modifying that station.
+ * Some indexes have special purposes (IWL_AP_ID, index 0, is for AP).
+ *
+ * modify_mask flags select which parameters to modify vs. leave alone.
+ */
+struct sta_id_modify {
+	u8 addr[ETH_ALEN];
+	__le16 reserved1;
+	u8 sta_id;
+	u8 modify_mask;
+	__le16 reserved2;
+} __packed;
+
+/*
+ * REPLY_ADD_STA = 0x18 (command)
+ *
+ * The device contains an internal table of per-station information,
+ * with info on security keys, aggregation parameters, and Tx rates for
+ * initial Tx attempt and any retries (4965 devices uses
+ * REPLY_TX_LINK_QUALITY_CMD,
+ * 3945 uses REPLY_RATE_SCALE to set up rate tables).
+ *
+ * REPLY_ADD_STA sets up the table entry for one station, either creating
+ * a new entry, or modifying a pre-existing one.
+ *
+ * NOTE:  RXON command (without "associated" bit set) wipes the station table
+ *        clean.  Moving into RF_KILL state does this also.  Driver must set up
+ *        new station table before transmitting anything on the RXON channel
+ *        (except active scans or active measurements; those commands carry
+ *        their own txpower/rate setup data).
+ *
+ *        When getting started on a new channel, driver must set up the
+ *        IWL_BROADCAST_ID entry (last entry in the table).  For a client
+ *        station in a BSS, once an AP is selected, driver sets up the AP STA
+ *        in the IWL_AP_ID entry (1st entry in the table).  BROADCAST and AP
+ *        are all that are needed for a BSS client station.  If the device is
+ *        used as AP, or in an IBSS network, driver must set up station table
+ *        entries for all STAs in network, starting with index IWL_STA_ID.
+ */
+
+struct iwl3945_addsta_cmd {
+	u8 mode;		/* 1: modify existing, 0: add new station */
+	u8 reserved[3];
+	struct sta_id_modify sta;
+	struct iwl4965_keyinfo key;
+	__le32 station_flags;		/* STA_FLG_* */
+	__le32 station_flags_msk;	/* STA_FLG_* */
+
+	/* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+	 * corresponding to bit (e.g. bit 5 controls TID 5).
+	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+	__le16 tid_disable_tx;
+
+	__le16 rate_n_flags;
+
+	/* TID for which to add block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	u8 add_immediate_ba_tid;
+
+	/* TID for which to remove block-ack support.
+	 * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+	u8 remove_immediate_ba_tid;
+
+	/* Starting Sequence Number for added block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	__le16 add_immediate_ba_ssn;
+} __packed;
+
+struct iwl4965_addsta_cmd {
+	u8 mode;		/* 1: modify existing, 0: add new station */
+	u8 reserved[3];
+	struct sta_id_modify sta;
+	struct iwl4965_keyinfo key;
+	__le32 station_flags;		/* STA_FLG_* */
+	__le32 station_flags_msk;	/* STA_FLG_* */
+
+	/* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+	 * corresponding to bit (e.g. bit 5 controls TID 5).
+	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+	__le16 tid_disable_tx;
+
+	__le16	reserved1;
+
+	/* TID for which to add block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	u8 add_immediate_ba_tid;
+
+	/* TID for which to remove block-ack support.
+	 * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+	u8 remove_immediate_ba_tid;
+
+	/* Starting Sequence Number for added block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	__le16 add_immediate_ba_ssn;
+
+	/*
+	 * Number of packets OK to transmit to station even though
+	 * it is asleep -- used to synchronise PS-poll and u-APSD
+	 * responses while ucode keeps track of STA sleep state.
+	 */
+	__le16 sleep_tx_count;
+
+	__le16 reserved2;
+} __packed;
+
+/* Wrapper struct for 3945 and 4965 addsta_cmd structures */
+struct iwl_legacy_addsta_cmd {
+	u8 mode;		/* 1: modify existing, 0: add new station */
+	u8 reserved[3];
+	struct sta_id_modify sta;
+	struct iwl4965_keyinfo key;
+	__le32 station_flags;		/* STA_FLG_* */
+	__le32 station_flags_msk;	/* STA_FLG_* */
+
+	/* bit field to disable (1) or enable (0) Tx for Traffic ID (TID)
+	 * corresponding to bit (e.g. bit 5 controls TID 5).
+	 * Set modify_mask bit STA_MODIFY_TID_DISABLE_TX to use this field. */
+	__le16 tid_disable_tx;
+
+	__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. */
+	u8 add_immediate_ba_tid;
+
+	/* TID for which to remove block-ack support.
+	 * Set modify_mask bit STA_MODIFY_DELBA_TID_MSK to use this field. */
+	u8 remove_immediate_ba_tid;
+
+	/* Starting Sequence Number for added block-ack support.
+	 * Set modify_mask bit STA_MODIFY_ADDBA_TID_MSK to use this field. */
+	__le16 add_immediate_ba_ssn;
+
+	/*
+	 * Number of packets OK to transmit to station even though
+	 * it is asleep -- used to synchronise PS-poll and u-APSD
+	 * responses while ucode keeps track of STA sleep state.
+	 */
+	__le16 sleep_tx_count;
+
+	__le16 reserved2;
+} __packed;
+
+
+#define ADD_STA_SUCCESS_MSK		0x1
+#define ADD_STA_NO_ROOM_IN_TABLE	0x2
+#define ADD_STA_NO_BLOCK_ACK_RESOURCE	0x4
+#define ADD_STA_MODIFY_NON_EXIST_STA	0x8
+/*
+ * REPLY_ADD_STA = 0x18 (response)
+ */
+struct iwl_add_sta_resp {
+	u8 status;	/* ADD_STA_* */
+} __packed;
+
+#define REM_STA_SUCCESS_MSK              0x1
+/*
+ *  REPLY_REM_STA = 0x19 (response)
+ */
+struct iwl_rem_sta_resp {
+	u8 status;
+} __packed;
+
+/*
+ *  REPLY_REM_STA = 0x19 (command)
+ */
+struct iwl_rem_sta_cmd {
+	u8 num_sta;     /* number of removed stations */
+	u8 reserved[3];
+	u8 addr[ETH_ALEN]; /* MAC addr of the first station */
+	u8 reserved2[2];
+} __packed;
+
+#define IWL_TX_FIFO_BK_MSK		cpu_to_le32(BIT(0))
+#define IWL_TX_FIFO_BE_MSK		cpu_to_le32(BIT(1))
+#define IWL_TX_FIFO_VI_MSK		cpu_to_le32(BIT(2))
+#define IWL_TX_FIFO_VO_MSK		cpu_to_le32(BIT(3))
+#define IWL_AGG_TX_QUEUE_MSK		cpu_to_le32(0xffc00)
+
+#define IWL_DROP_SINGLE		0
+#define IWL_DROP_SELECTED	1
+#define IWL_DROP_ALL		2
+
+/*
+ * REPLY_WEP_KEY = 0x20
+ */
+struct iwl_wep_key {
+	u8 key_index;
+	u8 key_offset;
+	u8 reserved1[2];
+	u8 key_size;
+	u8 reserved2[3];
+	u8 key[16];
+} __packed;
+
+struct iwl_wep_cmd {
+	u8 num_keys;
+	u8 global_key_type;
+	u8 flags;
+	u8 reserved;
+	struct iwl_wep_key key[0];
+} __packed;
+
+#define WEP_KEY_WEP_TYPE 1
+#define WEP_KEYS_MAX 4
+#define WEP_INVALID_OFFSET 0xff
+#define WEP_KEY_LEN_64 5
+#define WEP_KEY_LEN_128 13
+
+/******************************************************************************
+ * (4)
+ * Rx Responses:
+ *
+ *****************************************************************************/
+
+#define RX_RES_STATUS_NO_CRC32_ERROR	cpu_to_le32(1 << 0)
+#define RX_RES_STATUS_NO_RXE_OVERFLOW	cpu_to_le32(1 << 1)
+
+#define RX_RES_PHY_FLAGS_BAND_24_MSK	cpu_to_le16(1 << 0)
+#define RX_RES_PHY_FLAGS_MOD_CCK_MSK		cpu_to_le16(1 << 1)
+#define RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK	cpu_to_le16(1 << 2)
+#define RX_RES_PHY_FLAGS_NARROW_BAND_MSK	cpu_to_le16(1 << 3)
+#define RX_RES_PHY_FLAGS_ANTENNA_MSK		0xf0
+#define RX_RES_PHY_FLAGS_ANTENNA_POS		4
+
+#define RX_RES_STATUS_SEC_TYPE_MSK	(0x7 << 8)
+#define RX_RES_STATUS_SEC_TYPE_NONE	(0x0 << 8)
+#define RX_RES_STATUS_SEC_TYPE_WEP	(0x1 << 8)
+#define RX_RES_STATUS_SEC_TYPE_CCMP	(0x2 << 8)
+#define RX_RES_STATUS_SEC_TYPE_TKIP	(0x3 << 8)
+#define	RX_RES_STATUS_SEC_TYPE_ERR	(0x7 << 8)
+
+#define RX_RES_STATUS_STATION_FOUND	(1<<6)
+#define RX_RES_STATUS_NO_STATION_INFO_MISMATCH	(1<<7)
+
+#define RX_RES_STATUS_DECRYPT_TYPE_MSK	(0x3 << 11)
+#define RX_RES_STATUS_NOT_DECRYPT	(0x0 << 11)
+#define RX_RES_STATUS_DECRYPT_OK	(0x3 << 11)
+#define RX_RES_STATUS_BAD_ICV_MIC	(0x1 << 11)
+#define RX_RES_STATUS_BAD_KEY_TTAK	(0x2 << 11)
+
+#define RX_MPDU_RES_STATUS_ICV_OK	(0x20)
+#define RX_MPDU_RES_STATUS_MIC_OK	(0x40)
+#define RX_MPDU_RES_STATUS_TTAK_OK	(1 << 7)
+#define RX_MPDU_RES_STATUS_DEC_DONE_MSK	(0x800)
+
+
+struct iwl3945_rx_frame_stats {
+	u8 phy_count;
+	u8 id;
+	u8 rssi;
+	u8 agc;
+	__le16 sig_avg;
+	__le16 noise_diff;
+	u8 payload[0];
+} __packed;
+
+struct iwl3945_rx_frame_hdr {
+	__le16 channel;
+	__le16 phy_flags;
+	u8 reserved1;
+	u8 rate;
+	__le16 len;
+	u8 payload[0];
+} __packed;
+
+struct iwl3945_rx_frame_end {
+	__le32 status;
+	__le64 timestamp;
+	__le32 beacon_timestamp;
+} __packed;
+
+/*
+ * REPLY_3945_RX = 0x1b (response only, not a command)
+ *
+ * NOTE:  DO NOT dereference from casts to this structure
+ * It is provided only for calculating minimum data set size.
+ * The actual offsets of the hdr and end are dynamic based on
+ * stats.phy_count
+ */
+struct iwl3945_rx_frame {
+	struct iwl3945_rx_frame_stats stats;
+	struct iwl3945_rx_frame_hdr hdr;
+	struct iwl3945_rx_frame_end end;
+} __packed;
+
+#define IWL39_RX_FRAME_SIZE	(4 + sizeof(struct iwl3945_rx_frame))
+
+/* Fixed (non-configurable) rx data from phy */
+
+#define IWL49_RX_RES_PHY_CNT 14
+#define IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET	(4)
+#define IWL49_RX_PHY_FLAGS_ANTENNAE_MASK	(0x70)
+#define IWL49_AGC_DB_MASK			(0x3f80)	/* MASK(7,13) */
+#define IWL49_AGC_DB_POS			(7)
+struct iwl4965_rx_non_cfg_phy {
+	__le16 ant_selection;	/* ant A bit 4, ant B bit 5, ant C bit 6 */
+	__le16 agc_info;	/* agc code 0:6, agc dB 7:13, reserved 14:15 */
+	u8 rssi_info[6];	/* we use even entries, 0/2/4 for A/B/C rssi */
+	u8 pad[0];
+} __packed;
+
+
+/*
+ * REPLY_RX = 0xc3 (response only, not a command)
+ * Used only for legacy (non 11n) frames.
+ */
+struct iwl_rx_phy_res {
+	u8 non_cfg_phy_cnt;     /* non configurable DSP phy data byte count */
+	u8 cfg_phy_cnt;		/* configurable DSP phy data byte count */
+	u8 stat_id;		/* configurable DSP phy data set ID */
+	u8 reserved1;
+	__le64 timestamp;	/* TSF at on air rise */
+	__le32 beacon_time_stamp; /* beacon at on-air rise */
+	__le16 phy_flags;	/* general phy flags: band, modulation, ... */
+	__le16 channel;		/* channel number */
+	u8 non_cfg_phy_buf[32]; /* for various implementations of non_cfg_phy */
+	__le32 rate_n_flags;	/* RATE_MCS_* */
+	__le16 byte_count;	/* frame's byte-count */
+	__le16 frame_time;	/* frame's time on the air */
+} __packed;
+
+struct iwl_rx_mpdu_res_start {
+	__le16 byte_count;
+	__le16 reserved;
+} __packed;
+
+
+/******************************************************************************
+ * (5)
+ * Tx Commands & Responses:
+ *
+ * Driver must place each REPLY_TX command into one of the prioritized Tx
+ * queues in host DRAM, shared between driver and device (see comments for
+ * SCD registers and Tx/Rx Queues).  When the device's Tx scheduler and uCode
+ * are preparing to transmit, the device pulls the Tx command over the PCI
+ * bus via one of the device's Tx DMA channels, to fill an internal FIFO
+ * from which data will be transmitted.
+ *
+ * uCode handles all timing and protocol related to control frames
+ * (RTS/CTS/ACK), based on flags in the Tx command.  uCode and Tx scheduler
+ * handle reception of block-acks; uCode updates the host driver via
+ * REPLY_COMPRESSED_BA.
+ *
+ * uCode handles retrying Tx when an ACK is expected but not received.
+ * This includes trying lower data rates than the one requested in the Tx
+ * command, as set up by the REPLY_RATE_SCALE (for 3945) or
+ * REPLY_TX_LINK_QUALITY_CMD (4965).
+ *
+ * Driver sets up transmit power for various rates via REPLY_TX_PWR_TABLE_CMD.
+ * This command must be executed after every RXON command, before Tx can occur.
+ *****************************************************************************/
+
+/* REPLY_TX Tx flags field */
+
+/*
+ * 1: Use Request-To-Send protocol before this frame.
+ * Mutually exclusive vs. TX_CMD_FLG_CTS_MSK.
+ */
+#define TX_CMD_FLG_RTS_MSK cpu_to_le32(1 << 1)
+
+/*
+ * 1: Transmit Clear-To-Send to self before this frame.
+ * Driver should set this for AUTH/DEAUTH/ASSOC-REQ/REASSOC mgmnt frames.
+ * Mutually exclusive vs. TX_CMD_FLG_RTS_MSK.
+ */
+#define TX_CMD_FLG_CTS_MSK cpu_to_le32(1 << 2)
+
+/* 1: Expect ACK from receiving station
+ * 0: Don't expect ACK (MAC header's duration field s/b 0)
+ * Set this for unicast frames, but not broadcast/multicast. */
+#define TX_CMD_FLG_ACK_MSK cpu_to_le32(1 << 3)
+
+/* For 4965 devices:
+ * 1: Use rate scale table (see REPLY_TX_LINK_QUALITY_CMD).
+ *    Tx command's initial_rate_index indicates first rate to try;
+ *    uCode walks through table for additional Tx attempts.
+ * 0: Use Tx rate/MCS from Tx command's rate_n_flags field.
+ *    This rate will be used for all Tx attempts; it will not be scaled. */
+#define TX_CMD_FLG_STA_RATE_MSK cpu_to_le32(1 << 4)
+
+/* 1: Expect immediate block-ack.
+ * Set when Txing a block-ack request frame.  Also set TX_CMD_FLG_ACK_MSK. */
+#define TX_CMD_FLG_IMM_BA_RSP_MASK  cpu_to_le32(1 << 6)
+
+/*
+ * 1: Frame requires full Tx-Op protection.
+ * Set this if either RTS or CTS Tx Flag gets set.
+ */
+#define TX_CMD_FLG_FULL_TXOP_PROT_MSK cpu_to_le32(1 << 7)
+
+/* Tx antenna selection field; used only for 3945, reserved (0) for 4965 devices.
+ * Set field to "0" to allow 3945 uCode to select antenna (normal usage). */
+#define TX_CMD_FLG_ANT_SEL_MSK cpu_to_le32(0xf00)
+#define TX_CMD_FLG_ANT_A_MSK cpu_to_le32(1 << 8)
+#define TX_CMD_FLG_ANT_B_MSK cpu_to_le32(1 << 9)
+
+/* 1: uCode overrides sequence control field in MAC header.
+ * 0: Driver provides sequence control field in MAC header.
+ * Set this for management frames, non-QOS data frames, non-unicast frames,
+ * and also in Tx command embedded in REPLY_SCAN_CMD for active scans. */
+#define TX_CMD_FLG_SEQ_CTL_MSK cpu_to_le32(1 << 13)
+
+/* 1: This frame is non-last MPDU; more fragments are coming.
+ * 0: Last fragment, or not using fragmentation. */
+#define TX_CMD_FLG_MORE_FRAG_MSK cpu_to_le32(1 << 14)
+
+/* 1: uCode calculates and inserts Timestamp Function (TSF) in outgoing frame.
+ * 0: No TSF required in outgoing frame.
+ * Set this for transmitting beacons and probe responses. */
+#define TX_CMD_FLG_TSF_MSK cpu_to_le32(1 << 16)
+
+/* 1: Driver inserted 2 bytes pad after the MAC header, for (required) dword
+ *    alignment of frame's payload data field.
+ * 0: No pad
+ * Set this for MAC headers with 26 or 30 bytes, i.e. those with QOS or ADDR4
+ * field (but not both).  Driver must align frame data (i.e. data following
+ * MAC header) to DWORD boundary. */
+#define TX_CMD_FLG_MH_PAD_MSK cpu_to_le32(1 << 20)
+
+/* accelerate aggregation support
+ * 0 - no CCMP encryption; 1 - CCMP encryption */
+#define TX_CMD_FLG_AGG_CCMP_MSK cpu_to_le32(1 << 22)
+
+/* HCCA-AP - disable duration overwriting. */
+#define TX_CMD_FLG_DUR_MSK cpu_to_le32(1 << 25)
+
+
+/*
+ * TX command security control
+ */
+#define TX_CMD_SEC_WEP		0x01
+#define TX_CMD_SEC_CCM		0x02
+#define TX_CMD_SEC_TKIP		0x03
+#define TX_CMD_SEC_MSK		0x03
+#define TX_CMD_SEC_SHIFT	6
+#define TX_CMD_SEC_KEY128	0x08
+
+/*
+ * security overhead sizes
+ */
+#define WEP_IV_LEN 4
+#define WEP_ICV_LEN 4
+#define CCMP_MIC_LEN 8
+#define TKIP_ICV_LEN 4
+
+/*
+ * REPLY_TX = 0x1c (command)
+ */
+
+struct iwl3945_tx_cmd {
+	/*
+	 * MPDU byte count:
+	 * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+	 * + 8 byte IV for CCM or TKIP (not used for WEP)
+	 * + Data payload
+	 * + 8-byte MIC (not used for CCM/WEP)
+	 * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
+	 *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+	 * Range: 14-2342 bytes.
+	 */
+	__le16 len;
+
+	/*
+	 * MPDU or MSDU byte count for next frame.
+	 * Used for fragmentation and bursting, but not 11n aggregation.
+	 * Same as "len", but for next frame.  Set to 0 if not applicable.
+	 */
+	__le16 next_frame_len;
+
+	__le32 tx_flags;	/* TX_CMD_FLG_* */
+
+	u8 rate;
+
+	/* Index of recipient station in uCode's station table */
+	u8 sta_id;
+	u8 tid_tspec;
+	u8 sec_ctl;
+	u8 key[16];
+	union {
+		u8 byte[8];
+		__le16 word[4];
+		__le32 dw[2];
+	} tkip_mic;
+	__le32 next_frame_info;
+	union {
+		__le32 life_time;
+		__le32 attempt;
+	} stop_time;
+	u8 supp_rates[2];
+	u8 rts_retry_limit;	/*byte 50 */
+	u8 data_retry_limit;	/*byte 51 */
+	union {
+		__le16 pm_frame_timeout;
+		__le16 attempt_duration;
+	} timeout;
+
+	/*
+	 * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+	 * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+	 */
+	__le16 driver_txop;
+
+	/*
+	 * MAC header goes here, followed by 2 bytes padding if MAC header
+	 * length is 26 or 30 bytes, followed by payload data
+	 */
+	u8 payload[0];
+	struct ieee80211_hdr hdr[0];
+} __packed;
+
+/*
+ * REPLY_TX = 0x1c (response)
+ */
+struct iwl3945_tx_resp {
+	u8 failure_rts;
+	u8 failure_frame;
+	u8 bt_kill_count;
+	u8 rate;
+	__le32 wireless_media_time;
+	__le32 status;		/* TX status */
+} __packed;
+
+
+/*
+ * 4965 uCode updates these Tx attempt count values in host DRAM.
+ * Used for managing Tx retries when expecting block-acks.
+ * Driver should set these fields to 0.
+ */
+struct iwl_dram_scratch {
+	u8 try_cnt;		/* Tx attempts */
+	u8 bt_kill_cnt;		/* Tx attempts blocked by Bluetooth device */
+	__le16 reserved;
+} __packed;
+
+struct iwl_tx_cmd {
+	/*
+	 * MPDU byte count:
+	 * MAC header (24/26/30/32 bytes) + 2 bytes pad if 26/30 header size,
+	 * + 8 byte IV for CCM or TKIP (not used for WEP)
+	 * + Data payload
+	 * + 8-byte MIC (not used for CCM/WEP)
+	 * NOTE:  Does not include Tx command bytes, post-MAC pad bytes,
+	 *        MIC (CCM) 8 bytes, ICV (WEP/TKIP/CKIP) 4 bytes, CRC 4 bytes.i
+	 * Range: 14-2342 bytes.
+	 */
+	__le16 len;
+
+	/*
+	 * MPDU or MSDU byte count for next frame.
+	 * Used for fragmentation and bursting, but not 11n aggregation.
+	 * Same as "len", but for next frame.  Set to 0 if not applicable.
+	 */
+	__le16 next_frame_len;
+
+	__le32 tx_flags;	/* TX_CMD_FLG_* */
+
+	/* uCode may modify this field of the Tx command (in host DRAM!).
+	 * Driver must also set dram_lsb_ptr and dram_msb_ptr in this cmd. */
+	struct iwl_dram_scratch scratch;
+
+	/* Rate for *all* Tx attempts, if TX_CMD_FLG_STA_RATE_MSK is cleared. */
+	__le32 rate_n_flags;	/* RATE_MCS_* */
+
+	/* Index of destination station in uCode's station table */
+	u8 sta_id;
+
+	/* Type of security encryption:  CCM or TKIP */
+	u8 sec_ctl;		/* TX_CMD_SEC_* */
+
+	/*
+	 * Index into rate table (see REPLY_TX_LINK_QUALITY_CMD) for initial
+	 * Tx attempt, if TX_CMD_FLG_STA_RATE_MSK is set.  Normally "0" for
+	 * data frames, this field may be used to selectively reduce initial
+	 * rate (via non-0 value) for special frames (e.g. management), while
+	 * still supporting rate scaling for all frames.
+	 */
+	u8 initial_rate_index;
+	u8 reserved;
+	u8 key[16];
+	__le16 next_frame_flags;
+	__le16 reserved2;
+	union {
+		__le32 life_time;
+		__le32 attempt;
+	} stop_time;
+
+	/* Host DRAM physical address pointer to "scratch" in this command.
+	 * Must be dword aligned.  "0" in dram_lsb_ptr disables usage. */
+	__le32 dram_lsb_ptr;
+	u8 dram_msb_ptr;
+
+	u8 rts_retry_limit;	/*byte 50 */
+	u8 data_retry_limit;	/*byte 51 */
+	u8 tid_tspec;
+	union {
+		__le16 pm_frame_timeout;
+		__le16 attempt_duration;
+	} timeout;
+
+	/*
+	 * Duration of EDCA burst Tx Opportunity, in 32-usec units.
+	 * Set this if txop time is not specified by HCCA protocol (e.g. by AP).
+	 */
+	__le16 driver_txop;
+
+	/*
+	 * MAC header goes here, followed by 2 bytes padding if MAC header
+	 * length is 26 or 30 bytes, followed by payload data
+	 */
+	u8 payload[0];
+	struct ieee80211_hdr hdr[0];
+} __packed;
+
+/* TX command response is sent after *3945* transmission attempts.
+ *
+ * NOTES:
+ *
+ * TX_STATUS_FAIL_NEXT_FRAG
+ *
+ * If the fragment flag in the MAC header for the frame being transmitted
+ * is set and there is insufficient time to transmit the next frame, the
+ * TX status will be returned with 'TX_STATUS_FAIL_NEXT_FRAG'.
+ *
+ * TX_STATUS_FIFO_UNDERRUN
+ *
+ * Indicates the host did not provide bytes to the FIFO fast enough while
+ * a TX was in progress.
+ *
+ * TX_STATUS_FAIL_MGMNT_ABORT
+ *
+ * This status is only possible if the ABORT ON MGMT RX parameter was
+ * set to true with the TX command.
+ *
+ * If the MSB of the status parameter is set then an abort sequence is
+ * required.  This sequence consists of the host activating the TX Abort
+ * control line, and then waiting for the TX Abort command response.  This
+ * indicates that a the device is no longer in a transmit state, and that the
+ * command FIFO has been cleared.  The host must then deactivate the TX Abort
+ * control line.  Receiving is still allowed in this case.
+ */
+enum {
+	TX_3945_STATUS_SUCCESS = 0x01,
+	TX_3945_STATUS_DIRECT_DONE = 0x02,
+	TX_3945_STATUS_FAIL_SHORT_LIMIT = 0x82,
+	TX_3945_STATUS_FAIL_LONG_LIMIT = 0x83,
+	TX_3945_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
+	TX_3945_STATUS_FAIL_MGMNT_ABORT = 0x85,
+	TX_3945_STATUS_FAIL_NEXT_FRAG = 0x86,
+	TX_3945_STATUS_FAIL_LIFE_EXPIRE = 0x87,
+	TX_3945_STATUS_FAIL_DEST_PS = 0x88,
+	TX_3945_STATUS_FAIL_ABORTED = 0x89,
+	TX_3945_STATUS_FAIL_BT_RETRY = 0x8a,
+	TX_3945_STATUS_FAIL_STA_INVALID = 0x8b,
+	TX_3945_STATUS_FAIL_FRAG_DROPPED = 0x8c,
+	TX_3945_STATUS_FAIL_TID_DISABLE = 0x8d,
+	TX_3945_STATUS_FAIL_FRAME_FLUSHED = 0x8e,
+	TX_3945_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
+	TX_3945_STATUS_FAIL_TX_LOCKED = 0x90,
+	TX_3945_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
+};
+
+/*
+ * TX command response is sent after *4965* transmission attempts.
+ *
+ * both postpone and abort status are expected behavior from uCode. there is
+ * no special operation required from driver; except for RFKILL_FLUSH,
+ * which required tx flush host command to flush all the tx frames in queues
+ */
+enum {
+	TX_STATUS_SUCCESS = 0x01,
+	TX_STATUS_DIRECT_DONE = 0x02,
+	/* postpone TX */
+	TX_STATUS_POSTPONE_DELAY = 0x40,
+	TX_STATUS_POSTPONE_FEW_BYTES = 0x41,
+	TX_STATUS_POSTPONE_QUIET_PERIOD = 0x43,
+	TX_STATUS_POSTPONE_CALC_TTAK = 0x44,
+	/* abort TX */
+	TX_STATUS_FAIL_INTERNAL_CROSSED_RETRY = 0x81,
+	TX_STATUS_FAIL_SHORT_LIMIT = 0x82,
+	TX_STATUS_FAIL_LONG_LIMIT = 0x83,
+	TX_STATUS_FAIL_FIFO_UNDERRUN = 0x84,
+	TX_STATUS_FAIL_DRAIN_FLOW = 0x85,
+	TX_STATUS_FAIL_RFKILL_FLUSH = 0x86,
+	TX_STATUS_FAIL_LIFE_EXPIRE = 0x87,
+	TX_STATUS_FAIL_DEST_PS = 0x88,
+	TX_STATUS_FAIL_HOST_ABORTED = 0x89,
+	TX_STATUS_FAIL_BT_RETRY = 0x8a,
+	TX_STATUS_FAIL_STA_INVALID = 0x8b,
+	TX_STATUS_FAIL_FRAG_DROPPED = 0x8c,
+	TX_STATUS_FAIL_TID_DISABLE = 0x8d,
+	TX_STATUS_FAIL_FIFO_FLUSHED = 0x8e,
+	TX_STATUS_FAIL_INSUFFICIENT_CF_POLL = 0x8f,
+	TX_STATUS_FAIL_PASSIVE_NO_RX = 0x90,
+	TX_STATUS_FAIL_NO_BEACON_ON_RADAR = 0x91,
+};
+
+#define	TX_PACKET_MODE_REGULAR		0x0000
+#define	TX_PACKET_MODE_BURST_SEQ	0x0100
+#define	TX_PACKET_MODE_BURST_FIRST	0x0200
+
+enum {
+	TX_POWER_PA_NOT_ACTIVE = 0x0,
+};
+
+enum {
+	TX_STATUS_MSK = 0x000000ff,		/* bits 0:7 */
+	TX_STATUS_DELAY_MSK = 0x00000040,
+	TX_STATUS_ABORT_MSK = 0x00000080,
+	TX_PACKET_MODE_MSK = 0x0000ff00,	/* bits 8:15 */
+	TX_FIFO_NUMBER_MSK = 0x00070000,	/* bits 16:18 */
+	TX_RESERVED = 0x00780000,		/* bits 19:22 */
+	TX_POWER_PA_DETECT_MSK = 0x7f800000,	/* bits 23:30 */
+	TX_ABORT_REQUIRED_MSK = 0x80000000,	/* bits 31:31 */
+};
+
+/* *******************************
+ * TX aggregation status
+ ******************************* */
+
+enum {
+	AGG_TX_STATE_TRANSMITTED = 0x00,
+	AGG_TX_STATE_UNDERRUN_MSK = 0x01,
+	AGG_TX_STATE_FEW_BYTES_MSK = 0x04,
+	AGG_TX_STATE_ABORT_MSK = 0x08,
+	AGG_TX_STATE_LAST_SENT_TTL_MSK = 0x10,
+	AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK = 0x20,
+	AGG_TX_STATE_SCD_QUERY_MSK = 0x80,
+	AGG_TX_STATE_TEST_BAD_CRC32_MSK = 0x100,
+	AGG_TX_STATE_RESPONSE_MSK = 0x1ff,
+	AGG_TX_STATE_DUMP_TX_MSK = 0x200,
+	AGG_TX_STATE_DELAY_TX_MSK = 0x400
+};
+
+#define AGG_TX_STATUS_MSK	0x00000fff	/* bits 0:11 */
+#define AGG_TX_TRY_MSK		0x0000f000	/* bits 12:15 */
+
+#define AGG_TX_STATE_LAST_SENT_MSK  (AGG_TX_STATE_LAST_SENT_TTL_MSK | \
+				     AGG_TX_STATE_LAST_SENT_TRY_CNT_MSK)
+
+/* # tx attempts for first frame in aggregation */
+#define AGG_TX_STATE_TRY_CNT_POS 12
+#define AGG_TX_STATE_TRY_CNT_MSK 0xf000
+
+/* Command ID and sequence number of Tx command for this frame */
+#define AGG_TX_STATE_SEQ_NUM_POS 16
+#define AGG_TX_STATE_SEQ_NUM_MSK 0xffff0000
+
+/*
+ * REPLY_TX = 0x1c (response)
+ *
+ * This response may be in one of two slightly different formats, indicated
+ * by the frame_count field:
+ *
+ * 1)  No aggregation (frame_count == 1).  This reports Tx results for
+ *     a single frame.  Multiple attempts, at various bit rates, may have
+ *     been made for this frame.
+ *
+ * 2)  Aggregation (frame_count > 1).  This reports Tx results for
+ *     2 or more frames that used block-acknowledge.  All frames were
+ *     transmitted at same rate.  Rate scaling may have been used if first
+ *     frame in this new agg block failed in previous agg block(s).
+ *
+ *     Note that, for aggregation, ACK (block-ack) status is not delivered here;
+ *     block-ack has not been received by the time the 4965 device records
+ *     this status.
+ *     This status relates to reasons the tx might have been blocked or aborted
+ *     within the sending station (this 4965 device), rather than whether it was
+ *     received successfully by the destination station.
+ */
+struct agg_tx_status {
+	__le16 status;
+	__le16 sequence;
+} __packed;
+
+struct iwl4965_tx_resp {
+	u8 frame_count;		/* 1 no aggregation, >1 aggregation */
+	u8 bt_kill_count;	/* # blocked by bluetooth (unused for agg) */
+	u8 failure_rts;		/* # failures due to unsuccessful RTS */
+	u8 failure_frame;	/* # failures due to no ACK (unused for agg) */
+
+	/* For non-agg:  Rate at which frame was successful.
+	 * For agg:  Rate at which all frames were transmitted. */
+	__le32 rate_n_flags;	/* RATE_MCS_*  */
+
+	/* For non-agg:  RTS + CTS + frame tx attempts time + ACK.
+	 * For agg:  RTS + CTS + aggregation tx time + block-ack time. */
+	__le16 wireless_media_time;	/* uSecs */
+
+	__le16 reserved;
+	__le32 pa_power1;	/* RF power amplifier measurement (not used) */
+	__le32 pa_power2;
+
+	/*
+	 * For non-agg:  frame status TX_STATUS_*
+	 * For agg:  status of 1st frame, AGG_TX_STATE_*; other frame status
+	 *           fields follow this one, up to frame_count.
+	 *           Bit fields:
+	 *           11- 0:  AGG_TX_STATE_* status code
+	 *           15-12:  Retry count for 1st frame in aggregation (retries
+	 *                   occur if tx failed for this frame when it was a
+	 *                   member of a previous aggregation block).  If rate
+	 *                   scaling is used, retry count indicates the rate
+	 *                   table entry used for all frames in the new agg.
+	 *           31-16:  Sequence # for this frame's Tx cmd (not SSN!)
+	 */
+	union {
+		__le32 status;
+		struct agg_tx_status agg_status[0]; /* for each agg frame */
+	} u;
+} __packed;
+
+/*
+ * REPLY_COMPRESSED_BA = 0xc5 (response only, not a command)
+ *
+ * Reports Block-Acknowledge from recipient station
+ */
+struct iwl_compressed_ba_resp {
+	__le32 sta_addr_lo32;
+	__le16 sta_addr_hi16;
+	__le16 reserved;
+
+	/* Index of recipient (BA-sending) station in uCode's station table */
+	u8 sta_id;
+	u8 tid;
+	__le16 seq_ctl;
+	__le64 bitmap;
+	__le16 scd_flow;
+	__le16 scd_ssn;
+} __packed;
+
+/*
+ * REPLY_TX_PWR_TABLE_CMD = 0x97 (command, has simple generic response)
+ *
+ * See details under "TXPOWER" in iwl-4965-hw.h.
+ */
+
+struct iwl3945_txpowertable_cmd {
+	u8 band;		/* 0: 5 GHz, 1: 2.4 GHz */
+	u8 reserved;
+	__le16 channel;
+	struct iwl3945_power_per_rate power[IWL_MAX_RATES];
+} __packed;
+
+struct iwl4965_txpowertable_cmd {
+	u8 band;		/* 0: 5 GHz, 1: 2.4 GHz */
+	u8 reserved;
+	__le16 channel;
+	struct iwl4965_tx_power_db tx_power;
+} __packed;
+
+
+/**
+ * struct iwl3945_rate_scaling_cmd - Rate Scaling Command & Response
+ *
+ * REPLY_RATE_SCALE = 0x47 (command, has simple generic response)
+ *
+ * NOTE: The table of rates passed to the uCode via the
+ * RATE_SCALE command sets up the corresponding order of
+ * rates used for all related commands, including rate
+ * masks, etc.
+ *
+ * For example, if you set 9MB (PLCP 0x0f) as the first
+ * rate in the rate table, the bit mask for that rate
+ * when passed through ofdm_basic_rates on the REPLY_RXON
+ * command would be bit 0 (1 << 0)
+ */
+struct iwl3945_rate_scaling_info {
+	__le16 rate_n_flags;
+	u8 try_cnt;
+	u8 next_rate_index;
+} __packed;
+
+struct iwl3945_rate_scaling_cmd {
+	u8 table_id;
+	u8 reserved[3];
+	struct iwl3945_rate_scaling_info table[IWL_MAX_RATES];
+} __packed;
+
+
+/*RS_NEW_API: only TLC_RTS remains and moved to bit 0 */
+#define  LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK	(1 << 0)
+
+/* # of EDCA prioritized tx fifos */
+#define  LINK_QUAL_AC_NUM AC_NUM
+
+/* # entries in rate scale table to support Tx retries */
+#define  LINK_QUAL_MAX_RETRY_NUM 16
+
+/* Tx antenna selection values */
+#define  LINK_QUAL_ANT_A_MSK (1 << 0)
+#define  LINK_QUAL_ANT_B_MSK (1 << 1)
+#define  LINK_QUAL_ANT_MSK   (LINK_QUAL_ANT_A_MSK|LINK_QUAL_ANT_B_MSK)
+
+
+/**
+ * struct iwl_link_qual_general_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl_link_qual_general_params {
+	u8 flags;
+
+	/* No entries at or above this (driver chosen) index contain MIMO */
+	u8 mimo_delimiter;
+
+	/* Best single antenna to use for single stream (legacy, SISO). */
+	u8 single_stream_ant_msk;	/* LINK_QUAL_ANT_* */
+
+	/* Best antennas to use for MIMO (unused for 4965, assumes both). */
+	u8 dual_stream_ant_msk;		/* LINK_QUAL_ANT_* */
+
+	/*
+	 * If driver needs to use different initial rates for different
+	 * EDCA QOS access categories (as implemented by tx fifos 0-3),
+	 * this table will set that up, by indicating the indexes in the
+	 * rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table at which to start.
+	 * Otherwise, driver should set all entries to 0.
+	 *
+	 * Entry usage:
+	 * 0 = Background, 1 = Best Effort (normal), 2 = Video, 3 = Voice
+	 * TX FIFOs above 3 use same value (typically 0) as TX FIFO 3.
+	 */
+	u8 start_rate_index[LINK_QUAL_AC_NUM];
+} __packed;
+
+#define LINK_QUAL_AGG_TIME_LIMIT_DEF	(4000) /* 4 milliseconds */
+#define LINK_QUAL_AGG_TIME_LIMIT_MAX	(8000)
+#define LINK_QUAL_AGG_TIME_LIMIT_MIN	(100)
+
+#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	(63)
+#define LINK_QUAL_AGG_FRAME_LIMIT_MIN	(0)
+
+/**
+ * struct iwl_link_qual_agg_params
+ *
+ * Used in REPLY_TX_LINK_QUALITY_CMD
+ */
+struct iwl_link_qual_agg_params {
+
+	/*
+	 *Maximum number of uSec in aggregation.
+	 * default set to 4000 (4 milliseconds) if not configured in .cfg
+	 */
+	__le16 agg_time_limit;
+
+	/*
+	 * Number of Tx retries allowed for a frame, before that frame will
+	 * no longer be considered for the start of an aggregation sequence
+	 * (scheduler will then try to tx it as single frame).
+	 * Driver should set this to 3.
+	 */
+	u8 agg_dis_start_th;
+
+	/*
+	 * Maximum number of frames in aggregation.
+	 * 0 = no limit (default).  1 = no aggregation.
+	 * Other values = max # frames in aggregation.
+	 */
+	u8 agg_frame_cnt_limit;
+
+	__le32 reserved;
+} __packed;
+
+/*
+ * REPLY_TX_LINK_QUALITY_CMD = 0x4e (command, has simple generic response)
+ *
+ * For 4965 devices only; 3945 uses REPLY_RATE_SCALE.
+ *
+ * Each station in the 4965 device's internal station table has its own table
+ * of 16
+ * Tx rates and modulation modes (e.g. legacy/SISO/MIMO) for retrying Tx when
+ * an ACK is not received.  This command replaces the entire table for
+ * one station.
+ *
+ * NOTE:  Station must already be in 4965 device's station table.
+ *	  Use REPLY_ADD_STA.
+ *
+ * The rate scaling procedures described below work well.  Of course, other
+ * procedures are possible, and may work better for particular environments.
+ *
+ *
+ * FILLING THE RATE TABLE
+ *
+ * Given a particular initial rate and mode, as determined by the rate
+ * scaling algorithm described below, the Linux driver uses the following
+ * formula to fill the rs_table[LINK_QUAL_MAX_RETRY_NUM] rate table in the
+ * Link Quality command:
+ *
+ *
+ * 1)  If using High-throughput (HT) (SISO or MIMO) initial rate:
+ *     a) Use this same initial rate for first 3 entries.
+ *     b) Find next lower available rate using same mode (SISO or MIMO),
+ *        use for next 3 entries.  If no lower rate available, switch to
+ *        legacy mode (no HT40 channel, no MIMO, no short guard interval).
+ *     c) If using MIMO, set command's mimo_delimiter to number of entries
+ *        using MIMO (3 or 6).
+ *     d) After trying 2 HT rates, switch to legacy mode (no HT40 channel,
+ *        no MIMO, no short guard interval), at the next lower bit rate
+ *        (e.g. if second HT bit rate was 54, try 48 legacy), and follow
+ *        legacy procedure for remaining table entries.
+ *
+ * 2)  If using legacy initial rate:
+ *     a) Use the initial rate for only one entry.
+ *     b) For each following entry, reduce the rate to next lower available
+ *        rate, until reaching the lowest available rate.
+ *     c) When reducing rate, also switch antenna selection.
+ *     d) Once lowest available rate is reached, repeat this rate until
+ *        rate table is filled (16 entries), switching antenna each entry.
+ *
+ *
+ * ACCUMULATING HISTORY
+ *
+ * The rate scaling algorithm for 4965 devices, as implemented in Linux driver,
+ * uses two sets of frame Tx success history:  One for the current/active
+ * modulation mode, and one for a speculative/search mode that is being
+ * attempted. If the speculative mode turns out to be more effective (i.e.
+ * actual transfer rate is better), then the driver continues to use the
+ * speculative mode as the new current active mode.
+ *
+ * Each history set contains, separately for each possible rate, data for a
+ * sliding window of the 62 most recent tx attempts at that rate.  The data
+ * includes a shifting bitmap of success(1)/failure(0), and sums of successful
+ * and attempted frames, from which the driver can additionally calculate a
+ * success ratio (success / attempted) and number of failures
+ * (attempted - success), and control the size of the window (attempted).
+ * The driver uses the bit map to remove successes from the success sum, as
+ * the oldest tx attempts fall out of the window.
+ *
+ * When the 4965 device makes multiple tx attempts for a given frame, each
+ * attempt might be at a different rate, and have different modulation
+ * characteristics (e.g. antenna, fat channel, short guard interval), as set
+ * up in the rate scaling table in the Link Quality command.  The driver must
+ * determine which rate table entry was used for each tx attempt, to determine
+ * which rate-specific history to update, and record only those attempts that
+ * match the modulation characteristics of the history set.
+ *
+ * When using block-ack (aggregation), all frames are transmitted at the same
+ * rate, since there is no per-attempt acknowledgment from the destination
+ * station.  The Tx response struct iwl_tx_resp indicates the Tx rate in
+ * rate_n_flags field.  After receiving a block-ack, the driver can update
+ * history for the entire block all at once.
+ *
+ *
+ * FINDING BEST STARTING RATE:
+ *
+ * When working with a selected initial modulation mode (see below), the
+ * driver attempts to find a best initial rate.  The initial rate is the
+ * first entry in the Link Quality command's rate table.
+ *
+ * 1)  Calculate actual throughput (success ratio * expected throughput, see
+ *     table below) for current initial rate.  Do this only if enough frames
+ *     have been attempted to make the value meaningful:  at least 6 failed
+ *     tx attempts, or at least 8 successes.  If not enough, don't try rate
+ *     scaling yet.
+ *
+ * 2)  Find available rates adjacent to current initial rate.  Available means:
+ *     a)  supported by hardware &&
+ *     b)  supported by association &&
+ *     c)  within any constraints selected by user
+ *
+ * 3)  Gather measured throughputs for adjacent rates.  These might not have
+ *     enough history to calculate a throughput.  That's okay, we might try
+ *     using one of them anyway!
+ *
+ * 4)  Try decreasing rate if, for current rate:
+ *     a)  success ratio is < 15% ||
+ *     b)  lower adjacent rate has better measured throughput ||
+ *     c)  higher adjacent rate has worse throughput, and lower is unmeasured
+ *
+ *     As a sanity check, if decrease was determined above, leave rate
+ *     unchanged if:
+ *     a)  lower rate unavailable
+ *     b)  success ratio at current rate > 85% (very good)
+ *     c)  current measured throughput is better than expected throughput
+ *         of lower rate (under perfect 100% tx conditions, see table below)
+ *
+ * 5)  Try increasing rate if, for current rate:
+ *     a)  success ratio is < 15% ||
+ *     b)  both adjacent rates' throughputs are unmeasured (try it!) ||
+ *     b)  higher adjacent rate has better measured throughput ||
+ *     c)  lower adjacent rate has worse throughput, and higher is unmeasured
+ *
+ *     As a sanity check, if increase was determined above, leave rate
+ *     unchanged if:
+ *     a)  success ratio at current rate < 70%.  This is not particularly
+ *         good performance; higher rate is sure to have poorer success.
+ *
+ * 6)  Re-evaluate the rate after each tx frame.  If working with block-
+ *     acknowledge, history and statistics may be calculated for the entire
+ *     block (including prior history that fits within the history windows),
+ *     before re-evaluation.
+ *
+ * FINDING BEST STARTING MODULATION MODE:
+ *
+ * After working with a modulation mode for a "while" (and doing rate scaling),
+ * the driver searches for a new initial mode in an attempt to improve
+ * throughput.  The "while" is measured by numbers of attempted frames:
+ *
+ * For legacy mode, search for new mode after:
+ *   480 successful frames, or 160 failed frames
+ * For high-throughput modes (SISO or MIMO), search for new mode after:
+ *   4500 successful frames, or 400 failed frames
+ *
+ * Mode switch possibilities are (3 for each mode):
+ *
+ * For legacy:
+ *   Change antenna, try SISO (if HT association), try MIMO (if HT association)
+ * For SISO:
+ *   Change antenna, try MIMO, try shortened guard interval (SGI)
+ * For MIMO:
+ *   Try SISO antenna A, SISO antenna B, try shortened guard interval (SGI)
+ *
+ * When trying a new mode, use the same bit rate as the old/current mode when
+ * trying antenna switches and shortened guard interval.  When switching to
+ * SISO from MIMO or legacy, or to MIMO from SISO or legacy, use a rate
+ * for which the expected throughput (under perfect conditions) is about the
+ * same or slightly better than the actual measured throughput delivered by
+ * the old/current mode.
+ *
+ * Actual throughput can be estimated by multiplying the expected throughput
+ * by the success ratio (successful / attempted tx frames).  Frame size is
+ * not considered in this calculation; it assumes that frame size will average
+ * out to be fairly consistent over several samples.  The following are
+ * metric values for expected throughput assuming 100% success ratio.
+ * Only G band has support for CCK rates:
+ *
+ *           RATE:  1    2    5   11    6   9   12   18   24   36   48   54   60
+ *
+ *              G:  7   13   35   58   40  57   72   98  121  154  177  186  186
+ *              A:  0    0    0    0   40  57   72   98  121  154  177  186  186
+ *     SISO 20MHz:  0    0    0    0   42  42   76  102  124  159  183  193  202
+ * SGI SISO 20MHz:  0    0    0    0   46  46   82  110  132  168  192  202  211
+ *     MIMO 20MHz:  0    0    0    0   74  74  123  155  179  214  236  244  251
+ * SGI MIMO 20MHz:  0    0    0    0   81  81  131  164  188  222  243  251  257
+ *     SISO 40MHz:  0    0    0    0   77  77  127  160  184  220  242  250  257
+ * SGI SISO 40MHz:  0    0    0    0   83  83  135  169  193  229  250  257  264
+ *     MIMO 40MHz:  0    0    0    0  123 123  182  214  235  264  279  285  289
+ * SGI MIMO 40MHz:  0    0    0    0  131 131  191  222  242  270  284  289  293
+ *
+ * After the new mode has been tried for a short while (minimum of 6 failed
+ * frames or 8 successful frames), compare success ratio and actual throughput
+ * estimate of the new mode with the old.  If either is better with the new
+ * mode, continue to use the new mode.
+ *
+ * Continue comparing modes until all 3 possibilities have been tried.
+ * If moving from legacy to HT, try all 3 possibilities from the new HT
+ * mode.  After trying all 3, a best mode is found.  Continue to use this mode
+ * for the longer "while" described above (e.g. 480 successful frames for
+ * legacy), and then repeat the search process.
+ *
+ */
+struct iwl_link_quality_cmd {
+
+	/* Index of destination/recipient station in uCode's station table */
+	u8 sta_id;
+	u8 reserved1;
+	__le16 control;		/* not used */
+	struct iwl_link_qual_general_params general_params;
+	struct iwl_link_qual_agg_params agg_params;
+
+	/*
+	 * Rate info; when using rate-scaling, Tx command's initial_rate_index
+	 * specifies 1st Tx rate attempted, via index into this table.
+	 * 4965 devices works its way through table when retrying Tx.
+	 */
+	struct {
+		__le32 rate_n_flags;	/* RATE_MCS_*, IWL_RATE_* */
+	} rs_table[LINK_QUAL_MAX_RETRY_NUM];
+	__le32 reserved2;
+} __packed;
+
+/*
+ * BT configuration enable flags:
+ *   bit 0 - 1: BT channel announcement enabled
+ *           0: disable
+ *   bit 1 - 1: priority of BT device enabled
+ *           0: disable
+ */
+#define BT_COEX_DISABLE (0x0)
+#define BT_ENABLE_CHANNEL_ANNOUNCE BIT(0)
+#define BT_ENABLE_PRIORITY	   BIT(1)
+
+#define BT_COEX_ENABLE  (BT_ENABLE_CHANNEL_ANNOUNCE | BT_ENABLE_PRIORITY)
+
+#define BT_LEAD_TIME_DEF (0x1E)
+
+#define BT_MAX_KILL_DEF (0x5)
+
+/*
+ * REPLY_BT_CONFIG = 0x9b (command, has simple generic response)
+ *
+ * 3945 and 4965 devices support hardware handshake with Bluetooth device on
+ * same platform.  Bluetooth device alerts wireless device when it will Tx;
+ * wireless device can delay or kill its own Tx to accommodate.
+ */
+struct iwl_bt_cmd {
+	u8 flags;
+	u8 lead_time;
+	u8 max_kill;
+	u8 reserved;
+	__le32 kill_ack_mask;
+	__le32 kill_cts_mask;
+} __packed;
+
+
+/******************************************************************************
+ * (6)
+ * Spectrum Management (802.11h) Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/*
+ * Spectrum Management
+ */
+#define MEASUREMENT_FILTER_FLAG (RXON_FILTER_PROMISC_MSK         | \
+				 RXON_FILTER_CTL2HOST_MSK        | \
+				 RXON_FILTER_ACCEPT_GRP_MSK      | \
+				 RXON_FILTER_DIS_DECRYPT_MSK     | \
+				 RXON_FILTER_DIS_GRP_DECRYPT_MSK | \
+				 RXON_FILTER_ASSOC_MSK           | \
+				 RXON_FILTER_BCON_AWARE_MSK)
+
+struct iwl_measure_channel {
+	__le32 duration;	/* measurement duration in extended beacon
+				 * format */
+	u8 channel;		/* channel to measure */
+	u8 type;		/* see enum iwl_measure_type */
+	__le16 reserved;
+} __packed;
+
+/*
+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (command)
+ */
+struct iwl_spectrum_cmd {
+	__le16 len;		/* number of bytes starting from token */
+	u8 token;		/* token id */
+	u8 id;			/* measurement id -- 0 or 1 */
+	u8 origin;		/* 0 = TGh, 1 = other, 2 = TGk */
+	u8 periodic;		/* 1 = periodic */
+	__le16 path_loss_timeout;
+	__le32 start_time;	/* start time in extended beacon format */
+	__le32 reserved2;
+	__le32 flags;		/* rxon flags */
+	__le32 filter_flags;	/* rxon filter flags */
+	__le16 channel_count;	/* minimum 1, maximum 10 */
+	__le16 reserved3;
+	struct iwl_measure_channel channels[10];
+} __packed;
+
+/*
+ * REPLY_SPECTRUM_MEASUREMENT_CMD = 0x74 (response)
+ */
+struct iwl_spectrum_resp {
+	u8 token;
+	u8 id;			/* id of the prior command replaced, or 0xff */
+	__le16 status;		/* 0 - command will be handled
+				 * 1 - cannot handle (conflicts with another
+				 *     measurement) */
+} __packed;
+
+enum iwl_measurement_state {
+	IWL_MEASUREMENT_START = 0,
+	IWL_MEASUREMENT_STOP = 1,
+};
+
+enum iwl_measurement_status {
+	IWL_MEASUREMENT_OK = 0,
+	IWL_MEASUREMENT_CONCURRENT = 1,
+	IWL_MEASUREMENT_CSA_CONFLICT = 2,
+	IWL_MEASUREMENT_TGH_CONFLICT = 3,
+	/* 4-5 reserved */
+	IWL_MEASUREMENT_STOPPED = 6,
+	IWL_MEASUREMENT_TIMEOUT = 7,
+	IWL_MEASUREMENT_PERIODIC_FAILED = 8,
+};
+
+#define NUM_ELEMENTS_IN_HISTOGRAM 8
+
+struct iwl_measurement_histogram {
+	__le32 ofdm[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 0.8usec counts */
+	__le32 cck[NUM_ELEMENTS_IN_HISTOGRAM];	/* in 1usec counts */
+} __packed;
+
+/* clear channel availability counters */
+struct iwl_measurement_cca_counters {
+	__le32 ofdm;
+	__le32 cck;
+} __packed;
+
+enum iwl_measure_type {
+	IWL_MEASURE_BASIC = (1 << 0),
+	IWL_MEASURE_CHANNEL_LOAD = (1 << 1),
+	IWL_MEASURE_HISTOGRAM_RPI = (1 << 2),
+	IWL_MEASURE_HISTOGRAM_NOISE = (1 << 3),
+	IWL_MEASURE_FRAME = (1 << 4),
+	/* bits 5:6 are reserved */
+	IWL_MEASURE_IDLE = (1 << 7),
+};
+
+/*
+ * SPECTRUM_MEASURE_NOTIFICATION = 0x75 (notification only, not a command)
+ */
+struct iwl_spectrum_notification {
+	u8 id;			/* measurement id -- 0 or 1 */
+	u8 token;
+	u8 channel_index;	/* index in measurement channel list */
+	u8 state;		/* 0 - start, 1 - stop */
+	__le32 start_time;	/* lower 32-bits of TSF */
+	u8 band;		/* 0 - 5.2GHz, 1 - 2.4GHz */
+	u8 channel;
+	u8 type;		/* see enum iwl_measurement_type */
+	u8 reserved1;
+	/* NOTE:  cca_ofdm, cca_cck, basic_type, and histogram are only only
+	 * valid if applicable for measurement type requested. */
+	__le32 cca_ofdm;	/* cca fraction time in 40Mhz clock periods */
+	__le32 cca_cck;		/* cca fraction time in 44Mhz clock periods */
+	__le32 cca_time;	/* channel load time in usecs */
+	u8 basic_type;		/* 0 - bss, 1 - ofdm preamble, 2 -
+				 * unidentified */
+	u8 reserved2[3];
+	struct iwl_measurement_histogram histogram;
+	__le32 stop_time;	/* lower 32-bits of TSF */
+	__le32 status;		/* see iwl_measurement_status */
+} __packed;
+
+/******************************************************************************
+ * (7)
+ * Power Management Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+/**
+ * struct iwl_powertable_cmd - Power Table Command
+ * @flags: See below:
+ *
+ * POWER_TABLE_CMD = 0x77 (command, has simple generic response)
+ *
+ * PM allow:
+ *   bit 0 - '0' Driver not allow power management
+ *           '1' Driver allow PM (use rest of parameters)
+ *
+ * uCode send sleep notifications:
+ *   bit 1 - '0' Don't send sleep notification
+ *           '1' send sleep notification (SEND_PM_NOTIFICATION)
+ *
+ * Sleep over DTIM
+ *   bit 2 - '0' PM have to walk up every DTIM
+ *           '1' PM could sleep over DTIM till listen Interval.
+ *
+ * PCI power managed
+ *   bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
+ *           '1' !(PCI_CFG_LINK_CTRL & 0x1)
+ *
+ * Fast PD
+ *   bit 4 - '1' Put radio to sleep when receiving frame for others
+ *
+ * Force sleep Modes
+ *   bit 31/30- '00' use both mac/xtal sleeps
+ *              '01' force Mac sleep
+ *              '10' force xtal sleep
+ *              '11' Illegal set
+ *
+ * NOTE: if sleep_interval[SLEEP_INTRVL_TABLE_SIZE-1] > DTIM period then
+ * ucode assume sleep over DTIM is allowed and we don't need to wake up
+ * for every DTIM.
+ */
+#define IWL_POWER_VEC_SIZE 5
+
+#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK	cpu_to_le16(BIT(0))
+#define IWL_POWER_POWER_SAVE_ENA_MSK		cpu_to_le16(BIT(0))
+#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK	cpu_to_le16(BIT(1))
+#define IWL_POWER_SLEEP_OVER_DTIM_MSK		cpu_to_le16(BIT(2))
+#define IWL_POWER_PCI_PM_MSK			cpu_to_le16(BIT(3))
+#define IWL_POWER_FAST_PD			cpu_to_le16(BIT(4))
+#define IWL_POWER_BEACON_FILTERING		cpu_to_le16(BIT(5))
+#define IWL_POWER_SHADOW_REG_ENA		cpu_to_le16(BIT(6))
+#define IWL_POWER_CT_KILL_SET			cpu_to_le16(BIT(7))
+
+struct iwl3945_powertable_cmd {
+	__le16 flags;
+	u8 reserved[2];
+	__le32 rx_data_timeout;
+	__le32 tx_data_timeout;
+	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
+} __packed;
+
+struct iwl_powertable_cmd {
+	__le16 flags;
+	u8 keep_alive_seconds;		/* 3945 reserved */
+	u8 debug_flags;			/* 3945 reserved */
+	__le32 rx_data_timeout;
+	__le32 tx_data_timeout;
+	__le32 sleep_interval[IWL_POWER_VEC_SIZE];
+	__le32 keep_alive_beacons;
+} __packed;
+
+/*
+ * PM_SLEEP_NOTIFICATION = 0x7A (notification only, not a command)
+ * all devices identical.
+ */
+struct iwl_sleep_notification {
+	u8 pm_sleep_mode;
+	u8 pm_wakeup_src;
+	__le16 reserved;
+	__le32 sleep_time;
+	__le32 tsf_low;
+	__le32 bcon_timer;
+} __packed;
+
+/* Sleep states.  all devices identical. */
+enum {
+	IWL_PM_NO_SLEEP = 0,
+	IWL_PM_SLP_MAC = 1,
+	IWL_PM_SLP_FULL_MAC_UNASSOCIATE = 2,
+	IWL_PM_SLP_FULL_MAC_CARD_STATE = 3,
+	IWL_PM_SLP_PHY = 4,
+	IWL_PM_SLP_REPENT = 5,
+	IWL_PM_WAKEUP_BY_TIMER = 6,
+	IWL_PM_WAKEUP_BY_DRIVER = 7,
+	IWL_PM_WAKEUP_BY_RFKILL = 8,
+	/* 3 reserved */
+	IWL_PM_NUM_OF_MODES = 12,
+};
+
+/*
+ * CARD_STATE_NOTIFICATION = 0xa1 (notification only, not a command)
+ */
+struct iwl_card_state_notif {
+	__le32 flags;
+} __packed;
+
+#define HW_CARD_DISABLED   0x01
+#define SW_CARD_DISABLED   0x02
+#define CT_CARD_DISABLED   0x04
+#define RXON_CARD_DISABLED 0x10
+
+struct iwl_ct_kill_config {
+	__le32   reserved;
+	__le32   critical_temperature_M;
+	__le32   critical_temperature_R;
+}  __packed;
+
+/******************************************************************************
+ * (8)
+ * Scan Commands, Responses, Notifications:
+ *
+ *****************************************************************************/
+
+#define SCAN_CHANNEL_TYPE_PASSIVE cpu_to_le32(0)
+#define SCAN_CHANNEL_TYPE_ACTIVE  cpu_to_le32(1)
+
+/**
+ * struct iwl_scan_channel - entry in REPLY_SCAN_CMD channel table
+ *
+ * One for each channel in the scan list.
+ * Each channel can independently select:
+ * 1)  SSID for directed active scans
+ * 2)  Txpower setting (for rate specified within Tx command)
+ * 3)  How long to stay on-channel (behavior may be modified by quiet_time,
+ *     quiet_plcp_th, good_CRC_th)
+ *
+ * To avoid uCode errors, make sure the following are true (see comments
+ * under struct iwl_scan_cmd about max_out_time and quiet_time):
+ * 1)  If using passive_dwell (i.e. passive_dwell != 0):
+ *     active_dwell <= passive_dwell (< max_out_time if max_out_time != 0)
+ * 2)  quiet_time <= active_dwell
+ * 3)  If restricting off-channel time (i.e. max_out_time !=0):
+ *     passive_dwell < max_out_time
+ *     active_dwell < max_out_time
+ */
+struct iwl3945_scan_channel {
+	/*
+	 * type is defined as:
+	 * 0:0 1 = active, 0 = passive
+	 * 1:4 SSID direct bit map; if a bit is set, then corresponding
+	 *     SSID IE is transmitted in probe request.
+	 * 5:7 reserved
+	 */
+	u8 type;
+	u8 channel;	/* band is selected by iwl3945_scan_cmd "flags" field */
+	struct iwl3945_tx_power tpc;
+	__le16 active_dwell;	/* in 1024-uSec TU (time units), typ 5-50 */
+	__le16 passive_dwell;	/* in 1024-uSec TU (time units), typ 20-500 */
+} __packed;
+
+/* set number of direct probes u8 type */
+#define IWL39_SCAN_PROBE_MASK(n) ((BIT(n) | (BIT(n) - BIT(1))))
+
+struct iwl_scan_channel {
+	/*
+	 * type is defined as:
+	 * 0:0 1 = active, 0 = passive
+	 * 1:20 SSID direct bit map; if a bit is set, then corresponding
+	 *     SSID IE is transmitted in probe request.
+	 * 21:31 reserved
+	 */
+	__le32 type;
+	__le16 channel;	/* band is selected by iwl_scan_cmd "flags" field */
+	u8 tx_gain;		/* gain for analog radio */
+	u8 dsp_atten;		/* gain for DSP */
+	__le16 active_dwell;	/* in 1024-uSec TU (time units), typ 5-50 */
+	__le16 passive_dwell;	/* in 1024-uSec TU (time units), typ 20-500 */
+} __packed;
+
+/* set number of direct probes __le32 type */
+#define IWL_SCAN_PROBE_MASK(n)	cpu_to_le32((BIT(n) | (BIT(n) - BIT(1))))
+
+/**
+ * struct iwl_ssid_ie - directed scan network information element
+ *
+ * Up to 20 of these may appear in REPLY_SCAN_CMD (Note: Only 4 are in
+ * 3945 SCAN api), selected by "type" bit field in struct iwl_scan_channel;
+ * each channel may select different ssids from among the 20 (4) entries.
+ * SSID IEs get transmitted in reverse order of entry.
+ */
+struct iwl_ssid_ie {
+	u8 id;
+	u8 len;
+	u8 ssid[32];
+} __packed;
+
+#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_DISABLED	0
+#define IWL_GOOD_CRC_TH_DEFAULT		cpu_to_le16(1)
+#define IWL_GOOD_CRC_TH_NEVER		cpu_to_le16(0xffff)
+#define IWL_MAX_SCAN_SIZE 1024
+#define IWL_MAX_CMD_SIZE 4096
+
+/*
+ * REPLY_SCAN_CMD = 0x80 (command)
+ *
+ * The hardware scan command is very powerful; the driver can set it up to
+ * maintain (relatively) normal network traffic while doing a scan in the
+ * background.  The max_out_time and suspend_time control the ratio of how
+ * long the device stays on an associated network channel ("service channel")
+ * vs. how long it's away from the service channel, i.e. tuned to other channels
+ * for scanning.
+ *
+ * max_out_time is the max time off-channel (in usec), and suspend_time
+ * is how long (in "extended beacon" format) that the scan is "suspended"
+ * after returning to the service channel.  That is, suspend_time is the
+ * time that we stay on the service channel, doing normal work, between
+ * scan segments.  The driver may set these parameters differently to support
+ * scanning when associated vs. not associated, and light vs. heavy traffic
+ * loads when associated.
+ *
+ * After receiving this command, the device's scan engine does the following;
+ *
+ * 1)  Sends SCAN_START notification to driver
+ * 2)  Checks to see if it has time to do scan for one channel
+ * 3)  Sends NULL packet, with power-save (PS) bit set to 1,
+ *     to tell AP that we're going off-channel
+ * 4)  Tunes to first channel in scan list, does active or passive scan
+ * 5)  Sends SCAN_RESULT notification to driver
+ * 6)  Checks to see if it has time to do scan on *next* channel in list
+ * 7)  Repeats 4-6 until it no longer has time to scan the next channel
+ *     before max_out_time expires
+ * 8)  Returns to service channel
+ * 9)  Sends NULL packet with PS=0 to tell AP that we're back
+ * 10) Stays on service channel until suspend_time expires
+ * 11) Repeats entire process 2-10 until list is complete
+ * 12) Sends SCAN_COMPLETE notification
+ *
+ * For fast, efficient scans, the scan command also has support for staying on
+ * a channel for just a short time, if doing active scanning and getting no
+ * responses to the transmitted probe request.  This time is controlled by
+ * quiet_time, and the number of received packets below which a channel is
+ * considered "quiet" is controlled by quiet_plcp_threshold.
+ *
+ * For active scanning on channels that have regulatory restrictions against
+ * blindly transmitting, the scan can listen before transmitting, to make sure
+ * that there is already legitimate activity on the channel.  If enough
+ * packets are cleanly received on the channel (controlled by good_CRC_th,
+ * typical value 1), the scan engine starts transmitting probe requests.
+ *
+ * Driver must use separate scan commands for 2.4 vs. 5 GHz bands.
+ *
+ * To avoid uCode errors, see timing restrictions described under
+ * struct iwl_scan_channel.
+ */
+
+struct iwl3945_scan_cmd {
+	__le16 len;
+	u8 reserved0;
+	u8 channel_count;	/* # channels in channel list */
+	__le16 quiet_time;	/* dwell only this # millisecs on quiet channel
+				 * (only for active scan) */
+	__le16 quiet_plcp_th;	/* quiet chnl is < this # pkts (typ. 1) */
+	__le16 good_CRC_th;	/* passive -> active promotion threshold */
+	__le16 reserved1;
+	__le32 max_out_time;	/* max usec to be away from associated (service)
+				 * channel */
+	__le32 suspend_time;	/* pause scan this long (in "extended beacon
+				 * format") when returning to service channel:
+				 * 3945; 31:24 # beacons, 19:0 additional usec,
+				 * 4965; 31:22 # beacons, 21:0 additional usec.
+				 */
+	__le32 flags;		/* RXON_FLG_* */
+	__le32 filter_flags;	/* RXON_FILTER_* */
+
+	/* For active scans (set to all-0s for passive scans).
+	 * Does not include payload.  Must specify Tx rate; no rate scaling. */
+	struct iwl3945_tx_cmd tx_cmd;
+
+	/* For directed active scans (set to all-0s otherwise) */
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX_3945];
+
+	/*
+	 * Probe request frame, followed by channel list.
+	 *
+	 * Size of probe request frame is specified by byte count in tx_cmd.
+	 * Channel list follows immediately after probe request frame.
+	 * Number of channels in list is specified by channel_count.
+	 * Each channel in list is of type:
+	 *
+	 * struct iwl3945_scan_channel channels[0];
+	 *
+	 * NOTE:  Only one band of channels can be scanned per pass.  You
+	 * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+	 * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+	 * before requesting another scan.
+	 */
+	u8 data[0];
+} __packed;
+
+struct iwl_scan_cmd {
+	__le16 len;
+	u8 reserved0;
+	u8 channel_count;	/* # channels in channel list */
+	__le16 quiet_time;	/* dwell only this # millisecs on quiet channel
+				 * (only for active scan) */
+	__le16 quiet_plcp_th;	/* quiet chnl is < this # pkts (typ. 1) */
+	__le16 good_CRC_th;	/* passive -> active promotion threshold */
+	__le16 rx_chain;	/* RXON_RX_CHAIN_* */
+	__le32 max_out_time;	/* max usec to be away from associated (service)
+				 * channel */
+	__le32 suspend_time;	/* pause scan this long (in "extended beacon
+				 * format") when returning to service chnl:
+				 * 3945; 31:24 # beacons, 19:0 additional usec,
+				 * 4965; 31:22 # beacons, 21:0 additional usec.
+				 */
+	__le32 flags;		/* RXON_FLG_* */
+	__le32 filter_flags;	/* RXON_FILTER_* */
+
+	/* For active scans (set to all-0s for passive scans).
+	 * Does not include payload.  Must specify Tx rate; no rate scaling. */
+	struct iwl_tx_cmd tx_cmd;
+
+	/* For directed active scans (set to all-0s otherwise) */
+	struct iwl_ssid_ie direct_scan[PROBE_OPTION_MAX];
+
+	/*
+	 * Probe request frame, followed by channel list.
+	 *
+	 * Size of probe request frame is specified by byte count in tx_cmd.
+	 * Channel list follows immediately after probe request frame.
+	 * Number of channels in list is specified by channel_count.
+	 * Each channel in list is of type:
+	 *
+	 * struct iwl_scan_channel channels[0];
+	 *
+	 * NOTE:  Only one band of channels can be scanned per pass.  You
+	 * must not mix 2.4GHz channels and 5.2GHz channels, and you must wait
+	 * for one scan to complete (i.e. receive SCAN_COMPLETE_NOTIFICATION)
+	 * before requesting another scan.
+	 */
+	u8 data[0];
+} __packed;
+
+/* Can abort will notify by complete notification with abort status. */
+#define CAN_ABORT_STATUS	cpu_to_le32(0x1)
+/* complete notification statuses */
+#define ABORT_STATUS            0x2
+
+/*
+ * REPLY_SCAN_CMD = 0x80 (response)
+ */
+struct iwl_scanreq_notification {
+	__le32 status;		/* 1: okay, 2: cannot fulfill request */
+} __packed;
+
+/*
+ * SCAN_START_NOTIFICATION = 0x82 (notification only, not a command)
+ */
+struct iwl_scanstart_notification {
+	__le32 tsf_low;
+	__le32 tsf_high;
+	__le32 beacon_timer;
+	u8 channel;
+	u8 band;
+	u8 reserved[2];
+	__le32 status;
+} __packed;
+
+#define  SCAN_OWNER_STATUS 0x1;
+#define  MEASURE_OWNER_STATUS 0x2;
+
+#define IWL_PROBE_STATUS_OK		0
+#define IWL_PROBE_STATUS_TX_FAILED	BIT(0)
+/* error statuses combined with TX_FAILED */
+#define IWL_PROBE_STATUS_FAIL_TTL	BIT(1)
+#define IWL_PROBE_STATUS_FAIL_BT	BIT(2)
+
+#define NUMBER_OF_STATISTICS 1	/* first __le32 is good CRC */
+/*
+ * SCAN_RESULTS_NOTIFICATION = 0x83 (notification only, not a command)
+ */
+struct iwl_scanresults_notification {
+	u8 channel;
+	u8 band;
+	u8 probe_status;
+	u8 num_probe_not_sent; /* not enough time to send */
+	__le32 tsf_low;
+	__le32 tsf_high;
+	__le32 statistics[NUMBER_OF_STATISTICS];
+} __packed;
+
+/*
+ * SCAN_COMPLETE_NOTIFICATION = 0x84 (notification only, not a command)
+ */
+struct iwl_scancomplete_notification {
+	u8 scanned_channels;
+	u8 status;
+	u8 last_channel;
+	__le32 tsf_low;
+	__le32 tsf_high;
+} __packed;
+
+
+/******************************************************************************
+ * (9)
+ * IBSS/AP Commands and Notifications:
+ *
+ *****************************************************************************/
+
+enum iwl_ibss_manager {
+	IWL_NOT_IBSS_MANAGER = 0,
+	IWL_IBSS_MANAGER = 1,
+};
+
+/*
+ * BEACON_NOTIFICATION = 0x90 (notification only, not a command)
+ */
+
+struct iwl3945_beacon_notif {
+	struct iwl3945_tx_resp beacon_notify_hdr;
+	__le32 low_tsf;
+	__le32 high_tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
+struct iwl4965_beacon_notif {
+	struct iwl4965_tx_resp beacon_notify_hdr;
+	__le32 low_tsf;
+	__le32 high_tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
+/*
+ * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
+ */
+
+struct iwl3945_tx_beacon_cmd {
+	struct iwl3945_tx_cmd tx;
+	__le16 tim_idx;
+	u8 tim_size;
+	u8 reserved1;
+	struct ieee80211_hdr frame[0];	/* beacon frame */
+} __packed;
+
+struct iwl_tx_beacon_cmd {
+	struct iwl_tx_cmd tx;
+	__le16 tim_idx;
+	u8 tim_size;
+	u8 reserved1;
+	struct ieee80211_hdr frame[0];	/* beacon frame */
+} __packed;
+
+/******************************************************************************
+ * (10)
+ * Statistics Commands and Notifications:
+ *
+ *****************************************************************************/
+
+#define IWL_TEMP_CONVERT 260
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+/* Used for passing to driver number of successes and failures per rate */
+struct rate_histogram {
+	union {
+		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} success;
+	union {
+		__le32 a[SUP_RATE_11A_MAX_NUM_CHANNELS];
+		__le32 b[SUP_RATE_11B_MAX_NUM_CHANNELS];
+		__le32 g[SUP_RATE_11G_MAX_NUM_CHANNELS];
+	} failed;
+} __packed;
+
+/* statistics command response */
+
+struct iwl39_statistics_rx_phy {
+	__le32 ina_cnt;
+	__le32 fina_cnt;
+	__le32 plcp_err;
+	__le32 crc32_err;
+	__le32 overrun_err;
+	__le32 early_overrun_err;
+	__le32 crc32_good;
+	__le32 false_alarm_cnt;
+	__le32 fina_sync_err_cnt;
+	__le32 sfd_timeout;
+	__le32 fina_timeout;
+	__le32 unresponded_rts;
+	__le32 rxe_frame_limit_overrun;
+	__le32 sent_ack_cnt;
+	__le32 sent_cts_cnt;
+} __packed;
+
+struct iwl39_statistics_rx_non_phy {
+	__le32 bogus_cts;	/* CTS received when not expecting CTS */
+	__le32 bogus_ack;	/* ACK received when not expecting ACK */
+	__le32 non_bssid_frames;	/* number of frames with BSSID that
+					 * doesn't belong to the STA BSSID */
+	__le32 filtered_frames;	/* count frames that were dumped in the
+				 * filtering process */
+	__le32 non_channel_beacons;	/* beacons with our bss id but not on
+					 * our serving channel */
+} __packed;
+
+struct iwl39_statistics_rx {
+	struct iwl39_statistics_rx_phy ofdm;
+	struct iwl39_statistics_rx_phy cck;
+	struct iwl39_statistics_rx_non_phy general;
+} __packed;
+
+struct iwl39_statistics_tx {
+	__le32 preamble_cnt;
+	__le32 rx_detected_cnt;
+	__le32 bt_prio_defer_cnt;
+	__le32 bt_prio_kill_cnt;
+	__le32 few_bytes_cnt;
+	__le32 cts_timeout;
+	__le32 ack_timeout;
+	__le32 expected_ack_cnt;
+	__le32 actual_ack_cnt;
+} __packed;
+
+struct statistics_dbg {
+	__le32 burst_check;
+	__le32 burst_count;
+	__le32 wait_for_silence_timeout_cnt;
+	__le32 reserved[3];
+} __packed;
+
+struct iwl39_statistics_div {
+	__le32 tx_on_a;
+	__le32 tx_on_b;
+	__le32 exec_time;
+	__le32 probe_time;
+} __packed;
+
+struct iwl39_statistics_general {
+	__le32 temperature;
+	struct statistics_dbg dbg;
+	__le32 sleep_time;
+	__le32 slots_out;
+	__le32 slots_idle;
+	__le32 ttl_timestamp;
+	struct iwl39_statistics_div div;
+} __packed;
+
+struct statistics_rx_phy {
+	__le32 ina_cnt;
+	__le32 fina_cnt;
+	__le32 plcp_err;
+	__le32 crc32_err;
+	__le32 overrun_err;
+	__le32 early_overrun_err;
+	__le32 crc32_good;
+	__le32 false_alarm_cnt;
+	__le32 fina_sync_err_cnt;
+	__le32 sfd_timeout;
+	__le32 fina_timeout;
+	__le32 unresponded_rts;
+	__le32 rxe_frame_limit_overrun;
+	__le32 sent_ack_cnt;
+	__le32 sent_cts_cnt;
+	__le32 sent_ba_rsp_cnt;
+	__le32 dsp_self_kill;
+	__le32 mh_format_err;
+	__le32 re_acq_main_rssi_sum;
+	__le32 reserved3;
+} __packed;
+
+struct statistics_rx_ht_phy {
+	__le32 plcp_err;
+	__le32 overrun_err;
+	__le32 early_overrun_err;
+	__le32 crc32_good;
+	__le32 crc32_err;
+	__le32 mh_format_err;
+	__le32 agg_crc32_good;
+	__le32 agg_mpdu_cnt;
+	__le32 agg_cnt;
+	__le32 unsupport_mcs;
+} __packed;
+
+#define INTERFERENCE_DATA_AVAILABLE      cpu_to_le32(1)
+
+struct statistics_rx_non_phy {
+	__le32 bogus_cts;	/* CTS received when not expecting CTS */
+	__le32 bogus_ack;	/* ACK received when not expecting ACK */
+	__le32 non_bssid_frames;	/* number of frames with BSSID that
+					 * doesn't belong to the STA BSSID */
+	__le32 filtered_frames;	/* count frames that were dumped in the
+				 * filtering process */
+	__le32 non_channel_beacons;	/* beacons with our bss id but not on
+					 * our serving channel */
+	__le32 channel_beacons;	/* beacons with our bss id and in our
+				 * serving channel */
+	__le32 num_missed_bcon;	/* number of missed beacons */
+	__le32 adc_rx_saturation_time;	/* count in 0.8us units the time the
+					 * ADC was in saturation */
+	__le32 ina_detection_search_time;/* total time (in 0.8us) searched
+					  * for INA */
+	__le32 beacon_silence_rssi_a;	/* RSSI silence after beacon frame */
+	__le32 beacon_silence_rssi_b;	/* RSSI silence after beacon frame */
+	__le32 beacon_silence_rssi_c;	/* RSSI silence after beacon frame */
+	__le32 interference_data_flag;	/* flag for interference data
+					 * availability. 1 when data is
+					 * available. */
+	__le32 channel_load;		/* counts RX Enable time in uSec */
+	__le32 dsp_false_alarms;	/* DSP false alarm (both OFDM
+					 * and CCK) counter */
+	__le32 beacon_rssi_a;
+	__le32 beacon_rssi_b;
+	__le32 beacon_rssi_c;
+	__le32 beacon_energy_a;
+	__le32 beacon_energy_b;
+	__le32 beacon_energy_c;
+} __packed;
+
+struct statistics_rx {
+	struct statistics_rx_phy ofdm;
+	struct statistics_rx_phy cck;
+	struct statistics_rx_non_phy general;
+	struct statistics_rx_ht_phy ofdm_ht;
+} __packed;
+
+/**
+ * struct statistics_tx_power - current tx power
+ *
+ * @ant_a: current tx power on chain a in 1/2 dB step
+ * @ant_b: current tx power on chain b in 1/2 dB step
+ * @ant_c: current tx power on chain c in 1/2 dB step
+ */
+struct statistics_tx_power {
+	u8 ant_a;
+	u8 ant_b;
+	u8 ant_c;
+	u8 reserved;
+} __packed;
+
+struct statistics_tx_non_phy_agg {
+	__le32 ba_timeout;
+	__le32 ba_reschedule_frames;
+	__le32 scd_query_agg_frame_cnt;
+	__le32 scd_query_no_agg;
+	__le32 scd_query_agg;
+	__le32 scd_query_mismatch;
+	__le32 frame_not_ready;
+	__le32 underrun;
+	__le32 bt_prio_kill;
+	__le32 rx_ba_rsp_cnt;
+} __packed;
+
+struct statistics_tx {
+	__le32 preamble_cnt;
+	__le32 rx_detected_cnt;
+	__le32 bt_prio_defer_cnt;
+	__le32 bt_prio_kill_cnt;
+	__le32 few_bytes_cnt;
+	__le32 cts_timeout;
+	__le32 ack_timeout;
+	__le32 expected_ack_cnt;
+	__le32 actual_ack_cnt;
+	__le32 dump_msdu_cnt;
+	__le32 burst_abort_next_frame_mismatch_cnt;
+	__le32 burst_abort_missing_next_frame_cnt;
+	__le32 cts_timeout_collision;
+	__le32 ack_or_ba_timeout_collision;
+	struct statistics_tx_non_phy_agg agg;
+
+	__le32 reserved1;
+} __packed;
+
+
+struct statistics_div {
+	__le32 tx_on_a;
+	__le32 tx_on_b;
+	__le32 exec_time;
+	__le32 probe_time;
+	__le32 reserved1;
+	__le32 reserved2;
+} __packed;
+
+struct statistics_general_common {
+	__le32 temperature;   /* radio temperature */
+	struct statistics_dbg dbg;
+	__le32 sleep_time;
+	__le32 slots_out;
+	__le32 slots_idle;
+	__le32 ttl_timestamp;
+	struct statistics_div div;
+	__le32 rx_enable_counter;
+	/*
+	 * num_of_sos_states:
+	 *  count the number of times we have to re-tune
+	 *  in order to get out of bad PHY status
+	 */
+	__le32 num_of_sos_states;
+} __packed;
+
+struct statistics_general {
+	struct statistics_general_common common;
+	__le32 reserved2;
+	__le32 reserved3;
+} __packed;
+
+#define UCODE_STATISTICS_CLEAR_MSK		(0x1 << 0)
+#define UCODE_STATISTICS_FREQUENCY_MSK		(0x1 << 1)
+#define UCODE_STATISTICS_NARROW_BAND_MSK	(0x1 << 2)
+
+/*
+ * REPLY_STATISTICS_CMD = 0x9c,
+ * all devices identical.
+ *
+ * This command triggers an immediate response containing uCode statistics.
+ * The response is in the same format as STATISTICS_NOTIFICATION 0x9d, below.
+ *
+ * If the CLEAR_STATS configuration flag is set, uCode will clear its
+ * internal copy of the statistics (counters) after issuing the response.
+ * This flag does not affect STATISTICS_NOTIFICATIONs after beacons (see below).
+ *
+ * If the DISABLE_NOTIF configuration flag is set, uCode will not issue
+ * STATISTICS_NOTIFICATIONs after received beacons (see below).  This flag
+ * does not affect the response to the REPLY_STATISTICS_CMD 0x9c itself.
+ */
+#define IWL_STATS_CONF_CLEAR_STATS cpu_to_le32(0x1)	/* see above */
+#define IWL_STATS_CONF_DISABLE_NOTIF cpu_to_le32(0x2)/* see above */
+struct iwl_statistics_cmd {
+	__le32 configuration_flags;	/* IWL_STATS_CONF_* */
+} __packed;
+
+/*
+ * STATISTICS_NOTIFICATION = 0x9d (notification only, not a command)
+ *
+ * By default, uCode issues this notification after receiving a beacon
+ * while associated.  To disable this behavior, set DISABLE_NOTIF flag in the
+ * REPLY_STATISTICS_CMD 0x9c, above.
+ *
+ * Statistics counters continue to increment beacon after beacon, but are
+ * cleared when changing channels or when driver issues REPLY_STATISTICS_CMD
+ * 0x9c with CLEAR_STATS bit set (see above).
+ *
+ * uCode also issues this notification during scans.  uCode clears statistics
+ * appropriately so that each notification contains statistics for only the
+ * one channel that has just been scanned.
+ */
+#define STATISTICS_REPLY_FLG_BAND_24G_MSK         cpu_to_le32(0x2)
+#define STATISTICS_REPLY_FLG_HT40_MODE_MSK        cpu_to_le32(0x8)
+
+struct iwl3945_notif_statistics {
+	__le32 flag;
+	struct iwl39_statistics_rx rx;
+	struct iwl39_statistics_tx tx;
+	struct iwl39_statistics_general general;
+} __packed;
+
+struct iwl_notif_statistics {
+	__le32 flag;
+	struct statistics_rx rx;
+	struct statistics_tx tx;
+	struct statistics_general general;
+} __packed;
+
+/*
+ * MISSED_BEACONS_NOTIFICATION = 0xa2 (notification only, not a command)
+ *
+ * uCode send MISSED_BEACONS_NOTIFICATION to driver when detect beacon missed
+ * in regardless of how many missed beacons, which mean when driver receive the
+ * notification, inside the command, it can find all the beacons information
+ * which include number of total missed beacons, number of consecutive missed
+ * beacons, number of beacons received and number of beacons expected to
+ * receive.
+ *
+ * If uCode detected consecutive_missed_beacons > 5, it will reset the radio
+ * in order to bring the radio/PHY back to working state; which has no relation
+ * to when driver will perform sensitivity calibration.
+ *
+ * Driver should set it own missed_beacon_threshold to decide when to perform
+ * sensitivity calibration based on number of consecutive missed beacons in
+ * order to improve overall performance, especially in noisy environment.
+ *
+ */
+
+#define IWL_MISSED_BEACON_THRESHOLD_MIN	(1)
+#define IWL_MISSED_BEACON_THRESHOLD_DEF	(5)
+#define IWL_MISSED_BEACON_THRESHOLD_MAX	IWL_MISSED_BEACON_THRESHOLD_DEF
+
+struct iwl_missed_beacon_notif {
+	__le32 consecutive_missed_beacons;
+	__le32 total_missed_becons;
+	__le32 num_expected_beacons;
+	__le32 num_recvd_beacons;
+} __packed;
+
+
+/******************************************************************************
+ * (11)
+ * Rx Calibration Commands:
+ *
+ * With the uCode used for open source drivers, most Tx calibration (except
+ * for Tx Power) and most Rx calibration is done by uCode during the
+ * "initialize" phase of uCode boot.  Driver must calibrate only:
+ *
+ * 1)  Tx power (depends on temperature), described elsewhere
+ * 2)  Receiver gain balance (optimize MIMO, and detect disconnected antennas)
+ * 3)  Receiver sensitivity (to optimize signal detection)
+ *
+ *****************************************************************************/
+
+/**
+ * SENSITIVITY_CMD = 0xa8 (command, has simple generic response)
+ *
+ * This command sets up the Rx signal detector for a sensitivity level that
+ * is high enough to lock onto all signals within the associated network,
+ * but low enough to ignore signals that are below a certain threshold, so as
+ * not to have too many "false alarms".  False alarms are signals that the
+ * Rx DSP tries to lock onto, but then discards after determining that they
+ * are noise.
+ *
+ * The optimum number of false alarms is between 5 and 50 per 200 TUs
+ * (200 * 1024 uSecs, i.e. 204.8 milliseconds) of actual Rx time (i.e.
+ * time listening, not transmitting).  Driver must adjust sensitivity so that
+ * the ratio of actual false alarms to actual Rx time falls within this range.
+ *
+ * While associated, uCode delivers STATISTICS_NOTIFICATIONs after each
+ * received beacon.  These provide information to the driver to analyze the
+ * sensitivity.  Don't analyze statistics that come in from scanning, or any
+ * other non-associated-network source.  Pertinent statistics include:
+ *
+ * From "general" statistics (struct statistics_rx_non_phy):
+ *
+ * (beacon_energy_[abc] & 0x0FF00) >> 8 (unsigned, higher value is lower level)
+ *   Measure of energy of desired signal.  Used for establishing a level
+ *   below which the device does not detect signals.
+ *
+ * (beacon_silence_rssi_[abc] & 0x0FF00) >> 8 (unsigned, units in dB)
+ *   Measure of background noise in silent period after beacon.
+ *
+ * channel_load
+ *   uSecs of actual Rx time during beacon period (varies according to
+ *   how much time was spent transmitting).
+ *
+ * From "cck" and "ofdm" statistics (struct statistics_rx_phy), separately:
+ *
+ * false_alarm_cnt
+ *   Signal locks abandoned early (before phy-level header).
+ *
+ * plcp_err
+ *   Signal locks abandoned late (during phy-level header).
+ *
+ * NOTE:  Both false_alarm_cnt and plcp_err increment monotonically from
+ *        beacon to beacon, i.e. each value is an accumulation of all errors
+ *        before and including the latest beacon.  Values will wrap around to 0
+ *        after counting up to 2^32 - 1.  Driver must differentiate vs.
+ *        previous beacon's values to determine # false alarms in the current
+ *        beacon period.
+ *
+ * Total number of false alarms = false_alarms + plcp_errs
+ *
+ * For OFDM, adjust the following table entries in struct iwl_sensitivity_cmd
+ * (notice that the start points for OFDM are at or close to settings for
+ * maximum sensitivity):
+ *
+ *                                             START  /  MIN  /  MAX
+ *   HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX          90   /   85  /  120
+ *   HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX     170   /  170  /  210
+ *   HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX         105   /  105  /  140
+ *   HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX     220   /  220  /  270
+ *
+ *   If actual rate of OFDM false alarms (+ plcp_errors) is too high
+ *   (greater than 50 for each 204.8 msecs listening), reduce sensitivity
+ *   by *adding* 1 to all 4 of the table entries above, up to the max for
+ *   each entry.  Conversely, if false alarm rate is too low (less than 5
+ *   for each 204.8 msecs listening), *subtract* 1 from each entry to
+ *   increase sensitivity.
+ *
+ * For CCK sensitivity, keep track of the following:
+ *
+ *   1).  20-beacon history of maximum background noise, indicated by
+ *        (beacon_silence_rssi_[abc] & 0x0FF00), units in dB, across the
+ *        3 receivers.  For any given beacon, the "silence reference" is
+ *        the maximum of last 60 samples (20 beacons * 3 receivers).
+ *
+ *   2).  10-beacon history of strongest signal level, as indicated
+ *        by (beacon_energy_[abc] & 0x0FF00) >> 8, across the 3 receivers,
+ *        i.e. the strength of the signal through the best receiver at the
+ *        moment.  These measurements are "upside down", with lower values
+ *        for stronger signals, so max energy will be *minimum* value.
+ *
+ *        Then for any given beacon, the driver must determine the *weakest*
+ *        of the strongest signals; this is the minimum level that needs to be
+ *        successfully detected, when using the best receiver at the moment.
+ *        "Max cck energy" is the maximum (higher value means lower energy!)
+ *        of the last 10 minima.  Once this is determined, driver must add
+ *        a little margin by adding "6" to it.
+ *
+ *   3).  Number of consecutive beacon periods with too few false alarms.
+ *        Reset this to 0 at the first beacon period that falls within the
+ *        "good" range (5 to 50 false alarms per 204.8 milliseconds rx).
+ *
+ * Then, adjust the following CCK table entries in struct iwl_sensitivity_cmd
+ * (notice that the start points for CCK are at maximum sensitivity):
+ *
+ *                                             START  /  MIN  /  MAX
+ *   HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX         125   /  125  /  200
+ *   HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX     200   /  200  /  400
+ *   HD_MIN_ENERGY_CCK_DET_INDEX                100   /    0  /  100
+ *
+ *   If actual rate of CCK false alarms (+ plcp_errors) is too high
+ *   (greater than 50 for each 204.8 msecs listening), method for reducing
+ *   sensitivity is:
+ *
+ *   1)  *Add* 3 to value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ *       up to max 400.
+ *
+ *   2)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is < 160,
+ *       sensitivity has been reduced a significant amount; bring it up to
+ *       a moderate 161.  Otherwise, *add* 3, up to max 200.
+ *
+ *   3)  a)  If current value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX is > 160,
+ *       sensitivity has been reduced only a moderate or small amount;
+ *       *subtract* 2 from value in HD_MIN_ENERGY_CCK_DET_INDEX,
+ *       down to min 0.  Otherwise (if gain has been significantly reduced),
+ *       don't change the HD_MIN_ENERGY_CCK_DET_INDEX value.
+ *
+ *       b)  Save a snapshot of the "silence reference".
+ *
+ *   If actual rate of CCK false alarms (+ plcp_errors) is too low
+ *   (less than 5 for each 204.8 msecs listening), method for increasing
+ *   sensitivity is used only if:
+ *
+ *   1a)  Previous beacon did not have too many false alarms
+ *   1b)  AND difference between previous "silence reference" and current
+ *        "silence reference" (prev - current) is 2 or more,
+ *   OR 2)  100 or more consecutive beacon periods have had rate of
+ *          less than 5 false alarms per 204.8 milliseconds rx time.
+ *
+ *   Method for increasing sensitivity:
+ *
+ *   1)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX,
+ *       down to min 125.
+ *
+ *   2)  *Subtract* 3 from value in HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX,
+ *       down to min 200.
+ *
+ *   3)  *Add* 2 to value in HD_MIN_ENERGY_CCK_DET_INDEX, up to max 100.
+ *
+ *   If actual rate of CCK false alarms (+ plcp_errors) is within good range
+ *   (between 5 and 50 for each 204.8 msecs listening):
+ *
+ *   1)  Save a snapshot of the silence reference.
+ *
+ *   2)  If previous beacon had too many CCK false alarms (+ plcp_errors),
+ *       give some extra margin to energy threshold by *subtracting* 8
+ *       from value in HD_MIN_ENERGY_CCK_DET_INDEX.
+ *
+ *   For all cases (too few, too many, good range), make sure that the CCK
+ *   detection threshold (energy) is below the energy level for robust
+ *   detection over the past 10 beacon periods, the "Max cck energy".
+ *   Lower values mean higher energy; this means making sure that the value
+ *   in HD_MIN_ENERGY_CCK_DET_INDEX is at or *above* "Max cck energy".
+ *
+ */
+
+/*
+ * Table entries in SENSITIVITY_CMD (struct iwl_sensitivity_cmd)
+ */
+#define HD_TABLE_SIZE  (11)	/* number of entries */
+#define HD_MIN_ENERGY_CCK_DET_INDEX                 (0)	/* table indexes */
+#define HD_MIN_ENERGY_OFDM_DET_INDEX                (1)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_INDEX          (2)
+#define HD_AUTO_CORR32_X1_TH_ADD_MIN_MRC_INDEX      (3)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_MRC_INDEX      (4)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_INDEX          (5)
+#define HD_AUTO_CORR32_X4_TH_ADD_MIN_MRC_INDEX      (6)
+#define HD_BARKER_CORR_TH_ADD_MIN_INDEX             (7)
+#define HD_BARKER_CORR_TH_ADD_MIN_MRC_INDEX         (8)
+#define HD_AUTO_CORR40_X4_TH_ADD_MIN_INDEX          (9)
+#define HD_OFDM_ENERGY_TH_IN_INDEX                  (10)
+
+/* Control field in struct iwl_sensitivity_cmd */
+#define SENSITIVITY_CMD_CONTROL_DEFAULT_TABLE	cpu_to_le16(0)
+#define SENSITIVITY_CMD_CONTROL_WORK_TABLE	cpu_to_le16(1)
+
+/**
+ * struct iwl_sensitivity_cmd
+ * @control:  (1) updates working table, (0) updates default table
+ * @table:  energy threshold values, use HD_* as index into table
+ *
+ * Always use "1" in "control" to update uCode's working table and DSP.
+ */
+struct iwl_sensitivity_cmd {
+	__le16 control;			/* always use "1" */
+	__le16 table[HD_TABLE_SIZE];	/* use HD_* as index */
+} __packed;
+
+
+/**
+ * REPLY_PHY_CALIBRATION_CMD = 0xb0 (command, has simple generic response)
+ *
+ * This command sets the relative gains of 4965 device's 3 radio receiver chains.
+ *
+ * After the first association, driver should accumulate signal and noise
+ * statistics from the STATISTICS_NOTIFICATIONs that follow the first 20
+ * beacons from the associated network (don't collect statistics that come
+ * in from scanning, or any other non-network source).
+ *
+ * DISCONNECTED ANTENNA:
+ *
+ * Driver should determine which antennas are actually connected, by comparing
+ * average beacon signal levels for the 3 Rx chains.  Accumulate (add) the
+ * following values over 20 beacons, one accumulator for each of the chains
+ * a/b/c, from struct statistics_rx_non_phy:
+ *
+ * beacon_rssi_[abc] & 0x0FF (unsigned, units in dB)
+ *
+ * Find the strongest signal from among a/b/c.  Compare the other two to the
+ * strongest.  If any signal is more than 15 dB (times 20, unless you
+ * divide the accumulated values by 20) below the strongest, the driver
+ * considers that antenna to be disconnected, and should not try to use that
+ * antenna/chain for Rx or Tx.  If both A and B seem to be disconnected,
+ * driver should declare the stronger one as connected, and attempt to use it
+ * (A and B are the only 2 Tx chains!).
+ *
+ *
+ * RX BALANCE:
+ *
+ * Driver should balance the 3 receivers (but just the ones that are connected
+ * to antennas, see above) for gain, by comparing the average signal levels
+ * detected during the silence after each beacon (background noise).
+ * Accumulate (add) the following values over 20 beacons, one accumulator for
+ * each of the chains a/b/c, from struct statistics_rx_non_phy:
+ *
+ * beacon_silence_rssi_[abc] & 0x0FF (unsigned, units in dB)
+ *
+ * Find the weakest background noise level from among a/b/c.  This Rx chain
+ * will be the reference, with 0 gain adjustment.  Attenuate other channels by
+ * finding noise difference:
+ *
+ * (accum_noise[i] - accum_noise[reference]) / 30
+ *
+ * The "30" adjusts the dB in the 20 accumulated samples to units of 1.5 dB.
+ * For use in diff_gain_[abc] fields of struct iwl_calibration_cmd, the
+ * driver should limit the difference results to a range of 0-3 (0-4.5 dB),
+ * and set bit 2 to indicate "reduce gain".  The value for the reference
+ * (weakest) chain should be "0".
+ *
+ * diff_gain_[abc] bit fields:
+ *   2: (1) reduce gain, (0) increase gain
+ * 1-0: amount of gain, units of 1.5 dB
+ */
+
+/* Phy calibration command for series */
+/* The default calibrate table size if not specified by firmware */
+#define IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE	18
+enum {
+	IWL_PHY_CALIBRATE_DIFF_GAIN_CMD		= 7,
+	IWL_MAX_STANDARD_PHY_CALIBRATE_TBL_SIZE	= 19,
+};
+
+#define IWL_MAX_PHY_CALIBRATE_TBL_SIZE		(253)
+
+struct iwl_calib_hdr {
+	u8 op_code;
+	u8 first_group;
+	u8 groups_num;
+	u8 data_valid;
+} __packed;
+
+/* IWL_PHY_CALIBRATE_DIFF_GAIN_CMD (7) */
+struct iwl_calib_diff_gain_cmd {
+	struct iwl_calib_hdr hdr;
+	s8 diff_gain_a;		/* see above */
+	s8 diff_gain_b;
+	s8 diff_gain_c;
+	u8 reserved1;
+} __packed;
+
+/******************************************************************************
+ * (12)
+ * Miscellaneous Commands:
+ *
+ *****************************************************************************/
+
+/*
+ * LEDs Command & Response
+ * REPLY_LEDS_CMD = 0x48 (command, has simple generic response)
+ *
+ * For each of 3 possible LEDs (Activity/Link/Tech, selected by "id" field),
+ * this command turns it on or off, or sets up a periodic blinking cycle.
+ */
+struct iwl_led_cmd {
+	__le32 interval;	/* "interval" in uSec */
+	u8 id;			/* 1: Activity, 2: Link, 3: Tech */
+	u8 off;			/* # intervals off while blinking;
+				 * "0", with >0 "on" value, turns LED on */
+	u8 on;			/* # intervals on while blinking;
+				 * "0", regardless of "off", turns LED off */
+	u8 reserved;
+} __packed;
+
+
+/******************************************************************************
+ * (13)
+ * Union of all expected notifications/responses:
+ *
+ *****************************************************************************/
+
+struct iwl_rx_packet {
+	/*
+	 * The first 4 bytes of the RX frame header contain both the RX frame
+	 * size and some flags.
+	 * Bit fields:
+	 * 31:    flag flush RB request
+	 * 30:    flag ignore TC (terminal counter) request
+	 * 29:    flag fast IRQ request
+	 * 28-14: Reserved
+	 * 13-00: RX frame size
+	 */
+	__le32 len_n_flags;
+	struct iwl_cmd_header hdr;
+	union {
+		struct iwl3945_rx_frame rx_frame;
+		struct iwl3945_tx_resp tx_resp;
+		struct iwl3945_beacon_notif beacon_status;
+
+		struct iwl_alive_resp alive_frame;
+		struct iwl_spectrum_notification spectrum_notif;
+		struct iwl_csa_notification csa_notif;
+		struct iwl_error_resp err_resp;
+		struct iwl_card_state_notif card_state_notif;
+		struct iwl_add_sta_resp add_sta;
+		struct iwl_rem_sta_resp rem_sta;
+		struct iwl_sleep_notification sleep_notif;
+		struct iwl_spectrum_resp spectrum;
+		struct iwl_notif_statistics stats;
+		struct iwl_compressed_ba_resp compressed_ba;
+		struct iwl_missed_beacon_notif missed_beacon;
+		__le32 status;
+		u8 raw[0];
+	} u;
+} __packed;
+
+#endif				/* __iwl_legacy_commands_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-core.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-core.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-core.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2696 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * 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/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-power.h"
+#include "iwl-sta.h"
+#include "iwl-helpers.h"
+
+
+MODULE_DESCRIPTION("iwl-legacy: common functions for 3945 and 4965");
+MODULE_VERSION(IWLWIFI_VERSION);
+MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
+MODULE_LICENSE("GPL");
+
+/*
+ * set bt_coex_active to true, uCode will do kill/defer
+ * every time the priority line is asserted (BT is sending signals on the
+ * priority line in the PCIx).
+ * set bt_coex_active to false, uCode will ignore the BT activity and
+ * perform the normal operation
+ *
+ * User might experience transmit issue on some platform due to WiFi/BT
+ * co-exist problem. The possible behaviors are:
+ *   Able to scan and finding all the available AP
+ *   Not able to associate with any AP
+ * On those platforms, WiFi communication can be restored by set
+ * "bt_coex_active" module parameter to "false"
+ *
+ * default: bt_coex_active = true (BT_COEX_ENABLE)
+ */
+static bool bt_coex_active = true;
+module_param(bt_coex_active, bool, S_IRUGO);
+MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
+
+u32 iwlegacy_debug_level;
+EXPORT_SYMBOL(iwlegacy_debug_level);
+
+const u8 iwlegacy_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
+EXPORT_SYMBOL(iwlegacy_bcast_addr);
+
+
+/* This function both allocates and initializes hw and priv. */
+struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg)
+{
+	struct iwl_priv *priv;
+	/* mac80211 allocates memory for this device instance, including
+	 *   space for this driver's private structure */
+	struct ieee80211_hw *hw;
+
+	hw = ieee80211_alloc_hw(sizeof(struct iwl_priv),
+				cfg->ops->ieee80211_ops);
+	if (hw == NULL) {
+		pr_err("%s: Can not allocate network device\n",
+		       cfg->name);
+		goto out;
+	}
+
+	priv = hw->priv;
+	priv->hw = hw;
+
+out:
+	return hw;
+}
+EXPORT_SYMBOL(iwl_legacy_alloc_all);
+
+#define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
+#define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
+static void iwl_legacy_init_ht_hw_capab(const struct iwl_priv *priv,
+			      struct ieee80211_sta_ht_cap *ht_info,
+			      enum ieee80211_band band)
+{
+	u16 max_bit_rate = 0;
+	u8 rx_chains_num = priv->hw_params.rx_chains_num;
+	u8 tx_chains_num = priv->hw_params.tx_chains_num;
+
+	ht_info->cap = 0;
+	memset(&ht_info->mcs, 0, sizeof(ht_info->mcs));
+
+	ht_info->ht_supported = true;
+
+	ht_info->cap |= IEEE80211_HT_CAP_SGI_20;
+	max_bit_rate = MAX_BIT_RATE_20_MHZ;
+	if (priv->hw_params.ht40_channel & BIT(band)) {
+		ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+		ht_info->cap |= IEEE80211_HT_CAP_SGI_40;
+		ht_info->mcs.rx_mask[4] = 0x01;
+		max_bit_rate = MAX_BIT_RATE_40_MHZ;
+	}
+
+	if (priv->cfg->mod_params->amsdu_size_8K)
+		ht_info->cap |= IEEE80211_HT_CAP_MAX_AMSDU;
+
+	ht_info->ampdu_factor = CFG_HT_RX_AMPDU_FACTOR_DEF;
+	ht_info->ampdu_density = CFG_HT_MPDU_DENSITY_DEF;
+
+	ht_info->mcs.rx_mask[0] = 0xFF;
+	if (rx_chains_num >= 2)
+		ht_info->mcs.rx_mask[1] = 0xFF;
+	if (rx_chains_num >= 3)
+		ht_info->mcs.rx_mask[2] = 0xFF;
+
+	/* Highest supported Rx data rate */
+	max_bit_rate *= rx_chains_num;
+	WARN_ON(max_bit_rate & ~IEEE80211_HT_MCS_RX_HIGHEST_MASK);
+	ht_info->mcs.rx_highest = cpu_to_le16(max_bit_rate);
+
+	/* Tx MCS capabilities */
+	ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+	if (tx_chains_num != rx_chains_num) {
+		ht_info->mcs.tx_params |= IEEE80211_HT_MCS_TX_RX_DIFF;
+		ht_info->mcs.tx_params |= ((tx_chains_num - 1) <<
+				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT);
+	}
+}
+
+/**
+ * iwl_legacy_init_geos - Initialize mac80211's geo/channel info based from eeprom
+ */
+int iwl_legacy_init_geos(struct iwl_priv *priv)
+{
+	struct iwl_channel_info *ch;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *channels;
+	struct ieee80211_channel *geo_ch;
+	struct ieee80211_rate *rates;
+	int i = 0;
+	s8 max_tx_power = 0;
+
+	if (priv->bands[IEEE80211_BAND_2GHZ].n_bitrates ||
+	    priv->bands[IEEE80211_BAND_5GHZ].n_bitrates) {
+		IWL_DEBUG_INFO(priv, "Geography modes already initialized.\n");
+		set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+		return 0;
+	}
+
+	channels = kzalloc(sizeof(struct ieee80211_channel) *
+			   priv->channel_count, GFP_KERNEL);
+	if (!channels)
+		return -ENOMEM;
+
+	rates = kzalloc((sizeof(struct ieee80211_rate) * IWL_RATE_COUNT_LEGACY),
+			GFP_KERNEL);
+	if (!rates) {
+		kfree(channels);
+		return -ENOMEM;
+	}
+
+	/* 5.2GHz channels start after the 2.4GHz channels */
+	sband = &priv->bands[IEEE80211_BAND_5GHZ];
+	sband->channels = &channels[ARRAY_SIZE(iwlegacy_eeprom_band_1)];
+	/* just OFDM */
+	sband->bitrates = &rates[IWL_FIRST_OFDM_RATE];
+	sband->n_bitrates = IWL_RATE_COUNT_LEGACY - IWL_FIRST_OFDM_RATE;
+
+	if (priv->cfg->sku & IWL_SKU_N)
+		iwl_legacy_init_ht_hw_capab(priv, &sband->ht_cap,
+					 IEEE80211_BAND_5GHZ);
+
+	sband = &priv->bands[IEEE80211_BAND_2GHZ];
+	sband->channels = channels;
+	/* OFDM & CCK */
+	sband->bitrates = rates;
+	sband->n_bitrates = IWL_RATE_COUNT_LEGACY;
+
+	if (priv->cfg->sku & IWL_SKU_N)
+		iwl_legacy_init_ht_hw_capab(priv, &sband->ht_cap,
+					 IEEE80211_BAND_2GHZ);
+
+	priv->ieee_channels = channels;
+	priv->ieee_rates = rates;
+
+	for (i = 0;  i < priv->channel_count; i++) {
+		ch = &priv->channel_info[i];
+
+		if (!iwl_legacy_is_channel_valid(ch))
+			continue;
+
+		if (iwl_legacy_is_channel_a_band(ch))
+			sband =  &priv->bands[IEEE80211_BAND_5GHZ];
+		else
+			sband =  &priv->bands[IEEE80211_BAND_2GHZ];
+
+		geo_ch = &sband->channels[sband->n_channels++];
+
+		geo_ch->center_freq =
+			ieee80211_channel_to_frequency(ch->channel, ch->band);
+		geo_ch->max_power = ch->max_power_avg;
+		geo_ch->max_antenna_gain = 0xff;
+		geo_ch->hw_value = ch->channel;
+
+		if (iwl_legacy_is_channel_valid(ch)) {
+			if (!(ch->flags & EEPROM_CHANNEL_IBSS))
+				geo_ch->flags |= IEEE80211_CHAN_NO_IBSS;
+
+			if (!(ch->flags & EEPROM_CHANNEL_ACTIVE))
+				geo_ch->flags |= IEEE80211_CHAN_PASSIVE_SCAN;
+
+			if (ch->flags & EEPROM_CHANNEL_RADAR)
+				geo_ch->flags |= IEEE80211_CHAN_RADAR;
+
+			geo_ch->flags |= ch->ht40_extension_channel;
+
+			if (ch->max_power_avg > max_tx_power)
+				max_tx_power = ch->max_power_avg;
+		} else {
+			geo_ch->flags |= IEEE80211_CHAN_DISABLED;
+		}
+
+		IWL_DEBUG_INFO(priv, "Channel %d Freq=%d[%sGHz] %s flag=0x%X\n",
+				ch->channel, geo_ch->center_freq,
+				iwl_legacy_is_channel_a_band(ch) ?  "5.2" : "2.4",
+				geo_ch->flags & IEEE80211_CHAN_DISABLED ?
+				"restricted" : "valid",
+				 geo_ch->flags);
+	}
+
+	priv->tx_power_device_lmt = max_tx_power;
+	priv->tx_power_user_lmt = max_tx_power;
+	priv->tx_power_next = max_tx_power;
+
+	if ((priv->bands[IEEE80211_BAND_5GHZ].n_channels == 0) &&
+	     priv->cfg->sku & IWL_SKU_A) {
+		IWL_INFO(priv, "Incorrectly detected BG card as ABG. "
+			"Please send your PCI ID 0x%04X:0x%04X to maintainer.\n",
+			   priv->pci_dev->device,
+			   priv->pci_dev->subsystem_device);
+		priv->cfg->sku &= ~IWL_SKU_A;
+	}
+
+	IWL_INFO(priv, "Tunable channels: %d 802.11bg, %d 802.11a channels\n",
+		   priv->bands[IEEE80211_BAND_2GHZ].n_channels,
+		   priv->bands[IEEE80211_BAND_5GHZ].n_channels);
+
+	set_bit(STATUS_GEO_CONFIGURED, &priv->status);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_init_geos);
+
+/*
+ * iwl_legacy_free_geos - undo allocations in iwl_legacy_init_geos
+ */
+void iwl_legacy_free_geos(struct iwl_priv *priv)
+{
+	kfree(priv->ieee_channels);
+	kfree(priv->ieee_rates);
+	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
+}
+EXPORT_SYMBOL(iwl_legacy_free_geos);
+
+static bool iwl_legacy_is_channel_extension(struct iwl_priv *priv,
+				     enum ieee80211_band band,
+				     u16 channel, u8 extension_chan_offset)
+{
+	const struct iwl_channel_info *ch_info;
+
+	ch_info = iwl_legacy_get_channel_info(priv, band, channel);
+	if (!iwl_legacy_is_channel_valid(ch_info))
+		return false;
+
+	if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE)
+		return !(ch_info->ht40_extension_channel &
+					IEEE80211_CHAN_NO_HT40PLUS);
+	else if (extension_chan_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW)
+		return !(ch_info->ht40_extension_channel &
+					IEEE80211_CHAN_NO_HT40MINUS);
+
+	return false;
+}
+
+bool iwl_legacy_is_ht40_tx_allowed(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_sta_ht_cap *ht_cap)
+{
+	if (!ctx->ht.enabled || !ctx->ht.is_40mhz)
+		return false;
+
+	/*
+	 * We do not check for IEEE80211_HT_CAP_SUP_WIDTH_20_40
+	 * the bit will not set if it is pure 40MHz case
+	 */
+	if (ht_cap && !ht_cap->ht_supported)
+		return false;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	if (priv->disable_ht40)
+		return false;
+#endif
+
+	return iwl_legacy_is_channel_extension(priv, priv->band,
+			le16_to_cpu(ctx->staging.channel),
+			ctx->ht.extension_chan_offset);
+}
+EXPORT_SYMBOL(iwl_legacy_is_ht40_tx_allowed);
+
+static u16 iwl_legacy_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
+{
+	u16 new_val;
+	u16 beacon_factor;
+
+	/*
+	 * If mac80211 hasn't given us a beacon interval, program
+	 * the default into the device.
+	 */
+	if (!beacon_val)
+		return DEFAULT_BEACON_INTERVAL;
+
+	/*
+	 * If the beacon interval we obtained from the peer
+	 * is too large, we'll have to wake up more often
+	 * (and in IBSS case, we'll beacon too much)
+	 *
+	 * For example, if max_beacon_val is 4096, and the
+	 * requested beacon interval is 7000, we'll have to
+	 * use 3500 to be able to wake up on the beacons.
+	 *
+	 * This could badly influence beacon detection stats.
+	 */
+
+	beacon_factor = (beacon_val + max_beacon_val) / max_beacon_val;
+	new_val = beacon_val / beacon_factor;
+
+	if (!new_val)
+		new_val = max_beacon_val;
+
+	return new_val;
+}
+
+int
+iwl_legacy_send_rxon_timing(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	u64 tsf;
+	s32 interval_tm, rem;
+	struct ieee80211_conf *conf = NULL;
+	u16 beacon_int;
+	struct ieee80211_vif *vif = ctx->vif;
+
+	conf = iwl_legacy_ieee80211_get_hw_conf(priv->hw);
+
+	lockdep_assert_held(&priv->mutex);
+
+	memset(&ctx->timing, 0, sizeof(struct iwl_rxon_time_cmd));
+
+	ctx->timing.timestamp = cpu_to_le64(priv->timestamp);
+	ctx->timing.listen_interval = cpu_to_le16(conf->listen_interval);
+
+	beacon_int = vif ? vif->bss_conf.beacon_int : 0;
+
+	/*
+	 * TODO: For IBSS we need to get atim_window from mac80211,
+	 *	 for now just always use 0
+	 */
+	ctx->timing.atim_window = 0;
+
+	beacon_int = iwl_legacy_adjust_beacon_interval(beacon_int,
+			priv->hw_params.max_beacon_itrvl * TIME_UNIT);
+	ctx->timing.beacon_interval = cpu_to_le16(beacon_int);
+
+	tsf = priv->timestamp; /* tsf is modifed by do_div: copy it */
+	interval_tm = beacon_int * TIME_UNIT;
+	rem = do_div(tsf, interval_tm);
+	ctx->timing.beacon_init_val = cpu_to_le32(interval_tm - rem);
+
+	ctx->timing.dtim_period = vif ? (vif->bss_conf.dtim_period ?: 1) : 1;
+
+	IWL_DEBUG_ASSOC(priv,
+			"beacon interval %d beacon timer %d beacon tim %d\n",
+			le16_to_cpu(ctx->timing.beacon_interval),
+			le32_to_cpu(ctx->timing.beacon_init_val),
+			le16_to_cpu(ctx->timing.atim_window));
+
+	return iwl_legacy_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
+				sizeof(ctx->timing), &ctx->timing);
+}
+EXPORT_SYMBOL(iwl_legacy_send_rxon_timing);
+
+void
+iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx,
+				int hw_decrypt)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+
+	if (hw_decrypt)
+		rxon->filter_flags &= ~RXON_FILTER_DIS_DECRYPT_MSK;
+	else
+		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
+
+}
+EXPORT_SYMBOL(iwl_legacy_set_rxon_hwcrypto);
+
+/* validate RXON structure is valid */
+int
+iwl_legacy_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+	bool error = false;
+
+	if (rxon->flags & RXON_FLG_BAND_24G_MSK) {
+		if (rxon->flags & RXON_FLG_TGJ_NARROW_BAND_MSK) {
+			IWL_WARN(priv, "check 2.4G: wrong narrow\n");
+			error = true;
+		}
+		if (rxon->flags & RXON_FLG_RADAR_DETECT_MSK) {
+			IWL_WARN(priv, "check 2.4G: wrong radar\n");
+			error = true;
+		}
+	} else {
+		if (!(rxon->flags & RXON_FLG_SHORT_SLOT_MSK)) {
+			IWL_WARN(priv, "check 5.2G: not short slot!\n");
+			error = true;
+		}
+		if (rxon->flags & RXON_FLG_CCK_MSK) {
+			IWL_WARN(priv, "check 5.2G: CCK!\n");
+			error = true;
+		}
+	}
+	if ((rxon->node_addr[0] | rxon->bssid_addr[0]) & 0x1) {
+		IWL_WARN(priv, "mac/bssid mcast!\n");
+		error = true;
+	}
+
+	/* make sure basic rates 6Mbps and 1Mbps are supported */
+	if ((rxon->ofdm_basic_rates & IWL_RATE_6M_MASK) == 0 &&
+	    (rxon->cck_basic_rates & IWL_RATE_1M_MASK) == 0) {
+		IWL_WARN(priv, "neither 1 nor 6 are basic\n");
+		error = true;
+	}
+
+	if (le16_to_cpu(rxon->assoc_id) > 2007) {
+		IWL_WARN(priv, "aid > 2007\n");
+		error = true;
+	}
+
+	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK))
+			== (RXON_FLG_CCK_MSK | RXON_FLG_SHORT_SLOT_MSK)) {
+		IWL_WARN(priv, "CCK and short slot\n");
+		error = true;
+	}
+
+	if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
+			== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
+		IWL_WARN(priv, "CCK and auto detect");
+		error = true;
+	}
+
+	if ((rxon->flags & (RXON_FLG_AUTO_DETECT_MSK |
+			    RXON_FLG_TGG_PROTECT_MSK)) ==
+			    RXON_FLG_TGG_PROTECT_MSK) {
+		IWL_WARN(priv, "TGg but no auto-detect\n");
+		error = true;
+	}
+
+	if (error)
+		IWL_WARN(priv, "Tuning to channel %d\n",
+			    le16_to_cpu(rxon->channel));
+
+	if (error) {
+		IWL_ERR(priv, "Invalid RXON\n");
+		return -EINVAL;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_check_rxon_cmd);
+
+/**
+ * iwl_legacy_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
+ * @priv: staging_rxon is compared to active_rxon
+ *
+ * If the RXON structure is changing enough to require a new tune,
+ * or is clearing the RXON_FILTER_ASSOC_MSK, then return 1 to indicate that
+ * a new tune (full RXON command, rather than RXON_ASSOC cmd) is required.
+ */
+int iwl_legacy_full_rxon_required(struct iwl_priv *priv,
+			   struct iwl_rxon_context *ctx)
+{
+	const struct iwl_legacy_rxon_cmd *staging = &ctx->staging;
+	const struct iwl_legacy_rxon_cmd *active = &ctx->active;
+
+#define CHK(cond)							\
+	if ((cond)) {							\
+		IWL_DEBUG_INFO(priv, "need full RXON - " #cond "\n");	\
+		return 1;						\
+	}
+
+#define CHK_NEQ(c1, c2)						\
+	if ((c1) != (c2)) {					\
+		IWL_DEBUG_INFO(priv, "need full RXON - "	\
+			       #c1 " != " #c2 " - %d != %d\n",	\
+			       (c1), (c2));			\
+		return 1;					\
+	}
+
+	/* These items are only settable from the full RXON command */
+	CHK(!iwl_legacy_is_associated_ctx(ctx));
+	CHK(compare_ether_addr(staging->bssid_addr, active->bssid_addr));
+	CHK(compare_ether_addr(staging->node_addr, active->node_addr));
+	CHK(compare_ether_addr(staging->wlap_bssid_addr,
+				active->wlap_bssid_addr));
+	CHK_NEQ(staging->dev_type, active->dev_type);
+	CHK_NEQ(staging->channel, active->channel);
+	CHK_NEQ(staging->air_propagation, active->air_propagation);
+	CHK_NEQ(staging->ofdm_ht_single_stream_basic_rates,
+		active->ofdm_ht_single_stream_basic_rates);
+	CHK_NEQ(staging->ofdm_ht_dual_stream_basic_rates,
+		active->ofdm_ht_dual_stream_basic_rates);
+	CHK_NEQ(staging->assoc_id, active->assoc_id);
+
+	/* flags, filter_flags, ofdm_basic_rates, and cck_basic_rates can
+	 * be updated with the RXON_ASSOC command -- however only some
+	 * flag transitions are allowed using RXON_ASSOC */
+
+	/* Check if we are not switching bands */
+	CHK_NEQ(staging->flags & RXON_FLG_BAND_24G_MSK,
+		active->flags & RXON_FLG_BAND_24G_MSK);
+
+	/* Check if we are switching association toggle */
+	CHK_NEQ(staging->filter_flags & RXON_FILTER_ASSOC_MSK,
+		active->filter_flags & RXON_FILTER_ASSOC_MSK);
+
+#undef CHK
+#undef CHK_NEQ
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_full_rxon_required);
+
+u8 iwl_legacy_get_lowest_plcp(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx)
+{
+	/*
+	 * Assign the lowest rate -- should really get this from
+	 * the beacon skb from mac80211.
+	 */
+	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK)
+		return IWL_RATE_1M_PLCP;
+	else
+		return IWL_RATE_6M_PLCP;
+}
+EXPORT_SYMBOL(iwl_legacy_get_lowest_plcp);
+
+static void _iwl_legacy_set_rxon_ht(struct iwl_priv *priv,
+			     struct iwl_ht_config *ht_conf,
+			     struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+
+	if (!ctx->ht.enabled) {
+		rxon->flags &= ~(RXON_FLG_CHANNEL_MODE_MSK |
+			RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK |
+			RXON_FLG_HT40_PROT_MSK |
+			RXON_FLG_HT_PROT_MSK);
+		return;
+	}
+
+	rxon->flags |= cpu_to_le32(ctx->ht.protection <<
+					RXON_FLG_HT_OPERATING_MODE_POS);
+
+	/* Set up channel bandwidth:
+	 * 20 MHz only, 20/40 mixed or pure 40 if ht40 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_legacy_is_ht40_tx_allowed(priv, ctx, NULL)) {
+		/* pure ht40 */
+		if (ctx->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 (ctx->ht.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 (ctx->ht.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;
+	}
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	IWL_DEBUG_ASSOC(priv, "rxon flags 0x%X operation mode :0x%X "
+			"extension channel offset 0x%x\n",
+			le32_to_cpu(rxon->flags), ctx->ht.protection,
+			ctx->ht.extension_chan_offset);
+}
+
+void iwl_legacy_set_rxon_ht(struct iwl_priv *priv, struct iwl_ht_config *ht_conf)
+{
+	struct iwl_rxon_context *ctx;
+
+	for_each_context(priv, ctx)
+		_iwl_legacy_set_rxon_ht(priv, ht_conf, ctx);
+}
+EXPORT_SYMBOL(iwl_legacy_set_rxon_ht);
+
+/* Return valid, unused, channel for a passive scan to reset the RF */
+u8 iwl_legacy_get_single_channel_number(struct iwl_priv *priv,
+				 enum ieee80211_band band)
+{
+	const struct iwl_channel_info *ch_info;
+	int i;
+	u8 channel = 0;
+	u8 min, max;
+	struct iwl_rxon_context *ctx;
+
+	if (band == IEEE80211_BAND_5GHZ) {
+		min = 14;
+		max = priv->channel_count;
+	} else {
+		min = 0;
+		max = 14;
+	}
+
+	for (i = min; i < max; i++) {
+		bool busy = false;
+
+		for_each_context(priv, ctx) {
+			busy = priv->channel_info[i].channel ==
+				le16_to_cpu(ctx->staging.channel);
+			if (busy)
+				break;
+		}
+
+		if (busy)
+			continue;
+
+		channel = priv->channel_info[i].channel;
+		ch_info = iwl_legacy_get_channel_info(priv, band, channel);
+		if (iwl_legacy_is_channel_valid(ch_info))
+			break;
+	}
+
+	return channel;
+}
+EXPORT_SYMBOL(iwl_legacy_get_single_channel_number);
+
+/**
+ * iwl_legacy_set_rxon_channel - Set the band and channel values in staging RXON
+ * @ch: requested channel as a pointer to struct ieee80211_channel
+
+ * NOTE:  Does not commit to the hardware; it sets appropriate bit fields
+ * in the staging RXON flag structure based on the ch->band
+ */
+int
+iwl_legacy_set_rxon_channel(struct iwl_priv *priv, struct ieee80211_channel *ch,
+			 struct iwl_rxon_context *ctx)
+{
+	enum ieee80211_band band = ch->band;
+	u16 channel = ch->hw_value;
+
+	if ((le16_to_cpu(ctx->staging.channel) == channel) &&
+	    (priv->band == band))
+		return 0;
+
+	ctx->staging.channel = cpu_to_le16(channel);
+	if (band == IEEE80211_BAND_5GHZ)
+		ctx->staging.flags &= ~RXON_FLG_BAND_24G_MSK;
+	else
+		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+
+	priv->band = band;
+
+	IWL_DEBUG_INFO(priv, "Staging channel set to %d [%d]\n", channel, band);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_set_rxon_channel);
+
+void iwl_legacy_set_flags_for_band(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    enum ieee80211_band band,
+			    struct ieee80211_vif *vif)
+{
+	if (band == IEEE80211_BAND_5GHZ) {
+		ctx->staging.flags &=
+		    ~(RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK
+		      | RXON_FLG_CCK_MSK);
+		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+	} else {
+		/* Copied from iwl_post_associate() */
+		if (vif && vif->bss_conf.use_short_slot)
+			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
+
+		ctx->staging.flags |= RXON_FLG_BAND_24G_MSK;
+		ctx->staging.flags |= RXON_FLG_AUTO_DETECT_MSK;
+		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_set_flags_for_band);
+
+/*
+ * initialize rxon structure with default values from eeprom
+ */
+void iwl_legacy_connection_init_rx_config(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx)
+{
+	const struct iwl_channel_info *ch_info;
+
+	memset(&ctx->staging, 0, sizeof(ctx->staging));
+
+	if (!ctx->vif) {
+		ctx->staging.dev_type = ctx->unused_devtype;
+	} else
+	switch (ctx->vif->type) {
+
+	case NL80211_IFTYPE_STATION:
+		ctx->staging.dev_type = ctx->station_devtype;
+		ctx->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
+		break;
+
+	case NL80211_IFTYPE_ADHOC:
+		ctx->staging.dev_type = ctx->ibss_devtype;
+		ctx->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
+		ctx->staging.filter_flags = RXON_FILTER_BCON_AWARE_MSK |
+						  RXON_FILTER_ACCEPT_GRP_MSK;
+		break;
+
+	default:
+		IWL_ERR(priv, "Unsupported interface type %d\n",
+			ctx->vif->type);
+		break;
+	}
+
+#if 0
+	/* TODO:  Figure out when short_preamble would be set and cache from
+	 * that */
+	if (!hw_to_local(priv->hw)->short_preamble)
+		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
+	else
+		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+#endif
+
+	ch_info = iwl_legacy_get_channel_info(priv, priv->band,
+				       le16_to_cpu(ctx->active.channel));
+
+	if (!ch_info)
+		ch_info = &priv->channel_info[0];
+
+	ctx->staging.channel = cpu_to_le16(ch_info->channel);
+	priv->band = ch_info->band;
+
+	iwl_legacy_set_flags_for_band(priv, ctx, priv->band, ctx->vif);
+
+	ctx->staging.ofdm_basic_rates =
+	    (IWL_OFDM_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+	ctx->staging.cck_basic_rates =
+	    (IWL_CCK_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+	/* clear both MIX and PURE40 mode flag */
+	ctx->staging.flags &= ~(RXON_FLG_CHANNEL_MODE_MIXED |
+					RXON_FLG_CHANNEL_MODE_PURE_40);
+	if (ctx->vif)
+		memcpy(ctx->staging.node_addr, ctx->vif->addr, ETH_ALEN);
+
+	ctx->staging.ofdm_ht_single_stream_basic_rates = 0xff;
+	ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
+}
+EXPORT_SYMBOL(iwl_legacy_connection_init_rx_config);
+
+void iwl_legacy_set_rate(struct iwl_priv *priv)
+{
+	const struct ieee80211_supported_band *hw = NULL;
+	struct ieee80211_rate *rate;
+	struct iwl_rxon_context *ctx;
+	int i;
+
+	hw = iwl_get_hw_mode(priv, priv->band);
+	if (!hw) {
+		IWL_ERR(priv, "Failed to set rate: unable to get hw mode\n");
+		return;
+	}
+
+	priv->active_rate = 0;
+
+	for (i = 0; i < hw->n_bitrates; i++) {
+		rate = &(hw->bitrates[i]);
+		if (rate->hw_value < IWL_RATE_COUNT_LEGACY)
+			priv->active_rate |= (1 << rate->hw_value);
+	}
+
+	IWL_DEBUG_RATE(priv, "Set active_rate = %0x\n", priv->active_rate);
+
+	for_each_context(priv, ctx) {
+		ctx->staging.cck_basic_rates =
+		    (IWL_CCK_BASIC_RATES_MASK >> IWL_FIRST_CCK_RATE) & 0xF;
+
+		ctx->staging.ofdm_basic_rates =
+		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_set_rate);
+
+void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (priv->switch_rxon.switch_in_progress) {
+		ieee80211_chswitch_done(ctx->vif, is_success);
+		mutex_lock(&priv->mutex);
+		priv->switch_rxon.switch_in_progress = false;
+		mutex_unlock(&priv->mutex);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_chswitch_done);
+
+void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_legacy_rxon_cmd *rxon = (void *)&ctx->active;
+
+	if (priv->switch_rxon.switch_in_progress) {
+		if (!le32_to_cpu(csa->status) &&
+		    (csa->channel == priv->switch_rxon.channel)) {
+			rxon->channel = csa->channel;
+			ctx->staging.channel = csa->channel;
+			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_legacy_chswitch_done(priv, true);
+		} else {
+			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_legacy_chswitch_done(priv, false);
+		}
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_rx_csa);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_rxon_cmd *rxon = &ctx->staging;
+
+	IWL_DEBUG_RADIO(priv, "RX CONFIG:\n");
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, (u8 *) rxon, sizeof(*rxon));
+	IWL_DEBUG_RADIO(priv, "u16 channel: 0x%x\n",
+				le16_to_cpu(rxon->channel));
+	IWL_DEBUG_RADIO(priv, "u32 flags: 0x%08X\n", le32_to_cpu(rxon->flags));
+	IWL_DEBUG_RADIO(priv, "u32 filter_flags: 0x%08x\n",
+				le32_to_cpu(rxon->filter_flags));
+	IWL_DEBUG_RADIO(priv, "u8 dev_type: 0x%x\n", rxon->dev_type);
+	IWL_DEBUG_RADIO(priv, "u8 ofdm_basic_rates: 0x%02x\n",
+			rxon->ofdm_basic_rates);
+	IWL_DEBUG_RADIO(priv, "u8 cck_basic_rates: 0x%02x\n",
+				rxon->cck_basic_rates);
+	IWL_DEBUG_RADIO(priv, "u8[6] node_addr: %pM\n", rxon->node_addr);
+	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
+	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n",
+				le16_to_cpu(rxon->assoc_id));
+}
+EXPORT_SYMBOL(iwl_legacy_print_rx_config_cmd);
+#endif
+/**
+ * iwl_legacy_irq_handle_error - called for HW or SW error interrupt from card
+ */
+void iwl_legacy_irq_handle_error(struct iwl_priv *priv)
+{
+	/* Set the FW error flag -- cleared on iwl_down */
+	set_bit(STATUS_FW_ERROR, &priv->status);
+
+	/* Cancel currently queued command. */
+	clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+
+	IWL_ERR(priv, "Loaded firmware version: %s\n",
+		priv->hw->wiphy->fw_version);
+
+	priv->cfg->ops->lib->dump_nic_error_log(priv);
+	if (priv->cfg->ops->lib->dump_fh)
+		priv->cfg->ops->lib->dump_fh(priv, NULL, false);
+	priv->cfg->ops->lib->dump_nic_event_log(priv, false, NULL, false);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	if (iwl_legacy_get_debug_level(priv) & IWL_DL_FW_ERRORS)
+		iwl_legacy_print_rx_config_cmd(priv,
+					&priv->contexts[IWL_RXON_CTX_BSS]);
+#endif
+
+	wake_up_interruptible(&priv->wait_command_queue);
+
+	/* Keep the restart process from trying to send host
+	 * commands by clearing the INIT status bit */
+	clear_bit(STATUS_READY, &priv->status);
+
+	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
+		IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
+			  "Restarting adapter due to uCode error.\n");
+
+		if (priv->cfg->mod_params->restart_fw)
+			queue_work(priv->workqueue, &priv->restart);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_irq_handle_error);
+
+static int iwl_legacy_apm_stop_master(struct iwl_priv *priv)
+{
+	int ret = 0;
+
+	/* stop device's busmaster DMA activity */
+	iwl_legacy_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
+
+	ret = iwl_poll_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_MASTER_DISABLED,
+			CSR_RESET_REG_FLAG_MASTER_DISABLED, 100);
+	if (ret)
+		IWL_WARN(priv, "Master Disable Timed Out, 100 usec\n");
+
+	IWL_DEBUG_INFO(priv, "stop master\n");
+
+	return ret;
+}
+
+void iwl_legacy_apm_stop(struct iwl_priv *priv)
+{
+	IWL_DEBUG_INFO(priv, "Stop card, put in low power state\n");
+
+	/* Stop device's DMA activity */
+	iwl_legacy_apm_stop_master(priv);
+
+	/* Reset the entire device */
+	iwl_legacy_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_SW_RESET);
+
+	udelay(10);
+
+	/*
+	 * Clear "initialization complete" bit to move adapter from
+	 * D0A* (powered-up Active) --> D0U* (Uninitialized) state.
+	 */
+	iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+}
+EXPORT_SYMBOL(iwl_legacy_apm_stop);
+
+
+/*
+ * Start up NIC's basic functionality after it has been reset
+ * (e.g. after platform boot, or shutdown via iwl_legacy_apm_stop())
+ * NOTE:  This does not load uCode nor start the embedded processor
+ */
+int iwl_legacy_apm_init(struct iwl_priv *priv)
+{
+	int ret = 0;
+	u16 lctl;
+
+	IWL_DEBUG_INFO(priv, "Init card's basic functions\n");
+
+	/*
+	 * Use "set_bit" below rather than "write", to preserve any hardware
+	 * bits already set by default after reset.
+	 */
+
+	/* Disable L0S exit timer (platform NMI Work/Around) */
+	iwl_legacy_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+			  CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER);
+
+	/*
+	 * Disable L0s without affecting L1;
+	 *  don't wait for ICH L0s (ICH bug W/A)
+	 */
+	iwl_legacy_set_bit(priv, CSR_GIO_CHICKEN_BITS,
+			  CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX);
+
+	/* Set FH wait threshold to maximum (HW error during stress W/A) */
+	iwl_legacy_set_bit(priv, CSR_DBG_HPET_MEM_REG,
+					CSR_DBG_HPET_MEM_REG_VAL);
+
+	/*
+	 * Enable HAP INTA (interrupt from management bus) to
+	 * wake device's PCI Express link L1a -> L0s
+	 * NOTE:  This is no-op for 3945 (non-existent bit)
+	 */
+	iwl_legacy_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
+
+	/*
+	 * HW bug W/A for instability in PCIe bus L0->L0S->L1 transition.
+	 * Check if BIOS (or OS) enabled L1-ASPM on this device.
+	 * If so (likely), disable L0S, so device moves directly L0->L1;
+	 *    costs negligible amount of power savings.
+	 * If not (unlikely), enable L0S, so there is at least some
+	 *    power savings, even without L1.
+	 */
+	if (priv->cfg->base_params->set_l0s) {
+		lctl = iwl_legacy_pcie_link_ctl(priv);
+		if ((lctl & PCI_CFG_LINK_CTRL_VAL_L1_EN) ==
+					PCI_CFG_LINK_CTRL_VAL_L1_EN) {
+			/* L1-ASPM enabled; disable(!) L0S  */
+			iwl_legacy_set_bit(priv, CSR_GIO_REG,
+					CSR_GIO_REG_VAL_L0S_ENABLED);
+			IWL_DEBUG_POWER(priv, "L1 Enabled; Disabling L0S\n");
+		} else {
+			/* L1-ASPM disabled; enable(!) L0S */
+			iwl_legacy_clear_bit(priv, CSR_GIO_REG,
+					CSR_GIO_REG_VAL_L0S_ENABLED);
+			IWL_DEBUG_POWER(priv, "L1 Disabled; Enabling L0S\n");
+		}
+	}
+
+	/* Configure analog phase-lock-loop before activating to D0A */
+	if (priv->cfg->base_params->pll_cfg_val)
+		iwl_legacy_set_bit(priv, CSR_ANA_PLL_CFG,
+			    priv->cfg->base_params->pll_cfg_val);
+
+	/*
+	 * Set "initialization complete" bit to move adapter from
+	 * D0U* --> D0A* (powered-up active) state.
+	 */
+	iwl_legacy_set_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
+
+	/*
+	 * Wait for clock stabilization; once stabilized, access to
+	 * device-internal resources is supported, e.g. iwl_legacy_write_prph()
+	 * and accesses to uCode SRAM.
+	 */
+	ret = iwl_poll_bit(priv, CSR_GP_CNTRL,
+			CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY,
+			CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY, 25000);
+	if (ret < 0) {
+		IWL_DEBUG_INFO(priv, "Failed to init the card\n");
+		goto out;
+	}
+
+	/*
+	 * Enable DMA and BSM (if used) clocks, wait for them to stabilize.
+	 * BSM (Boostrap State Machine) is only in 3945 and 4965.
+	 *
+	 * Write to "CLK_EN_REG"; "1" bits enable clocks, while "0" bits
+	 * do not disable clocks.  This preserves any hardware bits already
+	 * set by default in "CLK_CTRL_REG" after reset.
+	 */
+	if (priv->cfg->base_params->use_bsm)
+		iwl_legacy_write_prph(priv, APMG_CLK_EN_REG,
+			APMG_CLK_VAL_DMA_CLK_RQT | APMG_CLK_VAL_BSM_CLK_RQT);
+	else
+		iwl_legacy_write_prph(priv, APMG_CLK_EN_REG,
+			APMG_CLK_VAL_DMA_CLK_RQT);
+	udelay(20);
+
+	/* Disable L1-Active */
+	iwl_legacy_set_bits_prph(priv, APMG_PCIDEV_STT_REG,
+			  APMG_PCIDEV_STT_VAL_L1_ACT_DIS);
+
+out:
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_apm_init);
+
+
+int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
+{
+	int ret;
+	s8 prev_tx_power;
+	bool defer;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (priv->tx_power_user_lmt == tx_power && !force)
+		return 0;
+
+	if (!priv->cfg->ops->lib->send_tx_power)
+		return -EOPNOTSUPP;
+
+	/* 0 dBm mean 1 milliwatt */
+	if (tx_power < 0) {
+		IWL_WARN(priv,
+			 "Requested user TXPOWER %d below 1 mW.\n",
+			 tx_power);
+		return -EINVAL;
+	}
+
+	if (tx_power > priv->tx_power_device_lmt) {
+		IWL_WARN(priv,
+			"Requested user TXPOWER %d above upper limit %d.\n",
+			 tx_power, priv->tx_power_device_lmt);
+		return -EINVAL;
+	}
+
+	if (!iwl_legacy_is_ready_rf(priv))
+		return -EIO;
+
+	/* scan complete and commit_rxon use tx_power_next value,
+	 * it always need to be updated for newest request */
+	priv->tx_power_next = tx_power;
+
+	/* do not set tx power when scanning or channel changing */
+	defer = test_bit(STATUS_SCANNING, &priv->status) ||
+		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+	if (defer && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
+		return 0;
+	}
+
+	prev_tx_power = priv->tx_power_user_lmt;
+	priv->tx_power_user_lmt = tx_power;
+
+	ret = priv->cfg->ops->lib->send_tx_power(priv);
+
+	/* if fail to set tx_power, restore the orig. tx power */
+	if (ret) {
+		priv->tx_power_user_lmt = prev_tx_power;
+		priv->tx_power_next = prev_tx_power;
+	}
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_set_tx_power);
+
+void iwl_legacy_send_bt_config(struct iwl_priv *priv)
+{
+	struct iwl_bt_cmd bt_cmd = {
+		.lead_time = BT_LEAD_TIME_DEF,
+		.max_kill = BT_MAX_KILL_DEF,
+		.kill_ack_mask = 0,
+		.kill_cts_mask = 0,
+	};
+
+	if (!bt_coex_active)
+		bt_cmd.flags = BT_COEX_DISABLE;
+	else
+		bt_cmd.flags = BT_COEX_ENABLE;
+
+	IWL_DEBUG_INFO(priv, "BT coex %s\n",
+		(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
+
+	if (iwl_legacy_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+			     sizeof(struct iwl_bt_cmd), &bt_cmd))
+		IWL_ERR(priv, "failed to send BT Coex Config\n");
+}
+EXPORT_SYMBOL(iwl_legacy_send_bt_config);
+
+int iwl_legacy_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
+{
+	struct iwl_statistics_cmd statistics_cmd = {
+		.configuration_flags =
+			clear ? IWL_STATS_CONF_CLEAR_STATS : 0,
+	};
+
+	if (flags & CMD_ASYNC)
+		return iwl_legacy_send_cmd_pdu_async(priv, REPLY_STATISTICS_CMD,
+					sizeof(struct iwl_statistics_cmd),
+					&statistics_cmd, NULL);
+	else
+		return iwl_legacy_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
+					sizeof(struct iwl_statistics_cmd),
+					&statistics_cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_statistics_request);
+
+void iwl_legacy_rx_pm_sleep_notif(struct iwl_priv *priv,
+			   struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	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_legacy_rx_pm_sleep_notif);
+
+void iwl_legacy_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
+			"notification for %s:\n", len,
+			iwl_legacy_get_cmd_string(pkt->hdr.cmd));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+}
+EXPORT_SYMBOL(iwl_legacy_rx_pm_debug_statistics_notif);
+
+void iwl_legacy_rx_reply_error(struct iwl_priv *priv,
+			struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	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),
+		iwl_legacy_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_legacy_rx_reply_error);
+
+void iwl_legacy_clear_isr_stats(struct iwl_priv *priv)
+{
+	memset(&priv->isr_stats, 0, sizeof(priv->isr_stats));
+}
+
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+			   const struct ieee80211_tx_queue_params *params)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx;
+	unsigned long flags;
+	int q;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (!iwl_legacy_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);
+
+	for_each_context(priv, ctx) {
+		ctx->qos_data.def_qos_parm.ac[q].cw_min =
+			cpu_to_le16(params->cw_min);
+		ctx->qos_data.def_qos_parm.ac[q].cw_max =
+			cpu_to_le16(params->cw_max);
+		ctx->qos_data.def_qos_parm.ac[q].aifsn = params->aifs;
+		ctx->qos_data.def_qos_parm.ac[q].edca_txop =
+				cpu_to_le16((params->txop * 32));
+
+		ctx->qos_data.def_qos_parm.ac[q].reserved1 = 0;
+	}
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_conf_tx);
+
+int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	return priv->ibss_manager == IWL_IBSS_MANAGER;
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_mac_tx_last_beacon);
+
+static int
+iwl_legacy_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	iwl_legacy_connection_init_rx_config(priv, ctx);
+
+	if (priv->cfg->ops->hcmd->set_rxon_chain)
+		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+
+	return iwl_legacy_commit_rxon(priv, ctx);
+}
+
+static int iwl_legacy_setup_interface(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx)
+{
+	struct ieee80211_vif *vif = ctx->vif;
+	int err;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/*
+	 * This variable will be correct only when there's just
+	 * a single context, but all code using it is for hardware
+	 * that supports only one context.
+	 */
+	priv->iw_mode = vif->type;
+
+	ctx->is_active = true;
+
+	err = iwl_legacy_set_mode(priv, ctx);
+	if (err) {
+		if (!ctx->always_active)
+			ctx->is_active = false;
+		return err;
+	}
+
+	return 0;
+}
+
+int
+iwl_legacy_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+	struct iwl_rxon_context *tmp, *ctx = NULL;
+	int err;
+
+	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
+			   vif->type, vif->addr);
+
+	mutex_lock(&priv->mutex);
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_WARN(priv, "Try to add interface when device not ready\n");
+		err = -EINVAL;
+		goto out;
+	}
+
+	for_each_context(priv, tmp) {
+		u32 possible_modes =
+			tmp->interface_modes | tmp->exclusive_interface_modes;
+
+		if (tmp->vif) {
+			/* check if this busy context is exclusive */
+			if (tmp->exclusive_interface_modes &
+						BIT(tmp->vif->type)) {
+				err = -EINVAL;
+				goto out;
+			}
+			continue;
+		}
+
+		if (!(possible_modes & BIT(vif->type)))
+			continue;
+
+		/* have maybe usable context w/o interface */
+		ctx = tmp;
+		break;
+	}
+
+	if (!ctx) {
+		err = -EOPNOTSUPP;
+		goto out;
+	}
+
+	vif_priv->ctx = ctx;
+	ctx->vif = vif;
+
+	err = iwl_legacy_setup_interface(priv, ctx);
+	if (!err)
+		goto out;
+
+	ctx->vif = NULL;
+	priv->iw_mode = NL80211_IFTYPE_STATION;
+ out:
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	return err;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_add_interface);
+
+static void iwl_legacy_teardown_interface(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   bool mode_change)
+{
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (priv->scan_vif == vif) {
+		iwl_legacy_scan_cancel_timeout(priv, 200);
+		iwl_legacy_force_scan_end(priv);
+	}
+
+	if (!mode_change) {
+		iwl_legacy_set_mode(priv, ctx);
+		if (!ctx->always_active)
+			ctx->is_active = false;
+	}
+}
+
+void iwl_legacy_mac_remove_interface(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	mutex_lock(&priv->mutex);
+
+	WARN_ON(ctx->vif != vif);
+	ctx->vif = NULL;
+
+	iwl_legacy_teardown_interface(priv, vif, false);
+
+	memset(priv->bssid, 0, ETH_ALEN);
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+}
+EXPORT_SYMBOL(iwl_legacy_mac_remove_interface);
+
+int iwl_legacy_alloc_txq_mem(struct iwl_priv *priv)
+{
+	if (!priv->txq)
+		priv->txq = kzalloc(
+			sizeof(struct iwl_tx_queue) *
+				priv->cfg->base_params->num_of_queues,
+			GFP_KERNEL);
+	if (!priv->txq) {
+		IWL_ERR(priv, "Not enough memory for txq\n");
+		return -ENOMEM;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_alloc_txq_mem);
+
+void iwl_legacy_txq_mem(struct iwl_priv *priv)
+{
+	kfree(priv->txq);
+	priv->txq = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_txq_mem);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+
+#define IWL_TRAFFIC_DUMP_SIZE	(IWL_TRAFFIC_ENTRY_SIZE * IWL_TRAFFIC_ENTRIES)
+
+void iwl_legacy_reset_traffic_log(struct iwl_priv *priv)
+{
+	priv->tx_traffic_idx = 0;
+	priv->rx_traffic_idx = 0;
+	if (priv->tx_traffic)
+		memset(priv->tx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+	if (priv->rx_traffic)
+		memset(priv->rx_traffic, 0, IWL_TRAFFIC_DUMP_SIZE);
+}
+
+int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv)
+{
+	u32 traffic_size = IWL_TRAFFIC_DUMP_SIZE;
+
+	if (iwlegacy_debug_level & IWL_DL_TX) {
+		if (!priv->tx_traffic) {
+			priv->tx_traffic =
+				kzalloc(traffic_size, GFP_KERNEL);
+			if (!priv->tx_traffic)
+				return -ENOMEM;
+		}
+	}
+	if (iwlegacy_debug_level & IWL_DL_RX) {
+		if (!priv->rx_traffic) {
+			priv->rx_traffic =
+				kzalloc(traffic_size, GFP_KERNEL);
+			if (!priv->rx_traffic)
+				return -ENOMEM;
+		}
+	}
+	iwl_legacy_reset_traffic_log(priv);
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_alloc_traffic_mem);
+
+void iwl_legacy_free_traffic_mem(struct iwl_priv *priv)
+{
+	kfree(priv->tx_traffic);
+	priv->tx_traffic = NULL;
+
+	kfree(priv->rx_traffic);
+	priv->rx_traffic = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_free_traffic_mem);
+
+void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+	__le16 fc;
+	u16 len;
+
+	if (likely(!(iwlegacy_debug_level & IWL_DL_TX)))
+		return;
+
+	if (!priv->tx_traffic)
+		return;
+
+	fc = header->frame_control;
+	if (ieee80211_is_data(fc)) {
+		len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+		       ? IWL_TRAFFIC_ENTRY_SIZE : length;
+		memcpy((priv->tx_traffic +
+		       (priv->tx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+		       header, len);
+		priv->tx_traffic_idx =
+			(priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_dbg_log_tx_data_frame);
+
+void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+	__le16 fc;
+	u16 len;
+
+	if (likely(!(iwlegacy_debug_level & IWL_DL_RX)))
+		return;
+
+	if (!priv->rx_traffic)
+		return;
+
+	fc = header->frame_control;
+	if (ieee80211_is_data(fc)) {
+		len = (length > IWL_TRAFFIC_ENTRY_SIZE)
+		       ? IWL_TRAFFIC_ENTRY_SIZE : length;
+		memcpy((priv->rx_traffic +
+		       (priv->rx_traffic_idx * IWL_TRAFFIC_ENTRY_SIZE)),
+		       header, len);
+		priv->rx_traffic_idx =
+			(priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_dbg_log_rx_data_frame);
+
+const char *iwl_legacy_get_mgmt_string(int cmd)
+{
+	switch (cmd) {
+		IWL_CMD(MANAGEMENT_ASSOC_REQ);
+		IWL_CMD(MANAGEMENT_ASSOC_RESP);
+		IWL_CMD(MANAGEMENT_REASSOC_REQ);
+		IWL_CMD(MANAGEMENT_REASSOC_RESP);
+		IWL_CMD(MANAGEMENT_PROBE_REQ);
+		IWL_CMD(MANAGEMENT_PROBE_RESP);
+		IWL_CMD(MANAGEMENT_BEACON);
+		IWL_CMD(MANAGEMENT_ATIM);
+		IWL_CMD(MANAGEMENT_DISASSOC);
+		IWL_CMD(MANAGEMENT_AUTH);
+		IWL_CMD(MANAGEMENT_DEAUTH);
+		IWL_CMD(MANAGEMENT_ACTION);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+const char *iwl_legacy_get_ctrl_string(int cmd)
+{
+	switch (cmd) {
+		IWL_CMD(CONTROL_BACK_REQ);
+		IWL_CMD(CONTROL_BACK);
+		IWL_CMD(CONTROL_PSPOLL);
+		IWL_CMD(CONTROL_RTS);
+		IWL_CMD(CONTROL_CTS);
+		IWL_CMD(CONTROL_ACK);
+		IWL_CMD(CONTROL_CFEND);
+		IWL_CMD(CONTROL_CFENDACK);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+
+void iwl_legacy_clear_traffic_stats(struct iwl_priv *priv)
+{
+	memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
+	memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
+}
+
+/*
+ * if CONFIG_IWLWIFI_LEGACY_DEBUGFS defined,
+ * iwl_legacy_update_stats function will
+ * record all the MGMT, CTRL and DATA pkt for both TX and Rx pass
+ * Use debugFs to display the rx/rx_statistics
+ * if CONFIG_IWLWIFI_LEGACY_DEBUGFS not being defined, then no MGMT and CTRL
+ * information will be recorded, but DATA pkt still will be recorded
+ * for the reason of iwl_led.c need to control the led blinking based on
+ * number of tx and rx data.
+ *
+ */
+void
+iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc, u16 len)
+{
+	struct traffic_stats	*stats;
+
+	if (is_tx)
+		stats = &priv->tx_stats;
+	else
+		stats = &priv->rx_stats;
+
+	if (ieee80211_is_mgmt(fc)) {
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+			stats->mgmt[MANAGEMENT_ASSOC_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_RESP):
+			stats->mgmt[MANAGEMENT_ASSOC_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			stats->mgmt[MANAGEMENT_REASSOC_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_RESP):
+			stats->mgmt[MANAGEMENT_REASSOC_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PROBE_REQ):
+			stats->mgmt[MANAGEMENT_PROBE_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PROBE_RESP):
+			stats->mgmt[MANAGEMENT_PROBE_RESP]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_BEACON):
+			stats->mgmt[MANAGEMENT_BEACON]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ATIM):
+			stats->mgmt[MANAGEMENT_ATIM]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_DISASSOC):
+			stats->mgmt[MANAGEMENT_DISASSOC]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+			stats->mgmt[MANAGEMENT_AUTH]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+			stats->mgmt[MANAGEMENT_DEAUTH]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ACTION):
+			stats->mgmt[MANAGEMENT_ACTION]++;
+			break;
+		}
+	} else if (ieee80211_is_ctl(fc)) {
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_BACK_REQ):
+			stats->ctrl[CONTROL_BACK_REQ]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_BACK):
+			stats->ctrl[CONTROL_BACK]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_PSPOLL):
+			stats->ctrl[CONTROL_PSPOLL]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_RTS):
+			stats->ctrl[CONTROL_RTS]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CTS):
+			stats->ctrl[CONTROL_CTS]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_ACK):
+			stats->ctrl[CONTROL_ACK]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CFEND):
+			stats->ctrl[CONTROL_CFEND]++;
+			break;
+		case cpu_to_le16(IEEE80211_STYPE_CFENDACK):
+			stats->ctrl[CONTROL_CFENDACK]++;
+			break;
+		}
+	} else {
+		/* data */
+		stats->data_cnt++;
+		stats->data_bytes += len;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_update_stats);
+#endif
+
+static void _iwl_legacy_force_rf_reset(struct iwl_priv *priv)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!iwl_legacy_is_any_associated(priv)) {
+		IWL_DEBUG_SCAN(priv, "force reset rejected: not associated\n");
+		return;
+	}
+	/*
+	 * There is no easy and better way to force reset the radio,
+	 * the only known method is switching channel which will force to
+	 * reset and tune the radio.
+	 * Use internal short scan (single channel) operation to should
+	 * achieve this objective.
+	 * Driver should reset the radio when number of consecutive missed
+	 * beacon, or any other uCode error condition detected.
+	 */
+	IWL_DEBUG_INFO(priv, "perform radio reset.\n");
+	iwl_legacy_internal_short_hw_scan(priv);
+}
+
+
+int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external)
+{
+	struct iwl_force_reset *force_reset;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EINVAL;
+
+	if (mode >= IWL_MAX_FORCE_RESET) {
+		IWL_DEBUG_INFO(priv, "invalid reset request.\n");
+		return -EINVAL;
+	}
+	force_reset = &priv->force_reset[mode];
+	force_reset->reset_request_count++;
+	if (!external) {
+		if (force_reset->last_force_reset_jiffies &&
+		    time_after(force_reset->last_force_reset_jiffies +
+		    force_reset->reset_duration, jiffies)) {
+			IWL_DEBUG_INFO(priv, "force reset rejected\n");
+			force_reset->reset_reject_count++;
+			return -EAGAIN;
+		}
+	}
+	force_reset->reset_success_count++;
+	force_reset->last_force_reset_jiffies = jiffies;
+	IWL_DEBUG_INFO(priv, "perform force reset (%d)\n", mode);
+	switch (mode) {
+	case IWL_RF_RESET:
+		_iwl_legacy_force_rf_reset(priv);
+		break;
+	case IWL_FW_RESET:
+		/*
+		 * if the request is from external(ex: debugfs),
+		 * then always perform the request in regardless the module
+		 * parameter setting
+		 * if the request is from internal (uCode error or driver
+		 * detect failure), then fw_restart module parameter
+		 * need to be check before performing firmware reload
+		 */
+		if (!external && !priv->cfg->mod_params->restart_fw) {
+			IWL_DEBUG_INFO(priv, "Cancel firmware reload based on "
+				       "module parameter setting\n");
+			break;
+		}
+		IWL_ERR(priv, "On demand firmware reload\n");
+		/* Set the FW error flag -- cleared on iwl_down */
+		set_bit(STATUS_FW_ERROR, &priv->status);
+		wake_up_interruptible(&priv->wait_command_queue);
+		/*
+		 * Keep the restart process from trying to send host
+		 * commands by clearing the INIT status bit
+		 */
+		clear_bit(STATUS_READY, &priv->status);
+		queue_work(priv->workqueue, &priv->restart);
+		break;
+	}
+	return 0;
+}
+
+int
+iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			enum nl80211_iftype newtype, bool newp2p)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+	struct iwl_rxon_context *tmp;
+	u32 interface_modes;
+	int err;
+
+	newtype = ieee80211_iftype_p2p(newtype, newp2p);
+
+	mutex_lock(&priv->mutex);
+
+	if (!ctx->vif || !iwl_legacy_is_ready_rf(priv)) {
+		/*
+		 * Huh? But wait ... this can maybe happen when
+		 * we're in the middle of a firmware restart!
+		 */
+		err = -EBUSY;
+		goto out;
+	}
+
+	interface_modes = ctx->interface_modes | ctx->exclusive_interface_modes;
+
+	if (!(interface_modes & BIT(newtype))) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	if (ctx->exclusive_interface_modes & BIT(newtype)) {
+		for_each_context(priv, tmp) {
+			if (ctx == tmp)
+				continue;
+
+			if (!tmp->vif)
+				continue;
+
+			/*
+			 * The current mode switch would be exclusive, but
+			 * another context is active ... refuse the switch.
+			 */
+			err = -EBUSY;
+			goto out;
+		}
+	}
+
+	/* success */
+	iwl_legacy_teardown_interface(priv, vif, true);
+	vif->type = newtype;
+	vif->p2p = newp2p;
+	err = iwl_legacy_setup_interface(priv, ctx);
+	WARN_ON(err);
+	/*
+	 * We've switched internally, but submitting to the
+	 * device may have failed for some reason. Mask this
+	 * error, because otherwise mac80211 will not switch
+	 * (and set the interface type back) and we'll be
+	 * out of sync with it.
+	 */
+	err = 0;
+
+ out:
+	mutex_unlock(&priv->mutex);
+	return err;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_change_interface);
+
+/*
+ * On every watchdog tick we check (latest) time stamp. If it does not
+ * change during timeout period and queue is not empty we reset firmware.
+ */
+static int iwl_legacy_check_stuck_queue(struct iwl_priv *priv, int cnt)
+{
+	struct iwl_tx_queue *txq = &priv->txq[cnt];
+	struct iwl_queue *q = &txq->q;
+	unsigned long timeout;
+	int ret;
+
+	if (q->read_ptr == q->write_ptr) {
+		txq->time_stamp = jiffies;
+		return 0;
+	}
+
+	timeout = txq->time_stamp +
+		  msecs_to_jiffies(priv->cfg->base_params->wd_timeout);
+
+	if (time_after(jiffies, timeout)) {
+		IWL_ERR(priv, "Queue %d stuck for %u ms.\n",
+				q->id, priv->cfg->base_params->wd_timeout);
+		ret = iwl_legacy_force_reset(priv, IWL_FW_RESET, false);
+		return (ret == -EAGAIN) ? 0 : 1;
+	}
+
+	return 0;
+}
+
+/*
+ * Making watchdog tick be a quarter of timeout assure we will
+ * discover the queue hung between timeout and 1.25*timeout
+ */
+#define IWL_WD_TICK(timeout) ((timeout) / 4)
+
+/*
+ * Watchdog timer callback, we check each tx queue for stuck, if if hung
+ * we reset the firmware. If everything is fine just rearm the timer.
+ */
+void iwl_legacy_bg_watchdog(unsigned long data)
+{
+	struct iwl_priv *priv = (struct iwl_priv *)data;
+	int cnt;
+	unsigned long timeout;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	timeout = priv->cfg->base_params->wd_timeout;
+	if (timeout == 0)
+		return;
+
+	/* monitor and check for stuck cmd queue */
+	if (iwl_legacy_check_stuck_queue(priv, priv->cmd_queue))
+		return;
+
+	/* monitor and check for other stuck queues */
+	if (iwl_legacy_is_any_associated(priv)) {
+		for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+			/* skip as we already checked the command queue */
+			if (cnt == priv->cmd_queue)
+				continue;
+			if (iwl_legacy_check_stuck_queue(priv, cnt))
+				return;
+		}
+	}
+
+	mod_timer(&priv->watchdog, jiffies +
+		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
+}
+EXPORT_SYMBOL(iwl_legacy_bg_watchdog);
+
+void iwl_legacy_setup_watchdog(struct iwl_priv *priv)
+{
+	unsigned int timeout = priv->cfg->base_params->wd_timeout;
+
+	if (timeout)
+		mod_timer(&priv->watchdog,
+			  jiffies + msecs_to_jiffies(IWL_WD_TICK(timeout)));
+	else
+		del_timer(&priv->watchdog);
+}
+EXPORT_SYMBOL(iwl_legacy_setup_watchdog);
+
+/*
+ * extended beacon time format
+ * time in usec will be changed into a 32-bit value in extended:internal format
+ * the extended part is the beacon counts
+ * the internal part is the time in usec within one beacon interval
+ */
+u32
+iwl_legacy_usecs_to_beacons(struct iwl_priv *priv,
+					u32 usec, u32 beacon_interval)
+{
+	u32 quot;
+	u32 rem;
+	u32 interval = beacon_interval * TIME_UNIT;
+
+	if (!interval || !usec)
+		return 0;
+
+	quot = (usec / interval) &
+		(iwl_legacy_beacon_time_mask_high(priv,
+		priv->hw_params.beacon_time_tsf_bits) >>
+		priv->hw_params.beacon_time_tsf_bits);
+	rem = (usec % interval) & iwl_legacy_beacon_time_mask_low(priv,
+				   priv->hw_params.beacon_time_tsf_bits);
+
+	return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
+}
+EXPORT_SYMBOL(iwl_legacy_usecs_to_beacons);
+
+/* base is usually what we get from ucode with each received frame,
+ * the same as HW timer counter counting down
+ */
+__le32 iwl_legacy_add_beacon_time(struct iwl_priv *priv, u32 base,
+			   u32 addon, u32 beacon_interval)
+{
+	u32 base_low = base & iwl_legacy_beacon_time_mask_low(priv,
+					priv->hw_params.beacon_time_tsf_bits);
+	u32 addon_low = addon & iwl_legacy_beacon_time_mask_low(priv,
+					priv->hw_params.beacon_time_tsf_bits);
+	u32 interval = beacon_interval * TIME_UNIT;
+	u32 res = (base & iwl_legacy_beacon_time_mask_high(priv,
+				priv->hw_params.beacon_time_tsf_bits)) +
+				(addon & iwl_legacy_beacon_time_mask_high(priv,
+				priv->hw_params.beacon_time_tsf_bits));
+
+	if (base_low > addon_low)
+		res += base_low - addon_low;
+	else if (base_low < addon_low) {
+		res += interval + base_low - addon_low;
+		res += (1 << priv->hw_params.beacon_time_tsf_bits);
+	} else
+		res += (1 << priv->hw_params.beacon_time_tsf_bits);
+
+	return cpu_to_le32(res);
+}
+EXPORT_SYMBOL(iwl_legacy_add_beacon_time);
+
+#ifdef CONFIG_PM
+
+int iwl_legacy_pci_suspend(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	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.
+	 */
+	iwl_legacy_apm_stop(priv);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_pci_suspend);
+
+int iwl_legacy_pci_resume(struct device *device)
+{
+	struct pci_dev *pdev = to_pci_dev(device);
+	struct iwl_priv *priv = pci_get_drvdata(pdev);
+	bool hw_rfkill = false;
+
+	/*
+	 * We disable the RETRY_TIMEOUT register (0x41) to keep
+	 * PCI Tx retries from interfering with C3 CPU state.
+	 */
+	pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+
+	iwl_legacy_enable_interrupts(priv);
+
+	if (!(iwl_read32(priv, CSR_GP_CNTRL) &
+				CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW))
+		hw_rfkill = true;
+
+	if (hw_rfkill)
+		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_rfkill);
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_pci_resume);
+
+const struct dev_pm_ops iwl_legacy_pm_ops = {
+	.suspend = iwl_legacy_pci_suspend,
+	.resume = iwl_legacy_pci_resume,
+	.freeze = iwl_legacy_pci_suspend,
+	.thaw = iwl_legacy_pci_resume,
+	.poweroff = iwl_legacy_pci_suspend,
+	.restore = iwl_legacy_pci_resume,
+};
+EXPORT_SYMBOL(iwl_legacy_pm_ops);
+
+#endif /* CONFIG_PM */
+
+static void
+iwl_legacy_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->qos_data.def_qos_parm.qos_flags = 0;
+
+	if (ctx->qos_data.qos_active)
+		ctx->qos_data.def_qos_parm.qos_flags |=
+			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
+
+	if (ctx->ht.enabled)
+		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
+
+	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
+		      ctx->qos_data.qos_active,
+		      ctx->qos_data.def_qos_parm.qos_flags);
+
+	iwl_legacy_send_cmd_pdu_async(priv, ctx->qos_cmd,
+			       sizeof(struct iwl_qosparam_cmd),
+			       &ctx->qos_data.def_qos_parm, NULL);
+}
+
+/**
+ * iwl_legacy_mac_config - mac80211 config callback
+ */
+int iwl_legacy_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;
+	struct ieee80211_channel *channel = conf->channel;
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct iwl_rxon_context *ctx;
+	unsigned long flags = 0;
+	int ret = 0;
+	u16 ch;
+	int scan_active = 0;
+	bool ht_changed[NUM_IWL_RXON_CTX] = {};
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
+					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");
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
+		       IEEE80211_CONF_CHANGE_CHANNEL)) {
+		/* mac80211 uses static for non-HT which is what we want */
+		priv->current_ht_config.smps = conf->smps_mode;
+
+		/*
+		 * Recalculate chain counts.
+		 *
+		 * If monitor mode is enabled then mac80211 will
+		 * set up the SM PS mode to OFF if an HT channel is
+		 * configured.
+		 */
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			for_each_context(priv, ctx)
+				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	/* 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 = channel->hw_value;
+		ch_info = iwl_legacy_get_channel_info(priv, channel->band, ch);
+		if (!iwl_legacy_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 &&
+		    !iwl_legacy_is_channel_ibss(ch_info)) {
+			IWL_DEBUG_MAC80211(priv, "leave - not IBSS channel\n");
+			ret = -EINVAL;
+			goto set_ch_out;
+		}
+
+		spin_lock_irqsave(&priv->lock, flags);
+
+		for_each_context(priv, ctx) {
+			/* Configure HT40 channels */
+			if (ctx->ht.enabled != conf_is_ht(conf)) {
+				ctx->ht.enabled = conf_is_ht(conf);
+				ht_changed[ctx->ctxid] = true;
+			}
+			if (ctx->ht.enabled) {
+				if (conf_is_ht40_minus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_BELOW;
+					ctx->ht.is_40mhz = true;
+				} else if (conf_is_ht40_plus(conf)) {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
+					ctx->ht.is_40mhz = true;
+				} else {
+					ctx->ht.extension_chan_offset =
+					IEEE80211_HT_PARAM_CHA_SEC_NONE;
+					ctx->ht.is_40mhz = false;
+				}
+			} else
+				ctx->ht.is_40mhz = false;
+
+			/*
+			 * Default to no protection. Protection mode will
+			 * later be set from BSS config in iwl_ht_conf
+			 */
+			ctx->ht.protection =
+					IEEE80211_HT_OP_MODE_PROTECTION_NONE;
+
+			/* 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(ctx->staging.channel) != ch))
+				ctx->staging.flags = 0;
+
+			iwl_legacy_set_rxon_channel(priv, channel, ctx);
+			iwl_legacy_set_rxon_ht(priv, ht_conf);
+
+			iwl_legacy_set_flags_for_band(priv, ctx, channel->band,
+					       ctx->vif);
+		}
+
+		spin_unlock_irqrestore(&priv->lock, flags);
+
+		if (priv->cfg->ops->legacy->update_bcast_stations)
+			ret =
+			priv->cfg->ops->legacy->update_bcast_stations(priv);
+
+ 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_legacy_set_rate(priv);
+	}
+
+	if (changed & (IEEE80211_CONF_CHANGE_PS |
+			IEEE80211_CONF_CHANGE_IDLE)) {
+		ret = iwl_legacy_power_update_mode(priv, false);
+		if (ret)
+			IWL_DEBUG_MAC80211(priv, "Error setting sleep 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_legacy_set_tx_power(priv, conf->power_level, false);
+	}
+
+	if (!iwl_legacy_is_ready(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
+		goto out;
+	}
+
+	if (scan_active)
+		goto out;
+
+	for_each_context(priv, ctx) {
+		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
+			iwl_legacy_commit_rxon(priv, ctx);
+		else
+			IWL_DEBUG_INFO(priv,
+				"Not re-sending same RXON configuration.\n");
+		if (ht_changed[ctx->ctxid])
+			iwl_legacy_update_qos(priv, ctx);
+	}
+
+out:
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_config);
+
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	/* IBSS can only be the IWL_RXON_CTX_BSS context */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	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_config));
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* new association get rid of ibss beacon skb */
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = NULL;
+
+	priv->timestamp = 0;
+
+	spin_unlock_irqrestore(&priv->lock, flags);
+
+	iwl_legacy_scan_cancel_timeout(priv, 100);
+	if (!iwl_legacy_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
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl_legacy_commit_rxon(priv, ctx);
+
+	iwl_legacy_set_rate(priv);
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
+
+static void iwl_legacy_ht_conf(struct iwl_priv *priv,
+			struct ieee80211_vif *vif)
+{
+	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct ieee80211_sta *sta;
+	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	IWL_DEBUG_ASSOC(priv, "enter:\n");
+
+	if (!ctx->ht.enabled)
+		return;
+
+	ctx->ht.protection =
+		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
+	ctx->ht.non_gf_sta_present =
+		!!(bss_conf->ht_operation_mode &
+				IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
+
+	ht_conf->single_chain_sufficient = false;
+
+	switch (vif->type) {
+	case NL80211_IFTYPE_STATION:
+		rcu_read_lock();
+		sta = ieee80211_find_sta(vif, bss_conf->bssid);
+		if (sta) {
+			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
+			int maxstreams;
+
+			maxstreams = (ht_cap->mcs.tx_params &
+			      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
+				>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			if ((ht_cap->mcs.rx_mask[1] == 0) &&
+			    (ht_cap->mcs.rx_mask[2] == 0))
+				ht_conf->single_chain_sufficient = true;
+			if (maxstreams <= 1)
+				ht_conf->single_chain_sufficient = true;
+		} else {
+			/*
+			 * If at all, this can only happen through a race
+			 * when the AP disconnects us while we're still
+			 * setting up the connection, in that case mac80211
+			 * will soon tell us about that.
+			 */
+			ht_conf->single_chain_sufficient = true;
+		}
+		rcu_read_unlock();
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		ht_conf->single_chain_sufficient = true;
+		break;
+	default:
+		break;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "leave\n");
+}
+
+static inline void iwl_legacy_set_no_assoc(struct iwl_priv *priv,
+				    struct ieee80211_vif *vif)
+{
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+
+	/*
+	 * inform the ucode that there is no longer an
+	 * association and that no more packets should be
+	 * sent
+	 */
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	ctx->staging.assoc_id = 0;
+	iwl_legacy_commit_rxon(priv, ctx);
+}
+
+static void iwl_legacy_beacon_update(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif)
+{
+	struct iwl_priv *priv = hw->priv;
+	unsigned long flags;
+	__le64 timestamp;
+	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
+
+	if (!skb)
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!priv->beacon_ctx) {
+		IWL_ERR(priv, "update beacon but no beacon context!\n");
+		dev_kfree_skb(skb);
+		return;
+	}
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	if (priv->beacon_skb)
+		dev_kfree_skb(priv->beacon_skb);
+
+	priv->beacon_skb = skb;
+
+	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);
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
+		return;
+	}
+
+	priv->cfg->ops->legacy->post_associate(priv);
+}
+
+void iwl_legacy_mac_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;
+	struct iwl_rxon_context *ctx = iwl_legacy_rxon_ctx_from_vif(vif);
+	int ret;
+
+	if (WARN_ON(!priv->cfg->ops->legacy))
+		return;
+
+	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
+
+	if (!iwl_legacy_is_alive(priv))
+		return;
+
+	mutex_lock(&priv->mutex);
+
+	if (changes & BSS_CHANGED_QOS) {
+		unsigned long flags;
+
+		spin_lock_irqsave(&priv->lock, flags);
+		ctx->qos_data.qos_active = bss_conf->qos;
+		iwl_legacy_update_qos(priv, ctx);
+		spin_unlock_irqrestore(&priv->lock, flags);
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		/*
+		 * the add_interface code must make sure we only ever
+		 * have a single interface that could be beaconing at
+		 * any time.
+		 */
+		if (vif->bss_conf.enable_beacon)
+			priv->beacon_ctx = ctx;
+		else
+			priv->beacon_ctx = NULL;
+	}
+
+	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_legacy_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 (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+
+			/* currently needed in a few places */
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+		} else {
+			ctx->staging.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 (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
+		iwl_legacy_beacon_update(hw, vif);
+
+	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)
+			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
+		else
+			ctx->staging.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))
+			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
+		else
+			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
+		if (bss_conf->use_cts_prot)
+			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
+		else
+			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
+	}
+
+	if (changes & BSS_CHANGED_BASIC_RATES) {
+		/* XXX use this information
+		 *
+		 * To do that, remove code from iwl_legacy_set_rate() and put something
+		 * like this here:
+		 *
+		if (A-band)
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates;
+		else
+			ctx->staging.ofdm_basic_rates =
+				bss_conf->basic_rates >> 4;
+			ctx->staging.cck_basic_rates =
+				bss_conf->basic_rates & 0xF;
+		 */
+	}
+
+	if (changes & BSS_CHANGED_HT) {
+		iwl_legacy_ht_conf(priv, vif);
+
+		if (priv->cfg->ops->hcmd->set_rxon_chain)
+			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
+	}
+
+	if (changes & BSS_CHANGED_ASSOC) {
+		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
+		if (bss_conf->assoc) {
+			priv->timestamp = bss_conf->timestamp;
+
+			if (!iwl_legacy_is_rfkill(priv))
+				priv->cfg->ops->legacy->post_associate(priv);
+		} else
+			iwl_legacy_set_no_assoc(priv, vif);
+	}
+
+	if (changes && iwl_legacy_is_associated_ctx(ctx) && bss_conf->aid) {
+		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
+				   changes);
+		ret = iwl_legacy_send_rxon_assoc(priv, ctx);
+		if (!ret) {
+			/* Sync active_rxon with latest change. */
+			memcpy((void *)&ctx->active,
+				&ctx->staging,
+				sizeof(struct iwl_legacy_rxon_cmd));
+		}
+	}
+
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		if (vif->bss_conf.enable_beacon) {
+			memcpy(ctx->staging.bssid_addr,
+			       bss_conf->bssid, ETH_ALEN);
+			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
+			priv->cfg->ops->legacy->config_ap(priv);
+		} else
+			iwl_legacy_set_no_assoc(priv, vif);
+	}
+
+	if (changes & BSS_CHANGED_IBSS) {
+		ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
+							bss_conf->ibss_joined);
+		if (ret)
+			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
+				bss_conf->ibss_joined ? "add" : "remove",
+				bss_conf->bssid);
+	}
+
+	mutex_unlock(&priv->mutex);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+}
+EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
+
+irqreturn_t iwl_legacy_isr(int irq, void *data)
+{
+	struct iwl_priv *priv = data;
+	u32 inta, inta_mask;
+	u32 inta_fh;
+	unsigned long flags;
+	if (!priv)
+		return IRQ_NONE;
+
+	spin_lock_irqsave(&priv->lock, flags);
+
+	/* 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);
+	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
+
+	/* 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 && !inta_fh) {
+		IWL_DEBUG_ISR(priv,
+			"Ignore interrupt, inta == 0, inta_fh == 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;
+	}
+
+	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
+		      inta, inta_mask, inta_fh);
+
+	inta &= ~CSR_INT_BIT_SCD;
+
+	/* iwl_irq_tasklet() will service interrupts and re-enable them */
+	if (likely(inta || inta_fh))
+		tasklet_schedule(&priv->irq_tasklet);
+
+unplugged:
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_HANDLED;
+
+none:
+	/* re-enable interrupts here since we don't have anything to service. */
+	/* only Re-enable if diabled by irq */
+	if (test_bit(STATUS_INT_ENABLED, &priv->status))
+		iwl_legacy_enable_interrupts(priv);
+	spin_unlock_irqrestore(&priv->lock, flags);
+	return IRQ_NONE;
+}
+EXPORT_SYMBOL(iwl_legacy_isr);
+
+/*
+ *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
+ *  function.
+ */
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+			       struct ieee80211_tx_info *info,
+			       __le16 fc, __le32 *tx_flags)
+{
+	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
+		*tx_flags |= TX_CMD_FLG_RTS_MSK;
+		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+
+		if (!ieee80211_is_mgmt(fc))
+			return;
+
+		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
+		case cpu_to_le16(IEEE80211_STYPE_AUTH):
+		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
+		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
+		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
+			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+			*tx_flags |= TX_CMD_FLG_CTS_MSK;
+			break;
+		}
+	} else if (info->control.rates[0].flags &
+		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
+		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
+		*tx_flags |= TX_CMD_FLG_CTS_MSK;
+		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-core.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-core.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-core.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,646 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_core_h__
+#define __iwl_legacy_core_h__
+
+/************************
+ * forward declarations *
+ ************************/
+struct iwl_host_cmd;
+struct iwl_cmd;
+
+
+#define IWLWIFI_VERSION "in-tree:"
+#define DRV_COPYRIGHT	"Copyright(c) 2003-2011 Intel Corporation"
+#define DRV_AUTHOR     "<ilw@linux.intel.com>"
+
+#define IWL_PCI_DEVICE(dev, subdev, cfg) \
+	.vendor = PCI_VENDOR_ID_INTEL,  .device = (dev), \
+	.subvendor = PCI_ANY_ID, .subdevice = (subdev), \
+	.driver_data = (kernel_ulong_t)&(cfg)
+
+#define TIME_UNIT		1024
+
+#define IWL_SKU_G       0x1
+#define IWL_SKU_A       0x2
+#define IWL_SKU_N       0x8
+
+#define IWL_CMD(x) case x: return #x
+
+struct iwl_hcmd_ops {
+	int (*rxon_assoc)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+	int (*commit_rxon)(struct iwl_priv *priv, struct iwl_rxon_context *ctx);
+	void (*set_rxon_chain)(struct iwl_priv *priv,
+			       struct iwl_rxon_context *ctx);
+};
+
+struct iwl_hcmd_utils_ops {
+	u16 (*get_hcmd_size)(u8 cmd_id, u16 len);
+	u16 (*build_addsta_hcmd)(const struct iwl_legacy_addsta_cmd *cmd,
+								u8 *data);
+	int (*request_scan)(struct iwl_priv *priv, struct ieee80211_vif *vif);
+	void (*post_scan)(struct iwl_priv *priv);
+};
+
+struct iwl_apm_ops {
+	int (*init)(struct iwl_priv *priv);
+	void (*config)(struct iwl_priv *priv);
+};
+
+struct iwl_debugfs_ops {
+	ssize_t (*rx_stats_read)(struct file *file, char __user *user_buf,
+				 size_t count, loff_t *ppos);
+	ssize_t (*tx_stats_read)(struct file *file, char __user *user_buf,
+				 size_t count, loff_t *ppos);
+	ssize_t (*general_stats_read)(struct file *file, char __user *user_buf,
+				      size_t count, loff_t *ppos);
+};
+
+struct iwl_temp_ops {
+	void (*temperature)(struct iwl_priv *priv);
+};
+
+struct iwl_lib_ops {
+	/* set hw dependent parameters */
+	int (*set_hw_params)(struct iwl_priv *priv);
+	/* Handling TX */
+	void (*txq_update_byte_cnt_tbl)(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq,
+					u16 byte_cnt);
+	int (*txq_attach_buf_to_tfd)(struct iwl_priv *priv,
+				     struct iwl_tx_queue *txq,
+				     dma_addr_t addr,
+				     u16 len, u8 reset, u8 pad);
+	void (*txq_free_tfd)(struct iwl_priv *priv,
+			     struct iwl_tx_queue *txq);
+	int (*txq_init)(struct iwl_priv *priv,
+			struct iwl_tx_queue *txq);
+	/* setup Rx handler */
+	void (*rx_handler_setup)(struct iwl_priv *priv);
+	/* alive notification after init uCode load */
+	void (*init_alive_start)(struct iwl_priv *priv);
+	/* check validity of rtc data address */
+	int (*is_valid_rtc_data_addr)(u32 addr);
+	/* 1st ucode load */
+	int (*load_ucode)(struct iwl_priv *priv);
+	int (*dump_nic_event_log)(struct iwl_priv *priv,
+				  bool full_log, char **buf, bool display);
+	void (*dump_nic_error_log)(struct iwl_priv *priv);
+	int (*dump_fh)(struct iwl_priv *priv, char **buf, bool display);
+	int (*set_channel_switch)(struct iwl_priv *priv,
+				  struct ieee80211_channel_switch *ch_switch);
+	/* 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);
+
+	/* eeprom operations (as defined in iwl-eeprom.h) */
+	struct iwl_eeprom_ops eeprom_ops;
+
+	/* temperature */
+	struct iwl_temp_ops temp_ops;
+	/* check for plcp health */
+	bool (*check_plcp_health)(struct iwl_priv *priv,
+					struct iwl_rx_packet *pkt);
+
+	struct iwl_debugfs_ops debugfs_ops;
+
+};
+
+struct iwl_led_ops {
+	int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
+};
+
+struct iwl_legacy_ops {
+	void (*post_associate)(struct iwl_priv *priv);
+	void (*config_ap)(struct iwl_priv *priv);
+	/* station management */
+	int (*update_bcast_stations)(struct iwl_priv *priv);
+	int (*manage_ibss_station)(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif, bool add);
+};
+
+struct iwl_ops {
+	const struct iwl_lib_ops *lib;
+	const struct iwl_hcmd_ops *hcmd;
+	const struct iwl_hcmd_utils_ops *utils;
+	const struct iwl_led_ops *led;
+	const struct iwl_nic_ops *nic;
+	const struct iwl_legacy_ops *legacy;
+	const struct ieee80211_ops *ieee80211_ops;
+};
+
+struct iwl_mod_params {
+	int sw_crypto;		/* def: 0 = using hardware encryption */
+	int disable_hw_scan;	/* def: 0 = use h/w scan */
+	int num_of_queues;	/* def: HW dependent */
+	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 */
+};
+
+/*
+ * @led_compensation: compensate on the led on/off time per HW according
+ *	to the deviation to achieve the desired led frequency.
+ *	The detail algorithm is described in iwl-led.c
+ * @chain_noise_num_beacons: number of beacons used to compute chain noise
+ * @plcp_delta_threshold: plcp error rate threshold used to trigger
+ *	radio tuning when there is a high receiving plcp error rate
+ * @wd_timeout: TX queues watchdog timeout
+ * @temperature_kelvin: temperature report by uCode in kelvin
+ * @max_event_log_size: size of event log buffer size for ucode event logging
+ * @ucode_tracing: support ucode continuous tracing
+ * @sensitivity_calib_by_driver: driver has the capability to perform
+ *	sensitivity calibration operation
+ * @chain_noise_calib_by_driver: driver has the capability to perform
+ *	chain noise calibration operation
+ */
+struct iwl_base_params {
+	int eeprom_size;
+	int num_of_queues;	/* def: HW dependent */
+	int num_of_ampdu_queues;/* def: HW dependent */
+	/* for iwl_legacy_apm_init() */
+	u32 pll_cfg_val;
+	bool set_l0s;
+	bool use_bsm;
+
+	u16 led_compensation;
+	int chain_noise_num_beacons;
+	u8 plcp_delta_threshold;
+	unsigned int wd_timeout;
+	bool temperature_kelvin;
+	u32 max_event_log_size;
+	const bool ucode_tracing;
+	const bool sensitivity_calib_by_driver;
+	const bool chain_noise_calib_by_driver;
+};
+
+/**
+ * struct iwl_cfg
+ * @fw_name_pre: Firmware filename prefix. The api version and extension
+ *	(.ucode) will be added to filename before loading from disk. The
+ *	filename is constructed as fw_name_pre<api>.ucode.
+ * @ucode_api_max: Highest version of uCode API supported by driver.
+ * @ucode_api_min: Lowest version of uCode API supported by driver.
+ * @scan_antennas: available antenna for scan operation
+ * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
+ *
+ * We enable the driver to be backward compatible wrt API version. The
+ * driver specifies which APIs it supports (with @ucode_api_max being the
+ * highest and @ucode_api_min the lowest). Firmware will only be loaded if
+ * it has a supported API version. The firmware's API version will be
+ * stored in @iwl_priv, enabling the driver to make runtime changes based
+ * on firmware version used.
+ *
+ * For example,
+ * if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
+ *	Driver interacts with Firmware API version >= 2.
+ * } else {
+ *	Driver interacts with Firmware API version 1.
+ * }
+ *
+ * The ideal usage of this infrastructure is to treat a new ucode API
+ * release as a new hardware revision. That is, through utilizing the
+ * iwl_hcmd_utils_ops etc. we accommodate different command structures
+ * and flows between hardware versions as well as their API
+ * versions.
+ *
+ */
+struct iwl_cfg {
+	/* params specific to an individual device within a device family */
+	const char *name;
+	const char *fw_name_pre;
+	const unsigned int ucode_api_max;
+	const unsigned int ucode_api_min;
+	u8   valid_tx_ant;
+	u8   valid_rx_ant;
+	unsigned int sku;
+	u16  eeprom_ver;
+	u16  eeprom_calib_ver;
+	const struct iwl_ops *ops;
+	/* module based parameters which can be set from modprobe cmd */
+	const struct iwl_mod_params *mod_params;
+	/* params not likely to change within a device family */
+	struct iwl_base_params *base_params;
+	/* params likely to change within a device family */
+	u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
+	u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
+	enum iwl_led_mode led_mode;
+};
+
+/***************************
+ *   L i b                 *
+ ***************************/
+
+struct ieee80211_hw *iwl_legacy_alloc_all(struct iwl_cfg *cfg);
+int iwl_legacy_mac_conf_tx(struct ieee80211_hw *hw, u16 queue,
+		    const struct ieee80211_tx_queue_params *params);
+int iwl_legacy_mac_tx_last_beacon(struct ieee80211_hw *hw);
+void iwl_legacy_set_rxon_hwcrypto(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			int hw_decrypt);
+int iwl_legacy_check_rxon_cmd(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx);
+int iwl_legacy_full_rxon_required(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx);
+int iwl_legacy_set_rxon_channel(struct iwl_priv *priv,
+			struct ieee80211_channel *ch,
+			struct iwl_rxon_context *ctx);
+void iwl_legacy_set_flags_for_band(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    enum ieee80211_band band,
+			    struct ieee80211_vif *vif);
+u8 iwl_legacy_get_single_channel_number(struct iwl_priv *priv,
+				  enum ieee80211_band band);
+void iwl_legacy_set_rxon_ht(struct iwl_priv *priv,
+			struct iwl_ht_config *ht_conf);
+bool iwl_legacy_is_ht40_tx_allowed(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx,
+			    struct ieee80211_sta_ht_cap *ht_cap);
+void iwl_legacy_connection_init_rx_config(struct iwl_priv *priv,
+				   struct iwl_rxon_context *ctx);
+void iwl_legacy_set_rate(struct iwl_priv *priv);
+int iwl_legacy_set_decrypted_flag(struct iwl_priv *priv,
+			   struct ieee80211_hdr *hdr,
+			   u32 decrypt_res,
+			   struct ieee80211_rx_status *stats);
+void iwl_legacy_irq_handle_error(struct iwl_priv *priv);
+int iwl_legacy_mac_add_interface(struct ieee80211_hw *hw,
+			  struct ieee80211_vif *vif);
+void iwl_legacy_mac_remove_interface(struct ieee80211_hw *hw,
+			      struct ieee80211_vif *vif);
+int iwl_legacy_mac_change_interface(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     enum nl80211_iftype newtype, bool newp2p);
+int iwl_legacy_alloc_txq_mem(struct iwl_priv *priv);
+void iwl_legacy_txq_mem(struct iwl_priv *priv);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv);
+void iwl_legacy_free_traffic_mem(struct iwl_priv *priv);
+void iwl_legacy_reset_traffic_log(struct iwl_priv *priv);
+void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
+				u16 length, struct ieee80211_hdr *header);
+void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
+				u16 length, struct ieee80211_hdr *header);
+const char *iwl_legacy_get_mgmt_string(int cmd);
+const char *iwl_legacy_get_ctrl_string(int cmd);
+void iwl_legacy_clear_traffic_stats(struct iwl_priv *priv);
+void iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx, __le16 fc,
+		      u16 len);
+#else
+static inline int iwl_legacy_alloc_traffic_mem(struct iwl_priv *priv)
+{
+	return 0;
+}
+static inline void iwl_legacy_free_traffic_mem(struct iwl_priv *priv)
+{
+}
+static inline void iwl_legacy_reset_traffic_log(struct iwl_priv *priv)
+{
+}
+static inline void iwl_legacy_dbg_log_tx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_legacy_dbg_log_rx_data_frame(struct iwl_priv *priv,
+		      u16 length, struct ieee80211_hdr *header)
+{
+}
+static inline void iwl_legacy_update_stats(struct iwl_priv *priv, bool is_tx,
+				    __le16 fc, u16 len)
+{
+}
+#endif
+/*****************************************************
+ * RX handlers.
+ * **************************************************/
+void iwl_legacy_rx_pm_sleep_notif(struct iwl_priv *priv,
+			   struct iwl_rx_mem_buffer *rxb);
+void iwl_legacy_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb);
+void iwl_legacy_rx_reply_error(struct iwl_priv *priv,
+			struct iwl_rx_mem_buffer *rxb);
+
+/*****************************************************
+* RX
+******************************************************/
+void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv);
+void iwl_legacy_cmd_queue_free(struct iwl_priv *priv);
+int iwl_legacy_rx_queue_alloc(struct iwl_priv *priv);
+void iwl_legacy_rx_queue_update_write_ptr(struct iwl_priv *priv,
+				  struct iwl_rx_queue *q);
+int iwl_legacy_rx_queue_space(const struct iwl_rx_queue *q);
+void iwl_legacy_tx_cmd_complete(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb);
+/* Handlers */
+void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
+					  struct iwl_rx_mem_buffer *rxb);
+void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt);
+void iwl_legacy_chswitch_done(struct iwl_priv *priv, bool is_success);
+void iwl_legacy_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+
+/* TX helpers */
+
+/*****************************************************
+* TX
+******************************************************/
+void iwl_legacy_txq_update_write_ptr(struct iwl_priv *priv,
+					struct iwl_tx_queue *txq);
+int iwl_legacy_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+		      int slots_num, u32 txq_id);
+void iwl_legacy_tx_queue_reset(struct iwl_priv *priv,
+			struct iwl_tx_queue *txq,
+			int slots_num, u32 txq_id);
+void iwl_legacy_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
+void iwl_legacy_tx_queue_free(struct iwl_priv *priv, int txq_id);
+void iwl_legacy_setup_watchdog(struct iwl_priv *priv);
+/*****************************************************
+ * TX power
+ ****************************************************/
+int iwl_legacy_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force);
+
+/*******************************************************************************
+ * Rate
+ ******************************************************************************/
+
+u8 iwl_legacy_get_lowest_plcp(struct iwl_priv *priv,
+			    struct iwl_rxon_context *ctx);
+
+/*******************************************************************************
+ * Scanning
+ ******************************************************************************/
+void iwl_legacy_init_scan_params(struct iwl_priv *priv);
+int iwl_legacy_scan_cancel(struct iwl_priv *priv);
+int iwl_legacy_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms);
+void iwl_legacy_force_scan_end(struct iwl_priv *priv);
+int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    struct cfg80211_scan_request *req);
+void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv);
+int iwl_legacy_force_reset(struct iwl_priv *priv, int mode, bool external);
+u16 iwl_legacy_fill_probe_req(struct iwl_priv *priv,
+			struct ieee80211_mgmt *frame,
+		       const u8 *ta, const u8 *ie, int ie_len, int left);
+void iwl_legacy_setup_rx_scan_handlers(struct iwl_priv *priv);
+u16 iwl_legacy_get_active_dwell_time(struct iwl_priv *priv,
+			      enum ieee80211_band band,
+			      u8 n_probes);
+u16 iwl_legacy_get_passive_dwell_time(struct iwl_priv *priv,
+			       enum ieee80211_band band,
+			       struct ieee80211_vif *vif);
+void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv);
+void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv);
+
+/* For faster active scanning, scan will move to the next channel if fewer than
+ * PLCP_QUIET_THRESH packets are heard on this channel within
+ * ACTIVE_QUIET_TIME after sending probe request.  This shortens the dwell
+ * time if it's a quiet channel (nothing responded to our probe, and there's
+ * no other traffic).
+ * Disable "quiet" feature by setting PLCP_QUIET_THRESH to 0. */
+#define IWL_ACTIVE_QUIET_TIME       cpu_to_le16(10)  /* msec */
+#define IWL_PLCP_QUIET_THRESH       cpu_to_le16(1)  /* packets */
+
+#define IWL_SCAN_CHECK_WATCHDOG		(HZ * 7)
+
+/*****************************************************
+ *   S e n d i n g     H o s t     C o m m a n d s   *
+ *****************************************************/
+
+const char *iwl_legacy_get_cmd_string(u8 cmd);
+int __must_check iwl_legacy_send_cmd_sync(struct iwl_priv *priv,
+				   struct iwl_host_cmd *cmd);
+int iwl_legacy_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+int __must_check iwl_legacy_send_cmd_pdu(struct iwl_priv *priv, u8 id,
+				  u16 len, const void *data);
+int iwl_legacy_send_cmd_pdu_async(struct iwl_priv *priv, u8 id, u16 len,
+			   const void *data,
+			   void (*callback)(struct iwl_priv *priv,
+					    struct iwl_device_cmd *cmd,
+					    struct iwl_rx_packet *pkt));
+
+int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd);
+
+
+/*****************************************************
+ * PCI						     *
+ *****************************************************/
+
+static inline u16 iwl_legacy_pcie_link_ctl(struct iwl_priv *priv)
+{
+	int pos;
+	u16 pci_lnk_ctl;
+	pos = pci_find_capability(priv->pci_dev, PCI_CAP_ID_EXP);
+	pci_read_config_word(priv->pci_dev, pos + PCI_EXP_LNKCTL, &pci_lnk_ctl);
+	return pci_lnk_ctl;
+}
+
+void iwl_legacy_bg_watchdog(unsigned long data);
+u32 iwl_legacy_usecs_to_beacons(struct iwl_priv *priv,
+					u32 usec, u32 beacon_interval);
+__le32 iwl_legacy_add_beacon_time(struct iwl_priv *priv, u32 base,
+			   u32 addon, u32 beacon_interval);
+
+#ifdef CONFIG_PM
+int iwl_legacy_pci_suspend(struct device *device);
+int iwl_legacy_pci_resume(struct device *device);
+extern const struct dev_pm_ops iwl_legacy_pm_ops;
+
+#define IWL_LEGACY_PM_OPS	(&iwl_legacy_pm_ops)
+
+#else /* !CONFIG_PM */
+
+#define IWL_LEGACY_PM_OPS	NULL
+
+#endif /* !CONFIG_PM */
+
+/*****************************************************
+*  Error Handling Debugging
+******************************************************/
+void iwl4965_dump_nic_error_log(struct iwl_priv *priv);
+int iwl4965_dump_nic_event_log(struct iwl_priv *priv,
+			   bool full_log, char **buf, bool display);
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
+			     struct iwl_rxon_context *ctx);
+#else
+static inline void iwl_legacy_print_rx_config_cmd(struct iwl_priv *priv,
+					   struct iwl_rxon_context *ctx)
+{
+}
+#endif
+
+void iwl_legacy_clear_isr_stats(struct iwl_priv *priv);
+
+/*****************************************************
+*  GEOS
+******************************************************/
+int iwl_legacy_init_geos(struct iwl_priv *priv);
+void iwl_legacy_free_geos(struct iwl_priv *priv);
+
+/*************** DRIVER STATUS FUNCTIONS   *****/
+
+#define STATUS_HCMD_ACTIVE	0	/* host command in progress */
+/* 1 is unused (used to be STATUS_HCMD_SYNC_ACTIVE) */
+#define STATUS_INT_ENABLED	2
+#define STATUS_RF_KILL_HW	3
+#define STATUS_CT_KILL		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_STATISTICS	12
+#define STATUS_SCANNING		13
+#define STATUS_SCAN_ABORTING	14
+#define STATUS_SCAN_HW		15
+#define STATUS_POWER_PMI	16
+#define STATUS_FW_ERROR		17
+
+
+static inline int iwl_legacy_is_ready(struct iwl_priv *priv)
+{
+	/* The adapter is 'ready' if READY and GEO_CONFIGURED bits are
+	 * set but EXIT_PENDING is not */
+	return test_bit(STATUS_READY, &priv->status) &&
+	       test_bit(STATUS_GEO_CONFIGURED, &priv->status) &&
+	       !test_bit(STATUS_EXIT_PENDING, &priv->status);
+}
+
+static inline int iwl_legacy_is_alive(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_ALIVE, &priv->status);
+}
+
+static inline int iwl_legacy_is_init(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_INIT, &priv->status);
+}
+
+static inline int iwl_legacy_is_rfkill_hw(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_RF_KILL_HW, &priv->status);
+}
+
+static inline int iwl_legacy_is_rfkill(struct iwl_priv *priv)
+{
+	return iwl_legacy_is_rfkill_hw(priv);
+}
+
+static inline int iwl_legacy_is_ctkill(struct iwl_priv *priv)
+{
+	return test_bit(STATUS_CT_KILL, &priv->status);
+}
+
+static inline int iwl_legacy_is_ready_rf(struct iwl_priv *priv)
+{
+
+	if (iwl_legacy_is_rfkill(priv))
+		return 0;
+
+	return iwl_legacy_is_ready(priv);
+}
+
+extern void iwl_legacy_send_bt_config(struct iwl_priv *priv);
+extern int iwl_legacy_send_statistics_request(struct iwl_priv *priv,
+				       u8 flags, bool clear);
+void iwl_legacy_apm_stop(struct iwl_priv *priv);
+int iwl_legacy_apm_init(struct iwl_priv *priv);
+
+int iwl_legacy_send_rxon_timing(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx);
+static inline int iwl_legacy_send_rxon_assoc(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx)
+{
+	return priv->cfg->ops->hcmd->rxon_assoc(priv, ctx);
+}
+static inline int iwl_legacy_commit_rxon(struct iwl_priv *priv,
+				      struct iwl_rxon_context *ctx)
+{
+	return priv->cfg->ops->hcmd->commit_rxon(priv, ctx);
+}
+static inline const struct ieee80211_supported_band *iwl_get_hw_mode(
+			struct iwl_priv *priv, enum ieee80211_band band)
+{
+	return priv->hw->wiphy->bands[band];
+}
+
+/* mac80211 handlers */
+int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
+void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
+void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
+				     struct ieee80211_vif *vif,
+				     struct ieee80211_bss_conf *bss_conf,
+				     u32 changes);
+void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
+				struct ieee80211_tx_info *info,
+				__le16 fc, __le32 *tx_flags);
+
+irqreturn_t iwl_legacy_isr(int irq, void *data);
+
+#endif /* __iwl_legacy_core_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-csr.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-csr.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-csr.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-csr.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,422 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+#ifndef __iwl_legacy_csr_h__
+#define __iwl_legacy_csr_h__
+/*
+ * CSR (control and status registers)
+ *
+ * CSR registers are mapped directly into PCI bus space, and are accessible
+ * whenever platform supplies power to device, even when device is in
+ * low power states due to driver-invoked device resets
+ * (e.g. CSR_RESET_REG_FLAG_SW_RESET) or uCode-driven power-saving modes.
+ *
+ * Use iwl_write32() and iwl_read32() family to access these registers;
+ * these provide simple PCI bus access, without waking up the MAC.
+ * Do not use iwl_legacy_write_direct32() family for these registers;
+ * no need to "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ.
+ * The MAC (uCode processor, etc.) does not need to be powered up for accessing
+ * the CSR registers.
+ *
+ * NOTE:  Device does need to be awake in order to read this memory
+ *        via CSR_EEPROM register
+ */
+#define CSR_BASE    (0x000)
+
+#define CSR_HW_IF_CONFIG_REG    (CSR_BASE+0x000) /* hardware interface config */
+#define CSR_INT_COALESCING      (CSR_BASE+0x004) /* accum ints, 32-usec units */
+#define CSR_INT                 (CSR_BASE+0x008) /* host interrupt status/ack */
+#define CSR_INT_MASK            (CSR_BASE+0x00c) /* host interrupt enable */
+#define CSR_FH_INT_STATUS       (CSR_BASE+0x010) /* busmaster int status/ack*/
+#define CSR_GPIO_IN             (CSR_BASE+0x018) /* read external chip pins */
+#define CSR_RESET               (CSR_BASE+0x020) /* busmaster enable, NMI, etc*/
+#define CSR_GP_CNTRL            (CSR_BASE+0x024)
+
+/* 2nd byte of CSR_INT_COALESCING, not accessible via iwl_write32()! */
+#define CSR_INT_PERIODIC_REG	(CSR_BASE+0x005)
+
+/*
+ * Hardware revision info
+ * Bit fields:
+ * 31-8:  Reserved
+ *  7-4:  Type of device:  see CSR_HW_REV_TYPE_xxx definitions
+ *  3-2:  Revision step:  0 = A, 1 = B, 2 = C, 3 = D
+ *  1-0:  "Dash" (-) value, as in A-1, etc.
+ *
+ * NOTE:  Revision step affects calculation of CCK txpower for 4965.
+ * NOTE:  See also CSR_HW_REV_WA_REG (work-around for bug in 4965).
+ */
+#define CSR_HW_REV              (CSR_BASE+0x028)
+
+/*
+ * EEPROM memory reads
+ *
+ * NOTE:  Device must be awake, initialized via apm_ops.init(),
+ *        in order to read.
+ */
+#define CSR_EEPROM_REG          (CSR_BASE+0x02c)
+#define CSR_EEPROM_GP           (CSR_BASE+0x030)
+
+#define CSR_GIO_REG		(CSR_BASE+0x03C)
+#define CSR_GP_UCODE_REG	(CSR_BASE+0x048)
+#define CSR_GP_DRIVER_REG	(CSR_BASE+0x050)
+
+/*
+ * UCODE-DRIVER GP (general purpose) mailbox registers.
+ * SET/CLR registers set/clear bit(s) if "1" is written.
+ */
+#define CSR_UCODE_DRV_GP1       (CSR_BASE+0x054)
+#define CSR_UCODE_DRV_GP1_SET   (CSR_BASE+0x058)
+#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)
+
+/* GIO Chicken Bits (PCI Express bus link power management) */
+#define CSR_GIO_CHICKEN_BITS    (CSR_BASE+0x100)
+
+/* Analog phase-lock-loop configuration  */
+#define CSR_ANA_PLL_CFG         (CSR_BASE+0x20c)
+
+/*
+ * CSR Hardware Revision Workaround Register.  Indicates hardware rev;
+ * "step" determines CCK backoff for txpower calculation.  Used for 4965 only.
+ * See also CSR_HW_REV register.
+ * Bit fields:
+ *  3-2:  0 = A, 1 = B, 2 = C, 3 = D step
+ *  1-0:  "Dash" (-) value, as in C-1, etc.
+ */
+#define CSR_HW_REV_WA_REG		(CSR_BASE+0x22C)
+
+#define CSR_DBG_HPET_MEM_REG		(CSR_BASE+0x240)
+#define CSR_DBG_LINK_PWR_MGMT_REG	(CSR_BASE+0x250)
+
+/* Bits for CSR_HW_IF_CONFIG_REG */
+#define CSR49_HW_IF_CONFIG_REG_BIT_4965_R	(0x00000010)
+#define CSR_HW_IF_CONFIG_REG_MSK_BOARD_VER	(0x00000C00)
+#define CSR_HW_IF_CONFIG_REG_BIT_MAC_SI 	(0x00000100)
+#define CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI	(0x00000200)
+
+#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MB         (0x00000100)
+#define CSR39_HW_IF_CONFIG_REG_BIT_3945_MM         (0x00000200)
+#define CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC            (0x00000400)
+#define CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE         (0x00000800)
+#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A    (0x00000000)
+#define CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B    (0x00001000)
+
+#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_NIC_READY	(0x00400000) /* PCI_OWN_SEM */
+#define CSR_HW_IF_CONFIG_REG_BIT_NIC_PREPARE_DONE (0x02000000) /* ME_OWN */
+#define CSR_HW_IF_CONFIG_REG_PREPARE		  (0x08000000) /* WAKE_ME */
+
+#define CSR_INT_PERIODIC_DIS			(0x00) /* disable periodic int*/
+#define CSR_INT_PERIODIC_ENA			(0xFF) /* 255*32 usec ~ 8 msec*/
+
+/* 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_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 */
+#define CSR_INT_BIT_RF_KILL      (1 << 7)  /* HW RFKILL switch GP_CNTRL[27] toggled */
+#define CSR_INT_BIT_CT_KILL      (1 << 6)  /* Critical temp (chip too hot) rfkill */
+#define CSR_INT_BIT_SW_RX        (1 << 3)  /* Rx, command responses, 3945 */
+#define CSR_INT_BIT_WAKEUP       (1 << 1)  /* NIC controller waking up (pwr mgmt) */
+#define CSR_INT_BIT_ALIVE        (1 << 0)  /* uCode interrupts once it initializes */
+
+#define CSR_INI_SET_MASK	(CSR_INT_BIT_FH_RX   | \
+				 CSR_INT_BIT_HW_ERR  | \
+				 CSR_INT_BIT_FH_TX   | \
+				 CSR_INT_BIT_SW_ERR  | \
+				 CSR_INT_BIT_RF_KILL | \
+				 CSR_INT_BIT_SW_RX   | \
+				 CSR_INT_BIT_WAKEUP  | \
+				 CSR_INT_BIT_ALIVE)
+
+/* interrupt flags in FH (flow handler) (PCI busmaster DMA) */
+#define CSR_FH_INT_BIT_ERR       (1 << 31) /* Error */
+#define CSR_FH_INT_BIT_HI_PRIOR  (1 << 30) /* High priority Rx, bypass coalescing */
+#define CSR39_FH_INT_BIT_RX_CHNL2  (1 << 18) /* Rx channel 2 (3945 only) */
+#define CSR_FH_INT_BIT_RX_CHNL1  (1 << 17) /* Rx channel 1 */
+#define CSR_FH_INT_BIT_RX_CHNL0  (1 << 16) /* Rx channel 0 */
+#define CSR39_FH_INT_BIT_TX_CHNL6  (1 << 6)  /* Tx channel 6 (3945 only) */
+#define CSR_FH_INT_BIT_TX_CHNL1  (1 << 1)  /* Tx channel 1 */
+#define CSR_FH_INT_BIT_TX_CHNL0  (1 << 0)  /* Tx channel 0 */
+
+#define CSR39_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
+				 CSR39_FH_INT_BIT_RX_CHNL2 | \
+				 CSR_FH_INT_BIT_RX_CHNL1 | \
+				 CSR_FH_INT_BIT_RX_CHNL0)
+
+
+#define CSR39_FH_INT_TX_MASK	(CSR39_FH_INT_BIT_TX_CHNL6 | \
+				 CSR_FH_INT_BIT_TX_CHNL1 | \
+				 CSR_FH_INT_BIT_TX_CHNL0)
+
+#define CSR49_FH_INT_RX_MASK	(CSR_FH_INT_BIT_HI_PRIOR | \
+				 CSR_FH_INT_BIT_RX_CHNL1 | \
+				 CSR_FH_INT_BIT_RX_CHNL0)
+
+#define CSR49_FH_INT_TX_MASK	(CSR_FH_INT_BIT_TX_CHNL1 | \
+				 CSR_FH_INT_BIT_TX_CHNL0)
+
+/* GPIO */
+#define CSR_GPIO_IN_BIT_AUX_POWER                   (0x00000200)
+#define CSR_GPIO_IN_VAL_VAUX_PWR_SRC                (0x00000000)
+#define CSR_GPIO_IN_VAL_VMAIN_PWR_SRC               (0x00000200)
+
+/* RESET */
+#define CSR_RESET_REG_FLAG_NEVO_RESET                (0x00000001)
+#define CSR_RESET_REG_FLAG_FORCE_NMI                 (0x00000002)
+#define CSR_RESET_REG_FLAG_SW_RESET                  (0x00000080)
+#define CSR_RESET_REG_FLAG_MASTER_DISABLED           (0x00000100)
+#define CSR_RESET_REG_FLAG_STOP_MASTER               (0x00000200)
+#define CSR_RESET_LINK_PWR_MGMT_DISABLED             (0x80000000)
+
+/*
+ * GP (general purpose) CONTROL REGISTER
+ * Bit fields:
+ *    27:  HW_RF_KILL_SW
+ *         Indicates state of (platform's) hardware RF-Kill switch
+ * 26-24:  POWER_SAVE_TYPE
+ *         Indicates current power-saving mode:
+ *         000 -- No power saving
+ *         001 -- MAC power-down
+ *         010 -- PHY (radio) power-down
+ *         011 -- Error
+ *   9-6:  SYS_CONFIG
+ *         Indicates current system configuration, reflecting pins on chip
+ *         as forced high/low by device circuit board.
+ *     4:  GOING_TO_SLEEP
+ *         Indicates MAC is entering a power-saving sleep power-down.
+ *         Not a good time to access device-internal resources.
+ *     3:  MAC_ACCESS_REQ
+ *         Host sets this to request and maintain MAC wakeup, to allow host
+ *         access to device-internal resources.  Host must wait for
+ *         MAC_CLOCK_READY (and !GOING_TO_SLEEP) before accessing non-CSR
+ *         device registers.
+ *     2:  INIT_DONE
+ *         Host sets this to put device into fully operational D0 power mode.
+ *         Host resets this after SW_RESET to put device into low power mode.
+ *     0:  MAC_CLOCK_READY
+ *         Indicates MAC (ucode processor, etc.) is powered up and can run.
+ *         Internal resources are accessible.
+ *         NOTE:  This does not indicate that the processor is actually running.
+ *         NOTE:  This does not indicate that 4965 or 3945 has completed
+ *                init or post-power-down restore of internal SRAM memory.
+ *                Use CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP as indication that
+ *                SRAM is restored and uCode is in normal operation mode.
+ *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
+ *                do not need to save/restore it.
+ *         NOTE:  After device reset, this bit remains "0" until host sets
+ *                INIT_DONE
+ */
+#define CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY        (0x00000001)
+#define CSR_GP_CNTRL_REG_FLAG_INIT_DONE              (0x00000004)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ         (0x00000008)
+#define CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP         (0x00000010)
+
+#define CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN           (0x00000001)
+
+#define CSR_GP_CNTRL_REG_MSK_POWER_SAVE_TYPE         (0x07000000)
+#define CSR_GP_CNTRL_REG_FLAG_MAC_POWER_SAVE         (0x04000000)
+#define CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW          (0x08000000)
+
+
+/* EEPROM REG */
+#define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
+#define CSR_EEPROM_REG_BIT_CMD		(0x00000002)
+#define CSR_EEPROM_REG_MSK_ADDR		(0x0000FFFC)
+#define CSR_EEPROM_REG_MSK_DATA		(0xFFFF0000)
+
+/* EEPROM GP */
+#define CSR_EEPROM_GP_VALID_MSK		(0x00000007) /* signature */
+#define CSR_EEPROM_GP_IF_OWNER_MSK	(0x00000180)
+#define CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K		(0x00000002)
+#define CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K		(0x00000004)
+
+/* GP REG */
+#define CSR_GP_REG_POWER_SAVE_STATUS_MSK            (0x03000000) /* bit 24/25 */
+#define CSR_GP_REG_NO_POWER_SAVE            (0x00000000)
+#define CSR_GP_REG_MAC_POWER_SAVE           (0x01000000)
+#define CSR_GP_REG_PHY_POWER_SAVE           (0x02000000)
+#define CSR_GP_REG_POWER_SAVE_ERROR         (0x03000000)
+
+
+/* CSR GIO */
+#define CSR_GIO_REG_VAL_L0S_ENABLED	(0x00000002)
+
+/*
+ * UCODE-DRIVER GP (general purpose) mailbox register 1
+ * Host driver and uCode write and/or read this register to communicate with
+ * each other.
+ * Bit fields:
+ *     4:  UCODE_DISABLE
+ *         Host sets this to request permanent halt of uCode, same as
+ *         sending CARD_STATE command with "halt" bit set.
+ *     3:  CT_KILL_EXIT
+ *         Host sets this to request exit from CT_KILL state, i.e. host thinks
+ *         device temperature is low enough to continue normal operation.
+ *     2:  CMD_BLOCKED
+ *         Host sets this during RF KILL power-down sequence (HW, SW, CT KILL)
+ *         to release uCode to clear all Tx and command queues, enter
+ *         unassociated mode, and power down.
+ *         NOTE:  Some devices also use HBUS_TARG_MBX_C register for this bit.
+ *     1:  SW_BIT_RFKILL
+ *         Host sets this when issuing CARD_STATE command to request
+ *         device sleep.
+ *     0:  MAC_SLEEP
+ *         uCode sets this when preparing a power-saving power-down.
+ *         uCode resets this when power-up is complete and SRAM is sane.
+ *         NOTE:  3945/4965 saves internal SRAM data to host when powering down,
+ *                and must restore this data after powering back up.
+ *                MAC_SLEEP is the best indication that restore is complete.
+ *                Later devices (5xxx/6xxx/1xxx) use non-volatile SRAM, and
+ *                do not need to save/restore it.
+ */
+#define CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP             (0x00000001)
+#define CSR_UCODE_SW_BIT_RFKILL                     (0x00000002)
+#define CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED           (0x00000004)
+#define CSR_UCODE_DRV_GP1_REG_BIT_CT_KILL_EXIT      (0x00000008)
+
+/* GIO Chicken Bits (PCI Express bus link power management) */
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
+#define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
+
+/* LED */
+#define CSR_LED_BSM_CTRL_MSK (0xFFFFFFDF)
+#define CSR_LED_REG_TRUN_ON (0x78)
+#define CSR_LED_REG_TRUN_OFF (0x38)
+
+/* ANA_PLL */
+#define CSR39_ANA_PLL_CFG_VAL        (0x01000000)
+
+/* 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)
+ *
+ * HBUS registers are mapped directly into PCI bus space, but are used
+ * to indirectly access device's internal memory or registers that
+ * may be powered-down.
+ *
+ * Use iwl_legacy_write_direct32()/iwl_legacy_read_direct32() family
+ * for these registers;
+ * host must "grab nic access" via CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ
+ * to make sure the MAC (uCode processor, etc.) is powered up for accessing
+ * internal resources.
+ *
+ * Do not use iwl_write32()/iwl_read32() family to access these registers;
+ * these provide only simple PCI bus access, without waking up the MAC.
+ */
+#define HBUS_BASE	(0x400)
+
+/*
+ * Registers for accessing device's internal SRAM memory (e.g. SCD SRAM
+ * structures, error log, event log, verifying uCode load).
+ * First write to address register, then read from or write to data register
+ * to complete the job.  Once the address register is set up, accesses to
+ * data registers auto-increment the address by one dword.
+ * Bit usage for address registers (read or write):
+ *  0-31:  memory address within device
+ */
+#define HBUS_TARG_MEM_RADDR     (HBUS_BASE+0x00c)
+#define HBUS_TARG_MEM_WADDR     (HBUS_BASE+0x010)
+#define HBUS_TARG_MEM_WDAT      (HBUS_BASE+0x018)
+#define HBUS_TARG_MEM_RDAT      (HBUS_BASE+0x01c)
+
+/* Mailbox C, used as workaround alternative to CSR_UCODE_DRV_GP1 mailbox */
+#define HBUS_TARG_MBX_C         (HBUS_BASE+0x030)
+#define HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED         (0x00000004)
+
+/*
+ * Registers for accessing device's internal peripheral registers
+ * (e.g. SCD, BSM, etc.).  First write to address register,
+ * then read from or write to data register to complete the job.
+ * Bit usage for address registers (read or write):
+ *  0-15:  register address (offset) within device
+ * 24-25:  (# bytes - 1) to read or write (e.g. 3 for dword)
+ */
+#define HBUS_TARG_PRPH_WADDR    (HBUS_BASE+0x044)
+#define HBUS_TARG_PRPH_RADDR    (HBUS_BASE+0x048)
+#define HBUS_TARG_PRPH_WDAT     (HBUS_BASE+0x04c)
+#define HBUS_TARG_PRPH_RDAT     (HBUS_BASE+0x050)
+
+/*
+ * Per-Tx-queue write pointer (index, really!)
+ * Indicates index to next TFD that driver will fill (1 past latest filled).
+ * Bit usage:
+ *  0-7:  queue write index
+ * 11-8:  queue selector
+ */
+#define HBUS_TARG_WRPTR         (HBUS_BASE+0x060)
+
+#endif /* !__iwl_legacy_csr_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-debugfs.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1467 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#include <linux/ieee80211.h>
+#include <net/mac80211.h>
+
+
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* create and remove of files */
+#define DEBUGFS_ADD_FILE(name, parent, mode) do {			\
+	if (!debugfs_create_file(#name, mode, parent, priv,		\
+			 &iwl_legacy_dbgfs_##name##_ops))		\
+		goto err;						\
+} while (0)
+
+#define DEBUGFS_ADD_BOOL(name, parent, ptr) do {			\
+	struct dentry *__tmp;						\
+	__tmp = debugfs_create_bool(#name, S_IWUSR | S_IRUSR,		\
+				    parent, ptr);			\
+	if (IS_ERR(__tmp) || !__tmp)					\
+		goto err;						\
+} while (0)
+
+#define DEBUGFS_ADD_X32(name, parent, ptr) do {				\
+	struct dentry *__tmp;						\
+	__tmp = debugfs_create_x32(#name, S_IWUSR | S_IRUSR,		\
+				   parent, ptr);			\
+	if (IS_ERR(__tmp) || !__tmp)					\
+		goto err;						\
+} while (0)
+
+/* file operation */
+#define DEBUGFS_READ_FUNC(name)                                         \
+static ssize_t iwl_legacy_dbgfs_##name##_read(struct file *file,               \
+					char __user *user_buf,          \
+					size_t count, loff_t *ppos);
+
+#define DEBUGFS_WRITE_FUNC(name)                                        \
+static ssize_t iwl_legacy_dbgfs_##name##_write(struct file *file,              \
+					const char __user *user_buf,    \
+					size_t count, loff_t *ppos);
+
+
+static int
+iwl_legacy_dbgfs_open_file_generic(struct inode *inode, struct file *file)
+{
+	file->private_data = inode->i_private;
+	return 0;
+}
+
+#define DEBUGFS_READ_FILE_OPS(name) 				\
+	DEBUGFS_READ_FUNC(name);                                        \
+static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {	\
+	.read = iwl_legacy_dbgfs_##name##_read,				\
+	.open = iwl_legacy_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
+};
+
+#define DEBUGFS_WRITE_FILE_OPS(name) 				\
+	DEBUGFS_WRITE_FUNC(name);                                       \
+static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {	\
+	.write = iwl_legacy_dbgfs_##name##_write,			\
+	.open = iwl_legacy_dbgfs_open_file_generic,                    	\
+	.llseek = generic_file_llseek,					\
+};
+
+#define DEBUGFS_READ_WRITE_FILE_OPS(name)                           \
+	DEBUGFS_READ_FUNC(name);                                        \
+	DEBUGFS_WRITE_FUNC(name);                                       \
+static const struct file_operations iwl_legacy_dbgfs_##name##_ops = {	\
+	.write = iwl_legacy_dbgfs_##name##_write,			\
+	.read = iwl_legacy_dbgfs_##name##_read,				\
+	.open = iwl_legacy_dbgfs_open_file_generic,			\
+	.llseek = generic_file_llseek,					\
+};
+
+static ssize_t iwl_legacy_dbgfs_tx_statistics_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+
+	int cnt;
+	ssize_t ret;
+	const size_t bufsz = 100 +
+		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_mgmt_string(cnt),
+				 priv->tx_stats.mgmt[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Control\n");
+	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_ctrl_string(cnt),
+				 priv->tx_stats.ctrl[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+			 priv->tx_stats.data_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+			 priv->tx_stats.data_bytes);
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t
+iwl_legacy_dbgfs_clear_traffic_statistics_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	u32 clear_flag;
+	char buf[8];
+	int buf_size;
+
+	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", &clear_flag) != 1)
+		return -EFAULT;
+	iwl_legacy_clear_traffic_stats(priv);
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_rx_statistics_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+	int cnt;
+	ssize_t ret;
+	const size_t bufsz = 100 +
+		sizeof(char) * 50 * (MANAGEMENT_MAX + CONTROL_MAX);
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Management:\n");
+	for (cnt = 0; cnt < MANAGEMENT_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_mgmt_string(cnt),
+				 priv->rx_stats.mgmt[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Control:\n");
+	for (cnt = 0; cnt < CONTROL_MAX; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "\t%25s\t\t: %u\n",
+				 iwl_legacy_get_ctrl_string(cnt),
+				 priv->rx_stats.ctrl[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Data:\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "\tcnt: %u\n",
+			 priv->rx_stats.data_cnt);
+	pos += scnprintf(buf + pos, bufsz - pos, "\tbytes: %llu\n",
+			 priv->rx_stats.data_bytes);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+#define BYTE1_MASK 0x000000ff;
+#define BYTE2_MASK 0x0000ffff;
+#define BYTE3_MASK 0x00ffffff;
+static ssize_t iwl_legacy_dbgfs_sram_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	u32 val;
+	char *buf;
+	ssize_t ret;
+	int i;
+	int pos = 0;
+	struct iwl_priv *priv = file->private_data;
+	size_t bufsz;
+
+	/* default is to dump the entire data segment */
+	if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
+		priv->dbgfs_sram_offset = 0x800000;
+		if (priv->ucode_type == UCODE_INIT)
+			priv->dbgfs_sram_len = priv->ucode_init_data.len;
+		else
+			priv->dbgfs_sram_len = priv->ucode_data.len;
+	}
+	bufsz =  30 + priv->dbgfs_sram_len * sizeof(char) * 10;
+	buf = kmalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
+			priv->dbgfs_sram_len);
+	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
+			priv->dbgfs_sram_offset);
+	for (i = priv->dbgfs_sram_len; i > 0; i -= 4) {
+		val = iwl_legacy_read_targ_mem(priv, priv->dbgfs_sram_offset + \
+					priv->dbgfs_sram_len - i);
+		if (i < 4) {
+			switch (i) {
+			case 1:
+				val &= BYTE1_MASK;
+				break;
+			case 2:
+				val &= BYTE2_MASK;
+				break;
+			case 3:
+				val &= BYTE3_MASK;
+				break;
+			}
+		}
+		if (!(i % 16))
+			pos += scnprintf(buf + pos, bufsz - pos, "\n");
+		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_sram_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[64];
+	int buf_size;
+	u32 offset, len;
+
+	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,%x", &offset, &len) == 2) {
+		priv->dbgfs_sram_offset = offset;
+		priv->dbgfs_sram_len = len;
+	} else {
+		priv->dbgfs_sram_offset = 0;
+		priv->dbgfs_sram_len = 0;
+	}
+
+	return count;
+}
+
+static ssize_t
+iwl_legacy_dbgfs_stations_read(struct file *file, char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_station_entry *station;
+	int max_sta = priv->hw_params.max_stations;
+	char *buf;
+	int i, j, pos = 0;
+	ssize_t ret;
+	/* Add 30 for initial string */
+	const size_t bufsz = 30 + sizeof(char) * 500 * (priv->num_stations);
+
+	buf = kmalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "num of stations: %d\n\n",
+			priv->num_stations);
+
+	for (i = 0; i < max_sta; i++) {
+		station = &priv->stations[i];
+		if (!station->used)
+			continue;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				 "station %d - addr: %pM, flags: %#x\n",
+				 i, station->sta.sta.addr,
+				 station->sta.station_flags_msk);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"TID\tseq_num\ttxq_id\tframes\ttfds\t");
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"start_idx\tbitmap\t\t\trate_n_flags\n");
+
+		for (j = 0; j < MAX_TID_COUNT; j++) {
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%d:\t%#x\t%#x\t%u\t%u\t%u\t\t%#.16llx\t%#x",
+				j, station->tid[j].seq_number,
+				station->tid[j].agg.txq_id,
+				station->tid[j].agg.frame_count,
+				station->tid[j].tfds_in_queue,
+				station->tid[j].agg.start_idx,
+				station->tid[j].agg.bitmap,
+				station->tid[j].agg.rate_n_flags);
+
+			if (station->tid[j].agg.wait_for_ba)
+				pos += scnprintf(buf + pos, bufsz - pos,
+						 " - waitforba");
+			pos += scnprintf(buf + pos, bufsz - pos, "\n");
+		}
+
+		pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_nvm_read(struct file *file,
+				       char __user *user_buf,
+				       size_t count,
+				       loff_t *ppos)
+{
+	ssize_t ret;
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0, ofs = 0, buf_size = 0;
+	const u8 *ptr;
+	char *buf;
+	u16 eeprom_ver;
+	size_t eeprom_len = priv->cfg->base_params->eeprom_size;
+	buf_size = 4 * eeprom_len + 256;
+
+	if (eeprom_len % 16) {
+		IWL_ERR(priv, "NVM size is not multiple of 16.\n");
+		return -ENODATA;
+	}
+
+	ptr = priv->eeprom;
+	if (!ptr) {
+		IWL_ERR(priv, "Invalid EEPROM 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;
+	}
+	eeprom_ver = iwl_legacy_eeprom_query16(priv, EEPROM_VERSION);
+	pos += scnprintf(buf + pos, buf_size - pos, "EEPROM "
+			"version: 0x%x\n", eeprom_ver);
+	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,
+				   buf_size - pos, 0);
+		pos += strlen(buf + pos);
+		if (buf_size - pos > 0)
+			buf[pos++] = '\n';
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_log_event_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+	ssize_t ret = -ENOMEM;
+
+	ret = pos = priv->cfg->ops->lib->dump_nic_event_log(
+					priv, true, &buf, true);
+	if (buf) {
+		ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+		kfree(buf);
+	}
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_log_event_write(struct file *file,
+					const char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	u32 event_log_flag;
+	char buf[8];
+	int buf_size;
+
+	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, "%d", &event_log_flag) != 1)
+		return -EFAULT;
+	if (event_log_flag == 1)
+		priv->cfg->ops->lib->dump_nic_event_log(priv, true,
+							NULL, false);
+
+	return count;
+}
+
+
+
+static ssize_t
+iwl_legacy_dbgfs_channels_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	struct ieee80211_channel *channels = NULL;
+	const struct ieee80211_supported_band *supp_band = NULL;
+	int pos = 0, i, bufsz = PAGE_SIZE;
+	char *buf;
+	ssize_t ret;
+
+	if (!test_bit(STATUS_GEO_CONFIGURED, &priv->status))
+		return -EAGAIN;
+
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	supp_band = iwl_get_hw_mode(priv, IEEE80211_BAND_2GHZ);
+	if (supp_band) {
+		channels = supp_band->channels;
+
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"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",
+				channels[i].hw_value,
+				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);
+	if (supp_band) {
+		channels = supp_band->channels;
+
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"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",
+				channels[i].hw_value,
+				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;
+}
+
+static ssize_t iwl_legacy_dbgfs_status_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	char buf[512];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_HCMD_ACTIVE:\t %d\n",
+		test_bit(STATUS_HCMD_ACTIVE, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_INT_ENABLED:\t %d\n",
+		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_CT_KILL:\t\t %d\n",
+		test_bit(STATUS_CT_KILL, &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",
+		test_bit(STATUS_ALIVE, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_READY:\t\t %d\n",
+		test_bit(STATUS_READY, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_TEMPERATURE:\t %d\n",
+		test_bit(STATUS_TEMPERATURE, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_GEO_CONFIGURED:\t %d\n",
+		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_STATISTICS:\t %d\n",
+		test_bit(STATUS_STATISTICS, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCANNING:\t %d\n",
+		test_bit(STATUS_SCANNING, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_ABORTING:\t %d\n",
+		test_bit(STATUS_SCAN_ABORTING, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_SCAN_HW:\t\t %d\n",
+		test_bit(STATUS_SCAN_HW, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_POWER_PMI:\t %d\n",
+		test_bit(STATUS_POWER_PMI, &priv->status));
+	pos += scnprintf(buf + pos, bufsz - pos, "STATUS_FW_ERROR:\t %d\n",
+		test_bit(STATUS_FW_ERROR, &priv->status));
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_interrupt_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *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 || priv->isr_stats.hw) {
+		pos += scnprintf(buf + pos, bufsz - pos,
+			"\tLast Restarting Code:  0x%X\n",
+			priv->isr_stats.err_code);
+	}
+#ifdef CONFIG_IWLWIFI_LEGACY_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",
+				iwl_legacy_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_legacy_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_legacy_clear_isr_stats(priv);
+
+	return count;
+}
+
+static ssize_t
+iwl_legacy_dbgfs_qos_read(struct file *file, char __user *user_buf,
+				       size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_rxon_context *ctx;
+	int pos = 0, i;
+	char buf[256 * NUM_IWL_RXON_CTX];
+	const size_t bufsz = sizeof(buf);
+
+	for_each_context(priv, ctx) {
+		pos += scnprintf(buf + pos, bufsz - pos, "context %d:\n",
+				 ctx->ctxid);
+		for (i = 0; i < AC_NUM; i++) {
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"\tcw_min\tcw_max\taifsn\ttxop\n");
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"AC[%d]\t%u\t%u\t%u\t%u\n", i,
+				ctx->qos_data.def_qos_parm.ac[i].cw_min,
+				ctx->qos_data.def_qos_parm.ac[i].cw_max,
+				ctx->qos_data.def_qos_parm.ac[i].aifsn,
+				ctx->qos_data.def_qos_parm.ac[i].edca_txop);
+		}
+		pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	}
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_disable_ht40_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;
+	int ht40;
+
+	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, "%d", &ht40) != 1)
+		return -EFAULT;
+	if (!iwl_legacy_is_any_associated(priv))
+		priv->disable_ht40 = ht40 ? true : false;
+	else {
+		IWL_ERR(priv, "Sta associated with AP - "
+			"Change to 40MHz channel support is not allowed\n");
+		return -EINVAL;
+	}
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_disable_ht40_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[100];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"11n 40MHz Mode: %s\n",
+			priv->disable_ht40 ? "Disabled" : "Enabled");
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+DEBUGFS_READ_WRITE_FILE_OPS(sram);
+DEBUGFS_READ_WRITE_FILE_OPS(log_event);
+DEBUGFS_READ_FILE_OPS(nvm);
+DEBUGFS_READ_FILE_OPS(stations);
+DEBUGFS_READ_FILE_OPS(channels);
+DEBUGFS_READ_FILE_OPS(status);
+DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
+DEBUGFS_READ_FILE_OPS(qos);
+DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
+
+static ssize_t iwl_legacy_dbgfs_traffic_log_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0, ofs = 0;
+	int cnt = 0, entry;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	char *buf;
+	int bufsz = ((IWL_TRAFFIC_ENTRIES * IWL_TRAFFIC_ENTRY_SIZE * 64) * 2) +
+		(priv->cfg->base_params->num_of_queues * 32 * 8) + 400;
+	const u8 *ptr;
+	ssize_t ret;
+
+	if (!priv->txq) {
+		IWL_ERR(priv, "txq not ready\n");
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate buffer\n");
+		return -ENOMEM;
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "Tx Queue\n");
+	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+		txq = &priv->txq[cnt];
+		q = &txq->q;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"q[%d]: read_ptr: %u, write_ptr: %u\n",
+				cnt, q->read_ptr, q->write_ptr);
+	}
+	if (priv->tx_traffic && (iwlegacy_debug_level & IWL_DL_TX)) {
+		ptr = priv->tx_traffic;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Tx Traffic idx: %u\n",	priv->tx_traffic_idx);
+		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+			     entry++,  ofs += 16) {
+				pos += scnprintf(buf + pos, bufsz - pos,
+						"0x%.4x ", ofs);
+				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+						   buf + pos, bufsz - pos, 0);
+				pos += strlen(buf + pos);
+				if (bufsz - pos > 0)
+					buf[pos++] = '\n';
+			}
+		}
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Rx Queue\n");
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"read: %u, write: %u\n",
+			 rxq->read, rxq->write);
+
+	if (priv->rx_traffic && (iwlegacy_debug_level & IWL_DL_RX)) {
+		ptr = priv->rx_traffic;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Rx Traffic idx: %u\n",	priv->rx_traffic_idx);
+		for (cnt = 0, ofs = 0; cnt < IWL_TRAFFIC_ENTRIES; cnt++) {
+			for (entry = 0; entry < IWL_TRAFFIC_ENTRY_SIZE / 16;
+			     entry++,  ofs += 16) {
+				pos += scnprintf(buf + pos, bufsz - pos,
+						"0x%.4x ", ofs);
+				hex_dump_to_buffer(ptr + ofs, 16, 16, 2,
+						   buf + pos, bufsz - pos, 0);
+				pos += strlen(buf + pos);
+				if (bufsz - pos > 0)
+					buf[pos++] = '\n';
+			}
+		}
+	}
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_traffic_log_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;
+	int traffic_log;
+
+	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, "%d", &traffic_log) != 1)
+		return -EFAULT;
+	if (traffic_log == 0)
+		iwl_legacy_reset_traffic_log(priv);
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_tx_queue_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_tx_queue *txq;
+	struct iwl_queue *q;
+	char *buf;
+	int pos = 0;
+	int cnt;
+	int ret;
+	const size_t bufsz = sizeof(char) * 64 *
+				priv->cfg->base_params->num_of_queues;
+
+	if (!priv->txq) {
+		IWL_ERR(priv, "txq not ready\n");
+		return -EAGAIN;
+	}
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	for (cnt = 0; cnt < priv->hw_params.max_txq_num; cnt++) {
+		txq = &priv->txq[cnt];
+		q = &txq->q;
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"hwq %.2d: read=%u write=%u stop=%d"
+				" swq_id=%#.2x (ac %d/hwq %d)\n",
+				cnt, q->read_ptr, q->write_ptr,
+				!!test_bit(cnt, priv->queue_stopped),
+				txq->swq_id, txq->swq_id & 3,
+				(txq->swq_id >> 2) & 0x1f);
+		if (cnt >= 4)
+			continue;
+		/* for the ACs, display the stop count too */
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"        stop-count: %d\n",
+				atomic_read(&priv->queue_stop_count[cnt]));
+	}
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_rx_queue_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	char buf[256];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "read: %u\n",
+						rxq->read);
+	pos += scnprintf(buf + pos, bufsz - pos, "write: %u\n",
+						rxq->write);
+	pos += scnprintf(buf + pos, bufsz - pos, "free_count: %u\n",
+						rxq->free_count);
+	if (rxq->rb_stts) {
+		pos += scnprintf(buf + pos, bufsz - pos, "closed_rb_num: %u\n",
+			 le16_to_cpu(rxq->rb_stts->closed_rb_num) &  0x0FFF);
+	} else {
+		pos += scnprintf(buf + pos, bufsz - pos,
+					"closed_rb_num: Not Allocated\n");
+	}
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_rx_stats_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	return priv->cfg->ops->lib->debugfs_ops.rx_stats_read(file,
+			user_buf, count, ppos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_tx_stats_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	return priv->cfg->ops->lib->debugfs_ops.tx_stats_read(file,
+			user_buf, count, ppos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_general_stats_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	return priv->cfg->ops->lib->debugfs_ops.general_stats_read(file,
+			user_buf, count, ppos);
+}
+
+static ssize_t iwl_legacy_dbgfs_sensitivity_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	int cnt = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl_sensitivity_data) * 4 + 100;
+	ssize_t ret;
+	struct iwl_sensitivity_data *data;
+
+	data = &priv->sensitivity_data;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm:\t\t\t %u\n",
+			data->auto_corr_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"auto_corr_ofdm_mrc:\t\t %u\n",
+			data->auto_corr_ofdm_mrc);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_ofdm_x1:\t\t %u\n",
+			data->auto_corr_ofdm_x1);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"auto_corr_ofdm_mrc_x1:\t\t %u\n",
+			data->auto_corr_ofdm_mrc_x1);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck:\t\t\t %u\n",
+			data->auto_corr_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "auto_corr_cck_mrc:\t\t %u\n",
+			data->auto_corr_cck_mrc);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"last_bad_plcp_cnt_ofdm:\t\t %u\n",
+			data->last_bad_plcp_cnt_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_ofdm:\t\t %u\n",
+			data->last_fa_cnt_ofdm);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"last_bad_plcp_cnt_cck:\t\t %u\n",
+			data->last_bad_plcp_cnt_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "last_fa_cnt_cck:\t\t %u\n",
+			data->last_fa_cnt_cck);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_curr_state:\t\t\t %u\n",
+			data->nrg_curr_state);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_prev_state:\t\t\t %u\n",
+			data->nrg_prev_state);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_value:\t\t\t");
+	for (cnt = 0; cnt < 10; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->nrg_value[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_rssi:\t\t");
+	for (cnt = 0; cnt < NRG_NUM_PREV_STAT_L; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->nrg_silence_rssi[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_ref:\t\t %u\n",
+			data->nrg_silence_ref);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_energy_idx:\t\t\t %u\n",
+			data->nrg_energy_idx);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_silence_idx:\t\t %u\n",
+			data->nrg_silence_idx);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_cck:\t\t\t %u\n",
+			data->nrg_th_cck);
+	pos += scnprintf(buf + pos, bufsz - pos,
+			"nrg_auto_corr_silence_diff:\t %u\n",
+			data->nrg_auto_corr_silence_diff);
+	pos += scnprintf(buf + pos, bufsz - pos, "num_in_cck_no_fa:\t\t %u\n",
+			data->num_in_cck_no_fa);
+	pos += scnprintf(buf + pos, bufsz - pos, "nrg_th_ofdm:\t\t\t %u\n",
+			data->nrg_th_ofdm);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+
+static ssize_t iwl_legacy_dbgfs_chain_noise_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	int cnt = 0;
+	char *buf;
+	int bufsz = sizeof(struct iwl_chain_noise_data) * 4 + 100;
+	ssize_t ret;
+	struct iwl_chain_noise_data *data;
+
+	data = &priv->chain_noise_data;
+	buf = kzalloc(bufsz, GFP_KERNEL);
+	if (!buf) {
+		IWL_ERR(priv, "Can not allocate Buffer\n");
+		return -ENOMEM;
+	}
+
+	pos += scnprintf(buf + pos, bufsz - pos, "active_chains:\t\t\t %u\n",
+			data->active_chains);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_a:\t\t\t %u\n",
+			data->chain_noise_a);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_b:\t\t\t %u\n",
+			data->chain_noise_b);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_noise_c:\t\t\t %u\n",
+			data->chain_noise_c);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_a:\t\t\t %u\n",
+			data->chain_signal_a);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_b:\t\t\t %u\n",
+			data->chain_signal_b);
+	pos += scnprintf(buf + pos, bufsz - pos, "chain_signal_c:\t\t\t %u\n",
+			data->chain_signal_c);
+	pos += scnprintf(buf + pos, bufsz - pos, "beacon_count:\t\t\t %u\n",
+			data->beacon_count);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "disconn_array:\t\t\t");
+	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->disconn_array[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "delta_gain_code:\t\t");
+	for (cnt = 0; cnt < NUM_RX_CHAINS; cnt++) {
+		pos += scnprintf(buf + pos, bufsz - pos, " %u",
+				data->delta_gain_code[cnt]);
+	}
+	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	pos += scnprintf(buf + pos, bufsz - pos, "radio_write:\t\t\t %u\n",
+			data->radio_write);
+	pos += scnprintf(buf + pos, bufsz - pos, "state:\t\t\t\t %u\n",
+			data->state);
+
+	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_power_save_status_read(struct file *file,
+						    char __user *user_buf,
+						    size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char buf[60];
+	int pos = 0;
+	const size_t bufsz = sizeof(buf);
+	u32 pwrsave_status;
+
+	pwrsave_status = iwl_read32(priv, CSR_GP_CNTRL) &
+			CSR_GP_REG_POWER_SAVE_STATUS_MSK;
+
+	pos += scnprintf(buf + pos, bufsz - pos, "Power Save Status: ");
+	pos += scnprintf(buf + pos, bufsz - pos, "%s\n",
+		(pwrsave_status == CSR_GP_REG_NO_POWER_SAVE) ? "none" :
+		(pwrsave_status == CSR_GP_REG_MAC_POWER_SAVE) ? "MAC" :
+		(pwrsave_status == CSR_GP_REG_PHY_POWER_SAVE) ? "PHY" :
+		"error");
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_clear_ucode_statistics_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;
+	int clear;
+
+	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, "%d", &clear) != 1)
+		return -EFAULT;
+
+	/* make request to uCode to retrieve statistics information */
+	mutex_lock(&priv->mutex);
+	iwl_legacy_send_statistics_request(priv, CMD_SYNC, true);
+	mutex_unlock(&priv->mutex);
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_tracing_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char buf[128];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "ucode trace timer is %s\n",
+			priv->event_log.ucode_trace ? "On" : "Off");
+	pos += scnprintf(buf + pos, bufsz - pos, "non_wraps_count:\t\t %u\n",
+			priv->event_log.non_wraps_count);
+	pos += scnprintf(buf + pos, bufsz - pos, "wraps_once_count:\t\t %u\n",
+			priv->event_log.wraps_once_count);
+	pos += scnprintf(buf + pos, bufsz - pos, "wraps_more_count:\t\t %u\n",
+			priv->event_log.wraps_more_count);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_ucode_tracing_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;
+	int trace;
+
+	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, "%d", &trace) != 1)
+		return -EFAULT;
+
+	if (trace) {
+		priv->event_log.ucode_trace = true;
+		/* schedule the ucode timer to occur in UCODE_TRACE_PERIOD */
+		mod_timer(&priv->ucode_trace,
+			jiffies + msecs_to_jiffies(UCODE_TRACE_PERIOD));
+	} else {
+		priv->event_log.ucode_trace = false;
+		del_timer_sync(&priv->ucode_trace);
+	}
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_rxon_flags_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int len = 0;
+	char buf[20];
+
+	len = sprintf(buf, "0x%04X\n",
+		le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.flags));
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_legacy_dbgfs_rxon_filter_flags_read(struct file *file,
+						char __user *user_buf,
+						size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int len = 0;
+	char buf[20];
+
+	len = sprintf(buf, "0x%04X\n",
+	le32_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags));
+	return simple_read_from_buffer(user_buf, count, ppos, buf, len);
+}
+
+static ssize_t iwl_legacy_dbgfs_fh_reg_read(struct file *file,
+					 char __user *user_buf,
+					 size_t count, loff_t *ppos)
+{
+	struct iwl_priv *priv = file->private_data;
+	char *buf;
+	int pos = 0;
+	ssize_t ret = -EFAULT;
+
+	if (priv->cfg->ops->lib->dump_fh) {
+		ret = pos = priv->cfg->ops->lib->dump_fh(priv, &buf, true);
+		if (buf) {
+			ret = simple_read_from_buffer(user_buf,
+						      count, ppos, buf, pos);
+			kfree(buf);
+		}
+	}
+
+	return ret;
+}
+
+static ssize_t iwl_legacy_dbgfs_missed_beacon_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char buf[12];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%d\n",
+			priv->missed_beacon_threshold);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_missed_beacon_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;
+	int missed;
+
+	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, "%d", &missed) != 1)
+		return -EINVAL;
+
+	if (missed < IWL_MISSED_BEACON_THRESHOLD_MIN ||
+	    missed > IWL_MISSED_BEACON_THRESHOLD_MAX)
+		priv->missed_beacon_threshold =
+			IWL_MISSED_BEACON_THRESHOLD_DEF;
+	else
+		priv->missed_beacon_threshold = missed;
+
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_plcp_delta_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int pos = 0;
+	char buf[12];
+	const size_t bufsz = sizeof(buf);
+
+	pos += scnprintf(buf + pos, bufsz - pos, "%u\n",
+			priv->cfg->base_params->plcp_delta_threshold);
+
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_plcp_delta_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;
+	int plcp;
+
+	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, "%d", &plcp) != 1)
+		return -EINVAL;
+	if ((plcp < IWL_MAX_PLCP_ERR_THRESHOLD_MIN) ||
+		(plcp > IWL_MAX_PLCP_ERR_THRESHOLD_MAX))
+		priv->cfg->base_params->plcp_delta_threshold =
+			IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE;
+	else
+		priv->cfg->base_params->plcp_delta_threshold = plcp;
+	return count;
+}
+
+static ssize_t iwl_legacy_dbgfs_force_reset_read(struct file *file,
+					char __user *user_buf,
+					size_t count, loff_t *ppos) {
+
+	struct iwl_priv *priv = file->private_data;
+	int i, pos = 0;
+	char buf[300];
+	const size_t bufsz = sizeof(buf);
+	struct iwl_force_reset *force_reset;
+
+	for (i = 0; i < IWL_MAX_FORCE_RESET; i++) {
+		force_reset = &priv->force_reset[i];
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"Force reset method %d\n", i);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\tnumber of reset request: %d\n",
+				force_reset->reset_request_count);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\tnumber of reset request success: %d\n",
+				force_reset->reset_success_count);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\tnumber of reset request reject: %d\n",
+				force_reset->reset_reject_count);
+		pos += scnprintf(buf + pos, bufsz - pos,
+				"\treset duration: %lu\n",
+				force_reset->reset_duration);
+	}
+	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
+}
+
+static ssize_t iwl_legacy_dbgfs_force_reset_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;
+	int reset, ret;
+
+	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, "%d", &reset) != 1)
+		return -EINVAL;
+	switch (reset) {
+	case IWL_RF_RESET:
+	case IWL_FW_RESET:
+		ret = iwl_legacy_force_reset(priv, reset, true);
+		break;
+	default:
+		return -EINVAL;
+	}
+	return ret ? ret : count;
+}
+
+static ssize_t iwl_legacy_dbgfs_wd_timeout_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;
+	int timeout;
+
+	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, "%d", &timeout) != 1)
+		return -EINVAL;
+	if (timeout < 0 || timeout > IWL_MAX_WD_TIMEOUT)
+		timeout = IWL_DEF_WD_TIMEOUT;
+
+	priv->cfg->base_params->wd_timeout = timeout;
+	iwl_legacy_setup_watchdog(priv);
+	return count;
+}
+
+DEBUGFS_READ_FILE_OPS(rx_statistics);
+DEBUGFS_READ_FILE_OPS(tx_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(traffic_log);
+DEBUGFS_READ_FILE_OPS(rx_queue);
+DEBUGFS_READ_FILE_OPS(tx_queue);
+DEBUGFS_READ_FILE_OPS(ucode_rx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_tx_stats);
+DEBUGFS_READ_FILE_OPS(ucode_general_stats);
+DEBUGFS_READ_FILE_OPS(sensitivity);
+DEBUGFS_READ_FILE_OPS(chain_noise);
+DEBUGFS_READ_FILE_OPS(power_save_status);
+DEBUGFS_WRITE_FILE_OPS(clear_ucode_statistics);
+DEBUGFS_WRITE_FILE_OPS(clear_traffic_statistics);
+DEBUGFS_READ_WRITE_FILE_OPS(ucode_tracing);
+DEBUGFS_READ_FILE_OPS(fh_reg);
+DEBUGFS_READ_WRITE_FILE_OPS(missed_beacon);
+DEBUGFS_READ_WRITE_FILE_OPS(plcp_delta);
+DEBUGFS_READ_WRITE_FILE_OPS(force_reset);
+DEBUGFS_READ_FILE_OPS(rxon_flags);
+DEBUGFS_READ_FILE_OPS(rxon_filter_flags);
+DEBUGFS_WRITE_FILE_OPS(wd_timeout);
+
+/*
+ * Create the debugfs files and directories
+ *
+ */
+int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
+{
+	struct dentry *phyd = priv->hw->wiphy->debugfsdir;
+	struct dentry *dir_drv, *dir_data, *dir_rf, *dir_debug;
+
+	dir_drv = debugfs_create_dir(name, phyd);
+	if (!dir_drv)
+		return -ENOMEM;
+
+	priv->debugfs_dir = dir_drv;
+
+	dir_data = debugfs_create_dir("data", dir_drv);
+	if (!dir_data)
+		goto err;
+	dir_rf = debugfs_create_dir("rf", dir_drv);
+	if (!dir_rf)
+		goto err;
+	dir_debug = debugfs_create_dir("debug", dir_drv);
+	if (!dir_debug)
+		goto err;
+
+	DEBUGFS_ADD_FILE(nvm, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(sram, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(log_event, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(stations, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(channels, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
+	DEBUGFS_ADD_FILE(disable_ht40, dir_data, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(rx_statistics, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(tx_statistics, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(traffic_log, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(rx_queue, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(tx_queue, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(power_save_status, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(clear_ucode_statistics, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(clear_traffic_statistics, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(fh_reg, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(missed_beacon, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(plcp_delta, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(force_reset, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(ucode_rx_stats, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(ucode_tx_stats, dir_debug, S_IRUSR);
+	DEBUGFS_ADD_FILE(ucode_general_stats, dir_debug, S_IRUSR);
+
+	if (priv->cfg->base_params->sensitivity_calib_by_driver)
+		DEBUGFS_ADD_FILE(sensitivity, dir_debug, S_IRUSR);
+	if (priv->cfg->base_params->chain_noise_calib_by_driver)
+		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
+	if (priv->cfg->base_params->ucode_tracing)
+		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
+	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
+	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
+	if (priv->cfg->base_params->sensitivity_calib_by_driver)
+		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
+				 &priv->disable_sens_cal);
+	if (priv->cfg->base_params->chain_noise_calib_by_driver)
+		DEBUGFS_ADD_BOOL(disable_chain_noise, dir_rf,
+				 &priv->disable_chain_noise_cal);
+	DEBUGFS_ADD_BOOL(disable_tx_power, dir_rf,
+				&priv->disable_tx_power_cal);
+	return 0;
+
+err:
+	IWL_ERR(priv, "Can't create the debugfs directory\n");
+	iwl_legacy_dbgfs_unregister(priv);
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(iwl_legacy_dbgfs_register);
+
+/**
+ * Remove the debugfs files and directories
+ *
+ */
+void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
+{
+	if (!priv->debugfs_dir)
+		return;
+
+	debugfs_remove_recursive(priv->debugfs_dir);
+	priv->debugfs_dir = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_dbgfs_unregister);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-debug.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-debug.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-debug.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,198 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * 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_legacy_debug_h__
+#define __iwl_legacy_debug_h__
+
+struct iwl_priv;
+extern u32 iwlegacy_debug_level;
+
+#define IWL_ERR(p, f, a...) dev_err(&((p)->pci_dev->dev), f, ## a)
+#define IWL_WARN(p, f, a...) dev_warn(&((p)->pci_dev->dev), f, ## a)
+#define IWL_INFO(p, f, a...) dev_info(&((p)->pci_dev->dev), f, ## a)
+#define IWL_CRIT(p, f, a...) dev_crit(&((p)->pci_dev->dev), f, ## a)
+
+#define iwl_print_hex_error(priv, p, len)				 \
+do {									\
+	print_hex_dump(KERN_ERR, "iwl data: ",				\
+		       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);		\
+} while (0)
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+#define IWL_DEBUG(__priv, level, fmt, args...)				\
+do {									\
+	if (iwl_legacy_get_debug_level(__priv) & (level))			\
+		dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),		\
+			 "%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
+			__func__ , ## args);				\
+} while (0)
+
+#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)			\
+do {									\
+	if ((iwl_legacy_get_debug_level(__priv) & (level)) && net_ratelimit())	\
+		dev_printk(KERN_ERR, &(__priv->hw->wiphy->dev),		\
+			"%c %s " fmt, in_interrupt() ? 'I' : 'U',	\
+			 __func__ , ## args);				\
+} while (0)
+
+#define iwl_print_hex_dump(priv, level, p, len) 			\
+do {									\
+	if (iwl_legacy_get_debug_level(priv) & level)				\
+		print_hex_dump(KERN_DEBUG, "iwl data: ",		\
+			       DUMP_PREFIX_OFFSET, 16, 1, p, len, 1);	\
+} while (0)
+
+#else
+#define IWL_DEBUG(__priv, level, fmt, args...)
+#define IWL_DEBUG_LIMIT(__priv, level, fmt, args...)
+static inline void iwl_print_hex_dump(struct iwl_priv *priv, int level,
+				      const void *p, u32 len)
+{}
+#endif				/* CONFIG_IWLWIFI_LEGACY_DEBUG */
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+int iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name);
+void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv);
+#else
+static inline int
+iwl_legacy_dbgfs_register(struct iwl_priv *priv, const char *name)
+{
+	return 0;
+}
+static inline void iwl_legacy_dbgfs_unregister(struct iwl_priv *priv)
+{
+}
+#endif				/* CONFIG_IWLWIFI_LEGACY_DEBUGFS */
+
+/*
+ * To use the debug system:
+ *
+ * If you are defining a new debug classification, simply add it to the #define
+ * list here in the form of
+ *
+ * #define IWL_DL_xxxx VALUE
+ *
+ * where xxxx should be the name of the classification (for example, WEP).
+ *
+ * You then need to either add a IWL_xxxx_DEBUG() macro definition for your
+ * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want
+ * to send output to that classification.
+ *
+ * The active debug levels can be accessed via files
+ *
+ * 	/sys/module/iwl4965/parameters/debug{50}
+ *	/sys/module/iwl3945/parameters/debug
+ * 	/sys/class/net/wlan0/device/debug_level
+ *
+ * when CONFIG_IWLWIFI_LEGACY_DEBUG=y.
+ */
+
+/* 0x0000000F - 0x00000001 */
+#define IWL_DL_INFO		(1 << 0)
+#define IWL_DL_MAC80211		(1 << 1)
+#define IWL_DL_HCMD		(1 << 2)
+#define IWL_DL_STATE		(1 << 3)
+/* 0x000000F0 - 0x00000010 */
+#define IWL_DL_MACDUMP		(1 << 4)
+#define IWL_DL_HCMD_DUMP	(1 << 5)
+#define IWL_DL_EEPROM		(1 << 6)
+#define IWL_DL_RADIO		(1 << 7)
+/* 0x00000F00 - 0x00000100 */
+#define IWL_DL_POWER		(1 << 8)
+#define IWL_DL_TEMP		(1 << 9)
+#define IWL_DL_NOTIF		(1 << 10)
+#define IWL_DL_SCAN		(1 << 11)
+/* 0x0000F000 - 0x00001000 */
+#define IWL_DL_ASSOC		(1 << 12)
+#define IWL_DL_DROP		(1 << 13)
+#define IWL_DL_TXPOWER		(1 << 14)
+#define IWL_DL_AP		(1 << 15)
+/* 0x000F0000 - 0x00010000 */
+#define IWL_DL_FW		(1 << 16)
+#define IWL_DL_RF_KILL		(1 << 17)
+#define IWL_DL_FW_ERRORS	(1 << 18)
+#define IWL_DL_LED		(1 << 19)
+/* 0x00F00000 - 0x00100000 */
+#define IWL_DL_RATE		(1 << 20)
+#define IWL_DL_CALIB		(1 << 21)
+#define IWL_DL_WEP		(1 << 22)
+#define IWL_DL_TX		(1 << 23)
+/* 0x0F000000 - 0x01000000 */
+#define IWL_DL_RX		(1 << 24)
+#define IWL_DL_ISR		(1 << 25)
+#define IWL_DL_HT		(1 << 26)
+#define IWL_DL_IO		(1 << 27)
+/* 0xF0000000 - 0x10000000 */
+#define IWL_DL_11H		(1 << 28)
+#define IWL_DL_STATS		(1 << 29)
+#define IWL_DL_TX_REPLY		(1 << 30)
+#define IWL_DL_QOS		(1 << 31)
+
+#define IWL_DEBUG_INFO(p, f, a...)	IWL_DEBUG(p, IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_MAC80211(p, f, a...)	IWL_DEBUG(p, IWL_DL_MAC80211, f, ## a)
+#define IWL_DEBUG_MACDUMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_MACDUMP, f, ## a)
+#define IWL_DEBUG_TEMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_TEMP, f, ## a)
+#define IWL_DEBUG_SCAN(p, f, a...)	IWL_DEBUG(p, IWL_DL_SCAN, f, ## a)
+#define IWL_DEBUG_RX(p, f, a...)	IWL_DEBUG(p, IWL_DL_RX, f, ## a)
+#define IWL_DEBUG_TX(p, f, a...)	IWL_DEBUG(p, IWL_DL_TX, f, ## a)
+#define IWL_DEBUG_ISR(p, f, a...)	IWL_DEBUG(p, IWL_DL_ISR, f, ## a)
+#define IWL_DEBUG_LED(p, f, a...)	IWL_DEBUG(p, IWL_DL_LED, f, ## a)
+#define IWL_DEBUG_WEP(p, f, a...)	IWL_DEBUG(p, IWL_DL_WEP, f, ## a)
+#define IWL_DEBUG_HC(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD, f, ## a)
+#define IWL_DEBUG_HC_DUMP(p, f, a...)	IWL_DEBUG(p, IWL_DL_HCMD_DUMP, f, ## a)
+#define IWL_DEBUG_EEPROM(p, f, a...)	IWL_DEBUG(p, IWL_DL_EEPROM, f, ## a)
+#define IWL_DEBUG_CALIB(p, f, a...)	IWL_DEBUG(p, IWL_DL_CALIB, f, ## a)
+#define IWL_DEBUG_FW(p, f, a...)	IWL_DEBUG(p, IWL_DL_FW, f, ## a)
+#define IWL_DEBUG_RF_KILL(p, f, a...)	IWL_DEBUG(p, IWL_DL_RF_KILL, f, ## a)
+#define IWL_DEBUG_DROP(p, f, a...)	IWL_DEBUG(p, IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_DROP_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_DROP, f, ## a)
+#define IWL_DEBUG_AP(p, f, a...)	IWL_DEBUG(p, IWL_DL_AP, f, ## a)
+#define IWL_DEBUG_TXPOWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_TXPOWER, f, ## a)
+#define IWL_DEBUG_IO(p, f, a...)	IWL_DEBUG(p, IWL_DL_IO, f, ## a)
+#define IWL_DEBUG_RATE(p, f, a...)	IWL_DEBUG(p, IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_RATE_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_RATE, f, ## a)
+#define IWL_DEBUG_NOTIF(p, f, a...)	IWL_DEBUG(p, IWL_DL_NOTIF, f, ## a)
+#define IWL_DEBUG_ASSOC(p, f, a...)	\
+		IWL_DEBUG(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_ASSOC_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_ASSOC | IWL_DL_INFO, f, ## a)
+#define IWL_DEBUG_HT(p, f, a...)	IWL_DEBUG(p, IWL_DL_HT, f, ## a)
+#define IWL_DEBUG_STATS(p, f, a...)	IWL_DEBUG(p, IWL_DL_STATS, f, ## a)
+#define IWL_DEBUG_STATS_LIMIT(p, f, a...)	\
+		IWL_DEBUG_LIMIT(p, IWL_DL_STATS, f, ## a)
+#define IWL_DEBUG_TX_REPLY(p, f, a...)	IWL_DEBUG(p, IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_TX_REPLY_LIMIT(p, f, a...) \
+		IWL_DEBUG_LIMIT(p, IWL_DL_TX_REPLY, f, ## a)
+#define IWL_DEBUG_QOS(p, f, a...)	IWL_DEBUG(p, IWL_DL_QOS, f, ## a)
+#define IWL_DEBUG_RADIO(p, f, a...)	IWL_DEBUG(p, IWL_DL_RADIO, f, ## a)
+#define IWL_DEBUG_POWER(p, f, a...)	IWL_DEBUG(p, IWL_DL_POWER, f, ## a)
+#define IWL_DEBUG_11H(p, f, a...)	IWL_DEBUG(p, IWL_DL_11H, f, ## a)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-dev.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-dev.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-dev.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-dev.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1432 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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
+ *
+ *****************************************************************************/
+/*
+ * Please use this file (iwl-dev.h) for driver implementation definitions.
+ * Please use iwl-commands.h for uCode API definitions.
+ * Please use iwl-4965-hw.h for hardware-related definitions.
+ */
+
+#ifndef __iwl_legacy_dev_h__
+#define __iwl_legacy_dev_h__
+
+#include <linux/pci.h> /* for struct pci_device_id */
+#include <linux/kernel.h>
+#include <linux/leds.h>
+#include <linux/wait.h>
+#include <net/ieee80211_radiotap.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-csr.h"
+#include "iwl-prph.h"
+#include "iwl-fh.h"
+#include "iwl-debug.h"
+#include "iwl-4965-hw.h"
+#include "iwl-3945-hw.h"
+#include "iwl-led.h"
+#include "iwl-power.h"
+#include "iwl-legacy-rs.h"
+
+struct iwl_tx_queue;
+
+/* CT-KILL constants */
+#define CT_KILL_THRESHOLD_LEGACY   110 /* in Celsius */
+
+/* Default noise level to report when noise measurement is not available.
+ *   This may be because we're:
+ *   1)  Not associated (4965, no beacon statistics being sent to driver)
+ *   2)  Scanning (noise measurement does not apply to associated channel)
+ *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
+ * Use default noise value of -127 ... this is below the range of measurable
+ *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
+ *   Also, -127 works better than 0 when averaging frames with/without
+ *   noise info (e.g. averaging might be done in app); measured dBm values are
+ *   always negative ... using a negative value as the default keeps all
+ *   averages within an s8's (used in some apps) range of negative values. */
+#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
+
+/*
+ * RTS threshold here is total size [2347] minus 4 FCS bytes
+ * Per spec:
+ *   a value of 0 means RTS on all data/management packets
+ *   a value > max MSDU size means no RTS
+ * else RTS for data/management frames where MPDU is larger
+ *   than RTS value.
+ */
+#define DEFAULT_RTS_THRESHOLD     2347U
+#define MIN_RTS_THRESHOLD         0U
+#define MAX_RTS_THRESHOLD         2347U
+#define MAX_MSDU_SIZE		  2304U
+#define MAX_MPDU_SIZE		  2346U
+#define DEFAULT_BEACON_INTERVAL   100U
+#define	DEFAULT_SHORT_RETRY_LIMIT 7U
+#define	DEFAULT_LONG_RETRY_LIMIT  4U
+
+struct iwl_rx_mem_buffer {
+	dma_addr_t page_dma;
+	struct page *page;
+	struct list_head list;
+};
+
+#define rxb_addr(r) page_address(r->page)
+
+/* defined below */
+struct iwl_device_cmd;
+
+struct iwl_cmd_meta {
+	/* only for SYNC commands, iff the reply skb is wanted */
+	struct iwl_host_cmd *source;
+	/*
+	 * only for ASYNC commands
+	 * (which is somewhat stupid -- look at iwl-sta.c for instance
+	 * which duplicates a bunch of code because the callback isn't
+	 * invoked for SYNC commands, if it were and its result passed
+	 * through it would be simpler...)
+	 */
+	void (*callback)(struct iwl_priv *priv,
+			 struct iwl_device_cmd *cmd,
+			 struct iwl_rx_packet *pkt);
+
+	/* The CMD_SIZE_HUGE flag bit indicates that the command
+	 * structure is stored at the end of the shared queue memory. */
+	u32 flags;
+
+	DEFINE_DMA_UNMAP_ADDR(mapping);
+	DEFINE_DMA_UNMAP_LEN(len);
+};
+
+/*
+ * Generic queue structure
+ *
+ * Contains common data for Rx and Tx queues
+ */
+struct iwl_queue {
+	int n_bd;              /* number of BDs in this queue */
+	int write_ptr;       /* 1-st empty entry (index) host_w*/
+	int read_ptr;         /* last used entry (index) host_r*/
+	/* use for monitoring and recovering the stuck queue */
+	dma_addr_t dma_addr;   /* physical addr for BD's */
+	int n_window;	       /* safe queue window */
+	u32 id;
+	int low_mark;	       /* low watermark, resume queue if free
+				* space more than this */
+	int high_mark;         /* high watermark, stop queue if free
+				* space less than this */
+} __packed;
+
+/* One for each TFD */
+struct iwl_tx_info {
+	struct sk_buff *skb;
+	struct iwl_rxon_context *ctx;
+};
+
+/**
+ * struct iwl_tx_queue - Tx Queue for DMA
+ * @q: generic Rx/Tx queue descriptor
+ * @bd: base of circular buffer of TFDs
+ * @cmd: array of command/TX buffer pointers
+ * @meta: array of meta data for each command/tx buffer
+ * @dma_addr_cmd: physical address of cmd/tx buffer array
+ * @txb: array of per-TFD driver data
+ * @time_stamp: time (in jiffies) of last read_ptr change
+ * @need_update: indicates need to update read/write index
+ * @sched_retry: indicates queue is high-throughput aggregation (HT AGG) enabled
+ *
+ * A Tx queue consists of circular buffer of BDs (a.k.a. TFDs, transmit frame
+ * descriptors) and required locking structures.
+ */
+#define TFD_TX_CMD_SLOTS 256
+#define TFD_CMD_SLOTS 32
+
+struct iwl_tx_queue {
+	struct iwl_queue q;
+	void *tfds;
+	struct iwl_device_cmd **cmd;
+	struct iwl_cmd_meta *meta;
+	struct iwl_tx_info *txb;
+	unsigned long time_stamp;
+	u8 need_update;
+	u8 sched_retry;
+	u8 active;
+	u8 swq_id;
+};
+
+#define IWL_NUM_SCAN_RATES         (2)
+
+struct iwl4965_channel_tgd_info {
+	u8 type;
+	s8 max_power;
+};
+
+struct iwl4965_channel_tgh_info {
+	s64 last_radar_time;
+};
+
+#define IWL4965_MAX_RATE (33)
+
+struct iwl3945_clip_group {
+	/* maximum power level to prevent clipping for each rate, derived by
+	 *   us from this band's saturation power in EEPROM */
+	const s8 clip_powers[IWL_MAX_RATES];
+};
+
+/* current Tx power values to use, one for each rate for each channel.
+ * requested power is limited by:
+ * -- regulatory EEPROM limits for this channel
+ * -- hardware capabilities (clip-powers)
+ * -- spectrum management
+ * -- user preference (e.g. iwconfig)
+ * when requested power is set, base power index must also be set. */
+struct iwl3945_channel_power_info {
+	struct iwl3945_tx_power tpc;	/* actual radio and DSP gain settings */
+	s8 power_table_index;	/* actual (compenst'd) index into gain table */
+	s8 base_power_index;	/* gain index for power at factory temp. */
+	s8 requested_power;	/* power (dBm) requested for this chnl/rate */
+};
+
+/* current scan Tx power values to use, one for each scan rate for each
+ * channel. */
+struct iwl3945_scan_power_info {
+	struct iwl3945_tx_power tpc;	/* actual radio and DSP gain settings */
+	s8 power_table_index;	/* actual (compenst'd) index into gain table */
+	s8 requested_power;	/* scan pwr (dBm) requested for chnl/rate */
+};
+
+/*
+ * One for each channel, holds all channel setup data
+ * Some of the fields (e.g. eeprom and flags/max_power_avg) are redundant
+ *     with one another!
+ */
+struct iwl_channel_info {
+	struct iwl4965_channel_tgd_info tgd;
+	struct iwl4965_channel_tgh_info tgh;
+	struct iwl_eeprom_channel eeprom;	/* EEPROM regulatory limit */
+	struct iwl_eeprom_channel ht40_eeprom;	/* EEPROM regulatory limit for
+						 * HT40 channel */
+
+	u8 channel;	  /* channel number */
+	u8 flags;	  /* flags copied from EEPROM */
+	s8 max_power_avg; /* (dBm) regul. eeprom, normal Tx, any rate */
+	s8 curr_txpow;	  /* (dBm) regulatory/spectrum/user (not h/w) limit */
+	s8 min_power;	  /* always 0 */
+	s8 scan_power;	  /* (dBm) regul. eeprom, direct scans, any rate */
+
+	u8 group_index;	  /* 0-4, maps channel to group1/2/3/4/5 */
+	u8 band_index;	  /* 0-4, maps channel to band1/2/3/4/5 */
+	enum ieee80211_band band;
+
+	/* HT40 channel info */
+	s8 ht40_max_power_avg;	/* (dBm) regul. eeprom, normal Tx, any rate */
+	u8 ht40_flags;		/* flags copied from EEPROM */
+	u8 ht40_extension_channel; /* HT_IE_EXT_CHANNEL_* */
+
+	/* Radio/DSP gain settings for each "normal" data Tx rate.
+	 * These include, in addition to RF and DSP gain, a few fields for
+	 *   remembering/modifying gain settings (indexes). */
+	struct iwl3945_channel_power_info power_info[IWL4965_MAX_RATE];
+
+	/* Radio/DSP gain settings for each scan rate, for directed scans. */
+	struct iwl3945_scan_power_info scan_pwr_info[IWL_NUM_SCAN_RATES];
+};
+
+#define IWL_TX_FIFO_BK		0	/* shared */
+#define IWL_TX_FIFO_BE		1
+#define IWL_TX_FIFO_VI		2	/* shared */
+#define IWL_TX_FIFO_VO		3
+#define IWL_TX_FIFO_UNUSED	-1
+
+/* 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
+
+#define IWL_DEFAULT_CMD_QUEUE_NUM	4
+
+#define IEEE80211_DATA_LEN              2304
+#define IEEE80211_4ADDR_LEN             30
+#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
+#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
+
+struct iwl_frame {
+	union {
+		struct ieee80211_hdr frame;
+		struct iwl_tx_beacon_cmd beacon;
+		u8 raw[IEEE80211_FRAME_LEN];
+		u8 cmd[360];
+	} u;
+	struct list_head list;
+};
+
+#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
+#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
+#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
+
+enum {
+	CMD_SYNC = 0,
+	CMD_SIZE_NORMAL = 0,
+	CMD_NO_SKB = 0,
+	CMD_SIZE_HUGE = (1 << 0),
+	CMD_ASYNC = (1 << 1),
+	CMD_WANT_SKB = (1 << 2),
+};
+
+#define DEF_CMD_PAYLOAD_SIZE 320
+
+/**
+ * struct iwl_device_cmd
+ *
+ * For allocation of the command and tx queues, this establishes the overall
+ * size of the largest command we send to uCode, except for a scan command
+ * (which is relatively huge; space is allocated separately).
+ */
+struct iwl_device_cmd {
+	struct iwl_cmd_header hdr;	/* uCode API */
+	union {
+		u32 flags;
+		u8 val8;
+		u16 val16;
+		u32 val32;
+		struct iwl_tx_cmd tx;
+		u8 payload[DEF_CMD_PAYLOAD_SIZE];
+	} __packed cmd;
+} __packed;
+
+#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+
+
+struct iwl_host_cmd {
+	const void *data;
+	unsigned long reply_page;
+	void (*callback)(struct iwl_priv *priv,
+			 struct iwl_device_cmd *cmd,
+			 struct iwl_rx_packet *pkt);
+	u32 flags;
+	u16 len;
+	u8 id;
+};
+
+#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
+#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
+#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
+
+/**
+ * struct iwl_rx_queue - Rx queue
+ * @bd: driver's pointer to buffer of receive buffer descriptors (rbd)
+ * @bd_dma: bus address of buffer of receive buffer descriptors (rbd)
+ * @read: Shared index to newest available Rx buffer
+ * @write: Shared index to oldest written Rx packet
+ * @free_count: Number of pre-allocated buffers in rx_free
+ * @rx_free: list of free SKBs for use
+ * @rx_used: List of Rx buffers with no SKB
+ * @need_update: flag to indicate we need to update read/write index
+ * @rb_stts: driver's pointer to receive buffer status
+ * @rb_stts_dma: bus address of receive buffer status
+ *
+ * NOTE:  rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers
+ */
+struct iwl_rx_queue {
+	__le32 *bd;
+	dma_addr_t bd_dma;
+	struct iwl_rx_mem_buffer pool[RX_QUEUE_SIZE + RX_FREE_BUFFERS];
+	struct iwl_rx_mem_buffer *queue[RX_QUEUE_SIZE];
+	u32 read;
+	u32 write;
+	u32 free_count;
+	u32 write_actual;
+	struct list_head rx_free;
+	struct list_head rx_used;
+	int need_update;
+	struct iwl_rb_status *rb_stts;
+	dma_addr_t rb_stts_dma;
+	spinlock_t lock;
+};
+
+#define IWL_SUPPORTED_RATES_IE_LEN         8
+
+#define MAX_TID_COUNT        9
+
+#define IWL_INVALID_RATE     0xFF
+#define IWL_INVALID_VALUE    -1
+
+/**
+ * struct iwl_ht_agg -- aggregation status while waiting for block-ack
+ * @txq_id: Tx queue used for Tx attempt
+ * @frame_count: # frames attempted by Tx command
+ * @wait_for_ba: Expect block-ack before next Tx reply
+ * @start_idx: Index of 1st Transmit Frame Descriptor (TFD) in Tx window
+ * @bitmap0: Low order bitmap, one bit for each frame pending ACK in Tx window
+ * @bitmap1: High order, one bit for each frame pending ACK in Tx window
+ * @rate_n_flags: Rate at which Tx was attempted
+ *
+ * If REPLY_TX indicates that aggregation was attempted, driver must wait
+ * for block ack (REPLY_COMPRESSED_BA).  This struct stores tx reply info
+ * until block ack arrives.
+ */
+struct iwl_ht_agg {
+	u16 txq_id;
+	u16 frame_count;
+	u16 wait_for_ba;
+	u16 start_idx;
+	u64 bitmap;
+	u32 rate_n_flags;
+#define IWL_AGG_OFF 0
+#define IWL_AGG_ON 1
+#define IWL_EMPTYING_HW_QUEUE_ADDBA 2
+#define IWL_EMPTYING_HW_QUEUE_DELBA 3
+	u8 state;
+};
+
+
+struct iwl_tid_data {
+	u16 seq_number; /* 4965 only */
+	u16 tfds_in_queue;
+	struct iwl_ht_agg agg;
+};
+
+struct iwl_hw_key {
+	u32 cipher;
+	int keylen;
+	u8 keyidx;
+	u8 key[32];
+};
+
+union iwl_ht_rate_supp {
+	u16 rates;
+	struct {
+		u8 siso_rate;
+		u8 mimo_rate;
+	};
+};
+
+#define CFG_HT_RX_AMPDU_FACTOR_8K   (0x0)
+#define CFG_HT_RX_AMPDU_FACTOR_16K  (0x1)
+#define CFG_HT_RX_AMPDU_FACTOR_32K  (0x2)
+#define CFG_HT_RX_AMPDU_FACTOR_64K  (0x3)
+#define CFG_HT_RX_AMPDU_FACTOR_DEF  CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MAX  CFG_HT_RX_AMPDU_FACTOR_64K
+#define CFG_HT_RX_AMPDU_FACTOR_MIN  CFG_HT_RX_AMPDU_FACTOR_8K
+
+/*
+ * Maximal MPDU density for TX aggregation
+ * 4 - 2us density
+ * 5 - 4us density
+ * 6 - 8us density
+ * 7 - 16us density
+ */
+#define CFG_HT_MPDU_DENSITY_2USEC   (0x4)
+#define CFG_HT_MPDU_DENSITY_4USEC   (0x5)
+#define CFG_HT_MPDU_DENSITY_8USEC   (0x6)
+#define CFG_HT_MPDU_DENSITY_16USEC  (0x7)
+#define CFG_HT_MPDU_DENSITY_DEF CFG_HT_MPDU_DENSITY_4USEC
+#define CFG_HT_MPDU_DENSITY_MAX CFG_HT_MPDU_DENSITY_16USEC
+#define CFG_HT_MPDU_DENSITY_MIN     (0x1)
+
+struct iwl_ht_config {
+	bool single_chain_sufficient;
+	enum ieee80211_smps_mode smps; /* current smps mode */
+};
+
+/* QoS structures */
+struct iwl_qos_info {
+	int qos_active;
+	struct iwl_qosparam_cmd def_qos_parm;
+};
+
+/*
+ * Structure should be accessed with sta_lock held. When station addition
+ * is in progress (IWL_STA_UCODE_INPROGRESS) it is possible to access only
+ * the commands (iwl_legacy_addsta_cmd and iwl_link_quality_cmd) without
+ * sta_lock held.
+ */
+struct iwl_station_entry {
+	struct iwl_legacy_addsta_cmd sta;
+	struct iwl_tid_data tid[MAX_TID_COUNT];
+	u8 used, ctxid;
+	struct iwl_hw_key keyinfo;
+	struct iwl_link_quality_cmd *lq;
+};
+
+struct iwl_station_priv_common {
+	struct iwl_rxon_context *ctx;
+	u8 sta_id;
+};
+
+/*
+ * iwl_station_priv: Driver's private station information
+ *
+ * When mac80211 creates a station it reserves some space (hw->sta_data_size)
+ * in the structure for use by driver. This structure is places in that
+ * space.
+ *
+ * The common struct MUST be first because it is shared between
+ * 3945 and 4965!
+ */
+struct iwl_station_priv {
+	struct iwl_station_priv_common common;
+	struct iwl_lq_sta lq_sta;
+	atomic_t pending_frames;
+	bool client;
+	bool asleep;
+};
+
+/**
+ * struct iwl_vif_priv - driver's private per-interface information
+ *
+ * When mac80211 allocates a virtual interface, it can allocate
+ * space for us to put data into.
+ */
+struct iwl_vif_priv {
+	struct iwl_rxon_context *ctx;
+	u8 ibss_bssid_sta_id;
+};
+
+/* one for each uCode image (inst/data, boot/init/runtime) */
+struct fw_desc {
+	void *v_addr;		/* access by driver */
+	dma_addr_t p_addr;	/* access by card's busmaster DMA */
+	u32 len;		/* bytes */
+};
+
+/* uCode file layout */
+struct iwl_ucode_header {
+	__le32 ver;	/* major/minor/API/serial */
+	struct {
+		__le32 inst_size;	/* bytes of runtime code */
+		__le32 data_size;	/* bytes of runtime data */
+		__le32 init_size;	/* bytes of init code */
+		__le32 init_data_size;	/* bytes of init data */
+		__le32 boot_size;	/* bytes of bootstrap code */
+		u8 data[0];		/* in same order as sizes */
+	} v1;
+};
+
+struct iwl4965_ibss_seq {
+	u8 mac[ETH_ALEN];
+	u16 seq_num;
+	u16 frag_num;
+	unsigned long packet_time;
+	struct list_head list;
+};
+
+struct iwl_sensitivity_ranges {
+	u16 min_nrg_cck;
+	u16 max_nrg_cck;
+
+	u16 nrg_th_cck;
+	u16 nrg_th_ofdm;
+
+	u16 auto_corr_min_ofdm;
+	u16 auto_corr_min_ofdm_mrc;
+	u16 auto_corr_min_ofdm_x1;
+	u16 auto_corr_min_ofdm_mrc_x1;
+
+	u16 auto_corr_max_ofdm;
+	u16 auto_corr_max_ofdm_mrc;
+	u16 auto_corr_max_ofdm_x1;
+	u16 auto_corr_max_ofdm_mrc_x1;
+
+	u16 auto_corr_max_cck;
+	u16 auto_corr_max_cck_mrc;
+	u16 auto_corr_min_cck;
+	u16 auto_corr_min_cck_mrc;
+
+	u16 barker_corr_th_min;
+	u16 barker_corr_th_min_mrc;
+	u16 nrg_th_cca;
+};
+
+
+#define KELVIN_TO_CELSIUS(x) ((x)-273)
+#define CELSIUS_TO_KELVIN(x) ((x)+273)
+
+
+/**
+ * struct iwl_hw_params
+ * @max_txq_num: Max # Tx queues supported
+ * @dma_chnl_num: Number of Tx DMA/FIFO channels
+ * @scd_bc_tbls_size: size of scheduler byte count tables
+ * @tfd_size: TFD size
+ * @tx/rx_chains_num: Number of TX/RX chains
+ * @valid_tx/rx_ant: usable antennas
+ * @max_rxq_size: Max # Rx frames in Rx queue (must be power-of-2)
+ * @max_rxq_log: Log-base-2 of max_rxq_size
+ * @rx_page_order: Rx buffer page order
+ * @rx_wrt_ptr_reg: FH{39}_RSCSR_CHNL0_WPTR
+ * @max_stations:
+ * @ht40_channel: is 40MHz width possible in band 2.4
+ * BIT(IEEE80211_BAND_5GHZ) BIT(IEEE80211_BAND_5GHZ)
+ * @sw_crypto: 0 for hw, 1 for sw
+ * @max_xxx_size: for ucode uses
+ * @ct_kill_threshold: temperature threshold
+ * @beacon_time_tsf_bits: number of valid tsf bits for beacon time
+ * @struct iwl_sensitivity_ranges: range of sensitivity values
+ */
+struct iwl_hw_params {
+	u8 max_txq_num;
+	u8 dma_chnl_num;
+	u16 scd_bc_tbls_size;
+	u32 tfd_size;
+	u8  tx_chains_num;
+	u8  rx_chains_num;
+	u8  valid_tx_ant;
+	u8  valid_rx_ant;
+	u16 max_rxq_size;
+	u16 max_rxq_log;
+	u32 rx_page_order;
+	u32 rx_wrt_ptr_reg;
+	u8  max_stations;
+	u8  ht40_channel;
+	u8  max_beacon_itrvl;	/* in 1024 ms */
+	u32 max_inst_size;
+	u32 max_data_size;
+	u32 max_bsm_size;
+	u32 ct_kill_threshold; /* value in hw-dependent units */
+	u16 beacon_time_tsf_bits;
+	const struct iwl_sensitivity_ranges *sens;
+};
+
+
+/******************************************************************************
+ *
+ * Functions implemented in core module which are forward declared here
+ * for use by iwl-[4-5].c
+ *
+ * NOTE:  The implementation of these functions are not hardware specific
+ * which is why they are in the core module files.
+ *
+ * Naming convention --
+ * iwl_         <-- Is part of iwlwifi
+ * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
+ * iwl4965_bg_      <-- Called from work queue context
+ * iwl4965_mac_     <-- mac80211 callback
+ *
+ ****************************************************************************/
+extern void iwl4965_update_chain_flags(struct iwl_priv *priv);
+extern const u8 iwlegacy_bcast_addr[ETH_ALEN];
+extern int iwl_legacy_queue_space(const struct iwl_queue *q);
+static inline int iwl_legacy_queue_used(const struct iwl_queue *q, int i)
+{
+	return q->write_ptr >= q->read_ptr ?
+		(i >= q->read_ptr && i < q->write_ptr) :
+		!(i < q->read_ptr && i >= q->write_ptr);
+}
+
+
+static inline u8 iwl_legacy_get_cmd_index(struct iwl_queue *q, u32 index,
+								int is_huge)
+{
+	/*
+	 * This is for init calibration result and scan command which
+	 * required buffer > TFD_MAX_PAYLOAD_SIZE,
+	 * the big buffer at end of command array
+	 */
+	if (is_huge)
+		return q->n_window;	/* must be power of 2 */
+
+	/* Otherwise, use normal size buffers */
+	return index & (q->n_window - 1);
+}
+
+
+struct iwl_dma_ptr {
+	dma_addr_t dma;
+	void *addr;
+	size_t size;
+};
+
+#define IWL_OPERATION_MODE_AUTO     0
+#define IWL_OPERATION_MODE_HT_ONLY  1
+#define IWL_OPERATION_MODE_MIXED    2
+#define IWL_OPERATION_MODE_20MHZ    3
+
+#define IWL_TX_CRC_SIZE 4
+#define IWL_TX_DELIMITER_SIZE 4
+
+#define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000
+
+/* Sensitivity and chain noise calibration */
+#define INITIALIZATION_VALUE		0xFFFF
+#define IWL4965_CAL_NUM_BEACONS		20
+#define IWL_CAL_NUM_BEACONS		16
+#define MAXIMUM_ALLOWED_PATHLOSS	15
+
+#define CHAIN_NOISE_MAX_DELTA_GAIN_CODE 3
+
+#define MAX_FA_OFDM  50
+#define MIN_FA_OFDM  5
+#define MAX_FA_CCK   50
+#define MIN_FA_CCK   5
+
+#define AUTO_CORR_STEP_OFDM       1
+
+#define AUTO_CORR_STEP_CCK     3
+#define AUTO_CORR_MAX_TH_CCK   160
+
+#define NRG_DIFF               2
+#define NRG_STEP_CCK           2
+#define NRG_MARGIN             8
+#define MAX_NUMBER_CCK_NO_FA 100
+
+#define AUTO_CORR_CCK_MIN_VAL_DEF    (125)
+
+#define CHAIN_A             0
+#define CHAIN_B             1
+#define CHAIN_C             2
+#define CHAIN_NOISE_DELTA_GAIN_INIT_VAL 4
+#define ALL_BAND_FILTER			0xFF00
+#define IN_BAND_FILTER			0xFF
+#define MIN_AVERAGE_NOISE_MAX_VALUE	0xFFFFFFFF
+
+#define NRG_NUM_PREV_STAT_L     20
+#define NUM_RX_CHAINS           3
+
+enum iwl4965_false_alarm_state {
+	IWL_FA_TOO_MANY = 0,
+	IWL_FA_TOO_FEW = 1,
+	IWL_FA_GOOD_RANGE = 2,
+};
+
+enum iwl4965_chain_noise_state {
+	IWL_CHAIN_NOISE_ALIVE = 0,  /* must be 0 */
+	IWL_CHAIN_NOISE_ACCUMULATE,
+	IWL_CHAIN_NOISE_CALIBRATED,
+	IWL_CHAIN_NOISE_DONE,
+};
+
+enum iwl4965_calib_enabled_state {
+	IWL_CALIB_DISABLED = 0,  /* must be 0 */
+	IWL_CALIB_ENABLED = 1,
+};
+
+/*
+ * enum iwl_calib
+ * defines the order in which results of initial calibrations
+ * should be sent to the runtime uCode
+ */
+enum iwl_calib {
+	IWL_CALIB_MAX,
+};
+
+/* Opaque calibration results */
+struct iwl_calib_result {
+	void *buf;
+	size_t buf_len;
+};
+
+enum ucode_type {
+	UCODE_NONE = 0,
+	UCODE_INIT,
+	UCODE_RT
+};
+
+/* Sensitivity calib data */
+struct iwl_sensitivity_data {
+	u32 auto_corr_ofdm;
+	u32 auto_corr_ofdm_mrc;
+	u32 auto_corr_ofdm_x1;
+	u32 auto_corr_ofdm_mrc_x1;
+	u32 auto_corr_cck;
+	u32 auto_corr_cck_mrc;
+
+	u32 last_bad_plcp_cnt_ofdm;
+	u32 last_fa_cnt_ofdm;
+	u32 last_bad_plcp_cnt_cck;
+	u32 last_fa_cnt_cck;
+
+	u32 nrg_curr_state;
+	u32 nrg_prev_state;
+	u32 nrg_value[10];
+	u8  nrg_silence_rssi[NRG_NUM_PREV_STAT_L];
+	u32 nrg_silence_ref;
+	u32 nrg_energy_idx;
+	u32 nrg_silence_idx;
+	u32 nrg_th_cck;
+	s32 nrg_auto_corr_silence_diff;
+	u32 num_in_cck_no_fa;
+	u32 nrg_th_ofdm;
+
+	u16 barker_corr_th_min;
+	u16 barker_corr_th_min_mrc;
+	u16 nrg_th_cca;
+};
+
+/* Chain noise (differential Rx gain) calib data */
+struct iwl_chain_noise_data {
+	u32 active_chains;
+	u32 chain_noise_a;
+	u32 chain_noise_b;
+	u32 chain_noise_c;
+	u32 chain_signal_a;
+	u32 chain_signal_b;
+	u32 chain_signal_c;
+	u16 beacon_count;
+	u8 disconn_array[NUM_RX_CHAINS];
+	u8 delta_gain_code[NUM_RX_CHAINS];
+	u8 radio_write;
+	u8 state;
+};
+
+#define	EEPROM_SEM_TIMEOUT 10		/* milliseconds */
+#define EEPROM_SEM_RETRY_LIMIT 1000	/* number of attempts (not time) */
+
+#define IWL_TRAFFIC_ENTRIES	(256)
+#define IWL_TRAFFIC_ENTRY_SIZE  (64)
+
+enum {
+	MEASUREMENT_READY = (1 << 0),
+	MEASUREMENT_ACTIVE = (1 << 1),
+};
+
+/* interrupt statistics */
+struct isr_statistics {
+	u32 hw;
+	u32 sw;
+	u32 err_code;
+	u32 sch;
+	u32 alive;
+	u32 rfkill;
+	u32 ctkill;
+	u32 wakeup;
+	u32 rx;
+	u32 rx_handlers[REPLY_MAX];
+	u32 tx;
+	u32 unhandled;
+};
+
+/* management statistics */
+enum iwl_mgmt_stats {
+	MANAGEMENT_ASSOC_REQ = 0,
+	MANAGEMENT_ASSOC_RESP,
+	MANAGEMENT_REASSOC_REQ,
+	MANAGEMENT_REASSOC_RESP,
+	MANAGEMENT_PROBE_REQ,
+	MANAGEMENT_PROBE_RESP,
+	MANAGEMENT_BEACON,
+	MANAGEMENT_ATIM,
+	MANAGEMENT_DISASSOC,
+	MANAGEMENT_AUTH,
+	MANAGEMENT_DEAUTH,
+	MANAGEMENT_ACTION,
+	MANAGEMENT_MAX,
+};
+/* control statistics */
+enum iwl_ctrl_stats {
+	CONTROL_BACK_REQ =  0,
+	CONTROL_BACK,
+	CONTROL_PSPOLL,
+	CONTROL_RTS,
+	CONTROL_CTS,
+	CONTROL_ACK,
+	CONTROL_CFEND,
+	CONTROL_CFENDACK,
+	CONTROL_MAX,
+};
+
+struct traffic_stats {
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	u32 mgmt[MANAGEMENT_MAX];
+	u32 ctrl[CONTROL_MAX];
+	u32 data_cnt;
+	u64 data_bytes;
+#endif
+};
+
+/*
+ * iwl_switch_rxon: "channel switch" structure
+ *
+ * @ switch_in_progress: channel switch in progress
+ * @ channel: new channel
+ */
+struct iwl_switch_rxon {
+	bool switch_in_progress;
+	__le16 channel;
+};
+
+/*
+ * schedule the timer to wake up every UCODE_TRACE_PERIOD milliseconds
+ * to perform continuous uCode event logging operation if enabled
+ */
+#define UCODE_TRACE_PERIOD (100)
+
+/*
+ * iwl_event_log: current uCode event log position
+ *
+ * @ucode_trace: enable/disable ucode continuous trace timer
+ * @num_wraps: how many times the event buffer wraps
+ * @next_entry:  the entry just before the next one that uCode would fill
+ * @non_wraps_count: counter for no wrap detected when dump ucode events
+ * @wraps_once_count: counter for wrap once detected when dump ucode events
+ * @wraps_more_count: counter for wrap more than once detected
+ *		      when dump ucode events
+ */
+struct iwl_event_log {
+	bool ucode_trace;
+	u32 num_wraps;
+	u32 next_entry;
+	int non_wraps_count;
+	int wraps_once_count;
+	int wraps_more_count;
+};
+
+/*
+ * host interrupt timeout value
+ * used with setting interrupt coalescing timer
+ * the CSR_INT_COALESCING is an 8 bit register in 32-usec unit
+ *
+ * default interrupt coalescing timer is 64 x 32 = 2048 usecs
+ * default interrupt coalescing calibration timer is 16 x 32 = 512 usecs
+ */
+#define IWL_HOST_INT_TIMEOUT_MAX	(0xFF)
+#define IWL_HOST_INT_TIMEOUT_DEF	(0x40)
+#define IWL_HOST_INT_TIMEOUT_MIN	(0x0)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MAX	(0xFF)
+#define IWL_HOST_INT_CALIB_TIMEOUT_DEF	(0x10)
+#define IWL_HOST_INT_CALIB_TIMEOUT_MIN	(0x0)
+
+/*
+ * This is the threshold value of plcp error rate per 100mSecs.  It is
+ * used to set and check for the validity of plcp_delta.
+ */
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MIN	(1)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_DEF	(50)
+#define IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF	(100)
+#define IWL_MAX_PLCP_ERR_EXT_LONG_THRESHOLD_DEF	(200)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_MAX	(255)
+#define IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE	(0)
+
+#define IWL_DELAY_NEXT_FORCE_RF_RESET  (HZ*3)
+#define IWL_DELAY_NEXT_FORCE_FW_RELOAD (HZ*5)
+
+/* TX queue watchdog timeouts in mSecs */
+#define IWL_DEF_WD_TIMEOUT	(2000)
+#define IWL_LONG_WD_TIMEOUT	(10000)
+#define IWL_MAX_WD_TIMEOUT	(120000)
+
+enum iwl_reset {
+	IWL_RF_RESET = 0,
+	IWL_FW_RESET,
+	IWL_MAX_FORCE_RESET,
+};
+
+struct iwl_force_reset {
+	int reset_request_count;
+	int reset_success_count;
+	int reset_reject_count;
+	unsigned long reset_duration;
+	unsigned long last_force_reset_jiffies;
+};
+
+/* extend beacon time format bit shifting  */
+/*
+ * for _3945 devices
+ * bits 31:24 - extended
+ * bits 23:0  - interval
+ */
+#define IWL3945_EXT_BEACON_TIME_POS	24
+/*
+ * for _4965 devices
+ * bits 31:22 - extended
+ * bits 21:0  - interval
+ */
+#define IWL4965_EXT_BEACON_TIME_POS	22
+
+enum iwl_rxon_context_id {
+	IWL_RXON_CTX_BSS,
+
+	NUM_IWL_RXON_CTX
+};
+
+struct iwl_rxon_context {
+	struct ieee80211_vif *vif;
+
+	const u8 *ac_to_fifo;
+	const u8 *ac_to_queue;
+	u8 mcast_queue;
+
+	/*
+	 * We could use the vif to indicate active, but we
+	 * also need it to be active during disabling when
+	 * we already removed the vif for type setting.
+	 */
+	bool always_active, is_active;
+
+	bool ht_need_multiple_chains;
+
+	enum iwl_rxon_context_id ctxid;
+
+	u32 interface_modes, exclusive_interface_modes;
+	u8 unused_devtype, ap_devtype, ibss_devtype, station_devtype;
+
+	/*
+	 * We declare this const so it can only be
+	 * changed via explicit cast within the
+	 * routines that actually update the physical
+	 * hardware.
+	 */
+	const struct iwl_legacy_rxon_cmd active;
+	struct iwl_legacy_rxon_cmd staging;
+
+	struct iwl_rxon_time_cmd timing;
+
+	struct iwl_qos_info qos_data;
+
+	u8 bcast_sta_id, ap_sta_id;
+
+	u8 rxon_cmd, rxon_assoc_cmd, rxon_timing_cmd;
+	u8 qos_cmd;
+	u8 wep_key_cmd;
+
+	struct iwl_wep_key wep_keys[WEP_KEYS_MAX];
+	u8 key_mapping_keys;
+
+	__le32 station_flags;
+
+	struct {
+		bool non_gf_sta_present;
+		u8 protection;
+		bool enabled, is_40mhz;
+		u8 extension_chan_offset;
+	} ht;
+};
+
+struct iwl_priv {
+
+	/* ieee device used by generic ieee processing code */
+	struct ieee80211_hw *hw;
+	struct ieee80211_channel *ieee_channels;
+	struct ieee80211_rate *ieee_rates;
+	struct iwl_cfg *cfg;
+
+	/* temporary frame storage list */
+	struct list_head free_frames;
+	int frames_count;
+
+	enum ieee80211_band band;
+	int alloc_rxb_page;
+
+	void (*rx_handlers[REPLY_MAX])(struct iwl_priv *priv,
+				       struct iwl_rx_mem_buffer *rxb);
+
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+	/* spectrum measurement report caching */
+	struct iwl_spectrum_notification measure_report;
+	u8 measurement_status;
+
+	/* ucode beacon time */
+	u32 ucode_beacon_time;
+	int missed_beacon_threshold;
+
+	/* track IBSS manager (last beacon) status */
+	u32 ibss_manager;
+
+	/* storing the jiffies when the plcp error rate is received */
+	unsigned long plcp_jiffies;
+
+	/* force reset */
+	struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
+
+	/* we allocate array of iwl_channel_info for NIC's valid channels.
+	 *    Access via channel # using indirect index array */
+	struct iwl_channel_info *channel_info;	/* channel info array */
+	u8 channel_count;	/* # of channels */
+
+	/* thermal calibration */
+	s32 temperature;	/* degrees Kelvin */
+	s32 last_temperature;
+
+	/* init calibration results */
+	struct iwl_calib_result calib_results[IWL_CALIB_MAX];
+
+	/* Scan related variables */
+	unsigned long scan_start;
+	unsigned long scan_start_tsf;
+	void *scan_cmd;
+	enum ieee80211_band scan_band;
+	struct cfg80211_scan_request *scan_request;
+	struct ieee80211_vif *scan_vif;
+	bool is_internal_short_scan;
+	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;
+	struct mutex sync_cmd_mutex; /* enable serialization of sync commands */
+
+	/* basic pci-network driver stuff */
+	struct pci_dev *pci_dev;
+
+	/* pci hardware address support */
+	void __iomem *hw_base;
+	u32  hw_rev;
+	u32  hw_wa_rev;
+	u8   rev_id;
+
+	/* microcode/device supports multiple contexts */
+	u8 valid_contexts;
+
+	/* command queue number */
+	u8 cmd_queue;
+
+	/* max number of station keys */
+	u8 sta_key_max_num;
+
+	/* EEPROM MAC addresses */
+	struct mac_address addresses[1];
+
+	/* uCode images, save to reload in case of failure */
+	int fw_index;			/* firmware we're trying to load */
+	u32 ucode_ver;			/* version of ucode, copy of
+					   iwl_ucode.ver */
+	struct fw_desc ucode_code;	/* runtime inst */
+	struct fw_desc ucode_data;	/* runtime data original */
+	struct fw_desc ucode_data_backup;	/* runtime data save/restore */
+	struct fw_desc ucode_init;	/* initialization inst */
+	struct fw_desc ucode_init_data;	/* initialization data */
+	struct fw_desc ucode_boot;	/* bootstrap inst */
+	enum ucode_type ucode_type;
+	u8 ucode_write_complete;	/* the image write is complete */
+	char firmware_name[25];
+
+	struct iwl_rxon_context contexts[NUM_IWL_RXON_CTX];
+
+	struct iwl_switch_rxon switch_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;
+
+	u16 active_rate;
+
+	u8 start_calib;
+	struct iwl_sensitivity_data sensitivity_data;
+	struct iwl_chain_noise_data chain_noise_data;
+	__le16 sensitivity_tbl[HD_TABLE_SIZE];
+
+	struct iwl_ht_config current_ht_config;
+
+	/* Rate scaling data */
+	u8 retry_rate;
+
+	wait_queue_head_t wait_command_queue;
+
+	int activity_timer_active;
+
+	/* Rx and Tx DMA processing queues */
+	struct iwl_rx_queue rxq;
+	struct iwl_tx_queue *txq;
+	unsigned long txq_ctx_active_msk;
+	struct iwl_dma_ptr  kw;	/* keep warm address */
+	struct iwl_dma_ptr  scd_bc_tbls;
+
+	u32 scd_base_addr;	/* scheduler sram base address */
+
+	unsigned long status;
+
+	/* counts mgmt, ctl, and data packets */
+	struct traffic_stats tx_stats;
+	struct traffic_stats rx_stats;
+
+	/* counts interrupts */
+	struct isr_statistics isr_stats;
+
+	struct iwl_power_mgr power_data;
+
+	/* context information */
+	u8 bssid[ETH_ALEN]; /* used only on 3945 but filled by core */
+
+	/* station table variables */
+
+	/* Note: if lock and sta_lock are needed, lock must be acquired first */
+	spinlock_t sta_lock;
+	int num_stations;
+	struct iwl_station_entry stations[IWL_STATION_COUNT];
+	unsigned long ucode_key_table;
+
+	/* queue refcounts */
+#define IWL_MAX_HW_QUEUES	32
+	unsigned long queue_stopped[BITS_TO_LONGS(IWL_MAX_HW_QUEUES)];
+	/* for each AC */
+	atomic_t queue_stop_count[4];
+
+	/* Indication if ieee80211_ops->open has been called */
+	u8 is_open;
+
+	u8 mac80211_registered;
+
+	/* eeprom -- this is in the card's little endian byte order */
+	u8 *eeprom;
+	struct iwl_eeprom_calib_info *calib_info;
+
+	enum nl80211_iftype iw_mode;
+
+	/* Last Rx'd beacon timestamp */
+	u64 timestamp;
+
+	union {
+#if defined(CONFIG_IWL3945) || defined(CONFIG_IWL3945_MODULE)
+		struct {
+			void *shared_virt;
+			dma_addr_t shared_phys;
+
+			struct delayed_work thermal_periodic;
+			struct delayed_work rfkill_poll;
+
+			struct iwl3945_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+			struct iwl3945_notif_statistics accum_statistics;
+			struct iwl3945_notif_statistics delta_statistics;
+			struct iwl3945_notif_statistics max_delta;
+#endif
+
+			u32 sta_supp_rates;
+			int last_rx_rssi;	/* From Rx packet statistics */
+
+			/* Rx'd packet timing information */
+			u32 last_beacon_time;
+			u64 last_tsf;
+
+			/*
+			 * each calibration channel group in the
+			 * EEPROM has a derived clip setting for
+			 * each rate.
+			 */
+			const struct iwl3945_clip_group clip_groups[5];
+
+		} _3945;
+#endif
+#if defined(CONFIG_IWL4965) || defined(CONFIG_IWL4965_MODULE)
+		struct {
+			/*
+			 * reporting the number of tids has AGG on. 0 means
+			 * no AGGREGATION
+			 */
+			u8 agg_tids_count;
+
+			struct iwl_rx_phy_res last_phy_res;
+			bool last_phy_res_valid;
+
+			struct completion firmware_loading_complete;
+
+			/*
+			 * chain noise reset and gain commands are the
+			 * two extra calibration commands follows the standard
+			 * phy calibration commands
+			 */
+			u8 phy_calib_chain_noise_reset_cmd;
+			u8 phy_calib_chain_noise_gain_cmd;
+
+			struct iwl_notif_statistics statistics;
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+			struct iwl_notif_statistics accum_statistics;
+			struct iwl_notif_statistics delta_statistics;
+			struct iwl_notif_statistics max_delta;
+#endif
+
+		} _4965;
+#endif
+	};
+
+	struct iwl_hw_params hw_params;
+
+	u32 inta_mask;
+
+	struct workqueue_struct *workqueue;
+
+	struct work_struct restart;
+	struct work_struct scan_completed;
+	struct work_struct rx_replenish;
+	struct work_struct abort_scan;
+
+	struct iwl_rxon_context *beacon_ctx;
+	struct sk_buff *beacon_skb;
+
+	struct work_struct start_internal_scan;
+	struct work_struct tx_flush;
+
+	struct tasklet_struct irq_tasklet;
+
+	struct delayed_work init_alive_start;
+	struct delayed_work alive_start;
+	struct delayed_work scan_check;
+
+	/* TX Power */
+	s8 tx_power_user_lmt;
+	s8 tx_power_device_lmt;
+	s8 tx_power_next;
+
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	/* debugging info */
+	u32 debug_level; /* per device debugging will override global
+			    iwlegacy_debug_level if set */
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUG */
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUGFS
+	/* debugfs */
+	u16 tx_traffic_idx;
+	u16 rx_traffic_idx;
+	u8 *tx_traffic;
+	u8 *rx_traffic;
+	struct dentry *debugfs_dir;
+	u32 dbgfs_sram_offset, dbgfs_sram_len;
+	bool disable_ht40;
+#endif /* CONFIG_IWLWIFI_LEGACY_DEBUGFS */
+
+	struct work_struct txpower_work;
+	u32 disable_sens_cal;
+	u32 disable_chain_noise_cal;
+	u32 disable_tx_power_cal;
+	struct work_struct run_time_calib_work;
+	struct timer_list statistics_periodic;
+	struct timer_list ucode_trace;
+	struct timer_list watchdog;
+	bool hw_ready;
+
+	struct iwl_event_log event_log;
+
+	struct led_classdev led;
+	unsigned long blink_on, blink_off;
+	bool led_registered;
+}; /*iwl_priv */
+
+static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
+{
+	set_bit(txq_id, &priv->txq_ctx_active_msk);
+}
+
+static inline void iwl_txq_ctx_deactivate(struct iwl_priv *priv, int txq_id)
+{
+	clear_bit(txq_id, &priv->txq_ctx_active_msk);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+/*
+ * iwl_legacy_get_debug_level: Return active debug level for device
+ *
+ * Using sysfs it is possible to set per device debug level. This debug
+ * level will be used if set, otherwise the global debug level which can be
+ * set via module parameter is used.
+ */
+static inline u32 iwl_legacy_get_debug_level(struct iwl_priv *priv)
+{
+	if (priv->debug_level)
+		return priv->debug_level;
+	else
+		return iwlegacy_debug_level;
+}
+#else
+static inline u32 iwl_legacy_get_debug_level(struct iwl_priv *priv)
+{
+	return iwlegacy_debug_level;
+}
+#endif
+
+
+static inline struct ieee80211_hdr *
+iwl_legacy_tx_queue_get_hdr(struct iwl_priv *priv,
+						 int txq_id, int idx)
+{
+	if (priv->txq[txq_id].txb[idx].skb)
+		return (struct ieee80211_hdr *)priv->txq[txq_id].
+				txb[idx].skb->data;
+	return NULL;
+}
+
+static inline struct iwl_rxon_context *
+iwl_legacy_rxon_ctx_from_vif(struct ieee80211_vif *vif)
+{
+	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
+
+	return vif_priv->ctx;
+}
+
+#define for_each_context(priv, ctx)				\
+	for (ctx = &priv->contexts[IWL_RXON_CTX_BSS];		\
+	     ctx < &priv->contexts[NUM_IWL_RXON_CTX]; ctx++)	\
+		if (priv->valid_contexts & BIT(ctx->ctxid))
+
+static inline int iwl_legacy_is_associated(struct iwl_priv *priv,
+				    enum iwl_rxon_context_id ctxid)
+{
+	return (priv->contexts[ctxid].active.filter_flags &
+			RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int iwl_legacy_is_any_associated(struct iwl_priv *priv)
+{
+	return iwl_legacy_is_associated(priv, IWL_RXON_CTX_BSS);
+}
+
+static inline int iwl_legacy_is_associated_ctx(struct iwl_rxon_context *ctx)
+{
+	return (ctx->active.filter_flags & RXON_FILTER_ASSOC_MSK) ? 1 : 0;
+}
+
+static inline int iwl_legacy_is_channel_valid(const struct iwl_channel_info *ch_info)
+{
+	if (ch_info == NULL)
+		return 0;
+	return (ch_info->flags & EEPROM_CHANNEL_VALID) ? 1 : 0;
+}
+
+static inline int iwl_legacy_is_channel_radar(const struct iwl_channel_info *ch_info)
+{
+	return (ch_info->flags & EEPROM_CHANNEL_RADAR) ? 1 : 0;
+}
+
+static inline u8 iwl_legacy_is_channel_a_band(const struct iwl_channel_info *ch_info)
+{
+	return ch_info->band == IEEE80211_BAND_5GHZ;
+}
+
+static inline int
+iwl_legacy_is_channel_passive(const struct iwl_channel_info *ch)
+{
+	return (!(ch->flags & EEPROM_CHANNEL_ACTIVE)) ? 1 : 0;
+}
+
+static inline int
+iwl_legacy_is_channel_ibss(const struct iwl_channel_info *ch)
+{
+	return (ch->flags & EEPROM_CHANNEL_IBSS) ? 1 : 0;
+}
+
+static inline void
+__iwl_legacy_free_pages(struct iwl_priv *priv, struct page *page)
+{
+	__free_pages(page, priv->hw_params.rx_page_order);
+	priv->alloc_rxb_page--;
+}
+
+static inline void iwl_legacy_free_pages(struct iwl_priv *priv, unsigned long page)
+{
+	free_pages(page, priv->hw_params.rx_page_order);
+	priv->alloc_rxb_page--;
+}
+#endif				/* __iwl_legacy_dev_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,45 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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/module.h>
+
+/* sparse doesn't like tracepoint macros */
+#ifndef __CHECKER__
+#include "iwl-dev.h"
+
+#define CREATE_TRACE_POINTS
+#include "iwl-devtrace.h"
+
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite8);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ioread32);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_iowrite32);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_rx);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_tx);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_event);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_error);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_cont_event);
+EXPORT_TRACEPOINT_SYMBOL(iwlwifi_legacy_dev_ucode_wrap_event);
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-devtrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,270 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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
+ *
+ *****************************************************************************/
+
+#if !defined(__IWLWIFI_LEGACY_DEVICE_TRACE) || defined(TRACE_HEADER_MULTI_READ)
+#define __IWLWIFI_LEGACY_DEVICE_TRACE
+
+#include <linux/tracepoint.h>
+
+#if !defined(CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING) || defined(__CHECKER__)
+#undef TRACE_EVENT
+#define TRACE_EVENT(name, proto, ...) \
+static inline void trace_ ## name(proto) {}
+#endif
+
+
+#define PRIV_ENTRY	__field(struct iwl_priv *, priv)
+#define PRIV_ASSIGN	(__entry->priv = priv)
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_legacy_io
+
+TRACE_EVENT(iwlwifi_legacy_dev_ioread32,
+	TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
+	TP_ARGS(priv, offs, val),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, offs)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%p] read io[%#x] = %#x", __entry->priv,
+					__entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_iowrite8,
+	TP_PROTO(struct iwl_priv *priv, u32 offs, u8 val),
+	TP_ARGS(priv, offs, val),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, offs)
+		__field(u8, val)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%p] write io[%#x] = %#x)", __entry->priv,
+					__entry->offs, __entry->val)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_iowrite32,
+	TP_PROTO(struct iwl_priv *priv, u32 offs, u32 val),
+	TP_ARGS(priv, offs, val),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, offs)
+		__field(u32, val)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->offs = offs;
+		__entry->val = val;
+	),
+	TP_printk("[%p] write io[%#x] = %#x)", __entry->priv,
+					__entry->offs, __entry->val)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi_legacy_ucode
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_cont_event,
+	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
+	TP_ARGS(priv, time, data, ev),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(u32, time)
+		__field(u32, data)
+		__field(u32, ev)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->time = time;
+		__entry->data = data;
+		__entry->ev = ev;
+	),
+	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
+		  __entry->priv, __entry->time, __entry->data, __entry->ev)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_wrap_event,
+	TP_PROTO(struct iwl_priv *priv, u32 wraps, u32 n_entry, u32 p_entry),
+	TP_ARGS(priv, wraps, n_entry, p_entry),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(u32, wraps)
+		__field(u32, n_entry)
+		__field(u32, p_entry)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->wraps = wraps;
+		__entry->n_entry = n_entry;
+		__entry->p_entry = p_entry;
+	),
+	TP_printk("[%p] wraps=#%02d n=0x%X p=0x%X",
+		  __entry->priv, __entry->wraps, __entry->n_entry,
+		  __entry->p_entry)
+);
+
+#undef TRACE_SYSTEM
+#define TRACE_SYSTEM iwlwifi
+
+TRACE_EVENT(iwlwifi_legacy_dev_hcmd,
+	TP_PROTO(struct iwl_priv *priv, void *hcmd, size_t len, u32 flags),
+	TP_ARGS(priv, hcmd, len, flags),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__dynamic_array(u8, hcmd, len)
+		__field(u32, flags)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		memcpy(__get_dynamic_array(hcmd), hcmd, len);
+		__entry->flags = flags;
+	),
+	TP_printk("[%p] hcmd %#.2x (%ssync)",
+		  __entry->priv, ((u8 *)__get_dynamic_array(hcmd))[0],
+		  __entry->flags & CMD_ASYNC ? "a" : "")
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_rx,
+	TP_PROTO(struct iwl_priv *priv, void *rxbuf, size_t len),
+	TP_ARGS(priv, rxbuf, len),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__dynamic_array(u8, rxbuf, len)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		memcpy(__get_dynamic_array(rxbuf), rxbuf, len);
+	),
+	TP_printk("[%p] RX cmd %#.2x",
+		  __entry->priv, ((u8 *)__get_dynamic_array(rxbuf))[4])
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_tx,
+	TP_PROTO(struct iwl_priv *priv, void *tfd, size_t tfdlen,
+		 void *buf0, size_t buf0_len,
+		 void *buf1, size_t buf1_len),
+	TP_ARGS(priv, tfd, tfdlen, buf0, buf0_len, buf1, buf1_len),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(size_t, framelen)
+		__dynamic_array(u8, tfd, tfdlen)
+
+		/*
+		 * Do not insert between or below these items,
+		 * we want to keep the frame together (except
+		 * for the possible padding).
+		 */
+		__dynamic_array(u8, buf0, buf0_len)
+		__dynamic_array(u8, buf1, buf1_len)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->framelen = buf0_len + buf1_len;
+		memcpy(__get_dynamic_array(tfd), tfd, tfdlen);
+		memcpy(__get_dynamic_array(buf0), buf0, buf0_len);
+		memcpy(__get_dynamic_array(buf1), buf1, buf1_len);
+	),
+	TP_printk("[%p] TX %.2x (%zu bytes)",
+		  __entry->priv,
+		  ((u8 *)__get_dynamic_array(buf0))[0],
+		  __entry->framelen)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_error,
+	TP_PROTO(struct iwl_priv *priv, u32 desc, u32 time,
+		 u32 data1, u32 data2, u32 line, u32 blink1,
+		 u32 blink2, u32 ilink1, u32 ilink2),
+	TP_ARGS(priv, desc, time, data1, data2, line,
+		blink1, blink2, ilink1, ilink2),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+		__field(u32, desc)
+		__field(u32, time)
+		__field(u32, data1)
+		__field(u32, data2)
+		__field(u32, line)
+		__field(u32, blink1)
+		__field(u32, blink2)
+		__field(u32, ilink1)
+		__field(u32, ilink2)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->desc = desc;
+		__entry->time = time;
+		__entry->data1 = data1;
+		__entry->data2 = data2;
+		__entry->line = line;
+		__entry->blink1 = blink1;
+		__entry->blink2 = blink2;
+		__entry->ilink1 = ilink1;
+		__entry->ilink2 = ilink2;
+	),
+	TP_printk("[%p] #%02d %010u data 0x%08X 0x%08X line %u, "
+		  "blink 0x%05X 0x%05X ilink 0x%05X 0x%05X",
+		  __entry->priv, __entry->desc, __entry->time, __entry->data1,
+		  __entry->data2, __entry->line, __entry->blink1,
+		  __entry->blink2, __entry->ilink1, __entry->ilink2)
+);
+
+TRACE_EVENT(iwlwifi_legacy_dev_ucode_event,
+	TP_PROTO(struct iwl_priv *priv, u32 time, u32 data, u32 ev),
+	TP_ARGS(priv, time, data, ev),
+	TP_STRUCT__entry(
+		PRIV_ENTRY
+
+		__field(u32, time)
+		__field(u32, data)
+		__field(u32, ev)
+	),
+	TP_fast_assign(
+		PRIV_ASSIGN;
+		__entry->time = time;
+		__entry->data = data;
+		__entry->ev = ev;
+	),
+	TP_printk("[%p] EVT_LOGT:%010u:0x%08x:%04u",
+		  __entry->priv, __entry->time, __entry->data, __entry->ev)
+);
+#endif /* __IWLWIFI_DEVICE_TRACE */
+
+#undef TRACE_INCLUDE_PATH
+#define TRACE_INCLUDE_PATH .
+#undef TRACE_INCLUDE_FILE
+#define TRACE_INCLUDE_FILE iwl-devtrace
+#include <trace/define_trace.h>
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,554 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-commands.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-debug.h"
+#include "iwl-eeprom.h"
+#include "iwl-io.h"
+
+/************************** EEPROM BANDS ****************************
+ *
+ * The iwlegacy_eeprom_band definitions below provide the mapping from the
+ * EEPROM contents to the specific channel number supported for each
+ * band.
+ *
+ * For example, iwl_priv->eeprom.band_3_channels[4] from the band_3
+ * definition below maps to physical channel 42 in the 5.2GHz spectrum.
+ * The specific geography and calibration information for that channel
+ * is contained in the eeprom map itself.
+ *
+ * During init, we copy the eeprom information and channel map
+ * information into priv->channel_info_24/52 and priv->channel_map_24/52
+ *
+ * channel_map_24/52 provides the index in the channel_info array for a
+ * given channel.  We have to have two separate maps as there is channel
+ * overlap with the 2.4GHz and 5.2GHz spectrum as seen in band_1 and
+ * band_2
+ *
+ * A value of 0xff stored in the channel_map indicates that the channel
+ * is not supported by the hardware at all.
+ *
+ * A value of 0xfe in the channel_map indicates that the channel is not
+ * valid for Tx with the current hardware.  This means that
+ * while the system can tune and receive on a given channel, it may not
+ * be able to associate or transmit any frames on that
+ * channel.  There is no corresponding channel information for that
+ * entry.
+ *
+ *********************************************************************/
+
+/* 2.4 GHz */
+const u8 iwlegacy_eeprom_band_1[14] = {
+	1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+};
+
+/* 5.2 GHz bands */
+static const u8 iwlegacy_eeprom_band_2[] = {	/* 4915-5080MHz */
+	183, 184, 185, 187, 188, 189, 192, 196, 7, 8, 11, 12, 16
+};
+
+static const u8 iwlegacy_eeprom_band_3[] = {	/* 5170-5320MHz */
+	34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+};
+
+static const u8 iwlegacy_eeprom_band_4[] = {	/* 5500-5700MHz */
+	100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+};
+
+static const u8 iwlegacy_eeprom_band_5[] = {	/* 5725-5825MHz */
+	145, 149, 153, 157, 161, 165
+};
+
+static const u8 iwlegacy_eeprom_band_6[] = {       /* 2.4 ht40 channel */
+	1, 2, 3, 4, 5, 6, 7
+};
+
+static const u8 iwlegacy_eeprom_band_7[] = {       /* 5.2 ht40 channel */
+	36, 44, 52, 60, 100, 108, 116, 124, 132, 149, 157
+};
+
+/******************************************************************************
+ *
+ * EEPROM related functions
+ *
+******************************************************************************/
+
+static int iwl_legacy_eeprom_verify_signature(struct iwl_priv *priv)
+{
+	u32 gp = iwl_read32(priv, CSR_EEPROM_GP) & CSR_EEPROM_GP_VALID_MSK;
+	int ret = 0;
+
+	IWL_DEBUG_EEPROM(priv, "EEPROM signature=0x%08x\n", gp);
+	switch (gp) {
+	case CSR_EEPROM_GP_GOOD_SIG_EEP_LESS_THAN_4K:
+	case CSR_EEPROM_GP_GOOD_SIG_EEP_MORE_THAN_4K:
+		break;
+	default:
+		IWL_ERR(priv, "bad EEPROM signature,"
+			"EEPROM_GP=0x%08x\n", gp);
+		ret = -ENOENT;
+		break;
+	}
+	return ret;
+}
+
+const u8
+*iwl_legacy_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
+{
+	BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
+	return &priv->eeprom[offset];
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_query_addr);
+
+u16 iwl_legacy_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_legacy_eeprom_query16);
+
+/**
+ * iwl_legacy_eeprom_init - read EEPROM contents
+ *
+ * Load the EEPROM contents from adapter into priv->eeprom
+ *
+ * NOTE:  This routine uses the non-debug IO access functions.
+ */
+int iwl_legacy_eeprom_init(struct iwl_priv *priv)
+{
+	__le16 *e;
+	u32 gp = iwl_read32(priv, CSR_EEPROM_GP);
+	int sz;
+	int ret;
+	u16 addr;
+
+	/* allocate eeprom */
+	sz = priv->cfg->base_params->eeprom_size;
+	IWL_DEBUG_EEPROM(priv, "NVM size = %d\n", sz);
+	priv->eeprom = kzalloc(sz, GFP_KERNEL);
+	if (!priv->eeprom) {
+		ret = -ENOMEM;
+		goto alloc_err;
+	}
+	e = (__le16 *)priv->eeprom;
+
+	priv->cfg->ops->lib->apm_ops.init(priv);
+
+	ret = iwl_legacy_eeprom_verify_signature(priv);
+	if (ret < 0) {
+		IWL_ERR(priv, "EEPROM not found, EEPROM_GP=0x%08x\n", gp);
+		ret = -ENOENT;
+		goto err;
+	}
+
+	/* Make sure driver (instead of uCode) is allowed to read EEPROM */
+	ret = priv->cfg->ops->lib->eeprom_ops.acquire_semaphore(priv);
+	if (ret < 0) {
+		IWL_ERR(priv, "Failed to acquire EEPROM semaphore.\n");
+		ret = -ENOENT;
+		goto err;
+	}
+
+	/* eeprom is an array of 16bit values */
+	for (addr = 0; addr < sz; addr += sizeof(u16)) {
+		u32 r;
+
+		_iwl_legacy_write32(priv, CSR_EEPROM_REG,
+			     CSR_EEPROM_REG_MSK_ADDR & (addr << 1));
+
+		ret = iwl_poll_bit(priv, CSR_EEPROM_REG,
+					  CSR_EEPROM_REG_READ_VALID_MSK,
+					  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_legacy_read_direct32(priv, CSR_EEPROM_REG);
+		e[addr / 2] = cpu_to_le16(r >> 16);
+	}
+
+	IWL_DEBUG_EEPROM(priv, "NVM Type: %s, version: 0x%x\n",
+		       "EEPROM",
+		       iwl_legacy_eeprom_query16(priv, EEPROM_VERSION));
+
+	ret = 0;
+done:
+	priv->cfg->ops->lib->eeprom_ops.release_semaphore(priv);
+
+err:
+	if (ret)
+		iwl_legacy_eeprom_free(priv);
+	/* Reset chip to save power until we load uCode during "up". */
+	iwl_legacy_apm_stop(priv);
+alloc_err:
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_init);
+
+void iwl_legacy_eeprom_free(struct iwl_priv *priv)
+{
+	kfree(priv->eeprom);
+	priv->eeprom = NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_eeprom_free);
+
+static void iwl_legacy_init_band_reference(const struct iwl_priv *priv,
+			int eep_band, int *eeprom_ch_count,
+			const struct iwl_eeprom_channel **eeprom_ch_info,
+			const u8 **eeprom_ch_index)
+{
+	u32 offset = priv->cfg->ops->lib->
+			eeprom_ops.regulatory_bands[eep_band - 1];
+	switch (eep_band) {
+	case 1:		/* 2.4GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_1);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_1;
+		break;
+	case 2:		/* 4.9GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_2);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_2;
+		break;
+	case 3:		/* 5.2GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_3);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_3;
+		break;
+	case 4:		/* 5.5GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_4);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_4;
+		break;
+	case 5:		/* 5.7GHz band */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_5);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_5;
+		break;
+	case 6:		/* 2.4GHz ht40 channels */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_6);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_6;
+		break;
+	case 7:		/* 5 GHz ht40 channels */
+		*eeprom_ch_count = ARRAY_SIZE(iwlegacy_eeprom_band_7);
+		*eeprom_ch_info = (struct iwl_eeprom_channel *)
+				iwl_legacy_eeprom_query_addr(priv, offset);
+		*eeprom_ch_index = iwlegacy_eeprom_band_7;
+		break;
+	default:
+		BUG();
+		return;
+	}
+}
+
+#define CHECK_AND_PRINT(x) ((eeprom_ch->flags & EEPROM_CHANNEL_##x) \
+			    ? # x " " : "")
+/**
+ * iwl_legacy_mod_ht40_chan_info - Copy ht40 channel info into driver's priv.
+ *
+ * Does not set up a command, or touch hardware.
+ */
+static int iwl_legacy_mod_ht40_chan_info(struct iwl_priv *priv,
+			      enum ieee80211_band band, u16 channel,
+			      const struct iwl_eeprom_channel *eeprom_ch,
+			      u8 clear_ht40_extension_channel)
+{
+	struct iwl_channel_info *ch_info;
+
+	ch_info = (struct iwl_channel_info *)
+			iwl_legacy_get_channel_info(priv, band, channel);
+
+	if (!iwl_legacy_is_channel_valid(ch_info))
+		return -1;
+
+	IWL_DEBUG_EEPROM(priv, "HT40 Ch. %d [%sGHz] %s%s%s%s%s(0x%02x %ddBm):"
+			" Ad-Hoc %ssupported\n",
+			ch_info->channel,
+			iwl_legacy_is_channel_a_band(ch_info) ?
+			"5.2" : "2.4",
+			CHECK_AND_PRINT(IBSS),
+			CHECK_AND_PRINT(ACTIVE),
+			CHECK_AND_PRINT(RADAR),
+			CHECK_AND_PRINT(WIDE),
+			CHECK_AND_PRINT(DFS),
+			eeprom_ch->flags,
+			eeprom_ch->max_power_avg,
+			((eeprom_ch->flags & EEPROM_CHANNEL_IBSS)
+			 && !(eeprom_ch->flags & EEPROM_CHANNEL_RADAR)) ?
+			"" : "not ");
+
+	ch_info->ht40_eeprom = *eeprom_ch;
+	ch_info->ht40_max_power_avg = eeprom_ch->max_power_avg;
+	ch_info->ht40_flags = eeprom_ch->flags;
+	if (eeprom_ch->flags & EEPROM_CHANNEL_VALID)
+		ch_info->ht40_extension_channel &=
+					~clear_ht40_extension_channel;
+
+	return 0;
+}
+
+#define CHECK_AND_PRINT_I(x) ((eeprom_ch_info[ch].flags & EEPROM_CHANNEL_##x) \
+			    ? # x " " : "")
+
+/**
+ * iwl_legacy_init_channel_map - Set up driver's info for all possible channels
+ */
+int iwl_legacy_init_channel_map(struct iwl_priv *priv)
+{
+	int eeprom_ch_count = 0;
+	const u8 *eeprom_ch_index = NULL;
+	const struct iwl_eeprom_channel *eeprom_ch_info = NULL;
+	int band, ch;
+	struct iwl_channel_info *ch_info;
+
+	if (priv->channel_count) {
+		IWL_DEBUG_EEPROM(priv, "Channel map already initialized.\n");
+		return 0;
+	}
+
+	IWL_DEBUG_EEPROM(priv, "Initializing regulatory info from EEPROM\n");
+
+	priv->channel_count =
+	    ARRAY_SIZE(iwlegacy_eeprom_band_1) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_2) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_3) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_4) +
+	    ARRAY_SIZE(iwlegacy_eeprom_band_5);
+
+	IWL_DEBUG_EEPROM(priv, "Parsing data for %d channels.\n",
+			priv->channel_count);
+
+	priv->channel_info = kzalloc(sizeof(struct iwl_channel_info) *
+				     priv->channel_count, GFP_KERNEL);
+	if (!priv->channel_info) {
+		IWL_ERR(priv, "Could not allocate channel_info\n");
+		priv->channel_count = 0;
+		return -ENOMEM;
+	}
+
+	ch_info = priv->channel_info;
+
+	/* Loop through the 5 EEPROM bands adding them in order to the
+	 * channel map we maintain (that contains additional information than
+	 * what just in the EEPROM) */
+	for (band = 1; band <= 5; band++) {
+
+		iwl_legacy_init_band_reference(priv, band, &eeprom_ch_count,
+					&eeprom_ch_info, &eeprom_ch_index);
+
+		/* Loop through each band adding each of the channels */
+		for (ch = 0; ch < eeprom_ch_count; ch++) {
+			ch_info->channel = eeprom_ch_index[ch];
+			ch_info->band = (band == 1) ? IEEE80211_BAND_2GHZ :
+			    IEEE80211_BAND_5GHZ;
+
+			/* permanently store EEPROM's channel regulatory flags
+			 *   and max power in channel info database. */
+			ch_info->eeprom = eeprom_ch_info[ch];
+
+			/* Copy the run-time flags so they are there even on
+			 * invalid channels */
+			ch_info->flags = eeprom_ch_info[ch].flags;
+			/* First write that ht40 is not enabled, and then enable
+			 * one by one */
+			ch_info->ht40_extension_channel =
+					IEEE80211_CHAN_NO_HT40;
+
+			if (!(iwl_legacy_is_channel_valid(ch_info))) {
+				IWL_DEBUG_EEPROM(priv,
+					       "Ch. %d Flags %x [%sGHz] - "
+					       "No traffic\n",
+					       ch_info->channel,
+					       ch_info->flags,
+					       iwl_legacy_is_channel_a_band(ch_info) ?
+					       "5.2" : "2.4");
+				ch_info++;
+				continue;
+			}
+
+			/* Initialize regulatory-based run-time data */
+			ch_info->max_power_avg = ch_info->curr_txpow =
+			    eeprom_ch_info[ch].max_power_avg;
+			ch_info->scan_power = eeprom_ch_info[ch].max_power_avg;
+			ch_info->min_power = 0;
+
+			IWL_DEBUG_EEPROM(priv, "Ch. %d [%sGHz] "
+				       "%s%s%s%s%s%s(0x%02x %ddBm):"
+				       " Ad-Hoc %ssupported\n",
+				       ch_info->channel,
+				       iwl_legacy_is_channel_a_band(ch_info) ?
+				       "5.2" : "2.4",
+				       CHECK_AND_PRINT_I(VALID),
+				       CHECK_AND_PRINT_I(IBSS),
+				       CHECK_AND_PRINT_I(ACTIVE),
+				       CHECK_AND_PRINT_I(RADAR),
+				       CHECK_AND_PRINT_I(WIDE),
+				       CHECK_AND_PRINT_I(DFS),
+				       eeprom_ch_info[ch].flags,
+				       eeprom_ch_info[ch].max_power_avg,
+				       ((eeprom_ch_info[ch].
+					 flags & EEPROM_CHANNEL_IBSS)
+					&& !(eeprom_ch_info[ch].
+					     flags & EEPROM_CHANNEL_RADAR))
+				       ? "" : "not ");
+
+			ch_info++;
+		}
+	}
+
+	/* Check if we do have HT40 channels */
+	if (priv->cfg->ops->lib->eeprom_ops.regulatory_bands[5] ==
+	    EEPROM_REGULATORY_BAND_NO_HT40 &&
+	    priv->cfg->ops->lib->eeprom_ops.regulatory_bands[6] ==
+	    EEPROM_REGULATORY_BAND_NO_HT40)
+		return 0;
+
+	/* Two additional EEPROM bands for 2.4 and 5 GHz HT40 channels */
+	for (band = 6; band <= 7; band++) {
+		enum ieee80211_band ieeeband;
+
+		iwl_legacy_init_band_reference(priv, band, &eeprom_ch_count,
+					&eeprom_ch_info, &eeprom_ch_index);
+
+		/* EEPROM band 6 is 2.4, band 7 is 5 GHz */
+		ieeeband =
+			(band == 6) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+
+		/* Loop through each band adding each of the channels */
+		for (ch = 0; ch < eeprom_ch_count; ch++) {
+			/* Set up driver's info for lower half */
+			iwl_legacy_mod_ht40_chan_info(priv, ieeeband,
+						eeprom_ch_index[ch],
+						&eeprom_ch_info[ch],
+						IEEE80211_CHAN_NO_HT40PLUS);
+
+			/* Set up driver's info for upper half */
+			iwl_legacy_mod_ht40_chan_info(priv, ieeeband,
+						eeprom_ch_index[ch] + 4,
+						&eeprom_ch_info[ch],
+						IEEE80211_CHAN_NO_HT40MINUS);
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_init_channel_map);
+
+/*
+ * iwl_legacy_free_channel_map - undo allocations in iwl_legacy_init_channel_map
+ */
+void iwl_legacy_free_channel_map(struct iwl_priv *priv)
+{
+	kfree(priv->channel_info);
+	priv->channel_count = 0;
+}
+EXPORT_SYMBOL(iwl_legacy_free_channel_map);
+
+/**
+ * iwl_legacy_get_channel_info - Find driver's private channel info
+ *
+ * Based on band and channel number.
+ */
+const struct
+iwl_channel_info *iwl_legacy_get_channel_info(const struct iwl_priv *priv,
+					enum ieee80211_band band, u16 channel)
+{
+	int i;
+
+	switch (band) {
+	case IEEE80211_BAND_5GHZ:
+		for (i = 14; i < priv->channel_count; i++) {
+			if (priv->channel_info[i].channel == channel)
+				return &priv->channel_info[i];
+		}
+		break;
+	case IEEE80211_BAND_2GHZ:
+		if (channel >= 1 && channel <= 14)
+			return &priv->channel_info[channel - 1];
+		break;
+	default:
+		BUG();
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(iwl_legacy_get_channel_info);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,344 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+#ifndef __iwl_legacy_eeprom_h__
+#define __iwl_legacy_eeprom_h__
+
+#include <net/mac80211.h>
+
+struct iwl_priv;
+
+/*
+ * EEPROM access time values:
+ *
+ * Driver initiates EEPROM read by writing byte address << 1 to CSR_EEPROM_REG.
+ * Driver then polls CSR_EEPROM_REG for CSR_EEPROM_REG_READ_VALID_MSK (0x1).
+ * When polling, wait 10 uSec between polling loops, up to a maximum 5000 uSec.
+ * Driver reads 16-bit value from bits 31-16 of CSR_EEPROM_REG.
+ */
+#define IWL_EEPROM_ACCESS_TIMEOUT	5000 /* uSec */
+
+#define IWL_EEPROM_SEM_TIMEOUT		10   /* microseconds */
+#define IWL_EEPROM_SEM_RETRY_LIMIT	1000 /* number of attempts (not time) */
+
+
+/*
+ * Regulatory channel usage flags in EEPROM struct iwl4965_eeprom_channel.flags.
+ *
+ * IBSS and/or AP operation is allowed *only* on those channels with
+ * (VALID && IBSS && ACTIVE && !RADAR).  This restriction is in place because
+ * RADAR detection is not supported by the 4965 driver, but is a
+ * requirement for establishing a new network for legal operation on channels
+ * requiring RADAR detection or restricting ACTIVE scanning.
+ *
+ * NOTE:  "WIDE" flag does not indicate anything about "HT40" 40 MHz channels.
+ *        It only indicates that 20 MHz channel use is supported; HT40 channel
+ *        usage is indicated by a separate set of regulatory flags for each
+ *        HT40 channel pair.
+ *
+ * NOTE:  Using a channel inappropriately will result in a uCode error!
+ */
+#define IWL_NUM_TX_CALIB_GROUPS 5
+enum {
+	EEPROM_CHANNEL_VALID = (1 << 0),	/* usable for this SKU/geo */
+	EEPROM_CHANNEL_IBSS = (1 << 1),		/* usable as an IBSS channel */
+	/* Bit 2 Reserved */
+	EEPROM_CHANNEL_ACTIVE = (1 << 3),	/* active scanning allowed */
+	EEPROM_CHANNEL_RADAR = (1 << 4),	/* radar detection required */
+	EEPROM_CHANNEL_WIDE = (1 << 5),		/* 20 MHz channel okay */
+	/* Bit 6 Reserved (was Narrow Channel) */
+	EEPROM_CHANNEL_DFS = (1 << 7),	/* dynamic freq selection candidate */
+};
+
+/* SKU Capabilities */
+/* 3945 only */
+#define EEPROM_SKU_CAP_SW_RF_KILL_ENABLE                (1 << 0)
+#define EEPROM_SKU_CAP_HW_RF_KILL_ENABLE                (1 << 1)
+
+/* *regulatory* channel data format in eeprom, one for each channel.
+ * There are separate entries for HT40 (40 MHz) vs. normal (20 MHz) channels. */
+struct iwl_eeprom_channel {
+	u8 flags;		/* EEPROM_CHANNEL_* flags copied from EEPROM */
+	s8 max_power_avg;	/* max power (dBm) on this chnl, limit 31 */
+} __packed;
+
+/* 3945 Specific */
+#define EEPROM_3945_EEPROM_VERSION	(0x2f)
+
+/* 4965 has two radio transmitters (and 3 radio receivers) */
+#define EEPROM_TX_POWER_TX_CHAINS      (2)
+
+/* 4965 has room for up to 8 sets of txpower calibration data */
+#define EEPROM_TX_POWER_BANDS          (8)
+
+/* 4965 factory calibration measures txpower gain settings for
+ * each of 3 target output levels */
+#define EEPROM_TX_POWER_MEASUREMENTS   (3)
+
+/* 4965 Specific */
+/* 4965 driver does not work with txpower calibration version < 5 */
+#define EEPROM_4965_TX_POWER_VERSION    (5)
+#define EEPROM_4965_EEPROM_VERSION	(0x2f)
+#define EEPROM_4965_CALIB_VERSION_OFFSET       (2*0xB6) /* 2 bytes */
+#define EEPROM_4965_CALIB_TXPOWER_OFFSET       (2*0xE8) /* 48  bytes */
+#define EEPROM_4965_BOARD_REVISION             (2*0x4F) /* 2 bytes */
+#define EEPROM_4965_BOARD_PBA                  (2*0x56+1) /* 9 bytes */
+
+/* 2.4 GHz */
+extern const u8 iwlegacy_eeprom_band_1[14];
+
+/*
+ * factory calibration data for one txpower level, on one channel,
+ * measured on one of the 2 tx chains (radio transmitter and associated
+ * antenna).  EEPROM contains:
+ *
+ * 1)  Temperature (degrees Celsius) of device when measurement was made.
+ *
+ * 2)  Gain table index used to achieve the target measurement power.
+ *     This refers to the "well-known" gain tables (see iwl-4965-hw.h).
+ *
+ * 3)  Actual measured output power, in half-dBm ("34" = 17 dBm).
+ *
+ * 4)  RF power amplifier detector level measurement (not used).
+ */
+struct iwl_eeprom_calib_measure {
+	u8 temperature;		/* Device temperature (Celsius) */
+	u8 gain_idx;		/* Index into gain table */
+	u8 actual_pow;		/* Measured RF output power, half-dBm */
+	s8 pa_det;		/* Power amp detector level (not used) */
+} __packed;
+
+
+/*
+ * measurement set for one channel.  EEPROM contains:
+ *
+ * 1)  Channel number measured
+ *
+ * 2)  Measurements for each of 3 power levels for each of 2 radio transmitters
+ *     (a.k.a. "tx chains") (6 measurements altogether)
+ */
+struct iwl_eeprom_calib_ch_info {
+	u8 ch_num;
+	struct iwl_eeprom_calib_measure
+		measurements[EEPROM_TX_POWER_TX_CHAINS]
+			[EEPROM_TX_POWER_MEASUREMENTS];
+} __packed;
+
+/*
+ * txpower subband info.
+ *
+ * For each frequency subband, EEPROM contains the following:
+ *
+ * 1)  First and last channels within range of the subband.  "0" values
+ *     indicate that this sample set is not being used.
+ *
+ * 2)  Sample measurement sets for 2 channels close to the range endpoints.
+ */
+struct iwl_eeprom_calib_subband_info {
+	u8 ch_from;	/* channel number of lowest channel in subband */
+	u8 ch_to;	/* channel number of highest channel in subband */
+	struct iwl_eeprom_calib_ch_info ch1;
+	struct iwl_eeprom_calib_ch_info ch2;
+} __packed;
+
+
+/*
+ * txpower calibration info.  EEPROM contains:
+ *
+ * 1)  Factory-measured saturation power levels (maximum levels at which
+ *     tx power amplifier can output a signal without too much distortion).
+ *     There is one level for 2.4 GHz band and one for 5 GHz band.  These
+ *     values apply to all channels within each of the bands.
+ *
+ * 2)  Factory-measured power supply voltage level.  This is assumed to be
+ *     constant (i.e. same value applies to all channels/bands) while the
+ *     factory measurements are being made.
+ *
+ * 3)  Up to 8 sets of factory-measured txpower calibration values.
+ *     These are for different frequency ranges, since txpower gain
+ *     characteristics of the analog radio circuitry vary with frequency.
+ *
+ *     Not all sets need to be filled with data;
+ *     struct iwl_eeprom_calib_subband_info contains range of channels
+ *     (0 if unused) for each set of data.
+ */
+struct iwl_eeprom_calib_info {
+	u8 saturation_power24;	/* half-dBm (e.g. "34" = 17 dBm) */
+	u8 saturation_power52;	/* half-dBm */
+	__le16 voltage;		/* signed */
+	struct iwl_eeprom_calib_subband_info
+		band_info[EEPROM_TX_POWER_BANDS];
+} __packed;
+
+
+/* General */
+#define EEPROM_DEVICE_ID                    (2*0x08)	/* 2 bytes */
+#define EEPROM_MAC_ADDRESS                  (2*0x15)	/* 6  bytes */
+#define EEPROM_BOARD_REVISION               (2*0x35)	/* 2  bytes */
+#define EEPROM_BOARD_PBA_NUMBER             (2*0x3B+1)	/* 9  bytes */
+#define EEPROM_VERSION                      (2*0x44)	/* 2  bytes */
+#define EEPROM_SKU_CAP                      (2*0x45)	/* 2  bytes */
+#define EEPROM_OEM_MODE                     (2*0x46)	/* 2  bytes */
+#define EEPROM_WOWLAN_MODE                  (2*0x47)	/* 2  bytes */
+#define EEPROM_RADIO_CONFIG                 (2*0x48)	/* 2  bytes */
+#define EEPROM_NUM_MAC_ADDRESS              (2*0x4C)	/* 2  bytes */
+
+/* The following masks are to be applied on EEPROM_RADIO_CONFIG */
+#define EEPROM_RF_CFG_TYPE_MSK(x)   (x & 0x3)         /* bits 0-1   */
+#define EEPROM_RF_CFG_STEP_MSK(x)   ((x >> 2)  & 0x3) /* bits 2-3   */
+#define EEPROM_RF_CFG_DASH_MSK(x)   ((x >> 4)  & 0x3) /* bits 4-5   */
+#define EEPROM_RF_CFG_PNUM_MSK(x)   ((x >> 6)  & 0x3) /* bits 6-7   */
+#define EEPROM_RF_CFG_TX_ANT_MSK(x) ((x >> 8)  & 0xF) /* bits 8-11  */
+#define EEPROM_RF_CFG_RX_ANT_MSK(x) ((x >> 12) & 0xF) /* bits 12-15 */
+
+#define EEPROM_3945_RF_CFG_TYPE_MAX  0x0
+#define EEPROM_4965_RF_CFG_TYPE_MAX  0x1
+
+/*
+ * Per-channel regulatory data.
+ *
+ * Each channel that *might* be supported by iwl has a fixed location
+ * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
+ * txpower (MSB).
+ *
+ * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
+ * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
+ *
+ * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
+ */
+#define EEPROM_REGULATORY_SKU_ID            (2*0x60)    /* 4  bytes */
+#define EEPROM_REGULATORY_BAND_1            (2*0x62)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_1_CHANNELS   (2*0x63)	/* 28 bytes */
+
+/*
+ * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
+ * 5.0 GHz channels 7, 8, 11, 12, 16
+ * (4915-5080MHz) (none of these is ever supported)
+ */
+#define EEPROM_REGULATORY_BAND_2            (2*0x71)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_2_CHANNELS   (2*0x72)	/* 26 bytes */
+
+/*
+ * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
+ * (5170-5320MHz)
+ */
+#define EEPROM_REGULATORY_BAND_3            (2*0x7F)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_3_CHANNELS   (2*0x80)	/* 24 bytes */
+
+/*
+ * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
+ * (5500-5700MHz)
+ */
+#define EEPROM_REGULATORY_BAND_4            (2*0x8C)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_4_CHANNELS   (2*0x8D)	/* 22 bytes */
+
+/*
+ * 5.7 GHz channels 145, 149, 153, 157, 161, 165
+ * (5725-5825MHz)
+ */
+#define EEPROM_REGULATORY_BAND_5            (2*0x98)	/* 2  bytes */
+#define EEPROM_REGULATORY_BAND_5_CHANNELS   (2*0x99)	/* 12 bytes */
+
+/*
+ * 2.4 GHz HT40 channels 1 (5), 2 (6), 3 (7), 4 (8), 5 (9), 6 (10), 7 (11)
+ *
+ * The channel listed is the center of the lower 20 MHz half of the channel.
+ * The overall center frequency is actually 2 channels (10 MHz) above that,
+ * and the upper half of each HT40 channel is centered 4 channels (20 MHz) away
+ * from the lower half; e.g. the upper half of HT40 channel 1 is channel 5,
+ * and the overall HT40 channel width centers on channel 3.
+ *
+ * NOTE:  The RXON command uses 20 MHz channel numbers to specify the
+ *        control channel to which to tune.  RXON also specifies whether the
+ *        control channel is the upper or lower half of a HT40 channel.
+ *
+ * NOTE:  4965 does not support HT40 channels on 2.4 GHz.
+ */
+#define EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS (2*0xA0)	/* 14 bytes */
+
+/*
+ * 5.2 GHz HT40 channels 36 (40), 44 (48), 52 (56), 60 (64),
+ * 100 (104), 108 (112), 116 (120), 124 (128), 132 (136), 149 (153), 157 (161)
+ */
+#define EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS (2*0xA8)	/* 22 bytes */
+
+#define EEPROM_REGULATORY_BAND_NO_HT40			(0)
+
+struct iwl_eeprom_ops {
+	const u32 regulatory_bands[7];
+	int (*acquire_semaphore) (struct iwl_priv *priv);
+	void (*release_semaphore) (struct iwl_priv *priv);
+};
+
+
+int iwl_legacy_eeprom_init(struct iwl_priv *priv);
+void iwl_legacy_eeprom_free(struct iwl_priv *priv);
+const u8 *iwl_legacy_eeprom_query_addr(const struct iwl_priv *priv,
+					size_t offset);
+u16 iwl_legacy_eeprom_query16(const struct iwl_priv *priv, size_t offset);
+int iwl_legacy_init_channel_map(struct iwl_priv *priv);
+void iwl_legacy_free_channel_map(struct iwl_priv *priv);
+const struct iwl_channel_info *iwl_legacy_get_channel_info(
+		const struct iwl_priv *priv,
+		enum ieee80211_band band, u16 channel);
+
+#endif  /* __iwl_legacy_eeprom_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-fh.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-fh.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-fh.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-fh.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,513 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *
+ *****************************************************************************/
+#ifndef __iwl_legacy_fh_h__
+#define __iwl_legacy_fh_h__
+
+/****************************/
+/* Flow Handler Definitions */
+/****************************/
+
+/**
+ * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
+ * Addresses are offsets from device's PCI hardware base address.
+ */
+#define FH_MEM_LOWER_BOUND                   (0x1000)
+#define FH_MEM_UPPER_BOUND                   (0x2000)
+
+/**
+ * Keep-Warm (KW) buffer base address.
+ *
+ * Driver must allocate a 4KByte buffer that is used by 4965 for keeping the
+ * host DRAM powered on (via dummy accesses to DRAM) to maintain low-latency
+ * DRAM access when 4965 is Txing or Rxing.  The dummy accesses prevent host
+ * from going into a power-savings mode that would cause higher DRAM latency,
+ * and possible data over/under-runs, before all Tx/Rx is complete.
+ *
+ * Driver loads FH_KW_MEM_ADDR_REG with the physical address (bits 35:4)
+ * of the buffer, which must be 4K aligned.  Once this is set up, the 4965
+ * automatically invokes keep-warm accesses when normal accesses might not
+ * be sufficient to maintain fast DRAM response.
+ *
+ * Bit fields:
+ *  31-0:  Keep-warm buffer physical base address [35:4], must be 4K aligned
+ */
+#define FH_KW_MEM_ADDR_REG		     (FH_MEM_LOWER_BOUND + 0x97C)
+
+
+/**
+ * TFD Circular Buffers Base (CBBC) addresses
+ *
+ * 4965 has 16 base pointer registers, one for each of 16 host-DRAM-resident
+ * circular buffers (CBs/queues) containing Transmit Frame Descriptors (TFDs)
+ * (see struct iwl_tfd_frame).  These 16 pointer registers are offset by 0x04
+ * bytes from one another.  Each TFD circular buffer in DRAM must be 256-byte
+ * aligned (address bits 0-7 must be 0).
+ *
+ * Bit fields in each pointer register:
+ *  27-0: TFD CB physical base address [35:8], must be 256-byte aligned
+ */
+#define FH_MEM_CBBC_LOWER_BOUND          (FH_MEM_LOWER_BOUND + 0x9D0)
+#define FH_MEM_CBBC_UPPER_BOUND          (FH_MEM_LOWER_BOUND + 0xA10)
+
+/* Find TFD CB base pointer for given queue (range 0-15). */
+#define FH_MEM_CBBC_QUEUE(x)  (FH_MEM_CBBC_LOWER_BOUND + (x) * 0x4)
+
+
+/**
+ * Rx SRAM Control and Status Registers (RSCSR)
+ *
+ * These registers provide handshake between driver and 4965 for the Rx queue
+ * (this queue handles *all* command responses, notifications, Rx data, etc.
+ * sent from 4965 uCode to host driver).  Unlike Tx, there is only one Rx
+ * queue, and only one Rx DMA/FIFO channel.  Also unlike Tx, which can
+ * concatenate up to 20 DRAM buffers to form a Tx frame, each Receive Buffer
+ * Descriptor (RBD) points to only one Rx Buffer (RB); there is a 1:1
+ * mapping between RBDs and RBs.
+ *
+ * Driver must allocate host DRAM memory for the following, and set the
+ * physical address of each into 4965 registers:
+ *
+ * 1)  Receive Buffer Descriptor (RBD) circular buffer (CB), typically with 256
+ *     entries (although any power of 2, up to 4096, is selectable by driver).
+ *     Each entry (1 dword) points to a receive buffer (RB) of consistent size
+ *     (typically 4K, although 8K or 16K are also selectable by driver).
+ *     Driver sets up RB size and number of RBDs in the CB via Rx config
+ *     register FH_MEM_RCSR_CHNL0_CONFIG_REG.
+ *
+ *     Bit fields within one RBD:
+ *     27-0:  Receive Buffer physical address bits [35:8], 256-byte aligned
+ *
+ *     Driver sets physical address [35:8] of base of RBD circular buffer
+ *     into FH_RSCSR_CHNL0_RBDCB_BASE_REG [27:0].
+ *
+ * 2)  Rx status buffer, 8 bytes, in which 4965 indicates which Rx Buffers
+ *     (RBs) have been filled, via a "write pointer", actually the index of
+ *     the RB's corresponding RBD within the circular buffer.  Driver sets
+ *     physical address [35:4] into FH_RSCSR_CHNL0_STTS_WPTR_REG [31:0].
+ *
+ *     Bit fields in lower dword of Rx status buffer (upper dword not used
+ *     by driver; see struct iwl4965_shared, val0):
+ *     31-12:  Not used by driver
+ *     11- 0:  Index of last filled Rx buffer descriptor
+ *             (4965 writes, driver reads this value)
+ *
+ * As the driver prepares Receive Buffers (RBs) for 4965 to fill, driver must
+ * enter pointers to these RBs into contiguous RBD circular buffer entries,
+ * and update the 4965's "write" index register,
+ * FH_RSCSR_CHNL0_RBDCB_WPTR_REG.
+ *
+ * This "write" index corresponds to the *next* RBD that the driver will make
+ * available, i.e. one RBD past the tail of the ready-to-fill RBDs within
+ * the circular buffer.  This value should initially be 0 (before preparing any
+ * RBs), should be 8 after preparing the first 8 RBs (for example), and must
+ * wrap back to 0 at the end of the circular buffer (but don't wrap before
+ * "read" index has advanced past 1!  See below).
+ * NOTE:  4965 EXPECTS THE WRITE INDEX TO BE INCREMENTED IN MULTIPLES OF 8.
+ *
+ * As the 4965 fills RBs (referenced from contiguous RBDs within the circular
+ * buffer), it updates the Rx status buffer in host DRAM, 2) described above,
+ * to tell the driver the index of the latest filled RBD.  The driver must
+ * read this "read" index from DRAM after receiving an Rx interrupt from 4965.
+ *
+ * The driver must also internally keep track of a third index, which is the
+ * next RBD to process.  When receiving an Rx interrupt, driver should process
+ * all filled but unprocessed RBs up to, but not including, the RB
+ * corresponding to the "read" index.  For example, if "read" index becomes "1",
+ * driver may process the RB pointed to by RBD 0.  Depending on volume of
+ * traffic, there may be many RBs to process.
+ *
+ * If read index == write index, 4965 thinks there is no room to put new data.
+ * Due to this, the maximum number of filled RBs is 255, instead of 256.  To
+ * be safe, make sure that there is a gap of at least 2 RBDs between "write"
+ * and "read" indexes; that is, make sure that there are no more than 254
+ * buffers waiting to be filled.
+ */
+#define FH_MEM_RSCSR_LOWER_BOUND	(FH_MEM_LOWER_BOUND + 0xBC0)
+#define FH_MEM_RSCSR_UPPER_BOUND	(FH_MEM_LOWER_BOUND + 0xC00)
+#define FH_MEM_RSCSR_CHNL0		(FH_MEM_RSCSR_LOWER_BOUND)
+
+/**
+ * Physical base address of 8-byte Rx Status buffer.
+ * Bit fields:
+ *  31-0: Rx status buffer physical base address [35:4], must 16-byte aligned.
+ */
+#define FH_RSCSR_CHNL0_STTS_WPTR_REG	(FH_MEM_RSCSR_CHNL0)
+
+/**
+ * Physical base address of Rx Buffer Descriptor Circular Buffer.
+ * Bit fields:
+ *  27-0:  RBD CD physical base address [35:8], must be 256-byte aligned.
+ */
+#define FH_RSCSR_CHNL0_RBDCB_BASE_REG	(FH_MEM_RSCSR_CHNL0 + 0x004)
+
+/**
+ * Rx write pointer (index, really!).
+ * Bit fields:
+ *  11-0:  Index of driver's most recent prepared-to-be-filled RBD, + 1.
+ *         NOTE:  For 256-entry circular buffer, use only bits [7:0].
+ */
+#define FH_RSCSR_CHNL0_RBDCB_WPTR_REG	(FH_MEM_RSCSR_CHNL0 + 0x008)
+#define FH_RSCSR_CHNL0_WPTR        (FH_RSCSR_CHNL0_RBDCB_WPTR_REG)
+
+
+/**
+ * Rx Config/Status Registers (RCSR)
+ * Rx Config Reg for channel 0 (only channel used)
+ *
+ * Driver must initialize FH_MEM_RCSR_CHNL0_CONFIG_REG as follows for
+ * normal operation (see bit fields).
+ *
+ * Clearing FH_MEM_RCSR_CHNL0_CONFIG_REG to 0 turns off Rx DMA.
+ * Driver should poll FH_MEM_RSSR_RX_STATUS_REG	for
+ * FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE (bit 24) before continuing.
+ *
+ * Bit fields:
+ * 31-30: Rx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ *        '10' operate normally
+ * 29-24: reserved
+ * 23-20: # RBDs in circular buffer = 2^value; use "8" for 256 RBDs (normal),
+ *        min "5" for 32 RBDs, max "12" for 4096 RBDs.
+ * 19-18: reserved
+ * 17-16: size of each receive buffer; '00' 4K (normal), '01' 8K,
+ *        '10' 12K, '11' 16K.
+ * 15-14: reserved
+ * 13-12: IRQ destination; '00' none, '01' host driver (normal operation)
+ * 11- 4: timeout for closing Rx buffer and interrupting host (units 32 usec)
+ *        typical value 0x10 (about 1/2 msec)
+ *  3- 0: reserved
+ */
+#define FH_MEM_RCSR_LOWER_BOUND      (FH_MEM_LOWER_BOUND + 0xC00)
+#define FH_MEM_RCSR_UPPER_BOUND      (FH_MEM_LOWER_BOUND + 0xCC0)
+#define FH_MEM_RCSR_CHNL0            (FH_MEM_RCSR_LOWER_BOUND)
+
+#define FH_MEM_RCSR_CHNL0_CONFIG_REG	(FH_MEM_RCSR_CHNL0)
+
+#define FH_RCSR_CHNL0_RX_CONFIG_RB_TIMEOUT_MSK (0x00000FF0) /* bits 4-11 */
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_MSK   (0x00001000) /* bits 12 */
+#define FH_RCSR_CHNL0_RX_CONFIG_SINGLE_FRAME_MSK (0x00008000) /* bit 15 */
+#define FH_RCSR_CHNL0_RX_CONFIG_RB_SIZE_MSK   (0x00030000) /* bits 16-17 */
+#define FH_RCSR_CHNL0_RX_CONFIG_RBDBC_SIZE_MSK (0x00F00000) /* bits 20-23 */
+#define FH_RCSR_CHNL0_RX_CONFIG_DMA_CHNL_EN_MSK (0xC0000000) /* bits 30-31*/
+
+#define FH_RCSR_RX_CONFIG_RBDCB_SIZE_POS	(20)
+#define FH_RCSR_RX_CONFIG_REG_IRQ_RBTH_POS	(4)
+#define RX_RB_TIMEOUT	(0x10)
+
+#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_VAL         (0x00000000)
+#define FH_RCSR_RX_CONFIG_CHNL_EN_PAUSE_EOF_VAL     (0x40000000)
+#define FH_RCSR_RX_CONFIG_CHNL_EN_ENABLE_VAL        (0x80000000)
+
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_4K    (0x00000000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_8K    (0x00010000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_12K   (0x00020000)
+#define FH_RCSR_RX_CONFIG_REG_VAL_RB_SIZE_16K   (0x00030000)
+
+#define FH_RCSR_CHNL0_RX_IGNORE_RXF_EMPTY              (0x00000004)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_NO_INT_VAL    (0x00000000)
+#define FH_RCSR_CHNL0_RX_CONFIG_IRQ_DEST_INT_HOST_VAL  (0x00001000)
+
+#define FH_RSCSR_FRAME_SIZE_MSK	(0x00003FFF)	/* bits 0-13 */
+
+/**
+ * Rx Shared Status Registers (RSSR)
+ *
+ * After stopping Rx DMA channel (writing 0 to
+ * FH_MEM_RCSR_CHNL0_CONFIG_REG), driver must poll
+ * FH_MEM_RSSR_RX_STATUS_REG until Rx channel is idle.
+ *
+ * Bit fields:
+ *  24:  1 = Channel 0 is idle
+ *
+ * FH_MEM_RSSR_SHARED_CTRL_REG and FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV
+ * contain default values that should not be altered by the driver.
+ */
+#define FH_MEM_RSSR_LOWER_BOUND           (FH_MEM_LOWER_BOUND + 0xC40)
+#define FH_MEM_RSSR_UPPER_BOUND           (FH_MEM_LOWER_BOUND + 0xD00)
+
+#define FH_MEM_RSSR_SHARED_CTRL_REG       (FH_MEM_RSSR_LOWER_BOUND)
+#define FH_MEM_RSSR_RX_STATUS_REG	(FH_MEM_RSSR_LOWER_BOUND + 0x004)
+#define FH_MEM_RSSR_RX_ENABLE_ERR_IRQ2DRV\
+					(FH_MEM_RSSR_LOWER_BOUND + 0x008)
+
+#define FH_RSSR_CHNL0_RX_STATUS_CHNL_IDLE	(0x01000000)
+
+#define FH_MEM_TFDIB_REG1_ADDR_BITSHIFT	28
+
+/* TFDB  Area - TFDs buffer table */
+#define FH_MEM_TFDIB_DRAM_ADDR_LSB_MSK      (0xFFFFFFFF)
+#define FH_TFDIB_LOWER_BOUND       (FH_MEM_LOWER_BOUND + 0x900)
+#define FH_TFDIB_UPPER_BOUND       (FH_MEM_LOWER_BOUND + 0x958)
+#define FH_TFDIB_CTRL0_REG(_chnl)  (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl))
+#define FH_TFDIB_CTRL1_REG(_chnl)  (FH_TFDIB_LOWER_BOUND + 0x8 * (_chnl) + 0x4)
+
+/**
+ * Transmit DMA Channel Control/Status Registers (TCSR)
+ *
+ * 4965 has one configuration register for each of 8 Tx DMA/FIFO channels
+ * supported in hardware (don't confuse these with the 16 Tx queues in DRAM,
+ * which feed the DMA/FIFO channels); config regs are separated by 0x20 bytes.
+ *
+ * To use a Tx DMA channel, driver must initialize its
+ * FH_TCSR_CHNL_TX_CONFIG_REG(chnl) with:
+ *
+ * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
+ * FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL
+ *
+ * All other bits should be 0.
+ *
+ * Bit fields:
+ * 31-30: Tx DMA channel enable: '00' off/pause, '01' pause at end of frame,
+ *        '10' operate normally
+ * 29- 4: Reserved, set to "0"
+ *     3: Enable internal DMA requests (1, normal operation), disable (0)
+ *  2- 0: Reserved, set to "0"
+ */
+#define FH_TCSR_LOWER_BOUND  (FH_MEM_LOWER_BOUND + 0xD00)
+#define FH_TCSR_UPPER_BOUND  (FH_MEM_LOWER_BOUND + 0xE60)
+
+/* Find Control/Status reg for given Tx DMA/FIFO channel */
+#define FH49_TCSR_CHNL_NUM                            (7)
+#define FH50_TCSR_CHNL_NUM                            (8)
+
+/* TCSR: tx_config register values */
+#define FH_TCSR_CHNL_TX_CONFIG_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl))
+#define FH_TCSR_CHNL_TX_CREDIT_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x4)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG(_chnl)	\
+		(FH_TCSR_LOWER_BOUND + 0x20 * (_chnl) + 0x8)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRV		(0x00000001)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE	(0x00000008)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_NOINT	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_ENDTFD	(0x00100000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD	(0x00200000)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_ENDTFD	(0x00400000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_IFTFD	(0x00800000)
+
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE	(0x00000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE_EOF	(0x40000000)
+#define FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE	(0x80000000)
+
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_EMPTY	(0x00000000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_WAIT	(0x00002000)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID	(0x00000003)
+
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_NUM		(20)
+#define FH_TCSR_CHNL_TX_BUF_STS_REG_POS_TB_IDX		(12)
+
+/**
+ * Tx Shared Status Registers (TSSR)
+ *
+ * After stopping Tx DMA channel (writing 0 to
+ * FH_TCSR_CHNL_TX_CONFIG_REG(chnl)), driver must poll
+ * FH_TSSR_TX_STATUS_REG until selected Tx channel is idle
+ * (channel's buffers empty | no pending requests).
+ *
+ * Bit fields:
+ * 31-24:  1 = Channel buffers empty (channel 7:0)
+ * 23-16:  1 = No pending requests (channel 7:0)
+ */
+#define FH_TSSR_LOWER_BOUND		(FH_MEM_LOWER_BOUND + 0xEA0)
+#define FH_TSSR_UPPER_BOUND		(FH_MEM_LOWER_BOUND + 0xEC0)
+
+#define FH_TSSR_TX_STATUS_REG		(FH_TSSR_LOWER_BOUND + 0x010)
+
+/**
+ * Bit fields for TSSR(Tx Shared Status & Control) error status register:
+ * 31:  Indicates an address error when accessed to internal memory
+ *	uCode/driver must write "1" in order to clear this flag
+ * 30:  Indicates that Host did not send the expected number of dwords to FH
+ *	uCode/driver must write "1" in order to clear this flag
+ * 16-9:Each status bit is for one channel. Indicates that an (Error) ActDMA
+ *	command was received from the scheduler while the TRB was already full
+ *	with previous command
+ *	uCode/driver must write "1" in order to clear this flag
+ * 7-0: Each status bit indicates a channel's TxCredit error. When an error
+ *	bit is set, it indicates that the FH has received a full indication
+ *	from the RTC TxFIFO and the current value of the TxCredit counter was
+ *	not equal to zero. This mean that the credit mechanism was not
+ *	synchronized to the TxFIFO status
+ *	uCode/driver must write "1" in order to clear this flag
+ */
+#define FH_TSSR_TX_ERROR_REG		(FH_TSSR_LOWER_BOUND + 0x018)
+
+#define FH_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_chnl) ((1 << (_chnl)) << 16)
+
+/* Tx service channels */
+#define FH_SRVC_CHNL		(9)
+#define FH_SRVC_LOWER_BOUND	(FH_MEM_LOWER_BOUND + 0x9C8)
+#define FH_SRVC_UPPER_BOUND	(FH_MEM_LOWER_BOUND + 0x9D0)
+#define FH_SRVC_CHNL_SRAM_ADDR_REG(_chnl) \
+		(FH_SRVC_LOWER_BOUND + ((_chnl) - 9) * 0x4)
+
+#define FH_TX_CHICKEN_BITS_REG	(FH_MEM_LOWER_BOUND + 0xE98)
+/* Instruct FH to increment the retry count of a packet when
+ * it is brought from the memory to TX-FIFO
+ */
+#define FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN	(0x00000002)
+
+#define RX_QUEUE_SIZE                         256
+#define RX_QUEUE_MASK                         255
+#define RX_QUEUE_SIZE_LOG                     8
+
+/*
+ * RX related structures and functions
+ */
+#define RX_FREE_BUFFERS 64
+#define RX_LOW_WATERMARK 8
+
+/* Size of one Rx buffer in host DRAM */
+#define IWL_RX_BUF_SIZE_3K (3 * 1000) /* 3945 only */
+#define IWL_RX_BUF_SIZE_4K (4 * 1024)
+#define IWL_RX_BUF_SIZE_8K (8 * 1024)
+
+/**
+ * struct iwl_rb_status - reseve buffer status
+ * 	host memory mapped FH registers
+ * @closed_rb_num [0:11] - Indicates the index of the RB which was closed
+ * @closed_fr_num [0:11] - Indicates the index of the RX Frame which was closed
+ * @finished_rb_num [0:11] - Indicates the index of the current RB
+ * 	in which the last frame was written to
+ * @finished_fr_num [0:11] - Indicates the index of the RX Frame
+ * 	which was transferred
+ */
+struct iwl_rb_status {
+	__le16 closed_rb_num;
+	__le16 closed_fr_num;
+	__le16 finished_rb_num;
+	__le16 finished_fr_nam;
+	__le32 __unused; /* 3945 only */
+} __packed;
+
+
+#define TFD_QUEUE_SIZE_MAX      (256)
+#define TFD_QUEUE_SIZE_BC_DUP	(64)
+#define TFD_QUEUE_BC_SIZE	(TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP)
+#define IWL_TX_DMA_MASK        DMA_BIT_MASK(36)
+#define IWL_NUM_OF_TBS		20
+
+static inline u8 iwl_legacy_get_dma_hi_addr(dma_addr_t addr)
+{
+	return (sizeof(addr) > sizeof(u32) ? (addr >> 16) >> 16 : 0) & 0xF;
+}
+/**
+ * struct iwl_tfd_tb transmit buffer descriptor within transmit frame descriptor
+ *
+ * This structure contains dma address and length of transmission address
+ *
+ * @lo: low [31:0] portion of the dma address of TX buffer
+ * 	every even is unaligned on 16 bit boundary
+ * @hi_n_len 0-3 [35:32] portion of dma
+ *	     4-15 length of the tx buffer
+ */
+struct iwl_tfd_tb {
+	__le32 lo;
+	__le16 hi_n_len;
+} __packed;
+
+/**
+ * struct iwl_tfd
+ *
+ * Transmit Frame Descriptor (TFD)
+ *
+ * @ __reserved1[3] reserved
+ * @ num_tbs 0-4 number of active tbs
+ *	     5   reserved
+ * 	     6-7 padding (not used)
+ * @ tbs[20]	transmit frame buffer descriptors
+ * @ __pad 	padding
+ *
+ * Each Tx queue uses a circular buffer of 256 TFDs stored in host DRAM.
+ * Both driver and device share these circular buffers, each of which must be
+ * contiguous 256 TFDs x 128 bytes-per-TFD = 32 KBytes
+ *
+ * Driver must indicate the physical address of the base of each
+ * circular buffer via the FH_MEM_CBBC_QUEUE registers.
+ *
+ * Each TFD contains pointer/size information for up to 20 data buffers
+ * in host DRAM.  These buffers collectively contain the (one) frame described
+ * by the TFD.  Each buffer must be a single contiguous block of memory within
+ * itself, but buffers may be scattered in host DRAM.  Each buffer has max size
+ * of (4K - 4).  The concatenates all of a TFD's buffers into a single
+ * Tx frame, up to 8 KBytes in size.
+ *
+ * A maximum of 255 (not 256!) TFDs may be on a queue waiting for Tx.
+ */
+struct iwl_tfd {
+	u8 __reserved1[3];
+	u8 num_tbs;
+	struct iwl_tfd_tb tbs[IWL_NUM_OF_TBS];
+	__le32 __pad;
+} __packed;
+
+/* Keep Warm Size */
+#define IWL_KW_SIZE 0x1000	/* 4k */
+
+#endif /* !__iwl_legacy_fh_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-hcmd.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-hcmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-hcmd.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-hcmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,271 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * 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/sched.h>
+#include <net/mac80211.h>
+
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-eeprom.h"
+#include "iwl-core.h"
+
+
+const char *iwl_legacy_get_cmd_string(u8 cmd)
+{
+	switch (cmd) {
+		IWL_CMD(REPLY_ALIVE);
+		IWL_CMD(REPLY_ERROR);
+		IWL_CMD(REPLY_RXON);
+		IWL_CMD(REPLY_RXON_ASSOC);
+		IWL_CMD(REPLY_QOS_PARAM);
+		IWL_CMD(REPLY_RXON_TIMING);
+		IWL_CMD(REPLY_ADD_STA);
+		IWL_CMD(REPLY_REMOVE_STA);
+		IWL_CMD(REPLY_WEPKEY);
+		IWL_CMD(REPLY_3945_RX);
+		IWL_CMD(REPLY_TX);
+		IWL_CMD(REPLY_RATE_SCALE);
+		IWL_CMD(REPLY_LEDS_CMD);
+		IWL_CMD(REPLY_TX_LINK_QUALITY_CMD);
+		IWL_CMD(REPLY_CHANNEL_SWITCH);
+		IWL_CMD(CHANNEL_SWITCH_NOTIFICATION);
+		IWL_CMD(REPLY_SPECTRUM_MEASUREMENT_CMD);
+		IWL_CMD(SPECTRUM_MEASURE_NOTIFICATION);
+		IWL_CMD(POWER_TABLE_CMD);
+		IWL_CMD(PM_SLEEP_NOTIFICATION);
+		IWL_CMD(PM_DEBUG_STATISTIC_NOTIFIC);
+		IWL_CMD(REPLY_SCAN_CMD);
+		IWL_CMD(REPLY_SCAN_ABORT_CMD);
+		IWL_CMD(SCAN_START_NOTIFICATION);
+		IWL_CMD(SCAN_RESULTS_NOTIFICATION);
+		IWL_CMD(SCAN_COMPLETE_NOTIFICATION);
+		IWL_CMD(BEACON_NOTIFICATION);
+		IWL_CMD(REPLY_TX_BEACON);
+		IWL_CMD(REPLY_TX_PWR_TABLE_CMD);
+		IWL_CMD(REPLY_BT_CONFIG);
+		IWL_CMD(REPLY_STATISTICS_CMD);
+		IWL_CMD(STATISTICS_NOTIFICATION);
+		IWL_CMD(CARD_STATE_NOTIFICATION);
+		IWL_CMD(MISSED_BEACONS_NOTIFICATION);
+		IWL_CMD(REPLY_CT_KILL_CONFIG_CMD);
+		IWL_CMD(SENSITIVITY_CMD);
+		IWL_CMD(REPLY_PHY_CALIBRATION_CMD);
+		IWL_CMD(REPLY_RX_PHY_CMD);
+		IWL_CMD(REPLY_RX_MPDU_CMD);
+		IWL_CMD(REPLY_RX);
+		IWL_CMD(REPLY_COMPRESSED_BA);
+	default:
+		return "UNKNOWN";
+
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_get_cmd_string);
+
+#define HOST_COMPLETE_TIMEOUT (HZ / 2)
+
+static void iwl_legacy_generic_cmd_callback(struct iwl_priv *priv,
+				     struct iwl_device_cmd *cmd,
+				     struct iwl_rx_packet *pkt)
+{
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from %s (0x%08X)\n",
+		iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+		return;
+	}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	switch (cmd->hdr.cmd) {
+	case REPLY_TX_LINK_QUALITY_CMD:
+	case SENSITIVITY_CMD:
+		IWL_DEBUG_HC_DUMP(priv, "back from %s (0x%08X)\n",
+		iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+		break;
+	default:
+		IWL_DEBUG_HC(priv, "back from %s (0x%08X)\n",
+		iwl_legacy_get_cmd_string(cmd->hdr.cmd), pkt->hdr.flags);
+	}
+#endif
+}
+
+static int
+iwl_legacy_send_cmd_async(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	int ret;
+
+	BUG_ON(!(cmd->flags & CMD_ASYNC));
+
+	/* An asynchronous command can not expect an SKB to be set. */
+	BUG_ON(cmd->flags & CMD_WANT_SKB);
+
+	/* Assign a generic callback if one is not provided */
+	if (!cmd->callback)
+		cmd->callback = iwl_legacy_generic_cmd_callback;
+
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EBUSY;
+
+	ret = iwl_legacy_enqueue_hcmd(priv, cmd);
+	if (ret < 0) {
+		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+			  iwl_legacy_get_cmd_string(cmd->id), ret);
+		return ret;
+	}
+	return 0;
+}
+
+int iwl_legacy_send_cmd_sync(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	int cmd_idx;
+	int ret;
+
+	BUG_ON(cmd->flags & CMD_ASYNC);
+
+	 /* A synchronous command can not have a callback set. */
+	BUG_ON(cmd->callback);
+
+	IWL_DEBUG_INFO(priv, "Attempting to send sync command %s\n",
+			iwl_legacy_get_cmd_string(cmd->id));
+	mutex_lock(&priv->sync_cmd_mutex);
+
+	set_bit(STATUS_HCMD_ACTIVE, &priv->status);
+	IWL_DEBUG_INFO(priv, "Setting HCMD_ACTIVE for command %s\n",
+			iwl_legacy_get_cmd_string(cmd->id));
+
+	cmd_idx = iwl_legacy_enqueue_hcmd(priv, cmd);
+	if (cmd_idx < 0) {
+		ret = cmd_idx;
+		IWL_ERR(priv, "Error sending %s: enqueue_hcmd failed: %d\n",
+			  iwl_legacy_get_cmd_string(cmd->id), ret);
+		goto out;
+	}
+
+	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
+			!test_bit(STATUS_HCMD_ACTIVE, &priv->status),
+			HOST_COMPLETE_TIMEOUT);
+	if (!ret) {
+		if (test_bit(STATUS_HCMD_ACTIVE, &priv->status)) {
+			IWL_ERR(priv,
+				"Error sending %s: time out after %dms.\n",
+				iwl_legacy_get_cmd_string(cmd->id),
+				jiffies_to_msecs(HOST_COMPLETE_TIMEOUT));
+
+			clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+			IWL_DEBUG_INFO(priv,
+				"Clearing HCMD_ACTIVE for command %s\n",
+				       iwl_legacy_get_cmd_string(cmd->id));
+			ret = -ETIMEDOUT;
+			goto cancel;
+		}
+	}
+
+	if (test_bit(STATUS_RF_KILL_HW, &priv->status)) {
+		IWL_ERR(priv, "Command %s aborted: RF KILL Switch\n",
+			       iwl_legacy_get_cmd_string(cmd->id));
+		ret = -ECANCELED;
+		goto fail;
+	}
+	if (test_bit(STATUS_FW_ERROR, &priv->status)) {
+		IWL_ERR(priv, "Command %s failed: FW Error\n",
+			       iwl_legacy_get_cmd_string(cmd->id));
+		ret = -EIO;
+		goto fail;
+	}
+	if ((cmd->flags & CMD_WANT_SKB) && !cmd->reply_page) {
+		IWL_ERR(priv, "Error: Response NULL in '%s'\n",
+			  iwl_legacy_get_cmd_string(cmd->id));
+		ret = -EIO;
+		goto cancel;
+	}
+
+	ret = 0;
+	goto out;
+
+cancel:
+	if (cmd->flags & CMD_WANT_SKB) {
+		/*
+		 * Cancel the CMD_WANT_SKB flag for the cmd in the
+		 * TX cmd queue. Otherwise in case the cmd comes
+		 * in later, it will possibly set an invalid
+		 * address (cmd->meta.source).
+		 */
+		priv->txq[priv->cmd_queue].meta[cmd_idx].flags &=
+							~CMD_WANT_SKB;
+	}
+fail:
+	if (cmd->reply_page) {
+		iwl_legacy_free_pages(priv, cmd->reply_page);
+		cmd->reply_page = 0;
+	}
+out:
+	mutex_unlock(&priv->sync_cmd_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd_sync);
+
+int iwl_legacy_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	if (cmd->flags & CMD_ASYNC)
+		return iwl_legacy_send_cmd_async(priv, cmd);
+
+	return iwl_legacy_send_cmd_sync(priv, cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd);
+
+int
+iwl_legacy_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
+{
+	struct iwl_host_cmd cmd = {
+		.id = id,
+		.len = len,
+		.data = data,
+	};
+
+	return iwl_legacy_send_cmd_sync(priv, &cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd_pdu);
+
+int iwl_legacy_send_cmd_pdu_async(struct iwl_priv *priv,
+			   u8 id, u16 len, const void *data,
+			   void (*callback)(struct iwl_priv *priv,
+					    struct iwl_device_cmd *cmd,
+					    struct iwl_rx_packet *pkt))
+{
+	struct iwl_host_cmd cmd = {
+		.id = id,
+		.len = len,
+		.data = data,
+	};
+
+	cmd.flags |= CMD_ASYNC;
+	cmd.callback = callback;
+
+	return iwl_legacy_send_cmd_async(priv, &cmd);
+}
+EXPORT_SYMBOL(iwl_legacy_send_cmd_pdu_async);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-helpers.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-helpers.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-helpers.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-helpers.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,181 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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_legacy_helpers_h__
+#define __iwl_legacy_helpers_h__
+
+#include <linux/ctype.h>
+#include <net/mac80211.h>
+
+#include "iwl-io.h"
+
+#define IWL_MASK(lo, hi) ((1 << (hi)) | ((1 << (hi)) - (1 << (lo))))
+
+
+static inline struct ieee80211_conf *iwl_legacy_ieee80211_get_hw_conf(
+	struct ieee80211_hw *hw)
+{
+	return &hw->conf;
+}
+
+/**
+ * iwl_legacy_queue_inc_wrap - increment queue index, wrap back to beginning
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_legacy_queue_inc_wrap(int index, int n_bd)
+{
+	return ++index & (n_bd - 1);
+}
+
+/**
+ * iwl_legacy_queue_dec_wrap - decrement queue index, wrap back to end
+ * @index -- current index
+ * @n_bd -- total number of entries in queue (must be power of 2)
+ */
+static inline int iwl_legacy_queue_dec_wrap(int index, int n_bd)
+{
+	return --index & (n_bd - 1);
+}
+
+/* TODO: Move fw_desc functions to iwl-pci.ko */
+static inline void iwl_legacy_free_fw_desc(struct pci_dev *pci_dev,
+				    struct fw_desc *desc)
+{
+	if (desc->v_addr)
+		dma_free_coherent(&pci_dev->dev, desc->len,
+				  desc->v_addr, desc->p_addr);
+	desc->v_addr = NULL;
+	desc->len = 0;
+}
+
+static inline int iwl_legacy_alloc_fw_desc(struct pci_dev *pci_dev,
+				    struct fw_desc *desc)
+{
+	if (!desc->len) {
+		desc->v_addr = NULL;
+		return -EINVAL;
+	}
+
+	desc->v_addr = dma_alloc_coherent(&pci_dev->dev, desc->len,
+					  &desc->p_addr, GFP_KERNEL);
+	return (desc->v_addr != NULL) ? 0 : -ENOMEM;
+}
+
+/*
+ * we have 8 bits used like this:
+ *
+ * 7 6 5 4 3 2 1 0
+ * | | | | | | | |
+ * | | | | | | +-+-------- AC queue (0-3)
+ * | | | | | |
+ * | +-+-+-+-+------------ HW queue ID
+ * |
+ * +---------------------- unused
+ */
+static inline void
+iwl_legacy_set_swq_id(struct iwl_tx_queue *txq, u8 ac, u8 hwq)
+{
+	BUG_ON(ac > 3);   /* only have 2 bits */
+	BUG_ON(hwq > 31); /* only use 5 bits */
+
+	txq->swq_id = (hwq << 2) | ac;
+}
+
+static inline void iwl_legacy_wake_queue(struct iwl_priv *priv,
+				  struct iwl_tx_queue *txq)
+{
+	u8 queue = txq->swq_id;
+	u8 ac = queue & 3;
+	u8 hwq = (queue >> 2) & 0x1f;
+
+	if (test_and_clear_bit(hwq, priv->queue_stopped))
+		if (atomic_dec_return(&priv->queue_stop_count[ac]) <= 0)
+			ieee80211_wake_queue(priv->hw, ac);
+}
+
+static inline void iwl_legacy_stop_queue(struct iwl_priv *priv,
+				  struct iwl_tx_queue *txq)
+{
+	u8 queue = txq->swq_id;
+	u8 ac = queue & 3;
+	u8 hwq = (queue >> 2) & 0x1f;
+
+	if (!test_and_set_bit(hwq, priv->queue_stopped))
+		if (atomic_inc_return(&priv->queue_stop_count[ac]) > 0)
+			ieee80211_stop_queue(priv->hw, ac);
+}
+
+#define ieee80211_stop_queue DO_NOT_USE_ieee80211_stop_queue
+#define ieee80211_wake_queue DO_NOT_USE_ieee80211_wake_queue
+
+static inline void iwl_legacy_disable_interrupts(struct iwl_priv *priv)
+{
+	clear_bit(STATUS_INT_ENABLED, &priv->status);
+
+	/* disable interrupts from uCode/NIC to host */
+	iwl_write32(priv, CSR_INT_MASK, 0x00000000);
+
+	/* acknowledge/clear/reset any interrupts still pending
+	 * from uCode or flow handler (Rx/Tx DMA) */
+	iwl_write32(priv, CSR_INT, 0xffffffff);
+	iwl_write32(priv, CSR_FH_INT_STATUS, 0xffffffff);
+	IWL_DEBUG_ISR(priv, "Disabled interrupts\n");
+}
+
+static inline void iwl_legacy_enable_interrupts(struct iwl_priv *priv)
+{
+	IWL_DEBUG_ISR(priv, "Enabling interrupts\n");
+	set_bit(STATUS_INT_ENABLED, &priv->status);
+	iwl_write32(priv, CSR_INT_MASK, priv->inta_mask);
+}
+
+/**
+ * iwl_legacy_beacon_time_mask_low - mask of lower 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_legacy_beacon_time_mask_low(struct iwl_priv *priv,
+					   u16 tsf_bits)
+{
+	return (1 << tsf_bits) - 1;
+}
+
+/**
+ * iwl_legacy_beacon_time_mask_high - mask of higher 32 bit of beacon time
+ * @priv -- pointer to iwl_priv data structure
+ * @tsf_bits -- number of bits need to shift for masking)
+ */
+static inline u32 iwl_legacy_beacon_time_mask_high(struct iwl_priv *priv,
+					    u16 tsf_bits)
+{
+	return ((1 << (32 - tsf_bits)) - 1) << tsf_bits;
+}
+
+#endif				/* __iwl_legacy_helpers_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-io.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-io.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-io.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-io.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,545 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from the ipw3945 project.
+ *
+ * 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_legacy_io_h__
+#define __iwl_legacy_io_h__
+
+#include <linux/io.h>
+
+#include "iwl-dev.h"
+#include "iwl-debug.h"
+#include "iwl-devtrace.h"
+
+/*
+ * IO, register, and NIC memory access functions
+ *
+ * NOTE on naming convention and macro usage for these
+ *
+ * A single _ prefix before a an access function means that no state
+ * check or debug information is printed when that function is called.
+ *
+ * A double __ prefix before an access function means that state is checked
+ * and the current line number and caller function name are printed in addition
+ * to any other debug output.
+ *
+ * The non-prefixed name is the #define that maps the caller into a
+ * #define that provides the caller's name and __LINE__ to the double
+ * prefix version.
+ *
+ * If you wish to call the function without any debug or state checking,
+ * you should use the single _ prefix version (as is used by dependent IO
+ * routines, for example _iwl_legacy_read_direct32 calls the non-check version of
+ * _iwl_legacy_read32.)
+ *
+ * These declarations are *extremely* useful in quickly isolating code deltas
+ * which result in misconfiguration of the hardware I/O.  In combination with
+ * git-bisect and the IO debug level you can quickly determine the specific
+ * commit which breaks the IO sequence to the hardware.
+ *
+ */
+
+static inline void _iwl_legacy_write8(struct iwl_priv *priv, u32 ofs, u8 val)
+{
+	trace_iwlwifi_legacy_dev_iowrite8(priv, ofs, val);
+	iowrite8(val, priv->hw_base + ofs);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void
+__iwl_legacy_write8(const char *f, u32 l, struct iwl_priv *priv,
+				 u32 ofs, u8 val)
+{
+	IWL_DEBUG_IO(priv, "write8(0x%08X, 0x%02X) - %s %d\n", ofs, val, f, l);
+	_iwl_legacy_write8(priv, ofs, val);
+}
+#define iwl_write8(priv, ofs, val) \
+	__iwl_legacy_write8(__FILE__, __LINE__, priv, ofs, val)
+#else
+#define iwl_write8(priv, ofs, val) _iwl_legacy_write8(priv, ofs, val)
+#endif
+
+
+static inline void _iwl_legacy_write32(struct iwl_priv *priv, u32 ofs, u32 val)
+{
+	trace_iwlwifi_legacy_dev_iowrite32(priv, ofs, val);
+	iowrite32(val, priv->hw_base + ofs);
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void
+__iwl_legacy_write32(const char *f, u32 l, struct iwl_priv *priv,
+				 u32 ofs, u32 val)
+{
+	IWL_DEBUG_IO(priv, "write32(0x%08X, 0x%08X) - %s %d\n", ofs, val, f, l);
+	_iwl_legacy_write32(priv, ofs, val);
+}
+#define iwl_write32(priv, ofs, val) \
+	__iwl_legacy_write32(__FILE__, __LINE__, priv, ofs, val)
+#else
+#define iwl_write32(priv, ofs, val) _iwl_legacy_write32(priv, ofs, val)
+#endif
+
+static inline u32 _iwl_legacy_read32(struct iwl_priv *priv, u32 ofs)
+{
+	u32 val = ioread32(priv->hw_base + ofs);
+	trace_iwlwifi_legacy_dev_ioread32(priv, ofs, val);
+	return val;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline u32
+__iwl_legacy_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs)
+{
+	IWL_DEBUG_IO(priv, "read_direct32(0x%08X) - %s %d\n", ofs, f, l);
+	return _iwl_legacy_read32(priv, ofs);
+}
+#define iwl_read32(priv, ofs) __iwl_legacy_read32(__FILE__, __LINE__, priv, ofs)
+#else
+#define iwl_read32(p, o) _iwl_legacy_read32(p, o)
+#endif
+
+#define IWL_POLL_INTERVAL 10	/* microseconds */
+static inline int
+_iwl_legacy_poll_bit(struct iwl_priv *priv, u32 addr,
+				u32 bits, u32 mask, int timeout)
+{
+	int t = 0;
+
+	do {
+		if ((_iwl_legacy_read32(priv, addr) & mask) == (bits & mask))
+			return t;
+		udelay(IWL_POLL_INTERVAL);
+		t += IWL_POLL_INTERVAL;
+	} while (t < timeout);
+
+	return -ETIMEDOUT;
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline int __iwl_legacy_poll_bit(const char *f, u32 l,
+				 struct iwl_priv *priv, u32 addr,
+				 u32 bits, u32 mask, int timeout)
+{
+	int ret = _iwl_legacy_poll_bit(priv, addr, bits, mask, timeout);
+	IWL_DEBUG_IO(priv, "poll_bit(0x%08X, 0x%08X, 0x%08X) - %s- %s %d\n",
+		     addr, bits, mask,
+		     unlikely(ret  == -ETIMEDOUT) ? "timeout" : "", f, l);
+	return ret;
+}
+#define iwl_poll_bit(priv, addr, bits, mask, timeout) \
+	__iwl_legacy_poll_bit(__FILE__, __LINE__, priv, addr, \
+	bits, mask, timeout)
+#else
+#define iwl_poll_bit(p, a, b, m, t) _iwl_legacy_poll_bit(p, a, b, m, t)
+#endif
+
+static inline void _iwl_legacy_set_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	_iwl_legacy_write32(priv, reg, _iwl_legacy_read32(priv, reg) | mask);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void __iwl_legacy_set_bit(const char *f, u32 l,
+				 struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	u32 val = _iwl_legacy_read32(priv, reg) | mask;
+	IWL_DEBUG_IO(priv, "set_bit(0x%08X, 0x%08X) = 0x%08X\n", reg,
+							mask, val);
+	_iwl_legacy_write32(priv, reg, val);
+}
+static inline void iwl_legacy_set_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	__iwl_legacy_set_bit(__FILE__, __LINE__, p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#else
+static inline void iwl_legacy_set_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	_iwl_legacy_set_bit(p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#endif
+
+static inline void
+_iwl_legacy_clear_bit(struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	_iwl_legacy_write32(priv, reg, _iwl_legacy_read32(priv, reg) & ~mask);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void
+__iwl_legacy_clear_bit(const char *f, u32 l,
+				   struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	u32 val = _iwl_legacy_read32(priv, reg) & ~mask;
+	IWL_DEBUG_IO(priv, "clear_bit(0x%08X, 0x%08X) = 0x%08X\n", reg, mask, val);
+	_iwl_legacy_write32(priv, reg, val);
+}
+static inline void iwl_legacy_clear_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	__iwl_legacy_clear_bit(__FILE__, __LINE__, p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#else
+static inline void iwl_legacy_clear_bit(struct iwl_priv *p, u32 r, u32 m)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&p->reg_lock, reg_flags);
+	_iwl_legacy_clear_bit(p, r, m);
+	spin_unlock_irqrestore(&p->reg_lock, reg_flags);
+}
+#endif
+
+static inline int _iwl_legacy_grab_nic_access(struct iwl_priv *priv)
+{
+	int ret;
+	u32 val;
+
+	/* this bit wakes up the NIC */
+	_iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+
+	/*
+	 * These bits say the device is running, and should keep running for
+	 * at least a short while (at least as long as MAC_ACCESS_REQ stays 1),
+	 * but they do not indicate that embedded SRAM is restored yet;
+	 * 3945 and 4965 have volatile SRAM, and must save/restore contents
+	 * to/from host DRAM when sleeping/waking for power-saving.
+	 * Each direction takes approximately 1/4 millisecond; with this
+	 * overhead, it's a good idea to grab and hold MAC_ACCESS_REQUEST if a
+	 * series of register accesses are expected (e.g. reading Event Log),
+	 * to keep device from sleeping.
+	 *
+	 * CSR_UCODE_DRV_GP1 register bit MAC_SLEEP == 0 indicates that
+	 * SRAM is okay/restored.  We don't check that here because this call
+	 * is just for hardware register access; but GP1 MAC_SLEEP check is a
+	 * good idea before accessing 3945/4965 SRAM (e.g. reading Event Log).
+	 *
+	 */
+	ret = _iwl_legacy_poll_bit(priv, CSR_GP_CNTRL,
+			   CSR_GP_CNTRL_REG_VAL_MAC_ACCESS_EN,
+			   (CSR_GP_CNTRL_REG_FLAG_MAC_CLOCK_READY |
+			    CSR_GP_CNTRL_REG_FLAG_GOING_TO_SLEEP), 15000);
+	if (ret < 0) {
+		val = _iwl_legacy_read32(priv, CSR_GP_CNTRL);
+		IWL_ERR(priv,
+			"MAC is in deep sleep!.  CSR_GP_CNTRL = 0x%08X\n", val);
+		_iwl_legacy_write32(priv, CSR_RESET,
+				CSR_RESET_REG_FLAG_FORCE_NMI);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline int __iwl_legacy_grab_nic_access(const char *f, u32 l,
+					       struct iwl_priv *priv)
+{
+	IWL_DEBUG_IO(priv, "grabbing nic access - %s %d\n", f, l);
+	return _iwl_legacy_grab_nic_access(priv);
+}
+#define iwl_grab_nic_access(priv) \
+	__iwl_legacy_grab_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl_grab_nic_access(priv) \
+	_iwl_legacy_grab_nic_access(priv)
+#endif
+
+static inline void _iwl_legacy_release_nic_access(struct iwl_priv *priv)
+{
+	_iwl_legacy_clear_bit(priv, CSR_GP_CNTRL,
+			CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline void __iwl_legacy_release_nic_access(const char *f, u32 l,
+					    struct iwl_priv *priv)
+{
+
+	IWL_DEBUG_IO(priv, "releasing nic access - %s %d\n", f, l);
+	_iwl_legacy_release_nic_access(priv);
+}
+#define iwl_release_nic_access(priv) \
+	__iwl_legacy_release_nic_access(__FILE__, __LINE__, priv)
+#else
+#define iwl_release_nic_access(priv) \
+	_iwl_legacy_release_nic_access(priv)
+#endif
+
+static inline u32 _iwl_legacy_read_direct32(struct iwl_priv *priv, u32 reg)
+{
+	return _iwl_legacy_read32(priv, reg);
+}
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline u32 __iwl_legacy_read_direct32(const char *f, u32 l,
+					struct iwl_priv *priv, u32 reg)
+{
+	u32 value = _iwl_legacy_read_direct32(priv, reg);
+	IWL_DEBUG_IO(priv,
+			"read_direct32(0x%4X) = 0x%08x - %s %d\n", reg, value,
+		     f, l);
+	return value;
+}
+static inline u32 iwl_legacy_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_legacy_read_direct32(__FILE__, __LINE__, priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+}
+
+#else
+static inline u32 iwl_legacy_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_legacy_read_direct32(priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return value;
+
+}
+#endif
+
+static inline void _iwl_legacy_write_direct32(struct iwl_priv *priv,
+					 u32 reg, u32 value)
+{
+	_iwl_legacy_write32(priv, reg, value);
+}
+static inline void
+iwl_legacy_write_direct32(struct iwl_priv *priv, u32 reg, u32 value)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_direct32(priv, reg, value);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline void iwl_legacy_write_reg_buf(struct iwl_priv *priv,
+					       u32 reg, u32 len, u32 *values)
+{
+	u32 count = sizeof(u32);
+
+	if ((priv != NULL) && (values != NULL)) {
+		for (; 0 < len; len -= count, reg += count, values++)
+			iwl_legacy_write_direct32(priv, reg, *values);
+	}
+}
+
+static inline int _iwl_legacy_poll_direct_bit(struct iwl_priv *priv, u32 addr,
+				       u32 mask, int timeout)
+{
+	int t = 0;
+
+	do {
+		if ((iwl_legacy_read_direct32(priv, addr) & mask) == mask)
+			return t;
+		udelay(IWL_POLL_INTERVAL);
+		t += IWL_POLL_INTERVAL;
+	} while (t < timeout);
+
+	return -ETIMEDOUT;
+}
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static inline int __iwl_legacy_poll_direct_bit(const char *f, u32 l,
+					    struct iwl_priv *priv,
+					    u32 addr, u32 mask, int timeout)
+{
+	int ret  = _iwl_legacy_poll_direct_bit(priv, addr, mask, timeout);
+
+	if (unlikely(ret == -ETIMEDOUT))
+		IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) - "
+			     "timedout - %s %d\n", addr, mask, f, l);
+	else
+		IWL_DEBUG_IO(priv, "poll_direct_bit(0x%08X, 0x%08X) = 0x%08X "
+			     "- %s %d\n", addr, mask, ret, f, l);
+	return ret;
+}
+#define iwl_poll_direct_bit(priv, addr, mask, timeout) \
+__iwl_legacy_poll_direct_bit(__FILE__, __LINE__, priv, addr, mask, timeout)
+#else
+#define iwl_poll_direct_bit _iwl_legacy_poll_direct_bit
+#endif
+
+static inline u32 _iwl_legacy_read_prph(struct iwl_priv *priv, u32 reg)
+{
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_RADDR, reg | (3 << 24));
+	rmb();
+	return _iwl_legacy_read_direct32(priv, HBUS_TARG_PRPH_RDAT);
+}
+static inline u32 iwl_legacy_read_prph(struct iwl_priv *priv, u32 reg)
+{
+	unsigned long reg_flags;
+	u32 val;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	val = _iwl_legacy_read_prph(priv, reg);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+	return val;
+}
+
+static inline void _iwl_legacy_write_prph(struct iwl_priv *priv,
+					     u32 addr, u32 val)
+{
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_WADDR,
+			      ((addr & 0x0000FFFF) | (3 << 24)));
+	wmb();
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_PRPH_WDAT, val);
+}
+
+static inline void
+iwl_legacy_write_prph(struct iwl_priv *priv, u32 addr, u32 val)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_prph(priv, addr, val);
+		iwl_release_nic_access(priv);
+	}
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+#define _iwl_legacy_set_bits_prph(priv, reg, mask) \
+_iwl_legacy_write_prph(priv, reg, (_iwl_legacy_read_prph(priv, reg) | mask))
+
+static inline void
+iwl_legacy_set_bits_prph(struct iwl_priv *priv, u32 reg, u32 mask)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	_iwl_legacy_set_bits_prph(priv, reg, mask);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+#define _iwl_legacy_set_bits_mask_prph(priv, reg, bits, mask) \
+_iwl_legacy_write_prph(priv, reg,				\
+		 ((_iwl_legacy_read_prph(priv, reg) & mask) | bits))
+
+static inline void iwl_legacy_set_bits_mask_prph(struct iwl_priv *priv, u32 reg,
+				u32 bits, u32 mask)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	_iwl_legacy_set_bits_mask_prph(priv, reg, bits, mask);
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline void iwl_legacy_clear_bits_prph(struct iwl_priv
+						 *priv, u32 reg, u32 mask)
+{
+	unsigned long reg_flags;
+	u32 val;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+	val = _iwl_legacy_read_prph(priv, reg);
+	_iwl_legacy_write_prph(priv, reg, (val & ~mask));
+	iwl_release_nic_access(priv);
+	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
+}
+
+static inline u32 iwl_legacy_read_targ_mem(struct iwl_priv *priv, u32 addr)
+{
+	unsigned long reg_flags;
+	u32 value;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	iwl_grab_nic_access(priv);
+
+	_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_RADDR, addr);
+	rmb();
+	value = _iwl_legacy_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_legacy_write_targ_mem(struct iwl_priv *priv, u32 addr, u32 val)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+		wmb();
+		_iwl_legacy_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_legacy_write_targ_mem_buf(struct iwl_priv *priv, u32 addr,
+					  u32 len, u32 *values)
+{
+	unsigned long reg_flags;
+
+	spin_lock_irqsave(&priv->reg_lock, reg_flags);
+	if (!iwl_grab_nic_access(priv)) {
+		_iwl_legacy_write_direct32(priv, HBUS_TARG_MEM_WADDR, addr);
+		wmb();
+		for (; 0 < len; len -= sizeof(u32), values++)
+			_iwl_legacy_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.38-gnu/drivers/net/wireless/iwlegacy/iwl-led.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-led.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,206 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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 <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+
+/* default: IWL_LED_BLINK(0) using blinking index table */
+static int led_mode;
+module_param(led_mode, int, S_IRUGO);
+MODULE_PARM_DESC(led_mode, "0=system default, "
+		"1=On(RF On)/Off(RF Off), 2=blinking");
+
+/* Throughput		OFF time(ms)	ON time (ms)
+ *	>300			25		25
+ *	>200 to 300		40		40
+ *	>100 to 200		55		55
+ *	>70 to 100		65		65
+ *	>50 to 70		75		75
+ *	>20 to 50		85		85
+ *	>10 to 20		95		95
+ *	>5 to 10		110		110
+ *	>1 to 5			130		130
+ *	>0 to 1			167		167
+ *	<=0					SOLID ON
+ */
+static const struct ieee80211_tpt_blink iwl_blink[] = {
+	{ .throughput = 0, .blink_time = 334 },
+	{ .throughput = 1 * 1024 - 1, .blink_time = 260 },
+	{ .throughput = 5 * 1024 - 1, .blink_time = 220 },
+	{ .throughput = 10 * 1024 - 1, .blink_time = 190 },
+	{ .throughput = 20 * 1024 - 1, .blink_time = 170 },
+	{ .throughput = 50 * 1024 - 1, .blink_time = 150 },
+	{ .throughput = 70 * 1024 - 1, .blink_time = 130 },
+	{ .throughput = 100 * 1024 - 1, .blink_time = 110 },
+	{ .throughput = 200 * 1024 - 1, .blink_time = 80 },
+	{ .throughput = 300 * 1024 - 1, .blink_time = 50 },
+};
+
+/*
+ * Adjust led blink rate to compensate on a MAC Clock difference on every HW
+ * Led blink rate analysis showed an average deviation of 0% on 3945,
+ * 5% on 4965 HW.
+ * Need to compensate on the led on/off time per HW according to the deviation
+ * to achieve the desired led frequency
+ * The calculation is: (100-averageDeviation)/100 * blinkTime
+ * For code efficiency the calculation will be:
+ *     compensation = (100 - averageDeviation) * 64 / 100
+ *     NewBlinkTime = (compensation * BlinkTime) / 64
+ */
+static inline u8 iwl_legacy_blink_compensation(struct iwl_priv *priv,
+				    u8 time, u16 compensation)
+{
+	if (!compensation) {
+		IWL_ERR(priv, "undefined blink compensation: "
+			"use pre-defined blinking time\n");
+		return time;
+	}
+
+	return (u8)((time * compensation) >> 6);
+}
+
+/* Set led pattern command */
+static int iwl_legacy_led_cmd(struct iwl_priv *priv,
+		       unsigned long on,
+		       unsigned long off)
+{
+	struct iwl_led_cmd led_cmd = {
+		.id = IWL_LED_LINK,
+		.interval = IWL_DEF_LED_INTRVL
+	};
+	int ret;
+
+	if (!test_bit(STATUS_READY, &priv->status))
+		return -EBUSY;
+
+	if (priv->blink_on == on && priv->blink_off == off)
+		return 0;
+
+	if (off == 0) {
+		/* led is SOLID_ON */
+		on = IWL_LED_SOLID;
+	}
+
+	IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
+			priv->cfg->base_params->led_compensation);
+	led_cmd.on = iwl_legacy_blink_compensation(priv, on,
+				priv->cfg->base_params->led_compensation);
+	led_cmd.off = iwl_legacy_blink_compensation(priv, off,
+				priv->cfg->base_params->led_compensation);
+
+	ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
+	if (!ret) {
+		priv->blink_on = on;
+		priv->blink_off = off;
+	}
+	return ret;
+}
+
+static void iwl_legacy_led_brightness_set(struct led_classdev *led_cdev,
+				   enum led_brightness brightness)
+{
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
+	unsigned long on = 0;
+
+	if (brightness > 0)
+		on = IWL_LED_SOLID;
+
+	iwl_legacy_led_cmd(priv, on, 0);
+}
+
+static int iwl_legacy_led_blink_set(struct led_classdev *led_cdev,
+			     unsigned long *delay_on,
+			     unsigned long *delay_off)
+{
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
+
+	return iwl_legacy_led_cmd(priv, *delay_on, *delay_off);
+}
+
+void iwl_legacy_leds_init(struct iwl_priv *priv)
+{
+	int mode = led_mode;
+	int ret;
+
+	if (mode == IWL_LED_DEFAULT)
+		mode = priv->cfg->led_mode;
+
+	priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
+				   wiphy_name(priv->hw->wiphy));
+	priv->led.brightness_set = iwl_legacy_led_brightness_set;
+	priv->led.blink_set = iwl_legacy_led_blink_set;
+	priv->led.max_brightness = 1;
+
+	switch (mode) {
+	case IWL_LED_DEFAULT:
+		WARN_ON(1);
+		break;
+	case IWL_LED_BLINK:
+		priv->led.default_trigger =
+			ieee80211_create_tpt_led_trigger(priv->hw,
+					IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
+					iwl_blink, ARRAY_SIZE(iwl_blink));
+		break;
+	case IWL_LED_RF_STATE:
+		priv->led.default_trigger =
+			ieee80211_get_radio_led_name(priv->hw);
+		break;
+	}
+
+	ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+	if (ret) {
+		kfree(priv->led.name);
+		return;
+	}
+
+	priv->led_registered = true;
+}
+EXPORT_SYMBOL(iwl_legacy_leds_init);
+
+void iwl_legacy_leds_exit(struct iwl_priv *priv)
+{
+	if (!priv->led_registered)
+		return;
+
+	led_classdev_unregister(&priv->led);
+	kfree(priv->led.name);
+}
+EXPORT_SYMBOL(iwl_legacy_leds_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-led.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-led.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-led.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,56 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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_legacy_leds_h__
+#define __iwl_legacy_leds_h__
+
+
+struct iwl_priv;
+
+#define IWL_LED_SOLID 11
+#define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
+
+#define IWL_LED_ACTIVITY       (0<<1)
+#define IWL_LED_LINK           (1<<1)
+
+/*
+ * LED mode
+ *    IWL_LED_DEFAULT:  use device default
+ *    IWL_LED_RF_STATE: turn LED on/off based on RF state
+ *			LED ON  = RF ON
+ *			LED OFF = RF OFF
+ *    IWL_LED_BLINK:    adjust led blink rate based on blink table
+ */
+enum iwl_led_mode {
+	IWL_LED_DEFAULT,
+	IWL_LED_RF_STATE,
+	IWL_LED_BLINK,
+};
+
+void iwl_legacy_leds_init(struct iwl_priv *priv);
+void iwl_legacy_leds_exit(struct iwl_priv *priv);
+
+#endif /* __iwl_legacy_leds_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-legacy-rs.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,456 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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_legacy_rs_h__
+#define __iwl_legacy_rs_h__
+
+struct iwl_rate_info {
+	u8 plcp;	/* uCode API:  IWL_RATE_6M_PLCP, etc. */
+	u8 plcp_siso;	/* uCode API:  IWL_RATE_SISO_6M_PLCP, etc. */
+	u8 plcp_mimo2;	/* uCode API:  IWL_RATE_MIMO2_6M_PLCP, etc. */
+	u8 ieee;	/* MAC header:  IWL_RATE_6M_IEEE, etc. */
+	u8 prev_ieee;    /* previous rate in IEEE speeds */
+	u8 next_ieee;    /* next rate in IEEE speeds */
+	u8 prev_rs;      /* previous rate used in rs algo */
+	u8 next_rs;      /* next rate used in rs algo */
+	u8 prev_rs_tgg;  /* previous rate used in TGG rs algo */
+	u8 next_rs_tgg;  /* next rate used in TGG rs algo */
+};
+
+struct iwl3945_rate_info {
+	u8 plcp;		/* uCode API:  IWL_RATE_6M_PLCP, etc. */
+	u8 ieee;		/* MAC header:  IWL_RATE_6M_IEEE, etc. */
+	u8 prev_ieee;		/* previous rate in IEEE speeds */
+	u8 next_ieee;		/* next rate in IEEE speeds */
+	u8 prev_rs;		/* previous rate used in rs algo */
+	u8 next_rs;		/* next rate used in rs algo */
+	u8 prev_rs_tgg;		/* previous rate used in TGG rs algo */
+	u8 next_rs_tgg;		/* next rate used in TGG rs algo */
+	u8 table_rs_index;	/* index in rate scale table cmd */
+	u8 prev_table_rs;	/* prev in rate table cmd */
+};
+
+
+/*
+ * These serve as indexes into
+ * struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT];
+ */
+enum {
+	IWL_RATE_1M_INDEX = 0,
+	IWL_RATE_2M_INDEX,
+	IWL_RATE_5M_INDEX,
+	IWL_RATE_11M_INDEX,
+	IWL_RATE_6M_INDEX,
+	IWL_RATE_9M_INDEX,
+	IWL_RATE_12M_INDEX,
+	IWL_RATE_18M_INDEX,
+	IWL_RATE_24M_INDEX,
+	IWL_RATE_36M_INDEX,
+	IWL_RATE_48M_INDEX,
+	IWL_RATE_54M_INDEX,
+	IWL_RATE_60M_INDEX,
+	IWL_RATE_COUNT,
+	IWL_RATE_COUNT_LEGACY = IWL_RATE_COUNT - 1,	/* Excluding 60M */
+	IWL_RATE_COUNT_3945 = IWL_RATE_COUNT - 1,
+	IWL_RATE_INVM_INDEX = IWL_RATE_COUNT,
+	IWL_RATE_INVALID = IWL_RATE_COUNT,
+};
+
+enum {
+	IWL_RATE_6M_INDEX_TABLE = 0,
+	IWL_RATE_9M_INDEX_TABLE,
+	IWL_RATE_12M_INDEX_TABLE,
+	IWL_RATE_18M_INDEX_TABLE,
+	IWL_RATE_24M_INDEX_TABLE,
+	IWL_RATE_36M_INDEX_TABLE,
+	IWL_RATE_48M_INDEX_TABLE,
+	IWL_RATE_54M_INDEX_TABLE,
+	IWL_RATE_1M_INDEX_TABLE,
+	IWL_RATE_2M_INDEX_TABLE,
+	IWL_RATE_5M_INDEX_TABLE,
+	IWL_RATE_11M_INDEX_TABLE,
+	IWL_RATE_INVM_INDEX_TABLE = IWL_RATE_INVM_INDEX - 1,
+};
+
+enum {
+	IWL_FIRST_OFDM_RATE = IWL_RATE_6M_INDEX,
+	IWL39_LAST_OFDM_RATE = IWL_RATE_54M_INDEX,
+	IWL_LAST_OFDM_RATE = IWL_RATE_60M_INDEX,
+	IWL_FIRST_CCK_RATE = IWL_RATE_1M_INDEX,
+	IWL_LAST_CCK_RATE = IWL_RATE_11M_INDEX,
+};
+
+/* #define vs. enum to keep from defaulting to 'large integer' */
+#define	IWL_RATE_6M_MASK   (1 << IWL_RATE_6M_INDEX)
+#define	IWL_RATE_9M_MASK   (1 << IWL_RATE_9M_INDEX)
+#define	IWL_RATE_12M_MASK  (1 << IWL_RATE_12M_INDEX)
+#define	IWL_RATE_18M_MASK  (1 << IWL_RATE_18M_INDEX)
+#define	IWL_RATE_24M_MASK  (1 << IWL_RATE_24M_INDEX)
+#define	IWL_RATE_36M_MASK  (1 << IWL_RATE_36M_INDEX)
+#define	IWL_RATE_48M_MASK  (1 << IWL_RATE_48M_INDEX)
+#define	IWL_RATE_54M_MASK  (1 << IWL_RATE_54M_INDEX)
+#define IWL_RATE_60M_MASK  (1 << IWL_RATE_60M_INDEX)
+#define	IWL_RATE_1M_MASK   (1 << IWL_RATE_1M_INDEX)
+#define	IWL_RATE_2M_MASK   (1 << IWL_RATE_2M_INDEX)
+#define	IWL_RATE_5M_MASK   (1 << IWL_RATE_5M_INDEX)
+#define	IWL_RATE_11M_MASK  (1 << IWL_RATE_11M_INDEX)
+
+/* uCode API values for legacy bit rates, both OFDM and CCK */
+enum {
+	IWL_RATE_6M_PLCP  = 13,
+	IWL_RATE_9M_PLCP  = 15,
+	IWL_RATE_12M_PLCP = 5,
+	IWL_RATE_18M_PLCP = 7,
+	IWL_RATE_24M_PLCP = 9,
+	IWL_RATE_36M_PLCP = 11,
+	IWL_RATE_48M_PLCP = 1,
+	IWL_RATE_54M_PLCP = 3,
+	IWL_RATE_60M_PLCP = 3,/*FIXME:RS:should be removed*/
+	IWL_RATE_1M_PLCP  = 10,
+	IWL_RATE_2M_PLCP  = 20,
+	IWL_RATE_5M_PLCP  = 55,
+	IWL_RATE_11M_PLCP = 110,
+	/*FIXME:RS:add IWL_RATE_LEGACY_INVM_PLCP = 0,*/
+};
+
+/* uCode API values for OFDM high-throughput (HT) bit rates */
+enum {
+	IWL_RATE_SISO_6M_PLCP = 0,
+	IWL_RATE_SISO_12M_PLCP = 1,
+	IWL_RATE_SISO_18M_PLCP = 2,
+	IWL_RATE_SISO_24M_PLCP = 3,
+	IWL_RATE_SISO_36M_PLCP = 4,
+	IWL_RATE_SISO_48M_PLCP = 5,
+	IWL_RATE_SISO_54M_PLCP = 6,
+	IWL_RATE_SISO_60M_PLCP = 7,
+	IWL_RATE_MIMO2_6M_PLCP  = 0x8,
+	IWL_RATE_MIMO2_12M_PLCP = 0x9,
+	IWL_RATE_MIMO2_18M_PLCP = 0xa,
+	IWL_RATE_MIMO2_24M_PLCP = 0xb,
+	IWL_RATE_MIMO2_36M_PLCP = 0xc,
+	IWL_RATE_MIMO2_48M_PLCP = 0xd,
+	IWL_RATE_MIMO2_54M_PLCP = 0xe,
+	IWL_RATE_MIMO2_60M_PLCP = 0xf,
+	IWL_RATE_SISO_INVM_PLCP,
+	IWL_RATE_MIMO2_INVM_PLCP = IWL_RATE_SISO_INVM_PLCP,
+};
+
+/* MAC header values for bit rates */
+enum {
+	IWL_RATE_6M_IEEE  = 12,
+	IWL_RATE_9M_IEEE  = 18,
+	IWL_RATE_12M_IEEE = 24,
+	IWL_RATE_18M_IEEE = 36,
+	IWL_RATE_24M_IEEE = 48,
+	IWL_RATE_36M_IEEE = 72,
+	IWL_RATE_48M_IEEE = 96,
+	IWL_RATE_54M_IEEE = 108,
+	IWL_RATE_60M_IEEE = 120,
+	IWL_RATE_1M_IEEE  = 2,
+	IWL_RATE_2M_IEEE  = 4,
+	IWL_RATE_5M_IEEE  = 11,
+	IWL_RATE_11M_IEEE = 22,
+};
+
+#define IWL_CCK_BASIC_RATES_MASK    \
+	(IWL_RATE_1M_MASK          | \
+	IWL_RATE_2M_MASK)
+
+#define IWL_CCK_RATES_MASK          \
+	(IWL_CCK_BASIC_RATES_MASK  | \
+	IWL_RATE_5M_MASK          | \
+	IWL_RATE_11M_MASK)
+
+#define IWL_OFDM_BASIC_RATES_MASK   \
+	(IWL_RATE_6M_MASK         | \
+	IWL_RATE_12M_MASK         | \
+	IWL_RATE_24M_MASK)
+
+#define IWL_OFDM_RATES_MASK         \
+	(IWL_OFDM_BASIC_RATES_MASK | \
+	IWL_RATE_9M_MASK          | \
+	IWL_RATE_18M_MASK         | \
+	IWL_RATE_36M_MASK         | \
+	IWL_RATE_48M_MASK         | \
+	IWL_RATE_54M_MASK)
+
+#define IWL_BASIC_RATES_MASK         \
+	(IWL_OFDM_BASIC_RATES_MASK | \
+	 IWL_CCK_BASIC_RATES_MASK)
+
+#define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
+#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1)
+
+#define IWL_INVALID_VALUE    -1
+
+#define IWL_MIN_RSSI_VAL                 -100
+#define IWL_MAX_RSSI_VAL                    0
+
+/* These values specify how many Tx frame attempts before
+ * searching for a new modulation mode */
+#define IWL_LEGACY_FAILURE_LIMIT	160
+#define IWL_LEGACY_SUCCESS_LIMIT	480
+#define IWL_LEGACY_TABLE_COUNT		160
+
+#define IWL_NONE_LEGACY_FAILURE_LIMIT	400
+#define IWL_NONE_LEGACY_SUCCESS_LIMIT	4500
+#define IWL_NONE_LEGACY_TABLE_COUNT	1500
+
+/* Success ratio (ACKed / attempted tx frames) values (perfect is 128 * 100) */
+#define IWL_RS_GOOD_RATIO		12800	/* 100% */
+#define IWL_RATE_SCALE_SWITCH		10880	/*  85% */
+#define IWL_RATE_HIGH_TH		10880	/*  85% */
+#define IWL_RATE_INCREASE_TH		6400	/*  50% */
+#define IWL_RATE_DECREASE_TH		1920	/*  15% */
+
+/* possible actions when in legacy mode */
+#define IWL_LEGACY_SWITCH_ANTENNA1      0
+#define IWL_LEGACY_SWITCH_ANTENNA2      1
+#define IWL_LEGACY_SWITCH_SISO          2
+#define IWL_LEGACY_SWITCH_MIMO2_AB      3
+#define IWL_LEGACY_SWITCH_MIMO2_AC      4
+#define IWL_LEGACY_SWITCH_MIMO2_BC      5
+
+/* possible actions when in siso mode */
+#define IWL_SISO_SWITCH_ANTENNA1        0
+#define IWL_SISO_SWITCH_ANTENNA2        1
+#define IWL_SISO_SWITCH_MIMO2_AB        2
+#define IWL_SISO_SWITCH_MIMO2_AC        3
+#define IWL_SISO_SWITCH_MIMO2_BC        4
+#define IWL_SISO_SWITCH_GI              5
+
+/* possible actions when in mimo mode */
+#define IWL_MIMO2_SWITCH_ANTENNA1       0
+#define IWL_MIMO2_SWITCH_ANTENNA2       1
+#define IWL_MIMO2_SWITCH_SISO_A         2
+#define IWL_MIMO2_SWITCH_SISO_B         3
+#define IWL_MIMO2_SWITCH_SISO_C         4
+#define IWL_MIMO2_SWITCH_GI             5
+
+#define IWL_MAX_SEARCH IWL_MIMO2_SWITCH_GI
+
+#define IWL_ACTION_LIMIT		3	/* # possible actions */
+
+#define LQ_SIZE		2	/* 2 mode tables:  "Active" and "Search" */
+
+/* load per tid defines for A-MPDU activation */
+#define IWL_AGG_TPT_THREHOLD	0
+#define IWL_AGG_LOAD_THRESHOLD	10
+#define IWL_AGG_ALL_TID		0xff
+#define TID_QUEUE_CELL_SPACING	50	/*mS */
+#define TID_QUEUE_MAX_SIZE	20
+#define TID_ROUND_VALUE		5	/* mS */
+#define TID_MAX_LOAD_COUNT	8
+
+#define TID_MAX_TIME_DIFF ((TID_QUEUE_MAX_SIZE - 1) * TID_QUEUE_CELL_SPACING)
+#define TIME_WRAP_AROUND(x, y) (((y) > (x)) ? (y) - (x) : (0-(x)) + (y))
+
+extern const struct iwl_rate_info iwlegacy_rates[IWL_RATE_COUNT];
+
+enum iwl_table_type {
+	LQ_NONE,
+	LQ_G,		/* legacy types */
+	LQ_A,
+	LQ_SISO,	/* high-throughput types */
+	LQ_MIMO2,
+	LQ_MAX,
+};
+
+#define is_legacy(tbl) (((tbl) == LQ_G) || ((tbl) == LQ_A))
+#define is_siso(tbl) ((tbl) == LQ_SISO)
+#define is_mimo2(tbl) ((tbl) == LQ_MIMO2)
+#define is_mimo(tbl) (is_mimo2(tbl))
+#define is_Ht(tbl) (is_siso(tbl) || is_mimo(tbl))
+#define is_a_band(tbl) ((tbl) == LQ_A)
+#define is_g_and(tbl) ((tbl) == LQ_G)
+
+#define	ANT_NONE	0x0
+#define	ANT_A		BIT(0)
+#define	ANT_B		BIT(1)
+#define	ANT_AB		(ANT_A | ANT_B)
+#define ANT_C		BIT(2)
+#define	ANT_AC		(ANT_A | ANT_C)
+#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];
+};
+
+/**
+ * struct iwl_rate_scale_data -- tx success history for one rate
+ */
+struct iwl_rate_scale_data {
+	u64 data;		/* bitmap of successful frames */
+	s32 success_counter;	/* number of frames successful */
+	s32 success_ratio;	/* per-cent * 128  */
+	s32 counter;		/* number of frames attempted */
+	s32 average_tpt;	/* success ratio * expected throughput */
+	unsigned long stamp;
+};
+
+/**
+ * struct iwl_scale_tbl_info -- tx params and success history for all rates
+ *
+ * There are two of these in struct iwl_lq_sta,
+ * one for "active", and one for "search".
+ */
+struct iwl_scale_tbl_info {
+	enum iwl_table_type lq_type;
+	u8 ant_type;
+	u8 is_SGI;	/* 1 = short guard interval */
+	u8 is_ht40;	/* 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 */
+};
+
+struct iwl_traffic_load {
+	unsigned long time_stamp;	/* age of the oldest statistics */
+	u32 packet_count[TID_QUEUE_MAX_SIZE];   /* packet count in this time
+						 * slice */
+	u32 total;			/* total num of packets during the
+					 * last TID_MAX_TIME_DIFF */
+	u8 queue_count;			/* number of queues that has
+					 * been used since the last cleanup */
+	u8 head;			/* start of the circular buffer */
+};
+
+/**
+ * struct iwl_lq_sta -- driver's rate scaling private structure
+ *
+ * Pointer to this gets passed back and forth between driver and mac80211.
+ */
+struct iwl_lq_sta {
+	u8 active_tbl;		/* index of active table, range 0-1 */
+	u8 enable_counter;	/* indicates HT mode */
+	u8 stay_in_tbl;		/* 1: disallow, 0: allow search for new mode */
+	u8 search_better_tbl;	/* 1: currently trying alternate mode */
+	s32 last_tpt;
+
+	/* The following determine when to search for a new mode */
+	u32 table_count_limit;
+	u32 max_failure_limit;	/* # failed frames before new search */
+	u32 max_success_limit;	/* # successful frames before new search */
+	u32 table_count;
+	u32 total_failed;	/* total failed frames, any/all rates */
+	u32 total_success;	/* total successful frames, any/all rates */
+	u64 flush_timer;	/* time staying in mode before new search */
+
+	u8 action_counter;	/* # mode-switch actions tried */
+	u8 is_green;
+	u8 is_dup;
+	enum ieee80211_band band;
+
+	/* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */
+	u32 supp_rates;
+	u16 active_legacy_rate;
+	u16 active_siso_rate;
+	u16 active_mimo2_rate;
+	s8 max_rate_idx;     /* Max rate set by user */
+	u8 missed_rate_counter;
+
+	struct iwl_link_quality_cmd lq;
+	struct iwl_scale_tbl_info lq_info[LQ_SIZE]; /* "active", "search" */
+	struct iwl_traffic_load load[TID_MAX_LOAD_COUNT];
+	u8 tx_agg_tid_en;
+#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
+	struct iwl_priv *drv;
+
+	/* used to be in sta_info */
+	int last_txrate_idx;
+	/* last tx rate_n_flags */
+	u32 last_rate_n_flags;
+	/* packets destined for this STA are aggregated */
+	u8 is_agg;
+};
+
+static inline u8 iwl4965_num_of_ant(u8 mask)
+{
+	return  !!((mask) & ANT_A) +
+		!!((mask) & ANT_B) +
+		!!((mask) & ANT_C);
+}
+
+static inline u8 iwl4965_first_antenna(u8 mask)
+{
+	if (mask & ANT_A)
+		return ANT_A;
+	if (mask & ANT_B)
+		return ANT_B;
+	return ANT_C;
+}
+
+
+/**
+ * iwl3945_rate_scale_init - Initialize the rate scale table based on assoc info
+ *
+ * The specific throughput table used is based on the type of network
+ * the associated with, including A, B, G, and G w/ TGG protection
+ */
+extern void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id);
+
+/* Initialize station's rate scaling information after adding station */
+extern void iwl4965_rs_rate_init(struct iwl_priv *priv,
+			     struct ieee80211_sta *sta, u8 sta_id);
+extern void iwl3945_rs_rate_init(struct iwl_priv *priv,
+				 struct ieee80211_sta *sta, u8 sta_id);
+
+/**
+ * iwl_rate_control_register - Register the rate control algorithm callbacks
+ *
+ * Since the rate control algorithm is hardware specific, there is no need
+ * or reason to place it as a stand alone module.  The driver can call
+ * iwl_rate_control_register in order to register the rate control callbacks
+ * with the mac80211 subsystem.  This should be performed prior to calling
+ * ieee80211_register_hw
+ *
+ */
+extern int iwl4965_rate_control_register(void);
+extern int iwl3945_rate_control_register(void);
+
+/**
+ * iwl_rate_control_unregister - Unregister the rate control callbacks
+ *
+ * This should be called after calling ieee80211_unregister_hw, but before
+ * the driver is unloaded.
+ */
+extern void iwl4965_rate_control_unregister(void);
+extern void iwl3945_rate_control_unregister(void);
+
+#endif /* __iwl_legacy_rs__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-power.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-power.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-power.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-power.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,165 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 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/slab.h>
+#include <linux/init.h>
+
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-commands.h"
+#include "iwl-debug.h"
+#include "iwl-power.h"
+
+/*
+ * Setting power level allows the card to go to sleep when not busy.
+ *
+ * We calculate a sleep command based on the required latency, which
+ * we get from mac80211. In order to handle thermal throttling, we can
+ * also use pre-defined power levels.
+ */
+
+/*
+ * This defines the old power levels. They are still used by default
+ * (level 1) and for thermal throttle (levels 3 through 5)
+ */
+
+struct iwl_power_vec_entry {
+	struct iwl_powertable_cmd cmd;
+	u8 no_dtim;	/* number of skip dtim */
+};
+
+static void iwl_legacy_power_sleep_cam_cmd(struct iwl_priv *priv,
+				    struct iwl_powertable_cmd *cmd)
+{
+	memset(cmd, 0, sizeof(*cmd));
+
+	if (priv->power_data.pci_pm)
+		cmd->flags |= IWL_POWER_PCI_PM_MSK;
+
+	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
+}
+
+static int
+iwl_legacy_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
+{
+	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
+	IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
+	IWL_DEBUG_POWER(priv, "Tx timeout = %u\n",
+					le32_to_cpu(cmd->tx_data_timeout));
+	IWL_DEBUG_POWER(priv, "Rx timeout = %u\n",
+					le32_to_cpu(cmd->rx_data_timeout));
+	IWL_DEBUG_POWER(priv,
+			"Sleep interval vector = { %d , %d , %d , %d , %d }\n",
+			le32_to_cpu(cmd->sleep_interval[0]),
+			le32_to_cpu(cmd->sleep_interval[1]),
+			le32_to_cpu(cmd->sleep_interval[2]),
+			le32_to_cpu(cmd->sleep_interval[3]),
+			le32_to_cpu(cmd->sleep_interval[4]));
+
+	return iwl_legacy_send_cmd_pdu(priv, POWER_TABLE_CMD,
+				sizeof(struct iwl_powertable_cmd), cmd);
+}
+
+int
+iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force)
+{
+	int ret;
+	bool update_chains;
+
+	lockdep_assert_held(&priv->mutex);
+
+	/* Don't update the RX chain when chain noise calibration is running */
+	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
+			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
+
+	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
+		return 0;
+
+	if (!iwl_legacy_is_ready_rf(priv))
+		return -EIO;
+
+	/* scan complete use sleep_power_next, need to be updated */
+	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
+	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
+		return 0;
+	}
+
+	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
+		set_bit(STATUS_POWER_PMI, &priv->status);
+
+	ret = iwl_legacy_set_power(priv, cmd);
+	if (!ret) {
+		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
+			clear_bit(STATUS_POWER_PMI, &priv->status);
+
+		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
+			priv->cfg->ops->lib->update_chain_flags(priv);
+		else if (priv->cfg->ops->lib->update_chain_flags)
+			IWL_DEBUG_POWER(priv,
+					"Cannot update the power, chain noise "
+					"calibration running: %d\n",
+					priv->chain_noise_data.state);
+
+		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
+	} else
+		IWL_ERR(priv, "set power fail, ret = %d", ret);
+
+	return ret;
+}
+
+int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force)
+{
+	struct iwl_powertable_cmd cmd;
+
+	iwl_legacy_power_sleep_cam_cmd(priv, &cmd);
+	return iwl_legacy_power_set_mode(priv, &cmd, force);
+}
+EXPORT_SYMBOL(iwl_legacy_power_update_mode);
+
+/* initialize to default */
+void iwl_legacy_power_initialize(struct iwl_priv *priv)
+{
+	u16 lctl = iwl_legacy_pcie_link_ctl(priv);
+
+	priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
+
+	priv->power_data.debug_sleep_level_override = -1;
+
+	memset(&priv->power_data.sleep_cmd, 0,
+		sizeof(priv->power_data.sleep_cmd));
+}
+EXPORT_SYMBOL(iwl_legacy_power_initialize);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-power.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-power.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-power.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-power.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,55 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2007 - 2011 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_legacy_power_setting_h__
+#define __iwl_legacy_power_setting_h__
+
+#include "iwl-commands.h"
+
+enum iwl_power_level {
+	IWL_POWER_INDEX_1,
+	IWL_POWER_INDEX_2,
+	IWL_POWER_INDEX_3,
+	IWL_POWER_INDEX_4,
+	IWL_POWER_INDEX_5,
+	IWL_POWER_NUM
+};
+
+struct iwl_power_mgr {
+	struct iwl_powertable_cmd sleep_cmd;
+	struct iwl_powertable_cmd sleep_cmd_next;
+	int debug_sleep_level_override;
+	bool pci_pm;
+};
+
+int
+iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
+		       bool force);
+int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force);
+void iwl_legacy_power_initialize(struct iwl_priv *priv);
+
+#endif  /* __iwl_legacy_power_setting_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-prph.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-prph.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-prph.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-prph.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,523 @@
+/******************************************************************************
+ *
+ * This file is provided under a dual BSD/GPLv2 license.  When using or
+ * redistributing this file, you may do so under either license.
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *
+ * BSD LICENSE
+ *
+ * Copyright(c) 2005 - 2011 Intel Corporation. All rights reserved.
+ * 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 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.
+ *****************************************************************************/
+
+#ifndef	__iwl_legacy_prph_h__
+#define __iwl_legacy_prph_h__
+
+/*
+ * Registers in this file are internal, not PCI bus memory mapped.
+ * Driver accesses these via HBUS_TARG_PRPH_* registers.
+ */
+#define PRPH_BASE	(0x00000)
+#define PRPH_END	(0xFFFFF)
+
+/* APMG (power management) constants */
+#define APMG_BASE			(PRPH_BASE + 0x3000)
+#define APMG_CLK_CTRL_REG		(APMG_BASE + 0x0000)
+#define APMG_CLK_EN_REG			(APMG_BASE + 0x0004)
+#define APMG_CLK_DIS_REG		(APMG_BASE + 0x0008)
+#define APMG_PS_CTRL_REG		(APMG_BASE + 0x000c)
+#define APMG_PCIDEV_STT_REG		(APMG_BASE + 0x0010)
+#define APMG_RFKILL_REG			(APMG_BASE + 0x0014)
+#define APMG_RTC_INT_STT_REG		(APMG_BASE + 0x001c)
+#define APMG_RTC_INT_MSK_REG		(APMG_BASE + 0x0020)
+#define APMG_DIGITAL_SVR_REG		(APMG_BASE + 0x0058)
+#define APMG_ANALOG_SVR_REG		(APMG_BASE + 0x006C)
+
+#define APMS_CLK_VAL_MRB_FUNC_MODE	(0x00000001)
+#define APMG_CLK_VAL_DMA_CLK_RQT	(0x00000200)
+#define APMG_CLK_VAL_BSM_CLK_RQT	(0x00000800)
+
+#define APMG_PS_CTRL_EARLY_PWR_OFF_RESET_DIS	(0x00400000)
+#define APMG_PS_CTRL_VAL_RESET_REQ		(0x04000000)
+#define APMG_PS_CTRL_MSK_PWR_SRC		(0x03000000)
+#define APMG_PS_CTRL_VAL_PWR_SRC_VMAIN		(0x00000000)
+#define APMG_PS_CTRL_VAL_PWR_SRC_MAX		(0x01000000) /* 3945 only */
+#define APMG_PS_CTRL_VAL_PWR_SRC_VAUX		(0x02000000)
+#define APMG_SVR_VOLTAGE_CONFIG_BIT_MSK	(0x000001E0) /* bit 8:5 */
+#define APMG_SVR_DIGITAL_VOLTAGE_1_32		(0x00000060)
+
+#define APMG_PCIDEV_STT_VAL_L1_ACT_DIS		(0x00000800)
+
+/**
+ * BSM (Bootstrap State Machine)
+ *
+ * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
+ * in special SRAM that does not power down when the embedded control
+ * processor is sleeping (e.g. for periodic power-saving shutdowns of radio).
+ *
+ * When powering back up after sleeps (or during initial uCode load), the BSM
+ * internally loads the short bootstrap program from the special SRAM into the
+ * embedded processor's instruction SRAM, and starts the processor so it runs
+ * the bootstrap program.
+ *
+ * This bootstrap program loads (via PCI busmaster DMA) instructions and data
+ * images for a uCode program from host DRAM locations.  The host driver
+ * indicates DRAM locations and sizes for instruction and data images via the
+ * four BSM_DRAM_* registers.  Once the bootstrap program loads the new program,
+ * the new program starts automatically.
+ *
+ * The uCode used for open-source drivers includes two programs:
+ *
+ * 1)  Initialization -- performs hardware calibration and sets up some
+ *     internal data, then notifies host via "initialize alive" notification
+ *     (struct iwl_init_alive_resp) that it has completed all of its work.
+ *     After signal from host, it then loads and starts the runtime program.
+ *     The initialization program must be used when initially setting up the
+ *     NIC after loading the driver.
+ *
+ * 2)  Runtime/Protocol -- performs all normal runtime operations.  This
+ *     notifies host via "alive" notification (struct iwl_alive_resp) that it
+ *     is ready to be used.
+ *
+ * When initializing the NIC, the host driver does the following procedure:
+ *
+ * 1)  Load bootstrap program (instructions only, no data image for bootstrap)
+ *     into bootstrap memory.  Use dword writes starting at BSM_SRAM_LOWER_BOUND
+ *
+ * 2)  Point (via BSM_DRAM_*) to the "initialize" uCode data and instruction
+ *     images in host DRAM.
+ *
+ * 3)  Set up BSM to copy from BSM SRAM into uCode instruction SRAM when asked:
+ *     BSM_WR_MEM_SRC_REG = 0
+ *     BSM_WR_MEM_DST_REG = RTC_INST_LOWER_BOUND
+ *     BSM_WR_MEM_DWCOUNT_REG = # dwords in bootstrap instruction image
+ *
+ * 4)  Load bootstrap into instruction SRAM:
+ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START
+ *
+ * 5)  Wait for load completion:
+ *     Poll BSM_WR_CTRL_REG for BSM_WR_CTRL_REG_BIT_START = 0
+ *
+ * 6)  Enable future boot loads whenever NIC's power management triggers it:
+ *     BSM_WR_CTRL_REG = BSM_WR_CTRL_REG_BIT_START_EN
+ *
+ * 7)  Start the NIC by removing all reset bits:
+ *     CSR_RESET = 0
+ *
+ *     The bootstrap uCode (already in instruction SRAM) loads initialization
+ *     uCode.  Initialization uCode performs data initialization, sends
+ *     "initialize alive" notification to host, and waits for a signal from
+ *     host to load runtime code.
+ *
+ * 4)  Point (via BSM_DRAM_*) to the "runtime" uCode data and instruction
+ *     images in host DRAM.  The last register loaded must be the instruction
+ *     byte count register ("1" in MSbit tells initialization uCode to load
+ *     the runtime uCode):
+ *     BSM_DRAM_INST_BYTECOUNT_REG = byte count | BSM_DRAM_INST_LOAD
+ *
+ * 5)  Wait for "alive" notification, then issue normal runtime commands.
+ *
+ * Data caching during power-downs:
+ *
+ * Just before the embedded controller powers down (e.g for automatic
+ * power-saving modes, or for RFKILL), uCode stores (via PCI busmaster DMA)
+ * a current snapshot of the embedded processor's data SRAM into host DRAM.
+ * This caches the data while the embedded processor's memory is powered down.
+ * Location and size are controlled by BSM_DRAM_DATA_* registers.
+ *
+ * NOTE:  Instruction SRAM does not need to be saved, since that doesn't
+ *        change during operation; the original image (from uCode distribution
+ *        file) can be used for reload.
+ *
+ * When powering back up, the BSM loads the bootstrap program.  Bootstrap looks
+ * at the BSM_DRAM_* registers, which now point to the runtime instruction
+ * image and the cached (modified) runtime data (*not* the initialization
+ * uCode).  Bootstrap reloads these runtime images into SRAM, and restarts the
+ * uCode from where it left off before the power-down.
+ *
+ * NOTE:  Initialization uCode does *not* run as part of the save/restore
+ *        procedure.
+ *
+ * This save/restore method is mostly for autonomous power management during
+ * normal operation (result of POWER_TABLE_CMD).  Platform suspend/resume and
+ * RFKILL should use complete restarts (with total re-initialization) of uCode,
+ * allowing total shutdown (including BSM memory).
+ *
+ * Note that, during normal operation, the host DRAM that held the initial
+ * startup data for the runtime code is now being used as a backup data cache
+ * for modified data!  If you need to completely re-initialize the NIC, make
+ * sure that you use the runtime data image from the uCode distribution file,
+ * not the modified/saved runtime data.  You may want to store a separate
+ * "clean" runtime data image in DRAM to avoid disk reads of distribution file.
+ */
+
+/* BSM bit fields */
+#define BSM_WR_CTRL_REG_BIT_START     (0x80000000) /* start boot load now */
+#define BSM_WR_CTRL_REG_BIT_START_EN  (0x40000000) /* enable boot after pwrup*/
+#define BSM_DRAM_INST_LOAD            (0x80000000) /* start program load now */
+
+/* BSM addresses */
+#define BSM_BASE                     (PRPH_BASE + 0x3400)
+#define BSM_END                      (PRPH_BASE + 0x3800)
+
+#define BSM_WR_CTRL_REG              (BSM_BASE + 0x000) /* ctl and status */
+#define BSM_WR_MEM_SRC_REG           (BSM_BASE + 0x004) /* source in BSM mem */
+#define BSM_WR_MEM_DST_REG           (BSM_BASE + 0x008) /* dest in SRAM mem */
+#define BSM_WR_DWCOUNT_REG           (BSM_BASE + 0x00C) /* bytes */
+#define BSM_WR_STATUS_REG            (BSM_BASE + 0x010) /* bit 0:  1 == done */
+
+/*
+ * Pointers and size regs for bootstrap load and data SRAM save/restore.
+ * NOTE:  3945 pointers use bits 31:0 of DRAM address.
+ *        4965 pointers use bits 35:4 of DRAM address.
+ */
+#define BSM_DRAM_INST_PTR_REG        (BSM_BASE + 0x090)
+#define BSM_DRAM_INST_BYTECOUNT_REG  (BSM_BASE + 0x094)
+#define BSM_DRAM_DATA_PTR_REG        (BSM_BASE + 0x098)
+#define BSM_DRAM_DATA_BYTECOUNT_REG  (BSM_BASE + 0x09C)
+
+/*
+ * BSM special memory, stays powered on during power-save sleeps.
+ * Read/write, address range from LOWER_BOUND to (LOWER_BOUND + SIZE -1)
+ */
+#define BSM_SRAM_LOWER_BOUND         (PRPH_BASE + 0x3800)
+#define BSM_SRAM_SIZE			(1024) /* bytes */
+
+
+/* 3945 Tx scheduler registers */
+#define ALM_SCD_BASE                        (PRPH_BASE + 0x2E00)
+#define ALM_SCD_MODE_REG                    (ALM_SCD_BASE + 0x000)
+#define ALM_SCD_ARASTAT_REG                 (ALM_SCD_BASE + 0x004)
+#define ALM_SCD_TXFACT_REG                  (ALM_SCD_BASE + 0x010)
+#define ALM_SCD_TXF4MF_REG                  (ALM_SCD_BASE + 0x014)
+#define ALM_SCD_TXF5MF_REG                  (ALM_SCD_BASE + 0x020)
+#define ALM_SCD_SBYP_MODE_1_REG             (ALM_SCD_BASE + 0x02C)
+#define ALM_SCD_SBYP_MODE_2_REG             (ALM_SCD_BASE + 0x030)
+
+/**
+ * Tx Scheduler
+ *
+ * The Tx Scheduler selects the next frame to be transmitted, choosing TFDs
+ * (Transmit Frame Descriptors) from up to 16 circular Tx queues resident in
+ * host DRAM.  It steers each frame's Tx command (which contains the frame
+ * data) into one of up to 7 prioritized Tx DMA FIFO channels within the
+ * device.  A queue maps to only one (selectable by driver) Tx DMA channel,
+ * but one DMA channel may take input from several queues.
+ *
+ * Tx DMA FIFOs have dedicated purposes.  For 4965, they are used as follows
+ * (cf. default_queue_to_tx_fifo in iwl-4965.c):
+ *
+ * 0 -- EDCA BK (background) frames, lowest priority
+ * 1 -- EDCA BE (best effort) frames, normal priority
+ * 2 -- EDCA VI (video) frames, higher priority
+ * 3 -- EDCA VO (voice) and management frames, highest priority
+ * 4 -- Commands (e.g. RXON, etc.)
+ * 5 -- unused (HCCA)
+ * 6 -- unused (HCCA)
+ * 7 -- not used by driver (device-internal only)
+ *
+ *
+ * Driver should normally map queues 0-6 to Tx DMA/FIFO channels 0-6.
+ * In addition, driver can map the remaining queues to Tx DMA/FIFO
+ * channels 0-3 to support 11n aggregation via EDCA DMA channels.
+ *
+ * The driver sets up each queue to work in one of two modes:
+ *
+ * 1)  Scheduler-Ack, in which the scheduler automatically supports a
+ *     block-ack (BA) window of up to 64 TFDs.  In this mode, each queue
+ *     contains TFDs for a unique combination of Recipient Address (RA)
+ *     and Traffic Identifier (TID), that is, traffic of a given
+ *     Quality-Of-Service (QOS) priority, destined for a single station.
+ *
+ *     In scheduler-ack mode, the scheduler keeps track of the Tx status of
+ *     each frame within the BA window, including whether it's been transmitted,
+ *     and whether it's been acknowledged by the receiving station.  The device
+ *     automatically processes block-acks received from the receiving STA,
+ *     and reschedules un-acked frames to be retransmitted (successful
+ *     Tx completion may end up being out-of-order).
+ *
+ *     The driver must maintain the queue's Byte Count table in host DRAM
+ *     (struct iwl4965_sched_queue_byte_cnt_tbl) for this mode.
+ *     This mode does not support fragmentation.
+ *
+ * 2)  FIFO (a.k.a. non-Scheduler-ACK), in which each TFD is processed in order.
+ *     The device may automatically retry Tx, but will retry only one frame
+ *     at a time, until receiving ACK from receiving station, or reaching
+ *     retry limit and giving up.
+ *
+ *     The command queue (#4/#9) must use this mode!
+ *     This mode does not require use of the Byte Count table in host DRAM.
+ *
+ * Driver controls scheduler operation via 3 means:
+ * 1)  Scheduler registers
+ * 2)  Shared scheduler data base in internal 4956 SRAM
+ * 3)  Shared data in host DRAM
+ *
+ * Initialization:
+ *
+ * When loading, driver should allocate memory for:
+ * 1)  16 TFD circular buffers, each with space for (typically) 256 TFDs.
+ * 2)  16 Byte Count circular buffers in 16 KBytes contiguous memory
+ *     (1024 bytes for each queue).
+ *
+ * After receiving "Alive" response from uCode, driver must initialize
+ * the scheduler (especially for queue #4/#9, the command queue, otherwise
+ * the driver can't issue commands!):
+ */
+
+/**
+ * Max Tx window size is the max number of contiguous TFDs that the scheduler
+ * can keep track of at one time when creating block-ack chains of frames.
+ * Note that "64" matches the number of ack bits in a block-ack packet.
+ * Driver should use SCD_WIN_SIZE and SCD_FRAME_LIMIT values to initialize
+ * IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) values.
+ */
+#define SCD_WIN_SIZE				64
+#define SCD_FRAME_LIMIT				64
+
+/* SCD registers are internal, must be accessed via HBUS_TARG_PRPH regs */
+#define IWL49_SCD_START_OFFSET		0xa02c00
+
+/*
+ * 4965 tells driver SRAM address for internal scheduler structs via this reg.
+ * Value is valid only after "Alive" response from uCode.
+ */
+#define IWL49_SCD_SRAM_BASE_ADDR           (IWL49_SCD_START_OFFSET + 0x0)
+
+/*
+ * Driver may need to update queue-empty bits after changing queue's
+ * write and read pointers (indexes) during (re-)initialization (i.e. when
+ * scheduler is not tracking what's happening).
+ * Bit fields:
+ * 31-16:  Write mask -- 1: update empty bit, 0: don't change empty bit
+ * 15-00:  Empty state, one for each queue -- 1: empty, 0: non-empty
+ * NOTE:  This register is not used by Linux driver.
+ */
+#define IWL49_SCD_EMPTY_BITS               (IWL49_SCD_START_OFFSET + 0x4)
+
+/*
+ * Physical base address of array of byte count (BC) circular buffers (CBs).
+ * Each Tx queue has a BC CB in host DRAM to support Scheduler-ACK mode.
+ * This register points to BC CB for queue 0, must be on 1024-byte boundary.
+ * Others are spaced by 1024 bytes.
+ * Each BC CB is 2 bytes * (256 + 64) = 740 bytes, followed by 384 bytes pad.
+ * (Index into a queue's BC CB) = (index into queue's TFD CB) = (SSN & 0xff).
+ * Bit fields:
+ * 25-00:  Byte Count CB physical address [35:10], must be 1024-byte aligned.
+ */
+#define IWL49_SCD_DRAM_BASE_ADDR           (IWL49_SCD_START_OFFSET + 0x10)
+
+/*
+ * Enables any/all Tx DMA/FIFO channels.
+ * Scheduler generates requests for only the active channels.
+ * Set this to 0xff to enable all 8 channels (normal usage).
+ * Bit fields:
+ *  7- 0:  Enable (1), disable (0), one bit for each channel 0-7
+ */
+#define IWL49_SCD_TXFACT                   (IWL49_SCD_START_OFFSET + 0x1c)
+/*
+ * Queue (x) Write Pointers (indexes, really!), one for each Tx queue.
+ * Initialized and updated by driver as new TFDs are added to queue.
+ * NOTE:  If using Block Ack, index must correspond to frame's
+ *        Start Sequence Number; index = (SSN & 0xff)
+ * NOTE:  Alternative to HBUS_TARG_WRPTR, which is what Linux driver uses?
+ */
+#define IWL49_SCD_QUEUE_WRPTR(x)  (IWL49_SCD_START_OFFSET + 0x24 + (x) * 4)
+
+/*
+ * Queue (x) Read Pointers (indexes, really!), one for each Tx queue.
+ * For FIFO mode, index indicates next frame to transmit.
+ * For Scheduler-ACK mode, index indicates first frame in Tx window.
+ * Initialized by driver, updated by scheduler.
+ */
+#define IWL49_SCD_QUEUE_RDPTR(x)  (IWL49_SCD_START_OFFSET + 0x64 + (x) * 4)
+
+/*
+ * Select which queues work in chain mode (1) vs. not (0).
+ * Use chain mode to build chains of aggregated frames.
+ * Bit fields:
+ * 31-16:  Reserved
+ * 15-00:  Mode, one bit for each queue -- 1: Chain mode, 0: one-at-a-time
+ * NOTE:  If driver sets up queue for chain mode, it should be also set up
+ *        Scheduler-ACK mode as well, via SCD_QUEUE_STATUS_BITS(x).
+ */
+#define IWL49_SCD_QUEUECHAIN_SEL  (IWL49_SCD_START_OFFSET + 0xd0)
+
+/*
+ * Select which queues interrupt driver when scheduler increments
+ * a queue's read pointer (index).
+ * Bit fields:
+ * 31-16:  Reserved
+ * 15-00:  Interrupt enable, one bit for each queue -- 1: enabled, 0: disabled
+ * NOTE:  This functionality is apparently a no-op; driver relies on interrupts
+ *        from Rx queue to read Tx command responses and update Tx queues.
+ */
+#define IWL49_SCD_INTERRUPT_MASK  (IWL49_SCD_START_OFFSET + 0xe4)
+
+/*
+ * Queue search status registers.  One for each queue.
+ * Sets up queue mode and assigns queue to Tx DMA channel.
+ * Bit fields:
+ * 19-10: Write mask/enable bits for bits 0-9
+ *     9: Driver should init to "0"
+ *     8: Scheduler-ACK mode (1), non-Scheduler-ACK (i.e. FIFO) mode (0).
+ *        Driver should init to "1" for aggregation mode, or "0" otherwise.
+ *   7-6: Driver should init to "0"
+ *     5: Window Size Left; indicates whether scheduler can request
+ *        another TFD, based on window size, etc.  Driver should init
+ *        this bit to "1" for aggregation mode, or "0" for non-agg.
+ *   4-1: Tx FIFO to use (range 0-7).
+ *     0: Queue is active (1), not active (0).
+ * Other bits should be written as "0"
+ *
+ * NOTE:  If enabling Scheduler-ACK mode, chain mode should also be enabled
+ *        via SCD_QUEUECHAIN_SEL.
+ */
+#define IWL49_SCD_QUEUE_STATUS_BITS(x)\
+	(IWL49_SCD_START_OFFSET + 0x104 + (x) * 4)
+
+/* Bit field positions */
+#define IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE	(0)
+#define IWL49_SCD_QUEUE_STTS_REG_POS_TXF	(1)
+#define IWL49_SCD_QUEUE_STTS_REG_POS_WSL	(5)
+#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK	(8)
+
+/* Write masks */
+#define IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN	(10)
+#define IWL49_SCD_QUEUE_STTS_REG_MSK		(0x0007FC00)
+
+/**
+ * 4965 internal SRAM structures for scheduler, shared with driver ...
+ *
+ * Driver should clear and initialize the following areas after receiving
+ * "Alive" response from 4965 uCode, i.e. after initial
+ * uCode load, or after a uCode load done for error recovery:
+ *
+ * SCD_CONTEXT_DATA_OFFSET (size 128 bytes)
+ * SCD_TX_STTS_BITMAP_OFFSET (size 256 bytes)
+ * SCD_TRANSLATE_TBL_OFFSET (size 32 bytes)
+ *
+ * Driver accesses SRAM via HBUS_TARG_MEM_* registers.
+ * Driver reads base address of this scheduler area from SCD_SRAM_BASE_ADDR.
+ * All OFFSET values must be added to this base address.
+ */
+
+/*
+ * Queue context.  One 8-byte entry for each of 16 queues.
+ *
+ * Driver should clear this entire area (size 0x80) to 0 after receiving
+ * "Alive" notification from uCode.  Additionally, driver should init
+ * each queue's entry as follows:
+ *
+ * LS Dword bit fields:
+ *  0-06:  Max Tx window size for Scheduler-ACK.  Driver should init to 64.
+ *
+ * MS Dword bit fields:
+ * 16-22:  Frame limit.  Driver should init to 10 (0xa).
+ *
+ * Driver should init all other bits to 0.
+ *
+ * Init must be done after driver receives "Alive" response from 4965 uCode,
+ * and when setting up queue for aggregation.
+ */
+#define IWL49_SCD_CONTEXT_DATA_OFFSET			0x380
+#define IWL49_SCD_CONTEXT_QUEUE_OFFSET(x) \
+			(IWL49_SCD_CONTEXT_DATA_OFFSET + ((x) * 8))
+
+#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS		(0)
+#define IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK		(0x0000007F)
+#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS	(16)
+#define IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK	(0x007F0000)
+
+/*
+ * Tx Status Bitmap
+ *
+ * Driver should clear this entire area (size 0x100) to 0 after receiving
+ * "Alive" notification from uCode.  Area is used only by device itself;
+ * no other support (besides clearing) is required from driver.
+ */
+#define IWL49_SCD_TX_STTS_BITMAP_OFFSET		0x400
+
+/*
+ * RAxTID to queue translation mapping.
+ *
+ * When queue is in Scheduler-ACK mode, frames placed in a that queue must be
+ * for only one combination of receiver address (RA) and traffic ID (TID), i.e.
+ * one QOS priority level destined for one station (for this wireless link,
+ * not final destination).  The SCD_TRANSLATE_TABLE area provides 16 16-bit
+ * mappings, one for each of the 16 queues.  If queue is not in Scheduler-ACK
+ * mode, the device ignores the mapping value.
+ *
+ * Bit fields, for each 16-bit map:
+ * 15-9:  Reserved, set to 0
+ *  8-4:  Index into device's station table for recipient station
+ *  3-0:  Traffic ID (tid), range 0-15
+ *
+ * Driver should clear this entire area (size 32 bytes) to 0 after receiving
+ * "Alive" notification from uCode.  To update a 16-bit map value, driver
+ * must read a dword-aligned value from device SRAM, replace the 16-bit map
+ * value of interest, and write the dword value back into device SRAM.
+ */
+#define IWL49_SCD_TRANSLATE_TBL_OFFSET		0x500
+
+/* Find translation table dword to read/write for given queue */
+#define IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(x) \
+	((IWL49_SCD_TRANSLATE_TBL_OFFSET + ((x) * 2)) & 0xfffffffc)
+
+#define IWL_SCD_TXFIFO_POS_TID			(0)
+#define IWL_SCD_TXFIFO_POS_RA			(4)
+#define IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK	(0x01FF)
+
+/*********************** END TX SCHEDULER *************************************/
+
+#endif				/* __iwl_legacy_prph_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-rx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,302 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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/etherdevice.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+#include <asm/unaligned.h>
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+/************************** RX-FUNCTIONS ****************************/
+/*
+ * Rx theory of operation
+ *
+ * Driver allocates a circular buffer of Receive Buffer Descriptors (RBDs),
+ * each of which point to Receive Buffers to be filled by the NIC.  These get
+ * used not only for Rx frames, but for any command response or notification
+ * from the NIC.  The driver and NIC manage the Rx buffers by means
+ * of indexes into the circular buffer.
+ *
+ * Rx Queue Indexes
+ * The host/firmware share two index registers for managing the Rx buffers.
+ *
+ * The READ index maps to the first position that the firmware may be writing
+ * to -- the driver can read up to (but not including) this position and get
+ * good data.
+ * The READ index is managed by the firmware once the card is enabled.
+ *
+ * The WRITE index maps to the last position the driver has read from -- the
+ * position preceding WRITE is the last slot the firmware can place a packet.
+ *
+ * The queue is empty (no good data) if WRITE = READ - 1, and is full if
+ * WRITE = READ.
+ *
+ * During initialization, the host sets up the READ queue position to the first
+ * INDEX position, and WRITE to the last (READ - 1 wrapped)
+ *
+ * When the firmware places a packet in a buffer, it will advance the READ index
+ * and fire the RX interrupt.  The driver can then query the READ index and
+ * process as many packets as possible, moving the WRITE index forward as it
+ * resets the Rx queue buffers with new memory.
+ *
+ * The management in the driver is as follows:
+ * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
+ *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
+ *   to replenish the iwl->rxq->rx_free.
+ * + In iwl_rx_replenish (scheduled) if 'processed' != 'read' then the
+ *   iwl->rxq is replenished and the READ INDEX is updated (updating the
+ *   'processed' and 'read' driver indexes as well)
+ * + A received packet is processed and handed to the kernel network stack,
+ *   detached from the iwl->rxq.  The driver 'processed' index is updated.
+ * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
+ *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
+ *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
+ *   were enough free buffers and RX_STALLED is set it is cleared.
+ *
+ *
+ * Driver sequence:
+ *
+ * iwl_legacy_rx_queue_alloc()   Allocates rx_free
+ * iwl_rx_replenish()     Replenishes rx_free list from rx_used, and calls
+ *                            iwl_rx_queue_restock
+ * iwl_rx_queue_restock() Moves available buffers from rx_free into Rx
+ *                            queue, updates firmware pointers, and updates
+ *                            the WRITE index.  If insufficient rx_free buffers
+ *                            are available, schedules iwl_rx_replenish
+ *
+ * -- enable interrupts --
+ * ISR - iwl_rx()         Detach iwl_rx_mem_buffers from pool up to the
+ *                            READ INDEX, detaching the SKB from the pool.
+ *                            Moves the packet buffer from queue to rx_used.
+ *                            Calls iwl_rx_queue_restock to refill any empty
+ *                            slots.
+ * ...
+ *
+ */
+
+/**
+ * iwl_legacy_rx_queue_space - Return number of free slots available in queue.
+ */
+int iwl_legacy_rx_queue_space(const struct iwl_rx_queue *q)
+{
+	int s = q->read - q->write;
+	if (s <= 0)
+		s += RX_QUEUE_SIZE;
+	/* keep some buffer to not confuse full and empty queue */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+EXPORT_SYMBOL(iwl_legacy_rx_queue_space);
+
+/**
+ * iwl_legacy_rx_queue_update_write_ptr - Update the write pointer for the RX queue
+ */
+void
+iwl_legacy_rx_queue_update_write_ptr(struct iwl_priv *priv,
+					struct iwl_rx_queue *q)
+{
+	unsigned long flags;
+	u32 rx_wrt_ptr_reg = priv->hw_params.rx_wrt_ptr_reg;
+	u32 reg;
+
+	spin_lock_irqsave(&q->lock, flags);
+
+	if (q->need_update == 0)
+		goto exit_unlock;
+
+	/* If power-saving is in use, make sure device is awake */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+			IWL_DEBUG_INFO(priv,
+				"Rx queue requesting wakeup,"
+				" GP1 = 0x%x\n", reg);
+			iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
+				CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+			goto exit_unlock;
+		}
+
+		q->write_actual = (q->write & ~0x7);
+		iwl_legacy_write_direct32(priv, rx_wrt_ptr_reg,
+				q->write_actual);
+
+	/* Else device is assumed to be awake */
+	} else {
+		/* Device expects a multiple of 8 */
+		q->write_actual = (q->write & ~0x7);
+		iwl_legacy_write_direct32(priv, rx_wrt_ptr_reg,
+			q->write_actual);
+	}
+
+	q->need_update = 0;
+
+ exit_unlock:
+	spin_unlock_irqrestore(&q->lock, flags);
+}
+EXPORT_SYMBOL(iwl_legacy_rx_queue_update_write_ptr);
+
+int iwl_legacy_rx_queue_alloc(struct iwl_priv *priv)
+{
+	struct iwl_rx_queue *rxq = &priv->rxq;
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	spin_lock_init(&rxq->lock);
+	INIT_LIST_HEAD(&rxq->rx_free);
+	INIT_LIST_HEAD(&rxq->rx_used);
+
+	/* Alloc the circular buffer of Read Buffer Descriptors (RBDs) */
+	rxq->bd = dma_alloc_coherent(dev, 4 * RX_QUEUE_SIZE, &rxq->bd_dma,
+				     GFP_KERNEL);
+	if (!rxq->bd)
+		goto err_bd;
+
+	rxq->rb_stts = dma_alloc_coherent(dev, sizeof(struct iwl_rb_status),
+					  &rxq->rb_stts_dma, GFP_KERNEL);
+	if (!rxq->rb_stts)
+		goto err_rb;
+
+	/* Fill the rx_used queue with _all_ of the Rx buffers */
+	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++)
+		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
+
+	/* 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;
+
+err_rb:
+	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
+			  rxq->bd_dma);
+err_bd:
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(iwl_legacy_rx_queue_alloc);
+
+
+void iwl_legacy_rx_spectrum_measure_notif(struct iwl_priv *priv,
+					  struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_spectrum_notification *report = &(pkt->u.spectrum_notif);
+
+	if (!report->state) {
+		IWL_DEBUG_11H(priv,
+			"Spectrum Measure Notification: Start\n");
+		return;
+	}
+
+	memcpy(&priv->measure_report, report, sizeof(*report));
+	priv->measurement_status |= MEASUREMENT_READY;
+}
+EXPORT_SYMBOL(iwl_legacy_rx_spectrum_measure_notif);
+
+void iwl_legacy_recover_from_statistics(struct iwl_priv *priv,
+				struct iwl_rx_packet *pkt)
+{
+	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return;
+	if (iwl_legacy_is_any_associated(priv)) {
+		if (priv->cfg->ops->lib->check_plcp_health) {
+			if (!priv->cfg->ops->lib->check_plcp_health(
+			    priv, pkt)) {
+				/*
+				 * high plcp error detected
+				 * reset Radio
+				 */
+				iwl_legacy_force_reset(priv,
+							IWL_RF_RESET, false);
+			}
+		}
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_recover_from_statistics);
+
+/*
+ * returns non-zero if packet should be dropped
+ */
+int iwl_legacy_set_decrypted_flag(struct iwl_priv *priv,
+			   struct ieee80211_hdr *hdr,
+			   u32 decrypt_res,
+			   struct ieee80211_rx_status *stats)
+{
+	u16 fc = le16_to_cpu(hdr->frame_control);
+
+	/*
+	 * All contexts have the same setting here due to it being
+	 * a module parameter, so OK to check any context.
+	 */
+	if (priv->contexts[IWL_RXON_CTX_BSS].active.filter_flags &
+						RXON_FILTER_DIS_DECRYPT_MSK)
+		return 0;
+
+	if (!(fc & IEEE80211_FCTL_PROTECTED))
+		return 0;
+
+	IWL_DEBUG_RX(priv, "decrypt_res:0x%x\n", decrypt_res);
+	switch (decrypt_res & RX_RES_STATUS_SEC_TYPE_MSK) {
+	case RX_RES_STATUS_SEC_TYPE_TKIP:
+		/* The uCode has got a bad phase 1 Key, pushes the packet.
+		 * Decryption will be done in SW. */
+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+		    RX_RES_STATUS_BAD_KEY_TTAK)
+			break;
+
+	case RX_RES_STATUS_SEC_TYPE_WEP:
+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+		    RX_RES_STATUS_BAD_ICV_MIC) {
+			/* bad ICV, the packet is destroyed since the
+			 * decryption is inplace, drop it */
+			IWL_DEBUG_RX(priv, "Packet destroyed\n");
+			return -1;
+		}
+	case RX_RES_STATUS_SEC_TYPE_CCMP:
+		if ((decrypt_res & RX_RES_STATUS_DECRYPT_TYPE_MSK) ==
+		    RX_RES_STATUS_DECRYPT_OK) {
+			IWL_DEBUG_RX(priv, "hw decrypt successfully!!!\n");
+			stats->flag |= RX_FLAG_DECRYPTED;
+		}
+		break;
+
+	default:
+		break;
+	}
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_set_decrypted_flag);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-scan.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-scan.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-scan.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,625 @@
+/******************************************************************************
+ *
+ * GPL LICENSE SUMMARY
+ *
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.GPL.
+ *
+ * Contact Information:
+ *  Intel Linux Wireless <ilw@linux.intel.com>
+ * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+ *****************************************************************************/
+#include <linux/slab.h>
+#include <linux/types.h>
+#include <linux/etherdevice.h>
+#include <net/mac80211.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+/* For active scan, listen ACTIVE_DWELL_TIME (msec) on each channel after
+ * sending probe req.  This should be set long enough to hear probe responses
+ * from more than one AP.  */
+#define IWL_ACTIVE_DWELL_TIME_24    (30)       /* all times in msec */
+#define IWL_ACTIVE_DWELL_TIME_52    (20)
+
+#define IWL_ACTIVE_DWELL_FACTOR_24GHZ (3)
+#define IWL_ACTIVE_DWELL_FACTOR_52GHZ (2)
+
+/* For passive scan, listen PASSIVE_DWELL_TIME (msec) on each channel.
+ * Must be set longer than active dwell time.
+ * For the most reliable scan, set > AP beacon interval (typically 100msec). */
+#define IWL_PASSIVE_DWELL_TIME_24   (20)       /* all times in msec */
+#define IWL_PASSIVE_DWELL_TIME_52   (10)
+#define IWL_PASSIVE_DWELL_BASE      (100)
+#define IWL_CHANNEL_TUNE_TIME       5
+
+static int iwl_legacy_send_scan_abort(struct iwl_priv *priv)
+{
+	int ret;
+	struct iwl_rx_packet *pkt;
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_SCAN_ABORT_CMD,
+		.flags = CMD_WANT_SKB,
+	};
+
+	/* Exit instantly with error when device is not ready
+	 * to receive scan abort command or it does not perform
+	 * hardware scan currently */
+	if (!test_bit(STATUS_READY, &priv->status) ||
+	    !test_bit(STATUS_GEO_CONFIGURED, &priv->status) ||
+	    !test_bit(STATUS_SCAN_HW, &priv->status) ||
+	    test_bit(STATUS_FW_ERROR, &priv->status) ||
+	    test_bit(STATUS_EXIT_PENDING, &priv->status))
+		return -EIO;
+
+	ret = iwl_legacy_send_cmd_sync(priv, &cmd);
+	if (ret)
+		return ret;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->u.status != CAN_ABORT_STATUS) {
+		/* The scan abort will return 1 for success or
+		 * 2 for "failure".  A failure condition can be
+		 * due to simply not being in an active scan which
+		 * can occur if we send the scan abort before we
+		 * the microcode has notified us that a scan is
+		 * completed. */
+		IWL_DEBUG_SCAN(priv, "SCAN_ABORT ret %d.\n", pkt->u.status);
+		ret = -EIO;
+	}
+
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+	return ret;
+}
+
+static void iwl_legacy_complete_scan(struct iwl_priv *priv, bool aborted)
+{
+	/* check if scan was requested from mac80211 */
+	if (priv->scan_request) {
+		IWL_DEBUG_SCAN(priv, "Complete scan in mac80211\n");
+		ieee80211_scan_completed(priv->hw, aborted);
+	}
+
+	priv->is_internal_short_scan = false;
+	priv->scan_vif = NULL;
+	priv->scan_request = NULL;
+}
+
+void iwl_legacy_force_scan_end(struct iwl_priv *priv)
+{
+	lockdep_assert_held(&priv->mutex);
+
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Forcing scan end while not scanning\n");
+		return;
+	}
+
+	IWL_DEBUG_SCAN(priv, "Forcing scan end\n");
+	clear_bit(STATUS_SCANNING, &priv->status);
+	clear_bit(STATUS_SCAN_HW, &priv->status);
+	clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+	iwl_legacy_complete_scan(priv, true);
+}
+
+static void iwl_legacy_do_scan_abort(struct iwl_priv *priv)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Not performing scan to abort\n");
+		return;
+	}
+
+	if (test_and_set_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan abort in progress\n");
+		return;
+	}
+
+	ret = iwl_legacy_send_scan_abort(priv);
+	if (ret) {
+		IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
+		iwl_legacy_force_scan_end(priv);
+	} else
+		IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n");
+}
+
+/**
+ * iwl_scan_cancel - Cancel any currently executing HW scan
+ */
+int iwl_legacy_scan_cancel(struct iwl_priv *priv)
+{
+	IWL_DEBUG_SCAN(priv, "Queuing abort scan\n");
+	queue_work(priv->workqueue, &priv->abort_scan);
+	return 0;
+}
+EXPORT_SYMBOL(iwl_legacy_scan_cancel);
+
+/**
+ * iwl_legacy_scan_cancel_timeout - Cancel any currently executing HW scan
+ * @ms: amount of time to wait (in milliseconds) for scan to abort
+ *
+ */
+int iwl_legacy_scan_cancel_timeout(struct iwl_priv *priv, unsigned long ms)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(ms);
+
+	lockdep_assert_held(&priv->mutex);
+
+	IWL_DEBUG_SCAN(priv, "Scan cancel timeout\n");
+
+	iwl_legacy_do_scan_abort(priv);
+
+	while (time_before_eq(jiffies, timeout)) {
+		if (!test_bit(STATUS_SCAN_HW, &priv->status))
+			break;
+		msleep(20);
+	}
+
+	return test_bit(STATUS_SCAN_HW, &priv->status);
+}
+EXPORT_SYMBOL(iwl_legacy_scan_cancel_timeout);
+
+/* Service response to REPLY_SCAN_CMD (0x80) */
+static void iwl_legacy_rx_reply_scan(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scanreq_notification *notif =
+	    (struct iwl_scanreq_notification *)pkt->u.raw;
+
+	IWL_DEBUG_SCAN(priv, "Scan request status = 0x%x\n", notif->status);
+#endif
+}
+
+/* Service SCAN_START_NOTIFICATION (0x82) */
+static void iwl_legacy_rx_scan_start_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scanstart_notification *notif =
+	    (struct iwl_scanstart_notification *)pkt->u.raw;
+	priv->scan_start_tsf = le32_to_cpu(notif->tsf_low);
+	IWL_DEBUG_SCAN(priv, "Scan start: "
+		       "%d [802.11%s] "
+		       "(TSF: 0x%08X:%08X) - %d (beacon timer %u)\n",
+		       notif->channel,
+		       notif->band ? "bg" : "a",
+		       le32_to_cpu(notif->tsf_high),
+		       le32_to_cpu(notif->tsf_low),
+		       notif->status, notif->beacon_timer);
+}
+
+/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
+static void iwl_legacy_rx_scan_results_notif(struct iwl_priv *priv,
+				      struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scanresults_notification *notif =
+	    (struct iwl_scanresults_notification *)pkt->u.raw;
+
+	IWL_DEBUG_SCAN(priv, "Scan ch.res: "
+		       "%d [802.11%s] "
+		       "(TSF: 0x%08X:%08X) - %d "
+		       "elapsed=%lu usec\n",
+		       notif->channel,
+		       notif->band ? "bg" : "a",
+		       le32_to_cpu(notif->tsf_high),
+		       le32_to_cpu(notif->tsf_low),
+		       le32_to_cpu(notif->statistics[0]),
+		       le32_to_cpu(notif->tsf_low) - priv->scan_start_tsf);
+#endif
+}
+
+/* Service SCAN_COMPLETE_NOTIFICATION (0x84) */
+static void iwl_legacy_rx_scan_complete_notif(struct iwl_priv *priv,
+				       struct iwl_rx_mem_buffer *rxb)
+{
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_scancomplete_notification *scan_notif = (void *)pkt->u.raw;
+#endif
+
+	IWL_DEBUG_SCAN(priv,
+			"Scan complete: %d channels (TSF 0x%08X:%08X) - %d\n",
+		       scan_notif->scanned_channels,
+		       scan_notif->tsf_low,
+		       scan_notif->tsf_high, scan_notif->status);
+
+	/* The HW is no longer scanning */
+	clear_bit(STATUS_SCAN_HW, &priv->status);
+
+	IWL_DEBUG_SCAN(priv, "Scan on %sGHz took %dms\n",
+		       (priv->scan_band == IEEE80211_BAND_2GHZ) ? "2.4" : "5.2",
+		       jiffies_to_msecs(jiffies - priv->scan_start));
+
+	queue_work(priv->workqueue, &priv->scan_completed);
+}
+
+void iwl_legacy_setup_rx_scan_handlers(struct iwl_priv *priv)
+{
+	/* scan handlers */
+	priv->rx_handlers[REPLY_SCAN_CMD] = iwl_legacy_rx_reply_scan;
+	priv->rx_handlers[SCAN_START_NOTIFICATION] =
+					iwl_legacy_rx_scan_start_notif;
+	priv->rx_handlers[SCAN_RESULTS_NOTIFICATION] =
+					iwl_legacy_rx_scan_results_notif;
+	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
+					iwl_legacy_rx_scan_complete_notif;
+}
+EXPORT_SYMBOL(iwl_legacy_setup_rx_scan_handlers);
+
+inline u16 iwl_legacy_get_active_dwell_time(struct iwl_priv *priv,
+				     enum ieee80211_band band,
+				     u8 n_probes)
+{
+	if (band == IEEE80211_BAND_5GHZ)
+		return IWL_ACTIVE_DWELL_TIME_52 +
+			IWL_ACTIVE_DWELL_FACTOR_52GHZ * (n_probes + 1);
+	else
+		return IWL_ACTIVE_DWELL_TIME_24 +
+			IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
+}
+EXPORT_SYMBOL(iwl_legacy_get_active_dwell_time);
+
+u16 iwl_legacy_get_passive_dwell_time(struct iwl_priv *priv,
+			       enum ieee80211_band band,
+			       struct ieee80211_vif *vif)
+{
+	struct iwl_rxon_context *ctx;
+	u16 passive = (band == IEEE80211_BAND_2GHZ) ?
+	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_24 :
+	    IWL_PASSIVE_DWELL_BASE + IWL_PASSIVE_DWELL_TIME_52;
+
+	if (iwl_legacy_is_any_associated(priv)) {
+		/*
+		 * If we're associated, we clamp the maximum passive
+		 * dwell time to be 98% of the smallest beacon interval
+		 * (minus 2 * channel tune time)
+		 */
+		for_each_context(priv, ctx) {
+			u16 value;
+
+			if (!iwl_legacy_is_associated_ctx(ctx))
+				continue;
+			value = ctx->vif ? ctx->vif->bss_conf.beacon_int : 0;
+			if ((value > IWL_PASSIVE_DWELL_BASE) || !value)
+				value = IWL_PASSIVE_DWELL_BASE;
+			value = (value * 98) / 100 - IWL_CHANNEL_TUNE_TIME * 2;
+			passive = min(value, passive);
+		}
+	}
+
+	return passive;
+}
+EXPORT_SYMBOL(iwl_legacy_get_passive_dwell_time);
+
+void iwl_legacy_init_scan_params(struct iwl_priv *priv)
+{
+	u8 ant_idx = fls(priv->hw_params.valid_tx_ant) - 1;
+	if (!priv->scan_tx_ant[IEEE80211_BAND_5GHZ])
+		priv->scan_tx_ant[IEEE80211_BAND_5GHZ] = ant_idx;
+	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
+		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
+}
+EXPORT_SYMBOL(iwl_legacy_init_scan_params);
+
+static int __must_check iwl_legacy_scan_initiate(struct iwl_priv *priv,
+					  struct ieee80211_vif *vif,
+					  bool internal,
+					  enum ieee80211_band band)
+{
+	int ret;
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (WARN_ON(!priv->cfg->ops->utils->request_scan))
+		return -EOPNOTSUPP;
+
+	cancel_delayed_work(&priv->scan_check);
+
+	if (!iwl_legacy_is_ready_rf(priv)) {
+		IWL_WARN(priv, "Request scan called when driver not ready.\n");
+		return -EIO;
+	}
+
+	if (test_bit(STATUS_SCAN_HW, &priv->status)) {
+		IWL_DEBUG_SCAN(priv,
+			"Multiple concurrent scan requests in parallel.\n");
+		return -EBUSY;
+	}
+
+	if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan request while abort pending.\n");
+		return -EBUSY;
+	}
+
+	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
+			internal ? "internal short " : "");
+
+	set_bit(STATUS_SCANNING, &priv->status);
+	priv->is_internal_short_scan = internal;
+	priv->scan_start = jiffies;
+	priv->scan_band = band;
+
+	ret = priv->cfg->ops->utils->request_scan(priv, vif);
+	if (ret) {
+		clear_bit(STATUS_SCANNING, &priv->status);
+		priv->is_internal_short_scan = false;
+		return ret;
+	}
+
+	queue_delayed_work(priv->workqueue, &priv->scan_check,
+			   IWL_SCAN_CHECK_WATCHDOG);
+
+	return 0;
+}
+
+int iwl_legacy_mac_hw_scan(struct ieee80211_hw *hw,
+		    struct ieee80211_vif *vif,
+		    struct cfg80211_scan_request *req)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	IWL_DEBUG_MAC80211(priv, "enter\n");
+
+	if (req->n_channels == 0)
+		return -EINVAL;
+
+	mutex_lock(&priv->mutex);
+
+	if (test_bit(STATUS_SCANNING, &priv->status) &&
+	    !priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+		ret = -EAGAIN;
+		goto out_unlock;
+	}
+
+	/* mac80211 will only ask for one band at a time */
+	priv->scan_request = req;
+	priv->scan_vif = vif;
+
+	/*
+	 * If an internal scan is in progress, just set
+	 * up the scan_request as per above.
+	 */
+	if (priv->is_internal_short_scan) {
+		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
+		ret = 0;
+	} else
+		ret = iwl_legacy_scan_initiate(priv, vif, false,
+					req->channels[0]->band);
+
+	IWL_DEBUG_MAC80211(priv, "leave\n");
+
+out_unlock:
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_hw_scan);
+
+/*
+ * internal short scan, this function should only been called while associated.
+ * It will reset and tune the radio to prevent possible RF related problem
+ */
+void iwl_legacy_internal_short_hw_scan(struct iwl_priv *priv)
+{
+	queue_work(priv->workqueue, &priv->start_internal_scan);
+}
+
+static void iwl_legacy_bg_start_internal_scan(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+		container_of(work, struct iwl_priv, start_internal_scan);
+
+	IWL_DEBUG_SCAN(priv, "Start internal scan\n");
+
+	mutex_lock(&priv->mutex);
+
+	if (priv->is_internal_short_scan == true) {
+		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
+		goto unlock;
+	}
+
+	if (test_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
+		goto unlock;
+	}
+
+	if (iwl_legacy_scan_initiate(priv, NULL, true, priv->band))
+		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
+ unlock:
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl_legacy_bg_scan_check(struct work_struct *data)
+{
+	struct iwl_priv *priv =
+	    container_of(data, struct iwl_priv, scan_check.work);
+
+	IWL_DEBUG_SCAN(priv, "Scan check work\n");
+
+	/* Since we are here firmware does not finish scan and
+	 * most likely is in bad shape, so we don't bother to
+	 * send abort command, just force scan complete to mac80211 */
+	mutex_lock(&priv->mutex);
+	iwl_legacy_force_scan_end(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+/**
+ * iwl_legacy_fill_probe_req - fill in all required fields and IE for probe request
+ */
+
+u16
+iwl_legacy_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
+		       const u8 *ta, const u8 *ies, int ie_len, int left)
+{
+	int len = 0;
+	u8 *pos = NULL;
+
+	/* Make sure there is enough space for the probe request,
+	 * two mandatory IEs and the data */
+	left -= 24;
+	if (left < 0)
+		return 0;
+
+	frame->frame_control = cpu_to_le16(IEEE80211_STYPE_PROBE_REQ);
+	memcpy(frame->da, iwlegacy_bcast_addr, ETH_ALEN);
+	memcpy(frame->sa, ta, ETH_ALEN);
+	memcpy(frame->bssid, iwlegacy_bcast_addr, ETH_ALEN);
+	frame->seq_ctrl = 0;
+
+	len += 24;
+
+	/* ...next IE... */
+	pos = &frame->u.probe_req.variable[0];
+
+	/* fill in our indirect SSID IE */
+	left -= 2;
+	if (left < 0)
+		return 0;
+	*pos++ = WLAN_EID_SSID;
+	*pos++ = 0;
+
+	len += 2;
+
+	if (WARN_ON(left < ie_len))
+		return len;
+
+	if (ies && ie_len) {
+		memcpy(pos, ies, ie_len);
+		len += ie_len;
+	}
+
+	return (u16)len;
+}
+EXPORT_SYMBOL(iwl_legacy_fill_probe_req);
+
+static void iwl_legacy_bg_abort_scan(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv, abort_scan);
+
+	IWL_DEBUG_SCAN(priv, "Abort scan work\n");
+
+	/* We keep scan_check work queued in case when firmware will not
+	 * report back scan completed notification */
+	mutex_lock(&priv->mutex);
+	iwl_legacy_scan_cancel_timeout(priv, 200);
+	mutex_unlock(&priv->mutex);
+}
+
+static void iwl_legacy_bg_scan_completed(struct work_struct *work)
+{
+	struct iwl_priv *priv =
+	    container_of(work, struct iwl_priv, scan_completed);
+	bool aborted;
+
+	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
+		       priv->is_internal_short_scan ? "internal short " : "");
+
+	cancel_delayed_work(&priv->scan_check);
+
+	mutex_lock(&priv->mutex);
+
+	aborted = test_and_clear_bit(STATUS_SCAN_ABORTING, &priv->status);
+	if (aborted)
+		IWL_DEBUG_SCAN(priv, "Aborted scan completed.\n");
+
+	if (!test_and_clear_bit(STATUS_SCANNING, &priv->status)) {
+		IWL_DEBUG_SCAN(priv, "Scan already completed.\n");
+		goto out_settings;
+	}
+
+	if (priv->is_internal_short_scan && !aborted) {
+		int err;
+
+		/* Check if mac80211 requested scan during our internal scan */
+		if (priv->scan_request == NULL)
+			goto out_complete;
+
+		/* If so request a new scan */
+		err = iwl_legacy_scan_initiate(priv, priv->scan_vif, false,
+					priv->scan_request->channels[0]->band);
+		if (err) {
+			IWL_DEBUG_SCAN(priv,
+				"failed to initiate pending scan: %d\n", err);
+			aborted = true;
+			goto out_complete;
+		}
+
+		goto out;
+	}
+
+out_complete:
+	iwl_legacy_complete_scan(priv, aborted);
+
+out_settings:
+	/* Can we still talk to firmware ? */
+	if (!iwl_legacy_is_ready_rf(priv))
+		goto out;
+
+	/*
+	 * We do not commit power settings while scan is pending,
+	 * do it now if the settings changed.
+	 */
+	iwl_legacy_power_set_mode(priv, &priv->power_data.sleep_cmd_next,
+								false);
+	iwl_legacy_set_tx_power(priv, priv->tx_power_next, false);
+
+	priv->cfg->ops->utils->post_scan(priv);
+
+out:
+	mutex_unlock(&priv->mutex);
+}
+
+void iwl_legacy_setup_scan_deferred_work(struct iwl_priv *priv)
+{
+	INIT_WORK(&priv->scan_completed, iwl_legacy_bg_scan_completed);
+	INIT_WORK(&priv->abort_scan, iwl_legacy_bg_abort_scan);
+	INIT_WORK(&priv->start_internal_scan,
+				iwl_legacy_bg_start_internal_scan);
+	INIT_DELAYED_WORK(&priv->scan_check, iwl_legacy_bg_scan_check);
+}
+EXPORT_SYMBOL(iwl_legacy_setup_scan_deferred_work);
+
+void iwl_legacy_cancel_scan_deferred_work(struct iwl_priv *priv)
+{
+	cancel_work_sync(&priv->start_internal_scan);
+	cancel_work_sync(&priv->abort_scan);
+	cancel_work_sync(&priv->scan_completed);
+
+	if (cancel_delayed_work_sync(&priv->scan_check)) {
+		mutex_lock(&priv->mutex);
+		iwl_legacy_force_scan_end(priv);
+		mutex_unlock(&priv->mutex);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_cancel_scan_deferred_work);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-spectrum.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-spectrum.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-spectrum.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-spectrum.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,92 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 Intel Corporation. All rights reserved.
+ *
+ * Portions of this file are derived from 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_legacy_spectrum_h__
+#define __iwl_legacy_spectrum_h__
+enum {				/* ieee80211_basic_report.map */
+	IEEE80211_BASIC_MAP_BSS = (1 << 0),
+	IEEE80211_BASIC_MAP_OFDM = (1 << 1),
+	IEEE80211_BASIC_MAP_UNIDENTIFIED = (1 << 2),
+	IEEE80211_BASIC_MAP_RADAR = (1 << 3),
+	IEEE80211_BASIC_MAP_UNMEASURED = (1 << 4),
+	/* Bits 5-7 are reserved */
+
+};
+struct ieee80211_basic_report {
+	u8 channel;
+	__le64 start_time;
+	__le16 duration;
+	u8 map;
+} __packed;
+
+enum {				/* ieee80211_measurement_request.mode */
+	/* Bit 0 is reserved */
+	IEEE80211_MEASUREMENT_ENABLE = (1 << 1),
+	IEEE80211_MEASUREMENT_REQUEST = (1 << 2),
+	IEEE80211_MEASUREMENT_REPORT = (1 << 3),
+	/* Bits 4-7 are reserved */
+};
+
+enum {
+	IEEE80211_REPORT_BASIC = 0,	/* required */
+	IEEE80211_REPORT_CCA = 1,	/* optional */
+	IEEE80211_REPORT_RPI = 2,	/* optional */
+	/* 3-255 reserved */
+};
+
+struct ieee80211_measurement_params {
+	u8 channel;
+	__le64 start_time;
+	__le16 duration;
+} __packed;
+
+struct ieee80211_info_element {
+	u8 id;
+	u8 len;
+	u8 data[0];
+} __packed;
+
+struct ieee80211_measurement_request {
+	struct ieee80211_info_element ie;
+	u8 token;
+	u8 mode;
+	u8 type;
+	struct ieee80211_measurement_params params[0];
+} __packed;
+
+struct ieee80211_measurement_report {
+	struct ieee80211_info_element ie;
+	u8 token;
+	u8 mode;
+	u8 type;
+	union {
+		struct ieee80211_basic_report basic[0];
+	} u;
+} __packed;
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-sta.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-sta.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-sta.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-sta.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,816 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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 <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/lockdep.h>
+
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+
+/* priv->sta_lock must be held */
+static void iwl_legacy_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
+{
+
+	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
+		IWL_ERR(priv,
+			"ACTIVATE a non DRIVER active station id %u addr %pM\n",
+			sta_id, priv->stations[sta_id].sta.sta.addr);
+
+	if (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) {
+		IWL_DEBUG_ASSOC(priv,
+			"STA id %u addr %pM already present"
+			" in uCode (according to driver)\n",
+			sta_id, priv->stations[sta_id].sta.sta.addr);
+	} else {
+		priv->stations[sta_id].used |= IWL_STA_UCODE_ACTIVE;
+		IWL_DEBUG_ASSOC(priv, "Added STA id %u addr %pM to uCode\n",
+				sta_id, priv->stations[sta_id].sta.sta.addr);
+	}
+}
+
+static int iwl_legacy_process_add_sta_resp(struct iwl_priv *priv,
+				    struct iwl_legacy_addsta_cmd *addsta,
+				    struct iwl_rx_packet *pkt,
+				    bool sync)
+{
+	u8 sta_id = addsta->sta.sta_id;
+	unsigned long flags;
+	int ret = -EIO;
+
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_ADD_STA (0x%08X)\n",
+			pkt->hdr.flags);
+		return ret;
+	}
+
+	IWL_DEBUG_INFO(priv, "Processing response for adding station %u\n",
+		       sta_id);
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	switch (pkt->u.add_sta.status) {
+	case ADD_STA_SUCCESS_MSK:
+		IWL_DEBUG_INFO(priv, "REPLY_ADD_STA PASSED\n");
+		iwl_legacy_sta_ucode_activate(priv, sta_id);
+		ret = 0;
+		break;
+	case ADD_STA_NO_ROOM_IN_TABLE:
+		IWL_ERR(priv, "Adding station %d failed, no room in table.\n",
+			sta_id);
+		break;
+	case ADD_STA_NO_BLOCK_ACK_RESOURCE:
+		IWL_ERR(priv,
+			"Adding station %d failed, no block ack resource.\n",
+			sta_id);
+		break;
+	case ADD_STA_MODIFY_NON_EXIST_STA:
+		IWL_ERR(priv, "Attempting to modify non-existing station %d\n",
+			sta_id);
+		break;
+	default:
+		IWL_DEBUG_ASSOC(priv, "Received REPLY_ADD_STA:(0x%08X)\n",
+				pkt->u.add_sta.status);
+		break;
+	}
+
+	IWL_DEBUG_INFO(priv, "%s station id %u addr %pM\n",
+		       priv->stations[sta_id].sta.mode ==
+		       STA_CONTROL_MODIFY_MSK ?  "Modified" : "Added",
+		       sta_id, priv->stations[sta_id].sta.sta.addr);
+
+	/*
+	 * XXX: The MAC address in the command buffer is often changed from
+	 * the original sent to the device. That is, the MAC address
+	 * written to the command buffer often is not the same MAC address
+	 * read from the command buffer when the command returns. This
+	 * issue has not yet been resolved and this debugging is left to
+	 * observe the problem.
+	 */
+	IWL_DEBUG_INFO(priv, "%s station according to cmd buffer %pM\n",
+		       priv->stations[sta_id].sta.mode ==
+		       STA_CONTROL_MODIFY_MSK ? "Modified" : "Added",
+		       addsta->sta.addr);
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return ret;
+}
+
+static void iwl_legacy_add_sta_callback(struct iwl_priv *priv,
+				 struct iwl_device_cmd *cmd,
+				 struct iwl_rx_packet *pkt)
+{
+	struct iwl_legacy_addsta_cmd *addsta =
+		(struct iwl_legacy_addsta_cmd *)cmd->cmd.payload;
+
+	iwl_legacy_process_add_sta_resp(priv, addsta, pkt, false);
+
+}
+
+int iwl_legacy_send_add_sta(struct iwl_priv *priv,
+		     struct iwl_legacy_addsta_cmd *sta, u8 flags)
+{
+	struct iwl_rx_packet *pkt = NULL;
+	int ret = 0;
+	u8 data[sizeof(*sta)];
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_ADD_STA,
+		.flags = flags,
+		.data = data,
+	};
+	u8 sta_id __maybe_unused = sta->sta.sta_id;
+
+	IWL_DEBUG_INFO(priv, "Adding sta %u (%pM) %ssynchronously\n",
+		       sta_id, sta->sta.addr, flags & CMD_ASYNC ?  "a" : "");
+
+	if (flags & CMD_ASYNC)
+		cmd.callback = iwl_legacy_add_sta_callback;
+	else {
+		cmd.flags |= CMD_WANT_SKB;
+		might_sleep();
+	}
+
+	cmd.len = priv->cfg->ops->utils->build_addsta_hcmd(sta, data);
+	ret = iwl_legacy_send_cmd(priv, &cmd);
+
+	if (ret || (flags & CMD_ASYNC))
+		return ret;
+
+	if (ret == 0) {
+		pkt = (struct iwl_rx_packet *)cmd.reply_page;
+		ret = iwl_legacy_process_add_sta_resp(priv, sta, pkt, true);
+	}
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_send_add_sta);
+
+static void iwl_legacy_set_ht_add_station(struct iwl_priv *priv, u8 index,
+				   struct ieee80211_sta *sta,
+				   struct iwl_rxon_context *ctx)
+{
+	struct ieee80211_sta_ht_cap *sta_ht_inf = &sta->ht_cap;
+	__le32 sta_flags;
+	u8 mimo_ps_mode;
+
+	if (!sta || !sta_ht_inf->ht_supported)
+		goto done;
+
+	mimo_ps_mode = (sta_ht_inf->cap & IEEE80211_HT_CAP_SM_PS) >> 2;
+	IWL_DEBUG_ASSOC(priv, "spatial multiplexing power save mode: %s\n",
+			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_STATIC) ?
+			"static" :
+			(mimo_ps_mode == WLAN_HT_CAP_SM_PS_DYNAMIC) ?
+			"dynamic" : "disabled");
+
+	sta_flags = priv->stations[index].sta.station_flags;
+
+	sta_flags &= ~(STA_FLG_RTS_MIMO_PROT_MSK | STA_FLG_MIMO_DIS_MSK);
+
+	switch (mimo_ps_mode) {
+	case WLAN_HT_CAP_SM_PS_STATIC:
+		sta_flags |= STA_FLG_MIMO_DIS_MSK;
+		break;
+	case WLAN_HT_CAP_SM_PS_DYNAMIC:
+		sta_flags |= STA_FLG_RTS_MIMO_PROT_MSK;
+		break;
+	case WLAN_HT_CAP_SM_PS_DISABLED:
+		break;
+	default:
+		IWL_WARN(priv, "Invalid MIMO PS mode %d\n", mimo_ps_mode);
+		break;
+	}
+
+	sta_flags |= cpu_to_le32(
+	      (u32)sta_ht_inf->ampdu_factor << STA_FLG_MAX_AGG_SIZE_POS);
+
+	sta_flags |= cpu_to_le32(
+	      (u32)sta_ht_inf->ampdu_density << STA_FLG_AGG_MPDU_DENSITY_POS);
+
+	if (iwl_legacy_is_ht40_tx_allowed(priv, ctx, &sta->ht_cap))
+		sta_flags |= STA_FLG_HT40_EN_MSK;
+	else
+		sta_flags &= ~STA_FLG_HT40_EN_MSK;
+
+	priv->stations[index].sta.station_flags = sta_flags;
+ done:
+	return;
+}
+
+/**
+ * iwl_legacy_prep_station - Prepare station information for addition
+ *
+ * should be called with sta_lock held
+ */
+u8 iwl_legacy_prep_station(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		    const u8 *addr, bool is_ap, struct ieee80211_sta *sta)
+{
+	struct iwl_station_entry *station;
+	int i;
+	u8 sta_id = IWL_INVALID_STATION;
+	u16 rate;
+
+	if (is_ap)
+		sta_id = ctx->ap_sta_id;
+	else if (is_broadcast_ether_addr(addr))
+		sta_id = ctx->bcast_sta_id;
+	else
+		for (i = IWL_STA_ID; i < priv->hw_params.max_stations; i++) {
+			if (!compare_ether_addr(priv->stations[i].sta.sta.addr,
+						addr)) {
+				sta_id = i;
+				break;
+			}
+
+			if (!priv->stations[i].used &&
+			    sta_id == IWL_INVALID_STATION)
+				sta_id = i;
+		}
+
+	/*
+	 * These two conditions have the same outcome, but keep them
+	 * separate
+	 */
+	if (unlikely(sta_id == IWL_INVALID_STATION))
+		return sta_id;
+
+	/*
+	 * uCode is not able to deal with multiple requests to add a
+	 * station. Keep track if one is in progress so that we do not send
+	 * another.
+	 */
+	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
+		IWL_DEBUG_INFO(priv,
+				"STA %d already in process of being added.\n",
+				sta_id);
+		return sta_id;
+	}
+
+	if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE) &&
+	    !compare_ether_addr(priv->stations[sta_id].sta.sta.addr, addr)) {
+		IWL_DEBUG_ASSOC(priv,
+				"STA %d (%pM) already added, not adding again.\n",
+				sta_id, addr);
+		return sta_id;
+	}
+
+	station = &priv->stations[sta_id];
+	station->used = IWL_STA_DRIVER_ACTIVE;
+	IWL_DEBUG_ASSOC(priv, "Add STA to driver ID %d: %pM\n",
+			sta_id, addr);
+	priv->num_stations++;
+
+	/* Set up the REPLY_ADD_STA command to send to device */
+	memset(&station->sta, 0, sizeof(struct iwl_legacy_addsta_cmd));
+	memcpy(station->sta.sta.addr, addr, ETH_ALEN);
+	station->sta.mode = 0;
+	station->sta.sta.sta_id = sta_id;
+	station->sta.station_flags = ctx->station_flags;
+	station->ctxid = ctx->ctxid;
+
+	if (sta) {
+		struct iwl_station_priv_common *sta_priv;
+
+		sta_priv = (void *)sta->drv_priv;
+		sta_priv->ctx = ctx;
+	}
+
+	/*
+	 * OK to call unconditionally, since local stations (IBSS BSSID
+	 * STA and broadcast STA) pass in a NULL sta, and mac80211
+	 * doesn't allow HT IBSS.
+	 */
+	iwl_legacy_set_ht_add_station(priv, sta_id, sta, ctx);
+
+	/* 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);
+
+	return sta_id;
+
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_prep_station);
+
+#define STA_WAIT_TIMEOUT (HZ/2)
+
+/**
+ * iwl_legacy_add_station_common -
+ */
+int
+iwl_legacy_add_station_common(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			   const u8 *addr, bool is_ap,
+			   struct ieee80211_sta *sta, u8 *sta_id_r)
+{
+	unsigned long flags_spin;
+	int ret = 0;
+	u8 sta_id;
+	struct iwl_legacy_addsta_cmd sta_cmd;
+
+	*sta_id_r = 0;
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	sta_id = iwl_legacy_prep_station(priv, ctx, addr, is_ap, sta);
+	if (sta_id == IWL_INVALID_STATION) {
+		IWL_ERR(priv, "Unable to prepare station %pM for addition\n",
+			addr);
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EINVAL;
+	}
+
+	/*
+	 * uCode is not able to deal with multiple requests to add a
+	 * station. Keep track if one is in progress so that we do not send
+	 * another.
+	 */
+	if (priv->stations[sta_id].used & IWL_STA_UCODE_INPROGRESS) {
+		IWL_DEBUG_INFO(priv,
+			"STA %d already in process of being added.\n",
+		       sta_id);
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EEXIST;
+	}
+
+	if ((priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE) &&
+	    (priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+		IWL_DEBUG_ASSOC(priv,
+			"STA %d (%pM) already added, not adding again.\n",
+			sta_id, addr);
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EEXIST;
+	}
+
+	priv->stations[sta_id].used |= IWL_STA_UCODE_INPROGRESS;
+	memcpy(&sta_cmd, &priv->stations[sta_id].sta,
+				sizeof(struct iwl_legacy_addsta_cmd));
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	/* Add station to device's station table */
+	ret = iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+	if (ret) {
+		spin_lock_irqsave(&priv->sta_lock, flags_spin);
+		IWL_ERR(priv, "Adding station %pM failed.\n",
+			priv->stations[sta_id].sta.sta.addr);
+		priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+		priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+	}
+	*sta_id_r = sta_id;
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_add_station_common);
+
+/**
+ * iwl_legacy_sta_ucode_deactivate - deactivate ucode status for a station
+ *
+ * priv->sta_lock must be held
+ */
+static void iwl_legacy_sta_ucode_deactivate(struct iwl_priv *priv, u8 sta_id)
+{
+	/* Ucode must be active and driver must be non active */
+	if ((priv->stations[sta_id].used &
+	     (IWL_STA_UCODE_ACTIVE | IWL_STA_DRIVER_ACTIVE)) !=
+						IWL_STA_UCODE_ACTIVE)
+		IWL_ERR(priv, "removed non active STA %u\n", sta_id);
+
+	priv->stations[sta_id].used &= ~IWL_STA_UCODE_ACTIVE;
+
+	memset(&priv->stations[sta_id], 0, sizeof(struct iwl_station_entry));
+	IWL_DEBUG_ASSOC(priv, "Removed STA %u\n", sta_id);
+}
+
+static int iwl_legacy_send_remove_station(struct iwl_priv *priv,
+				   const u8 *addr, int sta_id,
+				   bool temporary)
+{
+	struct iwl_rx_packet *pkt;
+	int ret;
+
+	unsigned long flags_spin;
+	struct iwl_rem_sta_cmd rm_sta_cmd;
+
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_REMOVE_STA,
+		.len = sizeof(struct iwl_rem_sta_cmd),
+		.flags = CMD_SYNC,
+		.data = &rm_sta_cmd,
+	};
+
+	memset(&rm_sta_cmd, 0, sizeof(rm_sta_cmd));
+	rm_sta_cmd.num_sta = 1;
+	memcpy(&rm_sta_cmd.addr, addr, ETH_ALEN);
+
+	cmd.flags |= CMD_WANT_SKB;
+
+	ret = iwl_legacy_send_cmd(priv, &cmd);
+
+	if (ret)
+		return ret;
+
+	pkt = (struct iwl_rx_packet *)cmd.reply_page;
+	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
+		IWL_ERR(priv, "Bad return from REPLY_REMOVE_STA (0x%08X)\n",
+			  pkt->hdr.flags);
+		ret = -EIO;
+	}
+
+	if (!ret) {
+		switch (pkt->u.rem_sta.status) {
+		case REM_STA_SUCCESS_MSK:
+			if (!temporary) {
+				spin_lock_irqsave(&priv->sta_lock, flags_spin);
+				iwl_legacy_sta_ucode_deactivate(priv, sta_id);
+				spin_unlock_irqrestore(&priv->sta_lock,
+								flags_spin);
+			}
+			IWL_DEBUG_ASSOC(priv, "REPLY_REMOVE_STA PASSED\n");
+			break;
+		default:
+			ret = -EIO;
+			IWL_ERR(priv, "REPLY_REMOVE_STA failed\n");
+			break;
+		}
+	}
+	iwl_legacy_free_pages(priv, cmd.reply_page);
+
+	return ret;
+}
+
+/**
+ * iwl_legacy_remove_station - Remove driver's knowledge of station.
+ */
+int iwl_legacy_remove_station(struct iwl_priv *priv, const u8 sta_id,
+		       const u8 *addr)
+{
+	unsigned long flags;
+
+	if (!iwl_legacy_is_ready(priv)) {
+		IWL_DEBUG_INFO(priv,
+			"Unable to remove station %pM, device not ready.\n",
+			addr);
+		/*
+		 * It is typical for stations to be removed when we are
+		 * going down. Return success since device will be down
+		 * soon anyway
+		 */
+		return 0;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "Removing STA from driver:%d  %pM\n",
+			sta_id, addr);
+
+	if (WARN_ON(sta_id == IWL_INVALID_STATION))
+		return -EINVAL;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+
+	if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		IWL_DEBUG_INFO(priv, "Removing %pM but non DRIVER active\n",
+				addr);
+		goto out_err;
+	}
+
+	if (!(priv->stations[sta_id].used & IWL_STA_UCODE_ACTIVE)) {
+		IWL_DEBUG_INFO(priv, "Removing %pM but non UCODE active\n",
+				addr);
+		goto out_err;
+	}
+
+	if (priv->stations[sta_id].used & IWL_STA_LOCAL) {
+		kfree(priv->stations[sta_id].lq);
+		priv->stations[sta_id].lq = NULL;
+	}
+
+	priv->stations[sta_id].used &= ~IWL_STA_DRIVER_ACTIVE;
+
+	priv->num_stations--;
+
+	BUG_ON(priv->num_stations < 0);
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+
+	return iwl_legacy_send_remove_station(priv, addr, sta_id, false);
+out_err:
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+	return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_remove_station);
+
+/**
+ * iwl_legacy_clear_ucode_stations - clear ucode station table bits
+ *
+ * This function clears all the bits in the driver indicating
+ * which stations are active in the ucode. Call when something
+ * other than explicit station management would cause this in
+ * the ucode, e.g. unassociated RXON.
+ */
+void iwl_legacy_clear_ucode_stations(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx)
+{
+	int i;
+	unsigned long flags_spin;
+	bool cleared = false;
+
+	IWL_DEBUG_INFO(priv, "Clearing ucode stations in driver\n");
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if (ctx && ctx->ctxid != priv->stations[i].ctxid)
+			continue;
+
+		if (priv->stations[i].used & IWL_STA_UCODE_ACTIVE) {
+			IWL_DEBUG_INFO(priv,
+				"Clearing ucode active for station %d\n", i);
+			priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+			cleared = true;
+		}
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	if (!cleared)
+		IWL_DEBUG_INFO(priv,
+			"No active stations found to be cleared\n");
+}
+EXPORT_SYMBOL(iwl_legacy_clear_ucode_stations);
+
+/**
+ * iwl_legacy_restore_stations() - Restore driver known stations to device
+ *
+ * All stations considered active by driver, but not present in ucode, is
+ * restored.
+ *
+ * Function sleeps.
+ */
+void
+iwl_legacy_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
+{
+	struct iwl_legacy_addsta_cmd sta_cmd;
+	struct iwl_link_quality_cmd lq;
+	unsigned long flags_spin;
+	int i;
+	bool found = false;
+	int ret;
+	bool send_lq;
+
+	if (!iwl_legacy_is_ready(priv)) {
+		IWL_DEBUG_INFO(priv,
+			"Not ready yet, not restoring any stations.\n");
+		return;
+	}
+
+	IWL_DEBUG_ASSOC(priv, "Restoring all known stations ... start.\n");
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if (ctx->ctxid != priv->stations[i].ctxid)
+			continue;
+		if ((priv->stations[i].used & IWL_STA_DRIVER_ACTIVE) &&
+			    !(priv->stations[i].used & IWL_STA_UCODE_ACTIVE)) {
+			IWL_DEBUG_ASSOC(priv, "Restoring sta %pM\n",
+					priv->stations[i].sta.sta.addr);
+			priv->stations[i].sta.mode = 0;
+			priv->stations[i].used |= IWL_STA_UCODE_INPROGRESS;
+			found = true;
+		}
+	}
+
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if ((priv->stations[i].used & IWL_STA_UCODE_INPROGRESS)) {
+			memcpy(&sta_cmd, &priv->stations[i].sta,
+			       sizeof(struct iwl_legacy_addsta_cmd));
+			send_lq = false;
+			if (priv->stations[i].lq) {
+				memcpy(&lq, priv->stations[i].lq,
+				       sizeof(struct iwl_link_quality_cmd));
+				send_lq = true;
+			}
+			spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+			ret = iwl_legacy_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+			if (ret) {
+				spin_lock_irqsave(&priv->sta_lock, flags_spin);
+				IWL_ERR(priv, "Adding station %pM failed.\n",
+					priv->stations[i].sta.sta.addr);
+				priv->stations[i].used &=
+						~IWL_STA_DRIVER_ACTIVE;
+				priv->stations[i].used &=
+						~IWL_STA_UCODE_INPROGRESS;
+				spin_unlock_irqrestore(&priv->sta_lock,
+								flags_spin);
+			}
+			/*
+			 * Rate scaling has already been initialized, send
+			 * current LQ command
+			 */
+			if (send_lq)
+				iwl_legacy_send_lq_cmd(priv, ctx, &lq,
+								CMD_SYNC, true);
+			spin_lock_irqsave(&priv->sta_lock, flags_spin);
+			priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
+		}
+	}
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+	if (!found)
+		IWL_DEBUG_INFO(priv, "Restoring all known stations"
+				" .... no stations to be restored.\n");
+	else
+		IWL_DEBUG_INFO(priv, "Restoring all known stations"
+				" .... complete.\n");
+}
+EXPORT_SYMBOL(iwl_legacy_restore_stations);
+
+int iwl_legacy_get_free_ucode_key_index(struct iwl_priv *priv)
+{
+	int i;
+
+	for (i = 0; i < priv->sta_key_max_num; i++)
+		if (!test_and_set_bit(i, &priv->ucode_key_table))
+			return i;
+
+	return WEP_INVALID_OFFSET;
+}
+EXPORT_SYMBOL(iwl_legacy_get_free_ucode_key_index);
+
+void iwl_legacy_dealloc_bcast_stations(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	for (i = 0; i < priv->hw_params.max_stations; i++) {
+		if (!(priv->stations[i].used & IWL_STA_BCAST))
+			continue;
+
+		priv->stations[i].used &= ~IWL_STA_UCODE_ACTIVE;
+		priv->num_stations--;
+		BUG_ON(priv->num_stations < 0);
+		kfree(priv->stations[i].lq);
+		priv->stations[i].lq = NULL;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+EXPORT_SYMBOL_GPL(iwl_legacy_dealloc_bcast_stations);
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+static void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
+			   struct iwl_link_quality_cmd *lq)
+{
+	int i;
+	IWL_DEBUG_RATE(priv, "lq station id 0x%x\n", lq->sta_id);
+	IWL_DEBUG_RATE(priv, "lq ant 0x%X 0x%X\n",
+		       lq->general_params.single_stream_ant_msk,
+		       lq->general_params.dual_stream_ant_msk);
+
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++)
+		IWL_DEBUG_RATE(priv, "lq index %d 0x%X\n",
+			       i, lq->rs_table[i].rate_n_flags);
+}
+#else
+static inline void iwl_legacy_dump_lq_cmd(struct iwl_priv *priv,
+				   struct iwl_link_quality_cmd *lq)
+{
+}
+#endif
+
+/**
+ * iwl_legacy_is_lq_table_valid() - Test one aspect of LQ cmd for validity
+ *
+ * It sometimes happens when a HT rate has been in use and we
+ * loose connectivity with AP then mac80211 will first tell us that the
+ * current channel is not HT anymore before removing the station. In such a
+ * scenario the RXON flags will be updated to indicate we are not
+ * communicating HT anymore, but the LQ command may still contain HT rates.
+ * Test for this to prevent driver from sending LQ command between the time
+ * RXON flags are updated and when LQ command is updated.
+ */
+static bool iwl_legacy_is_lq_table_valid(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx,
+			      struct iwl_link_quality_cmd *lq)
+{
+	int i;
+
+	if (ctx->ht.enabled)
+		return true;
+
+	IWL_DEBUG_INFO(priv, "Channel %u is not an HT channel\n",
+		       ctx->active.channel);
+	for (i = 0; i < LINK_QUAL_MAX_RETRY_NUM; i++) {
+		if (le32_to_cpu(lq->rs_table[i].rate_n_flags) &
+						RATE_MCS_HT_MSK) {
+			IWL_DEBUG_INFO(priv,
+				       "index %d of LQ expects HT channel\n",
+				       i);
+			return false;
+		}
+	}
+	return true;
+}
+
+/**
+ * iwl_legacy_send_lq_cmd() - Send link quality command
+ * @init: This command is sent as part of station initialization right
+ *        after station has been added.
+ *
+ * The link quality command is sent as the last step of station creation.
+ * This is the special case in which init is set and we call a callback in
+ * this case to clear the state indicating that station creation is in
+ * progress.
+ */
+int iwl_legacy_send_lq_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
+		    struct iwl_link_quality_cmd *lq, u8 flags, bool init)
+{
+	int ret = 0;
+	unsigned long flags_spin;
+
+	struct iwl_host_cmd cmd = {
+		.id = REPLY_TX_LINK_QUALITY_CMD,
+		.len = sizeof(struct iwl_link_quality_cmd),
+		.flags = flags,
+		.data = lq,
+	};
+
+	if (WARN_ON(lq->sta_id == IWL_INVALID_STATION))
+		return -EINVAL;
+
+
+	spin_lock_irqsave(&priv->sta_lock, flags_spin);
+	if (!(priv->stations[lq->sta_id].used & IWL_STA_DRIVER_ACTIVE)) {
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+		return -EINVAL;
+	}
+	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+
+	iwl_legacy_dump_lq_cmd(priv, lq);
+	BUG_ON(init && (cmd.flags & CMD_ASYNC));
+
+	if (iwl_legacy_is_lq_table_valid(priv, ctx, lq))
+		ret = iwl_legacy_send_cmd(priv, &cmd);
+	else
+		ret = -EINVAL;
+
+	if (cmd.flags & CMD_ASYNC)
+		return ret;
+
+	if (init) {
+		IWL_DEBUG_INFO(priv, "init LQ command complete,"
+				" clearing sta addition status for sta %d\n",
+			       lq->sta_id);
+		spin_lock_irqsave(&priv->sta_lock, flags_spin);
+		priv->stations[lq->sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
+		spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
+	}
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_send_lq_cmd);
+
+int iwl_legacy_mac_sta_remove(struct ieee80211_hw *hw,
+		       struct ieee80211_vif *vif,
+		       struct ieee80211_sta *sta)
+{
+	struct iwl_priv *priv = hw->priv;
+	struct iwl_station_priv_common *sta_common = (void *)sta->drv_priv;
+	int ret;
+
+	IWL_DEBUG_INFO(priv, "received request to remove station %pM\n",
+			sta->addr);
+	mutex_lock(&priv->mutex);
+	IWL_DEBUG_INFO(priv, "proceeding to remove station %pM\n",
+			sta->addr);
+	ret = iwl_legacy_remove_station(priv, sta_common->sta_id, sta->addr);
+	if (ret)
+		IWL_ERR(priv, "Error removing station %pM\n",
+			sta->addr);
+	mutex_unlock(&priv->mutex);
+	return ret;
+}
+EXPORT_SYMBOL(iwl_legacy_mac_sta_remove);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-sta.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-sta.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-sta.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-sta.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,148 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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_legacy_sta_h__
+#define __iwl_legacy_sta_h__
+
+#include "iwl-dev.h"
+
+#define HW_KEY_DYNAMIC 0
+#define HW_KEY_DEFAULT 1
+
+#define IWL_STA_DRIVER_ACTIVE BIT(0) /* driver entry is active */
+#define IWL_STA_UCODE_ACTIVE  BIT(1) /* ucode entry is active */
+#define IWL_STA_UCODE_INPROGRESS  BIT(2) /* ucode entry is in process of
+					    being activated */
+#define IWL_STA_LOCAL BIT(3) /* station state not directed by mac80211;
+				(this is for the IBSS BSSID stations) */
+#define IWL_STA_BCAST BIT(4) /* this station is the special bcast station */
+
+
+void iwl_legacy_restore_stations(struct iwl_priv *priv,
+				struct iwl_rxon_context *ctx);
+void iwl_legacy_clear_ucode_stations(struct iwl_priv *priv,
+			      struct iwl_rxon_context *ctx);
+void iwl_legacy_dealloc_bcast_stations(struct iwl_priv *priv);
+int iwl_legacy_get_free_ucode_key_index(struct iwl_priv *priv);
+int iwl_legacy_send_add_sta(struct iwl_priv *priv,
+			struct iwl_legacy_addsta_cmd *sta, u8 flags);
+int iwl_legacy_add_station_common(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			const u8 *addr, bool is_ap,
+			struct ieee80211_sta *sta, u8 *sta_id_r);
+int iwl_legacy_remove_station(struct iwl_priv *priv,
+			const u8 sta_id,
+			const u8 *addr);
+int iwl_legacy_mac_sta_remove(struct ieee80211_hw *hw,
+			struct ieee80211_vif *vif,
+			struct ieee80211_sta *sta);
+
+u8 iwl_legacy_prep_station(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			const u8 *addr, bool is_ap,
+			struct ieee80211_sta *sta);
+
+int iwl_legacy_send_lq_cmd(struct iwl_priv *priv,
+			struct iwl_rxon_context *ctx,
+			struct iwl_link_quality_cmd *lq,
+			u8 flags, bool init);
+
+/**
+ * iwl_legacy_clear_driver_stations - clear knowledge of all stations from driver
+ * @priv: iwl priv struct
+ *
+ * This is called during iwl_down() to make sure that in the case
+ * we're coming there from a hardware restart mac80211 will be
+ * able to reconfigure stations -- if we're getting there in the
+ * normal down flow then the stations will already be cleared.
+ */
+static inline void iwl_legacy_clear_driver_stations(struct iwl_priv *priv)
+{
+	unsigned long flags;
+	struct iwl_rxon_context *ctx;
+
+	spin_lock_irqsave(&priv->sta_lock, flags);
+	memset(priv->stations, 0, sizeof(priv->stations));
+	priv->num_stations = 0;
+
+	priv->ucode_key_table = 0;
+
+	for_each_context(priv, ctx) {
+		/*
+		 * Remove all key information that is not stored as part
+		 * of station information since mac80211 may not have had
+		 * a chance to remove all the keys. When device is
+		 * reconfigured by mac80211 after an error all keys will
+		 * be reconfigured.
+		 */
+		memset(ctx->wep_keys, 0, sizeof(ctx->wep_keys));
+		ctx->key_mapping_keys = 0;
+	}
+
+	spin_unlock_irqrestore(&priv->sta_lock, flags);
+}
+
+static inline int iwl_legacy_sta_id(struct ieee80211_sta *sta)
+{
+	if (WARN_ON(!sta))
+		return IWL_INVALID_STATION;
+
+	return ((struct iwl_station_priv_common *)sta->drv_priv)->sta_id;
+}
+
+/**
+ * iwl_legacy_sta_id_or_broadcast - return sta_id or broadcast sta
+ * @priv: iwl priv
+ * @context: the current context
+ * @sta: mac80211 station
+ *
+ * In certain circumstances mac80211 passes a station pointer
+ * that may be %NULL, for example during TX or key setup. In
+ * that case, we need to use the broadcast station, so this
+ * inline wraps that pattern.
+ */
+static inline int iwl_legacy_sta_id_or_broadcast(struct iwl_priv *priv,
+					  struct iwl_rxon_context *context,
+					  struct ieee80211_sta *sta)
+{
+	int sta_id;
+
+	if (!sta)
+		return context->bcast_sta_id;
+
+	sta_id = iwl_legacy_sta_id(sta);
+
+	/*
+	 * mac80211 should not be passing a partially
+	 * initialised station!
+	 */
+	WARN_ON(sta_id == IWL_INVALID_STATION);
+
+	return sta_id;
+}
+#endif /* __iwl_legacy_sta_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/iwl-tx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/iwl-tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,660 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2003 - 2011 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/etherdevice.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <net/mac80211.h>
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-sta.h"
+#include "iwl-io.h"
+#include "iwl-helpers.h"
+
+/**
+ * iwl_legacy_txq_update_write_ptr - Send new write index to hardware
+ */
+void
+iwl_legacy_txq_update_write_ptr(struct iwl_priv *priv, struct iwl_tx_queue *txq)
+{
+	u32 reg = 0;
+	int txq_id = txq->q.id;
+
+	if (txq->need_update == 0)
+		return;
+
+	/* if we're trying to save power */
+	if (test_bit(STATUS_POWER_PMI, &priv->status)) {
+		/* wake up nic if it's powered down ...
+		 * uCode will wake up, and interrupt us again, so next
+		 * time we'll skip this part. */
+		reg = iwl_read32(priv, CSR_UCODE_DRV_GP1);
+
+		if (reg & CSR_UCODE_DRV_GP1_BIT_MAC_SLEEP) {
+			IWL_DEBUG_INFO(priv,
+					"Tx queue %d requesting wakeup,"
+					" GP1 = 0x%x\n", txq_id, reg);
+			iwl_legacy_set_bit(priv, CSR_GP_CNTRL,
+					CSR_GP_CNTRL_REG_FLAG_MAC_ACCESS_REQ);
+			return;
+		}
+
+		iwl_legacy_write_direct32(priv, HBUS_TARG_WRPTR,
+				txq->q.write_ptr | (txq_id << 8));
+
+		/*
+		 * else not in power-save mode,
+		 * uCode will never sleep when we're
+		 * trying to tx (during RFKILL, we're not trying to tx).
+		 */
+	} else
+		iwl_write32(priv, HBUS_TARG_WRPTR,
+			    txq->q.write_ptr | (txq_id << 8));
+	txq->need_update = 0;
+}
+EXPORT_SYMBOL(iwl_legacy_txq_update_write_ptr);
+
+/**
+ * iwl_legacy_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+void iwl_legacy_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+
+	if (q->n_bd == 0)
+		return;
+
+	while (q->write_ptr != q->read_ptr) {
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+		q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_unmap);
+
+/**
+ * iwl_legacy_tx_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void iwl_legacy_tx_queue_free(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	iwl_legacy_tx_queue_unmap(priv, txq_id);
+
+	/* De-alloc array of command/tx buffers */
+	for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
+		kfree(txq->cmd[i]);
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd)
+		dma_free_coherent(dev, priv->hw_params.tfd_size *
+				  txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+
+	/* De-alloc array of per-TFD driver data */
+	kfree(txq->txb);
+	txq->txb = NULL;
+
+	/* deallocate arrays */
+	kfree(txq->cmd);
+	kfree(txq->meta);
+	txq->cmd = NULL;
+	txq->meta = NULL;
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_free);
+
+/**
+ * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
+ */
+void iwl_legacy_cmd_queue_unmap(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct iwl_queue *q = &txq->q;
+	bool huge = false;
+	int i;
+
+	if (q->n_bd == 0)
+		return;
+
+	while (q->read_ptr != q->write_ptr) {
+		/* we have no way to tell if it is a huge cmd ATM */
+		i = iwl_legacy_get_cmd_index(q, q->read_ptr, 0);
+
+		if (txq->meta[i].flags & CMD_SIZE_HUGE)
+			huge = true;
+		else
+			pci_unmap_single(priv->pci_dev,
+					 dma_unmap_addr(&txq->meta[i], mapping),
+					 dma_unmap_len(&txq->meta[i], len),
+					 PCI_DMA_BIDIRECTIONAL);
+
+		q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+
+	if (huge) {
+		i = q->n_window;
+		pci_unmap_single(priv->pci_dev,
+				 dma_unmap_addr(&txq->meta[i], mapping),
+				 dma_unmap_len(&txq->meta[i], len),
+				 PCI_DMA_BIDIRECTIONAL);
+	}
+}
+EXPORT_SYMBOL(iwl_legacy_cmd_queue_unmap);
+
+/**
+ * iwl_legacy_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void iwl_legacy_cmd_queue_free(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	iwl_legacy_cmd_queue_unmap(priv);
+
+	/* De-alloc array of command/tx buffers */
+	for (i = 0; i <= TFD_CMD_SLOTS; i++)
+		kfree(txq->cmd[i]);
+
+	/* De-alloc circular buffer of TFDs */
+	if (txq->q.n_bd)
+		dma_free_coherent(dev, priv->hw_params.tfd_size * txq->q.n_bd,
+				  txq->tfds, txq->q.dma_addr);
+
+	/* deallocate arrays */
+	kfree(txq->cmd);
+	kfree(txq->meta);
+	txq->cmd = NULL;
+	txq->meta = NULL;
+
+	/* 0-fill queue descriptor structure */
+	memset(txq, 0, sizeof(*txq));
+}
+EXPORT_SYMBOL(iwl_legacy_cmd_queue_free);
+
+/*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
+ * DMA services
+ *
+ * Theory of operation
+ *
+ * A Tx or Rx queue resides in host DRAM, and is comprised of a circular buffer
+ * of buffer descriptors, each of which points to one or more data buffers for
+ * the device to read from or fill.  Driver and device exchange status of each
+ * queue via "read" and "write" pointers.  Driver keeps minimum of 2 empty
+ * entries in each circular buffer, to protect against confusing empty and full
+ * queue states.
+ *
+ * The device reads or writes the data in the queues via the device's several
+ * DMA/FIFO channels.  Each queue is mapped to a single DMA channel.
+ *
+ * For Tx queue, there are low mark and high mark limits. If, after queuing
+ * the packet for Tx, free space become < low mark, Tx queue stopped. When
+ * reclaiming packets (on 'tx done IRQ), if free space become > high mark,
+ * Tx queue resumed.
+ *
+ * See more detailed info in iwl-4965-hw.h.
+ ***************************************************/
+
+int iwl_legacy_queue_space(const struct iwl_queue *q)
+{
+	int s = q->read_ptr - q->write_ptr;
+
+	if (q->read_ptr > q->write_ptr)
+		s -= q->n_bd;
+
+	if (s <= 0)
+		s += q->n_window;
+	/* keep some reserve to not confuse empty and full situations */
+	s -= 2;
+	if (s < 0)
+		s = 0;
+	return s;
+}
+EXPORT_SYMBOL(iwl_legacy_queue_space);
+
+
+/**
+ * iwl_legacy_queue_init - Initialize queue's high/low-water and read/write indexes
+ */
+static int iwl_legacy_queue_init(struct iwl_priv *priv, struct iwl_queue *q,
+			  int count, int slots_num, u32 id)
+{
+	q->n_bd = count;
+	q->n_window = slots_num;
+	q->id = id;
+
+	/* count must be power-of-two size, otherwise iwl_legacy_queue_inc_wrap
+	 * and iwl_legacy_queue_dec_wrap are broken. */
+	BUG_ON(!is_power_of_2(count));
+
+	/* slots_num must be power-of-two size, otherwise
+	 * iwl_legacy_get_cmd_index is broken. */
+	BUG_ON(!is_power_of_2(slots_num));
+
+	q->low_mark = q->n_window / 4;
+	if (q->low_mark < 4)
+		q->low_mark = 4;
+
+	q->high_mark = q->n_window / 8;
+	if (q->high_mark < 2)
+		q->high_mark = 2;
+
+	q->write_ptr = q->read_ptr = 0;
+
+	return 0;
+}
+
+/**
+ * iwl_legacy_tx_queue_alloc - Alloc driver data and TFD CB for one Tx/cmd queue
+ */
+static int iwl_legacy_tx_queue_alloc(struct iwl_priv *priv,
+			      struct iwl_tx_queue *txq, u32 id)
+{
+	struct device *dev = &priv->pci_dev->dev;
+	size_t tfd_sz = priv->hw_params.tfd_size * TFD_QUEUE_SIZE_MAX;
+
+	/* Driver private data, only for Tx (not command) queues,
+	 * not shared with device. */
+	if (id != priv->cmd_queue) {
+		txq->txb = kzalloc(sizeof(txq->txb[0]) *
+				   TFD_QUEUE_SIZE_MAX, GFP_KERNEL);
+		if (!txq->txb) {
+			IWL_ERR(priv, "kmalloc for auxiliary BD "
+				  "structures failed\n");
+			goto error;
+		}
+	} else {
+		txq->txb = NULL;
+	}
+
+	/* Circular buffer of transmit frame descriptors (TFDs),
+	 * shared with device */
+	txq->tfds = dma_alloc_coherent(dev, tfd_sz, &txq->q.dma_addr,
+				       GFP_KERNEL);
+	if (!txq->tfds) {
+		IWL_ERR(priv, "pci_alloc_consistent(%zd) failed\n", tfd_sz);
+		goto error;
+	}
+	txq->q.id = id;
+
+	return 0;
+
+ error:
+	kfree(txq->txb);
+	txq->txb = NULL;
+
+	return -ENOMEM;
+}
+
+/**
+ * iwl_legacy_tx_queue_init - Allocate and initialize one tx/cmd queue
+ */
+int iwl_legacy_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+		      int slots_num, u32 txq_id)
+{
+	int i, len;
+	int ret;
+	int actual_slots = slots_num;
+
+	/*
+	 * Alloc buffer array for commands (Tx or other types of commands).
+	 * For the command queue (#4/#9), allocate command space + one big
+	 * command for scan, since scan command is very huge; the system will
+	 * not have two scans at the same time, so only one is needed.
+	 * For normal Tx queues (all other queues), no super-size command
+	 * space is needed.
+	 */
+	if (txq_id == priv->cmd_queue)
+		actual_slots++;
+
+	txq->meta = kzalloc(sizeof(struct iwl_cmd_meta) * actual_slots,
+			    GFP_KERNEL);
+	txq->cmd = kzalloc(sizeof(struct iwl_device_cmd *) * actual_slots,
+			   GFP_KERNEL);
+
+	if (!txq->meta || !txq->cmd)
+		goto out_free_arrays;
+
+	len = sizeof(struct iwl_device_cmd);
+	for (i = 0; i < actual_slots; i++) {
+		/* only happens for cmd queue */
+		if (i == slots_num)
+			len = IWL_MAX_CMD_SIZE;
+
+		txq->cmd[i] = kmalloc(len, GFP_KERNEL);
+		if (!txq->cmd[i])
+			goto err;
+	}
+
+	/* Alloc driver data array and TFD circular buffer */
+	ret = iwl_legacy_tx_queue_alloc(priv, txq, txq_id);
+	if (ret)
+		goto err;
+
+	txq->need_update = 0;
+
+	/*
+	 * For the default queues 0-3, set up the swq_id
+	 * already -- all others need to get one later
+	 * (if they need one at all).
+	 */
+	if (txq_id < 4)
+		iwl_legacy_set_swq_id(txq, txq_id, txq_id);
+
+	/* TFD_QUEUE_SIZE_MAX must be power-of-two size, otherwise
+	 * iwl_legacy_queue_inc_wrap and iwl_legacy_queue_dec_wrap are broken. */
+	BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
+
+	/* Initialize queue's high/low-water marks, and head/tail indexes */
+	iwl_legacy_queue_init(priv, &txq->q,
+				TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+	/* Tell device where to find queue */
+	priv->cfg->ops->lib->txq_init(priv, txq);
+
+	return 0;
+err:
+	for (i = 0; i < actual_slots; i++)
+		kfree(txq->cmd[i]);
+out_free_arrays:
+	kfree(txq->meta);
+	kfree(txq->cmd);
+
+	return -ENOMEM;
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_init);
+
+void iwl_legacy_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
+			int slots_num, u32 txq_id)
+{
+	int actual_slots = slots_num;
+
+	if (txq_id == priv->cmd_queue)
+		actual_slots++;
+
+	memset(txq->meta, 0, sizeof(struct iwl_cmd_meta) * actual_slots);
+
+	txq->need_update = 0;
+
+	/* Initialize queue's high/low-water marks, and head/tail indexes */
+	iwl_legacy_queue_init(priv, &txq->q,
+				TFD_QUEUE_SIZE_MAX, slots_num, txq_id);
+
+	/* Tell device where to find queue */
+	priv->cfg->ops->lib->txq_init(priv, txq);
+}
+EXPORT_SYMBOL(iwl_legacy_tx_queue_reset);
+
+/*************** HOST COMMAND QUEUE FUNCTIONS   *****/
+
+/**
+ * iwl_legacy_enqueue_hcmd - enqueue a uCode command
+ * @priv: device private data point
+ * @cmd: a point to the ucode command structure
+ *
+ * The function returns < 0 values to indicate the operation is
+ * failed. On success, it turns the index (> 0) of command in the
+ * command queue.
+ */
+int iwl_legacy_enqueue_hcmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct iwl_queue *q = &txq->q;
+	struct iwl_device_cmd *out_cmd;
+	struct iwl_cmd_meta *out_meta;
+	dma_addr_t phys_addr;
+	unsigned long flags;
+	int len;
+	u32 idx;
+	u16 fix_size;
+
+	cmd->len = priv->cfg->ops->utils->get_hcmd_size(cmd->id, cmd->len);
+	fix_size = (u16)(cmd->len + sizeof(out_cmd->hdr));
+
+	/* If any of the command structures end up being larger than
+	 * the TFD_MAX_PAYLOAD_SIZE, and it sent as a 'small' command then
+	 * we will need to increase the size of the TFD entries
+	 * Also, check to see if command buffer should not exceed the size
+	 * of device_cmd and max_cmd_size. */
+	BUG_ON((fix_size > TFD_MAX_PAYLOAD_SIZE) &&
+	       !(cmd->flags & CMD_SIZE_HUGE));
+	BUG_ON(fix_size > IWL_MAX_CMD_SIZE);
+
+	if (iwl_legacy_is_rfkill(priv) || iwl_legacy_is_ctkill(priv)) {
+		IWL_WARN(priv, "Not sending command - %s KILL\n",
+			 iwl_legacy_is_rfkill(priv) ? "RF" : "CT");
+		return -EIO;
+	}
+
+	if (iwl_legacy_queue_space(q) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) {
+		IWL_ERR(priv, "No space in command queue\n");
+		IWL_ERR(priv, "Restarting adapter due to queue full\n");
+		queue_work(priv->workqueue, &priv->restart);
+		return -ENOSPC;
+	}
+
+	spin_lock_irqsave(&priv->hcmd_lock, flags);
+
+	/* If this is a huge cmd, mark the huge flag also on the meta.flags
+	 * of the _original_ cmd. This is used for DMA mapping clean up.
+	 */
+	if (cmd->flags & CMD_SIZE_HUGE) {
+		idx = iwl_legacy_get_cmd_index(q, q->write_ptr, 0);
+		txq->meta[idx].flags = CMD_SIZE_HUGE;
+	}
+
+	idx = iwl_legacy_get_cmd_index(q, q->write_ptr, cmd->flags & CMD_SIZE_HUGE);
+	out_cmd = txq->cmd[idx];
+	out_meta = &txq->meta[idx];
+
+	memset(out_meta, 0, sizeof(*out_meta));	/* re-initialize to NULL */
+	out_meta->flags = cmd->flags;
+	if (cmd->flags & CMD_WANT_SKB)
+		out_meta->source = cmd;
+	if (cmd->flags & CMD_ASYNC)
+		out_meta->callback = cmd->callback;
+
+	out_cmd->hdr.cmd = cmd->id;
+	memcpy(&out_cmd->cmd.payload, cmd->data, cmd->len);
+
+	/* At this point, the out_cmd now has all of the incoming cmd
+	 * information */
+
+	out_cmd->hdr.flags = 0;
+	out_cmd->hdr.sequence = cpu_to_le16(QUEUE_TO_SEQ(priv->cmd_queue) |
+			INDEX_TO_SEQ(q->write_ptr));
+	if (cmd->flags & CMD_SIZE_HUGE)
+		out_cmd->hdr.sequence |= SEQ_HUGE_FRAME;
+	len = sizeof(struct iwl_device_cmd);
+	if (idx == TFD_CMD_SLOTS)
+		len = IWL_MAX_CMD_SIZE;
+
+#ifdef CONFIG_IWLWIFI_LEGACY_DEBUG
+	switch (out_cmd->hdr.cmd) {
+	case REPLY_TX_LINK_QUALITY_CMD:
+	case SENSITIVITY_CMD:
+		IWL_DEBUG_HC_DUMP(priv,
+				"Sending command %s (#%x), seq: 0x%04X, "
+				"%d bytes at %d[%d]:%d\n",
+				iwl_legacy_get_cmd_string(out_cmd->hdr.cmd),
+				out_cmd->hdr.cmd,
+				le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+				q->write_ptr, idx, priv->cmd_queue);
+		break;
+	default:
+		IWL_DEBUG_HC(priv, "Sending command %s (#%x), seq: 0x%04X, "
+				"%d bytes at %d[%d]:%d\n",
+				iwl_legacy_get_cmd_string(out_cmd->hdr.cmd),
+				out_cmd->hdr.cmd,
+				le16_to_cpu(out_cmd->hdr.sequence), fix_size,
+				q->write_ptr, idx, priv->cmd_queue);
+	}
+#endif
+	txq->need_update = 1;
+
+	if (priv->cfg->ops->lib->txq_update_byte_cnt_tbl)
+		/* Set up entry in queue's byte count circular buffer */
+		priv->cfg->ops->lib->txq_update_byte_cnt_tbl(priv, txq, 0);
+
+	phys_addr = pci_map_single(priv->pci_dev, &out_cmd->hdr,
+				   fix_size, PCI_DMA_BIDIRECTIONAL);
+	dma_unmap_addr_set(out_meta, mapping, phys_addr);
+	dma_unmap_len_set(out_meta, len, fix_size);
+
+	trace_iwlwifi_legacy_dev_hcmd(priv, &out_cmd->hdr,
+						fix_size, cmd->flags);
+
+	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
+						   phys_addr, fix_size, 1,
+						   U32_PAD(cmd->len));
+
+	/* Increment and update queue's write index */
+	q->write_ptr = iwl_legacy_queue_inc_wrap(q->write_ptr, q->n_bd);
+	iwl_legacy_txq_update_write_ptr(priv, txq);
+
+	spin_unlock_irqrestore(&priv->hcmd_lock, flags);
+	return idx;
+}
+
+/**
+ * iwl_legacy_hcmd_queue_reclaim - Reclaim TX command queue entries already Tx'd
+ *
+ * When FW advances 'R' index, all entries between old and new 'R' index
+ * need to be reclaimed. As result, some free space forms.  If there is
+ * enough free space (> low mark), wake the stack that feeds us.
+ */
+static void iwl_legacy_hcmd_queue_reclaim(struct iwl_priv *priv, int txq_id,
+				   int idx, int cmd_idx)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+	int nfreed = 0;
+
+	if ((idx >= q->n_bd) || (iwl_legacy_queue_used(q, idx) == 0)) {
+		IWL_ERR(priv, "Read index for DMA queue txq id (%d), index %d, "
+			  "is out of range [0-%d] %d %d.\n", txq_id,
+			  idx, q->n_bd, q->write_ptr, q->read_ptr);
+		return;
+	}
+
+	for (idx = iwl_legacy_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
+	     q->read_ptr = iwl_legacy_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+
+		if (nfreed++ > 0) {
+			IWL_ERR(priv, "HCMD skipped: index (%d) %d %d\n", idx,
+					q->write_ptr, q->read_ptr);
+			queue_work(priv->workqueue, &priv->restart);
+		}
+
+	}
+}
+
+/**
+ * iwl_legacy_tx_cmd_complete - Pull unused buffers off the queue and reclaim them
+ * @rxb: Rx buffer to reclaim
+ *
+ * If an Rx buffer has an async callback associated with it the callback
+ * will be executed.  The attached skb (if present) will only be freed
+ * if the callback returns 1
+ */
+void
+iwl_legacy_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
+	int txq_id = SEQ_TO_QUEUE(sequence);
+	int index = SEQ_TO_INDEX(sequence);
+	int cmd_index;
+	bool huge = !!(pkt->hdr.sequence & SEQ_HUGE_FRAME);
+	struct iwl_device_cmd *cmd;
+	struct iwl_cmd_meta *meta;
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+
+	/* If a Tx command is being handled and it isn't in the actual
+	 * command queue then there a command routing bug has been introduced
+	 * in the queue management code. */
+	if (WARN(txq_id != priv->cmd_queue,
+		 "wrong command queue %d (should be %d), sequence 0x%X readp=%d writep=%d\n",
+		  txq_id, priv->cmd_queue, sequence,
+		  priv->txq[priv->cmd_queue].q.read_ptr,
+		  priv->txq[priv->cmd_queue].q.write_ptr)) {
+		iwl_print_hex_error(priv, pkt, 32);
+		return;
+	}
+
+	/* If this is a huge cmd, clear the huge flag on the meta.flags
+	 * of the _original_ cmd. So that iwl_legacy_cmd_queue_free won't unmap
+	 * the DMA buffer for the scan (huge) command.
+	 */
+	if (huge) {
+		cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, 0);
+		txq->meta[cmd_index].flags = 0;
+	}
+	cmd_index = iwl_legacy_get_cmd_index(&txq->q, index, huge);
+	cmd = txq->cmd[cmd_index];
+	meta = &txq->meta[cmd_index];
+
+	pci_unmap_single(priv->pci_dev,
+			 dma_unmap_addr(meta, mapping),
+			 dma_unmap_len(meta, len),
+			 PCI_DMA_BIDIRECTIONAL);
+
+	/* Input error checking is done when commands are added to queue. */
+	if (meta->flags & CMD_WANT_SKB) {
+		meta->source->reply_page = (unsigned long)rxb_addr(rxb);
+		rxb->page = NULL;
+	} else if (meta->callback)
+		meta->callback(priv, cmd, pkt);
+
+	iwl_legacy_hcmd_queue_reclaim(priv, txq_id, index, cmd_index);
+
+	if (!(meta->flags & CMD_ASYNC)) {
+		clear_bit(STATUS_HCMD_ACTIVE, &priv->status);
+		IWL_DEBUG_INFO(priv, "Clearing HCMD_ACTIVE for command %s\n",
+			       iwl_legacy_get_cmd_string(cmd->hdr.cmd));
+		wake_up_interruptible(&priv->wait_command_queue);
+	}
+	meta->flags = 0;
+}
+EXPORT_SYMBOL(iwl_legacy_tx_cmd_complete);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,117 @@
+config IWLWIFI_LEGACY
+	tristate
+	select FW_LOADER
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_TRIGGERS
+	select MAC80211_LEDS
+
+menu "Debugging Options"
+	depends on IWLWIFI_LEGACY
+
+config IWLWIFI_LEGACY_DEBUG
+	bool "Enable full debugging output in 4965 and 3945 drivers"
+	depends on IWLWIFI_LEGACY
+	---help---
+	  This option will enable debug tracing output for the iwlwifilegacy
+	  drivers.
+
+	  This will result in the kernel module being ~100k larger.  You can
+	  control which debug output is sent to the kernel log by setting the
+	  value in
+
+		/sys/class/net/wlan0/device/debug_level
+
+	  This entry will only exist if this option is enabled.
+
+	  To set a value, simply echo an 8-byte hex value to the same file:
+
+		  % echo 0x43fff > /sys/class/net/wlan0/device/debug_level
+
+	  You can find the list of debug mask values in:
+		  drivers/net/wireless/iwlwifilegacy/iwl-debug.h
+
+	  If this is your first time using this driver, you should say Y here
+	  as the debug information can assist others in helping you resolve
+	  any problems you may encounter.
+
+config IWLWIFI_LEGACY_DEBUGFS
+        bool "4965 and 3945 debugfs support"
+        depends on IWLWIFI_LEGACY && MAC80211_DEBUGFS
+        ---help---
+	  Enable creation of debugfs files for the iwlwifilegacy drivers. This
+	  is a low-impact option that allows getting insight into the
+	  driver's state at runtime.
+
+config IWLWIFI_LEGACY_DEVICE_TRACING
+	bool "iwlwifilegacy legacy device access tracing"
+	depends on IWLWIFI_LEGACY
+	depends on EVENT_TRACING
+	help
+	  Say Y here to trace all commands, including TX frames and IO
+	  accesses, sent to the device. If you say yes, iwlwifilegacy will
+	  register with the ftrace framework for event tracing and dump
+	  all this information to the ringbuffer, you may need to
+	  increase the ringbuffer size. See the ftrace documentation
+	  for more information.
+
+	  When tracing is not enabled, this option still has some
+	  (though rather small) overhead.
+
+	  If unsure, say Y so we can help you better when problems
+	  occur.
+endmenu
+
+config IWL4965
+	tristate "Intel Wireless WiFi 4965AGN (iwl4965)"
+	depends on PCI && MAC80211
+	select IWLWIFI_LEGACY
+	---help---
+	  This option enables support for
+
+	  Select to build the driver supporting the:
+
+	  Intel Wireless WiFi Link 4965AGN
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  In order to use this driver, you will need a microcode (uCode)
+	  image for it. You can obtain the microcode from:
+
+	          <http://intellinuxwireless.org/>.
+
+	  The microcode is typically installed in /lib/firmware. You can
+	  look in the hotplug script /etc/hotplug/firmware.agent to
+	  determine which directory FIRMWARE_DIR is set to when the script
+	  runs.
+
+	  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 iwl4965.
+
+config IWL3945
+	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
+	depends on PCI && MAC80211
+	select IWLWIFI_LEGACY
+	---help---
+	  Select to build the driver supporting the:
+
+	  Intel PRO/Wireless 3945ABG/BG Network Connection
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  In order to use this driver, you will need a microcode (uCode)
+	  image for it. You can obtain the microcode from:
+
+	          <http://intellinuxwireless.org/>.
+
+	  The microcode is typically installed in /lib/firmware. You can
+	  look in the hotplug script /etc/hotplug/firmware.agent to
+	  determine which directory FIRMWARE_DIR is set to when the script
+	  runs.
+
+	  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.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlegacy/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlegacy/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,25 @@
+obj-$(CONFIG_IWLWIFI_LEGACY)	+= iwl-legacy.o
+iwl-legacy-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
+iwl-legacy-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
+iwl-legacy-objs 		+= iwl-scan.o iwl-led.o
+iwl-legacy-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-debugfs.o
+iwl-legacy-$(CONFIG_IWLWIFI_LEGACY_DEVICE_TRACING) += iwl-devtrace.o
+
+iwl-legacy-objs += $(iwl-legacy-m)
+
+CFLAGS_iwl-devtrace.o := -I$(src)
+
+# 4965
+obj-$(CONFIG_IWL4965)	+= iwl4965.o
+iwl4965-objs		:= iwl-4965.o iwl4965-base.o iwl-4965-rs.o iwl-4965-led.o
+iwl4965-objs		+= iwl-4965-ucode.o iwl-4965-tx.o
+iwl4965-objs		+= iwl-4965-lib.o iwl-4965-rx.o iwl-4965-calib.o
+iwl4965-objs		+= iwl-4965-sta.o iwl-4965-eeprom.o
+iwl4965-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-4965-debugfs.o
+
+# 3945
+obj-$(CONFIG_IWL3945)	+= iwl3945.o
+iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
+iwl3945-$(CONFIG_IWLWIFI_LEGACY_DEBUGFS) += iwl-3945-debugfs.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-1000.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-1000.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-1000.c	2012-03-24 01:12:38.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-1000.c	2012-03-24 03:33:17.000000000 -0400
@@ -49,7 +49,7 @@
 #include "iwl-agn-debugfs.h"
 
 /* Highest firmware API version supported */
-#define IWL1000_UCODE_API_MAX 3
+#define IWL1000_UCODE_API_MAX 5
 #define IWL100_UCODE_API_MAX 5
 
 /* Lowest firmware API version supported */
@@ -232,8 +232,6 @@
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-2000.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-2000.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-2000.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-2000.c	2012-03-24 03:33:19.000000000 -0400
@@ -0,0 +1,558 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
+ *
+ * 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 <linux/pci.h>
+#include <linux/dma-mapping.h>
+#include <linux/delay.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/mac80211.h>
+#include <linux/etherdevice.h>
+#include <asm/unaligned.h>
+
+#include "iwl-eeprom.h"
+#include "iwl-dev.h"
+#include "iwl-core.h"
+#include "iwl-io.h"
+#include "iwl-sta.h"
+#include "iwl-agn.h"
+#include "iwl-helpers.h"
+#include "iwl-agn-hw.h"
+#include "iwl-6000-hw.h"
+#include "iwl-agn-led.h"
+#include "iwl-agn-debugfs.h"
+
+/* Highest firmware API version supported */
+#define IWL2030_UCODE_API_MAX 5
+#define IWL2000_UCODE_API_MAX 5
+#define IWL200_UCODE_API_MAX 5
+
+/* Lowest firmware API version supported */
+#define IWL2030_UCODE_API_MIN 5
+#define IWL2000_UCODE_API_MIN 5
+#define IWL200_UCODE_API_MIN 5
+
+#define IWL2030_FW_PRE "/*(DEBLOBBED)*/"
+#define _IWL2030_MODULE_FIRMWARE(api) IWL2030_FW_PRE /*(DEBLOBBED)*/
+#define IWL2030_MODULE_FIRMWARE(api) _IWL2030_MODULE_FIRMWARE(api)
+
+#define IWL2000_FW_PRE "/*(DEBLOBBED)*/"
+#define _IWL2000_MODULE_FIRMWARE(api) IWL2000_FW_PRE /*(DEBLOBBED)*/
+#define IWL2000_MODULE_FIRMWARE(api) _IWL2000_MODULE_FIRMWARE(api)
+
+#define IWL200_FW_PRE "/*(DEBLOBBED)*/"
+#define _IWL200_MODULE_FIRMWARE(api) IWL200_FW_PRE /*(DEBLOBBED)*/
+#define IWL200_MODULE_FIRMWARE(api) _IWL200_MODULE_FIRMWARE(api)
+
+static void iwl2000_set_ct_threshold(struct iwl_priv *priv)
+{
+	/* want Celsius */
+	priv->hw_params.ct_kill_threshold = CT_KILL_THRESHOLD;
+	priv->hw_params.ct_kill_exit_threshold = CT_KILL_EXIT_THRESHOLD;
+}
+
+/* NIC configuration for 2000 series */
+static void iwl2000_nic_config(struct iwl_priv *priv)
+{
+	u16 radio_cfg;
+
+	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
+
+	/* write radio config values to register */
+	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) <= EEPROM_RF_CONFIG_TYPE_MAX)
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+			EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
+			EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
+			EEPROM_RF_CFG_DASH_MSK(radio_cfg));
+
+	/* set CSR_HW_CONFIG_REG for uCode use */
+	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
+		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
+		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
+
+	if (priv->cfg->iq_invert)
+		iwl_set_bit(priv, CSR_GP_DRIVER_REG,
+			    CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER);
+
+}
+
+static struct iwl_sensitivity_ranges iwl2000_sensitivity = {
+	.min_nrg_cck = 97,
+	.max_nrg_cck = 0, /* not used, set to 0 */
+	.auto_corr_min_ofdm = 80,
+	.auto_corr_min_ofdm_mrc = 128,
+	.auto_corr_min_ofdm_x1 = 105,
+	.auto_corr_min_ofdm_mrc_x1 = 192,
+
+	.auto_corr_max_ofdm = 145,
+	.auto_corr_max_ofdm_mrc = 232,
+	.auto_corr_max_ofdm_x1 = 110,
+	.auto_corr_max_ofdm_mrc_x1 = 232,
+
+	.auto_corr_min_cck = 125,
+	.auto_corr_max_cck = 175,
+	.auto_corr_min_cck_mrc = 160,
+	.auto_corr_max_cck_mrc = 310,
+	.nrg_th_cck = 97,
+	.nrg_th_ofdm = 100,
+
+	.barker_corr_th_min = 190,
+	.barker_corr_th_min_mrc = 390,
+	.nrg_th_cca = 62,
+};
+
+static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
+{
+	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
+	    priv->cfg->mod_params->num_of_queues <= IWLAGN_NUM_QUEUES)
+		priv->cfg->base_params->num_of_queues =
+			priv->cfg->mod_params->num_of_queues;
+
+	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
+	priv->hw_params.dma_chnl_num = FH50_TCSR_CHNL_NUM;
+	priv->hw_params.scd_bc_tbls_size =
+		priv->cfg->base_params->num_of_queues *
+		sizeof(struct iwlagn_scd_bc_tbl);
+	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
+	priv->hw_params.max_stations = IWLAGN_STATION_COUNT;
+	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWLAGN_BROADCAST_ID;
+
+	priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
+	priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
+
+	priv->hw_params.max_bsm_size = 0;
+	priv->hw_params.ht40_channel =  BIT(IEEE80211_BAND_2GHZ) |
+					BIT(IEEE80211_BAND_5GHZ);
+	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
+
+	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
+	if (priv->cfg->rx_with_siso_diversity)
+		priv->hw_params.rx_chains_num = 1;
+	else
+		priv->hw_params.rx_chains_num =
+			num_of_ant(priv->cfg->valid_rx_ant);
+	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
+	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
+
+	iwl2000_set_ct_threshold(priv);
+
+	/* Set initial sensitivity parameters */
+	/* Set initial calibration set */
+	priv->hw_params.sens = &iwl2000_sensitivity;
+	priv->hw_params.calib_init_cfg =
+		BIT(IWL_CALIB_XTAL)             |
+		BIT(IWL_CALIB_LO)               |
+		BIT(IWL_CALIB_TX_IQ)            |
+		BIT(IWL_CALIB_BASE_BAND);
+	if (priv->cfg->need_dc_calib)
+		priv->hw_params.calib_rt_cfg |= BIT(IWL_CALIB_CFG_DC_IDX);
+	if (priv->cfg->need_temp_offset_calib)
+		priv->hw_params.calib_init_cfg |= BIT(IWL_CALIB_TEMP_OFFSET);
+
+	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
+
+	return 0;
+}
+
+static int iwl2030_hw_channel_switch(struct iwl_priv *priv,
+                                    struct ieee80211_channel_switch *ch_switch)
+{
+	/*
+	 * MULTI-FIXME
+	 * See iwl_mac_channel_switch.
+	 */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl6000_channel_switch_cmd cmd;
+	const struct iwl_channel_info *ch_info;
+	u32 switch_time_in_usec, ucode_switch_time;
+	u16 ch;
+	u32 tsf_low;
+	u8 switch_count;
+	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
+	struct ieee80211_vif *vif = ctx->vif;
+	struct iwl_host_cmd hcmd = {
+		.id = REPLY_CHANNEL_SWITCH,
+		.len = sizeof(cmd),
+		.flags = CMD_SYNC,
+		.data = &cmd,
+	};
+
+	cmd.band = priv->band == IEEE80211_BAND_2GHZ;
+	ch = ch_switch->channel->hw_value;
+	IWL_DEBUG_11H(priv, "channel switch from %u to %u\n",
+		ctx->active.channel, ch);
+	cmd.channel = cpu_to_le16(ch);
+	cmd.rxon_flags = ctx->staging.flags;
+	cmd.rxon_filter_flags = ctx->staging.filter_flags;
+	switch_count = ch_switch->count;
+	tsf_low = ch_switch->timestamp & 0x0ffffffff;
+	/*
+	 * calculate the ucode channel switch time
+	 * adding TSF as one of the factor for when to switch
+	 */
+	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
+		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
+		    beacon_interval)) {
+			switch_count -= (priv->ucode_beacon_time -
+				tsf_low) / beacon_interval;
+		} else
+			switch_count = 0;
+	}
+	if (switch_count <= 1)
+		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
+	else {
+		switch_time_in_usec =
+			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
+		ucode_switch_time = iwl_usecs_to_beacons(priv,
+						switch_time_in_usec,
+						beacon_interval);
+		cmd.switch_time = iwl_add_beacon_time(priv,
+						priv->ucode_beacon_time,
+						ucode_switch_time,
+						beacon_interval);
+	}
+	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
+		      cmd.switch_time);
+	ch_info = iwl_get_channel_info(priv, priv->band, ch);
+	if (ch_info)
+		cmd.expect_beacon = is_channel_radar(ch_info);
+	else {
+		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
+			ctx->active.channel, ch);
+		return -EFAULT;
+	}
+	priv->switch_rxon.channel = cmd.channel;
+	priv->switch_rxon.switch_in_progress = true;
+
+	return iwl_send_cmd_sync(priv, &hcmd);
+}
+
+static struct iwl_lib_ops iwl2000_lib = {
+	.set_hw_params = iwl2000_hw_set_hw_params,
+	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
+	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
+	.txq_set_sched = iwlagn_txq_set_sched,
+	.txq_agg_enable = iwlagn_txq_agg_enable,
+	.txq_agg_disable = iwlagn_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 = iwlagn_rx_handler_setup,
+	.setup_deferred_work = iwlagn_bt_setup_deferred_work,
+	.cancel_deferred_work = iwlagn_bt_cancel_deferred_work,
+	.is_valid_rtc_data_addr = iwlagn_hw_valid_rtc_data_addr,
+	.load_ucode = iwlagn_load_ucode,
+	.dump_nic_event_log = iwl_dump_nic_event_log,
+	.dump_nic_error_log = iwl_dump_nic_error_log,
+	.dump_csr = iwl_dump_csr,
+	.dump_fh = iwl_dump_fh,
+	.init_alive_start = iwlagn_init_alive_start,
+	.alive_notify = iwlagn_alive_notify,
+	.send_tx_power = iwlagn_send_tx_power,
+	.update_chain_flags = iwl_update_chain_flags,
+	.set_channel_switch = iwl2030_hw_channel_switch,
+	.apm_ops = {
+		.init = iwl_apm_init,
+		.config = iwl2000_nic_config,
+	},
+	.eeprom_ops = {
+		.regulatory_bands = {
+			EEPROM_REG_BAND_1_CHANNELS,
+			EEPROM_REG_BAND_2_CHANNELS,
+			EEPROM_REG_BAND_3_CHANNELS,
+			EEPROM_REG_BAND_4_CHANNELS,
+			EEPROM_REG_BAND_5_CHANNELS,
+			EEPROM_6000_REG_BAND_24_HT40_CHANNELS,
+			EEPROM_REG_BAND_52_HT40_CHANNELS
+		},
+		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
+		.release_semaphore = iwlcore_eeprom_release_semaphore,
+		.calib_version  = iwlagn_eeprom_calib_version,
+		.query_addr = iwlagn_eeprom_query_addr,
+		.update_enhanced_txpower = iwlcore_eeprom_enhanced_txpower,
+	},
+	.isr_ops = {
+		.isr = iwl_isr_ict,
+		.free = iwl_free_isr_ict,
+		.alloc = iwl_alloc_isr_ict,
+		.reset = iwl_reset_ict,
+		.disable = iwl_disable_ict,
+	},
+	.temp_ops = {
+		.temperature = iwlagn_temperature,
+	},
+	.debugfs_ops = {
+		.rx_stats_read = iwl_ucode_rx_stats_read,
+		.tx_stats_read = iwl_ucode_tx_stats_read,
+		.general_stats_read = iwl_ucode_general_stats_read,
+		.bt_stats_read = iwl_ucode_bt_stats_read,
+		.reply_tx_error = iwl_reply_tx_error_read,
+	},
+	.txfifo_flush = iwlagn_txfifo_flush,
+	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
+	.tt_ops = {
+		.lower_power_detection = iwl_tt_is_low_power_state,
+		.tt_power_mode = iwl_tt_current_power_mode,
+		.ct_kill_check = iwl_check_for_ct_kill,
+	}
+};
+
+static const struct iwl_ops iwl2000_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static const struct iwl_ops iwl2030_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_bt_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static const struct iwl_ops iwl200_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static const struct iwl_ops iwl230_ops = {
+	.lib = &iwl2000_lib,
+	.hcmd = &iwlagn_bt_hcmd,
+	.utils = &iwlagn_hcmd_utils,
+	.led = &iwlagn_led_ops,
+	.ieee80211_ops = &iwlagn_hw_ops,
+};
+
+static struct iwl_base_params iwl2000_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
+	.shadow_ram_support = true,
+	.led_compensation = 51,
+	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_DEF_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
+};
+
+
+static struct iwl_base_params iwl2030_base_params = {
+	.eeprom_size = OTP_LOW_IMAGE_SIZE,
+	.num_of_queues = IWLAGN_NUM_QUEUES,
+	.num_of_ampdu_queues = IWLAGN_NUM_AMPDU_QUEUES,
+	.pll_cfg_val = 0,
+	.set_l0s = true,
+	.use_bsm = false,
+	.max_ll_items = OTP_MAX_LL_ITEMS_2x00,
+	.shadow_ram_support = true,
+	.led_compensation = 57,
+	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
+	.adv_thermal_throttle = true,
+	.support_ct_kill_exit = true,
+	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
+	.chain_noise_scale = 1000,
+	.wd_timeout = IWL_LONG_WD_TIMEOUT,
+	.max_event_log_size = 512,
+	.ucode_tracing = true,
+	.sensitivity_calib_by_driver = true,
+	.chain_noise_calib_by_driver = true,
+	.shadow_reg_enable = true,
+};
+
+static struct iwl_ht_params iwl2000_ht_params = {
+	.ht_greenfield_support = true,
+	.use_rts_for_aggregation = true, /* use rts/cts protection */
+};
+
+static struct iwl_bt_params iwl2030_bt_params = {
+	.bt_statistics = true,
+	/* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
+	.advanced_bt_coexist = true,
+	.agg_time_limit = BT_AGG_THRESHOLD_DEF,
+	.bt_init_traffic_load = IWL_BT_COEX_TRAFFIC_LOAD_NONE,
+	.bt_prio_boost = IWLAGN_BT_PRIO_BOOST_DEFAULT,
+	.bt_sco_disable = true,
+	.bt_session_2 = true,
+};
+
+#define IWL_DEVICE_2000						\
+	.fw_name_pre = IWL2000_FW_PRE,				\
+	.ucode_api_max = IWL2000_UCODE_API_MAX,			\
+	.ucode_api_min = IWL2000_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl2000_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2000_base_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.iq_invert = true					\
+
+struct iwl_cfg iwl2000_2bgn_cfg = {
+	.name = "2000 Series 2x2 BGN",
+	IWL_DEVICE_2000,
+	.ht_params = &iwl2000_ht_params,
+};
+
+struct iwl_cfg iwl2000_2bg_cfg = {
+	.name = "2000 Series 2x2 BG",
+	IWL_DEVICE_2000,
+};
+
+#define IWL_DEVICE_2030						\
+	.fw_name_pre = IWL2030_FW_PRE,				\
+	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
+	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl2030_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.iq_invert = true					\
+
+struct iwl_cfg iwl2030_2bgn_cfg = {
+	.name = "2000 Series 2x2 BGN/BT",
+	IWL_DEVICE_2030,
+	.ht_params = &iwl2000_ht_params,
+};
+
+struct iwl_cfg iwl2030_2bg_cfg = {
+	.name = "2000 Series 2x2 BG/BT",
+	IWL_DEVICE_2030,
+};
+
+#define IWL_DEVICE_6035						\
+	.fw_name_pre = IWL2030_FW_PRE,				\
+	.ucode_api_max = IWL2030_UCODE_API_MAX,			\
+	.ucode_api_min = IWL2030_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_6035_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6035_TX_POWER_VERSION,	\
+	.ops = &iwl2030_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true						\
+
+struct iwl_cfg iwl6035_2agn_cfg = {
+	.name = "2000 Series 2x2 AGN/BT",
+	IWL_DEVICE_6035,
+	.ht_params = &iwl2000_ht_params,
+};
+
+struct iwl_cfg iwl6035_2abg_cfg = {
+	.name = "2000 Series 2x2 ABG/BT",
+	IWL_DEVICE_6035,
+};
+
+struct iwl_cfg iwl6035_2bg_cfg = {
+	.name = "2000 Series 2x2 BG/BT",
+	IWL_DEVICE_6035,
+};
+
+#define IWL_DEVICE_200						\
+	.fw_name_pre = IWL200_FW_PRE,				\
+	.ucode_api_max = IWL200_UCODE_API_MAX,			\
+	.ucode_api_min = IWL200_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl200_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2000_base_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.rx_with_siso_diversity = true				\
+
+struct iwl_cfg iwl200_bg_cfg = {
+	.name = "200 Series 1x1 BG",
+	IWL_DEVICE_200,
+};
+
+struct iwl_cfg iwl200_bgn_cfg = {
+	.name = "200 Series 1x1 BGN",
+	IWL_DEVICE_200,
+	.ht_params = &iwl2000_ht_params,
+};
+
+#define IWL_DEVICE_230						\
+	.fw_name_pre = IWL200_FW_PRE,				\
+	.ucode_api_max = IWL200_UCODE_API_MAX,			\
+	.ucode_api_min = IWL200_UCODE_API_MIN,			\
+	.eeprom_ver = EEPROM_2000_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION,	\
+	.ops = &iwl230_ops,					\
+	.mod_params = &iwlagn_mod_params,			\
+	.base_params = &iwl2030_base_params,			\
+	.bt_params = &iwl2030_bt_params,			\
+	.need_dc_calib = true,					\
+	.need_temp_offset_calib = true,				\
+	.led_mode = IWL_LED_RF_STATE,				\
+	.adv_pm = true,						\
+	.rx_with_siso_diversity = true				\
+
+struct iwl_cfg iwl230_bg_cfg = {
+	.name = "200 Series 1x1 BG/BT",
+	IWL_DEVICE_230,
+};
+
+struct iwl_cfg iwl230_bgn_cfg = {
+	.name = "200 Series 1x1 BGN/BT",
+	IWL_DEVICE_230,
+	.ht_params = &iwl2000_ht_params,
+};
+
+/*(DEBLOBBED)*/
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c	2012-03-24 01:12:08.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl3945-base.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,4327 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 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
- *
- *****************************************************************************/
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/pci-aspm.h>
-#include <linux/slab.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <linux/if_arp.h>
-
-#include <net/ieee80211_radiotap.h>
-#include <net/mac80211.h>
-
-#include <asm/div64.h>
-
-#define DRV_NAME	"iwl3945"
-
-#include "iwl-fh.h"
-#include "iwl-3945-fh.h"
-#include "iwl-commands.h"
-#include "iwl-sta.h"
-#include "iwl-3945.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-dev.h"
-#include "iwl-spectrum.h"
-#include "iwl-legacy.h"
-
-/*
- * module name, copyright, version, etc.
- */
-
-#define DRV_DESCRIPTION	\
-"Intel(R) PRO/Wireless 3945ABG/BG Network Connection driver for Linux"
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define VD "d"
-#else
-#define VD
-#endif
-
-/*
- * add "s" to indicate spectrum measurement included.
- * we add it here to be consistent with previous releases in which
- * this was configurable.
- */
-#define DRV_VERSION  IWLWIFI_VERSION VD "s"
-#define DRV_COPYRIGHT	"Copyright(c) 2003-2010 Intel Corporation"
-#define DRV_AUTHOR     "<ilw@linux.intel.com>"
-
-MODULE_DESCRIPTION(DRV_DESCRIPTION);
-MODULE_VERSION(DRV_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-
- /* module parameters */
-struct iwl_mod_params iwl3945_mod_params = {
-	.sw_crypto = 1,
-	.restart_fw = 1,
-	/* the rest are 0 by default */
-};
-
-/**
- * iwl3945_get_antenna_flags - Get antenna flags for RXON command
- * @priv: eeprom and antenna fields are used to determine antenna flags
- *
- * priv->eeprom39  is used to determine if antenna AUX/MAIN are reversed
- * iwl3945_mod_params.antenna specifies the antenna diversity mode:
- *
- * IWL_ANTENNA_DIVERSITY - NIC selects best antenna by itself
- * IWL_ANTENNA_MAIN      - Force MAIN antenna
- * IWL_ANTENNA_AUX       - Force AUX antenna
- */
-__le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-
-	switch (iwl3945_mod_params.antenna) {
-	case IWL_ANTENNA_DIVERSITY:
-		return 0;
-
-	case IWL_ANTENNA_MAIN:
-		if (eeprom->antenna_switch_type)
-			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-
-	case IWL_ANTENNA_AUX:
-		if (eeprom->antenna_switch_type)
-			return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_A_MSK;
-		return RXON_FLG_DIS_DIV_MSK | RXON_FLG_ANT_B_MSK;
-	}
-
-	/* bad antenna selector value */
-	IWL_ERR(priv, "Bad antenna selector value (0x%x)\n",
-		iwl3945_mod_params.antenna);
-
-	return 0;		/* "diversity" is default if error */
-}
-
-static int iwl3945_set_ccmp_dynamic_key_info(struct iwl_priv *priv,
-				   struct ieee80211_key_conf *keyconf,
-				   u8 sta_id)
-{
-	unsigned long flags;
-	__le16 key_flags = 0;
-	int ret;
-
-	key_flags |= (STA_KEY_FLG_CCMP | STA_KEY_FLG_MAP_KEY_MSK);
-	key_flags |= cpu_to_le16(keyconf->keyidx << STA_KEY_FLG_KEYID_POS);
-
-	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
-		key_flags |= STA_KEY_MULTICAST_MSK;
-
-	keyconf->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
-	keyconf->hw_key_idx = keyconf->keyidx;
-	key_flags &= ~STA_KEY_FLG_INVALID;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations[sta_id].keyinfo.cipher = keyconf->cipher;
-	priv->stations[sta_id].keyinfo.keylen = keyconf->keylen;
-	memcpy(priv->stations[sta_id].keyinfo.key, keyconf->key,
-	       keyconf->keylen);
-
-	memcpy(priv->stations[sta_id].sta.key.key, keyconf->key,
-	       keyconf->keylen);
-
-	if ((priv->stations[sta_id].sta.key.key_flags & STA_KEY_FLG_ENCRYPT_MSK)
-			== STA_KEY_FLG_NO_ENC)
-		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[sta_id].sta.key.key_offset == WEP_INVALID_OFFSET,
-		"no space for a new key");
-
-	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, &priv->stations[sta_id].sta, CMD_ASYNC);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return ret;
-}
-
-static int iwl3945_set_tkip_dynamic_key_info(struct iwl_priv *priv,
-				  struct ieee80211_key_conf *keyconf,
-				  u8 sta_id)
-{
-	return -EOPNOTSUPP;
-}
-
-static int iwl3945_set_wep_dynamic_key_info(struct iwl_priv *priv,
-				  struct ieee80211_key_conf *keyconf,
-				  u8 sta_id)
-{
-	return -EOPNOTSUPP;
-}
-
-static int iwl3945_clear_sta_key_info(struct iwl_priv *priv, u8 sta_id)
-{
-	unsigned long flags;
-	struct iwl_addsta_cmd sta_cmd;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	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[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;
-	memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	IWL_DEBUG_INFO(priv, "hwcrypto: clear ucode station key info\n");
-	return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
-}
-
-static int iwl3945_set_dynamic_key(struct iwl_priv *priv,
-			struct ieee80211_key_conf *keyconf, u8 sta_id)
-{
-	int ret = 0;
-
-	keyconf->hw_key_idx = HW_KEY_DYNAMIC;
-
-	switch (keyconf->cipher) {
-	case WLAN_CIPHER_SUITE_CCMP:
-		ret = iwl3945_set_ccmp_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	case WLAN_CIPHER_SUITE_TKIP:
-		ret = iwl3945_set_tkip_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	case WLAN_CIPHER_SUITE_WEP40:
-	case WLAN_CIPHER_SUITE_WEP104:
-		ret = iwl3945_set_wep_dynamic_key_info(priv, keyconf, sta_id);
-		break;
-	default:
-		IWL_ERR(priv, "Unknown alg: %s alg=%x\n", __func__,
-			keyconf->cipher);
-		ret = -EINVAL;
-	}
-
-	IWL_DEBUG_WEP(priv, "Set dynamic key: alg=%x len=%d idx=%d sta=%d ret=%d\n",
-		      keyconf->cipher, keyconf->keylen, keyconf->keyidx,
-		      sta_id, ret);
-
-	return ret;
-}
-
-static int iwl3945_remove_static_key(struct iwl_priv *priv)
-{
-	int ret = -EOPNOTSUPP;
-
-	return ret;
-}
-
-static int iwl3945_set_static_key(struct iwl_priv *priv,
-				struct ieee80211_key_conf *key)
-{
-	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
-	    key->cipher == WLAN_CIPHER_SUITE_WEP104)
-		return -EOPNOTSUPP;
-
-	IWL_ERR(priv, "Static key invalid: cipher %x\n", key->cipher);
-	return -EINVAL;
-}
-
-static void iwl3945_clear_free_frames(struct iwl_priv *priv)
-{
-	struct list_head *element;
-
-	IWL_DEBUG_INFO(priv, "%d frames on pre-allocated heap on clear.\n",
-		       priv->frames_count);
-
-	while (!list_empty(&priv->free_frames)) {
-		element = priv->free_frames.next;
-		list_del(element);
-		kfree(list_entry(element, struct iwl3945_frame, list));
-		priv->frames_count--;
-	}
-
-	if (priv->frames_count) {
-		IWL_WARN(priv, "%d frames still in use.  Did we lose one?\n",
-			    priv->frames_count);
-		priv->frames_count = 0;
-	}
-}
-
-static struct iwl3945_frame *iwl3945_get_free_frame(struct iwl_priv *priv)
-{
-	struct iwl3945_frame *frame;
-	struct list_head *element;
-	if (list_empty(&priv->free_frames)) {
-		frame = kzalloc(sizeof(*frame), GFP_KERNEL);
-		if (!frame) {
-			IWL_ERR(priv, "Could not allocate frame!\n");
-			return NULL;
-		}
-
-		priv->frames_count++;
-		return frame;
-	}
-
-	element = priv->free_frames.next;
-	list_del(element);
-	return list_entry(element, struct iwl3945_frame, list);
-}
-
-static void iwl3945_free_frame(struct iwl_priv *priv, struct iwl3945_frame *frame)
-{
-	memset(frame, 0, sizeof(*frame));
-	list_add(&frame->list, &priv->free_frames);
-}
-
-unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
-				struct ieee80211_hdr *hdr,
-				int left)
-{
-
-	if (!iwl_is_associated(priv, IWL_RXON_CTX_BSS) || !priv->beacon_skb)
-		return 0;
-
-	if (priv->beacon_skb->len > left)
-		return 0;
-
-	memcpy(hdr, priv->beacon_skb->data, priv->beacon_skb->len);
-
-	return priv->beacon_skb->len;
-}
-
-static int iwl3945_send_beacon_cmd(struct iwl_priv *priv)
-{
-	struct iwl3945_frame *frame;
-	unsigned int frame_size;
-	int rc;
-	u8 rate;
-
-	frame = iwl3945_get_free_frame(priv);
-
-	if (!frame) {
-		IWL_ERR(priv, "Could not obtain free frame buffer for beacon "
-			  "command.\n");
-		return -ENOMEM;
-	}
-
-	rate = iwl_rate_get_lowest_plcp(priv,
-				&priv->contexts[IWL_RXON_CTX_BSS]);
-
-	frame_size = iwl3945_hw_get_beacon_cmd(priv, frame, rate);
-
-	rc = iwl_send_cmd_pdu(priv, REPLY_TX_BEACON, frame_size,
-			      &frame->u.cmd[0]);
-
-	iwl3945_free_frame(priv, frame);
-
-	return rc;
-}
-
-static void iwl3945_unset_hw_params(struct iwl_priv *priv)
-{
-	if (priv->_3945.shared_virt)
-		dma_free_coherent(&priv->pci_dev->dev,
-				  sizeof(struct iwl3945_shared),
-				  priv->_3945.shared_virt,
-				  priv->_3945.shared_phys);
-}
-
-static void iwl3945_build_tx_cmd_hwcrypto(struct iwl_priv *priv,
-				      struct ieee80211_tx_info *info,
-				      struct iwl_device_cmd *cmd,
-				      struct sk_buff *skb_frag,
-				      int sta_id)
-{
-	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-	struct iwl_hw_key *keyinfo = &priv->stations[sta_id].keyinfo;
-
-	tx_cmd->sec_ctl = 0;
-
-	switch (keyinfo->cipher) {
-	case WLAN_CIPHER_SUITE_CCMP:
-		tx_cmd->sec_ctl = TX_CMD_SEC_CCM;
-		memcpy(tx_cmd->key, keyinfo->key, keyinfo->keylen);
-		IWL_DEBUG_TX(priv, "tx_cmd with AES hwcrypto\n");
-		break;
-
-	case WLAN_CIPHER_SUITE_TKIP:
-		break;
-
-	case WLAN_CIPHER_SUITE_WEP104:
-		tx_cmd->sec_ctl |= TX_CMD_SEC_KEY128;
-		/* fall through */
-	case WLAN_CIPHER_SUITE_WEP40:
-		tx_cmd->sec_ctl |= TX_CMD_SEC_WEP |
-		    (info->control.hw_key->hw_key_idx & TX_CMD_SEC_MSK) << TX_CMD_SEC_SHIFT;
-
-		memcpy(&tx_cmd->key[3], keyinfo->key, keyinfo->keylen);
-
-		IWL_DEBUG_TX(priv, "Configuring packet for WEP encryption "
-			     "with key %d\n", info->control.hw_key->hw_key_idx);
-		break;
-
-	default:
-		IWL_ERR(priv, "Unknown encode cipher %x\n", keyinfo->cipher);
-		break;
-	}
-}
-
-/*
- * handle build REPLY_TX command notification.
- */
-static void iwl3945_build_tx_cmd_basic(struct iwl_priv *priv,
-				  struct iwl_device_cmd *cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr, u8 std_id)
-{
-	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-	__le32 tx_flags = tx_cmd->tx_flags;
-	__le16 fc = hdr->frame_control;
-
-	tx_cmd->stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-	if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) {
-		tx_flags |= TX_CMD_FLG_ACK_MSK;
-		if (ieee80211_is_mgmt(fc))
-			tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-		if (ieee80211_is_probe_resp(fc) &&
-		    !(le16_to_cpu(hdr->seq_ctrl) & 0xf))
-			tx_flags |= TX_CMD_FLG_TSF_MSK;
-	} else {
-		tx_flags &= (~TX_CMD_FLG_ACK_MSK);
-		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-	}
-
-	tx_cmd->sta_id = std_id;
-	if (ieee80211_has_morefrags(fc))
-		tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
-
-	if (ieee80211_is_data_qos(fc)) {
-		u8 *qc = ieee80211_get_qos_ctl(hdr);
-		tx_cmd->tid_tspec = qc[0] & 0xf;
-		tx_flags &= ~TX_CMD_FLG_SEQ_CTL_MSK;
-	} else {
-		tx_flags |= TX_CMD_FLG_SEQ_CTL_MSK;
-	}
-
-	priv->cfg->ops->utils->tx_cmd_protection(priv, info, fc, &tx_flags);
-
-	tx_flags &= ~(TX_CMD_FLG_ANT_SEL_MSK);
-	if (ieee80211_is_mgmt(fc)) {
-		if (ieee80211_is_assoc_req(fc) || ieee80211_is_reassoc_req(fc))
-			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(3);
-		else
-			tx_cmd->timeout.pm_frame_timeout = cpu_to_le16(2);
-	} else {
-		tx_cmd->timeout.pm_frame_timeout = 0;
-	}
-
-	tx_cmd->driver_txop = 0;
-	tx_cmd->tx_flags = tx_flags;
-	tx_cmd->next_frame_len = 0;
-}
-
-/*
- * start REPLY_TX command process
- */
-static int iwl3945_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
-{
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-	struct iwl3945_tx_cmd *tx_cmd;
-	struct iwl_tx_queue *txq = NULL;
-	struct iwl_queue *q = NULL;
-	struct iwl_device_cmd *out_cmd;
-	struct iwl_cmd_meta *out_meta;
-	dma_addr_t phys_addr;
-	dma_addr_t txcmd_phys;
-	int txq_id = skb_get_queue_mapping(skb);
-	u16 len, idx, hdr_len;
-	u8 id;
-	u8 unicast;
-	u8 sta_id;
-	u8 tid = 0;
-	__le16 fc;
-	u8 wait_write_ptr = 0;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (iwl_is_rfkill(priv)) {
-		IWL_DEBUG_DROP(priv, "Dropping - RF KILL\n");
-		goto drop_unlock;
-	}
-
-	if ((ieee80211_get_tx_rate(priv->hw, info)->hw_value & 0xFF) == IWL_INVALID_RATE) {
-		IWL_ERR(priv, "ERROR: No TX rate available.\n");
-		goto drop_unlock;
-	}
-
-	unicast = !is_multicast_ether_addr(hdr->addr1);
-	id = 0;
-
-	fc = hdr->frame_control;
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (ieee80211_is_auth(fc))
-		IWL_DEBUG_TX(priv, "Sending AUTH frame\n");
-	else if (ieee80211_is_assoc_req(fc))
-		IWL_DEBUG_TX(priv, "Sending ASSOC frame\n");
-	else if (ieee80211_is_reassoc_req(fc))
-		IWL_DEBUG_TX(priv, "Sending REASSOC frame\n");
-#endif
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	hdr_len = ieee80211_hdrlen(fc);
-
-	/* Find index into station table for destination station */
-	sta_id = iwl_sta_id_or_broadcast(
-			priv, &priv->contexts[IWL_RXON_CTX_BSS],
-			info->control.sta);
-	if (sta_id == IWL_INVALID_STATION) {
-		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-			       hdr->addr1);
-		goto drop;
-	}
-
-	IWL_DEBUG_RATE(priv, "station Id %d\n", sta_id);
-
-	if (ieee80211_is_data_qos(fc)) {
-		u8 *qc = ieee80211_get_qos_ctl(hdr);
-		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
-		if (unlikely(tid >= MAX_TID_COUNT))
-			goto drop;
-	}
-
-	/* Descriptor for chosen Tx queue */
-	txq = &priv->txq[txq_id];
-	q = &txq->q;
-
-	if ((iwl_queue_space(q) < q->high_mark))
-		goto drop;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	idx = get_cmd_index(q, q->write_ptr, 0);
-
-	/* Set up driver data for this TFD */
-	memset(&(txq->txb[q->write_ptr]), 0, sizeof(struct iwl_tx_info));
-	txq->txb[q->write_ptr].skb = skb;
-	txq->txb[q->write_ptr].ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	/* Init first empty entry in queue's array of Tx/cmd buffers */
-	out_cmd = txq->cmd[idx];
-	out_meta = &txq->meta[idx];
-	tx_cmd = (struct iwl3945_tx_cmd *)out_cmd->cmd.payload;
-	memset(&out_cmd->hdr, 0, sizeof(out_cmd->hdr));
-	memset(tx_cmd, 0, sizeof(*tx_cmd));
-
-	/*
-	 * Set up the Tx-command (not MAC!) header.
-	 * Store the chosen Tx queue and TFD index within the sequence field;
-	 * after Tx, uCode's Tx response will return this value so driver can
-	 * locate the frame within the tx queue and do post-tx processing.
-	 */
-	out_cmd->hdr.cmd = REPLY_TX;
-	out_cmd->hdr.sequence = cpu_to_le16((u16)(QUEUE_TO_SEQ(txq_id) |
-				INDEX_TO_SEQ(q->write_ptr)));
-
-	/* Copy MAC header from skb into command buffer */
-	memcpy(tx_cmd->hdr, hdr, hdr_len);
-
-
-	if (info->control.hw_key)
-		iwl3945_build_tx_cmd_hwcrypto(priv, info, out_cmd, skb, sta_id);
-
-	/* TODO need this for burst mode later on */
-	iwl3945_build_tx_cmd_basic(priv, out_cmd, info, hdr, sta_id);
-
-	/* set is_hcca to 0; it probably will never be implemented */
-	iwl3945_hw_build_tx_cmd_rate(priv, out_cmd, info, hdr, sta_id, 0);
-
-	/* Total # bytes to be transmitted */
-	len = (u16)skb->len;
-	tx_cmd->len = cpu_to_le16(len);
-
-	iwl_dbg_log_tx_data_frame(priv, len, hdr);
-	iwl_update_stats(priv, true, fc, len);
-	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_A_MSK;
-	tx_cmd->tx_flags &= ~TX_CMD_FLG_ANT_B_MSK;
-
-	if (!ieee80211_has_morefrags(hdr->frame_control)) {
-		txq->need_update = 1;
-	} else {
-		wait_write_ptr = 1;
-		txq->need_update = 0;
-	}
-
-	IWL_DEBUG_TX(priv, "sequence nr = 0X%x\n",
-		     le16_to_cpu(out_cmd->hdr.sequence));
-	IWL_DEBUG_TX(priv, "tx_flags = 0X%x\n", le32_to_cpu(tx_cmd->tx_flags));
-	iwl_print_hex_dump(priv, IWL_DL_TX, tx_cmd, sizeof(*tx_cmd));
-	iwl_print_hex_dump(priv, IWL_DL_TX, (u8 *)tx_cmd->hdr,
-			   ieee80211_hdrlen(fc));
-
-	/*
-	 * Use the first empty entry in this queue's command buffer array
-	 * to contain the Tx command and MAC header concatenated together
-	 * (payload data will be in another buffer).
-	 * Size of this varies, due to varying MAC header length.
-	 * If end is not dword aligned, we'll have 2 extra bytes at the end
-	 * of the MAC header (device reads on dword boundaries).
-	 * We'll tell device about this padding later.
-	 */
-	len = sizeof(struct iwl3945_tx_cmd) +
-			sizeof(struct iwl_cmd_header) + hdr_len;
-	len = (len + 3) & ~3;
-
-	/* Physical address of this Tx command's header (not MAC header!),
-	 * within command buffer array. */
-	txcmd_phys = pci_map_single(priv->pci_dev, &out_cmd->hdr,
-				    len, PCI_DMA_TODEVICE);
-	/* we do not map meta data ... so we can safely access address to
-	 * provide to unmap command*/
-	dma_unmap_addr_set(out_meta, mapping, txcmd_phys);
-	dma_unmap_len_set(out_meta, len, len);
-
-	/* Add buffer containing Tx command and MAC(!) header to TFD's
-	 * first entry */
-	priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-						   txcmd_phys, len, 1, 0);
-
-
-	/* Set up TFD's 2nd entry to point directly to remainder of skb,
-	 * if any (802.11 null frames have no payload). */
-	len = skb->len - hdr_len;
-	if (len) {
-		phys_addr = pci_map_single(priv->pci_dev, skb->data + hdr_len,
-					   len, PCI_DMA_TODEVICE);
-		priv->cfg->ops->lib->txq_attach_buf_to_tfd(priv, txq,
-							   phys_addr, len,
-							   0, U32_PAD(len));
-	}
-
-
-	/* Tell device the write index *just past* this latest filled TFD */
-	q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
-	iwl_txq_update_write_ptr(priv, txq);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if ((iwl_queue_space(q) < q->high_mark)
-	    && priv->mac80211_registered) {
-		if (wait_write_ptr) {
-			spin_lock_irqsave(&priv->lock, flags);
-			txq->need_update = 1;
-			iwl_txq_update_write_ptr(priv, txq);
-			spin_unlock_irqrestore(&priv->lock, flags);
-		}
-
-		iwl_stop_queue(priv, txq);
-	}
-
-	return 0;
-
-drop_unlock:
-	spin_unlock_irqrestore(&priv->lock, flags);
-drop:
-	return -1;
-}
-
-static int iwl3945_get_measurement(struct iwl_priv *priv,
-			       struct ieee80211_measurement_params *params,
-			       u8 type)
-{
-	struct iwl_spectrum_cmd spectrum;
-	struct iwl_rx_packet *pkt;
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_SPECTRUM_MEASUREMENT_CMD,
-		.data = (void *)&spectrum,
-		.flags = CMD_WANT_SKB,
-	};
-	u32 add_time = le64_to_cpu(params->start_time);
-	int rc;
-	int spectrum_resp_status;
-	int duration = le16_to_cpu(params->duration);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
-		add_time = iwl_usecs_to_beacons(priv,
-			le64_to_cpu(params->start_time) - priv->_3945.last_tsf,
-			le16_to_cpu(ctx->timing.beacon_interval));
-
-	memset(&spectrum, 0, sizeof(spectrum));
-
-	spectrum.channel_count = cpu_to_le16(1);
-	spectrum.flags =
-	    RXON_FLG_TSF2HOST_MSK | RXON_FLG_ANT_A_MSK | RXON_FLG_DIS_DIV_MSK;
-	spectrum.filter_flags = MEASUREMENT_FILTER_FLAG;
-	cmd.len = sizeof(spectrum);
-	spectrum.len = cpu_to_le16(cmd.len - sizeof(spectrum.len));
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS))
-		spectrum.start_time =
-			iwl_add_beacon_time(priv,
-				priv->_3945.last_beacon_time, add_time,
-				le16_to_cpu(ctx->timing.beacon_interval));
-	else
-		spectrum.start_time = 0;
-
-	spectrum.channels[0].duration = cpu_to_le32(duration * TIME_UNIT);
-	spectrum.channels[0].channel = params->channel;
-	spectrum.channels[0].type = type;
-	if (ctx->active.flags & RXON_FLG_BAND_24G_MSK)
-		spectrum.flags |= RXON_FLG_BAND_24G_MSK |
-		    RXON_FLG_AUTO_DETECT_MSK | RXON_FLG_TGG_PROTECT_MSK;
-
-	rc = iwl_send_cmd_sync(priv, &cmd);
-	if (rc)
-		return rc;
-
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(priv, "Bad return from REPLY_RX_ON_ASSOC command\n");
-		rc = -EIO;
-	}
-
-	spectrum_resp_status = le16_to_cpu(pkt->u.spectrum.status);
-	switch (spectrum_resp_status) {
-	case 0:		/* Command will be handled */
-		if (pkt->u.spectrum.id != 0xff) {
-			IWL_DEBUG_INFO(priv, "Replaced existing measurement: %d\n",
-						pkt->u.spectrum.id);
-			priv->measurement_status &= ~MEASUREMENT_READY;
-		}
-		priv->measurement_status |= MEASUREMENT_ACTIVE;
-		rc = 0;
-		break;
-
-	case 1:		/* Command will not be handled */
-		rc = -EAGAIN;
-		break;
-	}
-
-	iwl_free_pages(priv, cmd.reply_page);
-
-	return rc;
-}
-
-static void iwl3945_rx_reply_alive(struct iwl_priv *priv,
-			       struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_alive_resp *palive;
-	struct delayed_work *pwork;
-
-	palive = &pkt->u.alive_frame;
-
-	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
-		       "0x%01X 0x%01X\n",
-		       palive->is_valid, palive->ver_type,
-		       palive->ver_subtype);
-
-	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
-		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-		memcpy(&priv->card_alive_init, &pkt->u.alive_frame,
-		       sizeof(struct iwl_alive_resp));
-		pwork = &priv->init_alive_start;
-	} else {
-		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-		memcpy(&priv->card_alive, &pkt->u.alive_frame,
-		       sizeof(struct iwl_alive_resp));
-		pwork = &priv->alive_start;
-		iwl3945_disable_events(priv);
-	}
-
-	/* We delay the ALIVE response by 5ms to
-	 * give the HW RF Kill time to activate... */
-	if (palive->is_valid == UCODE_VALID_OK)
-		queue_delayed_work(priv->workqueue, pwork,
-				   msecs_to_jiffies(5));
-	else
-		IWL_WARN(priv, "uCode did not respond OK.\n");
-}
-
-static void iwl3945_rx_reply_add_sta(struct iwl_priv *priv,
-				 struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-#endif
-
-	IWL_DEBUG_RX(priv, "Received REPLY_ADD_STA: 0x%02X\n", pkt->u.status);
-}
-
-static void iwl3945_bg_beacon_update(struct work_struct *work)
-{
-	struct iwl_priv *priv =
-		container_of(work, struct iwl_priv, beacon_update);
-	struct sk_buff *beacon;
-
-	/* Pull updated AP beacon from mac80211. will fail if not in AP mode */
-	beacon = ieee80211_beacon_get(priv->hw,
-			priv->contexts[IWL_RXON_CTX_BSS].vif);
-
-	if (!beacon) {
-		IWL_ERR(priv, "update beacon failed\n");
-		return;
-	}
-
-	mutex_lock(&priv->mutex);
-	/* new beacon skb is allocated every time; dispose previous.*/
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = beacon;
-	mutex_unlock(&priv->mutex);
-
-	iwl3945_send_beacon_cmd(priv);
-}
-
-static void iwl3945_rx_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl3945_beacon_notif *beacon = &(pkt->u.beacon_status);
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u8 rate = beacon->beacon_notify_hdr.rate;
-
-	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
-		"tsf %d %d rate %d\n",
-		le32_to_cpu(beacon->beacon_notify_hdr.status) & TX_STATUS_MSK,
-		beacon->beacon_notify_hdr.failure_frame,
-		le32_to_cpu(beacon->ibss_mgr_status),
-		le32_to_cpu(beacon->high_tsf),
-		le32_to_cpu(beacon->low_tsf), rate);
-#endif
-
-	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-
-	if ((priv->iw_mode == NL80211_IFTYPE_AP) &&
-	    (!test_bit(STATUS_EXIT_PENDING, &priv->status)))
-		queue_work(priv->workqueue, &priv->beacon_update);
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl3945_rx_card_state_notif(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-	unsigned long status = priv->status;
-
-	IWL_WARN(priv, "Card state received: HW:%s SW:%s\n",
-			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-			  (flags & SW_CARD_DISABLED) ? "Kill" : "On");
-
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-	if (flags & HW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-
-
-	iwl_scan_cancel(priv);
-
-	if ((test_bit(STATUS_RF_KILL_HW, &status) !=
-	     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);
-}
-
-/**
- * iwl3945_setup_rx_handlers - Initialize Rx handler callbacks
- *
- * Setup the RX handlers for each of the reply types sent from the uCode
- * to the host.
- *
- * This function chains into the hardware specific files for them to setup
- * any hardware specific handlers as well.
- */
-static void iwl3945_setup_rx_handlers(struct iwl_priv *priv)
-{
-	priv->rx_handlers[REPLY_ALIVE] = iwl3945_rx_reply_alive;
-	priv->rx_handlers[REPLY_ADD_STA] = iwl3945_rx_reply_add_sta;
-	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
-	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
-	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-			iwl_rx_spectrum_measure_notif;
-	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
-	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-	    iwl_rx_pm_debug_statistics_notif;
-	priv->rx_handlers[BEACON_NOTIFICATION] = iwl3945_rx_beacon_notif;
-
-	/*
-	 * The same handler is used for both the REPLY to a discrete
-	 * statistics request from the host as well as for the periodic
-	 * statistics notifications (after received beacons) from the uCode.
-	 */
-	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl3945_reply_statistics;
-	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl3945_hw_rx_statistics;
-
-	iwl_setup_rx_scan_handlers(priv);
-	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl3945_rx_card_state_notif;
-
-	/* Set up hardware specific Rx handlers */
-	iwl3945_hw_rx_handler_setup(priv);
-}
-
-/************************** RX-FUNCTIONS ****************************/
-/*
- * Rx theory of operation
- *
- * The host allocates 32 DMA target addresses and passes the host address
- * to the firmware at register IWL_RFDS_TABLE_LOWER + N * RFD_SIZE where N is
- * 0 to 31
- *
- * Rx Queue Indexes
- * The host/firmware share two index registers for managing the Rx buffers.
- *
- * The READ index maps to the first position that the firmware may be writing
- * to -- the driver can read up to (but not including) this position and get
- * good data.
- * The READ index is managed by the firmware once the card is enabled.
- *
- * The WRITE index maps to the last position the driver has read from -- the
- * position preceding WRITE is the last slot the firmware can place a packet.
- *
- * The queue is empty (no good data) if WRITE = READ - 1, and is full if
- * WRITE = READ.
- *
- * During initialization, the host sets up the READ queue position to the first
- * INDEX position, and WRITE to the last (READ - 1 wrapped)
- *
- * When the firmware places a packet in a buffer, it will advance the READ index
- * and fire the RX interrupt.  The driver can then query the READ index and
- * process as many packets as possible, moving the WRITE index forward as it
- * resets the Rx queue buffers with new memory.
- *
- * The management in the driver is as follows:
- * + A list of pre-allocated SKBs is stored in iwl->rxq->rx_free.  When
- *   iwl->rxq->free_count drops to or below RX_LOW_WATERMARK, work is scheduled
- *   to replenish the iwl->rxq->rx_free.
- * + In iwl3945_rx_replenish (scheduled) if 'processed' != 'read' then the
- *   iwl->rxq is replenished and the READ INDEX is updated (updating the
- *   'processed' and 'read' driver indexes as well)
- * + A received packet is processed and handed to the kernel network stack,
- *   detached from the iwl->rxq.  The driver 'processed' index is updated.
- * + The Host/Firmware iwl->rxq is replenished at tasklet time from the rx_free
- *   list. If there are no allocated buffers in iwl->rxq->rx_free, the READ
- *   INDEX is not incremented and iwl->status(RX_STALLED) is set.  If there
- *   were enough free buffers and RX_STALLED is set it is cleared.
- *
- *
- * Driver sequence:
- *
- * iwl3945_rx_replenish()     Replenishes rx_free list from rx_used, and calls
- *                            iwl3945_rx_queue_restock
- * iwl3945_rx_queue_restock() Moves available buffers from rx_free into Rx
- *                            queue, updates firmware pointers, and updates
- *                            the WRITE index.  If insufficient rx_free buffers
- *                            are available, schedules iwl3945_rx_replenish
- *
- * -- enable interrupts --
- * ISR - iwl3945_rx()         Detach iwl_rx_mem_buffers from pool up to the
- *                            READ INDEX, detaching the SKB from the pool.
- *                            Moves the packet buffer from queue to rx_used.
- *                            Calls iwl3945_rx_queue_restock to refill any empty
- *                            slots.
- * ...
- *
- */
-
-/**
- * iwl3945_dma_addr2rbd_ptr - convert a DMA address to a uCode read buffer ptr
- */
-static inline __le32 iwl3945_dma_addr2rbd_ptr(struct iwl_priv *priv,
-					  dma_addr_t dma_addr)
-{
-	return cpu_to_le32((u32)dma_addr);
-}
-
-/**
- * iwl3945_rx_queue_restock - refill RX queue from pre-allocated pool
- *
- * If there are slots in the RX queue that need to be restocked,
- * and we have free pre-allocated buffers, fill the ranks as much
- * as we can, pulling from rx_free.
- *
- * This moves the 'write' index forward to catch up with 'processed', and
- * also updates the memory address in the firmware to reference the new
- * target buffer.
- */
-static void iwl3945_rx_queue_restock(struct iwl_priv *priv)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct list_head *element;
-	struct iwl_rx_mem_buffer *rxb;
-	unsigned long flags;
-	int write;
-
-	spin_lock_irqsave(&rxq->lock, flags);
-	write = rxq->write & ~0x7;
-	while ((iwl_rx_queue_space(rxq) > 0) && (rxq->free_count)) {
-		/* Get next free Rx buffer, remove from free list */
-		element = rxq->rx_free.next;
-		rxb = list_entry(element, struct iwl_rx_mem_buffer, list);
-		list_del(element);
-
-		/* Point to Rx buffer via next RBD in circular buffer */
-		rxq->bd[rxq->write] = iwl3945_dma_addr2rbd_ptr(priv, rxb->page_dma);
-		rxq->queue[rxq->write] = rxb;
-		rxq->write = (rxq->write + 1) & RX_QUEUE_MASK;
-		rxq->free_count--;
-	}
-	spin_unlock_irqrestore(&rxq->lock, flags);
-	/* If the pre-allocated buffer pool is dropping low, schedule to
-	 * refill it */
-	if (rxq->free_count <= RX_LOW_WATERMARK)
-		queue_work(priv->workqueue, &priv->rx_replenish);
-
-
-	/* If we've added more space for the firmware to place data, tell it.
-	 * Increment device's write pointer in multiples of 8. */
-	if ((rxq->write_actual != (rxq->write & ~0x7))
-	    || (abs(rxq->write - rxq->read) > 7)) {
-		spin_lock_irqsave(&rxq->lock, flags);
-		rxq->need_update = 1;
-		spin_unlock_irqrestore(&rxq->lock, flags);
-		iwl_rx_queue_update_write_ptr(priv, rxq);
-	}
-}
-
-/**
- * iwl3945_rx_replenish - Move all used packet from rx_used to rx_free
- *
- * When moving to rx_free an SKB is allocated for the slot.
- *
- * 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, gfp_t priority)
-{
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	struct list_head *element;
-	struct iwl_rx_mem_buffer *rxb;
-	struct page *page;
-	unsigned long flags;
-	gfp_t gfp_mask = priority;
-
-	while (1) {
-		spin_lock_irqsave(&rxq->lock, flags);
-
-		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
-			return;
-		}
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		if (rxq->free_count > RX_LOW_WATERMARK)
-			gfp_mask |= __GFP_NOWARN;
-
-		if (priv->hw_params.rx_page_order > 0)
-			gfp_mask |= __GFP_COMP;
-
-		/* Alloc a new receive buffer */
-		page = alloc_pages(gfp_mask, priv->hw_params.rx_page_order);
-		if (!page) {
-			if (net_ratelimit())
-				IWL_DEBUG_INFO(priv, "Failed to allocate SKB buffer.\n");
-			if ((rxq->free_count <= RX_LOW_WATERMARK) &&
-			    net_ratelimit())
-				IWL_CRIT(priv, "Failed to allocate SKB buffer with %s. Only %u free buffers remaining.\n",
-					 priority == GFP_ATOMIC ?  "GFP_ATOMIC" : "GFP_KERNEL",
-					 rxq->free_count);
-			/* We don't reschedule replenish work here -- we will
-			 * call the restock method and if it still needs
-			 * more buffers it will schedule replenish */
-			break;
-		}
-
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (list_empty(&rxq->rx_used)) {
-			spin_unlock_irqrestore(&rxq->lock, flags);
-			__free_pages(page, priv->hw_params.rx_page_order);
-			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);
-
-		rxb->page = page;
-		/* Get physical address of RB/SKB */
-		rxb->page_dma = pci_map_page(priv->pci_dev, page, 0,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-
-		spin_lock_irqsave(&rxq->lock, flags);
-
-		list_add_tail(&rxb->list, &rxq->rx_free);
-		rxq->free_count++;
-		priv->alloc_rxb_page++;
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-	}
-}
-
-void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	unsigned long flags;
-	int i;
-	spin_lock_irqsave(&rxq->lock, flags);
-	INIT_LIST_HEAD(&rxq->rx_free);
-	INIT_LIST_HEAD(&rxq->rx_used);
-	/* Fill the rx_used queue with _all_ of the Rx buffers */
-	for (i = 0; i < RX_FREE_BUFFERS + RX_QUEUE_SIZE; i++) {
-		/* In the reset function, these buffers may have been allocated
-		 * to an SKB, so we need to unmap and free potential storage */
-		if (rxq->pool[i].page != NULL) {
-			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			__iwl_free_pages(priv, rxq->pool[i].page);
-			rxq->pool[i].page = NULL;
-		}
-		list_add_tail(&rxq->pool[i].list, &rxq->rx_used);
-	}
-
-	/* 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);
-}
-
-void iwl3945_rx_replenish(void *data)
-{
-	struct iwl_priv *priv = data;
-	unsigned long flags;
-
-	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
- * non NULL it is unmapped and freed
- */
-static void iwl3945_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	int i;
-	for (i = 0; i < RX_QUEUE_SIZE + RX_FREE_BUFFERS; i++) {
-		if (rxq->pool[i].page != NULL) {
-			pci_unmap_page(priv->pci_dev, rxq->pool[i].page_dma,
-				PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			__iwl_free_pages(priv, rxq->pool[i].page);
-			rxq->pool[i].page = NULL;
-		}
-	}
-
-	dma_free_coherent(&priv->pci_dev->dev, 4 * RX_QUEUE_SIZE, rxq->bd,
-			  rxq->bd_dma);
-	dma_free_coherent(&priv->pci_dev->dev, sizeof(struct iwl_rb_status),
-			  rxq->rb_stts, rxq->rb_stts_dma);
-	rxq->bd = NULL;
-	rxq->rb_stts  = NULL;
-}
-
-
-/* Convert linear signal-to-noise ratio into dB */
-static u8 ratio2dB[100] = {
-/*	 0   1   2   3   4   5   6   7   8   9 */
-	 0,  0,  6, 10, 12, 14, 16, 17, 18, 19, /* 00 - 09 */
-	20, 21, 22, 22, 23, 23, 24, 25, 26, 26, /* 10 - 19 */
-	26, 26, 26, 27, 27, 28, 28, 28, 29, 29, /* 20 - 29 */
-	29, 30, 30, 30, 31, 31, 31, 31, 32, 32, /* 30 - 39 */
-	32, 32, 32, 33, 33, 33, 33, 33, 34, 34, /* 40 - 49 */
-	34, 34, 34, 34, 35, 35, 35, 35, 35, 35, /* 50 - 59 */
-	36, 36, 36, 36, 36, 36, 36, 37, 37, 37, /* 60 - 69 */
-	37, 37, 37, 37, 37, 38, 38, 38, 38, 38, /* 70 - 79 */
-	38, 38, 38, 38, 38, 39, 39, 39, 39, 39, /* 80 - 89 */
-	39, 39, 39, 39, 39, 40, 40, 40, 40, 40  /* 90 - 99 */
-};
-
-/* Calculates a relative dB value from a ratio of linear
- *   (i.e. not dB) signal levels.
- * Conversion assumes that levels are voltages (20*log), not powers (10*log). */
-int iwl3945_calc_db_from_ratio(int sig_ratio)
-{
-	/* 1000:1 or higher just report as 60 dB */
-	if (sig_ratio >= 1000)
-		return 60;
-
-	/* 100:1 or higher, divide by 10 and use table,
-	 *   add 20 dB to make up for divide by 10 */
-	if (sig_ratio >= 100)
-		return 20 + (int)ratio2dB[sig_ratio/10];
-
-	/* We shouldn't see this */
-	if (sig_ratio < 1)
-		return 0;
-
-	/* Use table for ratios 1:1 - 99:1 */
-	return (int)ratio2dB[sig_ratio];
-}
-
-/**
- * iwl3945_rx_handle - Main entry function for receiving responses from uCode
- *
- * Uses the priv->rx_handlers callback function array to invoke
- * the appropriate handlers, including command responses,
- * frame-received notifications, and other notifications.
- */
-static void iwl3945_rx_handle(struct iwl_priv *priv)
-{
-	struct iwl_rx_mem_buffer *rxb;
-	struct iwl_rx_packet *pkt;
-	struct iwl_rx_queue *rxq = &priv->rxq;
-	u32 r, i;
-	int reclaim;
-	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;
-
-	/* calculate total frames need to be restock after handling RX */
-	total_empty = r - 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)
-		IWL_DEBUG_RX(priv, "r = %d, i = %d\n", r, i);
-
-	while (i != r) {
-		int len;
-
-		rxb = rxq->queue[i];
-
-		/* If an RXB doesn't have a Rx queue slot associated with it,
-		 * then a bug has been introduced in the queue refilling
-		 * routines -- catch it here */
-		BUG_ON(rxb == NULL);
-
-		rxq->queue[i] = NULL;
-
-		pci_unmap_page(priv->pci_dev, rxb->page_dma,
-			       PAGE_SIZE << priv->hw_params.rx_page_order,
-			       PCI_DMA_FROMDEVICE);
-		pkt = rxb_addr(rxb);
-
-		len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-		len += sizeof(u32); /* account for status word */
-		trace_iwlwifi_dev_rx(priv, pkt, len);
-
-		/* Reclaim a command buffer only if this packet is a response
-		 *   to a (driver-originated) command.
-		 * If the packet (e.g. Rx frame) originated from uCode,
-		 *   there is no command buffer to reclaim.
-		 * Ucode should set SEQ_RX_FRAME bit if ucode-originated,
-		 *   but apparently a few don't get set; catch them here. */
-		reclaim = !(pkt->hdr.sequence & SEQ_RX_FRAME) &&
-			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
-			(pkt->hdr.cmd != REPLY_TX);
-
-		/* Based on type of command response or notification,
-		 *   handle those that need handling via function in
-		 *   rx_handlers table.  See iwl3945_setup_rx_handlers() */
-		if (priv->rx_handlers[pkt->hdr.cmd]) {
-			IWL_DEBUG_RX(priv, "r = %d, i = %d, %s, 0x%02x\n", r, i,
-				get_cmd_string(pkt->hdr.cmd), pkt->hdr.cmd);
-			priv->isr_stats.rx_handlers[pkt->hdr.cmd]++;
-			priv->rx_handlers[pkt->hdr.cmd] (priv, rxb);
-		} else {
-			/* No handling needed */
-			IWL_DEBUG_RX(priv,
-				"r %d i %d No handler needed for %s, 0x%02x\n",
-				r, i, get_cmd_string(pkt->hdr.cmd),
-				pkt->hdr.cmd);
-		}
-
-		/*
-		 * XXX: After here, we should always check rxb->page
-		 * against NULL before touching it or its virtual
-		 * memory (pkt). Because some rx_handler might have
-		 * already taken or freed the pages.
-		 */
-
-		if (reclaim) {
-			/* Invoke any callbacks, transfer the buffer to caller,
-			 * and fire off the (possibly) blocking iwl_send_cmd()
-			 * as we reclaim the driver command queue */
-			if (rxb->page)
-				iwl_tx_cmd_complete(priv, rxb);
-			else
-				IWL_WARN(priv, "Claim null rxb?\n");
-		}
-
-		/* Reuse the page if possible. For notification packets and
-		 * SKBs that fail to Rx correctly, add them back into the
-		 * rx_free list for reuse later. */
-		spin_lock_irqsave(&rxq->lock, flags);
-		if (rxb->page != NULL) {
-			rxb->page_dma = pci_map_page(priv->pci_dev, rxb->page,
-				0, PAGE_SIZE << priv->hw_params.rx_page_order,
-				PCI_DMA_FROMDEVICE);
-			list_add_tail(&rxb->list, &rxq->rx_free);
-			rxq->free_count++;
-		} else
-			list_add_tail(&rxb->list, &rxq->rx_used);
-
-		spin_unlock_irqrestore(&rxq->lock, flags);
-
-		i = (i + 1) & RX_QUEUE_MASK;
-		/* If there are a lot of unused frames,
-		 * restock the Rx queue so ucode won't assert. */
-		if (fill_rx) {
-			count++;
-			if (count >= 8) {
-				rxq->read = i;
-				iwl3945_rx_replenish_now(priv);
-				count = 0;
-			}
-		}
-	}
-
-	/* Backtrack one entry */
-	rxq->read = i;
-	if (fill_rx)
-		iwl3945_rx_replenish_now(priv);
-	else
-		iwl3945_rx_queue_restock(priv);
-}
-
-/* call this function to flush any scheduled tasklet */
-static inline void iwl_synchronize_irq(struct iwl_priv *priv)
-{
-	/* wait to make sure we flush pending tasklet*/
-	synchronize_irq(priv->pci_dev->irq);
-	tasklet_kill(&priv->irq_tasklet);
-}
-
-static const char *desc_lookup(int i)
-{
-	switch (i) {
-	case 1:
-		return "FAIL";
-	case 2:
-		return "BAD_PARAM";
-	case 3:
-		return "BAD_CHECKSUM";
-	case 4:
-		return "NMI_INTERRUPT";
-	case 5:
-		return "SYSASSERT";
-	case 6:
-		return "FATAL_ERROR";
-	}
-
-	return "UNKNOWN";
-}
-
-#define ERROR_START_OFFSET  (1 * sizeof(u32))
-#define ERROR_ELEM_SIZE     (7 * sizeof(u32))
-
-void iwl3945_dump_nic_error_log(struct iwl_priv *priv)
-{
-	u32 i;
-	u32 desc, time, count, base, data1;
-	u32 blink1, blink2, ilink1, ilink2;
-
-	base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
-
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base);
-		return;
-	}
-
-
-	count = iwl_read_targ_mem(priv, base);
-
-	if (ERROR_START_OFFSET <= count * ERROR_ELEM_SIZE) {
-		IWL_ERR(priv, "Start IWL Error Log Dump:\n");
-		IWL_ERR(priv, "Status: 0x%08lX, count: %d\n",
-			priv->status, count);
-	}
-
-	IWL_ERR(priv, "Desc       Time       asrtPC  blink2 "
-		  "ilink1  nmiPC   Line\n");
-	for (i = ERROR_START_OFFSET;
-	     i < (count * ERROR_ELEM_SIZE) + ERROR_START_OFFSET;
-	     i += ERROR_ELEM_SIZE) {
-		desc = iwl_read_targ_mem(priv, base + i);
-		time =
-		    iwl_read_targ_mem(priv, base + i + 1 * sizeof(u32));
-		blink1 =
-		    iwl_read_targ_mem(priv, base + i + 2 * sizeof(u32));
-		blink2 =
-		    iwl_read_targ_mem(priv, base + i + 3 * sizeof(u32));
-		ilink1 =
-		    iwl_read_targ_mem(priv, base + i + 4 * sizeof(u32));
-		ilink2 =
-		    iwl_read_targ_mem(priv, base + i + 5 * sizeof(u32));
-		data1 =
-		    iwl_read_targ_mem(priv, base + i + 6 * sizeof(u32));
-
-		IWL_ERR(priv,
-			"%-13s (0x%X) %010u 0x%05X 0x%05X 0x%05X 0x%05X %u\n\n",
-			desc_lookup(desc), desc, time, blink1, blink2,
-			ilink1, ilink2, data1);
-		trace_iwlwifi_dev_ucode_error(priv, desc, time, data1, 0,
-					0, blink1, blink2, ilink1, ilink2);
-	}
-}
-
-#define EVENT_START_OFFSET  (6 * sizeof(u32))
-
-/**
- * iwl3945_print_event_log - Dump error event log to syslog
- *
- */
-static int iwl3945_print_event_log(struct iwl_priv *priv, u32 start_idx,
-				  u32 num_events, u32 mode,
-				  int pos, char **buf, size_t bufsz)
-{
-	u32 i;
-	u32 base;       /* SRAM byte address of event log header */
-	u32 event_size;	/* 2 u32s, or 3 u32s if timestamp recorded */
-	u32 ptr;        /* SRAM byte address of log data */
-	u32 ev, time, data; /* event log data */
-	unsigned long reg_flags;
-
-	if (num_events == 0)
-		return pos;
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-
-	if (mode == 0)
-		event_size = 2 * sizeof(u32);
-	else
-		event_size = 3 * sizeof(u32);
-
-	ptr = base + EVENT_START_OFFSET + (start_idx * event_size);
-
-	/* Make sure device is powered up for SRAM reads */
-	spin_lock_irqsave(&priv->reg_lock, reg_flags);
-	iwl_grab_nic_access(priv);
-
-	/* Set starting address; reads will auto-increment */
-	_iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR, ptr);
-	rmb();
-
-	/* "time" is actually "data" for mode 0 (no timestamp).
-	 * place event id # at far right for easier visual parsing. */
-	for (i = 0; i < num_events; i++) {
-		ev = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		time = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (mode == 0) {
-			/* data, ev */
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"0x%08x:%04u\n",
-						time, ev);
-			} else {
-				IWL_ERR(priv, "0x%08x\t%04u\n", time, ev);
-				trace_iwlwifi_dev_ucode_event(priv, 0,
-							      time, ev);
-			}
-		} else {
-			data = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-			if (bufsz) {
-				pos += scnprintf(*buf + pos, bufsz - pos,
-						"%010u:0x%08x:%04u\n",
-						 time, data, ev);
-			} else {
-				IWL_ERR(priv, "%010u\t0x%08x\t%04u\n",
-					time, data, ev);
-				trace_iwlwifi_dev_ucode_event(priv, time,
-							      data, ev);
-			}
-		}
-	}
-
-	/* Allow device to power down */
-	iwl_release_nic_access(priv);
-	spin_unlock_irqrestore(&priv->reg_lock, reg_flags);
-	return pos;
-}
-
-/**
- * iwl3945_print_last_event_logs - Dump the newest # of event log to syslog
- */
-static int iwl3945_print_last_event_logs(struct iwl_priv *priv, u32 capacity,
-				      u32 num_wraps, u32 next_entry,
-				      u32 size, u32 mode,
-				      int pos, char **buf, size_t bufsz)
-{
-	/*
-	 * display the newest DEFAULT_LOG_ENTRIES entries
-	 * i.e the entries just before the next ont that uCode would fill.
-	 */
-	if (num_wraps) {
-		if (next_entry < size) {
-			pos = iwl3945_print_event_log(priv,
-					     capacity - (size - next_entry),
-					     size - next_entry, mode,
-					     pos, buf, bufsz);
-			pos = iwl3945_print_event_log(priv, 0,
-						      next_entry, mode,
-						      pos, buf, bufsz);
-		} else
-			pos = iwl3945_print_event_log(priv, next_entry - size,
-						      size, mode,
-						      pos, buf, bufsz);
-	} else {
-		if (next_entry < size)
-			pos = iwl3945_print_event_log(priv, 0,
-						      next_entry, mode,
-						      pos, buf, bufsz);
-		else
-			pos = iwl3945_print_event_log(priv, next_entry - size,
-						      size, mode,
-						      pos, buf, bufsz);
-	}
-	return pos;
-}
-
-#define DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES (20)
-
-int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-			    char **buf, bool display)
-{
-	u32 base;       /* SRAM byte address of event log header */
-	u32 capacity;   /* event log capacity in # entries */
-	u32 mode;       /* 0 - no timestamp, 1 - timestamp recorded */
-	u32 num_wraps;  /* # times uCode wrapped to top of log */
-	u32 next_entry; /* index of next entry to be written by uCode */
-	u32 size;       /* # entries that we'll print */
-	int pos = 0;
-	size_t bufsz = 0;
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-		return  -EINVAL;
-	}
-
-	/* event log header */
-	capacity = iwl_read_targ_mem(priv, base);
-	mode = iwl_read_targ_mem(priv, base + (1 * sizeof(u32)));
-	num_wraps = iwl_read_targ_mem(priv, base + (2 * sizeof(u32)));
-	next_entry = iwl_read_targ_mem(priv, base + (3 * sizeof(u32)));
-
-	if (capacity > priv->cfg->base_params->max_event_log_size) {
-		IWL_ERR(priv, "Log capacity %d is bogus, limit to %d entries\n",
-			capacity, priv->cfg->base_params->max_event_log_size);
-		capacity = priv->cfg->base_params->max_event_log_size;
-	}
-
-	if (next_entry > priv->cfg->base_params->max_event_log_size) {
-		IWL_ERR(priv, "Log write index %d is bogus, limit to %d\n",
-			next_entry, priv->cfg->base_params->max_event_log_size);
-		next_entry = priv->cfg->base_params->max_event_log_size;
-	}
-
-	size = num_wraps ? capacity : next_entry;
-
-	/* bail out if nothing in log */
-	if (size == 0) {
-		IWL_ERR(priv, "Start IWL Event Log Dump: nothing in log\n");
-		return pos;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (!(iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) && !full_log)
-		size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-			? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#else
-	size = (size > DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES)
-		? DEFAULT_IWL3945_DUMP_EVENT_LOG_ENTRIES : size;
-#endif
-
-	IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
-		  size);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (display) {
-		if (full_log)
-			bufsz = capacity * 48;
-		else
-			bufsz = size * 48;
-		*buf = kmalloc(bufsz, GFP_KERNEL);
-		if (!*buf)
-			return -ENOMEM;
-	}
-	if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
-		/* if uCode has wrapped back to top of log,
-		 * start at the oldest entry,
-		 * i.e the next one that uCode would fill.
-		 */
-		if (num_wraps)
-			pos = iwl3945_print_event_log(priv, next_entry,
-						capacity - next_entry, mode,
-						pos, buf, bufsz);
-
-		/* (then/else) start at top of log */
-		pos = iwl3945_print_event_log(priv, 0, next_entry, mode,
-					      pos, buf, bufsz);
-	} else
-		pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-						    next_entry, size, mode,
-						    pos, buf, bufsz);
-#else
-	pos = iwl3945_print_last_event_logs(priv, capacity, num_wraps,
-					    next_entry, size, mode,
-					    pos, buf, bufsz);
-#endif
-	return pos;
-}
-
-static void iwl3945_irq_tasklet(struct iwl_priv *priv)
-{
-	u32 inta, handled = 0;
-	u32 inta_fh;
-	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,
-	 *  and will clear only when CSR_FH_INT_STATUS gets cleared. */
-	inta = iwl_read32(priv, CSR_INT);
-	iwl_write32(priv, CSR_INT, inta);
-
-	/* Ack/clear/reset pending flow-handler (DMA) interrupts.
-	 * Any new interrupts that happen after this, either while we're
-	 * in this tasklet, or later, will show up in next ISR/tasklet. */
-	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-	iwl_write32(priv, CSR_FH_INT_STATUS, inta_fh);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & IWL_DL_ISR) {
-		/* just for debug */
-		inta_mask = iwl_read32(priv, CSR_INT_MASK);
-		IWL_DEBUG_ISR(priv, "inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-			      inta, inta_mask, inta_fh);
-	}
-#endif
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	/* Since CSR_INT and CSR_FH_INT_STATUS reads and clears are not
-	 * atomic, make sure that inta covers all the interrupts that
-	 * we've discovered, even if FH interrupt came in just after
-	 * reading CSR_INT. */
-	if (inta_fh & CSR39_FH_INT_RX_MASK)
-		inta |= CSR_INT_BIT_FH_RX;
-	if (inta_fh & CSR39_FH_INT_TX_MASK)
-		inta |= CSR_INT_BIT_FH_TX;
-
-	/* Now service all interrupt bits discovered above. */
-	if (inta & CSR_INT_BIT_HW_ERR) {
-		IWL_ERR(priv, "Hardware 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;
-
-		return;
-	}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & (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);
-
-	/* 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++;
-		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)) {
-		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));
-		iwl_write_direct32(priv, FH39_TCSR_CREDIT
-					(FH39_SRVC_CHNL), 0x0);
-		handled |= CSR_INT_BIT_FH_TX;
-	}
-
-	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);
-		IWL_WARN(priv, "   with FH_INT = 0x%08x\n", inta_fh);
-	}
-
-	/* Re-enable all interrupts */
-	/* only Re-enable if disabled by irq */
-	if (test_bit(STATUS_INT_ENABLED, &priv->status))
-		iwl_enable_interrupts(priv);
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-	if (iwl_get_debug_level(priv) & (IWL_DL_ISR)) {
-		inta = iwl_read32(priv, CSR_INT);
-		inta_mask = iwl_read32(priv, CSR_INT_MASK);
-		inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-		IWL_DEBUG_ISR(priv, "End inta 0x%08x, enabled 0x%08x, fh 0x%08x, "
-			"flags 0x%08lx\n", inta, inta_mask, inta_fh, flags);
-	}
-#endif
-}
-
-static int iwl3945_get_single_channel_for_scan(struct iwl_priv *priv,
-					       struct ieee80211_vif *vif,
-					       enum ieee80211_band band,
-					       struct iwl3945_scan_channel *scan_ch)
-{
-	const struct ieee80211_supported_band *sband;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added = 0;
-	u8 channel = 0;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband) {
-		IWL_ERR(priv, "invalid band\n");
-		return added;
-	}
-
-	active_dwell = iwl_get_active_dwell_time(priv, band, 0);
-	passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-
-	channel = iwl_get_single_channel_number(priv, band);
-
-	if (channel) {
-		scan_ch->channel = channel;
-		scan_ch->type = 0;	/* passive */
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* Set txpower levels to defaults */
-		scan_ch->tpc.dsp_atten = 110;
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else
-			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-		added++;
-	} else
-		IWL_ERR(priv, "no valid channel found\n");
-	return added;
-}
-
-static int iwl3945_get_channels_for_scan(struct iwl_priv *priv,
-					 enum ieee80211_band band,
-				     u8 is_active, u8 n_probes,
-				     struct iwl3945_scan_channel *scan_ch,
-				     struct ieee80211_vif *vif)
-{
-	struct ieee80211_channel *chan;
-	const struct ieee80211_supported_band *sband;
-	const struct iwl_channel_info *ch_info;
-	u16 passive_dwell = 0;
-	u16 active_dwell = 0;
-	int added, i;
-
-	sband = iwl_get_hw_mode(priv, band);
-	if (!sband)
-		return 0;
-
-	active_dwell = iwl_get_active_dwell_time(priv, band, n_probes);
-	passive_dwell = iwl_get_passive_dwell_time(priv, band, vif);
-
-	if (passive_dwell <= active_dwell)
-		passive_dwell = active_dwell + 1;
-
-	for (i = 0, added = 0; i < priv->scan_request->n_channels; i++) {
-		chan = priv->scan_request->channels[i];
-
-		if (chan->band != band)
-			continue;
-
-		scan_ch->channel = chan->hw_value;
-
-		ch_info = iwl_get_channel_info(priv, band, scan_ch->channel);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_SCAN(priv, "Channel %d is INVALID for this band.\n",
-				       scan_ch->channel);
-			continue;
-		}
-
-		scan_ch->active_dwell = cpu_to_le16(active_dwell);
-		scan_ch->passive_dwell = cpu_to_le16(passive_dwell);
-		/* If passive , set up for auto-switch
-		 *  and use long active_dwell time.
-		 */
-		if (!is_active || is_channel_passive(ch_info) ||
-		    (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)) {
-			scan_ch->type = 0;	/* passive */
-			if (IWL_UCODE_API(priv->ucode_ver) == 1)
-				scan_ch->active_dwell = cpu_to_le16(passive_dwell - 1);
-		} else {
-			scan_ch->type = 1;	/* active */
-		}
-
-		/* Set direct probe bits. These may be used both for active
-		 * scan channels (probes gets sent right away),
-		 * or for passive channels (probes get se sent only after
-		 * hearing clear Rx packet).*/
-		if (IWL_UCODE_API(priv->ucode_ver) >= 2) {
-			if (n_probes)
-				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
-		} else {
-			/* uCode v1 does not allow setting direct probe bits on
-			 * passive channel. */
-			if ((scan_ch->type & 1) && n_probes)
-				scan_ch->type |= IWL39_SCAN_PROBE_MASK(n_probes);
-		}
-
-		/* Set txpower levels to defaults */
-		scan_ch->tpc.dsp_atten = 110;
-		/* scan_pwr_info->tpc.dsp_atten; */
-
-		/*scan_pwr_info->tpc.tx_gain; */
-		if (band == IEEE80211_BAND_5GHZ)
-			scan_ch->tpc.tx_gain = ((1 << 5) | (3 << 3)) | 3;
-		else {
-			scan_ch->tpc.tx_gain = ((1 << 5) | (5 << 3));
-			/* NOTE: if we were doing 6Mb OFDM for scans we'd use
-			 * power level:
-			 * scan_ch->tpc.tx_gain = ((1 << 5) | (2 << 3)) | 3;
-			 */
-		}
-
-		IWL_DEBUG_SCAN(priv, "Scanning %d [%s %d]\n",
-			       scan_ch->channel,
-			       (scan_ch->type & 1) ? "ACTIVE" : "PASSIVE",
-			       (scan_ch->type & 1) ?
-			       active_dwell : passive_dwell);
-
-		scan_ch++;
-		added++;
-	}
-
-	IWL_DEBUG_SCAN(priv, "total channels to scan %d\n", added);
-	return added;
-}
-
-static void iwl3945_init_hw_rates(struct iwl_priv *priv,
-			      struct ieee80211_rate *rates)
-{
-	int i;
-
-	for (i = 0; i < IWL_RATE_COUNT_LEGACY; i++) {
-		rates[i].bitrate = iwl3945_rates[i].ieee * 5;
-		rates[i].hw_value = i; /* Rate scaling will work on indexes */
-		rates[i].hw_value_short = i;
-		rates[i].flags = 0;
-		if ((i > IWL39_LAST_OFDM_RATE) || (i < IWL_FIRST_OFDM_RATE)) {
-			/*
-			 * If CCK != 1M then set short preamble rate flag.
-			 */
-			rates[i].flags |= (iwl3945_rates[i].plcp == 10) ?
-				0 : IEEE80211_RATE_SHORT_PREAMBLE;
-		}
-	}
-}
-
-/******************************************************************************
- *
- * uCode download functions
- *
- ******************************************************************************/
-
-static void iwl3945_dealloc_ucode_pci(struct iwl_priv *priv)
-{
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_code);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-	iwl_free_fw_desc(priv->pci_dev, &priv->ucode_boot);
-}
-
-/**
- * iwl3945_verify_inst_full - verify runtime uCode image in card vs. host,
- *     looking at all data.
- */
-static int iwl3945_verify_inst_full(struct iwl_priv *priv, __le32 *image, u32 len)
-{
-	u32 val;
-	u32 save_len = len;
-	int rc = 0;
-	u32 errcnt;
-
-	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-	iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-			       IWL39_RTC_INST_LOWER_BOUND);
-
-	errcnt = 0;
-	for (; len > 0; len -= sizeof(u32), image++) {
-		/* read data comes through single port, auto-incr addr */
-		/* NOTE: Use the debugless read so we don't flood kernel log
-		 * if IWL_DL_IO is set */
-		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(priv, "uCode INST section is invalid at "
-				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
-				  save_len - len, val, le32_to_cpu(*image));
-			rc = -EIO;
-			errcnt++;
-			if (errcnt >= 20)
-				break;
-		}
-	}
-
-
-	if (!errcnt)
-		IWL_DEBUG_INFO(priv,
-			"ucode image in INSTRUCTION memory is good\n");
-
-	return rc;
-}
-
-
-/**
- * iwl3945_verify_inst_sparse - verify runtime uCode image in card vs. host,
- *   using sample data 100 bytes apart.  If these sample points are good,
- *   it's a pretty good bet that everything between them is good, too.
- */
-static int iwl3945_verify_inst_sparse(struct iwl_priv *priv, __le32 *image, u32 len)
-{
-	u32 val;
-	int rc = 0;
-	u32 errcnt = 0;
-	u32 i;
-
-	IWL_DEBUG_INFO(priv, "ucode inst image size is %u\n", len);
-
-	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
-		 * if IWL_DL_IO is set */
-		iwl_write_direct32(priv, HBUS_TARG_MEM_RADDR,
-			i + IWL39_RTC_INST_LOWER_BOUND);
-		val = _iwl_read_direct32(priv, HBUS_TARG_MEM_RDAT);
-		if (val != le32_to_cpu(*image)) {
-#if 0 /* Enable this if you want to see details */
-			IWL_ERR(priv, "uCode INST section is invalid at "
-				  "offset 0x%x, is 0x%x, s/b 0x%x\n",
-				  i, val, *image);
-#endif
-			rc = -EIO;
-			errcnt++;
-			if (errcnt >= 3)
-				break;
-		}
-	}
-
-	return rc;
-}
-
-
-/**
- * iwl3945_verify_ucode - determine which instruction image is in SRAM,
- *    and verify its contents
- */
-static int iwl3945_verify_ucode(struct iwl_priv *priv)
-{
-	__le32 *image;
-	u32 len;
-	int rc = 0;
-
-	/* Try bootstrap */
-	image = (__le32 *)priv->ucode_boot.v_addr;
-	len = priv->ucode_boot.len;
-	rc = iwl3945_verify_inst_sparse(priv, image, len);
-	if (rc == 0) {
-		IWL_DEBUG_INFO(priv, "Bootstrap uCode is good in inst SRAM\n");
-		return 0;
-	}
-
-	/* Try initialize */
-	image = (__le32 *)priv->ucode_init.v_addr;
-	len = priv->ucode_init.len;
-	rc = iwl3945_verify_inst_sparse(priv, image, len);
-	if (rc == 0) {
-		IWL_DEBUG_INFO(priv, "Initialize uCode is good in inst SRAM\n");
-		return 0;
-	}
-
-	/* Try runtime/protocol */
-	image = (__le32 *)priv->ucode_code.v_addr;
-	len = priv->ucode_code.len;
-	rc = iwl3945_verify_inst_sparse(priv, image, len);
-	if (rc == 0) {
-		IWL_DEBUG_INFO(priv, "Runtime uCode is good in inst SRAM\n");
-		return 0;
-	}
-
-	IWL_ERR(priv, "NO VALID UCODE IMAGE IN INSTRUCTION SRAM!!\n");
-
-	/* Since nothing seems to match, show first several data entries in
-	 * instruction SRAM, so maybe visual inspection will give a clue.
-	 * Selection of bootstrap image (vs. other images) is arbitrary. */
-	image = (__le32 *)priv->ucode_boot.v_addr;
-	len = priv->ucode_boot.len;
-	rc = iwl3945_verify_inst_full(priv, image, len);
-
-	return rc;
-}
-
-static void iwl3945_nic_start(struct iwl_priv *priv)
-{
-	/* Remove all resets to allow NIC to operate */
-	iwl_write32(priv, CSR_RESET, 0);
-}
-
-#define IWL3945_UCODE_GET(item)						\
-static u32 iwl3945_ucode_get_##item(const struct iwl_ucode_header *ucode)\
-{									\
-	return le32_to_cpu(ucode->u.v1.item);				\
-}
-
-static u32 iwl3945_ucode_get_header_size(u32 api_ver)
-{
-	return 24;
-}
-
-static u8 *iwl3945_ucode_get_data(const struct iwl_ucode_header *ucode)
-{
-	return (u8 *) ucode->u.v1.data;
-}
-
-IWL3945_UCODE_GET(inst_size);
-IWL3945_UCODE_GET(data_size);
-IWL3945_UCODE_GET(init_size);
-IWL3945_UCODE_GET(init_data_size);
-IWL3945_UCODE_GET(boot_size);
-
-/**
- * iwl3945_read_ucode - Read uCode images from disk file.
- *
- * Copy into buffers for card to fetch via bus-mastering
- */
-static int iwl3945_read_ucode(struct iwl_priv *priv)
-{
-	const struct iwl_ucode_header *ucode;
-	int ret = -EINVAL, index;
-	const struct firmware *ucode_raw;
-	/* firmware file name contains uCode/driver compatibility version */
-	const char *name_pre = priv->cfg->fw_name_pre;
-	const unsigned int api_max = priv->cfg->ucode_api_max;
-	const unsigned int api_min = priv->cfg->ucode_api_min;
-	char buf[25];
-	u8 *src;
-	size_t len;
-	u32 api_ver, inst_size, data_size, init_size, init_data_size, boot_size;
-
-	/* Ask kernel firmware_class module to get the boot firmware off disk.
-	 * reject_firmware() is synchronous, file is in memory on return. */
-	for (index = api_max; index >= api_min; index--) {
-		sprintf(buf, "/*(DEBLOBBED)*/");
-		ret = reject_firmware(&ucode_raw, buf, &priv->pci_dev->dev);
-		if (ret < 0) {
-			IWL_ERR(priv, "%s firmware file req failed: %d\n",
-				  buf, ret);
-			if (ret == -ENOENT)
-				continue;
-			else
-				goto error;
-		} else {
-			if (index < api_max)
-				IWL_ERR(priv, "Loaded firmware %s, "
-					"which is deprecated. "
-					" Please use API v%u instead.\n",
-					  buf, api_max);
-			IWL_DEBUG_INFO(priv, "Got firmware '%s' file "
-				       "(%zd bytes) from disk\n",
-				       buf, ucode_raw->size);
-			break;
-		}
-	}
-
-	if (ret < 0)
-		goto error;
-
-	/* Make sure that we got at least our header! */
-	if (ucode_raw->size <  iwl3945_ucode_get_header_size(1)) {
-		IWL_ERR(priv, "File size way too small!\n");
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	/* Data from ucode file:  header followed by uCode images */
-	ucode = (struct iwl_ucode_header *)ucode_raw->data;
-
-	priv->ucode_ver = le32_to_cpu(ucode->ver);
-	api_ver = IWL_UCODE_API(priv->ucode_ver);
-	inst_size = iwl3945_ucode_get_inst_size(ucode);
-	data_size = iwl3945_ucode_get_data_size(ucode);
-	init_size = iwl3945_ucode_get_init_size(ucode);
-	init_data_size = iwl3945_ucode_get_init_data_size(ucode);
-	boot_size = iwl3945_ucode_get_boot_size(ucode);
-	src = iwl3945_ucode_get_data(ucode);
-
-	/* api_ver should match the api version forming part of the
-	 * firmware filename ... but we don't check for that and only rely
-	 * on the API version read from firmware header from here on forward */
-
-	if (api_ver < api_min || api_ver > api_max) {
-		IWL_ERR(priv, "Driver unable to support your firmware API. "
-			  "Driver supports v%u, firmware is v%u.\n",
-			  api_max, api_ver);
-		priv->ucode_ver = 0;
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (api_ver != api_max)
-		IWL_ERR(priv, "Firmware has old API version. Expected %u, "
-			  "got %u. New firmware can be obtained "
-			  "from http://www.intellinuxwireless.org.\n",
-			  api_max, api_ver);
-
-	IWL_INFO(priv, "loaded firmware version %u.%u.%u.%u\n",
-		IWL_UCODE_MAJOR(priv->ucode_ver),
-		IWL_UCODE_MINOR(priv->ucode_ver),
-		IWL_UCODE_API(priv->ucode_ver),
-		IWL_UCODE_SERIAL(priv->ucode_ver));
-
-	snprintf(priv->hw->wiphy->fw_version,
-		 sizeof(priv->hw->wiphy->fw_version),
-		 "%u.%u.%u.%u",
-		 IWL_UCODE_MAJOR(priv->ucode_ver),
-		 IWL_UCODE_MINOR(priv->ucode_ver),
-		 IWL_UCODE_API(priv->ucode_ver),
-		 IWL_UCODE_SERIAL(priv->ucode_ver));
-
-	IWL_DEBUG_INFO(priv, "f/w package hdr ucode version raw = 0x%x\n",
-		       priv->ucode_ver);
-	IWL_DEBUG_INFO(priv, "f/w package hdr runtime inst size = %u\n",
-		       inst_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr runtime data size = %u\n",
-		       data_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr init inst size = %u\n",
-		       init_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr init data size = %u\n",
-		       init_data_size);
-	IWL_DEBUG_INFO(priv, "f/w package hdr boot inst size = %u\n",
-		       boot_size);
-
-
-	/* Verify size of file vs. image size info in file's header */
-	if (ucode_raw->size != iwl3945_ucode_get_header_size(api_ver) +
-		inst_size + data_size + init_size +
-		init_data_size + boot_size) {
-
-		IWL_DEBUG_INFO(priv,
-			"uCode file size %zd does not match expected size\n",
-			ucode_raw->size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	/* Verify that uCode images will fit in card's SRAM */
-	if (inst_size > IWL39_MAX_INST_SIZE) {
-		IWL_DEBUG_INFO(priv, "uCode instr len %d too large to fit in\n",
-			       inst_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	if (data_size > IWL39_MAX_DATA_SIZE) {
-		IWL_DEBUG_INFO(priv, "uCode data len %d too large to fit in\n",
-			       data_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (init_size > IWL39_MAX_INST_SIZE) {
-		IWL_DEBUG_INFO(priv,
-				"uCode init instr len %d too large to fit in\n",
-				init_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (init_data_size > IWL39_MAX_DATA_SIZE) {
-		IWL_DEBUG_INFO(priv,
-				"uCode init data len %d too large to fit in\n",
-				init_data_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-	if (boot_size > IWL39_MAX_BSM_SIZE) {
-		IWL_DEBUG_INFO(priv,
-				"uCode boot instr len %d too large to fit in\n",
-				boot_size);
-		ret = -EINVAL;
-		goto err_release;
-	}
-
-	/* Allocate ucode buffers for card's bus-master loading ... */
-
-	/* Runtime instructions and 2 copies of data:
-	 * 1) unmodified from disk
-	 * 2) backup cache for save/restore during power-downs */
-	priv->ucode_code.len = inst_size;
-	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_code);
-
-	priv->ucode_data.len = data_size;
-	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data);
-
-	priv->ucode_data_backup.len = data_size;
-	iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_data_backup);
-
-	if (!priv->ucode_code.v_addr || !priv->ucode_data.v_addr ||
-	    !priv->ucode_data_backup.v_addr)
-		goto err_pci_alloc;
-
-	/* Initialization instructions and data */
-	if (init_size && init_data_size) {
-		priv->ucode_init.len = init_size;
-		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init);
-
-		priv->ucode_init_data.len = init_data_size;
-		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_init_data);
-
-		if (!priv->ucode_init.v_addr || !priv->ucode_init_data.v_addr)
-			goto err_pci_alloc;
-	}
-
-	/* Bootstrap (instructions only, no data) */
-	if (boot_size) {
-		priv->ucode_boot.len = boot_size;
-		iwl_alloc_fw_desc(priv->pci_dev, &priv->ucode_boot);
-
-		if (!priv->ucode_boot.v_addr)
-			goto err_pci_alloc;
-	}
-
-	/* Copy images into buffers for card's bus-master reads ... */
-
-	/* Runtime instructions (first block of data in file) */
-	len = inst_size;
-	IWL_DEBUG_INFO(priv,
-		"Copying (but not loading) uCode instr len %zd\n", len);
-	memcpy(priv->ucode_code.v_addr, src, len);
-	src += len;
-
-	IWL_DEBUG_INFO(priv, "uCode instr buf vaddr = 0x%p, paddr = 0x%08x\n",
-		priv->ucode_code.v_addr, (u32)priv->ucode_code.p_addr);
-
-	/* Runtime data (2nd block)
-	 * NOTE:  Copy into backup buffer will be done in iwl3945_up()  */
-	len = data_size;
-	IWL_DEBUG_INFO(priv,
-		"Copying (but not loading) uCode data len %zd\n", len);
-	memcpy(priv->ucode_data.v_addr, src, len);
-	memcpy(priv->ucode_data_backup.v_addr, src, len);
-	src += len;
-
-	/* Initialization instructions (3rd block) */
-	if (init_size) {
-		len = init_size;
-		IWL_DEBUG_INFO(priv,
-			"Copying (but not loading) init instr len %zd\n", len);
-		memcpy(priv->ucode_init.v_addr, src, len);
-		src += len;
-	}
-
-	/* Initialization data (4th block) */
-	if (init_data_size) {
-		len = init_data_size;
-		IWL_DEBUG_INFO(priv,
-			"Copying (but not loading) init data len %zd\n", len);
-		memcpy(priv->ucode_init_data.v_addr, src, len);
-		src += len;
-	}
-
-	/* Bootstrap instructions (5th block) */
-	len = boot_size;
-	IWL_DEBUG_INFO(priv,
-		"Copying (but not loading) boot instr len %zd\n", len);
-	memcpy(priv->ucode_boot.v_addr, src, len);
-
-	/* We have our copies now, allow OS release its copies */
-	release_firmware(ucode_raw);
-	return 0;
-
- err_pci_alloc:
-	IWL_ERR(priv, "failed to allocate pci memory\n");
-	ret = -ENOMEM;
-	iwl3945_dealloc_ucode_pci(priv);
-
- err_release:
-	release_firmware(ucode_raw);
-
- error:
-	return ret;
-}
-
-
-/**
- * iwl3945_set_ucode_ptrs - Set uCode address location
- *
- * Tell initialization uCode where to find runtime uCode.
- *
- * BSM registers initially contain pointers to initialization uCode.
- * We need to replace them to load runtime uCode inst and data,
- * and to save runtime data when powering down.
- */
-static int iwl3945_set_ucode_ptrs(struct iwl_priv *priv)
-{
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-
-	/* bits 31:0 for 3945 */
-	pinst = priv->ucode_code.p_addr;
-	pdata = priv->ucode_data_backup.p_addr;
-
-	/* 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);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-				 priv->ucode_data.len);
-
-	/* Inst byte count must be last to set up, bit 31 signals uCode
-	 *   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_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
-
-	return 0;
-}
-
-/**
- * iwl3945_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
- */
-static void iwl3945_init_alive_start(struct iwl_priv *priv)
-{
-	/* Check alive response for "valid" sign from uCode */
-	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
-		goto restart;
-	}
-
-	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
-	 * This is a paranoid check, because we would not have gotten the
-	 * "initialize" alive if code weren't properly loaded.  */
-	if (iwl3945_verify_ucode(priv)) {
-		/* Runtime instruction load was bad;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
-		goto restart;
-	}
-
-	/* Send pointers to protocol/runtime uCode image ... init code will
-	 * load and launch runtime uCode, which will send us another "Alive"
-	 * notification. */
-	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-	if (iwl3945_set_ucode_ptrs(priv)) {
-		/* Runtime instruction load won't happen;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
-		goto restart;
-	}
-	return;
-
- restart:
-	queue_work(priv->workqueue, &priv->restart);
-}
-
-/**
- * iwl3945_alive_start - called after REPLY_ALIVE notification received
- *                   from protocol/runtime uCode (initialization uCode's
- *                   Alive gets handled by iwl3945_init_alive_start()).
- */
-static void iwl3945_alive_start(struct iwl_priv *priv)
-{
-	int thermal_spin = 0;
-	u32 rfkill;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-
-	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Alive failed.\n");
-		goto restart;
-	}
-
-	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
-	 * This is a paranoid check, because we would not have gotten the
-	 * "runtime" alive if code weren't properly loaded.  */
-	if (iwl3945_verify_ucode(priv)) {
-		/* Runtime instruction load was bad;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Bad runtime uCode load.\n");
-		goto restart;
-	}
-
-	rfkill = iwl_read_prph(priv, APMG_RFKILL_REG);
-	IWL_DEBUG_INFO(priv, "RFKILL status: 0x%x\n", rfkill);
-
-	if (rfkill & 0x1) {
-		clear_bit(STATUS_RF_KILL_HW, &priv->status);
-		/* if RFKILL is not on, then wait for thermal
-		 * sensor in adapter to kick in */
-		while (iwl3945_hw_get_temperature(priv) == 0) {
-			thermal_spin++;
-			udelay(10);
-		}
-
-		if (thermal_spin)
-			IWL_DEBUG_INFO(priv, "Thermal calibration took %dus\n",
-				       thermal_spin * 10);
-	} else
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-
-	/* After the ALIVE response, we can send commands to 3945 uCode */
-	set_bit(STATUS_ALIVE, &priv->status);
-
-	/* Enable watchdog to monitor the driver tx queues */
-	iwl_setup_watchdog(priv);
-
-	if (iwl_is_rfkill(priv))
-		return;
-
-	ieee80211_wake_queues(priv->hw);
-
-	priv->active_rate = IWL_RATES_MASK;
-
-	iwl_power_update_mode(priv, true);
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-		struct iwl3945_rxon_cmd *active_rxon =
-				(struct iwl3945_rxon_cmd *)(&ctx->active);
-
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	} else {
-		/* Initialize our rx_config data */
-		iwl_connection_init_rx_config(priv, ctx);
-	}
-
-	/* Configure Bluetooth device coexistence support */
-	priv->cfg->ops->hcmd->send_bt_config(priv);
-
-	/* Configure the adapter for unassociated operation */
-	iwl3945_commit_rxon(priv, ctx);
-
-	iwl3945_reg_txpower_periodic(priv);
-
-	iwl_leds_init(priv);
-
-	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
-	set_bit(STATUS_READY, &priv->status);
-	wake_up_interruptible(&priv->wait_command_queue);
-
-	return;
-
- restart:
-	queue_work(priv->workqueue, &priv->restart);
-}
-
-static void iwl3945_cancel_deferred_work(struct iwl_priv *priv);
-
-static void __iwl3945_down(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	int exit_pending;
-
-	IWL_DEBUG_INFO(priv, DRV_NAME " is going down\n");
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	/* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
-	 * to prevent rearm timer */
-	del_timer_sync(&priv->watchdog);
-
-	/* Station information will now be cleared in device */
-	iwl_clear_ucode_stations(priv, NULL);
-	iwl_dealloc_bcast_stations(priv);
-	iwl_clear_driver_stations(priv);
-
-	/* Unblock any waiting calls */
-	wake_up_interruptible_all(&priv->wait_command_queue);
-
-	/* Wipe out the EXIT_PENDING status bit if we are not actually
-	 * exiting the module */
-	if (!exit_pending)
-		clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	/* stop and reset the on-board processor */
-	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-	/* tell the device to stop sending interrupts */
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	iwl_synchronize_irq(priv);
-
-	if (priv->mac80211_registered)
-		ieee80211_stop_queues(priv->hw);
-
-	/* If we have not previously called iwl3945_init() then
-	 * 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_GEO_CONFIGURED, &priv->status) <<
-					STATUS_GEO_CONFIGURED |
-				test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-					STATUS_EXIT_PENDING;
-		goto exit;
-	}
-
-	/* ...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_GEO_CONFIGURED, &priv->status) <<
-				STATUS_GEO_CONFIGURED |
-			test_bit(STATUS_FW_ERROR, &priv->status) <<
-				STATUS_FW_ERROR |
-			test_bit(STATUS_EXIT_PENDING, &priv->status) <<
-				STATUS_EXIT_PENDING;
-
-	iwl3945_hw_txq_ctx_stop(priv);
-	iwl3945_hw_rxq_stop(priv);
-
-	/* Power-down device's busmaster DMA clocks */
-	iwl_write_prph(priv, APMG_CLK_DIS_REG, APMG_CLK_VAL_DMA_CLK_RQT);
-	udelay(5);
-
-	/* Stop the device, and put it in low power state */
-	iwl_apm_stop(priv);
-
- exit:
-	memset(&priv->card_alive, 0, sizeof(struct iwl_alive_resp));
-
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-	priv->beacon_skb = NULL;
-
-	/* clear out any free frames */
-	iwl3945_clear_free_frames(priv);
-}
-
-static void iwl3945_down(struct iwl_priv *priv)
-{
-	mutex_lock(&priv->mutex);
-	__iwl3945_down(priv);
-	mutex_unlock(&priv->mutex);
-
-	iwl3945_cancel_deferred_work(priv);
-}
-
-#define MAX_HW_RESTARTS 5
-
-static int iwl3945_alloc_bcast_station(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	unsigned long flags;
-	u8 sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	sta_id = iwl_prep_station(priv, ctx, iwl_bcast_addr, false, NULL);
-	if (sta_id == IWL_INVALID_STATION) {
-		IWL_ERR(priv, "Unable to prepare broadcast station\n");
-		spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-		return -EINVAL;
-	}
-
-	priv->stations[sta_id].used |= IWL_STA_DRIVER_ACTIVE;
-	priv->stations[sta_id].used |= IWL_STA_BCAST;
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return 0;
-}
-
-static int __iwl3945_up(struct iwl_priv *priv)
-{
-	int rc, i;
-
-	rc = iwl3945_alloc_bcast_station(priv);
-	if (rc)
-		return rc;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		IWL_WARN(priv, "Exit pending; will not bring the NIC up\n");
-		return -EIO;
-	}
-
-	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;
-	}
-
-	/* 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);
-	else {
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-		IWL_WARN(priv, "Radio disabled by HW RF Kill switch\n");
-		return -ENODEV;
-	}
-
-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-
-	rc = iwl3945_hw_nic_init(priv);
-	if (rc) {
-		IWL_ERR(priv, "Unable to int nic\n");
-		return rc;
-	}
-
-	/* make sure rfkill handshake bits are cleared */
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR,
-		    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-	/* clear (again), then enable host interrupts */
-	iwl_write32(priv, CSR_INT, 0xFFFFFFFF);
-	iwl_enable_interrupts(priv);
-
-	/* really make sure rfkill handshake bits are cleared */
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-	iwl_write32(priv, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL);
-
-	/* Copy original ucode data image from disk into backup cache.
-	 * This will be used to initialize the on-board processor's
-	 * data SRAM for a clean start when the runtime program first loads. */
-	memcpy(priv->ucode_data_backup.v_addr, priv->ucode_data.v_addr,
-	       priv->ucode_data.len);
-
-	/* We return success when we resume from suspend and rf_kill is on. */
-	if (test_bit(STATUS_RF_KILL_HW, &priv->status))
-		return 0;
-
-	for (i = 0; i < MAX_HW_RESTARTS; i++) {
-
-		/* load bootstrap state machine,
-		 * load bootstrap program into processor's memory,
-		 * prepare to load the "initialize" uCode */
-		rc = priv->cfg->ops->lib->load_ucode(priv);
-
-		if (rc) {
-			IWL_ERR(priv,
-				"Unable to set up bootstrap uCode: %d\n", rc);
-			continue;
-		}
-
-		/* start card; "initialize" will load runtime ucode */
-		iwl3945_nic_start(priv);
-
-		IWL_DEBUG_INFO(priv, DRV_NAME " is coming up\n");
-
-		return 0;
-	}
-
-	set_bit(STATUS_EXIT_PENDING, &priv->status);
-	__iwl3945_down(priv);
-	clear_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	/* tried to restart and config the device for as long as our
-	 * patience could withstand */
-	IWL_ERR(priv, "Unable to initialize device after %d attempts.\n", i);
-	return -EIO;
-}
-
-
-/*****************************************************************************
- *
- * Workqueue callbacks
- *
- *****************************************************************************/
-
-static void iwl3945_bg_init_alive_start(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, init_alive_start.work);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_init_alive_start(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-static void iwl3945_bg_alive_start(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, alive_start.work);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_alive_start(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-/*
- * 3945 cannot interrupt driver when hardware rf kill switch toggles;
- * driver must poll CSR_GP_CNTRL_REG register for change.  This register
- * *is* readable even when device has been SW_RESET into low power mode
- * (e.g. during RF KILL).
- */
-static void iwl3945_rfkill_poll(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, _3945.rfkill_poll.work);
-	bool old_rfkill = test_bit(STATUS_RF_KILL_HW, &priv->status);
-	bool new_rfkill = !(iwl_read32(priv, CSR_GP_CNTRL)
-			& CSR_GP_CNTRL_REG_FLAG_HW_RF_KILL_SW);
-
-	if (new_rfkill != old_rfkill) {
-		if (new_rfkill)
-			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, new_rfkill);
-
-		IWL_DEBUG_RF_KILL(priv, "RF_KILL bit toggled to %s.\n",
-				new_rfkill ? "disable radio" : "enable radio");
-	}
-
-	/* Keep this running, even if radio now enabled.  This will be
-	 * cancelled in mac_start() if system decides to start again */
-	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-			   round_jiffies_relative(2 * HZ));
-
-}
-
-int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
-{
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_SCAN_CMD,
-		.len = sizeof(struct iwl3945_scan_cmd),
-		.flags = CMD_SIZE_HUGE,
-	};
-	struct iwl3945_scan_cmd *scan;
-	u8 n_probes = 0;
-	enum ieee80211_band band;
-	bool is_active = false;
-	int ret;
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (!priv->scan_cmd) {
-		priv->scan_cmd = kmalloc(sizeof(struct iwl3945_scan_cmd) +
-					 IWL_MAX_SCAN_SIZE, GFP_KERNEL);
-		if (!priv->scan_cmd) {
-			IWL_DEBUG_SCAN(priv, "Fail to allocate scan memory\n");
-			return -ENOMEM;
-		}
-	}
-	scan = priv->scan_cmd;
-	memset(scan, 0, sizeof(struct iwl3945_scan_cmd) + IWL_MAX_SCAN_SIZE);
-
-	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
-	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
-
-	if (iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-		u16 interval = 0;
-		u32 extra;
-		u32 suspend_time = 100;
-		u32 scan_suspend_time = 100;
-		unsigned long flags;
-
-		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-
-		spin_lock_irqsave(&priv->lock, flags);
-		if (priv->is_internal_short_scan)
-			interval = 0;
-		else
-			interval = vif->bss_conf.beacon_int;
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		scan->suspend_time = 0;
-		scan->max_out_time = cpu_to_le32(200 * 1024);
-		if (!interval)
-			interval = suspend_time;
-		/*
-		 * suspend time format:
-		 *  0-19: beacon interval in usec (time before exec.)
-		 * 20-23: 0
-		 * 24-31: number of beacons (suspend between channels)
-		 */
-
-		extra = (suspend_time / interval) << 24;
-		scan_suspend_time = 0xFF0FFFFF &
-		    (extra | ((suspend_time % interval) * 1024));
-
-		scan->suspend_time = cpu_to_le32(scan_suspend_time);
-		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
-			       scan_suspend_time, interval);
-	}
-
-	if (priv->is_internal_short_scan) {
-		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else 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 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 */
-	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
-	scan->tx_cmd.sta_id = priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-	scan->tx_cmd.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-	/* flags + rate selection */
-
-	switch (priv->scan_band) {
-	case IEEE80211_BAND_2GHZ:
-		scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
-		scan->tx_cmd.rate = IWL_RATE_1M_PLCP;
-		band = IEEE80211_BAND_2GHZ;
-		break;
-	case IEEE80211_BAND_5GHZ:
-		scan->tx_cmd.rate = IWL_RATE_6M_PLCP;
-		band = IEEE80211_BAND_5GHZ;
-		break;
-	default:
-		IWL_WARN(priv, "Invalid scan band\n");
-		return -EIO;
-	}
-
-	/*
-	 * 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_DEFAULT :
-					IWL_GOOD_CRC_TH_DISABLED;
-
-	if (!priv->is_internal_short_scan) {
-		scan->tx_cmd.len = cpu_to_le16(
-			iwl_fill_probe_req(priv,
-				(struct ieee80211_mgmt *)scan->data,
-				vif->addr,
-				priv->scan_request->ie,
-				priv->scan_request->ie_len,
-				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-	} else {
-		/* use bcast addr, will not be transmitted but must be valid */
-		scan->tx_cmd.len = cpu_to_le16(
-			iwl_fill_probe_req(priv,
-				(struct ieee80211_mgmt *)scan->data,
-				iwl_bcast_addr, NULL, 0,
-				IWL_MAX_SCAN_SIZE - sizeof(*scan)));
-	}
-	/* select Rx antennas */
-	scan->flags |= iwl3945_get_antenna_flags(priv);
-
-	if (priv->is_internal_short_scan) {
-		scan->channel_count =
-			iwl3945_get_single_channel_for_scan(priv, vif, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
-		scan->channel_count =
-			iwl3945_get_channels_for_scan(priv, band, is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)], vif);
-	}
-
-	if (scan->channel_count == 0) {
-		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
-		return -EIO;
-	}
-
-	cmd.len += le16_to_cpu(scan->tx_cmd.len) +
-	    scan->channel_count * sizeof(struct iwl3945_scan_channel);
-	cmd.data = scan;
-	scan->len = cpu_to_le16(cmd.len);
-
-	set_bit(STATUS_SCAN_HW, &priv->status);
-	ret = iwl_send_cmd_sync(priv, &cmd);
-	if (ret)
-		clear_bit(STATUS_SCAN_HW, &priv->status);
-	return ret;
-}
-
-void iwl3945_post_scan(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-		iwl3945_commit_rxon(priv, ctx);
-}
-
-static void iwl3945_bg_restart(struct work_struct *data)
-{
-	struct iwl_priv *priv = container_of(data, struct iwl_priv, restart);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
-		struct iwl_rxon_context *ctx;
-		mutex_lock(&priv->mutex);
-		for_each_context(priv, ctx)
-			ctx->vif = NULL;
-		priv->is_open = 0;
-		mutex_unlock(&priv->mutex);
-		iwl3945_down(priv);
-		ieee80211_restart_hw(priv->hw);
-	} else {
-		iwl3945_down(priv);
-
-		if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-			return;
-
-		mutex_lock(&priv->mutex);
-		__iwl3945_up(priv);
-		mutex_unlock(&priv->mutex);
-	}
-}
-
-static void iwl3945_bg_rx_replenish(struct work_struct *data)
-{
-	struct iwl_priv *priv =
-	    container_of(data, struct iwl_priv, rx_replenish);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_rx_replenish(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-void iwl3945_post_associate(struct iwl_priv *priv)
-{
-	int rc = 0;
-	struct ieee80211_conf *conf = NULL;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (!ctx->vif || !priv->is_open)
-		return;
-
-	if (ctx->vif->type == NL80211_IFTYPE_AP) {
-		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
-		return;
-	}
-
-	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			ctx->vif->bss_conf.aid, ctx->active.bssid_addr);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwl3945_commit_rxon(priv, ctx);
-
-	rc = iwl_send_rxon_timing(priv, ctx);
-	if (rc)
-		IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
-			    "Attempting to continue.\n");
-
-	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-	ctx->staging.assoc_id = cpu_to_le16(ctx->vif->bss_conf.aid);
-
-	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			ctx->vif->bss_conf.aid, ctx->vif->bss_conf.beacon_int);
-
-	if (ctx->vif->bss_conf.use_short_preamble)
-		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-	else
-		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (ctx->vif->bss_conf.use_short_slot)
-			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-	}
-
-	iwl3945_commit_rxon(priv, ctx);
-
-	switch (ctx->vif->type) {
-	case NL80211_IFTYPE_STATION:
-		iwl3945_rate_scale_init(priv->hw, IWL_AP_ID);
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		iwl3945_send_beacon_cmd(priv);
-		break;
-	default:
-		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			__func__, ctx->vif->type);
-		break;
-	}
-}
-
-/*****************************************************************************
- *
- * mac80211 entry point functions
- *
- *****************************************************************************/
-
-#define UCODE_READY_TIMEOUT	(2 * HZ)
-
-static int iwl3945_mac_start(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-	int ret;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	/* we should be verifying the device is ready to be opened */
-	mutex_lock(&priv->mutex);
-
-	/* fetch ucode file from disk, alloc and copy to bus-master buffers ...
-	 * ucode filename and max sizes are card-specific. */
-
-	if (!priv->ucode_code.len) {
-		ret = iwl3945_read_ucode(priv);
-		if (ret) {
-			IWL_ERR(priv, "Could not read microcode: %d\n", ret);
-			mutex_unlock(&priv->mutex);
-			goto out_release_irq;
-		}
-	}
-
-	ret = __iwl3945_up(priv);
-
-	mutex_unlock(&priv->mutex);
-
-	if (ret)
-		goto out_release_irq;
-
-	IWL_DEBUG_INFO(priv, "Start UP work.\n");
-
-	/* Wait for START_ALIVE from ucode. Otherwise callbacks from
-	 * mac80211 will not be run successfully. */
-	ret = wait_event_interruptible_timeout(priv->wait_command_queue,
-			test_bit(STATUS_READY, &priv->status),
-			UCODE_READY_TIMEOUT);
-	if (!ret) {
-		if (!test_bit(STATUS_READY, &priv->status)) {
-			IWL_ERR(priv,
-				"Wait for START_ALIVE timeout after %dms.\n",
-				jiffies_to_msecs(UCODE_READY_TIMEOUT));
-			ret = -ETIMEDOUT;
-			goto out_release_irq;
-		}
-	}
-
-	/* ucode is running and will send rfkill notifications,
-	 * no need to poll the killswitch state anymore */
-	cancel_delayed_work(&priv->_3945.rfkill_poll);
-
-	iwl_led_start(priv);
-
-	priv->is_open = 1;
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return 0;
-
-out_release_irq:
-	priv->is_open = 0;
-	IWL_DEBUG_MAC80211(priv, "leave - failed\n");
-	return ret;
-}
-
-static void iwl3945_mac_stop(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (!priv->is_open) {
-		IWL_DEBUG_MAC80211(priv, "leave - skip\n");
-		return;
-	}
-
-	priv->is_open = 0;
-
-	iwl3945_down(priv);
-
-	flush_workqueue(priv->workqueue);
-
-	/* start polling the killswitch state again */
-	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-			   round_jiffies_relative(2 * HZ));
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-
-static int iwl3945_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
-{
-	struct iwl_priv *priv = hw->priv;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	IWL_DEBUG_TX(priv, "dev->xmit(%d bytes) at rate 0x%02x\n", skb->len,
-		     ieee80211_get_tx_rate(hw, IEEE80211_SKB_CB(skb))->bitrate);
-
-	if (iwl3945_tx_skb(priv, skb))
-		dev_kfree_skb_any(skb);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	return NETDEV_TX_OK;
-}
-
-void iwl3945_config_ap(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_vif *vif = ctx->vif;
-	int rc = 0;
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* The following should be done only at AP bring up */
-	if (!(iwl_is_associated(priv, IWL_RXON_CTX_BSS))) {
-
-		/* RXON - unassoc (to set timing command) */
-		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv, ctx);
-
-		/* RXON Timing */
-		rc = iwl_send_rxon_timing(priv, ctx);
-		if (rc)
-			IWL_WARN(priv, "REPLY_RXON_TIMING failed - "
-					"Attempting to continue.\n");
-
-		ctx->staging.assoc_id = 0;
-
-		if (vif->bss_conf.use_short_preamble)
-			ctx->staging.flags |=
-				RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-			if (vif->bss_conf.use_short_slot)
-				ctx->staging.flags |=
-					RXON_FLG_SHORT_SLOT_MSK;
-			else
-				ctx->staging.flags &=
-					~RXON_FLG_SHORT_SLOT_MSK;
-		}
-		/* restore RXON assoc */
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwl3945_commit_rxon(priv, ctx);
-	}
-	iwl3945_send_beacon_cmd(priv);
-
-	/* FIXME - we need to add code here to detect a totally new
-	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-	 * clear sta table, add BCAST sta... */
-}
-
-static int iwl3945_mac_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 iwl_priv *priv = hw->priv;
-	int ret = 0;
-	u8 sta_id = IWL_INVALID_STATION;
-	u8 static_key;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	if (iwl3945_mod_params.sw_crypto) {
-		IWL_DEBUG_MAC80211(priv, "leave - hwcrypto disabled\n");
-		return -EOPNOTSUPP;
-	}
-
-	static_key = !iwl_is_associated(priv, IWL_RXON_CTX_BSS);
-
-	if (!static_key) {
-		sta_id = iwl_sta_id_or_broadcast(
-				priv, &priv->contexts[IWL_RXON_CTX_BSS], sta);
-		if (sta_id == IWL_INVALID_STATION)
-			return -EINVAL;
-	}
-
-	mutex_lock(&priv->mutex);
-	iwl_scan_cancel_timeout(priv, 100);
-
-	switch (cmd) {
-	case SET_KEY:
-		if (static_key)
-			ret = iwl3945_set_static_key(priv, key);
-		else
-			ret = iwl3945_set_dynamic_key(priv, key, sta_id);
-		IWL_DEBUG_MAC80211(priv, "enable hwcrypto key\n");
-		break;
-	case DISABLE_KEY:
-		if (static_key)
-			ret = iwl3945_remove_static_key(priv);
-		else
-			ret = iwl3945_clear_sta_key_info(priv, sta_id);
-		IWL_DEBUG_MAC80211(priv, "disable hwcrypto key\n");
-		break;
-	default:
-		ret = -EINVAL;
-	}
-
-	mutex_unlock(&priv->mutex);
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-
-	return ret;
-}
-
-static int iwl3945_mac_sta_add(struct ieee80211_hw *hw,
-			       struct ieee80211_vif *vif,
-			       struct ieee80211_sta *sta)
-{
-	struct iwl_priv *priv = hw->priv;
-	struct iwl3945_sta_priv *sta_priv = (void *)sta->drv_priv;
-	int ret;
-	bool is_ap = vif->type == NL80211_IFTYPE_STATION;
-	u8 sta_id;
-
-	IWL_DEBUG_INFO(priv, "received request to add station %pM\n",
-			sta->addr);
-	mutex_lock(&priv->mutex);
-	IWL_DEBUG_INFO(priv, "proceeding to add station %pM\n",
-			sta->addr);
-	sta_priv->common.sta_id = IWL_INVALID_STATION;
-
-
-	ret = iwl_add_station_common(priv, &priv->contexts[IWL_RXON_CTX_BSS],
-				     sta->addr, is_ap, sta, &sta_id);
-	if (ret) {
-		IWL_ERR(priv, "Unable to add station %pM (%d)\n",
-			sta->addr, ret);
-		/* Should we return success if return code is EEXIST ? */
-		mutex_unlock(&priv->mutex);
-		return ret;
-	}
-
-	sta_priv->common.sta_id = sta_id;
-
-	/* Initialize rate scaling */
-	IWL_DEBUG_INFO(priv, "Initializing rate scaling for station %pM\n",
-		       sta->addr);
-	iwl3945_rs_rate_init(priv, sta, sta_id);
-	mutex_unlock(&priv->mutex);
-
-	return 0;
-}
-
-static void iwl3945_configure_filter(struct ieee80211_hw *hw,
-				     unsigned int changed_flags,
-				     unsigned int *total_flags,
-				     u64 multicast)
-{
-	struct iwl_priv *priv = hw->priv;
-	__le32 filter_or = 0, filter_nand = 0;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-#define CHK(test, flag)	do { \
-	if (*total_flags & (test))		\
-		filter_or |= (flag);		\
-	else					\
-		filter_nand |= (flag);		\
-	} while (0)
-
-	IWL_DEBUG_MAC80211(priv, "Enter: changed: 0x%x, total: 0x%x\n",
-			changed_flags, *total_flags);
-
-	CHK(FIF_OTHER_BSS | FIF_PROMISC_IN_BSS, RXON_FILTER_PROMISC_MSK);
-	CHK(FIF_CONTROL, RXON_FILTER_CTL2HOST_MSK);
-	CHK(FIF_BCN_PRBRESP_PROMISC, RXON_FILTER_BCON_AWARE_MSK);
-
-#undef CHK
-
-	mutex_lock(&priv->mutex);
-
-	ctx->staging.filter_flags &= ~filter_nand;
-	ctx->staging.filter_flags |= filter_or;
-
-	/*
-	 * Not committing directly because hardware can perform a scan,
-	 * but even if hw is ready, committing here breaks for some reason,
-	 * we'll eventually commit the filter flags change anyway.
-	 */
-
-	mutex_unlock(&priv->mutex);
-
-	/*
-	 * Receiving all multicast frames is always enabled by the
-	 * default flags setup in iwl_connection_init_rx_config()
-	 * since we currently do not support programming multicast
-	 * filters into the device.
-	 */
-	*total_flags &= FIF_OTHER_BSS | FIF_ALLMULTI | FIF_PROMISC_IN_BSS |
-			FIF_BCN_PRBRESP_PROMISC | FIF_CONTROL;
-}
-
-
-/*****************************************************************************
- *
- * sysfs attributes
- *
- *****************************************************************************/
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-
-/*
- * The following adds a new attribute to the sysfs representation
- * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/)
- * used for controlling the debug level.
- *
- * See the level definitions in iwl for details.
- *
- * The debug_level being managed using sysfs below is a per device debug
- * level that is used instead of the global debug level if it (the per
- * device debug level) is set.
- */
-static ssize_t show_debug_level(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "0x%08X\n", iwl_get_debug_level(priv));
-}
-static ssize_t store_debug_level(struct device *d,
-				struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	unsigned long val;
-	int ret;
-
-	ret = strict_strtoul(buf, 0, &val);
-	if (ret)
-		IWL_INFO(priv, "%s is not in hex or decimal form.\n", buf);
-	else {
-		priv->debug_level = val;
-		if (iwl_alloc_traffic_mem(priv))
-			IWL_ERR(priv,
-				"Not enough memory to generate traffic log\n");
-	}
-	return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(debug_level, S_IWUSR | S_IRUGO,
-			show_debug_level, store_debug_level);
-
-#endif /* CONFIG_IWLWIFI_DEBUG */
-
-static ssize_t show_temperature(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	return sprintf(buf, "%d\n", iwl3945_hw_get_temperature(priv));
-}
-
-static DEVICE_ATTR(temperature, S_IRUGO, show_temperature, NULL);
-
-static ssize_t show_tx_power(struct device *d,
-			     struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "%d\n", priv->tx_power_user_lmt);
-}
-
-static ssize_t store_tx_power(struct device *d,
-			      struct device_attribute *attr,
-			      const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	char *p = (char *)buf;
-	u32 val;
-
-	val = simple_strtoul(p, &p, 10);
-	if (p == buf)
-		IWL_INFO(priv, ": %s is not in decimal form.\n", buf);
-	else
-		iwl3945_hw_reg_set_txpower(priv, val);
-
-	return count;
-}
-
-static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
-
-static ssize_t show_flags(struct device *d,
-			  struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	return sprintf(buf, "0x%04X\n", ctx->active.flags);
-}
-
-static ssize_t store_flags(struct device *d,
-			   struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	u32 flags = simple_strtoul(buf, NULL, 0);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	mutex_lock(&priv->mutex);
-	if (le32_to_cpu(ctx->staging.flags) != flags) {
-		/* Cancel any currently running scans... */
-		if (iwl_scan_cancel_timeout(priv, 100))
-			IWL_WARN(priv, "Could not cancel scan.\n");
-		else {
-			IWL_DEBUG_INFO(priv, "Committing rxon.flags = 0x%04X\n",
-				       flags);
-			ctx->staging.flags = cpu_to_le32(flags);
-			iwl3945_commit_rxon(priv, ctx);
-		}
-	}
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(flags, S_IWUSR | S_IRUGO, show_flags, store_flags);
-
-static ssize_t show_filter_flags(struct device *d,
-				 struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	return sprintf(buf, "0x%04X\n",
-		le32_to_cpu(ctx->active.filter_flags));
-}
-
-static ssize_t store_filter_flags(struct device *d,
-				  struct device_attribute *attr,
-				  const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	u32 filter_flags = simple_strtoul(buf, NULL, 0);
-
-	mutex_lock(&priv->mutex);
-	if (le32_to_cpu(ctx->staging.filter_flags) != filter_flags) {
-		/* Cancel any currently running scans... */
-		if (iwl_scan_cancel_timeout(priv, 100))
-			IWL_WARN(priv, "Could not cancel scan.\n");
-		else {
-			IWL_DEBUG_INFO(priv, "Committing rxon.filter_flags = "
-				       "0x%04X\n", filter_flags);
-			ctx->staging.filter_flags =
-				cpu_to_le32(filter_flags);
-			iwl3945_commit_rxon(priv, ctx);
-		}
-	}
-	mutex_unlock(&priv->mutex);
-
-	return count;
-}
-
-static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
-		   store_filter_flags);
-
-static ssize_t show_measurement(struct device *d,
-				struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_spectrum_notification measure_report;
-	u32 size = sizeof(measure_report), len = 0, ofs = 0;
-	u8 *data = (u8 *)&measure_report;
-	unsigned long flags;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	if (!(priv->measurement_status & MEASUREMENT_READY)) {
-		spin_unlock_irqrestore(&priv->lock, flags);
-		return 0;
-	}
-	memcpy(&measure_report, &priv->measure_report, size);
-	priv->measurement_status = 0;
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	while (size && (PAGE_SIZE - len)) {
-		hex_dump_to_buffer(data + ofs, size, 16, 1, buf + len,
-				   PAGE_SIZE - len, 1);
-		len = strlen(buf);
-		if (PAGE_SIZE - len)
-			buf[len++] = '\n';
-
-		ofs += 16;
-		size -= min(size, 16U);
-	}
-
-	return len;
-}
-
-static ssize_t store_measurement(struct device *d,
-				 struct device_attribute *attr,
-				 const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_measurement_params params = {
-		.channel = le16_to_cpu(ctx->active.channel),
-		.start_time = cpu_to_le64(priv->_3945.last_tsf),
-		.duration = cpu_to_le16(1),
-	};
-	u8 type = IWL_MEASURE_BASIC;
-	u8 buffer[32];
-	u8 channel;
-
-	if (count) {
-		char *p = buffer;
-		strncpy(buffer, buf, min(sizeof(buffer), count));
-		channel = simple_strtoul(p, NULL, 0);
-		if (channel)
-			params.channel = channel;
-
-		p = buffer;
-		while (*p && *p != ' ')
-			p++;
-		if (*p)
-			type = simple_strtoul(p + 1, NULL, 0);
-	}
-
-	IWL_DEBUG_INFO(priv, "Invoking measurement of type %d on "
-		       "channel %d (for '%s')\n", type, params.channel, buf);
-	iwl3945_get_measurement(priv, &params, type);
-
-	return count;
-}
-
-static DEVICE_ATTR(measurement, S_IRUSR | S_IWUSR,
-		   show_measurement, store_measurement);
-
-static ssize_t store_retry_rate(struct device *d,
-				struct device_attribute *attr,
-				const char *buf, size_t count)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-
-	priv->retry_rate = simple_strtoul(buf, NULL, 0);
-	if (priv->retry_rate <= 0)
-		priv->retry_rate = 1;
-
-	return count;
-}
-
-static ssize_t show_retry_rate(struct device *d,
-			       struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	return sprintf(buf, "%d", priv->retry_rate);
-}
-
-static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
-		   store_retry_rate);
-
-
-static ssize_t show_channels(struct device *d,
-			     struct device_attribute *attr, char *buf)
-{
-	/* all this shit doesn't belong into sysfs anyway */
-	return 0;
-}
-
-static DEVICE_ATTR(channels, S_IRUSR, show_channels, NULL);
-
-static ssize_t show_antenna(struct device *d,
-			    struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	return sprintf(buf, "%d\n", iwl3945_mod_params.antenna);
-}
-
-static ssize_t store_antenna(struct device *d,
-			     struct device_attribute *attr,
-			     const char *buf, size_t count)
-{
-	struct iwl_priv *priv __maybe_unused = dev_get_drvdata(d);
-	int ant;
-
-	if (count == 0)
-		return 0;
-
-	if (sscanf(buf, "%1i", &ant) != 1) {
-		IWL_DEBUG_INFO(priv, "not in hex or decimal form.\n");
-		return count;
-	}
-
-	if ((ant >= 0) && (ant <= 2)) {
-		IWL_DEBUG_INFO(priv, "Setting antenna select to %d.\n", ant);
-		iwl3945_mod_params.antenna = (enum iwl3945_antenna)ant;
-	} else
-		IWL_DEBUG_INFO(priv, "Bad antenna select value %d.\n", ant);
-
-
-	return count;
-}
-
-static DEVICE_ATTR(antenna, S_IWUSR | S_IRUGO, show_antenna, store_antenna);
-
-static ssize_t show_status(struct device *d,
-			   struct device_attribute *attr, char *buf)
-{
-	struct iwl_priv *priv = dev_get_drvdata(d);
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-	return sprintf(buf, "0x%08x\n", (int)priv->status);
-}
-
-static DEVICE_ATTR(status, S_IRUGO, show_status, NULL);
-
-static ssize_t dump_error_log(struct device *d,
-			      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(priv);
-
-	return strnlen(buf, count);
-}
-
-static DEVICE_ATTR(dump_errors, S_IWUSR, NULL, dump_error_log);
-
-/*****************************************************************************
- *
- * driver setup and tear down
- *
- *****************************************************************************/
-
-static void iwl3945_setup_deferred_work(struct iwl_priv *priv)
-{
-	priv->workqueue = create_singlethread_workqueue(DRV_NAME);
-
-	init_waitqueue_head(&priv->wait_command_queue);
-
-	INIT_WORK(&priv->restart, iwl3945_bg_restart);
-	INIT_WORK(&priv->rx_replenish, iwl3945_bg_rx_replenish);
-	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);
-	INIT_DELAYED_WORK(&priv->_3945.rfkill_poll, iwl3945_rfkill_poll);
-
-	iwl_setup_scan_deferred_work(priv);
-
-	iwl3945_hw_setup_deferred_work(priv);
-
-	init_timer(&priv->watchdog);
-	priv->watchdog.data = (unsigned long)priv;
-	priv->watchdog.function = iwl_bg_watchdog;
-
-	tasklet_init(&priv->irq_tasklet, (void (*)(unsigned long))
-		     iwl3945_irq_tasklet, (unsigned long)priv);
-}
-
-static void iwl3945_cancel_deferred_work(struct iwl_priv *priv)
-{
-	iwl3945_hw_cancel_deferred_work(priv);
-
-	cancel_delayed_work_sync(&priv->init_alive_start);
-	cancel_delayed_work(&priv->alive_start);
-	cancel_work_sync(&priv->beacon_update);
-
-	iwl_cancel_scan_deferred_work(priv);
-}
-
-static struct attribute *iwl3945_sysfs_entries[] = {
-	&dev_attr_antenna.attr,
-	&dev_attr_channels.attr,
-	&dev_attr_dump_errors.attr,
-	&dev_attr_flags.attr,
-	&dev_attr_filter_flags.attr,
-	&dev_attr_measurement.attr,
-	&dev_attr_retry_rate.attr,
-	&dev_attr_status.attr,
-	&dev_attr_temperature.attr,
-	&dev_attr_tx_power.attr,
-#ifdef CONFIG_IWLWIFI_DEBUG
-	&dev_attr_debug_level.attr,
-#endif
-	NULL
-};
-
-static struct attribute_group iwl3945_attribute_group = {
-	.name = NULL,		/* put in device directory */
-	.attrs = iwl3945_sysfs_entries,
-};
-
-struct ieee80211_ops iwl3945_hw_ops = {
-	.tx = iwl3945_mac_tx,
-	.start = iwl3945_mac_start,
-	.stop = iwl3945_mac_stop,
-	.add_interface = iwl_mac_add_interface,
-	.remove_interface = iwl_mac_remove_interface,
-	.change_interface = iwl_mac_change_interface,
-	.config = iwl_legacy_mac_config,
-	.configure_filter = iwl3945_configure_filter,
-	.set_key = iwl3945_mac_set_key,
-	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_legacy_mac_reset_tsf,
-	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
-	.hw_scan = iwl_mac_hw_scan,
-	.sta_add = iwl3945_mac_sta_add,
-	.sta_remove = iwl_mac_sta_remove,
-	.tx_last_beacon = iwl_mac_tx_last_beacon,
-};
-
-static int iwl3945_init_drv(struct iwl_priv *priv)
-{
-	int ret;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-
-	priv->retry_rate = 1;
-	priv->beacon_skb = NULL;
-
-	spin_lock_init(&priv->sta_lock);
-	spin_lock_init(&priv->hcmd_lock);
-
-	INIT_LIST_HEAD(&priv->free_frames);
-
-	mutex_init(&priv->mutex);
-	mutex_init(&priv->sync_cmd_mutex);
-
-	priv->ieee_channels = NULL;
-	priv->ieee_rates = NULL;
-	priv->band = IEEE80211_BAND_2GHZ;
-
-	priv->iw_mode = NL80211_IFTYPE_STATION;
-	priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
-
-	/* initialize force reset */
-	priv->force_reset[IWL_RF_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_RF_RESET;
-	priv->force_reset[IWL_FW_RESET].reset_duration =
-		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
-
-
-	priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
-	priv->tx_power_next = IWL_DEFAULT_TX_POWER;
-
-	if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
-		IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",
-			 eeprom->version);
-		ret = -EINVAL;
-		goto err;
-	}
-	ret = iwl_init_channel_map(priv);
-	if (ret) {
-		IWL_ERR(priv, "initializing regulatory failed: %d\n", ret);
-		goto err;
-	}
-
-	/* Set up txpower settings in driver for all channels */
-	if (iwl3945_txpower_set_from_eeprom(priv)) {
-		ret = -EIO;
-		goto err_free_channel_map;
-	}
-
-	ret = iwlcore_init_geos(priv);
-	if (ret) {
-		IWL_ERR(priv, "initializing geos failed: %d\n", ret);
-		goto err_free_channel_map;
-	}
-	iwl3945_init_hw_rates(priv, priv->ieee_rates);
-
-	return 0;
-
-err_free_channel_map:
-	iwl_free_channel_map(priv);
-err:
-	return ret;
-}
-
-#define IWL3945_MAX_PROBE_REQUEST	200
-
-static int iwl3945_setup_mac(struct iwl_priv *priv)
-{
-	int ret;
-	struct ieee80211_hw *hw = priv->hw;
-
-	hw->rate_control_algorithm = "iwl-3945-rs";
-	hw->sta_data_size = sizeof(struct iwl3945_sta_priv);
-	hw->vif_data_size = sizeof(struct iwl_vif_priv);
-
-	/* Tell mac80211 our characteristics */
-	hw->flags = IEEE80211_HW_SIGNAL_DBM |
-		    IEEE80211_HW_SPECTRUM_MGMT;
-
-	if (!priv->cfg->base_params->broken_powersave)
-		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
-			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
-
-	hw->wiphy->interface_modes =
-		priv->contexts[IWL_RXON_CTX_BSS].interface_modes;
-
-	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
-
-	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 = IWL3945_MAX_PROBE_REQUEST - 24 - 2;
-
-	/* Default value; 4 EDCA QOS priorities */
-	hw->queues = 4;
-
-	if (priv->bands[IEEE80211_BAND_2GHZ].n_channels)
-		priv->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
-			&priv->bands[IEEE80211_BAND_2GHZ];
-
-	if (priv->bands[IEEE80211_BAND_5GHZ].n_channels)
-		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
-			&priv->bands[IEEE80211_BAND_5GHZ];
-
-	ret = ieee80211_register_hw(priv->hw);
-	if (ret) {
-		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
-		return ret;
-	}
-	priv->mac80211_registered = 1;
-
-	return 0;
-}
-
-static int iwl3945_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-{
-	int err = 0, i;
-	struct iwl_priv *priv;
-	struct ieee80211_hw *hw;
-	struct iwl_cfg *cfg = (struct iwl_cfg *)(ent->driver_data);
-	struct iwl3945_eeprom *eeprom;
-	unsigned long flags;
-
-	/***********************
-	 * 1. Allocating HW data
-	 * ********************/
-
-	/* mac80211 allocates memory for this device instance, including
-	 *   space for this driver's private structure */
-	hw = iwl_alloc_all(cfg);
-	if (hw == NULL) {
-		pr_err("Can not allocate network device\n");
-		err = -ENOMEM;
-		goto out;
-	}
-	priv = hw->priv;
-	SET_IEEE80211_DEV(hw, &pdev->dev);
-
-	priv->cmd_queue = IWL39_CMD_QUEUE_NUM;
-
-	/* 3945 has only one valid context */
-	priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
-
-	for (i = 0; i < NUM_IWL_RXON_CTX; i++)
-		priv->contexts[i].ctxid = i;
-
-	priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
-	priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
-	priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
-	priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
-	priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
-	priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
-	priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
-		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
-	priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
-	priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
-	priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
-
-	/*
-	 * Disabling hardware scan means that mac80211 will perform scans
-	 * "the hard way", rather than using device's scan.
-	 */
-	if (iwl3945_mod_params.disable_hw_scan) {
-		dev_printk(KERN_DEBUG, &(pdev->dev),
-			"sw scan support is deprecated\n");
-		iwl3945_hw_ops.hw_scan = NULL;
-	}
-
-
-	IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n");
-	priv->cfg = cfg;
-	priv->pci_dev = pdev;
-	priv->inta_mask = CSR_INI_SET_MASK;
-
-	if (iwl_alloc_traffic_mem(priv))
-		IWL_ERR(priv, "Not enough memory to generate traffic log\n");
-
-	/***************************
-	 * 2. Initializing PCI bus
-	 * *************************/
-	pci_disable_link_state(pdev, PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1 |
-				PCIE_LINK_STATE_CLKPM);
-
-	if (pci_enable_device(pdev)) {
-		err = -ENODEV;
-		goto out_ieee80211_free_hw;
-	}
-
-	pci_set_master(pdev);
-
-	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (!err)
-		err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
-	if (err) {
-		IWL_WARN(priv, "No suitable DMA available.\n");
-		goto out_pci_disable_device;
-	}
-
-	pci_set_drvdata(pdev, priv);
-	err = pci_request_regions(pdev, DRV_NAME);
-	if (err)
-		goto out_pci_disable_device;
-
-	/***********************
-	 * 3. Read REV Register
-	 * ********************/
-	priv->hw_base = pci_iomap(pdev, 0, 0);
-	if (!priv->hw_base) {
-		err = -ENODEV;
-		goto out_pci_release_regions;
-	}
-
-	IWL_DEBUG_INFO(priv, "pci_resource_len = 0x%08llx\n",
-			(unsigned long long) pci_resource_len(pdev, 0));
-	IWL_DEBUG_INFO(priv, "pci_resource_base = %p\n", priv->hw_base);
-
-	/* We disable the RETRY_TIMEOUT register (0x41) to keep
-	 * PCI Tx retries from interfering with C3 CPU state */
-	pci_write_config_byte(pdev, 0x41, 0x00);
-
-	/* these spin locks will be used in apm_ops.init and EEPROM access
-	 * we should init now
-	 */
-	spin_lock_init(&priv->reg_lock);
-	spin_lock_init(&priv->lock);
-
-	/*
-	 * stop and reset the on-board processor just in case it is in a
-	 * strange state ... like being left stranded by a primary kernel
-	 * and this is now the kdump kernel trying to start up
-	 */
-	iwl_write32(priv, CSR_RESET, CSR_RESET_REG_FLAG_NEVO_RESET);
-
-	/***********************
-	 * 4. Read EEPROM
-	 * ********************/
-
-	/* Read the EEPROM */
-	err = iwl_eeprom_init(priv);
-	if (err) {
-		IWL_ERR(priv, "Unable to init EEPROM\n");
-		goto out_iounmap;
-	}
-	/* MAC Address location in EEPROM same for 3945/4965 */
-	eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	IWL_DEBUG_INFO(priv, "MAC address: %pM\n", eeprom->mac_address);
-	SET_IEEE80211_PERM_ADDR(priv->hw, eeprom->mac_address);
-
-	/***********************
-	 * 5. Setup HW Constants
-	 * ********************/
-	/* Device-specific setup */
-	if (iwl3945_hw_set_hw_params(priv)) {
-		IWL_ERR(priv, "failed to set hw settings\n");
-		goto out_eeprom_free;
-	}
-
-	/***********************
-	 * 6. Setup priv
-	 * ********************/
-
-	err = iwl3945_init_drv(priv);
-	if (err) {
-		IWL_ERR(priv, "initializing driver failed\n");
-		goto out_unset_hw_params;
-	}
-
-	IWL_INFO(priv, "Detected Intel Wireless WiFi Link %s\n",
-		priv->cfg->name);
-
-	/***********************
-	 * 7. Setup Services
-	 * ********************/
-
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	pci_enable_msi(priv->pci_dev);
-
-	err = request_irq(priv->pci_dev->irq, priv->cfg->ops->lib->isr_ops.isr,
-			  IRQF_SHARED, DRV_NAME, priv);
-	if (err) {
-		IWL_ERR(priv, "Error allocating IRQ %d\n", priv->pci_dev->irq);
-		goto out_disable_msi;
-	}
-
-	err = sysfs_create_group(&pdev->dev.kobj, &iwl3945_attribute_group);
-	if (err) {
-		IWL_ERR(priv, "failed to create sysfs device attributes\n");
-		goto out_release_irq;
-	}
-
-	iwl_set_rxon_channel(priv,
-			     &priv->bands[IEEE80211_BAND_2GHZ].channels[5],
-			     &priv->contexts[IWL_RXON_CTX_BSS]);
-	iwl3945_setup_deferred_work(priv);
-	iwl3945_setup_rx_handlers(priv);
-	iwl_power_initialize(priv);
-
-	/*********************************
-	 * 8. Setup and Register mac80211
-	 * *******************************/
-
-	iwl_enable_interrupts(priv);
-
-	err = iwl3945_setup_mac(priv);
-	if (err)
-		goto  out_remove_sysfs;
-
-	err = iwl_dbgfs_register(priv, DRV_NAME);
-	if (err)
-		IWL_ERR(priv, "failed to create debugfs files. Ignoring error: %d\n", err);
-
-	/* Start monitoring the killswitch */
-	queue_delayed_work(priv->workqueue, &priv->_3945.rfkill_poll,
-			   2 * HZ);
-
-	return 0;
-
- out_remove_sysfs:
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
-	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
- out_release_irq:
-	free_irq(priv->pci_dev->irq, priv);
- out_disable_msi:
-	pci_disable_msi(priv->pci_dev);
-	iwlcore_free_geos(priv);
-	iwl_free_channel_map(priv);
- out_unset_hw_params:
-	iwl3945_unset_hw_params(priv);
- out_eeprom_free:
-	iwl_eeprom_free(priv);
- out_iounmap:
-	pci_iounmap(pdev, priv->hw_base);
- out_pci_release_regions:
-	pci_release_regions(pdev);
- out_pci_disable_device:
-	pci_set_drvdata(pdev, NULL);
-	pci_disable_device(pdev);
- out_ieee80211_free_hw:
-	iwl_free_traffic_mem(priv);
-	ieee80211_free_hw(priv->hw);
- out:
-	return err;
-}
-
-static void __devexit iwl3945_pci_remove(struct pci_dev *pdev)
-{
-	struct iwl_priv *priv = pci_get_drvdata(pdev);
-	unsigned long flags;
-
-	if (!priv)
-		return;
-
-	IWL_DEBUG_INFO(priv, "*** UNLOAD DRIVER ***\n");
-
-	iwl_dbgfs_unregister(priv);
-
-	set_bit(STATUS_EXIT_PENDING, &priv->status);
-
-	if (priv->mac80211_registered) {
-		ieee80211_unregister_hw(priv->hw);
-		priv->mac80211_registered = 0;
-	} else {
-		iwl3945_down(priv);
-	}
-
-	/*
-	 * Make sure device is reset to low power before unloading driver.
-	 * This may be redundant with iwl_down(), but there are paths to
-	 * run iwl_down() without calling apm_ops.stop(), and there are
-	 * paths to avoid running iwl_down() at all before leaving driver.
-	 * This (inexpensive) call *makes sure* device is reset.
-	 */
-	iwl_apm_stop(priv);
-
-	/* make sure we flush any pending irq or
-	 * tasklet for the driver
-	 */
-	spin_lock_irqsave(&priv->lock, flags);
-	iwl_disable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_synchronize_irq(priv);
-
-	sysfs_remove_group(&pdev->dev.kobj, &iwl3945_attribute_group);
-
-	cancel_delayed_work_sync(&priv->_3945.rfkill_poll);
-
-	iwl3945_dealloc_ucode_pci(priv);
-
-	if (priv->rxq.bd)
-		iwl3945_rx_queue_free(priv, &priv->rxq);
-	iwl3945_hw_txq_ctx_free(priv);
-
-	iwl3945_unset_hw_params(priv);
-
-	/*netif_stop_queue(dev); */
-	flush_workqueue(priv->workqueue);
-
-	/* ieee80211_unregister_hw calls iwl3945_mac_stop, which flushes
-	 * priv->workqueue... so we can't take down the workqueue
-	 * until now... */
-	destroy_workqueue(priv->workqueue);
-	priv->workqueue = NULL;
-	iwl_free_traffic_mem(priv);
-
-	free_irq(pdev->irq, priv);
-	pci_disable_msi(pdev);
-
-	pci_iounmap(pdev, priv->hw_base);
-	pci_release_regions(pdev);
-	pci_disable_device(pdev);
-	pci_set_drvdata(pdev, NULL);
-
-	iwl_free_channel_map(priv);
-	iwlcore_free_geos(priv);
-	kfree(priv->scan_cmd);
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	ieee80211_free_hw(priv->hw);
-}
-
-
-/*****************************************************************************
- *
- * driver and module entry point
- *
- *****************************************************************************/
-
-static struct pci_driver iwl3945_driver = {
-	.name = DRV_NAME,
-	.id_table = iwl3945_hw_card_ids,
-	.probe = iwl3945_pci_probe,
-	.remove = __devexit_p(iwl3945_pci_remove),
-	.driver.pm = IWL_PM_OPS,
-};
-
-static int __init iwl3945_init(void)
-{
-
-	int ret;
-	pr_info(DRV_DESCRIPTION ", " DRV_VERSION "\n");
-	pr_info(DRV_COPYRIGHT "\n");
-
-	ret = iwl3945_rate_control_register();
-	if (ret) {
-		pr_err("Unable to register rate control algorithm: %d\n", ret);
-		return ret;
-	}
-
-	ret = pci_register_driver(&iwl3945_driver);
-	if (ret) {
-		pr_err("Unable to initialize PCI module\n");
-		goto error_register;
-	}
-
-	return ret;
-
-error_register:
-	iwl3945_rate_control_unregister();
-	return ret;
-}
-
-static void __exit iwl3945_exit(void)
-{
-	pci_unregister_driver(&iwl3945_driver);
-	iwl3945_rate_control_unregister();
-}
-
-/*(DEBLOBBED)*/
-
-module_param_named(antenna, iwl3945_mod_params.antenna, int, S_IRUGO);
-MODULE_PARM_DESC(antenna, "select antenna (1=Main, 2=Aux, default 0 [both])");
-module_param_named(swcrypto, iwl3945_mod_params.sw_crypto, int, S_IRUGO);
-MODULE_PARM_DESC(swcrypto,
-		 "using software crypto (default 1 [software])\n");
-#ifdef CONFIG_IWLWIFI_DEBUG
-module_param_named(debug, iwl_debug_level, uint, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "debug output mask");
-#endif
-module_param_named(disable_hw_scan, iwl3945_mod_params.disable_hw_scan,
-		   int, S_IRUGO);
-MODULE_PARM_DESC(disable_hw_scan,
-		 "disable hardware scanning (default 0) (deprecated)");
-module_param_named(fw_restart3945, iwl3945_mod_params.restart_fw, int, S_IRUGO);
-MODULE_PARM_DESC(fw_restart3945, "restart firmware in case of error");
-
-module_exit(iwl3945_exit);
-module_init(iwl3945_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2753 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
- *
- * 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 <linux/slab.h>
-#include <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <linux/firmware.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-#include <net/mac80211.h>
-
-#include "iwl-fh.h"
-#include "iwl-3945-fh.h"
-#include "iwl-commands.h"
-#include "iwl-sta.h"
-#include "iwl-3945.h"
-#include "iwl-eeprom.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-led.h"
-#include "iwl-3945-led.h"
-#include "iwl-3945-debugfs.h"
-#include "iwl-legacy.h"
-
-#define IWL_DECLARE_RATE_INFO(r, ip, in, rp, rn, pp, np)    \
-	[IWL_RATE_##r##M_INDEX] = { IWL_RATE_##r##M_PLCP,   \
-				    IWL_RATE_##r##M_IEEE,   \
-				    IWL_RATE_##ip##M_INDEX, \
-				    IWL_RATE_##in##M_INDEX, \
-				    IWL_RATE_##rp##M_INDEX, \
-				    IWL_RATE_##rn##M_INDEX, \
-				    IWL_RATE_##pp##M_INDEX, \
-				    IWL_RATE_##np##M_INDEX, \
-				    IWL_RATE_##r##M_INDEX_TABLE, \
-				    IWL_RATE_##ip##M_INDEX_TABLE }
-
-/*
- * Parameter order:
- *   rate, prev rate, next rate, prev tgg rate, next tgg rate
- *
- * If there isn't a valid next or previous rate then INV is used which
- * maps to IWL_RATE_INVALID
- *
- */
-const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945] = {
-	IWL_DECLARE_RATE_INFO(1, INV, 2, INV, 2, INV, 2),    /*  1mbps */
-	IWL_DECLARE_RATE_INFO(2, 1, 5, 1, 5, 1, 5),          /*  2mbps */
-	IWL_DECLARE_RATE_INFO(5, 2, 6, 2, 11, 2, 11),        /*5.5mbps */
-	IWL_DECLARE_RATE_INFO(11, 9, 12, 5, 12, 5, 18),      /* 11mbps */
-	IWL_DECLARE_RATE_INFO(6, 5, 9, 5, 11, 5, 11),        /*  6mbps */
-	IWL_DECLARE_RATE_INFO(9, 6, 11, 5, 11, 5, 11),       /*  9mbps */
-	IWL_DECLARE_RATE_INFO(12, 11, 18, 11, 18, 11, 18),   /* 12mbps */
-	IWL_DECLARE_RATE_INFO(18, 12, 24, 12, 24, 11, 24),   /* 18mbps */
-	IWL_DECLARE_RATE_INFO(24, 18, 36, 18, 36, 18, 36),   /* 24mbps */
-	IWL_DECLARE_RATE_INFO(36, 24, 48, 24, 48, 24, 48),   /* 36mbps */
-	IWL_DECLARE_RATE_INFO(48, 36, 54, 36, 54, 36, 54),   /* 48mbps */
-	IWL_DECLARE_RATE_INFO(54, 48, INV, 48, INV, 48, INV),/* 54mbps */
-};
-
-static inline u8 iwl3945_get_prev_ieee_rate(u8 rate_index)
-{
-	u8 rate = iwl3945_rates[rate_index].prev_ieee;
-
-	if (rate == IWL_RATE_INVALID)
-		rate = rate_index;
-	return rate;
-}
-
-/* 1 = enable the iwl3945_disable_events() function */
-#define IWL_EVT_DISABLE (0)
-#define IWL_EVT_DISABLE_SIZE (1532/32)
-
-/**
- * iwl3945_disable_events - Disable selected events in uCode event log
- *
- * Disable an event by writing "1"s into "disable"
- *   bitmap in SRAM.  Bit position corresponds to Event # (id/type).
- *   Default values of 0 enable uCode events to be logged.
- * Use for only special debugging.  This function is just a placeholder as-is,
- *   you'll need to provide the special bits! ...
- *   ... and set IWL_EVT_DISABLE to 1. */
-void iwl3945_disable_events(struct iwl_priv *priv)
-{
-	int i;
-	u32 base;		/* SRAM address of event log header */
-	u32 disable_ptr;	/* SRAM address of event-disable bitmap array */
-	u32 array_size;		/* # of u32 entries in array */
-	static const u32 evt_disable[IWL_EVT_DISABLE_SIZE] = {
-		0x00000000,	/*   31 -    0  Event id numbers */
-		0x00000000,	/*   63 -   32 */
-		0x00000000,	/*   95 -   64 */
-		0x00000000,	/*  127 -   96 */
-		0x00000000,	/*  159 -  128 */
-		0x00000000,	/*  191 -  160 */
-		0x00000000,	/*  223 -  192 */
-		0x00000000,	/*  255 -  224 */
-		0x00000000,	/*  287 -  256 */
-		0x00000000,	/*  319 -  288 */
-		0x00000000,	/*  351 -  320 */
-		0x00000000,	/*  383 -  352 */
-		0x00000000,	/*  415 -  384 */
-		0x00000000,	/*  447 -  416 */
-		0x00000000,	/*  479 -  448 */
-		0x00000000,	/*  511 -  480 */
-		0x00000000,	/*  543 -  512 */
-		0x00000000,	/*  575 -  544 */
-		0x00000000,	/*  607 -  576 */
-		0x00000000,	/*  639 -  608 */
-		0x00000000,	/*  671 -  640 */
-		0x00000000,	/*  703 -  672 */
-		0x00000000,	/*  735 -  704 */
-		0x00000000,	/*  767 -  736 */
-		0x00000000,	/*  799 -  768 */
-		0x00000000,	/*  831 -  800 */
-		0x00000000,	/*  863 -  832 */
-		0x00000000,	/*  895 -  864 */
-		0x00000000,	/*  927 -  896 */
-		0x00000000,	/*  959 -  928 */
-		0x00000000,	/*  991 -  960 */
-		0x00000000,	/* 1023 -  992 */
-		0x00000000,	/* 1055 - 1024 */
-		0x00000000,	/* 1087 - 1056 */
-		0x00000000,	/* 1119 - 1088 */
-		0x00000000,	/* 1151 - 1120 */
-		0x00000000,	/* 1183 - 1152 */
-		0x00000000,	/* 1215 - 1184 */
-		0x00000000,	/* 1247 - 1216 */
-		0x00000000,	/* 1279 - 1248 */
-		0x00000000,	/* 1311 - 1280 */
-		0x00000000,	/* 1343 - 1312 */
-		0x00000000,	/* 1375 - 1344 */
-		0x00000000,	/* 1407 - 1376 */
-		0x00000000,	/* 1439 - 1408 */
-		0x00000000,	/* 1471 - 1440 */
-		0x00000000,	/* 1503 - 1472 */
-	};
-
-	base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
-	if (!iwl3945_hw_valid_rtc_data_addr(base)) {
-		IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base);
-		return;
-	}
-
-	disable_ptr = iwl_read_targ_mem(priv, base + (4 * sizeof(u32)));
-	array_size = iwl_read_targ_mem(priv, base + (5 * sizeof(u32)));
-
-	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);
-		for (i = 0; i < IWL_EVT_DISABLE_SIZE; i++)
-			iwl_write_targ_mem(priv,
-					   disable_ptr + (i * sizeof(u32)),
-					   evt_disable[i]);
-
-	} 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");
-		IWL_DEBUG_INFO(priv, "  in SRAM at 0x%x, size %d u32s\n",
-			       disable_ptr, array_size);
-	}
-
-}
-
-static int iwl3945_hwrate_to_plcp_idx(u8 plcp)
-{
-	int idx;
-
-	for (idx = 0; idx < IWL_RATE_COUNT_3945; idx++)
-		if (iwl3945_rates[idx].plcp == plcp)
-			return idx;
-	return -1;
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUG
-#define TX_STATUS_ENTRY(x) case TX_3945_STATUS_FAIL_ ## x: return #x
-
-static const char *iwl3945_get_tx_fail_reason(u32 status)
-{
-	switch (status & TX_STATUS_MSK) {
-	case TX_3945_STATUS_SUCCESS:
-		return "SUCCESS";
-		TX_STATUS_ENTRY(SHORT_LIMIT);
-		TX_STATUS_ENTRY(LONG_LIMIT);
-		TX_STATUS_ENTRY(FIFO_UNDERRUN);
-		TX_STATUS_ENTRY(MGMNT_ABORT);
-		TX_STATUS_ENTRY(NEXT_FRAG);
-		TX_STATUS_ENTRY(LIFE_EXPIRE);
-		TX_STATUS_ENTRY(DEST_PS);
-		TX_STATUS_ENTRY(ABORTED);
-		TX_STATUS_ENTRY(BT_RETRY);
-		TX_STATUS_ENTRY(STA_INVALID);
-		TX_STATUS_ENTRY(FRAG_DROPPED);
-		TX_STATUS_ENTRY(TID_DISABLE);
-		TX_STATUS_ENTRY(FRAME_FLUSHED);
-		TX_STATUS_ENTRY(INSUFFICIENT_CF_POLL);
-		TX_STATUS_ENTRY(TX_LOCKED);
-		TX_STATUS_ENTRY(NO_BEACON_ON_RADAR);
-	}
-
-	return "UNKNOWN";
-}
-#else
-static inline const char *iwl3945_get_tx_fail_reason(u32 status)
-{
-	return "";
-}
-#endif
-
-/*
- * get ieee prev rate from rate scale table.
- * for A and B mode we need to overright prev
- * value
- */
-int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate)
-{
-	int next_rate = iwl3945_get_prev_ieee_rate(rate);
-
-	switch (priv->band) {
-	case IEEE80211_BAND_5GHZ:
-		if (rate == IWL_RATE_12M_INDEX)
-			next_rate = IWL_RATE_9M_INDEX;
-		else if (rate == IWL_RATE_6M_INDEX)
-			next_rate = IWL_RATE_6M_INDEX;
-		break;
-	case IEEE80211_BAND_2GHZ:
-		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-		    iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-			if (rate == IWL_RATE_11M_INDEX)
-				next_rate = IWL_RATE_5M_INDEX;
-		}
-		break;
-
-	default:
-		break;
-	}
-
-	return next_rate;
-}
-
-
-/**
- * iwl3945_tx_queue_reclaim - Reclaim Tx queue entries already Tx'd
- *
- * When FW advances 'R' index, all entries between old and new 'R' index
- * need to be reclaimed. As result, some free space forms. If there is
- * enough free space (> low mark), wake the stack that feeds us.
- */
-static void iwl3945_tx_queue_reclaim(struct iwl_priv *priv,
-				     int txq_id, int index)
-{
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
-	struct iwl_tx_info *tx_info;
-
-	BUG_ON(txq_id == IWL39_CMD_QUEUE_NUM);
-
-	for (index = iwl_queue_inc_wrap(index, q->n_bd); q->read_ptr != index;
-		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
-
-		tx_info = &txq->txb[txq->q.read_ptr];
-		ieee80211_tx_status_irqsafe(priv->hw, tx_info->skb);
-		tx_info->skb = NULL;
-		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
-	}
-
-	if (iwl_queue_space(q) > q->low_mark && (txq_id >= 0) &&
-			(txq_id != IWL39_CMD_QUEUE_NUM) &&
-			priv->mac80211_registered)
-		iwl_wake_queue(priv, txq);
-}
-
-/**
- * iwl3945_rx_reply_tx - Handle Tx response
- */
-static void iwl3945_rx_reply_tx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-	int txq_id = SEQ_TO_QUEUE(sequence);
-	int index = SEQ_TO_INDEX(sequence);
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct ieee80211_tx_info *info;
-	struct iwl3945_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-	u32  status = le32_to_cpu(tx_resp->status);
-	int rate_idx;
-	int fail;
-
-	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
-			  "is out of range [0-%d] %d %d\n", txq_id,
-			  index, txq->q.n_bd, txq->q.write_ptr,
-			  txq->q.read_ptr);
-		return;
-	}
-
-	txq->time_stamp = jiffies;
-	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
-	ieee80211_tx_info_clear_status(info);
-
-	/* Fill the MRR chain with some info about on-chip retransmissions */
-	rate_idx = iwl3945_hwrate_to_plcp_idx(tx_resp->rate);
-	if (info->band == IEEE80211_BAND_5GHZ)
-		rate_idx -= IWL_FIRST_OFDM_RATE;
-
-	fail = tx_resp->failure_frame;
-
-	info->status.rates[0].idx = rate_idx;
-	info->status.rates[0].count = fail + 1; /* add final attempt */
-
-	/* tx_status->rts_retry_count = tx_resp->failure_rts; */
-	info->flags |= ((status & TX_STATUS_MSK) == TX_STATUS_SUCCESS) ?
-				IEEE80211_TX_STAT_ACK : 0;
-
-	IWL_DEBUG_TX(priv, "Tx queue %d Status %s (0x%08x) plcp rate %d retries %d\n",
-			txq_id, iwl3945_get_tx_fail_reason(status), status,
-			tx_resp->rate, tx_resp->failure_frame);
-
-	IWL_DEBUG_TX_REPLY(priv, "Tx queue reclaim %d\n", index);
-	iwl3945_tx_queue_reclaim(priv, txq_id, index);
-
-	if (status & TX_ABORT_REQUIRED_MSK)
-		IWL_ERR(priv, "TODO:  Implement Tx ABORT REQUIRED!!!\n");
-}
-
-
-
-/*****************************************************************************
- *
- * Intel PRO/Wireless 3945ABG/BG Network Connection
- *
- *  RX handler implementations
- *
- *****************************************************************************/
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/*
- *  based on the assumption of all statistics counter are in DWORD
- *  FIXME: This function is for debugging, do not deal with
- *  the case of counters roll-over.
- */
-static void iwl3945_accumulative_statistics(struct iwl_priv *priv,
-					    __le32 *stats)
-{
-	int i;
-	__le32 *prev_stats;
-	u32 *accum_stats;
-	u32 *delta, *max_delta;
-
-	prev_stats = (__le32 *)&priv->_3945.statistics;
-	accum_stats = (u32 *)&priv->_3945.accum_statistics;
-	delta = (u32 *)&priv->_3945.delta_statistics;
-	max_delta = (u32 *)&priv->_3945.max_delta;
-
-	for (i = sizeof(__le32); i < sizeof(struct iwl3945_notif_statistics);
-	     i += sizeof(__le32), stats++, prev_stats++, delta++,
-	     max_delta++, accum_stats++) {
-		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-			*delta = (le32_to_cpu(*stats) -
-				le32_to_cpu(*prev_stats));
-			*accum_stats += *delta;
-			if (*delta > *max_delta)
-				*max_delta = *delta;
-		}
-	}
-
-	/* reset accumulative statistics for "no-counter" type statistics */
-	priv->_3945.accum_statistics.general.temperature =
-		priv->_3945.statistics.general.temperature;
-	priv->_3945.accum_statistics.general.ttl_timestamp =
-		priv->_3945.statistics.general.ttl_timestamp;
-}
-#endif
-
-void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
-		struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	IWL_DEBUG_RX(priv, "Statistics notification received (%d vs %d).\n",
-		     (int)sizeof(struct iwl3945_notif_statistics),
-		     le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK);
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-	iwl3945_accumulative_statistics(priv, (__le32 *)&pkt->u.raw);
-#endif
-	iwl_recover_from_statistics(priv, pkt);
-
-	memcpy(&priv->_3945.statistics, pkt->u.raw, sizeof(priv->_3945.statistics));
-}
-
-void iwl3945_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	__le32 *flag = (__le32 *)&pkt->u.raw;
-
-	if (le32_to_cpu(*flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->_3945.accum_statistics, 0,
-			sizeof(struct iwl3945_notif_statistics));
-		memset(&priv->_3945.delta_statistics, 0,
-			sizeof(struct iwl3945_notif_statistics));
-		memset(&priv->_3945.max_delta, 0,
-			sizeof(struct iwl3945_notif_statistics));
-#endif
-		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-	}
-	iwl3945_hw_rx_statistics(priv, rxb);
-}
-
-
-/******************************************************************************
- *
- * Misc. internal state and helper functions
- *
- ******************************************************************************/
-
-/* This is necessary only for a number of statistics, see the caller. */
-static int iwl3945_is_network_packet(struct iwl_priv *priv,
-		struct ieee80211_hdr *header)
-{
-	/* Filter incoming packets to determine if they are targeted toward
-	 * this network, discarding packets coming from ourselves */
-	switch (priv->iw_mode) {
-	case NL80211_IFTYPE_ADHOC: /* Header: Dest. | Source    | BSSID */
-		/* packets to our IBSS update information */
-		return !compare_ether_addr(header->addr3, priv->bssid);
-	case NL80211_IFTYPE_STATION: /* Header: Dest. | AP{BSSID} | Source */
-		/* packets to our IBSS update information */
-		return !compare_ether_addr(header->addr2, priv->bssid);
-	default:
-		return 1;
-	}
-}
-
-static void iwl3945_pass_packet_to_mac80211(struct iwl_priv *priv,
-				   struct iwl_rx_mem_buffer *rxb,
-				   struct ieee80211_rx_status *stats)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-	u16 len = le16_to_cpu(rx_hdr->len);
-	struct sk_buff *skb;
-	__le16 fc = hdr->frame_control;
-
-	/* We received data from the HW, so stop the watchdog */
-	if (unlikely(len + IWL39_RX_FRAME_SIZE >
-		     PAGE_SIZE << priv->hw_params.rx_page_order)) {
-		IWL_DEBUG_DROP(priv, "Corruption detected!\n");
-		return;
-	}
-
-	/* We only process data packets if the interface is open */
-	if (unlikely(!priv->is_open)) {
-		IWL_DEBUG_DROP_LIMIT(priv,
-			"Dropping packet while interface is not open.\n");
-		return;
-	}
-
-	skb = dev_alloc_skb(128);
-	if (!skb) {
-		IWL_ERR(priv, "dev_alloc_skb failed\n");
-		return;
-	}
-
-	if (!iwl3945_mod_params.sw_crypto)
-		iwl_set_decrypted_flag(priv,
-				       (struct ieee80211_hdr *)rxb_addr(rxb),
-				       le32_to_cpu(rx_end->status), stats);
-
-	skb_add_rx_frag(skb, 0, rxb->page,
-			(void *)rx_hdr->payload - (void *)pkt, len);
-
-	iwl_update_stats(priv, false, fc, len);
-	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
-	ieee80211_rx(priv->hw, skb);
-	priv->alloc_rxb_page--;
-	rxb->page = NULL;
-}
-
-#define IWL_DELAY_NEXT_SCAN_AFTER_ASSOC (HZ*6)
-
-static void iwl3945_rx_reply_rx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl3945_rx_frame_stats *rx_stats = IWL_RX_STATS(pkt);
-	struct iwl3945_rx_frame_hdr *rx_hdr = IWL_RX_HDR(pkt);
-	struct iwl3945_rx_frame_end *rx_end = IWL_RX_END(pkt);
-	u16 rx_stats_sig_avg __maybe_unused = le16_to_cpu(rx_stats->sig_avg);
-	u16 rx_stats_noise_diff __maybe_unused = le16_to_cpu(rx_stats->noise_diff);
-	u8 network_packet;
-
-	rx_status.flag = 0;
-	rx_status.mactime = le64_to_cpu(rx_end->timestamp);
-	rx_status.freq =
-		ieee80211_channel_to_frequency(le16_to_cpu(rx_hdr->channel));
-	rx_status.band = (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-
-	rx_status.rate_idx = iwl3945_hwrate_to_plcp_idx(rx_hdr->rate);
-	if (rx_status.band == IEEE80211_BAND_5GHZ)
-		rx_status.rate_idx -= IWL_FIRST_OFDM_RATE;
-
-	rx_status.antenna = (le16_to_cpu(rx_hdr->phy_flags) &
-					RX_RES_PHY_FLAGS_ANTENNA_MSK) >> 4;
-
-	/* set the preamble flag if appropriate */
-	if (rx_hdr->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-		rx_status.flag |= RX_FLAG_SHORTPRE;
-
-	if ((unlikely(rx_stats->phy_count > 20))) {
-		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-				rx_stats->phy_count);
-		return;
-	}
-
-	if (!(rx_end->status & RX_RES_STATUS_NO_CRC32_ERROR)
-	    || !(rx_end->status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n", rx_end->status);
-		return;
-	}
-
-
-
-	/* Convert 3945's rssi indicator to dBm */
-	rx_status.signal = rx_stats->rssi - IWL39_RSSI_OFFSET;
-
-	IWL_DEBUG_STATS(priv, "Rssi %d sig_avg %d noise_diff %d\n",
-			rx_status.signal, rx_stats_sig_avg,
-			rx_stats_noise_diff);
-
-	header = (struct ieee80211_hdr *)IWL_RX_DATA(pkt);
-
-	network_packet = iwl3945_is_network_packet(priv, header);
-
-	IWL_DEBUG_STATS_LIMIT(priv, "[%c] %d RSSI:%d Signal:%u, Rate:%u\n",
-			      network_packet ? '*' : ' ',
-			      le16_to_cpu(rx_hdr->channel),
-			      rx_status.signal, rx_status.signal,
-			      rx_status.rate_idx);
-
-	iwl_dbg_log_rx_data_frame(priv, le16_to_cpu(rx_hdr->len), header);
-
-	if (network_packet) {
-		priv->_3945.last_beacon_time =
-			le32_to_cpu(rx_end->beacon_timestamp);
-		priv->_3945.last_tsf = le64_to_cpu(rx_end->timestamp);
-		priv->_3945.last_rx_rssi = rx_status.signal;
-	}
-
-	iwl3945_pass_packet_to_mac80211(priv, rxb, &rx_status);
-}
-
-int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-				     struct iwl_tx_queue *txq,
-				     dma_addr_t addr, u16 len, u8 reset, u8 pad)
-{
-	int count;
-	struct iwl_queue *q;
-	struct iwl3945_tfd *tfd, *tfd_tmp;
-
-	q = &txq->q;
-	tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
-	tfd = &tfd_tmp[q->write_ptr];
-
-	if (reset)
-		memset(tfd, 0, sizeof(*tfd));
-
-	count = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-
-	if ((count >= NUM_TFD_CHUNKS) || (count < 0)) {
-		IWL_ERR(priv, "Error can not send more than %d chunks\n",
-			  NUM_TFD_CHUNKS);
-		return -EINVAL;
-	}
-
-	tfd->tbs[count].addr = cpu_to_le32(addr);
-	tfd->tbs[count].len = cpu_to_le32(len);
-
-	count++;
-
-	tfd->control_flags = cpu_to_le32(TFD_CTL_COUNT_SET(count) |
-					 TFD_CTL_PAD_SET(pad));
-
-	return 0;
-}
-
-/**
- * iwl3945_hw_txq_free_tfd - Free one TFD, those at index [txq->q.read_ptr]
- *
- * Does NOT advance any indexes
- */
-void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	struct iwl3945_tfd *tfd_tmp = (struct iwl3945_tfd *)txq->tfds;
-	int index = txq->q.read_ptr;
-	struct iwl3945_tfd *tfd = &tfd_tmp[index];
-	struct pci_dev *dev = priv->pci_dev;
-	int i;
-	int counter;
-
-	/* sanity check */
-	counter = TFD_CTL_COUNT_GET(le32_to_cpu(tfd->control_flags));
-	if (counter > NUM_TFD_CHUNKS) {
-		IWL_ERR(priv, "Too many chunks: %i\n", counter);
-		/* @todo issue fatal error, it is quite serious situation */
-		return;
-	}
-
-	/* Unmap tx_cmd */
-	if (counter)
-		pci_unmap_single(dev,
-				dma_unmap_addr(&txq->meta[index], mapping),
-				dma_unmap_len(&txq->meta[index], len),
-				PCI_DMA_TODEVICE);
-
-	/* unmap chunks if any */
-
-	for (i = 1; i < counter; i++)
-		pci_unmap_single(dev, le32_to_cpu(tfd->tbs[i].addr),
-			 le32_to_cpu(tfd->tbs[i].len), PCI_DMA_TODEVICE);
-
-	/* free SKB */
-	if (txq->txb) {
-		struct sk_buff *skb;
-
-		skb = txq->txb[txq->q.read_ptr].skb;
-
-		/* can be called from irqs-disabled context */
-		if (skb) {
-			dev_kfree_skb_any(skb);
-			txq->txb[txq->q.read_ptr].skb = NULL;
-		}
-	}
-}
-
-/**
- * iwl3945_hw_build_tx_cmd_rate - Add rate portion to TX_CMD:
- *
-*/
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-				  struct iwl_device_cmd *cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr,
-				  int sta_id, int tx_id)
-{
-	u16 hw_value = ieee80211_get_tx_rate(priv->hw, info)->hw_value;
-	u16 rate_index = min(hw_value & 0xffff, IWL_RATE_COUNT_3945);
-	u16 rate_mask;
-	int rate;
-	u8 rts_retry_limit;
-	u8 data_retry_limit;
-	__le32 tx_flags;
-	__le16 fc = hdr->frame_control;
-	struct iwl3945_tx_cmd *tx_cmd = (struct iwl3945_tx_cmd *)cmd->cmd.payload;
-
-	rate = iwl3945_rates[rate_index].plcp;
-	tx_flags = tx_cmd->tx_flags;
-
-	/* We need to figure out how to get the sta->supp_rates while
-	 * in this running context */
-	rate_mask = IWL_RATES_MASK;
-
-
-	/* Set retry limit on DATA packets and Probe Responses*/
-	if (ieee80211_is_probe_resp(fc))
-		data_retry_limit = 3;
-	else
-		data_retry_limit = IWL_DEFAULT_TX_RETRY;
-	tx_cmd->data_retry_limit = data_retry_limit;
-
-	if (tx_id >= IWL39_CMD_QUEUE_NUM)
-		rts_retry_limit = 3;
-	else
-		rts_retry_limit = 7;
-
-	if (data_retry_limit < rts_retry_limit)
-		rts_retry_limit = data_retry_limit;
-	tx_cmd->rts_retry_limit = rts_retry_limit;
-
-	tx_cmd->rate = rate;
-	tx_cmd->tx_flags = tx_flags;
-
-	/* OFDM */
-	tx_cmd->supp_rates[0] =
-	   ((rate_mask & IWL_OFDM_RATES_MASK) >> IWL_FIRST_OFDM_RATE) & 0xFF;
-
-	/* CCK */
-	tx_cmd->supp_rates[1] = (rate_mask & 0xF);
-
-	IWL_DEBUG_RATE(priv, "Tx sta id: %d, rate: %d (plcp), flags: 0x%4X "
-		       "cck/ofdm mask: 0x%x/0x%x\n", sta_id,
-		       tx_cmd->rate, le32_to_cpu(tx_cmd->tx_flags),
-		       tx_cmd->supp_rates[1], tx_cmd->supp_rates[0]);
-}
-
-static u8 iwl3945_sync_sta(struct iwl_priv *priv, int sta_id, u16 tx_rate)
-{
-	unsigned long flags_spin;
-	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[sta_id];
-
-	station->sta.sta.modify_mask = STA_MODIFY_TX_RATE_MSK;
-	station->sta.rate_n_flags = cpu_to_le16(tx_rate);
-	station->sta.mode = STA_CONTROL_MODIFY_MSK;
-	iwl_send_add_sta(priv, &station->sta, CMD_ASYNC);
-	spin_unlock_irqrestore(&priv->sta_lock, flags_spin);
-
-	IWL_DEBUG_RATE(priv, "SCALE sync station %d to rate %d\n",
-			sta_id, tx_rate);
-	return sta_id;
-}
-
-static void iwl3945_set_pwr_vmain(struct iwl_priv *priv)
-{
-/*
- * (for documentation purposes)
- * to set power to V_AUX, do
-
-		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_poll_bit(priv, CSR_GPIO_IN,
-				     CSR_GPIO_IN_VAL_VAUX_PWR_SRC,
-				     CSR_GPIO_IN_BIT_AUX_POWER, 5000);
-		}
- */
-
-	iwl_set_bits_mask_prph(priv, APMG_PS_CTRL_REG,
-			APMG_PS_CTRL_VAL_PWR_SRC_VMAIN,
-			~APMG_PS_CTRL_MSK_PWR_SRC);
-
-	iwl_poll_bit(priv, CSR_GPIO_IN, CSR_GPIO_IN_VAL_VMAIN_PWR_SRC,
-		     CSR_GPIO_IN_BIT_AUX_POWER, 5000);	/* uS */
-}
-
-static int iwl3945_rx_init(struct iwl_priv *priv, struct iwl_rx_queue *rxq)
-{
-	iwl_write_direct32(priv, FH39_RCSR_RBD_BASE(0), rxq->bd_dma);
-	iwl_write_direct32(priv, FH39_RCSR_RPTR_ADDR(0), rxq->rb_stts_dma);
-	iwl_write_direct32(priv, FH39_RCSR_WPTR(0), 0);
-	iwl_write_direct32(priv, FH39_RCSR_CONFIG(0),
-		FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE |
-		FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE |
-		FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN |
-		FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128 |
-		(RX_QUEUE_SIZE_LOG << FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE) |
-		FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST |
-		(1 << FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH) |
-		FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH);
-
-	/* fake read to flush all prev I/O */
-	iwl_read_direct32(priv, FH39_RSSR_CTRL);
-
-	return 0;
-}
-
-static int iwl3945_tx_reset(struct iwl_priv *priv)
-{
-
-	/* bypass mode */
-	iwl_write_prph(priv, ALM_SCD_MODE_REG, 0x2);
-
-	/* RA 0 is active */
-	iwl_write_prph(priv, ALM_SCD_ARASTAT_REG, 0x01);
-
-	/* all 6 fifo are active */
-	iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0x3f);
-
-	iwl_write_prph(priv, ALM_SCD_SBYP_MODE_1_REG, 0x010000);
-	iwl_write_prph(priv, ALM_SCD_SBYP_MODE_2_REG, 0x030002);
-	iwl_write_prph(priv, ALM_SCD_TXF4MF_REG, 0x000004);
-	iwl_write_prph(priv, ALM_SCD_TXF5MF_REG, 0x000005);
-
-	iwl_write_direct32(priv, FH39_TSSR_CBB_BASE,
-			     priv->_3945.shared_phys);
-
-	iwl_write_direct32(priv, FH39_TSSR_MSG_CONFIG,
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH |
-		FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH);
-
-
-	return 0;
-}
-
-/**
- * iwl3945_txq_ctx_reset - Reset TX queue context
- *
- * Destroys all DMA structures and initialize them again
- */
-static int iwl3945_txq_ctx_reset(struct iwl_priv *priv)
-{
-	int rc;
-	int txq_id, slots_num;
-
-	iwl3945_hw_txq_ctx_free(priv);
-
-	/* allocate tx queue structure */
-	rc = iwl_alloc_txq_mem(priv);
-	if (rc)
-		return rc;
-
-	/* Tx CMD queue */
-	rc = iwl3945_tx_reset(priv);
-	if (rc)
-		goto error;
-
-	/* Tx queue(s) */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		slots_num = (txq_id == IWL39_CMD_QUEUE_NUM) ?
-				TFD_CMD_SLOTS : TFD_TX_CMD_SLOTS;
-		rc = iwl_tx_queue_init(priv, &priv->txq[txq_id], slots_num,
-				       txq_id);
-		if (rc) {
-			IWL_ERR(priv, "Tx %d queue init failed\n", txq_id);
-			goto error;
-		}
-	}
-
-	return rc;
-
- error:
-	iwl3945_hw_txq_ctx_free(priv);
-	return rc;
-}
-
-
-/*
- * Start up 3945's basic functionality after it has been reset
- * (e.g. after platform boot, or shutdown via iwl_apm_stop())
- * NOTE:  This does not load uCode nor start the embedded processor
- */
-static int iwl3945_apm_init(struct iwl_priv *priv)
-{
-	int ret = iwl_apm_init(priv);
-
-	/* Clear APMG (NIC's internal power management) interrupts */
-	iwl_write_prph(priv, APMG_RTC_INT_MSK_REG, 0x0);
-	iwl_write_prph(priv, APMG_RTC_INT_STT_REG, 0xFFFFFFFF);
-
-	/* Reset radio chip */
-	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;
-}
-
-static void iwl3945_nic_config(struct iwl_priv *priv)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	unsigned long flags;
-	u8 rev_id = 0;
-
-	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) {
-		IWL_DEBUG_INFO(priv, "3945 RADIO-MB type\n");
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MB);
-	} else {
-		IWL_DEBUG_INFO(priv, "3945 RADIO-MM type\n");
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_3945_MM);
-	}
-
-	if (EEPROM_SKU_CAP_OP_MODE_MRC == eeprom->sku_cap) {
-		IWL_DEBUG_INFO(priv, "SKU OP mode is mrc\n");
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_SKU_MRC);
-	} else
-		IWL_DEBUG_INFO(priv, "SKU OP mode is basic\n");
-
-	if ((eeprom->board_revision & 0xF0) == 0xD0) {
-		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
-			       eeprom->board_revision);
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-	} else {
-		IWL_DEBUG_INFO(priv, "3945ABG revision is 0x%X\n",
-			       eeprom->board_revision);
-		iwl_clear_bit(priv, CSR_HW_IF_CONFIG_REG,
-			      CSR39_HW_IF_CONFIG_REG_BIT_BOARD_TYPE);
-	}
-
-	if (eeprom->almgor_m_version <= 1) {
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_A);
-		IWL_DEBUG_INFO(priv, "Card M type A version is 0x%X\n",
-			       eeprom->almgor_m_version);
-	} else {
-		IWL_DEBUG_INFO(priv, "Card M type B version is 0x%X\n",
-			       eeprom->almgor_m_version);
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    CSR39_HW_IF_CONFIG_REG_BITS_SILICON_TYPE_B);
-	}
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	if (eeprom->sku_cap & EEPROM_SKU_CAP_SW_RF_KILL_ENABLE)
-		IWL_DEBUG_RF_KILL(priv, "SW RF KILL supported in EEPROM.\n");
-
-	if (eeprom->sku_cap & EEPROM_SKU_CAP_HW_RF_KILL_ENABLE)
-		IWL_DEBUG_RF_KILL(priv, "HW RF KILL supported in EEPROM.\n");
-}
-
-int iwl3945_hw_nic_init(struct iwl_priv *priv)
-{
-	int rc;
-	unsigned long flags;
-	struct iwl_rx_queue *rxq = &priv->rxq;
-
-	spin_lock_irqsave(&priv->lock, flags);
-	priv->cfg->ops->lib->apm_ops.init(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl3945_set_pwr_vmain(priv);
-
-	priv->cfg->ops->lib->apm_ops.config(priv);
-
-	/* Allocate the RX queue, or reset if it is already allocated */
-	if (!rxq->bd) {
-		rc = iwl_rx_queue_alloc(priv);
-		if (rc) {
-			IWL_ERR(priv, "Unable to initialize Rx queue\n");
-			return -ENOMEM;
-		}
-	} else
-		iwl3945_rx_queue_reset(priv, rxq);
-
-	iwl3945_rx_replenish(priv);
-
-	iwl3945_rx_init(priv, rxq);
-
-
-	/* Look at using this instead:
-	rxq->need_update = 1;
-	iwl_rx_queue_update_write_ptr(priv, rxq);
-	*/
-
-	iwl_write_direct32(priv, FH39_RCSR_WPTR(0), rxq->write & ~7);
-
-	rc = iwl3945_txq_ctx_reset(priv);
-	if (rc)
-		return rc;
-
-	set_bit(STATUS_INIT, &priv->status);
-
-	return 0;
-}
-
-/**
- * iwl3945_hw_txq_ctx_free - Free TXQ Context
- *
- * Destroy all TX DMA queues and structures
- */
-void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv)
-{
-	int txq_id;
-
-	/* Tx queues */
-	if (priv->txq)
-		for (txq_id = 0; txq_id < priv->hw_params.max_txq_num;
-		     txq_id++)
-			if (txq_id == IWL39_CMD_QUEUE_NUM)
-				iwl_cmd_queue_free(priv);
-			else
-				iwl_tx_queue_free(priv, txq_id);
-
-	/* free tx queue structure */
-	iwl_free_txq_mem(priv);
-}
-
-void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv)
-{
-	int txq_id;
-
-	/* stop SCD */
-	iwl_write_prph(priv, ALM_SCD_MODE_REG, 0);
-	iwl_write_prph(priv, ALM_SCD_TXFACT_REG, 0);
-
-	/* reset TFD queues */
-	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++) {
-		iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id), 0x0);
-		iwl_poll_direct_bit(priv, FH39_TSSR_TX_STATUS,
-				FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(txq_id),
-				1000);
-	}
-
-	iwl3945_hw_txq_ctx_free(priv);
-}
-
-/**
- * iwl3945_hw_reg_adjust_power_by_temp
- * return index delta into power gain settings table
-*/
-static int iwl3945_hw_reg_adjust_power_by_temp(int new_reading, int old_reading)
-{
-	return (new_reading - old_reading) * (-11) / 100;
-}
-
-/**
- * iwl3945_hw_reg_temp_out_of_range - Keep temperature in sane range
- */
-static inline int iwl3945_hw_reg_temp_out_of_range(int temperature)
-{
-	return ((temperature < -260) || (temperature > 25)) ? 1 : 0;
-}
-
-int iwl3945_hw_get_temperature(struct iwl_priv *priv)
-{
-	return iwl_read32(priv, CSR_UCODE_DRV_GP2);
-}
-
-/**
- * iwl3945_hw_reg_txpower_get_temperature
- * get the current temperature by reading from NIC
-*/
-static int iwl3945_hw_reg_txpower_get_temperature(struct iwl_priv *priv)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	int temperature;
-
-	temperature = iwl3945_hw_get_temperature(priv);
-
-	/* driver's okay range is -260 to +25.
-	 *   human readable okay range is 0 to +285 */
-	IWL_DEBUG_INFO(priv, "Temperature: %d\n", temperature + IWL_TEMP_CONVERT);
-
-	/* handle insane temp reading */
-	if (iwl3945_hw_reg_temp_out_of_range(temperature)) {
-		IWL_ERR(priv, "Error bad temperature value  %d\n", temperature);
-
-		/* if really really hot(?),
-		 *   substitute the 3rd band/group's temp measured at factory */
-		if (priv->last_temperature > 100)
-			temperature = eeprom->groups[2].temperature;
-		else /* else use most recent "sane" value from driver */
-			temperature = priv->last_temperature;
-	}
-
-	return temperature;	/* raw, not "human readable" */
-}
-
-/* Adjust Txpower only if temperature variance is greater than threshold.
- *
- * Both are lower than older versions' 9 degrees */
-#define IWL_TEMPERATURE_LIMIT_TIMER   6
-
-/**
- * is_temp_calib_needed - determines if new calibration is needed
- *
- * records new temperature in tx_mgr->temperature.
- * replaces tx_mgr->last_temperature *only* if calib needed
- *    (assumes caller will actually do the calibration!). */
-static int is_temp_calib_needed(struct iwl_priv *priv)
-{
-	int temp_diff;
-
-	priv->temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
-	temp_diff = priv->temperature - priv->last_temperature;
-
-	/* get absolute value */
-	if (temp_diff < 0) {
-		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d,\n", temp_diff);
-		temp_diff = -temp_diff;
-	} else if (temp_diff == 0)
-		IWL_DEBUG_POWER(priv, "Same temp,\n");
-	else
-		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d,\n", temp_diff);
-
-	/* if we don't need calibration, *don't* update last_temperature */
-	if (temp_diff < IWL_TEMPERATURE_LIMIT_TIMER) {
-		IWL_DEBUG_POWER(priv, "Timed thermal calib not needed\n");
-		return 0;
-	}
-
-	IWL_DEBUG_POWER(priv, "Timed thermal calib needed\n");
-
-	/* assume that caller will actually do calib ...
-	 *   update the "last temperature" value */
-	priv->last_temperature = priv->temperature;
-	return 1;
-}
-
-#define IWL_MAX_GAIN_ENTRIES 78
-#define IWL_CCK_FROM_OFDM_POWER_DIFF  -5
-#define IWL_CCK_FROM_OFDM_INDEX_DIFF (10)
-
-/* radio and DSP power table, each step is 1/2 dB.
- * 1st number is for RF analog gain, 2nd number is for DSP pre-DAC gain. */
-static struct iwl3945_tx_power power_gain_table[2][IWL_MAX_GAIN_ENTRIES] = {
-	{
-	 {251, 127},		/* 2.4 GHz, highest power */
-	 {251, 127},
-	 {251, 127},
-	 {251, 127},
-	 {251, 125},
-	 {251, 110},
-	 {251, 105},
-	 {251, 98},
-	 {187, 125},
-	 {187, 115},
-	 {187, 108},
-	 {187, 99},
-	 {243, 119},
-	 {243, 111},
-	 {243, 105},
-	 {243, 97},
-	 {243, 92},
-	 {211, 106},
-	 {211, 100},
-	 {179, 120},
-	 {179, 113},
-	 {179, 107},
-	 {147, 125},
-	 {147, 119},
-	 {147, 112},
-	 {147, 106},
-	 {147, 101},
-	 {147, 97},
-	 {147, 91},
-	 {115, 107},
-	 {235, 121},
-	 {235, 115},
-	 {235, 109},
-	 {203, 127},
-	 {203, 121},
-	 {203, 115},
-	 {203, 108},
-	 {203, 102},
-	 {203, 96},
-	 {203, 92},
-	 {171, 110},
-	 {171, 104},
-	 {171, 98},
-	 {139, 116},
-	 {227, 125},
-	 {227, 119},
-	 {227, 113},
-	 {227, 107},
-	 {227, 101},
-	 {227, 96},
-	 {195, 113},
-	 {195, 106},
-	 {195, 102},
-	 {195, 95},
-	 {163, 113},
-	 {163, 106},
-	 {163, 102},
-	 {163, 95},
-	 {131, 113},
-	 {131, 106},
-	 {131, 102},
-	 {131, 95},
-	 {99, 113},
-	 {99, 106},
-	 {99, 102},
-	 {99, 95},
-	 {67, 113},
-	 {67, 106},
-	 {67, 102},
-	 {67, 95},
-	 {35, 113},
-	 {35, 106},
-	 {35, 102},
-	 {35, 95},
-	 {3, 113},
-	 {3, 106},
-	 {3, 102},
-	 {3, 95} },		/* 2.4 GHz, lowest power */
-	{
-	 {251, 127},		/* 5.x GHz, highest power */
-	 {251, 120},
-	 {251, 114},
-	 {219, 119},
-	 {219, 101},
-	 {187, 113},
-	 {187, 102},
-	 {155, 114},
-	 {155, 103},
-	 {123, 117},
-	 {123, 107},
-	 {123, 99},
-	 {123, 92},
-	 {91, 108},
-	 {59, 125},
-	 {59, 118},
-	 {59, 109},
-	 {59, 102},
-	 {59, 96},
-	 {59, 90},
-	 {27, 104},
-	 {27, 98},
-	 {27, 92},
-	 {115, 118},
-	 {115, 111},
-	 {115, 104},
-	 {83, 126},
-	 {83, 121},
-	 {83, 113},
-	 {83, 105},
-	 {83, 99},
-	 {51, 118},
-	 {51, 111},
-	 {51, 104},
-	 {51, 98},
-	 {19, 116},
-	 {19, 109},
-	 {19, 102},
-	 {19, 98},
-	 {19, 93},
-	 {171, 113},
-	 {171, 107},
-	 {171, 99},
-	 {139, 120},
-	 {139, 113},
-	 {139, 107},
-	 {139, 99},
-	 {107, 120},
-	 {107, 113},
-	 {107, 107},
-	 {107, 99},
-	 {75, 120},
-	 {75, 113},
-	 {75, 107},
-	 {75, 99},
-	 {43, 120},
-	 {43, 113},
-	 {43, 107},
-	 {43, 99},
-	 {11, 120},
-	 {11, 113},
-	 {11, 107},
-	 {11, 99},
-	 {131, 107},
-	 {131, 99},
-	 {99, 120},
-	 {99, 113},
-	 {99, 107},
-	 {99, 99},
-	 {67, 120},
-	 {67, 113},
-	 {67, 107},
-	 {67, 99},
-	 {35, 120},
-	 {35, 113},
-	 {35, 107},
-	 {35, 99},
-	 {3, 120} }		/* 5.x GHz, lowest power */
-};
-
-static inline u8 iwl3945_hw_reg_fix_power_index(int index)
-{
-	if (index < 0)
-		return 0;
-	if (index >= IWL_MAX_GAIN_ENTRIES)
-		return IWL_MAX_GAIN_ENTRIES - 1;
-	return (u8) index;
-}
-
-/* Kick off thermal recalibration check every 60 seconds */
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl3945_hw_reg_set_scan_power - Set Tx power for scan probe requests
- *
- * Set (in our channel info database) the direct scan Tx power for 1 Mbit (CCK)
- * or 6 Mbit (OFDM) rates.
- */
-static void iwl3945_hw_reg_set_scan_power(struct iwl_priv *priv, u32 scan_tbl_index,
-			       s32 rate_index, const s8 *clip_pwrs,
-			       struct iwl_channel_info *ch_info,
-			       int band_index)
-{
-	struct iwl3945_scan_power_info *scan_power_info;
-	s8 power;
-	u8 power_index;
-
-	scan_power_info = &ch_info->scan_pwr_info[scan_tbl_index];
-
-	/* use this channel group's 6Mbit clipping/saturation pwr,
-	 *   but cap at regulatory scan power restriction (set during init
-	 *   based on eeprom channel data) for this channel.  */
-	power = min(ch_info->scan_power, clip_pwrs[IWL_RATE_6M_INDEX_TABLE]);
-
-	/* further limit to user's max power preference.
-	 * FIXME:  Other spectrum management power limitations do not
-	 *   seem to apply?? */
-	power = min(power, priv->tx_power_user_lmt);
-	scan_power_info->requested_power = power;
-
-	/* find difference between new scan *power* and current "normal"
-	 *   Tx *power* for 6Mb.  Use this difference (x2) to adjust the
-	 *   current "normal" temperature-compensated Tx power *index* for
-	 *   this rate (1Mb or 6Mb) to yield new temp-compensated scan power
-	 *   *index*. */
-	power_index = ch_info->power_info[rate_index].power_table_index
-	    - (power - ch_info->power_info
-	       [IWL_RATE_6M_INDEX_TABLE].requested_power) * 2;
-
-	/* store reference index that we use when adjusting *all* scan
-	 *   powers.  So we can accommodate user (all channel) or spectrum
-	 *   management (single channel) power changes "between" temperature
-	 *   feedback compensation procedures.
-	 * don't force fit this reference index into gain table; it may be a
-	 *   negative number.  This will help avoid errors when we're at
-	 *   the lower bounds (highest gains, for warmest temperatures)
-	 *   of the table. */
-
-	/* don't exceed table bounds for "real" setting */
-	power_index = iwl3945_hw_reg_fix_power_index(power_index);
-
-	scan_power_info->power_table_index = power_index;
-	scan_power_info->tpc.tx_gain =
-	    power_gain_table[band_index][power_index].tx_gain;
-	scan_power_info->tpc.dsp_atten =
-	    power_gain_table[band_index][power_index].dsp_atten;
-}
-
-/**
- * iwl3945_send_tx_power - fill in Tx Power command with gain settings
- *
- * Configures power settings for all rates for the current channel,
- * using values from channel info struct, and send to NIC
- */
-static int iwl3945_send_tx_power(struct iwl_priv *priv)
-{
-	int rate_idx, i;
-	const struct iwl_channel_info *ch_info = NULL;
-	struct iwl3945_txpowertable_cmd txpower = {
-		.channel = priv->contexts[IWL_RXON_CTX_BSS].active.channel,
-	};
-	u16 chan;
-
-	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
-		      "TX Power requested while scanning!\n"))
-		return -EAGAIN;
-
-	chan = le16_to_cpu(priv->contexts[IWL_RXON_CTX_BSS].active.channel);
-
-	txpower.band = (priv->band == IEEE80211_BAND_5GHZ) ? 0 : 1;
-	ch_info = iwl_get_channel_info(priv, priv->band, chan);
-	if (!ch_info) {
-		IWL_ERR(priv,
-			"Failed to get channel info for channel %d [%d]\n",
-			chan, priv->band);
-		return -EINVAL;
-	}
-
-	if (!is_channel_valid(ch_info)) {
-		IWL_DEBUG_POWER(priv, "Not calling TX_PWR_TABLE_CMD on "
-				"non-Tx channel.\n");
-		return 0;
-	}
-
-	/* fill cmd with power settings for all rates for current channel */
-	/* Fill OFDM rate */
-	for (rate_idx = IWL_FIRST_OFDM_RATE, i = 0;
-	     rate_idx <= IWL39_LAST_OFDM_RATE; rate_idx++, i++) {
-
-		txpower.power[i].tpc = ch_info->power_info[i].tpc;
-		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
-
-		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
-				le16_to_cpu(txpower.channel),
-				txpower.band,
-				txpower.power[i].tpc.tx_gain,
-				txpower.power[i].tpc.dsp_atten,
-				txpower.power[i].rate);
-	}
-	/* Fill CCK rates */
-	for (rate_idx = IWL_FIRST_CCK_RATE;
-	     rate_idx <= IWL_LAST_CCK_RATE; rate_idx++, i++) {
-		txpower.power[i].tpc = ch_info->power_info[i].tpc;
-		txpower.power[i].rate = iwl3945_rates[rate_idx].plcp;
-
-		IWL_DEBUG_POWER(priv, "ch %d:%d rf %d dsp %3d rate code 0x%02x\n",
-				le16_to_cpu(txpower.channel),
-				txpower.band,
-				txpower.power[i].tpc.tx_gain,
-				txpower.power[i].tpc.dsp_atten,
-				txpower.power[i].rate);
-	}
-
-	return iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD,
-				sizeof(struct iwl3945_txpowertable_cmd),
-				&txpower);
-
-}
-
-/**
- * iwl3945_hw_reg_set_new_power - Configures power tables at new levels
- * @ch_info: Channel to update.  Uses power_info.requested_power.
- *
- * Replace requested_power and base_power_index ch_info fields for
- * one channel.
- *
- * Called if user or spectrum management changes power preferences.
- * Takes into account h/w and modulation limitations (clip power).
- *
- * This does *not* send anything to NIC, just sets up ch_info for one channel.
- *
- * NOTE: reg_compensate_for_temperature_dif() *must* be run after this to
- *	 properly fill out the scan powers, and actual h/w gain settings,
- *	 and send changes to NIC
- */
-static int iwl3945_hw_reg_set_new_power(struct iwl_priv *priv,
-			     struct iwl_channel_info *ch_info)
-{
-	struct iwl3945_channel_power_info *power_info;
-	int power_changed = 0;
-	int i;
-	const s8 *clip_pwrs;
-	int power;
-
-	/* Get this chnlgrp's rate-to-max/clip-powers table */
-	clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-	/* Get this channel's rate-to-current-power settings table */
-	power_info = ch_info->power_info;
-
-	/* update OFDM Txpower settings */
-	for (i = IWL_RATE_6M_INDEX_TABLE; i <= IWL_RATE_54M_INDEX_TABLE;
-	     i++, ++power_info) {
-		int delta_idx;
-
-		/* limit new power to be no more than h/w capability */
-		power = min(ch_info->curr_txpow, clip_pwrs[i]);
-		if (power == power_info->requested_power)
-			continue;
-
-		/* find difference between old and new requested powers,
-		 *    update base (non-temp-compensated) power index */
-		delta_idx = (power - power_info->requested_power) * 2;
-		power_info->base_power_index -= delta_idx;
-
-		/* save new requested power value */
-		power_info->requested_power = power;
-
-		power_changed = 1;
-	}
-
-	/* update CCK Txpower settings, based on OFDM 12M setting ...
-	 *    ... all CCK power settings for a given channel are the *same*. */
-	if (power_changed) {
-		power =
-		    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
-		    requested_power + IWL_CCK_FROM_OFDM_POWER_DIFF;
-
-		/* do all CCK rates' iwl3945_channel_power_info structures */
-		for (i = IWL_RATE_1M_INDEX_TABLE; i <= IWL_RATE_11M_INDEX_TABLE; i++) {
-			power_info->requested_power = power;
-			power_info->base_power_index =
-			    ch_info->power_info[IWL_RATE_12M_INDEX_TABLE].
-			    base_power_index + IWL_CCK_FROM_OFDM_INDEX_DIFF;
-			++power_info;
-		}
-	}
-
-	return 0;
-}
-
-/**
- * iwl3945_hw_reg_get_ch_txpower_limit - returns new power limit for channel
- *
- * NOTE: Returned power limit may be less (but not more) than requested,
- *	 based strictly on regulatory (eeprom and spectrum mgt) limitations
- *	 (no consideration for h/w clipping limitations).
- */
-static int iwl3945_hw_reg_get_ch_txpower_limit(struct iwl_channel_info *ch_info)
-{
-	s8 max_power;
-
-#if 0
-	/* if we're using TGd limits, use lower of TGd or EEPROM */
-	if (ch_info->tgd_data.max_power != 0)
-		max_power = min(ch_info->tgd_data.max_power,
-				ch_info->eeprom.max_power_avg);
-
-	/* else just use EEPROM limits */
-	else
-#endif
-		max_power = ch_info->eeprom.max_power_avg;
-
-	return min(max_power, ch_info->max_power_avg);
-}
-
-/**
- * iwl3945_hw_reg_comp_txpower_temp - Compensate for temperature
- *
- * Compensate txpower settings of *all* channels for temperature.
- * This only accounts for the difference between current temperature
- *   and the factory calibration temperatures, and bases the new settings
- *   on the channel's base_power_index.
- *
- * If RxOn is "associated", this sends the new Txpower to NIC!
- */
-static int iwl3945_hw_reg_comp_txpower_temp(struct iwl_priv *priv)
-{
-	struct iwl_channel_info *ch_info = NULL;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	int delta_index;
-	const s8 *clip_pwrs; /* array of h/w max power levels for each rate */
-	u8 a_band;
-	u8 rate_index;
-	u8 scan_tbl_index;
-	u8 i;
-	int ref_temp;
-	int temperature = priv->temperature;
-
-	if (priv->disable_tx_power_cal ||
-	    test_bit(STATUS_SCANNING, &priv->status)) {
-		/* do not perform tx power calibration */
-		return 0;
-	}
-	/* set up new Tx power info for each and every channel, 2.4 and 5.x */
-	for (i = 0; i < priv->channel_count; i++) {
-		ch_info = &priv->channel_info[i];
-		a_band = is_channel_a_band(ch_info);
-
-		/* Get this chnlgrp's factory calibration temperature */
-		ref_temp = (s16)eeprom->groups[ch_info->group_index].
-		    temperature;
-
-		/* get power index adjustment based on current and factory
-		 * temps */
-		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-							      ref_temp);
-
-		/* set tx power value for all rates, OFDM and CCK */
-		for (rate_index = 0; rate_index < IWL_RATE_COUNT;
-		     rate_index++) {
-			int power_idx =
-			    ch_info->power_info[rate_index].base_power_index;
-
-			/* temperature compensate */
-			power_idx += delta_index;
-
-			/* stay within table range */
-			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
-			ch_info->power_info[rate_index].
-			    power_table_index = (u8) power_idx;
-			ch_info->power_info[rate_index].tpc =
-			    power_gain_table[a_band][power_idx];
-		}
-
-		/* Get this chnlgrp's rate-to-max/clip-powers table */
-		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
-		for (scan_tbl_index = 0;
-		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
-			s32 actual_index = (scan_tbl_index == 0) ?
-			    IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
-			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
-					   actual_index, clip_pwrs,
-					   ch_info, a_band);
-		}
-	}
-
-	/* send Txpower command for current channel to ucode */
-	return priv->cfg->ops->lib->send_tx_power(priv);
-}
-
-int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power)
-{
-	struct iwl_channel_info *ch_info;
-	s8 max_power;
-	u8 a_band;
-	u8 i;
-
-	if (priv->tx_power_user_lmt == power) {
-		IWL_DEBUG_POWER(priv, "Requested Tx power same as current "
-				"limit: %ddBm.\n", power);
-		return 0;
-	}
-
-	IWL_DEBUG_POWER(priv, "Setting upper limit clamp to %ddBm.\n", power);
-	priv->tx_power_user_lmt = power;
-
-	/* set up new Tx powers for each and every channel, 2.4 and 5.x */
-
-	for (i = 0; i < priv->channel_count; i++) {
-		ch_info = &priv->channel_info[i];
-		a_band = is_channel_a_band(ch_info);
-
-		/* find minimum power of all user and regulatory constraints
-		 *    (does not consider h/w clipping limitations) */
-		max_power = iwl3945_hw_reg_get_ch_txpower_limit(ch_info);
-		max_power = min(power, max_power);
-		if (max_power != ch_info->curr_txpow) {
-			ch_info->curr_txpow = max_power;
-
-			/* this considers the h/w clipping limitations */
-			iwl3945_hw_reg_set_new_power(priv, ch_info);
-		}
-	}
-
-	/* update txpower settings for all channels,
-	 *   send to NIC if associated. */
-	is_temp_calib_needed(priv);
-	iwl3945_hw_reg_comp_txpower_temp(priv);
-
-	return 0;
-}
-
-static int iwl3945_send_rxon_assoc(struct iwl_priv *priv,
-				   struct iwl_rxon_context *ctx)
-{
-	int rc = 0;
-	struct iwl_rx_packet *pkt;
-	struct iwl3945_rxon_assoc_cmd rxon_assoc;
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_RXON_ASSOC,
-		.len = sizeof(rxon_assoc),
-		.flags = CMD_WANT_SKB,
-		.data = &rxon_assoc,
-	};
-	const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
-	const struct iwl_rxon_cmd *rxon2 = &ctx->active;
-
-	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 = ctx->staging.flags;
-	rxon_assoc.filter_flags = ctx->staging.filter_flags;
-	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
-	rxon_assoc.reserved = 0;
-
-	rc = iwl_send_cmd_sync(priv, &cmd);
-	if (rc)
-		return rc;
-
-	pkt = (struct iwl_rx_packet *)cmd.reply_page;
-	if (pkt->hdr.flags & IWL_CMD_FAILED_MSK) {
-		IWL_ERR(priv, "Bad return from REPLY_RXON_ASSOC command\n");
-		rc = -EIO;
-	}
-
-	iwl_free_pages(priv, cmd.reply_page);
-
-	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.
- */
-int iwl3945_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl3945_rxon_cmd *active_rxon = (void *)&ctx->active;
-	struct iwl3945_rxon_cmd *staging_rxon = (void *)&ctx->staging;
-	int rc = 0;
-	bool new_assoc = !!(staging_rxon->filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return -EINVAL;
-
-	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, ctx);
-	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, &priv->contexts[IWL_RXON_CTX_BSS])) {
-		rc = iwl_send_rxon_assoc(priv,
-					 &priv->contexts[IWL_RXON_CTX_BSS]);
-		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, IWL_RXON_CTX_BSS) && 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->contexts[IWL_RXON_CTX_BSS].active);
-
-		/* 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_clear_ucode_stations(priv,
-					 &priv->contexts[IWL_RXON_CTX_BSS]);
-		iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
-	}
-
-	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, ctx, !iwl3945_mod_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));
-
-	if (!new_assoc) {
-		iwl_clear_ucode_stations(priv,
-					 &priv->contexts[IWL_RXON_CTX_BSS]);
-		iwl_restore_stations(priv, &priv->contexts[IWL_RXON_CTX_BSS]);
-	}
-
-	/* 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;
-	}
-
-	/* 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;
-}
-
-/**
- * iwl3945_reg_txpower_periodic -  called when time to check our temperature.
- *
- * -- reset periodic timer
- * -- see if temp has changed enough to warrant re-calibration ... if so:
- *     -- correct coeffs for temp (can reset temp timer)
- *     -- save this temp as "last",
- *     -- send new set of gain settings to NIC
- * NOTE:  This should continue working, even when we're not associated,
- *   so we can keep our internal table of scan powers current. */
-void iwl3945_reg_txpower_periodic(struct iwl_priv *priv)
-{
-	/* This will kick in the "brute force"
-	 * iwl3945_hw_reg_comp_txpower_temp() below */
-	if (!is_temp_calib_needed(priv))
-		goto reschedule;
-
-	/* Set up a new set of temp-adjusted TxPowers, send to NIC.
-	 * This is based *only* on current temperature,
-	 * ignoring any previous power measurements */
-	iwl3945_hw_reg_comp_txpower_temp(priv);
-
- reschedule:
-	queue_delayed_work(priv->workqueue,
-			   &priv->_3945.thermal_periodic, REG_RECALIB_PERIOD * HZ);
-}
-
-static void iwl3945_bg_reg_txpower_periodic(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-					     _3945.thermal_periodic.work);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-	iwl3945_reg_txpower_periodic(priv);
-	mutex_unlock(&priv->mutex);
-}
-
-/**
- * iwl3945_hw_reg_get_ch_grp_index - find the channel-group index (0-4)
- * 				   for the channel.
- *
- * This function is used when initializing channel-info structs.
- *
- * NOTE: These channel groups do *NOT* match the bands above!
- *	 These channel groups are based on factory-tested channels;
- *	 on A-band, EEPROM's "group frequency" entries represent the top
- *	 channel in each group 1-4.  Group 5 All B/G channels are in group 0.
- */
-static u16 iwl3945_hw_reg_get_ch_grp_index(struct iwl_priv *priv,
-				       const struct iwl_channel_info *ch_info)
-{
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	struct iwl3945_eeprom_txpower_group *ch_grp = &eeprom->groups[0];
-	u8 group;
-	u16 group_index = 0;	/* based on factory calib frequencies */
-	u8 grp_channel;
-
-	/* Find the group index for the channel ... don't use index 1(?) */
-	if (is_channel_a_band(ch_info)) {
-		for (group = 1; group < 5; group++) {
-			grp_channel = ch_grp[group].group_channel;
-			if (ch_info->channel <= grp_channel) {
-				group_index = group;
-				break;
-			}
-		}
-		/* group 4 has a few channels *above* its factory cal freq */
-		if (group == 5)
-			group_index = 4;
-	} else
-		group_index = 0;	/* 2.4 GHz, group 0 */
-
-	IWL_DEBUG_POWER(priv, "Chnl %d mapped to grp %d\n", ch_info->channel,
-			group_index);
-	return group_index;
-}
-
-/**
- * iwl3945_hw_reg_get_matched_power_index - Interpolate to get nominal index
- *
- * Interpolate to get nominal (i.e. at factory calibration temperature) index
- *   into radio/DSP gain settings table for requested power.
- */
-static int iwl3945_hw_reg_get_matched_power_index(struct iwl_priv *priv,
-				       s8 requested_power,
-				       s32 setting_index, s32 *new_index)
-{
-	const struct iwl3945_eeprom_txpower_group *chnl_grp = NULL;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	s32 index0, index1;
-	s32 power = 2 * requested_power;
-	s32 i;
-	const struct iwl3945_eeprom_txpower_sample *samples;
-	s32 gains0, gains1;
-	s32 res;
-	s32 denominator;
-
-	chnl_grp = &eeprom->groups[setting_index];
-	samples = chnl_grp->samples;
-	for (i = 0; i < 5; i++) {
-		if (power == samples[i].power) {
-			*new_index = samples[i].gain_index;
-			return 0;
-		}
-	}
-
-	if (power > samples[1].power) {
-		index0 = 0;
-		index1 = 1;
-	} else if (power > samples[2].power) {
-		index0 = 1;
-		index1 = 2;
-	} else if (power > samples[3].power) {
-		index0 = 2;
-		index1 = 3;
-	} else {
-		index0 = 3;
-		index1 = 4;
-	}
-
-	denominator = (s32) samples[index1].power - (s32) samples[index0].power;
-	if (denominator == 0)
-		return -EINVAL;
-	gains0 = (s32) samples[index0].gain_index * (1 << 19);
-	gains1 = (s32) samples[index1].gain_index * (1 << 19);
-	res = gains0 + (gains1 - gains0) *
-	    ((s32) power - (s32) samples[index0].power) / denominator +
-	    (1 << 18);
-	*new_index = res >> 19;
-	return 0;
-}
-
-static void iwl3945_hw_reg_init_channel_groups(struct iwl_priv *priv)
-{
-	u32 i;
-	s32 rate_index;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	const struct iwl3945_eeprom_txpower_group *group;
-
-	IWL_DEBUG_POWER(priv, "Initializing factory calib info from EEPROM\n");
-
-	for (i = 0; i < IWL_NUM_TX_CALIB_GROUPS; i++) {
-		s8 *clip_pwrs;	/* table of power levels for each rate */
-		s8 satur_pwr;	/* saturation power for each chnl group */
-		group = &eeprom->groups[i];
-
-		/* sanity check on factory saturation power value */
-		if (group->saturation_power < 40) {
-			IWL_WARN(priv, "Error: saturation power is %d, "
-				    "less than minimum expected 40\n",
-				    group->saturation_power);
-			return;
-		}
-
-		/*
-		 * Derive requested power levels for each rate, based on
-		 *   hardware capabilities (saturation power for band).
-		 * Basic value is 3dB down from saturation, with further
-		 *   power reductions for highest 3 data rates.  These
-		 *   backoffs provide headroom for high rate modulation
-		 *   power peaks, without too much distortion (clipping).
-		 */
-		/* we'll fill in this array with h/w max power levels */
-		clip_pwrs = (s8 *) priv->_3945.clip_groups[i].clip_powers;
-
-		/* divide factory saturation power by 2 to find -3dB level */
-		satur_pwr = (s8) (group->saturation_power >> 1);
-
-		/* fill in channel group's nominal powers for each rate */
-		for (rate_index = 0;
-		     rate_index < IWL_RATE_COUNT_3945; rate_index++, clip_pwrs++) {
-			switch (rate_index) {
-			case IWL_RATE_36M_INDEX_TABLE:
-				if (i == 0)	/* B/G */
-					*clip_pwrs = satur_pwr;
-				else	/* A */
-					*clip_pwrs = satur_pwr - 5;
-				break;
-			case IWL_RATE_48M_INDEX_TABLE:
-				if (i == 0)
-					*clip_pwrs = satur_pwr - 7;
-				else
-					*clip_pwrs = satur_pwr - 10;
-				break;
-			case IWL_RATE_54M_INDEX_TABLE:
-				if (i == 0)
-					*clip_pwrs = satur_pwr - 9;
-				else
-					*clip_pwrs = satur_pwr - 12;
-				break;
-			default:
-				*clip_pwrs = satur_pwr;
-				break;
-			}
-		}
-	}
-}
-
-/**
- * iwl3945_txpower_set_from_eeprom - Set channel power info based on EEPROM
- *
- * Second pass (during init) to set up priv->channel_info
- *
- * Set up Tx-power settings in our channel info database for each VALID
- * (for this geo/SKU) channel, at all Tx data rates, based on eeprom values
- * and current temperature.
- *
- * Since this is based on current temperature (at init time), these values may
- * not be valid for very long, but it gives us a starting/default point,
- * and allows us to active (i.e. using Tx) scan.
- *
- * This does *not* write values to NIC, just sets up our internal table.
- */
-int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv)
-{
-	struct iwl_channel_info *ch_info = NULL;
-	struct iwl3945_channel_power_info *pwr_info;
-	struct iwl3945_eeprom *eeprom = (struct iwl3945_eeprom *)priv->eeprom;
-	int delta_index;
-	u8 rate_index;
-	u8 scan_tbl_index;
-	const s8 *clip_pwrs;	/* array of power levels for each rate */
-	u8 gain, dsp_atten;
-	s8 power;
-	u8 pwr_index, base_pwr_index, a_band;
-	u8 i;
-	int temperature;
-
-	/* save temperature reference,
-	 *   so we can determine next time to calibrate */
-	temperature = iwl3945_hw_reg_txpower_get_temperature(priv);
-	priv->last_temperature = temperature;
-
-	iwl3945_hw_reg_init_channel_groups(priv);
-
-	/* initialize Tx power info for each and every channel, 2.4 and 5.x */
-	for (i = 0, ch_info = priv->channel_info; i < priv->channel_count;
-	     i++, ch_info++) {
-		a_band = is_channel_a_band(ch_info);
-		if (!is_channel_valid(ch_info))
-			continue;
-
-		/* find this channel's channel group (*not* "band") index */
-		ch_info->group_index =
-			iwl3945_hw_reg_get_ch_grp_index(priv, ch_info);
-
-		/* Get this chnlgrp's rate->max/clip-powers table */
-		clip_pwrs = priv->_3945.clip_groups[ch_info->group_index].clip_powers;
-
-		/* calculate power index *adjustment* value according to
-		 *  diff between current temperature and factory temperature */
-		delta_index = iwl3945_hw_reg_adjust_power_by_temp(temperature,
-				eeprom->groups[ch_info->group_index].
-				temperature);
-
-		IWL_DEBUG_POWER(priv, "Delta index for channel %d: %d [%d]\n",
-				ch_info->channel, delta_index, temperature +
-				IWL_TEMP_CONVERT);
-
-		/* set tx power value for all OFDM rates */
-		for (rate_index = 0; rate_index < IWL_OFDM_RATES;
-		     rate_index++) {
-			s32 uninitialized_var(power_idx);
-			int rc;
-
-			/* use channel group's clip-power table,
-			 *   but don't exceed channel's max power */
-			s8 pwr = min(ch_info->max_power_avg,
-				     clip_pwrs[rate_index]);
-
-			pwr_info = &ch_info->power_info[rate_index];
-
-			/* get base (i.e. at factory-measured temperature)
-			 *    power table index for this rate's power */
-			rc = iwl3945_hw_reg_get_matched_power_index(priv, pwr,
-							 ch_info->group_index,
-							 &power_idx);
-			if (rc) {
-				IWL_ERR(priv, "Invalid power index\n");
-				return rc;
-			}
-			pwr_info->base_power_index = (u8) power_idx;
-
-			/* temperature compensate */
-			power_idx += delta_index;
-
-			/* stay within range of gain table */
-			power_idx = iwl3945_hw_reg_fix_power_index(power_idx);
-
-			/* fill 1 OFDM rate's iwl3945_channel_power_info struct */
-			pwr_info->requested_power = pwr;
-			pwr_info->power_table_index = (u8) power_idx;
-			pwr_info->tpc.tx_gain =
-			    power_gain_table[a_band][power_idx].tx_gain;
-			pwr_info->tpc.dsp_atten =
-			    power_gain_table[a_band][power_idx].dsp_atten;
-		}
-
-		/* set tx power for CCK rates, based on OFDM 12 Mbit settings*/
-		pwr_info = &ch_info->power_info[IWL_RATE_12M_INDEX_TABLE];
-		power = pwr_info->requested_power +
-			IWL_CCK_FROM_OFDM_POWER_DIFF;
-		pwr_index = pwr_info->power_table_index +
-			IWL_CCK_FROM_OFDM_INDEX_DIFF;
-		base_pwr_index = pwr_info->base_power_index +
-			IWL_CCK_FROM_OFDM_INDEX_DIFF;
-
-		/* stay within table range */
-		pwr_index = iwl3945_hw_reg_fix_power_index(pwr_index);
-		gain = power_gain_table[a_band][pwr_index].tx_gain;
-		dsp_atten = power_gain_table[a_band][pwr_index].dsp_atten;
-
-		/* fill each CCK rate's iwl3945_channel_power_info structure
-		 * NOTE:  All CCK-rate Txpwrs are the same for a given chnl!
-		 * NOTE:  CCK rates start at end of OFDM rates! */
-		for (rate_index = 0;
-		     rate_index < IWL_CCK_RATES; rate_index++) {
-			pwr_info = &ch_info->power_info[rate_index+IWL_OFDM_RATES];
-			pwr_info->requested_power = power;
-			pwr_info->power_table_index = pwr_index;
-			pwr_info->base_power_index = base_pwr_index;
-			pwr_info->tpc.tx_gain = gain;
-			pwr_info->tpc.dsp_atten = dsp_atten;
-		}
-
-		/* set scan tx power, 1Mbit for CCK, 6Mbit for OFDM */
-		for (scan_tbl_index = 0;
-		     scan_tbl_index < IWL_NUM_SCAN_RATES; scan_tbl_index++) {
-			s32 actual_index = (scan_tbl_index == 0) ?
-				IWL_RATE_1M_INDEX_TABLE : IWL_RATE_6M_INDEX_TABLE;
-			iwl3945_hw_reg_set_scan_power(priv, scan_tbl_index,
-				actual_index, clip_pwrs, ch_info, a_band);
-		}
-	}
-
-	return 0;
-}
-
-int iwl3945_hw_rxq_stop(struct iwl_priv *priv)
-{
-	int rc;
-
-	iwl_write_direct32(priv, FH39_RCSR_CONFIG(0), 0);
-	rc = iwl_poll_direct_bit(priv, FH39_RSSR_STATUS,
-			FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE, 1000);
-	if (rc < 0)
-		IWL_ERR(priv, "Can't stop Rx DMA.\n");
-
-	return 0;
-}
-
-int iwl3945_hw_tx_queue_init(struct iwl_priv *priv, struct iwl_tx_queue *txq)
-{
-	int txq_id = txq->q.id;
-
-	struct iwl3945_shared *shared_data = priv->_3945.shared_virt;
-
-	shared_data->tx_base_ptr[txq_id] = cpu_to_le32((u32)txq->q.dma_addr);
-
-	iwl_write_direct32(priv, FH39_CBCC_CTRL(txq_id), 0);
-	iwl_write_direct32(priv, FH39_CBCC_BASE(txq_id), 0);
-
-	iwl_write_direct32(priv, FH39_TCSR_CONFIG(txq_id),
-		FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT |
-		FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF |
-		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);
-
-	/* fake read to flush all prev. writes */
-	iwl_read32(priv, FH39_TSSR_CBB_BASE);
-
-	return 0;
-}
-
-/*
- * HCMD utils
- */
-static u16 iwl3945_get_hcmd_size(u8 cmd_id, u16 len)
-{
-	switch (cmd_id) {
-	case REPLY_RXON:
-		return sizeof(struct iwl3945_rxon_cmd);
-	case POWER_TABLE_CMD:
-		return sizeof(struct iwl3945_powertable_cmd);
-	default:
-		return len;
-	}
-}
-
-
-static u16 iwl3945_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
-	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);
-}
-
-static int iwl3945_add_bssid_station(struct iwl_priv *priv,
-				     const u8 *addr, u8 *sta_id_r)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	int ret;
-	u8 sta_id;
-	unsigned long flags;
-
-	if (sta_id_r)
-		*sta_id_r = IWL_INVALID_STATION;
-
-	ret = iwl_add_station_common(priv, ctx, addr, 0, NULL, &sta_id);
-	if (ret) {
-		IWL_ERR(priv, "Unable to add station %pM\n", addr);
-		return ret;
-	}
-
-	if (sta_id_r)
-		*sta_id_r = sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	priv->stations[sta_id].used |= IWL_STA_LOCAL;
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-
-	return 0;
-}
-static int iwl3945_manage_ibss_station(struct iwl_priv *priv,
-				       struct ieee80211_vif *vif, bool add)
-{
-	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
-	int ret;
-
-	if (add) {
-		ret = iwl3945_add_bssid_station(priv, vif->bss_conf.bssid,
-						&vif_priv->ibss_bssid_sta_id);
-		if (ret)
-			return ret;
-
-		iwl3945_sync_sta(priv, vif_priv->ibss_bssid_sta_id,
-				 (priv->band == IEEE80211_BAND_5GHZ) ?
-				 IWL_RATE_6M_PLCP : IWL_RATE_1M_PLCP);
-		iwl3945_rate_scale_init(priv->hw, vif_priv->ibss_bssid_sta_id);
-
-		return 0;
-	}
-
-	return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
-				  vif->bss_conf.bssid);
-}
-
-/**
- * iwl3945_init_hw_rate_table - Initialize the hardware rate fallback table
- */
-int iwl3945_init_hw_rate_table(struct iwl_priv *priv)
-{
-	int rc, i, index, prev_index;
-	struct iwl3945_rate_scaling_cmd rate_cmd = {
-		.reserved = {0, 0, 0},
-	};
-	struct iwl3945_rate_scaling_info *table = rate_cmd.table;
-
-	for (i = 0; i < ARRAY_SIZE(iwl3945_rates); i++) {
-		index = iwl3945_rates[i].table_rs_index;
-
-		table[index].rate_n_flags =
-			iwl3945_hw_set_rate_n_flags(iwl3945_rates[i].plcp, 0);
-		table[index].try_cnt = priv->retry_rate;
-		prev_index = iwl3945_get_prev_ieee_rate(i);
-		table[index].next_rate_index =
-				iwl3945_rates[prev_index].table_rs_index;
-	}
-
-	switch (priv->band) {
-	case IEEE80211_BAND_5GHZ:
-		IWL_DEBUG_RATE(priv, "Select A mode rate scale\n");
-		/* If one of the following CCK rates is used,
-		 * have it fall back to the 6M OFDM rate */
-		for (i = IWL_RATE_1M_INDEX_TABLE;
-			i <= IWL_RATE_11M_INDEX_TABLE; i++)
-			table[i].next_rate_index =
-			  iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
-
-		/* Don't fall back to CCK rates */
-		table[IWL_RATE_12M_INDEX_TABLE].next_rate_index =
-						IWL_RATE_9M_INDEX_TABLE;
-
-		/* Don't drop out of OFDM rates */
-		table[IWL_RATE_6M_INDEX_TABLE].next_rate_index =
-		    iwl3945_rates[IWL_FIRST_OFDM_RATE].table_rs_index;
-		break;
-
-	case IEEE80211_BAND_2GHZ:
-		IWL_DEBUG_RATE(priv, "Select B/G mode rate scale\n");
-		/* If an OFDM rate is used, have it fall back to the
-		 * 1M CCK rates */
-
-		if (!(priv->_3945.sta_supp_rates & IWL_OFDM_RATES_MASK) &&
-		    iwl_is_associated(priv, IWL_RXON_CTX_BSS)) {
-
-			index = IWL_FIRST_CCK_RATE;
-			for (i = IWL_RATE_6M_INDEX_TABLE;
-			     i <= IWL_RATE_54M_INDEX_TABLE; i++)
-				table[i].next_rate_index =
-					iwl3945_rates[index].table_rs_index;
-
-			index = IWL_RATE_11M_INDEX_TABLE;
-			/* CCK shouldn't fall back to OFDM... */
-			table[index].next_rate_index = IWL_RATE_5M_INDEX_TABLE;
-		}
-		break;
-
-	default:
-		WARN_ON(1);
-		break;
-	}
-
-	/* Update the rate scaling for control frame Tx */
-	rate_cmd.table_id = 0;
-	rc = iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
-			      &rate_cmd);
-	if (rc)
-		return rc;
-
-	/* Update the rate scaling for data frame Tx */
-	rate_cmd.table_id = 1;
-	return iwl_send_cmd_pdu(priv, REPLY_RATE_SCALE, sizeof(rate_cmd),
-				&rate_cmd);
-}
-
-/* Called when initializing driver */
-int iwl3945_hw_set_hw_params(struct iwl_priv *priv)
-{
-	memset((void *)&priv->hw_params, 0,
-	       sizeof(struct iwl_hw_params));
-
-	priv->_3945.shared_virt =
-		dma_alloc_coherent(&priv->pci_dev->dev,
-				   sizeof(struct iwl3945_shared),
-				   &priv->_3945.shared_phys, GFP_KERNEL);
-	if (!priv->_3945.shared_virt) {
-		IWL_ERR(priv, "failed to allocate pci memory\n");
-		return -ENOMEM;
-	}
-
-	/* Assign number of Usable TX queues */
-	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-
-	priv->hw_params.tfd_size = sizeof(struct iwl3945_tfd);
-	priv->hw_params.rx_page_order = get_order(IWL_RX_BUF_SIZE_3K);
-	priv->hw_params.max_rxq_size = RX_QUEUE_SIZE;
-	priv->hw_params.max_rxq_log = RX_QUEUE_SIZE_LOG;
-	priv->hw_params.max_stations = IWL3945_STATION_COUNT;
-	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL3945_BROADCAST_ID;
-
-	priv->sta_key_max_num = STA_KEY_MAX_NUM;
-
-	priv->hw_params.rx_wrt_ptr_reg = FH39_RSCSR_CHNL0_WPTR;
-	priv->hw_params.max_beacon_itrvl = IWL39_MAX_UCODE_BEACON_INTERVAL;
-	priv->hw_params.beacon_time_tsf_bits = IWL3945_EXT_BEACON_TIME_POS;
-
-	return 0;
-}
-
-unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
-			  struct iwl3945_frame *frame, u8 rate)
-{
-	struct iwl3945_tx_beacon_cmd *tx_beacon_cmd;
-	unsigned int frame_size;
-
-	tx_beacon_cmd = (struct iwl3945_tx_beacon_cmd *)&frame->u;
-	memset(tx_beacon_cmd, 0, sizeof(*tx_beacon_cmd));
-
-	tx_beacon_cmd->tx.sta_id =
-		priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-	tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE;
-
-	frame_size = iwl3945_fill_beacon_frame(priv,
-				tx_beacon_cmd->frame,
-				sizeof(frame->u) - sizeof(*tx_beacon_cmd));
-
-	BUG_ON(frame_size > MAX_MPDU_SIZE);
-	tx_beacon_cmd->tx.len = cpu_to_le16((u16)frame_size);
-
-	tx_beacon_cmd->tx.rate = rate;
-	tx_beacon_cmd->tx.tx_flags = (TX_CMD_FLG_SEQ_CTL_MSK |
-				      TX_CMD_FLG_TSF_MSK);
-
-	/* supp_rates[0] == OFDM start at IWL_FIRST_OFDM_RATE*/
-	tx_beacon_cmd->tx.supp_rates[0] =
-		(IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
-
-	tx_beacon_cmd->tx.supp_rates[1] =
-		(IWL_CCK_BASIC_RATES_MASK & 0xF);
-
-	return sizeof(struct iwl3945_tx_beacon_cmd) + frame_size;
-}
-
-void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv)
-{
-	priv->rx_handlers[REPLY_TX] = iwl3945_rx_reply_tx;
-	priv->rx_handlers[REPLY_3945_RX] = iwl3945_rx_reply_rx;
-}
-
-void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv)
-{
-	INIT_DELAYED_WORK(&priv->_3945.thermal_periodic,
-			  iwl3945_bg_reg_txpower_periodic);
-}
-
-void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv)
-{
-	cancel_delayed_work(&priv->_3945.thermal_periodic);
-}
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl3945_verify_bsm(struct iwl_priv *priv)
- {
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	u32 reg;
-	u32 val;
-
-	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
-
-	/* verify BSM SRAM contents */
-	val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
-	for (reg = BSM_SRAM_LOWER_BOUND;
-	     reg < BSM_SRAM_LOWER_BOUND + len;
-	     reg += sizeof(u32), image++) {
-		val = iwl_read_prph(priv, reg);
-		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(priv, "BSM uCode verification failed at "
-				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-				  BSM_SRAM_LOWER_BOUND,
-				  reg - BSM_SRAM_LOWER_BOUND, len,
-				  val, le32_to_cpu(*image));
-			return -EIO;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
-
-	return 0;
-}
-
-
-/******************************************************************************
- *
- * EEPROM related functions
- *
- ******************************************************************************/
-
-/*
- * Clear the OWNER_MSK, to establish driver (instead of uCode running on
- * embedded controller) as EEPROM reader; each read is a series of pulses
- * to/from the EEPROM chip, not a single event, so even reads could conflict
- * if they weren't arbitrated by some ownership mechanism.  Here, the driver
- * simply claims ownership, which should be safe when this function is called
- * (i.e. before loading uCode!).
- */
-static int iwl3945_eeprom_acquire_semaphore(struct iwl_priv *priv)
-{
-	_iwl_clear_bit(priv, CSR_EEPROM_GP, CSR_EEPROM_GP_IF_OWNER_MSK);
-	return 0;
-}
-
-
-static void iwl3945_eeprom_release_semaphore(struct iwl_priv *priv)
-{
-	return;
-}
-
- /**
-  * iwl3945_load_bsm - Load bootstrap instructions
-  *
-  * BSM operation:
-  *
-  * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
-  * in special SRAM that does not power down during RFKILL.  When powering back
-  * up after power-saving sleeps (or during initial uCode load), the BSM loads
-  * the bootstrap program into the on-board processor, and starts it.
-  *
-  * The bootstrap program loads (via DMA) instructions and data for a new
-  * program from host DRAM locations indicated by the host driver in the
-  * BSM_DRAM_* registers.  Once the new program is loaded, it starts
-  * automatically.
-  *
-  * When initializing the NIC, the host driver points the BSM to the
-  * "initialize" uCode image.  This uCode sets up some internal data, then
-  * notifies host via "initialize alive" that it is complete.
-  *
-  * The host then replaces the BSM_DRAM_* pointer values to point to the
-  * normal runtime uCode instructions and a backup uCode data cache buffer
-  * (filled initially with starting data values for the on-board processor),
-  * then triggers the "initialize" uCode to load and launch the runtime uCode,
-  * which begins normal operation.
-  *
-  * When doing a power-save shutdown, runtime uCode saves data SRAM into
-  * the backup data cache in DRAM before SRAM is powered down.
-  *
-  * When powering back up, the BSM loads the bootstrap program.  This reloads
-  * the runtime uCode instructions and the backup data cache into SRAM,
-  * and re-launches the runtime uCode from where it left off.
-  */
-static int iwl3945_load_bsm(struct iwl_priv *priv)
-{
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-	u32 inst_len;
-	u32 data_len;
-	int rc;
-	int i;
-	u32 done;
-	u32 reg_offset;
-
-	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
-
-	/* make sure bootstrap program is no larger than BSM's SRAM size */
-	if (len > IWL39_MAX_BSM_SIZE)
-		return -EINVAL;
-
-	/* Tell bootstrap uCode where to find the "Initialize" uCode
-	*   in host DRAM ... host DRAM physical address bits 31:0 for 3945.
-	* NOTE:  iwl3945_initialize_alive_start() will replace these values,
-	*        after the "initialize" uCode has run, to point to
-	*        runtime/protocol instructions and backup data cache. */
-	pinst = priv->ucode_init.p_addr;
-	pdata = priv->ucode_init_data.p_addr;
-	inst_len = priv->ucode_init.len;
-	data_len = priv->ucode_init_data.len;
-
-	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);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-
-	/* Fill BSM memory with bootstrap instructions */
-	for (reg_offset = BSM_SRAM_LOWER_BOUND;
-	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
-	     reg_offset += sizeof(u32), image++)
-		_iwl_write_prph(priv, reg_offset,
-					  le32_to_cpu(*image));
-
-	rc = iwl3945_verify_bsm(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);
-	iwl_write_prph(priv, BSM_WR_MEM_DST_REG,
-				 IWL39_RTC_INST_LOWER_BOUND);
-	iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-	/* Load bootstrap code into instruction SRAM now,
-	 *   to prepare to load "initialize" uCode */
-	iwl_write_prph(priv, BSM_WR_CTRL_REG,
-		BSM_WR_CTRL_REG_BIT_START);
-
-	/* Wait for load of bootstrap uCode to finish */
-	for (i = 0; i < 100; i++) {
-		done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
-		if (!(done & BSM_WR_CTRL_REG_BIT_START))
-			break;
-		udelay(10);
-	}
-	if (i < 100)
-		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
-	else {
-		IWL_ERR(priv, "BSM write did not complete!\n");
-		return -EIO;
-	}
-
-	/* Enable future boot loads whenever power management unit triggers it
-	 *   (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);
-
-	return 0;
-}
-
-static struct iwl_hcmd_ops iwl3945_hcmd = {
-	.rxon_assoc = iwl3945_send_rxon_assoc,
-	.commit_rxon = iwl3945_commit_rxon,
-	.send_bt_config = iwl_send_bt_config,
-};
-
-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,
-	.txq_init = iwl3945_hw_tx_queue_init,
-	.load_ucode = iwl3945_load_bsm,
-	.dump_nic_event_log = iwl3945_dump_nic_event_log,
-	.dump_nic_error_log = iwl3945_dump_nic_error_log,
-	.apm_ops = {
-		.init = iwl3945_apm_init,
-		.config = iwl3945_nic_config,
-	},
-	.eeprom_ops = {
-		.regulatory_bands = {
-			EEPROM_REGULATORY_BAND_1_CHANNELS,
-			EEPROM_REGULATORY_BAND_2_CHANNELS,
-			EEPROM_REGULATORY_BAND_3_CHANNELS,
-			EEPROM_REGULATORY_BAND_4_CHANNELS,
-			EEPROM_REGULATORY_BAND_5_CHANNELS,
-			EEPROM_REGULATORY_BAND_NO_HT40,
-			EEPROM_REGULATORY_BAND_NO_HT40,
-		},
-		.acquire_semaphore = iwl3945_eeprom_acquire_semaphore,
-		.release_semaphore = iwl3945_eeprom_release_semaphore,
-		.query_addr = iwlcore_eeprom_query_addr,
-	},
-	.send_tx_power	= iwl3945_send_tx_power,
-	.is_valid_rtc_data_addr = iwl3945_hw_valid_rtc_data_addr,
-	.isr_ops = {
-		.isr = iwl_isr_legacy,
-	},
-
-	.debugfs_ops = {
-		.rx_stats_read = iwl3945_ucode_rx_stats_read,
-		.tx_stats_read = iwl3945_ucode_tx_stats_read,
-		.general_stats_read = iwl3945_ucode_general_stats_read,
-	},
-};
-
-static const struct iwl_legacy_ops iwl3945_legacy_ops = {
-	.post_associate = iwl3945_post_associate,
-	.config_ap = iwl3945_config_ap,
-	.manage_ibss_station = iwl3945_manage_ibss_station,
-};
-
-static struct iwl_hcmd_utils_ops iwl3945_hcmd_utils = {
-	.get_hcmd_size = iwl3945_get_hcmd_size,
-	.build_addsta_hcmd = iwl3945_build_addsta_hcmd,
-	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
-	.request_scan = iwl3945_request_scan,
-	.post_scan = iwl3945_post_scan,
-};
-
-static const struct iwl_ops iwl3945_ops = {
-	.lib = &iwl3945_lib,
-	.hcmd = &iwl3945_hcmd,
-	.utils = &iwl3945_hcmd_utils,
-	.led = &iwl3945_led_ops,
-	.legacy = &iwl3945_legacy_ops,
-	.ieee80211_ops = &iwl3945_hw_ops,
-};
-
-static struct iwl_base_params iwl3945_base_params = {
-	.eeprom_size = IWL3945_EEPROM_IMG_SIZE,
-	.num_of_queues = IWL39_NUM_QUEUES,
-	.pll_cfg_val = CSR39_ANA_PLL_CFG_VAL,
-	.set_l0s = false,
-	.use_bsm = true,
-	.use_isr_legacy = true,
-	.led_compensation = 64,
-	.broken_powersave = true,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_LONG_THRESHOLD_DEF,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.max_event_log_size = 512,
-	.tx_power_by_driver = true,
-};
-
-static struct iwl_cfg iwl3945_bg_cfg = {
-	.name = "3945BG",
-	.fw_name_pre = IWL3945_FW_PRE,
-	.ucode_api_max = IWL3945_UCODE_API_MAX,
-	.ucode_api_min = IWL3945_UCODE_API_MIN,
-	.sku = IWL_SKU_G,
-	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-	.ops = &iwl3945_ops,
-	.mod_params = &iwl3945_mod_params,
-	.base_params = &iwl3945_base_params,
-	.led_mode = IWL_LED_BLINK,
-};
-
-static struct iwl_cfg iwl3945_abg_cfg = {
-	.name = "3945ABG",
-	.fw_name_pre = IWL3945_FW_PRE,
-	.ucode_api_max = IWL3945_UCODE_API_MAX,
-	.ucode_api_min = IWL3945_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G,
-	.eeprom_ver = EEPROM_3945_EEPROM_VERSION,
-	.ops = &iwl3945_ops,
-	.mod_params = &iwl3945_mod_params,
-	.base_params = &iwl3945_base_params,
-	.led_mode = IWL_LED_BLINK,
-};
-
-DEFINE_PCI_DEVICE_TABLE(iwl3945_hw_card_ids) = {
-	{IWL_PCI_DEVICE(0x4222, 0x1005, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4222, 0x1034, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4222, 0x1044, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4227, 0x1014, iwl3945_bg_cfg)},
-	{IWL_PCI_DEVICE(0x4222, PCI_ANY_ID, iwl3945_abg_cfg)},
-	{IWL_PCI_DEVICE(0x4227, PCI_ANY_ID, iwl3945_abg_cfg)},
-	{0}
-};
-
-MODULE_DEVICE_TABLE(pci, iwl3945_hw_card_ids);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,522 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-3945-debugfs.h"
-
-
-static int iwl3945_statistics_flag(struct iwl_priv *priv, char *buf, int bufsz)
-{
-	int p = 0;
-
-	p += scnprintf(buf + p, bufsz - p, "Statistics Flag(0x%X):\n",
-		       le32_to_cpu(priv->_3945.statistics.flag));
-	if (le32_to_cpu(priv->_3945.statistics.flag) &
-			UCODE_STATISTICS_CLEAR_MSK)
-		p += scnprintf(buf + p, bufsz - p,
-			       "\tStatistics have been cleared\n");
-	p += scnprintf(buf + p, bufsz - p, "\tOperational Frequency: %s\n",
-		       (le32_to_cpu(priv->_3945.statistics.flag) &
-			UCODE_STATISTICS_FREQUENCY_MSK)
-			? "2.4 GHz" : "5.2 GHz");
-	p += scnprintf(buf + p, bufsz - p, "\tTGj Narrow Band: %s\n",
-		       (le32_to_cpu(priv->_3945.statistics.flag) &
-			UCODE_STATISTICS_NARROW_BAND_MSK)
-			? "enabled" : "disabled");
-	return p;
-}
-
-ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
-				    char __user *user_buf,
-				    size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char *buf;
-	int bufsz = sizeof(struct iwl39_statistics_rx_phy) * 40 +
-		    sizeof(struct iwl39_statistics_rx_non_phy) * 40 + 400;
-	ssize_t ret;
-	struct iwl39_statistics_rx_phy *ofdm, *accum_ofdm, *delta_ofdm, *max_ofdm;
-	struct iwl39_statistics_rx_phy *cck, *accum_cck, *delta_cck, *max_cck;
-	struct iwl39_statistics_rx_non_phy *general, *accum_general;
-	struct iwl39_statistics_rx_non_phy *delta_general, *max_general;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf) {
-		IWL_ERR(priv, "Can not allocate Buffer\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The statistic information display here is based on
-	 * the last statistics notification from uCode
-	 * might not reflect the current uCode activity
-	 */
-	ofdm = &priv->_3945.statistics.rx.ofdm;
-	cck = &priv->_3945.statistics.rx.cck;
-	general = &priv->_3945.statistics.rx.general;
-	accum_ofdm = &priv->_3945.accum_statistics.rx.ofdm;
-	accum_cck = &priv->_3945.accum_statistics.rx.cck;
-	accum_general = &priv->_3945.accum_statistics.rx.general;
-	delta_ofdm = &priv->_3945.delta_statistics.rx.ofdm;
-	delta_cck = &priv->_3945.delta_statistics.rx.cck;
-	delta_general = &priv->_3945.delta_statistics.rx.general;
-	max_ofdm = &priv->_3945.max_delta.rx.ofdm;
-	max_cck = &priv->_3945.max_delta.rx.cck;
-	max_general = &priv->_3945.max_delta.rx.general;
-
-	pos += iwl3945_statistics_flag(priv, buf, bufsz);
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - OFDM:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ina_cnt:", le32_to_cpu(ofdm->ina_cnt),
-			 accum_ofdm->ina_cnt,
-			 delta_ofdm->ina_cnt, max_ofdm->ina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_cnt:",
-			 le32_to_cpu(ofdm->fina_cnt), accum_ofdm->fina_cnt,
-			 delta_ofdm->fina_cnt, max_ofdm->fina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "plcp_err:",
-			 le32_to_cpu(ofdm->plcp_err), accum_ofdm->plcp_err,
-			 delta_ofdm->plcp_err, max_ofdm->plcp_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",  "crc32_err:",
-			 le32_to_cpu(ofdm->crc32_err), accum_ofdm->crc32_err,
-			 delta_ofdm->crc32_err, max_ofdm->crc32_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "overrun_err:",
-			 le32_to_cpu(ofdm->overrun_err),
-			 accum_ofdm->overrun_err, delta_ofdm->overrun_err,
-			 max_ofdm->overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
-			 le32_to_cpu(ofdm->early_overrun_err),
-			 accum_ofdm->early_overrun_err,
-			 delta_ofdm->early_overrun_err,
-			 max_ofdm->early_overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:", le32_to_cpu(ofdm->crc32_good),
-			 accum_ofdm->crc32_good, delta_ofdm->crc32_good,
-			 max_ofdm->crc32_good);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n", "false_alarm_cnt:",
-			 le32_to_cpu(ofdm->false_alarm_cnt),
-			 accum_ofdm->false_alarm_cnt,
-			 delta_ofdm->false_alarm_cnt,
-			 max_ofdm->false_alarm_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_sync_err_cnt:",
-			 le32_to_cpu(ofdm->fina_sync_err_cnt),
-			 accum_ofdm->fina_sync_err_cnt,
-			 delta_ofdm->fina_sync_err_cnt,
-			 max_ofdm->fina_sync_err_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sfd_timeout:",
-			 le32_to_cpu(ofdm->sfd_timeout),
-			 accum_ofdm->sfd_timeout,
-			 delta_ofdm->sfd_timeout,
-			 max_ofdm->sfd_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_timeout:",
-			 le32_to_cpu(ofdm->fina_timeout),
-			 accum_ofdm->fina_timeout,
-			 delta_ofdm->fina_timeout,
-			 max_ofdm->fina_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unresponded_rts:",
-			 le32_to_cpu(ofdm->unresponded_rts),
-			 accum_ofdm->unresponded_rts,
-			 delta_ofdm->unresponded_rts,
-			 max_ofdm->unresponded_rts);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rxe_frame_lmt_ovrun:",
-			 le32_to_cpu(ofdm->rxe_frame_limit_overrun),
-			 accum_ofdm->rxe_frame_limit_overrun,
-			 delta_ofdm->rxe_frame_limit_overrun,
-			 max_ofdm->rxe_frame_limit_overrun);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_ack_cnt:",
-			 le32_to_cpu(ofdm->sent_ack_cnt),
-			 accum_ofdm->sent_ack_cnt,
-			 delta_ofdm->sent_ack_cnt,
-			 max_ofdm->sent_ack_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_cts_cnt:",
-			 le32_to_cpu(ofdm->sent_cts_cnt),
-			 accum_ofdm->sent_cts_cnt,
-			 delta_ofdm->sent_cts_cnt, max_ofdm->sent_cts_cnt);
-
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - CCK:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ina_cnt:",
-			 le32_to_cpu(cck->ina_cnt), accum_cck->ina_cnt,
-			 delta_cck->ina_cnt, max_cck->ina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_cnt:",
-			 le32_to_cpu(cck->fina_cnt), accum_cck->fina_cnt,
-			 delta_cck->fina_cnt, max_cck->fina_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "plcp_err:",
-			 le32_to_cpu(cck->plcp_err), accum_cck->plcp_err,
-			 delta_cck->plcp_err, max_cck->plcp_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_err:",
-			 le32_to_cpu(cck->crc32_err), accum_cck->crc32_err,
-			 delta_cck->crc32_err, max_cck->crc32_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "overrun_err:",
-			 le32_to_cpu(cck->overrun_err),
-			 accum_cck->overrun_err,
-			 delta_cck->overrun_err, max_cck->overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "early_overrun_err:",
-			 le32_to_cpu(cck->early_overrun_err),
-			 accum_cck->early_overrun_err,
-			 delta_cck->early_overrun_err,
-			 max_cck->early_overrun_err);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "crc32_good:",
-			 le32_to_cpu(cck->crc32_good), accum_cck->crc32_good,
-			 delta_cck->crc32_good,
-			 max_cck->crc32_good);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "false_alarm_cnt:",
-			 le32_to_cpu(cck->false_alarm_cnt),
-			 accum_cck->false_alarm_cnt,
-			 delta_cck->false_alarm_cnt, max_cck->false_alarm_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_sync_err_cnt:",
-			 le32_to_cpu(cck->fina_sync_err_cnt),
-			 accum_cck->fina_sync_err_cnt,
-			 delta_cck->fina_sync_err_cnt,
-			 max_cck->fina_sync_err_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sfd_timeout:",
-			 le32_to_cpu(cck->sfd_timeout),
-			 accum_cck->sfd_timeout,
-			 delta_cck->sfd_timeout, max_cck->sfd_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "fina_timeout:",
-			 le32_to_cpu(cck->fina_timeout),
-			 accum_cck->fina_timeout,
-			 delta_cck->fina_timeout, max_cck->fina_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "unresponded_rts:",
-			 le32_to_cpu(cck->unresponded_rts),
-			 accum_cck->unresponded_rts,
-			 delta_cck->unresponded_rts,
-			 max_cck->unresponded_rts);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rxe_frame_lmt_ovrun:",
-			 le32_to_cpu(cck->rxe_frame_limit_overrun),
-			 accum_cck->rxe_frame_limit_overrun,
-			 delta_cck->rxe_frame_limit_overrun,
-			 max_cck->rxe_frame_limit_overrun);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_ack_cnt:",
-			 le32_to_cpu(cck->sent_ack_cnt),
-			 accum_cck->sent_ack_cnt,
-			 delta_cck->sent_ack_cnt,
-			 max_cck->sent_ack_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sent_cts_cnt:",
-			 le32_to_cpu(cck->sent_cts_cnt),
-			 accum_cck->sent_cts_cnt,
-			 delta_cck->sent_cts_cnt,
-			 max_cck->sent_cts_cnt);
-
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Rx - GENERAL:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bogus_cts:",
-			 le32_to_cpu(general->bogus_cts),
-			 accum_general->bogus_cts,
-			 delta_general->bogus_cts, max_general->bogus_cts);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bogus_ack:",
-			 le32_to_cpu(general->bogus_ack),
-			 accum_general->bogus_ack,
-			 delta_general->bogus_ack, max_general->bogus_ack);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "non_bssid_frames:",
-			 le32_to_cpu(general->non_bssid_frames),
-			 accum_general->non_bssid_frames,
-			 delta_general->non_bssid_frames,
-			 max_general->non_bssid_frames);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "filtered_frames:",
-			 le32_to_cpu(general->filtered_frames),
-			 accum_general->filtered_frames,
-			 delta_general->filtered_frames,
-			 max_general->filtered_frames);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "non_channel_beacons:",
-			 le32_to_cpu(general->non_channel_beacons),
-			 accum_general->non_channel_beacons,
-			 delta_general->non_channel_beacons,
-			 max_general->non_channel_beacons);
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-	kfree(buf);
-	return ret;
-}
-
-ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
-				    char __user *user_buf,
-				    size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char *buf;
-	int bufsz = (sizeof(struct iwl39_statistics_tx) * 48) + 250;
-	ssize_t ret;
-	struct iwl39_statistics_tx *tx, *accum_tx, *delta_tx, *max_tx;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf) {
-		IWL_ERR(priv, "Can not allocate Buffer\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The statistic information display here is based on
-	 * the last statistics notification from uCode
-	 * might not reflect the current uCode activity
-	 */
-	tx = &priv->_3945.statistics.tx;
-	accum_tx = &priv->_3945.accum_statistics.tx;
-	delta_tx = &priv->_3945.delta_statistics.tx;
-	max_tx = &priv->_3945.max_delta.tx;
-	pos += iwl3945_statistics_flag(priv, buf, bufsz);
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_Tx:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "preamble:",
-			 le32_to_cpu(tx->preamble_cnt),
-			 accum_tx->preamble_cnt,
-			 delta_tx->preamble_cnt, max_tx->preamble_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "rx_detected_cnt:",
-			 le32_to_cpu(tx->rx_detected_cnt),
-			 accum_tx->rx_detected_cnt,
-			 delta_tx->rx_detected_cnt, max_tx->rx_detected_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bt_prio_defer_cnt:",
-			 le32_to_cpu(tx->bt_prio_defer_cnt),
-			 accum_tx->bt_prio_defer_cnt,
-			 delta_tx->bt_prio_defer_cnt,
-			 max_tx->bt_prio_defer_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "bt_prio_kill_cnt:",
-			 le32_to_cpu(tx->bt_prio_kill_cnt),
-			 accum_tx->bt_prio_kill_cnt,
-			 delta_tx->bt_prio_kill_cnt,
-			 max_tx->bt_prio_kill_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "few_bytes_cnt:",
-			 le32_to_cpu(tx->few_bytes_cnt),
-			 accum_tx->few_bytes_cnt,
-			 delta_tx->few_bytes_cnt, max_tx->few_bytes_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "cts_timeout:",
-			 le32_to_cpu(tx->cts_timeout), accum_tx->cts_timeout,
-			 delta_tx->cts_timeout, max_tx->cts_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "ack_timeout:",
-			 le32_to_cpu(tx->ack_timeout),
-			 accum_tx->ack_timeout,
-			 delta_tx->ack_timeout, max_tx->ack_timeout);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "expected_ack_cnt:",
-			 le32_to_cpu(tx->expected_ack_cnt),
-			 accum_tx->expected_ack_cnt,
-			 delta_tx->expected_ack_cnt,
-			 max_tx->expected_ack_cnt);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "actual_ack_cnt:",
-			 le32_to_cpu(tx->actual_ack_cnt),
-			 accum_tx->actual_ack_cnt,
-			 delta_tx->actual_ack_cnt,
-			 max_tx->actual_ack_cnt);
-
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-	kfree(buf);
-	return ret;
-}
-
-ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-					 char __user *user_buf,
-					 size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char *buf;
-	int bufsz = sizeof(struct iwl39_statistics_general) * 10 + 300;
-	ssize_t ret;
-	struct iwl39_statistics_general *general, *accum_general;
-	struct iwl39_statistics_general *delta_general, *max_general;
-	struct statistics_dbg *dbg, *accum_dbg, *delta_dbg, *max_dbg;
-	struct iwl39_statistics_div *div, *accum_div, *delta_div, *max_div;
-
-	if (!iwl_is_alive(priv))
-		return -EAGAIN;
-
-	buf = kzalloc(bufsz, GFP_KERNEL);
-	if (!buf) {
-		IWL_ERR(priv, "Can not allocate Buffer\n");
-		return -ENOMEM;
-	}
-
-	/*
-	 * The statistic information display here is based on
-	 * the last statistics notification from uCode
-	 * might not reflect the current uCode activity
-	 */
-	general = &priv->_3945.statistics.general;
-	dbg = &priv->_3945.statistics.general.dbg;
-	div = &priv->_3945.statistics.general.div;
-	accum_general = &priv->_3945.accum_statistics.general;
-	delta_general = &priv->_3945.delta_statistics.general;
-	max_general = &priv->_3945.max_delta.general;
-	accum_dbg = &priv->_3945.accum_statistics.general.dbg;
-	delta_dbg = &priv->_3945.delta_statistics.general.dbg;
-	max_dbg = &priv->_3945.max_delta.general.dbg;
-	accum_div = &priv->_3945.accum_statistics.general.div;
-	delta_div = &priv->_3945.delta_statistics.general.div;
-	max_div = &priv->_3945.max_delta.general.div;
-	pos += iwl3945_statistics_flag(priv, buf, bufsz);
-	pos += scnprintf(buf + pos, bufsz - pos, "%-32s     current"
-			 "acumulative       delta         max\n",
-			 "Statistics_General:");
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "burst_check:",
-			 le32_to_cpu(dbg->burst_check),
-			 accum_dbg->burst_check,
-			 delta_dbg->burst_check, max_dbg->burst_check);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "burst_count:",
-			 le32_to_cpu(dbg->burst_count),
-			 accum_dbg->burst_count,
-			 delta_dbg->burst_count, max_dbg->burst_count);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "sleep_time:",
-			 le32_to_cpu(general->sleep_time),
-			 accum_general->sleep_time,
-			 delta_general->sleep_time, max_general->sleep_time);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "slots_out:",
-			 le32_to_cpu(general->slots_out),
-			 accum_general->slots_out,
-			 delta_general->slots_out, max_general->slots_out);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "slots_idle:",
-			 le32_to_cpu(general->slots_idle),
-			 accum_general->slots_idle,
-			 delta_general->slots_idle, max_general->slots_idle);
-	pos += scnprintf(buf + pos, bufsz - pos, "ttl_timestamp:\t\t\t%u\n",
-			 le32_to_cpu(general->ttl_timestamp));
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "tx_on_a:",
-			 le32_to_cpu(div->tx_on_a), accum_div->tx_on_a,
-			 delta_div->tx_on_a, max_div->tx_on_a);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "tx_on_b:",
-			 le32_to_cpu(div->tx_on_b), accum_div->tx_on_b,
-			 delta_div->tx_on_b, max_div->tx_on_b);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "exec_time:",
-			 le32_to_cpu(div->exec_time), accum_div->exec_time,
-			 delta_div->exec_time, max_div->exec_time);
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "  %-30s %10u  %10u  %10u  %10u\n",
-			 "probe_time:",
-			 le32_to_cpu(div->probe_time), accum_div->probe_time,
-			 delta_div->probe_time, max_div->probe_time);
-	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-	kfree(buf);
-	return ret;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-debugfs.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,60 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *****************************************************************************/
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-debug.h"
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-ssize_t iwl3945_ucode_rx_stats_read(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos);
-ssize_t iwl3945_ucode_tx_stats_read(struct file *file, char __user *user_buf,
-				    size_t count, loff_t *ppos);
-ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-					 char __user *user_buf, size_t count,
-					 loff_t *ppos);
-#else
-static ssize_t iwl3945_ucode_rx_stats_read(struct file *file,
-					   char __user *user_buf, size_t count,
-					   loff_t *ppos)
-{
-	return 0;
-}
-static ssize_t iwl3945_ucode_tx_stats_read(struct file *file,
-					   char __user *user_buf, size_t count,
-					   loff_t *ppos)
-{
-	return 0;
-}
-static ssize_t iwl3945_ucode_general_stats_read(struct file *file,
-						char __user *user_buf,
-						size_t count, loff_t *ppos)
-{
-	return 0;
-}
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-fh.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-fh.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-fh.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-fh.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,188 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- * 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 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.
- *
- *****************************************************************************/
-#ifndef __iwl_3945_fh_h__
-#define __iwl_3945_fh_h__
-
-/************************************/
-/* iwl3945 Flow Handler Definitions */
-/************************************/
-
-/**
- * This I/O area is directly read/writable by driver (e.g. Linux uses writel())
- * Addresses are offsets from device's PCI hardware base address.
- */
-#define FH39_MEM_LOWER_BOUND                   (0x0800)
-#define FH39_MEM_UPPER_BOUND                   (0x1000)
-
-#define FH39_CBCC_TABLE		(FH39_MEM_LOWER_BOUND + 0x140)
-#define FH39_TFDB_TABLE		(FH39_MEM_LOWER_BOUND + 0x180)
-#define FH39_RCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x400)
-#define FH39_RSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x4c0)
-#define FH39_TCSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x500)
-#define FH39_TSSR_TABLE		(FH39_MEM_LOWER_BOUND + 0x680)
-
-/* TFDB (Transmit Frame Buffer Descriptor) */
-#define FH39_TFDB(_ch, buf)			(FH39_TFDB_TABLE + \
-						 ((_ch) * 2 + (buf)) * 0x28)
-#define FH39_TFDB_CHNL_BUF_CTRL_REG(_ch)	(FH39_TFDB_TABLE + 0x50 * (_ch))
-
-/* CBCC channel is [0,2] */
-#define FH39_CBCC(_ch)		(FH39_CBCC_TABLE + (_ch) * 0x8)
-#define FH39_CBCC_CTRL(_ch)	(FH39_CBCC(_ch) + 0x00)
-#define FH39_CBCC_BASE(_ch)	(FH39_CBCC(_ch) + 0x04)
-
-/* RCSR channel is [0,2] */
-#define FH39_RCSR(_ch)			(FH39_RCSR_TABLE + (_ch) * 0x40)
-#define FH39_RCSR_CONFIG(_ch)		(FH39_RCSR(_ch) + 0x00)
-#define FH39_RCSR_RBD_BASE(_ch)		(FH39_RCSR(_ch) + 0x04)
-#define FH39_RCSR_WPTR(_ch)		(FH39_RCSR(_ch) + 0x20)
-#define FH39_RCSR_RPTR_ADDR(_ch)	(FH39_RCSR(_ch) + 0x24)
-
-#define FH39_RSCSR_CHNL0_WPTR		(FH39_RCSR_WPTR(0))
-
-/* RSSR */
-#define FH39_RSSR_CTRL			(FH39_RSSR_TABLE + 0x000)
-#define FH39_RSSR_STATUS		(FH39_RSSR_TABLE + 0x004)
-
-/* TCSR */
-#define FH39_TCSR(_ch)			(FH39_TCSR_TABLE + (_ch) * 0x20)
-#define FH39_TCSR_CONFIG(_ch)		(FH39_TCSR(_ch) + 0x00)
-#define FH39_TCSR_CREDIT(_ch)		(FH39_TCSR(_ch) + 0x04)
-#define FH39_TCSR_BUFF_STTS(_ch)	(FH39_TCSR(_ch) + 0x08)
-
-/* TSSR */
-#define FH39_TSSR_CBB_BASE        (FH39_TSSR_TABLE + 0x000)
-#define FH39_TSSR_MSG_CONFIG      (FH39_TSSR_TABLE + 0x008)
-#define FH39_TSSR_TX_STATUS       (FH39_TSSR_TABLE + 0x010)
-
-
-/* DBM */
-
-#define FH39_SRVC_CHNL                            (6)
-
-#define FH39_RCSR_RX_CONFIG_REG_POS_RBDC_SIZE     (20)
-#define FH39_RCSR_RX_CONFIG_REG_POS_IRQ_RBTH      (4)
-
-#define FH39_RCSR_RX_CONFIG_REG_BIT_WR_STTS_EN    (0x08000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_DMA_CHNL_EN_ENABLE        (0x80000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_RDRBD_EN_ENABLE           (0x20000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_MAX_FRAG_SIZE_128		(0x01000000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_IRQ_DEST_INT_HOST		(0x00001000)
-
-#define FH39_RCSR_RX_CONFIG_REG_VAL_MSG_MODE_FH			(0x00000000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_TXF		(0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_MSG_MODE_DRIVER		(0x00000001)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_DISABLE_VAL	(0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE_VAL	(0x00000008)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_HOST_IFTFD		(0x00200000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_CIRQ_RTC_NOINT		(0x00000000)
-
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_PAUSE		(0x00000000)
-#define FH39_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE		(0x80000000)
-
-#define FH39_TCSR_CHNL_TX_BUF_STS_REG_VAL_TFDB_VALID		(0x00004000)
-
-#define FH39_TCSR_CHNL_TX_BUF_STS_REG_BIT_TFDB_WPTR		(0x00000001)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TXPD_ON	(0xFF000000)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_TXPD_ON	(0x00FF0000)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_MAX_FRAG_SIZE_128B	(0x00000400)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_SNOOP_RD_TFD_ON		(0x00000100)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RD_CBB_ON		(0x00000080)
-
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_ORDER_RSP_WAIT_TH	(0x00000020)
-#define FH39_TSSR_TX_MSG_CONFIG_REG_VAL_RSP_WAIT_TH		(0x00000005)
-
-#define FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch)	(BIT(_ch) << 24)
-#define FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch)	(BIT(_ch) << 16)
-
-#define FH39_TSSR_TX_STATUS_REG_MSK_CHNL_IDLE(_ch) \
-	(FH39_TSSR_TX_STATUS_REG_BIT_BUFS_EMPTY(_ch) | \
-	 FH39_TSSR_TX_STATUS_REG_BIT_NO_PEND_REQ(_ch))
-
-#define FH39_RSSR_CHNL0_RX_STATUS_CHNL_IDLE			(0x01000000)
-
-struct iwl3945_tfd_tb {
-	__le32 addr;
-	__le32 len;
-} __packed;
-
-struct iwl3945_tfd {
-	__le32 control_flags;
-	struct iwl3945_tfd_tb tbs[4];
-	u8 __pad[28];
-} __packed;
-
-
-#endif /* __iwl_3945_fh_h__ */
-
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h	2012-03-24 01:12:12.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,308 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
- *
- * 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
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945.h) for driver implementation definitions.
- * Please use iwl-3945-commands.h for uCode API definitions.
- * Please use iwl-3945-hw.h for hardware-related definitions.
- */
-
-#ifndef __iwl_3945_h__
-#define __iwl_3945_h__
-
-#include <linux/pci.h> /* for struct pci_device_id */
-#include <linux/kernel.h>
-#include <net/ieee80211_radiotap.h>
-
-/* Hardware specific file defines the PCI IDs table for that hardware module */
-extern const struct pci_device_id iwl3945_hw_card_ids[];
-
-#include "iwl-csr.h"
-#include "iwl-prph.h"
-#include "iwl-fh.h"
-#include "iwl-3945-hw.h"
-#include "iwl-debug.h"
-#include "iwl-power.h"
-#include "iwl-dev.h"
-#include "iwl-led.h"
-
-/* Highest firmware API version supported */
-#define IWL3945_UCODE_API_MAX 2
-
-/* Lowest firmware API version supported */
-#define IWL3945_UCODE_API_MIN 1
-
-#define IWL3945_FW_PRE	"/*(DEBLOBBED)*/"
-#define _IWL3945_MODULE_FIRMWARE(api) IWL3945_FW_PRE /*(DEBLOBBED)*/
-#define IWL3945_MODULE_FIRMWARE(api) _IWL3945_MODULE_FIRMWARE(api)
-
-/* Default noise level to report when noise measurement is not available.
- *   This may be because we're:
- *   1)  Not associated (4965, no beacon statistics being sent to driver)
- *   2)  Scanning (noise measurement does not apply to associated channel)
- *   3)  Receiving CCK (3945 delivers noise info only for OFDM frames)
- * Use default noise value of -127 ... this is below the range of measurable
- *   Rx dBm for either 3945 or 4965, so it can indicate "unmeasurable" to user.
- *   Also, -127 works better than 0 when averaging frames with/without
- *   noise info (e.g. averaging might be done in app); measured dBm values are
- *   always negative ... using a negative value as the default keeps all
- *   averages within an s8's (used in some apps) range of negative values. */
-#define IWL_NOISE_MEAS_NOT_AVAILABLE (-127)
-
-/* Module parameters accessible from iwl-*.c */
-extern struct iwl_mod_params iwl3945_mod_params;
-
-struct iwl3945_rate_scale_data {
-	u64 data;
-	s32 success_counter;
-	s32 success_ratio;
-	s32 counter;
-	s32 average_tpt;
-	unsigned long stamp;
-};
-
-struct iwl3945_rs_sta {
-	spinlock_t lock;
-	struct iwl_priv *priv;
-	s32 *expected_tpt;
-	unsigned long last_partial_flush;
-	unsigned long last_flush;
-	u32 flush_time;
-	u32 last_tx_packets;
-	u32 tx_packets;
-	u8 tgg;
-	u8 flush_pending;
-	u8 start_rate;
-	struct timer_list rate_scale_flush;
-	struct iwl3945_rate_scale_data win[IWL_RATE_COUNT_3945];
-#ifdef CONFIG_MAC80211_DEBUGFS
-	struct dentry *rs_sta_dbgfs_stats_table_file;
-#endif
-
-	/* used to be in sta_info */
-	int last_txrate_idx;
-};
-
-
-/*
- * The common struct MUST be first because it is shared between
- * 3945 and agn!
- */
-struct iwl3945_sta_priv {
-	struct iwl_station_priv_common common;
-	struct iwl3945_rs_sta rs_sta;
-};
-
-enum iwl3945_antenna {
-	IWL_ANTENNA_DIVERSITY,
-	IWL_ANTENNA_MAIN,
-	IWL_ANTENNA_AUX
-};
-
-/*
- * RTS threshold here is total size [2347] minus 4 FCS bytes
- * Per spec:
- *   a value of 0 means RTS on all data/management packets
- *   a value > max MSDU size means no RTS
- * else RTS for data/management frames where MPDU is larger
- *   than RTS value.
- */
-#define DEFAULT_RTS_THRESHOLD     2347U
-#define MIN_RTS_THRESHOLD         0U
-#define MAX_RTS_THRESHOLD         2347U
-#define MAX_MSDU_SIZE		  2304U
-#define MAX_MPDU_SIZE		  2346U
-#define DEFAULT_BEACON_INTERVAL   100U
-#define	DEFAULT_SHORT_RETRY_LIMIT 7U
-#define	DEFAULT_LONG_RETRY_LIMIT  4U
-
-#define IWL_TX_FIFO_AC0	0
-#define IWL_TX_FIFO_AC1	1
-#define IWL_TX_FIFO_AC2	2
-#define IWL_TX_FIFO_AC3	3
-#define IWL_TX_FIFO_HCCA_1	5
-#define IWL_TX_FIFO_HCCA_2	6
-#define IWL_TX_FIFO_NONE	7
-
-#define IEEE80211_DATA_LEN              2304
-#define IEEE80211_4ADDR_LEN             30
-#define IEEE80211_HLEN                  (IEEE80211_4ADDR_LEN)
-#define IEEE80211_FRAME_LEN             (IEEE80211_DATA_LEN + IEEE80211_HLEN)
-
-struct iwl3945_frame {
-	union {
-		struct ieee80211_hdr frame;
-		struct iwl3945_tx_beacon_cmd beacon;
-		u8 raw[IEEE80211_FRAME_LEN];
-		u8 cmd[360];
-	} u;
-	struct list_head list;
-};
-
-#define SEQ_TO_SN(seq) (((seq) & IEEE80211_SCTL_SEQ) >> 4)
-#define SN_TO_SEQ(ssn) (((ssn) << 4) & IEEE80211_SCTL_SEQ)
-#define MAX_SN ((IEEE80211_SCTL_SEQ) >> 4)
-
-#define SUP_RATE_11A_MAX_NUM_CHANNELS  8
-#define SUP_RATE_11B_MAX_NUM_CHANNELS  4
-#define SUP_RATE_11G_MAX_NUM_CHANNELS  12
-
-#define IWL_SUPPORTED_RATES_IE_LEN         8
-
-#define SCAN_INTERVAL 100
-
-#define MAX_TID_COUNT        9
-
-#define IWL_INVALID_RATE     0xFF
-#define IWL_INVALID_VALUE    -1
-
-#define STA_PS_STATUS_WAKE             0
-#define STA_PS_STATUS_SLEEP            1
-
-struct iwl3945_ibss_seq {
-	u8 mac[ETH_ALEN];
-	u16 seq_num;
-	u16 frag_num;
-	unsigned long packet_time;
-	struct list_head list;
-};
-
-#define IWL_RX_HDR(x) ((struct iwl3945_rx_frame_hdr *)(\
-		       x->u.rx_frame.stats.payload + \
-		       x->u.rx_frame.stats.phy_count))
-#define IWL_RX_END(x) ((struct iwl3945_rx_frame_end *)(\
-		       IWL_RX_HDR(x)->payload + \
-		       le16_to_cpu(IWL_RX_HDR(x)->len)))
-#define IWL_RX_STATS(x) (&x->u.rx_frame.stats)
-#define IWL_RX_DATA(x) (IWL_RX_HDR(x)->payload)
-
-
-/******************************************************************************
- *
- * Functions implemented in iwl-base.c which are forward declared here
- * for use by iwl-*.c
- *
- *****************************************************************************/
-extern int iwl3945_calc_db_from_ratio(int sig_ratio);
-extern void iwl3945_rx_replenish(void *data);
-extern void iwl3945_rx_queue_reset(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
-extern unsigned int iwl3945_fill_beacon_frame(struct iwl_priv *priv,
-					struct ieee80211_hdr *hdr,int left);
-extern int iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log,
-				       char **buf, bool display);
-extern void iwl3945_dump_nic_error_log(struct iwl_priv *priv);
-
-/******************************************************************************
- *
- * Functions implemented in iwl-[34]*.c which are forward declared here
- * for use by iwl-base.c
- *
- * NOTE:  The implementation of these functions are hardware specific
- * which is why they are in the hardware specific files (vs. iwl-base.c)
- *
- * Naming convention --
- * iwl3945_         <-- Its part of iwlwifi (should be changed to iwl3945_)
- * iwl3945_hw_      <-- Hardware specific (implemented in iwl-XXXX.c by all HW)
- * iwlXXXX_     <-- Hardware specific (implemented in iwl-XXXX.c for XXXX)
- * iwl3945_bg_      <-- Called from work queue context
- * iwl3945_mac_     <-- mac80211 callback
- *
- ****************************************************************************/
-extern void iwl3945_hw_rx_handler_setup(struct iwl_priv *priv);
-extern void iwl3945_hw_setup_deferred_work(struct iwl_priv *priv);
-extern void iwl3945_hw_cancel_deferred_work(struct iwl_priv *priv);
-extern int iwl3945_hw_rxq_stop(struct iwl_priv *priv);
-extern int iwl3945_hw_set_hw_params(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_init(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_stop_master(struct iwl_priv *priv);
-extern void iwl3945_hw_txq_ctx_free(struct iwl_priv *priv);
-extern void iwl3945_hw_txq_ctx_stop(struct iwl_priv *priv);
-extern int iwl3945_hw_nic_reset(struct iwl_priv *priv);
-extern int iwl3945_hw_txq_attach_buf_to_tfd(struct iwl_priv *priv,
-					    struct iwl_tx_queue *txq,
-					    dma_addr_t addr, u16 len,
-					    u8 reset, u8 pad);
-extern void iwl3945_hw_txq_free_tfd(struct iwl_priv *priv,
-				    struct iwl_tx_queue *txq);
-extern int iwl3945_hw_get_temperature(struct iwl_priv *priv);
-extern int iwl3945_hw_tx_queue_init(struct iwl_priv *priv,
-				struct iwl_tx_queue *txq);
-extern unsigned int iwl3945_hw_get_beacon_cmd(struct iwl_priv *priv,
-				 struct iwl3945_frame *frame, u8 rate);
-void iwl3945_hw_build_tx_cmd_rate(struct iwl_priv *priv,
-				  struct iwl_device_cmd *cmd,
-				  struct ieee80211_tx_info *info,
-				  struct ieee80211_hdr *hdr,
-				  int sta_id, int tx_id);
-extern int iwl3945_hw_reg_send_txpower(struct iwl_priv *priv);
-extern int iwl3945_hw_reg_set_txpower(struct iwl_priv *priv, s8 power);
-extern void iwl3945_hw_rx_statistics(struct iwl_priv *priv,
-				 struct iwl_rx_mem_buffer *rxb);
-void iwl3945_reply_statistics(struct iwl_priv *priv,
-			      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);
-
-extern int iwl3945_commit_rxon(struct iwl_priv *priv,
-			       struct iwl_rxon_context *ctx);
-
-/**
- * iwl3945_hw_find_station - Find station id for a given BSSID
- * @bssid: MAC address of station ID to find
- *
- * NOTE:  This should not be hardware specific but the code has
- * not yet been merged into a single common layer for managing the
- * station tables.
- */
-extern u8 iwl3945_hw_find_station(struct iwl_priv *priv, const u8 *bssid);
-
-extern struct ieee80211_ops iwl3945_hw_ops;
-
-/*
- * Forward declare iwl-3945.c functions for iwl-base.c
- */
-extern __le32 iwl3945_get_antenna_flags(const struct iwl_priv *priv);
-extern int iwl3945_init_hw_rate_table(struct iwl_priv *priv);
-extern void iwl3945_reg_txpower_periodic(struct iwl_priv *priv);
-extern int iwl3945_txpower_set_from_eeprom(struct iwl_priv *priv);
-
-extern const struct iwl_channel_info *iwl3945_get_channel_info(
-	const struct iwl_priv *priv, enum ieee80211_band band, u16 channel);
-
-extern int iwl3945_rs_next_rate(struct iwl_priv *priv, int rate);
-
-/* scanning */
-int iwl3945_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
-void iwl3945_post_scan(struct iwl_priv *priv);
-
-/* rates */
-extern const struct iwl3945_rate_info iwl3945_rates[IWL_RATE_COUNT_3945];
-
-/* Requires full declaration of iwl_priv before including */
-#include "iwl-io.h"
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,294 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- * 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 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.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-3945-hw.h) only for hardware-related definitions.
- * Please use iwl-commands.h for uCode API definitions.
- * Please use iwl-3945.h for driver implementation definitions.
- */
-
-#ifndef __iwl_3945_hw__
-#define __iwl_3945_hw__
-
-#include "iwl-eeprom.h"
-
-/* RSSI to dBm */
-#define IWL39_RSSI_OFFSET	95
-
-#define IWL_DEFAULT_TX_POWER	0x0F
-
-/*
- * EEPROM related constants, enums, and structures.
- */
-#define EEPROM_SKU_CAP_OP_MODE_MRC                      (1 << 7)
-
-/*
- * Mapping of a Tx power level, at factory calibration temperature,
- *   to a radio/DSP gain table index.
- * One for each of 5 "sample" power levels in each band.
- * v_det is measured at the factory, using the 3945's built-in power amplifier
- *   (PA) output voltage detector.  This same detector is used during Tx of
- *   long packets in normal operation to provide feedback as to proper output
- *   level.
- * Data copied from EEPROM.
- * DO NOT ALTER THIS STRUCTURE!!!
- */
-struct iwl3945_eeprom_txpower_sample {
-	u8 gain_index;		/* index into power (gain) setup table ... */
-	s8 power;		/* ... for this pwr level for this chnl group */
-	u16 v_det;		/* PA output voltage */
-} __packed;
-
-/*
- * Mappings of Tx power levels -> nominal radio/DSP gain table indexes.
- * One for each channel group (a.k.a. "band") (1 for BG, 4 for A).
- * Tx power setup code interpolates between the 5 "sample" power levels
- *    to determine the nominal setup for a requested power level.
- * Data copied from EEPROM.
- * DO NOT ALTER THIS STRUCTURE!!!
- */
-struct iwl3945_eeprom_txpower_group {
-	struct iwl3945_eeprom_txpower_sample samples[5];  /* 5 power levels */
-	s32 a, b, c, d, e;	/* coefficients for voltage->power
-				 * formula (signed) */
-	s32 Fa, Fb, Fc, Fd, Fe;	/* these modify coeffs based on
-				 * frequency (signed) */
-	s8 saturation_power;	/* highest power possible by h/w in this
-				 * band */
-	u8 group_channel;	/* "representative" channel # in this band */
-	s16 temperature;	/* h/w temperature at factory calib this band
-				 * (signed) */
-} __packed;
-
-/*
- * Temperature-based Tx-power compensation data, not band-specific.
- * These coefficients are use to modify a/b/c/d/e coeffs based on
- *   difference between current temperature and factory calib temperature.
- * Data copied from EEPROM.
- */
-struct iwl3945_eeprom_temperature_corr {
-	u32 Ta;
-	u32 Tb;
-	u32 Tc;
-	u32 Td;
-	u32 Te;
-} __packed;
-
-/*
- * EEPROM map
- */
-struct iwl3945_eeprom {
-	u8 reserved0[16];
-	u16 device_id;	/* abs.ofs: 16 */
-	u8 reserved1[2];
-	u16 pmc;		/* abs.ofs: 20 */
-	u8 reserved2[20];
-	u8 mac_address[6];	/* abs.ofs: 42 */
-	u8 reserved3[58];
-	u16 board_revision;	/* abs.ofs: 106 */
-	u8 reserved4[11];
-	u8 board_pba_number[9];	/* abs.ofs: 119 */
-	u8 reserved5[8];
-	u16 version;		/* abs.ofs: 136 */
-	u8 sku_cap;		/* abs.ofs: 138 */
-	u8 leds_mode;		/* abs.ofs: 139 */
-	u16 oem_mode;
-	u16 wowlan_mode;	/* abs.ofs: 142 */
-	u16 leds_time_interval;	/* abs.ofs: 144 */
-	u8 leds_off_time;	/* abs.ofs: 146 */
-	u8 leds_on_time;	/* abs.ofs: 147 */
-	u8 almgor_m_version;	/* abs.ofs: 148 */
-	u8 antenna_switch_type;	/* abs.ofs: 149 */
-	u8 reserved6[42];
-	u8 sku_id[4];		/* abs.ofs: 192 */
-
-/*
- * Per-channel regulatory data.
- *
- * Each channel that *might* be supported by 3945 or 4965 has a fixed location
- * in EEPROM containing EEPROM_CHANNEL_* usage flags (LSB) and max regulatory
- * txpower (MSB).
- *
- * Entries immediately below are for 20 MHz channel width.  HT40 (40 MHz)
- * channels (only for 4965, not supported by 3945) appear later in the EEPROM.
- *
- * 2.4 GHz channels 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
- */
-	u16 band_1_count;	/* abs.ofs: 196 */
-	struct iwl_eeprom_channel band_1_channels[14];  /* abs.ofs: 198 */
-
-/*
- * 4.9 GHz channels 183, 184, 185, 187, 188, 189, 192, 196,
- * 5.0 GHz channels 7, 8, 11, 12, 16
- * (4915-5080MHz) (none of these is ever supported)
- */
-	u16 band_2_count;	/* abs.ofs: 226 */
-	struct iwl_eeprom_channel band_2_channels[13];  /* abs.ofs: 228 */
-
-/*
- * 5.2 GHz channels 34, 36, 38, 40, 42, 44, 46, 48, 52, 56, 60, 64
- * (5170-5320MHz)
- */
-	u16 band_3_count;	/* abs.ofs: 254 */
-	struct iwl_eeprom_channel band_3_channels[12];  /* abs.ofs: 256 */
-
-/*
- * 5.5 GHz channels 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140
- * (5500-5700MHz)
- */
-	u16 band_4_count;	/* abs.ofs: 280 */
-	struct iwl_eeprom_channel band_4_channels[11];  /* abs.ofs: 282 */
-
-/*
- * 5.7 GHz channels 145, 149, 153, 157, 161, 165
- * (5725-5825MHz)
- */
-	u16 band_5_count;	/* abs.ofs: 304 */
-	struct iwl_eeprom_channel band_5_channels[6];  /* abs.ofs: 306 */
-
-	u8 reserved9[194];
-
-/*
- * 3945 Txpower calibration data.
- */
-#define IWL_NUM_TX_CALIB_GROUPS 5
-	struct iwl3945_eeprom_txpower_group groups[IWL_NUM_TX_CALIB_GROUPS];
-/* abs.ofs: 512 */
-	struct iwl3945_eeprom_temperature_corr corrections;  /* abs.ofs: 832 */
-	u8 reserved16[172];	/* fill out to full 1024 byte block */
-} __packed;
-
-#define IWL3945_EEPROM_IMG_SIZE 1024
-
-/* End of EEPROM */
-
-#define PCI_CFG_REV_ID_BIT_BASIC_SKU                (0x40)	/* bit 6    */
-#define PCI_CFG_REV_ID_BIT_RTP                      (0x80)	/* bit 7    */
-
-/* 4 DATA + 1 CMD. There are 2 HCCA queues that are not used. */
-#define IWL39_NUM_QUEUES        5
-#define IWL39_CMD_QUEUE_NUM	4
-
-#define IWL_DEFAULT_TX_RETRY  15
-
-/*********************************************/
-
-#define RFD_SIZE                              4
-#define NUM_TFD_CHUNKS                        4
-
-#define RX_QUEUE_SIZE                         256
-#define RX_QUEUE_MASK                         255
-#define RX_QUEUE_SIZE_LOG                     8
-
-#define U32_PAD(n)		((4-(n))&0x3)
-
-#define TFD_CTL_COUNT_SET(n)       (n << 24)
-#define TFD_CTL_COUNT_GET(ctl)     ((ctl >> 24) & 7)
-#define TFD_CTL_PAD_SET(n)         (n << 28)
-#define TFD_CTL_PAD_GET(ctl)       (ctl >> 28)
-
-/* Sizes and addresses for instruction and data memory (SRAM) in
- * 3945's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define IWL39_RTC_INST_LOWER_BOUND		(0x000000)
-#define IWL39_RTC_INST_UPPER_BOUND		(0x014000)
-
-#define IWL39_RTC_DATA_LOWER_BOUND		(0x800000)
-#define IWL39_RTC_DATA_UPPER_BOUND		(0x808000)
-
-#define IWL39_RTC_INST_SIZE (IWL39_RTC_INST_UPPER_BOUND - \
-				IWL39_RTC_INST_LOWER_BOUND)
-#define IWL39_RTC_DATA_SIZE (IWL39_RTC_DATA_UPPER_BOUND - \
-				IWL39_RTC_DATA_LOWER_BOUND)
-
-#define IWL39_MAX_INST_SIZE IWL39_RTC_INST_SIZE
-#define IWL39_MAX_DATA_SIZE IWL39_RTC_DATA_SIZE
-
-/* Size of uCode instruction memory in bootstrap state machine */
-#define IWL39_MAX_BSM_SIZE IWL39_RTC_INST_SIZE
-
-static inline int iwl3945_hw_valid_rtc_data_addr(u32 addr)
-{
-	return (addr >= IWL39_RTC_DATA_LOWER_BOUND) &&
-	       (addr < IWL39_RTC_DATA_UPPER_BOUND);
-}
-
-/* Base physical address of iwl3945_shared is provided to FH_TSSR_CBB_BASE
- * and &iwl3945_shared.rx_read_ptr[0] is provided to FH_RCSR_RPTR_ADDR(0) */
-struct iwl3945_shared {
-	__le32 tx_base_ptr[8];
-} __packed;
-
-static inline u8 iwl3945_hw_get_rate(__le16 rate_n_flags)
-{
-	return le16_to_cpu(rate_n_flags) & 0xFF;
-}
-
-static inline u16 iwl3945_hw_get_rate_n_flags(__le16 rate_n_flags)
-{
-	return le16_to_cpu(rate_n_flags);
-}
-
-static inline __le16 iwl3945_hw_set_rate_n_flags(u8 rate, u16 flags)
-{
-	return cpu_to_le16((u16)rate|flags);
-}
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,91 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
- *
- * 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 <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-commands.h"
-#include "iwl-3945.h"
-#include "iwl-core.h"
-#include "iwl-dev.h"
-#include "iwl-3945-led.h"
-
-
-/* Send led command */
-static int iwl3945_send_led_cmd(struct iwl_priv *priv,
-				struct iwl_led_cmd *led_cmd)
-{
-	struct iwl_host_cmd cmd = {
-		.id = REPLY_LEDS_CMD,
-		.len = sizeof(struct iwl_led_cmd),
-		.data = led_cmd,
-		.flags = CMD_ASYNC,
-		.callback = NULL,
-	};
-
-	return iwl_send_cmd(priv, &cmd);
-}
-
-/* Set led on command */
-static int iwl3945_led_on(struct iwl_priv *priv)
-{
-	struct iwl_led_cmd led_cmd = {
-		.id = IWL_LED_LINK,
-		.on = IWL_LED_SOLID,
-		.off = 0,
-		.interval = IWL_DEF_LED_INTRVL
-	};
-	return iwl3945_send_led_cmd(priv, &led_cmd);
-}
-
-/* Set led off command */
-static int iwl3945_led_off(struct iwl_priv *priv)
-{
-	struct iwl_led_cmd led_cmd = {
-		.id = IWL_LED_LINK,
-		.on = 0,
-		.off = 0,
-		.interval = IWL_DEF_LED_INTRVL
-	};
-	IWL_DEBUG_LED(priv, "led off\n");
-	return iwl3945_send_led_cmd(priv, &led_cmd);
-}
-
-const struct iwl_led_ops iwl3945_led_ops = {
-	.cmd = iwl3945_send_led_cmd,
-	.on = iwl3945_led_on,
-	.off = iwl3945_led_off,
-};
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-led.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,32 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
- *
- * 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_3945_led_h__
-#define __iwl_3945_led_h__
-
-extern const struct iwl_led_ops iwl3945_led_ops;
-
-#endif /* __iwl_3945_led_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-3945-rs.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,995 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- *
- * 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/init.h>
-#include <linux/skbuff.h>
-#include <linux/slab.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/delay.h>
-
-#include <linux/workqueue.h>
-
-#include "iwl-commands.h"
-#include "iwl-3945.h"
-#include "iwl-sta.h"
-
-#define RS_NAME "iwl-3945-rs"
-
-static s32 iwl3945_expected_tpt_g[IWL_RATE_COUNT_3945] = {
-	7, 13, 35, 58, 0, 0, 76, 104, 130, 168, 191, 202
-};
-
-static s32 iwl3945_expected_tpt_g_prot[IWL_RATE_COUNT_3945] = {
-	7, 13, 35, 58, 0, 0, 0, 80, 93, 113, 123, 125
-};
-
-static s32 iwl3945_expected_tpt_a[IWL_RATE_COUNT_3945] = {
-	0, 0, 0, 0, 40, 57, 72, 98, 121, 154, 177, 186
-};
-
-static s32 iwl3945_expected_tpt_b[IWL_RATE_COUNT_3945] = {
-	7, 13, 35, 58, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-struct iwl3945_tpt_entry {
-	s8 min_rssi;
-	u8 index;
-};
-
-static struct iwl3945_tpt_entry iwl3945_tpt_table_a[] = {
-	{-60, IWL_RATE_54M_INDEX},
-	{-64, IWL_RATE_48M_INDEX},
-	{-72, IWL_RATE_36M_INDEX},
-	{-80, IWL_RATE_24M_INDEX},
-	{-84, IWL_RATE_18M_INDEX},
-	{-85, IWL_RATE_12M_INDEX},
-	{-87, IWL_RATE_9M_INDEX},
-	{-89, IWL_RATE_6M_INDEX}
-};
-
-static struct iwl3945_tpt_entry iwl3945_tpt_table_g[] = {
-	{-60, IWL_RATE_54M_INDEX},
-	{-64, IWL_RATE_48M_INDEX},
-	{-68, IWL_RATE_36M_INDEX},
-	{-80, IWL_RATE_24M_INDEX},
-	{-84, IWL_RATE_18M_INDEX},
-	{-85, IWL_RATE_12M_INDEX},
-	{-86, IWL_RATE_11M_INDEX},
-	{-88, IWL_RATE_5M_INDEX},
-	{-90, IWL_RATE_2M_INDEX},
-	{-92, IWL_RATE_1M_INDEX}
-};
-
-#define IWL_RATE_MAX_WINDOW          62
-#define IWL_RATE_FLUSH       	 (3*HZ)
-#define IWL_RATE_WIN_FLUSH       (HZ/2)
-#define IWL39_RATE_HIGH_TH          11520
-#define IWL_SUCCESS_UP_TH	   8960
-#define IWL_SUCCESS_DOWN_TH	  10880
-#define IWL_RATE_MIN_FAILURE_TH       6
-#define IWL_RATE_MIN_SUCCESS_TH       8
-#define IWL_RATE_DECREASE_TH       1920
-#define IWL_RATE_RETRY_TH	     15
-
-static u8 iwl3945_get_rate_index_by_rssi(s32 rssi, enum ieee80211_band band)
-{
-	u32 index = 0;
-	u32 table_size = 0;
-	struct iwl3945_tpt_entry *tpt_table = NULL;
-
-	if ((rssi < IWL_MIN_RSSI_VAL) || (rssi > IWL_MAX_RSSI_VAL))
-		rssi = IWL_MIN_RSSI_VAL;
-
-	switch (band) {
-	case IEEE80211_BAND_2GHZ:
-		tpt_table = iwl3945_tpt_table_g;
-		table_size = ARRAY_SIZE(iwl3945_tpt_table_g);
-		break;
-
-	case IEEE80211_BAND_5GHZ:
-		tpt_table = iwl3945_tpt_table_a;
-		table_size = ARRAY_SIZE(iwl3945_tpt_table_a);
-		break;
-
-	default:
-		BUG();
-		break;
-	}
-
-	while ((index < table_size) && (rssi < tpt_table[index].min_rssi))
-		index++;
-
-	index = min(index, (table_size - 1));
-
-	return tpt_table[index].index;
-}
-
-static void iwl3945_clear_window(struct iwl3945_rate_scale_data *window)
-{
-	window->data = 0;
-	window->success_counter = 0;
-	window->success_ratio = -1;
-	window->counter = 0;
-	window->average_tpt = IWL_INVALID_VALUE;
-	window->stamp = 0;
-}
-
-/**
- * iwl3945_rate_scale_flush_windows - flush out the rate scale windows
- *
- * Returns the number of windows that have gathered data but were
- * not flushed.  If there were any that were not flushed, then
- * reschedule the rate flushing routine.
- */
-static int iwl3945_rate_scale_flush_windows(struct iwl3945_rs_sta *rs_sta)
-{
-	int unflushed = 0;
-	int i;
-	unsigned long flags;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-	/*
-	 * For each rate, if we have collected data on that rate
-	 * and it has been more than IWL_RATE_WIN_FLUSH
-	 * since we flushed, clear out the gathered statistics
-	 */
-	for (i = 0; i < IWL_RATE_COUNT_3945; i++) {
-		if (!rs_sta->win[i].counter)
-			continue;
-
-		spin_lock_irqsave(&rs_sta->lock, flags);
-		if (time_after(jiffies, rs_sta->win[i].stamp +
-			       IWL_RATE_WIN_FLUSH)) {
-			IWL_DEBUG_RATE(priv, "flushing %d samples of rate "
-				       "index %d\n",
-				       rs_sta->win[i].counter, i);
-			iwl3945_clear_window(&rs_sta->win[i]);
-		} else
-			unflushed++;
-		spin_unlock_irqrestore(&rs_sta->lock, flags);
-	}
-
-	return unflushed;
-}
-
-#define IWL_RATE_FLUSH_MAX              5000	/* msec */
-#define IWL_RATE_FLUSH_MIN              50	/* msec */
-#define IWL_AVERAGE_PACKETS             1500
-
-static void iwl3945_bg_rate_scale_flush(unsigned long data)
-{
-	struct iwl3945_rs_sta *rs_sta = (void *)data;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-	int unflushed = 0;
-	unsigned long flags;
-	u32 packet_count, duration, pps;
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	unflushed = iwl3945_rate_scale_flush_windows(rs_sta);
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	/* Number of packets Rx'd since last time this timer ran */
-	packet_count = (rs_sta->tx_packets - rs_sta->last_tx_packets) + 1;
-
-	rs_sta->last_tx_packets = rs_sta->tx_packets + 1;
-
-	if (unflushed) {
-		duration =
-		    jiffies_to_msecs(jiffies - rs_sta->last_partial_flush);
-
-		IWL_DEBUG_RATE(priv, "Tx'd %d packets in %dms\n",
-			       packet_count, duration);
-
-		/* Determine packets per second */
-		if (duration)
-			pps = (packet_count * 1000) / duration;
-		else
-			pps = 0;
-
-		if (pps) {
-			duration = (IWL_AVERAGE_PACKETS * 1000) / pps;
-			if (duration < IWL_RATE_FLUSH_MIN)
-				duration = IWL_RATE_FLUSH_MIN;
-			else if (duration > IWL_RATE_FLUSH_MAX)
-				duration = IWL_RATE_FLUSH_MAX;
-		} else
-			duration = IWL_RATE_FLUSH_MAX;
-
-		rs_sta->flush_time = msecs_to_jiffies(duration);
-
-		IWL_DEBUG_RATE(priv, "new flush period: %d msec ave %d\n",
-			       duration, packet_count);
-
-		mod_timer(&rs_sta->rate_scale_flush, jiffies +
-			  rs_sta->flush_time);
-
-		rs_sta->last_partial_flush = jiffies;
-	} else {
-		rs_sta->flush_time = IWL_RATE_FLUSH;
-		rs_sta->flush_pending = 0;
-	}
-	/* If there weren't any unflushed entries, we don't schedule the timer
-	 * to run again */
-
-	rs_sta->last_flush = jiffies;
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-/**
- * iwl3945_collect_tx_data - Update the success/failure sliding window
- *
- * We keep a sliding window of the last 64 packets transmitted
- * at this rate.  window->data contains the bitmask of successful
- * packets.
- */
-static void iwl3945_collect_tx_data(struct iwl3945_rs_sta *rs_sta,
-				struct iwl3945_rate_scale_data *window,
-				int success, int retries, int index)
-{
-	unsigned long flags;
-	s32 fail_count;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-	if (!retries) {
-		IWL_DEBUG_RATE(priv, "leave: retries == 0 -- should be at least 1\n");
-		return;
-	}
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	/*
-	 * Keep track of only the latest 62 tx frame attempts in this rate's
-	 * history window; anything older isn't really relevant any more.
-	 * If we have filled up the sliding window, drop the oldest attempt;
-	 * if the oldest attempt (highest bit in bitmap) shows "success",
-	 * subtract "1" from the success counter (this is the main reason
-	 * we keep these bitmaps!).
-	 * */
-	while (retries > 0) {
-		if (window->counter >= IWL_RATE_MAX_WINDOW) {
-
-			/* remove earliest */
-			window->counter = IWL_RATE_MAX_WINDOW - 1;
-
-			if (window->data & (1ULL << (IWL_RATE_MAX_WINDOW - 1))) {
-				window->data &= ~(1ULL << (IWL_RATE_MAX_WINDOW - 1));
-				window->success_counter--;
-			}
-		}
-
-		/* Increment frames-attempted counter */
-		window->counter++;
-
-		/* Shift bitmap by one frame (throw away oldest history),
-		 * OR in "1", and increment "success" if this
-		 * frame was successful. */
-		window->data <<= 1;
-		if (success > 0) {
-			window->success_counter++;
-			window->data |= 0x1;
-			success--;
-		}
-
-		retries--;
-	}
-
-	/* Calculate current success ratio, avoid divide-by-0! */
-	if (window->counter > 0)
-		window->success_ratio = 128 * (100 * window->success_counter)
-					/ window->counter;
-	else
-		window->success_ratio = IWL_INVALID_VALUE;
-
-	fail_count = window->counter - window->success_counter;
-
-	/* Calculate average throughput, if we have enough history. */
-	if ((fail_count >= IWL_RATE_MIN_FAILURE_TH) ||
-	    (window->success_counter >= IWL_RATE_MIN_SUCCESS_TH))
-		window->average_tpt = ((window->success_ratio *
-				rs_sta->expected_tpt[index] + 64) / 128);
-	else
-		window->average_tpt = IWL_INVALID_VALUE;
-
-	/* Tag this window as having been updated */
-	window->stamp = jiffies;
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-}
-
-/*
- * Called after adding a new station to initialize rate scaling
- */
-void iwl3945_rs_rate_init(struct iwl_priv *priv, struct ieee80211_sta *sta, u8 sta_id)
-{
-	struct ieee80211_hw *hw = priv->hw;
-	struct ieee80211_conf *conf = &priv->hw->conf;
-	struct iwl3945_sta_priv *psta;
-	struct iwl3945_rs_sta *rs_sta;
-	struct ieee80211_supported_band *sband;
-	int i;
-
-	IWL_DEBUG_INFO(priv, "enter\n");
-	if (sta_id == priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id)
-		goto out;
-
-	psta = (struct iwl3945_sta_priv *) sta->drv_priv;
-	rs_sta = &psta->rs_sta;
-	sband = hw->wiphy->bands[conf->channel->band];
-
-	rs_sta->priv = priv;
-
-	rs_sta->start_rate = IWL_RATE_INVALID;
-
-	/* default to just 802.11b */
-	rs_sta->expected_tpt = iwl3945_expected_tpt_b;
-
-	rs_sta->last_partial_flush = jiffies;
-	rs_sta->last_flush = jiffies;
-	rs_sta->flush_time = IWL_RATE_FLUSH;
-	rs_sta->last_tx_packets = 0;
-
-	rs_sta->rate_scale_flush.data = (unsigned long)rs_sta;
-	rs_sta->rate_scale_flush.function = iwl3945_bg_rate_scale_flush;
-
-	for (i = 0; i < IWL_RATE_COUNT_3945; i++)
-		iwl3945_clear_window(&rs_sta->win[i]);
-
-	/* TODO: what is a good starting rate for STA? About middle? Maybe not
-	 * the lowest or the highest rate.. Could consider using RSSI from
-	 * previous packets? Need to have IEEE 802.1X auth succeed immediately
-	 * after assoc.. */
-
-	for (i = sband->n_bitrates - 1; i >= 0; i--) {
-		if (sta->supp_rates[sband->band] & (1 << i)) {
-			rs_sta->last_txrate_idx = i;
-			break;
-		}
-	}
-
-	priv->_3945.sta_supp_rates = sta->supp_rates[sband->band];
-	/* For 5 GHz band it start at IWL_FIRST_OFDM_RATE */
-	if (sband->band == IEEE80211_BAND_5GHZ) {
-		rs_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE;
-		priv->_3945.sta_supp_rates = priv->_3945.sta_supp_rates <<
-						IWL_FIRST_OFDM_RATE;
-	}
-
-out:
-	priv->stations[sta_id].used &= ~IWL_STA_UCODE_INPROGRESS;
-
-	IWL_DEBUG_INFO(priv, "leave\n");
-}
-
-static void *rs_alloc(struct ieee80211_hw *hw, struct dentry *debugfsdir)
-{
-	return hw->priv;
-}
-
-/* rate scale requires free function to be implemented */
-static void rs_free(void *priv)
-{
-	return;
-}
-
-static void *rs_alloc_sta(void *iwl_priv, struct ieee80211_sta *sta, gfp_t gfp)
-{
-	struct iwl3945_rs_sta *rs_sta;
-	struct iwl3945_sta_priv *psta = (void *) sta->drv_priv;
-	struct iwl_priv *priv __maybe_unused = iwl_priv;
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	rs_sta = &psta->rs_sta;
-
-	spin_lock_init(&rs_sta->lock);
-	init_timer(&rs_sta->rate_scale_flush);
-
-	IWL_DEBUG_RATE(priv, "leave\n");
-
-	return rs_sta;
-}
-
-static void rs_free_sta(void *iwl_priv, struct ieee80211_sta *sta,
-			void *priv_sta)
-{
-	struct iwl3945_rs_sta *rs_sta = priv_sta;
-
-	/*
-	 * Be careful not to use any members of iwl3945_rs_sta (like trying
-	 * to use iwl_priv to print out debugging) since it may not be fully
-	 * initialized at this point.
-	 */
-	del_timer_sync(&rs_sta->rate_scale_flush);
-}
-
-
-/**
- * rs_tx_status - Update rate control values based on Tx results
- *
- * NOTE: Uses iwl_priv->retry_rate for the # of retries attempted by
- * the hardware for each rate.
- */
-static void rs_tx_status(void *priv_rate, struct ieee80211_supported_band *sband,
-			 struct ieee80211_sta *sta, void *priv_sta,
-			 struct sk_buff *skb)
-{
-	s8 retries = 0, current_count;
-	int scale_rate_index, first_index, last_index;
-	unsigned long flags;
-	struct iwl_priv *priv = (struct iwl_priv *)priv_rate;
-	struct iwl3945_rs_sta *rs_sta = priv_sta;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	retries = info->status.rates[0].count;
-	/* Sanity Check for retries */
-	if (retries > IWL_RATE_RETRY_TH)
-		retries = IWL_RATE_RETRY_TH;
-
-	first_index = sband->bitrates[info->status.rates[0].idx].hw_value;
-	if ((first_index < 0) || (first_index >= IWL_RATE_COUNT_3945)) {
-		IWL_DEBUG_RATE(priv, "leave: Rate out of bounds: %d\n", first_index);
-		return;
-	}
-
-	if (!priv_sta) {
-		IWL_DEBUG_RATE(priv, "leave: No STA priv data to update!\n");
-		return;
-	}
-
-	/* Treat uninitialized rate scaling data same as non-existing. */
-	if (!rs_sta->priv) {
-		IWL_DEBUG_RATE(priv, "leave: STA priv data uninitialized!\n");
-		return;
-	}
-
-
-	rs_sta->tx_packets++;
-
-	scale_rate_index = first_index;
-	last_index = first_index;
-
-	/*
-	 * Update the window for each rate.  We determine which rates
-	 * were Tx'd based on the total number of retries vs. the number
-	 * of retries configured for each rate -- currently set to the
-	 * priv value 'retry_rate' vs. rate specific
-	 *
-	 * On exit from this while loop last_index indicates the rate
-	 * at which the frame was finally transmitted (or failed if no
-	 * ACK)
-	 */
-	while (retries > 1) {
-		if ((retries - 1) < priv->retry_rate) {
-			current_count = (retries - 1);
-			last_index = scale_rate_index;
-		} else {
-			current_count = priv->retry_rate;
-			last_index = iwl3945_rs_next_rate(priv,
-							 scale_rate_index);
-		}
-
-		/* Update this rate accounting for as many retries
-		 * as was used for it (per current_count) */
-		iwl3945_collect_tx_data(rs_sta,
-				    &rs_sta->win[scale_rate_index],
-				    0, current_count, scale_rate_index);
-		IWL_DEBUG_RATE(priv, "Update rate %d for %d retries.\n",
-			       scale_rate_index, current_count);
-
-		retries -= current_count;
-
-		scale_rate_index = last_index;
-	}
-
-
-	/* Update the last index window with success/failure based on ACK */
-	IWL_DEBUG_RATE(priv, "Update rate %d with %s.\n",
-		       last_index,
-		       (info->flags & IEEE80211_TX_STAT_ACK) ?
-		       "success" : "failure");
-	iwl3945_collect_tx_data(rs_sta,
-			    &rs_sta->win[last_index],
-			    info->flags & IEEE80211_TX_STAT_ACK, 1, last_index);
-
-	/* We updated the rate scale window -- if its been more than
-	 * flush_time since the last run, schedule the flush
-	 * again */
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	if (!rs_sta->flush_pending &&
-	    time_after(jiffies, rs_sta->last_flush +
-		       rs_sta->flush_time)) {
-
-		rs_sta->last_partial_flush = jiffies;
-		rs_sta->flush_pending = 1;
-		mod_timer(&rs_sta->rate_scale_flush,
-			  jiffies + rs_sta->flush_time);
-	}
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	IWL_DEBUG_RATE(priv, "leave\n");
-}
-
-static u16 iwl3945_get_adjacent_rate(struct iwl3945_rs_sta *rs_sta,
-				 u8 index, u16 rate_mask, enum ieee80211_band band)
-{
-	u8 high = IWL_RATE_INVALID;
-	u8 low = IWL_RATE_INVALID;
-	struct iwl_priv *priv __maybe_unused = rs_sta->priv;
-
-	/* 802.11A walks to the next literal adjacent rate in
-	 * the rate table */
-	if (unlikely(band == IEEE80211_BAND_5GHZ)) {
-		int i;
-		u32 mask;
-
-		/* Find the previous rate that is in the rate mask */
-		i = index - 1;
-		for (mask = (1 << i); i >= 0; i--, mask >>= 1) {
-			if (rate_mask & mask) {
-				low = i;
-				break;
-			}
-		}
-
-		/* Find the next rate that is in the rate mask */
-		i = index + 1;
-		for (mask = (1 << i); i < IWL_RATE_COUNT_3945;
-		     i++, mask <<= 1) {
-			if (rate_mask & mask) {
-				high = i;
-				break;
-			}
-		}
-
-		return (high << 8) | low;
-	}
-
-	low = index;
-	while (low != IWL_RATE_INVALID) {
-		if (rs_sta->tgg)
-			low = iwl3945_rates[low].prev_rs_tgg;
-		else
-			low = iwl3945_rates[low].prev_rs;
-		if (low == IWL_RATE_INVALID)
-			break;
-		if (rate_mask & (1 << low))
-			break;
-		IWL_DEBUG_RATE(priv, "Skipping masked lower rate: %d\n", low);
-	}
-
-	high = index;
-	while (high != IWL_RATE_INVALID) {
-		if (rs_sta->tgg)
-			high = iwl3945_rates[high].next_rs_tgg;
-		else
-			high = iwl3945_rates[high].next_rs;
-		if (high == IWL_RATE_INVALID)
-			break;
-		if (rate_mask & (1 << high))
-			break;
-		IWL_DEBUG_RATE(priv, "Skipping masked higher rate: %d\n", high);
-	}
-
-	return (high << 8) | low;
-}
-
-/**
- * rs_get_rate - find the rate for the requested packet
- *
- * Returns the ieee80211_rate structure allocated by the driver.
- *
- * The rate control algorithm has no internal mapping between hw_mode's
- * rate ordering and the rate ordering used by the rate control algorithm.
- *
- * The rate control algorithm uses a single table of rates that goes across
- * the entire A/B/G spectrum vs. being limited to just one particular
- * hw_mode.
- *
- * As such, we can't convert the index obtained below into the hw_mode's
- * rate table and must reference the driver allocated rate table
- *
- */
-static void rs_get_rate(void *priv_r, 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;
-	u8 low = IWL_RATE_INVALID;
-	u8 high = IWL_RATE_INVALID;
-	u16 high_low;
-	int index;
-	struct iwl3945_rs_sta *rs_sta = priv_sta;
-	struct iwl3945_rate_scale_data *window = NULL;
-	int current_tpt = IWL_INVALID_VALUE;
-	int low_tpt = IWL_INVALID_VALUE;
-	int high_tpt = IWL_INVALID_VALUE;
-	u32 fail_count;
-	s8 scale_action = 0;
-	unsigned long flags;
-	u16 rate_mask = sta ? sta->supp_rates[sband->band] : 0;
-	s8 max_rate_idx = -1;
-	struct iwl_priv *priv __maybe_unused = (struct iwl_priv *)priv_r;
-	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	/* Treat uninitialized rate scaling data same as non-existing. */
-	if (rs_sta && !rs_sta->priv) {
-		IWL_DEBUG_RATE(priv, "Rate scaling information not initialized yet.\n");
-		priv_sta = NULL;
-	}
-
-	if (rate_control_send_low(sta, priv_sta, txrc))
-		return;
-
-	rate_mask = sta->supp_rates[sband->band];
-
-	/* get user max rate if set */
-	max_rate_idx = txrc->max_rate_idx;
-	if ((sband->band == IEEE80211_BAND_5GHZ) && (max_rate_idx != -1))
-		max_rate_idx += IWL_FIRST_OFDM_RATE;
-	if ((max_rate_idx < 0) || (max_rate_idx >= IWL_RATE_COUNT))
-		max_rate_idx = -1;
-
-	index = min(rs_sta->last_txrate_idx & 0xffff, IWL_RATE_COUNT_3945 - 1);
-
-	if (sband->band == IEEE80211_BAND_5GHZ)
-		rate_mask = rate_mask << IWL_FIRST_OFDM_RATE;
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	/* for recent assoc, choose best rate regarding
-	 * to rssi value
-	 */
-	if (rs_sta->start_rate != IWL_RATE_INVALID) {
-		if (rs_sta->start_rate < index &&
-		   (rate_mask & (1 << rs_sta->start_rate)))
-			index = rs_sta->start_rate;
-		rs_sta->start_rate = IWL_RATE_INVALID;
-	}
-
-	/* force user max rate if set by user */
-	if ((max_rate_idx != -1) && (max_rate_idx < index)) {
-		if (rate_mask & (1 << max_rate_idx))
-			index = max_rate_idx;
-	}
-
-	window = &(rs_sta->win[index]);
-
-	fail_count = window->counter - window->success_counter;
-
-	if (((fail_count < IWL_RATE_MIN_FAILURE_TH) &&
-	     (window->success_counter < IWL_RATE_MIN_SUCCESS_TH))) {
-		spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-		IWL_DEBUG_RATE(priv, "Invalid average_tpt on rate %d: "
-			       "counter: %d, success_counter: %d, "
-			       "expected_tpt is %sNULL\n",
-			       index,
-			       window->counter,
-			       window->success_counter,
-			       rs_sta->expected_tpt ? "not " : "");
-
-	   /* Can't calculate this yet; not enough history */
-		window->average_tpt = IWL_INVALID_VALUE;
-		goto out;
-
-	}
-
-	current_tpt = window->average_tpt;
-
-	high_low = iwl3945_get_adjacent_rate(rs_sta, index, rate_mask,
-					     sband->band);
-	low = high_low & 0xff;
-	high = (high_low >> 8) & 0xff;
-
-	/* If user set max rate, dont allow higher than user constrain */
-	if ((max_rate_idx != -1) && (max_rate_idx < high))
-		high = IWL_RATE_INVALID;
-
-	/* Collect Measured throughputs of adjacent rates */
-	if (low != IWL_RATE_INVALID)
-		low_tpt = rs_sta->win[low].average_tpt;
-
-	if (high != IWL_RATE_INVALID)
-		high_tpt = rs_sta->win[high].average_tpt;
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	scale_action = 0;
-
-	/* Low success ratio , need to drop the rate */
-	if ((window->success_ratio < IWL_RATE_DECREASE_TH) || !current_tpt) {
-		IWL_DEBUG_RATE(priv, "decrease rate because of low success_ratio\n");
-		scale_action = -1;
-	/* No throughput measured yet for adjacent rates,
-	 * try increase */
-	} else if ((low_tpt == IWL_INVALID_VALUE) &&
-		   (high_tpt == IWL_INVALID_VALUE)) {
-
-		if (high != IWL_RATE_INVALID && window->success_ratio >= IWL_RATE_INCREASE_TH)
-			scale_action = 1;
-		else if (low != IWL_RATE_INVALID)
-			scale_action = 0;
-
-	/* Both adjacent throughputs are measured, but neither one has
-	 * better throughput; we're using the best rate, don't change
-	 * it! */
-	} else if ((low_tpt != IWL_INVALID_VALUE) &&
-		 (high_tpt != IWL_INVALID_VALUE) &&
-		 (low_tpt < current_tpt) && (high_tpt < current_tpt)) {
-
-		IWL_DEBUG_RATE(priv, "No action -- low [%d] & high [%d] < "
-			       "current_tpt [%d]\n",
-			       low_tpt, high_tpt, current_tpt);
-		scale_action = 0;
-
-	/* At least one of the rates has better throughput */
-	} else {
-		if (high_tpt != IWL_INVALID_VALUE) {
-
-			/* High rate has better throughput, Increase
-			 * rate */
-			if (high_tpt > current_tpt &&
-				window->success_ratio >= IWL_RATE_INCREASE_TH)
-				scale_action = 1;
-			else {
-				IWL_DEBUG_RATE(priv,
-				    "decrease rate because of high tpt\n");
-				scale_action = 0;
-			}
-		} else if (low_tpt != IWL_INVALID_VALUE) {
-			if (low_tpt > current_tpt) {
-				IWL_DEBUG_RATE(priv,
-				    "decrease rate because of low tpt\n");
-				scale_action = -1;
-			} else if (window->success_ratio >= IWL_RATE_INCREASE_TH) {
-				/* Lower rate has better
-				 * throughput,decrease rate */
-				scale_action = 1;
-			}
-		}
-	}
-
-	/* Sanity check; asked for decrease, but success rate or throughput
-	 * has been good at old rate.  Don't change it. */
-	if ((scale_action == -1) && (low != IWL_RATE_INVALID) &&
-		    ((window->success_ratio > IWL_RATE_HIGH_TH) ||
-		     (current_tpt > (100 * rs_sta->expected_tpt[low]))))
-		scale_action = 0;
-
-	switch (scale_action) {
-	case -1:
-
-		/* Decrese rate */
-		if (low != IWL_RATE_INVALID)
-			index = low;
-		break;
-
-	case 1:
-		/* Increase rate */
-		if (high != IWL_RATE_INVALID)
-			index = high;
-
-		break;
-
-	case 0:
-	default:
-		/* No change */
-		break;
-	}
-
-	IWL_DEBUG_RATE(priv, "Selected %d (action %d) - low %d high %d\n",
-		       index, scale_action, low, high);
-
- out:
-
-	rs_sta->last_txrate_idx = index;
-	if (sband->band == IEEE80211_BAND_5GHZ)
-		info->control.rates[0].idx = rs_sta->last_txrate_idx -
-				IWL_FIRST_OFDM_RATE;
-	else
-		info->control.rates[0].idx = rs_sta->last_txrate_idx;
-
-	IWL_DEBUG_RATE(priv, "leave: %d\n", index);
-}
-
-#ifdef CONFIG_MAC80211_DEBUGFS
-static int iwl3945_open_file_generic(struct inode *inode, struct file *file)
-{
-	file->private_data = inode->i_private;
-	return 0;
-}
-
-static ssize_t iwl3945_sta_dbgfs_stats_table_read(struct file *file,
-						  char __user *user_buf,
-						  size_t count, loff_t *ppos)
-{
-	char *buff;
-	int desc = 0;
-	int j;
-	ssize_t ret;
-	struct iwl3945_rs_sta *lq_sta = file->private_data;
-
-	buff = kmalloc(1024, GFP_KERNEL);
-	if (!buff)
-		return -ENOMEM;
-
-	desc += sprintf(buff + desc, "tx packets=%d last rate index=%d\n"
-			"rate=0x%X flush time %d\n",
-			lq_sta->tx_packets,
-			lq_sta->last_txrate_idx,
-			lq_sta->start_rate, jiffies_to_msecs(lq_sta->flush_time));
-	for (j = 0; j < IWL_RATE_COUNT_3945; j++) {
-		desc += sprintf(buff+desc,
-				"counter=%d success=%d %%=%d\n",
-				lq_sta->win[j].counter,
-				lq_sta->win[j].success_counter,
-				lq_sta->win[j].success_ratio);
-	}
-	ret = simple_read_from_buffer(user_buf, count, ppos, buff, desc);
-	kfree(buff);
-	return ret;
-}
-
-static const struct file_operations rs_sta_dbgfs_stats_table_ops = {
-	.read = iwl3945_sta_dbgfs_stats_table_read,
-	.open = iwl3945_open_file_generic,
-	.llseek = default_llseek,
-};
-
-static void iwl3945_add_debugfs(void *priv, void *priv_sta,
-				struct dentry *dir)
-{
-	struct iwl3945_rs_sta *lq_sta = priv_sta;
-
-	lq_sta->rs_sta_dbgfs_stats_table_file =
-		debugfs_create_file("rate_stats_table", 0600, dir,
-		lq_sta, &rs_sta_dbgfs_stats_table_ops);
-
-}
-
-static void iwl3945_remove_debugfs(void *priv, void *priv_sta)
-{
-	struct iwl3945_rs_sta *lq_sta = priv_sta;
-	debugfs_remove(lq_sta->rs_sta_dbgfs_stats_table_file);
-}
-#endif
-
-/*
- * Initialization of rate scaling information is done by driver after
- * the station is added. Since mac80211 calls this function before a
- * station is added we ignore it.
- */
-static void rs_rate_init_stub(void *priv_r, struct ieee80211_supported_band *sband,
-			      struct ieee80211_sta *sta, void *priv_sta)
-{
-}
-
-static struct rate_control_ops rs_ops = {
-	.module = NULL,
-	.name = RS_NAME,
-	.tx_status = rs_tx_status,
-	.get_rate = rs_get_rate,
-	.rate_init = rs_rate_init_stub,
-	.alloc = rs_alloc,
-	.free = rs_free,
-	.alloc_sta = rs_alloc_sta,
-	.free_sta = rs_free_sta,
-#ifdef CONFIG_MAC80211_DEBUGFS
-	.add_sta_debugfs = iwl3945_add_debugfs,
-	.remove_sta_debugfs = iwl3945_remove_debugfs,
-#endif
-
-};
-void iwl3945_rate_scale_init(struct ieee80211_hw *hw, s32 sta_id)
-{
-	struct iwl_priv *priv = hw->priv;
-	s32 rssi = 0;
-	unsigned long flags;
-	struct iwl3945_rs_sta *rs_sta;
-	struct ieee80211_sta *sta;
-	struct iwl3945_sta_priv *psta;
-
-	IWL_DEBUG_RATE(priv, "enter\n");
-
-	rcu_read_lock();
-
-	sta = ieee80211_find_sta(priv->contexts[IWL_RXON_CTX_BSS].vif,
-				 priv->stations[sta_id].sta.sta.addr);
-	if (!sta) {
-		IWL_DEBUG_RATE(priv, "Unable to find station to initialize rate scaling.\n");
-		rcu_read_unlock();
-		return;
-	}
-
-	psta = (void *) sta->drv_priv;
-	rs_sta = &psta->rs_sta;
-
-	spin_lock_irqsave(&rs_sta->lock, flags);
-
-	rs_sta->tgg = 0;
-	switch (priv->band) {
-	case IEEE80211_BAND_2GHZ:
-		/* TODO: this always does G, not a regression */
-		if (priv->contexts[IWL_RXON_CTX_BSS].active.flags &
-						RXON_FLG_TGG_PROTECT_MSK) {
-			rs_sta->tgg = 1;
-			rs_sta->expected_tpt = iwl3945_expected_tpt_g_prot;
-		} else
-			rs_sta->expected_tpt = iwl3945_expected_tpt_g;
-		break;
-
-	case IEEE80211_BAND_5GHZ:
-		rs_sta->expected_tpt = iwl3945_expected_tpt_a;
-		break;
-	case IEEE80211_NUM_BANDS:
-		BUG();
-		break;
-	}
-
-	spin_unlock_irqrestore(&rs_sta->lock, flags);
-
-	rssi = priv->_3945.last_rx_rssi;
-	if (rssi == 0)
-		rssi = IWL_MIN_RSSI_VAL;
-
-	IWL_DEBUG_RATE(priv, "Network RSSI: %d\n", rssi);
-
-	rs_sta->start_rate = iwl3945_get_rate_index_by_rssi(rssi, priv->band);
-
-	IWL_DEBUG_RATE(priv, "leave: rssi %d assign rate index: "
-		       "%d (plcp 0x%x)\n", rssi, rs_sta->start_rate,
-		       iwl3945_rates[rs_sta->start_rate].plcp);
-	rcu_read_unlock();
-}
-
-int iwl3945_rate_control_register(void)
-{
-	return ieee80211_rate_control_register(&rs_ops);
-}
-
-void iwl3945_rate_control_unregister(void)
-{
-	ieee80211_rate_control_unregister(&rs_ops);
-}
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c	2012-03-24 01:12:25.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-4965.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2645 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2003 - 2010 Intel Corporation. All rights reserved.
- *
- * 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 <linux/pci.h>
-#include <linux/dma-mapping.h>
-#include <linux/delay.h>
-#include <linux/sched.h>
-#include <linux/skbuff.h>
-#include <linux/netdevice.h>
-#include <linux/wireless.h>
-#include <net/mac80211.h>
-#include <linux/etherdevice.h>
-#include <asm/unaligned.h>
-
-#include "iwl-eeprom.h"
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-agn-calib.h"
-#include "iwl-sta.h"
-#include "iwl-agn-led.h"
-#include "iwl-agn.h"
-#include "iwl-agn-debugfs.h"
-#include "iwl-legacy.h"
-
-static int iwl4965_send_tx_power(struct iwl_priv *priv);
-static int iwl4965_hw_get_temperature(struct iwl_priv *priv);
-
-/* Highest firmware API version supported */
-#define IWL4965_UCODE_API_MAX 2
-
-/* Lowest firmware API version supported */
-#define IWL4965_UCODE_API_MIN 2
-
-#define IWL4965_FW_PRE "/*(DEBLOBBED)*/"
-#define _IWL4965_MODULE_FIRMWARE(api) IWL4965_FW_PRE /*(DEBLOBBED)*/
-#define IWL4965_MODULE_FIRMWARE(api) _IWL4965_MODULE_FIRMWARE(api)
-
-/* check contents of special bootstrap uCode SRAM */
-static int iwl4965_verify_bsm(struct iwl_priv *priv)
-{
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	u32 reg;
-	u32 val;
-
-	IWL_DEBUG_INFO(priv, "Begin verify bsm\n");
-
-	/* verify BSM SRAM contents */
-	val = iwl_read_prph(priv, BSM_WR_DWCOUNT_REG);
-	for (reg = BSM_SRAM_LOWER_BOUND;
-	     reg < BSM_SRAM_LOWER_BOUND + len;
-	     reg += sizeof(u32), image++) {
-		val = iwl_read_prph(priv, reg);
-		if (val != le32_to_cpu(*image)) {
-			IWL_ERR(priv, "BSM uCode verification failed at "
-				  "addr 0x%08X+%u (of %u), is 0x%x, s/b 0x%x\n",
-				  BSM_SRAM_LOWER_BOUND,
-				  reg - BSM_SRAM_LOWER_BOUND, len,
-				  val, le32_to_cpu(*image));
-			return -EIO;
-		}
-	}
-
-	IWL_DEBUG_INFO(priv, "BSM bootstrap uCode image OK\n");
-
-	return 0;
-}
-
-/**
- * iwl4965_load_bsm - Load bootstrap instructions
- *
- * BSM operation:
- *
- * The Bootstrap State Machine (BSM) stores a short bootstrap uCode program
- * in special SRAM that does not power down during RFKILL.  When powering back
- * up after power-saving sleeps (or during initial uCode load), the BSM loads
- * the bootstrap program into the on-board processor, and starts it.
- *
- * The bootstrap program loads (via DMA) instructions and data for a new
- * program from host DRAM locations indicated by the host driver in the
- * BSM_DRAM_* registers.  Once the new program is loaded, it starts
- * automatically.
- *
- * When initializing the NIC, the host driver points the BSM to the
- * "initialize" uCode image.  This uCode sets up some internal data, then
- * notifies host via "initialize alive" that it is complete.
- *
- * The host then replaces the BSM_DRAM_* pointer values to point to the
- * normal runtime uCode instructions and a backup uCode data cache buffer
- * (filled initially with starting data values for the on-board processor),
- * then triggers the "initialize" uCode to load and launch the runtime uCode,
- * which begins normal operation.
- *
- * When doing a power-save shutdown, runtime uCode saves data SRAM into
- * the backup data cache in DRAM before SRAM is powered down.
- *
- * When powering back up, the BSM loads the bootstrap program.  This reloads
- * the runtime uCode instructions and the backup data cache into SRAM,
- * and re-launches the runtime uCode from where it left off.
- */
-static int iwl4965_load_bsm(struct iwl_priv *priv)
-{
-	__le32 *image = priv->ucode_boot.v_addr;
-	u32 len = priv->ucode_boot.len;
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-	u32 inst_len;
-	u32 data_len;
-	int i;
-	u32 done;
-	u32 reg_offset;
-	int ret;
-
-	IWL_DEBUG_INFO(priv, "Begin load bsm\n");
-
-	priv->ucode_type = UCODE_RT;
-
-	/* make sure bootstrap program is no larger than BSM's SRAM size */
-	if (len > IWL49_MAX_BSM_SIZE)
-		return -EINVAL;
-
-	/* Tell bootstrap uCode where to find the "Initialize" uCode
-	 *   in host DRAM ... host DRAM physical address bits 35:4 for 4965.
-	 * NOTE:  iwl_init_alive_start() will replace these values,
-	 *        after the "initialize" uCode has run, to point to
-	 *        runtime/protocol instructions and backup data cache.
-	 */
-	pinst = priv->ucode_init.p_addr >> 4;
-	pdata = priv->ucode_init_data.p_addr >> 4;
-	inst_len = priv->ucode_init.len;
-	data_len = priv->ucode_init_data.len;
-
-	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);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG, data_len);
-
-	/* Fill BSM memory with bootstrap instructions */
-	for (reg_offset = BSM_SRAM_LOWER_BOUND;
-	     reg_offset < BSM_SRAM_LOWER_BOUND + len;
-	     reg_offset += sizeof(u32), image++)
-		_iwl_write_prph(priv, reg_offset, le32_to_cpu(*image));
-
-	ret = iwl4965_verify_bsm(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);
-	iwl_write_prph(priv, BSM_WR_MEM_DST_REG, IWL49_RTC_INST_LOWER_BOUND);
-	iwl_write_prph(priv, BSM_WR_DWCOUNT_REG, len / sizeof(u32));
-
-	/* Load bootstrap code into instruction SRAM now,
-	 *   to prepare to load "initialize" uCode */
-	iwl_write_prph(priv, BSM_WR_CTRL_REG, BSM_WR_CTRL_REG_BIT_START);
-
-	/* Wait for load of bootstrap uCode to finish */
-	for (i = 0; i < 100; i++) {
-		done = iwl_read_prph(priv, BSM_WR_CTRL_REG);
-		if (!(done & BSM_WR_CTRL_REG_BIT_START))
-			break;
-		udelay(10);
-	}
-	if (i < 100)
-		IWL_DEBUG_INFO(priv, "BSM write complete, poll %d iterations\n", i);
-	else {
-		IWL_ERR(priv, "BSM write did not complete!\n");
-		return -EIO;
-	}
-
-	/* Enable future boot loads whenever power management unit triggers it
-	 *   (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);
-
-
-	return 0;
-}
-
-/**
- * iwl4965_set_ucode_ptrs - Set uCode address location
- *
- * Tell initialization uCode where to find runtime uCode.
- *
- * BSM registers initially contain pointers to initialization uCode.
- * We need to replace them to load runtime uCode inst and data,
- * and to save runtime data when powering down.
- */
-static int iwl4965_set_ucode_ptrs(struct iwl_priv *priv)
-{
-	dma_addr_t pinst;
-	dma_addr_t pdata;
-	int ret = 0;
-
-	/* bits 35:4 for 4965 */
-	pinst = priv->ucode_code.p_addr >> 4;
-	pdata = priv->ucode_data_backup.p_addr >> 4;
-
-	/* 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);
-	iwl_write_prph(priv, BSM_DRAM_DATA_BYTECOUNT_REG,
-				 priv->ucode_data.len);
-
-	/* Inst byte count must be last to set up, bit 31 signals uCode
-	 *   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_DEBUG_INFO(priv, "Runtime uCode pointers are set.\n");
-
-	return ret;
-}
-
-/**
- * iwl4965_init_alive_start - Called after REPLY_ALIVE notification received
- *
- * Called after REPLY_ALIVE notification received from "initialize" uCode.
- *
- * The 4965 "initialize" ALIVE reply contains calibration data for:
- *   Voltage, temperature, and MIMO tx gain correction, now stored in priv
- *   (3945 does not contain this data).
- *
- * Tell "initialize" uCode to go ahead and load the runtime uCode.
-*/
-static void iwl4965_init_alive_start(struct iwl_priv *priv)
-{
-	/* Check alive response for "valid" sign from uCode */
-	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
-		goto restart;
-	}
-
-	/* Bootstrap uCode has loaded initialize uCode ... verify inst image.
-	 * This is a paranoid check, because we would not have gotten the
-	 * "initialize" alive if code weren't properly loaded.  */
-	if (iwl_verify_ucode(priv)) {
-		/* Runtime instruction load was bad;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Bad \"initialize\" uCode load.\n");
-		goto restart;
-	}
-
-	/* Calculate temperature */
-	priv->temperature = iwl4965_hw_get_temperature(priv);
-
-	/* Send pointers to protocol/runtime uCode image ... init code will
-	 * load and launch runtime uCode, which will send us another "Alive"
-	 * notification. */
-	IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-	if (iwl4965_set_ucode_ptrs(priv)) {
-		/* Runtime instruction load won't happen;
-		 * take it all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Couldn't set up uCode pointers.\n");
-		goto restart;
-	}
-	return;
-
-restart:
-	queue_work(priv->workqueue, &priv->restart);
-}
-
-static bool is_ht40_channel(__le32 rxon_flags)
-{
-	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));
-}
-
-/*
- * EEPROM handlers
- */
-static u16 iwl4965_eeprom_calib_version(struct iwl_priv *priv)
-{
-	return iwl_eeprom_query16(priv, EEPROM_4965_CALIB_VERSION_OFFSET);
-}
-
-/*
- * Activate/Deactivate Tx DMA/FIFO channels according tx fifos mask
- * must be called under priv->lock and mac access
- */
-static void iwl4965_txq_set_sched(struct iwl_priv *priv, u32 mask)
-{
-	iwl_write_prph(priv, IWL49_SCD_TXFACT, mask);
-}
-
-static void iwl4965_nic_config(struct iwl_priv *priv)
-{
-	unsigned long flags;
-	u16 radio_cfg;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	radio_cfg = iwl_eeprom_query16(priv, EEPROM_RADIO_CONFIG);
-
-	/* write radio config values to register */
-	if (EEPROM_RF_CFG_TYPE_MSK(radio_cfg) == EEPROM_4965_RF_CFG_TYPE_MAX)
-		iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-			    EEPROM_RF_CFG_TYPE_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_STEP_MSK(radio_cfg) |
-			    EEPROM_RF_CFG_DASH_MSK(radio_cfg));
-
-	/* set CSR_HW_CONFIG_REG for uCode use */
-	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
-		    CSR_HW_IF_CONFIG_REG_BIT_RADIO_SI |
-		    CSR_HW_IF_CONFIG_REG_BIT_MAC_SI);
-
-	priv->calib_info = (struct iwl_eeprom_calib_info *)
-		iwl_eeprom_query_addr(priv, EEPROM_4965_CALIB_TXPOWER_OFFSET);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-}
-
-/* Reset differential Rx gains in NIC to prepare for chain noise calibration.
- * Called after every association, but this runs only once!
- *  ... once chain noise is calibrated the first time, it's good forever.  */
-static void iwl4965_chain_noise_reset(struct iwl_priv *priv)
-{
-	struct iwl_chain_noise_data *data = &(priv->chain_noise_data);
-
-	if ((data->state == IWL_CHAIN_NOISE_ALIVE) &&
-	    iwl_is_any_associated(priv)) {
-		struct iwl_calib_diff_gain_cmd cmd;
-
-		/* clear data for chain noise calibration algorithm */
-		data->chain_noise_a = 0;
-		data->chain_noise_b = 0;
-		data->chain_noise_c = 0;
-		data->chain_signal_a = 0;
-		data->chain_signal_b = 0;
-		data->chain_signal_c = 0;
-		data->beacon_count = 0;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
-		cmd.diff_gain_a = 0;
-		cmd.diff_gain_b = 0;
-		cmd.diff_gain_c = 0;
-		if (iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-				 sizeof(cmd), &cmd))
-			IWL_ERR(priv,
-				"Could not send REPLY_PHY_CALIBRATION_CMD\n");
-		data->state = IWL_CHAIN_NOISE_ACCUMULATE;
-		IWL_DEBUG_CALIB(priv, "Run chain_noise_calibrate\n");
-	}
-}
-
-static void iwl4965_gain_computation(struct iwl_priv *priv,
-		u32 *average_noise,
-		u16 min_average_noise_antenna_i,
-		u32 min_average_noise,
-		u8 default_chain)
-{
-	int i, ret;
-	struct iwl_chain_noise_data *data = &priv->chain_noise_data;
-
-	data->delta_gain_code[min_average_noise_antenna_i] = 0;
-
-	for (i = default_chain; i < NUM_RX_CHAINS; i++) {
-		s32 delta_g = 0;
-
-		if (!(data->disconn_array[i]) &&
-		    (data->delta_gain_code[i] ==
-			     CHAIN_NOISE_DELTA_GAIN_INIT_VAL)) {
-			delta_g = average_noise[i] - min_average_noise;
-			data->delta_gain_code[i] = (u8)((delta_g * 10) / 15);
-			data->delta_gain_code[i] =
-				min(data->delta_gain_code[i],
-				(u8) CHAIN_NOISE_MAX_DELTA_GAIN_CODE);
-
-			data->delta_gain_code[i] =
-				(data->delta_gain_code[i] | (1 << 2));
-		} else {
-			data->delta_gain_code[i] = 0;
-		}
-	}
-	IWL_DEBUG_CALIB(priv, "delta_gain_codes: a %d b %d c %d\n",
-		     data->delta_gain_code[0],
-		     data->delta_gain_code[1],
-		     data->delta_gain_code[2]);
-
-	/* Differential gain gets sent to uCode only once */
-	if (!data->radio_write) {
-		struct iwl_calib_diff_gain_cmd cmd;
-		data->radio_write = 1;
-
-		memset(&cmd, 0, sizeof(cmd));
-		cmd.hdr.op_code = IWL_PHY_CALIBRATE_DIFF_GAIN_CMD;
-		cmd.diff_gain_a = data->delta_gain_code[0];
-		cmd.diff_gain_b = data->delta_gain_code[1];
-		cmd.diff_gain_c = data->delta_gain_code[2];
-		ret = iwl_send_cmd_pdu(priv, REPLY_PHY_CALIBRATION_CMD,
-				      sizeof(cmd), &cmd);
-		if (ret)
-			IWL_DEBUG_CALIB(priv, "fail sending cmd "
-				     "REPLY_PHY_CALIBRATION_CMD\n");
-
-		/* TODO we might want recalculate
-		 * rx_chain in rxon cmd */
-
-		/* Mark so we run this algo only once! */
-		data->state = IWL_CHAIN_NOISE_CALIBRATED;
-	}
-}
-
-static void iwl4965_bg_txpower_work(struct work_struct *work)
-{
-	struct iwl_priv *priv = container_of(work, struct iwl_priv,
-			txpower_work);
-
-	/* If a scan happened to start before we got here
-	 * then just return; the statistics notification will
-	 * kick off another scheduled work to compensate for
-	 * any temperature delta we missed here. */
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status) ||
-	    test_bit(STATUS_SCANNING, &priv->status))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	/* Regardless of if we are associated, we must reconfigure the
-	 * TX power since frames can be sent on non-radar channels while
-	 * not associated */
-	iwl4965_send_tx_power(priv);
-
-	/* Update last_temperature to keep is_calib_needed from running
-	 * when it isn't needed... */
-	priv->last_temperature = priv->temperature;
-
-	mutex_unlock(&priv->mutex);
-}
-
-/*
- * Acquire priv->lock before calling this function !
- */
-static void iwl4965_set_wr_ptrs(struct iwl_priv *priv, int txq_id, u32 index)
-{
-	iwl_write_direct32(priv, HBUS_TARG_WRPTR,
-			     (index & 0xff) | (txq_id << 8));
-	iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(txq_id), index);
-}
-
-/**
- * iwl4965_tx_queue_set_status - (optionally) start Tx/Cmd queue
- * @tx_fifo_id: Tx DMA/FIFO channel (range 0-7) that the queue will feed
- * @scd_retry: (1) Indicates queue will be used in aggregation mode
- *
- * NOTE:  Acquire priv->lock before calling this function !
- */
-static void iwl4965_tx_queue_set_status(struct iwl_priv *priv,
-					struct iwl_tx_queue *txq,
-					int tx_fifo_id, int scd_retry)
-{
-	int txq_id = txq->q.id;
-
-	/* Find out whether to activate Tx queue */
-	int active = test_bit(txq_id, &priv->txq_ctx_active_msk) ? 1 : 0;
-
-	/* Set up and activate */
-	iwl_write_prph(priv, IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-			 (active << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE) |
-			 (tx_fifo_id << IWL49_SCD_QUEUE_STTS_REG_POS_TXF) |
-			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_WSL) |
-			 (scd_retry << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACK) |
-			 IWL49_SCD_QUEUE_STTS_REG_MSK);
-
-	txq->sched_retry = scd_retry;
-
-	IWL_DEBUG_INFO(priv, "%s %s Queue %d on AC %d\n",
-		       active ? "Activate" : "Deactivate",
-		       scd_retry ? "BA" : "AC", txq_id, tx_fifo_id);
-}
-
-static const s8 default_queue_to_tx_fifo[] = {
-	IWL_TX_FIFO_VO,
-	IWL_TX_FIFO_VI,
-	IWL_TX_FIFO_BE,
-	IWL_TX_FIFO_BK,
-	IWL49_CMD_FIFO_NUM,
-	IWL_TX_FIFO_UNUSED,
-	IWL_TX_FIFO_UNUSED,
-};
-
-static int iwl4965_alive_notify(struct iwl_priv *priv)
-{
-	u32 a;
-	unsigned long flags;
-	int i, chan;
-	u32 reg_val;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* 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;
-	for (; a < priv->scd_base_addr + IWL49_SCD_TX_STTS_BITMAP_OFFSET; a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-	for (; a < priv->scd_base_addr + IWL49_SCD_TRANSLATE_TBL_OFFSET; a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-	for (; a < priv->scd_base_addr +
-	       IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(priv->hw_params.max_txq_num); a += 4)
-		iwl_write_targ_mem(priv, a, 0);
-
-	/* Tel 4965 where to find Tx byte count tables */
-	iwl_write_prph(priv, IWL49_SCD_DRAM_BASE_ADDR,
-			priv->scd_bc_tbls.dma >> 10);
-
-	/* Enable DMA channel */
-	for (chan = 0; chan < FH49_TCSR_CHNL_NUM ; chan++)
-		iwl_write_direct32(priv, FH_TCSR_CHNL_TX_CONFIG_REG(chan),
-				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CHNL_ENABLE |
-				FH_TCSR_TX_CONFIG_REG_VAL_DMA_CREDIT_ENABLE);
-
-	/* Update FH chicken bits */
-	reg_val = iwl_read_direct32(priv, FH_TX_CHICKEN_BITS_REG);
-	iwl_write_direct32(priv, FH_TX_CHICKEN_BITS_REG,
-			   reg_val | FH_TX_CHICKEN_BITS_SCD_AUTO_RETRY_EN);
-
-	/* Disable chain mode for all queues */
-	iwl_write_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, 0);
-
-	/* Initialize each Tx queue (including the command queue) */
-	for (i = 0; i < priv->hw_params.max_txq_num; i++) {
-
-		/* TFD circular buffer read/write indexes */
-		iwl_write_prph(priv, IWL49_SCD_QUEUE_RDPTR(i), 0);
-		iwl_write_direct32(priv, HBUS_TARG_WRPTR, 0 | (i << 8));
-
-		/* Max Tx Window size for Scheduler-ACK mode */
-		iwl_write_targ_mem(priv, priv->scd_base_addr +
-				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i),
-				(SCD_WIN_SIZE <<
-				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
-				IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-		/* Frame limit */
-		iwl_write_targ_mem(priv, priv->scd_base_addr +
-				IWL49_SCD_CONTEXT_QUEUE_OFFSET(i) +
-				sizeof(u32),
-				(SCD_FRAME_LIMIT <<
-				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS) &
-				IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-	}
-	iwl_write_prph(priv, IWL49_SCD_INTERRUPT_MASK,
-				 (1 << priv->hw_params.max_txq_num) - 1);
-
-	/* Activate all Tx DMA/FIFO channels */
-	priv->cfg->ops->lib->txq_set_sched(priv, IWL_MASK(0, 6));
-
-	iwl4965_set_wr_ptrs(priv, IWL_DEFAULT_CMD_QUEUE_NUM, 0);
-
-	/* make sure all queue are not stopped */
-	memset(&priv->queue_stopped[0], 0, sizeof(priv->queue_stopped));
-	for (i = 0; i < 4; i++)
-		atomic_set(&priv->queue_stop_count[i], 0);
-
-	/* reset to 0 to enable all the queue first */
-	priv->txq_ctx_active_msk = 0;
-	/* Map each Tx/cmd queue to its corresponding fifo */
-	BUILD_BUG_ON(ARRAY_SIZE(default_queue_to_tx_fifo) != 7);
-
-	for (i = 0; i < ARRAY_SIZE(default_queue_to_tx_fifo); i++) {
-		int ac = default_queue_to_tx_fifo[i];
-
-		iwl_txq_ctx_activate(priv, i);
-
-		if (ac == IWL_TX_FIFO_UNUSED)
-			continue;
-
-		iwl4965_tx_queue_set_status(priv, &priv->txq[i], ac, 0);
-	}
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-static struct iwl_sensitivity_ranges iwl4965_sensitivity = {
-	.min_nrg_cck = 97,
-	.max_nrg_cck = 0, /* not used, set to 0 */
-
-	.auto_corr_min_ofdm = 85,
-	.auto_corr_min_ofdm_mrc = 170,
-	.auto_corr_min_ofdm_x1 = 105,
-	.auto_corr_min_ofdm_mrc_x1 = 220,
-
-	.auto_corr_max_ofdm = 120,
-	.auto_corr_max_ofdm_mrc = 210,
-	.auto_corr_max_ofdm_x1 = 140,
-	.auto_corr_max_ofdm_mrc_x1 = 270,
-
-	.auto_corr_min_cck = 125,
-	.auto_corr_max_cck = 200,
-	.auto_corr_min_cck_mrc = 200,
-	.auto_corr_max_cck_mrc = 400,
-
-	.nrg_th_cck = 100,
-	.nrg_th_ofdm = 100,
-
-	.barker_corr_th_min = 190,
-	.barker_corr_th_min_mrc = 390,
-	.nrg_th_cca = 62,
-};
-
-static void iwl4965_set_ct_threshold(struct iwl_priv *priv)
-{
-	/* want Kelvin */
-	priv->hw_params.ct_kill_threshold =
-		CELSIUS_TO_KELVIN(CT_KILL_THRESHOLD_LEGACY);
-}
-
-/**
- * iwl4965_hw_set_hw_params
- *
- * Called when initializing driver
- */
-static int iwl4965_hw_set_hw_params(struct iwl_priv *priv)
-{
-	if (priv->cfg->mod_params->num_of_queues >= IWL_MIN_NUM_QUEUES &&
-	    priv->cfg->mod_params->num_of_queues <= IWL49_NUM_QUEUES)
-		priv->cfg->base_params->num_of_queues =
-			priv->cfg->mod_params->num_of_queues;
-
-	priv->hw_params.max_txq_num = priv->cfg->base_params->num_of_queues;
-	priv->hw_params.dma_chnl_num = FH49_TCSR_CHNL_NUM;
-	priv->hw_params.scd_bc_tbls_size =
-			priv->cfg->base_params->num_of_queues *
-			sizeof(struct iwl4965_scd_bc_tbl);
-	priv->hw_params.tfd_size = sizeof(struct iwl_tfd);
-	priv->hw_params.max_stations = IWL4965_STATION_COUNT;
-	priv->contexts[IWL_RXON_CTX_BSS].bcast_sta_id = IWL4965_BROADCAST_ID;
-	priv->hw_params.max_data_size = IWL49_RTC_DATA_SIZE;
-	priv->hw_params.max_inst_size = IWL49_RTC_INST_SIZE;
-	priv->hw_params.max_bsm_size = BSM_SRAM_SIZE;
-	priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_5GHZ);
-
-	priv->hw_params.rx_wrt_ptr_reg = FH_RSCSR_CHNL0_WPTR;
-
-	priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
-	priv->hw_params.rx_chains_num = num_of_ant(priv->cfg->valid_rx_ant);
-	priv->hw_params.valid_tx_ant = priv->cfg->valid_tx_ant;
-	priv->hw_params.valid_rx_ant = priv->cfg->valid_rx_ant;
-
-	iwl4965_set_ct_threshold(priv);
-
-	priv->hw_params.sens = &iwl4965_sensitivity;
-	priv->hw_params.beacon_time_tsf_bits = IWLAGN_EXT_BEACON_TIME_POS;
-
-	return 0;
-}
-
-static s32 iwl4965_math_div_round(s32 num, s32 denom, s32 *res)
-{
-	s32 sign = 1;
-
-	if (num < 0) {
-		sign = -sign;
-		num = -num;
-	}
-	if (denom < 0) {
-		sign = -sign;
-		denom = -denom;
-	}
-	*res = 1;
-	*res = ((num * 2 + denom) / (denom * 2)) * sign;
-
-	return 1;
-}
-
-/**
- * iwl4965_get_voltage_compensation - Power supply voltage comp for txpower
- *
- * Determines power supply voltage compensation for txpower calculations.
- * Returns number of 1/2-dB steps to subtract from gain table index,
- * to compensate for difference between power supply voltage during
- * factory measurements, vs. current power supply voltage.
- *
- * Voltage indication is higher for lower voltage.
- * Lower voltage requires more gain (lower gain table index).
- */
-static s32 iwl4965_get_voltage_compensation(s32 eeprom_voltage,
-					    s32 current_voltage)
-{
-	s32 comp = 0;
-
-	if ((TX_POWER_IWL_ILLEGAL_VOLTAGE == eeprom_voltage) ||
-	    (TX_POWER_IWL_ILLEGAL_VOLTAGE == current_voltage))
-		return 0;
-
-	iwl4965_math_div_round(current_voltage - eeprom_voltage,
-			       TX_POWER_IWL_VOLTAGE_CODES_PER_03V, &comp);
-
-	if (current_voltage > eeprom_voltage)
-		comp *= 2;
-	if ((comp < -2) || (comp > 2))
-		comp = 0;
-
-	return comp;
-}
-
-static s32 iwl4965_get_tx_atten_grp(u16 channel)
-{
-	if (channel >= CALIB_IWL_TX_ATTEN_GR5_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR5_LCH)
-		return CALIB_CH_GROUP_5;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR1_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR1_LCH)
-		return CALIB_CH_GROUP_1;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR2_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR2_LCH)
-		return CALIB_CH_GROUP_2;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR3_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR3_LCH)
-		return CALIB_CH_GROUP_3;
-
-	if (channel >= CALIB_IWL_TX_ATTEN_GR4_FCH &&
-	    channel <= CALIB_IWL_TX_ATTEN_GR4_LCH)
-		return CALIB_CH_GROUP_4;
-
-	return -1;
-}
-
-static u32 iwl4965_get_sub_band(const struct iwl_priv *priv, u32 channel)
-{
-	s32 b = -1;
-
-	for (b = 0; b < EEPROM_TX_POWER_BANDS; b++) {
-		if (priv->calib_info->band_info[b].ch_from == 0)
-			continue;
-
-		if ((channel >= priv->calib_info->band_info[b].ch_from)
-		    && (channel <= priv->calib_info->band_info[b].ch_to))
-			break;
-	}
-
-	return b;
-}
-
-static s32 iwl4965_interpolate_value(s32 x, s32 x1, s32 y1, s32 x2, s32 y2)
-{
-	s32 val;
-
-	if (x2 == x1)
-		return y1;
-	else {
-		iwl4965_math_div_round((x2 - x) * (y1 - y2), (x2 - x1), &val);
-		return val + y2;
-	}
-}
-
-/**
- * iwl4965_interpolate_chan - Interpolate factory measurements for one channel
- *
- * Interpolates factory measurements from the two sample channels within a
- * sub-band, to apply to channel of interest.  Interpolation is proportional to
- * differences in channel frequencies, which is proportional to differences
- * in channel number.
- */
-static int iwl4965_interpolate_chan(struct iwl_priv *priv, u32 channel,
-				    struct iwl_eeprom_calib_ch_info *chan_info)
-{
-	s32 s = -1;
-	u32 c;
-	u32 m;
-	const struct iwl_eeprom_calib_measure *m1;
-	const struct iwl_eeprom_calib_measure *m2;
-	struct iwl_eeprom_calib_measure *omeas;
-	u32 ch_i1;
-	u32 ch_i2;
-
-	s = iwl4965_get_sub_band(priv, channel);
-	if (s >= EEPROM_TX_POWER_BANDS) {
-		IWL_ERR(priv, "Tx Power can not find channel %d\n", channel);
-		return -1;
-	}
-
-	ch_i1 = priv->calib_info->band_info[s].ch1.ch_num;
-	ch_i2 = priv->calib_info->band_info[s].ch2.ch_num;
-	chan_info->ch_num = (u8) channel;
-
-	IWL_DEBUG_TXPOWER(priv, "channel %d subband %d factory cal ch %d & %d\n",
-			  channel, s, ch_i1, ch_i2);
-
-	for (c = 0; c < EEPROM_TX_POWER_TX_CHAINS; c++) {
-		for (m = 0; m < EEPROM_TX_POWER_MEASUREMENTS; m++) {
-			m1 = &(priv->calib_info->band_info[s].ch1.
-			       measurements[c][m]);
-			m2 = &(priv->calib_info->band_info[s].ch2.
-			       measurements[c][m]);
-			omeas = &(chan_info->measurements[c][m]);
-
-			omeas->actual_pow =
-			    (u8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->actual_pow,
-							   ch_i2,
-							   m2->actual_pow);
-			omeas->gain_idx =
-			    (u8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->gain_idx, ch_i2,
-							   m2->gain_idx);
-			omeas->temperature =
-			    (u8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->temperature,
-							   ch_i2,
-							   m2->temperature);
-			omeas->pa_det =
-			    (s8) iwl4965_interpolate_value(channel, ch_i1,
-							   m1->pa_det, ch_i2,
-							   m2->pa_det);
-
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d AP1=%d AP2=%d AP=%d\n", c, m,
-				m1->actual_pow, m2->actual_pow, omeas->actual_pow);
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d NI1=%d NI2=%d NI=%d\n", c, m,
-				m1->gain_idx, m2->gain_idx, omeas->gain_idx);
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d PA1=%d PA2=%d PA=%d\n", c, m,
-				m1->pa_det, m2->pa_det, omeas->pa_det);
-			IWL_DEBUG_TXPOWER(priv,
-				"chain %d meas %d  T1=%d  T2=%d  T=%d\n", c, m,
-				m1->temperature, m2->temperature,
-				omeas->temperature);
-		}
-	}
-
-	return 0;
-}
-
-/* bit-rate-dependent table to prevent Tx distortion, in half-dB units,
- * for OFDM 6, 12, 18, 24, 36, 48, 54, 60 MBit, and CCK all rates. */
-static s32 back_off_table[] = {
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 20 MHz */
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 20 MHz */
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM SISO 40 MHz */
-	10, 10, 10, 10, 10, 15, 17, 20,	/* OFDM MIMO 40 MHz */
-	10			/* CCK */
-};
-
-/* Thermal compensation values for txpower for various frequency ranges ...
- *   ratios from 3:1 to 4.5:1 of degrees (Celsius) per half-dB gain adjust */
-static struct iwl4965_txpower_comp_entry {
-	s32 degrees_per_05db_a;
-	s32 degrees_per_05db_a_denom;
-} tx_power_cmp_tble[CALIB_CH_GROUP_MAX] = {
-	{9, 2},			/* group 0 5.2, ch  34-43 */
-	{4, 1},			/* group 1 5.2, ch  44-70 */
-	{4, 1},			/* group 2 5.2, ch  71-124 */
-	{4, 1},			/* group 3 5.2, ch 125-200 */
-	{3, 1}			/* group 4 2.4, ch   all */
-};
-
-static s32 get_min_power_index(s32 rate_power_index, u32 band)
-{
-	if (!band) {
-		if ((rate_power_index & 7) <= 4)
-			return MIN_TX_GAIN_INDEX_52GHZ_EXT;
-	}
-	return MIN_TX_GAIN_INDEX;
-}
-
-struct gain_entry {
-	u8 dsp;
-	u8 radio;
-};
-
-static const struct gain_entry gain_table[2][108] = {
-	/* 5.2GHz power gain index table */
-	{
-	 {123, 0x3F},		/* highest txpower */
-	 {117, 0x3F},
-	 {110, 0x3F},
-	 {104, 0x3F},
-	 {98, 0x3F},
-	 {110, 0x3E},
-	 {104, 0x3E},
-	 {98, 0x3E},
-	 {110, 0x3D},
-	 {104, 0x3D},
-	 {98, 0x3D},
-	 {110, 0x3C},
-	 {104, 0x3C},
-	 {98, 0x3C},
-	 {110, 0x3B},
-	 {104, 0x3B},
-	 {98, 0x3B},
-	 {110, 0x3A},
-	 {104, 0x3A},
-	 {98, 0x3A},
-	 {110, 0x39},
-	 {104, 0x39},
-	 {98, 0x39},
-	 {110, 0x38},
-	 {104, 0x38},
-	 {98, 0x38},
-	 {110, 0x37},
-	 {104, 0x37},
-	 {98, 0x37},
-	 {110, 0x36},
-	 {104, 0x36},
-	 {98, 0x36},
-	 {110, 0x35},
-	 {104, 0x35},
-	 {98, 0x35},
-	 {110, 0x34},
-	 {104, 0x34},
-	 {98, 0x34},
-	 {110, 0x33},
-	 {104, 0x33},
-	 {98, 0x33},
-	 {110, 0x32},
-	 {104, 0x32},
-	 {98, 0x32},
-	 {110, 0x31},
-	 {104, 0x31},
-	 {98, 0x31},
-	 {110, 0x30},
-	 {104, 0x30},
-	 {98, 0x30},
-	 {110, 0x25},
-	 {104, 0x25},
-	 {98, 0x25},
-	 {110, 0x24},
-	 {104, 0x24},
-	 {98, 0x24},
-	 {110, 0x23},
-	 {104, 0x23},
-	 {98, 0x23},
-	 {110, 0x22},
-	 {104, 0x18},
-	 {98, 0x18},
-	 {110, 0x17},
-	 {104, 0x17},
-	 {98, 0x17},
-	 {110, 0x16},
-	 {104, 0x16},
-	 {98, 0x16},
-	 {110, 0x15},
-	 {104, 0x15},
-	 {98, 0x15},
-	 {110, 0x14},
-	 {104, 0x14},
-	 {98, 0x14},
-	 {110, 0x13},
-	 {104, 0x13},
-	 {98, 0x13},
-	 {110, 0x12},
-	 {104, 0x08},
-	 {98, 0x08},
-	 {110, 0x07},
-	 {104, 0x07},
-	 {98, 0x07},
-	 {110, 0x06},
-	 {104, 0x06},
-	 {98, 0x06},
-	 {110, 0x05},
-	 {104, 0x05},
-	 {98, 0x05},
-	 {110, 0x04},
-	 {104, 0x04},
-	 {98, 0x04},
-	 {110, 0x03},
-	 {104, 0x03},
-	 {98, 0x03},
-	 {110, 0x02},
-	 {104, 0x02},
-	 {98, 0x02},
-	 {110, 0x01},
-	 {104, 0x01},
-	 {98, 0x01},
-	 {110, 0x00},
-	 {104, 0x00},
-	 {98, 0x00},
-	 {93, 0x00},
-	 {88, 0x00},
-	 {83, 0x00},
-	 {78, 0x00},
-	 },
-	/* 2.4GHz power gain index table */
-	{
-	 {110, 0x3f},		/* highest txpower */
-	 {104, 0x3f},
-	 {98, 0x3f},
-	 {110, 0x3e},
-	 {104, 0x3e},
-	 {98, 0x3e},
-	 {110, 0x3d},
-	 {104, 0x3d},
-	 {98, 0x3d},
-	 {110, 0x3c},
-	 {104, 0x3c},
-	 {98, 0x3c},
-	 {110, 0x3b},
-	 {104, 0x3b},
-	 {98, 0x3b},
-	 {110, 0x3a},
-	 {104, 0x3a},
-	 {98, 0x3a},
-	 {110, 0x39},
-	 {104, 0x39},
-	 {98, 0x39},
-	 {110, 0x38},
-	 {104, 0x38},
-	 {98, 0x38},
-	 {110, 0x37},
-	 {104, 0x37},
-	 {98, 0x37},
-	 {110, 0x36},
-	 {104, 0x36},
-	 {98, 0x36},
-	 {110, 0x35},
-	 {104, 0x35},
-	 {98, 0x35},
-	 {110, 0x34},
-	 {104, 0x34},
-	 {98, 0x34},
-	 {110, 0x33},
-	 {104, 0x33},
-	 {98, 0x33},
-	 {110, 0x32},
-	 {104, 0x32},
-	 {98, 0x32},
-	 {110, 0x31},
-	 {104, 0x31},
-	 {98, 0x31},
-	 {110, 0x30},
-	 {104, 0x30},
-	 {98, 0x30},
-	 {110, 0x6},
-	 {104, 0x6},
-	 {98, 0x6},
-	 {110, 0x5},
-	 {104, 0x5},
-	 {98, 0x5},
-	 {110, 0x4},
-	 {104, 0x4},
-	 {98, 0x4},
-	 {110, 0x3},
-	 {104, 0x3},
-	 {98, 0x3},
-	 {110, 0x2},
-	 {104, 0x2},
-	 {98, 0x2},
-	 {110, 0x1},
-	 {104, 0x1},
-	 {98, 0x1},
-	 {110, 0x0},
-	 {104, 0x0},
-	 {98, 0x0},
-	 {97, 0},
-	 {96, 0},
-	 {95, 0},
-	 {94, 0},
-	 {93, 0},
-	 {92, 0},
-	 {91, 0},
-	 {90, 0},
-	 {89, 0},
-	 {88, 0},
-	 {87, 0},
-	 {86, 0},
-	 {85, 0},
-	 {84, 0},
-	 {83, 0},
-	 {82, 0},
-	 {81, 0},
-	 {80, 0},
-	 {79, 0},
-	 {78, 0},
-	 {77, 0},
-	 {76, 0},
-	 {75, 0},
-	 {74, 0},
-	 {73, 0},
-	 {72, 0},
-	 {71, 0},
-	 {70, 0},
-	 {69, 0},
-	 {68, 0},
-	 {67, 0},
-	 {66, 0},
-	 {65, 0},
-	 {64, 0},
-	 {63, 0},
-	 {62, 0},
-	 {61, 0},
-	 {60, 0},
-	 {59, 0},
-	 }
-};
-
-static int iwl4965_fill_txpower_tbl(struct iwl_priv *priv, u8 band, u16 channel,
-				    u8 is_ht40, u8 ctrl_chan_high,
-				    struct iwl4965_tx_power_db *tx_power_tbl)
-{
-	u8 saturation_power;
-	s32 target_power;
-	s32 user_target_power;
-	s32 power_limit;
-	s32 current_temp;
-	s32 reg_limit;
-	s32 current_regulatory;
-	s32 txatten_grp = CALIB_CH_GROUP_MAX;
-	int i;
-	int c;
-	const struct iwl_channel_info *ch_info = NULL;
-	struct iwl_eeprom_calib_ch_info ch_eeprom_info;
-	const struct iwl_eeprom_calib_measure *measurement;
-	s16 voltage;
-	s32 init_voltage;
-	s32 voltage_compensation;
-	s32 degrees_per_05db_num;
-	s32 degrees_per_05db_denom;
-	s32 factory_temp;
-	s32 temperature_comp[2];
-	s32 factory_gain_index[2];
-	s32 factory_actual_pwr[2];
-	s32 power_index;
-
-	/* tx_power_user_lmt is in dBm, convert to half-dBm (half-dB units
-	 *   are used for indexing into txpower table) */
-	user_target_power = 2 * priv->tx_power_user_lmt;
-
-	/* Get current (RXON) channel, band, width */
-	IWL_DEBUG_TXPOWER(priv, "chan %d band %d is_ht40 %d\n", channel, band,
-			  is_ht40);
-
-	ch_info = iwl_get_channel_info(priv, priv->band, channel);
-
-	if (!is_channel_valid(ch_info))
-		return -EINVAL;
-
-	/* get txatten group, used to select 1) thermal txpower adjustment
-	 *   and 2) mimo txpower balance between Tx chains. */
-	txatten_grp = iwl4965_get_tx_atten_grp(channel);
-	if (txatten_grp < 0) {
-		IWL_ERR(priv, "Can't find txatten group for channel %d.\n",
-			  channel);
-		return -EINVAL;
-	}
-
-	IWL_DEBUG_TXPOWER(priv, "channel %d belongs to txatten group %d\n",
-			  channel, txatten_grp);
-
-	if (is_ht40) {
-		if (ctrl_chan_high)
-			channel -= 2;
-		else
-			channel += 2;
-	}
-
-	/* hardware txpower limits ...
-	 * saturation (clipping distortion) txpowers are in half-dBm */
-	if (band)
-		saturation_power = priv->calib_info->saturation_power24;
-	else
-		saturation_power = priv->calib_info->saturation_power52;
-
-	if (saturation_power < IWL_TX_POWER_SATURATION_MIN ||
-	    saturation_power > IWL_TX_POWER_SATURATION_MAX) {
-		if (band)
-			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_24;
-		else
-			saturation_power = IWL_TX_POWER_DEFAULT_SATURATION_52;
-	}
-
-	/* regulatory txpower limits ... reg_limit values are in half-dBm,
-	 *   max_power_avg values are in dBm, convert * 2 */
-	if (is_ht40)
-		reg_limit = ch_info->ht40_max_power_avg * 2;
-	else
-		reg_limit = ch_info->max_power_avg * 2;
-
-	if ((reg_limit < IWL_TX_POWER_REGULATORY_MIN) ||
-	    (reg_limit > IWL_TX_POWER_REGULATORY_MAX)) {
-		if (band)
-			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_24;
-		else
-			reg_limit = IWL_TX_POWER_DEFAULT_REGULATORY_52;
-	}
-
-	/* Interpolate txpower calibration values for this channel,
-	 *   based on factory calibration tests on spaced channels. */
-	iwl4965_interpolate_chan(priv, channel, &ch_eeprom_info);
-
-	/* calculate tx gain adjustment based on power supply voltage */
-	voltage = le16_to_cpu(priv->calib_info->voltage);
-	init_voltage = (s32)le32_to_cpu(priv->card_alive_init.voltage);
-	voltage_compensation =
-	    iwl4965_get_voltage_compensation(voltage, init_voltage);
-
-	IWL_DEBUG_TXPOWER(priv, "curr volt %d eeprom volt %d volt comp %d\n",
-			  init_voltage,
-			  voltage, voltage_compensation);
-
-	/* get current temperature (Celsius) */
-	current_temp = max(priv->temperature, IWL_TX_POWER_TEMPERATURE_MIN);
-	current_temp = min(priv->temperature, IWL_TX_POWER_TEMPERATURE_MAX);
-	current_temp = KELVIN_TO_CELSIUS(current_temp);
-
-	/* select thermal txpower adjustment params, based on channel group
-	 *   (same frequency group used for mimo txatten adjustment) */
-	degrees_per_05db_num =
-	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a;
-	degrees_per_05db_denom =
-	    tx_power_cmp_tble[txatten_grp].degrees_per_05db_a_denom;
-
-	/* get per-chain txpower values from factory measurements */
-	for (c = 0; c < 2; c++) {
-		measurement = &ch_eeprom_info.measurements[c][1];
-
-		/* txgain adjustment (in half-dB steps) based on difference
-		 *   between factory and current temperature */
-		factory_temp = measurement->temperature;
-		iwl4965_math_div_round((current_temp - factory_temp) *
-				       degrees_per_05db_denom,
-				       degrees_per_05db_num,
-				       &temperature_comp[c]);
-
-		factory_gain_index[c] = measurement->gain_idx;
-		factory_actual_pwr[c] = measurement->actual_pow;
-
-		IWL_DEBUG_TXPOWER(priv, "chain = %d\n", c);
-		IWL_DEBUG_TXPOWER(priv, "fctry tmp %d, "
-				  "curr tmp %d, comp %d steps\n",
-				  factory_temp, current_temp,
-				  temperature_comp[c]);
-
-		IWL_DEBUG_TXPOWER(priv, "fctry idx %d, fctry pwr %d\n",
-				  factory_gain_index[c],
-				  factory_actual_pwr[c]);
-	}
-
-	/* for each of 33 bit-rates (including 1 for CCK) */
-	for (i = 0; i < POWER_TABLE_NUM_ENTRIES; i++) {
-		u8 is_mimo_rate;
-		union iwl4965_tx_power_dual_stream tx_power;
-
-		/* for mimo, reduce each chain's txpower by half
-		 * (3dB, 6 steps), so total output power is regulatory
-		 * compliant. */
-		if (i & 0x8) {
-			current_regulatory = reg_limit -
-			    IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION;
-			is_mimo_rate = 1;
-		} else {
-			current_regulatory = reg_limit;
-			is_mimo_rate = 0;
-		}
-
-		/* find txpower limit, either hardware or regulatory */
-		power_limit = saturation_power - back_off_table[i];
-		if (power_limit > current_regulatory)
-			power_limit = current_regulatory;
-
-		/* reduce user's txpower request if necessary
-		 * for this rate on this channel */
-		target_power = user_target_power;
-		if (target_power > power_limit)
-			target_power = power_limit;
-
-		IWL_DEBUG_TXPOWER(priv, "rate %d sat %d reg %d usr %d tgt %d\n",
-				  i, saturation_power - back_off_table[i],
-				  current_regulatory, user_target_power,
-				  target_power);
-
-		/* for each of 2 Tx chains (radio transmitters) */
-		for (c = 0; c < 2; c++) {
-			s32 atten_value;
-
-			if (is_mimo_rate)
-				atten_value =
-				    (s32)le32_to_cpu(priv->card_alive_init.
-				    tx_atten[txatten_grp][c]);
-			else
-				atten_value = 0;
-
-			/* calculate index; higher index means lower txpower */
-			power_index = (u8) (factory_gain_index[c] -
-					    (target_power -
-					     factory_actual_pwr[c]) -
-					    temperature_comp[c] -
-					    voltage_compensation +
-					    atten_value);
-
-/*			IWL_DEBUG_TXPOWER(priv, "calculated txpower index %d\n",
-						power_index); */
-
-			if (power_index < get_min_power_index(i, band))
-				power_index = get_min_power_index(i, band);
-
-			/* adjust 5 GHz index to support negative indexes */
-			if (!band)
-				power_index += 9;
-
-			/* CCK, rate 32, reduce txpower for CCK */
-			if (i == POWER_TABLE_CCK_ENTRY)
-				power_index +=
-				    IWL_TX_POWER_CCK_COMPENSATION_C_STEP;
-
-			/* stay within the table! */
-			if (power_index > 107) {
-				IWL_WARN(priv, "txpower index %d > 107\n",
-					    power_index);
-				power_index = 107;
-			}
-			if (power_index < 0) {
-				IWL_WARN(priv, "txpower index %d < 0\n",
-					    power_index);
-				power_index = 0;
-			}
-
-			/* fill txpower command for this rate/chain */
-			tx_power.s.radio_tx_gain[c] =
-				gain_table[band][power_index].radio;
-			tx_power.s.dsp_predis_atten[c] =
-				gain_table[band][power_index].dsp;
-
-			IWL_DEBUG_TXPOWER(priv, "chain %d mimo %d index %d "
-					  "gain 0x%02x dsp %d\n",
-					  c, atten_value, power_index,
-					tx_power.s.radio_tx_gain[c],
-					tx_power.s.dsp_predis_atten[c]);
-		} /* for each chain */
-
-		tx_power_tbl->power_tbl[i].dw = cpu_to_le32(tx_power.dw);
-
-	} /* for each rate */
-
-	return 0;
-}
-
-/**
- * iwl4965_send_tx_power - Configure the TXPOWER level user limit
- *
- * Uses the active RXON for channel, band, and characteristics (ht40, high)
- * The power limit is taken from priv->tx_power_user_lmt.
- */
-static int iwl4965_send_tx_power(struct iwl_priv *priv)
-{
-	struct iwl4965_txpowertable_cmd cmd = { 0 };
-	int ret;
-	u8 band = 0;
-	bool is_ht40 = false;
-	u8 ctrl_chan_high = 0;
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->status),
-		      "TX Power requested while scanning!\n"))
-		return -EAGAIN;
-
-	band = priv->band == IEEE80211_BAND_2GHZ;
-
-	is_ht40 = is_ht40_channel(ctx->active.flags);
-
-	if (is_ht40 && (ctx->active.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
-		ctrl_chan_high = 1;
-
-	cmd.band = band;
-	cmd.channel = ctx->active.channel;
-
-	ret = iwl4965_fill_txpower_tbl(priv, band,
-				le16_to_cpu(ctx->active.channel),
-				is_ht40, ctrl_chan_high, &cmd.tx_power);
-	if (ret)
-		goto out;
-
-	ret = iwl_send_cmd_pdu(priv, REPLY_TX_PWR_TABLE_CMD, sizeof(cmd), &cmd);
-
-out:
-	return ret;
-}
-
-static int iwl4965_send_rxon_assoc(struct iwl_priv *priv,
-				   struct iwl_rxon_context *ctx)
-{
-	int ret = 0;
-	struct iwl4965_rxon_assoc_cmd rxon_assoc;
-	const struct iwl_rxon_cmd *rxon1 = &ctx->staging;
-	const struct iwl_rxon_cmd *rxon2 = &ctx->active;
-
-	if ((rxon1->flags == rxon2->flags) &&
-	    (rxon1->filter_flags == rxon2->filter_flags) &&
-	    (rxon1->cck_basic_rates == rxon2->cck_basic_rates) &&
-	    (rxon1->ofdm_ht_single_stream_basic_rates ==
-	     rxon2->ofdm_ht_single_stream_basic_rates) &&
-	    (rxon1->ofdm_ht_dual_stream_basic_rates ==
-	     rxon2->ofdm_ht_dual_stream_basic_rates) &&
-	    (rxon1->rx_chain == rxon2->rx_chain) &&
-	    (rxon1->ofdm_basic_rates == rxon2->ofdm_basic_rates)) {
-		IWL_DEBUG_INFO(priv, "Using current RXON_ASSOC.  Not resending.\n");
-		return 0;
-	}
-
-	rxon_assoc.flags = ctx->staging.flags;
-	rxon_assoc.filter_flags = ctx->staging.filter_flags;
-	rxon_assoc.ofdm_basic_rates = ctx->staging.ofdm_basic_rates;
-	rxon_assoc.cck_basic_rates = ctx->staging.cck_basic_rates;
-	rxon_assoc.reserved = 0;
-	rxon_assoc.ofdm_ht_single_stream_basic_rates =
-	    ctx->staging.ofdm_ht_single_stream_basic_rates;
-	rxon_assoc.ofdm_ht_dual_stream_basic_rates =
-	    ctx->staging.ofdm_ht_dual_stream_basic_rates;
-	rxon_assoc.rx_chain_select_flags = ctx->staging.rx_chain;
-
-	ret = iwl_send_cmd_pdu_async(priv, REPLY_RXON_ASSOC,
-				     sizeof(rxon_assoc), &rxon_assoc, NULL);
-	if (ret)
-		return ret;
-
-	return ret;
-}
-
-static int iwl4965_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	/* cast away the const for active_rxon in this function */
-	struct iwl_rxon_cmd *active_rxon = (void *)&ctx->active;
-	int ret;
-	bool new_assoc =
-		!!(ctx->staging.filter_flags & RXON_FILTER_ASSOC_MSK);
-
-	if (!iwl_is_alive(priv))
-		return -EBUSY;
-
-	if (!ctx->is_active)
-		return 0;
-
-	/* always get timestamp with Rx frame */
-	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
-
-	ret = iwl_check_rxon_cmd(priv, ctx);
-	if (ret) {
-		IWL_ERR(priv, "Invalid RXON configuration.  Not committing.\n");
-		return -EINVAL;
-	}
-
-	/*
-	 * receive commit_rxon request
-	 * abort any previous channel switch if still in process
-	 */
-	if (priv->switch_rxon.switch_in_progress &&
-	    (priv->switch_rxon.channel != ctx->staging.channel)) {
-		IWL_DEBUG_11H(priv, "abort channel switch on %d\n",
-		      le16_to_cpu(priv->switch_rxon.channel));
-		iwl_chswitch_done(priv, false);
-	}
-
-	/* If we don't need to send a full RXON, we can use
-	 * iwl_rxon_assoc_cmd which is used to reconfigure filter
-	 * and other flags for the current radio configuration. */
-	if (!iwl_full_rxon_required(priv, ctx)) {
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Error setting RXON_ASSOC (%d)\n", ret);
-			return ret;
-		}
-
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_print_rx_config_cmd(priv, ctx);
-		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_ctx(ctx) && new_assoc) {
-		IWL_DEBUG_INFO(priv, "Toggling associated bit on current RXON\n");
-		active_rxon->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-				       sizeof(struct iwl_rxon_cmd),
-				       active_rxon);
-
-		/* If the mask clearing failed then we set
-		 * active_rxon back to what it was previously */
-		if (ret) {
-			active_rxon->filter_flags |= RXON_FILTER_ASSOC_MSK;
-			IWL_ERR(priv, "Error clearing ASSOC_MSK (%d)\n", ret);
-			return ret;
-		}
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-
-	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(ctx->staging.channel),
-		       ctx->staging.bssid_addr);
-
-	iwl_set_rxon_hwcrypto(priv, ctx, !priv->cfg->mod_params->sw_crypto);
-
-	/* Apply the new configuration
-	 * RXON unassoc clears the station table in uCode so restoration of
-	 * stations is needed after it (the RXON command) completes
-	 */
-	if (!new_assoc) {
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		IWL_DEBUG_INFO(priv, "Return from !new_assoc RXON.\n");
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-		iwl_clear_ucode_stations(priv, ctx);
-		iwl_restore_stations(priv, ctx);
-		ret = iwl_restore_default_wep_keys(priv, ctx);
-		if (ret) {
-			IWL_ERR(priv, "Failed to restore WEP keys (%d)\n", ret);
-			return ret;
-		}
-	}
-	if (new_assoc) {
-		priv->start_calib = 0;
-		/* Apply the new configuration
-		 * RXON assoc doesn't clear the station table in uCode,
-		 */
-		ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd,
-			      sizeof(struct iwl_rxon_cmd), &ctx->staging);
-		if (ret) {
-			IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
-			return ret;
-		}
-		memcpy(active_rxon, &ctx->staging, sizeof(*active_rxon));
-	}
-	iwl_print_rx_config_cmd(priv, ctx);
-
-	iwl_init_sensitivity(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 */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
-	if (ret) {
-		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
-		return ret;
-	}
-
-	return 0;
-}
-
-static int iwl4965_hw_channel_switch(struct iwl_priv *priv,
-				     struct ieee80211_channel_switch *ch_switch)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	int rc;
-	u8 band = 0;
-	bool is_ht40 = false;
-	u8 ctrl_chan_high = 0;
-	struct iwl4965_channel_switch_cmd cmd;
-	const struct iwl_channel_info *ch_info;
-	u32 switch_time_in_usec, ucode_switch_time;
-	u16 ch;
-	u32 tsf_low;
-	u8 switch_count;
-	u16 beacon_interval = le16_to_cpu(ctx->timing.beacon_interval);
-	struct ieee80211_vif *vif = ctx->vif;
-	band = priv->band == IEEE80211_BAND_2GHZ;
-
-	is_ht40 = is_ht40_channel(ctx->staging.flags);
-
-	if (is_ht40 &&
-	    (ctx->staging.flags & RXON_FLG_CTRL_CHANNEL_LOC_HI_MSK))
-		ctrl_chan_high = 1;
-
-	cmd.band = band;
-	cmd.expect_beacon = 0;
-	ch = ch_switch->channel->hw_value;
-	cmd.channel = cpu_to_le16(ch);
-	cmd.rxon_flags = ctx->staging.flags;
-	cmd.rxon_filter_flags = ctx->staging.filter_flags;
-	switch_count = ch_switch->count;
-	tsf_low = ch_switch->timestamp & 0x0ffffffff;
-	/*
-	 * calculate the ucode channel switch time
-	 * adding TSF as one of the factor for when to switch
-	 */
-	if ((priv->ucode_beacon_time > tsf_low) && beacon_interval) {
-		if (switch_count > ((priv->ucode_beacon_time - tsf_low) /
-		    beacon_interval)) {
-			switch_count -= (priv->ucode_beacon_time -
-				tsf_low) / beacon_interval;
-		} else
-			switch_count = 0;
-	}
-	if (switch_count <= 1)
-		cmd.switch_time = cpu_to_le32(priv->ucode_beacon_time);
-	else {
-		switch_time_in_usec =
-			vif->bss_conf.beacon_int * switch_count * TIME_UNIT;
-		ucode_switch_time = iwl_usecs_to_beacons(priv,
-							 switch_time_in_usec,
-							 beacon_interval);
-		cmd.switch_time = iwl_add_beacon_time(priv,
-						      priv->ucode_beacon_time,
-						      ucode_switch_time,
-						      beacon_interval);
-	}
-	IWL_DEBUG_11H(priv, "uCode time for the switch is 0x%x\n",
-		      cmd.switch_time);
-	ch_info = iwl_get_channel_info(priv, priv->band, ch);
-	if (ch_info)
-		cmd.expect_beacon = is_channel_radar(ch_info);
-	else {
-		IWL_ERR(priv, "invalid channel switch from %u to %u\n",
-			ctx->active.channel, ch);
-		return -EFAULT;
-	}
-
-	rc = iwl4965_fill_txpower_tbl(priv, band, ch, is_ht40,
-				      ctrl_chan_high, &cmd.tx_power);
-	if (rc) {
-		IWL_DEBUG_11H(priv, "error:%d  fill txpower_tbl\n", rc);
-		return rc;
-	}
-
-	priv->switch_rxon.channel = cmd.channel;
-	priv->switch_rxon.switch_in_progress = true;
-
-	return iwl_send_cmd_pdu(priv, REPLY_CHANNEL_SWITCH, sizeof(cmd), &cmd);
-}
-
-/**
- * iwl4965_txq_update_byte_cnt_tbl - Set up entry in Tx byte-count array
- */
-static void iwl4965_txq_update_byte_cnt_tbl(struct iwl_priv *priv,
-					    struct iwl_tx_queue *txq,
-					    u16 byte_cnt)
-{
-	struct iwl4965_scd_bc_tbl *scd_bc_tbl = priv->scd_bc_tbls.addr;
-	int txq_id = txq->q.id;
-	int write_ptr = txq->q.write_ptr;
-	int len = byte_cnt + IWL_TX_CRC_SIZE + IWL_TX_DELIMITER_SIZE;
-	__le16 bc_ent;
-
-	WARN_ON(len > 0xFFF || write_ptr >= TFD_QUEUE_SIZE_MAX);
-
-	bc_ent = cpu_to_le16(len & 0xFFF);
-	/* Set up byte count within first 256 entries */
-	scd_bc_tbl[txq_id].tfd_offset[write_ptr] = bc_ent;
-
-	/* If within first 64 entries, duplicate at end */
-	if (write_ptr < TFD_QUEUE_SIZE_BC_DUP)
-		scd_bc_tbl[txq_id].
-			tfd_offset[TFD_QUEUE_SIZE_MAX + write_ptr] = bc_ent;
-}
-
-/**
- * iwl4965_hw_get_temperature - return the calibrated temperature (in Kelvin)
- * @statistics: Provides the temperature reading from the uCode
- *
- * A return of <0 indicates bogus data in the statistics
- */
-static int iwl4965_hw_get_temperature(struct iwl_priv *priv)
-{
-	s32 temperature;
-	s32 vt;
-	s32 R1, R2, R3;
-	u32 R4;
-
-	if (test_bit(STATUS_TEMPERATURE, &priv->status) &&
-	    (priv->_agn.statistics.flag &
-			STATISTICS_REPLY_FLG_HT40_MODE_MSK)) {
-		IWL_DEBUG_TEMP(priv, "Running HT40 temperature calibration\n");
-		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[1]);
-		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[1]);
-		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[1]);
-		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[1]);
-	} else {
-		IWL_DEBUG_TEMP(priv, "Running temperature calibration\n");
-		R1 = (s32)le32_to_cpu(priv->card_alive_init.therm_r1[0]);
-		R2 = (s32)le32_to_cpu(priv->card_alive_init.therm_r2[0]);
-		R3 = (s32)le32_to_cpu(priv->card_alive_init.therm_r3[0]);
-		R4 = le32_to_cpu(priv->card_alive_init.therm_r4[0]);
-	}
-
-	/*
-	 * Temperature is only 23 bits, so sign extend out to 32.
-	 *
-	 * NOTE If we haven't received a statistics notification yet
-	 * with an updated temperature, use R4 provided to us in the
-	 * "initialize" ALIVE response.
-	 */
-	if (!test_bit(STATUS_TEMPERATURE, &priv->status))
-		vt = sign_extend32(R4, 23);
-	else
-		vt = sign_extend32(le32_to_cpu(priv->_agn.statistics.
-				 general.common.temperature), 23);
-
-	IWL_DEBUG_TEMP(priv, "Calib values R[1-3]: %d %d %d R4: %d\n", R1, R2, R3, vt);
-
-	if (R3 == R1) {
-		IWL_ERR(priv, "Calibration conflict R1 == R3\n");
-		return -1;
-	}
-
-	/* Calculate temperature in degrees Kelvin, adjust by 97%.
-	 * Add offset to center the adjustment around 0 degrees Centigrade. */
-	temperature = TEMPERATURE_CALIB_A_VAL * (vt - R2);
-	temperature /= (R3 - R1);
-	temperature = (temperature * 97) / 100 + TEMPERATURE_CALIB_KELVIN_OFFSET;
-
-	IWL_DEBUG_TEMP(priv, "Calibrated temperature: %dK, %dC\n",
-			temperature, KELVIN_TO_CELSIUS(temperature));
-
-	return temperature;
-}
-
-/* Adjust Txpower only if temperature variance is greater than threshold. */
-#define IWL_TEMPERATURE_THRESHOLD   3
-
-/**
- * iwl4965_is_temp_calib_needed - determines if new calibration is needed
- *
- * If the temperature changed has changed sufficiently, then a recalibration
- * is needed.
- *
- * Assumes caller will replace priv->last_temperature once calibration
- * executed.
- */
-static int iwl4965_is_temp_calib_needed(struct iwl_priv *priv)
-{
-	int temp_diff;
-
-	if (!test_bit(STATUS_STATISTICS, &priv->status)) {
-		IWL_DEBUG_TEMP(priv, "Temperature not updated -- no statistics.\n");
-		return 0;
-	}
-
-	temp_diff = priv->temperature - priv->last_temperature;
-
-	/* get absolute value */
-	if (temp_diff < 0) {
-		IWL_DEBUG_POWER(priv, "Getting cooler, delta %d\n", temp_diff);
-		temp_diff = -temp_diff;
-	} else if (temp_diff == 0)
-		IWL_DEBUG_POWER(priv, "Temperature unchanged\n");
-	else
-		IWL_DEBUG_POWER(priv, "Getting warmer, delta %d\n", temp_diff);
-
-	if (temp_diff < IWL_TEMPERATURE_THRESHOLD) {
-		IWL_DEBUG_POWER(priv, " => thermal txpower calib not needed\n");
-		return 0;
-	}
-
-	IWL_DEBUG_POWER(priv, " => thermal txpower calib needed\n");
-
-	return 1;
-}
-
-static void iwl4965_temperature_calib(struct iwl_priv *priv)
-{
-	s32 temp;
-
-	temp = iwl4965_hw_get_temperature(priv);
-	if (temp < 0)
-		return;
-
-	if (priv->temperature != temp) {
-		if (priv->temperature)
-			IWL_DEBUG_TEMP(priv, "Temperature changed "
-				       "from %dC to %dC\n",
-				       KELVIN_TO_CELSIUS(priv->temperature),
-				       KELVIN_TO_CELSIUS(temp));
-		else
-			IWL_DEBUG_TEMP(priv, "Temperature "
-				       "initialized to %dC\n",
-				       KELVIN_TO_CELSIUS(temp));
-	}
-
-	priv->temperature = temp;
-	iwl_tt_handler(priv);
-	set_bit(STATUS_TEMPERATURE, &priv->status);
-
-	if (!priv->disable_tx_power_cal &&
-	     unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-	     iwl4965_is_temp_calib_needed(priv))
-		queue_work(priv->workqueue, &priv->txpower_work);
-}
-
-/**
- * iwl4965_tx_queue_stop_scheduler - Stop queue, but keep configuration
- */
-static void iwl4965_tx_queue_stop_scheduler(struct iwl_priv *priv,
-					    u16 txq_id)
-{
-	/* Simply stop the queue, but don't change any configuration;
-	 * the SCD_ACT_EN bit is the write-enable mask for the ACTIVE bit. */
-	iwl_write_prph(priv,
-		IWL49_SCD_QUEUE_STATUS_BITS(txq_id),
-		(0 << IWL49_SCD_QUEUE_STTS_REG_POS_ACTIVE)|
-		(1 << IWL49_SCD_QUEUE_STTS_REG_POS_SCD_ACT_EN));
-}
-
-/**
- * txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE
- * priv->lock must be held by the caller
- */
-static int iwl4965_txq_agg_disable(struct iwl_priv *priv, u16 txq_id,
-				   u16 ssn_idx, u8 tx_fifo)
-{
-	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWL49_FIRST_AMPDU_QUEUE +
-		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-		IWL_WARN(priv,
-			"queue number out of range: %d, must be %d to %d\n",
-			txq_id, IWL49_FIRST_AMPDU_QUEUE,
-			IWL49_FIRST_AMPDU_QUEUE +
-			priv->cfg->base_params->num_of_ampdu_queues - 1);
-		return -EINVAL;
-	}
-
-	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-
-	iwl_clear_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-	/* supposes that ssn_idx is valid (!= 0xFFF) */
-	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-	iwl_clear_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-	iwl_txq_ctx_deactivate(priv, txq_id);
-	iwl4965_tx_queue_set_status(priv, &priv->txq[txq_id], tx_fifo, 0);
-
-	return 0;
-}
-
-/**
- * iwl4965_tx_queue_set_q2ratid - Map unique receiver/tid combination to a queue
- */
-static int iwl4965_tx_queue_set_q2ratid(struct iwl_priv *priv, u16 ra_tid,
-					u16 txq_id)
-{
-	u32 tbl_dw_addr;
-	u32 tbl_dw;
-	u16 scd_q2ratid;
-
-	scd_q2ratid = ra_tid & IWL_SCD_QUEUE_RA_TID_MAP_RATID_MSK;
-
-	tbl_dw_addr = priv->scd_base_addr +
-			IWL49_SCD_TRANSLATE_TBL_OFFSET_QUEUE(txq_id);
-
-	tbl_dw = iwl_read_targ_mem(priv, tbl_dw_addr);
-
-	if (txq_id & 0x1)
-		tbl_dw = (scd_q2ratid << 16) | (tbl_dw & 0x0000FFFF);
-	else
-		tbl_dw = scd_q2ratid | (tbl_dw & 0xFFFF0000);
-
-	iwl_write_targ_mem(priv, tbl_dw_addr, tbl_dw);
-
-	return 0;
-}
-
-
-/**
- * iwl4965_tx_queue_agg_enable - Set up & enable aggregation for selected queue
- *
- * NOTE:  txq_id must be greater than IWL49_FIRST_AMPDU_QUEUE,
- *        i.e. it must be one of the higher queues used for aggregation
- */
-static int iwl4965_txq_agg_enable(struct iwl_priv *priv, int txq_id,
-				  int tx_fifo, int sta_id, int tid, u16 ssn_idx)
-{
-	unsigned long flags;
-	u16 ra_tid;
-	int ret;
-
-	if ((IWL49_FIRST_AMPDU_QUEUE > txq_id) ||
-	    (IWL49_FIRST_AMPDU_QUEUE +
-		priv->cfg->base_params->num_of_ampdu_queues <= txq_id)) {
-		IWL_WARN(priv,
-			"queue number out of range: %d, must be %d to %d\n",
-			txq_id, IWL49_FIRST_AMPDU_QUEUE,
-			IWL49_FIRST_AMPDU_QUEUE +
-			priv->cfg->base_params->num_of_ampdu_queues - 1);
-		return -EINVAL;
-	}
-
-	ra_tid = BUILD_RAxTID(sta_id, tid);
-
-	/* Modify device's station table to Tx this TID */
-	ret = iwl_sta_tx_modify_enable_tid(priv, sta_id, tid);
-	if (ret)
-		return ret;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* Stop this Tx queue before configuring it */
-	iwl4965_tx_queue_stop_scheduler(priv, txq_id);
-
-	/* Map receiver-address / traffic-ID to this queue */
-	iwl4965_tx_queue_set_q2ratid(priv, ra_tid, txq_id);
-
-	/* Set this queue as a chain-building queue */
-	iwl_set_bits_prph(priv, IWL49_SCD_QUEUECHAIN_SEL, (1 << txq_id));
-
-	/* Place first TFD at index corresponding to start sequence number.
-	 * Assumes that ssn_idx is valid (!= 0xFFF) */
-	priv->txq[txq_id].q.read_ptr = (ssn_idx & 0xff);
-	priv->txq[txq_id].q.write_ptr = (ssn_idx & 0xff);
-	iwl4965_set_wr_ptrs(priv, txq_id, ssn_idx);
-
-	/* Set up Tx window size and frame limit for this queue */
-	iwl_write_targ_mem(priv,
-		priv->scd_base_addr + IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id),
-		(SCD_WIN_SIZE << IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_POS) &
-		IWL49_SCD_QUEUE_CTX_REG1_WIN_SIZE_MSK);
-
-	iwl_write_targ_mem(priv, priv->scd_base_addr +
-		IWL49_SCD_CONTEXT_QUEUE_OFFSET(txq_id) + sizeof(u32),
-		(SCD_FRAME_LIMIT << IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_POS)
-		& IWL49_SCD_QUEUE_CTX_REG2_FRAME_LIMIT_MSK);
-
-	iwl_set_bits_prph(priv, IWL49_SCD_INTERRUPT_MASK, (1 << txq_id));
-
-	/* 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);
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	return 0;
-}
-
-
-static u16 iwl4965_get_hcmd_size(u8 cmd_id, u16 len)
-{
-	switch (cmd_id) {
-	case REPLY_RXON:
-		return (u16) sizeof(struct iwl4965_rxon_cmd);
-	default:
-		return len;
-	}
-}
-
-static u16 iwl4965_build_addsta_hcmd(const struct iwl_addsta_cmd *cmd, u8 *data)
-{
-	struct iwl4965_addsta_cmd *addsta = (struct iwl4965_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 = cmd->tid_disable_tx;
-	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;
-	addsta->sleep_tx_count = cmd->sleep_tx_count;
-	addsta->reserved1 = cpu_to_le16(0);
-	addsta->reserved2 = cpu_to_le16(0);
-
-	return (u16)sizeof(struct iwl4965_addsta_cmd);
-}
-
-static inline u32 iwl4965_get_scd_ssn(struct iwl4965_tx_resp *tx_resp)
-{
-	return le32_to_cpup(&tx_resp->u.status + tx_resp->frame_count) & MAX_SN;
-}
-
-/**
- * iwl4965_tx_status_reply_tx - Handle Tx response for frames in aggregation queue
- */
-static int iwl4965_tx_status_reply_tx(struct iwl_priv *priv,
-				      struct iwl_ht_agg *agg,
-				      struct iwl4965_tx_resp *tx_resp,
-				      int txq_id, u16 start_idx)
-{
-	u16 status;
-	struct agg_tx_status *frame_status = tx_resp->u.agg_status;
-	struct ieee80211_tx_info *info = NULL;
-	struct ieee80211_hdr *hdr = NULL;
-	u32 rate_n_flags = le32_to_cpu(tx_resp->rate_n_flags);
-	int i, sh, idx;
-	u16 seq;
-	if (agg->wait_for_ba)
-		IWL_DEBUG_TX_REPLY(priv, "got tx response w/o block-ack\n");
-
-	agg->frame_count = tx_resp->frame_count;
-	agg->start_idx = start_idx;
-	agg->rate_n_flags = rate_n_flags;
-	agg->bitmap = 0;
-
-	/* num frames attempted by Tx command */
-	if (agg->frame_count == 1) {
-		/* Only one frame was attempted; no block-ack will arrive */
-		status = le16_to_cpu(frame_status[0].status);
-		idx = start_idx;
-
-		/* FIXME: code repetition */
-		IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, StartIdx=%d idx=%d\n",
-				   agg->frame_count, agg->start_idx, idx);
-
-		info = IEEE80211_SKB_CB(priv->txq[txq_id].txb[idx].skb);
-		info->status.rates[0].count = tx_resp->failure_frame + 1;
-		info->flags &= ~IEEE80211_TX_CTL_AMPDU;
-		info->flags |= iwl_tx_status_to_mac80211(status);
-		iwlagn_hwrate_to_tx_control(priv, rate_n_flags, info);
-		/* FIXME: code repetition end */
-
-		IWL_DEBUG_TX_REPLY(priv, "1 Frame 0x%x failure :%d\n",
-				    status & 0xff, tx_resp->failure_frame);
-		IWL_DEBUG_TX_REPLY(priv, "Rate Info rate_n_flags=%x\n", rate_n_flags);
-
-		agg->wait_for_ba = 0;
-	} else {
-		/* Two or more frames were attempted; expect block-ack */
-		u64 bitmap = 0;
-		int start = agg->start_idx;
-
-		/* Construct bit-map of pending frames within Tx window */
-		for (i = 0; i < agg->frame_count; i++) {
-			u16 sc;
-			status = le16_to_cpu(frame_status[i].status);
-			seq  = le16_to_cpu(frame_status[i].sequence);
-			idx = SEQ_TO_INDEX(seq);
-			txq_id = SEQ_TO_QUEUE(seq);
-
-			if (status & (AGG_TX_STATE_FEW_BYTES_MSK |
-				      AGG_TX_STATE_ABORT_MSK))
-				continue;
-
-			IWL_DEBUG_TX_REPLY(priv, "FrameCnt = %d, txq_id=%d idx=%d\n",
-					   agg->frame_count, txq_id, idx);
-
-			hdr = iwl_tx_queue_get_hdr(priv, txq_id, idx);
-			if (!hdr) {
-				IWL_ERR(priv,
-					"BUG_ON idx doesn't point to valid skb"
-					" idx=%d, txq_id=%d\n", idx, txq_id);
-				return -1;
-			}
-
-			sc = le16_to_cpu(hdr->seq_ctrl);
-			if (idx != (SEQ_TO_SN(sc) & 0xff)) {
-				IWL_ERR(priv,
-					"BUG_ON idx doesn't match seq control"
-					" idx=%d, seq_idx=%d, seq=%d\n",
-					idx, SEQ_TO_SN(sc), hdr->seq_ctrl);
-				return -1;
-			}
-
-			IWL_DEBUG_TX_REPLY(priv, "AGG Frame i=%d idx %d seq=%d\n",
-					   i, idx, SEQ_TO_SN(sc));
-
-			sh = idx - start;
-			if (sh > 64) {
-				sh = (start - idx) + 0xff;
-				bitmap = bitmap << sh;
-				sh = 0;
-				start = idx;
-			} else if (sh < -64)
-				sh  = 0xff - (start - idx);
-			else if (sh < 0) {
-				sh = start - idx;
-				start = idx;
-				bitmap = bitmap << sh;
-				sh = 0;
-			}
-			bitmap |= 1ULL << sh;
-			IWL_DEBUG_TX_REPLY(priv, "start=%d bitmap=0x%llx\n",
-					   start, (unsigned long long)bitmap);
-		}
-
-		agg->bitmap = bitmap;
-		agg->start_idx = start;
-		IWL_DEBUG_TX_REPLY(priv, "Frames %d start_idx=%d bitmap=0x%llx\n",
-				   agg->frame_count, agg->start_idx,
-				   (unsigned long long)agg->bitmap);
-
-		if (bitmap)
-			agg->wait_for_ba = 1;
-	}
-	return 0;
-}
-
-static u8 iwl_find_station(struct iwl_priv *priv, const u8 *addr)
-{
-	int i;
-	int start = 0;
-	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->contexts[IWL_RXON_CTX_BSS].bcast_sta_id;
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	for (i = start; i < priv->hw_params.max_stations; i++)
-		if (priv->stations[i].used &&
-		    (!compare_ether_addr(priv->stations[i].sta.sta.addr,
-					 addr))) {
-			ret = i;
-			goto out;
-		}
-
-	IWL_DEBUG_ASSOC_LIMIT(priv, "can not find STA %pM total %d\n",
-			      addr, priv->num_stations);
-
- out:
-	/*
-	 * It may be possible that more commands interacting with stations
-	 * arrive before we completed processing the adding of
-	 * station
-	 */
-	if (ret != IWL_INVALID_STATION &&
-	    (!(priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) ||
-	     ((priv->stations[ret].used & IWL_STA_UCODE_ACTIVE) &&
-	      (priv->stations[ret].used & IWL_STA_UCODE_INPROGRESS)))) {
-		IWL_ERR(priv, "Requested station info for sta %d before ready.\n",
-			ret);
-		ret = IWL_INVALID_STATION;
-	}
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-	return ret;
-}
-
-static int iwl_get_ra_sta_id(struct iwl_priv *priv, struct ieee80211_hdr *hdr)
-{
-	if (priv->iw_mode == NL80211_IFTYPE_STATION) {
-		return IWL_AP_ID;
-	} else {
-		u8 *da = ieee80211_get_DA(hdr);
-		return iwl_find_station(priv, da);
-	}
-}
-
-/**
- * iwl4965_rx_reply_tx - Handle standard (non-aggregation) Tx response
- */
-static void iwl4965_rx_reply_tx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u16 sequence = le16_to_cpu(pkt->hdr.sequence);
-	int txq_id = SEQ_TO_QUEUE(sequence);
-	int index = SEQ_TO_INDEX(sequence);
-	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct ieee80211_hdr *hdr;
-	struct ieee80211_tx_info *info;
-	struct iwl4965_tx_resp *tx_resp = (void *)&pkt->u.raw[0];
-	u32  status = le32_to_cpu(tx_resp->u.status);
-	int uninitialized_var(tid);
-	int sta_id;
-	int freed;
-	u8 *qc = NULL;
-	unsigned long flags;
-
-	if ((index >= txq->q.n_bd) || (iwl_queue_used(&txq->q, index) == 0)) {
-		IWL_ERR(priv, "Read index for DMA queue txq_id (%d) index %d "
-			  "is out of range [0-%d] %d %d\n", txq_id,
-			  index, txq->q.n_bd, txq->q.write_ptr,
-			  txq->q.read_ptr);
-		return;
-	}
-
-	txq->time_stamp = jiffies;
-	info = IEEE80211_SKB_CB(txq->txb[txq->q.read_ptr].skb);
-	memset(&info->status, 0, sizeof(info->status));
-
-	hdr = iwl_tx_queue_get_hdr(priv, txq_id, index);
-	if (ieee80211_is_data_qos(hdr->frame_control)) {
-		qc = ieee80211_get_qos_ctl(hdr);
-		tid = qc[0] & 0xf;
-	}
-
-	sta_id = iwl_get_ra_sta_id(priv, hdr);
-	if (txq->sched_retry && unlikely(sta_id == IWL_INVALID_STATION)) {
-		IWL_ERR(priv, "Station not known\n");
-		return;
-	}
-
-	spin_lock_irqsave(&priv->sta_lock, flags);
-	if (txq->sched_retry) {
-		const u32 scd_ssn = iwl4965_get_scd_ssn(tx_resp);
-		struct iwl_ht_agg *agg = NULL;
-		WARN_ON(!qc);
-
-		agg = &priv->stations[sta_id].tid[tid].agg;
-
-		iwl4965_tx_status_reply_tx(priv, agg, tx_resp, txq_id, index);
-
-		/* check if BAR is needed */
-		if ((tx_resp->frame_count == 1) && !iwl_is_tx_success(status))
-			info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
-
-		if (txq->q.read_ptr != (scd_ssn & 0xff)) {
-			index = iwl_queue_dec_wrap(scd_ssn & 0xff, txq->q.n_bd);
-			IWL_DEBUG_TX_REPLY(priv, "Retry scheduler reclaim scd_ssn "
-					   "%d index %d\n", scd_ssn , index);
-			freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
-			if (qc)
-				iwl_free_tfds_in_queue(priv, sta_id,
-						       tid, freed);
-
-			if (priv->mac80211_registered &&
-			    (iwl_queue_space(&txq->q) > txq->q.low_mark) &&
-			    (agg->state != IWL_EMPTYING_HW_QUEUE_DELBA))
-				iwl_wake_queue(priv, txq);
-		}
-	} else {
-		info->status.rates[0].count = tx_resp->failure_frame + 1;
-		info->flags |= iwl_tx_status_to_mac80211(status);
-		iwlagn_hwrate_to_tx_control(priv,
-					le32_to_cpu(tx_resp->rate_n_flags),
-					info);
-
-		IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x) "
-				   "rate_n_flags 0x%x retries %d\n",
-				   txq_id,
-				   iwl_get_tx_fail_reason(status), status,
-				   le32_to_cpu(tx_resp->rate_n_flags),
-				   tx_resp->failure_frame);
-
-		freed = iwlagn_tx_queue_reclaim(priv, txq_id, index);
-		if (qc && likely(sta_id != IWL_INVALID_STATION))
-			iwl_free_tfds_in_queue(priv, sta_id, tid, freed);
-		else if (sta_id == IWL_INVALID_STATION)
-			IWL_DEBUG_TX_REPLY(priv, "Station not known\n");
-
-		if (priv->mac80211_registered &&
-		    (iwl_queue_space(&txq->q) > txq->q.low_mark))
-			iwl_wake_queue(priv, txq);
-	}
-	if (qc && likely(sta_id != IWL_INVALID_STATION))
-		iwlagn_txq_check_empty(priv, sta_id, tid, txq_id);
-
-	iwl_check_abort_status(priv, tx_resp->frame_count, status);
-
-	spin_unlock_irqrestore(&priv->sta_lock, flags);
-}
-
-static int iwl4965_calc_rssi(struct iwl_priv *priv,
-			     struct iwl_rx_phy_res *rx_resp)
-{
-	/* data from PHY/DSP regarding signal strength, etc.,
-	 *   contents are always there, not configurable by host.  */
-	struct iwl4965_rx_non_cfg_phy *ncphy =
-	    (struct iwl4965_rx_non_cfg_phy *)rx_resp->non_cfg_phy_buf;
-	u32 agc = (le16_to_cpu(ncphy->agc_info) & IWL49_AGC_DB_MASK)
-			>> IWL49_AGC_DB_POS;
-
-	u32 valid_antennae =
-	    (le16_to_cpu(rx_resp->phy_flags) & IWL49_RX_PHY_FLAGS_ANTENNAE_MASK)
-			>> IWL49_RX_PHY_FLAGS_ANTENNAE_OFFSET;
-	u8 max_rssi = 0;
-	u32 i;
-
-	/* Find max rssi among 3 possible receivers.
-	 * These values are measured by the digital signal processor (DSP).
-	 * They should stay fairly constant even as the signal strength varies,
-	 *   if the radio's automatic gain control (AGC) is working right.
-	 * AGC value (see below) will provide the "interesting" info. */
-	for (i = 0; i < 3; i++)
-		if (valid_antennae & (1 << i))
-			max_rssi = max(ncphy->rssi_info[i << 1], max_rssi);
-
-	IWL_DEBUG_STATS(priv, "Rssi In A %d B %d C %d Max %d AGC dB %d\n",
-		ncphy->rssi_info[0], ncphy->rssi_info[2], ncphy->rssi_info[4],
-		max_rssi, agc);
-
-	/* dBm = max_rssi dB - agc dB - constant.
-	 * Higher AGC (higher radio gain) means lower signal. */
-	return max_rssi - agc - IWLAGN_RSSI_OFFSET;
-}
-
-
-/* Set up 4965-specific Rx frame reply handlers */
-static void iwl4965_rx_handler_setup(struct iwl_priv *priv)
-{
-	/* Legacy Rx frames */
-	priv->rx_handlers[REPLY_RX] = iwlagn_rx_reply_rx;
-	/* Tx response */
-	priv->rx_handlers[REPLY_TX] = iwl4965_rx_reply_tx;
-}
-
-static void iwl4965_setup_deferred_work(struct iwl_priv *priv)
-{
-	INIT_WORK(&priv->txpower_work, iwl4965_bg_txpower_work);
-}
-
-static void iwl4965_cancel_deferred_work(struct iwl_priv *priv)
-{
-	cancel_work_sync(&priv->txpower_work);
-}
-
-static struct iwl_hcmd_ops iwl4965_hcmd = {
-	.rxon_assoc = iwl4965_send_rxon_assoc,
-	.commit_rxon = iwl4965_commit_rxon,
-	.set_rxon_chain = iwlagn_set_rxon_chain,
-	.send_bt_config = iwl_send_bt_config,
-};
-
-static void iwl4965_post_scan(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	/*
-	 * Since setting the RXON may have been deferred while
-	 * performing the scan, fire one off if needed
-	 */
-	if (memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
-		iwlcore_commit_rxon(priv, ctx);
-}
-
-static void iwl4965_post_associate(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_vif *vif = ctx->vif;
-	struct ieee80211_conf *conf = NULL;
-	int ret = 0;
-
-	if (!vif || !priv->is_open)
-		return;
-
-	if (vif->type == NL80211_IFTYPE_AP) {
-		IWL_ERR(priv, "%s Should not be called in AP mode\n", __func__);
-		return;
-	}
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	iwl_scan_cancel_timeout(priv, 200);
-
-	conf = ieee80211_get_hw_conf(priv->hw);
-
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
-
-	ret = iwl_send_rxon_timing(priv, ctx);
-	if (ret)
-		IWL_WARN(priv, "RXON timing - "
-			    "Attempting to continue.\n");
-
-	ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-
-	iwl_set_rxon_ht(priv, &priv->current_ht_config);
-
-	if (priv->cfg->ops->hcmd->set_rxon_chain)
-		priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-	ctx->staging.assoc_id = cpu_to_le16(vif->bss_conf.aid);
-
-	IWL_DEBUG_ASSOC(priv, "assoc id %d beacon interval %d\n",
-			vif->bss_conf.aid, vif->bss_conf.beacon_int);
-
-	if (vif->bss_conf.use_short_preamble)
-		ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-	else
-		ctx->staging.flags &= ~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-	if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-		if (vif->bss_conf.use_short_slot)
-			ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SHORT_SLOT_MSK;
-	}
-
-	iwlcore_commit_rxon(priv, ctx);
-
-	IWL_DEBUG_ASSOC(priv, "Associated as %d to: %pM\n",
-			vif->bss_conf.aid, ctx->active.bssid_addr);
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		iwlagn_send_beacon_cmd(priv);
-		break;
-	default:
-		IWL_ERR(priv, "%s Should not be called in %d mode\n",
-			  __func__, vif->type);
-		break;
-	}
-
-	/* the chain noise calibration will enabled PM upon completion
-	 * 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_update_mode(priv, false);
-
-	/* Enable Rx differential gain and sensitivity calibrations */
-	iwl_chain_noise_reset(priv);
-	priv->start_calib = 1;
-}
-
-static void iwl4965_config_ap(struct iwl_priv *priv)
-{
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct ieee80211_vif *vif = ctx->vif;
-	int ret = 0;
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	/* The following should be done only at AP bring up */
-	if (!iwl_is_associated_ctx(ctx)) {
-
-		/* RXON - unassoc (to set timing command) */
-		ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-
-		/* RXON Timing */
-		ret = iwl_send_rxon_timing(priv, ctx);
-		if (ret)
-			IWL_WARN(priv, "RXON timing failed - "
-					"Attempting to continue.\n");
-
-		/* AP has all antennas */
-		priv->chain_noise_data.active_chains =
-			priv->hw_params.valid_rx_ant;
-		iwl_set_rxon_ht(priv, &priv->current_ht_config);
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-
-		ctx->staging.assoc_id = 0;
-
-		if (vif->bss_conf.use_short_preamble)
-			ctx->staging.flags |=
-				RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.flags &=
-				~RXON_FLG_SHORT_PREAMBLE_MSK;
-
-		if (ctx->staging.flags & RXON_FLG_BAND_24G_MSK) {
-			if (vif->bss_conf.use_short_slot)
-				ctx->staging.flags |=
-					RXON_FLG_SHORT_SLOT_MSK;
-			else
-				ctx->staging.flags &=
-					~RXON_FLG_SHORT_SLOT_MSK;
-		}
-		/* need to send beacon cmd before committing assoc RXON! */
-		iwlagn_send_beacon_cmd(priv);
-		/* restore RXON assoc */
-		ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
-		iwlcore_commit_rxon(priv, ctx);
-	}
-	iwlagn_send_beacon_cmd(priv);
-
-	/* FIXME - we need to add code here to detect a totally new
-	 * configuration, reset the AP, unassoc, rxon timing, assoc,
-	 * clear sta table, add BCAST sta... */
-}
-
-static struct iwl_hcmd_utils_ops iwl4965_hcmd_utils = {
-	.get_hcmd_size = iwl4965_get_hcmd_size,
-	.build_addsta_hcmd = iwl4965_build_addsta_hcmd,
-	.chain_noise_reset = iwl4965_chain_noise_reset,
-	.gain_computation = iwl4965_gain_computation,
-	.tx_cmd_protection = iwl_legacy_tx_cmd_protection,
-	.calc_rssi = iwl4965_calc_rssi,
-	.request_scan = iwlagn_request_scan,
-	.post_scan = iwl4965_post_scan,
-};
-
-static struct iwl_lib_ops iwl4965_lib = {
-	.set_hw_params = iwl4965_hw_set_hw_params,
-	.txq_update_byte_cnt_tbl = iwl4965_txq_update_byte_cnt_tbl,
-	.txq_set_sched = iwl4965_txq_set_sched,
-	.txq_agg_enable = iwl4965_txq_agg_enable,
-	.txq_agg_disable = iwl4965_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 = iwl4965_rx_handler_setup,
-	.setup_deferred_work = iwl4965_setup_deferred_work,
-	.cancel_deferred_work = iwl4965_cancel_deferred_work,
-	.is_valid_rtc_data_addr = iwl4965_hw_valid_rtc_data_addr,
-	.alive_notify = iwl4965_alive_notify,
-	.init_alive_start = iwl4965_init_alive_start,
-	.load_ucode = iwl4965_load_bsm,
-	.dump_nic_event_log = iwl_dump_nic_event_log,
-	.dump_nic_error_log = iwl_dump_nic_error_log,
-	.dump_fh = iwl_dump_fh,
-	.set_channel_switch = iwl4965_hw_channel_switch,
-	.apm_ops = {
-		.init = iwl_apm_init,
-		.config = iwl4965_nic_config,
-	},
-	.eeprom_ops = {
-		.regulatory_bands = {
-			EEPROM_REGULATORY_BAND_1_CHANNELS,
-			EEPROM_REGULATORY_BAND_2_CHANNELS,
-			EEPROM_REGULATORY_BAND_3_CHANNELS,
-			EEPROM_REGULATORY_BAND_4_CHANNELS,
-			EEPROM_REGULATORY_BAND_5_CHANNELS,
-			EEPROM_4965_REGULATORY_BAND_24_HT40_CHANNELS,
-			EEPROM_4965_REGULATORY_BAND_52_HT40_CHANNELS
-		},
-		.acquire_semaphore = iwlcore_eeprom_acquire_semaphore,
-		.release_semaphore = iwlcore_eeprom_release_semaphore,
-		.calib_version = iwl4965_eeprom_calib_version,
-		.query_addr = iwlcore_eeprom_query_addr,
-	},
-	.send_tx_power	= iwl4965_send_tx_power,
-	.update_chain_flags = iwl_update_chain_flags,
-	.isr_ops = {
-		.isr = iwl_isr_legacy,
-	},
-	.temp_ops = {
-		.temperature = iwl4965_temperature_calib,
-	},
-	.debugfs_ops = {
-		.rx_stats_read = iwl_ucode_rx_stats_read,
-		.tx_stats_read = iwl_ucode_tx_stats_read,
-		.general_stats_read = iwl_ucode_general_stats_read,
-		.bt_stats_read = iwl_ucode_bt_stats_read,
-		.reply_tx_error = iwl_reply_tx_error_read,
-	},
-	.check_plcp_health = iwl_good_plcp_health,
-};
-
-static const struct iwl_legacy_ops iwl4965_legacy_ops = {
-	.post_associate = iwl4965_post_associate,
-	.config_ap = iwl4965_config_ap,
-	.manage_ibss_station = iwlagn_manage_ibss_station,
-	.update_bcast_stations = iwl_update_bcast_stations,
-};
-
-struct ieee80211_ops iwl4965_hw_ops = {
-	.tx = iwlagn_mac_tx,
-	.start = iwlagn_mac_start,
-	.stop = iwlagn_mac_stop,
-	.add_interface = iwl_mac_add_interface,
-	.remove_interface = iwl_mac_remove_interface,
-	.change_interface = iwl_mac_change_interface,
-	.config = iwl_legacy_mac_config,
-	.configure_filter = iwlagn_configure_filter,
-	.set_key = iwlagn_mac_set_key,
-	.update_tkip_key = iwlagn_mac_update_tkip_key,
-	.conf_tx = iwl_mac_conf_tx,
-	.reset_tsf = iwl_legacy_mac_reset_tsf,
-	.bss_info_changed = iwl_legacy_mac_bss_info_changed,
-	.ampdu_action = iwlagn_mac_ampdu_action,
-	.hw_scan = iwl_mac_hw_scan,
-	.sta_add = iwlagn_mac_sta_add,
-	.sta_remove = iwl_mac_sta_remove,
-	.channel_switch = iwlagn_mac_channel_switch,
-	.flush = iwlagn_mac_flush,
-	.tx_last_beacon = iwl_mac_tx_last_beacon,
-};
-
-static const struct iwl_ops iwl4965_ops = {
-	.lib = &iwl4965_lib,
-	.hcmd = &iwl4965_hcmd,
-	.utils = &iwl4965_hcmd_utils,
-	.led = &iwlagn_led_ops,
-	.legacy = &iwl4965_legacy_ops,
-	.ieee80211_ops = &iwl4965_hw_ops,
-};
-
-static struct iwl_base_params iwl4965_base_params = {
-	.eeprom_size = IWL4965_EEPROM_IMG_SIZE,
-	.num_of_queues = IWL49_NUM_QUEUES,
-	.num_of_ampdu_queues = IWL49_NUM_AMPDU_QUEUES,
-	.pll_cfg_val = 0,
-	.set_l0s = true,
-	.use_bsm = true,
-	.use_isr_legacy = true,
-	.broken_powersave = true,
-	.led_compensation = 61,
-	.chain_noise_num_beacons = IWL4965_CAL_NUM_BEACONS,
-	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
-	.wd_timeout = IWL_DEF_WD_TIMEOUT,
-	.temperature_kelvin = true,
-	.max_event_log_size = 512,
-	.tx_power_by_driver = true,
-	.ucode_tracing = true,
-	.sensitivity_calib_by_driver = true,
-	.chain_noise_calib_by_driver = true,
-	.no_agg_framecnt_info = true,
-};
-
-struct iwl_cfg iwl4965_agn_cfg = {
-	.name = "Intel(R) Wireless WiFi Link 4965AGN",
-	.fw_name_pre = IWL4965_FW_PRE,
-	.ucode_api_max = IWL4965_UCODE_API_MAX,
-	.ucode_api_min = IWL4965_UCODE_API_MIN,
-	.sku = IWL_SKU_A|IWL_SKU_G|IWL_SKU_N,
-	.valid_tx_ant = ANT_AB,
-	.valid_rx_ant = ANT_ABC,
-	.eeprom_ver = EEPROM_4965_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_4965_TX_POWER_VERSION,
-	.ops = &iwl4965_ops,
-	.mod_params = &iwlagn_mod_params,
-	.base_params = &iwl4965_base_params,
-	.led_mode = IWL_LED_BLINK,
-	/*
-	 * Force use of chains B and C for scan RX on 5 GHz band
-	 * because the device has off-channel reception on chain A.
-	 */
-	.scan_rx_antennas[IEEE80211_BAND_5GHZ] = ANT_BC,
-};
-
-/* Module firmware */
-/*(DEBLOBBED)*/
-
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-4965-hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-4965-hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-4965-hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-4965-hw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,792 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- * 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 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.
- *
- *****************************************************************************/
-/*
- * Please use this file (iwl-4965-hw.h) only for hardware-related definitions.
- * Use iwl-commands.h for uCode API definitions.
- * Use iwl-dev.h for driver implementation definitions.
- */
-
-#ifndef __iwl_4965_hw_h__
-#define __iwl_4965_hw_h__
-
-#include "iwl-fh.h"
-
-/* EEPROM */
-#define IWL4965_EEPROM_IMG_SIZE			1024
-
-/*
- * uCode queue management definitions ...
- * The first queue used for block-ack aggregation is #7 (4965 only).
- * All block-ack aggregation queues should map to Tx DMA/FIFO channel 7.
- */
-#define IWL49_FIRST_AMPDU_QUEUE	7
-
-/* Sizes and addresses for instruction and data memory (SRAM) in
- * 4965's embedded processor.  Driver access is via HBUS_TARG_MEM_* regs. */
-#define IWL49_RTC_INST_LOWER_BOUND		(0x000000)
-#define IWL49_RTC_INST_UPPER_BOUND		(0x018000)
-
-#define IWL49_RTC_DATA_LOWER_BOUND		(0x800000)
-#define IWL49_RTC_DATA_UPPER_BOUND		(0x80A000)
-
-#define IWL49_RTC_INST_SIZE  (IWL49_RTC_INST_UPPER_BOUND - \
-				IWL49_RTC_INST_LOWER_BOUND)
-#define IWL49_RTC_DATA_SIZE  (IWL49_RTC_DATA_UPPER_BOUND - \
-				IWL49_RTC_DATA_LOWER_BOUND)
-
-#define IWL49_MAX_INST_SIZE IWL49_RTC_INST_SIZE
-#define IWL49_MAX_DATA_SIZE IWL49_RTC_DATA_SIZE
-
-/* Size of uCode instruction memory in bootstrap state machine */
-#define IWL49_MAX_BSM_SIZE BSM_SRAM_SIZE
-
-static inline int iwl4965_hw_valid_rtc_data_addr(u32 addr)
-{
-	return (addr >= IWL49_RTC_DATA_LOWER_BOUND) &&
-	       (addr < IWL49_RTC_DATA_UPPER_BOUND);
-}
-
-/********************* START TEMPERATURE *************************************/
-
-/**
- * 4965 temperature calculation.
- *
- * The driver must calculate the device temperature before calculating
- * a txpower setting (amplifier gain is temperature dependent).  The
- * calculation uses 4 measurements, 3 of which (R1, R2, R3) are calibration
- * values used for the life of the driver, and one of which (R4) is the
- * real-time temperature indicator.
- *
- * uCode provides all 4 values to the driver via the "initialize alive"
- * notification (see struct iwl4965_init_alive_resp).  After the runtime uCode
- * image loads, uCode updates the R4 value via statistics notifications
- * (see STATISTICS_NOTIFICATION), which occur after each received beacon
- * when associated, or can be requested via REPLY_STATISTICS_CMD.
- *
- * NOTE:  uCode provides the R4 value as a 23-bit signed value.  Driver
- *        must sign-extend to 32 bits before applying formula below.
- *
- * Formula:
- *
- * degrees Kelvin = ((97 * 259 * (R4 - R2) / (R3 - R1)) / 100) + 8
- *
- * NOTE:  The basic formula is 259 * (R4-R2) / (R3-R1).  The 97/100 is
- * an additional correction, which should be centered around 0 degrees
- * Celsius (273 degrees Kelvin).  The 8 (3 percent of 273) compensates for
- * centering the 97/100 correction around 0 degrees K.
- *
- * Add 273 to Kelvin value to find degrees Celsius, for comparing current
- * temperature with factory-measured temperatures when calculating txpower
- * settings.
- */
-#define TEMPERATURE_CALIB_KELVIN_OFFSET 8
-#define TEMPERATURE_CALIB_A_VAL 259
-
-/* Limit range of calculated temperature to be between these Kelvin values */
-#define IWL_TX_POWER_TEMPERATURE_MIN  (263)
-#define IWL_TX_POWER_TEMPERATURE_MAX  (410)
-
-#define IWL_TX_POWER_TEMPERATURE_OUT_OF_RANGE(t) \
-	(((t) < IWL_TX_POWER_TEMPERATURE_MIN) || \
-	 ((t) > IWL_TX_POWER_TEMPERATURE_MAX))
-
-/********************* END TEMPERATURE ***************************************/
-
-/********************* START TXPOWER *****************************************/
-
-/**
- * 4965 txpower calculations rely on information from three sources:
- *
- *     1) EEPROM
- *     2) "initialize" alive notification
- *     3) statistics notifications
- *
- * EEPROM data consists of:
- *
- * 1)  Regulatory information (max txpower and channel usage flags) is provided
- *     separately for each channel that can possibly supported by 4965.
- *     40 MHz wide (.11n HT40) channels are listed separately from 20 MHz
- *     (legacy) channels.
- *
- *     See struct iwl4965_eeprom_channel for format, and struct iwl4965_eeprom
- *     for locations in EEPROM.
- *
- * 2)  Factory txpower calibration information is provided separately for
- *     sub-bands of contiguous channels.  2.4GHz has just one sub-band,
- *     but 5 GHz has several sub-bands.
- *
- *     In addition, per-band (2.4 and 5 Ghz) saturation txpowers are provided.
- *
- *     See struct iwl4965_eeprom_calib_info (and the tree of structures
- *     contained within it) for format, and struct iwl4965_eeprom for
- *     locations in EEPROM.
- *
- * "Initialization alive" notification (see struct iwl4965_init_alive_resp)
- * consists of:
- *
- * 1)  Temperature calculation parameters.
- *
- * 2)  Power supply voltage measurement.
- *
- * 3)  Tx gain compensation to balance 2 transmitters for MIMO use.
- *
- * Statistics notifications deliver:
- *
- * 1)  Current values for temperature param R4.
- */
-
-/**
- * To calculate a txpower setting for a given desired target txpower, channel,
- * modulation bit rate, and transmitter chain (4965 has 2 transmitters to
- * support MIMO and transmit diversity), driver must do the following:
- *
- * 1)  Compare desired txpower vs. (EEPROM) regulatory limit for this channel.
- *     Do not exceed regulatory limit; reduce target txpower if necessary.
- *
- *     If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
- *     2 transmitters will be used simultaneously; driver must reduce the
- *     regulatory limit by 3 dB (half-power) for each transmitter, so the
- *     combined total output of the 2 transmitters is within regulatory limits.
- *
- *
- * 2)  Compare target txpower vs. (EEPROM) saturation txpower *reduced by
- *     backoff for this bit rate*.  Do not exceed (saturation - backoff[rate]);
- *     reduce target txpower if necessary.
- *
- *     Backoff values below are in 1/2 dB units (equivalent to steps in
- *     txpower gain tables):
- *
- *     OFDM 6 - 36 MBit:  10 steps (5 dB)
- *     OFDM 48 MBit:      15 steps (7.5 dB)
- *     OFDM 54 MBit:      17 steps (8.5 dB)
- *     OFDM 60 MBit:      20 steps (10 dB)
- *     CCK all rates:     10 steps (5 dB)
- *
- *     Backoff values apply to saturation txpower on a per-transmitter basis;
- *     when using MIMO (2 transmitters), each transmitter uses the same
- *     saturation level provided in EEPROM, and the same backoff values;
- *     no reduction (such as with regulatory txpower limits) is required.
- *
- *     Saturation and Backoff values apply equally to 20 Mhz (legacy) channel
- *     widths and 40 Mhz (.11n HT40) channel widths; there is no separate
- *     factory measurement for ht40 channels.
- *
- *     The result of this step is the final target txpower.  The rest of
- *     the steps figure out the proper settings for the device to achieve
- *     that target txpower.
- *
- *
- * 3)  Determine (EEPROM) calibration sub band for the target channel, by
- *     comparing against first and last channels in each sub band
- *     (see struct iwl4965_eeprom_calib_subband_info).
- *
- *
- * 4)  Linearly interpolate (EEPROM) factory calibration measurement sets,
- *     referencing the 2 factory-measured (sample) channels within the sub band.
- *
- *     Interpolation is based on difference between target channel's frequency
- *     and the sample channels' frequencies.  Since channel numbers are based
- *     on frequency (5 MHz between each channel number), this is equivalent
- *     to interpolating based on channel number differences.
- *
- *     Note that the sample channels may or may not be the channels at the
- *     edges of the sub band.  The target channel may be "outside" of the
- *     span of the sampled channels.
- *
- *     Driver may choose the pair (for 2 Tx chains) of measurements (see
- *     struct iwl4965_eeprom_calib_ch_info) for which the actual measured
- *     txpower comes closest to the desired txpower.  Usually, though,
- *     the middle set of measurements is closest to the regulatory limits,
- *     and is therefore a good choice for all txpower calculations (this
- *     assumes that high accuracy is needed for maximizing legal txpower,
- *     while lower txpower configurations do not need as much accuracy).
- *
- *     Driver should interpolate both members of the chosen measurement pair,
- *     i.e. for both Tx chains (radio transmitters), unless the driver knows
- *     that only one of the chains will be used (e.g. only one tx antenna
- *     connected, but this should be unusual).  The rate scaling algorithm
- *     switches antennas to find best performance, so both Tx chains will
- *     be used (although only one at a time) even for non-MIMO transmissions.
- *
- *     Driver should interpolate factory values for temperature, gain table
- *     index, and actual power.  The power amplifier detector values are
- *     not used by the driver.
- *
- *     Sanity check:  If the target channel happens to be one of the sample
- *     channels, the results should agree with the sample channel's
- *     measurements!
- *
- *
- * 5)  Find difference between desired txpower and (interpolated)
- *     factory-measured txpower.  Using (interpolated) factory gain table index
- *     (shown elsewhere) as a starting point, adjust this index lower to
- *     increase txpower, or higher to decrease txpower, until the target
- *     txpower is reached.  Each step in the gain table is 1/2 dB.
- *
- *     For example, if factory measured txpower is 16 dBm, and target txpower
- *     is 13 dBm, add 6 steps to the factory gain index to reduce txpower
- *     by 3 dB.
- *
- *
- * 6)  Find difference between current device temperature and (interpolated)
- *     factory-measured temperature for sub-band.  Factory values are in
- *     degrees Celsius.  To calculate current temperature, see comments for
- *     "4965 temperature calculation".
- *
- *     If current temperature is higher than factory temperature, driver must
- *     increase gain (lower gain table index), and vice verse.
- *
- *     Temperature affects gain differently for different channels:
- *
- *     2.4 GHz all channels:  3.5 degrees per half-dB step
- *     5 GHz channels 34-43:  4.5 degrees per half-dB step
- *     5 GHz channels >= 44:  4.0 degrees per half-dB step
- *
- *     NOTE:  Temperature can increase rapidly when transmitting, especially
- *            with heavy traffic at high txpowers.  Driver should update
- *            temperature calculations often under these conditions to
- *            maintain strong txpower in the face of rising temperature.
- *
- *
- * 7)  Find difference between current power supply voltage indicator
- *     (from "initialize alive") and factory-measured power supply voltage
- *     indicator (EEPROM).
- *
- *     If the current voltage is higher (indicator is lower) than factory
- *     voltage, gain should be reduced (gain table index increased) by:
- *
- *     (eeprom - current) / 7
- *
- *     If the current voltage is lower (indicator is higher) than factory
- *     voltage, gain should be increased (gain table index decreased) by:
- *
- *     2 * (current - eeprom) / 7
- *
- *     If number of index steps in either direction turns out to be > 2,
- *     something is wrong ... just use 0.
- *
- *     NOTE:  Voltage compensation is independent of band/channel.
- *
- *     NOTE:  "Initialize" uCode measures current voltage, which is assumed
- *            to be constant after this initial measurement.  Voltage
- *            compensation for txpower (number of steps in gain table)
- *            may be calculated once and used until the next uCode bootload.
- *
- *
- * 8)  If setting up txpowers for MIMO rates (rate indexes 8-15, 24-31),
- *     adjust txpower for each transmitter chain, so txpower is balanced
- *     between the two chains.  There are 5 pairs of tx_atten[group][chain]
- *     values in "initialize alive", one pair for each of 5 channel ranges:
- *
- *     Group 0:  5 GHz channel 34-43
- *     Group 1:  5 GHz channel 44-70
- *     Group 2:  5 GHz channel 71-124
- *     Group 3:  5 GHz channel 125-200
- *     Group 4:  2.4 GHz all channels
- *
- *     Add the tx_atten[group][chain] value to the index for the target chain.
- *     The values are signed, but are in pairs of 0 and a non-negative number,
- *     so as to reduce gain (if necessary) of the "hotter" channel.  This
- *     avoids any need to double-check for regulatory compliance after
- *     this step.
- *
- *
- * 9)  If setting up for a CCK rate, lower the gain by adding a CCK compensation
- *     value to the index:
- *
- *     Hardware rev B:  9 steps (4.5 dB)
- *     Hardware rev C:  5 steps (2.5 dB)
- *
- *     Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
- *     bits [3:2], 1 = B, 2 = C.
- *
- *     NOTE:  This compensation is in addition to any saturation backoff that
- *            might have been applied in an earlier step.
- *
- *
- * 10) Select the gain table, based on band (2.4 vs 5 GHz).
- *
- *     Limit the adjusted index to stay within the table!
- *
- *
- * 11) Read gain table entries for DSP and radio gain, place into appropriate
- *     location(s) in command (struct iwl4965_txpowertable_cmd).
- */
-
-/**
- * When MIMO is used (2 transmitters operating simultaneously), driver should
- * limit each transmitter to deliver a max of 3 dB below the regulatory limit
- * for the device.  That is, use half power for each transmitter, so total
- * txpower is within regulatory limits.
- *
- * The value "6" represents number of steps in gain table to reduce power 3 dB.
- * Each step is 1/2 dB.
- */
-#define IWL_TX_POWER_MIMO_REGULATORY_COMPENSATION (6)
-
-/**
- * CCK gain compensation.
- *
- * When calculating txpowers for CCK, after making sure that the target power
- * is within regulatory and saturation limits, driver must additionally
- * back off gain by adding these values to the gain table index.
- *
- * Hardware rev for 4965 can be determined by reading CSR_HW_REV_WA_REG,
- * bits [3:2], 1 = B, 2 = C.
- */
-#define IWL_TX_POWER_CCK_COMPENSATION_B_STEP (9)
-#define IWL_TX_POWER_CCK_COMPENSATION_C_STEP (5)
-
-/*
- * 4965 power supply voltage compensation for txpower
- */
-#define TX_POWER_IWL_VOLTAGE_CODES_PER_03V   (7)
-
-/**
- * Gain tables.
- *
- * The following tables contain pair of values for setting txpower, i.e.
- * gain settings for the output of the device's digital signal processor (DSP),
- * and for the analog gain structure of the transmitter.
- *
- * Each entry in the gain tables represents a step of 1/2 dB.  Note that these
- * are *relative* steps, not indications of absolute output power.  Output
- * power varies with temperature, voltage, and channel frequency, and also
- * requires consideration of average power (to satisfy regulatory constraints),
- * and peak power (to avoid distortion of the output signal).
- *
- * Each entry contains two values:
- * 1)  DSP gain (or sometimes called DSP attenuation).  This is a fine-grained
- *     linear value that multiplies the output of the digital signal processor,
- *     before being sent to the analog radio.
- * 2)  Radio gain.  This sets the analog gain of the radio Tx path.
- *     It is a coarser setting, and behaves in a logarithmic (dB) fashion.
- *
- * EEPROM contains factory calibration data for txpower.  This maps actual
- * measured txpower levels to gain settings in the "well known" tables
- * below ("well-known" means here that both factory calibration *and* the
- * driver work with the same table).
- *
- * There are separate tables for 2.4 GHz and 5 GHz bands.  The 5 GHz table
- * has an extension (into negative indexes), in case the driver needs to
- * boost power setting for high device temperatures (higher than would be
- * present during factory calibration).  A 5 Ghz EEPROM index of "40"
- * corresponds to the 49th entry in the table used by the driver.
- */
-#define MIN_TX_GAIN_INDEX		(0)  /* highest gain, lowest idx, 2.4 */
-#define MIN_TX_GAIN_INDEX_52GHZ_EXT	(-9) /* highest gain, lowest idx, 5 */
-
-/**
- * 2.4 GHz gain table
- *
- * Index    Dsp gain   Radio gain
- *   0        110         0x3f      (highest gain)
- *   1        104         0x3f
- *   2         98         0x3f
- *   3        110         0x3e
- *   4        104         0x3e
- *   5         98         0x3e
- *   6        110         0x3d
- *   7        104         0x3d
- *   8         98         0x3d
- *   9        110         0x3c
- *  10        104         0x3c
- *  11         98         0x3c
- *  12        110         0x3b
- *  13        104         0x3b
- *  14         98         0x3b
- *  15        110         0x3a
- *  16        104         0x3a
- *  17         98         0x3a
- *  18        110         0x39
- *  19        104         0x39
- *  20         98         0x39
- *  21        110         0x38
- *  22        104         0x38
- *  23         98         0x38
- *  24        110         0x37
- *  25        104         0x37
- *  26         98         0x37
- *  27        110         0x36
- *  28        104         0x36
- *  29         98         0x36
- *  30        110         0x35
- *  31        104         0x35
- *  32         98         0x35
- *  33        110         0x34
- *  34        104         0x34
- *  35         98         0x34
- *  36        110         0x33
- *  37        104         0x33
- *  38         98         0x33
- *  39        110         0x32
- *  40        104         0x32
- *  41         98         0x32
- *  42        110         0x31
- *  43        104         0x31
- *  44         98         0x31
- *  45        110         0x30
- *  46        104         0x30
- *  47         98         0x30
- *  48        110          0x6
- *  49        104          0x6
- *  50         98          0x6
- *  51        110          0x5
- *  52        104          0x5
- *  53         98          0x5
- *  54        110          0x4
- *  55        104          0x4
- *  56         98          0x4
- *  57        110          0x3
- *  58        104          0x3
- *  59         98          0x3
- *  60        110          0x2
- *  61        104          0x2
- *  62         98          0x2
- *  63        110          0x1
- *  64        104          0x1
- *  65         98          0x1
- *  66        110          0x0
- *  67        104          0x0
- *  68         98          0x0
- *  69         97            0
- *  70         96            0
- *  71         95            0
- *  72         94            0
- *  73         93            0
- *  74         92            0
- *  75         91            0
- *  76         90            0
- *  77         89            0
- *  78         88            0
- *  79         87            0
- *  80         86            0
- *  81         85            0
- *  82         84            0
- *  83         83            0
- *  84         82            0
- *  85         81            0
- *  86         80            0
- *  87         79            0
- *  88         78            0
- *  89         77            0
- *  90         76            0
- *  91         75            0
- *  92         74            0
- *  93         73            0
- *  94         72            0
- *  95         71            0
- *  96         70            0
- *  97         69            0
- *  98         68            0
- */
-
-/**
- * 5 GHz gain table
- *
- * Index    Dsp gain   Radio gain
- *  -9 	      123         0x3F      (highest gain)
- *  -8 	      117         0x3F
- *  -7        110         0x3F
- *  -6        104         0x3F
- *  -5         98         0x3F
- *  -4        110         0x3E
- *  -3        104         0x3E
- *  -2         98         0x3E
- *  -1        110         0x3D
- *   0        104         0x3D
- *   1         98         0x3D
- *   2        110         0x3C
- *   3        104         0x3C
- *   4         98         0x3C
- *   5        110         0x3B
- *   6        104         0x3B
- *   7         98         0x3B
- *   8        110         0x3A
- *   9        104         0x3A
- *  10         98         0x3A
- *  11        110         0x39
- *  12        104         0x39
- *  13         98         0x39
- *  14        110         0x38
- *  15        104         0x38
- *  16         98         0x38
- *  17        110         0x37
- *  18        104         0x37
- *  19         98         0x37
- *  20        110         0x36
- *  21        104         0x36
- *  22         98         0x36
- *  23        110         0x35
- *  24        104         0x35
- *  25         98         0x35
- *  26        110         0x34
- *  27        104         0x34
- *  28         98         0x34
- *  29        110         0x33
- *  30        104         0x33
- *  31         98         0x33
- *  32        110         0x32
- *  33        104         0x32
- *  34         98         0x32
- *  35        110         0x31
- *  36        104         0x31
- *  37         98         0x31
- *  38        110         0x30
- *  39        104         0x30
- *  40         98         0x30
- *  41        110         0x25
- *  42        104         0x25
- *  43         98         0x25
- *  44        110         0x24
- *  45        104         0x24
- *  46         98         0x24
- *  47        110         0x23
- *  48        104         0x23
- *  49         98         0x23
- *  50        110         0x22
- *  51        104         0x18
- *  52         98         0x18
- *  53        110         0x17
- *  54        104         0x17
- *  55         98         0x17
- *  56        110         0x16
- *  57        104         0x16
- *  58         98         0x16
- *  59        110         0x15
- *  60        104         0x15
- *  61         98         0x15
- *  62        110         0x14
- *  63        104         0x14
- *  64         98         0x14
- *  65        110         0x13
- *  66        104         0x13
- *  67         98         0x13
- *  68        110         0x12
- *  69        104         0x08
- *  70         98         0x08
- *  71        110         0x07
- *  72        104         0x07
- *  73         98         0x07
- *  74        110         0x06
- *  75        104         0x06
- *  76         98         0x06
- *  77        110         0x05
- *  78        104         0x05
- *  79         98         0x05
- *  80        110         0x04
- *  81        104         0x04
- *  82         98         0x04
- *  83        110         0x03
- *  84        104         0x03
- *  85         98         0x03
- *  86        110         0x02
- *  87        104         0x02
- *  88         98         0x02
- *  89        110         0x01
- *  90        104         0x01
- *  91         98         0x01
- *  92        110         0x00
- *  93        104         0x00
- *  94         98         0x00
- *  95         93         0x00
- *  96         88         0x00
- *  97         83         0x00
- *  98         78         0x00
- */
-
-
-/**
- * Sanity checks and default values for EEPROM regulatory levels.
- * If EEPROM values fall outside MIN/MAX range, use default values.
- *
- * Regulatory limits refer to the maximum average txpower allowed by
- * regulatory agencies in the geographies in which the device is meant
- * to be operated.  These limits are SKU-specific (i.e. geography-specific),
- * and channel-specific; each channel has an individual regulatory limit
- * listed in the EEPROM.
- *
- * Units are in half-dBm (i.e. "34" means 17 dBm).
- */
-#define IWL_TX_POWER_DEFAULT_REGULATORY_24   (34)
-#define IWL_TX_POWER_DEFAULT_REGULATORY_52   (34)
-#define IWL_TX_POWER_REGULATORY_MIN          (0)
-#define IWL_TX_POWER_REGULATORY_MAX          (34)
-
-/**
- * Sanity checks and default values for EEPROM saturation levels.
- * If EEPROM values fall outside MIN/MAX range, use default values.
- *
- * Saturation is the highest level that the output power amplifier can produce
- * without significant clipping distortion.  This is a "peak" power level.
- * Different types of modulation (i.e. various "rates", and OFDM vs. CCK)
- * require differing amounts of backoff, relative to their average power output,
- * in order to avoid clipping distortion.
- *
- * Driver must make sure that it is violating neither the saturation limit,
- * nor the regulatory limit, when calculating Tx power settings for various
- * rates.
- *
- * Units are in half-dBm (i.e. "38" means 19 dBm).
- */
-#define IWL_TX_POWER_DEFAULT_SATURATION_24   (38)
-#define IWL_TX_POWER_DEFAULT_SATURATION_52   (38)
-#define IWL_TX_POWER_SATURATION_MIN          (20)
-#define IWL_TX_POWER_SATURATION_MAX          (50)
-
-/**
- * Channel groups used for Tx Attenuation calibration (MIMO tx channel balance)
- * and thermal Txpower calibration.
- *
- * When calculating txpower, driver must compensate for current device
- * temperature; higher temperature requires higher gain.  Driver must calculate
- * current temperature (see "4965 temperature calculation"), then compare vs.
- * factory calibration temperature in EEPROM; if current temperature is higher
- * than factory temperature, driver must *increase* gain by proportions shown
- * in table below.  If current temperature is lower than factory, driver must
- * *decrease* gain.
- *
- * Different frequency ranges require different compensation, as shown below.
- */
-/* Group 0, 5.2 GHz ch 34-43:  4.5 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR1_FCH 34
-#define CALIB_IWL_TX_ATTEN_GR1_LCH 43
-
-/* Group 1, 5.3 GHz ch 44-70:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR2_FCH 44
-#define CALIB_IWL_TX_ATTEN_GR2_LCH 70
-
-/* Group 2, 5.5 GHz ch 71-124:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR3_FCH 71
-#define CALIB_IWL_TX_ATTEN_GR3_LCH 124
-
-/* Group 3, 5.7 GHz ch 125-200:  4.0 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR4_FCH 125
-#define CALIB_IWL_TX_ATTEN_GR4_LCH 200
-
-/* Group 4, 2.4 GHz all channels:  3.5 degrees per 1/2 dB. */
-#define CALIB_IWL_TX_ATTEN_GR5_FCH 1
-#define CALIB_IWL_TX_ATTEN_GR5_LCH 20
-
-enum {
-	CALIB_CH_GROUP_1 = 0,
-	CALIB_CH_GROUP_2 = 1,
-	CALIB_CH_GROUP_3 = 2,
-	CALIB_CH_GROUP_4 = 3,
-	CALIB_CH_GROUP_5 = 4,
-	CALIB_CH_GROUP_MAX
-};
-
-/********************* END TXPOWER *****************************************/
-
-
-/**
- * Tx/Rx Queues
- *
- * Most communication between driver and 4965 is via queues of data buffers.
- * For example, all commands that the driver issues to device's embedded
- * controller (uCode) are via the command queue (one of the Tx queues).  All
- * uCode command responses/replies/notifications, including Rx frames, are
- * conveyed from uCode to driver via the Rx queue.
- *
- * Most support for these queues, including handshake support, resides in
- * structures in host DRAM, shared between the driver and the device.  When
- * allocating this memory, the driver must make sure that data written by
- * the host CPU updates DRAM immediately (and does not get "stuck" in CPU's
- * cache memory), so DRAM and cache are consistent, and the device can
- * immediately see changes made by the driver.
- *
- * 4965 supports up to 16 DRAM-based Tx queues, and services these queues via
- * up to 7 DMA channels (FIFOs).  Each Tx queue is supported by a circular array
- * in DRAM containing 256 Transmit Frame Descriptors (TFDs).
- */
-#define IWL49_NUM_FIFOS 	7
-#define IWL49_CMD_FIFO_NUM	4
-#define IWL49_NUM_QUEUES	16
-#define IWL49_NUM_AMPDU_QUEUES	8
-
-
-/**
- * struct iwl4965_schedq_bc_tbl
- *
- * Byte Count table
- *
- * Each Tx queue uses a byte-count table containing 320 entries:
- * one 16-bit entry for each of 256 TFDs, plus an additional 64 entries that
- * duplicate the first 64 entries (to avoid wrap-around within a Tx window;
- * max Tx window is 64 TFDs).
- *
- * When driver sets up a new TFD, it must also enter the total byte count
- * of the frame to be transmitted into the corresponding entry in the byte
- * count table for the chosen Tx queue.  If the TFD index is 0-63, the driver
- * must duplicate the byte count entry in corresponding index 256-319.
- *
- * padding puts each byte count table on a 1024-byte boundary;
- * 4965 assumes tables are separated by 1024 bytes.
- */
-struct iwl4965_scd_bc_tbl {
-	__le16 tfd_offset[TFD_QUEUE_BC_SIZE];
-	u8 pad[1024 - (TFD_QUEUE_BC_SIZE) * sizeof(__le16)];
-} __packed;
-
-#endif /* !__iwl_4965_hw_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c	2012-03-24 01:12:30.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-5000.c	2012-03-24 03:33:12.000000000 -0400
@@ -402,8 +402,6 @@
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -471,8 +469,6 @@
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -534,6 +530,9 @@
 struct iwl_cfg iwl5300_agn_cfg = {
 	.name = "Intel(R) Ultimate N WiFi Link 5300 AGN",
 	IWL_DEVICE_5000,
+	/* at least EEPROM 0x11A has wrong info */
+	.valid_tx_ant = ANT_ABC,	/* .cfg overwrite */
+	.valid_rx_ant = ANT_ABC,	/* .cfg overwrite */
 	.ht_params = &iwl5000_ht_params,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-6000.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-6000.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-6000.c	2012-03-24 01:12:34.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-6000.c	2012-03-24 03:33:15.000000000 -0400
@@ -67,13 +67,13 @@
 #define _IWL6050_MODULE_FIRMWARE(api) IWL6050_FW_PRE /*(DEBLOBBED)*/
 #define IWL6050_MODULE_FIRMWARE(api) _IWL6050_MODULE_FIRMWARE(api)
 
-#define IWL6000G2A_FW_PRE "/*(DEBLOBBED)*/"
-#define _IWL6000G2A_MODULE_FIRMWARE(api) IWL6000G2A_FW_PRE /*(DEBLOBBED)*/
-#define IWL6000G2A_MODULE_FIRMWARE(api) _IWL6000G2A_MODULE_FIRMWARE(api)
+#define IWL6005_FW_PRE "/*(DEBLOBBED)*/"
+#define _IWL6005_MODULE_FIRMWARE(api) IWL6005_FW_PRE /*(DEBLOBBED)*/
+#define IWL6005_MODULE_FIRMWARE(api) _IWL6005_MODULE_FIRMWARE(api)
 
-#define IWL6000G2B_FW_PRE "/*(DEBLOBBED)*/"
-#define _IWL6000G2B_MODULE_FIRMWARE(api) IWL6000G2B_FW_PRE /*(DEBLOBBED)*/
-#define IWL6000G2B_MODULE_FIRMWARE(api) _IWL6000G2B_MODULE_FIRMWARE(api)
+#define IWL6030_FW_PRE "/*(DEBLOBBED)*/"
+#define _IWL6030_MODULE_FIRMWARE(api) IWL6030_FW_PRE /*(DEBLOBBED)*/
+#define IWL6030_MODULE_FIRMWARE(api) _IWL6030_MODULE_FIRMWARE(api)
 
 static void iwl6000_set_ct_threshold(struct iwl_priv *priv)
 {
@@ -90,7 +90,7 @@
 				CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6);
 }
 
-static void iwl6050g2_additional_nic_config(struct iwl_priv *priv)
+static void iwl6150_additional_nic_config(struct iwl_priv *priv)
 {
 	/* Indicate calibration version to uCode. */
 	if (priv->cfg->ops->lib->eeprom_ops.calib_version(priv) >= 6)
@@ -343,8 +343,6 @@
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -354,7 +352,7 @@
 	}
 };
 
-static struct iwl_lib_ops iwl6000g2b_lib = {
+static struct iwl_lib_ops iwl6030_lib = {
 	.set_hw_params = iwl6000_hw_set_hw_params,
 	.txq_update_byte_cnt_tbl = iwlagn_txq_update_byte_cnt_tbl,
 	.txq_inval_byte_cnt_tbl = iwlagn_txq_inval_byte_cnt_tbl,
@@ -415,8 +413,6 @@
 		.bt_stats_read = iwl_ucode_bt_stats_read,
 		.reply_tx_error = iwl_reply_tx_error_read,
 	},
-	.check_plcp_health = iwl_good_plcp_health,
-	.check_ack_health = iwl_good_ack_health,
 	.txfifo_flush = iwlagn_txfifo_flush,
 	.dev_txfifo_flush = iwlagn_dev_txfifo_flush,
 	.tt_ops = {
@@ -430,8 +426,8 @@
 	.additional_nic_config = &iwl6050_additional_nic_config,
 };
 
-static struct iwl_nic_ops iwl6050g2_nic_ops = {
-	.additional_nic_config = &iwl6050g2_additional_nic_config,
+static struct iwl_nic_ops iwl6150_nic_ops = {
+	.additional_nic_config = &iwl6150_additional_nic_config,
 };
 
 static const struct iwl_ops iwl6000_ops = {
@@ -451,17 +447,17 @@
 	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
-static const struct iwl_ops iwl6050g2_ops = {
+static const struct iwl_ops iwl6150_ops = {
 	.lib = &iwl6000_lib,
 	.hcmd = &iwlagn_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
-	.nic = &iwl6050g2_nic_ops,
+	.nic = &iwl6150_nic_ops,
 	.ieee80211_ops = &iwlagn_hw_ops,
 };
 
-static const struct iwl_ops iwl6000g2b_ops = {
-	.lib = &iwl6000g2b_lib,
+static const struct iwl_ops iwl6030_ops = {
+	.lib = &iwl6030_lib,
 	.hcmd = &iwlagn_bt_hcmd,
 	.utils = &iwlagn_hcmd_utils,
 	.led = &iwlagn_led_ops,
@@ -479,7 +475,6 @@
 	.shadow_ram_support = true,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -503,7 +498,6 @@
 	.shadow_ram_support = true,
 	.led_compensation = 51,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -526,7 +520,6 @@
 	.shadow_ram_support = true,
 	.led_compensation = 57,
 	.chain_noise_num_beacons = IWL_CAL_NUM_BEACONS,
-	.supports_idle = true,
 	.adv_thermal_throttle = true,
 	.support_ct_kill_exit = true,
 	.plcp_delta_threshold = IWL_MAX_PLCP_ERR_THRESHOLD_DEF,
@@ -555,11 +548,11 @@
 };
 
 #define IWL_DEVICE_6005						\
-	.fw_name_pre = IWL6000G2A_FW_PRE,			\
+	.fw_name_pre = IWL6005_FW_PRE,			\
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,		\
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,	\
+	.eeprom_ver = EEPROM_6005_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION,	\
 	.ops = &iwl6000_ops,					\
 	.mod_params = &iwlagn_mod_params,			\
 	.base_params = &iwl6000_g2_base_params,			\
@@ -584,12 +577,12 @@
 };
 
 #define IWL_DEVICE_6030						\
-	.fw_name_pre = IWL6000G2B_FW_PRE,			\
+	.fw_name_pre = IWL6030_FW_PRE,			\
 	.ucode_api_max = IWL6000G2_UCODE_API_MAX,		\
 	.ucode_api_min = IWL6000G2_UCODE_API_MIN,		\
-	.eeprom_ver = EEPROM_6000G2_EEPROM_VERSION,		\
-	.eeprom_calib_ver = EEPROM_6000G2_TX_POWER_VERSION,	\
-	.ops = &iwl6000g2b_ops,					\
+	.eeprom_ver = EEPROM_6030_EEPROM_VERSION,		\
+	.eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION,	\
+	.ops = &iwl6030_ops,					\
 	.mod_params = &iwlagn_mod_params,			\
 	.base_params = &iwl6000_g2_base_params,			\
 	.bt_params = &iwl6000_bt_params,			\
@@ -708,9 +701,9 @@
 	.fw_name_pre = IWL6050_FW_PRE,
 	.ucode_api_max = IWL6050_UCODE_API_MAX,
 	.ucode_api_min = IWL6050_UCODE_API_MIN,
-	.eeprom_ver = EEPROM_6050G2_EEPROM_VERSION,
-	.eeprom_calib_ver = EEPROM_6050G2_TX_POWER_VERSION,
-	.ops = &iwl6050g2_ops,
+	.eeprom_ver = EEPROM_6150_EEPROM_VERSION,
+	.eeprom_calib_ver = EEPROM_6150_TX_POWER_VERSION,
+	.ops = &iwl6150_ops,
 	.mod_params = &iwlagn_mod_params,
 	.base_params = &iwl6050_base_params,
 	.ht_params = &iwl6000_ht_params,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c	2012-03-24 01:12:19.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn.c	2012-03-24 03:33:09.000000000 -0400
@@ -59,6 +59,7 @@
 #include "iwl-sta.h"
 #include "iwl-agn-calib.h"
 #include "iwl-agn.h"
+#include "iwl-agn-led.h"
 
 
 /******************************************************************************
@@ -85,7 +86,6 @@
 MODULE_VERSION(DRV_VERSION);
 MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
 MODULE_LICENSE("GPL");
-MODULE_ALIAS("iwl4965");
 
 static int iwlagn_ant_coupling;
 static bool iwlagn_bt_ch_announce = 1;
@@ -424,47 +424,6 @@
 	return 0;
 }
 
-/******************************************************************************
- *
- * Generic RX handler implementations
- *
- ******************************************************************************/
-static void iwl_rx_reply_alive(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_alive_resp *palive;
-	struct delayed_work *pwork;
-
-	palive = &pkt->u.alive_frame;
-
-	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
-		       "0x%01X 0x%01X\n",
-		       palive->is_valid, palive->ver_type,
-		       palive->ver_subtype);
-
-	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
-		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
-		memcpy(&priv->card_alive_init,
-		       &pkt->u.alive_frame,
-		       sizeof(struct iwl_init_alive_resp));
-		pwork = &priv->init_alive_start;
-	} else {
-		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
-		memcpy(&priv->card_alive, &pkt->u.alive_frame,
-		       sizeof(struct iwl_alive_resp));
-		pwork = &priv->alive_start;
-	}
-
-	/* We delay the ALIVE response by 5ms to
-	 * give the HW RF Kill time to activate... */
-	if (palive->is_valid == UCODE_VALID_OK)
-		queue_delayed_work(priv->workqueue, pwork,
-				   msecs_to_jiffies(5));
-	else
-		IWL_WARN(priv, "uCode did not respond OK.\n");
-}
-
 static void iwl_bg_beacon_update(struct work_struct *work)
 {
 	struct iwl_priv *priv =
@@ -699,83 +658,6 @@
 	}
 }
 
-static void iwl_rx_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl4965_beacon_notif *beacon =
-		(struct iwl4965_beacon_notif *)pkt->u.raw;
-#ifdef CONFIG_IWLWIFI_DEBUG
-	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
-
-	IWL_DEBUG_RX(priv, "beacon status %x retries %d iss %d "
-		"tsf %d %d rate %d\n",
-		le32_to_cpu(beacon->beacon_notify_hdr.u.status) & TX_STATUS_MSK,
-		beacon->beacon_notify_hdr.failure_frame,
-		le32_to_cpu(beacon->ibss_mgr_status),
-		le32_to_cpu(beacon->high_tsf),
-		le32_to_cpu(beacon->low_tsf), rate);
-#endif
-
-	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
-
-	if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
-		queue_work(priv->workqueue, &priv->beacon_update);
-}
-
-/* Handle notification from uCode that card's power state is changing
- * due to software, hardware, or critical temperature RFKILL */
-static void iwl_rx_card_state_notif(struct iwl_priv *priv,
-				    struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
-	unsigned long status = priv->status;
-
-	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
-			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
-			  (flags & SW_CARD_DISABLED) ? "Kill" : "On",
-			  (flags & CT_CARD_DISABLED) ?
-			  "Reached" : "Not reached");
-
-	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
-		     CT_CARD_DISABLED)) {
-
-		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
-			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
-
-		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);
-			iwl_write_direct32(priv, HBUS_TARG_MBX_C,
-					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
-		}
-		if (flags & CT_CARD_DISABLED)
-			iwl_tt_enter_ct_kill(priv);
-	}
-	if (!(flags & CT_CARD_DISABLED))
-		iwl_tt_exit_ct_kill(priv);
-
-	if (flags & HW_CARD_DISABLED)
-		set_bit(STATUS_RF_KILL_HW, &priv->status);
-	else
-		clear_bit(STATUS_RF_KILL_HW, &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)))
-		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
-			test_bit(STATUS_RF_KILL_HW, &priv->status));
-	else
-		wake_up_interruptible(&priv->wait_command_queue);
-}
-
 static void iwl_bg_tx_flush(struct work_struct *work)
 {
 	struct iwl_priv *priv =
@@ -795,58 +677,13 @@
 }
 
 /**
- * iwl_setup_rx_handlers - Initialize Rx handler callbacks
- *
- * Setup the RX handlers for each of the reply types sent from the uCode
- * to the host.
- *
- * This function chains into the hardware specific files for them to setup
- * any hardware specific handlers as well.
- */
-static void iwl_setup_rx_handlers(struct iwl_priv *priv)
-{
-	priv->rx_handlers[REPLY_ALIVE] = iwl_rx_reply_alive;
-	priv->rx_handlers[REPLY_ERROR] = iwl_rx_reply_error;
-	priv->rx_handlers[CHANNEL_SWITCH_NOTIFICATION] = iwl_rx_csa;
-	priv->rx_handlers[SPECTRUM_MEASURE_NOTIFICATION] =
-			iwl_rx_spectrum_measure_notif;
-	priv->rx_handlers[PM_SLEEP_NOTIFICATION] = iwl_rx_pm_sleep_notif;
-	priv->rx_handlers[PM_DEBUG_STATISTIC_NOTIFIC] =
-	    iwl_rx_pm_debug_statistics_notif;
-	priv->rx_handlers[BEACON_NOTIFICATION] = iwl_rx_beacon_notif;
-
-	/*
-	 * The same handler is used for both the REPLY to a discrete
-	 * statistics request from the host as well as for the periodic
-	 * statistics notifications (after received beacons) from the uCode.
-	 */
-	priv->rx_handlers[REPLY_STATISTICS_CMD] = iwl_reply_statistics;
-	priv->rx_handlers[STATISTICS_NOTIFICATION] = iwl_rx_statistics;
-
-	iwl_setup_rx_scan_handlers(priv);
-
-	/* status change handler */
-	priv->rx_handlers[CARD_STATE_NOTIFICATION] = iwl_rx_card_state_notif;
-
-	priv->rx_handlers[MISSED_BEACONS_NOTIFICATION] =
-	    iwl_rx_missed_beacon_notif;
-	/* Rx handlers */
-	priv->rx_handlers[REPLY_RX_PHY_CMD] = iwlagn_rx_reply_rx_phy;
-	priv->rx_handlers[REPLY_RX_MPDU_CMD] = iwlagn_rx_reply_rx;
-	/* block ack */
-	priv->rx_handlers[REPLY_COMPRESSED_BA] = iwlagn_rx_reply_compressed_ba;
-	/* Set up hardware specific Rx handlers */
-	priv->cfg->ops->lib->rx_handler_setup(priv);
-}
-
-/**
  * iwl_rx_handle - Main entry function for receiving responses from uCode
  *
  * Uses the priv->rx_handlers callback function array to invoke
  * the appropriate handlers, including command responses,
  * frame-received notifications, and other notifications.
  */
-void iwl_rx_handle(struct iwl_priv *priv)
+static void iwl_rx_handle(struct iwl_priv *priv)
 {
 	struct iwl_rx_mem_buffer *rxb;
 	struct iwl_rx_packet *pkt;
@@ -910,6 +747,27 @@
 			(pkt->hdr.cmd != STATISTICS_NOTIFICATION) &&
 			(pkt->hdr.cmd != REPLY_TX);
 
+		/*
+		 * Do the notification wait before RX handlers so
+		 * even if the RX handler consumes the RXB we have
+		 * access to it in the notification wait entry.
+		 */
+		if (!list_empty(&priv->_agn.notif_waits)) {
+			struct iwl_notification_wait *w;
+
+			spin_lock(&priv->_agn.notif_wait_lock);
+			list_for_each_entry(w, &priv->_agn.notif_waits, list) {
+				if (w->cmd == pkt->hdr.cmd) {
+					w->triggered = true;
+					if (w->fn)
+						w->fn(priv, pkt);
+				}
+			}
+			spin_unlock(&priv->_agn.notif_wait_lock);
+
+			wake_up_all(&priv->_agn.notif_waitq);
+		}
+
 		/* Based on type of command response or notification,
 		 *   handle those that need handling via function in
 		 *   rx_handlers table.  See iwl_setup_rx_handlers() */
@@ -1379,66 +1237,6 @@
 		iwl_enable_rfkill_int(priv);
 }
 
-/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
-#define ACK_CNT_RATIO (50)
-#define BA_TIMEOUT_CNT (5)
-#define BA_TIMEOUT_MAX (16)
-
-/**
- * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
- *
- * When the ACK count ratio is 0 and aggregated BA timeout retries exceeding
- * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
- * operation state.
- */
-bool iwl_good_ack_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int actual_ack_cnt_delta, expected_ack_cnt_delta;
-	int ba_timeout_delta;
-
-	actual_ack_cnt_delta =
-		le32_to_cpu(pkt->u.stats.tx.actual_ack_cnt) -
-		le32_to_cpu(priv->_agn.statistics.tx.actual_ack_cnt);
-	expected_ack_cnt_delta =
-		le32_to_cpu(pkt->u.stats.tx.expected_ack_cnt) -
-		le32_to_cpu(priv->_agn.statistics.tx.expected_ack_cnt);
-	ba_timeout_delta =
-		le32_to_cpu(pkt->u.stats.tx.agg.ba_timeout) -
-		le32_to_cpu(priv->_agn.statistics.tx.agg.ba_timeout);
-	if ((priv->_agn.agg_tids_count > 0) &&
-	    (expected_ack_cnt_delta > 0) &&
-	    (((actual_ack_cnt_delta * 100) / expected_ack_cnt_delta)
-		< ACK_CNT_RATIO) &&
-	    (ba_timeout_delta > BA_TIMEOUT_CNT)) {
-		IWL_DEBUG_RADIO(priv, "actual_ack_cnt delta = %d,"
-				" expected_ack_cnt = %d\n",
-				actual_ack_cnt_delta, expected_ack_cnt_delta);
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		/*
-		 * This is ifdef'ed on DEBUGFS because otherwise the
-		 * statistics aren't available. If DEBUGFS is set but
-		 * DEBUG is not, these will just compile out.
-		 */
-		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta = %d\n",
-				priv->_agn.delta_statistics.tx.rx_detected_cnt);
-		IWL_DEBUG_RADIO(priv,
-				"ack_or_ba_timeout_collision delta = %d\n",
-				priv->_agn.delta_statistics.tx.
-				ack_or_ba_timeout_collision);
-#endif
-		IWL_DEBUG_RADIO(priv, "agg ba_timeout delta = %d\n",
-				ba_timeout_delta);
-		if (!actual_ack_cnt_delta &&
-		    (ba_timeout_delta >= BA_TIMEOUT_MAX))
-			rc = false;
-	}
-	return rc;
-}
-
-
 /*****************************************************************************
  *
  * sysfs attributes
@@ -2632,13 +2430,6 @@
 
 	IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
 
-	if (priv->card_alive.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Alive failed.\n");
-		goto restart;
-	}
-
 	/* Initialize uCode has loaded Runtime uCode ... verify inst image.
 	 * This is a paranoid check, because we would not have gotten the
 	 * "runtime" alive if code weren't properly loaded.  */
@@ -2710,9 +2501,11 @@
 			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
 	}
 
-	if (priv->cfg->bt_params &&
-	    !priv->cfg->bt_params->advanced_bt_coexist) {
-		/* Configure Bluetooth device coexistence support */
+	if (!priv->cfg->bt_params || (priv->cfg->bt_params &&
+	    !priv->cfg->bt_params->advanced_bt_coexist)) {
+		/*
+		 * default is 2-wire BT coexexistence support
+		 */
 		priv->cfg->ops->hcmd->send_bt_config(priv);
 	}
 
@@ -2726,8 +2519,6 @@
 	/* At this point, the NIC is initialized and operational */
 	iwl_rf_kill_ct_config(priv);
 
-	iwl_leds_init(priv);
-
 	IWL_DEBUG_INFO(priv, "ALIVE processing complete.\n");
 	wake_up_interruptible(&priv->wait_command_queue);
 
@@ -2769,7 +2560,6 @@
 			 priv->cfg->bt_params->bt_init_traffic_load;
 	else
 		priv->bt_traffic_load = 0;
-	priv->bt_sco_active = false;
 	priv->bt_full_concurrent = false;
 	priv->bt_ci_compliance = 0;
 
@@ -3063,8 +2853,7 @@
 	}
 
 	if (priv->start_calib) {
-		if (priv->cfg->bt_params &&
-		    priv->cfg->bt_params->bt_statistics) {
+		if (iwl_bt_statistics(priv)) {
 			iwl_chain_noise_calibration(priv,
 					(void *)&priv->_agn.statistics_bt);
 			iwl_sensitivity_calibration(priv,
@@ -3089,7 +2878,7 @@
 
 	if (test_and_clear_bit(STATUS_FW_ERROR, &priv->status)) {
 		struct iwl_rxon_context *ctx;
-		bool bt_sco, bt_full_concurrent;
+		bool bt_full_concurrent;
 		u8 bt_ci_compliance;
 		u8 bt_load;
 		u8 bt_status;
@@ -3108,7 +2897,6 @@
 		 * re-configure the hw when we reconfigure the BT
 		 * command.
 		 */
-		bt_sco = priv->bt_sco_active;
 		bt_full_concurrent = priv->bt_full_concurrent;
 		bt_ci_compliance = priv->bt_ci_compliance;
 		bt_load = priv->bt_traffic_load;
@@ -3116,7 +2904,6 @@
 
 		__iwl_down(priv);
 
-		priv->bt_sco_active = bt_sco;
 		priv->bt_full_concurrent = bt_full_concurrent;
 		priv->bt_ci_compliance = bt_ci_compliance;
 		priv->bt_traffic_load = bt_load;
@@ -3150,6 +2937,94 @@
 	mutex_unlock(&priv->mutex);
 }
 
+static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
+				 struct ieee80211_channel *chan,
+				 enum nl80211_channel_type channel_type,
+				 unsigned int wait)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	/* Not supported if we don't have PAN */
+	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) {
+		ret = -EOPNOTSUPP;
+		goto free;
+	}
+
+	/* Not supported on pre-P2P firmware */
+	if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
+					BIT(NL80211_IFTYPE_P2P_CLIENT))) {
+		ret = -EOPNOTSUPP;
+		goto free;
+	}
+
+	mutex_lock(&priv->mutex);
+
+	if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) {
+		/*
+		 * If the PAN context is free, use the normal
+		 * way of doing remain-on-channel offload + TX.
+		 */
+		ret = 1;
+		goto out;
+	}
+
+	/* TODO: queue up if scanning? */
+	if (test_bit(STATUS_SCANNING, &priv->status) ||
+	    priv->_agn.offchan_tx_skb) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	/*
+	 * max_scan_ie_len doesn't include the blank SSID or the header,
+	 * so need to add that again here.
+	 */
+	if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) {
+		ret = -ENOBUFS;
+		goto out;
+	}
+
+	priv->_agn.offchan_tx_skb = skb;
+	priv->_agn.offchan_tx_timeout = wait;
+	priv->_agn.offchan_tx_chan = chan;
+
+	ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
+				IWL_SCAN_OFFCH_TX, chan->band);
+	if (ret)
+		priv->_agn.offchan_tx_skb = NULL;
+ out:
+	mutex_unlock(&priv->mutex);
+ free:
+	if (ret < 0)
+		kfree_skb(skb);
+
+	return ret;
+}
+
+static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+	int ret;
+
+	mutex_lock(&priv->mutex);
+
+	if (!priv->_agn.offchan_tx_skb) {
+		ret = -EINVAL;
+		goto unlock;
+	}
+
+	priv->_agn.offchan_tx_skb = NULL;
+
+	ret = iwl_scan_cancel_timeout(priv, 200);
+	if (ret)
+		ret = -EIO;
+unlock:
+	mutex_unlock(&priv->mutex);
+
+	return ret;
+}
+
 /*****************************************************************************
  *
  * mac80211 entry point functions
@@ -3178,6 +3053,8 @@
 		    IEEE80211_HW_SPECTRUM_MGMT |
 		    IEEE80211_HW_REPORTS_TX_ACK_STATUS;
 
+	hw->max_tx_aggregation_subframes = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
 	if (!priv->cfg->base_params->broken_powersave)
 		hw->flags |= IEEE80211_HW_SUPPORTS_PS |
 			     IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
@@ -3194,8 +3071,11 @@
 		hw->wiphy->interface_modes |= ctx->exclusive_interface_modes;
 	}
 
+	hw->wiphy->max_remain_on_channel_duration = 1000;
+
 	hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY |
-			    WIPHY_FLAG_DISABLE_BEACON_HINTS;
+			    WIPHY_FLAG_DISABLE_BEACON_HINTS |
+			    WIPHY_FLAG_IBSS_RSN;
 
 	/*
 	 * For now, disable PS by default because it affects
@@ -3219,6 +3099,8 @@
 		priv->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
 			&priv->bands[IEEE80211_BAND_5GHZ];
 
+	iwl_leds_init(priv);
+
 	ret = ieee80211_register_hw(priv->hw);
 	if (ret) {
 		IWL_ERR(priv, "Failed to register hw (error %d)\n", ret);
@@ -3263,7 +3145,7 @@
 		}
 	}
 
-	iwl_led_start(priv);
+	iwlagn_led_enable(priv);
 
 out:
 	priv->is_open = 1;
@@ -3294,7 +3176,7 @@
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
-int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct iwl_priv *priv = hw->priv;
 
@@ -3307,7 +3189,6 @@
 		dev_kfree_skb_any(skb);
 
 	IWL_DEBUG_MACDUMP(priv, "leave\n");
-	return NETDEV_TX_OK;
 }
 
 void iwlagn_mac_update_tkip_key(struct ieee80211_hw *hw,
@@ -3345,6 +3226,14 @@
 		return -EOPNOTSUPP;
 	}
 
+	/*
+	 * To support IBSS RSN, don't program group keys in IBSS, the
+	 * hardware will then not attempt to decrypt the frames.
+	 */
+	if (vif->type == NL80211_IFTYPE_ADHOC &&
+	    !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
+		return -EOPNOTSUPP;
+
 	sta_id = iwl_sta_id_or_broadcast(priv, vif_priv->ctx, sta);
 	if (sta_id == IWL_INVALID_STATION)
 		return -EINVAL;
@@ -3399,10 +3288,12 @@
 int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size)
 {
 	struct iwl_priv *priv = hw->priv;
 	int ret = -EINVAL;
+	struct iwl_station_priv *sta_priv = (void *) sta->drv_priv;
 
 	IWL_DEBUG_HT(priv, "A-MPDU action on addr %pM tid %d\n",
 		     sta->addr, tid);
@@ -3457,11 +3348,28 @@
 		}
 		break;
 	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		/*
+		 * If the limit is 0, then it wasn't initialised yet,
+		 * use the default. We can do that since we take the
+		 * minimum below, and we don't want to go above our
+		 * default due to hardware restrictions.
+		 */
+		if (sta_priv->max_agg_bufsize == 0)
+			sta_priv->max_agg_bufsize =
+				LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+
+		/*
+		 * Even though in theory the peer could have different
+		 * aggregation reorder buffer sizes for different sessions,
+		 * our ucode doesn't allow for that and has a global limit
+		 * for each station. Therefore, use the minimum of all the
+		 * aggregation sessions and our default value.
+		 */
+		sta_priv->max_agg_bufsize =
+			min(sta_priv->max_agg_bufsize, buf_size);
+
 		if (priv->cfg->ht_params &&
 		    priv->cfg->ht_params->use_rts_for_aggregation) {
-			struct iwl_station_priv *sta_priv =
-				(void *) sta->drv_priv;
-
 			/*
 			 * switch to RTS/CTS if it is the prefer protection
 			 * method for HT traffic
@@ -3469,9 +3377,13 @@
 
 			sta_priv->lq_sta.lq.general_params.flags |=
 				LINK_QUAL_FLAGS_SET_STA_TLC_RTS_MSK;
-			iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
-					&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		}
+
+		sta_priv->lq_sta.lq.agg_params.agg_frame_cnt_limit =
+			sta_priv->max_agg_bufsize;
+
+		iwl_send_lq_cmd(priv, iwl_rxon_ctx_from_vif(vif),
+				&sta_priv->lq_sta.lq, CMD_ASYNC, false);
 		ret = 0;
 		break;
 	}
@@ -3709,6 +3621,95 @@
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 }
 
+static void iwlagn_disable_roc(struct iwl_priv *priv)
+{
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
+	struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel);
+
+	lockdep_assert_held(&priv->mutex);
+
+	if (!ctx->is_active)
+		return;
+
+	ctx->staging.dev_type = RXON_DEV_TYPE_2STA;
+	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
+	iwl_set_rxon_channel(priv, chan, ctx);
+	iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
+
+	priv->_agn.hw_roc_channel = NULL;
+
+	iwlcore_commit_rxon(priv, ctx);
+
+	ctx->is_active = false;
+}
+
+static void iwlagn_bg_roc_done(struct work_struct *work)
+{
+	struct iwl_priv *priv = container_of(work, struct iwl_priv,
+					     _agn.hw_roc_work.work);
+
+	mutex_lock(&priv->mutex);
+	ieee80211_remain_on_channel_expired(priv->hw);
+	iwlagn_disable_roc(priv);
+	mutex_unlock(&priv->mutex);
+}
+
+static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
+				     struct ieee80211_channel *channel,
+				     enum nl80211_channel_type channel_type,
+				     int duration)
+{
+	struct iwl_priv *priv = hw->priv;
+	int err = 0;
+
+	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+		return -EOPNOTSUPP;
+
+	if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
+					BIT(NL80211_IFTYPE_P2P_CLIENT)))
+		return -EOPNOTSUPP;
+
+	mutex_lock(&priv->mutex);
+
+	if (priv->contexts[IWL_RXON_CTX_PAN].is_active ||
+	    test_bit(STATUS_SCAN_HW, &priv->status)) {
+		err = -EBUSY;
+		goto out;
+	}
+
+	priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
+	priv->_agn.hw_roc_channel = channel;
+	priv->_agn.hw_roc_chantype = channel_type;
+	priv->_agn.hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024);
+	iwlcore_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]);
+	queue_delayed_work(priv->workqueue, &priv->_agn.hw_roc_work,
+			   msecs_to_jiffies(duration + 20));
+
+	msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */
+	ieee80211_ready_on_channel(priv->hw);
+
+ out:
+	mutex_unlock(&priv->mutex);
+
+	return err;
+}
+
+static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
+{
+	struct iwl_priv *priv = hw->priv;
+
+	if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
+		return -EOPNOTSUPP;
+
+	cancel_delayed_work_sync(&priv->_agn.hw_roc_work);
+
+	mutex_lock(&priv->mutex);
+	iwlagn_disable_roc(priv);
+	mutex_unlock(&priv->mutex);
+
+	return 0;
+}
+
 /*****************************************************************************
  *
  * driver setup and teardown
@@ -3730,6 +3731,7 @@
 	INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
 	INIT_DELAYED_WORK(&priv->init_alive_start, iwl_bg_init_alive_start);
 	INIT_DELAYED_WORK(&priv->alive_start, iwl_bg_alive_start);
+	INIT_DELAYED_WORK(&priv->_agn.hw_roc_work, iwlagn_bg_roc_done);
 
 	iwl_setup_scan_deferred_work(priv);
 
@@ -3823,6 +3825,8 @@
 	priv->force_reset[IWL_FW_RESET].reset_duration =
 		IWL_DELAY_NEXT_FORCE_FW_RELOAD;
 
+	priv->rx_statistics_jiffies = jiffies;
+
 	/* Choose which receivers/antennas to use */
 	if (priv->cfg->ops->hcmd->set_rxon_chain)
 		priv->cfg->ops->hcmd->set_rxon_chain(priv,
@@ -3876,7 +3880,6 @@
 	kfree(priv->scan_cmd);
 }
 
-#ifdef CONFIG_IWL5000
 struct ieee80211_ops iwlagn_hw_ops = {
 	.tx = iwlagn_mac_tx,
 	.start = iwlagn_mac_start,
@@ -3898,14 +3901,17 @@
 	.channel_switch = iwlagn_mac_channel_switch,
 	.flush = iwlagn_mac_flush,
 	.tx_last_beacon = iwl_mac_tx_last_beacon,
+	.remain_on_channel = iwl_mac_remain_on_channel,
+	.cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
+	.offchannel_tx = iwl_mac_offchannel_tx,
+	.offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
 };
-#endif
 
 static void iwl_hw_detect(struct iwl_priv *priv)
 {
 	priv->hw_rev = _iwl_read32(priv, CSR_HW_REV);
 	priv->hw_wa_rev = _iwl_read32(priv, CSR_HW_REV_WA_REG);
-	pci_read_config_byte(priv->pci_dev, PCI_REVISION_ID, &priv->rev_id);
+	priv->rev_id = priv->pci_dev->revision;
 	IWL_DEBUG_INFO(priv, "HW Revision ID = 0x%X\n", priv->rev_id);
 }
 
@@ -3967,12 +3973,7 @@
 	if (cfg->mod_params->disable_hw_scan) {
 		dev_printk(KERN_DEBUG, &(pdev->dev),
 			"sw scan support is deprecated\n");
-#ifdef CONFIG_IWL5000
 		iwlagn_hw_ops.hw_scan = NULL;
-#endif
-#ifdef CONFIG_IWL4965
-		iwl4965_hw_ops.hw_scan = NULL;
-#endif
 	}
 
 	hw = iwl_alloc_all(cfg);
@@ -4025,6 +4026,10 @@
 	priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
 	priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
 		BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
+#ifdef CONFIG_IWL_P2P
+	priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
+		BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
+#endif
 	priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
 	priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
 	priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
@@ -4272,6 +4277,9 @@
 	 * we need to set STATUS_EXIT_PENDING bit.
 	 */
 	set_bit(STATUS_EXIT_PENDING, &priv->status);
+
+	iwl_leds_exit(priv);
+
 	if (priv->mac80211_registered) {
 		ieee80211_unregister_hw(priv->hw);
 		priv->mac80211_registered = 0;
@@ -4344,12 +4352,6 @@
 
 /* Hardware specific file defines the PCI IDs table for that hardware module */
 static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
-#ifdef CONFIG_IWL4965
-	{IWL_PCI_DEVICE(0x4229, PCI_ANY_ID, iwl4965_agn_cfg)},
-	{IWL_PCI_DEVICE(0x4230, PCI_ANY_ID, iwl4965_agn_cfg)},
-#endif /* CONFIG_IWL4965 */
-#ifdef CONFIG_IWL5000
-/* 5100 Series WiFi */
 	{IWL_PCI_DEVICE(0x4232, 0x1201, iwl5100_agn_cfg)}, /* Mini Card */
 	{IWL_PCI_DEVICE(0x4232, 0x1301, iwl5100_agn_cfg)}, /* Half Mini Card */
 	{IWL_PCI_DEVICE(0x4232, 0x1204, iwl5100_agn_cfg)}, /* Mini Card */
@@ -4492,7 +4494,48 @@
 	{IWL_PCI_DEVICE(0x0896, 0x5025, iwl130_bgn_cfg)},
 	{IWL_PCI_DEVICE(0x0896, 0x5027, iwl130_bg_cfg)},
 
-#endif /* CONFIG_IWL5000 */
+/* 2x00 Series */
+	{IWL_PCI_DEVICE(0x0890, 0x4022, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0891, 0x4222, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4422, iwl2000_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4026, iwl2000_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0891, 0x4226, iwl2000_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0890, 0x4426, iwl2000_2bg_cfg)},
+
+/* 2x30 Series */
+	{IWL_PCI_DEVICE(0x0887, 0x4062, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0888, 0x4262, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4462, iwl2030_2bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4066, iwl2030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0888, 0x4266, iwl2030_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x0887, 0x4466, iwl2030_2bg_cfg)},
+
+/* 6x35 Series */
+	{IWL_PCI_DEVICE(0x088E, 0x4060, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4260, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4460, iwl6035_2agn_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4064, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4264, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4464, iwl6035_2abg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4066, iwl6035_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x088F, 0x4266, iwl6035_2bg_cfg)},
+	{IWL_PCI_DEVICE(0x088E, 0x4466, iwl6035_2bg_cfg)},
+
+/* 200 Series */
+	{IWL_PCI_DEVICE(0x0894, 0x0022, iwl200_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0895, 0x0222, iwl200_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0422, iwl200_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0026, iwl200_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0895, 0x0226, iwl200_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0894, 0x0426, iwl200_bg_cfg)},
+
+/* 230 Series */
+	{IWL_PCI_DEVICE(0x0892, 0x0062, iwl230_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0893, 0x0262, iwl230_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0462, iwl230_bgn_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0066, iwl230_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0893, 0x0266, iwl230_bg_cfg)},
+	{IWL_PCI_DEVICE(0x0892, 0x0466, iwl230_bg_cfg)},
 
 	{0}
 };
@@ -4592,3 +4635,9 @@
 module_param_named(bt_ch_inhibition, iwlagn_bt_ch_announce, bool, S_IRUGO);
 MODULE_PARM_DESC(bt_ch_inhibition,
 		 "Disable BT channel inhibition (default: enable)");
+
+module_param_named(plcp_check, iwlagn_mod_params.plcp_check, bool, S_IRUGO);
+MODULE_PARM_DESC(plcp_check, "Check plcp health (default: 1 [enabled])");
+
+module_param_named(ack_check, iwlagn_mod_params.ack_check, bool, S_IRUGO);
+MODULE_PARM_DESC(ack_check, "Check ack health (default: 0 [disabled])");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-calib.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-calib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-calib.c	2011-05-19 00:06:34.000000000 -0400
@@ -631,8 +631,7 @@
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		rx_info = &(((struct iwl_bt_notif_statistics *)resp)->
 			      rx.general.common);
 		ofdm = &(((struct iwl_bt_notif_statistics *)resp)->rx.ofdm);
@@ -897,8 +896,7 @@
 	}
 
 	spin_lock_irqsave(&priv->lock, flags);
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		rx_info = &(((struct iwl_bt_notif_statistics *)stat_resp)->
 			      rx.general.common);
 	} else {
@@ -913,8 +911,7 @@
 
 	rxon_band24 = !!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK);
 	rxon_chnum = le16_to_cpu(ctx->staging.channel);
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		stat_band24 = !!(((struct iwl_bt_notif_statistics *)
 				 stat_resp)->flag &
 				 STATISTICS_REPLY_FLG_BAND_24G_MSK);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,8 +39,7 @@
 	int p = 0;
 	u32 flag;
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics)
+	if (iwl_bt_statistics(priv))
 		flag = le32_to_cpu(priv->_agn.statistics_bt.flag);
 	else
 		flag = le32_to_cpu(priv->_agn.statistics.flag);
@@ -89,8 +88,7 @@
 	 * the last statistics notification from uCode
 	 * might not reflect the current uCode activity
 	 */
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		ofdm = &priv->_agn.statistics_bt.rx.ofdm;
 		cck = &priv->_agn.statistics_bt.rx.cck;
 		general = &priv->_agn.statistics_bt.rx.general.common;
@@ -536,8 +534,7 @@
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		tx = &priv->_agn.statistics_bt.tx;
 		accum_tx = &priv->_agn.accum_statistics_bt.tx;
 		delta_tx = &priv->_agn.delta_statistics_bt.tx;
@@ -737,8 +734,7 @@
 	  * the last statistics notification from uCode
 	  * might not reflect the current uCode activity
 	  */
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
+	if (iwl_bt_statistics(priv)) {
 		general = &priv->_agn.statistics_bt.general.common;
 		dbg = &priv->_agn.statistics_bt.general.common.dbg;
 		div = &priv->_agn.statistics_bt.general.common.div;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn.h	2011-05-19 00:06:34.000000000 -0400
@@ -96,6 +96,17 @@
 extern struct iwl_cfg iwl100_bg_cfg;
 extern struct iwl_cfg iwl130_bgn_cfg;
 extern struct iwl_cfg iwl130_bg_cfg;
+extern struct iwl_cfg iwl2000_2bgn_cfg;
+extern struct iwl_cfg iwl2000_2bg_cfg;
+extern struct iwl_cfg iwl2030_2bgn_cfg;
+extern struct iwl_cfg iwl2030_2bg_cfg;
+extern struct iwl_cfg iwl6035_2agn_cfg;
+extern struct iwl_cfg iwl6035_2abg_cfg;
+extern struct iwl_cfg iwl6035_2bg_cfg;
+extern struct iwl_cfg iwl200_bg_cfg;
+extern struct iwl_cfg iwl200_bgn_cfg;
+extern struct iwl_cfg iwl230_bg_cfg;
+extern struct iwl_cfg iwl230_bgn_cfg;
 
 extern struct iwl_mod_params iwlagn_mod_params;
 extern struct iwl_hcmd_ops iwlagn_hcmd;
@@ -110,8 +121,6 @@
 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);
-bool iwl_good_ack_health(struct iwl_priv *priv,
-			 struct iwl_rx_packet *pkt);
 
 /* tx queue */
 void iwlagn_set_wr_ptrs(struct iwl_priv *priv,
@@ -181,11 +190,7 @@
 void iwlagn_rx_queue_free(struct iwl_priv *priv, struct iwl_rx_queue *rxq);
 int iwlagn_rxq_stop(struct iwl_priv *priv);
 int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band);
-void iwlagn_rx_reply_rx(struct iwl_priv *priv,
-		     struct iwl_rx_mem_buffer *rxb);
-void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
-			 struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_handle(struct iwl_priv *priv);
+void iwl_setup_rx_handlers(struct iwl_priv *priv);
 
 /* tx */
 void iwl_hw_txq_free_tfd(struct iwl_priv *priv, struct iwl_tx_queue *txq);
@@ -235,16 +240,6 @@
 
 u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
 
-/* rx */
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb);
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-			  struct iwl_rx_packet *pkt);
-void iwl_rx_statistics(struct iwl_priv *priv,
-		       struct iwl_rx_mem_buffer *rxb);
-void iwl_reply_statistics(struct iwl_priv *priv,
-			  struct iwl_rx_mem_buffer *rxb);
-
 /* scan */
 int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
 void iwlagn_post_scan(struct iwl_priv *priv);
@@ -330,8 +325,23 @@
 int iwlcore_eeprom_acquire_semaphore(struct iwl_priv *priv);
 void iwlcore_eeprom_release_semaphore(struct iwl_priv *priv);
 
+/* notification wait support */
+void __acquires(wait_entry)
+iwlagn_init_notification_wait(struct iwl_priv *priv,
+			      struct iwl_notification_wait *wait_entry,
+			      void (*fn)(struct iwl_priv *priv,
+					 struct iwl_rx_packet *pkt),
+			      u8 cmd);
+signed long __releases(wait_entry)
+iwlagn_wait_notification(struct iwl_priv *priv,
+			 struct iwl_notification_wait *wait_entry,
+			 unsigned long timeout);
+void __releases(wait_entry)
+iwlagn_remove_notification(struct iwl_priv *priv,
+			   struct iwl_notification_wait *wait_entry);
+
 /* mac80211 handlers (for 4965) */
-int iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void iwlagn_mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 int iwlagn_mac_start(struct ieee80211_hw *hw);
 void iwlagn_mac_stop(struct ieee80211_hw *hw);
 void iwlagn_configure_filter(struct ieee80211_hw *hw,
@@ -349,7 +359,8 @@
 int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
 			    struct ieee80211_vif *vif,
 			    enum ieee80211_ampdu_mlme_action action,
-			    struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			    struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			    u8 buf_size);
 int iwlagn_mac_sta_add(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
 		       struct ieee80211_sta *sta);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-hcmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -305,7 +305,11 @@
 	cmd.slots[0].type = 0; /* BSS */
 	cmd.slots[1].type = 1; /* PAN */
 
-	if (ctx_bss->vif && ctx_pan->vif) {
+	if (priv->_agn.hw_roc_channel) {
+		/* both contexts must be used for this to happen */
+		slot1 = priv->_agn.hw_roc_duration;
+		slot0 = IWL_MIN_SLOT_TIME;
+	} else if (ctx_bss->vif && ctx_pan->vif) {
 		int bcnint = ctx_pan->vif->bss_conf.beacon_int;
 		int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
 
@@ -330,12 +334,12 @@
 		if (test_bit(STATUS_SCAN_HW, &priv->status) ||
 		    (!ctx_bss->vif->bss_conf.idle &&
 		     !ctx_bss->vif->bss_conf.assoc)) {
-			slot0 = dtim * bcnint * 3 - 20;
-			slot1 = 20;
+			slot0 = dtim * bcnint * 3 - IWL_MIN_SLOT_TIME;
+			slot1 = IWL_MIN_SLOT_TIME;
 		} else if (!ctx_pan->vif->bss_conf.idle &&
 			   !ctx_pan->vif->bss_conf.assoc) {
-			slot1 = bcnint * 3 - 20;
-			slot0 = 20;
+			slot1 = bcnint * 3 - IWL_MIN_SLOT_TIME;
+			slot0 = IWL_MIN_SLOT_TIME;
 		}
 	} else if (ctx_pan->vif) {
 		slot0 = 0;
@@ -344,8 +348,8 @@
 		slot1 = max_t(int, DEFAULT_BEACON_INTERVAL, slot1);
 
 		if (test_bit(STATUS_SCAN_HW, &priv->status)) {
-			slot0 = slot1 * 3 - 20;
-			slot1 = 20;
+			slot0 = slot1 * 3 - IWL_MIN_SLOT_TIME;
+			slot1 = IWL_MIN_SLOT_TIME;
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ict.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ict.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ict.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ict.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,7 +69,7 @@
 	if (!priv->_agn.ict_tbl_vir)
 		return -ENOMEM;
 
-	/* align table to PAGE_SIZE boundry */
+	/* align table to PAGE_SIZE boundary */
 	priv->_agn.aligned_ict_tbl_dma = ALIGN(priv->_agn.ict_tbl_dma, PAGE_SIZE);
 
 	IWL_DEBUG_ISR(priv, "ict dma addr %Lx dma aligned %Lx diff %d\n",
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,23 +63,11 @@
 }
 
 /* Set led register off */
-static int iwl_led_on_reg(struct iwl_priv *priv)
+void iwlagn_led_enable(struct iwl_priv *priv)
 {
-	IWL_DEBUG_LED(priv, "led on\n");
 	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_ON);
-	return 0;
-}
-
-/* Set led register off */
-static int iwl_led_off_reg(struct iwl_priv *priv)
-{
-	IWL_DEBUG_LED(priv, "LED Reg off\n");
-	iwl_write32(priv, CSR_LED_REG, CSR_LED_REG_TRUN_OFF);
-	return 0;
 }
 
 const struct iwl_led_ops iwlagn_led_ops = {
 	.cmd = iwl_send_led_cmd,
-	.on = iwl_led_on_reg,
-	.off = iwl_led_off_reg,
 };
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-led.h	2011-05-19 00:06:34.000000000 -0400
@@ -28,5 +28,6 @@
 #define __iwl_agn_led_h__
 
 extern const struct iwl_led_ops iwlagn_led_ops;
+void iwlagn_led_enable(struct iwl_priv *priv);
 
 #endif /* __iwl_agn_led_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -473,6 +473,11 @@
 	priv->rx_handlers[CALIBRATION_COMPLETE_NOTIFICATION] =
 					iwlagn_rx_calib_complete;
 	priv->rx_handlers[REPLY_TX] = iwlagn_rx_reply_tx;
+
+	/* set up notification wait support */
+	spin_lock_init(&priv->_agn.notif_wait_lock);
+	INIT_LIST_HEAD(&priv->_agn.notif_waits);
+	init_waitqueue_head(&priv->_agn.notif_waitq);
 }
 
 void iwlagn_setup_deferred_work(struct iwl_priv *priv)
@@ -528,9 +533,10 @@
 
 void iwlagn_temperature(struct iwl_priv *priv)
 {
-	/* store temperature from statistics (in Celsius) */
-	priv->temperature =
-		le32_to_cpu(priv->_agn.statistics.general.common.temperature);
+	/* store temperature from correct statistics (in Celsius) */
+	priv->temperature = le32_to_cpu((iwl_bt_statistics(priv)) ?
+		priv->_agn.statistics_bt.general.common.temperature :
+		priv->_agn.statistics.general.common.temperature);
 	iwl_tt_handler(priv);
 }
 
@@ -604,6 +610,7 @@
 struct iwl_mod_params iwlagn_mod_params = {
 	.amsdu_size_8K = 1,
 	.restart_fw = 1,
+	.plcp_check = true,
 	/* the rest are 0 by default */
 };
 
@@ -988,240 +995,6 @@
 	return -1;
 }
 
-/* Calc max signal level (dBm) among 3 possible receivers */
-static inline int iwlagn_calc_rssi(struct iwl_priv *priv,
-				struct iwl_rx_phy_res *rx_resp)
-{
-	return priv->cfg->ops->utils->calc_rssi(priv, rx_resp);
-}
-
-static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
-{
-	u32 decrypt_out = 0;
-
-	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
-					RX_RES_STATUS_STATION_FOUND)
-		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
-				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
-
-	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
-
-	/* packet was not encrypted */
-	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-					RX_RES_STATUS_SEC_TYPE_NONE)
-		return decrypt_out;
-
-	/* packet was encrypted with unknown alg */
-	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
-					RX_RES_STATUS_SEC_TYPE_ERR)
-		return decrypt_out;
-
-	/* decryption was not done in HW */
-	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
-					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
-		return decrypt_out;
-
-	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
-
-	case RX_RES_STATUS_SEC_TYPE_CCMP:
-		/* alg is CCM: check MIC only */
-		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
-			/* Bad MIC */
-			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-		else
-			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-
-		break;
-
-	case RX_RES_STATUS_SEC_TYPE_TKIP:
-		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
-			/* Bad TTAK */
-			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
-			break;
-		}
-		/* fall through if TTAK OK */
-	default:
-		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
-			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
-		else
-			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
-		break;
-	}
-
-	IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
-					decrypt_in, decrypt_out);
-
-	return decrypt_out;
-}
-
-static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
-					struct ieee80211_hdr *hdr,
-					u16 len,
-					u32 ampdu_status,
-					struct iwl_rx_mem_buffer *rxb,
-					struct ieee80211_rx_status *stats)
-{
-	struct sk_buff *skb;
-	__le16 fc = hdr->frame_control;
-
-	/* We only process data packets if the interface is open */
-	if (unlikely(!priv->is_open)) {
-		IWL_DEBUG_DROP_LIMIT(priv,
-		    "Dropping packet while interface is not open.\n");
-		return;
-	}
-
-	/* In case of HW accelerated crypto and bad decryption, drop */
-	if (!priv->cfg->mod_params->sw_crypto &&
-	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
-		return;
-
-	skb = dev_alloc_skb(128);
-	if (!skb) {
-		IWL_ERR(priv, "dev_alloc_skb failed\n");
-		return;
-	}
-
-	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
-
-	iwl_update_stats(priv, false, fc, len);
-	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
-
-	ieee80211_rx(priv->hw, skb);
-	priv->alloc_rxb_page--;
-	rxb->page = NULL;
-}
-
-/* Called for REPLY_RX (legacy ABG frames), or
- * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
-void iwlagn_rx_reply_rx(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-{
-	struct ieee80211_hdr *header;
-	struct ieee80211_rx_status rx_status;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_rx_phy_res *phy_res;
-	__le32 rx_pkt_status;
-	struct iwl_rx_mpdu_res_start *amsdu;
-	u32 len;
-	u32 ampdu_status;
-	u32 rate_n_flags;
-
-	/**
-	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
-	 *	REPLY_RX: physical layer info is in this buffer
-	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
-	 *		command and cached in priv->last_phy_res
-	 *
-	 * Here we set up local variables depending on which command is
-	 * received.
-	 */
-	if (pkt->hdr.cmd == REPLY_RX) {
-		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
-		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
-				+ phy_res->cfg_phy_cnt);
-
-		len = le16_to_cpu(phy_res->byte_count);
-		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
-				phy_res->cfg_phy_cnt + len);
-		ampdu_status = le32_to_cpu(rx_pkt_status);
-	} else {
-		if (!priv->_agn.last_phy_res_valid) {
-			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
-			return;
-		}
-		phy_res = &priv->_agn.last_phy_res;
-		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
-		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
-		len = le16_to_cpu(amsdu->byte_count);
-		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
-		ampdu_status = iwlagn_translate_rx_status(priv,
-				le32_to_cpu(rx_pkt_status));
-	}
-
-	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
-		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
-				phy_res->cfg_phy_cnt);
-		return;
-	}
-
-	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
-	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
-		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
-				le32_to_cpu(rx_pkt_status));
-		return;
-	}
-
-	/* This will be used in several places later */
-	rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
-
-	/* rx_status carries information about the packet to mac80211 */
-	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
-	rx_status.freq =
-		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel));
-	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
-				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
-	rx_status.rate_idx =
-		iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
-	rx_status.flag = 0;
-
-	/* TSF isn't reliable. In order to allow smooth user experience,
-	 * this W/A doesn't propagate it to the mac80211 */
-	/*rx_status.flag |= RX_FLAG_TSFT;*/
-
-	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
-
-	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
-	rx_status.signal = iwlagn_calc_rssi(priv, phy_res);
-
-	iwl_dbg_log_rx_data_frame(priv, len, header);
-	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
-		rx_status.signal, (unsigned long long)rx_status.mactime);
-
-	/*
-	 * "antenna number"
-	 *
-	 * It seems that the antenna field in the phy flags value
-	 * is actually a bit field. This is undefined by radiotap,
-	 * it wants an actual antenna number but I always get "7"
-	 * for most legacy frames I receive indicating that the
-	 * same frame was received on all three RX chains.
-	 *
-	 * I think this field should be removed in favor of a
-	 * new 802.11n radiotap field "RX chains" that is defined
-	 * as a bitmask.
-	 */
-	rx_status.antenna =
-		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
-		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
-
-	/* set the preamble flag if appropriate */
-	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
-		rx_status.flag |= RX_FLAG_SHORTPRE;
-
-	/* Set up the HT phy flags */
-	if (rate_n_flags & RATE_MCS_HT_MSK)
-		rx_status.flag |= RX_FLAG_HT;
-	if (rate_n_flags & RATE_MCS_HT40_MSK)
-		rx_status.flag |= RX_FLAG_40MHZ;
-	if (rate_n_flags & RATE_MCS_SGI_MSK)
-		rx_status.flag |= RX_FLAG_SHORT_GI;
-
-	iwlagn_pass_packet_to_mac80211(priv, header, len, ampdu_status,
-				    rxb, &rx_status);
-}
-
-/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
- * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
-void iwlagn_rx_reply_rx_phy(struct iwl_priv *priv,
-			    struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	priv->_agn.last_phy_res_valid = true;
-	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
-	       sizeof(struct iwl_rx_phy_res));
-}
-
 static int iwl_get_single_channel_for_scan(struct iwl_priv *priv,
 					   struct ieee80211_vif *vif,
 					   enum ieee80211_band band,
@@ -1342,6 +1115,18 @@
 	return added;
 }
 
+static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
+{
+	struct sk_buff *skb = priv->_agn.offchan_tx_skb;
+
+	if (skb->len < maxlen)
+		maxlen = skb->len;
+
+	memcpy(data, skb->data, maxlen);
+
+	return maxlen;
+}
+
 int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
 {
 	struct iwl_host_cmd cmd = {
@@ -1384,20 +1169,25 @@
 	scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
 	scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
 
-	if (iwl_is_any_associated(priv)) {
+	if (priv->scan_type != IWL_SCAN_OFFCH_TX &&
+	    iwl_is_any_associated(priv)) {
 		u16 interval = 0;
 		u32 extra;
 		u32 suspend_time = 100;
 		u32 scan_suspend_time = 100;
-		unsigned long flags;
 
 		IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
-		spin_lock_irqsave(&priv->lock, flags);
-		if (priv->is_internal_short_scan)
+		switch (priv->scan_type) {
+		case IWL_SCAN_OFFCH_TX:
+			WARN_ON(1);
+			break;
+		case IWL_SCAN_RADIO_RESET:
 			interval = 0;
-		else
+			break;
+		case IWL_SCAN_NORMAL:
 			interval = vif->bss_conf.beacon_int;
-		spin_unlock_irqrestore(&priv->lock, flags);
+			break;
+		}
 
 		scan->suspend_time = 0;
 		scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -1410,29 +1200,41 @@
 		scan->suspend_time = cpu_to_le32(scan_suspend_time);
 		IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
 			       scan_suspend_time, interval);
+	} else if (priv->scan_type == IWL_SCAN_OFFCH_TX) {
+		scan->suspend_time = 0;
+		scan->max_out_time =
+			cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout);
 	}
 
-	if (priv->is_internal_short_scan) {
+	switch (priv->scan_type) {
+	case IWL_SCAN_RADIO_RESET:
 		IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
-	} else 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");
+		break;
+	case IWL_SCAN_NORMAL:
+		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");
+		break;
+	case IWL_SCAN_OFFCH_TX:
+		IWL_DEBUG_SCAN(priv, "Start offchannel TX scan.\n");
+		break;
+	}
 
 	scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
 	scan->tx_cmd.sta_id = ctx->bcast_sta_id;
@@ -1530,38 +1332,77 @@
 	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);
-	if (!priv->is_internal_short_scan) {
+	switch (priv->scan_type) {
+	case IWL_SCAN_NORMAL:
 		cmd_len = iwl_fill_probe_req(priv,
 					(struct ieee80211_mgmt *)scan->data,
 					vif->addr,
 					priv->scan_request->ie,
 					priv->scan_request->ie_len,
 					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-	} else {
+		break;
+	case IWL_SCAN_RADIO_RESET:
 		/* use bcast addr, will not be transmitted but must be valid */
 		cmd_len = iwl_fill_probe_req(priv,
 					(struct ieee80211_mgmt *)scan->data,
 					iwl_bcast_addr, NULL, 0,
 					IWL_MAX_SCAN_SIZE - sizeof(*scan));
-
+		break;
+	case IWL_SCAN_OFFCH_TX:
+		cmd_len = iwl_fill_offch_tx(priv, scan->data,
+					    IWL_MAX_SCAN_SIZE
+					     - sizeof(*scan)
+					     - sizeof(struct iwl_scan_channel));
+		scan->scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX;
+		break;
+	default:
+		BUG();
 	}
 	scan->tx_cmd.len = cpu_to_le16(cmd_len);
 
 	scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
 			       RXON_FILTER_BCON_AWARE_MSK);
 
-	if (priv->is_internal_short_scan) {
+	switch (priv->scan_type) {
+	case IWL_SCAN_RADIO_RESET:
 		scan->channel_count =
 			iwl_get_single_channel_for_scan(priv, vif, band,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
-	} else {
+				(void *)&scan->data[cmd_len]);
+		break;
+	case IWL_SCAN_NORMAL:
 		scan->channel_count =
 			iwl_get_channels_for_scan(priv, vif, band,
 				is_active, n_probes,
-				(void *)&scan->data[le16_to_cpu(
-				scan->tx_cmd.len)]);
+				(void *)&scan->data[cmd_len]);
+		break;
+	case IWL_SCAN_OFFCH_TX: {
+		struct iwl_scan_channel *scan_ch;
+
+		scan->channel_count = 1;
+
+		scan_ch = (void *)&scan->data[cmd_len];
+		scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
+		scan_ch->channel =
+			cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value);
+		scan_ch->active_dwell =
+			cpu_to_le16(priv->_agn.offchan_tx_timeout);
+		scan_ch->passive_dwell = 0;
+
+		/* Set txpower levels to defaults */
+		scan_ch->dsp_atten = 110;
+
+		/* NOTE: if we were doing 6Mb OFDM for scans we'd use
+		 * power level:
+		 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
+		 */
+		if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
+			scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
+		else
+			scan_ch->tx_gain = ((1 << 5) | (5 << 3));
+		}
+		break;
 	}
+
 	if (scan->channel_count == 0) {
 		IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
 		return -EIO;
@@ -1801,26 +1642,39 @@
 
 void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
 {
-	struct iwlagn_bt_cmd bt_cmd = {
+	struct iwl_basic_bt_cmd basic = {
 		.max_kill = IWLAGN_BT_MAX_KILL_DEFAULT,
 		.bt3_timer_t7_value = IWLAGN_BT3_T7_DEFAULT,
 		.bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT,
 		.bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT,
 	};
+	struct iwl6000_bt_cmd bt_cmd_6000;
+	struct iwl2000_bt_cmd bt_cmd_2000;
+	int ret;
 
 	BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
-			sizeof(bt_cmd.bt3_lookup_table));
+			sizeof(basic.bt3_lookup_table));
 
-	if (priv->cfg->bt_params)
-		bt_cmd.prio_boost = priv->cfg->bt_params->bt_prio_boost;
-	else
-		bt_cmd.prio_boost = 0;
-	bt_cmd.kill_ack_mask = priv->kill_ack_mask;
-	bt_cmd.kill_cts_mask = priv->kill_cts_mask;
+	if (priv->cfg->bt_params) {
+		if (priv->cfg->bt_params->bt_session_2) {
+			bt_cmd_2000.prio_boost = cpu_to_le32(
+				priv->cfg->bt_params->bt_prio_boost);
+			bt_cmd_2000.tx_prio_boost = 0;
+			bt_cmd_2000.rx_prio_boost = 0;
+		} else {
+			bt_cmd_6000.prio_boost =
+				priv->cfg->bt_params->bt_prio_boost;
+			bt_cmd_6000.tx_prio_boost = 0;
+			bt_cmd_6000.rx_prio_boost = 0;
+		}
+	} else {
+		IWL_ERR(priv, "failed to construct BT Coex Config\n");
+		return;
+	}
 
-	bt_cmd.valid = priv->bt_valid;
-	bt_cmd.tx_prio_boost = 0;
-	bt_cmd.rx_prio_boost = 0;
+	basic.kill_ack_mask = priv->kill_ack_mask;
+	basic.kill_cts_mask = priv->kill_cts_mask;
+	basic.valid = priv->bt_valid;
 
 	/*
 	 * Configure BT coex mode to "no coexistence" when the
@@ -1829,49 +1683,45 @@
 	 * IBSS mode (no proper uCode support for coex then).
 	 */
 	if (!bt_coex_active || priv->iw_mode == NL80211_IFTYPE_ADHOC) {
-		bt_cmd.flags = 0;
+		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
 	} else {
-		bt_cmd.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
+		basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
 					IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
 		if (priv->cfg->bt_params &&
 		    priv->cfg->bt_params->bt_sco_disable)
-			bt_cmd.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
+			basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
 
 		if (priv->bt_ch_announce)
-			bt_cmd.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
-		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", bt_cmd.flags);
+			basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
+		IWL_DEBUG_INFO(priv, "BT coex flag: 0X%x\n", basic.flags);
 	}
-	priv->bt_enable_flag = bt_cmd.flags;
+	priv->bt_enable_flag = basic.flags;
 	if (priv->bt_full_concurrent)
-		memcpy(bt_cmd.bt3_lookup_table, iwlagn_concurrent_lookup,
+		memcpy(basic.bt3_lookup_table, iwlagn_concurrent_lookup,
 			sizeof(iwlagn_concurrent_lookup));
 	else
-		memcpy(bt_cmd.bt3_lookup_table, iwlagn_def_3w_lookup,
+		memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
 			sizeof(iwlagn_def_3w_lookup));
 
 	IWL_DEBUG_INFO(priv, "BT coex %s in %s mode\n",
-		       bt_cmd.flags ? "active" : "disabled",
+		       basic.flags ? "active" : "disabled",
 		       priv->bt_full_concurrent ?
 		       "full concurrency" : "3-wire");
 
-	if (iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG, sizeof(bt_cmd), &bt_cmd))
+	if (priv->cfg->bt_params->bt_session_2) {
+		memcpy(&bt_cmd_2000.basic, &basic,
+			sizeof(basic));
+		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+			sizeof(bt_cmd_2000), &bt_cmd_2000);
+	} else {
+		memcpy(&bt_cmd_6000.basic, &basic,
+			sizeof(basic));
+		ret = iwl_send_cmd_pdu(priv, REPLY_BT_CONFIG,
+			sizeof(bt_cmd_6000), &bt_cmd_6000);
+	}
+	if (ret)
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 
-	/*
-	 * When we are doing a restart, need to also reconfigure BT
-	 * SCO to the device. If not doing a restart, bt_sco_active
-	 * will always be false, so there's no need to have an extra
-	 * variable to check for it.
-	 */
-	if (priv->bt_sco_active) {
-		struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
-
-		if (priv->bt_sco_active)
-			sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
-		if (iwl_send_cmd_pdu(priv, REPLY_BT_COEX_SCO,
-				     sizeof(sco_cmd), &sco_cmd))
-			IWL_ERR(priv, "failed to send BT SCO command\n");
-	}
 }
 
 static void iwlagn_bt_traffic_change_work(struct work_struct *work)
@@ -1881,6 +1731,11 @@
 	struct iwl_rxon_context *ctx;
 	int smps_request = -1;
 
+	if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
+		/* bt coex disabled */
+		return;
+	}
+
 	/*
 	 * Note: bt_traffic_load can be overridden by scan complete and
 	 * coex profile notifications. Ignore that since only bad consequence
@@ -1991,12 +1846,14 @@
 		(BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
 			BT_UART_MSG_FRAME6DISCOVERABLE_POS);
 
-	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Inquiry/Page SR Mode = "
-			"0x%X, Connectable = 0x%X",
+	IWL_DEBUG_NOTIF(priv, "Sniff Activity = 0x%X, Page = "
+			"0x%X, Inquiry = 0x%X, Connectable = 0x%X",
 		(BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
 			BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
-		(BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK & uart_msg->frame7) >>
-			BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS,
+		(BT_UART_MSG_FRAME7PAGE_MSK & uart_msg->frame7) >>
+			BT_UART_MSG_FRAME7PAGE_POS,
+		(BT_UART_MSG_FRAME7INQUIRY_MSK & uart_msg->frame7) >>
+			BT_UART_MSG_FRAME7INQUIRY_POS,
 		(BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >>
 			BT_UART_MSG_FRAME7CONNECTABLE_POS);
 }
@@ -2032,9 +1889,13 @@
 	unsigned long flags;
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
 	struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
-	struct iwlagn_bt_sco_cmd sco_cmd = { .flags = 0 };
 	struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
 
+	if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
+		/* bt coex disabled */
+		return;
+	}
+
 	IWL_DEBUG_NOTIF(priv, "BT Coex notification:\n");
 	IWL_DEBUG_NOTIF(priv, "    status: %d\n", coex->bt_status);
 	IWL_DEBUG_NOTIF(priv, "    traffic load: %d\n", coex->bt_traffic_load);
@@ -2063,15 +1924,6 @@
 			queue_work(priv->workqueue,
 				   &priv->bt_traffic_change_work);
 		}
-		if (priv->bt_sco_active !=
-		    (uart_msg->frame3 & BT_UART_MSG_FRAME3SCOESCO_MSK)) {
-			priv->bt_sco_active = uart_msg->frame3 &
-				BT_UART_MSG_FRAME3SCOESCO_MSK;
-			if (priv->bt_sco_active)
-				sco_cmd.flags |= IWLAGN_BT_SCO_ACTIVE;
-			iwl_send_cmd_pdu_async(priv, REPLY_BT_COEX_SCO,
-				       sizeof(sco_cmd), &sco_cmd, NULL);
-		}
 	}
 
 	iwlagn_set_kill_msk(priv, uart_msg);
@@ -2389,3 +2241,44 @@
 	}
 	return 0;
 }
+
+/* notification wait support */
+void iwlagn_init_notification_wait(struct iwl_priv *priv,
+				   struct iwl_notification_wait *wait_entry,
+				   void (*fn)(struct iwl_priv *priv,
+					      struct iwl_rx_packet *pkt),
+				   u8 cmd)
+{
+	wait_entry->fn = fn;
+	wait_entry->cmd = cmd;
+	wait_entry->triggered = false;
+
+	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	list_add(&wait_entry->list, &priv->_agn.notif_waits);
+	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
+
+signed long iwlagn_wait_notification(struct iwl_priv *priv,
+				     struct iwl_notification_wait *wait_entry,
+				     unsigned long timeout)
+{
+	int ret;
+
+	ret = wait_event_timeout(priv->_agn.notif_waitq,
+				 wait_entry->triggered,
+				 timeout);
+
+	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	list_del(&wait_entry->list);
+	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+
+	return ret;
+}
+
+void iwlagn_remove_notification(struct iwl_priv *priv,
+				struct iwl_notification_wait *wait_entry)
+{
+	spin_lock_bh(&priv->_agn.notif_wait_lock);
+	list_del(&wait_entry->list);
+	spin_unlock_bh(&priv->_agn.notif_wait_lock);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,31 +179,31 @@
 };
 
 static s32 expected_tpt_siso20MHz[4][IWL_RATE_COUNT] = {
-	{0, 0, 0, 0, 42, 0,  76, 102, 124, 158, 183, 193, 202}, /* Norm */
-	{0, 0, 0, 0, 46, 0,  82, 110, 132, 167, 192, 202, 210}, /* SGI */
-	{0, 0, 0, 0, 48, 0,  93, 135, 176, 251, 319, 351, 381}, /* AGG */
-	{0, 0, 0, 0, 53, 0, 102, 149, 193, 275, 348, 381, 413}, /* AGG+SGI */
+	{0, 0, 0, 0, 42, 0,  76, 102, 124, 159, 183, 193, 202}, /* Norm */
+	{0, 0, 0, 0, 46, 0,  82, 110, 132, 168, 192, 202, 210}, /* SGI */
+	{0, 0, 0, 0, 47, 0,  91, 133, 171, 242, 305, 334, 362}, /* AGG */
+	{0, 0, 0, 0, 52, 0, 101, 145, 187, 264, 330, 361, 390}, /* AGG+SGI */
 };
 
 static s32 expected_tpt_siso40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0,  77, 0, 127, 160, 184, 220, 242, 250, 257}, /* Norm */
 	{0, 0, 0, 0,  83, 0, 135, 169, 193, 229, 250, 257, 264}, /* SGI */
-	{0, 0, 0, 0,  96, 0, 182, 259, 328, 451, 553, 598, 640}, /* AGG */
-	{0, 0, 0, 0, 106, 0, 199, 282, 357, 487, 593, 640, 683}, /* AGG+SGI */
+	{0, 0, 0, 0,  94, 0, 177, 249, 313, 423, 512, 550, 586}, /* AGG */
+	{0, 0, 0, 0, 104, 0, 193, 270, 338, 454, 545, 584, 620}, /* AGG+SGI */
 };
 
 static s32 expected_tpt_mimo2_20MHz[4][IWL_RATE_COUNT] = {
-	{0, 0, 0, 0,  74, 0, 123, 155, 179, 213, 235, 243, 250}, /* Norm */
-	{0, 0, 0, 0,  81, 0, 131, 164, 187, 221, 242, 250, 256}, /* SGI */
-	{0, 0, 0, 0,  92, 0, 175, 250, 317, 436, 534, 578, 619}, /* AGG */
-	{0, 0, 0, 0, 102, 0, 192, 273, 344, 470, 573, 619, 660}, /* AGG+SGI*/
+	{0, 0, 0, 0,  74, 0, 123, 155, 179, 214, 236, 244, 251}, /* Norm */
+	{0, 0, 0, 0,  81, 0, 131, 164, 188, 223, 243, 251, 257}, /* SGI */
+	{0, 0, 0, 0,  89, 0, 167, 235, 296, 402, 488, 526, 560}, /* AGG */
+	{0, 0, 0, 0,  97, 0, 182, 255, 320, 431, 520, 558, 593}, /* AGG+SGI*/
 };
 
 static s32 expected_tpt_mimo2_40MHz[4][IWL_RATE_COUNT] = {
 	{0, 0, 0, 0, 123, 0, 182, 214, 235, 264, 279, 285, 289}, /* Norm */
 	{0, 0, 0, 0, 131, 0, 191, 222, 242, 270, 284, 289, 293}, /* SGI */
-	{0, 0, 0, 0, 180, 0, 327, 446, 545, 708, 828, 878, 922}, /* AGG */
-	{0, 0, 0, 0, 197, 0, 355, 481, 584, 752, 872, 922, 966}, /* AGG+SGI */
+	{0, 0, 0, 0, 171, 0, 305, 410, 496, 634, 731, 771, 805}, /* AGG */
+	{0, 0, 0, 0, 186, 0, 329, 439, 527, 667, 764, 803, 838}, /* AGG+SGI */
 };
 
 static s32 expected_tpt_mimo3_20MHz[4][IWL_RATE_COUNT] = {
@@ -2890,6 +2890,8 @@
 	u8 ant_toggle_cnt = 0;
 	u8 use_ht_possible = 1;
 	u8 valid_tx_ant = 0;
+	struct iwl_station_priv *sta_priv =
+		container_of(lq_sta, struct iwl_station_priv, lq_sta);
 	struct iwl_link_quality_cmd *lq_cmd = &lq_sta->lq;
 
 	/* Override starting rate (index 0) if needed for debug purposes */
@@ -3008,7 +3010,8 @@
 		repeat_rate--;
 	}
 
-	lq_cmd->agg_params.agg_frame_cnt_limit = LINK_QUAL_AGG_FRAME_LIMIT_DEF;
+	lq_cmd->agg_params.agg_frame_cnt_limit =
+		sta_priv->max_agg_bufsize ?: LINK_QUAL_AGG_FRAME_LIMIT_DEF;
 	lq_cmd->agg_params.agg_dis_start_th = LINK_QUAL_AGG_DISABLE_START_DEF;
 
 	lq_cmd->agg_params.agg_time_limit =
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rs.h	2011-05-19 00:06:34.000000000 -0400
@@ -213,6 +213,7 @@
 	 IWL_CCK_BASIC_RATES_MASK)
 
 #define IWL_RATES_MASK ((1 << IWL_RATE_COUNT) - 1)
+#define IWL_RATES_MASK_3945 ((1 << IWL_RATE_COUNT_3945) - 1)
 
 #define IWL_INVALID_VALUE    -1
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rx.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,356 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * 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 <linux/sched.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-agn-calib.h"
-#include "iwl-sta.h"
-#include "iwl-io.h"
-#include "iwl-helpers.h"
-#include "iwl-agn-hw.h"
-#include "iwl-agn.h"
-
-void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
-				struct iwl_rx_mem_buffer *rxb)
-
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_missed_beacon_notif *missed_beacon;
-
-	missed_beacon = &pkt->u.missed_beacon;
-	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
-	    priv->missed_beacon_threshold) {
-		IWL_DEBUG_CALIB(priv,
-		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
-		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
-		    le32_to_cpu(missed_beacon->total_missed_becons),
-		    le32_to_cpu(missed_beacon->num_recvd_beacons),
-		    le32_to_cpu(missed_beacon->num_expected_beacons));
-		if (!test_bit(STATUS_SCANNING, &priv->status))
-			iwl_init_sensitivity(priv);
-	}
-}
-
-/* Calculate noise level, based on measurements during network silence just
- *   before arriving beacon.  This measurement can be done only if we know
- *   exactly when to expect beacons, therefore only when we're associated. */
-static void iwl_rx_calc_noise(struct iwl_priv *priv)
-{
-	struct statistics_rx_non_phy *rx_info;
-	int num_active_rx = 0;
-	int total_silence = 0;
-	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
-	int last_rx_noise;
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics)
-		rx_info = &(priv->_agn.statistics_bt.rx.general.common);
-	else
-		rx_info = &(priv->_agn.statistics.rx.general);
-	bcn_silence_a =
-		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
-	bcn_silence_b =
-		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
-	bcn_silence_c =
-		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
-
-	if (bcn_silence_a) {
-		total_silence += bcn_silence_a;
-		num_active_rx++;
-	}
-	if (bcn_silence_b) {
-		total_silence += bcn_silence_b;
-		num_active_rx++;
-	}
-	if (bcn_silence_c) {
-		total_silence += bcn_silence_c;
-		num_active_rx++;
-	}
-
-	/* Average among active antennas */
-	if (num_active_rx)
-		last_rx_noise = (total_silence / num_active_rx) - 107;
-	else
-		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
-
-	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
-			bcn_silence_a, bcn_silence_b, bcn_silence_c,
-			last_rx_noise);
-}
-
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-/*
- *  based on the assumption of all statistics counter are in DWORD
- *  FIXME: This function is for debugging, do not deal with
- *  the case of counters roll-over.
- */
-static void iwl_accumulative_statistics(struct iwl_priv *priv,
-					__le32 *stats)
-{
-	int i, size;
-	__le32 *prev_stats;
-	u32 *accum_stats;
-	u32 *delta, *max_delta;
-	struct statistics_general_common *general, *accum_general;
-	struct statistics_tx *tx, *accum_tx;
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
-		prev_stats = (__le32 *)&priv->_agn.statistics_bt;
-		accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
-		size = sizeof(struct iwl_bt_notif_statistics);
-		general = &priv->_agn.statistics_bt.general.common;
-		accum_general = &priv->_agn.accum_statistics_bt.general.common;
-		tx = &priv->_agn.statistics_bt.tx;
-		accum_tx = &priv->_agn.accum_statistics_bt.tx;
-		delta = (u32 *)&priv->_agn.delta_statistics_bt;
-		max_delta = (u32 *)&priv->_agn.max_delta_bt;
-	} else {
-		prev_stats = (__le32 *)&priv->_agn.statistics;
-		accum_stats = (u32 *)&priv->_agn.accum_statistics;
-		size = sizeof(struct iwl_notif_statistics);
-		general = &priv->_agn.statistics.general.common;
-		accum_general = &priv->_agn.accum_statistics.general.common;
-		tx = &priv->_agn.statistics.tx;
-		accum_tx = &priv->_agn.accum_statistics.tx;
-		delta = (u32 *)&priv->_agn.delta_statistics;
-		max_delta = (u32 *)&priv->_agn.max_delta;
-	}
-	for (i = sizeof(__le32); i < size;
-	     i += sizeof(__le32), stats++, prev_stats++, delta++,
-	     max_delta++, accum_stats++) {
-		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
-			*delta = (le32_to_cpu(*stats) -
-				le32_to_cpu(*prev_stats));
-			*accum_stats += *delta;
-			if (*delta > *max_delta)
-				*max_delta = *delta;
-		}
-	}
-
-	/* reset accumulative statistics for "no-counter" type statistics */
-	accum_general->temperature = general->temperature;
-	accum_general->temperature_m = general->temperature_m;
-	accum_general->ttl_timestamp = general->ttl_timestamp;
-	accum_tx->tx_power.ant_a = tx->tx_power.ant_a;
-	accum_tx->tx_power.ant_b = tx->tx_power.ant_b;
-	accum_tx->tx_power.ant_c = tx->tx_power.ant_c;
-}
-#endif
-
-#define REG_RECALIB_PERIOD (60)
-
-/**
- * iwl_good_plcp_health - checks for plcp error.
- *
- * When the plcp error is exceeding the thresholds, reset the radio
- * to improve the throughput.
- */
-bool iwl_good_plcp_health(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
-{
-	bool rc = true;
-	int combined_plcp_delta;
-	unsigned int plcp_msec;
-	unsigned long plcp_received_jiffies;
-
-	if (priv->cfg->base_params->plcp_delta_threshold ==
-	    IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
-		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
-		return rc;
-	}
-
-	/*
-	 * check for plcp_err and trigger radio reset if it exceeds
-	 * the plcp error threshold plcp_delta.
-	 */
-	plcp_received_jiffies = jiffies;
-	plcp_msec = jiffies_to_msecs((long) plcp_received_jiffies -
-					(long) priv->plcp_jiffies);
-	priv->plcp_jiffies = plcp_received_jiffies;
-	/*
-	 * check to make sure plcp_msec is not 0 to prevent division
-	 * by zero.
-	 */
-	if (plcp_msec) {
-		struct statistics_rx_phy *ofdm;
-		struct statistics_rx_ht_phy *ofdm_ht;
-
-		if (priv->cfg->bt_params &&
-		    priv->cfg->bt_params->bt_statistics) {
-			ofdm = &pkt->u.stats_bt.rx.ofdm;
-			ofdm_ht = &pkt->u.stats_bt.rx.ofdm_ht;
-			combined_plcp_delta =
-			   (le32_to_cpu(ofdm->plcp_err) -
-			   le32_to_cpu(priv->_agn.statistics_bt.
-				       rx.ofdm.plcp_err)) +
-			   (le32_to_cpu(ofdm_ht->plcp_err) -
-			   le32_to_cpu(priv->_agn.statistics_bt.
-				       rx.ofdm_ht.plcp_err));
-		} else {
-			ofdm = &pkt->u.stats.rx.ofdm;
-			ofdm_ht = &pkt->u.stats.rx.ofdm_ht;
-			combined_plcp_delta =
-			    (le32_to_cpu(ofdm->plcp_err) -
-			    le32_to_cpu(priv->_agn.statistics.
-					rx.ofdm.plcp_err)) +
-			    (le32_to_cpu(ofdm_ht->plcp_err) -
-			    le32_to_cpu(priv->_agn.statistics.
-					rx.ofdm_ht.plcp_err));
-		}
-
-		if ((combined_plcp_delta > 0) &&
-		    ((combined_plcp_delta * 100) / plcp_msec) >
-			priv->cfg->base_params->plcp_delta_threshold) {
-			/*
-			 * if plcp_err exceed the threshold,
-			 * the following data is printed in csv format:
-			 *    Text: plcp_err exceeded %d,
-			 *    Received ofdm.plcp_err,
-			 *    Current ofdm.plcp_err,
-			 *    Received ofdm_ht.plcp_err,
-			 *    Current ofdm_ht.plcp_err,
-			 *    combined_plcp_delta,
-			 *    plcp_msec
-			 */
-			IWL_DEBUG_RADIO(priv, "plcp_err exceeded %u, "
-				"%u, %u, %u, %u, %d, %u mSecs\n",
-				priv->cfg->base_params->plcp_delta_threshold,
-				le32_to_cpu(ofdm->plcp_err),
-				le32_to_cpu(ofdm->plcp_err),
-				le32_to_cpu(ofdm_ht->plcp_err),
-				le32_to_cpu(ofdm_ht->plcp_err),
-				combined_plcp_delta, plcp_msec);
-
-			rc = false;
-		}
-	}
-	return rc;
-}
-
-void iwl_rx_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	int change;
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics) {
-		IWL_DEBUG_RX(priv,
-			     "Statistics notification received (%d vs %d).\n",
-			     (int)sizeof(struct iwl_bt_notif_statistics),
-			     le32_to_cpu(pkt->len_n_flags) &
-			     FH_RSCSR_FRAME_SIZE_MSK);
-
-		change = ((priv->_agn.statistics_bt.general.common.temperature !=
-			   pkt->u.stats_bt.general.common.temperature) ||
-			   ((priv->_agn.statistics_bt.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-			   (pkt->u.stats_bt.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt);
-#endif
-
-	} else {
-		IWL_DEBUG_RX(priv,
-			     "Statistics notification received (%d vs %d).\n",
-			     (int)sizeof(struct iwl_notif_statistics),
-			     le32_to_cpu(pkt->len_n_flags) &
-			     FH_RSCSR_FRAME_SIZE_MSK);
-
-		change = ((priv->_agn.statistics.general.common.temperature !=
-			   pkt->u.stats.general.common.temperature) ||
-			   ((priv->_agn.statistics.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
-			   (pkt->u.stats.flag &
-			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
-#endif
-
-	}
-
-	iwl_recover_from_statistics(priv, pkt);
-
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->bt_statistics)
-		memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
-			sizeof(priv->_agn.statistics_bt));
-	else
-		memcpy(&priv->_agn.statistics, &pkt->u.stats,
-			sizeof(priv->_agn.statistics));
-
-	set_bit(STATUS_STATISTICS, &priv->status);
-
-	/* Reschedule the statistics timer to occur in
-	 * REG_RECALIB_PERIOD seconds to ensure we get a
-	 * thermal update even if the uCode doesn't give
-	 * us one */
-	mod_timer(&priv->statistics_periodic, jiffies +
-		  msecs_to_jiffies(REG_RECALIB_PERIOD * 1000));
-
-	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
-	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
-		iwl_rx_calc_noise(priv);
-		queue_work(priv->workqueue, &priv->run_time_calib_work);
-	}
-	if (priv->cfg->ops->lib->temp_ops.temperature && change)
-		priv->cfg->ops->lib->temp_ops.temperature(priv);
-}
-
-void iwl_reply_statistics(struct iwl_priv *priv,
-			      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
-#ifdef CONFIG_IWLWIFI_DEBUGFS
-		memset(&priv->_agn.accum_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->_agn.delta_statistics, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->_agn.max_delta, 0,
-			sizeof(struct iwl_notif_statistics));
-		memset(&priv->_agn.accum_statistics_bt, 0,
-			sizeof(struct iwl_bt_notif_statistics));
-		memset(&priv->_agn.delta_statistics_bt, 0,
-			sizeof(struct iwl_bt_notif_statistics));
-		memset(&priv->_agn.max_delta_bt, 0,
-			sizeof(struct iwl_bt_notif_statistics));
-#endif
-		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
-	}
-	iwl_rx_statistics(priv, rxb);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,10 +52,14 @@
 			      struct iwl_rxon_context *ctx,
 			      struct iwl_rxon_cmd *send)
 {
+	struct iwl_notification_wait disable_wait;
 	__le32 old_filter = send->filter_flags;
 	u8 old_dev_type = send->dev_type;
 	int ret;
 
+	iwlagn_init_notification_wait(priv, &disable_wait, NULL,
+				      REPLY_WIPAN_DEACTIVATION_COMPLETE);
+
 	send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
 	send->dev_type = RXON_DEV_TYPE_P2P;
 	ret = iwl_send_cmd_pdu(priv, ctx->rxon_cmd, sizeof(*send), send);
@@ -63,11 +67,18 @@
 	send->filter_flags = old_filter;
 	send->dev_type = old_dev_type;
 
-	if (ret)
+	if (ret) {
 		IWL_ERR(priv, "Error disabling PAN (%d)\n", ret);
+		iwlagn_remove_notification(priv, &disable_wait);
+	} else {
+		signed long wait_res;
 
-	/* FIXME: WAIT FOR PAN DISABLE */
-	msleep(300);
+		wait_res = iwlagn_wait_notification(priv, &disable_wait, HZ);
+		if (wait_res == 0) {
+			IWL_ERR(priv, "Timed out waiting for PAN disable\n");
+			ret = -EIO;
+		}
+	}
 
 	return ret;
 }
@@ -145,6 +156,23 @@
 	/* always get timestamp with Rx frame */
 	ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
 
+	if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->_agn.hw_roc_channel) {
+		struct ieee80211_channel *chan = priv->_agn.hw_roc_channel;
+
+		iwl_set_rxon_channel(priv, chan, ctx);
+		iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
+		ctx->staging.filter_flags |=
+			RXON_FILTER_ASSOC_MSK |
+			RXON_FILTER_PROMISC_MSK |
+			RXON_FILTER_CTL2HOST_MSK;
+		ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
+		new_assoc = true;
+
+		if (memcmp(&ctx->staging, &ctx->active,
+			   sizeof(ctx->staging)) == 0)
+			return 0;
+	}
+
 	if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
 	    !(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
 		ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
@@ -288,10 +316,9 @@
 	 * 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.
 	 *
-	 * FIXME: which RXON requires a tune? Can we optimise this out in
-	 *        some cases?
+	 * It's expected we set power here if channel is changing.
 	 */
-	ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true);
+	ret = iwl_set_tx_power(priv, priv->tx_power_next, true);
 	if (ret) {
 		IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
 		return ret;
@@ -308,7 +335,6 @@
 	struct ieee80211_channel *channel = conf->channel;
 	const struct iwl_channel_info *ch_info;
 	int ret = 0;
-	bool ht_changed[NUM_IWL_RXON_CTX] = {};
 
 	IWL_DEBUG_MAC80211(priv, "changed %#x", changed);
 
@@ -356,10 +382,8 @@
 
 		for_each_context(priv, ctx) {
 			/* Configure HT40 channels */
-			if (ctx->ht.enabled != conf_is_ht(conf)) {
+			if (ctx->ht.enabled != conf_is_ht(conf))
 				ctx->ht.enabled = conf_is_ht(conf);
-				ht_changed[ctx->ctxid] = true;
-			}
 
 			if (ctx->ht.enabled) {
 				if (conf_is_ht40_minus(conf)) {
@@ -428,8 +452,6 @@
 		if (!memcmp(&ctx->staging, &ctx->active, sizeof(ctx->staging)))
 			continue;
 		iwlagn_commit_rxon(priv, ctx);
-		if (ht_changed[ctx->ctxid])
-			iwlagn_update_qos(priv, ctx);
 	}
  out:
 	mutex_unlock(&priv->mutex);
@@ -444,6 +466,7 @@
 	struct iwl_rxon_context *tmp;
 	struct ieee80211_sta *sta;
 	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
+	struct ieee80211_sta_ht_cap *ht_cap;
 	bool need_multiple;
 
 	lockdep_assert_held(&priv->mutex);
@@ -452,23 +475,7 @@
 	case NL80211_IFTYPE_STATION:
 		rcu_read_lock();
 		sta = ieee80211_find_sta(vif, bss_conf->bssid);
-		if (sta) {
-			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-			int maxstreams;
-
-			maxstreams = (ht_cap->mcs.tx_params &
-				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-			maxstreams += 1;
-
-			need_multiple = true;
-
-			if ((ht_cap->mcs.rx_mask[1] == 0) &&
-			    (ht_cap->mcs.rx_mask[2] == 0))
-				need_multiple = false;
-			if (maxstreams <= 1)
-				need_multiple = false;
-		} else {
+		if (!sta) {
 			/*
 			 * If at all, this can only happen through a race
 			 * when the AP disconnects us while we're still
@@ -476,7 +483,46 @@
 			 * will soon tell us about that.
 			 */
 			need_multiple = false;
+			rcu_read_unlock();
+			break;
 		}
+
+		ht_cap = &sta->ht_cap;
+
+		need_multiple = true;
+
+		/*
+		 * If the peer advertises no support for receiving 2 and 3
+		 * stream MCS rates, it can't be transmitting them either.
+		 */
+		if (ht_cap->mcs.rx_mask[1] == 0 &&
+		    ht_cap->mcs.rx_mask[2] == 0) {
+			need_multiple = false;
+		} else if (!(ht_cap->mcs.tx_params &
+						IEEE80211_HT_MCS_TX_DEFINED)) {
+			/* If it can't TX MCS at all ... */
+			need_multiple = false;
+		} else if (ht_cap->mcs.tx_params &
+						IEEE80211_HT_MCS_TX_RX_DIFF) {
+			int maxstreams;
+
+			/*
+			 * But if it can receive them, it might still not
+			 * be able to transmit them, which is what we need
+			 * to check here -- so check the number of streams
+			 * it advertises for TX (if different from RX).
+			 */
+
+			maxstreams = (ht_cap->mcs.tx_params &
+				 IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK);
+			maxstreams >>=
+				IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
+			maxstreams += 1;
+
+			if (maxstreams <= 1)
+				need_multiple = false;
+		}
+
 		rcu_read_unlock();
 		break;
 	case NL80211_IFTYPE_ADHOC:
@@ -546,12 +592,10 @@
 
 	if (changes & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
-			iwl_led_associate(priv);
 			priv->timestamp = bss_conf->timestamp;
 			ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK;
 		} else {
 			ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-			iwl_led_disassociate(priv);
 		}
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -539,7 +539,14 @@
 	unsigned long flags;
 	bool is_agg = false;
 
-	if (info->control.vif)
+	/*
+	 * If the frame needs to go out off-channel, then
+	 * we'll have put the PAN context to that channel,
+	 * so make the frame go out there.
+	 */
+	if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
+		ctx = &priv->contexts[IWL_RXON_CTX_PAN];
+	else if (info->control.vif)
 		ctx = iwl_rxon_ctx_from_vif(info->control.vif);
 
 	spin_lock_irqsave(&priv->lock, flags);
@@ -561,12 +568,17 @@
 
 	hdr_len = ieee80211_hdrlen(fc);
 
-	/* Find index into station table for destination station */
-	sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
-	if (sta_id == IWL_INVALID_STATION) {
-		IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
-			       hdr->addr1);
-		goto drop_unlock;
+	/* For management frames use broadcast id to do not break aggregation */
+	if (!ieee80211_is_data(fc))
+		sta_id = ctx->bcast_sta_id;
+	else {
+		/* Find index into station table for destination station */
+		sta_id = iwl_sta_id_or_broadcast(priv, ctx, info->control.sta);
+		if (sta_id == IWL_INVALID_STATION) {
+			IWL_DEBUG_DROP(priv, "Dropping - INVALID STATION: %pM\n",
+				       hdr->addr1);
+			goto drop_unlock;
+		}
 	}
 
 	IWL_DEBUG_TX(priv, "station Id %d\n", sta_id);
@@ -940,7 +952,7 @@
  */
 void iwlagn_txq_ctx_stop(struct iwl_priv *priv)
 {
-	int ch;
+	int ch, txq_id;
 	unsigned long flags;
 
 	/* Turn off all Tx DMA fifos */
@@ -959,6 +971,16 @@
 			    iwl_read_direct32(priv, FH_TSSR_TX_STATUS_REG));
 	}
 	spin_unlock_irqrestore(&priv->lock, flags);
+
+	if (!priv->txq)
+		return;
+
+	/* Unmap DMA from host system and free skb's */
+	for (txq_id = 0; txq_id < priv->hw_params.max_txq_num; txq_id++)
+		if (txq_id == priv->cmd_queue)
+			iwl_cmd_queue_unmap(priv);
+		else
+			iwl_tx_queue_unmap(priv, txq_id);
 }
 
 /*
@@ -1207,12 +1229,16 @@
 	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
 
 		tx_info = &txq->txb[txq->q.read_ptr];
-		iwlagn_tx_status(priv, tx_info,
-				 txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
+
+		if (WARN_ON_ONCE(tx_info->skb == NULL))
+			continue;
 
 		hdr = (struct ieee80211_hdr *)tx_info->skb->data;
-		if (hdr && ieee80211_is_data_qos(hdr->frame_control))
+		if (ieee80211_is_data_qos(hdr->frame_control))
 			nfreed++;
+
+		iwlagn_tx_status(priv, tx_info,
+				 txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
 		tx_info->skb = NULL;
 
 		if (priv->cfg->ops->lib->txq_inval_byte_cnt_tbl)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-agn-ucode.c	2011-05-19 00:06:34.000000000 -0400
@@ -308,14 +308,6 @@
 {
 	int ret = 0;
 
-	/* Check alive response for "valid" sign from uCode */
-	if (priv->card_alive_init.is_valid != UCODE_VALID_OK) {
-		/* We had an error bringing up the hardware, so take it
-		 * all the way back down so we can try again */
-		IWL_DEBUG_INFO(priv, "Initialize Alive failed.\n");
-		goto restart;
-	}
-
 	/* initialize uCode was loaded... verify inst image.
 	 * This is a paranoid check, because we would not have gotten the
 	 * "initialize" alive if code weren't properly loaded.  */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-commands.h	2011-05-19 00:06:34.000000000 -0400
@@ -178,7 +178,6 @@
 	REPLY_BT_COEX_PRIO_TABLE = 0xcc,
 	REPLY_BT_COEX_PROT_ENV = 0xcd,
 	REPLY_BT_COEX_PROFILE_NOTIF = 0xce,
-	REPLY_BT_COEX_SCO = 0xcf,
 
 	/* PAN commands */
 	REPLY_WIPAN_PARAMS = 0xb2,
@@ -189,6 +188,7 @@
 	REPLY_WIPAN_WEPKEY = 0xb8,	/* use REPLY_WEPKEY structure */
 	REPLY_WIPAN_P2P_CHANNEL_SWITCH = 0xb9,
 	REPLY_WIPAN_NOA_NOTIFICATION = 0xbc,
+	REPLY_WIPAN_DEACTIVATION_COMPLETE = 0xbd,
 
 	REPLY_MAX = 0xff
 };
@@ -2477,7 +2477,7 @@
 					IWLAGN_BT_VALID_BT4_TIMES | \
 					IWLAGN_BT_VALID_3W_LUT)
 
-struct iwlagn_bt_cmd {
+struct iwl_basic_bt_cmd {
 	u8 flags;
 	u8 ledtime; /* unused */
 	u8 max_kill;
@@ -2490,6 +2490,10 @@
 	__le32 bt3_lookup_table[12];
 	__le16 bt4_decision_time; /* unused */
 	__le16 valid;
+};
+
+struct iwl6000_bt_cmd {
+	struct iwl_basic_bt_cmd basic;
 	u8 prio_boost;
 	/*
 	 * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask
@@ -2499,6 +2503,18 @@
 	__le16 rx_prio_boost;	/* SW boost of WiFi rx priority */
 };
 
+struct iwl2000_bt_cmd {
+	struct iwl_basic_bt_cmd basic;
+	__le32 prio_boost;
+	/*
+	 * set IWLAGN_BT_VALID_BOOST to "1" in "valid" bitmask
+	 * if configure the following patterns
+	 */
+	u8 reserved;
+	u8 tx_prio_boost;	/* SW boost of WiFi tx priority */
+	__le16 rx_prio_boost;	/* SW boost of WiFi rx priority */
+};
+
 #define IWLAGN_BT_SCO_ACTIVE	cpu_to_le32(BIT(0))
 
 struct iwlagn_bt_sco_cmd {
@@ -2948,9 +2964,15 @@
 	u8 data[0];
 } __packed;
 
+enum iwl_scan_flags {
+	/* BIT(0) currently unused */
+	IWL_SCAN_FLAGS_ACTION_FRAME_TX	= BIT(1),
+	/* bits 2-7 reserved */
+};
+
 struct iwl_scan_cmd {
 	__le16 len;
-	u8 reserved0;
+	u8 scan_flags;		/* scan flags: see enum iwl_scan_flags */
 	u8 channel_count;	/* # channels in channel list */
 	__le16 quiet_time;	/* dwell only this # millisecs on quiet channel
 				 * (only for active scan) */
@@ -3082,6 +3104,13 @@
 	__le32 ibss_mgr_status;
 } __packed;
 
+struct iwlagn_beacon_notif {
+	struct iwlagn_tx_resp beacon_notify_hdr;
+	__le32 low_tsf;
+	__le32 high_tsf;
+	__le32 ibss_mgr_status;
+} __packed;
+
 /*
  * REPLY_TX_BEACON = 0x91 (command, has simple generic response)
  */
@@ -4143,6 +4172,10 @@
  */
 };
 
+#define BT_SESSION_ACTIVITY_1_UART_MSG		0x1
+#define BT_SESSION_ACTIVITY_2_UART_MSG		0x2
+
+/* BT UART message - Share Part (BT -> WiFi) */
 #define BT_UART_MSG_FRAME1MSGTYPE_POS		(0)
 #define BT_UART_MSG_FRAME1MSGTYPE_MSK		\
 		(0x7 << BT_UART_MSG_FRAME1MSGTYPE_POS)
@@ -4227,9 +4260,12 @@
 #define BT_UART_MSG_FRAME7SNIFFACTIVITY_POS	(0)
 #define BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK	\
 		(0x7 << BT_UART_MSG_FRAME7SNIFFACTIVITY_POS)
-#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS	(3)
-#define BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_MSK	\
-		(0x3 << BT_UART_MSG_FRAME7INQUIRYPAGESRMODE_POS)
+#define BT_UART_MSG_FRAME7PAGE_POS		(3)
+#define BT_UART_MSG_FRAME7PAGE_MSK		\
+		(0x1 << BT_UART_MSG_FRAME7PAGE_POS)
+#define BT_UART_MSG_FRAME7INQUIRY_POS		(4)
+#define BT_UART_MSG_FRAME7INQUIRY_MSK		\
+		(0x1 << BT_UART_MSG_FRAME7INQUIRY_POS)
 #define BT_UART_MSG_FRAME7CONNECTABLE_POS	(5)
 #define BT_UART_MSG_FRAME7CONNECTABLE_MSK	\
 		(0x1 << BT_UART_MSG_FRAME7CONNECTABLE_POS)
@@ -4237,6 +4273,83 @@
 #define BT_UART_MSG_FRAME7RESERVED_MSK		\
 		(0x3 << BT_UART_MSG_FRAME7RESERVED_POS)
 
+/* BT Session Activity 2 UART message (BT -> WiFi) */
+#define BT_UART_MSG_2_FRAME1RESERVED1_POS	(5)
+#define BT_UART_MSG_2_FRAME1RESERVED1_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME1RESERVED1_POS)
+#define BT_UART_MSG_2_FRAME1RESERVED2_POS	(6)
+#define BT_UART_MSG_2_FRAME1RESERVED2_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME1RESERVED2_POS)
+
+#define BT_UART_MSG_2_FRAME2AGGTRAFFICLOAD_POS	(0)
+#define BT_UART_MSG_2_FRAME2AGGTRAFFICLOAD_MSK	\
+		(0x3F<<BT_UART_MSG_2_FRAME2AGGTRAFFICLOAD_POS)
+#define BT_UART_MSG_2_FRAME2RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME2RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME2RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME3BRLASTTXPOWER_POS	(0)
+#define BT_UART_MSG_2_FRAME3BRLASTTXPOWER_MSK	\
+		(0xF<<BT_UART_MSG_2_FRAME3BRLASTTXPOWER_POS)
+#define BT_UART_MSG_2_FRAME3INQPAGESRMODE_POS	(4)
+#define BT_UART_MSG_2_FRAME3INQPAGESRMODE_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME3INQPAGESRMODE_POS)
+#define BT_UART_MSG_2_FRAME3LEMASTER_POS	(5)
+#define BT_UART_MSG_2_FRAME3LEMASTER_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME3LEMASTER_POS)
+#define BT_UART_MSG_2_FRAME3RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME3RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME3RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME4LELASTTXPOWER_POS	(0)
+#define BT_UART_MSG_2_FRAME4LELASTTXPOWER_MSK	\
+		(0xF<<BT_UART_MSG_2_FRAME4LELASTTXPOWER_POS)
+#define BT_UART_MSG_2_FRAME4NUMLECONN_POS	(4)
+#define BT_UART_MSG_2_FRAME4NUMLECONN_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME4NUMLECONN_POS)
+#define BT_UART_MSG_2_FRAME4RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME4RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME4RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME5BTMINRSSI_POS	(0)
+#define BT_UART_MSG_2_FRAME5BTMINRSSI_MSK	\
+		(0xF<<BT_UART_MSG_2_FRAME5BTMINRSSI_POS)
+#define BT_UART_MSG_2_FRAME5LESCANINITMODE_POS	(4)
+#define BT_UART_MSG_2_FRAME5LESCANINITMODE_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME5LESCANINITMODE_POS)
+#define BT_UART_MSG_2_FRAME5LEADVERMODE_POS	(5)
+#define BT_UART_MSG_2_FRAME5LEADVERMODE_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME5LEADVERMODE_POS)
+#define BT_UART_MSG_2_FRAME5RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME5RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME5RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME6LECONNINTERVAL_POS	(0)
+#define BT_UART_MSG_2_FRAME6LECONNINTERVAL_MSK	\
+		(0x1F<<BT_UART_MSG_2_FRAME6LECONNINTERVAL_POS)
+#define BT_UART_MSG_2_FRAME6RFU_POS		(5)
+#define BT_UART_MSG_2_FRAME6RFU_MSK		\
+		(0x1<<BT_UART_MSG_2_FRAME6RFU_POS)
+#define BT_UART_MSG_2_FRAME6RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME6RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME6RESERVED_POS)
+
+#define BT_UART_MSG_2_FRAME7LECONNSLAVELAT_POS	(0)
+#define BT_UART_MSG_2_FRAME7LECONNSLAVELAT_MSK	\
+		(0x7<<BT_UART_MSG_2_FRAME7LECONNSLAVELAT_POS)
+#define BT_UART_MSG_2_FRAME7LEPROFILE1_POS	(3)
+#define BT_UART_MSG_2_FRAME7LEPROFILE1_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME7LEPROFILE1_POS)
+#define BT_UART_MSG_2_FRAME7LEPROFILE2_POS	(4)
+#define BT_UART_MSG_2_FRAME7LEPROFILE2_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME7LEPROFILE2_POS)
+#define BT_UART_MSG_2_FRAME7LEPROFILEOTHER_POS	(5)
+#define BT_UART_MSG_2_FRAME7LEPROFILEOTHER_MSK	\
+		(0x1<<BT_UART_MSG_2_FRAME7LEPROFILEOTHER_POS)
+#define BT_UART_MSG_2_FRAME7RESERVED_POS	(6)
+#define BT_UART_MSG_2_FRAME7RESERVED_MSK	\
+		(0x3<<BT_UART_MSG_2_FRAME7RESERVED_POS)
+
 
 struct iwl_bt_uart_msg {
 	u8 header;
@@ -4369,6 +4482,11 @@
  * REPLY_WIPAN_PARAMS = 0xb2 (Commands and Notification)
  */
 
+/*
+ * Minimum slot time in TU
+ */
+#define IWL_MIN_SLOT_TIME	20
+
 /**
  * struct iwl_wipan_slot
  * @width: Time in TU
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-core.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-core.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,11 +43,6 @@
 #include "iwl-helpers.h"
 
 
-MODULE_DESCRIPTION("iwl core");
-MODULE_VERSION(IWLWIFI_VERSION);
-MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR);
-MODULE_LICENSE("GPL");
-
 /*
  * set bt_coex_active to true, uCode will do kill/defer
  * every time the priority line is asserted (BT is sending signals on the
@@ -65,15 +60,12 @@
  * default: bt_coex_active = true (BT_COEX_ENABLE)
  */
 bool bt_coex_active = true;
-EXPORT_SYMBOL_GPL(bt_coex_active);
 module_param(bt_coex_active, bool, S_IRUGO);
 MODULE_PARM_DESC(bt_coex_active, "enable wifi/bluetooth co-exist");
 
 u32 iwl_debug_level;
-EXPORT_SYMBOL(iwl_debug_level);
 
 const u8 iwl_bcast_addr[ETH_ALEN] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
-EXPORT_SYMBOL(iwl_bcast_addr);
 
 
 /* This function both allocates and initializes hw and priv. */
@@ -98,7 +90,6 @@
 out:
 	return hw;
 }
-EXPORT_SYMBOL(iwl_alloc_all);
 
 #define MAX_BIT_RATE_40_MHZ 150 /* Mbps */
 #define MAX_BIT_RATE_20_MHZ 72 /* Mbps */
@@ -219,15 +210,12 @@
 		if (!is_channel_valid(ch))
 			continue;
 
-		if (is_channel_a_band(ch))
-			sband =  &priv->bands[IEEE80211_BAND_5GHZ];
-		else
-			sband =  &priv->bands[IEEE80211_BAND_2GHZ];
+		sband =  &priv->bands[ch->band];
 
 		geo_ch = &sband->channels[sband->n_channels++];
 
 		geo_ch->center_freq =
-				ieee80211_channel_to_frequency(ch->channel);
+			ieee80211_channel_to_frequency(ch->channel, ch->band);
 		geo_ch->max_power = ch->max_power_avg;
 		geo_ch->max_antenna_gain = 0xff;
 		geo_ch->hw_value = ch->channel;
@@ -275,7 +263,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(iwlcore_init_geos);
 
 /*
  * iwlcore_free_geos - undo allocations in iwlcore_init_geos
@@ -286,7 +273,6 @@
 	kfree(priv->ieee_rates);
 	clear_bit(STATUS_GEO_CONFIGURED, &priv->status);
 }
-EXPORT_SYMBOL(iwlcore_free_geos);
 
 static bool iwl_is_channel_extension(struct iwl_priv *priv,
 				     enum ieee80211_band band,
@@ -331,7 +317,6 @@
 			le16_to_cpu(ctx->staging.channel),
 			ctx->ht.extension_chan_offset);
 }
-EXPORT_SYMBOL(iwl_is_ht40_tx_allowed);
 
 static u16 iwl_adjust_beacon_interval(u16 beacon_val, u16 max_beacon_val)
 {
@@ -432,7 +417,6 @@
 	return iwl_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
 				sizeof(ctx->timing), &ctx->timing);
 }
-EXPORT_SYMBOL(iwl_send_rxon_timing);
 
 void iwl_set_rxon_hwcrypto(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
 			   int hw_decrypt)
@@ -445,7 +429,6 @@
 		rxon->filter_flags |= RXON_FILTER_DIS_DECRYPT_MSK;
 
 }
-EXPORT_SYMBOL(iwl_set_rxon_hwcrypto);
 
 /* validate RXON structure is valid */
 int iwl_check_rxon_cmd(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
@@ -518,7 +501,6 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_check_rxon_cmd);
 
 /**
  * iwl_full_rxon_required - check if full RXON (vs RXON_ASSOC) cmd is needed
@@ -582,7 +564,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_full_rxon_required);
 
 u8 iwl_rate_get_lowest_plcp(struct iwl_priv *priv,
 			    struct iwl_rxon_context *ctx)
@@ -596,7 +577,6 @@
 	else
 		return IWL_RATE_6M_PLCP;
 }
-EXPORT_SYMBOL(iwl_rate_get_lowest_plcp);
 
 static void _iwl_set_rxon_ht(struct iwl_priv *priv,
 			     struct iwl_ht_config *ht_conf,
@@ -673,7 +653,6 @@
 	for_each_context(priv, ctx)
 		_iwl_set_rxon_ht(priv, ht_conf, ctx);
 }
-EXPORT_SYMBOL(iwl_set_rxon_ht);
 
 /* Return valid, unused, channel for a passive scan to reset the RF */
 u8 iwl_get_single_channel_number(struct iwl_priv *priv,
@@ -714,7 +693,6 @@
 
 	return channel;
 }
-EXPORT_SYMBOL(iwl_get_single_channel_number);
 
 /**
  * iwl_set_rxon_channel - Set the band and channel values in staging RXON
@@ -745,7 +723,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_set_rxon_channel);
 
 void iwl_set_flags_for_band(struct iwl_priv *priv,
 			    struct iwl_rxon_context *ctx,
@@ -769,7 +746,6 @@
 		ctx->staging.flags &= ~RXON_FLG_CCK_MSK;
 	}
 }
-EXPORT_SYMBOL(iwl_set_flags_for_band);
 
 /*
  * initialize rxon structure with default values from eeprom
@@ -841,7 +817,6 @@
 	ctx->staging.ofdm_ht_dual_stream_basic_rates = 0xff;
 	ctx->staging.ofdm_ht_triple_stream_basic_rates = 0xff;
 }
-EXPORT_SYMBOL(iwl_connection_init_rx_config);
 
 void iwl_set_rate(struct iwl_priv *priv)
 {
@@ -874,7 +849,6 @@
 		   (IWL_OFDM_BASIC_RATES_MASK >> IWL_FIRST_OFDM_RATE) & 0xFF;
 	}
 }
-EXPORT_SYMBOL(iwl_set_rate);
 
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success)
 {
@@ -894,35 +868,6 @@
 		mutex_unlock(&priv->mutex);
 	}
 }
-EXPORT_SYMBOL(iwl_chswitch_done);
-
-void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
-	/*
-	 * MULTI-FIXME
-	 * See iwl_mac_channel_switch.
-	 */
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-	struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
-
-	if (priv->switch_rxon.switch_in_progress) {
-		if (!le32_to_cpu(csa->status) &&
-		    (csa->channel == priv->switch_rxon.channel)) {
-			rxon->channel = csa->channel;
-			ctx->staging.channel = csa->channel;
-			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
-			      le16_to_cpu(csa->channel));
-			iwl_chswitch_done(priv, true);
-		} else {
-			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
-			      le16_to_cpu(csa->channel));
-			iwl_chswitch_done(priv, false);
-		}
-	}
-}
-EXPORT_SYMBOL(iwl_rx_csa);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 void iwl_print_rx_config_cmd(struct iwl_priv *priv,
@@ -944,13 +889,15 @@
 	IWL_DEBUG_RADIO(priv, "u8[6] bssid_addr: %pM\n", rxon->bssid_addr);
 	IWL_DEBUG_RADIO(priv, "u16 assoc_id: 0x%x\n", le16_to_cpu(rxon->assoc_id));
 }
-EXPORT_SYMBOL(iwl_print_rx_config_cmd);
 #endif
 /**
  * iwl_irq_handle_error - called for HW or SW error interrupt from card
  */
 void iwl_irq_handle_error(struct iwl_priv *priv)
 {
+	unsigned int reload_msec;
+	unsigned long reload_jiffies;
+
 	/* Set the FW error flag -- cleared on iwl_down */
 	set_bit(STATUS_FW_ERROR, &priv->status);
 
@@ -994,6 +941,25 @@
 	 * commands by clearing the INIT status bit */
 	clear_bit(STATUS_READY, &priv->status);
 
+	/*
+	 * If firmware keep reloading, then it indicate something
+	 * serious wrong and firmware having problem to recover
+	 * from it. Instead of keep trying which will fill the syslog
+	 * and hang the system, let's just stop it
+	 */
+	reload_jiffies = jiffies;
+	reload_msec = jiffies_to_msecs((long) reload_jiffies -
+				(long) priv->reload_jiffies);
+	priv->reload_jiffies = reload_jiffies;
+	if (reload_msec <= IWL_MIN_RELOAD_DURATION) {
+		priv->reload_count++;
+		if (priv->reload_count >= IWL_MAX_CONTINUE_RELOAD_CNT) {
+			IWL_ERR(priv, "BUG_ON, Stop restarting\n");
+			return;
+		}
+	} else
+		priv->reload_count = 0;
+
 	if (!test_bit(STATUS_EXIT_PENDING, &priv->status)) {
 		IWL_DEBUG(priv, IWL_DL_FW_ERRORS,
 			  "Restarting adapter due to uCode error.\n");
@@ -1002,7 +968,6 @@
 			queue_work(priv->workqueue, &priv->restart);
 	}
 }
-EXPORT_SYMBOL(iwl_irq_handle_error);
 
 static int iwl_apm_stop_master(struct iwl_priv *priv)
 {
@@ -1039,7 +1004,6 @@
 	 */
 	iwl_clear_bit(priv, CSR_GP_CNTRL, CSR_GP_CNTRL_REG_FLAG_INIT_DONE);
 }
-EXPORT_SYMBOL(iwl_apm_stop);
 
 
 /*
@@ -1076,7 +1040,7 @@
 	/*
 	 * Enable HAP INTA (interrupt from management bus) to
 	 * wake device's PCI Express link L1a -> L0s
-	 * NOTE:  This is no-op for 3945 (non-existant bit)
+	 * NOTE:  This is no-op for 3945 (non-existent bit)
 	 */
 	iwl_set_bit(priv, CSR_HW_IF_CONFIG_REG,
 				    CSR_HW_IF_CONFIG_REG_BIT_HAP_WAKE_L1A);
@@ -1154,13 +1118,14 @@
 out:
 	return ret;
 }
-EXPORT_SYMBOL(iwl_apm_init);
 
 
 int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
 {
 	int ret;
 	s8 prev_tx_power;
+	bool defer;
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
 
 	lockdep_assert_held(&priv->mutex);
 
@@ -1188,10 +1153,15 @@
 	if (!iwl_is_ready_rf(priv))
 		return -EIO;
 
-	/* scan complete use tx_power_next, need to be updated */
+	/* scan complete and commit_rxon use tx_power_next value,
+	 * it always need to be updated for newest request */
 	priv->tx_power_next = tx_power;
-	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
-		IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
+
+	/* do not set tx power when scanning or channel changing */
+	defer = test_bit(STATUS_SCANNING, &priv->status) ||
+		memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging));
+	if (defer && !force) {
+		IWL_DEBUG_INFO(priv, "Deferring tx power set\n");
 		return 0;
 	}
 
@@ -1207,7 +1177,6 @@
 	}
 	return ret;
 }
-EXPORT_SYMBOL(iwl_set_tx_power);
 
 void iwl_send_bt_config(struct iwl_priv *priv)
 {
@@ -1231,7 +1200,6 @@
 			     sizeof(struct iwl_bt_cmd), &bt_cmd))
 		IWL_ERR(priv, "failed to send BT Coex Config\n");
 }
-EXPORT_SYMBOL(iwl_send_bt_config);
 
 int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
 {
@@ -1249,46 +1217,6 @@
 					sizeof(struct iwl_statistics_cmd),
 					&statistics_cmd);
 }
-EXPORT_SYMBOL(iwl_send_statistics_request);
-
-void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-			   struct iwl_rx_mem_buffer *rxb)
-{
-#ifdef CONFIG_IWLWIFI_DEBUG
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	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);
-
-void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
-	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
-			"notification for %s:\n", len,
-			get_cmd_string(pkt->hdr.cmd));
-	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
-}
-EXPORT_SYMBOL(iwl_rx_pm_debug_statistics_notif);
-
-void iwl_rx_reply_error(struct iwl_priv *priv,
-			struct iwl_rx_mem_buffer *rxb)
-{
-	struct iwl_rx_packet *pkt = rxb_addr(rxb);
-
-	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_rx_reply_error);
 
 void iwl_clear_isr_stats(struct iwl_priv *priv)
 {
@@ -1340,7 +1268,6 @@
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return 0;
 }
-EXPORT_SYMBOL(iwl_mac_conf_tx);
 
 int iwl_mac_tx_last_beacon(struct ieee80211_hw *hw)
 {
@@ -1348,7 +1275,6 @@
 
 	return priv->ibss_manager == IWL_IBSS_MANAGER;
 }
-EXPORT_SYMBOL_GPL(iwl_mac_tx_last_beacon);
 
 static int iwl_set_mode(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
@@ -1403,9 +1329,10 @@
 	struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
 	struct iwl_rxon_context *tmp, *ctx = NULL;
 	int err;
+	enum nl80211_iftype viftype = ieee80211_vif_type_p2p(vif);
 
 	IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
-			   vif->type, vif->addr);
+			   viftype, vif->addr);
 
 	mutex_lock(&priv->mutex);
 
@@ -1429,7 +1356,7 @@
 			continue;
 		}
 
-		if (!(possible_modes & BIT(vif->type)))
+		if (!(possible_modes & BIT(viftype)))
 			continue;
 
 		/* have maybe usable context w/o interface */
@@ -1457,7 +1384,6 @@
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 	return err;
 }
-EXPORT_SYMBOL(iwl_mac_add_interface);
 
 static void iwl_teardown_interface(struct iwl_priv *priv,
 				   struct ieee80211_vif *vif,
@@ -1510,7 +1436,6 @@
 	IWL_DEBUG_MAC80211(priv, "leave\n");
 
 }
-EXPORT_SYMBOL(iwl_mac_remove_interface);
 
 int iwl_alloc_txq_mem(struct iwl_priv *priv)
 {
@@ -1525,14 +1450,12 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_alloc_txq_mem);
 
 void iwl_free_txq_mem(struct iwl_priv *priv)
 {
 	kfree(priv->txq);
 	priv->txq = NULL;
 }
-EXPORT_SYMBOL(iwl_free_txq_mem);
 
 #ifdef CONFIG_IWLWIFI_DEBUGFS
 
@@ -1571,7 +1494,6 @@
 	iwl_reset_traffic_log(priv);
 	return 0;
 }
-EXPORT_SYMBOL(iwl_alloc_traffic_mem);
 
 void iwl_free_traffic_mem(struct iwl_priv *priv)
 {
@@ -1581,7 +1503,6 @@
 	kfree(priv->rx_traffic);
 	priv->rx_traffic = NULL;
 }
-EXPORT_SYMBOL(iwl_free_traffic_mem);
 
 void iwl_dbg_log_tx_data_frame(struct iwl_priv *priv,
 		      u16 length, struct ieee80211_hdr *header)
@@ -1606,7 +1527,6 @@
 			(priv->tx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
 	}
 }
-EXPORT_SYMBOL(iwl_dbg_log_tx_data_frame);
 
 void iwl_dbg_log_rx_data_frame(struct iwl_priv *priv,
 		      u16 length, struct ieee80211_hdr *header)
@@ -1631,7 +1551,6 @@
 			(priv->rx_traffic_idx + 1) % IWL_TRAFFIC_ENTRIES;
 	}
 }
-EXPORT_SYMBOL(iwl_dbg_log_rx_data_frame);
 
 const char *get_mgmt_string(int cmd)
 {
@@ -1675,7 +1594,6 @@
 {
 	memset(&priv->tx_stats, 0, sizeof(struct traffic_stats));
 	memset(&priv->rx_stats, 0, sizeof(struct traffic_stats));
-	priv->led_tpt = 0;
 }
 
 /*
@@ -1768,9 +1686,7 @@
 		stats->data_cnt++;
 		stats->data_bytes += len;
 	}
-	iwl_leds_background(priv);
 }
-EXPORT_SYMBOL(iwl_update_stats);
 #endif
 
 static void iwl_force_rf_reset(struct iwl_priv *priv)
@@ -1909,7 +1825,6 @@
 	mutex_unlock(&priv->mutex);
 	return err;
 }
-EXPORT_SYMBOL(iwl_mac_change_interface);
 
 /*
  * On every watchdog tick we check (latest) time stamp. If it does not
@@ -1981,7 +1896,6 @@
 	mod_timer(&priv->watchdog, jiffies +
 		  msecs_to_jiffies(IWL_WD_TICK(timeout)));
 }
-EXPORT_SYMBOL(iwl_bg_watchdog);
 
 void iwl_setup_watchdog(struct iwl_priv *priv)
 {
@@ -1993,7 +1907,6 @@
 	else
 		del_timer(&priv->watchdog);
 }
-EXPORT_SYMBOL(iwl_setup_watchdog);
 
 /*
  * extended beacon time format
@@ -2019,7 +1932,6 @@
 
 	return (quot << priv->hw_params.beacon_time_tsf_bits) + rem;
 }
-EXPORT_SYMBOL(iwl_usecs_to_beacons);
 
 /* base is usually what we get from ucode with each received frame,
  * the same as HW timer counter counting down
@@ -2047,7 +1959,6 @@
 
 	return cpu_to_le32(res);
 }
-EXPORT_SYMBOL(iwl_add_beacon_time);
 
 #ifdef CONFIG_PM
 
@@ -2067,7 +1978,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_pci_suspend);
 
 int iwl_pci_resume(struct device *device)
 {
@@ -2096,7 +2006,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_pci_resume);
 
 const struct dev_pm_ops iwl_pm_ops = {
 	.suspend = iwl_pci_suspend,
@@ -2106,6 +2015,5 @@
 	.poweroff = iwl_pci_suspend,
 	.restore = iwl_pci_resume,
 };
-EXPORT_SYMBOL(iwl_pm_ops);
 
 #endif /* CONFIG_PM */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-core.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-core.h	2011-05-19 00:06:34.000000000 -0400
@@ -63,6 +63,8 @@
 #ifndef __iwl_core_h__
 #define __iwl_core_h__
 
+#include "iwl-dev.h"
+
 /************************
  * forward declarations *
  ************************/
@@ -210,12 +212,7 @@
 
 	/* temperature */
 	struct iwl_temp_ops temp_ops;
-	/* check for plcp health */
-	bool (*check_plcp_health)(struct iwl_priv *priv,
-					struct iwl_rx_packet *pkt);
-	/* check for ack health */
-	bool (*check_ack_health)(struct iwl_priv *priv,
-					struct iwl_rx_packet *pkt);
+
 	int (*txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 	void (*dev_txfifo_flush)(struct iwl_priv *priv, u16 flush_control);
 
@@ -227,8 +224,6 @@
 
 struct iwl_led_ops {
 	int (*cmd)(struct iwl_priv *priv, struct iwl_led_cmd *led_cmd);
-	int (*on)(struct iwl_priv *priv);
-	int (*off)(struct iwl_priv *priv);
 };
 
 /* NIC specific ops */
@@ -263,6 +258,8 @@
 	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 */
+	bool plcp_check;	/* def: true = enable plcp health check */
+	bool ack_check;		/* def: false = disable ack health check */
 };
 
 /*
@@ -307,7 +304,6 @@
 	u16 led_compensation;
 	const bool broken_powersave;
 	int chain_noise_num_beacons;
-	const bool supports_idle;
 	bool adv_thermal_throttle;
 	bool support_ct_kill_exit;
 	const bool support_wimax_coexist;
@@ -342,6 +338,7 @@
 	u8 ampdu_factor;
 	u8 ampdu_density;
 	bool bt_sco_disable;
+	bool bt_session_2;
 };
 /*
  * @use_rts_for_aggregation: use rts/cts protection for HT traffic
@@ -366,6 +363,7 @@
  * @adv_pm: advance power management
  * @rx_with_siso_diversity: 1x1 device with rx antenna diversity
  * @internal_wimax_coex: internal wifi/wimax combo device
+ * @iq_invert: I/Q inversion
  *
  * We enable the driver to be backward compatible wrt API version. The
  * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -415,6 +413,7 @@
 	const bool adv_pm;
 	const bool rx_with_siso_diversity;
 	const bool internal_wimax_coex;
+	const bool iq_invert;
 };
 
 /***************************
@@ -444,10 +443,6 @@
 void iwl_connection_init_rx_config(struct iwl_priv *priv,
 				   struct iwl_rxon_context *ctx);
 void iwl_set_rate(struct iwl_priv *priv);
-int iwl_set_decrypted_flag(struct iwl_priv *priv,
-			   struct ieee80211_hdr *hdr,
-			   u32 decrypt_res,
-			   struct ieee80211_rx_status *stats);
 void iwl_irq_handle_error(struct iwl_priv *priv);
 int iwl_mac_add_interface(struct ieee80211_hw *hw,
 			  struct ieee80211_vif *vif);
@@ -494,46 +489,21 @@
 static inline void iwl_update_stats(struct iwl_priv *priv, bool is_tx,
 				    __le16 fc, u16 len)
 {
-	struct traffic_stats	*stats;
-
-	if (is_tx)
-		stats = &priv->tx_stats;
-	else
-		stats = &priv->rx_stats;
-
-	if (ieee80211_is_data(fc)) {
-		/* data */
-		stats->data_bytes += len;
-	}
-	iwl_leds_background(priv);
 }
 #endif
-/*****************************************************
- * RX handlers.
- * **************************************************/
-void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
-			   struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
-				      struct iwl_rx_mem_buffer *rxb);
-void iwl_rx_reply_error(struct iwl_priv *priv,
-			struct iwl_rx_mem_buffer *rxb);
 
 /*****************************************************
 * RX
 ******************************************************/
 void iwl_cmd_queue_free(struct iwl_priv *priv);
+void iwl_cmd_queue_unmap(struct iwl_priv *priv);
 int iwl_rx_queue_alloc(struct iwl_priv *priv);
 void iwl_rx_queue_update_write_ptr(struct iwl_priv *priv,
 				  struct iwl_rx_queue *q);
 int iwl_rx_queue_space(const struct iwl_rx_queue *q);
 void iwl_tx_cmd_complete(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
-/* Handlers */
-void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
-					  struct iwl_rx_mem_buffer *rxb);
-void iwl_recover_from_statistics(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt);
+
 void iwl_chswitch_done(struct iwl_priv *priv, bool is_success);
-void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
 
 /* TX helpers */
 
@@ -546,6 +516,7 @@
 void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 			int slots_num, u32 txq_id);
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id);
+void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id);
 void iwl_setup_watchdog(struct iwl_priv *priv);
 /*****************************************************
  * TX power
@@ -582,6 +553,10 @@
 			       struct ieee80211_vif *vif);
 void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
 void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
+int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   enum iwl_scan_type scan_type,
+				   enum ieee80211_band band);
 
 /* For faster active scanning, scan will move to the next channel if fewer than
  * PLCP_QUIET_THRESH packets are heard on this channel within
@@ -755,6 +730,17 @@
 	return priv->hw->wiphy->bands[band];
 }
 
+static inline bool iwl_advanced_bt_coexist(struct iwl_priv *priv)
+{
+	return priv->cfg->bt_params &&
+	       priv->cfg->bt_params->advanced_bt_coexist;
+}
+
+static inline bool iwl_bt_statistics(struct iwl_priv *priv)
+{
+	return priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics;
+}
+
 extern bool bt_coex_active;
 extern bool bt_siso_mode;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-csr.h	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
 
 
 /* HW REV */
-#define CSR_HW_REV_TYPE_MSK            (0x00000F0)
+#define CSR_HW_REV_TYPE_MSK            (0x00001F0)
 #define CSR_HW_REV_TYPE_3945           (0x00000D0)
 #define CSR_HW_REV_TYPE_4965           (0x0000000)
 #define CSR_HW_REV_TYPE_5300           (0x0000020)
@@ -300,9 +300,15 @@
 #define CSR_HW_REV_TYPE_1000           (0x0000060)
 #define CSR_HW_REV_TYPE_6x00           (0x0000070)
 #define CSR_HW_REV_TYPE_6x50           (0x0000080)
-#define CSR_HW_REV_TYPE_6x50g2         (0x0000084)
-#define CSR_HW_REV_TYPE_6x00g2         (0x00000B0)
-#define CSR_HW_REV_TYPE_NONE           (0x00000F0)
+#define CSR_HW_REV_TYPE_6150           (0x0000084)
+#define CSR_HW_REV_TYPE_6x05	       (0x00000B0)
+#define CSR_HW_REV_TYPE_6x30	       CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_6x35	       CSR_HW_REV_TYPE_6x05
+#define CSR_HW_REV_TYPE_2x30	       (0x00000C0)
+#define CSR_HW_REV_TYPE_2x00	       (0x0000100)
+#define CSR_HW_REV_TYPE_200	       (0x0000110)
+#define CSR_HW_REV_TYPE_230	       (0x0000120)
+#define CSR_HW_REV_TYPE_NONE           (0x00001F0)
 
 /* EEPROM REG */
 #define CSR_EEPROM_REG_READ_VALID_MSK	(0x00000001)
@@ -376,6 +382,8 @@
 #define CSR_GP_DRIVER_REG_BIT_CALIB_VERSION6	    (0x00000004)
 #define CSR_GP_DRIVER_REG_BIT_6050_1x2		    (0x00000008)
 
+#define CSR_GP_DRIVER_REG_BIT_RADIO_IQ_INVER	    (0x00000080)
+
 /* GIO Chicken Bits (PCI Express bus link power management) */
 #define CSR_GIO_CHICKEN_BITS_REG_BIT_L1A_NO_L0S_RX  (0x00800000)
 #define CSR_GIO_CHICKEN_BITS_REG_BIT_DIS_L0S_EXIT_TIMER  (0x20000000)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,18 +207,19 @@
 	return ret;
 }
 
-#define BYTE1_MASK 0x000000ff;
-#define BYTE2_MASK 0x0000ffff;
-#define BYTE3_MASK 0x00ffffff;
 static ssize_t iwl_dbgfs_sram_read(struct file *file,
 					char __user *user_buf,
 					size_t count, loff_t *ppos)
 {
-	u32 val;
+	u32 val = 0;
 	char *buf;
 	ssize_t ret;
-	int i;
+	int i = 0;
+	bool device_format = false;
+	int offset = 0;
+	int len = 0;
 	int pos = 0;
+	int sram;
 	struct iwl_priv *priv = file->private_data;
 	size_t bufsz;
 
@@ -230,35 +231,62 @@
 		else
 			priv->dbgfs_sram_len = priv->ucode_data.len;
 	}
-	bufsz =  30 + priv->dbgfs_sram_len * sizeof(char) * 10;
+	len = priv->dbgfs_sram_len;
+
+	if (len == -4) {
+		device_format = true;
+		len = 4;
+	}
+
+	bufsz =  50 + len * 4;
 	buf = kmalloc(bufsz, GFP_KERNEL);
 	if (!buf)
 		return -ENOMEM;
+
 	pos += scnprintf(buf + pos, bufsz - pos, "sram_len: 0x%x\n",
-			priv->dbgfs_sram_len);
+			 len);
 	pos += scnprintf(buf + pos, bufsz - pos, "sram_offset: 0x%x\n",
 			priv->dbgfs_sram_offset);
-	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);
-		if (i < 4) {
-			switch (i) {
-			case 1:
-				val &= BYTE1_MASK;
-				break;
-			case 2:
-				val &= BYTE2_MASK;
-				break;
-			case 3:
-				val &= BYTE3_MASK;
-				break;
-			}
+
+	/* adjust sram address since reads are only on even u32 boundaries */
+	offset = priv->dbgfs_sram_offset & 0x3;
+	sram = priv->dbgfs_sram_offset & ~0x3;
+
+	/* read the first u32 from sram */
+	val = iwl_read_targ_mem(priv, sram);
+
+	for (; len; len--) {
+		/* put the address at the start of every line */
+		if (i == 0)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%08X: ", sram + offset);
+
+		if (device_format)
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%02x", (val >> (8 * (3 - offset))) & 0xff);
+		else
+			pos += scnprintf(buf + pos, bufsz - pos,
+				"%02x ", (val >> (8 * offset)) & 0xff);
+
+		/* if all bytes processed, read the next u32 from sram */
+		if (++offset == 4) {
+			sram += 4;
+			offset = 0;
+			val = iwl_read_targ_mem(priv, sram);
 		}
-		if (!(i % 16))
+
+		/* put in extra spaces and split lines for human readability */
+		if (++i == 16) {
+			i = 0;
 			pos += scnprintf(buf + pos, bufsz - pos, "\n");
-		pos += scnprintf(buf + pos, bufsz - pos, "0x%08x ", val);
+		} else if (!(i & 7)) {
+			pos += scnprintf(buf + pos, bufsz - pos, "   ");
+		} else if (!(i & 3)) {
+			pos += scnprintf(buf + pos, bufsz - pos, " ");
+		}
 	}
-	pos += scnprintf(buf + pos, bufsz - pos, "\n");
+	if (i)
+		pos += scnprintf(buf + pos, bufsz - pos, "\n");
 
 	ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 	kfree(buf);
@@ -282,6 +310,9 @@
 	if (sscanf(buf, "%x,%x", &offset, &len) == 2) {
 		priv->dbgfs_sram_offset = offset;
 		priv->dbgfs_sram_len = len;
+	} else if (sscanf(buf, "%x", &offset) == 1) {
+		priv->dbgfs_sram_offset = offset;
+		priv->dbgfs_sram_len = -4;
 	} else {
 		priv->dbgfs_sram_offset = 0;
 		priv->dbgfs_sram_len = 0;
@@ -668,29 +699,6 @@
 	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
 }
 
-static ssize_t iwl_dbgfs_led_read(struct file *file, char __user *user_buf,
-				  size_t count, loff_t *ppos)
-{
-	struct iwl_priv *priv = file->private_data;
-	int pos = 0;
-	char buf[256];
-	const size_t bufsz = sizeof(buf);
-
-	pos += scnprintf(buf + pos, bufsz - pos,
-			 "allow blinking: %s\n",
-			 (priv->allow_blinking) ? "True" : "False");
-	if (priv->allow_blinking) {
-		pos += scnprintf(buf + pos, bufsz - pos,
-				 "Led blinking rate: %u\n",
-				 priv->last_blink_rate);
-		pos += scnprintf(buf + pos, bufsz - pos,
-				 "Last blink time: %lu\n",
-				 priv->last_blink_time);
-	}
-
-	return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
-}
-
 static ssize_t iwl_dbgfs_thermal_throttling_read(struct file *file,
 				char __user *user_buf,
 				size_t count, loff_t *ppos)
@@ -856,7 +864,6 @@
 DEBUGFS_READ_FILE_OPS(status);
 DEBUGFS_READ_WRITE_FILE_OPS(interrupt);
 DEBUGFS_READ_FILE_OPS(qos);
-DEBUGFS_READ_FILE_OPS(led);
 DEBUGFS_READ_FILE_OPS(thermal_throttling);
 DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
 DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
@@ -1580,10 +1587,9 @@
 			 "last traffic notif: %d\n",
 		priv->bt_status ? "On" : "Off", priv->last_bt_traffic_load);
 	pos += scnprintf(buf + pos, bufsz - pos, "ch_announcement: %d, "
-			 "sco_active: %d, kill_ack_mask: %x, "
-			 "kill_cts_mask: %x\n",
-		priv->bt_ch_announce, priv->bt_sco_active,
-		priv->kill_ack_mask, priv->kill_cts_mask);
+			 "kill_ack_mask: %x, kill_cts_mask: %x\n",
+		priv->bt_ch_announce, priv->kill_ack_mask,
+		priv->kill_cts_mask);
 
 	pos += scnprintf(buf + pos, bufsz - pos, "bluetooth traffic load: ");
 	switch (priv->bt_traffic_load) {
@@ -1725,7 +1731,6 @@
 	DEBUGFS_ADD_FILE(status, dir_data, S_IRUSR);
 	DEBUGFS_ADD_FILE(interrupt, dir_data, S_IWUSR | S_IRUSR);
 	DEBUGFS_ADD_FILE(qos, dir_data, S_IRUSR);
-	DEBUGFS_ADD_FILE(led, dir_data, S_IRUSR);
 	if (!priv->cfg->base_params->broken_powersave) {
 		DEBUGFS_ADD_FILE(sleep_level_override, dir_data,
 				 S_IWUSR | S_IRUSR);
@@ -1759,13 +1764,13 @@
 		DEBUGFS_ADD_FILE(chain_noise, dir_debug, S_IRUSR);
 	if (priv->cfg->base_params->ucode_tracing)
 		DEBUGFS_ADD_FILE(ucode_tracing, dir_debug, S_IWUSR | S_IRUSR);
-	if (priv->cfg->bt_params && priv->cfg->bt_params->bt_statistics)
+	if (iwl_bt_statistics(priv))
 		DEBUGFS_ADD_FILE(ucode_bt_stats, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(reply_tx_error, dir_debug, S_IRUSR);
 	DEBUGFS_ADD_FILE(rxon_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(rxon_filter_flags, dir_debug, S_IWUSR);
 	DEBUGFS_ADD_FILE(wd_timeout, dir_debug, S_IWUSR);
-	if (priv->cfg->bt_params && priv->cfg->bt_params->advanced_bt_coexist)
+	if (iwl_advanced_bt_coexist(priv))
 		DEBUGFS_ADD_FILE(bt_traffic, dir_debug, S_IRUSR);
 	if (priv->cfg->base_params->sensitivity_calib_by_driver)
 		DEBUGFS_ADD_BOOL(disable_sensitivity, dir_rf,
@@ -1783,7 +1788,6 @@
 	iwl_dbgfs_unregister(priv);
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(iwl_dbgfs_register);
 
 /**
  * Remove the debugfs files and directories
@@ -1797,7 +1801,6 @@
 	debugfs_remove_recursive(priv->debugfs_dir);
 	priv->debugfs_dir = NULL;
 }
-EXPORT_SYMBOL(iwl_dbgfs_unregister);
 
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-dev.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,8 @@
 
 #include <linux/pci.h> /* for struct pci_device_id */
 #include <linux/kernel.h>
+#include <linux/wait.h>
+#include <linux/leds.h>
 #include <net/ieee80211_radiotap.h>
 
 #include "iwl-eeprom.h"
@@ -41,14 +43,14 @@
 #include "iwl-prph.h"
 #include "iwl-fh.h"
 #include "iwl-debug.h"
-#include "iwl-4965-hw.h"
-#include "iwl-3945-hw.h"
 #include "iwl-agn-hw.h"
 #include "iwl-led.h"
 #include "iwl-power.h"
 #include "iwl-agn-rs.h"
 #include "iwl-agn-tt.h"
 
+#define U32_PAD(n)		((4-(n))&0x3)
+
 struct iwl_tx_queue;
 
 /* CT-KILL constants */
@@ -136,7 +138,7 @@
 				* space more than this */
 	int high_mark;         /* high watermark, stop queue if free
 				* space less than this */
-} __packed;
+};
 
 /* One for each TFD */
 struct iwl_tx_info {
@@ -507,6 +509,7 @@
 	atomic_t pending_frames;
 	bool client;
 	bool asleep;
+	u8 max_agg_bufsize;
 };
 
 /**
@@ -995,7 +998,6 @@
 	u32 unknown;
 };
 
-#ifdef CONFIG_IWLWIFI_DEBUGFS
 /* management statistics */
 enum iwl_mgmt_stats {
 	MANAGEMENT_ASSOC_REQ = 0,
@@ -1026,16 +1028,13 @@
 };
 
 struct traffic_stats {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
 	u32 mgmt[MANAGEMENT_MAX];
 	u32 ctrl[CONTROL_MAX];
 	u32 data_cnt;
 	u64 data_bytes;
-};
-#else
-struct traffic_stats {
-	u64 data_bytes;
-};
 #endif
+};
 
 /*
  * iwl_switch_rxon: "channel switch" structure
@@ -1111,6 +1110,11 @@
 /* BT Antenna Coupling Threshold (dB) */
 #define IWL_BT_ANTENNA_COUPLING_THRESHOLD	(35)
 
+/* Firmware reload counter and Timestamp */
+#define IWL_MIN_RELOAD_DURATION		1000 /* 1000 ms */
+#define IWL_MAX_CONTINUE_RELOAD_CNT	4
+
+
 enum iwl_reset {
 	IWL_RF_RESET = 0,
 	IWL_FW_RESET,
@@ -1139,6 +1143,33 @@
  */
 #define IWLAGN_EXT_BEACON_TIME_POS	22
 
+/**
+ * struct iwl_notification_wait - notification wait entry
+ * @list: list head for global list
+ * @fn: function called with the notification
+ * @cmd: command ID
+ *
+ * This structure is not used directly, to wait for a
+ * notification declare it on the stack, and call
+ * iwlagn_init_notification_wait() with appropriate
+ * parameters. Then do whatever will cause the ucode
+ * to notify the driver, and to wait for that then
+ * call iwlagn_wait_notification().
+ *
+ * Each notification is one-shot. If at some point we
+ * need to support multi-shot notifications (which
+ * can't be allocated on the stack) we need to modify
+ * the code for them.
+ */
+struct iwl_notification_wait {
+	struct list_head list;
+
+	void (*fn)(struct iwl_priv *priv, struct iwl_rx_packet *pkt);
+
+	u8 cmd;
+	bool triggered;
+};
+
 enum iwl_rxon_context_id {
 	IWL_RXON_CTX_BSS,
 	IWL_RXON_CTX_PAN,
@@ -1199,6 +1230,12 @@
 	} ht;
 };
 
+enum iwl_scan_type {
+	IWL_SCAN_NORMAL,
+	IWL_SCAN_RADIO_RESET,
+	IWL_SCAN_OFFCH_TX,
+};
+
 struct iwl_priv {
 
 	/* ieee device used by generic ieee processing code */
@@ -1230,12 +1267,16 @@
 	/* track IBSS manager (last beacon) status */
 	u32 ibss_manager;
 
-	/* storing the jiffies when the plcp error rate is received */
-	unsigned long plcp_jiffies;
+	/* jiffies when last recovery from statistics was performed */
+	unsigned long rx_statistics_jiffies;
 
 	/* force reset */
 	struct iwl_force_reset force_reset[IWL_MAX_FORCE_RESET];
 
+	/* firmware reload counter and timestamp */
+	unsigned long reload_jiffies;
+	int reload_count;
+
 	/* we allocate array of iwl_channel_info for NIC's valid channels.
 	 *    Access via channel # using indirect index array */
 	struct iwl_channel_info *channel_info;	/* channel info array */
@@ -1255,7 +1296,7 @@
 	enum ieee80211_band scan_band;
 	struct cfg80211_scan_request *scan_request;
 	struct ieee80211_vif *scan_vif;
-	bool is_internal_short_scan;
+	enum iwl_scan_type scan_type;
 	u8 scan_tx_ant[IEEE80211_NUM_BANDS];
 	u8 mgmt_tx_ant;
 
@@ -1310,11 +1351,6 @@
 	struct iwl_init_alive_resp card_alive_init;
 	struct iwl_alive_resp card_alive;
 
-	unsigned long last_blink_time;
-	u8 last_blink_rate;
-	u8 allow_blinking;
-	u64 led_tpt;
-
 	u16 active_rate;
 
 	u8 start_calib;
@@ -1463,6 +1499,21 @@
 			struct iwl_bt_notif_statistics delta_statistics_bt;
 			struct iwl_bt_notif_statistics max_delta_bt;
 #endif
+
+			/* notification wait support */
+			struct list_head notif_waits;
+			spinlock_t notif_wait_lock;
+			wait_queue_head_t notif_waitq;
+
+			/* remain-on-channel offload support */
+			struct ieee80211_channel *hw_roc_channel;
+			struct delayed_work hw_roc_work;
+			enum nl80211_channel_type hw_roc_chantype;
+			int hw_roc_duration;
+
+			struct sk_buff *offchan_tx_skb;
+			int offchan_tx_timeout;
+			struct ieee80211_channel *offchan_tx_chan;
 		} _agn;
 #endif
 	};
@@ -1472,7 +1523,6 @@
 	u8 bt_status;
 	u8 bt_traffic_load, last_bt_traffic_load;
 	bool bt_ch_announce;
-	bool bt_sco_active;
 	bool bt_full_concurrent;
 	bool bt_ant_couple_ok;
 	__le32 kill_ack_mask;
@@ -1547,6 +1597,10 @@
 	bool hw_ready;
 
 	struct iwl_event_log event_log;
+
+	struct led_classdev led;
+	unsigned long blink_on, blink_off;
+	bool led_registered;
 }; /*iwl_priv */
 
 static inline void iwl_txq_ctx_activate(struct iwl_priv *priv, int txq_id)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -222,7 +222,6 @@
 	BUG_ON(offset >= priv->cfg->base_params->eeprom_size);
 	return &priv->eeprom[offset];
 }
-EXPORT_SYMBOL(iwlcore_eeprom_query_addr);
 
 static int iwl_init_otp_access(struct iwl_priv *priv)
 {
@@ -382,7 +381,6 @@
 {
 	return priv->cfg->ops->lib->eeprom_ops.query_addr(priv, offset);
 }
-EXPORT_SYMBOL(iwl_eeprom_query_addr);
 
 u16 iwl_eeprom_query16(const struct iwl_priv *priv, size_t offset)
 {
@@ -390,7 +388,6 @@
 		return 0;
 	return (u16)priv->eeprom[offset] | ((u16)priv->eeprom[offset + 1] << 8);
 }
-EXPORT_SYMBOL(iwl_eeprom_query16);
 
 /**
  * iwl_eeprom_init - read EEPROM contents
@@ -509,14 +506,12 @@
 alloc_err:
 	return ret;
 }
-EXPORT_SYMBOL(iwl_eeprom_init);
 
 void iwl_eeprom_free(struct iwl_priv *priv)
 {
 	kfree(priv->eeprom);
 	priv->eeprom = NULL;
 }
-EXPORT_SYMBOL(iwl_eeprom_free);
 
 static void iwl_init_band_reference(const struct iwl_priv *priv,
 			int eep_band, int *eeprom_ch_count,
@@ -779,7 +774,6 @@
 
 	return 0;
 }
-EXPORT_SYMBOL(iwl_init_channel_map);
 
 /*
  * iwl_free_channel_map - undo allocations in iwl_init_channel_map
@@ -789,7 +783,6 @@
 	kfree(priv->channel_info);
 	priv->channel_count = 0;
 }
-EXPORT_SYMBOL(iwl_free_channel_map);
 
 /**
  * iwl_get_channel_info - Find driver's private channel info
@@ -818,4 +811,3 @@
 
 	return NULL;
 }
-EXPORT_SYMBOL(iwl_get_channel_info);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -241,19 +241,32 @@
 
 /* 6x00 Specific */
 #define EEPROM_6000_TX_POWER_VERSION    (4)
-#define EEPROM_6000_EEPROM_VERSION	(0x434)
+#define EEPROM_6000_EEPROM_VERSION	(0x423)
 
 /* 6x50 Specific */
 #define EEPROM_6050_TX_POWER_VERSION    (4)
 #define EEPROM_6050_EEPROM_VERSION	(0x532)
 
-/* 6x50g2 Specific */
-#define EEPROM_6050G2_TX_POWER_VERSION    (6)
-#define EEPROM_6050G2_EEPROM_VERSION	(0x553)
+/* 6150 Specific */
+#define EEPROM_6150_TX_POWER_VERSION    (6)
+#define EEPROM_6150_EEPROM_VERSION	(0x553)
+
+/* 6x05 Specific */
+#define EEPROM_6005_TX_POWER_VERSION    (6)
+#define EEPROM_6005_EEPROM_VERSION	(0x709)
+
+/* 6x30 Specific */
+#define EEPROM_6030_TX_POWER_VERSION    (6)
+#define EEPROM_6030_EEPROM_VERSION	(0x709)
+
+/* 2x00 Specific */
+#define EEPROM_2000_TX_POWER_VERSION    (6)
+#define EEPROM_2000_EEPROM_VERSION	(0x805)
+
+/* 6x35 Specific */
+#define EEPROM_6035_TX_POWER_VERSION    (6)
+#define EEPROM_6035_EEPROM_VERSION	(0x753)
 
-/* 6x00g2 Specific */
-#define EEPROM_6000G2_TX_POWER_VERSION    (6)
-#define EEPROM_6000G2_EEPROM_VERSION	(0x709)
 
 /* OTP */
 /* lower blocks contain EEPROM image and calibration data */
@@ -264,6 +277,7 @@
 #define OTP_MAX_LL_ITEMS_1000		(3)	/* OTP blocks for 1000 */
 #define OTP_MAX_LL_ITEMS_6x00		(4)	/* OTP blocks for 6x00 */
 #define OTP_MAX_LL_ITEMS_6x50		(7)	/* OTP blocks for 6x50 */
+#define OTP_MAX_LL_ITEMS_2x00		(4)	/* OTP blocks for 2x00 */
 
 /* 2.4 GHz */
 extern const u8 iwl_eeprom_band_1[14];
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-fh.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-fh.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-fh.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-fh.h	2011-05-19 00:06:34.000000000 -0400
@@ -436,7 +436,7 @@
  * @finished_rb_num [0:11] - Indicates the index of the current RB
  * 	in which the last frame was written to
  * @finished_fr_num [0:11] - Indicates the index of the RX Frame
- * 	which was transfered
+ * 	which was transferred
  */
 struct iwl_rb_status {
 	__le16 closed_rb_num;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-hcmd.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-hcmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-hcmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-hcmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -108,12 +108,12 @@
 		IWL_CMD(REPLY_WIPAN_WEPKEY);
 		IWL_CMD(REPLY_WIPAN_P2P_CHANNEL_SWITCH);
 		IWL_CMD(REPLY_WIPAN_NOA_NOTIFICATION);
+		IWL_CMD(REPLY_WIPAN_DEACTIVATION_COMPLETE);
 	default:
 		return "UNKNOWN";
 
 	}
 }
-EXPORT_SYMBOL(get_cmd_string);
 
 #define HOST_COMPLETE_TIMEOUT (HZ / 2)
 
@@ -252,7 +252,6 @@
 	mutex_unlock(&priv->sync_cmd_mutex);
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_cmd_sync);
 
 int iwl_send_cmd(struct iwl_priv *priv, struct iwl_host_cmd *cmd)
 {
@@ -261,7 +260,6 @@
 
 	return iwl_send_cmd_sync(priv, cmd);
 }
-EXPORT_SYMBOL(iwl_send_cmd);
 
 int iwl_send_cmd_pdu(struct iwl_priv *priv, u8 id, u16 len, const void *data)
 {
@@ -273,7 +271,6 @@
 
 	return iwl_send_cmd_sync(priv, &cmd);
 }
-EXPORT_SYMBOL(iwl_send_cmd_pdu);
 
 int iwl_send_cmd_pdu_async(struct iwl_priv *priv,
 			   u8 id, u16 len, const void *data,
@@ -292,4 +289,3 @@
 
 	return iwl_send_cmd_async(priv, &cmd);
 }
-EXPORT_SYMBOL(iwl_send_cmd_pdu_async);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-led.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-led.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-led.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,31 +48,19 @@
 MODULE_PARM_DESC(led_mode, "0=system default, "
 		"1=On(RF On)/Off(RF Off), 2=blinking");
 
-static const struct {
-	u16 tpt;	/* Mb/s */
-	u8 on_time;
-	u8 off_time;
-} blink_tbl[] =
-{
-	{300, 25, 25},
-	{200, 40, 40},
-	{100, 55, 55},
-	{70, 65, 65},
-	{50, 75, 75},
-	{20, 85, 85},
-	{10, 95, 95},
-	{5, 110, 110},
-	{1, 130, 130},
-	{0, 167, 167},
-	/* SOLID_ON */
-	{-1, IWL_LED_SOLID, 0}
+static const struct ieee80211_tpt_blink iwl_blink[] = {
+	{ .throughput = 0 * 1024 - 1, .blink_time = 334 },
+	{ .throughput = 1 * 1024 - 1, .blink_time = 260 },
+	{ .throughput = 5 * 1024 - 1, .blink_time = 220 },
+	{ .throughput = 10 * 1024 - 1, .blink_time = 190 },
+	{ .throughput = 20 * 1024 - 1, .blink_time = 170 },
+	{ .throughput = 50 * 1024 - 1, .blink_time = 150 },
+	{ .throughput = 70 * 1024 - 1, .blink_time = 130 },
+	{ .throughput = 100 * 1024 - 1, .blink_time = 110 },
+	{ .throughput = 200 * 1024 - 1, .blink_time = 80 },
+	{ .throughput = 300 * 1024 - 1, .blink_time = 50 },
 };
 
-#define IWL_1MB_RATE (128 * 1024)
-#define IWL_LED_THRESHOLD (16)
-#define IWL_MAX_BLINK_TBL (ARRAY_SIZE(blink_tbl) - 1) /* exclude SOLID_ON */
-#define IWL_SOLID_BLINK_IDX (ARRAY_SIZE(blink_tbl) - 1)
-
 /*
  * Adjust led blink rate to compensate on a MAC Clock difference on every HW
  * Led blink rate analysis showed an average deviation of 0% on 3945,
@@ -97,133 +85,102 @@
 }
 
 /* Set led pattern command */
-static int iwl_led_pattern(struct iwl_priv *priv, unsigned int idx)
+static int iwl_led_cmd(struct iwl_priv *priv,
+		       unsigned long on,
+		       unsigned long off)
 {
 	struct iwl_led_cmd led_cmd = {
 		.id = IWL_LED_LINK,
 		.interval = IWL_DEF_LED_INTRVL
 	};
+	int ret;
 
-	BUG_ON(idx > IWL_MAX_BLINK_TBL);
+	if (!test_bit(STATUS_READY, &priv->status))
+		return -EBUSY;
 
-	IWL_DEBUG_LED(priv, "Led blink time compensation= %u\n",
+	if (priv->blink_on == on && priv->blink_off == off)
+		return 0;
+
+	IWL_DEBUG_LED(priv, "Led blink time compensation=%u\n",
 			priv->cfg->base_params->led_compensation);
-	led_cmd.on =
-		iwl_blink_compensation(priv, blink_tbl[idx].on_time,
+	led_cmd.on = iwl_blink_compensation(priv, on,
 				priv->cfg->base_params->led_compensation);
-	led_cmd.off =
-		iwl_blink_compensation(priv, blink_tbl[idx].off_time,
+	led_cmd.off = iwl_blink_compensation(priv, off,
 				priv->cfg->base_params->led_compensation);
 
-	return priv->cfg->ops->led->cmd(priv, &led_cmd);
+	ret = priv->cfg->ops->led->cmd(priv, &led_cmd);
+	if (!ret) {
+		priv->blink_on = on;
+		priv->blink_off = off;
+	}
+	return ret;
 }
 
-int iwl_led_start(struct iwl_priv *priv)
+static void iwl_led_brightness_set(struct led_classdev *led_cdev,
+				   enum led_brightness brightness)
 {
-	return priv->cfg->ops->led->on(priv);
-}
-EXPORT_SYMBOL(iwl_led_start);
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
+	unsigned long on = 0;
 
-int iwl_led_associate(struct iwl_priv *priv)
-{
-	IWL_DEBUG_LED(priv, "Associated\n");
-	if (priv->cfg->led_mode == IWL_LED_BLINK)
-		priv->allow_blinking = 1;
-	priv->last_blink_time = jiffies;
+	if (brightness > 0)
+		on = IWL_LED_SOLID;
 
-	return 0;
+	iwl_led_cmd(priv, on, 0);
 }
-EXPORT_SYMBOL(iwl_led_associate);
 
-int iwl_led_disassociate(struct iwl_priv *priv)
+static int iwl_led_blink_set(struct led_classdev *led_cdev,
+			     unsigned long *delay_on,
+			     unsigned long *delay_off)
 {
-	priv->allow_blinking = 0;
+	struct iwl_priv *priv = container_of(led_cdev, struct iwl_priv, led);
 
-	return 0;
+	return iwl_led_cmd(priv, *delay_on, *delay_off);
 }
-EXPORT_SYMBOL(iwl_led_disassociate);
 
-/*
- * calculate blink rate according to last second Tx/Rx activities
- */
-static int iwl_get_blink_rate(struct iwl_priv *priv)
+void iwl_leds_init(struct iwl_priv *priv)
 {
-	int i;
-	/* count both tx and rx traffic to be able to
-	 * handle traffic in either direction
-	 */
-	u64 current_tpt = priv->tx_stats.data_bytes +
-			  priv->rx_stats.data_bytes;
-	s64 tpt = current_tpt - priv->led_tpt;
-
-	if (tpt < 0) /* wraparound */
-		tpt = -tpt;
-
-	IWL_DEBUG_LED(priv, "tpt %lld current_tpt %llu\n",
-		(long long)tpt,
-		(unsigned long long)current_tpt);
-	priv->led_tpt = current_tpt;
-
-	if (!priv->allow_blinking)
-		i = IWL_MAX_BLINK_TBL;
-	else
-		for (i = 0; i < IWL_MAX_BLINK_TBL; i++)
-			if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE))
-				break;
+	int mode = led_mode;
+	int ret;
 
-	IWL_DEBUG_LED(priv, "LED BLINK IDX=%d\n", i);
-	return i;
-}
+	if (mode == IWL_LED_DEFAULT)
+		mode = priv->cfg->led_mode;
 
-/*
- * this function called from handler. Since setting Led command can
- * happen very frequent we postpone led command to be called from
- * REPLY handler so we know ucode is up
- */
-void iwl_leds_background(struct iwl_priv *priv)
-{
-	u8 blink_idx;
+	priv->led.name = kasprintf(GFP_KERNEL, "%s-led",
+				   wiphy_name(priv->hw->wiphy));
+	priv->led.brightness_set = iwl_led_brightness_set;
+	priv->led.blink_set = iwl_led_blink_set;
+	priv->led.max_brightness = 1;
 
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status)) {
-		priv->last_blink_time = 0;
-		return;
-	}
-	if (iwl_is_rfkill(priv)) {
-		priv->last_blink_time = 0;
-		return;
+	switch (mode) {
+	case IWL_LED_DEFAULT:
+		WARN_ON(1);
+		break;
+	case IWL_LED_BLINK:
+		priv->led.default_trigger =
+			ieee80211_create_tpt_led_trigger(priv->hw,
+					IEEE80211_TPT_LEDTRIG_FL_CONNECTED,
+					iwl_blink, ARRAY_SIZE(iwl_blink));
+		break;
+	case IWL_LED_RF_STATE:
+		priv->led.default_trigger =
+			ieee80211_get_radio_led_name(priv->hw);
+		break;
 	}
 
-	if (!priv->allow_blinking) {
-		priv->last_blink_time = 0;
-		if (priv->last_blink_rate != IWL_SOLID_BLINK_IDX) {
-			priv->last_blink_rate = IWL_SOLID_BLINK_IDX;
-			iwl_led_pattern(priv, IWL_SOLID_BLINK_IDX);
-		}
+	ret = led_classdev_register(&priv->pci_dev->dev, &priv->led);
+	if (ret) {
+		kfree(priv->led.name);
 		return;
 	}
-	if (!priv->last_blink_time ||
-	    !time_after(jiffies, priv->last_blink_time +
-			msecs_to_jiffies(1000)))
-		return;
 
-	blink_idx = iwl_get_blink_rate(priv);
-
-	/* call only if blink rate change */
-	if (blink_idx != priv->last_blink_rate)
-		iwl_led_pattern(priv, blink_idx);
-
-	priv->last_blink_time = jiffies;
-	priv->last_blink_rate = blink_idx;
+	priv->led_registered = true;
 }
-EXPORT_SYMBOL(iwl_leds_background);
 
-void iwl_leds_init(struct iwl_priv *priv)
+void iwl_leds_exit(struct iwl_priv *priv)
 {
-	priv->last_blink_rate = 0;
-	priv->last_blink_time = 0;
-	priv->allow_blinking = 0;
-	if (led_mode != IWL_LED_DEFAULT &&
-	    led_mode != priv->cfg->led_mode)
-		priv->cfg->led_mode = led_mode;
+	if (!priv->led_registered)
+		return;
+
+	led_classdev_unregister(&priv->led);
+	kfree(priv->led.name);
 }
-EXPORT_SYMBOL(iwl_leds_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-led.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-led.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-led.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,23 +31,14 @@
 struct iwl_priv;
 
 #define IWL_LED_SOLID 11
-#define IWL_LED_NAME_LEN 31
 #define IWL_DEF_LED_INTRVL cpu_to_le32(1000)
 
 #define IWL_LED_ACTIVITY       (0<<1)
 #define IWL_LED_LINK           (1<<1)
 
-enum led_type {
-	IWL_LED_TRG_TX,
-	IWL_LED_TRG_RX,
-	IWL_LED_TRG_ASSOC,
-	IWL_LED_TRG_RADIO,
-	IWL_LED_TRG_MAX,
-};
-
 /*
  * LED mode
- *    IWL_LED_DEFAULT:  use system default
+ *    IWL_LED_DEFAULT:  use device default
  *    IWL_LED_RF_STATE: turn LED on/off based on RF state
  *			LED ON  = RF ON
  *			LED OFF = RF OFF
@@ -60,9 +51,6 @@
 };
 
 void iwl_leds_init(struct iwl_priv *priv);
-void iwl_leds_background(struct iwl_priv *priv);
-int iwl_led_start(struct iwl_priv *priv);
-int iwl_led_associate(struct iwl_priv *priv);
-int iwl_led_disassociate(struct iwl_priv *priv);
+void iwl_leds_exit(struct iwl_priv *priv);
 
 #endif /* __iwl_leds_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,662 +0,0 @@
-/******************************************************************************
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * 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 <net/mac80211.h>
-
-#include "iwl-dev.h"
-#include "iwl-core.h"
-#include "iwl-helpers.h"
-#include "iwl-legacy.h"
-
-static void iwl_update_qos(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
-{
-	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
-		return;
-
-	if (!ctx->is_active)
-		return;
-
-	ctx->qos_data.def_qos_parm.qos_flags = 0;
-
-	if (ctx->qos_data.qos_active)
-		ctx->qos_data.def_qos_parm.qos_flags |=
-			QOS_PARAM_FLG_UPDATE_EDCA_MSK;
-
-	if (ctx->ht.enabled)
-		ctx->qos_data.def_qos_parm.qos_flags |= QOS_PARAM_FLG_TGN_MSK;
-
-	IWL_DEBUG_QOS(priv, "send QoS cmd with Qos active=%d FLAGS=0x%X\n",
-		      ctx->qos_data.qos_active,
-		      ctx->qos_data.def_qos_parm.qos_flags);
-
-	iwl_send_cmd_pdu_async(priv, ctx->qos_cmd,
-			       sizeof(struct iwl_qosparam_cmd),
-			       &ctx->qos_data.def_qos_parm, NULL);
-}
-
-/**
- * iwl_legacy_mac_config - mac80211 config callback
- */
-int iwl_legacy_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;
-	struct ieee80211_channel *channel = conf->channel;
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct iwl_rxon_context *ctx;
-	unsigned long flags = 0;
-	int ret = 0;
-	u16 ch;
-	int scan_active = 0;
-	bool ht_changed[NUM_IWL_RXON_CTX] = {};
-
-	if (WARN_ON(!priv->cfg->ops->legacy))
-		return -EOPNOTSUPP;
-
-	mutex_lock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "enter to channel %d changed 0x%X\n",
-					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");
-	}
-
-	if (changed & (IEEE80211_CONF_CHANGE_SMPS |
-		       IEEE80211_CONF_CHANGE_CHANNEL)) {
-		/* mac80211 uses static for non-HT which is what we want */
-		priv->current_ht_config.smps = conf->smps_mode;
-
-		/*
-		 * Recalculate chain counts.
-		 *
-		 * If monitor mode is enabled then mac80211 will
-		 * set up the SM PS mode to OFF if an HT channel is
-		 * configured.
-		 */
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			for_each_context(priv, ctx)
-				priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	/* 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 = channel->hw_value;
-		ch_info = iwl_get_channel_info(priv, channel->band, ch);
-		if (!is_channel_valid(ch_info)) {
-			IWL_DEBUG_MAC80211(priv, "leave - invalid channel\n");
-			ret = -EINVAL;
-			goto set_ch_out;
-		}
-
-		spin_lock_irqsave(&priv->lock, flags);
-
-		for_each_context(priv, ctx) {
-			/* Configure HT40 channels */
-			if (ctx->ht.enabled != conf_is_ht(conf)) {
-				ctx->ht.enabled = conf_is_ht(conf);
-				ht_changed[ctx->ctxid] = true;
-			}
-			if (ctx->ht.enabled) {
-				if (conf_is_ht40_minus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_BELOW;
-					ctx->ht.is_40mhz = true;
-				} else if (conf_is_ht40_plus(conf)) {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
-					ctx->ht.is_40mhz = true;
-				} else {
-					ctx->ht.extension_chan_offset =
-						IEEE80211_HT_PARAM_CHA_SEC_NONE;
-					ctx->ht.is_40mhz = false;
-				}
-			} else
-				ctx->ht.is_40mhz = false;
-
-			/*
-			 * Default to no protection. Protection mode will
-			 * later be set from BSS config in iwl_ht_conf
-			 */
-			ctx->ht.protection = IEEE80211_HT_OP_MODE_PROTECTION_NONE;
-
-			/* 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(ctx->staging.channel) != ch))
-				ctx->staging.flags = 0;
-
-			iwl_set_rxon_channel(priv, channel, ctx);
-			iwl_set_rxon_ht(priv, ht_conf);
-
-			iwl_set_flags_for_band(priv, ctx, channel->band,
-					       ctx->vif);
-		}
-
-		spin_unlock_irqrestore(&priv->lock, flags);
-
-		if (priv->cfg->ops->legacy->update_bcast_stations)
-			ret = priv->cfg->ops->legacy->update_bcast_stations(priv);
-
- 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 |
-			IEEE80211_CONF_CHANGE_IDLE)) {
-		ret = iwl_power_update_mode(priv, false);
-		if (ret)
-			IWL_DEBUG_MAC80211(priv, "Error setting sleep 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);
-	}
-
-	if (!iwl_is_ready(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - not ready\n");
-		goto out;
-	}
-
-	if (scan_active)
-		goto out;
-
-	for_each_context(priv, ctx) {
-		if (memcmp(&ctx->active, &ctx->staging, sizeof(ctx->staging)))
-			iwlcore_commit_rxon(priv, ctx);
-		else
-			IWL_DEBUG_INFO(priv,
-				"Not re-sending same RXON configuration.\n");
-		if (ht_changed[ctx->ctxid])
-			iwl_update_qos(priv, ctx);
-	}
-
-out:
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-	mutex_unlock(&priv->mutex);
-	return ret;
-}
-EXPORT_SYMBOL(iwl_legacy_mac_config);
-
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	/* IBSS can only be the IWL_RXON_CTX_BSS context */
-	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
-
-	if (WARN_ON(!priv->cfg->ops->legacy))
-		return;
-
-	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_config));
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* new association get rid of ibss beacon skb */
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = NULL;
-
-	priv->timestamp = 0;
-
-	spin_unlock_irqrestore(&priv->lock, flags);
-
-	iwl_scan_cancel_timeout(priv, 100);
-	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
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	iwlcore_commit_rxon(priv, ctx);
-
-	iwl_set_rate(priv);
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_legacy_mac_reset_tsf);
-
-static void iwl_ht_conf(struct iwl_priv *priv,
-			struct ieee80211_vif *vif)
-{
-	struct iwl_ht_config *ht_conf = &priv->current_ht_config;
-	struct ieee80211_sta *sta;
-	struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	IWL_DEBUG_ASSOC(priv, "enter:\n");
-
-	if (!ctx->ht.enabled)
-		return;
-
-	ctx->ht.protection =
-		bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION;
-	ctx->ht.non_gf_sta_present =
-		!!(bss_conf->ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
-
-	ht_conf->single_chain_sufficient = false;
-
-	switch (vif->type) {
-	case NL80211_IFTYPE_STATION:
-		rcu_read_lock();
-		sta = ieee80211_find_sta(vif, bss_conf->bssid);
-		if (sta) {
-			struct ieee80211_sta_ht_cap *ht_cap = &sta->ht_cap;
-			int maxstreams;
-
-			maxstreams = (ht_cap->mcs.tx_params &
-				      IEEE80211_HT_MCS_TX_MAX_STREAMS_MASK)
-					>> IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
-			maxstreams += 1;
-
-			if ((ht_cap->mcs.rx_mask[1] == 0) &&
-			    (ht_cap->mcs.rx_mask[2] == 0))
-				ht_conf->single_chain_sufficient = true;
-			if (maxstreams <= 1)
-				ht_conf->single_chain_sufficient = true;
-		} else {
-			/*
-			 * If at all, this can only happen through a race
-			 * when the AP disconnects us while we're still
-			 * setting up the connection, in that case mac80211
-			 * will soon tell us about that.
-			 */
-			ht_conf->single_chain_sufficient = true;
-		}
-		rcu_read_unlock();
-		break;
-	case NL80211_IFTYPE_ADHOC:
-		ht_conf->single_chain_sufficient = true;
-		break;
-	default:
-		break;
-	}
-
-	IWL_DEBUG_ASSOC(priv, "leave\n");
-}
-
-static inline void iwl_set_no_assoc(struct iwl_priv *priv,
-				    struct ieee80211_vif *vif)
-{
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-
-	iwl_led_disassociate(priv);
-	/*
-	 * inform the ucode that there is no longer an
-	 * association and that no more packets should be
-	 * sent
-	 */
-	ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
-	ctx->staging.assoc_id = 0;
-	iwlcore_commit_rxon(priv, ctx);
-}
-
-static void iwlcore_beacon_update(struct ieee80211_hw *hw,
-				  struct ieee80211_vif *vif)
-{
-	struct iwl_priv *priv = hw->priv;
-	unsigned long flags;
-	__le64 timestamp;
-	struct sk_buff *skb = ieee80211_beacon_get(hw, vif);
-
-	if (!skb)
-		return;
-
-	IWL_DEBUG_MAC80211(priv, "enter\n");
-
-	lockdep_assert_held(&priv->mutex);
-
-	if (!priv->beacon_ctx) {
-		IWL_ERR(priv, "update beacon but no beacon context!\n");
-		dev_kfree_skb(skb);
-		return;
-	}
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	if (priv->beacon_skb)
-		dev_kfree_skb(priv->beacon_skb);
-
-	priv->beacon_skb = skb;
-
-	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);
-
-	if (!iwl_is_ready_rf(priv)) {
-		IWL_DEBUG_MAC80211(priv, "leave - RF not ready\n");
-		return;
-	}
-
-	priv->cfg->ops->legacy->post_associate(priv);
-}
-
-void iwl_legacy_mac_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;
-	struct iwl_rxon_context *ctx = iwl_rxon_ctx_from_vif(vif);
-	int ret;
-
-	if (WARN_ON(!priv->cfg->ops->legacy))
-		return;
-
-	IWL_DEBUG_MAC80211(priv, "changes = 0x%X\n", changes);
-
-	if (!iwl_is_alive(priv))
-		return;
-
-	mutex_lock(&priv->mutex);
-
-	if (changes & BSS_CHANGED_QOS) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&priv->lock, flags);
-		ctx->qos_data.qos_active = bss_conf->qos;
-		iwl_update_qos(priv, ctx);
-		spin_unlock_irqrestore(&priv->lock, flags);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		/*
-		 * the add_interface code must make sure we only ever
-		 * have a single interface that could be beaconing at
-		 * any time.
-		 */
-		if (vif->bss_conf.enable_beacon)
-			priv->beacon_ctx = ctx;
-		else
-			priv->beacon_ctx = NULL;
-	}
-
-	if (changes & BSS_CHANGED_BEACON && vif->type == NL80211_IFTYPE_AP) {
-		dev_kfree_skb(priv->beacon_skb);
-		priv->beacon_skb = ieee80211_beacon_get(hw, vif);
-	}
-
-	if (changes & BSS_CHANGED_BEACON_INT && vif->type == NL80211_IFTYPE_AP)
-		iwl_send_rxon_timing(priv, ctx);
-
-	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 (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-
-			/* currently needed in a few places */
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-		} else {
-			ctx->staging.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 (vif->type == NL80211_IFTYPE_ADHOC && changes & BSS_CHANGED_BEACON)
-		iwlcore_beacon_update(hw, vif);
-
-	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)
-			ctx->staging.flags |= RXON_FLG_SHORT_PREAMBLE_MSK;
-		else
-			ctx->staging.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))
-			ctx->staging.flags |= RXON_FLG_TGG_PROTECT_MSK;
-		else
-			ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
-		if (bss_conf->use_cts_prot)
-			ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
-		else
-			ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
-	}
-
-	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)
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates;
-		else
-			ctx->staging.ofdm_basic_rates =
-				bss_conf->basic_rates >> 4;
-			ctx->staging.cck_basic_rates =
-				bss_conf->basic_rates & 0xF;
-		 */
-	}
-
-	if (changes & BSS_CHANGED_HT) {
-		iwl_ht_conf(priv, vif);
-
-		if (priv->cfg->ops->hcmd->set_rxon_chain)
-			priv->cfg->ops->hcmd->set_rxon_chain(priv, ctx);
-	}
-
-	if (changes & BSS_CHANGED_ASSOC) {
-		IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
-		if (bss_conf->assoc) {
-			priv->timestamp = bss_conf->timestamp;
-
-			iwl_led_associate(priv);
-
-			if (!iwl_is_rfkill(priv))
-				priv->cfg->ops->legacy->post_associate(priv);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes && iwl_is_associated_ctx(ctx) && bss_conf->aid) {
-		IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
-				   changes);
-		ret = iwl_send_rxon_assoc(priv, ctx);
-		if (!ret) {
-			/* Sync active_rxon with latest change. */
-			memcpy((void *)&ctx->active,
-				&ctx->staging,
-				sizeof(struct iwl_rxon_cmd));
-		}
-	}
-
-	if (changes & BSS_CHANGED_BEACON_ENABLED) {
-		if (vif->bss_conf.enable_beacon) {
-			memcpy(ctx->staging.bssid_addr,
-			       bss_conf->bssid, ETH_ALEN);
-			memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
-			iwl_led_associate(priv);
-			priv->cfg->ops->legacy->config_ap(priv);
-		} else
-			iwl_set_no_assoc(priv, vif);
-	}
-
-	if (changes & BSS_CHANGED_IBSS) {
-		ret = priv->cfg->ops->legacy->manage_ibss_station(priv, vif,
-							bss_conf->ibss_joined);
-		if (ret)
-			IWL_ERR(priv, "failed to %s IBSS station %pM\n",
-				bss_conf->ibss_joined ? "add" : "remove",
-				bss_conf->bssid);
-	}
-
-	mutex_unlock(&priv->mutex);
-
-	IWL_DEBUG_MAC80211(priv, "leave\n");
-}
-EXPORT_SYMBOL(iwl_legacy_mac_bss_info_changed);
-
-irqreturn_t iwl_isr_legacy(int irq, void *data)
-{
-	struct iwl_priv *priv = data;
-	u32 inta, inta_mask;
-	u32 inta_fh;
-	unsigned long flags;
-	if (!priv)
-		return IRQ_NONE;
-
-	spin_lock_irqsave(&priv->lock, flags);
-
-	/* 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);
-	inta_fh = iwl_read32(priv, CSR_FH_INT_STATUS);
-
-	/* 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 && !inta_fh) {
-		IWL_DEBUG_ISR(priv,
-			"Ignore interrupt, inta == 0, inta_fh == 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;
-	}
-
-	IWL_DEBUG_ISR(priv, "ISR inta 0x%08x, enabled 0x%08x, fh 0x%08x\n",
-		      inta, inta_mask, inta_fh);
-
-	inta &= ~CSR_INT_BIT_SCD;
-
-	/* iwl_irq_tasklet() will service interrupts and re-enable them */
-	if (likely(inta || inta_fh))
-		tasklet_schedule(&priv->irq_tasklet);
-
-unplugged:
-	spin_unlock_irqrestore(&priv->lock, flags);
-	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))
-		iwl_enable_interrupts(priv);
-	spin_unlock_irqrestore(&priv->lock, flags);
-	return IRQ_NONE;
-}
-EXPORT_SYMBOL(iwl_isr_legacy);
-
-/*
- *  iwl_legacy_tx_cmd_protection: Set rts/cts. 3945 and 4965 only share this
- *  function.
- */
-void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
-			       struct ieee80211_tx_info *info,
-			       __le16 fc, __le32 *tx_flags)
-{
-	if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
-		*tx_flags |= TX_CMD_FLG_RTS_MSK;
-		*tx_flags &= ~TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-
-		if (!ieee80211_is_mgmt(fc))
-			return;
-
-		switch (fc & cpu_to_le16(IEEE80211_FCTL_STYPE)) {
-		case cpu_to_le16(IEEE80211_STYPE_AUTH):
-		case cpu_to_le16(IEEE80211_STYPE_DEAUTH):
-		case cpu_to_le16(IEEE80211_STYPE_ASSOC_REQ):
-		case cpu_to_le16(IEEE80211_STYPE_REASSOC_REQ):
-			*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-			*tx_flags |= TX_CMD_FLG_CTS_MSK;
-			break;
-		}
-	} else if (info->control.rates[0].flags &
-		   IEEE80211_TX_RC_USE_CTS_PROTECT) {
-		*tx_flags &= ~TX_CMD_FLG_RTS_MSK;
-		*tx_flags |= TX_CMD_FLG_CTS_MSK;
-		*tx_flags |= TX_CMD_FLG_FULL_TXOP_PROT_MSK;
-	}
-}
-EXPORT_SYMBOL(iwl_legacy_tx_cmd_protection);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.h linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-legacy.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,79 +0,0 @@
-/******************************************************************************
- *
- * This file is provided under a dual BSD/GPLv2 license.  When using or
- * redistributing this file, you may do so under either license.
- *
- * GPL LICENSE SUMMARY
- *
- * Copyright(c) 2008 - 2010 Intel Corporation. All rights reserved.
- *
- * 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.GPL.
- *
- * Contact Information:
- *  Intel Linux Wireless <ilw@linux.intel.com>
- * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
- *
- * BSD LICENSE
- *
- * Copyright(c) 2005 - 2010 Intel Corporation. All rights reserved.
- * 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 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.
- *****************************************************************************/
-
-#ifndef __iwl_legacy_h__
-#define __iwl_legacy_h__
-
-/* mac80211 handlers */
-int iwl_legacy_mac_config(struct ieee80211_hw *hw, u32 changed);
-void iwl_legacy_mac_reset_tsf(struct ieee80211_hw *hw);
-void iwl_legacy_mac_bss_info_changed(struct ieee80211_hw *hw,
-				     struct ieee80211_vif *vif,
-				     struct ieee80211_bss_conf *bss_conf,
-				     u32 changes);
-void iwl_legacy_tx_cmd_protection(struct iwl_priv *priv,
-				struct ieee80211_tx_info *info,
-				__le16 fc, __le32 *tx_flags);
-
-irqreturn_t iwl_isr_legacy(int irq, void *data);
-
-#endif /* __iwl_legacy_h__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-power.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-power.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-power.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-power.c	2011-05-19 00:06:34.000000000 -0400
@@ -226,8 +226,7 @@
 	else
 		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist) {
+	if (iwl_advanced_bt_coexist(priv)) {
 		if (!priv->cfg->bt_params->bt_sco_disable)
 			cmd->flags |= IWL_POWER_BT_SCO_ENA;
 		else
@@ -313,8 +312,7 @@
 	else
 		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;
 
-	if (priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist) {
+	if (iwl_advanced_bt_coexist(priv)) {
 		if (!priv->cfg->bt_params->bt_sco_disable)
 			cmd->flags |= IWL_POWER_BT_SCO_ENA;
 		else
@@ -358,8 +356,7 @@
 
 	if (priv->cfg->base_params->broken_powersave)
 		iwl_power_sleep_cam_cmd(priv, cmd);
-	else if (priv->cfg->base_params->supports_idle &&
-		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
+	else if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
 		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
 	else if (priv->cfg->ops->lib->tt_ops.lower_power_detection &&
 		 priv->cfg->ops->lib->tt_ops.tt_power_mode &&
@@ -428,7 +425,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(iwl_power_set_mode);
 
 int iwl_power_update_mode(struct iwl_priv *priv, bool force)
 {
@@ -437,7 +433,6 @@
 	iwl_power_build_cmd(priv, &cmd);
 	return iwl_power_set_mode(priv, &cmd, force);
 }
-EXPORT_SYMBOL(iwl_power_update_mode);
 
 /* initialize to default */
 void iwl_power_initialize(struct iwl_priv *priv)
@@ -451,4 +446,3 @@
 	memset(&priv->power_data.sleep_cmd, 0,
 		sizeof(priv->power_data.sleep_cmd));
 }
-EXPORT_SYMBOL(iwl_power_initialize);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 
 #include <linux/etherdevice.h>
 #include <linux/slab.h>
+#include <linux/sched.h>
 #include <net/mac80211.h>
 #include <asm/unaligned.h>
 #include "iwl-eeprom.h"
@@ -37,7 +38,15 @@
 #include "iwl-sta.h"
 #include "iwl-io.h"
 #include "iwl-helpers.h"
-/************************** RX-FUNCTIONS ****************************/
+#include "iwl-agn-calib.h"
+#include "iwl-agn.h"
+
+/******************************************************************************
+ *
+ * RX path functions
+ *
+ ******************************************************************************/
+
 /*
  * Rx theory of operation
  *
@@ -118,7 +127,6 @@
 		s = 0;
 	return s;
 }
-EXPORT_SYMBOL(iwl_rx_queue_space);
 
 /**
  * iwl_rx_queue_update_write_ptr - Update the write pointer for the RX queue
@@ -170,7 +178,6 @@
  exit_unlock:
 	spin_unlock_irqrestore(&q->lock, flags);
 }
-EXPORT_SYMBOL(iwl_rx_queue_update_write_ptr);
 
 int iwl_rx_queue_alloc(struct iwl_priv *priv)
 {
@@ -211,10 +218,105 @@
 err_bd:
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(iwl_rx_queue_alloc);
 
+/******************************************************************************
+ *
+ * Generic RX handler implementations
+ *
+ ******************************************************************************/
 
-void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
+static void iwl_rx_reply_alive(struct iwl_priv *priv,
+			       struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_alive_resp *palive;
+	struct delayed_work *pwork;
+
+	palive = &pkt->u.alive_frame;
+
+	IWL_DEBUG_INFO(priv, "Alive ucode status 0x%08X revision "
+		       "0x%01X 0x%01X\n",
+		       palive->is_valid, palive->ver_type,
+		       palive->ver_subtype);
+
+	if (palive->ver_subtype == INITIALIZE_SUBTYPE) {
+		IWL_DEBUG_INFO(priv, "Initialization Alive received.\n");
+		memcpy(&priv->card_alive_init,
+		       &pkt->u.alive_frame,
+		       sizeof(struct iwl_init_alive_resp));
+		pwork = &priv->init_alive_start;
+	} else {
+		IWL_DEBUG_INFO(priv, "Runtime Alive received.\n");
+		memcpy(&priv->card_alive, &pkt->u.alive_frame,
+		       sizeof(struct iwl_alive_resp));
+		pwork = &priv->alive_start;
+	}
+
+	/* We delay the ALIVE response by 5ms to
+	 * give the HW RF Kill time to activate... */
+	if (palive->is_valid == UCODE_VALID_OK)
+		queue_delayed_work(priv->workqueue, pwork,
+				   msecs_to_jiffies(5));
+	else {
+		IWL_WARN(priv, "%s uCode did not respond OK.\n",
+			(palive->ver_subtype == INITIALIZE_SUBTYPE) ?
+			"init" : "runtime");
+		/*
+		 * If fail to load init uCode,
+		 * let's try to load the init uCode again.
+		 * We should not get into this situation, but if it
+		 * does happen, we should not move on and loading "runtime"
+		 * without proper calibrate the device.
+		 */
+		if (palive->ver_subtype == INITIALIZE_SUBTYPE)
+			priv->ucode_type = UCODE_NONE;
+		queue_work(priv->workqueue, &priv->restart);
+	}
+}
+
+static void iwl_rx_reply_error(struct iwl_priv *priv,
+			       struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	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));
+}
+
+static void iwl_rx_csa(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_csa_notification *csa = &(pkt->u.csa_notif);
+	/*
+	 * MULTI-FIXME
+	 * See iwl_mac_channel_switch.
+	 */
+	struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
+	struct iwl_rxon_cmd *rxon = (void *)&ctx->active;
+
+	if (priv->switch_rxon.switch_in_progress) {
+		if (!le32_to_cpu(csa->status) &&
+		    (csa->channel == priv->switch_rxon.channel)) {
+			rxon->channel = csa->channel;
+			ctx->staging.channel = csa->channel;
+			IWL_DEBUG_11H(priv, "CSA notif: channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_chswitch_done(priv, true);
+		} else {
+			IWL_ERR(priv, "CSA notif (fail) : channel %d\n",
+			      le16_to_cpu(csa->channel));
+			iwl_chswitch_done(priv, false);
+		}
+	}
+}
+
+
+static void iwl_rx_spectrum_measure_notif(struct iwl_priv *priv,
 					  struct iwl_rx_mem_buffer *rxb)
 {
 	struct iwl_rx_packet *pkt = rxb_addr(rxb);
@@ -229,48 +331,494 @@
 	memcpy(&priv->measure_report, report, sizeof(*report));
 	priv->measurement_status |= MEASUREMENT_READY;
 }
-EXPORT_SYMBOL(iwl_rx_spectrum_measure_notif);
 
-void iwl_recover_from_statistics(struct iwl_priv *priv,
-				struct iwl_rx_packet *pkt)
+static void iwl_rx_pm_sleep_notif(struct iwl_priv *priv,
+				  struct iwl_rx_mem_buffer *rxb)
+{
+#ifdef CONFIG_IWLWIFI_DEBUG
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	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
+}
+
+static void iwl_rx_pm_debug_statistics_notif(struct iwl_priv *priv,
+					     struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
+	IWL_DEBUG_RADIO(priv, "Dumping %d bytes of unhandled "
+			"notification for %s:\n", len,
+			get_cmd_string(pkt->hdr.cmd));
+	iwl_print_hex_dump(priv, IWL_DL_RADIO, pkt->u.raw, len);
+}
+
+static void iwl_rx_beacon_notif(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwlagn_beacon_notif *beacon = (void *)pkt->u.raw;
+#ifdef CONFIG_IWLWIFI_DEBUG
+	u16 status = le16_to_cpu(beacon->beacon_notify_hdr.status.status);
+	u8 rate = iwl_hw_get_rate(beacon->beacon_notify_hdr.rate_n_flags);
+
+	IWL_DEBUG_RX(priv, "beacon status %#x, retries:%d ibssmgr:%d "
+		"tsf:0x%.8x%.8x rate:%d\n",
+		status & TX_STATUS_MSK,
+		beacon->beacon_notify_hdr.failure_frame,
+		le32_to_cpu(beacon->ibss_mgr_status),
+		le32_to_cpu(beacon->high_tsf),
+		le32_to_cpu(beacon->low_tsf), rate);
+#endif
+
+	priv->ibss_manager = le32_to_cpu(beacon->ibss_mgr_status);
+
+	if (!test_bit(STATUS_EXIT_PENDING, &priv->status))
+		queue_work(priv->workqueue, &priv->beacon_update);
+}
+
+/* the threshold ratio of actual_ack_cnt to expected_ack_cnt in percent */
+#define ACK_CNT_RATIO (50)
+#define BA_TIMEOUT_CNT (5)
+#define BA_TIMEOUT_MAX (16)
+
+/**
+ * iwl_good_ack_health - checks for ACK count ratios, BA timeout retries.
+ *
+ * When the ACK count ratio is low and aggregated BA timeout retries exceeding
+ * the BA_TIMEOUT_MAX, reload firmware and bring system back to normal
+ * operation state.
+ */
+static bool iwl_good_ack_health(struct iwl_priv *priv, struct iwl_rx_packet *pkt)
+{
+	int actual_delta, expected_delta, ba_timeout_delta;
+	struct statistics_tx *cur, *old;
+
+	if (priv->_agn.agg_tids_count)
+		return true;
+
+	if (iwl_bt_statistics(priv)) {
+		cur = &pkt->u.stats_bt.tx;
+		old = &priv->_agn.statistics_bt.tx;
+	} else {
+		cur = &pkt->u.stats.tx;
+		old = &priv->_agn.statistics.tx;
+	}
+
+	actual_delta = le32_to_cpu(cur->actual_ack_cnt) -
+		       le32_to_cpu(old->actual_ack_cnt);
+	expected_delta = le32_to_cpu(cur->expected_ack_cnt) -
+			 le32_to_cpu(old->expected_ack_cnt);
+
+	/* Values should not be negative, but we do not trust the firmware */
+	if (actual_delta <= 0 || expected_delta <= 0)
+		return true;
+
+	ba_timeout_delta = le32_to_cpu(cur->agg.ba_timeout) -
+			   le32_to_cpu(old->agg.ba_timeout);
+
+	if ((actual_delta * 100 / expected_delta) < ACK_CNT_RATIO &&
+	    ba_timeout_delta > BA_TIMEOUT_CNT) {
+		IWL_DEBUG_RADIO(priv, "deltas: actual %d expected %d ba_timeout %d\n",
+				actual_delta, expected_delta, ba_timeout_delta);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		/*
+		 * This is ifdef'ed on DEBUGFS because otherwise the
+		 * statistics aren't available. If DEBUGFS is set but
+		 * DEBUG is not, these will just compile out.
+		 */
+		IWL_DEBUG_RADIO(priv, "rx_detected_cnt delta %d\n",
+				priv->_agn.delta_statistics.tx.rx_detected_cnt);
+		IWL_DEBUG_RADIO(priv,
+				"ack_or_ba_timeout_collision delta %d\n",
+				priv->_agn.delta_statistics.tx.ack_or_ba_timeout_collision);
+#endif
+
+		if (ba_timeout_delta >= BA_TIMEOUT_MAX)
+			return false;
+	}
+
+	return true;
+}
+
+/**
+ * iwl_good_plcp_health - checks for plcp error.
+ *
+ * When the plcp error is exceeding the thresholds, reset the radio
+ * to improve the throughput.
+ */
+static bool iwl_good_plcp_health(struct iwl_priv *priv,
+				 struct iwl_rx_packet *pkt, unsigned int msecs)
+{
+	int delta;
+	int threshold = priv->cfg->base_params->plcp_delta_threshold;
+
+	if (threshold == IWL_MAX_PLCP_ERR_THRESHOLD_DISABLE) {
+		IWL_DEBUG_RADIO(priv, "plcp_err check disabled\n");
+		return true;
+	}
+
+	if (iwl_bt_statistics(priv)) {
+		struct statistics_rx_bt *cur, *old;
+
+		cur = &pkt->u.stats_bt.rx;
+		old = &priv->_agn.statistics_bt.rx;
+
+		delta = le32_to_cpu(cur->ofdm.plcp_err) -
+			le32_to_cpu(old->ofdm.plcp_err) +
+			le32_to_cpu(cur->ofdm_ht.plcp_err) -
+			le32_to_cpu(old->ofdm_ht.plcp_err);
+	} else {
+		struct statistics_rx *cur, *old;
+
+		cur = &pkt->u.stats.rx;
+		old = &priv->_agn.statistics.rx;
+
+		delta = le32_to_cpu(cur->ofdm.plcp_err) -
+			le32_to_cpu(old->ofdm.plcp_err) +
+			le32_to_cpu(cur->ofdm_ht.plcp_err) -
+			le32_to_cpu(old->ofdm_ht.plcp_err);
+	}
+
+	/* Can be negative if firmware reseted statistics */
+	if (delta <= 0)
+		return true;
+
+	if ((delta * 100 / msecs) > threshold) {
+		IWL_DEBUG_RADIO(priv,
+				"plcp health threshold %u delta %d msecs %u\n",
+				threshold, delta, msecs);
+		return false;
+	}
+
+	return true;
+}
+
+static void iwl_recover_from_statistics(struct iwl_priv *priv,
+					struct iwl_rx_packet *pkt)
 {
+	const struct iwl_mod_params *mod_params = priv->cfg->mod_params;
+	unsigned int msecs;
+	unsigned long stamp;
+
 	if (test_bit(STATUS_EXIT_PENDING, &priv->status))
 		return;
-	if (iwl_is_any_associated(priv)) {
-		if (priv->cfg->ops->lib->check_ack_health) {
-			if (!priv->cfg->ops->lib->check_ack_health(
-			    priv, pkt)) {
-				/*
-				 * low ack count detected
-				 * restart Firmware
-				 */
-				IWL_ERR(priv, "low ack count detected, "
-					"restart firmware\n");
-				if (!iwl_force_reset(priv, IWL_FW_RESET, false))
-					return;
-			}
+
+	stamp = jiffies;
+	msecs = jiffies_to_msecs(stamp - priv->rx_statistics_jiffies);
+
+	/* Only gather statistics and update time stamp when not associated */
+	if (!iwl_is_any_associated(priv))
+		goto out;
+
+	/* Do not check/recover when do not have enough statistics data */
+	if (msecs < 99)
+		return;
+
+	if (mod_params->ack_check && !iwl_good_ack_health(priv, pkt)) {
+		IWL_ERR(priv, "low ack count detected, restart firmware\n");
+		if (!iwl_force_reset(priv, IWL_FW_RESET, false))
+			return;
+	}
+
+	if (mod_params->plcp_check && !iwl_good_plcp_health(priv, pkt, msecs))
+		iwl_force_reset(priv, IWL_RF_RESET, false);
+
+out:
+	if (iwl_bt_statistics(priv))
+		memcpy(&priv->_agn.statistics_bt, &pkt->u.stats_bt,
+			sizeof(priv->_agn.statistics_bt));
+	else
+		memcpy(&priv->_agn.statistics, &pkt->u.stats,
+			sizeof(priv->_agn.statistics));
+
+	priv->rx_statistics_jiffies = stamp;
+}
+
+/* Calculate noise level, based on measurements during network silence just
+ *   before arriving beacon.  This measurement can be done only if we know
+ *   exactly when to expect beacons, therefore only when we're associated. */
+static void iwl_rx_calc_noise(struct iwl_priv *priv)
+{
+	struct statistics_rx_non_phy *rx_info;
+	int num_active_rx = 0;
+	int total_silence = 0;
+	int bcn_silence_a, bcn_silence_b, bcn_silence_c;
+	int last_rx_noise;
+
+	if (iwl_bt_statistics(priv))
+		rx_info = &(priv->_agn.statistics_bt.rx.general.common);
+	else
+		rx_info = &(priv->_agn.statistics.rx.general);
+	bcn_silence_a =
+		le32_to_cpu(rx_info->beacon_silence_rssi_a) & IN_BAND_FILTER;
+	bcn_silence_b =
+		le32_to_cpu(rx_info->beacon_silence_rssi_b) & IN_BAND_FILTER;
+	bcn_silence_c =
+		le32_to_cpu(rx_info->beacon_silence_rssi_c) & IN_BAND_FILTER;
+
+	if (bcn_silence_a) {
+		total_silence += bcn_silence_a;
+		num_active_rx++;
+	}
+	if (bcn_silence_b) {
+		total_silence += bcn_silence_b;
+		num_active_rx++;
+	}
+	if (bcn_silence_c) {
+		total_silence += bcn_silence_c;
+		num_active_rx++;
+	}
+
+	/* Average among active antennas */
+	if (num_active_rx)
+		last_rx_noise = (total_silence / num_active_rx) - 107;
+	else
+		last_rx_noise = IWL_NOISE_MEAS_NOT_AVAILABLE;
+
+	IWL_DEBUG_CALIB(priv, "inband silence a %u, b %u, c %u, dBm %d\n",
+			bcn_silence_a, bcn_silence_b, bcn_silence_c,
+			last_rx_noise);
+}
+
+/*
+ *  based on the assumption of all statistics counter are in DWORD
+ *  FIXME: This function is for debugging, do not deal with
+ *  the case of counters roll-over.
+ */
+static void iwl_accumulative_statistics(struct iwl_priv *priv,
+					__le32 *stats)
+{
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+	int i, size;
+	__le32 *prev_stats;
+	u32 *accum_stats;
+	u32 *delta, *max_delta;
+	struct statistics_general_common *general, *accum_general;
+	struct statistics_tx *tx, *accum_tx;
+
+	if (iwl_bt_statistics(priv)) {
+		prev_stats = (__le32 *)&priv->_agn.statistics_bt;
+		accum_stats = (u32 *)&priv->_agn.accum_statistics_bt;
+		size = sizeof(struct iwl_bt_notif_statistics);
+		general = &priv->_agn.statistics_bt.general.common;
+		accum_general = &priv->_agn.accum_statistics_bt.general.common;
+		tx = &priv->_agn.statistics_bt.tx;
+		accum_tx = &priv->_agn.accum_statistics_bt.tx;
+		delta = (u32 *)&priv->_agn.delta_statistics_bt;
+		max_delta = (u32 *)&priv->_agn.max_delta_bt;
+	} else {
+		prev_stats = (__le32 *)&priv->_agn.statistics;
+		accum_stats = (u32 *)&priv->_agn.accum_statistics;
+		size = sizeof(struct iwl_notif_statistics);
+		general = &priv->_agn.statistics.general.common;
+		accum_general = &priv->_agn.accum_statistics.general.common;
+		tx = &priv->_agn.statistics.tx;
+		accum_tx = &priv->_agn.accum_statistics.tx;
+		delta = (u32 *)&priv->_agn.delta_statistics;
+		max_delta = (u32 *)&priv->_agn.max_delta;
+	}
+	for (i = sizeof(__le32); i < size;
+	     i += sizeof(__le32), stats++, prev_stats++, delta++,
+	     max_delta++, accum_stats++) {
+		if (le32_to_cpu(*stats) > le32_to_cpu(*prev_stats)) {
+			*delta = (le32_to_cpu(*stats) -
+				le32_to_cpu(*prev_stats));
+			*accum_stats += *delta;
+			if (*delta > *max_delta)
+				*max_delta = *delta;
 		}
-		if (priv->cfg->ops->lib->check_plcp_health) {
-			if (!priv->cfg->ops->lib->check_plcp_health(
-			    priv, pkt)) {
-				/*
-				 * high plcp error detected
-				 * reset Radio
-				 */
-				iwl_force_reset(priv, IWL_RF_RESET, false);
-			}
+	}
+
+	/* reset accumulative statistics for "no-counter" type statistics */
+	accum_general->temperature = general->temperature;
+	accum_general->temperature_m = general->temperature_m;
+	accum_general->ttl_timestamp = general->ttl_timestamp;
+	accum_tx->tx_power.ant_a = tx->tx_power.ant_a;
+	accum_tx->tx_power.ant_b = tx->tx_power.ant_b;
+	accum_tx->tx_power.ant_c = tx->tx_power.ant_c;
+#endif
+}
+
+static void iwl_rx_statistics(struct iwl_priv *priv,
+			      struct iwl_rx_mem_buffer *rxb)
+{
+	const int reg_recalib_period = 60;
+	int change;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (iwl_bt_statistics(priv)) {
+		IWL_DEBUG_RX(priv,
+			     "Statistics notification received (%d vs %d).\n",
+			     (int)sizeof(struct iwl_bt_notif_statistics),
+			     le32_to_cpu(pkt->len_n_flags) &
+			     FH_RSCSR_FRAME_SIZE_MSK);
+
+		change = ((priv->_agn.statistics_bt.general.common.temperature !=
+			   pkt->u.stats_bt.general.common.temperature) ||
+			   ((priv->_agn.statistics_bt.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+			   (pkt->u.stats_bt.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+
+		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats_bt);
+	} else {
+		IWL_DEBUG_RX(priv,
+			     "Statistics notification received (%d vs %d).\n",
+			     (int)sizeof(struct iwl_notif_statistics),
+			     le32_to_cpu(pkt->len_n_flags) &
+			     FH_RSCSR_FRAME_SIZE_MSK);
+
+		change = ((priv->_agn.statistics.general.common.temperature !=
+			   pkt->u.stats.general.common.temperature) ||
+			   ((priv->_agn.statistics.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK) !=
+			   (pkt->u.stats.flag &
+			   STATISTICS_REPLY_FLG_HT40_MODE_MSK)));
+
+		iwl_accumulative_statistics(priv, (__le32 *)&pkt->u.stats);
+	}
+
+	iwl_recover_from_statistics(priv, pkt);
+
+	set_bit(STATUS_STATISTICS, &priv->status);
+
+	/* Reschedule the statistics timer to occur in
+	 * reg_recalib_period seconds to ensure we get a
+	 * thermal update even if the uCode doesn't give
+	 * us one */
+	mod_timer(&priv->statistics_periodic, jiffies +
+		  msecs_to_jiffies(reg_recalib_period * 1000));
+
+	if (unlikely(!test_bit(STATUS_SCANNING, &priv->status)) &&
+	    (pkt->hdr.cmd == STATISTICS_NOTIFICATION)) {
+		iwl_rx_calc_noise(priv);
+		queue_work(priv->workqueue, &priv->run_time_calib_work);
+	}
+	if (priv->cfg->ops->lib->temp_ops.temperature && change)
+		priv->cfg->ops->lib->temp_ops.temperature(priv);
+}
+
+static void iwl_rx_reply_statistics(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	if (le32_to_cpu(pkt->u.stats.flag) & UCODE_STATISTICS_CLEAR_MSK) {
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+		memset(&priv->_agn.accum_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.delta_statistics, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.max_delta, 0,
+			sizeof(struct iwl_notif_statistics));
+		memset(&priv->_agn.accum_statistics_bt, 0,
+			sizeof(struct iwl_bt_notif_statistics));
+		memset(&priv->_agn.delta_statistics_bt, 0,
+			sizeof(struct iwl_bt_notif_statistics));
+		memset(&priv->_agn.max_delta_bt, 0,
+			sizeof(struct iwl_bt_notif_statistics));
+#endif
+		IWL_DEBUG_RX(priv, "Statistics have been cleared\n");
+	}
+	iwl_rx_statistics(priv, rxb);
+}
+
+/* Handle notification from uCode that card's power state is changing
+ * due to software, hardware, or critical temperature RFKILL */
+static void iwl_rx_card_state_notif(struct iwl_priv *priv,
+				    struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	u32 flags = le32_to_cpu(pkt->u.card_state_notif.flags);
+	unsigned long status = priv->status;
+
+	IWL_DEBUG_RF_KILL(priv, "Card state received: HW:%s SW:%s CT:%s\n",
+			  (flags & HW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & SW_CARD_DISABLED) ? "Kill" : "On",
+			  (flags & CT_CARD_DISABLED) ?
+			  "Reached" : "Not reached");
+
+	if (flags & (SW_CARD_DISABLED | HW_CARD_DISABLED |
+		     CT_CARD_DISABLED)) {
+
+		iwl_write32(priv, CSR_UCODE_DRV_GP1_SET,
+			    CSR_UCODE_DRV_GP1_BIT_CMD_BLOCKED);
+
+		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);
+			iwl_write_direct32(priv, HBUS_TARG_MBX_C,
+					HBUS_TARG_MBX_C_REG_BIT_CMD_BLOCKED);
 		}
+		if (flags & CT_CARD_DISABLED)
+			iwl_tt_enter_ct_kill(priv);
 	}
+	if (!(flags & CT_CARD_DISABLED))
+		iwl_tt_exit_ct_kill(priv);
+
+	if (flags & HW_CARD_DISABLED)
+		set_bit(STATUS_RF_KILL_HW, &priv->status);
+	else
+		clear_bit(STATUS_RF_KILL_HW, &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)))
+		wiphy_rfkill_set_hw_state(priv->hw->wiphy,
+			test_bit(STATUS_RF_KILL_HW, &priv->status));
+	else
+		wake_up_interruptible(&priv->wait_command_queue);
+}
+
+static void iwl_rx_missed_beacon_notif(struct iwl_priv *priv,
+				       struct iwl_rx_mem_buffer *rxb)
+
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_missed_beacon_notif *missed_beacon;
+
+	missed_beacon = &pkt->u.missed_beacon;
+	if (le32_to_cpu(missed_beacon->consecutive_missed_beacons) >
+	    priv->missed_beacon_threshold) {
+		IWL_DEBUG_CALIB(priv,
+		    "missed bcn cnsq %d totl %d rcd %d expctd %d\n",
+		    le32_to_cpu(missed_beacon->consecutive_missed_beacons),
+		    le32_to_cpu(missed_beacon->total_missed_becons),
+		    le32_to_cpu(missed_beacon->num_recvd_beacons),
+		    le32_to_cpu(missed_beacon->num_expected_beacons));
+		if (!test_bit(STATUS_SCANNING, &priv->status))
+			iwl_init_sensitivity(priv);
+	}
+}
+
+/* Cache phy data (Rx signal strength, etc) for HT frame (REPLY_RX_PHY_CMD).
+ * This will be used later in iwl_rx_reply_rx() for REPLY_RX_MPDU_CMD. */
+static void iwl_rx_reply_rx_phy(struct iwl_priv *priv,
+				struct iwl_rx_mem_buffer *rxb)
+{
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+
+	priv->_agn.last_phy_res_valid = true;
+	memcpy(&priv->_agn.last_phy_res, pkt->u.raw,
+	       sizeof(struct iwl_rx_phy_res));
 }
-EXPORT_SYMBOL(iwl_recover_from_statistics);
 
 /*
  * returns non-zero if packet should be dropped
  */
-int iwl_set_decrypted_flag(struct iwl_priv *priv,
-			   struct ieee80211_hdr *hdr,
-			   u32 decrypt_res,
-			   struct ieee80211_rx_status *stats)
+static int iwl_set_decrypted_flag(struct iwl_priv *priv,
+				  struct ieee80211_hdr *hdr,
+				  u32 decrypt_res,
+				  struct ieee80211_rx_status *stats)
 {
 	u16 fc = le16_to_cpu(hdr->frame_control);
 
@@ -315,4 +863,264 @@
 	}
 	return 0;
 }
-EXPORT_SYMBOL(iwl_set_decrypted_flag);
+
+static void iwl_pass_packet_to_mac80211(struct iwl_priv *priv,
+					struct ieee80211_hdr *hdr,
+					u16 len,
+					u32 ampdu_status,
+					struct iwl_rx_mem_buffer *rxb,
+					struct ieee80211_rx_status *stats)
+{
+	struct sk_buff *skb;
+	__le16 fc = hdr->frame_control;
+
+	/* We only process data packets if the interface is open */
+	if (unlikely(!priv->is_open)) {
+		IWL_DEBUG_DROP_LIMIT(priv,
+		    "Dropping packet while interface is not open.\n");
+		return;
+	}
+
+	/* In case of HW accelerated crypto and bad decryption, drop */
+	if (!priv->cfg->mod_params->sw_crypto &&
+	    iwl_set_decrypted_flag(priv, hdr, ampdu_status, stats))
+		return;
+
+	skb = dev_alloc_skb(128);
+	if (!skb) {
+		IWL_ERR(priv, "dev_alloc_skb failed\n");
+		return;
+	}
+
+	skb_add_rx_frag(skb, 0, rxb->page, (void *)hdr - rxb_addr(rxb), len);
+
+	iwl_update_stats(priv, false, fc, len);
+	memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
+
+	ieee80211_rx(priv->hw, skb);
+	priv->alloc_rxb_page--;
+	rxb->page = NULL;
+}
+
+static u32 iwl_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
+{
+	u32 decrypt_out = 0;
+
+	if ((decrypt_in & RX_RES_STATUS_STATION_FOUND) ==
+					RX_RES_STATUS_STATION_FOUND)
+		decrypt_out |= (RX_RES_STATUS_STATION_FOUND |
+				RX_RES_STATUS_NO_STATION_INFO_MISMATCH);
+
+	decrypt_out |= (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK);
+
+	/* packet was not encrypted */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_NONE)
+		return decrypt_out;
+
+	/* packet was encrypted with unknown alg */
+	if ((decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) ==
+					RX_RES_STATUS_SEC_TYPE_ERR)
+		return decrypt_out;
+
+	/* decryption was not done in HW */
+	if ((decrypt_in & RX_MPDU_RES_STATUS_DEC_DONE_MSK) !=
+					RX_MPDU_RES_STATUS_DEC_DONE_MSK)
+		return decrypt_out;
+
+	switch (decrypt_in & RX_RES_STATUS_SEC_TYPE_MSK) {
+
+	case RX_RES_STATUS_SEC_TYPE_CCMP:
+		/* alg is CCM: check MIC only */
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_MIC_OK))
+			/* Bad MIC */
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+
+		break;
+
+	case RX_RES_STATUS_SEC_TYPE_TKIP:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_TTAK_OK)) {
+			/* Bad TTAK */
+			decrypt_out |= RX_RES_STATUS_BAD_KEY_TTAK;
+			break;
+		}
+		/* fall through if TTAK OK */
+	default:
+		if (!(decrypt_in & RX_MPDU_RES_STATUS_ICV_OK))
+			decrypt_out |= RX_RES_STATUS_BAD_ICV_MIC;
+		else
+			decrypt_out |= RX_RES_STATUS_DECRYPT_OK;
+		break;
+	}
+
+	IWL_DEBUG_RX(priv, "decrypt_in:0x%x  decrypt_out = 0x%x\n",
+					decrypt_in, decrypt_out);
+
+	return decrypt_out;
+}
+
+/* Called for REPLY_RX (legacy ABG frames), or
+ * REPLY_RX_MPDU_CMD (HT high-throughput N frames). */
+static void iwl_rx_reply_rx(struct iwl_priv *priv,
+			    struct iwl_rx_mem_buffer *rxb)
+{
+	struct ieee80211_hdr *header;
+	struct ieee80211_rx_status rx_status;
+	struct iwl_rx_packet *pkt = rxb_addr(rxb);
+	struct iwl_rx_phy_res *phy_res;
+	__le32 rx_pkt_status;
+	struct iwl_rx_mpdu_res_start *amsdu;
+	u32 len;
+	u32 ampdu_status;
+	u32 rate_n_flags;
+
+	/**
+	 * REPLY_RX and REPLY_RX_MPDU_CMD are handled differently.
+	 *	REPLY_RX: physical layer info is in this buffer
+	 *	REPLY_RX_MPDU_CMD: physical layer info was sent in separate
+	 *		command and cached in priv->last_phy_res
+	 *
+	 * Here we set up local variables depending on which command is
+	 * received.
+	 */
+	if (pkt->hdr.cmd == REPLY_RX) {
+		phy_res = (struct iwl_rx_phy_res *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*phy_res)
+				+ phy_res->cfg_phy_cnt);
+
+		len = le16_to_cpu(phy_res->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*phy_res) +
+				phy_res->cfg_phy_cnt + len);
+		ampdu_status = le32_to_cpu(rx_pkt_status);
+	} else {
+		if (!priv->_agn.last_phy_res_valid) {
+			IWL_ERR(priv, "MPDU frame without cached PHY data\n");
+			return;
+		}
+		phy_res = &priv->_agn.last_phy_res;
+		amsdu = (struct iwl_rx_mpdu_res_start *)pkt->u.raw;
+		header = (struct ieee80211_hdr *)(pkt->u.raw + sizeof(*amsdu));
+		len = le16_to_cpu(amsdu->byte_count);
+		rx_pkt_status = *(__le32 *)(pkt->u.raw + sizeof(*amsdu) + len);
+		ampdu_status = iwl_translate_rx_status(priv,
+						le32_to_cpu(rx_pkt_status));
+	}
+
+	if ((unlikely(phy_res->cfg_phy_cnt > 20))) {
+		IWL_DEBUG_DROP(priv, "dsp size out of range [0,20]: %d/n",
+				phy_res->cfg_phy_cnt);
+		return;
+	}
+
+	if (!(rx_pkt_status & RX_RES_STATUS_NO_CRC32_ERROR) ||
+	    !(rx_pkt_status & RX_RES_STATUS_NO_RXE_OVERFLOW)) {
+		IWL_DEBUG_RX(priv, "Bad CRC or FIFO: 0x%08X.\n",
+				le32_to_cpu(rx_pkt_status));
+		return;
+	}
+
+	/* This will be used in several places later */
+	rate_n_flags = le32_to_cpu(phy_res->rate_n_flags);
+
+	/* rx_status carries information about the packet to mac80211 */
+	rx_status.mactime = le64_to_cpu(phy_res->timestamp);
+	rx_status.band = (phy_res->phy_flags & RX_RES_PHY_FLAGS_BAND_24_MSK) ?
+				IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	rx_status.freq =
+		ieee80211_channel_to_frequency(le16_to_cpu(phy_res->channel),
+					       rx_status.band);
+	rx_status.rate_idx =
+		iwlagn_hwrate_to_mac80211_idx(rate_n_flags, rx_status.band);
+	rx_status.flag = 0;
+
+	/* TSF isn't reliable. In order to allow smooth user experience,
+	 * this W/A doesn't propagate it to the mac80211 */
+	/*rx_status.flag |= RX_FLAG_MACTIME_MPDU;*/
+
+	priv->ucode_beacon_time = le32_to_cpu(phy_res->beacon_time_stamp);
+
+	/* Find max signal strength (dBm) among 3 antenna/receiver chains */
+	rx_status.signal = priv->cfg->ops->utils->calc_rssi(priv, phy_res);
+
+	iwl_dbg_log_rx_data_frame(priv, len, header);
+	IWL_DEBUG_STATS_LIMIT(priv, "Rssi %d, TSF %llu\n",
+		rx_status.signal, (unsigned long long)rx_status.mactime);
+
+	/*
+	 * "antenna number"
+	 *
+	 * It seems that the antenna field in the phy flags value
+	 * is actually a bit field. This is undefined by radiotap,
+	 * it wants an actual antenna number but I always get "7"
+	 * for most legacy frames I receive indicating that the
+	 * same frame was received on all three RX chains.
+	 *
+	 * I think this field should be removed in favor of a
+	 * new 802.11n radiotap field "RX chains" that is defined
+	 * as a bitmask.
+	 */
+	rx_status.antenna =
+		(le16_to_cpu(phy_res->phy_flags) & RX_RES_PHY_FLAGS_ANTENNA_MSK)
+		>> RX_RES_PHY_FLAGS_ANTENNA_POS;
+
+	/* set the preamble flag if appropriate */
+	if (phy_res->phy_flags & RX_RES_PHY_FLAGS_SHORT_PREAMBLE_MSK)
+		rx_status.flag |= RX_FLAG_SHORTPRE;
+
+	/* Set up the HT phy flags */
+	if (rate_n_flags & RATE_MCS_HT_MSK)
+		rx_status.flag |= RX_FLAG_HT;
+	if (rate_n_flags & RATE_MCS_HT40_MSK)
+		rx_status.flag |= RX_FLAG_40MHZ;
+	if (rate_n_flags & RATE_MCS_SGI_MSK)
+		rx_status.flag |= RX_FLAG_SHORT_GI;
+
+	iwl_pass_packet_to_mac80211(priv, header, len, ampdu_status,
+				    rxb, &rx_status);
+}
+
+/**
+ * iwl_setup_rx_handlers - Initialize Rx handler callbacks
+ *
+ * Setup the RX handlers for each of the reply types sent from the uCode
+ * to the host.
+ */
+void iwl_setup_rx_handlers(struct iwl_priv *priv)
+{
+	void (**handlers)(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb);
+
+	handlers = priv->rx_handlers;
+
+	handlers[REPLY_ALIVE]			= iwl_rx_reply_alive;
+	handlers[REPLY_ERROR]			= iwl_rx_reply_error;
+	handlers[CHANNEL_SWITCH_NOTIFICATION]	= iwl_rx_csa;
+	handlers[SPECTRUM_MEASURE_NOTIFICATION]	= iwl_rx_spectrum_measure_notif;
+	handlers[PM_SLEEP_NOTIFICATION]		= iwl_rx_pm_sleep_notif;
+	handlers[PM_DEBUG_STATISTIC_NOTIFIC]	= iwl_rx_pm_debug_statistics_notif;
+	handlers[BEACON_NOTIFICATION]		= iwl_rx_beacon_notif;
+
+	/*
+	 * The same handler is used for both the REPLY to a discrete
+	 * statistics request from the host as well as for the periodic
+	 * statistics notifications (after received beacons) from the uCode.
+	 */
+	handlers[REPLY_STATISTICS_CMD]		= iwl_rx_reply_statistics;
+	handlers[STATISTICS_NOTIFICATION]	= iwl_rx_statistics;
+
+	iwl_setup_rx_scan_handlers(priv);
+
+	handlers[CARD_STATE_NOTIFICATION]	= iwl_rx_card_state_notif;
+	handlers[MISSED_BEACONS_NOTIFICATION]	= iwl_rx_missed_beacon_notif;
+
+	/* Rx handlers */
+	handlers[REPLY_RX_PHY_CMD]		= iwl_rx_reply_rx_phy;
+	handlers[REPLY_RX_MPDU_CMD]		= iwl_rx_reply_rx;
+
+	/* block ack */
+	handlers[REPLY_COMPRESSED_BA]		= iwlagn_rx_reply_compressed_ba;
+
+	/* Set up hardware specific Rx handlers */
+	priv->cfg->ops->lib->rx_handler_setup(priv);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -101,7 +101,7 @@
 		ieee80211_scan_completed(priv->hw, aborted);
 	}
 
-	priv->is_internal_short_scan = false;
+	priv->scan_type = IWL_SCAN_NORMAL;
 	priv->scan_vif = NULL;
 	priv->scan_request = NULL;
 }
@@ -143,7 +143,7 @@
 		IWL_DEBUG_SCAN(priv, "Send scan abort failed %d\n", ret);
 		iwl_force_scan_end(priv);
 	} else
-		IWL_DEBUG_SCAN(priv, "Sucessfully send scan abort\n");
+		IWL_DEBUG_SCAN(priv, "Successfully send scan abort\n");
 }
 
 /**
@@ -155,7 +155,6 @@
 	queue_work(priv->workqueue, &priv->abort_scan);
 	return 0;
 }
-EXPORT_SYMBOL(iwl_scan_cancel);
 
 /**
  * iwl_scan_cancel_timeout - Cancel any currently executing HW scan
@@ -180,7 +179,6 @@
 
 	return test_bit(STATUS_SCAN_HW, &priv->status);
 }
-EXPORT_SYMBOL(iwl_scan_cancel_timeout);
 
 /* Service response to REPLY_SCAN_CMD (0x80) */
 static void iwl_rx_reply_scan(struct iwl_priv *priv,
@@ -257,8 +255,7 @@
 	queue_work(priv->workqueue, &priv->scan_completed);
 
 	if (priv->iw_mode != NL80211_IFTYPE_ADHOC &&
-	    priv->cfg->bt_params &&
-	    priv->cfg->bt_params->advanced_bt_coexist &&
+	    iwl_advanced_bt_coexist(priv) &&
 	    priv->bt_status != scan_notif->bt_status) {
 		if (scan_notif->bt_status) {
 			/* BT on */
@@ -289,7 +286,6 @@
 	priv->rx_handlers[SCAN_COMPLETE_NOTIFICATION] =
 					iwl_rx_scan_complete_notif;
 }
-EXPORT_SYMBOL(iwl_setup_rx_scan_handlers);
 
 inline u16 iwl_get_active_dwell_time(struct iwl_priv *priv,
 				     enum ieee80211_band band,
@@ -302,7 +298,6 @@
 		return IWL_ACTIVE_DWELL_TIME_24 +
 			IWL_ACTIVE_DWELL_FACTOR_24GHZ * (n_probes + 1);
 }
-EXPORT_SYMBOL(iwl_get_active_dwell_time);
 
 u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
 			       enum ieee80211_band band,
@@ -334,7 +329,6 @@
 
 	return passive;
 }
-EXPORT_SYMBOL(iwl_get_passive_dwell_time);
 
 void iwl_init_scan_params(struct iwl_priv *priv)
 {
@@ -344,12 +338,11 @@
 	if (!priv->scan_tx_ant[IEEE80211_BAND_2GHZ])
 		priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
 }
-EXPORT_SYMBOL(iwl_init_scan_params);
 
-static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
-					  struct ieee80211_vif *vif,
-					  bool internal,
-					  enum ieee80211_band band)
+int __must_check iwl_scan_initiate(struct iwl_priv *priv,
+				   struct ieee80211_vif *vif,
+				   enum iwl_scan_type scan_type,
+				   enum ieee80211_band band)
 {
 	int ret;
 
@@ -377,17 +370,19 @@
 	}
 
 	IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
-			internal ? "internal short " : "");
+			scan_type == IWL_SCAN_NORMAL ? "" :
+			scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " :
+			"internal short ");
 
 	set_bit(STATUS_SCANNING, &priv->status);
-	priv->is_internal_short_scan = internal;
+	priv->scan_type = scan_type;
 	priv->scan_start = jiffies;
 	priv->scan_band = band;
 
 	ret = priv->cfg->ops->utils->request_scan(priv, vif);
 	if (ret) {
 		clear_bit(STATUS_SCANNING, &priv->status);
-		priv->is_internal_short_scan = false;
+		priv->scan_type = IWL_SCAN_NORMAL;
 		return ret;
 	}
 
@@ -412,7 +407,7 @@
 	mutex_lock(&priv->mutex);
 
 	if (test_bit(STATUS_SCANNING, &priv->status) &&
-	    !priv->is_internal_short_scan) {
+	    priv->scan_type != IWL_SCAN_NORMAL) {
 		IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
 		ret = -EAGAIN;
 		goto out_unlock;
@@ -426,11 +421,11 @@
 	 * If an internal scan is in progress, just set
 	 * up the scan_request as per above.
 	 */
-	if (priv->is_internal_short_scan) {
+	if (priv->scan_type != IWL_SCAN_NORMAL) {
 		IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
 		ret = 0;
 	} else
-		ret = iwl_scan_initiate(priv, vif, false,
+		ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL,
 					req->channels[0]->band);
 
 	IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -440,7 +435,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(iwl_mac_hw_scan);
 
 /*
  * internal short scan, this function should only been called while associated.
@@ -460,7 +454,7 @@
 
 	mutex_lock(&priv->mutex);
 
-	if (priv->is_internal_short_scan == true) {
+	if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
 		IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
 		goto unlock;
 	}
@@ -470,7 +464,7 @@
 		goto unlock;
 	}
 
-	if (iwl_scan_initiate(priv, NULL, true, priv->band))
+	if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
 		IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
  unlock:
 	mutex_unlock(&priv->mutex);
@@ -537,7 +531,6 @@
 
 	return (u16)len;
 }
-EXPORT_SYMBOL(iwl_fill_probe_req);
 
 static void iwl_bg_abort_scan(struct work_struct *work)
 {
@@ -558,8 +551,7 @@
 	    container_of(work, struct iwl_priv, scan_completed);
 	bool aborted;
 
-	IWL_DEBUG_SCAN(priv, "Completed %sscan.\n",
-		       priv->is_internal_short_scan ? "internal short " : "");
+	IWL_DEBUG_SCAN(priv, "Completed scan.\n");
 
 	cancel_delayed_work(&priv->scan_check);
 
@@ -574,7 +566,13 @@
 		goto out_settings;
 	}
 
-	if (priv->is_internal_short_scan && !aborted) {
+	if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) {
+		ieee80211_tx_status_irqsafe(priv->hw,
+					    priv->_agn.offchan_tx_skb);
+		priv->_agn.offchan_tx_skb = NULL;
+	}
+
+	if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
 		int err;
 
 		/* Check if mac80211 requested scan during our internal scan */
@@ -582,7 +580,7 @@
 			goto out_complete;
 
 		/* If so request a new scan */
-		err = iwl_scan_initiate(priv, priv->scan_vif, false,
+		err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
 					priv->scan_request->channels[0]->band);
 		if (err) {
 			IWL_DEBUG_SCAN(priv,
@@ -622,7 +620,6 @@
 	INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan);
 	INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check);
 }
-EXPORT_SYMBOL(iwl_setup_scan_deferred_work);
 
 void iwl_cancel_scan_deferred_work(struct iwl_priv *priv)
 {
@@ -636,4 +633,3 @@
 		mutex_unlock(&priv->mutex);
 	}
 }
-EXPORT_SYMBOL(iwl_cancel_scan_deferred_work);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-sta.c	2011-05-19 00:06:34.000000000 -0400
@@ -169,7 +169,6 @@
 
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_add_sta);
 
 static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
 				   struct ieee80211_sta *sta,
@@ -316,7 +315,6 @@
 	return sta_id;
 
 }
-EXPORT_SYMBOL_GPL(iwl_prep_station);
 
 #define STA_WAIT_TIMEOUT (HZ/2)
 
@@ -379,7 +377,6 @@
 	*sta_id_r = sta_id;
 	return ret;
 }
-EXPORT_SYMBOL(iwl_add_station_common);
 
 /**
  * iwl_sta_ucode_deactivate - deactivate ucode status for a station
@@ -513,7 +510,6 @@
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 	return -EINVAL;
 }
-EXPORT_SYMBOL_GPL(iwl_remove_station);
 
 /**
  * iwl_clear_ucode_stations - clear ucode station table bits
@@ -548,7 +544,6 @@
 	if (!cleared)
 		IWL_DEBUG_INFO(priv, "No active stations found to be cleared\n");
 }
-EXPORT_SYMBOL(iwl_clear_ucode_stations);
 
 /**
  * iwl_restore_stations() - Restore driver known stations to device
@@ -625,7 +620,6 @@
 	else
 		IWL_DEBUG_INFO(priv, "Restoring all known stations .... complete.\n");
 }
-EXPORT_SYMBOL(iwl_restore_stations);
 
 void iwl_reprogram_ap_sta(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
 {
@@ -668,7 +662,6 @@
 			priv->stations[sta_id].sta.sta.addr, ret);
 	iwl_send_lq_cmd(priv, ctx, &lq, CMD_SYNC, true);
 }
-EXPORT_SYMBOL(iwl_reprogram_ap_sta);
 
 int iwl_get_free_ucode_key_index(struct iwl_priv *priv)
 {
@@ -680,7 +673,6 @@
 
 	return WEP_INVALID_OFFSET;
 }
-EXPORT_SYMBOL(iwl_get_free_ucode_key_index);
 
 void iwl_dealloc_bcast_stations(struct iwl_priv *priv)
 {
@@ -700,7 +692,6 @@
 	}
 	spin_unlock_irqrestore(&priv->sta_lock, flags);
 }
-EXPORT_SYMBOL_GPL(iwl_dealloc_bcast_stations);
 
 #ifdef CONFIG_IWLWIFI_DEBUG
 static void iwl_dump_lq_cmd(struct iwl_priv *priv,
@@ -810,7 +801,6 @@
 	}
 	return ret;
 }
-EXPORT_SYMBOL(iwl_send_lq_cmd);
 
 int iwl_mac_sta_remove(struct ieee80211_hw *hw,
 		       struct ieee80211_vif *vif,
@@ -832,4 +822,3 @@
 	mutex_unlock(&priv->mutex);
 	return ret;
 }
-EXPORT_SYMBOL(iwl_mac_sta_remove);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/iwl-tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,7 +84,23 @@
 	}
 	txq->need_update = 0;
 }
-EXPORT_SYMBOL(iwl_txq_update_write_ptr);
+
+/**
+ * iwl_tx_queue_unmap -  Unmap any remaining DMA mappings and free skb's
+ */
+void iwl_tx_queue_unmap(struct iwl_priv *priv, int txq_id)
+{
+	struct iwl_tx_queue *txq = &priv->txq[txq_id];
+	struct iwl_queue *q = &txq->q;
+
+	if (q->n_bd == 0)
+		return;
+
+	 while (q->write_ptr != q->read_ptr) {
+		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+		q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+	}
+}
 
 /**
  * iwl_tx_queue_free - Deallocate DMA queue.
@@ -97,17 +113,10 @@
 void iwl_tx_queue_free(struct iwl_priv *priv, int txq_id)
 {
 	struct iwl_tx_queue *txq = &priv->txq[txq_id];
-	struct iwl_queue *q = &txq->q;
 	struct device *dev = &priv->pci_dev->dev;
 	int i;
 
-	if (q->n_bd == 0)
-		return;
-
-	/* first, empty all BD's */
-	for (; q->write_ptr != q->read_ptr;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd))
-		priv->cfg->ops->lib->txq_free_tfd(priv, txq);
+	iwl_tx_queue_unmap(priv, txq_id);
 
 	/* De-alloc array of command/tx buffers */
 	for (i = 0; i < TFD_TX_CMD_SLOTS; i++)
@@ -131,42 +140,35 @@
 	/* 0-fill queue descriptor structure */
 	memset(txq, 0, sizeof(*txq));
 }
-EXPORT_SYMBOL(iwl_tx_queue_free);
 
 /**
- * iwl_cmd_queue_free - Deallocate DMA queue.
- * @txq: Transmit queue to deallocate.
- *
- * Empty queue by removing and destroying all BD's.
- * Free all buffers.
- * 0-fill, but do not free "txq" descriptor structure.
+ * iwl_cmd_queue_unmap - Unmap any remaining DMA mappings from command queue
  */
-void iwl_cmd_queue_free(struct iwl_priv *priv)
+void iwl_cmd_queue_unmap(struct iwl_priv *priv)
 {
 	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
 	struct iwl_queue *q = &txq->q;
-	struct device *dev = &priv->pci_dev->dev;
 	int i;
 	bool huge = false;
 
 	if (q->n_bd == 0)
 		return;
 
-	for (; q->read_ptr != q->write_ptr;
-	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+	while (q->read_ptr != q->write_ptr) {
 		/* we have no way to tell if it is a huge cmd ATM */
 		i = get_cmd_index(q, q->read_ptr, 0);
 
-		if (txq->meta[i].flags & CMD_SIZE_HUGE) {
+		if (txq->meta[i].flags & CMD_SIZE_HUGE)
 			huge = true;
-			continue;
-		}
+		else
+			pci_unmap_single(priv->pci_dev,
+					 dma_unmap_addr(&txq->meta[i], mapping),
+					 dma_unmap_len(&txq->meta[i], len),
+					 PCI_DMA_BIDIRECTIONAL);
 
-		pci_unmap_single(priv->pci_dev,
-				 dma_unmap_addr(&txq->meta[i], mapping),
-				 dma_unmap_len(&txq->meta[i], len),
-				 PCI_DMA_BIDIRECTIONAL);
+	     q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
 	}
+
 	if (huge) {
 		i = q->n_window;
 		pci_unmap_single(priv->pci_dev,
@@ -174,6 +176,23 @@
 				 dma_unmap_len(&txq->meta[i], len),
 				 PCI_DMA_BIDIRECTIONAL);
 	}
+}
+
+/**
+ * iwl_cmd_queue_free - Deallocate DMA queue.
+ * @txq: Transmit queue to deallocate.
+ *
+ * Empty queue by removing and destroying all BD's.
+ * Free all buffers.
+ * 0-fill, but do not free "txq" descriptor structure.
+ */
+void iwl_cmd_queue_free(struct iwl_priv *priv)
+{
+	struct iwl_tx_queue *txq = &priv->txq[priv->cmd_queue];
+	struct device *dev = &priv->pci_dev->dev;
+	int i;
+
+	iwl_cmd_queue_unmap(priv);
 
 	/* De-alloc array of command/tx buffers */
 	for (i = 0; i <= TFD_CMD_SLOTS; i++)
@@ -193,7 +212,6 @@
 	/* 0-fill queue descriptor structure */
 	memset(txq, 0, sizeof(*txq));
 }
-EXPORT_SYMBOL(iwl_cmd_queue_free);
 
 /*************** DMA-QUEUE-GENERAL-FUNCTIONS  *****
  * DMA services
@@ -233,7 +251,6 @@
 		s = 0;
 	return s;
 }
-EXPORT_SYMBOL(iwl_queue_space);
 
 
 /**
@@ -384,7 +401,6 @@
 
 	return -ENOMEM;
 }
-EXPORT_SYMBOL(iwl_tx_queue_init);
 
 void iwl_tx_queue_reset(struct iwl_priv *priv, struct iwl_tx_queue *txq,
 			int slots_num, u32 txq_id)
@@ -404,7 +420,6 @@
 	/* Tell device where to find queue */
 	priv->cfg->ops->lib->txq_init(priv, txq);
 }
-EXPORT_SYMBOL(iwl_tx_queue_reset);
 
 /*************** HOST COMMAND QUEUE FUNCTIONS   *****/
 
@@ -641,4 +656,3 @@
 	}
 	meta->flags = 0;
 }
-EXPORT_SYMBOL(iwl_tx_cmd_complete);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,14 +1,52 @@
-config IWLWIFI
-	tristate "Intel Wireless Wifi"
+config IWLAGN
+	tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlagn) "
 	depends on PCI && MAC80211
 	select FW_LOADER
+	select NEW_LEDS
+	select LEDS_CLASS
+	select LEDS_TRIGGERS
+	select MAC80211_LEDS
+	---help---
+	  Select to build the driver supporting the:
+
+	  Intel Wireless WiFi Link Next-Gen AGN
+
+	  This option enables support for use with the following hardware:
+		Intel Wireless WiFi Link 6250AGN Adapter
+		Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
+		Intel WiFi Link 1000BGN
+		Intel Wireless WiFi 5150AGN
+		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
+		Intel 6005 Series Wi-Fi Adapters
+		Intel 6030 Series Wi-Fi Adapters
+		Intel Wireless WiFi Link 6150BGN 2 Adapter
+		Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
+		Intel 2000 Series Wi-Fi Adapters
+
+
+	  This driver uses the kernel's mac80211 subsystem.
+
+	  In order to use this driver, you will need a microcode (uCode)
+	  image for it. You can obtain the microcode from:
+
+	          <http://intellinuxwireless.org/>.
+
+	  The microcode is typically installed in /lib/firmware. You can
+	  look in the hotplug script /etc/hotplug/firmware.agent to
+	  determine which directory FIRMWARE_DIR is set to when the script
+	  runs.
+
+	  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.
 
 menu "Debugging Options"
-	depends on IWLWIFI
+	depends on IWLAGN
 
 config IWLWIFI_DEBUG
-	bool "Enable full debugging output in iwlagn and iwl3945 drivers"
-	depends on IWLWIFI
+	bool "Enable full debugging output in the iwlagn driver"
+	depends on IWLAGN
 	---help---
 	  This option will enable debug tracing output for the iwlwifi drivers
 
@@ -33,7 +71,7 @@
 
 config IWLWIFI_DEBUGFS
         bool "iwlagn debugfs support"
-        depends on IWLWIFI && MAC80211_DEBUGFS
+        depends on IWLAGN && MAC80211_DEBUGFS
         ---help---
 	  Enable creation of debugfs files for the iwlwifi drivers. This
 	  is a low-impact option that allows getting insight into the
@@ -41,13 +79,13 @@
 
 config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
         bool "Experimental uCode support"
-        depends on IWLWIFI && IWLWIFI_DEBUG
+        depends on IWLAGN && IWLWIFI_DEBUG
         ---help---
 	  Enable use of experimental ucode for testing and debugging.
 
 config IWLWIFI_DEVICE_TRACING
 	bool "iwlwifi device access tracing"
-	depends on IWLWIFI
+	depends on IWLAGN
 	depends on EVENT_TRACING
 	help
 	  Say Y here to trace all commands, including TX frames and IO
@@ -64,73 +102,19 @@
 	  occur.
 endmenu
 
-config IWLAGN
-	tristate "Intel Wireless WiFi Next Gen AGN (iwlagn)"
-	depends on IWLWIFI
-	---help---
-	  Select to build the driver supporting the:
-
-	  Intel Wireless WiFi Link Next-Gen AGN
-
-	  This driver uses the kernel's mac80211 subsystem.
-
-	  In order to use this driver, you will need a microcode (uCode)
-	  image for it. You can obtain the microcode from:
-
-	          <http://intellinuxwireless.org/>.
-
-	  The microcode is typically installed in /lib/firmware. You can
-	  look in the hotplug script /etc/hotplug/firmware.agent to
-	  determine which directory FIRMWARE_DIR is set to when the script
-	  runs.
-
-	  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.
-
-
-config IWL4965
-	bool "Intel Wireless WiFi 4965AGN"
-	depends on IWLAGN
-	---help---
-	  This option enables support for Intel Wireless WiFi Link 4965AGN
-
-config IWL5000
-	bool "Intel Wireless-N/Advanced-N/Ultimate-N WiFi Link"
+config IWL_P2P
+	bool "iwlwifi experimental P2P support"
 	depends on IWLAGN
-	---help---
-	  This option enables support for use with the following hardware:
-		Intel Wireless WiFi Link 6250AGN Adapter
-		Intel 6000 Series Wi-Fi Adapters (6200AGN and 6300AGN)
-		Intel WiFi Link 1000BGN
-		Intel Wireless WiFi 5150AGN
-		Intel Wireless WiFi 5100AGN, 5300AGN, and 5350AGN
-		Intel 6000 Gen 2 Series Wi-Fi Adapters (6000G2A and 6000G2B)
-		Intel WIreless WiFi Link 6050BGN Gen 2 Adapter
-		Intel 100 Series Wi-Fi Adapters (100BGN and 130BGN)
-
-config IWL3945
-	tristate "Intel PRO/Wireless 3945ABG/BG Network Connection (iwl3945)"
-	depends on IWLWIFI
-	---help---
-	  Select to build the driver supporting the:
-
-	  Intel PRO/Wireless 3945ABG/BG Network Connection
-
-	  This driver uses the kernel's mac80211 subsystem.
-
-	  In order to use this driver, you will need a microcode (uCode)
-	  image for it. You can obtain the microcode from:
+	help
+	  This option enables experimental P2P support for some devices
+	  based on microcode support. Since P2P support is still under
+	  development, this option may even enable it for some devices
+	  now that turn out to not support it in the future due to
+	  microcode restrictions.
 
-	          <http://intellinuxwireless.org/>.
+	  To determine if your microcode supports the experimental P2P
+	  offered by this option, check if the driver advertises AP
+	  support when it is loaded.
 
-	  The microcode is typically installed in /lib/firmware. You can
-	  look in the hotplug script /etc/hotplug/firmware.agent to
-	  determine which directory FIRMWARE_DIR is set to when the script
-	  runs.
+	  Say Y only if you want to experiment with P2P.
 
-	  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.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwlwifi/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwlwifi/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,35 +1,23 @@
-obj-$(CONFIG_IWLWIFI)	+= iwlcore.o
-iwlcore-objs 		:= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
-iwlcore-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
-iwlcore-objs 		+= iwl-scan.o iwl-led.o
-iwlcore-$(CONFIG_IWL3945) += iwl-legacy.o
-iwlcore-$(CONFIG_IWL4965) += iwl-legacy.o
-iwlcore-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
-iwlcore-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
-
-# If 3945 is selected only, iwl-legacy.o will be added
-# to iwlcore-m above, but it needs to be built in.
-iwlcore-objs += $(iwlcore-m)
-
-CFLAGS_iwl-devtrace.o := -I$(src)
-
 # AGN
 obj-$(CONFIG_IWLAGN)	+= iwlagn.o
 iwlagn-objs		:= iwl-agn.o iwl-agn-rs.o iwl-agn-led.o
 iwlagn-objs		+= iwl-agn-ucode.o iwl-agn-tx.o
-iwlagn-objs		+= iwl-agn-lib.o iwl-agn-rx.o iwl-agn-calib.o
+iwlagn-objs		+= iwl-agn-lib.o iwl-agn-calib.o
 iwlagn-objs		+= iwl-agn-tt.o iwl-agn-sta.o iwl-agn-eeprom.o
-iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
 
-iwlagn-$(CONFIG_IWL4965) += iwl-4965.o
-iwlagn-$(CONFIG_IWL5000) += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
-iwlagn-$(CONFIG_IWL5000) += iwl-5000.o
-iwlagn-$(CONFIG_IWL5000) += iwl-6000.o
-iwlagn-$(CONFIG_IWL5000) += iwl-1000.o
+iwlagn-objs 		+= iwl-core.o iwl-eeprom.o iwl-hcmd.o iwl-power.o
+iwlagn-objs 		+= iwl-rx.o iwl-tx.o iwl-sta.o
+iwlagn-objs 		+= iwl-scan.o iwl-led.o
+iwlagn-objs             += iwl-agn-rxon.o iwl-agn-hcmd.o iwl-agn-ict.o
+iwlagn-objs             += iwl-5000.o
+iwlagn-objs             += iwl-6000.o
+iwlagn-objs             += iwl-1000.o
+iwlagn-objs             += iwl-2000.o
 
-# 3945
-obj-$(CONFIG_IWL3945)	+= iwl3945.o
-iwl3945-objs		:= iwl3945-base.o iwl-3945.o iwl-3945-rs.o iwl-3945-led.o
-iwl3945-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-3945-debugfs.o
+iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-agn-debugfs.o
+iwlagn-$(CONFIG_IWLWIFI_DEBUGFS) += iwl-debugfs.o
+iwlagn-$(CONFIG_IWLWIFI_DEVICE_TRACING) += iwl-devtrace.o
+
+CFLAGS_iwl-devtrace.o := -I$(src)
 
 ccflags-y += -D__CHECK_ENDIAN__
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/cfg80211.c	2011-05-19 00:06:34.000000000 -0400
@@ -287,7 +287,8 @@
 			return -EINVAL;
 		}
 
-		freq = ieee80211_channel_to_frequency(umac_bss->channel);
+		freq = ieee80211_channel_to_frequency(umac_bss->channel,
+						      band->band);
 		channel = ieee80211_get_channel(wiphy, freq);
 		signal = umac_bss->rssi * 100;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/hal.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/hal.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/hal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/hal.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
  *   This is due to the fact 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:
+ *   This is how a wifi command is laid out:
  *    ------------------------
  *   | iwm_udma_out_wifi_hdr  |
  *    ------------------------
@@ -72,7 +72,7 @@
  *   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:
+ *    *   This is how a non-wifi command is laid out:
  *    ---------------------------
  *   | iwm_udma_out_nonwifi_hdr  |
  *    ---------------------------
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -543,7 +543,10 @@
 	switch (le32_to_cpu(complete->status)) {
 	case UMAC_ASSOC_COMPLETE_SUCCESS:
 		chan = ieee80211_get_channel(wiphy,
-			ieee80211_channel_to_frequency(complete->channel));
+			ieee80211_channel_to_frequency(complete->channel,
+				complete->band == UMAC_BAND_2GHZ ?
+					IEEE80211_BAND_2GHZ :
+					IEEE80211_BAND_5GHZ));
 		if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) {
 			/* Associated to a unallowed channel, disassociate. */
 			__iwm_invalidate_mlme_profile(iwm);
@@ -841,7 +844,7 @@
 		goto err;
 	}
 
-	freq = ieee80211_channel_to_frequency(umac_bss->channel);
+	freq = ieee80211_channel_to_frequency(umac_bss->channel, band->band);
 	channel = ieee80211_get_channel(wiphy, freq);
 	signal = umac_bss->rssi * 100;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/iwmc3200wifi/tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/iwmc3200wifi/tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -197,7 +197,7 @@
 	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);
+		IWM_DBG_TX(iwm, DBG, "No credit available for pool[%d]\n", id);
 		ret = -ENOSPC;
 		goto out;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -274,6 +274,7 @@
 source "drivers/net/wireless/hostap/Kconfig"
 source "drivers/net/wireless/ipw2x00/Kconfig"
 source "drivers/net/wireless/iwlwifi/Kconfig"
+source "drivers/net/wireless/iwlegacy/Kconfig"
 source "drivers/net/wireless/iwmc3200wifi/Kconfig"
 source "drivers/net/wireless/libertas/Kconfig"
 source "drivers/net/wireless/orinoco/Kconfig"
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/cfg.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/cfg.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/cfg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/cfg.c	2011-05-19 00:06:34.000000000 -0400
@@ -607,7 +607,8 @@
 		/* No channel, no luck */
 		if (chan_no != -1) {
 			struct wiphy *wiphy = priv->wdev->wiphy;
-			int freq = ieee80211_channel_to_frequency(chan_no);
+			int freq = ieee80211_channel_to_frequency(chan_no,
+							IEEE80211_BAND_2GHZ);
 			struct ieee80211_channel *channel =
 				ieee80211_get_channel(wiphy, freq);
 
@@ -1349,7 +1350,7 @@
 		 * we remove all keys like in the WPA/WPA2 setup,
 		 * we just don't set RSN.
 		 *
-		 * Therefore: fall-throught
+		 * Therefore: fall-through
 		 */
 	case WLAN_CIPHER_SUITE_TKIP:
 	case WLAN_CIPHER_SUITE_CCMP:
@@ -1597,7 +1598,8 @@
 	lbs_deb_enter(LBS_DEB_CFG80211);
 
 	survey->channel = ieee80211_get_channel(wiphy,
-		ieee80211_channel_to_frequency(priv->channel));
+		ieee80211_channel_to_frequency(priv->channel,
+					       IEEE80211_BAND_2GHZ));
 
 	ret = lbs_get_rssi(priv, &signal, &noise);
 	if (ret == 0) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/cmd.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/cmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/cmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -145,9 +145,13 @@
 	if (priv->current_addr[0] == 0xff)
 		memmove(priv->current_addr, cmd.permanentaddr, ETH_ALEN);
 
-	memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
-	if (priv->mesh_dev)
-		memcpy(priv->mesh_dev->dev_addr, priv->current_addr, ETH_ALEN);
+	if (!priv->copied_hwaddr) {
+		memcpy(priv->dev->dev_addr, priv->current_addr, ETH_ALEN);
+		if (priv->mesh_dev)
+			memcpy(priv->mesh_dev->dev_addr,
+				priv->current_addr, ETH_ALEN);
+		priv->copied_hwaddr = 1;
+	}
 
 out:
 	lbs_deb_leave(LBS_DEB_CMD);
@@ -1335,8 +1339,8 @@
 				    cpu_to_le16(PS_MODE_ACTION_EXIT_PS)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore ENTER_PS cmd\n");
-					list_del(&cmdnode->list);
 					spin_lock_irqsave(&priv->driver_lock, flags);
+					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
 					spin_unlock_irqrestore(&priv->driver_lock, flags);
 
@@ -1348,8 +1352,8 @@
 				    (priv->psstate == PS_STATE_PRE_SLEEP)) {
 					lbs_deb_host(
 					       "EXEC_NEXT_CMD: ignore EXIT_PS cmd in sleep\n");
-					list_del(&cmdnode->list);
 					spin_lock_irqsave(&priv->driver_lock, flags);
+					list_del(&cmdnode->list);
 					lbs_complete_command(priv, cmdnode, 0);
 					spin_unlock_irqrestore(&priv->driver_lock, flags);
 					priv->needtowakeup = 1;
@@ -1362,7 +1366,9 @@
 				       "EXEC_NEXT_CMD: sending EXIT_PS\n");
 			}
 		}
+		spin_lock_irqsave(&priv->driver_lock, flags);
 		list_del(&cmdnode->list);
+		spin_unlock_irqrestore(&priv->driver_lock, flags);
 		lbs_deb_host("EXEC_NEXT_CMD: sending command 0x%04x\n",
 			    le16_to_cpu(cmd->command));
 		lbs_submit_command(priv, cmdnode);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/dev.h linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/dev.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/dev.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/dev.h	2011-05-19 00:06:34.000000000 -0400
@@ -90,6 +90,7 @@
 	void *card;
 	u8 fw_ready;
 	u8 surpriseremoved;
+	u8 setup_fw_on_resume;
 	int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
 	void (*reset_card) (struct lbs_private *priv);
 	int (*enter_deep_sleep) (struct lbs_private *priv);
@@ -101,6 +102,7 @@
 	u32 fwcapinfo;
 	u16 regioncode;
 	u8 current_addr[ETH_ALEN];
+	u8 copied_hwaddr;
 
 	/* Command download */
 	u8 dnld_sent;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/host.h linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/host.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/host.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/host.h	2011-05-19 00:06:34.000000000 -0400
@@ -387,7 +387,7 @@
 struct mrvl_ie_domain_param_set {
 	struct mrvl_ie_header header;
 
-	u8 country_code[3];
+	u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
 	struct ieee80211_country_ie_triplet triplet[MAX_11D_TRIPLETS];
 } __packed;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/if_cs.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/if_cs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/if_cs.c	2012-03-24 01:12:50.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/if_cs.c	2012-03-24 03:33:33.000000000 -0400
@@ -907,7 +907,7 @@
 		goto out3;
 	}
 
-	/* Clear any interrupt cause that happend while sending
+	/* Clear any interrupt cause that happened while sending
 	 * firmware/initializing card */
 	if_cs_write16(card, IF_CS_CARD_INT_CAUSE, IF_CS_BIT_MASK);
 	if_cs_enable_ints(card);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/if_spi.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/if_spi.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/if_spi.c	2012-03-24 01:13:00.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/if_spi.c	2012-03-24 03:33:38.000000000 -0400
@@ -20,10 +20,8 @@
 #include <linux/moduleparam.h>
 #include <linux/firmware.h>
 #include <linux/jiffies.h>
-#include <linux/kthread.h>
 #include <linux/list.h>
 #include <linux/netdevice.h>
-#include <linux/semaphore.h>
 #include <linux/slab.h>
 #include <linux/spi/libertas_spi.h>
 #include <linux/spi/spi.h>
@@ -34,6 +32,12 @@
 #include "dev.h"
 #include "if_spi.h"
 
+struct if_spi_packet {
+	struct list_head		list;
+	u16				blen;
+	u8				buffer[0] __attribute__((aligned(4)));
+};
+
 struct if_spi_card {
 	struct spi_device		*spi;
 	struct lbs_private		*priv;
@@ -51,18 +55,36 @@
 	unsigned long			spu_reg_delay;
 
 	/* Handles all SPI communication (except for FW load) */
-	struct task_struct		*spi_thread;
-	int				run_thread;
-
-	/* Used to wake up the spi_thread */
-	struct semaphore		spi_ready;
-	struct semaphore		spi_thread_terminated;
+	struct workqueue_struct		*workqueue;
+	struct work_struct		packet_work;
 
 	u8				cmd_buffer[IF_SPI_CMD_BUF_SIZE];
+
+	/* A buffer of incoming packets from libertas core.
+	 * Since we can't sleep in hw_host_to_card, we have to buffer
+	 * them. */
+	struct list_head		cmd_packet_list;
+	struct list_head		data_packet_list;
+
+	/* Protects cmd_packet_list and data_packet_list */
+	spinlock_t			buffer_lock;
 };
 
 static void free_if_spi_card(struct if_spi_card *card)
 {
+	struct list_head *cursor, *next;
+	struct if_spi_packet *packet;
+
+	list_for_each_safe(cursor, next, &card->cmd_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
+	list_for_each_safe(cursor, next, &card->data_packet_list) {
+		packet = container_of(cursor, struct if_spi_packet, list);
+		list_del(&packet->list);
+		kfree(packet);
+	}
 	spi_set_drvdata(card->spi, NULL);
 	kfree(card);
 }
@@ -614,7 +636,7 @@
 /*
  * SPI Transfer Thread
  *
- * The SPI thread handles all SPI transfers, so there is no need for a lock.
+ * The SPI worker handles all SPI transfers, so there is no need for a lock.
  */
 
 /* Move a command from the card to the host */
@@ -734,6 +756,40 @@
 	return err;
 }
 
+/* Move data or a command from the host to the card. */
+static void if_spi_h2c(struct if_spi_card *card,
+			struct if_spi_packet *packet, int type)
+{
+	int err = 0;
+	u16 int_type, port_reg;
+
+	switch (type) {
+	case MVMS_DAT:
+		int_type = IF_SPI_CIC_TX_DOWNLOAD_OVER;
+		port_reg = IF_SPI_DATA_RDWRPORT_REG;
+		break;
+	case MVMS_CMD:
+		int_type = IF_SPI_CIC_CMD_DOWNLOAD_OVER;
+		port_reg = IF_SPI_CMD_RDWRPORT_REG;
+		break;
+	default:
+		lbs_pr_err("can't transfer buffer of type %d\n", type);
+		err = -EINVAL;
+		goto out;
+	}
+
+	/* Write the data to the card */
+	err = spu_write(card, port_reg, packet->buffer, packet->blen);
+	if (err)
+		goto out;
+
+out:
+	kfree(packet);
+
+	if (err)
+		lbs_pr_err("%s: error %d\n", __func__, err);
+}
+
 /* Inform the host about a card event */
 static void if_spi_e2h(struct if_spi_card *card)
 {
@@ -758,71 +814,88 @@
 		lbs_pr_err("%s: error %d\n", __func__, err);
 }
 
-static int lbs_spi_thread(void *data)
+static void if_spi_host_to_card_worker(struct work_struct *work)
 {
 	int err;
-	struct if_spi_card *card = data;
+	struct if_spi_card *card;
 	u16 hiStatus;
+	unsigned long flags;
+	struct if_spi_packet *packet;
 
-	while (1) {
-		/* Wait to be woken up by one of two things.  First, our ISR
-		 * could tell us that something happened on the WLAN.
-		 * Secondly, libertas could call hw_host_to_card with more
-		 * data, which we might be able to send.
-		 */
-		do {
-			err = down_interruptible(&card->spi_ready);
-			if (!card->run_thread) {
-				up(&card->spi_thread_terminated);
-				do_exit(0);
-			}
-		} while (err == -EINTR);
+	card = container_of(work, struct if_spi_card, packet_work);
 
-		/* Read the host interrupt status register to see what we
-		 * can do. */
-		err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
-					&hiStatus);
-		if (err) {
-			lbs_pr_err("I/O error\n");
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	/* Read the host interrupt status register to see what we
+	 * can do. */
+	err = spu_read_u16(card, IF_SPI_HOST_INT_STATUS_REG,
+				&hiStatus);
+	if (err) {
+		lbs_pr_err("I/O error\n");
+		goto err;
+	}
+
+	if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) {
+		err = if_spi_c2h_cmd(card);
+		if (err)
 			goto err;
-		}
+	}
+	if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) {
+		err = if_spi_c2h_data(card);
+		if (err)
+			goto err;
+	}
 
-		if (hiStatus & IF_SPI_HIST_CMD_UPLOAD_RDY) {
-			err = if_spi_c2h_cmd(card);
-			if (err)
-				goto err;
-		}
-		if (hiStatus & IF_SPI_HIST_RX_UPLOAD_RDY) {
-			err = if_spi_c2h_data(card);
-			if (err)
-				goto err;
+	/* 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.
+		 * Secondly, it is now ready to download another
+		 * command.
+		 */
+		lbs_host_to_card_done(card->priv);
+
+		/* Do we have any command packets from the host to
+		 * send? */
+		packet = NULL;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		if (!list_empty(&card->cmd_packet_list)) {
+			packet = (struct if_spi_packet *)(card->
+					cmd_packet_list.next);
+			list_del(&packet->list);
 		}
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 
-		/* 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))) {
-			lbs_host_to_card_done(card->priv);
+		if (packet)
+			if_spi_h2c(card, packet, MVMS_CMD);
+	}
+	if (hiStatus & IF_SPI_HIST_TX_DOWNLOAD_RDY) {
+		/* Do we have any data packets from the host to
+		 * send? */
+		packet = NULL;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		if (!list_empty(&card->data_packet_list)) {
+			packet = (struct if_spi_packet *)(card->
+					data_packet_list.next);
+			list_del(&packet->list);
 		}
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 
-		if (hiStatus & IF_SPI_HIST_CARD_EVENT)
-			if_spi_e2h(card);
+		if (packet)
+			if_spi_h2c(card, packet, MVMS_DAT);
+	}
+	if (hiStatus & IF_SPI_HIST_CARD_EVENT)
+		if_spi_e2h(card);
 
 err:
-		if (err)
-			lbs_pr_err("%s: got error %d\n", __func__, err);
-	}
-}
+	if (err)
+		lbs_pr_err("%s: got error %d\n", __func__, err);
 
-/* Block until lbs_spi_thread thread has terminated */
-static void if_spi_terminate_spi_thread(struct if_spi_card *card)
-{
-	/* It would be nice to use kthread_stop here, but that function
-	 * can't wake threads waiting for a semaphore. */
-	card->run_thread = 0;
-	up(&card->spi_ready);
-	down(&card->spi_thread_terminated);
+	lbs_deb_leave(LBS_DEB_SPI);
 }
 
 /*
@@ -834,18 +907,40 @@
 				u8 type, u8 *buf, u16 nb)
 {
 	int err = 0;
+	unsigned long flags;
 	struct if_spi_card *card = priv->card;
+	struct if_spi_packet *packet;
+	u16 blen;
 
 	lbs_deb_enter_args(LBS_DEB_SPI, "type %d, bytes %d", type, nb);
 
-	nb = ALIGN(nb, 4);
+	if (nb == 0) {
+		lbs_pr_err("%s: invalid size requested: %d\n", __func__, nb);
+		err = -EINVAL;
+		goto out;
+	}
+	blen = ALIGN(nb, 4);
+	packet = kzalloc(sizeof(struct if_spi_packet) + blen, GFP_ATOMIC);
+	if (!packet) {
+		err = -ENOMEM;
+		goto out;
+	}
+	packet->blen = blen;
+	memcpy(packet->buffer, buf, nb);
+	memset(packet->buffer + nb, 0, blen - nb);
 
 	switch (type) {
 	case MVMS_CMD:
-		err = spu_write(card, IF_SPI_CMD_RDWRPORT_REG, buf, nb);
+		priv->dnld_sent = DNLD_CMD_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->cmd_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 		break;
 	case MVMS_DAT:
-		err = spu_write(card, IF_SPI_DATA_RDWRPORT_REG, buf, nb);
+		priv->dnld_sent = DNLD_DATA_SENT;
+		spin_lock_irqsave(&card->buffer_lock, flags);
+		list_add_tail(&packet->list, &card->data_packet_list);
+		spin_unlock_irqrestore(&card->buffer_lock, flags);
 		break;
 	default:
 		lbs_pr_err("can't transfer buffer of type %d", type);
@@ -853,6 +948,9 @@
 		break;
 	}
 
+	/* Queue spi xfer work */
+	queue_work(card->workqueue, &card->packet_work);
+out:
 	lbs_deb_leave_args(LBS_DEB_SPI, "err=%d", err);
 	return err;
 }
@@ -861,13 +959,14 @@
  * Host Interrupts
  *
  * Service incoming interrupts from the WLAN device. We can't sleep here, so
- * don't try to talk on the SPI bus, just wake up the SPI thread.
+ * don't try to talk on the SPI bus, just queue the SPI xfer work.
  */
 static irqreturn_t if_spi_host_interrupt(int irq, void *dev_id)
 {
 	struct if_spi_card *card = dev_id;
 
-	up(&card->spi_ready);
+	queue_work(card->workqueue, &card->packet_work);
+
 	return IRQ_HANDLED;
 }
 
@@ -875,56 +974,26 @@
  * SPI callbacks
  */
 
-static int __devinit if_spi_probe(struct spi_device *spi)
+static int if_spi_init_card(struct if_spi_card *card)
 {
-	struct if_spi_card *card;
-	struct lbs_private *priv = NULL;
-	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
-	int err = 0, i;
+	struct spi_device *spi = card->spi;
+	int err, i;
 	u32 scratch;
-	struct sched_param param = { .sched_priority = 1 };
 	const struct firmware *helper = NULL;
 	const struct firmware *mainfw = NULL;
 
 	lbs_deb_enter(LBS_DEB_SPI);
 
-	if (!pdata) {
-		err = -EINVAL;
-		goto out;
-	}
-
-	if (pdata->setup) {
-		err = pdata->setup(spi);
-		if (err)
-			goto out;
-	}
-
-	/* Allocate card structure to represent this specific device */
-	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
-	if (!card) {
-		err = -ENOMEM;
-		goto out;
-	}
-	spi_set_drvdata(spi, card);
-	card->pdata = pdata;
-	card->spi = spi;
-	card->prev_xfer_time = jiffies;
-
-	sema_init(&card->spi_ready, 0);
-	sema_init(&card->spi_thread_terminated, 0);
-
-	/* Initialize the SPI Interface Unit */
-	err = spu_init(card, pdata->use_dummy_writes);
+	err = spu_init(card, card->pdata->use_dummy_writes);
 	if (err)
-		goto free_card;
+		goto out;
 	err = spu_get_chip_revision(card, &card->card_id, &card->card_rev);
 	if (err)
-		goto free_card;
+		goto out;
 
-	/* Firmware load */
 	err = spu_read_u32(card, IF_SPI_SCRATCH_4_REG, &scratch);
 	if (err)
-		goto free_card;
+		goto out;
 	if (scratch == SUCCESSFUL_FW_DOWNLOAD_MAGIC)
 		lbs_deb_spi("Firmware is already loaded for "
 			    "Marvell WLAN 802.11 adapter\n");
@@ -938,7 +1007,7 @@
 			lbs_pr_err("Unsupported chip_id: 0x%02x\n",
 					card->card_id);
 			err = -ENODEV;
-			goto free_card;
+			goto out;
 		}
 
 		err = lbs_get_firmware(&card->spi->dev, NULL, NULL,
@@ -946,7 +1015,7 @@
 					&mainfw);
 		if (err) {
 			lbs_pr_err("failed to find firmware (%d)\n", err);
-			goto free_card;
+			goto out;
 		}
 
 		lbs_deb_spi("Initializing FW for Marvell WLAN 802.11 adapter "
@@ -958,15 +1027,68 @@
 				spi->max_speed_hz);
 		err = if_spi_prog_helper_firmware(card, helper);
 		if (err)
-			goto free_card;
+			goto out;
 		err = if_spi_prog_main_firmware(card, mainfw);
 		if (err)
-			goto free_card;
+			goto out;
 		lbs_deb_spi("loaded FW for Marvell WLAN 802.11 adapter\n");
 	}
 
 	err = spu_set_interrupt_mode(card, 0, 1);
 	if (err)
+		goto out;
+
+out:
+	if (helper)
+		release_firmware(helper);
+	if (mainfw)
+		release_firmware(mainfw);
+
+	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
+
+	return err;
+}
+
+static int __devinit if_spi_probe(struct spi_device *spi)
+{
+	struct if_spi_card *card;
+	struct lbs_private *priv = NULL;
+	struct libertas_spi_platform_data *pdata = spi->dev.platform_data;
+	int err = 0;
+
+	lbs_deb_enter(LBS_DEB_SPI);
+
+	if (!pdata) {
+		err = -EINVAL;
+		goto out;
+	}
+
+	if (pdata->setup) {
+		err = pdata->setup(spi);
+		if (err)
+			goto out;
+	}
+
+	/* Allocate card structure to represent this specific device */
+	card = kzalloc(sizeof(struct if_spi_card), GFP_KERNEL);
+	if (!card) {
+		err = -ENOMEM;
+		goto teardown;
+	}
+	spi_set_drvdata(spi, card);
+	card->pdata = pdata;
+	card->spi = spi;
+	card->prev_xfer_time = jiffies;
+
+	INIT_LIST_HEAD(&card->cmd_packet_list);
+	INIT_LIST_HEAD(&card->data_packet_list);
+	spin_lock_init(&card->buffer_lock);
+
+	/* Initialize the SPI Interface Unit */
+
+	/* Firmware load */
+	err = if_spi_init_card(card);
+	if (err)
 		goto free_card;
 
 	/* Register our card with libertas.
@@ -985,27 +1107,16 @@
 	priv->fw_ready = 1;
 
 	/* Initialize interrupt handling stuff. */
-	card->run_thread = 1;
-	card->spi_thread = kthread_run(lbs_spi_thread, card, "lbs_spi_thread");
-	if (IS_ERR(card->spi_thread)) {
-		card->run_thread = 0;
-		err = PTR_ERR(card->spi_thread);
-		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");
+	card->workqueue = create_workqueue("libertas_spi");
+	INIT_WORK(&card->packet_work, if_spi_host_to_card_worker);
 
 	err = request_irq(spi->irq, if_spi_host_interrupt,
 			IRQF_TRIGGER_FALLING, "libertas_spi", card);
 	if (err) {
 		lbs_pr_err("can't get host irq line-- request_irq failed\n");
-		goto terminate_thread;
+		goto terminate_workqueue;
 	}
 
-	/* poke the IRQ handler so that we don't miss the first interrupt */
-	up(&card->spi_ready);
-
 	/* Start the card.
 	 * This will call register_netdev, and we'll start
 	 * getting interrupts... */
@@ -1020,18 +1131,16 @@
 
 release_irq:
 	free_irq(spi->irq, card);
-terminate_thread:
-	if_spi_terminate_spi_thread(card);
-remove_card:
+terminate_workqueue:
+	flush_workqueue(card->workqueue);
+	destroy_workqueue(card->workqueue);
 	lbs_remove_card(priv); /* will call free_netdev */
 free_card:
 	free_if_spi_card(card);
+teardown:
+	if (pdata->teardown)
+		pdata->teardown(spi);
 out:
-	if (helper)
-		release_firmware(helper);
-	if (mainfw)
-		release_firmware(mainfw);
-
 	lbs_deb_leave_args(LBS_DEB_SPI, "err %d\n", err);
 	return err;
 }
@@ -1048,7 +1157,8 @@
 	lbs_remove_card(priv); /* will call free_netdev */
 
 	free_irq(spi->irq, card);
-	if_spi_terminate_spi_thread(card);
+	flush_workqueue(card->workqueue);
+	destroy_workqueue(card->workqueue);
 	if (card->pdata->teardown)
 		card->pdata->teardown(spi);
 	free_if_spi_card(card);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/if_spi.h linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/if_spi.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/if_spi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/if_spi.h	2011-05-19 00:06:34.000000000 -0400
@@ -66,7 +66,7 @@
 #define IF_SPI_HOST_INT_CTRL_REG 0x40	/* Host interrupt controller reg */
 
 #define IF_SPI_CARD_INT_CAUSE_REG 0x44	/* Card interrupt cause reg */
-#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interupt status reg */
+#define IF_SPI_CARD_INT_STATUS_REG 0x48 /* Card interrupt status reg */
 #define IF_SPI_CARD_INT_EVENT_MASK_REG 0x4C /* Card interrupt event mask */
 #define IF_SPI_CARD_INT_STATUS_MASK_REG	0x50 /* Card interrupt status mask */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/main.c	2012-03-24 01:12:46.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/main.c	2012-03-24 03:33:30.000000000 -0400
@@ -539,6 +539,43 @@
 	return 0;
 }
 
+/**
+ * @brief This function gets the HW spec from the firmware and sets
+ *        some basic parameters.
+ *
+ *  @param priv    A pointer to struct lbs_private structure
+ *  @return        0 or -1
+ */
+static int lbs_setup_firmware(struct lbs_private *priv)
+{
+	int ret = -1;
+	s16 curlevel = 0, minlevel = 0, maxlevel = 0;
+
+	lbs_deb_enter(LBS_DEB_FW);
+
+	/* Read MAC address from firmware */
+	memset(priv->current_addr, 0xff, ETH_ALEN);
+	ret = lbs_update_hw_spec(priv);
+	if (ret)
+		goto done;
+
+	/* Read power levels if available */
+	ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
+	if (ret == 0) {
+		priv->txpower_cur = curlevel;
+		priv->txpower_min = minlevel;
+		priv->txpower_max = maxlevel;
+	}
+
+	/* Send cmd to FW to enable 11D function */
+	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
+
+	lbs_set_mac_control(priv);
+done:
+	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
+	return ret;
+}
+
 int lbs_suspend(struct lbs_private *priv)
 {
 	int ret;
@@ -584,47 +621,13 @@
 			lbs_pr_err("deep sleep activation failed: %d\n", ret);
 	}
 
-	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
-	return ret;
-}
-EXPORT_SYMBOL_GPL(lbs_resume);
-
-/**
- * @brief This function gets the HW spec from the firmware and sets
- *        some basic parameters.
- *
- *  @param priv    A pointer to struct lbs_private structure
- *  @return 	   0 or -1
- */
-static int lbs_setup_firmware(struct lbs_private *priv)
-{
-	int ret = -1;
-	s16 curlevel = 0, minlevel = 0, maxlevel = 0;
-
-	lbs_deb_enter(LBS_DEB_FW);
-
-	/* Read MAC address from firmware */
-	memset(priv->current_addr, 0xff, ETH_ALEN);
-	ret = lbs_update_hw_spec(priv);
-	if (ret)
-		goto done;
-
-	/* Read power levels if available */
-	ret = lbs_get_tx_power(priv, &curlevel, &minlevel, &maxlevel);
-	if (ret == 0) {
-		priv->txpower_cur = curlevel;
-		priv->txpower_min = minlevel;
-		priv->txpower_max = maxlevel;
-	}
-
-	/* Send cmd to FW to enable 11D function */
-	ret = lbs_set_snmp_mib(priv, SNMP_MIB_OID_11D_ENABLE, 1);
+	if (priv->setup_fw_on_resume)
+		ret = lbs_setup_firmware(priv);
 
-	lbs_set_mac_control(priv);
-done:
 	lbs_deb_leave_args(LBS_DEB_FW, "ret %d", ret);
 	return ret;
 }
+EXPORT_SYMBOL_GPL(lbs_resume);
 
 /**
  *  This function handles the timeout of command sending.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/mesh.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/mesh.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/mesh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/mesh.c	2011-05-19 00:06:34.000000000 -0400
@@ -918,7 +918,6 @@
 			   char *buf)
 {
 	struct mrvl_mesh_defaults defs;
-	int maxlen;
 	int ret;
 
 	ret = mesh_get_default_parameters(dev, &defs);
@@ -931,13 +930,11 @@
 		defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
 	}
 
-	/* SSID not null terminated: reserve room for \0 + \n */
-	maxlen = defs.meshie.val.mesh_id_len + 2;
-	maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
-
-	defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
+	memcpy(buf, defs.meshie.val.mesh_id, defs.meshie.val.mesh_id_len);
+	buf[defs.meshie.val.mesh_id_len] = '\n';
+	buf[defs.meshie.val.mesh_id_len + 1] = '\0';
 
-	return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
+	return defs.meshie.val.mesh_id_len + 1;
 }
 
 /**
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/README linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/README
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas/README	2012-03-24 01:13:08.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas/README	2012-03-24 03:33:42.000000000 -0400
@@ -70,7 +70,7 @@
 	These commands are used to read the MAC, BBP and RF registers from the
 	card.  These commands take one parameter that specifies the offset
 	location that is to be read.  This parameter must be specified in
-	hexadecimal (its possible to preceed preceding the number with a "0x").
+	hexadecimal (its possible to precede preceding the number with a "0x").
 
 	Path: /sys/kernel/debug/libertas_wireless/ethX/registers/
 
@@ -84,7 +84,7 @@
 	These commands are used to write the MAC, BBP and RF registers in the
 	card.  These commands take two parameters that specify the offset
 	location and the value that is to be written. This parameters must
-	be specified in hexadecimal (its possible to preceed the number
+	be specified in hexadecimal (its possible to precede the number
 	with a "0x").
 
 	Usage:
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/libertas_tf/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/libertas_tf/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/libertas_tf/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/libertas_tf/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,7 +225,7 @@
 	lbtf_deb_leave(LBTF_DEB_MAIN);
 }
 
-static int lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void lbtf_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct lbtf_private *priv = hw->priv;
 
@@ -236,7 +236,6 @@
 	 * there are no buffered multicast frames to send
 	 */
 	ieee80211_stop_queues(priv->hw);
-	return NETDEV_TX_OK;
 }
 
 static void lbtf_tx_work(struct work_struct *work)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/mac80211_hwsim.c linux-libre-2.6.39-gnu/drivers/net/wireless/mac80211_hwsim.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/mac80211_hwsim.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/mac80211_hwsim.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
  * 	an intersection to occur but each device will still use their
  * 	respective regulatory requested domains. Subsequent radios will
  * 	use the resulting intersection.
- * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We acomplish
+ * @HWSIM_REGTEST_WORLD_ROAM: Used for testing the world roaming. We accomplish
  *	this by using a custom beacon-capable regulatory domain for the first
  *	radio. All other device world roam.
  * @HWSIM_REGTEST_CUSTOM_WORLD: Used for testing the custom world regulatory
@@ -541,7 +541,7 @@
 }
 
 
-static int mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void mac80211_hwsim_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	bool ack;
 	struct ieee80211_tx_info *txi;
@@ -551,7 +551,7 @@
 	if (skb->len < 10) {
 		/* Should not happen; just a sanity check for addr1 use */
 		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
 	ack = mac80211_hwsim_tx_frame(hw, skb);
@@ -571,7 +571,6 @@
 	if (!(txi->flags & IEEE80211_TX_CTL_NO_ACK) && ack)
 		txi->flags |= IEEE80211_TX_STAT_ACK;
 	ieee80211_tx_status_irqsafe(hw, skb);
-	return NETDEV_TX_OK;
 }
 
 
@@ -943,7 +942,8 @@
 static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
 				       struct ieee80211_vif *vif,
 				       enum ieee80211_ampdu_mlme_action action,
-				       struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+				       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+				       u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_TX_START:
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 obj-$(CONFIG_ZD1211RW)		+= zd1211rw/
 obj-$(CONFIG_RTL8180)		+= rtl818x/
 obj-$(CONFIG_RTL8187)		+= rtl818x/
-obj-$(CONFIG_RTL8192CE)		+= rtlwifi/
+obj-$(CONFIG_RTLWIFI)		+= rtlwifi/
 
 # 16-bit wireless PCMCIA client drivers
 obj-$(CONFIG_PCMCIA_RAYCS)	+= ray_cs.o
@@ -41,7 +41,8 @@
 
 obj-$(CONFIG_MWL8K)	+= mwl8k.o
 
-obj-$(CONFIG_IWLWIFI)	+= iwlwifi/
+obj-$(CONFIG_IWLAGN)	+= iwlwifi/
+obj-$(CONFIG_IWLWIFI_LEGACY)	+= iwlegacy/
 obj-$(CONFIG_RT2X00)	+= rt2x00/
 
 obj-$(CONFIG_P54_COMMON)	+= p54/
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/mwl8k.c linux-libre-2.6.39-gnu/drivers/net/wireless/mwl8k.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/mwl8k.c	2012-03-24 01:13:19.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/mwl8k.c	2012-03-24 03:33:49.000000000 -0400
@@ -137,6 +137,7 @@
 struct mwl8k_priv {
 	struct ieee80211_hw *hw;
 	struct pci_dev *pdev;
+	int irq;
 
 	struct mwl8k_device_info *device_info;
 
@@ -232,6 +233,9 @@
 	struct completion firmware_loading_complete;
 };
 
+#define MAX_WEP_KEY_LEN         13
+#define NUM_WEP_KEYS            4
+
 /* Per interface specific private data */
 struct mwl8k_vif {
 	struct list_head list;
@@ -242,8 +246,21 @@
 
 	/* Non AMPDU sequence number assigned by driver.  */
 	u16 seqno;
+
+	/* Saved WEP keys */
+	struct {
+		u8 enabled;
+		u8 key[sizeof(struct ieee80211_key_conf) + MAX_WEP_KEY_LEN];
+	} wep_key_conf[NUM_WEP_KEYS];
+
+	/* BSSID */
+	u8 bssid[ETH_ALEN];
+
+	/* A flag to indicate is HW crypto is enabled for this bssid */
+	bool is_hw_crypto_enabled;
 };
 #define MWL8K_VIF(_vif) ((struct mwl8k_vif *)&((_vif)->drv_priv))
+#define IEEE80211_KEY_CONF(_u8) ((struct ieee80211_key_conf *)(_u8))
 
 struct mwl8k_sta {
 	/* Index into station database. Returned by UPDATE_STADB.  */
@@ -337,6 +354,7 @@
 #define MWL8K_CMD_SET_RATEADAPT_MODE	0x0203
 #define MWL8K_CMD_BSS_START		0x1100		/* per-vif */
 #define MWL8K_CMD_SET_NEW_STN		0x1111		/* per-vif */
+#define MWL8K_CMD_UPDATE_ENCRYPTION	0x1122		/* per-vif */
 #define MWL8K_CMD_UPDATE_STADB		0x1123
 
 static const char *mwl8k_cmd_name(__le16 cmd, char *buf, int bufsize)
@@ -375,6 +393,7 @@
 		MWL8K_CMDNAME(SET_RATEADAPT_MODE);
 		MWL8K_CMDNAME(BSS_START);
 		MWL8K_CMDNAME(SET_NEW_STN);
+		MWL8K_CMDNAME(UPDATE_ENCRYPTION);
 		MWL8K_CMDNAME(UPDATE_STADB);
 	default:
 		snprintf(buf, bufsize, "0x%x", cmd);
@@ -715,10 +734,12 @@
 		skb_pull(skb, sizeof(*tr) - hdrlen);
 }
 
-static inline void mwl8k_add_dma_header(struct sk_buff *skb)
+static void
+mwl8k_add_dma_header(struct sk_buff *skb, int tail_pad)
 {
 	struct ieee80211_hdr *wh;
 	int hdrlen;
+	int reqd_hdrlen;
 	struct mwl8k_dma_data *tr;
 
 	/*
@@ -730,11 +751,13 @@
 	wh = (struct ieee80211_hdr *)skb->data;
 
 	hdrlen = ieee80211_hdrlen(wh->frame_control);
-	if (hdrlen != sizeof(*tr))
-		skb_push(skb, sizeof(*tr) - hdrlen);
+	reqd_hdrlen = sizeof(*tr);
+
+	if (hdrlen != reqd_hdrlen)
+		skb_push(skb, reqd_hdrlen - hdrlen);
 
 	if (ieee80211_is_data_qos(wh->frame_control))
-		hdrlen -= 2;
+		hdrlen -= IEEE80211_QOS_CTL_LEN;
 
 	tr = (struct mwl8k_dma_data *)skb->data;
 	if (wh != &tr->wh)
@@ -747,9 +770,52 @@
 	 * payload".  That is, everything except for the 802.11 header.
 	 * This includes all crypto material including the MIC.
 	 */
-	tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr));
+	tr->fwlen = cpu_to_le16(skb->len - sizeof(*tr) + tail_pad);
 }
 
+static void mwl8k_encapsulate_tx_frame(struct sk_buff *skb)
+{
+	struct ieee80211_hdr *wh;
+	struct ieee80211_tx_info *tx_info;
+	struct ieee80211_key_conf *key_conf;
+	int data_pad;
+
+	wh = (struct ieee80211_hdr *)skb->data;
+
+	tx_info = IEEE80211_SKB_CB(skb);
+
+	key_conf = NULL;
+	if (ieee80211_is_data(wh->frame_control))
+		key_conf = tx_info->control.hw_key;
+
+	/*
+	 * Make sure the packet header is in the DMA header format (4-address
+	 * without QoS), the necessary crypto padding between the header and the
+	 * payload has already been provided by mac80211, but it doesn't add tail
+	 * padding when HW crypto is enabled.
+	 *
+	 * We have the following trailer padding requirements:
+	 * - WEP: 4 trailer bytes (ICV)
+	 * - TKIP: 12 trailer bytes (8 MIC + 4 ICV)
+	 * - CCMP: 8 trailer bytes (MIC)
+	 */
+	data_pad = 0;
+	if (key_conf != NULL) {
+		switch (key_conf->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+			data_pad = 4;
+			break;
+		case WLAN_CIPHER_SUITE_TKIP:
+			data_pad = 12;
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			data_pad = 8;
+			break;
+		}
+	}
+	mwl8k_add_dma_header(skb, data_pad);
+}
 
 /*
  * Packet reception for 88w8366 AP firmware.
@@ -778,6 +844,13 @@
 
 #define MWL8K_8366_AP_RX_CTRL_OWNED_BY_HOST	0x80
 
+/* 8366 AP rx_status bits */
+#define MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK		0x80
+#define MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR	0xFF
+#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR	0x02
+#define MWL8K_8366_AP_RXSTAT_WEP_DECRYPT_ICV_ERR	0x04
+#define MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_ICV_ERR	0x08
+
 static void mwl8k_rxd_8366_ap_init(void *_rxd, dma_addr_t next_dma_addr)
 {
 	struct mwl8k_rxd_8366_ap *rxd = _rxd;
@@ -834,10 +907,16 @@
 	} else {
 		status->band = IEEE80211_BAND_2GHZ;
 	}
-	status->freq = ieee80211_channel_to_frequency(rxd->channel);
+	status->freq = ieee80211_channel_to_frequency(rxd->channel,
+						      status->band);
 
 	*qos = rxd->qos_control;
 
+	if ((rxd->rx_status != MWL8K_8366_AP_RXSTAT_GENERAL_DECRYPT_ERR) &&
+	    (rxd->rx_status & MWL8K_8366_AP_RXSTAT_DECRYPT_ERR_MASK) &&
+	    (rxd->rx_status & MWL8K_8366_AP_RXSTAT_TKIP_DECRYPT_MIC_ERR))
+		status->flag |= RX_FLAG_MMIC_ERROR;
+
 	return le16_to_cpu(rxd->pkt_len);
 }
 
@@ -876,6 +955,11 @@
 #define MWL8K_STA_RATE_INFO_MCS_FORMAT		0x0001
 
 #define MWL8K_STA_RX_CTRL_OWNED_BY_HOST		0x02
+#define MWL8K_STA_RX_CTRL_DECRYPT_ERROR		0x04
+/* ICV=0 or MIC=1 */
+#define MWL8K_STA_RX_CTRL_DEC_ERR_TYPE		0x08
+/* Key is uploaded only in failure case */
+#define MWL8K_STA_RX_CTRL_KEY_INDEX			0x30
 
 static void mwl8k_rxd_sta_init(void *_rxd, dma_addr_t next_dma_addr)
 {
@@ -931,9 +1015,13 @@
 	} else {
 		status->band = IEEE80211_BAND_2GHZ;
 	}
-	status->freq = ieee80211_channel_to_frequency(rxd->channel);
+	status->freq = ieee80211_channel_to_frequency(rxd->channel,
+						      status->band);
 
 	*qos = rxd->qos_control;
+	if ((rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DECRYPT_ERROR) &&
+	    (rxd->rx_ctrl & MWL8K_STA_RX_CTRL_DEC_ERR_TYPE))
+		status->flag |= RX_FLAG_MMIC_ERROR;
 
 	return le16_to_cpu(rxd->pkt_len);
 }
@@ -969,13 +1057,12 @@
 	}
 	memset(rxq->rxd, 0, size);
 
-	rxq->buf = kmalloc(MWL8K_RX_DESCS * sizeof(*rxq->buf), GFP_KERNEL);
+	rxq->buf = kcalloc(MWL8K_RX_DESCS, sizeof(*rxq->buf), GFP_KERNEL);
 	if (rxq->buf == NULL) {
 		wiphy_err(hw->wiphy, "failed to alloc RX skbuff list\n");
 		pci_free_consistent(priv->pdev, size, rxq->rxd, rxq->rxd_dma);
 		return -ENOMEM;
 	}
-	memset(rxq->buf, 0, MWL8K_RX_DESCS * sizeof(*rxq->buf));
 
 	for (i = 0; i < MWL8K_RX_DESCS; i++) {
 		int desc_size;
@@ -1092,9 +1179,25 @@
 		ieee80211_queue_work(hw, &priv->finalize_join_worker);
 }
 
+static inline struct mwl8k_vif *mwl8k_find_vif_bss(struct list_head *vif_list,
+						   u8 *bssid)
+{
+	struct mwl8k_vif *mwl8k_vif;
+
+	list_for_each_entry(mwl8k_vif,
+			    vif_list, list) {
+		if (memcmp(bssid, mwl8k_vif->bssid,
+			   ETH_ALEN) == 0)
+			return mwl8k_vif;
+	}
+
+	return NULL;
+}
+
 static int rxq_process(struct ieee80211_hw *hw, int index, int limit)
 {
 	struct mwl8k_priv *priv = hw->priv;
+	struct mwl8k_vif *mwl8k_vif = NULL;
 	struct mwl8k_rx_queue *rxq = priv->rxq + index;
 	int processed;
 
@@ -1104,6 +1207,7 @@
 		void *rxd;
 		int pkt_len;
 		struct ieee80211_rx_status status;
+		struct ieee80211_hdr *wh;
 		__le16 qos;
 
 		skb = rxq->buf[rxq->head].skb;
@@ -1130,8 +1234,7 @@
 
 		rxq->rxd_count--;
 
-		skb_put(skb, pkt_len);
-		mwl8k_remove_dma_header(skb, qos);
+		wh = &((struct mwl8k_dma_data *)skb->data)->wh;
 
 		/*
 		 * Check for a pending join operation.  Save a
@@ -1141,6 +1244,46 @@
 		if (mwl8k_capture_bssid(priv, (void *)skb->data))
 			mwl8k_save_beacon(hw, skb);
 
+		if (ieee80211_has_protected(wh->frame_control)) {
+
+			/* Check if hw crypto has been enabled for
+			 * this bss. If yes, set the status flags
+			 * accordingly
+			 */
+			mwl8k_vif = mwl8k_find_vif_bss(&priv->vif_list,
+								wh->addr1);
+
+			if (mwl8k_vif != NULL &&
+			    mwl8k_vif->is_hw_crypto_enabled == true) {
+				/*
+				 * When MMIC ERROR is encountered
+				 * by the firmware, payload is
+				 * dropped and only 32 bytes of
+				 * mwl8k Firmware header is sent
+				 * to the host.
+				 *
+				 * We need to add four bytes of
+				 * key information.  In it
+				 * MAC80211 expects keyidx set to
+				 * 0 for triggering Counter
+				 * Measure of MMIC failure.
+				 */
+				if (status.flag & RX_FLAG_MMIC_ERROR) {
+					struct mwl8k_dma_data *tr;
+					tr = (struct mwl8k_dma_data *)skb->data;
+					memset((void *)&(tr->data), 0, 4);
+					pkt_len += 4;
+				}
+
+				if (!ieee80211_is_auth(wh->frame_control))
+					status.flag |= RX_FLAG_IV_STRIPPED |
+						       RX_FLAG_DECRYPTED |
+						       RX_FLAG_MMIC_STRIPPED;
+			}
+		}
+
+		skb_put(skb, pkt_len);
+		mwl8k_remove_dma_header(skb, qos);
 		memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
 		ieee80211_rx_irqsafe(hw, skb);
 
@@ -1204,13 +1347,12 @@
 	}
 	memset(txq->txd, 0, size);
 
-	txq->skb = kmalloc(MWL8K_TX_DESCS * sizeof(*txq->skb), GFP_KERNEL);
+	txq->skb = kcalloc(MWL8K_TX_DESCS, sizeof(*txq->skb), GFP_KERNEL);
 	if (txq->skb == NULL) {
 		wiphy_err(hw->wiphy, "failed to alloc TX skbuff list\n");
 		pci_free_consistent(priv->pdev, size, txq->txd, txq->txd_dma);
 		return -ENOMEM;
 	}
-	memset(txq->skb, 0, MWL8K_TX_DESCS * sizeof(*txq->skb));
 
 	for (i = 0; i < MWL8K_TX_DESCS; i++) {
 		struct mwl8k_tx_desc *tx_desc;
@@ -1392,6 +1534,13 @@
 
 		info = IEEE80211_SKB_CB(skb);
 		ieee80211_tx_info_clear_status(info);
+
+		/* Rate control is happening in the firmware.
+		 * Ensure no tx rate is being reported.
+		 */
+                info->status.rates[0].idx = -1;
+                info->status.rates[0].count = 1;
+
 		if (MWL8K_TXD_SUCCESS(status))
 			info->flags |= IEEE80211_TX_STAT_ACK;
 
@@ -1423,7 +1572,7 @@
 	txq->txd = NULL;
 }
 
-static int
+static void
 mwl8k_txq_xmit(struct ieee80211_hw *hw, int index, struct sk_buff *skb)
 {
 	struct mwl8k_priv *priv = hw->priv;
@@ -1443,7 +1592,11 @@
 	else
 		qos = 0;
 
-	mwl8k_add_dma_header(skb);
+	if (priv->ap_fw)
+		mwl8k_encapsulate_tx_frame(skb);
+	else
+		mwl8k_add_dma_header(skb, 0);
+
 	wh = &((struct mwl8k_dma_data *)skb->data)->wh;
 
 	tx_info = IEEE80211_SKB_CB(skb);
@@ -1481,7 +1634,7 @@
 		wiphy_debug(hw->wiphy,
 			    "failed to dma map skb, dropping TX frame.\n");
 		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
 	spin_lock_bh(&priv->tx_lock);
@@ -1518,8 +1671,6 @@
 	mwl8k_tx_start(priv);
 
 	spin_unlock_bh(&priv->tx_lock);
-
-	return NETDEV_TX_OK;
 }
 
 
@@ -1974,8 +2125,18 @@
 	cmd->ps_cookie = cpu_to_le32(priv->cookie_dma);
 	cmd->rx_queue_ptr = cpu_to_le32(priv->rxq[0].rxd_dma);
 	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].txd_dma);
+
+	/*
+	 * Mac80211 stack has Q0 as highest priority and Q3 as lowest in
+	 * that order. Firmware has Q3 as highest priority and Q0 as lowest
+	 * in that order. Map Q3 of mac80211 to Q0 of firmware so that the
+	 * priority is interpreted the right way in firmware.
+	 */
+	for (i = 0; i < MWL8K_TX_QUEUES; i++) {
+		int j = MWL8K_TX_QUEUES - 1 - i;
+		cmd->tx_queue_ptrs[i] = cpu_to_le32(priv->txq[j].txd_dma);
+	}
+
 	cmd->flags = cpu_to_le32(MWL8K_SET_HW_SPEC_FLAG_HOST_DECR_MGMT |
 				 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_PROBERESP |
 				 MWL8K_SET_HW_SPEC_FLAG_HOSTFORM_BEACON);
@@ -3099,6 +3260,274 @@
 }
 
 /*
+ * CMD_UPDATE_ENCRYPTION.
+ */
+
+#define MAX_ENCR_KEY_LENGTH	16
+#define MIC_KEY_LENGTH		8
+
+struct mwl8k_cmd_update_encryption {
+	struct mwl8k_cmd_pkt header;
+
+	__le32 action;
+	__le32 reserved;
+	__u8 mac_addr[6];
+	__u8 encr_type;
+
+} __attribute__((packed));
+
+struct mwl8k_cmd_set_key {
+	struct mwl8k_cmd_pkt header;
+
+	__le32 action;
+	__le32 reserved;
+	__le16 length;
+	__le16 key_type_id;
+	__le32 key_info;
+	__le32 key_id;
+	__le16 key_len;
+	__u8 key_material[MAX_ENCR_KEY_LENGTH];
+	__u8 tkip_tx_mic_key[MIC_KEY_LENGTH];
+	__u8 tkip_rx_mic_key[MIC_KEY_LENGTH];
+	__le16 tkip_rsc_low;
+	__le32 tkip_rsc_high;
+	__le16 tkip_tsc_low;
+	__le32 tkip_tsc_high;
+	__u8 mac_addr[6];
+} __attribute__((packed));
+
+enum {
+	MWL8K_ENCR_ENABLE,
+	MWL8K_ENCR_SET_KEY,
+	MWL8K_ENCR_REMOVE_KEY,
+	MWL8K_ENCR_SET_GROUP_KEY,
+};
+
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_WEP	0
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_DISABLE	1
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_TKIP	4
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED	7
+#define MWL8K_UPDATE_ENCRYPTION_TYPE_AES	8
+
+enum {
+	MWL8K_ALG_WEP,
+	MWL8K_ALG_TKIP,
+	MWL8K_ALG_CCMP,
+};
+
+#define MWL8K_KEY_FLAG_TXGROUPKEY	0x00000004
+#define MWL8K_KEY_FLAG_PAIRWISE		0x00000008
+#define MWL8K_KEY_FLAG_TSC_VALID	0x00000040
+#define MWL8K_KEY_FLAG_WEP_TXKEY	0x01000000
+#define MWL8K_KEY_FLAG_MICKEY_VALID	0x02000000
+
+static int mwl8k_cmd_update_encryption_enable(struct ieee80211_hw *hw,
+					      struct ieee80211_vif *vif,
+					      u8 *addr,
+					      u8 encr_type)
+{
+	struct mwl8k_cmd_update_encryption *cmd;
+	int rc;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
+	cmd->header.length = cpu_to_le16(sizeof(*cmd));
+	cmd->action = cpu_to_le32(MWL8K_ENCR_ENABLE);
+	memcpy(cmd->mac_addr, addr, ETH_ALEN);
+	cmd->encr_type = encr_type;
+
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+	kfree(cmd);
+
+	return rc;
+}
+
+static int mwl8k_encryption_set_cmd_info(struct mwl8k_cmd_set_key *cmd,
+						u8 *addr,
+						struct ieee80211_key_conf *key)
+{
+	cmd->header.code = cpu_to_le16(MWL8K_CMD_UPDATE_ENCRYPTION);
+	cmd->header.length = cpu_to_le16(sizeof(*cmd));
+	cmd->length = cpu_to_le16(sizeof(*cmd) -
+				offsetof(struct mwl8k_cmd_set_key, length));
+	cmd->key_id = cpu_to_le32(key->keyidx);
+	cmd->key_len = cpu_to_le16(key->keylen);
+	memcpy(cmd->mac_addr, addr, ETH_ALEN);
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		cmd->key_type_id = cpu_to_le16(MWL8K_ALG_WEP);
+		if (key->keyidx == 0)
+			cmd->key_info =	cpu_to_le32(MWL8K_KEY_FLAG_WEP_TXKEY);
+
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		cmd->key_type_id = cpu_to_le16(MWL8K_ALG_TKIP);
+		cmd->key_info =	(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+			? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
+			: cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
+		cmd->key_info |= cpu_to_le32(MWL8K_KEY_FLAG_MICKEY_VALID
+						| MWL8K_KEY_FLAG_TSC_VALID);
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		cmd->key_type_id = cpu_to_le16(MWL8K_ALG_CCMP);
+		cmd->key_info =	(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+			? cpu_to_le32(MWL8K_KEY_FLAG_PAIRWISE)
+			: cpu_to_le32(MWL8K_KEY_FLAG_TXGROUPKEY);
+		break;
+	default:
+		return -ENOTSUPP;
+	}
+
+	return 0;
+}
+
+static int mwl8k_cmd_encryption_set_key(struct ieee80211_hw *hw,
+						struct ieee80211_vif *vif,
+						u8 *addr,
+						struct ieee80211_key_conf *key)
+{
+	struct mwl8k_cmd_set_key *cmd;
+	int rc;
+	int keymlen;
+	u32 action;
+	u8 idx;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
+	if (rc < 0)
+		goto done;
+
+	idx = key->keyidx;
+
+	if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE)
+		action = MWL8K_ENCR_SET_KEY;
+	else
+		action = MWL8K_ENCR_SET_GROUP_KEY;
+
+	switch (key->cipher) {
+	case WLAN_CIPHER_SUITE_WEP40:
+	case WLAN_CIPHER_SUITE_WEP104:
+		if (!mwl8k_vif->wep_key_conf[idx].enabled) {
+			memcpy(mwl8k_vif->wep_key_conf[idx].key, key,
+						sizeof(*key) + key->keylen);
+			mwl8k_vif->wep_key_conf[idx].enabled = 1;
+		}
+
+		keymlen = 0;
+		action = MWL8K_ENCR_SET_KEY;
+		break;
+	case WLAN_CIPHER_SUITE_TKIP:
+		keymlen = MAX_ENCR_KEY_LENGTH + 2 * MIC_KEY_LENGTH;
+		break;
+	case WLAN_CIPHER_SUITE_CCMP:
+		keymlen = key->keylen;
+		break;
+	default:
+		rc = -ENOTSUPP;
+		goto done;
+	}
+
+	memcpy(cmd->key_material, key->key, keymlen);
+	cmd->action = cpu_to_le32(action);
+
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+done:
+	kfree(cmd);
+
+	return rc;
+}
+
+static int mwl8k_cmd_encryption_remove_key(struct ieee80211_hw *hw,
+						struct ieee80211_vif *vif,
+						u8 *addr,
+						struct ieee80211_key_conf *key)
+{
+	struct mwl8k_cmd_set_key *cmd;
+	int rc;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (cmd == NULL)
+		return -ENOMEM;
+
+	rc = mwl8k_encryption_set_cmd_info(cmd, addr, key);
+	if (rc < 0)
+		goto done;
+
+	if (key->cipher == WLAN_CIPHER_SUITE_WEP40 ||
+			WLAN_CIPHER_SUITE_WEP104)
+		mwl8k_vif->wep_key_conf[key->keyidx].enabled = 0;
+
+	cmd->action = cpu_to_le32(MWL8K_ENCR_REMOVE_KEY);
+
+	rc = mwl8k_post_pervif_cmd(hw, vif, &cmd->header);
+done:
+	kfree(cmd);
+
+	return rc;
+}
+
+static int mwl8k_set_key(struct ieee80211_hw *hw,
+			 enum set_key_cmd cmd_param,
+			 struct ieee80211_vif *vif,
+			 struct ieee80211_sta *sta,
+			 struct ieee80211_key_conf *key)
+{
+	int rc = 0;
+	u8 encr_type;
+	u8 *addr;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+
+	if (vif->type == NL80211_IFTYPE_STATION)
+		return -EOPNOTSUPP;
+
+	if (sta == NULL)
+		addr = hw->wiphy->perm_addr;
+	else
+		addr = sta->addr;
+
+	if (cmd_param == SET_KEY) {
+		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
+		rc = mwl8k_cmd_encryption_set_key(hw, vif, addr, key);
+		if (rc)
+			goto out;
+
+		if ((key->cipher == WLAN_CIPHER_SUITE_WEP40)
+				|| (key->cipher == WLAN_CIPHER_SUITE_WEP104))
+			encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_WEP;
+		else
+			encr_type = MWL8K_UPDATE_ENCRYPTION_TYPE_MIXED;
+
+		rc = mwl8k_cmd_update_encryption_enable(hw, vif, addr,
+								encr_type);
+		if (rc)
+			goto out;
+
+		mwl8k_vif->is_hw_crypto_enabled = true;
+
+	} else {
+		rc = mwl8k_cmd_encryption_remove_key(hw, vif, addr, key);
+
+		if (rc)
+			goto out;
+
+		mwl8k_vif->is_hw_crypto_enabled = false;
+
+	}
+out:
+	return rc;
+}
+
+/*
  * CMD_UPDATE_STADB.
  */
 struct ewc_ht_info {
@@ -3310,22 +3739,19 @@
 /*
  * Core driver operations.
  */
-static int mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void mwl8k_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct mwl8k_priv *priv = hw->priv;
 	int index = skb_get_queue_mapping(skb);
-	int rc;
 
 	if (!priv->radio_on) {
 		wiphy_debug(hw->wiphy,
 			    "dropped TX frame since radio disabled\n");
 		dev_kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
-	rc = mwl8k_txq_xmit(hw, index, skb);
-
-	return rc;
+	mwl8k_txq_xmit(hw, index, skb);
 }
 
 static int mwl8k_start(struct ieee80211_hw *hw)
@@ -3336,9 +3762,11 @@
 	rc = request_irq(priv->pdev->irq, mwl8k_interrupt,
 			 IRQF_SHARED, MWL8K_NAME, hw);
 	if (rc) {
+		priv->irq = -1;
 		wiphy_err(hw->wiphy, "failed to register IRQ handler\n");
 		return -EIO;
 	}
+	priv->irq = priv->pdev->irq;
 
 	/* Enable TX reclaim and RX tasklets.  */
 	tasklet_enable(&priv->poll_tx_task);
@@ -3375,6 +3803,7 @@
 	if (rc) {
 		iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
 		free_irq(priv->pdev->irq, hw);
+		priv->irq = -1;
 		tasklet_disable(&priv->poll_tx_task);
 		tasklet_disable(&priv->poll_rx_task);
 	}
@@ -3393,7 +3822,10 @@
 
 	/* Disable interrupts */
 	iowrite32(0, priv->regs + MWL8K_HIU_A2H_INTERRUPT_MASK);
-	free_irq(priv->pdev->irq, hw);
+	if (priv->irq != -1) {
+		free_irq(priv->pdev->irq, hw);
+		priv->irq = -1;
+	}
 
 	/* Stop finalize join worker */
 	cancel_work_sync(&priv->finalize_join_worker);
@@ -3469,6 +3901,8 @@
 	mwl8k_vif->vif = vif;
 	mwl8k_vif->macid = macid;
 	mwl8k_vif->seqno = 0;
+	memcpy(mwl8k_vif->bssid, vif->addr, ETH_ALEN);
+	mwl8k_vif->is_hw_crypto_enabled = false;
 
 	/* Set the mac address.  */
 	mwl8k_cmd_set_mac_addr(hw, vif, vif->addr);
@@ -3528,9 +3962,13 @@
 		if (rc)
 			goto out;
 
-		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x7);
-		if (!rc)
-			rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
+		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_RX, 0x3);
+		if (rc)
+			wiphy_warn(hw->wiphy, "failed to set # of RX antennas");
+		rc = mwl8k_cmd_rf_antenna(hw, MWL8K_RF_ANTENNA_TX, 0x7);
+		if (rc)
+			wiphy_warn(hw->wiphy, "failed to set # of TX antennas");
+
 	} else {
 		rc = mwl8k_cmd_rf_tx_power(hw, conf->power_level);
 		if (rc)
@@ -3866,18 +4304,27 @@
 {
 	struct mwl8k_priv *priv = hw->priv;
 	int ret;
+	int i;
+	struct mwl8k_vif *mwl8k_vif = MWL8K_VIF(vif);
+	struct ieee80211_key_conf *key;
 
 	if (!priv->ap_fw) {
 		ret = mwl8k_cmd_update_stadb_add(hw, vif, sta);
 		if (ret >= 0) {
 			MWL8K_STA(sta)->peer_id = ret;
-			return 0;
+			ret = 0;
 		}
 
-		return ret;
+	} else {
+		ret = mwl8k_cmd_set_new_stn_add(hw, vif, sta);
 	}
 
-	return mwl8k_cmd_set_new_stn_add(hw, vif, sta);
+	for (i = 0; i < NUM_WEP_KEYS; i++) {
+		key = IEEE80211_KEY_CONF(mwl8k_vif->wep_key_conf[i].key);
+		if (mwl8k_vif->wep_key_conf[i].enabled)
+			mwl8k_set_key(hw, SET_KEY, vif, sta, key);
+	}
+	return ret;
 }
 
 static int mwl8k_conf_tx(struct ieee80211_hw *hw, u16 queue,
@@ -3894,12 +4341,14 @@
 		if (!priv->wmm_enabled)
 			rc = mwl8k_cmd_set_wmm_mode(hw, 1);
 
-		if (!rc)
-			rc = mwl8k_cmd_set_edca_params(hw, queue,
+		if (!rc) {
+			int q = MWL8K_TX_QUEUES - 1 - queue;
+			rc = mwl8k_cmd_set_edca_params(hw, q,
 						       params->cw_min,
 						       params->cw_max,
 						       params->aifs,
 						       params->txop);
+		}
 
 		mwl8k_fw_unlock(hw);
 	}
@@ -3932,7 +4381,8 @@
 static int
 mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 		   enum ieee80211_ampdu_mlme_action action,
-		   struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+		   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+		   u8 buf_size)
 {
 	switch (action) {
 	case IEEE80211_AMPDU_RX_START:
@@ -3955,6 +4405,7 @@
 	.bss_info_changed	= mwl8k_bss_info_changed,
 	.prepare_multicast	= mwl8k_prepare_multicast,
 	.configure_filter	= mwl8k_configure_filter,
+	.set_key                = mwl8k_set_key,
 	.set_rts_threshold	= mwl8k_set_rts_threshold,
 	.sta_add		= mwl8k_sta_add,
 	.sta_remove		= mwl8k_sta_remove,
@@ -4326,7 +4777,7 @@
 	hw->queues = MWL8K_TX_QUEUES;
 
 	/* Set rssi values to dBm */
-	hw->flags |= IEEE80211_HW_SIGNAL_DBM;
+	hw->flags |= IEEE80211_HW_SIGNAL_DBM | IEEE80211_HW_HAS_RATE_CONTROL;
 	hw->vif_data_size = sizeof(struct mwl8k_vif);
 	hw->sta_data_size = sizeof(struct mwl8k_sta);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/cfg.c linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/cfg.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/cfg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/cfg.c	2011-05-19 00:06:34.000000000 -0400
@@ -153,6 +153,9 @@
 	priv->scan_request = request;
 
 	err = orinoco_hw_trigger_scan(priv, request->ssids);
+	/* On error the we aren't processing the request */
+	if (err)
+		priv->scan_request = NULL;
 
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/hw.c linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -1031,7 +1031,7 @@
 	else
 		buf.tsc[4] = 0x10;
 
-	/* Wait upto 100ms for tx queue to empty */
+	/* Wait up to 100ms for tx queue to empty */
 	for (k = 100; k > 0; k--) {
 		udelay(1000);
 		ret = hermes_read_wordrec(hw, USER_BAP, HERMES_RID_TXQUEUEEMPTY,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -1376,13 +1376,13 @@
 
 	spin_lock_irqsave(&priv->scan_lock, flags);
 	list_for_each_entry_safe(sd, temp, &priv->scan_list, list) {
-		spin_unlock_irqrestore(&priv->scan_lock, flags);
 
 		buf = sd->buf;
 		len = sd->len;
 		type = sd->type;
 
 		list_del(&sd->list);
+		spin_unlock_irqrestore(&priv->scan_lock, flags);
 		kfree(sd);
 
 		if (len > 0) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/scan.c linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/scan.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/orinoco/scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/orinoco/scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -111,6 +111,11 @@
 
 	freq = ieee80211_dsss_chan_to_freq(le16_to_cpu(bss->a.channel));
 	channel = ieee80211_get_channel(wiphy, freq);
+	if (!channel) {
+		printk(KERN_DEBUG "Invalid channel designation %04X(%04X)",
+			bss->a.channel, freq);
+		return;	/* Then ignore it for now */
+	}
 	timestamp = 0;
 	capability = le16_to_cpu(bss->a.capabilities);
 	beacon_interval = le16_to_cpu(bss->a.beacon_interv);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/eeprom.c linux-libre-2.6.39-gnu/drivers/net/wireless/p54/eeprom.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -55,6 +55,17 @@
 	{ .bitrate = 540, .hw_value = 11, },
 };
 
+static struct p54_rssi_db_entry p54_rssi_default = {
+	/*
+	 * The defaults are taken from usb-logs of the
+	 * vendor driver. So, they should be safe to
+	 * use in case we can't get a match from the
+	 * rssi <-> dBm conversion database.
+	 */
+	.mul = 130,
+	.add = -398,
+};
+
 #define CHAN_HAS_CAL		BIT(0)
 #define CHAN_HAS_LIMIT		BIT(1)
 #define CHAN_HAS_CURVE		BIT(2)
@@ -87,13 +98,27 @@
 	return -1;
 }
 
+static int same_band(u16 freq, u16 freq2)
+{
+	return p54_get_band_from_freq(freq) == p54_get_band_from_freq(freq2);
+}
+
 static int p54_compare_channels(const void *_a,
 				const void *_b)
 {
 	const struct p54_channel_entry *a = _a;
 	const struct p54_channel_entry *b = _b;
 
-	return a->index - b->index;
+	return a->freq - b->freq;
+}
+
+static int p54_compare_rssichan(const void *_a,
+				const void *_b)
+{
+	const struct p54_rssi_db_entry *a = _a;
+	const struct p54_rssi_db_entry *b = _b;
+
+	return a->freq - b->freq;
 }
 
 static int p54_fill_band_bitrates(struct ieee80211_hw *dev,
@@ -145,25 +170,26 @@
 
 	for (i = 0, j = 0; (j < list->band_channel_num[band]) &&
 			   (i < list->entries); i++) {
+		struct p54_channel_entry *chan = &list->channels[i];
 
-		if (list->channels[i].band != band)
+		if (chan->band != band)
 			continue;
 
-		if (list->channels[i].data != CHAN_HAS_ALL) {
-			wiphy_err(dev->wiphy,
-				  "%s%s%s is/are missing for channel:%d [%d MHz].\n",
-				  (list->channels[i].data & CHAN_HAS_CAL ? "" :
+		if (chan->data != CHAN_HAS_ALL) {
+			wiphy_err(dev->wiphy, "%s%s%s is/are missing for "
+				  "channel:%d [%d MHz].\n",
+				  (chan->data & CHAN_HAS_CAL ? "" :
 				   " [iqauto calibration data]"),
-				  (list->channels[i].data & CHAN_HAS_LIMIT ? "" :
+				  (chan->data & CHAN_HAS_LIMIT ? "" :
 				   " [output power limits]"),
-				  (list->channels[i].data & CHAN_HAS_CURVE ? "" :
+				  (chan->data & CHAN_HAS_CURVE ? "" :
 				   " [curve data]"),
-				  list->channels[i].index, list->channels[i].freq);
+				  chan->index, chan->freq);
 			continue;
 		}
 
-		tmp->channels[j].band = list->channels[i].band;
-		tmp->channels[j].center_freq = list->channels[i].freq;
+		tmp->channels[j].band = chan->band;
+		tmp->channels[j].center_freq = chan->freq;
 		j++;
 	}
 
@@ -291,7 +317,7 @@
 		}
 	}
 
-	/* sort the list by the channel index */
+	/* sort the channel list by frequency */
 	sort(list->channels, list->entries, sizeof(struct p54_channel_entry),
 	     p54_compare_channels, NULL);
 
@@ -410,33 +436,121 @@
 static const char *p54_rf_chips[] = { "INVALID-0", "Duette3", "Duette2",
 	"Frisbee", "Xbow", "Longbow", "INVALID-6", "INVALID-7" };
 
-static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len,
-			     u16 type)
+static int p54_parse_rssical(struct ieee80211_hw *dev,
+			     u8 *data, int len, u16 type)
 {
 	struct p54_common *priv = dev->priv;
-	int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0;
-	int entry_size = sizeof(struct pda_rssi_cal_entry) + offset;
-	int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
-	int i;
+	struct p54_rssi_db_entry *entry;
+	size_t db_len, entries;
+	int offset = 0, i;
 
-	if (len != (entry_size * num_entries)) {
-		wiphy_err(dev->wiphy,
-			  "unknown rssi calibration data packing type:(%x) len:%d.\n",
-			  type, len);
+	if (type != PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
+		entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2;
+		if (len != sizeof(struct pda_rssi_cal_entry) * entries) {
+			wiphy_err(dev->wiphy, "rssical size mismatch.\n");
+			goto err_data;
+		}
+	} else {
+		/*
+		 * Some devices (Dell 1450 USB, Xbow 5GHz card, etc...)
+		 * have an empty two byte header.
+		 */
+		if (*((__le16 *)&data[offset]) == cpu_to_le16(0))
+			offset += 2;
 
-		print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE,
-				     data, len);
+		entries = (len - offset) /
+			sizeof(struct pda_rssi_cal_ext_entry);
 
-		wiphy_err(dev->wiphy, "please report this issue.\n");
-		return;
+		if ((len - offset) % sizeof(struct pda_rssi_cal_ext_entry) ||
+		    entries <= 0) {
+			wiphy_err(dev->wiphy, "invalid rssi database.\n");
+			goto err_data;
+		}
 	}
 
-	for (i = 0; i < num_entries; i++) {
-		struct pda_rssi_cal_entry *cal = data +
-						 (offset + i * entry_size);
-		priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul);
-		priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add);
+	db_len = sizeof(*entry) * entries;
+	priv->rssi_db = kzalloc(db_len + sizeof(*priv->rssi_db), GFP_KERNEL);
+	if (!priv->rssi_db)
+		return -ENOMEM;
+
+	priv->rssi_db->offset = 0;
+	priv->rssi_db->entries = entries;
+	priv->rssi_db->entry_size = sizeof(*entry);
+	priv->rssi_db->len = db_len;
+
+	entry = (void *)((unsigned long)priv->rssi_db->data + priv->rssi_db->offset);
+	if (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) {
+		struct pda_rssi_cal_ext_entry *cal = (void *) &data[offset];
+
+		for (i = 0; i < entries; i++) {
+			entry[i].freq = le16_to_cpu(cal[i].freq);
+			entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
+			entry[i].add = (s16) le16_to_cpu(cal[i].add);
+		}
+	} else {
+		struct pda_rssi_cal_entry *cal = (void *) &data[offset];
+
+		for (i = 0; i < entries; i++) {
+			u16 freq;
+			switch (i) {
+			case IEEE80211_BAND_2GHZ:
+				freq = 2437;
+				break;
+			case IEEE80211_BAND_5GHZ:
+				freq = 5240;
+				break;
+			}
+
+			entry[i].freq = freq;
+			entry[i].mul = (s16) le16_to_cpu(cal[i].mul);
+			entry[i].add = (s16) le16_to_cpu(cal[i].add);
+		}
 	}
+
+	/* sort the list by channel frequency */
+	sort(entry, entries, sizeof(*entry), p54_compare_rssichan, NULL);
+	return 0;
+
+err_data:
+	wiphy_err(dev->wiphy,
+		  "rssi calibration data packing type:(%x) len:%d.\n",
+		  type, len);
+
+	print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, data, len);
+
+	wiphy_err(dev->wiphy, "please report this issue.\n");
+	return -EINVAL;
+}
+
+struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
+{
+	struct p54_rssi_db_entry *entry;
+	int i, found = -1;
+
+	if (!priv->rssi_db)
+		return &p54_rssi_default;
+
+	entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset);
+	for (i = 0; i < priv->rssi_db->entries; i++) {
+		if (!same_band(freq, entry[i].freq))
+			continue;
+
+		if (found == -1) {
+			found = i;
+			continue;
+		}
+
+		/* nearest match */
+		if (abs(freq - entry[i].freq) <
+		    abs(freq - entry[found].freq)) {
+			found = i;
+			continue;
+		} else {
+			break;
+		}
+	}
+
+	return found < 0 ? &p54_rssi_default : &entry[found];
 }
 
 static void p54_parse_default_country(struct ieee80211_hw *dev,
@@ -627,21 +741,30 @@
 		case PDR_RSSI_LINEAR_APPROXIMATION:
 		case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND:
 		case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED:
-			p54_parse_rssical(dev, entry->data, data_len,
-					  le16_to_cpu(entry->code));
+			err = p54_parse_rssical(dev, entry->data, data_len,
+						le16_to_cpu(entry->code));
+			if (err)
+				goto err;
 			break;
-		case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM: {
-			__le16 *src = (void *) entry->data;
-			s16 *dst = (void *) &priv->rssical_db;
+		case PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2: {
+			struct pda_custom_wrapper *pda = (void *) entry->data;
+			__le16 *src;
+			u16 *dst;
 			int i;
 
-			if (data_len != sizeof(priv->rssical_db)) {
-				err = -EINVAL;
-				goto err;
-			}
-			for (i = 0; i < sizeof(priv->rssical_db) /
-					sizeof(*src); i++)
+			if (priv->rssi_db || data_len < sizeof(*pda))
+				break;
+
+			priv->rssi_db = p54_convert_db(pda, data_len);
+			if (!priv->rssi_db)
+				break;
+
+			src = (void *) priv->rssi_db->data;
+			dst = (void *) priv->rssi_db->data;
+
+			for (i = 0; i < priv->rssi_db->entries; i++)
 				*(dst++) = (s16) le16_to_cpu(*(src++));
+
 			}
 			break;
 		case PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM: {
@@ -717,6 +840,8 @@
 		SET_IEEE80211_PERM_ADDR(dev, perm_addr);
 	}
 
+	priv->cur_rssi = &p54_rssi_default;
+
 	wiphy_info(dev->wiphy, "hwaddr %pM, MAC:isl38%02x RF:%s\n",
 		   dev->wiphy->perm_addr, priv->version,
 		   p54_rf_chips[priv->rxhw]);
@@ -727,9 +852,11 @@
 	kfree(priv->iq_autocal);
 	kfree(priv->output_limit);
 	kfree(priv->curve_data);
+	kfree(priv->rssi_db);
 	priv->iq_autocal = NULL;
 	priv->output_limit = NULL;
 	priv->curve_data = NULL;
+	priv->rssi_db = NULL;
 
 	wiphy_err(dev->wiphy, "eeprom parse failed!\n");
 	return err;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/eeprom.h linux-libre-2.6.39-gnu/drivers/net/wireless/p54/eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -81,6 +81,12 @@
 	u8 data[0];
 } __packed;
 
+struct pda_rssi_cal_ext_entry {
+	__le16 freq;
+	__le16 mul;
+	__le16 add;
+} __packed;
+
 struct pda_rssi_cal_entry {
 	__le16 mul;
 	__le16 add;
@@ -179,6 +185,7 @@
 
 /* used by our modificated eeprom image */
 #define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM		0xDEAD
+#define PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2		0xCAFF
 #define PDR_PRISM_PA_CAL_OUTPUT_POWER_LIMITS_CUSTOM	0xBEEF
 #define PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM		0xB05D
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/fwio.c linux-libre-2.6.39-gnu/drivers/net/wireless/p54/fwio.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/fwio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/fwio.c	2011-05-19 00:06:34.000000000 -0400
@@ -397,9 +397,9 @@
 	union p54_scan_body_union *body;
 	struct p54_scan_tail_rate *rate;
 	struct pda_rssi_cal_entry *rssi;
+	struct p54_rssi_db_entry *rssi_data;
 	unsigned int i;
 	void *entry;
-	int band = priv->hw->conf.channel->band;
 	__le16 freq = cpu_to_le16(priv->hw->conf.channel->center_freq);
 
 	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*head) +
@@ -503,13 +503,14 @@
 	}
 
 	rssi = (struct pda_rssi_cal_entry *) skb_put(skb, sizeof(*rssi));
-	rssi->mul = cpu_to_le16(priv->rssical_db[band].mul);
-	rssi->add = cpu_to_le16(priv->rssical_db[band].add);
+	rssi_data = p54_rssi_find(priv, le16_to_cpu(freq));
+	rssi->mul = cpu_to_le16(rssi_data->mul);
+	rssi->add = cpu_to_le16(rssi_data->add);
 	if (priv->rxhw == PDR_SYNTH_FRONTEND_LONGBOW) {
 		/* Longbow frontend needs ever more */
 		rssi = (void *) skb_put(skb, sizeof(*rssi));
-		rssi->mul = cpu_to_le16(priv->rssical_db[band].longbow_unkn);
-		rssi->add = cpu_to_le16(priv->rssical_db[band].longbow_unk2);
+		rssi->mul = cpu_to_le16(rssi_data->longbow_unkn);
+		rssi->add = cpu_to_le16(rssi_data->longbow_unk2);
 	}
 
 	if (priv->fw_var >= 0x509) {
@@ -523,6 +524,7 @@
 	hdr->len = cpu_to_le16(skb->len - sizeof(*hdr));
 
 	p54_tx(priv, skb);
+	priv->cur_rssi = rssi_data;
 	return 0;
 
 err:
@@ -557,6 +559,7 @@
 {
 	struct sk_buff *skb;
 	struct p54_edcf *edcf;
+	u8 rtd;
 
 	skb = p54_alloc_skb(priv, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*edcf),
 			    P54_CONTROL_TYPE_DCFINIT, GFP_ATOMIC);
@@ -573,9 +576,15 @@
 		edcf->sifs = 0x0a;
 		edcf->eofpad = 0x06;
 	}
+	/*
+	 * calculate the extra round trip delay according to the
+	 * formula from 802.11-2007 17.3.8.6.
+	 */
+	rtd = 3 * priv->coverage_class;
+	edcf->slottime += rtd;
+	edcf->round_trip_delay = cpu_to_le16(rtd);
 	/* (see prism54/isl_oid.h for further details) */
 	edcf->frameburst = cpu_to_le16(0);
-	edcf->round_trip_delay = cpu_to_le16(0);
 	edcf->flags = 0;
 	memset(edcf->mapping, 0, sizeof(edcf->mapping));
 	memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue));
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/p54/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -43,9 +43,8 @@
 	tristate "Prism54 SPI (stlc45xx) support"
 	depends on P54_COMMON && SPI_MASTER && GENERIC_HARDIRQS
 	---help---
-	  This driver is for stlc4550 or stlc4560 based wireless chips.
-	  This driver is experimental, untested and will probably only work on
-	  Nokia's N800/N810 Portable Internet Tablet.
+	  This driver is for stlc4550 or stlc4560 based wireless chips
+	  such as Nokia's N800/N810 Portable Internet Tablet.
 
 	  If you choose to build a module, it'll be called p54spi.
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/lmac.h linux-libre-2.6.39-gnu/drivers/net/wireless/p54/lmac.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/lmac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/lmac.h	2011-05-19 00:06:34.000000000 -0400
@@ -526,7 +526,7 @@
 void p54_unregister_leds(struct p54_common *priv);
 
 /* xmit functions */
-int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb);
+void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb);
 int p54_tx_cancel(struct p54_common *priv, __le32 req_id);
 void p54_tx(struct p54_common *priv, struct sk_buff *skb);
 
@@ -551,6 +551,7 @@
 /* eeprom */
 int p54_download_eeprom(struct p54_common *priv, void *buf,
 			u16 offset, u16 len);
+struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *p, const u16 freq);
 
 /* utility */
 u8 *p54_find_ie(struct sk_buff *skb, u8 ie);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/p54/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -157,7 +157,7 @@
 	 * to cancel the old beacon template by hand, instead the firmware
 	 * will release the previous one through the feedback mechanism.
 	 */
-	WARN_ON(p54_tx_80211(priv->hw, beacon));
+	p54_tx_80211(priv->hw, beacon);
 	priv->tsf_high32 = 0;
 	priv->tsf_low32 = 0;
 
@@ -465,7 +465,7 @@
 
 		if (slot < 0) {
 			/*
-			 * The device supports the choosen algorithm, but the
+			 * The device supports the chosen algorithm, but the
 			 * firmware does not provide enough key slots to store
 			 * all of them.
 			 * But encryption offload for outgoing frames is always
@@ -524,6 +524,59 @@
 	return 0;
 }
 
+static unsigned int p54_flush_count(struct p54_common *priv)
+{
+	unsigned int total = 0, i;
+
+	BUILD_BUG_ON(P54_QUEUE_NUM > ARRAY_SIZE(priv->tx_stats));
+
+	/*
+	 * Because the firmware has the sole control over any frames
+	 * in the P54_QUEUE_BEACON or P54_QUEUE_SCAN queues, they
+	 * don't really count as pending or active.
+	 */
+	for (i = P54_QUEUE_MGMT; i < P54_QUEUE_NUM; i++)
+		total += priv->tx_stats[i].len;
+	return total;
+}
+
+static void p54_flush(struct ieee80211_hw *dev, bool drop)
+{
+	struct p54_common *priv = dev->priv;
+	unsigned int total, i;
+
+	/*
+	 * Currently, it wouldn't really matter if we wait for one second
+	 * or 15 minutes. But once someone gets around and completes the
+	 * TODOs [ancel stuck frames / reset device] in p54_work, it will
+	 * suddenly make sense to wait that long.
+	 */
+	i = P54_STATISTICS_UPDATE * 2 / 20;
+
+	/*
+	 * In this case no locking is required because as we speak the
+	 * queues have already been stopped and no new frames can sneak
+	 * up from behind.
+	 */
+	while ((total = p54_flush_count(priv) && i--)) {
+		/* waste time */
+		msleep(20);
+	}
+
+	WARN(total, "tx flush timeout, unresponsive firmware");
+}
+
+static void p54_set_coverage_class(struct ieee80211_hw *dev, u8 coverage_class)
+{
+	struct p54_common *priv = dev->priv;
+
+	mutex_lock(&priv->conf_mutex);
+	/* support all coverage class values as in 802.11-2007 Table 7-27 */
+	priv->coverage_class = clamp_t(u8, coverage_class, 0, 31);
+	p54_set_edcf(priv);
+	mutex_unlock(&priv->conf_mutex);
+}
+
 static const struct ieee80211_ops p54_ops = {
 	.tx			= p54_tx_80211,
 	.start			= p54_start,
@@ -536,11 +589,13 @@
 	.sta_remove		= p54_sta_add_remove,
 	.set_key		= p54_set_key,
 	.config			= p54_config,
+	.flush			= p54_flush,
 	.bss_info_changed	= p54_bss_info_changed,
 	.configure_filter	= p54_configure_filter,
 	.conf_tx		= p54_conf_tx,
 	.get_stats		= p54_get_stats,
 	.get_survey		= p54_get_survey,
+	.set_coverage_class	= p54_set_coverage_class,
 };
 
 struct ieee80211_hw *p54_init_common(size_t priv_data_len)
@@ -611,7 +666,7 @@
 
 int p54_register_common(struct ieee80211_hw *dev, struct device *pdev)
 {
-	struct p54_common *priv = dev->priv;
+	struct p54_common __maybe_unused *priv = dev->priv;
 	int err;
 
 	err = ieee80211_register_hw(dev);
@@ -642,10 +697,12 @@
 	kfree(priv->iq_autocal);
 	kfree(priv->output_limit);
 	kfree(priv->curve_data);
+	kfree(priv->rssi_db);
 	kfree(priv->used_rxkeys);
 	priv->iq_autocal = NULL;
 	priv->output_limit = NULL;
 	priv->curve_data = NULL;
+	priv->rssi_db = NULL;
 	priv->used_rxkeys = NULL;
 	ieee80211_free_hw(dev);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54.h linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54.h	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,8 @@
 	__le16 txop;
 } __packed;
 
-struct p54_rssi_linear_approximation {
+struct p54_rssi_db_entry {
+	u16 freq;
 	s16 mul;
 	s16 add;
 	s16 longbow_unkn;
@@ -197,13 +198,14 @@
 	u8 rx_diversity_mask;
 	u8 tx_diversity_mask;
 	unsigned int output_power;
+	struct p54_rssi_db_entry *cur_rssi;
 	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 *curve_data;
 	struct p54_cal_database *output_limit;
-	struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS];
+	struct p54_cal_database *rssi_db;
 	struct ieee80211_supported_band *band_table[IEEE80211_NUM_BANDS];
 
 	/* BBP/MAC state */
@@ -215,6 +217,7 @@
 	u32 tsf_low32, tsf_high32;
 	u32 basic_rate_mask;
 	u16 aid;
+	u8 coverage_class;
 	bool powersave_override;
 	__le32 beacon_req_id;
 	struct completion beacon_comp;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54spi.c linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54spi.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54spi.c	2012-03-24 01:13:41.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54spi.c	2012-03-24 03:34:00.000000000 -0400
@@ -287,7 +287,7 @@
 	enable_irq(gpio_to_irq(p54spi_gpio_irq));
 
 	/*
-	 * need to wait a while before device can be accessed, the lenght
+	 * need to wait a while before device can be accessed, the length
 	 * is just a guess
 	 */
 	msleep(10);
@@ -649,8 +649,7 @@
 		goto err_free_common;
 	}
 
-	set_irq_type(gpio_to_irq(p54spi_gpio_irq),
-		     IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(gpio_to_irq(p54spi_gpio_irq), IRQ_TYPE_EDGE_RISING);
 
 	disable_irq(gpio_to_irq(p54spi_gpio_irq));
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54spi_eeprom.h linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54spi_eeprom.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54spi_eeprom.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54spi_eeprom.h	2011-05-19 00:06:34.000000000 -0400
@@ -65,9 +65,10 @@
 0x03, 0x00, 0x00, 0x11,		/* PDR_ANTENNA_GAIN */
 	0x08, 0x08, 0x08, 0x08,
 
-0x09, 0x00, 0xad, 0xde,		/* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOM */
-	0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+0x0a, 0x00, 0xff, 0xca,		/* PDR_RSSI_LINEAR_APPROXIMATION_CUSTOMV2 */
+	0x01, 0x00, 0x0a, 0x00,
+	0x00, 0x00, 0x0a, 0x00,
+		0x85, 0x09, 0x0a, 0x01, 0x72, 0xfe, 0x1a, 0x00, 0x00, 0x00,
 
 /* struct pda_custom_wrapper */
 0x10, 0x06, 0x5d, 0xb0,		/* PDR_PRISM_PA_CAL_CURVE_DATA_CUSTOM */
@@ -671,7 +672,7 @@
 	0xa8, 0x09, 0x25, 0x00, 0xf5, 0xff, 0xf9, 0xff, 0x00, 0x01,
 
 0x02, 0x00, 0x00, 0x00,		/* PDR_END */
-	0x67, 0x99,
+	0xb6, 0x04,
 };
 
 #endif /* P54SPI_EEPROM_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/p54usb.c	2012-03-24 01:13:46.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/p54usb.c	2012-03-24 03:34:03.000000000 -0400
@@ -55,6 +55,7 @@
 	{USB_DEVICE(0x0846, 0x4210)},	/* Netgear WG121 the second ? */
 	{USB_DEVICE(0x0846, 0x4220)},	/* Netgear WG111 */
 	{USB_DEVICE(0x09aa, 0x1000)},	/* Spinnaker Proto board */
+	{USB_DEVICE(0x0bf8, 0x1007)},	/* Fujitsu E-5400 USB */
 	{USB_DEVICE(0x0cde, 0x0006)},	/* Medion 40900, Roper Europe */
 	{USB_DEVICE(0x0db0, 0x6826)},	/* MSI UB54G (MS-6826) */
 	{USB_DEVICE(0x107b, 0x55f2)},	/* Gateway WGU-210 (Gemtek) */
@@ -67,6 +68,7 @@
 	{USB_DEVICE(0x1915, 0x2235)},	/* Linksys WUSB54G Portable OEM */
 	{USB_DEVICE(0x2001, 0x3701)},	/* DLink DWL-G120 Spinnaker */
 	{USB_DEVICE(0x2001, 0x3703)},	/* DLink DWL-G122 */
+	{USB_DEVICE(0x2001, 0x3762)},	/* Conceptronic C54U */
 	{USB_DEVICE(0x5041, 0x2234)},	/* Linksys WUSB54G */
 	{USB_DEVICE(0x5041, 0x2235)},	/* Linksys WUSB54G Portable */
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/p54/txrx.c linux-libre-2.6.39-gnu/drivers/net/wireless/p54/txrx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/p54/txrx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/p54/txrx.c	2011-05-19 00:06:34.000000000 -0400
@@ -273,11 +273,9 @@
 
 static int p54_rssi_to_dbm(struct p54_common *priv, int rssi)
 {
-	int band = priv->hw->conf.channel->band;
-
 	if (priv->rxhw != 5) {
-		return ((rssi * priv->rssical_db[band].mul) / 64 +
-			 priv->rssical_db[band].add) / 4;
+		return ((rssi * priv->cur_rssi->mul) / 64 +
+			 priv->cur_rssi->add) / 4;
 	} else {
 		/*
 		 * TODO: find the correct formula
@@ -369,7 +367,7 @@
 	rx_status->mactime = ((u64)priv->tsf_high32) << 32 | tsf32;
 	priv->tsf_low32 = tsf32;
 
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	if (hdr->flags & cpu_to_le16(P54_HDR_FLAG_DATA_ALIGN))
 		header_len += hdr->align[0];
@@ -698,14 +696,14 @@
 	}
 }
 
-int p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
+void p54_tx_80211(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct p54_common *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct p54_tx_info *p54info;
 	struct p54_hdr *hdr;
 	struct p54_tx_data *txhdr;
-	unsigned int padding, len, extra_len;
+	unsigned int padding, len, extra_len = 0;
 	int i, j, ridx;
 	u16 hdr_flags = 0, aid = 0;
 	u8 rate, queue = 0, crypt_offset = 0;
@@ -719,12 +717,8 @@
 			    &hdr_flags, &aid, &burst_allowed);
 
 	if (p54_tx_qos_accounting_alloc(priv, skb, queue)) {
-		if (!IS_QOS_QUEUE(queue)) {
-			dev_kfree_skb_any(skb);
-			return NETDEV_TX_OK;
-		} else {
-			return NETDEV_TX_BUSY;
-		}
+		dev_kfree_skb_any(skb);
+		return;
 	}
 
 	padding = (unsigned long)(skb->data - (sizeof(*hdr) + sizeof(*txhdr))) & 3;
@@ -867,5 +861,4 @@
 	p54info->extra_len = extra_len;
 
 	p54_tx(priv, skb);
-	return NETDEV_TX_OK;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/prism54/islpci_eth.c linux-libre-2.6.39-gnu/drivers/net/wireless/prism54/islpci_eth.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/prism54/islpci_eth.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/prism54/islpci_eth.c	2011-05-19 00:06:34.000000000 -0400
@@ -113,7 +113,7 @@
 	 * be aligned on a 4-byte boundary. If WDS is enabled add another 6 bytes
 	 * and add WDS address information */
 	if (likely(((long) skb->data & 0x03) | init_wds)) {
-		/* get the number of bytes to add and re-allign */
+		/* get the number of bytes to add and re-align */
 		offset = (4 - (long) skb->data) & 0x03;
 		offset += init_wds ? 6 : 0;
 
@@ -342,7 +342,7 @@
 			 priv->pci_map_rx_address[index],
 			 MAX_FRAGMENT_SIZE_RX + 2, PCI_DMA_FROMDEVICE);
 
-	/* update the skb structure and allign the buffer */
+	/* update the skb structure and align the buffer */
 	skb_put(skb, size);
 	if (offset) {
 		/* shift the buffer allocation offset bytes to get the right frame */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rayctl.h linux-libre-2.6.39-gnu/drivers/net/wireless/rayctl.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rayctl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rayctl.h	2011-05-19 00:06:34.000000000 -0400
@@ -578,7 +578,7 @@
     UCHAR  var[1];
 };
 
-/****** ECF Receive Control Stucture (RCS) Area at Shared RAM offset 0x0800  */
+/****** ECF Receive Control Structure (RCS) Area at Shared RAM offset 0x0800  */
 /* Structures for command specific parameters (rcs.var) */
 struct rx_packet_cmd {
     UCHAR rx_data_ptr[2];
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -97,6 +97,18 @@
 	  Support for these devices is non-functional at the moment and is
 	  intended for testers and developers.
 
+config RT2800PCI_RT53XX
+       bool "rt2800-pci - Include support for rt53xx devices (EXPERIMENTAL)"
+       depends on EXPERIMENTAL
+       default n
+       ---help---
+         This adds support for rt53xx wireless chipset family to the
+         rt2800pci driver.
+         Supported chips: RT5390
+
+         Support for these devices is non-functional at the moment and is
+         intended for testers and developers.
+
 endif
 
 config RT2500USB
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2400pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2400pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2400pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2400pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
  * 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,
+ * between each attempt. When the busy bit is still set at that time,
  * the access attempt is considered to have failed,
  * and we will print an error.
  */
@@ -305,9 +305,7 @@
 		 * Enable synchronisation.
 		 */
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 	}
 
@@ -647,6 +645,11 @@
 		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow the tbtt tasklet to be scheduled.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
 		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -708,6 +711,11 @@
 		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
 		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
+		/*
+		 * Wait for possibly running tbtt tasklets.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
 		break;
 	default:
 		break;
@@ -771,7 +779,7 @@
 	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
 	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
+	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
 	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
 
@@ -787,13 +795,13 @@
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
 
-	entry_priv = rt2x00dev->bcn[1].entries[0].priv_data;
+	entry_priv = rt2x00dev->atim->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
 	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
 
-	entry_priv = rt2x00dev->bcn[0].entries[0].priv_data;
+	entry_priv = rt2x00dev->bcn->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
 	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
 			   entry_priv->desc_dma);
@@ -963,9 +971,9 @@
 static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF) ||
-		   (state == STATE_RADIO_IRQ_OFF_ISR);
+	int mask = (state == STATE_RADIO_IRQ_OFF);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -974,12 +982,20 @@
 	if (state == STATE_RADIO_IRQ_ON) {
 		rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
 		rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+
+		/*
+		 * Enable tasklets.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
 	}
 
 	/*
 	 * Only toggle the interrupts bits we are going to use.
 	 * Non-checked interrupt bits are disabled by default.
 	 */
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
 	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
 	rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
 	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
@@ -987,6 +1003,17 @@
 	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
 	rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
 	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished before
+		 * disabling the interrupts.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+	}
 }
 
 static int rt2400pci_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1059,9 +1086,7 @@
 		rt2400pci_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2400pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1106,19 +1131,21 @@
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 3, &word);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_REGNUM, 5);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL_BUSY, 1);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_REGNUM, 6);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE_BUSY, 1);
 	rt2x00_desc_write(txd, 3, word);
 
 	rt2x00_desc_read(txd, 4, &word);
-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW, txdesc->length_low);
+	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_REGNUM, 8);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW_BUSY, 1);
-	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W4_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_REGNUM, 7);
 	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH_BUSY, 1);
 	rt2x00_desc_write(txd, 4, word);
@@ -1139,7 +1166,7 @@
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_RTS,
 			   test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_desc_write(txd, 0, word);
@@ -1183,8 +1210,6 @@
 	/*
 	 * Enable beaconing again.
 	 */
-	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-	rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
@@ -1253,7 +1278,7 @@
 static void rt2400pci_txdone(struct rt2x00_dev *rt2x00dev,
 			     const enum data_queue_qid queue_idx)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 	struct queue_entry_priv_pci *entry_priv;
 	struct queue_entry *entry;
 	struct txdone_entry_desc txdesc;
@@ -1289,57 +1314,68 @@
 	}
 }
 
-static irqreturn_t rt2400pci_interrupt_thread(int irq, void *dev_instance)
+static void rt2400pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg;
 
 	/*
-	 * Handle interrupts, walk through all bits
-	 * and run the tasks, the bits are checked in order of
-	 * priority.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 1 - Beacon timer expired interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
-		rt2x00lib_beacondone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
 
-	/*
-	 * 2 - Rx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_RXDONE))
-		rt2x00pci_rxdone(rt2x00dev);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 3 - Atim ring transmit done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
-		rt2400pci_txdone(rt2x00dev, QID_ATIM);
+static void rt2400pci_txstatus_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	u32 reg;
 
 	/*
-	 * 4 - Priority ring transmit done interrupt.
+	 * Handle all tx queues.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
-		rt2400pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2400pci_txdone(rt2x00dev, QID_ATIM);
+	rt2400pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2400pci_txdone(rt2x00dev, QID_AC_VI);
 
 	/*
-	 * 5 - Tx ring transmit done interrupt.
+	 * Enable all TXDONE interrupts again.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
-		rt2400pci_txdone(rt2x00dev, QID_AC_VI);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
-	return IRQ_HANDLED;
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt2400pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+}
+
+static void rt2400pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
 }
 
 static irqreturn_t rt2400pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
+	u32 reg, mask;
 
 	/*
 	 * Get the interrupt sources & saved to local variable.
@@ -1354,14 +1390,44 @@
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalues for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
+	mask = reg;
 
-	/* Disable interrupts, will be enabled again in the interrupt thread. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_OFF_ISR);
+	/*
+	 * Schedule tasklets for interrupt handling.
+	 */
+	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
 
-	return IRQ_WAKE_THREAD;
+	if (rt2x00_get_field32(reg, CSR7_RXDONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
+		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+		/*
+		 * Mask out all txdone interrupts.
+		 */
+		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
+	}
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	reg |= mask;
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -1574,6 +1640,7 @@
 	 */
 	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1655,7 +1722,9 @@
 
 static const struct rt2x00lib_ops rt2400pci_rt2x00_ops = {
 	.irq_handler		= rt2400pci_interrupt,
-	.irq_handler_thread	= rt2400pci_interrupt_thread,
+	.txstatus_tasklet	= rt2400pci_txstatus_tasklet,
+	.tbtt_tasklet		= rt2400pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt2400pci_rxdone_tasklet,
 	.probe_hw		= rt2400pci_probe_hw,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2500pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2500pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2500pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2500pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -293,7 +293,7 @@
 				  struct rt2x00intf_conf *conf,
 				  const unsigned int flags)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
+	struct data_queue *queue = rt2x00dev->bcn;
 	unsigned int bcn_preload;
 	u32 reg;
 
@@ -311,9 +311,7 @@
 		 * Enable synchronisation.
 		 */
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
-		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 	}
 
@@ -737,6 +735,11 @@
 		rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow the tbtt tasklet to be scheduled.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+
 		rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
 		rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
 		rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -798,6 +801,11 @@
 		rt2x00_set_field32(&reg, CSR14_TBCN, 0);
 		rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 0);
 		rt2x00pci_register_write(rt2x00dev, CSR14, reg);
+
+		/*
+		 * Wait for possibly running tbtt tasklets.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
 		break;
 	default:
 		break;
@@ -857,7 +865,7 @@
 	rt2x00pci_register_read(rt2x00dev, TXCSR2, &reg);
 	rt2x00_set_field32(&reg, TXCSR2_TXD_SIZE, rt2x00dev->tx[0].desc_size);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_TXD, rt2x00dev->tx[1].limit);
-	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->bcn[1].limit);
+	rt2x00_set_field32(&reg, TXCSR2_NUM_ATIM, rt2x00dev->atim->limit);
 	rt2x00_set_field32(&reg, TXCSR2_NUM_PRIO, rt2x00dev->tx[0].limit);
 	rt2x00pci_register_write(rt2x00dev, TXCSR2, reg);
 
@@ -873,13 +881,13 @@
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR5, reg);
 
-	entry_priv = rt2x00dev->bcn[1].entries[0].priv_data;
+	entry_priv = rt2x00dev->atim->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR4, &reg);
 	rt2x00_set_field32(&reg, TXCSR4_ATIM_RING_REGISTER,
 			   entry_priv->desc_dma);
 	rt2x00pci_register_write(rt2x00dev, TXCSR4, reg);
 
-	entry_priv = rt2x00dev->bcn[0].entries[0].priv_data;
+	entry_priv = rt2x00dev->bcn->entries[0].priv_data;
 	rt2x00pci_register_read(rt2x00dev, TXCSR6, &reg);
 	rt2x00_set_field32(&reg, TXCSR6_BEACON_RING_REGISTER,
 			   entry_priv->desc_dma);
@@ -1118,9 +1126,9 @@
 static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF) ||
-		   (state == STATE_RADIO_IRQ_OFF_ISR);
+	int mask = (state == STATE_RADIO_IRQ_OFF);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -1129,12 +1137,20 @@
 	if (state == STATE_RADIO_IRQ_ON) {
 		rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
 		rt2x00pci_register_write(rt2x00dev, CSR7, reg);
+
+		/*
+		 * Enable tasklets.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
 	}
 
 	/*
 	 * Only toggle the interrupts bits we are going to use.
 	 * Non-checked interrupt bits are disabled by default.
 	 */
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
 	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
 	rt2x00_set_field32(&reg, CSR8_TBCN_EXPIRE, mask);
 	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, mask);
@@ -1142,6 +1158,16 @@
 	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, mask);
 	rt2x00_set_field32(&reg, CSR8_RXDONE, mask);
 	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+	}
 }
 
 static int rt2500pci_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1214,9 +1240,7 @@
 		rt2500pci_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2500pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1263,10 +1287,12 @@
 	rt2x00_desc_write(txd, 2, word);
 
 	rt2x00_desc_read(txd, 3, &word);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W3_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 3, word);
 
 	rt2x00_desc_read(txd, 10, &word);
@@ -1291,7 +1317,7 @@
 	rt2x00_set_field32(&word, TXD_W0_OFDM,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
 	rt2x00_set_field32(&word, TXD_W0_CIPHER_OWNER, 1);
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
@@ -1337,8 +1363,6 @@
 	/*
 	 * Enable beaconing again.
 	 */
-	rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
-	rt2x00_set_field32(&reg, CSR14_TBCN, 1);
 	rt2x00_set_field32(&reg, CSR14_BEACON_GEN, 1);
 	rt2x00pci_register_write(rt2x00dev, CSR14, reg);
 }
@@ -1386,7 +1410,7 @@
 static void rt2500pci_txdone(struct rt2x00_dev *rt2x00dev,
 			     const enum data_queue_qid queue_idx)
 {
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	struct data_queue *queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 	struct queue_entry_priv_pci *entry_priv;
 	struct queue_entry *entry;
 	struct txdone_entry_desc txdesc;
@@ -1422,58 +1446,68 @@
 	}
 }
 
-static irqreturn_t rt2500pci_interrupt_thread(int irq, void *dev_instance)
+static void rt2500pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg;
 
 	/*
-	 * Handle interrupts, walk through all bits
-	 * and run the tasks, the bits are checked in order of
-	 * priority.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 1 - Beacon timer expired interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
-		rt2x00lib_beacondone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
 
-	/*
-	 * 2 - Rx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_RXDONE))
-		rt2x00pci_rxdone(rt2x00dev);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 3 - Atim ring transmit done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING))
-		rt2500pci_txdone(rt2x00dev, QID_ATIM);
+static void rt2500pci_txstatus_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	u32 reg;
 
 	/*
-	 * 4 - Priority ring transmit done interrupt.
+	 * Handle all tx queues.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING))
-		rt2500pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2500pci_txdone(rt2x00dev, QID_ATIM);
+	rt2500pci_txdone(rt2x00dev, QID_AC_VO);
+	rt2500pci_txdone(rt2x00dev, QID_AC_VI);
 
 	/*
-	 * 5 - Tx ring transmit done interrupt.
+	 * Enable all TXDONE interrupts again.
 	 */
-	if (rt2x00_get_field32(reg, CSR7_TXDONE_TXRING))
-		rt2500pci_txdone(rt2x00dev, QID_AC_VI);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
+	rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
 
-	return IRQ_HANDLED;
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
+
+static void rt2500pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
+}
+
+static void rt2500pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
 }
 
 static irqreturn_t rt2500pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
+	u32 reg, mask;
 
 	/*
 	 * Get the interrupt sources & saved to local variable.
@@ -1488,14 +1522,42 @@
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalues for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
+	mask = reg;
 
-	/* Disable interrupts, will be enabled again in the interrupt thread. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_OFF_ISR);
+	/*
+	 * Schedule tasklets for interrupt handling.
+	 */
+	if (rt2x00_get_field32(reg, CSR7_TBCN_EXPIRE))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
 
-	return IRQ_WAKE_THREAD;
+	if (rt2x00_get_field32(reg, CSR7_RXDONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
+
+	if (rt2x00_get_field32(reg, CSR7_TXDONE_ATIMRING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_PRIORING) ||
+	    rt2x00_get_field32(reg, CSR7_TXDONE_TXRING)) {
+		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+		/*
+		 * Mask out all txdone interrupts.
+		 */
+		rt2x00_set_field32(&mask, CSR8_TXDONE_TXRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_ATIMRING, 1);
+		rt2x00_set_field32(&mask, CSR8_TXDONE_PRIORING, 1);
+	}
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
+	reg |= mask;
+	rt2x00pci_register_write(rt2x00dev, CSR8, reg);
+
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -1896,6 +1958,7 @@
 	 */
 	__set_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
 	__set_bit(DRIVER_REQUIRE_DMA, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -1952,7 +2015,9 @@
 
 static const struct rt2x00lib_ops rt2500pci_rt2x00_ops = {
 	.irq_handler		= rt2500pci_interrupt,
-	.irq_handler_thread	= rt2500pci_interrupt_thread,
+	.txstatus_tasklet	= rt2500pci_txstatus_tasklet,
+	.tbtt_tasklet		= rt2500pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt2500pci_rxdone_tasklet,
 	.probe_hw		= rt2500pci_probe_hw,
 	.initialize		= rt2x00pci_initialize,
 	.uninitialize		= rt2x00pci_uninitialize,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2500usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2500usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2500usb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2500usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -478,9 +478,7 @@
 		rt2500usb_register_write(rt2x00dev, TXRX_CSR18, reg);
 
 		rt2500usb_register_read(rt2x00dev, TXRX_CSR19, &reg);
-		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_COUNT, 1);
 		rt2x00_set_field16(&reg, TXRX_CSR19_TSF_SYNC, conf->sync);
-		rt2x00_set_field16(&reg, TXRX_CSR19_TBCN, 1);
 		rt2500usb_register_write(rt2x00dev, TXRX_CSR19, reg);
 	}
 
@@ -1056,9 +1054,7 @@
 		rt2500usb_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1104,7 +1100,7 @@
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
 	rt2x00_set_field32(&word, TXD_W0_NEW_SEQ,
 			   test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_DATABYTE_COUNT, txdesc->length);
 	rt2x00_set_field32(&word, TXD_W0_CIPHER, !!txdesc->cipher);
 	rt2x00_set_field32(&word, TXD_W0_KEY_ID, txdesc->key_idx);
@@ -1118,10 +1114,12 @@
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
@@ -1799,6 +1797,7 @@
 		__set_bit(DRIVER_REQUIRE_COPY_IV, &rt2x00dev->flags);
 	}
 	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_SW_SEQNO, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800.h	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,7 @@
  * RF3320 2.4G 1T1R(RT3350/RT3370/RT3390)
  * RF3322 2.4G 2T2R(RT3352/RT3371/RT3372/RT3391/RT3392)
  * RF3853 2.4G/5G 3T3R(RT3883/RT3563/RT3573/RT3593/RT3662)
+ * RF5390 2.4G 1T1R
  */
 #define RF2820				0x0001
 #define RF2850				0x0002
@@ -65,6 +66,7 @@
 #define RF3320				0x000b
 #define RF3322				0x000c
 #define RF3853				0x000d
+#define RF5390				0x5390
 
 /*
  * Chipset revisions.
@@ -77,6 +79,7 @@
 #define REV_RT3071E			0x0211
 #define REV_RT3090E			0x0211
 #define REV_RT3390E			0x0211
+#define REV_RT5390F			0x0502
 
 /*
  * Signal information.
@@ -121,6 +124,13 @@
 #define E2PROM_CSR_RELOAD		FIELD32(0x00000080)
 
 /*
+ * AUX_CTRL: Aux/PCI-E related configuration
+ */
+#define AUX_CTRL			0x10c
+#define AUX_CTRL_WAKE_PCIE_EN		FIELD32(0x00000002)
+#define AUX_CTRL_FORCE_PCIE_CLK		FIELD32(0x00000400)
+
+/*
  * OPT_14: Unknown register used by rt3xxx devices.
  */
 #define OPT_14_CSR			0x0114
@@ -270,6 +280,7 @@
 
 /*
  * GPIO_CTRL_CFG:
+ * GPIOD: GPIO direction, 0: Output, 1: Input
  */
 #define GPIO_CTRL_CFG			0x0228
 #define GPIO_CTRL_CFG_BIT0		FIELD32(0x00000001)
@@ -280,7 +291,14 @@
 #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)
+#define GPIO_CTRL_CFG_GPIOD_BIT0	FIELD32(0x00000100)
+#define GPIO_CTRL_CFG_GPIOD_BIT1	FIELD32(0x00000200)
+#define GPIO_CTRL_CFG_GPIOD_BIT2	FIELD32(0x00000400)
+#define GPIO_CTRL_CFG_GPIOD_BIT3	FIELD32(0x00000800)
+#define GPIO_CTRL_CFG_GPIOD_BIT4	FIELD32(0x00001000)
+#define GPIO_CTRL_CFG_GPIOD_BIT5	FIELD32(0x00002000)
+#define GPIO_CTRL_CFG_GPIOD_BIT6	FIELD32(0x00004000)
+#define GPIO_CTRL_CFG_GPIOD_BIT7	FIELD32(0x00008000)
 
 /*
  * MCU_CMD_CFG
@@ -372,8 +390,12 @@
 
 /*
  * US_CYC_CNT
+ * BT_MODE_EN: Bluetooth mode enable
+ * CLOCK CYCLE: Clock cycle count in 1us.
+ * PCI:0x21, PCIE:0x7d, USB:0x1e
  */
 #define US_CYC_CNT			0x02a4
+#define US_CYC_CNT_BT_MODE_EN		FIELD32(0x00000100)
 #define US_CYC_CNT_CLOCK_CYCLE		FIELD32(0x000000ff)
 
 /*
@@ -442,7 +464,7 @@
  */
 #define	RF_CSR_CFG			0x0500
 #define RF_CSR_CFG_DATA			FIELD32(0x000000ff)
-#define RF_CSR_CFG_REGNUM		FIELD32(0x00001f00)
+#define RF_CSR_CFG_REGNUM		FIELD32(0x00003f00)
 #define RF_CSR_CFG_WRITE		FIELD32(0x00010000)
 #define RF_CSR_CFG_BUSY			FIELD32(0x00020000)
 
@@ -594,7 +616,7 @@
  * 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
+ * BBP_RW_MODE: 0 serial, 1 parallel
  */
 #define BBP_CSR_CFG			0x101c
 #define BBP_CSR_CFG_VALUE		FIELD32(0x000000ff)
@@ -1132,8 +1154,8 @@
  * 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
+ * PROTECT_NAV_SHORT: TXOP protection type for CCK TX with short NAV
+ * PROTECT_NAV_LONG: TXOP protection type for CCK TX with long NAV
  * 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
@@ -1145,7 +1167,8 @@
 #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_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define CCK_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #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)
@@ -1160,7 +1183,8 @@
 #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_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define OFDM_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #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)
@@ -1175,7 +1199,8 @@
 #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_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define MM20_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #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)
@@ -1190,7 +1215,8 @@
 #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_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define MM40_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #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)
@@ -1205,7 +1231,8 @@
 #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_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define GF20_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #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)
@@ -1220,7 +1247,8 @@
 #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_PROTECT_NAV_SHORT	FIELD32(0x00040000)
+#define GF40_PROT_CFG_PROTECT_NAV_LONG	FIELD32(0x00080000)
 #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)
@@ -1697,11 +1725,14 @@
  */
 
 /*
- * BBP 1: TX Antenna & Power
- * POWER: 0 - normal, 1 - drop tx power by 6dBm, 2 - drop tx power by 12dBm,
- *	3 - increase tx power by 6dBm
+ * BBP 1: TX Antenna & Power Control
+ * POWER_CTRL:
+ * 0 - normal,
+ * 1 - drop tx power by 6dBm,
+ * 2 - drop tx power by 12dBm,
+ * 3 - increase tx power by 6dBm
  */
-#define BBP1_TX_POWER			FIELD8(0x07)
+#define BBP1_TX_POWER_CTRL		FIELD8(0x07)
 #define BBP1_TX_ANTENNA			FIELD8(0x18)
 
 /*
@@ -1715,6 +1746,13 @@
  */
 #define BBP4_TX_BF			FIELD8(0x01)
 #define BBP4_BANDWIDTH			FIELD8(0x18)
+#define BBP4_MAC_IF_CTRL		FIELD8(0x40)
+
+/*
+ * BBP 109
+ */
+#define BBP109_TX0_POWER		FIELD8(0x0f)
+#define BBP109_TX1_POWER		FIELD8(0xf0)
 
 /*
  * BBP 138: Unknown
@@ -1725,6 +1763,11 @@
 #define BBP138_TX_DAC2			FIELD8(0x40)
 
 /*
+ * BBP 152: Rx Ant
+ */
+#define BBP152_RX_DEFAULT_ANT		FIELD8(0x80)
+
+/*
  * RFCSR registers
  * The wordsize of the RFCSR is 8 bits.
  */
@@ -1733,12 +1776,18 @@
  * RFCSR 1:
  */
 #define RFCSR1_RF_BLOCK_EN		FIELD8(0x01)
+#define RFCSR1_PLL_PD			FIELD8(0x02)
 #define RFCSR1_RX0_PD			FIELD8(0x04)
 #define RFCSR1_TX0_PD			FIELD8(0x08)
 #define RFCSR1_RX1_PD			FIELD8(0x10)
 #define RFCSR1_TX1_PD			FIELD8(0x20)
 
 /*
+ * RFCSR 2:
+ */
+#define RFCSR2_RESCAL_EN		FIELD8(0x80)
+
+/*
  * RFCSR 6:
  */
 #define RFCSR6_R1			FIELD8(0x03)
@@ -1750,6 +1799,11 @@
 #define RFCSR7_RF_TUNING		FIELD8(0x01)
 
 /*
+ * RFCSR 11:
+ */
+#define RFCSR11_R			FIELD8(0x03)
+
+/*
  * RFCSR 12:
  */
 #define RFCSR12_TX_POWER		FIELD8(0x1f)
@@ -1770,6 +1824,7 @@
 #define RFCSR17_TXMIXER_GAIN		FIELD8(0x07)
 #define RFCSR17_TX_LO1_EN		FIELD8(0x08)
 #define RFCSR17_R			FIELD8(0x20)
+#define RFCSR17_CODE                   FIELD8(0x7f)
 
 /*
  * RFCSR 20:
@@ -1802,9 +1857,33 @@
 /*
  * RFCSR 30:
  */
+#define RFCSR30_TX_H20M			FIELD8(0x02)
+#define RFCSR30_RX_H20M			FIELD8(0x04)
+#define RFCSR30_RX_VCM			FIELD8(0x18)
 #define RFCSR30_RF_CALIBRATION		FIELD8(0x80)
 
 /*
+ * RFCSR 31:
+ */
+#define RFCSR31_RX_AGC_FC		FIELD8(0x1f)
+#define RFCSR31_RX_H20M			FIELD8(0x20)
+
+/*
+ * RFCSR 38:
+ */
+#define RFCSR38_RX_LO1_EN		FIELD8(0x20)
+
+/*
+ * RFCSR 39:
+ */
+#define RFCSR39_RX_LO2_EN		FIELD8(0x80)
+
+/*
+ * RFCSR 49:
+ */
+#define RFCSR49_TX			FIELD8(0x3f)
+
+/*
  * RF registers
  */
 
@@ -1837,6 +1916,11 @@
  */
 
 /*
+ * Chip ID
+ */
+#define EEPROM_CHIP_ID			0x0000
+
+/*
  * EEPROM Version
  */
 #define EEPROM_VERSION			0x0001
@@ -1989,23 +2073,26 @@
 #define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)
 
 /*
- * EEPROM Maximum TX power values
+ * EEPROM EIRP Maximum TX power values(unit: dbm)
  */
-#define EEPROM_MAX_TX_POWER		0x0027
-#define EEPROM_MAX_TX_POWER_24GHZ	FIELD16(0x00ff)
-#define EEPROM_MAX_TX_POWER_5GHZ	FIELD16(0xff00)
+#define EEPROM_EIRP_MAX_TX_POWER	0x0027
+#define EEPROM_EIRP_MAX_TX_POWER_2GHZ	FIELD16(0x00ff)
+#define EEPROM_EIRP_MAX_TX_POWER_5GHZ	FIELD16(0xff00)
 
 /*
  * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
  * This is delta in 40MHZ.
- * VALUE: Tx Power dalta value (MAX=4)
+ * VALUE: Tx Power dalta value, MAX=4(unit: dbm)
  * TYPE: 1: Plus the delta value, 0: minus the delta value
- * TXPOWER: Enable:
+ * ENABLE: enable tx power compensation for 40BW
  */
 #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)
+#define EEPROM_TXPOWER_DELTA_VALUE_2G	FIELD16(0x003f)
+#define EEPROM_TXPOWER_DELTA_TYPE_2G	FIELD16(0x0040)
+#define EEPROM_TXPOWER_DELTA_ENABLE_2G	FIELD16(0x0080)
+#define EEPROM_TXPOWER_DELTA_VALUE_5G	FIELD16(0x3f00)
+#define EEPROM_TXPOWER_DELTA_TYPE_5G	FIELD16(0x4000)
+#define EEPROM_TXPOWER_DELTA_ENABLE_5G	FIELD16(0x8000)
 
 /*
  * EEPROM TXPOWER 802.11BG
@@ -2058,6 +2145,7 @@
 #define MCU_LED_LED_POLARITY		0x54
 #define MCU_RADAR			0x60
 #define MCU_BOOT_SIGNAL			0x72
+#define MCU_ANT_SELECT			0X73
 #define MCU_BBP_SIGNAL			0x80
 #define MCU_POWER_SAVE			0x83
 
@@ -2202,4 +2290,9 @@
 #define TXPOWER_A_TO_DEV(__txpower) \
 	clamp_t(char, __txpower, MIN_A_TXPOWER, MAX_A_TXPOWER)
 
+/*
+ *  Board's maximun TX power limitation
+ */
+#define EIRP_MAX_TX_POWER_LIMIT	0x50
+
 #endif /* RT2800_H */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800lib.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800lib.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -400,8 +400,15 @@
 	if (rt2800_wait_csr_ready(rt2x00dev))
 		return -EBUSY;
 
-	if (rt2x00_is_pci(rt2x00dev))
+	if (rt2x00_is_pci(rt2x00dev)) {
+		if (rt2x00_rt(rt2x00dev, RT5390)) {
+			rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+			rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
+			rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
+			rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+		}
 		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000002);
+	}
 
 	/*
 	 * Disable DMA, will be reenabled later when enabling
@@ -465,14 +472,15 @@
 			   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->txop);
-	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->mcs);
+	rt2x00_set_field32(&word, TXWI_W0_MPDU_DENSITY,
+			   txdesc->u.ht.mpdu_density);
+	rt2x00_set_field32(&word, TXWI_W0_TX_OP, txdesc->u.ht.txop);
+	rt2x00_set_field32(&word, TXWI_W0_MCS, txdesc->u.ht.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_STBC, txdesc->u.ht.stbc);
 	rt2x00_set_field32(&word, TXWI_W0_PHYMODE, txdesc->rate_mode);
 	rt2x00_desc_write(txwi, 0, word);
 
@@ -481,7 +489,7 @@
 			   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_BW_WIN_SIZE, txdesc->u.ht.ba_size);
 	rt2x00_set_field32(&word, TXWI_W1_WIRELESS_CLI_ID,
 			   test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags) ?
 			   txdesc->key_idx : 0xff);
@@ -674,7 +682,7 @@
 	 * confuse the rate control algortihm by providing clearly wrong
 	 * data.
 	 */
-	if (aggr == 1 && ampdu == 0 && real_mcs != mcs) {
+	if (unlikely(aggr == 1 && ampdu == 0 && real_mcs != mcs)) {
 		skbdesc->tx_rate_idx = real_mcs;
 		mcs = real_mcs;
 	}
@@ -744,7 +752,7 @@
 		if (pid >= QID_RX)
 			continue;
 
-		queue = rt2x00queue_get_queue(rt2x00dev, pid);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, pid);
 		if (unlikely(!queue))
 			continue;
 
@@ -773,13 +781,14 @@
 	struct skb_frame_desc *skbdesc = get_skb_frame_desc(entry->skb);
 	unsigned int beacon_base;
 	unsigned int padding_len;
-	u32 reg;
+	u32 orig_reg, reg;
 
 	/*
 	 * Disable beaconing while we are reloading the beacon data,
 	 * otherwise we might be sending out invalid data.
 	 */
 	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	orig_reg = reg;
 	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
 	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
@@ -810,7 +819,14 @@
 	 * Write entire beacon with TXWI and padding to register.
 	 */
 	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-	skb_pad(entry->skb, padding_len);
+	if (padding_len && skb_pad(entry->skb, padding_len)) {
+		ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+		/* skb freed by skb_pad() on failure */
+		entry->skb = NULL;
+		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, orig_reg);
+		return;
+	}
+
 	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 	rt2800_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				   entry->skb->len + padding_len);
@@ -818,8 +834,6 @@
 	/*
 	 * Enable beaconing again.
 	 */
-	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);
 	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
 
@@ -831,8 +845,8 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_write_beacon);
 
-static inline void rt2800_clear_beacon(struct rt2x00_dev *rt2x00dev,
-				       unsigned int beacon_base)
+static inline void rt2800_clear_beacon_register(struct rt2x00_dev *rt2x00dev,
+						unsigned int beacon_base)
 {
 	int i;
 
@@ -845,6 +859,33 @@
 		rt2800_register_write(rt2x00dev, beacon_base + i, 0);
 }
 
+void rt2800_clear_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	u32 reg;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+	/*
+	 * Clear beacon.
+	 */
+	rt2800_clear_beacon_register(rt2x00dev,
+				     HW_BEACON_OFFSET(entry->entry_idx));
+
+	/*
+	 * Enabled beaconing again.
+	 */
+	rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 1);
+	rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+}
+EXPORT_SYMBOL_GPL(rt2800_clear_beacon);
+
 #ifdef CONFIG_RT2X00_LIB_DEBUGFS
 const struct rt2x00debug rt2800_rt2x00debug = {
 	.owner	= THIS_MODULE,
@@ -1005,7 +1046,7 @@
 
 	memset(&wcid_entry, 0, sizeof(wcid_entry));
 	if (crypto->cmd == SET_KEY)
-		memcpy(&wcid_entry, crypto->address, ETH_ALEN);
+		memcpy(wcid_entry.mac, crypto->address, ETH_ALEN);
 	rt2800_register_multiwrite(rt2x00dev, offset,
 				      &wcid_entry, sizeof(wcid_entry));
 }
@@ -1060,27 +1101,44 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_config_shared_key);
 
+static inline int rt2800_find_pairwise_keyslot(struct rt2x00_dev *rt2x00dev)
+{
+	int idx;
+	u32 offset, reg;
+
+	/*
+	 * Search for the first free pairwise key entry and return the
+	 * corresponding index.
+	 *
+	 * Make sure the WCID starts _after_ the last possible shared key
+	 * entry (>32).
+	 *
+	 * Since parts of the pairwise key table might be shared with
+	 * the beacon frame buffers 6 & 7 we should only write into the
+	 * first 222 entries.
+	 */
+	for (idx = 33; idx <= 222; idx++) {
+		offset = MAC_WCID_ATTR_ENTRY(idx);
+		rt2800_register_read(rt2x00dev, offset, &reg);
+		if (!reg)
+			return idx;
+	}
+	return -1;
+}
+
 int rt2800_config_pairwise_key(struct rt2x00_dev *rt2x00dev,
 			       struct rt2x00lib_crypto *crypto,
 			       struct ieee80211_key_conf *key)
 {
 	struct hw_key_entry key_entry;
 	u32 offset;
+	int idx;
 
 	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.
-		 *
-		 * Since parts of the pairwise key table might be shared with
-		 * the beacon frame buffers 6 & 7 we should only write into the
-		 * first 222 entries.
-		 */
-		if (crypto->aid > (222 - 32))
+		idx = rt2800_find_pairwise_keyslot(rt2x00dev);
+		if (idx < 0)
 			return -ENOSPC;
-
-		key->hw_key_idx = 32 + crypto->aid;
+		key->hw_key_idx = idx;
 
 		memcpy(key_entry.key, crypto->key,
 		       sizeof(key_entry.key));
@@ -1155,29 +1213,11 @@
 
 	if (flags & CONFIG_UPDATE_TYPE) {
 		/*
-		 * Clear current synchronisation setup.
-		 */
-		rt2800_clear_beacon(rt2x00dev,
-				    HW_BEACON_OFFSET(intf->beacon->entry_idx));
-		/*
 		 * Enable synchronisation.
 		 */
 		rt2800_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,
-				   (conf->sync == TSF_SYNC_ADHOC ||
-				    conf->sync == TSF_SYNC_AP_NONE));
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
-
-		/*
-		 * Enable pre tbtt interrupt for beaconing modes
-		 */
-		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
-		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER,
-				   (conf->sync == TSF_SYNC_AP_NONE));
-		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
-
 	}
 
 	if (flags & CONFIG_UPDATE_MAC) {
@@ -1361,10 +1401,32 @@
 }
 EXPORT_SYMBOL_GPL(rt2800_config_erp);
 
+static void rt2800_set_ant_diversity(struct rt2x00_dev *rt2x00dev,
+				     enum antenna ant)
+{
+	u32 reg;
+	u8 eesk_pin = (ant == ANTENNA_A) ? 1 : 0;
+	u8 gpio_bit3 = (ant == ANTENNA_A) ? 0 : 1;
+
+	if (rt2x00_is_pci(rt2x00dev)) {
+		rt2800_register_read(rt2x00dev, E2PROM_CSR, &reg);
+		rt2x00_set_field32(&reg, E2PROM_CSR_DATA_CLOCK, eesk_pin);
+		rt2800_register_write(rt2x00dev, E2PROM_CSR, reg);
+	} else if (rt2x00_is_usb(rt2x00dev))
+		rt2800_mcu_request(rt2x00dev, MCU_ANT_SELECT, 0xff,
+				   eesk_pin, 0);
+
+	rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+	rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0);
+	rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, gpio_bit3);
+	rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+}
+
 void rt2800_config_ant(struct rt2x00_dev *rt2x00dev, struct antenna_setup *ant)
 {
 	u8 r1;
 	u8 r3;
+	u16 eeprom;
 
 	rt2800_bbp_read(rt2x00dev, 1, &r1);
 	rt2800_bbp_read(rt2x00dev, 3, &r3);
@@ -1372,7 +1434,7 @@
 	/*
 	 * Configure the TX antenna.
 	 */
-	switch ((int)ant->tx) {
+	switch (ant->tx_chain_num) {
 	case 1:
 		rt2x00_set_field8(&r1, BBP1_TX_ANTENNA, 0);
 		break;
@@ -1387,8 +1449,18 @@
 	/*
 	 * Configure the RX antenna.
 	 */
-	switch ((int)ant->rx) {
+	switch (ant->rx_chain_num) {
 	case 1:
+		if (rt2x00_rt(rt2x00dev, RT3070) ||
+		    rt2x00_rt(rt2x00dev, RT3090) ||
+		    rt2x00_rt(rt2x00dev, RT3390)) {
+			rt2x00_eeprom_read(rt2x00dev,
+					   EEPROM_NIC_CONF1, &eeprom);
+			if (rt2x00_get_field16(eeprom,
+						EEPROM_NIC_CONF1_ANT_DIVERSITY))
+				rt2800_set_ant_diversity(rt2x00dev,
+						rt2x00dev->default_ant.rx);
+		}
 		rt2x00_set_field8(&r3, BBP3_RX_ANTENNA, 0);
 		break;
 	case 2:
@@ -1434,19 +1506,19 @@
 {
 	rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
 
-	if (rt2x00dev->default_ant.tx == 1)
+	if (rt2x00dev->default_ant.tx_chain_num == 1)
 		rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_TX1, 1);
 
-	if (rt2x00dev->default_ant.rx == 1) {
+	if (rt2x00dev->default_ant.rx_chain_num == 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)
+	} else if (rt2x00dev->default_ant.rx_chain_num == 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).
+		 * make it a positive value (Minimum value is -7).
 		 * However this means that values between 0 and 7 have
 		 * double meaning, and we should set a 7DBm boost flag.
 		 */
@@ -1526,6 +1598,105 @@
 	rt2800_rfcsr_write(rt2x00dev, 7, rfcsr);
 }
 
+
+#define RT5390_POWER_BOUND     0x27
+#define RT5390_FREQ_OFFSET_BOUND       0x5f
+
+static void rt2800_config_channel_rf53xx(struct rt2x00_dev *rt2x00dev,
+					 struct ieee80211_conf *conf,
+					 struct rf_channel *rf,
+					 struct channel_info *info)
+{
+	u8 rfcsr;
+	u16 eeprom;
+
+	rt2800_rfcsr_write(rt2x00dev, 8, rf->rf1);
+	rt2800_rfcsr_write(rt2x00dev, 9, rf->rf3);
+	rt2800_rfcsr_read(rt2x00dev, 11, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR11_R, rf->rf2);
+	rt2800_rfcsr_write(rt2x00dev, 11, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 49, &rfcsr);
+	if (info->default_power1 > RT5390_POWER_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, RT5390_POWER_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR49_TX, info->default_power1);
+	rt2800_rfcsr_write(rt2x00dev, 49, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 1, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RF_BLOCK_EN, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_PLL_PD, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_RX0_PD, 1);
+	rt2x00_set_field8(&rfcsr, RFCSR1_TX0_PD, 1);
+	rt2800_rfcsr_write(rt2x00dev, 1, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+	if (rt2x00dev->freq_offset > RT5390_FREQ_OFFSET_BOUND)
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE,
+				  RT5390_FREQ_OFFSET_BOUND);
+	else
+		rt2x00_set_field8(&rfcsr, RFCSR17_CODE, rt2x00dev->freq_offset);
+	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+	if (rf->channel <= 14) {
+		int idx = rf->channel-1;
+
+		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) {
+			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+				/* r55/r59 value array of channel 1~14 */
+				static const char r55_bt_rev[] = {0x83, 0x83,
+					0x83, 0x73, 0x73, 0x63, 0x53, 0x53,
+					0x53, 0x43, 0x43, 0x43, 0x43, 0x43};
+				static const char r59_bt_rev[] = {0x0e, 0x0e,
+					0x0e, 0x0e, 0x0e, 0x0b, 0x0a, 0x09,
+					0x07, 0x07, 0x07, 0x07, 0x07, 0x07};
+
+				rt2800_rfcsr_write(rt2x00dev, 55,
+						   r55_bt_rev[idx]);
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_bt_rev[idx]);
+			} else {
+				static const char r59_bt[] = {0x8b, 0x8b, 0x8b,
+					0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x89,
+					0x88, 0x88, 0x86, 0x85, 0x84};
+
+				rt2800_rfcsr_write(rt2x00dev, 59, r59_bt[idx]);
+			}
+		} else {
+			if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F)) {
+				static const char r55_nonbt_rev[] = {0x23, 0x23,
+					0x23, 0x23, 0x13, 0x13, 0x03, 0x03,
+					0x03, 0x03, 0x03, 0x03, 0x03, 0x03};
+				static const char r59_nonbt_rev[] = {0x07, 0x07,
+					0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
+					0x07, 0x07, 0x06, 0x05, 0x04, 0x04};
+
+				rt2800_rfcsr_write(rt2x00dev, 55,
+						   r55_nonbt_rev[idx]);
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_nonbt_rev[idx]);
+			} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+				static const char r59_non_bt[] = {0x8f, 0x8f,
+					0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8d,
+					0x8a, 0x88, 0x88, 0x87, 0x87, 0x86};
+
+				rt2800_rfcsr_write(rt2x00dev, 59,
+						   r59_non_bt[idx]);
+			}
+		}
+	}
+
+	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_TX_H20M, 0);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RX_H20M, 0);
+	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+
+	rt2800_rfcsr_read(rt2x00dev, 3, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+	rt2800_rfcsr_write(rt2x00dev, 3, rfcsr);
+}
+
 static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
 				  struct ieee80211_conf *conf,
 				  struct rf_channel *rf,
@@ -1550,6 +1721,8 @@
 	    rt2x00_rf(rt2x00dev, RF3052) ||
 	    rt2x00_rf(rt2x00dev, RF3320))
 		rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
+	else if (rt2x00_rf(rt2x00dev, RF5390))
+		rt2800_config_channel_rf53xx(rt2x00dev, conf, rf, info);
 	else
 		rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
 
@@ -1562,12 +1735,15 @@
 	rt2800_bbp_write(rt2x00dev, 86, 0);
 
 	if (rf->channel <= 14) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags)) {
-			rt2800_bbp_write(rt2x00dev, 82, 0x62);
-			rt2800_bbp_write(rt2x00dev, 75, 0x46);
-		} else {
-			rt2800_bbp_write(rt2x00dev, 82, 0x84);
-			rt2800_bbp_write(rt2x00dev, 75, 0x50);
+		if (!rt2x00_rt(rt2x00dev, RT5390)) {
+			if (test_bit(CONFIG_EXTERNAL_LNA_BG,
+				     &rt2x00dev->flags)) {
+				rt2800_bbp_write(rt2x00dev, 82, 0x62);
+				rt2800_bbp_write(rt2x00dev, 75, 0x46);
+			} else {
+				rt2800_bbp_write(rt2x00dev, 82, 0x84);
+				rt2800_bbp_write(rt2x00dev, 75, 0x50);
+			}
 		}
 	} else {
 		rt2800_bbp_write(rt2x00dev, 82, 0xf2);
@@ -1587,13 +1763,13 @@
 	tx_pin = 0;
 
 	/* Turn on unused PA or LNA when not using 1T or 1R */
-	if (rt2x00dev->default_ant.tx != 1) {
+	if (rt2x00dev->default_ant.tx_chain_num == 2) {
 		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) {
+	if (rt2x00dev->default_ant.rx_chain_num == 2) {
 		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);
 	}
@@ -1637,30 +1813,116 @@
 	rt2800_register_read(rt2x00dev, CH_BUSY_STA_SEC, &reg);
 }
 
+static int rt2800_get_txpower_bw_comp(struct rt2x00_dev *rt2x00dev,
+				      enum ieee80211_band band)
+{
+	u16 eeprom;
+	u8 comp_en;
+	u8 comp_type;
+	int comp_value;
+
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_DELTA, &eeprom);
+
+	if (eeprom == 0xffff)
+		return 0;
+
+	if (band == IEEE80211_BAND_2GHZ) {
+		comp_en = rt2x00_get_field16(eeprom,
+				 EEPROM_TXPOWER_DELTA_ENABLE_2G);
+		if (comp_en) {
+			comp_type = rt2x00_get_field16(eeprom,
+					   EEPROM_TXPOWER_DELTA_TYPE_2G);
+			comp_value = rt2x00_get_field16(eeprom,
+					    EEPROM_TXPOWER_DELTA_VALUE_2G);
+			if (!comp_type)
+				comp_value = -comp_value;
+		}
+	} else {
+		comp_en = rt2x00_get_field16(eeprom,
+				 EEPROM_TXPOWER_DELTA_ENABLE_5G);
+		if (comp_en) {
+			comp_type = rt2x00_get_field16(eeprom,
+					   EEPROM_TXPOWER_DELTA_TYPE_5G);
+			comp_value = rt2x00_get_field16(eeprom,
+					    EEPROM_TXPOWER_DELTA_VALUE_5G);
+			if (!comp_type)
+				comp_value = -comp_value;
+		}
+	}
+
+	return comp_value;
+}
+
+static u8 rt2800_compesate_txpower(struct rt2x00_dev *rt2x00dev,
+				     int is_rate_b,
+				     enum ieee80211_band band,
+				     int power_level,
+				     u8 txpower)
+{
+	u32 reg;
+	u16 eeprom;
+	u8 criterion;
+	u8 eirp_txpower;
+	u8 eirp_txpower_criterion;
+	u8 reg_limit;
+	int bw_comp = 0;
+
+	if (!((band == IEEE80211_BAND_5GHZ) && is_rate_b))
+		return txpower;
+
+	if (test_bit(CONFIG_CHANNEL_HT40, &rt2x00dev->flags))
+		bw_comp = rt2800_get_txpower_bw_comp(rt2x00dev, band);
+
+	if (test_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags)) {
+		/*
+		 * Check if eirp txpower exceed txpower_limit.
+		 * We use OFDM 6M as criterion and its eirp txpower
+		 * is stored at EEPROM_EIRP_MAX_TX_POWER.
+		 * .11b data rate need add additional 4dbm
+		 * when calculating eirp txpower.
+		 */
+		rt2800_register_read(rt2x00dev, TX_PWR_CFG_0, &reg);
+		criterion = rt2x00_get_field32(reg, TX_PWR_CFG_0_6MBS);
+
+		rt2x00_eeprom_read(rt2x00dev,
+				   EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+
+		if (band == IEEE80211_BAND_2GHZ)
+			eirp_txpower_criterion = rt2x00_get_field16(eeprom,
+						 EEPROM_EIRP_MAX_TX_POWER_2GHZ);
+		else
+			eirp_txpower_criterion = rt2x00_get_field16(eeprom,
+						 EEPROM_EIRP_MAX_TX_POWER_5GHZ);
+
+		eirp_txpower = eirp_txpower_criterion + (txpower - criterion) +
+				       (is_rate_b ? 4 : 0) + bw_comp;
+
+		reg_limit = (eirp_txpower > power_level) ?
+					(eirp_txpower - power_level) : 0;
+	} else
+		reg_limit = 0;
+
+	return txpower + bw_comp - reg_limit;
+}
+
 static void rt2800_config_txpower(struct rt2x00_dev *rt2x00dev,
-				  const int max_txpower)
+				  struct ieee80211_conf *conf)
 {
 	u8 txpower;
-	u8 max_value = (u8)max_txpower;
 	u16 eeprom;
-	int i;
+	int i, is_rate_b;
 	u32 reg;
 	u8 r1;
 	u32 offset;
+	enum ieee80211_band band = conf->channel->band;
+	int power_level = conf->power_level;
 
 	/*
-	 * set to normal tx power mode: +/- 0dBm
+	 * set to normal bbp tx power control mode: +/- 0dBm
 	 */
 	rt2800_bbp_read(rt2x00dev, 1, &r1);
-	rt2x00_set_field8(&r1, BBP1_TX_POWER, 0);
+	rt2x00_set_field8(&r1, BBP1_TX_POWER_CTRL, 0);
 	rt2800_bbp_write(rt2x00dev, 1, r1);
-
-	/*
-	 * The eeprom contains the tx power values for each rate. These
-	 * values map to 100% tx power. Each 16bit word contains four tx
-	 * power values and the order is the same as used in the TX_PWR_CFG
-	 * registers.
-	 */
 	offset = TX_PWR_CFG_0;
 
 	for (i = 0; i < EEPROM_TXPOWER_BYRATE_SIZE; i += 2) {
@@ -1674,73 +1936,99 @@
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i,
 				   &eeprom);
 
-		/* TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
+		is_rate_b = i ? 0 : 1;
+		/*
+		 * TX_PWR_CFG_0: 1MBS, TX_PWR_CFG_1: 24MBS,
 		 * TX_PWR_CFG_2: MCS4, TX_PWR_CFG_3: MCS12,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE0);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE0, txpower);
 
-		/* TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
+		/*
+		 * TX_PWR_CFG_0: 2MBS, TX_PWR_CFG_1: 36MBS,
 		 * TX_PWR_CFG_2: MCS5, TX_PWR_CFG_3: MCS13,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE1);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE1, txpower);
 
-		/* TX_PWR_CFG_0: 55MBS, TX_PWR_CFG_1: 48MBS,
+		/*
+		 * TX_PWR_CFG_0: 5.5MBS, TX_PWR_CFG_1: 48MBS,
 		 * TX_PWR_CFG_2: MCS6,  TX_PWR_CFG_3: MCS14,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE2);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE2, txpower);
 
-		/* TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,
+		/*
+		 * TX_PWR_CFG_0: 11MBS, TX_PWR_CFG_1: 54MBS,
 		 * TX_PWR_CFG_2: MCS7,  TX_PWR_CFG_3: MCS15,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE3);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE3, txpower);
 
 		/* read the next four txpower values */
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXPOWER_BYRATE + i + 1,
 				   &eeprom);
 
-		/* TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,
+		is_rate_b = 0;
+		/*
+		 * TX_PWR_CFG_0: 6MBS, TX_PWR_CFG_1: MCS0,
 		 * TX_PWR_CFG_2: MCS8, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE0);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE4, txpower);
 
-		/* TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,
+		/*
+		 * TX_PWR_CFG_0: 9MBS, TX_PWR_CFG_1: MCS1,
 		 * TX_PWR_CFG_2: MCS9, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE1);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE5, txpower);
 
-		/* TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,
+		/*
+		 * TX_PWR_CFG_0: 12MBS, TX_PWR_CFG_1: MCS2,
 		 * TX_PWR_CFG_2: MCS10, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE2);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE6, txpower);
 
-		/* TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,
+		/*
+		 * TX_PWR_CFG_0: 18MBS, TX_PWR_CFG_1: MCS3,
 		 * TX_PWR_CFG_2: MCS11, TX_PWR_CFG_3: unknown,
-		 * TX_PWR_CFG_4: unknown */
+		 * TX_PWR_CFG_4: unknown
+		 */
 		txpower = rt2x00_get_field16(eeprom,
 					     EEPROM_TXPOWER_BYRATE_RATE3);
-		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7,
-				   min(txpower, max_value));
+		txpower = rt2800_compesate_txpower(rt2x00dev, is_rate_b, band,
+					     power_level, txpower);
+		rt2x00_set_field32(&reg, TX_PWR_CFG_RATE7, txpower);
 
 		rt2800_register_write(rt2x00dev, offset, reg);
 
@@ -1799,11 +2087,13 @@
 	/* Always recalculate LNA gain before changing configuration */
 	rt2800_config_lna_gain(rt2x00dev, libconf);
 
-	if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
+	if (flags & IEEE80211_CONF_CHANGE_CHANNEL) {
 		rt2800_config_channel(rt2x00dev, libconf->conf,
 				      &libconf->rf, &libconf->channel);
+		rt2800_config_txpower(rt2x00dev, libconf->conf);
+	}
 	if (flags & IEEE80211_CONF_CHANGE_POWER)
-		rt2800_config_txpower(rt2x00dev, libconf->conf->power_level);
+		rt2800_config_txpower(rt2x00dev, libconf->conf);
 	if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
 		rt2800_config_retry_limit(rt2x00dev, libconf);
 	if (flags & IEEE80211_CONF_CHANGE_PS)
@@ -1832,7 +2122,8 @@
 		if (rt2x00_rt(rt2x00dev, RT3070) ||
 		    rt2x00_rt(rt2x00dev, RT3071) ||
 		    rt2x00_rt(rt2x00dev, RT3090) ||
-		    rt2x00_rt(rt2x00dev, RT3390))
+		    rt2x00_rt(rt2x00dev, RT3390) ||
+		    rt2x00_rt(rt2x00dev, RT5390))
 			return 0x1c + (2 * rt2x00dev->lna_gain);
 		else
 			return 0x2e + rt2x00dev->lna_gain;
@@ -1964,6 +2255,10 @@
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000400);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x0000001f);
+	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000404);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
+		rt2800_register_write(rt2x00dev, TX_SW_CFG2, 0x00000000);
 	} else {
 		rt2800_register_write(rt2x00dev, TX_SW_CFG0, 0x00000000);
 		rt2800_register_write(rt2x00dev, TX_SW_CFG1, 0x00080606);
@@ -2032,7 +2327,7 @@
 	rt2800_register_read(rt2x00dev, CCK_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, CCK_PROT_CFG_PROTECT_RATE, 3);
 	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_PROTECT_NAV_SHORT, 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);
@@ -2045,7 +2340,7 @@
 	rt2800_register_read(rt2x00dev, OFDM_PROT_CFG, &reg);
 	rt2x00_set_field32(&reg, OFDM_PROT_CFG_PROTECT_RATE, 3);
 	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_PROTECT_NAV_SHORT, 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);
@@ -2058,7 +2353,7 @@
 	rt2800_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_PROTECT_NAV_SHORT, 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);
@@ -2071,7 +2366,7 @@
 	rt2800_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_PROTECT_NAV_SHORT, 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);
@@ -2084,7 +2379,7 @@
 	rt2800_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_PROTECT_NAV_SHORT, 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);
@@ -2097,7 +2392,7 @@
 	rt2800_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_PROTECT_NAV_SHORT, 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);
@@ -2180,26 +2475,30 @@
 		rt2800_register_multiwrite(rt2x00dev, MAC_WCID_ENTRY(i),
 					      wcid, sizeof(wcid));
 
-		rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 1);
+		rt2800_register_write(rt2x00dev, MAC_WCID_ATTR_ENTRY(i), 0);
 		rt2800_register_write(rt2x00dev, MAC_IVEIV_ENTRY(i), 0);
 	}
 
 	/*
 	 * Clear all beacons
 	 */
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE0);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE1);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE2);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE3);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE4);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE5);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE6);
-	rt2800_clear_beacon(rt2x00dev, HW_BEACON_BASE7);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE0);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE1);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE2);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE3);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE4);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE5);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE6);
+	rt2800_clear_beacon_register(rt2x00dev, HW_BEACON_BASE7);
 
 	if (rt2x00_is_usb(rt2x00dev)) {
 		rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
 		rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 30);
 		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
+	} else if (rt2x00_is_pcie(rt2x00dev)) {
+		rt2800_register_read(rt2x00dev, US_CYC_CNT, &reg);
+		rt2x00_set_field32(&reg, US_CYC_CNT_CLOCK_CYCLE, 125);
+		rt2800_register_write(rt2x00dev, US_CYC_CNT, reg);
 	}
 
 	rt2800_register_read(rt2x00dev, HT_FBK_CFG0, &reg);
@@ -2335,15 +2634,31 @@
 		     rt2800_wait_bbp_ready(rt2x00dev)))
 		return -EACCES;
 
-	if (rt2800_is_305x_soc(rt2x00dev))
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_bbp_read(rt2x00dev, 4, &value);
+		rt2x00_set_field8(&value, BBP4_MAC_IF_CTRL, 1);
+		rt2800_bbp_write(rt2x00dev, 4, value);
+	}
+
+	if (rt2800_is_305x_soc(rt2x00dev) ||
+	    rt2x00_rt(rt2x00dev, RT5390))
 		rt2800_bbp_write(rt2x00dev, 31, 0x08);
 
 	rt2800_bbp_write(rt2x00dev, 65, 0x2c);
 	rt2800_bbp_write(rt2x00dev, 66, 0x38);
 
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 68, 0x0b);
+
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860C)) {
 		rt2800_bbp_write(rt2x00dev, 69, 0x16);
 		rt2800_bbp_write(rt2x00dev, 73, 0x12);
+	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_bbp_write(rt2x00dev, 69, 0x12);
+		rt2800_bbp_write(rt2x00dev, 73, 0x13);
+		rt2800_bbp_write(rt2x00dev, 75, 0x46);
+		rt2800_bbp_write(rt2x00dev, 76, 0x28);
+		rt2800_bbp_write(rt2x00dev, 77, 0x59);
 	} else {
 		rt2800_bbp_write(rt2x00dev, 69, 0x12);
 		rt2800_bbp_write(rt2x00dev, 73, 0x10);
@@ -2354,7 +2669,8 @@
 	if (rt2x00_rt(rt2x00dev, RT3070) ||
 	    rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
-	    rt2x00_rt(rt2x00dev, RT3390)) {
+	    rt2x00_rt(rt2x00dev, RT3390) ||
+	    rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_bbp_write(rt2x00dev, 79, 0x13);
 		rt2800_bbp_write(rt2x00dev, 80, 0x05);
 		rt2800_bbp_write(rt2x00dev, 81, 0x33);
@@ -2366,35 +2682,62 @@
 	}
 
 	rt2800_bbp_write(rt2x00dev, 82, 0x62);
-	rt2800_bbp_write(rt2x00dev, 83, 0x6a);
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 83, 0x7a);
+	else
+		rt2800_bbp_write(rt2x00dev, 83, 0x6a);
 
 	if (rt2x00_rt_rev(rt2x00dev, RT2860, REV_RT2860D))
 		rt2800_bbp_write(rt2x00dev, 84, 0x19);
+	else if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 84, 0x9a);
 	else
 		rt2800_bbp_write(rt2x00dev, 84, 0x99);
 
-	rt2800_bbp_write(rt2x00dev, 86, 0x00);
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 86, 0x38);
+	else
+		rt2800_bbp_write(rt2x00dev, 86, 0x00);
+
 	rt2800_bbp_write(rt2x00dev, 91, 0x04);
-	rt2800_bbp_write(rt2x00dev, 92, 0x00);
+
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 92, 0x02);
+	else
+		rt2800_bbp_write(rt2x00dev, 92, 0x00);
 
 	if (rt2x00_rt_rev_gte(rt2x00dev, RT3070, REV_RT3070F) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3071, REV_RT3071E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3090, REV_RT3090E) ||
 	    rt2x00_rt_rev_gte(rt2x00dev, RT3390, REV_RT3390E) ||
+	    rt2x00_rt(rt2x00dev, RT5390) ||
 	    rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 103, 0xc0);
 	else
 		rt2800_bbp_write(rt2x00dev, 103, 0x00);
 
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 104, 0x92);
+
 	if (rt2800_is_305x_soc(rt2x00dev))
 		rt2800_bbp_write(rt2x00dev, 105, 0x01);
+	else if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 105, 0x3c);
 	else
 		rt2800_bbp_write(rt2x00dev, 105, 0x05);
-	rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 106, 0x03);
+	else
+		rt2800_bbp_write(rt2x00dev, 106, 0x35);
+
+	if (rt2x00_rt(rt2x00dev, RT5390))
+		rt2800_bbp_write(rt2x00dev, 128, 0x12);
 
 	if (rt2x00_rt(rt2x00dev, RT3071) ||
 	    rt2x00_rt(rt2x00dev, RT3090) ||
-	    rt2x00_rt(rt2x00dev, RT3390)) {
+	    rt2x00_rt(rt2x00dev, RT3390) ||
+	    rt2x00_rt(rt2x00dev, RT5390)) {
 		rt2800_bbp_read(rt2x00dev, 138, &value);
 
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
@@ -2406,6 +2749,42 @@
 		rt2800_bbp_write(rt2x00dev, 138, value);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		int ant, div_mode;
+
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+		div_mode = rt2x00_get_field16(eeprom,
+					      EEPROM_NIC_CONF1_ANT_DIVERSITY);
+		ant = (div_mode == 3) ? 1 : 0;
+
+		/* check if this is a Bluetooth combo card */
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_BT_COEXIST)) {
+			u32 reg;
+
+			rt2800_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT3, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT6, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 0);
+			rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 0);
+			if (ant == 0)
+				rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT3, 1);
+			else if (ant == 1)
+				rt2x00_set_field32(&reg, GPIO_CTRL_CFG_BIT6, 1);
+			rt2800_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+		}
+
+		rt2800_bbp_read(rt2x00dev, 152, &value);
+		if (ant == 0)
+			rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 1);
+		else
+			rt2x00_set_field8(&value, BBP152_RX_DEFAULT_ANT, 0);
+		rt2800_bbp_write(rt2x00dev, 152, value);
+
+		/* Init frequency calibration */
+		rt2800_bbp_write(rt2x00dev, 142, 1);
+		rt2800_bbp_write(rt2x00dev, 143, 57);
+	}
 
 	for (i = 0; i < EEPROM_BBP_SIZE; i++) {
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_BBP_START + i, &eeprom);
@@ -2436,6 +2815,10 @@
 	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 2 * bw40);
 	rt2800_bbp_write(rt2x00dev, 4, bbp);
 
+	rt2800_rfcsr_read(rt2x00dev, 31, &rfcsr);
+	rt2x00_set_field8(&rfcsr, RFCSR31_RX_H20M, bw40);
+	rt2800_rfcsr_write(rt2x00dev, 31, rfcsr);
+
 	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
 	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 1);
 	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
@@ -2491,18 +2874,28 @@
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
 	    !rt2x00_rt(rt2x00dev, RT3390) &&
+	    !rt2x00_rt(rt2x00dev, RT5390) &&
 	    !rt2800_is_305x_soc(rt2x00dev))
 		return 0;
 
 	/*
 	 * Init RF calibration.
 	 */
-	rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
-	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
-	msleep(1);
-	rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
-	rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_read(rt2x00dev, 2, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 1);
+		rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+		msleep(1);
+		rt2x00_set_field8(&rfcsr, RFCSR2_RESCAL_EN, 0);
+		rt2800_rfcsr_write(rt2x00dev, 2, rfcsr);
+	} else {
+		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 1);
+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+		msleep(1);
+		rt2x00_set_field8(&rfcsr, RFCSR30_RF_CALIBRATION, 0);
+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+	}
 
 	if (rt2x00_rt(rt2x00dev, RT3070) ||
 	    rt2x00_rt(rt2x00dev, RT3071) ||
@@ -2510,7 +2903,7 @@
 		rt2800_rfcsr_write(rt2x00dev, 4, 0x40);
 		rt2800_rfcsr_write(rt2x00dev, 5, 0x03);
 		rt2800_rfcsr_write(rt2x00dev, 6, 0x02);
-		rt2800_rfcsr_write(rt2x00dev, 7, 0x70);
+		rt2800_rfcsr_write(rt2x00dev, 7, 0x60);
 		rt2800_rfcsr_write(rt2x00dev, 9, 0x0f);
 		rt2800_rfcsr_write(rt2x00dev, 10, 0x41);
 		rt2800_rfcsr_write(rt2x00dev, 11, 0x21);
@@ -2593,6 +2986,87 @@
 		rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
 		rt2800_rfcsr_write(rt2x00dev, 31, 0x00);
 		return 0;
+	} else if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_write(rt2x00dev, 1, 0x0f);
+		rt2800_rfcsr_write(rt2x00dev, 2, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 3, 0x88);
+		rt2800_rfcsr_write(rt2x00dev, 5, 0x10);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 6, 0xe0);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 6, 0xa0);
+		rt2800_rfcsr_write(rt2x00dev, 7, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 10, 0x53);
+		rt2800_rfcsr_write(rt2x00dev, 11, 0x4a);
+		rt2800_rfcsr_write(rt2x00dev, 12, 0xc6);
+		rt2800_rfcsr_write(rt2x00dev, 13, 0x9f);
+		rt2800_rfcsr_write(rt2x00dev, 14, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 15, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 16, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 18, 0x03);
+		rt2800_rfcsr_write(rt2x00dev, 19, 0x00);
+
+		rt2800_rfcsr_write(rt2x00dev, 20, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 21, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 22, 0x20);
+		rt2800_rfcsr_write(rt2x00dev, 23, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 24, 0x00);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 25, 0x80);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 25, 0xc0);
+		rt2800_rfcsr_write(rt2x00dev, 26, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 27, 0x09);
+		rt2800_rfcsr_write(rt2x00dev, 28, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 29, 0x10);
+
+		rt2800_rfcsr_write(rt2x00dev, 30, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 32, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 33, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 34, 0x07);
+		rt2800_rfcsr_write(rt2x00dev, 35, 0x12);
+		rt2800_rfcsr_write(rt2x00dev, 36, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 37, 0x08);
+		rt2800_rfcsr_write(rt2x00dev, 38, 0x85);
+		rt2800_rfcsr_write(rt2x00dev, 39, 0x1b);
+
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 40, 0x0b);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 40, 0x4b);
+		rt2800_rfcsr_write(rt2x00dev, 41, 0xbb);
+		rt2800_rfcsr_write(rt2x00dev, 42, 0xd2);
+		rt2800_rfcsr_write(rt2x00dev, 43, 0x9a);
+		rt2800_rfcsr_write(rt2x00dev, 44, 0x0e);
+		rt2800_rfcsr_write(rt2x00dev, 45, 0xa2);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 46, 0x73);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 46, 0x7b);
+		rt2800_rfcsr_write(rt2x00dev, 47, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 48, 0x10);
+		rt2800_rfcsr_write(rt2x00dev, 49, 0x94);
+
+		rt2800_rfcsr_write(rt2x00dev, 52, 0x38);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 53, 0x00);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 53, 0x84);
+		rt2800_rfcsr_write(rt2x00dev, 54, 0x78);
+		rt2800_rfcsr_write(rt2x00dev, 55, 0x44);
+		rt2800_rfcsr_write(rt2x00dev, 56, 0x22);
+		rt2800_rfcsr_write(rt2x00dev, 57, 0x80);
+		rt2800_rfcsr_write(rt2x00dev, 58, 0x7f);
+		rt2800_rfcsr_write(rt2x00dev, 59, 0x63);
+
+		rt2800_rfcsr_write(rt2x00dev, 60, 0x45);
+		if (rt2x00_rt_rev_gte(rt2x00dev, RT5390, REV_RT5390F))
+			rt2800_rfcsr_write(rt2x00dev, 61, 0xd1);
+		else
+			rt2800_rfcsr_write(rt2x00dev, 61, 0xdd);
+		rt2800_rfcsr_write(rt2x00dev, 62, 0x00);
+		rt2800_rfcsr_write(rt2x00dev, 63, 0x00);
 	}
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F)) {
@@ -2602,12 +3076,12 @@
 		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
 	} else if (rt2x00_rt(rt2x00dev, RT3071) ||
 		   rt2x00_rt(rt2x00dev, RT3090)) {
+		rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
+
 		rt2800_rfcsr_read(rt2x00dev, 6, &rfcsr);
 		rt2x00_set_field8(&rfcsr, RFCSR6_R2, 1);
 		rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
 
-		rt2800_rfcsr_write(rt2x00dev, 31, 0x14);
-
 		rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
 		rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
 		if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -2619,6 +3093,10 @@
 				rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
 		}
 		rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
+
+		rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
+		rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
+		rt2800_register_write(rt2x00dev, GPIO_SWITCH, reg);
 	} else if (rt2x00_rt(rt2x00dev, RT3390)) {
 		rt2800_register_read(rt2x00dev, GPIO_SWITCH, &reg);
 		rt2x00_set_field32(&reg, GPIO_SWITCH_5, 0);
@@ -2642,21 +3120,23 @@
 			rt2800_init_rx_filter(rt2x00dev, true, 0x27, 0x15);
 	}
 
-	/*
-	 * Set back to initial state
-	 */
-	rt2800_bbp_write(rt2x00dev, 24, 0);
+	if (!rt2x00_rt(rt2x00dev, RT5390)) {
+		/*
+		 * Set back to initial state
+		 */
+		rt2800_bbp_write(rt2x00dev, 24, 0);
 
-	rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
-	rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
+		rt2800_rfcsr_read(rt2x00dev, 22, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR22_BASEBAND_LOOPBACK, 0);
+		rt2800_rfcsr_write(rt2x00dev, 22, rfcsr);
 
-	/*
-	 * set BBP back to BW20
-	 */
-	rt2800_bbp_read(rt2x00dev, 4, &bbp);
-	rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
-	rt2800_bbp_write(rt2x00dev, 4, bbp);
+		/*
+		 * Set BBP back to BW20
+		 */
+		rt2800_bbp_read(rt2x00dev, 4, &bbp);
+		rt2x00_set_field8(&bbp, BBP4_BANDWIDTH, 0);
+		rt2800_bbp_write(rt2x00dev, 4, bbp);
+	}
 
 	if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
 	    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
@@ -2668,24 +3148,29 @@
 	rt2x00_set_field32(&reg, OPT_14_CSR_BIT0, 1);
 	rt2800_register_write(rt2x00dev, OPT_14_CSR, reg);
 
-	rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
-	rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
-	if (rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
-	    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
-	    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
-		if (test_bit(CONFIG_EXTERNAL_LNA_BG, &rt2x00dev->flags))
-			rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+	if (!rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_read(rt2x00dev, 17, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR17_TX_LO1_EN, 0);
+		if (rt2x00_rt(rt2x00dev, RT3070) ||
+		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E) ||
+		    rt2x00_rt_rev_lt(rt2x00dev, RT3090, REV_RT3090E) ||
+		    rt2x00_rt_rev_lt(rt2x00dev, RT3390, REV_RT3390E)) {
+			if (!test_bit(CONFIG_EXTERNAL_LNA_BG,
+				      &rt2x00dev->flags))
+				rt2x00_set_field8(&rfcsr, RFCSR17_R, 1);
+		}
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
+		if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1)
+			rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
+					rt2x00_get_field16(eeprom,
+						EEPROM_TXMIXER_GAIN_BG_VAL));
+		rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 	}
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_TXMIXER_GAIN_BG, &eeprom);
-	if (rt2x00_get_field16(eeprom, EEPROM_TXMIXER_GAIN_BG_VAL) >= 1)
-		rt2x00_set_field8(&rfcsr, RFCSR17_TXMIXER_GAIN,
-				  rt2x00_get_field16(eeprom,
-						   EEPROM_TXMIXER_GAIN_BG_VAL));
-	rt2800_rfcsr_write(rt2x00dev, 17, rfcsr);
 
 	if (rt2x00_rt(rt2x00dev, RT3090)) {
 		rt2800_bbp_read(rt2x00dev, 138, &bbp);
 
+		/*  Turn off unused DAC1 and ADC1 to reduce power consumption */
 		rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 		if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH) == 1)
 			rt2x00_set_field8(&bbp, BBP138_RX_ADC1, 0);
@@ -2719,10 +3204,9 @@
 		rt2800_rfcsr_write(rt2x00dev, 21, rfcsr);
 	}
 
-	if (rt2x00_rt(rt2x00dev, RT3070) || rt2x00_rt(rt2x00dev, RT3071)) {
+	if (rt2x00_rt(rt2x00dev, RT3070)) {
 		rt2800_rfcsr_read(rt2x00dev, 27, &rfcsr);
-		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F) ||
-		    rt2x00_rt_rev_lt(rt2x00dev, RT3071, REV_RT3071E))
+		if (rt2x00_rt_rev_lt(rt2x00dev, RT3070, REV_RT3070F))
 			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 3);
 		else
 			rt2x00_set_field8(&rfcsr, RFCSR27_R1, 0);
@@ -2732,6 +3216,20 @@
 		rt2800_rfcsr_write(rt2x00dev, 27, rfcsr);
 	}
 
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_rfcsr_read(rt2x00dev, 38, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR38_RX_LO1_EN, 0);
+		rt2800_rfcsr_write(rt2x00dev, 38, rfcsr);
+
+		rt2800_rfcsr_read(rt2x00dev, 39, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR39_RX_LO2_EN, 0);
+		rt2800_rfcsr_write(rt2x00dev, 39, rfcsr);
+
+		rt2800_rfcsr_read(rt2x00dev, 30, &rfcsr);
+		rt2x00_set_field8(&rfcsr, RFCSR30_RX_VCM, 2);
+		rt2800_rfcsr_write(rt2x00dev, 30, rfcsr);
+	}
+
 	return 0;
 }
 
@@ -2810,10 +3308,7 @@
 
 	rt2800_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_TX_WRITEBACK_DONE, 1);
 	rt2800_register_write(rt2x00dev, WPDMA_GLO_CFG, reg);
 
 	/* Wait for DMA, ignore error */
@@ -2823,9 +3318,6 @@
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_TX, 0);
 	rt2x00_set_field32(&reg, MAC_SYS_CTRL_ENABLE_RX, 0);
 	rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
-
-	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
-	rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
 }
 EXPORT_SYMBOL_GPL(rt2800_disable_radio);
 
@@ -2986,13 +3478,6 @@
 				   default_lna_gain);
 	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word);
-	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER);
-	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff)
-		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER);
-	rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word);
-
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
@@ -3009,10 +3494,15 @@
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF0, &eeprom);
 
 	/*
-	 * Identify RF chipset.
+	 * Identify RF chipset by EEPROM value
+	 * RT28xx/RT30xx: defined in "EEPROM_NIC_CONF0_RF_TYPE" field
+	 * RT53xx: defined in "EEPROM_CHIP_ID" field
 	 */
-	value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 	rt2800_register_read(rt2x00dev, MAC_CSR0, &reg);
+	if (rt2x00_get_field32(reg, MAC_CSR0_CHIPSET) == RT5390)
+		rt2x00_eeprom_read(rt2x00dev, EEPROM_CHIP_ID, &value);
+	else
+		value = rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RF_TYPE);
 
 	rt2x00_set_chip(rt2x00dev, rt2x00_get_field32(reg, MAC_CSR0_CHIPSET),
 			value, rt2x00_get_field32(reg, MAC_CSR0_REVISION));
@@ -3024,7 +3514,8 @@
 	    !rt2x00_rt(rt2x00dev, RT3071) &&
 	    !rt2x00_rt(rt2x00dev, RT3090) &&
 	    !rt2x00_rt(rt2x00dev, RT3390) &&
-	    !rt2x00_rt(rt2x00dev, RT3572)) {
+	    !rt2x00_rt(rt2x00dev, RT3572) &&
+	    !rt2x00_rt(rt2x00dev, RT5390)) {
 		ERROR(rt2x00dev, "Invalid RT chipset detected.\n");
 		return -ENODEV;
 	}
@@ -3038,7 +3529,8 @@
 	    !rt2x00_rf(rt2x00dev, RF3021) &&
 	    !rt2x00_rf(rt2x00dev, RF3022) &&
 	    !rt2x00_rf(rt2x00dev, RF3052) &&
-	    !rt2x00_rf(rt2x00dev, RF3320)) {
+	    !rt2x00_rf(rt2x00dev, RF3320) &&
+	    !rt2x00_rf(rt2x00dev, RF5390)) {
 		ERROR(rt2x00dev, "Invalid RF chipset detected.\n");
 		return -ENODEV;
 	}
@@ -3046,11 +3538,35 @@
 	/*
 	 * Identify default antenna configuration.
 	 */
-	rt2x00dev->default_ant.tx =
+	rt2x00dev->default_ant.tx_chain_num =
 	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_TXPATH);
-	rt2x00dev->default_ant.rx =
+	rt2x00dev->default_ant.rx_chain_num =
 	    rt2x00_get_field16(eeprom, EEPROM_NIC_CONF0_RXPATH);
 
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1, &eeprom);
+
+	if (rt2x00_rt(rt2x00dev, RT3070) ||
+	    rt2x00_rt(rt2x00dev, RT3090) ||
+	    rt2x00_rt(rt2x00dev, RT3390)) {
+		value = rt2x00_get_field16(eeprom,
+				EEPROM_NIC_CONF1_ANT_DIVERSITY);
+		switch (value) {
+		case 0:
+		case 1:
+		case 2:
+			rt2x00dev->default_ant.tx = ANTENNA_A;
+			rt2x00dev->default_ant.rx = ANTENNA_A;
+			break;
+		case 3:
+			rt2x00dev->default_ant.tx = ANTENNA_A;
+			rt2x00dev->default_ant.rx = ANTENNA_B;
+			break;
+		}
+	} else {
+		rt2x00dev->default_ant.tx = ANTENNA_A;
+		rt2x00dev->default_ant.rx = ANTENNA_A;
+	}
+
 	/*
 	 * Read frequency offset and RF programming sequence.
 	 */
@@ -3084,6 +3600,15 @@
 	rt2x00_eeprom_read(rt2x00dev, EEPROM_FREQ, &rt2x00dev->led_mcu_reg);
 #endif /* CONFIG_RT2X00_LIB_LEDS */
 
+	/*
+	 * Check if support EIRP tx power limit feature.
+	 */
+	rt2x00_eeprom_read(rt2x00dev, EEPROM_EIRP_MAX_TX_POWER, &eeprom);
+
+	if (rt2x00_get_field16(eeprom, EEPROM_EIRP_MAX_TX_POWER_2GHZ) <
+					EIRP_MAX_TX_POWER_LIMIT)
+		__set_bit(CONFIG_SUPPORT_POWER_LIMIT, &rt2x00dev->flags);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(rt2800_init_eeprom);
@@ -3236,7 +3761,6 @@
 	char *default_power1;
 	char *default_power2;
 	unsigned int i;
-	unsigned short max_power;
 	u16 eeprom;
 
 	/*
@@ -3303,7 +3827,8 @@
 		   rt2x00_rf(rt2x00dev, RF2020) ||
 		   rt2x00_rf(rt2x00dev, RF3021) ||
 		   rt2x00_rf(rt2x00dev, RF3022) ||
-		   rt2x00_rf(rt2x00dev, RF3320)) {
+		   rt2x00_rf(rt2x00dev, RF3320) ||
+		   rt2x00_rf(rt2x00dev, RF5390)) {
 		spec->num_channels = 14;
 		spec->channels = rf_vals_3x;
 	} else if (rt2x00_rf(rt2x00dev, RF3052)) {
@@ -3361,26 +3886,21 @@
 
 	spec->channels_info = info;
 
-	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom);
-	max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ);
 	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
 	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
 
 	for (i = 0; i < 14; i++) {
-		info[i].max_power = max_power;
-		info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]);
-		info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]);
+		info[i].default_power1 = default_power1[i];
+		info[i].default_power2 = default_power2[i];
 	}
 
 	if (spec->num_channels > 14) {
-		max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ);
 		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
 		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
 
 		for (i = 14; i < spec->num_channels; i++) {
-			info[i].max_power = max_power;
-			info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]);
-			info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]);
+			info[i].default_power1 = default_power1[i];
+			info[i].default_power2 = default_power2[i];
 		}
 	}
 
@@ -3472,7 +3992,7 @@
 	if (queue_idx >= 4)
 		return 0;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 
 	/* Update WMM TXOP register */
 	offset = WMM_TXOP0_CFG + (sizeof(u32) * (!!(queue_idx & 2)));
@@ -3530,7 +4050,8 @@
 
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn)
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size)
 {
 	int ret = 0;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800lib.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800lib.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800lib.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800lib.h	2011-05-19 00:06:34.000000000 -0400
@@ -156,6 +156,7 @@
 void rt2800_txdone_entry(struct queue_entry *entry, u32 status);
 
 void rt2800_write_beacon(struct queue_entry *entry, struct txentry_desc *txdesc);
+void rt2800_clear_beacon(struct queue_entry *entry);
 
 extern const struct rt2x00debug rt2800_rt2x00debug;
 
@@ -198,7 +199,8 @@
 u64 rt2800_get_tsf(struct ieee80211_hw *hw);
 int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
 			enum ieee80211_ampdu_mlme_action action,
-			struct ieee80211_sta *sta, u16 tid, u16 *ssn);
+			struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			u8 buf_size);
 int rt2800_get_survey(struct ieee80211_hw *hw, int idx,
 		      struct survey_info *survey);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800pci.c	2012-03-24 01:14:22.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800pci.c	2012-03-24 03:34:24.000000000 -0400
@@ -200,11 +200,22 @@
 		rt2800_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow beacon tasklets to be scheduled for periodic
+		 * beacon updates.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+		tasklet_enable(&rt2x00dev->pretbtt_tasklet);
+
 		rt2800_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
 		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);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 1);
+		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
 		break;
 	default:
 		break;
@@ -250,6 +261,16 @@
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_GEN, 0);
 		rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
+
+		rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
+		rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER, 0);
+		rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
+
+		/*
+		 * Wait for tbtt tasklets to finish.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
+		tasklet_disable(&rt2x00dev->pretbtt_tasklet);
 		break;
 	default:
 		break;
@@ -397,9 +418,9 @@
 static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 				 enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_ON) ||
-		   (state == STATE_RADIO_IRQ_ON_ISR);
+	int mask = (state == STATE_RADIO_IRQ_ON);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -408,8 +429,17 @@
 	if (state == STATE_RADIO_IRQ_ON) {
 		rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
 		rt2800_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
+
+		/*
+		 * Enable tasklets. The beacon related tasklets are
+		 * enabled when the beacon queue is started.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
+		tasklet_enable(&rt2x00dev->autowake_tasklet);
 	}
 
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
 	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDELAYINT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDELAYINT, 0);
@@ -430,6 +460,17 @@
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RX_COHERENT, 0);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TX_COHERENT, 0);
 	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished before
+		 * disabling the interrupts.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+		tasklet_disable(&rt2x00dev->autowake_tasklet);
+	}
 }
 
 static int rt2800pci_init_registers(struct rt2x00_dev *rt2x00dev)
@@ -452,6 +493,13 @@
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
 	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
 
+	if (rt2x00_rt(rt2x00dev, RT5390)) {
+		rt2800_register_read(rt2x00dev, AUX_CTRL, &reg);
+		rt2x00_set_field32(&reg, AUX_CTRL_FORCE_PCIE_CLK, 1);
+		rt2x00_set_field32(&reg, AUX_CTRL_WAKE_PCIE_EN, 1);
+		rt2800_register_write(rt2x00dev, AUX_CTRL, reg);
+	}
+
 	rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0x00000003);
 
 	rt2800_register_read(rt2x00dev, MAC_SYS_CTRL, &reg);
@@ -475,39 +523,23 @@
 
 static void rt2800pci_disable_radio(struct rt2x00_dev *rt2x00dev)
 {
-	u32 reg;
-
-	rt2800_disable_radio(rt2x00dev);
-
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00001280);
-
-	rt2800_register_read(rt2x00dev, WPDMA_RST_IDX, &reg);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX0, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX1, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX2, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX3, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX4, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DTX_IDX5, 1);
-	rt2x00_set_field32(&reg, WPDMA_RST_IDX_DRX_IDX0, 1);
-	rt2800_register_write(rt2x00dev, WPDMA_RST_IDX, reg);
-
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e1f);
-	rt2800_register_write(rt2x00dev, PBF_SYS_CTRL, 0x00000e00);
+	if (rt2x00_is_soc(rt2x00dev)) {
+		rt2800_disable_radio(rt2x00dev);
+		rt2800_register_write(rt2x00dev, PWR_PIN_CFG, 0);
+		rt2800_register_write(rt2x00dev, TX_PIN_CFG, 0);
+	}
 }
 
 static int rt2800pci_set_state(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 {
-	/*
-	 * Always put the device to sleep (even when we intend to wakeup!)
-	 * if the device is booting and wasn't asleep it will return
-	 * failure when attempting to wakeup.
-	 */
-	rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0xff, 0xff, 2);
-
 	if (state == STATE_AWAKE) {
-		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0);
+		rt2800_mcu_request(rt2x00dev, MCU_WAKEUP, TOKEN_WAKUP, 0, 0x02);
 		rt2800pci_mcu_status(rt2x00dev, TOKEN_WAKUP);
+	} else if (state == STATE_SLEEP) {
+		rt2800_register_write(rt2x00dev, H2M_MAILBOX_STATUS, 0xffffffff);
+		rt2800_register_write(rt2x00dev, H2M_MAILBOX_CID, 0xffffffff);
+		rt2800_mcu_request(rt2x00dev, MCU_SLEEP, 0x01, 0xff, 0x01);
 	}
 
 	return 0;
@@ -538,9 +570,7 @@
 		rt2800pci_set_state(rt2x00dev, STATE_SLEEP);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt2800pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -696,7 +726,7 @@
 
 	while (kfifo_get(&rt2x00dev->txstatus_fifo, &status)) {
 		qid = rt2x00_get_field32(status, TX_STA_FIFO_PID_QUEUE);
-		if (qid >= QID_RX) {
+		if (unlikely(qid >= QID_RX)) {
 			/*
 			 * Unknown queue, this shouldn't happen. Just drop
 			 * this tx status.
@@ -706,7 +736,7 @@
 			break;
 		}
 
-		queue = rt2x00queue_get_queue(rt2x00dev, qid);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
 		if (unlikely(queue == NULL)) {
 			/*
 			 * The queue is NULL, this shouldn't happen. Stop
@@ -717,7 +747,7 @@
 			break;
 		}
 
-		if (rt2x00queue_empty(queue)) {
+		if (unlikely(rt2x00queue_empty(queue))) {
 			/*
 			 * The queue is empty. Stop processing here
 			 * and drop the tx status.
@@ -732,45 +762,59 @@
 	}
 }
 
-static void rt2800pci_txstatus_tasklet(unsigned long data)
-{
-	rt2800pci_txdone((struct rt2x00_dev *)data);
-}
-
-static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
+static void rt2800pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				       struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
+	u32 reg;
 
 	/*
-	 * 1 - Pre TBTT interrupt.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
-		rt2x00lib_pretbtt(rt2x00dev);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
+	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00_set_field32(&reg, irq_field, 1);
+	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 2 - Beacondone interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
-		rt2x00lib_beacondone(rt2x00dev);
+static void rt2800pci_txstatus_tasklet(unsigned long data)
+{
+	rt2800pci_txdone((struct rt2x00_dev *)data);
 
 	/*
-	 * 3 - Rx ring done interrupt.
+	 * No need to enable the tx status interrupt here as we always
+	 * leave it enabled to minimize the possibility of a tx status
+	 * register overflow. See comment in interrupt handler.
 	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
-		rt2x00pci_rxdone(rt2x00dev);
+}
 
-	/*
-	 * 4 - Auto wakeup interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
-		rt2800pci_wakeup(rt2x00dev);
+static void rt2800pci_pretbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_pretbtt(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
+}
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
+static void rt2800pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
+}
 
-	return IRQ_HANDLED;
+static void rt2800pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
+}
+
+static void rt2800pci_autowake_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2800pci_wakeup(rt2x00dev);
+	rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
 }
 
 static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
@@ -791,7 +835,7 @@
 	 *
 	 * Furthermore we don't disable the TX_FIFO_STATUS
 	 * interrupt here but leave it enabled so that the TX_STA_FIFO
-	 * can also be read while the interrupt thread gets executed.
+	 * can also be read while the tx status tasklet gets executed.
 	 *
 	 * Since we have only one producer and one consumer we don't
 	 * need to lock the kfifo.
@@ -816,8 +860,7 @@
 static irqreturn_t rt2800pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg;
-	irqreturn_t ret = IRQ_HANDLED;
+	u32 reg, mask;
 
 	/* Read status and ACK all interrupts */
 	rt2800_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
@@ -829,38 +872,44 @@
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
-		rt2800pci_txstatus_interrupt(rt2x00dev);
+	/*
+	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+	 * for interrupts and interrupt masks we can just use the value of
+	 * INT_SOURCE_CSR to create the interrupt mask.
+	 */
+	mask = ~reg;
 
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT) ||
-	    rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT) ||
-	    rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE) ||
-	    rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) {
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) {
+		rt2800pci_txstatus_interrupt(rt2x00dev);
 		/*
-		 * All other interrupts are handled in the interrupt thread.
-		 * Store irqvalue for use in the interrupt thread.
+		 * Never disable the TX_FIFO_STATUS interrupt.
 		 */
-		rt2x00dev->irqvalue[0] = reg;
+		rt2x00_set_field32(&mask, INT_MASK_CSR_TX_FIFO_STATUS, 1);
+	}
 
-		/*
-		 * Disable interrupts, will be enabled again in the
-		 * interrupt thread.
-		*/
-		rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-						      STATE_RADIO_IRQ_OFF_ISR);
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
+		tasklet_hi_schedule(&rt2x00dev->pretbtt_tasklet);
 
-		/*
-		 * Leave the TX_FIFO_STATUS interrupt enabled to not lose any
-		 * tx status reports.
-		 */
-		rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
-		rt2x00_set_field32(&reg, INT_MASK_CSR_TX_FIFO_STATUS, 1);
-		rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
 
-		ret = IRQ_WAKE_THREAD;
-	}
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
 
-	return ret;
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
+		tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+	rt2800_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	reg &= mask;
+	rt2800_register_write(rt2x00dev, INT_MASK_CSR, reg);
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -928,6 +977,7 @@
 	if (!modparam_nohwcrypt)
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -975,8 +1025,11 @@
 
 static const struct rt2x00lib_ops rt2800pci_rt2x00_ops = {
 	.irq_handler		= rt2800pci_interrupt,
-	.irq_handler_thread	= rt2800pci_interrupt_thread,
-	.txstatus_tasklet       = rt2800pci_txstatus_tasklet,
+	.txstatus_tasklet	= rt2800pci_txstatus_tasklet,
+	.pretbtt_tasklet	= rt2800pci_pretbtt_tasklet,
+	.tbtt_tasklet		= rt2800pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt2800pci_rxdone_tasklet,
+	.autowake_tasklet	= rt2800pci_autowake_tasklet,
 	.probe_hw		= rt2800pci_probe_hw,
 	.get_firmware_name	= rt2800pci_get_firmware_name,
 	.check_firmware		= rt2800_check_firmware,
@@ -996,6 +1049,7 @@
 	.write_tx_desc		= rt2800pci_write_tx_desc,
 	.write_tx_data		= rt2800_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
+	.clear_beacon		= rt2800_clear_beacon,
 	.fill_rxdone		= rt2800pci_fill_rxdone,
 	.config_shared_key	= rt2800_config_shared_key,
 	.config_pairwise_key	= rt2800_config_pairwise_key,
@@ -1079,6 +1133,9 @@
 	{ PCI_DEVICE(0x1814, 0x3592), PCI_DEVICE_DATA(&rt2800pci_ops) },
 	{ PCI_DEVICE(0x1814, 0x3593), PCI_DEVICE_DATA(&rt2800pci_ops) },
 #endif
+#ifdef CONFIG_RT2800PCI_RT53XX
+	{ PCI_DEVICE(0x1814, 0x5390), PCI_DEVICE_DATA(&rt2800pci_ops) },
+#endif
 	{ 0, }
 };
 #endif /* CONFIG_PCI */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2012-03-24 01:14:30.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2800usb.c	2012-03-24 03:34:29.000000000 -0400
@@ -253,9 +253,7 @@
 		rt2800usb_set_state(rt2x00dev, STATE_SLEEP);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
@@ -567,6 +565,7 @@
 		__set_bit(CONFIG_SUPPORT_HW_CRYPTO, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_LINK_TUNING, &rt2x00dev->flags);
 	__set_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags);
+	__set_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags);
 
 	/*
 	 * Set the rssi offset.
@@ -639,6 +638,7 @@
 	.write_tx_desc		= rt2800usb_write_tx_desc,
 	.write_tx_data		= rt2800usb_write_tx_data,
 	.write_beacon		= rt2800_write_beacon,
+	.clear_beacon		= rt2800_clear_beacon,
 	.get_tx_data_len	= rt2800usb_get_tx_data_len,
 	.fill_rxdone		= rt2800usb_fill_rxdone,
 	.config_shared_key	= rt2800_config_shared_key,
@@ -719,6 +719,7 @@
 	{ USB_DEVICE(0x0b05, 0x1732), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x0b05, 0x1742), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x0b05, 0x1784), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* AzureWave */
 	{ USB_DEVICE(0x13d3, 0x3247), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x13d3, 0x3273), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -729,8 +730,12 @@
 	{ 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, 0x825b), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x935a), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x050d, 0x935b), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Buffalo */
 	{ USB_DEVICE(0x0411, 0x00e8), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x0411, 0x016f), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Conceptronic */
 	{ USB_DEVICE(0x14b2, 0x3c06), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x14b2, 0x3c07), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -817,6 +822,7 @@
 	/* Pegatron */
 	{ USB_DEVICE(0x1d4d, 0x000c), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x000e), USB_DEVICE_DATA(&rt2800usb_ops) },
+	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Philips */
 	{ USB_DEVICE(0x0471, 0x200f), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Planex */
@@ -898,6 +904,8 @@
 	{ USB_DEVICE(0x148f, 0x3572), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Sitecom */
 	{ USB_DEVICE(0x0df6, 0x0041), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Toshiba */
+	{ USB_DEVICE(0x0930, 0x0a07), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Zinwell */
 	{ USB_DEVICE(0x5a57, 0x0284), USB_DEVICE_DATA(&rt2800usb_ops) },
 #endif
@@ -913,7 +921,6 @@
 	{ USB_DEVICE(0x0b05, 0x1760), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x0b05, 0x1761), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x0b05, 0x1790), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1761, 0x0b05), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* AzureWave */
 	{ USB_DEVICE(0x13d3, 0x3262), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x13d3, 0x3284), USB_DEVICE_DATA(&rt2800usb_ops) },
@@ -937,6 +944,8 @@
 	{ USB_DEVICE(0x07d1, 0x3c13), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c15), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x07d1, 0x3c17), USB_DEVICE_DATA(&rt2800usb_ops) },
+	/* Edimax */
+	{ USB_DEVICE(0x7392, 0x4085), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Encore */
 	{ USB_DEVICE(0x203d, 0x14a1), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Gemtek */
@@ -959,8 +968,8 @@
 	{ USB_DEVICE(0x05a6, 0x0101), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x0002), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x1d4d, 0x0010), USB_DEVICE_DATA(&rt2800usb_ops) },
-	{ USB_DEVICE(0x1d4d, 0x0011), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Planex */
+	{ USB_DEVICE(0x2019, 0x5201), USB_DEVICE_DATA(&rt2800usb_ops) },
 	{ USB_DEVICE(0x2019, 0xab24), USB_DEVICE_DATA(&rt2800usb_ops) },
 	/* Qcom */
 	{ USB_DEVICE(0x18e8, 0x6259), USB_DEVICE_DATA(&rt2800usb_ops) },
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00config.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00config.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00config.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
 	 * Note that when NULL is passed as address we will send
 	 * 00:00:00:00:00 to the device to clear the address.
 	 * This will prevent the device being confused when it wants
-	 * to ACK frames or consideres itself associated.
+	 * to ACK frames or considers itself associated.
 	 */
 	memset(conf.mac, 0, sizeof(conf.mac));
 	if (mac)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00crypto.c	2011-05-19 00:06:34.000000000 -0400
@@ -237,7 +237,7 @@
 	}
 
 	/*
-	 * NOTE: Always count the payload as transfered,
+	 * NOTE: Always count the payload as transferred,
 	 * even when alignment was set to zero. This is required
 	 * for determining the correct offset for the ICV data.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,7 +121,7 @@
 		return;
 
 	if (test_and_clear_bit(DELAYED_UPDATE_BEACON, &intf->delayed_flags))
-		rt2x00queue_update_beacon(rt2x00dev, vif, true);
+		rt2x00queue_update_beacon(rt2x00dev, vif);
 }
 
 static void rt2x00lib_intf_scheduled(struct work_struct *work)
@@ -174,7 +174,13 @@
 	    vif->type != NL80211_IFTYPE_WDS)
 		return;
 
-	rt2x00queue_update_beacon(rt2x00dev, vif, true);
+	/*
+	 * Update the beacon without locking. This is safe on PCI devices
+	 * as they only update the beacon periodically here. This should
+	 * never be called for USB devices.
+	 */
+	WARN_ON(rt2x00_is_usb(rt2x00dev));
+	rt2x00queue_update_beacon_locked(rt2x00dev, vif);
 }
 
 void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
@@ -183,9 +189,9 @@
 		return;
 
 	/* send buffered bc/mc frames out for every bssid */
-	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_bc_buffer_iter,
-					    rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00lib_bc_buffer_iter,
+						   rt2x00dev);
 	/*
 	 * Devices with pre tbtt interrupt don't need to update the beacon
 	 * here as they will fetch the next beacon directly prior to
@@ -195,9 +201,9 @@
 		return;
 
 	/* fetch next beacon */
-	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_beaconupdate_iter,
-					    rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00lib_beaconupdate_iter,
+						   rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
 
@@ -207,9 +213,9 @@
 		return;
 
 	/* fetch next beacon */
-	ieee80211_iterate_active_interfaces(rt2x00dev->hw,
-					    rt2x00lib_beaconupdate_iter,
-					    rt2x00dev);
+	ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+						   rt2x00lib_beaconupdate_iter,
+						   rt2x00dev);
 }
 EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
 
@@ -649,7 +655,10 @@
 			      const int channel, const int tx_power,
 			      const int value)
 {
-	entry->center_freq = ieee80211_channel_to_frequency(channel);
+	/* XXX: this assumption about the band is wrong for 802.11j */
+	entry->band = channel <= 14 ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
+	entry->center_freq = ieee80211_channel_to_frequency(channel,
+							    entry->band);
 	entry->hw_value = value;
 	entry->max_power = tx_power;
 	entry->max_antenna_gain = 0xff;
@@ -812,15 +821,29 @@
 				     GFP_KERNEL);
 		if (status)
 			return status;
+	}
 
-		/* tasklet for processing the tx status reports. */
-		if (rt2x00dev->ops->lib->txstatus_tasklet)
-			tasklet_init(&rt2x00dev->txstatus_tasklet,
-				     rt2x00dev->ops->lib->txstatus_tasklet,
-				     (unsigned long)rt2x00dev);
-
+	/*
+	 * Initialize tasklets if used by the driver. Tasklets are
+	 * disabled until the interrupts are turned on. The driver
+	 * has to handle that.
+	 */
+#define RT2X00_TASKLET_INIT(taskletname) \
+	if (rt2x00dev->ops->lib->taskletname) { \
+		tasklet_init(&rt2x00dev->taskletname, \
+			     rt2x00dev->ops->lib->taskletname, \
+			     (unsigned long)rt2x00dev); \
+		tasklet_disable(&rt2x00dev->taskletname); \
 	}
 
+	RT2X00_TASKLET_INIT(txstatus_tasklet);
+	RT2X00_TASKLET_INIT(pretbtt_tasklet);
+	RT2X00_TASKLET_INIT(tbtt_tasklet);
+	RT2X00_TASKLET_INIT(rxdone_tasklet);
+	RT2X00_TASKLET_INIT(autowake_tasklet);
+
+#undef RT2X00_TASKLET_INIT
+
 	/*
 	 * Register HW.
 	 */
@@ -949,6 +972,7 @@
 {
 	int retval = -ENOMEM;
 
+	spin_lock_init(&rt2x00dev->irqmask_lock);
 	mutex_init(&rt2x00dev->csr_mutex);
 
 	set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
@@ -973,8 +997,15 @@
 		    BIT(NL80211_IFTYPE_WDS);
 
 	/*
-	 * Initialize configuration work.
+	 * Initialize work.
 	 */
+	rt2x00dev->workqueue =
+	    alloc_ordered_workqueue(wiphy_name(rt2x00dev->hw->wiphy), 0);
+	if (!rt2x00dev->workqueue) {
+		retval = -ENOMEM;
+		goto exit;
+	}
+
 	INIT_WORK(&rt2x00dev->intf_work, rt2x00lib_intf_scheduled);
 
 	/*
@@ -1031,8 +1062,11 @@
 	 * Stop all work.
 	 */
 	cancel_work_sync(&rt2x00dev->intf_work);
-	cancel_work_sync(&rt2x00dev->rxdone_work);
-	cancel_work_sync(&rt2x00dev->txdone_work);
+	if (rt2x00_is_usb(rt2x00dev)) {
+		cancel_work_sync(&rt2x00dev->rxdone_work);
+		cancel_work_sync(&rt2x00dev->txdone_work);
+	}
+	destroy_workqueue(rt2x00dev->workqueue);
 
 	/*
 	 * Free the tx status fifo.
@@ -1043,6 +1077,10 @@
 	 * Kill the tx status tasklet.
 	 */
 	tasklet_kill(&rt2x00dev->txstatus_tasklet);
+	tasklet_kill(&rt2x00dev->pretbtt_tasklet);
+	tasklet_kill(&rt2x00dev->tbtt_tasklet);
+	tasklet_kill(&rt2x00dev->rxdone_tasklet);
+	tasklet_kill(&rt2x00dev->autowake_tasklet);
 
 	/*
 	 * Uninitialize device.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00dump.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00dump.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00dump.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00dump.h	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
  *   [rt2x00dump header][hardware descriptor][ieee802.11 frame]
  *
  * rt2x00dump header: The description of the dumped frame, as well as
- *	additional information usefull for debugging. See &rt2x00dump_hdr.
+ *	additional information useful for debugging. See &rt2x00dump_hdr.
  * hardware descriptor: Descriptor that was used to receive or transmit
  *	the frame.
  * ieee802.11 frame: The actual frame that was received or transmitted.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00.h	2011-05-19 00:06:34.000000000 -0400
@@ -189,6 +189,7 @@
 #define RT3572		0x3572
 #define RT3593		0x3593	/* PCIe */
 #define RT3883		0x3883	/* WSOC */
+#define RT5390         0x5390  /* 2.4GHz */
 
 	u16 rf;
 	u16 rev;
@@ -225,6 +226,8 @@
 struct antenna_setup {
 	enum antenna rx;
 	enum antenna tx;
+	u8 rx_chain_num;
+	u8 tx_chain_num;
 };
 
 /*
@@ -368,6 +371,7 @@
 	 * dedicated beacon entry.
 	 */
 	struct queue_entry *beacon;
+	bool enable_beacon;
 
 	/*
 	 * Actions that needed rescheduling.
@@ -463,7 +467,6 @@
 	const u8 *address;
 
 	u32 bssidx;
-	u32 aid;
 
 	u8 key[16];
 	u8 tx_mic[8];
@@ -481,13 +484,13 @@
 	enum nl80211_iftype type;
 
 	/*
-	 * TSF sync value, this is dependant on the operation type.
+	 * TSF sync value, this is dependent on the operation type.
 	 */
 	enum tsf_sync sync;
 
 	/*
-	 * The MAC and BSSID addressess are simple array of bytes,
-	 * these arrays are little endian, so when sending the addressess
+	 * The MAC and BSSID addresses are simple array of bytes,
+	 * these arrays are little endian, so when sending the addresses
 	 * to the drivers, copy the it into a endian-signed variable.
 	 *
 	 * Note that all devices (except rt2500usb) have 32 bits
@@ -511,14 +514,13 @@
 	irq_handler_t irq_handler;
 
 	/*
-	 * Threaded Interrupt handlers.
-	 */
-	irq_handler_t irq_handler_thread;
-
-	/*
 	 * TX status tasklet handler.
 	 */
 	void (*txstatus_tasklet) (unsigned long data);
+	void (*pretbtt_tasklet) (unsigned long data);
+	void (*tbtt_tasklet) (unsigned long data);
+	void (*rxdone_tasklet) (unsigned long data);
+	void (*autowake_tasklet) (unsigned long data);
 
 	/*
 	 * Device init handlers.
@@ -573,6 +575,7 @@
 			       struct txentry_desc *txdesc);
 	void (*write_beacon) (struct queue_entry *entry,
 			      struct txentry_desc *txdesc);
+	void (*clear_beacon) (struct queue_entry *entry);
 	int (*get_tx_data_len) (struct queue_entry *entry);
 
 	/*
@@ -658,12 +661,15 @@
 	DRIVER_REQUIRE_L2PAD,
 	DRIVER_REQUIRE_TXSTATUS_FIFO,
 	DRIVER_REQUIRE_TASKLET_CONTEXT,
+	DRIVER_REQUIRE_SW_SEQNO,
+	DRIVER_REQUIRE_HT_TX_DESC,
 
 	/*
 	 * Driver features
 	 */
 	CONFIG_SUPPORT_HW_BUTTON,
 	CONFIG_SUPPORT_HW_CRYPTO,
+	CONFIG_SUPPORT_POWER_LIMIT,
 	DRIVER_SUPPORT_CONTROL_FILTERS,
 	DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
 	DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
@@ -788,10 +794,12 @@
 	 *  - Open ap interface count.
 	 *  - Open sta interface count.
 	 *  - Association count.
+	 *  - Beaconing enabled count.
 	 */
 	unsigned int intf_ap_count;
 	unsigned int intf_sta_count;
 	unsigned int intf_associated;
+	unsigned int intf_beaconing;
 
 	/*
 	 * Link quality
@@ -857,6 +865,13 @@
 	 */
 	struct ieee80211_low_level_stats low_level_stats;
 
+	/**
+	 * Work queue for all work which should not be placed
+	 * on the mac80211 workqueue (because of dependencies
+	 * between various work structures).
+	 */
+	struct workqueue_struct *workqueue;
+
 	/*
 	 * Scheduled work.
 	 * NOTE: intf_work will use ieee80211_iterate_active_interfaces()
@@ -872,14 +887,13 @@
 	struct work_struct txdone_work;
 
 	/*
-	 * Data queue arrays for RX, TX and Beacon.
-	 * The Beacon array also contains the Atim queue
-	 * if that is supported by the device.
+	 * Data queue arrays for RX, TX, Beacon and ATIM.
 	 */
 	unsigned int data_queues;
 	struct data_queue *rx;
 	struct data_queue *tx;
 	struct data_queue *bcn;
+	struct data_queue *atim;
 
 	/*
 	 * Firmware image.
@@ -887,12 +901,6 @@
 	const struct firmware *fw;
 
 	/*
-	 * Interrupt values, stored between interrupt service routine
-	 * and interrupt thread routine.
-	 */
-	u32 irqvalue[2];
-
-	/*
 	 * FIFO for storing tx status reports between isr and tasklet.
 	 */
 	DECLARE_KFIFO_PTR(txstatus_fifo, u32);
@@ -901,6 +909,15 @@
 	 * Tasklet for processing tx status reports (rt2800pci).
 	 */
 	struct tasklet_struct txstatus_tasklet;
+	struct tasklet_struct pretbtt_tasklet;
+	struct tasklet_struct tbtt_tasklet;
+	struct tasklet_struct rxdone_tasklet;
+	struct tasklet_struct autowake_tasklet;
+
+	/*
+	 * Protect the interrupt mask register.
+	 */
+	spinlock_t irqmask_lock;
 };
 
 /*
@@ -1046,12 +1063,24 @@
 void rt2x00queue_unmap_skb(struct queue_entry *entry);
 
 /**
- * rt2x00queue_get_queue - Convert queue index to queue pointer
+ * rt2x00queue_get_tx_queue - Convert tx queue index to queue pointer
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  * @queue: rt2x00 queue index (see &enum data_queue_qid).
+ *
+ * Returns NULL for non tx queues.
  */
-struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
-					 const enum data_queue_qid queue);
+static inline struct data_queue *
+rt2x00queue_get_tx_queue(struct rt2x00_dev *rt2x00dev,
+			 const enum data_queue_qid queue)
+{
+	if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
+		return &rt2x00dev->tx[queue];
+
+	if (queue == QID_ATIM)
+		return rt2x00dev->atim;
+
+	return NULL;
+}
 
 /**
  * rt2x00queue_get_entry - Get queue entry where the given index points to.
@@ -1102,7 +1131,7 @@
  * @drop: True to drop all pending frames.
  *
  * This function will flush the queue. After this call
- * the queue is guarenteed to be empty.
+ * the queue is guaranteed to be empty.
  */
 void rt2x00queue_flush_queue(struct data_queue *queue, bool drop);
 
@@ -1168,7 +1197,7 @@
 /*
  * mac80211 handlers.
  */
-int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
+void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb);
 int rt2x00mac_start(struct ieee80211_hw *hw);
 void rt2x00mac_stop(struct ieee80211_hw *hw);
 int rt2x00mac_add_interface(struct ieee80211_hw *hw,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00ht.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,12 +38,12 @@
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
 
 	if (tx_info->control.sta)
-		txdesc->mpdu_density =
+		txdesc->u.ht.mpdu_density =
 		    tx_info->control.sta->ht_cap.ampdu_density;
 
-	txdesc->ba_size = 7;	/* FIXME: What value is needed? */
+	txdesc->u.ht.ba_size = 7;	/* FIXME: What value is needed? */
 
-	txdesc->stbc =
+	txdesc->u.ht.stbc =
 	    (tx_info->flags & IEEE80211_TX_CTL_STBC) >> IEEE80211_TX_CTL_STBC_SHIFT;
 
 	/*
@@ -51,25 +51,24 @@
 	 * mcs rate to be used
 	 */
 	if (txrate->flags & IEEE80211_TX_RC_MCS) {
-		txdesc->mcs = txrate->idx;
+		txdesc->u.ht.mcs = txrate->idx;
 
 		/*
 		 * MIMO PS should be set to 1 for STA's using dynamic SM PS
 		 * when using more then one tx stream (>MCS7).
 		 */
-		if (tx_info->control.sta && txdesc->mcs > 7 &&
+		if (tx_info->control.sta && txdesc->u.ht.mcs > 7 &&
 		    ((tx_info->control.sta->ht_cap.cap &
 		      IEEE80211_HT_CAP_SM_PS) >>
 		     IEEE80211_HT_CAP_SM_PS_SHIFT) ==
 		    WLAN_HT_CAP_SM_PS_DYNAMIC)
 			__set_bit(ENTRY_TXD_HT_MIMO_PS, &txdesc->flags);
 	} else {
-		txdesc->mcs = rt2x00_get_rate_mcs(hwrate->mcs);
+		txdesc->u.ht.mcs = rt2x00_get_rate_mcs(hwrate->mcs);
 		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			txdesc->mcs |= 0x08;
+			txdesc->u.ht.mcs |= 0x08;
 	}
 
-
 	/*
 	 * This frame is eligible for an AMPDU, however, don't aggregate
 	 * frames that are intended to probe a specific tx rate.
@@ -79,14 +78,6 @@
 		__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;
-
-	/*
 	 * Set 40Mhz mode if necessary (for legacy rates this will
 	 * duplicate the frame to both channels).
 	 */
@@ -106,11 +97,11 @@
 	 * for frames not transmitted with TXOP_HTTXOP
 	 */
 	if (ieee80211_is_mgmt(hdr->frame_control))
-		txdesc->txop = TXOP_BACKOFF;
+		txdesc->u.ht.txop = TXOP_BACKOFF;
 	else if (!(tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT))
-		txdesc->txop = TXOP_SIFS;
+		txdesc->u.ht.txop = TXOP_SIFS;
 	else
-		txdesc->txop = TXOP_HTTXOP;
+		txdesc->u.ht.txop = TXOP_HTTXOP;
 }
 
 u16 rt2x00ht_center_channel(struct rt2x00_dev *rt2x00dev,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00lib.h	2011-05-19 00:06:34.000000000 -0400
@@ -157,14 +157,30 @@
 			       bool local);
 
 /**
- * rt2x00queue_update_beacon - Send new beacon from mac80211 to hardware
+ * rt2x00queue_update_beacon - Send new beacon from mac80211
+ *	to hardware. Handles locking by itself (mutex).
  * @rt2x00dev: Pointer to &struct rt2x00_dev.
  * @vif: Interface for which the beacon should be updated.
- * @enable_beacon: Enable beaconing
  */
 int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif,
-			      const bool enable_beacon);
+			      struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_update_beacon_locked - Send new beacon from mac80211
+ *	to hardware. Caller needs to ensure locking.
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif);
+
+/**
+ * rt2x00queue_clear_beacon - Clear beacon in hardware
+ * @rt2x00dev: Pointer to &struct rt2x00_dev.
+ * @vif: Interface for which the beacon should be updated.
+ */
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+			     struct ieee80211_vif *vif);
 
 /**
  * rt2x00queue_index_inc - Index incrementation function
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00link.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00link.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00link.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00link.c	2011-05-19 00:06:34.000000000 -0400
@@ -283,7 +283,7 @@
 	/**
 	 * While scanning, link tuning is disabled. By default
 	 * the most sensitive settings will be used to make sure
-	 * that all beacons and probe responses will be recieved
+	 * that all beacons and probe responses will be received
 	 * during the scan.
 	 */
 	if (test_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags))
@@ -417,7 +417,8 @@
 	    !test_bit(DRIVER_SUPPORT_WATCHDOG, &rt2x00dev->flags))
 		return;
 
-	schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
+	ieee80211_queue_delayed_work(rt2x00dev->hw,
+				     &link->watchdog_work, WATCHDOG_INTERVAL);
 }
 
 void rt2x00link_stop_watchdog(struct rt2x00_dev *rt2x00dev)
@@ -441,7 +442,9 @@
 	rt2x00dev->ops->lib->watchdog(rt2x00dev);
 
 	if (test_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags))
-		schedule_delayed_work(&link->watchdog_work, WATCHDOG_INTERVAL);
+		ieee80211_queue_delayed_work(rt2x00dev->hw,
+					     &link->watchdog_work,
+					     WATCHDOG_INTERVAL);
 }
 
 void rt2x00link_register(struct rt2x00_dev *rt2x00dev)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 	return retval;
 }
 
-int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -116,13 +116,13 @@
 		goto exit_fail;
 
 	/*
-	 * Determine which queue to put packet on.
+	 * Use the ATIM queue if appropriate and present.
 	 */
 	if (tx_info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM &&
 	    test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags))
-		queue = rt2x00queue_get_queue(rt2x00dev, QID_ATIM);
-	else
-		queue = rt2x00queue_get_queue(rt2x00dev, qid);
+		qid = QID_ATIM;
+
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, qid);
 	if (unlikely(!queue)) {
 		ERROR(rt2x00dev,
 		      "Attempt to send packet over invalid queue %d.\n"
@@ -139,9 +139,9 @@
 	 * either RTS or CTS-to-self frame and handles everything
 	 * inside the hardware.
 	 */
-	if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
-						IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
-	    !rt2x00dev->ops->hw->set_rts_threshold) {
+	if (!rt2x00dev->ops->hw->set_rts_threshold &&
+	    (tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
+						IEEE80211_TX_RC_USE_CTS_PROTECT))) {
 		if (rt2x00queue_available(queue) <= 1)
 			goto exit_fail;
 
@@ -149,18 +149,17 @@
 			goto exit_fail;
 	}
 
-	if (rt2x00queue_write_tx_frame(queue, skb, false))
+	if (unlikely(rt2x00queue_write_tx_frame(queue, skb, false)))
 		goto exit_fail;
 
 	if (rt2x00queue_threshold(queue))
 		rt2x00queue_pause_queue(queue);
 
-	return NETDEV_TX_OK;
+	return;
 
  exit_fail:
 	ieee80211_stop_queue(rt2x00dev->hw, qid);
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 EXPORT_SYMBOL_GPL(rt2x00mac_tx);
 
@@ -191,7 +190,7 @@
 {
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	struct data_queue *queue = rt2x00queue_get_queue(rt2x00dev, QID_BEACON);
+	struct data_queue *queue = rt2x00dev->bcn;
 	struct queue_entry *entry = NULL;
 	unsigned int i;
 
@@ -519,11 +518,9 @@
 
 	crypto.cmd = cmd;
 
-	if (sta) {
-		/* some drivers need the AID */
-		crypto.aid = sta->aid;
+	if (sta)
 		crypto.address = sta->addr;
-	} else
+	else
 		crypto.address = bcast_addr;
 
 	if (crypto.cipher == CIPHER_TKIP)
@@ -617,11 +614,47 @@
 				      bss_conf->bssid);
 
 	/*
-	 * Update the beacon.
+	 * Update the beacon. This is only required on USB devices. PCI
+	 * devices fetch beacons periodically.
 	 */
-	if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED))
-		rt2x00queue_update_beacon(rt2x00dev, vif,
-					  bss_conf->enable_beacon);
+	if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev))
+		rt2x00queue_update_beacon(rt2x00dev, vif);
+
+	/*
+	 * Start/stop beaconing.
+	 */
+	if (changes & BSS_CHANGED_BEACON_ENABLED) {
+		if (!bss_conf->enable_beacon && intf->enable_beacon) {
+			rt2x00queue_clear_beacon(rt2x00dev, vif);
+			rt2x00dev->intf_beaconing--;
+			intf->enable_beacon = false;
+
+			if (rt2x00dev->intf_beaconing == 0) {
+				/*
+				 * Last beaconing interface disabled
+				 * -> stop beacon queue.
+				 */
+				mutex_lock(&intf->beacon_skb_mutex);
+				rt2x00queue_stop_queue(rt2x00dev->bcn);
+				mutex_unlock(&intf->beacon_skb_mutex);
+			}
+
+
+		} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
+			rt2x00dev->intf_beaconing++;
+			intf->enable_beacon = true;
+
+			if (rt2x00dev->intf_beaconing == 1) {
+				/*
+				 * First beaconing interface enabled
+				 * -> start beacon queue.
+				 */
+				mutex_lock(&intf->beacon_skb_mutex);
+				rt2x00queue_start_queue(rt2x00dev->bcn);
+				mutex_unlock(&intf->beacon_skb_mutex);
+			}
+		}
+	}
 
 	/*
 	 * When the association status has changed we must reset the link
@@ -657,7 +690,7 @@
 	struct rt2x00_dev *rt2x00dev = hw->priv;
 	struct data_queue *queue;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 	if (unlikely(!queue))
 		return -EINVAL;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,10 +160,9 @@
 	/*
 	 * Register interrupt handler.
 	 */
-	status = request_threaded_irq(rt2x00dev->irq,
-				      rt2x00dev->ops->lib->irq_handler,
-				      rt2x00dev->ops->lib->irq_handler_thread,
-				      IRQF_SHARED, rt2x00dev->name, 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",
 		      rt2x00dev->irq, status);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00queue.c	2011-05-19 00:06:34.000000000 -0400
@@ -221,14 +221,17 @@
 	struct rt2x00_intf *intf = vif_to_intf(tx_info->control.vif);
 	unsigned long irqflags;
 
-	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) ||
-	    unlikely(!tx_info->control.vif))
+	if (!(tx_info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ))
+		return;
+
+	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
+
+	if (!test_bit(DRIVER_REQUIRE_SW_SEQNO, &entry->queue->rt2x00dev->flags))
 		return;
 
 	/*
-	 * Hardware should insert sequence counter.
-	 * FIXME: We insert a software sequence counter first for
-	 * hardware that doesn't support hardware sequence counting.
+	 * The hardware is not able to insert a sequence number. Assign a
+	 * software generated one here.
 	 *
 	 * This is wrong because beacons are not getting sequence
 	 * numbers assigned properly.
@@ -246,7 +249,6 @@
 
 	spin_unlock_irqrestore(&intf->seqlock, irqflags);
 
-	__set_bit(ENTRY_TXD_GENERATE_SEQ, &txdesc->flags);
 }
 
 static void rt2x00queue_create_tx_descriptor_plcp(struct queue_entry *entry,
@@ -260,6 +262,16 @@
 	unsigned int duration;
 	unsigned int residual;
 
+	/*
+	 * Determine with what IFS priority this frame should be send.
+	 * Set ifs to IFS_SIFS when the this is not the first fragment,
+	 * or this fragment came after RTS/CTS.
+	 */
+	if (test_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags))
+		txdesc->u.plcp.ifs = IFS_BACKOFF;
+	else
+		txdesc->u.plcp.ifs = IFS_SIFS;
+
 	/* Data length + CRC + Crypto overhead (IV/EIV/ICV/MIC) */
 	data_length = entry->skb->len + 4;
 	data_length += rt2x00crypto_tx_overhead(rt2x00dev, entry->skb);
@@ -268,12 +280,12 @@
 	 * PLCP setup
 	 * Length calculation depends on OFDM/CCK rate.
 	 */
-	txdesc->signal = hwrate->plcp;
-	txdesc->service = 0x04;
+	txdesc->u.plcp.signal = hwrate->plcp;
+	txdesc->u.plcp.service = 0x04;
 
 	if (hwrate->flags & DEV_RATE_OFDM) {
-		txdesc->length_high = (data_length >> 6) & 0x3f;
-		txdesc->length_low = data_length & 0x3f;
+		txdesc->u.plcp.length_high = (data_length >> 6) & 0x3f;
+		txdesc->u.plcp.length_low = data_length & 0x3f;
 	} else {
 		/*
 		 * Convert length to microseconds.
@@ -288,18 +300,18 @@
 			 * Check if we need to set the Length Extension
 			 */
 			if (hwrate->bitrate == 110 && residual <= 30)
-				txdesc->service |= 0x80;
+				txdesc->u.plcp.service |= 0x80;
 		}
 
-		txdesc->length_high = (duration >> 8) & 0xff;
-		txdesc->length_low = duration & 0xff;
+		txdesc->u.plcp.length_high = (duration >> 8) & 0xff;
+		txdesc->u.plcp.length_low = duration & 0xff;
 
 		/*
 		 * When preamble is enabled we should set the
 		 * preamble bit for the signal.
 		 */
 		if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
-			txdesc->signal |= 0x08;
+			txdesc->u.plcp.signal |= 0x08;
 	}
 }
 
@@ -309,9 +321,9 @@
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)entry->skb->data;
-	struct ieee80211_rate *rate =
-	    ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
-	const struct rt2x00_rate *hwrate;
+	struct ieee80211_tx_rate *txrate = &tx_info->control.rates[0];
+	struct ieee80211_rate *rate;
+	const struct rt2x00_rate *hwrate = NULL;
 
 	memset(txdesc, 0, sizeof(*txdesc));
 
@@ -365,42 +377,42 @@
 
 	/*
 	 * Beacons and probe responses require the tsf timestamp
-	 * to be inserted into the frame, except for a frame that has been injected
-	 * through a monitor interface. This latter is needed for testing a
-	 * monitor interface.
+	 * to be inserted into the frame.
 	 */
-	if ((ieee80211_is_beacon(hdr->frame_control) ||
-	    ieee80211_is_probe_resp(hdr->frame_control)) &&
-	    (!(tx_info->flags & IEEE80211_TX_CTL_INJECTED)))
+	if (ieee80211_is_beacon(hdr->frame_control) ||
+	    ieee80211_is_probe_resp(hdr->frame_control))
 		__set_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags);
 
-	/*
-	 * Determine with what IFS priority this frame should be send.
-	 * Set ifs to IFS_SIFS when the this is not the first fragment,
-	 * or this fragment came after RTS/CTS.
-	 */
 	if ((tx_info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) &&
-	    !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags)) {
+	    !test_bit(ENTRY_TXD_RTS_FRAME, &txdesc->flags))
 		__set_bit(ENTRY_TXD_FIRST_FRAGMENT, &txdesc->flags);
-		txdesc->ifs = IFS_BACKOFF;
-	} else
-		txdesc->ifs = IFS_SIFS;
 
 	/*
 	 * Determine rate modulation.
 	 */
-	hwrate = rt2x00_get_rate(rate->hw_value);
-	txdesc->rate_mode = RATE_MODE_CCK;
-	if (hwrate->flags & DEV_RATE_OFDM)
-		txdesc->rate_mode = RATE_MODE_OFDM;
+	if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
+		txdesc->rate_mode = RATE_MODE_HT_GREENFIELD;
+	else if (txrate->flags & IEEE80211_TX_RC_MCS)
+		txdesc->rate_mode = RATE_MODE_HT_MIX;
+	else {
+		rate = ieee80211_get_tx_rate(rt2x00dev->hw, tx_info);
+		hwrate = rt2x00_get_rate(rate->hw_value);
+		if (hwrate->flags & DEV_RATE_OFDM)
+			txdesc->rate_mode = RATE_MODE_OFDM;
+		else
+			txdesc->rate_mode = RATE_MODE_CCK;
+	}
 
 	/*
 	 * 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);
+
+	if (test_bit(DRIVER_REQUIRE_HT_TX_DESC, &rt2x00dev->flags))
+		rt2x00ht_create_tx_descriptor(entry, txdesc, hwrate);
+	else
+		rt2x00queue_create_tx_descriptor_plcp(entry, txdesc, hwrate);
 }
 
 static int rt2x00queue_write_tx_data(struct queue_entry *entry,
@@ -534,7 +546,7 @@
 	}
 
 	/*
-	 * When DMA allocation is required we should guarentee to the
+	 * When DMA allocation is required we should guarantee to the
 	 * driver that the DMA is aligned to a 4-byte boundary.
 	 * However some drivers require L2 padding to pad the payload
 	 * rather then the header. This could be a requirement for
@@ -566,13 +578,10 @@
 	return 0;
 }
 
-int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
-			      struct ieee80211_vif *vif,
-			      const bool enable_beacon)
+int rt2x00queue_clear_beacon(struct rt2x00_dev *rt2x00dev,
+			     struct ieee80211_vif *vif)
 {
 	struct rt2x00_intf *intf = vif_to_intf(vif);
-	struct skb_frame_desc *skbdesc;
-	struct txentry_desc txdesc;
 
 	if (unlikely(!intf->beacon))
 		return -ENOBUFS;
@@ -584,17 +593,36 @@
 	 */
 	rt2x00queue_free_skb(intf->beacon);
 
-	if (!enable_beacon) {
-		rt2x00queue_stop_queue(intf->beacon->queue);
-		mutex_unlock(&intf->beacon_skb_mutex);
-		return 0;
-	}
+	/*
+	 * Clear beacon (single bssid devices don't need to clear the beacon
+	 * since the beacon queue will get stopped anyway).
+	 */
+	if (rt2x00dev->ops->lib->clear_beacon)
+		rt2x00dev->ops->lib->clear_beacon(intf->beacon);
+
+	mutex_unlock(&intf->beacon_skb_mutex);
+
+	return 0;
+}
+
+int rt2x00queue_update_beacon_locked(struct rt2x00_dev *rt2x00dev,
+				     struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+	struct skb_frame_desc *skbdesc;
+	struct txentry_desc txdesc;
+
+	if (unlikely(!intf->beacon))
+		return -ENOBUFS;
+
+	/*
+	 * Clean up the beacon skb.
+	 */
+	rt2x00queue_free_skb(intf->beacon);
 
 	intf->beacon->skb = ieee80211_beacon_get(rt2x00dev->hw, vif);
-	if (!intf->beacon->skb) {
-		mutex_unlock(&intf->beacon_skb_mutex);
+	if (!intf->beacon->skb)
 		return -ENOMEM;
-	}
 
 	/*
 	 * Copy all TX descriptor information into txdesc,
@@ -611,13 +639,25 @@
 	skbdesc->entry = intf->beacon;
 
 	/*
-	 * Send beacon to hardware and enable beacon genaration..
+	 * Send beacon to hardware.
 	 */
 	rt2x00dev->ops->lib->write_beacon(intf->beacon, &txdesc);
 
+	return 0;
+
+}
+
+int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
+			      struct ieee80211_vif *vif)
+{
+	struct rt2x00_intf *intf = vif_to_intf(vif);
+	int ret;
+
+	mutex_lock(&intf->beacon_skb_mutex);
+	ret = rt2x00queue_update_beacon_locked(rt2x00dev, vif);
 	mutex_unlock(&intf->beacon_skb_mutex);
 
-	return 0;
+	return ret;
 }
 
 void rt2x00queue_for_each_entry(struct data_queue *queue,
@@ -649,7 +689,7 @@
 	spin_unlock_irqrestore(&queue->index_lock, irqflags);
 
 	/*
-	 * Start from the TX done pointer, this guarentees that we will
+	 * Start from the TX done pointer, this guarantees that we will
 	 * send out all frames in the correct order.
 	 */
 	if (index_start < index_end) {
@@ -665,29 +705,6 @@
 }
 EXPORT_SYMBOL_GPL(rt2x00queue_for_each_entry);
 
-struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
-					 const enum data_queue_qid queue)
-{
-	int atim = test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags);
-
-	if (queue == QID_RX)
-		return rt2x00dev->rx;
-
-	if (queue < rt2x00dev->ops->tx_queues && rt2x00dev->tx)
-		return &rt2x00dev->tx[queue];
-
-	if (!rt2x00dev->bcn)
-		return NULL;
-
-	if (queue == QID_BEACON)
-		return &rt2x00dev->bcn[0];
-	else if (queue == QID_ATIM && atim)
-		return &rt2x00dev->bcn[1];
-
-	return NULL;
-}
-EXPORT_SYMBOL_GPL(rt2x00queue_get_queue);
-
 struct queue_entry *rt2x00queue_get_entry(struct data_queue *queue,
 					  enum queue_index index)
 {
@@ -866,7 +883,7 @@
 	}
 
 	/*
-	 * Check if driver supports flushing, we can only guarentee
+	 * Check if driver supports flushing, we can only guarantee
 	 * full support for flushing if the driver is able
 	 * to cancel all pending frames (drop = true).
 	 */
@@ -885,7 +902,7 @@
 	 * The queue flush has failed...
 	 */
 	if (unlikely(!rt2x00queue_empty(queue)))
-		WARNING(queue->rt2x00dev, "Queue %d failed to flush", queue->qid);
+		WARNING(queue->rt2x00dev, "Queue %d failed to flush\n", queue->qid);
 
 	/*
 	 * Restore the queue to the previous status
@@ -1063,7 +1080,7 @@
 		goto exit;
 
 	if (test_bit(DRIVER_REQUIRE_ATIM_QUEUE, &rt2x00dev->flags)) {
-		status = rt2x00queue_alloc_entries(&rt2x00dev->bcn[1],
+		status = rt2x00queue_alloc_entries(rt2x00dev->atim,
 						   rt2x00dev->ops->atim);
 		if (status)
 			goto exit;
@@ -1137,6 +1154,7 @@
 	rt2x00dev->rx = queue;
 	rt2x00dev->tx = &queue[1];
 	rt2x00dev->bcn = &queue[1 + rt2x00dev->ops->tx_queues];
+	rt2x00dev->atim = req_atim ? &queue[2 + rt2x00dev->ops->tx_queues] : NULL;
 
 	/*
 	 * Initialize queue parameters.
@@ -1153,9 +1171,9 @@
 	tx_queue_for_each(rt2x00dev, queue)
 		rt2x00queue_init(rt2x00dev, queue, qid++);
 
-	rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[0], QID_BEACON);
+	rt2x00queue_init(rt2x00dev, rt2x00dev->bcn, QID_BEACON);
 	if (req_atim)
-		rt2x00queue_init(rt2x00dev, &rt2x00dev->bcn[1], QID_ATIM);
+		rt2x00queue_init(rt2x00dev, rt2x00dev->atim, QID_ATIM);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00queue.h	2011-05-19 00:06:34.000000000 -0400
@@ -305,20 +305,27 @@
 	u16 length;
 	u16 header_length;
 
-	u16 length_high;
-	u16 length_low;
-	u16 signal;
-	u16 service;
+	union {
+		struct {
+			u16 length_high;
+			u16 length_low;
+			u16 signal;
+			u16 service;
+			enum ifs ifs;
+		} plcp;
 
-	u16 mcs;
-	u16 stbc;
-	u16 ba_size;
-	u16 rate_mode;
-	u16 mpdu_density;
+		struct {
+			u16 mcs;
+			u8 stbc;
+			u8 ba_size;
+			u8 mpdu_density;
+			enum txop txop;
+		} ht;
+	} u;
+
+	enum rate_modulation rate_mode;
 
 	short retry_limit;
-	short ifs;
-	short txop;
 
 	enum cipher cipher;
 	u16 key_idx;
@@ -337,8 +344,8 @@
  *	only be touched after the device has signaled it is done with it.
  * @ENTRY_DATA_PENDING: This entry contains a valid frame and is waiting
  *	for the signal to start sending.
- * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occured
- *	while transfering the data to the hardware. No TX status report will
+ * @ENTRY_DATA_IO_FAILED: Hardware indicated that an IO error occurred
+ *	while transferring the data to the hardware. No TX status report will
  *	be expected from the hardware.
  * @ENTRY_DATA_STATUS_PENDING: The entry has been send to the device and
  *	returned. It is now waiting for the status reporting before the
@@ -358,7 +365,7 @@
  * @flags: Entry flags, see &enum queue_entry_flags.
  * @queue: The data queue (&struct data_queue) to which this entry belongs.
  * @skb: The buffer which is currently being transmitted (for TX queue),
- *	or used to directly recieve data in (for RX queue).
+ *	or used to directly receive data in (for RX queue).
  * @entry_idx: The entry index number.
  * @priv_data: Private data belonging to this queue entry. The pointer
  *	points to data specific to a particular driver and queue type.
@@ -381,7 +388,7 @@
  * @Q_INDEX: Index pointer to the current entry in the queue, if this entry is
  *	owned by the hardware then the queue is considered to be full.
  * @Q_INDEX_DMA_DONE: Index pointer for the next entry which will have been
- *	transfered to the hardware.
+ *	transferred to the hardware.
  * @Q_INDEX_DONE: Index pointer to the next entry which will be completed by
  *	the hardware and for which we need to run the txdone handler. If this
  *	entry is not owned by the hardware the queue is considered to be empty.
@@ -620,7 +627,7 @@
 }
 
 /**
- * rt2x00queue_status_timeout - Check if a timeout occured for STATUS reports
+ * rt2x00queue_status_timeout - Check if a timeout occurred for STATUS reports
  * @queue: Queue to check.
  */
 static inline int rt2x00queue_status_timeout(struct data_queue *queue)
@@ -630,7 +637,7 @@
 }
 
 /**
- * rt2x00queue_timeout - Check if a timeout occured for DMA transfers
+ * rt2x00queue_timeout - Check if a timeout occurred for DMA transfers
  * @queue: Queue to check.
  */
 static inline int rt2x00queue_dma_timeout(struct data_queue *queue)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00reg.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00reg.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -85,8 +85,6 @@
 	STATE_RADIO_OFF,
 	STATE_RADIO_IRQ_ON,
 	STATE_RADIO_IRQ_OFF,
-	STATE_RADIO_IRQ_ON_ISR,
-	STATE_RADIO_IRQ_OFF_ISR,
 };
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00usb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -173,7 +173,7 @@
 	/*
 	 * If the transfer to hardware succeeded, it does not mean the
 	 * frame was send out correctly. It only means the frame
-	 * was succesfully pushed to the hardware, we have no
+	 * was successfully pushed to the hardware, we have no
 	 * way to determine the transmission status right now.
 	 * (Only indirectly by looking at the failed TX counters
 	 * in the register).
@@ -227,7 +227,7 @@
 	 * Schedule the delayed work for reading the TX status
 	 * from the device.
 	 */
-	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->txdone_work);
+	queue_work(rt2x00dev->workqueue, &rt2x00dev->txdone_work);
 }
 
 static void rt2x00usb_kick_tx_entry(struct queue_entry *entry)
@@ -320,7 +320,7 @@
 	 * Schedule the delayed work for reading the RX status
 	 * from the device.
 	 */
-	ieee80211_queue_work(rt2x00dev->hw, &rt2x00dev->rxdone_work);
+	queue_work(rt2x00dev->workqueue, &rt2x00dev->rxdone_work);
 }
 
 static void rt2x00usb_kick_rx_entry(struct queue_entry *entry)
@@ -429,7 +429,7 @@
 		 * Schedule the completion handler manually, when this
 		 * worker function runs, it should cleanup the queue.
 		 */
-		ieee80211_queue_work(queue->rt2x00dev->hw, completion);
+		queue_work(queue->rt2x00dev->workqueue, completion);
 
 		/*
 		 * Wait for a little while to give the driver
@@ -453,7 +453,7 @@
 	WARNING(queue->rt2x00dev, "TX queue %d status timed out,"
 		" invoke forced tx handler\n", queue->qid);
 
-	ieee80211_queue_work(queue->rt2x00dev->hw, &queue->rt2x00dev->txdone_work);
+	queue_work(queue->rt2x00dev->workqueue, &queue->rt2x00dev->txdone_work);
 }
 
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00usb.h linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00usb.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt2x00usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt2x00usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -400,7 +400,7 @@
  * @rt2x00dev: Pointer to &struct rt2x00_dev
  *
  * Check the health of the USB communication and determine
- * if timeouts have occured. If this is the case, this function
+ * if timeouts have occurred. If this is the case, this function
  * will reset all communication to restore functionality again.
  */
 void rt2x00usb_watchdog(struct rt2x00_dev *rt2x00dev);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt61pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt61pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt61pci.c	2012-03-24 01:14:03.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt61pci.c	2012-03-24 03:34:13.000000000 -0400
@@ -551,26 +551,14 @@
 				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);
-		rt2x00pci_register_write(rt2x00dev, beacon_base, 0);
-
-		/*
 		 * Enable synchronisation.
 		 */
 		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 	}
 
@@ -1154,6 +1142,11 @@
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
 		break;
 	case QID_BEACON:
+		/*
+		 * Allow the tbtt tasklet to be scheduled.
+		 */
+		tasklet_enable(&rt2x00dev->tbtt_tasklet);
+
 		rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
@@ -1233,6 +1226,11 @@
 		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 0);
 		rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+		/*
+		 * Wait for possibly running tbtt tasklets.
+		 */
+		tasklet_disable(&rt2x00dev->tbtt_tasklet);
 		break;
 	default:
 		break;
@@ -1719,9 +1717,9 @@
 static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
 			       enum dev_state state)
 {
-	int mask = (state == STATE_RADIO_IRQ_OFF) ||
-		   (state == STATE_RADIO_IRQ_OFF_ISR);
+	int mask = (state == STATE_RADIO_IRQ_OFF);
 	u32 reg;
+	unsigned long flags;
 
 	/*
 	 * When interrupts are being enabled, the interrupt registers
@@ -1733,12 +1731,21 @@
 
 		rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
 		rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
+
+		/*
+		 * Enable tasklets.
+		 */
+		tasklet_enable(&rt2x00dev->txstatus_tasklet);
+		tasklet_enable(&rt2x00dev->rxdone_tasklet);
+		tasklet_enable(&rt2x00dev->autowake_tasklet);
 	}
 
 	/*
 	 * Only toggle the interrupts bits we are going to use.
 	 * Non-checked interrupt bits are disabled by default.
 	 */
+	spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
+
 	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_TXDONE, mask);
 	rt2x00_set_field32(&reg, INT_MASK_CSR_RXDONE, mask);
@@ -1758,6 +1765,17 @@
 	rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_7, mask);
 	rt2x00_set_field32(&reg, MCU_INT_MASK_CSR_TWAKEUP, mask);
 	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+	spin_unlock_irqrestore(&rt2x00dev->irqmask_lock, flags);
+
+	if (state == STATE_RADIO_IRQ_OFF) {
+		/*
+		 * Ensure that all tasklets are finished.
+		 */
+		tasklet_disable(&rt2x00dev->txstatus_tasklet);
+		tasklet_disable(&rt2x00dev->rxdone_tasklet);
+		tasklet_disable(&rt2x00dev->autowake_tasklet);
+	}
 }
 
 static int rt61pci_enable_radio(struct rt2x00_dev *rt2x00dev)
@@ -1833,9 +1851,7 @@
 		rt61pci_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		rt61pci_toggle_irq(rt2x00dev, state);
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1882,10 +1898,12 @@
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
@@ -1930,7 +1948,7 @@
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_OFDM,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
@@ -1962,13 +1980,14 @@
 	struct queue_entry_priv_pci *entry_priv = entry->priv_data;
 	unsigned int beacon_base;
 	unsigned int padding_len;
-	u32 reg;
+	u32 orig_reg, reg;
 
 	/*
 	 * Disable beaconing while we are reloading the beacon data,
 	 * otherwise we might be sending out invalid data.
 	 */
 	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	orig_reg = reg;
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -1986,7 +2005,14 @@
 	 * Write entire beacon with descriptor and padding to register.
 	 */
 	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-	skb_pad(entry->skb, padding_len);
+	if (padding_len && skb_pad(entry->skb, padding_len)) {
+		ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+		/* skb freed by skb_pad() on failure */
+		entry->skb = NULL;
+		rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+		return;
+	}
+
 	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 	rt2x00pci_register_multiwrite(rt2x00dev, beacon_base,
 				      entry_priv->desc, TXINFO_SIZE);
@@ -2002,8 +2028,6 @@
 	 */
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
 
-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
 	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -2014,6 +2038,32 @@
 	entry->skb = NULL;
 }
 
+static void rt61pci_clear_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	u32 reg;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+	/*
+	 * Clear beacon.
+	 */
+	rt2x00pci_register_write(rt2x00dev,
+				 HW_BEACON_OFFSET(entry->entry_idx), 0);
+
+	/*
+	 * Enable beaconing again.
+	 */
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+	rt2x00pci_register_write(rt2x00dev, TXRX_CSR9, reg);
+}
+
 /*
  * RX control handlers
  */
@@ -2078,9 +2128,8 @@
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
 
 		/*
-		 * FIXME: Legacy driver indicates that the frame does
-		 * contain the Michael Mic. Unfortunately, in rt2x00
-		 * the MIC seems to be missing completely...
+		 * The hardware has already checked the Michael Mic and has
+		 * stripped it from the frame. Signal this to mac80211.
 		 */
 		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
 
@@ -2143,7 +2192,7 @@
 		 * queue identication number.
 		 */
 		type = rt2x00_get_field32(reg, STA_CSR4_PID_TYPE);
-		queue = rt2x00queue_get_queue(rt2x00dev, type);
+		queue = rt2x00queue_get_tx_queue(rt2x00dev, type);
 		if (unlikely(!queue))
 			continue;
 
@@ -2211,61 +2260,77 @@
 	rt61pci_config(rt2x00dev, &libconf, IEEE80211_CONF_CHANGE_PS);
 }
 
-static irqreturn_t rt61pci_interrupt_thread(int irq, void *dev_instance)
+static void rt61pci_enable_interrupt(struct rt2x00_dev *rt2x00dev,
+				     struct rt2x00_field32 irq_field)
 {
-	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg = rt2x00dev->irqvalue[0];
-	u32 reg_mcu = rt2x00dev->irqvalue[1];
+	u32 reg;
 
 	/*
-	 * Handle interrupts, walk through all bits
-	 * and run the tasks, the bits are checked in order of
-	 * priority.
+	 * Enable a single interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 1 - Rx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
-		rt2x00pci_rxdone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
 
-	/*
-	 * 2 - Tx ring done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE))
-		rt61pci_txdone(rt2x00dev);
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
+}
 
-	/*
-	 * 3 - Handle MCU command done.
-	 */
-	if (reg_mcu)
-		rt2x00pci_register_write(rt2x00dev,
-					 M2H_CMD_DONE_CSR, 0xffffffff);
+static void rt61pci_enable_mcu_interrupt(struct rt2x00_dev *rt2x00dev,
+					 struct rt2x00_field32 irq_field)
+{
+	u32 reg;
 
 	/*
-	 * 4 - MCU Autowakeup interrupt.
+	 * Enable a single MCU interrupt. The interrupt mask register
+	 * access needs locking.
 	 */
-	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
-		rt61pci_wakeup(rt2x00dev);
+	spin_lock_irq(&rt2x00dev->irqmask_lock);
 
-	/*
-	 * 5 - Beacon done interrupt.
-	 */
-	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
-		rt2x00lib_beacondone(rt2x00dev);
+	rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+	rt2x00_set_field32(&reg, irq_field, 0);
+	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
 
-	/* Enable interrupts again. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_ON_ISR);
-	return IRQ_HANDLED;
+	spin_unlock_irq(&rt2x00dev->irqmask_lock);
 }
 
+static void rt61pci_txstatus_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt61pci_txdone(rt2x00dev);
+	rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
+}
+
+static void rt61pci_tbtt_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00lib_beacondone(rt2x00dev);
+	rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
+}
+
+static void rt61pci_rxdone_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt2x00pci_rxdone(rt2x00dev);
+	rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
+}
+
+static void rt61pci_autowake_tasklet(unsigned long data)
+{
+	struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
+	rt61pci_wakeup(rt2x00dev);
+	rt2x00pci_register_write(rt2x00dev,
+				 M2H_CMD_DONE_CSR, 0xffffffff);
+	rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
+}
 
 static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
 {
 	struct rt2x00_dev *rt2x00dev = dev_instance;
-	u32 reg_mcu;
-	u32 reg;
+	u32 reg_mcu, mask_mcu;
+	u32 reg, mask;
 
 	/*
 	 * Get the interrupt sources & saved to local variable.
@@ -2283,14 +2348,46 @@
 	if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
 		return IRQ_HANDLED;
 
-	/* Store irqvalues for use in the interrupt thread. */
-	rt2x00dev->irqvalue[0] = reg;
-	rt2x00dev->irqvalue[1] = reg_mcu;
+	/*
+	 * Schedule tasklets for interrupt handling.
+	 */
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RXDONE))
+		tasklet_schedule(&rt2x00dev->rxdone_tasklet);
 
-	/* Disable interrupts, will be enabled again in the interrupt thread. */
-	rt2x00dev->ops->lib->set_device_state(rt2x00dev,
-					      STATE_RADIO_IRQ_OFF_ISR);
-	return IRQ_WAKE_THREAD;
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TXDONE))
+		tasklet_schedule(&rt2x00dev->txstatus_tasklet);
+
+	if (rt2x00_get_field32(reg, INT_SOURCE_CSR_BEACON_DONE))
+		tasklet_hi_schedule(&rt2x00dev->tbtt_tasklet);
+
+	if (rt2x00_get_field32(reg_mcu, MCU_INT_SOURCE_CSR_TWAKEUP))
+		tasklet_schedule(&rt2x00dev->autowake_tasklet);
+
+	/*
+	 * Since INT_MASK_CSR and INT_SOURCE_CSR use the same bits
+	 * for interrupts and interrupt masks we can just use the value of
+	 * INT_SOURCE_CSR to create the interrupt mask.
+	 */
+	mask = reg;
+	mask_mcu = reg_mcu;
+
+	/*
+	 * Disable all interrupts for which a tasklet was scheduled right now,
+	 * the tasklet will reenable the appropriate interrupts.
+	 */
+	spin_lock(&rt2x00dev->irqmask_lock);
+
+	rt2x00pci_register_read(rt2x00dev, INT_MASK_CSR, &reg);
+	reg |= mask;
+	rt2x00pci_register_write(rt2x00dev, INT_MASK_CSR, reg);
+
+	rt2x00pci_register_read(rt2x00dev, MCU_INT_MASK_CSR, &reg);
+	reg |= mask_mcu;
+	rt2x00pci_register_write(rt2x00dev, MCU_INT_MASK_CSR, reg);
+
+	spin_unlock(&rt2x00dev->irqmask_lock);
+
+	return IRQ_HANDLED;
 }
 
 /*
@@ -2819,7 +2916,7 @@
 	if (queue_idx >= 4)
 		return 0;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 
 	/* Update WMM TXOP register */
 	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
@@ -2884,7 +2981,10 @@
 
 static const struct rt2x00lib_ops rt61pci_rt2x00_ops = {
 	.irq_handler		= rt61pci_interrupt,
-	.irq_handler_thread	= rt61pci_interrupt_thread,
+	.txstatus_tasklet	= rt61pci_txstatus_tasklet,
+	.tbtt_tasklet		= rt61pci_tbtt_tasklet,
+	.rxdone_tasklet		= rt61pci_rxdone_tasklet,
+	.autowake_tasklet	= rt61pci_autowake_tasklet,
 	.probe_hw		= rt61pci_probe_hw,
 	.get_firmware_name	= rt61pci_get_firmware_name,
 	.check_firmware		= rt61pci_check_firmware,
@@ -2903,6 +3003,7 @@
 	.stop_queue		= rt61pci_stop_queue,
 	.write_tx_desc		= rt61pci_write_tx_desc,
 	.write_beacon		= rt61pci_write_beacon,
+	.clear_beacon		= rt61pci_clear_beacon,
 	.fill_rxdone		= rt61pci_fill_rxdone,
 	.config_shared_key	= rt61pci_config_shared_key,
 	.config_pairwise_key	= rt61pci_config_pairwise_key,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt73usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt73usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rt2x00/rt73usb.c	2012-03-24 01:14:13.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rt2x00/rt73usb.c	2012-03-24 03:34:19.000000000 -0400
@@ -502,26 +502,14 @@
 				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, TXRX_CSR9, &reg);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
 		rt2x00_set_field32(&reg, TXRX_CSR9_TSF_SYNC, conf->sync);
-		rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 	}
 
@@ -1440,9 +1428,7 @@
 		rt73usb_disable_radio(rt2x00dev);
 		break;
 	case STATE_RADIO_IRQ_ON:
-	case STATE_RADIO_IRQ_ON_ISR:
 	case STATE_RADIO_IRQ_OFF:
-	case STATE_RADIO_IRQ_OFF_ISR:
 		/* No support, but no error either */
 		break;
 	case STATE_DEEP_SLEEP:
@@ -1488,7 +1474,7 @@
 			   test_bit(ENTRY_TXD_REQ_TIMESTAMP, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_OFDM,
 			   (txdesc->rate_mode == RATE_MODE_OFDM));
-	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->ifs);
+	rt2x00_set_field32(&word, TXD_W0_IFS, txdesc->u.plcp.ifs);
 	rt2x00_set_field32(&word, TXD_W0_RETRY_MODE,
 			   test_bit(ENTRY_TXD_RETRY_MODE, &txdesc->flags));
 	rt2x00_set_field32(&word, TXD_W0_TKIP_MIC,
@@ -1513,10 +1499,12 @@
 	rt2x00_desc_write(txd, 1, word);
 
 	rt2x00_desc_read(txd, 2, &word);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->signal);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->service);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW, txdesc->length_low);
-	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH, txdesc->length_high);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SIGNAL, txdesc->u.plcp.signal);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_SERVICE, txdesc->u.plcp.service);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_LOW,
+			   txdesc->u.plcp.length_low);
+	rt2x00_set_field32(&word, TXD_W2_PLCP_LENGTH_HIGH,
+			   txdesc->u.plcp.length_high);
 	rt2x00_desc_write(txd, 2, word);
 
 	if (test_bit(ENTRY_TXD_ENCRYPT, &txdesc->flags)) {
@@ -1547,13 +1535,14 @@
 	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
 	unsigned int beacon_base;
 	unsigned int padding_len;
-	u32 reg;
+	u32 orig_reg, reg;
 
 	/*
 	 * Disable beaconing while we are reloading the beacon data,
 	 * otherwise we might be sending out invalid data.
 	 */
 	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	orig_reg = reg;
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -1577,7 +1566,14 @@
 	 * Write entire beacon with descriptor and padding to register.
 	 */
 	padding_len = roundup(entry->skb->len, 4) - entry->skb->len;
-	skb_pad(entry->skb, padding_len);
+	if (padding_len && skb_pad(entry->skb, padding_len)) {
+		ERROR(rt2x00dev, "Failure padding beacon, aborting\n");
+		/* skb freed by skb_pad() on failure */
+		entry->skb = NULL;
+		rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, orig_reg);
+		return;
+	}
+
 	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
 	rt2x00usb_register_multiwrite(rt2x00dev, beacon_base, entry->skb->data,
 				      entry->skb->len + padding_len);
@@ -1590,8 +1586,6 @@
 	 */
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR10, 0x00001008);
 
-	rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
-	rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
 	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
 	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
 
@@ -1602,6 +1596,33 @@
 	entry->skb = NULL;
 }
 
+static void rt73usb_clear_beacon(struct queue_entry *entry)
+{
+	struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
+	unsigned int beacon_base;
+	u32 reg;
+
+	/*
+	 * Disable beaconing while we are reloading the beacon data,
+	 * otherwise we might be sending out invalid data.
+	 */
+	rt2x00usb_register_read(rt2x00dev, TXRX_CSR9, &reg);
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 0);
+	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+
+	/*
+	 * Clear beacon.
+	 */
+	beacon_base = HW_BEACON_OFFSET(entry->entry_idx);
+	rt2x00usb_register_write(rt2x00dev, beacon_base, 0);
+
+	/*
+	 * Enable beaconing again.
+	 */
+	rt2x00_set_field32(&reg, TXRX_CSR9_BEACON_GEN, 1);
+	rt2x00usb_register_write(rt2x00dev, TXRX_CSR9, reg);
+}
+
 static int rt73usb_get_tx_data_len(struct queue_entry *entry)
 {
 	int length;
@@ -1698,9 +1719,8 @@
 		rxdesc->flags |= RX_FLAG_IV_STRIPPED;
 
 		/*
-		 * FIXME: Legacy driver indicates that the frame does
-		 * contain the Michael Mic. Unfortunately, in rt2x00
-		 * the MIC seems to be missing completely...
+		 * The hardware has already checked the Michael Mic and has
+		 * stripped it from the frame. Signal this to mac80211.
 		 */
 		rxdesc->flags |= RX_FLAG_MMIC_STRIPPED;
 
@@ -2229,7 +2249,7 @@
 	if (queue_idx >= 4)
 		return 0;
 
-	queue = rt2x00queue_get_queue(rt2x00dev, queue_idx);
+	queue = rt2x00queue_get_tx_queue(rt2x00dev, queue_idx);
 
 	/* Update WMM TXOP register */
 	offset = AC_TXOP_CSR0 + (sizeof(u32) * (!!(queue_idx & 2)));
@@ -2313,6 +2333,7 @@
 	.flush_queue		= rt2x00usb_flush_queue,
 	.write_tx_desc		= rt73usb_write_tx_desc,
 	.write_beacon		= rt73usb_write_beacon,
+	.clear_beacon		= rt73usb_clear_beacon,
 	.get_tx_data_len	= rt73usb_get_tx_data_len,
 	.fill_rxdone		= rt73usb_fill_rxdone,
 	.config_shared_key	= rt73usb_config_shared_key,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtl818x/rtl8180/dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -146,7 +146,7 @@
 			rx_status.freq = dev->conf.channel->center_freq;
 			rx_status.band = dev->conf.channel->band;
 			rx_status.mactime = le64_to_cpu(entry->tsft);
-			rx_status.flag |= RX_FLAG_TSFT;
+			rx_status.flag |= RX_FLAG_MACTIME_MPDU;
 			if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
 				rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 
@@ -240,7 +240,7 @@
 	return IRQ_HANDLED;
 }
 
-static int rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void rtl8180_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
@@ -321,8 +321,6 @@
 	spin_unlock_irqrestore(&priv->lock, flags);
 
 	rtl818x_iowrite8(priv, &priv->map->TX_DMA_POLLING, (1 << (prio + 4)));
-
-	return 0;
 }
 
 void rtl8180_set_anaparam(struct rtl8180_priv *priv, u32 anaparam)
@@ -687,7 +685,6 @@
 	struct ieee80211_hw *dev = vif_priv->dev;
 	struct ieee80211_mgmt *mgmt;
 	struct sk_buff *skb;
-	int err = 0;
 
 	/* don't overflow the tx ring */
 	if (ieee80211_queue_stopped(dev, 0))
@@ -708,8 +705,7 @@
 	/* TODO: use actual beacon queue */
 	skb_set_queue_mapping(skb, 0);
 
-	err = rtl8180_tx(dev, skb);
-	WARN_ON(err);
+	rtl8180_tx(dev, skb);
 
 resched:
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtl818x/rtl8187/dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -227,7 +227,7 @@
 	}
 }
 
-static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
+static void rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb)
 {
 	struct rtl8187_priv *priv = dev->priv;
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -241,7 +241,7 @@
 	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		kfree_skb(skb);
-		return NETDEV_TX_OK;
+		return;
 	}
 
 	flags = skb->len;
@@ -309,8 +309,6 @@
 		kfree_skb(skb);
 	}
 	usb_free_urb(urb);
-
-	return NETDEV_TX_OK;
 }
 
 static void rtl8187_rx_cb(struct urb *urb)
@@ -373,7 +371,7 @@
 	rx_status.rate_idx = rate;
 	rx_status.freq = dev->conf.channel->center_freq;
 	rx_status.band = dev->conf.channel->band;
-	rx_status.flag |= RX_FLAG_TSFT;
+	rx_status.flag |= RX_FLAG_MACTIME_MPDU;
 	if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
 		rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
 	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
@@ -871,23 +869,35 @@
 	/* The RTL8187 returns the retry count through register 0xFFFA. In
 	 * addition, it appears to be a cumulative retry count, not the
 	 * value for the current TX packet. When multiple TX entries are
-	 * queued, the retry count will be valid for the last one in the queue.
-	 * The "error" should not matter for purposes of rate setting. */
+	 * waiting in the queue, the retry count will be the total for all.
+	 * The "error" may matter for purposes of rate setting, but there is
+	 * no other choice with this hardware.
+	 */
 	struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
 				    work.work);
 	struct ieee80211_tx_info *info;
 	struct ieee80211_hw *dev = priv->dev;
 	static u16 retry;
 	u16 tmp;
+	u16 avg_retry;
+	int length;
 
 	mutex_lock(&priv->conf_mutex);
 	tmp = rtl818x_ioread16(priv, (__le16 *)0xFFFA);
+	length = skb_queue_len(&priv->b_tx_status.queue);
+	if (unlikely(!length))
+		length = 1;
+	if (unlikely(tmp < retry))
+		tmp = retry;
+	avg_retry = (tmp - retry) / length;
 	while (skb_queue_len(&priv->b_tx_status.queue) > 0) {
 		struct sk_buff *old_skb;
 
 		old_skb = skb_dequeue(&priv->b_tx_status.queue);
 		info = IEEE80211_SKB_CB(old_skb);
-		info->status.rates[0].count = tmp - retry + 1;
+		info->status.rates[0].count = avg_retry + 1;
+		if (info->status.rates[0].count > RETRY_COUNT)
+			info->flags &= ~IEEE80211_TX_STAT_ACK;
 		ieee80211_tx_status_irqsafe(dev, old_skb);
 	}
 	retry = tmp;
@@ -933,8 +943,8 @@
 		rtl818x_iowrite32(priv, &priv->map->TX_CONF,
 				  RTL818X_TX_CONF_HW_SEQNUM |
 				  RTL818X_TX_CONF_DISREQQSIZE |
-				  (7 << 8  /* short retry limit */) |
-				  (7 << 0  /* long retry limit */) |
+				  (RETRY_COUNT << 8  /* short retry limit */) |
+				  (RETRY_COUNT << 0  /* long retry limit */) |
 				  (7 << 21 /* MAX TX DMA */));
 		rtl8187_init_urbs(dev);
 		rtl8187b_init_status_urb(dev);
@@ -1378,6 +1388,9 @@
 	dev->flags = IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
 		     IEEE80211_HW_SIGNAL_DBM |
 		     IEEE80211_HW_RX_INCLUDES_FCS;
+	/* Initialize rate-control variables */
+	dev->max_rates = 1;
+	dev->max_rate_tries = RETRY_COUNT;
 
 	eeprom.data = dev;
 	eeprom.register_read = rtl8187_eeprom_register_read;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,8 @@
 #define RFKILL_MASK_8187_89_97	0x2
 #define RFKILL_MASK_8198	0x4
 
+#define RETRY_COUNT		7
+
 struct rtl8187_rx_info {
 	struct urb *urb;
 	struct ieee80211_hw *dev;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/base.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/base.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/base.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,7 +144,7 @@
 		ht_cap->mcs.rx_mask[1] = 0xFF;
 		ht_cap->mcs.rx_mask[4] = 0x01;
 
-		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS15;
+		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS15);
 	} else if (get_rf_type(rtlphy) == RF_1T1R) {
 
 		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("1T1R\n"));
@@ -153,7 +153,7 @@
 		ht_cap->mcs.rx_mask[1] = 0x00;
 		ht_cap->mcs.rx_mask[4] = 0x01;
 
-		ht_cap->mcs.rx_highest = MAX_BIT_RATE_40MHZ_MCS7;
+		ht_cap->mcs.rx_highest = cpu_to_le16(MAX_BIT_RATE_40MHZ_MCS7);
 	}
 }
 
@@ -283,13 +283,7 @@
 	rtlmac->hw = hw;
 
 	/* <2> rate control register */
-	if (rtl_rate_control_register()) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("rtl: Unable to register rtl_rc,"
-			  "use default RC !!\n"));
-	} else {
-		hw->rate_control_algorithm = "rtl_rc";
-	}
+	hw->rate_control_algorithm = "rtl_rc";
 
 	/*
 	 * <3> init CRDA must come after init
@@ -325,8 +319,6 @@
 
 void rtl_deinit_core(struct ieee80211_hw *hw)
 {
-	 /*RC*/
-	rtl_rate_control_unregister();
 }
 
 void rtl_init_rx_config(struct ieee80211_hw *hw)
@@ -399,21 +391,21 @@
 	u8 rate_flag = info->control.rates[0].flags;
 
 	/* Common Settings */
-	tcb_desc->b_rts_stbc = false;
-	tcb_desc->b_cts_enable = false;
+	tcb_desc->rts_stbc = false;
+	tcb_desc->cts_enable = false;
 	tcb_desc->rts_sc = 0;
-	tcb_desc->b_rts_bw = false;
-	tcb_desc->b_rts_use_shortpreamble = false;
-	tcb_desc->b_rts_use_shortgi = false;
+	tcb_desc->rts_bw = false;
+	tcb_desc->rts_use_shortpreamble = false;
+	tcb_desc->rts_use_shortgi = false;
 
 	if (rate_flag & IEEE80211_TX_RC_USE_CTS_PROTECT) {
 		/* Use CTS-to-SELF in protection mode. */
-		tcb_desc->b_rts_enable = true;
-		tcb_desc->b_cts_enable = true;
+		tcb_desc->rts_enable = true;
+		tcb_desc->cts_enable = true;
 		tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M];
 	} else if (rate_flag & IEEE80211_TX_RC_USE_RTS_CTS) {
 		/* Use RTS-CTS in protection mode. */
-		tcb_desc->b_rts_enable = true;
+		tcb_desc->rts_enable = true;
 		tcb_desc->rts_rate = rtlpriv->cfg->maps[RTL_RC_OFDM_RATE24M];
 	}
 
@@ -429,7 +421,7 @@
 		if (mac->opmode == NL80211_IFTYPE_STATION)
 			tcb_desc->ratr_index = 0;
 		else if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			if (tcb_desc->b_multicast || tcb_desc->b_broadcast) {
+			if (tcb_desc->multicast || tcb_desc->broadcast) {
 				tcb_desc->hw_rate =
 				    rtlpriv->cfg->maps[RTL_RC_CCK_RATE2M];
 				tcb_desc->use_driver_rate = 1;
@@ -439,7 +431,7 @@
 		}
 	}
 
-	if (rtlpriv->dm.b_useramask) {
+	if (rtlpriv->dm.useramask) {
 		/* TODO we will differentiate adhoc and station futrue  */
 		tcb_desc->mac_id = 0;
 
@@ -461,19 +453,19 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	tcb_desc->b_packet_bw = false;
+	tcb_desc->packet_bw = false;
 
 	if (!mac->bw_40 || !mac->ht_enable)
 		return;
 
-	if (tcb_desc->b_multicast || tcb_desc->b_broadcast)
+	if (tcb_desc->multicast || tcb_desc->broadcast)
 		return;
 
 	/*use legency rate, shall use 20MHz */
 	if (tcb_desc->hw_rate <= rtlpriv->cfg->maps[RTL_RC_OFDM_RATE54M])
 		return;
 
-	tcb_desc->b_packet_bw = true;
+	tcb_desc->packet_bw = true;
 }
 
 static u8 _rtl_get_highest_n_rate(struct ieee80211_hw *hw)
@@ -498,7 +490,7 @@
 	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	struct ieee80211_rate *txrate;
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 
 	memset(tcb_desc, 0, sizeof(struct rtl_tcb_desc));
 
@@ -528,7 +520,7 @@
 			 *because hw will nerver use hw_rate
 			 *when tcb_desc->use_driver_rate = false
 			 *so we never set highest N rate here,
-			 *and N rate will all be controled by FW
+			 *and N rate will all be controlled by FW
 			 *when tcb_desc->use_driver_rate = false
 			 */
 			if (rtlmac->ht_enable) {
@@ -545,9 +537,9 @@
 		}
 
 		if (is_multicast_ether_addr(ieee80211_get_DA(hdr)))
-			tcb_desc->b_multicast = 1;
+			tcb_desc->multicast = 1;
 		else if (is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
-			tcb_desc->b_broadcast = 1;
+			tcb_desc->broadcast = 1;
 
 		_rtl_txrate_selectmode(hw, tcb_desc);
 		_rtl_query_bandwidth_mode(hw, tcb_desc);
@@ -570,7 +562,7 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 
 	if (ieee80211_is_auth(fc)) {
 		RT_TRACE(rtlpriv, COMP_SEND, DBG_DMESG, ("MAC80211_LINKING\n"));
@@ -587,7 +579,7 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u8 *act = (u8 *) (((u8 *) skb->data + MAC80211_3ADDR_LEN));
 	u8 category;
 
@@ -632,7 +624,7 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u16 ether_type;
 	u8 mac_hdr_len = ieee80211_get_hdrlen_from_skb(skb);
 	const struct iphdr *ip;
@@ -646,7 +638,6 @@
 	ip = (struct iphdr *)((u8 *) skb->data + mac_hdr_len +
 			      SNAP_SIZE + PROTOC_TYPE_SIZE);
 	ether_type = *(u16 *) ((u8 *) skb->data + mac_hdr_len + SNAP_SIZE);
-	ether_type = ntohs(ether_type);
 
 	if (ETH_P_IP == ether_type) {
 		if (IPPROTO_UDP == ip->protocol) {
@@ -690,7 +681,8 @@
 		}
 
 		return true;
-	} else if (0x86DD == ether_type) {
+	} else if (ETH_P_IPV6 == ether_type) {
+		/* IPv6 */
 		return true;
 	}
 
@@ -777,10 +769,10 @@
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
-	bool b_busytraffic = false;
-	bool b_higher_busytraffic = false;
-	bool b_higher_busyrxtraffic = false;
-	bool b_higher_busytxtraffic = false;
+	bool busytraffic = false;
+	bool higher_busytraffic = false;
+	bool higher_busyrxtraffic = false;
+	bool higher_busytxtraffic = false;
 
 	u8 idx = 0;
 	u32 rx_cnt_inp4eriod = 0;
@@ -788,7 +780,7 @@
 	u32 aver_rx_cnt_inperiod = 0;
 	u32 aver_tx_cnt_inperiod = 0;
 
-	bool benter_ps = false;
+	bool enter_ps = false;
 
 	if (is_hal_stop(rtlhal))
 		return;
@@ -832,29 +824,29 @@
 
 		/* (2) check traffic busy */
 		if (aver_rx_cnt_inperiod > 100 || aver_tx_cnt_inperiod > 100)
-			b_busytraffic = true;
+			busytraffic = true;
 
 		/* Higher Tx/Rx data. */
 		if (aver_rx_cnt_inperiod > 4000 ||
 		    aver_tx_cnt_inperiod > 4000) {
-			b_higher_busytraffic = true;
+			higher_busytraffic = true;
 
 			/* Extremely high Rx data. */
 			if (aver_rx_cnt_inperiod > 5000)
-				b_higher_busyrxtraffic = true;
+				higher_busyrxtraffic = true;
 			else
-				b_higher_busytxtraffic = false;
+				higher_busytxtraffic = false;
 		}
 
 		if (((rtlpriv->link_info.num_rx_inperiod +
 		      rtlpriv->link_info.num_tx_inperiod) > 8) ||
 		    (rtlpriv->link_info.num_rx_inperiod > 2))
-			benter_ps = false;
+			enter_ps = false;
 		else
-			benter_ps = true;
+			enter_ps = true;
 
 		/* LeisurePS only work in infra mode. */
-		if (benter_ps)
+		if (enter_ps)
 			rtl_lps_enter(hw);
 		else
 			rtl_lps_leave(hw);
@@ -863,9 +855,9 @@
 	rtlpriv->link_info.num_rx_inperiod = 0;
 	rtlpriv->link_info.num_tx_inperiod = 0;
 
-	rtlpriv->link_info.b_busytraffic = b_busytraffic;
-	rtlpriv->link_info.b_higher_busytraffic = b_higher_busytraffic;
-	rtlpriv->link_info.b_higher_busyrxtraffic = b_higher_busyrxtraffic;
+	rtlpriv->link_info.busytraffic = busytraffic;
+	rtlpriv->link_info.higher_busytraffic = higher_busytraffic;
+	rtlpriv->link_info.higher_busyrxtraffic = higher_busyrxtraffic;
 
 }
 
@@ -945,11 +937,16 @@
 
 static int __init rtl_core_module_init(void)
 {
+	if (rtl_rate_control_register())
+		printk(KERN_ERR "rtlwifi: Unable to register rtl_rc,"
+		       "use default RC !!\n");
 	return 0;
 }
 
 static void __exit rtl_core_module_exit(void)
 {
+	 /*RC*/
+	rtl_rate_control_unregister();
 }
 
 module_init(rtl_core_module_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/base.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/base.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/base.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/base.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #define __RTL_BASE_H__
 
 #define RTL_DUMMY_OFFSET	0
+#define RTL_RX_DESC_SIZE	24
 #define RTL_DUMMY_UNIT		8
 #define RTL_TX_DUMMY_SIZE	(RTL_DUMMY_OFFSET * RTL_DUMMY_UNIT)
 #define RTL_TX_DESC_SIZE	32
@@ -52,46 +53,22 @@
 #define FRAME_OFFSET_SEQUENCE		22
 #define FRAME_OFFSET_ADDRESS4		24
 
-#define SET_80211_HDR_FRAME_CONTROL(_hdr, _val)		\
-	WRITEEF2BYTE(_hdr, _val)
-#define SET_80211_HDR_TYPE_AND_SUBTYPE(_hdr, _val)	\
-	WRITEEF1BYTE(_hdr, _val)
-#define SET_80211_HDR_PWR_MGNT(_hdr, _val)		\
-	SET_BITS_TO_LE_2BYTE(_hdr, 12, 1, _val)
-#define SET_80211_HDR_TO_DS(_hdr, _val)			\
-	SET_BITS_TO_LE_2BYTE(_hdr, 8, 1, _val)
 
 #define SET_80211_PS_POLL_AID(_hdr, _val)		\
-	WRITEEF2BYTE(((u8 *)(_hdr)) + 2, _val)
+	(*(u16 *)((u8 *)(_hdr) + 2) = le16_to_cpu(_val))
 #define SET_80211_PS_POLL_BSSID(_hdr, _val)		\
-	CP_MACADDR(((u8 *)(_hdr)) + 4, (u8 *)(_val))
+	memcpy(((u8 *)(_hdr)) + 4, (u8 *)(_val), ETH_ALEN)
 #define SET_80211_PS_POLL_TA(_hdr, _val)		\
-	CP_MACADDR(((u8 *)(_hdr)) + 10, (u8 *)(_val))
+	memcpy(((u8 *)(_hdr)) + 10, (u8 *)(_val), ETH_ALEN)
 
 #define SET_80211_HDR_DURATION(_hdr, _val)	\
-	WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_DURATION, _val)
+	(*(u16 *)((u8 *)(_hdr) + FRAME_OFFSET_DURATION) = le16_to_cpu(_val))
 #define SET_80211_HDR_ADDRESS1(_hdr, _val)	\
-	CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val))
+	memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS1, (u8*)(_val), ETH_ALEN)
 #define SET_80211_HDR_ADDRESS2(_hdr, _val)	\
-	CP_MACADDR((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val))
+	memcpy((u8 *)(_hdr) + FRAME_OFFSET_ADDRESS2, (u8 *)(_val), ETH_ALEN)
 #define SET_80211_HDR_ADDRESS3(_hdr, _val)	\
-	CP_MACADDR((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val))
-#define SET_80211_HDR_FRAGMENT_SEQUENCE(_hdr, _val)  \
-	WRITEEF2BYTE((u8 *)(_hdr)+FRAME_OFFSET_SEQUENCE, _val)
-
-#define SET_BEACON_PROBE_RSP_TIME_STAMP_LOW(__phdr, __val)	\
-	WRITEEF4BYTE(((u8 *)(__phdr)) + 24, __val)
-#define SET_BEACON_PROBE_RSP_TIME_STAMP_HIGH(__phdr, __val) \
-	WRITEEF4BYTE(((u8 *)(__phdr)) + 28, __val)
-#define SET_BEACON_PROBE_RSP_BEACON_INTERVAL(__phdr, __val) \
-	WRITEEF2BYTE(((u8 *)(__phdr)) + 32, __val)
-#define GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr)	\
-	READEF2BYTE(((u8 *)(__phdr)) + 34)
-#define SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \
-	WRITEEF2BYTE(((u8 *)(__phdr)) + 34, __val)
-#define MASK_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, __val) \
-	SET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr, \
-	(GET_BEACON_PROBE_RSP_CAPABILITY_INFO(__phdr) & (~(__val))))
+	memcpy((u8 *)(_hdr)+FRAME_OFFSET_ADDRESS3, (u8 *)(_val), ETH_ALEN)
 
 int rtl_init_core(struct ieee80211_hw *hw);
 void rtl_deinit_core(struct ieee80211_hw *hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/core.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/core.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -82,7 +82,7 @@
 	mutex_unlock(&rtlpriv->locks.conf_mutex);
 }
 
-static int rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void rtl_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -97,11 +97,10 @@
 
 	rtlpriv->intf_ops->adapter_tx(hw, skb);
 
-	return NETDEV_TX_OK;
+	return;
 
 err_free:
 	dev_kfree_skb_any(skb);
-	return NETDEV_TX_OK;
 }
 
 static int rtl_op_add_interface(struct ieee80211_hw *hw,
@@ -434,9 +433,9 @@
 
 	aci = _rtl_get_hal_qnum(queue);
 	mac->ac[aci].aifs = param->aifs;
-	mac->ac[aci].cw_min = param->cw_min;
-	mac->ac[aci].cw_max = param->cw_max;
-	mac->ac[aci].tx_op = param->txop;
+	mac->ac[aci].cw_min = cpu_to_le16(param->cw_min);
+	mac->ac[aci].cw_max = cpu_to_le16(param->cw_max);
+	mac->ac[aci].tx_op = cpu_to_le16(param->txop);
 	memcpy(&mac->edca_param[aci], param, sizeof(*param));
 	rtlpriv->cfg->ops->set_qos(hw, aci);
 	return 0;
@@ -552,6 +551,7 @@
 		RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
 			 ("BSS_CHANGED_HT\n"));
 
+		rcu_read_lock();
 		sta = ieee80211_find_sta(mac->vif, mac->bssid);
 
 		if (sta) {
@@ -564,6 +564,7 @@
 				mac->current_ampdu_factor =
 				    sta->ht_cap.ampdu_factor;
 		}
+		rcu_read_unlock();
 
 		rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SHORTGI_DENSITY,
 					      (u8 *) (&mac->max_mss_density));
@@ -615,6 +616,7 @@
 		else
 			mac->mode = WIRELESS_MODE_G;
 
+		rcu_read_lock();
 		sta = ieee80211_find_sta(mac->vif, mac->bssid);
 
 		if (sta) {
@@ -649,6 +651,7 @@
 				 */
 			}
 		}
+		rcu_read_unlock();
 
 		/*mac80211 just give us CCK rates any time
 		 *So we add G rate in basic rates when
@@ -666,7 +669,7 @@
 			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_BASIC_RATE,
 					(u8 *) (&basic_rates));
 
-			if (rtlpriv->dm.b_useramask)
+			if (rtlpriv->dm.useramask)
 				rtlpriv->cfg->ops->update_rate_mask(hw, 0);
 			else
 				rtlpriv->cfg->ops->update_rate_table(hw);
@@ -681,7 +684,7 @@
 	 */
 	if (changed & BSS_CHANGED_ASSOC) {
 		if (bss_conf->assoc) {
-			if (ppsc->b_fwctrl_lps) {
+			if (ppsc->fwctrl_lps) {
 				u8 mstatus = RT_MEDIA_CONNECT;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						      HW_VAR_H2C_FW_JOINBSSRPT,
@@ -689,7 +692,7 @@
 				ppsc->report_linked = true;
 			}
 		} else {
-			if (ppsc->b_fwctrl_lps) {
+			if (ppsc->fwctrl_lps) {
 				u8 mstatus = RT_MEDIA_DISCONNECT;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						      HW_VAR_H2C_FW_JOINBSSRPT,
@@ -748,7 +751,8 @@
 static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
 			       struct ieee80211_vif *vif,
 			       enum ieee80211_ampdu_mlme_action action,
-			       struct ieee80211_sta *sta, u16 tid, u16 * ssn)
+			       struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			       u8 buf_size)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 
@@ -817,7 +821,7 @@
 		/* fix fwlps issue */
 		rtlpriv->cfg->ops->set_network_type(hw, mac->opmode);
 
-		if (rtlpriv->dm.b_useramask)
+		if (rtlpriv->dm.useramask)
 			rtlpriv->cfg->ops->update_rate_mask(hw, 0);
 		else
 			rtlpriv->cfg->ops->update_rate_table(hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/debug.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/debug.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/debug.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -105,6 +105,7 @@
 #define COMP_MAC80211		BIT(26)
 #define COMP_REGD			BIT(27)
 #define COMP_CHAN			BIT(28)
+#define COMP_USB			BIT(29)
 
 /*--------------------------------------------------------------
 		Define the rt_print components
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/efuse.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/efuse.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/efuse.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/efuse.c	2011-05-19 00:06:34.000000000 -0400
@@ -410,8 +410,8 @@
 
 	if (!efuse_shadow_update_chk(hw)) {
 		efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
-		memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
-		       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+		memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
+		       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 		       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
 		RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
@@ -446,9 +446,9 @@
 
 		if (word_en != 0x0F) {
 			u8 tmpdata[8];
-			memcpy((void *)tmpdata,
-			       (void *)(&rtlefuse->
-					efuse_map[EFUSE_MODIFY_MAP][base]), 8);
+			memcpy(tmpdata,
+			       &rtlefuse->efuse_map[EFUSE_MODIFY_MAP][base],
+			       8);
 			RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD,
 				      ("U-efuse\n"), tmpdata, 8);
 
@@ -465,8 +465,8 @@
 	efuse_power_switch(hw, true, false);
 	efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
 
-	memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
-	       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+	memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
+	       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 	       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
 	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD, ("<---\n"));
@@ -479,13 +479,12 @@
 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
 
 	if (rtlefuse->autoload_failflag == true) {
-		memset((void *)(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0]), 128,
-		       0xFF);
+		memset(&rtlefuse->efuse_map[EFUSE_INIT_MAP][0], 0xFF, 128);
 	} else
 		efuse_read_all_map(hw, &rtlefuse->efuse_map[EFUSE_INIT_MAP][0]);
 
-	memcpy((void *)&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
-	       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+	memcpy(&rtlefuse->efuse_map[EFUSE_MODIFY_MAP][0],
+	       &rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
 	       rtlpriv->cfg->maps[EFUSE_HWSET_MAX_SIZE]);
 
 }
@@ -686,7 +685,7 @@
 
 	u8 efuse_data, word_cnts = 0;
 	u16 efuse_addr = 0;
-	u8 hworden;
+	u8 hworden = 0;
 	u8 tmpdata[8];
 
 	if (data == NULL)
@@ -694,8 +693,8 @@
 	if (offset > 15)
 		return false;
 
-	memset((void *)data, PGPKT_DATA_SIZE * sizeof(u8), 0xff);
-	memset((void *)tmpdata, PGPKT_DATA_SIZE * sizeof(u8), 0xff);
+	memset(data, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
+	memset(tmpdata, 0xff, PGPKT_DATA_SIZE * sizeof(u8));
 
 	while (bcontinual && (efuse_addr < EFUSE_MAX_SIZE)) {
 		if (readstate & PG_STATE_HEADER) {
@@ -862,7 +861,7 @@
 
 		tmp_word_cnts = efuse_calculate_word_cnts(tmp_pkt.word_en);
 
-		memset((void *)originaldata, 8 * sizeof(u8), 0xff);
+		memset(originaldata, 0xff, 8 * sizeof(u8));
 
 		if (efuse_pg_packet_read(hw, tmp_pkt.offset, originaldata)) {
 			badworden = efuse_word_enable_data_write(hw,
@@ -917,7 +916,7 @@
 	target_pkt.offset = offset;
 	target_pkt.word_en = word_en;
 
-	memset((void *)target_pkt.data, 8 * sizeof(u8), 0xFF);
+	memset(target_pkt.data, 0xFF, 8 * sizeof(u8));
 
 	efuse_word_enable_data_read(word_en, data, target_pkt.data);
 	target_word_cnts = efuse_calculate_word_cnts(target_pkt.word_en);
@@ -1022,7 +1021,7 @@
 	u8 badworden = 0x0F;
 	u8 tmpdata[8];
 
-	memset((void *)tmpdata, PGPKT_DATA_SIZE, 0xff);
+	memset(tmpdata, 0xff, PGPKT_DATA_SIZE);
 	RT_TRACE(rtlpriv, COMP_EFUSE, DBG_LOUD,
 		 ("word_en = %x efuse_addr=%x\n", word_en, efuse_addr));
 
@@ -1169,21 +1168,3 @@
 	return word_cnts;
 }
 
-void efuse_reset_loader(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u16 tmp_u2b;
-
-	tmp_u2b = rtl_read_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN]);
-	rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN],
-		       (tmp_u2b & ~(BIT(12))));
-	udelay(10000);
-	rtl_write_word(rtlpriv, rtlpriv->cfg->maps[SYS_FUNC_EN],
-		       (tmp_u2b | BIT(12)));
-	udelay(10000);
-}
-
-bool efuse_program_map(struct ieee80211_hw *hw, char *p_filename, u8 tabletype)
-{
-	return true;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/efuse.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/efuse.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/efuse.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/efuse.h	2011-05-19 00:06:34.000000000 -0400
@@ -117,8 +117,5 @@
 extern void rtl_efuse_shadow_map_update(struct ieee80211_hw *hw);
 extern void efuse_force_write_vendor_Id(struct ieee80211_hw *hw);
 extern void efuse_re_pg_section(struct ieee80211_hw *hw, u8 section_idx);
-extern bool efuse_program_map(struct ieee80211_hw *hw,
-			      char *p_filename, u8 tabletype);
-extern void efuse_reset_loader(struct ieee80211_hw *hw);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,15 +1,33 @@
 config RTL8192CE
-	tristate "Realtek RTL8192CE/RTL8188SE Wireless Network Adapter"
-	depends on MAC80211 && EXPERIMENTAL
+	tristate "Realtek RTL8192CE/RTL8188CE Wireless Network Adapter"
+	depends on MAC80211 && PCI && EXPERIMENTAL
 	select FW_LOADER
 	select RTLWIFI
+	select RTL8192C_COMMON
 	---help---
 	This is the driver for Realtek RTL8192CE/RTL8188CE 802.11n PCIe
 	wireless network adapters.
 
 	If you choose to build it as a module, it will be called rtl8192ce
 
+config RTL8192CU
+	tristate "Realtek RTL8192CU/RTL8188CU USB Wireless Network Adapter"
+	depends on MAC80211 && USB && EXPERIMENTAL
+	select FW_LOADER
+	select RTLWIFI
+	select RTL8192C_COMMON
+	---help---
+	This is the driver for Realtek RTL8192CU/RTL8188CU 802.11n USB
+	wireless network adapters.
+
+	If you choose to build it as a module, it will be called rtl8192cu
+
 config RTLWIFI
 	tristate
-	depends on RTL8192CE
+	depends on RTL8192CE || RTL8192CU
+	default m
+
+config RTL8192C_COMMON
+	tristate
+	depends on RTL8192CE || RTL8192CU
 	default m
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,9 +5,22 @@
 		core.o		\
 		debug.o		\
 		efuse.o		\
-		pci.o		\
 		ps.o		\
 		rc.o		\
 		regd.o
 
+rtl8192c_common-objs +=		\
+
+ifneq ($(CONFIG_PCI),)
+rtlwifi-objs	+= pci.o
+endif
+
+ifneq ($(CONFIG_USB),)
+rtlwifi-objs	+= usb.o
+endif
+
+obj-$(CONFIG_RTL8192C_COMMON)	+= rtl8192c/
 obj-$(CONFIG_RTL8192CE)		+= rtl8192ce/
+obj-$(CONFIG_RTL8192CU)		+= rtl8192cu/
+
+ccflags-y += -D__CHECK_ENDIAN__
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/pci.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/pci.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 	u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
 
 	ppsc->reg_rfps_level = 0;
-	ppsc->b_support_aspm = 0;
+	ppsc->support_aspm = 0;
 
 	/*Update PCI ASPM setting */
 	ppsc->const_amdpci_aspm = rtlpci->const_amdpci_aspm;
@@ -115,29 +115,29 @@
 	switch (rtlpci->const_support_pciaspm) {
 	case 0:{
 			/*Not support ASPM. */
-			bool b_support_aspm = false;
-			ppsc->b_support_aspm = b_support_aspm;
+			bool support_aspm = false;
+			ppsc->support_aspm = support_aspm;
 			break;
 		}
 	case 1:{
 			/*Support ASPM. */
-			bool b_support_aspm = true;
-			bool b_support_backdoor = true;
-			ppsc->b_support_aspm = b_support_aspm;
+			bool support_aspm = true;
+			bool support_backdoor = true;
+			ppsc->support_aspm = support_aspm;
 
 			/*if(priv->oem_id == RT_CID_TOSHIBA &&
 			   !priv->ndis_adapter.amd_l1_patch)
-			   b_support_backdoor = false; */
+			   support_backdoor = false; */
 
-			ppsc->b_support_backdoor = b_support_backdoor;
+			ppsc->support_backdoor = support_backdoor;
 
 			break;
 		}
 	case 2:
 		/*ASPM value set by chipset. */
 		if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) {
-			bool b_support_aspm = true;
-			ppsc->b_support_aspm = b_support_aspm;
+			bool support_aspm = true;
+			ppsc->support_aspm = support_aspm;
 		}
 		break;
 	default:
@@ -395,7 +395,7 @@
 	 * 0 - Disable ASPM,
 	 * 1 - Enable ASPM without Clock Req,
 	 * 2 - Enable ASPM with Clock Req,
-	 * 3 - Alwyas Enable ASPM with Clock Req,
+	 * 3 - Always Enable ASPM with Clock Req,
 	 * 4 - Always Enable ASPM without Clock Req.
 	 * set defult to RTL8192CE:3 RTL8192E:2
 	 * */
@@ -476,9 +476,9 @@
 
 		skb = __skb_dequeue(&ring->queue);
 		pci_unmap_single(rtlpci->pdev,
-				 le32_to_cpu(rtlpriv->cfg->ops->
+				 rtlpriv->cfg->ops->
 					     get_desc((u8 *) entry, true,
-						      HW_DESC_TXBUFF_ADDR)),
+						      HW_DESC_TXBUFF_ADDR),
 				 skb->len, PCI_DMA_TODEVICE);
 
 		RT_TRACE(rtlpriv, (COMP_INTR | COMP_SEND), DBG_TRACE,
@@ -557,7 +557,7 @@
 			return;
 		} else {
 			struct ieee80211_hdr *hdr;
-			u16 fc;
+			__le16 fc;
 			struct sk_buff *new_skb = NULL;
 
 			rtlpriv->cfg->ops->query_rx_desc(hw, &stats,
@@ -583,9 +583,9 @@
 			 */
 
 			hdr = (struct ieee80211_hdr *)(skb->data);
-			fc = le16_to_cpu(hdr->frame_control);
+			fc = hdr->frame_control;
 
-			if (!stats.b_crc) {
+			if (!stats.crc) {
 				memcpy(IEEE80211_SKB_RXCB(skb), &rx_status,
 				       sizeof(rx_status));
 
@@ -666,7 +666,7 @@
 
 		}
 done:
-		bufferaddress = cpu_to_le32(*((dma_addr_t *) skb->cb));
+		bufferaddress = (u32)(*((dma_addr_t *) skb->cb));
 		tmp_one = 1;
 		rtlpriv->cfg->ops->set_desc((u8 *) pdesc, false,
 					    HW_DESC_RXBUFF_ADDR,
@@ -690,75 +690,6 @@
 
 }
 
-void _rtl_pci_tx_interrupt(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	int prio;
-
-	for (prio = 0; prio < RTL_PCI_MAX_TX_QUEUE_COUNT; prio++) {
-		struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[prio];
-
-		while (skb_queue_len(&ring->queue)) {
-			struct rtl_tx_desc *entry = &ring->desc[ring->idx];
-			struct sk_buff *skb;
-			struct ieee80211_tx_info *info;
-			u8 own;
-
-			/*
-			 *beacon packet will only use the first
-			 *descriptor defautly, and the own may not
-			 *be cleared by the hardware, and
-			 *beacon will free in prepare beacon
-			 */
-			if (prio == BEACON_QUEUE || prio == TXCMD_QUEUE ||
-			    prio == HCCA_QUEUE)
-				break;
-
-			own = (u8)rtlpriv->cfg->ops->get_desc((u8 *)entry,
-							       true,
-							       HW_DESC_OWN);
-
-			if (own)
-				break;
-
-			skb = __skb_dequeue(&ring->queue);
-			pci_unmap_single(rtlpci->pdev,
-					 le32_to_cpu(rtlpriv->cfg->ops->
-						     get_desc((u8 *) entry,
-						     true,
-						     HW_DESC_TXBUFF_ADDR)),
-					 skb->len, PCI_DMA_TODEVICE);
-
-			ring->idx = (ring->idx + 1) % ring->entries;
-
-			info = IEEE80211_SKB_CB(skb);
-			ieee80211_tx_info_clear_status(info);
-
-			info->flags |= IEEE80211_TX_STAT_ACK;
-			/*info->status.rates[0].count = 1; */
-
-			ieee80211_tx_status_irqsafe(hw, skb);
-
-			if ((ring->entries - skb_queue_len(&ring->queue))
-			    == 2 && prio != BEACON_QUEUE) {
-				RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-					 ("more desc left, wake "
-					  "skb_queue@%d,ring->idx = %d,"
-					  "skb_queue_len = 0x%d\n",
-					  prio, ring->idx,
-					  skb_queue_len(&ring->queue)));
-
-				ieee80211_wake_queue(hw,
-						     skb_get_queue_mapping
-						     (skb));
-			}
-
-			skb = NULL;
-		}
-	}
-}
-
 static irqreturn_t _rtl_pci_interrupt(int irq, void *dev_id)
 {
 	struct ieee80211_hw *hw = dev_id;
@@ -959,17 +890,17 @@
 	rtlhal->hw = hw;
 	rtlpci->pdev = pdev;
 
-	ppsc->b_inactiveps = false;
-	ppsc->b_leisure_ps = true;
-	ppsc->b_fwctrl_lps = true;
-	ppsc->b_reg_fwctrl_lps = 3;
+	ppsc->inactiveps = false;
+	ppsc->leisure_ps = true;
+	ppsc->fwctrl_lps = true;
+	ppsc->reg_fwctrl_lps = 3;
 	ppsc->reg_max_lps_awakeintvl = 5;
 
-	if (ppsc->b_reg_fwctrl_lps == 1)
+	if (ppsc->reg_fwctrl_lps == 1)
 		ppsc->fwctrl_psmode = FW_PS_MIN_MODE;
-	else if (ppsc->b_reg_fwctrl_lps == 2)
+	else if (ppsc->reg_fwctrl_lps == 2)
 		ppsc->fwctrl_psmode = FW_PS_MAX_MODE;
-	else if (ppsc->b_reg_fwctrl_lps == 3)
+	else if (ppsc->reg_fwctrl_lps == 3)
 		ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;
 
 	/*Tx/Rx related var */
@@ -1024,9 +955,8 @@
 		 ("queue:%d, ring_addr:%p\n", prio, ring));
 
 	for (i = 0; i < entries; i++) {
-		nextdescaddress = cpu_to_le32((u32) dma +
-					      ((i + 1) % entries) *
-					      sizeof(*ring));
+		nextdescaddress = (u32) dma + ((i + 1) % entries) *
+					      sizeof(*ring);
 
 		rtlpriv->cfg->ops->set_desc((u8 *)&(ring[i]),
 					    true, HW_DESC_TX_NEXTDESC_ADDR,
@@ -1090,7 +1020,7 @@
 					   rtlpci->rxbuffersize,
 					   PCI_DMA_FROMDEVICE);
 
-			bufferaddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
+			bufferaddress = (u32)(*((dma_addr_t *)skb->cb));
 			rtlpriv->cfg->ops->set_desc((u8 *)entry, false,
 						    HW_DESC_RXBUFF_ADDR,
 						    (u8 *)&bufferaddress);
@@ -1121,9 +1051,9 @@
 		struct sk_buff *skb = __skb_dequeue(&ring->queue);
 
 		pci_unmap_single(rtlpci->pdev,
-				 le32_to_cpu(rtlpriv->cfg->
+				 rtlpriv->cfg->
 					     ops->get_desc((u8 *) entry, true,
-						   HW_DESC_TXBUFF_ADDR)),
+						   HW_DESC_TXBUFF_ADDR),
 				 skb->len, PCI_DMA_TODEVICE);
 		kfree_skb(skb);
 		ring->idx = (ring->idx + 1) % ring->entries;
@@ -1255,11 +1185,11 @@
 				    __skb_dequeue(&ring->queue);
 
 				pci_unmap_single(rtlpci->pdev,
-						 le32_to_cpu(rtlpriv->cfg->ops->
+						 rtlpriv->cfg->ops->
 							 get_desc((u8 *)
 							 entry,
 							 true,
-							 HW_DESC_TXBUFF_ADDR)),
+							 HW_DESC_TXBUFF_ADDR),
 						 skb->len, PCI_DMA_TODEVICE);
 				kfree_skb(skb);
 				ring->idx = (ring->idx + 1) % ring->entries;
@@ -1273,7 +1203,7 @@
 	return 0;
 }
 
-unsigned int _rtl_mac_to_hwqueue(u16 fc,
+static unsigned int _rtl_mac_to_hwqueue(__le16 fc,
 		unsigned int mac80211_queue_index)
 {
 	unsigned int hw_queue_index;
@@ -1312,7 +1242,7 @@
 	return hw_queue_index;
 }
 
-int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static int rtl_pci_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
@@ -1323,7 +1253,7 @@
 	unsigned int queue_index, hw_queue;
 	unsigned long flags;
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u8 *pda_addr = hdr->addr1;
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	/*ssn */
@@ -1429,7 +1359,7 @@
 	return 0;
 }
 
-void rtl_pci_deinit(struct ieee80211_hw *hw)
+static void rtl_pci_deinit(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -1444,7 +1374,7 @@
 
 }
 
-int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
+static int rtl_pci_init(struct ieee80211_hw *hw, struct pci_dev *pdev)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	int err;
@@ -1461,7 +1391,7 @@
 	return 1;
 }
 
-int rtl_pci_start(struct ieee80211_hw *hw)
+static int rtl_pci_start(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -1496,7 +1426,7 @@
 	return 0;
 }
 
-void rtl_pci_stop(struct ieee80211_hw *hw)
+static void rtl_pci_stop(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -1547,13 +1477,11 @@
 	struct pci_dev *bridge_pdev = pdev->bus->self;
 	u16 venderid;
 	u16 deviceid;
-	u8 revisionid;
 	u16 irqline;
 	u8 tmp;
 
 	venderid = pdev->vendor;
 	deviceid = pdev->device;
-	pci_read_config_byte(pdev, 0x8, &revisionid);
 	pci_read_config_word(pdev, 0x3C, &irqline);
 
 	if (deviceid == RTL_PCI_8192_DID ||
@@ -1564,7 +1492,7 @@
 	    deviceid == RTL_PCI_8173_DID ||
 	    deviceid == RTL_PCI_8172_DID ||
 	    deviceid == RTL_PCI_8171_DID) {
-		switch (revisionid) {
+		switch (pdev->revision) {
 		case RTL_PCI_REVISION_ID_8192PCIE:
 			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
 				 ("8192 PCI-E is found - "
@@ -1838,7 +1766,7 @@
 	ieee80211_free_hw(hw);
 
 	if (rtlpriv->io.pci_mem_start != 0)
-		pci_iounmap(pdev, (void *)rtlpriv->io.pci_mem_start);
+		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 
 fail2:
 	pci_release_regions(pdev);
@@ -1888,7 +1816,7 @@
 	}
 
 	if (rtlpriv->io.pci_mem_start != 0) {
-		pci_iounmap(pdev, (void *)rtlpriv->io.pci_mem_start);
+		pci_iounmap(pdev, (void __iomem *)rtlpriv->io.pci_mem_start);
 		pci_release_regions(pdev);
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/pci.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/pci.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -244,34 +244,34 @@
 
 static inline u8 pci_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-	return 0xff & readb((u8 *) rtlpriv->io.pci_mem_start + addr);
+	return readb((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline u16 pci_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-	return readw((u8 *) rtlpriv->io.pci_mem_start + addr);
+	return readw((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline u32 pci_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
 {
-	return readl((u8 *) rtlpriv->io.pci_mem_start + addr);
+	return readl((u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void pci_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
 {
-	writeb(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
+	writeb(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void pci_write16_async(struct rtl_priv *rtlpriv,
 				     u32 addr, u16 val)
 {
-	writew(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
+	writew(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void pci_write32_async(struct rtl_priv *rtlpriv,
 				     u32 addr, u32 val)
 {
-	writel(val, (u8 *) rtlpriv->io.pci_mem_start + addr);
+	writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
 }
 
 static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/ps.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/ps.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/ps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/ps.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 	enum rf_pwrstate rtstate;
-	bool b_actionallowed = false;
+	bool actionallowed = false;
 	u16 rfwait_cnt = 0;
 	unsigned long flag;
 
@@ -139,13 +139,13 @@
 		ppsc->rfoff_reason &= (~changesource);
 
 		if ((changesource == RF_CHANGE_BY_HW) &&
-		    (ppsc->b_hwradiooff == true)) {
-			ppsc->b_hwradiooff = false;
+		    (ppsc->hwradiooff == true)) {
+			ppsc->hwradiooff = false;
 		}
 
 		if (!ppsc->rfoff_reason) {
 			ppsc->rfoff_reason = 0;
-			b_actionallowed = true;
+			actionallowed = true;
 		}
 
 		break;
@@ -153,17 +153,17 @@
 	case ERFOFF:
 
 		if ((changesource == RF_CHANGE_BY_HW)
-		    && (ppsc->b_hwradiooff == false)) {
-			ppsc->b_hwradiooff = true;
+		    && (ppsc->hwradiooff == false)) {
+			ppsc->hwradiooff = true;
 		}
 
 		ppsc->rfoff_reason |= changesource;
-		b_actionallowed = true;
+		actionallowed = true;
 		break;
 
 	case ERFSLEEP:
 		ppsc->rfoff_reason |= changesource;
-		b_actionallowed = true;
+		actionallowed = true;
 		break;
 
 	default:
@@ -172,7 +172,7 @@
 		break;
 	}
 
-	if (b_actionallowed)
+	if (actionallowed)
 		rtlpriv->cfg->ops->set_rf_power_state(hw, state_toset);
 
 	if (!protect_or_not) {
@@ -181,7 +181,7 @@
 		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
 	}
 
-	return b_actionallowed;
+	return actionallowed;
 }
 EXPORT_SYMBOL(rtl_ps_set_rf_state);
 
@@ -191,7 +191,7 @@
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
 
-	ppsc->b_swrf_processing = true;
+	ppsc->swrf_processing = true;
 
 	if (ppsc->inactive_pwrstate == ERFON && rtlhal->interface == INTF_PCI) {
 		if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
@@ -213,7 +213,7 @@
 		}
 	}
 
-	ppsc->b_swrf_processing = false;
+	ppsc->swrf_processing = false;
 }
 
 void rtl_ips_nic_off_wq_callback(void *data)
@@ -239,13 +239,13 @@
 	if (rtlpriv->sec.being_setkey)
 		return;
 
-	if (ppsc->b_inactiveps) {
+	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
 
 		/*
 		 *Do not enter IPS in the following conditions:
 		 *(1) RF is already OFF or Sleep
-		 *(2) b_swrf_processing (indicates the IPS is still under going)
+		 *(2) swrf_processing (indicates the IPS is still under going)
 		 *(3) Connectted (only disconnected can trigger IPS)
 		 *(4) IBSS (send Beacon)
 		 *(5) AP mode (send Beacon)
@@ -253,14 +253,14 @@
 		 */
 
 		if (rtstate == ERFON &&
-		    !ppsc->b_swrf_processing &&
+		    !ppsc->swrf_processing &&
 		    (mac->link_state == MAC80211_NOLINK) &&
 		    !mac->act_scanning) {
 			RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
 				 ("IPSEnter(): Turn off RF.\n"));
 
 			ppsc->inactive_pwrstate = ERFOFF;
-			ppsc->b_in_powersavemode = true;
+			ppsc->in_powersavemode = true;
 
 			/*rtl_pci_reset_trx_ring(hw); */
 			_rtl_ps_inactive_ps(hw);
@@ -290,15 +290,15 @@
 
 	spin_lock_irqsave(&rtlpriv->locks.ips_lock, flags);
 
-	if (ppsc->b_inactiveps) {
+	if (ppsc->inactiveps) {
 		rtstate = ppsc->rfpwr_state;
 
 		if (rtstate != ERFON &&
-		    !ppsc->b_swrf_processing &&
+		    !ppsc->swrf_processing &&
 		    ppsc->rfoff_reason <= RF_CHANGE_BY_IPS) {
 
 			ppsc->inactive_pwrstate = ERFON;
-			ppsc->b_in_powersavemode = false;
+			ppsc->in_powersavemode = false;
 
 			_rtl_ps_inactive_ps(hw);
 		}
@@ -370,9 +370,9 @@
 	 *   mode and set RPWM to turn RF on.
 	 */
 
-	if ((ppsc->b_fwctrl_lps) && (ppsc->b_leisure_ps) &&
+	if ((ppsc->fwctrl_lps) && (ppsc->leisure_ps) &&
 	     ppsc->report_linked) {
-		bool b_fw_current_inps;
+		bool fw_current_inps;
 		if (ppsc->dot11_psmode == EACTIVE) {
 			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 				 ("FW LPS leave ps_mode:%x\n",
@@ -385,11 +385,11 @@
 			rtlpriv->cfg->ops->set_hw_reg(hw,
 					HW_VAR_H2C_FW_PWRMODE,
 					(u8 *) (&fw_pwrmode));
-			b_fw_current_inps = false;
+			fw_current_inps = false;
 
 			rtlpriv->cfg->ops->set_hw_reg(hw,
 					HW_VAR_FW_PSMODE_STATUS,
-					(u8 *) (&b_fw_current_inps));
+					(u8 *) (&fw_current_inps));
 
 		} else {
 			if (rtl_get_fwlps_doze(hw)) {
@@ -398,10 +398,10 @@
 						 ppsc->fwctrl_psmode));
 
 				rpwm_val = 0x02;	/* RF off */
-				b_fw_current_inps = true;
+				fw_current_inps = true;
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						HW_VAR_FW_PSMODE_STATUS,
-						(u8 *) (&b_fw_current_inps));
+						(u8 *) (&fw_current_inps));
 				rtlpriv->cfg->ops->set_hw_reg(hw,
 						HW_VAR_H2C_FW_PWRMODE,
 						(u8 *) (&ppsc->fwctrl_psmode));
@@ -425,13 +425,13 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	unsigned long flag;
 
-	if (!(ppsc->b_fwctrl_lps && ppsc->b_leisure_ps))
+	if (!(ppsc->fwctrl_lps && ppsc->leisure_ps))
 		return;
 
 	if (rtlpriv->sec.being_setkey)
 		return;
 
-	if (rtlpriv->link_info.b_busytraffic)
+	if (rtlpriv->link_info.busytraffic)
 		return;
 
 	/*sleep after linked 10s, to let DHCP and 4-way handshake ok enough!! */
@@ -446,7 +446,7 @@
 
 	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
-	if (ppsc->b_leisure_ps) {
+	if (ppsc->leisure_ps) {
 		/* Idle for a while if we connect to AP a while ago. */
 		if (mac->cnt_after_linked >= 2) {
 			if (ppsc->dot11_psmode == EACTIVE) {
@@ -470,7 +470,7 @@
 
 	spin_lock_irqsave(&rtlpriv->locks.lps_lock, flag);
 
-	if (ppsc->b_fwctrl_lps && ppsc->b_leisure_ps) {
+	if (ppsc->fwctrl_lps && ppsc->leisure_ps) {
 		if (ppsc->dot11_psmode != EACTIVE) {
 
 			/*FIX ME */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/regd.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/regd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/regd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/regd.c	2011-05-19 00:06:34.000000000 -0400
@@ -179,7 +179,7 @@
 	}
 
 	/*
-	 *If a country IE has been recieved check its rule for this
+	 *If a country IE has been received 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.
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1398 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "dm_common.h"
+
+struct dig_t dm_digtable;
+static struct ps_t dm_pstable;
+
+static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
+	0x7f8001fe,
+	0x788001e2,
+	0x71c001c7,
+	0x6b8001ae,
+	0x65400195,
+	0x5fc0017f,
+	0x5a400169,
+	0x55400155,
+	0x50800142,
+	0x4c000130,
+	0x47c0011f,
+	0x43c0010f,
+	0x40000100,
+	0x3c8000f2,
+	0x390000e4,
+	0x35c000d7,
+	0x32c000cb,
+	0x300000c0,
+	0x2d4000b5,
+	0x2ac000ab,
+	0x288000a2,
+	0x26000098,
+	0x24000090,
+	0x22000088,
+	0x20000080,
+	0x1e400079,
+	0x1c800072,
+	0x1b00006c,
+	0x19800066,
+	0x18000060,
+	0x16c0005b,
+	0x15800056,
+	0x14400051,
+	0x1300004c,
+	0x12000048,
+	0x11000044,
+	0x10000040,
+};
+
+static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
+	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
+	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
+	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
+	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
+	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
+	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
+	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
+	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
+	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
+	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
+	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
+	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
+	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
+	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
+	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
+	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
+	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
+	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
+	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
+	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
+	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
+	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
+	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
+	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
+	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
+	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
+	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
+	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
+	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
+	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
+	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
+};
+
+static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
+	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
+	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
+	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
+	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
+	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
+	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
+	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
+	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
+	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
+	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
+	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
+	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
+	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
+	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
+	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
+	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
+	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
+	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
+	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
+	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
+	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
+	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
+	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
+};
+
+static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
+{
+	dm_digtable.dig_enable_flag = true;
+	dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+	dm_digtable.cur_igvalue = 0x20;
+	dm_digtable.pre_igvalue = 0x0;
+	dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+	dm_digtable.presta_connectstate = DIG_STA_DISCONNECT;
+	dm_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
+	dm_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
+	dm_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
+	dm_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
+	dm_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
+	dm_digtable.rx_gain_range_max = DM_DIG_MAX;
+	dm_digtable.rx_gain_range_min = DM_DIG_MIN;
+	dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+	dm_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
+	dm_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
+	dm_digtable.pre_cck_pd_state = CCK_PD_STAGE_MAX;
+	dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+}
+
+static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long rssi_val_min = 0;
+
+	if ((dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
+	    (dm_digtable.cursta_connectctate == DIG_STA_CONNECT)) {
+		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
+			rssi_val_min =
+			    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
+			     rtlpriv->dm.undecorated_smoothed_pwdb) ?
+			    rtlpriv->dm.undecorated_smoothed_pwdb :
+			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+		else
+			rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
+	} else if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT ||
+		   dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT) {
+		rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
+	} else if (dm_digtable.curmultista_connectstate ==
+		   DIG_MULTISTA_CONNECT) {
+		rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+	}
+
+	return (u8) rssi_val_min;
+}
+
+static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
+{
+	u32 ret_value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
+	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
+	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
+	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
+
+	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
+	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
+	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
+	    falsealm_cnt->cnt_rate_illegal +
+	    falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
+
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
+	falsealm_cnt->cnt_cck_fail = ret_value;
+
+	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
+	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
+	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
+				 falsealm_cnt->cnt_rate_illegal +
+				 falsealm_cnt->cnt_crc8_fail +
+				 falsealm_cnt->cnt_mcs_fail +
+				 falsealm_cnt->cnt_cck_fail);
+
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
+	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
+	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("cnt_parity_fail = %d, cnt_rate_illegal = %d, "
+		  "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
+		  falsealm_cnt->cnt_parity_fail,
+		  falsealm_cnt->cnt_rate_illegal,
+		  falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail));
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
+		  falsealm_cnt->cnt_ofdm_fail,
+		  falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all));
+}
+
+static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value_igi = dm_digtable.cur_igvalue;
+
+	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
+		value_igi--;
+	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
+		value_igi += 0;
+	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
+		value_igi++;
+	else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
+		value_igi += 2;
+	if (value_igi > DM_DIG_FA_UPPER)
+		value_igi = DM_DIG_FA_UPPER;
+	else if (value_igi < DM_DIG_FA_LOWER)
+		value_igi = DM_DIG_FA_LOWER;
+	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
+		value_igi = 0x32;
+
+	dm_digtable.cur_igvalue = value_igi;
+	rtl92c_dm_write_dig(hw);
+}
+
+static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable.fa_highthresh) {
+		if ((dm_digtable.backoff_val - 2) <
+		    dm_digtable.backoff_val_range_min)
+			dm_digtable.backoff_val =
+			    dm_digtable.backoff_val_range_min;
+		else
+			dm_digtable.backoff_val -= 2;
+	} else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable.fa_lowthresh) {
+		if ((dm_digtable.backoff_val + 2) >
+		    dm_digtable.backoff_val_range_max)
+			dm_digtable.backoff_val =
+			    dm_digtable.backoff_val_range_max;
+		else
+			dm_digtable.backoff_val += 2;
+	}
+
+	if ((dm_digtable.rssi_val_min + 10 - dm_digtable.backoff_val) >
+	    dm_digtable.rx_gain_range_max)
+		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_max;
+	else if ((dm_digtable.rssi_val_min + 10 -
+		  dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
+		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_min;
+	else
+		dm_digtable.cur_igvalue = dm_digtable.rssi_val_min + 10 -
+		    dm_digtable.backoff_val;
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("rssi_val_min = %x backoff_val %x\n",
+		  dm_digtable.rssi_val_min, dm_digtable.backoff_val));
+
+	rtl92c_dm_write_dig(hw);
+}
+
+static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
+{
+	static u8 binitialized; /* initialized to false */
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+	bool multi_sta = false;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		multi_sta = true;
+
+	if ((multi_sta == false) || (dm_digtable.cursta_connectctate !=
+				     DIG_STA_DISCONNECT)) {
+		binitialized = false;
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+		return;
+	} else if (binitialized == false) {
+		binitialized = true;
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+		dm_digtable.cur_igvalue = 0x20;
+		rtl92c_dm_write_dig(hw);
+	}
+
+	if (dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) {
+		if ((rssi_strength < dm_digtable.rssi_lowthresh) &&
+		    (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
+
+			if (dm_digtable.dig_ext_port_stage ==
+			    DIG_EXT_PORT_STAGE_2) {
+				dm_digtable.cur_igvalue = 0x20;
+				rtl92c_dm_write_dig(hw);
+			}
+
+			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
+		} else if (rssi_strength > dm_digtable.rssi_highthresh) {
+			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
+			rtl92c_dm_ctrl_initgain_by_fa(hw);
+		}
+	} else if (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
+		dm_digtable.cur_igvalue = 0x20;
+		rtl92c_dm_write_dig(hw);
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("curmultista_connectstate = "
+		  "%x dig_ext_port_stage %x\n",
+		  dm_digtable.curmultista_connectstate,
+		  dm_digtable.dig_ext_port_stage));
+}
+
+static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("presta_connectstate = %x,"
+		  " cursta_connectctate = %x\n",
+		  dm_digtable.presta_connectstate,
+		  dm_digtable.cursta_connectctate));
+
+	if (dm_digtable.presta_connectstate == dm_digtable.cursta_connectctate
+	    || dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT
+	    || dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+
+		if (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT) {
+			dm_digtable.rssi_val_min =
+			    rtl92c_dm_initial_gain_min_pwdb(hw);
+			rtl92c_dm_ctrl_initgain_by_rssi(hw);
+		}
+	} else {
+		dm_digtable.rssi_val_min = 0;
+		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
+		dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
+		dm_digtable.cur_igvalue = 0x20;
+		dm_digtable.pre_igvalue = 0;
+		rtl92c_dm_write_dig(hw);
+	}
+}
+
+static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
+		dm_digtable.rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
+
+		if (dm_digtable.pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+			if (dm_digtable.rssi_val_min <= 25)
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_LowRssi;
+			else
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_HighRssi;
+		} else {
+			if (dm_digtable.rssi_val_min <= 20)
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_LowRssi;
+			else
+				dm_digtable.cur_cck_pd_state =
+				    CCK_PD_STAGE_HighRssi;
+		}
+	} else {
+		dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
+	}
+
+	if (dm_digtable.pre_cck_pd_state != dm_digtable.cur_cck_pd_state) {
+		if (dm_digtable.cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
+			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
+				dm_digtable.cur_cck_fa_state =
+				    CCK_FA_STAGE_High;
+			else
+				dm_digtable.cur_cck_fa_state = CCK_FA_STAGE_Low;
+
+			if (dm_digtable.pre_cck_fa_state !=
+			    dm_digtable.cur_cck_fa_state) {
+				if (dm_digtable.cur_cck_fa_state ==
+				    CCK_FA_STAGE_Low)
+					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
+						      0x83);
+				else
+					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
+						      0xcd);
+
+				dm_digtable.pre_cck_fa_state =
+				    dm_digtable.cur_cck_fa_state;
+			}
+
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
+
+			if (IS_92C_SERIAL(rtlhal->version))
+				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
+					      MASKBYTE2, 0xd7);
+		} else {
+			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
+			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
+
+			if (IS_92C_SERIAL(rtlhal->version))
+				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
+					      MASKBYTE2, 0xd3);
+		}
+		dm_digtable.pre_cck_pd_state = dm_digtable.cur_cck_pd_state;
+	}
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("CCKPDStage=%x\n", dm_digtable.cur_cck_pd_state));
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
+		 ("is92C=%x\n", IS_92C_SERIAL(rtlhal->version)));
+}
+
+static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	if (mac->act_scanning == true)
+		return;
+
+	if ((mac->link_state > MAC80211_NOLINK) &&
+	    (mac->link_state < MAC80211_LINKED))
+		dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT;
+	else if (mac->link_state >= MAC80211_LINKED)
+		dm_digtable.cursta_connectctate = DIG_STA_CONNECT;
+	else
+		dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
+
+	rtl92c_dm_initial_gain_sta(hw);
+	rtl92c_dm_initial_gain_multi_sta(hw);
+	rtl92c_dm_cck_packet_detection_thresh(hw);
+
+	dm_digtable.presta_connectstate = dm_digtable.cursta_connectctate;
+
+}
+
+static void rtl92c_dm_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->dm.dm_initialgain_enable == false)
+		return;
+	if (dm_digtable.dig_enable_flag == false)
+		return;
+
+	rtl92c_dm_ctrl_initgain_by_twoport(hw);
+
+}
+
+static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dynamic_txpower_enable = false;
+
+	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+}
+
+void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
+		 ("cur_igvalue = 0x%x, "
+		  "pre_igvalue = 0x%x, backoff_val = %d\n",
+		  dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
+		  dm_digtable.backoff_val));
+
+	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
+		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
+			      dm_digtable.cur_igvalue);
+		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
+			      dm_digtable.cur_igvalue);
+
+		dm_digtable.pre_igvalue = dm_digtable.cur_igvalue;
+	}
+}
+EXPORT_SYMBOL(rtl92c_dm_write_dig);
+
+static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
+
+	u8 h2c_parameter[3] = { 0 };
+
+	return;
+
+	if (tmpentry_max_pwdb != 0) {
+		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
+		    tmpentry_max_pwdb;
+	} else {
+		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
+	}
+
+	if (tmpentry_min_pwdb != 0xff) {
+		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
+		    tmpentry_min_pwdb;
+	} else {
+		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
+	}
+
+	h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
+	h2c_parameter[0] = 0;
+
+	rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
+}
+
+void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	rtlpriv->dm.current_turbo_edca = false;
+	rtlpriv->dm.is_any_nonbepkts = false;
+	rtlpriv->dm.is_cur_rdlstate = false;
+}
+EXPORT_SYMBOL(rtl92c_dm_init_edca_turbo);
+
+static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	static u64 last_txok_cnt;
+	static u64 last_rxok_cnt;
+	u64 cur_txok_cnt;
+	u64 cur_rxok_cnt;
+	u32 edca_be_ul = 0x5ea42b;
+	u32 edca_be_dl = 0x5ea42b;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC)
+		goto dm_checkedcaturbo_exit;
+
+	if (mac->link_state != MAC80211_LINKED) {
+		rtlpriv->dm.current_turbo_edca = false;
+		return;
+	}
+
+	if (!mac->ht_enable) {	/*FIX MERGE */
+		if (!(edca_be_ul & 0xffff0000))
+			edca_be_ul |= 0x005e0000;
+
+		if (!(edca_be_dl & 0xffff0000))
+			edca_be_dl |= 0x005e0000;
+	}
+
+	if ((!rtlpriv->dm.is_any_nonbepkts) &&
+	    (!rtlpriv->dm.disable_framebursting)) {
+		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
+		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
+		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
+			if (!rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv,
+						REG_EDCA_BE_PARAM,
+						edca_be_dl);
+				rtlpriv->dm.is_cur_rdlstate = true;
+			}
+		} else {
+			if (rtlpriv->dm.is_cur_rdlstate ||
+			    !rtlpriv->dm.current_turbo_edca) {
+				rtl_write_dword(rtlpriv,
+						REG_EDCA_BE_PARAM,
+						edca_be_ul);
+				rtlpriv->dm.is_cur_rdlstate = false;
+			}
+		}
+		rtlpriv->dm.current_turbo_edca = true;
+	} else {
+		if (rtlpriv->dm.current_turbo_edca) {
+			u8 tmp = AC0_BE;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_AC_PARAM,
+						      (u8 *) (&tmp));
+			rtlpriv->dm.current_turbo_edca = false;
+		}
+	}
+
+dm_checkedcaturbo_exit:
+	rtlpriv->dm.is_any_nonbepkts = false;
+	last_txok_cnt = rtlpriv->stats.txbytesunicast;
+	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
+}
+
+static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
+							     *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 thermalvalue, delta, delta_lck, delta_iqk;
+	long ele_a, ele_d, temp_cck, val_x, value32;
+	long val_y, ele_c;
+	u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old;
+	int i;
+	bool is2t = IS_92C_SERIAL(rtlhal->version);
+	u8 txpwr_level[2] = {0, 0};
+	u8 ofdm_min_index = 6, rf;
+
+	rtlpriv->dm.txpower_trackingInit = true;
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n"));
+
+	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
+		  "eeprom_thermalmeter 0x%x\n",
+		  thermalvalue, rtlpriv->dm.thermalvalue,
+		  rtlefuse->eeprom_thermalmeter));
+
+	rtl92c_phy_ap_calibrate(hw, (thermalvalue -
+				     rtlefuse->eeprom_thermalmeter));
+	if (is2t)
+		rf = 2;
+	else
+		rf = 1;
+
+	if (thermalvalue) {
+		ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+				      MASKDWORD) & MASKOFDM_D;
+
+		for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
+			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
+				ofdm_index_old[0] = (u8) i;
+
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					("Initial pathA ele_d reg0x%x = 0x%lx, "
+					 "ofdm_index=0x%x\n",
+					 ROFDM0_XATXIQIMBALANCE,
+					 ele_d, ofdm_index_old[0]));
+				break;
+			}
+		}
+
+		if (is2t) {
+			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
+					      MASKDWORD) & MASKOFDM_D;
+
+			for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
+				if (ele_d == (ofdmswing_table[i] &
+				    MASKOFDM_D)) {
+					ofdm_index_old[1] = (u8) i;
+
+					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+					   DBG_LOUD,
+					   ("Initial pathB ele_d reg0x%x = "
+					   "0x%lx, ofdm_index=0x%x\n",
+					   ROFDM0_XBTXIQIMBALANCE, ele_d,
+					   ofdm_index_old[1]));
+					break;
+				}
+			}
+		}
+
+		temp_cck =
+		    rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
+
+		for (i = 0; i < CCK_TABLE_LENGTH; i++) {
+			if (rtlpriv->dm.cck_inch14) {
+				if (memcmp((void *)&temp_cck,
+					   (void *)&cckswing_table_ch14[i][2],
+					   4) == 0) {
+					cck_index_old = (u8) i;
+
+					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+						 DBG_LOUD,
+						 ("Initial reg0x%x = 0x%lx, "
+						  "cck_index=0x%x, ch 14 %d\n",
+						  RCCK0_TXFILTER2, temp_cck,
+						  cck_index_old,
+						  rtlpriv->dm.cck_inch14));
+					break;
+				}
+			} else {
+				if (memcmp((void *)&temp_cck,
+					   (void *)
+					   &cckswing_table_ch1ch13[i][2],
+					   4) == 0) {
+					cck_index_old = (u8) i;
+
+					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
+						 DBG_LOUD,
+						 ("Initial reg0x%x = 0x%lx, "
+						  "cck_index=0x%x, ch14 %d\n",
+						  RCCK0_TXFILTER2, temp_cck,
+						  cck_index_old,
+						  rtlpriv->dm.cck_inch14));
+					break;
+				}
+			}
+		}
+
+		if (!rtlpriv->dm.thermalvalue) {
+			rtlpriv->dm.thermalvalue =
+			    rtlefuse->eeprom_thermalmeter;
+			rtlpriv->dm.thermalvalue_lck = thermalvalue;
+			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+			for (i = 0; i < rf; i++)
+				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
+			rtlpriv->dm.cck_index = cck_index_old;
+		}
+
+		delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
+		    (thermalvalue - rtlpriv->dm.thermalvalue) :
+		    (rtlpriv->dm.thermalvalue - thermalvalue);
+
+		delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
+		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
+		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
+
+		delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
+		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
+		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
+
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
+			 "eeprom_thermalmeter 0x%x delta 0x%x "
+			 "delta_lck 0x%x delta_iqk 0x%x\n",
+			 thermalvalue, rtlpriv->dm.thermalvalue,
+			 rtlefuse->eeprom_thermalmeter, delta, delta_lck,
+			 delta_iqk));
+
+		if (delta_lck > 1) {
+			rtlpriv->dm.thermalvalue_lck = thermalvalue;
+			rtl92c_phy_lc_calibrate(hw);
+		}
+
+		if (delta > 0 && rtlpriv->dm.txpower_track_control) {
+			if (thermalvalue > rtlpriv->dm.thermalvalue) {
+				for (i = 0; i < rf; i++)
+					rtlpriv->dm.ofdm_index[i] -= delta;
+				rtlpriv->dm.cck_index -= delta;
+			} else {
+				for (i = 0; i < rf; i++)
+					rtlpriv->dm.ofdm_index[i] += delta;
+				rtlpriv->dm.cck_index += delta;
+			}
+
+			if (is2t) {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("temp OFDM_A_index=0x%x, "
+					  "OFDM_B_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  rtlpriv->dm.ofdm_index[0],
+					  rtlpriv->dm.ofdm_index[1],
+					  rtlpriv->dm.cck_index));
+			} else {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("temp OFDM_A_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  rtlpriv->dm.ofdm_index[0],
+					  rtlpriv->dm.cck_index));
+			}
+
+			if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
+				for (i = 0; i < rf; i++)
+					ofdm_index[i] =
+					    rtlpriv->dm.ofdm_index[i]
+					    + 1;
+				cck_index = rtlpriv->dm.cck_index + 1;
+			} else {
+				for (i = 0; i < rf; i++)
+					ofdm_index[i] =
+					    rtlpriv->dm.ofdm_index[i];
+				cck_index = rtlpriv->dm.cck_index;
+			}
+
+			for (i = 0; i < rf; i++) {
+				if (txpwr_level[i] >= 0 &&
+				    txpwr_level[i] <= 26) {
+					if (thermalvalue >
+					    rtlefuse->eeprom_thermalmeter) {
+						if (delta < 5)
+							ofdm_index[i] -= 1;
+
+						else
+							ofdm_index[i] -= 2;
+					} else if (delta > 5 && thermalvalue <
+						   rtlefuse->
+						   eeprom_thermalmeter) {
+						ofdm_index[i] += 1;
+					}
+				} else if (txpwr_level[i] >= 27 &&
+					   txpwr_level[i] <= 32
+					   && thermalvalue >
+					   rtlefuse->eeprom_thermalmeter) {
+					if (delta < 5)
+						ofdm_index[i] -= 1;
+
+					else
+						ofdm_index[i] -= 2;
+				} else if (txpwr_level[i] >= 32 &&
+					   txpwr_level[i] <= 38 &&
+					   thermalvalue >
+					   rtlefuse->eeprom_thermalmeter
+					   && delta > 5) {
+					ofdm_index[i] -= 1;
+				}
+			}
+
+			if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
+				if (thermalvalue >
+				    rtlefuse->eeprom_thermalmeter) {
+					if (delta < 5)
+						cck_index -= 1;
+
+					else
+						cck_index -= 2;
+				} else if (delta > 5 && thermalvalue <
+					   rtlefuse->eeprom_thermalmeter) {
+					cck_index += 1;
+				}
+			} else if (txpwr_level[i] >= 27 &&
+				   txpwr_level[i] <= 32 &&
+				   thermalvalue >
+				   rtlefuse->eeprom_thermalmeter) {
+				if (delta < 5)
+					cck_index -= 1;
+
+				else
+					cck_index -= 2;
+			} else if (txpwr_level[i] >= 32 &&
+				   txpwr_level[i] <= 38 &&
+				   thermalvalue > rtlefuse->eeprom_thermalmeter
+				   && delta > 5) {
+				cck_index -= 1;
+			}
+
+			for (i = 0; i < rf; i++) {
+				if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
+					ofdm_index[i] = OFDM_TABLE_SIZE - 1;
+
+				else if (ofdm_index[i] < ofdm_min_index)
+					ofdm_index[i] = ofdm_min_index;
+			}
+
+			if (cck_index > CCK_TABLE_SIZE - 1)
+				cck_index = CCK_TABLE_SIZE - 1;
+			else if (cck_index < 0)
+				cck_index = 0;
+
+			if (is2t) {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("new OFDM_A_index=0x%x, "
+					  "OFDM_B_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  ofdm_index[0], ofdm_index[1],
+					  cck_index));
+			} else {
+				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+					 ("new OFDM_A_index=0x%x,"
+					  "cck_index=0x%x\n",
+					  ofdm_index[0], cck_index));
+			}
+		}
+
+		if (rtlpriv->dm.txpower_track_control && delta != 0) {
+			ele_d =
+			    (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
+			val_x = rtlphy->reg_e94;
+			val_y = rtlphy->reg_e9c;
+
+			if (val_x != 0) {
+				if ((val_x & 0x00000200) != 0)
+					val_x = val_x | 0xFFFFFC00;
+				ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
+
+				if ((val_y & 0x00000200) != 0)
+					val_y = val_y | 0xFFFFFC00;
+				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
+
+				value32 = (ele_d << 22) |
+				    ((ele_c & 0x3F) << 16) | ele_a;
+
+				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					      MASKDWORD, value32);
+
+				value32 = (ele_c & 0x000003C0) >> 6;
+				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
+					      value32);
+
+				value32 = ((val_x * ele_d) >> 7) & 0x01;
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(31), value32);
+
+				value32 = ((val_y * ele_d) >> 7) & 0x01;
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(29), value32);
+			} else {
+				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					      MASKDWORD,
+					      ofdmswing_table[ofdm_index[0]]);
+
+				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
+					      0x00);
+				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+					      BIT(31) | BIT(29), 0x00);
+			}
+
+			if (!rtlpriv->dm.cck_inch14) {
+				rtl_write_byte(rtlpriv, 0xa22,
+					       cckswing_table_ch1ch13[cck_index]
+					       [0]);
+				rtl_write_byte(rtlpriv, 0xa23,
+					       cckswing_table_ch1ch13[cck_index]
+					       [1]);
+				rtl_write_byte(rtlpriv, 0xa24,
+					       cckswing_table_ch1ch13[cck_index]
+					       [2]);
+				rtl_write_byte(rtlpriv, 0xa25,
+					       cckswing_table_ch1ch13[cck_index]
+					       [3]);
+				rtl_write_byte(rtlpriv, 0xa26,
+					       cckswing_table_ch1ch13[cck_index]
+					       [4]);
+				rtl_write_byte(rtlpriv, 0xa27,
+					       cckswing_table_ch1ch13[cck_index]
+					       [5]);
+				rtl_write_byte(rtlpriv, 0xa28,
+					       cckswing_table_ch1ch13[cck_index]
+					       [6]);
+				rtl_write_byte(rtlpriv, 0xa29,
+					       cckswing_table_ch1ch13[cck_index]
+					       [7]);
+			} else {
+				rtl_write_byte(rtlpriv, 0xa22,
+					       cckswing_table_ch14[cck_index]
+					       [0]);
+				rtl_write_byte(rtlpriv, 0xa23,
+					       cckswing_table_ch14[cck_index]
+					       [1]);
+				rtl_write_byte(rtlpriv, 0xa24,
+					       cckswing_table_ch14[cck_index]
+					       [2]);
+				rtl_write_byte(rtlpriv, 0xa25,
+					       cckswing_table_ch14[cck_index]
+					       [3]);
+				rtl_write_byte(rtlpriv, 0xa26,
+					       cckswing_table_ch14[cck_index]
+					       [4]);
+				rtl_write_byte(rtlpriv, 0xa27,
+					       cckswing_table_ch14[cck_index]
+					       [5]);
+				rtl_write_byte(rtlpriv, 0xa28,
+					       cckswing_table_ch14[cck_index]
+					       [6]);
+				rtl_write_byte(rtlpriv, 0xa29,
+					       cckswing_table_ch14[cck_index]
+					       [7]);
+			}
+
+			if (is2t) {
+				ele_d = (ofdmswing_table[ofdm_index[1]] &
+					 0xFFC00000) >> 22;
+
+				val_x = rtlphy->reg_eb4;
+				val_y = rtlphy->reg_ebc;
+
+				if (val_x != 0) {
+					if ((val_x & 0x00000200) != 0)
+						val_x = val_x | 0xFFFFFC00;
+					ele_a = ((val_x * ele_d) >> 8) &
+					    0x000003FF;
+
+					if ((val_y & 0x00000200) != 0)
+						val_y = val_y | 0xFFFFFC00;
+					ele_c = ((val_y * ele_d) >> 8) &
+					    0x00003FF;
+
+					value32 = (ele_d << 22) |
+					    ((ele_c & 0x3F) << 16) | ele_a;
+					rtl_set_bbreg(hw,
+						      ROFDM0_XBTXIQIMBALANCE,
+						      MASKDWORD, value32);
+
+					value32 = (ele_c & 0x000003C0) >> 6;
+					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
+						      MASKH4BITS, value32);
+
+					value32 = ((val_x * ele_d) >> 7) & 0x01;
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(27), value32);
+
+					value32 = ((val_y * ele_d) >> 7) & 0x01;
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(25), value32);
+				} else {
+					rtl_set_bbreg(hw,
+						      ROFDM0_XBTXIQIMBALANCE,
+						      MASKDWORD,
+						      ofdmswing_table[ofdm_index
+								      [1]]);
+					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
+						      MASKH4BITS, 0x00);
+					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
+						      BIT(27) | BIT(25), 0x00);
+				}
+
+			}
+		}
+
+		if (delta_iqk > 3) {
+			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
+			rtl92c_phy_iq_calibrate(hw, false);
+		}
+
+		if (rtlpriv->dm.txpower_track_control)
+			rtlpriv->dm.thermalvalue = thermalvalue;
+	}
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
+
+}
+
+static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
+						struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.txpower_tracking = true;
+	rtlpriv->dm.txpower_trackingInit = false;
+
+	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+		 ("pMgntInfo->txpower_tracking = %d\n",
+		  rtlpriv->dm.txpower_tracking));
+}
+
+static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
+{
+	rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
+}
+
+static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
+{
+	rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
+}
+
+static void rtl92c_dm_check_txpower_tracking_thermal_meter(
+						struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	static u8 tm_trigger;
+
+	if (!rtlpriv->dm.txpower_tracking)
+		return;
+
+	if (!tm_trigger) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
+			      0x60);
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Trigger 92S Thermal Meter!!\n"));
+		tm_trigger = 1;
+		return;
+	} else {
+		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
+			 ("Schedule TxPowerTracking direct call!!\n"));
+		rtl92c_dm_txpower_tracking_directcall(hw);
+		tm_trigger = 0;
+	}
+}
+
+void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
+{
+	rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
+}
+EXPORT_SYMBOL(rtl92c_dm_check_txpower_tracking);
+
+void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rate_adaptive *p_ra = &(rtlpriv->ra);
+
+	p_ra->ratr_state = DM_RATR_STA_INIT;
+	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
+
+	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
+		rtlpriv->dm.useramask = true;
+	else
+		rtlpriv->dm.useramask = false;
+
+}
+EXPORT_SYMBOL(rtl92c_dm_init_rate_adaptive_mask);
+
+static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rate_adaptive *p_ra = &(rtlpriv->ra);
+	u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
+
+	if (is_hal_stop(rtlhal)) {
+		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+			 ("<---- driver is going to unload\n"));
+		return;
+	}
+
+	if (!rtlpriv->dm.useramask) {
+		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+			("<---- driver does not control rate adaptive mask\n"));
+		return;
+	}
+
+	if (mac->link_state == MAC80211_LINKED) {
+
+		switch (p_ra->pre_ratr_state) {
+		case DM_RATR_STA_HIGH:
+			high_rssithresh_for_ra = 50;
+			low_rssithresh_for_ra = 20;
+			break;
+		case DM_RATR_STA_MIDDLE:
+			high_rssithresh_for_ra = 55;
+			low_rssithresh_for_ra = 20;
+			break;
+		case DM_RATR_STA_LOW:
+			high_rssithresh_for_ra = 50;
+			low_rssithresh_for_ra = 25;
+			break;
+		default:
+			high_rssithresh_for_ra = 50;
+			low_rssithresh_for_ra = 20;
+			break;
+		}
+
+		if (rtlpriv->dm.undecorated_smoothed_pwdb >
+		    (long)high_rssithresh_for_ra)
+			p_ra->ratr_state = DM_RATR_STA_HIGH;
+		else if (rtlpriv->dm.undecorated_smoothed_pwdb >
+			 (long)low_rssithresh_for_ra)
+			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
+		else
+			p_ra->ratr_state = DM_RATR_STA_LOW;
+
+		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 ("RSSI = %ld\n",
+				  rtlpriv->dm.undecorated_smoothed_pwdb));
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 ("RSSI_LEVEL = %d\n", p_ra->ratr_state));
+			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
+				 ("PreState = %d, CurState = %d\n",
+				  p_ra->pre_ratr_state, p_ra->ratr_state));
+
+			rtlpriv->cfg->ops->update_rate_mask(hw,
+					p_ra->ratr_state);
+
+			p_ra->pre_ratr_state = p_ra->ratr_state;
+		}
+	}
+}
+
+static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
+{
+	dm_pstable.pre_ccastate = CCA_MAX;
+	dm_pstable.cur_ccasate = CCA_MAX;
+	dm_pstable.pre_rfstate = RF_MAX;
+	dm_pstable.cur_rfstate = RF_MAX;
+	dm_pstable.rssi_val_min = 0;
+}
+
+static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (dm_pstable.rssi_val_min != 0) {
+		if (dm_pstable.pre_ccastate == CCA_2R) {
+			if (dm_pstable.rssi_val_min >= 35)
+				dm_pstable.cur_ccasate = CCA_1R;
+			else
+				dm_pstable.cur_ccasate = CCA_2R;
+		} else {
+			if (dm_pstable.rssi_val_min <= 30)
+				dm_pstable.cur_ccasate = CCA_2R;
+			else
+				dm_pstable.cur_ccasate = CCA_1R;
+		}
+	} else {
+		dm_pstable.cur_ccasate = CCA_MAX;
+	}
+
+	if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) {
+		if (dm_pstable.cur_ccasate == CCA_1R) {
+			if (get_rf_type(rtlphy) == RF_2T2R) {
+				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
+					      MASKBYTE0, 0x13);
+				rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20);
+			} else {
+				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
+					      MASKBYTE0, 0x23);
+				rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c);
+			}
+		} else {
+			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0,
+				      0x33);
+			rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63);
+		}
+		dm_pstable.pre_ccastate = dm_pstable.cur_ccasate;
+	}
+
+	RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n",
+					       (dm_pstable.cur_ccasate ==
+						0) ? "1RCCA" : "2RCCA"));
+}
+
+void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
+{
+	static u8 initialize;
+	static u32 reg_874, reg_c70, reg_85c, reg_a74;
+
+	if (initialize == 0) {
+		reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+					 MASKDWORD) & 0x1CC000) >> 14;
+
+		reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
+					 MASKDWORD) & BIT(3)) >> 3;
+
+		reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+					 MASKDWORD) & 0xFF000000) >> 24;
+
+		reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
+
+		initialize = 1;
+	}
+
+	if (!bforce_in_normal) {
+		if (dm_pstable.rssi_val_min != 0) {
+			if (dm_pstable.pre_rfstate == RF_NORMAL) {
+				if (dm_pstable.rssi_val_min >= 30)
+					dm_pstable.cur_rfstate = RF_SAVE;
+				else
+					dm_pstable.cur_rfstate = RF_NORMAL;
+			} else {
+				if (dm_pstable.rssi_val_min <= 25)
+					dm_pstable.cur_rfstate = RF_NORMAL;
+				else
+					dm_pstable.cur_rfstate = RF_SAVE;
+			}
+		} else {
+			dm_pstable.cur_rfstate = RF_MAX;
+		}
+	} else {
+		dm_pstable.cur_rfstate = RF_NORMAL;
+	}
+
+	if (dm_pstable.pre_rfstate != dm_pstable.cur_rfstate) {
+		if (dm_pstable.cur_rfstate == RF_SAVE) {
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0x1C0000, 0x2);
+			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
+			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
+				      0xFF000000, 0x63);
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0xC000, 0x2);
+			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
+		} else {
+			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
+				      0x1CC000, reg_874);
+			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
+				      reg_c70);
+			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
+				      reg_85c);
+			rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
+			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
+		}
+
+		dm_pstable.pre_rfstate = dm_pstable.cur_rfstate;
+	}
+}
+EXPORT_SYMBOL(rtl92c_dm_rf_saving);
+
+static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (((mac->link_state == MAC80211_NOLINK)) &&
+	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+		dm_pstable.rssi_val_min = 0;
+		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+			 ("Not connected to any\n"));
+	}
+
+	if (mac->link_state == MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			dm_pstable.rssi_val_min =
+			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+				 ("AP Client PWDB = 0x%lx\n",
+				  dm_pstable.rssi_val_min));
+		} else {
+			dm_pstable.rssi_val_min =
+			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+				 ("STA Default Port PWDB = 0x%lx\n",
+				  dm_pstable.rssi_val_min));
+		}
+	} else {
+		dm_pstable.rssi_val_min =
+		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+
+		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
+			 ("AP Ext Port PWDB = 0x%lx\n",
+			  dm_pstable.rssi_val_min));
+	}
+
+	if (IS_92C_SERIAL(rtlhal->version))
+		rtl92c_dm_1r_cca(hw);
+}
+
+void rtl92c_dm_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
+	rtl92c_dm_diginit(hw);
+	rtl92c_dm_init_dynamic_txpower(hw);
+	rtl92c_dm_init_edca_turbo(hw);
+	rtl92c_dm_init_rate_adaptive_mask(hw);
+	rtl92c_dm_initialize_txpower_tracking(hw);
+	rtl92c_dm_init_dynamic_bb_powersaving(hw);
+}
+EXPORT_SYMBOL(rtl92c_dm_init);
+
+void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool fw_current_inpsmode = false;
+	bool fw_ps_awake = true;
+
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
+				      (u8 *) (&fw_current_inpsmode));
+	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
+				      (u8 *) (&fw_ps_awake));
+
+	if ((ppsc->rfpwr_state == ERFON) && ((!fw_current_inpsmode) &&
+					     fw_ps_awake)
+	    && (!ppsc->rfchange_inprogress)) {
+		rtl92c_dm_pwdb_monitor(hw);
+		rtl92c_dm_dig(hw);
+		rtl92c_dm_false_alarm_counter_statistics(hw);
+		rtl92c_dm_dynamic_bb_powersaving(hw);
+		rtlpriv->cfg->ops->dm_dynamic_txpower(hw);
+		rtl92c_dm_check_txpower_tracking(hw);
+		rtl92c_dm_refresh_rate_adaptive_mask(hw);
+		rtl92c_dm_check_edca_turbo(hw);
+
+	}
+}
+EXPORT_SYMBOL(rtl92c_dm_watchdog);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/dm_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,204 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef	__RTL92COMMON_DM_H__
+#define __RTL92COMMON_DM_H__
+
+#include "../wifi.h"
+#include "../rtl8192ce/def.h"
+#include "../rtl8192ce/reg.h"
+#include "fw_common.h"
+
+#define HAL_DM_DIG_DISABLE			BIT(0)
+#define HAL_DM_HIPWR_DISABLE			BIT(1)
+
+#define OFDM_TABLE_LENGTH			37
+#define CCK_TABLE_LENGTH			33
+
+#define OFDM_TABLE_SIZE				37
+#define CCK_TABLE_SIZE				33
+
+#define BW_AUTO_SWITCH_HIGH_LOW			25
+#define BW_AUTO_SWITCH_LOW_HIGH			30
+
+#define DM_DIG_THRESH_HIGH			40
+#define DM_DIG_THRESH_LOW			35
+
+#define DM_FALSEALARM_THRESH_LOW		400
+#define DM_FALSEALARM_THRESH_HIGH		1000
+
+#define DM_DIG_MAX				0x3e
+#define DM_DIG_MIN				0x1e
+
+#define DM_DIG_FA_UPPER				0x32
+#define DM_DIG_FA_LOWER				0x20
+#define DM_DIG_FA_TH0				0x20
+#define DM_DIG_FA_TH1				0x100
+#define DM_DIG_FA_TH2				0x200
+
+#define DM_DIG_BACKOFF_MAX			12
+#define DM_DIG_BACKOFF_MIN			-4
+#define DM_DIG_BACKOFF_DEFAULT			10
+
+#define RXPATHSELECTION_SS_TH_lOW		30
+#define RXPATHSELECTION_DIFF_TH			18
+
+#define DM_RATR_STA_INIT			0
+#define DM_RATR_STA_HIGH			1
+#define DM_RATR_STA_MIDDLE			2
+#define DM_RATR_STA_LOW				3
+
+#define CTS2SELF_THVAL				30
+#define REGC38_TH				20
+
+#define WAIOTTHVal				25
+
+#define TXHIGHPWRLEVEL_NORMAL			0
+#define TXHIGHPWRLEVEL_LEVEL1			1
+#define TXHIGHPWRLEVEL_LEVEL2			2
+#define TXHIGHPWRLEVEL_BT1			3
+#define TXHIGHPWRLEVEL_BT2			4
+
+#define DM_TYPE_BYFW				0
+#define DM_TYPE_BYDRIVER			1
+
+#define TX_POWER_NEAR_FIELD_THRESH_LVL2		74
+#define TX_POWER_NEAR_FIELD_THRESH_LVL1		67
+
+struct ps_t {
+	u8 pre_ccastate;
+	u8 cur_ccasate;
+	u8 pre_rfstate;
+	u8 cur_rfstate;
+	long rssi_val_min;
+};
+
+struct dig_t {
+	u8 dig_enable_flag;
+	u8 dig_ext_port_stage;
+	u32 rssi_lowthresh;
+	u32 rssi_highthresh;
+	u32 fa_lowthresh;
+	u32 fa_highthresh;
+	u8 cursta_connectctate;
+	u8 presta_connectstate;
+	u8 curmultista_connectstate;
+	u8 pre_igvalue;
+	u8 cur_igvalue;
+	char backoff_val;
+	char backoff_val_range_max;
+	char backoff_val_range_min;
+	u8 rx_gain_range_max;
+	u8 rx_gain_range_min;
+	u8 rssi_val_min;
+	u8 pre_cck_pd_state;
+	u8 cur_cck_pd_state;
+	u8 pre_cck_fa_state;
+	u8 cur_cck_fa_state;
+	u8 pre_ccastate;
+	u8 cur_ccasate;
+};
+
+struct swat_t {
+	u8 failure_cnt;
+	u8 try_flag;
+	u8 stop_trying;
+	long pre_rssi;
+	long trying_threshold;
+	u8 cur_antenna;
+	u8 pre_antenna;
+};
+
+enum tag_dynamic_init_gain_operation_type_definition {
+	DIG_TYPE_THRESH_HIGH = 0,
+	DIG_TYPE_THRESH_LOW = 1,
+	DIG_TYPE_BACKOFF = 2,
+	DIG_TYPE_RX_GAIN_MIN = 3,
+	DIG_TYPE_RX_GAIN_MAX = 4,
+	DIG_TYPE_ENABLE = 5,
+	DIG_TYPE_DISABLE = 6,
+	DIG_OP_TYPE_MAX
+};
+
+enum tag_cck_packet_detection_threshold_type_definition {
+	CCK_PD_STAGE_LowRssi = 0,
+	CCK_PD_STAGE_HighRssi = 1,
+	CCK_FA_STAGE_Low = 2,
+	CCK_FA_STAGE_High = 3,
+	CCK_PD_STAGE_MAX = 4,
+};
+
+enum dm_1r_cca_e {
+	CCA_1R = 0,
+	CCA_2R = 1,
+	CCA_MAX = 2,
+};
+
+enum dm_rf_e {
+	RF_SAVE = 0,
+	RF_NORMAL = 1,
+	RF_MAX = 2,
+};
+
+enum dm_sw_ant_switch_e {
+	ANS_ANTENNA_B = 1,
+	ANS_ANTENNA_A = 2,
+	ANS_ANTENNA_MAX = 3,
+};
+
+enum dm_dig_ext_port_alg_e {
+	DIG_EXT_PORT_STAGE_0 = 0,
+	DIG_EXT_PORT_STAGE_1 = 1,
+	DIG_EXT_PORT_STAGE_2 = 2,
+	DIG_EXT_PORT_STAGE_3 = 3,
+	DIG_EXT_PORT_STAGE_MAX = 4,
+};
+
+enum dm_dig_connect_e {
+	DIG_STA_DISCONNECT = 0,
+	DIG_STA_CONNECT = 1,
+	DIG_STA_BEFORE_CONNECT = 2,
+	DIG_MULTISTA_DISCONNECT = 3,
+	DIG_MULTISTA_CONNECT = 4,
+	DIG_CONNECT_MAX
+};
+
+extern struct dig_t dm_digtable;
+void rtl92c_dm_init(struct ieee80211_hw *hw);
+void rtl92c_dm_watchdog(struct ieee80211_hw *hw);
+void rtl92c_dm_write_dig(struct ieee80211_hw *hw);
+void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw);
+void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw);
+void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
+void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal);
+void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c	2012-03-24 03:34:36.000000000 -0400
@@ -0,0 +1,774 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include <linux/firmware.h>
+#include "../wifi.h"
+#include "../pci.h"
+#include "../base.h"
+#include "../rtl8192ce/reg.h"
+#include "../rtl8192ce/def.h"
+#include "fw_common.h"
+
+static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
+		u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+		if (enable)
+			value32 |= MCUFWDL_EN;
+		else
+			value32 &= ~MCUFWDL_EN;
+		rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+	} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
+		u8 tmp;
+		if (enable) {
+
+			tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+			rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
+				       tmp | 0x04);
+
+			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+			rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
+
+			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
+			rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
+		} else {
+
+			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
+			rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
+
+			rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
+		}
+	}
+}
+
+static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
+				   const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 blockSize = sizeof(u32);
+	u8 *bufferPtr = (u8 *) buffer;
+	u32 *pu4BytePtr = (u32 *) buffer;
+	u32 i, offset, blockCount, remainSize;
+
+	blockCount = size / blockSize;
+	remainSize = size % blockSize;
+
+	for (i = 0; i < blockCount; i++) {
+		offset = i * blockSize;
+		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
+				*(pu4BytePtr + i));
+	}
+
+	if (remainSize) {
+		offset = blockCount * blockSize;
+		bufferPtr += offset;
+		for (i = 0; i < remainSize; i++) {
+			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
+						 offset + i), *(bufferPtr + i));
+		}
+	}
+}
+
+static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
+				  u32 page, const u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value8;
+	u8 u8page = (u8) (page & 0x07);
+
+	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
+
+	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
+	_rtl92c_fw_block_write(hw, buffer, size);
+}
+
+static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
+{
+	u32 fwlen = *pfwlen;
+	u8 remain = (u8) (fwlen % 4);
+
+	remain = (remain == 0) ? 0 : (4 - remain);
+
+	while (remain > 0) {
+		pfwbuf[fwlen] = 0;
+		fwlen++;
+		remain--;
+	}
+
+	*pfwlen = fwlen;
+}
+
+static void _rtl92c_write_fw(struct ieee80211_hw *hw,
+			     enum version_8192c version, u8 *buffer, u32 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 *bufferPtr = (u8 *) buffer;
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
+
+	if (IS_CHIP_VER_B(version)) {
+		u32 pageNums, remainSize;
+		u32 page, offset;
+
+		if (IS_HARDWARE_TYPE_8192CE(rtlhal))
+			_rtl92c_fill_dummy(bufferPtr, &size);
+
+		pageNums = size / FW_8192C_PAGE_SIZE;
+		remainSize = size % FW_8192C_PAGE_SIZE;
+
+		if (pageNums > 4) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Page numbers should not greater then 4\n"));
+		}
+
+		for (page = 0; page < pageNums; page++) {
+			offset = page * FW_8192C_PAGE_SIZE;
+			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
+					      FW_8192C_PAGE_SIZE);
+		}
+
+		if (remainSize) {
+			offset = pageNums * FW_8192C_PAGE_SIZE;
+			page = pageNums;
+			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
+					      remainSize);
+		}
+	} else {
+		_rtl92c_fw_block_write(hw, buffer, size);
+	}
+}
+
+static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int err = -EIO;
+	u32 counter = 0;
+	u32 value32;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
+		 (!(value32 & FWDL_ChkSum_rpt)));
+
+	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
+			  value32));
+		goto exit;
+	}
+
+	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+		 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
+
+	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+	value32 |= MCUFWDL_RDY;
+	value32 &= ~WINTINI_RDY;
+	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
+
+	counter = 0;
+
+	do {
+		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
+		if (value32 & WINTINI_RDY) {
+			RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+				 ("Polling FW ready success!!"
+				 " REG_MCUFWDL:0x%08x .\n",
+				 value32));
+			err = 0;
+			goto exit;
+		}
+
+		mdelay(FW_8192C_POLLING_DELAY);
+
+	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
+
+	RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+		 ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32));
+
+exit:
+	return err;
+}
+
+int rtl92c_download_fw(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl92c_firmware_header *pfwheader;
+	u8 *pfwdata;
+	u32 fwsize;
+	int err;
+	enum version_8192c version = rtlhal->version;
+	const struct firmware *firmware;
+
+	printk(KERN_INFO "rtl8192cu: Loading firmware file %s\n",
+	       rtlpriv->cfg->fw_name);
+	err = reject_firmware(&firmware, rtlpriv->cfg->fw_name,
+			       rtlpriv->io.dev);
+	if (err) {
+		printk(KERN_ERR "rtl8192cu: Firmware loading failed\n");
+		return 1;
+	}
+
+	if (firmware->size > 0x4000) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is too big!\n"));
+		release_firmware(firmware);
+		return 1;
+	}
+
+	memcpy(rtlhal->pfirmware, firmware->data, firmware->size);
+	fwsize = firmware->size;
+	release_firmware(firmware);
+
+	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
+	pfwdata = (u8 *) rtlhal->pfirmware;
+
+	if (IS_FW_HEADER_EXIST(pfwheader)) {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
+			 ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
+			  pfwheader->version, pfwheader->signature,
+			  (uint)sizeof(struct rtl92c_firmware_header)));
+
+		pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
+		fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
+	}
+
+	_rtl92c_enable_fw_download(hw, true);
+	_rtl92c_write_fw(hw, version, pfwdata, fwsize);
+	_rtl92c_enable_fw_download(hw, false);
+
+	err = _rtl92c_fw_free_to_go(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Firmware is not ready to run!\n"));
+	} else {
+		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
+			 ("Firmware is ready to run!\n"));
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(rtl92c_download_fw);
+
+static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 val_hmetfr, val_mcutst_1;
+	bool result = false;
+
+	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
+	val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
+
+	if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
+		result = true;
+	return result;
+}
+
+static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
+			      u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 boxnum;
+	u16 box_reg, box_extreg;
+	u8 u1b_tmp;
+	bool isfw_read = false;
+	u8 buf_index = 0;
+	bool bwrite_sucess = false;
+	u8 wait_h2c_limmit = 100;
+	u8 wait_writeh2c_limmit = 100;
+	u8 boxcontent[4], boxextcontent[2];
+	u32 h2c_waitcounter = 0;
+	unsigned long flag;
+	u8 idx;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
+
+	while (true) {
+		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+		if (rtlhal->h2c_setinprogress) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("H2C set in progress! Wait to set.."
+				  "element_id(%d).\n", element_id));
+
+			while (rtlhal->h2c_setinprogress) {
+				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
+						       flag);
+				h2c_waitcounter++;
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 ("Wait 100 us (%d times)...\n",
+					  h2c_waitcounter));
+				udelay(100);
+
+				if (h2c_waitcounter > 1000)
+					return;
+				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
+						  flag);
+			}
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+		} else {
+			rtlhal->h2c_setinprogress = true;
+			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+			break;
+		}
+	}
+
+	while (!bwrite_sucess) {
+		wait_writeh2c_limmit--;
+		if (wait_writeh2c_limmit == 0) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Write H2C fail because no trigger "
+				  "for FW INT!\n"));
+			break;
+		}
+
+		boxnum = rtlhal->last_hmeboxnum;
+		switch (boxnum) {
+		case 0:
+			box_reg = REG_HMEBOX_0;
+			box_extreg = REG_HMEBOX_EXT_0;
+			break;
+		case 1:
+			box_reg = REG_HMEBOX_1;
+			box_extreg = REG_HMEBOX_EXT_1;
+			break;
+		case 2:
+			box_reg = REG_HMEBOX_2;
+			box_extreg = REG_HMEBOX_EXT_2;
+			break;
+		case 3:
+			box_reg = REG_HMEBOX_3;
+			box_extreg = REG_HMEBOX_EXT_3;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+
+		isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
+		while (!isfw_read) {
+
+			wait_h2c_limmit--;
+			if (wait_h2c_limmit == 0) {
+				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+					 ("Wating too long for FW read "
+					  "clear HMEBox(%d)!\n", boxnum));
+				break;
+			}
+
+			udelay(10);
+
+			isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
+			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("Wating for FW read clear HMEBox(%d)!!! "
+				  "0x1BF = %2x\n", boxnum, u1b_tmp));
+		}
+
+		if (!isfw_read) {
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+				 ("Write H2C register BOX[%d] fail!!!!! "
+				  "Fw do not read.\n", boxnum));
+			break;
+		}
+
+		memset(boxcontent, 0, sizeof(boxcontent));
+		memset(boxextcontent, 0, sizeof(boxextcontent));
+		boxcontent[0] = element_id;
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("Write element_id box_reg(%4x) = %2x\n",
+			  box_reg, element_id));
+
+		switch (cmd_len) {
+		case 1:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index, 1);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 2:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index, 2);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 3:
+			boxcontent[0] &= ~(BIT(7));
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index, 3);
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 4:
+			boxcontent[0] |= (BIT(7));
+			memcpy((u8 *) (boxextcontent),
+			       p_cmdbuffer + buf_index, 2);
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index + 2, 2);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		case 5:
+			boxcontent[0] |= (BIT(7));
+			memcpy((u8 *) (boxextcontent),
+			       p_cmdbuffer + buf_index, 2);
+			memcpy((u8 *) (boxcontent) + 1,
+			       p_cmdbuffer + buf_index + 2, 3);
+
+			for (idx = 0; idx < 2; idx++) {
+				rtl_write_byte(rtlpriv, box_extreg + idx,
+					       boxextcontent[idx]);
+			}
+
+			for (idx = 0; idx < 4; idx++) {
+				rtl_write_byte(rtlpriv, box_reg + idx,
+					       boxcontent[idx]);
+			}
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+
+		bwrite_sucess = true;
+
+		rtlhal->last_hmeboxnum = boxnum + 1;
+		if (rtlhal->last_hmeboxnum == 4)
+			rtlhal->last_hmeboxnum = 0;
+
+		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
+			 ("pHalData->last_hmeboxnum  = %d\n",
+			  rtlhal->last_hmeboxnum));
+	}
+
+	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
+	rtlhal->h2c_setinprogress = false;
+	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
+}
+
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u32 tmp_cmdbuf[2];
+
+	if (rtlhal->fw_ready == false) {
+		RT_ASSERT(false, ("return H2C cmd because of Fw "
+				  "download fail!!!\n"));
+		return;
+	}
+
+	memset(tmp_cmdbuf, 0, 8);
+	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
+	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
+
+	return;
+}
+EXPORT_SYMBOL(rtl92c_fill_h2c_cmd);
+
+void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
+{
+	u8 u1b_tmp;
+	u8 delay = 100;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
+	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+
+	while (u1b_tmp & BIT(2)) {
+		delay--;
+		if (delay == 0) {
+			RT_ASSERT(false, ("8051 reset fail.\n"));
+			break;
+		}
+		udelay(50);
+		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
+	}
+}
+EXPORT_SYMBOL(rtl92c_firmware_selfreset);
+
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 u1_h2c_set_pwrmode[3] = {0};
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
+
+	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
+	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
+	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
+					      ppsc->reg_max_lps_awakeintvl);
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
+		      u1_h2c_set_pwrmode, 3);
+	rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
+
+}
+EXPORT_SYMBOL(rtl92c_set_fw_pwrmode_cmd);
+
+#define BEACON_PG		0 /*->1*/
+#define PSPOLL_PG		2
+#define NULL_PG			3
+#define PROBERSP_PG		4 /*->5*/
+
+#define TOTAL_RESERVED_PKT_LEN	768
+
+static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
+	/* page 0 beacon */
+	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
+	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 1 beacon */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 2  ps-poll */
+	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 3  null */
+	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
+	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 4  probe_resp */
+	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
+	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
+	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
+	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
+	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
+	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
+	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
+	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
+	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
+	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
+	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
+	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+
+	/* page 5  probe_resp */
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+};
+
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct sk_buff *skb = NULL;
+
+	u32 totalpacketlen;
+	bool rtstatus;
+	u8 u1RsvdPageLoc[3] = {0};
+	bool b_dlok = false;
+
+	u8 *beacon;
+	u8 *p_pspoll;
+	u8 *nullfunc;
+	u8 *p_probersp;
+	/*---------------------------------------------------------
+				(1) beacon
+	---------------------------------------------------------*/
+	beacon = &reserved_page_packet[BEACON_PG * 128];
+	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
+
+	/*-------------------------------------------------------
+				(2) ps-poll
+	--------------------------------------------------------*/
+	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
+	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
+	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
+	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
+
+	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
+
+	/*--------------------------------------------------------
+				(3) null data
+	---------------------------------------------------------*/
+	nullfunc = &reserved_page_packet[NULL_PG * 128];
+	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
+	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
+
+	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
+
+	/*---------------------------------------------------------
+				(4) probe response
+	----------------------------------------------------------*/
+	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
+	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
+	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
+	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
+
+	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
+
+	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
+
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
+		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      &reserved_page_packet[0], totalpacketlen);
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
+		      u1RsvdPageLoc, 3);
+
+
+	skb = dev_alloc_skb(totalpacketlen);
+	memcpy((u8 *) skb_put(skb, totalpacketlen),
+	       &reserved_page_packet, totalpacketlen);
+
+	rtstatus = rtlpriv->cfg->ops->cmd_send_packet(hw, skb);
+
+	if (rtstatus)
+		b_dlok = true;
+
+	if (b_dlok) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("Set RSVD page location to Fw.\n"));
+		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
+				"H2C_RSVDPAGE:\n",
+				u1RsvdPageLoc, 3);
+		rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
+				    sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
+	} else
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
+}
+EXPORT_SYMBOL(rtl92c_set_fw_rsvdpagepkt);
+
+void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
+{
+	u8 u1_joinbssrpt_parm[1] = {0};
+
+	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
+
+	rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
+}
+EXPORT_SYMBOL(rtl92c_set_fw_joinbss_report_cmd);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C__FW__H__
+#define __RTL92C__FW__H__
+
+#define FW_8192C_SIZE				0x3000
+#define FW_8192C_START_ADDRESS			0x1000
+#define FW_8192C_END_ADDRESS			0x3FFF
+#define FW_8192C_PAGE_SIZE			4096
+#define FW_8192C_POLLING_DELAY			5
+#define FW_8192C_POLLING_TIMEOUT_COUNT		100
+
+#define IS_FW_HEADER_EXIST(_pfwhdr)	\
+	((_pfwhdr->signature&0xFFF0) == 0x92C0 ||\
+	(_pfwhdr->signature&0xFFF0) == 0x88C0)
+
+struct rtl92c_firmware_header {
+	u16 signature;
+	u8 category;
+	u8 function;
+	u16 version;
+	u8 subversion;
+	u8 rsvd1;
+	u8 month;
+	u8 date;
+	u8 hour;
+	u8 minute;
+	u16 ramcodeSize;
+	u16 rsvd2;
+	u32 svnindex;
+	u32 rsvd3;
+	u32 rsvd4;
+	u32 rsvd5;
+};
+
+enum rtl8192c_h2c_cmd {
+	H2C_AP_OFFLOAD = 0,
+	H2C_SETPWRMODE = 1,
+	H2C_JOINBSSRPT = 2,
+	H2C_RSVDPAGE = 3,
+	H2C_RSSI_REPORT = 5,
+	H2C_RA_MASK = 6,
+	MAX_H2CCMD
+};
+
+#define pagenum_128(_len)	(u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0))
+
+#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)			\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
+#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)		\
+	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
+
+int rtl92c_download_fw(struct ieee80211_hw *hw);
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
+			 u32 cmd_len, u8 *p_cmdbuffer);
+void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/main.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,39 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+
+
+MODULE_AUTHOR("lizhaoming	<chaoming_li@realsil.com.cn>");
+MODULE_AUTHOR("Realtek WlanFAE	<wlanfae@realtek.com>");
+MODULE_AUTHOR("Georgia		<georgia@realtek.com>");
+MODULE_AUTHOR("Ziv Huang	<ziv_huang@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n PCI wireless");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,9 @@
+rtl8192c-common-objs :=		\
+		main.o		\
+		dm_common.o	\
+		fw_common.o	\
+		phy_common.o
+
+obj-$(CONFIG_RTL8192C_COMMON) += rtl8192c-common.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2042 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../rtl8192ce/reg.h"
+#include "../rtl8192ce/def.h"
+#include "dm_common.h"
+#include "phy_common.h"
+
+/* Define macro to shorten lines */
+#define MCS_TXPWR	mcs_txpwrlevel_origoffset
+
+u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 returnvalue, originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+					       "bitmask(%#x)\n", regaddr,
+					       bitmask));
+	originalvalue = rtl_read_dword(rtlpriv, regaddr);
+	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+	returnvalue = (originalvalue & bitmask) >> bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
+					       "Addr[0x%x]=0x%x\n", bitmask,
+					       regaddr, originalvalue));
+
+	return returnvalue;
+
+}
+EXPORT_SYMBOL(rtl92c_phy_query_bb_reg);
+
+void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
+			   u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 originalvalue, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+					       " data(%#x)\n", regaddr, bitmask,
+					       data));
+
+	if (bitmask != MASKDWORD) {
+		originalvalue = rtl_read_dword(rtlpriv, regaddr);
+		bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+		data = ((originalvalue & (~bitmask)) | (data << bitshift));
+	}
+
+	rtl_write_dword(rtlpriv, regaddr, data);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
+					       " data(%#x)\n", regaddr, bitmask,
+					       data));
+}
+EXPORT_SYMBOL(rtl92c_phy_set_bb_reg);
+
+u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+					 enum radio_path rfpath, u32 offset)
+{
+	RT_ASSERT(false, ("deprecated!\n"));
+	return 0;
+}
+EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_read);
+
+void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+					   enum radio_path rfpath, u32 offset,
+					   u32 data)
+{
+	RT_ASSERT(false, ("deprecated!\n"));
+}
+EXPORT_SYMBOL(_rtl92c_phy_fw_rf_serial_write);
+
+u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
+				      enum radio_path rfpath, u32 offset)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+	u32 newoffset;
+	u32 tmplong, tmplong2;
+	u8 rfpi_enable = 0;
+	u32 retvalue;
+
+	offset &= 0x3f;
+	newoffset = offset;
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("return all one\n"));
+		return 0xFFFFFFFF;
+	}
+	tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD);
+	if (rfpath == RF90_PATH_A)
+		tmplong2 = tmplong;
+	else
+		tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD);
+	tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
+	    (newoffset << 23) | BLSSIREADEDGE;
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+		      tmplong & (~BLSSIREADEDGE));
+	mdelay(1);
+	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2);
+	mdelay(1);
+	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
+		      tmplong | BLSSIREADEDGE);
+	mdelay(1);
+	if (rfpath == RF90_PATH_A)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
+						 BIT(8));
+	else if (rfpath == RF90_PATH_B)
+		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
+						 BIT(8));
+	if (rfpi_enable)
+		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
+					 BLSSIREADBACKDATA);
+	else
+		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
+					 BLSSIREADBACKDATA);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n",
+					       rfpath, pphyreg->rflssi_readback,
+					       retvalue));
+	return retvalue;
+}
+EXPORT_SYMBOL(_rtl92c_phy_rf_serial_read);
+
+void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
+					enum radio_path rfpath, u32 offset,
+					u32 data)
+{
+	u32 data_and_addr;
+	u32 newoffset;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
+
+	if (RT_CANNOT_IO(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("stop\n"));
+		return;
+	}
+	offset &= 0x3f;
+	newoffset = offset;
+	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
+	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
+					       rfpath, pphyreg->rf3wire_offset,
+					       data_and_addr));
+}
+EXPORT_SYMBOL(_rtl92c_phy_rf_serial_write);
+
+u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask)
+{
+	u32 i;
+
+	for (i = 0; i <= 31; i++) {
+		if (((bitmask >> i) & 0x1) == 1)
+			break;
+	}
+	return i;
+}
+EXPORT_SYMBOL(_rtl92c_phy_calculate_bit_shift);
+
+static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
+	rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
+	rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
+	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
+	rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
+	rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
+	rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
+}
+bool rtl92c_phy_rf_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtlpriv->cfg->ops->phy_rf6052_config(hw);
+}
+EXPORT_SYMBOL(rtl92c_phy_rf_config);
+
+bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	bool rtstatus;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
+	rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw,
+						 BASEBAND_CONFIG_PHY_REG);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
+		return false;
+	}
+	if (rtlphy->rf_type == RF_1T2R) {
+		_rtl92c_phy_bb_config_1t(hw);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
+	}
+	if (rtlefuse->autoload_failflag == false) {
+		rtlphy->pwrgroup_cnt = 0;
+		rtstatus = rtlpriv->cfg->ops->config_bb_with_pgheaderfile(hw,
+						   BASEBAND_CONFIG_PHY_REG);
+	}
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
+		return false;
+	}
+	rtstatus = rtlpriv->cfg->ops->config_bb_with_headerfile(hw,
+						 BASEBAND_CONFIG_AGC_TAB);
+	if (rtstatus != true) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
+		return false;
+	}
+	rtlphy->cck_high_power = (bool) (rtl_get_bbreg(hw,
+						RFPGA0_XA_HSSIPARAMETER2,
+						0x200));
+	return true;
+}
+EXPORT_SYMBOL(_rtl92c_phy_bb8192c_config_parafile);
+
+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (regaddr == RTXAGC_A_RATE18_06) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][0] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][0]));
+	}
+	if (regaddr == RTXAGC_A_RATE54_24) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][1] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][1]));
+	}
+	if (regaddr == RTXAGC_A_CCK1_MCS32) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][6] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][6]));
+	}
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][7] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][7]));
+	}
+	if (regaddr == RTXAGC_A_MCS03_MCS00) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][2] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][2]));
+	}
+	if (regaddr == RTXAGC_A_MCS07_MCS04) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][3] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][3]));
+	}
+	if (regaddr == RTXAGC_A_MCS11_MCS08) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][4] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][4]));
+	}
+	if (regaddr == RTXAGC_A_MCS15_MCS12) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][5] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][5]));
+	}
+	if (regaddr == RTXAGC_B_RATE18_06) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][8] = data;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][8]));
+	}
+	if (regaddr == RTXAGC_B_RATE54_24) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][9]));
+	}
+
+	if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][14]));
+	}
+
+	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][15]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS03_MCS00) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][10]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS07_MCS04) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][11]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS11_MCS08) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][12]));
+	}
+
+	if (regaddr == RTXAGC_B_MCS15_MCS12) {
+		rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13] = data;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
+			  rtlphy->pwrgroup_cnt,
+			  rtlphy->MCS_TXPWR[rtlphy->pwrgroup_cnt][13]));
+
+		rtlphy->pwrgroup_cnt++;
+	}
+}
+EXPORT_SYMBOL(_rtl92c_store_pwrIndex_diffrate_offset);
+
+void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->default_initialgain[0] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[1] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[2] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
+	rtlphy->default_initialgain[3] =
+	    (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Default initial gain (c50=0x%x, "
+		  "c58=0x%x, c60=0x%x, c68=0x%x\n",
+		  rtlphy->default_initialgain[0],
+		  rtlphy->default_initialgain[1],
+		  rtlphy->default_initialgain[2],
+		  rtlphy->default_initialgain[3]));
+
+	rtlphy->framesync = (u8) rtl_get_bbreg(hw,
+					       ROFDM0_RXDETECTOR3, MASKBYTE0);
+	rtlphy->framesync_c34 = rtl_get_bbreg(hw,
+					      ROFDM0_RXDETECTOR2, MASKDWORD);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Default framesync (0x%x) = 0x%x\n",
+		  ROFDM0_RXDETECTOR3, rtlphy->framesync));
+}
+
+void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+	rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
+	    RFPGA0_XA_LSSIPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
+	    RFPGA0_XB_LSSIPARAMETER;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
+	    RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
+	    RFPGA0_XAB_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
+	    RFPGA0_XCD_SWITCHCONTROL;
+	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
+	    RFPGA0_XCD_SWITCHCONTROL;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
+	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
+	    ROFDM0_XARXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
+	    ROFDM0_XBRXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
+	    ROFDM0_XCRXIQIMBANLANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
+	    ROFDM0_XDRXIQIMBALANCE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
+	    ROFDM0_XATXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
+	    ROFDM0_XBTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
+	    ROFDM0_XCTXIQIMBALANCE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
+	    ROFDM0_XDTXIQIMBALANCE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
+	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
+	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
+	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
+	    RFPGA0_XA_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
+	    RFPGA0_XB_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
+	    RFPGA0_XC_LSSIREADBACK;
+	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
+	    RFPGA0_XD_LSSIREADBACK;
+
+	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
+	    TRANSCEIVEA_HSPI_READBACK;
+	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
+	    TRANSCEIVEB_HSPI_READBACK;
+
+}
+EXPORT_SYMBOL(_rtl92c_phy_init_bb_rf_register_definition);
+
+void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 txpwr_level;
+	long txpwr_dbm;
+
+	txpwr_level = rtlphy->cur_cck_txpwridx;
+	txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw,
+						 WIRELESS_MODE_B, txpwr_level);
+	txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
+	    rtlefuse->legacy_ht_txpowerdiff;
+	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
+					 WIRELESS_MODE_G,
+					 txpwr_level) > txpwr_dbm)
+		txpwr_dbm =
+		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
+						 txpwr_level);
+	txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
+	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
+					 WIRELESS_MODE_N_24G,
+					 txpwr_level) > txpwr_dbm)
+		txpwr_dbm =
+		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
+						 txpwr_level);
+	*powerlevel = txpwr_dbm;
+}
+
+static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
+				      u8 *cckpowerlevel, u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 index = (channel - 1);
+
+	cckpowerlevel[RF90_PATH_A] =
+	    rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
+	cckpowerlevel[RF90_PATH_B] =
+	    rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
+	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
+	} else if (get_rf_type(rtlphy) == RF_2T2R) {
+		ofdmpowerlevel[RF90_PATH_A] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
+		ofdmpowerlevel[RF90_PATH_B] =
+		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
+	}
+}
+
+static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw,
+					 u8 channel, u8 *cckpowerlevel,
+					 u8 *ofdmpowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
+	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
+}
+
+void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
+	u8 cckpowerlevel[2], ofdmpowerlevel[2];
+
+	if (rtlefuse->txpwr_fromeprom == false)
+		return;
+	_rtl92c_get_txpower_index(hw, channel,
+				  &cckpowerlevel[0], &ofdmpowerlevel[0]);
+	_rtl92c_ccxpower_index_check(hw,
+				     channel, &cckpowerlevel[0],
+				     &ofdmpowerlevel[0]);
+	rtlpriv->cfg->ops->phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
+	rtlpriv->cfg->ops->phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0],
+						       channel);
+}
+EXPORT_SYMBOL(rtl92c_phy_set_txpower_level);
+
+bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 idx;
+	u8 rf_path;
+
+	u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
+						      WIRELESS_MODE_B,
+						      power_indbm);
+	u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
+						       WIRELESS_MODE_N_24G,
+						       power_indbm);
+	if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
+		ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
+	else
+		ofdmtxpwridx = 0;
+	RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
+		 ("%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
+		  power_indbm, ccktxpwridx, ofdmtxpwridx));
+	for (idx = 0; idx < 14; idx++) {
+		for (rf_path = 0; rf_path < 2; rf_path++) {
+			rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
+			rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
+			    ofdmtxpwridx;
+			rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
+			    ofdmtxpwridx;
+		}
+	}
+	rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+	return true;
+}
+EXPORT_SYMBOL(rtl92c_phy_update_txpower_dbm);
+
+void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval)
+{
+}
+EXPORT_SYMBOL(rtl92c_phy_set_beacon_hw_reg);
+
+u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+				enum wireless_mode wirelessmode,
+				long power_indbm)
+{
+	u8 txpwridx;
+	long offset;
+
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+
+	if ((power_indbm - offset) > 0)
+		txpwridx = (u8) ((power_indbm - offset) * 2);
+	else
+		txpwridx = 0;
+
+	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
+		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
+
+	return txpwridx;
+}
+EXPORT_SYMBOL(_rtl92c_phy_dbm_to_txpwr_Idx);
+
+long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+				  enum wireless_mode wirelessmode,
+				  u8 txpwridx)
+{
+	long offset;
+	long pwrout_dbm;
+
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		offset = -7;
+		break;
+	case WIRELESS_MODE_G:
+	case WIRELESS_MODE_N_24G:
+		offset = -8;
+		break;
+	default:
+		offset = -8;
+		break;
+	}
+	pwrout_dbm = txpwridx / 2 + offset;
+	return pwrout_dbm;
+}
+EXPORT_SYMBOL(_rtl92c_phy_txpwr_idx_to_dbm);
+
+void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	enum io_type iotype;
+
+	if (!is_hal_stop(rtlhal)) {
+		switch (operation) {
+		case SCAN_OPT_BACKUP:
+			iotype = IO_CMD_PAUSE_DM_BY_SCAN;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_IO_CMD,
+						      (u8 *)&iotype);
+
+			break;
+		case SCAN_OPT_RESTORE:
+			iotype = IO_CMD_RESUME_DM_BY_SCAN;
+			rtlpriv->cfg->ops->set_hw_reg(hw,
+						      HW_VAR_IO_CMD,
+						      (u8 *)&iotype);
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Unknown Scan Backup operation.\n"));
+			break;
+		}
+	}
+}
+EXPORT_SYMBOL(rtl92c_phy_scan_operation_backup);
+
+void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
+			    enum nl80211_channel_type ch_type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_bw = rtlphy->current_chan_bw;
+
+	if (rtlphy->set_bwmode_inprogress)
+		return;
+	rtlphy->set_bwmode_inprogress = true;
+	if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw)))
+		rtlpriv->cfg->ops->phy_set_bw_mode_callback(hw);
+	else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("FALSE driver sleep or unload\n"));
+		rtlphy->set_bwmode_inprogress = false;
+		rtlphy->current_chan_bw = tmp_bw;
+	}
+}
+EXPORT_SYMBOL(rtl92c_phy_set_bw_mode);
+
+void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 delay;
+
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 ("switch to channel%d\n", rtlphy->current_channel));
+	if (is_hal_stop(rtlhal))
+		return;
+	do {
+		if (!rtlphy->sw_chnl_inprogress)
+			break;
+		if (!_rtl92c_phy_sw_chnl_step_by_step
+		    (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
+		     &rtlphy->sw_chnl_step, &delay)) {
+			if (delay > 0)
+				mdelay(delay);
+			else
+				continue;
+		} else
+			rtlphy->sw_chnl_inprogress = false;
+		break;
+	} while (true);
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+EXPORT_SYMBOL(rtl92c_phy_sw_chnl_callback);
+
+u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlphy->sw_chnl_inprogress)
+		return 0;
+	if (rtlphy->set_bwmode_inprogress)
+		return 0;
+	RT_ASSERT((rtlphy->current_channel <= 14),
+		  ("WIRELESS_MODE_G but channel>14"));
+	rtlphy->sw_chnl_inprogress = true;
+	rtlphy->sw_chnl_stage = 0;
+	rtlphy->sw_chnl_step = 0;
+	if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
+		rtl92c_phy_sw_chnl_callback(hw);
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 ("sw_chnl_inprogress false schdule workitem\n"));
+		rtlphy->sw_chnl_inprogress = false;
+	} else {
+		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
+			 ("sw_chnl_inprogress false driver sleep or"
+			  " unload\n"));
+		rtlphy->sw_chnl_inprogress = false;
+	}
+	return 1;
+}
+EXPORT_SYMBOL(rtl92c_phy_sw_chnl);
+
+static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+					     u8 channel, u8 *stage, u8 *step,
+					     u32 *delay)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
+	u32 precommoncmdcnt;
+	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
+	u32 postcommoncmdcnt;
+	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
+	u32 rfdependcmdcnt;
+	struct swchnlcmd *currentcmd = NULL;
+	u8 rfpath;
+	u8 num_total_rfpath = rtlphy->num_total_rfpath;
+
+	precommoncmdcnt = 0;
+	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					 MAX_PRECMD_CNT,
+					 CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
+	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
+					 MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
+
+	postcommoncmdcnt = 0;
+
+	_rtl92c_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
+					 MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
+
+	rfdependcmdcnt = 0;
+
+	RT_ASSERT((channel >= 1 && channel <= 14),
+		  ("illegal channel for Zebra: %d\n", channel));
+
+	_rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+					 MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
+					 RF_CHNLBW, channel, 10);
+
+	_rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
+					 MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0,
+					 0);
+
+	do {
+		switch (*stage) {
+		case 0:
+			currentcmd = &precommoncmd[*step];
+			break;
+		case 1:
+			currentcmd = &rfdependcmd[*step];
+			break;
+		case 2:
+			currentcmd = &postcommoncmd[*step];
+			break;
+		}
+
+		if (currentcmd->cmdid == CMDID_END) {
+			if ((*stage) == 2) {
+				return true;
+			} else {
+				(*stage)++;
+				(*step) = 0;
+				continue;
+			}
+		}
+
+		switch (currentcmd->cmdid) {
+		case CMDID_SET_TXPOWEROWER_LEVEL:
+			rtl92c_phy_set_txpower_level(hw, channel);
+			break;
+		case CMDID_WRITEPORT_ULONG:
+			rtl_write_dword(rtlpriv, currentcmd->para1,
+					currentcmd->para2);
+			break;
+		case CMDID_WRITEPORT_USHORT:
+			rtl_write_word(rtlpriv, currentcmd->para1,
+				       (u16) currentcmd->para2);
+			break;
+		case CMDID_WRITEPORT_UCHAR:
+			rtl_write_byte(rtlpriv, currentcmd->para1,
+				       (u8) currentcmd->para2);
+			break;
+		case CMDID_RF_WRITEREG:
+			for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
+				rtlphy->rfreg_chnlval[rfpath] =
+				    ((rtlphy->rfreg_chnlval[rfpath] &
+				      0xfffffc00) | currentcmd->para2);
+
+				rtl_set_rfreg(hw, (enum radio_path)rfpath,
+					      currentcmd->para1,
+					      RFREG_OFFSET_MASK,
+					      rtlphy->rfreg_chnlval[rfpath]);
+			}
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+
+		break;
+	} while (true);
+
+	(*delay) = currentcmd->msdelay;
+	(*step)++;
+	return false;
+}
+
+static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+					     u32 cmdtableidx, u32 cmdtablesz,
+					     enum swchnlcmd_id cmdid,
+					     u32 para1, u32 para2, u32 msdelay)
+{
+	struct swchnlcmd *pcmd;
+
+	if (cmdtable == NULL) {
+		RT_ASSERT(false, ("cmdtable cannot be NULL.\n"));
+		return false;
+	}
+
+	if (cmdtableidx >= cmdtablesz)
+		return false;
+
+	pcmd = cmdtable + cmdtableidx;
+	pcmd->cmdid = cmdid;
+	pcmd->para1 = para1;
+	pcmd->para2 = para2;
+	pcmd->msdelay = msdelay;
+	return true;
+}
+
+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath)
+{
+	return true;
+}
+EXPORT_SYMBOL(rtl8192_phy_check_is_legal_rfpath);
+
+static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
+{
+	u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
+	rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
+	rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
+	rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
+		      config_pathb ? 0x28160202 : 0x28160502);
+
+	if (config_pathb) {
+		rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
+		rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
+		rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
+	}
+
+	rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
+	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
+	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
+
+	mdelay(IQK_DELAY_TIME);
+
+	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+	reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
+	reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
+	reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
+
+	if (!(reg_eac & BIT(28)) &&
+	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+
+	if (!(reg_eac & BIT(27)) &&
+	    (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_eac & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw)
+{
+	u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
+	u8 result = 0x00;
+
+	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
+	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
+	mdelay(IQK_DELAY_TIME);
+	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
+	reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
+	reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
+	reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
+	reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
+	if (!(reg_eac & BIT(31)) &&
+	    (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
+	    (((reg_ebc & 0x03FF0000) >> 16) != 0x42))
+		result |= 0x01;
+	else
+		return result;
+
+	if (!(reg_eac & BIT(30)) &&
+	    (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
+	    (((reg_ecc & 0x03FF0000) >> 16) != 0x36))
+		result |= 0x02;
+	return result;
+}
+
+static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw,
+					       bool iqk_ok, long result[][8],
+					       u8 final_candidate, bool btxonly)
+{
+	u32 oldval_0, x, tx0_a, reg;
+	long y, tx0_c;
+
+	if (final_candidate == 0xFF)
+		return;
+	else if (iqk_ok) {
+		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
+					  MASKDWORD) >> 22) & 0x3FF;
+		x = result[final_candidate][0];
+		if ((x & 0x00000200) != 0)
+			x = x | 0xFFFFFC00;
+		tx0_a = (x * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31),
+			      ((x * oldval_0 >> 7) & 0x1));
+		y = result[final_candidate][1];
+		if ((y & 0x00000200) != 0)
+			y = y | 0xFFFFFC00;
+		tx0_c = (y * oldval_0) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
+			      ((tx0_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
+			      (tx0_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29),
+			      ((y * oldval_0 >> 7) & 0x1));
+		if (btxonly)
+			return;
+		reg = result[final_candidate][2];
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][3] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][3] >> 6) & 0xF;
+		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
+	}
+}
+
+static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw,
+					       bool iqk_ok, long result[][8],
+					       u8 final_candidate, bool btxonly)
+{
+	u32 oldval_1, x, tx1_a, reg;
+	long y, tx1_c;
+
+	if (final_candidate == 0xFF)
+		return;
+	else if (iqk_ok) {
+		oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
+					  MASKDWORD) >> 22) & 0x3FF;
+		x = result[final_candidate][4];
+		if ((x & 0x00000200) != 0)
+			x = x | 0xFFFFFC00;
+		tx1_a = (x * oldval_1) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a);
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27),
+			      ((x * oldval_1 >> 7) & 0x1));
+		y = result[final_candidate][5];
+		if ((y & 0x00000200) != 0)
+			y = y | 0xFFFFFC00;
+		tx1_c = (y * oldval_1) >> 8;
+		rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000,
+			      ((tx1_c & 0x3C0) >> 6));
+		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000,
+			      (tx1_c & 0x3F));
+		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25),
+			      ((y * oldval_1 >> 7) & 0x1));
+		if (btxonly)
+			return;
+		reg = result[final_candidate][6];
+		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
+		reg = result[final_candidate][7] & 0x3F;
+		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
+		reg = (result[final_candidate][7] >> 6) & 0xF;
+		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
+	}
+}
+
+static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw,
+					    u32 *addareg, u32 *addabackup,
+					    u32 registernum)
+{
+	u32 i;
+
+	for (i = 0; i < registernum; i++)
+		addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
+}
+
+static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw,
+					   u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
+	macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
+}
+
+static void _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw,
+					      u32 *addareg, u32 *addabackup,
+					      u32 regiesternum)
+{
+	u32 i;
+
+	for (i = 0; i < regiesternum; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]);
+}
+
+static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw,
+					     u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
+	rtl_write_dword(rtlpriv, macreg[i], macbackup[i]);
+}
+
+static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw,
+				     u32 *addareg, bool is_patha_on, bool is2t)
+{
+	u32 pathOn;
+	u32 i;
+
+	pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
+	if (false == is2t) {
+		pathOn = 0x0bdb25a0;
+		rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
+	} else {
+		rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn);
+	}
+
+	for (i = 1; i < IQK_ADDA_REG_NUM; i++)
+		rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn);
+}
+
+static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw,
+						u32 *macreg, u32 *macbackup)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 i;
+
+	rtl_write_byte(rtlpriv, macreg[0], 0x3F);
+
+	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
+		rtl_write_byte(rtlpriv, macreg[i],
+			       (u8) (macbackup[i] & (~BIT(3))));
+	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
+}
+
+static void _rtl92c_phy_path_a_standby(struct ieee80211_hw *hw)
+{
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0);
+	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+}
+
+static void _rtl92c_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode)
+{
+	u32 mode;
+
+	mode = pi_mode ? 0x01000100 : 0x01000000;
+	rtl_set_bbreg(hw, 0x820, MASKDWORD, mode);
+	rtl_set_bbreg(hw, 0x828, MASKDWORD, mode);
+}
+
+static bool _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw,
+					   long result[][8], u8 c1, u8 c2)
+{
+	u32 i, j, diff, simularity_bitmap, bound;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	u8 final_candidate[2] = { 0xFF, 0xFF };
+	bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version);
+
+	if (is2t)
+		bound = 8;
+	else
+		bound = 4;
+
+	simularity_bitmap = 0;
+
+	for (i = 0; i < bound; i++) {
+		diff = (result[c1][i] > result[c2][i]) ?
+		    (result[c1][i] - result[c2][i]) :
+		    (result[c2][i] - result[c1][i]);
+
+		if (diff > MAX_TOLERANCE) {
+			if ((i == 2 || i == 6) && !simularity_bitmap) {
+				if (result[c1][i] + result[c1][i + 1] == 0)
+					final_candidate[(i / 4)] = c2;
+				else if (result[c2][i] + result[c2][i + 1] == 0)
+					final_candidate[(i / 4)] = c1;
+				else
+					simularity_bitmap = simularity_bitmap |
+					    (1 << i);
+			} else
+				simularity_bitmap =
+				    simularity_bitmap | (1 << i);
+		}
+	}
+
+	if (simularity_bitmap == 0) {
+		for (i = 0; i < (bound / 4); i++) {
+			if (final_candidate[i] != 0xFF) {
+				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
+					result[3][j] =
+					    result[final_candidate[i]][j];
+				bresult = false;
+			}
+		}
+		return bresult;
+	} else if (!(simularity_bitmap & 0x0F)) {
+		for (i = 0; i < 4; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else if (!(simularity_bitmap & 0xF0) && is2t) {
+		for (i = 4; i < 8; i++)
+			result[3][i] = result[c1][i];
+		return false;
+	} else {
+		return false;
+	}
+
+}
+
+static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
+				     long result[][8], u8 t, bool is2t)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 i;
+	u8 patha_ok, pathb_ok;
+	u32 adda_reg[IQK_ADDA_REG_NUM] = {
+		0x85c, 0xe6c, 0xe70, 0xe74,
+		0xe78, 0xe7c, 0xe80, 0xe84,
+		0xe88, 0xe8c, 0xed0, 0xed4,
+		0xed8, 0xedc, 0xee0, 0xeec
+	};
+
+	u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+
+	const u32 retrycount = 2;
+
+	u32 bbvalue;
+
+	if (t == 0) {
+		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
+
+		_rtl92c_phy_save_adda_registers(hw, adda_reg,
+						rtlphy->adda_backup, 16);
+		_rtl92c_phy_save_mac_registers(hw, iqk_mac_reg,
+					       rtlphy->iqk_mac_backup);
+	}
+	_rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t);
+	if (t == 0) {
+		rtlphy->rfpi_enable = (u8) rtl_get_bbreg(hw,
+						   RFPGA0_XA_HSSIPARAMETER1,
+						   BIT(8));
+	}
+	if (!rtlphy->rfpi_enable)
+		_rtl92c_phy_pi_mode_switch(hw, true);
+	if (t == 0) {
+		rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
+		rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
+		rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
+	}
+	rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
+	if (is2t) {
+		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
+	}
+	_rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg,
+					    rtlphy->iqk_mac_backup);
+	rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
+	if (is2t)
+		rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
+	rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
+	rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
+	for (i = 0; i < retrycount; i++) {
+		patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t);
+		if (patha_ok == 0x03) {
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
+					0x3FF0000) >> 16;
+			result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
+					0x3FF0000) >> 16;
+			break;
+		} else if (i == (retrycount - 1) && patha_ok == 0x01)
+			result[t][0] = (rtl_get_bbreg(hw, 0xe94,
+						      MASKDWORD) & 0x3FF0000) >>
+						      16;
+		result[t][1] =
+		    (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
+
+	}
+
+	if (is2t) {
+		_rtl92c_phy_path_a_standby(hw);
+		_rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t);
+		for (i = 0; i < retrycount; i++) {
+			pathb_ok = _rtl92c_phy_path_b_iqk(hw);
+			if (pathb_ok == 0x03) {
+				result[t][4] = (rtl_get_bbreg(hw,
+						      0xeb4,
+						      MASKDWORD) &
+						0x3FF0000) >> 16;
+				result[t][5] =
+				    (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				result[t][6] =
+				    (rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				result[t][7] =
+				    (rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
+				     0x3FF0000) >> 16;
+				break;
+			} else if (i == (retrycount - 1) && pathb_ok == 0x01) {
+				result[t][4] = (rtl_get_bbreg(hw,
+						      0xeb4,
+						      MASKDWORD) &
+						0x3FF0000) >> 16;
+			}
+			result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
+					0x3FF0000) >> 16;
+		}
+	}
+	rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04);
+	rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
+	rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
+	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
+	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
+	if (is2t)
+		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
+	if (t != 0) {
+		if (!rtlphy->rfpi_enable)
+			_rtl92c_phy_pi_mode_switch(hw, false);
+		_rtl92c_phy_reload_adda_registers(hw, adda_reg,
+						  rtlphy->adda_backup, 16);
+		_rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg,
+						 rtlphy->iqk_mac_backup);
+	}
+}
+
+static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw,
+				     char delta, bool is2t)
+{
+	/* This routine is deliberately dummied out for later fixes */
+#if 0
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+
+	u32 reg_d[PATH_NUM];
+	u32 tmpreg, index, offset, path, i, pathbound = PATH_NUM, apkbound;
+
+	u32 bb_backup[APK_BB_REG_NUM];
+	u32 bb_reg[APK_BB_REG_NUM] = {
+		0x904, 0xc04, 0x800, 0xc08, 0x874
+	};
+	u32 bb_ap_mode[APK_BB_REG_NUM] = {
+		0x00000020, 0x00a05430, 0x02040000,
+		0x000800e4, 0x00204000
+	};
+	u32 bb_normal_ap_mode[APK_BB_REG_NUM] = {
+		0x00000020, 0x00a05430, 0x02040000,
+		0x000800e4, 0x22204000
+	};
+
+	u32 afe_backup[APK_AFE_REG_NUM];
+	u32 afe_reg[APK_AFE_REG_NUM] = {
+		0x85c, 0xe6c, 0xe70, 0xe74, 0xe78,
+		0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
+		0xed0, 0xed4, 0xed8, 0xedc, 0xee0,
+		0xeec
+	};
+
+	u32 mac_backup[IQK_MAC_REG_NUM];
+	u32 mac_reg[IQK_MAC_REG_NUM] = {
+		0x522, 0x550, 0x551, 0x040
+	};
+
+	u32 apk_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
+		{0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
+	};
+
+	u32 apk_normal_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c},
+		{0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
+	};
+
+	u32 apk_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
+		{0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
+	};
+
+	u32 apk_normal_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
+		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a},
+		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
+	};
+
+	u32 afe_on_off[PATH_NUM] = {
+		0x04db25a4, 0x0b1b25a4
+	};
+
+	u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c };
+
+	u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 };
+
+	u32 apk_value[PATH_NUM] = { 0x92fc0000, 0x12fc0000 };
+
+	u32 apk_normal_value[PATH_NUM] = { 0x92680000, 0x12680000 };
+
+	const char apk_delta_mapping[APK_BB_REG_NUM][13] = {
+		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
+		{-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
+	};
+
+	const u32 apk_normal_setting_value_1[13] = {
+		0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
+		0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
+		0x12680000, 0x00880000, 0x00880000
+	};
+
+	const u32 apk_normal_setting_value_2[16] = {
+		0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
+		0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
+		0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
+		0x00050006
+	};
+
+	const u32 apk_result[PATH_NUM][APK_BB_REG_NUM];
+
+	long bb_offset, delta_v, delta_offset;
+
+	if (!is2t)
+		pathbound = 1;
+
+	for (index = 0; index < PATH_NUM; index++) {
+		apk_offset[index] = apk_normal_offset[index];
+		apk_value[index] = apk_normal_value[index];
+		afe_on_off[index] = 0x6fdb25a4;
+	}
+
+	for (index = 0; index < APK_BB_REG_NUM; index++) {
+		for (path = 0; path < pathbound; path++) {
+			apk_rf_init_value[path][index] =
+			    apk_normal_rf_init_value[path][index];
+			apk_rf_value_0[path][index] =
+			    apk_normal_rf_value_0[path][index];
+		}
+		bb_ap_mode[index] = bb_normal_ap_mode[index];
+
+		apkbound = 6;
+	}
+
+	for (index = 0; index < APK_BB_REG_NUM; index++) {
+		if (index == 0)
+			continue;
+		bb_backup[index] = rtl_get_bbreg(hw, bb_reg[index], MASKDWORD);
+	}
+
+	_rtl92c_phy_save_mac_registers(hw, mac_reg, mac_backup);
+
+	_rtl92c_phy_save_adda_registers(hw, afe_reg, afe_backup, 16);
+
+	for (path = 0; path < pathbound; path++) {
+		if (path == RF90_PATH_A) {
+			offset = 0xb00;
+			for (index = 0; index < 11; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+
+			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
+
+			offset = 0xb68;
+			for (; index < 13; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
+
+			offset = 0xb00;
+			for (index = 0; index < 16; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_2
+					      [index]);
+
+				offset += 0x04;
+			}
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
+		} else if (path == RF90_PATH_B) {
+			offset = 0xb70;
+			for (index = 0; index < 10; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+			rtl_set_bbreg(hw, 0xb28, MASKDWORD, 0x12680000);
+			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
+
+			offset = 0xb68;
+			index = 11;
+			for (; index < 13; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_1
+					      [index]);
+
+				offset += 0x04;
+			}
+
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
+
+			offset = 0xb60;
+			for (index = 0; index < 16; index++) {
+				rtl_set_bbreg(hw, offset, MASKDWORD,
+					      apk_normal_setting_value_2
+					      [index]);
+
+				offset += 0x04;
+			}
+			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
+		}
+
+		reg_d[path] = rtl_get_rfreg(hw, (enum radio_path)path,
+					    0xd, MASKDWORD);
+
+		for (index = 0; index < APK_AFE_REG_NUM; index++)
+			rtl_set_bbreg(hw, afe_reg[index], MASKDWORD,
+				      afe_on_off[path]);
+
+		if (path == RF90_PATH_A) {
+			for (index = 0; index < APK_BB_REG_NUM; index++) {
+				if (index == 0)
+					continue;
+				rtl_set_bbreg(hw, bb_reg[index], MASKDWORD,
+					      bb_ap_mode[index]);
+			}
+		}
+
+		_rtl92c_phy_mac_setting_calibration(hw, mac_reg, mac_backup);
+
+		if (path == 0) {
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x0, MASKDWORD, 0x10000);
+		} else {
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASKDWORD,
+				      0x10000);
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
+				      0x1000f);
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
+				      0x20103);
+		}
+
+		delta_offset = ((delta + 14) / 2);
+		if (delta_offset < 0)
+			delta_offset = 0;
+		else if (delta_offset > 12)
+			delta_offset = 12;
+
+		for (index = 0; index < APK_BB_REG_NUM; index++) {
+			if (index != 1)
+				continue;
+
+			tmpreg = apk_rf_init_value[path][index];
+
+			if (!rtlefuse->apk_thermalmeterignore) {
+				bb_offset = (tmpreg & 0xF0000) >> 16;
+
+				if (!(tmpreg & BIT(15)))
+					bb_offset = -bb_offset;
+
+				delta_v =
+				    apk_delta_mapping[index][delta_offset];
+
+				bb_offset += delta_v;
+
+				if (bb_offset < 0) {
+					tmpreg = tmpreg & (~BIT(15));
+					bb_offset = -bb_offset;
+				} else {
+					tmpreg = tmpreg | BIT(15);
+				}
+
+				tmpreg =
+				    (tmpreg & 0xFFF0FFFF) | (bb_offset << 16);
+			}
+
+			rtl_set_rfreg(hw, (enum radio_path)path, 0xc,
+				      MASKDWORD, 0x8992e);
+			rtl_set_rfreg(hw, (enum radio_path)path, 0x0,
+				      MASKDWORD, apk_rf_value_0[path][index]);
+			rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
+				      MASKDWORD, tmpreg);
+
+			i = 0;
+			do {
+				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80000000);
+				rtl_set_bbreg(hw, apk_offset[path],
+					      MASKDWORD, apk_value[0]);
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("PHY_APCalibrate() offset 0x%x "
+					 "value 0x%x\n",
+					 apk_offset[path],
+					 rtl_get_bbreg(hw, apk_offset[path],
+						       MASKDWORD)));
+
+				mdelay(3);
+
+				rtl_set_bbreg(hw, apk_offset[path],
+					      MASKDWORD, apk_value[1]);
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("PHY_APCalibrate() offset 0x%x "
+					 "value 0x%x\n",
+					 apk_offset[path],
+					 rtl_get_bbreg(hw, apk_offset[path],
+						       MASKDWORD)));
+
+				mdelay(20);
+
+				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
+
+				if (path == RF90_PATH_A)
+					tmpreg = rtl_get_bbreg(hw, 0xbd8,
+							       0x03E00000);
+				else
+					tmpreg = rtl_get_bbreg(hw, 0xbd8,
+							       0xF8000000);
+
+				RTPRINT(rtlpriv, FINIT, INIT_IQK,
+					("PHY_APCalibrate() offset "
+					 "0xbd8[25:21] %x\n", tmpreg));
+
+				i++;
+
+			} while (tmpreg > apkbound && i < 4);
+
+			apk_result[path][index] = tmpreg;
+		}
+	}
+
+	_rtl92c_phy_reload_mac_registers(hw, mac_reg, mac_backup);
+
+	for (index = 0; index < APK_BB_REG_NUM; index++) {
+		if (index == 0)
+			continue;
+		rtl_set_bbreg(hw, bb_reg[index], MASKDWORD, bb_backup[index]);
+	}
+
+	_rtl92c_phy_reload_adda_registers(hw, afe_reg, afe_backup, 16);
+
+	for (path = 0; path < pathbound; path++) {
+		rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
+			      MASKDWORD, reg_d[path]);
+
+		if (path == RF90_PATH_B) {
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
+				      0x1000f);
+			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
+				      0x20101);
+		}
+
+		if (apk_result[path][1] > 6)
+			apk_result[path][1] = 6;
+	}
+
+	for (path = 0; path < pathbound; path++) {
+		rtl_set_rfreg(hw, (enum radio_path)path, 0x3, MASKDWORD,
+			      ((apk_result[path][1] << 15) |
+			       (apk_result[path][1] << 10) |
+			       (apk_result[path][1] << 5) |
+			       apk_result[path][1]));
+
+		if (path == RF90_PATH_A)
+			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
+				      ((apk_result[path][1] << 15) |
+				       (apk_result[path][1] << 10) |
+				       (0x00 << 5) | 0x05));
+		else
+			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
+				      ((apk_result[path][1] << 15) |
+				       (apk_result[path][1] << 10) |
+				       (0x02 << 5) | 0x05));
+
+		rtl_set_rfreg(hw, (enum radio_path)path, 0xe, MASKDWORD,
+			      ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) |
+			       0x08));
+
+	}
+
+	rtlphy->apk_done = true;
+#endif
+}
+
+static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw,
+					  bool bmain, bool is2t)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (is_hal_stop(rtlhal)) {
+		rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
+		rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+	}
+	if (is2t) {
+		if (bmain)
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(5) | BIT(6), 0x1);
+		else
+			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
+				      BIT(5) | BIT(6), 0x2);
+	} else {
+		if (bmain)
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
+		else
+			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
+
+	}
+}
+
+#undef IQK_ADDA_REG_NUM
+#undef IQK_DELAY_TIME
+
+void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool recovery)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	long result[4][8];
+	u8 i, final_candidate;
+	bool patha_ok, pathb_ok;
+	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
+	    reg_ecc, reg_tmp = 0;
+	bool is12simular, is13simular, is23simular;
+	bool start_conttx = false, singletone = false;
+	u32 iqk_bb_reg[10] = {
+		ROFDM0_XARXIQIMBALANCE,
+		ROFDM0_XBRXIQIMBALANCE,
+		ROFDM0_ECCATHRESHOLD,
+		ROFDM0_AGCRSSITABLE,
+		ROFDM0_XATXIQIMBALANCE,
+		ROFDM0_XBTXIQIMBALANCE,
+		ROFDM0_XCTXIQIMBALANCE,
+		ROFDM0_XCTXAFE,
+		ROFDM0_XDTXAFE,
+		ROFDM0_RXIQEXTANTA
+	};
+
+	if (recovery) {
+		_rtl92c_phy_reload_adda_registers(hw,
+						  iqk_bb_reg,
+						  rtlphy->iqk_bb_backup, 10);
+		return;
+	}
+	if (start_conttx || singletone)
+		return;
+	for (i = 0; i < 8; i++) {
+		result[0][i] = 0;
+		result[1][i] = 0;
+		result[2][i] = 0;
+		result[3][i] = 0;
+	}
+	final_candidate = 0xff;
+	patha_ok = false;
+	pathb_ok = false;
+	is12simular = false;
+	is23simular = false;
+	is13simular = false;
+	for (i = 0; i < 3; i++) {
+		if (IS_92C_SERIAL(rtlhal->version))
+			_rtl92c_phy_iq_calibrate(hw, result, i, true);
+		else
+			_rtl92c_phy_iq_calibrate(hw, result, i, false);
+		if (i == 1) {
+			is12simular = _rtl92c_phy_simularity_compare(hw,
+								     result, 0,
+								     1);
+			if (is12simular) {
+				final_candidate = 0;
+				break;
+			}
+		}
+		if (i == 2) {
+			is13simular = _rtl92c_phy_simularity_compare(hw,
+								     result, 0,
+								     2);
+			if (is13simular) {
+				final_candidate = 0;
+				break;
+			}
+			is23simular = _rtl92c_phy_simularity_compare(hw,
+								     result, 1,
+								     2);
+			if (is23simular)
+				final_candidate = 1;
+			else {
+				for (i = 0; i < 8; i++)
+					reg_tmp += result[3][i];
+
+				if (reg_tmp != 0)
+					final_candidate = 3;
+				else
+					final_candidate = 0xFF;
+			}
+		}
+	}
+	for (i = 0; i < 4; i++) {
+		reg_e94 = result[i][0];
+		reg_e9c = result[i][1];
+		reg_ea4 = result[i][2];
+		reg_eac = result[i][3];
+		reg_eb4 = result[i][4];
+		reg_ebc = result[i][5];
+		reg_ec4 = result[i][6];
+		reg_ecc = result[i][7];
+	}
+	if (final_candidate != 0xff) {
+		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
+		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
+		reg_ea4 = result[final_candidate][2];
+		reg_eac = result[final_candidate][3];
+		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
+		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
+		reg_ec4 = result[final_candidate][6];
+		reg_ecc = result[final_candidate][7];
+		patha_ok = pathb_ok = true;
+	} else {
+		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
+		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
+	}
+	if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
+		_rtl92c_phy_path_a_fill_iqk_matrix(hw, patha_ok, result,
+						   final_candidate,
+						   (reg_ea4 == 0));
+	if (IS_92C_SERIAL(rtlhal->version)) {
+		if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */
+			_rtl92c_phy_path_b_fill_iqk_matrix(hw, pathb_ok,
+							   result,
+							   final_candidate,
+							   (reg_ec4 == 0));
+	}
+	_rtl92c_phy_save_adda_registers(hw, iqk_bb_reg,
+					rtlphy->iqk_bb_backup, 10);
+}
+EXPORT_SYMBOL(rtl92c_phy_iq_calibrate);
+
+void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool start_conttx = false, singletone = false;
+
+	if (start_conttx || singletone)
+		return;
+	if (IS_92C_SERIAL(rtlhal->version))
+		rtlpriv->cfg->ops->phy_lc_calibrate(hw, true);
+	else
+		rtlpriv->cfg->ops->phy_lc_calibrate(hw, false);
+}
+EXPORT_SYMBOL(rtl92c_phy_lc_calibrate);
+
+void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlphy->apk_done)
+		return;
+	if (IS_92C_SERIAL(rtlhal->version))
+		_rtl92c_phy_ap_calibrate(hw, delta, true);
+	else
+		_rtl92c_phy_ap_calibrate(hw, delta, false);
+}
+EXPORT_SYMBOL(rtl92c_phy_ap_calibrate);
+
+void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (IS_92C_SERIAL(rtlhal->version))
+		_rtl92c_phy_set_rfpath_switch(hw, bmain, true);
+	else
+		_rtl92c_phy_set_rfpath_switch(hw, bmain, false);
+}
+EXPORT_SYMBOL(rtl92c_phy_set_rfpath_switch);
+
+bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool postprocessing = false;
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("-->IO Cmd(%#x), set_io_inprogress(%d)\n",
+		  iotype, rtlphy->set_io_inprogress));
+	do {
+		switch (iotype) {
+		case IO_CMD_RESUME_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 ("[IO CMD] Resume DM after scan.\n"));
+			postprocessing = true;
+			break;
+		case IO_CMD_PAUSE_DM_BY_SCAN:
+			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+				 ("[IO CMD] Pause DM before scan.\n"));
+			postprocessing = true;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("switch case not process\n"));
+			break;
+		}
+	} while (false);
+	if (postprocessing && !rtlphy->set_io_inprogress) {
+		rtlphy->set_io_inprogress = true;
+		rtlphy->current_io_type = iotype;
+	} else {
+		return false;
+	}
+	rtl92c_phy_set_io(hw);
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
+	return true;
+}
+EXPORT_SYMBOL(rtl92c_phy_set_io_cmd);
+
+void rtl92c_phy_set_io(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("--->Cmd(%#x), set_io_inprogress(%d)\n",
+		  rtlphy->current_io_type, rtlphy->set_io_inprogress));
+	switch (rtlphy->current_io_type) {
+	case IO_CMD_RESUME_DM_BY_SCAN:
+		dm_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
+		rtl92c_dm_write_dig(hw);
+		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+		break;
+	case IO_CMD_PAUSE_DM_BY_SCAN:
+		rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
+		dm_digtable.cur_igvalue = 0x17;
+		rtl92c_dm_write_dig(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	rtlphy->set_io_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
+		 ("<---(%#x)\n", rtlphy->current_io_type));
+}
+EXPORT_SYMBOL(rtl92c_phy_set_io);
+
+void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+}
+EXPORT_SYMBOL(rtl92ce_phy_set_rf_on);
+
+void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw)
+{
+	u32 u4b_tmp;
+	u8 delay = 5;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+	u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+	while (u4b_tmp != 0 && delay > 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
+		u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
+		delay--;
+	}
+	if (delay == 0) {
+		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 ("Switch RF timeout !!!.\n"));
+		return;
+	}
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
+}
+EXPORT_SYMBOL(_rtl92c_phy_set_rf_sleep);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,246 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_PHY_H__
+#define __RTL92C_PHY_H__
+
+#define MAX_PRECMD_CNT			16
+#define MAX_RFDEPENDCMD_CNT		16
+#define MAX_POSTCMD_CNT			16
+
+#define MAX_DOZE_WAITING_TIMES_9x	64
+
+#define RT_CANNOT_IO(hw)		false
+#define HIGHPOWER_RADIOA_ARRAYLEN	22
+
+#define MAX_TOLERANCE			5
+#define	IQK_DELAY_TIME			1
+
+#define	APK_BB_REG_NUM			5
+#define	APK_AFE_REG_NUM			16
+#define	APK_CURVE_REG_NUM		4
+#define	PATH_NUM			2
+
+#define LOOP_LIMIT			5
+#define MAX_STALL_TIME			50
+#define AntennaDiversityValue		0x80
+#define MAX_TXPWR_IDX_NMODE_92S		63
+#define Reset_Cnt_Limit			3
+
+#define IQK_ADDA_REG_NUM		16
+#define IQK_MAC_REG_NUM			4
+
+#define RF90_PATH_MAX			2
+
+#define CT_OFFSET_MAC_ADDR		0X16
+
+#define CT_OFFSET_CCK_TX_PWR_IDX	0x5A
+#define CT_OFFSET_HT401S_TX_PWR_IDX	0x60
+#define CT_OFFSET_HT402S_TX_PWR_IDX_DIF	0x66
+#define CT_OFFSET_HT20_TX_PWR_IDX_DIFF	0x69
+#define CT_OFFSET_OFDM_TX_PWR_IDX_DIFF	0x6C
+
+#define CT_OFFSET_HT40_MAX_PWR_OFFSET	0x6F
+#define CT_OFFSET_HT20_MAX_PWR_OFFSET	0x72
+
+#define CT_OFFSET_CHANNEL_PLAH		0x75
+#define CT_OFFSET_THERMAL_METER		0x78
+#define CT_OFFSET_RF_OPTION		0x79
+#define CT_OFFSET_VERSION		0x7E
+#define CT_OFFSET_CUSTOMER_ID		0x7F
+
+#define RTL92C_MAX_PATH_NUM		2
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER	255
+enum swchnlcmd_id {
+	CMDID_END,
+	CMDID_SET_TXPOWEROWER_LEVEL,
+	CMDID_BBREGWRITE10,
+	CMDID_WRITEPORT_ULONG,
+	CMDID_WRITEPORT_USHORT,
+	CMDID_WRITEPORT_UCHAR,
+	CMDID_RF_WRITEREG,
+};
+
+struct swchnlcmd {
+	enum swchnlcmd_id cmdid;
+	u32 para1;
+	u32 para2;
+	u32 msdelay;
+};
+
+enum hw90_block_e {
+	HW90_BLOCK_MAC = 0,
+	HW90_BLOCK_PHY0 = 1,
+	HW90_BLOCK_PHY1 = 2,
+	HW90_BLOCK_RF = 3,
+	HW90_BLOCK_MAXIMUM = 4,
+};
+
+enum baseband_config_type {
+	BASEBAND_CONFIG_PHY_REG = 0,
+	BASEBAND_CONFIG_AGC_TAB = 1,
+};
+
+enum ra_offset_area {
+	RA_OFFSET_LEGACY_OFDM1,
+	RA_OFFSET_LEGACY_OFDM2,
+	RA_OFFSET_HT_OFDM1,
+	RA_OFFSET_HT_OFDM2,
+	RA_OFFSET_HT_OFDM3,
+	RA_OFFSET_HT_OFDM4,
+	RA_OFFSET_HT_CCK,
+};
+
+enum antenna_path {
+	ANTENNA_NONE,
+	ANTENNA_D,
+	ANTENNA_C,
+	ANTENNA_CD,
+	ANTENNA_B,
+	ANTENNA_BD,
+	ANTENNA_BC,
+	ANTENNA_BCD,
+	ANTENNA_A,
+	ANTENNA_AD,
+	ANTENNA_AC,
+	ANTENNA_ACD,
+	ANTENNA_AB,
+	ANTENNA_ABD,
+	ANTENNA_ABC,
+	ANTENNA_ABCD
+};
+
+struct r_antenna_select_ofdm {
+	u32 r_tx_antenna:4;
+	u32 r_ant_l:4;
+	u32 r_ant_non_ht:4;
+	u32 r_ant_ht1:4;
+	u32 r_ant_ht2:4;
+	u32 r_ant_ht_s1:4;
+	u32 r_ant_non_ht_s1:4;
+	u32 ofdm_txsc:2;
+	u32 reserved:2;
+};
+
+struct r_antenna_select_cck {
+	u8 r_cckrx_enable_2:2;
+	u8 r_cckrx_enable:2;
+	u8 r_ccktx_enable:4;
+};
+
+struct efuse_contents {
+	u8 mac_addr[ETH_ALEN];
+	u8 cck_tx_power_idx[6];
+	u8 ht40_1s_tx_power_idx[6];
+	u8 ht40_2s_tx_power_idx_diff[3];
+	u8 ht20_tx_power_idx_diff[3];
+	u8 ofdm_tx_power_idx_diff[3];
+	u8 ht40_max_power_offset[3];
+	u8 ht20_max_power_offset[3];
+	u8 channel_plan;
+	u8 thermal_meter;
+	u8 rf_option[5];
+	u8 version;
+	u8 oem_id;
+	u8 regulatory;
+};
+
+struct tx_power_struct {
+	u8 cck[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht40_1s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht40_2s[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 ht20_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 legacy_ht_diff[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 legacy_ht_txpowerdiff;
+	u8 groupht20[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 groupht40[RTL92C_MAX_PATH_NUM][CHANNEL_MAX_NUMBER];
+	u8 pwrgroup_cnt;
+	u32 mcs_original_offset[4][16];
+};
+
+extern u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw,
+				   u32 regaddr, u32 bitmask);
+extern void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
+				  u32 regaddr, u32 bitmask, u32 data);
+extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
+				   enum radio_path rfpath, u32 regaddr,
+				   u32 bitmask);
+extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
+				  enum radio_path rfpath, u32 regaddr,
+				  u32 bitmask, u32 data);
+extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw);
+extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
+						 enum radio_path rfpath);
+extern void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw);
+extern void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw,
+					 long *powerlevel);
+extern void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel);
+extern bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw,
+					  long power_indbm);
+extern void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw,
+					     u8 operation);
+extern void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+extern void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
+				   enum nl80211_channel_type ch_type);
+extern void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw);
+extern u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw);
+extern void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery);
+extern void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw,
+					 u16 beaconinterval);
+void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta);
+void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw);
+void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain);
+bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw,
+					      u32 rfpath);
+extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					  enum rf_pwrstate rfpwr_state);
+void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
+void rtl92c_phy_set_io(struct ieee80211_hw *hw);
+void rtl92c_bb_block_on(struct ieee80211_hw *hw);
+u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
+long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
+				  enum wireless_mode wirelessmode,
+				  u8 txpwridx);
+u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
+				enum wireless_mode wirelessmode,
+				long power_indbm);
+void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
+static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
+					     u32 cmdtableidx, u32 cmdtablesz,
+					     enum swchnlcmd_id cmdid, u32 para1,
+					     u32 para2, u32 msdelay);
+static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
+					     u8 channel, u8 *stage, u8 *step,
+					     u32 *delay);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/def.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/def.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/def.h	2011-05-19 00:06:34.000000000 -0400
@@ -121,11 +121,37 @@
 #define CHIP_92C			0x01
 #define CHIP_88C			0x00
 
+/* Add vendor information into chip version definition.
+ * Add UMC B-Cut and RTL8723 chip info definition.
+ *
+ * BIT 7	Reserved
+ * BIT 6	UMC BCut
+ * BIT 5	Manufacturer(TSMC/UMC)
+ * BIT 4	TEST/NORMAL
+ * BIT 3	8723 Version
+ * BIT 2	8723?
+ * BIT 1	1T2R?
+ * BIT 0	88C/92C
+*/
+
 enum version_8192c {
 	VERSION_A_CHIP_92C = 0x01,
 	VERSION_A_CHIP_88C = 0x00,
 	VERSION_B_CHIP_92C = 0x11,
 	VERSION_B_CHIP_88C = 0x10,
+	VERSION_TEST_CHIP_88C = 0x00,
+	VERSION_TEST_CHIP_92C = 0x01,
+	VERSION_NORMAL_TSMC_CHIP_88C = 0x10,
+	VERSION_NORMAL_TSMC_CHIP_92C = 0x11,
+	VERSION_NORMAL_TSMC_CHIP_92C_1T2R = 0x13,
+	VERSION_NORMAL_UMC_CHIP_88C_A_CUT = 0x30,
+	VERSION_NORMAL_UMC_CHIP_92C_A_CUT = 0x31,
+	VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT = 0x33,
+	VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT = 0x34,
+	VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT = 0x3c,
+	VERSION_NORMAL_UMC_CHIP_88C_B_CUT = 0x70,
+	VERSION_NORMAL_UMC_CHIP_92C_B_CUT = 0x71,
+	VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT = 0x73,
 	VERSION_UNKNOWN = 0x88,
 };
 
@@ -254,4 +280,122 @@
 	u8 *p_cmdbuffer;
 };
 
+static inline u8 _rtl92c_get_chnl_group(u8 chnl)
+{
+	u8 group = 0;
+
+	if (chnl < 3)
+		group = 0;
+	else if (chnl < 9)
+		group = 1;
+	else
+		group = 2;
+
+	return group;
+}
+
+/* NOTE: reference to rtl8192c_rates struct */
+static inline int _rtl92c_rate_mapping(struct ieee80211_hw *hw, bool isHT,
+				       u8 desc_rate, bool first_ampdu)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int rate_idx = 0;
+
+	if (first_ampdu) {
+		if (false == isHT) {
+			switch (desc_rate) {
+			case DESC92C_RATE1M:
+				rate_idx = 0;
+				break;
+			case DESC92C_RATE2M:
+				rate_idx = 1;
+				break;
+			case DESC92C_RATE5_5M:
+				rate_idx = 2;
+				break;
+			case DESC92C_RATE11M:
+				rate_idx = 3;
+				break;
+			case DESC92C_RATE6M:
+				rate_idx = 4;
+				break;
+			case DESC92C_RATE9M:
+				rate_idx = 5;
+				break;
+			case DESC92C_RATE12M:
+				rate_idx = 6;
+				break;
+			case DESC92C_RATE18M:
+				rate_idx = 7;
+				break;
+			case DESC92C_RATE24M:
+				rate_idx = 8;
+				break;
+			case DESC92C_RATE36M:
+				rate_idx = 9;
+				break;
+			case DESC92C_RATE48M:
+				rate_idx = 10;
+				break;
+			case DESC92C_RATE54M:
+				rate_idx = 11;
+				break;
+			default:
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG,
+					 ("Rate %d is not support, set to "
+					"1M rate.\n", desc_rate));
+				rate_idx = 0;
+				break;
+			}
+		} else {
+			rate_idx = 11;
+		}
+		return rate_idx;
+	}
+	switch (desc_rate) {
+	case DESC92C_RATE1M:
+		rate_idx = 0;
+		break;
+	case DESC92C_RATE2M:
+		rate_idx = 1;
+		break;
+	case DESC92C_RATE5_5M:
+		rate_idx = 2;
+		break;
+	case DESC92C_RATE11M:
+		rate_idx = 3;
+		break;
+	case DESC92C_RATE6M:
+		rate_idx = 4;
+		break;
+	case DESC92C_RATE9M:
+		rate_idx = 5;
+		break;
+	case DESC92C_RATE12M:
+		rate_idx = 6;
+		break;
+	case DESC92C_RATE18M:
+		rate_idx = 7;
+		break;
+	case DESC92C_RATE24M:
+		rate_idx = 8;
+		break;
+	case DESC92C_RATE36M:
+		rate_idx = 9;
+		break;
+	case DESC92C_RATE48M:
+		rate_idx = 10;
+		break;
+	case DESC92C_RATE54M:
+		rate_idx = 11;
+		break;
+	/* TODO: How to mapping MCS rate? */
+	/*  NOTE: referenc to __ieee80211_rx */
+	default:
+		rate_idx = 11;
+		break;
+	}
+	return rate_idx;
+}
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,487 +33,15 @@
 #include "def.h"
 #include "phy.h"
 #include "dm.h"
-#include "fw.h"
-
-struct dig_t dm_digtable;
-static struct ps_t dm_pstable;
-
-static const u32 ofdmswing_table[OFDM_TABLE_SIZE] = {
-	0x7f8001fe,
-	0x788001e2,
-	0x71c001c7,
-	0x6b8001ae,
-	0x65400195,
-	0x5fc0017f,
-	0x5a400169,
-	0x55400155,
-	0x50800142,
-	0x4c000130,
-	0x47c0011f,
-	0x43c0010f,
-	0x40000100,
-	0x3c8000f2,
-	0x390000e4,
-	0x35c000d7,
-	0x32c000cb,
-	0x300000c0,
-	0x2d4000b5,
-	0x2ac000ab,
-	0x288000a2,
-	0x26000098,
-	0x24000090,
-	0x22000088,
-	0x20000080,
-	0x1e400079,
-	0x1c800072,
-	0x1b00006c,
-	0x19800066,
-	0x18000060,
-	0x16c0005b,
-	0x15800056,
-	0x14400051,
-	0x1300004c,
-	0x12000048,
-	0x11000044,
-	0x10000040,
-};
-
-static const u8 cckswing_table_ch1ch13[CCK_TABLE_SIZE][8] = {
-	{0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04},
-	{0x33, 0x32, 0x2b, 0x23, 0x1a, 0x11, 0x08, 0x04},
-	{0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03},
-	{0x2d, 0x2d, 0x27, 0x1f, 0x18, 0x0f, 0x08, 0x03},
-	{0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03},
-	{0x28, 0x28, 0x22, 0x1c, 0x15, 0x0d, 0x07, 0x03},
-	{0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03},
-	{0x24, 0x23, 0x1f, 0x19, 0x13, 0x0c, 0x06, 0x03},
-	{0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02},
-	{0x20, 0x20, 0x1b, 0x16, 0x11, 0x08, 0x05, 0x02},
-	{0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02},
-	{0x1d, 0x1c, 0x18, 0x14, 0x0f, 0x0a, 0x05, 0x02},
-	{0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02},
-	{0x1a, 0x19, 0x16, 0x12, 0x0d, 0x09, 0x04, 0x02},
-	{0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02},
-	{0x17, 0x16, 0x13, 0x10, 0x0c, 0x08, 0x04, 0x02},
-	{0x16, 0x15, 0x12, 0x0f, 0x0b, 0x07, 0x04, 0x01},
-	{0x14, 0x14, 0x11, 0x0e, 0x0b, 0x07, 0x03, 0x02},
-	{0x13, 0x13, 0x10, 0x0d, 0x0a, 0x06, 0x03, 0x01},
-	{0x12, 0x12, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
-	{0x11, 0x11, 0x0f, 0x0c, 0x09, 0x06, 0x03, 0x01},
-	{0x10, 0x10, 0x0e, 0x0b, 0x08, 0x05, 0x03, 0x01},
-	{0x0f, 0x0f, 0x0d, 0x0b, 0x08, 0x05, 0x03, 0x01},
-	{0x0e, 0x0e, 0x0c, 0x0a, 0x08, 0x05, 0x02, 0x01},
-	{0x0d, 0x0d, 0x0c, 0x0a, 0x07, 0x05, 0x02, 0x01},
-	{0x0d, 0x0c, 0x0b, 0x09, 0x07, 0x04, 0x02, 0x01},
-	{0x0c, 0x0c, 0x0a, 0x09, 0x06, 0x04, 0x02, 0x01},
-	{0x0b, 0x0b, 0x0a, 0x08, 0x06, 0x04, 0x02, 0x01},
-	{0x0b, 0x0a, 0x09, 0x08, 0x06, 0x04, 0x02, 0x01},
-	{0x0a, 0x0a, 0x09, 0x07, 0x05, 0x03, 0x02, 0x01},
-	{0x0a, 0x09, 0x08, 0x07, 0x05, 0x03, 0x02, 0x01},
-	{0x09, 0x09, 0x08, 0x06, 0x05, 0x03, 0x01, 0x01},
-	{0x09, 0x08, 0x07, 0x06, 0x04, 0x03, 0x01, 0x01}
-};
-
-static const u8 cckswing_table_ch14[CCK_TABLE_SIZE][8] = {
-	{0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00},
-	{0x33, 0x32, 0x2b, 0x19, 0x00, 0x00, 0x00, 0x00},
-	{0x30, 0x2f, 0x29, 0x18, 0x00, 0x00, 0x00, 0x00},
-	{0x2d, 0x2d, 0x17, 0x17, 0x00, 0x00, 0x00, 0x00},
-	{0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00},
-	{0x28, 0x28, 0x24, 0x14, 0x00, 0x00, 0x00, 0x00},
-	{0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00},
-	{0x24, 0x23, 0x1f, 0x12, 0x00, 0x00, 0x00, 0x00},
-	{0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00},
-	{0x20, 0x20, 0x1b, 0x10, 0x00, 0x00, 0x00, 0x00},
-	{0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00},
-	{0x1d, 0x1c, 0x18, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00},
-	{0x1a, 0x19, 0x16, 0x0d, 0x00, 0x00, 0x00, 0x00},
-	{0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00},
-	{0x17, 0x16, 0x13, 0x0b, 0x00, 0x00, 0x00, 0x00},
-	{0x16, 0x15, 0x12, 0x0b, 0x00, 0x00, 0x00, 0x00},
-	{0x14, 0x14, 0x11, 0x0a, 0x00, 0x00, 0x00, 0x00},
-	{0x13, 0x13, 0x10, 0x0a, 0x00, 0x00, 0x00, 0x00},
-	{0x12, 0x12, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
-	{0x11, 0x11, 0x0f, 0x09, 0x00, 0x00, 0x00, 0x00},
-	{0x10, 0x10, 0x0e, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x0f, 0x0f, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00},
-	{0x0e, 0x0e, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
-	{0x0d, 0x0d, 0x0c, 0x07, 0x00, 0x00, 0x00, 0x00},
-	{0x0d, 0x0c, 0x0b, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x0c, 0x0c, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x0b, 0x0b, 0x0a, 0x06, 0x00, 0x00, 0x00, 0x00},
-	{0x0b, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x0a, 0x0a, 0x09, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x0a, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x09, 0x09, 0x08, 0x05, 0x00, 0x00, 0x00, 0x00},
-	{0x09, 0x08, 0x07, 0x04, 0x00, 0x00, 0x00, 0x00}
-};
-
-static void rtl92c_dm_diginit(struct ieee80211_hw *hw)
-{
-	dm_digtable.dig_enable_flag = true;
-	dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-	dm_digtable.cur_igvalue = 0x20;
-	dm_digtable.pre_igvalue = 0x0;
-	dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
-	dm_digtable.presta_connectstate = DIG_STA_DISCONNECT;
-	dm_digtable.curmultista_connectstate = DIG_MULTISTA_DISCONNECT;
-	dm_digtable.rssi_lowthresh = DM_DIG_THRESH_LOW;
-	dm_digtable.rssi_highthresh = DM_DIG_THRESH_HIGH;
-	dm_digtable.fa_lowthresh = DM_FALSEALARM_THRESH_LOW;
-	dm_digtable.fa_highthresh = DM_FALSEALARM_THRESH_HIGH;
-	dm_digtable.rx_gain_range_max = DM_DIG_MAX;
-	dm_digtable.rx_gain_range_min = DM_DIG_MIN;
-	dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
-	dm_digtable.backoff_val_range_max = DM_DIG_BACKOFF_MAX;
-	dm_digtable.backoff_val_range_min = DM_DIG_BACKOFF_MIN;
-	dm_digtable.pre_cck_pd_state = CCK_PD_STAGE_MAX;
-	dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
-}
-
-static u8 rtl92c_dm_initial_gain_min_pwdb(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	long rssi_val_min = 0;
-
-	if ((dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) &&
-	    (dm_digtable.cursta_connectctate == DIG_STA_CONNECT)) {
-		if (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb != 0)
-			rssi_val_min =
-			    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb >
-			     rtlpriv->dm.undecorated_smoothed_pwdb) ?
-			    rtlpriv->dm.undecorated_smoothed_pwdb :
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-		else
-			rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT ||
-		   dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT) {
-		rssi_val_min = rtlpriv->dm.undecorated_smoothed_pwdb;
-	} else if (dm_digtable.curmultista_connectstate ==
-		   DIG_MULTISTA_CONNECT) {
-		rssi_val_min = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-	}
-
-	return (u8) rssi_val_min;
-}
-
-static void rtl92c_dm_false_alarm_counter_statistics(struct ieee80211_hw *hw)
-{
-	u32 ret_value;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct false_alarm_statistics *falsealm_cnt = &(rtlpriv->falsealm_cnt);
-
-	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER1, MASKDWORD);
-	falsealm_cnt->cnt_parity_fail = ((ret_value & 0xffff0000) >> 16);
-
-	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER2, MASKDWORD);
-	falsealm_cnt->cnt_rate_illegal = (ret_value & 0xffff);
-	falsealm_cnt->cnt_crc8_fail = ((ret_value & 0xffff0000) >> 16);
-
-	ret_value = rtl_get_bbreg(hw, ROFDM_PHYCOUNTER3, MASKDWORD);
-	falsealm_cnt->cnt_mcs_fail = (ret_value & 0xffff);
-	falsealm_cnt->cnt_ofdm_fail = falsealm_cnt->cnt_parity_fail +
-	    falsealm_cnt->cnt_rate_illegal +
-	    falsealm_cnt->cnt_crc8_fail + falsealm_cnt->cnt_mcs_fail;
-
-	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, BIT(14), 1);
-	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERLOWER, MASKBYTE0);
-	falsealm_cnt->cnt_cck_fail = ret_value;
-
-	ret_value = rtl_get_bbreg(hw, RCCK0_FACOUNTERUPPER, MASKBYTE3);
-	falsealm_cnt->cnt_cck_fail += (ret_value & 0xff) << 8;
-	falsealm_cnt->cnt_all = (falsealm_cnt->cnt_parity_fail +
-				 falsealm_cnt->cnt_rate_illegal +
-				 falsealm_cnt->cnt_crc8_fail +
-				 falsealm_cnt->cnt_mcs_fail +
-				 falsealm_cnt->cnt_cck_fail);
-
-	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 1);
-	rtl_set_bbreg(hw, ROFDM1_LSTF, 0x08000000, 0);
-	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 0);
-	rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT, 0x0000c000, 2);
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("cnt_parity_fail = %d, cnt_rate_illegal = %d, "
-		  "cnt_crc8_fail = %d, cnt_mcs_fail = %d\n",
-		  falsealm_cnt->cnt_parity_fail,
-		  falsealm_cnt->cnt_rate_illegal,
-		  falsealm_cnt->cnt_crc8_fail, falsealm_cnt->cnt_mcs_fail));
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("cnt_ofdm_fail = %x, cnt_cck_fail = %x, cnt_all = %x\n",
-		  falsealm_cnt->cnt_ofdm_fail,
-		  falsealm_cnt->cnt_cck_fail, falsealm_cnt->cnt_all));
-}
-
-static void rtl92c_dm_ctrl_initgain_by_fa(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 value_igi = dm_digtable.cur_igvalue;
-
-	if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH0)
-		value_igi--;
-	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH1)
-		value_igi += 0;
-	else if (rtlpriv->falsealm_cnt.cnt_all < DM_DIG_FA_TH2)
-		value_igi++;
-	else if (rtlpriv->falsealm_cnt.cnt_all >= DM_DIG_FA_TH2)
-		value_igi += 2;
-	if (value_igi > DM_DIG_FA_UPPER)
-		value_igi = DM_DIG_FA_UPPER;
-	else if (value_igi < DM_DIG_FA_LOWER)
-		value_igi = DM_DIG_FA_LOWER;
-	if (rtlpriv->falsealm_cnt.cnt_all > 10000)
-		value_igi = 0x32;
-
-	dm_digtable.cur_igvalue = value_igi;
-	rtl92c_dm_write_dig(hw);
-}
-
-static void rtl92c_dm_ctrl_initgain_by_rssi(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	if (rtlpriv->falsealm_cnt.cnt_all > dm_digtable.fa_highthresh) {
-		if ((dm_digtable.backoff_val - 2) <
-		    dm_digtable.backoff_val_range_min)
-			dm_digtable.backoff_val =
-			    dm_digtable.backoff_val_range_min;
-		else
-			dm_digtable.backoff_val -= 2;
-	} else if (rtlpriv->falsealm_cnt.cnt_all < dm_digtable.fa_lowthresh) {
-		if ((dm_digtable.backoff_val + 2) >
-		    dm_digtable.backoff_val_range_max)
-			dm_digtable.backoff_val =
-			    dm_digtable.backoff_val_range_max;
-		else
-			dm_digtable.backoff_val += 2;
-	}
-
-	if ((dm_digtable.rssi_val_min + 10 - dm_digtable.backoff_val) >
-	    dm_digtable.rx_gain_range_max)
-		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_max;
-	else if ((dm_digtable.rssi_val_min + 10 -
-		  dm_digtable.backoff_val) < dm_digtable.rx_gain_range_min)
-		dm_digtable.cur_igvalue = dm_digtable.rx_gain_range_min;
-	else
-		dm_digtable.cur_igvalue = dm_digtable.rssi_val_min + 10 -
-		    dm_digtable.backoff_val;
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("rssi_val_min = %x backoff_val %x\n",
-		  dm_digtable.rssi_val_min, dm_digtable.backoff_val));
-
-	rtl92c_dm_write_dig(hw);
-}
-
-static void rtl92c_dm_initial_gain_multi_sta(struct ieee80211_hw *hw)
-{
-	static u8 binitialized; /* initialized to false */
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	long rssi_strength = rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-	bool b_multi_sta = false;
-
-	if (mac->opmode == NL80211_IFTYPE_ADHOC)
-		b_multi_sta = true;
-
-	if ((b_multi_sta == false) || (dm_digtable.cursta_connectctate !=
-				       DIG_STA_DISCONNECT)) {
-		binitialized = false;
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-		return;
-	} else if (binitialized == false) {
-		binitialized = true;
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
-		dm_digtable.cur_igvalue = 0x20;
-		rtl92c_dm_write_dig(hw);
-	}
-
-	if (dm_digtable.curmultista_connectstate == DIG_MULTISTA_CONNECT) {
-		if ((rssi_strength < dm_digtable.rssi_lowthresh) &&
-		    (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_1)) {
-
-			if (dm_digtable.dig_ext_port_stage ==
-			    DIG_EXT_PORT_STAGE_2) {
-				dm_digtable.cur_igvalue = 0x20;
-				rtl92c_dm_write_dig(hw);
-			}
-
-			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_1;
-		} else if (rssi_strength > dm_digtable.rssi_highthresh) {
-			dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_2;
-			rtl92c_dm_ctrl_initgain_by_fa(hw);
-		}
-	} else if (dm_digtable.dig_ext_port_stage != DIG_EXT_PORT_STAGE_0) {
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_0;
-		dm_digtable.cur_igvalue = 0x20;
-		rtl92c_dm_write_dig(hw);
-	}
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("curmultista_connectstate = "
-		  "%x dig_ext_port_stage %x\n",
-		  dm_digtable.curmultista_connectstate,
-		  dm_digtable.dig_ext_port_stage));
-}
-
-static void rtl92c_dm_initial_gain_sta(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("presta_connectstate = %x,"
-		  " cursta_connectctate = %x\n",
-		  dm_digtable.presta_connectstate,
-		  dm_digtable.cursta_connectctate));
-
-	if (dm_digtable.presta_connectstate == dm_digtable.cursta_connectctate
-	    || dm_digtable.cursta_connectctate == DIG_STA_BEFORE_CONNECT
-	    || dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
-
-		if (dm_digtable.cursta_connectctate != DIG_STA_DISCONNECT) {
-			dm_digtable.rssi_val_min =
-			    rtl92c_dm_initial_gain_min_pwdb(hw);
-			rtl92c_dm_ctrl_initgain_by_rssi(hw);
-		}
-	} else {
-		dm_digtable.rssi_val_min = 0;
-		dm_digtable.dig_ext_port_stage = DIG_EXT_PORT_STAGE_MAX;
-		dm_digtable.backoff_val = DM_DIG_BACKOFF_DEFAULT;
-		dm_digtable.cur_igvalue = 0x20;
-		dm_digtable.pre_igvalue = 0;
-		rtl92c_dm_write_dig(hw);
-	}
-}
-
-static void rtl92c_dm_cck_packet_detection_thresh(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (dm_digtable.cursta_connectctate == DIG_STA_CONNECT) {
-		dm_digtable.rssi_val_min = rtl92c_dm_initial_gain_min_pwdb(hw);
-
-		if (dm_digtable.pre_cck_pd_state == CCK_PD_STAGE_LowRssi) {
-			if (dm_digtable.rssi_val_min <= 25)
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_LowRssi;
-			else
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_HighRssi;
-		} else {
-			if (dm_digtable.rssi_val_min <= 20)
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_LowRssi;
-			else
-				dm_digtable.cur_cck_pd_state =
-				    CCK_PD_STAGE_HighRssi;
-		}
-	} else {
-		dm_digtable.cur_cck_pd_state = CCK_PD_STAGE_MAX;
-	}
-
-	if (dm_digtable.pre_cck_pd_state != dm_digtable.cur_cck_pd_state) {
-		if (dm_digtable.cur_cck_pd_state == CCK_PD_STAGE_LowRssi) {
-			if (rtlpriv->falsealm_cnt.cnt_cck_fail > 800)
-				dm_digtable.cur_cck_fa_state =
-				    CCK_FA_STAGE_High;
-			else
-				dm_digtable.cur_cck_fa_state = CCK_FA_STAGE_Low;
-
-			if (dm_digtable.pre_cck_fa_state !=
-			    dm_digtable.cur_cck_fa_state) {
-				if (dm_digtable.cur_cck_fa_state ==
-				    CCK_FA_STAGE_Low)
-					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
-						      0x83);
-				else
-					rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2,
-						      0xcd);
 
-				dm_digtable.pre_cck_fa_state =
-				    dm_digtable.cur_cck_fa_state;
-			}
-
-			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x40);
-
-			if (IS_92C_SERIAL(rtlhal->version))
-				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
-					      MASKBYTE2, 0xd7);
-		} else {
-			rtl_set_bbreg(hw, RCCK0_CCA, MASKBYTE2, 0xcd);
-			rtl_set_bbreg(hw, RCCK0_SYSTEM, MASKBYTE1, 0x47);
-
-			if (IS_92C_SERIAL(rtlhal->version))
-				rtl_set_bbreg(hw, RCCK0_FALSEALARMREPORT,
-					      MASKBYTE2, 0xd3);
-		}
-		dm_digtable.pre_cck_pd_state = dm_digtable.cur_cck_pd_state;
-	}
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("CCKPDStage=%x\n", dm_digtable.cur_cck_pd_state));
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_TRACE,
-		 ("is92C=%x\n", IS_92C_SERIAL(rtlhal->version)));
-}
-
-static void rtl92c_dm_ctrl_initgain_by_twoport(struct ieee80211_hw *hw)
-{
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-
-	if (mac->act_scanning == true)
-		return;
-
-	if ((mac->link_state > MAC80211_NOLINK) &&
-	    (mac->link_state < MAC80211_LINKED))
-		dm_digtable.cursta_connectctate = DIG_STA_BEFORE_CONNECT;
-	else if (mac->link_state >= MAC80211_LINKED)
-		dm_digtable.cursta_connectctate = DIG_STA_CONNECT;
-	else
-		dm_digtable.cursta_connectctate = DIG_STA_DISCONNECT;
-
-	rtl92c_dm_initial_gain_sta(hw);
-	rtl92c_dm_initial_gain_multi_sta(hw);
-	rtl92c_dm_cck_packet_detection_thresh(hw);
-
-	dm_digtable.presta_connectstate = dm_digtable.cursta_connectctate;
-
-}
-
-static void rtl92c_dm_dig(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	if (rtlpriv->dm.b_dm_initialgain_enable == false)
-		return;
-	if (dm_digtable.dig_enable_flag == false)
-		return;
-
-	rtl92c_dm_ctrl_initgain_by_twoport(hw);
-
-}
-
-static void rtl92c_dm_init_dynamic_txpower(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtlpriv->dm.bdynamic_txpower_enable = false;
-
-	rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
-	rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
-}
-
-static void rtl92c_dm_dynamic_txpower(struct ieee80211_hw *hw)
+void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	long undecorated_smoothed_pwdb;
 
-	if (!rtlpriv->dm.bdynamic_txpower_enable)
+	if (!rtlpriv->dm.dynamic_txpower_enable)
 		return;
 
 	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
@@ -583,891 +111,3 @@
 
 	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
 }
-
-void rtl92c_dm_write_dig(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	RT_TRACE(rtlpriv, COMP_DIG, DBG_LOUD,
-		 ("cur_igvalue = 0x%x, "
-		  "pre_igvalue = 0x%x, backoff_val = %d\n",
-		  dm_digtable.cur_igvalue, dm_digtable.pre_igvalue,
-		  dm_digtable.backoff_val));
-
-	if (dm_digtable.pre_igvalue != dm_digtable.cur_igvalue) {
-		rtl_set_bbreg(hw, ROFDM0_XAAGCCORE1, 0x7f,
-			      dm_digtable.cur_igvalue);
-		rtl_set_bbreg(hw, ROFDM0_XBAGCCORE1, 0x7f,
-			      dm_digtable.cur_igvalue);
-
-		dm_digtable.pre_igvalue = dm_digtable.cur_igvalue;
-	}
-}
-
-static void rtl92c_dm_pwdb_monitor(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	long tmpentry_max_pwdb = 0, tmpentry_min_pwdb = 0xff;
-
-	u8 h2c_parameter[3] = { 0 };
-
-	return;
-
-	if (tmpentry_max_pwdb != 0) {
-		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb =
-		    tmpentry_max_pwdb;
-	} else {
-		rtlpriv->dm.entry_max_undecoratedsmoothed_pwdb = 0;
-	}
-
-	if (tmpentry_min_pwdb != 0xff) {
-		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb =
-		    tmpentry_min_pwdb;
-	} else {
-		rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb = 0;
-	}
-
-	h2c_parameter[2] = (u8) (rtlpriv->dm.undecorated_smoothed_pwdb & 0xFF);
-	h2c_parameter[0] = 0;
-
-	rtl92c_fill_h2c_cmd(hw, H2C_RSSI_REPORT, 3, h2c_parameter);
-}
-
-void rtl92c_dm_init_edca_turbo(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	rtlpriv->dm.bcurrent_turbo_edca = false;
-	rtlpriv->dm.bis_any_nonbepkts = false;
-	rtlpriv->dm.bis_cur_rdlstate = false;
-}
-
-static void rtl92c_dm_check_edca_turbo(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	static u64 last_txok_cnt;
-	static u64 last_rxok_cnt;
-	u64 cur_txok_cnt;
-	u64 cur_rxok_cnt;
-	u32 edca_be_ul = 0x5ea42b;
-	u32 edca_be_dl = 0x5ea42b;
-
-	if (mac->opmode == NL80211_IFTYPE_ADHOC)
-		goto dm_checkedcaturbo_exit;
-
-	if (mac->link_state != MAC80211_LINKED) {
-		rtlpriv->dm.bcurrent_turbo_edca = false;
-		return;
-	}
-
-	if (!mac->ht_enable) {	/*FIX MERGE */
-		if (!(edca_be_ul & 0xffff0000))
-			edca_be_ul |= 0x005e0000;
-
-		if (!(edca_be_dl & 0xffff0000))
-			edca_be_dl |= 0x005e0000;
-	}
-
-	if ((!rtlpriv->dm.bis_any_nonbepkts) &&
-	    (!rtlpriv->dm.b_disable_framebursting)) {
-		cur_txok_cnt = rtlpriv->stats.txbytesunicast - last_txok_cnt;
-		cur_rxok_cnt = rtlpriv->stats.rxbytesunicast - last_rxok_cnt;
-		if (cur_rxok_cnt > 4 * cur_txok_cnt) {
-			if (!rtlpriv->dm.bis_cur_rdlstate ||
-			    !rtlpriv->dm.bcurrent_turbo_edca) {
-				rtl_write_dword(rtlpriv,
-						REG_EDCA_BE_PARAM,
-						edca_be_dl);
-				rtlpriv->dm.bis_cur_rdlstate = true;
-			}
-		} else {
-			if (rtlpriv->dm.bis_cur_rdlstate ||
-			    !rtlpriv->dm.bcurrent_turbo_edca) {
-				rtl_write_dword(rtlpriv,
-						REG_EDCA_BE_PARAM,
-						edca_be_ul);
-				rtlpriv->dm.bis_cur_rdlstate = false;
-			}
-		}
-		rtlpriv->dm.bcurrent_turbo_edca = true;
-	} else {
-		if (rtlpriv->dm.bcurrent_turbo_edca) {
-			u8 tmp = AC0_BE;
-			rtlpriv->cfg->ops->set_hw_reg(hw,
-						      HW_VAR_AC_PARAM,
-						      (u8 *) (&tmp));
-			rtlpriv->dm.bcurrent_turbo_edca = false;
-		}
-	}
-
-dm_checkedcaturbo_exit:
-	rtlpriv->dm.bis_any_nonbepkts = false;
-	last_txok_cnt = rtlpriv->stats.txbytesunicast;
-	last_rxok_cnt = rtlpriv->stats.rxbytesunicast;
-}
-
-static void rtl92c_dm_txpower_tracking_callback_thermalmeter(struct ieee80211_hw
-							     *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 thermalvalue, delta, delta_lck, delta_iqk;
-	long ele_a, ele_d, temp_cck, val_x, value32;
-	long val_y, ele_c;
-	u8 ofdm_index[2], cck_index, ofdm_index_old[2], cck_index_old;
-	int i;
-	bool is2t = IS_92C_SERIAL(rtlhal->version);
-	u8 txpwr_level[2] = {0, 0};
-	u8 ofdm_min_index = 6, rf;
-
-	rtlpriv->dm.btxpower_trackingInit = true;
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 ("rtl92c_dm_txpower_tracking_callback_thermalmeter\n"));
-
-	thermalvalue = (u8) rtl_get_rfreg(hw, RF90_PATH_A, RF_T_METER, 0x1f);
-
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 ("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
-		  "eeprom_thermalmeter 0x%x\n",
-		  thermalvalue, rtlpriv->dm.thermalvalue,
-		  rtlefuse->eeprom_thermalmeter));
-
-	rtl92c_phy_ap_calibrate(hw, (thermalvalue -
-				     rtlefuse->eeprom_thermalmeter));
-	if (is2t)
-		rf = 2;
-	else
-		rf = 1;
-
-	if (thermalvalue) {
-		ele_d = rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-				      MASKDWORD) & MASKOFDM_D;
-
-		for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
-			if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
-				ofdm_index_old[0] = (u8) i;
-
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					("Initial pathA ele_d reg0x%x = 0x%lx, "
-					 "ofdm_index=0x%x\n",
-					 ROFDM0_XATXIQIMBALANCE,
-					 ele_d, ofdm_index_old[0]));
-				break;
-			}
-		}
-
-		if (is2t) {
-			ele_d = rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
-					      MASKDWORD) & MASKOFDM_D;
-
-			for (i = 0; i < OFDM_TABLE_LENGTH; i++) {
-				if (ele_d == (ofdmswing_table[i] & MASKOFDM_D)) {
-					ofdm_index_old[1] = (u8) i;
-
-					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
-					   DBG_LOUD,
-					   ("Initial pathB ele_d reg0x%x = "
-					   "0x%lx, ofdm_index=0x%x\n",
-					   ROFDM0_XBTXIQIMBALANCE, ele_d,
-					   ofdm_index_old[1]));
-					break;
-				}
-			}
-		}
-
-		temp_cck =
-		    rtl_get_bbreg(hw, RCCK0_TXFILTER2, MASKDWORD) & MASKCCK;
-
-		for (i = 0; i < CCK_TABLE_LENGTH; i++) {
-			if (rtlpriv->dm.b_cck_inch14) {
-				if (memcmp((void *)&temp_cck,
-					   (void *)&cckswing_table_ch14[i][2],
-					   4) == 0) {
-					cck_index_old = (u8) i;
-
-					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
-						 DBG_LOUD,
-						 ("Initial reg0x%x = 0x%lx, "
-						  "cck_index=0x%x, ch 14 %d\n",
-						  RCCK0_TXFILTER2, temp_cck,
-						  cck_index_old,
-						  rtlpriv->dm.b_cck_inch14));
-					break;
-				}
-			} else {
-				if (memcmp((void *)&temp_cck,
-					   (void *)
-					   &cckswing_table_ch1ch13[i][2],
-					   4) == 0) {
-					cck_index_old = (u8) i;
-
-					RT_TRACE(rtlpriv, COMP_POWER_TRACKING,
-						 DBG_LOUD,
-						 ("Initial reg0x%x = 0x%lx, "
-						  "cck_index=0x%x, ch14 %d\n",
-						  RCCK0_TXFILTER2, temp_cck,
-						  cck_index_old,
-						  rtlpriv->dm.b_cck_inch14));
-					break;
-				}
-			}
-		}
-
-		if (!rtlpriv->dm.thermalvalue) {
-			rtlpriv->dm.thermalvalue =
-			    rtlefuse->eeprom_thermalmeter;
-			rtlpriv->dm.thermalvalue_lck = thermalvalue;
-			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
-			for (i = 0; i < rf; i++)
-				rtlpriv->dm.ofdm_index[i] = ofdm_index_old[i];
-			rtlpriv->dm.cck_index = cck_index_old;
-		}
-
-		delta = (thermalvalue > rtlpriv->dm.thermalvalue) ?
-		    (thermalvalue - rtlpriv->dm.thermalvalue) :
-		    (rtlpriv->dm.thermalvalue - thermalvalue);
-
-		delta_lck = (thermalvalue > rtlpriv->dm.thermalvalue_lck) ?
-		    (thermalvalue - rtlpriv->dm.thermalvalue_lck) :
-		    (rtlpriv->dm.thermalvalue_lck - thermalvalue);
-
-		delta_iqk = (thermalvalue > rtlpriv->dm.thermalvalue_iqk) ?
-		    (thermalvalue - rtlpriv->dm.thermalvalue_iqk) :
-		    (rtlpriv->dm.thermalvalue_iqk - thermalvalue);
-
-		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-			("Readback Thermal Meter = 0x%x pre thermal meter 0x%x "
-			 "eeprom_thermalmeter 0x%x delta 0x%x "
-			 "delta_lck 0x%x delta_iqk 0x%x\n",
-			 thermalvalue, rtlpriv->dm.thermalvalue,
-			 rtlefuse->eeprom_thermalmeter, delta, delta_lck,
-			 delta_iqk));
-
-		if (delta_lck > 1) {
-			rtlpriv->dm.thermalvalue_lck = thermalvalue;
-			rtl92c_phy_lc_calibrate(hw);
-		}
-
-		if (delta > 0 && rtlpriv->dm.txpower_track_control) {
-			if (thermalvalue > rtlpriv->dm.thermalvalue) {
-				for (i = 0; i < rf; i++)
-					rtlpriv->dm.ofdm_index[i] -= delta;
-				rtlpriv->dm.cck_index -= delta;
-			} else {
-				for (i = 0; i < rf; i++)
-					rtlpriv->dm.ofdm_index[i] += delta;
-				rtlpriv->dm.cck_index += delta;
-			}
-
-			if (is2t) {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("temp OFDM_A_index=0x%x, "
-					  "OFDM_B_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  rtlpriv->dm.ofdm_index[0],
-					  rtlpriv->dm.ofdm_index[1],
-					  rtlpriv->dm.cck_index));
-			} else {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("temp OFDM_A_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  rtlpriv->dm.ofdm_index[0],
-					  rtlpriv->dm.cck_index));
-			}
-
-			if (thermalvalue > rtlefuse->eeprom_thermalmeter) {
-				for (i = 0; i < rf; i++)
-					ofdm_index[i] =
-					    rtlpriv->dm.ofdm_index[i]
-					    + 1;
-				cck_index = rtlpriv->dm.cck_index + 1;
-			} else {
-				for (i = 0; i < rf; i++)
-					ofdm_index[i] =
-					    rtlpriv->dm.ofdm_index[i];
-				cck_index = rtlpriv->dm.cck_index;
-			}
-
-			for (i = 0; i < rf; i++) {
-				if (txpwr_level[i] >= 0 &&
-				    txpwr_level[i] <= 26) {
-					if (thermalvalue >
-					    rtlefuse->eeprom_thermalmeter) {
-						if (delta < 5)
-							ofdm_index[i] -= 1;
-
-						else
-							ofdm_index[i] -= 2;
-					} else if (delta > 5 && thermalvalue <
-						   rtlefuse->
-						   eeprom_thermalmeter) {
-						ofdm_index[i] += 1;
-					}
-				} else if (txpwr_level[i] >= 27 &&
-					   txpwr_level[i] <= 32
-					   && thermalvalue >
-					   rtlefuse->eeprom_thermalmeter) {
-					if (delta < 5)
-						ofdm_index[i] -= 1;
-
-					else
-						ofdm_index[i] -= 2;
-				} else if (txpwr_level[i] >= 32 &&
-					   txpwr_level[i] <= 38 &&
-					   thermalvalue >
-					   rtlefuse->eeprom_thermalmeter
-					   && delta > 5) {
-					ofdm_index[i] -= 1;
-				}
-			}
-
-			if (txpwr_level[i] >= 0 && txpwr_level[i] <= 26) {
-				if (thermalvalue >
-				    rtlefuse->eeprom_thermalmeter) {
-					if (delta < 5)
-						cck_index -= 1;
-
-					else
-						cck_index -= 2;
-				} else if (delta > 5 && thermalvalue <
-					   rtlefuse->eeprom_thermalmeter) {
-					cck_index += 1;
-				}
-			} else if (txpwr_level[i] >= 27 &&
-				   txpwr_level[i] <= 32 &&
-				   thermalvalue >
-				   rtlefuse->eeprom_thermalmeter) {
-				if (delta < 5)
-					cck_index -= 1;
-
-				else
-					cck_index -= 2;
-			} else if (txpwr_level[i] >= 32 &&
-				   txpwr_level[i] <= 38 &&
-				   thermalvalue > rtlefuse->eeprom_thermalmeter
-				   && delta > 5) {
-				cck_index -= 1;
-			}
-
-			for (i = 0; i < rf; i++) {
-				if (ofdm_index[i] > OFDM_TABLE_SIZE - 1)
-					ofdm_index[i] = OFDM_TABLE_SIZE - 1;
-
-				else if (ofdm_index[i] < ofdm_min_index)
-					ofdm_index[i] = ofdm_min_index;
-			}
-
-			if (cck_index > CCK_TABLE_SIZE - 1)
-				cck_index = CCK_TABLE_SIZE - 1;
-			else if (cck_index < 0)
-				cck_index = 0;
-
-			if (is2t) {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("new OFDM_A_index=0x%x, "
-					  "OFDM_B_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  ofdm_index[0], ofdm_index[1],
-					  cck_index));
-			} else {
-				RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-					 ("new OFDM_A_index=0x%x,"
-					  "cck_index=0x%x\n",
-					  ofdm_index[0], cck_index));
-			}
-		}
-
-		if (rtlpriv->dm.txpower_track_control && delta != 0) {
-			ele_d =
-			    (ofdmswing_table[ofdm_index[0]] & 0xFFC00000) >> 22;
-			val_x = rtlphy->reg_e94;
-			val_y = rtlphy->reg_e9c;
-
-			if (val_x != 0) {
-				if ((val_x & 0x00000200) != 0)
-					val_x = val_x | 0xFFFFFC00;
-				ele_a = ((val_x * ele_d) >> 8) & 0x000003FF;
-
-				if ((val_y & 0x00000200) != 0)
-					val_y = val_y | 0xFFFFFC00;
-				ele_c = ((val_y * ele_d) >> 8) & 0x000003FF;
-
-				value32 = (ele_d << 22) |
-				    ((ele_c & 0x3F) << 16) | ele_a;
-
-				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-					      MASKDWORD, value32);
-
-				value32 = (ele_c & 0x000003C0) >> 6;
-				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
-					      value32);
-
-				value32 = ((val_x * ele_d) >> 7) & 0x01;
-				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-					      BIT(31), value32);
-
-				value32 = ((val_y * ele_d) >> 7) & 0x01;
-				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-					      BIT(29), value32);
-			} else {
-				rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-					      MASKDWORD,
-					      ofdmswing_table[ofdm_index[0]]);
-
-				rtl_set_bbreg(hw, ROFDM0_XCTXAFE, MASKH4BITS,
-					      0x00);
-				rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-					      BIT(31) | BIT(29), 0x00);
-			}
-
-			if (!rtlpriv->dm.b_cck_inch14) {
-				rtl_write_byte(rtlpriv, 0xa22,
-					       cckswing_table_ch1ch13[cck_index]
-					       [0]);
-				rtl_write_byte(rtlpriv, 0xa23,
-					       cckswing_table_ch1ch13[cck_index]
-					       [1]);
-				rtl_write_byte(rtlpriv, 0xa24,
-					       cckswing_table_ch1ch13[cck_index]
-					       [2]);
-				rtl_write_byte(rtlpriv, 0xa25,
-					       cckswing_table_ch1ch13[cck_index]
-					       [3]);
-				rtl_write_byte(rtlpriv, 0xa26,
-					       cckswing_table_ch1ch13[cck_index]
-					       [4]);
-				rtl_write_byte(rtlpriv, 0xa27,
-					       cckswing_table_ch1ch13[cck_index]
-					       [5]);
-				rtl_write_byte(rtlpriv, 0xa28,
-					       cckswing_table_ch1ch13[cck_index]
-					       [6]);
-				rtl_write_byte(rtlpriv, 0xa29,
-					       cckswing_table_ch1ch13[cck_index]
-					       [7]);
-			} else {
-				rtl_write_byte(rtlpriv, 0xa22,
-					       cckswing_table_ch14[cck_index]
-					       [0]);
-				rtl_write_byte(rtlpriv, 0xa23,
-					       cckswing_table_ch14[cck_index]
-					       [1]);
-				rtl_write_byte(rtlpriv, 0xa24,
-					       cckswing_table_ch14[cck_index]
-					       [2]);
-				rtl_write_byte(rtlpriv, 0xa25,
-					       cckswing_table_ch14[cck_index]
-					       [3]);
-				rtl_write_byte(rtlpriv, 0xa26,
-					       cckswing_table_ch14[cck_index]
-					       [4]);
-				rtl_write_byte(rtlpriv, 0xa27,
-					       cckswing_table_ch14[cck_index]
-					       [5]);
-				rtl_write_byte(rtlpriv, 0xa28,
-					       cckswing_table_ch14[cck_index]
-					       [6]);
-				rtl_write_byte(rtlpriv, 0xa29,
-					       cckswing_table_ch14[cck_index]
-					       [7]);
-			}
-
-			if (is2t) {
-				ele_d = (ofdmswing_table[ofdm_index[1]] &
-					 0xFFC00000) >> 22;
-
-				val_x = rtlphy->reg_eb4;
-				val_y = rtlphy->reg_ebc;
-
-				if (val_x != 0) {
-					if ((val_x & 0x00000200) != 0)
-						val_x = val_x | 0xFFFFFC00;
-					ele_a = ((val_x * ele_d) >> 8) &
-					    0x000003FF;
-
-					if ((val_y & 0x00000200) != 0)
-						val_y = val_y | 0xFFFFFC00;
-					ele_c = ((val_y * ele_d) >> 8) &
-					    0x00003FF;
-
-					value32 = (ele_d << 22) |
-					    ((ele_c & 0x3F) << 16) | ele_a;
-					rtl_set_bbreg(hw,
-						      ROFDM0_XBTXIQIMBALANCE,
-						      MASKDWORD, value32);
-
-					value32 = (ele_c & 0x000003C0) >> 6;
-					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
-						      MASKH4BITS, value32);
-
-					value32 = ((val_x * ele_d) >> 7) & 0x01;
-					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-						      BIT(27), value32);
-
-					value32 = ((val_y * ele_d) >> 7) & 0x01;
-					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-						      BIT(25), value32);
-				} else {
-					rtl_set_bbreg(hw,
-						      ROFDM0_XBTXIQIMBALANCE,
-						      MASKDWORD,
-						      ofdmswing_table[ofdm_index
-								      [1]]);
-					rtl_set_bbreg(hw, ROFDM0_XDTXAFE,
-						      MASKH4BITS, 0x00);
-					rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD,
-						      BIT(27) | BIT(25), 0x00);
-				}
-
-			}
-		}
-
-		if (delta_iqk > 3) {
-			rtlpriv->dm.thermalvalue_iqk = thermalvalue;
-			rtl92c_phy_iq_calibrate(hw, false);
-		}
-
-		if (rtlpriv->dm.txpower_track_control)
-			rtlpriv->dm.thermalvalue = thermalvalue;
-	}
-
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD, ("<===\n"));
-
-}
-
-static void rtl92c_dm_initialize_txpower_tracking_thermalmeter(
-						struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtlpriv->dm.btxpower_tracking = true;
-	rtlpriv->dm.btxpower_trackingInit = false;
-
-	RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-		 ("pMgntInfo->btxpower_tracking = %d\n",
-		  rtlpriv->dm.btxpower_tracking));
-}
-
-static void rtl92c_dm_initialize_txpower_tracking(struct ieee80211_hw *hw)
-{
-	rtl92c_dm_initialize_txpower_tracking_thermalmeter(hw);
-}
-
-static void rtl92c_dm_txpower_tracking_directcall(struct ieee80211_hw *hw)
-{
-	rtl92c_dm_txpower_tracking_callback_thermalmeter(hw);
-}
-
-static void rtl92c_dm_check_txpower_tracking_thermal_meter(
-						struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	static u8 tm_trigger;
-
-	if (!rtlpriv->dm.btxpower_tracking)
-		return;
-
-	if (!tm_trigger) {
-		rtl_set_rfreg(hw, RF90_PATH_A, RF_T_METER, RFREG_OFFSET_MASK,
-			      0x60);
-		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-			 ("Trigger 92S Thermal Meter!!\n"));
-		tm_trigger = 1;
-		return;
-	} else {
-		RT_TRACE(rtlpriv, COMP_POWER_TRACKING, DBG_LOUD,
-			 ("Schedule TxPowerTracking direct call!!\n"));
-		rtl92c_dm_txpower_tracking_directcall(hw);
-		tm_trigger = 0;
-	}
-}
-
-void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw)
-{
-	rtl92c_dm_check_txpower_tracking_thermal_meter(hw);
-}
-
-void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rate_adaptive *p_ra = &(rtlpriv->ra);
-
-	p_ra->ratr_state = DM_RATR_STA_INIT;
-	p_ra->pre_ratr_state = DM_RATR_STA_INIT;
-
-	if (rtlpriv->dm.dm_type == DM_TYPE_BYDRIVER)
-		rtlpriv->dm.b_useramask = true;
-	else
-		rtlpriv->dm.b_useramask = false;
-
-}
-
-static void rtl92c_dm_refresh_rate_adaptive_mask(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	struct rate_adaptive *p_ra = &(rtlpriv->ra);
-	u32 low_rssithresh_for_ra, high_rssithresh_for_ra;
-
-	if (is_hal_stop(rtlhal)) {
-		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-			 ("<---- driver is going to unload\n"));
-		return;
-	}
-
-	if (!rtlpriv->dm.b_useramask) {
-		RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-			("<---- driver does not control rate adaptive mask\n"));
-		return;
-	}
-
-	if (mac->link_state == MAC80211_LINKED) {
-
-		switch (p_ra->pre_ratr_state) {
-		case DM_RATR_STA_HIGH:
-			high_rssithresh_for_ra = 50;
-			low_rssithresh_for_ra = 20;
-			break;
-		case DM_RATR_STA_MIDDLE:
-			high_rssithresh_for_ra = 55;
-			low_rssithresh_for_ra = 20;
-			break;
-		case DM_RATR_STA_LOW:
-			high_rssithresh_for_ra = 50;
-			low_rssithresh_for_ra = 25;
-			break;
-		default:
-			high_rssithresh_for_ra = 50;
-			low_rssithresh_for_ra = 20;
-			break;
-		}
-
-		if (rtlpriv->dm.undecorated_smoothed_pwdb >
-		    (long)high_rssithresh_for_ra)
-			p_ra->ratr_state = DM_RATR_STA_HIGH;
-		else if (rtlpriv->dm.undecorated_smoothed_pwdb >
-			 (long)low_rssithresh_for_ra)
-			p_ra->ratr_state = DM_RATR_STA_MIDDLE;
-		else
-			p_ra->ratr_state = DM_RATR_STA_LOW;
-
-		if (p_ra->pre_ratr_state != p_ra->ratr_state) {
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-				 ("RSSI = %ld\n",
-				  rtlpriv->dm.undecorated_smoothed_pwdb));
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-				 ("RSSI_LEVEL = %d\n", p_ra->ratr_state));
-			RT_TRACE(rtlpriv, COMP_RATE, DBG_LOUD,
-				 ("PreState = %d, CurState = %d\n",
-				  p_ra->pre_ratr_state, p_ra->ratr_state));
-
-			rtlpriv->cfg->ops->update_rate_mask(hw,
-					p_ra->ratr_state);
-
-			p_ra->pre_ratr_state = p_ra->ratr_state;
-		}
-	}
-}
-
-static void rtl92c_dm_init_dynamic_bb_powersaving(struct ieee80211_hw *hw)
-{
-	dm_pstable.pre_ccastate = CCA_MAX;
-	dm_pstable.cur_ccasate = CCA_MAX;
-	dm_pstable.pre_rfstate = RF_MAX;
-	dm_pstable.cur_rfstate = RF_MAX;
-	dm_pstable.rssi_val_min = 0;
-}
-
-static void rtl92c_dm_1r_cca(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	if (dm_pstable.rssi_val_min != 0) {
-		if (dm_pstable.pre_ccastate == CCA_2R) {
-			if (dm_pstable.rssi_val_min >= 35)
-				dm_pstable.cur_ccasate = CCA_1R;
-			else
-				dm_pstable.cur_ccasate = CCA_2R;
-		} else {
-			if (dm_pstable.rssi_val_min <= 30)
-				dm_pstable.cur_ccasate = CCA_2R;
-			else
-				dm_pstable.cur_ccasate = CCA_1R;
-		}
-	} else {
-		dm_pstable.cur_ccasate = CCA_MAX;
-	}
-
-	if (dm_pstable.pre_ccastate != dm_pstable.cur_ccasate) {
-		if (dm_pstable.cur_ccasate == CCA_1R) {
-			if (get_rf_type(rtlphy) == RF_2T2R) {
-				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
-					      MASKBYTE0, 0x13);
-				rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x20);
-			} else {
-				rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE,
-					      MASKBYTE0, 0x23);
-				rtl_set_bbreg(hw, 0xe70, 0x7fc00000, 0x10c);
-			}
-		} else {
-			rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0,
-				      0x33);
-			rtl_set_bbreg(hw, 0xe70, MASKBYTE3, 0x63);
-		}
-		dm_pstable.pre_ccastate = dm_pstable.cur_ccasate;
-	}
-
-	RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD, ("CCAStage = %s\n",
-					       (dm_pstable.cur_ccasate ==
-						0) ? "1RCCA" : "2RCCA"));
-}
-
-void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal)
-{
-	static u8 initialize;
-	static u32 reg_874, reg_c70, reg_85c, reg_a74;
-
-	if (initialize == 0) {
-		reg_874 = (rtl_get_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-					 MASKDWORD) & 0x1CC000) >> 14;
-
-		reg_c70 = (rtl_get_bbreg(hw, ROFDM0_AGCPARAMETER1,
-					 MASKDWORD) & BIT(3)) >> 3;
-
-		reg_85c = (rtl_get_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
-					 MASKDWORD) & 0xFF000000) >> 24;
-
-		reg_a74 = (rtl_get_bbreg(hw, 0xa74, MASKDWORD) & 0xF000) >> 12;
-
-		initialize = 1;
-	}
-
-	if (!bforce_in_normal) {
-		if (dm_pstable.rssi_val_min != 0) {
-			if (dm_pstable.pre_rfstate == RF_NORMAL) {
-				if (dm_pstable.rssi_val_min >= 30)
-					dm_pstable.cur_rfstate = RF_SAVE;
-				else
-					dm_pstable.cur_rfstate = RF_NORMAL;
-			} else {
-				if (dm_pstable.rssi_val_min <= 25)
-					dm_pstable.cur_rfstate = RF_NORMAL;
-				else
-					dm_pstable.cur_rfstate = RF_SAVE;
-			}
-		} else {
-			dm_pstable.cur_rfstate = RF_MAX;
-		}
-	} else {
-		dm_pstable.cur_rfstate = RF_NORMAL;
-	}
-
-	if (dm_pstable.pre_rfstate != dm_pstable.cur_rfstate) {
-		if (dm_pstable.cur_rfstate == RF_SAVE) {
-			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-				      0x1C0000, 0x2);
-			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3), 0);
-			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL,
-				      0xFF000000, 0x63);
-			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-				      0xC000, 0x2);
-			rtl_set_bbreg(hw, 0xa74, 0xF000, 0x3);
-			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
-			rtl_set_bbreg(hw, 0x818, BIT(28), 0x1);
-		} else {
-			rtl_set_bbreg(hw, RFPGA0_XCD_RFINTERFACESW,
-				      0x1CC000, reg_874);
-			rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, BIT(3),
-				      reg_c70);
-			rtl_set_bbreg(hw, RFPGA0_XCD_SWITCHCONTROL, 0xFF000000,
-				      reg_85c);
-			rtl_set_bbreg(hw, 0xa74, 0xF000, reg_a74);
-			rtl_set_bbreg(hw, 0x818, BIT(28), 0x0);
-		}
-
-		dm_pstable.pre_rfstate = dm_pstable.cur_rfstate;
-	}
-}
-
-static void rtl92c_dm_dynamic_bb_powersaving(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (((mac->link_state == MAC80211_NOLINK)) &&
-	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
-		dm_pstable.rssi_val_min = 0;
-		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-			 ("Not connected to any\n"));
-	}
-
-	if (mac->link_state == MAC80211_LINKED) {
-		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
-			dm_pstable.rssi_val_min =
-			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-				 ("AP Client PWDB = 0x%lx\n",
-				  dm_pstable.rssi_val_min));
-		} else {
-			dm_pstable.rssi_val_min =
-			    rtlpriv->dm.undecorated_smoothed_pwdb;
-			RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-				 ("STA Default Port PWDB = 0x%lx\n",
-				  dm_pstable.rssi_val_min));
-		}
-	} else {
-		dm_pstable.rssi_val_min =
-		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
-
-		RT_TRACE(rtlpriv, DBG_LOUD, DBG_LOUD,
-			 ("AP Ext Port PWDB = 0x%lx\n",
-			  dm_pstable.rssi_val_min));
-	}
-
-	if (IS_92C_SERIAL(rtlhal->version))
-		rtl92c_dm_1r_cca(hw);
-}
-
-void rtl92c_dm_init(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtlpriv->dm.dm_type = DM_TYPE_BYDRIVER;
-	rtl92c_dm_diginit(hw);
-	rtl92c_dm_init_dynamic_txpower(hw);
-	rtl92c_dm_init_edca_turbo(hw);
-	rtl92c_dm_init_rate_adaptive_mask(hw);
-	rtl92c_dm_initialize_txpower_tracking(hw);
-	rtl92c_dm_init_dynamic_bb_powersaving(hw);
-}
-
-void rtl92c_dm_watchdog(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	bool b_fw_current_inpsmode = false;
-	bool b_fw_ps_awake = true;
-
-	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FW_PSMODE_STATUS,
-				      (u8 *) (&b_fw_current_inpsmode));
-	rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_FWLPS_RF_ON,
-				      (u8 *) (&b_fw_ps_awake));
-
-	if ((ppsc->rfpwr_state == ERFON) && ((!b_fw_current_inpsmode) &&
-					     b_fw_ps_awake)
-	    && (!ppsc->rfchange_inprogress)) {
-		rtl92c_dm_pwdb_monitor(hw);
-		rtl92c_dm_dig(hw);
-		rtl92c_dm_false_alarm_counter_statistics(hw);
-		rtl92c_dm_dynamic_bb_powersaving(hw);
-		rtl92c_dm_dynamic_txpower(hw);
-		rtl92c_dm_check_txpower_tracking(hw);
-		rtl92c_dm_refresh_rate_adaptive_mask(hw);
-		rtl92c_dm_check_edca_turbo(hw);
-	}
-}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/dm.h	2011-05-19 00:06:34.000000000 -0400
@@ -192,5 +192,6 @@
 void rtl92c_dm_check_txpower_tracking(struct ieee80211_hw *hw);
 void rtl92c_dm_init_rate_adaptive_mask(struct ieee80211_hw *hw);
 void rtl92c_dm_rf_saving(struct ieee80211_hw *hw, u8 bforce_in_normal);
+void rtl92ce_dm_dynamic_txpower(struct ieee80211_hw *hw);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c	2012-03-24 01:14:44.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,804 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010  Realtek Corporation.
- *
- * 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:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-
-#include <linux/firmware.h>
-#include "../wifi.h"
-#include "../pci.h"
-#include "../base.h"
-#include "reg.h"
-#include "def.h"
-#include "fw.h"
-#include "table.h"
-
-static void _rtl92c_enable_fw_download(struct ieee80211_hw *hw, bool enable)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU) {
-		u32 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
-		if (enable)
-			value32 |= MCUFWDL_EN;
-		else
-			value32 &= ~MCUFWDL_EN;
-		rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
-	} else if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE) {
-		u8 tmp;
-		if (enable) {
-
-			tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
-			rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1,
-				       tmp | 0x04);
-
-			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
-			rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01);
-
-			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2);
-			rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7);
-		} else {
-
-			tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL);
-			rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe);
-
-			rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00);
-		}
-	}
-}
-
-static void _rtl92c_fw_block_write(struct ieee80211_hw *hw,
-				   const u8 *buffer, u32 size)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 blockSize = sizeof(u32);
-	u8 *bufferPtr = (u8 *) buffer;
-	u32 *pu4BytePtr = (u32 *) buffer;
-	u32 i, offset, blockCount, remainSize;
-
-	blockCount = size / blockSize;
-	remainSize = size % blockSize;
-
-	for (i = 0; i < blockCount; i++) {
-		offset = i * blockSize;
-		rtl_write_dword(rtlpriv, (FW_8192C_START_ADDRESS + offset),
-				*(pu4BytePtr + i));
-	}
-
-	if (remainSize) {
-		offset = blockCount * blockSize;
-		bufferPtr += offset;
-		for (i = 0; i < remainSize; i++) {
-			rtl_write_byte(rtlpriv, (FW_8192C_START_ADDRESS +
-						 offset + i), *(bufferPtr + i));
-		}
-	}
-}
-
-static void _rtl92c_fw_page_write(struct ieee80211_hw *hw,
-				  u32 page, const u8 *buffer, u32 size)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 value8;
-	u8 u8page = (u8) (page & 0x07);
-
-	value8 = (rtl_read_byte(rtlpriv, REG_MCUFWDL + 2) & 0xF8) | u8page;
-
-	rtl_write_byte(rtlpriv, (REG_MCUFWDL + 2), value8);
-	_rtl92c_fw_block_write(hw, buffer, size);
-}
-
-static void _rtl92c_fill_dummy(u8 *pfwbuf, u32 *pfwlen)
-{
-	u32 fwlen = *pfwlen;
-	u8 remain = (u8) (fwlen % 4);
-
-	remain = (remain == 0) ? 0 : (4 - remain);
-
-	while (remain > 0) {
-		pfwbuf[fwlen] = 0;
-		fwlen++;
-		remain--;
-	}
-
-	*pfwlen = fwlen;
-}
-
-static void _rtl92c_write_fw(struct ieee80211_hw *hw,
-			     enum version_8192c version, u8 *buffer, u32 size)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	bool is_version_b;
-	u8 *bufferPtr = (u8 *) buffer;
-
-	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, ("FW size is %d bytes,\n", size));
-
-	is_version_b = IS_CHIP_VER_B(version);
-	if (is_version_b) {
-		u32 pageNums, remainSize;
-		u32 page, offset;
-
-		if (rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
-			_rtl92c_fill_dummy(bufferPtr, &size);
-
-		pageNums = size / FW_8192C_PAGE_SIZE;
-		remainSize = size % FW_8192C_PAGE_SIZE;
-
-		if (pageNums > 4) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("Page numbers should not greater then 4\n"));
-		}
-
-		for (page = 0; page < pageNums; page++) {
-			offset = page * FW_8192C_PAGE_SIZE;
-			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
-					      FW_8192C_PAGE_SIZE);
-		}
-
-		if (remainSize) {
-			offset = pageNums * FW_8192C_PAGE_SIZE;
-			page = pageNums;
-			_rtl92c_fw_page_write(hw, page, (bufferPtr + offset),
-					      remainSize);
-		}
-	} else {
-		_rtl92c_fw_block_write(hw, buffer, size);
-	}
-}
-
-static int _rtl92c_fw_free_to_go(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	int err = -EIO;
-	u32 counter = 0;
-	u32 value32;
-
-	do {
-		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
-	} while ((counter++ < FW_8192C_POLLING_TIMEOUT_COUNT) &&
-		 (!(value32 & FWDL_ChkSum_rpt)));
-
-	if (counter >= FW_8192C_POLLING_TIMEOUT_COUNT) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("chksum report faill ! REG_MCUFWDL:0x%08x .\n",
-			  value32));
-		goto exit;
-	}
-
-	RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-		 ("Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32));
-
-	value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
-	value32 |= MCUFWDL_RDY;
-	value32 &= ~WINTINI_RDY;
-	rtl_write_dword(rtlpriv, REG_MCUFWDL, value32);
-
-	counter = 0;
-
-	do {
-		value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL);
-		if (value32 & WINTINI_RDY) {
-			RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-				 ("Polling FW ready success!!"
-				 " REG_MCUFWDL:0x%08x .\n",
-				 value32));
-			err = 0;
-			goto exit;
-		}
-
-		mdelay(FW_8192C_POLLING_DELAY);
-
-	} while (counter++ < FW_8192C_POLLING_TIMEOUT_COUNT);
-
-	RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-		 ("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", value32));
-
-exit:
-	return err;
-}
-
-int rtl92c_download_fw(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	struct rtl92c_firmware_header *pfwheader;
-	u8 *pfwdata;
-	u32 fwsize;
-	int err;
-	enum version_8192c version = rtlhal->version;
-
-	const struct firmware *firmware = NULL;
-
-	err = reject_firmware(&firmware, rtlpriv->cfg->fw_name,
-			       rtlpriv->io.dev);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Failed to request firmware!\n"));
-		return 1;
-	}
-
-	if (firmware->size > 0x4000) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is too big!\n"));
-		release_firmware(firmware);
-		return 1;
-	}
-
-	memcpy(rtlhal->pfirmware, firmware->data, firmware->size);
-	fwsize = firmware->size;
-	release_firmware(firmware);
-
-	pfwheader = (struct rtl92c_firmware_header *)rtlhal->pfirmware;
-	pfwdata = (u8 *) rtlhal->pfirmware;
-
-	if (IS_FW_HEADER_EXIST(pfwheader)) {
-		RT_TRACE(rtlpriv, COMP_FW, DBG_DMESG,
-			 ("Firmware Version(%d), Signature(%#x),Size(%d)\n",
-			  pfwheader->version, pfwheader->signature,
-			  (uint)sizeof(struct rtl92c_firmware_header)));
-
-		pfwdata = pfwdata + sizeof(struct rtl92c_firmware_header);
-		fwsize = fwsize - sizeof(struct rtl92c_firmware_header);
-	}
-
-	_rtl92c_enable_fw_download(hw, true);
-	_rtl92c_write_fw(hw, version, pfwdata, fwsize);
-	_rtl92c_enable_fw_download(hw, false);
-
-	err = _rtl92c_fw_free_to_go(hw);
-	if (err) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("Firmware is not ready to run!\n"));
-	} else {
-		RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE,
-			 ("Firmware is ready to run!\n"));
-	}
-
-	return 0;
-}
-
-static bool _rtl92c_check_fw_read_last_h2c(struct ieee80211_hw *hw, u8 boxnum)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 val_hmetfr, val_mcutst_1;
-	bool result = false;
-
-	val_hmetfr = rtl_read_byte(rtlpriv, REG_HMETFR);
-	val_mcutst_1 = rtl_read_byte(rtlpriv, (REG_MCUTST_1 + boxnum));
-
-	if (((val_hmetfr >> boxnum) & BIT(0)) == 0 && val_mcutst_1 == 0)
-		result = true;
-	return result;
-}
-
-static void _rtl92c_fill_h2c_command(struct ieee80211_hw *hw,
-			      u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	u8 boxnum;
-	u16 box_reg, box_extreg;
-	u8 u1b_tmp;
-	bool isfw_read = false;
-	u8 buf_index;
-	bool bwrite_sucess = false;
-	u8 wait_h2c_limmit = 100;
-	u8 wait_writeh2c_limmit = 100;
-	u8 boxcontent[4], boxextcontent[2];
-	u32 h2c_waitcounter = 0;
-	unsigned long flag;
-	u8 idx;
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("come in\n"));
-
-	while (true) {
-		spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
-		if (rtlhal->b_h2c_setinprogress) {
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 ("H2C set in progress! Wait to set.."
-				  "element_id(%d).\n", element_id));
-
-			while (rtlhal->b_h2c_setinprogress) {
-				spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock,
-						       flag);
-				h2c_waitcounter++;
-				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-					 ("Wait 100 us (%d times)...\n",
-					  h2c_waitcounter));
-				udelay(100);
-
-				if (h2c_waitcounter > 1000)
-					return;
-				spin_lock_irqsave(&rtlpriv->locks.h2c_lock,
-						  flag);
-			}
-			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
-		} else {
-			rtlhal->b_h2c_setinprogress = true;
-			spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
-			break;
-		}
-	}
-
-	while (!bwrite_sucess) {
-		wait_writeh2c_limmit--;
-		if (wait_writeh2c_limmit == 0) {
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("Write H2C fail because no trigger "
-				  "for FW INT!\n"));
-			break;
-		}
-
-		boxnum = rtlhal->last_hmeboxnum;
-		switch (boxnum) {
-		case 0:
-			box_reg = REG_HMEBOX_0;
-			box_extreg = REG_HMEBOX_EXT_0;
-			break;
-		case 1:
-			box_reg = REG_HMEBOX_1;
-			box_extreg = REG_HMEBOX_EXT_1;
-			break;
-		case 2:
-			box_reg = REG_HMEBOX_2;
-			box_extreg = REG_HMEBOX_EXT_2;
-			break;
-		case 3:
-			box_reg = REG_HMEBOX_3;
-			box_extreg = REG_HMEBOX_EXT_3;
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-
-		isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
-		while (!isfw_read) {
-
-			wait_h2c_limmit--;
-			if (wait_h2c_limmit == 0) {
-				RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-					 ("Wating too long for FW read "
-					  "clear HMEBox(%d)!\n", boxnum));
-				break;
-			}
-
-			udelay(10);
-
-			isfw_read = _rtl92c_check_fw_read_last_h2c(hw, boxnum);
-			u1b_tmp = rtl_read_byte(rtlpriv, 0x1BF);
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 ("Wating for FW read clear HMEBox(%d)!!! "
-				  "0x1BF = %2x\n", boxnum, u1b_tmp));
-		}
-
-		if (!isfw_read) {
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-				 ("Write H2C register BOX[%d] fail!!!!! "
-				  "Fw do not read.\n", boxnum));
-			break;
-		}
-
-		memset(boxcontent, 0, sizeof(boxcontent));
-		memset(boxextcontent, 0, sizeof(boxextcontent));
-		boxcontent[0] = element_id;
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-			 ("Write element_id box_reg(%4x) = %2x\n",
-			  box_reg, element_id));
-
-		switch (cmd_len) {
-		case 1:
-			boxcontent[0] &= ~(BIT(7));
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index, 1);
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 2:
-			boxcontent[0] &= ~(BIT(7));
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index, 2);
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 3:
-			boxcontent[0] &= ~(BIT(7));
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index, 3);
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 4:
-			boxcontent[0] |= (BIT(7));
-			memcpy((u8 *) (boxextcontent),
-			       p_cmdbuffer + buf_index, 2);
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index + 2, 2);
-
-			for (idx = 0; idx < 2; idx++) {
-				rtl_write_byte(rtlpriv, box_extreg + idx,
-					       boxextcontent[idx]);
-			}
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		case 5:
-			boxcontent[0] |= (BIT(7));
-			memcpy((u8 *) (boxextcontent),
-			       p_cmdbuffer + buf_index, 2);
-			memcpy((u8 *) (boxcontent) + 1,
-			       p_cmdbuffer + buf_index + 2, 3);
-
-			for (idx = 0; idx < 2; idx++) {
-				rtl_write_byte(rtlpriv, box_extreg + idx,
-					       boxextcontent[idx]);
-			}
-
-			for (idx = 0; idx < 4; idx++) {
-				rtl_write_byte(rtlpriv, box_reg + idx,
-					       boxcontent[idx]);
-			}
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-
-		bwrite_sucess = true;
-
-		rtlhal->last_hmeboxnum = boxnum + 1;
-		if (rtlhal->last_hmeboxnum == 4)
-			rtlhal->last_hmeboxnum = 0;
-
-		RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD,
-			 ("pHalData->last_hmeboxnum  = %d\n",
-			  rtlhal->last_hmeboxnum));
-	}
-
-	spin_lock_irqsave(&rtlpriv->locks.h2c_lock, flag);
-	rtlhal->b_h2c_setinprogress = false;
-	spin_unlock_irqrestore(&rtlpriv->locks.h2c_lock, flag);
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_LOUD, ("go out\n"));
-}
-
-void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
-			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	u32 tmp_cmdbuf[2];
-
-	if (rtlhal->bfw_ready == false) {
-		RT_ASSERT(false, ("return H2C cmd because of Fw "
-				  "download fail!!!\n"));
-		return;
-	}
-
-	memset(tmp_cmdbuf, 0, 8);
-	memcpy(tmp_cmdbuf, p_cmdbuffer, cmd_len);
-	_rtl92c_fill_h2c_command(hw, element_id, cmd_len, (u8 *)&tmp_cmdbuf);
-
-	return;
-}
-
-void rtl92c_firmware_selfreset(struct ieee80211_hw *hw)
-{
-	u8 u1b_tmp;
-	u8 delay = 100;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20);
-	u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
-
-	while (u1b_tmp & BIT(2)) {
-		delay--;
-		if (delay == 0) {
-			RT_ASSERT(false, ("8051 reset fail.\n"));
-			break;
-		}
-		udelay(50);
-		u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1);
-	}
-}
-
-void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u8 u1_h2c_set_pwrmode[3] = {0};
-	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-
-	RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("FW LPS mode = %d\n", mode));
-
-	SET_H2CCMD_PWRMODE_PARM_MODE(u1_h2c_set_pwrmode, mode);
-	SET_H2CCMD_PWRMODE_PARM_SMART_PS(u1_h2c_set_pwrmode, 1);
-	SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(u1_h2c_set_pwrmode,
-					      ppsc->reg_max_lps_awakeintvl);
-
-	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
-		      "rtl92c_set_fw_rsvdpagepkt(): u1_h2c_set_pwrmode\n",
-		      u1_h2c_set_pwrmode, 3);
-	rtl92c_fill_h2c_cmd(hw, H2C_SETPWRMODE, 3, u1_h2c_set_pwrmode);
-
-}
-
-static bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
-				    struct sk_buff *skb)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-	struct rtl8192_tx_ring *ring;
-	struct rtl_tx_desc *pdesc;
-	u8 own;
-	unsigned long flags;
-	struct sk_buff *pskb = NULL;
-
-	ring = &rtlpci->tx_ring[BEACON_QUEUE];
-
-	pskb = __skb_dequeue(&ring->queue);
-	if (pskb)
-		kfree_skb(pskb);
-
-	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
-
-	pdesc = &ring->desc[0];
-	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
-
-	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
-
-	__skb_queue_tail(&ring->queue, skb);
-
-	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
-
-	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
-
-	return true;
-}
-
-#define BEACON_PG		0 /*->1*/
-#define PSPOLL_PG		2
-#define NULL_PG			3
-#define PROBERSP_PG		4 /*->5*/
-
-#define TOTAL_RESERVED_PKT_LEN	768
-
-static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = {
-	/* page 0 beacon */
-	0x80, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF,
-	0xFF, 0xFF, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
-	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x50, 0x08,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
-	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
-	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
-	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
-	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
-	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
-	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
-	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-	/* page 1 beacon */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x10, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x10, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-	/* page 2  ps-poll */
-	0xA4, 0x10, 0x01, 0xC0, 0x00, 0x40, 0x10, 0x10,
-	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x18, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-	/* page 3  null */
-	0x48, 0x01, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
-	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
-	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x72, 0x00, 0x20, 0x8C, 0x00, 0x12, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80,
-	0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-	/* page 4  probe_resp */
-	0x50, 0x00, 0x00, 0x00, 0x00, 0x40, 0x10, 0x10,
-	0x00, 0x03, 0x00, 0xE0, 0x4C, 0x76, 0x00, 0x42,
-	0x00, 0x40, 0x10, 0x10, 0x00, 0x03, 0x00, 0x00,
-	0x9E, 0x46, 0x15, 0x32, 0x27, 0xF2, 0x2D, 0x00,
-	0x64, 0x00, 0x00, 0x04, 0x00, 0x0C, 0x6C, 0x69,
-	0x6E, 0x6B, 0x73, 0x79, 0x73, 0x5F, 0x77, 0x6C,
-	0x61, 0x6E, 0x01, 0x04, 0x82, 0x84, 0x8B, 0x96,
-	0x03, 0x01, 0x01, 0x06, 0x02, 0x00, 0x00, 0x2A,
-	0x01, 0x00, 0x32, 0x08, 0x24, 0x30, 0x48, 0x6C,
-	0x0C, 0x12, 0x18, 0x60, 0x2D, 0x1A, 0x6C, 0x18,
-	0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x3D, 0x00, 0xDD, 0x06, 0x00, 0xE0, 0x4C, 0x02,
-	0x01, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-
-	/* page 5  probe_resp */
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-	struct sk_buff *skb = NULL;
-
-	u32 totalpacketlen;
-	bool rtstatus;
-	u8 u1RsvdPageLoc[3] = {0};
-	bool b_dlok = false;
-
-	u8 *beacon;
-	u8 *p_pspoll;
-	u8 *nullfunc;
-	u8 *p_probersp;
-	/*---------------------------------------------------------
-				(1) beacon
-	---------------------------------------------------------*/
-	beacon = &reserved_page_packet[BEACON_PG * 128];
-	SET_80211_HDR_ADDRESS2(beacon, mac->mac_addr);
-	SET_80211_HDR_ADDRESS3(beacon, mac->bssid);
-
-	/*-------------------------------------------------------
-				(2) ps-poll
-	--------------------------------------------------------*/
-	p_pspoll = &reserved_page_packet[PSPOLL_PG * 128];
-	SET_80211_PS_POLL_AID(p_pspoll, (mac->assoc_id | 0xc000));
-	SET_80211_PS_POLL_BSSID(p_pspoll, mac->bssid);
-	SET_80211_PS_POLL_TA(p_pspoll, mac->mac_addr);
-
-	SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(u1RsvdPageLoc, PSPOLL_PG);
-
-	/*--------------------------------------------------------
-				(3) null data
-	---------------------------------------------------------*/
-	nullfunc = &reserved_page_packet[NULL_PG * 128];
-	SET_80211_HDR_ADDRESS1(nullfunc, mac->bssid);
-	SET_80211_HDR_ADDRESS2(nullfunc, mac->mac_addr);
-	SET_80211_HDR_ADDRESS3(nullfunc, mac->bssid);
-
-	SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(u1RsvdPageLoc, NULL_PG);
-
-	/*---------------------------------------------------------
-				(4) probe response
-	----------------------------------------------------------*/
-	p_probersp = &reserved_page_packet[PROBERSP_PG * 128];
-	SET_80211_HDR_ADDRESS1(p_probersp, mac->bssid);
-	SET_80211_HDR_ADDRESS2(p_probersp, mac->mac_addr);
-	SET_80211_HDR_ADDRESS3(p_probersp, mac->bssid);
-
-	SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(u1RsvdPageLoc, PROBERSP_PG);
-
-	totalpacketlen = TOTAL_RESERVED_PKT_LEN;
-
-	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
-		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
-		      &reserved_page_packet[0], totalpacketlen);
-	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
-		      "rtl92c_set_fw_rsvdpagepkt(): HW_VAR_SET_TX_CMD: ALL\n",
-		      u1RsvdPageLoc, 3);
-
-
-	skb = dev_alloc_skb(totalpacketlen);
-	memcpy((u8 *) skb_put(skb, totalpacketlen),
-	       &reserved_page_packet, totalpacketlen);
-
-	rtstatus = _rtl92c_cmd_send_packet(hw, skb);
-
-	if (rtstatus)
-		b_dlok = true;
-
-	if (b_dlok) {
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
-			 ("Set RSVD page location to Fw.\n"));
-		RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_DMESG,
-				"H2C_RSVDPAGE:\n",
-				u1RsvdPageLoc, 3);
-		rtl92c_fill_h2c_cmd(hw, H2C_RSVDPAGE,
-				    sizeof(u1RsvdPageLoc), u1RsvdPageLoc);
-	} else
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 ("Set RSVD page location to Fw FAIL!!!!!!.\n"));
-}
-
-void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus)
-{
-	u8 u1_joinbssrpt_parm[1] = {0};
-
-	SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(u1_joinbssrpt_parm, mstatus);
-
-	rtl92c_fill_h2c_cmd(hw, H2C_JOINBSSRPT, 1, u1_joinbssrpt_parm);
-}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/fw.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,98 +0,0 @@
-/******************************************************************************
- *
- * Copyright(c) 2009-2010  Realtek Corporation.
- *
- * 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:
- * wlanfae <wlanfae@realtek.com>
- * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
- * Hsinchu 300, Taiwan.
- *
- * Larry Finger <Larry.Finger@lwfinger.net>
- *
- *****************************************************************************/
-
-#ifndef __RTL92C__FW__H__
-#define __RTL92C__FW__H__
-
-#define FW_8192C_SIZE				0x3000
-#define FW_8192C_START_ADDRESS			0x1000
-#define FW_8192C_END_ADDRESS			0x3FFF
-#define FW_8192C_PAGE_SIZE			4096
-#define FW_8192C_POLLING_DELAY			5
-#define FW_8192C_POLLING_TIMEOUT_COUNT		100
-
-#define IS_FW_HEADER_EXIST(_pfwhdr)	\
-	((_pfwhdr->signature&0xFFF0) == 0x92C0 ||\
-	(_pfwhdr->signature&0xFFF0) == 0x88C0)
-
-struct rtl92c_firmware_header {
-	u16 signature;
-	u8 category;
-	u8 function;
-	u16 version;
-	u8 subversion;
-	u8 rsvd1;
-	u8 month;
-	u8 date;
-	u8 hour;
-	u8 minute;
-	u16 ramcodeSize;
-	u16 rsvd2;
-	u32 svnindex;
-	u32 rsvd3;
-	u32 rsvd4;
-	u32 rsvd5;
-};
-
-enum rtl8192c_h2c_cmd {
-	H2C_AP_OFFLOAD = 0,
-	H2C_SETPWRMODE = 1,
-	H2C_JOINBSSRPT = 2,
-	H2C_RSVDPAGE = 3,
-	H2C_RSSI_REPORT = 5,
-	H2C_RA_MASK = 6,
-	MAX_H2CCMD
-};
-
-#define pagenum_128(_len)	(u32)(((_len)>>7) + ((_len)&0x7F ? 1 : 0))
-
-#define SET_H2CCMD_PWRMODE_PARM_MODE(__ph2ccmd, __val)			\
-	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
-#define SET_H2CCMD_PWRMODE_PARM_SMART_PS(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
-#define SET_H2CCMD_PWRMODE_PARM_BCN_PASS_TIME(__ph2ccmd, __val)	\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
-#define SET_H2CCMD_JOINBSSRPT_PARM_OPMODE(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
-#define SET_H2CCMD_RSVDPAGE_LOC_PROBE_RSP(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE(__ph2ccmd, 0, 8, __val)
-#define SET_H2CCMD_RSVDPAGE_LOC_PSPOLL(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+1, 0, 8, __val)
-#define SET_H2CCMD_RSVDPAGE_LOC_NULL_DATA(__ph2ccmd, __val)		\
-	SET_BITS_TO_LE_1BYTE((__ph2ccmd)+2, 0, 8, __val)
-
-int rtl92c_download_fw(struct ieee80211_hw *hw);
-void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id,
-			 u32 cmd_len, u8 *p_cmdbuffer);
-void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
-void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
-void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
-void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
-
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,6 @@
 #include "def.h"
 #include "phy.h"
 #include "dm.h"
-#include "fw.h"
 #include "led.h"
 #include "hw.h"
 
@@ -124,7 +123,7 @@
 			break;
 		}
 	case HW_VAR_FW_PSMODE_STATUS:
-		*((bool *) (val)) = ppsc->b_fw_current_inpsmode;
+		*((bool *) (val)) = ppsc->fw_current_inpsmode;
 		break;
 	case HW_VAR_CORRECT_TSF:{
 		u64 tsf;
@@ -173,15 +172,15 @@
 			break;
 		}
 	case HW_VAR_BASIC_RATE:{
-			u16 b_rate_cfg = ((u16 *) val)[0];
+			u16 rate_cfg = ((u16 *) val)[0];
 			u8 rate_index = 0;
-			b_rate_cfg = b_rate_cfg & 0x15f;
-			b_rate_cfg |= 0x01;
-			rtl_write_byte(rtlpriv, REG_RRSR, b_rate_cfg & 0xff);
+			rate_cfg &= 0x15f;
+			rate_cfg |= 0x01;
+			rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
 			rtl_write_byte(rtlpriv, REG_RRSR + 1,
-				       (b_rate_cfg >> 8)&0xff);
-			while (b_rate_cfg > 0x1) {
-				b_rate_cfg = (b_rate_cfg >> 1);
+				       (rate_cfg >> 8)&0xff);
+			while (rate_cfg > 0x1) {
+				rate_cfg = (rate_cfg >> 1);
 				rate_index++;
 			}
 			rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
@@ -318,15 +317,17 @@
 		}
 	case HW_VAR_AC_PARAM:{
 			u8 e_aci = *((u8 *) val);
-			u32 u4b_ac_param = 0;
+			u32 u4b_ac_param;
+			u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min);
+			u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max);
+			u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op);
 
-			u4b_ac_param |= (u32) mac->ac[e_aci].aifs;
-			u4b_ac_param |= ((u32) mac->ac[e_aci].cw_min
+			u4b_ac_param = (u32) mac->ac[e_aci].aifs;
+			u4b_ac_param |= ((u32)cw_min
 					 & 0xF) << AC_PARAM_ECW_MIN_OFFSET;
-			u4b_ac_param |= ((u32) mac->ac[e_aci].cw_max &
+			u4b_ac_param |= ((u32)cw_max &
 					 0xF) << AC_PARAM_ECW_MAX_OFFSET;
-			u4b_ac_param |= (u32) mac->ac[e_aci].tx_op
-			    << AC_PARAM_TXOP_LIMIT_OFFSET;
+			u4b_ac_param |= (u32)tx_op << AC_PARAM_TXOP_OFFSET;
 
 			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
 				 ("queue:%x, ac_param:%x\n", e_aci,
@@ -469,12 +470,12 @@
 			break;
 		}
 	case HW_VAR_FW_PSMODE_STATUS:
-		ppsc->b_fw_current_inpsmode = *((bool *) val);
+		ppsc->fw_current_inpsmode = *((bool *) val);
 		break;
 	case HW_VAR_H2C_FW_JOINBSSRPT:{
 			u8 mstatus = (*(u8 *) val);
 			u8 tmp_regcr, tmp_reg422;
-			bool b_recover = false;
+			bool recover = false;
 
 			if (mstatus == RT_MEDIA_CONNECT) {
 				rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_AID,
@@ -491,7 +492,7 @@
 				    rtl_read_byte(rtlpriv,
 						  REG_FWHW_TXQ_CTRL + 2);
 				if (tmp_reg422 & BIT(6))
-					b_recover = true;
+					recover = true;
 				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
 					       tmp_reg422 & (~BIT(6)));
 
@@ -500,7 +501,7 @@
 				_rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0);
 				_rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4));
 
-				if (b_recover) {
+				if (recover) {
 					rtl_write_byte(rtlpriv,
 						       REG_FWHW_TXQ_CTRL + 2,
 						       tmp_reg422);
@@ -868,7 +869,7 @@
 	rtl_write_word(rtlpriv, 0x350, 0x870c);
 	rtl_write_byte(rtlpriv, 0x352, 0x1);
 
-	if (ppsc->b_support_backdoor)
+	if (ppsc->support_backdoor)
 		rtl_write_byte(rtlpriv, 0x349, 0x1b);
 	else
 		rtl_write_byte(rtlpriv, 0x349, 0x03);
@@ -940,15 +941,15 @@
 			 ("Failed to download FW. Init HW "
 			  "without FW now..\n"));
 		err = 1;
-		rtlhal->bfw_ready = false;
+		rtlhal->fw_ready = false;
 		return err;
 	} else {
-		rtlhal->bfw_ready = true;
+		rtlhal->fw_ready = true;
 	}
 
 	rtlhal->last_hmeboxnum = 0;
-	rtl92c_phy_mac_config(hw);
-	rtl92c_phy_bb_config(hw);
+	rtl92ce_phy_mac_config(hw);
+	rtl92ce_phy_bb_config(hw);
 	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
 	rtl92c_phy_rf_config(hw);
 	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
@@ -1170,21 +1171,20 @@
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
-
 	u32 u4b_ac_param;
+	u16 cw_min = le16_to_cpu(mac->ac[aci].cw_min);
+	u16 cw_max = le16_to_cpu(mac->ac[aci].cw_max);
+	u16 tx_op = le16_to_cpu(mac->ac[aci].tx_op);
 
 	rtl92c_dm_init_edca_turbo(hw);
-
 	u4b_ac_param = (u32) mac->ac[aci].aifs;
-	u4b_ac_param |=
-	    ((u32) mac->ac[aci].cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET;
-	u4b_ac_param |=
-	    ((u32) mac->ac[aci].cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET;
-	u4b_ac_param |= (u32) mac->ac[aci].tx_op << AC_PARAM_TXOP_LIMIT_OFFSET;
+	u4b_ac_param |= (u32) ((cw_min & 0xF) << AC_PARAM_ECW_MIN_OFFSET);
+	u4b_ac_param |= (u32) ((cw_max & 0xF) << AC_PARAM_ECW_MAX_OFFSET);
+	u4b_ac_param |= (u32) (tx_op << AC_PARAM_TXOP_OFFSET);
 	RT_TRACE(rtlpriv, COMP_QOS, DBG_DMESG,
 		 ("queue:%x, ac_param:%x aifs:%x cwmin:%x cwmax:%x txop:%x\n",
-		  aci, u4b_ac_param, mac->ac[aci].aifs, mac->ac[aci].cw_min,
-		  mac->ac[aci].cw_max, mac->ac[aci].tx_op));
+		  aci, u4b_ac_param, mac->ac[aci].aifs, cw_min,
+		  cw_max, tx_op));
 	switch (aci) {
 	case AC1_BK:
 		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
@@ -1237,7 +1237,7 @@
 	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE0);
-	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->bfw_ready)
+	if ((rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(7)) && rtlhal->fw_ready)
 		rtl92c_firmware_selfreset(hw);
 	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x51);
 	rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00);
@@ -1335,19 +1335,6 @@
 	rtl92ce_enable_interrupt(hw);
 }
 
-static u8 _rtl92c_get_chnl_group(u8 chnl)
-{
-	u8 group;
-
-	if (chnl < 3)
-		group = 0;
-	else if (chnl < 9)
-		group = 1;
-	else
-		group = 2;
-	return group;
-}
-
 static void _rtl92ce_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
 						 bool autoload_fail,
 						 u8 *hwinfo)
@@ -1568,7 +1555,7 @@
 	rtlefuse->eeprom_thermalmeter = (tempval & 0x1f);
 
 	if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
-		rtlefuse->b_apk_thermalmeterignore = true;
+		rtlefuse->apk_thermalmeterignore = true;
 
 	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
 	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
@@ -1625,7 +1612,7 @@
 
 	rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
 	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
-	rtlefuse->b_txpwr_fromeprom = true;
+	rtlefuse->txpwr_fromeprom = true;
 	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
 
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
@@ -1668,7 +1655,7 @@
 
 	switch (rtlhal->oem_id) {
 	case RT_CID_819x_HP:
-		pcipriv->ledctl.bled_opendrain = true;
+		pcipriv->ledctl.led_opendrain = true;
 		break;
 	case RT_CID_819x_Lenovo:
 	case RT_CID_DEFAULT:
@@ -1693,10 +1680,10 @@
 
 	rtlhal->version = _rtl92ce_read_chip_version(hw);
 	if (get_rf_type(rtlphy) == RF_1T1R)
-		rtlpriv->dm.brfpath_rxenable[0] = true;
+		rtlpriv->dm.rfpath_rxenable[0] = true;
 	else
-		rtlpriv->dm.brfpath_rxenable[0] =
-		    rtlpriv->dm.brfpath_rxenable[1] = true;
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
 	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("VersionID = 0x%4x\n",
 						rtlhal->version));
 	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
@@ -1725,18 +1712,18 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 
 	u32 ratr_value = (u32) mac->basic_rates;
-	u8 *p_mcsrate = mac->mcs;
+	u8 *mcsrate = mac->mcs;
 	u8 ratr_index = 0;
-	u8 b_nmode = mac->ht_enable;
+	u8 nmode = mac->ht_enable;
 	u8 mimo_ps = 1;
 	u16 shortgi_rate;
 	u32 tmp_ratr_value;
-	u8 b_curtxbw_40mhz = mac->bw_40;
-	u8 b_curshortgi_40mhz = mac->sgi_40;
-	u8 b_curshortgi_20mhz = mac->sgi_20;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
 	enum wireless_mode wirelessmode = mac->mode;
 
-	ratr_value |= EF2BYTE((*(u16 *) (p_mcsrate))) << 12;
+	ratr_value |= ((*(u16 *) (mcsrate))) << 12;
 
 	switch (wirelessmode) {
 	case WIRELESS_MODE_B:
@@ -1750,7 +1737,7 @@
 		break;
 	case WIRELESS_MODE_N_24G:
 	case WIRELESS_MODE_N_5G:
-		b_nmode = 1;
+		nmode = 1;
 		if (mimo_ps == 0) {
 			ratr_value &= 0x0007F005;
 		} else {
@@ -1776,9 +1763,8 @@
 
 	ratr_value &= 0x0FFFFFFF;
 
-	if (b_nmode && ((b_curtxbw_40mhz &&
-			 b_curshortgi_40mhz) || (!b_curtxbw_40mhz &&
-						 b_curshortgi_20mhz))) {
+	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) || (!curtxbw_40mhz &&
+		       curshortgi_20mhz))) {
 
 		ratr_value |= 0x10000000;
 		tmp_ratr_value = (ratr_value >> 12);
@@ -1806,11 +1792,11 @@
 	u32 ratr_bitmap = (u32) mac->basic_rates;
 	u8 *p_mcsrate = mac->mcs;
 	u8 ratr_index;
-	u8 b_curtxbw_40mhz = mac->bw_40;
-	u8 b_curshortgi_40mhz = mac->sgi_40;
-	u8 b_curshortgi_20mhz = mac->sgi_20;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
 	enum wireless_mode wirelessmode = mac->mode;
-	bool b_shortgi = false;
+	bool shortgi = false;
 	u8 rate_mask[5];
 	u8 macid = 0;
 	u8 mimops = 1;
@@ -1852,7 +1838,7 @@
 		} else {
 			if (rtlphy->rf_type == RF_1T2R ||
 			    rtlphy->rf_type == RF_1T1R) {
-				if (b_curtxbw_40mhz) {
+				if (curtxbw_40mhz) {
 					if (rssi_level == 1)
 						ratr_bitmap &= 0x000f0000;
 					else if (rssi_level == 2)
@@ -1868,7 +1854,7 @@
 						ratr_bitmap &= 0x000ff005;
 				}
 			} else {
-				if (b_curtxbw_40mhz) {
+				if (curtxbw_40mhz) {
 					if (rssi_level == 1)
 						ratr_bitmap &= 0x0f0f0000;
 					else if (rssi_level == 2)
@@ -1886,13 +1872,13 @@
 			}
 		}
 
-		if ((b_curtxbw_40mhz && b_curshortgi_40mhz) ||
-		    (!b_curtxbw_40mhz && b_curshortgi_20mhz)) {
+		if ((curtxbw_40mhz && curshortgi_40mhz) ||
+		    (!curtxbw_40mhz && curshortgi_20mhz)) {
 
 			if (macid == 0)
-				b_shortgi = true;
+				shortgi = true;
 			else if (macid == 1)
-				b_shortgi = false;
+				shortgi = false;
 		}
 		break;
 	default:
@@ -1906,9 +1892,9 @@
 	}
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG,
 		 ("ratr_bitmap :%x\n", ratr_bitmap));
-	*(u32 *)&rate_mask = EF4BYTE((ratr_bitmap & 0x0fffffff) |
-				       (ratr_index << 28));
-	rate_mask[4] = macid | (b_shortgi ? 0x20 : 0x00) | 0x80;
+	*(u32 *)&rate_mask = (ratr_bitmap & 0x0fffffff) |
+				       (ratr_index << 28);
+	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
 	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, "
 						 "ratr_val:%x, %x:%x:%x:%x:%x\n",
 						 ratr_index, ratr_bitmap,
@@ -1940,13 +1926,13 @@
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
 	u8 u1tmp;
-	bool b_actuallyset = false;
+	bool actuallyset = false;
 	unsigned long flag;
 
 	if ((rtlpci->up_first_time == 1) || (rtlpci->being_init_adapter))
 		return false;
 
-	if (ppsc->b_swrf_processing)
+	if (ppsc->swrf_processing)
 		return false;
 
 	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
@@ -1972,24 +1958,24 @@
 	u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
 	e_rfpowerstate_toset = (u1tmp & BIT(3)) ? ERFON : ERFOFF;
 
-	if ((ppsc->b_hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
+	if ((ppsc->hwradiooff == true) && (e_rfpowerstate_toset == ERFON)) {
 		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 			 ("GPIOChangeRF  - HW Radio ON, RF ON\n"));
 
 		e_rfpowerstate_toset = ERFON;
-		ppsc->b_hwradiooff = false;
-		b_actuallyset = true;
-	} else if ((ppsc->b_hwradiooff == false)
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((ppsc->hwradiooff == false)
 		   && (e_rfpowerstate_toset == ERFOFF)) {
 		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
 			 ("GPIOChangeRF  - HW Radio OFF, RF OFF\n"));
 
 		e_rfpowerstate_toset = ERFOFF;
-		ppsc->b_hwradiooff = true;
-		b_actuallyset = true;
+		ppsc->hwradiooff = true;
+		actuallyset = true;
 	}
 
-	if (b_actuallyset) {
+	if (actuallyset) {
 		if (e_rfpowerstate_toset == ERFON) {
 			if ((ppsc->reg_rfps_level & RT_RF_OFF_LEVL_ASPM) &&
 			    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM)) {
@@ -2028,7 +2014,7 @@
 	}
 
 	*valid = 1;
-	return !ppsc->b_hwradiooff;
+	return !ppsc->hwradiooff;
 
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,8 @@
 #ifndef __RTL92CE_HW_H__
 #define __RTL92CE_HW_H__
 
+#define H2C_RA_MASK	6
+
 void rtl92ce_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
 void rtl92ce_read_eeprom_info(struct ieee80211_hw *hw);
 void rtl92ce_interrupt_recognized(struct ieee80211_hw *hw,
@@ -53,5 +55,14 @@
 void rtl92ce_set_key(struct ieee80211_hw *hw, u32 key_index,
 		     u8 *p_macaddr, bool is_group, u8 enc_algo,
 		     bool is_wepkey, bool clear_all);
+bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished);
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+int rtl92c_download_fw(struct ieee80211_hw *hw);
+void rtl92c_firmware_selfreset(struct ieee80211_hw *hw);
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
+bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/led.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/led.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/led.c	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
 			 ("switch case not process\n"));
 		break;
 	}
-	pled->b_ledon = true;
+	pled->ledon = true;
 }
 
 void rtl92ce_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
@@ -76,7 +76,7 @@
 		break;
 	case LED_PIN_LED0:
 		ledcfg &= 0xf0;
-		if (pcipriv->ledctl.bled_opendrain == true)
+		if (pcipriv->ledctl.led_opendrain == true)
 			rtl_write_byte(rtlpriv, REG_LEDCFG2,
 				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
 		else
@@ -92,7 +92,7 @@
 			 ("switch case not process\n"));
 		break;
 	}
-	pled->b_ledon = false;
+	pled->ledon = false;
 }
 
 void rtl92ce_init_sw_leds(struct ieee80211_hw *hw)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,5 @@
 rtl8192ce-objs :=		\
 		dm.o		\
-		fw.o		\
 		hw.o		\
 		led.o		\
 		phy.o		\
@@ -10,3 +9,5 @@
 		trx.o
 
 obj-$(CONFIG_RTL8192CE) += rtl8192ce.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,89 +32,13 @@
 #include "../ps.h"
 #include "reg.h"
 #include "def.h"
+#include "hw.h"
 #include "phy.h"
 #include "rf.h"
 #include "dm.h"
 #include "table.h"
 
-static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
-					 enum radio_path rfpath, u32 offset);
-static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
-					   enum radio_path rfpath, u32 offset,
-					   u32 data);
-static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
-				      enum radio_path rfpath, u32 offset);
-static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
-					enum radio_path rfpath, u32 offset,
-					u32 data);
-static u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
-static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
-static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
-static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
-						  u8 configtype);
-static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
-						    u8 configtype);
-static void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
-static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
-					     u32 cmdtableidx, u32 cmdtablesz,
-					     enum swchnlcmd_id cmdid, u32 para1,
-					     u32 para2, u32 msdelay);
-static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
-					     u8 channel, u8 *stage, u8 *step,
-					     u32 *delay);
-static u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
-				       enum wireless_mode wirelessmode,
-				       long power_indbm);
-static bool _rtl92c_phy_config_rf_external_pa(struct ieee80211_hw *hw,
-					      enum radio_path rfpath);
-static long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
-					 enum wireless_mode wirelessmode,
-					 u8 txpwridx);
-u32 rtl92c_phy_query_bb_reg(struct ieee80211_hw *hw, u32 regaddr, u32 bitmask)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 returnvalue, originalvalue, bitshift;
-
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
-					       "bitmask(%#x)\n", regaddr,
-					       bitmask));
-	originalvalue = rtl_read_dword(rtlpriv, regaddr);
-	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
-	returnvalue = (originalvalue & bitmask) >> bitshift;
-
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("BBR MASK=0x%x "
-					       "Addr[0x%x]=0x%x\n", bitmask,
-					       regaddr, originalvalue));
-
-	return returnvalue;
-
-}
-
-void rtl92c_phy_set_bb_reg(struct ieee80211_hw *hw,
-			   u32 regaddr, u32 bitmask, u32 data)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 originalvalue, bitshift;
-
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
-					       " data(%#x)\n", regaddr, bitmask,
-					       data));
-
-	if (bitmask != MASKDWORD) {
-		originalvalue = rtl_read_dword(rtlpriv, regaddr);
-		bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
-		data = ((originalvalue & (~bitmask)) | (data << bitshift));
-	}
-
-	rtl_write_dword(rtlpriv, regaddr, data);
-
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), bitmask(%#x),"
-					       " data(%#x)\n", regaddr, bitmask,
-					       data));
-
-}
-
-u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
+u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw,
 			    enum radio_path rfpath, u32 regaddr, u32 bitmask)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -149,7 +73,7 @@
 	return readback_value;
 }
 
-void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
+void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
 			   enum radio_path rfpath,
 			   u32 regaddr, u32 bitmask, u32 data)
 {
@@ -197,137 +121,25 @@
 					       bitmask, data, rfpath));
 }
 
-static u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
-					 enum radio_path rfpath, u32 offset)
-{
-	RT_ASSERT(false, ("deprecated!\n"));
-	return 0;
-}
-
-static void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
-					   enum radio_path rfpath, u32 offset,
-					   u32 data)
-{
-	RT_ASSERT(false, ("deprecated!\n"));
-}
-
-static u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
-				      enum radio_path rfpath, u32 offset)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
-	u32 newoffset;
-	u32 tmplong, tmplong2;
-	u8 rfpi_enable = 0;
-	u32 retvalue;
-
-	offset &= 0x3f;
-	newoffset = offset;
-	if (RT_CANNOT_IO(hw)) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("return all one\n"));
-		return 0xFFFFFFFF;
-	}
-	tmplong = rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD);
-	if (rfpath == RF90_PATH_A)
-		tmplong2 = tmplong;
-	else
-		tmplong2 = rtl_get_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD);
-	tmplong2 = (tmplong2 & (~BLSSIREADADDRESS)) |
-	    (newoffset << 23) | BLSSIREADEDGE;
-	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
-		      tmplong & (~BLSSIREADEDGE));
-	mdelay(1);
-	rtl_set_bbreg(hw, pphyreg->rfhssi_para2, MASKDWORD, tmplong2);
-	mdelay(1);
-	rtl_set_bbreg(hw, RFPGA0_XA_HSSIPARAMETER2, MASKDWORD,
-		      tmplong | BLSSIREADEDGE);
-	mdelay(1);
-	if (rfpath == RF90_PATH_A)
-		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XA_HSSIPARAMETER1,
-						 BIT(8));
-	else if (rfpath == RF90_PATH_B)
-		rfpi_enable = (u8) rtl_get_bbreg(hw, RFPGA0_XB_HSSIPARAMETER1,
-						 BIT(8));
-	if (rfpi_enable)
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readbackpi,
-					 BLSSIREADBACKDATA);
-	else
-		retvalue = rtl_get_bbreg(hw, pphyreg->rflssi_readback,
-					 BLSSIREADBACKDATA);
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFR-%d Addr[0x%x]=0x%x\n",
-					       rfpath, pphyreg->rflssi_readback,
-					       retvalue));
-	return retvalue;
-}
-
-static void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
-					enum radio_path rfpath, u32 offset,
-					u32 data)
-{
-	u32 data_and_addr;
-	u32 newoffset;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct bb_reg_def *pphyreg = &rtlphy->phyreg_def[rfpath];
-
-	if (RT_CANNOT_IO(hw)) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("stop\n"));
-		return;
-	}
-	offset &= 0x3f;
-	newoffset = offset;
-	data_and_addr = ((newoffset << 20) | (data & 0x000fffff)) & 0x0fffffff;
-	rtl_set_bbreg(hw, pphyreg->rf3wire_offset, MASKDWORD, data_and_addr);
-	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("RFW-%d Addr[0x%x]=0x%x\n",
-					       rfpath, pphyreg->rf3wire_offset,
-					       data_and_addr));
-}
-
-static u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask)
-{
-	u32 i;
-
-	for (i = 0; i <= 31; i++) {
-		if (((bitmask >> i) & 0x1) == 1)
-			break;
-	}
-	return i;
-}
-
-static void _rtl92c_phy_bb_config_1t(struct ieee80211_hw *hw)
-{
-	rtl_set_bbreg(hw, RFPGA0_TXINFO, 0x3, 0x2);
-	rtl_set_bbreg(hw, RFPGA1_TXINFO, 0x300033, 0x200022);
-	rtl_set_bbreg(hw, RCCK0_AFESETTING, MASKBYTE3, 0x45);
-	rtl_set_bbreg(hw, ROFDM0_TRXPATHENABLE, MASKBYTE0, 0x23);
-	rtl_set_bbreg(hw, ROFDM0_AGCPARAMETER1, 0x30, 0x1);
-	rtl_set_bbreg(hw, 0xe74, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe78, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe7c, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe80, 0x0c000000, 0x2);
-	rtl_set_bbreg(hw, 0xe88, 0x0c000000, 0x2);
-}
-
-bool rtl92c_phy_mac_config(struct ieee80211_hw *hw)
+bool rtl92ce_phy_mac_config(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
 	bool is92c = IS_92C_SERIAL(rtlhal->version);
-	bool rtstatus = _rtl92c_phy_config_mac_with_headerfile(hw);
+	bool rtstatus = _rtl92ce_phy_config_mac_with_headerfile(hw);
 
 	if (is92c)
 		rtl_write_byte(rtlpriv, 0x14, 0x71);
 	return rtstatus;
 }
 
-bool rtl92c_phy_bb_config(struct ieee80211_hw *hw)
+bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw)
 {
 	bool rtstatus = true;
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u16 regval;
 	u32 regvaldw;
-	u8 b_reg_hwparafile = 1;
+	u8 reg_hwparafile = 1;
 
 	_rtl92c_phy_init_bb_rf_register_definition(hw);
 	regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
@@ -342,56 +154,12 @@
 	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
 	regvaldw = rtl_read_dword(rtlpriv, REG_LEDCFG0);
 	rtl_write_dword(rtlpriv, REG_LEDCFG0, regvaldw | BIT(23));
-	if (b_reg_hwparafile == 1)
+	if (reg_hwparafile == 1)
 		rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
 	return rtstatus;
 }
 
-bool rtl92c_phy_rf_config(struct ieee80211_hw *hw)
-{
-	return rtl92c_phy_rf6052_config(hw);
-}
-
-static bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	bool rtstatus;
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("==>\n"));
-	rtstatus = _rtl92c_phy_config_bb_with_headerfile(hw,
-						 BASEBAND_CONFIG_PHY_REG);
-	if (rtstatus != true) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("Write BB Reg Fail!!"));
-		return false;
-	}
-	if (rtlphy->rf_type == RF_1T2R) {
-		_rtl92c_phy_bb_config_1t(hw);
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Config to 1T!!\n"));
-	}
-	if (rtlefuse->autoload_failflag == false) {
-		rtlphy->pwrgroup_cnt = 0;
-		rtstatus = _rtl92c_phy_config_bb_with_pgheaderfile(hw,
-						   BASEBAND_CONFIG_PHY_REG);
-	}
-	if (rtstatus != true) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("BB_PG Reg Fail!!"));
-		return false;
-	}
-	rtstatus = _rtl92c_phy_config_bb_with_headerfile(hw,
-						 BASEBAND_CONFIG_AGC_TAB);
-	if (rtstatus != true) {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("AGC Table Fail\n"));
-		return false;
-	}
-	rtlphy->bcck_high_power = (bool) (rtl_get_bbreg(hw,
-						RFPGA0_XA_HSSIPARAMETER2,
-						0x200));
-	return true;
-}
-
-static bool _rtl92c_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
+bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	u32 i;
@@ -408,11 +176,7 @@
 	return true;
 }
 
-void rtl92c_phy_config_bb_external_pa(struct ieee80211_hw *hw)
-{
-}
-
-static bool _rtl92c_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
 						  u8 configtype)
 {
 	int i;
@@ -456,7 +220,6 @@
 				  phy_regarray_table[i],
 				  phy_regarray_table[i + 1]));
 		}
-		rtl92c_phy_config_bb_external_pa(hw);
 	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
 		for (i = 0; i < agctab_arraylen; i = i + 2) {
 			rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
@@ -472,175 +235,7 @@
 	return true;
 }
 
-static void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
-						   u32 regaddr, u32 bitmask,
-						   u32 data)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	if (regaddr == RTXAGC_A_RATE18_06) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][0] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][0] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][0]));
-	}
-	if (regaddr == RTXAGC_A_RATE54_24) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][1] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][1] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][1]));
-	}
-	if (regaddr == RTXAGC_A_CCK1_MCS32) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][6] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][6] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][6]));
-	}
-	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0xffffff00) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][7] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][7] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][7]));
-	}
-	if (regaddr == RTXAGC_A_MCS03_MCS00) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][2] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][2] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][2]));
-	}
-	if (regaddr == RTXAGC_A_MCS07_MCS04) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][3] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][3] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][3]));
-	}
-	if (regaddr == RTXAGC_A_MCS11_MCS08) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][4] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][4] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][4]));
-	}
-	if (regaddr == RTXAGC_A_MCS15_MCS12) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][5] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][5] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][5]));
-	}
-	if (regaddr == RTXAGC_B_RATE18_06) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][8] =
-		    data;
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][8] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][8]));
-	}
-	if (regaddr == RTXAGC_B_RATE54_24) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][9] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][9] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][9]));
-	}
-
-	if (regaddr == RTXAGC_B_CCK1_55_MCS32) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][14] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][14] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][14]));
-	}
-
-	if (regaddr == RTXAGC_B_CCK11_A_CCK2_11 && bitmask == 0x000000ff) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][15] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][15] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][15]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS03_MCS00) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][10] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][10] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][10]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS07_MCS04) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][11] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][11] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][11]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS11_MCS08) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][12] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][12] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][12]));
-	}
-
-	if (regaddr == RTXAGC_B_MCS15_MCS12) {
-		rtlphy->mcs_txpwrlevel_origoffset[rtlphy->pwrgroup_cnt][13] =
-		    data;
-
-		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-			 ("MCSTxPowerLevelOriginalOffset[%d][13] = 0x%x\n",
-			  rtlphy->pwrgroup_cnt,
-			  rtlphy->mcs_txpwrlevel_origoffset[rtlphy->
-							    pwrgroup_cnt][13]));
-
-		rtlphy->pwrgroup_cnt++;
-	}
-}
-
-static bool _rtl92c_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
 						    u8 configtype)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -679,13 +274,7 @@
 	return true;
 }
 
-static bool _rtl92c_phy_config_rf_external_pa(struct ieee80211_hw *hw,
-					      enum radio_path rfpath)
-{
-	return true;
-}
-
-bool rtl92c_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
 					  enum radio_path rfpath)
 {
 
@@ -740,7 +329,6 @@
 				udelay(1);
 			}
 		}
-		_rtl92c_phy_config_rf_external_pa(hw, rfpath);
 		break;
 	case RF90_PATH_B:
 		for (i = 0; i < radiob_arraylen; i = i + 2) {
@@ -776,346 +364,7 @@
 	return true;
 }
 
-void rtl92c_phy_get_hw_reg_originalvalue(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	rtlphy->default_initialgain[0] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XAAGCCORE1, MASKBYTE0);
-	rtlphy->default_initialgain[1] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XBAGCCORE1, MASKBYTE0);
-	rtlphy->default_initialgain[2] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XCAGCCORE1, MASKBYTE0);
-	rtlphy->default_initialgain[3] =
-	    (u8) rtl_get_bbreg(hw, ROFDM0_XDAGCCORE1, MASKBYTE0);
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-		 ("Default initial gain (c50=0x%x, "
-		  "c58=0x%x, c60=0x%x, c68=0x%x\n",
-		  rtlphy->default_initialgain[0],
-		  rtlphy->default_initialgain[1],
-		  rtlphy->default_initialgain[2],
-		  rtlphy->default_initialgain[3]));
-
-	rtlphy->framesync = (u8) rtl_get_bbreg(hw,
-					       ROFDM0_RXDETECTOR3, MASKBYTE0);
-	rtlphy->framesync_c34 = rtl_get_bbreg(hw,
-					      ROFDM0_RXDETECTOR2, MASKDWORD);
-
-	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
-		 ("Default framesync (0x%x) = 0x%x\n",
-		  ROFDM0_RXDETECTOR3, rtlphy->framesync));
-}
-
-static void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfintfs = RFPGA0_XAB_RFINTERFACESW;
-	rtlphy->phyreg_def[RF90_PATH_B].rfintfs = RFPGA0_XAB_RFINTERFACESW;
-	rtlphy->phyreg_def[RF90_PATH_C].rfintfs = RFPGA0_XCD_RFINTERFACESW;
-	rtlphy->phyreg_def[RF90_PATH_D].rfintfs = RFPGA0_XCD_RFINTERFACESW;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfintfi = RFPGA0_XAB_RFINTERFACERB;
-	rtlphy->phyreg_def[RF90_PATH_B].rfintfi = RFPGA0_XAB_RFINTERFACERB;
-	rtlphy->phyreg_def[RF90_PATH_C].rfintfi = RFPGA0_XCD_RFINTERFACERB;
-	rtlphy->phyreg_def[RF90_PATH_D].rfintfi = RFPGA0_XCD_RFINTERFACERB;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfintfo = RFPGA0_XA_RFINTERFACEOE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfintfo = RFPGA0_XB_RFINTERFACEOE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfintfe = RFPGA0_XA_RFINTERFACEOE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfintfe = RFPGA0_XB_RFINTERFACEOE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rf3wire_offset =
-	    RFPGA0_XA_LSSIPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_B].rf3wire_offset =
-	    RFPGA0_XB_LSSIPARAMETER;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_select = rFPGA0_XAB_RFPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_select = rFPGA0_XAB_RFPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_select = rFPGA0_XCD_RFPARAMETER;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_select = rFPGA0_XCD_RFPARAMETER;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rftxgain_stage = RFPGA0_TXGAINSTAGE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftxgain_stage = RFPGA0_TXGAINSTAGE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftxgain_stage = RFPGA0_TXGAINSTAGE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftxgain_stage = RFPGA0_TXGAINSTAGE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para1 = RFPGA0_XA_HSSIPARAMETER1;
-	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para1 = RFPGA0_XB_HSSIPARAMETER1;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfhssi_para2 = RFPGA0_XA_HSSIPARAMETER2;
-	rtlphy->phyreg_def[RF90_PATH_B].rfhssi_para2 = RFPGA0_XB_HSSIPARAMETER2;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_B].rfswitch_control =
-	    RFPGA0_XAB_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_C].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
-	rtlphy->phyreg_def[RF90_PATH_D].rfswitch_control =
-	    RFPGA0_XCD_SWITCHCONTROL;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control1 = ROFDM0_XAAGCCORE1;
-	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control1 = ROFDM0_XBAGCCORE1;
-	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control1 = ROFDM0_XCAGCCORE1;
-	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control1 = ROFDM0_XDAGCCORE1;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfagc_control2 = ROFDM0_XAAGCCORE2;
-	rtlphy->phyreg_def[RF90_PATH_B].rfagc_control2 = ROFDM0_XBAGCCORE2;
-	rtlphy->phyreg_def[RF90_PATH_C].rfagc_control2 = ROFDM0_XCAGCCORE2;
-	rtlphy->phyreg_def[RF90_PATH_D].rfagc_control2 = ROFDM0_XDAGCCORE2;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfrxiq_imbalance =
-	    ROFDM0_XARXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrxiq_imbalance =
-	    ROFDM0_XBRXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrxiq_imbalance =
-	    ROFDM0_XCRXIQIMBANLANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrxiq_imbalance =
-	    ROFDM0_XDRXIQIMBALANCE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rfrx_afe = ROFDM0_XARXAFE;
-	rtlphy->phyreg_def[RF90_PATH_B].rfrx_afe = ROFDM0_XBRXAFE;
-	rtlphy->phyreg_def[RF90_PATH_C].rfrx_afe = ROFDM0_XCRXAFE;
-	rtlphy->phyreg_def[RF90_PATH_D].rfrx_afe = ROFDM0_XDRXAFE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rftxiq_imbalance =
-	    ROFDM0_XATXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftxiq_imbalance =
-	    ROFDM0_XBTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftxiq_imbalance =
-	    ROFDM0_XCTXIQIMBALANCE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftxiq_imbalance =
-	    ROFDM0_XDTXIQIMBALANCE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rftx_afe = ROFDM0_XATXAFE;
-	rtlphy->phyreg_def[RF90_PATH_B].rftx_afe = ROFDM0_XBTXAFE;
-	rtlphy->phyreg_def[RF90_PATH_C].rftx_afe = ROFDM0_XCTXAFE;
-	rtlphy->phyreg_def[RF90_PATH_D].rftx_afe = ROFDM0_XDTXAFE;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readback =
-	    RFPGA0_XA_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readback =
-	    RFPGA0_XB_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_C].rflssi_readback =
-	    RFPGA0_XC_LSSIREADBACK;
-	rtlphy->phyreg_def[RF90_PATH_D].rflssi_readback =
-	    RFPGA0_XD_LSSIREADBACK;
-
-	rtlphy->phyreg_def[RF90_PATH_A].rflssi_readbackpi =
-	    TRANSCEIVEA_HSPI_READBACK;
-	rtlphy->phyreg_def[RF90_PATH_B].rflssi_readbackpi =
-	    TRANSCEIVEB_HSPI_READBACK;
-
-}
-
-void rtl92c_phy_get_txpower_level(struct ieee80211_hw *hw, long *powerlevel)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 txpwr_level;
-	long txpwr_dbm;
-
-	txpwr_level = rtlphy->cur_cck_txpwridx;
-	txpwr_dbm = _rtl92c_phy_txpwr_idx_to_dbm(hw,
-						 WIRELESS_MODE_B, txpwr_level);
-	txpwr_level = rtlphy->cur_ofdm24g_txpwridx +
-	    rtlefuse->legacy_ht_txpowerdiff;
-	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
-					 WIRELESS_MODE_G,
-					 txpwr_level) > txpwr_dbm)
-		txpwr_dbm =
-		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_G,
-						 txpwr_level);
-	txpwr_level = rtlphy->cur_ofdm24g_txpwridx;
-	if (_rtl92c_phy_txpwr_idx_to_dbm(hw,
-					 WIRELESS_MODE_N_24G,
-					 txpwr_level) > txpwr_dbm)
-		txpwr_dbm =
-		    _rtl92c_phy_txpwr_idx_to_dbm(hw, WIRELESS_MODE_N_24G,
-						 txpwr_level);
-	*powerlevel = txpwr_dbm;
-}
-
-static void _rtl92c_get_txpower_index(struct ieee80211_hw *hw, u8 channel,
-				      u8 *cckpowerlevel, u8 *ofdmpowerlevel)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 index = (channel - 1);
-
-	cckpowerlevel[RF90_PATH_A] =
-	    rtlefuse->txpwrlevel_cck[RF90_PATH_A][index];
-	cckpowerlevel[RF90_PATH_B] =
-	    rtlefuse->txpwrlevel_cck[RF90_PATH_B][index];
-	if (get_rf_type(rtlphy) == RF_1T2R || get_rf_type(rtlphy) == RF_1T1R) {
-		ofdmpowerlevel[RF90_PATH_A] =
-		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_A][index];
-		ofdmpowerlevel[RF90_PATH_B] =
-		    rtlefuse->txpwrlevel_ht40_1s[RF90_PATH_B][index];
-	} else if (get_rf_type(rtlphy) == RF_2T2R) {
-		ofdmpowerlevel[RF90_PATH_A] =
-		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_A][index];
-		ofdmpowerlevel[RF90_PATH_B] =
-		    rtlefuse->txpwrlevel_ht40_2s[RF90_PATH_B][index];
-	}
-}
-
-static void _rtl92c_ccxpower_index_check(struct ieee80211_hw *hw,
-					 u8 channel, u8 *cckpowerlevel,
-					 u8 *ofdmpowerlevel)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	rtlphy->cur_cck_txpwridx = cckpowerlevel[0];
-	rtlphy->cur_ofdm24g_txpwridx = ofdmpowerlevel[0];
-}
-
-void rtl92c_phy_set_txpower_level(struct ieee80211_hw *hw, u8 channel)
-{
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 cckpowerlevel[2], ofdmpowerlevel[2];
-
-	if (rtlefuse->b_txpwr_fromeprom == false)
-		return;
-	_rtl92c_get_txpower_index(hw, channel,
-				  &cckpowerlevel[0], &ofdmpowerlevel[0]);
-	_rtl92c_ccxpower_index_check(hw,
-				     channel, &cckpowerlevel[0],
-				     &ofdmpowerlevel[0]);
-	rtl92c_phy_rf6052_set_cck_txpower(hw, &cckpowerlevel[0]);
-	rtl92c_phy_rf6052_set_ofdm_txpower(hw, &ofdmpowerlevel[0], channel);
-}
-
-bool rtl92c_phy_update_txpower_dbm(struct ieee80211_hw *hw, long power_indbm)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-	u8 idx;
-	u8 rf_path;
-
-	u8 ccktxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
-						      WIRELESS_MODE_B,
-						      power_indbm);
-	u8 ofdmtxpwridx = _rtl92c_phy_dbm_to_txpwr_Idx(hw,
-						       WIRELESS_MODE_N_24G,
-						       power_indbm);
-	if (ofdmtxpwridx - rtlefuse->legacy_ht_txpowerdiff > 0)
-		ofdmtxpwridx -= rtlefuse->legacy_ht_txpowerdiff;
-	else
-		ofdmtxpwridx = 0;
-	RT_TRACE(rtlpriv, COMP_TXAGC, DBG_TRACE,
-		 ("%lx dBm, ccktxpwridx = %d, ofdmtxpwridx = %d\n",
-		  power_indbm, ccktxpwridx, ofdmtxpwridx));
-	for (idx = 0; idx < 14; idx++) {
-		for (rf_path = 0; rf_path < 2; rf_path++) {
-			rtlefuse->txpwrlevel_cck[rf_path][idx] = ccktxpwridx;
-			rtlefuse->txpwrlevel_ht40_1s[rf_path][idx] =
-			    ofdmtxpwridx;
-			rtlefuse->txpwrlevel_ht40_2s[rf_path][idx] =
-			    ofdmtxpwridx;
-		}
-	}
-	rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
-	return true;
-}
-
-void rtl92c_phy_set_beacon_hw_reg(struct ieee80211_hw *hw, u16 beaconinterval)
-{
-}
-
-static u8 _rtl92c_phy_dbm_to_txpwr_Idx(struct ieee80211_hw *hw,
-				       enum wireless_mode wirelessmode,
-				       long power_indbm)
-{
-	u8 txpwridx;
-	long offset;
-
-	switch (wirelessmode) {
-	case WIRELESS_MODE_B:
-		offset = -7;
-		break;
-	case WIRELESS_MODE_G:
-	case WIRELESS_MODE_N_24G:
-		offset = -8;
-		break;
-	default:
-		offset = -8;
-		break;
-	}
-
-	if ((power_indbm - offset) > 0)
-		txpwridx = (u8) ((power_indbm - offset) * 2);
-	else
-		txpwridx = 0;
-
-	if (txpwridx > MAX_TXPWR_IDX_NMODE_92S)
-		txpwridx = MAX_TXPWR_IDX_NMODE_92S;
-
-	return txpwridx;
-}
-
-static long _rtl92c_phy_txpwr_idx_to_dbm(struct ieee80211_hw *hw,
-					 enum wireless_mode wirelessmode,
-					 u8 txpwridx)
-{
-	long offset;
-	long pwrout_dbm;
-
-	switch (wirelessmode) {
-	case WIRELESS_MODE_B:
-		offset = -7;
-		break;
-	case WIRELESS_MODE_G:
-	case WIRELESS_MODE_N_24G:
-		offset = -8;
-		break;
-	default:
-		offset = -8;
-		break;
-	}
-	pwrout_dbm = txpwridx / 2 + offset;
-	return pwrout_dbm;
-}
-
-void rtl92c_phy_scan_operation_backup(struct ieee80211_hw *hw, u8 operation)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	enum io_type iotype;
-
-	if (!is_hal_stop(rtlhal)) {
-		switch (operation) {
-		case SCAN_OPT_BACKUP:
-			iotype = IO_CMD_PAUSE_DM_BY_SCAN;
-			rtlpriv->cfg->ops->set_hw_reg(hw,
-						      HW_VAR_IO_CMD,
-						      (u8 *)&iotype);
-
-			break;
-		case SCAN_OPT_RESTORE:
-			iotype = IO_CMD_RESUME_DM_BY_SCAN;
-			rtlpriv->cfg->ops->set_hw_reg(hw,
-						      HW_VAR_IO_CMD,
-						      (u8 *)&iotype);
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("Unknown Scan Backup operation.\n"));
-			break;
-		}
-	}
-}
-
-void rtl92c_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
+void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
@@ -1183,645 +432,7 @@
 	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
 }
 
-void rtl92c_phy_set_bw_mode(struct ieee80211_hw *hw,
-			    enum nl80211_channel_type ch_type)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	u8 tmp_bw = rtlphy->current_chan_bw;
-
-	if (rtlphy->set_bwmode_inprogress)
-		return;
-	rtlphy->set_bwmode_inprogress = true;
-	if ((!is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw)))
-		rtl92c_phy_set_bw_mode_callback(hw);
-	else {
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
-			 ("FALSE driver sleep or unload\n"));
-		rtlphy->set_bwmode_inprogress = false;
-		rtlphy->current_chan_bw = tmp_bw;
-	}
-}
-
-void rtl92c_phy_sw_chnl_callback(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	u32 delay;
-
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
-		 ("switch to channel%d\n", rtlphy->current_channel));
-	if (is_hal_stop(rtlhal))
-		return;
-	do {
-		if (!rtlphy->sw_chnl_inprogress)
-			break;
-		if (!_rtl92c_phy_sw_chnl_step_by_step
-		    (hw, rtlphy->current_channel, &rtlphy->sw_chnl_stage,
-		     &rtlphy->sw_chnl_step, &delay)) {
-			if (delay > 0)
-				mdelay(delay);
-			else
-				continue;
-		} else
-			rtlphy->sw_chnl_inprogress = false;
-		break;
-	} while (true);
-	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
-}
-
-u8 rtl92c_phy_sw_chnl(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (rtlphy->sw_chnl_inprogress)
-		return 0;
-	if (rtlphy->set_bwmode_inprogress)
-		return 0;
-	RT_ASSERT((rtlphy->current_channel <= 14),
-		  ("WIRELESS_MODE_G but channel>14"));
-	rtlphy->sw_chnl_inprogress = true;
-	rtlphy->sw_chnl_stage = 0;
-	rtlphy->sw_chnl_step = 0;
-	if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
-		rtl92c_phy_sw_chnl_callback(hw);
-		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-			 ("sw_chnl_inprogress false schdule workitem\n"));
-		rtlphy->sw_chnl_inprogress = false;
-	} else {
-		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-			 ("sw_chnl_inprogress false driver sleep or"
-			  " unload\n"));
-		rtlphy->sw_chnl_inprogress = false;
-	}
-	return 1;
-}
-
-static bool _rtl92c_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw,
-					     u8 channel, u8 *stage, u8 *step,
-					     u32 *delay)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct swchnlcmd precommoncmd[MAX_PRECMD_CNT];
-	u32 precommoncmdcnt;
-	struct swchnlcmd postcommoncmd[MAX_POSTCMD_CNT];
-	u32 postcommoncmdcnt;
-	struct swchnlcmd rfdependcmd[MAX_RFDEPENDCMD_CNT];
-	u32 rfdependcmdcnt;
-	struct swchnlcmd *currentcmd = NULL;
-	u8 rfpath;
-	u8 num_total_rfpath = rtlphy->num_total_rfpath;
-
-	precommoncmdcnt = 0;
-	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
-					 MAX_PRECMD_CNT,
-					 CMDID_SET_TXPOWEROWER_LEVEL, 0, 0, 0);
-	_rtl92c_phy_set_sw_chnl_cmdarray(precommoncmd, precommoncmdcnt++,
-					 MAX_PRECMD_CNT, CMDID_END, 0, 0, 0);
-
-	postcommoncmdcnt = 0;
-
-	_rtl92c_phy_set_sw_chnl_cmdarray(postcommoncmd, postcommoncmdcnt++,
-					 MAX_POSTCMD_CNT, CMDID_END, 0, 0, 0);
-
-	rfdependcmdcnt = 0;
-
-	RT_ASSERT((channel >= 1 && channel <= 14),
-		  ("illegal channel for Zebra: %d\n", channel));
-
-	_rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
-					 MAX_RFDEPENDCMD_CNT, CMDID_RF_WRITEREG,
-					 RF_CHNLBW, channel, 10);
-
-	_rtl92c_phy_set_sw_chnl_cmdarray(rfdependcmd, rfdependcmdcnt++,
-					 MAX_RFDEPENDCMD_CNT, CMDID_END, 0, 0,
-					 0);
-
-	do {
-		switch (*stage) {
-		case 0:
-			currentcmd = &precommoncmd[*step];
-			break;
-		case 1:
-			currentcmd = &rfdependcmd[*step];
-			break;
-		case 2:
-			currentcmd = &postcommoncmd[*step];
-			break;
-		}
-
-		if (currentcmd->cmdid == CMDID_END) {
-			if ((*stage) == 2) {
-				return true;
-			} else {
-				(*stage)++;
-				(*step) = 0;
-				continue;
-			}
-		}
-
-		switch (currentcmd->cmdid) {
-		case CMDID_SET_TXPOWEROWER_LEVEL:
-			rtl92c_phy_set_txpower_level(hw, channel);
-			break;
-		case CMDID_WRITEPORT_ULONG:
-			rtl_write_dword(rtlpriv, currentcmd->para1,
-					currentcmd->para2);
-			break;
-		case CMDID_WRITEPORT_USHORT:
-			rtl_write_word(rtlpriv, currentcmd->para1,
-				       (u16) currentcmd->para2);
-			break;
-		case CMDID_WRITEPORT_UCHAR:
-			rtl_write_byte(rtlpriv, currentcmd->para1,
-				       (u8) currentcmd->para2);
-			break;
-		case CMDID_RF_WRITEREG:
-			for (rfpath = 0; rfpath < num_total_rfpath; rfpath++) {
-				rtlphy->rfreg_chnlval[rfpath] =
-				    ((rtlphy->rfreg_chnlval[rfpath] &
-				      0xfffffc00) | currentcmd->para2);
-
-				rtl_set_rfreg(hw, (enum radio_path)rfpath,
-					      currentcmd->para1,
-					      RFREG_OFFSET_MASK,
-					      rtlphy->rfreg_chnlval[rfpath]);
-			}
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-
-		break;
-	} while (true);
-
-	(*delay) = currentcmd->msdelay;
-	(*step)++;
-	return false;
-}
-
-static bool _rtl92c_phy_set_sw_chnl_cmdarray(struct swchnlcmd *cmdtable,
-					     u32 cmdtableidx, u32 cmdtablesz,
-					     enum swchnlcmd_id cmdid,
-					     u32 para1, u32 para2, u32 msdelay)
-{
-	struct swchnlcmd *pcmd;
-
-	if (cmdtable == NULL) {
-		RT_ASSERT(false, ("cmdtable cannot be NULL.\n"));
-		return false;
-	}
-
-	if (cmdtableidx >= cmdtablesz)
-		return false;
-
-	pcmd = cmdtable + cmdtableidx;
-	pcmd->cmdid = cmdid;
-	pcmd->para1 = para1;
-	pcmd->para2 = para2;
-	pcmd->msdelay = msdelay;
-	return true;
-}
-
-bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath)
-{
-	return true;
-}
-
-static u8 _rtl92c_phy_path_a_iqk(struct ieee80211_hw *hw, bool config_pathb)
-{
-	u32 reg_eac, reg_e94, reg_e9c, reg_ea4;
-	u8 result = 0x00;
-
-	rtl_set_bbreg(hw, 0xe30, MASKDWORD, 0x10008c1f);
-	rtl_set_bbreg(hw, 0xe34, MASKDWORD, 0x10008c1f);
-	rtl_set_bbreg(hw, 0xe38, MASKDWORD, 0x82140102);
-	rtl_set_bbreg(hw, 0xe3c, MASKDWORD,
-		      config_pathb ? 0x28160202 : 0x28160502);
-
-	if (config_pathb) {
-		rtl_set_bbreg(hw, 0xe50, MASKDWORD, 0x10008c22);
-		rtl_set_bbreg(hw, 0xe54, MASKDWORD, 0x10008c22);
-		rtl_set_bbreg(hw, 0xe58, MASKDWORD, 0x82140102);
-		rtl_set_bbreg(hw, 0xe5c, MASKDWORD, 0x28160202);
-	}
-
-	rtl_set_bbreg(hw, 0xe4c, MASKDWORD, 0x001028d1);
-	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf9000000);
-	rtl_set_bbreg(hw, 0xe48, MASKDWORD, 0xf8000000);
-
-	mdelay(IQK_DELAY_TIME);
-
-	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
-	reg_e94 = rtl_get_bbreg(hw, 0xe94, MASKDWORD);
-	reg_e9c = rtl_get_bbreg(hw, 0xe9c, MASKDWORD);
-	reg_ea4 = rtl_get_bbreg(hw, 0xea4, MASKDWORD);
-
-	if (!(reg_eac & BIT(28)) &&
-	    (((reg_e94 & 0x03FF0000) >> 16) != 0x142) &&
-	    (((reg_e9c & 0x03FF0000) >> 16) != 0x42))
-		result |= 0x01;
-	else
-		return result;
-
-	if (!(reg_eac & BIT(27)) &&
-	    (((reg_ea4 & 0x03FF0000) >> 16) != 0x132) &&
-	    (((reg_eac & 0x03FF0000) >> 16) != 0x36))
-		result |= 0x02;
-	return result;
-}
-
-static u8 _rtl92c_phy_path_b_iqk(struct ieee80211_hw *hw)
-{
-	u32 reg_eac, reg_eb4, reg_ebc, reg_ec4, reg_ecc;
-	u8 result = 0x00;
-
-	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000002);
-	rtl_set_bbreg(hw, 0xe60, MASKDWORD, 0x00000000);
-	mdelay(IQK_DELAY_TIME);
-	reg_eac = rtl_get_bbreg(hw, 0xeac, MASKDWORD);
-	reg_eb4 = rtl_get_bbreg(hw, 0xeb4, MASKDWORD);
-	reg_ebc = rtl_get_bbreg(hw, 0xebc, MASKDWORD);
-	reg_ec4 = rtl_get_bbreg(hw, 0xec4, MASKDWORD);
-	reg_ecc = rtl_get_bbreg(hw, 0xecc, MASKDWORD);
-	if (!(reg_eac & BIT(31)) &&
-	    (((reg_eb4 & 0x03FF0000) >> 16) != 0x142) &&
-	    (((reg_ebc & 0x03FF0000) >> 16) != 0x42))
-		result |= 0x01;
-	else
-		return result;
-
-	if (!(reg_eac & BIT(30)) &&
-	    (((reg_ec4 & 0x03FF0000) >> 16) != 0x132) &&
-	    (((reg_ecc & 0x03FF0000) >> 16) != 0x36))
-		result |= 0x02;
-	return result;
-}
-
-static void _rtl92c_phy_path_a_fill_iqk_matrix(struct ieee80211_hw *hw,
-					       bool b_iqk_ok, long result[][8],
-					       u8 final_candidate, bool btxonly)
-{
-	u32 oldval_0, x, tx0_a, reg;
-	long y, tx0_c;
-
-	if (final_candidate == 0xFF)
-		return;
-	else if (b_iqk_ok) {
-		oldval_0 = (rtl_get_bbreg(hw, ROFDM0_XATXIQIMBALANCE,
-					  MASKDWORD) >> 22) & 0x3FF;
-		x = result[final_candidate][0];
-		if ((x & 0x00000200) != 0)
-			x = x | 0xFFFFFC00;
-		tx0_a = (x * oldval_0) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x3FF, tx0_a);
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(31),
-			      ((x * oldval_0 >> 7) & 0x1));
-		y = result[final_candidate][1];
-		if ((y & 0x00000200) != 0)
-			y = y | 0xFFFFFC00;
-		tx0_c = (y * oldval_0) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XCTXAFE, 0xF0000000,
-			      ((tx0_c & 0x3C0) >> 6));
-		rtl_set_bbreg(hw, ROFDM0_XATXIQIMBALANCE, 0x003F0000,
-			      (tx0_c & 0x3F));
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(29),
-			      ((y * oldval_0 >> 7) & 0x1));
-		if (btxonly)
-			return;
-		reg = result[final_candidate][2];
-		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0x3FF, reg);
-		reg = result[final_candidate][3] & 0x3F;
-		rtl_set_bbreg(hw, ROFDM0_XARXIQIMBALANCE, 0xFC00, reg);
-		reg = (result[final_candidate][3] >> 6) & 0xF;
-		rtl_set_bbreg(hw, 0xca0, 0xF0000000, reg);
-	}
-}
-
-static void _rtl92c_phy_path_b_fill_iqk_matrix(struct ieee80211_hw *hw,
-					       bool b_iqk_ok, long result[][8],
-					       u8 final_candidate, bool btxonly)
-{
-	u32 oldval_1, x, tx1_a, reg;
-	long y, tx1_c;
-
-	if (final_candidate == 0xFF)
-		return;
-	else if (b_iqk_ok) {
-		oldval_1 = (rtl_get_bbreg(hw, ROFDM0_XBTXIQIMBALANCE,
-					  MASKDWORD) >> 22) & 0x3FF;
-		x = result[final_candidate][4];
-		if ((x & 0x00000200) != 0)
-			x = x | 0xFFFFFC00;
-		tx1_a = (x * oldval_1) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x3FF, tx1_a);
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(27),
-			      ((x * oldval_1 >> 7) & 0x1));
-		y = result[final_candidate][5];
-		if ((y & 0x00000200) != 0)
-			y = y | 0xFFFFFC00;
-		tx1_c = (y * oldval_1) >> 8;
-		rtl_set_bbreg(hw, ROFDM0_XDTXAFE, 0xF0000000,
-			      ((tx1_c & 0x3C0) >> 6));
-		rtl_set_bbreg(hw, ROFDM0_XBTXIQIMBALANCE, 0x003F0000,
-			      (tx1_c & 0x3F));
-		rtl_set_bbreg(hw, ROFDM0_ECCATHRESHOLD, BIT(25),
-			      ((y * oldval_1 >> 7) & 0x1));
-		if (btxonly)
-			return;
-		reg = result[final_candidate][6];
-		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0x3FF, reg);
-		reg = result[final_candidate][7] & 0x3F;
-		rtl_set_bbreg(hw, ROFDM0_XBRXIQIMBALANCE, 0xFC00, reg);
-		reg = (result[final_candidate][7] >> 6) & 0xF;
-		rtl_set_bbreg(hw, ROFDM0_AGCRSSITABLE, 0x0000F000, reg);
-	}
-}
-
-static void _rtl92c_phy_save_adda_registers(struct ieee80211_hw *hw,
-					    u32 *addareg, u32 *addabackup,
-					    u32 registernum)
-{
-	u32 i;
-
-	for (i = 0; i < registernum; i++)
-		addabackup[i] = rtl_get_bbreg(hw, addareg[i], MASKDWORD);
-}
-
-static void _rtl92c_phy_save_mac_registers(struct ieee80211_hw *hw,
-					   u32 *macreg, u32 *macbackup)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 i;
-
-	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
-		macbackup[i] = rtl_read_byte(rtlpriv, macreg[i]);
-	macbackup[i] = rtl_read_dword(rtlpriv, macreg[i]);
-}
-
-static void _rtl92c_phy_reload_adda_registers(struct ieee80211_hw *hw,
-					      u32 *addareg, u32 *addabackup,
-					      u32 regiesternum)
-{
-	u32 i;
-
-	for (i = 0; i < regiesternum; i++)
-		rtl_set_bbreg(hw, addareg[i], MASKDWORD, addabackup[i]);
-}
-
-static void _rtl92c_phy_reload_mac_registers(struct ieee80211_hw *hw,
-					     u32 *macreg, u32 *macbackup)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 i;
-
-	for (i = 0; i < (IQK_MAC_REG_NUM - 1); i++)
-		rtl_write_byte(rtlpriv, macreg[i], (u8) macbackup[i]);
-	rtl_write_dword(rtlpriv, macreg[i], macbackup[i]);
-}
-
-static void _rtl92c_phy_path_adda_on(struct ieee80211_hw *hw,
-				     u32 *addareg, bool is_patha_on, bool is2t)
-{
-	u32 pathOn;
-	u32 i;
-
-	pathOn = is_patha_on ? 0x04db25a4 : 0x0b1b25a4;
-	if (false == is2t) {
-		pathOn = 0x0bdb25a0;
-		rtl_set_bbreg(hw, addareg[0], MASKDWORD, 0x0b1b25a0);
-	} else {
-		rtl_set_bbreg(hw, addareg[0], MASKDWORD, pathOn);
-	}
-
-	for (i = 1; i < IQK_ADDA_REG_NUM; i++)
-		rtl_set_bbreg(hw, addareg[i], MASKDWORD, pathOn);
-}
-
-static void _rtl92c_phy_mac_setting_calibration(struct ieee80211_hw *hw,
-						u32 *macreg, u32 *macbackup)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	u32 i;
-
-	rtl_write_byte(rtlpriv, macreg[0], 0x3F);
-
-	for (i = 1; i < (IQK_MAC_REG_NUM - 1); i++)
-		rtl_write_byte(rtlpriv, macreg[i],
-			       (u8) (macbackup[i] & (~BIT(3))));
-	rtl_write_byte(rtlpriv, macreg[i], (u8) (macbackup[i] & (~BIT(5))));
-}
-
-static void _rtl92c_phy_path_a_standby(struct ieee80211_hw *hw)
-{
-	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x0);
-	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
-	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
-}
-
-static void _rtl92c_phy_pi_mode_switch(struct ieee80211_hw *hw, bool pi_mode)
-{
-	u32 mode;
-
-	mode = pi_mode ? 0x01000100 : 0x01000000;
-	rtl_set_bbreg(hw, 0x820, MASKDWORD, mode);
-	rtl_set_bbreg(hw, 0x828, MASKDWORD, mode);
-}
-
-static bool _rtl92c_phy_simularity_compare(struct ieee80211_hw *hw,
-					   long result[][8], u8 c1, u8 c2)
-{
-	u32 i, j, diff, simularity_bitmap, bound;
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	u8 final_candidate[2] = { 0xFF, 0xFF };
-	bool bresult = true, is2t = IS_92C_SERIAL(rtlhal->version);
-
-	if (is2t)
-		bound = 8;
-	else
-		bound = 4;
-
-	simularity_bitmap = 0;
-
-	for (i = 0; i < bound; i++) {
-		diff = (result[c1][i] > result[c2][i]) ?
-		    (result[c1][i] - result[c2][i]) :
-		    (result[c2][i] - result[c1][i]);
-
-		if (diff > MAX_TOLERANCE) {
-			if ((i == 2 || i == 6) && !simularity_bitmap) {
-				if (result[c1][i] + result[c1][i + 1] == 0)
-					final_candidate[(i / 4)] = c2;
-				else if (result[c2][i] + result[c2][i + 1] == 0)
-					final_candidate[(i / 4)] = c1;
-				else
-					simularity_bitmap = simularity_bitmap |
-					    (1 << i);
-			} else
-				simularity_bitmap =
-				    simularity_bitmap | (1 << i);
-		}
-	}
-
-	if (simularity_bitmap == 0) {
-		for (i = 0; i < (bound / 4); i++) {
-			if (final_candidate[i] != 0xFF) {
-				for (j = i * 4; j < (i + 1) * 4 - 2; j++)
-					result[3][j] =
-					    result[final_candidate[i]][j];
-				bresult = false;
-			}
-		}
-		return bresult;
-	} else if (!(simularity_bitmap & 0x0F)) {
-		for (i = 0; i < 4; i++)
-			result[3][i] = result[c1][i];
-		return false;
-	} else if (!(simularity_bitmap & 0xF0) && is2t) {
-		for (i = 4; i < 8; i++)
-			result[3][i] = result[c1][i];
-		return false;
-	} else {
-		return false;
-	}
-
-}
-
-static void _rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw,
-				     long result[][8], u8 t, bool is2t)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	u32 i;
-	u8 patha_ok, pathb_ok;
-	u32 adda_reg[IQK_ADDA_REG_NUM] = {
-		0x85c, 0xe6c, 0xe70, 0xe74,
-		0xe78, 0xe7c, 0xe80, 0xe84,
-		0xe88, 0xe8c, 0xed0, 0xed4,
-		0xed8, 0xedc, 0xee0, 0xeec
-	};
-
-	u32 iqk_mac_reg[IQK_MAC_REG_NUM] = {
-		0x522, 0x550, 0x551, 0x040
-	};
-
-	const u32 retrycount = 2;
-
-	u32 bbvalue;
-
-	if (t == 0) {
-		bbvalue = rtl_get_bbreg(hw, 0x800, MASKDWORD);
-
-		_rtl92c_phy_save_adda_registers(hw, adda_reg,
-						rtlphy->adda_backup, 16);
-		_rtl92c_phy_save_mac_registers(hw, iqk_mac_reg,
-					       rtlphy->iqk_mac_backup);
-	}
-	_rtl92c_phy_path_adda_on(hw, adda_reg, true, is2t);
-	if (t == 0) {
-		rtlphy->b_rfpi_enable = (u8) rtl_get_bbreg(hw,
-						   RFPGA0_XA_HSSIPARAMETER1,
-						   BIT(8));
-	}
-	if (!rtlphy->b_rfpi_enable)
-		_rtl92c_phy_pi_mode_switch(hw, true);
-	if (t == 0) {
-		rtlphy->reg_c04 = rtl_get_bbreg(hw, 0xc04, MASKDWORD);
-		rtlphy->reg_c08 = rtl_get_bbreg(hw, 0xc08, MASKDWORD);
-		rtlphy->reg_874 = rtl_get_bbreg(hw, 0x874, MASKDWORD);
-	}
-	rtl_set_bbreg(hw, 0xc04, MASKDWORD, 0x03a05600);
-	rtl_set_bbreg(hw, 0xc08, MASKDWORD, 0x000800e4);
-	rtl_set_bbreg(hw, 0x874, MASKDWORD, 0x22204000);
-	if (is2t) {
-		rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00010000);
-		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00010000);
-	}
-	_rtl92c_phy_mac_setting_calibration(hw, iqk_mac_reg,
-					    rtlphy->iqk_mac_backup);
-	rtl_set_bbreg(hw, 0xb68, MASKDWORD, 0x00080000);
-	if (is2t)
-		rtl_set_bbreg(hw, 0xb6c, MASKDWORD, 0x00080000);
-	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80800000);
-	rtl_set_bbreg(hw, 0xe40, MASKDWORD, 0x01007c00);
-	rtl_set_bbreg(hw, 0xe44, MASKDWORD, 0x01004800);
-	for (i = 0; i < retrycount; i++) {
-		patha_ok = _rtl92c_phy_path_a_iqk(hw, is2t);
-		if (patha_ok == 0x03) {
-			result[t][0] = (rtl_get_bbreg(hw, 0xe94, MASKDWORD) &
-					0x3FF0000) >> 16;
-			result[t][1] = (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) &
-					0x3FF0000) >> 16;
-			result[t][2] = (rtl_get_bbreg(hw, 0xea4, MASKDWORD) &
-					0x3FF0000) >> 16;
-			result[t][3] = (rtl_get_bbreg(hw, 0xeac, MASKDWORD) &
-					0x3FF0000) >> 16;
-			break;
-		} else if (i == (retrycount - 1) && patha_ok == 0x01)
-			result[t][0] = (rtl_get_bbreg(hw, 0xe94,
-						      MASKDWORD) & 0x3FF0000) >>
-						      16;
-		result[t][1] =
-		    (rtl_get_bbreg(hw, 0xe9c, MASKDWORD) & 0x3FF0000) >> 16;
-
-	}
-
-	if (is2t) {
-		_rtl92c_phy_path_a_standby(hw);
-		_rtl92c_phy_path_adda_on(hw, adda_reg, false, is2t);
-		for (i = 0; i < retrycount; i++) {
-			pathb_ok = _rtl92c_phy_path_b_iqk(hw);
-			if (pathb_ok == 0x03) {
-				result[t][4] = (rtl_get_bbreg(hw,
-						      0xeb4,
-						      MASKDWORD) &
-						0x3FF0000) >> 16;
-				result[t][5] =
-				    (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
-				     0x3FF0000) >> 16;
-				result[t][6] =
-				    (rtl_get_bbreg(hw, 0xec4, MASKDWORD) &
-				     0x3FF0000) >> 16;
-				result[t][7] =
-				    (rtl_get_bbreg(hw, 0xecc, MASKDWORD) &
-				     0x3FF0000) >> 16;
-				break;
-			} else if (i == (retrycount - 1) && pathb_ok == 0x01) {
-				result[t][4] = (rtl_get_bbreg(hw,
-						      0xeb4,
-						      MASKDWORD) &
-						0x3FF0000) >> 16;
-			}
-			result[t][5] = (rtl_get_bbreg(hw, 0xebc, MASKDWORD) &
-					0x3FF0000) >> 16;
-		}
-	}
-	rtl_set_bbreg(hw, 0xc04, MASKDWORD, rtlphy->reg_c04);
-	rtl_set_bbreg(hw, 0x874, MASKDWORD, rtlphy->reg_874);
-	rtl_set_bbreg(hw, 0xc08, MASKDWORD, rtlphy->reg_c08);
-	rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0);
-	rtl_set_bbreg(hw, 0x840, MASKDWORD, 0x00032ed3);
-	if (is2t)
-		rtl_set_bbreg(hw, 0x844, MASKDWORD, 0x00032ed3);
-	if (t != 0) {
-		if (!rtlphy->b_rfpi_enable)
-			_rtl92c_phy_pi_mode_switch(hw, false);
-		_rtl92c_phy_reload_adda_registers(hw, adda_reg,
-						  rtlphy->adda_backup, 16);
-		_rtl92c_phy_reload_mac_registers(hw, iqk_mac_reg,
-						 rtlphy->iqk_mac_backup);
-	}
-}
-
-static void _rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
 {
 	u8 tmpreg;
 	u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
@@ -1866,666 +477,6 @@
 	}
 }
 
-static void _rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw,
-				     char delta, bool is2t)
-{
-	/* This routine is deliberately dummied out for later fixes */
-#if 0
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
-
-	u32 reg_d[PATH_NUM];
-	u32 tmpreg, index, offset, path, i, pathbound = PATH_NUM, apkbound;
-
-	u32 bb_backup[APK_BB_REG_NUM];
-	u32 bb_reg[APK_BB_REG_NUM] = {
-		0x904, 0xc04, 0x800, 0xc08, 0x874
-	};
-	u32 bb_ap_mode[APK_BB_REG_NUM] = {
-		0x00000020, 0x00a05430, 0x02040000,
-		0x000800e4, 0x00204000
-	};
-	u32 bb_normal_ap_mode[APK_BB_REG_NUM] = {
-		0x00000020, 0x00a05430, 0x02040000,
-		0x000800e4, 0x22204000
-	};
-
-	u32 afe_backup[APK_AFE_REG_NUM];
-	u32 afe_reg[APK_AFE_REG_NUM] = {
-		0x85c, 0xe6c, 0xe70, 0xe74, 0xe78,
-		0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c,
-		0xed0, 0xed4, 0xed8, 0xedc, 0xee0,
-		0xeec
-	};
-
-	u32 mac_backup[IQK_MAC_REG_NUM];
-	u32 mac_reg[IQK_MAC_REG_NUM] = {
-		0x522, 0x550, 0x551, 0x040
-	};
-
-	u32 apk_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x0852c, 0x1852c, 0x5852c, 0x1852c, 0x5852c},
-		{0x2852e, 0x0852e, 0x3852e, 0x0852e, 0x0852e}
-	};
-
-	u32 apk_normal_rf_init_value[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x0852c, 0x0a52c, 0x3a52c, 0x5a52c, 0x5a52c},
-		{0x0852c, 0x0a52c, 0x5a52c, 0x5a52c, 0x5a52c}
-	};
-
-	u32 apk_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x52019, 0x52014, 0x52013, 0x5200f, 0x5208d},
-		{0x5201a, 0x52019, 0x52016, 0x52033, 0x52050}
-	};
-
-	u32 apk_normal_rf_value_0[PATH_NUM][APK_BB_REG_NUM] = {
-		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a},
-		{0x52019, 0x52017, 0x52010, 0x5200d, 0x5206a}
-	};
-
-	u32 afe_on_off[PATH_NUM] = {
-		0x04db25a4, 0x0b1b25a4
-	};
-
-	u32 apk_offset[PATH_NUM] = { 0xb68, 0xb6c };
-
-	u32 apk_normal_offset[PATH_NUM] = { 0xb28, 0xb98 };
-
-	u32 apk_value[PATH_NUM] = { 0x92fc0000, 0x12fc0000 };
-
-	u32 apk_normal_value[PATH_NUM] = { 0x92680000, 0x12680000 };
-
-	const char apk_delta_mapping[APK_BB_REG_NUM][13] = {
-		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-4, -3, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-6, -4, -2, -2, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6},
-		{-11, -9, -7, -5, -3, -1, 0, 0, 0, 0, 0, 0, 0}
-	};
-
-	const u32 apk_normal_setting_value_1[13] = {
-		0x01017018, 0xf7ed8f84, 0x1b1a1816, 0x2522201e, 0x322e2b28,
-		0x433f3a36, 0x5b544e49, 0x7b726a62, 0xa69a8f84, 0xdfcfc0b3,
-		0x12680000, 0x00880000, 0x00880000
-	};
-
-	const u32 apk_normal_setting_value_2[16] = {
-		0x01c7021d, 0x01670183, 0x01000123, 0x00bf00e2, 0x008d00a3,
-		0x0068007b, 0x004d0059, 0x003a0042, 0x002b0031, 0x001f0025,
-		0x0017001b, 0x00110014, 0x000c000f, 0x0009000b, 0x00070008,
-		0x00050006
-	};
-
-	const u32 apk_result[PATH_NUM][APK_BB_REG_NUM];
-
-	long bb_offset, delta_v, delta_offset;
-
-	if (!is2t)
-		pathbound = 1;
-
-	for (index = 0; index < PATH_NUM; index++) {
-		apk_offset[index] = apk_normal_offset[index];
-		apk_value[index] = apk_normal_value[index];
-		afe_on_off[index] = 0x6fdb25a4;
-	}
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		for (path = 0; path < pathbound; path++) {
-			apk_rf_init_value[path][index] =
-			    apk_normal_rf_init_value[path][index];
-			apk_rf_value_0[path][index] =
-			    apk_normal_rf_value_0[path][index];
-		}
-		bb_ap_mode[index] = bb_normal_ap_mode[index];
-
-		apkbound = 6;
-	}
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		if (index == 0)
-			continue;
-		bb_backup[index] = rtl_get_bbreg(hw, bb_reg[index], MASKDWORD);
-	}
-
-	_rtl92c_phy_save_mac_registers(hw, mac_reg, mac_backup);
-
-	_rtl92c_phy_save_adda_registers(hw, afe_reg, afe_backup, 16);
-
-	for (path = 0; path < pathbound; path++) {
-		if (path == RF90_PATH_A) {
-			offset = 0xb00;
-			for (index = 0; index < 11; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-
-			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
-
-			offset = 0xb68;
-			for (; index < 13; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
-
-			offset = 0xb00;
-			for (index = 0; index < 16; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_2
-					      [index]);
-
-				offset += 0x04;
-			}
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
-		} else if (path == RF90_PATH_B) {
-			offset = 0xb70;
-			for (index = 0; index < 10; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-			rtl_set_bbreg(hw, 0xb28, MASKDWORD, 0x12680000);
-			rtl_set_bbreg(hw, 0xb98, MASKDWORD, 0x12680000);
-
-			offset = 0xb68;
-			index = 11;
-			for (; index < 13; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_1
-					      [index]);
-
-				offset += 0x04;
-			}
-
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x40000000);
-
-			offset = 0xb60;
-			for (index = 0; index < 16; index++) {
-				rtl_set_bbreg(hw, offset, MASKDWORD,
-					      apk_normal_setting_value_2
-					      [index]);
-
-				offset += 0x04;
-			}
-			rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
-		}
-
-		reg_d[path] = rtl_get_rfreg(hw, (enum radio_path)path,
-					    0xd, MASKDWORD);
-
-		for (index = 0; index < APK_AFE_REG_NUM; index++)
-			rtl_set_bbreg(hw, afe_reg[index], MASKDWORD,
-				      afe_on_off[path]);
-
-		if (path == RF90_PATH_A) {
-			for (index = 0; index < APK_BB_REG_NUM; index++) {
-				if (index == 0)
-					continue;
-				rtl_set_bbreg(hw, bb_reg[index], MASKDWORD,
-					      bb_ap_mode[index]);
-			}
-		}
-
-		_rtl92c_phy_mac_setting_calibration(hw, mac_reg, mac_backup);
-
-		if (path == 0) {
-			rtl_set_rfreg(hw, RF90_PATH_B, 0x0, MASKDWORD, 0x10000);
-		} else {
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASKDWORD,
-				      0x10000);
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
-				      0x1000f);
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
-				      0x20103);
-		}
-
-		delta_offset = ((delta + 14) / 2);
-		if (delta_offset < 0)
-			delta_offset = 0;
-		else if (delta_offset > 12)
-			delta_offset = 12;
-
-		for (index = 0; index < APK_BB_REG_NUM; index++) {
-			if (index != 1)
-				continue;
-
-			tmpreg = apk_rf_init_value[path][index];
-
-			if (!rtlefuse->b_apk_thermalmeterignore) {
-				bb_offset = (tmpreg & 0xF0000) >> 16;
-
-				if (!(tmpreg & BIT(15)))
-					bb_offset = -bb_offset;
-
-				delta_v =
-				    apk_delta_mapping[index][delta_offset];
-
-				bb_offset += delta_v;
-
-				if (bb_offset < 0) {
-					tmpreg = tmpreg & (~BIT(15));
-					bb_offset = -bb_offset;
-				} else {
-					tmpreg = tmpreg | BIT(15);
-				}
-
-				tmpreg =
-				    (tmpreg & 0xFFF0FFFF) | (bb_offset << 16);
-			}
-
-			rtl_set_rfreg(hw, (enum radio_path)path, 0xc,
-				      MASKDWORD, 0x8992e);
-			rtl_set_rfreg(hw, (enum radio_path)path, 0x0,
-				      MASKDWORD, apk_rf_value_0[path][index]);
-			rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
-				      MASKDWORD, tmpreg);
-
-			i = 0;
-			do {
-				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x80000000);
-				rtl_set_bbreg(hw, apk_offset[path],
-					      MASKDWORD, apk_value[0]);
-				RTPRINT(rtlpriv, FINIT, INIT_IQK,
-					("PHY_APCalibrate() offset 0x%x "
-					 "value 0x%x\n",
-					 apk_offset[path],
-					 rtl_get_bbreg(hw, apk_offset[path],
-						       MASKDWORD)));
-
-				mdelay(3);
-
-				rtl_set_bbreg(hw, apk_offset[path],
-					      MASKDWORD, apk_value[1]);
-				RTPRINT(rtlpriv, FINIT, INIT_IQK,
-					("PHY_APCalibrate() offset 0x%x "
-					 "value 0x%x\n",
-					 apk_offset[path],
-					 rtl_get_bbreg(hw, apk_offset[path],
-						       MASKDWORD)));
-
-				mdelay(20);
-
-				rtl_set_bbreg(hw, 0xe28, MASKDWORD, 0x00000000);
-
-				if (path == RF90_PATH_A)
-					tmpreg = rtl_get_bbreg(hw, 0xbd8,
-							       0x03E00000);
-				else
-					tmpreg = rtl_get_bbreg(hw, 0xbd8,
-							       0xF8000000);
-
-				RTPRINT(rtlpriv, FINIT, INIT_IQK,
-					("PHY_APCalibrate() offset "
-					 "0xbd8[25:21] %x\n", tmpreg));
-
-				i++;
-
-			} while (tmpreg > apkbound && i < 4);
-
-			apk_result[path][index] = tmpreg;
-		}
-	}
-
-	_rtl92c_phy_reload_mac_registers(hw, mac_reg, mac_backup);
-
-	for (index = 0; index < APK_BB_REG_NUM; index++) {
-		if (index == 0)
-			continue;
-		rtl_set_bbreg(hw, bb_reg[index], MASKDWORD, bb_backup[index]);
-	}
-
-	_rtl92c_phy_reload_adda_registers(hw, afe_reg, afe_backup, 16);
-
-	for (path = 0; path < pathbound; path++) {
-		rtl_set_rfreg(hw, (enum radio_path)path, 0xd,
-			      MASKDWORD, reg_d[path]);
-
-		if (path == RF90_PATH_B) {
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x10, MASKDWORD,
-				      0x1000f);
-			rtl_set_rfreg(hw, RF90_PATH_A, 0x11, MASKDWORD,
-				      0x20101);
-		}
-
-		if (apk_result[path][1] > 6)
-			apk_result[path][1] = 6;
-	}
-
-	for (path = 0; path < pathbound; path++) {
-		rtl_set_rfreg(hw, (enum radio_path)path, 0x3, MASKDWORD,
-			      ((apk_result[path][1] << 15) |
-			       (apk_result[path][1] << 10) |
-			       (apk_result[path][1] << 5) |
-			       apk_result[path][1]));
-
-		if (path == RF90_PATH_A)
-			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
-				      ((apk_result[path][1] << 15) |
-				       (apk_result[path][1] << 10) |
-				       (0x00 << 5) | 0x05));
-		else
-			rtl_set_rfreg(hw, (enum radio_path)path, 0x4, MASKDWORD,
-				      ((apk_result[path][1] << 15) |
-				       (apk_result[path][1] << 10) |
-				       (0x02 << 5) | 0x05));
-
-		rtl_set_rfreg(hw, (enum radio_path)path, 0xe, MASKDWORD,
-			      ((0x08 << 15) | (0x08 << 10) | (0x08 << 5) |
-			       0x08));
-
-	}
-
-	rtlphy->b_apk_done = true;
-#endif
-}
-
-static void _rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw,
-					  bool bmain, bool is2t)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (is_hal_stop(rtlhal)) {
-		rtl_set_bbreg(hw, REG_LEDCFG0, BIT(23), 0x01);
-		rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
-	}
-	if (is2t) {
-		if (bmain)
-			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
-				      BIT(5) | BIT(6), 0x1);
-		else
-			rtl_set_bbreg(hw, RFPGA0_XB_RFINTERFACEOE,
-				      BIT(5) | BIT(6), 0x2);
-	} else {
-		if (bmain)
-			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x2);
-		else
-			rtl_set_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300, 0x1);
-
-	}
-}
-
-#undef IQK_ADDA_REG_NUM
-#undef IQK_DELAY_TIME
-
-void rtl92c_phy_iq_calibrate(struct ieee80211_hw *hw, bool b_recovery)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	long result[4][8];
-	u8 i, final_candidate;
-	bool b_patha_ok, b_pathb_ok;
-	long reg_e94, reg_e9c, reg_ea4, reg_eac, reg_eb4, reg_ebc, reg_ec4,
-	    reg_ecc, reg_tmp = 0;
-	bool is12simular, is13simular, is23simular;
-	bool b_start_conttx = false, b_singletone = false;
-	u32 iqk_bb_reg[10] = {
-		ROFDM0_XARXIQIMBALANCE,
-		ROFDM0_XBRXIQIMBALANCE,
-		ROFDM0_ECCATHRESHOLD,
-		ROFDM0_AGCRSSITABLE,
-		ROFDM0_XATXIQIMBALANCE,
-		ROFDM0_XBTXIQIMBALANCE,
-		ROFDM0_XCTXIQIMBALANCE,
-		ROFDM0_XCTXAFE,
-		ROFDM0_XDTXAFE,
-		ROFDM0_RXIQEXTANTA
-	};
-
-	if (b_recovery) {
-		_rtl92c_phy_reload_adda_registers(hw,
-						  iqk_bb_reg,
-						  rtlphy->iqk_bb_backup, 10);
-		return;
-	}
-	if (b_start_conttx || b_singletone)
-		return;
-	for (i = 0; i < 8; i++) {
-		result[0][i] = 0;
-		result[1][i] = 0;
-		result[2][i] = 0;
-		result[3][i] = 0;
-	}
-	final_candidate = 0xff;
-	b_patha_ok = false;
-	b_pathb_ok = false;
-	is12simular = false;
-	is23simular = false;
-	is13simular = false;
-	for (i = 0; i < 3; i++) {
-		if (IS_92C_SERIAL(rtlhal->version))
-			_rtl92c_phy_iq_calibrate(hw, result, i, true);
-		else
-			_rtl92c_phy_iq_calibrate(hw, result, i, false);
-		if (i == 1) {
-			is12simular = _rtl92c_phy_simularity_compare(hw,
-								     result, 0,
-								     1);
-			if (is12simular) {
-				final_candidate = 0;
-				break;
-			}
-		}
-		if (i == 2) {
-			is13simular = _rtl92c_phy_simularity_compare(hw,
-								     result, 0,
-								     2);
-			if (is13simular) {
-				final_candidate = 0;
-				break;
-			}
-			is23simular = _rtl92c_phy_simularity_compare(hw,
-								     result, 1,
-								     2);
-			if (is23simular)
-				final_candidate = 1;
-			else {
-				for (i = 0; i < 8; i++)
-					reg_tmp += result[3][i];
-
-				if (reg_tmp != 0)
-					final_candidate = 3;
-				else
-					final_candidate = 0xFF;
-			}
-		}
-	}
-	for (i = 0; i < 4; i++) {
-		reg_e94 = result[i][0];
-		reg_e9c = result[i][1];
-		reg_ea4 = result[i][2];
-		reg_eac = result[i][3];
-		reg_eb4 = result[i][4];
-		reg_ebc = result[i][5];
-		reg_ec4 = result[i][6];
-		reg_ecc = result[i][7];
-	}
-	if (final_candidate != 0xff) {
-		rtlphy->reg_e94 = reg_e94 = result[final_candidate][0];
-		rtlphy->reg_e9c = reg_e9c = result[final_candidate][1];
-		reg_ea4 = result[final_candidate][2];
-		reg_eac = result[final_candidate][3];
-		rtlphy->reg_eb4 = reg_eb4 = result[final_candidate][4];
-		rtlphy->reg_ebc = reg_ebc = result[final_candidate][5];
-		reg_ec4 = result[final_candidate][6];
-		reg_ecc = result[final_candidate][7];
-		b_patha_ok = b_pathb_ok = true;
-	} else {
-		rtlphy->reg_e94 = rtlphy->reg_eb4 = 0x100;
-		rtlphy->reg_e9c = rtlphy->reg_ebc = 0x0;
-	}
-	if (reg_e94 != 0) /*&&(reg_ea4 != 0) */
-		_rtl92c_phy_path_a_fill_iqk_matrix(hw, b_patha_ok, result,
-						   final_candidate,
-						   (reg_ea4 == 0));
-	if (IS_92C_SERIAL(rtlhal->version)) {
-		if (reg_eb4 != 0) /*&&(reg_ec4 != 0) */
-			_rtl92c_phy_path_b_fill_iqk_matrix(hw, b_pathb_ok,
-							   result,
-							   final_candidate,
-							   (reg_ec4 == 0));
-	}
-	_rtl92c_phy_save_adda_registers(hw, iqk_bb_reg,
-					rtlphy->iqk_bb_backup, 10);
-}
-
-void rtl92c_phy_lc_calibrate(struct ieee80211_hw *hw)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-	bool b_start_conttx = false, b_singletone = false;
-
-	if (b_start_conttx || b_singletone)
-		return;
-	if (IS_92C_SERIAL(rtlhal->version))
-		_rtl92c_phy_lc_calibrate(hw, true);
-	else
-		_rtl92c_phy_lc_calibrate(hw, false);
-}
-
-void rtl92c_phy_ap_calibrate(struct ieee80211_hw *hw, char delta)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (rtlphy->b_apk_done)
-		return;
-	if (IS_92C_SERIAL(rtlhal->version))
-		_rtl92c_phy_ap_calibrate(hw, delta, true);
-	else
-		_rtl92c_phy_ap_calibrate(hw, delta, false);
-}
-
-void rtl92c_phy_set_rfpath_switch(struct ieee80211_hw *hw, bool bmain)
-{
-	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
-
-	if (IS_92C_SERIAL(rtlhal->version))
-		_rtl92c_phy_set_rfpath_switch(hw, bmain, true);
-	else
-		_rtl92c_phy_set_rfpath_switch(hw, bmain, false);
-}
-
-bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-	bool b_postprocessing = false;
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-		 ("-->IO Cmd(%#x), set_io_inprogress(%d)\n",
-		  iotype, rtlphy->set_io_inprogress));
-	do {
-		switch (iotype) {
-		case IO_CMD_RESUME_DM_BY_SCAN:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-				 ("[IO CMD] Resume DM after scan.\n"));
-			b_postprocessing = true;
-			break;
-		case IO_CMD_PAUSE_DM_BY_SCAN:
-			RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-				 ("[IO CMD] Pause DM before scan.\n"));
-			b_postprocessing = true;
-			break;
-		default:
-			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-				 ("switch case not process\n"));
-			break;
-		}
-	} while (false);
-	if (b_postprocessing && !rtlphy->set_io_inprogress) {
-		rtlphy->set_io_inprogress = true;
-		rtlphy->current_io_type = iotype;
-	} else {
-		return false;
-	}
-	rtl92c_phy_set_io(hw);
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE, ("<--IO Type(%#x)\n", iotype));
-	return true;
-}
-
-void rtl92c_phy_set_io(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	struct rtl_phy *rtlphy = &(rtlpriv->phy);
-
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-		 ("--->Cmd(%#x), set_io_inprogress(%d)\n",
-		  rtlphy->current_io_type, rtlphy->set_io_inprogress));
-	switch (rtlphy->current_io_type) {
-	case IO_CMD_RESUME_DM_BY_SCAN:
-		dm_digtable.cur_igvalue = rtlphy->initgain_backup.xaagccore1;
-		rtl92c_dm_write_dig(hw);
-		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
-		break;
-	case IO_CMD_PAUSE_DM_BY_SCAN:
-		rtlphy->initgain_backup.xaagccore1 = dm_digtable.cur_igvalue;
-		dm_digtable.cur_igvalue = 0x17;
-		rtl92c_dm_write_dig(hw);
-		break;
-	default:
-		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
-			 ("switch case not process\n"));
-		break;
-	}
-	rtlphy->set_io_inprogress = false;
-	RT_TRACE(rtlpriv, COMP_CMD, DBG_TRACE,
-		 ("<---(%#x)\n", rtlphy->current_io_type));
-}
-
-void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw)
-{
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
-	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
-	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
-	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
-	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
-	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
-}
-
-static void _rtl92ce_phy_set_rf_sleep(struct ieee80211_hw *hw)
-{
-	u32 u4b_tmp;
-	u8 delay = 5;
-	struct rtl_priv *rtlpriv = rtl_priv(hw);
-
-	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
-	rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
-	rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
-	u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
-	while (u4b_tmp != 0 && delay > 0) {
-		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x0);
-		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, RFREG_OFFSET_MASK, 0x00);
-		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x40);
-		u4b_tmp = rtl_get_rfreg(hw, RF90_PATH_A, 0, RFREG_OFFSET_MASK);
-		delay--;
-	}
-	if (delay == 0) {
-		rtl_write_byte(rtlpriv, REG_APSD_CTRL, 0x00);
-		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
-		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE3);
-		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
-		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
-			 ("Switch RF timeout !!!.\n"));
-		return;
-	}
-	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, 0xE2);
-	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x22);
-}
-
 static bool _rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 					    enum rf_pwrstate rfpwr_state)
 {
@@ -2648,7 +599,7 @@
 				  jiffies_to_msecs(jiffies -
 						   ppsc->last_awake_jiffies)));
 			ppsc->last_sleep_jiffies = jiffies;
-			_rtl92ce_phy_set_rf_sleep(hw);
+			_rtl92c_phy_set_rf_sleep(hw);
 			break;
 		}
 	default:
@@ -2663,7 +614,7 @@
 	return bresult;
 }
 
-bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
+bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 				   enum rf_pwrstate rfpwr_state)
 {
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/phy.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,8 +57,6 @@
 #define IQK_MAC_REG_NUM			4
 
 #define RF90_PATH_MAX			2
-#define CHANNEL_MAX_NUMBER		14
-#define CHANNEL_GROUP_MAX		3
 
 #define CT_OFFSET_MAC_ADDR		0X16
 
@@ -78,9 +76,7 @@
 #define CT_OFFSET_CUSTOMER_ID		0x7F
 
 #define RTL92C_MAX_PATH_NUM		2
-#define CHANNEL_MAX_NUMBER		14
-#define CHANNEL_GROUP_MAX		3
-
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER	255
 enum swchnlcmd_id {
 	CMDID_END,
 	CMDID_SET_TXPOWEROWER_LEVEL,
@@ -195,11 +191,11 @@
 extern u32 rtl92c_phy_query_rf_reg(struct ieee80211_hw *hw,
 				   enum radio_path rfpath, u32 regaddr,
 				   u32 bitmask);
-extern void rtl92c_phy_set_rf_reg(struct ieee80211_hw *hw,
+extern void rtl92ce_phy_set_rf_reg(struct ieee80211_hw *hw,
 				  enum radio_path rfpath, u32 regaddr,
 				  u32 bitmask, u32 data);
 extern bool rtl92c_phy_mac_config(struct ieee80211_hw *hw);
-extern bool rtl92c_phy_bb_config(struct ieee80211_hw *hw);
+bool rtl92ce_phy_bb_config(struct ieee80211_hw *hw);
 extern bool rtl92c_phy_rf_config(struct ieee80211_hw *hw);
 extern bool rtl92c_phy_config_rf_with_feaderfile(struct ieee80211_hw *hw,
 						 enum radio_path rfpath);
@@ -227,11 +223,32 @@
 extern bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw,
 					      u32 rfpath);
 bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
-extern bool rtl92c_phy_set_rf_power_state(struct ieee80211_hw *hw,
+bool rtl92ce_phy_set_rf_power_state(struct ieee80211_hw *hw,
 					  enum rf_pwrstate rfpwr_state);
-void rtl92c_phy_config_bb_external_pa(struct ieee80211_hw *hw);
 void rtl92ce_phy_set_rf_on(struct ieee80211_hw *hw);
 bool rtl92c_phy_set_io_cmd(struct ieee80211_hw *hw, enum io_type iotype);
 void rtl92c_phy_set_io(struct ieee80211_hw *hw);
+void rtl92c_bb_block_on(struct ieee80211_hw *hw);
+u32 _rtl92c_phy_rf_serial_read(struct ieee80211_hw *hw,
+				      enum radio_path rfpath, u32 offset);
+u32 _rtl92c_phy_fw_rf_serial_read(struct ieee80211_hw *hw,
+					 enum radio_path rfpath, u32 offset);
+u32 _rtl92c_phy_calculate_bit_shift(u32 bitmask);
+void _rtl92c_phy_rf_serial_write(struct ieee80211_hw *hw,
+					enum radio_path rfpath, u32 offset,
+					u32 data);
+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data);
+void _rtl92c_phy_fw_rf_serial_write(struct ieee80211_hw *hw,
+					   enum radio_path rfpath, u32 offset,
+					   u32 data);
+void _rtl92c_store_pwrIndex_diffrate_offset(struct ieee80211_hw *hw,
+						   u32 regaddr, u32 bitmask,
+						   u32 data);
+bool _rtl92ce_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
+void _rtl92c_phy_init_bb_rf_register_definition(struct ieee80211_hw *hw);
+bool _rtl92c_phy_bb8192c_config_parafile(struct ieee80211_hw *hw);
+void _rtl92c_phy_set_rf_sleep(struct ieee80211_hw *hw);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,15 @@
 #define REG_LEDCFG3				0x004F
 #define REG_FSIMR				0x0050
 #define REG_FSISR				0x0054
+#define REG_HSIMR				0x0058
+#define REG_HSISR				0x005c
 
+/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Pin Control. */
+#define REG_GPIO_PIN_CTRL_2			0x0060
+/* RTL8723 WIFI/BT/GPS Multi-Function GPIO Select. */
+#define REG_GPIO_IO_SEL_2			0x0062
+/* RTL8723 WIFI/BT/GPS Multi-Function control source. */
+#define REG_MULTI_FUNC_CTRL			0x0068
 #define REG_MCUFWDL				0x0080
 
 #define REG_HMEBOX_EXT_0			0x0088
@@ -79,6 +87,7 @@
 #define REG_PCIE_MIO_INTD			0x00E8
 #define REG_HPON_FSM				0x00EC
 #define REG_SYS_CFG				0x00F0
+#define REG_GPIO_OUTSTS				0x00F4	/* For RTL8723 only.*/
 
 #define REG_CR					0x0100
 #define REG_PBP					0x0104
@@ -209,6 +218,8 @@
 #define REG_RDG_PIFS				0x0513
 #define REG_SIFS_CTX				0x0514
 #define REG_SIFS_TRX				0x0516
+#define REG_SIFS_CCK				0x0514
+#define REG_SIFS_OFDM				0x0516
 #define REG_AGGR_BREAK_TIME			0x051A
 #define REG_SLOT				0x051B
 #define REG_TX_PTCL_CTRL			0x0520
@@ -261,6 +272,10 @@
 #define REG_MAC_SPEC_SIFS			0x063A
 #define REG_RESP_SIFS_CCK			0x063C
 #define REG_RESP_SIFS_OFDM			0x063E
+/* [15:8]SIFS_R2T_OFDM, [7:0]SIFS_R2T_CCK */
+#define REG_R2T_SIFS				0x063C
+/* [15:8]SIFS_T2T_OFDM, [7:0]SIFS_T2T_CCK */
+#define REG_T2T_SIFS				0x063E
 #define REG_ACKTO				0x0640
 #define REG_CTS2TO				0x0641
 #define REG_EIFS				0x0642
@@ -641,9 +656,10 @@
 #define	STOPBE					BIT(1)
 #define	STOPBK					BIT(0)
 
-#define	RCR_APPFCS				BIT(31)
+#define	RCR_APP_FCS				BIT(31)
 #define	RCR_APP_MIC				BIT(30)
 #define	RCR_APP_ICV				BIT(29)
+#define	RCR_APP_PHYSTS				BIT(28)
 #define	RCR_APP_PHYST_RXFF			BIT(28)
 #define	RCR_APP_BA_SSN				BIT(27)
 #define	RCR_ENMBID				BIT(24)
@@ -759,6 +775,7 @@
 
 #define	BOOT_FROM_EEPROM			BIT(4)
 #define	EEPROM_EN				BIT(5)
+#define	EEPROMSEL				BOOT_FROM_EEPROM
 
 #define AFE_BGEN				BIT(0)
 #define AFE_MBEN				BIT(1)
@@ -876,6 +893,8 @@
 #define BD_MAC2					BIT(9)
 #define BD_MAC1					BIT(10)
 #define IC_MACPHY_MODE				BIT(11)
+#define BT_FUNC					BIT(16)
+#define VENDOR_ID				BIT(19)
 #define PAD_HWPD_IDN				BIT(22)
 #define TRP_VAUX_EN				BIT(23)
 #define TRP_BT_EN				BIT(24)
@@ -883,6 +902,28 @@
 #define BD_HCI_SEL				BIT(26)
 #define TYPE_ID					BIT(27)
 
+/* REG_GPIO_OUTSTS (For RTL8723 only) */
+#define	EFS_HCI_SEL				(BIT(0)|BIT(1))
+#define	PAD_HCI_SEL				(BIT(2)|BIT(3))
+#define	HCI_SEL					(BIT(4)|BIT(5))
+#define	PKG_SEL_HCI				BIT(6)
+#define	FEN_GPS					BIT(7)
+#define	FEN_BT					BIT(8)
+#define	FEN_WL					BIT(9)
+#define	FEN_PCI					BIT(10)
+#define	FEN_USB					BIT(11)
+#define	BTRF_HWPDN_N				BIT(12)
+#define	WLRF_HWPDN_N				BIT(13)
+#define	PDN_BT_N				BIT(14)
+#define	PDN_GPS_N				BIT(15)
+#define	BT_CTL_HWPDN				BIT(16)
+#define	GPS_CTL_HWPDN				BIT(17)
+#define	PPHY_SUSB				BIT(20)
+#define	UPHY_SUSB				BIT(21)
+#define	PCI_SUSEN				BIT(22)
+#define	USB_SUSEN				BIT(23)
+#define	RF_RL_ID			(BIT(31) | BIT(30) | BIT(29) | BIT(28))
+
 #define CHIP_VER_RTL_MASK			0xF000
 #define CHIP_VER_RTL_SHIFT			12
 
@@ -1035,7 +1076,7 @@
 #define _RARF_RC7(x)				(((x) & 0x1F) << 16)
 #define _RARF_RC8(x)				(((x) & 0x1F) << 24)
 
-#define AC_PARAM_TXOP_LIMIT_OFFSET		16
+#define AC_PARAM_TXOP_OFFSET			16
 #define AC_PARAM_ECW_MAX_OFFSET			12
 #define AC_PARAM_ECW_MIN_OFFSET			8
 #define AC_PARAM_AIFS_OFFSET			0
@@ -1184,6 +1225,30 @@
 
 #define	HAL_8192C_HW_GPIO_WPS_BIT		BIT(2)
 
+/* REG_MULTI_FUNC_CTRL(For RTL8723 Only) */
+/* Enable GPIO[9] as WiFi HW PDn source */
+#define	WL_HWPDN_EN				BIT(0)
+/* WiFi HW PDn polarity control */
+#define	WL_HWPDN_SL				BIT(1)
+/* WiFi function enable */
+#define	WL_FUNC_EN				BIT(2)
+/* Enable GPIO[9] as WiFi RF HW PDn source */
+#define	WL_HWROF_EN				BIT(3)
+/* Enable GPIO[11] as BT HW PDn source */
+#define	BT_HWPDN_EN				BIT(16)
+/* BT HW PDn polarity control */
+#define	BT_HWPDN_SL				BIT(17)
+/* BT function enable */
+#define	BT_FUNC_EN				BIT(18)
+/* Enable GPIO[11] as BT/GPS RF HW PDn source */
+#define	BT_HWROF_EN				BIT(19)
+/* Enable GPIO[10] as GPS HW PDn source */
+#define	GPS_HWPDN_EN				BIT(20)
+/* GPS HW PDn polarity control */
+#define	GPS_HWPDN_SL				BIT(21)
+/* GPS function enable */
+#define	GPS_FUNC_EN				BIT(22)
+
 #define	RPMAC_RESET				0x100
 #define	RPMAC_TXSTART				0x104
 #define	RPMAC_TXLEGACYSIG			0x108
@@ -1496,7 +1561,7 @@
 #define	BTXHTSTBC				0x30
 #define	BTXHTADVANCECODING			0x40
 #define	BTXHTSHORTGI				0x80
-#define	BTXHTNUMBERHT_LT	F		0x300
+#define	BTXHTNUMBERHT_LTF			0x300
 #define	BTXHTCRC8				0x3fc00
 #define	BCOUNTERRESET				0x10000
 #define	BNUMOFOFDMTX				0xffff
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.c	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
 	}
 }
 
-void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
 				       u8 *ppowerlevel)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
@@ -410,7 +410,7 @@
 	}
 }
 
-void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
 					u8 *ppowerlevel, u8 channel)
 {
 	u32 writeVal[2], powerBase0[2], powerBase1[2];
@@ -430,7 +430,7 @@
 	}
 }
 
-bool rtl92c_phy_rf6052_config(struct ieee80211_hw *hw)
+bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_phy *rtlphy = &(rtlpriv->phy);
@@ -484,11 +484,11 @@
 
 		switch (rfpath) {
 		case RF90_PATH_A:
-			rtstatus = rtl92c_phy_config_rf_with_headerfile(hw,
+			rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw,
 					(enum radio_path) rfpath);
 			break;
 		case RF90_PATH_B:
-			rtstatus = rtl92c_phy_config_rf_with_headerfile(hw,
+			rtstatus = rtl92ce_phy_config_rf_with_headerfile(hw,
 					(enum radio_path) rfpath);
 			break;
 		case RF90_PATH_C:
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/rf.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,5 +40,8 @@
 					      u8 *ppowerlevel);
 extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
 					       u8 *ppowerlevel, u8 channel);
-extern bool rtl92c_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92ce_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92ce_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2012-03-24 01:14:48.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c	2012-03-24 03:34:38.000000000 -0400
@@ -37,6 +37,7 @@
 #include "phy.h"
 #include "dm.h"
 #include "hw.h"
+#include "rf.h"
 #include "sw.h"
 #include "trx.h"
 #include "led.h"
@@ -46,13 +47,13 @@
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 
-	rtlpriv->dm.b_dm_initialgain_enable = 1;
+	rtlpriv->dm.dm_initialgain_enable = 1;
 	rtlpriv->dm.dm_flag = 0;
-	rtlpriv->dm.b_disable_framebursting = 0;;
+	rtlpriv->dm.disable_framebursting = 0;
 	rtlpriv->dm.thermalvalue = 0;
 	rtlpci->transmit_config = CFENDFORM | BIT(12) | BIT(13);
 
-	rtlpci->receive_config = (RCR_APPFCS |
+	rtlpci->receive_config = (RCR_APP_FCS |
 				  RCR_AMF |
 				  RCR_ADF |
 				  RCR_APP_MIC |
@@ -122,7 +123,7 @@
 	.switch_channel = rtl92c_phy_sw_chnl,
 	.dm_watchdog = rtl92c_dm_watchdog,
 	.scan_operation_backup = rtl92c_phy_scan_operation_backup,
-	.set_rf_power_state = rtl92c_phy_set_rf_power_state,
+	.set_rf_power_state = rtl92ce_phy_set_rf_power_state,
 	.led_control = rtl92ce_led_control,
 	.set_desc = rtl92ce_set_desc,
 	.get_desc = rtl92ce_get_desc,
@@ -133,8 +134,17 @@
 	.deinit_sw_leds = rtl92ce_deinit_sw_leds,
 	.get_bbreg = rtl92c_phy_query_bb_reg,
 	.set_bbreg = rtl92c_phy_set_bb_reg,
-	.get_rfreg = rtl92c_phy_query_rf_reg,
-	.set_rfreg = rtl92c_phy_set_rf_reg,
+	.get_rfreg = rtl92ce_phy_query_rf_reg,
+	.set_rfreg = rtl92ce_phy_set_rf_reg,
+	.cmd_send_packet = _rtl92c_cmd_send_packet,
+	.phy_rf6052_config = rtl92ce_phy_rf6052_config,
+	.phy_rf6052_set_cck_txpower = rtl92ce_phy_rf6052_set_cck_txpower,
+	.phy_rf6052_set_ofdm_txpower = rtl92ce_phy_rf6052_set_ofdm_txpower,
+	.config_bb_with_headerfile = _rtl92ce_phy_config_bb_with_headerfile,
+	.config_bb_with_pgheaderfile = _rtl92ce_phy_config_bb_with_pgheaderfile,
+	.phy_lc_calibrate = _rtl92ce_phy_lc_calibrate,
+	.phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback,
+	.dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower,
 };
 
 static struct rtl_mod_params rtl92ce_mod_params = {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/sw.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,5 +33,19 @@
 int rtl92c_init_sw_vars(struct ieee80211_hw *hw);
 void rtl92c_deinit_sw_vars(struct ieee80211_hw *hw);
 void rtl92c_init_var_map(struct ieee80211_hw *hw);
+bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
+			     struct sk_buff *skb);
+void rtl92ce_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel);
+void rtl92ce_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					 u8 *ppowerlevel, u8 channel);
+bool _rtl92ce_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+						  u8 configtype);
+bool _rtl92ce_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+						    u8 configtype);
+void _rtl92ce_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
+u32 rtl92ce_phy_query_rf_reg(struct ieee80211_hw *hw,
+			    enum radio_path rfpath, u32 regaddr, u32 bitmask);
+void rtl92ce_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 #include "trx.h"
 #include "led.h"
 
-static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(u16 fc,
+static enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc,
 							  unsigned int
 							  skb_queue)
 {
@@ -245,24 +245,24 @@
 				       struct rtl_stats *pstats,
 				       struct rx_desc_92c *pdesc,
 				       struct rx_fwinfo_92c *p_drvinfo,
-				       bool bpacket_match_bssid,
-				       bool bpacket_toself,
-				       bool b_packet_beacon)
+				       bool packet_match_bssid,
+				       bool packet_toself,
+				       bool packet_beacon)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct phy_sts_cck_8192s_t *cck_buf;
 	s8 rx_pwr_all, rx_pwr[4];
-	u8 rf_rx_num, evm, pwdb_all;
+	u8 evm, pwdb_all, rf_rx_num = 0;
 	u8 i, max_spatial_stream;
-	u32 rssi, total_rssi;
+	u32 rssi, total_rssi = 0;
 	bool is_cck_rate;
 
 	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
-	pstats->b_packet_matchbssid = bpacket_match_bssid;
-	pstats->b_packet_toself = bpacket_toself;
-	pstats->b_is_cck = is_cck_rate;
-	pstats->b_packet_beacon = b_packet_beacon;
-	pstats->b_is_cck = is_cck_rate;
+	pstats->packet_matchbssid = packet_match_bssid;
+	pstats->packet_toself = packet_toself;
+	pstats->is_cck = is_cck_rate;
+	pstats->packet_beacon = packet_beacon;
+	pstats->is_cck = is_cck_rate;
 	pstats->rx_mimo_signalquality[0] = -1;
 	pstats->rx_mimo_signalquality[1] = -1;
 
@@ -315,7 +315,7 @@
 		pstats->rx_pwdb_all = pwdb_all;
 		pstats->recvsignalpower = rx_pwr_all;
 
-		if (bpacket_match_bssid) {
+		if (packet_match_bssid) {
 			u8 sq;
 			if (pstats->rx_pwdb_all > 40)
 				sq = 100;
@@ -334,10 +334,10 @@
 			pstats->rx_mimo_signalquality[1] = -1;
 		}
 	} else {
-		rtlpriv->dm.brfpath_rxenable[0] =
-		    rtlpriv->dm.brfpath_rxenable[1] = true;
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
 		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
-			if (rtlpriv->dm.brfpath_rxenable[i])
+			if (rtlpriv->dm.rfpath_rxenable[i])
 				rf_rx_num++;
 
 			rx_pwr[i] =
@@ -347,7 +347,7 @@
 			rtlpriv->stats.rx_snr_db[i] =
 			    (long)(p_drvinfo->rxsnr[i] / 2);
 
-			if (bpacket_match_bssid)
+			if (packet_match_bssid)
 				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
 		}
 
@@ -366,7 +366,7 @@
 		for (i = 0; i < max_spatial_stream; i++) {
 			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
 
-			if (bpacket_match_bssid) {
+			if (packet_match_bssid) {
 				if (i == 0)
 					pstats->signalquality =
 					    (u8) (evm & 0xff);
@@ -393,7 +393,7 @@
 	u8 rfpath;
 	u32 last_rssi, tmpval;
 
-	if (pstats->b_packet_toself || pstats->b_packet_beacon) {
+	if (pstats->packet_toself || pstats->packet_beacon) {
 		rtlpriv->stats.rssi_calculate_cnt++;
 
 		if (rtlpriv->stats.ui_rssi.total_num++ >=
@@ -421,7 +421,7 @@
 		pstats->rssi = rtlpriv->stats.signal_strength;
 	}
 
-	if (!pstats->b_is_cck && pstats->b_packet_toself) {
+	if (!pstats->is_cck && pstats->packet_toself) {
 		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
 		     rfpath++) {
 
@@ -463,7 +463,7 @@
 					       struct rtl_stats *pstats)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
-	int weighting;
+	int weighting = 0;
 
 	if (rtlpriv->stats.recv_signal_power == 0)
 		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
@@ -493,7 +493,7 @@
 		    rtlpriv->dm.undecorated_smoothed_pwdb;
 	}
 
-	if (pstats->b_packet_toself || pstats->b_packet_beacon) {
+	if (pstats->packet_toself || pstats->packet_beacon) {
 		if (undecorated_smoothed_pwdb < 0)
 			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
 
@@ -525,7 +525,7 @@
 	u32 last_evm, n_spatialstream, tmpval;
 
 	if (pstats->signalquality != 0) {
-		if (pstats->b_packet_toself || pstats->b_packet_beacon) {
+		if (pstats->packet_toself || pstats->packet_beacon) {
 
 			if (rtlpriv->stats.ui_link_quality.total_num++ >=
 			    PHY_LINKQUALITY_SLID_WIN_MAX) {
@@ -595,8 +595,8 @@
 				     struct rtl_stats *pcurrent_stats)
 {
 
-	if (!pcurrent_stats->b_packet_matchbssid &&
-	    !pcurrent_stats->b_packet_beacon)
+	if (!pcurrent_stats->packet_matchbssid &&
+	    !pcurrent_stats->packet_beacon)
 		return;
 
 	_rtl92ce_process_ui_rssi(hw, pcurrent_stats);
@@ -617,34 +617,36 @@
 	u8 *tmp_buf;
 	u8 *praddr;
 	u8 *psaddr;
-	u16 fc, type;
-	bool b_packet_matchbssid, b_packet_toself, b_packet_beacon;
+	__le16 fc;
+	u16 type, c_fc;
+	bool packet_matchbssid, packet_toself, packet_beacon;
 
 	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
 
 	hdr = (struct ieee80211_hdr *)tmp_buf;
-	fc = le16_to_cpu(hdr->frame_control);
+	fc = hdr->frame_control;
+	c_fc = le16_to_cpu(fc);
 	type = WLAN_FC_GET_TYPE(fc);
 	praddr = hdr->addr1;
 	psaddr = hdr->addr2;
 
-	b_packet_matchbssid =
+	packet_matchbssid =
 	    ((IEEE80211_FTYPE_CTL != type) &&
 	     (!compare_ether_addr(mac->bssid,
-				  (fc & IEEE80211_FCTL_TODS) ?
-				  hdr->addr1 : (fc & IEEE80211_FCTL_FROMDS) ?
+				  (c_fc & IEEE80211_FCTL_TODS) ?
+				  hdr->addr1 : (c_fc & IEEE80211_FCTL_FROMDS) ?
 				  hdr->addr2 : hdr->addr3)) &&
-	     (!pstats->b_hwerror) && (!pstats->b_crc) && (!pstats->b_icv));
+	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
 
-	b_packet_toself = b_packet_matchbssid &&
+	packet_toself = packet_matchbssid &&
 	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
 
 	if (ieee80211_is_beacon(fc))
-		b_packet_beacon = true;
+		packet_beacon = true;
 
 	_rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
-				   b_packet_matchbssid, b_packet_toself,
-				   b_packet_beacon);
+				   packet_matchbssid, packet_toself,
+				   packet_beacon);
 
 	_rtl92ce_process_phyinfo(hw, tmp_buf, pstats);
 }
@@ -662,14 +664,14 @@
 	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
 	    RX_DRV_INFO_SIZE_UNIT;
 	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
-	stats->b_icv = (u16) GET_RX_DESC_ICV(pdesc);
-	stats->b_crc = (u16) GET_RX_DESC_CRC32(pdesc);
-	stats->b_hwerror = (stats->b_crc | stats->b_icv);
+	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	stats->hwerror = (stats->crc | stats->icv);
 	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
 	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
-	stats->b_shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
-	stats->b_isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
-	stats->b_isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+	stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
 				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
 	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
 	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
@@ -689,7 +691,7 @@
 	if (GET_RX_DESC_RXHT(pdesc))
 		rx_status->flag |= RX_FLAG_HT;
 
-	rx_status->flag |= RX_FLAG_TSFT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	if (stats->decrypted)
 		rx_status->flag |= RX_FLAG_DECRYPTED;
@@ -727,27 +729,24 @@
 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
 	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
-	bool b_defaultadapter = true;
-
-	struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid);
-
+	bool defaultadapter = true;
+	struct ieee80211_sta *sta;
 	u8 *pdesc = (u8 *) pdesc_tx;
 	struct rtl_tcb_desc tcb_desc;
 	u8 *qc = ieee80211_get_qos_ctl(hdr);
 	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
 	u16 seq_number;
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 	u8 rate_flag = info->control.rates[0].flags;
 
 	enum rtl_desc_qsel fw_qsel =
-	    _rtl92ce_map_hwqueue_to_fwqueue(le16_to_cpu(hdr->frame_control),
-					    queue_index);
+	    _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index);
 
-	bool b_firstseg = ((hdr->seq_ctrl &
-			    cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
+	bool firstseg = ((hdr->seq_ctrl &
+			  cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
 
-	bool b_lastseg = ((hdr->frame_control &
-			   cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
+	bool lastseg = ((hdr->frame_control &
+			 cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
 
 	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
 					    skb->data, skb->len,
@@ -759,7 +758,7 @@
 
 	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c));
 
-	if (b_firstseg) {
+	if (firstseg) {
 		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
 
 		SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate);
@@ -774,25 +773,25 @@
 		}
 		SET_TX_DESC_SEQ(pdesc, seq_number);
 
-		SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.b_rts_enable &&
+		SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable &&
 						!tcb_desc.
-						b_cts_enable) ? 1 : 0));
+						cts_enable) ? 1 : 0));
 		SET_TX_DESC_HW_RTS_ENABLE(pdesc,
-					  ((tcb_desc.b_rts_enable
-					    || tcb_desc.b_cts_enable) ? 1 : 0));
-		SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.b_cts_enable) ? 1 : 0));
-		SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.b_rts_stbc) ? 1 : 0));
+					  ((tcb_desc.rts_enable
+					    || tcb_desc.cts_enable) ? 1 : 0));
+		SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0));
+		SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0));
 
 		SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate);
 		SET_TX_DESC_RTS_BW(pdesc, 0);
 		SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc);
 		SET_TX_DESC_RTS_SHORT(pdesc,
 				      ((tcb_desc.rts_rate <= DESC92C_RATE54M) ?
-				      (tcb_desc.b_rts_use_shortpreamble ? 1 : 0)
-				      : (tcb_desc.b_rts_use_shortgi ? 1 : 0)));
+				      (tcb_desc.rts_use_shortpreamble ? 1 : 0)
+				      : (tcb_desc.rts_use_shortgi ? 1 : 0)));
 
 		if (mac->bw_40) {
-			if (tcb_desc.b_packet_bw) {
+			if (tcb_desc.packet_bw) {
 				SET_TX_DESC_DATA_BW(pdesc, 1);
 				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
 			} else {
@@ -811,10 +810,13 @@
 		SET_TX_DESC_LINIP(pdesc, 0);
 		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
 
+		rcu_read_lock();
+		sta = ieee80211_find_sta(mac->vif, mac->bssid);
 		if (sta) {
 			u8 ampdu_density = sta->ht_cap.ampdu_density;
 			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
 		}
+		rcu_read_unlock();
 
 		if (info->control.hw_key) {
 			struct ieee80211_key_conf *keyconf =
@@ -854,14 +856,14 @@
 		}
 	}
 
-	SET_TX_DESC_FIRST_SEG(pdesc, (b_firstseg ? 1 : 0));
-	SET_TX_DESC_LAST_SEG(pdesc, (b_lastseg ? 1 : 0));
+	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
+	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
 
 	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
 
 	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
 
-	if (rtlpriv->dm.b_useramask) {
+	if (rtlpriv->dm.useramask) {
 		SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index);
 		SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id);
 	} else {
@@ -869,16 +871,16 @@
 		SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index);
 	}
 
-	if ((!ieee80211_is_data_qos(fc)) && ppsc->b_leisure_ps &&
-	    ppsc->b_fwctrl_lps) {
+	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
+	    ppsc->fwctrl_lps) {
 		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
 		SET_TX_DESC_PKT_ID(pdesc, 8);
 
-		if (!b_defaultadapter)
+		if (!defaultadapter)
 			SET_TX_DESC_QOS(pdesc, 1);
 	}
 
-	SET_TX_DESC_MORE_FRAG(pdesc, (b_lastseg ? 0 : 1));
+	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
 
 	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
 	    is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
@@ -889,8 +891,8 @@
 }
 
 void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
-			     u8 *pdesc, bool b_firstseg,
-			     bool b_lastseg, struct sk_buff *skb)
+			     u8 *pdesc, bool firstseg,
+			     bool lastseg, struct sk_buff *skb)
 {
 	struct rtl_priv *rtlpriv = rtl_priv(hw);
 	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
@@ -901,11 +903,11 @@
 					    PCI_DMA_TODEVICE);
 
 	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
-	u16 fc = le16_to_cpu(hdr->frame_control);
+	__le16 fc = hdr->frame_control;
 
 	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
 
-	if (b_firstseg)
+	if (firstseg)
 		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
 
 	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
@@ -1029,3 +1031,36 @@
 			       BIT(0) << (hw_queue));
 	}
 }
+
+bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
+			     struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl8192_tx_ring *ring;
+	struct rtl_tx_desc *pdesc;
+	u8 own;
+	unsigned long flags;
+	struct sk_buff *pskb = NULL;
+
+	ring = &rtlpci->tx_ring[BEACON_QUEUE];
+
+	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
+
+	pskb = __skb_dequeue(&ring->queue);
+	if (pskb)
+		kfree_skb(pskb);
+
+	pdesc = &ring->desc[0];
+	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
+
+	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
+
+	__skb_queue_tail(&ring->queue, skb);
+
+	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
+
+	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
+
+	return true;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192ce/trx.h	2011-05-19 00:06:34.000000000 -0400
@@ -40,470 +40,494 @@
 #define USB_HWDESC_HEADER_LEN			32
 #define CRCLENGTH				4
 
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __mask)		\
+	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\
+	BIT_LEN_MASK_32(__mask))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val)	\
+	(*(__le32 *)(__pdesc) = 				\
+	(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) &	\
+	(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) |		\
+	(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read/write various fields in RX or TX descriptors */
+
 #define SET_TX_DESC_PKT_SIZE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 16, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 0, 16, __val)
 #define SET_TX_DESC_OFFSET(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 16, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 16, 8, __val)
 #define SET_TX_DESC_BMC(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 24, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 24, 1, __val)
 #define SET_TX_DESC_HTC(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 25, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 25, 1, __val)
 #define SET_TX_DESC_LAST_SEG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 26, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 26, 1, __val)
 #define SET_TX_DESC_FIRST_SEG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 27, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 27, 1, __val)
 #define SET_TX_DESC_LINIP(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 28, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 28, 1, __val)
 #define SET_TX_DESC_NO_ACM(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 29, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 29, 1, __val)
 #define SET_TX_DESC_GF(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
 #define SET_TX_DESC_OWN(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
 
 #define GET_TX_DESC_PKT_SIZE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 0, 16)
+	SHIFT_AND_MASK_LE(__pdesc, 0, 16)
 #define GET_TX_DESC_OFFSET(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 16, 8)
+	SHIFT_AND_MASK_LE(__pdesc, 16, 8)
 #define GET_TX_DESC_BMC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 24, 1)
 #define GET_TX_DESC_HTC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 25, 1)
 #define GET_TX_DESC_LAST_SEG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 26, 1)
 #define GET_TX_DESC_FIRST_SEG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 27, 1)
 #define GET_TX_DESC_LINIP(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 28, 1)
 #define GET_TX_DESC_NO_ACM(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 29, 1)
 #define GET_TX_DESC_GF(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 30, 1)
 #define GET_TX_DESC_OWN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 31, 1)
 
 #define SET_TX_DESC_MACID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 0, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 0, 5, __val)
 #define SET_TX_DESC_AGG_BREAK(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 5, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 5, 1, __val)
 #define SET_TX_DESC_BK(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 6, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 6, 1, __val)
 #define SET_TX_DESC_RDG_ENABLE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 7, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 7, 1, __val)
 #define SET_TX_DESC_QUEUE_SEL(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 8, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 8, 5, __val)
 #define SET_TX_DESC_RDG_NAV_EXT(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 13, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 13, 1, __val)
 #define SET_TX_DESC_LSIG_TXOP_EN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 14, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 14, 1, __val)
 #define SET_TX_DESC_PIFS(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 15, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 15, 1, __val)
 #define SET_TX_DESC_RATE_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 16, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 16, 4, __val)
 #define SET_TX_DESC_NAV_USE_HDR(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 20, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 20, 1, __val)
 #define SET_TX_DESC_EN_DESC_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 21, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 21, 1, __val)
 #define SET_TX_DESC_SEC_TYPE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 22, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 22, 2, __val)
 #define SET_TX_DESC_PKT_OFFSET(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+4, 24, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+4, 24, 8, __val)
 
 #define GET_TX_DESC_MACID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
 #define GET_TX_DESC_AGG_ENABLE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 5, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 5, 1)
 #define GET_TX_DESC_AGG_BREAK(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 6, 1)
 #define GET_TX_DESC_RDG_ENABLE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 7, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 7, 1)
 #define GET_TX_DESC_QUEUE_SEL(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 8, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 8, 5)
 #define GET_TX_DESC_RDG_NAV_EXT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+4, 13, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 13, 1)
 #define GET_TX_DESC_LSIG_TXOP_EN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
 #define GET_TX_DESC_PIFS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
 #define GET_TX_DESC_RATE_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
 #define GET_TX_DESC_NAV_USE_HDR(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+4, 20, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 20, 1)
 #define GET_TX_DESC_EN_DESC_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 21, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 21, 1)
 #define GET_TX_DESC_SEC_TYPE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 22, 2)
+	SHIFT_AND_MASK_LE(__pdesc+4, 22, 2)
 #define GET_TX_DESC_PKT_OFFSET(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 24, 8)
+	SHIFT_AND_MASK_LE(__pdesc+4, 24, 8)
 
 #define SET_TX_DESC_RTS_RC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 0, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 0, 6, __val)
 #define SET_TX_DESC_DATA_RC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 6, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 6, 6, __val)
 #define SET_TX_DESC_BAR_RTY_TH(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 14, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 14, 2, __val)
 #define SET_TX_DESC_MORE_FRAG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 17, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 17, 1, __val)
 #define SET_TX_DESC_RAW(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 18, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 18, 1, __val)
 #define SET_TX_DESC_CCX(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 19, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 19, 1, __val)
 #define SET_TX_DESC_AMPDU_DENSITY(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 20, 3, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 20, 3, __val)
 #define SET_TX_DESC_ANTSEL_A(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 24, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 24, 1, __val)
 #define SET_TX_DESC_ANTSEL_B(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 25, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 25, 1, __val)
 #define SET_TX_DESC_TX_ANT_CCK(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 26, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 26, 2, __val)
 #define SET_TX_DESC_TX_ANTL(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 28, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 28, 2, __val)
 #define SET_TX_DESC_TX_ANT_HT(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+8, 30, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+8, 30, 2, __val)
 
 #define GET_TX_DESC_RTS_RC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 0, 6)
+	SHIFT_AND_MASK_LE(__pdesc+8, 0, 6)
 #define GET_TX_DESC_DATA_RC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 6, 6)
+	SHIFT_AND_MASK_LE(__pdesc+8, 6, 6)
 #define GET_TX_DESC_BAR_RTY_TH(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 14, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 14, 2)
 #define GET_TX_DESC_MORE_FRAG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 17, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 17, 1)
 #define GET_TX_DESC_RAW(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 18, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 18, 1)
 #define GET_TX_DESC_CCX(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 19, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 19, 1)
 #define GET_TX_DESC_AMPDU_DENSITY(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+8, 20, 3)
+	SHIFT_AND_MASK_LE(__pdesc+8, 20, 3)
 #define GET_TX_DESC_ANTSEL_A(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 24, 1)
 #define GET_TX_DESC_ANTSEL_B(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 25, 1)
 #define GET_TX_DESC_TX_ANT_CCK(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 26, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 26, 2)
 #define GET_TX_DESC_TX_ANTL(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 28, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 28, 2)
 #define GET_TX_DESC_TX_ANT_HT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 30, 2)
+	SHIFT_AND_MASK_LE(__pdesc+8, 30, 2)
 
 #define SET_TX_DESC_NEXT_HEAP_PAGE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 0, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 0, 8, __val)
 #define SET_TX_DESC_TAIL_PAGE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 8, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 8, 8, __val)
 #define SET_TX_DESC_SEQ(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 16, 12, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 16, 12, __val)
 #define SET_TX_DESC_PKT_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+12, 28, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+12, 28, 4, __val)
 
 #define GET_TX_DESC_NEXT_HEAP_PAGE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+12, 0, 8)
+	SHIFT_AND_MASK_LE(__pdesc+12, 0, 8)
 #define GET_TX_DESC_TAIL_PAGE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 8, 8)
+	SHIFT_AND_MASK_LE(__pdesc+12, 8, 8)
 #define GET_TX_DESC_SEQ(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 16, 12)
+	SHIFT_AND_MASK_LE(__pdesc+12, 16, 12)
 #define GET_TX_DESC_PKT_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 28, 4)
+	SHIFT_AND_MASK_LE(__pdesc+12, 28, 4)
 
 #define SET_TX_DESC_RTS_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 0, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 0, 5, __val)
 #define SET_TX_DESC_AP_DCFE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 5, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 5, 1, __val)
 #define SET_TX_DESC_QOS(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 6, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 6, 1, __val)
 #define SET_TX_DESC_HWSEQ_EN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 7, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 7, 1, __val)
 #define SET_TX_DESC_USE_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 8, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 8, 1, __val)
 #define SET_TX_DESC_DISABLE_RTS_FB(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 9, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 9, 1, __val)
 #define SET_TX_DESC_DISABLE_FB(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 10, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 10, 1, __val)
 #define SET_TX_DESC_CTS2SELF(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 11, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 11, 1, __val)
 #define SET_TX_DESC_RTS_ENABLE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 12, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 12, 1, __val)
 #define SET_TX_DESC_HW_RTS_ENABLE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 13, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 13, 1, __val)
 #define SET_TX_DESC_PORT_ID(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 14, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 14, 1, __val)
 #define SET_TX_DESC_WAIT_DCTS(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 18, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 18, 1, __val)
 #define SET_TX_DESC_CTS2AP_EN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 19, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 19, 1, __val)
 #define SET_TX_DESC_TX_SUB_CARRIER(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 20, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 20, 2, __val)
 #define SET_TX_DESC_TX_STBC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 22, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 22, 2, __val)
 #define SET_TX_DESC_DATA_SHORT(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 24, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 24, 1, __val)
 #define SET_TX_DESC_DATA_BW(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 25, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 25, 1, __val)
 #define SET_TX_DESC_RTS_SHORT(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 26, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 26, 1, __val)
 #define SET_TX_DESC_RTS_BW(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 27, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 27, 1, __val)
 #define SET_TX_DESC_RTS_SC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 28, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 28, 2, __val)
 #define SET_TX_DESC_RTS_STBC(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+16, 30, 2, __val)
+	SET_BITS_OFFSET_LE(__pdesc+16, 30, 2, __val)
 
 #define GET_TX_DESC_RTS_RATE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+16, 0, 5)
 #define GET_TX_DESC_AP_DCFE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 5, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 5, 1)
 #define GET_TX_DESC_QOS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 6, 1)
 #define GET_TX_DESC_HWSEQ_EN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 7, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 7, 1)
 #define GET_TX_DESC_USE_RATE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 8, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 8, 1)
 #define GET_TX_DESC_DISABLE_RTS_FB(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+16, 9, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 9, 1)
 #define GET_TX_DESC_DISABLE_FB(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 10, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 10, 1)
 #define GET_TX_DESC_CTS2SELF(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 11, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 11, 1)
 #define GET_TX_DESC_RTS_ENABLE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 12, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 12, 1)
 #define GET_TX_DESC_HW_RTS_ENABLE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+16, 13, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 13, 1)
 #define GET_TX_DESC_PORT_ID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 14, 1)
 #define GET_TX_DESC_WAIT_DCTS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 18, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 18, 1)
 #define GET_TX_DESC_CTS2AP_EN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 19, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 19, 1)
 #define GET_TX_DESC_TX_SUB_CARRIER(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+16, 20, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 20, 2)
 #define GET_TX_DESC_TX_STBC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 22, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 22, 2)
 #define GET_TX_DESC_DATA_SHORT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 24, 1)
 #define GET_TX_DESC_DATA_BW(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 25, 1)
 #define GET_TX_DESC_RTS_SHORT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 26, 1)
 #define GET_TX_DESC_RTS_BW(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc+16, 27, 1)
 #define GET_TX_DESC_RTS_SC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 28, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 28, 2)
 #define GET_TX_DESC_RTS_STBC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 30, 2)
+	SHIFT_AND_MASK_LE(__pdesc+16, 30, 2)
 
 #define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 0, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
 #define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 6, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
 #define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 7, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val)
 #define SET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 8, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 8, 5, __val)
 #define SET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 13, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 13, 4, __val)
 #define SET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 17, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 17, 1, __val)
 #define SET_TX_DESC_DATA_RETRY_LIMIT(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 18, 6, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 18, 6, __val)
 #define SET_TX_DESC_USB_TXAGG_NUM(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+20, 24, 8, __val)
+	SET_BITS_OFFSET_LE(__pdesc+20, 24, 8, __val)
 
 #define GET_TX_DESC_TX_RATE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+20, 0, 6)
+	SHIFT_AND_MASK_LE(__pdesc+20, 0, 6)
 #define GET_TX_DESC_DATA_SHORTGI(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+20, 6, 1)
 #define GET_TX_DESC_CCX_TAG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+20, 7, 1)
+	SHIFT_AND_MASK_LE(__pdesc+20, 7, 1)
 #define GET_TX_DESC_DATA_RATE_FB_LIMIT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 8, 5)
+	SHIFT_AND_MASK_LE(__pdesc+20, 8, 5)
 #define GET_TX_DESC_RTS_RATE_FB_LIMIT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 13, 4)
+	SHIFT_AND_MASK_LE(__pdesc+20, 13, 4)
 #define GET_TX_DESC_RETRY_LIMIT_ENABLE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 17, 1)
+	SHIFT_AND_MASK_LE(__pdesc+20, 17, 1)
 #define GET_TX_DESC_DATA_RETRY_LIMIT(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 18, 6)
+	SHIFT_AND_MASK_LE(__pdesc+20, 18, 6)
 #define GET_TX_DESC_USB_TXAGG_NUM(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+20, 24, 8)
+	SHIFT_AND_MASK_LE(__pdesc+20, 24, 8)
 
 #define SET_TX_DESC_TXAGC_A(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 0, 5, __val)
 #define SET_TX_DESC_TXAGC_B(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 5, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 5, 5, __val)
 #define SET_TX_DESC_USE_MAX_LEN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 10, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 10, 1, __val)
 #define SET_TX_DESC_MAX_AGG_NUM(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 11, 5, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 11, 5, __val)
 #define SET_TX_DESC_MCSG1_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 16, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 16, 4, __val)
 #define SET_TX_DESC_MCSG2_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 20, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 20, 4, __val)
 #define SET_TX_DESC_MCSG3_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 24, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 24, 4, __val)
 #define SET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 28, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 28, 4, __val)
 
 #define GET_TX_DESC_TXAGC_A(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+24, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+24, 0, 5)
 #define GET_TX_DESC_TXAGC_B(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+24, 5, 5)
+	SHIFT_AND_MASK_LE(__pdesc+24, 5, 5)
 #define GET_TX_DESC_USE_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 10, 1)
+	SHIFT_AND_MASK_LE(__pdesc+24, 10, 1)
 #define GET_TX_DESC_MAX_AGG_NUM(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 11, 5)
+	SHIFT_AND_MASK_LE(__pdesc+24, 11, 5)
 #define GET_TX_DESC_MCSG1_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 16, 4)
 #define GET_TX_DESC_MCSG2_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 20, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 20, 4)
 #define GET_TX_DESC_MCSG3_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 24, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 24, 4)
 #define GET_TX_DESC_MCS7_SGI_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+24, 28, 4)
+	SHIFT_AND_MASK_LE(__pdesc+24, 28, 4)
 
 #define SET_TX_DESC_TX_BUFFER_SIZE(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 16, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 0, 16, __val)
 #define SET_TX_DESC_MCSG4_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 16, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 16, 4, __val)
 #define SET_TX_DESC_MCSG5_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 20, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 20, 4, __val)
 #define SET_TX_DESC_MCSG6_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 24, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 24, 4, __val)
 #define SET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 28, 4, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 28, 4, __val)
 
 #define GET_TX_DESC_TX_BUFFER_SIZE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 0, 16)
+	SHIFT_AND_MASK_LE(__pdesc+28, 0, 16)
 #define GET_TX_DESC_MCSG4_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 16, 4)
 #define GET_TX_DESC_MCSG5_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 20, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 20, 4)
 #define GET_TX_DESC_MCSG6_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 24, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 24, 4)
 #define GET_TX_DESC_MCS15_SGI_MAX_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 28, 4)
+	SHIFT_AND_MASK_LE(__pdesc+28, 28, 4)
 
 #define SET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+32, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+32, 0, 32, __val)
 #define SET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc, __val) \
-	SET_BITS_TO_LE_4BYTE(__pdesc+36, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+36, 0, 32, __val)
 
 #define GET_TX_DESC_TX_BUFFER_ADDRESS(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+32, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+32, 0, 32)
 #define GET_TX_DESC_TX_BUFFER_ADDRESS64(__pdesc)	\
-	LE_BITS_TO_4BYTE(__pdesc+36, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+36, 0, 32)
 
 #define SET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc, __val)	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+40, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+40, 0, 32, __val)
 #define SET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc, __val) \
-	SET_BITS_TO_LE_4BYTE(__pdesc+44, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+44, 0, 32, __val)
 
 #define GET_TX_DESC_NEXT_DESC_ADDRESS(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+40, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+40, 0, 32)
 #define GET_TX_DESC_NEXT_DESC_ADDRESS64(__pdesc)	\
-	LE_BITS_TO_4BYTE(__pdesc+44, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+44, 0, 32)
 
 #define GET_RX_DESC_PKT_LEN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 0, 14)
+	SHIFT_AND_MASK_LE(__pdesc, 0, 14)
 #define GET_RX_DESC_CRC32(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 14, 1)
 #define GET_RX_DESC_ICV(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 15, 1)
 #define GET_RX_DESC_DRV_INFO_SIZE(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc, 16, 4)
 #define GET_RX_DESC_SECURITY(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 20, 3)
+	SHIFT_AND_MASK_LE(__pdesc, 20, 3)
 #define GET_RX_DESC_QOS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 23, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 23, 1)
 #define GET_RX_DESC_SHIFT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 24, 2)
+	SHIFT_AND_MASK_LE(__pdesc, 24, 2)
 #define GET_RX_DESC_PHYST(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 26, 1)
 #define GET_RX_DESC_SWDEC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 27, 1)
 #define GET_RX_DESC_LS(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc, 28, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 28, 1)
 #define GET_RX_DESC_FS(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc, 29, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 29, 1)
 #define GET_RX_DESC_EOR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 30, 1)
 #define GET_RX_DESC_OWN(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc, 31, 1)
 
 #define SET_RX_DESC_PKT_LEN(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 0, 14, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 0, 14, __val)
 #define SET_RX_DESC_EOR(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 30, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 30, 1, __val)
 #define SET_RX_DESC_OWN(__pdesc, __val)			\
-	SET_BITS_TO_LE_4BYTE(__pdesc, 31, 1, __val)
+	SET_BITS_OFFSET_LE(__pdesc, 31, 1, __val)
 
 #define GET_RX_DESC_MACID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 0, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 0, 5)
 #define GET_RX_DESC_TID(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 5, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 5, 4)
 #define GET_RX_DESC_HWRSVD(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 9, 5)
+	SHIFT_AND_MASK_LE(__pdesc+4, 9, 5)
 #define GET_RX_DESC_PAGGR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 14, 1)
 #define GET_RX_DESC_FAGGR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 15, 1)
 #define GET_RX_DESC_A1_FIT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 16, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 16, 4)
 #define GET_RX_DESC_A2_FIT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 20, 4)
+	SHIFT_AND_MASK_LE(__pdesc+4, 20, 4)
 #define GET_RX_DESC_PAM(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 24, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 24, 1)
 #define GET_RX_DESC_PWR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 25, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 25, 1)
 #define GET_RX_DESC_MD(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 26, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 26, 1)
 #define GET_RX_DESC_MF(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 27, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 27, 1)
 #define GET_RX_DESC_TYPE(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+4, 28, 2)
+	SHIFT_AND_MASK_LE(__pdesc+4, 28, 2)
 #define GET_RX_DESC_MC(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 30, 1)
 #define GET_RX_DESC_BC(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+4, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc+4, 31, 1)
 #define GET_RX_DESC_SEQ(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 0, 12)
+	SHIFT_AND_MASK_LE(__pdesc+8, 0, 12)
 #define GET_RX_DESC_FRAG(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 12, 4)
+	SHIFT_AND_MASK_LE(__pdesc+8, 12, 4)
 #define GET_RX_DESC_NEXT_PKT_LEN(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+8, 16, 14)
+	SHIFT_AND_MASK_LE(__pdesc+8, 16, 14)
 #define GET_RX_DESC_NEXT_IND(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 30, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 30, 1)
 #define GET_RX_DESC_RSVD(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+8, 31, 1)
+	SHIFT_AND_MASK_LE(__pdesc+8, 31, 1)
 
 #define GET_RX_DESC_RXMCS(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 0, 6)
+	SHIFT_AND_MASK_LE(__pdesc+12, 0, 6)
 #define GET_RX_DESC_RXHT(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 6, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 6, 1)
 #define GET_RX_DESC_SPLCP(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 8, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 8, 1)
 #define GET_RX_DESC_BW(__pdesc)				\
-	LE_BITS_TO_4BYTE(__pdesc+12, 9, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 9, 1)
 #define GET_RX_DESC_HTC(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 10, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 10, 1)
 #define GET_RX_DESC_HWPC_ERR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 14, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 14, 1)
 #define GET_RX_DESC_HWPC_IND(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 15, 1)
+	SHIFT_AND_MASK_LE(__pdesc+12, 15, 1)
 #define GET_RX_DESC_IV0(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+12, 16, 16)
+	SHIFT_AND_MASK_LE(__pdesc+12, 16, 16)
 
 #define GET_RX_DESC_IV1(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+16, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+16, 0, 32)
 #define GET_RX_DESC_TSFL(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+20, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+20, 0, 32)
 
 #define GET_RX_DESC_BUFF_ADDR(__pdesc)			\
-	LE_BITS_TO_4BYTE(__pdesc+24, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+24, 0, 32)
 #define GET_RX_DESC_BUFF_ADDR64(__pdesc)		\
-	LE_BITS_TO_4BYTE(__pdesc+28, 0, 32)
+	SHIFT_AND_MASK_LE(__pdesc+28, 0, 32)
 
 #define SET_RX_DESC_BUFF_ADDR(__pdesc, __val)		\
-	SET_BITS_TO_LE_4BYTE(__pdesc+24, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+24, 0, 32, __val)
 #define SET_RX_DESC_BUFF_ADDR64(__pdesc, __val) 	\
-	SET_BITS_TO_LE_4BYTE(__pdesc+28, 0, 32, __val)
+	SET_BITS_OFFSET_LE(__pdesc+28, 0, 32, __val)
 
 #define CLEAR_PCI_TX_DESC_CONTENT(__pdesc, _size)	\
 do {							\
@@ -711,4 +735,6 @@
 void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
 			     bool b_firstseg, bool b_lastseg,
 			     struct sk_buff *skb);
+bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/def.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/def.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/def.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/def.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/def.h"
+
+/*-------------------------------------------------------------------------
+ *	Chip specific
+ *-------------------------------------------------------------------------*/
+#define CHIP_8723			BIT(2) /* RTL8723 With BT feature */
+#define CHIP_8723_DRV_REV		BIT(3) /* RTL8723 Driver Revised */
+#define NORMAL_CHIP			BIT(4)
+#define CHIP_VENDOR_UMC			BIT(5)
+#define CHIP_VENDOR_UMC_B_CUT		BIT(6)
+
+#define IS_NORMAL_CHIP(version)		\
+	(((version) & NORMAL_CHIP) ? true : false)
+
+#define IS_8723_SERIES(version)		\
+	(((version) & CHIP_8723) ? true : false)
+
+#define IS_92C_1T2R(version)		\
+	(((version) & CHIP_92C) && ((version) & CHIP_92C_1T2R))
+
+#define IS_VENDOR_UMC(version)		\
+	(((version) & CHIP_VENDOR_UMC) ? true : false)
+
+#define IS_VENDOR_UMC_A_CUT(version)	\
+	(((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6) | BIT(7))) ? \
+	false : true) : false)
+
+#define IS_VENDOR_8723_A_CUT(version)	\
+	(((version) & CHIP_VENDOR_UMC) ? (((version) & (BIT(6))) ? \
+	false : true) : false)
+
+#define CHIP_BONDING_92C_1T2R	0x1
+#define CHIP_BONDING_IDENTIFIER(_value)	(((_value) >> 22) & 0x3)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,113 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "dm.h"
+
+void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undecorated_smoothed_pwdb;
+
+	if (!rtlpriv->dm.dynamic_txpower_enable)
+		return;
+
+	if (rtlpriv->dm.dm_flag & HAL_DM_HIPWR_DISABLE) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+
+	if ((mac->link_state < MAC80211_LINKED) &&
+	    (rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb == 0)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_TRACE,
+			 ("Not connected to any\n"));
+
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+
+		rtlpriv->dm.last_dtp_lvl = TXHIGHPWRLEVEL_NORMAL;
+		return;
+	}
+
+	if (mac->link_state >= MAC80211_LINKED) {
+		if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+			undecorated_smoothed_pwdb =
+			    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("AP Client PWDB = 0x%lx\n",
+				  undecorated_smoothed_pwdb));
+		} else {
+			undecorated_smoothed_pwdb =
+			    rtlpriv->dm.undecorated_smoothed_pwdb;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+				 ("STA Default Port PWDB = 0x%lx\n",
+				  undecorated_smoothed_pwdb));
+		}
+	} else {
+		undecorated_smoothed_pwdb =
+		    rtlpriv->dm.entry_min_undecoratedsmoothed_pwdb;
+
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("AP Ext Port PWDB = 0x%lx\n",
+			  undecorated_smoothed_pwdb));
+	}
+
+	if (undecorated_smoothed_pwdb >= TX_POWER_NEAR_FIELD_THRESH_LVL2) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x0)\n"));
+	} else if ((undecorated_smoothed_pwdb <
+		    (TX_POWER_NEAR_FIELD_THRESH_LVL2 - 3)) &&
+		   (undecorated_smoothed_pwdb >=
+		    TX_POWER_NEAR_FIELD_THRESH_LVL1)) {
+
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_LEVEL1;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("TXHIGHPWRLEVEL_LEVEL1 (TxPwr=0x10)\n"));
+	} else if (undecorated_smoothed_pwdb <
+		   (TX_POWER_NEAR_FIELD_THRESH_LVL1 - 5)) {
+		rtlpriv->dm.dynamic_txhighpower_lvl = TXHIGHPWRLEVEL_NORMAL;
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("TXHIGHPWRLEVEL_NORMAL\n"));
+	}
+
+	if ((rtlpriv->dm.dynamic_txhighpower_lvl != rtlpriv->dm.last_dtp_lvl)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD,
+			 ("PHY_SetTxPowerLevel8192S() Channel = %d\n",
+			  rtlphy->current_channel));
+		rtl92c_phy_set_txpower_level(hw, rtlphy->current_channel);
+	}
+
+	rtlpriv->dm.last_dtp_lvl = rtlpriv->dm.dynamic_txhighpower_lvl;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/dm.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,32 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/dm.h"
+
+void rtl92cu_dm_dynamic_txpower(struct ieee80211_hw *hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2504 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../efuse.h"
+#include "../base.h"
+#include "../cam.h"
+#include "../ps.h"
+#include "../usb.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "mac.h"
+#include "dm.h"
+#include "hw.h"
+#include "trx.h"
+#include "led.h"
+#include "table.h"
+
+static void _rtl92cu_phy_param_tab_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtlpriv);
+
+	rtlphy->hwparam_tables[MAC_REG].length = RTL8192CUMAC_2T_ARRAYLENGTH;
+	rtlphy->hwparam_tables[MAC_REG].pdata = RTL8192CUMAC_2T_ARRAY;
+	if (IS_HIGHT_PA(rtlefuse->board_type)) {
+		rtlphy->hwparam_tables[PHY_REG_PG].length =
+			RTL8192CUPHY_REG_Array_PG_HPLength;
+		rtlphy->hwparam_tables[PHY_REG_PG].pdata =
+			RTL8192CUPHY_REG_Array_PG_HP;
+	} else {
+		rtlphy->hwparam_tables[PHY_REG_PG].length =
+			RTL8192CUPHY_REG_ARRAY_PGLENGTH;
+		rtlphy->hwparam_tables[PHY_REG_PG].pdata =
+			RTL8192CUPHY_REG_ARRAY_PG;
+	}
+	/* 2T */
+	rtlphy->hwparam_tables[PHY_REG_2T].length =
+			RTL8192CUPHY_REG_2TARRAY_LENGTH;
+	rtlphy->hwparam_tables[PHY_REG_2T].pdata =
+			RTL8192CUPHY_REG_2TARRAY;
+	rtlphy->hwparam_tables[RADIOA_2T].length =
+			RTL8192CURADIOA_2TARRAYLENGTH;
+	rtlphy->hwparam_tables[RADIOA_2T].pdata =
+			RTL8192CURADIOA_2TARRAY;
+	rtlphy->hwparam_tables[RADIOB_2T].length =
+			RTL8192CURADIOB_2TARRAYLENGTH;
+	rtlphy->hwparam_tables[RADIOB_2T].pdata =
+			RTL8192CU_RADIOB_2TARRAY;
+	rtlphy->hwparam_tables[AGCTAB_2T].length =
+			RTL8192CUAGCTAB_2TARRAYLENGTH;
+	rtlphy->hwparam_tables[AGCTAB_2T].pdata =
+			RTL8192CUAGCTAB_2TARRAY;
+	/* 1T */
+	if (IS_HIGHT_PA(rtlefuse->board_type)) {
+		rtlphy->hwparam_tables[PHY_REG_1T].length =
+			RTL8192CUPHY_REG_1T_HPArrayLength;
+		rtlphy->hwparam_tables[PHY_REG_1T].pdata =
+			RTL8192CUPHY_REG_1T_HPArray;
+		rtlphy->hwparam_tables[RADIOA_1T].length =
+			RTL8192CURadioA_1T_HPArrayLength;
+		rtlphy->hwparam_tables[RADIOA_1T].pdata =
+			RTL8192CURadioA_1T_HPArray;
+		rtlphy->hwparam_tables[RADIOB_1T].length =
+			RTL8192CURADIOB_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[RADIOB_1T].pdata =
+			RTL8192CU_RADIOB_1TARRAY;
+		rtlphy->hwparam_tables[AGCTAB_1T].length =
+			RTL8192CUAGCTAB_1T_HPArrayLength;
+		rtlphy->hwparam_tables[AGCTAB_1T].pdata =
+			Rtl8192CUAGCTAB_1T_HPArray;
+	} else {
+		rtlphy->hwparam_tables[PHY_REG_1T].length =
+			 RTL8192CUPHY_REG_1TARRAY_LENGTH;
+		rtlphy->hwparam_tables[PHY_REG_1T].pdata =
+			RTL8192CUPHY_REG_1TARRAY;
+		rtlphy->hwparam_tables[RADIOA_1T].length =
+			RTL8192CURADIOA_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[RADIOA_1T].pdata =
+			RTL8192CU_RADIOA_1TARRAY;
+		rtlphy->hwparam_tables[RADIOB_1T].length =
+			RTL8192CURADIOB_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[RADIOB_1T].pdata =
+			RTL8192CU_RADIOB_1TARRAY;
+		rtlphy->hwparam_tables[AGCTAB_1T].length =
+			RTL8192CUAGCTAB_1TARRAYLENGTH;
+		rtlphy->hwparam_tables[AGCTAB_1T].pdata =
+			RTL8192CUAGCTAB_1TARRAY;
+	}
+}
+
+static void _rtl92cu_read_txpower_info_from_hwpg(struct ieee80211_hw *hw,
+						 bool autoload_fail,
+						 u8 *hwinfo)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 rf_path, index, tempval;
+	u16 i;
+
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 3; i++) {
+			if (!autoload_fail) {
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_cck[rf_path][i] =
+				    hwinfo[EEPROM_TXPOWERCCK + rf_path * 3 + i];
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] =
+				    hwinfo[EEPROM_TXPOWERHT40_1S + rf_path * 3 +
+					   i];
+			} else {
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_cck[rf_path][i] =
+				    EEPROM_DEFAULT_TXPOWERLEVEL;
+				rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_1s[rf_path][i] =
+				    EEPROM_DEFAULT_TXPOWERLEVEL;
+			}
+		}
+	}
+	for (i = 0; i < 3; i++) {
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWERHT40_2SDIFF + i];
+		else
+			tempval = EEPROM_DEFAULT_HT40_2SDIFF;
+		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_A][i] =
+		    (tempval & 0xf);
+		rtlefuse->eeprom_chnlarea_txpwr_ht40_2sdiif[RF90_PATH_B][i] =
+		    ((tempval & 0xf0) >> 4);
+	}
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				("RF(%d) EEPROM CCK Area(%d) = 0x%x\n", rf_path,
+				 i, rtlefuse->
+				 eeprom_chnlarea_txpwr_cck[rf_path][i]));
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				("RF(%d) EEPROM HT40 1S Area(%d) = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->
+				 eeprom_chnlarea_txpwr_ht40_1s[rf_path][i]));
+	for (rf_path = 0; rf_path < 2; rf_path++)
+		for (i = 0; i < 3; i++)
+			RTPRINT(rtlpriv, FINIT, INIT_EEPROM,
+				("RF(%d) EEPROM HT40 2S Diff Area(%d) = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->
+				 eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+				 [i]));
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = _rtl92c_get_chnl_group((u8) i);
+			rtlefuse->txpwrlevel_cck[rf_path][i] =
+			    rtlefuse->eeprom_chnlarea_txpwr_cck[rf_path][index];
+			rtlefuse->txpwrlevel_ht40_1s[rf_path][i] =
+			    rtlefuse->
+			    eeprom_chnlarea_txpwr_ht40_1s[rf_path][index];
+			if ((rtlefuse->
+			     eeprom_chnlarea_txpwr_ht40_1s[rf_path][index] -
+			     rtlefuse->
+			     eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path][index])
+			    > 0) {
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] =
+				    rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_1s[rf_path]
+				    [index] - rtlefuse->
+				    eeprom_chnlarea_txpwr_ht40_2sdiif[rf_path]
+				    [index];
+			} else {
+				rtlefuse->txpwrlevel_ht40_2s[rf_path][i] = 0;
+			}
+		}
+		for (i = 0; i < 14; i++) {
+			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+				("RF(%d)-Ch(%d) [CCK / HT40_1S / HT40_2S] = "
+				 "[0x%x / 0x%x / 0x%x]\n", rf_path, i,
+				 rtlefuse->txpwrlevel_cck[rf_path][i],
+				 rtlefuse->txpwrlevel_ht40_1s[rf_path][i],
+				 rtlefuse->txpwrlevel_ht40_2s[rf_path][i]));
+		}
+	}
+	for (i = 0; i < 3; i++) {
+		if (!autoload_fail) {
+			rtlefuse->eeprom_pwrlimit_ht40[i] =
+			    hwinfo[EEPROM_TXPWR_GROUP + i];
+			rtlefuse->eeprom_pwrlimit_ht20[i] =
+			    hwinfo[EEPROM_TXPWR_GROUP + 3 + i];
+		} else {
+			rtlefuse->eeprom_pwrlimit_ht40[i] = 0;
+			rtlefuse->eeprom_pwrlimit_ht20[i] = 0;
+		}
+	}
+	for (rf_path = 0; rf_path < 2; rf_path++) {
+		for (i = 0; i < 14; i++) {
+			index = _rtl92c_get_chnl_group((u8) i);
+			if (rf_path == RF90_PATH_A) {
+				rtlefuse->pwrgroup_ht20[rf_path][i] =
+				    (rtlefuse->eeprom_pwrlimit_ht20[index]
+				     & 0xf);
+				rtlefuse->pwrgroup_ht40[rf_path][i] =
+				    (rtlefuse->eeprom_pwrlimit_ht40[index]
+				     & 0xf);
+			} else if (rf_path == RF90_PATH_B) {
+				rtlefuse->pwrgroup_ht20[rf_path][i] =
+				    ((rtlefuse->eeprom_pwrlimit_ht20[index]
+				      & 0xf0) >> 4);
+				rtlefuse->pwrgroup_ht40[rf_path][i] =
+				    ((rtlefuse->eeprom_pwrlimit_ht40[index]
+				      & 0xf0) >> 4);
+			}
+			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+				("RF-%d pwrgroup_ht20[%d] = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->pwrgroup_ht20[rf_path][i]));
+			RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+				("RF-%d pwrgroup_ht40[%d] = 0x%x\n",
+				 rf_path, i,
+				 rtlefuse->pwrgroup_ht40[rf_path][i]));
+		}
+	}
+	for (i = 0; i < 14; i++) {
+		index = _rtl92c_get_chnl_group((u8) i);
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWERHT20DIFF + index];
+		else
+			tempval = EEPROM_DEFAULT_HT20_DIFF;
+		rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] = (tempval & 0xF);
+		rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] =
+		    ((tempval >> 4) & 0xF);
+		if (rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] & BIT(3))
+			rtlefuse->txpwr_ht20diff[RF90_PATH_A][i] |= 0xF0;
+		if (rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] & BIT(3))
+			rtlefuse->txpwr_ht20diff[RF90_PATH_B][i] |= 0xF0;
+		index = _rtl92c_get_chnl_group((u8) i);
+		if (!autoload_fail)
+			tempval = hwinfo[EEPROM_TXPOWER_OFDMDIFF + index];
+		else
+			tempval = EEPROM_DEFAULT_LEGACYHTTXPOWERDIFF;
+		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i] = (tempval & 0xF);
+		rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i] =
+		    ((tempval >> 4) & 0xF);
+	}
+	rtlefuse->legacy_ht_txpowerdiff =
+	    rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][7];
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			("RF-A Ht20 to HT40 Diff[%d] = 0x%x\n", i,
+			 rtlefuse->txpwr_ht20diff[RF90_PATH_A][i]));
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			("RF-A Legacy to Ht40 Diff[%d] = 0x%x\n", i,
+			 rtlefuse->txpwr_legacyhtdiff[RF90_PATH_A][i]));
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			("RF-B Ht20 to HT40 Diff[%d] = 0x%x\n", i,
+			 rtlefuse->txpwr_ht20diff[RF90_PATH_B][i]));
+	for (i = 0; i < 14; i++)
+		RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+			("RF-B Legacy to HT40 Diff[%d] = 0x%x\n", i,
+			 rtlefuse->txpwr_legacyhtdiff[RF90_PATH_B][i]));
+	if (!autoload_fail)
+		rtlefuse->eeprom_regulatory = (hwinfo[RF_OPTION1] & 0x7);
+	else
+		rtlefuse->eeprom_regulatory = 0;
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		("eeprom_regulatory = 0x%x\n", rtlefuse->eeprom_regulatory));
+	if (!autoload_fail) {
+		rtlefuse->eeprom_tssi[RF90_PATH_A] = hwinfo[EEPROM_TSSI_A];
+		rtlefuse->eeprom_tssi[RF90_PATH_B] = hwinfo[EEPROM_TSSI_B];
+	} else {
+		rtlefuse->eeprom_tssi[RF90_PATH_A] = EEPROM_DEFAULT_TSSI;
+		rtlefuse->eeprom_tssi[RF90_PATH_B] = EEPROM_DEFAULT_TSSI;
+	}
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		("TSSI_A = 0x%x, TSSI_B = 0x%x\n",
+		 rtlefuse->eeprom_tssi[RF90_PATH_A],
+		 rtlefuse->eeprom_tssi[RF90_PATH_B]));
+	if (!autoload_fail)
+		tempval = hwinfo[EEPROM_THERMAL_METER];
+	else
+		tempval = EEPROM_DEFAULT_THERMALMETER;
+	rtlefuse->eeprom_thermalmeter = (tempval & 0x1f);
+	if (rtlefuse->eeprom_thermalmeter < 0x06 ||
+	    rtlefuse->eeprom_thermalmeter > 0x1c)
+		rtlefuse->eeprom_thermalmeter = 0x12;
+	if (rtlefuse->eeprom_thermalmeter == 0x1f || autoload_fail)
+		rtlefuse->apk_thermalmeterignore = true;
+	rtlefuse->thermalmeter[0] = rtlefuse->eeprom_thermalmeter;
+	RTPRINT(rtlpriv, FINIT, INIT_TxPower,
+		("thermalmeter = 0x%x\n", rtlefuse->eeprom_thermalmeter));
+}
+
+static void _rtl92cu_read_board_type(struct ieee80211_hw *hw, u8 *contents)
+{
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 boardType;
+
+	if (IS_NORMAL_CHIP(rtlhal->version)) {
+		boardType = ((contents[EEPROM_RF_OPT1]) &
+			    BOARD_TYPE_NORMAL_MASK) >> 5; /*bit[7:5]*/
+	} else {
+		boardType = contents[EEPROM_RF_OPT4];
+		boardType &= BOARD_TYPE_TEST_MASK;
+	}
+	rtlefuse->board_type = boardType;
+	if (IS_HIGHT_PA(rtlefuse->board_type))
+		rtlefuse->external_pa = 1;
+	printk(KERN_INFO "rtl8192cu: Board Type %x\n", rtlefuse->board_type);
+
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	/* Antenna Diversity setting. */
+	if (registry_par->antdiv_cfg == 2) /* 2: From Efuse */
+		rtl_efuse->antenna_cfg = (contents[EEPROM_RF_OPT1]&0x18)>>3;
+	else
+		rtl_efuse->antenna_cfg = registry_par->antdiv_cfg; /* 0:OFF, */
+
+	printk(KERN_INFO "rtl8192cu: Antenna Config %x\n",
+	       rtl_efuse->antenna_cfg);
+#endif
+}
+
+#ifdef CONFIG_BT_COEXIST
+static void _update_bt_param(_adapter *padapter)
+{
+	struct btcoexist_priv	 *pbtpriv = &(padapter->halpriv.bt_coexist);
+	struct registry_priv	*registry_par = &padapter->registrypriv;
+	if (2 != registry_par->bt_iso) {
+		/* 0:Low, 1:High, 2:From Efuse */
+		pbtpriv->BT_Ant_isolation = registry_par->bt_iso;
+	}
+	if (registry_par->bt_sco == 1) {
+		/* 0:Idle, 1:None-SCO, 2:SCO, 3:From Counter, 4.Busy,
+		 * 5.OtherBusy */
+		pbtpriv->BT_Service = BT_OtherAction;
+	} else if (registry_par->bt_sco == 2) {
+		pbtpriv->BT_Service = BT_SCO;
+	} else if (registry_par->bt_sco == 4) {
+		pbtpriv->BT_Service = BT_Busy;
+	} else if (registry_par->bt_sco == 5) {
+		pbtpriv->BT_Service = BT_OtherBusy;
+	} else {
+		pbtpriv->BT_Service = BT_Idle;
+	}
+	pbtpriv->BT_Ampdu = registry_par->bt_ampdu;
+	pbtpriv->bCOBT = _TRUE;
+	pbtpriv->BtEdcaUL = 0;
+	pbtpriv->BtEdcaDL = 0;
+	pbtpriv->BtRssiState = 0xff;
+	pbtpriv->bInitSet = _FALSE;
+	pbtpriv->bBTBusyTraffic = _FALSE;
+	pbtpriv->bBTTrafficModeSet = _FALSE;
+	pbtpriv->bBTNonTrafficModeSet = _FALSE;
+	pbtpriv->CurrentState = 0;
+	pbtpriv->PreviousState = 0;
+	printk(KERN_INFO "rtl8192cu: BT Coexistance = %s\n",
+	       (pbtpriv->BT_Coexist == _TRUE) ? "enable" : "disable");
+	if (pbtpriv->BT_Coexist) {
+		if (pbtpriv->BT_Ant_Num == Ant_x2)
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "Ant_Num = Antx2\n");
+		else if (pbtpriv->BT_Ant_Num == Ant_x1)
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "Ant_Num = Antx1\n");
+		switch (pbtpriv->BT_CoexistType) {
+		case BT_2Wire:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_2Wire\n");
+			break;
+		case BT_ISSC_3Wire:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_ISSC_3Wire\n");
+			break;
+		case BT_Accel:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_Accel\n");
+			break;
+		case BT_CSR_BC4:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_CSR_BC4\n");
+			break;
+		case BT_CSR_BC8:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_CSR_BC8\n");
+			break;
+		case BT_RTL8756:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = BT_RTL8756\n");
+			break;
+		default:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_"
+			       "CoexistType = Unknown\n");
+			break;
+		}
+		printk(KERN_INFO "rtl8192cu: BlueTooth BT_Ant_isolation = %d\n",
+		       pbtpriv->BT_Ant_isolation);
+		switch (pbtpriv->BT_Service) {
+		case BT_OtherAction:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_OtherAction\n");
+			break;
+		case BT_SCO:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_SCO\n");
+			break;
+		case BT_Busy:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_Busy\n");
+			break;
+		case BT_OtherBusy:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_OtherBusy\n");
+			break;
+		default:
+			printk(KERN_INFO "rtl8192cu: BlueTooth BT_Service = "
+			       "BT_Idle\n");
+			break;
+		}
+		printk(KERN_INFO "rtl8192cu: BT_RadioSharedType = 0x%x\n",
+		       pbtpriv->BT_RadioSharedType);
+	}
+}
+
+#define GET_BT_COEXIST(priv) (&priv->bt_coexist)
+
+static void _rtl92cu_read_bluetooth_coexistInfo(struct ieee80211_hw *hw,
+						u8 *contents,
+						bool bautoloadfailed);
+{
+	HAL_DATA_TYPE	*pHalData = GET_HAL_DATA(Adapter);
+	bool isNormal = IS_NORMAL_CHIP(pHalData->VersionID);
+	struct btcoexist_priv	 *pbtpriv = &pHalData->bt_coexist;
+	u8	rf_opt4;
+
+	_rtw_memset(pbtpriv, 0, sizeof(struct btcoexist_priv));
+	if (AutoloadFail) {
+		pbtpriv->BT_Coexist = _FALSE;
+		pbtpriv->BT_CoexistType = BT_2Wire;
+		pbtpriv->BT_Ant_Num = Ant_x2;
+		pbtpriv->BT_Ant_isolation = 0;
+		pbtpriv->BT_RadioSharedType = BT_Radio_Shared;
+		return;
+	}
+	if (isNormal) {
+		if (pHalData->BoardType == BOARD_USB_COMBO)
+			pbtpriv->BT_Coexist = _TRUE;
+		else
+			pbtpriv->BT_Coexist = ((PROMContent[EEPROM_RF_OPT3] &
+					      0x20) >> 5); /* bit[5] */
+		rf_opt4 = PROMContent[EEPROM_RF_OPT4];
+		pbtpriv->BT_CoexistType = ((rf_opt4&0xe)>>1); /* bit [3:1] */
+		pbtpriv->BT_Ant_Num = (rf_opt4&0x1); /* bit [0] */
+		pbtpriv->BT_Ant_isolation = ((rf_opt4&0x10)>>4); /* bit [4] */
+		pbtpriv->BT_RadioSharedType = ((rf_opt4&0x20)>>5); /* bit [5] */
+	} else {
+		pbtpriv->BT_Coexist = (PROMContent[EEPROM_RF_OPT4] >> 4) ?
+				       _TRUE : _FALSE;
+	}
+	_update_bt_param(Adapter);
+}
+#endif
+
+static void _rtl92cu_read_adapter_info(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u16 i, usvalue;
+	u8 hwinfo[HWSET_MAX_SIZE] = {0};
+	u16 eeprom_id;
+
+	if (rtlefuse->epromtype == EEPROM_BOOT_EFUSE) {
+		rtl_efuse_shadow_map_update(hw);
+		memcpy((void *)hwinfo,
+		       (void *)&rtlefuse->efuse_map[EFUSE_INIT_MAP][0],
+		       HWSET_MAX_SIZE);
+	} else if (rtlefuse->epromtype == EEPROM_93C46) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("RTL819X Not boot from eeprom, check it !!"));
+	}
+	RT_PRINT_DATA(rtlpriv, COMP_INIT, DBG_LOUD, ("MAP\n"),
+		      hwinfo, HWSET_MAX_SIZE);
+	eeprom_id = *((u16 *)&hwinfo[0]);
+	if (eeprom_id != RTL8190_EEPROM_ID) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("EEPROM ID(%#x) is invalid!!\n", eeprom_id));
+		rtlefuse->autoload_failflag = true;
+	} else {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload OK\n"));
+		rtlefuse->autoload_failflag = false;
+	}
+	if (rtlefuse->autoload_failflag == true)
+		return;
+	for (i = 0; i < 6; i += 2) {
+		usvalue = *(u16 *)&hwinfo[EEPROM_MAC_ADDR + i];
+		*((u16 *) (&rtlefuse->dev_addr[i])) = usvalue;
+	}
+	printk(KERN_INFO "rtl8192cu: MAC address: %pM\n", rtlefuse->dev_addr);
+	_rtl92cu_read_txpower_info_from_hwpg(hw,
+					   rtlefuse->autoload_failflag, hwinfo);
+	rtlefuse->eeprom_vid = *(u16 *)&hwinfo[EEPROM_VID];
+	rtlefuse->eeprom_did = *(u16 *)&hwinfo[EEPROM_DID];
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 (" VID = 0x%02x PID = 0x%02x\n",
+		 rtlefuse->eeprom_vid, rtlefuse->eeprom_did));
+	rtlefuse->eeprom_channelplan = *(u8 *)&hwinfo[EEPROM_CHANNELPLAN];
+	rtlefuse->eeprom_version = *(u16 *)&hwinfo[EEPROM_VERSION];
+	rtlefuse->txpwr_fromeprom = true;
+	rtlefuse->eeprom_oemid = *(u8 *)&hwinfo[EEPROM_CUSTOMER_ID];
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("EEPROM Customer ID: 0x%2x\n", rtlefuse->eeprom_oemid));
+	if (rtlhal->oem_id == RT_CID_DEFAULT) {
+		switch (rtlefuse->eeprom_oemid) {
+		case EEPROM_CID_DEFAULT:
+			if (rtlefuse->eeprom_did == 0x8176) {
+				if ((rtlefuse->eeprom_svid == 0x103C &&
+				     rtlefuse->eeprom_smid == 0x1629))
+					rtlhal->oem_id = RT_CID_819x_HP;
+				else
+					rtlhal->oem_id = RT_CID_DEFAULT;
+			} else {
+				rtlhal->oem_id = RT_CID_DEFAULT;
+			}
+			break;
+		case EEPROM_CID_TOSHIBA:
+			rtlhal->oem_id = RT_CID_TOSHIBA;
+			break;
+		case EEPROM_CID_QMI:
+			rtlhal->oem_id = RT_CID_819x_QMI;
+			break;
+		case EEPROM_CID_WHQL:
+		default:
+			rtlhal->oem_id = RT_CID_DEFAULT;
+			break;
+		}
+	}
+	_rtl92cu_read_board_type(hw, hwinfo);
+#ifdef CONFIG_BT_COEXIST
+	_rtl92cu_read_bluetooth_coexistInfo(hw, hwinfo,
+					    rtlefuse->autoload_failflag);
+#endif
+}
+
+static void _rtl92cu_hal_customized_behavior(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	switch (rtlhal->oem_id) {
+	case RT_CID_819x_HP:
+		usb_priv->ledctl.led_opendrain = true;
+		break;
+	case RT_CID_819x_Lenovo:
+	case RT_CID_DEFAULT:
+	case RT_CID_TOSHIBA:
+	case RT_CID_CCX:
+	case RT_CID_819x_Acer:
+	case RT_CID_WHQL:
+	default:
+		break;
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 ("RT Customized ID: 0x%02X\n", rtlhal->oem_id));
+}
+
+void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw)
+{
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 tmp_u1b;
+
+	if (!IS_NORMAL_CHIP(rtlhal->version))
+		return;
+	tmp_u1b = rtl_read_byte(rtlpriv, REG_9346CR);
+	rtlefuse->epromtype = (tmp_u1b & EEPROMSEL) ?
+			       EEPROM_93C46 : EEPROM_BOOT_EFUSE;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Boot from %s\n",
+		 (tmp_u1b & EEPROMSEL) ? "EERROM" : "EFUSE"));
+	rtlefuse->autoload_failflag = (tmp_u1b & EEPROM_EN) ? false : true;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("Autoload %s\n",
+		 (tmp_u1b & EEPROM_EN) ? "OK!!" : "ERR!!"));
+	_rtl92cu_read_adapter_info(hw);
+	_rtl92cu_hal_customized_behavior(hw);
+	return;
+}
+
+static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int		status = 0;
+	u16		value16;
+	u8		value8;
+	/*  polling autoload done. */
+	u32	pollingCount = 0;
+
+	do {
+		if (rtl_read_byte(rtlpriv, REG_APS_FSMCO) & PFM_ALDN) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+				 ("Autoload Done!\n"));
+			break;
+		}
+		if (pollingCount++ > 100) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+				 ("Failed to polling REG_APS_FSMCO[PFM_ALDN]"
+				 " done!\n"));
+			return -ENODEV;
+		}
+	} while (true);
+	/* 0. RSV_CTRL 0x1C[7:0] = 0 unlock ISO/CLK/Power control register */
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0);
+	/* Power on when re-enter from IPS/Radio off/card disable */
+	/* enable SPS into PWM mode */
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x2b);
+	udelay(100);
+	value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL);
+	if (0 == (value8 & LDV12_EN)) {
+		value8 |= LDV12_EN;
+		rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8);
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 (" power-on :REG_LDOV12D_CTRL Reg0x21:0x%02x.\n",
+			 value8));
+		udelay(100);
+		value8 = rtl_read_byte(rtlpriv, REG_SYS_ISO_CTRL);
+		value8 &= ~ISO_MD2PP;
+		rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, value8);
+	}
+	/*  auto enable WLAN */
+	pollingCount = 0;
+	value16 = rtl_read_word(rtlpriv, REG_APS_FSMCO);
+	value16 |= APFM_ONMAC;
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, value16);
+	do {
+		if (!(rtl_read_word(rtlpriv, REG_APS_FSMCO) & APFM_ONMAC)) {
+			printk(KERN_INFO "rtl8192cu: MAC auto ON okay!\n");
+			break;
+		}
+		if (pollingCount++ > 100) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+				 ("Failed to polling REG_APS_FSMCO[APFM_ONMAC]"
+				 " done!\n"));
+			return -ENODEV;
+		}
+	} while (true);
+	/* Enable Radio ,GPIO ,and LED function */
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x0812);
+	/* release RF digital isolation */
+	value16 = rtl_read_word(rtlpriv, REG_SYS_ISO_CTRL);
+	value16 &= ~ISO_DIOR;
+	rtl_write_word(rtlpriv, REG_SYS_ISO_CTRL, value16);
+	/* Reconsider when to do this operation after asking HWSD. */
+	pollingCount = 0;
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, (rtl_read_byte(rtlpriv,
+						REG_APSD_CTRL) & ~BIT(6)));
+	do {
+		pollingCount++;
+	} while ((pollingCount < 200) &&
+		 (rtl_read_byte(rtlpriv, REG_APSD_CTRL) & BIT(7)));
+	/* Enable MAC DMA/WMAC/SCHEDULE/SEC block */
+	value16 = rtl_read_word(rtlpriv,  REG_CR);
+	value16 |= (HCI_TXDMA_EN | HCI_RXDMA_EN | TXDMA_EN | RXDMA_EN |
+		    PROTOCOL_EN | SCHEDULE_EN | MACTXEN | MACRXEN | ENSEC);
+	rtl_write_word(rtlpriv, REG_CR, value16);
+	return status;
+}
+
+static void _rtl92cu_init_queue_reserved_page(struct ieee80211_hw *hw,
+					      bool wmm_enable,
+					      u8 out_ep_num,
+					      u8 queue_sel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool isChipN = IS_NORMAL_CHIP(rtlhal->version);
+	u32 outEPNum = (u32)out_ep_num;
+	u32 numHQ = 0;
+	u32 numLQ = 0;
+	u32 numNQ = 0;
+	u32 numPubQ;
+	u32 value32;
+	u8 value8;
+	u32 txQPageNum, txQPageUnit, txQRemainPage;
+
+	if (!wmm_enable) {
+		numPubQ = (isChipN) ? CHIP_B_PAGE_NUM_PUBQ :
+			  CHIP_A_PAGE_NUM_PUBQ;
+		txQPageNum = TX_TOTAL_PAGE_NUMBER - numPubQ;
+
+		txQPageUnit = txQPageNum/outEPNum;
+		txQRemainPage = txQPageNum % outEPNum;
+		if (queue_sel & TX_SELE_HQ)
+			numHQ = txQPageUnit;
+		if (queue_sel & TX_SELE_LQ)
+			numLQ = txQPageUnit;
+		/* HIGH priority queue always present in the configuration of
+		 * 2 out-ep. Remainder pages have assigned to High queue */
+		if ((outEPNum > 1) && (txQRemainPage))
+			numHQ += txQRemainPage;
+		/* NOTE: This step done before writting REG_RQPN. */
+		if (isChipN) {
+			if (queue_sel & TX_SELE_NQ)
+				numNQ = txQPageUnit;
+			value8 = (u8)_NPQ(numNQ);
+			rtl_write_byte(rtlpriv,  REG_RQPN_NPQ, value8);
+		}
+	} else {
+		/* for WMM ,number of out-ep must more than or equal to 2! */
+		numPubQ = isChipN ? WMM_CHIP_B_PAGE_NUM_PUBQ :
+			  WMM_CHIP_A_PAGE_NUM_PUBQ;
+		if (queue_sel & TX_SELE_HQ) {
+			numHQ = isChipN ? WMM_CHIP_B_PAGE_NUM_HPQ :
+				WMM_CHIP_A_PAGE_NUM_HPQ;
+		}
+		if (queue_sel & TX_SELE_LQ) {
+			numLQ = isChipN ? WMM_CHIP_B_PAGE_NUM_LPQ :
+				WMM_CHIP_A_PAGE_NUM_LPQ;
+		}
+		/* NOTE: This step done before writting REG_RQPN. */
+		if (isChipN) {
+			if (queue_sel & TX_SELE_NQ)
+				numNQ = WMM_CHIP_B_PAGE_NUM_NPQ;
+			value8 = (u8)_NPQ(numNQ);
+			rtl_write_byte(rtlpriv, REG_RQPN_NPQ, value8);
+		}
+	}
+	/* TX DMA */
+	value32 = _HPQ(numHQ) | _LPQ(numLQ) | _PUBQ(numPubQ) | LD_RQPN;
+	rtl_write_dword(rtlpriv, REG_RQPN, value32);
+}
+
+static void _rtl92c_init_trx_buffer(struct ieee80211_hw *hw, bool wmm_enable)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8	txpktbuf_bndy;
+	u8	value8;
+
+	if (!wmm_enable)
+		txpktbuf_bndy = TX_PAGE_BOUNDARY;
+	else /* for WMM */
+		txpktbuf_bndy = (IS_NORMAL_CHIP(rtlhal->version))
+						? WMM_CHIP_B_TX_PAGE_BOUNDARY
+						: WMM_CHIP_A_TX_PAGE_BOUNDARY;
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_BCNQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_MGQ_BDNY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TXPKTBUF_WMAC_LBK_BF_HD, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TRXFF_BNDY, txpktbuf_bndy);
+	rtl_write_byte(rtlpriv, REG_TDECTRL+1, txpktbuf_bndy);
+	rtl_write_word(rtlpriv,  (REG_TRXFF_BNDY + 2), 0x27FF);
+	value8 = _PSRX(RX_PAGE_SIZE_REG_VALUE) | _PSTX(PBP_128);
+	rtl_write_byte(rtlpriv, REG_PBP, value8);
+}
+
+static void _rtl92c_init_chipN_reg_priority(struct ieee80211_hw *hw, u16 beQ,
+					    u16 bkQ, u16 viQ, u16 voQ,
+					    u16 mgtQ, u16 hiQ)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u16 value16 = (rtl_read_word(rtlpriv, REG_TRXDMA_CTRL) & 0x7);
+
+	value16 |= _TXDMA_BEQ_MAP(beQ) | _TXDMA_BKQ_MAP(bkQ) |
+		   _TXDMA_VIQ_MAP(viQ) | _TXDMA_VOQ_MAP(voQ) |
+		   _TXDMA_MGQ_MAP(mgtQ) | _TXDMA_HIQ_MAP(hiQ);
+	rtl_write_word(rtlpriv,  REG_TRXDMA_CTRL, value16);
+}
+
+static void _rtl92cu_init_chipN_one_out_ep_priority(struct ieee80211_hw *hw,
+						    bool wmm_enable,
+						    u8 queue_sel)
+{
+	u16 uninitialized_var(value);
+
+	switch (queue_sel) {
+	case TX_SELE_HQ:
+		value = QUEUE_HIGH;
+		break;
+	case TX_SELE_LQ:
+		value = QUEUE_LOW;
+		break;
+	case TX_SELE_NQ:
+		value = QUEUE_NORMAL;
+		break;
+	default:
+		WARN_ON(1); /* Shall not reach here! */
+		break;
+	}
+	_rtl92c_init_chipN_reg_priority(hw, value, value, value, value,
+					value, value);
+	printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+}
+
+static void _rtl92cu_init_chipN_two_out_ep_priority(struct ieee80211_hw *hw,
+								bool wmm_enable,
+								u8 queue_sel)
+{
+	u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+	u16 uninitialized_var(valueHi);
+	u16 uninitialized_var(valueLow);
+
+	switch (queue_sel) {
+	case (TX_SELE_HQ | TX_SELE_LQ):
+		valueHi = QUEUE_HIGH;
+		valueLow = QUEUE_LOW;
+		break;
+	case (TX_SELE_NQ | TX_SELE_LQ):
+		valueHi = QUEUE_NORMAL;
+		valueLow = QUEUE_LOW;
+		break;
+	case (TX_SELE_HQ | TX_SELE_NQ):
+		valueHi = QUEUE_HIGH;
+		valueLow = QUEUE_NORMAL;
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+	if (!wmm_enable) {
+		beQ = valueLow;
+		bkQ = valueLow;
+		viQ = valueHi;
+		voQ = valueHi;
+		mgtQ = valueHi;
+		hiQ = valueHi;
+	} else {/* for WMM ,CONFIG_OUT_EP_WIFI_MODE */
+		beQ = valueHi;
+		bkQ = valueLow;
+		viQ = valueLow;
+		voQ = valueHi;
+		mgtQ = valueHi;
+		hiQ = valueHi;
+	}
+	_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+	printk(KERN_INFO "rtl8192cu: Tx queue select: 0x%02x\n", queue_sel);
+}
+
+static void _rtl92cu_init_chipN_three_out_ep_priority(struct ieee80211_hw *hw,
+						      bool wmm_enable,
+						      u8 queue_sel)
+{
+	u16 beQ, bkQ, viQ, voQ, mgtQ, hiQ;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (!wmm_enable) { /* typical setting */
+		beQ	= QUEUE_LOW;
+		bkQ	= QUEUE_LOW;
+		viQ	= QUEUE_NORMAL;
+		voQ	= QUEUE_HIGH;
+		mgtQ	= QUEUE_HIGH;
+		hiQ	= QUEUE_HIGH;
+	} else { /* for WMM */
+		beQ	= QUEUE_LOW;
+		bkQ	= QUEUE_NORMAL;
+		viQ	= QUEUE_NORMAL;
+		voQ	= QUEUE_HIGH;
+		mgtQ	= QUEUE_HIGH;
+		hiQ	= QUEUE_HIGH;
+	}
+	_rtl92c_init_chipN_reg_priority(hw, beQ, bkQ, viQ, voQ, mgtQ, hiQ);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+		 ("Tx queue select :0x%02x..\n", queue_sel));
+}
+
+static void _rtl92cu_init_chipN_queue_priority(struct ieee80211_hw *hw,
+					       bool wmm_enable,
+					       u8 out_ep_num,
+					       u8 queue_sel)
+{
+	switch (out_ep_num) {
+	case 1:
+		_rtl92cu_init_chipN_one_out_ep_priority(hw, wmm_enable,
+							queue_sel);
+		break;
+	case 2:
+		_rtl92cu_init_chipN_two_out_ep_priority(hw, wmm_enable,
+							queue_sel);
+		break;
+	case 3:
+		_rtl92cu_init_chipN_three_out_ep_priority(hw, wmm_enable,
+							  queue_sel);
+		break;
+	default:
+		WARN_ON(1); /* Shall not reach here! */
+		break;
+	}
+}
+
+static void _rtl92cu_init_chipT_queue_priority(struct ieee80211_hw *hw,
+					       bool wmm_enable,
+					       u8 out_ep_num,
+					       u8 queue_sel)
+{
+	u8	hq_sele;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	switch (out_ep_num) {
+	case 2:	/* (TX_SELE_HQ|TX_SELE_LQ) */
+		if (!wmm_enable) /* typical setting */
+			hq_sele =  HQSEL_VOQ | HQSEL_VIQ | HQSEL_MGTQ |
+				   HQSEL_HIQ;
+		else	/* for WMM */
+			hq_sele = HQSEL_VOQ | HQSEL_BEQ | HQSEL_MGTQ |
+				  HQSEL_HIQ;
+		break;
+	case 1:
+		if (TX_SELE_LQ == queue_sel) {
+			/* map all endpoint to Low queue */
+			hq_sele = 0;
+		} else if (TX_SELE_HQ == queue_sel) {
+			/* map all endpoint to High queue */
+			hq_sele =  HQSEL_VOQ | HQSEL_VIQ | HQSEL_BEQ |
+				   HQSEL_BKQ | HQSEL_MGTQ | HQSEL_HIQ;
+		}
+		break;
+	default:
+		WARN_ON(1); /* Shall not reach here! */
+		break;
+	}
+	rtl_write_byte(rtlpriv, (REG_TRXDMA_CTRL+1), hq_sele);
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+		 ("Tx queue select :0x%02x..\n", hq_sele));
+}
+
+static void _rtl92cu_init_queue_priority(struct ieee80211_hw *hw,
+						bool wmm_enable,
+						u8 out_ep_num,
+						u8 queue_sel)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		_rtl92cu_init_chipN_queue_priority(hw, wmm_enable, out_ep_num,
+						   queue_sel);
+	else
+		_rtl92cu_init_chipT_queue_priority(hw, wmm_enable, out_ep_num,
+						   queue_sel);
+}
+
+static void _rtl92cu_init_usb_aggregation(struct ieee80211_hw *hw)
+{
+}
+
+static void _rtl92cu_init_wmac_setting(struct ieee80211_hw *hw)
+{
+	u16			value16;
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	mac->rx_conf = (RCR_APM | RCR_AM | RCR_ADF | RCR_AB | RCR_APP_FCS |
+		      RCR_APP_ICV | RCR_AMF | RCR_HTC_LOC_CTRL |
+		      RCR_APP_MIC | RCR_APP_PHYSTS | RCR_ACRC32);
+	rtl_write_dword(rtlpriv, REG_RCR, mac->rx_conf);
+	/* Accept all multicast address */
+	rtl_write_dword(rtlpriv,  REG_MAR, 0xFFFFFFFF);
+	rtl_write_dword(rtlpriv,  REG_MAR + 4, 0xFFFFFFFF);
+	/* Accept all management frames */
+	value16 = 0xFFFF;
+	rtl92c_set_mgt_filter(hw, value16);
+	/* Reject all control frame - default value is 0 */
+	rtl92c_set_ctrl_filter(hw, 0x0);
+	/* Accept all data frames */
+	value16 = 0xFFFF;
+	rtl92c_set_data_filter(hw, value16);
+}
+
+static int _rtl92cu_init_mac(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+	int err = 0;
+	u32	boundary = 0;
+	u8 wmm_enable = false; /* TODO */
+	u8 out_ep_nums = rtlusb->out_ep_nums;
+	u8 queue_sel = rtlusb->out_queue_sel;
+	err = _rtl92cu_init_power_on(hw);
+
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			("Failed to init power on!\n"));
+		return err;
+	}
+	if (!wmm_enable) {
+		boundary = TX_PAGE_BOUNDARY;
+	} else { /* for WMM */
+		boundary = (IS_NORMAL_CHIP(rtlhal->version))
+					? WMM_CHIP_B_TX_PAGE_BOUNDARY
+					: WMM_CHIP_A_TX_PAGE_BOUNDARY;
+	}
+	if (false == rtl92c_init_llt_table(hw, boundary)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			("Failed to init LLT Table!\n"));
+		return -EINVAL;
+	}
+	_rtl92cu_init_queue_reserved_page(hw, wmm_enable, out_ep_nums,
+					  queue_sel);
+	_rtl92c_init_trx_buffer(hw, wmm_enable);
+	_rtl92cu_init_queue_priority(hw, wmm_enable, out_ep_nums,
+				     queue_sel);
+	/* Get Rx PHY status in order to report RSSI and others. */
+	rtl92c_init_driver_info_size(hw, RTL92C_DRIVER_INFO_SIZE);
+	rtl92c_init_interrupt(hw);
+	rtl92c_init_network_type(hw);
+	_rtl92cu_init_wmac_setting(hw);
+	rtl92c_init_adaptive_ctrl(hw);
+	rtl92c_init_edca(hw);
+	rtl92c_init_rate_fallback(hw);
+	rtl92c_init_retry_function(hw);
+	_rtl92cu_init_usb_aggregation(hw);
+	rtlpriv->cfg->ops->set_bw_mode(hw, NL80211_CHAN_HT20);
+	rtl92c_set_min_space(hw, IS_92C_SERIAL(rtlhal->version));
+	rtl92c_init_beacon_parameters(hw, rtlhal->version);
+	rtl92c_init_ampdu_aggregation(hw);
+	rtl92c_init_beacon_max_error(hw, true);
+	return err;
+}
+
+void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 sec_reg_value = 0x0;
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("PairwiseEncAlgorithm = %d GroupEncAlgorithm = %d\n",
+		  rtlpriv->sec.pairwise_enc_algorithm,
+		  rtlpriv->sec.group_enc_algorithm));
+	if (rtlpriv->cfg->mod_params->sw_crypto || rtlpriv->sec.use_sw_sec) {
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+			 ("not open sw encryption\n"));
+		return;
+	}
+	sec_reg_value = SCR_TxEncEnable | SCR_RxDecEnable;
+	if (rtlpriv->sec.use_defaultkey) {
+		sec_reg_value |= SCR_TxUseDK;
+		sec_reg_value |= SCR_RxUseDK;
+	}
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		sec_reg_value |= (SCR_RXBCUSEDK | SCR_TXBCUSEDK);
+	rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+	RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+		 ("The SECR-value %x\n", sec_reg_value));
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_WPA_CONFIG, &sec_reg_value);
+}
+
+static void _rtl92cu_hw_configure(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	/* To Fix MAC loopback mode fail. */
+	rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
+	rtl_write_byte(rtlpriv, 0x15, 0xe9);
+	/* HW SEQ CTRL */
+	/* set 0x0 to 0xFF by tynli. Default enable HW SEQ NUM. */
+	rtl_write_byte(rtlpriv, REG_HWSEQ_CTRL, 0xFF);
+	/* fixed USB interface interference issue */
+	rtl_write_byte(rtlpriv, 0xfe40, 0xe0);
+	rtl_write_byte(rtlpriv, 0xfe41, 0x8d);
+	rtl_write_byte(rtlpriv, 0xfe42, 0x80);
+	rtlusb->reg_bcn_ctrl_val = 0x18;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8)rtlusb->reg_bcn_ctrl_val);
+}
+
+static void _InitPABias(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u8 pa_setting;
+
+	/* FIXED PA current issue */
+	pa_setting = efuse_read_1byte(hw, 0x1FA);
+	if (!(pa_setting & BIT(0))) {
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x0F406);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x4F406);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0x8F406);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x15, 0x0FFFFF, 0xCF406);
+	}
+	if (!(pa_setting & BIT(1)) && IS_NORMAL_CHIP(rtlhal->version) &&
+	    IS_92C_SERIAL(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x0F406);
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x4F406);
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0x8F406);
+		rtl_set_rfreg(hw, RF90_PATH_B, 0x15, 0x0FFFFF, 0xCF406);
+	}
+	if (!(pa_setting & BIT(4))) {
+		pa_setting = rtl_read_byte(rtlpriv, 0x16);
+		pa_setting &= 0x0F;
+		rtl_write_byte(rtlpriv, 0x16, pa_setting | 0x90);
+	}
+}
+
+static void _InitAntenna_Selection(struct ieee80211_hw *hw)
+{
+#ifdef CONFIG_ANTENNA_DIVERSITY
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (pHalData->AntDivCfg == 0)
+		return;
+
+	if (rtlphy->rf_type == RF_1T1R) {
+		rtl_write_dword(rtlpriv, REG_LEDCFG0,
+				rtl_read_dword(rtlpriv,
+				REG_LEDCFG0)|BIT(23));
+		rtl_set_bbreg(hw, rFPGA0_XAB_RFPARAMETER, BIT(13), 0x01);
+		if (rtl_get_bbreg(hw, RFPGA0_XA_RFINTERFACEOE, 0x300) ==
+		    Antenna_A)
+			pHalData->CurAntenna = Antenna_A;
+		else
+			pHalData->CurAntenna = Antenna_B;
+	}
+#endif
+}
+
+static void _dump_registers(struct ieee80211_hw *hw)
+{
+}
+
+static void _update_mac_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	mac->rx_conf = rtl_read_dword(rtlpriv, REG_RCR);
+	mac->rx_mgt_filter = rtl_read_word(rtlpriv, REG_RXFLTMAP0);
+	mac->rx_ctrl_filter = rtl_read_word(rtlpriv, REG_RXFLTMAP1);
+	mac->rx_data_filter = rtl_read_word(rtlpriv, REG_RXFLTMAP2);
+}
+
+int rtl92cu_hw_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	int err = 0;
+	static bool iqk_initialized;
+
+	rtlhal->hw_type = HARDWARE_TYPE_RTL8192CU;
+	err = _rtl92cu_init_mac(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("init mac failed!\n"));
+		return err;
+	}
+	err = rtl92c_download_fw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+			 ("Failed to download FW. Init HW without FW now..\n"));
+		err = 1;
+		rtlhal->fw_ready = false;
+		return err;
+	} else {
+		rtlhal->fw_ready = true;
+	}
+	rtlhal->last_hmeboxnum = 0; /* h2c */
+	_rtl92cu_phy_param_tab_init(hw);
+	rtl92cu_phy_mac_config(hw);
+	rtl92cu_phy_bb_config(hw);
+	rtlphy->rf_mode = RF_OP_BY_SW_3WIRE;
+	rtl92c_phy_rf_config(hw);
+	if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
+	    !IS_92C_SERIAL(rtlhal->version)) {
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G1, MASKDWORD, 0x30255);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_RX_G2, MASKDWORD, 0x50a00);
+	}
+	rtlphy->rfreg_chnlval[0] = rtl_get_rfreg(hw, (enum radio_path)0,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtlphy->rfreg_chnlval[1] = rtl_get_rfreg(hw, (enum radio_path)1,
+						 RF_CHNLBW, RFREG_OFFSET_MASK);
+	rtl92cu_bb_block_on(hw);
+	rtl_cam_reset_all_entry(hw);
+	rtl92cu_enable_hw_security_config(hw);
+	ppsc->rfpwr_state = ERFON;
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_ETHER_ADDR, mac->mac_addr);
+	if (ppsc->rfpwr_state == ERFON) {
+		rtl92c_phy_set_rfpath_switch(hw, 1);
+		if (iqk_initialized) {
+			rtl92c_phy_iq_calibrate(hw, false);
+		} else {
+			rtl92c_phy_iq_calibrate(hw, false);
+			iqk_initialized = true;
+		}
+		rtl92c_dm_check_txpower_tracking(hw);
+		rtl92c_phy_lc_calibrate(hw);
+	}
+	_rtl92cu_hw_configure(hw);
+	_InitPABias(hw);
+	_InitAntenna_Selection(hw);
+	_update_mac_setting(hw);
+	rtl92c_dm_init(hw);
+	_dump_registers(hw);
+	return err;
+}
+
+static void _DisableRFAFEAndResetBB(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+/**************************************
+a.	TXPAUSE 0x522[7:0] = 0xFF	Pause MAC TX queue
+b.	RF path 0 offset 0x00 = 0x00	disable RF
+c.	APSD_CTRL 0x600[7:0] = 0x40
+d.	SYS_FUNC_EN 0x02[7:0] = 0x16	reset BB state machine
+e.	SYS_FUNC_EN 0x02[7:0] = 0x14	reset BB state machine
+***************************************/
+	u8 eRFPath = 0, value8 = 0;
+	rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+	rtl_set_rfreg(hw, (enum radio_path)eRFPath, 0x0, MASKBYTE0, 0x0);
+
+	value8 |= APSDOFF;
+	rtl_write_byte(rtlpriv, REG_APSD_CTRL, value8); /*0x40*/
+	value8 = 0;
+	value8 |= (FEN_USBD | FEN_USBA | FEN_BB_GLB_RSTn);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8);/*0x16*/
+	value8 &= (~FEN_BB_GLB_RSTn);
+	rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, value8); /*0x14*/
+}
+
+static void  _ResetDigitalProcedure1(struct ieee80211_hw *hw, bool bWithoutHWSM)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+
+	if (rtlhal->fw_version <=  0x20) {
+		/*****************************
+		f. MCUFWDL 0x80[7:0]=0		reset MCU ready status
+		g. SYS_FUNC_EN 0x02[10]= 0	reset MCU reg, (8051 reset)
+		h. SYS_FUNC_EN 0x02[15-12]= 5	reset MAC reg, DCORE
+		i. SYS_FUNC_EN 0x02[10]= 1	enable MCU reg, (8051 enable)
+		******************************/
+		u16 valu16 = 0;
+
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+		valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+		rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 &
+			       (~FEN_CPUEN))); /* reset MCU ,8051 */
+		valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN)&0x0FFF;
+		rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 |
+			      (FEN_HWPDN|FEN_ELDR))); /* reset MAC */
+		valu16 = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+		rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, (valu16 |
+			       FEN_CPUEN)); /* enable MCU ,8051 */
+	} else {
+		u8 retry_cnts = 0;
+
+		/* IF fw in RAM code, do reset */
+		if (rtl_read_byte(rtlpriv, REG_MCUFWDL) & BIT(1)) {
+			/* reset MCU ready status */
+			rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+			if (rtlhal->fw_ready) {
+				/* 8051 reset by self */
+				rtl_write_byte(rtlpriv, REG_HMETFR+3, 0x20);
+				while ((retry_cnts++ < 100) &&
+				       (FEN_CPUEN & rtl_read_word(rtlpriv,
+				       REG_SYS_FUNC_EN))) {
+					udelay(50);
+				}
+				if (retry_cnts >= 100) {
+					RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+						("#####=> 8051 reset failed!.."
+						".......................\n"););
+					/* if 8051 reset fail, reset MAC. */
+					rtl_write_byte(rtlpriv,
+						       REG_SYS_FUNC_EN + 1,
+						       0x50);
+					udelay(100);
+				}
+			}
+		}
+		/* Reset MAC and Enable 8051 */
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 0x54);
+		rtl_write_byte(rtlpriv, REG_MCUFWDL, 0);
+	}
+	if (bWithoutHWSM) {
+		/*****************************
+		  Without HW auto state machine
+		g.SYS_CLKR 0x08[15:0] = 0x30A3		disable MAC clock
+		h.AFE_PLL_CTRL 0x28[7:0] = 0x80		disable AFE PLL
+		i.AFE_XTAL_CTRL 0x24[15:0] = 0x880F	gated AFE DIG_CLOCK
+		j.SYS_ISu_CTRL 0x00[7:0] = 0xF9		isolated digital to PON
+		******************************/
+		rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3);
+		rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x80);
+		rtl_write_word(rtlpriv, REG_AFE_XTAL_CTRL, 0x880F);
+		rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL, 0xF9);
+	}
+}
+
+static void _ResetDigitalProcedure2(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+/*****************************
+k. SYS_FUNC_EN 0x03[7:0] = 0x44		disable ELDR runction
+l. SYS_CLKR 0x08[15:0] = 0x3083		disable ELDR clock
+m. SYS_ISO_CTRL 0x01[7:0] = 0x83	isolated ELDR to PON
+******************************/
+	rtl_write_word(rtlpriv, REG_SYS_CLKR, 0x70A3);
+	rtl_write_byte(rtlpriv, REG_SYS_ISO_CTRL+1, 0x82);
+}
+
+static void _DisableGPIO(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+/***************************************
+j. GPIO_PIN_CTRL 0x44[31:0]=0x000
+k. Value = GPIO_PIN_CTRL[7:0]
+l.  GPIO_PIN_CTRL 0x44[31:0] = 0x00FF0000 | (value <<8); write ext PIN level
+m. GPIO_MUXCFG 0x42 [15:0] = 0x0780
+n. LEDCFG 0x4C[15:0] = 0x8080
+***************************************/
+	u8	value8;
+	u16	value16;
+	u32	value32;
+
+	/* 1. Disable GPIO[7:0] */
+	rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, 0x0000);
+	value32 = rtl_read_dword(rtlpriv, REG_GPIO_PIN_CTRL) & 0xFFFF00FF;
+	value8 = (u8) (value32&0x000000FF);
+	value32 |= ((value8<<8) | 0x00FF0000);
+	rtl_write_dword(rtlpriv, REG_GPIO_PIN_CTRL, value32);
+	/* 2. Disable GPIO[10:8] */
+	rtl_write_byte(rtlpriv, REG_GPIO_MUXCFG+3, 0x00);
+	value16 = rtl_read_word(rtlpriv, REG_GPIO_MUXCFG+2) & 0xFF0F;
+	value8 = (u8) (value16&0x000F);
+	value16 |= ((value8<<4) | 0x0780);
+	rtl_write_word(rtlpriv, REG_GPIO_PIN_CTRL+2, value16);
+	/* 3. Disable LED0 & 1 */
+	rtl_write_word(rtlpriv, REG_LEDCFG0, 0x8080);
+}
+
+static void _DisableAnalog(struct ieee80211_hw *hw, bool bWithoutHWSM)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u16 value16 = 0;
+	u8 value8 = 0;
+
+	if (bWithoutHWSM) {
+		/*****************************
+		n. LDOA15_CTRL 0x20[7:0] = 0x04	 disable A15 power
+		o. LDOV12D_CTRL 0x21[7:0] = 0x54 disable digital core power
+		r. When driver call disable, the ASIC will turn off remaining
+		   clock automatically
+		******************************/
+		rtl_write_byte(rtlpriv, REG_LDOA15_CTRL, 0x04);
+		value8 = rtl_read_byte(rtlpriv, REG_LDOV12D_CTRL);
+		value8 &= (~LDV12_EN);
+		rtl_write_byte(rtlpriv, REG_LDOV12D_CTRL, value8);
+	}
+
+/*****************************
+h. SPS0_CTRL 0x11[7:0] = 0x23		enter PFM mode
+i. APS_FSMCO 0x04[15:0] = 0x4802	set USB suspend
+******************************/
+	rtl_write_byte(rtlpriv, REG_SPS0_CTRL, 0x23);
+	value16 |= (APDM_HOST | AFSM_HSUS | PFM_ALDN);
+	rtl_write_word(rtlpriv, REG_APS_FSMCO, (u16)value16);
+	rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0E);
+}
+
+static void _CardDisableHWSM(struct ieee80211_hw *hw)
+{
+	/* ==== RF Off Sequence ==== */
+	_DisableRFAFEAndResetBB(hw);
+	/* ==== Reset digital sequence   ====== */
+	_ResetDigitalProcedure1(hw, false);
+	/*  ==== Pull GPIO PIN to balance level and LED control ====== */
+	_DisableGPIO(hw);
+	/* ==== Disable analog sequence === */
+	_DisableAnalog(hw, false);
+}
+
+static void _CardDisableWithoutHWSM(struct ieee80211_hw *hw)
+{
+	/*==== RF Off Sequence ==== */
+	_DisableRFAFEAndResetBB(hw);
+	/*  ==== Reset digital sequence   ====== */
+	_ResetDigitalProcedure1(hw, true);
+	/*  ==== Pull GPIO PIN to balance level and LED control ====== */
+	_DisableGPIO(hw);
+	/*  ==== Reset digital sequence   ====== */
+	_ResetDigitalProcedure2(hw);
+	/*  ==== Disable analog sequence === */
+	_DisableAnalog(hw, true);
+}
+
+static void _rtl92cu_set_bcn_ctrl_reg(struct ieee80211_hw *hw,
+				      u8 set_bits, u8 clear_bits)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtlusb->reg_bcn_ctrl_val |= set_bits;
+	rtlusb->reg_bcn_ctrl_val &= ~clear_bits;
+	rtl_write_byte(rtlpriv, REG_BCN_CTRL, (u8) rtlusb->reg_bcn_ctrl_val);
+}
+
+static void _rtl92cu_stop_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 tmp1byte = 0;
+	if (IS_NORMAL_CHIP(rtlhal->version)) {
+		tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+		rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+			       tmp1byte & (~BIT(6)));
+		rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0x64);
+		tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+		tmp1byte &= ~(BIT(0));
+		rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE,
+			       rtl_read_byte(rtlpriv, REG_TXPAUSE) | BIT(6));
+	}
+}
+
+static void _rtl92cu_resume_tx_beacon(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	u8 tmp1byte = 0;
+
+	if (IS_NORMAL_CHIP(rtlhal->version)) {
+		tmp1byte = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2);
+		rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+			       tmp1byte | BIT(6));
+		rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 1, 0xff);
+		tmp1byte = rtl_read_byte(rtlpriv, REG_TBTT_PROHIBIT + 2);
+		tmp1byte |= BIT(0);
+		rtl_write_byte(rtlpriv, REG_TBTT_PROHIBIT + 2, tmp1byte);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE,
+			       rtl_read_byte(rtlpriv, REG_TXPAUSE) & (~BIT(6)));
+	}
+}
+
+static void _rtl92cu_enable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(1));
+	else
+		_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
+}
+
+static void _rtl92cu_disable_bcn_sub_func(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		_rtl92cu_set_bcn_ctrl_reg(hw, BIT(1), 0);
+	else
+		_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+}
+
+static int _rtl92cu_set_media_status(struct ieee80211_hw *hw,
+				     enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 bt_msr = rtl_read_byte(rtlpriv, MSR);
+	enum led_ctl_mode ledaction = LED_CTL_NO_LINK;
+
+	bt_msr &= 0xfc;
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
+	if (type == NL80211_IFTYPE_UNSPECIFIED || type ==
+	    NL80211_IFTYPE_STATION) {
+		_rtl92cu_stop_tx_beacon(hw);
+		_rtl92cu_enable_bcn_sub_func(hw);
+	} else if (type == NL80211_IFTYPE_ADHOC || type == NL80211_IFTYPE_AP) {
+		_rtl92cu_resume_tx_beacon(hw);
+		_rtl92cu_disable_bcn_sub_func(hw);
+	} else {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING, ("Set HW_VAR_MEDIA_"
+			 "STATUS:No such media status(%x).\n", type));
+	}
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		bt_msr |= MSR_NOLINK;
+		ledaction = LED_CTL_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to NO LINK!\n"));
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		bt_msr |= MSR_ADHOC;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to Ad Hoc!\n"));
+		break;
+	case NL80211_IFTYPE_STATION:
+		bt_msr |= MSR_INFRA;
+		ledaction = LED_CTL_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to STA!\n"));
+		break;
+	case NL80211_IFTYPE_AP:
+		bt_msr |= MSR_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Set Network type to AP!\n"));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Network type %d not support!\n", type));
+		goto error_out;
+	}
+	rtl_write_byte(rtlpriv, (MSR), bt_msr);
+	rtlpriv->cfg->ops->led_control(hw, ledaction);
+	if ((bt_msr & 0xfc) == MSR_AP)
+		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x00);
+	else
+		rtl_write_byte(rtlpriv, REG_BCNTCFG + 1, 0x66);
+	return 0;
+error_out:
+	return 1;
+}
+
+void rtl92cu_card_disable(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	enum nl80211_iftype opmode;
+
+	mac->link_state = MAC80211_NOLINK;
+	opmode = NL80211_IFTYPE_UNSPECIFIED;
+	_rtl92cu_set_media_status(hw, opmode);
+	rtlpriv->cfg->ops->led_control(hw, LED_CTL_POWER_OFF);
+	RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+	if (rtlusb->disableHWSM)
+		_CardDisableHWSM(hw);
+	else
+		_CardDisableWithoutHWSM(hw);
+}
+
+void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid)
+{
+	/* dummy routine needed for callback from rtl_op_configure_filter() */
+}
+
+/*========================================================================== */
+
+static void _rtl92cu_set_check_bssid(struct ieee80211_hw *hw,
+			      enum nl80211_iftype type)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 reg_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 filterout_non_associated_bssid = false;
+
+	switch (type) {
+	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_STATION:
+		filterout_non_associated_bssid = true;
+		break;
+	case NL80211_IFTYPE_UNSPECIFIED:
+	case NL80211_IFTYPE_AP:
+	default:
+		break;
+	}
+	if (filterout_non_associated_bssid == true) {
+		if (IS_NORMAL_CHIP(rtlhal->version)) {
+			switch (rtlphy->current_io_type) {
+			case IO_CMD_RESUME_DM_BY_SCAN:
+				reg_rcr |= (RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						 HW_VAR_RCR, (u8 *)(&reg_rcr));
+				/* enable update TSF */
+				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
+				break;
+			case IO_CMD_PAUSE_DM_BY_SCAN:
+				reg_rcr &= ~(RCR_CBSSID_DATA | RCR_CBSSID_BCN);
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+						 HW_VAR_RCR, (u8 *)(&reg_rcr));
+				/* disable update TSF */
+				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+				break;
+			}
+		} else {
+			reg_rcr |= (RCR_CBSSID);
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+						      (u8 *)(&reg_rcr));
+			_rtl92cu_set_bcn_ctrl_reg(hw, 0, (BIT(4)|BIT(5)));
+		}
+	} else if (filterout_non_associated_bssid == false) {
+		if (IS_NORMAL_CHIP(rtlhal->version)) {
+			reg_rcr &= (~(RCR_CBSSID_DATA | RCR_CBSSID_BCN));
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+						      (u8 *)(&reg_rcr));
+			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+		} else {
+			reg_rcr &= (~RCR_CBSSID);
+			rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_RCR,
+						      (u8 *)(&reg_rcr));
+			_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4)|BIT(5)), 0);
+		}
+	}
+}
+
+int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+	if (_rtl92cu_set_media_status(hw, type))
+		return -EOPNOTSUPP;
+	_rtl92cu_set_check_bssid(hw, type);
+	return 0;
+}
+
+static void _InitBeaconParameters(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	rtl_write_word(rtlpriv, REG_BCN_CTRL, 0x1010);
+
+	/* TODO: Remove these magic number */
+	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);
+	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);
+	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
+	/* Change beacon AIFS to the largest number
+	 * beacause test chip does not contension before sending beacon. */
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
+	else
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
+}
+
+static void _beacon_function_enable(struct ieee80211_hw *hw, bool Enable,
+				    bool Linked)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	_rtl92cu_set_bcn_ctrl_reg(hw, (BIT(4) | BIT(3) | BIT(1)), 0x00);
+	rtl_write_byte(rtlpriv, REG_RD_CTRL+1, 0x6F);
+}
+
+void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw)
+{
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval, atim_window;
+	u32 value32;
+
+	bcn_interval = mac->beacon_interval;
+	atim_window = 2;	/*FIX MERGE */
+	rtl_write_word(rtlpriv, REG_ATIMWND, atim_window);
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+	_InitBeaconParameters(hw);
+	rtl_write_byte(rtlpriv, REG_SLOT, 0x09);
+	/*
+	 * Force beacon frame transmission even after receiving beacon frame
+	 * from other ad hoc STA
+	 *
+	 *
+	 * Reset TSF Timer to zero, added by Roger. 2008.06.24
+	 */
+	value32 = rtl_read_dword(rtlpriv, REG_TCR);
+	value32 &= ~TSFRST;
+	rtl_write_dword(rtlpriv, REG_TCR, value32);
+	value32 |= TSFRST;
+	rtl_write_dword(rtlpriv, REG_TCR, value32);
+	RT_TRACE(rtlpriv, COMP_INIT|COMP_BEACON, DBG_LOUD,
+		 ("SetBeaconRelatedRegisters8192CUsb(): Set TCR(%x)\n",
+		 value32));
+	/* TODO: Modify later (Find the right parameters)
+	 * NOTE: Fix test chip's bug (about contention windows's randomness) */
+	if ((mac->opmode == NL80211_IFTYPE_ADHOC) ||
+	    (mac->opmode == NL80211_IFTYPE_AP)) {
+		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_CCK, 0x50);
+		rtl_write_byte(rtlpriv, REG_RXTSF_OFFSET_OFDM, 0x50);
+	}
+	_beacon_function_enable(hw, true, true);
+}
+
+void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 bcn_interval = mac->beacon_interval;
+
+	RT_TRACE(rtlpriv, COMP_BEACON, DBG_DMESG,
+		 ("beacon_interval:%d\n", bcn_interval));
+	rtl_write_word(rtlpriv, REG_BCN_INTERVAL, bcn_interval);
+}
+
+void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr)
+{
+}
+
+void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+
+	switch (variable) {
+	case HW_VAR_RCR:
+		*((u32 *)(val)) = mac->rx_conf;
+		break;
+	case HW_VAR_RF_STATE:
+		*((enum rf_pwrstate *)(val)) = ppsc->rfpwr_state;
+		break;
+	case HW_VAR_FWLPS_RF_ON:{
+			enum rf_pwrstate rfState;
+			u32 val_rcr;
+
+			rtlpriv->cfg->ops->get_hw_reg(hw, HW_VAR_RF_STATE,
+						      (u8 *)(&rfState));
+			if (rfState == ERFOFF) {
+				*((bool *) (val)) = true;
+			} else {
+				val_rcr = rtl_read_dword(rtlpriv, REG_RCR);
+				val_rcr &= 0x00070000;
+				if (val_rcr)
+					*((bool *) (val)) = false;
+				else
+					*((bool *) (val)) = true;
+			}
+			break;
+		}
+	case HW_VAR_FW_PSMODE_STATUS:
+		*((bool *) (val)) = ppsc->fw_current_inpsmode;
+		break;
+	case HW_VAR_CORRECT_TSF:{
+			u64 tsf;
+			u32 *ptsf_low = (u32 *)&tsf;
+			u32 *ptsf_high = ((u32 *)&tsf) + 1;
+
+			*ptsf_high = rtl_read_dword(rtlpriv, (REG_TSFTR + 4));
+			*ptsf_low = rtl_read_dword(rtlpriv, REG_TSFTR);
+			*((u64 *)(val)) = tsf;
+			break;
+		}
+	case HW_VAR_MGT_FILTER:
+		*((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP0);
+		break;
+	case HW_VAR_CTRL_FILTER:
+		*((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP1);
+		break;
+	case HW_VAR_DATA_FILTER:
+		*((u16 *) (val)) = rtl_read_word(rtlpriv, REG_RXFLTMAP2);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+}
+
+void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	enum wireless_mode wirelessmode = mac->mode;
+	u8 idx = 0;
+
+	switch (variable) {
+	case HW_VAR_ETHER_ADDR:{
+			for (idx = 0; idx < ETH_ALEN; idx++) {
+				rtl_write_byte(rtlpriv, (REG_MACID + idx),
+					       val[idx]);
+			}
+			break;
+		}
+	case HW_VAR_BASIC_RATE:{
+			u16 rate_cfg = ((u16 *) val)[0];
+			u8 rate_index = 0;
+
+			rate_cfg &= 0x15f;
+			/* TODO */
+			/* if (mac->current_network.vender == HT_IOT_PEER_CISCO
+			 *     && ((rate_cfg & 0x150) == 0)) {
+			 *	  rate_cfg |= 0x010;
+			 * } */
+			rate_cfg |= 0x01;
+			rtl_write_byte(rtlpriv, REG_RRSR, rate_cfg & 0xff);
+			rtl_write_byte(rtlpriv, REG_RRSR + 1,
+				       (rate_cfg >> 8) & 0xff);
+			while (rate_cfg > 0x1) {
+				rate_cfg >>= 1;
+				rate_index++;
+			}
+			rtl_write_byte(rtlpriv, REG_INIRTS_RATE_SEL,
+				       rate_index);
+			break;
+		}
+	case HW_VAR_BSSID:{
+			for (idx = 0; idx < ETH_ALEN; idx++) {
+				rtl_write_byte(rtlpriv, (REG_BSSID + idx),
+					       val[idx]);
+			}
+			break;
+		}
+	case HW_VAR_SIFS:{
+			rtl_write_byte(rtlpriv, REG_SIFS_CCK + 1, val[0]);
+			rtl_write_byte(rtlpriv, REG_SIFS_OFDM + 1, val[1]);
+			rtl_write_byte(rtlpriv, REG_SPEC_SIFS + 1, val[0]);
+			rtl_write_byte(rtlpriv, REG_MAC_SPEC_SIFS + 1, val[0]);
+			rtl_write_byte(rtlpriv, REG_R2T_SIFS+1, val[0]);
+			rtl_write_byte(rtlpriv, REG_T2T_SIFS+1, val[0]);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("HW_VAR_SIFS\n"));
+			break;
+		}
+	case HW_VAR_SLOT_TIME:{
+			u8 e_aci;
+			u8 QOS_MODE = 1;
+
+			rtl_write_byte(rtlpriv, REG_SLOT, val[0]);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("HW_VAR_SLOT_TIME %x\n", val[0]));
+			if (QOS_MODE) {
+				for (e_aci = 0; e_aci < AC_MAX; e_aci++)
+					rtlpriv->cfg->ops->set_hw_reg(hw,
+								HW_VAR_AC_PARAM,
+								(u8 *)(&e_aci));
+			} else {
+				u8 sifstime = 0;
+				u8	u1bAIFS;
+
+				if (IS_WIRELESS_MODE_A(wirelessmode) ||
+				    IS_WIRELESS_MODE_N_24G(wirelessmode) ||
+				    IS_WIRELESS_MODE_N_5G(wirelessmode))
+					sifstime = 16;
+				else
+					sifstime = 10;
+				u1bAIFS = sifstime + (2 *  val[0]);
+				rtl_write_byte(rtlpriv, REG_EDCA_VO_PARAM,
+					       u1bAIFS);
+				rtl_write_byte(rtlpriv, REG_EDCA_VI_PARAM,
+					       u1bAIFS);
+				rtl_write_byte(rtlpriv, REG_EDCA_BE_PARAM,
+					       u1bAIFS);
+				rtl_write_byte(rtlpriv, REG_EDCA_BK_PARAM,
+					       u1bAIFS);
+			}
+			break;
+		}
+	case HW_VAR_ACK_PREAMBLE:{
+			u8 reg_tmp;
+			u8 short_preamble = (bool) (*(u8 *) val);
+			reg_tmp = 0;
+			if (short_preamble)
+				reg_tmp |= 0x80;
+			rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_tmp);
+			break;
+		}
+	case HW_VAR_AMPDU_MIN_SPACE:{
+			u8 min_spacing_to_set;
+			u8 sec_min_space;
+
+			min_spacing_to_set = *((u8 *) val);
+			if (min_spacing_to_set <= 7) {
+				switch (rtlpriv->sec.pairwise_enc_algorithm) {
+				case NO_ENCRYPTION:
+				case AESCCMP_ENCRYPTION:
+					sec_min_space = 0;
+					break;
+				case WEP40_ENCRYPTION:
+				case WEP104_ENCRYPTION:
+				case TKIP_ENCRYPTION:
+					sec_min_space = 6;
+					break;
+				default:
+					sec_min_space = 7;
+					break;
+				}
+				if (min_spacing_to_set < sec_min_space)
+					min_spacing_to_set = sec_min_space;
+				mac->min_space_cfg = ((mac->min_space_cfg &
+						     0xf8) |
+						     min_spacing_to_set);
+				*val = min_spacing_to_set;
+				RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+					("Set HW_VAR_AMPDU_MIN_SPACE: %#x\n",
+					mac->min_space_cfg));
+				rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+					       mac->min_space_cfg);
+			}
+			break;
+		}
+	case HW_VAR_SHORTGI_DENSITY:{
+			u8 density_to_set;
+
+			density_to_set = *((u8 *) val);
+			density_to_set &= 0x1f;
+			mac->min_space_cfg &= 0x07;
+			mac->min_space_cfg |= (density_to_set << 3);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("Set HW_VAR_SHORTGI_DENSITY: %#x\n",
+				  mac->min_space_cfg));
+			rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE,
+				       mac->min_space_cfg);
+			break;
+		}
+	case HW_VAR_AMPDU_FACTOR:{
+			u8 regtoset_normal[4] = {0x41, 0xa8, 0x72, 0xb9};
+			u8 factor_toset;
+			u8 *p_regtoset = NULL;
+			u8 index = 0;
+
+			p_regtoset = regtoset_normal;
+			factor_toset = *((u8 *) val);
+			if (factor_toset <= 3) {
+				factor_toset = (1 << (factor_toset + 2));
+				if (factor_toset > 0xf)
+					factor_toset = 0xf;
+				for (index = 0; index < 4; index++) {
+					if ((p_regtoset[index] & 0xf0) >
+					    (factor_toset << 4))
+						p_regtoset[index] =
+						     (p_regtoset[index] & 0x0f)
+						     | (factor_toset << 4);
+					if ((p_regtoset[index] & 0x0f) >
+					     factor_toset)
+						p_regtoset[index] =
+						     (p_regtoset[index] & 0xf0)
+						     | (factor_toset);
+					rtl_write_byte(rtlpriv,
+						       (REG_AGGLEN_LMT + index),
+						       p_regtoset[index]);
+				}
+				RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+					 ("Set HW_VAR_AMPDU_FACTOR: %#x\n",
+					  factor_toset));
+			}
+			break;
+		}
+	case HW_VAR_AC_PARAM:{
+			u8 e_aci = *((u8 *) val);
+			u32 u4b_ac_param;
+			u16 cw_min = le16_to_cpu(mac->ac[e_aci].cw_min);
+			u16 cw_max = le16_to_cpu(mac->ac[e_aci].cw_max);
+			u16 tx_op = le16_to_cpu(mac->ac[e_aci].tx_op);
+
+			u4b_ac_param = (u32) mac->ac[e_aci].aifs;
+			u4b_ac_param |= (u32) ((cw_min & 0xF) <<
+					 AC_PARAM_ECW_MIN_OFFSET);
+			u4b_ac_param |= (u32) ((cw_max & 0xF) <<
+					 AC_PARAM_ECW_MAX_OFFSET);
+			u4b_ac_param |= (u32) tx_op << AC_PARAM_TXOP_OFFSET;
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_LOUD,
+				 ("queue:%x, ac_param:%x\n", e_aci,
+				  u4b_ac_param));
+			switch (e_aci) {
+			case AC1_BK:
+				rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM,
+						u4b_ac_param);
+				break;
+			case AC0_BE:
+				rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM,
+						u4b_ac_param);
+				break;
+			case AC2_VI:
+				rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM,
+						u4b_ac_param);
+				break;
+			case AC3_VO:
+				rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM,
+						u4b_ac_param);
+				break;
+			default:
+				RT_ASSERT(false, ("SetHwReg8185(): invalid"
+					  " aci: %d !\n", e_aci));
+				break;
+			}
+			if (rtlusb->acm_method != eAcmWay2_SW)
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+					 HW_VAR_ACM_CTRL, (u8 *)(&e_aci));
+			break;
+		}
+	case HW_VAR_ACM_CTRL:{
+			u8 e_aci = *((u8 *) val);
+			union aci_aifsn *p_aci_aifsn = (union aci_aifsn *)
+							(&(mac->ac[0].aifs));
+			u8 acm = p_aci_aifsn->f.acm;
+			u8 acm_ctrl = rtl_read_byte(rtlpriv, REG_ACMHWCTRL);
+
+			acm_ctrl =
+			    acm_ctrl | ((rtlusb->acm_method == 2) ? 0x0 : 0x1);
+			if (acm) {
+				switch (e_aci) {
+				case AC0_BE:
+					acm_ctrl |= AcmHw_BeqEn;
+					break;
+				case AC2_VI:
+					acm_ctrl |= AcmHw_ViqEn;
+					break;
+				case AC3_VO:
+					acm_ctrl |= AcmHw_VoqEn;
+					break;
+				default:
+					RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+						 ("HW_VAR_ACM_CTRL acm set "
+						  "failed: eACI is %d\n", acm));
+					break;
+				}
+			} else {
+				switch (e_aci) {
+				case AC0_BE:
+					acm_ctrl &= (~AcmHw_BeqEn);
+					break;
+				case AC2_VI:
+					acm_ctrl &= (~AcmHw_ViqEn);
+					break;
+				case AC3_VO:
+					acm_ctrl &= (~AcmHw_BeqEn);
+					break;
+				default:
+					RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+						 ("switch case not process\n"));
+					break;
+				}
+			}
+			RT_TRACE(rtlpriv, COMP_QOS, DBG_TRACE,
+				 ("SetHwReg8190pci(): [HW_VAR_ACM_CTRL] "
+				  "Write 0x%X\n", acm_ctrl));
+			rtl_write_byte(rtlpriv, REG_ACMHWCTRL, acm_ctrl);
+			break;
+		}
+	case HW_VAR_RCR:{
+			rtl_write_dword(rtlpriv, REG_RCR, ((u32 *) (val))[0]);
+			mac->rx_conf = ((u32 *) (val))[0];
+			RT_TRACE(rtlpriv, COMP_RECV, DBG_DMESG,
+				 ("### Set RCR(0x%08x) ###\n", mac->rx_conf));
+			break;
+		}
+	case HW_VAR_RETRY_LIMIT:{
+			u8 retry_limit = ((u8 *) (val))[0];
+
+			rtl_write_word(rtlpriv, REG_RL,
+				       retry_limit << RETRY_LIMIT_SHORT_SHIFT |
+				       retry_limit << RETRY_LIMIT_LONG_SHIFT);
+			RT_TRACE(rtlpriv, COMP_MLME, DBG_DMESG, ("Set HW_VAR_R"
+				 "ETRY_LIMIT(0x%08x)\n", retry_limit));
+			break;
+		}
+	case HW_VAR_DUAL_TSF_RST:
+		rtl_write_byte(rtlpriv, REG_DUAL_TSF_RST, (BIT(0) | BIT(1)));
+		break;
+	case HW_VAR_EFUSE_BYTES:
+		rtlefuse->efuse_usedbytes = *((u16 *) val);
+		break;
+	case HW_VAR_EFUSE_USAGE:
+		rtlefuse->efuse_usedpercentage = *((u8 *) val);
+		break;
+	case HW_VAR_IO_CMD:
+		rtl92c_phy_set_io_cmd(hw, (*(enum io_type *)val));
+		break;
+	case HW_VAR_WPA_CONFIG:
+		rtl_write_byte(rtlpriv, REG_SECCFG, *((u8 *) val));
+		break;
+	case HW_VAR_SET_RPWM:{
+			u8 rpwm_val = rtl_read_byte(rtlpriv, REG_USB_HRPWM);
+
+			if (rpwm_val & BIT(7))
+				rtl_write_byte(rtlpriv, REG_USB_HRPWM,
+					       (*(u8 *)val));
+			else
+				rtl_write_byte(rtlpriv, REG_USB_HRPWM,
+					       ((*(u8 *)val) | BIT(7)));
+			break;
+		}
+	case HW_VAR_H2C_FW_PWRMODE:{
+			u8 psmode = (*(u8 *) val);
+
+			if ((psmode != FW_PS_ACTIVE_MODE) &&
+			   (!IS_92C_SERIAL(rtlhal->version)))
+				rtl92c_dm_rf_saving(hw, true);
+			rtl92c_set_fw_pwrmode_cmd(hw, (*(u8 *) val));
+			break;
+		}
+	case HW_VAR_FW_PSMODE_STATUS:
+		ppsc->fw_current_inpsmode = *((bool *) val);
+		break;
+	case HW_VAR_H2C_FW_JOINBSSRPT:{
+			u8 mstatus = (*(u8 *) val);
+			u8 tmp_reg422;
+			bool recover = false;
+
+			if (mstatus == RT_MEDIA_CONNECT) {
+				rtlpriv->cfg->ops->set_hw_reg(hw,
+							 HW_VAR_AID, NULL);
+				rtl_write_byte(rtlpriv, REG_CR + 1, 0x03);
+				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
+				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(4), 0);
+				tmp_reg422 = rtl_read_byte(rtlpriv,
+							REG_FWHW_TXQ_CTRL + 2);
+				if (tmp_reg422 & BIT(6))
+					recover = true;
+				rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2,
+					       tmp_reg422 & (~BIT(6)));
+				rtl92c_set_fw_rsvdpagepkt(hw, 0);
+				_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
+				_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4));
+				if (recover)
+					rtl_write_byte(rtlpriv,
+						 REG_FWHW_TXQ_CTRL + 2,
+						tmp_reg422 | BIT(6));
+				rtl_write_byte(rtlpriv, REG_CR + 1, 0x02);
+			}
+			rtl92c_set_fw_joinbss_report_cmd(hw, (*(u8 *) val));
+			break;
+		}
+	case HW_VAR_AID:{
+			u16 u2btmp;
+
+			u2btmp = rtl_read_word(rtlpriv, REG_BCN_PSR_RPT);
+			u2btmp &= 0xC000;
+			rtl_write_word(rtlpriv, REG_BCN_PSR_RPT,
+				       (u2btmp | mac->assoc_id));
+			break;
+		}
+	case HW_VAR_CORRECT_TSF:{
+			u8 btype_ibss = ((u8 *) (val))[0];
+
+			if (btype_ibss == true)
+				_rtl92cu_stop_tx_beacon(hw);
+			_rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(3));
+			rtl_write_dword(rtlpriv, REG_TSFTR, (u32)(mac->tsf &
+					0xffffffff));
+			rtl_write_dword(rtlpriv, REG_TSFTR + 4,
+					(u32)((mac->tsf >> 32) & 0xffffffff));
+			_rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0);
+			if (btype_ibss == true)
+				_rtl92cu_resume_tx_beacon(hw);
+			break;
+		}
+	case HW_VAR_MGT_FILTER:
+		rtl_write_word(rtlpriv, REG_RXFLTMAP0, *(u16 *)val);
+		break;
+	case HW_VAR_CTRL_FILTER:
+		rtl_write_word(rtlpriv, REG_RXFLTMAP1, *(u16 *)val);
+		break;
+	case HW_VAR_DATA_FILTER:
+		rtl_write_word(rtlpriv, REG_RXFLTMAP2, *(u16 *)val);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, ("switch case "
+							"not process\n"));
+		break;
+	}
+}
+
+void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u32 ratr_value = (u32) mac->basic_rates;
+	u8 *mcsrate = mac->mcs;
+	u8 ratr_index = 0;
+	u8 nmode = mac->ht_enable;
+	u8 mimo_ps = 1;
+	u16 shortgi_rate = 0;
+	u32 tmp_ratr_value = 0;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
+	enum wireless_mode wirelessmode = mac->mode;
+
+	ratr_value |= ((*(u16 *) (mcsrate))) << 12;
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		if (ratr_value & 0x0000000c)
+			ratr_value &= 0x0000000d;
+		else
+			ratr_value &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_value &= 0x00000FF5;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		nmode = 1;
+		if (mimo_ps == 0) {
+			ratr_value &= 0x0007F005;
+		} else {
+			u32 ratr_mask;
+
+			if (get_rf_type(rtlphy) == RF_1T2R ||
+			    get_rf_type(rtlphy) == RF_1T1R)
+				ratr_mask = 0x000ff005;
+			else
+				ratr_mask = 0x0f0ff005;
+			if (curtxbw_40mhz)
+				ratr_mask |= 0x00000010;
+			ratr_value &= ratr_mask;
+		}
+		break;
+	default:
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_value &= 0x000ff0ff;
+		else
+			ratr_value &= 0x0f0ff0ff;
+		break;
+	}
+	ratr_value &= 0x0FFFFFFF;
+	if (nmode && ((curtxbw_40mhz && curshortgi_40mhz) ||
+	    (!curtxbw_40mhz && curshortgi_20mhz))) {
+		ratr_value |= 0x10000000;
+		tmp_ratr_value = (ratr_value >> 12);
+		for (shortgi_rate = 15; shortgi_rate > 0; shortgi_rate--) {
+			if ((1 << shortgi_rate) & tmp_ratr_value)
+				break;
+		}
+		shortgi_rate = (shortgi_rate << 12) | (shortgi_rate << 8) |
+			       (shortgi_rate << 4) | (shortgi_rate);
+	}
+	rtl_write_dword(rtlpriv, REG_ARFR0 + ratr_index * 4, ratr_value);
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("%x\n", rtl_read_dword(rtlpriv,
+		 REG_ARFR0)));
+}
+
+void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u32 ratr_bitmap = (u32) mac->basic_rates;
+	u8 *p_mcsrate = mac->mcs;
+	u8 ratr_index = 0;
+	u8 curtxbw_40mhz = mac->bw_40;
+	u8 curshortgi_40mhz = mac->sgi_40;
+	u8 curshortgi_20mhz = mac->sgi_20;
+	enum wireless_mode wirelessmode = mac->mode;
+	bool shortgi = false;
+	u8 rate_mask[5];
+	u8 macid = 0;
+	u8 mimops = 1;
+
+	ratr_bitmap |= (p_mcsrate[1] << 20) | (p_mcsrate[0] << 12);
+	switch (wirelessmode) {
+	case WIRELESS_MODE_B:
+		ratr_index = RATR_INX_WIRELESS_B;
+		if (ratr_bitmap & 0x0000000c)
+			ratr_bitmap &= 0x0000000d;
+		else
+			ratr_bitmap &= 0x0000000f;
+		break;
+	case WIRELESS_MODE_G:
+		ratr_index = RATR_INX_WIRELESS_GB;
+		if (rssi_level == 1)
+			ratr_bitmap &= 0x00000f00;
+		else if (rssi_level == 2)
+			ratr_bitmap &= 0x00000ff0;
+		else
+			ratr_bitmap &= 0x00000ff5;
+		break;
+	case WIRELESS_MODE_A:
+		ratr_index = RATR_INX_WIRELESS_A;
+		ratr_bitmap &= 0x00000ff0;
+		break;
+	case WIRELESS_MODE_N_24G:
+	case WIRELESS_MODE_N_5G:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+		if (mimops == 0) {
+			if (rssi_level == 1)
+				ratr_bitmap &= 0x00070000;
+			else if (rssi_level == 2)
+				ratr_bitmap &= 0x0007f000;
+			else
+				ratr_bitmap &= 0x0007f005;
+		} else {
+			if (rtlphy->rf_type == RF_1T2R ||
+			    rtlphy->rf_type == RF_1T1R) {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x000f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x000ff000;
+					else
+						ratr_bitmap &= 0x000ff005;
+				}
+			} else {
+				if (curtxbw_40mhz) {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff015;
+				} else {
+					if (rssi_level == 1)
+						ratr_bitmap &= 0x0f0f0000;
+					else if (rssi_level == 2)
+						ratr_bitmap &= 0x0f0ff000;
+					else
+						ratr_bitmap &= 0x0f0ff005;
+				}
+			}
+		}
+		if ((curtxbw_40mhz && curshortgi_40mhz) ||
+		    (!curtxbw_40mhz && curshortgi_20mhz)) {
+			if (macid == 0)
+				shortgi = true;
+			else if (macid == 1)
+				shortgi = false;
+		}
+		break;
+	default:
+		ratr_index = RATR_INX_WIRELESS_NGB;
+		if (rtlphy->rf_type == RF_1T2R)
+			ratr_bitmap &= 0x000ff0ff;
+		else
+			ratr_bitmap &= 0x0f0ff0ff;
+		break;
+	}
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("ratr_bitmap :%x\n",
+		 ratr_bitmap));
+	*(u32 *)&rate_mask = ((ratr_bitmap & 0x0fffffff) |
+				      ratr_index << 28);
+	rate_mask[4] = macid | (shortgi ? 0x20 : 0x00) | 0x80;
+	RT_TRACE(rtlpriv, COMP_RATR, DBG_DMESG, ("Rate_index:%x, "
+						"ratr_val:%x, %x:%x:%x:%x:%x\n",
+						ratr_index, ratr_bitmap,
+						rate_mask[0], rate_mask[1],
+						rate_mask[2], rate_mask[3],
+						rate_mask[4]));
+	rtl92c_fill_h2c_cmd(hw, H2C_RA_MASK, 5, rate_mask);
+}
+
+void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u16 sifs_timer;
+
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SLOT_TIME,
+				      (u8 *)&mac->slot_time);
+	if (!mac->ht_enable)
+		sifs_timer = 0x0a0a;
+	else
+		sifs_timer = 0x0e0e;
+	rtlpriv->cfg->ops->set_hw_reg(hw, HW_VAR_SIFS, (u8 *)&sifs_timer);
+}
+
+bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	enum rf_pwrstate e_rfpowerstate_toset, cur_rfstate;
+	u8 u1tmp = 0;
+	bool actuallyset = false;
+	unsigned long flag = 0;
+	/* to do - usb autosuspend */
+	u8 usb_autosuspend = 0;
+
+	if (ppsc->swrf_processing)
+		return false;
+	spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+	if (ppsc->rfchange_inprogress) {
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+		return false;
+	} else {
+		ppsc->rfchange_inprogress = true;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	}
+	cur_rfstate = ppsc->rfpwr_state;
+	if (usb_autosuspend) {
+		/* to do................... */
+	} else {
+		if (ppsc->pwrdown_mode) {
+			u1tmp = rtl_read_byte(rtlpriv, REG_HSISR);
+			e_rfpowerstate_toset = (u1tmp & BIT(7)) ?
+					       ERFOFF : ERFON;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+				 ("pwrdown, 0x5c(BIT7)=%02x\n", u1tmp));
+		} else {
+			rtl_write_byte(rtlpriv, REG_MAC_PINMUX_CFG,
+				       rtl_read_byte(rtlpriv,
+				       REG_MAC_PINMUX_CFG) & ~(BIT(3)));
+			u1tmp = rtl_read_byte(rtlpriv, REG_GPIO_IO_SEL);
+			e_rfpowerstate_toset  = (u1tmp & BIT(3)) ?
+						 ERFON : ERFOFF;
+			RT_TRACE(rtlpriv, COMP_POWER, DBG_DMESG,
+				("GPIO_IN=%02x\n", u1tmp));
+		}
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("N-SS RF =%x\n",
+			 e_rfpowerstate_toset));
+	}
+	if ((ppsc->hwradiooff) && (e_rfpowerstate_toset == ERFON)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("GPIOChangeRF  - HW "
+			 "Radio ON, RF ON\n"));
+		ppsc->hwradiooff = false;
+		actuallyset = true;
+	} else if ((!ppsc->hwradiooff) && (e_rfpowerstate_toset  ==
+		    ERFOFF)) {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD, ("GPIOChangeRF  - HW"
+			 " Radio OFF\n"));
+		ppsc->hwradiooff = true;
+		actuallyset = true;
+	} else {
+		RT_TRACE(rtlpriv, COMP_POWER, DBG_LOUD ,
+			 ("pHalData->bHwRadioOff and eRfPowerStateToSet do not"
+			 " match: pHalData->bHwRadioOff %x, eRfPowerStateToSet "
+			 "%x\n", ppsc->hwradiooff, e_rfpowerstate_toset));
+	}
+	if (actuallyset) {
+		ppsc->hwradiooff = 1;
+		if (e_rfpowerstate_toset == ERFON) {
+			if ((ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM) &&
+			     RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM))
+				RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
+			else if ((ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_PCI_D3)
+				 && RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3))
+				RT_CLEAR_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3);
+		}
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+		/* For power down module, we need to enable register block
+		 * contrl reg at 0x1c. Then enable power down control bit
+		 * of register 0x04 BIT4 and BIT15 as 1.
+		 */
+		if (ppsc->pwrdown_mode && e_rfpowerstate_toset == ERFOFF) {
+			/* Enable register area 0x0-0xc. */
+			rtl_write_byte(rtlpriv, REG_RSV_CTRL, 0x0);
+			if (IS_HARDWARE_TYPE_8723U(rtlhal)) {
+				/*
+				 * We should configure HW PDn source for WiFi
+				 * ONLY, and then our HW will be set in
+				 * power-down mode if PDn source from all
+				 * functions are configured.
+				 */
+				u1tmp = rtl_read_byte(rtlpriv,
+						      REG_MULTI_FUNC_CTRL);
+				rtl_write_byte(rtlpriv, REG_MULTI_FUNC_CTRL,
+					       (u1tmp|WL_HWPDN_EN));
+			} else {
+				rtl_write_word(rtlpriv, REG_APS_FSMCO, 0x8812);
+			}
+		}
+		if (e_rfpowerstate_toset == ERFOFF) {
+			if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM)
+				RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
+			else if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_PCI_D3)
+				RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3);
+		}
+	} else if (e_rfpowerstate_toset == ERFOFF || cur_rfstate == ERFOFF) {
+		/* Enter D3 or ASPM after GPIO had been done. */
+		if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_ASPM)
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_ASPM);
+		else if (ppsc->reg_rfps_level  & RT_RF_OFF_LEVL_PCI_D3)
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_PCI_D3);
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	} else {
+		spin_lock_irqsave(&rtlpriv->locks.rf_ps_lock, flag);
+		ppsc->rfchange_inprogress = false;
+		spin_unlock_irqrestore(&rtlpriv->locks.rf_ps_lock, flag);
+	}
+	*valid = 1;
+	return !ppsc->hwradiooff;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,116 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_HW_H__
+#define __RTL92CU_HW_H__
+
+#define H2C_RA_MASK	6
+
+#define LLT_POLLING_LLT_THRESHOLD		20
+#define LLT_POLLING_READY_TIMEOUT_COUNT		100
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER		255
+
+#define RX_PAGE_SIZE_REG_VALUE			PBP_128
+/* Note: We will divide number of page equally for each queue
+ * other than public queue! */
+#define TX_TOTAL_PAGE_NUMBER			0xF8
+#define TX_PAGE_BOUNDARY			(TX_TOTAL_PAGE_NUMBER + 1)
+
+
+#define CHIP_B_PAGE_NUM_PUBQ			0xE7
+
+/* For Test Chip Setting
+ * (HPQ + LPQ + PUBQ) shall be TX_TOTAL_PAGE_NUMBER */
+#define CHIP_A_PAGE_NUM_PUBQ			0x7E
+
+
+/* For Chip A Setting */
+#define WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER		0xF5
+#define WMM_CHIP_A_TX_PAGE_BOUNDARY		\
+	(WMM_CHIP_A_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */
+
+#define WMM_CHIP_A_PAGE_NUM_PUBQ		0xA3
+#define WMM_CHIP_A_PAGE_NUM_HPQ			0x29
+#define WMM_CHIP_A_PAGE_NUM_LPQ			0x29
+
+
+
+/* Note: For Chip B Setting ,modify later */
+#define WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER		0xF5
+#define WMM_CHIP_B_TX_PAGE_BOUNDARY		\
+	(WMM_CHIP_B_TX_TOTAL_PAGE_NUMBER + 1) /* F6 */
+
+#define WMM_CHIP_B_PAGE_NUM_PUBQ		0xB0
+#define WMM_CHIP_B_PAGE_NUM_HPQ			0x29
+#define WMM_CHIP_B_PAGE_NUM_LPQ			0x1C
+#define WMM_CHIP_B_PAGE_NUM_NPQ			0x1C
+
+#define BOARD_TYPE_NORMAL_MASK			0xE0
+#define BOARD_TYPE_TEST_MASK			0x0F
+
+/* should be renamed and moved to another file */
+enum _BOARD_TYPE_8192CUSB {
+	BOARD_USB_DONGLE		= 0,	/* USB dongle */
+	BOARD_USB_High_PA		= 1,	/* USB dongle - high power PA */
+	BOARD_MINICARD			= 2,	/* Minicard */
+	BOARD_USB_SOLO			= 3,	/* USB solo-Slim module */
+	BOARD_USB_COMBO			= 4,	/* USB Combo-Slim module */
+};
+
+#define IS_HIGHT_PA(boardtype)		\
+	((boardtype == BOARD_USB_High_PA) ? true : false)
+
+#define RTL92C_DRIVER_INFO_SIZE				4
+void rtl92cu_read_eeprom_info(struct ieee80211_hw *hw);
+void rtl92cu_enable_hw_security_config(struct ieee80211_hw *hw);
+int rtl92cu_hw_init(struct ieee80211_hw *hw);
+void rtl92cu_card_disable(struct ieee80211_hw *hw);
+int rtl92cu_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92cu_set_beacon_related_registers(struct ieee80211_hw *hw);
+void rtl92cu_set_beacon_interval(struct ieee80211_hw *hw);
+void rtl92cu_update_interrupt_mask(struct ieee80211_hw *hw,
+				   u32 add_msr, u32 rm_msr);
+void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val);
+void rtl92cu_update_hal_rate_table(struct ieee80211_hw *hw);
+void rtl92cu_update_hal_rate_mask(struct ieee80211_hw *hw, u8 rssi_level);
+
+void rtl92cu_update_channel_access_setting(struct ieee80211_hw *hw);
+bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid);
+void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid);
+u8 _rtl92c_get_chnl_group(u8 chnl);
+int rtl92c_download_fw(struct ieee80211_hw *hw);
+void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode);
+void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished);
+void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus);
+void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw,
+			 u8 element_id, u32 cmd_len, u8 *p_cmdbuffer);
+bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,142 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../usb.h"
+#include "reg.h"
+#include "led.h"
+
+static void _rtl92cu_init_led(struct ieee80211_hw *hw,
+			      struct rtl_led *pled, enum rtl_led_pin ledpin)
+{
+	pled->hw = hw;
+	pled->ledpin = ledpin;
+	pled->ledon = false;
+}
+
+static void _rtl92cu_deInit_led(struct rtl_led *pled)
+{
+}
+
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	u8 ledcfg;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		rtl_write_byte(rtlpriv,
+			       REG_LEDCFG2, (ledcfg & 0xf0) | BIT(5) | BIT(6));
+		break;
+	case LED_PIN_LED1:
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg & 0x0f) | BIT(5));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	pled->ledon = true;
+}
+
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
+	u8 ledcfg;
+
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD,
+		 ("LedAddr:%X ledpin=%d\n", REG_LEDCFG2, pled->ledpin));
+	ledcfg = rtl_read_byte(rtlpriv, REG_LEDCFG2);
+	switch (pled->ledpin) {
+	case LED_PIN_GPIO0:
+		break;
+	case LED_PIN_LED0:
+		ledcfg &= 0xf0;
+		if (usbpriv->ledctl.led_opendrain == true)
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(1) | BIT(5) | BIT(6)));
+		else
+			rtl_write_byte(rtlpriv, REG_LEDCFG2,
+				       (ledcfg | BIT(3) | BIT(5) | BIT(6)));
+		break;
+	case LED_PIN_LED1:
+		ledcfg &= 0x0f;
+		rtl_write_byte(rtlpriv, REG_LEDCFG2, (ledcfg | BIT(3)));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	pled->ledon = false;
+}
+
+void rtl92cu_init_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
+	_rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led0), LED_PIN_LED0);
+	_rtl92cu_init_led(hw, &(usbpriv->ledctl.sw_led1), LED_PIN_LED1);
+}
+
+void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw)
+{
+	struct rtl_usb_priv *usbpriv = rtl_usbpriv(hw);
+	_rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led0));
+	_rtl92cu_deInit_led(&(usbpriv->ledctl.sw_led1));
+}
+
+static void _rtl92cu_sw_led_control(struct ieee80211_hw *hw,
+				    enum led_ctl_mode ledaction)
+{
+}
+
+void rtl92cu_led_control(struct ieee80211_hw *hw,
+			enum led_ctl_mode ledaction)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+
+	if ((ppsc->rfoff_reason > RF_CHANGE_BY_PS) &&
+	    (ledaction == LED_CTL_TX ||
+	     ledaction == LED_CTL_RX ||
+	     ledaction == LED_CTL_SITE_SURVEY ||
+	     ledaction == LED_CTL_LINK ||
+	     ledaction == LED_CTL_NO_LINK ||
+	     ledaction == LED_CTL_START_TO_LINK ||
+	     ledaction == LED_CTL_POWER_ON)) {
+		return;
+	}
+	RT_TRACE(rtlpriv, COMP_LED, DBG_LOUD, ("ledaction %d,\n",
+				ledaction));
+	_rtl92cu_sw_led_control(hw, ledaction);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/led.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,37 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_LED_H__
+#define __RTL92CU_LED_H__
+
+void rtl92cu_init_sw_leds(struct ieee80211_hw *hw);
+void rtl92cu_deinit_sw_leds(struct ieee80211_hw *hw);
+void rtl92cu_sw_led_on(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92cu_sw_led_off(struct ieee80211_hw *hw, struct rtl_led *pled);
+void rtl92cu_led_control(struct ieee80211_hw *hw, enum led_ctl_mode ledaction);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1144 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+****************************************************************************/
+#include <linux/module.h>
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../usb.h"
+#include "../ps.h"
+#include "../cam.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "mac.h"
+#include "trx.h"
+
+/* macro to shorten lines */
+
+#define LINK_Q	ui_link_quality
+#define RX_EVM	rx_evm_percentage
+#define RX_SIGQ	rx_mimo_signalquality
+
+
+void rtl92c_read_chip_version(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	enum version_8192c chip_version = VERSION_UNKNOWN;
+	u32 value32;
+
+	value32 = rtl_read_dword(rtlpriv, REG_SYS_CFG);
+	if (value32 & TRP_VAUX_EN) {
+		chip_version = (value32 & TYPE_ID) ? VERSION_TEST_CHIP_92C :
+			       VERSION_TEST_CHIP_88C;
+	} else {
+		/* Normal mass production chip. */
+		chip_version = NORMAL_CHIP;
+		chip_version |= ((value32 & TYPE_ID) ? CHIP_92C : 0);
+		chip_version |= ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0);
+		/* RTL8723 with BT function. */
+		chip_version |= ((value32 & BT_FUNC) ? CHIP_8723 : 0);
+		if (IS_VENDOR_UMC(chip_version))
+			chip_version |= ((value32 & CHIP_VER_RTL_MASK) ?
+					 CHIP_VENDOR_UMC_B_CUT : 0);
+		if (IS_92C_SERIAL(chip_version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_HPON_FSM);
+			chip_version |= ((CHIP_BONDING_IDENTIFIER(value32) ==
+				 CHIP_BONDING_92C_1T2R) ? CHIP_92C_1T2R : 0);
+		} else if (IS_8723_SERIES(chip_version)) {
+			value32 = rtl_read_dword(rtlpriv, REG_GPIO_OUTSTS);
+			chip_version |= ((value32 & RF_RL_ID) ?
+					  CHIP_8723_DRV_REV : 0);
+		}
+	}
+	rtlhal->version  = (enum version_8192c)chip_version;
+	switch (rtlhal->version) {
+	case VERSION_NORMAL_TSMC_CHIP_92C_1T2R:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Chip Version ID: VERSION_B_CHIP_92C.\n"));
+		break;
+	case VERSION_NORMAL_TSMC_CHIP_92C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_92C.\n"));
+		break;
+	case VERSION_NORMAL_TSMC_CHIP_88C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_TSMC_CHIP_88C.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP_i"
+			"92C_1T2R_A_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP_"
+			"92C_A_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_88C_A_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_1T2R_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_92C_1T2R_B_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_92C_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_92C_B_CUT.\n"));
+		break;
+	case VERSION_NORMAL_UMC_CHIP_88C_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMAL_UMC_CHIP"
+			"_88C_B_CUT.\n"));
+		break;
+	case VERSION_NORMA_UMC_CHIP_8723_1T1R_A_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMA_UMC_CHIP"
+			"_8723_1T1R_A_CUT.\n"));
+		break;
+	case VERSION_NORMA_UMC_CHIP_8723_1T1R_B_CUT:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_NORMA_UMC_CHIP"
+			"_8723_1T1R_B_CUT.\n"));
+		break;
+	case VERSION_TEST_CHIP_92C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_TEST_CHIP_92C.\n"));
+		break;
+	case VERSION_TEST_CHIP_88C:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: VERSION_TEST_CHIP_88C.\n"));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			("Chip Version ID: ???????????????.\n"));
+		break;
+	}
+	if (IS_92C_SERIAL(rtlhal->version))
+		rtlphy->rf_type =
+			 (IS_92C_1T2R(rtlhal->version)) ? RF_1T2R : RF_2T2R;
+	else
+		rtlphy->rf_type = RF_1T1R;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
+		 ("Chip RF Type: %s\n", (rtlphy->rf_type == RF_2T2R) ?
+		  "RF_2T2R" : "RF_1T1R"));
+	if (get_rf_type(rtlphy) == RF_1T1R)
+		rtlpriv->dm.rfpath_rxenable[0] = true;
+	else
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, ("VersionID = 0x%4x\n",
+						rtlhal->version));
+}
+
+/**
+ * writeLLT - LLT table write access
+ * @io: io callback
+ * @address: LLT logical address.
+ * @data: LLT data content
+ *
+ * Realtek hardware access function.
+ *
+ */
+bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	bool status = true;
+	long count = 0;
+	u32 value = _LLT_INIT_ADDR(address) |
+	    _LLT_INIT_DATA(data) | _LLT_OP(_LLT_WRITE_ACCESS);
+
+	rtl_write_dword(rtlpriv, REG_LLT_INIT, value);
+	do {
+		value = rtl_read_dword(rtlpriv, REG_LLT_INIT);
+		if (_LLT_NO_ACTIVE == _LLT_OP_VALUE(value))
+			break;
+		if (count > POLLING_LLT_THRESHOLD) {
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				 ("Failed to polling write LLT done at"
+				 " address %d! _LLT_OP_VALUE(%x)\n",
+				 address, _LLT_OP_VALUE(value)));
+			status = false;
+			break;
+		}
+	} while (++count);
+	return status;
+}
+/**
+ * rtl92c_init_LLT_table - Init LLT table
+ * @io: io callback
+ * @boundary:
+ *
+ * Realtek hardware access function.
+ *
+ */
+bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary)
+{
+	bool rst = true;
+	u32	i;
+
+	for (i = 0; i < (boundary - 1); i++) {
+		rst = rtl92c_llt_write(hw, i , i + 1);
+		if (true != rst) {
+			printk(KERN_ERR "===> %s #1 fail\n", __func__);
+			return rst;
+		}
+	}
+	/* end of list */
+	rst = rtl92c_llt_write(hw, (boundary - 1), 0xFF);
+	if (true != rst) {
+		printk(KERN_ERR "===> %s #2 fail\n", __func__);
+		return rst;
+	}
+	/* Make the other pages as ring buffer
+	 * This ring buffer is used as beacon buffer if we config this MAC
+	 *  as two MAC transfer.
+	 * Otherwise used as local loopback buffer.
+	 */
+	for (i = boundary; i < LLT_LAST_ENTRY_OF_TX_PKT_BUFFER; i++) {
+		rst = rtl92c_llt_write(hw, i, (i + 1));
+		if (true != rst) {
+			printk(KERN_ERR "===> %s #3 fail\n", __func__);
+			return rst;
+		}
+	}
+	/* Let last entry point to the start entry of ring buffer */
+	rst = rtl92c_llt_write(hw, LLT_LAST_ENTRY_OF_TX_PKT_BUFFER, boundary);
+	if (true != rst) {
+		printk(KERN_ERR "===> %s #4 fail\n", __func__);
+		return rst;
+	}
+	return rst;
+}
+void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
+		     u8 *p_macaddr, bool is_group, u8 enc_algo,
+		     bool is_wepkey, bool clear_all)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 *macaddr = p_macaddr;
+	u32 entry_id = 0;
+	bool is_pairwise = false;
+	static u8 cam_const_addr[4][6] = {
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x01},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x02},
+		{0x00, 0x00, 0x00, 0x00, 0x00, 0x03}
+	};
+	static u8 cam_const_broad[] = {
+		0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+	};
+
+	if (clear_all) {
+		u8 idx = 0;
+		u8 cam_offset = 0;
+		u8 clear_number = 5;
+
+		RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG, ("clear_all\n"));
+		for (idx = 0; idx < clear_number; idx++) {
+			rtl_cam_mark_invalid(hw, cam_offset + idx);
+			rtl_cam_empty_entry(hw, cam_offset + idx);
+			if (idx < 5) {
+				memset(rtlpriv->sec.key_buf[idx], 0,
+				       MAX_KEY_LEN);
+				rtlpriv->sec.key_len[idx] = 0;
+			}
+		}
+	} else {
+		switch (enc_algo) {
+		case WEP40_ENCRYPTION:
+			enc_algo = CAM_WEP40;
+			break;
+		case WEP104_ENCRYPTION:
+			enc_algo = CAM_WEP104;
+			break;
+		case TKIP_ENCRYPTION:
+			enc_algo = CAM_TKIP;
+			break;
+		case AESCCMP_ENCRYPTION:
+			enc_algo = CAM_AES;
+			break;
+		default:
+			RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+				("iillegal switch case\n"));
+			enc_algo = CAM_TKIP;
+			break;
+		}
+		if (is_wepkey || rtlpriv->sec.use_defaultkey) {
+			macaddr = cam_const_addr[key_index];
+			entry_id = key_index;
+		} else {
+			if (is_group) {
+				macaddr = cam_const_broad;
+				entry_id = key_index;
+			} else {
+				key_index = PAIRWISE_KEYIDX;
+				entry_id = CAM_PAIRWISE_KEY_POSITION;
+				is_pairwise = true;
+			}
+		}
+		if (rtlpriv->sec.key_len[key_index] == 0) {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 ("delete one entry\n"));
+			rtl_cam_delete_one_entry(hw, p_macaddr, entry_id);
+		} else {
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+				 ("The insert KEY length is %d\n",
+				  rtlpriv->sec.key_len[PAIRWISE_KEYIDX]));
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_LOUD,
+				 ("The insert KEY  is %x %x\n",
+				  rtlpriv->sec.key_buf[0][0],
+				  rtlpriv->sec.key_buf[0][1]));
+			RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+				 ("add one entry\n"));
+			if (is_pairwise) {
+				RT_PRINT_DATA(rtlpriv, COMP_SEC, DBG_LOUD,
+					      "Pairwiase Key content :",
+					      rtlpriv->sec.pairwise_key,
+					      rtlpriv->sec.
+					      key_len[PAIRWISE_KEYIDX]);
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 ("set Pairwiase key\n"));
+
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						entry_id, enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.
+						key_buf[key_index]);
+			} else {
+				RT_TRACE(rtlpriv, COMP_SEC, DBG_DMESG,
+					 ("set group key\n"));
+				if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+					rtl_cam_add_one_entry(hw,
+						rtlefuse->dev_addr,
+						PAIRWISE_KEYIDX,
+						CAM_PAIRWISE_KEY_POSITION,
+						enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf
+						[entry_id]);
+				}
+				rtl_cam_add_one_entry(hw, macaddr, key_index,
+						entry_id, enc_algo,
+						CAM_CONFIG_NO_USEDK,
+						rtlpriv->sec.key_buf[entry_id]);
+			}
+		}
+	}
+}
+
+u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_dword(rtlpriv, REG_TXDMA_STATUS);
+}
+
+void rtl92c_enable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
+		rtl_write_dword(rtlpriv, REG_HIMR, rtlpci->irq_mask[0] &
+				0xFFFFFFFF);
+		rtl_write_dword(rtlpriv, REG_HIMRE, rtlpci->irq_mask[1] &
+				0xFFFFFFFF);
+		rtlpci->irq_enabled = true;
+	} else {
+		rtl_write_dword(rtlpriv, REG_HIMR, rtlusb->irq_mask[0] &
+				0xFFFFFFFF);
+		rtl_write_dword(rtlpriv, REG_HIMRE, rtlusb->irq_mask[1] &
+				0xFFFFFFFF);
+		rtlusb->irq_enabled = true;
+	}
+}
+
+void rtl92c_init_interrupt(struct ieee80211_hw *hw)
+{
+	 rtl92c_enable_interrupt(hw);
+}
+
+void rtl92c_disable_interrupt(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtl_write_dword(rtlpriv, REG_HIMR, IMR8190_DISABLED);
+	rtl_write_dword(rtlpriv, REG_HIMRE, IMR8190_DISABLED);
+	if (IS_HARDWARE_TYPE_8192CE(rtlhal))
+		rtlpci->irq_enabled = false;
+	else if (IS_HARDWARE_TYPE_8192CU(rtlhal))
+		rtlusb->irq_enabled = false;
+}
+
+void rtl92c_set_qos(struct ieee80211_hw *hw, int aci)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u32 u4b_ac_param;
+
+	rtl92c_dm_init_edca_turbo(hw);
+	u4b_ac_param = (u32) mac->ac[aci].aifs;
+	u4b_ac_param |=
+	    ((u32) le16_to_cpu(mac->ac[aci].cw_min) & 0xF) <<
+	    AC_PARAM_ECW_MIN_OFFSET;
+	u4b_ac_param |=
+	    ((u32) le16_to_cpu(mac->ac[aci].cw_max) & 0xF) <<
+	    AC_PARAM_ECW_MAX_OFFSET;
+	u4b_ac_param |= (u32) le16_to_cpu(mac->ac[aci].tx_op) <<
+			 AC_PARAM_TXOP_OFFSET;
+	RT_TRACE(rtlpriv, COMP_QOS, DBG_LOUD,
+		 ("queue:%x, ac_param:%x\n", aci, u4b_ac_param));
+	switch (aci) {
+	case AC1_BK:
+		rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, u4b_ac_param);
+		break;
+	case AC0_BE:
+		rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, u4b_ac_param);
+		break;
+	case AC2_VI:
+		rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, u4b_ac_param);
+		break;
+	case AC3_VO:
+		rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, u4b_ac_param);
+		break;
+	default:
+		RT_ASSERT(false, ("invalid aci: %d !\n", aci));
+		break;
+	}
+}
+
+/*-------------------------------------------------------------------------
+ * HW MAC Address
+ *-------------------------------------------------------------------------*/
+void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr)
+{
+	u32 i;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	for (i = 0 ; i < ETH_ALEN ; i++)
+		rtl_write_byte(rtlpriv, (REG_MACID + i), *(addr+i));
+
+	RT_TRACE(rtlpriv, COMP_CMD, DBG_DMESG, ("MAC Address: %02X-%02X-%02X-"
+		"%02X-%02X-%02X\n",
+		rtl_read_byte(rtlpriv, REG_MACID),
+		rtl_read_byte(rtlpriv, REG_MACID+1),
+		rtl_read_byte(rtlpriv, REG_MACID+2),
+		rtl_read_byte(rtlpriv, REG_MACID+3),
+		rtl_read_byte(rtlpriv, REG_MACID+4),
+		rtl_read_byte(rtlpriv, REG_MACID+5)));
+}
+
+void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	rtl_write_byte(rtlpriv, REG_RX_DRVINFO_SZ, size);
+}
+
+int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type)
+{
+	u8 value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	switch (type) {
+	case NL80211_IFTYPE_UNSPECIFIED:
+		value = NT_NO_LINK;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to NO LINK!\n"));
+		break;
+	case NL80211_IFTYPE_ADHOC:
+		value = NT_LINK_AD_HOC;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to Ad Hoc!\n"));
+		break;
+	case NL80211_IFTYPE_STATION:
+		value = NT_LINK_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to STA!\n"));
+		break;
+	case NL80211_IFTYPE_AP:
+		value = NT_AS_AP;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Set Network type to AP!\n"));
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			("Network type %d not support!\n", type));
+		return -EOPNOTSUPP;
+	}
+	rtl_write_byte(rtlpriv, (REG_CR + 2), value);
+	return 0;
+}
+
+void rtl92c_init_network_type(struct ieee80211_hw *hw)
+{
+	rtl92c_set_network_type(hw, NL80211_IFTYPE_UNSPECIFIED);
+}
+
+void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw)
+{
+	u16	value16;
+	u32	value32;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* Response Rate Set */
+	value32 = rtl_read_dword(rtlpriv, REG_RRSR);
+	value32 &= ~RATE_BITMAP_ALL;
+	value32 |= RATE_RRSR_CCK_ONLY_1M;
+	rtl_write_dword(rtlpriv, REG_RRSR, value32);
+	/* SIFS (used in NAV) */
+	value16 = _SPEC_SIFS_CCK(0x10) | _SPEC_SIFS_OFDM(0x10);
+	rtl_write_word(rtlpriv,  REG_SPEC_SIFS, value16);
+	/* Retry Limit */
+	value16 = _LRL(0x30) | _SRL(0x30);
+	rtl_write_dword(rtlpriv,  REG_RL, value16);
+}
+
+void rtl92c_init_rate_fallback(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* Set Data Auto Rate Fallback Retry Count register. */
+	rtl_write_dword(rtlpriv,  REG_DARFRC, 0x00000000);
+	rtl_write_dword(rtlpriv,  REG_DARFRC+4, 0x10080404);
+	rtl_write_dword(rtlpriv,  REG_RARFRC, 0x04030201);
+	rtl_write_dword(rtlpriv,  REG_RARFRC+4, 0x08070605);
+}
+
+static void rtl92c_set_cck_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
+				u8 ctx_sifs)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SIFS_CCK, trx_sifs);
+	rtl_write_byte(rtlpriv, (REG_SIFS_CCK + 1), ctx_sifs);
+}
+
+static void rtl92c_set_ofdm_sifs(struct ieee80211_hw *hw, u8 trx_sifs,
+				 u8 ctx_sifs)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_SIFS_OFDM, trx_sifs);
+	rtl_write_byte(rtlpriv, (REG_SIFS_OFDM + 1), ctx_sifs);
+}
+
+void rtl92c_init_edca_param(struct ieee80211_hw *hw,
+			    u16 queue, u16 txop, u8 cw_min, u8 cw_max, u8 aifs)
+{
+	/* sequence: VO, VI, BE, BK ==> the same as 92C hardware design.
+	 * referenc : enum nl80211_txq_q or ieee80211_set_wmm_default function.
+	 */
+	u32 value;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	value = (u32)aifs;
+	value |= ((u32)cw_min & 0xF) << 8;
+	value |= ((u32)cw_max & 0xF) << 12;
+	value |= (u32)txop << 16;
+	/* 92C hardware register sequence is the same as queue number. */
+	rtl_write_dword(rtlpriv, (REG_EDCA_VO_PARAM + (queue * 4)), value);
+}
+
+void rtl92c_init_edca(struct ieee80211_hw *hw)
+{
+	u16 value16;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	/* disable EDCCA count down, to reduce collison and retry */
+	value16 = rtl_read_word(rtlpriv, REG_RD_CTRL);
+	value16 |= DIS_EDCA_CNT_DWN;
+	rtl_write_word(rtlpriv, REG_RD_CTRL, value16);
+	/* Update SIFS timing.  ??????????
+	 * pHalData->SifsTime = 0x0e0e0a0a; */
+	rtl92c_set_cck_sifs(hw, 0xa, 0xa);
+	rtl92c_set_ofdm_sifs(hw, 0xe, 0xe);
+	/* Set CCK/OFDM SIFS to be 10us. */
+	rtl_write_word(rtlpriv, REG_SIFS_CCK, 0x0a0a);
+	rtl_write_word(rtlpriv, REG_SIFS_OFDM, 0x1010);
+	rtl_write_word(rtlpriv, REG_PROT_MODE_CTRL, 0x0204);
+	rtl_write_dword(rtlpriv, REG_BAR_MODE_CTRL, 0x014004);
+	/* TXOP */
+	rtl_write_dword(rtlpriv, REG_EDCA_BE_PARAM, 0x005EA42B);
+	rtl_write_dword(rtlpriv, REG_EDCA_BK_PARAM, 0x0000A44F);
+	rtl_write_dword(rtlpriv, REG_EDCA_VI_PARAM, 0x005EA324);
+	rtl_write_dword(rtlpriv, REG_EDCA_VO_PARAM, 0x002FA226);
+	/* PIFS */
+	rtl_write_byte(rtlpriv, REG_PIFS, 0x1C);
+	/* AGGR BREAK TIME Register */
+	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+	rtl_write_word(rtlpriv, REG_NAV_PROT_LEN, 0x0040);
+	rtl_write_byte(rtlpriv, REG_BCNDMATIM, 0x02);
+	rtl_write_byte(rtlpriv, REG_ATIMWND, 0x02);
+}
+
+void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_dword(rtlpriv, REG_AGGLEN_LMT, 0x99997631);
+	rtl_write_byte(rtlpriv, REG_AGGR_BREAK_TIME, 0x16);
+	/* init AMPDU aggregation number, tuning for Tx's TP, */
+	rtl_write_word(rtlpriv, 0x4CA, 0x0708);
+}
+
+void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_BCN_MAX_ERR, 0xFF);
+}
+
+void rtl92c_init_rdg_setting(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_byte(rtlpriv, REG_RD_CTRL, 0xFF);
+	rtl_write_word(rtlpriv, REG_RD_NAV_NXT, 0x200);
+	rtl_write_byte(rtlpriv, REG_RD_RESP_PKT_TH, 0x05);
+}
+
+void rtl92c_init_retry_function(struct ieee80211_hw *hw)
+{
+	u8	value8;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	value8 = rtl_read_byte(rtlpriv, REG_FWHW_TXQ_CTRL);
+	value8 |= EN_AMPDU_RTY_NEW;
+	rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL, value8);
+	/* Set ACK timeout */
+	rtl_write_byte(rtlpriv, REG_ACKTO, 0x40);
+}
+
+void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
+				   enum version_8192c version)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+
+	rtl_write_word(rtlpriv, REG_TBTT_PROHIBIT, 0x6404);/* ms */
+	rtl_write_byte(rtlpriv, REG_DRVERLYINT, DRIVER_EARLY_INT_TIME);/*ms*/
+	rtl_write_byte(rtlpriv, REG_BCNDMATIM, BCN_DMA_ATIME_INT_TIME);
+	if (IS_NORMAL_CHIP(rtlhal->version))
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x660F);
+	else
+		rtl_write_word(rtlpriv, REG_BCNTCFG, 0x66FF);
+}
+
+void rtl92c_disable_fast_edca(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_FAST_EDCA_CTRL, 0);
+}
+
+void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 value = is2T ? MAX_MSS_DENSITY_2T : MAX_MSS_DENSITY_1T;
+
+	rtl_write_byte(rtlpriv, REG_AMPDU_MIN_SPACE, value);
+}
+
+u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_word(rtlpriv, REG_RXFLTMAP0);
+}
+
+void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_RXFLTMAP0, filter);
+}
+
+u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_word(rtlpriv, REG_RXFLTMAP1);
+}
+
+void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_RXFLTMAP1, filter);
+}
+
+u16 rtl92c_get_data_filter(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	return rtl_read_word(rtlpriv,  REG_RXFLTMAP2);
+}
+
+void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtl_write_word(rtlpriv, REG_RXFLTMAP2, filter);
+}
+/*==============================================================*/
+
+static u8 _rtl92c_query_rxpwrpercentage(char antpower)
+{
+	if ((antpower <= -100) || (antpower >= 20))
+		return 0;
+	else if (antpower >= 0)
+		return 100;
+	else
+		return 100 + antpower;
+}
+
+static u8 _rtl92c_evm_db_to_percentage(char value)
+{
+	char ret_val;
+
+	ret_val = value;
+	if (ret_val >= 0)
+		ret_val = 0;
+	if (ret_val <= -33)
+		ret_val = -33;
+	ret_val = 0 - ret_val;
+	ret_val *= 3;
+	if (ret_val == 99)
+		ret_val = 100;
+	return ret_val;
+}
+
+static long _rtl92c_translate_todbm(struct ieee80211_hw *hw,
+				     u8 signal_strength_index)
+{
+	long signal_power;
+
+	signal_power = (long)((signal_strength_index + 1) >> 1);
+	signal_power -= 95;
+	return signal_power;
+}
+
+static long _rtl92c_signal_scale_mapping(struct ieee80211_hw *hw,
+		long currsig)
+{
+	long retsig;
+
+	if (currsig >= 61 && currsig <= 100)
+		retsig = 90 + ((currsig - 60) / 4);
+	else if (currsig >= 41 && currsig <= 60)
+		retsig = 78 + ((currsig - 40) / 2);
+	else if (currsig >= 31 && currsig <= 40)
+		retsig = 66 + (currsig - 30);
+	else if (currsig >= 21 && currsig <= 30)
+		retsig = 54 + (currsig - 20);
+	else if (currsig >= 5 && currsig <= 20)
+		retsig = 42 + (((currsig - 5) * 2) / 3);
+	else if (currsig == 4)
+		retsig = 36;
+	else if (currsig == 3)
+		retsig = 27;
+	else if (currsig == 2)
+		retsig = 18;
+	else if (currsig == 1)
+		retsig = 9;
+	else
+		retsig = currsig;
+	return retsig;
+}
+
+static void _rtl92c_query_rxphystatus(struct ieee80211_hw *hw,
+				      struct rtl_stats *pstats,
+				      struct rx_desc_92c *pdesc,
+				      struct rx_fwinfo_92c *p_drvinfo,
+				      bool packet_match_bssid,
+				      bool packet_toself,
+				      bool packet_beacon)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct phy_sts_cck_8192s_t *cck_buf;
+	s8 rx_pwr_all = 0, rx_pwr[4];
+	u8 rf_rx_num = 0, evm, pwdb_all;
+	u8 i, max_spatial_stream;
+	u32 rssi, total_rssi = 0;
+	bool in_powersavemode = false;
+	bool is_cck_rate;
+
+	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
+	pstats->packet_matchbssid = packet_match_bssid;
+	pstats->packet_toself = packet_toself;
+	pstats->is_cck = is_cck_rate;
+	pstats->packet_beacon = packet_beacon;
+	pstats->is_cck = is_cck_rate;
+	pstats->RX_SIGQ[0] = -1;
+	pstats->RX_SIGQ[1] = -1;
+	if (is_cck_rate) {
+		u8 report, cck_highpwr;
+		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
+		if (!in_powersavemode)
+			cck_highpwr = rtlphy->cck_high_power;
+		else
+			cck_highpwr = false;
+		if (!cck_highpwr) {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = cck_buf->cck_agc_rpt & 0xc0;
+			report = report >> 6;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
+				break;
+			}
+		} else {
+			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
+			report = p_drvinfo->cfosho[0] & 0x60;
+			report = report >> 5;
+			switch (report) {
+			case 0x3:
+				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x2:
+				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x1:
+				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			case 0x0:
+				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
+				break;
+			}
+		}
+		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
+		pstats->rx_pwdb_all = pwdb_all;
+		pstats->recvsignalpower = rx_pwr_all;
+		if (packet_match_bssid) {
+			u8 sq;
+			if (pstats->rx_pwdb_all > 40)
+				sq = 100;
+			else {
+				sq = cck_buf->sq_rpt;
+				if (sq > 64)
+					sq = 0;
+				else if (sq < 20)
+					sq = 100;
+				else
+					sq = ((64 - sq) * 100) / 44;
+			}
+			pstats->signalquality = sq;
+			pstats->RX_SIGQ[0] = sq;
+			pstats->RX_SIGQ[1] = -1;
+		}
+	} else {
+		rtlpriv->dm.rfpath_rxenable[0] =
+		    rtlpriv->dm.rfpath_rxenable[1] = true;
+		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
+			if (rtlpriv->dm.rfpath_rxenable[i])
+				rf_rx_num++;
+			rx_pwr[i] =
+			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
+			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
+			total_rssi += rssi;
+			rtlpriv->stats.rx_snr_db[i] =
+			    (long)(p_drvinfo->rxsnr[i] / 2);
+
+			if (packet_match_bssid)
+				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
+		}
+		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
+		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
+		pstats->rx_pwdb_all = pwdb_all;
+		pstats->rxpower = rx_pwr_all;
+		pstats->recvsignalpower = rx_pwr_all;
+		if (GET_RX_DESC_RX_MCS(pdesc) &&
+		    GET_RX_DESC_RX_MCS(pdesc) >= DESC92C_RATEMCS8 &&
+		    GET_RX_DESC_RX_MCS(pdesc) <= DESC92C_RATEMCS15)
+			max_spatial_stream = 2;
+		else
+			max_spatial_stream = 1;
+		for (i = 0; i < max_spatial_stream; i++) {
+			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
+			if (packet_match_bssid) {
+				if (i == 0)
+					pstats->signalquality =
+					    (u8) (evm & 0xff);
+				pstats->RX_SIGQ[i] =
+				    (u8) (evm & 0xff);
+			}
+		}
+	}
+	if (is_cck_rate)
+		pstats->signalstrength =
+		    (u8) (_rtl92c_signal_scale_mapping(hw, pwdb_all));
+	else if (rf_rx_num != 0)
+		pstats->signalstrength =
+		    (u8) (_rtl92c_signal_scale_mapping
+			  (hw, total_rssi /= rf_rx_num));
+}
+
+static void _rtl92c_process_ui_rssi(struct ieee80211_hw *hw,
+		struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u8 rfpath;
+	u32 last_rssi, tmpval;
+
+	if (pstats->packet_toself || pstats->packet_beacon) {
+		rtlpriv->stats.rssi_calculate_cnt++;
+		if (rtlpriv->stats.ui_rssi.total_num++ >=
+		    PHY_RSSI_SLID_WIN_MAX) {
+			rtlpriv->stats.ui_rssi.total_num =
+			    PHY_RSSI_SLID_WIN_MAX;
+			last_rssi =
+			    rtlpriv->stats.ui_rssi.elements[rtlpriv->
+							   stats.ui_rssi.index];
+			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
+		}
+		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
+		rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
+					index++] = pstats->signalstrength;
+		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
+			rtlpriv->stats.ui_rssi.index = 0;
+		tmpval = rtlpriv->stats.ui_rssi.total_val /
+		    rtlpriv->stats.ui_rssi.total_num;
+		rtlpriv->stats.signal_strength =
+		    _rtl92c_translate_todbm(hw, (u8) tmpval);
+		pstats->rssi = rtlpriv->stats.signal_strength;
+	}
+	if (!pstats->is_cck && pstats->packet_toself) {
+		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
+		     rfpath++) {
+			if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
+				continue;
+			if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
+				rtlpriv->stats.rx_rssi_percentage[rfpath] =
+				    pstats->rx_mimo_signalstrength[rfpath];
+			}
+			if (pstats->rx_mimo_signalstrength[rfpath] >
+			    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
+				rtlpriv->stats.rx_rssi_percentage[rfpath] =
+				    ((rtlpriv->stats.
+				      rx_rssi_percentage[rfpath] *
+				      (RX_SMOOTH_FACTOR - 1)) +
+				     (pstats->rx_mimo_signalstrength[rfpath])) /
+				    (RX_SMOOTH_FACTOR);
+
+				rtlpriv->stats.rx_rssi_percentage[rfpath] =
+				    rtlpriv->stats.rx_rssi_percentage[rfpath] +
+				    1;
+			} else {
+				rtlpriv->stats.rx_rssi_percentage[rfpath] =
+				    ((rtlpriv->stats.
+				      rx_rssi_percentage[rfpath] *
+				      (RX_SMOOTH_FACTOR - 1)) +
+				     (pstats->rx_mimo_signalstrength[rfpath])) /
+				    (RX_SMOOTH_FACTOR);
+			}
+		}
+	}
+}
+
+static void _rtl92c_update_rxsignalstatistics(struct ieee80211_hw *hw,
+					       struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int weighting = 0;
+
+	if (rtlpriv->stats.recv_signal_power == 0)
+		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
+	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
+		weighting = 5;
+	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
+		weighting = (-5);
+	rtlpriv->stats.recv_signal_power =
+	    (rtlpriv->stats.recv_signal_power * 5 +
+	     pstats->recvsignalpower + weighting) / 6;
+}
+
+static void _rtl92c_process_pwdb(struct ieee80211_hw *hw,
+		struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	long undecorated_smoothed_pwdb = 0;
+
+	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
+		return;
+	} else {
+		undecorated_smoothed_pwdb =
+		    rtlpriv->dm.undecorated_smoothed_pwdb;
+	}
+	if (pstats->packet_toself || pstats->packet_beacon) {
+		if (undecorated_smoothed_pwdb < 0)
+			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
+		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
+			undecorated_smoothed_pwdb =
+			    (((undecorated_smoothed_pwdb) *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
+			    + 1;
+		} else {
+			undecorated_smoothed_pwdb =
+			    (((undecorated_smoothed_pwdb) *
+			      (RX_SMOOTH_FACTOR - 1)) +
+			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
+		}
+		rtlpriv->dm.undecorated_smoothed_pwdb =
+		    undecorated_smoothed_pwdb;
+		_rtl92c_update_rxsignalstatistics(hw, pstats);
+	}
+}
+
+static void _rtl92c_process_LINK_Q(struct ieee80211_hw *hw,
+					     struct rtl_stats *pstats)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 last_evm = 0, n_stream, tmpval;
+
+	if (pstats->signalquality != 0) {
+		if (pstats->packet_toself || pstats->packet_beacon) {
+			if (rtlpriv->stats.LINK_Q.total_num++ >=
+			    PHY_LINKQUALITY_SLID_WIN_MAX) {
+				rtlpriv->stats.LINK_Q.total_num =
+				    PHY_LINKQUALITY_SLID_WIN_MAX;
+				last_evm =
+				    rtlpriv->stats.LINK_Q.elements
+				    [rtlpriv->stats.LINK_Q.index];
+				rtlpriv->stats.LINK_Q.total_val -=
+				    last_evm;
+			}
+			rtlpriv->stats.LINK_Q.total_val +=
+			    pstats->signalquality;
+			rtlpriv->stats.LINK_Q.elements
+			   [rtlpriv->stats.LINK_Q.index++] =
+			    pstats->signalquality;
+			if (rtlpriv->stats.LINK_Q.index >=
+			    PHY_LINKQUALITY_SLID_WIN_MAX)
+				rtlpriv->stats.LINK_Q.index = 0;
+			tmpval = rtlpriv->stats.LINK_Q.total_val /
+			    rtlpriv->stats.LINK_Q.total_num;
+			rtlpriv->stats.signal_quality = tmpval;
+			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
+			for (n_stream = 0; n_stream < 2;
+			     n_stream++) {
+				if (pstats->RX_SIGQ[n_stream] != -1) {
+					if (!rtlpriv->stats.RX_EVM[n_stream]) {
+						rtlpriv->stats.RX_EVM[n_stream]
+						 = pstats->RX_SIGQ[n_stream];
+					}
+					rtlpriv->stats.RX_EVM[n_stream] =
+					    ((rtlpriv->stats.RX_EVM
+					    [n_stream] *
+					    (RX_SMOOTH_FACTOR - 1)) +
+					    (pstats->RX_SIGQ
+					    [n_stream] * 1)) /
+					    (RX_SMOOTH_FACTOR);
+				}
+			}
+		}
+	} else {
+		;
+	}
+}
+
+static void _rtl92c_process_phyinfo(struct ieee80211_hw *hw,
+				     u8 *buffer,
+				     struct rtl_stats *pcurrent_stats)
+{
+	if (!pcurrent_stats->packet_matchbssid &&
+	    !pcurrent_stats->packet_beacon)
+		return;
+	_rtl92c_process_ui_rssi(hw, pcurrent_stats);
+	_rtl92c_process_pwdb(hw, pcurrent_stats);
+	_rtl92c_process_LINK_Q(hw, pcurrent_stats);
+}
+
+void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+					       struct sk_buff *skb,
+					       struct rtl_stats *pstats,
+					       struct rx_desc_92c *pdesc,
+					       struct rx_fwinfo_92c *p_drvinfo)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	struct ieee80211_hdr *hdr;
+	u8 *tmp_buf;
+	u8 *praddr;
+	u8 *psaddr;
+	__le16 fc;
+	u16 type, cpu_fc;
+	bool packet_matchbssid, packet_toself, packet_beacon;
+
+	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
+	hdr = (struct ieee80211_hdr *)tmp_buf;
+	fc = hdr->frame_control;
+	cpu_fc = le16_to_cpu(fc);
+	type = WLAN_FC_GET_TYPE(fc);
+	praddr = hdr->addr1;
+	psaddr = hdr->addr2;
+	packet_matchbssid =
+	    ((IEEE80211_FTYPE_CTL != type) &&
+	     (!compare_ether_addr(mac->bssid,
+			  (cpu_fc & IEEE80211_FCTL_TODS) ?
+			  hdr->addr1 : (cpu_fc & IEEE80211_FCTL_FROMDS) ?
+			  hdr->addr2 : hdr->addr3)) &&
+	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
+
+	packet_toself = packet_matchbssid &&
+	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
+	if (ieee80211_is_beacon(fc))
+		packet_beacon = true;
+	_rtl92c_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
+				   packet_matchbssid, packet_toself,
+				   packet_beacon);
+	_rtl92c_process_phyinfo(hw, tmp_buf, pstats);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/mac.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,180 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92C_MAC_H__
+#define __RTL92C_MAC_H__
+
+#define LLT_LAST_ENTRY_OF_TX_PKT_BUFFER		255
+#define DRIVER_EARLY_INT_TIME					0x05
+#define BCN_DMA_ATIME_INT_TIME				0x02
+
+void rtl92c_read_chip_version(struct ieee80211_hw *hw);
+bool rtl92c_llt_write(struct ieee80211_hw *hw, u32 address, u32 data);
+bool rtl92c_init_llt_table(struct ieee80211_hw *hw, u32 boundary);
+void rtl92c_set_key(struct ieee80211_hw *hw, u32 key_index,
+		     u8 *p_macaddr, bool is_group, u8 enc_algo,
+		     bool is_wepkey, bool clear_all);
+void rtl92c_enable_interrupt(struct ieee80211_hw *hw);
+void rtl92c_disable_interrupt(struct ieee80211_hw *hw);
+void rtl92c_set_qos(struct ieee80211_hw *hw, int aci);
+
+
+/*---------------------------------------------------------------
+ *	Hardware init functions
+ *---------------------------------------------------------------*/
+void rtl92c_set_mac_addr(struct ieee80211_hw *hw, const u8 *addr);
+void rtl92c_init_interrupt(struct ieee80211_hw *hw);
+void rtl92c_init_driver_info_size(struct ieee80211_hw *hw, u8 size);
+
+int rtl92c_set_network_type(struct ieee80211_hw *hw, enum nl80211_iftype type);
+void rtl92c_init_network_type(struct ieee80211_hw *hw);
+void rtl92c_init_adaptive_ctrl(struct ieee80211_hw *hw);
+void rtl92c_init_rate_fallback(struct ieee80211_hw *hw);
+
+void rtl92c_init_edca_param(struct ieee80211_hw *hw,
+							u16 queue,
+							u16 txop,
+							u8 ecwmax,
+							u8 ecwmin,
+							u8 aifs);
+
+void rtl92c_init_edca(struct ieee80211_hw *hw);
+void rtl92c_init_ampdu_aggregation(struct ieee80211_hw *hw);
+void rtl92c_init_beacon_max_error(struct ieee80211_hw *hw, bool infra_mode);
+void rtl92c_init_rdg_setting(struct ieee80211_hw *hw);
+void rtl92c_init_retry_function(struct ieee80211_hw *hw);
+
+void rtl92c_init_beacon_parameters(struct ieee80211_hw *hw,
+				   enum version_8192c version);
+
+void rtl92c_disable_fast_edca(struct ieee80211_hw *hw);
+void rtl92c_set_min_space(struct ieee80211_hw *hw, bool is2T);
+
+/* For filter */
+u16 rtl92c_get_mgt_filter(struct ieee80211_hw *hw);
+void rtl92c_set_mgt_filter(struct ieee80211_hw *hw, u16 filter);
+u16 rtl92c_get_ctrl_filter(struct ieee80211_hw *hw);
+void rtl92c_set_ctrl_filter(struct ieee80211_hw *hw, u16 filter);
+u16 rtl92c_get_data_filter(struct ieee80211_hw *hw);
+void rtl92c_set_data_filter(struct ieee80211_hw *hw, u16 filter);
+
+
+u32 rtl92c_get_txdma_status(struct ieee80211_hw *hw);
+
+#define RX_HAL_IS_CCK_RATE(_pdesc)\
+	(GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE1M ||\
+	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE2M ||\
+	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE5_5M ||\
+	 GET_RX_DESC_RX_MCS(_pdesc) == DESC92C_RATE11M)
+
+struct rx_fwinfo_92c {
+	u8 gain_trsw[4];
+	u8 pwdb_all;
+	u8 cfosho[4];
+	u8 cfotail[4];
+	char rxevm[2];
+	char rxsnr[4];
+	u8 pdsnr[2];
+	u8 csi_current[2];
+	u8 csi_target[2];
+	u8 sigevm;
+	u8 max_ex_pwr;
+	u8 ex_intf_flag:1;
+	u8 sgi_en:1;
+	u8 rxsc:2;
+	u8 reserve:4;
+} __packed;
+
+struct rx_desc_92c {
+	u32 length:14;
+	u32 crc32:1;
+	u32 icverror:1;
+	u32 drv_infosize:4;
+	u32 security:3;
+	u32 qos:1;
+	u32 shift:2;
+	u32 phystatus:1;
+	u32 swdec:1;
+	u32 lastseg:1;
+	u32 firstseg:1;
+	u32 eor:1;
+	u32 own:1;
+	u32 macid:5;	/* word 1 */
+	u32 tid:4;
+	u32 hwrsvd:5;
+	u32 paggr:1;
+	u32 faggr:1;
+	u32 a1_fit:4;
+	u32 a2_fit:4;
+	u32 pam:1;
+	u32 pwr:1;
+	u32 moredata:1;
+	u32 morefrag:1;
+	u32 type:2;
+	u32 mc:1;
+	u32 bc:1;
+	u32 seq:12;	/* word 2 */
+	u32 frag:4;
+	u32 nextpktlen:14;
+	u32 nextind:1;
+	u32 rsvd:1;
+	u32 rxmcs:6;	/* word 3 */
+	u32 rxht:1;
+	u32 amsdu:1;
+	u32 splcp:1;
+	u32 bandwidth:1;
+	u32 htc:1;
+	u32 tcpchk_rpt:1;
+	u32 ipcchk_rpt:1;
+	u32 tcpchk_valid:1;
+	u32 hwpcerr:1;
+	u32 hwpcind:1;
+	u32 iv0:16;
+	u32 iv1;	/* word 4 */
+	u32 tsfl;	/* word 5 */
+	u32 bufferaddress;	/* word 6 */
+	u32 bufferaddress64;	/* word 7 */
+} __packed;
+
+enum rtl_desc_qsel rtl92c_map_hwqueue_to_fwqueue(u16 fc,
+							  unsigned int
+							  skb_queue);
+void rtl92c_translate_rx_signal_stuff(struct ieee80211_hw *hw,
+				      struct sk_buff *skb,
+				      struct rtl_stats *pstats,
+				      struct rx_desc_92c *pdesc,
+				      struct rx_fwinfo_92c *p_drvinfo);
+
+/*---------------------------------------------------------------
+ *	Card disable functions
+ *---------------------------------------------------------------*/
+
+
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,14 @@
+rtl8192cu-objs :=		\
+		dm.o		\
+		hw.o		\
+		led.o		\
+		mac.o		\
+		phy.o		\
+		rf.o		\
+		sw.o		\
+		table.o		\
+		trx.o
+
+obj-$(CONFIG_RTL8192CU) += rtl8192cu.o
+
+ccflags-y += -D__CHECK_ENDIAN__
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,607 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../pci.h"
+#include "../ps.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "table.h"
+
+u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
+			    enum radio_path rfpath, u32 regaddr, u32 bitmask)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u32 original_value, readback_value, bitshift;
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+					       "rfpath(%#x), bitmask(%#x)\n",
+					       regaddr, rfpath, bitmask));
+	if (rtlphy->rf_mode != RF_OP_BY_FW) {
+		original_value = _rtl92c_phy_rf_serial_read(hw,
+							    rfpath, regaddr);
+	} else {
+		original_value = _rtl92c_phy_fw_rf_serial_read(hw,
+							       rfpath, regaddr);
+	}
+	bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+	readback_value = (original_value & bitmask) >> bitshift;
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 ("regaddr(%#x), rfpath(%#x), "
+		  "bitmask(%#x), original_value(%#x)\n",
+		  regaddr, rfpath, bitmask, original_value));
+	return readback_value;
+}
+
+void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
+			   enum radio_path rfpath,
+			   u32 regaddr, u32 bitmask, u32 data)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 original_value, bitshift;
+
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE,
+		 ("regaddr(%#x), bitmask(%#x), data(%#x), rfpath(%#x)\n",
+		  regaddr, bitmask, data, rfpath));
+	if (rtlphy->rf_mode != RF_OP_BY_FW) {
+		if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = _rtl92c_phy_rf_serial_read(hw,
+								    rfpath,
+								    regaddr);
+			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			data =
+			    ((original_value & (~bitmask)) |
+			     (data << bitshift));
+		}
+		_rtl92c_phy_rf_serial_write(hw, rfpath, regaddr, data);
+	} else {
+		if (bitmask != RFREG_OFFSET_MASK) {
+			original_value = _rtl92c_phy_fw_rf_serial_read(hw,
+								       rfpath,
+								       regaddr);
+			bitshift = _rtl92c_phy_calculate_bit_shift(bitmask);
+			data =
+			    ((original_value & (~bitmask)) |
+			     (data << bitshift));
+		}
+		_rtl92c_phy_fw_rf_serial_write(hw, rfpath, regaddr, data);
+	}
+	RT_TRACE(rtlpriv, COMP_RF, DBG_TRACE, ("regaddr(%#x), "
+					       "bitmask(%#x), data(%#x), rfpath(%#x)\n",
+					       regaddr, bitmask, data, rfpath));
+}
+
+bool rtl92cu_phy_mac_config(struct ieee80211_hw *hw)
+{
+	bool rtstatus;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	bool is92c = IS_92C_SERIAL(rtlhal->version);
+
+	rtstatus = _rtl92cu_phy_config_mac_with_headerfile(hw);
+	if (is92c && IS_HARDWARE_TYPE_8192CE(rtlhal))
+		rtl_write_byte(rtlpriv, 0x14, 0x71);
+	return rtstatus;
+}
+
+bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw)
+{
+	bool rtstatus = true;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	u16 regval;
+	u8 b_reg_hwparafile = 1;
+
+	_rtl92c_phy_init_bb_rf_register_definition(hw);
+	regval = rtl_read_word(rtlpriv, REG_SYS_FUNC_EN);
+	rtl_write_word(rtlpriv, REG_SYS_FUNC_EN, regval | BIT(13) |
+		       BIT(0) | BIT(1));
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL, 0x83);
+	rtl_write_byte(rtlpriv, REG_AFE_PLL_CTRL + 1, 0xdb);
+	rtl_write_byte(rtlpriv, REG_RF_CTRL, RF_EN | RF_RSTB | RF_SDMRSTB);
+	if (IS_HARDWARE_TYPE_8192CE(rtlhal)) {
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_PPLL | FEN_PCIEA |
+			       FEN_DIO_PCIE |	FEN_BB_GLB_RSTn | FEN_BBRSTB);
+	} else if (IS_HARDWARE_TYPE_8192CU(rtlhal)) {
+		rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN, FEN_USBA | FEN_USBD |
+			       FEN_BB_GLB_RSTn | FEN_BBRSTB);
+		rtl_write_byte(rtlpriv, REG_LDOHCI12_CTRL, 0x0f);
+	}
+	rtl_write_byte(rtlpriv, REG_AFE_XTAL_CTRL + 1, 0x80);
+	if (b_reg_hwparafile == 1)
+		rtstatus = _rtl92c_phy_bb8192c_config_parafile(hw);
+	return rtstatus;
+}
+
+bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 i;
+	u32 arraylength;
+	u32 *ptrarray;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Read Rtl819XMACPHY_Array\n"));
+	arraylength =  rtlphy->hwparam_tables[MAC_REG].length ;
+	ptrarray = rtlphy->hwparam_tables[MAC_REG].pdata;
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+		 ("Img:RTL8192CEMAC_2T_ARRAY\n"));
+	for (i = 0; i < arraylength; i = i + 2)
+		rtl_write_byte(rtlpriv, ptrarray[i], (u8) ptrarray[i + 1]);
+	return true;
+}
+
+bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+						  u8 configtype)
+{
+	int i;
+	u32 *phy_regarray_table;
+	u32 *agctab_array_table;
+	u16 phy_reg_arraylen, agctab_arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (IS_92C_SERIAL(rtlhal->version)) {
+		agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_2T].length;
+		agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_2T].pdata;
+		phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_2T].length;
+		phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_2T].pdata;
+	} else {
+		agctab_arraylen = rtlphy->hwparam_tables[AGCTAB_1T].length;
+		agctab_array_table =  rtlphy->hwparam_tables[AGCTAB_1T].pdata;
+		phy_reg_arraylen = rtlphy->hwparam_tables[PHY_REG_1T].length;
+		phy_regarray_table = rtlphy->hwparam_tables[PHY_REG_1T].pdata;
+	}
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_reg_arraylen; i = i + 2) {
+			if (phy_regarray_table[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table[i] == 0xf9)
+				udelay(1);
+			rtl_set_bbreg(hw, phy_regarray_table[i], MASKDWORD,
+				      phy_regarray_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("The phy_regarray_table[0] is %x"
+				  " Rtl819XPHY_REGArray[1] is %x\n",
+				  phy_regarray_table[i],
+				  phy_regarray_table[i + 1]));
+		}
+	} else if (configtype == BASEBAND_CONFIG_AGC_TAB) {
+		for (i = 0; i < agctab_arraylen; i = i + 2) {
+			rtl_set_bbreg(hw, agctab_array_table[i], MASKDWORD,
+				      agctab_array_table[i + 1]);
+			udelay(1);
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("The agctab_array_table[0] is "
+				  "%x Rtl819XPHY_REGArray[1] is %x\n",
+				  agctab_array_table[i],
+				  agctab_array_table[i + 1]));
+		}
+	}
+	return true;
+}
+
+bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+						    u8 configtype)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	int i;
+	u32 *phy_regarray_table_pg;
+	u16 phy_regarray_pg_len;
+
+	rtlphy->pwrgroup_cnt = 0;
+	phy_regarray_pg_len = rtlphy->hwparam_tables[PHY_REG_PG].length;
+	phy_regarray_table_pg = rtlphy->hwparam_tables[PHY_REG_PG].pdata;
+	if (configtype == BASEBAND_CONFIG_PHY_REG) {
+		for (i = 0; i < phy_regarray_pg_len; i = i + 3) {
+			if (phy_regarray_table_pg[i] == 0xfe)
+				mdelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfd)
+				mdelay(5);
+			else if (phy_regarray_table_pg[i] == 0xfc)
+				mdelay(1);
+			else if (phy_regarray_table_pg[i] == 0xfb)
+				udelay(50);
+			else if (phy_regarray_table_pg[i] == 0xfa)
+				udelay(5);
+			else if (phy_regarray_table_pg[i] == 0xf9)
+				udelay(1);
+			_rtl92c_store_pwrIndex_diffrate_offset(hw,
+						  phy_regarray_table_pg[i],
+						  phy_regarray_table_pg[i + 1],
+						  phy_regarray_table_pg[i + 2]);
+		}
+	} else {
+		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+			 ("configtype != BaseBand_Config_PHY_REG\n"));
+	}
+	return true;
+}
+
+bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath)
+{
+	int i;
+	u32 *radioa_array_table;
+	u32 *radiob_array_table;
+	u16 radioa_arraylen, radiob_arraylen;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	if (IS_92C_SERIAL(rtlhal->version)) {
+		radioa_arraylen = rtlphy->hwparam_tables[RADIOA_2T].length;
+		radioa_array_table = rtlphy->hwparam_tables[RADIOA_2T].pdata;
+		radiob_arraylen = rtlphy->hwparam_tables[RADIOB_2T].length;
+		radiob_array_table = rtlphy->hwparam_tables[RADIOB_2T].pdata;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_A:RTL8192CERADIOA_2TARRAY\n"));
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_B:RTL8192CE_RADIOB_2TARRAY\n"));
+	} else {
+		radioa_arraylen = rtlphy->hwparam_tables[RADIOA_1T].length;
+		radioa_array_table = rtlphy->hwparam_tables[RADIOA_1T].pdata;
+		radiob_arraylen = rtlphy->hwparam_tables[RADIOB_1T].length;
+		radiob_array_table = rtlphy->hwparam_tables[RADIOB_1T].pdata;
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_A:RTL8192CE_RADIOA_1TARRAY\n"));
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+			 ("Radio_B:RTL8192CE_RADIOB_1TARRAY\n"));
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("Radio No %x\n", rfpath));
+	switch (rfpath) {
+	case RF90_PATH_A:
+		for (i = 0; i < radioa_arraylen; i = i + 2) {
+			if (radioa_array_table[i] == 0xfe)
+				mdelay(50);
+			else if (radioa_array_table[i] == 0xfd)
+				mdelay(5);
+			else if (radioa_array_table[i] == 0xfc)
+				mdelay(1);
+			else if (radioa_array_table[i] == 0xfb)
+				udelay(50);
+			else if (radioa_array_table[i] == 0xfa)
+				udelay(5);
+			else if (radioa_array_table[i] == 0xf9)
+				udelay(1);
+			else {
+				rtl_set_rfreg(hw, rfpath, radioa_array_table[i],
+					      RFREG_OFFSET_MASK,
+					      radioa_array_table[i + 1]);
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_B:
+		for (i = 0; i < radiob_arraylen; i = i + 2) {
+			if (radiob_array_table[i] == 0xfe) {
+				mdelay(50);
+			} else if (radiob_array_table[i] == 0xfd)
+				mdelay(5);
+			else if (radiob_array_table[i] == 0xfc)
+				mdelay(1);
+			else if (radiob_array_table[i] == 0xfb)
+				udelay(50);
+			else if (radiob_array_table[i] == 0xfa)
+				udelay(5);
+			else if (radiob_array_table[i] == 0xf9)
+				udelay(1);
+			else {
+				rtl_set_rfreg(hw, rfpath, radiob_array_table[i],
+					      RFREG_OFFSET_MASK,
+					      radiob_array_table[i + 1]);
+				udelay(1);
+			}
+		}
+		break;
+	case RF90_PATH_C:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	case RF90_PATH_D:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		break;
+	}
+	return true;
+}
+
+void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	u8 reg_bw_opmode;
+	u8 reg_prsr_rsc;
+
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE,
+		 ("Switch to %s bandwidth\n",
+		  rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20 ?
+		  "20MHz" : "40MHz"))
+	if (is_hal_stop(rtlhal)) {
+		rtlphy->set_bwmode_inprogress = false;
+		return;
+	}
+	reg_bw_opmode = rtl_read_byte(rtlpriv, REG_BWOPMODE);
+	reg_prsr_rsc = rtl_read_byte(rtlpriv, REG_RRSR + 2);
+	switch (rtlphy->current_chan_bw) {
+	case HT_CHANNEL_WIDTH_20:
+		reg_bw_opmode |= BW_OPMODE_20MHZ;
+		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		reg_bw_opmode &= ~BW_OPMODE_20MHZ;
+		rtl_write_byte(rtlpriv, REG_BWOPMODE, reg_bw_opmode);
+		reg_prsr_rsc =
+		    (reg_prsr_rsc & 0x90) | (mac->cur_40_prime_sc << 5);
+		rtl_write_byte(rtlpriv, REG_RRSR + 2, reg_prsr_rsc);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+		break;
+	}
+	switch (rtlphy->current_chan_bw) {
+	case HT_CHANNEL_WIDTH_20:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x0);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x0);
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 1);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtl_set_bbreg(hw, RFPGA0_RFMOD, BRFMOD, 0x1);
+		rtl_set_bbreg(hw, RFPGA1_RFMOD, BRFMOD, 0x1);
+		rtl_set_bbreg(hw, RCCK0_SYSTEM, BCCK_SIDEBAND,
+			      (mac->cur_40_prime_sc >> 1));
+		rtl_set_bbreg(hw, ROFDM1_LSTF, 0xC00, mac->cur_40_prime_sc);
+		rtl_set_bbreg(hw, RFPGA0_ANALOGPARAMETER2, BIT(10), 0);
+		rtl_set_bbreg(hw, 0x818, (BIT(26) | BIT(27)),
+			      (mac->cur_40_prime_sc ==
+			       HAL_PRIME_CHNL_OFFSET_LOWER) ? 2 : 1);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("unknown bandwidth: %#X\n", rtlphy->current_chan_bw));
+		break;
+	}
+	rtl92cu_phy_rf6052_set_bandwidth(hw, rtlphy->current_chan_bw);
+	rtlphy->set_bwmode_inprogress = false;
+	RT_TRACE(rtlpriv, COMP_SCAN, DBG_TRACE, ("<==\n"));
+}
+
+void rtl92cu_bb_block_on(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	mutex_lock(&rtlpriv->io.bb_mutex);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BCCKEN, 0x1);
+	rtl_set_bbreg(hw, RFPGA0_RFMOD, BOFDMEN, 0x1);
+	mutex_unlock(&rtlpriv->io.bb_mutex);
+}
+
+void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t)
+{
+	u8 tmpreg;
+	u32 rf_a_mode = 0, rf_b_mode = 0, lc_cal;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	tmpreg = rtl_read_byte(rtlpriv, 0xd03);
+
+	if ((tmpreg & 0x70) != 0)
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg & 0x8F);
+	else
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0xFF);
+
+	if ((tmpreg & 0x70) != 0) {
+		rf_a_mode = rtl_get_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS);
+		if (is2t)
+			rf_b_mode = rtl_get_rfreg(hw, RF90_PATH_B, 0x00,
+						  MASK12BITS);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS,
+			      (rf_a_mode & 0x8FFFF) | 0x10000);
+		if (is2t)
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+				      (rf_b_mode & 0x8FFFF) | 0x10000);
+	}
+	lc_cal = rtl_get_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS);
+	rtl_set_rfreg(hw, RF90_PATH_A, 0x18, MASK12BITS, lc_cal | 0x08000);
+	mdelay(100);
+	if ((tmpreg & 0x70) != 0) {
+		rtl_write_byte(rtlpriv, 0xd03, tmpreg);
+		rtl_set_rfreg(hw, RF90_PATH_A, 0x00, MASK12BITS, rf_a_mode);
+		if (is2t)
+			rtl_set_rfreg(hw, RF90_PATH_B, 0x00, MASK12BITS,
+				      rf_b_mode);
+	} else {
+		rtl_write_byte(rtlpriv, REG_TXPAUSE, 0x00);
+	}
+}
+
+bool _rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
+					    enum rf_pwrstate rfpwr_state)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool bresult = true;
+	u8 i, queue_id;
+	struct rtl8192_tx_ring *ring = NULL;
+
+	ppsc->set_rfpowerstate_inprogress = true;
+	switch (rfpwr_state) {
+	case ERFON:
+		if ((ppsc->rfpwr_state == ERFOFF) &&
+		    RT_IN_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC)) {
+			bool rtstatus;
+			u32 InitializeCount = 0;
+
+			do {
+				InitializeCount++;
+				RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+					 ("IPS Set eRf nic enable\n"));
+				rtstatus = rtl_ps_enable_nic(hw);
+			} while ((rtstatus != true)
+				 && (InitializeCount < 10));
+			RT_CLEAR_PS_LEVEL(ppsc,
+					  RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 ("Set ERFON sleeped:%d ms\n",
+				  jiffies_to_msecs(jiffies -
+						   ppsc->
+						   last_sleep_jiffies)));
+			ppsc->last_awake_jiffies = jiffies;
+			rtl92ce_phy_set_rf_on(hw);
+		}
+		if (mac->link_state == MAC80211_LINKED) {
+			rtlpriv->cfg->ops->led_control(hw,
+						       LED_CTL_LINK);
+		} else {
+			rtlpriv->cfg->ops->led_control(hw,
+						       LED_CTL_NO_LINK);
+		}
+		break;
+	case ERFOFF:
+		for (queue_id = 0, i = 0;
+		     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+			ring = &pcipriv->dev.tx_ring[queue_id];
+			if (skb_queue_len(&ring->queue) == 0 ||
+				queue_id == BEACON_QUEUE) {
+				queue_id++;
+				continue;
+			} else {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("eRf Off/Sleep: %d times "
+					  "TcbBusyQueue[%d] "
+					  "=%d before doze!\n", (i + 1),
+					  queue_id,
+					  skb_queue_len(&ring->queue)));
+				udelay(10);
+				i++;
+			}
+			if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("\nERFOFF: %d times "
+					  "TcbBusyQueue[%d] = %d !\n",
+					  MAX_DOZE_WAITING_TIMES_9x,
+					  queue_id,
+					  skb_queue_len(&ring->queue)));
+				break;
+			}
+		}
+		if (ppsc->reg_rfps_level & RT_RF_OFF_LEVL_HALT_NIC) {
+			RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+				 ("IPS Set eRf nic disable\n"));
+			rtl_ps_disable_nic(hw);
+			RT_SET_PS_LEVEL(ppsc, RT_RF_OFF_LEVL_HALT_NIC);
+		} else {
+			if (ppsc->rfoff_reason == RF_CHANGE_BY_IPS) {
+				rtlpriv->cfg->ops->led_control(hw,
+							 LED_CTL_NO_LINK);
+			} else {
+				rtlpriv->cfg->ops->led_control(hw,
+							 LED_CTL_POWER_OFF);
+			}
+		}
+		break;
+	case ERFSLEEP:
+		if (ppsc->rfpwr_state == ERFOFF)
+			break;
+		for (queue_id = 0, i = 0;
+		     queue_id < RTL_PCI_MAX_TX_QUEUE_COUNT;) {
+			ring = &pcipriv->dev.tx_ring[queue_id];
+			if (skb_queue_len(&ring->queue) == 0) {
+				queue_id++;
+				continue;
+			} else {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("eRf Off/Sleep: %d times "
+					  "TcbBusyQueue[%d] =%d before "
+					  "doze!\n", (i + 1), queue_id,
+					  skb_queue_len(&ring->queue)));
+				udelay(10);
+				i++;
+			}
+			if (i >= MAX_DOZE_WAITING_TIMES_9x) {
+				RT_TRACE(rtlpriv, COMP_ERR, DBG_WARNING,
+					 ("\n ERFSLEEP: %d times "
+					  "TcbBusyQueue[%d] = %d !\n",
+					  MAX_DOZE_WAITING_TIMES_9x,
+					  queue_id,
+					  skb_queue_len(&ring->queue)));
+				break;
+			}
+		}
+		RT_TRACE(rtlpriv, COMP_RF, DBG_DMESG,
+			 ("Set ERFSLEEP awaked:%d ms\n",
+			  jiffies_to_msecs(jiffies -
+					   ppsc->last_awake_jiffies)));
+		ppsc->last_sleep_jiffies = jiffies;
+		_rtl92c_phy_set_rf_sleep(hw);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("switch case not process\n"));
+		bresult = false;
+		break;
+	}
+	if (bresult)
+		ppsc->rfpwr_state = rfpwr_state;
+	ppsc->set_rfpowerstate_inprogress = false;
+	return bresult;
+}
+
+bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
+				   enum rf_pwrstate rfpwr_state)
+{
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool bresult = false;
+
+	if (rfpwr_state == ppsc->rfpwr_state)
+		return bresult;
+	bresult = _rtl92cu_phy_set_rf_power_state(hw, rfpwr_state);
+	return bresult;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/phy.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,36 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/phy.h"
+
+void rtl92cu_bb_block_on(struct ieee80211_hw *hw);
+bool rtl8192_phy_check_is_legal_rfpath(struct ieee80211_hw *hw, u32 rfpath);
+void rtl92c_phy_set_io(struct ieee80211_hw *hw);
+bool _rtl92cu_phy_config_mac_with_headerfile(struct ieee80211_hw *hw);
+bool rtl92cu_phy_bb_config(struct ieee80211_hw *hw);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/reg.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,30 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../rtl8192ce/reg.h"
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,493 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+
+static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw);
+
+void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw, u8 bandwidth)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+
+	switch (bandwidth) {
+	case HT_CHANNEL_WIDTH_20:
+		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+					     0xfffff3ff) | 0x0400);
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+			      rtlphy->rfreg_chnlval[0]);
+		break;
+	case HT_CHANNEL_WIDTH_20_40:
+		rtlphy->rfreg_chnlval[0] = ((rtlphy->rfreg_chnlval[0] &
+					     0xfffff3ff));
+		rtl_set_rfreg(hw, RF90_PATH_A, RF_CHNLBW, RFREG_OFFSET_MASK,
+			      rtlphy->rfreg_chnlval[0]);
+		break;
+	default:
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("unknown bandwidth: %#X\n", bandwidth));
+		break;
+	}
+}
+
+void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+				       u8 *ppowerlevel)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 tx_agc[2] = { 0, 0 }, tmpval = 0;
+	bool turbo_scanoff = false;
+	u8 idx1, idx2;
+	u8 *ptr;
+
+	if (rtlhal->interface == INTF_PCI) {
+		if (rtlefuse->eeprom_regulatory != 0)
+			turbo_scanoff = true;
+	} else {
+		if ((rtlefuse->eeprom_regulatory != 0) ||
+		    (rtlefuse->external_pa))
+			turbo_scanoff = true;
+	}
+	if (mac->act_scanning == true) {
+		tx_agc[RF90_PATH_A] = 0x3f3f3f3f;
+		tx_agc[RF90_PATH_B] = 0x3f3f3f3f;
+		if (turbo_scanoff) {
+			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+				tx_agc[idx1] = ppowerlevel[idx1] |
+				    (ppowerlevel[idx1] << 8) |
+				    (ppowerlevel[idx1] << 16) |
+				    (ppowerlevel[idx1] << 24);
+				if (rtlhal->interface == INTF_USB) {
+					if (tx_agc[idx1] > 0x20 &&
+					    rtlefuse->external_pa)
+						tx_agc[idx1] = 0x20;
+				}
+			}
+		}
+	} else {
+		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+		    TXHIGHPWRLEVEL_LEVEL1) {
+			tx_agc[RF90_PATH_A] = 0x10101010;
+			tx_agc[RF90_PATH_B] = 0x10101010;
+		} else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			   TXHIGHPWRLEVEL_LEVEL1) {
+			tx_agc[RF90_PATH_A] = 0x00000000;
+			tx_agc[RF90_PATH_B] = 0x00000000;
+		} else{
+			for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+				tx_agc[idx1] = ppowerlevel[idx1] |
+				    (ppowerlevel[idx1] << 8) |
+				    (ppowerlevel[idx1] << 16) |
+				    (ppowerlevel[idx1] << 24);
+			}
+			if (rtlefuse->eeprom_regulatory == 0) {
+				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
+					[0][6]) +
+					(rtlphy->mcs_txpwrlevel_origoffset
+					[0][7] <<  8);
+				tx_agc[RF90_PATH_A] += tmpval;
+				tmpval = (rtlphy->mcs_txpwrlevel_origoffset
+					[0][14]) +
+					(rtlphy->mcs_txpwrlevel_origoffset
+					[0][15] << 24);
+				tx_agc[RF90_PATH_B] += tmpval;
+			}
+		}
+	}
+	for (idx1 = RF90_PATH_A; idx1 <= RF90_PATH_B; idx1++) {
+		ptr = (u8 *) (&(tx_agc[idx1]));
+		for (idx2 = 0; idx2 < 4; idx2++) {
+			if (*ptr > RF6052_MAX_TX_PWR)
+				*ptr = RF6052_MAX_TX_PWR;
+			ptr++;
+		}
+	}
+	tmpval = tx_agc[RF90_PATH_A] & 0xff;
+	rtl_set_bbreg(hw, RTXAGC_A_CCK1_MCS32, MASKBYTE1, tmpval);
+
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 1M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+		 RTXAGC_A_CCK1_MCS32));
+
+	tmpval = tx_agc[RF90_PATH_A] >> 8;
+	if (mac->mode == WIRELESS_MODE_B)
+		tmpval = tmpval & 0xff00ffff;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, 0xffffff00, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 2~11M (rf-A) = 0x%x (reg 0x%x)\n", tmpval,
+		 RTXAGC_B_CCK11_A_CCK2_11));
+	tmpval = tx_agc[RF90_PATH_B] >> 24;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK11_A_CCK2_11, MASKBYTE0, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 11M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+		 RTXAGC_B_CCK11_A_CCK2_11));
+	tmpval = tx_agc[RF90_PATH_B] & 0x00ffffff;
+	rtl_set_bbreg(hw, RTXAGC_B_CCK1_55_MCS32, 0xffffff00, tmpval);
+	RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+		("CCK PWR 1~5.5M (rf-B) = 0x%x (reg 0x%x)\n", tmpval,
+		 RTXAGC_B_CCK1_55_MCS32));
+}
+
+static void rtl92c_phy_get_power_base(struct ieee80211_hw *hw,
+				      u8 *ppowerlevel, u8 channel,
+				      u32 *ofdmbase, u32 *mcsbase)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u32 powerBase0, powerBase1;
+	u8 legacy_pwrdiff = 0, ht20_pwrdiff = 0;
+	u8 i, powerlevel[2];
+
+	for (i = 0; i < 2; i++) {
+		powerlevel[i] = ppowerlevel[i];
+		legacy_pwrdiff = rtlefuse->txpwr_legacyhtdiff[i][channel - 1];
+		powerBase0 = powerlevel[i] + legacy_pwrdiff;
+		powerBase0 = (powerBase0 << 24) | (powerBase0 << 16) |
+		    (powerBase0 << 8) | powerBase0;
+		*(ofdmbase + i) = powerBase0;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			(" [OFDM power base index rf(%c) = 0x%x]\n",
+			 ((i == 0) ? 'A' : 'B'), *(ofdmbase + i)));
+	}
+	for (i = 0; i < 2; i++) {
+		if (rtlphy->current_chan_bw == HT_CHANNEL_WIDTH_20) {
+			ht20_pwrdiff = rtlefuse->txpwr_ht20diff[i][channel - 1];
+			powerlevel[i] += ht20_pwrdiff;
+		}
+		powerBase1 = powerlevel[i];
+		powerBase1 = (powerBase1 << 24) |
+		    (powerBase1 << 16) | (powerBase1 << 8) | powerBase1;
+		*(mcsbase + i) = powerBase1;
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			(" [MCS power base index rf(%c) = 0x%x]\n",
+			 ((i == 0) ? 'A' : 'B'), *(mcsbase + i)));
+	}
+}
+
+static void _rtl92c_get_txpower_writeval_by_regulatory(struct ieee80211_hw *hw,
+						       u8 channel, u8 index,
+						       u32 *powerBase0,
+						       u32 *powerBase1,
+						       u32 *p_outwriteval)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
+	u8 i, chnlgroup = 0, pwr_diff_limit[4];
+	u32 writeVal, customer_limit, rf;
+
+	for (rf = 0; rf < 2; rf++) {
+		switch (rtlefuse->eeprom_regulatory) {
+		case 0:
+			chnlgroup = 0;
+			writeVal = rtlphy->mcs_txpwrlevel_origoffset
+			    [chnlgroup][index + (rf ? 8 : 0)]
+			    + ((index < 2) ? powerBase0[rf] : powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("RTK better performance,writeVal(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		case 1:
+			if (rtlphy->pwrgroup_cnt == 1)
+				chnlgroup = 0;
+			if (rtlphy->pwrgroup_cnt >= 3) {
+				if (channel <= 3)
+					chnlgroup = 0;
+				else if (channel >= 4 && channel <= 9)
+					chnlgroup = 1;
+				else if (channel > 9)
+					chnlgroup = 2;
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20)
+					chnlgroup++;
+				else
+					chnlgroup += 4;
+			}
+			writeVal = rtlphy->mcs_txpwrlevel_origoffset
+					[chnlgroup][index +
+					(rf ? 8 : 0)] +
+					((index < 2) ? powerBase0[rf] :
+					powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Realtek regulatory, 20MHz, "
+				"writeVal(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		case 2:
+			writeVal = ((index < 2) ? powerBase0[rf] :
+				   powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Better regulatory,writeVal(%c) = 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		case 3:
+			chnlgroup = 0;
+			if (rtlphy->current_chan_bw ==
+			    HT_CHANNEL_WIDTH_20_40) {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("customer's limit, 40MHzrf(%c) = "
+					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht40[rf]
+					[channel - 1]));
+			} else {
+				RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+					("customer's limit, 20MHz rf(%c) = "
+					"0x%x\n", ((rf == 0) ? 'A' : 'B'),
+					rtlefuse->pwrgroup_ht20[rf]
+					[channel - 1]));
+			}
+			for (i = 0; i < 4; i++) {
+				pwr_diff_limit[i] =
+				    (u8) ((rtlphy->mcs_txpwrlevel_origoffset
+				    [chnlgroup][index + (rf ? 8 : 0)]
+				    & (0x7f << (i * 8))) >> (i * 8));
+				if (rtlphy->current_chan_bw ==
+				    HT_CHANNEL_WIDTH_20_40) {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->pwrgroup_ht40[rf]
+						[channel - 1])
+						pwr_diff_limit[i] = rtlefuse->
+						    pwrgroup_ht40[rf]
+						    [channel - 1];
+				} else {
+					if (pwr_diff_limit[i] >
+					    rtlefuse->pwrgroup_ht20[rf]
+						[channel - 1])
+						pwr_diff_limit[i] =
+						    rtlefuse->pwrgroup_ht20[rf]
+						    [channel - 1];
+				}
+			}
+			customer_limit = (pwr_diff_limit[3] << 24) |
+			    (pwr_diff_limit[2] << 16) |
+			    (pwr_diff_limit[1] << 8) | (pwr_diff_limit[0]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Customer's limit rf(%c) = 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), customer_limit));
+			writeVal = customer_limit + ((index < 2) ?
+				   powerBase0[rf] : powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+				("Customer, writeVal rf(%c)= 0x%x\n",
+				 ((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		default:
+			chnlgroup = 0;
+			writeVal = rtlphy->mcs_txpwrlevel_origoffset[chnlgroup]
+				   [index + (rf ? 8 : 0)] + ((index < 2) ?
+				   powerBase0[rf] : powerBase1[rf]);
+			RTPRINT(rtlpriv, FPHY, PHY_TXPWR, ("RTK better "
+				"performance, writeValrf(%c) = 0x%x\n",
+				((rf == 0) ? 'A' : 'B'), writeVal));
+			break;
+		}
+		if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+		    TXHIGHPWRLEVEL_LEVEL1)
+			writeVal = 0x14141414;
+		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			 TXHIGHPWRLEVEL_LEVEL2)
+			writeVal = 0x00000000;
+		if (rtlpriv->dm.dynamic_txhighpower_lvl == TXHIGHPWRLEVEL_BT1)
+			writeVal = writeVal - 0x06060606;
+		else if (rtlpriv->dm.dynamic_txhighpower_lvl ==
+			 TXHIGHPWRLEVEL_BT2)
+			writeVal = writeVal;
+		*(p_outwriteval + rf) = writeVal;
+	}
+}
+
+static void _rtl92c_write_ofdm_power_reg(struct ieee80211_hw *hw,
+					 u8 index, u32 *pValue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u16 regoffset_a[6] = {
+		RTXAGC_A_RATE18_06, RTXAGC_A_RATE54_24,
+		RTXAGC_A_MCS03_MCS00, RTXAGC_A_MCS07_MCS04,
+		RTXAGC_A_MCS11_MCS08, RTXAGC_A_MCS15_MCS12
+	};
+	u16 regoffset_b[6] = {
+		RTXAGC_B_RATE18_06, RTXAGC_B_RATE54_24,
+		RTXAGC_B_MCS03_MCS00, RTXAGC_B_MCS07_MCS04,
+		RTXAGC_B_MCS11_MCS08, RTXAGC_B_MCS15_MCS12
+	};
+	u8 i, rf, pwr_val[4];
+	u32 writeVal;
+	u16 regoffset;
+
+	for (rf = 0; rf < 2; rf++) {
+		writeVal = pValue[rf];
+		for (i = 0; i < 4; i++) {
+			pwr_val[i] = (u8)((writeVal & (0x7f << (i * 8))) >>
+					  (i * 8));
+			if (pwr_val[i] > RF6052_MAX_TX_PWR)
+				pwr_val[i] = RF6052_MAX_TX_PWR;
+		}
+		writeVal = (pwr_val[3] << 24) | (pwr_val[2] << 16) |
+		    (pwr_val[1] << 8) | pwr_val[0];
+		if (rf == 0)
+			regoffset = regoffset_a[index];
+		else
+			regoffset = regoffset_b[index];
+		rtl_set_bbreg(hw, regoffset, MASKDWORD, writeVal);
+		RTPRINT(rtlpriv, FPHY, PHY_TXPWR,
+			("Set 0x%x = %08x\n", regoffset, writeVal));
+		if (((get_rf_type(rtlphy) == RF_2T2R) &&
+		     (regoffset == RTXAGC_A_MCS15_MCS12 ||
+		      regoffset == RTXAGC_B_MCS15_MCS12)) ||
+		    ((get_rf_type(rtlphy) != RF_2T2R) &&
+		     (regoffset == RTXAGC_A_MCS07_MCS04 ||
+		      regoffset == RTXAGC_B_MCS07_MCS04))) {
+			writeVal = pwr_val[3];
+			if (regoffset == RTXAGC_A_MCS15_MCS12 ||
+			    regoffset == RTXAGC_A_MCS07_MCS04)
+				regoffset = 0xc90;
+			if (regoffset == RTXAGC_B_MCS15_MCS12 ||
+			    regoffset == RTXAGC_B_MCS07_MCS04)
+				regoffset = 0xc98;
+			for (i = 0; i < 3; i++) {
+				writeVal = (writeVal > 6) ? (writeVal - 6) : 0;
+				rtl_write_byte(rtlpriv, (u32)(regoffset + i),
+					      (u8)writeVal);
+			}
+		}
+	}
+}
+
+void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel, u8 channel)
+{
+	u32 writeVal[2], powerBase0[2], powerBase1[2];
+	u8 index = 0;
+
+	rtl92c_phy_get_power_base(hw, ppowerlevel,
+				  channel, &powerBase0[0], &powerBase1[0]);
+	for (index = 0; index < 6; index++) {
+		_rtl92c_get_txpower_writeval_by_regulatory(hw,
+							   channel, index,
+							   &powerBase0[0],
+							   &powerBase1[0],
+							   &writeVal[0]);
+		_rtl92c_write_ofdm_power_reg(hw, index, &writeVal[0]);
+	}
+}
+
+bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	bool rtstatus = true;
+	u8 b_reg_hwparafile = 1;
+
+	if (rtlphy->rf_type == RF_1T1R)
+		rtlphy->num_total_rfpath = 1;
+	else
+		rtlphy->num_total_rfpath = 2;
+	if (b_reg_hwparafile == 1)
+		rtstatus = _rtl92c_phy_rf6052_config_parafile(hw);
+	return rtstatus;
+}
+
+static bool _rtl92c_phy_rf6052_config_parafile(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_phy *rtlphy = &(rtlpriv->phy);
+	u32 u4_regvalue = 0;
+	u8 rfpath;
+	bool rtstatus = true;
+	struct bb_reg_def *pphyreg;
+
+	for (rfpath = 0; rfpath < rtlphy->num_total_rfpath; rfpath++) {
+		pphyreg = &rtlphy->phyreg_def[rfpath];
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			u4_regvalue = rtl_get_bbreg(hw, pphyreg->rfintfs,
+						    BRFSI_RFENV << 16);
+			break;
+		}
+		rtl_set_bbreg(hw, pphyreg->rfintfe, BRFSI_RFENV << 16, 0x1);
+		udelay(1);
+		rtl_set_bbreg(hw, pphyreg->rfintfo, BRFSI_RFENV, 0x1);
+		udelay(1);
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2,
+			      B3WIREADDREAALENGTH, 0x0);
+		udelay(1);
+		rtl_set_bbreg(hw, pphyreg->rfhssi_para2, B3WIREDATALENGTH, 0x0);
+		udelay(1);
+		switch (rfpath) {
+		case RF90_PATH_A:
+			rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
+					(enum radio_path) rfpath);
+			break;
+		case RF90_PATH_B:
+			rtstatus = rtl92cu_phy_config_rf_with_headerfile(hw,
+					(enum radio_path) rfpath);
+			break;
+		case RF90_PATH_C:
+			break;
+		case RF90_PATH_D:
+			break;
+		}
+		switch (rfpath) {
+		case RF90_PATH_A:
+		case RF90_PATH_C:
+			rtl_set_bbreg(hw, pphyreg->rfintfs,
+				      BRFSI_RFENV, u4_regvalue);
+			break;
+		case RF90_PATH_B:
+		case RF90_PATH_D:
+			rtl_set_bbreg(hw, pphyreg->rfintfs,
+				      BRFSI_RFENV << 16, u4_regvalue);
+			break;
+		}
+		if (rtstatus != true) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE,
+				 ("Radio[%d] Fail!!", rfpath));
+			goto phy_rf_cfg_fail;
+		}
+	}
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_TRACE, ("<---\n"));
+	return rtstatus;
+phy_rf_cfg_fail:
+	return rtstatus;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/rf.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,47 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_RF_H__
+#define __RTL92CU_RF_H__
+
+#define RF6052_MAX_TX_PWR		0x3F
+#define RF6052_MAX_REG			0x3F
+#define RF6052_MAX_PATH			2
+
+extern void rtl92cu_phy_rf6052_set_bandwidth(struct ieee80211_hw *hw,
+					    u8 bandwidth);
+extern void rtl92c_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					      u8 *ppowerlevel);
+extern void rtl92c_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					       u8 *ppowerlevel, u8 channel);
+bool rtl92cu_phy_rf6052_config(struct ieee80211_hw *hw);
+bool rtl92cu_phy_config_rf_with_headerfile(struct ieee80211_hw *hw,
+					  enum radio_path rfpath);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c	2012-03-24 03:34:40.000000000 -0400
@@ -0,0 +1,336 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../core.h"
+#include "../usb.h"
+#include "../efuse.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "mac.h"
+#include "dm.h"
+#include "rf.h"
+#include "sw.h"
+#include "trx.h"
+#include "led.h"
+#include "hw.h"
+#include <linux/vmalloc.h>
+
+MODULE_AUTHOR("Georgia		<georgia@realtek.com>");
+MODULE_AUTHOR("Ziv Huang	<ziv_huang@realtek.com>");
+MODULE_AUTHOR("Larry Finger	<Larry.Finger@lwfinger.net>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("Realtek 8192C/8188C 802.11n USB wireless");
+/*(DEBLOBBED)*/
+
+static int rtl92cu_init_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->dm.dm_initialgain_enable = 1;
+	rtlpriv->dm.dm_flag = 0;
+	rtlpriv->dm.disable_framebursting = 0;
+	rtlpriv->dm.thermalvalue = 0;
+	rtlpriv->rtlhal.pfirmware = vmalloc(0x4000);
+	if (!rtlpriv->rtlhal.pfirmware) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't alloc buffer for fw.\n"));
+		return 1;
+	}
+	return 0;
+}
+
+static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (rtlpriv->rtlhal.pfirmware) {
+		vfree(rtlpriv->rtlhal.pfirmware);
+		rtlpriv->rtlhal.pfirmware = NULL;
+	}
+}
+
+static struct rtl_hal_ops rtl8192cu_hal_ops = {
+	.init_sw_vars = rtl92cu_init_sw_vars,
+	.deinit_sw_vars = rtl92cu_deinit_sw_vars,
+	.read_chip_version = rtl92c_read_chip_version,
+	.read_eeprom_info = rtl92cu_read_eeprom_info,
+	.enable_interrupt = rtl92c_enable_interrupt,
+	.disable_interrupt = rtl92c_disable_interrupt,
+	.hw_init = rtl92cu_hw_init,
+	.hw_disable = rtl92cu_card_disable,
+	.set_network_type = rtl92cu_set_network_type,
+	.set_chk_bssid = rtl92cu_set_check_bssid,
+	.set_qos = rtl92c_set_qos,
+	.set_bcn_reg = rtl92cu_set_beacon_related_registers,
+	.set_bcn_intv = rtl92cu_set_beacon_interval,
+	.update_interrupt_mask = rtl92cu_update_interrupt_mask,
+	.get_hw_reg = rtl92cu_get_hw_reg,
+	.set_hw_reg = rtl92cu_set_hw_reg,
+	.update_rate_table = rtl92cu_update_hal_rate_table,
+	.update_rate_mask = rtl92cu_update_hal_rate_mask,
+	.fill_tx_desc = rtl92cu_tx_fill_desc,
+	.fill_fake_txdesc = rtl92cu_fill_fake_txdesc,
+	.fill_tx_cmddesc = rtl92cu_tx_fill_cmddesc,
+	.cmd_send_packet = rtl92cu_cmd_send_packet,
+	.query_rx_desc = rtl92cu_rx_query_desc,
+	.set_channel_access = rtl92cu_update_channel_access_setting,
+	.radio_onoff_checking = rtl92cu_gpio_radio_on_off_checking,
+	.set_bw_mode = rtl92c_phy_set_bw_mode,
+	.switch_channel = rtl92c_phy_sw_chnl,
+	.dm_watchdog = rtl92c_dm_watchdog,
+	.scan_operation_backup = rtl92c_phy_scan_operation_backup,
+	.set_rf_power_state = rtl92cu_phy_set_rf_power_state,
+	.led_control = rtl92cu_led_control,
+	.enable_hw_sec = rtl92cu_enable_hw_security_config,
+	.set_key = rtl92c_set_key,
+	.init_sw_leds = rtl92cu_init_sw_leds,
+	.deinit_sw_leds = rtl92cu_deinit_sw_leds,
+	.get_bbreg = rtl92c_phy_query_bb_reg,
+	.set_bbreg = rtl92c_phy_set_bb_reg,
+	.get_rfreg = rtl92cu_phy_query_rf_reg,
+	.set_rfreg = rtl92cu_phy_set_rf_reg,
+	.phy_rf6052_config = rtl92cu_phy_rf6052_config,
+	.phy_rf6052_set_cck_txpower = rtl92cu_phy_rf6052_set_cck_txpower,
+	.phy_rf6052_set_ofdm_txpower = rtl92cu_phy_rf6052_set_ofdm_txpower,
+	.config_bb_with_headerfile = _rtl92cu_phy_config_bb_with_headerfile,
+	.config_bb_with_pgheaderfile = _rtl92cu_phy_config_bb_with_pgheaderfile,
+	.phy_lc_calibrate = _rtl92cu_phy_lc_calibrate,
+	.phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback,
+	.dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower,
+};
+
+static struct rtl_mod_params rtl92cu_mod_params = {
+	.sw_crypto = 0,
+};
+
+static struct rtl_hal_usbint_cfg rtl92cu_interface_cfg = {
+	/* rx */
+	.in_ep_num = RTL92C_USB_BULK_IN_NUM,
+	.rx_urb_num = RTL92C_NUM_RX_URBS,
+	.rx_max_size = RTL92C_SIZE_MAX_RX_BUFFER,
+	.usb_rx_hdl = rtl8192cu_rx_hdl,
+	.usb_rx_segregate_hdl = NULL, /* rtl8192c_rx_segregate_hdl; */
+	/* tx */
+	.usb_tx_cleanup = rtl8192c_tx_cleanup,
+	.usb_tx_post_hdl = rtl8192c_tx_post_hdl,
+	.usb_tx_aggregate_hdl = rtl8192c_tx_aggregate_hdl,
+	/* endpoint mapping */
+	.usb_endpoint_mapping = rtl8192cu_endpoint_mapping,
+	.usb_mq_to_hwq = rtl8192cu_mq_to_hwq,
+};
+
+static struct rtl_hal_cfg rtl92cu_hal_cfg = {
+	.name = "rtl92c_usb",
+	.fw_name = "/*(DEBLOBBED)*/",
+	.ops = &rtl8192cu_hal_ops,
+	.mod_params = &rtl92cu_mod_params,
+	.usb_interface_cfg = &rtl92cu_interface_cfg,
+
+	.maps[SYS_ISO_CTRL] = REG_SYS_ISO_CTRL,
+	.maps[SYS_FUNC_EN] = REG_SYS_FUNC_EN,
+	.maps[SYS_CLK] = REG_SYS_CLKR,
+	.maps[MAC_RCR_AM] = AM,
+	.maps[MAC_RCR_AB] = AB,
+	.maps[MAC_RCR_ACRC32] = ACRC32,
+	.maps[MAC_RCR_ACF] = ACF,
+	.maps[MAC_RCR_AAP] = AAP,
+
+	.maps[EFUSE_TEST] = REG_EFUSE_TEST,
+	.maps[EFUSE_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_CLK] = 0,
+	.maps[EFUSE_CLK_CTRL] = REG_EFUSE_CTRL,
+	.maps[EFUSE_PWC_EV12V] = PWC_EV12V,
+	.maps[EFUSE_FEN_ELDR] = FEN_ELDR,
+	.maps[EFUSE_LOADER_CLK_EN] = LOADER_CLK_EN,
+	.maps[EFUSE_ANA8M] = EFUSE_ANA8M,
+	.maps[EFUSE_HWSET_MAX_SIZE] = HWSET_MAX_SIZE,
+	.maps[EFUSE_MAX_SECTION_MAP] = EFUSE_MAX_SECTION,
+	.maps[EFUSE_REAL_CONTENT_SIZE] = EFUSE_REAL_CONTENT_LEN,
+
+	.maps[RWCAM] = REG_CAMCMD,
+	.maps[WCAMI] = REG_CAMWRITE,
+	.maps[RCAMO] = REG_CAMREAD,
+	.maps[CAMDBG] = REG_CAMDBG,
+	.maps[SECR] = REG_SECCFG,
+	.maps[SEC_CAM_NONE] = CAM_NONE,
+	.maps[SEC_CAM_WEP40] = CAM_WEP40,
+	.maps[SEC_CAM_TKIP] = CAM_TKIP,
+	.maps[SEC_CAM_AES] = CAM_AES,
+	.maps[SEC_CAM_WEP104] = CAM_WEP104,
+
+	.maps[RTL_IMR_BCNDMAINT6] = IMR_BCNDMAINT6,
+	.maps[RTL_IMR_BCNDMAINT5] = IMR_BCNDMAINT5,
+	.maps[RTL_IMR_BCNDMAINT4] = IMR_BCNDMAINT4,
+	.maps[RTL_IMR_BCNDMAINT3] = IMR_BCNDMAINT3,
+	.maps[RTL_IMR_BCNDMAINT2] = IMR_BCNDMAINT2,
+	.maps[RTL_IMR_BCNDMAINT1] = IMR_BCNDMAINT1,
+	.maps[RTL_IMR_BCNDOK8] = IMR_BCNDOK8,
+	.maps[RTL_IMR_BCNDOK7] = IMR_BCNDOK7,
+	.maps[RTL_IMR_BCNDOK6] = IMR_BCNDOK6,
+	.maps[RTL_IMR_BCNDOK5] = IMR_BCNDOK5,
+	.maps[RTL_IMR_BCNDOK4] = IMR_BCNDOK4,
+	.maps[RTL_IMR_BCNDOK3] = IMR_BCNDOK3,
+	.maps[RTL_IMR_BCNDOK2] = IMR_BCNDOK2,
+	.maps[RTL_IMR_BCNDOK1] = IMR_BCNDOK1,
+	.maps[RTL_IMR_TIMEOUT2] = IMR_TIMEOUT2,
+	.maps[RTL_IMR_TIMEOUT1] = IMR_TIMEOUT1,
+
+	.maps[RTL_IMR_TXFOVW] = IMR_TXFOVW,
+	.maps[RTL_IMR_PSTIMEOUT] = IMR_PSTIMEOUT,
+	.maps[RTL_IMR_BcnInt] = IMR_BCNINT,
+	.maps[RTL_IMR_RXFOVW] = IMR_RXFOVW,
+	.maps[RTL_IMR_RDU] = IMR_RDU,
+	.maps[RTL_IMR_ATIMEND] = IMR_ATIMEND,
+	.maps[RTL_IMR_BDOK] = IMR_BDOK,
+	.maps[RTL_IMR_MGNTDOK] = IMR_MGNTDOK,
+	.maps[RTL_IMR_TBDER] = IMR_TBDER,
+	.maps[RTL_IMR_HIGHDOK] = IMR_HIGHDOK,
+	.maps[RTL_IMR_TBDOK] = IMR_TBDOK,
+	.maps[RTL_IMR_BKDOK] = IMR_BKDOK,
+	.maps[RTL_IMR_BEDOK] = IMR_BEDOK,
+	.maps[RTL_IMR_VIDOK] = IMR_VIDOK,
+	.maps[RTL_IMR_VODOK] = IMR_VODOK,
+	.maps[RTL_IMR_ROK] = IMR_ROK,
+	.maps[RTL_IBSS_INT_MASKS] = (IMR_BCNINT | IMR_TBDOK | IMR_TBDER),
+
+	.maps[RTL_RC_CCK_RATE1M] = DESC92C_RATE1M,
+	.maps[RTL_RC_CCK_RATE2M] = DESC92C_RATE2M,
+	.maps[RTL_RC_CCK_RATE5_5M] = DESC92C_RATE5_5M,
+	.maps[RTL_RC_CCK_RATE11M] = DESC92C_RATE11M,
+	.maps[RTL_RC_OFDM_RATE6M] = DESC92C_RATE6M,
+	.maps[RTL_RC_OFDM_RATE9M] = DESC92C_RATE9M,
+	.maps[RTL_RC_OFDM_RATE12M] = DESC92C_RATE12M,
+	.maps[RTL_RC_OFDM_RATE18M] = DESC92C_RATE18M,
+	.maps[RTL_RC_OFDM_RATE24M] = DESC92C_RATE24M,
+	.maps[RTL_RC_OFDM_RATE36M] = DESC92C_RATE36M,
+	.maps[RTL_RC_OFDM_RATE48M] = DESC92C_RATE48M,
+	.maps[RTL_RC_OFDM_RATE54M] = DESC92C_RATE54M,
+	.maps[RTL_RC_HT_RATEMCS7] = DESC92C_RATEMCS7,
+	.maps[RTL_RC_HT_RATEMCS15] = DESC92C_RATEMCS15,
+};
+
+#define USB_VENDER_ID_REALTEK		0x0bda
+
+/* 2010-10-19 DID_USB_V3.4 */
+static struct usb_device_id rtl8192c_usb_ids[] = {
+
+	/*=== Realtek demoboard ===*/
+	/* Default ID */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8191, rtl92cu_hal_cfg)},
+
+	/****** 8188CU ********/
+	/* 8188CE-VAU USB minCard */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8170, rtl92cu_hal_cfg)},
+	/* 8188cu 1*1 dongle */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8176, rtl92cu_hal_cfg)},
+	/* 8188cu 1*1 dongle, (b/g mode only) */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)},
+	/* 8188cu Slim Solo */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817a, rtl92cu_hal_cfg)},
+	/* 8188cu Slim Combo */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)},
+	/* 8188RU High-power USB Dongle */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817d, rtl92cu_hal_cfg)},
+	/* 8188CE-VAU USB minCard (b/g mode only) */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817e, rtl92cu_hal_cfg)},
+	/* 8188 Combo for BC4 */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8754, rtl92cu_hal_cfg)},
+
+	/****** 8192CU ********/
+	/* 8191cu 1*2 */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x8177, rtl92cu_hal_cfg)},
+	/* 8192cu 2*2 */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817b, rtl92cu_hal_cfg)},
+	/* 8192CE-VAU USB minCard */
+	{RTL_USB_DEVICE(USB_VENDER_ID_REALTEK, 0x817c, rtl92cu_hal_cfg)},
+
+	/*=== Customer ID ===*/
+	/****** 8188CU ********/
+	{RTL_USB_DEVICE(0x050d, 0x1102, rtl92cu_hal_cfg)}, /*Belkin - Edimax*/
+	{RTL_USB_DEVICE(0x06f8, 0xe033, rtl92cu_hal_cfg)}, /*Hercules - Edimax*/
+	{RTL_USB_DEVICE(0x07b8, 0x8188, rtl92cu_hal_cfg)}, /*Abocom - Abocom*/
+	{RTL_USB_DEVICE(0x07b8, 0x8189, rtl92cu_hal_cfg)}, /*Funai - Abocom*/
+	{RTL_USB_DEVICE(0x0Df6, 0x0052, rtl92cu_hal_cfg)}, /*Sitecom - Edimax*/
+	{RTL_USB_DEVICE(0x0eb0, 0x9071, rtl92cu_hal_cfg)}, /*NO Brand - Etop*/
+	/* HP - Lite-On ,8188CUS Slim Combo */
+	{RTL_USB_DEVICE(0x103c, 0x1629, rtl92cu_hal_cfg)},
+	{RTL_USB_DEVICE(0x2001, 0x3308, rtl92cu_hal_cfg)}, /*D-Link - Alpha*/
+	{RTL_USB_DEVICE(0x2019, 0xab2a, rtl92cu_hal_cfg)}, /*Planex - Abocom*/
+	{RTL_USB_DEVICE(0x2019, 0xed17, rtl92cu_hal_cfg)}, /*PCI - Edimax*/
+	{RTL_USB_DEVICE(0x20f4, 0x648b, rtl92cu_hal_cfg)}, /*TRENDnet - Cameo*/
+	{RTL_USB_DEVICE(0x7392, 0x7811, rtl92cu_hal_cfg)}, /*Edimax - Edimax*/
+	{RTL_USB_DEVICE(0x3358, 0x13d3, rtl92cu_hal_cfg)}, /*Azwave 8188CE-VAU*/
+	/* Russian customer -Azwave (8188CE-VAU  b/g mode only) */
+	{RTL_USB_DEVICE(0x3359, 0x13d3, rtl92cu_hal_cfg)},
+
+	/****** 8192CU ********/
+	{RTL_USB_DEVICE(0x0586, 0x341f, rtl92cu_hal_cfg)}, /*Zyxel -Abocom*/
+	{RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/
+	{RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/
+	{RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Abocom -Abocom*/
+	{RTL_USB_DEVICE(0x2001, 0x3307, rtl92cu_hal_cfg)}, /*D-Link-Cameo*/
+	{RTL_USB_DEVICE(0x2001, 0x3309, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+	{RTL_USB_DEVICE(0x2001, 0x330a, rtl92cu_hal_cfg)}, /*D-Link-Alpha*/
+	{RTL_USB_DEVICE(0x2019, 0xab2b, rtl92cu_hal_cfg)}, /*Planex -Abocom*/
+	{RTL_USB_DEVICE(0x7392, 0x7822, rtl92cu_hal_cfg)}, /*Edimax -Edimax*/
+	{}
+};
+
+MODULE_DEVICE_TABLE(usb, rtl8192c_usb_ids);
+
+static struct usb_driver rtl8192cu_driver = {
+	.name = "rtl8192cu",
+	.probe = rtl_usb_probe,
+	.disconnect = rtl_usb_disconnect,
+	.id_table = rtl8192c_usb_ids,
+
+#ifdef CONFIG_PM
+	/* .suspend = rtl_usb_suspend, */
+	/* .resume = rtl_usb_resume, */
+	/* .reset_resume = rtl8192c_resume, */
+#endif /* CONFIG_PM */
+#ifdef CONFIG_AUTOSUSPEND
+	.supports_autosuspend = 1,
+#endif
+};
+
+static int __init rtl8192cu_init(void)
+{
+	return usb_register(&rtl8192cu_driver);
+}
+
+static void __exit rtl8192cu_exit(void)
+{
+	usb_deregister(&rtl8192cu_driver);
+}
+
+module_init(rtl8192cu_init);
+module_exit(rtl8192cu_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/sw.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,53 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_SW_H__
+#define __RTL92CU_SW_H__
+
+#define EFUSE_MAX_SECTION	16
+
+void rtl92cu_phy_rf6052_set_cck_txpower(struct ieee80211_hw *hw,
+					u8 *powerlevel);
+void rtl92cu_phy_rf6052_set_ofdm_txpower(struct ieee80211_hw *hw,
+					u8 *ppowerlevel, u8 channel);
+bool _rtl92cu_phy_config_bb_with_headerfile(struct ieee80211_hw *hw,
+					    u8 configtype);
+bool _rtl92cu_phy_config_bb_with_pgheaderfile(struct ieee80211_hw *hw,
+						    u8 configtype);
+void _rtl92cu_phy_lc_calibrate(struct ieee80211_hw *hw, bool is2t);
+void rtl92cu_phy_set_rf_reg(struct ieee80211_hw *hw,
+			   enum radio_path rfpath,
+			   u32 regaddr, u32 bitmask, u32 data);
+bool rtl92cu_phy_set_rf_power_state(struct ieee80211_hw *hw,
+				   enum rf_pwrstate rfpwr_state);
+u32 rtl92cu_phy_query_rf_reg(struct ieee80211_hw *hw,
+			    enum radio_path rfpath, u32 regaddr, u32 bitmask);
+void rtl92cu_phy_set_bw_mode_callback(struct ieee80211_hw *hw);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1888 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "table.h"
+
+u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH] = {
+	0x024, 0x0011800f,
+	0x028, 0x00ffdb83,
+	0x800, 0x80040002,
+	0x804, 0x00000003,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390004,
+	0x828, 0x01000100,
+	0x82c, 0x00390004,
+	0x830, 0x27272727,
+	0x834, 0x27272727,
+	0x838, 0x27272727,
+	0x83c, 0x27272727,
+	0x840, 0x00010000,
+	0x844, 0x00010000,
+	0x848, 0x27272727,
+	0x84c, 0x27272727,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569a569a,
+	0x85c, 0x0c1b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x27272727,
+	0x86c, 0x2b2b2b27,
+	0x870, 0x07000700,
+	0x874, 0x22184000,
+	0x878, 0x08080808,
+	0x87c, 0x00000000,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xcc0000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121313,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x1a1b0000,
+	0xa24, 0x090e1317,
+	0xa28, 0x00000204,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xc00, 0x48071d40,
+	0xc04, 0x03a05633,
+	0xc08, 0x000000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x6954341e,
+	0xc54, 0x43bc0094,
+	0xc58, 0x6954341e,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c7f000d,
+	0xc74, 0x0186115b,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b99612,
+	0xc80, 0x40000100,
+	0xc84, 0x20f60000,
+	0xc88, 0x40000100,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020403,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x2a2a2a2a,
+	0xe04, 0x2a2a2a2a,
+	0xe08, 0x03902a2a,
+	0xe10, 0x2a2a2a2a,
+	0xe14, 0x2a2a2a2a,
+	0xe18, 0x2a2a2a2a,
+	0xe1c, 0x2a2a2a2a,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000010,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x63db25a4,
+	0xe70, 0x63db25a4,
+	0xe74, 0x0c1b25a4,
+	0xe78, 0x0c1b25a4,
+	0xe7c, 0x0c1b25a4,
+	0xe80, 0x0c1b25a4,
+	0xe84, 0x63db25a4,
+	0xe88, 0x0c1b25a4,
+	0xe8c, 0x63db25a4,
+	0xed0, 0x63db25a4,
+	0xed4, 0x63db25a4,
+	0xed8, 0x63db25a4,
+	0xedc, 0x001b25a4,
+	0xee0, 0x001b25a4,
+	0xeec, 0x6fdb25a4,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH] = {
+	0x024, 0x0011800f,
+	0x028, 0x00ffdb83,
+	0x800, 0x80040000,
+	0x804, 0x00000001,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390004,
+	0x828, 0x00000000,
+	0x82c, 0x00000000,
+	0x830, 0x00000000,
+	0x834, 0x00000000,
+	0x838, 0x00000000,
+	0x83c, 0x00000000,
+	0x840, 0x00010000,
+	0x844, 0x00000000,
+	0x848, 0x00000000,
+	0x84c, 0x00000000,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569a569a,
+	0x85c, 0x001b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x00000000,
+	0x86c, 0x32323200,
+	0x870, 0x07000700,
+	0x874, 0x22004000,
+	0x878, 0x00000808,
+	0x87c, 0x00000000,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xccc000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121111,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x1a1b0000,
+	0xa24, 0x090e1317,
+	0xa28, 0x00000204,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xc00, 0x48071d40,
+	0xc04, 0x03a05611,
+	0xc08, 0x000000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x6954341e,
+	0xc54, 0x43bc0094,
+	0xc58, 0x6954341e,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c7f000d,
+	0xc74, 0x018610db,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b91612,
+	0xc80, 0x40000100,
+	0xc84, 0x20f60000,
+	0xc88, 0x40000100,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020401,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x2a2a2a2a,
+	0xe04, 0x2a2a2a2a,
+	0xe08, 0x03902a2a,
+	0xe10, 0x2a2a2a2a,
+	0xe14, 0x2a2a2a2a,
+	0xe18, 0x2a2a2a2a,
+	0xe1c, 0x2a2a2a2a,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000008,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x631b25a0,
+	0xe70, 0x631b25a0,
+	0xe74, 0x081b25a0,
+	0xe78, 0x081b25a0,
+	0xe7c, 0x081b25a0,
+	0xe80, 0x081b25a0,
+	0xe84, 0x631b25a0,
+	0xe88, 0x081b25a0,
+	0xe8c, 0x631b25a0,
+	0xed0, 0x631b25a0,
+	0xed4, 0x631b25a0,
+	0xed8, 0x631b25a0,
+	0xedc, 0x001b25a0,
+	0xee0, 0x001b25a0,
+	0xeec, 0x6b1b25a0,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH] = {
+	0xe00, 0xffffffff, 0x07090c0c,
+	0xe04, 0xffffffff, 0x01020405,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x0b0c0c0e,
+	0xe14, 0xffffffff, 0x01030506,
+	0xe18, 0xffffffff, 0x0b0c0d0e,
+	0xe1c, 0xffffffff, 0x01030509,
+	0x830, 0xffffffff, 0x07090c0c,
+	0x834, 0xffffffff, 0x01020405,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x0b0c0d0e,
+	0x848, 0xffffffff, 0x01030509,
+	0x84c, 0xffffffff, 0x0b0c0d0e,
+	0x868, 0xffffffff, 0x01030509,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x06060606,
+	0xe14, 0xffffffff, 0x00020406,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x06060606,
+	0x848, 0xffffffff, 0x00020406,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x04040404,
+	0xe04, 0xffffffff, 0x00020204,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x04040404,
+	0x834, 0xffffffff, 0x00020204,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+};
+
+u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb1,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e52c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00010255,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x00000000,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x000577c0,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287af,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x00014297,
+	0x013, 0x00010295,
+	0x013, 0x0000c298,
+	0x013, 0x0000819c,
+	0x013, 0x000040a8,
+	0x013, 0x0000001c,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x015, 0x000cf424,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb1,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e52c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287af,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x00014297,
+	0x013, 0x00010295,
+	0x013, 0x0000c298,
+	0x013, 0x0000819c,
+	0x013, 0x000040a8,
+	0x013, 0x0000001c,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f424,
+	0x015, 0x0004f424,
+	0x015, 0x0008f424,
+	0x015, 0x000cf424,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+};
+
+u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb1,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e52c,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00010255,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x00000000,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x000577c0,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x00032000,
+	0x012, 0x00071000,
+	0x012, 0x000b0000,
+	0x012, 0x000fc000,
+	0x013, 0x000287b3,
+	0x013, 0x000244b7,
+	0x013, 0x000204ab,
+	0x013, 0x0001c49f,
+	0x013, 0x00018493,
+	0x013, 0x0001429b,
+	0x013, 0x00010299,
+	0x013, 0x0000c29c,
+	0x013, 0x000081a0,
+	0x013, 0x000040ac,
+	0x013, 0x00000020,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f405,
+	0x015, 0x0004f405,
+	0x015, 0x0008f405,
+	0x015, 0x000cf405,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH] = {
+	0x0,
+};
+
+u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH] = {
+	0x420, 0x00000080,
+	0x423, 0x00000000,
+	0x430, 0x00000000,
+	0x431, 0x00000000,
+	0x432, 0x00000000,
+	0x433, 0x00000001,
+	0x434, 0x00000004,
+	0x435, 0x00000005,
+	0x436, 0x00000006,
+	0x437, 0x00000007,
+	0x438, 0x00000000,
+	0x439, 0x00000000,
+	0x43a, 0x00000000,
+	0x43b, 0x00000001,
+	0x43c, 0x00000004,
+	0x43d, 0x00000005,
+	0x43e, 0x00000006,
+	0x43f, 0x00000007,
+	0x440, 0x0000005d,
+	0x441, 0x00000001,
+	0x442, 0x00000000,
+	0x444, 0x00000015,
+	0x445, 0x000000f0,
+	0x446, 0x0000000f,
+	0x447, 0x00000000,
+	0x458, 0x00000041,
+	0x459, 0x000000a8,
+	0x45a, 0x00000072,
+	0x45b, 0x000000b9,
+	0x460, 0x00000066,
+	0x461, 0x00000066,
+	0x462, 0x00000008,
+	0x463, 0x00000003,
+	0x4c8, 0x000000ff,
+	0x4c9, 0x00000008,
+	0x4cc, 0x000000ff,
+	0x4cd, 0x000000ff,
+	0x4ce, 0x00000001,
+	0x500, 0x00000026,
+	0x501, 0x000000a2,
+	0x502, 0x0000002f,
+	0x503, 0x00000000,
+	0x504, 0x00000028,
+	0x505, 0x000000a3,
+	0x506, 0x0000005e,
+	0x507, 0x00000000,
+	0x508, 0x0000002b,
+	0x509, 0x000000a4,
+	0x50a, 0x0000005e,
+	0x50b, 0x00000000,
+	0x50c, 0x0000004f,
+	0x50d, 0x000000a4,
+	0x50e, 0x00000000,
+	0x50f, 0x00000000,
+	0x512, 0x0000001c,
+	0x514, 0x0000000a,
+	0x515, 0x00000010,
+	0x516, 0x0000000a,
+	0x517, 0x00000010,
+	0x51a, 0x00000016,
+	0x524, 0x0000000f,
+	0x525, 0x0000004f,
+	0x546, 0x00000040,
+	0x547, 0x00000000,
+	0x550, 0x00000010,
+	0x551, 0x00000010,
+	0x559, 0x00000002,
+	0x55a, 0x00000002,
+	0x55d, 0x000000ff,
+	0x605, 0x00000030,
+	0x608, 0x0000000e,
+	0x609, 0x0000002a,
+	0x652, 0x00000020,
+	0x63c, 0x0000000a,
+	0x63d, 0x0000000e,
+	0x63e, 0x0000000a,
+	0x63f, 0x0000000e,
+	0x66e, 0x00000005,
+	0x700, 0x00000021,
+	0x701, 0x00000043,
+	0x702, 0x00000065,
+	0x703, 0x00000087,
+	0x708, 0x00000021,
+	0x709, 0x00000043,
+	0x70a, 0x00000065,
+	0x70b, 0x00000087,
+};
+
+u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7a060001,
+	0xc78, 0x79070001,
+	0xc78, 0x78080001,
+	0xc78, 0x77090001,
+	0xc78, 0x760a0001,
+	0xc78, 0x750b0001,
+	0xc78, 0x740c0001,
+	0xc78, 0x730d0001,
+	0xc78, 0x720e0001,
+	0xc78, 0x710f0001,
+	0xc78, 0x70100001,
+	0xc78, 0x6f110001,
+	0xc78, 0x6e120001,
+	0xc78, 0x6d130001,
+	0xc78, 0x6c140001,
+	0xc78, 0x6b150001,
+	0xc78, 0x6a160001,
+	0xc78, 0x69170001,
+	0xc78, 0x68180001,
+	0xc78, 0x67190001,
+	0xc78, 0x661a0001,
+	0xc78, 0x651b0001,
+	0xc78, 0x641c0001,
+	0xc78, 0x631d0001,
+	0xc78, 0x621e0001,
+	0xc78, 0x611f0001,
+	0xc78, 0x60200001,
+	0xc78, 0x49210001,
+	0xc78, 0x48220001,
+	0xc78, 0x47230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7a460001,
+	0xc78, 0x79470001,
+	0xc78, 0x78480001,
+	0xc78, 0x77490001,
+	0xc78, 0x764a0001,
+	0xc78, 0x754b0001,
+	0xc78, 0x744c0001,
+	0xc78, 0x734d0001,
+	0xc78, 0x724e0001,
+	0xc78, 0x714f0001,
+	0xc78, 0x70500001,
+	0xc78, 0x6f510001,
+	0xc78, 0x6e520001,
+	0xc78, 0x6d530001,
+	0xc78, 0x6c540001,
+	0xc78, 0x6b550001,
+	0xc78, 0x6a560001,
+	0xc78, 0x69570001,
+	0xc78, 0x68580001,
+	0xc78, 0x67590001,
+	0xc78, 0x665a0001,
+	0xc78, 0x655b0001,
+	0xc78, 0x645c0001,
+	0xc78, 0x635d0001,
+	0xc78, 0x625e0001,
+	0xc78, 0x615f0001,
+	0xc78, 0x60600001,
+	0xc78, 0x49610001,
+	0xc78, 0x48620001,
+	0xc78, 0x47630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
+
+u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7a060001,
+	0xc78, 0x79070001,
+	0xc78, 0x78080001,
+	0xc78, 0x77090001,
+	0xc78, 0x760a0001,
+	0xc78, 0x750b0001,
+	0xc78, 0x740c0001,
+	0xc78, 0x730d0001,
+	0xc78, 0x720e0001,
+	0xc78, 0x710f0001,
+	0xc78, 0x70100001,
+	0xc78, 0x6f110001,
+	0xc78, 0x6e120001,
+	0xc78, 0x6d130001,
+	0xc78, 0x6c140001,
+	0xc78, 0x6b150001,
+	0xc78, 0x6a160001,
+	0xc78, 0x69170001,
+	0xc78, 0x68180001,
+	0xc78, 0x67190001,
+	0xc78, 0x661a0001,
+	0xc78, 0x651b0001,
+	0xc78, 0x641c0001,
+	0xc78, 0x631d0001,
+	0xc78, 0x621e0001,
+	0xc78, 0x611f0001,
+	0xc78, 0x60200001,
+	0xc78, 0x49210001,
+	0xc78, 0x48220001,
+	0xc78, 0x47230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7a460001,
+	0xc78, 0x79470001,
+	0xc78, 0x78480001,
+	0xc78, 0x77490001,
+	0xc78, 0x764a0001,
+	0xc78, 0x754b0001,
+	0xc78, 0x744c0001,
+	0xc78, 0x734d0001,
+	0xc78, 0x724e0001,
+	0xc78, 0x714f0001,
+	0xc78, 0x70500001,
+	0xc78, 0x6f510001,
+	0xc78, 0x6e520001,
+	0xc78, 0x6d530001,
+	0xc78, 0x6c540001,
+	0xc78, 0x6b550001,
+	0xc78, 0x6a560001,
+	0xc78, 0x69570001,
+	0xc78, 0x68580001,
+	0xc78, 0x67590001,
+	0xc78, 0x665a0001,
+	0xc78, 0x655b0001,
+	0xc78, 0x645c0001,
+	0xc78, 0x635d0001,
+	0xc78, 0x625e0001,
+	0xc78, 0x615f0001,
+	0xc78, 0x60600001,
+	0xc78, 0x49610001,
+	0xc78, 0x48620001,
+	0xc78, 0x47630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
+
+u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength] = {
+	0x024, 0x0011800f,
+	0x028, 0x00ffdb83,
+	0x040, 0x000c0004,
+	0x800, 0x80040000,
+	0x804, 0x00000001,
+	0x808, 0x0000fc00,
+	0x80c, 0x0000000a,
+	0x810, 0x10005388,
+	0x814, 0x020c3d10,
+	0x818, 0x02200385,
+	0x81c, 0x00000000,
+	0x820, 0x01000100,
+	0x824, 0x00390204,
+	0x828, 0x00000000,
+	0x82c, 0x00000000,
+	0x830, 0x00000000,
+	0x834, 0x00000000,
+	0x838, 0x00000000,
+	0x83c, 0x00000000,
+	0x840, 0x00010000,
+	0x844, 0x00000000,
+	0x848, 0x00000000,
+	0x84c, 0x00000000,
+	0x850, 0x00000000,
+	0x854, 0x00000000,
+	0x858, 0x569a569a,
+	0x85c, 0x001b25a4,
+	0x860, 0x66e60230,
+	0x864, 0x061f0130,
+	0x868, 0x00000000,
+	0x86c, 0x20202000,
+	0x870, 0x03000300,
+	0x874, 0x22004000,
+	0x878, 0x00000808,
+	0x87c, 0x00ffc3f1,
+	0x880, 0xc0083070,
+	0x884, 0x000004d5,
+	0x888, 0x00000000,
+	0x88c, 0xccc000c0,
+	0x890, 0x00000800,
+	0x894, 0xfffffffe,
+	0x898, 0x40302010,
+	0x89c, 0x00706050,
+	0x900, 0x00000000,
+	0x904, 0x00000023,
+	0x908, 0x00000000,
+	0x90c, 0x81121111,
+	0xa00, 0x00d047c8,
+	0xa04, 0x80ff000c,
+	0xa08, 0x8c838300,
+	0xa0c, 0x2e68120f,
+	0xa10, 0x9500bb78,
+	0xa14, 0x11144028,
+	0xa18, 0x00881117,
+	0xa1c, 0x89140f00,
+	0xa20, 0x15160000,
+	0xa24, 0x070b0f12,
+	0xa28, 0x00000104,
+	0xa2c, 0x00d30000,
+	0xa70, 0x101fbf00,
+	0xa74, 0x00000007,
+	0xc00, 0x48071d40,
+	0xc04, 0x03a05611,
+	0xc08, 0x000000e4,
+	0xc0c, 0x6c6c6c6c,
+	0xc10, 0x08800000,
+	0xc14, 0x40000100,
+	0xc18, 0x08800000,
+	0xc1c, 0x40000100,
+	0xc20, 0x00000000,
+	0xc24, 0x00000000,
+	0xc28, 0x00000000,
+	0xc2c, 0x00000000,
+	0xc30, 0x69e9ac44,
+	0xc34, 0x469652cf,
+	0xc38, 0x49795994,
+	0xc3c, 0x0a97971c,
+	0xc40, 0x1f7c403f,
+	0xc44, 0x000100b7,
+	0xc48, 0xec020107,
+	0xc4c, 0x007f037f,
+	0xc50, 0x6954342e,
+	0xc54, 0x43bc0094,
+	0xc58, 0x6954342f,
+	0xc5c, 0x433c0094,
+	0xc60, 0x00000000,
+	0xc64, 0x5116848b,
+	0xc68, 0x47c00bff,
+	0xc6c, 0x00000036,
+	0xc70, 0x2c46000d,
+	0xc74, 0x018610db,
+	0xc78, 0x0000001f,
+	0xc7c, 0x00b91612,
+	0xc80, 0x24000090,
+	0xc84, 0x20f60000,
+	0xc88, 0x24000090,
+	0xc8c, 0x20200000,
+	0xc90, 0x00121820,
+	0xc94, 0x00000000,
+	0xc98, 0x00121820,
+	0xc9c, 0x00007f7f,
+	0xca0, 0x00000000,
+	0xca4, 0x00000080,
+	0xca8, 0x00000000,
+	0xcac, 0x00000000,
+	0xcb0, 0x00000000,
+	0xcb4, 0x00000000,
+	0xcb8, 0x00000000,
+	0xcbc, 0x28000000,
+	0xcc0, 0x00000000,
+	0xcc4, 0x00000000,
+	0xcc8, 0x00000000,
+	0xccc, 0x00000000,
+	0xcd0, 0x00000000,
+	0xcd4, 0x00000000,
+	0xcd8, 0x64b22427,
+	0xcdc, 0x00766932,
+	0xce0, 0x00222222,
+	0xce4, 0x00000000,
+	0xce8, 0x37644302,
+	0xcec, 0x2f97d40c,
+	0xd00, 0x00080740,
+	0xd04, 0x00020401,
+	0xd08, 0x0000907f,
+	0xd0c, 0x20010201,
+	0xd10, 0xa0633333,
+	0xd14, 0x3333bc43,
+	0xd18, 0x7a8f5b6b,
+	0xd2c, 0xcc979975,
+	0xd30, 0x00000000,
+	0xd34, 0x80608000,
+	0xd38, 0x00000000,
+	0xd3c, 0x00027293,
+	0xd40, 0x00000000,
+	0xd44, 0x00000000,
+	0xd48, 0x00000000,
+	0xd4c, 0x00000000,
+	0xd50, 0x6437140a,
+	0xd54, 0x00000000,
+	0xd58, 0x00000000,
+	0xd5c, 0x30032064,
+	0xd60, 0x4653de68,
+	0xd64, 0x04518a3c,
+	0xd68, 0x00002101,
+	0xd6c, 0x2a201c16,
+	0xd70, 0x1812362e,
+	0xd74, 0x322c2220,
+	0xd78, 0x000e3c24,
+	0xe00, 0x24242424,
+	0xe04, 0x24242424,
+	0xe08, 0x03902024,
+	0xe10, 0x24242424,
+	0xe14, 0x24242424,
+	0xe18, 0x24242424,
+	0xe1c, 0x24242424,
+	0xe28, 0x00000000,
+	0xe30, 0x1000dc1f,
+	0xe34, 0x10008c1f,
+	0xe38, 0x02140102,
+	0xe3c, 0x681604c2,
+	0xe40, 0x01007c00,
+	0xe44, 0x01004800,
+	0xe48, 0xfb000000,
+	0xe4c, 0x000028d1,
+	0xe50, 0x1000dc1f,
+	0xe54, 0x10008c1f,
+	0xe58, 0x02140102,
+	0xe5c, 0x28160d05,
+	0xe60, 0x00000008,
+	0xe68, 0x001b25a4,
+	0xe6c, 0x631b25a0,
+	0xe70, 0x631b25a0,
+	0xe74, 0x081b25a0,
+	0xe78, 0x081b25a0,
+	0xe7c, 0x081b25a0,
+	0xe80, 0x081b25a0,
+	0xe84, 0x631b25a0,
+	0xe88, 0x081b25a0,
+	0xe8c, 0x631b25a0,
+	0xed0, 0x631b25a0,
+	0xed4, 0x631b25a0,
+	0xed8, 0x631b25a0,
+	0xedc, 0x001b25a0,
+	0xee0, 0x001b25a0,
+	0xeec, 0x6b1b25a0,
+	0xee8, 0x31555448,
+	0xf14, 0x00000003,
+	0xf4c, 0x00000000,
+	0xf00, 0x00000300,
+};
+
+u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength] = {
+	0xe00, 0xffffffff, 0x06080808,
+	0xe04, 0xffffffff, 0x00040406,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x04060608,
+	0xe14, 0xffffffff, 0x00020204,
+	0xe18, 0xffffffff, 0x04060608,
+	0xe1c, 0xffffffff, 0x00020204,
+	0x830, 0xffffffff, 0x06080808,
+	0x834, 0xffffffff, 0x00040406,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x04060608,
+	0x848, 0xffffffff, 0x00020204,
+	0x84c, 0xffffffff, 0x04060608,
+	0x868, 0xffffffff, 0x00020204,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+	0xe00, 0xffffffff, 0x00000000,
+	0xe04, 0xffffffff, 0x00000000,
+	0xe08, 0x0000ff00, 0x00000000,
+	0x86c, 0xffffff00, 0x00000000,
+	0xe10, 0xffffffff, 0x00000000,
+	0xe14, 0xffffffff, 0x00000000,
+	0xe18, 0xffffffff, 0x00000000,
+	0xe1c, 0xffffffff, 0x00000000,
+	0x830, 0xffffffff, 0x00000000,
+	0x834, 0xffffffff, 0x00000000,
+	0x838, 0xffffff00, 0x00000000,
+	0x86c, 0x000000ff, 0x00000000,
+	0x83c, 0xffffffff, 0x00000000,
+	0x848, 0xffffffff, 0x00000000,
+	0x84c, 0xffffffff, 0x00000000,
+	0x868, 0xffffffff, 0x00000000,
+};
+
+u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength] = {
+	0x000, 0x00030159,
+	0x001, 0x00031284,
+	0x002, 0x00098000,
+	0x003, 0x00018c63,
+	0x004, 0x000210e7,
+	0x009, 0x0002044f,
+	0x00a, 0x0001adb0,
+	0x00b, 0x00054867,
+	0x00c, 0x0008992e,
+	0x00d, 0x0000e529,
+	0x00e, 0x00039ce7,
+	0x00f, 0x00000451,
+	0x019, 0x00000000,
+	0x01a, 0x00000255,
+	0x01b, 0x00060a00,
+	0x01c, 0x000fc378,
+	0x01d, 0x000a1250,
+	0x01e, 0x0004445f,
+	0x01f, 0x00080001,
+	0x020, 0x0000b614,
+	0x021, 0x0006c000,
+	0x022, 0x0000083c,
+	0x023, 0x00001558,
+	0x024, 0x00000060,
+	0x025, 0x00000483,
+	0x026, 0x0004f000,
+	0x027, 0x000ec7d9,
+	0x028, 0x000977c0,
+	0x029, 0x00004783,
+	0x02a, 0x00000001,
+	0x02b, 0x00021334,
+	0x02a, 0x00000000,
+	0x02b, 0x00000054,
+	0x02a, 0x00000001,
+	0x02b, 0x00000808,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000c,
+	0x02a, 0x00000002,
+	0x02b, 0x00000808,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000003,
+	0x02b, 0x00000808,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000004,
+	0x02b, 0x00000808,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000005,
+	0x02b, 0x00000808,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000006,
+	0x02b, 0x00000709,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000007,
+	0x02b, 0x00000709,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000008,
+	0x02b, 0x0000060a,
+	0x02b, 0x0004b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x00000009,
+	0x02b, 0x0000060a,
+	0x02b, 0x00053333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000a,
+	0x02b, 0x0000060a,
+	0x02b, 0x0005b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000b,
+	0x02b, 0x0000060a,
+	0x02b, 0x00063333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000c,
+	0x02b, 0x0000060a,
+	0x02b, 0x0006b333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000d,
+	0x02b, 0x0000060a,
+	0x02b, 0x00073333,
+	0x02c, 0x0000000d,
+	0x02a, 0x0000000e,
+	0x02b, 0x0000050b,
+	0x02b, 0x00066666,
+	0x02c, 0x0000001a,
+	0x02a, 0x000e0000,
+	0x010, 0x0004000f,
+	0x011, 0x000e31fc,
+	0x010, 0x0006000f,
+	0x011, 0x000ff9f8,
+	0x010, 0x0002000f,
+	0x011, 0x000203f9,
+	0x010, 0x0003000f,
+	0x011, 0x000ff500,
+	0x010, 0x00000000,
+	0x011, 0x00000000,
+	0x010, 0x0008000f,
+	0x011, 0x0003f100,
+	0x010, 0x0009000f,
+	0x011, 0x00023100,
+	0x012, 0x000d8000,
+	0x012, 0x00090000,
+	0x012, 0x00051000,
+	0x012, 0x00012000,
+	0x013, 0x00028fb4,
+	0x013, 0x00024fa8,
+	0x013, 0x000207a4,
+	0x013, 0x0001c798,
+	0x013, 0x000183a4,
+	0x013, 0x00014398,
+	0x013, 0x000101a4,
+	0x013, 0x0000c198,
+	0x013, 0x000080a4,
+	0x013, 0x00004098,
+	0x013, 0x00000000,
+	0x014, 0x0001944c,
+	0x014, 0x00059444,
+	0x014, 0x0009944c,
+	0x014, 0x000d9444,
+	0x015, 0x0000f405,
+	0x015, 0x0004f405,
+	0x015, 0x0008f405,
+	0x015, 0x000cf405,
+	0x016, 0x000e0330,
+	0x016, 0x000a0330,
+	0x016, 0x00060330,
+	0x016, 0x00020330,
+	0x000, 0x00010159,
+	0x018, 0x0000f401,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01f, 0x00080003,
+	0x0fe, 0x00000000,
+	0x0fe, 0x00000000,
+	0x01e, 0x00044457,
+	0x01f, 0x00080000,
+	0x000, 0x00030159,
+};
+
+u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength] = {
+	0xc78, 0x7b000001,
+	0xc78, 0x7b010001,
+	0xc78, 0x7b020001,
+	0xc78, 0x7b030001,
+	0xc78, 0x7b040001,
+	0xc78, 0x7b050001,
+	0xc78, 0x7b060001,
+	0xc78, 0x7b070001,
+	0xc78, 0x7b080001,
+	0xc78, 0x7a090001,
+	0xc78, 0x790a0001,
+	0xc78, 0x780b0001,
+	0xc78, 0x770c0001,
+	0xc78, 0x760d0001,
+	0xc78, 0x750e0001,
+	0xc78, 0x740f0001,
+	0xc78, 0x73100001,
+	0xc78, 0x72110001,
+	0xc78, 0x71120001,
+	0xc78, 0x70130001,
+	0xc78, 0x6f140001,
+	0xc78, 0x6e150001,
+	0xc78, 0x6d160001,
+	0xc78, 0x6c170001,
+	0xc78, 0x6b180001,
+	0xc78, 0x6a190001,
+	0xc78, 0x691a0001,
+	0xc78, 0x681b0001,
+	0xc78, 0x671c0001,
+	0xc78, 0x661d0001,
+	0xc78, 0x651e0001,
+	0xc78, 0x641f0001,
+	0xc78, 0x63200001,
+	0xc78, 0x62210001,
+	0xc78, 0x61220001,
+	0xc78, 0x60230001,
+	0xc78, 0x46240001,
+	0xc78, 0x45250001,
+	0xc78, 0x44260001,
+	0xc78, 0x43270001,
+	0xc78, 0x42280001,
+	0xc78, 0x41290001,
+	0xc78, 0x402a0001,
+	0xc78, 0x262b0001,
+	0xc78, 0x252c0001,
+	0xc78, 0x242d0001,
+	0xc78, 0x232e0001,
+	0xc78, 0x222f0001,
+	0xc78, 0x21300001,
+	0xc78, 0x20310001,
+	0xc78, 0x06320001,
+	0xc78, 0x05330001,
+	0xc78, 0x04340001,
+	0xc78, 0x03350001,
+	0xc78, 0x02360001,
+	0xc78, 0x01370001,
+	0xc78, 0x00380001,
+	0xc78, 0x00390001,
+	0xc78, 0x003a0001,
+	0xc78, 0x003b0001,
+	0xc78, 0x003c0001,
+	0xc78, 0x003d0001,
+	0xc78, 0x003e0001,
+	0xc78, 0x003f0001,
+	0xc78, 0x7b400001,
+	0xc78, 0x7b410001,
+	0xc78, 0x7b420001,
+	0xc78, 0x7b430001,
+	0xc78, 0x7b440001,
+	0xc78, 0x7b450001,
+	0xc78, 0x7b460001,
+	0xc78, 0x7b470001,
+	0xc78, 0x7b480001,
+	0xc78, 0x7a490001,
+	0xc78, 0x794a0001,
+	0xc78, 0x784b0001,
+	0xc78, 0x774c0001,
+	0xc78, 0x764d0001,
+	0xc78, 0x754e0001,
+	0xc78, 0x744f0001,
+	0xc78, 0x73500001,
+	0xc78, 0x72510001,
+	0xc78, 0x71520001,
+	0xc78, 0x70530001,
+	0xc78, 0x6f540001,
+	0xc78, 0x6e550001,
+	0xc78, 0x6d560001,
+	0xc78, 0x6c570001,
+	0xc78, 0x6b580001,
+	0xc78, 0x6a590001,
+	0xc78, 0x695a0001,
+	0xc78, 0x685b0001,
+	0xc78, 0x675c0001,
+	0xc78, 0x665d0001,
+	0xc78, 0x655e0001,
+	0xc78, 0x645f0001,
+	0xc78, 0x63600001,
+	0xc78, 0x62610001,
+	0xc78, 0x61620001,
+	0xc78, 0x60630001,
+	0xc78, 0x46640001,
+	0xc78, 0x45650001,
+	0xc78, 0x44660001,
+	0xc78, 0x43670001,
+	0xc78, 0x42680001,
+	0xc78, 0x41690001,
+	0xc78, 0x406a0001,
+	0xc78, 0x266b0001,
+	0xc78, 0x256c0001,
+	0xc78, 0x246d0001,
+	0xc78, 0x236e0001,
+	0xc78, 0x226f0001,
+	0xc78, 0x21700001,
+	0xc78, 0x20710001,
+	0xc78, 0x06720001,
+	0xc78, 0x05730001,
+	0xc78, 0x04740001,
+	0xc78, 0x03750001,
+	0xc78, 0x02760001,
+	0xc78, 0x01770001,
+	0xc78, 0x00780001,
+	0xc78, 0x00790001,
+	0xc78, 0x007a0001,
+	0xc78, 0x007b0001,
+	0xc78, 0x007c0001,
+	0xc78, 0x007d0001,
+	0xc78, 0x007e0001,
+	0xc78, 0x007f0001,
+	0xc78, 0x3800001e,
+	0xc78, 0x3801001e,
+	0xc78, 0x3802001e,
+	0xc78, 0x3803001e,
+	0xc78, 0x3804001e,
+	0xc78, 0x3805001e,
+	0xc78, 0x3806001e,
+	0xc78, 0x3807001e,
+	0xc78, 0x3808001e,
+	0xc78, 0x3c09001e,
+	0xc78, 0x3e0a001e,
+	0xc78, 0x400b001e,
+	0xc78, 0x440c001e,
+	0xc78, 0x480d001e,
+	0xc78, 0x4c0e001e,
+	0xc78, 0x500f001e,
+	0xc78, 0x5210001e,
+	0xc78, 0x5611001e,
+	0xc78, 0x5a12001e,
+	0xc78, 0x5e13001e,
+	0xc78, 0x6014001e,
+	0xc78, 0x6015001e,
+	0xc78, 0x6016001e,
+	0xc78, 0x6217001e,
+	0xc78, 0x6218001e,
+	0xc78, 0x6219001e,
+	0xc78, 0x621a001e,
+	0xc78, 0x621b001e,
+	0xc78, 0x621c001e,
+	0xc78, 0x621d001e,
+	0xc78, 0x621e001e,
+	0xc78, 0x621f001e,
+};
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/table.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,71 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_TABLE__H_
+#define __RTL92CU_TABLE__H_
+
+#include <linux/types.h>
+
+#define RTL8192CUPHY_REG_2TARRAY_LENGTH		374
+extern u32 RTL8192CUPHY_REG_2TARRAY[RTL8192CUPHY_REG_2TARRAY_LENGTH];
+#define RTL8192CUPHY_REG_1TARRAY_LENGTH		374
+extern u32 RTL8192CUPHY_REG_1TARRAY[RTL8192CUPHY_REG_1TARRAY_LENGTH];
+
+#define RTL8192CUPHY_REG_ARRAY_PGLENGTH		336
+extern u32 RTL8192CUPHY_REG_ARRAY_PG[RTL8192CUPHY_REG_ARRAY_PGLENGTH];
+
+#define RTL8192CURADIOA_2TARRAYLENGTH	282
+extern u32 RTL8192CURADIOA_2TARRAY[RTL8192CURADIOA_2TARRAYLENGTH];
+#define RTL8192CURADIOB_2TARRAYLENGTH	78
+extern u32 RTL8192CU_RADIOB_2TARRAY[RTL8192CURADIOB_2TARRAYLENGTH];
+#define RTL8192CURADIOA_1TARRAYLENGTH	282
+extern u32 RTL8192CU_RADIOA_1TARRAY[RTL8192CURADIOA_1TARRAYLENGTH];
+#define RTL8192CURADIOB_1TARRAYLENGTH	1
+extern u32 RTL8192CU_RADIOB_1TARRAY[RTL8192CURADIOB_1TARRAYLENGTH];
+
+#define RTL8192CUMAC_2T_ARRAYLENGTH		172
+extern u32 RTL8192CUMAC_2T_ARRAY[RTL8192CUMAC_2T_ARRAYLENGTH];
+
+#define RTL8192CUAGCTAB_2TARRAYLENGTH	320
+extern u32 RTL8192CUAGCTAB_2TARRAY[RTL8192CUAGCTAB_2TARRAYLENGTH];
+#define RTL8192CUAGCTAB_1TARRAYLENGTH	320
+extern u32 RTL8192CUAGCTAB_1TARRAY[RTL8192CUAGCTAB_1TARRAYLENGTH];
+
+#define RTL8192CUPHY_REG_1T_HPArrayLength 378
+extern u32 RTL8192CUPHY_REG_1T_HPArray[RTL8192CUPHY_REG_1T_HPArrayLength];
+
+#define RTL8192CUPHY_REG_Array_PG_HPLength 336
+extern u32 RTL8192CUPHY_REG_Array_PG_HP[RTL8192CUPHY_REG_Array_PG_HPLength];
+
+#define RTL8192CURadioA_1T_HPArrayLength 282
+extern u32 RTL8192CURadioA_1T_HPArray[RTL8192CURadioA_1T_HPArrayLength];
+#define RTL8192CUAGCTAB_1T_HPArrayLength 320
+extern u32 Rtl8192CUAGCTAB_1T_HPArray[RTL8192CUAGCTAB_1T_HPArrayLength];
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,687 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#include "../wifi.h"
+#include "../usb.h"
+#include "../ps.h"
+#include "../base.h"
+#include "reg.h"
+#include "def.h"
+#include "phy.h"
+#include "rf.h"
+#include "dm.h"
+#include "mac.h"
+#include "trx.h"
+
+static int _ConfigVerTOutEP(struct ieee80211_hw *hw)
+{
+	u8 ep_cfg, txqsele;
+	u8 ep_nums = 0;
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+
+	rtlusb->out_queue_sel = 0;
+	ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL);
+	ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT;
+	switch (ep_cfg)	{
+	case 0:		/* 2 bulk OUT, 1 bulk IN */
+	case 3:
+		rtlusb->out_queue_sel  = TX_SELE_HQ | TX_SELE_LQ;
+		ep_nums = 2;
+		break;
+	case 1:	/* 1 bulk IN/OUT => map all endpoint to Low queue */
+	case 2:	/* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */
+		txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS);
+		if (txqsele & 0x0F) /* /map all endpoint to High queue */
+			rtlusb->out_queue_sel =  TX_SELE_HQ;
+		else if (txqsele&0xF0) /* map all endpoint to Low queue */
+			rtlusb->out_queue_sel =  TX_SELE_LQ;
+		ep_nums = 1;
+		break;
+	default:
+		break;
+	}
+	return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
+}
+
+static int _ConfigVerNOutEP(struct ieee80211_hw *hw)
+{
+	u8 ep_cfg;
+	u8 ep_nums = 0;
+
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+
+	rtlusb->out_queue_sel = 0;
+	/* Normal and High queue */
+	ep_cfg =  rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1));
+	if (ep_cfg & USB_NORMAL_SIE_EP_MASK) {
+		rtlusb->out_queue_sel |= TX_SELE_HQ;
+		ep_nums++;
+	}
+	if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) {
+		rtlusb->out_queue_sel |= TX_SELE_NQ;
+		ep_nums++;
+	}
+	/* Low queue */
+	ep_cfg =  rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2));
+	if (ep_cfg & USB_NORMAL_SIE_EP_MASK) {
+		rtlusb->out_queue_sel |= TX_SELE_LQ;
+		ep_nums++;
+	}
+	return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
+}
+
+static void _TwoOutEpMapping(struct ieee80211_hw *hw, bool bIsChipB,
+			     bool  bwificfg, struct rtl_ep_map *ep_map)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (bwificfg) { /* for WMM */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB Chip-B & WMM Setting.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VO] = 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	} else { /* typical setting */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB typical Setting.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	}
+}
+
+static void _ThreeOutEpMapping(struct ieee80211_hw *hw, bool  bwificfg,
+			       struct rtl_ep_map *ep_map)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	if (bwificfg) { /* for WMM */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB 3EP Setting for WMM.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 5;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	} else { /* typical setting */
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB 3EP Setting for typical.....\n"));
+		ep_map->ep_mapping[RTL_TXQ_BE]	= 5;
+		ep_map->ep_mapping[RTL_TXQ_BK]	= 5;
+		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
+		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
+		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+	}
+}
+
+static void _OneOutEpMapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
+{
+	ep_map->ep_mapping[RTL_TXQ_BE]	= 2;
+	ep_map->ep_mapping[RTL_TXQ_BK]	= 2;
+	ep_map->ep_mapping[RTL_TXQ_VI]	= 2;
+	ep_map->ep_mapping[RTL_TXQ_VO] = 2;
+	ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
+	ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
+	ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
+}
+static int _out_ep_mapping(struct ieee80211_hw *hw)
+{
+	int err = 0;
+	bool bIsChipN, bwificfg = false;
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+	struct rtl_ep_map *ep_map = &(rtlusb->ep_map);
+
+	bIsChipN = IS_NORMAL_CHIP(rtlhal->version);
+	switch (rtlusb->out_ep_nums) {
+	case 2:
+		_TwoOutEpMapping(hw, bIsChipN, bwificfg, ep_map);
+		break;
+	case 3:
+		/* Test chip doesn't support three out EPs. */
+		if (!bIsChipN) {
+			err  =  -EINVAL;
+			goto err_out;
+		}
+		_ThreeOutEpMapping(hw, bIsChipN, ep_map);
+		break;
+	case 1:
+		_OneOutEpMapping(hw, ep_map);
+		break;
+	default:
+		err  =  -EINVAL;
+		break;
+	}
+err_out:
+	return err;
+
+}
+/* endpoint mapping */
+int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw)
+{
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	int error = 0;
+	if (likely(IS_NORMAL_CHIP(rtlhal->version)))
+		error = _ConfigVerNOutEP(hw);
+	else
+		error = _ConfigVerTOutEP(hw);
+	if (error)
+		goto err_out;
+	error = _out_ep_mapping(hw);
+	if (error)
+		goto err_out;
+err_out:
+	return error;
+}
+
+u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index)
+{
+	u16 hw_queue_index;
+
+	if (unlikely(ieee80211_is_beacon(fc))) {
+		hw_queue_index = RTL_TXQ_BCN;
+		goto out;
+	}
+	if (ieee80211_is_mgmt(fc)) {
+		hw_queue_index = RTL_TXQ_MGT;
+		goto out;
+	}
+	switch (mac80211_queue_index) {
+	case 0:
+		hw_queue_index = RTL_TXQ_VO;
+		break;
+	case 1:
+		hw_queue_index = RTL_TXQ_VI;
+		break;
+	case 2:
+		hw_queue_index = RTL_TXQ_BE;
+		break;
+	case 3:
+		hw_queue_index = RTL_TXQ_BK;
+		break;
+	default:
+		hw_queue_index = RTL_TXQ_BE;
+		RT_ASSERT(false, ("QSLT_BE queue, skb_queue:%d\n",
+			  mac80211_queue_index));
+		break;
+	}
+out:
+	return hw_queue_index;
+}
+
+static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw,
+					 __le16 fc, u16 mac80211_queue_index)
+{
+	enum rtl_desc_qsel qsel;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	if (unlikely(ieee80211_is_beacon(fc))) {
+		qsel = QSLT_BEACON;
+		goto out;
+	}
+	if (ieee80211_is_mgmt(fc)) {
+		qsel = QSLT_MGNT;
+		goto out;
+	}
+	switch (mac80211_queue_index) {
+	case 0:	/* VO */
+		qsel = QSLT_VO;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("VO queue, set qsel = 0x%x\n", QSLT_VO));
+		break;
+	case 1:	/* VI */
+		qsel = QSLT_VI;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("VI queue, set qsel = 0x%x\n", QSLT_VI));
+		break;
+	case 3:	/* BK */
+		qsel = QSLT_BK;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("BK queue, set qsel = 0x%x\n", QSLT_BK));
+		break;
+	case 2:	/* BE */
+	default:
+		qsel = QSLT_BE;
+		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
+			 ("BE queue, set qsel = 0x%x\n", QSLT_BE));
+		break;
+	}
+out:
+	return qsel;
+}
+
+/* =============================================================== */
+
+/*----------------------------------------------------------------------
+ *
+ *	Rx handler
+ *
+ *---------------------------------------------------------------------- */
+bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *stats,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *p_desc, struct sk_buff *skb)
+{
+	struct rx_fwinfo_92c *p_drvinfo;
+	struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
+	u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc);
+
+	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
+	stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) *
+				 RX_DRV_INFO_SIZE_UNIT;
+	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
+	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
+	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
+	stats->hwerror = (stats->crc | stats->icv);
+	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
+	stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc);
+	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
+	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
+	stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
+				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
+	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
+	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+	if (GET_RX_DESC_CRC32(pdesc))
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+	if (!GET_RX_DESC_SWDEC(pdesc))
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	if (GET_RX_DESC_BW(pdesc))
+		rx_status->flag |= RX_FLAG_40MHZ;
+	if (GET_RX_DESC_RX_HT(pdesc))
+		rx_status->flag |= RX_FLAG_HT;
+	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
+	if (stats->decrypted)
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	rx_status->rate_idx = _rtl92c_rate_mapping(hw,
+						(bool)GET_RX_DESC_RX_HT(pdesc),
+						(u8)GET_RX_DESC_RX_MCS(pdesc),
+						(bool)GET_RX_DESC_PAGGR(pdesc));
+	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
+	if (phystatus == true) {
+		p_drvinfo = (struct rx_fwinfo_92c *)(pdesc + RTL_RX_DESC_SIZE);
+		rtl92c_translate_rx_signal_stuff(hw, skb, stats, pdesc,
+						 p_drvinfo);
+	}
+	/*rx_status->qual = stats->signal; */
+	rx_status->signal = stats->rssi + 10;
+	/*rx_status->noise = -stats->noise; */
+	return true;
+}
+
+#define RTL_RX_DRV_INFO_UNIT		8
+
+static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct ieee80211_rx_status *rx_status =
+		 (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb);
+	u32 skb_len, pkt_len, drvinfo_len;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *rxdesc;
+	struct rtl_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+	};
+	struct rx_fwinfo_92c *p_drvinfo;
+	bool bv;
+	__le16 fc;
+	struct ieee80211_hdr *hdr;
+
+	memset(rx_status, 0, sizeof(rx_status));
+	rxdesc	= skb->data;
+	skb_len	= skb->len;
+	drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT);
+	pkt_len		= GET_RX_DESC_PKT_LEN(rxdesc);
+	/* TODO: Error recovery. drop this skb or something. */
+	WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len));
+	stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc);
+	stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) *
+				RX_DRV_INFO_SIZE_UNIT;
+	stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03);
+	stats.icv = (u16) GET_RX_DESC_ICV(rxdesc);
+	stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc);
+	stats.hwerror = (stats.crc | stats.icv);
+	stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc);
+	stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc);
+	stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc);
+	stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1)
+				   && (GET_RX_DESC_FAGGR(rxdesc) == 1));
+	stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc);
+	stats.rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(rxdesc);
+	/* TODO: is center_freq changed when doing scan? */
+	/* TODO: Shall we add protection or just skip those two step? */
+	rx_status->freq = hw->conf.channel->center_freq;
+	rx_status->band = hw->conf.channel->band;
+	if (GET_RX_DESC_CRC32(rxdesc))
+		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
+	if (!GET_RX_DESC_SWDEC(rxdesc))
+		rx_status->flag |= RX_FLAG_DECRYPTED;
+	if (GET_RX_DESC_BW(rxdesc))
+		rx_status->flag |= RX_FLAG_40MHZ;
+	if (GET_RX_DESC_RX_HT(rxdesc))
+		rx_status->flag |= RX_FLAG_HT;
+	/* Data rate */
+	rx_status->rate_idx = _rtl92c_rate_mapping(hw,
+						(bool)GET_RX_DESC_RX_HT(rxdesc),
+						(u8)GET_RX_DESC_RX_MCS(rxdesc),
+						(bool)GET_RX_DESC_PAGGR(rxdesc)
+						);
+	/*  There is a phy status after this rx descriptor. */
+	if (GET_RX_DESC_PHY_STATUS(rxdesc)) {
+		p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE);
+		rtl92c_translate_rx_signal_stuff(hw, skb, &stats,
+				 (struct rx_desc_92c *)rxdesc, p_drvinfo);
+	}
+	skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE));
+	hdr = (struct ieee80211_hdr *)(skb->data);
+	fc = hdr->frame_control;
+	bv = ieee80211_is_probe_resp(fc);
+	if (bv)
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("Got probe response frame.\n"));
+	if (ieee80211_is_beacon(fc))
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("Got beacon frame.\n"));
+	if (ieee80211_is_data(fc))
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("Got data frame.\n"));
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+		 ("Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:"
+		 "0x%02X\n", fc, (u32)hdr->addr1[0], (u32)hdr->addr1[1],
+		 (u32)hdr->addr1[2], (u32)hdr->addr1[3], (u32)hdr->addr1[4],
+		 (u32)hdr->addr1[5]));
+	memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+	ieee80211_rx_irqsafe(hw, skb);
+}
+
+void  rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb)
+{
+	_rtl_rx_process(hw, skb);
+}
+
+void rtl8192c_rx_segregate_hdl(
+	struct ieee80211_hw *hw,
+	struct sk_buff *skb,
+	struct sk_buff_head *skb_list)
+{
+}
+
+/*----------------------------------------------------------------------
+ *
+ *	Tx handler
+ *
+ *---------------------------------------------------------------------- */
+void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff  *skb)
+{
+}
+
+int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb,
+			 struct sk_buff *skb)
+{
+	return 0;
+}
+
+struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw,
+					   struct sk_buff_head *list)
+{
+	return skb_dequeue(list);
+}
+
+/*======================================== trx ===============================*/
+
+static void _rtl_fill_usb_tx_desc(u8 *txdesc)
+{
+	SET_TX_DESC_OWN(txdesc, 1);
+	SET_TX_DESC_LAST_SEG(txdesc, 1);
+	SET_TX_DESC_FIRST_SEG(txdesc, 1);
+}
+/**
+ *	For HW recovery information
+ */
+static void _rtl_tx_desc_checksum(u8 *txdesc)
+{
+	u16 *ptr = (u16 *)txdesc;
+	u16	checksum = 0;
+	u32 index;
+
+	/* Clear first */
+	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
+	for (index = 0; index < 16; index++)
+		checksum = checksum ^ (*(ptr + index));
+	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
+}
+
+void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info, struct sk_buff *skb,
+			  unsigned int queue_index)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	bool defaultadapter = true;
+	struct ieee80211_sta *sta;
+	struct rtl_tcb_desc tcb_desc;
+	u8 *qc = ieee80211_get_qos_ctl(hdr);
+	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+	u16 seq_number;
+	__le16 fc = hdr->frame_control;
+	u8 rate_flag = info->control.rates[0].flags;
+	u16 pktlen = skb->len;
+	enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc,
+						skb_get_queue_mapping(skb));
+	u8 *txdesc;
+
+	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+	rtl_get_tcb_desc(hw, info, skb, &tcb_desc);
+	txdesc = (u8 *)skb_push(skb, RTL_TX_HEADER_SIZE);
+	memset(txdesc, 0, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_PKT_SIZE(txdesc, pktlen);
+	SET_TX_DESC_LINIP(txdesc, 0);
+	SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET);
+	SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_TX_RATE(txdesc, tcb_desc.hw_rate);
+	if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble)
+		SET_TX_DESC_DATA_SHORTGI(txdesc, 1);
+	if (mac->tids[tid].agg.agg_state == RTL_AGG_ON &&
+		    info->flags & IEEE80211_TX_CTL_AMPDU) {
+		SET_TX_DESC_AGG_ENABLE(txdesc, 1);
+		SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14);
+	} else {
+		SET_TX_DESC_AGG_BREAK(txdesc, 1);
+	}
+	SET_TX_DESC_SEQ(txdesc, seq_number);
+	SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable &&
+			       !tcb_desc.cts_enable) ? 1 : 0));
+	SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc.rts_enable ||
+				  tcb_desc.cts_enable) ? 1 : 0));
+	SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc.cts_enable) ? 1 : 0));
+	SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc.rts_stbc) ? 1 : 0));
+	SET_TX_DESC_RTS_RATE(txdesc, tcb_desc.rts_rate);
+	SET_TX_DESC_RTS_BW(txdesc, 0);
+	SET_TX_DESC_RTS_SC(txdesc, tcb_desc.rts_sc);
+	SET_TX_DESC_RTS_SHORT(txdesc,
+			      ((tcb_desc.rts_rate <= DESC92C_RATE54M) ?
+			       (tcb_desc.rts_use_shortpreamble ? 1 : 0)
+			       : (tcb_desc.rts_use_shortgi ? 1 : 0)));
+	if (mac->bw_40) {
+		if (tcb_desc.packet_bw) {
+			SET_TX_DESC_DATA_BW(txdesc, 1);
+			SET_TX_DESC_DATA_SC(txdesc, 3);
+		} else {
+			SET_TX_DESC_DATA_BW(txdesc, 0);
+				if (rate_flag & IEEE80211_TX_RC_DUP_DATA)
+					SET_TX_DESC_DATA_SC(txdesc,
+							  mac->cur_40_prime_sc);
+			}
+	} else {
+		SET_TX_DESC_DATA_BW(txdesc, 0);
+		SET_TX_DESC_DATA_SC(txdesc, 0);
+	}
+	rcu_read_lock();
+	sta = ieee80211_find_sta(mac->vif, mac->bssid);
+	if (sta) {
+		u8 ampdu_density = sta->ht_cap.ampdu_density;
+		SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density);
+	}
+	rcu_read_unlock();
+	if (info->control.hw_key) {
+		struct ieee80211_key_conf *keyconf = info->control.hw_key;
+		switch (keyconf->cipher) {
+		case WLAN_CIPHER_SUITE_WEP40:
+		case WLAN_CIPHER_SUITE_WEP104:
+		case WLAN_CIPHER_SUITE_TKIP:
+			SET_TX_DESC_SEC_TYPE(txdesc, 0x1);
+			break;
+		case WLAN_CIPHER_SUITE_CCMP:
+			SET_TX_DESC_SEC_TYPE(txdesc, 0x3);
+			break;
+		default:
+			SET_TX_DESC_SEC_TYPE(txdesc, 0x0);
+			break;
+		}
+	}
+	SET_TX_DESC_PKT_ID(txdesc, 0);
+	SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel);
+	SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F);
+	SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF);
+	SET_TX_DESC_DISABLE_FB(txdesc, 0);
+	SET_TX_DESC_USE_RATE(txdesc, tcb_desc.use_driver_rate ? 1 : 0);
+	if (ieee80211_is_data_qos(fc)) {
+		if (mac->rdg_en) {
+			RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
+				 ("Enable RDG function.\n"));
+			SET_TX_DESC_RDG_ENABLE(txdesc, 1);
+			SET_TX_DESC_HTC(txdesc, 1);
+		}
+	}
+	if (rtlpriv->dm.useramask) {
+		SET_TX_DESC_RATE_ID(txdesc, tcb_desc.ratr_index);
+		SET_TX_DESC_MACID(txdesc, tcb_desc.mac_id);
+	} else {
+		SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc.ratr_index);
+		SET_TX_DESC_MACID(txdesc, tcb_desc.ratr_index);
+	}
+	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
+	      ppsc->fwctrl_lps) {
+		SET_TX_DESC_HWSEQ_EN(txdesc, 1);
+		SET_TX_DESC_PKT_ID(txdesc, 8);
+		if (!defaultadapter)
+			SET_TX_DESC_QOS(txdesc, 1);
+	}
+	if (ieee80211_has_morefrags(fc))
+		SET_TX_DESC_MORE_FRAG(txdesc, 1);
+	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
+	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
+		SET_TX_DESC_BMC(txdesc, 1);
+	_rtl_fill_usb_tx_desc(txdesc);
+	_rtl_tx_desc_checksum(txdesc);
+	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, (" %s ==>\n", __func__));
+}
+
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
+			      u32 buffer_len, bool bIsPsPoll)
+{
+	/* Clear all status */
+	memset(pDesc, 0, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_FIRST_SEG(pDesc, 1); /* bFirstSeg; */
+	SET_TX_DESC_LAST_SEG(pDesc, 1); /* bLastSeg; */
+	SET_TX_DESC_OFFSET(pDesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
+	SET_TX_DESC_PKT_SIZE(pDesc, buffer_len); /* Buffer size + command hdr */
+	SET_TX_DESC_QUEUE_SEL(pDesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
+	/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error
+	 * vlaue by Hw. */
+	if (bIsPsPoll) {
+		SET_TX_DESC_NAV_USE_HDR(pDesc, 1);
+	} else {
+		SET_TX_DESC_HWSEQ_EN(pDesc, 1); /* Hw set sequence number */
+		SET_TX_DESC_PKT_ID(pDesc, 0x100); /* set bit3 to 1. */
+	}
+	SET_TX_DESC_USE_RATE(pDesc, 1); /* use data rate which is set by Sw */
+	SET_TX_DESC_OWN(pDesc, 1);
+	SET_TX_DESC_TX_RATE(pDesc, DESC92C_RATE1M);
+	_rtl_tx_desc_checksum(pDesc);
+}
+
+void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
+			     u8 *pdesc, bool firstseg,
+			     bool lastseg, struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 fw_queue = QSLT_BEACON;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+
+	memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
+	if (firstseg)
+		SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE);
+	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
+	SET_TX_DESC_SEQ(pdesc, 0);
+	SET_TX_DESC_LINIP(pdesc, 0);
+	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
+	SET_TX_DESC_FIRST_SEG(pdesc, 1);
+	SET_TX_DESC_LAST_SEG(pdesc, 1);
+	SET_TX_DESC_RATE_ID(pdesc, 7);
+	SET_TX_DESC_MACID(pdesc, 0);
+	SET_TX_DESC_OWN(pdesc, 1);
+	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
+	SET_TX_DESC_FIRST_SEG(pdesc, 1);
+	SET_TX_DESC_LAST_SEG(pdesc, 1);
+	SET_TX_DESC_OFFSET(pdesc, 0x20);
+	SET_TX_DESC_USE_RATE(pdesc, 1);
+	if (!ieee80211_is_data_qos(fc)) {
+		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
+		SET_TX_DESC_PKT_ID(pdesc, 8);
+	}
+	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content\n",
+		      pdesc, RTL_TX_DESC_SIZE);
+}
+
+bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	return true;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/rtl8192cu/trx.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,430 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2010  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ * Larry Finger <Larry.Finger@lwfinger.net>
+ *
+ *****************************************************************************/
+
+#ifndef __RTL92CU_TRX_H__
+#define __RTL92CU_TRX_H__
+
+#define RTL92C_USB_BULK_IN_NUM			1
+#define RTL92C_NUM_RX_URBS			8
+#define RTL92C_NUM_TX_URBS			32
+
+#define RTL92C_SIZE_MAX_RX_BUFFER		15360   /* 8192 */
+#define RX_DRV_INFO_SIZE_UNIT			8
+
+enum usb_rx_agg_mode {
+	USB_RX_AGG_DISABLE,
+	USB_RX_AGG_DMA,
+	USB_RX_AGG_USB,
+	USB_RX_AGG_DMA_USB
+};
+
+#define TX_SELE_HQ				BIT(0)	/* High Queue */
+#define TX_SELE_LQ				BIT(1)	/* Low Queue */
+#define TX_SELE_NQ				BIT(2)	/* Normal Queue */
+
+#define RTL_USB_TX_AGG_NUM_DESC			5
+
+#define RTL_USB_RX_AGG_PAGE_NUM			4
+#define RTL_USB_RX_AGG_PAGE_TIMEOUT		3
+
+#define RTL_USB_RX_AGG_BLOCK_NUM		5
+#define RTL_USB_RX_AGG_BLOCK_TIMEOUT		3
+
+/*======================== rx status =========================================*/
+
+struct rx_drv_info_92c {
+	/*
+	 * Driver info contain PHY status and other variabel size info
+	 * PHY Status content as below
+	 */
+
+	/* DWORD 0 */
+	u8 gain_trsw[4];
+
+	/* DWORD 1 */
+	u8 pwdb_all;
+	u8 cfosho[4];
+
+	/* DWORD 2 */
+	u8 cfotail[4];
+
+	/* DWORD 3 */
+	s8 rxevm[2];
+	s8 rxsnr[4];
+
+	/* DWORD 4 */
+	u8 pdsnr[2];
+
+	/* DWORD 5 */
+	u8 csi_current[2];
+	u8 csi_target[2];
+
+	/* DWORD 6 */
+	u8 sigevm;
+	u8 max_ex_pwr;
+	u8 ex_intf_flag:1;
+	u8 sgi_en:1;
+	u8 rxsc:2;
+	u8 reserve:4;
+} __packed;
+
+/* Define a macro that takes a le32 word, converts it to host ordering,
+ * right shifts by a specified count, creates a mask of the specified
+ * bit count, and extracts that number of bits.
+ */
+
+#define SHIFT_AND_MASK_LE(__pdesc, __shift, __bits)		\
+	((le32_to_cpu(*(((__le32 *)(__pdesc)))) >> (__shift)) &	\
+	BIT_LEN_MASK_32(__bits))
+
+/* Define a macro that clears a bit field in an le32 word and
+ * sets the specified value into that bit field. The resulting
+ * value remains in le32 ordering; however, it is properly converted
+ * to host ordering for the clear and set operations before conversion
+ * back to le32.
+ */
+
+#define SET_BITS_OFFSET_LE(__pdesc, __shift, __len, __val)	\
+	(*(__le32 *)(__pdesc) = 				\
+	(cpu_to_le32((le32_to_cpu(*((__le32 *)(__pdesc))) &	\
+	(~(BIT_OFFSET_LEN_MASK_32((__shift), __len)))) |		\
+	(((u32)(__val) & BIT_LEN_MASK_32(__len)) << (__shift)))));
+
+/* macros to read various fields in RX descriptor */
+
+/* DWORD 0 */
+#define GET_RX_DESC_PKT_LEN(__rxdesc)		\
+	SHIFT_AND_MASK_LE((__rxdesc), 0, 14)
+#define GET_RX_DESC_CRC32(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 14, 1)
+#define GET_RX_DESC_ICV(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 15, 1)
+#define GET_RX_DESC_DRVINFO_SIZE(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc, 16, 4)
+#define GET_RX_DESC_SECURITY(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 20, 3)
+#define GET_RX_DESC_QOS(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 23, 1)
+#define GET_RX_DESC_SHIFT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 24, 2)
+#define GET_RX_DESC_PHY_STATUS(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc, 26, 1)
+#define GET_RX_DESC_SWDEC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 27, 1)
+#define GET_RX_DESC_LAST_SEG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 28, 1)
+#define GET_RX_DESC_FIRST_SEG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 29, 1)
+#define GET_RX_DESC_EOR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 30, 1)
+#define GET_RX_DESC_OWN(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc, 31, 1)
+
+/* DWORD 1 */
+#define GET_RX_DESC_MACID(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 0, 5)
+#define GET_RX_DESC_TID(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 5, 4)
+#define GET_RX_DESC_PAGGR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 14, 1)
+#define GET_RX_DESC_FAGGR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 15, 1)
+#define GET_RX_DESC_A1_FIT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 16, 4)
+#define GET_RX_DESC_A2_FIT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 20, 4)
+#define GET_RX_DESC_PAM(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 24, 1)
+#define GET_RX_DESC_PWR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 25, 1)
+#define GET_RX_DESC_MORE_DATA(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 26, 1)
+#define GET_RX_DESC_MORE_FRAG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 27, 1)
+#define GET_RX_DESC_TYPE(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 28, 2)
+#define GET_RX_DESC_MC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 30, 1)
+#define GET_RX_DESC_BC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+4, 31, 1)
+
+/* DWORD 2 */
+#define GET_RX_DESC_SEQ(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 0, 12)
+#define GET_RX_DESC_FRAG(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 12, 4)
+#define GET_RX_DESC_USB_AGG_PKTNUM(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 16, 8)
+#define GET_RX_DESC_NEXT_IND(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+8, 30, 1)
+
+/* DWORD 3 */
+#define GET_RX_DESC_RX_MCS(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 0, 6)
+#define GET_RX_DESC_RX_HT(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 6, 1)
+#define GET_RX_DESC_AMSDU(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 7, 1)
+#define GET_RX_DESC_SPLCP(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 8, 1)
+#define GET_RX_DESC_BW(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 9, 1)
+#define GET_RX_DESC_HTC(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 10, 1)
+#define GET_RX_DESC_TCP_CHK_RPT(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 11, 1)
+#define GET_RX_DESC_IP_CHK_RPT(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 12, 1)
+#define GET_RX_DESC_TCP_CHK_VALID(__rxdesc)	\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 13, 1)
+#define GET_RX_DESC_HWPC_ERR(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 14, 1)
+#define GET_RX_DESC_HWPC_IND(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 15, 1)
+#define GET_RX_DESC_IV0(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+12, 16, 16)
+
+/* DWORD 4 */
+#define GET_RX_DESC_IV1(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+16, 0, 32)
+
+/* DWORD 5 */
+#define GET_RX_DESC_TSFL(__rxdesc)		\
+	SHIFT_AND_MASK_LE(__rxdesc+20, 0, 32)
+
+/*======================= tx desc ============================================*/
+
+/* macros to set various fields in TX descriptor */
+
+/* Dword 0 */
+#define SET_TX_DESC_PKT_SIZE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 0, 16, __value)
+#define SET_TX_DESC_OFFSET(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 16, 8, __value)
+#define SET_TX_DESC_BMC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 24, 1, __value)
+#define SET_TX_DESC_HTC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 25, 1, __value)
+#define SET_TX_DESC_LAST_SEG(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 26, 1, __value)
+#define SET_TX_DESC_FIRST_SEG(__txdesc, __value)	\
+	 SET_BITS_OFFSET_LE(__txdesc, 27, 1, __value)
+#define SET_TX_DESC_LINIP(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 28, 1, __value)
+#define SET_TX_DESC_NO_ACM(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 29, 1, __value)
+#define SET_TX_DESC_GF(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 30, 1, __value)
+#define SET_TX_DESC_OWN(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc, 31, 1, __value)
+
+
+/* Dword 1 */
+#define SET_TX_DESC_MACID(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 0, 5, __value)
+#define SET_TX_DESC_AGG_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 5, 1, __value)
+#define SET_TX_DESC_AGG_BREAK(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 6, 1, __value)
+#define SET_TX_DESC_RDG_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 7, 1, __value)
+#define SET_TX_DESC_QUEUE_SEL(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 8, 5, __value)
+#define SET_TX_DESC_RDG_NAV_EXT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 13, 1, __value)
+#define SET_TX_DESC_LSIG_TXOP_EN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 14, 1, __value)
+#define SET_TX_DESC_PIFS(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 15, 1, __value)
+#define SET_TX_DESC_RATE_ID(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value)
+#define SET_TX_DESC_RA_BRSR_ID(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 16, 4, __value)
+#define SET_TX_DESC_NAV_USE_HDR(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 20, 1, __value)
+#define SET_TX_DESC_EN_DESC_ID(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 21, 1, __value)
+#define SET_TX_DESC_SEC_TYPE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+4, 22, 2, __value)
+#define SET_TX_DESC_PKT_OFFSET(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+4, 26, 5, __value)
+
+/* Dword 2 */
+#define SET_TX_DESC_RTS_RC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 0, 6, __value)
+#define SET_TX_DESC_DATA_RC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 6, 6, __value)
+#define SET_TX_DESC_BAR_RTY_TH(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 14, 2, __value)
+#define SET_TX_DESC_MORE_FRAG(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 17, 1, __value)
+#define SET_TX_DESC_RAW(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 18, 1, __value)
+#define SET_TX_DESC_CCX(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 19, 1, __value)
+#define SET_TX_DESC_AMPDU_DENSITY(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 20, 3, __value)
+#define SET_TX_DESC_ANTSEL_A(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 24, 1, __value)
+#define SET_TX_DESC_ANTSEL_B(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 25, 1, __value)
+#define SET_TX_DESC_TX_ANT_CCK(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 26, 2, __value)
+#define SET_TX_DESC_TX_ANTL(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+8, 28, 2, __value)
+#define SET_TX_DESC_TX_ANT_HT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+8, 30, 2, __value)
+
+/* Dword 3 */
+#define SET_TX_DESC_NEXT_HEAP_PAGE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+12, 0, 8, __value)
+#define SET_TX_DESC_TAIL_PAGE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+12, 8, 8, __value)
+#define SET_TX_DESC_SEQ(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+12, 16, 12, __value)
+#define SET_TX_DESC_PKT_ID(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+12, 28, 4, __value)
+
+/* Dword 4 */
+#define SET_TX_DESC_RTS_RATE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 0, 5, __value)
+#define SET_TX_DESC_AP_DCFE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 5, 1, __value)
+#define SET_TX_DESC_QOS(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 6, 1, __value)
+#define SET_TX_DESC_HWSEQ_EN(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 7, 1, __value)
+#define SET_TX_DESC_USE_RATE(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 8, 1, __value)
+#define SET_TX_DESC_DISABLE_RTS_FB(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 9, 1, __value)
+#define SET_TX_DESC_DISABLE_FB(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 10, 1, __value)
+#define SET_TX_DESC_CTS2SELF(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 11, 1, __value)
+#define SET_TX_DESC_RTS_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 12, 1, __value)
+#define SET_TX_DESC_HW_RTS_ENABLE(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 13, 1, __value)
+#define SET_TX_DESC_WAIT_DCTS(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 18, 1, __value)
+#define SET_TX_DESC_CTS2AP_EN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 19, 1, __value)
+#define SET_TX_DESC_DATA_SC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 20, 2, __value)
+#define SET_TX_DESC_DATA_STBC(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 22, 2, __value)
+#define SET_TX_DESC_DATA_SHORT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 24, 1, __value)
+#define SET_TX_DESC_DATA_BW(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 25, 1, __value)
+#define SET_TX_DESC_RTS_SHORT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+16, 26, 1, __value)
+#define SET_TX_DESC_RTS_BW(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 27, 1, __value)
+#define SET_TX_DESC_RTS_SC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 28, 2, __value)
+#define SET_TX_DESC_RTS_STBC(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+16, 30, 2, __value)
+
+/* Dword 5 */
+#define SET_TX_DESC_TX_RATE(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+20, 0, 6, __val)
+#define SET_TX_DESC_DATA_SHORTGI(__pdesc, __val)	\
+	SET_BITS_OFFSET_LE(__pdesc+20, 6, 1, __val)
+#define SET_TX_DESC_CCX_TAG(__pdesc, __val)		\
+	SET_BITS_OFFSET_LE(__pdesc+20, 7, 1, __val)
+#define SET_TX_DESC_DATA_RATE_FB_LIMIT(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+20, 8, 5, __value)
+#define SET_TX_DESC_RTS_RATE_FB_LIMIT(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+20, 13, 4, __value)
+#define SET_TX_DESC_RETRY_LIMIT_ENABLE(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+20, 17, 1, __value)
+#define SET_TX_DESC_DATA_RETRY_LIMIT(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+20, 18, 6, __value)
+#define SET_TX_DESC_USB_TXAGG_NUM(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+20, 24, 8, __value)
+
+/* Dword 6 */
+#define SET_TX_DESC_TXAGC_A(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+24, 0, 5, __value)
+#define SET_TX_DESC_TXAGC_B(__txdesc, __value)		\
+	SET_BITS_OFFSET_LE(__txdesc+24, 5, 5, __value)
+#define SET_TX_DESC_USB_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 10, 1, __value)
+#define SET_TX_DESC_MAX_AGG_NUM(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 11, 5, __value)
+#define SET_TX_DESC_MCSG1_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 16, 4, __value)
+#define SET_TX_DESC_MCSG2_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 20, 4, __value)
+#define SET_TX_DESC_MCSG3_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 24, 4, __value)
+#define SET_TX_DESC_MCSG7_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+24, 28, 4, __value)
+
+/* Dword 7 */
+#define SET_TX_DESC_TX_DESC_CHECKSUM(__txdesc, __value) \
+	SET_BITS_OFFSET_LE(__txdesc+28, 0, 16, __value)
+#define SET_TX_DESC_MCSG4_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 16, 4, __value)
+#define SET_TX_DESC_MCSG5_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 20, 4, __value)
+#define SET_TX_DESC_MCSG6_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 24, 4, __value)
+#define SET_TX_DESC_MCSG15_MAX_LEN(__txdesc, __value)	\
+	SET_BITS_OFFSET_LE(__txdesc+28, 28, 4, __value)
+
+
+int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw);
+u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index);
+bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
+			   struct rtl_stats *stats,
+			   struct ieee80211_rx_status *rx_status,
+			   u8 *p_desc, struct sk_buff *skb);
+void  rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb);
+void rtl8192c_rx_segregate_hdl(struct ieee80211_hw *, struct sk_buff *,
+			       struct sk_buff_head *);
+void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff  *skb);
+int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb,
+			 struct sk_buff *skb);
+struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *,
+					   struct sk_buff_head *);
+void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
+			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
+			  struct ieee80211_tx_info *info, struct sk_buff *skb,
+			  unsigned int queue_index);
+void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 * pDesc,
+			      u32 buffer_len, bool bIsPsPoll);
+void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
+			     u8 *pdesc, bool b_firstseg,
+			     bool b_lastseg, struct sk_buff *skb);
+bool rtl92cu_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/usb.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/usb.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1035 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2011  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+#include <linux/usb.h>
+#include "core.h"
+#include "wifi.h"
+#include "usb.h"
+#include "base.h"
+#include "ps.h"
+
+#define	REALTEK_USB_VENQT_READ			0xC0
+#define	REALTEK_USB_VENQT_WRITE			0x40
+#define REALTEK_USB_VENQT_CMD_REQ		0x05
+#define	REALTEK_USB_VENQT_CMD_IDX		0x00
+
+#define REALTEK_USB_VENQT_MAX_BUF_SIZE		254
+
+static void usbctrl_async_callback(struct urb *urb)
+{
+	if (urb)
+		kfree(urb->context);
+}
+
+static int _usbctrl_vendorreq_async_write(struct usb_device *udev, u8 request,
+					  u16 value, u16 index, void *pdata,
+					  u16 len)
+{
+	int rc;
+	unsigned int pipe;
+	u8 reqtype;
+	struct usb_ctrlrequest *dr;
+	struct urb *urb;
+	struct rtl819x_async_write_data {
+		u8 data[REALTEK_USB_VENQT_MAX_BUF_SIZE];
+		struct usb_ctrlrequest dr;
+	} *buf;
+
+	pipe = usb_sndctrlpipe(udev, 0); /* write_out */
+	reqtype =  REALTEK_USB_VENQT_WRITE;
+
+	buf = kmalloc(sizeof(*buf), GFP_ATOMIC);
+	if (!buf)
+		return -ENOMEM;
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!urb) {
+		kfree(buf);
+		return -ENOMEM;
+	}
+
+	dr = &buf->dr;
+
+	dr->bRequestType = reqtype;
+	dr->bRequest = request;
+	dr->wValue = cpu_to_le16(value);
+	dr->wIndex = cpu_to_le16(index);
+	dr->wLength = cpu_to_le16(len);
+	memcpy(buf, pdata, len);
+	usb_fill_control_urb(urb, udev, pipe,
+			     (unsigned char *)dr, buf, len,
+			     usbctrl_async_callback, buf);
+	rc = usb_submit_urb(urb, GFP_ATOMIC);
+	if (rc < 0)
+		kfree(buf);
+	usb_free_urb(urb);
+	return rc;
+}
+
+static int _usbctrl_vendorreq_sync_read(struct usb_device *udev, u8 request,
+					u16 value, u16 index, void *pdata,
+					u16 len)
+{
+	unsigned int pipe;
+	int status;
+	u8 reqtype;
+
+	pipe = usb_rcvctrlpipe(udev, 0); /* read_in */
+	reqtype =  REALTEK_USB_VENQT_READ;
+
+	status = usb_control_msg(udev, pipe, request, reqtype, value, index,
+				 pdata, len, 0); /* max. timeout */
+
+	if (status < 0)
+		printk(KERN_ERR "reg 0x%x, usbctrl_vendorreq TimeOut! "
+		       "status:0x%x value=0x%x\n", value, status,
+		       *(u32 *)pdata);
+	return status;
+}
+
+static u32 _usb_read_sync(struct usb_device *udev, u32 addr, u16 len)
+{
+	u8 request;
+	u16 wvalue;
+	u16 index;
+	u32 *data;
+	u32 ret;
+
+	data = kmalloc(sizeof(u32), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+	request = REALTEK_USB_VENQT_CMD_REQ;
+	index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
+
+	wvalue = (u16)addr;
+	_usbctrl_vendorreq_sync_read(udev, request, wvalue, index, data, len);
+	ret = *data;
+	kfree(data);
+	return ret;
+}
+
+static u8 _usb_read8_sync(struct rtl_priv *rtlpriv, u32 addr)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return (u8)_usb_read_sync(to_usb_device(dev), addr, 1);
+}
+
+static u16 _usb_read16_sync(struct rtl_priv *rtlpriv, u32 addr)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return (u16)_usb_read_sync(to_usb_device(dev), addr, 2);
+}
+
+static u32 _usb_read32_sync(struct rtl_priv *rtlpriv, u32 addr)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return _usb_read_sync(to_usb_device(dev), addr, 4);
+}
+
+static void _usb_write_async(struct usb_device *udev, u32 addr, u32 val,
+			     u16 len)
+{
+	u8 request;
+	u16 wvalue;
+	u16 index;
+	u32 data;
+
+	request = REALTEK_USB_VENQT_CMD_REQ;
+	index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
+	wvalue = (u16)(addr&0x0000ffff);
+	data = val;
+	_usbctrl_vendorreq_async_write(udev, request, wvalue, index, &data,
+				       len);
+}
+
+static void _usb_write8_async(struct rtl_priv *rtlpriv, u32 addr, u8 val)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	_usb_write_async(to_usb_device(dev), addr, val, 1);
+}
+
+static void _usb_write16_async(struct rtl_priv *rtlpriv, u32 addr, u16 val)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	_usb_write_async(to_usb_device(dev), addr, val, 2);
+}
+
+static void _usb_write32_async(struct rtl_priv *rtlpriv, u32 addr, u32 val)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	_usb_write_async(to_usb_device(dev), addr, val, 4);
+}
+
+static int _usb_nbytes_read_write(struct usb_device *udev, bool read, u32 addr,
+				  u16 len, u8 *pdata)
+{
+	int status;
+	u8 request;
+	u16 wvalue;
+	u16 index;
+
+	request = REALTEK_USB_VENQT_CMD_REQ;
+	index = REALTEK_USB_VENQT_CMD_IDX; /* n/a */
+	wvalue = (u16)addr;
+	if (read)
+		status = _usbctrl_vendorreq_sync_read(udev, request, wvalue,
+						      index, pdata, len);
+	else
+		status = _usbctrl_vendorreq_async_write(udev, request, wvalue,
+							index, pdata, len);
+	return status;
+}
+
+static int _usb_readN_sync(struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			   u8 *pdata)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return _usb_nbytes_read_write(to_usb_device(dev), true, addr, len,
+				       pdata);
+}
+
+static int _usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			     u8 *pdata)
+{
+	struct device *dev = rtlpriv->io.dev;
+
+	return _usb_nbytes_read_write(to_usb_device(dev), false, addr, len,
+				      pdata);
+}
+
+static void _rtl_usb_io_handler_init(struct device *dev,
+				     struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	rtlpriv->io.dev = dev;
+	mutex_init(&rtlpriv->io.bb_mutex);
+	rtlpriv->io.write8_async	= _usb_write8_async;
+	rtlpriv->io.write16_async	= _usb_write16_async;
+	rtlpriv->io.write32_async	= _usb_write32_async;
+	rtlpriv->io.writeN_async	= _usb_writeN_async;
+	rtlpriv->io.read8_sync		= _usb_read8_sync;
+	rtlpriv->io.read16_sync		= _usb_read16_sync;
+	rtlpriv->io.read32_sync		= _usb_read32_sync;
+	rtlpriv->io.readN_sync		= _usb_readN_sync;
+}
+
+static void _rtl_usb_io_handler_release(struct ieee80211_hw *hw)
+{
+	struct rtl_priv __maybe_unused *rtlpriv = rtl_priv(hw);
+
+	mutex_destroy(&rtlpriv->io.bb_mutex);
+}
+
+/**
+ *
+ *	Default aggregation handler. Do nothing and just return the oldest skb.
+ */
+static struct sk_buff *_none_usb_tx_aggregate_hdl(struct ieee80211_hw *hw,
+						  struct sk_buff_head *list)
+{
+	return skb_dequeue(list);
+}
+
+#define IS_HIGH_SPEED_USB(udev) \
+		((USB_SPEED_HIGH == (udev)->speed) ? true : false)
+
+static int _rtl_usb_init_tx(struct ieee80211_hw *hw)
+{
+	u32 i;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtlusb->max_bulk_out_size = IS_HIGH_SPEED_USB(rtlusb->udev)
+						    ? USB_HIGH_SPEED_BULK_SIZE
+						    : USB_FULL_SPEED_BULK_SIZE;
+
+	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, ("USB Max Bulk-out Size=%d\n",
+		 rtlusb->max_bulk_out_size));
+
+	for (i = 0; i < __RTL_TXQ_NUM; i++) {
+		u32 ep_num = rtlusb->ep_map.ep_mapping[i];
+		if (!ep_num) {
+			RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+				 ("Invalid endpoint map setting!\n"));
+			return -EINVAL;
+		}
+	}
+
+	rtlusb->usb_tx_post_hdl =
+		 rtlpriv->cfg->usb_interface_cfg->usb_tx_post_hdl;
+	rtlusb->usb_tx_cleanup	=
+		 rtlpriv->cfg->usb_interface_cfg->usb_tx_cleanup;
+	rtlusb->usb_tx_aggregate_hdl =
+		 (rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl)
+		 ? rtlpriv->cfg->usb_interface_cfg->usb_tx_aggregate_hdl
+		 : &_none_usb_tx_aggregate_hdl;
+
+	init_usb_anchor(&rtlusb->tx_submitted);
+	for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
+		skb_queue_head_init(&rtlusb->tx_skb_queue[i]);
+		init_usb_anchor(&rtlusb->tx_pending[i]);
+	}
+	return 0;
+}
+
+static int _rtl_usb_init_rx(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+
+	rtlusb->rx_max_size = rtlpriv->cfg->usb_interface_cfg->rx_max_size;
+	rtlusb->rx_urb_num = rtlpriv->cfg->usb_interface_cfg->rx_urb_num;
+	rtlusb->in_ep = rtlpriv->cfg->usb_interface_cfg->in_ep_num;
+	rtlusb->usb_rx_hdl = rtlpriv->cfg->usb_interface_cfg->usb_rx_hdl;
+	rtlusb->usb_rx_segregate_hdl =
+		rtlpriv->cfg->usb_interface_cfg->usb_rx_segregate_hdl;
+
+	printk(KERN_INFO "rtl8192cu: rx_max_size %d, rx_urb_num %d, in_ep %d\n",
+		rtlusb->rx_max_size, rtlusb->rx_urb_num, rtlusb->in_ep);
+	init_usb_anchor(&rtlusb->rx_submitted);
+	return 0;
+}
+
+static int _rtl_usb_init(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
+	int err;
+	u8 epidx;
+	struct usb_interface	*usb_intf = rtlusb->intf;
+	u8 epnums = usb_intf->cur_altsetting->desc.bNumEndpoints;
+
+	rtlusb->out_ep_nums = rtlusb->in_ep_nums = 0;
+	for (epidx = 0; epidx < epnums; epidx++) {
+		struct usb_endpoint_descriptor *pep_desc;
+		pep_desc = &usb_intf->cur_altsetting->endpoint[epidx].desc;
+
+		if (usb_endpoint_dir_in(pep_desc))
+			rtlusb->in_ep_nums++;
+		else if (usb_endpoint_dir_out(pep_desc))
+			rtlusb->out_ep_nums++;
+
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
+			 ("USB EP(0x%02x), MaxPacketSize=%d ,Interval=%d.\n",
+			 pep_desc->bEndpointAddress, pep_desc->wMaxPacketSize,
+			 pep_desc->bInterval));
+	}
+	if (rtlusb->in_ep_nums <  rtlpriv->cfg->usb_interface_cfg->in_ep_num)
+		return -EINVAL ;
+
+	/* usb endpoint mapping */
+	err = rtlpriv->cfg->usb_interface_cfg->usb_endpoint_mapping(hw);
+	rtlusb->usb_mq_to_hwq =  rtlpriv->cfg->usb_interface_cfg->usb_mq_to_hwq;
+	_rtl_usb_init_tx(hw);
+	_rtl_usb_init_rx(hw);
+	return err;
+}
+
+static int _rtl_usb_init_sw(struct ieee80211_hw *hw)
+{
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	rtlhal->hw = hw;
+	ppsc->inactiveps = false;
+	ppsc->leisure_ps = false;
+	ppsc->fwctrl_lps = false;
+	ppsc->reg_fwctrl_lps = 3;
+	ppsc->reg_max_lps_awakeintvl = 5;
+	ppsc->fwctrl_psmode = FW_PS_DTIM_MODE;
+
+	 /* IBSS */
+	mac->beacon_interval = 100;
+
+	 /* AMPDU */
+	mac->min_space_cfg = 0;
+	mac->max_mss_density = 0;
+
+	/* set sane AMPDU defaults */
+	mac->current_ampdu_density = 7;
+	mac->current_ampdu_factor = 3;
+
+	/* QOS */
+	rtlusb->acm_method = eAcmWay2_SW;
+
+	/* IRQ */
+	/* HIMR - turn all on */
+	rtlusb->irq_mask[0] = 0xFFFFFFFF;
+	/* HIMR_EX - turn all on */
+	rtlusb->irq_mask[1] = 0xFFFFFFFF;
+	rtlusb->disableHWSM =  true;
+	return 0;
+}
+
+#define __RADIO_TAP_SIZE_RSV	32
+
+static void _rtl_rx_completed(struct urb *urb);
+
+static struct sk_buff *_rtl_prep_rx_urb(struct ieee80211_hw *hw,
+					struct rtl_usb *rtlusb,
+					struct urb *urb,
+					gfp_t gfp_mask)
+{
+	struct sk_buff *skb;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+
+	skb = __dev_alloc_skb((rtlusb->rx_max_size + __RADIO_TAP_SIZE_RSV),
+			       gfp_mask);
+	if (!skb) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Failed to __dev_alloc_skb!!\n"))
+		return ERR_PTR(-ENOMEM);
+	}
+
+	/* reserve some space for mac80211's radiotap */
+	skb_reserve(skb, __RADIO_TAP_SIZE_RSV);
+	usb_fill_bulk_urb(urb, rtlusb->udev,
+			  usb_rcvbulkpipe(rtlusb->udev, rtlusb->in_ep),
+			  skb->data, min(skb_tailroom(skb),
+			  (int)rtlusb->rx_max_size),
+			  _rtl_rx_completed, skb);
+
+	_rtl_install_trx_info(rtlusb, skb, rtlusb->in_ep);
+	return skb;
+}
+
+#undef __RADIO_TAP_SIZE_RSV
+
+static void _rtl_usb_rx_process_agg(struct ieee80211_hw *hw,
+				    struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *rxdesc = skb->data;
+	struct ieee80211_hdr *hdr;
+	bool unicast = false;
+	__le16 fc;
+	struct ieee80211_rx_status rx_status = {0};
+	struct rtl_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+	};
+
+	skb_pull(skb, RTL_RX_DESC_SIZE);
+	rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
+	skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
+	hdr = (struct ieee80211_hdr *)(skb->data);
+	fc = hdr->frame_control;
+	if (!stats.crc) {
+		memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+		if (is_broadcast_ether_addr(hdr->addr1)) {
+			/*TODO*/;
+		} else if (is_multicast_ether_addr(hdr->addr1)) {
+			/*TODO*/
+		} else {
+			unicast = true;
+			rtlpriv->stats.rxbytesunicast +=  skb->len;
+		}
+
+		rtl_is_special_data(hw, skb, false);
+
+		if (ieee80211_is_data(fc)) {
+			rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+			if (unicast)
+				rtlpriv->link_info.num_rx_inperiod++;
+		}
+	}
+}
+
+static void _rtl_usb_rx_process_noagg(struct ieee80211_hw *hw,
+				      struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	u8 *rxdesc = skb->data;
+	struct ieee80211_hdr *hdr;
+	bool unicast = false;
+	__le16 fc;
+	struct ieee80211_rx_status rx_status = {0};
+	struct rtl_stats stats = {
+		.signal = 0,
+		.noise = -98,
+		.rate = 0,
+	};
+
+	skb_pull(skb, RTL_RX_DESC_SIZE);
+	rtlpriv->cfg->ops->query_rx_desc(hw, &stats, &rx_status, rxdesc, skb);
+	skb_pull(skb, (stats.rx_drvinfo_size + stats.rx_bufshift));
+	hdr = (struct ieee80211_hdr *)(skb->data);
+	fc = hdr->frame_control;
+	if (!stats.crc) {
+		memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
+
+		if (is_broadcast_ether_addr(hdr->addr1)) {
+			/*TODO*/;
+		} else if (is_multicast_ether_addr(hdr->addr1)) {
+			/*TODO*/
+		} else {
+			unicast = true;
+			rtlpriv->stats.rxbytesunicast +=  skb->len;
+		}
+
+		rtl_is_special_data(hw, skb, false);
+
+		if (ieee80211_is_data(fc)) {
+			rtlpriv->cfg->ops->led_control(hw, LED_CTL_RX);
+
+			if (unicast)
+				rtlpriv->link_info.num_rx_inperiod++;
+		}
+		if (likely(rtl_action_proc(hw, skb, false))) {
+			struct sk_buff *uskb = NULL;
+			u8 *pdata;
+
+			uskb = dev_alloc_skb(skb->len + 128);
+			memcpy(IEEE80211_SKB_RXCB(uskb), &rx_status,
+			       sizeof(rx_status));
+			pdata = (u8 *)skb_put(uskb, skb->len);
+			memcpy(pdata, skb->data, skb->len);
+			dev_kfree_skb_any(skb);
+			ieee80211_rx_irqsafe(hw, uskb);
+		} else {
+			dev_kfree_skb_any(skb);
+		}
+	}
+}
+
+static void _rtl_rx_pre_process(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct sk_buff *_skb;
+	struct sk_buff_head rx_queue;
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	skb_queue_head_init(&rx_queue);
+	if (rtlusb->usb_rx_segregate_hdl)
+		rtlusb->usb_rx_segregate_hdl(hw, skb, &rx_queue);
+	WARN_ON(skb_queue_empty(&rx_queue));
+	while (!skb_queue_empty(&rx_queue)) {
+		_skb = skb_dequeue(&rx_queue);
+		_rtl_usb_rx_process_agg(hw, skb);
+		ieee80211_rx_irqsafe(hw, skb);
+	}
+}
+
+static void _rtl_rx_completed(struct urb *_urb)
+{
+	struct sk_buff *skb = (struct sk_buff *)_urb->context;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0];
+	struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	int err = 0;
+
+	if (unlikely(IS_USB_STOP(rtlusb)))
+		goto free;
+
+	if (likely(0 == _urb->status)) {
+		/* If this code were moved to work queue, would CPU
+		 * utilization be improved?  NOTE: We shall allocate another skb
+		 * and reuse the original one.
+		 */
+		skb_put(skb, _urb->actual_length);
+
+		if (likely(!rtlusb->usb_rx_segregate_hdl)) {
+			struct sk_buff *_skb;
+			_rtl_usb_rx_process_noagg(hw, skb);
+			_skb = _rtl_prep_rx_urb(hw, rtlusb, _urb, GFP_ATOMIC);
+			if (IS_ERR(_skb)) {
+				err = PTR_ERR(_skb);
+				RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+					("Can't allocate skb for bulk IN!\n"));
+				return;
+			}
+			skb = _skb;
+		} else{
+			/* TO DO */
+			_rtl_rx_pre_process(hw, skb);
+			printk(KERN_ERR "rtlwifi: rx agg not supported\n");
+		}
+		goto resubmit;
+	}
+
+	switch (_urb->status) {
+	/* disconnect */
+	case -ENOENT:
+	case -ECONNRESET:
+	case -ENODEV:
+	case -ESHUTDOWN:
+		goto free;
+	default:
+		break;
+	}
+
+resubmit:
+	skb_reset_tail_pointer(skb);
+	skb_trim(skb, 0);
+
+	usb_anchor_urb(_urb, &rtlusb->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 _rtl_usb_receive(struct ieee80211_hw *hw)
+{
+	struct urb *urb;
+	struct sk_buff *skb;
+	int err;
+	int i;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	WARN_ON(0 == rtlusb->rx_urb_num);
+	/* 1600 == 1514 + max WLAN header + rtk info */
+	WARN_ON(rtlusb->rx_max_size < 1600);
+
+	for (i = 0; i < rtlusb->rx_urb_num; i++) {
+		err = -ENOMEM;
+		urb = usb_alloc_urb(0, GFP_KERNEL);
+		if (!urb) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 ("Failed to alloc URB!!\n"))
+			goto err_out;
+		}
+
+		skb = _rtl_prep_rx_urb(hw, rtlusb, urb, GFP_KERNEL);
+		if (IS_ERR(skb)) {
+			RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+				 ("Failed to prep_rx_urb!!\n"))
+			err = PTR_ERR(skb);
+			goto err_out;
+		}
+
+		usb_anchor_urb(urb, &rtlusb->rx_submitted);
+		err = usb_submit_urb(urb, GFP_KERNEL);
+		if (err)
+			goto err_out;
+		usb_free_urb(urb);
+	}
+	return 0;
+
+err_out:
+	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+	return err;
+}
+
+static int rtl_usb_start(struct ieee80211_hw *hw)
+{
+	int err;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	err = rtlpriv->cfg->ops->hw_init(hw);
+	rtl_init_rx_config(hw);
+
+	/* Enable software */
+	SET_USB_START(rtlusb);
+	/* should after adapter start and interrupt enable. */
+	set_hal_start(rtlhal);
+
+	/* Start bulk IN */
+	_rtl_usb_receive(hw);
+
+	return err;
+}
+/**
+ *
+ *
+ */
+
+/*=======================  tx =========================================*/
+static void rtl_usb_cleanup(struct ieee80211_hw *hw)
+{
+	u32 i;
+	struct sk_buff *_skb;
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct ieee80211_tx_info *txinfo;
+
+	SET_USB_STOP(rtlusb);
+
+	/* clean up rx stuff. */
+	usb_kill_anchored_urbs(&rtlusb->rx_submitted);
+
+	/* clean up tx stuff */
+	for (i = 0; i < RTL_USB_MAX_EP_NUM; i++) {
+		while ((_skb = skb_dequeue(&rtlusb->tx_skb_queue[i]))) {
+			rtlusb->usb_tx_cleanup(hw, _skb);
+			txinfo = IEEE80211_SKB_CB(_skb);
+			ieee80211_tx_info_clear_status(txinfo);
+			txinfo->flags |= IEEE80211_TX_STAT_ACK;
+			ieee80211_tx_status_irqsafe(hw, _skb);
+		}
+		usb_kill_anchored_urbs(&rtlusb->tx_pending[i]);
+	}
+	usb_kill_anchored_urbs(&rtlusb->tx_submitted);
+}
+
+/**
+ *
+ * We may add some struct into struct rtl_usb later. Do deinit here.
+ *
+ */
+static void rtl_usb_deinit(struct ieee80211_hw *hw)
+{
+	rtl_usb_cleanup(hw);
+}
+
+static void rtl_usb_stop(struct ieee80211_hw *hw)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	/* should after adapter start and interrupt enable. */
+	set_hal_stop(rtlhal);
+	/* Enable software */
+	SET_USB_STOP(rtlusb);
+	rtl_usb_deinit(hw);
+	rtlpriv->cfg->ops->hw_disable(hw);
+}
+
+static void _rtl_submit_tx_urb(struct ieee80211_hw *hw, struct urb *_urb)
+{
+	int err;
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	usb_anchor_urb(_urb, &rtlusb->tx_submitted);
+	err = usb_submit_urb(_urb, GFP_ATOMIC);
+	if (err < 0) {
+		struct sk_buff *skb;
+
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Failed to submit urb.\n"));
+		usb_unanchor_urb(_urb);
+		skb = (struct sk_buff *)_urb->context;
+		kfree_skb(skb);
+	}
+	usb_free_urb(_urb);
+}
+
+static int _usb_tx_post(struct ieee80211_hw *hw, struct urb *urb,
+			struct sk_buff *skb)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct ieee80211_tx_info *txinfo;
+
+	rtlusb->usb_tx_post_hdl(hw, urb, skb);
+	skb_pull(skb, RTL_TX_HEADER_SIZE);
+	txinfo = IEEE80211_SKB_CB(skb);
+	ieee80211_tx_info_clear_status(txinfo);
+	txinfo->flags |= IEEE80211_TX_STAT_ACK;
+
+	if (urb->status) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Urb has error status 0x%X\n", urb->status));
+		goto out;
+	}
+	/*  TODO:	statistics */
+out:
+	ieee80211_tx_status_irqsafe(hw, skb);
+	return urb->status;
+}
+
+static void _rtl_tx_complete(struct urb *urb)
+{
+	struct sk_buff *skb = (struct sk_buff *)urb->context;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct rtl_usb *rtlusb = (struct rtl_usb *)info->rate_driver_data[0];
+	struct ieee80211_hw *hw = usb_get_intfdata(rtlusb->intf);
+	int err;
+
+	if (unlikely(IS_USB_STOP(rtlusb)))
+		return;
+	err = _usb_tx_post(hw, urb, skb);
+	if (err) {
+		/* Ignore error and keep issuiing other urbs */
+		return;
+	}
+}
+
+static struct urb *_rtl_usb_tx_urb_setup(struct ieee80211_hw *hw,
+				struct sk_buff *skb, u32 ep_num)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct urb *_urb;
+
+	WARN_ON(NULL == skb);
+	_urb = usb_alloc_urb(0, GFP_ATOMIC);
+	if (!_urb) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("Can't allocate URB for bulk out!\n"));
+		kfree_skb(skb);
+		return NULL;
+	}
+	_rtl_install_trx_info(rtlusb, skb, ep_num);
+	usb_fill_bulk_urb(_urb, rtlusb->udev, usb_sndbulkpipe(rtlusb->udev,
+			  ep_num), skb->data, skb->len, _rtl_tx_complete, skb);
+	_urb->transfer_flags |= URB_ZERO_PACKET;
+	return _urb;
+}
+
+static void _rtl_usb_transmit(struct ieee80211_hw *hw, struct sk_buff *skb,
+		       enum rtl_txq qnum)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	u32 ep_num;
+	struct urb *_urb = NULL;
+	struct sk_buff *_skb = NULL;
+	struct sk_buff_head *skb_list;
+	struct usb_anchor *urb_list;
+
+	WARN_ON(NULL == rtlusb->usb_tx_aggregate_hdl);
+	if (unlikely(IS_USB_STOP(rtlusb))) {
+		RT_TRACE(rtlpriv, COMP_USB, DBG_EMERG,
+			 ("USB device is stopping...\n"));
+		kfree_skb(skb);
+		return;
+	}
+	ep_num = rtlusb->ep_map.ep_mapping[qnum];
+	skb_list = &rtlusb->tx_skb_queue[ep_num];
+	_skb = skb;
+	_urb = _rtl_usb_tx_urb_setup(hw, _skb, ep_num);
+	if (unlikely(!_urb)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't allocate urb. Drop skb!\n"));
+		return;
+	}
+	urb_list = &rtlusb->tx_pending[ep_num];
+	_rtl_submit_tx_urb(hw, _urb);
+}
+
+static void _rtl_usb_tx_preprocess(struct ieee80211_hw *hw, struct sk_buff *skb,
+			    u16 hw_queue)
+{
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	struct rtl_tx_desc *pdesc = NULL;
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+	u8 *pda_addr = hdr->addr1;
+	/* ssn */
+	u8 *qc = NULL;
+	u8 tid = 0;
+	u16 seq_number = 0;
+
+	if (ieee80211_is_mgmt(fc))
+		rtl_tx_mgmt_proc(hw, skb);
+	rtl_action_proc(hw, skb, true);
+	if (is_multicast_ether_addr(pda_addr))
+		rtlpriv->stats.txbytesmulticast += skb->len;
+	else if (is_broadcast_ether_addr(pda_addr))
+		rtlpriv->stats.txbytesbroadcast += skb->len;
+	else
+		rtlpriv->stats.txbytesunicast += skb->len;
+	if (ieee80211_is_data_qos(fc)) {
+		qc = ieee80211_get_qos_ctl(hdr);
+		tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
+		seq_number = (le16_to_cpu(hdr->seq_ctrl) &
+			     IEEE80211_SCTL_SEQ) >> 4;
+		seq_number += 1;
+		seq_number <<= 4;
+	}
+	rtlpriv->cfg->ops->fill_tx_desc(hw, hdr, (u8 *)pdesc, info, skb,
+					hw_queue);
+	if (!ieee80211_has_morefrags(hdr->frame_control)) {
+		if (qc)
+			mac->tids[tid].seq_number = seq_number;
+	}
+	if (ieee80211_is_data(fc))
+		rtlpriv->cfg->ops->led_control(hw, LED_CTL_TX);
+}
+
+static int rtl_usb_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
+	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
+	__le16 fc = hdr->frame_control;
+	u16 hw_queue;
+
+	if (unlikely(is_hal_stop(rtlhal)))
+		goto err_free;
+	hw_queue = rtlusb->usb_mq_to_hwq(fc, skb_get_queue_mapping(skb));
+	_rtl_usb_tx_preprocess(hw, skb, hw_queue);
+	_rtl_usb_transmit(hw, skb, hw_queue);
+	return NETDEV_TX_OK;
+
+err_free:
+	dev_kfree_skb_any(skb);
+	return NETDEV_TX_OK;
+}
+
+static bool rtl_usb_tx_chk_waitq_insert(struct ieee80211_hw *hw,
+					struct sk_buff *skb)
+{
+	return false;
+}
+
+static struct rtl_intf_ops rtl_usb_ops = {
+	.adapter_start = rtl_usb_start,
+	.adapter_stop = rtl_usb_stop,
+	.adapter_tx = rtl_usb_tx,
+	.waitq_insert = rtl_usb_tx_chk_waitq_insert,
+};
+
+int __devinit rtl_usb_probe(struct usb_interface *intf,
+			const struct usb_device_id *id)
+{
+	int err;
+	struct ieee80211_hw *hw = NULL;
+	struct rtl_priv *rtlpriv = NULL;
+	struct usb_device	*udev;
+	struct rtl_usb_priv *usb_priv;
+
+	hw = ieee80211_alloc_hw(sizeof(struct rtl_priv) +
+				sizeof(struct rtl_usb_priv), &rtl_ops);
+	if (!hw) {
+		RT_ASSERT(false, ("%s : ieee80211 alloc failed\n", __func__));
+		return -ENOMEM;
+	}
+	rtlpriv = hw->priv;
+	SET_IEEE80211_DEV(hw, &intf->dev);
+	udev = interface_to_usbdev(intf);
+	usb_get_dev(udev);
+	usb_priv = rtl_usbpriv(hw);
+	memset(usb_priv, 0, sizeof(*usb_priv));
+	usb_priv->dev.intf = intf;
+	usb_priv->dev.udev = udev;
+	usb_set_intfdata(intf, hw);
+	/* init cfg & intf_ops */
+	rtlpriv->rtlhal.interface = INTF_USB;
+	rtlpriv->cfg = (struct rtl_hal_cfg *)(id->driver_info);
+	rtlpriv->intf_ops = &rtl_usb_ops;
+	rtl_dbgp_flag_init(hw);
+	/* Init IO handler */
+	_rtl_usb_io_handler_init(&udev->dev, hw);
+	rtlpriv->cfg->ops->read_chip_version(hw);
+	/*like read eeprom and so on */
+	rtlpriv->cfg->ops->read_eeprom_info(hw);
+	if (rtlpriv->cfg->ops->init_sw_vars(hw)) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't init_sw_vars.\n"));
+		goto error_out;
+	}
+	rtlpriv->cfg->ops->init_sw_leds(hw);
+	err = _rtl_usb_init(hw);
+	err = _rtl_usb_init_sw(hw);
+	/* Init mac80211 sw */
+	err = rtl_init_core(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG,
+			 ("Can't allocate sw for mac80211.\n"));
+		goto error_out;
+	}
+
+	/*init rfkill */
+	/* rtl_init_rfkill(hw); */
+
+	err = ieee80211_register_hw(hw);
+	if (err) {
+		RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
+			 ("Can't register mac80211 hw.\n"));
+		goto error_out;
+	} else {
+		rtlpriv->mac80211.mac80211_registered = 1;
+	}
+	set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status);
+	return 0;
+error_out:
+	rtl_deinit_core(hw);
+	_rtl_usb_io_handler_release(hw);
+	ieee80211_free_hw(hw);
+	usb_put_dev(udev);
+	return -ENODEV;
+}
+EXPORT_SYMBOL(rtl_usb_probe);
+
+void rtl_usb_disconnect(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct rtl_priv *rtlpriv = rtl_priv(hw);
+	struct rtl_mac *rtlmac = rtl_mac(rtl_priv(hw));
+	struct rtl_usb *rtlusb = rtl_usbdev(rtl_usbpriv(hw));
+
+	if (unlikely(!rtlpriv))
+		return;
+	/*ieee80211_unregister_hw will call ops_stop */
+	if (rtlmac->mac80211_registered == 1) {
+		ieee80211_unregister_hw(hw);
+		rtlmac->mac80211_registered = 0;
+	} else {
+		rtl_deinit_deferred_work(hw);
+		rtlpriv->intf_ops->adapter_stop(hw);
+	}
+	/*deinit rfkill */
+	/* rtl_deinit_rfkill(hw); */
+	rtl_usb_deinit(hw);
+	rtl_deinit_core(hw);
+	rtlpriv->cfg->ops->deinit_sw_leds(hw);
+	rtlpriv->cfg->ops->deinit_sw_vars(hw);
+	_rtl_usb_io_handler_release(hw);
+	usb_put_dev(rtlusb->udev);
+	usb_set_intfdata(intf, NULL);
+	ieee80211_free_hw(hw);
+}
+EXPORT_SYMBOL(rtl_usb_disconnect);
+
+int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message)
+{
+	return 0;
+}
+EXPORT_SYMBOL(rtl_usb_suspend);
+
+int rtl_usb_resume(struct usb_interface *pusb_intf)
+{
+	return 0;
+}
+EXPORT_SYMBOL(rtl_usb_resume);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/usb.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/usb.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/usb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,164 @@
+/******************************************************************************
+ *
+ * Copyright(c) 2009-2011  Realtek Corporation. All rights reserved.
+ *
+ * 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:
+ * wlanfae <wlanfae@realtek.com>
+ * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
+ * Hsinchu 300, Taiwan.
+ *
+ *****************************************************************************/
+
+#ifndef __RTL_USB_H__
+#define __RTL_USB_H__
+
+#include <linux/usb.h>
+#include <linux/skbuff.h>
+
+#define RTL_USB_DEVICE(vend, prod, cfg) \
+	.match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
+	.idVendor = (vend), \
+	.idProduct = (prod), \
+	.driver_info = (kernel_ulong_t)&(cfg)
+
+#define USB_HIGH_SPEED_BULK_SIZE	512
+#define USB_FULL_SPEED_BULK_SIZE	64
+
+
+#define RTL_USB_MAX_TXQ_NUM		4		/* max tx queue */
+#define RTL_USB_MAX_EP_NUM		6		/* max ep number */
+#define RTL_USB_MAX_TX_URBS_NUM		8
+
+enum rtl_txq {
+	/* These definitions shall be consistent with value
+	 * returned by skb_get_queue_mapping
+	 *------------------------------------*/
+	RTL_TXQ_BK,
+	RTL_TXQ_BE,
+	RTL_TXQ_VI,
+	RTL_TXQ_VO,
+	/*------------------------------------*/
+	RTL_TXQ_BCN,
+	RTL_TXQ_MGT,
+	RTL_TXQ_HI,
+
+	/* Must be last */
+	__RTL_TXQ_NUM,
+};
+
+struct rtl_ep_map {
+	u32 ep_mapping[__RTL_TXQ_NUM];
+};
+
+struct _trx_info {
+	struct rtl_usb *rtlusb;
+	u32 ep_num;
+};
+
+static inline void _rtl_install_trx_info(struct rtl_usb *rtlusb,
+					 struct sk_buff *skb,
+					 u32 ep_num)
+{
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+	info->rate_driver_data[0] = rtlusb;
+	info->rate_driver_data[1] = (void *)(__kernel_size_t)ep_num;
+}
+
+
+/*  Add suspend/resume later */
+enum rtl_usb_state {
+	USB_STATE_STOP	= 0,
+	USB_STATE_START	= 1,
+};
+
+#define IS_USB_STOP(rtlusb_ptr) (USB_STATE_STOP == (rtlusb_ptr)->state)
+#define IS_USB_START(rtlusb_ptr) (USB_STATE_START == (rtlusb_ptr)->state)
+#define SET_USB_STOP(rtlusb_ptr) \
+	do {							\
+		(rtlusb_ptr)->state = USB_STATE_STOP;		\
+	} while (0)
+
+#define SET_USB_START(rtlusb_ptr)				\
+	do { \
+		(rtlusb_ptr)->state = USB_STATE_START;		\
+	} while (0)
+
+struct rtl_usb {
+	struct usb_device *udev;
+	struct usb_interface *intf;
+	enum rtl_usb_state state;
+
+	/* Bcn control register setting */
+	u32 reg_bcn_ctrl_val;
+	/* for 88/92cu card disable */
+	u8	disableHWSM;
+	/*QOS & EDCA */
+	enum acm_method acm_method;
+	/* irq  . HIMR,HIMR_EX */
+	u32 irq_mask[2];
+	bool irq_enabled;
+
+	u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index);
+
+	/* Tx */
+	u8 out_ep_nums ;
+	u8 out_queue_sel;
+	struct rtl_ep_map ep_map;
+
+	u32 max_bulk_out_size;
+	u32 tx_submitted_urbs;
+	struct sk_buff_head tx_skb_queue[RTL_USB_MAX_EP_NUM];
+
+	struct usb_anchor tx_pending[RTL_USB_MAX_EP_NUM];
+	struct usb_anchor tx_submitted;
+
+	struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *,
+						struct sk_buff_head *);
+	int (*usb_tx_post_hdl)(struct ieee80211_hw *,
+			       struct urb *, struct sk_buff *);
+	void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *);
+
+	/* Rx */
+	u8 in_ep_nums ;
+	u32 in_ep;		/* Bulk IN endpoint number */
+	u32 rx_max_size;	/* Bulk IN max buffer size */
+	u32 rx_urb_num;		/* How many Bulk INs are submitted to host. */
+	struct usb_anchor	rx_submitted;
+	void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *,
+				     struct sk_buff_head *);
+	void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *);
+};
+
+struct rtl_usb_priv {
+	struct rtl_usb dev;
+	struct rtl_led_ctl ledctl;
+};
+
+#define rtl_usbpriv(hw)	 (((struct rtl_usb_priv *)(rtl_priv(hw))->priv))
+#define rtl_usbdev(usbpriv)	(&((usbpriv)->dev))
+
+
+
+int __devinit rtl_usb_probe(struct usb_interface *intf,
+			    const struct usb_device_id *id);
+void rtl_usb_disconnect(struct usb_interface *intf);
+int rtl_usb_suspend(struct usb_interface *pusb_intf, pm_message_t message);
+int rtl_usb_resume(struct usb_interface *pusb_intf);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/wifi.h linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/wifi.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/rtlwifi/wifi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/rtlwifi/wifi.h	2011-05-19 00:06:34.000000000 -0400
@@ -34,6 +34,8 @@
 #include <linux/firmware.h>
 #include <linux/version.h>
 #include <linux/etherdevice.h>
+#include <linux/vmalloc.h>
+#include <linux/usb.h>
 #include <net/mac80211.h>
 #include "debug.h"
 
@@ -82,6 +84,19 @@
 #define MAC80211_3ADDR_LEN			24
 #define MAC80211_4ADDR_LEN			30
 
+#define CHANNEL_MAX_NUMBER	(14 + 24 + 21)	/* 14 is the max channel no */
+#define CHANNEL_GROUP_MAX	(3 + 9)	/*  ch1~3, 4~9, 10~14 = three groups */
+#define MAX_PG_GROUP			13
+#define	CHANNEL_GROUP_MAX_2G		3
+#define	CHANNEL_GROUP_IDX_5GL		3
+#define	CHANNEL_GROUP_IDX_5GM		6
+#define	CHANNEL_GROUP_IDX_5GH		9
+#define	CHANNEL_GROUP_MAX_5G		9
+#define CHANNEL_MAX_NUMBER_2G		14
+#define AVG_THERMAL_NUM			8
+
+/* for early mode */
+#define EM_HDR_LEN			8
 enum intf_type {
 	INTF_PCI = 0,
 	INTF_USB = 1,
@@ -113,11 +128,38 @@
 	HARDWARE_TYPE_RTL8192CU,
 	HARDWARE_TYPE_RTL8192DE,
 	HARDWARE_TYPE_RTL8192DU,
+	HARDWARE_TYPE_RTL8723E,
+	HARDWARE_TYPE_RTL8723U,
 
-	/*keep it last*/
+	/* keep it last */
 	HARDWARE_TYPE_NUM
 };
 
+#define IS_HARDWARE_TYPE_8192SU(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192SU)
+#define IS_HARDWARE_TYPE_8192SE(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192SE)
+#define IS_HARDWARE_TYPE_8192CE(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192CE)
+#define IS_HARDWARE_TYPE_8192CU(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192CU)
+#define IS_HARDWARE_TYPE_8192DE(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192DE)
+#define IS_HARDWARE_TYPE_8192DU(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8192DU)
+#define IS_HARDWARE_TYPE_8723E(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8723E)
+#define IS_HARDWARE_TYPE_8723U(rtlhal)			\
+	(rtlhal->hw_type == HARDWARE_TYPE_RTL8723U)
+#define	IS_HARDWARE_TYPE_8192S(rtlhal)			\
+(IS_HARDWARE_TYPE_8192SE(rtlhal) || IS_HARDWARE_TYPE_8192SU(rtlhal))
+#define	IS_HARDWARE_TYPE_8192C(rtlhal)			\
+(IS_HARDWARE_TYPE_8192CE(rtlhal) || IS_HARDWARE_TYPE_8192CU(rtlhal))
+#define	IS_HARDWARE_TYPE_8192D(rtlhal)			\
+(IS_HARDWARE_TYPE_8192DE(rtlhal) || IS_HARDWARE_TYPE_8192DU(rtlhal))
+#define	IS_HARDWARE_TYPE_8723(rtlhal)			\
+(IS_HARDWARE_TYPE_8723E(rtlhal) || IS_HARDWARE_TYPE_8723U(rtlhal))
+
 enum scan_operation_backup_opt {
 	SCAN_OPT_BACKUP = 0,
 	SCAN_OPT_RESTORE,
@@ -315,6 +357,7 @@
 	RF_1T1R = 0,
 	RF_1T2R = 1,
 	RF_2T2R = 2,
+	RF_2T2R_GREEN = 3,
 };
 
 enum ht_channel_width {
@@ -359,6 +402,8 @@
 	EFUSE_LOADER_CLK_EN,
 	EFUSE_ANA8M,
 	EFUSE_HWSET_MAX_SIZE,
+	EFUSE_MAX_SECTION_MAP,
+	EFUSE_REAL_CONTENT_SIZE,
 
 	/*CAM map */
 	RWCAM,
@@ -397,6 +442,7 @@
 	RTL_IMR_ATIMEND,	/*For 92C,ATIM Window End Interrupt */
 	RTL_IMR_BDOK,		/*Beacon Queue DMA OK Interrup */
 	RTL_IMR_HIGHDOK,	/*High Queue DMA OK Interrupt */
+	RTL_IMR_COMDOK,		/*Command Queue DMA OK Interrupt*/
 	RTL_IMR_TBDOK,		/*Transmit Beacon OK interrup */
 	RTL_IMR_MGNTDOK,	/*Management Queue DMA OK Interrupt */
 	RTL_IMR_TBDER,		/*For 92C,Transmit Beacon Error Interrupt */
@@ -405,7 +451,8 @@
 	RTL_IMR_VIDOK,		/*AC_VI DMA OK Interrupt */
 	RTL_IMR_VODOK,		/*AC_VO DMA Interrupt */
 	RTL_IMR_ROK,		/*Receive DMA OK Interrupt */
-	RTL_IBSS_INT_MASKS,	/*(RTL_IMR_BcnInt|RTL_IMR_TBDOK|RTL_IMR_TBDER)*/
+	RTL_IBSS_INT_MASKS,	/*(RTL_IMR_BcnInt | RTL_IMR_TBDOK |
+				 * RTL_IMR_TBDER) */
 
 	/*CCK Rates, TxHT = 0 */
 	RTL_RC_CCK_RATE1M,
@@ -481,6 +528,19 @@
 	eAcmWay2_SW = 2,
 };
 
+enum macphy_mode {
+	SINGLEMAC_SINGLEPHY = 0,
+	DUALMAC_DUALPHY,
+	DUALMAC_SINGLEPHY,
+};
+
+enum band_type {
+	BAND_ON_2_4G = 0,
+	BAND_ON_5G,
+	BAND_ON_BOTH,
+	BANDMAX
+};
+
 /*aci/aifsn Field.
 Ref: WMM spec 2.2.2: WME Parameter Element, p.12.*/
 union aci_aifsn {
@@ -505,6 +565,17 @@
 	WIRELESS_MODE_N_5G = 0x20
 };
 
+#define IS_WIRELESS_MODE_A(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_A)
+#define IS_WIRELESS_MODE_B(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_B)
+#define IS_WIRELESS_MODE_G(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_G)
+#define IS_WIRELESS_MODE_N_24G(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_N_24G)
+#define IS_WIRELESS_MODE_N_5G(wirelessmode)	\
+	(wirelessmode == WIRELESS_MODE_N_5G)
+
 enum ratr_table_mode {
 	RATR_INX_WIRELESS_NGB = 0,
 	RATR_INX_WIRELESS_NG = 1,
@@ -574,11 +645,11 @@
 struct rtl_led {
 	void *hw;
 	enum rtl_led_pin ledpin;
-	bool b_ledon;
+	bool ledon;
 };
 
 struct rtl_led_ctl {
-	bool bled_opendrain;
+	bool led_opendrain;
 	struct rtl_led sw_led0;
 	struct rtl_led sw_led1;
 };
@@ -603,6 +674,8 @@
 	u32 cnt_rate_illegal;
 	u32 cnt_crc8_fail;
 	u32 cnt_mcs_fail;
+	u32 cnt_fast_fsync_fail;
+	u32 cnt_sb_search_fail;
 	u32 cnt_ofdm_fail;
 	u32 cnt_cck_fail;
 	u32 cnt_all;
@@ -690,6 +763,32 @@
 	bool rfkill_state;	/*0 is off, 1 is on */
 };
 
+#define IQK_MATRIX_REG_NUM	8
+#define IQK_MATRIX_SETTINGS_NUM	(1 + 24 + 21)
+struct iqk_matrix_regs {
+	bool b_iqk_done;
+	long value[1][IQK_MATRIX_REG_NUM];
+};
+
+struct phy_parameters {
+	u16 length;
+	u32 *pdata;
+};
+
+enum hw_param_tab_index {
+	PHY_REG_2T,
+	PHY_REG_1T,
+	PHY_REG_PG,
+	RADIOA_2T,
+	RADIOB_2T,
+	RADIOA_1T,
+	RADIOB_1T,
+	MAC_REG,
+	AGCTAB_2T,
+	AGCTAB_1T,
+	MAX_TAB
+};
+
 struct rtl_phy {
 	struct bb_reg_def phyreg_def[4];	/*Radio A/B/C/D */
 	struct init_gain initgain_backup;
@@ -705,8 +804,9 @@
 	u8 current_channel;
 	u8 h2c_box_num;
 	u8 set_io_inprogress;
+	u8 lck_inprogress;
 
-	/*record for power tracking*/
+	/* record for power tracking */
 	s32 reg_e94;
 	s32 reg_e9c;
 	s32 reg_ea4;
@@ -723,26 +823,32 @@
 	u32 iqk_mac_backup[IQK_MAC_REG_NUM];
 	u32 iqk_bb_backup[10];
 
-	bool b_rfpi_enable;
+	/* Dual mac */
+	bool need_iqk;
+	struct iqk_matrix_regs iqk_matrix_regsetting[IQK_MATRIX_SETTINGS_NUM];
+
+	bool rfpi_enable;
 
 	u8 pwrgroup_cnt;
-	u8 bcck_high_power;
-	/* 3 groups of pwr diff by rates*/
-	u32 mcs_txpwrlevel_origoffset[4][16];
+	u8 cck_high_power;
+	/* MAX_PG_GROUP groups of pwr diff by rates */
+	u32 mcs_txpwrlevel_origoffset[MAX_PG_GROUP][16];
 	u8 default_initialgain[4];
 
-	/*the current Tx power level*/
+	/* the current Tx power level */
 	u8 cur_cck_txpwridx;
 	u8 cur_ofdm24g_txpwridx;
 
 	u32 rfreg_chnlval[2];
-	bool b_apk_done;
+	bool apk_done;
+	u32 reg_rf3c[2];	/* pathA / pathB  */
 
-	/*fsync*/
 	u8 framesync;
 	u32 framesync_c34;
 
 	u8 num_total_rfpath;
+	struct phy_parameters hwparam_tables[MAX_TAB];
+	u16 rf_pathmap;
 };
 
 #define MAX_TID_COUNT				9
@@ -768,6 +874,7 @@
 struct rtl_priv;
 struct rtl_io {
 	struct device *dev;
+	struct mutex bb_mutex;
 
 	/*PCI MEM map */
 	unsigned long pci_mem_end;	/*shared mem end        */
@@ -779,11 +886,14 @@
 	void (*write8_async) (struct rtl_priv *rtlpriv, u32 addr, u8 val);
 	void (*write16_async) (struct rtl_priv *rtlpriv, u32 addr, u16 val);
 	void (*write32_async) (struct rtl_priv *rtlpriv, u32 addr, u32 val);
+	int (*writeN_async) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			     u8 *pdata);
 
-	 u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
-	 u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
-	 u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
-
+	u8(*read8_sync) (struct rtl_priv *rtlpriv, u32 addr);
+	u16(*read16_sync) (struct rtl_priv *rtlpriv, u32 addr);
+	u32(*read32_sync) (struct rtl_priv *rtlpriv, u32 addr);
+	int (*readN_sync) (struct rtl_priv *rtlpriv, u32 addr, u16 len,
+			    u8 *pdata);
 };
 
 struct rtl_mac {
@@ -815,16 +925,24 @@
 	bool act_scanning;
 	u8 cnt_after_linked;
 
-	 /*RDG*/ bool rdg_en;
+	/* early mode */
+	/* skb wait queue */
+	struct sk_buff_head skb_waitq[MAX_TID_COUNT];
+	u8 earlymode_threshold;
 
-	 /*AP*/ u8 bssid[6];
-	u8 mcs[16];	/*16 bytes mcs for HT rates.*/
-	u32 basic_rates; /*b/g rates*/
+	/*RDG*/
+	bool rdg_en;
+
+	/*AP*/
+	u8 bssid[6];
+	u32 vendor;
+	u8 mcs[16];	/* 16 bytes mcs for HT rates. */
+	u32 basic_rates; /* b/g rates */
 	u8 ht_enable;
 	u8 sgi_40;
 	u8 sgi_20;
 	u8 bw_40;
-	u8 mode;		/*wireless mode*/
+	u8 mode;		/* wireless mode */
 	u8 slot_time;
 	u8 short_preamble;
 	u8 use_cts_protect;
@@ -835,9 +953,11 @@
 	u8 retry_long;
 	u16 assoc_id;
 
-	 /*IBSS*/ int beacon_interval;
+	/*IBSS*/
+	int beacon_interval;
 
-	 /*AMPDU*/ u8 min_space_cfg;	/*For Min spacing configurations */
+	/*AMPDU*/
+	u8 min_space_cfg;	/*For Min spacing configurations */
 	u8 max_mss_density;
 	u8 current_ampdu_factor;
 	u8 current_ampdu_density;
@@ -852,17 +972,54 @@
 
 	enum intf_type interface;
 	u16 hw_type;		/*92c or 92d or 92s and so on */
+	u8 ic_class;
 	u8 oem_id;
-	u8 version;		/*version of chip */
+	u32 version;		/*version of chip */
 	u8 state;		/*stop 0, start 1 */
 
 	/*firmware */
+	u32 fwsize;
 	u8 *pfirmware;
-	bool b_h2c_setinprogress;
+	u16 fw_version;
+	u16 fw_subversion;
+	bool h2c_setinprogress;
 	u8 last_hmeboxnum;
-	bool bfw_ready;
+	bool fw_ready;
 	/*Reserve page start offset except beacon in TxQ. */
 	u8 fw_rsvdpage_startoffset;
+	u8 h2c_txcmd_seq;
+
+	/* FW Cmd IO related */
+	u16 fwcmd_iomap;
+	u32 fwcmd_ioparam;
+	bool set_fwcmd_inprogress;
+	u8 current_fwcmd_io;
+
+	/**/
+	bool driver_going2unload;
+
+	/*AMPDU init min space*/
+	u8 minspace_cfg;	/*For Min spacing configurations */
+
+	/* Dual mac */
+	enum macphy_mode macphymode;
+	enum band_type current_bandtype;	/* 0:2.4G, 1:5G */
+	enum band_type current_bandtypebackup;
+	enum band_type bandset;
+	/* dual MAC 0--Mac0 1--Mac1 */
+	u32 interfaceindex;
+	/* just for DualMac S3S4 */
+	u8 macphyctl_reg;
+	bool earlymode_enable;
+	/* Dual mac*/
+	bool during_mac0init_radiob;
+	bool during_mac1init_radioa;
+	bool reloadtxpowerindex;
+	/* True if IMR or IQK  have done
+	for 2.4G in scan progress */
+	bool load_imrandiqk_setting_for2g;
+
+	bool disable_amsdu_8k;
 };
 
 struct rtl_security {
@@ -887,48 +1044,61 @@
 };
 
 struct rtl_dm {
-	/*PHY status for DM */
+	/*PHY status for Dynamic Management */
 	long entry_min_undecoratedsmoothed_pwdb;
 	long undecorated_smoothed_pwdb;	/*out dm */
 	long entry_max_undecoratedsmoothed_pwdb;
-	bool b_dm_initialgain_enable;
-	bool bdynamic_txpower_enable;
-	bool bcurrent_turbo_edca;
-	bool bis_any_nonbepkts;	/*out dm */
-	bool bis_cur_rdlstate;
-	bool btxpower_trackingInit;
-	bool b_disable_framebursting;
-	bool b_cck_inch14;
-	bool btxpower_tracking;
-	bool b_useramask;
-	bool brfpath_rxenable[4];
+	bool dm_initialgain_enable;
+	bool dynamic_txpower_enable;
+	bool current_turbo_edca;
+	bool is_any_nonbepkts;	/*out dm */
+	bool is_cur_rdlstate;
+	bool txpower_trackingInit;
+	bool disable_framebursting;
+	bool cck_inch14;
+	bool txpower_tracking;
+	bool useramask;
+	bool rfpath_rxenable[4];
+	bool inform_fw_driverctrldm;
+	bool current_mrc_switch;
+	u8 txpowercount;
 
+	u8 thermalvalue_rxgain;
 	u8 thermalvalue_iqk;
 	u8 thermalvalue_lck;
 	u8 thermalvalue;
 	u8 last_dtp_lvl;
+	u8 thermalvalue_avg[AVG_THERMAL_NUM];
+	u8 thermalvalue_avg_index;
+	bool done_txpower;
 	u8 dynamic_txhighpower_lvl;	/*Tx high power level */
-	u8 dm_flag;	/*Indicate if each dynamic mechanism's status. */
+	u8 dm_flag;		/*Indicate each dynamic mechanism's status. */
 	u8 dm_type;
 	u8 txpower_track_control;
-
+	bool interrupt_migration;
+	bool disable_tx_int;
 	char ofdm_index[2];
 	char cck_index;
+	u8 power_index_backup[6];
 };
 
-#define	EFUSE_MAX_LOGICAL_SIZE			 128
+#define	EFUSE_MAX_LOGICAL_SIZE			256
 
 struct rtl_efuse {
-	bool bautoLoad_ok;
+	bool autoLoad_ok;
 	bool bootfromefuse;
 	u16 max_physical_size;
-	u8 contents[EFUSE_MAX_LOGICAL_SIZE];
 
 	u8 efuse_map[2][EFUSE_MAX_LOGICAL_SIZE];
 	u16 efuse_usedbytes;
 	u8 efuse_usedpercentage;
+#ifdef EFUSE_REPG_WORKAROUND
+	bool efuse_re_pg_sec1flag;
+	u8 efuse_re_pg_data[8];
+#endif
 
 	u8 autoload_failflag;
+	u8 autoload_status;
 
 	short epromtype;
 	u16 eeprom_vid;
@@ -938,69 +1108,90 @@
 	u8 eeprom_oemid;
 	u16 eeprom_channelplan;
 	u8 eeprom_version;
+	u8 board_type;
+	u8 external_pa;
 
 	u8 dev_addr[6];
 
-	bool b_txpwr_fromeprom;
+	bool txpwr_fromeprom;
+	u8 eeprom_crystalcap;
 	u8 eeprom_tssi[2];
-	u8 eeprom_pwrlimit_ht20[3];
-	u8 eeprom_pwrlimit_ht40[3];
-	u8 eeprom_chnlarea_txpwr_cck[2][3];
-	u8 eeprom_chnlarea_txpwr_ht40_1s[2][3];
-	u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][3];
-	u8 txpwrlevel_cck[2][14];
-	u8 txpwrlevel_ht40_1s[2][14];	/*For HT 40MHZ pwr */
-	u8 txpwrlevel_ht40_2s[2][14];	/*For HT 40MHZ pwr */
+	u8 eeprom_tssi_5g[3][2]; /* for 5GL/5GM/5GH band. */
+	u8 eeprom_pwrlimit_ht20[CHANNEL_GROUP_MAX];
+	u8 eeprom_pwrlimit_ht40[CHANNEL_GROUP_MAX];
+	u8 eeprom_chnlarea_txpwr_cck[2][CHANNEL_GROUP_MAX_2G];
+	u8 eeprom_chnlarea_txpwr_ht40_1s[2][CHANNEL_GROUP_MAX];
+	u8 eeprom_chnlarea_txpwr_ht40_2sdiif[2][CHANNEL_GROUP_MAX];
+	u8 txpwrlevel_cck[2][CHANNEL_MAX_NUMBER_2G];
+	u8 txpwrlevel_ht40_1s[2][CHANNEL_MAX_NUMBER];	/*For HT 40MHZ pwr */
+	u8 txpwrlevel_ht40_2s[2][CHANNEL_MAX_NUMBER];	/*For HT 40MHZ pwr */
+
+	u8 internal_pa_5g[2];	/* pathA / pathB */
+	u8 eeprom_c9;
+	u8 eeprom_cc;
 
 	/*For power group */
-	u8 pwrgroup_ht20[2][14];
-	u8 pwrgroup_ht40[2][14];
+	u8 eeprom_pwrgroup[2][3];
+	u8 pwrgroup_ht20[2][CHANNEL_MAX_NUMBER];
+	u8 pwrgroup_ht40[2][CHANNEL_MAX_NUMBER];
 
-	char txpwr_ht20diff[2][14];	/*HT 20<->40 Pwr diff */
-	u8 txpwr_legacyhtdiff[2][14];	/*For HT<->legacy pwr diff */
+	char txpwr_ht20diff[2][CHANNEL_MAX_NUMBER]; /*HT 20<->40 Pwr diff */
+	/*For HT<->legacy pwr diff*/
+	u8 txpwr_legacyhtdiff[2][CHANNEL_MAX_NUMBER];
+	u8 txpwr_safetyflag;			/* Band edge enable flag */
+	u16 eeprom_txpowerdiff;
+	u8 legacy_httxpowerdiff;	/* Legacy to HT rate power diff */
+	u8 antenna_txpwdiff[3];
 
 	u8 eeprom_regulatory;
 	u8 eeprom_thermalmeter;
-	/*ThermalMeter, index 0 for RFIC0, and 1 for RFIC1 */
-	u8 thermalmeter[2];
+	u8 thermalmeter[2]; /*ThermalMeter, index 0 for RFIC0, 1 for RFIC1 */
+	u16 tssi_13dbm;
+	u8 crystalcap;		/* CrystalCap. */
+	u8 delta_iqk;
+	u8 delta_lck;
 
 	u8 legacy_ht_txpowerdiff;	/*Legacy to HT rate power diff */
-	bool b_apk_thermalmeterignore;
+	bool apk_thermalmeterignore;
+
+	bool b1x1_recvcombine;
+	bool b1ss_support;
+
+	/*channel plan */
+	u8 channel_plan;
 };
 
 struct rtl_ps_ctl {
+	bool pwrdomain_protect;
 	bool set_rfpowerstate_inprogress;
-	bool b_in_powersavemode;
+	bool in_powersavemode;
 	bool rfchange_inprogress;
-	bool b_swrf_processing;
-	bool b_hwradiooff;
-
-	u32 last_sleep_jiffies;
-	u32 last_awake_jiffies;
-	u32 last_delaylps_stamp_jiffies;
+	bool swrf_processing;
+	bool hwradiooff;
 
 	/*
 	 * just for PCIE ASPM
 	 * If it supports ASPM, Offset[560h] = 0x40,
 	 * otherwise Offset[560h] = 0x00.
 	 * */
-	bool b_support_aspm;
-	bool b_support_backdoor;
+	bool support_aspm;
+	bool support_backdoor;
 
 	/*for LPS */
 	enum rt_psmode dot11_psmode;	/*Power save mode configured. */
-	bool b_leisure_ps;
-	bool b_fwctrl_lps;
+	bool swctrl_lps;
+	bool leisure_ps;
+	bool fwctrl_lps;
 	u8 fwctrl_psmode;
 	/*For Fw control LPS mode */
-	u8 b_reg_fwctrl_lps;
+	u8 reg_fwctrl_lps;
 	/*Record Fw PS mode status. */
-	bool b_fw_current_inpsmode;
+	bool fw_current_inpsmode;
 	u8 reg_max_lps_awakeintvl;
 	bool report_linked;
 
 	/*for IPS */
-	bool b_inactiveps;
+	bool inactiveps;
 
 	u32 rfoff_reason;
 
@@ -1011,8 +1202,26 @@
 	/*just for PCIE ASPM */
 	u8 const_amdpci_aspm;
 
+	bool pwrdown_mode;
+
 	enum rf_pwrstate inactive_pwrstate;
 	enum rf_pwrstate rfpwr_state;	/*cur power state */
+
+	/* for SW LPS*/
+	bool sw_ps_enabled;
+	bool state;
+	bool state_inap;
+	bool multi_buffered;
+	u16 nullfunc_seq;
+	unsigned int dtim_counter;
+	unsigned int sleep_ms;
+	unsigned long last_sleep_jiffies;
+	unsigned long last_awake_jiffies;
+	unsigned long last_delaylps_stamp_jiffies;
+	unsigned long last_dtim;
+	unsigned long last_beacon;
+	unsigned long last_action;
+	unsigned long last_slept;
 };
 
 struct rtl_stats {
@@ -1038,10 +1247,10 @@
 	s32 recvsignalpower;
 	s8 rxpower;		/*in dBm Translate from PWdB */
 	u8 signalstrength;	/*in 0-100 index. */
-	u16 b_hwerror:1;
-	u16 b_crc:1;
-	u16 b_icv:1;
-	u16 b_shortpreamble:1;
+	u16 hwerror:1;
+	u16 crc:1;
+	u16 icv:1;
+	u16 shortpreamble:1;
 	u16 antenna:1;
 	u16 decrypted:1;
 	u16 wakeup:1;
@@ -1050,15 +1259,16 @@
 
 	u8 rx_drvinfo_size;
 	u8 rx_bufshift;
-	bool b_isampdu;
+	bool isampdu;
+	bool isfirst_ampdu;
 	bool rx_is40Mhzpacket;
 	u32 rx_pwdb_all;
 	u8 rx_mimo_signalstrength[4];	/*in 0~100 index */
 	s8 rx_mimo_signalquality[2];
-	bool b_packet_matchbssid;
-	bool b_is_cck;
-	bool b_packet_toself;
-	bool b_packet_beacon;	/*for rssi */
+	bool packet_matchbssid;
+	bool is_cck;
+	bool packet_toself;
+	bool packet_beacon;	/*for rssi */
 	char cck_adc_pwdb[4];	/*for rx path selection */
 };
 
@@ -1069,23 +1279,23 @@
 	u32 num_tx_inperiod;
 	u32 num_rx_inperiod;
 
-	bool b_busytraffic;
-	bool b_higher_busytraffic;
-	bool b_higher_busyrxtraffic;
+	bool busytraffic;
+	bool higher_busytraffic;
+	bool higher_busyrxtraffic;
 };
 
 struct rtl_tcb_desc {
-	u8 b_packet_bw:1;
-	u8 b_multicast:1;
-	u8 b_broadcast:1;
+	u8 packet_bw:1;
+	u8 multicast:1;
+	u8 broadcast:1;
 
-	u8 b_rts_stbc:1;
-	u8 b_rts_enable:1;
-	u8 b_cts_enable:1;
-	u8 b_rts_use_shortpreamble:1;
-	u8 b_rts_use_shortgi:1;
+	u8 rts_stbc:1;
+	u8 rts_enable:1;
+	u8 cts_enable:1;
+	u8 rts_use_shortpreamble:1;
+	u8 rts_use_shortgi:1;
 	u8 rts_sc:1;
-	u8 b_rts_bw:1;
+	u8 rts_bw:1;
 	u8 rts_rate;
 
 	u8 use_shortgi:1;
@@ -1096,20 +1306,34 @@
 	u8 ratr_index;
 	u8 mac_id;
 	u8 hw_rate;
+
+	u8 last_inipkt:1;
+	u8 cmd_or_init:1;
+	u8 queue_index;
+
+	/* early mode */
+	u8 empkt_num;
+	/* The max value by HW */
+	u32 empkt_len[5];
 };
 
 struct rtl_hal_ops {
 	int (*init_sw_vars) (struct ieee80211_hw *hw);
 	void (*deinit_sw_vars) (struct ieee80211_hw *hw);
+	void (*read_chip_version)(struct ieee80211_hw *hw);
 	void (*read_eeprom_info) (struct ieee80211_hw *hw);
 	void (*interrupt_recognized) (struct ieee80211_hw *hw,
 				      u32 *p_inta, u32 *p_intb);
 	int (*hw_init) (struct ieee80211_hw *hw);
 	void (*hw_disable) (struct ieee80211_hw *hw);
+	void (*hw_suspend) (struct ieee80211_hw *hw);
+	void (*hw_resume) (struct ieee80211_hw *hw);
 	void (*enable_interrupt) (struct ieee80211_hw *hw);
 	void (*disable_interrupt) (struct ieee80211_hw *hw);
 	int (*set_network_type) (struct ieee80211_hw *hw,
 				 enum nl80211_iftype type);
+	void (*set_chk_bssid)(struct ieee80211_hw *hw,
+				bool check_bssid);
 	void (*set_bw_mode) (struct ieee80211_hw *hw,
 			     enum nl80211_channel_type ch_type);
 	 u8(*switch_channel) (struct ieee80211_hw *hw);
@@ -1126,23 +1350,26 @@
 			      struct ieee80211_hdr *hdr, u8 *pdesc_tx,
 			      struct ieee80211_tx_info *info,
 			      struct sk_buff *skb, unsigned int queue_index);
+	void (*fill_fake_txdesc) (struct ieee80211_hw *hw, u8 * pDesc,
+				  u32 buffer_len, bool bIsPsPoll);
 	void (*fill_tx_cmddesc) (struct ieee80211_hw *hw, u8 *pdesc,
-				 bool b_firstseg, bool b_lastseg,
+				 bool firstseg, bool lastseg,
 				 struct sk_buff *skb);
-	 bool(*query_rx_desc) (struct ieee80211_hw *hw,
+	bool (*cmd_send_packet)(struct ieee80211_hw *hw, struct sk_buff *skb);
+	bool (*query_rx_desc) (struct ieee80211_hw *hw,
 			       struct rtl_stats *stats,
 			       struct ieee80211_rx_status *rx_status,
 			       u8 *pdesc, struct sk_buff *skb);
 	void (*set_channel_access) (struct ieee80211_hw *hw);
-	 bool(*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid);
+	bool (*radio_onoff_checking) (struct ieee80211_hw *hw, u8 *valid);
 	void (*dm_watchdog) (struct ieee80211_hw *hw);
 	void (*scan_operation_backup) (struct ieee80211_hw *hw, u8 operation);
-	 bool(*set_rf_power_state) (struct ieee80211_hw *hw,
+	bool (*set_rf_power_state) (struct ieee80211_hw *hw,
 				    enum rf_pwrstate rfpwr_state);
 	void (*led_control) (struct ieee80211_hw *hw,
 			     enum led_ctl_mode ledaction);
 	void (*set_desc) (u8 *pdesc, bool istx, u8 desc_name, u8 *val);
-	 u32(*get_desc) (u8 *pdesc, bool istx, u8 desc_name);
+	u32 (*get_desc) (u8 *pdesc, bool istx, u8 desc_name);
 	void (*tx_polling) (struct ieee80211_hw *hw, unsigned int hw_queue);
 	void (*enable_hw_sec) (struct ieee80211_hw *hw);
 	void (*set_key) (struct ieee80211_hw *hw, u32 key_index,
@@ -1150,22 +1377,36 @@
 			 bool is_wepkey, bool clear_all);
 	void (*init_sw_leds) (struct ieee80211_hw *hw);
 	void (*deinit_sw_leds) (struct ieee80211_hw *hw);
-	 u32(*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
+	u32 (*get_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask);
 	void (*set_bbreg) (struct ieee80211_hw *hw, u32 regaddr, u32 bitmask,
 			   u32 data);
-	 u32(*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
+	u32 (*get_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
 			  u32 regaddr, u32 bitmask);
 	void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
 			   u32 regaddr, u32 bitmask, u32 data);
+	bool (*phy_rf6052_config) (struct ieee80211_hw *hw);
+	void (*phy_rf6052_set_cck_txpower) (struct ieee80211_hw *hw,
+					    u8 *powerlevel);
+	void (*phy_rf6052_set_ofdm_txpower) (struct ieee80211_hw *hw,
+					     u8 *ppowerlevel, u8 channel);
+	bool (*config_bb_with_headerfile) (struct ieee80211_hw *hw,
+					   u8 configtype);
+	bool (*config_bb_with_pgheaderfile) (struct ieee80211_hw *hw,
+					     u8 configtype);
+	void (*phy_lc_calibrate) (struct ieee80211_hw *hw, bool is2t);
+	void (*phy_set_bw_mode_callback) (struct ieee80211_hw *hw);
+	void (*dm_dynamic_txpower) (struct ieee80211_hw *hw);
 };
 
 struct rtl_intf_ops {
 	/*com */
+	void (*read_efuse_byte)(struct ieee80211_hw *hw, u16 _offset, u8 *pbuf);
 	int (*adapter_start) (struct ieee80211_hw *hw);
 	void (*adapter_stop) (struct ieee80211_hw *hw);
 
 	int (*adapter_tx) (struct ieee80211_hw *hw, struct sk_buff *skb);
 	int (*reset_trx_ring) (struct ieee80211_hw *hw);
+	bool (*waitq_insert) (struct ieee80211_hw *hw, struct sk_buff *skb);
 
 	/*pci */
 	void (*disable_aspm) (struct ieee80211_hw *hw);
@@ -1179,11 +1420,36 @@
 	int sw_crypto;
 };
 
+struct rtl_hal_usbint_cfg {
+	/* data - rx */
+	u32 in_ep_num;
+	u32 rx_urb_num;
+	u32 rx_max_size;
+
+	/* op - rx */
+	void (*usb_rx_hdl)(struct ieee80211_hw *, struct sk_buff *);
+	void (*usb_rx_segregate_hdl)(struct ieee80211_hw *, struct sk_buff *,
+				     struct sk_buff_head *);
+
+	/* tx */
+	void (*usb_tx_cleanup)(struct ieee80211_hw *, struct sk_buff *);
+	int (*usb_tx_post_hdl)(struct ieee80211_hw *, struct urb *,
+			       struct sk_buff *);
+	struct sk_buff *(*usb_tx_aggregate_hdl)(struct ieee80211_hw *,
+						struct sk_buff_head *);
+
+	/* endpoint mapping */
+	int (*usb_endpoint_mapping)(struct ieee80211_hw *hw);
+	u16 (*usb_mq_to_hwq)(__le16 fc, u16 mac80211_queue_index);
+};
+
 struct rtl_hal_cfg {
+	u8 bar_id;
 	char *name;
 	char *fw_name;
 	struct rtl_hal_ops *ops;
 	struct rtl_mod_params *mod_params;
+	struct rtl_hal_usbint_cfg *usb_interface_cfg;
 
 	/*this map used for some registers or vars
 	   defined int HAL but used in MAIN */
@@ -1202,6 +1468,11 @@
 	spinlock_t rf_ps_lock;
 	spinlock_t rf_lock;
 	spinlock_t lps_lock;
+	spinlock_t waitq_lock;
+	spinlock_t tx_urb_lock;
+
+	/*Dual mac*/
+	spinlock_t cck_and_rw_pagea_lock;
 };
 
 struct rtl_works {
@@ -1218,12 +1489,20 @@
 	struct workqueue_struct *rtl_wq;
 	struct delayed_work watchdog_wq;
 	struct delayed_work ips_nic_off_wq;
+
+	/* For SW LPS */
+	struct delayed_work ps_work;
+	struct delayed_work ps_rfon_wq;
 };
 
 struct rtl_debug {
 	u32 dbgp_type[DBGP_TYPE_MAX];
 	u32 global_debuglevel;
 	u64 global_debugcomponents;
+
+	/* add for proc debug */
+	struct proc_dir_entry *proc_dir;
+	char proc_name[20];
 };
 
 struct rtl_priv {
@@ -1274,6 +1553,91 @@
 #define rtl_efuse(rtlpriv)	(&((rtlpriv)->efuse))
 #define rtl_psc(rtlpriv)	(&((rtlpriv)->psc))
 
+
+/***************************************
+    Bluetooth Co-existence Related
+****************************************/
+
+enum bt_ant_num {
+	ANT_X2 = 0,
+	ANT_X1 = 1,
+};
+
+enum bt_co_type {
+	BT_2WIRE = 0,
+	BT_ISSC_3WIRE = 1,
+	BT_ACCEL = 2,
+	BT_CSR_BC4 = 3,
+	BT_CSR_BC8 = 4,
+	BT_RTL8756 = 5,
+};
+
+enum bt_cur_state {
+	BT_OFF = 0,
+	BT_ON = 1,
+};
+
+enum bt_service_type {
+	BT_SCO = 0,
+	BT_A2DP = 1,
+	BT_HID = 2,
+	BT_HID_IDLE = 3,
+	BT_SCAN = 4,
+	BT_IDLE = 5,
+	BT_OTHER_ACTION = 6,
+	BT_BUSY = 7,
+	BT_OTHERBUSY = 8,
+	BT_PAN = 9,
+};
+
+enum bt_radio_shared {
+	BT_RADIO_SHARED = 0,
+	BT_RADIO_INDIVIDUAL = 1,
+};
+
+struct bt_coexist_info {
+
+	/* EEPROM BT info. */
+	u8 eeprom_bt_coexist;
+	u8 eeprom_bt_type;
+	u8 eeprom_bt_ant_num;
+	u8 eeprom_bt_ant_isolation;
+	u8 eeprom_bt_radio_shared;
+
+	u8 bt_coexistence;
+	u8 bt_ant_num;
+	u8 bt_coexist_type;
+	u8 bt_state;
+	u8 bt_cur_state;	/* 0:on, 1:off */
+	u8 bt_ant_isolation;	/* 0:good, 1:bad */
+	u8 bt_pape_ctrl;	/* 0:SW, 1:SW/HW dynamic */
+	u8 bt_service;
+	u8 bt_radio_shared_type;
+	u8 bt_rfreg_origin_1e;
+	u8 bt_rfreg_origin_1f;
+	u8 bt_rssi_state;
+	u32 ratio_tx;
+	u32 ratio_pri;
+	u32 bt_edca_ul;
+	u32 bt_edca_dl;
+
+	bool b_init_set;
+	bool b_bt_busy_traffic;
+	bool b_bt_traffic_mode_set;
+	bool b_bt_non_traffic_mode_set;
+
+	bool b_fw_coexist_all_off;
+	bool b_sw_coexist_all_off;
+	u32 current_state;
+	u32 previous_state;
+	u8 bt_pre_rssi_state;
+
+	u8 b_reg_bt_iso;
+	u8 b_reg_bt_sco;
+
+};
+
+
 /****************************************
 	mem access macro define start
 	Call endian free function when
@@ -1281,7 +1645,7 @@
 	2. Before write integer to IO.
 	3. After read integer from IO.
 ****************************************/
-/* Convert little data endian to host */
+/* Convert little data endian to host ordering */
 #define EF1BYTE(_val)		\
 	((u8)(_val))
 #define EF2BYTE(_val)		\
@@ -1289,27 +1653,21 @@
 #define EF4BYTE(_val)		\
 	(le32_to_cpu(_val))
 
-/* Read data from memory */
-#define READEF1BYTE(_ptr)	\
-	EF1BYTE(*((u8 *)(_ptr)))
+/* Read le16 data from memory and convert to host ordering */
 #define READEF2BYTE(_ptr)	\
 	EF2BYTE(*((u16 *)(_ptr)))
-#define READEF4BYTE(_ptr)	\
-	EF4BYTE(*((u32 *)(_ptr)))
 
-/* Write data to memory */
-#define WRITEEF1BYTE(_ptr, _val)	\
-	(*((u8 *)(_ptr))) = EF1BYTE(_val)
+/* Write le16 data to memory in host ordering */
 #define WRITEEF2BYTE(_ptr, _val)	\
 	(*((u16 *)(_ptr))) = EF2BYTE(_val)
-#define WRITEEF4BYTE(_ptr, _val)	\
-	(*((u32 *)(_ptr))) = EF4BYTE(_val)
 
-/*Example:
-BIT_LEN_MASK_32(0) => 0x00000000
-BIT_LEN_MASK_32(1) => 0x00000001
-BIT_LEN_MASK_32(2) => 0x00000003
-BIT_LEN_MASK_32(32) => 0xFFFFFFFF*/
+/* Create a bit mask
+ * Examples:
+ * BIT_LEN_MASK_32(0) => 0x00000000
+ * BIT_LEN_MASK_32(1) => 0x00000001
+ * BIT_LEN_MASK_32(2) => 0x00000003
+ * BIT_LEN_MASK_32(32) => 0xFFFFFFFF
+ */
 #define BIT_LEN_MASK_32(__bitlen)	 \
 	(0xFFFFFFFF >> (32 - (__bitlen)))
 #define BIT_LEN_MASK_16(__bitlen)	 \
@@ -1317,9 +1675,11 @@
 #define BIT_LEN_MASK_8(__bitlen) \
 	(0xFF >> (8 - (__bitlen)))
 
-/*Example:
-BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
-BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000*/
+/* Create an offset bit mask
+ * Examples:
+ * BIT_OFFSET_LEN_MASK_32(0, 2) => 0x00000003
+ * BIT_OFFSET_LEN_MASK_32(16, 2) => 0x00030000
+ */
 #define BIT_OFFSET_LEN_MASK_32(__bitoffset, __bitlen) \
 	(BIT_LEN_MASK_32(__bitlen) << (__bitoffset))
 #define BIT_OFFSET_LEN_MASK_16(__bitoffset, __bitlen) \
@@ -1328,8 +1688,9 @@
 	(BIT_LEN_MASK_8(__bitlen) << (__bitoffset))
 
 /*Description:
-Return 4-byte value in host byte ordering from
-4-byte pointer in little-endian system.*/
+ * Return 4-byte value in host byte ordering from
+ * 4-byte pointer in little-endian system.
+ */
 #define LE_P4BYTE_TO_HOST_4BYTE(__pstart) \
 	(EF4BYTE(*((u32 *)(__pstart))))
 #define LE_P2BYTE_TO_HOST_2BYTE(__pstart) \
@@ -1337,28 +1698,10 @@
 #define LE_P1BYTE_TO_HOST_1BYTE(__pstart) \
 	(EF1BYTE(*((u8 *)(__pstart))))
 
-/*Description:
-Translate subfield (continuous bits in little-endian) of 4-byte
-value to host byte ordering.*/
-#define LE_BITS_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
-	( \
-		(LE_P4BYTE_TO_HOST_4BYTE(__pstart) >> (__bitoffset))  & \
-		BIT_LEN_MASK_32(__bitlen) \
-	)
-#define LE_BITS_TO_2BYTE(__pstart, __bitoffset, __bitlen) \
-	( \
-		(LE_P2BYTE_TO_HOST_2BYTE(__pstart) >> (__bitoffset)) & \
-		BIT_LEN_MASK_16(__bitlen) \
-	)
-#define LE_BITS_TO_1BYTE(__pstart, __bitoffset, __bitlen) \
-	( \
-		(LE_P1BYTE_TO_HOST_1BYTE(__pstart) >> (__bitoffset)) & \
-		BIT_LEN_MASK_8(__bitlen) \
-	)
-
-/*Description:
-Mask subfield (continuous bits in little-endian) of 4-byte value
-and return the result in 4-byte value in host byte ordering.*/
+/* Description:
+ * Mask subfield (continuous bits in little-endian) of 4-byte value
+ * and return the result in 4-byte value in host byte ordering.
+ */
 #define LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) \
 	( \
 		LE_P4BYTE_TO_HOST_4BYTE(__pstart)  & \
@@ -1375,20 +1718,9 @@
 		(~BIT_OFFSET_LEN_MASK_8(__bitoffset, __bitlen)) \
 	)
 
-/*Description:
-Set subfield of little-endian 4-byte value to specified value.	*/
-#define SET_BITS_TO_LE_4BYTE(__pstart, __bitoffset, __bitlen, __val) \
-	*((u32 *)(__pstart)) = EF4BYTE \
-	( \
-		LE_BITS_CLEARED_TO_4BYTE(__pstart, __bitoffset, __bitlen) | \
-		((((u32)__val) & BIT_LEN_MASK_32(__bitlen)) << (__bitoffset)) \
-	);
-#define SET_BITS_TO_LE_2BYTE(__pstart, __bitoffset, __bitlen, __val) \
-	*((u16 *)(__pstart)) = EF2BYTE \
-	( \
-		LE_BITS_CLEARED_TO_2BYTE(__pstart, __bitoffset, __bitlen) | \
-		((((u16)__val) & BIT_LEN_MASK_16(__bitlen)) << (__bitoffset)) \
-	);
+/* Description:
+ * Set subfield of little-endian 4-byte value to specified value.
+ */
 #define SET_BITS_TO_LE_1BYTE(__pstart, __bitoffset, __bitlen, __val) \
 	*((u8 *)(__pstart)) = EF1BYTE \
 	( \
@@ -1400,13 +1732,14 @@
 	mem access macro define end
 ****************************************/
 
-#define packet_get_type(_packet) (EF1BYTE((_packet).octet[0]) & 0xFC)
+#define byte(x, n) ((x >> (8 * n)) & 0xff)
+
 #define RTL_WATCH_DOG_TIME	2000
 #define MSECS(t)		msecs_to_jiffies(t)
-#define WLAN_FC_GET_VERS(fc)	((fc) & IEEE80211_FCTL_VERS)
-#define WLAN_FC_GET_TYPE(fc)	((fc) & IEEE80211_FCTL_FTYPE)
-#define WLAN_FC_GET_STYPE(fc)	((fc) & IEEE80211_FCTL_STYPE)
-#define WLAN_FC_MORE_DATA(fc)	((fc) & IEEE80211_FCTL_MOREDATA)
+#define WLAN_FC_GET_VERS(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_VERS)
+#define WLAN_FC_GET_TYPE(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE)
+#define WLAN_FC_GET_STYPE(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_STYPE)
+#define WLAN_FC_MORE_DATA(fc)	(le16_to_cpu(fc) & IEEE80211_FCTL_MOREDATA)
 #define SEQ_TO_SN(seq)		(((seq) & IEEE80211_SCTL_SEQ) >> 4)
 #define SN_TO_SEQ(ssn)		(((ssn) << 4) & IEEE80211_SCTL_SEQ)
 #define MAX_SN			((IEEE80211_SCTL_SEQ) >> 4)
@@ -1420,6 +1753,8 @@
 #define	RT_RF_OFF_LEVL_FW_32K		BIT(5)	/*FW in 32k */
 /*Always enable ASPM and Clock Req in initialization.*/
 #define	RT_RF_PS_LEVEL_ALWAYS_ASPM	BIT(6)
+/* no matter RFOFF or SLEEP we set PS_ASPM_LEVL*/
+#define	RT_PS_LEVEL_ASPM		BIT(7)
 /*When LPS is on, disable 2R if no packet is received or transmittd.*/
 #define	RT_RF_LPS_DISALBE_2R		BIT(30)
 #define	RT_RF_LPS_LEVEL_ASPM		BIT(31)	/*LPS with ASPM */
@@ -1433,15 +1768,6 @@
 #define container_of_dwork_rtl(x, y, z) \
 	container_of(container_of(x, struct delayed_work, work), y, z)
 
-#define FILL_OCTET_STRING(_os, _octet, _len)	\
-		(_os).octet = (u8 *)(_octet);		\
-		(_os).length = (_len);
-
-#define CP_MACADDR(des, src)	\
-	((des)[0] = (src)[0], (des)[1] = (src)[1],\
-	(des)[2] = (src)[2], (des)[3] = (src)[3],\
-	(des)[4] = (src)[4], (des)[5] = (src)[5])
-
 static inline u8 rtl_read_byte(struct rtl_priv *rtlpriv, u32 addr)
 {
 	return rtlpriv->io.read8_sync(rtlpriv, addr);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/acx.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/acx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/acx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/acx.c	2011-05-19 00:06:34.000000000 -0400
@@ -776,6 +776,31 @@
 	return ret;
 }
 
+int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
+			u8 depth, enum wl1251_acx_low_rssi_type type)
+{
+	struct acx_low_rssi *rssi;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx low rssi");
+
+	rssi = kzalloc(sizeof(*rssi), GFP_KERNEL);
+	if (!rssi)
+		return -ENOMEM;
+
+	rssi->threshold = threshold;
+	rssi->weight = weight;
+	rssi->depth = depth;
+	rssi->type = type;
+
+	ret = wl1251_cmd_configure(wl, ACX_LOW_RSSI, rssi, sizeof(*rssi));
+	if (ret < 0)
+		wl1251_warning("failed to set low rssi threshold: %d", ret);
+
+	kfree(rssi);
+	return ret;
+}
+
 int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble)
 {
 	struct acx_preamble *acx;
@@ -973,6 +998,34 @@
 		goto out;
 	}
 
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
+			  u8 max_consecutive)
+{
+	struct wl1251_acx_bet_enable *acx;
+	int ret;
+
+	wl1251_debug(DEBUG_ACX, "acx bet enable");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->enable = mode;
+	acx->max_consecutive = max_consecutive;
+
+	ret = wl1251_cmd_configure(wl, ACX_BET_ENABLE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1251_warning("wl1251 acx bet enable failed: %d", ret);
+		goto out;
+	}
+
 out:
 	kfree(acx);
 	return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/acx.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/acx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/acx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/acx.h	2011-05-19 00:06:34.000000000 -0400
@@ -399,6 +399,49 @@
 	u8 pad[2];
 } __packed;
 
+enum wl1251_acx_low_rssi_type {
+	/*
+	 * The event is a "Level" indication which keeps triggering
+	 * as long as the average RSSI is below the threshold.
+	 */
+	WL1251_ACX_LOW_RSSI_TYPE_LEVEL = 0,
+
+	/*
+	 * The event is an "Edge" indication which triggers
+	 * only when the RSSI threshold is crossed from above.
+	 */
+	WL1251_ACX_LOW_RSSI_TYPE_EDGE = 1,
+};
+
+struct acx_low_rssi {
+	struct acx_header header;
+
+	/*
+	 * The threshold (in dBm) below (or above after low rssi
+	 * indication) which the firmware generates an interrupt to the
+	 * host. This parameter is signed.
+	 */
+	s8 threshold;
+
+	/*
+	 * The weight of the current RSSI sample, before adding the new
+	 * sample, that is used to calculate the average RSSI.
+	 */
+	u8 weight;
+
+	/*
+	 * The number of Beacons/Probe response frames that will be
+	 * received before issuing the Low or Regained RSSI event.
+	 */
+	u8 depth;
+
+	/*
+	 * Configures how the Low RSSI Event is triggered. Refer to
+	 * enum wl1251_acx_low_rssi_type for more.
+	 */
+	u8 type;
+} __packed;
+
 struct acx_beacon_filter_option {
 	struct acx_header header;
 
@@ -1164,6 +1207,31 @@
 	u8  padding;
 } __packed;
 
+enum wl1251_acx_bet_mode {
+	WL1251_ACX_BET_DISABLE = 0,
+	WL1251_ACX_BET_ENABLE = 1,
+};
+
+struct wl1251_acx_bet_enable {
+	struct acx_header header;
+
+	/*
+	 * Specifies if beacon early termination procedure is enabled or
+	 * disabled, see enum wl1251_acx_bet_mode.
+	 */
+	u8 enable;
+
+	/*
+	 * Specifies the maximum number of consecutive beacons that may be
+	 * early terminated. After this number is reached at least one full
+	 * beacon must be correctly received in FW before beacon ET
+	 * resumes. Range 0 - 255.
+	 */
+	u8 max_consecutive;
+
+	u8 padding[2];
+} __packed;
+
 struct wl1251_acx_ac_cfg {
 	struct acx_header header;
 
@@ -1393,6 +1461,8 @@
 int wl1251_acx_bcn_dtim_options(struct wl1251 *wl);
 int wl1251_acx_aid(struct wl1251 *wl, u16 aid);
 int wl1251_acx_event_mbox_mask(struct wl1251 *wl, u32 event_mask);
+int wl1251_acx_low_rssi(struct wl1251 *wl, s8 threshold, u8 weight,
+			u8 depth, enum wl1251_acx_low_rssi_type type);
 int wl1251_acx_set_preamble(struct wl1251 *wl, enum acx_preamble_type preamble);
 int wl1251_acx_cts_protect(struct wl1251 *wl,
 			    enum acx_ctsprotect_type ctsprotect);
@@ -1401,6 +1471,8 @@
 int wl1251_acx_rate_policies(struct wl1251 *wl);
 int wl1251_acx_mem_cfg(struct wl1251 *wl);
 int wl1251_acx_wr_tbtt_and_dtim(struct wl1251 *wl, u16 tbtt, u8 dtim);
+int wl1251_acx_bet_enable(struct wl1251 *wl, enum wl1251_acx_bet_mode mode,
+			  u8 max_consecutive);
 int wl1251_acx_ac_cfg(struct wl1251 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifs, u16 txop);
 int wl1251_acx_tid_cfg(struct wl1251 *wl, u8 queue,
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/cmd.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/cmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/cmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -104,7 +104,7 @@
  * @wl: wl struct
  * @id: acx id
  * @buf: buffer for the response, including all headers, must work with dma
- * @len: lenght of buf
+ * @len: length of buf
  */
 int wl1251_cmd_interrogate(struct wl1251 *wl, u16 id, void *buf, size_t len)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/event.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/event.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/event.c	2011-05-19 00:06:34.000000000 -0400
@@ -90,6 +90,24 @@
 		}
 	}
 
+	if (wl->vif && wl->rssi_thold) {
+		if (vector & ROAMING_TRIGGER_LOW_RSSI_EVENT_ID) {
+			wl1251_debug(DEBUG_EVENT,
+				     "ROAMING_TRIGGER_LOW_RSSI_EVENT");
+			ieee80211_cqm_rssi_notify(wl->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW,
+				GFP_KERNEL);
+		}
+
+		if (vector & ROAMING_TRIGGER_REGAINED_RSSI_EVENT_ID) {
+			wl1251_debug(DEBUG_EVENT,
+				     "ROAMING_TRIGGER_REGAINED_RSSI_EVENT");
+			ieee80211_cqm_rssi_notify(wl->vif,
+				NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH,
+				GFP_KERNEL);
+		}
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/main.c	2012-03-24 01:15:22.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/main.c	2012-03-24 03:34:51.000000000 -0400
@@ -375,7 +375,7 @@
 	mutex_unlock(&wl->mutex);
 }
 
-static int wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void wl1251_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1251 *wl = hw->priv;
 	unsigned long flags;
@@ -401,8 +401,6 @@
 		wl->tx_queue_stopped = true;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
-
-	return NETDEV_TX_OK;
 }
 
 static int wl1251_op_start(struct ieee80211_hw *hw)
@@ -502,6 +500,7 @@
 	wl->psm = 0;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+	wl->rssi_thold = 0;
 	wl->channel = WL1251_DEFAULT_CHANNEL;
 
 	wl1251_debugfs_reset(wl);
@@ -959,6 +958,16 @@
 	if (ret < 0)
 		goto out;
 
+	if (changed & BSS_CHANGED_CQM) {
+		ret = wl1251_acx_low_rssi(wl, bss_conf->cqm_rssi_thold,
+					  WL1251_DEFAULT_LOW_RSSI_WEIGHT,
+					  WL1251_DEFAULT_LOW_RSSI_DEPTH,
+					  WL1251_ACX_LOW_RSSI_TYPE_EDGE);
+		if (ret < 0)
+			goto out;
+		wl->rssi_thold = bss_conf->cqm_rssi_thold;
+	}
+
 	if (changed & BSS_CHANGED_BSSID) {
 		memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
 
@@ -1313,9 +1322,11 @@
 	wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
 		IEEE80211_HW_SUPPORTS_PS |
 		IEEE80211_HW_BEACON_FILTER |
-		IEEE80211_HW_SUPPORTS_UAPSD;
+		IEEE80211_HW_SUPPORTS_UAPSD |
+		IEEE80211_HW_SUPPORTS_CQM_RSSI;
 
-	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
+	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+					 BIT(NL80211_IFTYPE_ADHOC);
 	wl->hw->wiphy->max_scan_ssids = 1;
 	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1251_band_2ghz;
 
@@ -1377,6 +1388,7 @@
 	wl->psm_requested = false;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
+	wl->rssi_thold = 0;
 	wl->beacon_int = WL1251_DEFAULT_BEACON_INT;
 	wl->dtim_period = WL1251_DEFAULT_DTIM_PERIOD;
 	wl->vif = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/ps.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/ps.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/ps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/ps.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,7 +58,6 @@
 	unsigned long delay;
 
 	if (wl->psm) {
-		cancel_delayed_work(&wl->elp_work);
 		delay = msecs_to_jiffies(ELP_ENTRY_DELAY);
 		ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
 	}
@@ -69,6 +68,9 @@
 	unsigned long timeout, start;
 	u32 elp_reg;
 
+	if (delayed_work_pending(&wl->elp_work))
+		cancel_delayed_work(&wl->elp_work);
+
 	if (!wl->elp)
 		return 0;
 
@@ -102,38 +104,6 @@
 	return 0;
 }
 
-static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable)
-{
-	int ret;
-
-	if (enable) {
-		wl1251_debug(DEBUG_PSM, "sleep auth psm/elp");
-
-		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
-		if (ret < 0)
-			return ret;
-
-		wl1251_ps_elp_sleep(wl);
-	} else {
-		wl1251_debug(DEBUG_PSM, "sleep auth cam");
-
-		/*
-		 * When the target is in ELP, we can only
-		 * access the ELP control register. Thus,
-		 * we have to wake the target up before
-		 * changing the power authorization.
-		 */
-
-		wl1251_ps_elp_wakeup(wl);
-
-		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
-		if (ret < 0)
-			return ret;
-	}
-
-	return 0;
-}
-
 int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 {
 	int ret;
@@ -153,11 +123,16 @@
 		if (ret < 0)
 			return ret;
 
+		ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_ENABLE,
+					    WL1251_DEFAULT_BET_CONSECUTIVE);
+		if (ret < 0)
+			return ret;
+
 		ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
 
-		ret = wl1251_ps_set_elp(wl, true);
+		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
 		if (ret < 0)
 			return ret;
 
@@ -166,7 +141,14 @@
 	case STATION_ACTIVE_MODE:
 	default:
 		wl1251_debug(DEBUG_PSM, "leaving psm");
-		ret = wl1251_ps_set_elp(wl, false);
+
+		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
+		if (ret < 0)
+			return ret;
+
+		/* disable BET */
+		ret = wl1251_acx_bet_enable(wl, WL1251_ACX_BET_DISABLE,
+					    WL1251_DEFAULT_BET_CONSECUTIVE);
 		if (ret < 0)
 			return ret;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,9 +78,10 @@
 	 */
 	wl->noise = desc->rssi - desc->snr / 2;
 
-	status->freq = ieee80211_channel_to_frequency(desc->channel);
+	status->freq = ieee80211_channel_to_frequency(desc->channel,
+						      status->band);
 
-	status->flag |= RX_FLAG_TSFT;
+	status->flag |= RX_FLAG_MACTIME_MPDU;
 
 	if (desc->flags & RX_DESC_ENCRYPTION_MASK) {
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -95,8 +96,52 @@
 	if (unlikely(!(desc->flags & RX_DESC_VALID_FCS)))
 		status->flag |= RX_FLAG_FAILED_FCS_CRC;
 
+	switch (desc->rate) {
+		/* skip 1 and 12 Mbps because they have same value 0x0a */
+	case RATE_2MBPS:
+		status->rate_idx = 1;
+		break;
+	case RATE_5_5MBPS:
+		status->rate_idx = 2;
+		break;
+	case RATE_11MBPS:
+		status->rate_idx = 3;
+		break;
+	case RATE_6MBPS:
+		status->rate_idx = 4;
+		break;
+	case RATE_9MBPS:
+		status->rate_idx = 5;
+		break;
+	case RATE_18MBPS:
+		status->rate_idx = 7;
+		break;
+	case RATE_24MBPS:
+		status->rate_idx = 8;
+		break;
+	case RATE_36MBPS:
+		status->rate_idx = 9;
+		break;
+	case RATE_48MBPS:
+		status->rate_idx = 10;
+		break;
+	case RATE_54MBPS:
+		status->rate_idx = 11;
+		break;
+	}
 
-	/* FIXME: set status->rate_idx */
+	/* for 1 and 12 Mbps we have to check the modulation */
+	if (desc->rate == RATE_1MBPS) {
+		if (!(desc->mod_pre & OFDM_RATE_BIT))
+			/* CCK -> RATE_1MBPS */
+			status->rate_idx = 0;
+		else
+			/* OFDM -> RATE_12MBPS */
+			status->rate_idx = 6;
+	}
+
+	if (desc->mod_pre & SHORT_PREAMBLE_BIT)
+		status->flag |= RX_FLAG_SHORTPRE;
 }
 
 static void wl1251_rx_body(struct wl1251 *wl,
@@ -134,7 +179,7 @@
 	rx_buffer = skb_put(skb, length);
 	wl1251_mem_read(wl, rx_packet_ring_addr, rx_buffer, length);
 
-	/* The actual lenght doesn't include the target's alignment */
+	/* The actual length doesn't include the target's alignment */
 	skb->len = desc->length  - PLCP_HEADER_LENGTH;
 
 	fc = (u16 *)skb->data;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/sdio.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/sdio.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/sdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/sdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -265,7 +265,7 @@
 			goto disable;
 		}
 
-		set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+		irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
 		disable_irq(wl->irq);
 
 		wl1251_sdio_ops.enable_irq = wl1251_enable_line_irq;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/spi.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/spi.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -286,7 +286,7 @@
 		goto out_free;
 	}
 
-	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
+	irq_set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
 
 	disable_irq(wl->irq);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -213,16 +213,30 @@
 		wl1251_debug(DEBUG_TX, "skb offset %d", offset);
 
 		/* check whether the current skb can be used */
-		if (!skb_cloned(skb) && (skb_tailroom(skb) >= offset)) {
-			unsigned char *src = skb->data;
+		if (skb_cloned(skb) || (skb_tailroom(skb) < offset)) {
+			struct sk_buff *newskb = skb_copy_expand(skb, 0, 3,
+								 GFP_KERNEL);
 
-			/* align the buffer on a 4-byte boundary */
+			if (unlikely(newskb == NULL)) {
+				wl1251_error("Can't allocate skb!");
+				return -EINVAL;
+			}
+
+			tx_hdr = (struct tx_double_buffer_desc *) newskb->data;
+
+			dev_kfree_skb_any(skb);
+			wl->tx_frames[tx_hdr->id] = skb = newskb;
+
+			offset = (4 - (long)skb->data) & 0x03;
+			wl1251_debug(DEBUG_TX, "new skb offset %d", offset);
+		}
+
+		/* align the buffer on a 4-byte boundary */
+		if (offset) {
+			unsigned char *src = skb->data;
 			skb_reserve(skb, offset);
 			memmove(skb->data, src, skb->len);
 			tx_hdr = (struct tx_double_buffer_desc *) skb->data;
-		} else {
-			wl1251_info("No handler, fixme!");
-			return -EINVAL;
 		}
 	}
 
@@ -368,7 +382,7 @@
 {
 	struct ieee80211_tx_info *info;
 	struct sk_buff *skb;
-	int hdrlen, ret;
+	int hdrlen;
 	u8 *frame;
 
 	skb = wl->tx_frames[result->id];
@@ -407,40 +421,12 @@
 	ieee80211_tx_status(wl->hw, skb);
 
 	wl->tx_frames[result->id] = NULL;
-
-	if (wl->tx_queue_stopped) {
-		wl1251_debug(DEBUG_TX, "cb: queue was stopped");
-
-		skb = skb_dequeue(&wl->tx_queue);
-
-		/* The skb can be NULL because tx_work might have been
-		   scheduled before the queue was stopped making the
-		   queue empty */
-
-		if (skb) {
-			ret = wl1251_tx_frame(wl, skb);
-			if (ret == -EBUSY) {
-				/* firmware buffer is still full */
-				wl1251_debug(DEBUG_TX, "cb: fw buffer "
-					     "still full");
-				skb_queue_head(&wl->tx_queue, skb);
-				return;
-			} else if (ret < 0) {
-				dev_kfree_skb(skb);
-				return;
-			}
-		}
-
-		wl1251_debug(DEBUG_TX, "cb: waking queues");
-		ieee80211_wake_queues(wl->hw);
-		wl->tx_queue_stopped = false;
-	}
 }
 
 /* Called upon reception of a TX complete interrupt */
 void wl1251_tx_complete(struct wl1251 *wl)
 {
-	int i, result_index, num_complete = 0;
+	int i, result_index, num_complete = 0, queue_len;
 	struct tx_result result[FW_TX_CMPLT_BLOCK_SIZE], *result_ptr;
 	unsigned long flags;
 
@@ -471,18 +457,22 @@
 		}
 	}
 
-	if (wl->tx_queue_stopped
-	    &&
-	    skb_queue_len(&wl->tx_queue) <= WL1251_TX_QUEUE_LOW_WATERMARK){
+	queue_len = skb_queue_len(&wl->tx_queue);
 
-		/* firmware buffer has space, restart queues */
+	if ((num_complete > 0) && (queue_len > 0)) {
+		/* firmware buffer has space, reschedule tx_work */
+		wl1251_debug(DEBUG_TX, "tx_complete: reschedule tx_work");
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	}
+
+	if (wl->tx_queue_stopped &&
+	    queue_len <= WL1251_TX_QUEUE_LOW_WATERMARK) {
+		/* tx_queue has space, restart queues */
 		wl1251_debug(DEBUG_TX, "tx_complete: waking queues");
 		spin_lock_irqsave(&wl->wl_lock, flags);
 		ieee80211_wake_queues(wl->hw);
 		wl->tx_queue_stopped = false;
 		spin_unlock_irqrestore(&wl->wl_lock, flags);
-		ieee80211_queue_work(wl->hw, &wl->tx_work);
-
 	}
 
 	/* Every completed frame needs to be acknowledged */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/wl1251.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/wl1251.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/wl1251.h	2012-03-24 01:15:26.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/wl1251.h	2012-03-24 03:34:53.000000000 -0400
@@ -370,6 +370,8 @@
 	/* in dBm */
 	int power_level;
 
+	int rssi_thold;
+
 	struct wl1251_stats stats;
 	struct wl1251_debugfs debugfs;
 
@@ -410,6 +412,8 @@
 
 #define WL1251_DEFAULT_CHANNEL 0
 
+#define WL1251_DEFAULT_BET_CONSECUTIVE 10
+
 #define CHIP_ID_1251_PG10	           (0x7010101)
 #define CHIP_ID_1251_PG11	           (0x7020101)
 #define CHIP_ID_1251_PG12	           (0x7030101)
@@ -431,4 +435,7 @@
 #define WL1251_PART_WORK_REG_START	REGISTERS_BASE
 #define WL1251_PART_WORK_REG_SIZE	REGISTERS_WORK_SIZE
 
+#define WL1251_DEFAULT_LOW_RSSI_WEIGHT          10
+#define WL1251_DEFAULT_LOW_RSSI_DEPTH           10
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/wl12xx_80211.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/wl12xx_80211.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl1251/wl12xx_80211.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl1251/wl12xx_80211.h	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,6 @@
 
 /* This really should be 8, but not for our firmware */
 #define MAX_SUPPORTED_RATES 32
-#define COUNTRY_STRING_LEN 3
 #define MAX_COUNTRY_TRIPLETS 32
 
 /* Headers */
@@ -98,7 +97,7 @@
 
 struct wl12xx_ie_country {
 	struct wl12xx_ie_header header;
-	u8 country_string[COUNTRY_STRING_LEN];
+	u8 country_string[IEEE80211_COUNTRY_STRING_LEN];
 	struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
 } __packed;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/acx.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/acx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/acx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/acx.c	2011-05-19 00:06:34.000000000 -0400
@@ -751,10 +751,10 @@
 	return 0;
 }
 
-int wl1271_acx_rate_policies(struct wl1271 *wl)
+int wl1271_acx_sta_rate_policies(struct wl1271 *wl)
 {
-	struct acx_rate_policy *acx;
-	struct conf_tx_rate_class *c = &wl->conf.tx.rc_conf;
+	struct acx_sta_rate_policy *acx;
+	struct conf_tx_rate_class *c = &wl->conf.tx.sta_rc_conf;
 	int idx = 0;
 	int ret = 0;
 
@@ -783,6 +783,10 @@
 
 	acx->rate_class_cnt = cpu_to_le32(ACX_TX_RATE_POLICY_CNT);
 
+	wl1271_debug(DEBUG_ACX, "basic_rate: 0x%x, full_rate: 0x%x",
+		acx->rate_class[ACX_TX_BASIC_RATE].enabled_rates,
+		acx->rate_class[ACX_TX_AP_FULL_RATE].enabled_rates);
+
 	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("Setting of rate policies failed: %d", ret);
@@ -794,6 +798,38 @@
 	return ret;
 }
 
+int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
+		      u8 idx)
+{
+	struct acx_ap_rate_policy *acx;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_ACX, "acx ap rate policy");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	acx->rate_policy.enabled_rates = cpu_to_le32(c->enabled_rates);
+	acx->rate_policy.short_retry_limit = c->short_retry_limit;
+	acx->rate_policy.long_retry_limit = c->long_retry_limit;
+	acx->rate_policy.aflags = c->aflags;
+
+	acx->rate_policy_idx = cpu_to_le32(idx);
+
+	ret = wl1271_cmd_configure(wl, ACX_RATE_POLICY, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("Setting of ap rate policy failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
 int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifsn, u16 txop)
 {
@@ -915,9 +951,9 @@
 	return ret;
 }
 
-int wl1271_acx_mem_cfg(struct wl1271 *wl)
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl)
 {
-	struct wl1271_acx_config_memory *mem_conf;
+	struct wl1271_acx_ap_config_memory *mem_conf;
 	int ret;
 
 	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
@@ -929,10 +965,10 @@
 	}
 
 	/* memory config */
-	mem_conf->num_stations = DEFAULT_NUM_STATIONS;
-	mem_conf->rx_mem_block_num = ACX_RX_MEM_BLOCKS;
-	mem_conf->tx_min_mem_block_num = ACX_TX_MIN_MEM_BLOCKS;
-	mem_conf->num_ssid_profiles = ACX_NUM_SSID_PROFILES;
+	mem_conf->num_stations = wl->conf.mem.num_stations;
+	mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
+	mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
+	mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
 	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
 
 	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
@@ -947,13 +983,45 @@
 	return ret;
 }
 
-int wl1271_acx_init_mem_config(struct wl1271 *wl)
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl)
 {
+	struct wl1271_acx_sta_config_memory *mem_conf;
 	int ret;
 
-	ret = wl1271_acx_mem_cfg(wl);
-	if (ret < 0)
-		return ret;
+	wl1271_debug(DEBUG_ACX, "wl1271 mem cfg");
+
+	mem_conf = kzalloc(sizeof(*mem_conf), GFP_KERNEL);
+	if (!mem_conf) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* memory config */
+	mem_conf->num_stations = wl->conf.mem.num_stations;
+	mem_conf->rx_mem_block_num = wl->conf.mem.rx_block_num;
+	mem_conf->tx_min_mem_block_num = wl->conf.mem.tx_min_block_num;
+	mem_conf->num_ssid_profiles = wl->conf.mem.ssid_profiles;
+	mem_conf->total_tx_descriptors = cpu_to_le32(ACX_TX_DESCRIPTORS);
+	mem_conf->dyn_mem_enable = wl->conf.mem.dynamic_memory;
+	mem_conf->tx_free_req = wl->conf.mem.min_req_tx_blocks;
+	mem_conf->rx_free_req = wl->conf.mem.min_req_rx_blocks;
+	mem_conf->tx_min = wl->conf.mem.tx_min;
+
+	ret = wl1271_cmd_configure(wl, ACX_MEM_CFG, mem_conf,
+				   sizeof(*mem_conf));
+	if (ret < 0) {
+		wl1271_warning("wl1271 mem config failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(mem_conf);
+	return ret;
+}
+
+int wl1271_acx_init_mem_config(struct wl1271 *wl)
+{
+	int ret;
 
 	wl->target_mem_map = kzalloc(sizeof(struct wl1271_acx_mem_map),
 				     GFP_KERNEL);
@@ -1233,6 +1301,7 @@
 	struct wl1271_acx_ht_capabilities *acx;
 	u8 mac_address[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 	int ret = 0;
+	u32 ht_capabilites = 0;
 
 	wl1271_debug(DEBUG_ACX, "acx ht capabilities setting");
 
@@ -1244,27 +1313,26 @@
 
 	/* Allow HT Operation ? */
 	if (allow_ht_operation) {
-		acx->ht_capabilites =
+		ht_capabilites =
 			WL1271_ACX_FW_CAP_HT_OPERATION;
 		if (ht_cap->cap & IEEE80211_HT_CAP_GRN_FLD)
-			acx->ht_capabilites |=
+			ht_capabilites |=
 				WL1271_ACX_FW_CAP_GREENFIELD_FRAME_FORMAT;
 		if (ht_cap->cap & IEEE80211_HT_CAP_SGI_20)
-			acx->ht_capabilites |=
+			ht_capabilites |=
 				WL1271_ACX_FW_CAP_SHORT_GI_FOR_20MHZ_PACKETS;
 		if (ht_cap->cap & IEEE80211_HT_CAP_LSIG_TXOP_PROT)
-			acx->ht_capabilites |=
+			ht_capabilites |=
 				WL1271_ACX_FW_CAP_LSIG_TXOP_PROTECTION;
 
 		/* get data from A-MPDU parameters field */
 		acx->ampdu_max_length = ht_cap->ampdu_factor;
 		acx->ampdu_min_spacing = ht_cap->ampdu_density;
-
-		memcpy(acx->mac_address, mac_address, ETH_ALEN);
-	} else { /* HT operations are not allowed */
-		acx->ht_capabilites = 0;
 	}
 
+	memcpy(acx->mac_address, mac_address, ETH_ALEN);
+	acx->ht_capabilites = cpu_to_le32(ht_capabilites);
+
 	ret = wl1271_cmd_configure(wl, ACX_PEER_HT_CAP, acx, sizeof(*acx));
 	if (ret < 0) {
 		wl1271_warning("acx ht capabilities setting failed: %d", ret);
@@ -1293,7 +1361,8 @@
 	acx->ht_protection =
 		(u8)(ht_operation_mode & IEEE80211_HT_OP_MODE_PROTECTION);
 	acx->rifs_mode = 0;
-	acx->gf_protection = 0;
+	acx->gf_protection =
+		!!(ht_operation_mode & IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT);
 	acx->ht_tx_burst_limit = 0;
 	acx->dual_cts_protection = 0;
 
@@ -1309,6 +1378,91 @@
 	return ret;
 }
 
+/* Configure BA session initiator/receiver parameters setting in the FW. */
+int wl1271_acx_set_ba_session(struct wl1271 *wl,
+			       enum ieee80211_back_parties direction,
+			       u8 tid_index, u8 policy)
+{
+	struct wl1271_acx_ba_session_policy *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx ba session setting");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* ANY role */
+	acx->role_id = 0xff;
+	acx->tid = tid_index;
+	acx->enable = policy;
+	acx->ba_direction = direction;
+
+	switch (direction) {
+	case WLAN_BACK_INITIATOR:
+		acx->win_size = wl->conf.ht.tx_ba_win_size;
+		acx->inactivity_timeout = wl->conf.ht.inactivity_timeout;
+		break;
+	case WLAN_BACK_RECIPIENT:
+		acx->win_size = RX_BA_WIN_SIZE;
+		acx->inactivity_timeout = 0;
+		break;
+	default:
+		wl1271_error("Incorrect acx command id=%x\n", direction);
+		ret = -EINVAL;
+		goto out;
+	}
+
+	ret = wl1271_cmd_configure(wl,
+				   ACX_BA_SESSION_POLICY_CFG,
+				   acx,
+				   sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx ba session setting failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+/* setup BA session receiver setting in the FW. */
+int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
+					bool enable)
+{
+	struct wl1271_acx_ba_receiver_setup *acx;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx ba receiver session setting");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* Single link for now */
+	acx->link_id = 1;
+	acx->tid = tid_index;
+	acx->enable = enable;
+	acx->win_size = 0;
+	acx->ssn = ssn;
+
+	ret = wl1271_cmd_configure(wl, ACX_BA_SESSION_RX_SETUP, acx,
+				   sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx ba receiver session failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime)
 {
 	struct wl1271_acx_fw_tsf_information *tsf_info;
@@ -1334,3 +1488,82 @@
 	kfree(tsf_info);
 	return ret;
 }
+
+int wl1271_acx_max_tx_retry(struct wl1271 *wl)
+{
+	struct wl1271_acx_max_tx_retry *acx = NULL;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx max tx retry");
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx)
+		return -ENOMEM;
+
+	acx->max_tx_retry = cpu_to_le16(wl->conf.tx.ap_max_tx_retries);
+
+	ret = wl1271_cmd_configure(wl, ACX_MAX_TX_FAILURE, acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx max tx retry failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
+
+int wl1271_acx_config_ps(struct wl1271 *wl)
+{
+	struct wl1271_acx_config_ps *config_ps;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx config ps");
+
+	config_ps = kzalloc(sizeof(*config_ps), GFP_KERNEL);
+	if (!config_ps) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	config_ps->exit_retries = wl->conf.conn.psm_exit_retries;
+	config_ps->enter_retries = wl->conf.conn.psm_entry_retries;
+	config_ps->null_data_rate = cpu_to_le32(wl->basic_rate);
+
+	ret = wl1271_cmd_configure(wl, ACX_CONFIG_PS, config_ps,
+				   sizeof(*config_ps));
+
+	if (ret < 0) {
+		wl1271_warning("acx config ps failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(config_ps);
+	return ret;
+}
+
+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr)
+{
+	struct wl1271_acx_inconnection_sta *acx = NULL;
+	int ret;
+
+	wl1271_debug(DEBUG_ACX, "acx set inconnaction sta %pM", addr);
+
+	acx = kzalloc(sizeof(*acx), GFP_KERNEL);
+	if (!acx)
+		return -ENOMEM;
+
+	memcpy(acx->addr, addr, ETH_ALEN);
+
+	ret = wl1271_cmd_configure(wl, ACX_UPDATE_INCONNECTION_STA_LIST,
+				   acx, sizeof(*acx));
+	if (ret < 0) {
+		wl1271_warning("acx set inconnaction sta failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(acx);
+	return ret;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/acx.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/acx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/acx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/acx.h	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,6 @@
 
 #define DEFAULT_UCAST_PRIORITY          0
 #define DEFAULT_RX_Q_PRIORITY           0
-#define DEFAULT_NUM_STATIONS            1
 #define DEFAULT_RXQ_PRIORITY            0 /* low 0 .. 15 high  */
 #define DEFAULT_RXQ_TYPE                0x07    /* All frames, Data/Ctrl/Mgmt */
 #define TRACE_BUFFER_MAX_SIZE           256
@@ -747,13 +746,23 @@
 #define ACX_TX_BASIC_RATE      0
 #define ACX_TX_AP_FULL_RATE    1
 #define ACX_TX_RATE_POLICY_CNT 2
-struct acx_rate_policy {
+struct acx_sta_rate_policy {
 	struct acx_header header;
 
 	__le32 rate_class_cnt;
 	struct acx_rate_class rate_class[CONF_TX_MAX_RATE_CLASSES];
 } __packed;
 
+
+#define ACX_TX_AP_MODE_MGMT_RATE 4
+#define ACX_TX_AP_MODE_BCST_RATE 5
+struct acx_ap_rate_policy {
+	struct acx_header header;
+
+	__le32 rate_policy_idx;
+	struct acx_rate_class rate_policy;
+} __packed;
+
 struct acx_ac_cfg {
 	struct acx_header header;
 	u8 ac;
@@ -787,12 +796,9 @@
 	__le16 tx_compl_threshold;   /* number of packets */
 } __packed;
 
-#define ACX_RX_MEM_BLOCKS     70
-#define ACX_TX_MIN_MEM_BLOCKS 40
 #define ACX_TX_DESCRIPTORS    32
-#define ACX_NUM_SSID_PROFILES 1
 
-struct wl1271_acx_config_memory {
+struct wl1271_acx_ap_config_memory {
 	struct acx_header header;
 
 	u8 rx_mem_block_num;
@@ -802,6 +808,20 @@
 	__le32 total_tx_descriptors;
 } __packed;
 
+struct wl1271_acx_sta_config_memory {
+	struct acx_header header;
+
+	u8 rx_mem_block_num;
+	u8 tx_min_mem_block_num;
+	u8 num_stations;
+	u8 num_ssid_profiles;
+	__le32 total_tx_descriptors;
+	u8 dyn_mem_enable;
+	u8 tx_free_req;
+	u8 rx_free_req;
+	u8 tx_min;
+} __packed;
+
 struct wl1271_acx_mem_map {
 	struct acx_header header;
 
@@ -1051,6 +1071,59 @@
 	u8 padding[3];
 } __packed;
 
+#define RX_BA_WIN_SIZE 8
+
+struct wl1271_acx_ba_session_policy {
+	struct acx_header header;
+	/*
+	 * Specifies role Id, Range 0-7, 0xFF means ANY role.
+	 * Future use. For now this field is irrelevant
+	 */
+	u8 role_id;
+	/*
+	 * Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id.
+	 * Not applicable if Role Id is set to ANY.
+	 */
+	u8 link_id;
+
+	u8 tid;
+
+	u8 enable;
+
+	/* Windows size in number of packets */
+	u16 win_size;
+
+	/*
+	 * As initiator inactivity timeout in time units(TU) of 1024us.
+	 * As receiver reserved
+	 */
+	u16 inactivity_timeout;
+
+	/* Initiator = 1/Receiver = 0 */
+	u8 ba_direction;
+
+	u8 padding[3];
+} __packed;
+
+struct wl1271_acx_ba_receiver_setup {
+	struct acx_header header;
+
+	/* Specifies Link Id, Range 0-31, 0xFF means ANY  Link Id */
+	u8 link_id;
+
+	u8 tid;
+
+	u8 enable;
+
+	u8 padding[1];
+
+	/* Windows size in number of packets */
+	u16 win_size;
+
+	/* BA session starting sequence number.  RANGE 0-FFF */
+	u16 ssn;
+} __packed;
+
 struct wl1271_acx_fw_tsf_information {
 	struct acx_header header;
 
@@ -1062,6 +1135,33 @@
 	u8 padding[3];
 } __packed;
 
+struct wl1271_acx_max_tx_retry {
+	struct acx_header header;
+
+	/*
+	 * the number of frames transmission failures before
+	 * issuing the aging event.
+	 */
+	__le16 max_tx_retry;
+	u8 padding_1[2];
+} __packed;
+
+struct wl1271_acx_config_ps {
+	struct acx_header header;
+
+	u8 exit_retries;
+	u8 enter_retries;
+	u8 padding[2];
+	__le32 null_data_rate;
+} __packed;
+
+struct wl1271_acx_inconnection_sta {
+	struct acx_header header;
+
+	u8 addr[ETH_ALEN];
+	u8 padding1[2];
+} __packed;
+
 enum {
 	ACX_WAKE_UP_CONDITIONS      = 0x0002,
 	ACX_MEM_CFG                 = 0x0003,
@@ -1113,22 +1213,24 @@
 	ACX_RSSI_SNR_WEIGHTS        = 0x0052,
 	ACX_KEEP_ALIVE_MODE         = 0x0053,
 	ACX_SET_KEEP_ALIVE_CONFIG   = 0x0054,
-	ACX_BA_SESSION_RESPONDER_POLICY = 0x0055,
-	ACX_BA_SESSION_INITIATOR_POLICY = 0x0056,
+	ACX_BA_SESSION_POLICY_CFG   = 0x0055,
+	ACX_BA_SESSION_RX_SETUP     = 0x0056,
 	ACX_PEER_HT_CAP             = 0x0057,
 	ACX_HT_BSS_OPERATION        = 0x0058,
 	ACX_COEX_ACTIVITY           = 0x0059,
 	ACX_SET_DCO_ITRIM_PARAMS    = 0x0061,
+	ACX_GEN_FW_CMD              = 0x0070,
+	ACX_HOST_IF_CFG_BITMAP      = 0x0071,
+	ACX_MAX_TX_FAILURE          = 0x0072,
+	ACX_UPDATE_INCONNECTION_STA_LIST = 0x0073,
 	DOT11_RX_MSDU_LIFE_TIME     = 0x1004,
 	DOT11_CUR_TX_PWR            = 0x100D,
 	DOT11_RX_DOT11_MODE         = 0x1012,
 	DOT11_RTS_THRESHOLD         = 0x1013,
 	DOT11_GROUP_ADDRESS_TBL     = 0x1014,
 	ACX_PM_CONFIG               = 0x1016,
-
-	MAX_DOT11_IE = DOT11_GROUP_ADDRESS_TBL,
-
-	MAX_IE = 0xFFFF
+	ACX_CONFIG_PS               = 0x1017,
+	ACX_CONFIG_HANGOVER         = 0x1018,
 };
 
 
@@ -1160,7 +1262,9 @@
 int wl1271_acx_cts_protect(struct wl1271 *wl,
 			   enum acx_ctsprotect_type ctsprotect);
 int wl1271_acx_statistics(struct wl1271 *wl, struct acx_statistics *stats);
-int wl1271_acx_rate_policies(struct wl1271 *wl);
+int wl1271_acx_sta_rate_policies(struct wl1271 *wl);
+int wl1271_acx_ap_rate_policy(struct wl1271 *wl, struct conf_tx_rate_class *c,
+		      u8 idx);
 int wl1271_acx_ac_cfg(struct wl1271 *wl, u8 ac, u8 cw_min, u16 cw_max,
 		      u8 aifsn, u16 txop);
 int wl1271_acx_tid_cfg(struct wl1271 *wl, u8 queue_id, u8 channel_type,
@@ -1168,7 +1272,8 @@
 		       u32 apsd_conf0, u32 apsd_conf1);
 int wl1271_acx_frag_threshold(struct wl1271 *wl, u16 frag_threshold);
 int wl1271_acx_tx_config_options(struct wl1271 *wl);
-int wl1271_acx_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_ap_mem_cfg(struct wl1271 *wl);
+int wl1271_acx_sta_mem_cfg(struct wl1271 *wl);
 int wl1271_acx_init_mem_config(struct wl1271 *wl);
 int wl1271_acx_init_rx_interrupt(struct wl1271 *wl);
 int wl1271_acx_smart_reflex(struct wl1271 *wl);
@@ -1185,6 +1290,14 @@
 				    bool allow_ht_operation);
 int wl1271_acx_set_ht_information(struct wl1271 *wl,
 				   u16 ht_operation_mode);
+int wl1271_acx_set_ba_session(struct wl1271 *wl,
+			      enum ieee80211_back_parties direction,
+			      u8 tid_index, u8 policy);
+int wl1271_acx_set_ba_receiver_session(struct wl1271 *wl, u8 tid_index, u16 ssn,
+				       bool enable);
 int wl1271_acx_tsf_info(struct wl1271 *wl, u64 *mactime);
+int wl1271_acx_max_tx_retry(struct wl1271 *wl);
+int wl1271_acx_config_ps(struct wl1271 *wl);
+int wl1271_acx_set_inconnection_sta(struct wl1271 *wl, u8 *addr);
 
 #endif /* __WL1271_ACX_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/boot.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/boot.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/boot.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/boot.c	2011-05-19 00:06:34.000000000 -0400
@@ -28,6 +28,7 @@
 #include "boot.h"
 #include "io.h"
 #include "event.h"
+#include "rx.h"
 
 static struct wl1271_partition_set part_table[PART_TABLE_LEN] = {
 	[PART_DOWN] = {
@@ -100,6 +101,22 @@
 	wl1271_write32(wl, ACX_REG_ECPU_CONTROL, cpu_ctrl);
 }
 
+static void wl1271_parse_fw_ver(struct wl1271 *wl)
+{
+	int ret;
+
+	ret = sscanf(wl->chip.fw_ver_str + 4, "%u.%u.%u.%u.%u",
+		     &wl->chip.fw_ver[0], &wl->chip.fw_ver[1],
+		     &wl->chip.fw_ver[2], &wl->chip.fw_ver[3],
+		     &wl->chip.fw_ver[4]);
+
+	if (ret != 5) {
+		wl1271_warning("fw version incorrect value");
+		memset(wl->chip.fw_ver, 0, sizeof(wl->chip.fw_ver));
+		return;
+	}
+}
+
 static void wl1271_boot_fw_version(struct wl1271 *wl)
 {
 	struct wl1271_static_data static_data;
@@ -107,11 +124,13 @@
 	wl1271_read(wl, wl->cmd_box_addr, &static_data, sizeof(static_data),
 		    false);
 
-	strncpy(wl->chip.fw_ver, static_data.fw_version,
-		sizeof(wl->chip.fw_ver));
+	strncpy(wl->chip.fw_ver_str, static_data.fw_version,
+		sizeof(wl->chip.fw_ver_str));
 
 	/* make sure the string is NULL-terminated */
-	wl->chip.fw_ver[sizeof(wl->chip.fw_ver) - 1] = '\0';
+	wl->chip.fw_ver_str[sizeof(wl->chip.fw_ver_str) - 1] = '\0';
+
+	wl1271_parse_fw_ver(wl);
 }
 
 static int wl1271_boot_upload_firmware_chunk(struct wl1271 *wl, void *buf,
@@ -231,7 +250,9 @@
 	 */
 	if (wl->nvs_len == sizeof(struct wl1271_nvs_file) ||
 	    wl->nvs_len == WL1271_INI_LEGACY_NVS_FILE_SIZE) {
-		if (wl->nvs->general_params.dual_mode_select)
+		/* for now 11a is unsupported in AP mode */
+		if (wl->bss_type != BSS_TYPE_AP_BSS &&
+		    wl->nvs->general_params.dual_mode_select)
 			wl->enable_11a = true;
 	}
 
@@ -431,6 +452,9 @@
 		PSPOLL_DELIVERY_FAILURE_EVENT_ID |
 		SOFT_GEMINI_SENSE_EVENT_ID;
 
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl->event_mask |= STA_REMOVE_COMPLETE_EVENT_ID;
+
 	ret = wl1271_event_unmask(wl);
 	if (ret < 0) {
 		wl1271_error("EVENT mask setting failed");
@@ -464,6 +488,9 @@
 	fuse = (fuse & PG_VER_MASK) >> PG_VER_OFFSET;
 
 	wl->hw_pg_ver = (s8)fuse;
+
+	if (((wl->hw_pg_ver & PG_MAJOR_VER_MASK) >> PG_MAJOR_VER_OFFSET) < 3)
+		wl->quirks |= WL12XX_QUIRK_END_OF_TRANSACTION;
 }
 
 /* uploads NVS and firmware */
@@ -595,8 +622,7 @@
 	wl1271_boot_enable_interrupts(wl);
 
 	/* set the wl1271 default filters */
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+	wl1271_set_default_filters(wl);
 
 	wl1271_event_mbox_config(wl);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/boot.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/boot.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/boot.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/boot.h	2011-05-19 00:06:34.000000000 -0400
@@ -59,6 +59,11 @@
 #define PG_VER_MASK          0x3c
 #define PG_VER_OFFSET        2
 
+#define PG_MAJOR_VER_MASK    0x3
+#define PG_MAJOR_VER_OFFSET  0x0
+#define PG_MINOR_VER_MASK    0xc
+#define PG_MINOR_VER_OFFSET  0x2
+
 #define CMD_MBOX_ADDRESS     0x407B4
 
 #define POLARITY_LOW         BIT(1)
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/cmd.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/cmd.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/cmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,6 +36,7 @@
 #include "wl12xx_80211.h"
 #include "cmd.h"
 #include "event.h"
+#include "tx.h"
 
 #define WL1271_CMD_FAST_POLL_COUNT       50
 
@@ -62,6 +63,7 @@
 	cmd->status = 0;
 
 	WARN_ON(len % 4 != 0);
+	WARN_ON(test_bit(WL1271_FLAG_IN_ELP, &wl->flags));
 
 	wl1271_write(wl, wl->cmd_box_addr, buf, len, false);
 
@@ -221,7 +223,7 @@
  * Poll the mailbox event field until any of the bits in the mask is set or a
  * timeout occurs (WL1271_EVENT_TIMEOUT in msecs)
  */
-static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
+static int wl1271_cmd_wait_for_event_or_timeout(struct wl1271 *wl, u32 mask)
 {
 	u32 events_vector, event;
 	unsigned long timeout;
@@ -230,7 +232,8 @@
 
 	do {
 		if (time_after(jiffies, timeout)) {
-			ieee80211_queue_work(wl->hw, &wl->recovery_work);
+			wl1271_debug(DEBUG_CMD, "timeout waiting for event %d",
+				     (int)mask);
 			return -ETIMEDOUT;
 		}
 
@@ -248,6 +251,19 @@
 	return 0;
 }
 
+static int wl1271_cmd_wait_for_event(struct wl1271 *wl, u32 mask)
+{
+	int ret;
+
+	ret = wl1271_cmd_wait_for_event_or_timeout(wl, mask);
+	if (ret != 0) {
+		ieee80211_queue_work(wl->hw, &wl->recovery_work);
+		return ret;
+	}
+
+	return 0;
+}
+
 int wl1271_cmd_join(struct wl1271 *wl, u8 bss_type)
 {
 	struct wl1271_cmd_join *join;
@@ -271,6 +287,7 @@
 	join->rx_filter_options = cpu_to_le32(wl->rx_filter);
 	join->bss_type = bss_type;
 	join->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	join->supported_rate_set = cpu_to_le32(wl->rate_set);
 
 	if (wl->band == IEEE80211_BAND_5GHZ)
 		join->bss_type |= WL1271_JOIN_CMD_BSS_TYPE_5GHZ;
@@ -288,6 +305,9 @@
 	wl->tx_security_last_seq = 0;
 	wl->tx_security_seq = 0;
 
+	wl1271_debug(DEBUG_CMD, "cmd join: basic_rate_set=0x%x, rate_set=0x%x",
+		join->basic_rate_set, join->supported_rate_set);
+
 	ret = wl1271_cmd_send(wl, CMD_START_JOIN, join, sizeof(*join), 0);
 	if (ret < 0) {
 		wl1271_error("failed to initiate cmd join");
@@ -339,7 +359,7 @@
  * @wl: wl struct
  * @id: acx id
  * @buf: buffer for the response, including all headers, must work with dma
- * @len: lenght of buf
+ * @len: length of buf
  */
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len)
 {
@@ -439,7 +459,7 @@
 	return ret;
 }
 
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send)
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode)
 {
 	struct wl1271_cmd_ps_params *ps_params = NULL;
 	int ret = 0;
@@ -453,10 +473,6 @@
 	}
 
 	ps_params->ps_mode = ps_mode;
-	ps_params->send_null_data = send;
-	ps_params->retries = wl->conf.conn.psm_entry_nullfunc_retries;
-	ps_params->hang_over_period = wl->conf.conn.psm_entry_hangover_period;
-	ps_params->null_data_rate = cpu_to_le32(rates);
 
 	ret = wl1271_cmd_send(wl, CMD_SET_PS_MODE, ps_params,
 			      sizeof(*ps_params), 0);
@@ -490,8 +506,8 @@
 	cmd->len = cpu_to_le16(buf_len);
 	cmd->template_type = template_id;
 	cmd->enabled_rates = cpu_to_le32(rates);
-	cmd->short_retry_limit = wl->conf.tx.rc_conf.short_retry_limit;
-	cmd->long_retry_limit = wl->conf.tx.rc_conf.long_retry_limit;
+	cmd->short_retry_limit = wl->conf.tx.tmpl_short_retry_limit;
+	cmd->long_retry_limit = wl->conf.tx.tmpl_long_retry_limit;
 	cmd->index = index;
 
 	if (buf)
@@ -659,15 +675,15 @@
 
 	/* llc layer */
 	memcpy(tmpl.llc_hdr, rfc1042_header, sizeof(rfc1042_header));
-	tmpl.llc_type = htons(ETH_P_ARP);
+	tmpl.llc_type = cpu_to_be16(ETH_P_ARP);
 
 	/* arp header */
 	arp_hdr = &tmpl.arp_hdr;
-	arp_hdr->ar_hrd = htons(ARPHRD_ETHER);
-	arp_hdr->ar_pro = htons(ETH_P_IP);
+	arp_hdr->ar_hrd = cpu_to_be16(ARPHRD_ETHER);
+	arp_hdr->ar_pro = cpu_to_be16(ETH_P_IP);
 	arp_hdr->ar_hln = ETH_ALEN;
 	arp_hdr->ar_pln = 4;
-	arp_hdr->ar_op = htons(ARPOP_REPLY);
+	arp_hdr->ar_op = cpu_to_be16(ARPOP_REPLY);
 
 	/* arp payload */
 	memcpy(tmpl.sender_hw, wl->vif->addr, ETH_ALEN);
@@ -702,9 +718,9 @@
 				       wl->basic_rate);
 }
 
-int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id)
+int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id)
 {
-	struct wl1271_cmd_set_keys *cmd;
+	struct wl1271_cmd_set_sta_keys *cmd;
 	int ret = 0;
 
 	wl1271_debug(DEBUG_CMD, "cmd set_default_wep_key %d", id);
@@ -731,11 +747,42 @@
 	return ret;
 }
 
-int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id)
+{
+	struct wl1271_cmd_set_ap_keys *cmd;
+	int ret = 0;
+
+	wl1271_debug(DEBUG_CMD, "cmd set_ap_default_wep_key %d", id);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->key_id = id;
+	cmd->lid_key_type = WEP_DEFAULT_LID_TYPE;
+	cmd->key_action = cpu_to_le16(KEY_SET_ID);
+	cmd->key_type = KEY_WEP;
+
+	ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_warning("cmd set_ap_default_wep_key failed: %d", ret);
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+
+	return ret;
+}
+
+int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
 		       u8 key_size, const u8 *key, const u8 *addr,
 		       u32 tx_seq_32, u16 tx_seq_16)
 {
-	struct wl1271_cmd_set_keys *cmd;
+	struct wl1271_cmd_set_sta_keys *cmd;
 	int ret = 0;
 
 	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
@@ -788,6 +835,67 @@
 	return ret;
 }
 
+int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+			u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
+			u16 tx_seq_16)
+{
+	struct wl1271_cmd_set_ap_keys *cmd;
+	int ret = 0;
+	u8 lid_type;
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd)
+		return -ENOMEM;
+
+	if (hlid == WL1271_AP_BROADCAST_HLID) {
+		if (key_type == KEY_WEP)
+			lid_type = WEP_DEFAULT_LID_TYPE;
+		else
+			lid_type = BROADCAST_LID_TYPE;
+	} else {
+		lid_type = UNICAST_LID_TYPE;
+	}
+
+	wl1271_debug(DEBUG_CRYPT, "ap key action: %d id: %d lid: %d type: %d"
+		     " hlid: %d", (int)action, (int)id, (int)lid_type,
+		     (int)key_type, (int)hlid);
+
+	cmd->lid_key_type = lid_type;
+	cmd->hlid = hlid;
+	cmd->key_action = cpu_to_le16(action);
+	cmd->key_size = key_size;
+	cmd->key_type = key_type;
+	cmd->key_id = id;
+	cmd->ac_seq_num16[0] = cpu_to_le16(tx_seq_16);
+	cmd->ac_seq_num32[0] = cpu_to_le32(tx_seq_32);
+
+	if (key_type == KEY_TKIP) {
+		/*
+		 * We get the key in the following form:
+		 * TKIP (16 bytes) - TX MIC (8 bytes) - RX MIC (8 bytes)
+		 * but the target is expecting:
+		 * TKIP - RX MIC - TX MIC
+		 */
+		memcpy(cmd->key, key, 16);
+		memcpy(cmd->key + 16, key + 24, 8);
+		memcpy(cmd->key + 24, key + 16, 8);
+	} else {
+		memcpy(cmd->key, key, key_size);
+	}
+
+	wl1271_dump(DEBUG_CRYPT, "TARGET AP KEY: ", cmd, sizeof(*cmd));
+
+	ret = wl1271_cmd_send(wl, CMD_SET_KEYS, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_warning("could not set ap keys");
+		goto out;
+	}
+
+out:
+	kfree(cmd);
+	return ret;
+}
+
 int wl1271_cmd_disconnect(struct wl1271 *wl)
 {
 	struct wl1271_cmd_disconnect *cmd;
@@ -846,6 +954,183 @@
 
 out_free:
 	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_start_bss(struct wl1271 *wl)
+{
+	struct wl1271_cmd_bss_start *cmd;
+	struct ieee80211_bss_conf *bss_conf = &wl->vif->bss_conf;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd start bss");
+
+	/*
+	 * FIXME: We currently do not support hidden SSID. The real SSID
+	 * should be fetched from mac80211 first.
+	 */
+	if (wl->ssid_len == 0) {
+		wl1271_warning("Hidden SSID currently not supported for AP");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	memcpy(cmd->bssid, bss_conf->bssid, ETH_ALEN);
+
+	cmd->aging_period = cpu_to_le16(WL1271_AP_DEF_INACTIV_SEC);
+	cmd->bss_index = WL1271_AP_BSS_INDEX;
+	cmd->global_hlid = WL1271_AP_GLOBAL_HLID;
+	cmd->broadcast_hlid = WL1271_AP_BROADCAST_HLID;
+	cmd->basic_rate_set = cpu_to_le32(wl->basic_rate_set);
+	cmd->beacon_interval = cpu_to_le16(wl->beacon_int);
+	cmd->dtim_interval = bss_conf->dtim_period;
+	cmd->beacon_expiry = WL1271_AP_DEF_BEACON_EXP;
+	cmd->channel = wl->channel;
+	cmd->ssid_len = wl->ssid_len;
+	cmd->ssid_type = SSID_TYPE_PUBLIC;
+	memcpy(cmd->ssid, wl->ssid, wl->ssid_len);
+
+	switch (wl->band) {
+	case IEEE80211_BAND_2GHZ:
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	case IEEE80211_BAND_5GHZ:
+		cmd->band = RADIO_BAND_5GHZ;
+		break;
+	default:
+		wl1271_warning("bss start - unknown band: %d", (int)wl->band);
+		cmd->band = RADIO_BAND_2_4GHZ;
+		break;
+	}
+
+	ret = wl1271_cmd_send(wl, CMD_BSS_START, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd start bss");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_stop_bss(struct wl1271 *wl)
+{
+	struct wl1271_cmd_bss_start *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd stop bss");
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->bss_index = WL1271_AP_BSS_INDEX;
+
+	ret = wl1271_cmd_send(wl, CMD_BSS_STOP, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd stop bss");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid)
+{
+	struct wl1271_cmd_add_sta *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd add sta %d", (int)hlid);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	/* currently we don't support UAPSD */
+	cmd->sp_len = 0;
+
+	memcpy(cmd->addr, sta->addr, ETH_ALEN);
+	cmd->bss_index = WL1271_AP_BSS_INDEX;
+	cmd->aid = sta->aid;
+	cmd->hlid = hlid;
+
+	/*
+	 * FIXME: Does STA support QOS? We need to propagate this info from
+	 * hostapd. Currently not that important since this is only used for
+	 * sending the correct flavor of null-data packet in response to a
+	 * trigger.
+	 */
+	cmd->wmm = 0;
+
+	cmd->supported_rates = cpu_to_le32(wl1271_tx_enabled_rates_get(wl,
+						sta->supp_rates[wl->band]));
+
+	wl1271_debug(DEBUG_CMD, "new sta rates: 0x%x", cmd->supported_rates);
+
+	ret = wl1271_cmd_send(wl, CMD_ADD_STA, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd add sta");
+		goto out_free;
+	}
+
+out_free:
+	kfree(cmd);
+
+out:
+	return ret;
+}
+
+int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid)
+{
+	struct wl1271_cmd_remove_sta *cmd;
+	int ret;
+
+	wl1271_debug(DEBUG_CMD, "cmd remove sta %d", (int)hlid);
+
+	cmd = kzalloc(sizeof(*cmd), GFP_KERNEL);
+	if (!cmd) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	cmd->hlid = hlid;
+	/* We never send a deauth, mac80211 is in charge of this */
+	cmd->reason_opcode = 0;
+	cmd->send_deauth_flag = 0;
+
+	ret = wl1271_cmd_send(wl, CMD_REMOVE_STA, cmd, sizeof(*cmd), 0);
+	if (ret < 0) {
+		wl1271_error("failed to initiate cmd remove sta");
+		goto out_free;
+	}
+
+	/*
+	 * We are ok with a timeout here. The event is sometimes not sent
+	 * due to a firmware bug.
+	 */
+	wl1271_cmd_wait_for_event_or_timeout(wl, STA_REMOVE_COMPLETE_EVENT_ID);
+
+out_free:
+	kfree(cmd);
 
 out:
 	return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/cmd.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/cmd.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/cmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/cmd.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_configure(struct wl1271 *wl, u16 id, void *buf, size_t len);
 int wl1271_cmd_data_path(struct wl1271 *wl, bool enable);
-int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode, u32 rates, bool send);
+int wl1271_cmd_ps_mode(struct wl1271 *wl, u8 ps_mode);
 int wl1271_cmd_read_memory(struct wl1271 *wl, u32 addr, void *answer,
 			   size_t len);
 int wl1271_cmd_template_set(struct wl1271 *wl, u16 template_id,
@@ -54,12 +54,20 @@
 int wl1271_cmd_build_arp_rsp(struct wl1271 *wl, __be32 ip_addr);
 int wl1271_build_qos_null_data(struct wl1271 *wl);
 int wl1271_cmd_build_klv_null_data(struct wl1271 *wl);
-int wl1271_cmd_set_default_wep_key(struct wl1271 *wl, u8 id);
-int wl1271_cmd_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
-		       u8 key_size, const u8 *key, const u8 *addr,
-		       u32 tx_seq_32, u16 tx_seq_16);
+int wl1271_cmd_set_sta_default_wep_key(struct wl1271 *wl, u8 id);
+int wl1271_cmd_set_ap_default_wep_key(struct wl1271 *wl, u8 id);
+int wl1271_cmd_set_sta_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+			   u8 key_size, const u8 *key, const u8 *addr,
+			   u32 tx_seq_32, u16 tx_seq_16);
+int wl1271_cmd_set_ap_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+			  u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
+			  u16 tx_seq_16);
 int wl1271_cmd_disconnect(struct wl1271 *wl);
 int wl1271_cmd_set_sta_state(struct wl1271 *wl);
+int wl1271_cmd_start_bss(struct wl1271 *wl);
+int wl1271_cmd_stop_bss(struct wl1271 *wl);
+int wl1271_cmd_add_sta(struct wl1271 *wl, struct ieee80211_sta *sta, u8 hlid);
+int wl1271_cmd_remove_sta(struct wl1271 *wl, u8 hlid);
 
 enum wl1271_commands {
 	CMD_INTERROGATE     = 1,    /*use this to read information elements*/
@@ -98,6 +106,12 @@
 	CMD_STOP_PERIODIC_SCAN       = 51,
 	CMD_SET_STA_STATE            = 52,
 
+	/* AP mode commands */
+	CMD_BSS_START                = 60,
+	CMD_BSS_STOP                 = 61,
+	CMD_ADD_STA                  = 62,
+	CMD_REMOVE_STA               = 63,
+
 	NUM_COMMANDS,
 	MAX_COMMAND_ID = 0xFFFF,
 };
@@ -126,6 +140,14 @@
 				  * For CTS-to-self (FastCTS) mechanism
 				  * for BT/WLAN coexistence (SoftGemini). */
 	CMD_TEMPL_ARP_RSP,
+	CMD_TEMPL_LINK_MEASUREMENT_REPORT,
+
+	/* AP-mode specific */
+	CMD_TEMPL_AP_BEACON = 13,
+	CMD_TEMPL_AP_PROBE_RESPONSE,
+	CMD_TEMPL_AP_ARP_RSP,
+	CMD_TEMPL_DEAUTH_AP,
+
 	CMD_TEMPL_MAX = 0xff
 };
 
@@ -195,6 +217,7 @@
 	 * ACK or CTS frames).
 	 */
 	__le32 basic_rate_set;
+	__le32 supported_rate_set;
 	u8 dtim_interval;
 	/*
 	 * bits 0-2: This bitwise field specifies the type
@@ -257,20 +280,11 @@
 	struct wl1271_cmd_header header;
 
 	u8 ps_mode; /* STATION_* */
-	u8 send_null_data; /* Do we have to send NULL data packet ? */
-	u8 retries; /* Number of retires for the initial NULL data packet */
-
-	 /*
-	  * TUs during which the target stays awake after switching
-	  * to power save mode.
-	  */
-	u8 hang_over_period;
-	__le32 null_data_rate;
+	u8 padding[3];
 } __packed;
 
 /* HW encryption keys */
 #define NUM_ACCESS_CATEGORIES_COPY 4
-#define MAX_KEY_SIZE 32
 
 enum wl1271_cmd_key_action {
 	KEY_ADD_OR_REPLACE = 1,
@@ -289,7 +303,7 @@
 
 /* FIXME: Add description for key-types */
 
-struct wl1271_cmd_set_keys {
+struct wl1271_cmd_set_sta_keys {
 	struct wl1271_cmd_header header;
 
 	/* Ignored for default WEP key */
@@ -318,6 +332,57 @@
 	__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
 } __packed;
 
+enum wl1271_cmd_lid_key_type {
+	UNICAST_LID_TYPE     = 0,
+	BROADCAST_LID_TYPE   = 1,
+	WEP_DEFAULT_LID_TYPE = 2
+};
+
+struct wl1271_cmd_set_ap_keys {
+	struct wl1271_cmd_header header;
+
+	/*
+	 * Indicates whether the HLID is a unicast key set
+	 * or broadcast key set. A special value 0xFF is
+	 * used to indicate that the HLID is on WEP-default
+	 * (multi-hlids). of type wl1271_cmd_lid_key_type.
+	 */
+	u8 hlid;
+
+	/*
+	 * In WEP-default network (hlid == 0xFF) used to
+	 * indicate which network STA/IBSS/AP role should be
+	 * changed
+	 */
+	u8 lid_key_type;
+
+	/*
+	 * Key ID - For TKIP and AES key types, this field
+	 * indicates the value that should be inserted into
+	 * the KeyID field of frames transmitted using this
+	 * key entry. For broadcast keys the index use as a
+	 * marker for TX/RX key.
+	 * For WEP default network (HLID=0xFF), this field
+	 * indicates the ID of the key to add or remove.
+	 */
+	u8 key_id;
+	u8 reserved_1;
+
+	/* key_action_e */
+	__le16 key_action;
+
+	/* key size in bytes */
+	u8 key_size;
+
+	/* key_type_e */
+	u8 key_type;
+
+	/* This field holds the security key data to add to the STA table */
+	u8 key[MAX_KEY_SIZE];
+	__le16 ac_seq_num16[NUM_ACCESS_CATEGORIES_COPY];
+	__le32 ac_seq_num32[NUM_ACCESS_CATEGORIES_COPY];
+} __packed;
+
 struct wl1271_cmd_test_header {
 	u8 id;
 	u8 padding[3];
@@ -412,4 +477,68 @@
 	u8 padding[3];
 } __packed;
 
+enum wl1271_ssid_type {
+	SSID_TYPE_PUBLIC = 0,
+	SSID_TYPE_HIDDEN = 1
+};
+
+struct wl1271_cmd_bss_start {
+	struct wl1271_cmd_header header;
+
+	/* wl1271_ssid_type */
+	u8 ssid_type;
+	u8 ssid_len;
+	u8 ssid[IW_ESSID_MAX_SIZE];
+	u8 padding_1[2];
+
+	/* Basic rate set */
+	__le32 basic_rate_set;
+	/* Aging period in seconds*/
+	__le16 aging_period;
+
+	/*
+	 * This field specifies the time between target beacon
+	 * transmission times (TBTTs), in time units (TUs).
+	 * Valid values are 1 to 1024.
+	 */
+	__le16 beacon_interval;
+	u8 bssid[ETH_ALEN];
+	u8 bss_index;
+	/* Radio band */
+	u8 band;
+	u8 channel;
+	/* The host link id for the AP's global queue */
+	u8 global_hlid;
+	/* The host link id for the AP's broadcast queue */
+	u8 broadcast_hlid;
+	/* DTIM count */
+	u8 dtim_interval;
+	/* Beacon expiry time in ms */
+	u8 beacon_expiry;
+	u8 padding_2[3];
+} __packed;
+
+struct wl1271_cmd_add_sta {
+	struct wl1271_cmd_header header;
+
+	u8 addr[ETH_ALEN];
+	u8 hlid;
+	u8 aid;
+	u8 psd_type[NUM_ACCESS_CATEGORIES_COPY];
+	__le32 supported_rates;
+	u8 bss_index;
+	u8 sp_len;
+	u8 wmm;
+	u8 padding1;
+} __packed;
+
+struct wl1271_cmd_remove_sta {
+	struct wl1271_cmd_header header;
+
+	u8 hlid;
+	u8 reason_opcode;
+	u8 send_deauth_flag;
+	u8 padding1;
+} __packed;
+
 #endif /* __WL1271_CMD_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/conf.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/conf.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/conf.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/conf.h	2011-05-19 00:06:34.000000000 -0400
@@ -496,6 +496,26 @@
 					CONF_HW_BIT_RATE_2MBPS)
 #define CONF_TX_RATE_RETRY_LIMIT       10
 
+/*
+ * Rates supported for data packets when operating as AP. Note the absence
+ * of the 22Mbps rate. There is a FW limitation on 12 rates so we must drop
+ * one. The rate dropped is not mandatory under any operating mode.
+ */
+#define CONF_TX_AP_ENABLED_RATES       (CONF_HW_BIT_RATE_1MBPS | \
+	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS |      \
+	CONF_HW_BIT_RATE_6MBPS | CONF_HW_BIT_RATE_9MBPS |        \
+	CONF_HW_BIT_RATE_11MBPS | CONF_HW_BIT_RATE_12MBPS |      \
+	CONF_HW_BIT_RATE_18MBPS | CONF_HW_BIT_RATE_24MBPS |      \
+	CONF_HW_BIT_RATE_36MBPS | CONF_HW_BIT_RATE_48MBPS |      \
+	CONF_HW_BIT_RATE_54MBPS)
+
+/*
+ * Default rates for management traffic when operating in AP mode. This
+ * should be configured according to the basic rate set of the AP
+ */
+#define CONF_TX_AP_DEFAULT_MGMT_RATES  (CONF_HW_BIT_RATE_1MBPS | \
+	CONF_HW_BIT_RATE_2MBPS | CONF_HW_BIT_RATE_5_5MBPS)
+
 struct conf_tx_rate_class {
 
 	/*
@@ -552,7 +572,7 @@
 	CONF_TX_AC_BK = 1,         /* background */
 	CONF_TX_AC_VI = 2,         /* video */
 	CONF_TX_AC_VO = 3,         /* voice */
-	CONF_TX_AC_CTS2SELF = 4,   /* fictious AC, follows AC_VO */
+	CONF_TX_AC_CTS2SELF = 4,   /* fictitious AC, follows AC_VO */
 	CONF_TX_AC_ANY_TID = 0x1f
 };
 
@@ -636,9 +656,9 @@
 
 	/*
 	 * Configuration for rate classes for TX (currently only one
-	 * rate class supported.)
+	 * rate class supported). Used in non-AP mode.
 	 */
-	struct conf_tx_rate_class rc_conf;
+	struct conf_tx_rate_class sta_rc_conf;
 
 	/*
 	 * Configuration for access categories for TX rate control.
@@ -647,6 +667,28 @@
 	struct conf_tx_ac_category ac_conf[CONF_TX_MAX_AC_COUNT];
 
 	/*
+	 * Configuration for rate classes in AP-mode. These rate classes
+	 * are for the AC TX queues
+	 */
+	struct conf_tx_rate_class ap_rc_conf[CONF_TX_MAX_AC_COUNT];
+
+	/*
+	 * Management TX rate class for AP-mode.
+	 */
+	struct conf_tx_rate_class ap_mgmt_conf;
+
+	/*
+	 * Broadcast TX rate class for AP-mode.
+	 */
+	struct conf_tx_rate_class ap_bcst_conf;
+
+	/*
+	 * AP-mode - allow this number of TX retries to a station before an
+	 * event is triggered from FW.
+	 */
+	u16 ap_max_tx_retries;
+
+	/*
 	 * Configuration for TID parameters.
 	 */
 	u8 tid_conf_count;
@@ -687,6 +729,12 @@
 	 * Range: CONF_HW_BIT_RATE_* bit mask
 	 */
 	u32 basic_rate_5;
+
+	/*
+	 * TX retry limits for templates
+	 */
+	u8 tmpl_short_retry_limit;
+	u8 tmpl_long_retry_limit;
 };
 
 enum {
@@ -912,6 +960,14 @@
 	u8 psm_entry_retries;
 
 	/*
+	 * Specifies the maximum number of times to try PSM exit if it fails
+	 * (if sending the appropriate null-func message fails.)
+	 *
+	 * Range 0 - 255
+	 */
+	u8 psm_exit_retries;
+
+	/*
 	 * Specifies the maximum number of times to try transmit the PSM entry
 	 * null-func frame for each PSM entry attempt
 	 *
@@ -1036,30 +1092,30 @@
 	/*
 	 * The minimum time to wait on each channel for active scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 min_dwell_time_active;
+	u32 min_dwell_time_active;
 
 	/*
 	 * The maximum time to wait on each channel for active scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 max_dwell_time_active;
+	u32 max_dwell_time_active;
 
 	/*
-	 * The maximum time to wait on each channel for passive scans
+	 * The minimum time to wait on each channel for passive scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 min_dwell_time_passive;
+	u32 min_dwell_time_passive;
 
 	/*
 	 * The maximum time to wait on each channel for passive scans
 	 *
-	 * Range: 0 - 65536 tu
+	 * Range: u32 tu/1000
 	 */
-	u16 max_dwell_time_passive;
+	u32 max_dwell_time_passive;
 
 	/*
 	 * Number of probe requests to transmit on each active scan channel
@@ -1090,6 +1146,51 @@
 	u8 tx_per_channel_power_compensation_5[CONF_TX_PWR_COMPENSATION_LEN_5];
 };
 
+struct conf_ht_setting {
+	u16 tx_ba_win_size;
+	u16 inactivity_timeout;
+};
+
+struct conf_memory_settings {
+	/* Number of stations supported in IBSS mode */
+	u8 num_stations;
+
+	/* Number of ssid profiles used in IBSS mode */
+	u8 ssid_profiles;
+
+	/* Number of memory buffers allocated to rx pool */
+	u8 rx_block_num;
+
+	/* Minimum number of blocks allocated to tx pool */
+	u8 tx_min_block_num;
+
+	/* Disable/Enable dynamic memory */
+	u8 dynamic_memory;
+
+	/*
+	 * Minimum required free tx memory blocks in order to assure optimum
+	 * performance
+	 *
+	 * Range: 0-120
+	 */
+	u8 min_req_tx_blocks;
+
+	/*
+	 * Minimum required free rx memory blocks in order to assure optimum
+	 * performance
+	 *
+	 * Range: 0-120
+	 */
+	u8 min_req_rx_blocks;
+
+	/*
+	 * Minimum number of mem blocks (free+used) guaranteed for TX
+	 *
+	 * Range: 0-120
+	 */
+	u8 tx_min;
+};
+
 struct conf_drv_settings {
 	struct conf_sg_settings sg;
 	struct conf_rx_settings rx;
@@ -1100,6 +1201,8 @@
 	struct conf_roam_trigger_settings roam_trigger;
 	struct conf_scan_settings scan;
 	struct conf_rf_settings rf;
+	struct conf_ht_setting ht;
+	struct conf_memory_settings mem;
 };
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/debugfs.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/debugfs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -99,7 +99,7 @@
 
 	mutex_lock(&wl->mutex);
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -261,27 +261,25 @@
 	unsigned long value;
 	int ret;
 
-	mutex_lock(&wl->mutex);
-
 	len = min(count, sizeof(buf) - 1);
 	if (copy_from_user(buf, user_buf, len)) {
-		ret = -EFAULT;
-		goto out;
+		return -EFAULT;
 	}
 	buf[len] = '\0';
 
 	ret = strict_strtoul(buf, 0, &value);
 	if (ret < 0) {
 		wl1271_warning("illegal value in gpio_power");
-		goto out;
+		return -EINVAL;
 	}
 
+	mutex_lock(&wl->mutex);
+
 	if (value)
 		wl1271_power_on(wl);
 	else
 		wl1271_power_off(wl);
 
-out:
 	mutex_unlock(&wl->mutex);
 	return count;
 }
@@ -293,12 +291,13 @@
 	.llseek = default_llseek,
 };
 
-static int wl1271_debugfs_add_files(struct wl1271 *wl)
+static int wl1271_debugfs_add_files(struct wl1271 *wl,
+				     struct dentry *rootdir)
 {
 	int ret = 0;
 	struct dentry *entry, *stats;
 
-	stats = debugfs_create_dir("fw-statistics", wl->rootdir);
+	stats = debugfs_create_dir("fw-statistics", rootdir);
 	if (!stats || IS_ERR(stats)) {
 		entry = stats;
 		goto err;
@@ -395,16 +394,11 @@
 	DEBUGFS_FWSTATS_ADD(rxpipe, missed_beacon_host_int_trig_rx_data);
 	DEBUGFS_FWSTATS_ADD(rxpipe, tx_xfr_host_int_trig_rx_data);
 
-	DEBUGFS_ADD(tx_queue_len, wl->rootdir);
-	DEBUGFS_ADD(retry_count, wl->rootdir);
-	DEBUGFS_ADD(excessive_retries, wl->rootdir);
-
-	DEBUGFS_ADD(gpio_power, wl->rootdir);
+	DEBUGFS_ADD(tx_queue_len, rootdir);
+	DEBUGFS_ADD(retry_count, rootdir);
+	DEBUGFS_ADD(excessive_retries, rootdir);
 
-	entry = debugfs_create_x32("debug_level", 0600, wl->rootdir,
-				   &wl12xx_debug_level);
-	if (!entry || IS_ERR(entry))
-		goto err;
+	DEBUGFS_ADD(gpio_power, rootdir);
 
 	return 0;
 
@@ -419,7 +413,7 @@
 
 void wl1271_debugfs_reset(struct wl1271 *wl)
 {
-	if (!wl->rootdir)
+	if (!wl->stats.fw_stats)
 		return;
 
 	memset(wl->stats.fw_stats, 0, sizeof(*wl->stats.fw_stats));
@@ -430,13 +424,13 @@
 int wl1271_debugfs_init(struct wl1271 *wl)
 {
 	int ret;
+	struct dentry *rootdir;
 
-	wl->rootdir = debugfs_create_dir(KBUILD_MODNAME,
-					 wl->hw->wiphy->debugfsdir);
+	rootdir = debugfs_create_dir(KBUILD_MODNAME,
+				     wl->hw->wiphy->debugfsdir);
 
-	if (IS_ERR(wl->rootdir)) {
-		ret = PTR_ERR(wl->rootdir);
-		wl->rootdir = NULL;
+	if (IS_ERR(rootdir)) {
+		ret = PTR_ERR(rootdir);
 		goto err;
 	}
 
@@ -450,7 +444,7 @@
 
 	wl->stats.fw_stats_update = jiffies;
 
-	ret = wl1271_debugfs_add_files(wl);
+	ret = wl1271_debugfs_add_files(wl, rootdir);
 
 	if (ret < 0)
 		goto err_file;
@@ -462,8 +456,7 @@
 	wl->stats.fw_stats = NULL;
 
 err_fw:
-	debugfs_remove_recursive(wl->rootdir);
-	wl->rootdir = NULL;
+	debugfs_remove_recursive(rootdir);
 
 err:
 	return ret;
@@ -473,8 +466,4 @@
 {
 	kfree(wl->stats.fw_stats);
 	wl->stats.fw_stats = NULL;
-
-	debugfs_remove_recursive(wl->rootdir);
-	wl->rootdir = NULL;
-
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/event.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/event.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/event.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/event.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,20 +135,6 @@
 		/* go to extremely low power mode */
 		wl1271_ps_elp_sleep(wl);
 		break;
-	case EVENT_EXIT_POWER_SAVE_FAIL:
-		wl1271_debug(DEBUG_PSM, "PSM exit failed");
-
-		if (test_bit(WL1271_FLAG_PSM, &wl->flags)) {
-			wl->psm_entry_retry = 0;
-			break;
-		}
-
-		/* make sure the firmware goes to active mode - the frame to
-		   be sent next will indicate to the AP, that we are active. */
-		ret = wl1271_ps_set_mode(wl, STATION_ACTIVE_MODE,
-					 wl->basic_rate, false);
-		break;
-	case EVENT_EXIT_POWER_SAVE_SUCCESS:
 	default:
 		break;
 	}
@@ -186,6 +172,7 @@
 	int ret;
 	u32 vector;
 	bool beacon_loss = false;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
 	wl1271_event_mbox_dump(mbox);
 
@@ -218,21 +205,21 @@
 	 * BSS_LOSE_EVENT, beacon loss has to be reported to the stack.
 	 *
 	 */
-	if (vector & BSS_LOSE_EVENT_ID) {
+	if ((vector & BSS_LOSE_EVENT_ID) && !is_ap) {
 		wl1271_info("Beacon loss detected.");
 
 		/* indicate to the stack, that beacons have been lost */
 		beacon_loss = true;
 	}
 
-	if (vector & PS_REPORT_EVENT_ID) {
+	if ((vector & PS_REPORT_EVENT_ID) && !is_ap) {
 		wl1271_debug(DEBUG_EVENT, "PS_REPORT_EVENT");
 		ret = wl1271_event_ps_report(wl, mbox, &beacon_loss);
 		if (ret < 0)
 			return ret;
 	}
 
-	if (vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID)
+	if ((vector & PSPOLL_DELIVERY_FAILURE_EVENT_ID) && !is_ap)
 		wl1271_event_pspoll_delivery_fail(wl);
 
 	if (vector & RSSI_SNR_TRIGGER_0_EVENT_ID) {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/event.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/event.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/event.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/event.h	2011-05-19 00:06:34.000000000 -0400
@@ -59,6 +59,7 @@
 	BSS_LOSE_EVENT_ID			 = BIT(18),
 	REGAINED_BSS_EVENT_ID			 = BIT(19),
 	ROAMING_TRIGGER_MAX_TX_RETRY_EVENT_ID	 = BIT(20),
+	STA_REMOVE_COMPLETE_EVENT_ID		 = BIT(21), /* AP */
 	SOFT_GEMINI_SENSE_EVENT_ID		 = BIT(22),
 	SOFT_GEMINI_PREDICTION_EVENT_ID		 = BIT(23),
 	SOFT_GEMINI_AVALANCHE_EVENT_ID		 = BIT(24),
@@ -74,8 +75,6 @@
 enum {
 	EVENT_ENTER_POWER_SAVE_FAIL = 0,
 	EVENT_ENTER_POWER_SAVE_SUCCESS,
-	EVENT_EXIT_POWER_SAVE_FAIL,
-	EVENT_EXIT_POWER_SAVE_SUCCESS,
 };
 
 struct event_debug_report {
@@ -115,7 +114,12 @@
 	u8 scheduled_scan_status;
 	u8 ps_status;
 
-	u8 reserved_5[29];
+	/* AP FW only */
+	u8 hlid_removed;
+	__le16 sta_aging_status;
+	__le16 sta_tx_retry_exceeded;
+
+	u8 reserved_5[24];
 } __packed;
 
 int wl1271_event_unmask(struct wl1271 *wl);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/init.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/init.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/init.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,27 +30,9 @@
 #include "acx.h"
 #include "cmd.h"
 #include "reg.h"
+#include "tx.h"
 
-static int wl1271_init_hwenc_config(struct wl1271 *wl)
-{
-	int ret;
-
-	ret = wl1271_acx_feature_cfg(wl);
-	if (ret < 0) {
-		wl1271_warning("couldn't set feature config");
-		return ret;
-	}
-
-	ret = wl1271_cmd_set_default_wep_key(wl, wl->default_key);
-	if (ret < 0) {
-		wl1271_warning("couldn't set default key");
-		return ret;
-	}
-
-	return 0;
-}
-
-int wl1271_init_templates_config(struct wl1271 *wl)
+int wl1271_sta_init_templates_config(struct wl1271 *wl)
 {
 	int ret, i;
 
@@ -118,6 +100,132 @@
 	return 0;
 }
 
+static int wl1271_ap_init_deauth_template(struct wl1271 *wl)
+{
+	struct wl12xx_disconn_template *tmpl;
+	int ret;
+
+	tmpl = kzalloc(sizeof(*tmpl), GFP_KERNEL);
+	if (!tmpl) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	tmpl->header.frame_ctl = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+					     IEEE80211_STYPE_DEAUTH);
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP,
+				      tmpl, sizeof(*tmpl), 0,
+				      wl1271_tx_min_rate_get(wl));
+
+out:
+	kfree(tmpl);
+	return ret;
+}
+
+static int wl1271_ap_init_null_template(struct wl1271 *wl)
+{
+	struct ieee80211_hdr_3addr *nullfunc;
+	int ret;
+
+	nullfunc = kzalloc(sizeof(*nullfunc), GFP_KERNEL);
+	if (!nullfunc) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	nullfunc->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+					      IEEE80211_STYPE_NULLFUNC |
+					      IEEE80211_FCTL_FROMDS);
+
+	/* nullfunc->addr1 is filled by FW */
+
+	memcpy(nullfunc->addr2, wl->mac_addr, ETH_ALEN);
+	memcpy(nullfunc->addr3, wl->mac_addr, ETH_ALEN);
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, nullfunc,
+				      sizeof(*nullfunc), 0,
+				      wl1271_tx_min_rate_get(wl));
+
+out:
+	kfree(nullfunc);
+	return ret;
+}
+
+static int wl1271_ap_init_qos_null_template(struct wl1271 *wl)
+{
+	struct ieee80211_qos_hdr *qosnull;
+	int ret;
+
+	qosnull = kzalloc(sizeof(*qosnull), GFP_KERNEL);
+	if (!qosnull) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	qosnull->frame_control = cpu_to_le16(IEEE80211_FTYPE_DATA |
+					     IEEE80211_STYPE_QOS_NULLFUNC |
+					     IEEE80211_FCTL_FROMDS);
+
+	/* qosnull->addr1 is filled by FW */
+
+	memcpy(qosnull->addr2, wl->mac_addr, ETH_ALEN);
+	memcpy(qosnull->addr3, wl->mac_addr, ETH_ALEN);
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, qosnull,
+				      sizeof(*qosnull), 0,
+				      wl1271_tx_min_rate_get(wl));
+
+out:
+	kfree(qosnull);
+	return ret;
+}
+
+static int wl1271_ap_init_templates_config(struct wl1271 *wl)
+{
+	int ret;
+
+	/*
+	 * Put very large empty placeholders for all templates. These
+	 * reserve memory for later.
+	 */
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_PROBE_RESPONSE, NULL,
+				      sizeof
+				      (struct wl12xx_probe_resp_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_AP_BEACON, NULL,
+				      sizeof
+				      (struct wl12xx_beacon_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_DEAUTH_AP, NULL,
+				      sizeof
+				      (struct wl12xx_disconn_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_NULL_DATA, NULL,
+				      sizeof(struct wl12xx_null_data_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_cmd_template_set(wl, CMD_TEMPL_QOS_NULL_DATA, NULL,
+				      sizeof
+				      (struct wl12xx_qos_null_data_template),
+				      0, WL1271_RATE_AUTOMATIC);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
 static int wl1271_init_rx_config(struct wl1271 *wl, u32 config, u32 filter)
 {
 	int ret;
@@ -145,10 +253,6 @@
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
-	if (ret < 0)
-		return ret;
-
 	ret = wl1271_acx_service_period_timeout(wl);
 	if (ret < 0)
 		return ret;
@@ -213,11 +317,199 @@
 	return 0;
 }
 
+static int wl1271_sta_hw_init(struct wl1271 *wl)
+{
+	int ret;
+
+	ret = wl1271_cmd_ext_radio_parms(wl);
+	if (ret < 0)
+		return ret;
+
+	/* PS config */
+	ret = wl1271_acx_config_ps(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_sta_init_templates_config(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_group_address_tbl(wl, true, NULL, 0);
+	if (ret < 0)
+		return ret;
+
+	/* Initialize connection monitoring thresholds */
+	ret = wl1271_acx_conn_monit_params(wl, false);
+	if (ret < 0)
+		return ret;
+
+	/* Beacon filtering */
+	ret = wl1271_init_beacon_filter(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Bluetooth WLAN coexistence */
+	ret = wl1271_init_pta(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Beacons and broadcast settings */
+	ret = wl1271_init_beacon_broadcast(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Configure for ELP power saving */
+	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
+	if (ret < 0)
+		return ret;
+
+	/* Configure rssi/snr averaging weights */
+	ret = wl1271_acx_rssi_snr_avg_weights(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_sta_rate_policies(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_sta_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wl1271_sta_hw_init_post_mem(struct wl1271 *wl)
+{
+	int ret, i;
+
+	ret = wl1271_cmd_set_sta_default_wep_key(wl, wl->default_key);
+	if (ret < 0) {
+		wl1271_warning("couldn't set default key");
+		return ret;
+	}
+
+	/* disable all keep-alive templates */
+	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
+		ret = wl1271_acx_keep_alive_config(wl, i,
+						   ACX_KEEP_ALIVE_TPL_INVALID);
+		if (ret < 0)
+			return ret;
+	}
+
+	/* disable the keep-alive feature */
+	ret = wl1271_acx_keep_alive_mode(wl, false);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wl1271_ap_hw_init(struct wl1271 *wl)
+{
+	int ret, i;
+
+	ret = wl1271_ap_init_templates_config(wl);
+	if (ret < 0)
+		return ret;
+
+	/* Configure for power always on */
+	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_CAM);
+	if (ret < 0)
+		return ret;
+
+	/* Configure initial TX rate classes */
+	for (i = 0; i < wl->conf.tx.ac_conf_count; i++) {
+		ret = wl1271_acx_ap_rate_policy(wl,
+				&wl->conf.tx.ap_rc_conf[i], i);
+		if (ret < 0)
+			return ret;
+	}
+
+	ret = wl1271_acx_ap_rate_policy(wl,
+					&wl->conf.tx.ap_mgmt_conf,
+					ACX_TX_AP_MODE_MGMT_RATE);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_ap_rate_policy(wl,
+					&wl->conf.tx.ap_bcst_conf,
+					ACX_TX_AP_MODE_BCST_RATE);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_max_tx_retry(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_acx_ap_mem_cfg(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static int wl1271_ap_hw_init_post_mem(struct wl1271 *wl)
+{
+	int ret;
+
+	ret = wl1271_ap_init_deauth_template(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_ap_init_null_template(wl);
+	if (ret < 0)
+		return ret;
+
+	ret = wl1271_ap_init_qos_null_template(wl);
+	if (ret < 0)
+		return ret;
+
+	return 0;
+}
+
+static void wl1271_check_ba_support(struct wl1271 *wl)
+{
+	/* validate FW cose ver x.x.x.50-60.x */
+	if ((wl->chip.fw_ver[3] >= WL12XX_BA_SUPPORT_FW_COST_VER2_START) &&
+	    (wl->chip.fw_ver[3] < WL12XX_BA_SUPPORT_FW_COST_VER2_END)) {
+		wl->ba_support = true;
+		return;
+	}
+
+	wl->ba_support = false;
+}
+
+static int wl1271_set_ba_policies(struct wl1271 *wl)
+{
+	u8 tid_index;
+	int ret = 0;
+
+	/* Reset the BA RX indicators */
+	wl->ba_rx_bitmap = 0;
+
+	/* validate that FW support BA */
+	wl1271_check_ba_support(wl);
+
+	if (wl->ba_support)
+		/* 802.11n initiator BA session setting */
+		for (tid_index = 0; tid_index < CONF_TX_MAX_TID_COUNT;
+		     ++tid_index) {
+			ret = wl1271_acx_set_ba_session(wl, WLAN_BACK_INITIATOR,
+							tid_index, true);
+			if (ret < 0)
+				break;
+		}
+
+	return ret;
+}
+
 int wl1271_hw_init(struct wl1271 *wl)
 {
 	struct conf_tx_ac_category *conf_ac;
 	struct conf_tx_tid *conf_tid;
 	int ret, i;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
 
 	ret = wl1271_cmd_general_parms(wl);
 	if (ret < 0)
@@ -227,12 +519,12 @@
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_cmd_ext_radio_parms(wl);
-	if (ret < 0)
-		return ret;
+	/* Mode specific init */
+	if (is_ap)
+		ret = wl1271_ap_hw_init(wl);
+	else
+		ret = wl1271_sta_hw_init(wl);
 
-	/* Template settings */
-	ret = wl1271_init_templates_config(wl);
 	if (ret < 0)
 		return ret;
 
@@ -259,16 +551,6 @@
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Initialize connection monitoring thresholds */
-	ret = wl1271_acx_conn_monit_params(wl, false);
-	if (ret < 0)
-		goto out_free_memmap;
-
-	/* Beacon filtering */
-	ret = wl1271_init_beacon_filter(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Configure TX patch complete interrupt behavior */
 	ret = wl1271_acx_tx_config_options(wl);
 	if (ret < 0)
@@ -279,21 +561,11 @@
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Bluetooth WLAN coexistence */
-	ret = wl1271_init_pta(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Energy detection */
 	ret = wl1271_init_energy_detection(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Beacons and boradcast settings */
-	ret = wl1271_init_beacon_broadcast(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Default fragmentation threshold */
 	ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
 	if (ret < 0)
@@ -321,23 +593,13 @@
 			goto out_free_memmap;
 	}
 
-	/* Configure TX rate classes */
-	ret = wl1271_acx_rate_policies(wl);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Enable data path */
 	ret = wl1271_cmd_data_path(wl, 1);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Configure for ELP power saving */
-	ret = wl1271_acx_sleep_auth(wl, WL1271_PSM_ELP);
-	if (ret < 0)
-		goto out_free_memmap;
-
 	/* Configure HW encryption */
-	ret = wl1271_init_hwenc_config(wl);
+	ret = wl1271_acx_feature_cfg(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
@@ -346,21 +608,17 @@
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* disable all keep-alive templates */
-	for (i = 0; i < CMD_TEMPL_KLV_IDX_MAX; i++) {
-		ret = wl1271_acx_keep_alive_config(wl, i,
-						   ACX_KEEP_ALIVE_TPL_INVALID);
-		if (ret < 0)
-			goto out_free_memmap;
-	}
+	/* Mode specific init - post mem init */
+	if (is_ap)
+		ret = wl1271_ap_hw_init_post_mem(wl);
+	else
+		ret = wl1271_sta_hw_init_post_mem(wl);
 
-	/* disable the keep-alive feature */
-	ret = wl1271_acx_keep_alive_mode(wl, false);
 	if (ret < 0)
 		goto out_free_memmap;
 
-	/* Configure rssi/snr averaging weights */
-	ret = wl1271_acx_rssi_snr_avg_weights(wl);
+	/* Configure initiator BA sessions policies */
+	ret = wl1271_set_ba_policies(wl);
 	if (ret < 0)
 		goto out_free_memmap;
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/init.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/init.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/init.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/init.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 #include "wl12xx.h"
 
 int wl1271_hw_init_power_auth(struct wl1271 *wl);
-int wl1271_init_templates_config(struct wl1271 *wl);
+int wl1271_sta_init_templates_config(struct wl1271 *wl);
 int wl1271_init_phy_config(struct wl1271 *wl);
 int wl1271_init_pta(struct wl1271 *wl);
 int wl1271_init_energy_detection(struct wl1271 *wl);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/io.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/io.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/io.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/io.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,7 +94,7 @@
 	 * translated region.
 	 *
 	 * The translated regions occur next to each other in physical device
-	 * memory, so just add the sizes of the preceeding address regions to
+	 * memory, so just add the sizes of the preceding address regions to
 	 * get the offset to the new region.
 	 *
 	 * Currently, only the two first regions are addressed, and the
@@ -168,5 +168,6 @@
 int wl1271_init_ieee80211(struct wl1271 *wl);
 struct ieee80211_hw *wl1271_alloc_hw(void);
 int wl1271_free_hw(struct wl1271 *wl);
+irqreturn_t wl1271_irq(int irq, void *data);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/Kconfig linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/Kconfig
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 
 config WL12XX_SDIO_TEST
 	tristate "TI wl12xx SDIO testing support"
-	depends on WL12XX && MMC
+	depends on WL12XX && MMC && WL12XX_SDIO
 	default n
 	---help---
 	  This module adds support for the SDIO bus testing with the
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/main.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/main.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/main.c	2012-03-24 01:15:26.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/main.c	2012-03-24 03:34:53.000000000 -0400
@@ -116,11 +116,11 @@
 	},
 	.tx = {
 		.tx_energy_detection         = 0,
-		.rc_conf                     = {
+		.sta_rc_conf                 = {
 			.enabled_rates       = 0,
 			.short_retry_limit   = 10,
 			.long_retry_limit    = 10,
-			.aflags              = 0
+			.aflags              = 0,
 		},
 		.ac_conf_count               = 4,
 		.ac_conf                     = {
@@ -153,6 +153,45 @@
 				.tx_op_limit = 1504,
 			},
 		},
+		.ap_rc_conf                  = {
+			[0] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[1] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[2] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+			[3] = {
+				.enabled_rates = CONF_TX_AP_ENABLED_RATES,
+				.short_retry_limit = 10,
+				.long_retry_limit = 10,
+				.aflags      = 0,
+			},
+		},
+		.ap_mgmt_conf = {
+			.enabled_rates       = CONF_TX_AP_DEFAULT_MGMT_RATES,
+			.short_retry_limit   = 10,
+			.long_retry_limit    = 10,
+			.aflags              = 0,
+		},
+		.ap_bcst_conf = {
+			.enabled_rates       = CONF_HW_BIT_RATE_1MBPS,
+			.short_retry_limit   = 10,
+			.long_retry_limit    = 10,
+			.aflags              = 0,
+		},
+		.ap_max_tx_retries = 100,
 		.tid_conf_count = 4,
 		.tid_conf = {
 			[CONF_TX_AC_BE] = {
@@ -193,6 +232,8 @@
 		.tx_compl_threshold          = 4,
 		.basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
 		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
+		.tmpl_short_retry_limit      = 10,
+		.tmpl_long_retry_limit       = 10,
 	},
 	.conn = {
 		.wake_up_event               = CONF_WAKE_UP_EVENT_DTIM,
@@ -215,6 +256,7 @@
 		.bet_enable                  = CONF_BET_MODE_ENABLE,
 		.bet_max_consecutive         = 10,
 		.psm_entry_retries           = 5,
+		.psm_exit_retries            = 255,
 		.psm_entry_nullfunc_retries  = 3,
 		.psm_entry_hangover_period   = 1,
 		.keep_alive_interval         = 55000,
@@ -233,13 +275,13 @@
 		.avg_weight_rssi_beacon       = 20,
 		.avg_weight_rssi_data         = 10,
 		.avg_weight_snr_beacon        = 20,
-		.avg_weight_snr_data          = 10
+		.avg_weight_snr_data          = 10,
 	},
 	.scan = {
 		.min_dwell_time_active        = 7500,
 		.max_dwell_time_active        = 30000,
-		.min_dwell_time_passive       = 30000,
-		.max_dwell_time_passive       = 60000,
+		.min_dwell_time_passive       = 100000,
+		.max_dwell_time_passive       = 100000,
 		.num_probe_reqs               = 2,
 	},
 	.rf = {
@@ -252,9 +294,24 @@
 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 		},
 	},
+	.ht = {
+		.tx_ba_win_size = 64,
+		.inactivity_timeout = 10000,
+	},
+	.mem = {
+		.num_stations                 = 1,
+		.ssid_profiles                = 1,
+		.rx_block_num                 = 70,
+		.tx_min_block_num             = 40,
+		.dynamic_memory               = 0,
+		.min_req_tx_blocks            = 100,
+		.min_req_rx_blocks            = 22,
+		.tx_min                       = 27,
+	}
 };
 
 static void __wl1271_op_remove_interface(struct wl1271 *wl);
+static void wl1271_free_ap_keys(struct wl1271 *wl);
 
 
 static void wl1271_device_release(struct device *dev)
@@ -317,7 +374,7 @@
 	if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -393,7 +450,7 @@
 	if (ret < 0)
 		return ret;
 
-	ret = wl1271_init_templates_config(wl);
+	ret = wl1271_sta_init_templates_config(wl);
 	if (ret < 0)
 		return ret;
 
@@ -425,6 +482,10 @@
 	if (ret < 0)
 		goto out_free_memmap;
 
+	ret = wl1271_acx_sta_mem_cfg(wl);
+	if (ret < 0)
+		goto out_free_memmap;
+
 	/* Default fragmentation threshold */
 	ret = wl1271_acx_frag_threshold(wl, wl->conf.tx.frag_threshold);
 	if (ret < 0)
@@ -476,14 +537,71 @@
 	return ret;
 }
 
+static void wl1271_irq_ps_regulate_link(struct wl1271 *wl, u8 hlid, u8 tx_blks)
+{
+	bool fw_ps;
+
+	/* only regulate station links */
+	if (hlid < WL1271_AP_STA_HLID_START)
+		return;
+
+	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+
+	/*
+	 * Wake up from high level PS if the STA is asleep with too little
+	 * blocks in FW or if the STA is awake.
+	 */
+	if (!fw_ps || tx_blks < WL1271_PS_STA_MAX_BLOCKS)
+		wl1271_ps_link_end(wl, hlid);
+
+	/* Start high-level PS if the STA is asleep with enough blocks in FW */
+	else if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+		wl1271_ps_link_start(wl, hlid, true);
+}
+
+static void wl1271_irq_update_links_status(struct wl1271 *wl,
+				       struct wl1271_fw_ap_status *status)
+{
+	u32 cur_fw_ps_map;
+	u8 hlid;
+
+	cur_fw_ps_map = le32_to_cpu(status->link_ps_bitmap);
+	if (wl->ap_fw_ps_map != cur_fw_ps_map) {
+		wl1271_debug(DEBUG_PSM,
+			     "link ps prev 0x%x cur 0x%x changed 0x%x",
+			     wl->ap_fw_ps_map, cur_fw_ps_map,
+			     wl->ap_fw_ps_map ^ cur_fw_ps_map);
+
+		wl->ap_fw_ps_map = cur_fw_ps_map;
+	}
+
+	for (hlid = WL1271_AP_STA_HLID_START; hlid < AP_MAX_LINKS; hlid++) {
+		u8 cnt = status->tx_lnk_free_blks[hlid] -
+			wl->links[hlid].prev_freed_blks;
+
+		wl->links[hlid].prev_freed_blks =
+			status->tx_lnk_free_blks[hlid];
+		wl->links[hlid].allocated_blks -= cnt;
+
+		wl1271_irq_ps_regulate_link(wl, hlid,
+					    wl->links[hlid].allocated_blks);
+	}
+}
+
 static void wl1271_fw_status(struct wl1271 *wl,
-			     struct wl1271_fw_status *status)
+			     struct wl1271_fw_full_status *full_status)
 {
+	struct wl1271_fw_common_status *status = &full_status->common;
 	struct timespec ts;
 	u32 total = 0;
 	int i;
 
-	wl1271_raw_read(wl, FW_STATUS_ADDR, status, sizeof(*status), false);
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+				sizeof(struct wl1271_fw_ap_status), false);
+	else
+		wl1271_raw_read(wl, FW_STATUS_ADDR, status,
+				sizeof(struct wl1271_fw_sta_status), false);
 
 	wl1271_debug(DEBUG_IRQ, "intr: 0x%x (fw_rx_counter = %d, "
 		     "drv_rx_counter = %d, tx_results_counter = %d)",
@@ -507,22 +625,54 @@
 	if (total)
 		clear_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags);
 
+	/* for AP update num of allocated TX blocks per link and ps status */
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		wl1271_irq_update_links_status(wl, &full_status->ap);
+
 	/* update the host-chipset time offset */
 	getnstimeofday(&ts);
 	wl->time_offset = (timespec_to_ns(&ts) >> 10) -
 		(s64)le32_to_cpu(status->fw_localtime);
 }
 
-#define WL1271_IRQ_MAX_LOOPS 10
+static void wl1271_flush_deferred_work(struct wl1271 *wl)
+{
+	struct sk_buff *skb;
 
-static void wl1271_irq_work(struct work_struct *work)
+	/* Pass all received frames to the network stack */
+	while ((skb = skb_dequeue(&wl->deferred_rx_queue)))
+		ieee80211_rx_ni(wl->hw, skb);
+
+	/* Return sent skbs to the network stack */
+	while ((skb = skb_dequeue(&wl->deferred_tx_queue)))
+		ieee80211_tx_status(wl->hw, skb);
+}
+
+static void wl1271_netstack_work(struct work_struct *work)
+{
+	struct wl1271 *wl =
+		container_of(work, struct wl1271, netstack_work);
+
+	do {
+		wl1271_flush_deferred_work(wl);
+	} while (skb_queue_len(&wl->deferred_rx_queue));
+}
+
+#define WL1271_IRQ_MAX_LOOPS 256
+
+irqreturn_t wl1271_irq(int irq, void *cookie)
 {
 	int ret;
 	u32 intr;
 	int loopcount = WL1271_IRQ_MAX_LOOPS;
+	struct wl1271 *wl = (struct wl1271 *)cookie;
+	bool done = false;
+	unsigned int defer_count;
 	unsigned long flags;
-	struct wl1271 *wl =
-		container_of(work, struct wl1271, irq_work);
+
+	/* TX might be handled here, avoid redundant work */
+	set_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
+	cancel_work_sync(&wl->tx_work);
 
 	mutex_lock(&wl->mutex);
 
@@ -531,26 +681,27 @@
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, true);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	while (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags) && loopcount) {
-		clear_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-		loopcount--;
+	while (!done && loopcount--) {
+		/*
+		 * In order to avoid a race with the hardirq, clear the flag
+		 * before acknowledging the chip. Since the mutex is held,
+		 * wl1271_ps_elp_wakeup cannot be called concurrently.
+		 */
+		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
+		smp_mb__after_clear_bit();
 
 		wl1271_fw_status(wl, wl->fw_status);
-		intr = le32_to_cpu(wl->fw_status->intr);
+		intr = le32_to_cpu(wl->fw_status->common.intr);
+		intr &= WL1271_INTR_MASK;
 		if (!intr) {
-			wl1271_debug(DEBUG_IRQ, "Zero interrupt received.");
-			spin_lock_irqsave(&wl->wl_lock, flags);
+			done = true;
 			continue;
 		}
 
-		intr &= WL1271_INTR_MASK;
-
 		if (unlikely(intr & WL1271_ACX_INTR_WATCHDOG)) {
 			wl1271_error("watchdog interrupt received! "
 				     "starting recovery.");
@@ -560,25 +711,35 @@
 			goto out;
 		}
 
-		if (intr & WL1271_ACX_INTR_DATA) {
+		if (likely(intr & WL1271_ACX_INTR_DATA)) {
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_DATA");
 
-			/* check for tx results */
-			if (wl->fw_status->tx_results_counter !=
-			    (wl->tx_results_count & 0xff))
-				wl1271_tx_complete(wl);
+			wl1271_rx(wl, &wl->fw_status->common);
 
 			/* Check if any tx blocks were freed */
+			spin_lock_irqsave(&wl->wl_lock, flags);
 			if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
 			    wl->tx_queue_count) {
+				spin_unlock_irqrestore(&wl->wl_lock, flags);
 				/*
 				 * In order to avoid starvation of the TX path,
 				 * call the work function directly.
 				 */
 				wl1271_tx_work_locked(wl);
+			} else {
+				spin_unlock_irqrestore(&wl->wl_lock, flags);
 			}
 
-			wl1271_rx(wl, wl->fw_status);
+			/* check for tx results */
+			if (wl->fw_status->common.tx_results_counter !=
+			    (wl->tx_results_count & 0xff))
+				wl1271_tx_complete(wl);
+
+			/* Make sure the deferred queues don't get too long */
+			defer_count = skb_queue_len(&wl->deferred_tx_queue) +
+				      skb_queue_len(&wl->deferred_rx_queue);
+			if (defer_count > WL1271_DEFERRED_QUEUE_LIMIT)
+				wl1271_flush_deferred_work(wl);
 		}
 
 		if (intr & WL1271_ACX_INTR_EVENT_A) {
@@ -597,28 +758,48 @@
 
 		if (intr & WL1271_ACX_INTR_HW_AVAILABLE)
 			wl1271_debug(DEBUG_IRQ, "WL1271_ACX_INTR_HW_AVAILABLE");
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
 	}
 
-	if (test_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->irq_work);
-	else
-		clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
 	wl1271_ps_elp_sleep(wl);
 
 out:
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	/* In case TX was not handled here, queue TX work */
+	clear_bit(WL1271_FLAG_TX_PENDING, &wl->flags);
+	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
+	    wl->tx_queue_count)
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
 	mutex_unlock(&wl->mutex);
+
+	return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(wl1271_irq);
 
 static int wl1271_fetch_firmware(struct wl1271 *wl)
 {
 	const struct firmware *fw;
+	const char *fw_name;
 	int ret;
 
-	ret = reject_firmware(&fw, WL1271_FW_NAME, wl1271_wl_to_dev(wl));
+	switch (wl->bss_type) {
+	case BSS_TYPE_AP_BSS:
+		fw_name = WL1271_AP_FW_NAME;
+		break;
+	case BSS_TYPE_IBSS:
+	case BSS_TYPE_STA_BSS:
+		fw_name = WL1271_FW_NAME;
+		break;
+	default:
+		wl1271_error("no compatible firmware for bss_type %d",
+			     wl->bss_type);
+		return -EINVAL;
+	}
+
+	wl1271_debug(DEBUG_BOOT, "booting firmware %s", fw_name);
+
+	ret = reject_firmware(&fw, fw_name, wl1271_wl_to_dev(wl));
 
 	if (ret < 0) {
 		wl1271_error("could not get firmware: %d", ret);
@@ -632,6 +813,7 @@
 		goto out;
 	}
 
+	vfree(wl->fw);
 	wl->fw_len = fw->size;
 	wl->fw = vmalloc(wl->fw_len);
 
@@ -642,7 +824,7 @@
 	}
 
 	memcpy(wl->fw, fw->data, wl->fw_len);
-
+	wl->fw_bss_type = wl->bss_type;
 	ret = 0;
 
 out:
@@ -778,7 +960,8 @@
 		goto out;
 	}
 
-	if (wl->fw == NULL) {
+	/* Make sure the firmware type matches the BSS type */
+	if (wl->fw == NULL || wl->fw_bss_type != wl->bss_type) {
 		ret = wl1271_fetch_firmware(wl);
 		if (ret < 0)
 			goto out;
@@ -811,6 +994,8 @@
 		goto out;
 	}
 
+	wl->bss_type = BSS_TYPE_STA_BSS;
+
 	while (retries) {
 		retries--;
 		ret = wl1271_chip_wakeup(wl);
@@ -827,11 +1012,10 @@
 
 		wl->state = WL1271_STATE_PLT;
 		wl1271_notice("firmware booted in PLT mode (%s)",
-			      wl->chip.fw_ver);
+			      wl->chip.fw_ver_str);
 		goto out;
 
 irq_disable:
-		wl1271_disable_interrupts(wl);
 		mutex_unlock(&wl->mutex);
 		/* Unlocking the mutex in the middle of handling is
 		   inherently unsafe. In this case we deem it safe to do,
@@ -840,7 +1024,9 @@
 		   work function will not do anything.) Also, any other
 		   possible concurrent operations will fail due to the
 		   current state, hence the wl1271 struct should be safe. */
-		cancel_work_sync(&wl->irq_work);
+		wl1271_disable_interrupts(wl);
+		wl1271_flush_deferred_work(wl);
+		cancel_work_sync(&wl->netstack_work);
 		mutex_lock(&wl->mutex);
 power_off:
 		wl1271_power_off(wl);
@@ -854,12 +1040,10 @@
 	return ret;
 }
 
-int wl1271_plt_stop(struct wl1271 *wl)
+int __wl1271_plt_stop(struct wl1271 *wl)
 {
 	int ret = 0;
 
-	mutex_lock(&wl->mutex);
-
 	wl1271_notice("power down");
 
 	if (wl->state != WL1271_STATE_PLT) {
@@ -869,70 +1053,46 @@
 		goto out;
 	}
 
-	wl1271_disable_interrupts(wl);
 	wl1271_power_off(wl);
 
 	wl->state = WL1271_STATE_OFF;
 	wl->rx_counter = 0;
 
-out:
 	mutex_unlock(&wl->mutex);
-
-	cancel_work_sync(&wl->irq_work);
+	wl1271_disable_interrupts(wl);
+	wl1271_flush_deferred_work(wl);
+	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->recovery_work);
+	mutex_lock(&wl->mutex);
+out:
+	return ret;
+}
+
+int wl1271_plt_stop(struct wl1271 *wl)
+{
+	int ret;
 
+	mutex_lock(&wl->mutex);
+	ret = __wl1271_plt_stop(wl);
+	mutex_unlock(&wl->mutex);
 	return ret;
 }
 
-static int wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
-	struct ieee80211_conf *conf = &hw->conf;
-	struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
-	struct ieee80211_sta *sta = txinfo->control.sta;
 	unsigned long flags;
 	int q;
+	u8 hlid = 0;
 
-	/*
-	 * peek into the rates configured in the STA entry.
-	 * The rates set after connection stage, The first block only BG sets:
-	 * the compare is for bit 0-16 of sta_rate_set. The second block add
-	 * HT rates in case of HT supported.
-	 */
-	spin_lock_irqsave(&wl->wl_lock, flags);
-	if (sta &&
-	    (sta->supp_rates[conf->channel->band] !=
-	    (wl->sta_rate_set & HW_BG_RATES_MASK))) {
-		wl->sta_rate_set = sta->supp_rates[conf->channel->band];
-		set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
-	}
-
-#ifdef CONFIG_WL12XX_HT
-	if (sta &&
-	    sta->ht_cap.ht_supported &&
-	    ((wl->sta_rate_set >> HW_HT_RATES_OFFSET) !=
-	      sta->ht_cap.mcs.rx_mask[0])) {
-		/* Clean MCS bits before setting them */
-		wl->sta_rate_set &= HW_BG_RATES_MASK;
-		wl->sta_rate_set |=
-			(sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
-		set_bit(WL1271_FLAG_STA_RATES_CHANGED, &wl->flags);
-	}
-#endif
-	wl->tx_queue_count++;
-	spin_unlock_irqrestore(&wl->wl_lock, flags);
-
-	/* queue the packet */
 	q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
-	skb_queue_tail(&wl->tx_queue[q], skb);
 
-	/*
-	 * The chip specific setup must run before the first TX packet -
-	 * before that, the tx_work will not be initialized!
-	 */
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		hlid = wl1271_tx_get_hlid(skb);
 
-	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	spin_lock_irqsave(&wl->wl_lock, flags);
+
+	wl->tx_queue_count++;
 
 	/*
 	 * The workqueue is slow to process the tx_queue and we need stop
@@ -940,14 +1100,28 @@
 	 */
 	if (wl->tx_queue_count >= WL1271_TX_QUEUE_HIGH_WATERMARK) {
 		wl1271_debug(DEBUG_TX, "op_tx: stopping queues");
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
 		ieee80211_stop_queues(wl->hw);
 		set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
 	}
 
-	return NETDEV_TX_OK;
+	/* queue the packet */
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		wl1271_debug(DEBUG_TX, "queue skb hlid %d q %d", hlid, q);
+		skb_queue_tail(&wl->links[hlid].tx_queue[q], skb);
+	} else {
+		skb_queue_tail(&wl->tx_queue[q], skb);
+	}
+
+	/*
+	 * The chip specific setup must run before the first TX packet -
+	 * before that, the tx_work will not be initialized!
+	 */
+
+	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
+	    !test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
+		ieee80211_queue_work(wl->hw, &wl->tx_work);
+
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
 }
 
 static struct notifier_block wl1271_dev_notifier = {
@@ -967,6 +1141,9 @@
 	 *
 	 * The MAC address is first known when the corresponding interface
 	 * is added. That is where we will initialize the hardware.
+	 *
+	 * In addition, we currently have different firmwares for AP and managed
+	 * operation. We will know which to boot according to interface type.
 	 */
 
 	return 0;
@@ -1006,6 +1183,9 @@
 		wl->bss_type = BSS_TYPE_IBSS;
 		wl->set_bss_type = BSS_TYPE_STA_BSS;
 		break;
+	case NL80211_IFTYPE_AP:
+		wl->bss_type = BSS_TYPE_AP_BSS;
+		break;
 	default:
 		ret = -EOPNOTSUPP;
 		goto out;
@@ -1038,7 +1218,6 @@
 		break;
 
 irq_disable:
-		wl1271_disable_interrupts(wl);
 		mutex_unlock(&wl->mutex);
 		/* Unlocking the mutex in the middle of handling is
 		   inherently unsafe. In this case we deem it safe to do,
@@ -1047,7 +1226,9 @@
 		   work function will not do anything.) Also, any other
 		   possible concurrent operations will fail due to the
 		   current state, hence the wl1271 struct should be safe. */
-		cancel_work_sync(&wl->irq_work);
+		wl1271_disable_interrupts(wl);
+		wl1271_flush_deferred_work(wl);
+		cancel_work_sync(&wl->netstack_work);
 		mutex_lock(&wl->mutex);
 power_off:
 		wl1271_power_off(wl);
@@ -1061,11 +1242,11 @@
 
 	wl->vif = vif;
 	wl->state = WL1271_STATE_ON;
-	wl1271_info("firmware booted (%s)", wl->chip.fw_ver);
+	wl1271_info("firmware booted (%s)", wl->chip.fw_ver_str);
 
 	/* update hw/fw version info in wiphy struct */
 	wiphy->hw_version = wl->chip.id;
-	strncpy(wiphy->fw_version, wl->chip.fw_ver,
+	strncpy(wiphy->fw_version, wl->chip.fw_ver_str,
 		sizeof(wiphy->fw_version));
 
 	/*
@@ -1113,12 +1294,12 @@
 
 	wl->state = WL1271_STATE_OFF;
 
-	wl1271_disable_interrupts(wl);
-
 	mutex_unlock(&wl->mutex);
 
+	wl1271_disable_interrupts(wl);
+	wl1271_flush_deferred_work(wl);
 	cancel_delayed_work_sync(&wl->scan_complete_work);
-	cancel_work_sync(&wl->irq_work);
+	cancel_work_sync(&wl->netstack_work);
 	cancel_work_sync(&wl->tx_work);
 	cancel_delayed_work_sync(&wl->pspoll_work);
 	cancel_delayed_work_sync(&wl->elp_work);
@@ -1147,10 +1328,13 @@
 	wl->time_offset = 0;
 	wl->session_counter = 0;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
-	wl->sta_rate_set = 0;
 	wl->flags = 0;
 	wl->vif = NULL;
 	wl->filters = 0;
+	wl1271_free_ap_keys(wl);
+	memset(wl->ap_hlid_map, 0, sizeof(wl->ap_hlid_map));
+	wl->ap_fw_ps_map = 0;
+	wl->ap_ps_map = 0;
 
 	for (i = 0; i < NUM_TX_QUEUES; i++)
 		wl->tx_blocks_freed[i] = 0;
@@ -1186,8 +1370,7 @@
 
 static void wl1271_configure_filters(struct wl1271 *wl, unsigned int filters)
 {
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+	wl1271_set_default_filters(wl);
 
 	/* combine requested filters with current filter config */
 	filters = wl->filters | filters;
@@ -1322,25 +1505,7 @@
 		wl->basic_rate_set = wl->conf.tx.basic_rate_5;
 }
 
-static u32 wl1271_min_rate_get(struct wl1271 *wl)
-{
-	int i;
-	u32 rate = 0;
-
-	if (!wl->basic_rate_set) {
-		WARN_ON(1);
-		wl->basic_rate_set = wl->conf.tx.basic_rate;
-	}
-
-	for (i = 0; !rate; i++) {
-		if ((wl->basic_rate_set >> i) & 0x1)
-			rate = 1 << i;
-	}
-
-	return rate;
-}
-
-static int wl1271_handle_idle(struct wl1271 *wl, bool idle)
+static int wl1271_sta_handle_idle(struct wl1271 *wl, bool idle)
 {
 	int ret;
 
@@ -1350,9 +1515,8 @@
 			if (ret < 0)
 				goto out;
 		}
-		wl->rate_set = wl1271_min_rate_get(wl);
-		wl->sta_rate_set = 0;
-		ret = wl1271_acx_rate_policies(wl);
+		wl->rate_set = wl1271_tx_min_rate_get(wl);
+		ret = wl1271_acx_sta_rate_policies(wl);
 		if (ret < 0)
 			goto out;
 		ret = wl1271_acx_keep_alive_config(
@@ -1381,14 +1545,17 @@
 	struct wl1271 *wl = hw->priv;
 	struct ieee80211_conf *conf = &hw->conf;
 	int channel, ret = 0;
+	bool is_ap;
 
 	channel = ieee80211_frequency_to_channel(conf->channel->center_freq);
 
-	wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s",
+	wl1271_debug(DEBUG_MAC80211, "mac80211 config ch %d psm %s power %d %s"
+		     " changed 0x%x",
 		     channel,
 		     conf->flags & IEEE80211_CONF_PS ? "on" : "off",
 		     conf->power_level,
-		     conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use");
+		     conf->flags & IEEE80211_CONF_IDLE ? "idle" : "in use",
+			 changed);
 
 	/*
 	 * mac80211 will go to idle nearly immediately after transmitting some
@@ -1406,7 +1573,9 @@
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1417,31 +1586,34 @@
 		wl->band = conf->channel->band;
 		wl->channel = channel;
 
-		/*
-		 * FIXME: the mac80211 should really provide a fixed rate
-		 * to use here. for now, just use the smallest possible rate
-		 * for the band as a fixed rate for association frames and
-		 * other control messages.
-		 */
-		if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
-			wl1271_set_band_rate(wl);
-
-		wl->basic_rate = wl1271_min_rate_get(wl);
-		ret = wl1271_acx_rate_policies(wl);
-		if (ret < 0)
-			wl1271_warning("rate policy for update channel "
-				       "failed %d", ret);
+		if (!is_ap) {
+			/*
+			 * FIXME: the mac80211 should really provide a fixed
+			 * rate to use here. for now, just use the smallest
+			 * possible rate for the band as a fixed rate for
+			 * association frames and other control messages.
+			 */
+			if (!test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
+				wl1271_set_band_rate(wl);
 
-		if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
-			ret = wl1271_join(wl, false);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
-				wl1271_warning("cmd join to update channel "
+				wl1271_warning("rate policy for channel "
 					       "failed %d", ret);
+
+			if (test_bit(WL1271_FLAG_JOINED, &wl->flags)) {
+				ret = wl1271_join(wl, false);
+				if (ret < 0)
+					wl1271_warning("cmd join on channel "
+						       "failed %d", ret);
+			}
 		}
 	}
 
-	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
-		ret = wl1271_handle_idle(wl, conf->flags & IEEE80211_CONF_IDLE);
+	if (changed & IEEE80211_CONF_CHANGE_IDLE && !is_ap) {
+		ret = wl1271_sta_handle_idle(wl,
+					conf->flags & IEEE80211_CONF_IDLE);
 		if (ret < 0)
 			wl1271_warning("idle mode change failed %d", ret);
 	}
@@ -1548,7 +1720,8 @@
 	struct wl1271 *wl = hw->priv;
 	int ret;
 
-	wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter");
+	wl1271_debug(DEBUG_MAC80211, "mac80211 configure filter changed %x"
+		     " total %x", changed, *total);
 
 	mutex_lock(&wl->mutex);
 
@@ -1558,19 +1731,20 @@
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
-
-	if (*total & FIF_ALLMULTI)
-		ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
-	else if (fp)
-		ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
-						   fp->mc_list,
-						   fp->mc_list_length);
-	if (ret < 0)
-		goto out_sleep;
+	if (wl->bss_type != BSS_TYPE_AP_BSS) {
+		if (*total & FIF_ALLMULTI)
+			ret = wl1271_acx_group_address_tbl(wl, false, NULL, 0);
+		else if (fp)
+			ret = wl1271_acx_group_address_tbl(wl, fp->enabled,
+							   fp->mc_list,
+							   fp->mc_list_length);
+		if (ret < 0)
+			goto out_sleep;
+	}
 
 	/* determine, whether supported filter values have changed */
 	if (changed == 0)
@@ -1593,38 +1767,192 @@
 	kfree(fp);
 }
 
+static int wl1271_record_ap_key(struct wl1271 *wl, u8 id, u8 key_type,
+			u8 key_size, const u8 *key, u8 hlid, u32 tx_seq_32,
+			u16 tx_seq_16)
+{
+	struct wl1271_ap_key *ap_key;
+	int i;
+
+	wl1271_debug(DEBUG_CRYPT, "record ap key id %d", (int)id);
+
+	if (key_size > MAX_KEY_SIZE)
+		return -EINVAL;
+
+	/*
+	 * Find next free entry in ap_keys. Also check we are not replacing
+	 * an existing key.
+	 */
+	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		if (wl->recorded_ap_keys[i] == NULL)
+			break;
+
+		if (wl->recorded_ap_keys[i]->id == id) {
+			wl1271_warning("trying to record key replacement");
+			return -EINVAL;
+		}
+	}
+
+	if (i == MAX_NUM_KEYS)
+		return -EBUSY;
+
+	ap_key = kzalloc(sizeof(*ap_key), GFP_KERNEL);
+	if (!ap_key)
+		return -ENOMEM;
+
+	ap_key->id = id;
+	ap_key->key_type = key_type;
+	ap_key->key_size = key_size;
+	memcpy(ap_key->key, key, key_size);
+	ap_key->hlid = hlid;
+	ap_key->tx_seq_32 = tx_seq_32;
+	ap_key->tx_seq_16 = tx_seq_16;
+
+	wl->recorded_ap_keys[i] = ap_key;
+	return 0;
+}
+
+static void wl1271_free_ap_keys(struct wl1271 *wl)
+{
+	int i;
+
+	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		kfree(wl->recorded_ap_keys[i]);
+		wl->recorded_ap_keys[i] = NULL;
+	}
+}
+
+static int wl1271_ap_init_hwenc(struct wl1271 *wl)
+{
+	int i, ret = 0;
+	struct wl1271_ap_key *key;
+	bool wep_key_added = false;
+
+	for (i = 0; i < MAX_NUM_KEYS; i++) {
+		if (wl->recorded_ap_keys[i] == NULL)
+			break;
+
+		key = wl->recorded_ap_keys[i];
+		ret = wl1271_cmd_set_ap_key(wl, KEY_ADD_OR_REPLACE,
+					    key->id, key->key_type,
+					    key->key_size, key->key,
+					    key->hlid, key->tx_seq_32,
+					    key->tx_seq_16);
+		if (ret < 0)
+			goto out;
+
+		if (key->key_type == KEY_WEP)
+			wep_key_added = true;
+	}
+
+	if (wep_key_added) {
+		ret = wl1271_cmd_set_ap_default_wep_key(wl, wl->default_key);
+		if (ret < 0)
+			goto out;
+	}
+
+out:
+	wl1271_free_ap_keys(wl);
+	return ret;
+}
+
+static int wl1271_set_key(struct wl1271 *wl, u16 action, u8 id, u8 key_type,
+		       u8 key_size, const u8 *key, u32 tx_seq_32,
+		       u16 tx_seq_16, struct ieee80211_sta *sta)
+{
+	int ret;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+
+	if (is_ap) {
+		struct wl1271_station *wl_sta;
+		u8 hlid;
+
+		if (sta) {
+			wl_sta = (struct wl1271_station *)sta->drv_priv;
+			hlid = wl_sta->hlid;
+		} else {
+			hlid = WL1271_AP_BROADCAST_HLID;
+		}
+
+		if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+			/*
+			 * We do not support removing keys after AP shutdown.
+			 * Pretend we do to make mac80211 happy.
+			 */
+			if (action != KEY_ADD_OR_REPLACE)
+				return 0;
+
+			ret = wl1271_record_ap_key(wl, id,
+					     key_type, key_size,
+					     key, hlid, tx_seq_32,
+					     tx_seq_16);
+		} else {
+			ret = wl1271_cmd_set_ap_key(wl, action,
+					     id, key_type, key_size,
+					     key, hlid, tx_seq_32,
+					     tx_seq_16);
+		}
+
+		if (ret < 0)
+			return ret;
+	} else {
+		const u8 *addr;
+		static const u8 bcast_addr[ETH_ALEN] = {
+			0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+		};
+
+		addr = sta ? sta->addr : bcast_addr;
+
+		if (is_zero_ether_addr(addr)) {
+			/* We dont support TX only encryption */
+			return -EOPNOTSUPP;
+		}
+
+		/* The wl1271 does not allow to remove unicast keys - they
+		   will be cleared automatically on next CMD_JOIN. Ignore the
+		   request silently, as we dont want the mac80211 to emit
+		   an error message. */
+		if (action == KEY_REMOVE && !is_broadcast_ether_addr(addr))
+			return 0;
+
+		ret = wl1271_cmd_set_sta_key(wl, action,
+					     id, key_type, key_size,
+					     key, addr, tx_seq_32,
+					     tx_seq_16);
+		if (ret < 0)
+			return ret;
+
+		/* the default WEP key needs to be configured at least once */
+		if (key_type == KEY_WEP) {
+			ret = wl1271_cmd_set_sta_default_wep_key(wl,
+							wl->default_key);
+			if (ret < 0)
+				return ret;
+		}
+	}
+
+	return 0;
+}
+
 static int wl1271_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 			     struct ieee80211_vif *vif,
 			     struct ieee80211_sta *sta,
 			     struct ieee80211_key_conf *key_conf)
 {
 	struct wl1271 *wl = hw->priv;
-	const u8 *addr;
 	int ret;
 	u32 tx_seq_32 = 0;
 	u16 tx_seq_16 = 0;
 	u8 key_type;
 
-	static const u8 bcast_addr[ETH_ALEN] =
-		{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-
 	wl1271_debug(DEBUG_MAC80211, "mac80211 set key");
 
-	addr = sta ? sta->addr : bcast_addr;
-
-	wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x", cmd);
-	wl1271_dump(DEBUG_CRYPT, "ADDR: ", addr, ETH_ALEN);
+	wl1271_debug(DEBUG_CRYPT, "CMD: 0x%x sta: %p", cmd, sta);
 	wl1271_debug(DEBUG_CRYPT, "Key: algo:0x%x, id:%d, len:%d flags 0x%x",
 		     key_conf->cipher, key_conf->keyidx,
 		     key_conf->keylen, key_conf->flags);
 	wl1271_dump(DEBUG_CRYPT, "KEY: ", key_conf->key, key_conf->keylen);
 
-	if (is_zero_ether_addr(addr)) {
-		/* We dont support TX only encryption */
-		ret = -EOPNOTSUPP;
-		goto out;
-	}
-
 	mutex_lock(&wl->mutex);
 
 	if (unlikely(wl->state == WL1271_STATE_OFF)) {
@@ -1632,7 +1960,7 @@
 		goto out_unlock;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out_unlock;
 
@@ -1671,36 +1999,21 @@
 
 	switch (cmd) {
 	case SET_KEY:
-		ret = wl1271_cmd_set_key(wl, KEY_ADD_OR_REPLACE,
-					 key_conf->keyidx, key_type,
-					 key_conf->keylen, key_conf->key,
-					 addr, tx_seq_32, tx_seq_16);
+		ret = wl1271_set_key(wl, KEY_ADD_OR_REPLACE,
+				 key_conf->keyidx, key_type,
+				 key_conf->keylen, key_conf->key,
+				 tx_seq_32, tx_seq_16, sta);
 		if (ret < 0) {
 			wl1271_error("Could not add or replace key");
 			goto out_sleep;
 		}
-
-		/* the default WEP key needs to be configured at least once */
-		if (key_type == KEY_WEP) {
-			ret = wl1271_cmd_set_default_wep_key(wl,
-							     wl->default_key);
-			if (ret < 0)
-				goto out_sleep;
-		}
 		break;
 
 	case DISABLE_KEY:
-		/* The wl1271 does not allow to remove unicast keys - they
-		   will be cleared automatically on next CMD_JOIN. Ignore the
-		   request silently, as we dont want the mac80211 to emit
-		   an error message. */
-		if (!is_broadcast_ether_addr(addr))
-			break;
-
-		ret = wl1271_cmd_set_key(wl, KEY_REMOVE,
-					 key_conf->keyidx, key_type,
-					 key_conf->keylen, key_conf->key,
-					 addr, 0, 0);
+		ret = wl1271_set_key(wl, KEY_REMOVE,
+				     key_conf->keyidx, key_type,
+				     key_conf->keylen, key_conf->key,
+				     0, 0, sta);
 		if (ret < 0) {
 			wl1271_error("Could not remove key");
 			goto out_sleep;
@@ -1719,7 +2032,6 @@
 out_unlock:
 	mutex_unlock(&wl->mutex);
 
-out:
 	return ret;
 }
 
@@ -1751,7 +2063,7 @@
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1777,7 +2089,7 @@
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1805,7 +2117,7 @@
 		goto out;
 	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -1821,7 +2133,7 @@
 	return ret;
 }
 
-static void wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
+static int wl1271_ssid_set(struct wl1271 *wl, struct sk_buff *skb,
 			    int offset)
 {
 	u8 *ptr = skb->data + offset;
@@ -1831,89 +2143,213 @@
 		if (ptr[0] == WLAN_EID_SSID) {
 			wl->ssid_len = ptr[1];
 			memcpy(wl->ssid, ptr+2, wl->ssid_len);
-			return;
+			return 0;
 		}
 		ptr += (ptr[1] + 2);
 	}
+
 	wl1271_error("No SSID in IEs!\n");
+	return -ENOENT;
 }
 
-static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
-				       struct ieee80211_vif *vif,
+static int wl1271_bss_erp_info_changed(struct wl1271 *wl,
 				       struct ieee80211_bss_conf *bss_conf,
 				       u32 changed)
 {
-	enum wl1271_cmd_ps_mode mode;
-	struct wl1271 *wl = hw->priv;
-	struct ieee80211_sta *sta = ieee80211_find_sta(vif, bss_conf->bssid);
-	bool do_join = false;
-	bool set_assoc = false;
-	int ret;
+	int ret = 0;
 
-	wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed");
+	if (changed & BSS_CHANGED_ERP_SLOT) {
+		if (bss_conf->use_short_slot)
+			ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
+		else
+			ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
+		if (ret < 0) {
+			wl1271_warning("Set slot time failed %d", ret);
+			goto out;
+		}
+	}
 
-	mutex_lock(&wl->mutex);
+	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
+		if (bss_conf->use_short_preamble)
+			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
+		else
+			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
+	}
 
-	if (unlikely(wl->state == WL1271_STATE_OFF))
-		goto out;
+	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
+		if (bss_conf->use_cts_prot)
+			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
+		else
+			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
+		if (ret < 0) {
+			wl1271_warning("Set ctsprotect failed %d", ret);
+			goto out;
+		}
+	}
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
-	if (ret < 0)
-		goto out;
+out:
+	return ret;
+}
 
-	if ((changed & BSS_CHANGED_BEACON_INT) &&
-	    (wl->bss_type == BSS_TYPE_IBSS)) {
-		wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon interval updated: %d",
+static int wl1271_bss_beacon_info_changed(struct wl1271 *wl,
+					  struct ieee80211_vif *vif,
+					  struct ieee80211_bss_conf *bss_conf,
+					  u32 changed)
+{
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+	int ret = 0;
+
+	if ((changed & BSS_CHANGED_BEACON_INT)) {
+		wl1271_debug(DEBUG_MASTER, "beacon interval updated: %d",
 			bss_conf->beacon_int);
 
 		wl->beacon_int = bss_conf->beacon_int;
-		do_join = true;
 	}
 
-	if ((changed & BSS_CHANGED_BEACON) &&
-	    (wl->bss_type == BSS_TYPE_IBSS)) {
-		struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
+	if ((changed & BSS_CHANGED_BEACON)) {
+		struct ieee80211_hdr *hdr;
+		int ieoffset = offsetof(struct ieee80211_mgmt,
+					u.beacon.variable);
+		struct sk_buff *beacon = ieee80211_beacon_get(wl->hw, vif);
+		u16 tmpl_id;
 
-		wl1271_debug(DEBUG_ADHOC, "ad-hoc beacon updated");
+		if (!beacon)
+			goto out;
 
-		if (beacon) {
-			struct ieee80211_hdr *hdr;
-			int ieoffset = offsetof(struct ieee80211_mgmt,
-						u.beacon.variable);
+		wl1271_debug(DEBUG_MASTER, "beacon updated");
 
-			wl1271_ssid_set(wl, beacon, ieoffset);
+		ret = wl1271_ssid_set(wl, beacon, ieoffset);
+		if (ret < 0) {
+			dev_kfree_skb(beacon);
+			goto out;
+		}
+		tmpl_id = is_ap ? CMD_TEMPL_AP_BEACON :
+				  CMD_TEMPL_BEACON;
+		ret = wl1271_cmd_template_set(wl, tmpl_id,
+					      beacon->data,
+					      beacon->len, 0,
+					      wl1271_tx_min_rate_get(wl));
+		if (ret < 0) {
+			dev_kfree_skb(beacon);
+			goto out;
+		}
 
-			ret = wl1271_cmd_template_set(wl, CMD_TEMPL_BEACON,
-						      beacon->data,
-						      beacon->len, 0,
-						      wl1271_min_rate_get(wl));
+		hdr = (struct ieee80211_hdr *) beacon->data;
+		hdr->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
+						 IEEE80211_STYPE_PROBE_RESP);
 
-			if (ret < 0) {
-				dev_kfree_skb(beacon);
-				goto out_sleep;
-			}
+		tmpl_id = is_ap ? CMD_TEMPL_AP_PROBE_RESPONSE :
+				  CMD_TEMPL_PROBE_RESPONSE;
+		ret = wl1271_cmd_template_set(wl,
+					      tmpl_id,
+					      beacon->data,
+					      beacon->len, 0,
+					      wl1271_tx_min_rate_get(wl));
+		dev_kfree_skb(beacon);
+		if (ret < 0)
+			goto out;
+	}
 
-			hdr = (struct ieee80211_hdr *) beacon->data;
-			hdr->frame_control = cpu_to_le16(
-				IEEE80211_FTYPE_MGMT |
-				IEEE80211_STYPE_PROBE_RESP);
+out:
+	return ret;
+}
 
-			ret = wl1271_cmd_template_set(wl,
-						      CMD_TEMPL_PROBE_RESPONSE,
-						      beacon->data,
-						      beacon->len, 0,
-						      wl1271_min_rate_get(wl));
-			dev_kfree_skb(beacon);
-			if (ret < 0)
-				goto out_sleep;
+/* AP mode changes */
+static void wl1271_bss_info_changed_ap(struct wl1271 *wl,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *bss_conf,
+				       u32 changed)
+{
+	int ret = 0;
 
-			/* Need to update the SSID (for filtering etc) */
-			do_join = true;
+	if ((changed & BSS_CHANGED_BASIC_RATES)) {
+		u32 rates = bss_conf->basic_rates;
+		struct conf_tx_rate_class mgmt_rc;
+
+		wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl, rates);
+		wl->basic_rate = wl1271_tx_min_rate_get(wl);
+		wl1271_debug(DEBUG_AP, "basic rates: 0x%x",
+			     wl->basic_rate_set);
+
+		/* update the AP management rate policy with the new rates */
+		mgmt_rc.enabled_rates = wl->basic_rate_set;
+		mgmt_rc.long_retry_limit = 10;
+		mgmt_rc.short_retry_limit = 10;
+		mgmt_rc.aflags = 0;
+		ret = wl1271_acx_ap_rate_policy(wl, &mgmt_rc,
+						ACX_TX_AP_MODE_MGMT_RATE);
+		if (ret < 0) {
+			wl1271_error("AP mgmt policy change failed %d", ret);
+			goto out;
 		}
 	}
 
-	if ((changed & BSS_CHANGED_BEACON_ENABLED) &&
-	    (wl->bss_type == BSS_TYPE_IBSS)) {
+	ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf, changed);
+	if (ret < 0)
+		goto out;
+
+	if ((changed & BSS_CHANGED_BEACON_ENABLED)) {
+		if (bss_conf->enable_beacon) {
+			if (!test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+				ret = wl1271_cmd_start_bss(wl);
+				if (ret < 0)
+					goto out;
+
+				set_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+				wl1271_debug(DEBUG_AP, "started AP");
+
+				ret = wl1271_ap_init_hwenc(wl);
+				if (ret < 0)
+					goto out;
+			}
+		} else {
+			if (test_bit(WL1271_FLAG_AP_STARTED, &wl->flags)) {
+				ret = wl1271_cmd_stop_bss(wl);
+				if (ret < 0)
+					goto out;
+
+				clear_bit(WL1271_FLAG_AP_STARTED, &wl->flags);
+				wl1271_debug(DEBUG_AP, "stopped AP");
+			}
+		}
+	}
+
+	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
+	if (ret < 0)
+		goto out;
+out:
+	return;
+}
+
+/* STA/IBSS mode changes */
+static void wl1271_bss_info_changed_sta(struct wl1271 *wl,
+					struct ieee80211_vif *vif,
+					struct ieee80211_bss_conf *bss_conf,
+					u32 changed)
+{
+	bool do_join = false, set_assoc = false;
+	bool is_ibss = (wl->bss_type == BSS_TYPE_IBSS);
+	u32 sta_rate_set = 0;
+	int ret;
+	struct ieee80211_sta *sta;
+	bool sta_exists = false;
+	struct ieee80211_sta_ht_cap sta_ht_cap;
+
+	if (is_ibss) {
+		ret = wl1271_bss_beacon_info_changed(wl, vif, bss_conf,
+						     changed);
+		if (ret < 0)
+			goto out;
+	}
+
+	if ((changed & BSS_CHANGED_BEACON_INT)  && is_ibss)
+		do_join = true;
+
+	/* Need to update the SSID (for filtering etc) */
+	if ((changed & BSS_CHANGED_BEACON) && is_ibss)
+		do_join = true;
+
+	if ((changed & BSS_CHANGED_BEACON_ENABLED) && is_ibss) {
 		wl1271_debug(DEBUG_ADHOC, "ad-hoc beaconing: %s",
 			     bss_conf->enable_beacon ? "enabled" : "disabled");
 
@@ -1924,7 +2360,7 @@
 		do_join = true;
 	}
 
-	if (changed & BSS_CHANGED_CQM) {
+	if ((changed & BSS_CHANGED_CQM)) {
 		bool enable = false;
 		if (bss_conf->cqm_rssi_thold)
 			enable = true;
@@ -1942,24 +2378,70 @@
 	     * and enable the BSSID filter
 	     */
 	    memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
-			memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
+		memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
 
+		if (!is_zero_ether_addr(wl->bssid)) {
 			ret = wl1271_cmd_build_null_data(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			ret = wl1271_build_qos_null_data(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* filter out all packets not from this BSSID */
 			wl1271_configure_filters(wl, 0);
 
 			/* Need to update the BSSID (for filtering etc) */
 			do_join = true;
+		}
 	}
 
-	if (changed & BSS_CHANGED_ASSOC) {
+	rcu_read_lock();
+	sta = ieee80211_find_sta(vif, bss_conf->bssid);
+	if (sta)  {
+		/* save the supp_rates of the ap */
+		sta_rate_set = sta->supp_rates[wl->hw->conf.channel->band];
+		if (sta->ht_cap.ht_supported)
+			sta_rate_set |=
+			    (sta->ht_cap.mcs.rx_mask[0] << HW_HT_RATES_OFFSET);
+		sta_ht_cap = sta->ht_cap;
+		sta_exists = true;
+	}
+	rcu_read_unlock();
+
+	if (sta_exists) {
+		/* handle new association with HT and HT information change */
+		if ((changed & BSS_CHANGED_HT) &&
+		    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
+							     true);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap true failed %d",
+					       ret);
+				goto out;
+			}
+			ret = wl1271_acx_set_ht_information(wl,
+						bss_conf->ht_operation_mode);
+			if (ret < 0) {
+				wl1271_warning("Set ht information failed %d",
+					       ret);
+				goto out;
+			}
+		}
+		/* handle new association without HT and disassociation */
+		else if (changed & BSS_CHANGED_ASSOC) {
+			ret = wl1271_acx_set_ht_capabilities(wl, &sta_ht_cap,
+							     false);
+			if (ret < 0) {
+				wl1271_warning("Set ht cap false failed %d",
+					       ret);
+				goto out;
+			}
+		}
+	}
+
+	if ((changed & BSS_CHANGED_ASSOC)) {
 		if (bss_conf->assoc) {
 			u32 rates;
 			int ieoffset;
@@ -1975,10 +2457,13 @@
 			rates = bss_conf->basic_rates;
 			wl->basic_rate_set = wl1271_tx_enabled_rates_get(wl,
 									 rates);
-			wl->basic_rate = wl1271_min_rate_get(wl);
-			ret = wl1271_acx_rate_policies(wl);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			if (sta_rate_set)
+				wl->rate_set = wl1271_tx_enabled_rates_get(wl,
+								sta_rate_set);
+			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/*
 			 * with wl1271, we don't need to update the
@@ -1988,7 +2473,7 @@
 			 */
 			ret = wl1271_cmd_build_ps_poll(wl, wl->aid);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/*
 			 * Get a template for hardware connection maintenance
@@ -2002,17 +2487,19 @@
 			/* enable the connection monitoring feature */
 			ret = wl1271_acx_conn_monit_params(wl, true);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* If we want to go in PSM but we're not there yet */
 			if (test_bit(WL1271_FLAG_PSM_REQUESTED, &wl->flags) &&
 			    !test_bit(WL1271_FLAG_PSM, &wl->flags)) {
+				enum wl1271_cmd_ps_mode mode;
+
 				mode = STATION_POWER_SAVE_MODE;
 				ret = wl1271_ps_set_mode(wl, mode,
 							 wl->basic_rate,
 							 true);
 				if (ret < 0)
-					goto out_sleep;
+					goto out;
 			}
 		} else {
 			/* use defaults when not associated */
@@ -2029,10 +2516,10 @@
 
 			/* revert back to minimum rates for the current band */
 			wl1271_set_band_rate(wl);
-			wl->basic_rate = wl1271_min_rate_get(wl);
-			ret = wl1271_acx_rate_policies(wl);
+			wl->basic_rate = wl1271_tx_min_rate_get(wl);
+			ret = wl1271_acx_sta_rate_policies(wl);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* disable connection monitor features */
 			ret = wl1271_acx_conn_monit_params(wl, false);
@@ -2040,74 +2527,17 @@
 			/* Disable the keep-alive feature */
 			ret = wl1271_acx_keep_alive_mode(wl, false);
 			if (ret < 0)
-				goto out_sleep;
+				goto out;
 
 			/* restore the bssid filter and go to dummy bssid */
 			wl1271_unjoin(wl);
 			wl1271_dummy_join(wl);
 		}
-
 	}
 
-	if (changed & BSS_CHANGED_ERP_SLOT) {
-		if (bss_conf->use_short_slot)
-			ret = wl1271_acx_slot(wl, SLOT_TIME_SHORT);
-		else
-			ret = wl1271_acx_slot(wl, SLOT_TIME_LONG);
-		if (ret < 0) {
-			wl1271_warning("Set slot time failed %d", ret);
-			goto out_sleep;
-		}
-	}
-
-	if (changed & BSS_CHANGED_ERP_PREAMBLE) {
-		if (bss_conf->use_short_preamble)
-			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_SHORT);
-		else
-			wl1271_acx_set_preamble(wl, ACX_PREAMBLE_LONG);
-	}
-
-	if (changed & BSS_CHANGED_ERP_CTS_PROT) {
-		if (bss_conf->use_cts_prot)
-			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_ENABLE);
-		else
-			ret = wl1271_acx_cts_protect(wl, CTSPROTECT_DISABLE);
-		if (ret < 0) {
-			wl1271_warning("Set ctsprotect failed %d", ret);
-			goto out_sleep;
-		}
-	}
-
-	/*
-	 * Takes care of: New association with HT enable,
-	 *                HT information change in beacon.
-	 */
-	if (sta &&
-	    (changed & BSS_CHANGED_HT) &&
-	    (bss_conf->channel_type != NL80211_CHAN_NO_HT)) {
-		ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, true);
-		if (ret < 0) {
-			wl1271_warning("Set ht cap true failed %d", ret);
-			goto out_sleep;
-		}
-			ret = wl1271_acx_set_ht_information(wl,
-				bss_conf->ht_operation_mode);
-		if (ret < 0) {
-			wl1271_warning("Set ht information failed %d", ret);
-			goto out_sleep;
-		}
-	}
-	/*
-	 * Takes care of: New association without HT,
-	 *                Disassociation.
-	 */
-	else if (sta && (changed & BSS_CHANGED_ASSOC)) {
-		ret = wl1271_acx_set_ht_capabilities(wl, &sta->ht_cap, false);
-		if (ret < 0) {
-			wl1271_warning("Set ht cap false failed %d", ret);
-			goto out_sleep;
-		}
-	}
+	ret = wl1271_bss_erp_info_changed(wl, bss_conf, changed);
+	if (ret < 0)
+		goto out;
 
 	if (changed & BSS_CHANGED_ARP_FILTER) {
 		__be32 addr = bss_conf->arp_addr_list[0];
@@ -2124,29 +2554,57 @@
 			ret = wl1271_cmd_build_arp_rsp(wl, addr);
 			if (ret < 0) {
 				wl1271_warning("build arp rsp failed: %d", ret);
-				goto out_sleep;
+				goto out;
 			}
 
 			ret = wl1271_acx_arp_ip_filter(wl,
-				(ACX_ARP_FILTER_ARP_FILTERING |
-				 ACX_ARP_FILTER_AUTO_ARP),
+				ACX_ARP_FILTER_ARP_FILTERING,
 				addr);
 		} else
 			ret = wl1271_acx_arp_ip_filter(wl, 0, addr);
 
 		if (ret < 0)
-			goto out_sleep;
+			goto out;
 	}
 
 	if (do_join) {
 		ret = wl1271_join(wl, set_assoc);
 		if (ret < 0) {
 			wl1271_warning("cmd join failed %d", ret);
-			goto out_sleep;
+			goto out;
 		}
 	}
 
-out_sleep:
+out:
+	return;
+}
+
+static void wl1271_op_bss_info_changed(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_bss_conf *bss_conf,
+				       u32 changed)
+{
+	struct wl1271 *wl = hw->priv;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+	int ret;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 bss info changed 0x%x",
+		     (int)changed);
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	if (is_ap)
+		wl1271_bss_info_changed_ap(wl, vif, bss_conf, changed);
+	else
+		wl1271_bss_info_changed_sta(wl, vif, bss_conf, changed);
+
 	wl1271_ps_elp_sleep(wl);
 
 out:
@@ -2158,42 +2616,66 @@
 {
 	struct wl1271 *wl = hw->priv;
 	u8 ps_scheme;
-	int ret;
+	int ret = 0;
 
 	mutex_lock(&wl->mutex);
 
 	wl1271_debug(DEBUG_MAC80211, "mac80211 conf tx %d", queue);
 
-	if (unlikely(wl->state == WL1271_STATE_OFF)) {
-		ret = -EAGAIN;
-		goto out;
-	}
-
-	ret = wl1271_ps_elp_wakeup(wl, false);
-	if (ret < 0)
-		goto out;
-
-	/* the txop is confed in units of 32us by the mac80211, we need us */
-	ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
-				params->cw_min, params->cw_max,
-				params->aifs, params->txop << 5);
-	if (ret < 0)
-		goto out_sleep;
-
 	if (params->uapsd)
 		ps_scheme = CONF_PS_SCHEME_UPSD_TRIGGER;
 	else
 		ps_scheme = CONF_PS_SCHEME_LEGACY;
 
-	ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
-				 CONF_CHANNEL_TYPE_EDCF,
-				 wl1271_tx_get_queue(queue),
-				 ps_scheme, CONF_ACK_POLICY_LEGACY, 0, 0);
-	if (ret < 0)
-		goto out_sleep;
+	if (wl->state == WL1271_STATE_OFF) {
+		/*
+		 * If the state is off, the parameters will be recorded and
+		 * configured on init. This happens in AP-mode.
+		 */
+		struct conf_tx_ac_category *conf_ac =
+			&wl->conf.tx.ac_conf[wl1271_tx_get_queue(queue)];
+		struct conf_tx_tid *conf_tid =
+			&wl->conf.tx.tid_conf[wl1271_tx_get_queue(queue)];
+
+		conf_ac->ac = wl1271_tx_get_queue(queue);
+		conf_ac->cw_min = (u8)params->cw_min;
+		conf_ac->cw_max = params->cw_max;
+		conf_ac->aifsn = params->aifs;
+		conf_ac->tx_op_limit = params->txop << 5;
+
+		conf_tid->queue_id = wl1271_tx_get_queue(queue);
+		conf_tid->channel_type = CONF_CHANNEL_TYPE_EDCF;
+		conf_tid->tsid = wl1271_tx_get_queue(queue);
+		conf_tid->ps_scheme = ps_scheme;
+		conf_tid->ack_policy = CONF_ACK_POLICY_LEGACY;
+		conf_tid->apsd_conf[0] = 0;
+		conf_tid->apsd_conf[1] = 0;
+	} else {
+		ret = wl1271_ps_elp_wakeup(wl);
+		if (ret < 0)
+			goto out;
+
+		/*
+		 * the txop is confed in units of 32us by the mac80211,
+		 * we need us
+		 */
+		ret = wl1271_acx_ac_cfg(wl, wl1271_tx_get_queue(queue),
+					params->cw_min, params->cw_max,
+					params->aifs, params->txop << 5);
+		if (ret < 0)
+			goto out_sleep;
+
+		ret = wl1271_acx_tid_cfg(wl, wl1271_tx_get_queue(queue),
+					 CONF_CHANNEL_TYPE_EDCF,
+					 wl1271_tx_get_queue(queue),
+					 ps_scheme, CONF_ACK_POLICY_LEGACY,
+					 0, 0);
+		if (ret < 0)
+			goto out_sleep;
 
 out_sleep:
-	wl1271_ps_elp_sleep(wl);
+		wl1271_ps_elp_sleep(wl);
+	}
 
 out:
 	mutex_unlock(&wl->mutex);
@@ -2215,7 +2697,7 @@
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -2247,6 +2729,184 @@
 	return 0;
 }
 
+static int wl1271_allocate_sta(struct wl1271 *wl,
+			     struct ieee80211_sta *sta,
+			     u8 *hlid)
+{
+	struct wl1271_station *wl_sta;
+	int id;
+
+	id = find_first_zero_bit(wl->ap_hlid_map, AP_MAX_STATIONS);
+	if (id >= AP_MAX_STATIONS) {
+		wl1271_warning("could not allocate HLID - too much stations");
+		return -EBUSY;
+	}
+
+	wl_sta = (struct wl1271_station *)sta->drv_priv;
+	__set_bit(id, wl->ap_hlid_map);
+	wl_sta->hlid = WL1271_AP_STA_HLID_START + id;
+	*hlid = wl_sta->hlid;
+	memcpy(wl->links[wl_sta->hlid].addr, sta->addr, ETH_ALEN);
+	return 0;
+}
+
+static void wl1271_free_sta(struct wl1271 *wl, u8 hlid)
+{
+	int id = hlid - WL1271_AP_STA_HLID_START;
+
+	if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+		return;
+
+	__clear_bit(id, wl->ap_hlid_map);
+	memset(wl->links[hlid].addr, 0, ETH_ALEN);
+	wl1271_tx_reset_link_queues(wl, hlid);
+	__clear_bit(hlid, &wl->ap_ps_map);
+	__clear_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+}
+
+static int wl1271_op_sta_add(struct ieee80211_hw *hw,
+			     struct ieee80211_vif *vif,
+			     struct ieee80211_sta *sta)
+{
+	struct wl1271 *wl = hw->priv;
+	int ret = 0;
+	u8 hlid;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS)
+		goto out;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 add sta %d", (int)sta->aid);
+
+	ret = wl1271_allocate_sta(wl, sta, &hlid);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out_free_sta;
+
+	ret = wl1271_cmd_add_sta(wl, sta, hlid);
+	if (ret < 0)
+		goto out_sleep;
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out_free_sta:
+	if (ret < 0)
+		wl1271_free_sta(wl, hlid);
+
+out:
+	mutex_unlock(&wl->mutex);
+	return ret;
+}
+
+static int wl1271_op_sta_remove(struct ieee80211_hw *hw,
+				struct ieee80211_vif *vif,
+				struct ieee80211_sta *sta)
+{
+	struct wl1271 *wl = hw->priv;
+	struct wl1271_station *wl_sta;
+	int ret = 0, id;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF))
+		goto out;
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS)
+		goto out;
+
+	wl1271_debug(DEBUG_MAC80211, "mac80211 remove sta %d", (int)sta->aid);
+
+	wl_sta = (struct wl1271_station *)sta->drv_priv;
+	id = wl_sta->hlid - WL1271_AP_STA_HLID_START;
+	if (WARN_ON(!test_bit(id, wl->ap_hlid_map)))
+		goto out;
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	ret = wl1271_cmd_remove_sta(wl, wl_sta->hlid);
+	if (ret < 0)
+		goto out_sleep;
+
+	wl1271_free_sta(wl, wl_sta->hlid);
+
+out_sleep:
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+	return ret;
+}
+
+int wl1271_op_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+			   enum ieee80211_ampdu_mlme_action action,
+			   struct ieee80211_sta *sta, u16 tid, u16 *ssn,
+			   u8 buf_size)
+{
+	struct wl1271 *wl = hw->priv;
+	int ret;
+
+	mutex_lock(&wl->mutex);
+
+	if (unlikely(wl->state == WL1271_STATE_OFF)) {
+		ret = -EAGAIN;
+		goto out;
+	}
+
+	ret = wl1271_ps_elp_wakeup(wl);
+	if (ret < 0)
+		goto out;
+
+	switch (action) {
+	case IEEE80211_AMPDU_RX_START:
+		if (wl->ba_support) {
+			ret = wl1271_acx_set_ba_receiver_session(wl, tid, *ssn,
+								 true);
+			if (!ret)
+				wl->ba_rx_bitmap |= BIT(tid);
+		} else {
+			ret = -ENOTSUPP;
+		}
+		break;
+
+	case IEEE80211_AMPDU_RX_STOP:
+		ret = wl1271_acx_set_ba_receiver_session(wl, tid, 0, false);
+		if (!ret)
+			wl->ba_rx_bitmap &= ~BIT(tid);
+		break;
+
+	/*
+	 * The BA initiator session management in FW independently.
+	 * Falling break here on purpose for all TX APDU commands.
+	 */
+	case IEEE80211_AMPDU_TX_START:
+	case IEEE80211_AMPDU_TX_STOP:
+	case IEEE80211_AMPDU_TX_OPERATIONAL:
+		ret = -EINVAL;
+		break;
+
+	default:
+		wl1271_error("Incorrect ampdu action id=%x\n", action);
+		ret = -EINVAL;
+	}
+
+	wl1271_ps_elp_sleep(wl);
+
+out:
+	mutex_unlock(&wl->mutex);
+
+	return ret;
+}
+
 /* can't be const, mac80211 writes to this */
 static struct ieee80211_rate wl1271_rates[] = {
 	{ .bitrate = 10,
@@ -2305,6 +2965,7 @@
 	{ .hw_value = 11, .center_freq = 2462, .max_power = 25 },
 	{ .hw_value = 12, .center_freq = 2467, .max_power = 25 },
 	{ .hw_value = 13, .center_freq = 2472, .max_power = 25 },
+	{ .hw_value = 14, .center_freq = 2484, .max_power = 25 },
 };
 
 /* mapping to indexes for wl1271_rates */
@@ -2493,6 +3154,9 @@
 	.conf_tx = wl1271_op_conf_tx,
 	.get_tsf = wl1271_op_get_tsf,
 	.get_survey = wl1271_op_get_survey,
+	.sta_add = wl1271_op_sta_add,
+	.sta_remove = wl1271_op_sta_remove,
+	.ampdu_action = wl1271_op_ampdu_action,
 	CFG80211_TESTMODE_CMD(wl1271_tm_cmd)
 };
 
@@ -2562,7 +3226,7 @@
 	if (wl->state == WL1271_STATE_OFF)
 		goto out;
 
-	ret = wl1271_ps_elp_wakeup(wl, false);
+	ret = wl1271_ps_elp_wakeup(wl);
 	if (ret < 0)
 		goto out;
 
@@ -2607,6 +3271,18 @@
 	if (wl->mac80211_registered)
 		return 0;
 
+	ret = wl1271_fetch_nvs(wl);
+	if (ret == 0) {
+		u8 *nvs_ptr = (u8 *)wl->nvs->nvs;
+
+		wl->mac_addr[0] = nvs_ptr[11];
+		wl->mac_addr[1] = nvs_ptr[10];
+		wl->mac_addr[2] = nvs_ptr[6];
+		wl->mac_addr[3] = nvs_ptr[5];
+		wl->mac_addr[4] = nvs_ptr[4];
+		wl->mac_addr[5] = nvs_ptr[3];
+	}
+
 	SET_IEEE80211_PERM_ADDR(wl->hw, wl->mac_addr);
 
 	ret = ieee80211_register_hw(wl->hw);
@@ -2629,6 +3305,9 @@
 
 void wl1271_unregister_hw(struct wl1271 *wl)
 {
+	if (wl->state == WL1271_STATE_PLT)
+		__wl1271_plt_stop(wl);
+
 	unregister_netdevice_notifier(&wl1271_dev_notifier);
 	ieee80211_unregister_hw(wl->hw);
 	wl->mac80211_registered = false;
@@ -2661,13 +3340,15 @@
 		IEEE80211_HW_SUPPORTS_UAPSD |
 		IEEE80211_HW_HAS_RATE_CONTROL |
 		IEEE80211_HW_CONNECTION_MONITOR |
-		IEEE80211_HW_SUPPORTS_CQM_RSSI;
+		IEEE80211_HW_SUPPORTS_CQM_RSSI |
+		IEEE80211_HW_REPORTS_TX_ACK_STATUS |
+		IEEE80211_HW_AP_LINK_PS;
 
 	wl->hw->wiphy->cipher_suites = cipher_suites;
 	wl->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
 
 	wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
+		BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
 	wl->hw->wiphy->max_scan_ssids = 1;
 	/*
 	 * Maximum length of elements in scanning probe request templates
@@ -2676,8 +3357,20 @@
 	 */
 	wl->hw->wiphy->max_scan_ie_len = WL1271_CMD_TEMPL_MAX_SIZE -
 			sizeof(struct ieee80211_header);
-	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &wl1271_band_2ghz;
-	wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &wl1271_band_5ghz;
+
+	/*
+	 * We keep local copies of the band structs because we need to
+	 * modify them on a per-device basis.
+	 */
+	memcpy(&wl->bands[IEEE80211_BAND_2GHZ], &wl1271_band_2ghz,
+	       sizeof(wl1271_band_2ghz));
+	memcpy(&wl->bands[IEEE80211_BAND_5GHZ], &wl1271_band_5ghz,
+	       sizeof(wl1271_band_5ghz));
+
+	wl->hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
+		&wl->bands[IEEE80211_BAND_2GHZ];
+	wl->hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
+		&wl->bands[IEEE80211_BAND_5GHZ];
 
 	wl->hw->queues = 4;
 	wl->hw->max_rates = 1;
@@ -2686,6 +3379,10 @@
 
 	SET_IEEE80211_DEV(wl->hw, wl1271_wl_to_dev(wl));
 
+	wl->hw->sta_data_size = sizeof(struct wl1271_station);
+
+	wl->hw->max_rx_aggregation_subframes = 8;
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(wl1271_init_ieee80211);
@@ -2697,7 +3394,7 @@
 	struct ieee80211_hw *hw;
 	struct platform_device *plat_dev = NULL;
 	struct wl1271 *wl;
-	int i, ret;
+	int i, j, ret;
 	unsigned int order;
 
 	hw = ieee80211_alloc_hw(sizeof(*wl), &wl1271_ops);
@@ -2725,9 +3422,16 @@
 	for (i = 0; i < NUM_TX_QUEUES; i++)
 		skb_queue_head_init(&wl->tx_queue[i]);
 
+	for (i = 0; i < NUM_TX_QUEUES; i++)
+		for (j = 0; j < AP_MAX_LINKS; j++)
+			skb_queue_head_init(&wl->links[j].tx_queue[i]);
+
+	skb_queue_head_init(&wl->deferred_rx_queue);
+	skb_queue_head_init(&wl->deferred_tx_queue);
+
 	INIT_DELAYED_WORK(&wl->elp_work, wl1271_elp_work);
 	INIT_DELAYED_WORK(&wl->pspoll_work, wl1271_pspoll_work);
-	INIT_WORK(&wl->irq_work, wl1271_irq_work);
+	INIT_WORK(&wl->netstack_work, wl1271_netstack_work);
 	INIT_WORK(&wl->tx_work, wl1271_tx_work);
 	INIT_WORK(&wl->recovery_work, wl1271_recovery_work);
 	INIT_DELAYED_WORK(&wl->scan_complete_work, wl1271_scan_complete_work);
@@ -2735,19 +3439,25 @@
 	wl->beacon_int = WL1271_DEFAULT_BEACON_INT;
 	wl->default_key = 0;
 	wl->rx_counter = 0;
-	wl->rx_config = WL1271_DEFAULT_RX_CONFIG;
-	wl->rx_filter = WL1271_DEFAULT_RX_FILTER;
+	wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
+	wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
 	wl->psm_entry_retry = 0;
 	wl->power_level = WL1271_DEFAULT_POWER_LEVEL;
 	wl->basic_rate_set = CONF_TX_RATE_MASK_BASIC;
 	wl->basic_rate = CONF_TX_RATE_MASK_BASIC;
 	wl->rate_set = CONF_TX_RATE_MASK_BASIC;
-	wl->sta_rate_set = 0;
 	wl->band = IEEE80211_BAND_2GHZ;
 	wl->vif = NULL;
 	wl->flags = 0;
 	wl->sg_enabled = true;
 	wl->hw_pg_ver = -1;
+	wl->bss_type = MAX_BSS_TYPE;
+	wl->set_bss_type = MAX_BSS_TYPE;
+	wl->fw_bss_type = MAX_BSS_TYPE;
+	wl->last_tx_hlid = 0;
+	wl->ap_ps_map = 0;
+	wl->ap_fw_ps_map = 0;
+	wl->quirks = 0;
 
 	memset(wl->tx_frames_map, 0, sizeof(wl->tx_frames_map));
 	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
@@ -2837,11 +3547,11 @@
 }
 EXPORT_SYMBOL_GPL(wl1271_free_hw);
 
-u32 wl12xx_debug_level;
+u32 wl12xx_debug_level = DEBUG_NONE;
 EXPORT_SYMBOL_GPL(wl12xx_debug_level);
-module_param_named(debug_level, wl12xx_debug_level, uint, DEBUG_NONE);
+module_param_named(debug_level, wl12xx_debug_level, uint, S_IRUSR | S_IWUSR);
 MODULE_PARM_DESC(debug_level, "wl12xx debugging level");
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/ps.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/ps.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/ps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/ps.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,6 +24,7 @@
 #include "reg.h"
 #include "ps.h"
 #include "io.h"
+#include "tx.h"
 
 #define WL1271_WAKEUP_TIMEOUT 500
 
@@ -68,7 +69,7 @@
 	}
 }
 
-int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake)
+int wl1271_ps_elp_wakeup(struct wl1271 *wl)
 {
 	DECLARE_COMPLETION_ONSTACK(compl);
 	unsigned long flags;
@@ -86,7 +87,7 @@
 	 * the completion variable in one entity.
 	 */
 	spin_lock_irqsave(&wl->wl_lock, flags);
-	if (work_pending(&wl->irq_work) || chip_awake)
+	if (test_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
 		pending = true;
 	else
 		wl->elp_compl = &compl;
@@ -139,8 +140,7 @@
 			return ret;
 		}
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE,
-					 rates, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
 
@@ -149,7 +149,7 @@
 	case STATION_ACTIVE_MODE:
 	default:
 		wl1271_debug(DEBUG_PSM, "leaving psm");
-		ret = wl1271_ps_elp_wakeup(wl, false);
+		ret = wl1271_ps_elp_wakeup(wl);
 		if (ret < 0)
 			return ret;
 
@@ -163,8 +163,7 @@
 		if (ret < 0)
 			return ret;
 
-		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE,
-					 rates, send);
+		ret = wl1271_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
 		if (ret < 0)
 			return ret;
 
@@ -175,4 +174,81 @@
 	return ret;
 }
 
+static void wl1271_ps_filter_frames(struct wl1271 *wl, u8 hlid)
+{
+	int i, filtered = 0;
+	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
+	unsigned long flags;
+
+	/* filter all frames currently the low level queus for this hlid */
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+			info = IEEE80211_SKB_CB(skb);
+			info->flags |= IEEE80211_TX_STAT_TX_FILTERED;
+			info->status.rates[0].idx = -1;
+			ieee80211_tx_status(wl->hw, skb);
+			filtered++;
+		}
+	}
+
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	wl->tx_queue_count -= filtered;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	wl1271_handle_tx_low_watermark(wl);
+}
+
+void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues)
+{
+	struct ieee80211_sta *sta;
+
+	if (test_bit(hlid, &wl->ap_ps_map))
+		return;
+
+	wl1271_debug(DEBUG_PSM, "start mac80211 PSM on hlid %d blks %d "
+		     "clean_queues %d", hlid, wl->links[hlid].allocated_blks,
+		     clean_queues);
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
+	if (!sta) {
+		wl1271_error("could not find sta %pM for starting ps",
+			     wl->links[hlid].addr);
+		rcu_read_unlock();
+		return;
+	}
+
+	ieee80211_sta_ps_transition_ni(sta, true);
+	rcu_read_unlock();
+
+	/* do we want to filter all frames from this link's queues? */
+	if (clean_queues)
+		wl1271_ps_filter_frames(wl, hlid);
+
+	__set_bit(hlid, &wl->ap_ps_map);
+}
+
+void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid)
+{
+	struct ieee80211_sta *sta;
+
+	if (!test_bit(hlid, &wl->ap_ps_map))
+		return;
+
+	wl1271_debug(DEBUG_PSM, "end mac80211 PSM on hlid %d", hlid);
+
+	__clear_bit(hlid, &wl->ap_ps_map);
+
+	rcu_read_lock();
+	sta = ieee80211_find_sta(wl->vif, wl->links[hlid].addr);
+	if (!sta) {
+		wl1271_error("could not find sta %pM for ending ps",
+			     wl->links[hlid].addr);
+		goto end;
+	}
 
+	ieee80211_sta_ps_transition_ni(sta, false);
+end:
+	rcu_read_unlock();
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/ps.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/ps.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/ps.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/ps.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,9 @@
 int wl1271_ps_set_mode(struct wl1271 *wl, enum wl1271_cmd_ps_mode mode,
 		       u32 rates, bool send);
 void wl1271_ps_elp_sleep(struct wl1271 *wl);
-int wl1271_ps_elp_wakeup(struct wl1271 *wl, bool chip_awake);
+int wl1271_ps_elp_wakeup(struct wl1271 *wl);
 void wl1271_elp_work(struct work_struct *work);
+void wl1271_ps_link_start(struct wl1271 *wl, u8 hlid, bool clean_queues);
+void wl1271_ps_link_end(struct wl1271 *wl, u8 hlid);
 
 #endif /* __WL1271_PS_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/rx.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/rx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,14 +29,14 @@
 #include "rx.h"
 #include "io.h"
 
-static u8 wl1271_rx_get_mem_block(struct wl1271_fw_status *status,
+static u8 wl1271_rx_get_mem_block(struct wl1271_fw_common_status *status,
 				  u32 drv_rx_counter)
 {
 	return le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
 		RX_MEM_BLOCK_MASK;
 }
 
-static u32 wl1271_rx_get_buf_size(struct wl1271_fw_status *status,
+static u32 wl1271_rx_get_buf_size(struct wl1271_fw_common_status *status,
 				 u32 drv_rx_counter)
 {
 	return (le32_to_cpu(status->rx_pkt_descs[drv_rx_counter]) &
@@ -76,7 +76,7 @@
 	 */
 	wl->noise = desc->rssi - (desc->snr >> 1);
 
-	status->freq = ieee80211_channel_to_frequency(desc->channel);
+	status->freq = ieee80211_channel_to_frequency(desc->channel, desc_band);
 
 	if (desc->flags & WL1271_RX_DESC_ENCRYPT_MASK) {
 		status->flag |= RX_FLAG_IV_STRIPPED | RX_FLAG_MMIC_STRIPPED;
@@ -92,7 +92,7 @@
 {
 	struct wl1271_rx_descriptor *desc;
 	struct sk_buff *skb;
-	u16 *fc;
+	struct ieee80211_hdr *hdr;
 	u8 *buf;
 	u8 beacon = 0;
 
@@ -118,8 +118,8 @@
 	/* now we pull the descriptor out of the buffer */
 	skb_pull(skb, sizeof(*desc));
 
-	fc = (u16 *)skb->data;
-	if ((*fc & IEEE80211_FCTL_STYPE) == IEEE80211_STYPE_BEACON)
+	hdr = (struct ieee80211_hdr *)skb->data;
+	if (ieee80211_is_beacon(hdr->frame_control))
 		beacon = 1;
 
 	wl1271_rx_status(wl, desc, IEEE80211_SKB_RXCB(skb), beacon);
@@ -129,12 +129,13 @@
 
 	skb_trim(skb, skb->len - desc->pad_len);
 
-	ieee80211_rx_ni(wl->hw, skb);
+	skb_queue_tail(&wl->deferred_rx_queue, skb);
+	ieee80211_queue_work(wl->hw, &wl->netstack_work);
 
 	return 0;
 }
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status)
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status)
 {
 	struct wl1271_acx_mem_map *wl_mem_map = wl->target_mem_map;
 	u32 buf_size;
@@ -198,6 +199,22 @@
 			pkt_offset += pkt_length;
 		}
 	}
-	wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS,
-			cpu_to_le32(wl->rx_counter));
+
+	/*
+	 * Write the driver's packet counter to the FW. This is only required
+	 * for older hardware revisions
+	 */
+	if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
+		wl1271_write32(wl, RX_DRIVER_COUNTER_ADDRESS, wl->rx_counter);
+}
+
+void wl1271_set_default_filters(struct wl1271 *wl)
+{
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		wl->rx_config = WL1271_DEFAULT_AP_RX_CONFIG;
+		wl->rx_filter = WL1271_DEFAULT_AP_RX_FILTER;
+	} else {
+		wl->rx_config = WL1271_DEFAULT_STA_RX_CONFIG;
+		wl->rx_filter = WL1271_DEFAULT_STA_RX_FILTER;
+	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/rx.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/rx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/rx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/rx.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,10 +30,6 @@
 #define WL1271_RX_MAX_RSSI -30
 #define WL1271_RX_MIN_RSSI -95
 
-#define WL1271_RX_ALIGN_TO 4
-#define WL1271_RX_ALIGN(len) (((len) + WL1271_RX_ALIGN_TO - 1) & \
-			     ~(WL1271_RX_ALIGN_TO - 1))
-
 #define SHORT_PREAMBLE_BIT   BIT(0)
 #define OFDM_RATE_BIT        BIT(6)
 #define PBCC_RATE_BIT        BIT(7)
@@ -86,8 +82,9 @@
 /*
  * RX Descriptor status
  *
- * Bits 0-2 - status
- * Bits 3-7 - reserved
+ * Bits 0-2 - error code
+ * Bits 3-5 - process_id tag (AP mode FW)
+ * Bits 6-7 - reserved
  */
 #define WL1271_RX_DESC_STATUS_MASK      0x07
 
@@ -110,12 +107,16 @@
 	u8  snr;
 	__le32 timestamp;
 	u8  packet_class;
-	u8  process_id;
+	union {
+		u8  process_id; /* STA FW */
+		u8  hlid; /* AP FW */
+	} __packed;
 	u8  pad_len;
 	u8  reserved;
 } __packed;
 
-void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_status *status);
+void wl1271_rx(struct wl1271 *wl, struct wl1271_fw_common_status *status);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
+void wl1271_set_default_filters(struct wl1271 *wl);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/scan.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/scan.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,7 @@
 #include "cmd.h"
 #include "scan.h"
 #include "acx.h"
+#include "ps.h"
 
 void wl1271_scan_complete_work(struct work_struct *work)
 {
@@ -40,10 +41,11 @@
 
 	mutex_lock(&wl->mutex);
 
-	if (wl->scan.state == WL1271_SCAN_STATE_IDLE) {
-		mutex_unlock(&wl->mutex);
-		return;
-	}
+	if (wl->state == WL1271_STATE_OFF)
+		goto out;
+
+	if (wl->scan.state == WL1271_SCAN_STATE_IDLE)
+		goto out;
 
 	wl->scan.state = WL1271_SCAN_STATE_IDLE;
 	kfree(wl->scan.scanned_ch);
@@ -52,13 +54,19 @@
 	ieee80211_scan_completed(wl->hw, false);
 
 	/* restore hardware connection monitoring template */
-	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags))
-		wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
+	if (test_bit(WL1271_FLAG_STA_ASSOCIATED, &wl->flags)) {
+		if (wl1271_ps_elp_wakeup(wl) == 0) {
+			wl1271_cmd_build_ap_probe_req(wl, wl->probereq);
+			wl1271_ps_elp_sleep(wl);
+		}
+	}
 
 	if (wl->scan.failed) {
 		wl1271_info("Scan completed due to error.");
 		ieee80211_queue_work(wl->hw, &wl->recovery_work);
 	}
+
+out:
 	mutex_unlock(&wl->mutex);
 
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/sdio.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/sdio.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/sdio.c	2012-03-24 01:15:34.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/sdio.c	2012-03-24 03:34:58.000000000 -0400
@@ -28,6 +28,7 @@
 #include <linux/mmc/sdio_func.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
 #include <linux/gpio.h>
 #include <linux/wl12xx.h>
 #include <linux/pm_runtime.h>
@@ -60,7 +61,7 @@
 	return &(wl_to_func(wl)->dev);
 }
 
-static irqreturn_t wl1271_irq(int irq, void *cookie)
+static irqreturn_t wl1271_hardirq(int irq, void *cookie)
 {
 	struct wl1271 *wl = cookie;
 	unsigned long flags;
@@ -69,17 +70,14 @@
 
 	/* complete the ELP completion */
 	spin_lock_irqsave(&wl->wl_lock, flags);
+	set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
 	if (wl->elp_compl) {
 		complete(wl->elp_compl);
 		wl->elp_compl = NULL;
 	}
-
-	if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->irq_work);
-	set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static void wl1271_sdio_disable_interrupts(struct wl1271 *wl)
@@ -106,8 +104,6 @@
 	int ret;
 	struct sdio_func *func = wl_to_func(wl);
 
-	sdio_claim_host(func);
-
 	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
 		((u8 *)buf)[0] = sdio_f0_readb(func, addr, &ret);
 		wl1271_debug(DEBUG_SDIO, "sdio read 52 addr 0x%x, byte 0x%02x",
@@ -123,8 +119,6 @@
 		wl1271_dump_ascii(DEBUG_SDIO, "data: ", buf, len);
 	}
 
-	sdio_release_host(func);
-
 	if (ret)
 		wl1271_error("sdio read failed (%d)", ret);
 }
@@ -135,8 +129,6 @@
 	int ret;
 	struct sdio_func *func = wl_to_func(wl);
 
-	sdio_claim_host(func);
-
 	if (unlikely(addr == HW_ACCESS_ELP_CTRL_REG_ADDR)) {
 		sdio_f0_writeb(func, ((u8 *)buf)[0], addr, &ret);
 		wl1271_debug(DEBUG_SDIO, "sdio write 52 addr 0x%x, byte 0x%02x",
@@ -152,8 +144,6 @@
 			ret = sdio_memcpy_toio(func, addr, buf, len);
 	}
 
-	sdio_release_host(func);
-
 	if (ret)
 		wl1271_error("sdio write failed (%d)", ret);
 }
@@ -163,14 +153,18 @@
 	struct sdio_func *func = wl_to_func(wl);
 	int ret;
 
-	/* Power up the card */
+	/* Make sure the card will not be powered off by runtime PM */
 	ret = pm_runtime_get_sync(&func->dev);
 	if (ret < 0)
 		goto out;
 
+	/* Runtime PM might be disabled, so power up the card manually */
+	ret = mmc_power_restore_host(func->card->host);
+	if (ret < 0)
+		goto out;
+
 	sdio_claim_host(func);
 	sdio_enable_func(func);
-	sdio_release_host(func);
 
 out:
 	return ret;
@@ -179,12 +173,17 @@
 static int wl1271_sdio_power_off(struct wl1271 *wl)
 {
 	struct sdio_func *func = wl_to_func(wl);
+	int ret;
 
-	sdio_claim_host(func);
 	sdio_disable_func(func);
 	sdio_release_host(func);
 
-	/* Power down the card */
+	/* Runtime PM might be disabled, so power off the card manually */
+	ret = mmc_power_save_host(func->card->host);
+	if (ret < 0)
+		return ret;
+
+	/* Let runtime PM know the card is powered off */
 	return pm_runtime_put_sync(&func->dev);
 }
 
@@ -241,14 +240,14 @@
 	wl->irq = wlan_data->irq;
 	wl->ref_clock = wlan_data->board_ref_clock;
 
-	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
+	ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   DRIVER_NAME, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
 		goto out_free;
 	}
 
-	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
 	disable_irq(wl->irq);
 
 	ret = wl1271_init_ieee80211(wl);
@@ -271,7 +270,6 @@
  out_irq:
 	free_irq(wl->irq, wl);
 
-
  out_free:
 	wl1271_free_hw(wl);
 
@@ -342,6 +340,6 @@
 module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 /*(DEBLOBBED)*/
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/spi.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/spi.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/spi.c	2012-03-24 01:15:37.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/spi.c	2012-03-24 03:35:00.000000000 -0400
@@ -110,6 +110,7 @@
 	spi_message_add_tail(&t, &m);
 
 	spi_sync(wl_to_spi(wl), &m);
+
 	wl1271_dump(DEBUG_SPI, "spi reset -> ", cmd, WSPI_INIT_CMD_LEN);
 	kfree(cmd);
 }
@@ -319,28 +320,23 @@
 	spi_sync(wl_to_spi(wl), &m);
 }
 
-static irqreturn_t wl1271_irq(int irq, void *cookie)
+static irqreturn_t wl1271_hardirq(int irq, void *cookie)
 {
-	struct wl1271 *wl;
+	struct wl1271 *wl = cookie;
 	unsigned long flags;
 
 	wl1271_debug(DEBUG_IRQ, "IRQ");
 
-	wl = cookie;
-
 	/* complete the ELP completion */
 	spin_lock_irqsave(&wl->wl_lock, flags);
+	set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
 	if (wl->elp_compl) {
 		complete(wl->elp_compl);
 		wl->elp_compl = NULL;
 	}
-
-	if (!test_and_set_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags))
-		ieee80211_queue_work(wl->hw, &wl->irq_work);
-	set_bit(WL1271_FLAG_IRQ_PENDING, &wl->flags);
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 
-	return IRQ_HANDLED;
+	return IRQ_WAKE_THREAD;
 }
 
 static int wl1271_spi_set_power(struct wl1271 *wl, bool enable)
@@ -412,14 +408,14 @@
 		goto out_free;
 	}
 
-	ret = request_irq(wl->irq, wl1271_irq, 0, DRIVER_NAME, wl);
+	ret = request_threaded_irq(wl->irq, wl1271_hardirq, wl1271_irq,
+				   IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+				   DRIVER_NAME, wl);
 	if (ret < 0) {
 		wl1271_error("request_irq() failed: %d", ret);
 		goto out_free;
 	}
 
-	set_irq_type(wl->irq, IRQ_TYPE_EDGE_RISING);
-
 	disable_irq(wl->irq);
 
 	ret = wl1271_init_ieee80211(wl);
@@ -491,7 +487,7 @@
 module_exit(wl1271_exit);
 
 MODULE_LICENSE("GPL");
-MODULE_AUTHOR("Luciano Coelho <luciano.coelho@nokia.com>");
+MODULE_AUTHOR("Luciano Coelho <coelho@ti.com>");
 MODULE_AUTHOR("Juuso Oikarinen <juuso.oikarinen@nokia.com>");
 /*(DEBLOBBED)*/
 MODULE_ALIAS("spi:wl1271");
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/testmode.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/testmode.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/testmode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/testmode.c	2011-05-19 00:06:34.000000000 -0400
@@ -204,7 +204,10 @@
 
 	kfree(wl->nvs);
 
-	wl->nvs = kzalloc(sizeof(struct wl1271_nvs_file), GFP_KERNEL);
+	if (len != sizeof(struct wl1271_nvs_file))
+		return -EINVAL;
+
+	wl->nvs = kzalloc(len, GFP_KERNEL);
 	if (!wl->nvs) {
 		wl1271_error("could not allocate memory for the nvs file");
 		ret = -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/tx.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/tx.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/tx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/tx.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,6 +23,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/etherdevice.h>
 
 #include "wl12xx.h"
 #include "io.h"
@@ -30,6 +31,23 @@
 #include "ps.h"
 #include "tx.h"
 
+static int wl1271_set_default_wep_key(struct wl1271 *wl, u8 id)
+{
+	int ret;
+	bool is_ap = (wl->bss_type == BSS_TYPE_AP_BSS);
+
+	if (is_ap)
+		ret = wl1271_cmd_set_ap_default_wep_key(wl, id);
+	else
+		ret = wl1271_cmd_set_sta_default_wep_key(wl, id);
+
+	if (ret < 0)
+		return ret;
+
+	wl1271_debug(DEBUG_CRYPT, "default wep key idx: %d", (int)id);
+	return 0;
+}
+
 static int wl1271_alloc_tx_id(struct wl1271 *wl, struct sk_buff *skb)
 {
 	int id;
@@ -52,8 +70,65 @@
 	}
 }
 
+static void wl1271_tx_ap_update_inconnection_sta(struct wl1271 *wl,
+						 struct sk_buff *skb)
+{
+	struct ieee80211_hdr *hdr;
+
+	/*
+	 * add the station to the known list before transmitting the
+	 * authentication response. this way it won't get de-authed by FW
+	 * when transmitting too soon.
+	 */
+	hdr = (struct ieee80211_hdr *)(skb->data +
+				       sizeof(struct wl1271_tx_hw_descr));
+	if (ieee80211_is_auth(hdr->frame_control))
+		wl1271_acx_set_inconnection_sta(wl, hdr->addr1);
+}
+
+static void wl1271_tx_regulate_link(struct wl1271 *wl, u8 hlid)
+{
+	bool fw_ps;
+	u8 tx_blks;
+
+	/* only regulate station links */
+	if (hlid < WL1271_AP_STA_HLID_START)
+		return;
+
+	fw_ps = test_bit(hlid, (unsigned long *)&wl->ap_fw_ps_map);
+	tx_blks = wl->links[hlid].allocated_blks;
+
+	/*
+	 * if in FW PS and there is enough data in FW we can put the link
+	 * into high-level PS and clean out its TX queues.
+	 */
+	if (fw_ps && tx_blks >= WL1271_PS_STA_MAX_BLOCKS)
+		wl1271_ps_link_start(wl, hlid, true);
+}
+
+u8 wl1271_tx_get_hlid(struct sk_buff *skb)
+{
+	struct ieee80211_tx_info *control = IEEE80211_SKB_CB(skb);
+
+	if (control->control.sta) {
+		struct wl1271_station *wl_sta;
+
+		wl_sta = (struct wl1271_station *)
+				control->control.sta->drv_priv;
+		return wl_sta->hlid;
+	} else {
+		struct ieee80211_hdr *hdr;
+
+		hdr = (struct ieee80211_hdr *)skb->data;
+		if (ieee80211_is_mgmt(hdr->frame_control))
+			return WL1271_AP_GLOBAL_HLID;
+		else
+			return WL1271_AP_BROADCAST_HLID;
+	}
+}
+
 static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
-				u32 buf_offset)
+				u32 buf_offset, u8 hlid)
 {
 	struct wl1271_tx_hw_descr *desc;
 	u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
@@ -82,6 +157,9 @@
 
 		wl->tx_blocks_available -= total_blocks;
 
+		if (wl->bss_type == BSS_TYPE_AP_BSS)
+			wl->links[hlid].allocated_blks += total_blocks;
+
 		ret = 0;
 
 		wl1271_debug(DEBUG_TX,
@@ -95,11 +173,12 @@
 }
 
 static void wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
-			      u32 extra, struct ieee80211_tx_info *control)
+			      u32 extra, struct ieee80211_tx_info *control,
+			      u8 hlid)
 {
 	struct timespec ts;
 	struct wl1271_tx_hw_descr *desc;
-	int pad, ac;
+	int pad, ac, rate_idx;
 	s64 hosttime;
 	u16 tx_attr;
 
@@ -117,7 +196,11 @@
 	getnstimeofday(&ts);
 	hosttime = (timespec_to_ns(&ts) >> 10);
 	desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
-	desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS)
+		desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
+	else
+		desc->life_time = cpu_to_le16(TX_HW_AP_MODE_PKT_LIFETIME_TU);
 
 	/* configure the tx attributes */
 	tx_attr = wl->session_counter << TX_HW_ATTR_OFST_SESSION_COUNTER;
@@ -125,25 +208,49 @@
 	/* queue (we use same identifiers for tid's and ac's */
 	ac = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 	desc->tid = ac;
-	desc->aid = TX_HW_DEFAULT_AID;
+
+	if (wl->bss_type != BSS_TYPE_AP_BSS) {
+		desc->aid = hlid;
+
+		/* if the packets are destined for AP (have a STA entry)
+		   send them with AP rate policies, otherwise use default
+		   basic rates */
+		if (control->control.sta)
+			rate_idx = ACX_TX_AP_FULL_RATE;
+		else
+			rate_idx = ACX_TX_BASIC_RATE;
+	} else {
+		desc->hlid = hlid;
+		switch (hlid) {
+		case WL1271_AP_GLOBAL_HLID:
+			rate_idx = ACX_TX_AP_MODE_MGMT_RATE;
+			break;
+		case WL1271_AP_BROADCAST_HLID:
+			rate_idx = ACX_TX_AP_MODE_BCST_RATE;
+			break;
+		default:
+			rate_idx = ac;
+			break;
+		}
+	}
+
+	tx_attr |= rate_idx << TX_HW_ATTR_OFST_RATE_POLICY;
 	desc->reserved = 0;
 
 	/* align the length (and store in terms of words) */
-	pad = WL1271_TX_ALIGN(skb->len);
+	pad = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
 	desc->length = cpu_to_le16(pad >> 2);
 
 	/* calculate number of padding bytes */
 	pad = pad - skb->len;
 	tx_attr |= pad << TX_HW_ATTR_OFST_LAST_WORD_PAD;
 
-	/* if the packets are destined for AP (have a STA entry) send them
-	   with AP rate policies, otherwise use default basic rates */
-	if (control->control.sta)
-		tx_attr |= ACX_TX_AP_FULL_RATE << TX_HW_ATTR_OFST_RATE_POLICY;
-
 	desc->tx_attr = cpu_to_le16(tx_attr);
 
-	wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d", pad);
+	wl1271_debug(DEBUG_TX, "tx_fill_hdr: pad: %d hlid: %d "
+		"tx_attr: 0x%x len: %d life: %d mem: %d", pad, desc->hlid,
+		le16_to_cpu(desc->tx_attr), le16_to_cpu(desc->length),
+		le16_to_cpu(desc->life_time), desc->total_mem_blocks);
 }
 
 /* caller must hold wl->mutex */
@@ -153,8 +260,8 @@
 	struct ieee80211_tx_info *info;
 	u32 extra = 0;
 	int ret = 0;
-	u8 idx;
 	u32 total_len;
+	u8 hlid;
 
 	if (!skb)
 		return -EINVAL;
@@ -166,29 +273,43 @@
 		extra = WL1271_TKIP_IV_SPACE;
 
 	if (info->control.hw_key) {
-		idx = info->control.hw_key->hw_key_idx;
+		bool is_wep;
+		u8 idx = info->control.hw_key->hw_key_idx;
+		u32 cipher = info->control.hw_key->cipher;
 
-		/* FIXME: do we have to do this if we're not using WEP? */
-		if (unlikely(wl->default_key != idx)) {
-			ret = wl1271_cmd_set_default_wep_key(wl, idx);
+		is_wep = (cipher == WLAN_CIPHER_SUITE_WEP40) ||
+			 (cipher == WLAN_CIPHER_SUITE_WEP104);
+
+		if (unlikely(is_wep && wl->default_key != idx)) {
+			ret = wl1271_set_default_wep_key(wl, idx);
 			if (ret < 0)
 				return ret;
 			wl->default_key = idx;
 		}
 	}
 
-	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset);
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		hlid = wl1271_tx_get_hlid(skb);
+	else
+		hlid = TX_HW_DEFAULT_AID;
+
+	ret = wl1271_tx_allocate(wl, skb, extra, buf_offset, hlid);
 	if (ret < 0)
 		return ret;
 
-	wl1271_tx_fill_hdr(wl, skb, extra, info);
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		wl1271_tx_ap_update_inconnection_sta(wl, skb);
+		wl1271_tx_regulate_link(wl, hlid);
+	}
+
+	wl1271_tx_fill_hdr(wl, skb, extra, info, hlid);
 
 	/*
 	 * The length of each packet is stored in terms of words. Thus, we must
 	 * pad the skb data to make sure its length is aligned.
 	 * The number of padding bytes is computed and set in wl1271_tx_fill_hdr
 	 */
-	total_len = WL1271_TX_ALIGN(skb->len);
+	total_len = ALIGN(skb->len, WL1271_TX_ALIGN_TO);
 	memcpy(wl->aggr_buf + buf_offset, skb->data, skb->len);
 	memset(wl->aggr_buf + buf_offset + skb->len, 0, total_len - skb->len);
 
@@ -222,7 +343,7 @@
 	return enabled_rates;
 }
 
-static void handle_tx_low_watermark(struct wl1271 *wl)
+void wl1271_handle_tx_low_watermark(struct wl1271 *wl)
 {
 	unsigned long flags;
 
@@ -236,7 +357,7 @@
 	}
 }
 
-static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
+static struct sk_buff *wl1271_sta_skb_dequeue(struct wl1271 *wl)
 {
 	struct sk_buff *skb = NULL;
 	unsigned long flags;
@@ -262,12 +383,69 @@
 	return skb;
 }
 
+static struct sk_buff *wl1271_ap_skb_dequeue(struct wl1271 *wl)
+{
+	struct sk_buff *skb = NULL;
+	unsigned long flags;
+	int i, h, start_hlid;
+
+	/* start from the link after the last one */
+	start_hlid = (wl->last_tx_hlid + 1) % AP_MAX_LINKS;
+
+	/* dequeue according to AC, round robin on each link */
+	for (i = 0; i < AP_MAX_LINKS; i++) {
+		h = (start_hlid + i) % AP_MAX_LINKS;
+
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VO]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_VI]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BE]);
+		if (skb)
+			goto out;
+		skb = skb_dequeue(&wl->links[h].tx_queue[CONF_TX_AC_BK]);
+		if (skb)
+			goto out;
+	}
+
+out:
+	if (skb) {
+		wl->last_tx_hlid = h;
+		spin_lock_irqsave(&wl->wl_lock, flags);
+		wl->tx_queue_count--;
+		spin_unlock_irqrestore(&wl->wl_lock, flags);
+	} else {
+		wl->last_tx_hlid = 0;
+	}
+
+	return skb;
+}
+
+static struct sk_buff *wl1271_skb_dequeue(struct wl1271 *wl)
+{
+	if (wl->bss_type == BSS_TYPE_AP_BSS)
+		return wl1271_ap_skb_dequeue(wl);
+
+	return wl1271_sta_skb_dequeue(wl);
+}
+
 static void wl1271_skb_queue_head(struct wl1271 *wl, struct sk_buff *skb)
 {
 	unsigned long flags;
 	int q = wl1271_tx_get_queue(skb_get_queue_mapping(skb));
 
-	skb_queue_head(&wl->tx_queue[q], skb);
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		u8 hlid = wl1271_tx_get_hlid(skb);
+		skb_queue_head(&wl->links[hlid].tx_queue[q], skb);
+
+		/* make sure we dequeue the same packet next time */
+		wl->last_tx_hlid = (hlid + AP_MAX_LINKS - 1) % AP_MAX_LINKS;
+	} else {
+		skb_queue_head(&wl->tx_queue[q], skb);
+	}
+
 	spin_lock_irqsave(&wl->wl_lock, flags);
 	wl->tx_queue_count++;
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
@@ -277,38 +455,16 @@
 {
 	struct sk_buff *skb;
 	bool woken_up = false;
-	u32 sta_rates = 0;
 	u32 buf_offset = 0;
 	bool sent_packets = false;
 	int ret;
 
-	/* check if the rates supported by the AP have changed */
-	if (unlikely(test_and_clear_bit(WL1271_FLAG_STA_RATES_CHANGED,
-					&wl->flags))) {
-		unsigned long flags;
-
-		spin_lock_irqsave(&wl->wl_lock, flags);
-		sta_rates = wl->sta_rate_set;
-		spin_unlock_irqrestore(&wl->wl_lock, flags);
-	}
-
 	if (unlikely(wl->state == WL1271_STATE_OFF))
 		goto out;
 
-	/* if rates have changed, re-configure the rate policy */
-	if (unlikely(sta_rates)) {
-		ret = wl1271_ps_elp_wakeup(wl, false);
-		if (ret < 0)
-			goto out;
-		woken_up = true;
-
-		wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
-		wl1271_acx_rate_policies(wl);
-	}
-
 	while ((skb = wl1271_skb_dequeue(wl))) {
 		if (!woken_up) {
-			ret = wl1271_ps_elp_wakeup(wl, false);
+			ret = wl1271_ps_elp_wakeup(wl);
 			if (ret < 0)
 				goto out_ack;
 			woken_up = true;
@@ -350,9 +506,15 @@
 		sent_packets = true;
 	}
 	if (sent_packets) {
-		/* interrupt the firmware with the new packets */
-		wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
-		handle_tx_low_watermark(wl);
+		/*
+		 * Interrupt the firmware with the new packets. This is only
+		 * required for older hardware revisions
+		 */
+		if (wl->quirks & WL12XX_QUIRK_END_OF_TRANSACTION)
+			wl1271_write32(wl, WL1271_HOST_WR_ACCESS,
+				       wl->tx_packets_count);
+
+		wl1271_handle_tx_low_watermark(wl);
 	}
 
 out:
@@ -427,7 +589,8 @@
 		     result->rate_class_index, result->status);
 
 	/* return the packet to the stack */
-	ieee80211_tx_status(wl->hw, skb);
+	skb_queue_tail(&wl->deferred_tx_queue, skb);
+	ieee80211_queue_work(wl->hw, &wl->netstack_work);
 	wl1271_free_tx_id(wl, result->id);
 }
 
@@ -469,34 +632,92 @@
 	}
 }
 
+void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid)
+{
+	struct sk_buff *skb;
+	int i, total = 0;
+	unsigned long flags;
+	struct ieee80211_tx_info *info;
+
+	for (i = 0; i < NUM_TX_QUEUES; i++) {
+		while ((skb = skb_dequeue(&wl->links[hlid].tx_queue[i]))) {
+			wl1271_debug(DEBUG_TX, "link freeing skb 0x%p", skb);
+			info = IEEE80211_SKB_CB(skb);
+			info->status.rates[0].idx = -1;
+			info->status.rates[0].count = 0;
+			ieee80211_tx_status(wl->hw, skb);
+			total++;
+		}
+	}
+
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	wl->tx_queue_count -= total;
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+
+	wl1271_handle_tx_low_watermark(wl);
+}
+
 /* caller must hold wl->mutex */
 void wl1271_tx_reset(struct wl1271 *wl)
 {
 	int i;
 	struct sk_buff *skb;
+	struct ieee80211_tx_info *info;
 
 	/* TX failure */
-	for (i = 0; i < NUM_TX_QUEUES; i++) {
-		while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
-			wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
-			ieee80211_tx_status(wl->hw, skb);
+	if (wl->bss_type == BSS_TYPE_AP_BSS) {
+		for (i = 0; i < AP_MAX_LINKS; i++) {
+			wl1271_tx_reset_link_queues(wl, i);
+			wl->links[i].allocated_blks = 0;
+			wl->links[i].prev_freed_blks = 0;
+		}
+
+		wl->last_tx_hlid = 0;
+	} else {
+		for (i = 0; i < NUM_TX_QUEUES; i++) {
+			while ((skb = skb_dequeue(&wl->tx_queue[i]))) {
+				wl1271_debug(DEBUG_TX, "freeing skb 0x%p",
+					     skb);
+				info = IEEE80211_SKB_CB(skb);
+				info->status.rates[0].idx = -1;
+				info->status.rates[0].count = 0;
+				ieee80211_tx_status(wl->hw, skb);
+			}
 		}
 	}
+
 	wl->tx_queue_count = 0;
 
 	/*
 	 * Make sure the driver is at a consistent state, in case this
 	 * function is called from a context other than interface removal.
 	 */
-	handle_tx_low_watermark(wl);
+	wl1271_handle_tx_low_watermark(wl);
 
-	for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
-		if (wl->tx_frames[i] != NULL) {
-			skb = wl->tx_frames[i];
-			wl1271_free_tx_id(wl, i);
-			wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
-			ieee80211_tx_status(wl->hw, skb);
+	for (i = 0; i < ACX_TX_DESCRIPTORS; i++) {
+		if (wl->tx_frames[i] == NULL)
+			continue;
+
+		skb = wl->tx_frames[i];
+		wl1271_free_tx_id(wl, i);
+		wl1271_debug(DEBUG_TX, "freeing skb 0x%p", skb);
+
+		/* Remove private headers before passing the skb to mac80211 */
+		info = IEEE80211_SKB_CB(skb);
+		skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
+		if (info->control.hw_key &&
+		    info->control.hw_key->cipher == WLAN_CIPHER_SUITE_TKIP) {
+			int hdrlen = ieee80211_get_hdrlen_from_skb(skb);
+			memmove(skb->data + WL1271_TKIP_IV_SPACE, skb->data,
+				hdrlen);
+			skb_pull(skb, WL1271_TKIP_IV_SPACE);
 		}
+
+		info->status.rates[0].idx = -1;
+		info->status.rates[0].count = 0;
+
+		ieee80211_tx_status(wl->hw, skb);
+	}
 }
 
 #define WL1271_TX_FLUSH_TIMEOUT 500000
@@ -509,8 +730,8 @@
 
 	while (!time_after(jiffies, timeout)) {
 		mutex_lock(&wl->mutex);
-		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d",
-			     wl->tx_frames_cnt);
+		wl1271_debug(DEBUG_TX, "flushing tx buffer: %d %d",
+			     wl->tx_frames_cnt, wl->tx_queue_count);
 		if ((wl->tx_frames_cnt == 0) && (wl->tx_queue_count == 0)) {
 			mutex_unlock(&wl->mutex);
 			return;
@@ -521,3 +742,21 @@
 
 	wl1271_warning("Unable to flush all TX buffers, timed out.");
 }
+
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl)
+{
+	int i;
+	u32 rate = 0;
+
+	if (!wl->basic_rate_set) {
+		WARN_ON(1);
+		wl->basic_rate_set = wl->conf.tx.basic_rate;
+	}
+
+	for (i = 0; !rate; i++) {
+		if ((wl->basic_rate_set >> i) & 0x1)
+			rate = 1 << i;
+	}
+
+	return rate;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/tx.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/tx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/tx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/tx.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,6 +29,7 @@
 #define TX_HW_BLOCK_SIZE                 252
 
 #define TX_HW_MGMT_PKT_LIFETIME_TU       2000
+#define TX_HW_AP_MODE_PKT_LIFETIME_TU    8000
 /* The chipset reference driver states, that the "aid" value 1
  * is for infra-BSS, but is still always used */
 #define TX_HW_DEFAULT_AID                1
@@ -52,8 +53,6 @@
 #define TX_HW_RESULT_QUEUE_LEN_MASK      0xf
 
 #define WL1271_TX_ALIGN_TO 4
-#define WL1271_TX_ALIGN(len) (((len) + WL1271_TX_ALIGN_TO - 1) & \
-			     ~(WL1271_TX_ALIGN_TO - 1))
 #define WL1271_TKIP_IV_SPACE 4
 
 struct wl1271_tx_hw_descr {
@@ -77,8 +76,12 @@
 	u8 id;
 	/* The packet TID value (as User-Priority) */
 	u8 tid;
-	/* Identifier of the remote STA in IBSS, 1 in infra-BSS */
-	u8 aid;
+	union {
+		/* STA - Identifier of the remote STA in IBSS, 1 in infra-BSS */
+		u8 aid;
+		/* AP - host link ID (HLID) */
+		u8 hlid;
+	} __packed;
 	u8 reserved;
 } __packed;
 
@@ -146,5 +149,9 @@
 void wl1271_tx_flush(struct wl1271 *wl);
 u8 wl1271_rate_to_idx(int rate, enum ieee80211_band band);
 u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set);
+u32 wl1271_tx_min_rate_get(struct wl1271 *wl);
+u8 wl1271_tx_get_hlid(struct sk_buff *skb);
+void wl1271_tx_reset_link_queues(struct wl1271 *wl, u8 hlid);
+void wl1271_handle_tx_low_watermark(struct wl1271 *wl);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/wl12xx_80211.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/wl12xx_80211.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/wl12xx_80211.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/wl12xx_80211.h	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,6 @@
 
 /* This really should be 8, but not for our firmware */
 #define MAX_SUPPORTED_RATES 32
-#define COUNTRY_STRING_LEN 3
 #define MAX_COUNTRY_TRIPLETS 32
 
 /* Headers */
@@ -99,7 +98,7 @@
 
 struct wl12xx_ie_country {
 	struct wl12xx_ie_header header;
-	u8 country_string[COUNTRY_STRING_LEN];
+	u8 country_string[IEEE80211_COUNTRY_STRING_LEN];
 	struct country_triplet triplets[MAX_COUNTRY_TRIPLETS];
 } __packed;
 
@@ -138,13 +137,13 @@
 	struct ieee80211_hdr_3addr hdr;
 
 	u8 llc_hdr[sizeof(rfc1042_header)];
-	u16 llc_type;
+	__be16 llc_type;
 
 	struct arphdr arp_hdr;
 	u8 sender_hw[ETH_ALEN];
-	u32 sender_ip;
+	__be32 sender_ip;
 	u8 target_hw[ETH_ALEN];
-	u32 target_ip;
+	__be32 target_ip;
 } __packed;
 
 
@@ -160,4 +159,9 @@
 	struct wl12xx_ie_country country;
 } __packed;
 
+struct wl12xx_disconn_template {
+	struct ieee80211_header header;
+	__le16 disconn_reason;
+} __packed;
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/wl12xx.h linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/wl12xx.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl12xx/wl12xx.h	2012-03-24 01:15:30.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl12xx/wl12xx.h	2012-03-24 03:34:55.000000000 -0400
@@ -38,6 +38,13 @@
 #define DRIVER_NAME "wl1271"
 #define DRIVER_PREFIX DRIVER_NAME ": "
 
+/*
+ * FW versions support BA 11n
+ * versions marks x.x.x.50-60.x
+ */
+#define WL12XX_BA_SUPPORT_FW_COST_VER2_START    50
+#define WL12XX_BA_SUPPORT_FW_COST_VER2_END      60
+
 enum {
 	DEBUG_NONE	= 0,
 	DEBUG_IRQ	= BIT(0),
@@ -57,6 +64,8 @@
 	DEBUG_SDIO	= BIT(14),
 	DEBUG_FILTERS   = BIT(15),
 	DEBUG_ADHOC     = BIT(16),
+	DEBUG_AP	= BIT(17),
+	DEBUG_MASTER	= (DEBUG_ADHOC | DEBUG_AP),
 	DEBUG_ALL	= ~0,
 };
 
@@ -103,16 +112,27 @@
 				       true);				\
 	} while (0)
 
-#define WL1271_DEFAULT_RX_CONFIG (CFG_UNI_FILTER_EN |	\
+#define WL1271_DEFAULT_STA_RX_CONFIG (CFG_UNI_FILTER_EN |	\
 				  CFG_BSSID_FILTER_EN | \
 				  CFG_MC_FILTER_EN)
 
-#define WL1271_DEFAULT_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN |  \
+#define WL1271_DEFAULT_STA_RX_FILTER (CFG_RX_RCTS_ACK | CFG_RX_PRSP_EN |  \
 				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN |   \
 				  CFG_RX_CTL_EN | CFG_RX_BCN_EN |     \
 				  CFG_RX_AUTH_EN | CFG_RX_ASSOC_EN)
 
+#define WL1271_DEFAULT_AP_RX_CONFIG  0
+
+#define WL1271_DEFAULT_AP_RX_FILTER  (CFG_RX_RCTS_ACK | CFG_RX_PREQ_EN | \
+				  CFG_RX_MGMT_EN | CFG_RX_DATA_EN | \
+				  CFG_RX_CTL_EN | CFG_RX_AUTH_EN | \
+				  CFG_RX_ASSOC_EN)
+
+
+
 #define WL1271_FW_NAME "/*(DEBLOBBED)*/"
+#define WL1271_AP_FW_NAME "/*(DEBLOBBED)*/"
+
 #define WL1271_NVS_NAME "/*(DEBLOBBED)*/"
 
 #define WL1271_TX_SECURITY_LO16(s) ((u16)((s) & 0xffff))
@@ -129,6 +149,25 @@
 #define WL1271_DEFAULT_BEACON_INT  100
 #define WL1271_DEFAULT_DTIM_PERIOD 1
 
+#define WL1271_AP_GLOBAL_HLID      0
+#define WL1271_AP_BROADCAST_HLID   1
+#define WL1271_AP_STA_HLID_START   2
+
+/*
+ * When in AP-mode, we allow (at least) this number of mem-blocks
+ * to be transmitted to FW for a STA in PS-mode. Only when packets are
+ * present in the FW buffers it will wake the sleeping STA. We want to put
+ * enough packets for the driver to transmit all of its buffered data before
+ * the STA goes to sleep again. But we don't want to take too much mem-blocks
+ * as it might hurt the throughput of active STAs.
+ * The number of blocks (18) is enough for 2 large packets.
+ */
+#define WL1271_PS_STA_MAX_BLOCKS  (2 * 9)
+
+#define WL1271_AP_BSS_INDEX        0
+#define WL1271_AP_DEF_INACTIV_SEC  300
+#define WL1271_AP_DEF_BEACON_EXP   20
+
 #define ACX_TX_DESCRIPTORS         32
 
 #define WL1271_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
@@ -161,10 +200,13 @@
 
 struct wl1271;
 
+#define WL12XX_NUM_FW_VER 5
+
 /* FIXME: I'm not sure about this structure name */
 struct wl1271_chip {
 	u32 id;
-	char fw_ver[21];
+	char fw_ver_str[ETHTOOL_BUSINFO_LEN];
+	unsigned int fw_ver[WL12XX_NUM_FW_VER];
 };
 
 struct wl1271_stats {
@@ -178,8 +220,13 @@
 #define NUM_TX_QUEUES              4
 #define NUM_RX_PKT_DESC            8
 
-/* FW status registers */
-struct wl1271_fw_status {
+#define AP_MAX_STATIONS            5
+
+/* Broadcast and Global links + links to stations */
+#define AP_MAX_LINKS               (AP_MAX_STATIONS + 2)
+
+/* FW status registers common for AP/STA */
+struct wl1271_fw_common_status {
 	__le32 intr;
 	u8  fw_rx_counter;
 	u8  drv_rx_counter;
@@ -188,9 +235,43 @@
 	__le32 rx_pkt_descs[NUM_RX_PKT_DESC];
 	__le32 tx_released_blks[NUM_TX_QUEUES];
 	__le32 fw_localtime;
-	__le32 padding[2];
 } __packed;
 
+/* FW status registers for AP */
+struct wl1271_fw_ap_status {
+	struct wl1271_fw_common_status common;
+
+	/* Next fields valid only in AP FW */
+
+	/*
+	 * A bitmap (where each bit represents a single HLID)
+	 * to indicate if the station is in PS mode.
+	 */
+	__le32 link_ps_bitmap;
+
+	/* Number of freed MBs per HLID */
+	u8 tx_lnk_free_blks[AP_MAX_LINKS];
+	u8 padding_1[1];
+} __packed;
+
+/* FW status registers for STA */
+struct wl1271_fw_sta_status {
+	struct wl1271_fw_common_status common;
+
+	u8  tx_total;
+	u8  reserved1;
+	__le16 reserved2;
+} __packed;
+
+struct wl1271_fw_full_status {
+	union {
+		struct wl1271_fw_common_status common;
+		struct wl1271_fw_sta_status sta;
+		struct wl1271_fw_ap_status ap;
+	};
+} __packed;
+
+
 struct wl1271_rx_mem_pool_addr {
 	u32 addr;
 	u32 addr_extra;
@@ -218,6 +299,48 @@
 	void (*disable_irq)(struct wl1271 *wl);
 };
 
+#define MAX_NUM_KEYS 14
+#define MAX_KEY_SIZE 32
+
+struct wl1271_ap_key {
+	u8 id;
+	u8 key_type;
+	u8 key_size;
+	u8 key[MAX_KEY_SIZE];
+	u8 hlid;
+	u32 tx_seq_32;
+	u16 tx_seq_16;
+};
+
+enum wl12xx_flags {
+	WL1271_FLAG_STA_ASSOCIATED,
+	WL1271_FLAG_JOINED,
+	WL1271_FLAG_GPIO_POWER,
+	WL1271_FLAG_TX_QUEUE_STOPPED,
+	WL1271_FLAG_TX_PENDING,
+	WL1271_FLAG_IN_ELP,
+	WL1271_FLAG_PSM,
+	WL1271_FLAG_PSM_REQUESTED,
+	WL1271_FLAG_IRQ_RUNNING,
+	WL1271_FLAG_IDLE,
+	WL1271_FLAG_IDLE_REQUESTED,
+	WL1271_FLAG_PSPOLL_FAILURE,
+	WL1271_FLAG_STA_STATE_SENT,
+	WL1271_FLAG_FW_TX_BUSY,
+	WL1271_FLAG_AP_STARTED
+};
+
+struct wl1271_link {
+	/* AP-mode - TX queue per AC in link */
+	struct sk_buff_head tx_queue[NUM_TX_QUEUES];
+
+	/* accounting for allocated / available TX blocks in FW */
+	u8 allocated_blks;
+	u8 prev_freed_blks;
+
+	u8 addr[ETH_ALEN];
+};
+
 struct wl1271 {
 	struct platform_device *plat_dev;
 	struct ieee80211_hw *hw;
@@ -236,21 +359,6 @@
 	enum wl1271_state state;
 	struct mutex mutex;
 
-#define WL1271_FLAG_STA_RATES_CHANGED  (0)
-#define WL1271_FLAG_STA_ASSOCIATED     (1)
-#define WL1271_FLAG_JOINED             (2)
-#define WL1271_FLAG_GPIO_POWER         (3)
-#define WL1271_FLAG_TX_QUEUE_STOPPED   (4)
-#define WL1271_FLAG_IN_ELP             (5)
-#define WL1271_FLAG_PSM                (6)
-#define WL1271_FLAG_PSM_REQUESTED      (7)
-#define WL1271_FLAG_IRQ_PENDING        (8)
-#define WL1271_FLAG_IRQ_RUNNING        (9)
-#define WL1271_FLAG_IDLE              (10)
-#define WL1271_FLAG_IDLE_REQUESTED    (11)
-#define WL1271_FLAG_PSPOLL_FAILURE    (12)
-#define WL1271_FLAG_STA_STATE_SENT    (13)
-#define WL1271_FLAG_FW_TX_BUSY        (14)
 	unsigned long flags;
 
 	struct wl1271_partition_set part;
@@ -262,6 +370,7 @@
 
 	u8 *fw;
 	size_t fw_len;
+	u8 fw_bss_type;
 	struct wl1271_nvs_file *nvs;
 	size_t nvs_len;
 
@@ -295,6 +404,12 @@
 	struct sk_buff_head tx_queue[NUM_TX_QUEUES];
 	int tx_queue_count;
 
+	/* Frames received, not handled yet by mac80211 */
+	struct sk_buff_head deferred_rx_queue;
+
+	/* Frames sent, not returned yet to mac80211 */
+	struct sk_buff_head deferred_tx_queue;
+
 	struct work_struct tx_work;
 
 	/* Pending TX frames */
@@ -315,8 +430,8 @@
 	/* Intermediate buffer, used for packet aggregation */
 	u8 *aggr_buf;
 
-	/* The target interrupt mask */
-	struct work_struct irq_work;
+	/* Network stack work  */
+	struct work_struct netstack_work;
 
 	/* Hardware recovery work */
 	struct work_struct recovery_work;
@@ -343,7 +458,6 @@
 	 *	bits 16-23 - 802.11n   MCS index mask
 	 * support only 1 stream, thus only 8 bits for the MCS rates (0-7).
 	 */
-	u32 sta_rate_set;
 	u32 basic_rate_set;
 	u32 basic_rate;
 	u32 rate_set;
@@ -378,13 +492,12 @@
 	int last_rssi_event;
 
 	struct wl1271_stats stats;
-	struct dentry *rootdir;
 
 	__le32 buffer_32;
 	u32 buffer_cmd;
 	u32 buffer_busyword[WL1271_BUSY_WORD_CNT];
 
-	struct wl1271_fw_status *fw_status;
+	struct wl1271_fw_full_status *fw_status;
 	struct wl1271_tx_hw_res_if *tx_res_if;
 
 	struct ieee80211_vif *vif;
@@ -400,6 +513,41 @@
 
 	/* Most recently reported noise in dBm */
 	s8 noise;
+
+	/* map for HLIDs of associated stations - when operating in AP mode */
+	unsigned long ap_hlid_map[BITS_TO_LONGS(AP_MAX_STATIONS)];
+
+	/* recoreded keys for AP-mode - set here before AP startup */
+	struct wl1271_ap_key *recorded_ap_keys[MAX_NUM_KEYS];
+
+	/* bands supported by this instance of wl12xx */
+	struct ieee80211_supported_band bands[IEEE80211_NUM_BANDS];
+
+	/* RX BA constraint value */
+	bool ba_support;
+	u8 ba_rx_bitmap;
+
+	/*
+	 * AP-mode - links indexed by HLID. The global and broadcast links
+	 * are always active.
+	 */
+	struct wl1271_link links[AP_MAX_LINKS];
+
+	/* the hlid of the link where the last transmitted skb came from */
+	int last_tx_hlid;
+
+	/* AP-mode - a bitmap of links currently in PS mode according to FW */
+	u32 ap_fw_ps_map;
+
+	/* AP-mode - a bitmap of links currently in PS mode in mac80211 */
+	unsigned long ap_ps_map;
+
+	/* Quirks of specific hardware revisions */
+	unsigned int quirks;
+};
+
+struct wl1271_station {
+	u8 hlid;
 };
 
 int wl1271_plt_start(struct wl1271 *wl);
@@ -414,6 +562,8 @@
 #define WL1271_TX_QUEUE_LOW_WATERMARK  10
 #define WL1271_TX_QUEUE_HIGH_WATERMARK 25
 
+#define WL1271_DEFERRED_QUEUE_LIMIT    64
+
 /* WL1271 needs a 200ms sleep after power on, and a 20ms sleep before power
    on in case is has been shut down shortly before */
 #define WL1271_PRE_POWER_ON_SLEEP 20 /* in milliseconds */
@@ -423,4 +573,9 @@
 #define HW_BG_RATES_MASK	0xffff
 #define HW_HT_RATES_OFFSET	16
 
+/* Quirks */
+
+/* Each RX/TX transaction requires an end-of-transaction transfer */
+#define WL12XX_QUIRK_END_OF_TRANSACTION	BIT(0)
+
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/wl3501_cs.c linux-libre-2.6.39-gnu/drivers/net/wireless/wl3501_cs.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/wl3501_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/wl3501_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
  *  \               \- IEEE 802.11 -/ \-------------- len --------------/
  *   \-struct wl3501_80211_tx_hdr--/   \-------- Ethernet Frame -------/
  *
- * Return = Postion in Card
+ * Return = Position in Card
  */
 static u16 wl3501_get_tx_buffer(struct wl3501_card *this, u16 len)
 {
@@ -1932,7 +1932,7 @@
 	this->base_addr = dev->base_addr;
 
 	if (!wl3501_get_flash_mac_addr(this)) {
-		printk(KERN_WARNING "%s: Cant read MAC addr in flash ROM?\n",
+		printk(KERN_WARNING "%s: Can't read MAC addr in flash ROM?\n",
 		       dev->name);
 		unregister_netdev(dev);
 		goto failed;
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/Makefile linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,5 @@
 		zd_rf_al7230b.o zd_rf_uw2453.o \
 		zd_rf.o zd_usb.o
 
-ifeq ($(CONFIG_ZD1211RW_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_ZD1211RW_DEBUG) := -DDEBUG
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_chip.c linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_chip.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_chip.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_chip.c	2011-05-19 00:06:34.000000000 -0400
@@ -108,25 +108,17 @@
 {
 	int r;
 	int i;
-	zd_addr_t *a16;
-	u16 *v16;
+	zd_addr_t a16[USB_MAX_IOREAD32_COUNT * 2];
+	u16 v16[USB_MAX_IOREAD32_COUNT * 2];
 	unsigned int count16;
 
 	if (count > USB_MAX_IOREAD32_COUNT)
 		return -EINVAL;
 
-	/* Allocate a single memory block for values and addresses. */
-	count16 = 2*count;
-	/* zd_addr_t is __nocast, so the kmalloc needs an explicit cast */
-	a16 = (zd_addr_t *) kmalloc(count16 * (sizeof(zd_addr_t) + sizeof(u16)),
-		                   GFP_KERNEL);
-	if (!a16) {
-		dev_dbg_f(zd_chip_dev(chip),
-			  "error ENOMEM in allocation of a16\n");
-		r = -ENOMEM;
-		goto out;
-	}
-	v16 = (u16 *)(a16 + count16);
+	/* Use stack for values and addresses. */
+	count16 = 2 * count;
+	BUG_ON(count16 * sizeof(zd_addr_t) > sizeof(a16));
+	BUG_ON(count16 * sizeof(u16) > sizeof(v16));
 
 	for (i = 0; i < count; i++) {
 		int j = 2*i;
@@ -139,7 +131,7 @@
 	if (r) {
 		dev_dbg_f(zd_chip_dev(chip),
 			  "error: zd_ioread16v_locked. Error number %d\n", r);
-		goto out;
+		return r;
 	}
 
 	for (i = 0; i < count; i++) {
@@ -147,18 +139,19 @@
 		values[i] = (v16[j] << 16) | v16[j+1];
 	}
 
-out:
-	kfree((void *)a16);
-	return r;
+	return 0;
 }
 
-int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
-	           unsigned int count)
+static int _zd_iowrite32v_async_locked(struct zd_chip *chip,
+				       const struct zd_ioreq32 *ioreqs,
+				       unsigned int count)
 {
 	int i, j, r;
-	struct zd_ioreq16 *ioreqs16;
+	struct zd_ioreq16 ioreqs16[USB_MAX_IOWRITE32_COUNT * 2];
 	unsigned int count16;
 
+	/* Use stack for values and addresses. */
+
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
 
 	if (count == 0)
@@ -166,15 +159,8 @@
 	if (count > USB_MAX_IOWRITE32_COUNT)
 		return -EINVAL;
 
-	/* Allocate a single memory block for values and addresses. */
-	count16 = 2*count;
-	ioreqs16 = kmalloc(count16 * sizeof(struct zd_ioreq16), GFP_KERNEL);
-	if (!ioreqs16) {
-		r = -ENOMEM;
-		dev_dbg_f(zd_chip_dev(chip),
-			  "error %d in ioreqs16 allocation\n", r);
-		goto out;
-	}
+	count16 = 2 * count;
+	BUG_ON(count16 * sizeof(struct zd_ioreq16) > sizeof(ioreqs16));
 
 	for (i = 0; i < count; i++) {
 		j = 2*i;
@@ -185,18 +171,30 @@
 		ioreqs16[j+1].addr  = ioreqs[i].addr;
 	}
 
-	r = zd_usb_iowrite16v(&chip->usb, ioreqs16, count16);
+	r = zd_usb_iowrite16v_async(&chip->usb, ioreqs16, count16);
 #ifdef DEBUG
 	if (r) {
 		dev_dbg_f(zd_chip_dev(chip),
 			  "error %d in zd_usb_write16v\n", r);
 	}
 #endif /* DEBUG */
-out:
-	kfree(ioreqs16);
 	return r;
 }
 
+int _zd_iowrite32v_locked(struct zd_chip *chip, const struct zd_ioreq32 *ioreqs,
+			  unsigned int count)
+{
+	int r;
+
+	zd_usb_iowrite16v_async_start(&chip->usb);
+	r = _zd_iowrite32v_async_locked(chip, ioreqs, count);
+	if (r) {
+		zd_usb_iowrite16v_async_end(&chip->usb, 0);
+		return r;
+	}
+	return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
+}
+
 int zd_iowrite16a_locked(struct zd_chip *chip,
                   const struct zd_ioreq16 *ioreqs, unsigned int count)
 {
@@ -204,6 +202,8 @@
 	unsigned int i, j, t, max;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+	zd_usb_iowrite16v_async_start(&chip->usb);
+
 	for (i = 0; i < count; i += j + t) {
 		t = 0;
 		max = count-i;
@@ -216,8 +216,9 @@
 			}
 		}
 
-		r = zd_usb_iowrite16v(&chip->usb, &ioreqs[i], j);
+		r = zd_usb_iowrite16v_async(&chip->usb, &ioreqs[i], j);
 		if (r) {
+			zd_usb_iowrite16v_async_end(&chip->usb, 0);
 			dev_dbg_f(zd_chip_dev(chip),
 				  "error zd_usb_iowrite16v. Error number %d\n",
 				  r);
@@ -225,7 +226,7 @@
 		}
 	}
 
-	return 0;
+	return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
 }
 
 /* Writes a variable number of 32 bit registers. The functions will split
@@ -238,6 +239,8 @@
 	int r;
 	unsigned int i, j, t, max;
 
+	zd_usb_iowrite16v_async_start(&chip->usb);
+
 	for (i = 0; i < count; i += j + t) {
 		t = 0;
 		max = count-i;
@@ -250,8 +253,9 @@
 			}
 		}
 
-		r = _zd_iowrite32v_locked(chip, &ioreqs[i], j);
+		r = _zd_iowrite32v_async_locked(chip, &ioreqs[i], j);
 		if (r) {
+			zd_usb_iowrite16v_async_end(&chip->usb, 0);
 			dev_dbg_f(zd_chip_dev(chip),
 				"error _zd_iowrite32v_locked."
 				" Error number %d\n", r);
@@ -259,7 +263,7 @@
 		}
 	}
 
-	return 0;
+	return zd_usb_iowrite16v_async_end(&chip->usb, 50 /* ms */);
 }
 
 int zd_ioread16(struct zd_chip *chip, zd_addr_t addr, u16 *value)
@@ -370,16 +374,12 @@
 	return r;
 }
 
-/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
- *              CR_MAC_ADDR_P2 must be overwritten
- */
-int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+static int zd_write_mac_addr_common(struct zd_chip *chip, const u8 *mac_addr,
+				    const struct zd_ioreq32 *in_reqs,
+				    const char *type)
 {
 	int r;
-	struct zd_ioreq32 reqs[2] = {
-		[0] = { .addr = CR_MAC_ADDR_P1 },
-		[1] = { .addr = CR_MAC_ADDR_P2 },
-	};
+	struct zd_ioreq32 reqs[2] = {in_reqs[0], in_reqs[1]};
 
 	if (mac_addr) {
 		reqs[0].value = (mac_addr[3] << 24)
@@ -388,9 +388,9 @@
 			      |  mac_addr[0];
 		reqs[1].value = (mac_addr[5] <<  8)
 			      |  mac_addr[4];
-		dev_dbg_f(zd_chip_dev(chip), "mac addr %pM\n", mac_addr);
+		dev_dbg_f(zd_chip_dev(chip), "%s addr %pM\n", type, mac_addr);
 	} else {
-		dev_dbg_f(zd_chip_dev(chip), "set NULL mac\n");
+		dev_dbg_f(zd_chip_dev(chip), "set NULL %s\n", type);
 	}
 
 	mutex_lock(&chip->mutex);
@@ -399,6 +399,29 @@
 	return r;
 }
 
+/* MAC address: if custom mac addresses are to be used CR_MAC_ADDR_P1 and
+ *              CR_MAC_ADDR_P2 must be overwritten
+ */
+int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr)
+{
+	static const struct zd_ioreq32 reqs[2] = {
+		[0] = { .addr = CR_MAC_ADDR_P1 },
+		[1] = { .addr = CR_MAC_ADDR_P2 },
+	};
+
+	return zd_write_mac_addr_common(chip, mac_addr, reqs, "mac");
+}
+
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid)
+{
+	static const struct zd_ioreq32 reqs[2] = {
+		[0] = { .addr = CR_BSSID_P1 },
+		[1] = { .addr = CR_BSSID_P2 },
+	};
+
+	return zd_write_mac_addr_common(chip, bssid, reqs, "bssid");
+}
+
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain)
 {
 	int r;
@@ -849,11 +872,12 @@
 static int set_aw_pt_bi(struct zd_chip *chip, struct aw_pt_bi *s)
 {
 	struct zd_ioreq32 reqs[3];
+	u16 b_interval = s->beacon_interval & 0xffff;
 
-	if (s->beacon_interval <= 5)
-		s->beacon_interval = 5;
-	if (s->pre_tbtt < 4 || s->pre_tbtt >= s->beacon_interval)
-		s->pre_tbtt = s->beacon_interval - 1;
+	if (b_interval <= 5)
+		b_interval = 5;
+	if (s->pre_tbtt < 4 || s->pre_tbtt >= b_interval)
+		s->pre_tbtt = b_interval - 1;
 	if (s->atim_wnd_period >= s->pre_tbtt)
 		s->atim_wnd_period = s->pre_tbtt - 1;
 
@@ -862,31 +886,57 @@
 	reqs[1].addr = CR_PRE_TBTT;
 	reqs[1].value = s->pre_tbtt;
 	reqs[2].addr = CR_BCN_INTERVAL;
-	reqs[2].value = s->beacon_interval;
+	reqs[2].value = (s->beacon_interval & ~0xffff) | b_interval;
 
 	return zd_iowrite32a_locked(chip, reqs, ARRAY_SIZE(reqs));
 }
 
 
-static int set_beacon_interval(struct zd_chip *chip, u32 interval)
+static int set_beacon_interval(struct zd_chip *chip, u16 interval,
+			       u8 dtim_period, int type)
 {
 	int r;
 	struct aw_pt_bi s;
+	u32 b_interval, mode_flag;
 
 	ZD_ASSERT(mutex_is_locked(&chip->mutex));
+
+	if (interval > 0) {
+		switch (type) {
+		case NL80211_IFTYPE_ADHOC:
+		case NL80211_IFTYPE_MESH_POINT:
+			mode_flag = BCN_MODE_IBSS;
+			break;
+		case NL80211_IFTYPE_AP:
+			mode_flag = BCN_MODE_AP;
+			break;
+		default:
+			mode_flag = 0;
+			break;
+		}
+	} else {
+		dtim_period = 0;
+		mode_flag = 0;
+	}
+
+	b_interval = mode_flag | (dtim_period << 16) | interval;
+
+	r = zd_iowrite32_locked(chip, b_interval, CR_BCN_INTERVAL);
+	if (r)
+		return r;
 	r = get_aw_pt_bi(chip, &s);
 	if (r)
 		return r;
-	s.beacon_interval = interval;
 	return set_aw_pt_bi(chip, &s);
 }
 
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval)
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+			   int type)
 {
 	int r;
 
 	mutex_lock(&chip->mutex);
-	r = set_beacon_interval(chip, interval);
+	r = set_beacon_interval(chip, interval, dtim_period, type);
 	mutex_unlock(&chip->mutex);
 	return r;
 }
@@ -905,7 +955,7 @@
 	if (r)
 		return r;
 
-	return set_beacon_interval(chip, 100);
+	return set_beacon_interval(chip, 100, 0, NL80211_IFTYPE_UNSPECIFIED);
 }
 
 static zd_addr_t fw_reg_addr(struct zd_chip *chip, u16 offset)
@@ -1407,6 +1457,9 @@
 	mutex_lock(&chip->mutex);
 	zd_usb_disable_int(&chip->usb);
 	mutex_unlock(&chip->mutex);
+
+	/* cancel pending interrupt work */
+	cancel_work_sync(&zd_chip_to_mac(chip)->process_intr);
 }
 
 int zd_chip_enable_rxtx(struct zd_chip *chip)
@@ -1416,6 +1469,7 @@
 	mutex_lock(&chip->mutex);
 	zd_usb_enable_tx(&chip->usb);
 	r = zd_usb_enable_rx(&chip->usb);
+	zd_tx_watchdog_enable(&chip->usb);
 	mutex_unlock(&chip->mutex);
 	return r;
 }
@@ -1423,6 +1477,7 @@
 void zd_chip_disable_rxtx(struct zd_chip *chip)
 {
 	mutex_lock(&chip->mutex);
+	zd_tx_watchdog_disable(&chip->usb);
 	zd_usb_disable_rx(&chip->usb);
 	zd_usb_disable_tx(&chip->usb);
 	mutex_unlock(&chip->mutex);
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_chip.h linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_chip.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_chip.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_chip.h	2011-05-19 00:06:34.000000000 -0400
@@ -546,6 +546,7 @@
 #define RX_FILTER_CTRL (RX_FILTER_RTS | RX_FILTER_CTS | \
 	RX_FILTER_CFEND | RX_FILTER_CFACK)
 
+#define BCN_MODE_AP			0x1000000
 #define BCN_MODE_IBSS			0x2000000
 
 /* Monitor mode sets filter to 0xfffff */
@@ -881,6 +882,7 @@
 u8  zd_chip_get_channel(struct zd_chip *chip);
 int zd_read_regdomain(struct zd_chip *chip, u8 *regdomain);
 int zd_write_mac_addr(struct zd_chip *chip, const u8 *mac_addr);
+int zd_write_bssid(struct zd_chip *chip, const u8 *bssid);
 int zd_chip_switch_radio_on(struct zd_chip *chip);
 int zd_chip_switch_radio_off(struct zd_chip *chip);
 int zd_chip_enable_int(struct zd_chip *chip);
@@ -920,7 +922,8 @@
 
 int zd_chip_control_leds(struct zd_chip *chip, enum led_status status);
 
-int zd_set_beacon_interval(struct zd_chip *chip, u32 interval);
+int zd_set_beacon_interval(struct zd_chip *chip, u16 interval, u8 dtim_period,
+			   int type);
 
 static inline int zd_get_beacon_interval(struct zd_chip *chip, u32 *interval)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_def.h linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_def.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,7 +45,7 @@
 #ifdef DEBUG
 #  define ZD_ASSERT(x) \
 do { \
-	if (!(x)) { \
+	if (unlikely(!(x))) { \
 		pr_debug("%s:%d ASSERT %s VIOLATED!\n", \
 			__FILE__, __LINE__, __stringify(x)); \
 		dump_stack(); \
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_mac.c linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_mac.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_mac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_mac.c	2011-05-19 00:06:34.000000000 -0400
@@ -138,6 +138,12 @@
 static void housekeeping_init(struct zd_mac *mac);
 static void housekeeping_enable(struct zd_mac *mac);
 static void housekeeping_disable(struct zd_mac *mac);
+static void beacon_init(struct zd_mac *mac);
+static void beacon_enable(struct zd_mac *mac);
+static void beacon_disable(struct zd_mac *mac);
+static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble);
+static int zd_mac_config_beacon(struct ieee80211_hw *hw,
+				struct sk_buff *beacon);
 
 static int zd_reg2alpha2(u8 regdomain, char *alpha2)
 {
@@ -231,6 +237,26 @@
 	return zd_iowrite32(&mac->chip, CR_RX_FILTER, filter);
 }
 
+static int set_mac_and_bssid(struct zd_mac *mac)
+{
+	int r;
+
+	if (!mac->vif)
+		return -1;
+
+	r = zd_write_mac_addr(&mac->chip, mac->vif->addr);
+	if (r)
+		return r;
+
+	/* Vendor driver after setting MAC either sets BSSID for AP or
+	 * filter for other modes.
+	 */
+	if (mac->type != NL80211_IFTYPE_AP)
+		return set_rx_filter(mac);
+	else
+		return zd_write_bssid(&mac->chip, mac->vif->addr);
+}
+
 static int set_mc_hash(struct zd_mac *mac)
 {
 	struct zd_mc_hash hash;
@@ -238,7 +264,7 @@
 	return zd_chip_set_multicast_hash(&mac->chip, &hash);
 }
 
-static int zd_op_start(struct ieee80211_hw *hw)
+int zd_op_start(struct ieee80211_hw *hw)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct zd_chip *chip = &mac->chip;
@@ -275,6 +301,8 @@
 		goto disable_rxtx;
 
 	housekeeping_enable(mac);
+	beacon_enable(mac);
+	set_bit(ZD_DEVICE_RUNNING, &mac->flags);
 	return 0;
 disable_rxtx:
 	zd_chip_disable_rxtx(chip);
@@ -286,19 +314,22 @@
 	return r;
 }
 
-static void zd_op_stop(struct ieee80211_hw *hw)
+void zd_op_stop(struct ieee80211_hw *hw)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct zd_chip *chip = &mac->chip;
 	struct sk_buff *skb;
 	struct sk_buff_head *ack_wait_queue = &mac->ack_wait_queue;
 
+	clear_bit(ZD_DEVICE_RUNNING, &mac->flags);
+
 	/* The order here deliberately is a little different from the open()
 	 * method, since we need to make sure there is no opportunity for RX
 	 * frames to be processed by mac80211 after we have stopped it.
 	 */
 
 	zd_chip_disable_rxtx(chip);
+	beacon_disable(mac);
 	housekeeping_disable(mac);
 	flush_workqueue(zd_workqueue);
 
@@ -311,6 +342,68 @@
 		dev_kfree_skb_any(skb);
 }
 
+int zd_restore_settings(struct zd_mac *mac)
+{
+	struct sk_buff *beacon;
+	struct zd_mc_hash multicast_hash;
+	unsigned int short_preamble;
+	int r, beacon_interval, beacon_period;
+	u8 channel;
+
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+
+	spin_lock_irq(&mac->lock);
+	multicast_hash = mac->multicast_hash;
+	short_preamble = mac->short_preamble;
+	beacon_interval = mac->beacon.interval;
+	beacon_period = mac->beacon.period;
+	channel = mac->channel;
+	spin_unlock_irq(&mac->lock);
+
+	r = set_mac_and_bssid(mac);
+	if (r < 0) {
+		dev_dbg_f(zd_mac_dev(mac), "set_mac_and_bssid failed, %d\n", r);
+		return r;
+	}
+
+	r = zd_chip_set_channel(&mac->chip, channel);
+	if (r < 0) {
+		dev_dbg_f(zd_mac_dev(mac), "zd_chip_set_channel failed, %d\n",
+			  r);
+		return r;
+	}
+
+	set_rts_cts(mac, short_preamble);
+
+	r = zd_chip_set_multicast_hash(&mac->chip, &multicast_hash);
+	if (r < 0) {
+		dev_dbg_f(zd_mac_dev(mac),
+			  "zd_chip_set_multicast_hash failed, %d\n", r);
+		return r;
+	}
+
+	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
+	    mac->type == NL80211_IFTYPE_ADHOC ||
+	    mac->type == NL80211_IFTYPE_AP) {
+		if (mac->vif != NULL) {
+			beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+			if (beacon) {
+				zd_mac_config_beacon(mac->hw, beacon);
+				kfree_skb(beacon);
+			}
+		}
+
+		zd_set_beacon_interval(&mac->chip, beacon_interval,
+					beacon_period, mac->type);
+
+		spin_lock_irq(&mac->lock);
+		mac->beacon.last_update = jiffies;
+		spin_unlock_irq(&mac->lock);
+	}
+
+	return 0;
+}
+
 /**
  * zd_mac_tx_status - reports tx status of a packet if required
  * @hw - a &struct ieee80211_hw pointer
@@ -574,64 +667,120 @@
 static int zd_mac_config_beacon(struct ieee80211_hw *hw, struct sk_buff *beacon)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
-	int r;
+	int r, ret, num_cmds, req_pos = 0;
 	u32 tmp, j = 0;
 	/* 4 more bytes for tail CRC */
 	u32 full_len = beacon->len + 4;
+	unsigned long end_jiffies, message_jiffies;
+	struct zd_ioreq32 *ioreqs;
 
-	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 0);
+	/* Alloc memory for full beacon write at once. */
+	num_cmds = 1 + zd_chip_is_zd1211b(&mac->chip) + full_len;
+	ioreqs = kmalloc(num_cmds * sizeof(struct zd_ioreq32), GFP_KERNEL);
+	if (!ioreqs)
+		return -ENOMEM;
+
+	mutex_lock(&mac->chip.mutex);
+
+	r = zd_iowrite32_locked(&mac->chip, 0, CR_BCN_FIFO_SEMAPHORE);
 	if (r < 0)
-		return r;
-	r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+		goto out;
+	r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
 	if (r < 0)
-		return r;
+		goto release_sema;
 
+	end_jiffies = jiffies + HZ / 2; /*~500ms*/
+	message_jiffies = jiffies + HZ / 10; /*~100ms*/
 	while (tmp & 0x2) {
-		r = zd_ioread32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, &tmp);
+		r = zd_ioread32_locked(&mac->chip, &tmp, CR_BCN_FIFO_SEMAPHORE);
 		if (r < 0)
-			return r;
-		if ((++j % 100) == 0) {
-			printk(KERN_ERR "CR_BCN_FIFO_SEMAPHORE not ready\n");
-			if (j >= 500)  {
-				printk(KERN_ERR "Giving up beacon config.\n");
-				return -ETIMEDOUT;
+			goto release_sema;
+		if (time_is_before_eq_jiffies(message_jiffies)) {
+			message_jiffies = jiffies + HZ / 10;
+			dev_err(zd_mac_dev(mac),
+					"CR_BCN_FIFO_SEMAPHORE not ready\n");
+			if (time_is_before_eq_jiffies(end_jiffies))  {
+				dev_err(zd_mac_dev(mac),
+						"Giving up beacon config.\n");
+				r = -ETIMEDOUT;
+				goto reset_device;
 			}
 		}
-		msleep(1);
+		msleep(20);
 	}
 
-	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, full_len - 1);
-	if (r < 0)
-		return r;
+	ioreqs[req_pos].addr = CR_BCN_FIFO;
+	ioreqs[req_pos].value = full_len - 1;
+	req_pos++;
 	if (zd_chip_is_zd1211b(&mac->chip)) {
-		r = zd_iowrite32(&mac->chip, CR_BCN_LENGTH, full_len - 1);
-		if (r < 0)
-			return r;
+		ioreqs[req_pos].addr = CR_BCN_LENGTH;
+		ioreqs[req_pos].value = full_len - 1;
+		req_pos++;
 	}
 
 	for (j = 0 ; j < beacon->len; j++) {
-		r = zd_iowrite32(&mac->chip, CR_BCN_FIFO,
-				*((u8 *)(beacon->data + j)));
-		if (r < 0)
-			return r;
+		ioreqs[req_pos].addr = CR_BCN_FIFO;
+		ioreqs[req_pos].value = *((u8 *)(beacon->data + j));
+		req_pos++;
 	}
 
 	for (j = 0; j < 4; j++) {
-		r = zd_iowrite32(&mac->chip, CR_BCN_FIFO, 0x0);
-		if (r < 0)
-			return r;
+		ioreqs[req_pos].addr = CR_BCN_FIFO;
+		ioreqs[req_pos].value = 0x0;
+		req_pos++;
 	}
 
-	r = zd_iowrite32(&mac->chip, CR_BCN_FIFO_SEMAPHORE, 1);
-	if (r < 0)
-		return r;
+	BUG_ON(req_pos != num_cmds);
+
+	r = zd_iowrite32a_locked(&mac->chip, ioreqs, num_cmds);
+
+release_sema:
+	/*
+	 * Try very hard to release device beacon semaphore, as otherwise
+	 * device/driver can be left in unusable state.
+	 */
+	end_jiffies = jiffies + HZ / 2; /*~500ms*/
+	ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
+	while (ret < 0) {
+		if (time_is_before_eq_jiffies(end_jiffies)) {
+			ret = -ETIMEDOUT;
+			break;
+		}
+
+		msleep(20);
+		ret = zd_iowrite32_locked(&mac->chip, 1, CR_BCN_FIFO_SEMAPHORE);
+	}
+
+	if (ret < 0)
+		dev_err(zd_mac_dev(mac), "Could not release "
+					 "CR_BCN_FIFO_SEMAPHORE!\n");
+	if (r < 0 || ret < 0) {
+		if (r >= 0)
+			r = ret;
+		goto out;
+	}
 
 	/* 802.11b/g 2.4G CCK 1Mb
 	 * 802.11a, not yet implemented, uses different values (see GPL vendor
 	 * driver)
 	 */
-	return zd_iowrite32(&mac->chip, CR_BCN_PLCP_CFG, 0x00000400 |
-			(full_len << 19));
+	r = zd_iowrite32_locked(&mac->chip, 0x00000400 | (full_len << 19),
+				CR_BCN_PLCP_CFG);
+out:
+	mutex_unlock(&mac->chip.mutex);
+	kfree(ioreqs);
+	return r;
+
+reset_device:
+	mutex_unlock(&mac->chip.mutex);
+	kfree(ioreqs);
+
+	/* semaphore stuck, reset device to avoid fw freeze later */
+	dev_warn(zd_mac_dev(mac), "CR_BCN_FIFO_SEMAPHORE stuck, "
+				  "reseting device...");
+	usb_queue_reset_device(mac->chip.usb.intf);
+
+	return r;
 }
 
 static int fill_ctrlset(struct zd_mac *mac,
@@ -701,7 +850,7 @@
  * control block of the skbuff will be initialized. If necessary the incoming
  * mac80211 queues will be stopped.
  */
-static int zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
+static void zd_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
@@ -716,11 +865,10 @@
 	r = zd_usb_tx(&mac->chip.usb, skb);
 	if (r)
 		goto fail;
-	return 0;
+	return;
 
 fail:
 	dev_kfree_skb(skb);
-	return 0;
 }
 
 /**
@@ -779,6 +927,13 @@
 
 		mac->ack_pending = 1;
 		mac->ack_signal = stats->signal;
+
+		/* Prevent pending tx-packet on AP-mode */
+		if (mac->type == NL80211_IFTYPE_AP) {
+			skb = __skb_dequeue(q);
+			zd_mac_tx_status(hw, skb, mac->ack_signal, NULL);
+			mac->ack_pending = 0;
+		}
 	}
 
 	spin_unlock_irqrestore(&q->lock, flags);
@@ -882,13 +1037,16 @@
 	case NL80211_IFTYPE_MESH_POINT:
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_ADHOC:
+	case NL80211_IFTYPE_AP:
 		mac->type = vif->type;
 		break;
 	default:
 		return -EOPNOTSUPP;
 	}
 
-	return zd_write_mac_addr(&mac->chip, vif->addr);
+	mac->vif = vif;
+
+	return set_mac_and_bssid(mac);
 }
 
 static void zd_op_remove_interface(struct ieee80211_hw *hw,
@@ -896,7 +1054,8 @@
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
 	mac->type = NL80211_IFTYPE_UNSPECIFIED;
-	zd_set_beacon_interval(&mac->chip, 0);
+	mac->vif = NULL;
+	zd_set_beacon_interval(&mac->chip, 0, 0, NL80211_IFTYPE_UNSPECIFIED);
 	zd_write_mac_addr(&mac->chip, NULL);
 }
 
@@ -905,49 +1064,67 @@
 	struct zd_mac *mac = zd_hw_mac(hw);
 	struct ieee80211_conf *conf = &hw->conf;
 
+	spin_lock_irq(&mac->lock);
+	mac->channel = conf->channel->hw_value;
+	spin_unlock_irq(&mac->lock);
+
 	return zd_chip_set_channel(&mac->chip, conf->channel->hw_value);
 }
 
-static void zd_process_intr(struct work_struct *work)
+static void zd_beacon_done(struct zd_mac *mac)
 {
-	u16 int_status;
-	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
-
-	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer+4));
-	if (int_status & INT_CFG_NEXT_BCN)
-		dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");
-	else
-		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
+	struct sk_buff *skb, *beacon;
 
-	zd_chip_enable_hwint(&mac->chip);
-}
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		return;
+	if (!mac->vif || mac->vif->type != NL80211_IFTYPE_AP)
+		return;
 
+	/*
+	 * Send out buffered broad- and multicast frames.
+	 */
+	while (!ieee80211_queue_stopped(mac->hw, 0)) {
+		skb = ieee80211_get_buffered_bc(mac->hw, mac->vif);
+		if (!skb)
+			break;
+		zd_op_tx(mac->hw, skb);
+	}
 
-static void set_multicast_hash_handler(struct work_struct *work)
-{
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_multicast_hash_work);
-	struct zd_mc_hash hash;
+	/*
+	 * Fetch next beacon so that tim_count is updated.
+	 */
+	beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+	if (beacon) {
+		zd_mac_config_beacon(mac->hw, beacon);
+		kfree_skb(beacon);
+	}
 
 	spin_lock_irq(&mac->lock);
-	hash = mac->multicast_hash;
+	mac->beacon.last_update = jiffies;
 	spin_unlock_irq(&mac->lock);
-
-	zd_chip_set_multicast_hash(&mac->chip, &hash);
 }
 
-static void set_rx_filter_handler(struct work_struct *work)
+static void zd_process_intr(struct work_struct *work)
 {
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_rx_filter_work);
-	int r;
+	u16 int_status;
+	unsigned long flags;
+	struct zd_mac *mac = container_of(work, struct zd_mac, process_intr);
 
-	dev_dbg_f(zd_mac_dev(mac), "\n");
-	r = set_rx_filter(mac);
-	if (r)
-		dev_err(zd_mac_dev(mac), "set_rx_filter_handler error %d\n", r);
+	spin_lock_irqsave(&mac->lock, flags);
+	int_status = le16_to_cpu(*(__le16 *)(mac->intr_buffer + 4));
+	spin_unlock_irqrestore(&mac->lock, flags);
+
+	if (int_status & INT_CFG_NEXT_BCN) {
+		/*dev_dbg_f_limit(zd_mac_dev(mac), "INT_CFG_NEXT_BCN\n");*/
+		zd_beacon_done(mac);
+	} else {
+		dev_dbg_f(zd_mac_dev(mac), "Unsupported interrupt\n");
+	}
+
+	zd_chip_enable_hwint(&mac->chip);
 }
 
+
 static u64 zd_op_prepare_multicast(struct ieee80211_hw *hw,
 				   struct netdev_hw_addr_list *mc_list)
 {
@@ -979,6 +1156,7 @@
 	};
 	struct zd_mac *mac = zd_hw_mac(hw);
 	unsigned long flags;
+	int r;
 
 	/* Only deal with supported flags */
 	changed_flags &= SUPPORTED_FIF_FLAGS;
@@ -1000,11 +1178,13 @@
 	mac->multicast_hash = hash;
 	spin_unlock_irqrestore(&mac->lock, flags);
 
-	/* XXX: these can be called here now, can sleep now! */
-	queue_work(zd_workqueue, &mac->set_multicast_hash_work);
+	zd_chip_set_multicast_hash(&mac->chip, &hash);
 
-	if (changed_flags & FIF_CONTROL)
-		queue_work(zd_workqueue, &mac->set_rx_filter_work);
+	if (changed_flags & FIF_CONTROL) {
+		r = set_rx_filter(mac);
+		if (r)
+			dev_err(zd_mac_dev(mac), "set_rx_filter error %d\n", r);
+	}
 
 	/* no handling required for FIF_OTHER_BSS as we don't currently
 	 * do BSSID filtering */
@@ -1016,20 +1196,9 @@
 	 * time. */
 }
 
-static void set_rts_cts_work(struct work_struct *work)
+static void set_rts_cts(struct zd_mac *mac, unsigned int short_preamble)
 {
-	struct zd_mac *mac =
-		container_of(work, struct zd_mac, set_rts_cts_work);
-	unsigned long flags;
-	unsigned int short_preamble;
-
 	mutex_lock(&mac->chip.mutex);
-
-	spin_lock_irqsave(&mac->lock, flags);
-	mac->updating_rts_rate = 0;
-	short_preamble = mac->short_preamble;
-	spin_unlock_irqrestore(&mac->lock, flags);
-
 	zd_chip_set_rts_cts_rate_locked(&mac->chip, short_preamble);
 	mutex_unlock(&mac->chip.mutex);
 }
@@ -1040,33 +1209,42 @@
 				   u32 changes)
 {
 	struct zd_mac *mac = zd_hw_mac(hw);
-	unsigned long flags;
 	int associated;
 
 	dev_dbg_f(zd_mac_dev(mac), "changes: %x\n", changes);
 
 	if (mac->type == NL80211_IFTYPE_MESH_POINT ||
-	    mac->type == NL80211_IFTYPE_ADHOC) {
+	    mac->type == NL80211_IFTYPE_ADHOC ||
+	    mac->type == NL80211_IFTYPE_AP) {
 		associated = true;
 		if (changes & BSS_CHANGED_BEACON) {
 			struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
 
 			if (beacon) {
+				zd_chip_disable_hwint(&mac->chip);
 				zd_mac_config_beacon(hw, beacon);
+				zd_chip_enable_hwint(&mac->chip);
 				kfree_skb(beacon);
 			}
 		}
 
 		if (changes & BSS_CHANGED_BEACON_ENABLED) {
-			u32 interval;
+			u16 interval = 0;
+			u8 period = 0;
 
-			if (bss_conf->enable_beacon)
-				interval = BCN_MODE_IBSS |
-						bss_conf->beacon_int;
-			else
-				interval = 0;
+			if (bss_conf->enable_beacon) {
+				period = bss_conf->dtim_period;
+				interval = bss_conf->beacon_int;
+			}
 
-			zd_set_beacon_interval(&mac->chip, interval);
+			spin_lock_irq(&mac->lock);
+			mac->beacon.period = period;
+			mac->beacon.interval = interval;
+			mac->beacon.last_update = jiffies;
+			spin_unlock_irq(&mac->lock);
+
+			zd_set_beacon_interval(&mac->chip, interval, period,
+					       mac->type);
 		}
 	} else
 		associated = is_valid_ether_addr(bss_conf->bssid);
@@ -1078,15 +1256,11 @@
 	/* TODO: do hardware bssid filtering */
 
 	if (changes & BSS_CHANGED_ERP_PREAMBLE) {
-		spin_lock_irqsave(&mac->lock, flags);
+		spin_lock_irq(&mac->lock);
 		mac->short_preamble = bss_conf->use_short_preamble;
-		if (!mac->updating_rts_rate) {
-			mac->updating_rts_rate = 1;
-			/* FIXME: should disable TX here, until work has
-			 * completed and RTS_CTS reg is updated */
-			queue_work(zd_workqueue, &mac->set_rts_cts_work);
-		}
-		spin_unlock_irqrestore(&mac->lock, flags);
+		spin_unlock_irq(&mac->lock);
+
+		set_rts_cts(mac, bss_conf->use_short_preamble);
 	}
 }
 
@@ -1138,12 +1312,14 @@
 	hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &mac->band;
 
 	hw->flags = IEEE80211_HW_RX_INCLUDES_FCS |
-		    IEEE80211_HW_SIGNAL_UNSPEC;
+		    IEEE80211_HW_SIGNAL_UNSPEC |
+		    IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING;
 
 	hw->wiphy->interface_modes =
 		BIT(NL80211_IFTYPE_MESH_POINT) |
 		BIT(NL80211_IFTYPE_STATION) |
-		BIT(NL80211_IFTYPE_ADHOC);
+		BIT(NL80211_IFTYPE_ADHOC) |
+		BIT(NL80211_IFTYPE_AP);
 
 	hw->max_signal = 100;
 	hw->queues = 1;
@@ -1160,15 +1336,82 @@
 
 	zd_chip_init(&mac->chip, hw, intf);
 	housekeeping_init(mac);
-	INIT_WORK(&mac->set_multicast_hash_work, set_multicast_hash_handler);
-	INIT_WORK(&mac->set_rts_cts_work, set_rts_cts_work);
-	INIT_WORK(&mac->set_rx_filter_work, set_rx_filter_handler);
+	beacon_init(mac);
 	INIT_WORK(&mac->process_intr, zd_process_intr);
 
 	SET_IEEE80211_DEV(hw, &intf->dev);
 	return hw;
 }
 
+#define BEACON_WATCHDOG_DELAY round_jiffies_relative(HZ)
+
+static void beacon_watchdog_handler(struct work_struct *work)
+{
+	struct zd_mac *mac =
+		container_of(work, struct zd_mac, beacon.watchdog_work.work);
+	struct sk_buff *beacon;
+	unsigned long timeout;
+	int interval, period;
+
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		goto rearm;
+	if (mac->type != NL80211_IFTYPE_AP || !mac->vif)
+		goto rearm;
+
+	spin_lock_irq(&mac->lock);
+	interval = mac->beacon.interval;
+	period = mac->beacon.period;
+	timeout = mac->beacon.last_update + msecs_to_jiffies(interval) + HZ;
+	spin_unlock_irq(&mac->lock);
+
+	if (interval > 0 && time_is_before_jiffies(timeout)) {
+		dev_dbg_f(zd_mac_dev(mac), "beacon interrupt stalled, "
+					   "restarting. "
+					   "(interval: %d, dtim: %d)\n",
+					   interval, period);
+
+		zd_chip_disable_hwint(&mac->chip);
+
+		beacon = ieee80211_beacon_get(mac->hw, mac->vif);
+		if (beacon) {
+			zd_mac_config_beacon(mac->hw, beacon);
+			kfree_skb(beacon);
+		}
+
+		zd_set_beacon_interval(&mac->chip, interval, period, mac->type);
+
+		zd_chip_enable_hwint(&mac->chip);
+
+		spin_lock_irq(&mac->lock);
+		mac->beacon.last_update = jiffies;
+		spin_unlock_irq(&mac->lock);
+	}
+
+rearm:
+	queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
+			   BEACON_WATCHDOG_DELAY);
+}
+
+static void beacon_init(struct zd_mac *mac)
+{
+	INIT_DELAYED_WORK(&mac->beacon.watchdog_work, beacon_watchdog_handler);
+}
+
+static void beacon_enable(struct zd_mac *mac)
+{
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+
+	mac->beacon.last_update = jiffies;
+	queue_delayed_work(zd_workqueue, &mac->beacon.watchdog_work,
+			   BEACON_WATCHDOG_DELAY);
+}
+
+static void beacon_disable(struct zd_mac *mac)
+{
+	dev_dbg_f(zd_mac_dev(mac), "\n");
+	cancel_delayed_work_sync(&mac->beacon.watchdog_work);
+}
+
 #define LINK_LED_WORK_DELAY HZ
 
 static void link_led_handler(struct work_struct *work)
@@ -1179,6 +1422,9 @@
 	int is_associated;
 	int r;
 
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		goto requeue;
+
 	spin_lock_irq(&mac->lock);
 	is_associated = mac->associated;
 	spin_unlock_irq(&mac->lock);
@@ -1188,6 +1434,7 @@
 	if (r)
 		dev_dbg_f(zd_mac_dev(mac), "zd_chip_control_leds error %d\n", r);
 
+requeue:
 	queue_delayed_work(zd_workqueue, &mac->housekeeping.link_led_work,
 		           LINK_LED_WORK_DELAY);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_mac.h linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_mac.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_mac.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_mac.h	2011-05-19 00:06:34.000000000 -0400
@@ -163,6 +163,17 @@
 	struct delayed_work link_led_work;
 };
 
+struct beacon {
+	struct delayed_work watchdog_work;
+	unsigned long last_update;
+	u16 interval;
+	u8 period;
+};
+
+enum zd_device_flags {
+	ZD_DEVICE_RUNNING,
+};
+
 #define ZD_MAC_STATS_BUFFER_SIZE 16
 
 #define ZD_MAC_MAX_ACK_WAITERS 50
@@ -172,17 +183,19 @@
 	spinlock_t lock;
 	spinlock_t intr_lock;
 	struct ieee80211_hw *hw;
+	struct ieee80211_vif *vif;
 	struct housekeeping housekeeping;
-	struct work_struct set_multicast_hash_work;
+	struct beacon beacon;
 	struct work_struct set_rts_cts_work;
-	struct work_struct set_rx_filter_work;
 	struct work_struct process_intr;
 	struct zd_mc_hash multicast_hash;
 	u8 intr_buffer[USB_MAX_EP_INT_BUFFER];
 	u8 regdomain;
 	u8 default_regdomain;
+	u8 channel;
 	int type;
 	int associated;
+	unsigned long flags;
 	struct sk_buff_head ack_wait_queue;
 	struct ieee80211_channel channels[14];
 	struct ieee80211_rate rates[12];
@@ -191,9 +204,6 @@
 	/* Short preamble (used for RTS/CTS) */
 	unsigned int short_preamble:1;
 
-	/* flags to indicate update in progress */
-	unsigned int updating_rts_rate:1;
-
 	/* whether to pass frames with CRC errors to stack */
 	unsigned int pass_failed_fcs:1;
 
@@ -304,6 +314,10 @@
 void zd_mac_tx_failed(struct urb *urb);
 void zd_mac_tx_to_dev(struct sk_buff *skb, int error);
 
+int zd_op_start(struct ieee80211_hw *hw);
+void zd_op_stop(struct ieee80211_hw *hw);
+int zd_restore_settings(struct zd_mac *mac);
+
 #ifdef DEBUG
 void zd_dump_rx_status(const struct rx_status *status);
 #else
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_rf_rf2959.c	2011-05-19 00:06:34.000000000 -0400
@@ -169,7 +169,7 @@
 		{ CR85,  0x00 }, { CR86,  0x10 }, { CR87,  0x2A },
 		{ CR88,  0x10 }, { CR89,  0x24 }, { CR90,  0x18 },
 		/* { CR91,  0x18 }, */
-		/* should solve continous CTS frame problems */
+		/* should solve continuous CTS frame problems */
 		{ CR91,  0x00 },
 		{ CR92,  0x0a }, { CR93,  0x00 }, { CR94,  0x01 },
 		{ CR95,  0x00 }, { CR96,  0x40 }, { CR97,  0x37 },
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_rf_uw2453.c	2011-05-19 00:06:34.000000000 -0400
@@ -353,7 +353,7 @@
 	};
 
 	static const u32 rv[] = {
-		UW2453_REGWRITE(4, 0x2b),    /* configure reciever gain */
+		UW2453_REGWRITE(4, 0x2b),    /* configure receiver gain */
 		UW2453_REGWRITE(5, 0x19e4f), /* configure transmitter gain */
 		UW2453_REGWRITE(6, 0xf81ad), /* enable RX/TX filter tuning */
 		UW2453_REGWRITE(7, 0x3fffe), /* disable TX gain in test mode */
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_usb.c linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_usb.c
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_usb.c	2012-03-24 01:15:47.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_usb.c	2012-03-24 03:35:07.000000000 -0400
@@ -60,6 +60,7 @@
 	{ USB_DEVICE(0x157e, 0x300a), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x157e, 0x300b), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x157e, 0x3204), .driver_info = DEVICE_ZD1211 },
+	{ USB_DEVICE(0x157e, 0x3207), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x1740, 0x2000), .driver_info = DEVICE_ZD1211 },
 	{ USB_DEVICE(0x6891, 0xa727), .driver_info = DEVICE_ZD1211 },
 	/* ZD1211B */
@@ -372,8 +373,10 @@
 	int_num = le16_to_cpu(*(__le16 *)(urb->transfer_buffer+2));
 	if (int_num == CR_INTERRUPT) {
 		struct zd_mac *mac = zd_hw_mac(zd_usb_to_hw(urb->context));
+		spin_lock(&mac->lock);
 		memcpy(&mac->intr_buffer, urb->transfer_buffer,
 				USB_MAX_EP_INT_BUFFER);
+		spin_unlock(&mac->lock);
 		schedule_work(&mac->process_intr);
 	} else if (intr->read_regs_enabled) {
 		intr->read_regs.length = len = urb->actual_length;
@@ -404,8 +407,10 @@
 	case -ENOENT:
 	case -ECONNRESET:
 	case -EPIPE:
-		goto kfree;
+		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
+		return;
 	default:
+		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
 		goto resubmit;
 	}
 
@@ -436,12 +441,11 @@
 resubmit:
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r) {
-		dev_dbg_f(urb_dev(urb), "resubmit urb %p\n", urb);
-		goto kfree;
+		dev_dbg_f(urb_dev(urb), "error: resubmit urb %p err code %d\n",
+			  urb, r);
+		/* TODO: add worker to reset intr->urb */
 	}
 	return;
-kfree:
-	kfree(urb->transfer_buffer);
 }
 
 static inline int int_urb_interval(struct usb_device *udev)
@@ -472,9 +476,8 @@
 int zd_usb_enable_int(struct zd_usb *usb)
 {
 	int r;
-	struct usb_device *udev;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct zd_usb_interrupt *intr = &usb->intr;
-	void *transfer_buffer = NULL;
 	struct urb *urb;
 
 	dev_dbg_f(zd_usb_dev(usb), "\n");
@@ -495,20 +498,21 @@
 	intr->urb = urb;
 	spin_unlock_irq(&intr->lock);
 
-	/* TODO: make it a DMA buffer */
 	r = -ENOMEM;
-	transfer_buffer = kmalloc(USB_MAX_EP_INT_BUFFER, GFP_KERNEL);
-	if (!transfer_buffer) {
+	intr->buffer = usb_alloc_coherent(udev, USB_MAX_EP_INT_BUFFER,
+					  GFP_KERNEL, &intr->buffer_dma);
+	if (!intr->buffer) {
 		dev_dbg_f(zd_usb_dev(usb),
 			"couldn't allocate transfer_buffer\n");
 		goto error_set_urb_null;
 	}
 
-	udev = zd_usb_to_usbdev(usb);
 	usb_fill_int_urb(urb, udev, usb_rcvintpipe(udev, EP_INT_IN),
-			 transfer_buffer, USB_MAX_EP_INT_BUFFER,
+			 intr->buffer, USB_MAX_EP_INT_BUFFER,
 			 int_urb_complete, usb,
 			 intr->interval);
+	urb->transfer_dma = intr->buffer_dma;
+	urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
 
 	dev_dbg_f(zd_usb_dev(usb), "submit urb %p\n", intr->urb);
 	r = usb_submit_urb(urb, GFP_KERNEL);
@@ -520,7 +524,8 @@
 
 	return 0;
 error:
-	kfree(transfer_buffer);
+	usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
+			  intr->buffer, intr->buffer_dma);
 error_set_urb_null:
 	spin_lock_irq(&intr->lock);
 	intr->urb = NULL;
@@ -534,8 +539,11 @@
 void zd_usb_disable_int(struct zd_usb *usb)
 {
 	unsigned long flags;
+	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct zd_usb_interrupt *intr = &usb->intr;
 	struct urb *urb;
+	void *buffer;
+	dma_addr_t buffer_dma;
 
 	spin_lock_irqsave(&intr->lock, flags);
 	urb = intr->urb;
@@ -544,11 +552,18 @@
 		return;
 	}
 	intr->urb = NULL;
+	buffer = intr->buffer;
+	buffer_dma = intr->buffer_dma;
+	intr->buffer = NULL;
 	spin_unlock_irqrestore(&intr->lock, flags);
 
 	usb_kill_urb(urb);
 	dev_dbg_f(zd_usb_dev(usb), "urb %p killed\n", urb);
 	usb_free_urb(urb);
+
+	if (buffer)
+		usb_free_coherent(udev, USB_MAX_EP_INT_BUFFER,
+				  buffer, buffer_dma);
 }
 
 static void handle_rx_packet(struct zd_usb *usb, const u8 *buffer,
@@ -596,6 +611,7 @@
 
 static void rx_urb_complete(struct urb *urb)
 {
+	int r;
 	struct zd_usb *usb;
 	struct zd_usb_rx *rx;
 	const u8 *buffer;
@@ -610,6 +626,7 @@
 	case -ENOENT:
 	case -ECONNRESET:
 	case -EPIPE:
+		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
 		return;
 	default:
 		dev_dbg_f(urb_dev(urb), "urb %p error %d\n", urb, urb->status);
@@ -621,6 +638,8 @@
 	usb = urb->context;
 	rx = &usb->rx;
 
+	tasklet_schedule(&rx->reset_timer_tasklet);
+
 	if (length%rx->usb_packet_size > rx->usb_packet_size-4) {
 		/* If there is an old first fragment, we don't care. */
 		dev_dbg_f(urb_dev(urb), "*** first fragment ***\n");
@@ -649,7 +668,9 @@
 	}
 
 resubmit:
-	usb_submit_urb(urb, GFP_ATOMIC);
+	r = usb_submit_urb(urb, GFP_ATOMIC);
+	if (r)
+		dev_dbg_f(urb_dev(urb), "urb %p resubmit error %d\n", urb, r);
 }
 
 static struct urb *alloc_rx_urb(struct zd_usb *usb)
@@ -685,7 +706,7 @@
 	usb_free_urb(urb);
 }
 
-int zd_usb_enable_rx(struct zd_usb *usb)
+static int __zd_usb_enable_rx(struct zd_usb *usb)
 {
 	int i, r;
 	struct zd_usb_rx *rx = &usb->rx;
@@ -737,7 +758,21 @@
 	return r;
 }
 
-void zd_usb_disable_rx(struct zd_usb *usb)
+int zd_usb_enable_rx(struct zd_usb *usb)
+{
+	int r;
+	struct zd_usb_rx *rx = &usb->rx;
+
+	mutex_lock(&rx->setup_mutex);
+	r = __zd_usb_enable_rx(usb);
+	mutex_unlock(&rx->setup_mutex);
+
+	zd_usb_reset_rx_idle_timer(usb);
+
+	return r;
+}
+
+static void __zd_usb_disable_rx(struct zd_usb *usb)
 {
 	int i;
 	unsigned long flags;
@@ -764,6 +799,41 @@
 	spin_unlock_irqrestore(&rx->lock, flags);
 }
 
+void zd_usb_disable_rx(struct zd_usb *usb)
+{
+	struct zd_usb_rx *rx = &usb->rx;
+
+	mutex_lock(&rx->setup_mutex);
+	__zd_usb_disable_rx(usb);
+	mutex_unlock(&rx->setup_mutex);
+
+	tasklet_kill(&rx->reset_timer_tasklet);
+	cancel_delayed_work_sync(&rx->idle_work);
+}
+
+static void zd_usb_reset_rx(struct zd_usb *usb)
+{
+	bool do_reset;
+	struct zd_usb_rx *rx = &usb->rx;
+	unsigned long flags;
+
+	mutex_lock(&rx->setup_mutex);
+
+	spin_lock_irqsave(&rx->lock, flags);
+	do_reset = rx->urbs != NULL;
+	spin_unlock_irqrestore(&rx->lock, flags);
+
+	if (do_reset) {
+		__zd_usb_disable_rx(usb);
+		__zd_usb_enable_rx(usb);
+	}
+
+	mutex_unlock(&rx->setup_mutex);
+
+	if (do_reset)
+		zd_usb_reset_rx_idle_timer(usb);
+}
+
 /**
  * zd_usb_disable_tx - disable transmission
  * @usb: the zd1211rw-private USB structure
@@ -774,19 +844,21 @@
 {
 	struct zd_usb_tx *tx = &usb->tx;
 	unsigned long flags;
-	struct list_head *pos, *n;
+
+	atomic_set(&tx->enabled, 0);
+
+	/* kill all submitted tx-urbs */
+	usb_kill_anchored_urbs(&tx->submitted);
 
 	spin_lock_irqsave(&tx->lock, flags);
-	list_for_each_safe(pos, n, &tx->free_urb_list) {
-		list_del(pos);
-		usb_free_urb(list_entry(pos, struct urb, urb_list));
-	}
-	tx->enabled = 0;
+	WARN_ON(!skb_queue_empty(&tx->submitted_skbs));
+	WARN_ON(tx->submitted_urbs != 0);
 	tx->submitted_urbs = 0;
+	spin_unlock_irqrestore(&tx->lock, flags);
+
 	/* The stopped state is ignored, relying on ieee80211_wake_queues()
 	 * in a potentionally following zd_usb_enable_tx().
 	 */
-	spin_unlock_irqrestore(&tx->lock, flags);
 }
 
 /**
@@ -802,63 +874,13 @@
 	struct zd_usb_tx *tx = &usb->tx;
 
 	spin_lock_irqsave(&tx->lock, flags);
-	tx->enabled = 1;
+	atomic_set(&tx->enabled, 1);
 	tx->submitted_urbs = 0;
 	ieee80211_wake_queues(zd_usb_to_hw(usb));
 	tx->stopped = 0;
 	spin_unlock_irqrestore(&tx->lock, flags);
 }
 
-/**
- * alloc_tx_urb - provides an tx URB
- * @usb: a &struct zd_usb pointer
- *
- * Allocates a new URB. If possible takes the urb from the free list in
- * usb->tx.
- */
-static struct urb *alloc_tx_urb(struct zd_usb *usb)
-{
-	struct zd_usb_tx *tx = &usb->tx;
-	unsigned long flags;
-	struct list_head *entry;
-	struct urb *urb;
-
-	spin_lock_irqsave(&tx->lock, flags);
-	if (list_empty(&tx->free_urb_list)) {
-		urb = usb_alloc_urb(0, GFP_ATOMIC);
-		goto out;
-	}
-	entry = tx->free_urb_list.next;
-	list_del(entry);
-	urb = list_entry(entry, struct urb, urb_list);
-out:
-	spin_unlock_irqrestore(&tx->lock, flags);
-	return urb;
-}
-
-/**
- * free_tx_urb - frees a used tx URB
- * @usb: a &struct zd_usb pointer
- * @urb: URB to be freed
- *
- * Frees the transmission URB, which means to put it on the free URB
- * list.
- */
-static void free_tx_urb(struct zd_usb *usb, struct urb *urb)
-{
-	struct zd_usb_tx *tx = &usb->tx;
-	unsigned long flags;
-
-	spin_lock_irqsave(&tx->lock, flags);
-	if (!tx->enabled) {
-		usb_free_urb(urb);
-		goto out;
-	}
-	list_add(&urb->urb_list, &tx->free_urb_list);
-out:
-	spin_unlock_irqrestore(&tx->lock, flags);
-}
-
 static void tx_dec_submitted_urbs(struct zd_usb *usb)
 {
 	struct zd_usb_tx *tx = &usb->tx;
@@ -900,6 +922,16 @@
 	struct sk_buff *skb;
 	struct ieee80211_tx_info *info;
 	struct zd_usb *usb;
+	struct zd_usb_tx *tx;
+
+	skb = (struct sk_buff *)urb->context;
+	info = IEEE80211_SKB_CB(skb);
+	/*
+	 * grab 'usb' pointer before handing off the skb (since
+	 * it might be freed by zd_mac_tx_to_dev or mac80211)
+	 */
+	usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
+	tx = &usb->tx;
 
 	switch (urb->status) {
 	case 0:
@@ -917,20 +949,16 @@
 		goto resubmit;
 	}
 free_urb:
-	skb = (struct sk_buff *)urb->context;
-	/*
-	 * grab 'usb' pointer before handing off the skb (since
-	 * it might be freed by zd_mac_tx_to_dev or mac80211)
-	 */
-	info = IEEE80211_SKB_CB(skb);
-	usb = &zd_hw_mac(info->rate_driver_data[0])->chip.usb;
+	skb_unlink(skb, &usb->tx.submitted_skbs);
 	zd_mac_tx_to_dev(skb, urb->status);
-	free_tx_urb(usb, urb);
+	usb_free_urb(urb);
 	tx_dec_submitted_urbs(usb);
 	return;
 resubmit:
+	usb_anchor_urb(urb, &tx->submitted);
 	r = usb_submit_urb(urb, GFP_ATOMIC);
 	if (r) {
+		usb_unanchor_urb(urb);
 		dev_dbg_f(urb_dev(urb), "error resubmit urb %p %d\n", urb, r);
 		goto free_urb;
 	}
@@ -951,10 +979,17 @@
 int zd_usb_tx(struct zd_usb *usb, struct sk_buff *skb)
 {
 	int r;
+	struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
 	struct usb_device *udev = zd_usb_to_usbdev(usb);
 	struct urb *urb;
+	struct zd_usb_tx *tx = &usb->tx;
 
-	urb = alloc_tx_urb(usb);
+	if (!atomic_read(&tx->enabled)) {
+		r = -ENOENT;
+		goto out;
+	}
+
+	urb = usb_alloc_urb(0, GFP_ATOMIC);
 	if (!urb) {
 		r = -ENOMEM;
 		goto out;
@@ -963,17 +998,125 @@
 	usb_fill_bulk_urb(urb, udev, usb_sndbulkpipe(udev, EP_DATA_OUT),
 		          skb->data, skb->len, tx_urb_complete, skb);
 
+	info->rate_driver_data[1] = (void *)jiffies;
+	skb_queue_tail(&tx->submitted_skbs, skb);
+	usb_anchor_urb(urb, &tx->submitted);
+
 	r = usb_submit_urb(urb, GFP_ATOMIC);
-	if (r)
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb), "error submit urb %p %d\n", urb, r);
+		usb_unanchor_urb(urb);
+		skb_unlink(skb, &tx->submitted_skbs);
 		goto error;
+	}
 	tx_inc_submitted_urbs(usb);
 	return 0;
 error:
-	free_tx_urb(usb, urb);
+	usb_free_urb(urb);
 out:
 	return r;
 }
 
+static bool zd_tx_timeout(struct zd_usb *usb)
+{
+	struct zd_usb_tx *tx = &usb->tx;
+	struct sk_buff_head *q = &tx->submitted_skbs;
+	struct sk_buff *skb, *skbnext;
+	struct ieee80211_tx_info *info;
+	unsigned long flags, trans_start;
+	bool have_timedout = false;
+
+	spin_lock_irqsave(&q->lock, flags);
+	skb_queue_walk_safe(q, skb, skbnext) {
+		info = IEEE80211_SKB_CB(skb);
+		trans_start = (unsigned long)info->rate_driver_data[1];
+
+		if (time_is_before_jiffies(trans_start + ZD_TX_TIMEOUT)) {
+			have_timedout = true;
+			break;
+		}
+	}
+	spin_unlock_irqrestore(&q->lock, flags);
+
+	return have_timedout;
+}
+
+static void zd_tx_watchdog_handler(struct work_struct *work)
+{
+	struct zd_usb *usb =
+		container_of(work, struct zd_usb, tx.watchdog_work.work);
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (!atomic_read(&tx->enabled) || !tx->watchdog_enabled)
+		goto out;
+	if (!zd_tx_timeout(usb))
+		goto out;
+
+	/* TX halted, try reset */
+	dev_warn(zd_usb_dev(usb), "TX-stall detected, reseting device...");
+
+	usb_queue_reset_device(usb->intf);
+
+	/* reset will stop this worker, don't rearm */
+	return;
+out:
+	queue_delayed_work(zd_workqueue, &tx->watchdog_work,
+			   ZD_TX_WATCHDOG_INTERVAL);
+}
+
+void zd_tx_watchdog_enable(struct zd_usb *usb)
+{
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (!tx->watchdog_enabled) {
+		dev_dbg_f(zd_usb_dev(usb), "\n");
+		queue_delayed_work(zd_workqueue, &tx->watchdog_work,
+				   ZD_TX_WATCHDOG_INTERVAL);
+		tx->watchdog_enabled = 1;
+	}
+}
+
+void zd_tx_watchdog_disable(struct zd_usb *usb)
+{
+	struct zd_usb_tx *tx = &usb->tx;
+
+	if (tx->watchdog_enabled) {
+		dev_dbg_f(zd_usb_dev(usb), "\n");
+		tx->watchdog_enabled = 0;
+		cancel_delayed_work_sync(&tx->watchdog_work);
+	}
+}
+
+static void zd_rx_idle_timer_handler(struct work_struct *work)
+{
+	struct zd_usb *usb =
+		container_of(work, struct zd_usb, rx.idle_work.work);
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+
+	if (!test_bit(ZD_DEVICE_RUNNING, &mac->flags))
+		return;
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	/* 30 seconds since last rx, reset rx */
+	zd_usb_reset_rx(usb);
+}
+
+static void zd_usb_reset_rx_idle_timer_tasklet(unsigned long param)
+{
+	struct zd_usb *usb = (struct zd_usb *)param;
+
+	zd_usb_reset_rx_idle_timer(usb);
+}
+
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb)
+{
+	struct zd_usb_rx *rx = &usb->rx;
+
+	cancel_delayed_work(&rx->idle_work);
+	queue_delayed_work(zd_workqueue, &rx->idle_work, ZD_RX_IDLE_INTERVAL);
+}
+
 static inline void init_usb_interrupt(struct zd_usb *usb)
 {
 	struct zd_usb_interrupt *intr = &usb->intr;
@@ -987,23 +1130,32 @@
 static inline void init_usb_rx(struct zd_usb *usb)
 {
 	struct zd_usb_rx *rx = &usb->rx;
+
 	spin_lock_init(&rx->lock);
+	mutex_init(&rx->setup_mutex);
 	if (interface_to_usbdev(usb->intf)->speed == USB_SPEED_HIGH) {
 		rx->usb_packet_size = 512;
 	} else {
 		rx->usb_packet_size = 64;
 	}
 	ZD_ASSERT(rx->fragment_length == 0);
+	INIT_DELAYED_WORK(&rx->idle_work, zd_rx_idle_timer_handler);
+	rx->reset_timer_tasklet.func = zd_usb_reset_rx_idle_timer_tasklet;
+	rx->reset_timer_tasklet.data = (unsigned long)usb;
 }
 
 static inline void init_usb_tx(struct zd_usb *usb)
 {
 	struct zd_usb_tx *tx = &usb->tx;
+
 	spin_lock_init(&tx->lock);
-	tx->enabled = 0;
+	atomic_set(&tx->enabled, 0);
 	tx->stopped = 0;
-	INIT_LIST_HEAD(&tx->free_urb_list);
+	skb_queue_head_init(&tx->submitted_skbs);
+	init_usb_anchor(&tx->submitted);
 	tx->submitted_urbs = 0;
+	tx->watchdog_enabled = 0;
+	INIT_DELAYED_WORK(&tx->watchdog_work, zd_tx_watchdog_handler);
 }
 
 void zd_usb_init(struct zd_usb *usb, struct ieee80211_hw *hw,
@@ -1012,6 +1164,7 @@
 	memset(usb, 0, sizeof(*usb));
 	usb->intf = usb_get_intf(intf);
 	usb_set_intfdata(usb->intf, hw);
+	init_usb_anchor(&usb->submitted_cmds);
 	init_usb_interrupt(usb);
 	init_usb_tx(usb);
 	init_usb_rx(usb);
@@ -1235,6 +1388,7 @@
 	ieee80211_unregister_hw(hw);
 
 	/* Just in case something has gone wrong! */
+	zd_usb_disable_tx(usb);
 	zd_usb_disable_rx(usb);
 	zd_usb_disable_int(usb);
 
@@ -1250,11 +1404,92 @@
 	dev_dbg(&intf->dev, "disconnected\n");
 }
 
+static void zd_usb_resume(struct zd_usb *usb)
+{
+	struct zd_mac *mac = zd_usb_to_mac(usb);
+	int r;
+
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	r = zd_op_start(zd_usb_to_hw(usb));
+	if (r < 0) {
+		dev_warn(zd_usb_dev(usb), "Device resume failed "
+			 "with error code %d. Retrying...\n", r);
+		if (usb->was_running)
+			set_bit(ZD_DEVICE_RUNNING, &mac->flags);
+		usb_queue_reset_device(usb->intf);
+		return;
+	}
+
+	if (mac->type != NL80211_IFTYPE_UNSPECIFIED) {
+		r = zd_restore_settings(mac);
+		if (r < 0) {
+			dev_dbg(zd_usb_dev(usb),
+				"failed to restore settings, %d\n", r);
+			return;
+		}
+	}
+}
+
+static void zd_usb_stop(struct zd_usb *usb)
+{
+	dev_dbg_f(zd_usb_dev(usb), "\n");
+
+	zd_op_stop(zd_usb_to_hw(usb));
+
+	zd_usb_disable_tx(usb);
+	zd_usb_disable_rx(usb);
+	zd_usb_disable_int(usb);
+
+	usb->initialized = 0;
+}
+
+static int pre_reset(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct zd_mac *mac;
+	struct zd_usb *usb;
+
+	if (!hw || intf->condition != USB_INTERFACE_BOUND)
+		return 0;
+
+	mac = zd_hw_mac(hw);
+	usb = &mac->chip.usb;
+
+	usb->was_running = test_bit(ZD_DEVICE_RUNNING, &mac->flags);
+
+	zd_usb_stop(usb);
+
+	mutex_lock(&mac->chip.mutex);
+	return 0;
+}
+
+static int post_reset(struct usb_interface *intf)
+{
+	struct ieee80211_hw *hw = usb_get_intfdata(intf);
+	struct zd_mac *mac;
+	struct zd_usb *usb;
+
+	if (!hw || intf->condition != USB_INTERFACE_BOUND)
+		return 0;
+
+	mac = zd_hw_mac(hw);
+	usb = &mac->chip.usb;
+
+	mutex_unlock(&mac->chip.mutex);
+
+	if (usb->was_running)
+		zd_usb_resume(usb);
+	return 0;
+}
+
 static struct usb_driver driver = {
 	.name		= KBUILD_MODNAME,
 	.id_table	= usb_ids,
 	.probe		= probe,
 	.disconnect	= disconnect,
+	.pre_reset	= pre_reset,
+	.post_reset	= post_reset,
 };
 
 struct workqueue_struct *zd_workqueue;
@@ -1388,30 +1623,35 @@
 		return -EWOULDBLOCK;
 	}
 	if (!usb_int_enabled(usb)) {
-		 dev_dbg_f(zd_usb_dev(usb),
+		dev_dbg_f(zd_usb_dev(usb),
 			  "error: usb interrupt not enabled\n");
 		return -EWOULDBLOCK;
 	}
 
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	BUILD_BUG_ON(sizeof(struct usb_req_read_regs) + USB_MAX_IOREAD16_COUNT *
+		     sizeof(__le16) > sizeof(usb->req_buf));
+	BUG_ON(sizeof(struct usb_req_read_regs) + count * sizeof(__le16) >
+	       sizeof(usb->req_buf));
+
 	req_len = sizeof(struct usb_req_read_regs) + count * sizeof(__le16);
-	req = kmalloc(req_len, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
+	req = (void *)usb->req_buf;
+
 	req->id = cpu_to_le16(USB_REQ_READ_REGS);
 	for (i = 0; i < count; i++)
 		req->addr[i] = cpu_to_le16((u16)addresses[i]);
 
 	udev = zd_usb_to_usbdev(usb);
 	prepare_read_regs_int(usb);
-	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-		         req, req_len, &actual_req_len, 1000 /* ms */);
+	r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
+			      req, req_len, &actual_req_len, 50 /* ms */);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg(). Error number %d\n", r);
+			"error in usb_interrupt_msg(). Error number %d\n", r);
 		goto error;
 	}
 	if (req_len != actual_req_len) {
-		dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()\n"
+		dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()\n"
 			" req_len %d != actual_req_len %d\n",
 			req_len, actual_req_len);
 		r = -EIO;
@@ -1419,7 +1659,7 @@
 	}
 
 	timeout = wait_for_completion_timeout(&usb->intr.read_regs.completion,
-	                                      msecs_to_jiffies(1000));
+					      msecs_to_jiffies(50));
 	if (!timeout) {
 		disable_read_regs_int(usb);
 		dev_dbg_f(zd_usb_dev(usb), "read timed out\n");
@@ -1429,17 +1669,110 @@
 
 	r = get_results(usb, values, req, count);
 error:
-	kfree(req);
 	return r;
 }
 
-int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
-	              unsigned int count)
+static void iowrite16v_urb_complete(struct urb *urb)
+{
+	struct zd_usb *usb = urb->context;
+
+	if (urb->status && !usb->cmd_error)
+		usb->cmd_error = urb->status;
+
+	if (!usb->cmd_error &&
+			urb->actual_length != urb->transfer_buffer_length)
+		usb->cmd_error = -EIO;
+}
+
+static int zd_submit_waiting_urb(struct zd_usb *usb, bool last)
+{
+	int r = 0;
+	struct urb *urb = usb->urb_async_waiting;
+
+	if (!urb)
+		return 0;
+
+	usb->urb_async_waiting = NULL;
+
+	if (!last)
+		urb->transfer_flags |= URB_NO_INTERRUPT;
+
+	usb_anchor_urb(urb, &usb->submitted_cmds);
+	r = usb_submit_urb(urb, GFP_KERNEL);
+	if (r) {
+		usb_unanchor_urb(urb);
+		dev_dbg_f(zd_usb_dev(usb),
+			"error in usb_submit_urb(). Error number %d\n", r);
+		goto error;
+	}
+
+	/* fall-through with r == 0 */
+error:
+	usb_free_urb(urb);
+	return r;
+}
+
+void zd_usb_iowrite16v_async_start(struct zd_usb *usb)
+{
+	ZD_ASSERT(usb_anchor_empty(&usb->submitted_cmds));
+	ZD_ASSERT(usb->urb_async_waiting == NULL);
+	ZD_ASSERT(!usb->in_async);
+
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+
+	usb->in_async = 1;
+	usb->cmd_error = 0;
+	usb->urb_async_waiting = NULL;
+}
+
+int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout)
+{
+	int r;
+
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	ZD_ASSERT(usb->in_async);
+
+	/* Submit last iowrite16v URB */
+	r = zd_submit_waiting_urb(usb, true);
+	if (r) {
+		dev_dbg_f(zd_usb_dev(usb),
+			"error in zd_submit_waiting_usb(). "
+			"Error number %d\n", r);
+
+		usb_kill_anchored_urbs(&usb->submitted_cmds);
+		goto error;
+	}
+
+	if (timeout)
+		timeout = usb_wait_anchor_empty_timeout(&usb->submitted_cmds,
+							timeout);
+	if (!timeout) {
+		usb_kill_anchored_urbs(&usb->submitted_cmds);
+		if (usb->cmd_error == -ENOENT) {
+			dev_dbg_f(zd_usb_dev(usb), "timed out");
+			r = -ETIMEDOUT;
+			goto error;
+		}
+	}
+
+	r = usb->cmd_error;
+error:
+	usb->in_async = 0;
+	return r;
+}
+
+int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+			    unsigned int count)
 {
 	int r;
 	struct usb_device *udev;
 	struct usb_req_write_regs *req = NULL;
-	int i, req_len, actual_req_len;
+	int i, req_len;
+	struct urb *urb;
+	struct usb_host_endpoint *ep;
+
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	ZD_ASSERT(usb->in_async);
 
 	if (count == 0)
 		return 0;
@@ -1455,11 +1788,23 @@
 		return -EWOULDBLOCK;
 	}
 
+	udev = zd_usb_to_usbdev(usb);
+
+	ep = usb_pipe_endpoint(udev, usb_sndintpipe(udev, EP_REGS_OUT));
+	if (!ep)
+		return -ENOENT;
+
+	urb = usb_alloc_urb(0, GFP_KERNEL);
+	if (!urb)
+		return -ENOMEM;
+
 	req_len = sizeof(struct usb_req_write_regs) +
 		  count * sizeof(struct reg_data);
 	req = kmalloc(req_len, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
+	if (!req) {
+		r = -ENOMEM;
+		goto error;
+	}
 
 	req->id = cpu_to_le16(USB_REQ_WRITE_REGS);
 	for (i = 0; i < count; i++) {
@@ -1468,29 +1813,44 @@
 		rw->value = cpu_to_le16(ioreqs[i].value);
 	}
 
-	udev = zd_usb_to_usbdev(usb);
-	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-		         req, req_len, &actual_req_len, 1000 /* ms */);
+	usb_fill_int_urb(urb, udev, usb_sndintpipe(udev, EP_REGS_OUT),
+			 req, req_len, iowrite16v_urb_complete, usb,
+			 ep->desc.bInterval);
+	urb->transfer_flags |= URB_FREE_BUFFER;
+
+	/* Submit previous URB */
+	r = zd_submit_waiting_urb(usb, false);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg(). Error number %d\n", r);
-		goto error;
-	}
-	if (req_len != actual_req_len) {
-		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg()"
-			" req_len %d != actual_req_len %d\n",
-			req_len, actual_req_len);
-		r = -EIO;
+			"error in zd_submit_waiting_usb(). "
+			"Error number %d\n", r);
 		goto error;
 	}
 
-	/* FALL-THROUGH with r == 0 */
+	/* Delay submit so that URB_NO_INTERRUPT flag can be set for all URBs
+	 * of currect batch except for very last.
+	 */
+	usb->urb_async_waiting = urb;
+	return 0;
 error:
-	kfree(req);
+	usb_free_urb(urb);
 	return r;
 }
 
+int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+			unsigned int count)
+{
+	int r;
+
+	zd_usb_iowrite16v_async_start(usb);
+	r = zd_usb_iowrite16v_async(usb, ioreqs, count);
+	if (r) {
+		zd_usb_iowrite16v_async_end(usb, 0);
+		return r;
+	}
+	return zd_usb_iowrite16v_async_end(usb, 50 /* ms */);
+}
+
 int zd_usb_rfwrite(struct zd_usb *usb, u32 value, u8 bits)
 {
 	int r;
@@ -1532,14 +1892,19 @@
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
 			"error %d: Couldn't read CR203\n", r);
-		goto out;
+		return r;
 	}
 	bit_value_template &= ~(RF_IF_LE|RF_CLK|RF_DATA);
 
+	ZD_ASSERT(mutex_is_locked(&zd_usb_to_chip(usb)->mutex));
+	BUILD_BUG_ON(sizeof(struct usb_req_rfwrite) +
+		     USB_MAX_RFWRITE_BIT_COUNT * sizeof(__le16) >
+		     sizeof(usb->req_buf));
+	BUG_ON(sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16) >
+	       sizeof(usb->req_buf));
+
 	req_len = sizeof(struct usb_req_rfwrite) + bits * sizeof(__le16);
-	req = kmalloc(req_len, GFP_KERNEL);
-	if (!req)
-		return -ENOMEM;
+	req = (void *)usb->req_buf;
 
 	req->id = cpu_to_le16(USB_REQ_WRITE_RF);
 	/* 1: 3683a, but not used in ZYDAS driver */
@@ -1554,15 +1919,15 @@
 	}
 
 	udev = zd_usb_to_usbdev(usb);
-	r = usb_bulk_msg(udev, usb_sndbulkpipe(udev, EP_REGS_OUT),
-		         req, req_len, &actual_req_len, 1000 /* ms */);
+	r = usb_interrupt_msg(udev, usb_sndintpipe(udev, EP_REGS_OUT),
+			      req, req_len, &actual_req_len, 50 /* ms */);
 	if (r) {
 		dev_dbg_f(zd_usb_dev(usb),
-			"error in usb_bulk_msg(). Error number %d\n", r);
+			"error in usb_interrupt_msg(). Error number %d\n", r);
 		goto out;
 	}
 	if (req_len != actual_req_len) {
-		dev_dbg_f(zd_usb_dev(usb), "error in usb_bulk_msg()"
+		dev_dbg_f(zd_usb_dev(usb), "error in usb_interrupt_msg()"
 			" req_len %d != actual_req_len %d\n",
 			req_len, actual_req_len);
 		r = -EIO;
@@ -1571,6 +1936,5 @@
 
 	/* FALL-THROUGH with r == 0 */
 out:
-	kfree(req);
 	return r;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_usb.h linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_usb.h
--- linux-libre-2.6.38-gnu/drivers/net/wireless/zd1211rw/zd_usb.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/wireless/zd1211rw/zd_usb.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,10 @@
 #define ZD_USB_TX_HIGH  5
 #define ZD_USB_TX_LOW   2
 
+#define ZD_TX_TIMEOUT		(HZ * 5)
+#define ZD_TX_WATCHDOG_INTERVAL	round_jiffies_relative(HZ)
+#define ZD_RX_IDLE_INTERVAL	round_jiffies_relative(30 * HZ)
+
 enum devicetype {
 	DEVICE_ZD1211  = 0,
 	DEVICE_ZD1211B = 1,
@@ -162,6 +166,8 @@
 	struct read_regs_int read_regs;
 	spinlock_t lock;
 	struct urb *urb;
+	void *buffer;
+	dma_addr_t buffer_dma;
 	int interval;
 	u8 read_regs_enabled:1;
 };
@@ -175,7 +181,10 @@
 
 struct zd_usb_rx {
 	spinlock_t lock;
-	u8 fragment[2*USB_MAX_RX_SIZE];
+	struct mutex setup_mutex;
+	struct delayed_work idle_work;
+	struct tasklet_struct reset_timer_tasklet;
+	u8 fragment[2 * USB_MAX_RX_SIZE];
 	unsigned int fragment_length;
 	unsigned int usb_packet_size;
 	struct urb **urbs;
@@ -184,19 +193,21 @@
 
 /**
  * struct zd_usb_tx - structure used for transmitting frames
+ * @enabled: atomic enabled flag, indicates whether tx is enabled
  * @lock: lock for transmission
- * @free_urb_list: list of free URBs, contains all the URBs, which can be used
+ * @submitted: anchor for URBs sent to device
  * @submitted_urbs: atomic integer that counts the URBs having sent to the
  *	device, which haven't been completed
- * @enabled: enabled flag, indicates whether tx is enabled
  * @stopped: indicates whether higher level tx queues are stopped
  */
 struct zd_usb_tx {
+	atomic_t enabled;
 	spinlock_t lock;
-	struct list_head free_urb_list;
+	struct delayed_work watchdog_work;
+	struct sk_buff_head submitted_skbs;
+	struct usb_anchor submitted;
 	int submitted_urbs;
-	int enabled;
-	int stopped;
+	u8 stopped:1, watchdog_enabled:1;
 };
 
 /* Contains the usb parts. The structure doesn't require a lock because intf
@@ -207,7 +218,11 @@
 	struct zd_usb_rx rx;
 	struct zd_usb_tx tx;
 	struct usb_interface *intf;
-	u8 is_zd1211b:1, initialized:1;
+	struct usb_anchor submitted_cmds;
+	struct urb *urb_async_waiting;
+	int cmd_error;
+	u8 req_buf[64]; /* zd_usb_iowrite16v needs 62 bytes */
+	u8 is_zd1211b:1, initialized:1, was_running:1, in_async:1;
 };
 
 #define zd_usb_dev(usb) (&usb->intf->dev)
@@ -234,12 +249,17 @@
 
 int zd_usb_scnprint_id(struct zd_usb *usb, char *buffer, size_t size);
 
+void zd_tx_watchdog_enable(struct zd_usb *usb);
+void zd_tx_watchdog_disable(struct zd_usb *usb);
+
 int zd_usb_enable_int(struct zd_usb *usb);
 void zd_usb_disable_int(struct zd_usb *usb);
 
 int zd_usb_enable_rx(struct zd_usb *usb);
 void zd_usb_disable_rx(struct zd_usb *usb);
 
+void zd_usb_reset_rx_idle_timer(struct zd_usb *usb);
+
 void zd_usb_enable_tx(struct zd_usb *usb);
 void zd_usb_disable_tx(struct zd_usb *usb);
 
@@ -254,6 +274,10 @@
 	return zd_usb_ioread16v(usb, value, (const zd_addr_t *)&addr, 1);
 }
 
+void zd_usb_iowrite16v_async_start(struct zd_usb *usb);
+int zd_usb_iowrite16v_async_end(struct zd_usb *usb, unsigned int timeout);
+int zd_usb_iowrite16v_async(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
+			    unsigned int count);
 int zd_usb_iowrite16v(struct zd_usb *usb, const struct zd_ioreq16 *ioreqs,
 	              unsigned int count);
 
diff -druN linux-libre-2.6.38-gnu/drivers/net/xen-netback/common.h linux-libre-2.6.39-gnu/drivers/net/xen-netback/common.h
--- linux-libre-2.6.38-gnu/drivers/net/xen-netback/common.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/xen-netback/common.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,161 @@
+/*
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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
+ * 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.
+ */
+
+#ifndef __XEN_NETBACK__COMMON_H__
+#define __XEN_NETBACK__COMMON_H__
+
+#define pr_fmt(fmt) KBUILD_MODNAME ":%s: " fmt, __func__
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/ip.h>
+#include <linux/in.h>
+#include <linux/io.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+
+#include <xen/interface/io/netif.h>
+#include <xen/interface/grant_table.h>
+#include <xen/grant_table.h>
+#include <xen/xenbus.h>
+
+struct xen_netbk;
+
+struct xenvif {
+	/* Unique identifier for this interface. */
+	domid_t          domid;
+	unsigned int     handle;
+
+	/* Reference to netback processing backend. */
+	struct xen_netbk *netbk;
+
+	u8               fe_dev_addr[6];
+
+	/* Physical parameters of the comms window. */
+	grant_handle_t   tx_shmem_handle;
+	grant_ref_t      tx_shmem_ref;
+	grant_handle_t   rx_shmem_handle;
+	grant_ref_t      rx_shmem_ref;
+	unsigned int     irq;
+
+	/* List of frontends to notify after a batch of frames sent. */
+	struct list_head notify_list;
+
+	/* The shared rings and indexes. */
+	struct xen_netif_tx_back_ring tx;
+	struct xen_netif_rx_back_ring rx;
+	struct vm_struct *tx_comms_area;
+	struct vm_struct *rx_comms_area;
+
+	/* Flags that must not be set in dev->features */
+	u32 features_disabled;
+
+	/* Frontend feature information. */
+	u8 can_sg:1;
+	u8 gso:1;
+	u8 gso_prefix:1;
+	u8 csum:1;
+
+	/* Internal feature information. */
+	u8 can_queue:1;	    /* can queue packets for receiver? */
+
+	/*
+	 * Allow xenvif_start_xmit() to peek ahead in the rx request
+	 * ring.  This is a prediction of what rx_req_cons will be
+	 * once all queued skbs are put on the ring.
+	 */
+	RING_IDX rx_req_cons_peek;
+
+	/* Transmit shaping: allow 'credit_bytes' every 'credit_usec'. */
+	unsigned long   credit_bytes;
+	unsigned long   credit_usec;
+	unsigned long   remaining_credit;
+	struct timer_list credit_timeout;
+
+	/* Statistics */
+	unsigned long rx_gso_checksum_fixup;
+
+	/* Miscellaneous private stuff. */
+	struct list_head schedule_list;
+	atomic_t         refcnt;
+	struct net_device *dev;
+
+	wait_queue_head_t waiting_to_free;
+};
+
+#define XEN_NETIF_TX_RING_SIZE __RING_SIZE((struct xen_netif_tx_sring *)0, PAGE_SIZE)
+#define XEN_NETIF_RX_RING_SIZE __RING_SIZE((struct xen_netif_rx_sring *)0, PAGE_SIZE)
+
+struct xenvif *xenvif_alloc(struct device *parent,
+			    domid_t domid,
+			    unsigned int handle);
+
+int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
+		   unsigned long rx_ring_ref, unsigned int evtchn);
+void xenvif_disconnect(struct xenvif *vif);
+
+void xenvif_get(struct xenvif *vif);
+void xenvif_put(struct xenvif *vif);
+
+int xenvif_xenbus_init(void);
+
+int xenvif_schedulable(struct xenvif *vif);
+
+int xen_netbk_rx_ring_full(struct xenvif *vif);
+
+int xen_netbk_must_stop_queue(struct xenvif *vif);
+
+/* (Un)Map communication rings. */
+void xen_netbk_unmap_frontend_rings(struct xenvif *vif);
+int xen_netbk_map_frontend_rings(struct xenvif *vif,
+				 grant_ref_t tx_ring_ref,
+				 grant_ref_t rx_ring_ref);
+
+/* (De)Register a xenvif with the netback backend. */
+void xen_netbk_add_xenvif(struct xenvif *vif);
+void xen_netbk_remove_xenvif(struct xenvif *vif);
+
+/* (De)Schedule backend processing for a xenvif */
+void xen_netbk_schedule_xenvif(struct xenvif *vif);
+void xen_netbk_deschedule_xenvif(struct xenvif *vif);
+
+/* Check for SKBs from frontend and schedule backend processing */
+void xen_netbk_check_rx_xenvif(struct xenvif *vif);
+/* Receive an SKB from the frontend */
+void xenvif_receive_skb(struct xenvif *vif, struct sk_buff *skb);
+
+/* Queue an SKB for transmission to the frontend */
+void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb);
+/* Notify xenvif that ring now has space to send an skb to the frontend */
+void xenvif_notify_tx_completion(struct xenvif *vif);
+
+/* Returns number of ring slots required to send an skb to the frontend */
+unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb);
+
+#endif /* __XEN_NETBACK__COMMON_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/net/xen-netback/interface.c linux-libre-2.6.39-gnu/drivers/net/xen-netback/interface.c
--- linux-libre-2.6.38-gnu/drivers/net/xen-netback/interface.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/xen-netback/interface.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,424 @@
+/*
+ * Network-device interface management.
+ *
+ * Copyright (c) 2004-2005, Keir Fraser
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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
+ * 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 <linux/ethtool.h>
+#include <linux/rtnetlink.h>
+#include <linux/if_vlan.h>
+
+#include <xen/events.h>
+#include <asm/xen/hypercall.h>
+
+#define XENVIF_QUEUE_LENGTH 32
+
+void xenvif_get(struct xenvif *vif)
+{
+	atomic_inc(&vif->refcnt);
+}
+
+void xenvif_put(struct xenvif *vif)
+{
+	if (atomic_dec_and_test(&vif->refcnt))
+		wake_up(&vif->waiting_to_free);
+}
+
+int xenvif_schedulable(struct xenvif *vif)
+{
+	return netif_running(vif->dev) && netif_carrier_ok(vif->dev);
+}
+
+static int xenvif_rx_schedulable(struct xenvif *vif)
+{
+	return xenvif_schedulable(vif) && !xen_netbk_rx_ring_full(vif);
+}
+
+static irqreturn_t xenvif_interrupt(int irq, void *dev_id)
+{
+	struct xenvif *vif = dev_id;
+
+	if (vif->netbk == NULL)
+		return IRQ_NONE;
+
+	xen_netbk_schedule_xenvif(vif);
+
+	if (xenvif_rx_schedulable(vif))
+		netif_wake_queue(vif->dev);
+
+	return IRQ_HANDLED;
+}
+
+static int xenvif_start_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+
+	BUG_ON(skb->dev != dev);
+
+	if (vif->netbk == NULL)
+		goto drop;
+
+	/* Drop the packet if the target domain has no receive buffers. */
+	if (!xenvif_rx_schedulable(vif))
+		goto drop;
+
+	/* Reserve ring slots for the worst-case number of fragments. */
+	vif->rx_req_cons_peek += xen_netbk_count_skb_slots(vif, skb);
+	xenvif_get(vif);
+
+	if (vif->can_queue && xen_netbk_must_stop_queue(vif))
+		netif_stop_queue(dev);
+
+	xen_netbk_queue_tx_skb(vif, skb);
+
+	return NETDEV_TX_OK;
+
+ drop:
+	vif->dev->stats.tx_dropped++;
+	dev_kfree_skb(skb);
+	return NETDEV_TX_OK;
+}
+
+void xenvif_receive_skb(struct xenvif *vif, struct sk_buff *skb)
+{
+	netif_rx_ni(skb);
+}
+
+void xenvif_notify_tx_completion(struct xenvif *vif)
+{
+	if (netif_queue_stopped(vif->dev) && xenvif_rx_schedulable(vif))
+		netif_wake_queue(vif->dev);
+}
+
+static struct net_device_stats *xenvif_get_stats(struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	return &vif->dev->stats;
+}
+
+static void xenvif_up(struct xenvif *vif)
+{
+	xen_netbk_add_xenvif(vif);
+	enable_irq(vif->irq);
+	xen_netbk_check_rx_xenvif(vif);
+}
+
+static void xenvif_down(struct xenvif *vif)
+{
+	disable_irq(vif->irq);
+	xen_netbk_deschedule_xenvif(vif);
+	xen_netbk_remove_xenvif(vif);
+}
+
+static int xenvif_open(struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (netif_carrier_ok(dev))
+		xenvif_up(vif);
+	netif_start_queue(dev);
+	return 0;
+}
+
+static int xenvif_close(struct net_device *dev)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (netif_carrier_ok(dev))
+		xenvif_down(vif);
+	netif_stop_queue(dev);
+	return 0;
+}
+
+static int xenvif_change_mtu(struct net_device *dev, int mtu)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	int max = vif->can_sg ? 65535 - VLAN_ETH_HLEN : ETH_DATA_LEN;
+
+	if (mtu > max)
+		return -EINVAL;
+	dev->mtu = mtu;
+	return 0;
+}
+
+static void xenvif_set_features(struct xenvif *vif)
+{
+	struct net_device *dev = vif->dev;
+	u32 features = dev->features;
+
+	if (vif->can_sg)
+		features |= NETIF_F_SG;
+	if (vif->gso || vif->gso_prefix)
+		features |= NETIF_F_TSO;
+	if (vif->csum)
+		features |= NETIF_F_IP_CSUM;
+
+	features &= ~(vif->features_disabled);
+
+	if (!(features & NETIF_F_SG) && dev->mtu > ETH_DATA_LEN)
+		dev->mtu = ETH_DATA_LEN;
+
+	dev->features = features;
+}
+
+static int xenvif_set_tx_csum(struct net_device *dev, u32 data)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (data) {
+		if (!vif->csum)
+			return -EOPNOTSUPP;
+		vif->features_disabled &= ~NETIF_F_IP_CSUM;
+	} else {
+		vif->features_disabled |= NETIF_F_IP_CSUM;
+	}
+
+	xenvif_set_features(vif);
+	return 0;
+}
+
+static int xenvif_set_sg(struct net_device *dev, u32 data)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (data) {
+		if (!vif->can_sg)
+			return -EOPNOTSUPP;
+		vif->features_disabled &= ~NETIF_F_SG;
+	} else {
+		vif->features_disabled |= NETIF_F_SG;
+	}
+
+	xenvif_set_features(vif);
+	return 0;
+}
+
+static int xenvif_set_tso(struct net_device *dev, u32 data)
+{
+	struct xenvif *vif = netdev_priv(dev);
+	if (data) {
+		if (!vif->gso && !vif->gso_prefix)
+			return -EOPNOTSUPP;
+		vif->features_disabled &= ~NETIF_F_TSO;
+	} else {
+		vif->features_disabled |= NETIF_F_TSO;
+	}
+
+	xenvif_set_features(vif);
+	return 0;
+}
+
+static const struct xenvif_stat {
+	char name[ETH_GSTRING_LEN];
+	u16 offset;
+} xenvif_stats[] = {
+	{
+		"rx_gso_checksum_fixup",
+		offsetof(struct xenvif, rx_gso_checksum_fixup)
+	},
+};
+
+static int xenvif_get_sset_count(struct net_device *dev, int string_set)
+{
+	switch (string_set) {
+	case ETH_SS_STATS:
+		return ARRAY_SIZE(xenvif_stats);
+	default:
+		return -EINVAL;
+	}
+}
+
+static void xenvif_get_ethtool_stats(struct net_device *dev,
+				     struct ethtool_stats *stats, u64 * data)
+{
+	void *vif = netdev_priv(dev);
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++)
+		data[i] = *(unsigned long *)(vif + xenvif_stats[i].offset);
+}
+
+static void xenvif_get_strings(struct net_device *dev, u32 stringset, u8 * data)
+{
+	int i;
+
+	switch (stringset) {
+	case ETH_SS_STATS:
+		for (i = 0; i < ARRAY_SIZE(xenvif_stats); i++)
+			memcpy(data + i * ETH_GSTRING_LEN,
+			       xenvif_stats[i].name, ETH_GSTRING_LEN);
+		break;
+	}
+}
+
+static struct ethtool_ops xenvif_ethtool_ops = {
+	.get_tx_csum	= ethtool_op_get_tx_csum,
+	.set_tx_csum	= xenvif_set_tx_csum,
+	.get_sg		= ethtool_op_get_sg,
+	.set_sg		= xenvif_set_sg,
+	.get_tso	= ethtool_op_get_tso,
+	.set_tso	= xenvif_set_tso,
+	.get_link	= ethtool_op_get_link,
+
+	.get_sset_count = xenvif_get_sset_count,
+	.get_ethtool_stats = xenvif_get_ethtool_stats,
+	.get_strings = xenvif_get_strings,
+};
+
+static struct net_device_ops xenvif_netdev_ops = {
+	.ndo_start_xmit	= xenvif_start_xmit,
+	.ndo_get_stats	= xenvif_get_stats,
+	.ndo_open	= xenvif_open,
+	.ndo_stop	= xenvif_close,
+	.ndo_change_mtu	= xenvif_change_mtu,
+};
+
+struct xenvif *xenvif_alloc(struct device *parent, domid_t domid,
+			    unsigned int handle)
+{
+	int err;
+	struct net_device *dev;
+	struct xenvif *vif;
+	char name[IFNAMSIZ] = {};
+
+	snprintf(name, IFNAMSIZ - 1, "vif%u.%u", domid, handle);
+	dev = alloc_netdev(sizeof(struct xenvif), name, ether_setup);
+	if (dev == NULL) {
+		pr_warn("Could not allocate netdev\n");
+		return ERR_PTR(-ENOMEM);
+	}
+
+	SET_NETDEV_DEV(dev, parent);
+
+	vif = netdev_priv(dev);
+	vif->domid  = domid;
+	vif->handle = handle;
+	vif->netbk  = NULL;
+	vif->can_sg = 1;
+	vif->csum = 1;
+	atomic_set(&vif->refcnt, 1);
+	init_waitqueue_head(&vif->waiting_to_free);
+	vif->dev = dev;
+	INIT_LIST_HEAD(&vif->schedule_list);
+	INIT_LIST_HEAD(&vif->notify_list);
+
+	vif->credit_bytes = vif->remaining_credit = ~0UL;
+	vif->credit_usec  = 0UL;
+	init_timer(&vif->credit_timeout);
+	/* Initialize 'expires' now: it's used to track the credit window. */
+	vif->credit_timeout.expires = jiffies;
+
+	dev->netdev_ops	= &xenvif_netdev_ops;
+	xenvif_set_features(vif);
+	SET_ETHTOOL_OPS(dev, &xenvif_ethtool_ops);
+
+	dev->tx_queue_len = XENVIF_QUEUE_LENGTH;
+
+	/*
+	 * Initialise a dummy MAC address. We choose the numerically
+	 * largest non-broadcast address to prevent the address getting
+	 * stolen by an Ethernet bridge for STP purposes.
+	 * (FE:FF:FF:FF:FF:FF)
+	 */
+	memset(dev->dev_addr, 0xFF, ETH_ALEN);
+	dev->dev_addr[0] &= ~0x01;
+
+	netif_carrier_off(dev);
+
+	err = register_netdev(dev);
+	if (err) {
+		netdev_warn(dev, "Could not register device: err=%d\n", err);
+		free_netdev(dev);
+		return ERR_PTR(err);
+	}
+
+	netdev_dbg(dev, "Successfully created xenvif\n");
+	return vif;
+}
+
+int xenvif_connect(struct xenvif *vif, unsigned long tx_ring_ref,
+		   unsigned long rx_ring_ref, unsigned int evtchn)
+{
+	int err = -ENOMEM;
+
+	/* Already connected through? */
+	if (vif->irq)
+		return 0;
+
+	xenvif_set_features(vif);
+
+	err = xen_netbk_map_frontend_rings(vif, tx_ring_ref, rx_ring_ref);
+	if (err < 0)
+		goto err;
+
+	err = bind_interdomain_evtchn_to_irqhandler(
+		vif->domid, evtchn, xenvif_interrupt, 0,
+		vif->dev->name, vif);
+	if (err < 0)
+		goto err_unmap;
+	vif->irq = err;
+	disable_irq(vif->irq);
+
+	xenvif_get(vif);
+
+	rtnl_lock();
+	netif_carrier_on(vif->dev);
+	if (netif_running(vif->dev))
+		xenvif_up(vif);
+	rtnl_unlock();
+
+	return 0;
+err_unmap:
+	xen_netbk_unmap_frontend_rings(vif);
+err:
+	return err;
+}
+
+void xenvif_disconnect(struct xenvif *vif)
+{
+	struct net_device *dev = vif->dev;
+	if (netif_carrier_ok(dev)) {
+		rtnl_lock();
+		netif_carrier_off(dev); /* discard queued packets */
+		if (netif_running(dev))
+			xenvif_down(vif);
+		rtnl_unlock();
+		xenvif_put(vif);
+	}
+
+	atomic_dec(&vif->refcnt);
+	wait_event(vif->waiting_to_free, atomic_read(&vif->refcnt) == 0);
+
+	del_timer_sync(&vif->credit_timeout);
+
+	if (vif->irq)
+		unbind_from_irqhandler(vif->irq, vif);
+
+	unregister_netdev(vif->dev);
+
+	xen_netbk_unmap_frontend_rings(vif);
+
+	free_netdev(vif->dev);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/xen-netback/Makefile linux-libre-2.6.39-gnu/drivers/net/xen-netback/Makefile
--- linux-libre-2.6.38-gnu/drivers/net/xen-netback/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/xen-netback/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3 @@
+obj-$(CONFIG_XEN_NETDEV_BACKEND) := xen-netback.o
+
+xen-netback-y := netback.o xenbus.o interface.o
diff -druN linux-libre-2.6.38-gnu/drivers/net/xen-netback/netback.c linux-libre-2.6.39-gnu/drivers/net/xen-netback/netback.c
--- linux-libre-2.6.38-gnu/drivers/net/xen-netback/netback.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/xen-netback/netback.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1745 @@
+/*
+ * Back-end of the driver for virtual network devices. This portion of the
+ * driver exports a 'unified' network-device interface that can be accessed
+ * by any operating system that implements a compatible front end. A
+ * reference front-end implementation can be found in:
+ *  drivers/net/xen-netfront.c
+ *
+ * Copyright (c) 2002-2005, K A Fraser
+ *
+ * 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; or, when distributed
+ * separately from the Linux kernel or incorporated into other
+ * software packages, subject to the following license:
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this source file (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
+ * 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 <linux/kthread.h>
+#include <linux/if_vlan.h>
+#include <linux/udp.h>
+
+#include <net/tcp.h>
+
+#include <xen/events.h>
+#include <xen/interface/memory.h>
+
+#include <asm/xen/hypercall.h>
+#include <asm/xen/page.h>
+
+struct pending_tx_info {
+	struct xen_netif_tx_request req;
+	struct xenvif *vif;
+};
+typedef unsigned int pending_ring_idx_t;
+
+struct netbk_rx_meta {
+	int id;
+	int size;
+	int gso_size;
+};
+
+#define MAX_PENDING_REQS 256
+
+#define MAX_BUFFER_OFFSET PAGE_SIZE
+
+/* extra field used in struct page */
+union page_ext {
+	struct {
+#if BITS_PER_LONG < 64
+#define IDX_WIDTH   8
+#define GROUP_WIDTH (BITS_PER_LONG - IDX_WIDTH)
+		unsigned int group:GROUP_WIDTH;
+		unsigned int idx:IDX_WIDTH;
+#else
+		unsigned int group, idx;
+#endif
+	} e;
+	void *mapping;
+};
+
+struct xen_netbk {
+	wait_queue_head_t wq;
+	struct task_struct *task;
+
+	struct sk_buff_head rx_queue;
+	struct sk_buff_head tx_queue;
+
+	struct timer_list net_timer;
+
+	struct page *mmap_pages[MAX_PENDING_REQS];
+
+	pending_ring_idx_t pending_prod;
+	pending_ring_idx_t pending_cons;
+	struct list_head net_schedule_list;
+
+	/* Protect the net_schedule_list in netif. */
+	spinlock_t net_schedule_list_lock;
+
+	atomic_t netfront_count;
+
+	struct pending_tx_info pending_tx_info[MAX_PENDING_REQS];
+	struct gnttab_copy tx_copy_ops[MAX_PENDING_REQS];
+
+	u16 pending_ring[MAX_PENDING_REQS];
+
+	/*
+	 * Given MAX_BUFFER_OFFSET of 4096 the worst case is that each
+	 * head/fragment page uses 2 copy operations because it
+	 * straddles two buffers in the frontend.
+	 */
+	struct gnttab_copy grant_copy_op[2*XEN_NETIF_RX_RING_SIZE];
+	struct netbk_rx_meta meta[2*XEN_NETIF_RX_RING_SIZE];
+};
+
+static struct xen_netbk *xen_netbk;
+static int xen_netbk_group_nr;
+
+void xen_netbk_add_xenvif(struct xenvif *vif)
+{
+	int i;
+	int min_netfront_count;
+	int min_group = 0;
+	struct xen_netbk *netbk;
+
+	min_netfront_count = atomic_read(&xen_netbk[0].netfront_count);
+	for (i = 0; i < xen_netbk_group_nr; i++) {
+		int netfront_count = atomic_read(&xen_netbk[i].netfront_count);
+		if (netfront_count < min_netfront_count) {
+			min_group = i;
+			min_netfront_count = netfront_count;
+		}
+	}
+
+	netbk = &xen_netbk[min_group];
+
+	vif->netbk = netbk;
+	atomic_inc(&netbk->netfront_count);
+}
+
+void xen_netbk_remove_xenvif(struct xenvif *vif)
+{
+	struct xen_netbk *netbk = vif->netbk;
+	vif->netbk = NULL;
+	atomic_dec(&netbk->netfront_count);
+}
+
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx);
+static void make_tx_response(struct xenvif *vif,
+			     struct xen_netif_tx_request *txp,
+			     s8       st);
+static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
+					     u16      id,
+					     s8       st,
+					     u16      offset,
+					     u16      size,
+					     u16      flags);
+
+static inline unsigned long idx_to_pfn(struct xen_netbk *netbk,
+				       unsigned int idx)
+{
+	return page_to_pfn(netbk->mmap_pages[idx]);
+}
+
+static inline unsigned long idx_to_kaddr(struct xen_netbk *netbk,
+					 unsigned int idx)
+{
+	return (unsigned long)pfn_to_kaddr(idx_to_pfn(netbk, idx));
+}
+
+/* extra field used in struct page */
+static inline void set_page_ext(struct page *pg, struct xen_netbk *netbk,
+				unsigned int idx)
+{
+	unsigned int group = netbk - xen_netbk;
+	union page_ext ext = { .e = { .group = group + 1, .idx = idx } };
+
+	BUILD_BUG_ON(sizeof(ext) > sizeof(ext.mapping));
+	pg->mapping = ext.mapping;
+}
+
+static int get_page_ext(struct page *pg,
+			unsigned int *pgroup, unsigned int *pidx)
+{
+	union page_ext ext = { .mapping = pg->mapping };
+	struct xen_netbk *netbk;
+	unsigned int group, idx;
+
+	group = ext.e.group - 1;
+
+	if (group < 0 || group >= xen_netbk_group_nr)
+		return 0;
+
+	netbk = &xen_netbk[group];
+
+	idx = ext.e.idx;
+
+	if ((idx < 0) || (idx >= MAX_PENDING_REQS))
+		return 0;
+
+	if (netbk->mmap_pages[idx] != pg)
+		return 0;
+
+	*pgroup = group;
+	*pidx = idx;
+
+	return 1;
+}
+
+/*
+ * This is the amount of packet we copy rather than map, so that the
+ * guest can't fiddle with the contents of the headers while we do
+ * packet processing on them (netfilter, routing, etc).
+ */
+#define PKT_PROT_LEN    (ETH_HLEN + \
+			 VLAN_HLEN + \
+			 sizeof(struct iphdr) + MAX_IPOPTLEN + \
+			 sizeof(struct tcphdr) + MAX_TCP_OPTION_SPACE)
+
+static inline pending_ring_idx_t pending_index(unsigned i)
+{
+	return i & (MAX_PENDING_REQS-1);
+}
+
+static inline pending_ring_idx_t nr_pending_reqs(struct xen_netbk *netbk)
+{
+	return MAX_PENDING_REQS -
+		netbk->pending_prod + netbk->pending_cons;
+}
+
+static void xen_netbk_kick_thread(struct xen_netbk *netbk)
+{
+	wake_up(&netbk->wq);
+}
+
+static int max_required_rx_slots(struct xenvif *vif)
+{
+	int max = DIV_ROUND_UP(vif->dev->mtu, PAGE_SIZE);
+
+	if (vif->can_sg || vif->gso || vif->gso_prefix)
+		max += MAX_SKB_FRAGS + 1; /* extra_info + frags */
+
+	return max;
+}
+
+int xen_netbk_rx_ring_full(struct xenvif *vif)
+{
+	RING_IDX peek   = vif->rx_req_cons_peek;
+	RING_IDX needed = max_required_rx_slots(vif);
+
+	return ((vif->rx.sring->req_prod - peek) < needed) ||
+	       ((vif->rx.rsp_prod_pvt + XEN_NETIF_RX_RING_SIZE - peek) < needed);
+}
+
+int xen_netbk_must_stop_queue(struct xenvif *vif)
+{
+	if (!xen_netbk_rx_ring_full(vif))
+		return 0;
+
+	vif->rx.sring->req_event = vif->rx_req_cons_peek +
+		max_required_rx_slots(vif);
+	mb(); /* request notification /then/ check the queue */
+
+	return xen_netbk_rx_ring_full(vif);
+}
+
+/*
+ * Returns true if we should start a new receive buffer instead of
+ * adding 'size' bytes to a buffer which currently contains 'offset'
+ * bytes.
+ */
+static bool start_new_rx_buffer(int offset, unsigned long size, int head)
+{
+	/* simple case: we have completely filled the current buffer. */
+	if (offset == MAX_BUFFER_OFFSET)
+		return true;
+
+	/*
+	 * complex case: start a fresh buffer if the current frag
+	 * would overflow the current buffer but only if:
+	 *     (i)   this frag would fit completely in the next buffer
+	 * and (ii)  there is already some data in the current buffer
+	 * and (iii) this is not the head buffer.
+	 *
+	 * Where:
+	 * - (i) stops us splitting a frag into two copies
+	 *   unless the frag is too large for a single buffer.
+	 * - (ii) stops us from leaving a buffer pointlessly empty.
+	 * - (iii) stops us leaving the first buffer
+	 *   empty. Strictly speaking this is already covered
+	 *   by (ii) but is explicitly checked because
+	 *   netfront relies on the first buffer being
+	 *   non-empty and can crash otherwise.
+	 *
+	 * This means we will effectively linearise small
+	 * frags but do not needlessly split large buffers
+	 * into multiple copies tend to give large frags their
+	 * own buffers as before.
+	 */
+	if ((offset + size > MAX_BUFFER_OFFSET) &&
+	    (size <= MAX_BUFFER_OFFSET) && offset && !head)
+		return true;
+
+	return false;
+}
+
+/*
+ * Figure out how many ring slots we're going to need to send @skb to
+ * the guest. This function is essentially a dry run of
+ * netbk_gop_frag_copy.
+ */
+unsigned int xen_netbk_count_skb_slots(struct xenvif *vif, struct sk_buff *skb)
+{
+	unsigned int count;
+	int i, copy_off;
+
+	count = DIV_ROUND_UP(
+			offset_in_page(skb->data)+skb_headlen(skb), PAGE_SIZE);
+
+	copy_off = skb_headlen(skb) % PAGE_SIZE;
+
+	if (skb_shinfo(skb)->gso_size)
+		count++;
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		unsigned long size = skb_shinfo(skb)->frags[i].size;
+		unsigned long bytes;
+		while (size > 0) {
+			BUG_ON(copy_off > MAX_BUFFER_OFFSET);
+
+			if (start_new_rx_buffer(copy_off, size, 0)) {
+				count++;
+				copy_off = 0;
+			}
+
+			bytes = size;
+			if (copy_off + bytes > MAX_BUFFER_OFFSET)
+				bytes = MAX_BUFFER_OFFSET - copy_off;
+
+			copy_off += bytes;
+			size -= bytes;
+		}
+	}
+	return count;
+}
+
+struct netrx_pending_operations {
+	unsigned copy_prod, copy_cons;
+	unsigned meta_prod, meta_cons;
+	struct gnttab_copy *copy;
+	struct netbk_rx_meta *meta;
+	int copy_off;
+	grant_ref_t copy_gref;
+};
+
+static struct netbk_rx_meta *get_next_rx_buffer(struct xenvif *vif,
+						struct netrx_pending_operations *npo)
+{
+	struct netbk_rx_meta *meta;
+	struct xen_netif_rx_request *req;
+
+	req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
+
+	meta = npo->meta + npo->meta_prod++;
+	meta->gso_size = 0;
+	meta->size = 0;
+	meta->id = req->id;
+
+	npo->copy_off = 0;
+	npo->copy_gref = req->gref;
+
+	return meta;
+}
+
+/*
+ * Set up the grant operations for this fragment. If it's a flipping
+ * interface, we also set up the unmap request from here.
+ */
+static void netbk_gop_frag_copy(struct xenvif *vif, struct sk_buff *skb,
+				struct netrx_pending_operations *npo,
+				struct page *page, unsigned long size,
+				unsigned long offset, int *head)
+{
+	struct gnttab_copy *copy_gop;
+	struct netbk_rx_meta *meta;
+	/*
+	 * These variables a used iff get_page_ext returns true,
+	 * in which case they are guaranteed to be initialized.
+	 */
+	unsigned int uninitialized_var(group), uninitialized_var(idx);
+	int foreign = get_page_ext(page, &group, &idx);
+	unsigned long bytes;
+
+	/* Data must not cross a page boundary. */
+	BUG_ON(size + offset > PAGE_SIZE);
+
+	meta = npo->meta + npo->meta_prod - 1;
+
+	while (size > 0) {
+		BUG_ON(npo->copy_off > MAX_BUFFER_OFFSET);
+
+		if (start_new_rx_buffer(npo->copy_off, size, *head)) {
+			/*
+			 * Netfront requires there to be some data in the head
+			 * buffer.
+			 */
+			BUG_ON(*head);
+
+			meta = get_next_rx_buffer(vif, npo);
+		}
+
+		bytes = size;
+		if (npo->copy_off + bytes > MAX_BUFFER_OFFSET)
+			bytes = MAX_BUFFER_OFFSET - npo->copy_off;
+
+		copy_gop = npo->copy + npo->copy_prod++;
+		copy_gop->flags = GNTCOPY_dest_gref;
+		if (foreign) {
+			struct xen_netbk *netbk = &xen_netbk[group];
+			struct pending_tx_info *src_pend;
+
+			src_pend = &netbk->pending_tx_info[idx];
+
+			copy_gop->source.domid = src_pend->vif->domid;
+			copy_gop->source.u.ref = src_pend->req.gref;
+			copy_gop->flags |= GNTCOPY_source_gref;
+		} else {
+			void *vaddr = page_address(page);
+			copy_gop->source.domid = DOMID_SELF;
+			copy_gop->source.u.gmfn = virt_to_mfn(vaddr);
+		}
+		copy_gop->source.offset = offset;
+		copy_gop->dest.domid = vif->domid;
+
+		copy_gop->dest.offset = npo->copy_off;
+		copy_gop->dest.u.ref = npo->copy_gref;
+		copy_gop->len = bytes;
+
+		npo->copy_off += bytes;
+		meta->size += bytes;
+
+		offset += bytes;
+		size -= bytes;
+
+		/* Leave a gap for the GSO descriptor. */
+		if (*head && skb_shinfo(skb)->gso_size && !vif->gso_prefix)
+			vif->rx.req_cons++;
+
+		*head = 0; /* There must be something in this buffer now. */
+
+	}
+}
+
+/*
+ * Prepare an SKB to be transmitted to the frontend.
+ *
+ * This function is responsible for allocating grant operations, meta
+ * structures, etc.
+ *
+ * It returns the number of meta structures consumed. The number of
+ * ring slots used is always equal to the number of meta slots used
+ * plus the number of GSO descriptors used. Currently, we use either
+ * zero GSO descriptors (for non-GSO packets) or one descriptor (for
+ * frontend-side LRO).
+ */
+static int netbk_gop_skb(struct sk_buff *skb,
+			 struct netrx_pending_operations *npo)
+{
+	struct xenvif *vif = netdev_priv(skb->dev);
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	int i;
+	struct xen_netif_rx_request *req;
+	struct netbk_rx_meta *meta;
+	unsigned char *data;
+	int head = 1;
+	int old_meta_prod;
+
+	old_meta_prod = npo->meta_prod;
+
+	/* Set up a GSO prefix descriptor, if necessary */
+	if (skb_shinfo(skb)->gso_size && vif->gso_prefix) {
+		req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
+		meta = npo->meta + npo->meta_prod++;
+		meta->gso_size = skb_shinfo(skb)->gso_size;
+		meta->size = 0;
+		meta->id = req->id;
+	}
+
+	req = RING_GET_REQUEST(&vif->rx, vif->rx.req_cons++);
+	meta = npo->meta + npo->meta_prod++;
+
+	if (!vif->gso_prefix)
+		meta->gso_size = skb_shinfo(skb)->gso_size;
+	else
+		meta->gso_size = 0;
+
+	meta->size = 0;
+	meta->id = req->id;
+	npo->copy_off = 0;
+	npo->copy_gref = req->gref;
+
+	data = skb->data;
+	while (data < skb_tail_pointer(skb)) {
+		unsigned int offset = offset_in_page(data);
+		unsigned int len = PAGE_SIZE - offset;
+
+		if (data + len > skb_tail_pointer(skb))
+			len = skb_tail_pointer(skb) - data;
+
+		netbk_gop_frag_copy(vif, skb, npo,
+				    virt_to_page(data), len, offset, &head);
+		data += len;
+	}
+
+	for (i = 0; i < nr_frags; i++) {
+		netbk_gop_frag_copy(vif, skb, npo,
+				    skb_shinfo(skb)->frags[i].page,
+				    skb_shinfo(skb)->frags[i].size,
+				    skb_shinfo(skb)->frags[i].page_offset,
+				    &head);
+	}
+
+	return npo->meta_prod - old_meta_prod;
+}
+
+/*
+ * This is a twin to netbk_gop_skb.  Assume that netbk_gop_skb was
+ * used to set up the operations on the top of
+ * netrx_pending_operations, which have since been done.  Check that
+ * they didn't give any errors and advance over them.
+ */
+static int netbk_check_gop(struct xenvif *vif, int nr_meta_slots,
+			   struct netrx_pending_operations *npo)
+{
+	struct gnttab_copy     *copy_op;
+	int status = XEN_NETIF_RSP_OKAY;
+	int i;
+
+	for (i = 0; i < nr_meta_slots; i++) {
+		copy_op = npo->copy + npo->copy_cons++;
+		if (copy_op->status != GNTST_okay) {
+			netdev_dbg(vif->dev,
+				   "Bad status %d from copy to DOM%d.\n",
+				   copy_op->status, vif->domid);
+			status = XEN_NETIF_RSP_ERROR;
+		}
+	}
+
+	return status;
+}
+
+static void netbk_add_frag_responses(struct xenvif *vif, int status,
+				     struct netbk_rx_meta *meta,
+				     int nr_meta_slots)
+{
+	int i;
+	unsigned long offset;
+
+	/* No fragments used */
+	if (nr_meta_slots <= 1)
+		return;
+
+	nr_meta_slots--;
+
+	for (i = 0; i < nr_meta_slots; i++) {
+		int flags;
+		if (i == nr_meta_slots - 1)
+			flags = 0;
+		else
+			flags = XEN_NETRXF_more_data;
+
+		offset = 0;
+		make_rx_response(vif, meta[i].id, status, offset,
+				 meta[i].size, flags);
+	}
+}
+
+struct skb_cb_overlay {
+	int meta_slots_used;
+};
+
+static void xen_netbk_rx_action(struct xen_netbk *netbk)
+{
+	struct xenvif *vif = NULL, *tmp;
+	s8 status;
+	u16 irq, flags;
+	struct xen_netif_rx_response *resp;
+	struct sk_buff_head rxq;
+	struct sk_buff *skb;
+	LIST_HEAD(notify);
+	int ret;
+	int nr_frags;
+	int count;
+	unsigned long offset;
+	struct skb_cb_overlay *sco;
+
+	struct netrx_pending_operations npo = {
+		.copy  = netbk->grant_copy_op,
+		.meta  = netbk->meta,
+	};
+
+	skb_queue_head_init(&rxq);
+
+	count = 0;
+
+	while ((skb = skb_dequeue(&netbk->rx_queue)) != NULL) {
+		vif = netdev_priv(skb->dev);
+		nr_frags = skb_shinfo(skb)->nr_frags;
+
+		sco = (struct skb_cb_overlay *)skb->cb;
+		sco->meta_slots_used = netbk_gop_skb(skb, &npo);
+
+		count += nr_frags + 1;
+
+		__skb_queue_tail(&rxq, skb);
+
+		/* Filled the batch queue? */
+		if (count + MAX_SKB_FRAGS >= XEN_NETIF_RX_RING_SIZE)
+			break;
+	}
+
+	BUG_ON(npo.meta_prod > ARRAY_SIZE(netbk->meta));
+
+	if (!npo.copy_prod)
+		return;
+
+	BUG_ON(npo.copy_prod > ARRAY_SIZE(netbk->grant_copy_op));
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_copy, &netbk->grant_copy_op,
+					npo.copy_prod);
+	BUG_ON(ret != 0);
+
+	while ((skb = __skb_dequeue(&rxq)) != NULL) {
+		sco = (struct skb_cb_overlay *)skb->cb;
+
+		vif = netdev_priv(skb->dev);
+
+		if (netbk->meta[npo.meta_cons].gso_size && vif->gso_prefix) {
+			resp = RING_GET_RESPONSE(&vif->rx,
+						vif->rx.rsp_prod_pvt++);
+
+			resp->flags = XEN_NETRXF_gso_prefix | XEN_NETRXF_more_data;
+
+			resp->offset = netbk->meta[npo.meta_cons].gso_size;
+			resp->id = netbk->meta[npo.meta_cons].id;
+			resp->status = sco->meta_slots_used;
+
+			npo.meta_cons++;
+			sco->meta_slots_used--;
+		}
+
+
+		vif->dev->stats.tx_bytes += skb->len;
+		vif->dev->stats.tx_packets++;
+
+		status = netbk_check_gop(vif, sco->meta_slots_used, &npo);
+
+		if (sco->meta_slots_used == 1)
+			flags = 0;
+		else
+			flags = XEN_NETRXF_more_data;
+
+		if (skb->ip_summed == CHECKSUM_PARTIAL) /* local packet? */
+			flags |= XEN_NETRXF_csum_blank | XEN_NETRXF_data_validated;
+		else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
+			/* remote but checksummed. */
+			flags |= XEN_NETRXF_data_validated;
+
+		offset = 0;
+		resp = make_rx_response(vif, netbk->meta[npo.meta_cons].id,
+					status, offset,
+					netbk->meta[npo.meta_cons].size,
+					flags);
+
+		if (netbk->meta[npo.meta_cons].gso_size && !vif->gso_prefix) {
+			struct xen_netif_extra_info *gso =
+				(struct xen_netif_extra_info *)
+				RING_GET_RESPONSE(&vif->rx,
+						  vif->rx.rsp_prod_pvt++);
+
+			resp->flags |= XEN_NETRXF_extra_info;
+
+			gso->u.gso.size = netbk->meta[npo.meta_cons].gso_size;
+			gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
+			gso->u.gso.pad = 0;
+			gso->u.gso.features = 0;
+
+			gso->type = XEN_NETIF_EXTRA_TYPE_GSO;
+			gso->flags = 0;
+		}
+
+		netbk_add_frag_responses(vif, status,
+					 netbk->meta + npo.meta_cons + 1,
+					 sco->meta_slots_used);
+
+		RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->rx, ret);
+		irq = vif->irq;
+		if (ret && list_empty(&vif->notify_list))
+			list_add_tail(&vif->notify_list, &notify);
+
+		xenvif_notify_tx_completion(vif);
+
+		xenvif_put(vif);
+		npo.meta_cons += sco->meta_slots_used;
+		dev_kfree_skb(skb);
+	}
+
+	list_for_each_entry_safe(vif, tmp, &notify, notify_list) {
+		notify_remote_via_irq(vif->irq);
+		list_del_init(&vif->notify_list);
+	}
+
+	/* More work to do? */
+	if (!skb_queue_empty(&netbk->rx_queue) &&
+			!timer_pending(&netbk->net_timer))
+		xen_netbk_kick_thread(netbk);
+}
+
+void xen_netbk_queue_tx_skb(struct xenvif *vif, struct sk_buff *skb)
+{
+	struct xen_netbk *netbk = vif->netbk;
+
+	skb_queue_tail(&netbk->rx_queue, skb);
+
+	xen_netbk_kick_thread(netbk);
+}
+
+static void xen_netbk_alarm(unsigned long data)
+{
+	struct xen_netbk *netbk = (struct xen_netbk *)data;
+	xen_netbk_kick_thread(netbk);
+}
+
+static int __on_net_schedule_list(struct xenvif *vif)
+{
+	return !list_empty(&vif->schedule_list);
+}
+
+/* Must be called with net_schedule_list_lock held */
+static void remove_from_net_schedule_list(struct xenvif *vif)
+{
+	if (likely(__on_net_schedule_list(vif))) {
+		list_del_init(&vif->schedule_list);
+		xenvif_put(vif);
+	}
+}
+
+static struct xenvif *poll_net_schedule_list(struct xen_netbk *netbk)
+{
+	struct xenvif *vif = NULL;
+
+	spin_lock_irq(&netbk->net_schedule_list_lock);
+	if (list_empty(&netbk->net_schedule_list))
+		goto out;
+
+	vif = list_first_entry(&netbk->net_schedule_list,
+			       struct xenvif, schedule_list);
+	if (!vif)
+		goto out;
+
+	xenvif_get(vif);
+
+	remove_from_net_schedule_list(vif);
+out:
+	spin_unlock_irq(&netbk->net_schedule_list_lock);
+	return vif;
+}
+
+void xen_netbk_schedule_xenvif(struct xenvif *vif)
+{
+	unsigned long flags;
+	struct xen_netbk *netbk = vif->netbk;
+
+	if (__on_net_schedule_list(vif))
+		goto kick;
+
+	spin_lock_irqsave(&netbk->net_schedule_list_lock, flags);
+	if (!__on_net_schedule_list(vif) &&
+	    likely(xenvif_schedulable(vif))) {
+		list_add_tail(&vif->schedule_list, &netbk->net_schedule_list);
+		xenvif_get(vif);
+	}
+	spin_unlock_irqrestore(&netbk->net_schedule_list_lock, flags);
+
+kick:
+	smp_mb();
+	if ((nr_pending_reqs(netbk) < (MAX_PENDING_REQS/2)) &&
+	    !list_empty(&netbk->net_schedule_list))
+		xen_netbk_kick_thread(netbk);
+}
+
+void xen_netbk_deschedule_xenvif(struct xenvif *vif)
+{
+	struct xen_netbk *netbk = vif->netbk;
+	spin_lock_irq(&netbk->net_schedule_list_lock);
+	remove_from_net_schedule_list(vif);
+	spin_unlock_irq(&netbk->net_schedule_list_lock);
+}
+
+void xen_netbk_check_rx_xenvif(struct xenvif *vif)
+{
+	int more_to_do;
+
+	RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, more_to_do);
+
+	if (more_to_do)
+		xen_netbk_schedule_xenvif(vif);
+}
+
+static void tx_add_credit(struct xenvif *vif)
+{
+	unsigned long max_burst, max_credit;
+
+	/*
+	 * Allow a burst big enough to transmit a jumbo packet of up to 128kB.
+	 * Otherwise the interface can seize up due to insufficient credit.
+	 */
+	max_burst = RING_GET_REQUEST(&vif->tx, vif->tx.req_cons)->size;
+	max_burst = min(max_burst, 131072UL);
+	max_burst = max(max_burst, vif->credit_bytes);
+
+	/* Take care that adding a new chunk of credit doesn't wrap to zero. */
+	max_credit = vif->remaining_credit + vif->credit_bytes;
+	if (max_credit < vif->remaining_credit)
+		max_credit = ULONG_MAX; /* wrapped: clamp to ULONG_MAX */
+
+	vif->remaining_credit = min(max_credit, max_burst);
+}
+
+static void tx_credit_callback(unsigned long data)
+{
+	struct xenvif *vif = (struct xenvif *)data;
+	tx_add_credit(vif);
+	xen_netbk_check_rx_xenvif(vif);
+}
+
+static void netbk_tx_err(struct xenvif *vif,
+			 struct xen_netif_tx_request *txp, RING_IDX end)
+{
+	RING_IDX cons = vif->tx.req_cons;
+
+	do {
+		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
+		if (cons >= end)
+			break;
+		txp = RING_GET_REQUEST(&vif->tx, cons++);
+	} while (1);
+	vif->tx.req_cons = cons;
+	xen_netbk_check_rx_xenvif(vif);
+	xenvif_put(vif);
+}
+
+static int netbk_count_requests(struct xenvif *vif,
+				struct xen_netif_tx_request *first,
+				struct xen_netif_tx_request *txp,
+				int work_to_do)
+{
+	RING_IDX cons = vif->tx.req_cons;
+	int frags = 0;
+
+	if (!(first->flags & XEN_NETTXF_more_data))
+		return 0;
+
+	do {
+		if (frags >= work_to_do) {
+			netdev_dbg(vif->dev, "Need more frags\n");
+			return -frags;
+		}
+
+		if (unlikely(frags >= MAX_SKB_FRAGS)) {
+			netdev_dbg(vif->dev, "Too many frags\n");
+			return -frags;
+		}
+
+		memcpy(txp, RING_GET_REQUEST(&vif->tx, cons + frags),
+		       sizeof(*txp));
+		if (txp->size > first->size) {
+			netdev_dbg(vif->dev, "Frags galore\n");
+			return -frags;
+		}
+
+		first->size -= txp->size;
+		frags++;
+
+		if (unlikely((txp->offset + txp->size) > PAGE_SIZE)) {
+			netdev_dbg(vif->dev, "txp->offset: %x, size: %u\n",
+				 txp->offset, txp->size);
+			return -frags;
+		}
+	} while ((txp++)->flags & XEN_NETTXF_more_data);
+	return frags;
+}
+
+static struct page *xen_netbk_alloc_page(struct xen_netbk *netbk,
+					 struct sk_buff *skb,
+					 unsigned long pending_idx)
+{
+	struct page *page;
+	page = alloc_page(GFP_KERNEL|__GFP_COLD);
+	if (!page)
+		return NULL;
+	set_page_ext(page, netbk, pending_idx);
+	netbk->mmap_pages[pending_idx] = page;
+	return page;
+}
+
+static struct gnttab_copy *xen_netbk_get_requests(struct xen_netbk *netbk,
+						  struct xenvif *vif,
+						  struct sk_buff *skb,
+						  struct xen_netif_tx_request *txp,
+						  struct gnttab_copy *gop)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	skb_frag_t *frags = shinfo->frags;
+	unsigned long pending_idx = *((u16 *)skb->data);
+	int i, start;
+
+	/* Skip first skb fragment if it is on same page as header fragment. */
+	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+	for (i = start; i < shinfo->nr_frags; i++, txp++) {
+		struct page *page;
+		pending_ring_idx_t index;
+		struct pending_tx_info *pending_tx_info =
+			netbk->pending_tx_info;
+
+		index = pending_index(netbk->pending_cons++);
+		pending_idx = netbk->pending_ring[index];
+		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		if (!page)
+			return NULL;
+
+		netbk->mmap_pages[pending_idx] = page;
+
+		gop->source.u.ref = txp->gref;
+		gop->source.domid = vif->domid;
+		gop->source.offset = txp->offset;
+
+		gop->dest.u.gmfn = virt_to_mfn(page_address(page));
+		gop->dest.domid = DOMID_SELF;
+		gop->dest.offset = txp->offset;
+
+		gop->len = txp->size;
+		gop->flags = GNTCOPY_source_gref;
+
+		gop++;
+
+		memcpy(&pending_tx_info[pending_idx].req, txp, sizeof(*txp));
+		xenvif_get(vif);
+		pending_tx_info[pending_idx].vif = vif;
+		frags[i].page = (void *)pending_idx;
+	}
+
+	return gop;
+}
+
+static int xen_netbk_tx_check_gop(struct xen_netbk *netbk,
+				  struct sk_buff *skb,
+				  struct gnttab_copy **gopp)
+{
+	struct gnttab_copy *gop = *gopp;
+	int pending_idx = *((u16 *)skb->data);
+	struct pending_tx_info *pending_tx_info = netbk->pending_tx_info;
+	struct xenvif *vif = pending_tx_info[pending_idx].vif;
+	struct xen_netif_tx_request *txp;
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	int i, err, start;
+
+	/* Check status of header. */
+	err = gop->status;
+	if (unlikely(err)) {
+		pending_ring_idx_t index;
+		index = pending_index(netbk->pending_prod++);
+		txp = &pending_tx_info[pending_idx].req;
+		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
+		netbk->pending_ring[index] = pending_idx;
+		xenvif_put(vif);
+	}
+
+	/* Skip first skb fragment if it is on same page as header fragment. */
+	start = ((unsigned long)shinfo->frags[0].page == pending_idx);
+
+	for (i = start; i < nr_frags; i++) {
+		int j, newerr;
+		pending_ring_idx_t index;
+
+		pending_idx = (unsigned long)shinfo->frags[i].page;
+
+		/* Check error status: if okay then remember grant handle. */
+		newerr = (++gop)->status;
+		if (likely(!newerr)) {
+			/* Had a previous error? Invalidate this fragment. */
+			if (unlikely(err))
+				xen_netbk_idx_release(netbk, pending_idx);
+			continue;
+		}
+
+		/* Error on this fragment: respond to client with an error. */
+		txp = &netbk->pending_tx_info[pending_idx].req;
+		make_tx_response(vif, txp, XEN_NETIF_RSP_ERROR);
+		index = pending_index(netbk->pending_prod++);
+		netbk->pending_ring[index] = pending_idx;
+		xenvif_put(vif);
+
+		/* Not the first error? Preceding frags already invalidated. */
+		if (err)
+			continue;
+
+		/* First error: invalidate header and preceding fragments. */
+		pending_idx = *((u16 *)skb->data);
+		xen_netbk_idx_release(netbk, pending_idx);
+		for (j = start; j < i; j++) {
+			pending_idx = (unsigned long)shinfo->frags[i].page;
+			xen_netbk_idx_release(netbk, pending_idx);
+		}
+
+		/* Remember the error: invalidate all subsequent fragments. */
+		err = newerr;
+	}
+
+	*gopp = gop + 1;
+	return err;
+}
+
+static void xen_netbk_fill_frags(struct xen_netbk *netbk, struct sk_buff *skb)
+{
+	struct skb_shared_info *shinfo = skb_shinfo(skb);
+	int nr_frags = shinfo->nr_frags;
+	int i;
+
+	for (i = 0; i < nr_frags; i++) {
+		skb_frag_t *frag = shinfo->frags + i;
+		struct xen_netif_tx_request *txp;
+		unsigned long pending_idx;
+
+		pending_idx = (unsigned long)frag->page;
+
+		txp = &netbk->pending_tx_info[pending_idx].req;
+		frag->page = virt_to_page(idx_to_kaddr(netbk, pending_idx));
+		frag->size = txp->size;
+		frag->page_offset = txp->offset;
+
+		skb->len += txp->size;
+		skb->data_len += txp->size;
+		skb->truesize += txp->size;
+
+		/* Take an extra reference to offset xen_netbk_idx_release */
+		get_page(netbk->mmap_pages[pending_idx]);
+		xen_netbk_idx_release(netbk, pending_idx);
+	}
+}
+
+static int xen_netbk_get_extras(struct xenvif *vif,
+				struct xen_netif_extra_info *extras,
+				int work_to_do)
+{
+	struct xen_netif_extra_info extra;
+	RING_IDX cons = vif->tx.req_cons;
+
+	do {
+		if (unlikely(work_to_do-- <= 0)) {
+			netdev_dbg(vif->dev, "Missing extra info\n");
+			return -EBADR;
+		}
+
+		memcpy(&extra, RING_GET_REQUEST(&vif->tx, cons),
+		       sizeof(extra));
+		if (unlikely(!extra.type ||
+			     extra.type >= XEN_NETIF_EXTRA_TYPE_MAX)) {
+			vif->tx.req_cons = ++cons;
+			netdev_dbg(vif->dev,
+				   "Invalid extra type: %d\n", extra.type);
+			return -EINVAL;
+		}
+
+		memcpy(&extras[extra.type - 1], &extra, sizeof(extra));
+		vif->tx.req_cons = ++cons;
+	} while (extra.flags & XEN_NETIF_EXTRA_FLAG_MORE);
+
+	return work_to_do;
+}
+
+static int netbk_set_skb_gso(struct xenvif *vif,
+			     struct sk_buff *skb,
+			     struct xen_netif_extra_info *gso)
+{
+	if (!gso->u.gso.size) {
+		netdev_dbg(vif->dev, "GSO size must not be zero.\n");
+		return -EINVAL;
+	}
+
+	/* Currently only TCPv4 S.O. is supported. */
+	if (gso->u.gso.type != XEN_NETIF_GSO_TYPE_TCPV4) {
+		netdev_dbg(vif->dev, "Bad GSO type %d.\n", gso->u.gso.type);
+		return -EINVAL;
+	}
+
+	skb_shinfo(skb)->gso_size = gso->u.gso.size;
+	skb_shinfo(skb)->gso_type = SKB_GSO_TCPV4;
+
+	/* Header must be checked, and gso_segs computed. */
+	skb_shinfo(skb)->gso_type |= SKB_GSO_DODGY;
+	skb_shinfo(skb)->gso_segs = 0;
+
+	return 0;
+}
+
+static int checksum_setup(struct xenvif *vif, struct sk_buff *skb)
+{
+	struct iphdr *iph;
+	unsigned char *th;
+	int err = -EPROTO;
+	int recalculate_partial_csum = 0;
+
+	/*
+	 * A GSO SKB must be CHECKSUM_PARTIAL. However some buggy
+	 * peers can fail to set NETRXF_csum_blank when sending a GSO
+	 * frame. In this case force the SKB to CHECKSUM_PARTIAL and
+	 * recalculate the partial checksum.
+	 */
+	if (skb->ip_summed != CHECKSUM_PARTIAL && skb_is_gso(skb)) {
+		vif->rx_gso_checksum_fixup++;
+		skb->ip_summed = CHECKSUM_PARTIAL;
+		recalculate_partial_csum = 1;
+	}
+
+	/* A non-CHECKSUM_PARTIAL SKB does not require setup. */
+	if (skb->ip_summed != CHECKSUM_PARTIAL)
+		return 0;
+
+	if (skb->protocol != htons(ETH_P_IP))
+		goto out;
+
+	iph = (void *)skb->data;
+	th = skb->data + 4 * iph->ihl;
+	if (th >= skb_tail_pointer(skb))
+		goto out;
+
+	skb->csum_start = th - skb->head;
+	switch (iph->protocol) {
+	case IPPROTO_TCP:
+		skb->csum_offset = offsetof(struct tcphdr, check);
+
+		if (recalculate_partial_csum) {
+			struct tcphdr *tcph = (struct tcphdr *)th;
+			tcph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+							 skb->len - iph->ihl*4,
+							 IPPROTO_TCP, 0);
+		}
+		break;
+	case IPPROTO_UDP:
+		skb->csum_offset = offsetof(struct udphdr, check);
+
+		if (recalculate_partial_csum) {
+			struct udphdr *udph = (struct udphdr *)th;
+			udph->check = ~csum_tcpudp_magic(iph->saddr, iph->daddr,
+							 skb->len - iph->ihl*4,
+							 IPPROTO_UDP, 0);
+		}
+		break;
+	default:
+		if (net_ratelimit())
+			netdev_err(vif->dev,
+				   "Attempting to checksum a non-TCP/UDP packet, dropping a protocol %d packet\n",
+				   iph->protocol);
+		goto out;
+	}
+
+	if ((th + skb->csum_offset + 2) > skb_tail_pointer(skb))
+		goto out;
+
+	err = 0;
+
+out:
+	return err;
+}
+
+static bool tx_credit_exceeded(struct xenvif *vif, unsigned size)
+{
+	unsigned long now = jiffies;
+	unsigned long next_credit =
+		vif->credit_timeout.expires +
+		msecs_to_jiffies(vif->credit_usec / 1000);
+
+	/* Timer could already be pending in rare cases. */
+	if (timer_pending(&vif->credit_timeout))
+		return true;
+
+	/* Passed the point where we can replenish credit? */
+	if (time_after_eq(now, next_credit)) {
+		vif->credit_timeout.expires = now;
+		tx_add_credit(vif);
+	}
+
+	/* Still too big to send right now? Set a callback. */
+	if (size > vif->remaining_credit) {
+		vif->credit_timeout.data     =
+			(unsigned long)vif;
+		vif->credit_timeout.function =
+			tx_credit_callback;
+		mod_timer(&vif->credit_timeout,
+			  next_credit);
+
+		return true;
+	}
+
+	return false;
+}
+
+static unsigned xen_netbk_tx_build_gops(struct xen_netbk *netbk)
+{
+	struct gnttab_copy *gop = netbk->tx_copy_ops, *request_gop;
+	struct sk_buff *skb;
+	int ret;
+
+	while (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+		!list_empty(&netbk->net_schedule_list)) {
+		struct xenvif *vif;
+		struct xen_netif_tx_request txreq;
+		struct xen_netif_tx_request txfrags[MAX_SKB_FRAGS];
+		struct page *page;
+		struct xen_netif_extra_info extras[XEN_NETIF_EXTRA_TYPE_MAX-1];
+		u16 pending_idx;
+		RING_IDX idx;
+		int work_to_do;
+		unsigned int data_len;
+		pending_ring_idx_t index;
+
+		/* Get a netif from the list with work to do. */
+		vif = poll_net_schedule_list(netbk);
+		if (!vif)
+			continue;
+
+		RING_FINAL_CHECK_FOR_REQUESTS(&vif->tx, work_to_do);
+		if (!work_to_do) {
+			xenvif_put(vif);
+			continue;
+		}
+
+		idx = vif->tx.req_cons;
+		rmb(); /* Ensure that we see the request before we copy it. */
+		memcpy(&txreq, RING_GET_REQUEST(&vif->tx, idx), sizeof(txreq));
+
+		/* Credit-based scheduling. */
+		if (txreq.size > vif->remaining_credit &&
+		    tx_credit_exceeded(vif, txreq.size)) {
+			xenvif_put(vif);
+			continue;
+		}
+
+		vif->remaining_credit -= txreq.size;
+
+		work_to_do--;
+		vif->tx.req_cons = ++idx;
+
+		memset(extras, 0, sizeof(extras));
+		if (txreq.flags & XEN_NETTXF_extra_info) {
+			work_to_do = xen_netbk_get_extras(vif, extras,
+							  work_to_do);
+			idx = vif->tx.req_cons;
+			if (unlikely(work_to_do < 0)) {
+				netbk_tx_err(vif, &txreq, idx);
+				continue;
+			}
+		}
+
+		ret = netbk_count_requests(vif, &txreq, txfrags, work_to_do);
+		if (unlikely(ret < 0)) {
+			netbk_tx_err(vif, &txreq, idx - ret);
+			continue;
+		}
+		idx += ret;
+
+		if (unlikely(txreq.size < ETH_HLEN)) {
+			netdev_dbg(vif->dev,
+				   "Bad packet size: %d\n", txreq.size);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+
+		/* No crossing a page as the payload mustn't fragment. */
+		if (unlikely((txreq.offset + txreq.size) > PAGE_SIZE)) {
+			netdev_dbg(vif->dev,
+				   "txreq.offset: %x, size: %u, end: %lu\n",
+				   txreq.offset, txreq.size,
+				   (txreq.offset&~PAGE_MASK) + txreq.size);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+
+		index = pending_index(netbk->pending_cons);
+		pending_idx = netbk->pending_ring[index];
+
+		data_len = (txreq.size > PKT_PROT_LEN &&
+			    ret < MAX_SKB_FRAGS) ?
+			PKT_PROT_LEN : txreq.size;
+
+		skb = alloc_skb(data_len + NET_SKB_PAD + NET_IP_ALIGN,
+				GFP_ATOMIC | __GFP_NOWARN);
+		if (unlikely(skb == NULL)) {
+			netdev_dbg(vif->dev,
+				   "Can't allocate a skb in start_xmit.\n");
+			netbk_tx_err(vif, &txreq, idx);
+			break;
+		}
+
+		/* Packets passed to netif_rx() must have some headroom. */
+		skb_reserve(skb, NET_SKB_PAD + NET_IP_ALIGN);
+
+		if (extras[XEN_NETIF_EXTRA_TYPE_GSO - 1].type) {
+			struct xen_netif_extra_info *gso;
+			gso = &extras[XEN_NETIF_EXTRA_TYPE_GSO - 1];
+
+			if (netbk_set_skb_gso(vif, skb, gso)) {
+				kfree_skb(skb);
+				netbk_tx_err(vif, &txreq, idx);
+				continue;
+			}
+		}
+
+		/* XXX could copy straight to head */
+		page = xen_netbk_alloc_page(netbk, skb, pending_idx);
+		if (!page) {
+			kfree_skb(skb);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+
+		netbk->mmap_pages[pending_idx] = page;
+
+		gop->source.u.ref = txreq.gref;
+		gop->source.domid = vif->domid;
+		gop->source.offset = txreq.offset;
+
+		gop->dest.u.gmfn = virt_to_mfn(page_address(page));
+		gop->dest.domid = DOMID_SELF;
+		gop->dest.offset = txreq.offset;
+
+		gop->len = txreq.size;
+		gop->flags = GNTCOPY_source_gref;
+
+		gop++;
+
+		memcpy(&netbk->pending_tx_info[pending_idx].req,
+		       &txreq, sizeof(txreq));
+		netbk->pending_tx_info[pending_idx].vif = vif;
+		*((u16 *)skb->data) = pending_idx;
+
+		__skb_put(skb, data_len);
+
+		skb_shinfo(skb)->nr_frags = ret;
+		if (data_len < txreq.size) {
+			skb_shinfo(skb)->nr_frags++;
+			skb_shinfo(skb)->frags[0].page =
+				(void *)(unsigned long)pending_idx;
+		} else {
+			/* Discriminate from any valid pending_idx value. */
+			skb_shinfo(skb)->frags[0].page = (void *)~0UL;
+		}
+
+		__skb_queue_tail(&netbk->tx_queue, skb);
+
+		netbk->pending_cons++;
+
+		request_gop = xen_netbk_get_requests(netbk, vif,
+						     skb, txfrags, gop);
+		if (request_gop == NULL) {
+			kfree_skb(skb);
+			netbk_tx_err(vif, &txreq, idx);
+			continue;
+		}
+		gop = request_gop;
+
+		vif->tx.req_cons = idx;
+		xen_netbk_check_rx_xenvif(vif);
+
+		if ((gop-netbk->tx_copy_ops) >= ARRAY_SIZE(netbk->tx_copy_ops))
+			break;
+	}
+
+	return gop - netbk->tx_copy_ops;
+}
+
+static void xen_netbk_tx_submit(struct xen_netbk *netbk)
+{
+	struct gnttab_copy *gop = netbk->tx_copy_ops;
+	struct sk_buff *skb;
+
+	while ((skb = __skb_dequeue(&netbk->tx_queue)) != NULL) {
+		struct xen_netif_tx_request *txp;
+		struct xenvif *vif;
+		u16 pending_idx;
+		unsigned data_len;
+
+		pending_idx = *((u16 *)skb->data);
+		vif = netbk->pending_tx_info[pending_idx].vif;
+		txp = &netbk->pending_tx_info[pending_idx].req;
+
+		/* Check the remap error code. */
+		if (unlikely(xen_netbk_tx_check_gop(netbk, skb, &gop))) {
+			netdev_dbg(vif->dev, "netback grant failed.\n");
+			skb_shinfo(skb)->nr_frags = 0;
+			kfree_skb(skb);
+			continue;
+		}
+
+		data_len = skb->len;
+		memcpy(skb->data,
+		       (void *)(idx_to_kaddr(netbk, pending_idx)|txp->offset),
+		       data_len);
+		if (data_len < txp->size) {
+			/* Append the packet payload as a fragment. */
+			txp->offset += data_len;
+			txp->size -= data_len;
+		} else {
+			/* Schedule a response immediately. */
+			xen_netbk_idx_release(netbk, pending_idx);
+		}
+
+		if (txp->flags & XEN_NETTXF_csum_blank)
+			skb->ip_summed = CHECKSUM_PARTIAL;
+		else if (txp->flags & XEN_NETTXF_data_validated)
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+
+		xen_netbk_fill_frags(netbk, skb);
+
+		/*
+		 * If the initial fragment was < PKT_PROT_LEN then
+		 * pull through some bytes from the other fragments to
+		 * increase the linear region to PKT_PROT_LEN bytes.
+		 */
+		if (skb_headlen(skb) < PKT_PROT_LEN && skb_is_nonlinear(skb)) {
+			int target = min_t(int, skb->len, PKT_PROT_LEN);
+			__pskb_pull_tail(skb, target - skb_headlen(skb));
+		}
+
+		skb->dev      = vif->dev;
+		skb->protocol = eth_type_trans(skb, skb->dev);
+
+		if (checksum_setup(vif, skb)) {
+			netdev_dbg(vif->dev,
+				   "Can't setup checksum in net_tx_action\n");
+			kfree_skb(skb);
+			continue;
+		}
+
+		vif->dev->stats.rx_bytes += skb->len;
+		vif->dev->stats.rx_packets++;
+
+		xenvif_receive_skb(vif, skb);
+	}
+}
+
+/* Called after netfront has transmitted */
+static void xen_netbk_tx_action(struct xen_netbk *netbk)
+{
+	unsigned nr_gops;
+	int ret;
+
+	nr_gops = xen_netbk_tx_build_gops(netbk);
+
+	if (nr_gops == 0)
+		return;
+	ret = HYPERVISOR_grant_table_op(GNTTABOP_copy,
+					netbk->tx_copy_ops, nr_gops);
+	BUG_ON(ret);
+
+	xen_netbk_tx_submit(netbk);
+
+}
+
+static void xen_netbk_idx_release(struct xen_netbk *netbk, u16 pending_idx)
+{
+	struct xenvif *vif;
+	struct pending_tx_info *pending_tx_info;
+	pending_ring_idx_t index;
+
+	/* Already complete? */
+	if (netbk->mmap_pages[pending_idx] == NULL)
+		return;
+
+	pending_tx_info = &netbk->pending_tx_info[pending_idx];
+
+	vif = pending_tx_info->vif;
+
+	make_tx_response(vif, &pending_tx_info->req, XEN_NETIF_RSP_OKAY);
+
+	index = pending_index(netbk->pending_prod++);
+	netbk->pending_ring[index] = pending_idx;
+
+	xenvif_put(vif);
+
+	netbk->mmap_pages[pending_idx]->mapping = 0;
+	put_page(netbk->mmap_pages[pending_idx]);
+	netbk->mmap_pages[pending_idx] = NULL;
+}
+
+static void make_tx_response(struct xenvif *vif,
+			     struct xen_netif_tx_request *txp,
+			     s8       st)
+{
+	RING_IDX i = vif->tx.rsp_prod_pvt;
+	struct xen_netif_tx_response *resp;
+	int notify;
+
+	resp = RING_GET_RESPONSE(&vif->tx, i);
+	resp->id     = txp->id;
+	resp->status = st;
+
+	if (txp->flags & XEN_NETTXF_extra_info)
+		RING_GET_RESPONSE(&vif->tx, ++i)->status = XEN_NETIF_RSP_NULL;
+
+	vif->tx.rsp_prod_pvt = ++i;
+	RING_PUSH_RESPONSES_AND_CHECK_NOTIFY(&vif->tx, notify);
+	if (notify)
+		notify_remote_via_irq(vif->irq);
+}
+
+static struct xen_netif_rx_response *make_rx_response(struct xenvif *vif,
+					     u16      id,
+					     s8       st,
+					     u16      offset,
+					     u16      size,
+					     u16      flags)
+{
+	RING_IDX i = vif->rx.rsp_prod_pvt;
+	struct xen_netif_rx_response *resp;
+
+	resp = RING_GET_RESPONSE(&vif->rx, i);
+	resp->offset     = offset;
+	resp->flags      = flags;
+	resp->id         = id;
+	resp->status     = (s16)size;
+	if (st < 0)
+		resp->status = (s16)st;
+
+	vif->rx.rsp_prod_pvt = ++i;
+
+	return resp;
+}
+
+static inline int rx_work_todo(struct xen_netbk *netbk)
+{
+	return !skb_queue_empty(&netbk->rx_queue);
+}
+
+static inline int tx_work_todo(struct xen_netbk *netbk)
+{
+
+	if (((nr_pending_reqs(netbk) + MAX_SKB_FRAGS) < MAX_PENDING_REQS) &&
+			!list_empty(&netbk->net_schedule_list))
+		return 1;
+
+	return 0;
+}
+
+static int xen_netbk_kthread(void *data)
+{
+	struct xen_netbk *netbk = data;
+	while (!kthread_should_stop()) {
+		wait_event_interruptible(netbk->wq,
+				rx_work_todo(netbk) ||
+				tx_work_todo(netbk) ||
+				kthread_should_stop());
+		cond_resched();
+
+		if (kthread_should_stop())
+			break;
+
+		if (rx_work_todo(netbk))
+			xen_netbk_rx_action(netbk);
+
+		if (tx_work_todo(netbk))
+			xen_netbk_tx_action(netbk);
+	}
+
+	return 0;
+}
+
+void xen_netbk_unmap_frontend_rings(struct xenvif *vif)
+{
+	struct gnttab_unmap_grant_ref op;
+
+	if (vif->tx.sring) {
+		gnttab_set_unmap_op(&op, (unsigned long)vif->tx_comms_area->addr,
+				    GNTMAP_host_map, vif->tx_shmem_handle);
+
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+			BUG();
+	}
+
+	if (vif->rx.sring) {
+		gnttab_set_unmap_op(&op, (unsigned long)vif->rx_comms_area->addr,
+				    GNTMAP_host_map, vif->rx_shmem_handle);
+
+		if (HYPERVISOR_grant_table_op(GNTTABOP_unmap_grant_ref, &op, 1))
+			BUG();
+	}
+	if (vif->rx_comms_area)
+		free_vm_area(vif->rx_comms_area);
+	if (vif->tx_comms_area)
+		free_vm_area(vif->tx_comms_area);
+}
+
+int xen_netbk_map_frontend_rings(struct xenvif *vif,
+				 grant_ref_t tx_ring_ref,
+				 grant_ref_t rx_ring_ref)
+{
+	struct gnttab_map_grant_ref op;
+	struct xen_netif_tx_sring *txs;
+	struct xen_netif_rx_sring *rxs;
+
+	int err = -ENOMEM;
+
+	vif->tx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (vif->tx_comms_area == NULL)
+		goto err;
+
+	vif->rx_comms_area = alloc_vm_area(PAGE_SIZE);
+	if (vif->rx_comms_area == NULL)
+		goto err;
+
+	gnttab_set_map_op(&op, (unsigned long)vif->tx_comms_area->addr,
+			  GNTMAP_host_map, tx_ring_ref, vif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		netdev_warn(vif->dev,
+			    "failed to map tx ring. err=%d status=%d\n",
+			    err, op.status);
+		err = op.status;
+		goto err;
+	}
+
+	vif->tx_shmem_ref    = tx_ring_ref;
+	vif->tx_shmem_handle = op.handle;
+
+	txs = (struct xen_netif_tx_sring *)vif->tx_comms_area->addr;
+	BACK_RING_INIT(&vif->tx, txs, PAGE_SIZE);
+
+	gnttab_set_map_op(&op, (unsigned long)vif->rx_comms_area->addr,
+			  GNTMAP_host_map, rx_ring_ref, vif->domid);
+
+	if (HYPERVISOR_grant_table_op(GNTTABOP_map_grant_ref, &op, 1))
+		BUG();
+
+	if (op.status) {
+		netdev_warn(vif->dev,
+			    "failed to map rx ring. err=%d status=%d\n",
+			    err, op.status);
+		err = op.status;
+		goto err;
+	}
+
+	vif->rx_shmem_ref     = rx_ring_ref;
+	vif->rx_shmem_handle  = op.handle;
+	vif->rx_req_cons_peek = 0;
+
+	rxs = (struct xen_netif_rx_sring *)vif->rx_comms_area->addr;
+	BACK_RING_INIT(&vif->rx, rxs, PAGE_SIZE);
+
+	return 0;
+
+err:
+	xen_netbk_unmap_frontend_rings(vif);
+	return err;
+}
+
+static int __init netback_init(void)
+{
+	int i;
+	int rc = 0;
+	int group;
+
+	if (!xen_pv_domain())
+		return -ENODEV;
+
+	xen_netbk_group_nr = num_online_cpus();
+	xen_netbk = vzalloc(sizeof(struct xen_netbk) * xen_netbk_group_nr);
+	if (!xen_netbk) {
+		printk(KERN_ALERT "%s: out of memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	for (group = 0; group < xen_netbk_group_nr; group++) {
+		struct xen_netbk *netbk = &xen_netbk[group];
+		skb_queue_head_init(&netbk->rx_queue);
+		skb_queue_head_init(&netbk->tx_queue);
+
+		init_timer(&netbk->net_timer);
+		netbk->net_timer.data = (unsigned long)netbk;
+		netbk->net_timer.function = xen_netbk_alarm;
+
+		netbk->pending_cons = 0;
+		netbk->pending_prod = MAX_PENDING_REQS;
+		for (i = 0; i < MAX_PENDING_REQS; i++)
+			netbk->pending_ring[i] = i;
+
+		init_waitqueue_head(&netbk->wq);
+		netbk->task = kthread_create(xen_netbk_kthread,
+					     (void *)netbk,
+					     "netback/%u", group);
+
+		if (IS_ERR(netbk->task)) {
+			printk(KERN_ALERT "kthread_run() fails at netback\n");
+			del_timer(&netbk->net_timer);
+			rc = PTR_ERR(netbk->task);
+			goto failed_init;
+		}
+
+		kthread_bind(netbk->task, group);
+
+		INIT_LIST_HEAD(&netbk->net_schedule_list);
+
+		spin_lock_init(&netbk->net_schedule_list_lock);
+
+		atomic_set(&netbk->netfront_count, 0);
+
+		wake_up_process(netbk->task);
+	}
+
+	rc = xenvif_xenbus_init();
+	if (rc)
+		goto failed_init;
+
+	return 0;
+
+failed_init:
+	while (--group >= 0) {
+		struct xen_netbk *netbk = &xen_netbk[group];
+		for (i = 0; i < MAX_PENDING_REQS; i++) {
+			if (netbk->mmap_pages[i])
+				__free_page(netbk->mmap_pages[i]);
+		}
+		del_timer(&netbk->net_timer);
+		kthread_stop(netbk->task);
+	}
+	vfree(xen_netbk);
+	return rc;
+
+}
+
+module_init(netback_init);
+
+MODULE_LICENSE("Dual BSD/GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/net/xen-netback/xenbus.c linux-libre-2.6.39-gnu/drivers/net/xen-netback/xenbus.c
--- linux-libre-2.6.38-gnu/drivers/net/xen-netback/xenbus.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/net/xen-netback/xenbus.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,490 @@
+/*
+ * Xenbus code for netif backend
+ *
+ * Copyright (C) 2005 Rusty Russell <rusty@rustcorp.com.au>
+ * Copyright (C) 2005 XenSource 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
+*/
+
+#include "common.h"
+
+struct backend_info {
+	struct xenbus_device *dev;
+	struct xenvif *vif;
+	enum xenbus_state frontend_state;
+	struct xenbus_watch hotplug_status_watch;
+	int have_hotplug_status_watch:1;
+};
+
+static int connect_rings(struct backend_info *);
+static void connect(struct backend_info *);
+static void backend_create_xenvif(struct backend_info *be);
+static void unregister_hotplug_status_watch(struct backend_info *be);
+
+static int netback_remove(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	unregister_hotplug_status_watch(be);
+	if (be->vif) {
+		kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
+		xenvif_disconnect(be->vif);
+		be->vif = NULL;
+	}
+	kfree(be);
+	dev_set_drvdata(&dev->dev, NULL);
+	return 0;
+}
+
+
+/**
+ * Entry point to this code when a new device is created.  Allocate the basic
+ * structures and switch to InitWait.
+ */
+static int netback_probe(struct xenbus_device *dev,
+			 const struct xenbus_device_id *id)
+{
+	const char *message;
+	struct xenbus_transaction xbt;
+	int err;
+	int sg;
+	struct backend_info *be = kzalloc(sizeof(struct backend_info),
+					  GFP_KERNEL);
+	if (!be) {
+		xenbus_dev_fatal(dev, -ENOMEM,
+				 "allocating backend structure");
+		return -ENOMEM;
+	}
+
+	be->dev = dev;
+	dev_set_drvdata(&dev->dev, be);
+
+	sg = 1;
+
+	do {
+		err = xenbus_transaction_start(&xbt);
+		if (err) {
+			xenbus_dev_fatal(dev, err, "starting transaction");
+			goto fail;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-sg", "%d", sg);
+		if (err) {
+			message = "writing feature-sg";
+			goto abort_transaction;
+		}
+
+		err = xenbus_printf(xbt, dev->nodename, "feature-gso-tcpv4",
+				    "%d", sg);
+		if (err) {
+			message = "writing feature-gso-tcpv4";
+			goto abort_transaction;
+		}
+
+		/* We support rx-copy path. */
+		err = xenbus_printf(xbt, dev->nodename,
+				    "feature-rx-copy", "%d", 1);
+		if (err) {
+			message = "writing feature-rx-copy";
+			goto abort_transaction;
+		}
+
+		/*
+		 * We don't support rx-flip path (except old guests who don't
+		 * grok this feature flag).
+		 */
+		err = xenbus_printf(xbt, dev->nodename,
+				    "feature-rx-flip", "%d", 0);
+		if (err) {
+			message = "writing feature-rx-flip";
+			goto abort_transaction;
+		}
+
+		err = xenbus_transaction_end(xbt, 0);
+	} while (err == -EAGAIN);
+
+	if (err) {
+		xenbus_dev_fatal(dev, err, "completing transaction");
+		goto fail;
+	}
+
+	err = xenbus_switch_state(dev, XenbusStateInitWait);
+	if (err)
+		goto fail;
+
+	/* This kicks hotplug scripts, so do it immediately. */
+	backend_create_xenvif(be);
+
+	return 0;
+
+abort_transaction:
+	xenbus_transaction_end(xbt, 1);
+	xenbus_dev_fatal(dev, err, "%s", message);
+fail:
+	pr_debug("failed");
+	netback_remove(dev);
+	return err;
+}
+
+
+/*
+ * Handle the creation of the hotplug script environment.  We add the script
+ * and vif variables to the environment, for the benefit of the vif-* hotplug
+ * scripts.
+ */
+static int netback_uevent(struct xenbus_device *xdev,
+			  struct kobj_uevent_env *env)
+{
+	struct backend_info *be = dev_get_drvdata(&xdev->dev);
+	char *val;
+
+	val = xenbus_read(XBT_NIL, xdev->nodename, "script", NULL);
+	if (IS_ERR(val)) {
+		int err = PTR_ERR(val);
+		xenbus_dev_fatal(xdev, err, "reading script");
+		return err;
+	} else {
+		if (add_uevent_var(env, "script=%s", val)) {
+			kfree(val);
+			return -ENOMEM;
+		}
+		kfree(val);
+	}
+
+	if (!be || !be->vif)
+		return 0;
+
+	return add_uevent_var(env, "vif=%s", be->vif->dev->name);
+}
+
+
+static void backend_create_xenvif(struct backend_info *be)
+{
+	int err;
+	long handle;
+	struct xenbus_device *dev = be->dev;
+
+	if (be->vif != NULL)
+		return;
+
+	err = xenbus_scanf(XBT_NIL, dev->nodename, "handle", "%li", &handle);
+	if (err != 1) {
+		xenbus_dev_fatal(dev, err, "reading handle");
+		return;
+	}
+
+	be->vif = xenvif_alloc(&dev->dev, dev->otherend_id, handle);
+	if (IS_ERR(be->vif)) {
+		err = PTR_ERR(be->vif);
+		be->vif = NULL;
+		xenbus_dev_fatal(dev, err, "creating interface");
+		return;
+	}
+
+	kobject_uevent(&dev->dev.kobj, KOBJ_ONLINE);
+}
+
+
+static void disconnect_backend(struct xenbus_device *dev)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	if (be->vif) {
+		xenbus_rm(XBT_NIL, dev->nodename, "hotplug-status");
+		xenvif_disconnect(be->vif);
+		be->vif = NULL;
+	}
+}
+
+/**
+ * Callback received when the frontend's state changes.
+ */
+static void frontend_changed(struct xenbus_device *dev,
+			     enum xenbus_state frontend_state)
+{
+	struct backend_info *be = dev_get_drvdata(&dev->dev);
+
+	pr_debug("frontend state %s", xenbus_strstate(frontend_state));
+
+	be->frontend_state = frontend_state;
+
+	switch (frontend_state) {
+	case XenbusStateInitialising:
+		if (dev->state == XenbusStateClosed) {
+			printk(KERN_INFO "%s: %s: prepare for reconnect\n",
+			       __func__, dev->nodename);
+			xenbus_switch_state(dev, XenbusStateInitWait);
+		}
+		break;
+
+	case XenbusStateInitialised:
+		break;
+
+	case XenbusStateConnected:
+		if (dev->state == XenbusStateConnected)
+			break;
+		backend_create_xenvif(be);
+		if (be->vif)
+			connect(be);
+		break;
+
+	case XenbusStateClosing:
+		if (be->vif)
+			kobject_uevent(&dev->dev.kobj, KOBJ_OFFLINE);
+		disconnect_backend(dev);
+		xenbus_switch_state(dev, XenbusStateClosing);
+		break;
+
+	case XenbusStateClosed:
+		xenbus_switch_state(dev, XenbusStateClosed);
+		if (xenbus_dev_is_online(dev))
+			break;
+		/* fall through if not online */
+	case XenbusStateUnknown:
+		device_unregister(&dev->dev);
+		break;
+
+	default:
+		xenbus_dev_fatal(dev, -EINVAL, "saw state %d at frontend",
+				 frontend_state);
+		break;
+	}
+}
+
+
+static void xen_net_read_rate(struct xenbus_device *dev,
+			      unsigned long *bytes, unsigned long *usec)
+{
+	char *s, *e;
+	unsigned long b, u;
+	char *ratestr;
+
+	/* Default to unlimited bandwidth. */
+	*bytes = ~0UL;
+	*usec = 0;
+
+	ratestr = xenbus_read(XBT_NIL, dev->nodename, "rate", NULL);
+	if (IS_ERR(ratestr))
+		return;
+
+	s = ratestr;
+	b = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != ','))
+		goto fail;
+
+	s = e + 1;
+	u = simple_strtoul(s, &e, 10);
+	if ((s == e) || (*e != '\0'))
+		goto fail;
+
+	*bytes = b;
+	*usec = u;
+
+	kfree(ratestr);
+	return;
+
+ fail:
+	pr_warn("Failed to parse network rate limit. Traffic unlimited.\n");
+	kfree(ratestr);
+}
+
+static int xen_net_read_mac(struct xenbus_device *dev, u8 mac[])
+{
+	char *s, *e, *macstr;
+	int i;
+
+	macstr = s = xenbus_read(XBT_NIL, dev->nodename, "mac", NULL);
+	if (IS_ERR(macstr))
+		return PTR_ERR(macstr);
+
+	for (i = 0; i < ETH_ALEN; i++) {
+		mac[i] = simple_strtoul(s, &e, 16);
+		if ((s == e) || (*e != ((i == ETH_ALEN-1) ? '\0' : ':'))) {
+			kfree(macstr);
+			return -ENOENT;
+		}
+		s = e+1;
+	}
+
+	kfree(macstr);
+	return 0;
+}
+
+static void unregister_hotplug_status_watch(struct backend_info *be)
+{
+	if (be->have_hotplug_status_watch) {
+		unregister_xenbus_watch(&be->hotplug_status_watch);
+		kfree(be->hotplug_status_watch.node);
+	}
+	be->have_hotplug_status_watch = 0;
+}
+
+static void hotplug_status_changed(struct xenbus_watch *watch,
+				   const char **vec,
+				   unsigned int vec_size)
+{
+	struct backend_info *be = container_of(watch,
+					       struct backend_info,
+					       hotplug_status_watch);
+	char *str;
+	unsigned int len;
+
+	str = xenbus_read(XBT_NIL, be->dev->nodename, "hotplug-status", &len);
+	if (IS_ERR(str))
+		return;
+	if (len == sizeof("connected")-1 && !memcmp(str, "connected", len)) {
+		xenbus_switch_state(be->dev, XenbusStateConnected);
+		/* Not interested in this watch anymore. */
+		unregister_hotplug_status_watch(be);
+	}
+	kfree(str);
+}
+
+static void connect(struct backend_info *be)
+{
+	int err;
+	struct xenbus_device *dev = be->dev;
+
+	err = connect_rings(be);
+	if (err)
+		return;
+
+	err = xen_net_read_mac(dev, be->vif->fe_dev_addr);
+	if (err) {
+		xenbus_dev_fatal(dev, err, "parsing %s/mac", dev->nodename);
+		return;
+	}
+
+	xen_net_read_rate(dev, &be->vif->credit_bytes,
+			  &be->vif->credit_usec);
+	be->vif->remaining_credit = be->vif->credit_bytes;
+
+	unregister_hotplug_status_watch(be);
+	err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch,
+				   hotplug_status_changed,
+				   "%s/%s", dev->nodename, "hotplug-status");
+	if (err) {
+		/* Switch now, since we can't do a watch. */
+		xenbus_switch_state(dev, XenbusStateConnected);
+	} else {
+		be->have_hotplug_status_watch = 1;
+	}
+
+	netif_wake_queue(be->vif->dev);
+}
+
+
+static int connect_rings(struct backend_info *be)
+{
+	struct xenvif *vif = be->vif;
+	struct xenbus_device *dev = be->dev;
+	unsigned long tx_ring_ref, rx_ring_ref;
+	unsigned int evtchn, rx_copy;
+	int err;
+	int val;
+
+	err = xenbus_gather(XBT_NIL, dev->otherend,
+			    "tx-ring-ref", "%lu", &tx_ring_ref,
+			    "rx-ring-ref", "%lu", &rx_ring_ref,
+			    "event-channel", "%u", &evtchn, NULL);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "reading %s/ring-ref and event-channel",
+				 dev->otherend);
+		return err;
+	}
+
+	err = xenbus_scanf(XBT_NIL, dev->otherend, "request-rx-copy", "%u",
+			   &rx_copy);
+	if (err == -ENOENT) {
+		err = 0;
+		rx_copy = 0;
+	}
+	if (err < 0) {
+		xenbus_dev_fatal(dev, err, "reading %s/request-rx-copy",
+				 dev->otherend);
+		return err;
+	}
+	if (!rx_copy)
+		return -EOPNOTSUPP;
+
+	if (vif->dev->tx_queue_len != 0) {
+		if (xenbus_scanf(XBT_NIL, dev->otherend,
+				 "feature-rx-notify", "%d", &val) < 0)
+			val = 0;
+		if (val)
+			vif->can_queue = 1;
+		else
+			/* Must be non-zero for pfifo_fast to work. */
+			vif->dev->tx_queue_len = 1;
+	}
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-sg",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->can_sg = !!val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->gso = !!val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-gso-tcpv4-prefix",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->gso_prefix = !!val;
+
+	if (xenbus_scanf(XBT_NIL, dev->otherend, "feature-no-csum-offload",
+			 "%d", &val) < 0)
+		val = 0;
+	vif->csum = !val;
+
+	/* Map the shared frame, irq etc. */
+	err = xenvif_connect(vif, tx_ring_ref, rx_ring_ref, evtchn);
+	if (err) {
+		xenbus_dev_fatal(dev, err,
+				 "mapping shared-frames %lu/%lu port %u",
+				 tx_ring_ref, rx_ring_ref, evtchn);
+		return err;
+	}
+	return 0;
+}
+
+
+/* ** Driver Registration ** */
+
+
+static const struct xenbus_device_id netback_ids[] = {
+	{ "vif" },
+	{ "" }
+};
+
+
+static struct xenbus_driver netback = {
+	.name = "vif",
+	.owner = THIS_MODULE,
+	.ids = netback_ids,
+	.probe = netback_probe,
+	.remove = netback_remove,
+	.uevent = netback_uevent,
+	.otherend_changed = frontend_changed,
+};
+
+int xenvif_xenbus_init(void)
+{
+	return xenbus_register_backend(&netback);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/net/xen-netfront.c linux-libre-2.6.39-gnu/drivers/net/xen-netfront.c
--- linux-libre-2.6.38-gnu/drivers/net/xen-netfront.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/xen-netfront.c	2011-05-19 00:06:34.000000000 -0400
@@ -122,7 +122,7 @@
 	struct mmu_update rx_mmu[NET_RX_RING_SIZE];
 
 	/* Statistics */
-	int rx_gso_checksum_fixup;
+	unsigned long rx_gso_checksum_fixup;
 };
 
 struct netfront_rx_info {
@@ -359,7 +359,7 @@
 			struct xen_netif_tx_response *txrsp;
 
 			txrsp = RING_GET_RESPONSE(&np->tx, cons);
-			if (txrsp->status == NETIF_RSP_NULL)
+			if (txrsp->status == XEN_NETIF_RSP_NULL)
 				continue;
 
 			id  = txrsp->id;
@@ -416,7 +416,7 @@
 	   larger than a page), split it it into page-sized chunks. */
 	while (len > PAGE_SIZE - offset) {
 		tx->size = PAGE_SIZE - offset;
-		tx->flags |= NETTXF_more_data;
+		tx->flags |= XEN_NETTXF_more_data;
 		len -= tx->size;
 		data += tx->size;
 		offset = 0;
@@ -442,7 +442,7 @@
 	for (i = 0; i < frags; i++) {
 		skb_frag_t *frag = skb_shinfo(skb)->frags + i;
 
-		tx->flags |= NETTXF_more_data;
+		tx->flags |= XEN_NETTXF_more_data;
 
 		id = get_id_from_freelist(&np->tx_skb_freelist, np->tx_skbs);
 		np->tx_skbs[id].skb = skb_get(skb);
@@ -517,10 +517,10 @@
 	tx->flags = 0;
 	if (skb->ip_summed == CHECKSUM_PARTIAL)
 		/* local packet? */
-		tx->flags |= NETTXF_csum_blank | NETTXF_data_validated;
+		tx->flags |= XEN_NETTXF_csum_blank | XEN_NETTXF_data_validated;
 	else if (skb->ip_summed == CHECKSUM_UNNECESSARY)
 		/* remote but checksummed. */
-		tx->flags |= NETTXF_data_validated;
+		tx->flags |= XEN_NETTXF_data_validated;
 
 	if (skb_shinfo(skb)->gso_size) {
 		struct xen_netif_extra_info *gso;
@@ -531,7 +531,7 @@
 		if (extra)
 			extra->flags |= XEN_NETIF_EXTRA_FLAG_MORE;
 		else
-			tx->flags |= NETTXF_extra_info;
+			tx->flags |= XEN_NETTXF_extra_info;
 
 		gso->u.gso.size = skb_shinfo(skb)->gso_size;
 		gso->u.gso.type = XEN_NETIF_GSO_TYPE_TCPV4;
@@ -651,7 +651,7 @@
 	int err = 0;
 	unsigned long ret;
 
-	if (rx->flags & NETRXF_extra_info) {
+	if (rx->flags & XEN_NETRXF_extra_info) {
 		err = xennet_get_extras(np, extras, rp);
 		cons = np->rx.rsp_cons;
 	}
@@ -688,7 +688,7 @@
 		__skb_queue_tail(list, skb);
 
 next:
-		if (!(rx->flags & NETRXF_more_data))
+		if (!(rx->flags & XEN_NETRXF_more_data))
 			break;
 
 		if (cons + frags == rp) {
@@ -983,9 +983,9 @@
 		skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
 		skb->len += skb->data_len;
 
-		if (rx->flags & NETRXF_csum_blank)
+		if (rx->flags & XEN_NETRXF_csum_blank)
 			skb->ip_summed = CHECKSUM_PARTIAL;
-		else if (rx->flags & NETRXF_data_validated)
+		else if (rx->flags & XEN_NETRXF_data_validated)
 			skb->ip_summed = CHECKSUM_UNNECESSARY;
 
 		__skb_queue_tail(&rxq, skb);
@@ -1692,7 +1692,7 @@
 	int i;
 
 	for (i = 0; i < ARRAY_SIZE(xennet_stats); i++)
-		data[i] = *(int *)(np + xennet_stats[i].offset);
+		data[i] = *(unsigned long *)(np + xennet_stats[i].offset);
 }
 
 static void xennet_get_strings(struct net_device *dev, u32 stringset, u8 * data)
diff -druN linux-libre-2.6.38-gnu/drivers/net/xilinx_emaclite.c linux-libre-2.6.39-gnu/drivers/net/xilinx_emaclite.c
--- linux-libre-2.6.38-gnu/drivers/net/xilinx_emaclite.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/xilinx_emaclite.c	2011-05-19 00:06:34.000000000 -0400
@@ -786,7 +786,7 @@
  * @reg:	register number to write to
  * @val:	value to write to the register number specified by reg
  *
- * This fucntion waits till the device is ready to accept a new MDIO
+ * This function waits till the device is ready to accept a new MDIO
  * request and then writes the val to the MDIO Write Data register.
  */
 static int xemaclite_mdio_write(struct mii_bus *bus, int phy_id, int reg,
@@ -1101,8 +1101,7 @@
  * Return:	0, if the driver is bound to the Emaclite device, or
  *		a negative error if there is failure.
  */
-static int __devinit xemaclite_of_probe(struct platform_device *ofdev,
-					const struct of_device_id *match)
+static int __devinit xemaclite_of_probe(struct platform_device *ofdev)
 {
 	struct resource r_irq; /* Interrupt resources */
 	struct resource r_mem; /* IO mem resources */
@@ -1288,7 +1287,7 @@
 };
 MODULE_DEVICE_TABLE(of, xemaclite_of_match);
 
-static struct of_platform_driver xemaclite_of_driver = {
+static struct platform_driver xemaclite_of_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1306,7 +1305,7 @@
 static int __init xemaclite_init(void)
 {
 	/* No kernel boot options used, we just need to register the driver */
-	return of_register_platform_driver(&xemaclite_of_driver);
+	return platform_driver_register(&xemaclite_of_driver);
 }
 
 /**
@@ -1314,7 +1313,7 @@
  */
 static void __exit xemaclite_cleanup(void)
 {
-	of_unregister_platform_driver(&xemaclite_of_driver);
+	platform_driver_unregister(&xemaclite_of_driver);
 }
 
 module_init(xemaclite_init);
diff -druN linux-libre-2.6.38-gnu/drivers/net/znet.c linux-libre-2.6.39-gnu/drivers/net/znet.c
--- linux-libre-2.6.38-gnu/drivers/net/znet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/znet.c	2011-05-19 00:06:34.000000000 -0400
@@ -652,7 +652,7 @@
 					dev->stats.tx_errors++;
 
 				/* Transceiver may be stuck if cable
-				 * was removed while emiting a
+				 * was removed while emitting a
 				 * packet. Flip it off, then on to
 				 * reset it. This is very empirical,
 				 * but it seems to work. */
diff -druN linux-libre-2.6.38-gnu/drivers/net/zorro8390.c linux-libre-2.6.39-gnu/drivers/net/zorro8390.c
--- linux-libre-2.6.38-gnu/drivers/net/zorro8390.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/net/zorro8390.c	2011-05-19 00:06:34.000000000 -0400
@@ -126,7 +126,7 @@
 
     board = z->resource.start;
     ioaddr = board+cards[i].offset;
-    dev = alloc_ei_netdev();
+    dev = ____alloc_ei_netdev(0);
     if (!dev)
 	return -ENOMEM;
     if (!request_mem_region(ioaddr, NE_IO_EXTENT*2, DRV_NAME)) {
@@ -146,15 +146,15 @@
 static const struct net_device_ops zorro8390_netdev_ops = {
 	.ndo_open		= zorro8390_open,
 	.ndo_stop		= zorro8390_close,
-	.ndo_start_xmit		= ei_start_xmit,
-	.ndo_tx_timeout		= ei_tx_timeout,
-	.ndo_get_stats		= ei_get_stats,
-	.ndo_set_multicast_list = ei_set_multicast_list,
+	.ndo_start_xmit		= __ei_start_xmit,
+	.ndo_tx_timeout		= __ei_tx_timeout,
+	.ndo_get_stats		= __ei_get_stats,
+	.ndo_set_multicast_list = __ei_set_multicast_list,
 	.ndo_validate_addr	= eth_validate_addr,
 	.ndo_set_mac_address 	= eth_mac_addr,
 	.ndo_change_mtu		= eth_change_mtu,
 #ifdef CONFIG_NET_POLL_CONTROLLER
-	.ndo_poll_controller	= ei_poll,
+	.ndo_poll_controller	= __ei_poll,
 #endif
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/of/base.c linux-libre-2.6.39-gnu/drivers/of/base.c
--- linux-libre-2.6.38-gnu/drivers/of/base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/base.c	2011-05-19 00:06:34.000000000 -0400
@@ -496,6 +496,9 @@
 const struct of_device_id *of_match_node(const struct of_device_id *matches,
 					 const struct device_node *node)
 {
+	if (!matches)
+		return NULL;
+
 	while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
 		int match = 1;
 		if (matches->name[0])
diff -druN linux-libre-2.6.38-gnu/drivers/of/device.c linux-libre-2.6.39-gnu/drivers/of/device.c
--- linux-libre-2.6.38-gnu/drivers/of/device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/device.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,40 +47,6 @@
 }
 EXPORT_SYMBOL(of_dev_put);
 
-static ssize_t devspec_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct platform_device *ofdev;
-
-	ofdev = to_platform_device(dev);
-	return sprintf(buf, "%s\n", ofdev->dev.of_node->full_name);
-}
-
-static ssize_t name_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	struct platform_device *ofdev;
-
-	ofdev = to_platform_device(dev);
-	return sprintf(buf, "%s\n", ofdev->dev.of_node->name);
-}
-
-static ssize_t modalias_show(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	ssize_t len = of_device_get_modalias(dev, buf, PAGE_SIZE - 2);
-	buf[len] = '\n';
-	buf[len+1] = 0;
-	return len+1;
-}
-
-struct device_attribute of_platform_device_attrs[] = {
-	__ATTR_RO(devspec),
-	__ATTR_RO(name),
-	__ATTR_RO(modalias),
-	__ATTR_NULL
-};
-
 int of_device_add(struct platform_device *ofdev)
 {
 	BUG_ON(ofdev->dev.of_node == NULL);
diff -druN linux-libre-2.6.38-gnu/drivers/of/fdt.c linux-libre-2.6.39-gnu/drivers/of/fdt.c
--- linux-libre-2.6.38-gnu/drivers/of/fdt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/fdt.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,12 +139,13 @@
 /**
  * unflatten_dt_node - Alloc and populate a device_node from the flat tree
  * @blob: The parent device tree blob
+ * @mem: Memory chunk to use for allocating device nodes and properties
  * @p: pointer to node in flat tree
  * @dad: Parent struct device_node
  * @allnextpp: pointer to ->allnext from last allocated device_node
  * @fpsize: Size of the node path up at the current depth.
  */
-unsigned long unflatten_dt_node(struct boot_param_header *blob,
+static unsigned long unflatten_dt_node(struct boot_param_header *blob,
 				unsigned long mem,
 				unsigned long *p,
 				struct device_node *dad,
@@ -230,6 +231,7 @@
 		}
 		kref_init(&np->kref);
 	}
+	/* process properties */
 	while (1) {
 		u32 sz, noff;
 		char *pname;
@@ -351,7 +353,7 @@
  * @dt_alloc: An allocator that provides a virtual address to memory
  * for the resulting tree
  */
-void __unflatten_device_tree(struct boot_param_header *blob,
+static void __unflatten_device_tree(struct boot_param_header *blob,
 			     struct device_node **mynodes,
 			     void * (*dt_alloc)(u64 size, u64 align))
 {
@@ -674,7 +676,7 @@
 
 	early_init_dt_check_for_initrd(node);
 
-	/* Retreive command line */
+	/* Retrieve command line */
 	p = of_get_flat_dt_prop(node, "bootargs", &l);
 	if (p != NULL && l > 0)
 		strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));
diff -druN linux-libre-2.6.38-gnu/drivers/of/Kconfig linux-libre-2.6.39-gnu/drivers/of/Kconfig
--- linux-libre-2.6.38-gnu/drivers/of/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -69,4 +69,10 @@
 	help
 	  OpenFirmware MDIO bus (Ethernet PHY) accessors
 
+config OF_PCI
+	def_tristate PCI
+	depends on PCI && (PPC || MICROBLAZE || X86)
+	help
+	  OpenFirmware PCI bus accessors
+
 endmenu # OF
diff -druN linux-libre-2.6.38-gnu/drivers/of/Makefile linux-libre-2.6.39-gnu/drivers/of/Makefile
--- linux-libre-2.6.38-gnu/drivers/of/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,3 +9,4 @@
 obj-$(CONFIG_OF_NET)	+= of_net.o
 obj-$(CONFIG_OF_SPI)	+= of_spi.o
 obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
+obj-$(CONFIG_OF_PCI)	+= of_pci.o
diff -druN linux-libre-2.6.38-gnu/drivers/of/of_mdio.c linux-libre-2.6.39-gnu/drivers/of/of_mdio.c
--- linux-libre-2.6.38-gnu/drivers/of/of_mdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/of_mdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,7 @@
  * @hndlr: Link state callback for the network device
  * @iface: PHY data interface type
  *
- * Returns a pointer to the phy_device if successfull.  NULL otherwise
+ * Returns a pointer to the phy_device if successful.  NULL otherwise
  */
 struct phy_device *of_phy_connect(struct net_device *dev,
 				  struct device_node *phy_np,
diff -druN linux-libre-2.6.38-gnu/drivers/of/of_pci.c linux-libre-2.6.39-gnu/drivers/of/of_pci.c
--- linux-libre-2.6.38-gnu/drivers/of/of_pci.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/of/of_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,92 @@
+#include <linux/kernel.h>
+#include <linux/of_pci.h>
+#include <linux/of_irq.h>
+#include <asm/prom.h>
+
+/**
+ * of_irq_map_pci - Resolve the interrupt for a PCI device
+ * @pdev:       the device whose interrupt is to be resolved
+ * @out_irq:    structure of_irq filled by this function
+ *
+ * This function resolves the PCI interrupt for a given PCI device. If a
+ * device-node exists for a given pci_dev, it will use normal OF tree
+ * walking. If not, it will implement standard swizzling and walk up the
+ * PCI tree until an device-node is found, at which point it will finish
+ * resolving using the OF tree walking.
+ */
+int of_irq_map_pci(struct pci_dev *pdev, struct of_irq *out_irq)
+{
+	struct device_node *dn, *ppnode;
+	struct pci_dev *ppdev;
+	u32 lspec;
+	__be32 lspec_be;
+	__be32 laddr[3];
+	u8 pin;
+	int rc;
+
+	/* Check if we have a device node, if yes, fallback to standard
+	 * device tree parsing
+	 */
+	dn = pci_device_to_OF_node(pdev);
+	if (dn) {
+		rc = of_irq_map_one(dn, 0, out_irq);
+		if (!rc)
+			return rc;
+	}
+
+	/* Ok, we don't, time to have fun. Let's start by building up an
+	 * interrupt spec.  we assume #interrupt-cells is 1, which is standard
+	 * for PCI. If you do different, then don't use that routine.
+	 */
+	rc = pci_read_config_byte(pdev, PCI_INTERRUPT_PIN, &pin);
+	if (rc != 0)
+		return rc;
+	/* No pin, exit */
+	if (pin == 0)
+		return -ENODEV;
+
+	/* Now we walk up the PCI tree */
+	lspec = pin;
+	for (;;) {
+		/* Get the pci_dev of our parent */
+		ppdev = pdev->bus->self;
+
+		/* Ouch, it's a host bridge... */
+		if (ppdev == NULL) {
+			ppnode = pci_bus_to_OF_node(pdev->bus);
+
+			/* No node for host bridge ? give up */
+			if (ppnode == NULL)
+				return -EINVAL;
+		} else {
+			/* We found a P2P bridge, check if it has a node */
+			ppnode = pci_device_to_OF_node(ppdev);
+		}
+
+		/* Ok, we have found a parent with a device-node, hand over to
+		 * the OF parsing code.
+		 * We build a unit address from the linux device to be used for
+		 * resolution. Note that we use the linux bus number which may
+		 * not match your firmware bus numbering.
+		 * Fortunately, in most cases, interrupt-map-mask doesn't
+		 * include the bus number as part of the matching.
+		 * You should still be careful about that though if you intend
+		 * to rely on this function (you ship  a firmware that doesn't
+		 * create device nodes for all PCI devices).
+		 */
+		if (ppnode)
+			break;
+
+		/* We can only get here if we hit a P2P bridge with no node,
+		 * let's do standard swizzling and try again
+		 */
+		lspec = pci_swizzle_interrupt_pin(pdev, lspec);
+		pdev = ppdev;
+	}
+
+	lspec_be = cpu_to_be32(lspec);
+	laddr[0] = cpu_to_be32((pdev->bus->number << 16) | (pdev->devfn << 8));
+	laddr[1]  = laddr[2] = cpu_to_be32(0);
+	return of_irq_map_raw(ppnode, &lspec_be, 1, laddr, out_irq);
+}
+EXPORT_SYMBOL_GPL(of_irq_map_pci);
diff -druN linux-libre-2.6.38-gnu/drivers/of/platform.c linux-libre-2.6.39-gnu/drivers/of/platform.c
--- linux-libre-2.6.38-gnu/drivers/of/platform.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/of/platform.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,471 +42,10 @@
 }
 EXPORT_SYMBOL(of_find_device_by_node);
 
-static int platform_driver_probe_shim(struct platform_device *pdev)
-{
-	struct platform_driver *pdrv;
-	struct of_platform_driver *ofpdrv;
-	const struct of_device_id *match;
-
-	pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
-	ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
-
-	/* There is an unlikely chance that an of_platform driver might match
-	 * on a non-OF platform device.  If so, then of_match_device() will
-	 * come up empty.  Return -EINVAL in this case so other drivers get
-	 * the chance to bind. */
-	match = of_match_device(pdev->dev.driver->of_match_table, &pdev->dev);
-	return match ? ofpdrv->probe(pdev, match) : -EINVAL;
-}
-
-static void platform_driver_shutdown_shim(struct platform_device *pdev)
-{
-	struct platform_driver *pdrv;
-	struct of_platform_driver *ofpdrv;
-
-	pdrv = container_of(pdev->dev.driver, struct platform_driver, driver);
-	ofpdrv = container_of(pdrv, struct of_platform_driver, platform_driver);
-	ofpdrv->shutdown(pdev);
-}
-
-/**
- * of_register_platform_driver
- */
-int of_register_platform_driver(struct of_platform_driver *drv)
-{
-	char *of_name;
-
-	/* setup of_platform_driver to platform_driver adaptors */
-	drv->platform_driver.driver = drv->driver;
-
-	/* Prefix the driver name with 'of:' to avoid namespace collisions
-	 * and bogus matches.  There are some drivers in the tree that
-	 * register both an of_platform_driver and a platform_driver with
-	 * the same name.  This is a temporary measure until they are all
-	 * cleaned up --gcl July 29, 2010 */
-	of_name = kmalloc(strlen(drv->driver.name) + 5, GFP_KERNEL);
-	if (!of_name)
-		return -ENOMEM;
-	sprintf(of_name, "of:%s", drv->driver.name);
-	drv->platform_driver.driver.name = of_name;
-
-	if (drv->probe)
-		drv->platform_driver.probe = platform_driver_probe_shim;
-	drv->platform_driver.remove = drv->remove;
-	if (drv->shutdown)
-		drv->platform_driver.shutdown = platform_driver_shutdown_shim;
-	drv->platform_driver.suspend = drv->suspend;
-	drv->platform_driver.resume = drv->resume;
-
-	return platform_driver_register(&drv->platform_driver);
-}
-EXPORT_SYMBOL(of_register_platform_driver);
-
-void of_unregister_platform_driver(struct of_platform_driver *drv)
-{
-	platform_driver_unregister(&drv->platform_driver);
-	kfree(drv->platform_driver.driver.name);
-	drv->platform_driver.driver.name = NULL;
-}
-EXPORT_SYMBOL(of_unregister_platform_driver);
-
 #if defined(CONFIG_PPC_DCR)
 #include <asm/dcr.h>
 #endif
 
-extern struct device_attribute of_platform_device_attrs[];
-
-static int of_platform_bus_match(struct device *dev, struct device_driver *drv)
-{
-	const struct of_device_id *matches = drv->of_match_table;
-
-	if (!matches)
-		return 0;
-
-	return of_match_device(matches, dev) != NULL;
-}
-
-static int of_platform_device_probe(struct device *dev)
-{
-	int error = -ENODEV;
-	struct of_platform_driver *drv;
-	struct platform_device *of_dev;
-	const struct of_device_id *match;
-
-	drv = to_of_platform_driver(dev->driver);
-	of_dev = to_platform_device(dev);
-
-	if (!drv->probe)
-		return error;
-
-	of_dev_get(of_dev);
-
-	match = of_match_device(drv->driver.of_match_table, dev);
-	if (match)
-		error = drv->probe(of_dev, match);
-	if (error)
-		of_dev_put(of_dev);
-
-	return error;
-}
-
-static int of_platform_device_remove(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-
-	if (dev->driver && drv->remove)
-		drv->remove(of_dev);
-	return 0;
-}
-
-static void of_platform_device_shutdown(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-
-	if (dev->driver && drv->shutdown)
-		drv->shutdown(of_dev);
-}
-
-#ifdef CONFIG_PM_SLEEP
-
-static int of_platform_legacy_suspend(struct device *dev, pm_message_t mesg)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->suspend)
-		ret = drv->suspend(of_dev, mesg);
-	return ret;
-}
-
-static int of_platform_legacy_resume(struct device *dev)
-{
-	struct platform_device *of_dev = to_platform_device(dev);
-	struct of_platform_driver *drv = to_of_platform_driver(dev->driver);
-	int ret = 0;
-
-	if (dev->driver && drv->resume)
-		ret = drv->resume(of_dev);
-	return ret;
-}
-
-static int of_platform_pm_prepare(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (drv && drv->pm && drv->pm->prepare)
-		ret = drv->pm->prepare(dev);
-
-	return ret;
-}
-
-static void of_platform_pm_complete(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-
-	if (drv && drv->pm && drv->pm->complete)
-		drv->pm->complete(dev);
-}
-
-#ifdef CONFIG_SUSPEND
-
-static int of_platform_pm_suspend(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->suspend)
-			ret = drv->pm->suspend(dev);
-	} else {
-		ret = of_platform_legacy_suspend(dev, PMSG_SUSPEND);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_suspend_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->suspend_noirq)
-			ret = drv->pm->suspend_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_resume(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->resume)
-			ret = drv->pm->resume(dev);
-	} else {
-		ret = of_platform_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_resume_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->resume_noirq)
-			ret = drv->pm->resume_noirq(dev);
-	}
-
-	return ret;
-}
-
-#else /* !CONFIG_SUSPEND */
-
-#define of_platform_pm_suspend		NULL
-#define of_platform_pm_resume		NULL
-#define of_platform_pm_suspend_noirq	NULL
-#define of_platform_pm_resume_noirq	NULL
-
-#endif /* !CONFIG_SUSPEND */
-
-#ifdef CONFIG_HIBERNATION
-
-static int of_platform_pm_freeze(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->freeze)
-			ret = drv->pm->freeze(dev);
-	} else {
-		ret = of_platform_legacy_suspend(dev, PMSG_FREEZE);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_freeze_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->freeze_noirq)
-			ret = drv->pm->freeze_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_thaw(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->thaw)
-			ret = drv->pm->thaw(dev);
-	} else {
-		ret = of_platform_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_thaw_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->thaw_noirq)
-			ret = drv->pm->thaw_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_poweroff(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->poweroff)
-			ret = drv->pm->poweroff(dev);
-	} else {
-		ret = of_platform_legacy_suspend(dev, PMSG_HIBERNATE);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_poweroff_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->poweroff_noirq)
-			ret = drv->pm->poweroff_noirq(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_restore(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->restore)
-			ret = drv->pm->restore(dev);
-	} else {
-		ret = of_platform_legacy_resume(dev);
-	}
-
-	return ret;
-}
-
-static int of_platform_pm_restore_noirq(struct device *dev)
-{
-	struct device_driver *drv = dev->driver;
-	int ret = 0;
-
-	if (!drv)
-		return 0;
-
-	if (drv->pm) {
-		if (drv->pm->restore_noirq)
-			ret = drv->pm->restore_noirq(dev);
-	}
-
-	return ret;
-}
-
-#else /* !CONFIG_HIBERNATION */
-
-#define of_platform_pm_freeze		NULL
-#define of_platform_pm_thaw		NULL
-#define of_platform_pm_poweroff		NULL
-#define of_platform_pm_restore		NULL
-#define of_platform_pm_freeze_noirq	NULL
-#define of_platform_pm_thaw_noirq		NULL
-#define of_platform_pm_poweroff_noirq	NULL
-#define of_platform_pm_restore_noirq	NULL
-
-#endif /* !CONFIG_HIBERNATION */
-
-static struct dev_pm_ops of_platform_dev_pm_ops = {
-	.prepare = of_platform_pm_prepare,
-	.complete = of_platform_pm_complete,
-	.suspend = of_platform_pm_suspend,
-	.resume = of_platform_pm_resume,
-	.freeze = of_platform_pm_freeze,
-	.thaw = of_platform_pm_thaw,
-	.poweroff = of_platform_pm_poweroff,
-	.restore = of_platform_pm_restore,
-	.suspend_noirq = of_platform_pm_suspend_noirq,
-	.resume_noirq = of_platform_pm_resume_noirq,
-	.freeze_noirq = of_platform_pm_freeze_noirq,
-	.thaw_noirq = of_platform_pm_thaw_noirq,
-	.poweroff_noirq = of_platform_pm_poweroff_noirq,
-	.restore_noirq = of_platform_pm_restore_noirq,
-};
-
-#define OF_PLATFORM_PM_OPS_PTR	(&of_platform_dev_pm_ops)
-
-#else /* !CONFIG_PM_SLEEP */
-
-#define OF_PLATFORM_PM_OPS_PTR	NULL
-
-#endif /* !CONFIG_PM_SLEEP */
-
-int of_bus_type_init(struct bus_type *bus, const char *name)
-{
-	bus->name = name;
-	bus->match = of_platform_bus_match;
-	bus->probe = of_platform_device_probe;
-	bus->remove = of_platform_device_remove;
-	bus->shutdown = of_platform_device_shutdown;
-	bus->dev_attrs = of_platform_device_attrs;
-	bus->pm = OF_PLATFORM_PM_OPS_PTR;
-	return bus_register(bus);
-}
-
-int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
-{
-	/*
-	 * Temporary: of_platform_bus used to be distinct from the platform
-	 * bus.  It isn't anymore, and so drivers on the platform bus need
-	 * to be registered in a special way.
-	 *
-	 * After all of_platform_bus_type drivers are converted to
-	 * platform_drivers, this exception can be removed.
-	 */
-	if (bus == &platform_bus_type)
-		return of_register_platform_driver(drv);
-
-	/* register with core */
-	drv->driver.bus = bus;
-	return driver_register(&drv->driver);
-}
-EXPORT_SYMBOL(of_register_driver);
-
-void of_unregister_driver(struct of_platform_driver *drv)
-{
-	if (drv->driver.bus == &platform_bus_type)
-		of_unregister_platform_driver(drv);
-	else
-		driver_unregister(&drv->driver);
-}
-EXPORT_SYMBOL(of_unregister_driver);
-
 #if !defined(CONFIG_SPARC)
 /*
  * The following routines scan a subtree and registers a device for
@@ -671,13 +210,16 @@
 EXPORT_SYMBOL(of_platform_device_create);
 
 /**
- * of_platform_bus_create - Create an OF device for a bus node and all its
- * children. Optionally recursively instantiate matching busses.
+ * of_platform_bus_create() - Create a device for a node and its children.
  * @bus: device node of the bus to instantiate
- * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to
- * disallow recursive creation of child busses
+ * @matches: match table for bus nodes
+ * disallow recursive creation of child buses
+ * @parent: parent for new device, or NULL for top level.
+ *
+ * Creates a platform_device for the provided device_node, and optionally
+ * recursively create devices for all the child nodes.
  */
-static int of_platform_bus_create(const struct device_node *bus,
+static int of_platform_bus_create(struct device_node *bus,
 				  const struct of_device_id *matches,
 				  struct device *parent)
 {
@@ -685,18 +227,13 @@
 	struct platform_device *dev;
 	int rc = 0;
 
+	dev = of_platform_device_create(bus, NULL, parent);
+	if (!dev || !of_match_node(matches, bus))
+		return 0;
+
 	for_each_child_of_node(bus, child) {
 		pr_debug("   create child: %s\n", child->full_name);
-		dev = of_platform_device_create(child, NULL, parent);
-		if (dev == NULL)
-			continue;
-
-		if (!of_match_node(matches, child))
-			continue;
-		if (rc == 0) {
-			pr_debug("   and sub busses\n");
-			rc = of_platform_bus_create(child, matches, &dev->dev);
-		}
+		rc = of_platform_bus_create(child, matches, &dev->dev);
 		if (rc) {
 			of_node_put(child);
 			break;
@@ -706,9 +243,9 @@
 }
 
 /**
- * of_platform_bus_probe - Probe the device-tree for platform busses
+ * of_platform_bus_probe() - Probe the device-tree for platform buses
  * @root: parent of the first level to probe or NULL for the root of the tree
- * @matches: match table, NULL to use the default
+ * @matches: match table for bus nodes
  * @parent: parent to hook devices from, NULL for toplevel
  *
  * Note that children of the provided root are not instantiated as devices
@@ -719,50 +256,26 @@
 			  struct device *parent)
 {
 	struct device_node *child;
-	struct platform_device *dev;
 	int rc = 0;
 
-	if (WARN_ON(!matches || matches == OF_NO_DEEP_PROBE))
-		return -EINVAL;
-	if (root == NULL)
-		root = of_find_node_by_path("/");
-	else
-		of_node_get(root);
-	if (root == NULL)
+	root = root ? of_node_get(root) : of_find_node_by_path("/");
+	if (!root)
 		return -EINVAL;
 
 	pr_debug("of_platform_bus_probe()\n");
 	pr_debug(" starting at: %s\n", root->full_name);
 
-	/* Do a self check of bus type, if there's a match, create
-	 * children
-	 */
+	/* Do a self check of bus type, if there's a match, create children */
 	if (of_match_node(matches, root)) {
-		pr_debug(" root match, create all sub devices\n");
-		dev = of_platform_device_create(root, NULL, parent);
-		if (dev == NULL)
-			goto bail;
-
-		pr_debug(" create all sub busses\n");
-		rc = of_platform_bus_create(root, matches, &dev->dev);
-		goto bail;
-	}
-	for_each_child_of_node(root, child) {
+		rc = of_platform_bus_create(root, matches, parent);
+	} else for_each_child_of_node(root, child) {
 		if (!of_match_node(matches, child))
 			continue;
-
-		pr_debug("  match: %s\n", child->full_name);
-		dev = of_platform_device_create(child, NULL, parent);
-		if (dev == NULL)
-			continue;
-
-		rc = of_platform_bus_create(child, matches, &dev->dev);
-		if (rc) {
-			of_node_put(child);
+		rc = of_platform_bus_create(child, matches, parent);
+		if (rc)
 			break;
-		}
 	}
- bail:
+
 	of_node_put(root);
 	return rc;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/oprofile/cpu_buffer.c linux-libre-2.6.39-gnu/drivers/oprofile/cpu_buffer.c
--- linux-libre-2.6.38-gnu/drivers/oprofile/cpu_buffer.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/oprofile/cpu_buffer.c	2011-05-19 00:06:34.000000000 -0400
@@ -258,8 +258,10 @@
  */
 static int
 log_sample(struct oprofile_cpu_buffer *cpu_buf, unsigned long pc,
-	   unsigned long backtrace, int is_kernel, unsigned long event)
+	   unsigned long backtrace, int is_kernel, unsigned long event,
+	   struct task_struct *task)
 {
+	struct task_struct *tsk = task ? task : current;
 	cpu_buf->sample_received++;
 
 	if (pc == ESCAPE_CODE) {
@@ -267,7 +269,7 @@
 		return 0;
 	}
 
-	if (op_add_code(cpu_buf, backtrace, is_kernel, current))
+	if (op_add_code(cpu_buf, backtrace, is_kernel, tsk))
 		goto fail;
 
 	if (op_add_sample(cpu_buf, pc, event))
@@ -292,7 +294,8 @@
 
 static inline void
 __oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
-			  unsigned long event, int is_kernel)
+			  unsigned long event, int is_kernel,
+			  struct task_struct *task)
 {
 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
 	unsigned long backtrace = oprofile_backtrace_depth;
@@ -301,7 +304,7 @@
 	 * if log_sample() fail we can't backtrace since we lost the
 	 * source of this event
 	 */
-	if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event))
+	if (!log_sample(cpu_buf, pc, backtrace, is_kernel, event, task))
 		/* failed */
 		return;
 
@@ -313,10 +316,17 @@
 	oprofile_end_trace(cpu_buf);
 }
 
+void oprofile_add_ext_hw_sample(unsigned long pc, struct pt_regs * const regs,
+				unsigned long event, int is_kernel,
+				struct task_struct *task)
+{
+	__oprofile_add_ext_sample(pc, regs, event, is_kernel, task);
+}
+
 void oprofile_add_ext_sample(unsigned long pc, struct pt_regs * const regs,
 			     unsigned long event, int is_kernel)
 {
-	__oprofile_add_ext_sample(pc, regs, event, is_kernel);
+	__oprofile_add_ext_sample(pc, regs, event, is_kernel, NULL);
 }
 
 void oprofile_add_sample(struct pt_regs * const regs, unsigned long event)
@@ -332,7 +342,7 @@
 		pc = ESCAPE_CODE; /* as this causes an early return. */
 	}
 
-	__oprofile_add_ext_sample(pc, regs, event, is_kernel);
+	__oprofile_add_ext_sample(pc, regs, event, is_kernel, NULL);
 }
 
 /*
@@ -403,7 +413,7 @@
 void oprofile_add_pc(unsigned long pc, int is_kernel, unsigned long event)
 {
 	struct oprofile_cpu_buffer *cpu_buf = &__get_cpu_var(op_cpu_buffer);
-	log_sample(cpu_buf, pc, 0, is_kernel, event);
+	log_sample(cpu_buf, pc, 0, is_kernel, event, NULL);
 }
 
 void oprofile_add_trace(unsigned long pc)
diff -druN linux-libre-2.6.38-gnu/drivers/oprofile/timer_int.c linux-libre-2.6.39-gnu/drivers/oprofile/timer_int.c
--- linux-libre-2.6.38-gnu/drivers/oprofile/timer_int.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/oprofile/timer_int.c	2011-05-19 00:06:34.000000000 -0400
@@ -97,7 +97,7 @@
 	.notifier_call = oprofile_cpu_notify,
 };
 
-int __init oprofile_timer_init(struct oprofile_operations *ops)
+int oprofile_timer_init(struct oprofile_operations *ops)
 {
 	int rc;
 
@@ -113,7 +113,7 @@
 	return 0;
 }
 
-void __exit oprofile_timer_exit(void)
+void oprofile_timer_exit(void)
 {
 	unregister_hotcpu_notifier(&oprofile_cpu_notifier);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/parisc/dino.c linux-libre-2.6.39-gnu/drivers/parisc/dino.c
--- linux-libre-2.6.38-gnu/drivers/parisc/dino.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parisc/dino.c	2011-05-19 00:06:34.000000000 -0400
@@ -296,25 +296,25 @@
 	.outl	= dino_out32
 };
 
-static void dino_mask_irq(unsigned int irq)
+static void dino_mask_irq(struct irq_data *d)
 {
-	struct dino_device *dino_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
+	struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 
-	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
+	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq);
 
 	/* Clear the matching bit in the IMR register */
 	dino_dev->imr &= ~(DINO_MASK_IRQ(local_irq));
 	__raw_writel(dino_dev->imr, dino_dev->hba.base_addr+DINO_IMR);
 }
 
-static void dino_unmask_irq(unsigned int irq)
+static void dino_unmask_irq(struct irq_data *d)
 {
-	struct dino_device *dino_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
+	struct dino_device *dino_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, dino_dev->global_irq, DINO_LOCAL_IRQS);
 	u32 tmp;
 
-	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, irq);
+	DBG(KERN_WARNING "%s(0x%p, %d)\n", __func__, dino_dev, d->irq);
 
 	/*
 	** clear pending IRQ bits
@@ -346,9 +346,9 @@
 }
 
 static struct irq_chip dino_interrupt_type = {
-	.name	= "GSC-PCI",
-	.unmask	= dino_unmask_irq,
-	.mask	= dino_mask_irq,
+	.name		= "GSC-PCI",
+	.irq_unmask	= dino_unmask_irq,
+	.irq_mask	= dino_mask_irq,
 };
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/parisc/eisa.c linux-libre-2.6.39-gnu/drivers/parisc/eisa.c
--- linux-libre-2.6.38-gnu/drivers/parisc/eisa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parisc/eisa.c	2011-05-19 00:06:34.000000000 -0400
@@ -144,8 +144,9 @@
 
 
 /* called by free irq */
-static void eisa_mask_irq(unsigned int irq)
+static void eisa_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 
 	EISA_DBG("disable irq %d\n", irq);
@@ -164,8 +165,9 @@
 }
 
 /* called by request irq */
-static void eisa_unmask_irq(unsigned int irq)
+static void eisa_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	unsigned long flags;
 	EISA_DBG("enable irq %d\n", irq);
 		
@@ -183,9 +185,9 @@
 }
 
 static struct irq_chip eisa_interrupt_type = {
-	.name	=	"EISA",
-	.unmask	=	eisa_unmask_irq,
-	.mask	=	eisa_mask_irq,
+	.name		=	"EISA",
+	.irq_unmask	=	eisa_unmask_irq,
+	.irq_mask	=	eisa_mask_irq,
 };
 
 static irqreturn_t eisa_irq(int wax_irq, void *intr_dev)
@@ -338,7 +340,7 @@
 	/* Reserve IRQ2 */
 	setup_irq(2, &irq2_action);
 	for (i = 0; i < 16; i++) {
-		set_irq_chip_and_handler(i, &eisa_interrupt_type,
+		irq_set_chip_and_handler(i, &eisa_interrupt_type,
 					 handle_simple_irq);
 	}
 	
diff -druN linux-libre-2.6.38-gnu/drivers/parisc/gsc.c linux-libre-2.6.39-gnu/drivers/parisc/gsc.c
--- linux-libre-2.6.38-gnu/drivers/parisc/gsc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parisc/gsc.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,13 +105,13 @@
 	return NO_IRQ;
 }
 
-static void gsc_asic_mask_irq(unsigned int irq)
+static void gsc_asic_mask_irq(struct irq_data *d)
 {
-	struct gsc_asic *irq_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
+	struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32);
 	u32 imr;
 
-	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq,
+	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq,
 			irq_dev->name, imr);
 
 	/* Disable the IRQ line by clearing the bit in the IMR */
@@ -120,13 +120,13 @@
 	gsc_writel(imr, irq_dev->hpa + OFFSET_IMR);
 }
 
-static void gsc_asic_unmask_irq(unsigned int irq)
+static void gsc_asic_unmask_irq(struct irq_data *d)
 {
-	struct gsc_asic *irq_dev = get_irq_chip_data(irq);
-	int local_irq = gsc_find_local_irq(irq, irq_dev->global_irq, 32);
+	struct gsc_asic *irq_dev = irq_data_get_irq_chip_data(d);
+	int local_irq = gsc_find_local_irq(d->irq, irq_dev->global_irq, 32);
 	u32 imr;
 
-	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, irq,
+	DEBPRINTK(KERN_DEBUG "%s(%d) %s: IMR 0x%x\n", __func__, d->irq,
 			irq_dev->name, imr);
 
 	/* Enable the IRQ line by setting the bit in the IMR */
@@ -140,9 +140,9 @@
 }
 
 static struct irq_chip gsc_asic_interrupt_type = {
-	.name	=	"GSC-ASIC",
-	.unmask	=	gsc_asic_unmask_irq,
-	.mask	=	gsc_asic_mask_irq,
+	.name		=	"GSC-ASIC",
+	.irq_unmask	=	gsc_asic_unmask_irq,
+	.irq_mask	=	gsc_asic_mask_irq,
 };
 
 int gsc_assign_irq(struct irq_chip *type, void *data)
@@ -152,8 +152,8 @@
 	if (irq > GSC_IRQ_MAX)
 		return NO_IRQ;
 
-	set_irq_chip_and_handler(irq, type, handle_simple_irq);
-	set_irq_chip_data(irq, data);
+	irq_set_chip_and_handler(irq, type, handle_simple_irq);
+	irq_set_chip_data(irq, data);
 
 	return irq++;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/parisc/iosapic.c linux-libre-2.6.39-gnu/drivers/parisc/iosapic.c
--- linux-libre-2.6.38-gnu/drivers/parisc/iosapic.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parisc/iosapic.c	2011-05-19 00:06:34.000000000 -0400
@@ -615,10 +615,10 @@
 }
 
 
-static void iosapic_mask_irq(unsigned int irq)
+static void iosapic_mask_irq(struct irq_data *d)
 {
 	unsigned long flags;
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 	u32 d0, d1;
 
 	spin_lock_irqsave(&iosapic_lock, flags);
@@ -628,9 +628,9 @@
 	spin_unlock_irqrestore(&iosapic_lock, flags);
 }
 
-static void iosapic_unmask_irq(unsigned int irq)
+static void iosapic_unmask_irq(struct irq_data *d)
 {
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 	u32 d0, d1;
 
 	/* data is initialized by fixup_irq */
@@ -666,34 +666,34 @@
 	 * enables their IRQ. It can lead to "interesting" race conditions
 	 * in the driver initialization sequence.
 	 */
-	DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", irq,
+	DBG(KERN_DEBUG "enable_irq(%d): eoi(%p, 0x%x)\n", d->irq,
 			vi->eoi_addr, vi->eoi_data);
 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
 }
 
-static void iosapic_eoi_irq(unsigned int irq)
+static void iosapic_eoi_irq(struct irq_data *d)
 {
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 
 	iosapic_eoi(vi->eoi_addr, vi->eoi_data);
-	cpu_eoi_irq(irq);
+	cpu_eoi_irq(d);
 }
 
 #ifdef CONFIG_SMP
-static int iosapic_set_affinity_irq(unsigned int irq,
-				     const struct cpumask *dest)
+static int iosapic_set_affinity_irq(struct irq_data *d,
+				    const struct cpumask *dest, bool force)
 {
-	struct vector_info *vi = get_irq_chip_data(irq);
+	struct vector_info *vi = irq_data_get_irq_chip_data(d);
 	u32 d0, d1, dummy_d0;
 	unsigned long flags;
 	int dest_cpu;
 
-	dest_cpu = cpu_check_affinity(irq, dest);
+	dest_cpu = cpu_check_affinity(d, dest);
 	if (dest_cpu < 0)
 		return -1;
 
-	cpumask_copy(irq_desc[irq].affinity, cpumask_of(dest_cpu));
-	vi->txn_addr = txn_affinity_addr(irq, dest_cpu);
+	cpumask_copy(d->affinity, cpumask_of(dest_cpu));
+	vi->txn_addr = txn_affinity_addr(d->irq, dest_cpu);
 
 	spin_lock_irqsave(&iosapic_lock, flags);
 	/* d1 contains the destination CPU, so only want to set that
@@ -708,13 +708,13 @@
 #endif
 
 static struct irq_chip iosapic_interrupt_type = {
-	.name	=	"IO-SAPIC-level",
-	.unmask	=	iosapic_unmask_irq,
-	.mask	=	iosapic_mask_irq,
-	.ack	=	cpu_ack_irq,
-	.eoi	=	iosapic_eoi_irq,
+	.name		=	"IO-SAPIC-level",
+	.irq_unmask	=	iosapic_unmask_irq,
+	.irq_mask	=	iosapic_mask_irq,
+	.irq_ack	=	cpu_ack_irq,
+	.irq_eoi	=	iosapic_eoi_irq,
 #ifdef CONFIG_SMP
-	.set_affinity =	iosapic_set_affinity_irq,
+	.irq_set_affinity =	iosapic_set_affinity_irq,
 #endif
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/parisc/pdc_stable.c linux-libre-2.6.39-gnu/drivers/parisc/pdc_stable.c
--- linux-libre-2.6.38-gnu/drivers/parisc/pdc_stable.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parisc/pdc_stable.c	2011-05-19 00:06:34.000000000 -0400
@@ -141,7 +141,7 @@
  * @entry: A pointer to an allocated pdcspath_entry.
  * 
  * The general idea is that you don't read from the Stable Storage every time
- * you access the files provided by the facilites. We store a copy of the
+ * you access the files provided by the facilities. We store a copy of the
  * content of the stable storage WRT various paths in these structs. We read
  * these structs when reading the files, and we will write to these structs when
  * writing to the files, and only then write them back to the Stable Storage.
@@ -213,7 +213,7 @@
 
 	/* addr, devpath and count must be word aligned */
 	if (pdc_stable_write(entry->addr, devpath, sizeof(*devpath)) != PDC_OK) {
-		printk(KERN_ERR "%s: an error occured when writing to PDC.\n"
+		printk(KERN_ERR "%s: an error occurred when writing to PDC.\n"
 				"It is likely that the Stable Storage data has been corrupted.\n"
 				"Please check it carefully upon next reboot.\n", __func__);
 		WARN_ON(1);
diff -druN linux-libre-2.6.38-gnu/drivers/parisc/superio.c linux-libre-2.6.39-gnu/drivers/parisc/superio.c
--- linux-libre-2.6.38-gnu/drivers/parisc/superio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parisc/superio.c	2011-05-19 00:06:34.000000000 -0400
@@ -286,8 +286,9 @@
 }
 DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87560_LIO, superio_init);
 
-static void superio_mask_irq(unsigned int irq)
+static void superio_mask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	u8 r8;
 
 	if ((irq < 1) || (irq == 2) || (irq > 7)) {
@@ -303,8 +304,9 @@
 	outb (r8,IC_PIC1+1);
 }
 
-static void superio_unmask_irq(unsigned int irq)
+static void superio_unmask_irq(struct irq_data *d)
 {
+	unsigned int irq = d->irq;
 	u8 r8;
 
 	if ((irq < 1) || (irq == 2) || (irq > 7)) {
@@ -320,9 +322,9 @@
 }
 
 static struct irq_chip superio_interrupt_type = {
-	.name	=	SUPERIO,
-	.unmask	=	superio_unmask_irq,
-	.mask	=	superio_mask_irq,
+	.name		=	SUPERIO,
+	.irq_unmask	=	superio_unmask_irq,
+	.irq_mask	=	superio_mask_irq,
 };
 
 #ifdef DEBUG_SUPERIO_INIT
@@ -353,7 +355,8 @@
 #endif
 
 	for (i = 0; i < 16; i++) {
-		set_irq_chip_and_handler(i, &superio_interrupt_type, handle_simple_irq);
+		irq_set_chip_and_handler(i, &superio_interrupt_type,
+					 handle_simple_irq);
 	}
 
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/parport/ieee1284.c linux-libre-2.6.39-gnu/drivers/parport/ieee1284.c
--- linux-libre-2.6.38-gnu/drivers/parport/ieee1284.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parport/ieee1284.c	2011-05-19 00:06:34.000000000 -0400
@@ -355,7 +355,7 @@
 		return 0;
 	}
 
-	/* Go to compability forward idle mode */
+	/* Go to compatibility forward idle mode */
 	if (port->ieee1284.mode != IEEE1284_MODE_COMPAT)
 		parport_ieee1284_terminate (port);
 
diff -druN linux-libre-2.6.38-gnu/drivers/parport/Kconfig linux-libre-2.6.39-gnu/drivers/parport/Kconfig
--- linux-libre-2.6.38-gnu/drivers/parport/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parport/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -142,7 +142,7 @@
 	  the AX88796 network controller chip. This code is also available
 	  as a module (say M), called parport_ax88796.
 
-	  The driver is not dependant on the AX88796 network driver, and
+	  The driver is not dependent on the AX88796 network driver, and
 	  should not interfere with the networking functions of the chip.
 
 config PARPORT_1284
diff -druN linux-libre-2.6.38-gnu/drivers/parport/parport_pc.c linux-libre-2.6.39-gnu/drivers/parport/parport_pc.c
--- linux-libre-2.6.38-gnu/drivers/parport/parport_pc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parport/parport_pc.c	2011-05-19 00:06:34.000000000 -0400
@@ -1488,7 +1488,7 @@
 
 	outb(key, io);
 	outb(key, io);     /* Write Magic Sequence to EFER, extended
-			      funtion enable register */
+			      function enable register */
 	outb(0x20, io);    /* Write EFIR, extended function index register */
 	devid = inb(io + 1);  /* Read EFDR, extended function data register */
 	outb(0x21, io);
@@ -1527,7 +1527,7 @@
 	x_oldid = inb(io + 2);
 
 	outb(key, io);     /* Write Magic Byte to EFER, extended
-			      funtion enable register */
+			      function enable register */
 	outb(0x20, io + 2);  /* Write EFIR, extended function index register */
 	devid = inb(io + 2);  /* Read EFDR, extended function data register */
 	outb(0x21, io + 1);
@@ -1569,7 +1569,7 @@
 
 	outb(key, io);
 	outb(key, io);     /* Write Magic Sequence to EFER, extended
-			      funtion enable register */
+			      function enable register */
 	outb(0x0d, io);    /* Write EFIR, extended function index register */
 	oldid = inb(io + 1);  /* Read EFDR, extended function data register */
 	outb(0x0e, io);
@@ -2550,7 +2550,6 @@
 					 const struct parport_pc_via_data *via)
 {
 	short inta_addr[6] = { 0x2A0, 0x2C0, 0x220, 0x240, 0x1E0 };
-	struct resource *base_res;
 	u32 ite8872set;
 	u32 ite8872_lpt, ite8872_lpthi;
 	u8 ite8872_irq, type;
@@ -2561,8 +2560,7 @@
 
 	/* make sure which one chip */
 	for (i = 0; i < 5; i++) {
-		base_res = request_region(inta_addr[i], 32, "it887x");
-		if (base_res) {
+		if (request_region(inta_addr[i], 32, "it887x")) {
 			int test;
 			pci_write_config_dword(pdev, 0x60,
 						0xe5000000 | inta_addr[i]);
@@ -2571,7 +2569,7 @@
 			test = inb(inta_addr[i]);
 			if (test != 0xff)
 				break;
-			release_region(inta_addr[i], 0x8);
+			release_region(inta_addr[i], 32);
 		}
 	}
 	if (i >= 5) {
@@ -2635,7 +2633,7 @@
 	/*
 	 * Release the resource so that parport_pc_probe_port can get it.
 	 */
-	release_resource(base_res);
+	release_region(inta_addr[i], 32);
 	if (parport_pc_probe_port(ite8872_lpt, ite8872_lpthi,
 				   irq, PARPORT_DMA_NONE, &pdev->dev, 0)) {
 		printk(KERN_INFO
diff -druN linux-libre-2.6.38-gnu/drivers/parport/parport_sunbpp.c linux-libre-2.6.39-gnu/drivers/parport/parport_sunbpp.c
--- linux-libre-2.6.38-gnu/drivers/parport/parport_sunbpp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/parport/parport_sunbpp.c	2011-05-19 00:06:34.000000000 -0400
@@ -286,7 +286,7 @@
 	.owner		= THIS_MODULE,
 };
 
-static int __devinit bpp_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit bpp_probe(struct platform_device *op)
 {
 	struct parport_operations *ops;
 	struct bpp_regs __iomem *regs;
@@ -381,7 +381,7 @@
 
 MODULE_DEVICE_TABLE(of, bpp_match);
 
-static struct of_platform_driver bpp_sbus_driver = {
+static struct platform_driver bpp_sbus_driver = {
 	.driver = {
 		.name = "bpp",
 		.owner = THIS_MODULE,
@@ -393,12 +393,12 @@
 
 static int __init parport_sunbpp_init(void)
 {
-	return of_register_platform_driver(&bpp_sbus_driver);
+	return platform_driver_register(&bpp_sbus_driver);
 }
 
 static void __exit parport_sunbpp_exit(void)
 {
-	of_unregister_platform_driver(&bpp_sbus_driver);
+	platform_driver_unregister(&bpp_sbus_driver);
 }
 
 MODULE_AUTHOR("Derrick J Brashear");
diff -druN linux-libre-2.6.38-gnu/drivers/pci/dmar.c linux-libre-2.6.39-gnu/drivers/pci/dmar.c
--- linux-libre-2.6.38-gnu/drivers/pci/dmar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/dmar.c	2011-05-19 00:06:34.000000000 -0400
@@ -1226,7 +1226,7 @@
 
 void dmar_msi_unmask(struct irq_data *data)
 {
-	struct intel_iommu *iommu = irq_data_get_irq_data(data);
+	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
 	unsigned long flag;
 
 	/* unmask it */
@@ -1240,7 +1240,7 @@
 void dmar_msi_mask(struct irq_data *data)
 {
 	unsigned long flag;
-	struct intel_iommu *iommu = irq_data_get_irq_data(data);
+	struct intel_iommu *iommu = irq_data_get_irq_handler_data(data);
 
 	/* mask it */
 	spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1252,7 +1252,7 @@
 
 void dmar_msi_write(int irq, struct msi_msg *msg)
 {
-	struct intel_iommu *iommu = get_irq_data(irq);
+	struct intel_iommu *iommu = irq_get_handler_data(irq);
 	unsigned long flag;
 
 	spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1264,7 +1264,7 @@
 
 void dmar_msi_read(int irq, struct msi_msg *msg)
 {
-	struct intel_iommu *iommu = get_irq_data(irq);
+	struct intel_iommu *iommu = irq_get_handler_data(irq);
 	unsigned long flag;
 
 	spin_lock_irqsave(&iommu->register_lock, flag);
@@ -1382,12 +1382,12 @@
 		return -EINVAL;
 	}
 
-	set_irq_data(irq, iommu);
+	irq_set_handler_data(irq, iommu);
 	iommu->irq = irq;
 
 	ret = arch_setup_dmar_msi(irq);
 	if (ret) {
-		set_irq_data(irq, NULL);
+		irq_set_handler_data(irq, NULL);
 		iommu->irq = 0;
 		destroy_irq(irq);
 		return ret;
diff -druN linux-libre-2.6.38-gnu/drivers/pci/hotplug/acpi_pcihp.c linux-libre-2.6.39-gnu/drivers/pci/hotplug/acpi_pcihp.c
--- linux-libre-2.6.38-gnu/drivers/pci/hotplug/acpi_pcihp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/hotplug/acpi_pcihp.c	2011-05-19 00:06:34.000000000 -0400
@@ -351,7 +351,7 @@
 	 * To handle different BIOS behavior, we look for _OSC on a root
 	 * bridge preferentially (according to PCI fw spec). Later for
 	 * OSHP within the scope of the hotplug controller and its parents,
-	 * upto the host bridge under which this controller exists.
+	 * up to the host bridge under which this controller exists.
 	 */
 	handle = acpi_find_root_bridge_handle(pdev);
 	if (handle) {
diff -druN linux-libre-2.6.38-gnu/drivers/pci/hotplug/acpiphp_glue.c linux-libre-2.6.39-gnu/drivers/pci/hotplug/acpiphp_glue.c
--- linux-libre-2.6.38-gnu/drivers/pci/hotplug/acpiphp_glue.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/hotplug/acpiphp_glue.c	2011-05-19 00:06:34.000000000 -0400
@@ -212,6 +212,7 @@
 
 	pdev = pci_get_slot(pbus, PCI_DEVFN(device, function));
 	if (pdev) {
+		pdev->current_state = PCI_D0;
 		slot->flags |= (SLOT_ENABLED | SLOT_POWEREDON);
 		pci_dev_put(pdev);
 	}
@@ -584,7 +585,7 @@
 
 	/*
 	 * On root bridges with hotplug slots directly underneath (ie,
-	 * no p2p bridge inbetween), we call cleanup_bridge(). 
+	 * no p2p bridge between), we call cleanup_bridge(). 
 	 *
 	 * The else clause cleans up root bridges that either had no
 	 * hotplug slots at all, or had a p2p bridge underneath.
diff -druN linux-libre-2.6.38-gnu/drivers/pci/hotplug/rpaphp_core.c linux-libre-2.6.39-gnu/drivers/pci/hotplug/rpaphp_core.c
--- linux-libre-2.6.38-gnu/drivers/pci/hotplug/rpaphp_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/hotplug/rpaphp_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -290,7 +290,7 @@
  * @dn: device node of slot
  *
  * This subroutine will register a hotplugable slot with the
- * PCI hotplug infrastructure. This routine is typicaly called
+ * PCI hotplug infrastructure. This routine is typically called
  * during boot time, if the hotplug slots are present at boot time,
  * or is called later, by the dlpar add code, if the slot is
  * being dynamically added during runtime.
diff -druN linux-libre-2.6.38-gnu/drivers/pci/htirq.c linux-libre-2.6.39-gnu/drivers/pci/htirq.c
--- linux-libre-2.6.38-gnu/drivers/pci/htirq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/htirq.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 
 void write_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 {
-	struct ht_irq_cfg *cfg = get_irq_data(irq);
+	struct ht_irq_cfg *cfg = irq_get_handler_data(irq);
 	unsigned long flags;
 	spin_lock_irqsave(&ht_irq_lock, flags);
 	if (cfg->msg.address_lo != msg->address_lo) {
@@ -53,13 +53,13 @@
 
 void fetch_ht_irq_msg(unsigned int irq, struct ht_irq_msg *msg)
 {
-	struct ht_irq_cfg *cfg = get_irq_data(irq);
+	struct ht_irq_cfg *cfg = irq_get_handler_data(irq);
 	*msg = cfg->msg;
 }
 
 void mask_ht_irq(struct irq_data *data)
 {
-	struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+	struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data);
 	struct ht_irq_msg msg = cfg->msg;
 
 	msg.address_lo |= 1;
@@ -68,7 +68,7 @@
 
 void unmask_ht_irq(struct irq_data *data)
 {
-	struct ht_irq_cfg *cfg = irq_data_get_irq_data(data);
+	struct ht_irq_cfg *cfg = irq_data_get_irq_handler_data(data);
 	struct ht_irq_msg msg = cfg->msg;
 
 	msg.address_lo &= ~1;
@@ -126,7 +126,7 @@
 		kfree(cfg);
 		return -EBUSY;
 	}
-	set_irq_data(irq, cfg);
+	irq_set_handler_data(irq, cfg);
 
 	if (arch_setup_ht_irq(irq, dev) < 0) {
 		ht_destroy_irq(irq);
@@ -162,9 +162,9 @@
 {
 	struct ht_irq_cfg *cfg;
 
-	cfg = get_irq_data(irq);
-	set_irq_chip(irq, NULL);
-	set_irq_data(irq, NULL);
+	cfg = irq_get_handler_data(irq);
+	irq_set_chip(irq, NULL);
+	irq_set_handler_data(irq, NULL);
 	destroy_irq(irq);
 
 	kfree(cfg);
diff -druN linux-libre-2.6.38-gnu/drivers/pci/intel-iommu.c linux-libre-2.6.39-gnu/drivers/pci/intel-iommu.c
--- linux-libre-2.6.38-gnu/drivers/pci/intel-iommu.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/intel-iommu.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 #include <linux/iova.h>
 #include <linux/iommu.h>
 #include <linux/intel-iommu.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/tboot.h>
 #include <linux/dmi.h>
 #include <asm/cacheflush.h>
@@ -1206,7 +1206,7 @@
 		iommu_disable_translation(iommu);
 
 	if (iommu->irq) {
-		set_irq_data(iommu->irq, NULL);
+		irq_set_handler_data(iommu->irq, NULL);
 		/* This will mask the irq */
 		free_irq(iommu->irq, iommu);
 		destroy_irq(iommu->irq);
@@ -1299,7 +1299,7 @@
 static struct iova_domain reserved_iova_list;
 static struct lock_class_key reserved_rbtree_key;
 
-static void dmar_init_reserved_ranges(void)
+static int dmar_init_reserved_ranges(void)
 {
 	struct pci_dev *pdev = NULL;
 	struct iova *iova;
@@ -1313,8 +1313,10 @@
 	/* IOAPIC ranges shouldn't be accessed by DMA */
 	iova = reserve_iova(&reserved_iova_list, IOVA_PFN(IOAPIC_RANGE_START),
 		IOVA_PFN(IOAPIC_RANGE_END));
-	if (!iova)
+	if (!iova) {
 		printk(KERN_ERR "Reserve IOAPIC range failed\n");
+		return -ENODEV;
+	}
 
 	/* Reserve all PCI MMIO to avoid peer-to-peer access */
 	for_each_pci_dev(pdev) {
@@ -1327,11 +1329,13 @@
 			iova = reserve_iova(&reserved_iova_list,
 					    IOVA_PFN(r->start),
 					    IOVA_PFN(r->end));
-			if (!iova)
+			if (!iova) {
 				printk(KERN_ERR "Reserve iova failed\n");
+				return -ENODEV;
+			}
 		}
 	}
-
+	return 0;
 }
 
 static void domain_reserve_special_ranges(struct dmar_domain *domain)
@@ -1835,7 +1839,7 @@
 
 	ret = iommu_attach_domain(domain, iommu);
 	if (ret) {
-		domain_exit(domain);
+		free_domain_mem(domain);
 		goto error;
 	}
 
@@ -2213,7 +2217,7 @@
 	return 0;
 }
 
-int __init init_dmars(void)
+static int __init init_dmars(int force_on)
 {
 	struct dmar_drhd_unit *drhd;
 	struct dmar_rmrr_unit *rmrr;
@@ -2265,7 +2269,7 @@
 		/*
 		 * TBD:
 		 * we could share the same root & context tables
-		 * amoung all IOMMU's. Need to Split it later.
+		 * among all IOMMU's. Need to Split it later.
 		 */
 		ret = iommu_alloc_root_entry(iommu);
 		if (ret) {
@@ -2393,8 +2397,15 @@
 	 *   enable translation
 	 */
 	for_each_drhd_unit(drhd) {
-		if (drhd->ignored)
+		if (drhd->ignored) {
+			/*
+			 * we always have to disable PMRs or DMA may fail on
+			 * this device
+			 */
+			if (force_on)
+				iommu_disable_protect_mem_regions(drhd->iommu);
 			continue;
+		}
 		iommu = drhd->iommu;
 
 		iommu_flush_write_buffer(iommu);
@@ -3135,7 +3146,7 @@
 	}
 }
 
-static int iommu_suspend(struct sys_device *dev, pm_message_t state)
+static int iommu_suspend(void)
 {
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu = NULL;
@@ -3175,7 +3186,7 @@
 	return -ENOMEM;
 }
 
-static int iommu_resume(struct sys_device *dev)
+static void iommu_resume(void)
 {
 	struct dmar_drhd_unit *drhd;
 	struct intel_iommu *iommu = NULL;
@@ -3183,7 +3194,7 @@
 
 	if (init_iommu_hw()) {
 		WARN(1, "IOMMU setup failed, DMAR can not resume!\n");
-		return -EIO;
+		return;
 	}
 
 	for_each_active_iommu(iommu, drhd) {
@@ -3204,40 +3215,20 @@
 
 	for_each_active_iommu(iommu, drhd)
 		kfree(iommu->iommu_state);
-
-	return 0;
 }
 
-static struct sysdev_class iommu_sysclass = {
-	.name		= "iommu",
+static struct syscore_ops iommu_syscore_ops = {
 	.resume		= iommu_resume,
 	.suspend	= iommu_suspend,
 };
 
-static struct sys_device device_iommu = {
-	.cls	= &iommu_sysclass,
-};
-
-static int __init init_iommu_sysfs(void)
+static void __init init_iommu_pm_ops(void)
 {
-	int error;
-
-	error = sysdev_class_register(&iommu_sysclass);
-	if (error)
-		return error;
-
-	error = sysdev_register(&device_iommu);
-	if (error)
-		sysdev_class_unregister(&iommu_sysclass);
-
-	return error;
+	register_syscore_ops(&iommu_syscore_ops);
 }
 
 #else
-static int __init init_iommu_sysfs(void)
-{
-	return 0;
-}
+static inline int init_iommu_pm_ops(void) { }
 #endif	/* CONFIG_PM */
 
 /*
@@ -3260,9 +3251,15 @@
 	if (!domain)
 		return 0;
 
-	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through)
+	if (action == BUS_NOTIFY_UNBOUND_DRIVER && !iommu_pass_through) {
 		domain_remove_one_dev_info(domain, pdev);
 
+		if (!(domain->flags & DOMAIN_FLAG_VIRTUAL_MACHINE) &&
+		    !(domain->flags & DOMAIN_FLAG_STATIC_IDENTITY) &&
+		    list_empty(&domain->devices))
+			domain_exit(domain);
+	}
+
 	return 0;
 }
 
@@ -3297,12 +3294,21 @@
 	if (no_iommu || dmar_disabled)
 		return -ENODEV;
 
-	iommu_init_mempool();
-	dmar_init_reserved_ranges();
+	if (iommu_init_mempool()) {
+		if (force_on)
+			panic("tboot: Failed to initialize iommu memory\n");
+		return 	-ENODEV;
+	}
+
+	if (dmar_init_reserved_ranges()) {
+		if (force_on)
+			panic("tboot: Failed to reserve iommu ranges\n");
+		return 	-ENODEV;
+	}
 
 	init_no_remapping_devices();
 
-	ret = init_dmars();
+	ret = init_dmars(force_on);
 	if (ret) {
 		if (force_on)
 			panic("tboot: Failed to initialize DMARs\n");
@@ -3320,7 +3326,7 @@
 #endif
 	dma_ops = &intel_dma_ops;
 
-	init_iommu_sysfs();
+	init_iommu_pm_ops();
 
 	register_iommu(&intel_iommu_ops);
 
@@ -3411,6 +3417,11 @@
 		domain->iommu_count--;
 		domain_update_iommu_cap(domain);
 		spin_unlock_irqrestore(&domain->iommu_lock, tmp_flags);
+
+		spin_lock_irqsave(&iommu->lock, tmp_flags);
+		clear_bit(domain->id, iommu->domain_ids);
+		iommu->domains[domain->id] = NULL;
+		spin_unlock_irqrestore(&iommu->lock, tmp_flags);
 	}
 
 	spin_unlock_irqrestore(&device_domain_lock, flags);
@@ -3627,9 +3638,9 @@
 
 		pte = dmar_domain->pgd;
 		if (dma_pte_present(pte)) {
-			free_pgtable_page(dmar_domain->pgd);
 			dmar_domain->pgd = (struct dma_pte *)
 				phys_to_virt(dma_pte_addr(pte));
+			free_pgtable_page(pte);
 		}
 		dmar_domain->agaw--;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/pci/intr_remapping.c linux-libre-2.6.39-gnu/drivers/pci/intr_remapping.c
--- linux-libre-2.6.38-gnu/drivers/pci/intr_remapping.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/intr_remapping.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 
 static struct irq_2_iommu *irq_2_iommu(unsigned int irq)
 {
-	struct irq_cfg *cfg = get_irq_chip_data(irq);
+	struct irq_cfg *cfg = irq_get_chip_data(irq);
 	return cfg ? &cfg->irq_2_iommu : NULL;
 }
 
@@ -289,7 +289,7 @@
  * source validation type
  */
 #define SVT_NO_VERIFY		0x0  /* no verification is required */
-#define SVT_VERIFY_SID_SQ	0x1  /* verify using SID and SQ fiels */
+#define SVT_VERIFY_SID_SQ	0x1  /* verify using SID and SQ fields */
 #define SVT_VERIFY_BUS		0x2  /* verify bus of request-id */
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/pci/iova.c linux-libre-2.6.39-gnu/drivers/pci/iova.c
--- linux-libre-2.6.38-gnu/drivers/pci/iova.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/iova.c	2011-05-19 00:06:34.000000000 -0400
@@ -391,7 +391,7 @@
 				break;
 	}
 
-	/* We are here either becasue this is the first reserver node
+	/* We are here either because this is the first reserver node
 	 * or need to insert remaining non overlap addr range
 	 */
 	iova = __insert_new_range(iovad, pfn_lo, pfn_hi);
diff -druN linux-libre-2.6.38-gnu/drivers/pci/Kconfig linux-libre-2.6.39-gnu/drivers/pci/Kconfig
--- linux-libre-2.6.38-gnu/drivers/pci/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -87,3 +87,7 @@
 	depends on ACPI
 	depends on HOTPLUG
 	default y
+
+config PCI_LABEL
+	def_bool y if (DMI || ACPI)
+	select NLS
diff -druN linux-libre-2.6.38-gnu/drivers/pci/Makefile linux-libre-2.6.39-gnu/drivers/pci/Makefile
--- linux-libre-2.6.38-gnu/drivers/pci/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -42,6 +42,7 @@
 obj-$(CONFIG_X86) += setup-bus.o
 obj-$(CONFIG_ALPHA) += setup-bus.o setup-irq.o
 obj-$(CONFIG_ARM) += setup-bus.o setup-irq.o
+obj-$(CONFIG_UNICORE32) += setup-bus.o setup-irq.o
 obj-$(CONFIG_PARISC) += setup-bus.o
 obj-$(CONFIG_SUPERH) += setup-bus.o setup-irq.o
 obj-$(CONFIG_PPC) += setup-bus.o
@@ -53,11 +54,12 @@
 
 #
 # ACPI Related PCI FW Functions
+# ACPI _DSM provided firmware instance and string name
 #
 obj-$(CONFIG_ACPI)    += pci-acpi.o
 
 # SMBIOS provided firmware instance and labels
-obj-$(CONFIG_DMI)    += pci-label.o
+obj-$(CONFIG_PCI_LABEL) += pci-label.o
 
 # Cardbus & CompactPCI use setup-bus
 obj-$(CONFIG_HOTPLUG) += setup-bus.o
diff -druN linux-libre-2.6.38-gnu/drivers/pci/msi.c linux-libre-2.6.39-gnu/drivers/pci/msi.c
--- linux-libre-2.6.38-gnu/drivers/pci/msi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/msi.c	2011-05-19 00:06:34.000000000 -0400
@@ -236,7 +236,7 @@
 
 void read_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-	struct msi_desc *entry = get_irq_msi(irq);
+	struct msi_desc *entry = irq_get_msi_desc(irq);
 
 	__read_msi_msg(entry, msg);
 }
@@ -253,7 +253,7 @@
 
 void get_cached_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-	struct msi_desc *entry = get_irq_msi(irq);
+	struct msi_desc *entry = irq_get_msi_desc(irq);
 
 	__get_cached_msi_msg(entry, msg);
 }
@@ -297,7 +297,7 @@
 
 void write_msi_msg(unsigned int irq, struct msi_msg *msg)
 {
-	struct msi_desc *entry = get_irq_msi(irq);
+	struct msi_desc *entry = irq_get_msi_desc(irq);
 
 	__write_msi_msg(entry, msg);
 }
@@ -354,7 +354,7 @@
 	if (!dev->msi_enabled)
 		return;
 
-	entry = get_irq_msi(dev->irq);
+	entry = irq_get_msi_desc(dev->irq);
 	pos = entry->msi_attrib.pos;
 
 	pci_intx_for_msi(dev, 0);
@@ -519,7 +519,7 @@
 						PCI_MSIX_ENTRY_VECTOR_CTRL;
 
 		entries[i].vector = entry->irq;
-		set_irq_msi(entry->irq, entry);
+		irq_set_msi_desc(entry->irq, entry);
 		entry->masked = readl(entry->mask_base + offset);
 		msix_mask_irq(entry, 1);
 		i++;
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci-acpi.c linux-libre-2.6.39-gnu/drivers/pci/pci-acpi.c
--- linux-libre-2.6.38-gnu/drivers/pci/pci-acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pci-acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -293,19 +293,11 @@
 	}
 
 	if (enable) {
-		if (!dev->wakeup.run_wake_count++) {
-			acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
-			acpi_enable_gpe(dev->wakeup.gpe_device,
-					dev->wakeup.gpe_number);
-		}
-	} else if (dev->wakeup.run_wake_count > 0) {
-		if (!--dev->wakeup.run_wake_count) {
-			acpi_disable_gpe(dev->wakeup.gpe_device,
-					 dev->wakeup.gpe_number);
-			acpi_disable_wakeup_device_power(dev);
-		}
+		acpi_enable_wakeup_device_power(dev, ACPI_STATE_S0);
+		acpi_enable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
 	} else {
-		error = -EALREADY;
+		acpi_disable_gpe(dev->wakeup.gpe_device, dev->wakeup.gpe_number);
+		acpi_disable_wakeup_device_power(dev);
 	}
 
 	return error;
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci.c linux-libre-2.6.39-gnu/drivers/pci/pci.c
--- linux-libre-2.6.38-gnu/drivers/pci/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -740,6 +740,12 @@
 
 	if (!__pci_complete_power_transition(dev, state))
 		error = 0;
+	/*
+	 * When aspm_policy is "powersave" this call ensures
+	 * that ASPM is configured.
+	 */
+	if (!error && dev->bus->self)
+		pcie_aspm_powersave_config_link(dev->bus->self);
 
 	return error;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci-driver.c linux-libre-2.6.39-gnu/drivers/pci/pci-driver.c
--- linux-libre-2.6.38-gnu/drivers/pci/pci-driver.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pci-driver.c	2011-05-19 00:06:34.000000000 -0400
@@ -431,7 +431,7 @@
 	pci_msix_shutdown(pci_dev);
 }
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 
 /* Auxiliary functions used for system resume and run-time resume. */
 
@@ -781,7 +781,7 @@
 
 #endif /* !CONFIG_SUSPEND */
 
-#ifdef CONFIG_HIBERNATION
+#ifdef CONFIG_HIBERNATE_CALLBACKS
 
 static int pci_pm_freeze(struct device *dev)
 {
@@ -970,7 +970,7 @@
 	return error;
 }
 
-#else /* !CONFIG_HIBERNATION */
+#else /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #define pci_pm_freeze		NULL
 #define pci_pm_freeze_noirq	NULL
@@ -981,7 +981,7 @@
 #define pci_pm_restore		NULL
 #define pci_pm_restore_noirq	NULL
 
-#endif /* !CONFIG_HIBERNATION */
+#endif /* !CONFIG_HIBERNATE_CALLBACKS */
 
 #ifdef CONFIG_PM_RUNTIME
 
@@ -1059,7 +1059,7 @@
 
 #endif /* !CONFIG_PM_RUNTIME */
 
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 
 const struct dev_pm_ops pci_dev_pm_ops = {
 	.prepare = pci_pm_prepare,
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c linux-libre-2.6.39-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c
--- linux-libre-2.6.38-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pcie/aer/aerdrv_errprint.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,6 +19,7 @@
 #include <linux/errno.h>
 #include <linux/pm.h>
 #include <linux/suspend.h>
+#include <linux/cper.h>
 
 #include "aerdrv.h"
 
@@ -57,86 +58,44 @@
 	(e & AER_DATA_LINK_LAYER_ERROR_MASK(t)) ? AER_DATA_LINK_LAYER_ERROR : \
 	AER_TRANSACTION_LAYER_ERROR)
 
-#define AER_PR(info, pdev, fmt, args...)				\
-	printk("%s%s %s: " fmt, (info->severity == AER_CORRECTABLE) ?	\
-		KERN_WARNING : KERN_ERR, dev_driver_string(&pdev->dev),	\
-		dev_name(&pdev->dev), ## args)
-
 /*
  * AER error strings
  */
-static char *aer_error_severity_string[] = {
+static const char *aer_error_severity_string[] = {
 	"Uncorrected (Non-Fatal)",
 	"Uncorrected (Fatal)",
 	"Corrected"
 };
 
-static char *aer_error_layer[] = {
+static const char *aer_error_layer[] = {
 	"Physical Layer",
 	"Data Link Layer",
 	"Transaction Layer"
 };
-static char *aer_correctable_error_string[] = {
-	"Receiver Error        ",	/* Bit Position 0	*/
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Bad TLP               ",	/* Bit Position 6	*/
-	"Bad DLLP              ",	/* Bit Position 7	*/
-	"RELAY_NUM Rollover    ",	/* Bit Position 8	*/
-	NULL,
-	NULL,
-	NULL,
-	"Replay Timer Timeout  ",	/* Bit Position 12	*/
-	"Advisory Non-Fatal    ",	/* Bit Position 13	*/
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
+
+static const char *aer_correctable_error_string[] = {
+	"Receiver Error",		/* Bit Position 0	*/
 	NULL,
 	NULL,
 	NULL,
 	NULL,
 	NULL,
+	"Bad TLP",			/* Bit Position 6	*/
+	"Bad DLLP",			/* Bit Position 7	*/
+	"RELAY_NUM Rollover",		/* Bit Position 8	*/
 	NULL,
 	NULL,
 	NULL,
+	"Replay Timer Timeout",		/* Bit Position 12	*/
+	"Advisory Non-Fatal",		/* Bit Position 13	*/
 };
 
-static char *aer_uncorrectable_error_string[] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Data Link Protocol    ",	/* Bit Position 4	*/
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	"Poisoned TLP          ",	/* Bit Position 12	*/
-	"Flow Control Protocol ",	/* Bit Position 13	*/
-	"Completion Timeout    ",	/* Bit Position 14	*/
-	"Completer Abort       ",	/* Bit Position 15	*/
-	"Unexpected Completion ",	/* Bit Position 16	*/
-	"Receiver Overflow     ",	/* Bit Position 17	*/
-	"Malformed TLP         ",	/* Bit Position 18	*/
-	"ECRC                  ",	/* Bit Position 19	*/
-	"Unsupported Request   ",	/* Bit Position 20	*/
+static const char *aer_uncorrectable_error_string[] = {
 	NULL,
 	NULL,
 	NULL,
 	NULL,
+	"Data Link Protocol",		/* Bit Position 4	*/
 	NULL,
 	NULL,
 	NULL,
@@ -144,19 +103,29 @@
 	NULL,
 	NULL,
 	NULL,
+	"Poisoned TLP",			/* Bit Position 12	*/
+	"Flow Control Protocol",	/* Bit Position 13	*/
+	"Completion Timeout",		/* Bit Position 14	*/
+	"Completer Abort",		/* Bit Position 15	*/
+	"Unexpected Completion",	/* Bit Position 16	*/
+	"Receiver Overflow",		/* Bit Position 17	*/
+	"Malformed TLP",		/* Bit Position 18	*/
+	"ECRC",				/* Bit Position 19	*/
+	"Unsupported Request",		/* Bit Position 20	*/
 };
 
-static char *aer_agent_string[] = {
+static const char *aer_agent_string[] = {
 	"Receiver ID",
 	"Requester ID",
 	"Completer ID",
 	"Transmitter ID"
 };
 
-static void __aer_print_error(struct aer_err_info *info, struct pci_dev *dev)
+static void __aer_print_error(const char *prefix,
+			      struct aer_err_info *info)
 {
 	int i, status;
-	char *errmsg = NULL;
+	const char *errmsg = NULL;
 
 	status = (info->status & ~info->mask);
 
@@ -165,15 +134,17 @@
 			continue;
 
 		if (info->severity == AER_CORRECTABLE)
-			errmsg = aer_correctable_error_string[i];
+			errmsg = i < ARRAY_SIZE(aer_correctable_error_string) ?
+				aer_correctable_error_string[i] : NULL;
 		else
-			errmsg = aer_uncorrectable_error_string[i];
+			errmsg = i < ARRAY_SIZE(aer_uncorrectable_error_string) ?
+				aer_uncorrectable_error_string[i] : NULL;
 
 		if (errmsg)
-			AER_PR(info, dev, "   [%2d] %s%s\n", i, errmsg,
+			printk("%s""   [%2d] %-22s%s\n", prefix, i, errmsg,
 				info->first_error == i ? " (First)" : "");
 		else
-			AER_PR(info, dev, "   [%2d] Unknown Error Bit%s\n", i,
+			printk("%s""   [%2d] Unknown Error Bit%s\n", prefix, i,
 				info->first_error == i ? " (First)" : "");
 	}
 }
@@ -181,11 +152,15 @@
 void aer_print_error(struct pci_dev *dev, struct aer_err_info *info)
 {
 	int id = ((dev->bus->number << 8) | dev->devfn);
+	char prefix[44];
+
+	snprintf(prefix, sizeof(prefix), "%s%s %s: ",
+		 (info->severity == AER_CORRECTABLE) ? KERN_WARNING : KERN_ERR,
+		 dev_driver_string(&dev->dev), dev_name(&dev->dev));
 
 	if (info->status == 0) {
-		AER_PR(info, dev,
-			"PCIe Bus Error: severity=%s, type=Unaccessible, "
-			"id=%04x(Unregistered Agent ID)\n",
+		printk("%s""PCIe Bus Error: severity=%s, type=Unaccessible, "
+			"id=%04x(Unregistered Agent ID)\n", prefix,
 			aer_error_severity_string[info->severity], id);
 	} else {
 		int layer, agent;
@@ -193,23 +168,22 @@
 		layer = AER_GET_LAYER_ERROR(info->severity, info->status);
 		agent = AER_GET_AGENT(info->severity, info->status);
 
-		AER_PR(info, dev,
-			"PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
-			aer_error_severity_string[info->severity],
+		printk("%s""PCIe Bus Error: severity=%s, type=%s, id=%04x(%s)\n",
+			prefix, aer_error_severity_string[info->severity],
 			aer_error_layer[layer], id, aer_agent_string[agent]);
 
-		AER_PR(info, dev,
-			"  device [%04x:%04x] error status/mask=%08x/%08x\n",
-			dev->vendor, dev->device, info->status, info->mask);
+		printk("%s""  device [%04x:%04x] error status/mask=%08x/%08x\n",
+			prefix, dev->vendor, dev->device,
+			info->status, info->mask);
 
-		__aer_print_error(info, dev);
+		__aer_print_error(prefix, info);
 
 		if (info->tlp_header_valid) {
 			unsigned char *tlp = (unsigned char *) &info->tlp;
-			AER_PR(info, dev, "  TLP Header:"
+			printk("%s""  TLP Header:"
 				" %02x%02x%02x%02x %02x%02x%02x%02x"
 				" %02x%02x%02x%02x %02x%02x%02x%02x\n",
-				*(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+				prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
 				*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
 				*(tlp + 11), *(tlp + 10), *(tlp + 9),
 				*(tlp + 8), *(tlp + 15), *(tlp + 14),
@@ -218,8 +192,8 @@
 	}
 
 	if (info->id && info->error_dev_num > 1 && info->id == id)
-		AER_PR(info, dev,
-			"  Error of this Agent(%04x) is reported first\n", id);
+		printk("%s""  Error of this Agent(%04x) is reported first\n",
+			prefix, id);
 }
 
 void aer_print_port_info(struct pci_dev *dev, struct aer_err_info *info)
@@ -228,3 +202,61 @@
 		info->multi_error_valid ? "Multiple " : "",
 		aer_error_severity_string[info->severity], info->id);
 }
+
+#ifdef CONFIG_ACPI_APEI_PCIEAER
+static int cper_severity_to_aer(int cper_severity)
+{
+	switch (cper_severity) {
+	case CPER_SEV_RECOVERABLE:
+		return AER_NONFATAL;
+	case CPER_SEV_FATAL:
+		return AER_FATAL;
+	default:
+		return AER_CORRECTABLE;
+	}
+}
+
+void cper_print_aer(const char *prefix, int cper_severity,
+		    struct aer_capability_regs *aer)
+{
+	int aer_severity, layer, agent, status_strs_size, tlp_header_valid = 0;
+	u32 status, mask;
+	const char **status_strs;
+
+	aer_severity = cper_severity_to_aer(cper_severity);
+	if (aer_severity == AER_CORRECTABLE) {
+		status = aer->cor_status;
+		mask = aer->cor_mask;
+		status_strs = aer_correctable_error_string;
+		status_strs_size = ARRAY_SIZE(aer_correctable_error_string);
+	} else {
+		status = aer->uncor_status;
+		mask = aer->uncor_mask;
+		status_strs = aer_uncorrectable_error_string;
+		status_strs_size = ARRAY_SIZE(aer_uncorrectable_error_string);
+		tlp_header_valid = status & AER_LOG_TLP_MASKS;
+	}
+	layer = AER_GET_LAYER_ERROR(aer_severity, status);
+	agent = AER_GET_AGENT(aer_severity, status);
+	printk("%s""aer_status: 0x%08x, aer_mask: 0x%08x\n",
+	       prefix, status, mask);
+	cper_print_bits(prefix, status, status_strs, status_strs_size);
+	printk("%s""aer_layer=%s, aer_agent=%s\n", prefix,
+	       aer_error_layer[layer], aer_agent_string[agent]);
+	if (aer_severity != AER_CORRECTABLE)
+		printk("%s""aer_uncor_severity: 0x%08x\n",
+		       prefix, aer->uncor_severity);
+	if (tlp_header_valid) {
+		const unsigned char *tlp;
+		tlp = (const unsigned char *)&aer->header_log;
+		printk("%s""aer_tlp_header:"
+			" %02x%02x%02x%02x %02x%02x%02x%02x"
+			" %02x%02x%02x%02x %02x%02x%02x%02x\n",
+			prefix, *(tlp + 3), *(tlp + 2), *(tlp + 1), *tlp,
+			*(tlp + 7), *(tlp + 6), *(tlp + 5), *(tlp + 4),
+			*(tlp + 11), *(tlp + 10), *(tlp + 9),
+			*(tlp + 8), *(tlp + 15), *(tlp + 14),
+			*(tlp + 13), *(tlp + 12));
+	}
+}
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pcie/aer/aerdrv.h linux-libre-2.6.39-gnu/drivers/pci/pcie/aer/aerdrv.h
--- linux-libre-2.6.38-gnu/drivers/pci/pcie/aer/aerdrv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pcie/aer/aerdrv.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,13 +35,6 @@
 					PCI_ERR_UNC_UNX_COMP|		\
 					PCI_ERR_UNC_MALF_TLP)
 
-struct header_log_regs {
-	unsigned int dw0;
-	unsigned int dw1;
-	unsigned int dw2;
-	unsigned int dw3;
-};
-
 #define AER_MAX_MULTI_ERR_DEVICES	5	/* Not likely to have more */
 struct aer_err_info {
 	struct pci_dev *dev[AER_MAX_MULTI_ERR_DEVICES];
@@ -59,7 +52,7 @@
 
 	unsigned int status;		/* COR/UNCOR Error Status */
 	unsigned int mask;		/* COR/UNCOR Error Mask */
-	struct header_log_regs tlp;	/* TLP Header */
+	struct aer_header_log_regs tlp;	/* TLP Header */
 };
 
 struct aer_err_source {
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pcie/aer/aer_inject.c linux-libre-2.6.39-gnu/drivers/pci/pcie/aer/aer_inject.c
--- linux-libre-2.6.38-gnu/drivers/pci/pcie/aer/aer_inject.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pcie/aer/aer_inject.c	2011-05-19 00:06:34.000000000 -0400
@@ -27,6 +27,10 @@
 #include <linux/stddef.h>
 #include "aerdrv.h"
 
+/* Override the existing corrected and uncorrected error masks */
+static int aer_mask_override;
+module_param(aer_mask_override, bool, 0);
+
 struct aer_error_inj {
 	u8 bus;
 	u8 dev;
@@ -322,7 +326,7 @@
 	unsigned long flags;
 	unsigned int devfn = PCI_DEVFN(einj->dev, einj->fn);
 	int pos_cap_err, rp_pos_cap_err;
-	u32 sever, cor_mask, uncor_mask;
+	u32 sever, cor_mask, uncor_mask, cor_mask_orig, uncor_mask_orig;
 	int ret = 0;
 
 	dev = pci_get_domain_bus_and_slot((int)einj->domain, einj->bus, devfn);
@@ -361,6 +365,18 @@
 		goto out_put;
 	}
 
+	if (aer_mask_override) {
+		cor_mask_orig = cor_mask;
+		cor_mask &= !(einj->cor_status);
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
+				       cor_mask);
+
+		uncor_mask_orig = uncor_mask;
+		uncor_mask &= !(einj->uncor_status);
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
+				       uncor_mask);
+	}
+
 	spin_lock_irqsave(&inject_lock, flags);
 
 	err = __find_aer_error_by_dev(dev);
@@ -378,14 +394,16 @@
 	err->header_log2 = einj->header_log2;
 	err->header_log3 = einj->header_log3;
 
-	if (einj->cor_status && !(einj->cor_status & ~cor_mask)) {
+	if (!aer_mask_override && einj->cor_status &&
+	    !(einj->cor_status & ~cor_mask)) {
 		ret = -EINVAL;
 		printk(KERN_WARNING "The correctable error(s) is masked "
 				"by device\n");
 		spin_unlock_irqrestore(&inject_lock, flags);
 		goto out_put;
 	}
-	if (einj->uncor_status && !(einj->uncor_status & ~uncor_mask)) {
+	if (!aer_mask_override && einj->uncor_status &&
+	    !(einj->uncor_status & ~uncor_mask)) {
 		ret = -EINVAL;
 		printk(KERN_WARNING "The uncorrectable error(s) is masked "
 				"by device\n");
@@ -425,6 +443,13 @@
 	}
 	spin_unlock_irqrestore(&inject_lock, flags);
 
+	if (aer_mask_override) {
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_COR_MASK,
+				       cor_mask_orig);
+		pci_write_config_dword(dev, pos_cap_err + PCI_ERR_UNCOR_MASK,
+				       uncor_mask_orig);
+	}
+
 	ret = pci_bus_set_aer_ops(dev->bus);
 	if (ret)
 		goto out_put;
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pcie/aspm.c linux-libre-2.6.39-gnu/drivers/pci/pcie/aspm.c
--- linux-libre-2.6.38-gnu/drivers/pci/pcie/aspm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pcie/aspm.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,6 +69,7 @@
 };
 
 static int aspm_disabled, aspm_force, aspm_clear_state;
+static bool aspm_support_enabled = true;
 static DEFINE_MUTEX(aspm_lock);
 static LIST_HEAD(link_list);
 
@@ -707,6 +708,28 @@
 	up_read(&pci_bus_sem);
 }
 
+void pcie_aspm_powersave_config_link(struct pci_dev *pdev)
+{
+	struct pcie_link_state *link = pdev->link_state;
+
+	if (aspm_disabled || !pci_is_pcie(pdev) || !link)
+		return;
+
+	if (aspm_policy != POLICY_POWERSAVE)
+		return;
+
+	if ((pdev->pcie_type != PCI_EXP_TYPE_ROOT_PORT) &&
+	    (pdev->pcie_type != PCI_EXP_TYPE_DOWNSTREAM))
+		return;
+
+	down_read(&pci_bus_sem);
+	mutex_lock(&aspm_lock);
+	pcie_config_aspm_path(link);
+	pcie_set_clkpm(link, policy_to_clkpm_state(link));
+	mutex_unlock(&aspm_lock);
+	up_read(&pci_bus_sem);
+}
+
 /*
  * pci_disable_link_state - disable pci device's link state, so the link will
  * never enter specific states
@@ -747,6 +770,8 @@
 	int i;
 	struct pcie_link_state *link;
 
+	if (aspm_disabled)
+		return -EPERM;
 	for (i = 0; i < ARRAY_SIZE(policy_str); i++)
 		if (!strncmp(val, policy_str[i], strlen(policy_str[i])))
 			break;
@@ -801,6 +826,8 @@
 	struct pcie_link_state *link, *root = pdev->link_state->root;
 	u32 val = buf[0] - '0', state = 0;
 
+	if (aspm_disabled)
+		return -EPERM;
 	if (n < 1 || val > 3)
 		return -EINVAL;
 
@@ -896,6 +923,7 @@
 {
 	if (!strcmp(str, "off")) {
 		aspm_disabled = 1;
+		aspm_support_enabled = false;
 		printk(KERN_INFO "PCIe ASPM is disabled\n");
 	} else if (!strcmp(str, "force")) {
 		aspm_force = 1;
@@ -930,3 +958,8 @@
 }
 EXPORT_SYMBOL(pcie_aspm_enabled);
 
+bool pcie_aspm_support_enabled(void)
+{
+	return aspm_support_enabled;
+}
+EXPORT_SYMBOL(pcie_aspm_support_enabled);
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pcie/portdrv_core.c linux-libre-2.6.39-gnu/drivers/pci/pcie/portdrv_core.c
--- linux-libre-2.6.38-gnu/drivers/pci/pcie/portdrv_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pcie/portdrv_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/pcieport_if.h>
 #include <linux/aer.h>
-#include <linux/pci-aspm.h>
 
 #include "../pci.h"
 #include "portdrv.h"
@@ -356,10 +355,8 @@
 
 	/* Get and check PCI Express port services */
 	capabilities = get_port_device_capability(dev);
-	if (!capabilities) {
-		pcie_no_aspm();
+	if (!capabilities)
 		return 0;
-	}
 
 	pci_set_master(dev);
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci.h linux-libre-2.6.39-gnu/drivers/pci/pci.h
--- linux-libre-2.6.38-gnu/drivers/pci/pci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pci.h	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 extern int pci_uevent(struct device *dev, struct kobj_uevent_env *env);
 extern int pci_create_sysfs_dev_files(struct pci_dev *pdev);
 extern void pci_remove_sysfs_dev_files(struct pci_dev *pdev);
-#ifndef CONFIG_DMI
+#if !defined(CONFIG_DMI) && !defined(CONFIG_ACPI)
 static inline void pci_create_firmware_label_files(struct pci_dev *pdev)
 { return; }
 static inline void pci_remove_firmware_label_files(struct pci_dev *pdev)
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci-label.c linux-libre-2.6.39-gnu/drivers/pci/pci-label.c
--- linux-libre-2.6.38-gnu/drivers/pci/pci-label.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pci-label.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,13 @@
  * by Narendra K <Narendra_K@dell.com>,
  * Jordan Hargrave <Jordan_Hargrave@dell.com>
  *
+ * PCI Firmware Specification Revision 3.1 section 4.6.7 (DSM for Naming a
+ * PCI or PCI Express Device Under Operating Systems) defines an instance
+ * number and string name. This code retrieves them and exports them to sysfs.
+ * If the system firmware does not provide the ACPI _DSM (Device Specific
+ * Method), then the SMBIOS type 41 instance number and string is exported to
+ * sysfs.
+ *
  * SMBIOS defines type 41 for onboard pci devices. This code retrieves
  * the instance number and string from the type 41 record and exports
  * it to sysfs.
@@ -19,8 +26,29 @@
 #include <linux/pci_ids.h>
 #include <linux/module.h>
 #include <linux/device.h>
+#include <linux/nls.h>
+#include <linux/acpi.h>
+#include <linux/pci-acpi.h>
+#include <acpi/acpi_bus.h>
 #include "pci.h"
 
+#define	DEVICE_LABEL_DSM	0x07
+
+#ifndef CONFIG_DMI
+
+static inline int
+pci_create_smbiosname_file(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline void
+pci_remove_smbiosname_file(struct pci_dev *pdev)
+{
+}
+
+#else
+
 enum smbios_attr_enum {
 	SMBIOS_ATTR_NONE = 0,
 	SMBIOS_ATTR_LABEL_SHOW,
@@ -120,9 +148,7 @@
 static int
 pci_create_smbiosname_file(struct pci_dev *pdev)
 {
-	if (!sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group))
-		return 0;
-	return -ENODEV;
+	return sysfs_create_group(&pdev->dev.kobj, &smbios_attr_group);
 }
 
 static void
@@ -131,13 +157,227 @@
 	sysfs_remove_group(&pdev->dev.kobj, &smbios_attr_group);
 }
 
+#endif
+
+#ifndef CONFIG_ACPI
+
+static inline int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return -1;
+}
+
+static inline bool
+device_has_dsm(struct device *dev)
+{
+	return false;
+}
+
+#else
+
+static const char device_label_dsm_uuid[] = {
+	0xD0, 0x37, 0xC9, 0xE5, 0x53, 0x35, 0x7A, 0x4D,
+	0x91, 0x17, 0xEA, 0x4D, 0x19, 0xC3, 0x43, 0x4D
+};
+
+enum acpi_attr_enum {
+	ACPI_ATTR_NONE = 0,
+	ACPI_ATTR_LABEL_SHOW,
+	ACPI_ATTR_INDEX_SHOW,
+};
+
+static void dsm_label_utf16s_to_utf8s(union acpi_object *obj, char *buf)
+{
+	int len;
+	len = utf16s_to_utf8s((const wchar_t *)obj->
+			      package.elements[1].string.pointer,
+			      obj->package.elements[1].string.length,
+			      UTF16_LITTLE_ENDIAN,
+			      buf, PAGE_SIZE);
+	buf[len] = '\n';
+}
+
+static int
+dsm_get_label(acpi_handle handle, int func,
+	      struct acpi_buffer *output,
+	      char *buf, enum acpi_attr_enum attribute)
+{
+	struct acpi_object_list input;
+	union acpi_object params[4];
+	union acpi_object *obj;
+	int len = 0;
+
+	int err;
+
+	input.count = 4;
+	input.pointer = params;
+	params[0].type = ACPI_TYPE_BUFFER;
+	params[0].buffer.length = sizeof(device_label_dsm_uuid);
+	params[0].buffer.pointer = (char *)device_label_dsm_uuid;
+	params[1].type = ACPI_TYPE_INTEGER;
+	params[1].integer.value = 0x02;
+	params[2].type = ACPI_TYPE_INTEGER;
+	params[2].integer.value = func;
+	params[3].type = ACPI_TYPE_PACKAGE;
+	params[3].package.count = 0;
+	params[3].package.elements = NULL;
+
+	err = acpi_evaluate_object(handle, "_DSM", &input, output);
+	if (err)
+		return -1;
+
+	obj = (union acpi_object *)output->pointer;
+
+	switch (obj->type) {
+	case ACPI_TYPE_PACKAGE:
+		if (obj->package.count != 2)
+			break;
+		len = obj->package.elements[0].integer.value;
+		if (buf) {
+			if (attribute == ACPI_ATTR_INDEX_SHOW)
+				scnprintf(buf, PAGE_SIZE, "%llu\n",
+				obj->package.elements[0].integer.value);
+			else if (attribute == ACPI_ATTR_LABEL_SHOW)
+				dsm_label_utf16s_to_utf8s(obj, buf);
+			kfree(output->pointer);
+			return strlen(buf);
+		}
+		kfree(output->pointer);
+		return len;
+	break;
+	default:
+		kfree(output->pointer);
+	}
+	return -1;
+}
+
+static bool
+device_has_dsm(struct device *dev)
+{
+	acpi_handle handle;
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return FALSE;
+
+	if (dsm_get_label(handle, DEVICE_LABEL_DSM, &output, NULL,
+			  ACPI_ATTR_NONE) > 0)
+		return TRUE;
+
+	return FALSE;
+}
+
+static mode_t
+acpi_index_string_exist(struct kobject *kobj, struct attribute *attr, int n)
+{
+	struct device *dev;
+
+	dev = container_of(kobj, struct device, kobj);
+
+	if (device_has_dsm(dev))
+		return S_IRUGO;
+
+	return 0;
+}
+
+static ssize_t
+acpilabel_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return -1;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, buf, ACPI_ATTR_LABEL_SHOW);
+
+	if (length < 1)
+		return -1;
+
+	return length;
+}
+
+static ssize_t
+acpiindex_show(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct acpi_buffer output = {ACPI_ALLOCATE_BUFFER, NULL};
+	acpi_handle handle;
+	int length;
+
+	handle = DEVICE_ACPI_HANDLE(dev);
+
+	if (!handle)
+		return -1;
+
+	length = dsm_get_label(handle, DEVICE_LABEL_DSM,
+			       &output, buf, ACPI_ATTR_INDEX_SHOW);
+
+	if (length < 0)
+		return -1;
+
+	return length;
+
+}
+
+static struct device_attribute acpi_attr_label = {
+	.attr = {.name = "label", .mode = 0444},
+	.show = acpilabel_show,
+};
+
+static struct device_attribute acpi_attr_index = {
+	.attr = {.name = "acpi_index", .mode = 0444},
+	.show = acpiindex_show,
+};
+
+static struct attribute *acpi_attributes[] = {
+	&acpi_attr_label.attr,
+	&acpi_attr_index.attr,
+	NULL,
+};
+
+static struct attribute_group acpi_attr_group = {
+	.attrs = acpi_attributes,
+	.is_visible = acpi_index_string_exist,
+};
+
+static int
+pci_create_acpi_index_label_files(struct pci_dev *pdev)
+{
+	return sysfs_create_group(&pdev->dev.kobj, &acpi_attr_group);
+}
+
+static int
+pci_remove_acpi_index_label_files(struct pci_dev *pdev)
+{
+	sysfs_remove_group(&pdev->dev.kobj, &acpi_attr_group);
+	return 0;
+}
+#endif
+
 void pci_create_firmware_label_files(struct pci_dev *pdev)
 {
-	if (!pci_create_smbiosname_file(pdev))
-		;
+	if (device_has_dsm(&pdev->dev))
+		pci_create_acpi_index_label_files(pdev);
+	else
+		pci_create_smbiosname_file(pdev);
 }
 
 void pci_remove_firmware_label_files(struct pci_dev *pdev)
 {
-	pci_remove_smbiosname_file(pdev);
+	if (device_has_dsm(&pdev->dev))
+		pci_remove_acpi_index_label_files(pdev);
+	else
+		pci_remove_smbiosname_file(pdev);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/pci/pci-sysfs.c linux-libre-2.6.39-gnu/drivers/pci/pci-sysfs.c
--- linux-libre-2.6.38-gnu/drivers/pci/pci-sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/pci-sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -369,7 +369,7 @@
 	u8 *data = (u8*) buf;
 
 	/* Several chips lock up trying to read undefined config space */
-	if (security_capable(filp->f_cred, CAP_SYS_ADMIN) == 0) {
+	if (security_capable(&init_user_ns, filp->f_cred, CAP_SYS_ADMIN) == 0) {
 		size = dev->cfg_size;
 	} else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
 		size = 128;
@@ -645,7 +645,7 @@
  * a per-bus basis.  This routine creates the files and ties them into
  * their associated read, write and mmap files from pci-sysfs.c
  *
- * On error unwind, but don't propogate the error to the caller
+ * On error unwind, but don't propagate the error to the caller
  * as it is ok to set up the PCI bus without these files.
  */
 void pci_create_legacy_files(struct pci_bus *b)
@@ -1088,7 +1088,7 @@
 		attr->write = write_vpd_attr;
 		retval = sysfs_create_bin_file(&dev->dev.kobj, attr);
 		if (retval) {
-			kfree(dev->vpd->attr);
+			kfree(attr);
 			return retval;
 		}
 		dev->vpd->attr = attr;
diff -druN linux-libre-2.6.38-gnu/drivers/pci/probe.c linux-libre-2.6.39-gnu/drivers/pci/probe.c
--- linux-libre-2.6.38-gnu/drivers/pci/probe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/probe.c	2011-05-19 00:06:34.000000000 -0400
@@ -764,6 +764,8 @@
 		if (pci_find_bus(pci_domain_nr(bus), max+1))
 			goto out;
 		child = pci_add_new_bus(bus, dev, ++max);
+		if (!child)
+			goto out;
 		buses = (buses & 0xff000000)
 		      | ((unsigned int)(child->primary)     <<  0)
 		      | ((unsigned int)(child->secondary)   <<  8)
@@ -777,7 +779,7 @@
 			buses &= ~0xff000000;
 			buses |= CARDBUS_LATENCY_TIMER << 24;
 		}
-			
+
 		/*
 		 * We need to blast all three values with a single write.
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/pci/quirks.c linux-libre-2.6.39-gnu/drivers/pci/quirks.c
--- linux-libre-2.6.38-gnu/drivers/pci/quirks.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/quirks.c	2011-05-19 00:06:34.000000000 -0400
@@ -263,7 +263,7 @@
 	 *	This happens to include the IDE controllers....
 	 *
 	 *	VIA only apply this fix when an SB Live! is present but under
-	 *	both Linux and Windows this isnt enough, and we have seen
+	 *	both Linux and Windows this isn't enough, and we have seen
 	 *	corruption without SB Live! but with things like 3 UDMA IDE
 	 *	controllers. So we ignore that bit of the VIA recommendation..
 	 */
@@ -533,6 +533,17 @@
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82371AB_3,	quirk_piix4_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82443MX_3,	quirk_piix4_acpi);
 
+#define ICH_PMBASE	0x40
+#define ICH_ACPI_CNTL	0x44
+#define  ICH4_ACPI_EN	0x10
+#define  ICH6_ACPI_EN	0x80
+#define ICH4_GPIOBASE	0x58
+#define ICH4_GPIO_CNTL	0x5c
+#define  ICH4_GPIO_EN	0x10
+#define ICH6_GPIOBASE	0x48
+#define ICH6_GPIO_CNTL	0x4c
+#define  ICH6_GPIO_EN	0x10
+
 /*
  * ICH4, ICH4-M, ICH5, ICH5-M ACPI: Three IO regions pointed to by longwords at
  *	0x40 (128 bytes of ACPI, GPIO & TCO registers)
@@ -541,12 +552,33 @@
 static void __devinit quirk_ich4_lpc_acpi(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH4 ACPI/GPIO/TCO");
+	/*
+	 * The check for PCIBIOS_MIN_IO is to ensure we won't create a conflict
+	 * with low legacy (and fixed) ports. We don't know the decoding
+	 * priority and can't tell whether the legacy device or the one created
+	 * here is really at that address.  This happens on boards with broken
+	 * BIOSes.
+	*/
 
-	pci_read_config_dword(dev, 0x58, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH4 GPIO");
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH4_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH4 ACPI/GPIO/TCO");
+	}
+
+	pci_read_config_byte(dev, ICH4_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH4_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH4 GPIO");
+	}
 }
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AA_0,		quirk_ich4_lpc_acpi);
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL,    PCI_DEVICE_ID_INTEL_82801AB_0,		quirk_ich4_lpc_acpi);
@@ -562,12 +594,25 @@
 static void __devinit ich6_lpc_acpi_gpio(struct pci_dev *dev)
 {
 	u32 region;
+	u8 enable;
 
-	pci_read_config_dword(dev, 0x40, &region);
-	quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES, "ICH6 ACPI/GPIO/TCO");
+	pci_read_config_byte(dev, ICH_ACPI_CNTL, &enable);
+	if (enable & ICH6_ACPI_EN) {
+		pci_read_config_dword(dev, ICH_PMBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 128, PCI_BRIDGE_RESOURCES,
+					"ICH6 ACPI/GPIO/TCO");
+	}
 
-	pci_read_config_dword(dev, 0x48, &region);
-	quirk_io_region(dev, region, 64, PCI_BRIDGE_RESOURCES+1, "ICH6 GPIO");
+	pci_read_config_byte(dev, ICH6_GPIO_CNTL, &enable);
+	if (enable & ICH4_GPIO_EN) {
+		pci_read_config_dword(dev, ICH6_GPIOBASE, &region);
+		region &= PCI_BASE_ADDRESS_IO_MASK;
+		if (region >= PCIBIOS_MIN_IO)
+			quirk_io_region(dev, region, 64,
+					PCI_BRIDGE_RESOURCES + 1, "ICH6 GPIO");
+	}
 }
 
 static void __devinit ich6_lpc_generic_decode(struct pci_dev *dev, unsigned reg, const char *name, int dynsize)
@@ -2618,58 +2663,6 @@
 
 #endif /* CONFIG_PCI_MSI */
 
-#ifdef CONFIG_PCI_IOV
-
-/*
- * For Intel 82576 SR-IOV NIC, if BIOS doesn't allocate resources for the
- * SR-IOV BARs, zero the Flash BAR and program the SR-IOV BARs to use the
- * old Flash Memory Space.
- */
-static void __devinit quirk_i82576_sriov(struct pci_dev *dev)
-{
-	int pos, flags;
-	u32 bar, start, size;
-
-	if (PAGE_SIZE > 0x10000)
-		return;
-
-	flags = pci_resource_flags(dev, 0);
-	if ((flags & PCI_BASE_ADDRESS_SPACE) !=
-			PCI_BASE_ADDRESS_SPACE_MEMORY ||
-	    (flags & PCI_BASE_ADDRESS_MEM_TYPE_MASK) !=
-			PCI_BASE_ADDRESS_MEM_TYPE_32)
-		return;
-
-	pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_SRIOV);
-	if (!pos)
-		return;
-
-	pci_read_config_dword(dev, pos + PCI_SRIOV_BAR, &bar);
-	if (bar & PCI_BASE_ADDRESS_MEM_MASK)
-		return;
-
-	start = pci_resource_start(dev, 1);
-	size = pci_resource_len(dev, 1);
-	if (!start || size != 0x400000 || start & (size - 1))
-		return;
-
-	pci_resource_flags(dev, 1) = 0;
-	pci_write_config_dword(dev, PCI_BASE_ADDRESS_1, 0);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR, start);
-	pci_write_config_dword(dev, pos + PCI_SRIOV_BAR + 12, start + size / 2);
-
-	dev_info(&dev->dev, "use Flash Memory Space for SR-IOV BARs\n");
-}
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10c9, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e6, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e7, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x10e8, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150a, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x150d, quirk_i82576_sriov);
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1518, quirk_i82576_sriov);
-
-#endif	/* CONFIG_PCI_IOV */
-
 /* Allow manual resource allocation for PCI hotplug bridges
  * via pci=hpmemsize=nnM and pci=hpiosize=nnM parameters. For
  * some PCI-PCI hotplug bridges, like PLX 6254 (former HINT HB6),
@@ -2687,7 +2680,7 @@
  * This is a quirk for the Ricoh MMC controller found as a part of
  * some mulifunction chips.
 
- * This is very similiar and based on the ricoh_mmc driver written by
+ * This is very similar and based on the ricoh_mmc driver written by
  * Philip Langdale. Thank you for these magic sequences.
  *
  * These chips implement the four main memory card controllers (SD, MMC, MS, xD)
diff -druN linux-libre-2.6.38-gnu/drivers/pci/setup-bus.c linux-libre-2.6.39-gnu/drivers/pci/setup-bus.c
--- linux-libre-2.6.38-gnu/drivers/pci/setup-bus.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/setup-bus.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,11 +33,32 @@
 	struct pci_dev *dev;
 	resource_size_t start;
 	resource_size_t end;
+	resource_size_t add_size;
 	unsigned long flags;
 };
 
-static void add_to_failed_list(struct resource_list_x *head,
-				 struct pci_dev *dev, struct resource *res)
+#define free_list(type, head) do {                      \
+	struct type *list, *tmp;			\
+	for (list = (head)->next; list;) {		\
+		tmp = list;				\
+		list = list->next;			\
+		kfree(tmp);				\
+	}						\
+	(head)->next = NULL;				\
+} while (0)
+
+/**
+ * add_to_list() - add a new resource tracker to the list
+ * @head:	Head of the list
+ * @dev:	device corresponding to which the resource
+ *		belongs
+ * @res:	The resource to be tracked
+ * @add_size:	additional size to be optionally added
+ *              to the resource
+ */
+static void add_to_list(struct resource_list_x *head,
+		 struct pci_dev *dev, struct resource *res,
+		 resource_size_t add_size)
 {
 	struct resource_list_x *list = head;
 	struct resource_list_x *ln = list->next;
@@ -45,7 +66,7 @@
 
 	tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
 	if (!tmp) {
-		pr_warning("add_to_failed_list: kmalloc() failed!\n");
+		pr_warning("add_to_list: kmalloc() failed!\n");
 		return;
 	}
 
@@ -55,20 +76,14 @@
 	tmp->start = res->start;
 	tmp->end = res->end;
 	tmp->flags = res->flags;
+	tmp->add_size = add_size;
 	list->next = tmp;
 }
 
-static void free_failed_list(struct resource_list_x *head)
+static void add_to_failed_list(struct resource_list_x *head,
+				struct pci_dev *dev, struct resource *res)
 {
-	struct resource_list_x *list, *tmp;
-
-	for (list = head->next; list;) {
-		tmp = list;
-		list = list->next;
-		kfree(tmp);
-	}
-
-	head->next = NULL;
+	add_to_list(head, dev, res, 0);
 }
 
 static void __dev_sort_resources(struct pci_dev *dev,
@@ -91,18 +106,88 @@
 	pdev_sort_resources(dev, head);
 }
 
-static void __assign_resources_sorted(struct resource_list *head,
-				 struct resource_list_x *fail_head)
+static inline void reset_resource(struct resource *res)
+{
+	res->start = 0;
+	res->end = 0;
+	res->flags = 0;
+}
+
+/**
+ * adjust_resources_sorted() - satisfy any additional resource requests
+ *
+ * @add_head : head of the list tracking requests requiring additional
+ *             resources
+ * @head     : head of the list tracking requests with allocated
+ *             resources
+ *
+ * Walk through each element of the add_head and try to procure
+ * additional resources for the element, provided the element
+ * is in the head list.
+ */
+static void adjust_resources_sorted(struct resource_list_x *add_head,
+		struct resource_list *head)
 {
 	struct resource *res;
-	struct resource_list *list, *tmp;
+	struct resource_list_x *list, *tmp, *prev;
+	struct resource_list *hlist;
+	resource_size_t add_size;
 	int idx;
 
-	for (list = head->next; list;) {
+	prev = add_head;
+	for (list = add_head->next; list;) {
 		res = list->res;
+		/* skip resource that has been reset */
+		if (!res->flags)
+			goto out;
+
+		/* skip this resource if not found in head list */
+		for (hlist = head->next; hlist && hlist->res != res;
+				hlist = hlist->next);
+		if (!hlist) { /* just skip */
+			prev = list;
+			list = list->next;
+			continue;
+		}
+
 		idx = res - &list->dev->resource[0];
+		add_size=list->add_size;
+		if (!resource_size(res) && add_size) {
+			 res->end = res->start + add_size - 1;
+			 if(pci_assign_resource(list->dev, idx))
+				reset_resource(res);
+		} else if (add_size) {
+			adjust_resource(res, res->start,
+				resource_size(res) + add_size);
+		}
+out:
+		tmp = list;
+		prev->next = list = list->next;
+		kfree(tmp);
+	}
+}
 
-		if (pci_assign_resource(list->dev, idx)) {
+/**
+ * assign_requested_resources_sorted() - satisfy resource requests
+ *
+ * @head : head of the list tracking requests for resources
+ * @failed_list : head of the list tracking requests that could
+ *		not be allocated
+ *
+ * Satisfy resource requests of each element in the list. Add
+ * requests that could not satisfied to the failed_list.
+ */
+static void assign_requested_resources_sorted(struct resource_list *head,
+				 struct resource_list_x *fail_head)
+{
+	struct resource *res;
+	struct resource_list *list;
+	int idx;
+
+	for (list = head->next; list; list = list->next) {
+		res = list->res;
+		idx = res - &list->dev->resource[0];
+		if (resource_size(res) && pci_assign_resource(list->dev, idx)) {
 			if (fail_head && !pci_is_root_bus(list->dev->bus)) {
 				/*
 				 * if the failed res is for ROM BAR, and it will
@@ -112,16 +197,25 @@
 				      (!(res->flags & IORESOURCE_ROM_ENABLE))))
 					add_to_failed_list(fail_head, list->dev, res);
 			}
-			res->start = 0;
-			res->end = 0;
-			res->flags = 0;
+			reset_resource(res);
 		}
-		tmp = list;
-		list = list->next;
-		kfree(tmp);
 	}
 }
 
+static void __assign_resources_sorted(struct resource_list *head,
+				 struct resource_list_x *add_head,
+				 struct resource_list_x *fail_head)
+{
+	/* Satisfy the must-have resource requests */
+	assign_requested_resources_sorted(head, fail_head);
+
+	/* Try to satisfy any additional nice-to-have resource
+		requests */
+	if (add_head)
+		adjust_resources_sorted(add_head, head);
+	free_list(resource_list, head);
+}
+
 static void pdev_assign_resources_sorted(struct pci_dev *dev,
 				 struct resource_list_x *fail_head)
 {
@@ -129,11 +223,12 @@
 
 	head.next = NULL;
 	__dev_sort_resources(dev, &head);
-	__assign_resources_sorted(&head, fail_head);
+	__assign_resources_sorted(&head, NULL, fail_head);
 
 }
 
 static void pbus_assign_resources_sorted(const struct pci_bus *bus,
+					 struct resource_list_x *add_head,
 					 struct resource_list_x *fail_head)
 {
 	struct pci_dev *dev;
@@ -143,7 +238,7 @@
 	list_for_each_entry(dev, &bus->devices, bus_list)
 		__dev_sort_resources(dev, &head);
 
-	__assign_resources_sorted(&head, fail_head);
+	__assign_resources_sorted(&head, add_head, fail_head);
 }
 
 void pci_setup_cardbus(struct pci_bus *bus)
@@ -404,15 +499,62 @@
 	return NULL;
 }
 
-/* Sizing the IO windows of the PCI-PCI bridge is trivial,
-   since these windows have 4K granularity and the IO ranges
-   of non-bridge PCI devices are limited to 256 bytes.
-   We must be careful with the ISA aliasing though. */
-static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size)
+static resource_size_t calculate_iosize(resource_size_t size,
+		resource_size_t min_size,
+		resource_size_t size1,
+		resource_size_t old_size,
+		resource_size_t align)
+{
+	if (size < min_size)
+		size = min_size;
+	if (old_size == 1 )
+		old_size = 0;
+	/* To be fixed in 2.5: we should have sort of HAVE_ISA
+	   flag in the struct pci_bus. */
+#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
+	size = (size & 0xff) + ((size & ~0xffUL) << 2);
+#endif
+	size = ALIGN(size + size1, align);
+	if (size < old_size)
+		size = old_size;
+	return size;
+}
+
+static resource_size_t calculate_memsize(resource_size_t size,
+		resource_size_t min_size,
+		resource_size_t size1,
+		resource_size_t old_size,
+		resource_size_t align)
+{
+	if (size < min_size)
+		size = min_size;
+	if (old_size == 1 )
+		old_size = 0;
+	if (size < old_size)
+		size = old_size;
+	size = ALIGN(size + size1, align);
+	return size;
+}
+
+/**
+ * pbus_size_io() - size the io window of a given bus
+ *
+ * @bus : the bus
+ * @min_size : the minimum io window that must to be allocated
+ * @add_size : additional optional io window
+ * @add_head : track the additional io window on this list
+ *
+ * Sizing the IO windows of the PCI-PCI bridge is trivial,
+ * since these windows have 4K granularity and the IO ranges
+ * of non-bridge PCI devices are limited to 256 bytes.
+ * We must be careful with the ISA aliasing though.
+ */
+static void pbus_size_io(struct pci_bus *bus, resource_size_t min_size,
+		resource_size_t add_size, struct resource_list_x *add_head)
 {
 	struct pci_dev *dev;
 	struct resource *b_res = find_free_bus_resource(bus, IORESOURCE_IO);
-	unsigned long size = 0, size1 = 0, old_size;
+	unsigned long size = 0, size0 = 0, size1 = 0;
 
 	if (!b_res)
  		return;
@@ -435,20 +577,12 @@
 				size1 += r_size;
 		}
 	}
-	if (size < min_size)
-		size = min_size;
-	old_size = resource_size(b_res);
-	if (old_size == 1)
-		old_size = 0;
-/* To be fixed in 2.5: we should have sort of HAVE_ISA
-   flag in the struct pci_bus. */
-#if defined(CONFIG_ISA) || defined(CONFIG_EISA)
-	size = (size & 0xff) + ((size & ~0xffUL) << 2);
-#endif
-	size = ALIGN(size + size1, 4096);
-	if (size < old_size)
-		size = old_size;
-	if (!size) {
+	size0 = calculate_iosize(size, min_size, size1,
+			resource_size(b_res), 4096);
+	size1 = (!add_head || (add_head && !add_size)) ? size0 :
+		calculate_iosize(size, min_size+add_size, size1,
+			resource_size(b_res), 4096);
+	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
 				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
@@ -458,17 +592,30 @@
 	}
 	/* Alignment of the IO window is always 4K */
 	b_res->start = 4096;
-	b_res->end = b_res->start + size - 1;
+	b_res->end = b_res->start + size0 - 1;
 	b_res->flags |= IORESOURCE_STARTALIGN;
+	if (size1 > size0 && add_head)
+		add_to_list(add_head, bus->self, b_res, size1-size0);
 }
 
-/* Calculate the size of the bus and minimal alignment which
-   guarantees that all child resources fit in this size. */
+/**
+ * pbus_size_mem() - size the memory window of a given bus
+ *
+ * @bus : the bus
+ * @min_size : the minimum memory window that must to be allocated
+ * @add_size : additional optional memory window
+ * @add_head : track the additional memory window on this list
+ *
+ * Calculate the size of the bus and minimal alignment which
+ * guarantees that all child resources fit in this size.
+ */
 static int pbus_size_mem(struct pci_bus *bus, unsigned long mask,
-			 unsigned long type, resource_size_t min_size)
+			 unsigned long type, resource_size_t min_size,
+			resource_size_t add_size,
+			struct resource_list_x *add_head)
 {
 	struct pci_dev *dev;
-	resource_size_t min_align, align, size, old_size;
+	resource_size_t min_align, align, size, size0, size1;
 	resource_size_t aligns[12];	/* Alignments from 1Mb to 2Gb */
 	int order, max_order;
 	struct resource *b_res = find_free_bus_resource(bus, type);
@@ -516,14 +663,6 @@
 			mem64_mask &= r->flags & IORESOURCE_MEM_64;
 		}
 	}
-	if (size < min_size)
-		size = min_size;
-	old_size = resource_size(b_res);
-	if (old_size == 1)
-		old_size = 0;
-	if (size < old_size)
-		size = old_size;
-
 	align = 0;
 	min_align = 0;
 	for (order = 0; order <= max_order; order++) {
@@ -537,8 +676,11 @@
 			min_align = align1 >> 1;
 		align += aligns[order];
 	}
-	size = ALIGN(size, min_align);
-	if (!size) {
+	size0 = calculate_memsize(size, min_size, 0, resource_size(b_res), min_align);
+	size1 = (!add_head || (add_head && !add_size)) ? size0 :
+		calculate_memsize(size, min_size+add_size, 0,
+				resource_size(b_res), min_align);
+	if (!size0 && !size1) {
 		if (b_res->start || b_res->end)
 			dev_info(&bus->self->dev, "disabling bridge window "
 				 "%pR to [bus %02x-%02x] (unused)\n", b_res,
@@ -547,9 +689,10 @@
 		return 1;
 	}
 	b_res->start = min_align;
-	b_res->end = size + min_align - 1;
-	b_res->flags |= IORESOURCE_STARTALIGN;
-	b_res->flags |= mem64_mask;
+	b_res->end = size0 + min_align - 1;
+	b_res->flags |= IORESOURCE_STARTALIGN | mem64_mask;
+	if (size1 > size0 && add_head)
+		add_to_list(add_head, bus->self, b_res, size1-size0);
 	return 1;
 }
 
@@ -602,11 +745,12 @@
 	}
 }
 
-void __ref pci_bus_size_bridges(struct pci_bus *bus)
+void __ref __pci_bus_size_bridges(struct pci_bus *bus,
+			struct resource_list_x *add_head)
 {
 	struct pci_dev *dev;
 	unsigned long mask, prefmask;
-	resource_size_t min_mem_size = 0, min_io_size = 0;
+	resource_size_t additional_mem_size = 0, additional_io_size = 0;
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		struct pci_bus *b = dev->subordinate;
@@ -620,7 +764,7 @@
 
 		case PCI_CLASS_BRIDGE_PCI:
 		default:
-			pci_bus_size_bridges(b);
+			__pci_bus_size_bridges(b, add_head);
 			break;
 		}
 	}
@@ -637,11 +781,14 @@
 	case PCI_CLASS_BRIDGE_PCI:
 		pci_bridge_check_ranges(bus);
 		if (bus->self->is_hotplug_bridge) {
-			min_io_size  = pci_hotplug_io_size;
-			min_mem_size = pci_hotplug_mem_size;
+			additional_io_size  = pci_hotplug_io_size;
+			additional_mem_size = pci_hotplug_mem_size;
 		}
+		/*
+		 * Follow thru
+		 */
 	default:
-		pbus_size_io(bus, min_io_size);
+		pbus_size_io(bus, 0, additional_io_size, add_head);
 		/* If the bridge supports prefetchable range, size it
 		   separately. If it doesn't, or its prefetchable window
 		   has already been allocated by arch code, try
@@ -649,30 +796,36 @@
 		   resources. */
 		mask = IORESOURCE_MEM;
 		prefmask = IORESOURCE_MEM | IORESOURCE_PREFETCH;
-		if (pbus_size_mem(bus, prefmask, prefmask, min_mem_size))
+		if (pbus_size_mem(bus, prefmask, prefmask, 0, additional_mem_size, add_head))
 			mask = prefmask; /* Success, size non-prefetch only. */
 		else
-			min_mem_size += min_mem_size;
-		pbus_size_mem(bus, mask, IORESOURCE_MEM, min_mem_size);
+			additional_mem_size += additional_mem_size;
+		pbus_size_mem(bus, mask, IORESOURCE_MEM, 0, additional_mem_size, add_head);
 		break;
 	}
 }
+
+void __ref pci_bus_size_bridges(struct pci_bus *bus)
+{
+	__pci_bus_size_bridges(bus, NULL);
+}
 EXPORT_SYMBOL(pci_bus_size_bridges);
 
 static void __ref __pci_bus_assign_resources(const struct pci_bus *bus,
+					 struct resource_list_x *add_head,
 					 struct resource_list_x *fail_head)
 {
 	struct pci_bus *b;
 	struct pci_dev *dev;
 
-	pbus_assign_resources_sorted(bus, fail_head);
+	pbus_assign_resources_sorted(bus, add_head, fail_head);
 
 	list_for_each_entry(dev, &bus->devices, bus_list) {
 		b = dev->subordinate;
 		if (!b)
 			continue;
 
-		__pci_bus_assign_resources(b, fail_head);
+		__pci_bus_assign_resources(b, add_head, fail_head);
 
 		switch (dev->class >> 8) {
 		case PCI_CLASS_BRIDGE_PCI:
@@ -694,7 +847,7 @@
 
 void __ref pci_bus_assign_resources(const struct pci_bus *bus)
 {
-	__pci_bus_assign_resources(bus, NULL);
+	__pci_bus_assign_resources(bus, NULL, NULL);
 }
 EXPORT_SYMBOL(pci_bus_assign_resources);
 
@@ -709,7 +862,7 @@
 	if (!b)
 		return;
 
-	__pci_bus_assign_resources(b, fail_head);
+	__pci_bus_assign_resources(b, NULL, fail_head);
 
 	switch (bridge->class >> 8) {
 	case PCI_CLASS_BRIDGE_PCI:
@@ -842,17 +995,21 @@
 pci_assign_unassigned_resources(void)
 {
 	struct pci_bus *bus;
-
+	struct resource_list_x add_list; /* list of resources that
+					want additional resources */
+	add_list.next = NULL;
 	/* Depth first, calculate sizes and alignments of all
 	   subordinate buses. */
 	list_for_each_entry(bus, &pci_root_buses, node) {
-		pci_bus_size_bridges(bus);
+		__pci_bus_size_bridges(bus, &add_list);
 	}
+
 	/* Depth last, allocate resources and update the hardware. */
 	list_for_each_entry(bus, &pci_root_buses, node) {
-		pci_bus_assign_resources(bus);
+		__pci_bus_assign_resources(bus, &add_list, NULL);
 		pci_enable_bridges(bus);
 	}
+	BUG_ON(add_list.next);
 
 	/* dump the resource on buses */
 	list_for_each_entry(bus, &pci_root_buses, node) {
@@ -882,7 +1039,7 @@
 
 	if (tried_times >= 2) {
 		/* still fail, don't need to try more */
-		free_failed_list(&head);
+		free_list(resource_list_x, &head);
 		goto enable_all;
 	}
 
@@ -913,7 +1070,7 @@
 
 		list = list->next;
 	}
-	free_failed_list(&head);
+	free_list(resource_list_x, &head);
 
 	goto again;
 
diff -druN linux-libre-2.6.38-gnu/drivers/pci/xen-pcifront.c linux-libre-2.6.39-gnu/drivers/pci/xen-pcifront.c
--- linux-libre-2.6.38-gnu/drivers/pci/xen-pcifront.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pci/xen-pcifront.c	2011-05-19 00:06:34.000000000 -0400
@@ -243,7 +243,7 @@
 
 #ifdef CONFIG_PCI_MSI
 static int pci_frontend_enable_msix(struct pci_dev *dev,
-				    int **vector, int nvec)
+				    int vector[], int nvec)
 {
 	int err;
 	int i;
@@ -277,18 +277,24 @@
 	if (likely(!err)) {
 		if (likely(!op.value)) {
 			/* we get the result */
-			for (i = 0; i < nvec; i++)
-				*(*vector+i) = op.msix_entries[i].vector;
-			return 0;
+			for (i = 0; i < nvec; i++) {
+				if (op.msix_entries[i].vector <= 0) {
+					dev_warn(&dev->dev, "MSI-X entry %d is invalid: %d!\n",
+						i, op.msix_entries[i].vector);
+					err = -EINVAL;
+					vector[i] = -1;
+					continue;
+				}
+				vector[i] = op.msix_entries[i].vector;
+			}
 		} else {
 			printk(KERN_DEBUG "enable msix get value %x\n",
 				op.value);
-			return op.value;
 		}
 	} else {
 		dev_err(&dev->dev, "enable msix get err %x\n", err);
-		return err;
 	}
+	return err;
 }
 
 static void pci_frontend_disable_msix(struct pci_dev *dev)
@@ -310,7 +316,7 @@
 		dev_err(&dev->dev, "pci_disable_msix get err %x\n", err);
 }
 
-static int pci_frontend_enable_msi(struct pci_dev *dev, int **vector)
+static int pci_frontend_enable_msi(struct pci_dev *dev, int vector[])
 {
 	int err;
 	struct xen_pci_op op = {
@@ -324,7 +330,13 @@
 
 	err = do_pci_op(pdev, &op);
 	if (likely(!err)) {
-		*(*vector) = op.value;
+		vector[0] = op.value;
+		if (op.value <= 0) {
+			dev_warn(&dev->dev, "MSI entry is invalid: %d!\n",
+				op.value);
+			err = -EINVAL;
+			vector[0] = -1;
+		}
 	} else {
 		dev_err(&dev->dev, "pci frontend enable msi failed for dev "
 				    "%x:%x\n", op.bus, op.devfn);
@@ -733,8 +745,7 @@
 
 	pcifront_free_roots(pdev);
 
-	/*For PCIE_AER error handling job*/
-	flush_scheduled_work();
+	cancel_work_sync(&pdev->op_work);
 
 	if (pdev->irq >= 0)
 		unbind_from_irqhandler(pdev->irq, pdev);
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/bfin_cf_pcmcia.c linux-libre-2.6.39-gnu/drivers/pcmcia/bfin_cf_pcmcia.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/bfin_cf_pcmcia.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/bfin_cf_pcmcia.c	2011-05-19 00:06:34.000000000 -0400
@@ -235,7 +235,7 @@
 	cf->irq = irq;
 	cf->socket.pci_irq = irq;
 
-	set_irq_type(irq, IRQF_TRIGGER_LOW);
+	irq_set_irq_type(irq, IRQF_TRIGGER_LOW);
 
 	io_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	attr_mem = platform_get_resource(pdev, IORESOURCE_MEM, 1);
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/db1xxx_ss.c linux-libre-2.6.39-gnu/drivers/pcmcia/db1xxx_ss.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/db1xxx_ss.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/db1xxx_ss.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,7 +181,7 @@
 		/* all other (older) Db1x00 boards use a GPIO to show
 		 * card detection status:  use both-edge triggers.
 		 */
-		set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
+		irq_set_irq_type(sock->insert_irq, IRQ_TYPE_EDGE_BOTH);
 		ret = request_irq(sock->insert_irq, db1000_pcmcia_cdirq,
 				  0, "pcmcia_carddetect", sock);
 
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/electra_cf.c linux-libre-2.6.39-gnu/drivers/pcmcia/electra_cf.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/electra_cf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/electra_cf.c	2011-05-19 00:06:34.000000000 -0400
@@ -181,8 +181,7 @@
 	.set_mem_map		= electra_cf_set_mem_map,
 };
 
-static int __devinit electra_cf_probe(struct platform_device *ofdev,
-				      const struct of_device_id *match)
+static int __devinit electra_cf_probe(struct platform_device *ofdev)
 {
 	struct device *device = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -356,7 +355,7 @@
 };
 MODULE_DEVICE_TABLE(of, electra_cf_match);
 
-static struct of_platform_driver electra_cf_driver = {
+static struct platform_driver electra_cf_driver = {
 	.driver = {
 		.name = (char *)driver_name,
 		.owner = THIS_MODULE,
@@ -368,13 +367,13 @@
 
 static int __init electra_cf_init(void)
 {
-	return of_register_platform_driver(&electra_cf_driver);
+	return platform_driver_register(&electra_cf_driver);
 }
 module_init(electra_cf_init);
 
 static void __exit electra_cf_exit(void)
 {
-	of_unregister_platform_driver(&electra_cf_driver);
+	platform_driver_unregister(&electra_cf_driver);
 }
 module_exit(electra_cf_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/i82092.c linux-libre-2.6.39-gnu/drivers/pcmcia/i82092.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/i82092.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/i82092.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,7 +54,7 @@
 	.set_mem_map		= i82092aa_set_mem_map,
 };
 
-/* The card can do upto 4 sockets, allocate a structure for each of them */
+/* The card can do up to 4 sockets, allocate a structure for each of them */
 
 struct socket_info {
 	int	number;
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/m8xx_pcmcia.c linux-libre-2.6.39-gnu/drivers/pcmcia/m8xx_pcmcia.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/m8xx_pcmcia.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/m8xx_pcmcia.c	2011-05-19 00:06:34.000000000 -0400
@@ -1148,8 +1148,7 @@
 	.set_mem_map = m8xx_set_mem_map,
 };
 
-static int __init m8xx_probe(struct platform_device *ofdev,
-			     const struct of_device_id *match)
+static int __init m8xx_probe(struct platform_device *ofdev)
 {
 	struct pcmcia_win *w;
 	unsigned int i, m, hwirq;
@@ -1295,7 +1294,7 @@
 
 MODULE_DEVICE_TABLE(of, m8xx_pcmcia_match);
 
-static struct of_platform_driver m8xx_pcmcia_driver = {
+static struct platform_driver m8xx_pcmcia_driver = {
 	.driver = {
 		.name = driver_name,
 		.owner = THIS_MODULE,
@@ -1307,12 +1306,12 @@
 
 static int __init m8xx_init(void)
 {
-	return of_register_platform_driver(&m8xx_pcmcia_driver);
+	return platform_driver_register(&m8xx_pcmcia_driver);
 }
 
 static void __exit m8xx_exit(void)
 {
-	of_unregister_platform_driver(&m8xx_pcmcia_driver);
+	platform_driver_unregister(&m8xx_pcmcia_driver);
 }
 
 module_init(m8xx_init);
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pcmcia_resource.c linux-libre-2.6.39-gnu/drivers/pcmcia/pcmcia_resource.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pcmcia_resource.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pcmcia_resource.c	2011-05-19 00:06:34.000000000 -0400
@@ -173,7 +173,7 @@
 	c = p_dev->function_config;
 
 	if (!(c->state & CONFIG_LOCKED)) {
-		dev_dbg(&p_dev->dev, "Configuration isnt't locked\n");
+		dev_dbg(&p_dev->dev, "Configuration isn't locked\n");
 		mutex_unlock(&s->ops_mutex);
 		return -EACCES;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_balloon3.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_balloon3.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_balloon3.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_balloon3.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,8 @@
 
 #include <mach/balloon3.h>
 
+#include <asm/mach-types.h>
+
 #include "soc_common.h"
 
 /*
@@ -127,6 +129,9 @@
 {
 	int ret;
 
+	if (!machine_is_balloon3())
+		return -ENODEV;
+
 	balloon3_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 	if (!balloon3_pcmcia_device)
 		return -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_colibri.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_colibri.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_colibri.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_colibri.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,14 +34,24 @@
 #define	COLIBRI320_DETECT_GPIO	81
 #define	COLIBRI320_READY_GPIO	29
 
-static struct {
-	int	reset_gpio;
-	int	ppen_gpio;
-	int	bvd1_gpio;
-	int	bvd2_gpio;
-	int	detect_gpio;
-	int	ready_gpio;
-} colibri_pcmcia_gpio;
+enum {
+	DETECT = 0,
+	READY = 1,
+	BVD1 = 2,
+	BVD2 = 3,
+	PPEN = 4,
+	RESET = 5,
+};
+
+/* Contents of this array are configured on-the-fly in init function */
+static struct gpio colibri_pcmcia_gpios[] = {
+	{ 0,	GPIOF_IN,	"PCMCIA Detect" },
+	{ 0,	GPIOF_IN,	"PCMCIA Ready" },
+	{ 0,	GPIOF_IN,	"PCMCIA BVD1" },
+	{ 0,	GPIOF_IN,	"PCMCIA BVD2" },
+	{ 0,	GPIOF_INIT_LOW,	"PCMCIA PPEN" },
+	{ 0,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+};
 
 static struct pcmcia_irqs colibri_irqs[] = {
 	{
@@ -54,88 +64,42 @@
 {
 	int ret;
 
-	ret = gpio_request(colibri_pcmcia_gpio.detect_gpio, "DETECT");
+	ret = gpio_request_array(colibri_pcmcia_gpios,
+				ARRAY_SIZE(colibri_pcmcia_gpios));
 	if (ret)
 		goto err1;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.detect_gpio);
-	if (ret)
-		goto err2;
 
-	ret = gpio_request(colibri_pcmcia_gpio.ready_gpio, "READY");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.ready_gpio);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(colibri_pcmcia_gpio.bvd1_gpio, "BVD1");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.bvd1_gpio);
-	if (ret)
-		goto err4;
-
-	ret = gpio_request(colibri_pcmcia_gpio.bvd2_gpio, "BVD2");
-	if (ret)
-		goto err4;
-	ret = gpio_direction_input(colibri_pcmcia_gpio.bvd2_gpio);
-	if (ret)
-		goto err5;
-
-	ret = gpio_request(colibri_pcmcia_gpio.ppen_gpio, "PPEN");
-	if (ret)
-		goto err5;
-	ret = gpio_direction_output(colibri_pcmcia_gpio.ppen_gpio, 0);
-	if (ret)
-		goto err6;
+	colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpios[DETECT].gpio);
+	skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpios[READY].gpio);
 
-	ret = gpio_request(colibri_pcmcia_gpio.reset_gpio, "RESET");
-	if (ret)
-		goto err6;
-	ret = gpio_direction_output(colibri_pcmcia_gpio.reset_gpio, 1);
+	ret = soc_pcmcia_request_irqs(skt, colibri_irqs,
+					ARRAY_SIZE(colibri_irqs));
 	if (ret)
-		goto err7;
-
-	colibri_irqs[0].irq = gpio_to_irq(colibri_pcmcia_gpio.detect_gpio);
-	skt->socket.pci_irq = gpio_to_irq(colibri_pcmcia_gpio.ready_gpio);
+		goto err2;
 
-	return soc_pcmcia_request_irqs(skt, colibri_irqs,
-					ARRAY_SIZE(colibri_irqs));
+	return ret;
 
-err7:
-	gpio_free(colibri_pcmcia_gpio.detect_gpio);
-err6:
-	gpio_free(colibri_pcmcia_gpio.ready_gpio);
-err5:
-	gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
-err4:
-	gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
-err3:
-	gpio_free(colibri_pcmcia_gpio.reset_gpio);
 err2:
-	gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+	gpio_free_array(colibri_pcmcia_gpios,
+			ARRAY_SIZE(colibri_pcmcia_gpios));
 err1:
 	return ret;
 }
 
 static void colibri_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(colibri_pcmcia_gpio.detect_gpio);
-	gpio_free(colibri_pcmcia_gpio.ready_gpio);
-	gpio_free(colibri_pcmcia_gpio.bvd1_gpio);
-	gpio_free(colibri_pcmcia_gpio.bvd2_gpio);
-	gpio_free(colibri_pcmcia_gpio.reset_gpio);
-	gpio_free(colibri_pcmcia_gpio.ppen_gpio);
+	gpio_free_array(colibri_pcmcia_gpios,
+			ARRAY_SIZE(colibri_pcmcia_gpios));
 }
 
 static void colibri_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
 					struct pcmcia_state *state)
 {
 
-	state->detect = !!gpio_get_value(colibri_pcmcia_gpio.detect_gpio);
-	state->ready  = !!gpio_get_value(colibri_pcmcia_gpio.ready_gpio);
-	state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpio.bvd1_gpio);
-	state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpio.bvd2_gpio);
+	state->detect = !!gpio_get_value(colibri_pcmcia_gpios[DETECT].gpio);
+	state->ready  = !!gpio_get_value(colibri_pcmcia_gpios[READY].gpio);
+	state->bvd1   = !!gpio_get_value(colibri_pcmcia_gpios[BVD1].gpio);
+	state->bvd2   = !!gpio_get_value(colibri_pcmcia_gpios[BVD2].gpio);
 	state->wrprot = 0;
 	state->vs_3v  = 1;
 	state->vs_Xv  = 0;
@@ -145,9 +109,10 @@
 colibri_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
 				const socket_state_t *state)
 {
-	gpio_set_value(colibri_pcmcia_gpio.ppen_gpio,
+	gpio_set_value(colibri_pcmcia_gpios[PPEN].gpio,
 			!(state->Vcc == 33 && state->Vpp < 50));
-	gpio_set_value(colibri_pcmcia_gpio.reset_gpio, state->flags & SS_RESET);
+	gpio_set_value(colibri_pcmcia_gpios[RESET].gpio,
+			state->flags & SS_RESET);
 	return 0;
 }
 
@@ -190,20 +155,20 @@
 
 	/* Colibri PXA270 */
 	if (machine_is_colibri()) {
-		colibri_pcmcia_gpio.reset_gpio	= COLIBRI270_RESET_GPIO;
-		colibri_pcmcia_gpio.ppen_gpio	= COLIBRI270_PPEN_GPIO;
-		colibri_pcmcia_gpio.bvd1_gpio	= COLIBRI270_BVD1_GPIO;
-		colibri_pcmcia_gpio.bvd2_gpio	= COLIBRI270_BVD2_GPIO;
-		colibri_pcmcia_gpio.detect_gpio	= COLIBRI270_DETECT_GPIO;
-		colibri_pcmcia_gpio.ready_gpio	= COLIBRI270_READY_GPIO;
+		colibri_pcmcia_gpios[RESET].gpio	= COLIBRI270_RESET_GPIO;
+		colibri_pcmcia_gpios[PPEN].gpio		= COLIBRI270_PPEN_GPIO;
+		colibri_pcmcia_gpios[BVD1].gpio		= COLIBRI270_BVD1_GPIO;
+		colibri_pcmcia_gpios[BVD2].gpio		= COLIBRI270_BVD2_GPIO;
+		colibri_pcmcia_gpios[DETECT].gpio	= COLIBRI270_DETECT_GPIO;
+		colibri_pcmcia_gpios[READY].gpio	= COLIBRI270_READY_GPIO;
 	/* Colibri PXA320 */
 	} else if (machine_is_colibri320()) {
-		colibri_pcmcia_gpio.reset_gpio	= COLIBRI320_RESET_GPIO;
-		colibri_pcmcia_gpio.ppen_gpio	= COLIBRI320_PPEN_GPIO;
-		colibri_pcmcia_gpio.bvd1_gpio	= COLIBRI320_BVD1_GPIO;
-		colibri_pcmcia_gpio.bvd2_gpio	= COLIBRI320_BVD2_GPIO;
-		colibri_pcmcia_gpio.detect_gpio	= COLIBRI320_DETECT_GPIO;
-		colibri_pcmcia_gpio.ready_gpio	= COLIBRI320_READY_GPIO;
+		colibri_pcmcia_gpios[RESET].gpio	= COLIBRI320_RESET_GPIO;
+		colibri_pcmcia_gpios[PPEN].gpio		= COLIBRI320_PPEN_GPIO;
+		colibri_pcmcia_gpios[BVD1].gpio		= COLIBRI320_BVD1_GPIO;
+		colibri_pcmcia_gpios[BVD2].gpio		= COLIBRI320_BVD2_GPIO;
+		colibri_pcmcia_gpios[DETECT].gpio	= COLIBRI320_DETECT_GPIO;
+		colibri_pcmcia_gpios[READY].gpio	= COLIBRI320_READY_GPIO;
 	}
 
 	ret = platform_device_add_data(colibri_pcmcia_device,
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_lubbock.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_lubbock.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_lubbock.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_lubbock.c	2011-05-19 00:06:34.000000000 -0400
@@ -187,7 +187,7 @@
 			 * We need to hack around the const qualifier as
 			 * well to keep this ugly workaround localized and
 			 * not force it to the rest of the code. Barf bags
-			 * avaliable in the seat pocket in front of you!
+			 * available in the seat pocket in front of you!
 			 */
 			((socket_state_t *)state)->Vcc = 50;
 			((socket_state_t *)state)->Vpp = 50;
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_palmld.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_palmld.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_palmld.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_palmld.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * Driver for Palm LifeDrive PCMCIA
  *
  * Copyright (C) 2006 Alex Osborne <ato@meshy.org>
- * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@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
@@ -20,49 +20,27 @@
 #include <mach/palmld.h>
 #include "soc_common.h"
 
+static struct gpio palmld_pcmcia_gpios[] = {
+	{ GPIO_NR_PALMLD_PCMCIA_POWER,	GPIOF_INIT_LOW,	"PCMCIA Power" },
+	{ GPIO_NR_PALMLD_PCMCIA_RESET,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+	{ GPIO_NR_PALMLD_PCMCIA_READY,	GPIOF_IN,	"PCMCIA Ready" },
+};
+
 static int palmld_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_POWER, "PCMCIA PWR");
-	if (ret)
-		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_POWER, 0);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_RESET, "PCMCIA RST");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMLD_PCMCIA_RESET, 1);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(GPIO_NR_PALMLD_PCMCIA_READY, "PCMCIA RDY");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_input(GPIO_NR_PALMLD_PCMCIA_READY);
-	if (ret)
-		goto err4;
+	ret = gpio_request_array(palmld_pcmcia_gpios,
+				ARRAY_SIZE(palmld_pcmcia_gpios));
 
 	skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMLD_PCMCIA_READY);
-	return 0;
 
-err4:
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
-err3:
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
-err2:
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
-err1:
 	return ret;
 }
 
 static void palmld_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_READY);
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_RESET);
-	gpio_free(GPIO_NR_PALMLD_PCMCIA_POWER);
+	gpio_free_array(palmld_pcmcia_gpios, ARRAY_SIZE(palmld_pcmcia_gpios));
 }
 
 static void palmld_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_palmtc.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_palmtc.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_palmtc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_palmtc.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,7 @@
  * Driver for Palm Tungsten|C PCMCIA
  *
  * Copyright (C) 2008 Alex Osborne <ato@meshy.org>
- * Copyright (C) 2009 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2009-2011 Marek Vasut <marek.vasut@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
@@ -21,79 +21,30 @@
 #include <mach/palmtc.h>
 #include "soc_common.h"
 
+static struct gpio palmtc_pcmcia_gpios[] = {
+	{ GPIO_NR_PALMTC_PCMCIA_POWER1,	GPIOF_INIT_LOW,	"PCMCIA Power 1" },
+	{ GPIO_NR_PALMTC_PCMCIA_POWER2,	GPIOF_INIT_LOW,	"PCMCIA Power 2" },
+	{ GPIO_NR_PALMTC_PCMCIA_POWER3,	GPIOF_INIT_LOW,	"PCMCIA Power 3" },
+	{ GPIO_NR_PALMTC_PCMCIA_RESET,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+	{ GPIO_NR_PALMTC_PCMCIA_READY,	GPIOF_IN,	"PCMCIA Ready" },
+	{ GPIO_NR_PALMTC_PCMCIA_PWRREADY, GPIOF_IN,	"PCMCIA Power Ready" },
+};
+
 static int palmtc_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER1, "PCMCIA PWR1");
-	if (ret)
-		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER1, 0);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER2, "PCMCIA PWR2");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER2, 0);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_POWER3, "PCMCIA PWR3");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_POWER3, 0);
-	if (ret)
-		goto err4;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_RESET, "PCMCIA RST");
-	if (ret)
-		goto err4;
-	ret = gpio_direction_output(GPIO_NR_PALMTC_PCMCIA_RESET, 1);
-	if (ret)
-		goto err5;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_READY, "PCMCIA RDY");
-	if (ret)
-		goto err5;
-	ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_READY);
-	if (ret)
-		goto err6;
-
-	ret = gpio_request(GPIO_NR_PALMTC_PCMCIA_PWRREADY, "PCMCIA PWRRDY");
-	if (ret)
-		goto err6;
-	ret = gpio_direction_input(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-	if (ret)
-		goto err7;
+	ret = gpio_request_array(palmtc_pcmcia_gpios,
+				ARRAY_SIZE(palmtc_pcmcia_gpios));
 
 	skt->socket.pci_irq = IRQ_GPIO(GPIO_NR_PALMTC_PCMCIA_READY);
-	return 0;
 
-err7:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-err6:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_READY);
-err5:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET);
-err4:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3);
-err3:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2);
-err2:
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1);
-err1:
 	return ret;
 }
 
 static void palmtc_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_PWRREADY);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_READY);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_RESET);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER3);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER2);
-	gpio_free(GPIO_NR_PALMTC_PCMCIA_POWER1);
+	gpio_free_array(palmtc_pcmcia_gpios, ARRAY_SIZE(palmtc_pcmcia_gpios));
 }
 
 static void palmtc_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_palmtx.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_palmtx.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_palmtx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_palmtx.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Driver for Palm T|X PCMCIA
  *
- * Copyright (C) 2007-2008 Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2007-2011 Marek Vasut <marek.vasut@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
@@ -13,67 +13,34 @@
 
 #include <linux/module.h>
 #include <linux/platform_device.h>
+#include <linux/gpio.h>
 
 #include <asm/mach-types.h>
-
-#include <mach/gpio.h>
 #include <mach/palmtx.h>
-
 #include "soc_common.h"
 
+static struct gpio palmtx_pcmcia_gpios[] = {
+	{ GPIO_NR_PALMTX_PCMCIA_POWER1,	GPIOF_INIT_LOW,	"PCMCIA Power 1" },
+	{ GPIO_NR_PALMTX_PCMCIA_POWER2,	GPIOF_INIT_LOW,	"PCMCIA Power 2" },
+	{ GPIO_NR_PALMTX_PCMCIA_RESET,	GPIOF_INIT_HIGH,"PCMCIA Reset" },
+	{ GPIO_NR_PALMTX_PCMCIA_READY,	GPIOF_IN,	"PCMCIA Ready" },
+};
+
 static int palmtx_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
 {
 	int ret;
 
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER1, "PCMCIA PWR1");
-	if (ret)
-		goto err1;
-	ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER1, 0);
-	if (ret)
-		goto err2;
-
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_POWER2, "PCMCIA PWR2");
-	if (ret)
-		goto err2;
-	ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_POWER2, 0);
-	if (ret)
-		goto err3;
-
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_RESET, "PCMCIA RST");
-	if (ret)
-		goto err3;
-	ret = gpio_direction_output(GPIO_NR_PALMTX_PCMCIA_RESET, 1);
-	if (ret)
-		goto err4;
-
-	ret = gpio_request(GPIO_NR_PALMTX_PCMCIA_READY, "PCMCIA RDY");
-	if (ret)
-		goto err4;
-	ret = gpio_direction_input(GPIO_NR_PALMTX_PCMCIA_READY);
-	if (ret)
-		goto err5;
+	ret = gpio_request_array(palmtx_pcmcia_gpios,
+				ARRAY_SIZE(palmtx_pcmcia_gpios));
 
 	skt->socket.pci_irq = gpio_to_irq(GPIO_NR_PALMTX_PCMCIA_READY);
-	return 0;
 
-err5:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
-err4:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
-err3:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
-err2:
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
-err1:
 	return ret;
 }
 
 static void palmtx_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_READY);
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_RESET);
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER2);
-	gpio_free(GPIO_NR_PALMTX_PCMCIA_POWER1);
+	gpio_free_array(palmtx_pcmcia_gpios, ARRAY_SIZE(palmtx_pcmcia_gpios));
 }
 
 static void palmtx_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_trizeps4.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_trizeps4.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_trizeps4.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_trizeps4.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,15 +69,15 @@
 	for (i = 0; i < ARRAY_SIZE(irqs); i++) {
 		if (irqs[i].sock != skt->nr)
 			continue;
-		if (gpio_request(IRQ_TO_GPIO(irqs[i].irq), irqs[i].str) < 0) {
+		if (gpio_request(irq_to_gpio(irqs[i].irq), irqs[i].str) < 0) {
 			pr_err("%s: sock %d unable to request gpio %d\n",
-				__func__, skt->nr, IRQ_TO_GPIO(irqs[i].irq));
+				__func__, skt->nr, irq_to_gpio(irqs[i].irq));
 			ret = -EBUSY;
 			goto error;
 		}
-		if (gpio_direction_input(IRQ_TO_GPIO(irqs[i].irq)) < 0) {
+		if (gpio_direction_input(irq_to_gpio(irqs[i].irq)) < 0) {
 			pr_err("%s: sock %d unable to set input gpio %d\n",
-				__func__, skt->nr, IRQ_TO_GPIO(irqs[i].irq));
+				__func__, skt->nr, irq_to_gpio(irqs[i].irq));
 			ret = -EINVAL;
 			goto error;
 		}
@@ -86,7 +86,7 @@
 
 error:
 	for (; i >= 0; i--) {
-		gpio_free(IRQ_TO_GPIO(irqs[i].irq));
+		gpio_free(irq_to_gpio(irqs[i].irq));
 	}
 	return (ret);
 }
@@ -97,7 +97,7 @@
 	/* free allocated gpio's */
 	gpio_free(GPIO_PRDY);
 	for (i = 0; i < ARRAY_SIZE(irqs); i++)
-		gpio_free(IRQ_TO_GPIO(irqs[i].irq));
+		gpio_free(irq_to_gpio(irqs[i].irq));
 }
 
 static unsigned long trizeps_pcmcia_status[2];
@@ -226,6 +226,9 @@
 {
 	int ret;
 
+	if (!machine_is_trizeps4() && !machine_is_trizeps4wl())
+		return -ENODEV;
+
 	trizeps_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
 	if (!trizeps_pcmcia_device)
 		return -ENOMEM;
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_vpac270.c linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_vpac270.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/pxa2xx_vpac270.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/pxa2xx_vpac270.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,8 +3,7 @@
  *
  * Driver for Voipac PXA270 PCMCIA and CF sockets
  *
- * Copyright (C) 2010
- * Marek Vasut <marek.vasut@gmail.com>
+ * Copyright (C) 2010-2011 Marek Vasut <marek.vasut@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
@@ -22,6 +21,19 @@
 
 #include "soc_common.h"
 
+static struct gpio vpac270_pcmcia_gpios[] = {
+	{ GPIO84_VPAC270_PCMCIA_CD,	GPIOF_IN,	"PCMCIA Card Detect" },
+	{ GPIO35_VPAC270_PCMCIA_RDY,	GPIOF_IN,	"PCMCIA Ready" },
+	{ GPIO107_VPAC270_PCMCIA_PPEN,	GPIOF_INIT_LOW,	"PCMCIA PPEN" },
+	{ GPIO11_VPAC270_PCMCIA_RESET,	GPIOF_INIT_LOW,	"PCMCIA Reset" },
+};
+
+static struct gpio vpac270_cf_gpios[] = {
+	{ GPIO17_VPAC270_CF_CD,		GPIOF_IN,	"CF Card Detect" },
+	{ GPIO12_VPAC270_CF_RDY,	GPIOF_IN,	"CF Ready" },
+	{ GPIO16_VPAC270_CF_RESET,	GPIOF_INIT_LOW,	"CF Reset" },
+};
+
 static struct pcmcia_irqs cd_irqs[] = {
 	{
 		.sock = 0,
@@ -40,96 +52,34 @@
 	int ret;
 
 	if (skt->nr == 0) {
-		ret = gpio_request(GPIO84_VPAC270_PCMCIA_CD, "PCMCIA CD");
-		if (ret)
-			goto err1;
-		ret = gpio_direction_input(GPIO84_VPAC270_PCMCIA_CD);
-		if (ret)
-			goto err2;
-
-		ret = gpio_request(GPIO35_VPAC270_PCMCIA_RDY, "PCMCIA RDY");
-		if (ret)
-			goto err2;
-		ret = gpio_direction_input(GPIO35_VPAC270_PCMCIA_RDY);
-		if (ret)
-			goto err3;
-
-		ret = gpio_request(GPIO107_VPAC270_PCMCIA_PPEN, "PCMCIA PPEN");
-		if (ret)
-			goto err3;
-		ret = gpio_direction_output(GPIO107_VPAC270_PCMCIA_PPEN, 0);
-		if (ret)
-			goto err4;
-
-		ret = gpio_request(GPIO11_VPAC270_PCMCIA_RESET, "PCMCIA RESET");
-		if (ret)
-			goto err4;
-		ret = gpio_direction_output(GPIO11_VPAC270_PCMCIA_RESET, 0);
-		if (ret)
-			goto err5;
+		ret = gpio_request_array(vpac270_pcmcia_gpios,
+				ARRAY_SIZE(vpac270_pcmcia_gpios));
 
 		skt->socket.pci_irq = gpio_to_irq(GPIO35_VPAC270_PCMCIA_RDY);
 
-		return soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1);
-
-err5:
-		gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
-err4:
-		gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
-err3:
-		gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
-err2:
-		gpio_free(GPIO84_VPAC270_PCMCIA_CD);
-err1:
-		return ret;
-
+		if (!ret)
+			ret = soc_pcmcia_request_irqs(skt, &cd_irqs[0], 1);
 	} else {
-		ret = gpio_request(GPIO17_VPAC270_CF_CD, "CF CD");
-		if (ret)
-			goto err6;
-		ret = gpio_direction_input(GPIO17_VPAC270_CF_CD);
-		if (ret)
-			goto err7;
-
-		ret = gpio_request(GPIO12_VPAC270_CF_RDY, "CF RDY");
-		if (ret)
-			goto err7;
-		ret = gpio_direction_input(GPIO12_VPAC270_CF_RDY);
-		if (ret)
-			goto err8;
-
-		ret = gpio_request(GPIO16_VPAC270_CF_RESET, "CF RESET");
-		if (ret)
-			goto err8;
-		ret = gpio_direction_output(GPIO16_VPAC270_CF_RESET, 0);
-		if (ret)
-			goto err9;
+		ret = gpio_request_array(vpac270_cf_gpios,
+				ARRAY_SIZE(vpac270_cf_gpios));
 
 		skt->socket.pci_irq = gpio_to_irq(GPIO12_VPAC270_CF_RDY);
 
-		return soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1);
-
-err9:
-		gpio_free(GPIO16_VPAC270_CF_RESET);
-err8:
-		gpio_free(GPIO12_VPAC270_CF_RDY);
-err7:
-		gpio_free(GPIO17_VPAC270_CF_CD);
-err6:
-		return ret;
-
+		if (!ret)
+			ret = soc_pcmcia_request_irqs(skt, &cd_irqs[1], 1);
 	}
+
+	return ret;
 }
 
 static void vpac270_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
 {
-	gpio_free(GPIO11_VPAC270_PCMCIA_RESET);
-	gpio_free(GPIO107_VPAC270_PCMCIA_PPEN);
-	gpio_free(GPIO35_VPAC270_PCMCIA_RDY);
-	gpio_free(GPIO84_VPAC270_PCMCIA_CD);
-	gpio_free(GPIO16_VPAC270_CF_RESET);
-	gpio_free(GPIO12_VPAC270_CF_RDY);
-	gpio_free(GPIO17_VPAC270_CF_CD);
+	if (skt->nr == 0)
+		gpio_request_array(vpac270_pcmcia_gpios,
+					ARRAY_SIZE(vpac270_pcmcia_gpios));
+	else
+		gpio_request_array(vpac270_cf_gpios,
+					ARRAY_SIZE(vpac270_cf_gpios));
 }
 
 static void vpac270_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/sa1100_nanoengine.c linux-libre-2.6.39-gnu/drivers/pcmcia/sa1100_nanoengine.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/sa1100_nanoengine.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/sa1100_nanoengine.c	2011-05-19 00:06:34.000000000 -0400
@@ -86,7 +86,7 @@
 	GPDR &= ~nano_skts[i].input_pins;
 	GPDR |= nano_skts[i].output_pins;
 	GPCR = nano_skts[i].clear_outputs;
-	set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(nano_skts[i].transition_pins, IRQ_TYPE_EDGE_BOTH);
 	skt->socket.pci_irq = nano_skts[i].pci_irq;
 
 	return soc_pcmcia_request_irqs(skt,
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/soc_common.c linux-libre-2.6.39-gnu/drivers/pcmcia/soc_common.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/soc_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/soc_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -155,11 +155,11 @@
 		 */
 		if (skt->irq_state != 1 && state->io_irq) {
 			skt->irq_state = 1;
-			set_irq_type(skt->socket.pci_irq,
-				IRQ_TYPE_EDGE_FALLING);
+			irq_set_irq_type(skt->socket.pci_irq,
+					 IRQ_TYPE_EDGE_FALLING);
 		} else if (skt->irq_state == 1 && state->io_irq == 0) {
 			skt->irq_state = 0;
-			set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
+			irq_set_irq_type(skt->socket.pci_irq, IRQ_TYPE_NONE);
 		}
 
 		skt->cs_state = *state;
@@ -537,7 +537,7 @@
 				  IRQF_DISABLED, irqs[i].str, skt);
 		if (res)
 			break;
-		set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
+		irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
 	}
 
 	if (res) {
@@ -570,7 +570,7 @@
 
 	for (i = 0; i < nr; i++)
 		if (irqs[i].sock == skt->nr)
-			set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
+			irq_set_irq_type(irqs[i].irq, IRQ_TYPE_NONE);
 }
 EXPORT_SYMBOL(soc_pcmcia_disable_irqs);
 
@@ -581,8 +581,8 @@
 
 	for (i = 0; i < nr; i++)
 		if (irqs[i].sock == skt->nr) {
-			set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
-			set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
+			irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_RISING);
+			irq_set_irq_type(irqs[i].irq, IRQ_TYPE_EDGE_BOTH);
 		}
 }
 EXPORT_SYMBOL(soc_pcmcia_enable_irqs);
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/ti113x.h linux-libre-2.6.39-gnu/drivers/pcmcia/ti113x.h
--- linux-libre-2.6.38-gnu/drivers/pcmcia/ti113x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/ti113x.h	2011-05-19 00:06:34.000000000 -0400
@@ -691,7 +691,7 @@
 		/*
 		 * those are either single or dual slot CB with additional functions
 		 * like 1394, smartcard reader, etc. check the TIEALL flag for them
-		 * the TIEALL flag binds the IRQ of all functions toghether.
+		 * the TIEALL flag binds the IRQ of all functions together.
 		 * we catch the single slot variants later.
 		 */
 		sysctl = config_readl(socket, TI113X_SYSTEM_CONTROL);
diff -druN linux-libre-2.6.38-gnu/drivers/pcmcia/xxs1500_ss.c linux-libre-2.6.39-gnu/drivers/pcmcia/xxs1500_ss.c
--- linux-libre-2.6.38-gnu/drivers/pcmcia/xxs1500_ss.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pcmcia/xxs1500_ss.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,7 +274,7 @@
 	 * edge detector.
 	 */
 	irq = gpio_to_irq(GPIO_CDA);
-	set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
+	irq_set_irq_type(irq, IRQ_TYPE_EDGE_BOTH);
 	ret = request_irq(irq, cdirq, 0, "pcmcia_carddetect", sock);
 	if (ret) {
 		dev_err(&pdev->dev, "cannot setup cd irq\n");
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/acer-wmi.c linux-libre-2.6.39-gnu/drivers/platform/x86/acer-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/acer-wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/acer-wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,6 +22,8 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
@@ -39,7 +41,6 @@
 #include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-#include <linux/dmi.h>
 
 #include <acpi/acpi_drivers.h>
 
@@ -47,12 +48,6 @@
 MODULE_DESCRIPTION("Acer Laptop WMI Extras Driver");
 MODULE_LICENSE("GPL");
 
-#define ACER_LOGPREFIX "acer-wmi: "
-#define ACER_ERR KERN_ERR ACER_LOGPREFIX
-#define ACER_NOTICE KERN_NOTICE ACER_LOGPREFIX
-#define ACER_INFO KERN_INFO ACER_LOGPREFIX
-#define ACER_WARNING KERN_WARNING ACER_LOGPREFIX
-
 /*
  * Magic Number
  * Meaning is unknown - this number is required for writing to ACPI for AMW0
@@ -85,7 +80,7 @@
 #define AMW0_GUID1		"67C3371D-95A3-4C37-BB61-DD47B491DAAB"
 #define AMW0_GUID2		"431F16ED-0C2B-444C-B267-27DEB140CF9C"
 #define WMID_GUID1		"6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3"
-#define WMID_GUID2		"95764E09-FB56-4e83-B31A-37761F60994A"
+#define WMID_GUID2		"95764E09-FB56-4E83-B31A-37761F60994A"
 #define WMID_GUID3		"61EF69EA-865C-4BC3-A502-A0DEBA0CB531"
 
 /*
@@ -94,7 +89,7 @@
 #define ACERWMID_EVENT_GUID "676AA15E-6A47-4D9F-A2CC-1E6D18D14026"
 
 MODULE_ALIAS("wmi:67C3371D-95A3-4C37-BB61-DD47B491DAAB");
-MODULE_ALIAS("wmi:6AF4F258-B401-42fd-BE91-3D4AC2D7C0D3");
+MODULE_ALIAS("wmi:6AF4F258-B401-42FD-BE91-3D4AC2D7C0D3");
 MODULE_ALIAS("wmi:676AA15E-6A47-4D9F-A2CC-1E6D18D14026");
 
 enum acer_wmi_event_ids {
@@ -109,7 +104,7 @@
 	{KE_KEY, 0x23, {KEY_PROG3} },    /* P_Key */
 	{KE_KEY, 0x24, {KEY_PROG4} },    /* Social networking_Key */
 	{KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} },	/* Display Switch */
-	{KE_KEY, 0x82, {KEY_F22} },      /* Touch Pad On/Off */
+	{KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} },	/* Touch Pad On/Off */
 	{KE_END, 0}
 };
 
@@ -222,6 +217,7 @@
 static struct rfkill *wireless_rfkill;
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *threeg_rfkill;
+static bool rfkill_inited;
 
 /* Each low-level interface must define at least some of the following */
 struct wmi_interface {
@@ -846,7 +842,7 @@
 	has_type_aa = true;
 	type_aa = (struct hotkey_function_type_aa *) header;
 
-	printk(ACER_INFO "Function bitmap for Communication Button: 0x%x\n",
+	pr_info("Function bitmap for Communication Button: 0x%x\n",
 		type_aa->commun_func_bitmap);
 
 	if (type_aa->commun_func_bitmap & ACER_WMID3_GDS_WIRELESS)
@@ -992,6 +988,7 @@
 
 static void acer_led_exit(void)
 {
+	set_u32(LED_OFF, ACER_CAP_MAILLED);
 	led_classdev_unregister(&mail_led);
 }
 
@@ -1032,11 +1029,12 @@
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = max_brightness;
 	bd = backlight_device_register("acer-wmi", dev, NULL, &acer_bl_ops,
 				       &props);
 	if (IS_ERR(bd)) {
-		printk(ACER_ERR "Could not register Acer backlight device\n");
+		pr_err("Could not register Acer backlight device\n");
 		acer_backlight_device = NULL;
 		return PTR_ERR(bd);
 	}
@@ -1083,8 +1081,7 @@
 		return AE_ERROR;
 	}
 	if (obj->buffer.length != 8) {
-		printk(ACER_WARNING "Unknown buffer length %d\n",
-			obj->buffer.length);
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
 		kfree(obj);
 		return AE_ERROR;
 	}
@@ -1093,7 +1090,7 @@
 	kfree(obj);
 
 	if (return_value.error_code || return_value.ec_return_value)
-		printk(ACER_WARNING "Get Device Status failed: "
+		pr_warning("Get Device Status failed: "
 			"0x%x - 0x%x\n", return_value.error_code,
 			return_value.ec_return_value);
 	else
@@ -1161,9 +1158,13 @@
 {
 	acpi_status status;
 	u32 cap = (unsigned long)data;
-	status = set_u32(!blocked, cap);
-	if (ACPI_FAILURE(status))
-		return -ENODEV;
+
+	if (rfkill_inited) {
+		status = set_u32(!blocked, cap);
+		if (ACPI_FAILURE(status))
+			return -ENODEV;
+	}
+
 	return 0;
 }
 
@@ -1187,14 +1188,16 @@
 		return ERR_PTR(-ENOMEM);
 
 	status = get_device_status(&state, cap);
-	if (ACPI_SUCCESS(status))
-		rfkill_init_sw_state(rfkill_dev, !state);
 
 	err = rfkill_register(rfkill_dev);
 	if (err) {
 		rfkill_destroy(rfkill_dev);
 		return ERR_PTR(err);
 	}
+
+	if (ACPI_SUCCESS(status))
+		rfkill_set_sw_state(rfkill_dev, !state);
+
 	return rfkill_dev;
 }
 
@@ -1229,14 +1232,19 @@
 		}
 	}
 
-	schedule_delayed_work(&acer_rfkill_work, round_jiffies_relative(HZ));
+	rfkill_inited = true;
+
+	if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+		schedule_delayed_work(&acer_rfkill_work,
+			round_jiffies_relative(HZ));
 
 	return 0;
 }
 
 static void acer_rfkill_exit(void)
 {
-	cancel_delayed_work_sync(&acer_rfkill_work);
+	if (ec_raw_mode || !wmi_has_guid(ACERWMID_EVENT_GUID))
+		cancel_delayed_work_sync(&acer_rfkill_work);
 
 	rfkill_unregister(wireless_rfkill);
 	rfkill_destroy(wireless_rfkill);
@@ -1309,7 +1317,7 @@
 
 	status = wmi_get_event_data(value, &response);
 	if (status != AE_OK) {
-		printk(ACER_WARNING "bad event status 0x%x\n", status);
+		pr_warning("bad event status 0x%x\n", status);
 		return;
 	}
 
@@ -1318,14 +1326,12 @@
 	if (!obj)
 		return;
 	if (obj->type != ACPI_TYPE_BUFFER) {
-		printk(ACER_WARNING "Unknown response received %d\n",
-			obj->type);
+		pr_warning("Unknown response received %d\n", obj->type);
 		kfree(obj);
 		return;
 	}
 	if (obj->buffer.length != 8) {
-		printk(ACER_WARNING "Unknown buffer length %d\n",
-			obj->buffer.length);
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
 		kfree(obj);
 		return;
 	}
@@ -1335,13 +1341,26 @@
 
 	switch (return_value.function) {
 	case WMID_HOTKEY_EVENT:
+		if (return_value.device_state) {
+			u16 device_state = return_value.device_state;
+			pr_debug("deivces states: 0x%x\n", device_state);
+			if (has_cap(ACER_CAP_WIRELESS))
+				rfkill_set_sw_state(wireless_rfkill,
+				!(device_state & ACER_WMID3_GDS_WIRELESS));
+			if (has_cap(ACER_CAP_BLUETOOTH))
+				rfkill_set_sw_state(bluetooth_rfkill,
+				!(device_state & ACER_WMID3_GDS_BLUETOOTH));
+			if (has_cap(ACER_CAP_THREEG))
+				rfkill_set_sw_state(threeg_rfkill,
+				!(device_state & ACER_WMID3_GDS_THREEG));
+		}
 		if (!sparse_keymap_report_event(acer_wmi_input_dev,
 				return_value.key_num, 1, true))
-			printk(ACER_WARNING "Unknown key number - 0x%x\n",
+			pr_warning("Unknown key number - 0x%x\n",
 				return_value.key_num);
 		break;
 	default:
-		printk(ACER_WARNING "Unknown function number - %d - %d\n",
+		pr_warning("Unknown function number - %d - %d\n",
 			return_value.function, return_value.key_num);
 		break;
 	}
@@ -1370,8 +1389,7 @@
 		return AE_ERROR;
 	}
 	if (obj->buffer.length != 4) {
-		printk(ACER_WARNING "Unknown buffer length %d\n",
-		       obj->buffer.length);
+		pr_warning("Unknown buffer length %d\n", obj->buffer.length);
 		kfree(obj);
 		return AE_ERROR;
 	}
@@ -1396,11 +1414,11 @@
 	status = wmid3_set_lm_mode(&params, &return_value);
 
 	if (return_value.error_code || return_value.ec_return_value)
-		printk(ACER_WARNING "Enabling EC raw mode failed: "
+		pr_warning("Enabling EC raw mode failed: "
 		       "0x%x - 0x%x\n", return_value.error_code,
 		       return_value.ec_return_value);
 	else
-		printk(ACER_INFO "Enabled EC raw mode");
+		pr_info("Enabled EC raw mode");
 
 	return status;
 }
@@ -1419,7 +1437,7 @@
 	status = wmid3_set_lm_mode(&params, &return_value);
 
 	if (return_value.error_code || return_value.ec_return_value)
-		printk(ACER_WARNING "Enabling Launch Manager failed: "
+		pr_warning("Enabling Launch Manager failed: "
 		       "0x%x - 0x%x\n", return_value.error_code,
 		       return_value.ec_return_value);
 
@@ -1553,6 +1571,7 @@
 
 	if (has_cap(ACER_CAP_MAILLED)) {
 		get_u32(&value, ACER_CAP_MAILLED);
+		set_u32(LED_OFF, ACER_CAP_MAILLED);
 		data->mailled = value;
 	}
 
@@ -1580,6 +1599,17 @@
 	return 0;
 }
 
+static void acer_platform_shutdown(struct platform_device *device)
+{
+	struct acer_data *data = &interface->data;
+
+	if (!data)
+		return;
+
+	if (has_cap(ACER_CAP_MAILLED))
+		set_u32(LED_OFF, ACER_CAP_MAILLED);
+}
+
 static struct platform_driver acer_platform_driver = {
 	.driver = {
 		.name = "acer-wmi",
@@ -1589,6 +1619,7 @@
 	.remove = acer_platform_remove,
 	.suspend = acer_platform_suspend,
 	.resume = acer_platform_resume,
+	.shutdown = acer_platform_shutdown,
 };
 
 static struct platform_device *acer_platform_device;
@@ -1636,7 +1667,7 @@
 {
 	interface->debug.root = debugfs_create_dir("acer-wmi", NULL);
 	if (!interface->debug.root) {
-		printk(ACER_ERR "Failed to create debugfs directory");
+		pr_err("Failed to create debugfs directory");
 		return -ENOMEM;
 	}
 
@@ -1657,11 +1688,10 @@
 {
 	int err;
 
-	printk(ACER_INFO "Acer Laptop ACPI-WMI Extras\n");
+	pr_info("Acer Laptop ACPI-WMI Extras\n");
 
 	if (dmi_check_system(acer_blacklist)) {
-		printk(ACER_INFO "Blacklisted hardware detected - "
-				"not loading\n");
+		pr_info("Blacklisted hardware detected - not loading\n");
 		return -ENODEV;
 	}
 
@@ -1678,12 +1708,11 @@
 
 	if (wmi_has_guid(WMID_GUID2) && interface) {
 		if (ACPI_FAILURE(WMID_set_capabilities())) {
-			printk(ACER_ERR "Unable to detect available WMID "
-					"devices\n");
+			pr_err("Unable to detect available WMID devices\n");
 			return -ENODEV;
 		}
 	} else if (!wmi_has_guid(WMID_GUID2) && interface) {
-		printk(ACER_ERR "No WMID device detection method found\n");
+		pr_err("No WMID device detection method found\n");
 		return -ENODEV;
 	}
 
@@ -1691,8 +1720,7 @@
 		interface = &AMW0_interface;
 
 		if (ACPI_FAILURE(AMW0_set_capabilities())) {
-			printk(ACER_ERR "Unable to detect available AMW0 "
-					"devices\n");
+			pr_err("Unable to detect available AMW0 devices\n");
 			return -ENODEV;
 		}
 	}
@@ -1701,8 +1729,7 @@
 		AMW0_find_mailled();
 
 	if (!interface) {
-		printk(ACER_INFO "No or unsupported WMI interface, unable to "
-				"load\n");
+		pr_err("No or unsupported WMI interface, unable to load\n");
 		return -ENODEV;
 	}
 
@@ -1710,22 +1737,22 @@
 
 	if (acpi_video_backlight_support() && has_cap(ACER_CAP_BRIGHTNESS)) {
 		interface->capability &= ~ACER_CAP_BRIGHTNESS;
-		printk(ACER_INFO "Brightness must be controlled by "
+		pr_info("Brightness must be controlled by "
 		       "generic video driver\n");
 	}
 
 	if (wmi_has_guid(WMID_GUID3)) {
 		if (ec_raw_mode) {
 			if (ACPI_FAILURE(acer_wmi_enable_ec_raw())) {
-				printk(ACER_ERR "Cannot enable EC raw mode\n");
+				pr_err("Cannot enable EC raw mode\n");
 				return -ENODEV;
 			}
 		} else if (ACPI_FAILURE(acer_wmi_enable_lm())) {
-			printk(ACER_ERR "Cannot enable Launch Manager mode\n");
+			pr_err("Cannot enable Launch Manager mode\n");
 			return -ENODEV;
 		}
 	} else if (ec_raw_mode) {
-		printk(ACER_INFO "No WMID EC raw mode enable method\n");
+		pr_info("No WMID EC raw mode enable method\n");
 	}
 
 	if (wmi_has_guid(ACERWMID_EVENT_GUID)) {
@@ -1736,7 +1763,7 @@
 
 	err = platform_driver_register(&acer_platform_driver);
 	if (err) {
-		printk(ACER_ERR "Unable to register platform driver.\n");
+		pr_err("Unable to register platform driver.\n");
 		goto error_platform_register;
 	}
 
@@ -1791,7 +1818,7 @@
 	platform_device_unregister(acer_platform_device);
 	platform_driver_unregister(&acer_platform_driver);
 
-	printk(ACER_INFO "Acer Laptop WMI Extras unloaded\n");
+	pr_info("Acer Laptop WMI Extras unloaded\n");
 	return;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/asus_acpi.c linux-libre-2.6.39-gnu/drivers/platform/x86/asus_acpi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/asus_acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/asus_acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1507,6 +1507,7 @@
 	}
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	asus_backlight_device = backlight_device_register("asus", NULL, NULL,
 							  &asus_backlight_data,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/asus-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/asus-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/asus-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/asus-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,7 +29,7 @@
  *  John Belmonte  - ACPI code for Toshiba laptop was a good starting point.
  *  Eric Burghard  - LED display support for W1N
  *  Josh Green     - Light Sens support
- *  Thomas Tuttle  - His first patch for led support was very helpfull
+ *  Thomas Tuttle  - His first patch for led support was very helpful
  *  Sam Lin        - GPS support
  */
 
@@ -50,6 +50,7 @@
 #include <linux/input/sparse-keymap.h>
 #include <linux/rfkill.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 #include <acpi/acpi_drivers.h>
 #include <acpi/acpi_bus.h>
 
@@ -157,46 +158,9 @@
 #define METHOD_BRIGHTNESS_SET	"SPLV"
 #define METHOD_BRIGHTNESS_GET	"GPLV"
 
-/* Backlight */
-static acpi_handle lcd_switch_handle;
-static char *lcd_switch_paths[] = {
-  "\\_SB.PCI0.SBRG.EC0._Q10",	/* All new models */
-  "\\_SB.PCI0.ISA.EC0._Q10",	/* A1x */
-  "\\_SB.PCI0.PX40.ECD0._Q10",	/* L3C */
-  "\\_SB.PCI0.PX40.EC0.Q10",	/* M1A */
-  "\\_SB.PCI0.LPCB.EC0._Q10",	/* P30 */
-  "\\_SB.PCI0.LPCB.EC0._Q0E", /* P30/P35 */
-  "\\_SB.PCI0.PX40.Q10",	/* S1x */
-  "\\Q10"};		/* A2x, L2D, L3D, M2E */
-
 /* Display */
 #define METHOD_SWITCH_DISPLAY	"SDSP"
 
-static acpi_handle display_get_handle;
-static char *display_get_paths[] = {
-  /* A6B, A6K A6R A7D F3JM L4R M6R A3G M6A M6V VX-1 V6J V6V W3Z */
-  "\\_SB.PCI0.P0P1.VGA.GETD",
-  /* A3E A4K, A4D A4L A6J A7J A8J Z71V M9V S5A M5A z33A W1Jc W2V G1 */
-  "\\_SB.PCI0.P0P2.VGA.GETD",
-  /* A6V A6Q */
-  "\\_SB.PCI0.P0P3.VGA.GETD",
-  /* A6T, A6M */
-  "\\_SB.PCI0.P0PA.VGA.GETD",
-  /* L3C */
-  "\\_SB.PCI0.PCI1.VGAC.NMAP",
-  /* Z96F */
-  "\\_SB.PCI0.VGA.GETD",
-  /* A2D */
-  "\\ACTD",
-  /* A4G Z71A W1N W5A W5F M2N M3N M5N M6N S1N S5N */
-  "\\ADVG",
-  /* P30 */
-  "\\DNXT",
-  /* A2H D1 L2D L3D L3H L2E L5D L5C M1A M2E L4L W3V */
-  "\\INFB",
-  /* A3F A6F A3N A3L M6N W3N W6A */
-  "\\SSTE"};
-
 #define METHOD_ALS_CONTROL	"ALSC" /* Z71A Z71V */
 #define METHOD_ALS_LEVEL	"ALSL" /* Z71A Z71V */
 
@@ -246,7 +210,6 @@
 
 	int wireless_status;
 	bool have_rsts;
-	int lcd_state;
 
 	struct rfkill *gps_rfkill;
 
@@ -559,48 +522,6 @@
 /*
  * Backlight device
  */
-static int asus_lcd_status(struct asus_laptop *asus)
-{
-	return asus->lcd_state;
-}
-
-static int asus_lcd_set(struct asus_laptop *asus, int value)
-{
-	int lcd = 0;
-	acpi_status status = 0;
-
-	lcd = !!value;
-
-	if (lcd == asus_lcd_status(asus))
-		return 0;
-
-	if (!lcd_switch_handle)
-		return -ENODEV;
-
-	status = acpi_evaluate_object(lcd_switch_handle,
-				      NULL, NULL, NULL);
-
-	if (ACPI_FAILURE(status)) {
-		pr_warning("Error switching LCD\n");
-		return -ENODEV;
-	}
-
-	asus->lcd_state = lcd;
-	return 0;
-}
-
-static void lcd_blank(struct asus_laptop *asus, int blank)
-{
-	struct backlight_device *bd = asus->backlight_device;
-
-	asus->lcd_state = (blank == FB_BLANK_UNBLANK);
-
-	if (bd) {
-		bd->props.power = blank;
-		backlight_update_status(bd);
-	}
-}
-
 static int asus_read_brightness(struct backlight_device *bd)
 {
 	struct asus_laptop *asus = bl_get_data(bd);
@@ -628,16 +549,9 @@
 
 static int update_bl_status(struct backlight_device *bd)
 {
-	struct asus_laptop *asus = bl_get_data(bd);
-	int rv;
 	int value = bd->props.brightness;
 
-	rv = asus_set_brightness(bd, value);
-	if (rv)
-		return rv;
-
-	value = (bd->props.power == FB_BLANK_UNBLANK) ? 1 : 0;
-	return asus_lcd_set(asus, value);
+	return asus_set_brightness(bd, value);
 }
 
 static const struct backlight_ops asusbl_ops = {
@@ -661,12 +575,12 @@
 	struct backlight_properties props;
 
 	if (acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_GET, NULL) ||
-	    acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL) ||
-	    !lcd_switch_handle)
+	    acpi_check_handle(asus->handle, METHOD_BRIGHTNESS_SET, NULL))
 		return 0;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
 	props.max_brightness = 15;
+	props.type = BACKLIGHT_PLATFORM;
 
 	bd = backlight_device_register(ASUS_LAPTOP_FILE,
 				       &asus->platform_device->dev, asus,
@@ -970,41 +884,6 @@
 	return;
 }
 
-static int read_display(struct asus_laptop *asus)
-{
-	unsigned long long value = 0;
-	acpi_status rv = AE_OK;
-
-	/*
-	 * In most of the case, we know how to set the display, but sometime
-	 * we can't read it
-	 */
-	if (display_get_handle) {
-		rv = acpi_evaluate_integer(display_get_handle, NULL,
-					   NULL, &value);
-		if (ACPI_FAILURE(rv))
-			pr_warning("Error reading display status\n");
-	}
-
-	value &= 0x0F; /* needed for some models, shouldn't hurt others */
-
-	return value;
-}
-
-/*
- * Now, *this* one could be more user-friendly, but so far, no-one has
- * complained. The significance of bits is the same as in store_disp()
- */
-static ssize_t show_disp(struct device *dev,
-			 struct device_attribute *attr, char *buf)
-{
-	struct asus_laptop *asus = dev_get_drvdata(dev);
-
-	if (!display_get_handle)
-		return -ENODEV;
-	return sprintf(buf, "%d\n", read_display(asus));
-}
-
 /*
  * Experimental support for display switching. As of now: 1 should activate
  * the LCD output, 2 should do for CRT, 4 for TV-Out and 8 for DVI.
@@ -1246,15 +1125,6 @@
 	struct asus_laptop *asus = acpi_driver_data(device);
 	u16 count;
 
-	/*
-	 * We need to tell the backlight device when the backlight power is
-	 * switched
-	 */
-	if (event == ATKD_LCD_ON)
-		lcd_blank(asus, FB_BLANK_UNBLANK);
-	else if (event == ATKD_LCD_OFF)
-		lcd_blank(asus, FB_BLANK_POWERDOWN);
-
 	/* TODO Find a better way to handle events count. */
 	count = asus->event_count[event % 128]++;
 	acpi_bus_generate_proc_event(asus->device, event, count);
@@ -1281,7 +1151,7 @@
 		   show_bluetooth, store_bluetooth);
 static DEVICE_ATTR(wimax, S_IRUGO | S_IWUSR, show_wimax, store_wimax);
 static DEVICE_ATTR(wwan, S_IRUGO | S_IWUSR, show_wwan, store_wwan);
-static DEVICE_ATTR(display, S_IRUGO | S_IWUSR, show_disp, store_disp);
+static DEVICE_ATTR(display, S_IWUSR, NULL, store_disp);
 static DEVICE_ATTR(ledd, S_IRUGO | S_IWUSR, show_ledd, store_ledd);
 static DEVICE_ATTR(ls_level, S_IRUGO | S_IWUSR, show_lslvl, store_lslvl);
 static DEVICE_ATTR(ls_switch, S_IRUGO | S_IWUSR, show_lssw, store_lssw);
@@ -1392,26 +1262,6 @@
 	}
 };
 
-static int asus_handle_init(char *name, acpi_handle * handle,
-			    char **paths, int num_paths)
-{
-	int i;
-	acpi_status status;
-
-	for (i = 0; i < num_paths; i++) {
-		status = acpi_get_handle(NULL, paths[i], handle);
-		if (ACPI_SUCCESS(status))
-			return 0;
-	}
-
-	*handle = NULL;
-	return -ENODEV;
-}
-
-#define ASUS_HANDLE_INIT(object)					\
-	asus_handle_init(#object, &object##_handle, object##_paths,	\
-			 ARRAY_SIZE(object##_paths))
-
 /*
  * This function is used to initialize the context with right values. In this
  * method, we can make all the detection we want, and modify the asus_laptop
@@ -1497,10 +1347,6 @@
 	if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
 		asus->have_rsts = true;
 
-	/* Scheduled for removal */
-	ASUS_HANDLE_INIT(lcd_switch);
-	ASUS_HANDLE_INIT(display_get);
-
 	kfree(model);
 
 	return AE_OK;
@@ -1552,10 +1398,23 @@
 		asus_als_level(asus, asus->light_level);
 	}
 
-	asus->lcd_state = 1; /* LCD should be on when the module load */
 	return result;
 }
 
+static void __devinit asus_dmi_check(void)
+{
+	const char *model;
+
+	model = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!model)
+		return;
+
+	/* On L1400B WLED control the sound card, don't mess with it ... */
+	if (strncmp(model, "L1400B", 6) == 0) {
+		wlan_status = -1;
+	}
+}
+
 static bool asus_device_present;
 
 static int __devinit asus_acpi_add(struct acpi_device *device)
@@ -1574,6 +1433,8 @@
 	device->driver_data = asus;
 	asus->device = device;
 
+	asus_dmi_check();
+
 	result = asus_acpi_init(asus);
 	if (result)
 		goto fail_platform;
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/asus-nb-wmi.c linux-libre-2.6.39-gnu/drivers/platform/x86/asus-nb-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/asus-nb-wmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/asus-nb-wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * Asus Notebooks WMI hotkey driver
+ *
+ * Copyright(C) 2010 Corentin Chary <corentin.chary@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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+
+#include "asus-wmi.h"
+
+#define	ASUS_NB_WMI_FILE	"asus-nb-wmi"
+
+MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
+MODULE_DESCRIPTION("Asus Notebooks WMI Hotkey Driver");
+MODULE_LICENSE("GPL");
+
+#define ASUS_NB_WMI_EVENT_GUID	"0B3CBB35-E3C2-45ED-91C2-4C5A6D195D1C"
+
+MODULE_ALIAS("wmi:"ASUS_NB_WMI_EVENT_GUID);
+
+static const struct key_entry asus_nb_wmi_keymap[] = {
+	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
+	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 0x32, { KEY_MUTE } },
+	{ KE_KEY, 0x33, { KEY_DISPLAYTOGGLE } }, /* LCD on */
+	{ KE_KEY, 0x34, { KEY_DISPLAY_OFF } }, /* LCD off */
+	{ KE_KEY, 0x40, { KEY_PREVIOUSSONG } },
+	{ KE_KEY, 0x41, { KEY_NEXTSONG } },
+	{ KE_KEY, 0x43, { KEY_STOPCD } },
+	{ KE_KEY, 0x45, { KEY_PLAYPAUSE } },
+	{ KE_KEY, 0x4c, { KEY_MEDIA } },
+	{ KE_KEY, 0x50, { KEY_EMAIL } },
+	{ KE_KEY, 0x51, { KEY_WWW } },
+	{ KE_KEY, 0x55, { KEY_CALC } },
+	{ KE_KEY, 0x5C, { KEY_F15 } },  /* Power Gear key */
+	{ KE_KEY, 0x5D, { KEY_WLAN } },
+	{ KE_KEY, 0x5E, { KEY_WLAN } },
+	{ KE_KEY, 0x5F, { KEY_WLAN } },
+	{ KE_KEY, 0x60, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x61, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x62, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x63, { KEY_SWITCHVIDEOMODE } },
+	{ KE_KEY, 0x6B, { KEY_TOUCHPAD_TOGGLE } },
+	{ KE_KEY, 0x7E, { KEY_BLUETOOTH } },
+	{ KE_KEY, 0x7D, { KEY_BLUETOOTH } },
+	{ KE_KEY, 0x82, { KEY_CAMERA } },
+	{ KE_KEY, 0x88, { KEY_RFKILL  } },
+	{ KE_KEY, 0x8A, { KEY_PROG1 } },
+	{ KE_KEY, 0x95, { KEY_MEDIA } },
+	{ KE_KEY, 0x99, { KEY_PHONE } },
+	{ KE_KEY, 0xb5, { KEY_CALC } },
+	{ KE_KEY, 0xc4, { KEY_KBDILLUMUP } },
+	{ KE_KEY, 0xc5, { KEY_KBDILLUMDOWN } },
+	{ KE_END, 0},
+};
+
+static struct asus_wmi_driver asus_nb_wmi_driver = {
+	.name = ASUS_NB_WMI_FILE,
+	.owner = THIS_MODULE,
+	.event_guid = ASUS_NB_WMI_EVENT_GUID,
+	.keymap = asus_nb_wmi_keymap,
+	.input_name = "Asus WMI hotkeys",
+	.input_phys = ASUS_NB_WMI_FILE "/input0",
+};
+
+
+static int __init asus_nb_wmi_init(void)
+{
+	return asus_wmi_register_driver(&asus_nb_wmi_driver);
+}
+
+static void __exit asus_nb_wmi_exit(void)
+{
+	asus_wmi_unregister_driver(&asus_nb_wmi_driver);
+}
+
+module_init(asus_nb_wmi_init);
+module_exit(asus_nb_wmi_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/asus-wmi.c linux-libre-2.6.39-gnu/drivers/platform/x86/asus-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/asus-wmi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/asus-wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1656 @@
+/*
+ * Asus PC WMI hotkey driver
+ *
+ * Copyright(C) 2010 Intel Corporation.
+ * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/slab.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <linux/fb.h>
+#include <linux/backlight.h>
+#include <linux/leds.h>
+#include <linux/rfkill.h>
+#include <linux/pci.h>
+#include <linux/pci_hotplug.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/platform_device.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#include "asus-wmi.h"
+
+MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>, "
+	      "Yong Wang <yong.y.wang@intel.com>");
+MODULE_DESCRIPTION("Asus Generic WMI Driver");
+MODULE_LICENSE("GPL");
+
+#define to_platform_driver(drv)					\
+	(container_of((drv), struct platform_driver, driver))
+
+#define to_asus_wmi_driver(pdrv)					\
+	(container_of((pdrv), struct asus_wmi_driver, platform_driver))
+
+#define ASUS_WMI_MGMT_GUID	"97845ED0-4E6D-11DE-8A39-0800200C9A66"
+
+#define NOTIFY_BRNUP_MIN		0x11
+#define NOTIFY_BRNUP_MAX		0x1f
+#define NOTIFY_BRNDOWN_MIN		0x20
+#define NOTIFY_BRNDOWN_MAX		0x2e
+
+/* WMI Methods */
+#define ASUS_WMI_METHODID_SPEC	        0x43455053 /* BIOS SPECification */
+#define ASUS_WMI_METHODID_SFBD		0x44424653 /* Set First Boot Device */
+#define ASUS_WMI_METHODID_GLCD		0x44434C47 /* Get LCD status */
+#define ASUS_WMI_METHODID_GPID		0x44495047 /* Get Panel ID?? (Resol) */
+#define ASUS_WMI_METHODID_QMOD		0x444F4D51 /* Quiet MODe */
+#define ASUS_WMI_METHODID_SPLV		0x4C425053 /* Set Panel Light Value */
+#define ASUS_WMI_METHODID_SFUN		0x4E554653 /* FUNCtionalities */
+#define ASUS_WMI_METHODID_SDSP		0x50534453 /* Set DiSPlay output */
+#define ASUS_WMI_METHODID_GDSP		0x50534447 /* Get DiSPlay output */
+#define ASUS_WMI_METHODID_DEVP		0x50564544 /* DEVice Policy */
+#define ASUS_WMI_METHODID_OSVR		0x5256534F /* OS VeRsion */
+#define ASUS_WMI_METHODID_DSTS		0x53544344 /* Device STatuS */
+#define ASUS_WMI_METHODID_DSTS2		0x53545344 /* Device STatuS #2*/
+#define ASUS_WMI_METHODID_BSTS		0x53545342 /* Bios STatuS ? */
+#define ASUS_WMI_METHODID_DEVS		0x53564544 /* DEVice Set */
+#define ASUS_WMI_METHODID_CFVS		0x53564643 /* CPU Frequency Volt Set */
+#define ASUS_WMI_METHODID_KBFT		0x5446424B /* KeyBoard FilTer */
+#define ASUS_WMI_METHODID_INIT		0x54494E49 /* INITialize */
+#define ASUS_WMI_METHODID_HKEY		0x59454B48 /* Hot KEY ?? */
+
+#define ASUS_WMI_UNSUPPORTED_METHOD	0xFFFFFFFE
+
+/* Wireless */
+#define ASUS_WMI_DEVID_HW_SWITCH	0x00010001
+#define ASUS_WMI_DEVID_WIRELESS_LED	0x00010002
+#define ASUS_WMI_DEVID_WLAN		0x00010011
+#define ASUS_WMI_DEVID_BLUETOOTH	0x00010013
+#define ASUS_WMI_DEVID_GPS		0x00010015
+#define ASUS_WMI_DEVID_WIMAX		0x00010017
+#define ASUS_WMI_DEVID_WWAN3G		0x00010019
+#define ASUS_WMI_DEVID_UWB		0x00010021
+
+/* Leds */
+/* 0x000200XX and 0x000400XX */
+
+/* Backlight and Brightness */
+#define ASUS_WMI_DEVID_BACKLIGHT	0x00050011
+#define ASUS_WMI_DEVID_BRIGHTNESS	0x00050012
+#define ASUS_WMI_DEVID_KBD_BACKLIGHT	0x00050021
+#define ASUS_WMI_DEVID_LIGHT_SENSOR	0x00050022 /* ?? */
+
+/* Misc */
+#define ASUS_WMI_DEVID_CAMERA		0x00060013
+
+/* Storage */
+#define ASUS_WMI_DEVID_CARDREADER	0x00080013
+
+/* Input */
+#define ASUS_WMI_DEVID_TOUCHPAD		0x00100011
+#define ASUS_WMI_DEVID_TOUCHPAD_LED	0x00100012
+
+/* Fan, Thermal */
+#define ASUS_WMI_DEVID_THERMAL_CTRL	0x00110011
+#define ASUS_WMI_DEVID_FAN_CTRL		0x00110012
+
+/* Power */
+#define ASUS_WMI_DEVID_PROCESSOR_STATE	0x00120012
+
+/* DSTS masks */
+#define ASUS_WMI_DSTS_STATUS_BIT	0x00000001
+#define ASUS_WMI_DSTS_UNKNOWN_BIT	0x00000002
+#define ASUS_WMI_DSTS_PRESENCE_BIT	0x00010000
+#define ASUS_WMI_DSTS_USER_BIT		0x00020000
+#define ASUS_WMI_DSTS_BIOS_BIT		0x00040000
+#define ASUS_WMI_DSTS_BRIGHTNESS_MASK	0x000000FF
+#define ASUS_WMI_DSTS_MAX_BRIGTH_MASK	0x0000FF00
+
+struct bios_args {
+	u32 arg0;
+	u32 arg1;
+} __packed;
+
+/*
+ * <platform>/    - debugfs root directory
+ *   dev_id      - current dev_id
+ *   ctrl_param  - current ctrl_param
+ *   method_id   - current method_id
+ *   devs        - call DEVS(dev_id, ctrl_param) and print result
+ *   dsts        - call DSTS(dev_id)  and print result
+ *   call        - call method_id(dev_id, ctrl_param) and print result
+ */
+struct asus_wmi_debug {
+	struct dentry *root;
+	u32 method_id;
+	u32 dev_id;
+	u32 ctrl_param;
+};
+
+struct asus_rfkill {
+	struct asus_wmi *asus;
+	struct rfkill *rfkill;
+	u32 dev_id;
+};
+
+struct asus_wmi {
+	int dsts_id;
+	int spec;
+	int sfun;
+
+	struct input_dev *inputdev;
+	struct backlight_device *backlight_device;
+	struct device *hwmon_device;
+	struct platform_device *platform_device;
+
+	struct led_classdev tpd_led;
+	int tpd_led_wk;
+	struct workqueue_struct *led_workqueue;
+	struct work_struct tpd_led_work;
+
+	struct asus_rfkill wlan;
+	struct asus_rfkill bluetooth;
+	struct asus_rfkill wimax;
+	struct asus_rfkill wwan3g;
+
+	struct hotplug_slot *hotplug_slot;
+	struct mutex hotplug_lock;
+	struct mutex wmi_lock;
+	struct workqueue_struct *hotplug_workqueue;
+	struct work_struct hotplug_work;
+
+	struct asus_wmi_debug debug;
+
+	struct asus_wmi_driver *driver;
+};
+
+static int asus_wmi_input_init(struct asus_wmi *asus)
+{
+	int err;
+
+	asus->inputdev = input_allocate_device();
+	if (!asus->inputdev)
+		return -ENOMEM;
+
+	asus->inputdev->name = asus->driver->input_name;
+	asus->inputdev->phys = asus->driver->input_phys;
+	asus->inputdev->id.bustype = BUS_HOST;
+	asus->inputdev->dev.parent = &asus->platform_device->dev;
+
+	err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL);
+	if (err)
+		goto err_free_dev;
+
+	err = input_register_device(asus->inputdev);
+	if (err)
+		goto err_free_keymap;
+
+	return 0;
+
+err_free_keymap:
+	sparse_keymap_free(asus->inputdev);
+err_free_dev:
+	input_free_device(asus->inputdev);
+	return err;
+}
+
+static void asus_wmi_input_exit(struct asus_wmi *asus)
+{
+	if (asus->inputdev) {
+		sparse_keymap_free(asus->inputdev);
+		input_unregister_device(asus->inputdev);
+	}
+
+	asus->inputdev = NULL;
+}
+
+static int asus_wmi_evaluate_method(u32 method_id, u32 arg0, u32 arg1,
+				    u32 *retval)
+{
+	struct bios_args args = {
+		.arg0 = arg0,
+		.arg1 = arg1,
+	};
+	struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	acpi_status status;
+	union acpi_object *obj;
+	u32 tmp;
+
+	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID, 1, method_id,
+				     &input, &output);
+
+	if (ACPI_FAILURE(status))
+		goto exit;
+
+	obj = (union acpi_object *)output.pointer;
+	if (obj && obj->type == ACPI_TYPE_INTEGER)
+		tmp = (u32) obj->integer.value;
+	else
+		tmp = 0;
+
+	if (retval)
+		*retval = tmp;
+
+	kfree(obj);
+
+exit:
+	if (ACPI_FAILURE(status))
+		return -EIO;
+
+	if (tmp == ASUS_WMI_UNSUPPORTED_METHOD)
+		return -ENODEV;
+
+	return 0;
+}
+
+static int asus_wmi_get_devstate(struct asus_wmi *asus, u32 dev_id, u32 *retval)
+{
+	return asus_wmi_evaluate_method(asus->dsts_id, dev_id, 0, retval);
+}
+
+static int asus_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
+				 u32 *retval)
+{
+	return asus_wmi_evaluate_method(ASUS_WMI_METHODID_DEVS, dev_id,
+					ctrl_param, retval);
+}
+
+/* Helper for special devices with magic return codes */
+static int asus_wmi_get_devstate_bits(struct asus_wmi *asus,
+				      u32 dev_id, u32 mask)
+{
+	u32 retval = 0;
+	int err;
+
+	err = asus_wmi_get_devstate(asus, dev_id, &retval);
+
+	if (err < 0)
+		return err;
+
+	if (!(retval & ASUS_WMI_DSTS_PRESENCE_BIT))
+		return -ENODEV;
+
+	if (mask == ASUS_WMI_DSTS_STATUS_BIT) {
+		if (retval & ASUS_WMI_DSTS_UNKNOWN_BIT)
+			return -ENODEV;
+	}
+
+	return retval & mask;
+}
+
+static int asus_wmi_get_devstate_simple(struct asus_wmi *asus, u32 dev_id)
+{
+	return asus_wmi_get_devstate_bits(asus, dev_id,
+					  ASUS_WMI_DSTS_STATUS_BIT);
+}
+
+/*
+ * LEDs
+ */
+/*
+ * These functions actually update the LED's, and are called from a
+ * workqueue. By doing this as separate work rather than when the LED
+ * subsystem asks, we avoid messing with the Asus ACPI stuff during a
+ * potentially bad time, such as a timer interrupt.
+ */
+static void tpd_led_update(struct work_struct *work)
+{
+	int ctrl_param;
+	struct asus_wmi *asus;
+
+	asus = container_of(work, struct asus_wmi, tpd_led_work);
+
+	ctrl_param = asus->tpd_led_wk;
+	asus_wmi_set_devstate(ASUS_WMI_DEVID_TOUCHPAD_LED, ctrl_param, NULL);
+}
+
+static void tpd_led_set(struct led_classdev *led_cdev,
+			enum led_brightness value)
+{
+	struct asus_wmi *asus;
+
+	asus = container_of(led_cdev, struct asus_wmi, tpd_led);
+
+	asus->tpd_led_wk = !!value;
+	queue_work(asus->led_workqueue, &asus->tpd_led_work);
+}
+
+static int read_tpd_led_state(struct asus_wmi *asus)
+{
+	return asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_TOUCHPAD_LED);
+}
+
+static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
+{
+	struct asus_wmi *asus;
+
+	asus = container_of(led_cdev, struct asus_wmi, tpd_led);
+
+	return read_tpd_led_state(asus);
+}
+
+static int asus_wmi_led_init(struct asus_wmi *asus)
+{
+	int rv;
+
+	if (read_tpd_led_state(asus) < 0)
+		return 0;
+
+	asus->led_workqueue = create_singlethread_workqueue("led_workqueue");
+	if (!asus->led_workqueue)
+		return -ENOMEM;
+	INIT_WORK(&asus->tpd_led_work, tpd_led_update);
+
+	asus->tpd_led.name = "asus::touchpad";
+	asus->tpd_led.brightness_set = tpd_led_set;
+	asus->tpd_led.brightness_get = tpd_led_get;
+	asus->tpd_led.max_brightness = 1;
+
+	rv = led_classdev_register(&asus->platform_device->dev, &asus->tpd_led);
+	if (rv) {
+		destroy_workqueue(asus->led_workqueue);
+		return rv;
+	}
+
+	return 0;
+}
+
+static void asus_wmi_led_exit(struct asus_wmi *asus)
+{
+	if (asus->tpd_led.dev)
+		led_classdev_unregister(&asus->tpd_led);
+	if (asus->led_workqueue)
+		destroy_workqueue(asus->led_workqueue);
+}
+
+/*
+ * PCI hotplug (for wlan rfkill)
+ */
+static bool asus_wlan_rfkill_blocked(struct asus_wmi *asus)
+{
+	int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
+
+	if (result < 0)
+		return false;
+	return !result;
+}
+
+static void asus_rfkill_hotplug(struct asus_wmi *asus)
+{
+	struct pci_dev *dev;
+	struct pci_bus *bus;
+	bool blocked;
+	bool absent;
+	u32 l;
+
+	mutex_lock(&asus->wmi_lock);
+	blocked = asus_wlan_rfkill_blocked(asus);
+	mutex_unlock(&asus->wmi_lock);
+
+	mutex_lock(&asus->hotplug_lock);
+
+	if (asus->wlan.rfkill)
+		rfkill_set_sw_state(asus->wlan.rfkill, blocked);
+
+	if (asus->hotplug_slot) {
+		bus = pci_find_bus(0, 1);
+		if (!bus) {
+			pr_warning("Unable to find PCI bus 1?\n");
+			goto out_unlock;
+		}
+
+		if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
+			pr_err("Unable to read PCI config space?\n");
+			goto out_unlock;
+		}
+		absent = (l == 0xffffffff);
+
+		if (blocked != absent) {
+			pr_warning("BIOS says wireless lan is %s, "
+				   "but the pci device is %s\n",
+				   blocked ? "blocked" : "unblocked",
+				   absent ? "absent" : "present");
+			pr_warning("skipped wireless hotplug as probably "
+				   "inappropriate for this model\n");
+			goto out_unlock;
+		}
+
+		if (!blocked) {
+			dev = pci_get_slot(bus, 0);
+			if (dev) {
+				/* Device already present */
+				pci_dev_put(dev);
+				goto out_unlock;
+			}
+			dev = pci_scan_single_device(bus, 0);
+			if (dev) {
+				pci_bus_assign_resources(bus);
+				if (pci_bus_add_device(dev))
+					pr_err("Unable to hotplug wifi\n");
+			}
+		} else {
+			dev = pci_get_slot(bus, 0);
+			if (dev) {
+				pci_remove_bus_device(dev);
+				pci_dev_put(dev);
+			}
+		}
+	}
+
+out_unlock:
+	mutex_unlock(&asus->hotplug_lock);
+}
+
+static void asus_rfkill_notify(acpi_handle handle, u32 event, void *data)
+{
+	struct asus_wmi *asus = data;
+
+	if (event != ACPI_NOTIFY_BUS_CHECK)
+		return;
+
+	/*
+	 * We can't call directly asus_rfkill_hotplug because most
+	 * of the time WMBC is still being executed and not reetrant.
+	 * There is currently no way to tell ACPICA that  we want this
+	 * method to be serialized, we schedule a asus_rfkill_hotplug
+	 * call later, in a safer context.
+	 */
+	queue_work(asus->hotplug_workqueue, &asus->hotplug_work);
+}
+
+static int asus_register_rfkill_notifier(struct asus_wmi *asus, char *node)
+{
+	acpi_status status;
+	acpi_handle handle;
+
+	status = acpi_get_handle(NULL, node, &handle);
+
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_install_notify_handler(handle,
+						     ACPI_SYSTEM_NOTIFY,
+						     asus_rfkill_notify, asus);
+		if (ACPI_FAILURE(status))
+			pr_warning("Failed to register notify on %s\n", node);
+	} else
+		return -ENODEV;
+
+	return 0;
+}
+
+static void asus_unregister_rfkill_notifier(struct asus_wmi *asus, char *node)
+{
+	acpi_status status = AE_OK;
+	acpi_handle handle;
+
+	status = acpi_get_handle(NULL, node, &handle);
+
+	if (ACPI_SUCCESS(status)) {
+		status = acpi_remove_notify_handler(handle,
+						    ACPI_SYSTEM_NOTIFY,
+						    asus_rfkill_notify);
+		if (ACPI_FAILURE(status))
+			pr_err("Error removing rfkill notify handler %s\n",
+			       node);
+	}
+}
+
+static int asus_get_adapter_status(struct hotplug_slot *hotplug_slot,
+				   u8 *value)
+{
+	struct asus_wmi *asus = hotplug_slot->private;
+	int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
+
+	if (result < 0)
+		return result;
+
+	*value = !!result;
+	return 0;
+}
+
+static void asus_cleanup_pci_hotplug(struct hotplug_slot *hotplug_slot)
+{
+	kfree(hotplug_slot->info);
+	kfree(hotplug_slot);
+}
+
+static struct hotplug_slot_ops asus_hotplug_slot_ops = {
+	.owner = THIS_MODULE,
+	.get_adapter_status = asus_get_adapter_status,
+	.get_power_status = asus_get_adapter_status,
+};
+
+static void asus_hotplug_work(struct work_struct *work)
+{
+	struct asus_wmi *asus;
+
+	asus = container_of(work, struct asus_wmi, hotplug_work);
+	asus_rfkill_hotplug(asus);
+}
+
+static int asus_setup_pci_hotplug(struct asus_wmi *asus)
+{
+	int ret = -ENOMEM;
+	struct pci_bus *bus = pci_find_bus(0, 1);
+
+	if (!bus) {
+		pr_err("Unable to find wifi PCI bus\n");
+		return -ENODEV;
+	}
+
+	asus->hotplug_workqueue =
+	    create_singlethread_workqueue("hotplug_workqueue");
+	if (!asus->hotplug_workqueue)
+		goto error_workqueue;
+
+	INIT_WORK(&asus->hotplug_work, asus_hotplug_work);
+
+	asus->hotplug_slot = kzalloc(sizeof(struct hotplug_slot), GFP_KERNEL);
+	if (!asus->hotplug_slot)
+		goto error_slot;
+
+	asus->hotplug_slot->info = kzalloc(sizeof(struct hotplug_slot_info),
+					   GFP_KERNEL);
+	if (!asus->hotplug_slot->info)
+		goto error_info;
+
+	asus->hotplug_slot->private = asus;
+	asus->hotplug_slot->release = &asus_cleanup_pci_hotplug;
+	asus->hotplug_slot->ops = &asus_hotplug_slot_ops;
+	asus_get_adapter_status(asus->hotplug_slot,
+				&asus->hotplug_slot->info->adapter_status);
+
+	ret = pci_hp_register(asus->hotplug_slot, bus, 0, "asus-wifi");
+	if (ret) {
+		pr_err("Unable to register hotplug slot - %d\n", ret);
+		goto error_register;
+	}
+
+	return 0;
+
+error_register:
+	kfree(asus->hotplug_slot->info);
+error_info:
+	kfree(asus->hotplug_slot);
+	asus->hotplug_slot = NULL;
+error_slot:
+	destroy_workqueue(asus->hotplug_workqueue);
+error_workqueue:
+	return ret;
+}
+
+/*
+ * Rfkill devices
+ */
+static int asus_rfkill_set(void *data, bool blocked)
+{
+	struct asus_rfkill *priv = data;
+	u32 ctrl_param = !blocked;
+
+	return asus_wmi_set_devstate(priv->dev_id, ctrl_param, NULL);
+}
+
+static void asus_rfkill_query(struct rfkill *rfkill, void *data)
+{
+	struct asus_rfkill *priv = data;
+	int result;
+
+	result = asus_wmi_get_devstate_simple(priv->asus, priv->dev_id);
+
+	if (result < 0)
+		return;
+
+	rfkill_set_sw_state(priv->rfkill, !result);
+}
+
+static int asus_rfkill_wlan_set(void *data, bool blocked)
+{
+	struct asus_rfkill *priv = data;
+	struct asus_wmi *asus = priv->asus;
+	int ret;
+
+	/*
+	 * This handler is enabled only if hotplug is enabled.
+	 * In this case, the asus_wmi_set_devstate() will
+	 * trigger a wmi notification and we need to wait
+	 * this call to finish before being able to call
+	 * any wmi method
+	 */
+	mutex_lock(&asus->wmi_lock);
+	ret = asus_rfkill_set(data, blocked);
+	mutex_unlock(&asus->wmi_lock);
+	return ret;
+}
+
+static const struct rfkill_ops asus_rfkill_wlan_ops = {
+	.set_block = asus_rfkill_wlan_set,
+	.query = asus_rfkill_query,
+};
+
+static const struct rfkill_ops asus_rfkill_ops = {
+	.set_block = asus_rfkill_set,
+	.query = asus_rfkill_query,
+};
+
+static int asus_new_rfkill(struct asus_wmi *asus,
+			   struct asus_rfkill *arfkill,
+			   const char *name, enum rfkill_type type, int dev_id)
+{
+	int result = asus_wmi_get_devstate_simple(asus, dev_id);
+	struct rfkill **rfkill = &arfkill->rfkill;
+
+	if (result < 0)
+		return result;
+
+	arfkill->dev_id = dev_id;
+	arfkill->asus = asus;
+
+	if (dev_id == ASUS_WMI_DEVID_WLAN && asus->driver->hotplug_wireless)
+		*rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
+				       &asus_rfkill_wlan_ops, arfkill);
+	else
+		*rfkill = rfkill_alloc(name, &asus->platform_device->dev, type,
+				       &asus_rfkill_ops, arfkill);
+
+	if (!*rfkill)
+		return -EINVAL;
+
+	rfkill_init_sw_state(*rfkill, !result);
+	result = rfkill_register(*rfkill);
+	if (result) {
+		rfkill_destroy(*rfkill);
+		*rfkill = NULL;
+		return result;
+	}
+	return 0;
+}
+
+static void asus_wmi_rfkill_exit(struct asus_wmi *asus)
+{
+	asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
+	asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
+	asus_unregister_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
+	if (asus->wlan.rfkill) {
+		rfkill_unregister(asus->wlan.rfkill);
+		rfkill_destroy(asus->wlan.rfkill);
+		asus->wlan.rfkill = NULL;
+	}
+	/*
+	 * Refresh pci hotplug in case the rfkill state was changed after
+	 * asus_unregister_rfkill_notifier()
+	 */
+	asus_rfkill_hotplug(asus);
+	if (asus->hotplug_slot)
+		pci_hp_deregister(asus->hotplug_slot);
+	if (asus->hotplug_workqueue)
+		destroy_workqueue(asus->hotplug_workqueue);
+
+	if (asus->bluetooth.rfkill) {
+		rfkill_unregister(asus->bluetooth.rfkill);
+		rfkill_destroy(asus->bluetooth.rfkill);
+		asus->bluetooth.rfkill = NULL;
+	}
+	if (asus->wimax.rfkill) {
+		rfkill_unregister(asus->wimax.rfkill);
+		rfkill_destroy(asus->wimax.rfkill);
+		asus->wimax.rfkill = NULL;
+	}
+	if (asus->wwan3g.rfkill) {
+		rfkill_unregister(asus->wwan3g.rfkill);
+		rfkill_destroy(asus->wwan3g.rfkill);
+		asus->wwan3g.rfkill = NULL;
+	}
+}
+
+static int asus_wmi_rfkill_init(struct asus_wmi *asus)
+{
+	int result = 0;
+
+	mutex_init(&asus->hotplug_lock);
+	mutex_init(&asus->wmi_lock);
+
+	result = asus_new_rfkill(asus, &asus->wlan, "asus-wlan",
+				 RFKILL_TYPE_WLAN, ASUS_WMI_DEVID_WLAN);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = asus_new_rfkill(asus, &asus->bluetooth,
+				 "asus-bluetooth", RFKILL_TYPE_BLUETOOTH,
+				 ASUS_WMI_DEVID_BLUETOOTH);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = asus_new_rfkill(asus, &asus->wimax, "asus-wimax",
+				 RFKILL_TYPE_WIMAX, ASUS_WMI_DEVID_WIMAX);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	result = asus_new_rfkill(asus, &asus->wwan3g, "asus-wwan3g",
+				 RFKILL_TYPE_WWAN, ASUS_WMI_DEVID_WWAN3G);
+
+	if (result && result != -ENODEV)
+		goto exit;
+
+	if (!asus->driver->hotplug_wireless)
+		goto exit;
+
+	result = asus_setup_pci_hotplug(asus);
+	/*
+	 * If we get -EBUSY then something else is handling the PCI hotplug -
+	 * don't fail in this case
+	 */
+	if (result == -EBUSY)
+		result = 0;
+
+	asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P5");
+	asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P6");
+	asus_register_rfkill_notifier(asus, "\\_SB.PCI0.P0P7");
+	/*
+	 * Refresh pci hotplug in case the rfkill state was changed during
+	 * setup.
+	 */
+	asus_rfkill_hotplug(asus);
+
+exit:
+	if (result && result != -ENODEV)
+		asus_wmi_rfkill_exit(asus);
+
+	if (result == -ENODEV)
+		result = 0;
+
+	return result;
+}
+
+/*
+ * Hwmon device
+ */
+static ssize_t asus_hwmon_pwm1(struct device *dev,
+			    struct device_attribute *attr,
+			    char *buf)
+{
+	struct asus_wmi *asus = dev_get_drvdata(dev);
+	u32 value;
+	int err;
+
+	err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_FAN_CTRL, &value);
+
+	if (err < 0)
+		return err;
+
+	value |= 0xFF;
+
+	if (value == 1) /* Low Speed */
+		value = 85;
+	else if (value == 2)
+		value = 170;
+	else if (value == 3)
+		value = 255;
+	else if (value != 0) {
+		pr_err("Unknown fan speed %#x", value);
+		value = -1;
+	}
+
+	return sprintf(buf, "%d\n", value);
+}
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO, asus_hwmon_pwm1, NULL, 0);
+
+static ssize_t
+show_name(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	return sprintf(buf, "asus\n");
+}
+static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0);
+
+static struct attribute *hwmon_attributes[] = {
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_name.dev_attr.attr,
+	NULL
+};
+
+static mode_t asus_hwmon_sysfs_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int idx)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev->parent);
+	struct asus_wmi *asus = platform_get_drvdata(pdev);
+	bool ok = true;
+	int dev_id = -1;
+	u32 value = ASUS_WMI_UNSUPPORTED_METHOD;
+
+	if (attr == &sensor_dev_attr_pwm1.dev_attr.attr)
+		dev_id = ASUS_WMI_DEVID_FAN_CTRL;
+
+	if (dev_id != -1) {
+		int err = asus_wmi_get_devstate(asus, dev_id, &value);
+
+		if (err < 0)
+			return err;
+	}
+
+	if (dev_id == ASUS_WMI_DEVID_FAN_CTRL) {
+		/*
+		 * We need to find a better way, probably using sfun,
+		 * bits or spec ...
+		 * Currently we disable it if:
+		 * - ASUS_WMI_UNSUPPORTED_METHOD is returned
+		 * - reverved bits are non-zero
+		 * - sfun and presence bit are not set
+		 */
+		if (value != ASUS_WMI_UNSUPPORTED_METHOD || value & 0xFFF80000
+		    || (!asus->sfun && !(value & ASUS_WMI_DSTS_PRESENCE_BIT)))
+			ok = false;
+	}
+
+	return ok ? attr->mode : 0;
+}
+
+static struct attribute_group hwmon_attribute_group = {
+	.is_visible = asus_hwmon_sysfs_is_visible,
+	.attrs = hwmon_attributes
+};
+
+static void asus_wmi_hwmon_exit(struct asus_wmi *asus)
+{
+	struct device *hwmon;
+
+	hwmon = asus->hwmon_device;
+	if (!hwmon)
+		return;
+	sysfs_remove_group(&hwmon->kobj, &hwmon_attribute_group);
+	hwmon_device_unregister(hwmon);
+	asus->hwmon_device = NULL;
+}
+
+static int asus_wmi_hwmon_init(struct asus_wmi *asus)
+{
+	struct device *hwmon;
+	int result;
+
+	hwmon = hwmon_device_register(&asus->platform_device->dev);
+	if (IS_ERR(hwmon)) {
+		pr_err("Could not register asus hwmon device\n");
+		return PTR_ERR(hwmon);
+	}
+	asus->hwmon_device = hwmon;
+	result = sysfs_create_group(&hwmon->kobj, &hwmon_attribute_group);
+	if (result)
+		asus_wmi_hwmon_exit(asus);
+	return result;
+}
+
+/*
+ * Backlight
+ */
+static int read_backlight_power(struct asus_wmi *asus)
+{
+	int ret = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_BACKLIGHT);
+
+	if (ret < 0)
+		return ret;
+
+	return ret ? FB_BLANK_UNBLANK : FB_BLANK_POWERDOWN;
+}
+
+static int read_brightness_max(struct asus_wmi *asus)
+{
+	u32 retval;
+	int err;
+
+	err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
+
+	if (err < 0)
+		return err;
+
+	retval = retval & ASUS_WMI_DSTS_MAX_BRIGTH_MASK;
+	retval >>= 8;
+
+	if (!retval)
+		return -ENODEV;
+
+	return retval;
+}
+
+static int read_brightness(struct backlight_device *bd)
+{
+	struct asus_wmi *asus = bl_get_data(bd);
+	u32 retval;
+	int err;
+
+	err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_BRIGHTNESS, &retval);
+
+	if (err < 0)
+		return err;
+
+	return retval & ASUS_WMI_DSTS_BRIGHTNESS_MASK;
+}
+
+static int update_bl_status(struct backlight_device *bd)
+{
+	struct asus_wmi *asus = bl_get_data(bd);
+	u32 ctrl_param;
+	int power, err;
+
+	ctrl_param = bd->props.brightness;
+
+	err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BRIGHTNESS,
+				    ctrl_param, NULL);
+
+	if (err < 0)
+		return err;
+
+	power = read_backlight_power(asus);
+	if (power != -ENODEV && bd->props.power != power) {
+		ctrl_param = !!(bd->props.power == FB_BLANK_UNBLANK);
+		err = asus_wmi_set_devstate(ASUS_WMI_DEVID_BACKLIGHT,
+					    ctrl_param, NULL);
+	}
+	return err;
+}
+
+static const struct backlight_ops asus_wmi_bl_ops = {
+	.get_brightness = read_brightness,
+	.update_status = update_bl_status,
+};
+
+static int asus_wmi_backlight_notify(struct asus_wmi *asus, int code)
+{
+	struct backlight_device *bd = asus->backlight_device;
+	int old = bd->props.brightness;
+	int new = old;
+
+	if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
+		new = code - NOTIFY_BRNUP_MIN + 1;
+	else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
+		new = code - NOTIFY_BRNDOWN_MIN;
+
+	bd->props.brightness = new;
+	backlight_update_status(bd);
+	backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
+
+	return old;
+}
+
+static int asus_wmi_backlight_init(struct asus_wmi *asus)
+{
+	struct backlight_device *bd;
+	struct backlight_properties props;
+	int max;
+	int power;
+
+	max = read_brightness_max(asus);
+
+	if (max == -ENODEV)
+		max = 0;
+	else if (max < 0)
+		return max;
+
+	power = read_backlight_power(asus);
+
+	if (power == -ENODEV)
+		power = FB_BLANK_UNBLANK;
+	else if (power < 0)
+		return power;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.max_brightness = max;
+	bd = backlight_device_register(asus->driver->name,
+				       &asus->platform_device->dev, asus,
+				       &asus_wmi_bl_ops, &props);
+	if (IS_ERR(bd)) {
+		pr_err("Could not register backlight device\n");
+		return PTR_ERR(bd);
+	}
+
+	asus->backlight_device = bd;
+
+	bd->props.brightness = read_brightness(bd);
+	bd->props.power = power;
+	backlight_update_status(bd);
+
+	return 0;
+}
+
+static void asus_wmi_backlight_exit(struct asus_wmi *asus)
+{
+	if (asus->backlight_device)
+		backlight_device_unregister(asus->backlight_device);
+
+	asus->backlight_device = NULL;
+}
+
+static void asus_wmi_notify(u32 value, void *context)
+{
+	struct asus_wmi *asus = context;
+	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	acpi_status status;
+	int code;
+	int orig_code;
+
+	status = wmi_get_event_data(value, &response);
+	if (status != AE_OK) {
+		pr_err("bad event status 0x%x\n", status);
+		return;
+	}
+
+	obj = (union acpi_object *)response.pointer;
+
+	if (!obj || obj->type != ACPI_TYPE_INTEGER)
+		goto exit;
+
+	code = obj->integer.value;
+	orig_code = code;
+
+	if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
+		code = NOTIFY_BRNUP_MIN;
+	else if (code >= NOTIFY_BRNDOWN_MIN &&
+		 code <= NOTIFY_BRNDOWN_MAX)
+		code = NOTIFY_BRNDOWN_MIN;
+
+	if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
+		if (!acpi_video_backlight_support())
+			asus_wmi_backlight_notify(asus, orig_code);
+	} else if (!sparse_keymap_report_event(asus->inputdev, code, 1, true))
+		pr_info("Unknown key %x pressed\n", code);
+
+exit:
+	kfree(obj);
+}
+
+/*
+ * Sys helpers
+ */
+static int parse_arg(const char *buf, unsigned long count, int *val)
+{
+	if (!count)
+		return 0;
+	if (sscanf(buf, "%i", val) != 1)
+		return -EINVAL;
+	return count;
+}
+
+static ssize_t store_sys_wmi(struct asus_wmi *asus, int devid,
+			     const char *buf, size_t count)
+{
+	u32 retval;
+	int rv, err, value;
+
+	value = asus_wmi_get_devstate_simple(asus, devid);
+	if (value == -ENODEV)	/* Check device presence */
+		return value;
+
+	rv = parse_arg(buf, count, &value);
+	err = asus_wmi_set_devstate(devid, value, &retval);
+
+	if (err < 0)
+		return err;
+
+	return rv;
+}
+
+static ssize_t show_sys_wmi(struct asus_wmi *asus, int devid, char *buf)
+{
+	int value = asus_wmi_get_devstate_simple(asus, devid);
+
+	if (value < 0)
+		return value;
+
+	return sprintf(buf, "%d\n", value);
+}
+
+#define ASUS_WMI_CREATE_DEVICE_ATTR(_name, _mode, _cm)			\
+	static ssize_t show_##_name(struct device *dev,			\
+				    struct device_attribute *attr,	\
+				    char *buf)				\
+	{								\
+		struct asus_wmi *asus = dev_get_drvdata(dev);		\
+									\
+		return show_sys_wmi(asus, _cm, buf);			\
+	}								\
+	static ssize_t store_##_name(struct device *dev,		\
+				     struct device_attribute *attr,	\
+				     const char *buf, size_t count)	\
+	{								\
+		struct asus_wmi *asus = dev_get_drvdata(dev);		\
+									\
+		return store_sys_wmi(asus, _cm, buf, count);		\
+	}								\
+	static struct device_attribute dev_attr_##_name = {		\
+		.attr = {						\
+			.name = __stringify(_name),			\
+			.mode = _mode },				\
+		.show   = show_##_name,					\
+		.store  = store_##_name,				\
+	}
+
+ASUS_WMI_CREATE_DEVICE_ATTR(touchpad, 0644, ASUS_WMI_DEVID_TOUCHPAD);
+ASUS_WMI_CREATE_DEVICE_ATTR(camera, 0644, ASUS_WMI_DEVID_CAMERA);
+ASUS_WMI_CREATE_DEVICE_ATTR(cardr, 0644, ASUS_WMI_DEVID_CARDREADER);
+
+static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	int value;
+
+	if (!count || sscanf(buf, "%i", &value) != 1)
+		return -EINVAL;
+	if (value < 0 || value > 2)
+		return -EINVAL;
+
+	return asus_wmi_evaluate_method(ASUS_WMI_METHODID_CFVS, value, 0, NULL);
+}
+
+static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
+
+static struct attribute *platform_attributes[] = {
+	&dev_attr_cpufv.attr,
+	&dev_attr_camera.attr,
+	&dev_attr_cardr.attr,
+	&dev_attr_touchpad.attr,
+	NULL
+};
+
+static mode_t asus_sysfs_is_visible(struct kobject *kobj,
+				    struct attribute *attr, int idx)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct platform_device *pdev = to_platform_device(dev);
+	struct asus_wmi *asus = platform_get_drvdata(pdev);
+	bool ok = true;
+	int devid = -1;
+
+	if (attr == &dev_attr_camera.attr)
+		devid = ASUS_WMI_DEVID_CAMERA;
+	else if (attr == &dev_attr_cardr.attr)
+		devid = ASUS_WMI_DEVID_CARDREADER;
+	else if (attr == &dev_attr_touchpad.attr)
+		devid = ASUS_WMI_DEVID_TOUCHPAD;
+
+	if (devid != -1)
+		ok = !(asus_wmi_get_devstate_simple(asus, devid) < 0);
+
+	return ok ? attr->mode : 0;
+}
+
+static struct attribute_group platform_attribute_group = {
+	.is_visible = asus_sysfs_is_visible,
+	.attrs = platform_attributes
+};
+
+static void asus_wmi_sysfs_exit(struct platform_device *device)
+{
+	sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
+}
+
+static int asus_wmi_sysfs_init(struct platform_device *device)
+{
+	return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
+}
+
+/*
+ * Platform device
+ */
+static int __init asus_wmi_platform_init(struct asus_wmi *asus)
+{
+	int rv;
+
+	/* INIT enable hotkeys on some models */
+	if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_INIT, 0, 0, &rv))
+		pr_info("Initialization: %#x", rv);
+
+	/* We don't know yet what to do with this version... */
+	if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SPEC, 0, 0x9, &rv)) {
+		pr_info("BIOS WMI version: %d.%d", rv >> 8, rv & 0xFF);
+		asus->spec = rv;
+	}
+
+	/*
+	 * The SFUN method probably allows the original driver to get the list
+	 * of features supported by a given model. For now, 0x0100 or 0x0800
+	 * bit signifies that the laptop is equipped with a Wi-Fi MiniPCI card.
+	 * The significance of others is yet to be found.
+	 */
+	if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_SFUN, 0, 0, &rv)) {
+		pr_info("SFUN value: %#x", rv);
+		asus->sfun = rv;
+	}
+
+	/*
+	 * Eee PC and Notebooks seems to have different method_id for DSTS,
+	 * but it may also be related to the BIOS's SPEC.
+	 * Note, on most Eeepc, there is no way to check if a method exist
+	 * or note, while on notebooks, they returns 0xFFFFFFFE on failure,
+	 * but once again, SPEC may probably be used for that kind of things.
+	 */
+	if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS, 0, 0, NULL))
+		asus->dsts_id = ASUS_WMI_METHODID_DSTS;
+	else if (!asus_wmi_evaluate_method(ASUS_WMI_METHODID_DSTS2, 0, 0, NULL))
+		asus->dsts_id = ASUS_WMI_METHODID_DSTS2;
+
+	if (!asus->dsts_id) {
+		pr_err("Can't find DSTS");
+		return -ENODEV;
+	}
+
+	return asus_wmi_sysfs_init(asus->platform_device);
+}
+
+static void asus_wmi_platform_exit(struct asus_wmi *asus)
+{
+	asus_wmi_sysfs_exit(asus->platform_device);
+}
+
+/*
+ * debugfs
+ */
+struct asus_wmi_debugfs_node {
+	struct asus_wmi *asus;
+	char *name;
+	int (*show) (struct seq_file *m, void *data);
+};
+
+static int show_dsts(struct seq_file *m, void *data)
+{
+	struct asus_wmi *asus = m->private;
+	int err;
+	u32 retval = -1;
+
+	err = asus_wmi_get_devstate(asus, asus->debug.dev_id, &retval);
+
+	if (err < 0)
+		return err;
+
+	seq_printf(m, "DSTS(%#x) = %#x\n", asus->debug.dev_id, retval);
+
+	return 0;
+}
+
+static int show_devs(struct seq_file *m, void *data)
+{
+	struct asus_wmi *asus = m->private;
+	int err;
+	u32 retval = -1;
+
+	err = asus_wmi_set_devstate(asus->debug.dev_id, asus->debug.ctrl_param,
+				    &retval);
+
+	if (err < 0)
+		return err;
+
+	seq_printf(m, "DEVS(%#x, %#x) = %#x\n", asus->debug.dev_id,
+		   asus->debug.ctrl_param, retval);
+
+	return 0;
+}
+
+static int show_call(struct seq_file *m, void *data)
+{
+	struct asus_wmi *asus = m->private;
+	struct bios_args args = {
+		.arg0 = asus->debug.dev_id,
+		.arg1 = asus->debug.ctrl_param,
+	};
+	struct acpi_buffer input = { (acpi_size) sizeof(args), &args };
+	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	acpi_status status;
+
+	status = wmi_evaluate_method(ASUS_WMI_MGMT_GUID,
+				     1, asus->debug.method_id,
+				     &input, &output);
+
+	if (ACPI_FAILURE(status))
+		return -EIO;
+
+	obj = (union acpi_object *)output.pointer;
+	if (obj && obj->type == ACPI_TYPE_INTEGER)
+		seq_printf(m, "%#x(%#x, %#x) = %#x\n", asus->debug.method_id,
+			   asus->debug.dev_id, asus->debug.ctrl_param,
+			   (u32) obj->integer.value);
+	else
+		seq_printf(m, "%#x(%#x, %#x) = t:%d\n", asus->debug.method_id,
+			   asus->debug.dev_id, asus->debug.ctrl_param,
+			   obj ? obj->type : -1);
+
+	kfree(obj);
+
+	return 0;
+}
+
+static struct asus_wmi_debugfs_node asus_wmi_debug_files[] = {
+	{NULL, "devs", show_devs},
+	{NULL, "dsts", show_dsts},
+	{NULL, "call", show_call},
+};
+
+static int asus_wmi_debugfs_open(struct inode *inode, struct file *file)
+{
+	struct asus_wmi_debugfs_node *node = inode->i_private;
+
+	return single_open(file, node->show, node->asus);
+}
+
+static const struct file_operations asus_wmi_debugfs_io_ops = {
+	.owner = THIS_MODULE,
+	.open = asus_wmi_debugfs_open,
+	.read = seq_read,
+	.llseek = seq_lseek,
+	.release = single_release,
+};
+
+static void asus_wmi_debugfs_exit(struct asus_wmi *asus)
+{
+	debugfs_remove_recursive(asus->debug.root);
+}
+
+static int asus_wmi_debugfs_init(struct asus_wmi *asus)
+{
+	struct dentry *dent;
+	int i;
+
+	asus->debug.root = debugfs_create_dir(asus->driver->name, NULL);
+	if (!asus->debug.root) {
+		pr_err("failed to create debugfs directory");
+		goto error_debugfs;
+	}
+
+	dent = debugfs_create_x32("method_id", S_IRUGO | S_IWUSR,
+				  asus->debug.root, &asus->debug.method_id);
+	if (!dent)
+		goto error_debugfs;
+
+	dent = debugfs_create_x32("dev_id", S_IRUGO | S_IWUSR,
+				  asus->debug.root, &asus->debug.dev_id);
+	if (!dent)
+		goto error_debugfs;
+
+	dent = debugfs_create_x32("ctrl_param", S_IRUGO | S_IWUSR,
+				  asus->debug.root, &asus->debug.ctrl_param);
+	if (!dent)
+		goto error_debugfs;
+
+	for (i = 0; i < ARRAY_SIZE(asus_wmi_debug_files); i++) {
+		struct asus_wmi_debugfs_node *node = &asus_wmi_debug_files[i];
+
+		node->asus = asus;
+		dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
+					   asus->debug.root, node,
+					   &asus_wmi_debugfs_io_ops);
+		if (!dent) {
+			pr_err("failed to create debug file: %s\n", node->name);
+			goto error_debugfs;
+		}
+	}
+
+	return 0;
+
+error_debugfs:
+	asus_wmi_debugfs_exit(asus);
+	return -ENOMEM;
+}
+
+/*
+ * WMI Driver
+ */
+static int asus_wmi_add(struct platform_device *pdev)
+{
+	struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
+	struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
+	struct asus_wmi *asus;
+	acpi_status status;
+	int err;
+
+	asus = kzalloc(sizeof(struct asus_wmi), GFP_KERNEL);
+	if (!asus)
+		return -ENOMEM;
+
+	asus->driver = wdrv;
+	asus->platform_device = pdev;
+	wdrv->platform_device = pdev;
+	platform_set_drvdata(asus->platform_device, asus);
+
+	if (wdrv->quirks)
+		wdrv->quirks(asus->driver);
+
+	err = asus_wmi_platform_init(asus);
+	if (err)
+		goto fail_platform;
+
+	err = asus_wmi_input_init(asus);
+	if (err)
+		goto fail_input;
+
+	err = asus_wmi_hwmon_init(asus);
+	if (err)
+		goto fail_hwmon;
+
+	err = asus_wmi_led_init(asus);
+	if (err)
+		goto fail_leds;
+
+	err = asus_wmi_rfkill_init(asus);
+	if (err)
+		goto fail_rfkill;
+
+	if (!acpi_video_backlight_support()) {
+		err = asus_wmi_backlight_init(asus);
+		if (err && err != -ENODEV)
+			goto fail_backlight;
+	} else
+		pr_info("Backlight controlled by ACPI video driver\n");
+
+	status = wmi_install_notify_handler(asus->driver->event_guid,
+					    asus_wmi_notify, asus);
+	if (ACPI_FAILURE(status)) {
+		pr_err("Unable to register notify handler - %d\n", status);
+		err = -ENODEV;
+		goto fail_wmi_handler;
+	}
+
+	err = asus_wmi_debugfs_init(asus);
+	if (err)
+		goto fail_debugfs;
+
+	return 0;
+
+fail_debugfs:
+	wmi_remove_notify_handler(asus->driver->event_guid);
+fail_wmi_handler:
+	asus_wmi_backlight_exit(asus);
+fail_backlight:
+	asus_wmi_rfkill_exit(asus);
+fail_rfkill:
+	asus_wmi_led_exit(asus);
+fail_leds:
+	asus_wmi_hwmon_exit(asus);
+fail_hwmon:
+	asus_wmi_input_exit(asus);
+fail_input:
+	asus_wmi_platform_exit(asus);
+fail_platform:
+	kfree(asus);
+	return err;
+}
+
+static int asus_wmi_remove(struct platform_device *device)
+{
+	struct asus_wmi *asus;
+
+	asus = platform_get_drvdata(device);
+	wmi_remove_notify_handler(asus->driver->event_guid);
+	asus_wmi_backlight_exit(asus);
+	asus_wmi_input_exit(asus);
+	asus_wmi_hwmon_exit(asus);
+	asus_wmi_led_exit(asus);
+	asus_wmi_rfkill_exit(asus);
+	asus_wmi_debugfs_exit(asus);
+	asus_wmi_platform_exit(asus);
+
+	kfree(asus);
+	return 0;
+}
+
+/*
+ * Platform driver - hibernate/resume callbacks
+ */
+static int asus_hotk_thaw(struct device *device)
+{
+	struct asus_wmi *asus = dev_get_drvdata(device);
+
+	if (asus->wlan.rfkill) {
+		bool wlan;
+
+		/*
+		 * Work around bios bug - acpi _PTS turns off the wireless led
+		 * during suspend.  Normally it restores it on resume, but
+		 * we should kick it ourselves in case hibernation is aborted.
+		 */
+		wlan = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WLAN);
+		asus_wmi_set_devstate(ASUS_WMI_DEVID_WLAN, wlan, NULL);
+	}
+
+	return 0;
+}
+
+static int asus_hotk_restore(struct device *device)
+{
+	struct asus_wmi *asus = dev_get_drvdata(device);
+	int bl;
+
+	/* Refresh both wlan rfkill state and pci hotplug */
+	if (asus->wlan.rfkill)
+		asus_rfkill_hotplug(asus);
+
+	if (asus->bluetooth.rfkill) {
+		bl = !asus_wmi_get_devstate_simple(asus,
+						   ASUS_WMI_DEVID_BLUETOOTH);
+		rfkill_set_sw_state(asus->bluetooth.rfkill, bl);
+	}
+	if (asus->wimax.rfkill) {
+		bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WIMAX);
+		rfkill_set_sw_state(asus->wimax.rfkill, bl);
+	}
+	if (asus->wwan3g.rfkill) {
+		bl = !asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_WWAN3G);
+		rfkill_set_sw_state(asus->wwan3g.rfkill, bl);
+	}
+
+	return 0;
+}
+
+static const struct dev_pm_ops asus_pm_ops = {
+	.thaw = asus_hotk_thaw,
+	.restore = asus_hotk_restore,
+};
+
+static int asus_wmi_probe(struct platform_device *pdev)
+{
+	struct platform_driver *pdrv = to_platform_driver(pdev->dev.driver);
+	struct asus_wmi_driver *wdrv = to_asus_wmi_driver(pdrv);
+	int ret;
+
+	if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
+		pr_warning("Management GUID not found\n");
+		return -ENODEV;
+	}
+
+	if (wdrv->event_guid && !wmi_has_guid(wdrv->event_guid)) {
+		pr_warning("Event GUID not found\n");
+		return -ENODEV;
+	}
+
+	if (wdrv->probe) {
+		ret = wdrv->probe(pdev);
+		if (ret)
+			return ret;
+	}
+
+	return asus_wmi_add(pdev);
+}
+
+static bool used;
+
+int asus_wmi_register_driver(struct asus_wmi_driver *driver)
+{
+	struct platform_driver *platform_driver;
+	struct platform_device *platform_device;
+
+	if (used)
+		return -EBUSY;
+
+	platform_driver = &driver->platform_driver;
+	platform_driver->remove = asus_wmi_remove;
+	platform_driver->driver.owner = driver->owner;
+	platform_driver->driver.name = driver->name;
+	platform_driver->driver.pm = &asus_pm_ops;
+
+	platform_device = platform_create_bundle(platform_driver,
+						 asus_wmi_probe,
+						 NULL, 0, NULL, 0);
+	if (IS_ERR(platform_device))
+		return PTR_ERR(platform_device);
+
+	used = true;
+	return 0;
+}
+EXPORT_SYMBOL_GPL(asus_wmi_register_driver);
+
+void asus_wmi_unregister_driver(struct asus_wmi_driver *driver)
+{
+	platform_device_unregister(driver->platform_device);
+	platform_driver_unregister(&driver->platform_driver);
+	used = false;
+}
+EXPORT_SYMBOL_GPL(asus_wmi_unregister_driver);
+
+static int __init asus_wmi_init(void)
+{
+	if (!wmi_has_guid(ASUS_WMI_MGMT_GUID)) {
+		pr_info("Asus Management GUID not found");
+		return -ENODEV;
+	}
+
+	pr_info("ASUS WMI generic driver loaded");
+	return 0;
+}
+
+static void __exit asus_wmi_exit(void)
+{
+	pr_info("ASUS WMI generic driver unloaded");
+}
+
+module_init(asus_wmi_init);
+module_exit(asus_wmi_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/asus-wmi.h linux-libre-2.6.39-gnu/drivers/platform/x86/asus-wmi.h
--- linux-libre-2.6.38-gnu/drivers/platform/x86/asus-wmi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/asus-wmi.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,58 @@
+/*
+ * Asus PC WMI hotkey driver
+ *
+ * Copyright(C) 2010 Intel Corporation.
+ * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
+ *
+ * Portions based on wistron_btns.c:
+ * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
+ * Copyright (C) 2005 Bernhard Rosenkraenzer <bero@arklinux.org>
+ * Copyright (C) 2005 Dmitry Torokhov <dtor@mail.ru>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 _ASUS_WMI_H_
+#define _ASUS_WMI_H_
+
+#include <linux/platform_device.h>
+
+struct module;
+struct key_entry;
+struct asus_wmi;
+
+struct asus_wmi_driver {
+	bool			hotplug_wireless;
+
+	const char		*name;
+	struct module		*owner;
+
+	const char		*event_guid;
+
+	const struct key_entry	*keymap;
+	const char		*input_name;
+	const char		*input_phys;
+
+	int (*probe) (struct platform_device *device);
+	void (*quirks) (struct asus_wmi_driver *driver);
+
+	struct platform_driver	platform_driver;
+	struct platform_device *platform_device;
+};
+
+int asus_wmi_register_driver(struct asus_wmi_driver *driver);
+void asus_wmi_unregister_driver(struct asus_wmi_driver *driver);
+
+#endif /* !_ASUS_WMI_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/classmate-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/classmate-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/classmate-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/classmate-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -564,6 +564,7 @@
 		return -ENOMEM;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 7;
 	ipml->bd = backlight_device_register("cmpc_bl", &acpi->dev,
 					     acpi->handle, &cmpc_bl_ops,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/compal-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/compal-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/compal-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/compal-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -201,7 +201,7 @@
  * into 0x4F and read a few bytes from the output, like so:
  *	u8 writeData = 0x33;
  *	ec_transaction(0x4F, &writeData, 1, buffer, 32, 0);
- * That address is labled "fan1 table information" in the service manual.
+ * That address is labelled "fan1 table information" in the service manual.
  * It should be clear which value in 'buffer' changes). This seems to be
  * related to fan speed. It isn't a proper 'realtime' fan speed value
  * though, because physically stopping or speeding up the fan doesn't
@@ -275,7 +275,7 @@
 
 	ec_write(BACKLIGHT_LEVEL_ADDR, level);
 
-	return 1;
+	return 0;
 }
 
 static int get_backlight_level(void)
@@ -763,7 +763,7 @@
 	printk(KERN_INFO DRIVER_NAME": Identified laptop model '%s'\n",
 		id->ident);
 	extra_features = false;
-	return 0;
+	return 1;
 }
 
 static int dmi_check_cb_extra(const struct dmi_system_id *id)
@@ -772,7 +772,7 @@
 		"enabling extra features\n",
 		id->ident);
 	extra_features = true;
-	return 0;
+	return 1;
 }
 
 static struct dmi_system_id __initdata compal_dmi_table[] = {
@@ -970,6 +970,7 @@
 	if (!acpi_video_backlight_support()) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = BACKLIGHT_LEVEL_MAX;
 		compalbl_device = backlight_device_register(DRIVER_NAME,
 							    NULL, NULL,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/dell-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/dell-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/dell-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/dell-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -671,6 +671,7 @@
 	if (max_intensity) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = max_intensity;
 		dell_backlight_device = backlight_device_register("dell_backlight",
 								  &platform_device->dev,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/dell-wmi-aio.c linux-libre-2.6.39-gnu/drivers/platform/x86/dell-wmi-aio.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/dell-wmi-aio.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/dell-wmi-aio.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,171 @@
+/*
+ *  WMI hotkeys support for Dell All-In-One series
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
+#include <acpi/acpi_drivers.h>
+#include <linux/acpi.h>
+#include <linux/string.h>
+
+MODULE_DESCRIPTION("WMI hotkeys driver for Dell All-In-One series");
+MODULE_LICENSE("GPL");
+
+#define EVENT_GUID1 "284A0E6B-380E-472A-921F-E52786257FB4"
+#define EVENT_GUID2 "02314822-307C-4F66-BF0E-48AEAEB26CC8"
+
+static const char *dell_wmi_aio_guids[] = {
+	EVENT_GUID1,
+	EVENT_GUID2,
+	NULL
+};
+
+MODULE_ALIAS("wmi:"EVENT_GUID1);
+MODULE_ALIAS("wmi:"EVENT_GUID2);
+
+static const struct key_entry dell_wmi_aio_keymap[] = {
+	{ KE_KEY, 0xc0, { KEY_VOLUMEUP } },
+	{ KE_KEY, 0xc1, { KEY_VOLUMEDOWN } },
+	{ KE_END, 0 }
+};
+
+static struct input_dev *dell_wmi_aio_input_dev;
+
+static void dell_wmi_aio_notify(u32 value, void *context)
+{
+	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
+	union acpi_object *obj;
+	acpi_status status;
+
+	status = wmi_get_event_data(value, &response);
+	if (status != AE_OK) {
+		pr_info("bad event status 0x%x\n", status);
+		return;
+	}
+
+	obj = (union acpi_object *)response.pointer;
+	if (obj) {
+		unsigned int scancode;
+
+		switch (obj->type) {
+		case ACPI_TYPE_INTEGER:
+			/* Most All-In-One correctly return integer scancode */
+			scancode = obj->integer.value;
+			sparse_keymap_report_event(dell_wmi_aio_input_dev,
+				scancode, 1, true);
+			break;
+		case ACPI_TYPE_BUFFER:
+			/* Broken machines return the scancode in a buffer */
+			if (obj->buffer.pointer && obj->buffer.length > 0) {
+				scancode = obj->buffer.pointer[0];
+				sparse_keymap_report_event(
+					dell_wmi_aio_input_dev,
+					scancode, 1, true);
+			}
+			break;
+		}
+	}
+	kfree(obj);
+}
+
+static int __init dell_wmi_aio_input_setup(void)
+{
+	int err;
+
+	dell_wmi_aio_input_dev = input_allocate_device();
+
+	if (!dell_wmi_aio_input_dev)
+		return -ENOMEM;
+
+	dell_wmi_aio_input_dev->name = "Dell AIO WMI hotkeys";
+	dell_wmi_aio_input_dev->phys = "wmi/input0";
+	dell_wmi_aio_input_dev->id.bustype = BUS_HOST;
+
+	err = sparse_keymap_setup(dell_wmi_aio_input_dev,
+			dell_wmi_aio_keymap, NULL);
+	if (err) {
+		pr_err("Unable to setup input device keymap\n");
+		goto err_free_dev;
+	}
+	err = input_register_device(dell_wmi_aio_input_dev);
+	if (err) {
+		pr_info("Unable to register input device\n");
+		goto err_free_keymap;
+	}
+	return 0;
+
+err_free_keymap:
+	sparse_keymap_free(dell_wmi_aio_input_dev);
+err_free_dev:
+	input_free_device(dell_wmi_aio_input_dev);
+	return err;
+}
+
+static const char *dell_wmi_aio_find(void)
+{
+	int i;
+
+	for (i = 0; dell_wmi_aio_guids[i] != NULL; i++)
+		if (wmi_has_guid(dell_wmi_aio_guids[i]))
+			return dell_wmi_aio_guids[i];
+
+	return NULL;
+}
+
+static int __init dell_wmi_aio_init(void)
+{
+	int err;
+	const char *guid;
+
+	guid = dell_wmi_aio_find();
+	if (!guid) {
+		pr_warning("No known WMI GUID found\n");
+		return -ENXIO;
+	}
+
+	err = dell_wmi_aio_input_setup();
+	if (err)
+		return err;
+
+	err = wmi_install_notify_handler(guid, dell_wmi_aio_notify, NULL);
+	if (err) {
+		pr_err("Unable to register notify handler - %d\n", err);
+		sparse_keymap_free(dell_wmi_aio_input_dev);
+		input_unregister_device(dell_wmi_aio_input_dev);
+		return err;
+	}
+
+	return 0;
+}
+
+static void __exit dell_wmi_aio_exit(void)
+{
+	const char *guid;
+
+	guid = dell_wmi_aio_find();
+	wmi_remove_notify_handler(guid);
+	sparse_keymap_free(dell_wmi_aio_input_dev);
+	input_unregister_device(dell_wmi_aio_input_dev);
+}
+
+module_init(dell_wmi_aio_init);
+module_exit(dell_wmi_aio_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/eeepc-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/eeepc-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/eeepc-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/eeepc-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -585,8 +585,9 @@
 	return true;
 }
 
-static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc)
+static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
 {
+	struct pci_dev *port;
 	struct pci_dev *dev;
 	struct pci_bus *bus;
 	bool blocked = eeepc_wlan_rfkill_blocked(eeepc);
@@ -599,9 +600,16 @@
 	mutex_lock(&eeepc->hotplug_lock);
 
 	if (eeepc->hotplug_slot) {
-		bus = pci_find_bus(0, 1);
+		port = acpi_get_pci_dev(handle);
+		if (!port) {
+			pr_warning("Unable to find port\n");
+			goto out_unlock;
+		}
+
+		bus = port->subordinate;
+
 		if (!bus) {
-			pr_warning("Unable to find PCI bus 1?\n");
+			pr_warning("Unable to find PCI bus?\n");
 			goto out_unlock;
 		}
 
@@ -609,6 +617,7 @@
 			pr_err("Unable to read PCI config space?\n");
 			goto out_unlock;
 		}
+
 		absent = (l == 0xffffffff);
 
 		if (blocked != absent) {
@@ -647,6 +656,17 @@
 	mutex_unlock(&eeepc->hotplug_lock);
 }
 
+static void eeepc_rfkill_hotplug_update(struct eeepc_laptop *eeepc, char *node)
+{
+	acpi_status status = AE_OK;
+	acpi_handle handle;
+
+	status = acpi_get_handle(NULL, node, &handle);
+
+	if (ACPI_SUCCESS(status))
+		eeepc_rfkill_hotplug(eeepc, handle);
+}
+
 static void eeepc_rfkill_notify(acpi_handle handle, u32 event, void *data)
 {
 	struct eeepc_laptop *eeepc = data;
@@ -654,7 +674,7 @@
 	if (event != ACPI_NOTIFY_BUS_CHECK)
 		return;
 
-	eeepc_rfkill_hotplug(eeepc);
+	eeepc_rfkill_hotplug(eeepc, handle);
 }
 
 static int eeepc_register_rfkill_notifier(struct eeepc_laptop *eeepc,
@@ -672,6 +692,11 @@
 						     eeepc);
 		if (ACPI_FAILURE(status))
 			pr_warning("Failed to register notify on %s\n", node);
+		/*
+		 * Refresh pci hotplug in case the rfkill state was
+		 * changed during setup.
+		 */
+		eeepc_rfkill_hotplug(eeepc, handle);
 	} else
 		return -ENODEV;
 
@@ -693,6 +718,12 @@
 		if (ACPI_FAILURE(status))
 			pr_err("Error removing rfkill notify handler %s\n",
 				node);
+			/*
+			 * Refresh pci hotplug in case the rfkill
+			 * state was changed after
+			 * eeepc_unregister_rfkill_notifier()
+			 */
+		eeepc_rfkill_hotplug(eeepc, handle);
 	}
 }
 
@@ -816,11 +847,7 @@
 		rfkill_destroy(eeepc->wlan_rfkill);
 		eeepc->wlan_rfkill = NULL;
 	}
-	/*
-	 * Refresh pci hotplug in case the rfkill state was changed after
-	 * eeepc_unregister_rfkill_notifier()
-	 */
-	eeepc_rfkill_hotplug(eeepc);
+
 	if (eeepc->hotplug_slot)
 		pci_hp_deregister(eeepc->hotplug_slot);
 
@@ -889,11 +916,6 @@
 	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P5");
 	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P6");
 	eeepc_register_rfkill_notifier(eeepc, "\\_SB.PCI0.P0P7");
-	/*
-	 * Refresh pci hotplug in case the rfkill state was changed during
-	 * setup.
-	 */
-	eeepc_rfkill_hotplug(eeepc);
 
 exit:
 	if (result && result != -ENODEV)
@@ -928,8 +950,11 @@
 	struct eeepc_laptop *eeepc = dev_get_drvdata(device);
 
 	/* Refresh both wlan rfkill state and pci hotplug */
-	if (eeepc->wlan_rfkill)
-		eeepc_rfkill_hotplug(eeepc);
+	if (eeepc->wlan_rfkill) {
+		eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P5");
+		eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P6");
+		eeepc_rfkill_hotplug_update(eeepc, "\\_SB.PCI0.P0P7");
+	}
 
 	if (eeepc->bluetooth_rfkill)
 		rfkill_set_sw_state(eeepc->bluetooth_rfkill,
@@ -1147,6 +1172,7 @@
 	struct backlight_device *bd;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = 15;
 	bd = backlight_device_register(EEEPC_LAPTOP_FILE,
 				       &eeepc->platform_device->dev, eeepc,
@@ -1321,7 +1347,7 @@
 {
 	int dummy;
 
-	/* Some BIOSes do not report cm although it is avaliable.
+	/* Some BIOSes do not report cm although it is available.
 	   Check if cm_getv[cm] works and, if yes, assume cm should be set. */
 	if (!(eeepc->cm_supported & (1 << cm))
 	    && !read_acpi_int(eeepc->handle, cm_getv[cm], &dummy)) {
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/eeepc-wmi.c linux-libre-2.6.39-gnu/drivers/platform/x86/eeepc-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/eeepc-wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/eeepc-wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,7 +2,7 @@
  * Eee PC WMI hotkey driver
  *
  * Copyright(C) 2010 Intel Corporation.
- * Copyright(C) 2010 Corentin Chary <corentin.chary@gmail.com>
+ * Copyright(C) 2010-2011 Corentin Chary <corentin.chary@gmail.com>
  *
  * Portions based on wistron_btns.c:
  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
@@ -29,841 +29,59 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/init.h>
-#include <linux/types.h>
-#include <linux/slab.h>
 #include <linux/input.h>
 #include <linux/input/sparse-keymap.h>
-#include <linux/fb.h>
-#include <linux/backlight.h>
-#include <linux/leds.h>
-#include <linux/rfkill.h>
-#include <linux/debugfs.h>
-#include <linux/seq_file.h>
-#include <linux/platform_device.h>
+#include <linux/dmi.h>
 #include <acpi/acpi_bus.h>
-#include <acpi/acpi_drivers.h>
+
+#include "asus-wmi.h"
 
 #define	EEEPC_WMI_FILE	"eeepc-wmi"
 
-MODULE_AUTHOR("Yong Wang <yong.y.wang@intel.com>");
+MODULE_AUTHOR("Corentin Chary <corentincj@iksaif.net>");
 MODULE_DESCRIPTION("Eee PC WMI Hotkey Driver");
 MODULE_LICENSE("GPL");
 
 #define EEEPC_ACPI_HID		"ASUS010" /* old _HID used in eeepc-laptop */
 
 #define EEEPC_WMI_EVENT_GUID	"ABBC0F72-8EA1-11D1-00A0-C90629100000"
-#define EEEPC_WMI_MGMT_GUID	"97845ED0-4E6D-11DE-8A39-0800200C9A66"
 
 MODULE_ALIAS("wmi:"EEEPC_WMI_EVENT_GUID);
-MODULE_ALIAS("wmi:"EEEPC_WMI_MGMT_GUID);
-
-#define NOTIFY_BRNUP_MIN	0x11
-#define NOTIFY_BRNUP_MAX	0x1f
-#define NOTIFY_BRNDOWN_MIN	0x20
-#define NOTIFY_BRNDOWN_MAX	0x2e
 
-#define EEEPC_WMI_METHODID_DEVS	0x53564544
-#define EEEPC_WMI_METHODID_DSTS	0x53544344
-#define EEEPC_WMI_METHODID_CFVS	0x53564643
+static bool hotplug_wireless;
 
-#define EEEPC_WMI_DEVID_BACKLIGHT	0x00050012
-#define EEEPC_WMI_DEVID_TPDLED		0x00100011
-#define EEEPC_WMI_DEVID_WLAN		0x00010011
-#define EEEPC_WMI_DEVID_BLUETOOTH	0x00010013
-#define EEEPC_WMI_DEVID_WWAN3G		0x00010019
+module_param(hotplug_wireless, bool, 0444);
+MODULE_PARM_DESC(hotplug_wireless,
+		 "Enable hotplug for wireless device. "
+		 "If your laptop needs that, please report to "
+		 "acpi4asus-user@lists.sourceforge.net.");
 
 static const struct key_entry eeepc_wmi_keymap[] = {
 	/* Sleep already handled via generic ACPI code */
-	{ KE_KEY, 0x5d, { KEY_WLAN } },
-	{ KE_KEY, 0x32, { KEY_MUTE } },
-	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
 	{ KE_KEY, 0x30, { KEY_VOLUMEUP } },
-	{ KE_IGNORE, NOTIFY_BRNDOWN_MIN, { KEY_BRIGHTNESSDOWN } },
-	{ KE_IGNORE, NOTIFY_BRNUP_MIN, { KEY_BRIGHTNESSUP } },
+	{ KE_KEY, 0x31, { KEY_VOLUMEDOWN } },
+	{ KE_KEY, 0x32, { KEY_MUTE } },
+	{ KE_KEY, 0x5c, { KEY_F15 } }, /* Power Gear key */
+	{ KE_KEY, 0x5d, { KEY_WLAN } },
+	{ KE_KEY, 0x6b, { KEY_TOUCHPAD_TOGGLE } }, /* Toggle Touchpad */
+	{ KE_KEY, 0x82, { KEY_CAMERA } },
+	{ KE_KEY, 0x83, { KEY_CAMERA_ZOOMIN } },
+	{ KE_KEY, 0x88, { KEY_WLAN } },
+	{ KE_KEY, 0xbd, { KEY_CAMERA } },
 	{ KE_KEY, 0xcc, { KEY_SWITCHVIDEOMODE } },
-	{ KE_KEY, 0x6b, { KEY_F13 } }, /* Disable Touchpad */
-	{ KE_KEY, 0xe1, { KEY_F14 } },
-	{ KE_KEY, 0xe9, { KEY_DISPLAY_OFF } },
-	{ KE_KEY, 0xe0, { KEY_PROG1 } },
-	{ KE_KEY, 0x5c, { KEY_F15 } },
+	{ KE_KEY, 0xe0, { KEY_PROG1 } }, /* Task Manager */
+	{ KE_KEY, 0xe1, { KEY_F14 } }, /* Change Resolution */
+	{ KE_KEY, 0xe8, { KEY_SCREENLOCK } },
+	{ KE_KEY, 0xe9, { KEY_BRIGHTNESS_ZERO } },
+	{ KE_KEY, 0xeb, { KEY_CAMERA_ZOOMOUT } },
+	{ KE_KEY, 0xec, { KEY_CAMERA_UP } },
+	{ KE_KEY, 0xed, { KEY_CAMERA_DOWN } },
+	{ KE_KEY, 0xee, { KEY_CAMERA_LEFT } },
+	{ KE_KEY, 0xef, { KEY_CAMERA_RIGHT } },
 	{ KE_END, 0},
 };
 
-struct bios_args {
-	u32	dev_id;
-	u32	ctrl_param;
-};
-
-/*
- * eeepc-wmi/    - debugfs root directory
- *   dev_id      - current dev_id
- *   ctrl_param  - current ctrl_param
- *   devs        - call DEVS(dev_id, ctrl_param) and print result
- *   dsts        - call DSTS(dev_id)  and print result
- */
-struct eeepc_wmi_debug {
-	struct dentry *root;
-	u32 dev_id;
-	u32 ctrl_param;
-};
-
-struct eeepc_wmi {
-	struct input_dev *inputdev;
-	struct backlight_device *backlight_device;
-	struct platform_device *platform_device;
-
-	struct led_classdev tpd_led;
-	int tpd_led_wk;
-	struct workqueue_struct *led_workqueue;
-	struct work_struct tpd_led_work;
-
-	struct rfkill *wlan_rfkill;
-	struct rfkill *bluetooth_rfkill;
-	struct rfkill *wwan3g_rfkill;
-
-	struct eeepc_wmi_debug debug;
-};
-
-/* Only used in eeepc_wmi_init() and eeepc_wmi_exit() */
-static struct platform_device *platform_device;
-
-static int eeepc_wmi_input_init(struct eeepc_wmi *eeepc)
-{
-	int err;
-
-	eeepc->inputdev = input_allocate_device();
-	if (!eeepc->inputdev)
-		return -ENOMEM;
-
-	eeepc->inputdev->name = "Eee PC WMI hotkeys";
-	eeepc->inputdev->phys = EEEPC_WMI_FILE "/input0";
-	eeepc->inputdev->id.bustype = BUS_HOST;
-	eeepc->inputdev->dev.parent = &eeepc->platform_device->dev;
-
-	err = sparse_keymap_setup(eeepc->inputdev, eeepc_wmi_keymap, NULL);
-	if (err)
-		goto err_free_dev;
-
-	err = input_register_device(eeepc->inputdev);
-	if (err)
-		goto err_free_keymap;
-
-	return 0;
-
-err_free_keymap:
-	sparse_keymap_free(eeepc->inputdev);
-err_free_dev:
-	input_free_device(eeepc->inputdev);
-	return err;
-}
-
-static void eeepc_wmi_input_exit(struct eeepc_wmi *eeepc)
-{
-	if (eeepc->inputdev) {
-		sparse_keymap_free(eeepc->inputdev);
-		input_unregister_device(eeepc->inputdev);
-	}
-
-	eeepc->inputdev = NULL;
-}
-
-static acpi_status eeepc_wmi_get_devstate(u32 dev_id, u32 *retval)
-{
-	struct acpi_buffer input = { (acpi_size)sizeof(u32), &dev_id };
-	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *obj;
-	acpi_status status;
-	u32 tmp;
-
-	status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
-			1, EEEPC_WMI_METHODID_DSTS, &input, &output);
-
-	if (ACPI_FAILURE(status))
-		return status;
-
-	obj = (union acpi_object *)output.pointer;
-	if (obj && obj->type == ACPI_TYPE_INTEGER)
-		tmp = (u32)obj->integer.value;
-	else
-		tmp = 0;
-
-	if (retval)
-		*retval = tmp;
-
-	kfree(obj);
-
-	return status;
-
-}
-
-static acpi_status eeepc_wmi_set_devstate(u32 dev_id, u32 ctrl_param,
-					  u32 *retval)
-{
-	struct bios_args args = {
-		.dev_id = dev_id,
-		.ctrl_param = ctrl_param,
-	};
-	struct acpi_buffer input = { (acpi_size)sizeof(args), &args };
-	acpi_status status;
-
-	if (!retval) {
-		status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
-					     EEEPC_WMI_METHODID_DEVS,
-					     &input, NULL);
-	} else {
-		struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
-		union acpi_object *obj;
-		u32 tmp;
-
-		status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID, 1,
-					     EEEPC_WMI_METHODID_DEVS,
-					     &input, &output);
-
-		if (ACPI_FAILURE(status))
-			return status;
-
-		obj = (union acpi_object *)output.pointer;
-		if (obj && obj->type == ACPI_TYPE_INTEGER)
-			tmp = (u32)obj->integer.value;
-		else
-			tmp = 0;
-
-		*retval = tmp;
-
-		kfree(obj);
-	}
-
-	return status;
-}
-
-/*
- * LEDs
- */
-/*
- * These functions actually update the LED's, and are called from a
- * workqueue. By doing this as separate work rather than when the LED
- * subsystem asks, we avoid messing with the Eeepc ACPI stuff during a
- * potentially bad time, such as a timer interrupt.
- */
-static void tpd_led_update(struct work_struct *work)
-{
-	int ctrl_param;
-	struct eeepc_wmi *eeepc;
-
-	eeepc = container_of(work, struct eeepc_wmi, tpd_led_work);
-
-	ctrl_param = eeepc->tpd_led_wk;
-	eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_TPDLED, ctrl_param, NULL);
-}
-
-static void tpd_led_set(struct led_classdev *led_cdev,
-			enum led_brightness value)
-{
-	struct eeepc_wmi *eeepc;
-
-	eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
-
-	eeepc->tpd_led_wk = !!value;
-	queue_work(eeepc->led_workqueue, &eeepc->tpd_led_work);
-}
-
-static int read_tpd_state(struct eeepc_wmi *eeepc)
-{
-	u32 retval;
-	acpi_status status;
-
-	status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_TPDLED, &retval);
-
-	if (ACPI_FAILURE(status))
-		return -1;
-	else if (!retval || retval == 0x00060000)
-		/*
-		 * if touchpad led is present, DSTS will set some bits,
-		 * usually 0x00020000.
-		 * 0x00060000 means that the device is not supported
-		 */
-		return -ENODEV;
-	else
-		/* Status is stored in the first bit */
-		return retval & 0x1;
-}
-
-static enum led_brightness tpd_led_get(struct led_classdev *led_cdev)
-{
-	struct eeepc_wmi *eeepc;
-
-	eeepc = container_of(led_cdev, struct eeepc_wmi, tpd_led);
-
-	return read_tpd_state(eeepc);
-}
-
-static int eeepc_wmi_led_init(struct eeepc_wmi *eeepc)
-{
-	int rv;
-
-	if (read_tpd_state(eeepc) < 0)
-		return 0;
-
-	eeepc->led_workqueue = create_singlethread_workqueue("led_workqueue");
-	if (!eeepc->led_workqueue)
-		return -ENOMEM;
-	INIT_WORK(&eeepc->tpd_led_work, tpd_led_update);
-
-	eeepc->tpd_led.name = "eeepc::touchpad";
-	eeepc->tpd_led.brightness_set = tpd_led_set;
-	eeepc->tpd_led.brightness_get = tpd_led_get;
-	eeepc->tpd_led.max_brightness = 1;
-
-	rv = led_classdev_register(&eeepc->platform_device->dev,
-				   &eeepc->tpd_led);
-	if (rv) {
-		destroy_workqueue(eeepc->led_workqueue);
-		return rv;
-	}
-
-	return 0;
-}
-
-static void eeepc_wmi_led_exit(struct eeepc_wmi *eeepc)
-{
-	if (eeepc->tpd_led.dev)
-		led_classdev_unregister(&eeepc->tpd_led);
-	if (eeepc->led_workqueue)
-		destroy_workqueue(eeepc->led_workqueue);
-}
-
-/*
- * Rfkill devices
- */
-static int eeepc_rfkill_set(void *data, bool blocked)
-{
-	int dev_id = (unsigned long)data;
-	u32 ctrl_param = !blocked;
-
-	return eeepc_wmi_set_devstate(dev_id, ctrl_param, NULL);
-}
-
-static void eeepc_rfkill_query(struct rfkill *rfkill, void *data)
-{
-	int dev_id = (unsigned long)data;
-	u32 retval;
-	acpi_status status;
-
-	status = eeepc_wmi_get_devstate(dev_id, &retval);
-
-	if (ACPI_FAILURE(status))
-		return ;
-
-	rfkill_set_sw_state(rfkill, !(retval & 0x1));
-}
-
-static const struct rfkill_ops eeepc_rfkill_ops = {
-	.set_block = eeepc_rfkill_set,
-	.query = eeepc_rfkill_query,
-};
-
-static int eeepc_new_rfkill(struct eeepc_wmi *eeepc,
-			    struct rfkill **rfkill,
-			    const char *name,
-			    enum rfkill_type type, int dev_id)
-{
-	int result;
-	u32 retval;
-	acpi_status status;
-
-	status = eeepc_wmi_get_devstate(dev_id, &retval);
-
-	if (ACPI_FAILURE(status))
-		return -1;
-
-	/* If the device is present, DSTS will always set some bits
-	 * 0x00070000 - 1110000000000000000 - device supported
-	 * 0x00060000 - 1100000000000000000 - not supported
-	 * 0x00020000 - 0100000000000000000 - device supported
-	 * 0x00010000 - 0010000000000000000 - not supported / special mode ?
-	 */
-	if (!retval || retval == 0x00060000)
-		return -ENODEV;
-
-	*rfkill = rfkill_alloc(name, &eeepc->platform_device->dev, type,
-			       &eeepc_rfkill_ops, (void *)(long)dev_id);
-
-	if (!*rfkill)
-		return -EINVAL;
-
-	rfkill_init_sw_state(*rfkill, !(retval & 0x1));
-	result = rfkill_register(*rfkill);
-	if (result) {
-		rfkill_destroy(*rfkill);
-		*rfkill = NULL;
-		return result;
-	}
-	return 0;
-}
-
-static void eeepc_wmi_rfkill_exit(struct eeepc_wmi *eeepc)
-{
-	if (eeepc->wlan_rfkill) {
-		rfkill_unregister(eeepc->wlan_rfkill);
-		rfkill_destroy(eeepc->wlan_rfkill);
-		eeepc->wlan_rfkill = NULL;
-	}
-	if (eeepc->bluetooth_rfkill) {
-		rfkill_unregister(eeepc->bluetooth_rfkill);
-		rfkill_destroy(eeepc->bluetooth_rfkill);
-		eeepc->bluetooth_rfkill = NULL;
-	}
-	if (eeepc->wwan3g_rfkill) {
-		rfkill_unregister(eeepc->wwan3g_rfkill);
-		rfkill_destroy(eeepc->wwan3g_rfkill);
-		eeepc->wwan3g_rfkill = NULL;
-	}
-}
-
-static int eeepc_wmi_rfkill_init(struct eeepc_wmi *eeepc)
-{
-	int result = 0;
-
-	result = eeepc_new_rfkill(eeepc, &eeepc->wlan_rfkill,
-				  "eeepc-wlan", RFKILL_TYPE_WLAN,
-				  EEEPC_WMI_DEVID_WLAN);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-	result = eeepc_new_rfkill(eeepc, &eeepc->bluetooth_rfkill,
-				  "eeepc-bluetooth", RFKILL_TYPE_BLUETOOTH,
-				  EEEPC_WMI_DEVID_BLUETOOTH);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-	result = eeepc_new_rfkill(eeepc, &eeepc->wwan3g_rfkill,
-				  "eeepc-wwan3g", RFKILL_TYPE_WWAN,
-				  EEEPC_WMI_DEVID_WWAN3G);
-
-	if (result && result != -ENODEV)
-		goto exit;
-
-exit:
-	if (result && result != -ENODEV)
-		eeepc_wmi_rfkill_exit(eeepc);
-
-	if (result == -ENODEV)
-		result = 0;
-
-	return result;
-}
-
-/*
- * Backlight
- */
-static int read_brightness(struct backlight_device *bd)
-{
-	u32 retval;
-	acpi_status status;
-
-	status = eeepc_wmi_get_devstate(EEEPC_WMI_DEVID_BACKLIGHT, &retval);
-
-	if (ACPI_FAILURE(status))
-		return -1;
-	else
-		return retval & 0xFF;
-}
-
-static int update_bl_status(struct backlight_device *bd)
-{
-
-	u32 ctrl_param;
-	acpi_status status;
-
-	ctrl_param = bd->props.brightness;
-
-	status = eeepc_wmi_set_devstate(EEEPC_WMI_DEVID_BACKLIGHT,
-					ctrl_param, NULL);
-
-	if (ACPI_FAILURE(status))
-		return -1;
-	else
-		return 0;
-}
-
-static const struct backlight_ops eeepc_wmi_bl_ops = {
-	.get_brightness = read_brightness,
-	.update_status = update_bl_status,
-};
-
-static int eeepc_wmi_backlight_notify(struct eeepc_wmi *eeepc, int code)
-{
-	struct backlight_device *bd = eeepc->backlight_device;
-	int old = bd->props.brightness;
-	int new = old;
-
-	if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
-		new = code - NOTIFY_BRNUP_MIN + 1;
-	else if (code >= NOTIFY_BRNDOWN_MIN && code <= NOTIFY_BRNDOWN_MAX)
-		new = code - NOTIFY_BRNDOWN_MIN;
-
-	bd->props.brightness = new;
-	backlight_update_status(bd);
-	backlight_force_update(bd, BACKLIGHT_UPDATE_HOTKEY);
-
-	return old;
-}
-
-static int eeepc_wmi_backlight_init(struct eeepc_wmi *eeepc)
-{
-	struct backlight_device *bd;
-	struct backlight_properties props;
-
-	memset(&props, 0, sizeof(struct backlight_properties));
-	props.max_brightness = 15;
-	bd = backlight_device_register(EEEPC_WMI_FILE,
-				       &eeepc->platform_device->dev, eeepc,
-				       &eeepc_wmi_bl_ops, &props);
-	if (IS_ERR(bd)) {
-		pr_err("Could not register backlight device\n");
-		return PTR_ERR(bd);
-	}
-
-	eeepc->backlight_device = bd;
-
-	bd->props.brightness = read_brightness(bd);
-	bd->props.power = FB_BLANK_UNBLANK;
-	backlight_update_status(bd);
-
-	return 0;
-}
-
-static void eeepc_wmi_backlight_exit(struct eeepc_wmi *eeepc)
-{
-	if (eeepc->backlight_device)
-		backlight_device_unregister(eeepc->backlight_device);
-
-	eeepc->backlight_device = NULL;
-}
-
-static void eeepc_wmi_notify(u32 value, void *context)
-{
-	struct eeepc_wmi *eeepc = context;
-	struct acpi_buffer response = { ACPI_ALLOCATE_BUFFER, NULL };
-	union acpi_object *obj;
-	acpi_status status;
-	int code;
-	int orig_code;
-
-	status = wmi_get_event_data(value, &response);
-	if (status != AE_OK) {
-		pr_err("bad event status 0x%x\n", status);
-		return;
-	}
-
-	obj = (union acpi_object *)response.pointer;
-
-	if (obj && obj->type == ACPI_TYPE_INTEGER) {
-		code = obj->integer.value;
-		orig_code = code;
-
-		if (code >= NOTIFY_BRNUP_MIN && code <= NOTIFY_BRNUP_MAX)
-			code = NOTIFY_BRNUP_MIN;
-		else if (code >= NOTIFY_BRNDOWN_MIN &&
-			 code <= NOTIFY_BRNDOWN_MAX)
-			code = NOTIFY_BRNDOWN_MIN;
-
-		if (code == NOTIFY_BRNUP_MIN || code == NOTIFY_BRNDOWN_MIN) {
-			if (!acpi_video_backlight_support())
-				eeepc_wmi_backlight_notify(eeepc, orig_code);
-		}
-
-		if (!sparse_keymap_report_event(eeepc->inputdev,
-						code, 1, true))
-			pr_info("Unknown key %x pressed\n", code);
-	}
-
-	kfree(obj);
-}
-
-static ssize_t store_cpufv(struct device *dev, struct device_attribute *attr,
-			   const char *buf, size_t count)
-{
-	int value;
-	struct acpi_buffer input = { (acpi_size)sizeof(value), &value };
-	acpi_status status;
-
-	if (!count || sscanf(buf, "%i", &value) != 1)
-		return -EINVAL;
-	if (value < 0 || value > 2)
-		return -EINVAL;
-
-	status = wmi_evaluate_method(EEEPC_WMI_MGMT_GUID,
-				     1, EEEPC_WMI_METHODID_CFVS, &input, NULL);
-
-	if (ACPI_FAILURE(status))
-		return -EIO;
-	else
-		return count;
-}
-
-static DEVICE_ATTR(cpufv, S_IRUGO | S_IWUSR, NULL, store_cpufv);
-
-static struct attribute *platform_attributes[] = {
-	&dev_attr_cpufv.attr,
-	NULL
-};
-
-static struct attribute_group platform_attribute_group = {
-	.attrs = platform_attributes
-};
-
-static void eeepc_wmi_sysfs_exit(struct platform_device *device)
-{
-	sysfs_remove_group(&device->dev.kobj, &platform_attribute_group);
-}
-
-static int eeepc_wmi_sysfs_init(struct platform_device *device)
-{
-	return sysfs_create_group(&device->dev.kobj, &platform_attribute_group);
-}
-
-/*
- * Platform device
- */
-static int __init eeepc_wmi_platform_init(struct eeepc_wmi *eeepc)
-{
-	int err;
-
-	eeepc->platform_device = platform_device_alloc(EEEPC_WMI_FILE, -1);
-	if (!eeepc->platform_device)
-		return -ENOMEM;
-	platform_set_drvdata(eeepc->platform_device, eeepc);
-
-	err = platform_device_add(eeepc->platform_device);
-	if (err)
-		goto fail_platform_device;
-
-	err = eeepc_wmi_sysfs_init(eeepc->platform_device);
-	if (err)
-		goto fail_sysfs;
-	return 0;
-
-fail_sysfs:
-	platform_device_del(eeepc->platform_device);
-fail_platform_device:
-	platform_device_put(eeepc->platform_device);
-	return err;
-}
-
-static void eeepc_wmi_platform_exit(struct eeepc_wmi *eeepc)
-{
-	eeepc_wmi_sysfs_exit(eeepc->platform_device);
-	platform_device_unregister(eeepc->platform_device);
-}
-
-/*
- * debugfs
- */
-struct eeepc_wmi_debugfs_node {
-	struct eeepc_wmi *eeepc;
-	char *name;
-	int (*show)(struct seq_file *m, void *data);
-};
-
-static int show_dsts(struct seq_file *m, void *data)
-{
-	struct eeepc_wmi *eeepc = m->private;
-	acpi_status status;
-	u32 retval = -1;
-
-	status = eeepc_wmi_get_devstate(eeepc->debug.dev_id, &retval);
-
-	if (ACPI_FAILURE(status))
-		return -EIO;
-
-	seq_printf(m, "DSTS(%x) = %x\n", eeepc->debug.dev_id, retval);
-
-	return 0;
-}
-
-static int show_devs(struct seq_file *m, void *data)
-{
-	struct eeepc_wmi *eeepc = m->private;
-	acpi_status status;
-	u32 retval = -1;
-
-	status = eeepc_wmi_set_devstate(eeepc->debug.dev_id,
-					eeepc->debug.ctrl_param, &retval);
-	if (ACPI_FAILURE(status))
-		return -EIO;
-
-	seq_printf(m, "DEVS(%x, %x) = %x\n", eeepc->debug.dev_id,
-		   eeepc->debug.ctrl_param, retval);
-
-	return 0;
-}
-
-static struct eeepc_wmi_debugfs_node eeepc_wmi_debug_files[] = {
-	{ NULL, "devs", show_devs },
-	{ NULL, "dsts", show_dsts },
-};
-
-static int eeepc_wmi_debugfs_open(struct inode *inode, struct file *file)
-{
-	struct eeepc_wmi_debugfs_node *node = inode->i_private;
-
-	return single_open(file, node->show, node->eeepc);
-}
-
-static const struct file_operations eeepc_wmi_debugfs_io_ops = {
-	.owner = THIS_MODULE,
-	.open  = eeepc_wmi_debugfs_open,
-	.read = seq_read,
-	.llseek = seq_lseek,
-	.release = single_release,
-};
-
-static void eeepc_wmi_debugfs_exit(struct eeepc_wmi *eeepc)
-{
-	debugfs_remove_recursive(eeepc->debug.root);
-}
-
-static int eeepc_wmi_debugfs_init(struct eeepc_wmi *eeepc)
-{
-	struct dentry *dent;
-	int i;
-
-	eeepc->debug.root = debugfs_create_dir(EEEPC_WMI_FILE, NULL);
-	if (!eeepc->debug.root) {
-		pr_err("failed to create debugfs directory");
-		goto error_debugfs;
-	}
-
-	dent = debugfs_create_x32("dev_id", S_IRUGO|S_IWUSR,
-				  eeepc->debug.root, &eeepc->debug.dev_id);
-	if (!dent)
-		goto error_debugfs;
-
-	dent = debugfs_create_x32("ctrl_param", S_IRUGO|S_IWUSR,
-				  eeepc->debug.root, &eeepc->debug.ctrl_param);
-	if (!dent)
-		goto error_debugfs;
-
-	for (i = 0; i < ARRAY_SIZE(eeepc_wmi_debug_files); i++) {
-		struct eeepc_wmi_debugfs_node *node = &eeepc_wmi_debug_files[i];
-
-		node->eeepc = eeepc;
-		dent = debugfs_create_file(node->name, S_IFREG | S_IRUGO,
-					   eeepc->debug.root, node,
-					   &eeepc_wmi_debugfs_io_ops);
-		if (!dent) {
-			pr_err("failed to create debug file: %s\n", node->name);
-			goto error_debugfs;
-		}
-	}
-
-	return 0;
-
-error_debugfs:
-	eeepc_wmi_debugfs_exit(eeepc);
-	return -ENOMEM;
-}
-
-/*
- * WMI Driver
- */
-static struct platform_device * __init eeepc_wmi_add(void)
-{
-	struct eeepc_wmi *eeepc;
-	acpi_status status;
-	int err;
-
-	eeepc = kzalloc(sizeof(struct eeepc_wmi), GFP_KERNEL);
-	if (!eeepc)
-		return ERR_PTR(-ENOMEM);
-
-	/*
-	 * Register the platform device first.  It is used as a parent for the
-	 * sub-devices below.
-	 */
-	err = eeepc_wmi_platform_init(eeepc);
-	if (err)
-		goto fail_platform;
-
-	err = eeepc_wmi_input_init(eeepc);
-	if (err)
-		goto fail_input;
-
-	err = eeepc_wmi_led_init(eeepc);
-	if (err)
-		goto fail_leds;
-
-	err = eeepc_wmi_rfkill_init(eeepc);
-	if (err)
-		goto fail_rfkill;
-
-	if (!acpi_video_backlight_support()) {
-		err = eeepc_wmi_backlight_init(eeepc);
-		if (err)
-			goto fail_backlight;
-	} else
-		pr_info("Backlight controlled by ACPI video driver\n");
-
-	status = wmi_install_notify_handler(EEEPC_WMI_EVENT_GUID,
-					    eeepc_wmi_notify, eeepc);
-	if (ACPI_FAILURE(status)) {
-		pr_err("Unable to register notify handler - %d\n",
-			status);
-		err = -ENODEV;
-		goto fail_wmi_handler;
-	}
-
-	err = eeepc_wmi_debugfs_init(eeepc);
-	if (err)
-		goto fail_debugfs;
-
-	return eeepc->platform_device;
-
-fail_debugfs:
-	wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
-fail_wmi_handler:
-	eeepc_wmi_backlight_exit(eeepc);
-fail_backlight:
-	eeepc_wmi_rfkill_exit(eeepc);
-fail_rfkill:
-	eeepc_wmi_led_exit(eeepc);
-fail_leds:
-	eeepc_wmi_input_exit(eeepc);
-fail_input:
-	eeepc_wmi_platform_exit(eeepc);
-fail_platform:
-	kfree(eeepc);
-	return ERR_PTR(err);
-}
-
-static int eeepc_wmi_remove(struct platform_device *device)
-{
-	struct eeepc_wmi *eeepc;
-
-	eeepc = platform_get_drvdata(device);
-	wmi_remove_notify_handler(EEEPC_WMI_EVENT_GUID);
-	eeepc_wmi_backlight_exit(eeepc);
-	eeepc_wmi_input_exit(eeepc);
-	eeepc_wmi_led_exit(eeepc);
-	eeepc_wmi_rfkill_exit(eeepc);
-	eeepc_wmi_debugfs_exit(eeepc);
-	eeepc_wmi_platform_exit(eeepc);
-
-	kfree(eeepc);
-	return 0;
-}
-
-static struct platform_driver platform_driver = {
-	.driver = {
-		.name = EEEPC_WMI_FILE,
-		.owner = THIS_MODULE,
-	},
-};
-
-static acpi_status __init eeepc_wmi_parse_device(acpi_handle handle, u32 level,
+static acpi_status eeepc_wmi_parse_device(acpi_handle handle, u32 level,
 						 void *context, void **retval)
 {
 	pr_warning("Found legacy ATKD device (%s)", EEEPC_ACPI_HID);
@@ -871,7 +89,7 @@
 	return AE_CTRL_TERMINATE;
 }
 
-static int __init eeepc_wmi_check_atkd(void)
+static int eeepc_wmi_check_atkd(void)
 {
 	acpi_status status;
 	bool found = false;
@@ -884,16 +102,8 @@
 	return -1;
 }
 
-static int __init eeepc_wmi_init(void)
+static int eeepc_wmi_probe(struct platform_device *pdev)
 {
-	int err;
-
-	if (!wmi_has_guid(EEEPC_WMI_EVENT_GUID) ||
-	    !wmi_has_guid(EEEPC_WMI_MGMT_GUID)) {
-		pr_warning("No known WMI GUID found\n");
-		return -ENODEV;
-	}
-
 	if (eeepc_wmi_check_atkd()) {
 		pr_warning("WMI device present, but legacy ATKD device is also "
 			   "present and enabled.");
@@ -901,33 +111,59 @@
 			   "acpi_osi=\"!Windows 2009\"");
 		pr_warning("Can't load eeepc-wmi, use default acpi_osi "
 			   "(preferred) or eeepc-laptop");
-		return -ENODEV;
+		return -EBUSY;
 	}
+	return 0;
+}
 
-	platform_device = eeepc_wmi_add();
-	if (IS_ERR(platform_device)) {
-		err = PTR_ERR(platform_device);
-		goto fail_eeepc_wmi;
-	}
+static void eeepc_dmi_check(struct asus_wmi_driver *driver)
+{
+	const char *model;
 
-	err = platform_driver_register(&platform_driver);
-	if (err) {
-		pr_warning("Unable to register platform driver\n");
-		goto fail_platform_driver;
+	model = dmi_get_system_info(DMI_PRODUCT_NAME);
+	if (!model)
+		return;
+
+	/*
+	 * Whitelist for wlan hotplug
+	 *
+	 * Asus 1000H needs the current hotplug code to handle
+	 * Fn+F2 correctly. We may add other Asus here later, but
+	 * it seems that most of the laptops supported by asus-wmi
+	 * don't need to be on this list
+	 */
+	if (strcmp(model, "1000H") == 0) {
+		driver->hotplug_wireless = true;
+		pr_info("wlan hotplug enabled\n");
 	}
+}
 
-	return 0;
+static void eeepc_wmi_quirks(struct asus_wmi_driver *driver)
+{
+	driver->hotplug_wireless = hotplug_wireless;
+	eeepc_dmi_check(driver);
+}
 
-fail_platform_driver:
-	eeepc_wmi_remove(platform_device);
-fail_eeepc_wmi:
-	return err;
+static struct asus_wmi_driver asus_wmi_driver = {
+	.name = EEEPC_WMI_FILE,
+	.owner = THIS_MODULE,
+	.event_guid = EEEPC_WMI_EVENT_GUID,
+	.keymap = eeepc_wmi_keymap,
+	.input_name = "Eee PC WMI hotkeys",
+	.input_phys = EEEPC_WMI_FILE "/input0",
+	.probe = eeepc_wmi_probe,
+	.quirks = eeepc_wmi_quirks,
+};
+
+
+static int __init eeepc_wmi_init(void)
+{
+	return asus_wmi_register_driver(&asus_wmi_driver);
 }
 
 static void __exit eeepc_wmi_exit(void)
 {
-	eeepc_wmi_remove(platform_device);
-	platform_driver_unregister(&platform_driver);
+	asus_wmi_unregister_driver(&asus_wmi_driver);
 }
 
 module_init(eeepc_wmi_init);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/fujitsu-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/fujitsu-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/fujitsu-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/fujitsu-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -1128,6 +1128,7 @@
 
 		memset(&props, 0, sizeof(struct backlight_properties));
 		max_brightness = fujitsu->max_brightness;
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = max_brightness - 1;
 		fujitsu->bl_device = backlight_device_register("fujitsu-laptop",
 							       NULL, NULL,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/hp_accel.c linux-libre-2.6.39-gnu/drivers/platform/x86/hp_accel.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/hp_accel.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/hp_accel.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,404 @@
+/*
+ *  hp_accel.c - Interface between LIS3LV02DL driver and HP ACPI BIOS
+ *
+ *  Copyright (C) 2007-2008 Yan Burman
+ *  Copyright (C) 2008 Eric Piel
+ *  Copyright (C) 2008-2009 Pavel Machek
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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 pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/dmi.h>
+#include <linux/module.h>
+#include <linux/types.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/poll.h>
+#include <linux/freezer.h>
+#include <linux/uaccess.h>
+#include <linux/leds.h>
+#include <linux/atomic.h>
+#include <acpi/acpi_drivers.h>
+#include "../../misc/lis3lv02d/lis3lv02d.h"
+
+#define DRIVER_NAME     "hp_accel"
+#define ACPI_MDPS_CLASS "accelerometer"
+
+/* Delayed LEDs infrastructure ------------------------------------ */
+
+/* Special LED class that can defer work */
+struct delayed_led_classdev {
+	struct led_classdev led_classdev;
+	struct work_struct work;
+	enum led_brightness new_brightness;
+
+	unsigned int led;		/* For driver */
+	void (*set_brightness)(struct delayed_led_classdev *data, enum led_brightness value);
+};
+
+static inline void delayed_set_status_worker(struct work_struct *work)
+{
+	struct delayed_led_classdev *data =
+			container_of(work, struct delayed_led_classdev, work);
+
+	data->set_brightness(data, data->new_brightness);
+}
+
+static inline void delayed_sysfs_set(struct led_classdev *led_cdev,
+			      enum led_brightness brightness)
+{
+	struct delayed_led_classdev *data = container_of(led_cdev,
+			     struct delayed_led_classdev, led_classdev);
+	data->new_brightness = brightness;
+	schedule_work(&data->work);
+}
+
+/* HP-specific accelerometer driver ------------------------------------ */
+
+/* For automatic insertion of the module */
+static struct acpi_device_id lis3lv02d_device_ids[] = {
+	{"HPQ0004", 0}, /* HP Mobile Data Protection System PNP */
+	{"", 0},
+};
+MODULE_DEVICE_TABLE(acpi, lis3lv02d_device_ids);
+
+
+/**
+ * lis3lv02d_acpi_init - ACPI _INI method: initialize the device.
+ * @lis3: pointer to the device struct
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_init(struct lis3lv02d *lis3)
+{
+	struct acpi_device *dev = lis3->bus_priv;
+	if (acpi_evaluate_object(dev->handle, METHOD_NAME__INI,
+				 NULL, NULL) != AE_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+/**
+ * lis3lv02d_acpi_read - ACPI ALRD method: read a register
+ * @lis3: pointer to the device struct
+ * @reg:    the register to read
+ * @ret:    result of the operation
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_read(struct lis3lv02d *lis3, int reg, u8 *ret)
+{
+	struct acpi_device *dev = lis3->bus_priv;
+	union acpi_object arg0 = { ACPI_TYPE_INTEGER };
+	struct acpi_object_list args = { 1, &arg0 };
+	unsigned long long lret;
+	acpi_status status;
+
+	arg0.integer.value = reg;
+
+	status = acpi_evaluate_integer(dev->handle, "ALRD", &args, &lret);
+	*ret = lret;
+	return (status != AE_OK) ? -EINVAL : 0;
+}
+
+/**
+ * lis3lv02d_acpi_write - ACPI ALWR method: write to a register
+ * @lis3: pointer to the device struct
+ * @reg:    the register to write to
+ * @val:    the value to write
+ *
+ * Returns 0 on success.
+ */
+int lis3lv02d_acpi_write(struct lis3lv02d *lis3, int reg, u8 val)
+{
+	struct acpi_device *dev = lis3->bus_priv;
+	unsigned long long ret; /* Not used when writting */
+	union acpi_object in_obj[2];
+	struct acpi_object_list args = { 2, in_obj };
+
+	in_obj[0].type          = ACPI_TYPE_INTEGER;
+	in_obj[0].integer.value = reg;
+	in_obj[1].type          = ACPI_TYPE_INTEGER;
+	in_obj[1].integer.value = val;
+
+	if (acpi_evaluate_integer(dev->handle, "ALWR", &args, &ret) != AE_OK)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int lis3lv02d_dmi_matched(const struct dmi_system_id *dmi)
+{
+	lis3_dev.ac = *((union axis_conversion *)dmi->driver_data);
+	pr_info("hardware type %s found\n", dmi->ident);
+
+	return 1;
+}
+
+/* Represents, for each axis seen by userspace, the corresponding hw axis (+1).
+ * If the value is negative, the opposite of the hw value is used. */
+#define DEFINE_CONV(name, x, y, z)			      \
+	static union axis_conversion lis3lv02d_axis_##name = \
+		{ .as_array = { x, y, z } }
+DEFINE_CONV(normal, 1, 2, 3);
+DEFINE_CONV(y_inverted, 1, -2, 3);
+DEFINE_CONV(x_inverted, -1, 2, 3);
+DEFINE_CONV(z_inverted, 1, 2, -3);
+DEFINE_CONV(xy_swap, 2, 1, 3);
+DEFINE_CONV(xy_rotated_left, -2, 1, 3);
+DEFINE_CONV(xy_rotated_left_usd, -2, 1, -3);
+DEFINE_CONV(xy_swap_inverted, -2, -1, 3);
+DEFINE_CONV(xy_rotated_right, 2, -1, 3);
+DEFINE_CONV(xy_swap_yz_inverted, 2, -1, -3);
+
+#define AXIS_DMI_MATCH(_ident, _name, _axis) {		\
+	.ident = _ident,				\
+	.callback = lis3lv02d_dmi_matched,		\
+	.matches = {					\
+		DMI_MATCH(DMI_PRODUCT_NAME, _name)	\
+	},						\
+	.driver_data = &lis3lv02d_axis_##_axis		\
+}
+
+#define AXIS_DMI_MATCH2(_ident, _class1, _name1,	\
+				_class2, _name2,	\
+				_axis) {		\
+	.ident = _ident,				\
+	.callback = lis3lv02d_dmi_matched,		\
+	.matches = {					\
+		DMI_MATCH(DMI_##_class1, _name1),	\
+		DMI_MATCH(DMI_##_class2, _name2),	\
+	},						\
+	.driver_data = &lis3lv02d_axis_##_axis		\
+}
+static struct dmi_system_id lis3lv02d_dmi_ids[] = {
+	/* product names are truncated to match all kinds of a same model */
+	AXIS_DMI_MATCH("NC64x0", "HP Compaq nc64", x_inverted),
+	AXIS_DMI_MATCH("NC84x0", "HP Compaq nc84", z_inverted),
+	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("NC6730b", "HP Compaq 6730b", xy_rotated_left_usd),
+	AXIS_DMI_MATCH("NC6730s", "HP Compaq 6730s", xy_swap),
+	AXIS_DMI_MATCH("NC651xx", "HP Compaq 651", xy_rotated_right),
+	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),
+	AXIS_DMI_MATCH("NC693xx", "HP EliteBook 853", xy_swap),
+	/* Intel-based HP Pavilion dv5 */
+	AXIS_DMI_MATCH2("HPDV5_I",
+			PRODUCT_NAME, "HP Pavilion dv5",
+			BOARD_NAME, "3603",
+			x_inverted),
+	/* AMD-based HP Pavilion dv5 */
+	AXIS_DMI_MATCH2("HPDV5_A",
+			PRODUCT_NAME, "HP Pavilion dv5",
+			BOARD_NAME, "3600",
+			y_inverted),
+	AXIS_DMI_MATCH("DV7", "HP Pavilion dv7", x_inverted),
+	AXIS_DMI_MATCH("HP8710", "HP Compaq 8710", y_inverted),
+	AXIS_DMI_MATCH("HDX18", "HP HDX 18", x_inverted),
+	AXIS_DMI_MATCH("HPB432x", "HP ProBook 432", xy_rotated_left),
+	AXIS_DMI_MATCH("HPB442x", "HP ProBook 442", xy_rotated_left),
+	AXIS_DMI_MATCH("HPB452x", "HP ProBook 452", y_inverted),
+	AXIS_DMI_MATCH("HPB522x", "HP ProBook 522", xy_swap),
+	AXIS_DMI_MATCH("HPB532x", "HP ProBook 532", y_inverted),
+	AXIS_DMI_MATCH("Mini510x", "HP Mini 510", xy_rotated_left_usd),
+	{ NULL, }
+/* Laptop models without axis info (yet):
+ * "NC6910" "HP Compaq 6910"
+ * "NC2400" "HP Compaq nc2400"
+ * "NX74x0" "HP Compaq nx74"
+ * "NX6325" "HP Compaq nx6325"
+ * "NC4400" "HP Compaq nc4400"
+ */
+};
+
+static void hpled_set(struct delayed_led_classdev *led_cdev, enum led_brightness value)
+{
+	struct acpi_device *dev = lis3_dev.bus_priv;
+	unsigned long long ret; /* Not used when writing */
+	union acpi_object in_obj[1];
+	struct acpi_object_list args = { 1, in_obj };
+
+	in_obj[0].type          = ACPI_TYPE_INTEGER;
+	in_obj[0].integer.value = !!value;
+
+	acpi_evaluate_integer(dev->handle, "ALED", &args, &ret);
+}
+
+static struct delayed_led_classdev hpled_led = {
+	.led_classdev = {
+		.name			= "hp::hddprotect",
+		.default_trigger	= "none",
+		.brightness_set		= delayed_sysfs_set,
+		.flags                  = LED_CORE_SUSPENDRESUME,
+	},
+	.set_brightness = hpled_set,
+};
+
+static acpi_status
+lis3lv02d_get_resource(struct acpi_resource *resource, void *context)
+{
+	if (resource->type == ACPI_RESOURCE_TYPE_EXTENDED_IRQ) {
+		struct acpi_resource_extended_irq *irq;
+		u32 *device_irq = context;
+
+		irq = &resource->data.extended_irq;
+		*device_irq = irq->interrupts[0];
+	}
+
+	return AE_OK;
+}
+
+static void lis3lv02d_enum_resources(struct acpi_device *device)
+{
+	acpi_status status;
+
+	status = acpi_walk_resources(device->handle, METHOD_NAME__CRS,
+					lis3lv02d_get_resource, &lis3_dev.irq);
+	if (ACPI_FAILURE(status))
+		printk(KERN_DEBUG DRIVER_NAME ": Error getting resources\n");
+}
+
+static int lis3lv02d_add(struct acpi_device *device)
+{
+	int ret;
+
+	if (!device)
+		return -EINVAL;
+
+	lis3_dev.bus_priv = device;
+	lis3_dev.init = lis3lv02d_acpi_init;
+	lis3_dev.read = lis3lv02d_acpi_read;
+	lis3_dev.write = lis3lv02d_acpi_write;
+	strcpy(acpi_device_name(device), DRIVER_NAME);
+	strcpy(acpi_device_class(device), ACPI_MDPS_CLASS);
+	device->driver_data = &lis3_dev;
+
+	/* obtain IRQ number of our device from ACPI */
+	lis3lv02d_enum_resources(device);
+
+	/* If possible use a "standard" axes order */
+	if (lis3_dev.ac.x && lis3_dev.ac.y && lis3_dev.ac.z) {
+		pr_info("Using custom axes %d,%d,%d\n",
+			lis3_dev.ac.x, lis3_dev.ac.y, lis3_dev.ac.z);
+	} else if (dmi_check_system(lis3lv02d_dmi_ids) == 0) {
+		pr_info("laptop model unknown, using default axes configuration\n");
+		lis3_dev.ac = lis3lv02d_axis_normal;
+	}
+
+	/* call the core layer do its init */
+	ret = lis3lv02d_init_device(&lis3_dev);
+	if (ret)
+		return ret;
+
+	INIT_WORK(&hpled_led.work, delayed_set_status_worker);
+	ret = led_classdev_register(NULL, &hpled_led.led_classdev);
+	if (ret) {
+		lis3lv02d_joystick_disable();
+		lis3lv02d_poweroff(&lis3_dev);
+		flush_work(&hpled_led.work);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int lis3lv02d_remove(struct acpi_device *device, int type)
+{
+	if (!device)
+		return -EINVAL;
+
+	lis3lv02d_joystick_disable();
+	lis3lv02d_poweroff(&lis3_dev);
+
+	led_classdev_unregister(&hpled_led.led_classdev);
+	flush_work(&hpled_led.work);
+
+	return lis3lv02d_remove_fs(&lis3_dev);
+}
+
+
+#ifdef CONFIG_PM
+static int lis3lv02d_suspend(struct acpi_device *device, pm_message_t state)
+{
+	/* make sure the device is off when we suspend */
+	lis3lv02d_poweroff(&lis3_dev);
+	return 0;
+}
+
+static int lis3lv02d_resume(struct acpi_device *device)
+{
+	lis3lv02d_poweron(&lis3_dev);
+	return 0;
+}
+#else
+#define lis3lv02d_suspend NULL
+#define lis3lv02d_resume NULL
+#endif
+
+/* For the HP MDPS aka 3D Driveguard */
+static struct acpi_driver lis3lv02d_driver = {
+	.name  = DRIVER_NAME,
+	.class = ACPI_MDPS_CLASS,
+	.ids   = lis3lv02d_device_ids,
+	.ops = {
+		.add     = lis3lv02d_add,
+		.remove  = lis3lv02d_remove,
+		.suspend = lis3lv02d_suspend,
+		.resume  = lis3lv02d_resume,
+	}
+};
+
+static int __init lis3lv02d_init_module(void)
+{
+	int ret;
+
+	if (acpi_disabled)
+		return -ENODEV;
+
+	ret = acpi_bus_register_driver(&lis3lv02d_driver);
+	if (ret < 0)
+		return ret;
+
+	pr_info("driver loaded\n");
+
+	return 0;
+}
+
+static void __exit lis3lv02d_exit_module(void)
+{
+	acpi_bus_unregister_driver(&lis3lv02d_driver);
+}
+
+MODULE_DESCRIPTION("Glue between LIS3LV02Dx and HP ACPI BIOS and support for disk protection LED.");
+MODULE_AUTHOR("Yan Burman, Eric Piel, Pavel Machek");
+MODULE_LICENSE("GPL");
+
+module_init(lis3lv02d_init_module);
+module_exit(lis3lv02d_exit_module);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/hp-wmi.c linux-libre-2.6.39-gnu/drivers/platform/x86/hp-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/hp-wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/hp-wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -2,6 +2,7 @@
  * HP WMI hotkeys
  *
  * Copyright (C) 2008 Red Hat <mjg@redhat.com>
+ * Copyright (C) 2010, 2011 Anssi Hannula <anssi.hannula@iki.fi>
  *
  * Portions based on wistron_btns.c:
  * Copyright (C) 2005 Miloslav Trmac <mitr@volny.cz>
@@ -51,6 +52,7 @@
 #define HPWMI_HARDWARE_QUERY 0x4
 #define HPWMI_WIRELESS_QUERY 0x5
 #define HPWMI_HOTKEY_QUERY 0xc
+#define HPWMI_WIRELESS2_QUERY 0x1b
 
 #define PREFIX "HP WMI: "
 #define UNIMP "Unimplemented "
@@ -86,7 +88,46 @@
 struct bios_return {
 	u32 sigpass;
 	u32 return_code;
-	u32 value;
+};
+
+enum hp_return_value {
+	HPWMI_RET_WRONG_SIGNATURE	= 0x02,
+	HPWMI_RET_UNKNOWN_COMMAND	= 0x03,
+	HPWMI_RET_UNKNOWN_CMDTYPE	= 0x04,
+	HPWMI_RET_INVALID_PARAMETERS	= 0x05,
+};
+
+enum hp_wireless2_bits {
+	HPWMI_POWER_STATE	= 0x01,
+	HPWMI_POWER_SOFT	= 0x02,
+	HPWMI_POWER_BIOS	= 0x04,
+	HPWMI_POWER_HARD	= 0x08,
+};
+
+#define IS_HWBLOCKED(x) ((x & (HPWMI_POWER_BIOS | HPWMI_POWER_HARD)) \
+			 != (HPWMI_POWER_BIOS | HPWMI_POWER_HARD))
+#define IS_SWBLOCKED(x) !(x & HPWMI_POWER_SOFT)
+
+struct bios_rfkill2_device_state {
+	u8 radio_type;
+	u8 bus_type;
+	u16 vendor_id;
+	u16 product_id;
+	u16 subsys_vendor_id;
+	u16 subsys_product_id;
+	u8 rfkill_id;
+	u8 power;
+	u8 unknown[4];
+};
+
+/* 7 devices fit into the 128 byte buffer */
+#define HPWMI_MAX_RFKILL2_DEVICES	7
+
+struct bios_rfkill2_state {
+	u8 unknown[7];
+	u8 count;
+	u8 pad[8];
+	struct bios_rfkill2_device_state device[HPWMI_MAX_RFKILL2_DEVICES];
 };
 
 static const struct key_entry hp_wmi_keymap[] = {
@@ -108,6 +149,15 @@
 static struct rfkill *bluetooth_rfkill;
 static struct rfkill *wwan_rfkill;
 
+struct rfkill2_device {
+	u8 id;
+	int num;
+	struct rfkill *rfkill;
+};
+
+static int rfkill2_count;
+static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES];
+
 static const struct dev_pm_ops hp_wmi_pm_ops = {
 	.resume  = hp_wmi_resume_handler,
 	.restore  = hp_wmi_resume_handler,
@@ -129,7 +179,8 @@
  * query:	The commandtype -> What should be queried
  * write:	The command -> 0 read, 1 write, 3 ODM specific
  * buffer:	Buffer used as input and/or output
- * buffersize:	Size of buffer
+ * insize:	Size of input buffer
+ * outsize:	Size of output buffer
  *
  * returns zero on success
  *         an HP WMI query specific error code (which is positive)
@@ -140,25 +191,29 @@
  *       size. E.g. Battery info query (0x7) is defined to have 1 byte input
  *       and 128 byte output. The caller would do:
  *       buffer = kzalloc(128, GFP_KERNEL);
- *       ret = hp_wmi_perform_query(0x7, 0, buffer, 128)
+ *       ret = hp_wmi_perform_query(0x7, 0, buffer, 1, 128)
  */
-static int hp_wmi_perform_query(int query, int write, u32 *buffer,
-				int buffersize)
+static int hp_wmi_perform_query(int query, int write, void *buffer,
+				int insize, int outsize)
 {
-	struct bios_return bios_return;
-	acpi_status status;
+	struct bios_return *bios_return;
+	int actual_outsize;
 	union acpi_object *obj;
 	struct bios_args args = {
 		.signature = 0x55434553,
 		.command = write ? 0x2 : 0x1,
 		.commandtype = query,
-		.datasize = buffersize,
-		.data = *buffer,
+		.datasize = insize,
+		.data = 0,
 	};
 	struct acpi_buffer input = { sizeof(struct bios_args), &args };
 	struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL };
 
-	status = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
+	if (WARN_ON(insize > sizeof(args.data)))
+		return -EINVAL;
+	memcpy(&args.data, buffer, insize);
+
+	wmi_evaluate_method(HPWMI_BIOS_GUID, 0, 0x3, &input, &output);
 
 	obj = output.pointer;
 
@@ -169,10 +224,26 @@
 		return -EINVAL;
 	}
 
-	bios_return = *((struct bios_return *)obj->buffer.pointer);
+	bios_return = (struct bios_return *)obj->buffer.pointer;
 
-	memcpy(buffer, &bios_return.value, sizeof(bios_return.value));
+	if (bios_return->return_code) {
+		if (bios_return->return_code != HPWMI_RET_UNKNOWN_CMDTYPE)
+			printk(KERN_WARNING PREFIX "query 0x%x returned "
+						   "error 0x%x\n",
+			       query, bios_return->return_code);
+		kfree(obj);
+		return bios_return->return_code;
+	}
+
+	if (!outsize) {
+		/* ignore output data */
+		kfree(obj);
+		return 0;
+	}
 
+	actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return)));
+	memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize);
+	memset(buffer + actual_outsize, 0, outsize - actual_outsize);
 	kfree(obj);
 	return 0;
 }
@@ -181,7 +252,7 @@
 {
 	int state = 0;
 	int ret = hp_wmi_perform_query(HPWMI_DISPLAY_QUERY, 0, &state,
-				       sizeof(state));
+				       sizeof(state), sizeof(state));
 	if (ret)
 		return -EINVAL;
 	return state;
@@ -191,7 +262,7 @@
 {
 	int state = 0;
 	int ret = hp_wmi_perform_query(HPWMI_HDDTEMP_QUERY, 0, &state,
-				       sizeof(state));
+				       sizeof(state), sizeof(state));
 	if (ret)
 		return -EINVAL;
 	return state;
@@ -201,7 +272,7 @@
 {
 	int state = 0;
 	int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 0, &state,
-				       sizeof(state));
+				       sizeof(state), sizeof(state));
 	if (ret)
 		return -EINVAL;
 	return state;
@@ -211,7 +282,7 @@
 {
 	int state = 0;
 	int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
-				       sizeof(state));
+				       sizeof(state), sizeof(state));
 
 	if (ret)
 		return -EINVAL;
@@ -223,7 +294,7 @@
 {
 	int state = 0;
 	int ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, 0, &state,
-				       sizeof(state));
+				       sizeof(state), sizeof(state));
 	if (ret)
 		return ret;
 
@@ -237,7 +308,7 @@
 	int ret;
 
 	ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 1,
-				   &query, sizeof(query));
+				   &query, sizeof(query), 0);
 	if (ret)
 		return -EINVAL;
 	return 0;
@@ -252,7 +323,8 @@
 	int wireless = 0;
 	int mask;
 	hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
-			     &wireless, sizeof(wireless));
+			     &wireless, sizeof(wireless),
+			     sizeof(wireless));
 	/* TBD: Pass error */
 
 	mask = 0x200 << (r * 8);
@@ -268,7 +340,8 @@
 	int wireless = 0;
 	int mask;
 	hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0,
-			     &wireless, sizeof(wireless));
+			     &wireless, sizeof(wireless),
+			     sizeof(wireless));
 	/* TBD: Pass error */
 
 	mask = 0x800 << (r * 8);
@@ -279,6 +352,51 @@
 		return true;
 }
 
+static int hp_wmi_rfkill2_set_block(void *data, bool blocked)
+{
+	int rfkill_id = (int)(long)data;
+	char buffer[4] = { 0x01, 0x00, rfkill_id, !blocked };
+
+	if (hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 1,
+				   buffer, sizeof(buffer), 0))
+		return -EINVAL;
+	return 0;
+}
+
+static const struct rfkill_ops hp_wmi_rfkill2_ops = {
+	.set_block = hp_wmi_rfkill2_set_block,
+};
+
+static int hp_wmi_rfkill2_refresh(void)
+{
+	int err, i;
+	struct bios_rfkill2_state state;
+
+	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
+				   0, sizeof(state));
+	if (err)
+		return err;
+
+	for (i = 0; i < rfkill2_count; i++) {
+		int num = rfkill2[i].num;
+		struct bios_rfkill2_device_state *devstate;
+		devstate = &state.device[num];
+
+		if (num >= state.count ||
+		    devstate->rfkill_id != rfkill2[i].id) {
+			printk(KERN_WARNING PREFIX "power configuration of "
+			       "the wireless devices unexpectedly changed\n");
+			continue;
+		}
+
+		rfkill_set_states(rfkill2[i].rfkill,
+				  IS_SWBLOCKED(devstate->power),
+				  IS_HWBLOCKED(devstate->power));
+	}
+
+	return 0;
+}
+
 static ssize_t show_display(struct device *dev, struct device_attribute *attr,
 			    char *buf)
 {
@@ -329,7 +447,7 @@
 {
 	u32 tmp = simple_strtoul(buf, NULL, 10);
 	int ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, 1, &tmp,
-				       sizeof(tmp));
+				       sizeof(tmp), sizeof(tmp));
 	if (ret)
 		return -EINVAL;
 
@@ -402,6 +520,7 @@
 	case HPWMI_BEZEL_BUTTON:
 		ret = hp_wmi_perform_query(HPWMI_HOTKEY_QUERY, 0,
 					   &key_code,
+					   sizeof(key_code),
 					   sizeof(key_code));
 		if (ret)
 			break;
@@ -412,6 +531,11 @@
 			       key_code);
 		break;
 	case HPWMI_WIRELESS:
+		if (rfkill2_count) {
+			hp_wmi_rfkill2_refresh();
+			break;
+		}
+
 		if (wifi_rfkill)
 			rfkill_set_states(wifi_rfkill,
 					  hp_wmi_get_sw_state(HPWMI_WIFI),
@@ -502,32 +626,16 @@
 	device_remove_file(&device->dev, &dev_attr_tablet);
 }
 
-static int __devinit hp_wmi_bios_setup(struct platform_device *device)
+static int __devinit hp_wmi_rfkill_setup(struct platform_device *device)
 {
 	int err;
 	int wireless = 0;
 
 	err = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, 0, &wireless,
-				   sizeof(wireless));
+				   sizeof(wireless), sizeof(wireless));
 	if (err)
 		return err;
 
-	err = device_create_file(&device->dev, &dev_attr_display);
-	if (err)
-		goto add_sysfs_error;
-	err = device_create_file(&device->dev, &dev_attr_hddtemp);
-	if (err)
-		goto add_sysfs_error;
-	err = device_create_file(&device->dev, &dev_attr_als);
-	if (err)
-		goto add_sysfs_error;
-	err = device_create_file(&device->dev, &dev_attr_dock);
-	if (err)
-		goto add_sysfs_error;
-	err = device_create_file(&device->dev, &dev_attr_tablet);
-	if (err)
-		goto add_sysfs_error;
-
 	if (wireless & 0x1) {
 		wifi_rfkill = rfkill_alloc("hp-wifi", &device->dev,
 					   RFKILL_TYPE_WLAN,
@@ -573,14 +681,131 @@
 	return 0;
 register_wwan_err:
 	rfkill_destroy(wwan_rfkill);
+	wwan_rfkill = NULL;
 	if (bluetooth_rfkill)
 		rfkill_unregister(bluetooth_rfkill);
 register_bluetooth_error:
 	rfkill_destroy(bluetooth_rfkill);
+	bluetooth_rfkill = NULL;
 	if (wifi_rfkill)
 		rfkill_unregister(wifi_rfkill);
 register_wifi_error:
 	rfkill_destroy(wifi_rfkill);
+	wifi_rfkill = NULL;
+	return err;
+}
+
+static int __devinit hp_wmi_rfkill2_setup(struct platform_device *device)
+{
+	int err, i;
+	struct bios_rfkill2_state state;
+	err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, 0, &state,
+				   0, sizeof(state));
+	if (err)
+		return err;
+
+	if (state.count > HPWMI_MAX_RFKILL2_DEVICES) {
+		printk(KERN_WARNING PREFIX "unable to parse 0x1b query output\n");
+		return -EINVAL;
+	}
+
+	for (i = 0; i < state.count; i++) {
+		struct rfkill *rfkill;
+		enum rfkill_type type;
+		char *name;
+		switch (state.device[i].radio_type) {
+		case HPWMI_WIFI:
+			type = RFKILL_TYPE_WLAN;
+			name = "hp-wifi";
+			break;
+		case HPWMI_BLUETOOTH:
+			type = RFKILL_TYPE_BLUETOOTH;
+			name = "hp-bluetooth";
+			break;
+		case HPWMI_WWAN:
+			type = RFKILL_TYPE_WWAN;
+			name = "hp-wwan";
+			break;
+		default:
+			printk(KERN_WARNING PREFIX "unknown device type 0x%x\n",
+				 state.device[i].radio_type);
+			continue;
+		}
+
+		if (!state.device[i].vendor_id) {
+			printk(KERN_WARNING PREFIX "zero device %d while %d "
+			       "reported\n", i, state.count);
+			continue;
+		}
+
+		rfkill = rfkill_alloc(name, &device->dev, type,
+				      &hp_wmi_rfkill2_ops, (void *)(long)i);
+		if (!rfkill) {
+			err = -ENOMEM;
+			goto fail;
+		}
+
+		rfkill2[rfkill2_count].id = state.device[i].rfkill_id;
+		rfkill2[rfkill2_count].num = i;
+		rfkill2[rfkill2_count].rfkill = rfkill;
+
+		rfkill_init_sw_state(rfkill,
+				     IS_SWBLOCKED(state.device[i].power));
+		rfkill_set_hw_state(rfkill,
+				    IS_HWBLOCKED(state.device[i].power));
+
+		if (!(state.device[i].power & HPWMI_POWER_BIOS))
+			printk(KERN_INFO PREFIX "device %s blocked by BIOS\n",
+			       name);
+
+		err = rfkill_register(rfkill);
+		if (err) {
+			rfkill_destroy(rfkill);
+			goto fail;
+		}
+
+		rfkill2_count++;
+	}
+
+	return 0;
+fail:
+	for (; rfkill2_count > 0; rfkill2_count--) {
+		rfkill_unregister(rfkill2[rfkill2_count - 1].rfkill);
+		rfkill_destroy(rfkill2[rfkill2_count - 1].rfkill);
+	}
+	return err;
+}
+
+static int __devinit hp_wmi_bios_setup(struct platform_device *device)
+{
+	int err;
+
+	/* clear detected rfkill devices */
+	wifi_rfkill = NULL;
+	bluetooth_rfkill = NULL;
+	wwan_rfkill = NULL;
+	rfkill2_count = 0;
+
+	if (hp_wmi_rfkill_setup(device))
+		hp_wmi_rfkill2_setup(device);
+
+	err = device_create_file(&device->dev, &dev_attr_display);
+	if (err)
+		goto add_sysfs_error;
+	err = device_create_file(&device->dev, &dev_attr_hddtemp);
+	if (err)
+		goto add_sysfs_error;
+	err = device_create_file(&device->dev, &dev_attr_als);
+	if (err)
+		goto add_sysfs_error;
+	err = device_create_file(&device->dev, &dev_attr_dock);
+	if (err)
+		goto add_sysfs_error;
+	err = device_create_file(&device->dev, &dev_attr_tablet);
+	if (err)
+		goto add_sysfs_error;
+	return 0;
+
 add_sysfs_error:
 	cleanup_sysfs(device);
 	return err;
@@ -588,8 +813,14 @@
 
 static int __exit hp_wmi_bios_remove(struct platform_device *device)
 {
+	int i;
 	cleanup_sysfs(device);
 
+	for (i = 0; i < rfkill2_count; i++) {
+		rfkill_unregister(rfkill2[i].rfkill);
+		rfkill_destroy(rfkill2[i].rfkill);
+	}
+
 	if (wifi_rfkill) {
 		rfkill_unregister(wifi_rfkill);
 		rfkill_destroy(wifi_rfkill);
@@ -622,6 +853,9 @@
 		input_sync(hp_wmi_input_dev);
 	}
 
+	if (rfkill2_count)
+		hp_wmi_rfkill2_refresh();
+
 	if (wifi_rfkill)
 		rfkill_set_states(wifi_rfkill,
 				  hp_wmi_get_sw_state(HPWMI_WIFI),
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/ideapad-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/ideapad-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/ideapad-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/ideapad-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -459,6 +459,8 @@
 		if (test_bit(vpc_bit, &vpc1)) {
 			if (vpc_bit == 9)
 				ideapad_sync_rfk_state(adevice);
+			else if (vpc_bit == 4)
+				read_ec_data(handle, 0x12, &vpc2);
 			else
 				ideapad_input_report(priv, vpc_bit);
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_ips.c linux-libre-2.6.39-gnu/drivers/platform/x86/intel_ips.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_ips.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/intel_ips.c	2011-05-19 00:06:34.000000000 -0400
@@ -1111,7 +1111,7 @@
 		last_msecs = jiffies_to_msecs(jiffies);
 		expire = jiffies + msecs_to_jiffies(IPS_SAMPLE_PERIOD);
 
-		__set_current_state(TASK_UNINTERRUPTIBLE);
+		__set_current_state(TASK_INTERRUPTIBLE);
 		mod_timer(&timer, expire);
 		schedule();
 
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_mid_powerbtn.c linux-libre-2.6.39-gnu/drivers/platform/x86/intel_mid_powerbtn.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_mid_powerbtn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/intel_mid_powerbtn.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,148 @@
+/*
+ * Power button driver for Medfield.
+ *
+ * Copyright (C) 2010 Intel Corp
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; 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/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/input.h>
+#include <asm/intel_scu_ipc.h>
+
+#define DRIVER_NAME "msic_power_btn"
+
+#define MSIC_IRQ_STAT	0x02
+  #define MSIC_IRQ_PB	(1 << 0)
+#define MSIC_PB_CONFIG	0x3e
+#define MSIC_PB_STATUS	0x3f
+  #define MSIC_PB_LEVEL (1 << 3) /* 1 - release, 0 - press */
+
+struct mfld_pb_priv {
+	struct input_dev *input;
+	unsigned int irq;
+};
+
+static irqreturn_t mfld_pb_isr(int irq, void *dev_id)
+{
+	struct mfld_pb_priv *priv = dev_id;
+	int ret;
+	u8 pbstat;
+
+	ret = intel_scu_ipc_ioread8(MSIC_PB_STATUS, &pbstat);
+	if (ret < 0)
+		return IRQ_HANDLED;
+
+	input_event(priv->input, EV_KEY, KEY_POWER, !(pbstat & MSIC_PB_LEVEL));
+	input_sync(priv->input);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit mfld_pb_probe(struct platform_device *pdev)
+{
+	struct mfld_pb_priv *priv;
+	struct input_dev *input;
+	int irq;
+	int error;
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0)
+		return -EINVAL;
+
+	priv = kzalloc(sizeof(struct mfld_pb_priv), GFP_KERNEL);
+	input = input_allocate_device();
+	if (!priv || !input) {
+		error = -ENOMEM;
+		goto err_free_mem;
+	}
+
+	priv->input = input;
+	priv->irq = irq;
+
+	input->name = pdev->name;
+	input->phys = "power-button/input0";
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &pdev->dev;
+
+	input_set_capability(input, EV_KEY, KEY_POWER);
+
+	error = request_threaded_irq(priv->irq, NULL, mfld_pb_isr,
+				     0, DRIVER_NAME, priv);
+	if (error) {
+		dev_err(&pdev->dev,
+			"unable to request irq %d for mfld power button\n",
+			irq);
+		goto err_free_mem;
+	}
+
+	error = input_register_device(input);
+	if (error) {
+		dev_err(&pdev->dev,
+			"unable to register input dev, error %d\n", error);
+		goto err_free_irq;
+	}
+
+	platform_set_drvdata(pdev, priv);
+	return 0;
+
+err_free_irq:
+	free_irq(priv->irq, priv);
+err_free_mem:
+	input_free_device(input);
+	kfree(priv);
+	return error;
+}
+
+static int __devexit mfld_pb_remove(struct platform_device *pdev)
+{
+	struct mfld_pb_priv *priv = platform_get_drvdata(pdev);
+
+	free_irq(priv->irq, priv);
+	input_unregister_device(priv->input);
+	kfree(priv);
+
+	platform_set_drvdata(pdev, NULL);
+	return 0;
+}
+
+static struct platform_driver mfld_pb_driver = {
+	.driver = {
+		.name = DRIVER_NAME,
+		.owner = THIS_MODULE,
+	},
+	.probe	= mfld_pb_probe,
+	.remove	= __devexit_p(mfld_pb_remove),
+};
+
+static int __init mfld_pb_init(void)
+{
+	return platform_driver_register(&mfld_pb_driver);
+}
+module_init(mfld_pb_init);
+
+static void __exit mfld_pb_exit(void)
+{
+	platform_driver_unregister(&mfld_pb_driver);
+}
+module_exit(mfld_pb_exit);
+
+MODULE_AUTHOR("Hong Liu <hong.liu@intel.com>");
+MODULE_DESCRIPTION("Intel Medfield Power Button Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:" DRIVER_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_mid_thermal.c linux-libre-2.6.39-gnu/drivers/platform/x86/intel_mid_thermal.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_mid_thermal.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/intel_mid_thermal.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,576 @@
+/*
+ * intel_mid_thermal.c - Intel MID platform thermal driver
+ *
+ * Copyright (C) 2011 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.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.        See 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.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ * Author: Durgadoss R <durgadoss.r@intel.com>
+ */
+
+#define pr_fmt(fmt) "intel_mid_thermal: " fmt
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/param.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/pm.h>
+#include <linux/thermal.h>
+
+#include <asm/intel_scu_ipc.h>
+
+/* Number of thermal sensors */
+#define MSIC_THERMAL_SENSORS   4
+
+/* ADC1 - thermal registers */
+#define MSIC_THERM_ADC1CNTL1   0x1C0
+#define MSIC_ADC_ENBL          0x10
+#define MSIC_ADC_START         0x08
+
+#define MSIC_THERM_ADC1CNTL3   0x1C2
+#define MSIC_ADCTHERM_ENBL     0x04
+#define MSIC_ADCRRDATA_ENBL    0x05
+#define MSIC_CHANL_MASK_VAL    0x0F
+
+#define MSIC_STOPBIT_MASK      16
+#define MSIC_ADCTHERM_MASK     4
+#define ADC_CHANLS_MAX         15 /* Number of ADC channels */
+#define ADC_LOOP_MAX           (ADC_CHANLS_MAX - MSIC_THERMAL_SENSORS)
+
+/* ADC channel code values */
+#define SKIN_SENSOR0_CODE      0x08
+#define SKIN_SENSOR1_CODE      0x09
+#define SYS_SENSOR_CODE                0x0A
+#define MSIC_DIE_SENSOR_CODE   0x03
+
+#define SKIN_THERM_SENSOR0     0
+#define SKIN_THERM_SENSOR1     1
+#define SYS_THERM_SENSOR2      2
+#define MSIC_DIE_THERM_SENSOR3 3
+
+/* ADC code range */
+#define ADC_MAX                        977
+#define ADC_MIN                        162
+#define ADC_VAL0C              887
+#define ADC_VAL20C             720
+#define ADC_VAL40C             508
+#define ADC_VAL60C             315
+
+/* ADC base addresses */
+#define ADC_CHNL_START_ADDR    0x1C5   /* increments by 1 */
+#define ADC_DATA_START_ADDR     0x1D4   /* increments by 2 */
+
+/* MSIC die attributes */
+#define MSIC_DIE_ADC_MIN       488
+#define MSIC_DIE_ADC_MAX       1004
+
+/* This holds the address of the first free ADC channel,
+ * among the 15 channels
+ */
+static int channel_index;
+
+struct platform_info {
+       struct platform_device *pdev;
+       struct thermal_zone_device *tzd[MSIC_THERMAL_SENSORS];
+};
+
+struct thermal_device_info {
+       unsigned int chnl_addr;
+       int direct;
+       /* This holds the current temperature in millidegree celsius */
+       long curr_temp;
+};
+
+/**
+ * to_msic_die_temp - converts adc_val to msic_die temperature
+ * @adc_val: ADC value to be converted
+ *
+ * Can sleep
+ */
+static int to_msic_die_temp(uint16_t adc_val)
+{
+       return (368 * (adc_val) / 1000) - 220;
+}
+
+/**
+ * is_valid_adc - checks whether the adc code is within the defined range
+ * @min: minimum value for the sensor
+ * @max: maximum value for the sensor
+ *
+ * Can sleep
+ */
+static int is_valid_adc(uint16_t adc_val, uint16_t min, uint16_t max)
+{
+       return (adc_val >= min) && (adc_val <= max);
+}
+
+/**
+ * adc_to_temp - converts the ADC code to temperature in C
+ * @direct: true if ths channel is direct index
+ * @adc_val: the adc_val that needs to be converted
+ * @tp: temperature return value
+ *
+ * Linear approximation is used to covert the skin adc value into temperature.
+ * This technique is used to avoid very long look-up table to get
+ * the appropriate temp value from ADC value.
+ * The adc code vs sensor temp curve is split into five parts
+ * to achieve very close approximate temp value with less than
+ * 0.5C error
+ */
+static int adc_to_temp(int direct, uint16_t adc_val, unsigned long *tp)
+{
+       int temp;
+
+       /* Direct conversion for die temperature */
+       if (direct) {
+               if (is_valid_adc(adc_val, MSIC_DIE_ADC_MIN, MSIC_DIE_ADC_MAX)) {
+                       *tp = to_msic_die_temp(adc_val) * 1000;
+                       return 0;
+               }
+               return -ERANGE;
+       }
+
+       if (!is_valid_adc(adc_val, ADC_MIN, ADC_MAX))
+               return -ERANGE;
+
+       /* Linear approximation for skin temperature */
+       if (adc_val > ADC_VAL0C)
+               temp = 177 - (adc_val/5);
+       else if ((adc_val <= ADC_VAL0C) && (adc_val > ADC_VAL20C))
+               temp = 111 - (adc_val/8);
+       else if ((adc_val <= ADC_VAL20C) && (adc_val > ADC_VAL40C))
+               temp = 92 - (adc_val/10);
+       else if ((adc_val <= ADC_VAL40C) && (adc_val > ADC_VAL60C))
+               temp = 91 - (adc_val/10);
+       else
+               temp = 112 - (adc_val/6);
+
+       /* Convert temperature in celsius to milli degree celsius */
+       *tp = temp * 1000;
+       return 0;
+}
+
+/**
+ * mid_read_temp - read sensors for temperature
+ * @temp: holds the current temperature for the sensor after reading
+ *
+ * reads the adc_code from the channel and converts it to real
+ * temperature. The converted value is stored in temp.
+ *
+ * Can sleep
+ */
+static int mid_read_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+{
+       struct thermal_device_info *td_info = tzd->devdata;
+       uint16_t adc_val, addr;
+       uint8_t data = 0;
+       int ret;
+       unsigned long curr_temp;
+
+
+       addr = td_info->chnl_addr;
+
+       /* Enable the msic for conversion before reading */
+       ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCRRDATA_ENBL);
+       if (ret)
+               return ret;
+
+       /* Re-toggle the RRDATARD bit (temporary workaround) */
+       ret = intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL3, MSIC_ADCTHERM_ENBL);
+       if (ret)
+               return ret;
+
+       /* Read the higher bits of data */
+       ret = intel_scu_ipc_ioread8(addr, &data);
+       if (ret)
+               return ret;
+
+       /* Shift bits to accommodate the lower two data bits */
+       adc_val = (data << 2);
+       addr++;
+
+       ret = intel_scu_ipc_ioread8(addr, &data);/* Read lower bits */
+       if (ret)
+               return ret;
+
+       /* Adding lower two bits to the higher bits */
+       data &= 03;
+       adc_val += data;
+
+       /* Convert ADC value to temperature */
+       ret = adc_to_temp(td_info->direct, adc_val, &curr_temp);
+       if (ret == 0)
+               *temp = td_info->curr_temp = curr_temp;
+       return ret;
+}
+
+/**
+ * configure_adc - enables/disables the ADC for conversion
+ * @val: zero: disables the ADC non-zero:enables the ADC
+ *
+ * Enable/Disable the ADC depending on the argument
+ *
+ * Can sleep
+ */
+static int configure_adc(int val)
+{
+       int ret;
+       uint8_t data;
+
+       ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
+       if (ret)
+               return ret;
+
+       if (val) {
+               /* Enable and start the ADC */
+               data |= (MSIC_ADC_ENBL | MSIC_ADC_START);
+       } else {
+               /* Just stop the ADC */
+               data &= (~MSIC_ADC_START);
+       }
+
+       return intel_scu_ipc_iowrite8(MSIC_THERM_ADC1CNTL1, data);
+}
+
+/**
+ * set_up_therm_channel - enable thermal channel for conversion
+ * @base_addr: index of free msic ADC channel
+ *
+ * Enable all the three channels for conversion
+ *
+ * Can sleep
+ */
+static int set_up_therm_channel(u16 base_addr)
+{
+       int ret;
+
+       /* Enable all the sensor channels */
+       ret = intel_scu_ipc_iowrite8(base_addr, SKIN_SENSOR0_CODE);
+       if (ret)
+               return ret;
+
+       ret = intel_scu_ipc_iowrite8(base_addr + 1, SKIN_SENSOR1_CODE);
+       if (ret)
+               return ret;
+
+       ret = intel_scu_ipc_iowrite8(base_addr + 2, SYS_SENSOR_CODE);
+       if (ret)
+               return ret;
+
+       /* Since this is the last channel, set the stop bit
+          to 1 by ORing the DIE_SENSOR_CODE with 0x10 */
+       ret = intel_scu_ipc_iowrite8(base_addr + 3,
+                                       (MSIC_DIE_SENSOR_CODE | 0x10));
+       if (ret)
+               return ret;
+
+       /* Enable ADC and start it */
+       return configure_adc(1);
+}
+
+/**
+ * reset_stopbit - sets the stop bit to 0 on the given channel
+ * @addr: address of the channel
+ *
+ * Can sleep
+ */
+static int reset_stopbit(uint16_t addr)
+{
+       int ret;
+       uint8_t data;
+       ret = intel_scu_ipc_ioread8(addr, &data);
+       if (ret)
+               return ret;
+       /* Set the stop bit to zero */
+       return intel_scu_ipc_iowrite8(addr, (data & 0xEF));
+}
+
+/**
+ * find_free_channel - finds an empty channel for conversion
+ *
+ * If the ADC is not enabled then start using 0th channel
+ * itself. Otherwise find an empty channel by looking for a
+ * channel in which the stopbit is set to 1. returns the index
+ * of the first free channel if succeeds or an error code.
+ *
+ * Context: can sleep
+ *
+ * FIXME: Ultimately the channel allocator will move into the intel_scu_ipc
+ * code.
+ */
+static int find_free_channel(void)
+{
+       int ret;
+       int i;
+       uint8_t data;
+
+       /* check whether ADC is enabled */
+       ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL1, &data);
+       if (ret)
+               return ret;
+
+       if ((data & MSIC_ADC_ENBL) == 0)
+               return 0;
+
+       /* ADC is already enabled; Looking for an empty channel */
+       for (i = 0; i < ADC_CHANLS_MAX; i++) {
+               ret = intel_scu_ipc_ioread8(ADC_CHNL_START_ADDR + i, &data);
+               if (ret)
+                       return ret;
+
+               if (data & MSIC_STOPBIT_MASK) {
+                       ret = i;
+                       break;
+               }
+       }
+       return (ret > ADC_LOOP_MAX) ? (-EINVAL) : ret;
+}
+
+/**
+ * mid_initialize_adc - initializing the ADC
+ * @dev: our device structure
+ *
+ * Initialize the ADC for reading thermistor values. Can sleep.
+ */
+static int mid_initialize_adc(struct device *dev)
+{
+       u8  data;
+       u16 base_addr;
+       int ret;
+
+       /*
+        * Ensure that adctherm is disabled before we
+        * initialize the ADC
+        */
+       ret = intel_scu_ipc_ioread8(MSIC_THERM_ADC1CNTL3, &data);
+       if (ret)
+               return ret;
+
+       if (data & MSIC_ADCTHERM_MASK)
+               dev_warn(dev, "ADCTHERM already set");
+
+       /* Index of the first channel in which the stop bit is set */
+       channel_index = find_free_channel();
+       if (channel_index < 0) {
+               dev_err(dev, "No free ADC channels");
+               return channel_index;
+       }
+
+       base_addr = ADC_CHNL_START_ADDR + channel_index;
+
+       if (!(channel_index == 0 || channel_index == ADC_LOOP_MAX)) {
+               /* Reset stop bit for channels other than 0 and 12 */
+               ret = reset_stopbit(base_addr);
+               if (ret)
+                       return ret;
+
+               /* Index of the first free channel */
+               base_addr++;
+               channel_index++;
+       }
+
+       ret = set_up_therm_channel(base_addr);
+       if (ret) {
+               dev_err(dev, "unable to enable ADC");
+               return ret;
+       }
+       dev_dbg(dev, "ADC initialization successful");
+       return ret;
+}
+
+/**
+ * initialize_sensor - sets default temp and timer ranges
+ * @index: index of the sensor
+ *
+ * Context: can sleep
+ */
+static struct thermal_device_info *initialize_sensor(int index)
+{
+       struct thermal_device_info *td_info =
+               kzalloc(sizeof(struct thermal_device_info), GFP_KERNEL);
+
+       if (!td_info)
+               return NULL;
+
+       /* Set the base addr of the channel for this sensor */
+       td_info->chnl_addr = ADC_DATA_START_ADDR + 2 * (channel_index + index);
+       /* Sensor 3 is direct conversion */
+       if (index == 3)
+               td_info->direct = 1;
+       return td_info;
+}
+
+/**
+ * mid_thermal_resume - resume routine
+ * @pdev: platform device structure
+ *
+ * mid thermal resume: re-initializes the adc. Can sleep.
+ */
+static int mid_thermal_resume(struct platform_device *pdev)
+{
+       return mid_initialize_adc(&pdev->dev);
+}
+
+/**
+ * mid_thermal_suspend - suspend routine
+ * @pdev: platform device structure
+ *
+ * mid thermal suspend implements the suspend functionality
+ * by stopping the ADC. Can sleep.
+ */
+static int mid_thermal_suspend(struct platform_device *pdev, pm_message_t mesg)
+{
+       /*
+        * This just stops the ADC and does not disable it.
+        * temporary workaround until we have a generic ADC driver.
+        * If 0 is passed, it disables the ADC.
+        */
+       return configure_adc(0);
+}
+
+/**
+ * read_curr_temp - reads the current temperature and stores in temp
+ * @temp: holds the current temperature value after reading
+ *
+ * Can sleep
+ */
+static int read_curr_temp(struct thermal_zone_device *tzd, unsigned long *temp)
+{
+       WARN_ON(tzd == NULL);
+       return mid_read_temp(tzd, temp);
+}
+
+/* Can't be const */
+static struct thermal_zone_device_ops tzd_ops = {
+       .get_temp = read_curr_temp,
+};
+
+
+/**
+ * mid_thermal_probe - mfld thermal initialize
+ * @pdev: platform device structure
+ *
+ * mid thermal probe initializes the hardware and registers
+ * all the sensors with the generic thermal framework. Can sleep.
+ */
+static int mid_thermal_probe(struct platform_device *pdev)
+{
+       static char *name[MSIC_THERMAL_SENSORS] = {
+               "skin0", "skin1", "sys", "msicdie"
+       };
+
+       int ret;
+       int i;
+       struct platform_info *pinfo;
+
+       pinfo = kzalloc(sizeof(struct platform_info), GFP_KERNEL);
+       if (!pinfo)
+               return -ENOMEM;
+
+       /* Initializing the hardware */
+       ret = mid_initialize_adc(&pdev->dev);
+       if (ret) {
+               dev_err(&pdev->dev, "ADC init failed");
+               kfree(pinfo);
+               return ret;
+       }
+
+       /* Register each sensor with the generic thermal framework*/
+       for (i = 0; i < MSIC_THERMAL_SENSORS; i++) {
+               pinfo->tzd[i] = thermal_zone_device_register(name[i],
+                                       0, initialize_sensor(i),
+                                       &tzd_ops, 0, 0, 0, 0);
+               if (IS_ERR(pinfo->tzd[i]))
+                       goto reg_fail;
+       }
+
+       pinfo->pdev = pdev;
+       platform_set_drvdata(pdev, pinfo);
+       return 0;
+
+reg_fail:
+       ret = PTR_ERR(pinfo->tzd[i]);
+       while (--i >= 0)
+               thermal_zone_device_unregister(pinfo->tzd[i]);
+       configure_adc(0);
+       kfree(pinfo);
+       return ret;
+}
+
+/**
+ * mid_thermal_remove - mfld thermal finalize
+ * @dev: platform device structure
+ *
+ * MLFD thermal remove unregisters all the sensors from the generic
+ * thermal framework. Can sleep.
+ */
+static int mid_thermal_remove(struct platform_device *pdev)
+{
+       int i;
+       struct platform_info *pinfo = platform_get_drvdata(pdev);
+
+       for (i = 0; i < MSIC_THERMAL_SENSORS; i++)
+               thermal_zone_device_unregister(pinfo->tzd[i]);
+
+       platform_set_drvdata(pdev, NULL);
+
+       /* Stop the ADC */
+       return configure_adc(0);
+}
+
+/*********************************************************************
+ *             Driver initialisation and finalization
+ *********************************************************************/
+
+#define DRIVER_NAME "msic_sensor"
+
+static const struct platform_device_id therm_id_table[] = {
+       { DRIVER_NAME, 1 },
+       { }
+};
+
+static struct platform_driver mid_thermal_driver = {
+       .driver = {
+               .name = DRIVER_NAME,
+               .owner = THIS_MODULE,
+       },
+       .probe = mid_thermal_probe,
+       .suspend = mid_thermal_suspend,
+       .resume = mid_thermal_resume,
+       .remove = __devexit_p(mid_thermal_remove),
+       .id_table = therm_id_table,
+};
+
+static int __init mid_thermal_module_init(void)
+{
+       return platform_driver_register(&mid_thermal_driver);
+}
+
+static void __exit mid_thermal_module_exit(void)
+{
+       platform_driver_unregister(&mid_thermal_driver);
+}
+
+module_init(mid_thermal_module_init);
+module_exit(mid_thermal_module_exit);
+
+MODULE_AUTHOR("Durgadoss R <durgadoss.r@intel.com>");
+MODULE_DESCRIPTION("Intel Medfield Platform Thermal Driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_pmic_gpio.c linux-libre-2.6.39-gnu/drivers/platform/x86/intel_pmic_gpio.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_pmic_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/intel_pmic_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,6 +74,19 @@
 	u32			trigger_type;
 };
 
+static void pmic_program_irqtype(int gpio, int type)
+{
+	if (type & IRQ_TYPE_EDGE_RISING)
+		intel_scu_ipc_update_register(GPIO0 + gpio, 0x20, 0x20);
+	else
+		intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x20);
+
+	if (type & IRQ_TYPE_EDGE_FALLING)
+		intel_scu_ipc_update_register(GPIO0 + gpio, 0x10, 0x10);
+	else
+		intel_scu_ipc_update_register(GPIO0 + gpio, 0x00, 0x10);
+};
+
 static int pmic_gpio_direction_input(struct gpio_chip *chip, unsigned offset)
 {
 	if (offset > 8) {
@@ -166,16 +179,38 @@
 	return pg->irq_base + offset;
 }
 
+static void pmic_bus_lock(struct irq_data *data)
+{
+	struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
+
+	mutex_lock(&pg->buslock);
+}
+
+static void pmic_bus_sync_unlock(struct irq_data *data)
+{
+	struct pmic_gpio *pg = irq_data_get_irq_chip_data(data);
+
+	if (pg->update_type) {
+		unsigned int gpio = pg->update_type & ~GPIO_UPDATE_TYPE;
+
+		pmic_program_irqtype(gpio, pg->trigger_type);
+		pg->update_type = 0;
+	}
+	mutex_unlock(&pg->buslock);
+}
+
 /* the gpiointr register is read-clear, so just do nothing. */
 static void pmic_irq_unmask(struct irq_data *data) { }
 
 static void pmic_irq_mask(struct irq_data *data) { }
 
 static struct irq_chip pmic_irqchip = {
-	.name		= "PMIC-GPIO",
-	.irq_mask	= pmic_irq_mask,
-	.irq_unmask	= pmic_irq_unmask,
-	.irq_set_type	= pmic_irq_type,
+	.name			= "PMIC-GPIO",
+	.irq_mask		= pmic_irq_mask,
+	.irq_unmask		= pmic_irq_unmask,
+	.irq_set_type		= pmic_irq_type,
+	.irq_bus_lock		= pmic_bus_lock,
+	.irq_bus_sync_unlock	= pmic_bus_sync_unlock,
 };
 
 static irqreturn_t pmic_irq_handler(int irq, void *data)
@@ -257,9 +292,11 @@
 	}
 
 	for (i = 0; i < 8; i++) {
-		set_irq_chip_and_handler_name(i + pg->irq_base, &pmic_irqchip,
-					handle_simple_irq, "demux");
-		set_irq_chip_data(i + pg->irq_base, pg);
+		irq_set_chip_and_handler_name(i + pg->irq_base,
+					      &pmic_irqchip,
+					      handle_simple_irq,
+					      "demux");
+		irq_set_chip_data(i + pg->irq_base, pg);
 	}
 	return 0;
 err:
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_rar_register.c linux-libre-2.6.39-gnu/drivers/platform/x86/intel_rar_register.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_rar_register.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/intel_rar_register.c	2011-05-19 00:06:34.000000000 -0400
@@ -485,7 +485,7 @@
  *
  *	The register_rar function is to used by other device drivers
  *	to ensure that this driver is ready. As we cannot be sure of
- *	the compile/execute order of drivers in ther kernel, it is
+ *	the compile/execute order of drivers in the kernel, it is
  *	best to give this driver a callback function to call when
  *	it is ready to give out addresses. The callback function
  *	would have those steps that continue the initialization of
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/intel_scu_ipc.c linux-libre-2.6.39-gnu/drivers/platform/x86/intel_scu_ipc.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/intel_scu_ipc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/intel_scu_ipc.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
  * as published by the Free Software Foundation; version 2
  * of the License.
  *
- * SCU runing in ARC processor communicates with other entity running in IA
+ * SCU running in ARC processor communicates with other entity running in IA
  * core through IPC mechanism which in turn messaging between IA core ad SCU.
  * SCU has two IPC mechanism IPC-1 and IPC-2. IPC-1 is used between IA32 and
  * SCU where IPC-2 is used between P-Unit and SCU. This driver delas with
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/Kconfig linux-libre-2.6.39-gnu/drivers/platform/x86/Kconfig
--- linux-libre-2.6.38-gnu/drivers/platform/x86/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -101,6 +101,19 @@
 	  To compile this driver as a module, choose M here: the module will
 	  be called dell-wmi.
 
+config DELL_WMI_AIO
+	tristate "WMI Hotkeys for Dell All-In-One series"
+	depends on ACPI_WMI
+	depends on INPUT
+	select INPUT_SPARSEKMAP
+	---help---
+	  Say Y here if you want to support WMI-based hotkeys on Dell
+	  All-In-One machines.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called dell-wmi.
+
+
 config FUJITSU_LAPTOP
 	tristate "Fujitsu Laptop Extras"
 	depends on ACPI
@@ -138,6 +151,24 @@
 	  This is a driver for the WMI extensions (wireless and bluetooth power
 	  control) of the HP Compaq TC1100 tablet.
 
+config HP_ACCEL
+	tristate "HP laptop accelerometer"
+	depends on INPUT && ACPI
+	select SENSORS_LIS3LV02D
+	select NEW_LEDS
+	select LEDS_CLASS
+	help
+	  This driver provides support for the "Mobile Data Protection System 3D"
+	  or "3D DriveGuard" feature of HP laptops. On such systems the driver
+	  should load automatically (via ACPI alias).
+
+	  Support for a led indicating disk protection will be provided as
+	  hp::hddprotect. For more information on the feature, refer to
+	  Documentation/hwmon/lis3lv02d.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called hp_accel.
+
 config HP_WMI
 	tristate "HP WMI extras"
 	depends on ACPI_WMI
@@ -156,7 +187,8 @@
 	depends on ACPI
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on RFKILL
-	depends on SERIO_I8042
+	depends on INPUT && SERIO_I8042
+	select INPUT_SPARSEKMAP
 	---help---
 	  This is a driver for laptops built by MSI (MICRO-STAR
 	  INTERNATIONAL):
@@ -420,23 +452,53 @@
 	  Bluetooth, backlight and allows powering on/off some other
 	  devices.
 
-	  If you have an Eee PC laptop, say Y or M here.
+	  If you have an Eee PC laptop, say Y or M here. If this driver
+	  doesn't work on your Eee PC, try eeepc-wmi instead.
 
-config EEEPC_WMI
-	tristate "Eee PC WMI Hotkey Driver (EXPERIMENTAL)"
+config ASUS_WMI
+	tristate "ASUS WMI Driver (EXPERIMENTAL)"
 	depends on ACPI_WMI
 	depends on INPUT
+	depends on HWMON
 	depends on EXPERIMENTAL
 	depends on BACKLIGHT_CLASS_DEVICE
 	depends on RFKILL || RFKILL = n
+	depends on HOTPLUG_PCI
 	select INPUT_SPARSEKMAP
 	select LEDS_CLASS
 	select NEW_LEDS
 	---help---
-	  Say Y here if you want to support WMI-based hotkeys on Eee PC laptops.
+	  Say Y here if you have a WMI aware Asus laptop (like Eee PCs or new
+	  Asus Notebooks).
 
 	  To compile this driver as a module, choose M here: the module will
-	  be called eeepc-wmi.
+	  be called asus-wmi.
+
+config ASUS_NB_WMI
+	tristate "Asus Notebook WMI Driver (EXPERIMENTAL)"
+	depends on ASUS_WMI
+	---help---
+	  This is a driver for newer Asus notebooks. It adds extra features
+	  like wireless radio and bluetooth control, leds, hotkeys, backlight...
+
+	  For more informations, see
+	  <file:Documentation/ABI/testing/sysfs-platform-asus-wmi>
+
+	  If you have an ACPI-WMI compatible Asus Notebook, say Y or M
+	  here.
+
+config EEEPC_WMI
+	tristate "Eee PC WMI Driver (EXPERIMENTAL)"
+	depends on ASUS_WMI
+	---help---
+	  This is a driver for newer Eee PC laptops. It adds extra features
+	  like wireless radio and bluetooth control, leds, hotkeys, backlight...
+
+	  For more informations, see
+	  <file:Documentation/ABI/testing/sysfs-platform-asus-wmi>
+
+	  If you have an ACPI-WMI compatible Eee PC laptop (>= 1000), say Y or M
+	  here.
 
 config ACPI_WMI
 	tristate "WMI"
@@ -598,6 +660,21 @@
 	  Say Y here to support GPIO via the SCU IPC interface
 	  on Intel MID platforms.
 
+config INTEL_MID_POWER_BUTTON
+	tristate "power button driver for Intel MID platforms"
+	depends on INTEL_SCU_IPC && INPUT
+	help
+	  This driver handles the power button on the Intel MID platforms.
+
+	  If unsure, say N.
+
+config INTEL_MFLD_THERMAL
+       tristate "Thermal driver for Intel Medfield platform"
+       depends on INTEL_SCU_IPC && THERMAL
+       help
+         Say Y here to enable thermal driver support for the  Intel Medfield
+         platform.
+
 config RAR_REGISTER
 	bool "Restricted Access Region Register Driver"
 	depends on PCI && X86_MRST
@@ -654,4 +731,26 @@
 	  Support for enabling/disabling the WLAN interface on the OLPC XO-1
 	  laptop.
 
+config XO15_EBOOK
+	tristate "OLPC XO-1.5 ebook switch"
+	depends on ACPI && INPUT
+	---help---
+	  Support for the ebook switch on the OLPC XO-1.5 laptop.
+
+	  This switch is triggered as the screen is rotated and folded down to
+	  convert the device into ebook form.
+
+config SAMSUNG_LAPTOP
+	tristate "Samsung Laptop driver"
+	depends on RFKILL && BACKLIGHT_CLASS_DEVICE && X86
+	---help---
+	  This module implements a driver for a wide range of different
+	  Samsung laptops.  It offers control over the different
+	  function keys, wireless LED, LCD backlight level, and
+	  sometimes provides a "performance_control" sysfs file to allow
+	  the performance level of the laptop to be changed.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called samsung-laptop.
+
 endif # X86_PLATFORM_DEVICES
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/Makefile linux-libre-2.6.39-gnu/drivers/platform/x86/Makefile
--- linux-libre-2.6.38-gnu/drivers/platform/x86/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,8 @@
 # x86 Platform-Specific Drivers
 #
 obj-$(CONFIG_ASUS_LAPTOP)	+= asus-laptop.o
+obj-$(CONFIG_ASUS_WMI)		+= asus-wmi.o
+obj-$(CONFIG_ASUS_NB_WMI)	+= asus-nb-wmi.o
 obj-$(CONFIG_EEEPC_LAPTOP)	+= eeepc-laptop.o
 obj-$(CONFIG_EEEPC_WMI)		+= eeepc-wmi.o
 obj-$(CONFIG_MSI_LAPTOP)	+= msi-laptop.o
@@ -10,8 +12,10 @@
 obj-$(CONFIG_COMPAL_LAPTOP)	+= compal-laptop.o
 obj-$(CONFIG_DELL_LAPTOP)	+= dell-laptop.o
 obj-$(CONFIG_DELL_WMI)		+= dell-wmi.o
+obj-$(CONFIG_DELL_WMI_AIO)	+= dell-wmi-aio.o
 obj-$(CONFIG_ACER_WMI)		+= acer-wmi.o
 obj-$(CONFIG_ACERHDF)		+= acerhdf.o
+obj-$(CONFIG_HP_ACCEL)		+= hp_accel.o
 obj-$(CONFIG_HP_WMI)		+= hp-wmi.o
 obj-$(CONFIG_TC1100_WMI)	+= tc1100-wmi.o
 obj-$(CONFIG_SONY_LAPTOP)	+= sony-laptop.o
@@ -28,9 +32,13 @@
 obj-$(CONFIG_ACPI_TOSHIBA)	+= toshiba_acpi.o
 obj-$(CONFIG_TOSHIBA_BT_RFKILL)	+= toshiba_bluetooth.o
 obj-$(CONFIG_INTEL_SCU_IPC)	+= intel_scu_ipc.o
-obj-$(CONFIG_INTEL_SCU_IPC_UTIL)+= intel_scu_ipcutil.o
+obj-$(CONFIG_INTEL_SCU_IPC_UTIL) += intel_scu_ipcutil.o
+obj-$(CONFIG_INTEL_MFLD_THERMAL) += intel_mid_thermal.o
 obj-$(CONFIG_RAR_REGISTER)	+= intel_rar_register.o
 obj-$(CONFIG_INTEL_IPS)		+= intel_ips.o
 obj-$(CONFIG_GPIO_INTEL_PMIC)	+= intel_pmic_gpio.o
 obj-$(CONFIG_XO1_RFKILL)	+= xo1-rfkill.o
+obj-$(CONFIG_XO15_EBOOK)	+= xo15-ebook.o
 obj-$(CONFIG_IBM_RTL)		+= ibm_rtl.o
+obj-$(CONFIG_SAMSUNG_LAPTOP)	+= samsung-laptop.o
+obj-$(CONFIG_INTEL_MFLD_THERMAL)	+= intel_mid_thermal.o
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/msi-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/msi-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/msi-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/msi-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,8 @@
  * laptop as MSI S270. YMMV.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/module.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
@@ -60,6 +62,8 @@
 #include <linux/platform_device.h>
 #include <linux/rfkill.h>
 #include <linux/i8042.h>
+#include <linux/input.h>
+#include <linux/input/sparse-keymap.h>
 
 #define MSI_DRIVER_VERSION "0.5"
 
@@ -78,6 +82,9 @@
 #define MSI_STANDARD_EC_SCM_LOAD_ADDRESS	0x2d
 #define MSI_STANDARD_EC_SCM_LOAD_MASK		(1 << 0)
 
+#define MSI_STANDARD_EC_TOUCHPAD_ADDRESS	0xe4
+#define MSI_STANDARD_EC_TOUCHPAD_MASK		(1 << 4)
+
 static int msi_laptop_resume(struct platform_device *device);
 
 #define MSI_STANDARD_EC_DEVICES_EXISTS_ADDRESS	0x2f
@@ -90,6 +97,14 @@
 module_param(auto_brightness, int, 0);
 MODULE_PARM_DESC(auto_brightness, "Enable automatic brightness control (0: disabled; 1: enabled; 2: don't touch)");
 
+static const struct key_entry msi_laptop_keymap[] = {
+	{KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },	/* Touch Pad On */
+	{KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },/* Touch Pad On */
+	{KE_END, 0}
+};
+
+static struct input_dev *msi_laptop_input_dev;
+
 static bool old_ec_model;
 static int wlan_s, bluetooth_s, threeg_s;
 static int threeg_exists;
@@ -432,8 +447,7 @@
 
 static int dmi_check_cb(const struct dmi_system_id *id)
 {
-	printk(KERN_INFO "msi-laptop: Identified laptop model '%s'.\n",
-	       id->ident);
+	pr_info("Identified laptop model '%s'.\n", id->ident);
 	return 1;
 }
 
@@ -605,6 +619,21 @@
 }
 static DECLARE_DELAYED_WORK(msi_rfkill_work, msi_update_rfkill);
 
+static void msi_send_touchpad_key(struct work_struct *ignored)
+{
+	u8 rdata;
+	int result;
+
+	result = ec_read(MSI_STANDARD_EC_TOUCHPAD_ADDRESS, &rdata);
+	if (result < 0)
+		return;
+
+	sparse_keymap_report_event(msi_laptop_input_dev,
+		(rdata & MSI_STANDARD_EC_TOUCHPAD_MASK) ?
+		KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF, 1, true);
+}
+static DECLARE_DELAYED_WORK(msi_touchpad_work, msi_send_touchpad_key);
+
 static bool msi_laptop_i8042_filter(unsigned char data, unsigned char str,
 				struct serio *port)
 {
@@ -613,12 +642,17 @@
 	if (str & 0x20)
 		return false;
 
-	/* 0x54 wwan, 0x62 bluetooth, 0x76 wlan*/
+	/* 0x54 wwan, 0x62 bluetooth, 0x76 wlan, 0xE4 touchpad toggle*/
 	if (unlikely(data == 0xe0)) {
 		extended = true;
 		return false;
 	} else if (unlikely(extended)) {
+		extended = false;
 		switch (data) {
+		case 0xE4:
+			schedule_delayed_work(&msi_touchpad_work,
+				round_jiffies_relative(0.5 * HZ));
+			break;
 		case 0x54:
 		case 0x62:
 		case 0x76:
@@ -626,7 +660,6 @@
 				round_jiffies_relative(0.5 * HZ));
 			break;
 		}
-		extended = false;
 	}
 
 	return false;
@@ -731,6 +764,42 @@
 	return 0;
 }
 
+static int __init msi_laptop_input_setup(void)
+{
+	int err;
+
+	msi_laptop_input_dev = input_allocate_device();
+	if (!msi_laptop_input_dev)
+		return -ENOMEM;
+
+	msi_laptop_input_dev->name = "MSI Laptop hotkeys";
+	msi_laptop_input_dev->phys = "msi-laptop/input0";
+	msi_laptop_input_dev->id.bustype = BUS_HOST;
+
+	err = sparse_keymap_setup(msi_laptop_input_dev,
+		msi_laptop_keymap, NULL);
+	if (err)
+		goto err_free_dev;
+
+	err = input_register_device(msi_laptop_input_dev);
+	if (err)
+		goto err_free_keymap;
+
+	return 0;
+
+err_free_keymap:
+	sparse_keymap_free(msi_laptop_input_dev);
+err_free_dev:
+	input_free_device(msi_laptop_input_dev);
+	return err;
+}
+
+static void msi_laptop_input_destroy(void)
+{
+	sparse_keymap_free(msi_laptop_input_dev);
+	input_unregister_device(msi_laptop_input_dev);
+}
+
 static int load_scm_model_init(struct platform_device *sdev)
 {
 	u8 data;
@@ -759,16 +828,23 @@
 	if (result < 0)
 		goto fail_rfkill;
 
+	/* setup input device */
+	result = msi_laptop_input_setup();
+	if (result)
+		goto fail_input;
+
 	result = i8042_install_filter(msi_laptop_i8042_filter);
 	if (result) {
-		printk(KERN_ERR
-			"msi-laptop: Unable to install key filter\n");
+		pr_err("Unable to install key filter\n");
 		goto fail_filter;
 	}
 
 	return 0;
 
 fail_filter:
+	msi_laptop_input_destroy();
+
+fail_input:
 	rfkill_cleanup();
 
 fail_rfkill:
@@ -799,11 +875,12 @@
 	/* Register backlight stuff */
 
 	if (acpi_video_backlight_support()) {
-		printk(KERN_INFO "MSI: Brightness ignored, must be controlled "
+		pr_info("Brightness ignored, must be controlled "
 		       "by ACPI video driver\n");
 	} else {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = MSI_LCD_LEVEL_MAX - 1;
 		msibl_device = backlight_device_register("msi-laptop-bl", NULL,
 							 NULL, &msibl_ops,
@@ -853,7 +930,7 @@
 	if (auto_brightness != 2)
 		set_auto_brightness(auto_brightness);
 
-	printk(KERN_INFO "msi-laptop: driver "MSI_DRIVER_VERSION" successfully loaded.\n");
+	pr_info("driver "MSI_DRIVER_VERSION" successfully loaded.\n");
 
 	return 0;
 
@@ -885,6 +962,7 @@
 {
 	if (load_scm_model) {
 		i8042_remove_filter(msi_laptop_i8042_filter);
+		msi_laptop_input_destroy();
 		cancel_delayed_work_sync(&msi_rfkill_work);
 		rfkill_cleanup();
 	}
@@ -900,7 +978,7 @@
 	if (auto_brightness != 2)
 		set_auto_brightness(1);
 
-	printk(KERN_INFO "msi-laptop: driver unloaded.\n");
+	pr_info("driver unloaded.\n");
 }
 
 module_init(msi_init);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/msi-wmi.c linux-libre-2.6.39-gnu/drivers/platform/x86/msi-wmi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/msi-wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/msi-wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -254,6 +254,7 @@
 	if (!acpi_video_backlight_support()) {
 		struct backlight_properties props;
 		memset(&props, 0, sizeof(struct backlight_properties));
+		props.type = BACKLIGHT_PLATFORM;
 		props.max_brightness = ARRAY_SIZE(backlight_map) - 1;
 		backlight = backlight_device_register(DRV_NAME, NULL, NULL,
 						      &msi_backlight_ops,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/panasonic-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/panasonic-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/panasonic-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/panasonic-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -602,6 +602,7 @@
 	}
 	/* initialize backlight */
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = pcc->sinf[SINF_AC_MAX_BRIGHT];
 	pcc->backlight = backlight_device_register("panasonic", NULL, pcc,
 						   &pcc_backlight_ops, &props);
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/samsung-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/samsung-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/samsung-laptop.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/samsung-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,843 @@
+/*
+ * Samsung Laptop driver
+ *
+ * Copyright (C) 2009,2011 Greg Kroah-Hartman (gregkh@suse.de)
+ * Copyright (C) 2009,2011 Novell 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.
+ *
+ */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/backlight.h>
+#include <linux/fb.h>
+#include <linux/dmi.h>
+#include <linux/platform_device.h>
+#include <linux/rfkill.h>
+
+/*
+ * This driver is needed because a number of Samsung laptops do not hook
+ * their control settings through ACPI.  So we have to poke around in the
+ * BIOS to do things like brightness values, and "special" key controls.
+ */
+
+/*
+ * We have 0 - 8 as valid brightness levels.  The specs say that level 0 should
+ * be reserved by the BIOS (which really doesn't make much sense), we tell
+ * userspace that the value is 0 - 7 and then just tell the hardware 1 - 8
+ */
+#define MAX_BRIGHT	0x07
+
+
+#define SABI_IFACE_MAIN			0x00
+#define SABI_IFACE_SUB			0x02
+#define SABI_IFACE_COMPLETE		0x04
+#define SABI_IFACE_DATA			0x05
+
+/* Structure to get data back to the calling function */
+struct sabi_retval {
+	u8 retval[20];
+};
+
+struct sabi_header_offsets {
+	u8 port;
+	u8 re_mem;
+	u8 iface_func;
+	u8 en_mem;
+	u8 data_offset;
+	u8 data_segment;
+};
+
+struct sabi_commands {
+	/*
+	 * Brightness is 0 - 8, as described above.
+	 * Value 0 is for the BIOS to use
+	 */
+	u8 get_brightness;
+	u8 set_brightness;
+
+	/*
+	 * first byte:
+	 * 0x00 - wireless is off
+	 * 0x01 - wireless is on
+	 * second byte:
+	 * 0x02 - 3G is off
+	 * 0x03 - 3G is on
+	 * TODO, verify 3G is correct, that doesn't seem right...
+	 */
+	u8 get_wireless_button;
+	u8 set_wireless_button;
+
+	/* 0 is off, 1 is on */
+	u8 get_backlight;
+	u8 set_backlight;
+
+	/*
+	 * 0x80 or 0x00 - no action
+	 * 0x81 - recovery key pressed
+	 */
+	u8 get_recovery_mode;
+	u8 set_recovery_mode;
+
+	/*
+	 * on seclinux: 0 is low, 1 is high,
+	 * on swsmi: 0 is normal, 1 is silent, 2 is turbo
+	 */
+	u8 get_performance_level;
+	u8 set_performance_level;
+
+	/*
+	 * Tell the BIOS that Linux is running on this machine.
+	 * 81 is on, 80 is off
+	 */
+	u8 set_linux;
+};
+
+struct sabi_performance_level {
+	const char *name;
+	u8 value;
+};
+
+struct sabi_config {
+	const char *test_string;
+	u16 main_function;
+	const struct sabi_header_offsets header_offsets;
+	const struct sabi_commands commands;
+	const struct sabi_performance_level performance_levels[4];
+	u8 min_brightness;
+	u8 max_brightness;
+};
+
+static const struct sabi_config sabi_configs[] = {
+	{
+		.test_string = "SECLINUX",
+
+		.main_function = 0x4c49,
+
+		.header_offsets = {
+			.port = 0x00,
+			.re_mem = 0x02,
+			.iface_func = 0x03,
+			.en_mem = 0x04,
+			.data_offset = 0x05,
+			.data_segment = 0x07,
+		},
+
+		.commands = {
+			.get_brightness = 0x00,
+			.set_brightness = 0x01,
+
+			.get_wireless_button = 0x02,
+			.set_wireless_button = 0x03,
+
+			.get_backlight = 0x04,
+			.set_backlight = 0x05,
+
+			.get_recovery_mode = 0x06,
+			.set_recovery_mode = 0x07,
+
+			.get_performance_level = 0x08,
+			.set_performance_level = 0x09,
+
+			.set_linux = 0x0a,
+		},
+
+		.performance_levels = {
+			{
+				.name = "silent",
+				.value = 0,
+			},
+			{
+				.name = "normal",
+				.value = 1,
+			},
+			{ },
+		},
+		.min_brightness = 1,
+		.max_brightness = 8,
+	},
+	{
+		.test_string = "SwSmi@",
+
+		.main_function = 0x5843,
+
+		.header_offsets = {
+			.port = 0x00,
+			.re_mem = 0x04,
+			.iface_func = 0x02,
+			.en_mem = 0x03,
+			.data_offset = 0x05,
+			.data_segment = 0x07,
+		},
+
+		.commands = {
+			.get_brightness = 0x10,
+			.set_brightness = 0x11,
+
+			.get_wireless_button = 0x12,
+			.set_wireless_button = 0x13,
+
+			.get_backlight = 0x2d,
+			.set_backlight = 0x2e,
+
+			.get_recovery_mode = 0xff,
+			.set_recovery_mode = 0xff,
+
+			.get_performance_level = 0x31,
+			.set_performance_level = 0x32,
+
+			.set_linux = 0xff,
+		},
+
+		.performance_levels = {
+			{
+				.name = "normal",
+				.value = 0,
+			},
+			{
+				.name = "silent",
+				.value = 1,
+			},
+			{
+				.name = "overclock",
+				.value = 2,
+			},
+			{ },
+		},
+		.min_brightness = 0,
+		.max_brightness = 8,
+	},
+	{ },
+};
+
+static const struct sabi_config *sabi_config;
+
+static void __iomem *sabi;
+static void __iomem *sabi_iface;
+static void __iomem *f0000_segment;
+static struct backlight_device *backlight_device;
+static struct mutex sabi_mutex;
+static struct platform_device *sdev;
+static struct rfkill *rfk;
+
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force,
+		"Disable the DMI check and forces the driver to be loaded");
+
+static int debug;
+module_param(debug, bool, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(debug, "Debug enabled or not");
+
+static int sabi_get_command(u8 command, struct sabi_retval *sretval)
+{
+	int retval = 0;
+	u16 port = readw(sabi + sabi_config->header_offsets.port);
+	u8 complete, iface_data;
+
+	mutex_lock(&sabi_mutex);
+
+	/* enable memory to be able to write to it */
+	outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
+
+	/* write out the command */
+	writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
+	writew(command, sabi_iface + SABI_IFACE_SUB);
+	writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
+	outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
+
+	/* write protect memory to make it safe */
+	outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+
+	/* see if the command actually succeeded */
+	complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
+	iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+	if (complete != 0xaa || iface_data == 0xff) {
+		pr_warn("SABI get command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
+		        command, complete, iface_data);
+		retval = -EINVAL;
+		goto exit;
+	}
+	/*
+	 * Save off the data into a structure so the caller use it.
+	 * Right now we only want the first 4 bytes,
+	 * There are commands that need more, but not for the ones we
+	 * currently care about.
+	 */
+	sretval->retval[0] = readb(sabi_iface + SABI_IFACE_DATA);
+	sretval->retval[1] = readb(sabi_iface + SABI_IFACE_DATA + 1);
+	sretval->retval[2] = readb(sabi_iface + SABI_IFACE_DATA + 2);
+	sretval->retval[3] = readb(sabi_iface + SABI_IFACE_DATA + 3);
+
+exit:
+	mutex_unlock(&sabi_mutex);
+	return retval;
+
+}
+
+static int sabi_set_command(u8 command, u8 data)
+{
+	int retval = 0;
+	u16 port = readw(sabi + sabi_config->header_offsets.port);
+	u8 complete, iface_data;
+
+	mutex_lock(&sabi_mutex);
+
+	/* enable memory to be able to write to it */
+	outb(readb(sabi + sabi_config->header_offsets.en_mem), port);
+
+	/* write out the command */
+	writew(sabi_config->main_function, sabi_iface + SABI_IFACE_MAIN);
+	writew(command, sabi_iface + SABI_IFACE_SUB);
+	writeb(0, sabi_iface + SABI_IFACE_COMPLETE);
+	writeb(data, sabi_iface + SABI_IFACE_DATA);
+	outb(readb(sabi + sabi_config->header_offsets.iface_func), port);
+
+	/* write protect memory to make it safe */
+	outb(readb(sabi + sabi_config->header_offsets.re_mem), port);
+
+	/* see if the command actually succeeded */
+	complete = readb(sabi_iface + SABI_IFACE_COMPLETE);
+	iface_data = readb(sabi_iface + SABI_IFACE_DATA);
+	if (complete != 0xaa || iface_data == 0xff) {
+		pr_warn("SABI set command 0x%02x failed with completion flag 0x%02x and data 0x%02x\n",
+		       command, complete, iface_data);
+		retval = -EINVAL;
+	}
+
+	mutex_unlock(&sabi_mutex);
+	return retval;
+}
+
+static void test_backlight(void)
+{
+	struct sabi_retval sretval;
+
+	sabi_get_command(sabi_config->commands.get_backlight, &sretval);
+	printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+
+	sabi_set_command(sabi_config->commands.set_backlight, 0);
+	printk(KERN_DEBUG "backlight should be off\n");
+
+	sabi_get_command(sabi_config->commands.get_backlight, &sretval);
+	printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+
+	msleep(1000);
+
+	sabi_set_command(sabi_config->commands.set_backlight, 1);
+	printk(KERN_DEBUG "backlight should be on\n");
+
+	sabi_get_command(sabi_config->commands.get_backlight, &sretval);
+	printk(KERN_DEBUG "backlight = 0x%02x\n", sretval.retval[0]);
+}
+
+static void test_wireless(void)
+{
+	struct sabi_retval sretval;
+
+	sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
+	printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+
+	sabi_set_command(sabi_config->commands.set_wireless_button, 0);
+	printk(KERN_DEBUG "wireless led should be off\n");
+
+	sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
+	printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+
+	msleep(1000);
+
+	sabi_set_command(sabi_config->commands.set_wireless_button, 1);
+	printk(KERN_DEBUG "wireless led should be on\n");
+
+	sabi_get_command(sabi_config->commands.get_wireless_button, &sretval);
+	printk(KERN_DEBUG "wireless led = 0x%02x\n", sretval.retval[0]);
+}
+
+static u8 read_brightness(void)
+{
+	struct sabi_retval sretval;
+	int user_brightness = 0;
+	int retval;
+
+	retval = sabi_get_command(sabi_config->commands.get_brightness,
+				  &sretval);
+	if (!retval) {
+		user_brightness = sretval.retval[0];
+		if (user_brightness != 0)
+			user_brightness -= sabi_config->min_brightness;
+	}
+	return user_brightness;
+}
+
+static void set_brightness(u8 user_brightness)
+{
+	u8 user_level = user_brightness - sabi_config->min_brightness;
+
+	sabi_set_command(sabi_config->commands.set_brightness, user_level);
+}
+
+static int get_brightness(struct backlight_device *bd)
+{
+	return (int)read_brightness();
+}
+
+static int update_status(struct backlight_device *bd)
+{
+	set_brightness(bd->props.brightness);
+
+	if (bd->props.power == FB_BLANK_UNBLANK)
+		sabi_set_command(sabi_config->commands.set_backlight, 1);
+	else
+		sabi_set_command(sabi_config->commands.set_backlight, 0);
+	return 0;
+}
+
+static const struct backlight_ops backlight_ops = {
+	.get_brightness	= get_brightness,
+	.update_status	= update_status,
+};
+
+static int rfkill_set(void *data, bool blocked)
+{
+	/* Do something with blocked...*/
+	/*
+	 * blocked == false is on
+	 * blocked == true is off
+	 */
+	if (blocked)
+		sabi_set_command(sabi_config->commands.set_wireless_button, 0);
+	else
+		sabi_set_command(sabi_config->commands.set_wireless_button, 1);
+
+	return 0;
+}
+
+static struct rfkill_ops rfkill_ops = {
+	.set_block = rfkill_set,
+};
+
+static int init_wireless(struct platform_device *sdev)
+{
+	int retval;
+
+	rfk = rfkill_alloc("samsung-wifi", &sdev->dev, RFKILL_TYPE_WLAN,
+			   &rfkill_ops, NULL);
+	if (!rfk)
+		return -ENOMEM;
+
+	retval = rfkill_register(rfk);
+	if (retval) {
+		rfkill_destroy(rfk);
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void destroy_wireless(void)
+{
+	rfkill_unregister(rfk);
+	rfkill_destroy(rfk);
+}
+
+static ssize_t get_performance_level(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct sabi_retval sretval;
+	int retval;
+	int i;
+
+	/* Read the state */
+	retval = sabi_get_command(sabi_config->commands.get_performance_level,
+				  &sretval);
+	if (retval)
+		return retval;
+
+	/* The logic is backwards, yeah, lots of fun... */
+	for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+		if (sretval.retval[0] == sabi_config->performance_levels[i].value)
+			return sprintf(buf, "%s\n", sabi_config->performance_levels[i].name);
+	}
+	return sprintf(buf, "%s\n", "unknown");
+}
+
+static ssize_t set_performance_level(struct device *dev,
+				struct device_attribute *attr, const char *buf,
+				size_t count)
+{
+	if (count >= 1) {
+		int i;
+		for (i = 0; sabi_config->performance_levels[i].name; ++i) {
+			const struct sabi_performance_level *level =
+				&sabi_config->performance_levels[i];
+			if (!strncasecmp(level->name, buf, strlen(level->name))) {
+				sabi_set_command(sabi_config->commands.set_performance_level,
+						 level->value);
+				break;
+			}
+		}
+		if (!sabi_config->performance_levels[i].name)
+			return -EINVAL;
+	}
+	return count;
+}
+static DEVICE_ATTR(performance_level, S_IWUSR | S_IRUGO,
+		   get_performance_level, set_performance_level);
+
+
+static int __init dmi_check_cb(const struct dmi_system_id *id)
+{
+	pr_info("found laptop model '%s'\n",
+		id->ident);
+	return 1;
+}
+
+static struct dmi_system_id __initdata samsung_dmi_table[] = {
+	{
+		.ident = "N128",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N128"),
+			DMI_MATCH(DMI_BOARD_NAME, "N128"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N130",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N130"),
+			DMI_MATCH(DMI_BOARD_NAME, "N130"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "X125",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X125"),
+			DMI_MATCH(DMI_BOARD_NAME, "X125"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "X120/X170",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X120/X170"),
+			DMI_MATCH(DMI_BOARD_NAME, "X120/X170"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "NC10",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "NC10"),
+			DMI_MATCH(DMI_BOARD_NAME, "NC10"),
+		},
+		.callback = dmi_check_cb,
+	},
+		{
+		.ident = "NP-Q45",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "SQ45S70S"),
+			DMI_MATCH(DMI_BOARD_NAME, "SQ45S70S"),
+		},
+		.callback = dmi_check_cb,
+		},
+	{
+		.ident = "X360",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "X360"),
+			DMI_MATCH(DMI_BOARD_NAME, "X360"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R410 Plus",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R410P"),
+			DMI_MATCH(DMI_BOARD_NAME, "R460"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R518",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R518"),
+			DMI_MATCH(DMI_BOARD_NAME, "R518"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R519/R719",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R519/R719"),
+			DMI_MATCH(DMI_BOARD_NAME, "R519/R719"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N150/N210/N220/N230",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N150/N210/N220/N230"),
+			DMI_MATCH(DMI_BOARD_NAME, "N150/N210/N220/N230"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N150P/N210P/N220P",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N150P/N210P/N220P"),
+			DMI_MATCH(DMI_BOARD_NAME, "N150P/N210P/N220P"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R530/R730",
+		.matches = {
+		      DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+		      DMI_MATCH(DMI_PRODUCT_NAME, "R530/R730"),
+		      DMI_MATCH(DMI_BOARD_NAME, "R530/R730"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "NF110/NF210/NF310",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "NF110/NF210/NF310"),
+			DMI_MATCH(DMI_BOARD_NAME, "NF110/NF210/NF310"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "N145P/N250P/N260P",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "N145P/N250P/N260P"),
+			DMI_MATCH(DMI_BOARD_NAME, "N145P/N250P/N260P"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "R70/R71",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR,
+					"SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "R70/R71"),
+			DMI_MATCH(DMI_BOARD_NAME, "R70/R71"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{
+		.ident = "P460",
+		.matches = {
+			DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+			DMI_MATCH(DMI_PRODUCT_NAME, "P460"),
+			DMI_MATCH(DMI_BOARD_NAME, "P460"),
+		},
+		.callback = dmi_check_cb,
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
+
+static int find_signature(void __iomem *memcheck, const char *testStr)
+{
+	int i = 0;
+	int loca;
+
+	for (loca = 0; loca < 0xffff; loca++) {
+		char temp = readb(memcheck + loca);
+
+		if (temp == testStr[i]) {
+			if (i == strlen(testStr)-1)
+				break;
+			++i;
+		} else {
+			i = 0;
+		}
+	}
+	return loca;
+}
+
+static int __init samsung_init(void)
+{
+	struct backlight_properties props;
+	struct sabi_retval sretval;
+	unsigned int ifaceP;
+	int i;
+	int loca;
+	int retval;
+
+	mutex_init(&sabi_mutex);
+
+	if (!force && !dmi_check_system(samsung_dmi_table))
+		return -ENODEV;
+
+	f0000_segment = ioremap_nocache(0xf0000, 0xffff);
+	if (!f0000_segment) {
+		pr_err("Can't map the segment at 0xf0000\n");
+		return -EINVAL;
+	}
+
+	/* Try to find one of the signatures in memory to find the header */
+	for (i = 0; sabi_configs[i].test_string != 0; ++i) {
+		sabi_config = &sabi_configs[i];
+		loca = find_signature(f0000_segment, sabi_config->test_string);
+		if (loca != 0xffff)
+			break;
+	}
+
+	if (loca == 0xffff) {
+		pr_err("This computer does not support SABI\n");
+		goto error_no_signature;
+	}
+
+	/* point to the SMI port Number */
+	loca += 1;
+	sabi = (f0000_segment + loca);
+
+	if (debug) {
+		printk(KERN_DEBUG "This computer supports SABI==%x\n",
+			loca + 0xf0000 - 6);
+		printk(KERN_DEBUG "SABI header:\n");
+		printk(KERN_DEBUG " SMI Port Number = 0x%04x\n",
+			readw(sabi + sabi_config->header_offsets.port));
+		printk(KERN_DEBUG " SMI Interface Function = 0x%02x\n",
+			readb(sabi + sabi_config->header_offsets.iface_func));
+		printk(KERN_DEBUG " SMI enable memory buffer = 0x%02x\n",
+			readb(sabi + sabi_config->header_offsets.en_mem));
+		printk(KERN_DEBUG " SMI restore memory buffer = 0x%02x\n",
+			readb(sabi + sabi_config->header_offsets.re_mem));
+		printk(KERN_DEBUG " SABI data offset = 0x%04x\n",
+			readw(sabi + sabi_config->header_offsets.data_offset));
+		printk(KERN_DEBUG " SABI data segment = 0x%04x\n",
+			readw(sabi + sabi_config->header_offsets.data_segment));
+	}
+
+	/* Get a pointer to the SABI Interface */
+	ifaceP = (readw(sabi + sabi_config->header_offsets.data_segment) & 0x0ffff) << 4;
+	ifaceP += readw(sabi + sabi_config->header_offsets.data_offset) & 0x0ffff;
+	sabi_iface = ioremap_nocache(ifaceP, 16);
+	if (!sabi_iface) {
+		pr_err("Can't remap %x\n", ifaceP);
+		goto exit;
+	}
+	if (debug) {
+		printk(KERN_DEBUG "ifaceP = 0x%08x\n", ifaceP);
+		printk(KERN_DEBUG "sabi_iface = %p\n", sabi_iface);
+
+		test_backlight();
+		test_wireless();
+
+		retval = sabi_get_command(sabi_config->commands.get_brightness,
+					  &sretval);
+		printk(KERN_DEBUG "brightness = 0x%02x\n", sretval.retval[0]);
+	}
+
+	/* Turn on "Linux" mode in the BIOS */
+	if (sabi_config->commands.set_linux != 0xff) {
+		retval = sabi_set_command(sabi_config->commands.set_linux,
+					  0x81);
+		if (retval) {
+			pr_warn("Linux mode was not set!\n");
+			goto error_no_platform;
+		}
+	}
+
+	/* knock up a platform device to hang stuff off of */
+	sdev = platform_device_register_simple("samsung", -1, NULL, 0);
+	if (IS_ERR(sdev))
+		goto error_no_platform;
+
+	/* create a backlight device to talk to this one */
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
+	props.max_brightness = sabi_config->max_brightness;
+	backlight_device = backlight_device_register("samsung", &sdev->dev,
+						     NULL, &backlight_ops,
+						     &props);
+	if (IS_ERR(backlight_device))
+		goto error_no_backlight;
+
+	backlight_device->props.brightness = read_brightness();
+	backlight_device->props.power = FB_BLANK_UNBLANK;
+	backlight_update_status(backlight_device);
+
+	retval = init_wireless(sdev);
+	if (retval)
+		goto error_no_rfk;
+
+	retval = device_create_file(&sdev->dev, &dev_attr_performance_level);
+	if (retval)
+		goto error_file_create;
+
+exit:
+	return 0;
+
+error_file_create:
+	destroy_wireless();
+
+error_no_rfk:
+	backlight_device_unregister(backlight_device);
+
+error_no_backlight:
+	platform_device_unregister(sdev);
+
+error_no_platform:
+	iounmap(sabi_iface);
+
+error_no_signature:
+	iounmap(f0000_segment);
+	return -EINVAL;
+}
+
+static void __exit samsung_exit(void)
+{
+	/* Turn off "Linux" mode in the BIOS */
+	if (sabi_config->commands.set_linux != 0xff)
+		sabi_set_command(sabi_config->commands.set_linux, 0x80);
+
+	device_remove_file(&sdev->dev, &dev_attr_performance_level);
+	backlight_device_unregister(backlight_device);
+	destroy_wireless();
+	iounmap(sabi_iface);
+	iounmap(f0000_segment);
+	platform_device_unregister(sdev);
+}
+
+module_init(samsung_init);
+module_exit(samsung_exit);
+
+MODULE_AUTHOR("Greg Kroah-Hartman <gregkh@suse.de>");
+MODULE_DESCRIPTION("Samsung Backlight driver");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/sony-laptop.c linux-libre-2.6.39-gnu/drivers/platform/x86/sony-laptop.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/sony-laptop.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/sony-laptop.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,8 +71,9 @@
 #endif
 
 #define DRV_PFX			"sony-laptop: "
-#define dprintk(msg...)		do {			\
-	if (debug) printk(KERN_WARNING DRV_PFX  msg);	\
+#define dprintk(msg...)		do {	\
+	if (debug)			\
+		pr_warn(DRV_PFX msg);	\
 } while (0)
 
 #define SONY_LAPTOP_DRIVER_VERSION	"0.6"
@@ -124,6 +125,21 @@
 		 "default is -1 (automatic)");
 #endif
 
+static int kbd_backlight;	/* = 1 */
+module_param(kbd_backlight, int, 0444);
+MODULE_PARM_DESC(kbd_backlight,
+		 "set this to 0 to disable keyboard backlight, "
+		 "1 to enable it (default: 0)");
+
+static int kbd_backlight_timeout;	/* = 0 */
+module_param(kbd_backlight_timeout, int, 0444);
+MODULE_PARM_DESC(kbd_backlight_timeout,
+		 "set this to 0 to set the default 10 seconds timeout, "
+		 "1 for 30 seconds, 2 for 60 seconds and 3 to disable timeout "
+		 "(default: 0)");
+
+static void sony_nc_kbd_backlight_resume(void);
+
 enum sony_nc_rfkill {
 	SONY_WIFI,
 	SONY_BLUETOOTH,
@@ -402,7 +418,7 @@
 	error = kfifo_alloc(&sony_laptop_input.fifo,
 			    SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
 	if (error) {
-		printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
+		pr_err(DRV_PFX "kfifo_alloc failed\n");
 		goto err_dec_users;
 	}
 
@@ -591,7 +607,7 @@
 	int value;		/* current setting */
 	int valid;		/* Has ever been set */
 	int debug;		/* active only in debug mode ? */
-	struct device_attribute devattr;	/* sysfs atribute */
+	struct device_attribute devattr;	/* sysfs attribute */
 };
 
 #define SNC_HANDLE_NAMES(_name, _values...) \
@@ -686,7 +702,7 @@
 		return 0;
 	}
 
-	printk(KERN_WARNING DRV_PFX "acpi_callreadfunc failed\n");
+	pr_warn(DRV_PFX "acpi_callreadfunc failed\n");
 
 	return -1;
 }
@@ -712,7 +728,7 @@
 	if (status == AE_OK) {
 		if (result != NULL) {
 			if (out_obj.type != ACPI_TYPE_INTEGER) {
-				printk(KERN_WARNING DRV_PFX "acpi_evaluate_object bad "
+				pr_warn(DRV_PFX "acpi_evaluate_object bad "
 				       "return type\n");
 				return -1;
 			}
@@ -721,34 +737,111 @@
 		return 0;
 	}
 
-	printk(KERN_WARNING DRV_PFX "acpi_evaluate_object failed\n");
+	pr_warn(DRV_PFX "acpi_evaluate_object failed\n");
 
 	return -1;
 }
 
-static int sony_find_snc_handle(int handle)
+struct sony_nc_handles {
+	u16 cap[0x10];
+	struct device_attribute devattr;
+};
+
+static struct sony_nc_handles *handles;
+
+static ssize_t sony_nc_handles_show(struct device *dev,
+		struct device_attribute *attr, char *buffer)
+{
+	ssize_t len = 0;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+		len += snprintf(buffer + len, PAGE_SIZE - len, "0x%.4x ",
+				handles->cap[i]);
+	}
+	len += snprintf(buffer + len, PAGE_SIZE - len, "\n");
+
+	return len;
+}
+
+static int sony_nc_handles_setup(struct platform_device *pd)
 {
 	int i;
 	int result;
 
-	for (i = 0x20; i < 0x30; i++) {
-		acpi_callsetfunc(sony_nc_acpi_handle, "SN00", i, &result);
-		if (result == handle)
-			return i-0x20;
+	handles = kzalloc(sizeof(*handles), GFP_KERNEL);
+	if (!handles)
+		return -ENOMEM;
+
+	for (i = 0; i < ARRAY_SIZE(handles->cap); i++) {
+		if (!acpi_callsetfunc(sony_nc_acpi_handle,
+					"SN00", i + 0x20, &result)) {
+			dprintk("caching handle 0x%.4x (offset: 0x%.2x)\n",
+					result, i);
+			handles->cap[i] = result;
+		}
+	}
+
+	if (debug) {
+		sysfs_attr_init(&handles->devattr.attr);
+		handles->devattr.attr.name = "handles";
+		handles->devattr.attr.mode = S_IRUGO;
+		handles->devattr.show = sony_nc_handles_show;
+
+		/* allow reading capabilities via sysfs */
+		if (device_create_file(&pd->dev, &handles->devattr)) {
+			kfree(handles);
+			handles = NULL;
+			return -1;
+		}
+	}
+
+	return 0;
+}
+
+static int sony_nc_handles_cleanup(struct platform_device *pd)
+{
+	if (handles) {
+		if (debug)
+			device_remove_file(&pd->dev, &handles->devattr);
+		kfree(handles);
+		handles = NULL;
 	}
+	return 0;
+}
+
+static int sony_find_snc_handle(int handle)
+{
+	int i;
+
+	/* not initialized yet, return early */
+	if (!handles)
+		return -1;
 
+	for (i = 0; i < 0x10; i++) {
+		if (handles->cap[i] == handle) {
+			dprintk("found handle 0x%.4x (offset: 0x%.2x)\n",
+					handle, i);
+			return i;
+		}
+	}
+	dprintk("handle 0x%.4x not found\n", handle);
 	return -1;
 }
 
 static int sony_call_snc_handle(int handle, int argument, int *result)
 {
+	int ret = 0;
 	int offset = sony_find_snc_handle(handle);
 
 	if (offset < 0)
 		return -1;
 
-	return acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
-				result);
+	ret = acpi_callsetfunc(sony_nc_acpi_handle, "SN07", offset | argument,
+			result);
+	dprintk("called SN07 with 0x%.4x (result: 0x%.4x)\n", offset | argument,
+			*result);
+	return ret;
 }
 
 /*
@@ -841,6 +934,14 @@
 /*
  * Backlight device
  */
+struct sony_backlight_props {
+	struct backlight_device *dev;
+	int			handle;
+	u8			offset;
+	u8			maxlvl;
+};
+struct sony_backlight_props sony_bl_props;
+
 static int sony_backlight_update_status(struct backlight_device *bd)
 {
 	return acpi_callsetfunc(sony_nc_acpi_handle, "SBRT",
@@ -857,11 +958,42 @@
 	return value - 1;
 }
 
-static struct backlight_device *sony_backlight_device;
+static int sony_nc_get_brightness_ng(struct backlight_device *bd)
+{
+	int result;
+	int *handle = (int *)bl_get_data(bd);
+	struct sony_backlight_props *sdev =
+		(struct sony_backlight_props *)bl_get_data(bd);
+
+	sony_call_snc_handle(sdev->handle, 0x0200, &result);
+
+	return (result & 0xff) - sdev->offset;
+}
+
+static int sony_nc_update_status_ng(struct backlight_device *bd)
+{
+	int value, result;
+	int *handle = (int *)bl_get_data(bd);
+	struct sony_backlight_props *sdev =
+		(struct sony_backlight_props *)bl_get_data(bd);
+
+	value = bd->props.brightness + sdev->offset;
+	if (sony_call_snc_handle(sdev->handle, 0x0100 | (value << 16), &result))
+		return -EIO;
+
+	return value;
+}
+
 static const struct backlight_ops sony_backlight_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
 	.update_status = sony_backlight_update_status,
 	.get_brightness = sony_backlight_get_brightness,
 };
+static const struct backlight_ops sony_backlight_ng_ops = {
+	.options = BL_CORE_SUSPENDRESUME,
+	.update_status = sony_nc_update_status_ng,
+	.get_brightness = sony_nc_get_brightness_ng,
+};
 
 /*
  * New SNC-only Vaios event mapping to driver known keys
@@ -972,7 +1104,7 @@
 				}
 
 				if (!key_event->data)
-					printk(KERN_INFO DRV_PFX
+					pr_info(DRV_PFX
 							"Unknown event: 0x%x 0x%x\n",
 							key_handle,
 							ev);
@@ -996,7 +1128,7 @@
 	struct acpi_device_info *info;
 
 	if (ACPI_SUCCESS(acpi_get_object_info(handle, &info))) {
-		printk(KERN_WARNING DRV_PFX "method: name: %4.4s, args %X\n",
+		pr_warn(DRV_PFX "method: name: %4.4s, args %X\n",
 			(char *)&info->name, info->param_count);
 
 		kfree(info);
@@ -1037,7 +1169,7 @@
 		ret = acpi_callsetfunc(sony_nc_acpi_handle, *item->acpiset,
 				       item->value, NULL);
 		if (ret < 0) {
-			printk("%s: %d\n", __func__, ret);
+			pr_err(DRV_PFX "%s: %d\n", __func__, ret);
 			break;
 		}
 	}
@@ -1054,14 +1186,12 @@
 		sony_nc_function_setup(device);
 	}
 
-	/* set the last requested brightness level */
-	if (sony_backlight_device &&
-			sony_backlight_update_status(sony_backlight_device) < 0)
-		printk(KERN_WARNING DRV_PFX "unable to restore brightness level\n");
-
 	/* re-read rfkill state */
 	sony_nc_rfkill_update();
 
+	/* restore kbd backlight states */
+	sony_nc_kbd_backlight_resume();
+
 	return 0;
 }
 
@@ -1206,12 +1336,12 @@
 
 	device_enum = (union acpi_object *) buffer.pointer;
 	if (!device_enum) {
-		pr_err("Invalid SN06 return object\n");
+		pr_err(DRV_PFX "No SN06 return object.");
 		goto out_no_enum;
 	}
 	if (device_enum->type != ACPI_TYPE_BUFFER) {
-		pr_err("Invalid SN06 return object type 0x%.2x\n",
-		       device_enum->type);
+		pr_err(DRV_PFX "Invalid SN06 return object 0x%.2x\n",
+				device_enum->type);
 		goto out_no_enum;
 	}
 
@@ -1245,6 +1375,306 @@
 	return;
 }
 
+/* Keyboard backlight feature */
+#define KBDBL_HANDLER	0x137
+#define KBDBL_PRESENT	0xB00
+#define	SET_MODE	0xC00
+#define SET_STATE	0xD00
+#define SET_TIMEOUT	0xE00
+
+struct kbd_backlight {
+	int mode;
+	int timeout;
+	struct device_attribute mode_attr;
+	struct device_attribute timeout_attr;
+};
+
+static struct kbd_backlight *kbdbl_handle;
+
+static ssize_t __sony_nc_kbd_backlight_mode_set(u8 value)
+{
+	int result;
+
+	if (value > 1)
+		return -EINVAL;
+
+	if (sony_call_snc_handle(KBDBL_HANDLER,
+				(value << 0x10) | SET_MODE, &result))
+		return -EIO;
+
+	/* Try to turn the light on/off immediately */
+	sony_call_snc_handle(KBDBL_HANDLER, (value << 0x10) | SET_STATE,
+			&result);
+
+	kbdbl_handle->mode = value;
+
+	return 0;
+}
+
+static ssize_t sony_nc_kbd_backlight_mode_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buffer, size_t count)
+{
+	int ret = 0;
+	unsigned long value;
+
+	if (count > 31)
+		return -EINVAL;
+
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
+	ret = __sony_nc_kbd_backlight_mode_set(value);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t sony_nc_kbd_backlight_mode_show(struct device *dev,
+		struct device_attribute *attr, char *buffer)
+{
+	ssize_t count = 0;
+	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->mode);
+	return count;
+}
+
+static int __sony_nc_kbd_backlight_timeout_set(u8 value)
+{
+	int result;
+
+	if (value > 3)
+		return -EINVAL;
+
+	if (sony_call_snc_handle(KBDBL_HANDLER,
+				(value << 0x10) | SET_TIMEOUT, &result))
+		return -EIO;
+
+	kbdbl_handle->timeout = value;
+
+	return 0;
+}
+
+static ssize_t sony_nc_kbd_backlight_timeout_store(struct device *dev,
+		struct device_attribute *attr,
+		const char *buffer, size_t count)
+{
+	int ret = 0;
+	unsigned long value;
+
+	if (count > 31)
+		return -EINVAL;
+
+	if (strict_strtoul(buffer, 10, &value))
+		return -EINVAL;
+
+	ret = __sony_nc_kbd_backlight_timeout_set(value);
+	if (ret < 0)
+		return ret;
+
+	return count;
+}
+
+static ssize_t sony_nc_kbd_backlight_timeout_show(struct device *dev,
+		struct device_attribute *attr, char *buffer)
+{
+	ssize_t count = 0;
+	count = snprintf(buffer, PAGE_SIZE, "%d\n", kbdbl_handle->timeout);
+	return count;
+}
+
+static int sony_nc_kbd_backlight_setup(struct platform_device *pd)
+{
+	int result;
+
+	if (sony_call_snc_handle(KBDBL_HANDLER, KBDBL_PRESENT, &result))
+		return 0;
+	if (!(result & 0x02))
+		return 0;
+
+	kbdbl_handle = kzalloc(sizeof(*kbdbl_handle), GFP_KERNEL);
+	if (!kbdbl_handle)
+		return -ENOMEM;
+
+	sysfs_attr_init(&kbdbl_handle->mode_attr.attr);
+	kbdbl_handle->mode_attr.attr.name = "kbd_backlight";
+	kbdbl_handle->mode_attr.attr.mode = S_IRUGO | S_IWUSR;
+	kbdbl_handle->mode_attr.show = sony_nc_kbd_backlight_mode_show;
+	kbdbl_handle->mode_attr.store = sony_nc_kbd_backlight_mode_store;
+
+	sysfs_attr_init(&kbdbl_handle->timeout_attr.attr);
+	kbdbl_handle->timeout_attr.attr.name = "kbd_backlight_timeout";
+	kbdbl_handle->timeout_attr.attr.mode = S_IRUGO | S_IWUSR;
+	kbdbl_handle->timeout_attr.show = sony_nc_kbd_backlight_timeout_show;
+	kbdbl_handle->timeout_attr.store = sony_nc_kbd_backlight_timeout_store;
+
+	if (device_create_file(&pd->dev, &kbdbl_handle->mode_attr))
+		goto outkzalloc;
+
+	if (device_create_file(&pd->dev, &kbdbl_handle->timeout_attr))
+		goto outmode;
+
+	__sony_nc_kbd_backlight_mode_set(kbd_backlight);
+	__sony_nc_kbd_backlight_timeout_set(kbd_backlight_timeout);
+
+	return 0;
+
+outmode:
+	device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
+outkzalloc:
+	kfree(kbdbl_handle);
+	kbdbl_handle = NULL;
+	return -1;
+}
+
+static int sony_nc_kbd_backlight_cleanup(struct platform_device *pd)
+{
+	if (kbdbl_handle) {
+		int result;
+
+		device_remove_file(&pd->dev, &kbdbl_handle->mode_attr);
+		device_remove_file(&pd->dev, &kbdbl_handle->timeout_attr);
+
+		/* restore the default hw behaviour */
+		sony_call_snc_handle(KBDBL_HANDLER, 0x1000 | SET_MODE, &result);
+		sony_call_snc_handle(KBDBL_HANDLER, SET_TIMEOUT, &result);
+
+		kfree(kbdbl_handle);
+	}
+	return 0;
+}
+
+static void sony_nc_kbd_backlight_resume(void)
+{
+	int ignore = 0;
+
+	if (!kbdbl_handle)
+		return;
+
+	if (kbdbl_handle->mode == 0)
+		sony_call_snc_handle(KBDBL_HANDLER, SET_MODE, &ignore);
+
+	if (kbdbl_handle->timeout != 0)
+		sony_call_snc_handle(KBDBL_HANDLER,
+				(kbdbl_handle->timeout << 0x10) | SET_TIMEOUT,
+				&ignore);
+}
+
+static void sony_nc_backlight_ng_read_limits(int handle,
+		struct sony_backlight_props *props)
+{
+	int offset;
+	acpi_status status;
+	u8 brlvl, i;
+	u8 min = 0xff, max = 0x00;
+	struct acpi_object_list params;
+	union acpi_object in_obj;
+	union acpi_object *lvl_enum;
+	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+
+	props->handle = handle;
+	props->offset = 0;
+	props->maxlvl = 0xff;
+
+	offset = sony_find_snc_handle(handle);
+	if (offset < 0)
+		return;
+
+	/* try to read the boundaries from ACPI tables, if we fail the above
+	 * defaults should be reasonable
+	 */
+	params.count = 1;
+	params.pointer = &in_obj;
+	in_obj.type = ACPI_TYPE_INTEGER;
+	in_obj.integer.value = offset;
+	status = acpi_evaluate_object(sony_nc_acpi_handle, "SN06", &params,
+			&buffer);
+	if (ACPI_FAILURE(status))
+		return;
+
+	lvl_enum = (union acpi_object *) buffer.pointer;
+	if (!lvl_enum) {
+		pr_err("No SN06 return object.");
+		return;
+	}
+	if (lvl_enum->type != ACPI_TYPE_BUFFER) {
+		pr_err("Invalid SN06 return object 0x%.2x\n",
+		       lvl_enum->type);
+		goto out_invalid;
+	}
+
+	/* the buffer lists brightness levels available, brightness levels are
+	 * from 0 to 8 in the array, other values are used by ALS control.
+	 */
+	for (i = 0; i < 9 && i < lvl_enum->buffer.length; i++) {
+
+		brlvl = *(lvl_enum->buffer.pointer + i);
+		dprintk("Brightness level: %d\n", brlvl);
+
+		if (!brlvl)
+			break;
+
+		if (brlvl > max)
+			max = brlvl;
+		if (brlvl < min)
+			min = brlvl;
+	}
+	props->offset = min;
+	props->maxlvl = max;
+	dprintk("Brightness levels: min=%d max=%d\n", props->offset,
+			props->maxlvl);
+
+out_invalid:
+	kfree(buffer.pointer);
+	return;
+}
+
+static void sony_nc_backlight_setup(void)
+{
+	acpi_handle unused;
+	int max_brightness = 0;
+	const struct backlight_ops *ops = NULL;
+	struct backlight_properties props;
+
+	if (sony_find_snc_handle(0x12f) != -1) {
+		ops = &sony_backlight_ng_ops;
+		sony_nc_backlight_ng_read_limits(0x12f, &sony_bl_props);
+		max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
+
+	} else if (sony_find_snc_handle(0x137) != -1) {
+		ops = &sony_backlight_ng_ops;
+		sony_nc_backlight_ng_read_limits(0x137, &sony_bl_props);
+		max_brightness = sony_bl_props.maxlvl - sony_bl_props.offset;
+
+	} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
+						&unused))) {
+		ops = &sony_backlight_ops;
+		max_brightness = SONY_MAX_BRIGHTNESS - 1;
+
+	} else
+		return;
+
+	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
+	props.max_brightness = max_brightness;
+	sony_bl_props.dev = backlight_device_register("sony", NULL,
+						      &sony_bl_props,
+						      ops, &props);
+
+	if (IS_ERR(sony_bl_props.dev)) {
+		pr_warn(DRV_PFX "unable to register backlight device\n");
+		sony_bl_props.dev = NULL;
+	} else
+		sony_bl_props.dev->props.brightness =
+			ops->get_brightness(sony_bl_props.dev);
+}
+
+static void sony_nc_backlight_cleanup(void)
+{
+	if (sony_bl_props.dev)
+		backlight_device_unregister(sony_bl_props.dev);
+}
+
 static int sony_nc_add(struct acpi_device *device)
 {
 	acpi_status status;
@@ -1252,8 +1682,8 @@
 	acpi_handle handle;
 	struct sony_nc_value *item;
 
-	printk(KERN_INFO DRV_PFX "%s v%s.\n",
-		SONY_NC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
+	pr_info(DRV_PFX "%s v%s.\n", SONY_NC_DRIVER_NAME,
+			SONY_LAPTOP_DRIVER_VERSION);
 
 	sony_nc_acpi_device = device;
 	strcpy(acpi_device_class(device), "sony/hotkey");
@@ -1269,13 +1699,18 @@
 		goto outwalk;
 	}
 
+	result = sony_pf_add();
+	if (result)
+		goto outpresent;
+
 	if (debug) {
-		status = acpi_walk_namespace(ACPI_TYPE_METHOD, sony_nc_acpi_handle,
-					     1, sony_walk_callback, NULL, NULL, NULL);
+		status = acpi_walk_namespace(ACPI_TYPE_METHOD,
+				sony_nc_acpi_handle, 1, sony_walk_callback,
+				NULL, NULL, NULL);
 		if (ACPI_FAILURE(status)) {
-			printk(KERN_WARNING DRV_PFX "unable to walk acpi resources\n");
+			pr_warn(DRV_PFX "unable to walk acpi resources\n");
 			result = -ENODEV;
-			goto outwalk;
+			goto outpresent;
 		}
 	}
 
@@ -1288,6 +1723,12 @@
 	if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "SN00",
 					 &handle))) {
 		dprintk("Doing SNC setup\n");
+		result = sony_nc_handles_setup(sony_pf_device);
+		if (result)
+			goto outpresent;
+		result = sony_nc_kbd_backlight_setup(sony_pf_device);
+		if (result)
+			goto outsnc;
 		sony_nc_function_setup(device);
 		sony_nc_rfkill_setup(device);
 	}
@@ -1295,39 +1736,17 @@
 	/* setup input devices and helper fifo */
 	result = sony_laptop_setup_input(device);
 	if (result) {
-		printk(KERN_ERR DRV_PFX
-				"Unable to create input devices.\n");
-		goto outwalk;
+		pr_err(DRV_PFX "Unable to create input devices.\n");
+		goto outkbdbacklight;
 	}
 
 	if (acpi_video_backlight_support()) {
-		printk(KERN_INFO DRV_PFX "brightness ignored, must be "
+		pr_info(DRV_PFX "brightness ignored, must be "
 		       "controlled by ACPI video driver\n");
-	} else if (ACPI_SUCCESS(acpi_get_handle(sony_nc_acpi_handle, "GBRT",
-						&handle))) {
-							struct backlight_properties props;
-		memset(&props, 0, sizeof(struct backlight_properties));
-		props.max_brightness = SONY_MAX_BRIGHTNESS - 1;
-		sony_backlight_device = backlight_device_register("sony", NULL,
-								  NULL,
-								  &sony_backlight_ops,
-								  &props);
-
-		if (IS_ERR(sony_backlight_device)) {
-			printk(KERN_WARNING DRV_PFX "unable to register backlight device\n");
-			sony_backlight_device = NULL;
-		} else {
-			sony_backlight_device->props.brightness =
-			    sony_backlight_get_brightness
-			    (sony_backlight_device);
-		}
-
+	} else {
+		sony_nc_backlight_setup();
 	}
 
-	result = sony_pf_add();
-	if (result)
-		goto outbacklight;
-
 	/* create sony_pf sysfs attributes related to the SNC device */
 	for (item = sony_nc_values; item->name; ++item) {
 
@@ -1373,14 +1792,19 @@
 	for (item = sony_nc_values; item->name; ++item) {
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
 	}
-	sony_pf_remove();
-
-      outbacklight:
-	if (sony_backlight_device)
-		backlight_device_unregister(sony_backlight_device);
+	sony_nc_backlight_cleanup();
 
 	sony_laptop_remove_input();
 
+      outkbdbacklight:
+	sony_nc_kbd_backlight_cleanup(sony_pf_device);
+
+      outsnc:
+	sony_nc_handles_cleanup(sony_pf_device);
+
+      outpresent:
+	sony_pf_remove();
+
       outwalk:
 	sony_nc_rfkill_cleanup();
 	return result;
@@ -1390,8 +1814,7 @@
 {
 	struct sony_nc_value *item;
 
-	if (sony_backlight_device)
-		backlight_device_unregister(sony_backlight_device);
+	sony_nc_backlight_cleanup();
 
 	sony_nc_acpi_device = NULL;
 
@@ -1399,6 +1822,8 @@
 		device_remove_file(&sony_pf_device->dev, &item->devattr);
 	}
 
+	sony_nc_kbd_backlight_cleanup(sony_pf_device);
+	sony_nc_handles_cleanup(sony_pf_device);
 	sony_pf_remove();
 	sony_laptop_remove_input();
 	sony_nc_rfkill_cleanup();
@@ -1437,7 +1862,6 @@
 #define SONYPI_DEVICE_TYPE1	0x00000001
 #define SONYPI_DEVICE_TYPE2	0x00000002
 #define SONYPI_DEVICE_TYPE3	0x00000004
-#define SONYPI_DEVICE_TYPE4	0x00000008
 
 #define SONYPI_TYPE1_OFFSET	0x04
 #define SONYPI_TYPE2_OFFSET	0x12
@@ -1583,8 +2007,8 @@
 
 /* The set of possible wireless events */
 static struct sonypi_event sonypi_wlessev[] = {
-	{ 0x59, SONYPI_EVENT_WIRELESS_ON },
-	{ 0x5a, SONYPI_EVENT_WIRELESS_OFF },
+	{ 0x59, SONYPI_EVENT_IGNORE },
+	{ 0x5a, SONYPI_EVENT_IGNORE },
 	{ 0, 0 }
 };
 
@@ -1841,7 +2265,7 @@
 	if (pcidev)
 		pci_dev_put(pcidev);
 
-	printk(KERN_INFO DRV_PFX "detected Type%d model\n",
+	pr_info(DRV_PFX "detected Type%d model\n",
 			dev->model == SONYPI_DEVICE_TYPE1 ? 1 :
 			dev->model == SONYPI_DEVICE_TYPE2 ? 2 : 3);
 }
@@ -1889,7 +2313,7 @@
 static int __sony_pic_camera_off(void)
 {
 	if (!camera) {
-		printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
+		pr_warn(DRV_PFX "camera control not enabled\n");
 		return -ENODEV;
 	}
 
@@ -1909,7 +2333,7 @@
 	int i, j, x;
 
 	if (!camera) {
-		printk(KERN_WARNING DRV_PFX "camera control not enabled\n");
+		pr_warn(DRV_PFX "camera control not enabled\n");
 		return -ENODEV;
 	}
 
@@ -1932,7 +2356,7 @@
 	}
 
 	if (j == 0) {
-		printk(KERN_WARNING DRV_PFX "failed to power on camera\n");
+		pr_warn(DRV_PFX "failed to power on camera\n");
 		return -ENODEV;
 	}
 
@@ -1988,7 +2412,7 @@
 				ITERATIONS_SHORT);
 		break;
 	default:
-		printk(KERN_ERR DRV_PFX "sony_pic_camera_command invalid: %d\n",
+		pr_err(DRV_PFX "sony_pic_camera_command invalid: %d\n",
 		       command);
 		break;
 	}
@@ -2246,7 +2670,7 @@
 	mutex_lock(&spic_dev.lock);
 	switch (cmd) {
 	case SONYPI_IOCGBRT:
-		if (sony_backlight_device == NULL) {
+		if (sony_bl_props.dev == NULL) {
 			ret = -EIO;
 			break;
 		}
@@ -2259,7 +2683,7 @@
 				ret = -EFAULT;
 		break;
 	case SONYPI_IOCSBRT:
-		if (sony_backlight_device == NULL) {
+		if (sony_bl_props.dev == NULL) {
 			ret = -EIO;
 			break;
 		}
@@ -2273,8 +2697,8 @@
 			break;
 		}
 		/* sync the backlight device status */
-		sony_backlight_device->props.brightness =
-		    sony_backlight_get_brightness(sony_backlight_device);
+		sony_bl_props.dev->props.brightness =
+		    sony_backlight_get_brightness(sony_bl_props.dev);
 		break;
 	case SONYPI_IOCGBAT1CAP:
 		if (ec_read16(SONYPI_BAT1_FULL, &val16)) {
@@ -2395,7 +2819,7 @@
 	error =
 	 kfifo_alloc(&sonypi_compat.fifo, SONY_LAPTOP_BUF_SIZE, GFP_KERNEL);
 	if (error) {
-		printk(KERN_ERR DRV_PFX "kfifo_alloc failed\n");
+		pr_err(DRV_PFX "kfifo_alloc failed\n");
 		return error;
 	}
 
@@ -2405,11 +2829,11 @@
 		sonypi_misc_device.minor = minor;
 	error = misc_register(&sonypi_misc_device);
 	if (error) {
-		printk(KERN_ERR DRV_PFX "misc_register failed\n");
+		pr_err(DRV_PFX "misc_register failed\n");
 		goto err_free_kfifo;
 	}
 	if (minor == -1)
-		printk(KERN_INFO DRV_PFX "device allocated minor is %d\n",
+		pr_info(DRV_PFX "device allocated minor is %d\n",
 		       sonypi_misc_device.minor);
 
 	return 0;
@@ -2469,8 +2893,7 @@
 			}
 			for (i = 0; i < p->interrupt_count; i++) {
 				if (!p->interrupts[i]) {
-					printk(KERN_WARNING DRV_PFX
-							"Invalid IRQ %d\n",
+					pr_warn(DRV_PFX "Invalid IRQ %d\n",
 							p->interrupts[i]);
 					continue;
 				}
@@ -2509,7 +2932,7 @@
 						ioport->io2.address_length);
 			}
 			else {
-				printk(KERN_ERR DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
+				pr_err(DRV_PFX "Unknown SPIC Type, more than 2 IO Ports\n");
 				return AE_ERROR;
 			}
 			return AE_OK;
@@ -2537,7 +2960,7 @@
 	dprintk("Evaluating _STA\n");
 	result = acpi_bus_get_status(device);
 	if (result) {
-		printk(KERN_WARNING DRV_PFX "Unable to read status\n");
+		pr_warn(DRV_PFX "Unable to read status\n");
 		goto end;
 	}
 
@@ -2553,8 +2976,7 @@
 	status = acpi_walk_resources(device->handle, METHOD_NAME__PRS,
 			sony_pic_read_possible_resource, &spic_dev);
 	if (ACPI_FAILURE(status)) {
-		printk(KERN_WARNING DRV_PFX
-				"Failure evaluating %s\n",
+		pr_warn(DRV_PFX "Failure evaluating %s\n",
 				METHOD_NAME__PRS);
 		result = -ENODEV;
 	}
@@ -2668,7 +3090,7 @@
 
 	/* check for total failure */
 	if (ACPI_FAILURE(status)) {
-		printk(KERN_ERR DRV_PFX "Error evaluating _SRS\n");
+		pr_err(DRV_PFX "Error evaluating _SRS\n");
 		result = -ENODEV;
 		goto end;
 	}
@@ -2724,6 +3146,9 @@
 			if (ev == dev->event_types[i].events[j].data) {
 				device_event =
 					dev->event_types[i].events[j].event;
+				/* some events may require ignoring */
+				if (!device_event)
+					return IRQ_HANDLED;
 				goto found;
 			}
 		}
@@ -2743,7 +3168,6 @@
 	sony_laptop_report_input_event(device_event);
 	acpi_bus_generate_proc_event(dev->acpi_dev, 1, device_event);
 	sonypi_compat_report_event(device_event);
-
 	return IRQ_HANDLED;
 }
 
@@ -2758,7 +3182,7 @@
 	struct sony_pic_irq *irq, *tmp_irq;
 
 	if (sony_pic_disable(device)) {
-		printk(KERN_ERR DRV_PFX "Couldn't disable device.\n");
+		pr_err(DRV_PFX "Couldn't disable device.\n");
 		return -ENXIO;
 	}
 
@@ -2798,8 +3222,8 @@
 	struct sony_pic_ioport *io, *tmp_io;
 	struct sony_pic_irq *irq, *tmp_irq;
 
-	printk(KERN_INFO DRV_PFX "%s v%s.\n",
-		SONY_PIC_DRIVER_NAME, SONY_LAPTOP_DRIVER_VERSION);
+	pr_info(DRV_PFX "%s v%s.\n", SONY_PIC_DRIVER_NAME,
+			SONY_LAPTOP_DRIVER_VERSION);
 
 	spic_dev.acpi_dev = device;
 	strcpy(acpi_device_class(device), "sony/hotkey");
@@ -2809,16 +3233,14 @@
 	/* read _PRS resources */
 	result = sony_pic_possible_resources(device);
 	if (result) {
-		printk(KERN_ERR DRV_PFX
-				"Unable to read possible resources.\n");
+		pr_err(DRV_PFX "Unable to read possible resources.\n");
 		goto err_free_resources;
 	}
 
 	/* setup input devices and helper fifo */
 	result = sony_laptop_setup_input(device);
 	if (result) {
-		printk(KERN_ERR DRV_PFX
-				"Unable to create input devices.\n");
+		pr_err(DRV_PFX "Unable to create input devices.\n");
 		goto err_free_resources;
 	}
 
@@ -2828,7 +3250,7 @@
 	/* request io port */
 	list_for_each_entry_reverse(io, &spic_dev.ioports, list) {
 		if (request_region(io->io1.minimum, io->io1.address_length,
-					"Sony Programable I/O Device")) {
+					"Sony Programmable I/O Device")) {
 			dprintk("I/O port1: 0x%.4x (0x%.4x) + 0x%.2x\n",
 					io->io1.minimum, io->io1.maximum,
 					io->io1.address_length);
@@ -2836,7 +3258,7 @@
 			if (io->io2.minimum) {
 				if (request_region(io->io2.minimum,
 						io->io2.address_length,
-						"Sony Programable I/O Device")) {
+						"Sony Programmable I/O Device")) {
 					dprintk("I/O port2: 0x%.4x (0x%.4x) + 0x%.2x\n",
 							io->io2.minimum, io->io2.maximum,
 							io->io2.address_length);
@@ -2859,7 +3281,7 @@
 		}
 	}
 	if (!spic_dev.cur_ioport) {
-		printk(KERN_ERR DRV_PFX "Failed to request_region.\n");
+		pr_err(DRV_PFX "Failed to request_region.\n");
 		result = -ENODEV;
 		goto err_remove_compat;
 	}
@@ -2879,7 +3301,7 @@
 		}
 	}
 	if (!spic_dev.cur_irq) {
-		printk(KERN_ERR DRV_PFX "Failed to request_irq.\n");
+		pr_err(DRV_PFX "Failed to request_irq.\n");
 		result = -ENODEV;
 		goto err_release_region;
 	}
@@ -2887,7 +3309,7 @@
 	/* set resource status _SRS */
 	result = sony_pic_enable(device, spic_dev.cur_ioport, spic_dev.cur_irq);
 	if (result) {
-		printk(KERN_ERR DRV_PFX "Couldn't enable device.\n");
+		pr_err(DRV_PFX "Couldn't enable device.\n");
 		goto err_free_irq;
 	}
 
@@ -2996,8 +3418,7 @@
 	if (!no_spic && dmi_check_system(sonypi_dmi_table)) {
 		result = acpi_bus_register_driver(&sony_pic_driver);
 		if (result) {
-			printk(KERN_ERR DRV_PFX
-					"Unable to register SPIC driver.");
+			pr_err(DRV_PFX "Unable to register SPIC driver.");
 			goto out;
 		}
 		spic_drv_registered = 1;
@@ -3005,7 +3426,7 @@
 
 	result = acpi_bus_register_driver(&sony_nc_driver);
 	if (result) {
-		printk(KERN_ERR DRV_PFX "Unable to register SNC driver.");
+		pr_err(DRV_PFX "Unable to register SNC driver.");
 		goto out_unregister_pic;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/thinkpad_acpi.c linux-libre-2.6.39-gnu/drivers/platform/x86/thinkpad_acpi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/thinkpad_acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/thinkpad_acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -128,7 +128,8 @@
 };
 
 /* ACPI HIDs */
-#define TPACPI_ACPI_HKEY_HID		"IBM0068"
+#define TPACPI_ACPI_IBM_HKEY_HID	"IBM0068"
+#define TPACPI_ACPI_LENOVO_HKEY_HID	"LEN0068"
 #define TPACPI_ACPI_EC_HID		"PNP0C09"
 
 /* Input IDs */
@@ -2407,7 +2408,7 @@
 	 * This code is supposed to duplicate the IBM firmware behaviour:
 	 * - Pressing MUTE issues mute hotkey message, even when already mute
 	 * - Pressing Volume up/down issues volume up/down hotkey messages,
-	 *   even when already at maximum or minumum volume
+	 *   even when already at maximum or minimum volume
 	 * - The act of unmuting issues volume up/down notification,
 	 *   depending which key was used to unmute
 	 *
@@ -2990,7 +2991,7 @@
 	 * rfkill input events, or we will race the rfkill core input
 	 * handler.
 	 *
-	 * tpacpi_inputdev_send_mutex works as a syncronization point
+	 * tpacpi_inputdev_send_mutex works as a synchronization point
 	 * for the above.
 	 *
 	 * We optimize to avoid numerous calls to hotkey_get_wlsw.
@@ -3879,7 +3880,8 @@
 }
 
 static const struct acpi_device_id ibm_htk_device_ids[] = {
-	{TPACPI_ACPI_HKEY_HID, 0},
+	{TPACPI_ACPI_IBM_HKEY_HID, 0},
+	{TPACPI_ACPI_LENOVO_HKEY_HID, 0},
 	{"", 0},
 };
 
@@ -6307,6 +6309,7 @@
 		return 1;
 
 	memset(&props, 0, sizeof(struct backlight_properties));
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = bright_maxlvl;
 	props.brightness = b & TP_EC_BACKLIGHT_LVLMSK;
 	ibm_backlight_device = backlight_device_register(TPACPI_BACKLIGHT_DEV_NAME,
@@ -8617,8 +8620,7 @@
 		tpacpi_is_fw_digit(s[1]) &&
 		s[2] == t && s[3] == 'T' &&
 		tpacpi_is_fw_digit(s[4]) &&
-		tpacpi_is_fw_digit(s[5]) &&
-		s[6] == 'W' && s[7] == 'W';
+		tpacpi_is_fw_digit(s[5]);
 }
 
 /* returns 0 - probe ok, or < 0 - probe error.
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/toshiba_acpi.c linux-libre-2.6.39-gnu/drivers/platform/x86/toshiba_acpi.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/toshiba_acpi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/toshiba_acpi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1018,6 +1018,7 @@
 		create_toshiba_proc_entries();
 	}
 
+	props.type = BACKLIGHT_PLATFORM;
 	props.max_brightness = HCI_LCD_BRIGHTNESS_LEVELS - 1;
 	toshiba_backlight_device = backlight_device_register("toshiba",
 							     &toshiba_acpi.p_dev->dev,
diff -druN linux-libre-2.6.38-gnu/drivers/platform/x86/xo15-ebook.c linux-libre-2.6.39-gnu/drivers/platform/x86/xo15-ebook.c
--- linux-libre-2.6.38-gnu/drivers/platform/x86/xo15-ebook.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/platform/x86/xo15-ebook.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,180 @@
+/*
+ *  OLPC XO-1.5 ebook switch driver
+ *  (based on generic ACPI button driver)
+ *
+ *  Copyright (C) 2009 Paul Fox <pgf@laptop.org>
+ *  Copyright (C) 2010 One Laptop per Child
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the 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/init.h>
+#include <linux/types.h>
+#include <linux/input.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+#define MODULE_NAME "xo15-ebook"
+#define PREFIX MODULE_NAME ": "
+
+#define XO15_EBOOK_CLASS		MODULE_NAME
+#define XO15_EBOOK_TYPE_UNKNOWN	0x00
+#define XO15_EBOOK_NOTIFY_STATUS	0x80
+
+#define XO15_EBOOK_SUBCLASS		"ebook"
+#define XO15_EBOOK_HID			"XO15EBK"
+#define XO15_EBOOK_DEVICE_NAME		"EBook Switch"
+
+ACPI_MODULE_NAME(MODULE_NAME);
+
+MODULE_DESCRIPTION("OLPC XO-1.5 ebook switch driver");
+MODULE_LICENSE("GPL");
+
+static const struct acpi_device_id ebook_device_ids[] = {
+	{ XO15_EBOOK_HID, 0 },
+	{ "", 0 },
+};
+MODULE_DEVICE_TABLE(acpi, ebook_device_ids);
+
+struct ebook_switch {
+	struct input_dev *input;
+	char phys[32];			/* for input device */
+};
+
+static int ebook_send_state(struct acpi_device *device)
+{
+	struct ebook_switch *button = acpi_driver_data(device);
+	unsigned long long state;
+	acpi_status status;
+
+	status = acpi_evaluate_integer(device->handle, "EBK", NULL, &state);
+	if (ACPI_FAILURE(status))
+		return -EIO;
+
+	/* input layer checks if event is redundant */
+	input_report_switch(button->input, SW_TABLET_MODE, !state);
+	input_sync(button->input);
+	return 0;
+}
+
+static void ebook_switch_notify(struct acpi_device *device, u32 event)
+{
+	switch (event) {
+	case ACPI_FIXED_HARDWARE_EVENT:
+	case XO15_EBOOK_NOTIFY_STATUS:
+		ebook_send_state(device);
+		break;
+	default:
+		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
+				  "Unsupported event [0x%x]\n", event));
+		break;
+	}
+}
+
+static int ebook_switch_resume(struct acpi_device *device)
+{
+	return ebook_send_state(device);
+}
+
+static int ebook_switch_add(struct acpi_device *device)
+{
+	struct ebook_switch *button;
+	struct input_dev *input;
+	const char *hid = acpi_device_hid(device);
+	char *name, *class;
+	int error;
+
+	button = kzalloc(sizeof(struct ebook_switch), GFP_KERNEL);
+	if (!button)
+		return -ENOMEM;
+
+	device->driver_data = button;
+
+	button->input = input = input_allocate_device();
+	if (!input) {
+		error = -ENOMEM;
+		goto err_free_button;
+	}
+
+	name = acpi_device_name(device);
+	class = acpi_device_class(device);
+
+	if (strcmp(hid, XO15_EBOOK_HID)) {
+		printk(KERN_ERR PREFIX "Unsupported hid [%s]\n", hid);
+		error = -ENODEV;
+		goto err_free_input;
+	}
+
+	strcpy(name, XO15_EBOOK_DEVICE_NAME);
+	sprintf(class, "%s/%s", XO15_EBOOK_CLASS, XO15_EBOOK_SUBCLASS);
+
+	snprintf(button->phys, sizeof(button->phys), "%s/button/input0", hid);
+
+	input->name = name;
+	input->phys = button->phys;
+	input->id.bustype = BUS_HOST;
+	input->dev.parent = &device->dev;
+
+	input->evbit[0] = BIT_MASK(EV_SW);
+	set_bit(SW_TABLET_MODE, input->swbit);
+
+	error = input_register_device(input);
+	if (error)
+		goto err_free_input;
+
+	ebook_send_state(device);
+
+	if (device->wakeup.flags.valid) {
+		/* Button's GPE is run-wake GPE */
+		acpi_enable_gpe(device->wakeup.gpe_device,
+				device->wakeup.gpe_number);
+		device_set_wakeup_enable(&device->dev, true);
+	}
+
+	return 0;
+
+ err_free_input:
+	input_free_device(input);
+ err_free_button:
+	kfree(button);
+	return error;
+}
+
+static int ebook_switch_remove(struct acpi_device *device, int type)
+{
+	struct ebook_switch *button = acpi_driver_data(device);
+
+	input_unregister_device(button->input);
+	kfree(button);
+	return 0;
+}
+
+static struct acpi_driver xo15_ebook_driver = {
+	.name = MODULE_NAME,
+	.class = XO15_EBOOK_CLASS,
+	.ids = ebook_device_ids,
+	.ops = {
+		.add = ebook_switch_add,
+		.resume = ebook_switch_resume,
+		.remove = ebook_switch_remove,
+		.notify = ebook_switch_notify,
+	},
+};
+
+static int __init xo15_ebook_init(void)
+{
+	return acpi_bus_register_driver(&xo15_ebook_driver);
+}
+
+static void __exit xo15_ebook_exit(void)
+{
+	acpi_bus_unregister_driver(&xo15_ebook_driver);
+}
+
+module_init(xo15_ebook_init);
+module_exit(xo15_ebook_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/pnp/base.h linux-libre-2.6.39-gnu/drivers/pnp/base.h
--- linux-libre-2.6.38-gnu/drivers/pnp/base.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pnp/base.h	2011-05-19 00:06:34.000000000 -0400
@@ -142,7 +142,9 @@
 int pnp_check_port(struct pnp_dev *dev, struct resource *res);
 int pnp_check_mem(struct pnp_dev *dev, struct resource *res);
 int pnp_check_irq(struct pnp_dev *dev, struct resource *res);
+#ifdef CONFIG_ISA_DMA_API
 int pnp_check_dma(struct pnp_dev *dev, struct resource *res);
+#endif
 
 char *pnp_resource_type_name(struct resource *res);
 void dbg_pnp_show_resources(struct pnp_dev *dev, char *desc);
diff -druN linux-libre-2.6.38-gnu/drivers/pnp/card.c linux-libre-2.6.39-gnu/drivers/pnp/card.c
--- linux-libre-2.6.38-gnu/drivers/pnp/card.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pnp/card.c	2011-05-19 00:06:34.000000000 -0400
@@ -320,7 +320,7 @@
  * pnp_request_card_device - Searches for a PnP device under the specified card
  * @clink: pointer to the card link, cannot be NULL
  * @id: pointer to a PnP ID structure that explains the rules for finding the device
- * @from: Starting place to search from. If NULL it will start from the begining.
+ * @from: Starting place to search from. If NULL it will start from the beginning.
  */
 struct pnp_dev *pnp_request_card_device(struct pnp_card_link *clink,
 					const char *id, struct pnp_dev *from)
@@ -369,7 +369,7 @@
 
 /**
  * pnp_release_card_device - call this when the driver no longer needs the device
- * @dev: pointer to the PnP device stucture
+ * @dev: pointer to the PnP device structure
  */
 void pnp_release_card_device(struct pnp_dev *dev)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/pnp/manager.c linux-libre-2.6.39-gnu/drivers/pnp/manager.c
--- linux-libre-2.6.38-gnu/drivers/pnp/manager.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pnp/manager.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,6 +171,7 @@
 	return 0;
 }
 
+#ifdef CONFIG_ISA_DMA_API
 static int pnp_assign_dma(struct pnp_dev *dev, struct pnp_dma *rule, int idx)
 {
 	struct resource *res, local_res;
@@ -210,6 +211,7 @@
 	pnp_add_dma_resource(dev, res->start, res->flags);
 	return 0;
 }
+#endif /* CONFIG_ISA_DMA_API */
 
 void pnp_init_resources(struct pnp_dev *dev)
 {
@@ -234,7 +236,8 @@
 static int pnp_assign_resources(struct pnp_dev *dev, int set)
 {
 	struct pnp_option *option;
-	int nport = 0, nmem = 0, nirq = 0, ndma = 0;
+	int nport = 0, nmem = 0, nirq = 0;
+	int ndma __maybe_unused = 0;
 	int ret = 0;
 
 	pnp_dbg(&dev->dev, "pnp_assign_resources, try dependent set %d\n", set);
@@ -256,9 +259,11 @@
 		case IORESOURCE_IRQ:
 			ret = pnp_assign_irq(dev, &option->u.irq, nirq++);
 			break;
+#ifdef CONFIG_ISA_DMA_API
 		case IORESOURCE_DMA:
 			ret = pnp_assign_dma(dev, &option->u.dma, ndma++);
 			break;
+#endif
 		default:
 			ret = -EINVAL;
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/pnp/pnpbios/bioscalls.c linux-libre-2.6.39-gnu/drivers/pnp/pnpbios/bioscalls.c
--- linux-libre-2.6.38-gnu/drivers/pnp/pnpbios/bioscalls.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pnp/pnpbios/bioscalls.c	2011-05-19 00:06:34.000000000 -0400
@@ -219,7 +219,7 @@
 		       module);
 		break;
 	case PNP_HARDWARE_ERROR:
-		printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occured\n",
+		printk(KERN_ERR "PnPBIOS: %s: a hardware failure has occurred\n",
 		       module);
 		break;
 	default:
diff -druN linux-libre-2.6.38-gnu/drivers/pnp/resource.c linux-libre-2.6.39-gnu/drivers/pnp/resource.c
--- linux-libre-2.6.38-gnu/drivers/pnp/resource.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pnp/resource.c	2011-05-19 00:06:34.000000000 -0400
@@ -409,9 +409,9 @@
 	return 1;
 }
 
+#ifdef CONFIG_ISA_DMA_API
 int pnp_check_dma(struct pnp_dev *dev, struct resource *res)
 {
-#ifndef CONFIG_IA64
 	int i;
 	struct pnp_dev *tdev;
 	struct resource *tres;
@@ -466,11 +466,8 @@
 	}
 
 	return 1;
-#else
-	/* IA64 does not have legacy DMA */
-	return 0;
-#endif
 }
+#endif /* CONFIG_ISA_DMA_API */
 
 unsigned long pnp_resource_type(struct resource *res)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/power/bq20z75.c linux-libre-2.6.39-gnu/drivers/power/bq20z75.c
--- linux-libre-2.6.38-gnu/drivers/power/bq20z75.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/bq20z75.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,10 @@
 #include <linux/power_supply.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/gpio.h>
+
+#include <linux/power/bq20z75.h>
 
 enum {
 	REG_MANUFACTURER_DATA,
@@ -38,11 +42,22 @@
 	REG_CYCLE_COUNT,
 	REG_SERIAL_NUMBER,
 	REG_REMAINING_CAPACITY,
+	REG_REMAINING_CAPACITY_CHARGE,
 	REG_FULL_CHARGE_CAPACITY,
+	REG_FULL_CHARGE_CAPACITY_CHARGE,
 	REG_DESIGN_CAPACITY,
+	REG_DESIGN_CAPACITY_CHARGE,
 	REG_DESIGN_VOLTAGE,
 };
 
+/* Battery Mode defines */
+#define BATTERY_MODE_OFFSET		0x03
+#define BATTERY_MODE_MASK		0x8000
+enum bq20z75_battery_mode {
+	BATTERY_MODE_AMPS,
+	BATTERY_MODE_WATTS
+};
+
 /* manufacturer access defines */
 #define MANUFACTURER_ACCESS_STATUS	0x0006
 #define MANUFACTURER_ACCESS_SLEEP	0x0011
@@ -78,8 +93,12 @@
 		BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
 	[REG_REMAINING_CAPACITY] =
 		BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
+	[REG_REMAINING_CAPACITY_CHARGE] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
 	[REG_FULL_CHARGE_CAPACITY] =
 		BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
+	[REG_FULL_CHARGE_CAPACITY_CHARGE] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
 	[REG_TIME_TO_EMPTY] =
 		BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
 			65535),
@@ -93,6 +112,9 @@
 	[REG_DESIGN_CAPACITY] =
 		BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
 			65535),
+	[REG_DESIGN_CAPACITY_CHARGE] =
+		BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0,
+			65535),
 	[REG_DESIGN_VOLTAGE] =
 		BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
 			65535),
@@ -117,39 +139,72 @@
 	POWER_SUPPLY_PROP_ENERGY_NOW,
 	POWER_SUPPLY_PROP_ENERGY_FULL,
 	POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 };
 
 struct bq20z75_info {
-	struct i2c_client	*client;
-	struct power_supply	power_supply;
+	struct i2c_client		*client;
+	struct power_supply		power_supply;
+	struct bq20z75_platform_data	*pdata;
+	bool				is_present;
+	bool				gpio_detect;
+	bool				enable_detection;
+	int				irq;
 };
 
 static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
 {
-	s32 ret;
+	struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+	s32 ret = 0;
+	int retries = 1;
+
+	if (bq20z75_device->pdata)
+		retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
+
+	while (retries > 0) {
+		ret = i2c_smbus_read_word_data(client, address);
+		if (ret >= 0)
+			break;
+		retries--;
+	}
 
-	ret = i2c_smbus_read_word_data(client, address);
 	if (ret < 0) {
-		dev_err(&client->dev,
+		dev_dbg(&client->dev,
 			"%s: i2c read at address 0x%x failed\n",
 			__func__, address);
 		return ret;
 	}
+
 	return le16_to_cpu(ret);
 }
 
 static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
 	u16 value)
 {
-	s32 ret;
+	struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+	s32 ret = 0;
+	int retries = 1;
+
+	if (bq20z75_device->pdata)
+		retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
+
+	while (retries > 0) {
+		ret = i2c_smbus_write_word_data(client, address,
+			le16_to_cpu(value));
+		if (ret >= 0)
+			break;
+		retries--;
+	}
 
-	ret = i2c_smbus_write_word_data(client, address, le16_to_cpu(value));
 	if (ret < 0) {
-		dev_err(&client->dev,
+		dev_dbg(&client->dev,
 			"%s: i2c write to address 0x%x failed\n",
 			__func__, address);
 		return ret;
 	}
+
 	return 0;
 }
 
@@ -158,6 +213,19 @@
 	union power_supply_propval *val)
 {
 	s32 ret;
+	struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+
+	if (psp == POWER_SUPPLY_PROP_PRESENT &&
+		bq20z75_device->gpio_detect) {
+		ret = gpio_get_value(
+			bq20z75_device->pdata->battery_detect);
+		if (ret == bq20z75_device->pdata->battery_detect_present)
+			val->intval = 1;
+		else
+			val->intval = 0;
+		bq20z75_device->is_present = val->intval;
+		return ret;
+	}
 
 	/* Write to ManufacturerAccess with
 	 * ManufacturerAccess command and then
@@ -165,9 +233,11 @@
 	ret = bq20z75_write_word_data(client,
 		bq20z75_data[REG_MANUFACTURER_DATA].addr,
 		MANUFACTURER_ACCESS_STATUS);
-	if (ret < 0)
+	if (ret < 0) {
+		if (psp == POWER_SUPPLY_PROP_PRESENT)
+			val->intval = 0; /* battery removed */
 		return ret;
-
+	}
 
 	ret = bq20z75_read_word_data(client,
 		bq20z75_data[REG_MANUFACTURER_DATA].addr);
@@ -248,30 +318,39 @@
 {
 #define BASE_UNIT_CONVERSION		1000
 #define BATTERY_MODE_CAP_MULT_WATT	(10 * BASE_UNIT_CONVERSION)
-#define TIME_UNIT_CONVERSION		600
-#define TEMP_KELVIN_TO_CELCIUS		2731
+#define TIME_UNIT_CONVERSION		60
+#define TEMP_KELVIN_TO_CELSIUS		2731
 	switch (psp) {
 	case POWER_SUPPLY_PROP_ENERGY_NOW:
 	case POWER_SUPPLY_PROP_ENERGY_FULL:
 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+		/* bq20z75 provides energy in units of 10mWh.
+		 * Convert to ÂµWh
+		 */
 		val->intval *= BATTERY_MODE_CAP_MULT_WATT;
 		break;
 
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 		val->intval *= BASE_UNIT_CONVERSION;
 		break;
 
 	case POWER_SUPPLY_PROP_TEMP:
-		/* bq20z75 provides battery tempreture in 0.1Â°K
-		 * so convert it to 0.1Â°C */
-		val->intval -= TEMP_KELVIN_TO_CELCIUS;
-		val->intval *= 10;
+		/* bq20z75 provides battery temperature in 0.1K
+		 * so convert it to 0.1Â°C
+		 */
+		val->intval -= TEMP_KELVIN_TO_CELSIUS;
 		break;
 
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
 	case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
+		/* bq20z75 provides time to empty and time to full in minutes.
+		 * Convert to seconds
+		 */
 		val->intval *= TIME_UNIT_CONVERSION;
 		break;
 
@@ -281,11 +360,44 @@
 	}
 }
 
+static enum bq20z75_battery_mode
+bq20z75_set_battery_mode(struct i2c_client *client,
+	enum bq20z75_battery_mode mode)
+{
+	int ret, original_val;
+
+	original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET);
+	if (original_val < 0)
+		return original_val;
+
+	if ((original_val & BATTERY_MODE_MASK) == mode)
+		return mode;
+
+	if (mode == BATTERY_MODE_AMPS)
+		ret = original_val & ~BATTERY_MODE_MASK;
+	else
+		ret = original_val | BATTERY_MODE_MASK;
+
+	ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret);
+	if (ret < 0)
+		return ret;
+
+	return original_val & BATTERY_MODE_MASK;
+}
+
 static int bq20z75_get_battery_capacity(struct i2c_client *client,
 	int reg_offset, enum power_supply_property psp,
 	union power_supply_propval *val)
 {
 	s32 ret;
+	enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS;
+
+	if (power_supply_is_amp_property(psp))
+		mode = BATTERY_MODE_AMPS;
+
+	mode = bq20z75_set_battery_mode(client, mode);
+	if (mode < 0)
+		return mode;
 
 	ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
 	if (ret < 0)
@@ -298,6 +410,10 @@
 	} else
 		val->intval = ret;
 
+	ret = bq20z75_set_battery_mode(client, mode);
+	if (ret < 0)
+		return ret;
+
 	return 0;
 }
 
@@ -318,12 +434,25 @@
 	return 0;
 }
 
+static int bq20z75_get_property_index(struct i2c_client *client,
+	enum power_supply_property psp)
+{
+	int count;
+	for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++)
+		if (psp == bq20z75_data[count].psp)
+			return count;
+
+	dev_warn(&client->dev,
+		"%s: Invalid Property - %d\n", __func__, psp);
+
+	return -EINVAL;
+}
+
 static int bq20z75_get_property(struct power_supply *psy,
 	enum power_supply_property psp,
 	union power_supply_propval *val)
 {
-	int count;
-	int ret;
+	int ret = 0;
 	struct bq20z75_info *bq20z75_device = container_of(psy,
 				struct bq20z75_info, power_supply);
 	struct i2c_client *client = bq20z75_device->client;
@@ -332,8 +461,8 @@
 	case POWER_SUPPLY_PROP_PRESENT:
 	case POWER_SUPPLY_PROP_HEALTH:
 		ret = bq20z75_get_battery_presence_and_health(client, psp, val);
-		if (ret)
-			return ret;
+		if (psp == POWER_SUPPLY_PROP_PRESENT)
+			return 0;
 		break;
 
 	case POWER_SUPPLY_PROP_TECHNOLOGY:
@@ -343,22 +472,19 @@
 	case POWER_SUPPLY_PROP_ENERGY_NOW:
 	case POWER_SUPPLY_PROP_ENERGY_FULL:
 	case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
 	case POWER_SUPPLY_PROP_CAPACITY:
-		for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) {
-			if (psp == bq20z75_data[count].psp)
-				break;
-		}
-
-		ret = bq20z75_get_battery_capacity(client, count, psp, val);
-		if (ret)
-			return ret;
+		ret = bq20z75_get_property_index(client, psp);
+		if (ret < 0)
+			break;
 
+		ret = bq20z75_get_battery_capacity(client, ret, psp, val);
 		break;
 
 	case POWER_SUPPLY_PROP_SERIAL_NUMBER:
 		ret = bq20z75_get_battery_serial_number(client, val);
-		if (ret)
-			return ret;
 		break;
 
 	case POWER_SUPPLY_PROP_STATUS:
@@ -369,15 +495,11 @@
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
 	case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
 	case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
-		for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++) {
-			if (psp == bq20z75_data[count].psp)
-				break;
-		}
-
-		ret = bq20z75_get_battery_property(client, count, psp, val);
-		if (ret)
-			return ret;
+		ret = bq20z75_get_property_index(client, psp);
+		if (ret < 0)
+			break;
 
+		ret = bq20z75_get_battery_property(client, ret, psp, val);
 		break;
 
 	default:
@@ -386,26 +508,58 @@
 		return -EINVAL;
 	}
 
-	/* Convert units to match requirements for power supply class */
-	bq20z75_unit_adjustment(client, psp, val);
+	if (!bq20z75_device->enable_detection)
+		goto done;
+
+	if (!bq20z75_device->gpio_detect &&
+		bq20z75_device->is_present != (ret >= 0)) {
+		bq20z75_device->is_present = (ret >= 0);
+		power_supply_changed(&bq20z75_device->power_supply);
+	}
+
+done:
+	if (!ret) {
+		/* Convert units to match requirements for power supply class */
+		bq20z75_unit_adjustment(client, psp, val);
+	}
 
 	dev_dbg(&client->dev,
-		"%s: property = %d, value = %d\n", __func__, psp, val->intval);
+		"%s: property = %d, value = %x\n", __func__, psp, val->intval);
+
+	if (ret && bq20z75_device->is_present)
+		return ret;
+
+	/* battery not present, so return NODATA for properties */
+	if (ret)
+		return -ENODATA;
 
 	return 0;
 }
 
-static int bq20z75_probe(struct i2c_client *client,
+static irqreturn_t bq20z75_irq(int irq, void *devid)
+{
+	struct power_supply *battery = devid;
+
+	power_supply_changed(battery);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit bq20z75_probe(struct i2c_client *client,
 	const struct i2c_device_id *id)
 {
 	struct bq20z75_info *bq20z75_device;
+	struct bq20z75_platform_data *pdata = client->dev.platform_data;
 	int rc;
+	int irq;
 
 	bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
 	if (!bq20z75_device)
 		return -ENOMEM;
 
 	bq20z75_device->client = client;
+	bq20z75_device->enable_detection = false;
+	bq20z75_device->gpio_detect = false;
 	bq20z75_device->power_supply.name = "battery";
 	bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
 	bq20z75_device->power_supply.properties = bq20z75_properties;
@@ -413,26 +567,86 @@
 		ARRAY_SIZE(bq20z75_properties);
 	bq20z75_device->power_supply.get_property = bq20z75_get_property;
 
+	if (pdata) {
+		bq20z75_device->gpio_detect =
+			gpio_is_valid(pdata->battery_detect);
+		bq20z75_device->pdata = pdata;
+	}
+
 	i2c_set_clientdata(client, bq20z75_device);
 
+	if (!bq20z75_device->gpio_detect)
+		goto skip_gpio;
+
+	rc = gpio_request(pdata->battery_detect, dev_name(&client->dev));
+	if (rc) {
+		dev_warn(&client->dev, "Failed to request gpio: %d\n", rc);
+		bq20z75_device->gpio_detect = false;
+		goto skip_gpio;
+	}
+
+	rc = gpio_direction_input(pdata->battery_detect);
+	if (rc) {
+		dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc);
+		gpio_free(pdata->battery_detect);
+		bq20z75_device->gpio_detect = false;
+		goto skip_gpio;
+	}
+
+	irq = gpio_to_irq(pdata->battery_detect);
+	if (irq <= 0) {
+		dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
+		gpio_free(pdata->battery_detect);
+		bq20z75_device->gpio_detect = false;
+		goto skip_gpio;
+	}
+
+	rc = request_irq(irq, bq20z75_irq,
+		IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
+		dev_name(&client->dev), &bq20z75_device->power_supply);
+	if (rc) {
+		dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
+		gpio_free(pdata->battery_detect);
+		bq20z75_device->gpio_detect = false;
+		goto skip_gpio;
+	}
+
+	bq20z75_device->irq = irq;
+
+skip_gpio:
+
 	rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
 	if (rc) {
 		dev_err(&client->dev,
 			"%s: Failed to register power supply\n", __func__);
-		kfree(bq20z75_device);
-		return rc;
+		goto exit_psupply;
 	}
 
 	dev_info(&client->dev,
 		"%s: battery gas gauge device registered\n", client->name);
 
 	return 0;
+
+exit_psupply:
+	if (bq20z75_device->irq)
+		free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
+	if (bq20z75_device->gpio_detect)
+		gpio_free(pdata->battery_detect);
+
+	kfree(bq20z75_device);
+
+	return rc;
 }
 
-static int bq20z75_remove(struct i2c_client *client)
+static int __devexit bq20z75_remove(struct i2c_client *client)
 {
 	struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
 
+	if (bq20z75_device->irq)
+		free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
+	if (bq20z75_device->gpio_detect)
+		gpio_free(bq20z75_device->pdata->battery_detect);
+
 	power_supply_unregister(&bq20z75_device->power_supply);
 	kfree(bq20z75_device);
 	bq20z75_device = NULL;
@@ -444,13 +658,14 @@
 static int bq20z75_suspend(struct i2c_client *client,
 	pm_message_t state)
 {
+	struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
 	s32 ret;
 
 	/* write to manufacturer access with sleep command */
 	ret = bq20z75_write_word_data(client,
 		bq20z75_data[REG_MANUFACTURER_DATA].addr,
 		MANUFACTURER_ACCESS_SLEEP);
-	if (ret < 0)
+	if (bq20z75_device->is_present && ret < 0)
 		return ret;
 
 	return 0;
@@ -465,10 +680,11 @@
 	{ "bq20z75", 0 },
 	{}
 };
+MODULE_DEVICE_TABLE(i2c, bq20z75_id);
 
 static struct i2c_driver bq20z75_battery_driver = {
 	.probe		= bq20z75_probe,
-	.remove		= bq20z75_remove,
+	.remove		= __devexit_p(bq20z75_remove),
 	.suspend	= bq20z75_suspend,
 	.resume		= bq20z75_resume,
 	.id_table	= bq20z75_id,
diff -druN linux-libre-2.6.38-gnu/drivers/power/bq27x00_battery.c linux-libre-2.6.39-gnu/drivers/power/bq27x00_battery.c
--- linux-libre-2.6.38-gnu/drivers/power/bq27x00_battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/bq27x00_battery.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,7 @@
  *
  * Copyright (C) 2008 Rodolfo Giometti <giometti@linux.it>
  * Copyright (C) 2008 Eurotech S.p.A. <info@eurotech.it>
+ * Copyright (C) 2010-2011 Lars-Peter Clausen <lars@metafoo.de>
  *
  * Based on a previous work by Copyright (C) 2008 Texas Instruments, Inc.
  *
@@ -15,6 +16,13 @@
  * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  *
  */
+
+/*
+ * Datasheets:
+ * http://focus.ti.com/docs/prod/folders/print/bq27000.html
+ * http://focus.ti.com/docs/prod/folders/print/bq27500.html
+ */
+
 #include <linux/module.h>
 #include <linux/param.h>
 #include <linux/jiffies.h>
@@ -27,7 +35,9 @@
 #include <linux/slab.h>
 #include <asm/unaligned.h>
 
-#define DRIVER_VERSION			"1.1.0"
+#include <linux/power/bq27x00_battery.h>
+
+#define DRIVER_VERSION			"1.2.0"
 
 #define BQ27x00_REG_TEMP		0x06
 #define BQ27x00_REG_VOLT		0x08
@@ -36,36 +46,59 @@
 #define BQ27x00_REG_TTE			0x16
 #define BQ27x00_REG_TTF			0x18
 #define BQ27x00_REG_TTECP		0x26
+#define BQ27x00_REG_NAC			0x0C /* Nominal available capaciy */
+#define BQ27x00_REG_LMD			0x12 /* Last measured discharge */
+#define BQ27x00_REG_CYCT		0x2A /* Cycle count total */
+#define BQ27x00_REG_AE			0x22 /* Available enery */
 
 #define BQ27000_REG_RSOC		0x0B /* Relative State-of-Charge */
+#define BQ27000_REG_ILMD		0x76 /* Initial last measured discharge */
 #define BQ27000_FLAG_CHGS		BIT(7)
+#define BQ27000_FLAG_FC			BIT(5)
 
-#define BQ27500_REG_SOC			0x2c
+#define BQ27500_REG_SOC			0x2C
+#define BQ27500_REG_DCAP		0x3C /* Design capacity */
 #define BQ27500_FLAG_DSC		BIT(0)
 #define BQ27500_FLAG_FC			BIT(9)
 
-/* If the system has several batteries we need a different name for each
- * of them...
- */
-static DEFINE_IDR(battery_id);
-static DEFINE_MUTEX(battery_mutex);
+#define BQ27000_RS			20 /* Resistor sense */
 
 struct bq27x00_device_info;
 struct bq27x00_access_methods {
-	int (*read)(u8 reg, int *rt_value, int b_single,
-		struct bq27x00_device_info *di);
+	int (*read)(struct bq27x00_device_info *di, u8 reg, bool single);
 };
 
 enum bq27x00_chip { BQ27000, BQ27500 };
 
+struct bq27x00_reg_cache {
+	int temperature;
+	int time_to_empty;
+	int time_to_empty_avg;
+	int time_to_full;
+	int charge_full;
+	int charge_counter;
+	int capacity;
+	int flags;
+
+	int current_now;
+};
+
 struct bq27x00_device_info {
 	struct device 		*dev;
 	int			id;
-	struct bq27x00_access_methods	*bus;
-	struct power_supply	bat;
 	enum bq27x00_chip	chip;
 
-	struct i2c_client	*client;
+	struct bq27x00_reg_cache cache;
+	int charge_design_full;
+
+	unsigned long last_update;
+	struct delayed_work work;
+
+	struct power_supply	bat;
+
+	struct bq27x00_access_methods bus;
+
+	struct mutex lock;
 };
 
 static enum power_supply_property bq27x00_battery_props[] = {
@@ -78,164 +111,328 @@
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
 	POWER_SUPPLY_PROP_TIME_TO_FULL_NOW,
+	POWER_SUPPLY_PROP_TECHNOLOGY,
+	POWER_SUPPLY_PROP_CHARGE_FULL,
+	POWER_SUPPLY_PROP_CHARGE_NOW,
+	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_ENERGY_NOW,
 };
 
+static unsigned int poll_interval = 360;
+module_param(poll_interval, uint, 0644);
+MODULE_PARM_DESC(poll_interval, "battery poll interval in seconds - " \
+				"0 disables polling");
+
 /*
  * Common code for BQ27x00 devices
  */
 
-static int bq27x00_read(u8 reg, int *rt_value, int b_single,
-			struct bq27x00_device_info *di)
+static inline int bq27x00_read(struct bq27x00_device_info *di, u8 reg,
+		bool single)
 {
-	return di->bus->read(reg, rt_value, b_single, di);
+	return di->bus.read(di, reg, single);
 }
 
 /*
- * Return the battery temperature in tenths of degree Celsius
+ * Return the battery Relative State-of-Charge
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_temperature(struct bq27x00_device_info *di)
+static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
 {
-	int ret;
-	int temp = 0;
+	int rsoc;
 
-	ret = bq27x00_read(BQ27x00_REG_TEMP, &temp, 0, di);
-	if (ret) {
-		dev_err(di->dev, "error reading temperature\n");
-		return ret;
+	if (di->chip == BQ27500)
+		rsoc = bq27x00_read(di, BQ27500_REG_SOC, false);
+	else
+		rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
+
+	if (rsoc < 0)
+		dev_err(di->dev, "error reading relative State-of-Charge\n");
+
+	return rsoc;
+}
+
+/*
+ * Return a battery charge value in ÂµAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
+{
+	int charge;
+
+	charge = bq27x00_read(di, reg, false);
+	if (charge < 0) {
+		dev_err(di->dev, "error reading nominal available capacity\n");
+		return charge;
 	}
 
 	if (di->chip == BQ27500)
-		return temp - 2731;
+		charge *= 1000;
 	else
-		return ((temp >> 2) - 273) * 10;
+		charge = charge * 3570 / BQ27000_RS;
+
+	return charge;
 }
 
 /*
- * Return the battery Voltage in milivolts
+ * Return the battery Nominal available capaciy in ÂµAh
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_voltage(struct bq27x00_device_info *di)
+static inline int bq27x00_battery_read_nac(struct bq27x00_device_info *di)
 {
-	int ret;
-	int volt = 0;
+	return bq27x00_battery_read_charge(di, BQ27x00_REG_NAC);
+}
 
-	ret = bq27x00_read(BQ27x00_REG_VOLT, &volt, 0, di);
-	if (ret) {
-		dev_err(di->dev, "error reading voltage\n");
-		return ret;
+/*
+ * Return the battery Last measured discharge in ÂµAh
+ * Or < 0 if something fails.
+ */
+static inline int bq27x00_battery_read_lmd(struct bq27x00_device_info *di)
+{
+	return bq27x00_battery_read_charge(di, BQ27x00_REG_LMD);
+}
+
+/*
+ * Return the battery Initial last measured discharge in ÂµAh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
+{
+	int ilmd;
+
+	if (di->chip == BQ27500)
+		ilmd = bq27x00_read(di, BQ27500_REG_DCAP, false);
+	else
+		ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
+
+	if (ilmd < 0) {
+		dev_err(di->dev, "error reading initial last measured discharge\n");
+		return ilmd;
 	}
 
-	return volt * 1000;
+	if (di->chip == BQ27500)
+		ilmd *= 1000;
+	else
+		ilmd = ilmd * 256 * 3570 / BQ27000_RS;
+
+	return ilmd;
 }
 
 /*
- * Return the battery average current
- * Note that current can be negative signed as well
- * Or 0 if something fails.
+ * Return the battery Cycle count total
+ * Or < 0 if something fails.
  */
-static int bq27x00_battery_current(struct bq27x00_device_info *di)
+static int bq27x00_battery_read_cyct(struct bq27x00_device_info *di)
 {
-	int ret;
-	int curr = 0;
-	int flags = 0;
+	int cyct;
 
-	ret = bq27x00_read(BQ27x00_REG_AI, &curr, 0, di);
-	if (ret) {
-		dev_err(di->dev, "error reading current\n");
-		return 0;
+	cyct = bq27x00_read(di, BQ27x00_REG_CYCT, false);
+	if (cyct < 0)
+		dev_err(di->dev, "error reading cycle count total\n");
+
+	return cyct;
+}
+
+/*
+ * Read a time register.
+ * Return < 0 if something fails.
+ */
+static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
+{
+	int tval;
+
+	tval = bq27x00_read(di, reg, false);
+	if (tval < 0) {
+		dev_err(di->dev, "error reading register %02x: %d\n", reg, tval);
+		return tval;
 	}
 
-	if (di->chip == BQ27500) {
-		/* bq27500 returns signed value */
-		curr = (int)(s16)curr;
-	} else {
-		ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
-		if (ret < 0) {
-			dev_err(di->dev, "error reading flags\n");
-			return 0;
-		}
-		if (flags & BQ27000_FLAG_CHGS) {
-			dev_dbg(di->dev, "negative current!\n");
-			curr = -curr;
-		}
+	if (tval == 65535)
+		return -ENODATA;
+
+	return tval * 60;
+}
+
+static void bq27x00_update(struct bq27x00_device_info *di)
+{
+	struct bq27x00_reg_cache cache = {0, };
+	bool is_bq27500 = di->chip == BQ27500;
+
+	cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
+	if (cache.flags >= 0) {
+		cache.capacity = bq27x00_battery_read_rsoc(di);
+		cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false);
+		cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
+		cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
+		cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
+		cache.charge_full = bq27x00_battery_read_lmd(di);
+		cache.charge_counter = bq27x00_battery_read_cyct(di);
+
+		if (!is_bq27500)
+			cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
+
+		/* We only have to read charge design full once */
+		if (di->charge_design_full <= 0)
+			di->charge_design_full = bq27x00_battery_read_ilmd(di);
 	}
 
-	return curr * 1000;
+	/* Ignore current_now which is a snapshot of the current battery state
+	 * and is likely to be different even between two consecutive reads */
+	if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {
+		di->cache = cache;
+		power_supply_changed(&di->bat);
+	}
+
+	di->last_update = jiffies;
 }
 
+static void bq27x00_battery_poll(struct work_struct *work)
+{
+	struct bq27x00_device_info *di =
+		container_of(work, struct bq27x00_device_info, work.work);
+
+	bq27x00_update(di);
+
+	if (poll_interval > 0) {
+		/* The timer does not have to be accurate. */
+		set_timer_slack(&di->work.timer, poll_interval * HZ / 4);
+		schedule_delayed_work(&di->work, poll_interval * HZ);
+	}
+}
+
+
 /*
- * Return the battery Relative State-of-Charge
+ * Return the battery temperature in tenths of degree Celsius
  * Or < 0 if something fails.
  */
-static int bq27x00_battery_rsoc(struct bq27x00_device_info *di)
+static int bq27x00_battery_temperature(struct bq27x00_device_info *di,
+	union power_supply_propval *val)
 {
-	int ret;
-	int rsoc = 0;
+	if (di->cache.temperature < 0)
+		return di->cache.temperature;
 
 	if (di->chip == BQ27500)
-		ret = bq27x00_read(BQ27500_REG_SOC, &rsoc, 0, di);
+		val->intval = di->cache.temperature - 2731;
 	else
-		ret = bq27x00_read(BQ27000_REG_RSOC, &rsoc, 1, di);
-	if (ret) {
-		dev_err(di->dev, "error reading relative State-of-Charge\n");
-		return ret;
+		val->intval = ((di->cache.temperature * 5) - 5463) / 2;
+
+	return 0;
+}
+
+/*
+ * Return the battery average current in ÂµA
+ * Note that current can be negative signed as well
+ * Or 0 if something fails.
+ */
+static int bq27x00_battery_current(struct bq27x00_device_info *di,
+	union power_supply_propval *val)
+{
+	int curr;
+
+	if (di->chip == BQ27500)
+	    curr = bq27x00_read(di, BQ27x00_REG_AI, false);
+	else
+	    curr = di->cache.current_now;
+
+	if (curr < 0)
+		return curr;
+
+	if (di->chip == BQ27500) {
+		/* bq27500 returns signed value */
+		val->intval = (int)((s16)curr) * 1000;
+	} else {
+		if (di->cache.flags & BQ27000_FLAG_CHGS) {
+			dev_dbg(di->dev, "negative current!\n");
+			curr = -curr;
+		}
+
+		val->intval = curr * 3570 / BQ27000_RS;
 	}
 
-	return rsoc;
+	return 0;
 }
 
 static int bq27x00_battery_status(struct bq27x00_device_info *di,
-				  union power_supply_propval *val)
+	union power_supply_propval *val)
 {
-	int flags = 0;
 	int status;
-	int ret;
-
-	ret = bq27x00_read(BQ27x00_REG_FLAGS, &flags, 0, di);
-	if (ret < 0) {
-		dev_err(di->dev, "error reading flags\n");
-		return ret;
-	}
 
 	if (di->chip == BQ27500) {
-		if (flags & BQ27500_FLAG_FC)
+		if (di->cache.flags & BQ27500_FLAG_FC)
 			status = POWER_SUPPLY_STATUS_FULL;
-		else if (flags & BQ27500_FLAG_DSC)
+		else if (di->cache.flags & BQ27500_FLAG_DSC)
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_CHARGING;
 	} else {
-		if (flags & BQ27000_FLAG_CHGS)
+		if (di->cache.flags & BQ27000_FLAG_FC)
+			status = POWER_SUPPLY_STATUS_FULL;
+		else if (di->cache.flags & BQ27000_FLAG_CHGS)
 			status = POWER_SUPPLY_STATUS_CHARGING;
+		else if (power_supply_am_i_supplied(&di->bat))
+			status = POWER_SUPPLY_STATUS_NOT_CHARGING;
 		else
 			status = POWER_SUPPLY_STATUS_DISCHARGING;
 	}
 
 	val->intval = status;
+
 	return 0;
 }
 
 /*
- * Read a time register.
- * Return < 0 if something fails.
+ * Return the battery Voltage in milivolts
+ * Or < 0 if something fails.
  */
-static int bq27x00_battery_time(struct bq27x00_device_info *di, int reg,
-				union power_supply_propval *val)
+static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
+	union power_supply_propval *val)
 {
-	int tval = 0;
-	int ret;
+	int volt;
 
-	ret = bq27x00_read(reg, &tval, 0, di);
-	if (ret) {
-		dev_err(di->dev, "error reading register %02x\n", reg);
-		return ret;
+	volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
+	if (volt < 0)
+		return volt;
+
+	val->intval = volt * 1000;
+
+	return 0;
+}
+
+/*
+ * Return the battery Available energy in ÂµWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_energy(struct bq27x00_device_info *di,
+	union power_supply_propval *val)
+{
+	int ae;
+
+	ae = bq27x00_read(di, BQ27x00_REG_AE, false);
+	if (ae < 0) {
+		dev_err(di->dev, "error reading available energy\n");
+		return ae;
 	}
 
-	if (tval == 65535)
-		return -ENODATA;
+	if (di->chip == BQ27500)
+		ae *= 1000;
+	else
+		ae = ae * 29200 / BQ27000_RS;
+
+	val->intval = ae;
+
+	return 0;
+}
+
+
+static int bq27x00_simple_value(int value,
+	union power_supply_propval *val)
+{
+	if (value < 0)
+		return value;
+
+	val->intval = value;
 
-	val->intval = tval * 60;
 	return 0;
 }
 
@@ -249,33 +446,61 @@
 	int ret = 0;
 	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
 
+	mutex_lock(&di->lock);
+	if (time_is_before_jiffies(di->last_update + 5 * HZ)) {
+		cancel_delayed_work_sync(&di->work);
+		bq27x00_battery_poll(&di->work.work);
+	}
+	mutex_unlock(&di->lock);
+
+	if (psp != POWER_SUPPLY_PROP_PRESENT && di->cache.flags < 0)
+		return -ENODEV;
+
 	switch (psp) {
 	case POWER_SUPPLY_PROP_STATUS:
 		ret = bq27x00_battery_status(di, val);
 		break;
 	case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+		ret = bq27x00_battery_voltage(di, val);
+		break;
 	case POWER_SUPPLY_PROP_PRESENT:
-		val->intval = bq27x00_battery_voltage(di);
-		if (psp == POWER_SUPPLY_PROP_PRESENT)
-			val->intval = val->intval <= 0 ? 0 : 1;
+		val->intval = di->cache.flags < 0 ? 0 : 1;
 		break;
 	case POWER_SUPPLY_PROP_CURRENT_NOW:
-		val->intval = bq27x00_battery_current(di);
+		ret = bq27x00_battery_current(di, val);
 		break;
 	case POWER_SUPPLY_PROP_CAPACITY:
-		val->intval = bq27x00_battery_rsoc(di);
+		ret = bq27x00_simple_value(di->cache.capacity, val);
 		break;
 	case POWER_SUPPLY_PROP_TEMP:
-		val->intval = bq27x00_battery_temperature(di);
+		ret = bq27x00_battery_temperature(di, val);
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
-		ret = bq27x00_battery_time(di, BQ27x00_REG_TTE, val);
+		ret = bq27x00_simple_value(di->cache.time_to_empty, val);
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
-		ret = bq27x00_battery_time(di, BQ27x00_REG_TTECP, val);
+		ret = bq27x00_simple_value(di->cache.time_to_empty_avg, val);
 		break;
 	case POWER_SUPPLY_PROP_TIME_TO_FULL_NOW:
-		ret = bq27x00_battery_time(di, BQ27x00_REG_TTF, val);
+		ret = bq27x00_simple_value(di->cache.time_to_full, val);
+		break;
+	case POWER_SUPPLY_PROP_TECHNOLOGY:
+		val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_NOW:
+		ret = bq27x00_simple_value(bq27x00_battery_read_nac(di), val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL:
+		ret = bq27x00_simple_value(di->cache.charge_full, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
+		ret = bq27x00_simple_value(di->charge_design_full, val);
+		break;
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+		ret = bq27x00_simple_value(di->cache.charge_counter, val);
+		break;
+	case POWER_SUPPLY_PROP_ENERGY_NOW:
+		ret = bq27x00_battery_energy(di, val);
 		break;
 	default:
 		return -EINVAL;
@@ -284,56 +509,91 @@
 	return ret;
 }
 
-static void bq27x00_powersupply_init(struct bq27x00_device_info *di)
+static void bq27x00_external_power_changed(struct power_supply *psy)
 {
+	struct bq27x00_device_info *di = to_bq27x00_device_info(psy);
+
+	cancel_delayed_work_sync(&di->work);
+	schedule_delayed_work(&di->work, 0);
+}
+
+static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
+{
+	int ret;
+
 	di->bat.type = POWER_SUPPLY_TYPE_BATTERY;
 	di->bat.properties = bq27x00_battery_props;
 	di->bat.num_properties = ARRAY_SIZE(bq27x00_battery_props);
 	di->bat.get_property = bq27x00_battery_get_property;
-	di->bat.external_power_changed = NULL;
+	di->bat.external_power_changed = bq27x00_external_power_changed;
+
+	INIT_DELAYED_WORK(&di->work, bq27x00_battery_poll);
+	mutex_init(&di->lock);
+
+	ret = power_supply_register(di->dev, &di->bat);
+	if (ret) {
+		dev_err(di->dev, "failed to register battery: %d\n", ret);
+		return ret;
+	}
+
+	dev_info(di->dev, "support ver. %s enabled\n", DRIVER_VERSION);
+
+	bq27x00_update(di);
+
+	return 0;
 }
 
-/*
- * i2c specific code
+static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
+{
+	cancel_delayed_work_sync(&di->work);
+
+	power_supply_unregister(&di->bat);
+
+	mutex_destroy(&di->lock);
+}
+
+
+/* i2c specific code */
+#ifdef CONFIG_BATTERY_BQ27X00_I2C
+
+/* If the system has several batteries we need a different name for each
+ * of them...
  */
+static DEFINE_IDR(battery_id);
+static DEFINE_MUTEX(battery_mutex);
 
-static int bq27x00_read_i2c(u8 reg, int *rt_value, int b_single,
-			struct bq27x00_device_info *di)
+static int bq27x00_read_i2c(struct bq27x00_device_info *di, u8 reg, bool single)
 {
-	struct i2c_client *client = di->client;
-	struct i2c_msg msg[1];
+	struct i2c_client *client = to_i2c_client(di->dev);
+	struct i2c_msg msg[2];
 	unsigned char data[2];
-	int err;
+	int ret;
 
 	if (!client->adapter)
 		return -ENODEV;
 
-	msg->addr = client->addr;
-	msg->flags = 0;
-	msg->len = 1;
-	msg->buf = data;
-
-	data[0] = reg;
-	err = i2c_transfer(client->adapter, msg, 1);
+	msg[0].addr = client->addr;
+	msg[0].flags = 0;
+	msg[0].buf = &reg;
+	msg[0].len = sizeof(reg);
+	msg[1].addr = client->addr;
+	msg[1].flags = I2C_M_RD;
+	msg[1].buf = data;
+	if (single)
+		msg[1].len = 1;
+	else
+		msg[1].len = 2;
 
-	if (err >= 0) {
-		if (!b_single)
-			msg->len = 2;
-		else
-			msg->len = 1;
+	ret = i2c_transfer(client->adapter, msg, ARRAY_SIZE(msg));
+	if (ret < 0)
+		return ret;
 
-		msg->flags = I2C_M_RD;
-		err = i2c_transfer(client->adapter, msg, 1);
-		if (err >= 0) {
-			if (!b_single)
-				*rt_value = get_unaligned_le16(data);
-			else
-				*rt_value = data[0];
+	if (!single)
+		ret = get_unaligned_le16(data);
+	else
+		ret = data[0];
 
-			return 0;
-		}
-	}
-	return err;
+	return ret;
 }
 
 static int bq27x00_battery_probe(struct i2c_client *client,
@@ -341,7 +601,6 @@
 {
 	char *name;
 	struct bq27x00_device_info *di;
-	struct bq27x00_access_methods *bus;
 	int num;
 	int retval = 0;
 
@@ -368,38 +627,20 @@
 		retval = -ENOMEM;
 		goto batt_failed_2;
 	}
+
 	di->id = num;
+	di->dev = &client->dev;
 	di->chip = id->driver_data;
+	di->bat.name = name;
+	di->bus.read = &bq27x00_read_i2c;
 
-	bus = kzalloc(sizeof(*bus), GFP_KERNEL);
-	if (!bus) {
-		dev_err(&client->dev, "failed to allocate access method "
-					"data\n");
-		retval = -ENOMEM;
+	if (bq27x00_powersupply_init(di))
 		goto batt_failed_3;
-	}
 
 	i2c_set_clientdata(client, di);
-	di->dev = &client->dev;
-	di->bat.name = name;
-	bus->read = &bq27x00_read_i2c;
-	di->bus = bus;
-	di->client = client;
-
-	bq27x00_powersupply_init(di);
-
-	retval = power_supply_register(&client->dev, &di->bat);
-	if (retval) {
-		dev_err(&client->dev, "failed to register battery\n");
-		goto batt_failed_4;
-	}
-
-	dev_info(&client->dev, "support ver. %s enabled\n", DRIVER_VERSION);
 
 	return 0;
 
-batt_failed_4:
-	kfree(bus);
 batt_failed_3:
 	kfree(di);
 batt_failed_2:
@@ -416,9 +657,8 @@
 {
 	struct bq27x00_device_info *di = i2c_get_clientdata(client);
 
-	power_supply_unregister(&di->bat);
+	bq27x00_powersupply_unregister(di);
 
-	kfree(di->bus);
 	kfree(di->bat.name);
 
 	mutex_lock(&battery_mutex);
@@ -430,15 +670,12 @@
 	return 0;
 }
 
-/*
- * Module stuff
- */
-
 static const struct i2c_device_id bq27x00_id[] = {
 	{ "bq27200", BQ27000 },	/* bq27200 is same as bq27000, but with i2c */
 	{ "bq27500", BQ27500 },
 	{},
 };
+MODULE_DEVICE_TABLE(i2c, bq27x00_id);
 
 static struct i2c_driver bq27x00_battery_driver = {
 	.driver = {
@@ -449,13 +686,164 @@
 	.id_table = bq27x00_id,
 };
 
+static inline int bq27x00_battery_i2c_init(void)
+{
+	int ret = i2c_add_driver(&bq27x00_battery_driver);
+	if (ret)
+		printk(KERN_ERR "Unable to register BQ27x00 i2c driver\n");
+
+	return ret;
+}
+
+static inline void bq27x00_battery_i2c_exit(void)
+{
+	i2c_del_driver(&bq27x00_battery_driver);
+}
+
+#else
+
+static inline int bq27x00_battery_i2c_init(void) { return 0; }
+static inline void bq27x00_battery_i2c_exit(void) {};
+
+#endif
+
+/* platform specific code */
+#ifdef CONFIG_BATTERY_BQ27X00_PLATFORM
+
+static int bq27000_read_platform(struct bq27x00_device_info *di, u8 reg,
+			bool single)
+{
+	struct device *dev = di->dev;
+	struct bq27000_platform_data *pdata = dev->platform_data;
+	unsigned int timeout = 3;
+	int upper, lower;
+	int temp;
+
+	if (!single) {
+		/* Make sure the value has not changed in between reading the
+		 * lower and the upper part */
+		upper = pdata->read(dev, reg + 1);
+		do {
+			temp = upper;
+			if (upper < 0)
+				return upper;
+
+			lower = pdata->read(dev, reg);
+			if (lower < 0)
+				return lower;
+
+			upper = pdata->read(dev, reg + 1);
+		} while (temp != upper && --timeout);
+
+		if (timeout == 0)
+			return -EIO;
+
+		return (upper << 8) | lower;
+	}
+
+	return pdata->read(dev, reg);
+}
+
+static int __devinit bq27000_battery_probe(struct platform_device *pdev)
+{
+	struct bq27x00_device_info *di;
+	struct bq27000_platform_data *pdata = pdev->dev.platform_data;
+	int ret;
+
+	if (!pdata) {
+		dev_err(&pdev->dev, "no platform_data supplied\n");
+		return -EINVAL;
+	}
+
+	if (!pdata->read) {
+		dev_err(&pdev->dev, "no hdq read callback supplied\n");
+		return -EINVAL;
+	}
+
+	di = kzalloc(sizeof(*di), GFP_KERNEL);
+	if (!di) {
+		dev_err(&pdev->dev, "failed to allocate device info data\n");
+		return -ENOMEM;
+	}
+
+	platform_set_drvdata(pdev, di);
+
+	di->dev = &pdev->dev;
+	di->chip = BQ27000;
+
+	di->bat.name = pdata->name ?: dev_name(&pdev->dev);
+	di->bus.read = &bq27000_read_platform;
+
+	ret = bq27x00_powersupply_init(di);
+	if (ret)
+		goto err_free;
+
+	return 0;
+
+err_free:
+	platform_set_drvdata(pdev, NULL);
+	kfree(di);
+
+	return ret;
+}
+
+static int __devexit bq27000_battery_remove(struct platform_device *pdev)
+{
+	struct bq27x00_device_info *di = platform_get_drvdata(pdev);
+
+	bq27x00_powersupply_unregister(di);
+
+	platform_set_drvdata(pdev, NULL);
+	kfree(di);
+
+	return 0;
+}
+
+static struct platform_driver bq27000_battery_driver = {
+	.probe	= bq27000_battery_probe,
+	.remove = __devexit_p(bq27000_battery_remove),
+	.driver = {
+		.name = "bq27000-battery",
+		.owner = THIS_MODULE,
+	},
+};
+
+static inline int bq27x00_battery_platform_init(void)
+{
+	int ret = platform_driver_register(&bq27000_battery_driver);
+	if (ret)
+		printk(KERN_ERR "Unable to register BQ27000 platform driver\n");
+
+	return ret;
+}
+
+static inline void bq27x00_battery_platform_exit(void)
+{
+	platform_driver_unregister(&bq27000_battery_driver);
+}
+
+#else
+
+static inline int bq27x00_battery_platform_init(void) { return 0; }
+static inline void bq27x00_battery_platform_exit(void) {};
+
+#endif
+
+/*
+ * Module stuff
+ */
+
 static int __init bq27x00_battery_init(void)
 {
 	int ret;
 
-	ret = i2c_add_driver(&bq27x00_battery_driver);
+	ret = bq27x00_battery_i2c_init();
 	if (ret)
-		printk(KERN_ERR "Unable to register BQ27x00 driver\n");
+		return ret;
+
+	ret = bq27x00_battery_platform_init();
+	if (ret)
+		bq27x00_battery_i2c_exit();
 
 	return ret;
 }
@@ -463,7 +851,8 @@
 
 static void __exit bq27x00_battery_exit(void)
 {
-	i2c_del_driver(&bq27x00_battery_driver);
+	bq27x00_battery_platform_exit();
+	bq27x00_battery_i2c_exit();
 }
 module_exit(bq27x00_battery_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/power/ds2782_battery.c linux-libre-2.6.39-gnu/drivers/power/ds2782_battery.c
--- linux-libre-2.6.38-gnu/drivers/power/ds2782_battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/ds2782_battery.c	2011-05-19 00:06:34.000000000 -0400
@@ -393,6 +393,7 @@
 	{"ds2786", DS2786},
 	{},
 };
+MODULE_DEVICE_TABLE(i2c, ds278x_id);
 
 static struct i2c_driver ds278x_battery_driver = {
 	.driver 	= {
diff -druN linux-libre-2.6.38-gnu/drivers/power/jz4740-battery.c linux-libre-2.6.39-gnu/drivers/power/jz4740-battery.c
--- linux-libre-2.6.38-gnu/drivers/power/jz4740-battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/jz4740-battery.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,7 @@
 	int irq;
 	int charge_irq;
 
-	struct mfd_cell *cell;
+	const struct mfd_cell *cell;
 
 	int status;
 	long voltage;
@@ -258,7 +258,7 @@
 		return -ENOMEM;
 	}
 
-	jz_battery->cell = pdev->dev.platform_data;
+	jz_battery->cell = mfd_get_cell(pdev);
 
 	jz_battery->irq = platform_get_irq(pdev, 0);
 	if (jz_battery->irq < 0) {
diff -druN linux-libre-2.6.38-gnu/drivers/power/Kconfig linux-libre-2.6.39-gnu/drivers/power/Kconfig
--- linux-libre-2.6.38-gnu/drivers/power/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -117,10 +117,24 @@
 
 config BATTERY_BQ27x00
 	tristate "BQ27x00 battery driver"
+	help
+	  Say Y here to enable support for batteries with BQ27x00 (I2C/HDQ) chips.
+
+config BATTERY_BQ27X00_I2C
+	bool "BQ27200/BQ27500 support"
+	depends on BATTERY_BQ27x00
 	depends on I2C
+	default y
 	help
 	  Say Y here to enable support for batteries with BQ27x00 (I2C) chips.
 
+config BATTERY_BQ27X00_PLATFORM
+	bool "BQ27000 support"
+	depends on BATTERY_BQ27x00
+	default y
+	help
+	  Say Y here to enable support for batteries with BQ27000 (HDQ) chips.
+
 config BATTERY_DA9030
 	tristate "DA9030 battery driver"
 	depends on PMIC_DA903X
diff -druN linux-libre-2.6.38-gnu/drivers/power/power_supply_core.c linux-libre-2.6.39-gnu/drivers/power/power_supply_core.c
--- linux-libre-2.6.38-gnu/drivers/power/power_supply_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/power_supply_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,6 +171,8 @@
 	dev_set_drvdata(dev, psy);
 	psy->dev = dev;
 
+	INIT_WORK(&psy->changed_work, power_supply_changed_work);
+
 	rc = kobject_set_name(&dev->kobj, "%s", psy->name);
 	if (rc)
 		goto kobject_set_name_failed;
@@ -179,8 +181,6 @@
 	if (rc)
 		goto device_add_failed;
 
-	INIT_WORK(&psy->changed_work, power_supply_changed_work);
-
 	rc = power_supply_create_triggers(psy);
 	if (rc)
 		goto create_triggers_failed;
diff -druN linux-libre-2.6.38-gnu/drivers/power/power_supply_leds.c linux-libre-2.6.39-gnu/drivers/power/power_supply_leds.c
--- linux-libre-2.6.38-gnu/drivers/power/power_supply_leds.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/power_supply_leds.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,6 +21,8 @@
 static void power_supply_update_bat_leds(struct power_supply *psy)
 {
 	union power_supply_propval status;
+	unsigned long delay_on = 0;
+	unsigned long delay_off = 0;
 
 	if (psy->get_property(psy, POWER_SUPPLY_PROP_STATUS, &status))
 		return;
@@ -32,16 +34,22 @@
 		led_trigger_event(psy->charging_full_trig, LED_FULL);
 		led_trigger_event(psy->charging_trig, LED_OFF);
 		led_trigger_event(psy->full_trig, LED_FULL);
+		led_trigger_event(psy->charging_blink_full_solid_trig,
+			LED_FULL);
 		break;
 	case POWER_SUPPLY_STATUS_CHARGING:
 		led_trigger_event(psy->charging_full_trig, LED_FULL);
 		led_trigger_event(psy->charging_trig, LED_FULL);
 		led_trigger_event(psy->full_trig, LED_OFF);
+		led_trigger_blink(psy->charging_blink_full_solid_trig,
+			&delay_on, &delay_off);
 		break;
 	default:
 		led_trigger_event(psy->charging_full_trig, LED_OFF);
 		led_trigger_event(psy->charging_trig, LED_OFF);
 		led_trigger_event(psy->full_trig, LED_OFF);
+		led_trigger_event(psy->charging_blink_full_solid_trig,
+			LED_OFF);
 		break;
 	}
 }
@@ -64,15 +72,24 @@
 	if (!psy->full_trig_name)
 		goto full_failed;
 
+	psy->charging_blink_full_solid_trig_name = kasprintf(GFP_KERNEL,
+		"%s-charging-blink-full-solid", psy->name);
+	if (!psy->charging_blink_full_solid_trig_name)
+		goto charging_blink_full_solid_failed;
+
 	led_trigger_register_simple(psy->charging_full_trig_name,
 				    &psy->charging_full_trig);
 	led_trigger_register_simple(psy->charging_trig_name,
 				    &psy->charging_trig);
 	led_trigger_register_simple(psy->full_trig_name,
 				    &psy->full_trig);
+	led_trigger_register_simple(psy->charging_blink_full_solid_trig_name,
+				    &psy->charging_blink_full_solid_trig);
 
 	goto success;
 
+charging_blink_full_solid_failed:
+	kfree(psy->full_trig_name);
 full_failed:
 	kfree(psy->charging_trig_name);
 charging_failed:
@@ -88,6 +105,8 @@
 	led_trigger_unregister_simple(psy->charging_full_trig);
 	led_trigger_unregister_simple(psy->charging_trig);
 	led_trigger_unregister_simple(psy->full_trig);
+	led_trigger_unregister_simple(psy->charging_blink_full_solid_trig);
+	kfree(psy->charging_blink_full_solid_trig_name);
 	kfree(psy->full_trig_name);
 	kfree(psy->charging_trig_name);
 	kfree(psy->charging_full_trig_name);
diff -druN linux-libre-2.6.38-gnu/drivers/power/power_supply_sysfs.c linux-libre-2.6.39-gnu/drivers/power/power_supply_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/power/power_supply_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/power_supply_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -270,7 +270,7 @@
 		attr = &power_supply_attrs[psy->properties[j]];
 
 		ret = power_supply_show_property(dev, attr, prop_buf);
-		if (ret == -ENODEV) {
+		if (ret == -ENODEV || ret == -ENODATA) {
 			/* When a battery is absent, we expect -ENODEV. Don't abort;
 			   send the uevent with at least the the PRESENT=0 property */
 			ret = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/power/s3c_adc_battery.c linux-libre-2.6.39-gnu/drivers/power/s3c_adc_battery.c
--- linux-libre-2.6.38-gnu/drivers/power/s3c_adc_battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/s3c_adc_battery.c	2011-05-19 00:06:34.000000000 -0400
@@ -406,8 +406,8 @@
 	return 0;
 }
 #else
-#define s3c_adc_battery_suspend NULL
-#define s3c_adc_battery_resume NULL
+#define s3c_adc_bat_suspend NULL
+#define s3c_adc_bat_resume NULL
 #endif
 
 static struct platform_driver s3c_adc_bat_driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/power/twl4030_charger.c linux-libre-2.6.39-gnu/drivers/power/twl4030_charger.c
--- linux-libre-2.6.38-gnu/drivers/power/twl4030_charger.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/twl4030_charger.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,8 +71,11 @@
 	struct power_supply	usb;
 	struct otg_transceiver	*transceiver;
 	struct notifier_block	otg_nb;
+	struct work_struct	work;
 	int			irq_chg;
 	int			irq_bci;
+
+	unsigned long		event;
 };
 
 /*
@@ -258,14 +261,11 @@
 	return IRQ_HANDLED;
 }
 
-static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
-			       void *priv)
+static void twl4030_bci_usb_work(struct work_struct *data)
 {
-	struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb);
-
-	dev_dbg(bci->dev, "OTG notify %lu\n", val);
+	struct twl4030_bci *bci = container_of(data, struct twl4030_bci, work);
 
-	switch (val) {
+	switch (bci->event) {
 	case USB_EVENT_VBUS:
 	case USB_EVENT_CHARGER:
 		twl4030_charger_enable_usb(bci, true);
@@ -274,6 +274,17 @@
 		twl4030_charger_enable_usb(bci, false);
 		break;
 	}
+}
+
+static int twl4030_bci_usb_ncb(struct notifier_block *nb, unsigned long val,
+			       void *priv)
+{
+	struct twl4030_bci *bci = container_of(nb, struct twl4030_bci, otg_nb);
+
+	dev_dbg(bci->dev, "OTG notify %lu\n", val);
+
+	bci->event = val;
+	schedule_work(&bci->work);
 
 	return NOTIFY_OK;
 }
@@ -466,6 +477,8 @@
 		goto fail_bci_irq;
 	}
 
+	INIT_WORK(&bci->work, twl4030_bci_usb_work);
+
 	bci->transceiver = otg_get_transceiver();
 	if (bci->transceiver != NULL) {
 		bci->otg_nb.notifier_call = twl4030_bci_usb_ncb;
diff -druN linux-libre-2.6.38-gnu/drivers/power/z2_battery.c linux-libre-2.6.39-gnu/drivers/power/z2_battery.c
--- linux-libre-2.6.38-gnu/drivers/power/z2_battery.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/power/z2_battery.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,6 +134,8 @@
 	enum power_supply_property *prop;
 	struct z2_battery_info *info = charger->info;
 
+	if (info->charge_gpio >= 0)
+		props++;	/* POWER_SUPPLY_PROP_STATUS */
 	if (info->batt_tech >= 0)
 		props++;	/* POWER_SUPPLY_PROP_TECHNOLOGY */
 	if (info->batt_I2C_reg >= 0)
@@ -213,8 +215,8 @@
 		if (ret)
 			goto err2;
 
-		set_irq_type(gpio_to_irq(info->charge_gpio),
-				IRQ_TYPE_EDGE_BOTH);
+		irq_set_irq_type(gpio_to_irq(info->charge_gpio),
+				 IRQ_TYPE_EDGE_BOTH);
 		ret = request_irq(gpio_to_irq(info->charge_gpio),
 				z2_charge_switch_irq, IRQF_DISABLED,
 				"AC Detect", charger);
@@ -293,6 +295,7 @@
 	{ "aer915", 0 },
 	{ }
 };
+MODULE_DEVICE_TABLE(i2c, z2_batt_id);
 
 static struct i2c_driver z2_batt_driver = {
 	.driver	= {
diff -druN linux-libre-2.6.38-gnu/drivers/pps/clients/Makefile linux-libre-2.6.39-gnu/drivers/pps/clients/Makefile
--- linux-libre-2.6.38-gnu/drivers/pps/clients/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pps/clients/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -6,6 +6,4 @@
 obj-$(CONFIG_PPS_CLIENT_LDISC)	+= pps-ldisc.o
 obj-$(CONFIG_PPS_CLIENT_PARPORT) += pps_parport.o
 
-ifeq ($(CONFIG_PPS_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+ccflags-$(CONFIG_PPS_DEBUG) := -DDEBUG
diff -druN linux-libre-2.6.38-gnu/drivers/pps/generators/pps_gen_parport.c linux-libre-2.6.39-gnu/drivers/pps/generators/pps_gen_parport.c
--- linux-libre-2.6.38-gnu/drivers/pps/generators/pps_gen_parport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pps/generators/pps_gen_parport.c	2011-05-19 00:06:34.000000000 -0400
@@ -216,11 +216,6 @@
 
 	hrtimer_init(&device.timer, CLOCK_REALTIME, HRTIMER_MODE_ABS);
 	device.timer.function = hrtimer_event;
-#ifdef CONFIG_PREEMPT_RT
-	/* hrtimer interrupt will run in the interrupt context with this */
-	device.timer.irqsafe = 1;
-#endif
-
 	hrtimer_start(&device.timer, next_intr_time(&device), HRTIMER_MODE_ABS);
 
 	return;
diff -druN linux-libre-2.6.38-gnu/drivers/pps/Kconfig linux-libre-2.6.39-gnu/drivers/pps/Kconfig
--- linux-libre-2.6.38-gnu/drivers/pps/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/pps/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -35,7 +35,7 @@
 	depends on PPS && !NO_HZ
 	help
 	  This option adds support for direct in-kernel time
-	  syncronization using an external PPS signal.
+	  synchronization using an external PPS signal.
 
 	  It doesn't work on tickless systems at the moment.
 
diff -druN linux-libre-2.6.38-gnu/drivers/ps3/ps3-lpm.c linux-libre-2.6.39-gnu/drivers/ps3/ps3-lpm.c
--- linux-libre-2.6.38-gnu/drivers/ps3/ps3-lpm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ps3/ps3-lpm.c	2011-05-19 00:06:34.000000000 -0400
@@ -919,7 +919,7 @@
  * @offset: Offset in bytes from the start of the trace buffer.
  * @buf: Copy destination.
  * @count: Maximum count of bytes to copy.
- * @bytes_copied: Pointer to a variable that will recieve the number of
+ * @bytes_copied: Pointer to a variable that will receive the number of
  *  bytes copied to @buf.
  *
  * On error @buf will contain any successfully copied trace buffer data
@@ -974,7 +974,7 @@
  * @offset: Offset in bytes from the start of the trace buffer.
  * @buf: A __user copy destination.
  * @count: Maximum count of bytes to copy.
- * @bytes_copied: Pointer to a variable that will recieve the number of
+ * @bytes_copied: Pointer to a variable that will receive the number of
  *  bytes copied to @buf.
  *
  * On error @buf will contain any successfully copied trace buffer data
@@ -1074,7 +1074,7 @@
 
 /**
  * ps3_lpm_open - Open the logical performance monitor device.
- * @tb_type: Specifies the type of trace buffer lv1 sould use for this lpm
+ * @tb_type: Specifies the type of trace buffer lv1 should use for this lpm
  *  instance, specified by one of enum ps3_lpm_tb_type.
  * @tb_cache: Optional user supplied buffer to use as the trace buffer cache.
  *  If NULL, the driver will allocate and manage an internal buffer.
diff -druN linux-libre-2.6.38-gnu/drivers/ps3/ps3-sys-manager.c linux-libre-2.6.39-gnu/drivers/ps3/ps3-sys-manager.c
--- linux-libre-2.6.38-gnu/drivers/ps3/ps3-sys-manager.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ps3/ps3-sys-manager.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,7 +80,7 @@
  *
  * Currently all messages received from the system manager are either
  * (16 bytes header + 8 bytes payload = 24 bytes) or (16 bytes header
- * + 16 bytes payload = 32 bytes).  This knowlege is used to simplify
+ * + 16 bytes payload = 32 bytes).  This knowledge is used to simplify
  * the logic.
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/Makefile linux-libre-2.6.39-gnu/drivers/rapidio/Makefile
--- linux-libre-2.6.38-gnu/drivers/rapidio/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -5,6 +5,4 @@
 
 obj-$(CONFIG_RAPIDIO)		+= switches/
 
-ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
+subdir-ccflags-$(CONFIG_RAPIDIO_DEBUG) := -DDEBUG
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/rio.c linux-libre-2.6.39-gnu/drivers/rapidio/rio.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/rio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/rio.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 #include "rio.h"
 
 static LIST_HEAD(rio_mports);
+static unsigned char next_portid;
 
 /**
  * rio_local_get_device_id - Get the base/extended device id for a port
@@ -68,9 +69,13 @@
 			 void (*minb) (struct rio_mport * mport, void *dev_id, int mbox,
 				       int slot))
 {
-	int rc = 0;
+	int rc = -ENOSYS;
+	struct resource *res;
 
-	struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+	if (mport->ops->open_inb_mbox == NULL)
+		goto out;
+
+	res = kmalloc(sizeof(struct resource), GFP_KERNEL);
 
 	if (res) {
 		rio_init_mbox_res(res, mbox, mbox);
@@ -88,7 +93,7 @@
 		/* Hook the inbound message callback */
 		mport->inb_msg[mbox].mcback = minb;
 
-		rc = rio_open_inb_mbox(mport, dev_id, mbox, entries);
+		rc = mport->ops->open_inb_mbox(mport, dev_id, mbox, entries);
 	} else
 		rc = -ENOMEM;
 
@@ -106,10 +111,13 @@
  */
 int rio_release_inb_mbox(struct rio_mport *mport, int mbox)
 {
-	rio_close_inb_mbox(mport, mbox);
+	if (mport->ops->close_inb_mbox) {
+		mport->ops->close_inb_mbox(mport, mbox);
 
-	/* Release the mailbox resource */
-	return release_resource(mport->inb_msg[mbox].res);
+		/* Release the mailbox resource */
+		return release_resource(mport->inb_msg[mbox].res);
+	} else
+		return -ENOSYS;
 }
 
 /**
@@ -129,9 +137,13 @@
 			  int entries,
 			  void (*moutb) (struct rio_mport * mport, void *dev_id, int mbox, int slot))
 {
-	int rc = 0;
+	int rc = -ENOSYS;
+	struct resource *res;
 
-	struct resource *res = kmalloc(sizeof(struct resource), GFP_KERNEL);
+	if (mport->ops->open_outb_mbox == NULL)
+		goto out;
+
+	res = kmalloc(sizeof(struct resource), GFP_KERNEL);
 
 	if (res) {
 		rio_init_mbox_res(res, mbox, mbox);
@@ -149,7 +161,7 @@
 		/* Hook the inbound message callback */
 		mport->outb_msg[mbox].mcback = moutb;
 
-		rc = rio_open_outb_mbox(mport, dev_id, mbox, entries);
+		rc = mport->ops->open_outb_mbox(mport, dev_id, mbox, entries);
 	} else
 		rc = -ENOMEM;
 
@@ -167,10 +179,13 @@
  */
 int rio_release_outb_mbox(struct rio_mport *mport, int mbox)
 {
-	rio_close_outb_mbox(mport, mbox);
+	if (mport->ops->close_outb_mbox) {
+		mport->ops->close_outb_mbox(mport, mbox);
 
-	/* Release the mailbox resource */
-	return release_resource(mport->outb_msg[mbox].res);
+		/* Release the mailbox resource */
+		return release_resource(mport->outb_msg[mbox].res);
+	} else
+		return -ENOSYS;
 }
 
 /**
@@ -1120,37 +1135,53 @@
 	return 0;
 }
 
-device_initcall(rio_init);
-
 int __devinit rio_init_mports(void)
 {
-	int rc = 0;
 	struct rio_mport *port;
 
 	list_for_each_entry(port, &rio_mports, node) {
-		if (!request_mem_region(port->iores.start,
-					resource_size(&port->iores),
-					port->name)) {
-			printk(KERN_ERR
-			       "RIO: Error requesting master port region 0x%016llx-0x%016llx\n",
-			       (u64)port->iores.start, (u64)port->iores.end);
-			rc = -ENOMEM;
-			goto out;
-		}
-
 		if (port->host_deviceid >= 0)
 			rio_enum_mport(port);
 		else
 			rio_disc_mport(port);
 	}
 
-      out:
-	return rc;
+	rio_init();
+
+	return 0;
 }
 
-void rio_register_mport(struct rio_mport *port)
+device_initcall_sync(rio_init_mports);
+
+static int hdids[RIO_MAX_MPORTS + 1];
+
+static int rio_get_hdid(int index)
 {
+	if (!hdids[0] || hdids[0] <= index || index >= RIO_MAX_MPORTS)
+		return -1;
+
+	return hdids[index + 1];
+}
+
+static int rio_hdid_setup(char *str)
+{
+	(void)get_options(str, ARRAY_SIZE(hdids), hdids);
+	return 1;
+}
+
+__setup("riohdid=", rio_hdid_setup);
+
+int rio_register_mport(struct rio_mport *port)
+{
+	if (next_portid >= RIO_MAX_MPORTS) {
+		pr_err("RIO: reached specified max number of mports\n");
+		return 1;
+	}
+
+	port->id = next_portid++;
+	port->host_deviceid = rio_get_hdid(port->id);
 	list_add_tail(&port->node, &rio_mports);
+	return 0;
 }
 
 EXPORT_SYMBOL_GPL(rio_local_get_device_id);
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/rio-scan.c linux-libre-2.6.39-gnu/drivers/rapidio/rio-scan.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/rio-scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/rio-scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -295,7 +295,7 @@
 }
 
 /**
- * rio_enable_rx_tx_port - enable input reciever and output transmitter of
+ * rio_enable_rx_tx_port - enable input receiver and output transmitter of
  * given port
  * @port: Master port associated with the RIO network
  * @local: local=1 select local port otherwise a far device is reached
@@ -517,7 +517,7 @@
 	return rdev;
 
 cleanup:
-	if (rswitch->route_table)
+	if (rio_is_switch(rdev))
 		kfree(rswitch->route_table);
 
 	kfree(rdev);
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/rio-sysfs.c linux-libre-2.6.39-gnu/drivers/rapidio/rio-sysfs.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/rio-sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/rio-sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -14,6 +14,7 @@
 #include <linux/rio.h>
 #include <linux/rio_drv.h>
 #include <linux/stat.h>
+#include <linux/capability.h>
 
 #include "rio.h"
 
@@ -33,6 +34,8 @@
 rio_config_attr(asm_did, "0x%04x\n");
 rio_config_attr(asm_vid, "0x%04x\n");
 rio_config_attr(asm_rev, "0x%04x\n");
+rio_config_attr(destid, "0x%04x\n");
+rio_config_attr(hopcount, "0x%02x\n");
 
 static ssize_t routes_show(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -52,6 +55,35 @@
 	return (str - buf);
 }
 
+static ssize_t lprev_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct rio_dev *rdev = to_rio_dev(dev);
+
+	return sprintf(buf, "%s\n",
+			(rdev->prev) ? rio_name(rdev->prev) : "root");
+}
+
+static ssize_t lnext_show(struct device *dev,
+			  struct device_attribute *attr, char *buf)
+{
+	struct rio_dev *rdev = to_rio_dev(dev);
+	char *str = buf;
+	int i;
+
+	if (rdev->pef & RIO_PEF_SWITCH) {
+		for (i = 0; i < RIO_GET_TOTAL_PORTS(rdev->swpinfo); i++) {
+			if (rdev->rswitch->nextdev[i])
+				str += sprintf(str, "%s\n",
+					rio_name(rdev->rswitch->nextdev[i]));
+			else
+				str += sprintf(str, "null\n");
+		}
+	}
+
+	return str - buf;
+}
+
 struct device_attribute rio_dev_attrs[] = {
 	__ATTR_RO(did),
 	__ATTR_RO(vid),
@@ -59,10 +91,14 @@
 	__ATTR_RO(asm_did),
 	__ATTR_RO(asm_vid),
 	__ATTR_RO(asm_rev),
+	__ATTR_RO(lprev),
+	__ATTR_RO(destid),
 	__ATTR_NULL,
 };
 
 static DEVICE_ATTR(routes, S_IRUGO, routes_show, NULL);
+static DEVICE_ATTR(lnext, S_IRUGO, lnext_show, NULL);
+static DEVICE_ATTR(hopcount, S_IRUGO, hopcount_show, NULL);
 
 static ssize_t
 rio_read_config(struct file *filp, struct kobject *kobj,
@@ -218,7 +254,9 @@
 	err = device_create_bin_file(&rdev->dev, &rio_config_attr);
 
 	if (!err && (rdev->pef & RIO_PEF_SWITCH)) {
-		err = device_create_file(&rdev->dev, &dev_attr_routes);
+		err |= device_create_file(&rdev->dev, &dev_attr_routes);
+		err |= device_create_file(&rdev->dev, &dev_attr_lnext);
+		err |= device_create_file(&rdev->dev, &dev_attr_hopcount);
 		if (!err && rdev->rswitch->sw_sysfs)
 			err = rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_CREATE);
 	}
@@ -241,6 +279,8 @@
 	device_remove_bin_file(&rdev->dev, &rio_config_attr);
 	if (rdev->pef & RIO_PEF_SWITCH) {
 		device_remove_file(&rdev->dev, &dev_attr_routes);
+		device_remove_file(&rdev->dev, &dev_attr_lnext);
+		device_remove_file(&rdev->dev, &dev_attr_hopcount);
 		if (rdev->rswitch->sw_sysfs)
 			rdev->rswitch->sw_sysfs(rdev, RIO_SW_SYSFS_REMOVE);
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/idtcps.c linux-libre-2.6.39-gnu/drivers/rapidio/switches/idtcps.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/idtcps.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/switches/idtcps.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,6 +26,9 @@
 {
 	u32 result;
 
+	if (route_port == RIO_INVALID_ROUTE)
+		route_port = CPS_DEFAULT_ROUTE;
+
 	if (table == RIO_GLOBAL_TABLE) {
 		rio_mport_write_config_32(mport, destid, hopcount,
 				RIO_STD_RTE_CONF_DESTID_SEL_CSR, route_destid);
@@ -130,6 +133,9 @@
 		/* set TVAL = ~50us */
 		rio_write_config_32(rdev,
 			rdev->phys_efptr + RIO_PORT_LINKTO_CTL_CSR, 0x8e << 8);
+		/* Ensure that default routing is disabled on startup */
+		rio_write_config_32(rdev,
+				    RIO_STD_RTE_DEFAULT_PORT, CPS_NO_ROUTE);
 	}
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/idt_gen2.c linux-libre-2.6.39-gnu/drivers/rapidio/switches/idt_gen2.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/idt_gen2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/switches/idt_gen2.c	2011-05-19 00:06:34.000000000 -0400
@@ -95,6 +95,9 @@
 	else
 		table++;
 
+	if (route_port == RIO_INVALID_ROUTE)
+		route_port = IDT_DEFAULT_ROUTE;
+
 	rio_mport_write_config_32(mport, destid, hopcount,
 				  LOCAL_RTE_CONF_DESTID_SEL, table);
 
@@ -411,6 +414,12 @@
 	rdev->rswitch->em_handle = idtg2_em_handler;
 	rdev->rswitch->sw_sysfs = idtg2_sysfs;
 
+	if (do_enum) {
+		/* Ensure that default routing is disabled on startup */
+		rio_write_config_32(rdev,
+				    RIO_STD_RTE_DEFAULT_PORT, IDT_NO_ROUTE);
+	}
+
 	return 0;
 }
 
@@ -418,3 +427,4 @@
 DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1616, idtg2_switch_init);
 DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTVPS1616, idtg2_switch_init);
 DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTSPS1616, idtg2_switch_init);
+DECLARE_RIO_SWITCH_INIT(RIO_VID_IDT, RIO_DID_IDTCPS1432, idtg2_switch_init);
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/Makefile linux-libre-2.6.39-gnu/drivers/rapidio/switches/Makefile
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/switches/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -7,7 +7,3 @@
 obj-$(CONFIG_RAPIDIO_TSI568)	+= tsi568.o
 obj-$(CONFIG_RAPIDIO_TSI500)	+= tsi500.o
 obj-$(CONFIG_RAPIDIO_CPS_GEN2)	+= idt_gen2.o
-
-ifeq ($(CONFIG_RAPIDIO_DEBUG),y)
-EXTRA_CFLAGS += -DDEBUG
-endif
diff -druN linux-libre-2.6.38-gnu/drivers/rapidio/switches/tsi57x.c linux-libre-2.6.39-gnu/drivers/rapidio/switches/tsi57x.c
--- linux-libre-2.6.38-gnu/drivers/rapidio/switches/tsi57x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rapidio/switches/tsi57x.c	2011-05-19 00:06:34.000000000 -0400
@@ -303,6 +303,12 @@
 	rdev->rswitch->em_init = tsi57x_em_init;
 	rdev->rswitch->em_handle = tsi57x_em_handler;
 
+	if (do_enum) {
+		/* Ensure that default routing is disabled on startup */
+		rio_write_config_32(rdev, RIO_STD_RTE_DEFAULT_PORT,
+				    RIO_INVALID_ROUTE);
+	}
+
 	return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/88pm8607.c linux-libre-2.6.39-gnu/drivers/regulator/88pm8607.c
--- linux-libre-2.6.38-gnu/drivers/regulator/88pm8607.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/88pm8607.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/mfd/core.h>
 #include <linux/mfd/88pm860x.h>
 
 struct pm8607_regulator_info {
@@ -394,47 +395,48 @@
 	PM8607_LDO(14,        LDO14, 0, 4, SUPPLIES_EN12, 6),
 };
 
-static inline struct pm8607_regulator_info *find_regulator_info(int id)
+static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
 {
-	struct pm8607_regulator_info *info;
+	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
+	struct pm8607_regulator_info *info = NULL;
+	struct regulator_init_data *pdata;
+	struct mfd_cell *cell;
 	int i;
 
+	cell = pdev->dev.platform_data;
+	if (cell == NULL)
+		return -ENODEV;
+	pdata = cell->mfd_data;
+	if (pdata == NULL)
+		return -EINVAL;
+
 	for (i = 0; i < ARRAY_SIZE(pm8607_regulator_info); i++) {
 		info = &pm8607_regulator_info[i];
-		if (info->desc.id == id)
-			return info;
+		if (!strcmp(info->desc.name, pdata->constraints.name))
+			break;
 	}
-	return NULL;
-}
-
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
-{
-	struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
-	struct pm860x_platform_data *pdata = chip->dev->platform_data;
-	struct pm8607_regulator_info *info = NULL;
-
-	info = find_regulator_info(pdev->id);
-	if (info == NULL) {
-		dev_err(&pdev->dev, "invalid regulator ID specified\n");
+	if (i > ARRAY_SIZE(pm8607_regulator_info)) {
+		dev_err(&pdev->dev, "Failed to find regulator %s\n",
+			pdata->constraints.name);
 		return -EINVAL;
 	}
 
 	info->i2c = (chip->id == CHIP_PM8607) ? chip->client : chip->companion;
 	info->chip = chip;
 
+	/* check DVC ramp slope double */
+	if (!strcmp(info->desc.name, "BUCK3"))
+		if (info->chip->buck3_double)
+			info->slope_double = 1;
+
 	info->regulator = regulator_register(&info->desc, &pdev->dev,
-					     pdata->regulator[pdev->id], info);
+					     pdata, info);
 	if (IS_ERR(info->regulator)) {
 		dev_err(&pdev->dev, "failed to register regulator %s\n",
 			info->desc.name);
 		return PTR_ERR(info->regulator);
 	}
 
-	/* check DVC ramp slope double */
-	if (info->desc.id == PM8607_ID_BUCK3)
-		if (info->chip->buck3_double)
-			info->slope_double = 1;
-
 	platform_set_drvdata(pdev, info);
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/ab3100.c linux-libre-2.6.39-gnu/drivers/regulator/ab3100.c
--- linux-libre-2.6.38-gnu/drivers/regulator/ab3100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/ab3100.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,6 +17,7 @@
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/mfd/abx500.h>
+#include <linux/mfd/core.h>
 
 /* LDO registers and some handy masking definitions for AB3100 */
 #define AB3100_LDO_A		0x40
@@ -205,29 +206,6 @@
 		return err;
 	}
 
-	/* Per-regulator power on delay from spec */
-	switch (abreg->regreg) {
-	case AB3100_LDO_A: /* Fallthrough */
-	case AB3100_LDO_C: /* Fallthrough */
-	case AB3100_LDO_D: /* Fallthrough */
-	case AB3100_LDO_E: /* Fallthrough */
-	case AB3100_LDO_H: /* Fallthrough */
-	case AB3100_LDO_K:
-		udelay(200);
-		break;
-	case AB3100_LDO_F:
-		udelay(600);
-		break;
-	case AB3100_LDO_G:
-		udelay(400);
-		break;
-	case AB3100_BUCK:
-		mdelay(1);
-		break;
-	default:
-		break;
-	}
-
 	return 0;
 }
 
@@ -449,11 +427,37 @@
 	return abreg->plfdata->external_voltage;
 }
 
+static int ab3100_enable_time_regulator(struct regulator_dev *reg)
+{
+	struct ab3100_regulator *abreg = reg->reg_data;
+
+	/* Per-regulator power on delay from spec */
+	switch (abreg->regreg) {
+	case AB3100_LDO_A: /* Fallthrough */
+	case AB3100_LDO_C: /* Fallthrough */
+	case AB3100_LDO_D: /* Fallthrough */
+	case AB3100_LDO_E: /* Fallthrough */
+	case AB3100_LDO_H: /* Fallthrough */
+	case AB3100_LDO_K:
+		return 200;
+	case AB3100_LDO_F:
+		return 600;
+	case AB3100_LDO_G:
+		return 400;
+	case AB3100_BUCK:
+		return 1000;
+	default:
+		break;
+	}
+	return 0;
+}
+
 static struct regulator_ops regulator_ops_fixed = {
 	.enable      = ab3100_enable_regulator,
 	.disable     = ab3100_disable_regulator,
 	.is_enabled  = ab3100_is_enabled_regulator,
 	.get_voltage = ab3100_get_voltage_regulator,
+	.enable_time = ab3100_enable_time_regulator,
 };
 
 static struct regulator_ops regulator_ops_variable = {
@@ -463,6 +467,7 @@
 	.get_voltage = ab3100_get_voltage_regulator,
 	.set_voltage = ab3100_set_voltage_regulator,
 	.list_voltage = ab3100_list_voltage_regulator,
+	.enable_time = ab3100_enable_time_regulator,
 };
 
 static struct regulator_ops regulator_ops_variable_sleepable = {
@@ -473,6 +478,7 @@
 	.set_voltage = ab3100_set_voltage_regulator,
 	.set_suspend_voltage = ab3100_set_suspend_voltage_regulator,
 	.list_voltage = ab3100_list_voltage_regulator,
+	.enable_time = ab3100_enable_time_regulator,
 };
 
 /*
@@ -576,7 +582,7 @@
 
 static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
 {
-	struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
+	struct ab3100_platform_data *plfdata = mfd_get_data(pdev);
 	int err = 0;
 	u8 data;
 	int i;
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/ab8500.c linux-libre-2.6.39-gnu/drivers/regulator/ab8500.c
--- linux-libre-2.6.38-gnu/drivers/regulator/ab8500.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/ab8500.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,7 +9,7 @@
  * AB8500 peripheral regulators
  *
  * AB8500 supports the following regulators:
- *   VAUX1/2/3, VINTCORE, VTVOUT, VAUDIO, VAMIC1/2, VDMIC, VANA
+ *   VAUX1/2/3, VINTCORE, VTVOUT, VUSB, VAUDIO, VAMIC1/2, VDMIC, VANA
  */
 #include <linux/init.h>
 #include <linux/kernel.h>
@@ -38,6 +38,7 @@
  * @voltage_mask: mask to control regulator voltage
  * @voltages: supported voltage table
  * @voltages_len: number of supported voltages for the regulator
+ * @delay: startup/set voltage delay in us
  */
 struct ab8500_regulator_info {
 	struct device		*dev;
@@ -55,6 +56,7 @@
 	u8 voltage_mask;
 	int const *voltages;
 	int voltages_len;
+	unsigned int delay;
 };
 
 /* voltage tables for the vauxn/vintcore supplies */
@@ -290,6 +292,29 @@
 	return ret;
 }
 
+static int ab8500_regulator_enable_time(struct regulator_dev *rdev)
+{
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+
+	return info->delay;
+}
+
+static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev,
+					     unsigned int old_sel,
+					     unsigned int new_sel)
+{
+	struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
+	int ret;
+
+	/* If the regulator isn't on, it won't take time here */
+	ret = ab8500_regulator_is_enabled(rdev);
+	if (ret < 0)
+		return ret;
+	if (!ret)
+		return 0;
+	return info->delay;
+}
+
 static struct regulator_ops ab8500_regulator_ops = {
 	.enable		= ab8500_regulator_enable,
 	.disable	= ab8500_regulator_disable,
@@ -297,6 +322,8 @@
 	.get_voltage	= ab8500_regulator_get_voltage,
 	.set_voltage	= ab8500_regulator_set_voltage,
 	.list_voltage	= ab8500_list_voltage,
+	.enable_time	= ab8500_regulator_enable_time,
+	.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static int ab8500_fixed_get_voltage(struct regulator_dev *rdev)
@@ -317,6 +344,8 @@
 	.is_enabled	= ab8500_regulator_is_enabled,
 	.get_voltage	= ab8500_fixed_get_voltage,
 	.list_voltage	= ab8500_list_voltage,
+	.enable_time	= ab8500_regulator_enable_time,
+	.set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel,
 };
 
 static struct ab8500_regulator_info
@@ -426,12 +455,28 @@
 			.owner		= THIS_MODULE,
 			.n_voltages	= 1,
 		},
+		.delay			= 10000,
 		.fixed_uV		= 2000000,
 		.update_bank		= 0x03,
 		.update_reg		= 0x80,
 		.update_mask		= 0x82,
 		.update_val_enable	= 0x02,
 	},
+	[AB8500_LDO_USB] = {
+		.desc = {
+			.name           = "LDO-USB",
+			.ops            = &ab8500_regulator_fixed_ops,
+			.type           = REGULATOR_VOLTAGE,
+			.id             = AB8500_LDO_USB,
+			.owner          = THIS_MODULE,
+			.n_voltages     = 1,
+		},
+		.fixed_uV               = 3300000,
+		.update_bank            = 0x03,
+		.update_reg             = 0x82,
+		.update_mask            = 0x03,
+		.update_val_enable      = 0x01,
+	},
 	[AB8500_LDO_AUDIO] = {
 		.desc = {
 			.name		= "LDO-AUDIO",
@@ -511,6 +556,186 @@
 
 };
 
+struct ab8500_reg_init {
+	u8 bank;
+	u8 addr;
+	u8 mask;
+};
+
+#define REG_INIT(_id, _bank, _addr, _mask)	\
+	[_id] = {				\
+		.bank = _bank,			\
+		.addr = _addr,			\
+		.mask = _mask,			\
+	}
+
+static struct ab8500_reg_init ab8500_reg_init[] = {
+	/*
+	 * 0x30, VanaRequestCtrl
+	 * 0x0C, VpllRequestCtrl
+	 * 0xc0, VextSupply1RequestCtrl
+	 */
+	REG_INIT(AB8500_REGUREQUESTCTRL2,	0x03, 0x04, 0xfc),
+	/*
+	 * 0x03, VextSupply2RequestCtrl
+	 * 0x0c, VextSupply3RequestCtrl
+	 * 0x30, Vaux1RequestCtrl
+	 * 0xc0, Vaux2RequestCtrl
+	 */
+	REG_INIT(AB8500_REGUREQUESTCTRL3,	0x03, 0x05, 0xff),
+	/*
+	 * 0x03, Vaux3RequestCtrl
+	 * 0x04, SwHPReq
+	 */
+	REG_INIT(AB8500_REGUREQUESTCTRL4,	0x03, 0x06, 0x07),
+	/*
+	 * 0x08, VanaSysClkReq1HPValid
+	 * 0x20, Vaux1SysClkReq1HPValid
+	 * 0x40, Vaux2SysClkReq1HPValid
+	 * 0x80, Vaux3SysClkReq1HPValid
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID1,	0x03, 0x07, 0xe8),
+	/*
+	 * 0x10, VextSupply1SysClkReq1HPValid
+	 * 0x20, VextSupply2SysClkReq1HPValid
+	 * 0x40, VextSupply3SysClkReq1HPValid
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQ1HPVALID2,	0x03, 0x08, 0x70),
+	/*
+	 * 0x08, VanaHwHPReq1Valid
+	 * 0x20, Vaux1HwHPReq1Valid
+	 * 0x40, Vaux2HwHPReq1Valid
+	 * 0x80, Vaux3HwHPReq1Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ1VALID1,	0x03, 0x09, 0xe8),
+	/*
+	 * 0x01, VextSupply1HwHPReq1Valid
+	 * 0x02, VextSupply2HwHPReq1Valid
+	 * 0x04, VextSupply3HwHPReq1Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ1VALID2,	0x03, 0x0a, 0x07),
+	/*
+	 * 0x08, VanaHwHPReq2Valid
+	 * 0x20, Vaux1HwHPReq2Valid
+	 * 0x40, Vaux2HwHPReq2Valid
+	 * 0x80, Vaux3HwHPReq2Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ2VALID1,	0x03, 0x0b, 0xe8),
+	/*
+	 * 0x01, VextSupply1HwHPReq2Valid
+	 * 0x02, VextSupply2HwHPReq2Valid
+	 * 0x04, VextSupply3HwHPReq2Valid
+	 */
+	REG_INIT(AB8500_REGUHWHPREQ2VALID2,	0x03, 0x0c, 0x07),
+	/*
+	 * 0x20, VanaSwHPReqValid
+	 * 0x80, Vaux1SwHPReqValid
+	 */
+	REG_INIT(AB8500_REGUSWHPREQVALID1,	0x03, 0x0d, 0xa0),
+	/*
+	 * 0x01, Vaux2SwHPReqValid
+	 * 0x02, Vaux3SwHPReqValid
+	 * 0x04, VextSupply1SwHPReqValid
+	 * 0x08, VextSupply2SwHPReqValid
+	 * 0x10, VextSupply3SwHPReqValid
+	 */
+	REG_INIT(AB8500_REGUSWHPREQVALID2,	0x03, 0x0e, 0x1f),
+	/*
+	 * 0x02, SysClkReq2Valid1
+	 * ...
+	 * 0x80, SysClkReq8Valid1
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQVALID1,	0x03, 0x0f, 0xfe),
+	/*
+	 * 0x02, SysClkReq2Valid2
+	 * ...
+	 * 0x80, SysClkReq8Valid2
+	 */
+	REG_INIT(AB8500_REGUSYSCLKREQVALID2,	0x03, 0x10, 0xfe),
+	/*
+	 * 0x02, VTVoutEna
+	 * 0x04, Vintcore12Ena
+	 * 0x38, Vintcore12Sel
+	 * 0x40, Vintcore12LP
+	 * 0x80, VTVoutLP
+	 */
+	REG_INIT(AB8500_REGUMISC1,		0x03, 0x80, 0xfe),
+	/*
+	 * 0x02, VaudioEna
+	 * 0x04, VdmicEna
+	 * 0x08, Vamic1Ena
+	 * 0x10, Vamic2Ena
+	 */
+	REG_INIT(AB8500_VAUDIOSUPPLY,		0x03, 0x83, 0x1e),
+	/*
+	 * 0x01, Vamic1_dzout
+	 * 0x02, Vamic2_dzout
+	 */
+	REG_INIT(AB8500_REGUCTRL1VAMIC,		0x03, 0x84, 0x03),
+	/*
+	 * 0x0c, VanaRegu
+	 * 0x03, VpllRegu
+	 */
+	REG_INIT(AB8500_VPLLVANAREGU,		0x04, 0x06, 0x0f),
+	/*
+	 * 0x01, VrefDDREna
+	 * 0x02, VrefDDRSleepMode
+	 */
+	REG_INIT(AB8500_VREFDDR,		0x04, 0x07, 0x03),
+	/*
+	 * 0x03, VextSupply1Regu
+	 * 0x0c, VextSupply2Regu
+	 * 0x30, VextSupply3Regu
+	 * 0x40, ExtSupply2Bypass
+	 * 0x80, ExtSupply3Bypass
+	 */
+	REG_INIT(AB8500_EXTSUPPLYREGU,		0x04, 0x08, 0xff),
+	/*
+	 * 0x03, Vaux1Regu
+	 * 0x0c, Vaux2Regu
+	 */
+	REG_INIT(AB8500_VAUX12REGU,		0x04, 0x09, 0x0f),
+	/*
+	 * 0x03, Vaux3Regu
+	 */
+	REG_INIT(AB8500_VRF1VAUX3REGU,		0x04, 0x0a, 0x03),
+	/*
+	 * 0x3f, Vsmps1Sel1
+	 */
+	REG_INIT(AB8500_VSMPS1SEL1,		0x04, 0x13, 0x3f),
+	/*
+	 * 0x0f, Vaux1Sel
+	 */
+	REG_INIT(AB8500_VAUX1SEL,		0x04, 0x1f, 0x0f),
+	/*
+	 * 0x0f, Vaux2Sel
+	 */
+	REG_INIT(AB8500_VAUX2SEL,		0x04, 0x20, 0x0f),
+	/*
+	 * 0x07, Vaux3Sel
+	 */
+	REG_INIT(AB8500_VRF1VAUX3SEL,		0x04, 0x21, 0x07),
+	/*
+	 * 0x01, VextSupply12LP
+	 */
+	REG_INIT(AB8500_REGUCTRL2SPARE,		0x04, 0x22, 0x01),
+	/*
+	 * 0x04, Vaux1Disch
+	 * 0x08, Vaux2Disch
+	 * 0x10, Vaux3Disch
+	 * 0x20, Vintcore12Disch
+	 * 0x40, VTVoutDisch
+	 * 0x80, VaudioDisch
+	 */
+	REG_INIT(AB8500_REGUCTRLDISCH,		0x04, 0x43, 0xfc),
+	/*
+	 * 0x02, VanaDisch
+	 * 0x04, VdmicPullDownEna
+	 * 0x10, VdmicDisch
+	 */
+	REG_INIT(AB8500_REGUCTRLDISCH2,		0x04, 0x44, 0x16),
+};
+
 static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
 {
 	struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
@@ -529,10 +754,51 @@
 
 	/* make sure the platform data has the correct size */
 	if (pdata->num_regulator != ARRAY_SIZE(ab8500_regulator_info)) {
-		dev_err(&pdev->dev, "platform configuration error\n");
+		dev_err(&pdev->dev, "Configuration error: size mismatch.\n");
 		return -EINVAL;
 	}
 
+	/* initialize registers */
+	for (i = 0; i < pdata->num_regulator_reg_init; i++) {
+		int id;
+		u8 value;
+
+		id = pdata->regulator_reg_init[i].id;
+		value = pdata->regulator_reg_init[i].value;
+
+		/* check for configuration errors */
+		if (id >= AB8500_NUM_REGULATOR_REGISTERS) {
+			dev_err(&pdev->dev,
+				"Configuration error: id outside range.\n");
+			return -EINVAL;
+		}
+		if (value & ~ab8500_reg_init[id].mask) {
+			dev_err(&pdev->dev,
+				"Configuration error: value outside mask.\n");
+			return -EINVAL;
+		}
+
+		/* initialize register */
+		err = abx500_mask_and_set_register_interruptible(&pdev->dev,
+			ab8500_reg_init[id].bank,
+			ab8500_reg_init[id].addr,
+			ab8500_reg_init[id].mask,
+			value);
+		if (err < 0) {
+			dev_err(&pdev->dev,
+				"Failed to initialize 0x%02x, 0x%02x.\n",
+				ab8500_reg_init[id].bank,
+				ab8500_reg_init[id].addr);
+			return err;
+		}
+		dev_vdbg(&pdev->dev,
+			"  init: 0x%02x, 0x%02x, 0x%02x, 0x%02x\n",
+			ab8500_reg_init[id].bank,
+			ab8500_reg_init[id].addr,
+			ab8500_reg_init[id].mask,
+			value);
+	}
+
 	/* register all regulators */
 	for (i = 0; i < ARRAY_SIZE(ab8500_regulator_info); i++) {
 		struct ab8500_regulator_info *info = NULL;
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/core.c linux-libre-2.6.39-gnu/drivers/regulator/core.c
--- linux-libre-2.6.38-gnu/drivers/regulator/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -1313,7 +1313,7 @@
 				return -EINVAL;
 
 			/* Query before enabling in case configuration
-			 * dependant.  */
+			 * dependent.  */
 			ret = _regulator_get_enable_time(rdev);
 			if (ret >= 0) {
 				delay = ret;
@@ -1629,6 +1629,7 @@
 				     int min_uV, int max_uV)
 {
 	int ret;
+	int delay = 0;
 	unsigned int selector;
 
 	trace_regulator_set_voltage(rdev_get_name(rdev), min_uV, max_uV);
@@ -1662,6 +1663,22 @@
 			}
 		}
 
+		/*
+		 * If we can't obtain the old selector there is not enough
+		 * info to call set_voltage_time_sel().
+		 */
+		if (rdev->desc->ops->set_voltage_time_sel &&
+		    rdev->desc->ops->get_voltage_sel) {
+			unsigned int old_selector = 0;
+
+			ret = rdev->desc->ops->get_voltage_sel(rdev);
+			if (ret < 0)
+				return ret;
+			old_selector = ret;
+			delay = rdev->desc->ops->set_voltage_time_sel(rdev,
+						old_selector, selector);
+		}
+
 		if (best_val != INT_MAX) {
 			ret = rdev->desc->ops->set_voltage_sel(rdev, selector);
 			selector = best_val;
@@ -1672,6 +1689,14 @@
 		ret = -EINVAL;
 	}
 
+	/* Insert any necessary delays */
+	if (delay >= 1000) {
+		mdelay(delay / 1000);
+		udelay(delay % 1000);
+	} else if (delay) {
+		udelay(delay);
+	}
+
 	if (ret == 0)
 		_notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE,
 				     NULL);
@@ -1740,6 +1765,51 @@
 EXPORT_SYMBOL_GPL(regulator_set_voltage);
 
 /**
+ * regulator_set_voltage_time - get raise/fall time
+ * @regulator: regulator source
+ * @old_uV: starting voltage in microvolts
+ * @new_uV: target voltage in microvolts
+ *
+ * Provided with the starting and ending voltage, this function attempts to
+ * calculate the time in microseconds required to rise or fall to this new
+ * voltage.
+ */
+int regulator_set_voltage_time(struct regulator *regulator,
+			       int old_uV, int new_uV)
+{
+	struct regulator_dev	*rdev = regulator->rdev;
+	struct regulator_ops	*ops = rdev->desc->ops;
+	int old_sel = -1;
+	int new_sel = -1;
+	int voltage;
+	int i;
+
+	/* Currently requires operations to do this */
+	if (!ops->list_voltage || !ops->set_voltage_time_sel
+	    || !rdev->desc->n_voltages)
+		return -EINVAL;
+
+	for (i = 0; i < rdev->desc->n_voltages; i++) {
+		/* We only look for exact voltage matches here */
+		voltage = regulator_list_voltage(regulator, i);
+		if (voltage < 0)
+			return -EINVAL;
+		if (voltage == 0)
+			continue;
+		if (voltage == old_uV)
+			old_sel = i;
+		if (voltage == new_uV)
+			new_sel = i;
+	}
+
+	if (old_sel < 0 || new_sel < 0)
+		return -EINVAL;
+
+	return ops->set_voltage_time_sel(rdev, old_sel, new_sel);
+}
+EXPORT_SYMBOL_GPL(regulator_set_voltage_time);
+
+/**
  * regulator_sync_voltage - re-apply last regulator output voltage
  * @regulator: regulator source
  *
@@ -2565,8 +2635,11 @@
 			init_data->consumer_supplies[i].dev,
 			init_data->consumer_supplies[i].dev_name,
 			init_data->consumer_supplies[i].supply);
-		if (ret < 0)
+		if (ret < 0) {
+			dev_err(dev, "Failed to set supply %s\n",
+				init_data->consumer_supplies[i].supply);
 			goto unset_supplies;
+		}
 	}
 
 	list_add(&rdev->list, &regulator_list);
@@ -2653,6 +2726,47 @@
 EXPORT_SYMBOL_GPL(regulator_suspend_prepare);
 
 /**
+ * regulator_suspend_finish - resume regulators from system wide suspend
+ *
+ * Turn on regulators that might be turned off by regulator_suspend_prepare
+ * and that should be turned on according to the regulators properties.
+ */
+int regulator_suspend_finish(void)
+{
+	struct regulator_dev *rdev;
+	int ret = 0, error;
+
+	mutex_lock(&regulator_list_mutex);
+	list_for_each_entry(rdev, &regulator_list, list) {
+		struct regulator_ops *ops = rdev->desc->ops;
+
+		mutex_lock(&rdev->mutex);
+		if ((rdev->use_count > 0  || rdev->constraints->always_on) &&
+				ops->enable) {
+			error = ops->enable(rdev);
+			if (error)
+				ret = error;
+		} else {
+			if (!has_full_constraints)
+				goto unlock;
+			if (!ops->disable)
+				goto unlock;
+			if (ops->is_enabled && !ops->is_enabled(rdev))
+				goto unlock;
+
+			error = ops->disable(rdev);
+			if (error)
+				ret = error;
+		}
+unlock:
+		mutex_unlock(&rdev->mutex);
+	}
+	mutex_unlock(&regulator_list_mutex);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(regulator_suspend_finish);
+
+/**
  * regulator_has_full_constraints - the system has fully specified constraints
  *
  * Calling this function will cause the regulator API to disable all
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/Kconfig linux-libre-2.6.39-gnu/drivers/regulator/Kconfig
--- linux-libre-2.6.38-gnu/drivers/regulator/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -108,6 +108,15 @@
 	  via I2C bus. Maxim 8952 has one voltage output and supports 4 DVS
 	  modes ranging from 0.77V to 1.40V by 0.01V steps.
 
+config REGULATOR_MAX8997
+	tristate "Maxim 8997/8966 regulator"
+	depends on MFD_MAX8997
+	help
+	  This driver controls a Maxim 8997/8966 regulator
+	  via I2C bus. The provided regulator is suitable for S5PC110,
+	  S5PV210, and Exynos-4 chips to control VCC_CORE and
+	  VCC_USIM voltages.
+
 config REGULATOR_MAX8998
 	tristate "Maxim 8998 voltage regulator"
 	depends on MFD_MAX8998
@@ -117,7 +126,7 @@
 	  and S5PC1XX chips to control VCC_CORE and VCC_USIM voltages.
 
 config REGULATOR_TWL4030
-	bool "TI TWL4030/TWL5030/TWL6030/TPS695x0 PMIC"
+	bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
 	depends on TWL4030_CORE
 	help
 	  This driver supports the voltage regulators provided by
@@ -214,6 +223,15 @@
 	 AB3100 analog baseband dealing with power regulators
 	 for the system.
 
+config REGULATOR_TPS6105X
+	tristate "TI TPS6105X Power regulators"
+	depends on TPS6105X
+	default y if TPS6105X
+	help
+	  This driver supports TPS61050/TPS61052 voltage regulator chips.
+	  It is a single boost converter primarily for white LEDs and
+	  audio amplifiers.
+
 config REGULATOR_TPS65023
 	tristate "TI TPS65023 Power regulators"
 	depends on I2C
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/Makefile linux-libre-2.6.39-gnu/drivers/regulator/Makefile
--- linux-libre-2.6.38-gnu/drivers/regulator/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o
 obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o
 obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o
+obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
 obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
@@ -33,7 +34,7 @@
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
-
+obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65023) += tps65023-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6507X) += tps6507x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/max8952.c linux-libre-2.6.39-gnu/drivers/regulator/max8952.c
--- linux-libre-2.6.38-gnu/drivers/regulator/max8952.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/max8952.c	2011-05-19 00:06:34.000000000 -0400
@@ -262,7 +262,7 @@
 
 	if (err) {
 		dev_warn(max8952->dev, "VID0/1 gpio invalid: "
-				"DVS not avilable.\n");
+				"DVS not available.\n");
 		max8952->vid0 = 0;
 		max8952->vid1 = 0;
 		/* Mark invalid */
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/max8997.c linux-libre-2.6.39-gnu/drivers/regulator/max8997.c
--- linux-libre-2.6.38-gnu/drivers/regulator/max8997.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/regulator/max8997.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1214 @@
+/*
+ * max8997.c - Regulator driver for the Maxim 8997/8966
+ *
+ * Copyright (C) 2011 Samsung Electronics
+ * MyungJoo Ham <myungjoo.ham@smasung.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
+ *
+ * This driver is based on max8998.c
+ */
+
+#include <linux/bug.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max8997.h>
+#include <linux/mfd/max8997-private.h>
+
+struct max8997_data {
+	struct device *dev;
+	struct max8997_dev *iodev;
+	int num_regulators;
+	struct regulator_dev **rdev;
+	int ramp_delay; /* in mV/us */
+
+	u8 buck1_vol[8];
+	u8 buck2_vol[8];
+	u8 buck5_vol[8];
+	int buck125_gpioindex;
+
+	u8 saved_states[MAX8997_REG_MAX];
+};
+
+static inline void max8997_set_gpio(struct max8997_data *max8997)
+{
+	struct max8997_platform_data *pdata =
+		dev_get_platdata(max8997->iodev->dev);
+	int set3 = (max8997->buck125_gpioindex) & 0x1;
+	int set2 = ((max8997->buck125_gpioindex) >> 1) & 0x1;
+	int set1 = ((max8997->buck125_gpioindex) >> 2) & 0x1;
+
+	gpio_set_value(pdata->buck125_gpios[0], set1);
+	gpio_set_value(pdata->buck125_gpios[1], set2);
+	gpio_set_value(pdata->buck125_gpios[2], set3);
+}
+
+struct voltage_map_desc {
+	int min;
+	int max;
+	int step;
+	unsigned int n_bits;
+};
+
+/* Voltage maps in mV */
+static const struct voltage_map_desc ldo_voltage_map_desc = {
+	.min = 800,	.max = 3950,	.step = 50,	.n_bits = 6,
+}; /* LDO1 ~ 18, 21 all */
+
+static const struct voltage_map_desc buck1245_voltage_map_desc = {
+	.min = 650,	.max = 2225,	.step = 25,	.n_bits = 6,
+}; /* Buck1, 2, 4, 5 */
+
+static const struct voltage_map_desc buck37_voltage_map_desc = {
+	.min = 750,	.max = 3900,	.step = 50,	.n_bits = 6,
+}; /* Buck3, 7 */
+
+/* current map in mA */
+static const struct voltage_map_desc charger_current_map_desc = {
+	.min = 200,	.max = 950,	.step = 50,	.n_bits = 4,
+};
+
+static const struct voltage_map_desc topoff_current_map_desc = {
+	.min = 50,	.max = 200,	.step = 10,	.n_bits = 4,
+};
+
+static const struct voltage_map_desc *reg_voltage_map[] = {
+	[MAX8997_LDO1] = &ldo_voltage_map_desc,
+	[MAX8997_LDO2] = &ldo_voltage_map_desc,
+	[MAX8997_LDO3] = &ldo_voltage_map_desc,
+	[MAX8997_LDO4] = &ldo_voltage_map_desc,
+	[MAX8997_LDO5] = &ldo_voltage_map_desc,
+	[MAX8997_LDO6] = &ldo_voltage_map_desc,
+	[MAX8997_LDO7] = &ldo_voltage_map_desc,
+	[MAX8997_LDO8] = &ldo_voltage_map_desc,
+	[MAX8997_LDO9] = &ldo_voltage_map_desc,
+	[MAX8997_LDO10] = &ldo_voltage_map_desc,
+	[MAX8997_LDO11] = &ldo_voltage_map_desc,
+	[MAX8997_LDO12] = &ldo_voltage_map_desc,
+	[MAX8997_LDO13] = &ldo_voltage_map_desc,
+	[MAX8997_LDO14] = &ldo_voltage_map_desc,
+	[MAX8997_LDO15] = &ldo_voltage_map_desc,
+	[MAX8997_LDO16] = &ldo_voltage_map_desc,
+	[MAX8997_LDO17] = &ldo_voltage_map_desc,
+	[MAX8997_LDO18] = &ldo_voltage_map_desc,
+	[MAX8997_LDO21] = &ldo_voltage_map_desc,
+	[MAX8997_BUCK1] = &buck1245_voltage_map_desc,
+	[MAX8997_BUCK2] = &buck1245_voltage_map_desc,
+	[MAX8997_BUCK3] = &buck37_voltage_map_desc,
+	[MAX8997_BUCK4] = &buck1245_voltage_map_desc,
+	[MAX8997_BUCK5] = &buck1245_voltage_map_desc,
+	[MAX8997_BUCK6] = NULL,
+	[MAX8997_BUCK7] = &buck37_voltage_map_desc,
+	[MAX8997_EN32KHZ_AP] = NULL,
+	[MAX8997_EN32KHZ_CP] = NULL,
+	[MAX8997_ENVICHG] = NULL,
+	[MAX8997_ESAFEOUT1] = NULL,
+	[MAX8997_ESAFEOUT2] = NULL,
+	[MAX8997_CHARGER_CV] = NULL,
+	[MAX8997_CHARGER] = &charger_current_map_desc,
+	[MAX8997_CHARGER_TOPOFF] = &topoff_current_map_desc,
+};
+
+static inline int max8997_get_rid(struct regulator_dev *rdev)
+{
+	return rdev_get_id(rdev);
+}
+
+static int max8997_list_voltage_safeout(struct regulator_dev *rdev,
+		unsigned int selector)
+{
+	int rid = max8997_get_rid(rdev);
+
+	if (rid == MAX8997_ESAFEOUT1 || rid == MAX8997_ESAFEOUT2) {
+		switch (selector) {
+		case 0:
+			return 4850000;
+		case 1:
+			return 4900000;
+		case 2:
+			return 4950000;
+		case 3:
+			return 3300000;
+		default:
+			return -EINVAL;
+		}
+	}
+
+	return -EINVAL;
+}
+
+static int max8997_list_voltage_charger_cv(struct regulator_dev *rdev,
+		unsigned int selector)
+{
+	int rid = max8997_get_rid(rdev);
+
+	if (rid != MAX8997_CHARGER_CV)
+		goto err;
+
+	switch (selector) {
+	case 0x00:
+		return 4200000;
+	case 0x01 ... 0x0E:
+		return 4000000 + 20000 * (selector - 0x01);
+	case 0x0F:
+		return 4350000;
+	default:
+		return -EINVAL;
+	}
+err:
+	return -EINVAL;
+}
+
+static int max8997_list_voltage(struct regulator_dev *rdev,
+		unsigned int selector)
+{
+	const struct voltage_map_desc *desc;
+	int rid = max8997_get_rid(rdev);
+	int val;
+
+	if (rid >= ARRAY_SIZE(reg_voltage_map) ||
+			rid < 0)
+		return -EINVAL;
+
+	desc = reg_voltage_map[rid];
+	if (desc == NULL)
+		return -EINVAL;
+
+	val = desc->min + desc->step * selector;
+	if (val > desc->max)
+		return -EINVAL;
+
+	return val * 1000;
+}
+
+static int max8997_get_enable_register(struct regulator_dev *rdev,
+		int *reg, int *mask, int *pattern)
+{
+	int rid = max8997_get_rid(rdev);
+
+	switch (rid) {
+	case MAX8997_LDO1 ... MAX8997_LDO21:
+		*reg = MAX8997_REG_LDO1CTRL + (rid - MAX8997_LDO1);
+		*mask = 0xC0;
+		*pattern = 0xC0;
+		break;
+	case MAX8997_BUCK1:
+		*reg = MAX8997_REG_BUCK1CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_BUCK2:
+		*reg = MAX8997_REG_BUCK2CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_BUCK3:
+		*reg = MAX8997_REG_BUCK3CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_BUCK4:
+		*reg = MAX8997_REG_BUCK4CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_BUCK5:
+		*reg = MAX8997_REG_BUCK5CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_BUCK6:
+		*reg = MAX8997_REG_BUCK6CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_BUCK7:
+		*reg = MAX8997_REG_BUCK7CTRL;
+		*mask = 0x01;
+		*pattern = 0x01;
+		break;
+	case MAX8997_EN32KHZ_AP ... MAX8997_EN32KHZ_CP:
+		*reg = MAX8997_REG_MAINCON1;
+		*mask = 0x01 << (rid - MAX8997_EN32KHZ_AP);
+		*pattern = 0x01 << (rid - MAX8997_EN32KHZ_AP);
+		break;
+	case MAX8997_ENVICHG:
+		*reg = MAX8997_REG_MBCCTRL1;
+		*mask = 0x80;
+		*pattern = 0x80;
+		break;
+	case MAX8997_ESAFEOUT1 ... MAX8997_ESAFEOUT2:
+		*reg = MAX8997_REG_SAFEOUTCTRL;
+		*mask = 0x40 << (rid - MAX8997_ESAFEOUT1);
+		*pattern = 0x40 << (rid - MAX8997_ESAFEOUT1);
+		break;
+	case MAX8997_CHARGER:
+		*reg = MAX8997_REG_MBCCTRL2;
+		*mask = 0x40;
+		*pattern = 0x40;
+		break;
+	default:
+		/* Not controllable or not exists */
+		return -EINVAL;
+		break;
+	}
+
+	return 0;
+}
+
+static int max8997_reg_is_enabled(struct regulator_dev *rdev)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int ret, reg, mask, pattern;
+	u8 val;
+
+	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
+	if (ret == -EINVAL)
+		return 1; /* "not controllable" */
+	else if (ret)
+		return ret;
+
+	ret = max8997_read_reg(i2c, reg, &val);
+	if (ret)
+		return ret;
+
+	return (val & mask) == pattern;
+}
+
+static int max8997_reg_enable(struct regulator_dev *rdev)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int ret, reg, mask, pattern;
+
+	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
+	if (ret)
+		return ret;
+
+	return max8997_update_reg(i2c, reg, pattern, mask);
+}
+
+static int max8997_reg_disable(struct regulator_dev *rdev)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int ret, reg, mask, pattern;
+
+	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
+	if (ret)
+		return ret;
+
+	return max8997_update_reg(i2c, reg, ~pattern, mask);
+}
+
+static int max8997_get_voltage_register(struct regulator_dev *rdev,
+		int *_reg, int *_shift, int *_mask)
+{
+	int rid = max8997_get_rid(rdev);
+	int reg, shift = 0, mask = 0x3f;
+
+	switch (rid) {
+	case MAX8997_LDO1 ... MAX8997_LDO21:
+		reg = MAX8997_REG_LDO1CTRL + (rid - MAX8997_LDO1);
+		break;
+	case MAX8997_BUCK1:
+		reg = MAX8997_REG_BUCK1DVS1;
+		break;
+	case MAX8997_BUCK2:
+		reg = MAX8997_REG_BUCK2DVS1;
+		break;
+	case MAX8997_BUCK3:
+		reg = MAX8997_REG_BUCK3DVS;
+		break;
+	case MAX8997_BUCK4:
+		reg = MAX8997_REG_BUCK4DVS;
+		break;
+	case MAX8997_BUCK5:
+		reg = MAX8997_REG_BUCK5DVS1;
+		break;
+	case MAX8997_BUCK7:
+		reg = MAX8997_REG_BUCK7DVS;
+		break;
+	case MAX8997_ESAFEOUT1 ...  MAX8997_ESAFEOUT2:
+		reg = MAX8997_REG_SAFEOUTCTRL;
+		shift = (rid == MAX8997_ESAFEOUT2) ? 2 : 0;
+		mask = 0x3;
+		break;
+	case MAX8997_CHARGER_CV:
+		reg = MAX8997_REG_MBCCTRL3;
+		shift = 0;
+		mask = 0xf;
+		break;
+	case MAX8997_CHARGER:
+		reg = MAX8997_REG_MBCCTRL4;
+		shift = 0;
+		mask = 0xf;
+		break;
+	case MAX8997_CHARGER_TOPOFF:
+		reg = MAX8997_REG_MBCCTRL5;
+		shift = 0;
+		mask = 0xf;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	*_reg = reg;
+	*_shift = shift;
+	*_mask = mask;
+
+	return 0;
+}
+
+static int max8997_get_voltage(struct regulator_dev *rdev)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct max8997_platform_data *pdata =
+		dev_get_platdata(max8997->iodev->dev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int reg, shift, mask, ret;
+	int rid = max8997_get_rid(rdev);
+	u8 val;
+
+	ret = max8997_get_voltage_register(rdev, &reg, &shift, &mask);
+	if (ret)
+		return ret;
+
+	if ((rid == MAX8997_BUCK1 && pdata->buck1_gpiodvs) ||
+			(rid == MAX8997_BUCK2 && pdata->buck2_gpiodvs) ||
+			(rid == MAX8997_BUCK5 && pdata->buck5_gpiodvs))
+		reg += max8997->buck125_gpioindex;
+
+	ret = max8997_read_reg(i2c, reg, &val);
+	if (ret)
+		return ret;
+
+	val >>= shift;
+	val &= mask;
+
+	if (rdev->desc && rdev->desc->ops && rdev->desc->ops->list_voltage)
+		return rdev->desc->ops->list_voltage(rdev, val);
+
+	/*
+	 * max8997_list_voltage returns value for any rdev with voltage_map,
+	 * which works for "CHARGER" and "CHARGER TOPOFF" that do not have
+	 * list_voltage ops (they are current regulators).
+	 */
+	return max8997_list_voltage(rdev, val);
+}
+
+static inline int max8997_get_voltage_proper_val(
+		const struct voltage_map_desc *desc,
+		int min_vol, int max_vol)
+{
+	int i = 0;
+
+	if (desc == NULL)
+		return -EINVAL;
+
+	if (max_vol < desc->min || min_vol > desc->max)
+		return -EINVAL;
+
+	while (desc->min + desc->step * i < min_vol &&
+			desc->min + desc->step * i < desc->max)
+		i++;
+
+	if (desc->min + desc->step * i > max_vol)
+		return -EINVAL;
+
+	if (i >= (1 << desc->n_bits))
+		return -EINVAL;
+
+	return i;
+}
+
+static int max8997_set_voltage_charger_cv(struct regulator_dev *rdev,
+		int min_uV, int max_uV, unsigned *selector)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int rid = max8997_get_rid(rdev);
+	int lb, ub;
+	int reg, shift = 0, mask, ret = 0;
+	u8 val = 0x0;
+
+	if (rid != MAX8997_CHARGER_CV)
+		return -EINVAL;
+
+	ret = max8997_get_voltage_register(rdev, &reg, &shift, &mask);
+	if (ret)
+		return ret;
+
+	if (max_uV < 4000000 || min_uV > 4350000)
+		return -EINVAL;
+
+	if (min_uV <= 4000000) {
+		if (max_uV >= 4000000)
+			return -EINVAL;
+		else
+			val = 0x1;
+	} else if (min_uV <= 4200000 && max_uV >= 4200000)
+		val = 0x0;
+	else {
+		lb = (min_uV - 4000001) / 20000 + 2;
+		ub = (max_uV - 4000000) / 20000 + 1;
+
+		if (lb > ub)
+			return -EINVAL;
+
+		if (lb < 0xf)
+			val = lb;
+		else {
+			if (ub >= 0xf)
+				val = 0xf;
+			else
+				return -EINVAL;
+		}
+	}
+
+	*selector = val;
+
+	ret = max8997_update_reg(i2c, reg, val << shift, mask);
+
+	return ret;
+}
+
+/*
+ * For LDO1 ~ LDO21, BUCK1~5, BUCK7, CHARGER, CHARGER_TOPOFF
+ * BUCK1, 2, and 5 are available if they are not controlled by gpio
+ */
+static int max8997_set_voltage_ldobuck(struct regulator_dev *rdev,
+		int min_uV, int max_uV, unsigned *selector)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
+	const struct voltage_map_desc *desc;
+	int rid = max8997_get_rid(rdev);
+	int reg, shift = 0, mask, ret;
+	int i;
+	u8 org;
+
+	switch (rid) {
+	case MAX8997_LDO1 ... MAX8997_LDO21:
+		break;
+	case MAX8997_BUCK1 ... MAX8997_BUCK5:
+		break;
+	case MAX8997_BUCK6:
+		return -EINVAL;
+	case MAX8997_BUCK7:
+		break;
+	case MAX8997_CHARGER:
+		break;
+	case MAX8997_CHARGER_TOPOFF:
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	desc = reg_voltage_map[rid];
+
+	i = max8997_get_voltage_proper_val(desc, min_vol, max_vol);
+	if (i < 0)
+		return i;
+
+	ret = max8997_get_voltage_register(rdev, &reg, &shift, &mask);
+	if (ret)
+		return ret;
+
+	max8997_read_reg(i2c, reg, &org);
+	org = (org & mask) >> shift;
+
+	ret = max8997_update_reg(i2c, reg, i << shift, mask << shift);
+	*selector = i;
+
+	if (rid == MAX8997_BUCK1 || rid == MAX8997_BUCK2 ||
+			rid == MAX8997_BUCK4 || rid == MAX8997_BUCK5) {
+		/* If the voltage is increasing */
+		if (org < i)
+			udelay(desc->step * (i - org) / max8997->ramp_delay);
+	}
+
+	return ret;
+}
+
+/*
+ * Assess the damage on the voltage setting of BUCK1,2,5 by the change.
+ *
+ * When GPIO-DVS mode is used for multiple bucks, changing the voltage value
+ * of one of the bucks may affect that of another buck, which is the side
+ * effect of the change (set_voltage). This function examines the GPIO-DVS
+ * configurations and checks whether such side-effect exists.
+ */
+static int max8997_assess_side_effect(struct regulator_dev *rdev,
+		u8 new_val, int *best)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct max8997_platform_data *pdata =
+		dev_get_platdata(max8997->iodev->dev);
+	int rid = max8997_get_rid(rdev);
+	u8 *buckx_val[3];
+	bool buckx_gpiodvs[3];
+	int side_effect[8];
+	int min_side_effect = INT_MAX;
+	int i;
+
+	*best = -1;
+
+	switch (rid) {
+	case MAX8997_BUCK1:
+		rid = 0;
+		break;
+	case MAX8997_BUCK2:
+		rid = 1;
+		break;
+	case MAX8997_BUCK5:
+		rid = 2;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	buckx_val[0] = max8997->buck1_vol;
+	buckx_val[1] = max8997->buck2_vol;
+	buckx_val[2] = max8997->buck5_vol;
+	buckx_gpiodvs[0] = pdata->buck1_gpiodvs;
+	buckx_gpiodvs[1] = pdata->buck2_gpiodvs;
+	buckx_gpiodvs[2] = pdata->buck5_gpiodvs;
+
+	for (i = 0; i < 8; i++) {
+		int others;
+
+		if (new_val != (buckx_val[rid])[i]) {
+			side_effect[i] = -1;
+			continue;
+		}
+
+		side_effect[i] = 0;
+		for (others = 0; others < 3; others++) {
+			int diff;
+
+			if (others == rid)
+				continue;
+			if (buckx_gpiodvs[others] == false)
+				continue; /* Not affected */
+			diff = (buckx_val[others])[i] -
+				(buckx_val[others])[max8997->buck125_gpioindex];
+			if (diff > 0)
+				side_effect[i] += diff;
+			else if (diff < 0)
+				side_effect[i] -= diff;
+		}
+		if (side_effect[i] == 0) {
+			*best = i;
+			return 0; /* NO SIDE EFFECT! Use This! */
+		}
+		if (side_effect[i] < min_side_effect) {
+			min_side_effect = side_effect[i];
+			*best = i;
+		}
+	}
+
+	if (*best == -1)
+		return -EINVAL;
+
+	return side_effect[*best];
+}
+
+/*
+ * For Buck 1 ~ 5 and 7. If it is not controlled by GPIO, this calls
+ * max8997_set_voltage_ldobuck to do the job.
+ */
+static int max8997_set_voltage_buck(struct regulator_dev *rdev,
+		int min_uV, int max_uV, unsigned *selector)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct max8997_platform_data *pdata =
+		dev_get_platdata(max8997->iodev->dev);
+	int rid = max8997_get_rid(rdev);
+	const struct voltage_map_desc *desc;
+	int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg;
+	bool gpio_dvs_mode = false;
+	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
+
+	if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7)
+		return -EINVAL;
+
+	switch (rid) {
+	case MAX8997_BUCK1:
+		if (pdata->buck1_gpiodvs)
+			gpio_dvs_mode = true;
+		break;
+	case MAX8997_BUCK2:
+		if (pdata->buck2_gpiodvs)
+			gpio_dvs_mode = true;
+		break;
+	case MAX8997_BUCK5:
+		if (pdata->buck5_gpiodvs)
+			gpio_dvs_mode = true;
+		break;
+	}
+
+	if (!gpio_dvs_mode)
+		return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV,
+						selector);
+
+	desc = reg_voltage_map[rid];
+	new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol);
+	if (new_val < 0)
+		return new_val;
+
+	tmp_dmg = INT_MAX;
+	tmp_idx = -1;
+	tmp_val = -1;
+	do {
+		damage = max8997_assess_side_effect(rdev, new_val, &new_idx);
+		if (damage == 0)
+			goto out;
+
+		if (tmp_dmg > damage) {
+			tmp_idx = new_idx;
+			tmp_val = new_val;
+			tmp_dmg = damage;
+		}
+
+		new_val++;
+	} while (desc->min + desc->step + new_val <= desc->max);
+
+	new_idx = tmp_idx;
+	new_val = tmp_val;
+
+	if (pdata->ignore_gpiodvs_side_effect == false)
+		return -EINVAL;
+
+	dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:"
+			" %d -> %d\n", max8997->buck125_gpioindex, tmp_idx);
+
+out:
+	if (new_idx < 0 || new_val < 0)
+		return -EINVAL;
+
+	max8997->buck125_gpioindex = new_idx;
+	max8997_set_gpio(max8997);
+	*selector = new_val;
+
+	return 0;
+}
+
+static const int safeoutvolt[] = {
+	3300000,
+	4850000,
+	4900000,
+	4950000,
+};
+
+/* For SAFEOUT1 and SAFEOUT2 */
+static int max8997_set_voltage_safeout(struct regulator_dev *rdev,
+		int min_uV, int max_uV, unsigned *selector)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int rid = max8997_get_rid(rdev);
+	int reg, shift = 0, mask, ret;
+	int i = 0;
+	u8 val;
+
+	if (rid != MAX8997_ESAFEOUT1 && rid != MAX8997_ESAFEOUT2)
+		return -EINVAL;
+
+	for (i = 0; i < ARRAY_SIZE(safeoutvolt); i++) {
+		if (min_uV <= safeoutvolt[i] &&
+				max_uV >= safeoutvolt[i])
+			break;
+	}
+
+	if (i >= ARRAY_SIZE(safeoutvolt))
+		return -EINVAL;
+
+	if (i == 0)
+		val = 0x3;
+	else
+		val = i - 1;
+
+	ret = max8997_get_voltage_register(rdev, &reg, &shift, &mask);
+	if (ret)
+		return ret;
+
+	ret = max8997_update_reg(i2c, reg, val << shift, mask << shift);
+	*selector = val;
+
+	return ret;
+}
+
+static int max8997_reg_enable_suspend(struct regulator_dev *rdev)
+{
+	return 0;
+}
+
+static int max8997_reg_disable_suspend(struct regulator_dev *rdev)
+{
+	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
+	struct i2c_client *i2c = max8997->iodev->i2c;
+	int ret, reg, mask, pattern;
+	int rid = max8997_get_rid(rdev);
+
+	ret = max8997_get_enable_register(rdev, &reg, &mask, &pattern);
+	if (ret)
+		return ret;
+
+	max8997_read_reg(i2c, reg, &max8997->saved_states[rid]);
+
+	if (rid == MAX8997_LDO1 ||
+			rid == MAX8997_LDO10 ||
+			rid == MAX8997_LDO21) {
+		dev_dbg(&rdev->dev, "Conditional Power-Off for %s\n",
+				rdev->desc->name);
+		return max8997_update_reg(i2c, reg, 0x40, mask);
+	}
+
+	dev_dbg(&rdev->dev, "Full Power-Off for %s (%xh -> %xh)\n",
+			rdev->desc->name, max8997->saved_states[rid] & mask,
+			(~pattern) & mask);
+	return max8997_update_reg(i2c, reg, ~pattern, mask);
+}
+
+static struct regulator_ops max8997_ldo_ops = {
+	.list_voltage		= max8997_list_voltage,
+	.is_enabled		= max8997_reg_is_enabled,
+	.enable			= max8997_reg_enable,
+	.disable		= max8997_reg_disable,
+	.get_voltage		= max8997_get_voltage,
+	.set_voltage		= max8997_set_voltage_ldobuck,
+	.set_suspend_enable	= max8997_reg_enable_suspend,
+	.set_suspend_disable	= max8997_reg_disable_suspend,
+};
+
+static struct regulator_ops max8997_buck_ops = {
+	.list_voltage		= max8997_list_voltage,
+	.is_enabled		= max8997_reg_is_enabled,
+	.enable			= max8997_reg_enable,
+	.disable		= max8997_reg_disable,
+	.get_voltage		= max8997_get_voltage,
+	.set_voltage		= max8997_set_voltage_buck,
+	.set_suspend_enable	= max8997_reg_enable_suspend,
+	.set_suspend_disable	= max8997_reg_disable_suspend,
+};
+
+static struct regulator_ops max8997_fixedvolt_ops = {
+	.list_voltage		= max8997_list_voltage,
+	.is_enabled		= max8997_reg_is_enabled,
+	.enable			= max8997_reg_enable,
+	.disable		= max8997_reg_disable,
+	.set_suspend_enable	= max8997_reg_enable_suspend,
+	.set_suspend_disable	= max8997_reg_disable_suspend,
+};
+
+static struct regulator_ops max8997_safeout_ops = {
+	.list_voltage		= max8997_list_voltage_safeout,
+	.is_enabled		= max8997_reg_is_enabled,
+	.enable			= max8997_reg_enable,
+	.disable		= max8997_reg_disable,
+	.get_voltage		= max8997_get_voltage,
+	.set_voltage		= max8997_set_voltage_safeout,
+	.set_suspend_enable	= max8997_reg_enable_suspend,
+	.set_suspend_disable	= max8997_reg_disable_suspend,
+};
+
+static struct regulator_ops max8997_fixedstate_ops = {
+	.list_voltage		= max8997_list_voltage_charger_cv,
+	.get_voltage		= max8997_get_voltage,
+	.set_voltage		= max8997_set_voltage_charger_cv,
+};
+
+static int max8997_set_voltage_ldobuck_wrap(struct regulator_dev *rdev,
+		int min_uV, int max_uV)
+{
+	unsigned dummy;
+
+	return max8997_set_voltage_ldobuck(rdev, min_uV, max_uV, &dummy);
+}
+
+
+static struct regulator_ops max8997_charger_ops = {
+	.is_enabled		= max8997_reg_is_enabled,
+	.enable			= max8997_reg_enable,
+	.disable		= max8997_reg_disable,
+	.get_current_limit	= max8997_get_voltage,
+	.set_current_limit	= max8997_set_voltage_ldobuck_wrap,
+};
+
+static struct regulator_ops max8997_charger_fixedstate_ops = {
+	.is_enabled		= max8997_reg_is_enabled,
+	.get_current_limit	= max8997_get_voltage,
+	.set_current_limit	= max8997_set_voltage_ldobuck_wrap,
+};
+
+#define regulator_desc_ldo(num)		{	\
+	.name		= "LDO"#num,		\
+	.id		= MAX8997_LDO##num,	\
+	.ops		= &max8997_ldo_ops,	\
+	.type		= REGULATOR_VOLTAGE,	\
+	.owner		= THIS_MODULE,		\
+}
+#define regulator_desc_buck(num)		{	\
+	.name		= "BUCK"#num,		\
+	.id		= MAX8997_BUCK##num,	\
+	.ops		= &max8997_buck_ops,	\
+	.type		= REGULATOR_VOLTAGE,	\
+	.owner		= THIS_MODULE,		\
+}
+
+static struct regulator_desc regulators[] = {
+	regulator_desc_ldo(1),
+	regulator_desc_ldo(2),
+	regulator_desc_ldo(3),
+	regulator_desc_ldo(4),
+	regulator_desc_ldo(5),
+	regulator_desc_ldo(6),
+	regulator_desc_ldo(7),
+	regulator_desc_ldo(8),
+	regulator_desc_ldo(9),
+	regulator_desc_ldo(10),
+	regulator_desc_ldo(11),
+	regulator_desc_ldo(12),
+	regulator_desc_ldo(13),
+	regulator_desc_ldo(14),
+	regulator_desc_ldo(15),
+	regulator_desc_ldo(16),
+	regulator_desc_ldo(17),
+	regulator_desc_ldo(18),
+	regulator_desc_ldo(21),
+	regulator_desc_buck(1),
+	regulator_desc_buck(2),
+	regulator_desc_buck(3),
+	regulator_desc_buck(4),
+	regulator_desc_buck(5),
+	{
+		.name	= "BUCK6",
+		.id	= MAX8997_BUCK6,
+		.ops	= &max8997_fixedvolt_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	= THIS_MODULE,
+	},
+	regulator_desc_buck(7),
+	{
+		.name	= "EN32KHz AP",
+		.id	= MAX8997_EN32KHZ_AP,
+		.ops	= &max8997_fixedvolt_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	= THIS_MODULE,
+	}, {
+		.name	= "EN32KHz CP",
+		.id	= MAX8997_EN32KHZ_CP,
+		.ops	= &max8997_fixedvolt_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	= THIS_MODULE,
+	}, {
+		.name	= "ENVICHG",
+		.id	= MAX8997_ENVICHG,
+		.ops	= &max8997_fixedvolt_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	= THIS_MODULE,
+	}, {
+		.name	= "ESAFEOUT1",
+		.id	= MAX8997_ESAFEOUT1,
+		.ops	= &max8997_safeout_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	 = THIS_MODULE,
+	}, {
+		.name	= "ESAFEOUT2",
+		.id	= MAX8997_ESAFEOUT2,
+		.ops	= &max8997_safeout_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	 = THIS_MODULE,
+	}, {
+		.name	= "CHARGER CV",
+		.id	= MAX8997_CHARGER_CV,
+		.ops	= &max8997_fixedstate_ops,
+		.type	= REGULATOR_VOLTAGE,
+		.owner	 = THIS_MODULE,
+	}, {
+		.name	= "CHARGER",
+		.id	= MAX8997_CHARGER,
+		.ops	= &max8997_charger_ops,
+		.type	= REGULATOR_CURRENT,
+		.owner	 = THIS_MODULE,
+	}, {
+		.name	= "CHARGER TOPOFF",
+		.id	= MAX8997_CHARGER_TOPOFF,
+		.ops	= &max8997_charger_fixedstate_ops,
+		.type	= REGULATOR_CURRENT,
+		.owner	 = THIS_MODULE,
+	},
+};
+
+static __devinit int max8997_pmic_probe(struct platform_device *pdev)
+{
+	struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
+	struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
+	struct regulator_dev **rdev;
+	struct max8997_data *max8997;
+	struct i2c_client *i2c;
+	int i, ret, size;
+	u8 max_buck1 = 0, max_buck2 = 0, max_buck5 = 0;
+
+	if (!pdata) {
+		dev_err(pdev->dev.parent, "No platform init data supplied.\n");
+		return -ENODEV;
+	}
+
+	max8997 = kzalloc(sizeof(struct max8997_data), GFP_KERNEL);
+	if (!max8997)
+		return -ENOMEM;
+
+	size = sizeof(struct regulator_dev *) * pdata->num_regulators;
+	max8997->rdev = kzalloc(size, GFP_KERNEL);
+	if (!max8997->rdev) {
+		kfree(max8997);
+		return -ENOMEM;
+	}
+
+	rdev = max8997->rdev;
+	max8997->dev = &pdev->dev;
+	max8997->iodev = iodev;
+	max8997->num_regulators = pdata->num_regulators;
+	platform_set_drvdata(pdev, max8997);
+	i2c = max8997->iodev->i2c;
+
+	max8997->buck125_gpioindex = pdata->buck125_default_idx;
+
+	for (i = 0; i < 8; i++) {
+		max8997->buck1_vol[i] = ret =
+			max8997_get_voltage_proper_val(
+					&buck1245_voltage_map_desc,
+					pdata->buck1_voltage[i] / 1000,
+					pdata->buck1_voltage[i] / 1000 +
+					buck1245_voltage_map_desc.step);
+		if (ret < 0)
+			goto err_alloc;
+
+		max8997->buck2_vol[i] = ret =
+			max8997_get_voltage_proper_val(
+					&buck1245_voltage_map_desc,
+					pdata->buck2_voltage[i] / 1000,
+					pdata->buck2_voltage[i] / 1000 +
+					buck1245_voltage_map_desc.step);
+		if (ret < 0)
+			goto err_alloc;
+
+		max8997->buck5_vol[i] = ret =
+			max8997_get_voltage_proper_val(
+					&buck1245_voltage_map_desc,
+					pdata->buck5_voltage[i] / 1000,
+					pdata->buck5_voltage[i] / 1000 +
+					buck1245_voltage_map_desc.step);
+		if (ret < 0)
+			goto err_alloc;
+
+		if (max_buck1 < max8997->buck1_vol[i])
+			max_buck1 = max8997->buck1_vol[i];
+		if (max_buck2 < max8997->buck2_vol[i])
+			max_buck2 = max8997->buck2_vol[i];
+		if (max_buck5 < max8997->buck5_vol[i])
+			max_buck5 = max8997->buck5_vol[i];
+	}
+
+	/* For the safety, set max voltage before setting up */
+	for (i = 0; i < 8; i++) {
+		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1),
+				max_buck1, 0x3f);
+		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1),
+				max_buck2, 0x3f);
+		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1),
+				max_buck5, 0x3f);
+	}
+
+	/*
+	 * If buck 1, 2, and 5 do not care DVS GPIO settings, ignore them.
+	 * If at least one of them cares, set gpios.
+	 */
+	if (pdata->buck1_gpiodvs || pdata->buck2_gpiodvs ||
+			pdata->buck5_gpiodvs) {
+		bool gpio1set = false, gpio2set = false;
+
+		if (!gpio_is_valid(pdata->buck125_gpios[0]) ||
+				!gpio_is_valid(pdata->buck125_gpios[1]) ||
+				!gpio_is_valid(pdata->buck125_gpios[2])) {
+			dev_err(&pdev->dev, "GPIO NOT VALID\n");
+			ret = -EINVAL;
+			goto err_alloc;
+		}
+
+		ret = gpio_request(pdata->buck125_gpios[0],
+				"MAX8997 SET1");
+		if (ret == -EBUSY)
+			dev_warn(&pdev->dev, "Duplicated gpio request"
+					" on SET1\n");
+		else if (ret)
+			goto err_alloc;
+		else
+			gpio1set = true;
+
+		ret = gpio_request(pdata->buck125_gpios[1],
+				"MAX8997 SET2");
+		if (ret == -EBUSY)
+			dev_warn(&pdev->dev, "Duplicated gpio request"
+					" on SET2\n");
+		else if (ret) {
+			if (gpio1set)
+				gpio_free(pdata->buck125_gpios[0]);
+			goto err_alloc;
+		} else
+			gpio2set = true;
+
+		ret = gpio_request(pdata->buck125_gpios[2],
+				"MAX8997 SET3");
+		if (ret == -EBUSY)
+			dev_warn(&pdev->dev, "Duplicated gpio request"
+					" on SET3\n");
+		else if (ret) {
+			if (gpio1set)
+				gpio_free(pdata->buck125_gpios[0]);
+			if (gpio2set)
+				gpio_free(pdata->buck125_gpios[1]);
+			goto err_alloc;
+		}
+
+		gpio_direction_output(pdata->buck125_gpios[0],
+				(max8997->buck125_gpioindex >> 2)
+				& 0x1); /* SET1 */
+		gpio_direction_output(pdata->buck125_gpios[1],
+				(max8997->buck125_gpioindex >> 1)
+				& 0x1); /* SET2 */
+		gpio_direction_output(pdata->buck125_gpios[2],
+				(max8997->buck125_gpioindex >> 0)
+				& 0x1); /* SET3 */
+		ret = 0;
+	}
+
+	/* DVS-GPIO disabled */
+	max8997_update_reg(i2c, MAX8997_REG_BUCK1CTRL, (pdata->buck1_gpiodvs) ?
+			(1 << 1) : (0 << 1), 1 << 1);
+	max8997_update_reg(i2c, MAX8997_REG_BUCK2CTRL, (pdata->buck2_gpiodvs) ?
+			(1 << 1) : (0 << 1), 1 << 1);
+	max8997_update_reg(i2c, MAX8997_REG_BUCK5CTRL, (pdata->buck5_gpiodvs) ?
+			(1 << 1) : (0 << 1), 1 << 1);
+
+	/* Initialize all the DVS related BUCK registers */
+	for (i = 0; i < 8; i++) {
+		max8997_update_reg(i2c, MAX8997_REG_BUCK1DVS(i + 1),
+				max8997->buck1_vol[i],
+				0x3f);
+		max8997_update_reg(i2c, MAX8997_REG_BUCK2DVS(i + 1),
+				max8997->buck2_vol[i],
+				0x3f);
+		max8997_update_reg(i2c, MAX8997_REG_BUCK5DVS(i + 1),
+				max8997->buck5_vol[i],
+				0x3f);
+	}
+
+	for (i = 0; i < pdata->num_regulators; i++) {
+		const struct voltage_map_desc *desc;
+		int id = pdata->regulators[i].id;
+
+		desc = reg_voltage_map[id];
+		if (desc)
+			regulators[id].n_voltages =
+				(desc->max - desc->min) / desc->step + 1;
+		else if (id == MAX8997_ESAFEOUT1 || id == MAX8997_ESAFEOUT2)
+			regulators[id].n_voltages = 4;
+		else if (id == MAX8997_CHARGER_CV)
+			regulators[id].n_voltages = 16;
+
+		rdev[i] = regulator_register(&regulators[id], max8997->dev,
+				pdata->regulators[i].initdata, max8997);
+		if (IS_ERR(rdev[i])) {
+			ret = PTR_ERR(rdev[i]);
+			dev_err(max8997->dev, "regulator init failed for %d\n",
+					id);
+			rdev[i] = NULL;
+			goto err;
+		}
+	}
+
+	/* Misc Settings */
+	max8997->ramp_delay = 10; /* set 10mV/us, which is the default */
+	max8997_write_reg(i2c, MAX8997_REG_BUCKRAMP, (0xf << 4) | 0x9);
+
+	return 0;
+err:
+	for (i = 0; i < max8997->num_regulators; i++)
+		if (rdev[i])
+			regulator_unregister(rdev[i]);
+err_alloc:
+	kfree(max8997->rdev);
+	kfree(max8997);
+
+	return ret;
+}
+
+static int __devexit max8997_pmic_remove(struct platform_device *pdev)
+{
+	struct max8997_data *max8997 = platform_get_drvdata(pdev);
+	struct regulator_dev **rdev = max8997->rdev;
+	int i;
+
+	for (i = 0; i < max8997->num_regulators; i++)
+		if (rdev[i])
+			regulator_unregister(rdev[i]);
+
+	kfree(max8997->rdev);
+	kfree(max8997);
+
+	return 0;
+}
+
+static const struct platform_device_id max8997_pmic_id[] = {
+	{ "max8997-pmic", 0},
+	{ },
+};
+MODULE_DEVICE_TABLE(platform, max8997_pmic_id);
+
+static struct platform_driver max8997_pmic_driver = {
+	.driver = {
+		.name = "max8997-pmic",
+		.owner = THIS_MODULE,
+	},
+	.probe = max8997_pmic_probe,
+	.remove = __devexit_p(max8997_pmic_remove),
+	.id_table = max8997_pmic_id,
+};
+
+static int __init max8997_pmic_init(void)
+{
+	return platform_driver_register(&max8997_pmic_driver);
+}
+subsys_initcall(max8997_pmic_init);
+
+static void __exit max8997_pmic_cleanup(void)
+{
+	platform_driver_unregister(&max8997_pmic_driver);
+}
+module_exit(max8997_pmic_cleanup);
+
+MODULE_DESCRIPTION("MAXIM 8997/8966 Regulator Driver");
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/max8998.c linux-libre-2.6.39-gnu/drivers/regulator/max8998.c
--- linux-libre-2.6.38-gnu/drivers/regulator/max8998.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/max8998.c	2011-05-19 00:06:34.000000000 -0400
@@ -887,6 +887,7 @@
 	{ "lp3974-pmic", TYPE_LP3974 },
 	{ }
 };
+MODULE_DEVICE_TABLE(platform, max8998_pmic_id);
 
 static struct platform_driver max8998_pmic_driver = {
 	.driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/mc13783-regulator.c linux-libre-2.6.39-gnu/drivers/regulator/mc13783-regulator.c
--- linux-libre-2.6.38-gnu/drivers/regulator/mc13783-regulator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/mc13783-regulator.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
+#include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -336,8 +337,7 @@
 {
 	struct mc13xxx_regulator_priv *priv;
 	struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
-	struct mc13783_regulator_platform_data *pdata =
-		dev_get_platdata(&pdev->dev);
+	struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev);
 	struct mc13783_regulator_init_data *init_data;
 	int i, ret;
 
@@ -381,8 +381,7 @@
 static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-	struct mc13783_regulator_platform_data *pdata =
-		dev_get_platdata(&pdev->dev);
+	struct mc13783_regulator_platform_data *pdata = mfd_get_data(pdev);
 	int i;
 
 	platform_set_drvdata(pdev, NULL);
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/mc13892-regulator.c linux-libre-2.6.39-gnu/drivers/regulator/mc13892-regulator.c
--- linux-libre-2.6.38-gnu/drivers/regulator/mc13892-regulator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/mc13892-regulator.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,6 +15,7 @@
 #include <linux/regulator/driver.h>
 #include <linux/platform_device.h>
 #include <linux/kernel.h>
+#include <linux/mfd/core.h>
 #include <linux/slab.h>
 #include <linux/init.h>
 #include <linux/err.h>
@@ -520,8 +521,7 @@
 {
 	struct mc13xxx_regulator_priv *priv;
 	struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
-	struct mc13xxx_regulator_platform_data *pdata =
-		dev_get_platdata(&pdev->dev);
+	struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev);
 	struct mc13xxx_regulator_init_data *init_data;
 	int i, ret;
 	u32 val;
@@ -595,8 +595,7 @@
 static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
 {
 	struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
-	struct mc13xxx_regulator_platform_data *pdata =
-		dev_get_platdata(&pdev->dev);
+	struct mc13xxx_regulator_platform_data *pdata = mfd_get_data(pdev);
 	int i;
 
 	platform_set_drvdata(pdev, NULL);
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/tps6105x-regulator.c linux-libre-2.6.39-gnu/drivers/regulator/tps6105x-regulator.c
--- linux-libre-2.6.38-gnu/drivers/regulator/tps6105x-regulator.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/regulator/tps6105x-regulator.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,196 @@
+/*
+ * Driver for TPS61050/61052 boost converters, typically used for white LEDs
+ * or audio amplifiers.
+ *
+ * Copyright (C) 2011 ST-Ericsson SA
+ * Written on behalf of Linaro for ST-Ericsson
+ *
+ * Author: Linus Walleij <linus.walleij@linaro.org>
+ *
+ * License terms: GNU General Public License (GPL) version 2
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/i2c.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/mfd/core.h>
+#include <linux/mfd/tps6105x.h>
+
+static const int tps6105x_voltages[] = {
+	4500000,
+	5000000,
+	5250000,
+	5000000, /* There is an additional 5V */
+};
+
+static int tps6105x_regulator_enable(struct regulator_dev *rdev)
+{
+	struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
+	int ret;
+
+	/* Activate voltage mode */
+	ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+		TPS6105X_REG0_MODE_MASK,
+		TPS6105X_REG0_MODE_VOLTAGE << TPS6105X_REG0_MODE_SHIFT);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int tps6105x_regulator_disable(struct regulator_dev *rdev)
+{
+	struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
+	int ret;
+
+	/* Set into shutdown mode */
+	ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+		TPS6105X_REG0_MODE_MASK,
+		TPS6105X_REG0_MODE_SHUTDOWN << TPS6105X_REG0_MODE_SHIFT);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int tps6105x_regulator_is_enabled(struct regulator_dev *rdev)
+{
+	struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
+	u8 regval;
+	int ret;
+
+	ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+	if (ret)
+		return ret;
+	regval &= TPS6105X_REG0_MODE_MASK;
+	regval >>= TPS6105X_REG0_MODE_SHIFT;
+
+	if (regval == TPS6105X_REG0_MODE_VOLTAGE)
+		return 1;
+
+	return 0;
+}
+
+static int tps6105x_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+	struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
+	u8 regval;
+	int ret;
+
+	ret = tps6105x_get(tps6105x, TPS6105X_REG_0, &regval);
+	if (ret)
+		return ret;
+
+	regval &= TPS6105X_REG0_VOLTAGE_MASK;
+	regval >>= TPS6105X_REG0_VOLTAGE_SHIFT;
+	return (int) regval;
+}
+
+static int tps6105x_regulator_set_voltage_sel(struct regulator_dev *rdev,
+					      unsigned selector)
+{
+	struct tps6105x *tps6105x = rdev_get_drvdata(rdev);
+	int ret;
+
+	ret = tps6105x_mask_and_set(tps6105x, TPS6105X_REG_0,
+				    TPS6105X_REG0_VOLTAGE_MASK,
+				    selector << TPS6105X_REG0_VOLTAGE_SHIFT);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
+static int tps6105x_regulator_list_voltage(struct regulator_dev *rdev,
+					   unsigned selector)
+{
+	if (selector >= ARRAY_SIZE(tps6105x_voltages))
+		return -EINVAL;
+
+	return tps6105x_voltages[selector];
+}
+
+static struct regulator_ops tps6105x_regulator_ops = {
+	.enable		= tps6105x_regulator_enable,
+	.disable	= tps6105x_regulator_disable,
+	.is_enabled	= tps6105x_regulator_is_enabled,
+	.get_voltage_sel = tps6105x_regulator_get_voltage_sel,
+	.set_voltage_sel = tps6105x_regulator_set_voltage_sel,
+	.list_voltage	= tps6105x_regulator_list_voltage,
+};
+
+static struct regulator_desc tps6105x_regulator_desc = {
+	.name		= "tps6105x-boost",
+	.ops		= &tps6105x_regulator_ops,
+	.type		= REGULATOR_VOLTAGE,
+	.id		= 0,
+	.owner		= THIS_MODULE,
+	.n_voltages	= ARRAY_SIZE(tps6105x_voltages),
+};
+
+/*
+ * Registers the chip as a voltage regulator
+ */
+static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
+{
+	struct tps6105x *tps6105x = mfd_get_data(pdev);
+	struct tps6105x_platform_data *pdata = tps6105x->pdata;
+	int ret;
+
+	/* This instance is not set for regulator mode so bail out */
+	if (pdata->mode != TPS6105X_MODE_VOLTAGE) {
+		dev_info(&pdev->dev,
+			 "chip not in voltage mode mode, exit probe \n");
+		return 0;
+	}
+
+	/* Register regulator with framework */
+	tps6105x->regulator = regulator_register(&tps6105x_regulator_desc,
+					     &tps6105x->client->dev,
+					     pdata->regulator_data, tps6105x);
+	if (IS_ERR(tps6105x->regulator)) {
+		ret = PTR_ERR(tps6105x->regulator);
+		dev_err(&tps6105x->client->dev,
+			"failed to register regulator\n");
+		return ret;
+	}
+
+	return 0;
+}
+
+static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
+{
+	struct tps6105x *tps6105x = platform_get_drvdata(pdev);
+	regulator_unregister(tps6105x->regulator);
+	return 0;
+}
+
+static struct platform_driver tps6105x_regulator_driver = {
+	.driver = {
+		.name  = "tps6105x-regulator",
+		.owner = THIS_MODULE,
+	},
+	.probe = tps6105x_regulator_probe,
+	.remove = __devexit_p(tps6105x_regulator_remove),
+};
+
+static __init int tps6105x_regulator_init(void)
+{
+	return platform_driver_register(&tps6105x_regulator_driver);
+}
+subsys_initcall(tps6105x_regulator_init);
+
+static __exit void tps6105x_regulator_exit(void)
+{
+	platform_driver_unregister(&tps6105x_regulator_driver);
+}
+module_exit(tps6105x_regulator_exit);
+
+MODULE_AUTHOR("Linus Walleij <linus.walleij@linaro.org>");
+MODULE_DESCRIPTION("TPS6105x regulator driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:tps6105x-regulator");
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/tps6524x-regulator.c linux-libre-2.6.39-gnu/drivers/regulator/tps6524x-regulator.c
--- linux-libre-2.6.38-gnu/drivers/regulator/tps6524x-regulator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/tps6524x-regulator.c	2011-05-19 00:06:34.000000000 -0400
@@ -596,7 +596,7 @@
 	.get_current_limit	= get_current_limit,
 };
 
-static int __devexit pmic_remove(struct spi_device *spi)
+static int pmic_remove(struct spi_device *spi)
 {
 	struct tps6524x *hw = spi_get_drvdata(spi);
 	int i;
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/twl-regulator.c linux-libre-2.6.39-gnu/drivers/regulator/twl-regulator.c
--- linux-libre-2.6.38-gnu/drivers/regulator/twl-regulator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/twl-regulator.c	2011-05-19 00:06:34.000000000 -0400
@@ -475,6 +475,13 @@
 	.get_status	= twlreg_get_status,
 };
 
+static struct regulator_ops twl6030_fixed_resource = {
+	.enable		= twlreg_enable,
+	.disable	= twlreg_disable,
+	.is_enabled	= twlreg_is_enabled,
+	.get_status	= twlreg_get_status,
+};
+
 /*----------------------------------------------------------------------*/
 
 #define TWL4030_FIXED_LDO(label, offset, mVolts, num, turnon_delay, \
@@ -538,6 +545,20 @@
 		}, \
 	}
 
+#define TWL6030_FIXED_RESOURCE(label, offset, num, turnon_delay, remap_conf) { \
+	.base = offset, \
+	.id = num, \
+	.delay = turnon_delay, \
+	.remap = remap_conf, \
+	.desc = { \
+		.name = #label, \
+		.id = TWL6030_REG_##label, \
+		.ops = &twl6030_fixed_resource, \
+		.type = REGULATOR_VOLTAGE, \
+		.owner = THIS_MODULE, \
+		}, \
+	}
+
 /*
  * We list regulators here if systems need some level of
  * software control over them after boot.
@@ -577,7 +598,8 @@
 	TWL6030_FIXED_LDO(VANA, 0x50, 2100, 15, 0, 0x21),
 	TWL6030_FIXED_LDO(VCXIO, 0x60, 1800, 16, 0, 0x21),
 	TWL6030_FIXED_LDO(VDAC, 0x64, 1800, 17, 0, 0x21),
-	TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21)
+	TWL6030_FIXED_LDO(VUSB, 0x70, 3300, 18, 0, 0x21),
+	TWL6030_FIXED_RESOURCE(CLK32KG, 0x8C, 48, 0, 0x21),
 };
 
 static int __devinit twlreg_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/wm831x-dcdc.c linux-libre-2.6.39-gnu/drivers/regulator/wm831x-dcdc.c
--- linux-libre-2.6.38-gnu/drivers/regulator/wm831x-dcdc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/wm831x-dcdc.c	2011-05-19 00:06:34.000000000 -0400
@@ -565,9 +565,8 @@
 	}
 
 	irq = platform_get_irq_byname(pdev, "UV");
-	ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_uv_irq,
-				 IRQF_TRIGGER_RISING, dcdc->name,
-				 dcdc);
+	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
+				   IRQF_TRIGGER_RISING, dcdc->name, dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
@@ -575,9 +574,8 @@
 	}
 
 	irq = platform_get_irq_byname(pdev, "HC");
-	ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_oc_irq,
-				 IRQF_TRIGGER_RISING, dcdc->name,
-				 dcdc);
+	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq,
+				   IRQF_TRIGGER_RISING, dcdc->name, dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
 			irq, ret);
@@ -589,7 +587,7 @@
 	return 0;
 
 err_uv:
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+	free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
 err_regulator:
 	regulator_unregister(dcdc->regulator);
 err:
@@ -606,8 +604,8 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "HC"), dcdc);
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+	free_irq(platform_get_irq_byname(pdev, "HC"), dcdc);
+	free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
 	if (dcdc->dvs_gpio)
 		gpio_free(dcdc->dvs_gpio);
@@ -756,9 +754,8 @@
 	}
 
 	irq = platform_get_irq_byname(pdev, "UV");
-	ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_uv_irq,
-				 IRQF_TRIGGER_RISING, dcdc->name,
-				 dcdc);
+	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
+				   IRQF_TRIGGER_RISING,	dcdc->name, dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
@@ -783,7 +780,7 @@
 
 	platform_set_drvdata(pdev, NULL);
 
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+	free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
 	kfree(dcdc);
 
@@ -885,9 +882,9 @@
 	}
 
 	irq = platform_get_irq_byname(pdev, "UV");
-	ret = wm831x_request_irq(wm831x, irq, wm831x_dcdc_uv_irq,
-				 IRQF_TRIGGER_RISING, dcdc->name,
-				 dcdc);
+	ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
+				   IRQF_TRIGGER_RISING, dcdc->name,
+				   dcdc);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
@@ -908,11 +905,10 @@
 static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
 {
 	struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-	struct wm831x *wm831x = dcdc->wm831x;
 
 	platform_set_drvdata(pdev, NULL);
 
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), dcdc);
+	free_irq(platform_get_irq_byname(pdev, "UV"), dcdc);
 	regulator_unregister(dcdc->regulator);
 	kfree(dcdc);
 
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/wm831x-isink.c linux-libre-2.6.39-gnu/drivers/regulator/wm831x-isink.c
--- linux-libre-2.6.38-gnu/drivers/regulator/wm831x-isink.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/wm831x-isink.c	2011-05-19 00:06:34.000000000 -0400
@@ -198,9 +198,8 @@
 	}
 
 	irq = platform_get_irq(pdev, 0);
-	ret = wm831x_request_irq(wm831x, irq, wm831x_isink_irq,
-				 IRQF_TRIGGER_RISING, isink->name,
-				 isink);
+	ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
+				   IRQF_TRIGGER_RISING, isink->name, isink);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
 			irq, ret);
@@ -221,11 +220,10 @@
 static __devexit int wm831x_isink_remove(struct platform_device *pdev)
 {
 	struct wm831x_isink *isink = platform_get_drvdata(pdev);
-	struct wm831x *wm831x = isink->wm831x;
 
 	platform_set_drvdata(pdev, NULL);
 
-	wm831x_free_irq(wm831x, platform_get_irq(pdev, 0), isink);
+	free_irq(platform_get_irq(pdev, 0), isink);
 
 	regulator_unregister(isink->regulator);
 	kfree(isink);
diff -druN linux-libre-2.6.38-gnu/drivers/regulator/wm831x-ldo.c linux-libre-2.6.39-gnu/drivers/regulator/wm831x-ldo.c
--- linux-libre-2.6.38-gnu/drivers/regulator/wm831x-ldo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/regulator/wm831x-ldo.c	2011-05-19 00:06:34.000000000 -0400
@@ -354,9 +354,9 @@
 	}
 
 	irq = platform_get_irq_byname(pdev, "UV");
-	ret = wm831x_request_irq(wm831x, irq, wm831x_ldo_uv_irq,
-				 IRQF_TRIGGER_RISING, ldo->name,
-				 ldo);
+	ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
+				   IRQF_TRIGGER_RISING, ldo->name,
+				   ldo);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
@@ -377,11 +377,10 @@
 static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
 {
 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-	struct wm831x *wm831x = ldo->wm831x;
 
 	platform_set_drvdata(pdev, NULL);
 
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), ldo);
+	free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
 	regulator_unregister(ldo->regulator);
 	kfree(ldo);
 
@@ -619,9 +618,8 @@
 	}
 
 	irq = platform_get_irq_byname(pdev, "UV");
-	ret = wm831x_request_irq(wm831x, irq, wm831x_ldo_uv_irq,
-				 IRQF_TRIGGER_RISING, ldo->name,
-				 ldo);
+	ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
+				   IRQF_TRIGGER_RISING, ldo->name, ldo);
 	if (ret != 0) {
 		dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
 			irq, ret);
@@ -642,9 +640,8 @@
 static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
 {
 	struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-	struct wm831x *wm831x = ldo->wm831x;
 
-	wm831x_free_irq(wm831x, platform_get_irq_byname(pdev, "UV"), ldo);
+	free_irq(platform_get_irq_byname(pdev, "UV"), ldo);
 	regulator_unregister(ldo->regulator);
 	kfree(ldo);
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/class.c linux-libre-2.6.39-gnu/drivers/rtc/class.c
--- linux-libre-2.6.38-gnu/drivers/rtc/class.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/class.c	2011-05-19 00:06:34.000000000 -0400
@@ -117,6 +117,7 @@
 					struct module *owner)
 {
 	struct rtc_device *rtc;
+	struct rtc_wkalrm alrm;
 	int id, err;
 
 	if (idr_pre_get(&rtc_idr, GFP_KERNEL) == 0) {
@@ -166,6 +167,12 @@
 	rtc->pie_timer.function = rtc_pie_update_irq;
 	rtc->pie_enabled = 0;
 
+	/* Check to see if there is an ALARM already set in hw */
+	err = __rtc_read_alarm(rtc, &alrm);
+
+	if (!err && !rtc_valid_tm(&alrm.time))
+		rtc_initialize_alarm(rtc, &alrm);
+
 	strlcpy(rtc->name, name, RTC_DEVICE_NAME_SIZE);
 	dev_set_name(&rtc->dev, "rtc%d", id);
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/interface.c linux-libre-2.6.39-gnu/drivers/rtc/interface.c
--- linux-libre-2.6.38-gnu/drivers/rtc/interface.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/interface.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,6 +116,186 @@
 }
 EXPORT_SYMBOL_GPL(rtc_set_mmss);
 
+static int rtc_read_alarm_internal(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+	int err;
+
+	err = mutex_lock_interruptible(&rtc->ops_lock);
+	if (err)
+		return err;
+
+	if (rtc->ops == NULL)
+		err = -ENODEV;
+	else if (!rtc->ops->read_alarm)
+		err = -EINVAL;
+	else {
+		memset(alarm, 0, sizeof(struct rtc_wkalrm));
+		err = rtc->ops->read_alarm(rtc->dev.parent, alarm);
+	}
+
+	mutex_unlock(&rtc->ops_lock);
+	return err;
+}
+
+int __rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+	int err;
+	struct rtc_time before, now;
+	int first_time = 1;
+	unsigned long t_now, t_alm;
+	enum { none, day, month, year } missing = none;
+	unsigned days;
+
+	/* The lower level RTC driver may return -1 in some fields,
+	 * creating invalid alarm->time values, for reasons like:
+	 *
+	 *   - The hardware may not be capable of filling them in;
+	 *     many alarms match only on time-of-day fields, not
+	 *     day/month/year calendar data.
+	 *
+	 *   - Some hardware uses illegal values as "wildcard" match
+	 *     values, which non-Linux firmware (like a BIOS) may try
+	 *     to set up as e.g. "alarm 15 minutes after each hour".
+	 *     Linux uses only oneshot alarms.
+	 *
+	 * When we see that here, we deal with it by using values from
+	 * a current RTC timestamp for any missing (-1) values.  The
+	 * RTC driver prevents "periodic alarm" modes.
+	 *
+	 * But this can be racey, because some fields of the RTC timestamp
+	 * may have wrapped in the interval since we read the RTC alarm,
+	 * which would lead to us inserting inconsistent values in place
+	 * of the -1 fields.
+	 *
+	 * Reading the alarm and timestamp in the reverse sequence
+	 * would have the same race condition, and not solve the issue.
+	 *
+	 * So, we must first read the RTC timestamp,
+	 * then read the RTC alarm value,
+	 * and then read a second RTC timestamp.
+	 *
+	 * If any fields of the second timestamp have changed
+	 * when compared with the first timestamp, then we know
+	 * our timestamp may be inconsistent with that used by
+	 * the low-level rtc_read_alarm_internal() function.
+	 *
+	 * So, when the two timestamps disagree, we just loop and do
+	 * the process again to get a fully consistent set of values.
+	 *
+	 * This could all instead be done in the lower level driver,
+	 * but since more than one lower level RTC implementation needs it,
+	 * then it's probably best best to do it here instead of there..
+	 */
+
+	/* Get the "before" timestamp */
+	err = rtc_read_time(rtc, &before);
+	if (err < 0)
+		return err;
+	do {
+		if (!first_time)
+			memcpy(&before, &now, sizeof(struct rtc_time));
+		first_time = 0;
+
+		/* get the RTC alarm values, which may be incomplete */
+		err = rtc_read_alarm_internal(rtc, alarm);
+		if (err)
+			return err;
+
+		/* full-function RTCs won't have such missing fields */
+		if (rtc_valid_tm(&alarm->time) == 0)
+			return 0;
+
+		/* get the "after" timestamp, to detect wrapped fields */
+		err = rtc_read_time(rtc, &now);
+		if (err < 0)
+			return err;
+
+		/* note that tm_sec is a "don't care" value here: */
+	} while (   before.tm_min   != now.tm_min
+		 || before.tm_hour  != now.tm_hour
+		 || before.tm_mon   != now.tm_mon
+		 || before.tm_year  != now.tm_year);
+
+	/* Fill in the missing alarm fields using the timestamp; we
+	 * know there's at least one since alarm->time is invalid.
+	 */
+	if (alarm->time.tm_sec == -1)
+		alarm->time.tm_sec = now.tm_sec;
+	if (alarm->time.tm_min == -1)
+		alarm->time.tm_min = now.tm_min;
+	if (alarm->time.tm_hour == -1)
+		alarm->time.tm_hour = now.tm_hour;
+
+	/* For simplicity, only support date rollover for now */
+	if (alarm->time.tm_mday == -1) {
+		alarm->time.tm_mday = now.tm_mday;
+		missing = day;
+	}
+	if (alarm->time.tm_mon == -1) {
+		alarm->time.tm_mon = now.tm_mon;
+		if (missing == none)
+			missing = month;
+	}
+	if (alarm->time.tm_year == -1) {
+		alarm->time.tm_year = now.tm_year;
+		if (missing == none)
+			missing = year;
+	}
+
+	/* with luck, no rollover is needed */
+	rtc_tm_to_time(&now, &t_now);
+	rtc_tm_to_time(&alarm->time, &t_alm);
+	if (t_now < t_alm)
+		goto done;
+
+	switch (missing) {
+
+	/* 24 hour rollover ... if it's now 10am Monday, an alarm that
+	 * that will trigger at 5am will do so at 5am Tuesday, which
+	 * could also be in the next month or year.  This is a common
+	 * case, especially for PCs.
+	 */
+	case day:
+		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "day");
+		t_alm += 24 * 60 * 60;
+		rtc_time_to_tm(t_alm, &alarm->time);
+		break;
+
+	/* Month rollover ... if it's the 31th, an alarm on the 3rd will
+	 * be next month.  An alarm matching on the 30th, 29th, or 28th
+	 * may end up in the month after that!  Many newer PCs support
+	 * this type of alarm.
+	 */
+	case month:
+		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "month");
+		do {
+			if (alarm->time.tm_mon < 11)
+				alarm->time.tm_mon++;
+			else {
+				alarm->time.tm_mon = 0;
+				alarm->time.tm_year++;
+			}
+			days = rtc_month_days(alarm->time.tm_mon,
+					alarm->time.tm_year);
+		} while (days < alarm->time.tm_mday);
+		break;
+
+	/* Year rollover ... easy except for leap years! */
+	case year:
+		dev_dbg(&rtc->dev, "alarm rollover: %s\n", "year");
+		do {
+			alarm->time.tm_year++;
+		} while (rtc_valid_tm(&alarm->time) != 0);
+		break;
+
+	default:
+		dev_warn(&rtc->dev, "alarm rollover not handled\n");
+	}
+
+done:
+	return 0;
+}
+
 int rtc_read_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
 {
 	int err;
@@ -195,6 +375,32 @@
 }
 EXPORT_SYMBOL_GPL(rtc_set_alarm);
 
+/* Called once per device from rtc_device_register */
+int rtc_initialize_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm)
+{
+	int err;
+
+	err = rtc_valid_tm(&alarm->time);
+	if (err != 0)
+		return err;
+
+	err = mutex_lock_interruptible(&rtc->ops_lock);
+	if (err)
+		return err;
+
+	rtc->aie_timer.node.expires = rtc_tm_to_ktime(alarm->time);
+	rtc->aie_timer.period = ktime_set(0, 0);
+	if (alarm->enabled) {
+		rtc->aie_timer.enabled = 1;
+		timerqueue_add(&rtc->timerqueue, &rtc->aie_timer.node);
+	}
+	mutex_unlock(&rtc->ops_lock);
+	return err;
+}
+EXPORT_SYMBOL_GPL(rtc_initialize_alarm);
+
+
+
 int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled)
 {
 	int err = mutex_lock_interruptible(&rtc->ops_lock);
@@ -274,7 +480,7 @@
  * @rtc: pointer to the rtc device
  *
  * This function is called when an AIE, UIE or PIE mode interrupt
- * has occured (or been emulated).
+ * has occurred (or been emulated).
  *
  * Triggers the registered irq_task function callback.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/Kconfig linux-libre-2.6.39-gnu/drivers/rtc/Kconfig
--- linux-libre-2.6.38-gnu/drivers/rtc/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -985,4 +985,14 @@
 	  This driver can also be buillt as a module. If so, the module
 	  will be called rtc-lpc32xx.
 
+config RTC_DRV_TEGRA
+	tristate "NVIDIA Tegra Internal RTC driver"
+	depends on RTC_CLASS && ARCH_TEGRA
+	help
+	  If you say yes here you get support for the
+	  Tegra 200 series internal RTC module.
+
+	  This drive can also be built as a module. If so, the module
+	  will be called rtc-tegra.
+
 endif # RTC_CLASS
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/Makefile linux-libre-2.6.39-gnu/drivers/rtc/Makefile
--- linux-libre-2.6.38-gnu/drivers/rtc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -2,9 +2,7 @@
 # Makefile for RTC class/drivers.
 #
 
-ifeq ($(CONFIG_RTC_DEBUG),y)
-	EXTRA_CFLAGS		+= -DDEBUG
-endif
+ccflags-$(CONFIG_RTC_DEBUG)	:= -DDEBUG
 
 obj-$(CONFIG_RTC_LIB)		+= rtc-lib.o
 obj-$(CONFIG_RTC_HCTOSYS)	+= hctosys.o
@@ -93,6 +91,7 @@
 obj-$(CONFIG_RTC_DRV_STK17TA8)	+= rtc-stk17ta8.o
 obj-$(CONFIG_RTC_DRV_STMP)	+= rtc-stmp3xxx.o
 obj-$(CONFIG_RTC_DRV_SUN4V)	+= rtc-sun4v.o
+obj-$(CONFIG_RTC_DRV_TEGRA)	+= rtc-tegra.o
 obj-$(CONFIG_RTC_DRV_TEST)	+= rtc-test.o
 obj-$(CONFIG_RTC_DRV_TWL4030)	+= rtc-twl.o
 obj-$(CONFIG_RTC_DRV_TX4939)	+= rtc-tx4939.o
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-at91rm9200.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-at91rm9200.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-at91rm9200.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-at91rm9200.c	2011-05-19 00:06:34.000000000 -0400
@@ -60,7 +60,7 @@
 	/*
 	 * The Calendar Alarm register does not have a field for
 	 * the year - so these will return an invalid value.  When an
-	 * alarm is set, at91_alarm_year wille store the current year.
+	 * alarm is set, at91_alarm_year will store the current year.
 	 */
 	tm->tm_year  = bcd2bin(date & AT91_RTC_CENT) * 100;	/* century */
 	tm->tm_year += bcd2bin((date & AT91_RTC_YEAR) >> 8);	/* year */
@@ -183,33 +183,6 @@
 	return 0;
 }
 
-/*
- * Handle commands from user-space
- */
-static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
-			unsigned long arg)
-{
-	int ret = 0;
-
-	pr_debug("%s(): cmd=%08x, arg=%08lx.\n", __func__, cmd, arg);
-
-	/* important:  scrub old status before enabling IRQs */
-	switch (cmd) {
-	case RTC_UIE_OFF:	/* update off */
-		at91_sys_write(AT91_RTC_IDR, AT91_RTC_SECEV);
-		break;
-	case RTC_UIE_ON:	/* update on */
-		at91_sys_write(AT91_RTC_SCCR, AT91_RTC_SECEV);
-		at91_sys_write(AT91_RTC_IER, AT91_RTC_SECEV);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-
-	return ret;
-}
-
 static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	pr_debug("%s(): cmd=%08x\n", __func__, enabled);
@@ -269,7 +242,6 @@
 }
 
 static const struct rtc_class_ops at91_rtc_ops = {
-	.ioctl		= at91_rtc_ioctl,
 	.read_time	= at91_rtc_readtime,
 	.set_time	= at91_rtc_settime,
 	.read_alarm	= at91_rtc_readalarm,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-at91sam9.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-at91sam9.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-at91sam9.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-at91sam9.c	2011-05-19 00:06:34.000000000 -0400
@@ -216,33 +216,6 @@
 	return 0;
 }
 
-/*
- * Handle commands from user-space
- */
-static int at91_rtc_ioctl(struct device *dev, unsigned int cmd,
-			unsigned long arg)
-{
-	struct sam9_rtc *rtc = dev_get_drvdata(dev);
-	int ret = 0;
-	u32 mr = rtt_readl(rtc, MR);
-
-	dev_dbg(dev, "ioctl: cmd=%08x, arg=%08lx, mr %08x\n", cmd, arg, mr);
-
-	switch (cmd) {
-	case RTC_UIE_OFF:		/* update off */
-		rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
-		break;
-	case RTC_UIE_ON:		/* update on */
-		rtt_writel(rtc, MR, mr | AT91_RTT_RTTINCIEN);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-		break;
-	}
-
-	return ret;
-}
-
 static int at91_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct sam9_rtc *rtc = dev_get_drvdata(dev);
@@ -303,7 +276,6 @@
 }
 
 static const struct rtc_class_ops at91_rtc_ops = {
-	.ioctl		= at91_rtc_ioctl,
 	.read_time	= at91_rtc_readtime,
 	.set_time	= at91_rtc_settime,
 	.read_alarm	= at91_rtc_readalarm,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-bfin.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-bfin.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-bfin.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-bfin.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,9 +20,9 @@
  * write would be discarded and things quickly fall apart.
  *
  * To keep this delay from significantly degrading performance (we, in theory,
- * would have to sleep for up to 1 second everytime we wanted to write a
+ * would have to sleep for up to 1 second every time we wanted to write a
  * register), we only check the write pending status before we start to issue
- * a new write.  We bank on the idea that it doesnt matter when the sync
+ * a new write.  We bank on the idea that it doesn't matter when the sync
  * happens so long as we don't attempt another write before it does.  The only
  * time userspace would take this penalty is when they try and do multiple
  * operations right after another ... but in this case, they need to take the
@@ -240,32 +240,6 @@
 	 */
 	bfin_rtc_int_set(rtc->rtc_alarm.tm_yday == -1 ? RTC_ISTAT_ALARM : RTC_ISTAT_ALARM_DAY);
 }
-static int bfin_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	struct bfin_rtc *rtc = dev_get_drvdata(dev);
-	int ret = 0;
-
-	dev_dbg_stamp(dev);
-
-	bfin_rtc_sync_pending(dev);
-
-	switch (cmd) {
-	case RTC_UIE_ON:
-		dev_dbg_stamp(dev);
-		bfin_rtc_int_set(RTC_ISTAT_SEC);
-		break;
-	case RTC_UIE_OFF:
-		dev_dbg_stamp(dev);
-		bfin_rtc_int_clear(~RTC_ISTAT_SEC);
-		break;
-
-	default:
-		dev_dbg_stamp(dev);
-		ret = -ENOIOCTLCMD;
-	}
-
-	return ret;
-}
 
 static int bfin_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
@@ -276,6 +250,8 @@
 		bfin_rtc_int_set_alarm(rtc);
 	else
 		bfin_rtc_int_clear(~(RTC_ISTAT_ALARM | RTC_ISTAT_ALARM_DAY));
+
+	return 0;
 }
 
 static int bfin_rtc_read_time(struct device *dev, struct rtc_time *tm)
@@ -358,7 +334,6 @@
 }
 
 static struct rtc_class_ops bfin_rtc_ops = {
-	.ioctl         = bfin_rtc_ioctl,
 	.read_time     = bfin_rtc_read_time,
 	.set_time      = bfin_rtc_set_time,
 	.read_alarm    = bfin_rtc_read_alarm,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-cmos.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-cmos.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-cmos.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-cmos.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,6 +37,8 @@
 #include <linux/mod_devicetable.h>
 #include <linux/log2.h>
 #include <linux/pm.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
 
 /* this is for "generic access to PC-style RTC" using CMOS_READ/CMOS_WRITE */
 #include <asm-generic/rtc.h>
@@ -375,50 +377,6 @@
 	return 0;
 }
 
-static int cmos_irq_set_freq(struct device *dev, int freq)
-{
-	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
-	int		f;
-	unsigned long	flags;
-
-	if (!is_valid_irq(cmos->irq))
-		return -ENXIO;
-
-	if (!is_power_of_2(freq))
-		return -EINVAL;
-	/* 0 = no irqs; 1 = 2^15 Hz ... 15 = 2^0 Hz */
-	f = ffs(freq);
-	if (f-- > 16)
-		return -EINVAL;
-	f = 16 - f;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-	hpet_set_periodic_freq(freq);
-	CMOS_WRITE(RTC_REF_CLCK_32KHZ | f, RTC_FREQ_SELECT);
-	spin_unlock_irqrestore(&rtc_lock, flags);
-
-	return 0;
-}
-
-static int cmos_irq_set_state(struct device *dev, int enabled)
-{
-	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
-	unsigned long	flags;
-
-	if (!is_valid_irq(cmos->irq))
-		return -ENXIO;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-
-	if (enabled)
-		cmos_irq_enable(cmos, RTC_PIE);
-	else
-		cmos_irq_disable(cmos, RTC_PIE);
-
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return 0;
-}
-
 static int cmos_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
@@ -438,25 +396,6 @@
 	return 0;
 }
 
-static int cmos_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct cmos_rtc	*cmos = dev_get_drvdata(dev);
-	unsigned long	flags;
-
-	if (!is_valid_irq(cmos->irq))
-		return -EINVAL;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-
-	if (enabled)
-		cmos_irq_enable(cmos, RTC_UIE);
-	else
-		cmos_irq_disable(cmos, RTC_UIE);
-
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return 0;
-}
-
 #if defined(CONFIG_RTC_INTF_PROC) || defined(CONFIG_RTC_INTF_PROC_MODULE)
 
 static int cmos_procfs(struct device *dev, struct seq_file *seq)
@@ -501,10 +440,7 @@
 	.read_alarm		= cmos_read_alarm,
 	.set_alarm		= cmos_set_alarm,
 	.proc			= cmos_procfs,
-	.irq_set_freq		= cmos_irq_set_freq,
-	.irq_set_state		= cmos_irq_set_state,
 	.alarm_irq_enable	= cmos_alarm_irq_enable,
-	.update_irq_enable	= cmos_update_irq_enable,
 };
 
 /*----------------------------------------------------------------*/
@@ -1123,6 +1059,47 @@
 
 #endif	/* CONFIG_PNP */
 
+#ifdef CONFIG_OF
+static const struct of_device_id of_cmos_match[] = {
+	{
+		.compatible = "motorola,mc146818",
+	},
+	{ },
+};
+MODULE_DEVICE_TABLE(of, of_cmos_match);
+
+static __init void cmos_of_init(struct platform_device *pdev)
+{
+	struct device_node *node = pdev->dev.of_node;
+	struct rtc_time time;
+	int ret;
+	const __be32 *val;
+
+	if (!node)
+		return;
+
+	val = of_get_property(node, "ctrl-reg", NULL);
+	if (val)
+		CMOS_WRITE(be32_to_cpup(val), RTC_CONTROL);
+
+	val = of_get_property(node, "freq-reg", NULL);
+	if (val)
+		CMOS_WRITE(be32_to_cpup(val), RTC_FREQ_SELECT);
+
+	get_rtc_time(&time);
+	ret = rtc_valid_tm(&time);
+	if (ret) {
+		struct rtc_time def_time = {
+			.tm_year = 1,
+			.tm_mday = 1,
+		};
+		set_rtc_time(&def_time);
+	}
+}
+#else
+static inline void cmos_of_init(struct platform_device *pdev) {}
+#define of_cmos_match NULL
+#endif
 /*----------------------------------------------------------------*/
 
 /* Platform setup should have set up an RTC device, when PNP is
@@ -1131,6 +1108,7 @@
 
 static int __init cmos_platform_probe(struct platform_device *pdev)
 {
+	cmos_of_init(pdev);
 	cmos_wake_setup(&pdev->dev);
 	return cmos_do_probe(&pdev->dev,
 			platform_get_resource(pdev, IORESOURCE_IO, 0),
@@ -1162,6 +1140,7 @@
 #ifdef CONFIG_PM
 		.pm		= &cmos_pm_ops,
 #endif
+		.of_match_table = of_cmos_match,
 	}
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-coh901331.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-coh901331.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-coh901331.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-coh901331.c	2011-05-19 00:06:34.000000000 -0400
@@ -220,6 +220,7 @@
 	}
 	clk_disable(rtap->clk);
 
+	platform_set_drvdata(pdev, rtap);
 	rtap->rtc = rtc_device_register("coh901331", &pdev->dev, &coh901331_ops,
 					 THIS_MODULE);
 	if (IS_ERR(rtap->rtc)) {
@@ -227,11 +228,10 @@
 		goto out_no_rtc;
 	}
 
-	platform_set_drvdata(pdev, rtap);
-
 	return 0;
 
  out_no_rtc:
+	platform_set_drvdata(pdev, NULL);
  out_no_clk_enable:
 	clk_put(rtap->clk);
  out_no_clk:
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-davinci.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-davinci.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-davinci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-davinci.c	2011-05-19 00:06:34.000000000 -0400
@@ -231,10 +231,6 @@
 	case RTC_WIE_OFF:
 		rtc_ctrl &= ~PRTCSS_RTC_CTRL_WEN;
 		break;
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		ret = -ENOTTY;
-		break;
 	default:
 		ret = -ENOIOCTLCMD;
 	}
@@ -473,55 +469,6 @@
 	return 0;
 }
 
-static int davinci_rtc_irq_set_state(struct device *dev, int enabled)
-{
-	struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
-	unsigned long flags;
-	u8 rtc_ctrl;
-
-	spin_lock_irqsave(&davinci_rtc_lock, flags);
-
-	rtc_ctrl = rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL);
-
-	if (enabled) {
-		while (rtcss_read(davinci_rtc, PRTCSS_RTC_CTRL)
-		       & PRTCSS_RTC_CTRL_WDTBUS)
-			cpu_relax();
-
-		rtc_ctrl |= PRTCSS_RTC_CTRL_TE;
-		rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL);
-
-		rtcss_write(davinci_rtc, 0x0, PRTCSS_RTC_CLKC_CNT);
-
-		rtc_ctrl |= PRTCSS_RTC_CTRL_TIEN |
-			    PRTCSS_RTC_CTRL_TMMD |
-			    PRTCSS_RTC_CTRL_TMRFLG;
-	} else
-		rtc_ctrl &= ~PRTCSS_RTC_CTRL_TIEN;
-
-	rtcss_write(davinci_rtc, rtc_ctrl, PRTCSS_RTC_CTRL);
-
-	spin_unlock_irqrestore(&davinci_rtc_lock, flags);
-
-	return 0;
-}
-
-static int davinci_rtc_irq_set_freq(struct device *dev, int freq)
-{
-	struct davinci_rtc *davinci_rtc = dev_get_drvdata(dev);
-	unsigned long flags;
-	u16 tmr_counter = (0x8000 >> (ffs(freq) - 1));
-
-	spin_lock_irqsave(&davinci_rtc_lock, flags);
-
-	rtcss_write(davinci_rtc, tmr_counter & 0xFF, PRTCSS_RTC_TMR0);
-	rtcss_write(davinci_rtc, (tmr_counter & 0xFF00) >> 8, PRTCSS_RTC_TMR1);
-
-	spin_unlock_irqrestore(&davinci_rtc_lock, flags);
-
-	return 0;
-}
-
 static struct rtc_class_ops davinci_rtc_ops = {
 	.ioctl			= davinci_rtc_ioctl,
 	.read_time		= davinci_rtc_read_time,
@@ -529,8 +476,6 @@
 	.alarm_irq_enable	= davinci_rtc_alarm_irq_enable,
 	.read_alarm		= davinci_rtc_read_alarm,
 	.set_alarm		= davinci_rtc_set_alarm,
-	.irq_set_state		= davinci_rtc_irq_set_state,
-	.irq_set_freq		= davinci_rtc_irq_set_freq,
 };
 
 static int __init davinci_rtc_probe(struct platform_device *pdev)
@@ -579,6 +524,8 @@
 		goto fail2;
 	}
 
+	platform_set_drvdata(pdev, davinci_rtc);
+
 	davinci_rtc->rtc = rtc_device_register(pdev->name, &pdev->dev,
 				    &davinci_rtc_ops, THIS_MODULE);
 	if (IS_ERR(davinci_rtc->rtc)) {
@@ -608,8 +555,6 @@
 
 	rtcss_write(davinci_rtc, PRTCSS_RTC_CCTRL_CAEN, PRTCSS_RTC_CCTRL);
 
-	platform_set_drvdata(pdev, davinci_rtc);
-
 	device_init_wakeup(&pdev->dev, 0);
 
 	return 0;
@@ -617,6 +562,7 @@
 fail4:
 	rtc_device_unregister(davinci_rtc->rtc);
 fail3:
+	platform_set_drvdata(pdev, NULL);
 	iounmap(davinci_rtc->base);
 fail2:
 	release_mem_region(davinci_rtc->pbase, davinci_rtc->base_size);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1286.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1286.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1286.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1286.c	2011-05-19 00:06:34.000000000 -0400
@@ -355,6 +355,7 @@
 		goto out;
 	}
 	spin_lock_init(&priv->lock);
+	platform_set_drvdata(pdev, priv);
 	rtc = rtc_device_register("ds1286", &pdev->dev,
 				  &ds1286_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
@@ -362,7 +363,6 @@
 		goto out;
 	}
 	priv->rtc = rtc;
-	platform_set_drvdata(pdev, priv);
 	return 0;
 
 out:
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1374.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1374.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1374.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1374.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/bcd.h>
 #include <linux/workqueue.h>
 #include <linux/slab.h>
+#include <linux/pm.h>
 
 #define DS1374_REG_TOD0		0x00 /* Time of Day */
 #define DS1374_REG_TOD1		0x01
@@ -409,32 +410,38 @@
 }
 
 #ifdef CONFIG_PM
-static int ds1374_suspend(struct i2c_client *client, pm_message_t state)
+static int ds1374_suspend(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	if (client->irq >= 0 && device_may_wakeup(&client->dev))
 		enable_irq_wake(client->irq);
 	return 0;
 }
 
-static int ds1374_resume(struct i2c_client *client)
+static int ds1374_resume(struct device *dev)
 {
+	struct i2c_client *client = to_i2c_client(dev);
+
 	if (client->irq >= 0 && device_may_wakeup(&client->dev))
 		disable_irq_wake(client->irq);
 	return 0;
 }
+
+static SIMPLE_DEV_PM_OPS(ds1374_pm, ds1374_suspend, ds1374_resume);
+
+#define DS1374_PM (&ds1374_pm)
 #else
-#define ds1374_suspend	NULL
-#define ds1374_resume	NULL
+#define DS1374_PM NULL
 #endif
 
 static struct i2c_driver ds1374_driver = {
 	.driver = {
 		.name = "rtc-ds1374",
 		.owner = THIS_MODULE,
+		.pm = DS1374_PM,
 	},
 	.probe = ds1374_probe,
-	.suspend = ds1374_suspend,
-	.resume = ds1374_resume,
 	.remove = __devexit_p(ds1374_remove),
 	.id_table = ds1374_id,
 };
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1390.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1390.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1390.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1390.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,7 +158,7 @@
 
 static int __devexit ds1390_remove(struct spi_device *spi)
 {
-	struct ds1390 *chip = platform_get_drvdata(spi);
+	struct ds1390 *chip = spi_get_drvdata(spi);
 
 	rtc_device_unregister(chip->rtc);
 	kfree(chip);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1511.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1511.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1511.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1511.c	2011-05-19 00:06:34.000000000 -0400
@@ -397,29 +397,12 @@
 	return 0;
 }
 
-static int ds1511_rtc_update_irq_enable(struct device *dev,
-	unsigned int enabled)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-	if (pdata->irq <= 0)
-		return -EINVAL;
-	if (enabled)
-		pdata->irqen |= RTC_UF;
-	else
-		pdata->irqen &= ~RTC_UF;
-	ds1511_rtc_update_alarm(pdata);
-	return 0;
-}
-
 static const struct rtc_class_ops ds1511_rtc_ops = {
 	.read_time		= ds1511_rtc_read_time,
 	.set_time		= ds1511_rtc_set_time,
 	.read_alarm		= ds1511_rtc_read_alarm,
 	.set_alarm		= ds1511_rtc_set_alarm,
 	.alarm_irq_enable	= ds1511_rtc_alarm_irq_enable,
-	.update_irq_enable	= ds1511_rtc_update_irq_enable,
 };
 
  static ssize_t
@@ -485,7 +468,7 @@
 static struct bin_attribute ds1511_nvram_attr = {
 	.attr = {
 		.name = "nvram",
-		.mode = S_IRUGO | S_IWUGO,
+		.mode = S_IRUGO | S_IWUSR,
 	},
 	.size = DS1511_RAM_MAX,
 	.read = ds1511_nvram_read,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1553.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1553.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds1553.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds1553.c	2011-05-19 00:06:34.000000000 -0400
@@ -227,29 +227,12 @@
 	return 0;
 }
 
-static int ds1553_rtc_update_irq_enable(struct device *dev,
-	unsigned int enabled)
-{
-	struct platform_device *pdev = to_platform_device(dev);
-	struct rtc_plat_data *pdata = platform_get_drvdata(pdev);
-
-	if (pdata->irq <= 0)
-		return -EINVAL;
-	if (enabled)
-		pdata->irqen |= RTC_UF;
-	else
-		pdata->irqen &= ~RTC_UF;
-	ds1553_rtc_update_alarm(pdata);
-	return 0;
-}
-
 static const struct rtc_class_ops ds1553_rtc_ops = {
 	.read_time		= ds1553_rtc_read_time,
 	.set_time		= ds1553_rtc_set_time,
 	.read_alarm		= ds1553_rtc_read_alarm,
 	.set_alarm		= ds1553_rtc_set_alarm,
 	.alarm_irq_enable	= ds1553_rtc_alarm_irq_enable,
-	.update_irq_enable	= ds1553_rtc_update_irq_enable,
 };
 
 static ssize_t ds1553_nvram_read(struct file *filp, struct kobject *kobj,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds3232.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds3232.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds3232.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds3232.c	2011-05-19 00:06:34.000000000 -0400
@@ -339,23 +339,6 @@
 	return 0;
 }
 
-static int ds3232_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct ds3232 *ds3232 = i2c_get_clientdata(client);
-
-	if (client->irq <= 0)
-		return -EINVAL;
-
-	if (enabled)
-		ds3232->rtc->irq_data |= RTC_UF;
-	else
-		ds3232->rtc->irq_data &= ~RTC_UF;
-
-	ds3232_update_alarm(client);
-	return 0;
-}
-
 static irqreturn_t ds3232_irq(int irq, void *dev_id)
 {
 	struct i2c_client *client = dev_id;
@@ -406,7 +389,6 @@
 	.read_alarm = ds3232_read_alarm,
 	.set_alarm = ds3232_set_alarm,
 	.alarm_irq_enable = ds3232_alarm_irq_enable,
-	.update_irq_enable = ds3232_update_irq_enable,
 };
 
 static int __devinit ds3232_probe(struct i2c_client *client,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds3234.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds3234.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ds3234.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ds3234.c	2011-05-19 00:06:34.000000000 -0400
@@ -158,7 +158,7 @@
 
 static int __devexit ds3234_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = platform_get_drvdata(spi);
+	struct rtc_device *rtc = spi_get_drvdata(spi);
 
 	rtc_device_unregister(rtc);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-ep93xx.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-ep93xx.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-ep93xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-ep93xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -151,6 +151,7 @@
 		return -ENXIO;
 
 	pdev->dev.platform_data = ep93xx_rtc;
+	platform_set_drvdata(pdev, rtc);
 
 	rtc = rtc_device_register(pdev->name,
 				&pdev->dev, &ep93xx_rtc_ops, THIS_MODULE);
@@ -159,8 +160,6 @@
 		goto exit;
 	}
 
-	platform_set_drvdata(pdev, rtc);
-
 	err = sysfs_create_group(&pdev->dev.kobj, &ep93xx_rtc_sysfs_files);
 	if (err)
 		goto fail;
@@ -168,9 +167,9 @@
 	return 0;
 
 fail:
-	platform_set_drvdata(pdev, NULL);
 	rtc_device_unregister(rtc);
 exit:
+	platform_set_drvdata(pdev, NULL);
 	pdev->dev.platform_data = NULL;
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-isl1208.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-isl1208.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-isl1208.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-isl1208.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,6 +39,8 @@
 #define ISL1208_REG_SR_BAT     (1<<1)	/* battery */
 #define ISL1208_REG_SR_RTCF    (1<<0)	/* rtc fail */
 #define ISL1208_REG_INT 0x08
+#define ISL1208_REG_INT_ALME   (1<<6)   /* alarm enable */
+#define ISL1208_REG_INT_IM     (1<<7)   /* interrupt/alarm mode */
 #define ISL1208_REG_09  0x09	/* reserved */
 #define ISL1208_REG_ATR 0x0a
 #define ISL1208_REG_DTR 0x0b
@@ -202,6 +204,30 @@
 }
 
 static int
+isl1208_rtc_toggle_alarm(struct i2c_client *client, int enable)
+{
+	int icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT);
+
+	if (icr < 0) {
+		dev_err(&client->dev, "%s: reading INT failed\n", __func__);
+		return icr;
+	}
+
+	if (enable)
+		icr |= ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM;
+	else
+		icr &= ~(ISL1208_REG_INT_ALME | ISL1208_REG_INT_IM);
+
+	icr = i2c_smbus_write_byte_data(client, ISL1208_REG_INT, icr);
+	if (icr < 0) {
+		dev_err(&client->dev, "%s: writing INT failed\n", __func__);
+		return icr;
+	}
+
+	return 0;
+}
+
+static int
 isl1208_rtc_proc(struct device *dev, struct seq_file *seq)
 {
 	struct i2c_client *const client = to_i2c_client(dev);
@@ -288,9 +314,8 @@
 {
 	struct rtc_time *const tm = &alarm->time;
 	u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
-	int sr;
+	int icr, yr, sr = isl1208_i2c_get_sr(client);
 
-	sr = isl1208_i2c_get_sr(client);
 	if (sr < 0) {
 		dev_err(&client->dev, "%s: reading SR failed\n", __func__);
 		return sr;
@@ -313,6 +338,73 @@
 		bcd2bin(regs[ISL1208_REG_MOA - ISL1208_REG_SCA] & 0x1f) - 1;
 	tm->tm_wday = bcd2bin(regs[ISL1208_REG_DWA - ISL1208_REG_SCA] & 0x03);
 
+	/* The alarm doesn't store the year so get it from the rtc section */
+	yr = i2c_smbus_read_byte_data(client, ISL1208_REG_YR);
+	if (yr < 0) {
+		dev_err(&client->dev, "%s: reading RTC YR failed\n", __func__);
+		return yr;
+	}
+	tm->tm_year = bcd2bin(yr) + 100;
+
+	icr = i2c_smbus_read_byte_data(client, ISL1208_REG_INT);
+	if (icr < 0) {
+		dev_err(&client->dev, "%s: reading INT failed\n", __func__);
+		return icr;
+	}
+	alarm->enabled = !!(icr & ISL1208_REG_INT_ALME);
+
+	return 0;
+}
+
+static int
+isl1208_i2c_set_alarm(struct i2c_client *client, struct rtc_wkalrm *alarm)
+{
+	struct rtc_time *alarm_tm = &alarm->time;
+	u8 regs[ISL1208_ALARM_SECTION_LEN] = { 0, };
+	const int offs = ISL1208_REG_SCA;
+	unsigned long rtc_secs, alarm_secs;
+	struct rtc_time rtc_tm;
+	int err, enable;
+
+	err = isl1208_i2c_read_time(client, &rtc_tm);
+	if (err)
+		return err;
+	err = rtc_tm_to_time(&rtc_tm, &rtc_secs);
+	if (err)
+		return err;
+	err = rtc_tm_to_time(alarm_tm, &alarm_secs);
+	if (err)
+		return err;
+
+	/* If the alarm time is before the current time disable the alarm */
+	if (!alarm->enabled || alarm_secs <= rtc_secs)
+		enable = 0x00;
+	else
+		enable = 0x80;
+
+	/* Program the alarm and enable it for each setting */
+	regs[ISL1208_REG_SCA - offs] = bin2bcd(alarm_tm->tm_sec) | enable;
+	regs[ISL1208_REG_MNA - offs] = bin2bcd(alarm_tm->tm_min) | enable;
+	regs[ISL1208_REG_HRA - offs] = bin2bcd(alarm_tm->tm_hour) |
+		ISL1208_REG_HR_MIL | enable;
+
+	regs[ISL1208_REG_DTA - offs] = bin2bcd(alarm_tm->tm_mday) | enable;
+	regs[ISL1208_REG_MOA - offs] = bin2bcd(alarm_tm->tm_mon + 1) | enable;
+	regs[ISL1208_REG_DWA - offs] = bin2bcd(alarm_tm->tm_wday & 7) | enable;
+
+	/* write ALARM registers */
+	err = isl1208_i2c_set_regs(client, offs, regs,
+				  ISL1208_ALARM_SECTION_LEN);
+	if (err < 0) {
+		dev_err(&client->dev, "%s: writing ALARM section failed\n",
+			__func__);
+		return err;
+	}
+
+	err = isl1208_rtc_toggle_alarm(client, enable);
+	if (err)
+		return err;
+
 	return 0;
 }
 
@@ -391,12 +483,63 @@
 	return isl1208_i2c_read_alarm(to_i2c_client(dev), alarm);
 }
 
+static int
+isl1208_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	return isl1208_i2c_set_alarm(to_i2c_client(dev), alarm);
+}
+
+static irqreturn_t
+isl1208_rtc_interrupt(int irq, void *data)
+{
+	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+	struct i2c_client *client = data;
+	int handled = 0, sr, err;
+
+	/*
+	 * I2C reads get NAK'ed if we read straight away after an interrupt?
+	 * Using a mdelay/msleep didn't seem to help either, so we work around
+	 * this by continually trying to read the register for a short time.
+	 */
+	while (1) {
+		sr = isl1208_i2c_get_sr(client);
+		if (sr >= 0)
+			break;
+
+		if (time_after(jiffies, timeout)) {
+			dev_err(&client->dev, "%s: reading SR failed\n",
+				__func__);
+			return sr;
+		}
+	}
+
+	if (sr & ISL1208_REG_SR_ALM) {
+		dev_dbg(&client->dev, "alarm!\n");
+
+		/* Clear the alarm */
+		sr &= ~ISL1208_REG_SR_ALM;
+		sr = i2c_smbus_write_byte_data(client, ISL1208_REG_SR, sr);
+		if (sr < 0)
+			dev_err(&client->dev, "%s: writing SR failed\n",
+				__func__);
+		else
+			handled = 1;
+
+		/* Disable the alarm */
+		err = isl1208_rtc_toggle_alarm(client, 0);
+		if (err)
+			return err;
+	}
+
+	return handled ? IRQ_HANDLED : IRQ_NONE;
+}
+
 static const struct rtc_class_ops isl1208_rtc_ops = {
 	.proc = isl1208_rtc_proc,
 	.read_time = isl1208_rtc_read_time,
 	.set_time = isl1208_rtc_set_time,
 	.read_alarm = isl1208_rtc_read_alarm,
-	/*.set_alarm    = isl1208_rtc_set_alarm, */
+	.set_alarm = isl1208_rtc_set_alarm,
 };
 
 /* sysfs interface */
@@ -488,11 +631,29 @@
 	dev_info(&client->dev,
 		 "chip found, driver version " DRV_VERSION "\n");
 
+	if (client->irq > 0) {
+		rc = request_threaded_irq(client->irq, NULL,
+					  isl1208_rtc_interrupt,
+					  IRQF_SHARED,
+					  isl1208_driver.driver.name, client);
+		if (!rc) {
+			device_init_wakeup(&client->dev, 1);
+			enable_irq_wake(client->irq);
+		} else {
+			dev_err(&client->dev,
+				"Unable to request irq %d, no alarm support\n",
+				client->irq);
+			client->irq = 0;
+		}
+	}
+
 	rtc = rtc_device_register(isl1208_driver.driver.name,
 				  &client->dev, &isl1208_rtc_ops,
 				  THIS_MODULE);
-	if (IS_ERR(rtc))
-		return PTR_ERR(rtc);
+	if (IS_ERR(rtc)) {
+		rc = PTR_ERR(rtc);
+		goto exit_free_irq;
+	}
 
 	i2c_set_clientdata(client, rtc);
 
@@ -514,6 +675,9 @@
 
 exit_unregister:
 	rtc_device_unregister(rtc);
+exit_free_irq:
+	if (client->irq)
+		free_irq(client->irq, client);
 
 	return rc;
 }
@@ -525,6 +689,8 @@
 
 	sysfs_remove_group(&client->dev.kobj, &isl1208_rtc_sysfs_files);
 	rtc_device_unregister(rtc);
+	if (client->irq)
+		free_irq(client->irq, client);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-jz4740.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-jz4740.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-jz4740.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-jz4740.c	2011-05-19 00:06:34.000000000 -0400
@@ -168,12 +168,6 @@
 	return ret;
 }
 
-static int jz4740_rtc_update_irq_enable(struct device *dev, unsigned int enable)
-{
-	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
-	return jz4740_rtc_ctrl_set_bits(rtc, JZ_RTC_CTRL_1HZ_IRQ, enable);
-}
-
 static int jz4740_rtc_alarm_irq_enable(struct device *dev, unsigned int enable)
 {
 	struct jz4740_rtc *rtc = dev_get_drvdata(dev);
@@ -185,7 +179,6 @@
 	.set_mmss	= jz4740_rtc_set_mmss,
 	.read_alarm	= jz4740_rtc_read_alarm,
 	.set_alarm	= jz4740_rtc_set_alarm,
-	.update_irq_enable = jz4740_rtc_update_irq_enable,
 	.alarm_irq_enable = jz4740_rtc_alarm_irq_enable,
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-lpc32xx.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-lpc32xx.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-lpc32xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-lpc32xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,7 +240,7 @@
 	spin_lock_init(&rtc->lock);
 
 	/*
-	 * The RTC is on a seperate power domain and can keep it's state
+	 * The RTC is on a separate power domain and can keep it's state
 	 * across a chip power cycle. If the RTC has never been previously
 	 * setup, then set it up now for the first time.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-m41t80.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-m41t80.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-m41t80.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-m41t80.c	2011-05-19 00:06:34.000000000 -0400
@@ -783,6 +783,9 @@
 		goto exit;
 	}
 
+	clientdata->features = id->driver_data;
+	i2c_set_clientdata(client, clientdata);
+
 	rtc = rtc_device_register(client->name, &client->dev,
 				  &m41t80_rtc_ops, THIS_MODULE);
 	if (IS_ERR(rtc)) {
@@ -792,8 +795,6 @@
 	}
 
 	clientdata->rtc = rtc;
-	clientdata->features = id->driver_data;
-	i2c_set_clientdata(client, clientdata);
 
 	/* Make sure HT (Halt Update) bit is cleared */
 	rc = i2c_smbus_read_byte_data(client, M41T80_REG_ALARM_HOUR);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-m41t94.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-m41t94.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-m41t94.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-m41t94.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,7 @@
 
 static int __devexit m41t94_remove(struct spi_device *spi)
 {
-	struct rtc_device *rtc = platform_get_drvdata(spi);
+	struct rtc_device *rtc = spi_get_drvdata(spi);
 
 	if (rtc)
 		rtc_device_unregister(rtc);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-max8925.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-max8925.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-max8925.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-max8925.c	2011-05-19 00:06:34.000000000 -0400
@@ -257,6 +257,10 @@
 		goto out_irq;
 	}
 
+	dev_set_drvdata(&pdev->dev, info);
+	/* XXX - isn't this redundant? */
+	platform_set_drvdata(pdev, info);
+
 	info->rtc_dev = rtc_device_register("max8925-rtc", &pdev->dev,
 					&max8925_rtc_ops, THIS_MODULE);
 	ret = PTR_ERR(info->rtc_dev);
@@ -265,11 +269,9 @@
 		goto out_rtc;
 	}
 
-	dev_set_drvdata(&pdev->dev, info);
-	platform_set_drvdata(pdev, info);
-
 	return 0;
 out_rtc:
+	platform_set_drvdata(pdev, NULL);
 	free_irq(chip->irq_base + MAX8925_IRQ_RTC_ALARM0, info);
 out_irq:
 	kfree(info);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-max8998.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-max8998.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-max8998.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-max8998.c	2011-05-19 00:06:34.000000000 -0400
@@ -265,6 +265,8 @@
 	info->rtc = max8998->rtc;
 	info->irq = max8998->irq_base + MAX8998_IRQ_ALARM0;
 
+	platform_set_drvdata(pdev, info);
+
 	info->rtc_dev = rtc_device_register("max8998-rtc", &pdev->dev,
 			&max8998_rtc_ops, THIS_MODULE);
 
@@ -274,8 +276,6 @@
 		goto out_rtc;
 	}
 
-	platform_set_drvdata(pdev, info);
-
 	ret = request_threaded_irq(info->irq, NULL, max8998_rtc_alarm_irq, 0,
 			"rtc-alarm0", info);
 
@@ -293,6 +293,7 @@
 	return 0;
 
 out_rtc:
+	platform_set_drvdata(pdev, NULL);
 	kfree(info);
 	return ret;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-mc13xxx.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-mc13xxx.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-mc13xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-mc13xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -282,12 +282,6 @@
 	return IRQ_HANDLED;
 }
 
-static int mc13xxx_rtc_update_irq_enable(struct device *dev,
-		unsigned int enabled)
-{
-	return mc13xxx_rtc_irq_enable(dev, enabled, MC13XXX_IRQ_1HZ);
-}
-
 static int mc13xxx_rtc_alarm_irq_enable(struct device *dev,
 		unsigned int enabled)
 {
@@ -300,7 +294,6 @@
 	.read_alarm = mc13xxx_rtc_read_alarm,
 	.set_alarm = mc13xxx_rtc_set_alarm,
 	.alarm_irq_enable = mc13xxx_rtc_alarm_irq_enable,
-	.update_irq_enable = mc13xxx_rtc_update_irq_enable,
 };
 
 static irqreturn_t mc13xxx_rtc_reset_handler(int irq, void *dev)
@@ -356,11 +349,15 @@
 	if (ret)
 		goto err_alarm_irq_request;
 
+	mc13xxx_unlock(mc13xxx);
+
 	priv->rtc = rtc_device_register(pdev->name,
 			&pdev->dev, &mc13xxx_rtc_ops, THIS_MODULE);
 	if (IS_ERR(priv->rtc)) {
 		ret = PTR_ERR(priv->rtc);
 
+		mc13xxx_lock(mc13xxx);
+
 		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_TODA, priv);
 err_alarm_irq_request:
 
@@ -372,12 +369,12 @@
 		mc13xxx_irq_free(mc13xxx, MC13XXX_IRQ_RTCRST, priv);
 err_reset_irq_request:
 
+		mc13xxx_unlock(mc13xxx);
+
 		platform_set_drvdata(pdev, NULL);
 		kfree(priv);
 	}
 
-	mc13xxx_unlock(mc13xxx);
-
 	return ret;
 }
 
@@ -408,6 +405,7 @@
 	}, {
 		.name = "mc13892-rtc",
 	},
+	{ }
 };
 
 static struct platform_driver mc13xxx_rtc_driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-mpc5121.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-mpc5121.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-mpc5121.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-mpc5121.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,36 +240,15 @@
 	return 0;
 }
 
-static int mpc5121_rtc_update_irq_enable(struct device *dev,
-					 unsigned int enabled)
-{
-	struct mpc5121_rtc_data *rtc = dev_get_drvdata(dev);
-	struct mpc5121_rtc_regs __iomem *regs = rtc->regs;
-	int val;
-
-	val = in_8(&regs->int_enable);
-
-	if (enabled)
-		val = (val & ~0x8) | 0x1;
-	else
-		val &= ~0x1;
-
-	out_8(&regs->int_enable, val);
-
-	return 0;
-}
-
 static const struct rtc_class_ops mpc5121_rtc_ops = {
 	.read_time = mpc5121_rtc_read_time,
 	.set_time = mpc5121_rtc_set_time,
 	.read_alarm = mpc5121_rtc_read_alarm,
 	.set_alarm = mpc5121_rtc_set_alarm,
 	.alarm_irq_enable = mpc5121_rtc_alarm_irq_enable,
-	.update_irq_enable = mpc5121_rtc_update_irq_enable,
 };
 
-static int __devinit mpc5121_rtc_probe(struct platform_device *op,
-					const struct of_device_id *match)
+static int __devinit mpc5121_rtc_probe(struct platform_device *op)
 {
 	struct mpc5121_rtc_data *rtc;
 	int err = 0;
@@ -364,7 +343,7 @@
 	{},
 };
 
-static struct of_platform_driver mpc5121_rtc_driver = {
+static struct platform_driver mpc5121_rtc_driver = {
 	.driver = {
 		.name = "mpc5121-rtc",
 		.owner = THIS_MODULE,
@@ -376,13 +355,13 @@
 
 static int __init mpc5121_rtc_init(void)
 {
-	return of_register_platform_driver(&mpc5121_rtc_driver);
+	return platform_driver_register(&mpc5121_rtc_driver);
 }
 module_init(mpc5121_rtc_init);
 
 static void __exit mpc5121_rtc_exit(void)
 {
-	of_unregister_platform_driver(&mpc5121_rtc_driver);
+	platform_driver_unregister(&mpc5121_rtc_driver);
 }
 module_exit(mpc5121_rtc_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-mrst.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-mrst.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-mrst.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-mrst.c	2011-05-19 00:06:34.000000000 -0400
@@ -62,6 +62,17 @@
 	return rtc_intr & RTC_IRQMASK;
 }
 
+static inline unsigned char vrtc_is_updating(void)
+{
+	unsigned char uip;
+	unsigned long flags;
+
+	spin_lock_irqsave(&rtc_lock, flags);
+	uip = (vrtc_cmos_read(RTC_FREQ_SELECT) & RTC_UIP);
+	spin_unlock_irqrestore(&rtc_lock, flags);
+	return uip;
+}
+
 /*
  * rtc_time's year contains the increment over 1900, but vRTC's YEAR
  * register can't be programmed to value larger than 0x64, so vRTC
@@ -76,7 +87,7 @@
 {
 	unsigned long flags;
 
-	if (rtc_is_updating())
+	if (vrtc_is_updating())
 		mdelay(20);
 
 	spin_lock_irqsave(&rtc_lock, flags);
@@ -236,25 +247,6 @@
 	return 0;
 }
 
-static int mrst_irq_set_state(struct device *dev, int enabled)
-{
-	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
-	unsigned long	flags;
-
-	if (!mrst->irq)
-		return -ENXIO;
-
-	spin_lock_irqsave(&rtc_lock, flags);
-
-	if (enabled)
-		mrst_irq_enable(mrst, RTC_PIE);
-	else
-		mrst_irq_disable(mrst, RTC_PIE);
-
-	spin_unlock_irqrestore(&rtc_lock, flags);
-	return 0;
-}
-
 /* Currently, the vRTC doesn't support UIE ON/OFF */
 static int mrst_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
@@ -301,7 +293,6 @@
 	.read_alarm	= mrst_read_alarm,
 	.set_alarm	= mrst_set_alarm,
 	.proc		= mrst_procfs,
-	.irq_set_state	= mrst_irq_set_state,
 	.alarm_irq_enable = mrst_rtc_alarm_irq_enable,
 };
 
@@ -328,7 +319,7 @@
 	return IRQ_NONE;
 }
 
-static int __init
+static int __devinit
 vrtc_mrst_do_probe(struct device *dev, struct resource *iomem, int rtc_irq)
 {
 	int retval = 0;
@@ -351,6 +342,8 @@
 
 	mrst_rtc.irq = rtc_irq;
 	mrst_rtc.iomem = iomem;
+	mrst_rtc.dev = dev;
+	dev_set_drvdata(dev, &mrst_rtc);
 
 	mrst_rtc.rtc = rtc_device_register(driver_name, dev,
 				&mrst_rtc_ops, THIS_MODULE);
@@ -359,8 +352,6 @@
 		goto cleanup0;
 	}
 
-	mrst_rtc.dev = dev;
-	dev_set_drvdata(dev, &mrst_rtc);
 	rename_region(iomem, dev_name(&mrst_rtc.rtc->dev));
 
 	spin_lock_irq(&rtc_lock);
@@ -385,9 +376,10 @@
 	return 0;
 
 cleanup1:
-	mrst_rtc.dev = NULL;
 	rtc_device_unregister(mrst_rtc.rtc);
 cleanup0:
+	dev_set_drvdata(dev, NULL);
+	mrst_rtc.dev = NULL;
 	release_region(iomem->start, iomem->end + 1 - iomem->start);
 	dev_err(dev, "rtc-mrst: unable to initialise\n");
 	return retval;
@@ -400,7 +392,7 @@
 	spin_unlock_irq(&rtc_lock);
 }
 
-static void __exit rtc_mrst_do_remove(struct device *dev)
+static void __devexit rtc_mrst_do_remove(struct device *dev)
 {
 	struct mrst_rtc	*mrst = dev_get_drvdata(dev);
 	struct resource *iomem;
@@ -509,14 +501,14 @@
 
 #endif
 
-static int __init vrtc_mrst_platform_probe(struct platform_device *pdev)
+static int __devinit vrtc_mrst_platform_probe(struct platform_device *pdev)
 {
 	return vrtc_mrst_do_probe(&pdev->dev,
 			platform_get_resource(pdev, IORESOURCE_MEM, 0),
 			platform_get_irq(pdev, 0));
 }
 
-static int __exit vrtc_mrst_platform_remove(struct platform_device *pdev)
+static int __devexit vrtc_mrst_platform_remove(struct platform_device *pdev)
 {
 	rtc_mrst_do_remove(&pdev->dev);
 	return 0;
@@ -534,7 +526,7 @@
 
 static struct platform_driver vrtc_mrst_platform_driver = {
 	.probe		= vrtc_mrst_platform_probe,
-	.remove		= __exit_p(vrtc_mrst_platform_remove),
+	.remove		= __devexit_p(vrtc_mrst_platform_remove),
 	.shutdown	= vrtc_mrst_platform_shutdown,
 	.driver = {
 		.name		= (char *) driver_name,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-msm6242.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-msm6242.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-msm6242.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-msm6242.c	2011-05-19 00:06:34.000000000 -0400
@@ -214,6 +214,7 @@
 		error = -ENOMEM;
 		goto out_free_priv;
 	}
+	platform_set_drvdata(dev, priv);
 
 	rtc = rtc_device_register("rtc-msm6242", &dev->dev, &msm6242_rtc_ops,
 				  THIS_MODULE);
@@ -223,10 +224,10 @@
 	}
 
 	priv->rtc = rtc;
-	platform_set_drvdata(dev, priv);
 	return 0;
 
 out_unmap:
+	platform_set_drvdata(dev, NULL);
 	iounmap(priv->regs);
 out_free_priv:
 	kfree(priv);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-mxc.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-mxc.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-mxc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-mxc.c	2011-05-19 00:06:34.000000000 -0400
@@ -274,12 +274,6 @@
 	return 0;
 }
 
-static int mxc_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	mxc_rtc_irq_enable(dev, RTC_1HZ_BIT, enabled);
-	return 0;
-}
-
 /*
  * This function reads the current RTC time into tm in Gregorian date.
  */
@@ -368,7 +362,6 @@
 	.read_alarm		= mxc_rtc_read_alarm,
 	.set_alarm		= mxc_rtc_set_alarm,
 	.alarm_irq_enable	= mxc_rtc_alarm_irq_enable,
-	.update_irq_enable	= mxc_rtc_update_irq_enable,
 };
 
 static int __init mxc_rtc_probe(struct platform_device *pdev)
@@ -425,14 +418,6 @@
 		goto exit_put_clk;
 	}
 
-	rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
-				  THIS_MODULE);
-	if (IS_ERR(rtc)) {
-		ret = PTR_ERR(rtc);
-		goto exit_put_clk;
-	}
-
-	pdata->rtc = rtc;
 	platform_set_drvdata(pdev, pdata);
 
 	/* Configure and enable the RTC */
@@ -445,8 +430,19 @@
 		pdata->irq = -1;
 	}
 
+	rtc = rtc_device_register(pdev->name, &pdev->dev, &mxc_rtc_ops,
+				  THIS_MODULE);
+	if (IS_ERR(rtc)) {
+		ret = PTR_ERR(rtc);
+		goto exit_clr_drvdata;
+	}
+
+	pdata->rtc = rtc;
+
 	return 0;
 
+exit_clr_drvdata:
+	platform_set_drvdata(pdev, NULL);
 exit_put_clk:
 	clk_disable(pdata->clk);
 	clk_put(pdata->clk);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-nuc900.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-nuc900.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-nuc900.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-nuc900.c	2011-05-19 00:06:34.000000000 -0400
@@ -134,20 +134,6 @@
 	gettm->bcd_hour = bin2bcd(settm->tm_hour) << 16;
 }
 
-static int nuc900_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
-
-	if (enabled)
-		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)|
-				(TICKINTENB), rtc->rtc_reg + REG_RTC_RIER);
-	else
-		__raw_writel(__raw_readl(rtc->rtc_reg + REG_RTC_RIER)&
-				(~TICKINTENB), rtc->rtc_reg + REG_RTC_RIER);
-
-	return 0;
-}
-
 static int nuc900_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct nuc900_rtc *rtc = dev_get_drvdata(dev);
@@ -234,7 +220,6 @@
 	.read_alarm = nuc900_rtc_read_alarm,
 	.set_alarm = nuc900_rtc_set_alarm,
 	.alarm_irq_enable = nuc900_alarm_irq_enable,
-	.update_irq_enable = nuc900_update_irq_enable,
 };
 
 static int __devinit nuc900_rtc_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-omap.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-omap.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-omap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-omap.c	2011-05-19 00:06:34.000000000 -0400
@@ -135,44 +135,6 @@
 	return IRQ_HANDLED;
 }
 
-#ifdef	CONFIG_RTC_INTF_DEV
-
-static int
-omap_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	u8 reg;
-
-	switch (cmd) {
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		break;
-	default:
-		return -ENOIOCTLCMD;
-	}
-
-	local_irq_disable();
-	rtc_wait_not_busy();
-	reg = rtc_read(OMAP_RTC_INTERRUPTS_REG);
-	switch (cmd) {
-	/* UIE = Update Interrupt Enable (1/second) */
-	case RTC_UIE_OFF:
-		reg &= ~OMAP_RTC_INTERRUPTS_IT_TIMER;
-		break;
-	case RTC_UIE_ON:
-		reg |= OMAP_RTC_INTERRUPTS_IT_TIMER;
-		break;
-	}
-	rtc_wait_not_busy();
-	rtc_write(reg, OMAP_RTC_INTERRUPTS_REG);
-	local_irq_enable();
-
-	return 0;
-}
-
-#else
-#define	omap_rtc_ioctl	NULL
-#endif
-
 static int omap_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	u8 reg;
@@ -313,7 +275,6 @@
 }
 
 static struct rtc_class_ops omap_rtc_ops = {
-	.ioctl		= omap_rtc_ioctl,
 	.read_time	= omap_rtc_read_time,
 	.set_time	= omap_rtc_set_time,
 	.read_alarm	= omap_rtc_read_alarm,
@@ -433,7 +394,7 @@
 	return 0;
 
 fail2:
-	free_irq(omap_rtc_timer, NULL);
+	free_irq(omap_rtc_timer, rtc);
 fail1:
 	rtc_device_unregister(rtc);
 fail0:
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-pcap.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-pcap.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-pcap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-pcap.c	2011-05-19 00:06:34.000000000 -0400
@@ -131,18 +131,12 @@
 	return pcap_rtc_irq_enable(dev, PCAP_IRQ_TODA, en);
 }
 
-static int pcap_rtc_update_irq_enable(struct device *dev, unsigned int en)
-{
-	return pcap_rtc_irq_enable(dev, PCAP_IRQ_1HZ, en);
-}
-
 static const struct rtc_class_ops pcap_rtc_ops = {
 	.read_time = pcap_rtc_read_time,
 	.read_alarm = pcap_rtc_read_alarm,
 	.set_alarm = pcap_rtc_set_alarm,
 	.set_mmss = pcap_rtc_set_mmss,
 	.alarm_irq_enable = pcap_rtc_alarm_irq_enable,
-	.update_irq_enable = pcap_rtc_update_irq_enable,
 };
 
 static int __devinit pcap_rtc_probe(struct platform_device *pdev)
@@ -157,6 +151,8 @@
 
 	pcap_rtc->pcap = dev_get_drvdata(pdev->dev.parent);
 
+	platform_set_drvdata(pdev, pcap_rtc);
+
 	pcap_rtc->rtc = rtc_device_register("pcap", &pdev->dev,
 				  &pcap_rtc_ops, THIS_MODULE);
 	if (IS_ERR(pcap_rtc->rtc)) {
@@ -164,7 +160,6 @@
 		goto fail_rtc;
 	}
 
-	platform_set_drvdata(pdev, pcap_rtc);
 
 	timer_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_1HZ);
 	alarm_irq = pcap_to_irq(pcap_rtc->pcap, PCAP_IRQ_TODA);
@@ -183,6 +178,7 @@
 fail_timer:
 	rtc_device_unregister(pcap_rtc->rtc);
 fail_rtc:
+	platform_set_drvdata(pdev, NULL);
 	kfree(pcap_rtc);
 	return err;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-pcf50633.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-pcf50633.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-pcf50633.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-pcf50633.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,25 +106,6 @@
 	return 0;
 }
 
-static int
-pcf50633_rtc_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct pcf50633_rtc *rtc = dev_get_drvdata(dev);
-	int err;
-
-	if (enabled)
-		err = pcf50633_irq_unmask(rtc->pcf, PCF50633_IRQ_SECOND);
-	else
-		err = pcf50633_irq_mask(rtc->pcf, PCF50633_IRQ_SECOND);
-
-	if (err < 0)
-		return err;
-
-	rtc->second_enabled = enabled;
-
-	return 0;
-}
-
 static int pcf50633_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pcf50633_rtc *rtc;
@@ -262,8 +243,7 @@
 	.set_time		= pcf50633_rtc_set_time,
 	.read_alarm		= pcf50633_rtc_read_alarm,
 	.set_alarm		= pcf50633_rtc_set_alarm,
-	.alarm_irq_enable 	= pcf50633_rtc_alarm_irq_enable,
-	.update_irq_enable 	= pcf50633_rtc_update_irq_enable,
+	.alarm_irq_enable	= pcf50633_rtc_alarm_irq_enable,
 };
 
 static void pcf50633_rtc_irq(int irq, void *data)
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-pl030.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-pl030.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-pl030.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-pl030.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,11 +35,6 @@
 	return IRQ_HANDLED;
 }
 
-static int pl030_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	return -ENOIOCTLCMD;
-}
-
 static int pl030_read_alarm(struct device *dev, struct rtc_wkalrm *alrm)
 {
 	struct pl030_rtc *rtc = dev_get_drvdata(dev);
@@ -96,14 +91,13 @@
 }
 
 static const struct rtc_class_ops pl030_ops = {
-	.ioctl		= pl030_ioctl,
 	.read_time	= pl030_read_time,
 	.set_time	= pl030_set_time,
 	.read_alarm	= pl030_read_alarm,
 	.set_alarm	= pl030_set_alarm,
 };
 
-static int pl030_probe(struct amba_device *dev, struct amba_id *id)
+static int pl030_probe(struct amba_device *dev, const struct amba_id *id)
 {
 	struct pl030_rtc *rtc;
 	int ret;
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-pl031.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-pl031.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-pl031.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-pl031.c	2011-05-19 00:06:34.000000000 -0400
@@ -293,57 +293,6 @@
 	return ret;
 }
 
-/* Periodic interrupt is only available in ST variants. */
-static int pl031_irq_set_state(struct device *dev, int enabled)
-{
-	struct pl031_local *ldata = dev_get_drvdata(dev);
-
-	if (enabled == 1) {
-		/* Clear any pending timer interrupt. */
-		writel(RTC_BIT_PI, ldata->base + RTC_ICR);
-
-		writel(readl(ldata->base + RTC_IMSC) | RTC_BIT_PI,
-			ldata->base + RTC_IMSC);
-
-		/* Now start the timer */
-		writel(readl(ldata->base + RTC_TCR) | RTC_TCR_EN,
-			ldata->base + RTC_TCR);
-
-	} else {
-		writel(readl(ldata->base + RTC_IMSC) & (~RTC_BIT_PI),
-			ldata->base + RTC_IMSC);
-
-		/* Also stop the timer */
-		writel(readl(ldata->base + RTC_TCR) & (~RTC_TCR_EN),
-			ldata->base + RTC_TCR);
-	}
-	/* Wait at least 1 RTC32 clock cycle to ensure next access
-	 * to RTC_TCR will succeed.
-	 */
-	udelay(40);
-
-	return 0;
-}
-
-static int pl031_irq_set_freq(struct device *dev, int freq)
-{
-	struct pl031_local *ldata = dev_get_drvdata(dev);
-
-	/* Cant set timer if it is already enabled */
-	if (readl(ldata->base + RTC_TCR) & RTC_TCR_EN) {
-		dev_err(dev, "can't change frequency while timer enabled\n");
-		return -EINVAL;
-	}
-
-	/* If self start bit in RTC_TCR is set timer will start here,
-	 * but we never set that bit. Instead we start the timer when
-	 * set_state is called with enabled == 1.
-	 */
-	writel(RTC_TIMER_FREQ / freq, ldata->base + RTC_TLR);
-
-	return 0;
-}
-
 static int pl031_remove(struct amba_device *adev)
 {
 	struct pl031_local *ldata = dev_get_drvdata(&adev->dev);
@@ -358,7 +307,7 @@
 	return 0;
 }
 
-static int pl031_probe(struct amba_device *adev, struct amba_id *id)
+static int pl031_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	int ret;
 	struct pl031_local *ldata;
@@ -440,8 +389,6 @@
 	.read_alarm = pl031_read_alarm,
 	.set_alarm = pl031_set_alarm,
 	.alarm_irq_enable = pl031_alarm_irq_enable,
-	.irq_set_state = pl031_irq_set_state,
-	.irq_set_freq = pl031_irq_set_freq,
 };
 
 /* And the second ST derivative */
@@ -451,8 +398,6 @@
 	.read_alarm = pl031_stv2_read_alarm,
 	.set_alarm = pl031_stv2_set_alarm,
 	.alarm_irq_enable = pl031_alarm_irq_enable,
-	.irq_set_state = pl031_irq_set_state,
-	.irq_set_freq = pl031_irq_set_freq,
 };
 
 static struct amba_id pl031_ids[] = {
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-proc.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-proc.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-proc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-proc.c	2011-05-19 00:06:34.000000000 -0400
@@ -69,6 +69,14 @@
 				alrm.enabled ? "yes" : "no");
 		seq_printf(seq, "alrm_pending\t: %s\n",
 				alrm.pending ? "yes" : "no");
+		seq_printf(seq, "update IRQ enabled\t: %s\n",
+			(rtc->uie_rtctimer.enabled) ? "yes" : "no");
+		seq_printf(seq, "periodic IRQ enabled\t: %s\n",
+			(rtc->pie_enabled) ? "yes" : "no");
+		seq_printf(seq, "periodic IRQ frequency\t: %d\n",
+			rtc->irq_freq);
+		seq_printf(seq, "max user IRQ frequency\t: %d\n",
+			rtc->max_user_freq);
 	}
 
 	seq_printf(seq, "24hr\t\t: yes\n");
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-pxa.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-pxa.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-pxa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-pxa.c	2011-05-19 00:06:34.000000000 -0400
@@ -209,32 +209,6 @@
 	free_irq(pxa_rtc->irq_1Hz, dev);
 }
 
-static int pxa_periodic_irq_set_freq(struct device *dev, int freq)
-{
-	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-	int period_ms;
-
-	if (freq < 1 || freq > MAXFREQ_PERIODIC)
-		return -EINVAL;
-
-	period_ms = 1000 / freq;
-	rtc_writel(pxa_rtc, PIAR, period_ms);
-
-	return 0;
-}
-
-static int pxa_periodic_irq_set_state(struct device *dev, int enabled)
-{
-	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-
-	if (enabled)
-		rtsr_set_bits(pxa_rtc, RTSR_PIALE | RTSR_PICE);
-	else
-		rtsr_clear_bits(pxa_rtc, RTSR_PIALE | RTSR_PICE);
-
-	return 0;
-}
-
 static int pxa_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
@@ -250,21 +224,6 @@
 	return 0;
 }
 
-static int pxa_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
-
-	spin_lock_irq(&pxa_rtc->lock);
-
-	if (enabled)
-		rtsr_set_bits(pxa_rtc, RTSR_HZE);
-	else
-		rtsr_clear_bits(pxa_rtc, RTSR_HZE);
-
-	spin_unlock_irq(&pxa_rtc->lock);
-	return 0;
-}
-
 static int pxa_rtc_read_time(struct device *dev, struct rtc_time *tm)
 {
 	struct pxa_rtc *pxa_rtc = dev_get_drvdata(dev);
@@ -346,10 +305,7 @@
 	.read_alarm = pxa_rtc_read_alarm,
 	.set_alarm = pxa_rtc_set_alarm,
 	.alarm_irq_enable = pxa_alarm_irq_enable,
-	.update_irq_enable = pxa_update_irq_enable,
 	.proc = pxa_rtc_proc,
-	.irq_set_state = pxa_periodic_irq_set_state,
-	.irq_set_freq = pxa_periodic_irq_set_freq,
 };
 
 static int __init pxa_rtc_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-rp5c01.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-rp5c01.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-rp5c01.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-rp5c01.c	2011-05-19 00:06:34.000000000 -0400
@@ -249,15 +249,15 @@
 
 	spin_lock_init(&priv->lock);
 
+	platform_set_drvdata(dev, priv);
+
 	rtc = rtc_device_register("rtc-rp5c01", &dev->dev, &rp5c01_rtc_ops,
 				  THIS_MODULE);
 	if (IS_ERR(rtc)) {
 		error = PTR_ERR(rtc);
 		goto out_unmap;
 	}
-
 	priv->rtc = rtc;
-	platform_set_drvdata(dev, priv);
 
 	error = sysfs_create_bin_file(&dev->dev.kobj, &priv->nvram_attr);
 	if (error)
@@ -268,6 +268,7 @@
 out_unregister:
 	rtc_device_unregister(rtc);
 out_unmap:
+	platform_set_drvdata(dev, NULL);
 	iounmap(priv->regs);
 out_free_priv:
 	kfree(priv);
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-rs5c372.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-rs5c372.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-rs5c372.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-rs5c372.c	2011-05-19 00:06:34.000000000 -0400
@@ -281,57 +281,6 @@
 	return rs5c372_set_datetime(to_i2c_client(dev), tm);
 }
 
-#if defined(CONFIG_RTC_INTF_DEV) || defined(CONFIG_RTC_INTF_DEV_MODULE)
-
-static int
-rs5c_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	struct i2c_client	*client = to_i2c_client(dev);
-	struct rs5c372		*rs5c = i2c_get_clientdata(client);
-	unsigned char		buf;
-	int			status, addr;
-
-	buf = rs5c->regs[RS5C_REG_CTRL1];
-	switch (cmd) {
-	case RTC_UIE_OFF:
-	case RTC_UIE_ON:
-		/* some 327a modes use a different IRQ pin for 1Hz irqs */
-		if (rs5c->type == rtc_rs5c372a
-				&& (buf & RS5C372A_CTRL1_SL1))
-			return -ENOIOCTLCMD;
-	default:
-		return -ENOIOCTLCMD;
-	}
-
-	status = rs5c_get_regs(rs5c);
-	if (status < 0)
-		return status;
-
-	addr = RS5C_ADDR(RS5C_REG_CTRL1);
-	switch (cmd) {
-	case RTC_UIE_OFF:	/* update off */
-		buf &= ~RS5C_CTRL1_CT_MASK;
-		break;
-	case RTC_UIE_ON:	/* update on */
-		buf &= ~RS5C_CTRL1_CT_MASK;
-		buf |= RS5C_CTRL1_CT4;
-		break;
-	}
-
-	if (i2c_smbus_write_byte_data(client, addr, buf) < 0) {
-		printk(KERN_WARNING "%s: can't update alarm\n",
-			rs5c->rtc->name);
-		status = -EIO;
-	} else
-		rs5c->regs[RS5C_REG_CTRL1] = buf;
-
-	return status;
-}
-
-#else
-#define	rs5c_rtc_ioctl	NULL
-#endif
-
 
 static int rs5c_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
@@ -480,7 +429,6 @@
 
 static const struct rtc_class_ops rs5c372_rtc_ops = {
 	.proc		= rs5c372_rtc_proc,
-	.ioctl		= rs5c_rtc_ioctl,
 	.read_time	= rs5c372_rtc_read_time,
 	.set_time	= rs5c372_rtc_set_time,
 	.read_alarm	= rs5c_read_alarm,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-rx8025.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-rx8025.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-rx8025.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-rx8025.c	2011-05-19 00:06:34.000000000 -0400
@@ -424,37 +424,12 @@
 	return 0;
 }
 
-static int rx8025_irq_set_state(struct device *dev, int enabled)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct rx8025_data *rx8025 = i2c_get_clientdata(client);
-	int ctrl1;
-	int err;
-
-	if (client->irq <= 0)
-		return -ENXIO;
-
-	ctrl1 = rx8025->ctrl1 & ~RX8025_BIT_CTRL1_CT;
-	if (enabled)
-		ctrl1 |= RX8025_BIT_CTRL1_CT_1HZ;
-	if (ctrl1 != rx8025->ctrl1) {
-		rx8025->ctrl1 = ctrl1;
-		err = rx8025_write_reg(rx8025->client, RX8025_REG_CTRL1,
-				       rx8025->ctrl1);
-		if (err)
-			return err;
-	}
-
-	return 0;
-}
-
 static struct rtc_class_ops rx8025_rtc_ops = {
 	.read_time = rx8025_get_time,
 	.set_time = rx8025_set_time,
 	.read_alarm = rx8025_read_alarm,
 	.set_alarm = rx8025_set_alarm,
 	.alarm_irq_enable = rx8025_alarm_irq_enable,
-	.irq_set_state  = rx8025_irq_set_state,
 };
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-s3c.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-s3c.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-s3c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-s3c.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,6 +46,7 @@
 static void __iomem *s3c_rtc_base;
 static int s3c_rtc_alarmno = NO_IRQ;
 static int s3c_rtc_tickno  = NO_IRQ;
+static bool wake_en;
 static enum s3c_cpu_type s3c_rtc_cpu_type;
 
 static DEFINE_SPINLOCK(s3c_rtc_pie_lock);
@@ -93,37 +94,6 @@
 	return 0;
 }
 
-static int s3c_rtc_setpie(struct device *dev, int enabled)
-{
-	unsigned int tmp;
-
-	pr_debug("%s: pie=%d\n", __func__, enabled);
-
-	spin_lock_irq(&s3c_rtc_pie_lock);
-
-	if (s3c_rtc_cpu_type == TYPE_S3C64XX) {
-		tmp = readw(s3c_rtc_base + S3C2410_RTCCON);
-		tmp &= ~S3C64XX_RTCCON_TICEN;
-
-		if (enabled)
-			tmp |= S3C64XX_RTCCON_TICEN;
-
-		writew(tmp, s3c_rtc_base + S3C2410_RTCCON);
-	} else {
-		tmp = readb(s3c_rtc_base + S3C2410_TICNT);
-		tmp &= ~S3C2410_TICNT_ENABLE;
-
-		if (enabled)
-			tmp |= S3C2410_TICNT_ENABLE;
-
-		writeb(tmp, s3c_rtc_base + S3C2410_TICNT);
-	}
-
-	spin_unlock_irq(&s3c_rtc_pie_lock);
-
-	return 0;
-}
-
 static int s3c_rtc_setfreq(struct device *dev, int freq)
 {
 	struct platform_device *pdev = to_platform_device(dev);
@@ -367,7 +337,6 @@
 
 	/* do not clear AIE here, it may be needed for wake */
 
-	s3c_rtc_setpie(dev, 0);
 	free_irq(s3c_rtc_alarmno, rtc_dev);
 	free_irq(s3c_rtc_tickno, rtc_dev);
 }
@@ -379,8 +348,6 @@
 	.set_time	= s3c_rtc_settime,
 	.read_alarm	= s3c_rtc_getalarm,
 	.set_alarm	= s3c_rtc_setalarm,
-	.irq_set_freq	= s3c_rtc_setfreq,
-	.irq_set_state	= s3c_rtc_setpie,
 	.proc		= s3c_rtc_proc,
 	.alarm_irq_enable = s3c_rtc_setaie,
 };
@@ -441,7 +408,6 @@
 	platform_set_drvdata(dev, NULL);
 	rtc_device_unregister(rtc);
 
-	s3c_rtc_setpie(&dev->dev, 0);
 	s3c_rtc_setaie(&dev->dev, 0);
 
 	clk_disable(rtc_clk);
@@ -597,8 +563,12 @@
 	}
 	s3c_rtc_enable(pdev, 0);
 
-	if (device_may_wakeup(&pdev->dev))
-		enable_irq_wake(s3c_rtc_alarmno);
+	if (device_may_wakeup(&pdev->dev) && !wake_en) {
+		if (enable_irq_wake(s3c_rtc_alarmno) == 0)
+			wake_en = true;
+		else
+			dev_err(&pdev->dev, "enable_irq_wake failed\n");
+	}
 
 	return 0;
 }
@@ -614,8 +584,10 @@
 		writew(tmp | ticnt_en_save, s3c_rtc_base + S3C2410_RTCCON);
 	}
 
-	if (device_may_wakeup(&pdev->dev))
+	if (device_may_wakeup(&pdev->dev) && wake_en) {
 		disable_irq_wake(s3c_rtc_alarmno);
+		wake_en = false;
+	}
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-sa1100.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-sa1100.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-sa1100.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-sa1100.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,7 +43,6 @@
 #define RTC_DEF_TRIM		0
 
 static const unsigned long RTC_FREQ = 1024;
-static unsigned long timer_freq;
 static struct rtc_time rtc_alarm;
 static DEFINE_SPINLOCK(sa1100_rtc_lock);
 
@@ -156,114 +155,11 @@
 	return IRQ_HANDLED;
 }
 
-static int sa1100_irq_set_freq(struct device *dev, int freq)
-{
-	if (freq < 1 || freq > timer_freq) {
-		return -EINVAL;
-	} else {
-		struct rtc_device *rtc = (struct rtc_device *)dev;
-
-		rtc->irq_freq = freq;
-
-		return 0;
-	}
-}
-
-static int rtc_timer1_count;
-
-static int sa1100_irq_set_state(struct device *dev, int enabled)
-{
-	spin_lock_irq(&sa1100_rtc_lock);
-	if (enabled) {
-		struct rtc_device *rtc = (struct rtc_device *)dev;
-
-		OSMR1 = timer_freq / rtc->irq_freq + OSCR;
-		OIER |= OIER_E1;
-		rtc_timer1_count = 1;
-	} else {
-		OIER &= ~OIER_E1;
-	}
-	spin_unlock_irq(&sa1100_rtc_lock);
-
-	return 0;
-}
-
-static inline int sa1100_timer1_retrigger(struct rtc_device *rtc)
-{
-	unsigned long diff;
-	unsigned long period = timer_freq / rtc->irq_freq;
-
-	spin_lock_irq(&sa1100_rtc_lock);
-
-	do {
-		OSMR1 += period;
-		diff = OSMR1 - OSCR;
-		/* If OSCR > OSMR1, diff is a very large number (unsigned
-		 * math). This means we have a lost interrupt. */
-	} while (diff > period);
-	OIER |= OIER_E1;
-
-	spin_unlock_irq(&sa1100_rtc_lock);
-
-	return 0;
-}
-
-static irqreturn_t timer1_interrupt(int irq, void *dev_id)
-{
-	struct platform_device *pdev = to_platform_device(dev_id);
-	struct rtc_device *rtc = platform_get_drvdata(pdev);
-
-	/*
-	 * If we match for the first time, rtc_timer1_count will be 1.
-	 * Otherwise, we wrapped around (very unlikely but
-	 * still possible) so compute the amount of missed periods.
-	 * The match reg is updated only when the data is actually retrieved
-	 * to avoid unnecessary interrupts.
-	 */
-	OSSR = OSSR_M1;	/* clear match on timer1 */
-
-	rtc_update_irq(rtc, rtc_timer1_count, RTC_PF | RTC_IRQF);
-
-	if (rtc_timer1_count == 1)
-		rtc_timer1_count =
-			(rtc->irq_freq * ((1 << 30) / (timer_freq >> 2)));
-
-	/* retrigger. */
-	sa1100_timer1_retrigger(rtc);
-
-	return IRQ_HANDLED;
-}
-
-static int sa1100_rtc_read_callback(struct device *dev, int data)
-{
-	if (data & RTC_PF) {
-		struct rtc_device *rtc = (struct rtc_device *)dev;
-
-		/* interpolate missed periods and set match for the next */
-		unsigned long period = timer_freq / rtc->irq_freq;
-		unsigned long oscr = OSCR;
-		unsigned long osmr1 = OSMR1;
-		unsigned long missed = (oscr - osmr1)/period;
-		data += missed << 8;
-		OSSR = OSSR_M1;	/* clear match on timer 1 */
-		OSMR1 = osmr1 + (missed + 1)*period;
-		/* Ensure we didn't miss another match in the mean time.
-		 * Here we compare (match - OSCR) 8 instead of 0 --
-		 * see comment in pxa_timer_interrupt() for explanation.
-		 */
-		while ((signed long)((osmr1 = OSMR1) - OSCR) <= 8) {
-			data += 0x100;
-			OSSR = OSSR_M1;	/* clear match on timer 1 */
-			OSMR1 = osmr1 + period;
-		}
-	}
-	return data;
-}
-
 static int sa1100_rtc_open(struct device *dev)
 {
 	int ret;
-	struct rtc_device *rtc = (struct rtc_device *)dev;
+	struct platform_device *plat_dev = to_platform_device(dev);
+	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
 	ret = request_irq(IRQ_RTC1Hz, sa1100_rtc_interrupt, IRQF_DISABLED,
 		"rtc 1Hz", dev);
@@ -277,19 +173,11 @@
 		dev_err(dev, "IRQ %d already in use.\n", IRQ_RTCAlrm);
 		goto fail_ai;
 	}
-	ret = request_irq(IRQ_OST1, timer1_interrupt, IRQF_DISABLED,
-		"rtc timer", dev);
-	if (ret) {
-		dev_err(dev, "IRQ %d already in use.\n", IRQ_OST1);
-		goto fail_pi;
-	}
 	rtc->max_user_freq = RTC_FREQ;
-	sa1100_irq_set_freq(dev, RTC_FREQ);
+	rtc_irq_set_freq(rtc, NULL, RTC_FREQ);
 
 	return 0;
 
- fail_pi:
-	free_irq(IRQ_RTCAlrm, dev);
  fail_ai:
 	free_irq(IRQ_RTC1Hz, dev);
  fail_ui:
@@ -304,30 +192,10 @@
 	OSSR = OSSR_M1;
 	spin_unlock_irq(&sa1100_rtc_lock);
 
-	free_irq(IRQ_OST1, dev);
 	free_irq(IRQ_RTCAlrm, dev);
 	free_irq(IRQ_RTC1Hz, dev);
 }
 
-
-static int sa1100_rtc_ioctl(struct device *dev, unsigned int cmd,
-		unsigned long arg)
-{
-	switch (cmd) {
-	case RTC_UIE_OFF:
-		spin_lock_irq(&sa1100_rtc_lock);
-		RTSR &= ~RTSR_HZE;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	case RTC_UIE_ON:
-		spin_lock_irq(&sa1100_rtc_lock);
-		RTSR |= RTSR_HZE;
-		spin_unlock_irq(&sa1100_rtc_lock);
-		return 0;
-	}
-	return -ENOIOCTLCMD;
-}
-
 static int sa1100_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	spin_lock_irq(&sa1100_rtc_lock);
@@ -386,31 +254,20 @@
 
 static int sa1100_rtc_proc(struct device *dev, struct seq_file *seq)
 {
-	struct rtc_device *rtc = (struct rtc_device *)dev;
-
-	seq_printf(seq, "trim/divider\t: 0x%08x\n", (u32) RTTR);
-	seq_printf(seq, "update_IRQ\t: %s\n",
-			(RTSR & RTSR_HZE) ? "yes" : "no");
-	seq_printf(seq, "periodic_IRQ\t: %s\n",
-			(OIER & OIER_E1) ? "yes" : "no");
-	seq_printf(seq, "periodic_freq\t: %d\n", rtc->irq_freq);
-	seq_printf(seq, "RTSR\t\t: 0x%08x\n", (u32)RTSR);
+	seq_printf(seq, "trim/divider\t\t: 0x%08x\n", (u32) RTTR);
+	seq_printf(seq, "RTSR\t\t\t: 0x%08x\n", (u32)RTSR);
 
 	return 0;
 }
 
 static const struct rtc_class_ops sa1100_rtc_ops = {
 	.open = sa1100_rtc_open,
-	.read_callback = sa1100_rtc_read_callback,
 	.release = sa1100_rtc_release,
-	.ioctl = sa1100_rtc_ioctl,
 	.read_time = sa1100_rtc_read_time,
 	.set_time = sa1100_rtc_set_time,
 	.read_alarm = sa1100_rtc_read_alarm,
 	.set_alarm = sa1100_rtc_set_alarm,
 	.proc = sa1100_rtc_proc,
-	.irq_set_freq = sa1100_irq_set_freq,
-	.irq_set_state = sa1100_irq_set_state,
 	.alarm_irq_enable = sa1100_rtc_alarm_irq_enable,
 };
 
@@ -418,8 +275,6 @@
 {
 	struct rtc_device *rtc;
 
-	timer_freq = get_clock_tick_rate();
-
 	/*
 	 * According to the manual we should be able to let RTTR be zero
 	 * and then a default diviser for a 32.768KHz clock is used.
@@ -445,11 +300,6 @@
 
 	platform_set_drvdata(pdev, rtc);
 
-	/* Set the irq_freq */
-	/*TODO: Find out who is messing with this value after we initialize
-	 * it here.*/
-	rtc->irq_freq = RTC_FREQ;
-
 	/* Fix for a nasty initialization problem the in SA11xx RTSR register.
 	 * See also the comments in sa1100_rtc_interrupt().
 	 *
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-sh.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-sh.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-sh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-sh.c	2011-05-19 00:06:34.000000000 -0400
@@ -344,27 +344,6 @@
 	spin_unlock_irq(&rtc->lock);
 }
 
-static int sh_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
-{
-	struct sh_rtc *rtc = dev_get_drvdata(dev);
-	unsigned int ret = 0;
-
-	switch (cmd) {
-	case RTC_UIE_OFF:
-		rtc->periodic_freq &= ~PF_OXS;
-		sh_rtc_setcie(dev, 0);
-		break;
-	case RTC_UIE_ON:
-		rtc->periodic_freq |= PF_OXS;
-		sh_rtc_setcie(dev, 1);
-		break;
-	default:
-		ret = -ENOIOCTLCMD;
-	}
-
-	return ret;
-}
-
 static int sh_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
 {
 	sh_rtc_setaie(dev, enabled);
@@ -598,13 +577,10 @@
 }
 
 static struct rtc_class_ops sh_rtc_ops = {
-	.ioctl		= sh_rtc_ioctl,
 	.read_time	= sh_rtc_read_time,
 	.set_time	= sh_rtc_set_time,
 	.read_alarm	= sh_rtc_read_alarm,
 	.set_alarm	= sh_rtc_set_alarm,
-	.irq_set_state	= sh_rtc_irq_set_state,
-	.irq_set_freq	= sh_rtc_irq_set_freq,
 	.proc		= sh_rtc_proc,
 	.alarm_irq_enable = sh_rtc_alarm_irq_enable,
 };
@@ -806,11 +782,11 @@
 	struct platform_device *pdev = to_platform_device(dev);
 	struct sh_rtc *rtc = platform_get_drvdata(pdev);
 
-	set_irq_wake(rtc->periodic_irq, enabled);
+	irq_set_irq_wake(rtc->periodic_irq, enabled);
 
 	if (rtc->carry_irq > 0) {
-		set_irq_wake(rtc->carry_irq, enabled);
-		set_irq_wake(rtc->alarm_irq, enabled);
+		irq_set_irq_wake(rtc->carry_irq, enabled);
+		irq_set_irq_wake(rtc->alarm_irq, enabled);
 	}
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-stmp3xxx.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-stmp3xxx.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-stmp3xxx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-stmp3xxx.c	2011-05-19 00:06:34.000000000 -0400
@@ -115,19 +115,6 @@
 	return 0;
 }
 
-static int stmp3xxx_update_irq_enable(struct device *dev, unsigned int enabled)
-{
-	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
-
-	if (enabled)
-		stmp3xxx_setl(BM_RTC_CTRL_ONEMSEC_IRQ_EN,
-				rtc_data->io + HW_RTC_CTRL);
-	else
-		stmp3xxx_clearl(BM_RTC_CTRL_ONEMSEC_IRQ_EN,
-				rtc_data->io + HW_RTC_CTRL);
-	return 0;
-}
-
 static int stmp3xxx_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alm)
 {
 	struct stmp3xxx_rtc_data *rtc_data = dev_get_drvdata(dev);
@@ -149,8 +136,6 @@
 static struct rtc_class_ops stmp3xxx_rtc_ops = {
 	.alarm_irq_enable =
 			  stmp3xxx_alarm_irq_enable,
-	.update_irq_enable =
-			  stmp3xxx_update_irq_enable,
 	.read_time	= stmp3xxx_rtc_gettime,
 	.set_mmss	= stmp3xxx_rtc_set_mmss,
 	.read_alarm	= stmp3xxx_rtc_read_alarm,
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-tegra.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-tegra.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-tegra.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-tegra.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,488 @@
+/*
+ * An RTC driver for the NVIDIA Tegra 200 series internal RTC.
+ *
+ * Copyright (c) 2010, NVIDIA 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/irq.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/rtc.h>
+#include <linux/platform_device.h>
+
+/* set to 1 = busy every eight 32kHz clocks during copy of sec+msec to AHB */
+#define TEGRA_RTC_REG_BUSY			0x004
+#define TEGRA_RTC_REG_SECONDS			0x008
+/* when msec is read, the seconds are buffered into shadow seconds. */
+#define TEGRA_RTC_REG_SHADOW_SECONDS		0x00c
+#define TEGRA_RTC_REG_MILLI_SECONDS		0x010
+#define TEGRA_RTC_REG_SECONDS_ALARM0		0x014
+#define TEGRA_RTC_REG_SECONDS_ALARM1		0x018
+#define TEGRA_RTC_REG_MILLI_SECONDS_ALARM0	0x01c
+#define TEGRA_RTC_REG_INTR_MASK			0x028
+/* write 1 bits to clear status bits */
+#define TEGRA_RTC_REG_INTR_STATUS		0x02c
+
+/* bits in INTR_MASK */
+#define TEGRA_RTC_INTR_MASK_MSEC_CDN_ALARM	(1<<4)
+#define TEGRA_RTC_INTR_MASK_SEC_CDN_ALARM	(1<<3)
+#define TEGRA_RTC_INTR_MASK_MSEC_ALARM		(1<<2)
+#define TEGRA_RTC_INTR_MASK_SEC_ALARM1		(1<<1)
+#define TEGRA_RTC_INTR_MASK_SEC_ALARM0		(1<<0)
+
+/* bits in INTR_STATUS */
+#define TEGRA_RTC_INTR_STATUS_MSEC_CDN_ALARM	(1<<4)
+#define TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM	(1<<3)
+#define TEGRA_RTC_INTR_STATUS_MSEC_ALARM	(1<<2)
+#define TEGRA_RTC_INTR_STATUS_SEC_ALARM1	(1<<1)
+#define TEGRA_RTC_INTR_STATUS_SEC_ALARM0	(1<<0)
+
+struct tegra_rtc_info {
+	struct platform_device	*pdev;
+	struct rtc_device	*rtc_dev;
+	void __iomem		*rtc_base; /* NULL if not initialized. */
+	int			tegra_rtc_irq; /* alarm and periodic irq */
+	spinlock_t		tegra_rtc_lock;
+};
+
+/* RTC hardware is busy when it is updating its values over AHB once
+ * every eight 32kHz clocks (~250uS).
+ * outside of these updates the CPU is free to write.
+ * CPU is always free to read.
+ */
+static inline u32 tegra_rtc_check_busy(struct tegra_rtc_info *info)
+{
+	return readl(info->rtc_base + TEGRA_RTC_REG_BUSY) & 1;
+}
+
+/* Wait for hardware to be ready for writing.
+ * This function tries to maximize the amount of time before the next update.
+ * It does this by waiting for the RTC to become busy with its periodic update,
+ * then returning once the RTC first becomes not busy.
+ * This periodic update (where the seconds and milliseconds are copied to the
+ * AHB side) occurs every eight 32kHz clocks (~250uS).
+ * The behavior of this function allows us to make some assumptions without
+ * introducing a race, because 250uS is plenty of time to read/write a value.
+ */
+static int tegra_rtc_wait_while_busy(struct device *dev)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+
+	int retries = 500; /* ~490 us is the worst case, ~250 us is best. */
+
+	/* first wait for the RTC to become busy. this is when it
+	 * posts its updated seconds+msec registers to AHB side. */
+	while (tegra_rtc_check_busy(info)) {
+		if (!retries--)
+			goto retry_failed;
+		udelay(1);
+	}
+
+	/* now we have about 250 us to manipulate registers */
+	return 0;
+
+retry_failed:
+	dev_err(dev, "write failed:retry count exceeded.\n");
+	return -ETIMEDOUT;
+}
+
+static int tegra_rtc_read_time(struct device *dev, struct rtc_time *tm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec, msec;
+	unsigned long sl_irq_flags;
+
+	/* RTC hardware copies seconds to shadow seconds when a read
+	 * of milliseconds occurs. use a lock to keep other threads out. */
+	spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+
+	msec = readl(info->rtc_base + TEGRA_RTC_REG_MILLI_SECONDS);
+	sec = readl(info->rtc_base + TEGRA_RTC_REG_SHADOW_SECONDS);
+
+	spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+
+	rtc_time_to_tm(sec, tm);
+
+	dev_vdbg(dev, "time read as %lu. %d/%d/%d %d:%02u:%02u\n",
+		sec,
+		tm->tm_mon + 1,
+		tm->tm_mday,
+		tm->tm_year + 1900,
+		tm->tm_hour,
+		tm->tm_min,
+		tm->tm_sec
+	);
+
+	return 0;
+}
+
+static int tegra_rtc_set_time(struct device *dev, struct rtc_time *tm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec;
+	int ret;
+
+	/* convert tm to seconds. */
+	ret = rtc_valid_tm(tm);
+	if (ret)
+		return ret;
+
+	rtc_tm_to_time(tm, &sec);
+
+	dev_vdbg(dev, "time set to %lu. %d/%d/%d %d:%02u:%02u\n",
+		sec,
+		tm->tm_mon+1,
+		tm->tm_mday,
+		tm->tm_year+1900,
+		tm->tm_hour,
+		tm->tm_min,
+		tm->tm_sec
+	);
+
+	/* seconds only written if wait succeeded. */
+	ret = tegra_rtc_wait_while_busy(dev);
+	if (!ret)
+		writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS);
+
+	dev_vdbg(dev, "time read back as %d\n",
+		readl(info->rtc_base + TEGRA_RTC_REG_SECONDS));
+
+	return ret;
+}
+
+static int tegra_rtc_read_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec;
+	unsigned tmp;
+
+	sec = readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+
+	if (sec == 0) {
+		/* alarm is disabled. */
+		alarm->enabled = 0;
+		alarm->time.tm_mon = -1;
+		alarm->time.tm_mday = -1;
+		alarm->time.tm_year = -1;
+		alarm->time.tm_hour = -1;
+		alarm->time.tm_min = -1;
+		alarm->time.tm_sec = -1;
+	} else {
+		/* alarm is enabled. */
+		alarm->enabled = 1;
+		rtc_time_to_tm(sec, &alarm->time);
+	}
+
+	tmp = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	alarm->pending = (tmp & TEGRA_RTC_INTR_STATUS_SEC_ALARM0) != 0;
+
+	return 0;
+}
+
+static int tegra_rtc_alarm_irq_enable(struct device *dev, unsigned int enabled)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned status;
+	unsigned long sl_irq_flags;
+
+	tegra_rtc_wait_while_busy(dev);
+	spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+
+	/* read the original value, and OR in the flag. */
+	status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+	if (enabled)
+		status |= TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* set it */
+	else
+		status &= ~TEGRA_RTC_INTR_MASK_SEC_ALARM0; /* clear it */
+
+	writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+
+	spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+
+	return 0;
+}
+
+static int tegra_rtc_set_alarm(struct device *dev, struct rtc_wkalrm *alarm)
+{
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long sec;
+
+	if (alarm->enabled)
+		rtc_tm_to_time(&alarm->time, &sec);
+	else
+		sec = 0;
+
+	tegra_rtc_wait_while_busy(dev);
+	writel(sec, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+	dev_vdbg(dev, "alarm read back as %d\n",
+		readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0));
+
+	/* if successfully written and alarm is enabled ... */
+	if (sec) {
+		tegra_rtc_alarm_irq_enable(dev, 1);
+
+		dev_vdbg(dev, "alarm set as %lu. %d/%d/%d %d:%02u:%02u\n",
+			sec,
+			alarm->time.tm_mon+1,
+			alarm->time.tm_mday,
+			alarm->time.tm_year+1900,
+			alarm->time.tm_hour,
+			alarm->time.tm_min,
+			alarm->time.tm_sec);
+	} else {
+		/* disable alarm if 0 or write error. */
+		dev_vdbg(dev, "alarm disabled\n");
+		tegra_rtc_alarm_irq_enable(dev, 0);
+	}
+
+	return 0;
+}
+
+static int tegra_rtc_proc(struct device *dev, struct seq_file *seq)
+{
+	if (!dev || !dev->driver)
+		return 0;
+
+	return seq_printf(seq, "name\t\t: %s\n", dev_name(dev));
+}
+
+static irqreturn_t tegra_rtc_irq_handler(int irq, void *data)
+{
+	struct device *dev = data;
+	struct tegra_rtc_info *info = dev_get_drvdata(dev);
+	unsigned long events = 0;
+	unsigned status;
+	unsigned long sl_irq_flags;
+
+	status = readl(info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	if (status) {
+		/* clear the interrupt masks and status on any irq. */
+		tegra_rtc_wait_while_busy(dev);
+		spin_lock_irqsave(&info->tegra_rtc_lock, sl_irq_flags);
+		writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+		writel(status, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+		spin_unlock_irqrestore(&info->tegra_rtc_lock, sl_irq_flags);
+	}
+
+	/* check if Alarm */
+	if ((status & TEGRA_RTC_INTR_STATUS_SEC_ALARM0))
+		events |= RTC_IRQF | RTC_AF;
+
+	/* check if Periodic */
+	if ((status & TEGRA_RTC_INTR_STATUS_SEC_CDN_ALARM))
+		events |= RTC_IRQF | RTC_PF;
+
+	rtc_update_irq(info->rtc_dev, 1, events);
+
+	return IRQ_HANDLED;
+}
+
+static struct rtc_class_ops tegra_rtc_ops = {
+	.read_time	= tegra_rtc_read_time,
+	.set_time	= tegra_rtc_set_time,
+	.read_alarm	= tegra_rtc_read_alarm,
+	.set_alarm	= tegra_rtc_set_alarm,
+	.proc		= tegra_rtc_proc,
+	.alarm_irq_enable = tegra_rtc_alarm_irq_enable,
+};
+
+static int __devinit tegra_rtc_probe(struct platform_device *pdev)
+{
+	struct tegra_rtc_info *info;
+	struct resource *res;
+	int ret;
+
+	info = kzalloc(sizeof(struct tegra_rtc_info), GFP_KERNEL);
+	if (!info)
+		return -ENOMEM;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(&pdev->dev,
+			"Unable to allocate resources for device.\n");
+		ret = -EBUSY;
+		goto err_free_info;
+	}
+
+	if (!request_mem_region(res->start, resource_size(res), pdev->name)) {
+		dev_err(&pdev->dev,
+			"Unable to request mem region for device.\n");
+		ret = -EBUSY;
+		goto err_free_info;
+	}
+
+	info->tegra_rtc_irq = platform_get_irq(pdev, 0);
+	if (info->tegra_rtc_irq <= 0) {
+		ret = -EBUSY;
+		goto err_release_mem_region;
+	}
+
+	info->rtc_base = ioremap_nocache(res->start, resource_size(res));
+	if (!info->rtc_base) {
+		dev_err(&pdev->dev, "Unable to grab IOs for device.\n");
+		ret = -EBUSY;
+		goto err_release_mem_region;
+	}
+
+	/* set context info. */
+	info->pdev = pdev;
+	info->tegra_rtc_lock = __SPIN_LOCK_UNLOCKED(info->tegra_rtc_lock);
+
+	platform_set_drvdata(pdev, info);
+
+	/* clear out the hardware. */
+	writel(0, info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0);
+	writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	writel(0, info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+
+	device_init_wakeup(&pdev->dev, 1);
+
+	info->rtc_dev = rtc_device_register(
+		pdev->name, &pdev->dev, &tegra_rtc_ops, THIS_MODULE);
+	if (IS_ERR(info->rtc_dev)) {
+		ret = PTR_ERR(info->rtc_dev);
+		info->rtc_dev = NULL;
+		dev_err(&pdev->dev,
+			"Unable to register device (err=%d).\n",
+			ret);
+		goto err_iounmap;
+	}
+
+	ret = request_irq(info->tegra_rtc_irq, tegra_rtc_irq_handler,
+		IRQF_TRIGGER_HIGH, "rtc alarm", &pdev->dev);
+	if (ret) {
+		dev_err(&pdev->dev,
+			"Unable to request interrupt for device (err=%d).\n",
+			ret);
+		goto err_dev_unreg;
+	}
+
+	dev_notice(&pdev->dev, "Tegra internal Real Time Clock\n");
+
+	return 0;
+
+err_dev_unreg:
+	rtc_device_unregister(info->rtc_dev);
+err_iounmap:
+	iounmap(info->rtc_base);
+err_release_mem_region:
+	release_mem_region(res->start, resource_size(res));
+err_free_info:
+	kfree(info);
+
+	return ret;
+}
+
+static int __devexit tegra_rtc_remove(struct platform_device *pdev)
+{
+	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -EBUSY;
+
+	free_irq(info->tegra_rtc_irq, &pdev->dev);
+	rtc_device_unregister(info->rtc_dev);
+	iounmap(info->rtc_base);
+	release_mem_region(res->start, resource_size(res));
+	kfree(info);
+
+	platform_set_drvdata(pdev, NULL);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int tegra_rtc_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+
+	tegra_rtc_wait_while_busy(dev);
+
+	/* only use ALARM0 as a wake source. */
+	writel(0xffffffff, info->rtc_base + TEGRA_RTC_REG_INTR_STATUS);
+	writel(TEGRA_RTC_INTR_STATUS_SEC_ALARM0,
+		info->rtc_base + TEGRA_RTC_REG_INTR_MASK);
+
+	dev_vdbg(dev, "alarm sec = %d\n",
+		readl(info->rtc_base + TEGRA_RTC_REG_SECONDS_ALARM0));
+
+	dev_vdbg(dev, "Suspend (device_may_wakeup=%d) irq:%d\n",
+		device_may_wakeup(dev), info->tegra_rtc_irq);
+
+	/* leave the alarms on as a wake source. */
+	if (device_may_wakeup(dev))
+		enable_irq_wake(info->tegra_rtc_irq);
+
+	return 0;
+}
+
+static int tegra_rtc_resume(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tegra_rtc_info *info = platform_get_drvdata(pdev);
+
+	dev_vdbg(dev, "Resume (device_may_wakeup=%d)\n",
+		device_may_wakeup(dev));
+	/* alarms were left on as a wake source, turn them off. */
+	if (device_may_wakeup(dev))
+		disable_irq_wake(info->tegra_rtc_irq);
+
+	return 0;
+}
+#endif
+
+static void tegra_rtc_shutdown(struct platform_device *pdev)
+{
+	dev_vdbg(&pdev->dev, "disabling interrupts.\n");
+	tegra_rtc_alarm_irq_enable(&pdev->dev, 0);
+}
+
+MODULE_ALIAS("platform:tegra_rtc");
+static struct platform_driver tegra_rtc_driver = {
+	.remove		= __devexit_p(tegra_rtc_remove),
+	.shutdown	= tegra_rtc_shutdown,
+	.driver		= {
+		.name	= "tegra_rtc",
+		.owner	= THIS_MODULE,
+	},
+#ifdef CONFIG_PM
+	.suspend	= tegra_rtc_suspend,
+	.resume		= tegra_rtc_resume,
+#endif
+};
+
+static int __init tegra_rtc_init(void)
+{
+	return platform_driver_probe(&tegra_rtc_driver, tegra_rtc_probe);
+}
+module_init(tegra_rtc_init);
+
+static void __exit tegra_rtc_exit(void)
+{
+	platform_driver_unregister(&tegra_rtc_driver);
+}
+module_exit(tegra_rtc_exit);
+
+MODULE_AUTHOR("Jon Mayo <jmayo@nvidia.com>");
+MODULE_DESCRIPTION("driver for Tegra internal RTC");
+MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-test.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-test.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-test.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-test.c	2011-05-19 00:06:34.000000000 -0400
@@ -78,11 +78,16 @@
 	struct rtc_device *rtc = platform_get_drvdata(plat_dev);
 
 	retval = count;
-	if (strncmp(buf, "tick", 4) == 0)
+	if (strncmp(buf, "tick", 4) == 0 && rtc->pie_enabled)
 		rtc_update_irq(rtc, 1, RTC_PF | RTC_IRQF);
-	else if (strncmp(buf, "alarm", 5) == 0)
-		rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
-	else if (strncmp(buf, "update", 6) == 0)
+	else if (strncmp(buf, "alarm", 5) == 0) {
+		struct rtc_wkalrm alrm;
+		int err = rtc_read_alarm(rtc, &alrm);
+
+		if (!err && alrm.enabled)
+			rtc_update_irq(rtc, 1, RTC_AF | RTC_IRQF);
+
+	} else if (strncmp(buf, "update", 6) == 0 && rtc->uie_rtctimer.enabled)
 		rtc_update_irq(rtc, 1, RTC_UF | RTC_IRQF);
 	else
 		retval = -EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-twl.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-twl.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-twl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-twl.c	2011-05-19 00:06:34.000000000 -0400
@@ -213,18 +213,6 @@
 	return ret;
 }
 
-static int twl_rtc_update_irq_enable(struct device *dev, unsigned enabled)
-{
-	int ret;
-
-	if (enabled)
-		ret = set_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-	else
-		ret = mask_rtc_irq_bit(BIT_RTC_INTERRUPTS_REG_IT_TIMER_M);
-
-	return ret;
-}
-
 /*
  * Gets current TWL RTC time and date parameters.
  *
@@ -433,7 +421,6 @@
 	.read_alarm	= twl_rtc_read_alarm,
 	.set_alarm	= twl_rtc_set_alarm,
 	.alarm_irq_enable = twl_rtc_alarm_irq_enable,
-	.update_irq_enable = twl_rtc_update_irq_enable,
 };
 
 /*----------------------------------------------------------------------*/
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-vr41xx.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-vr41xx.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-vr41xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-vr41xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -207,36 +207,6 @@
 	return 0;
 }
 
-static int vr41xx_rtc_irq_set_freq(struct device *dev, int freq)
-{
-	u64 count;
-
-	if (!is_power_of_2(freq))
-		return -EINVAL;
-	count = RTC_FREQUENCY;
-	do_div(count, freq);
-
-	spin_lock_irq(&rtc_lock);
-
-	periodic_count = count;
-	rtc1_write(RTCL1LREG, periodic_count);
-	rtc1_write(RTCL1HREG, periodic_count >> 16);
-
-	spin_unlock_irq(&rtc_lock);
-
-	return 0;
-}
-
-static int vr41xx_rtc_irq_set_state(struct device *dev, int enabled)
-{
-	if (enabled)
-		enable_irq(pie_irq);
-	else
-		disable_irq(pie_irq);
-
-	return 0;
-}
-
 static int vr41xx_rtc_ioctl(struct device *dev, unsigned int cmd, unsigned long arg)
 {
 	switch (cmd) {
@@ -308,8 +278,6 @@
 	.set_time	= vr41xx_rtc_set_time,
 	.read_alarm	= vr41xx_rtc_read_alarm,
 	.set_alarm	= vr41xx_rtc_set_alarm,
-	.irq_set_freq	= vr41xx_rtc_irq_set_freq,
-	.irq_set_state	= vr41xx_rtc_irq_set_state,
 };
 
 static int __devinit rtc_probe(struct platform_device *pdev)
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-wm831x.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-wm831x.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-wm831x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-wm831x.c	2011-05-19 00:06:34.000000000 -0400
@@ -315,21 +315,6 @@
 		return wm831x_rtc_stop_alarm(wm831x_rtc);
 }
 
-static int wm831x_rtc_update_irq_enable(struct device *dev,
-					unsigned int enabled)
-{
-	struct wm831x_rtc *wm831x_rtc = dev_get_drvdata(dev);
-	int val;
-
-	if (enabled)
-		val = 1 << WM831X_RTC_PINT_FREQ_SHIFT;
-	else
-		val = 0;
-
-	return wm831x_set_bits(wm831x_rtc->wm831x, WM831X_RTC_CONTROL,
-			       WM831X_RTC_PINT_FREQ_MASK, val);
-}
-
 static irqreturn_t wm831x_alm_irq(int irq, void *data)
 {
 	struct wm831x_rtc *wm831x_rtc = data;
@@ -354,7 +339,6 @@
 	.read_alarm = wm831x_rtc_readalarm,
 	.set_alarm = wm831x_rtc_setalarm,
 	.alarm_irq_enable = wm831x_rtc_alarm_irq_enable,
-	.update_irq_enable = wm831x_rtc_update_irq_enable,
 };
 
 #ifdef CONFIG_PM
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-wm8350.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-wm8350.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-wm8350.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-wm8350.c	2011-05-19 00:06:34.000000000 -0400
@@ -302,26 +302,6 @@
 	return ret;
 }
 
-static int wm8350_rtc_update_irq_enable(struct device *dev,
-					unsigned int enabled)
-{
-	struct wm8350 *wm8350 = dev_get_drvdata(dev);
-
-	/* Suppress duplicate changes since genirq nests enable and
-	 * disable calls. */
-	if (enabled == wm8350->rtc.update_enabled)
-		return 0;
-
-	if (enabled)
-		wm8350_unmask_irq(wm8350, WM8350_IRQ_RTC_SEC);
-	else
-		wm8350_mask_irq(wm8350, WM8350_IRQ_RTC_SEC);
-
-	wm8350->rtc.update_enabled = enabled;
-
-	return 0;
-}
-
 static irqreturn_t wm8350_rtc_alarm_handler(int irq, void *data)
 {
 	struct wm8350 *wm8350 = data;
@@ -357,7 +337,6 @@
 	.read_alarm = wm8350_rtc_readalarm,
 	.set_alarm = wm8350_rtc_setalarm,
 	.alarm_irq_enable = wm8350_rtc_alarm_irq_enable,
-	.update_irq_enable = wm8350_rtc_update_irq_enable,
 };
 
 #ifdef CONFIG_PM
diff -druN linux-libre-2.6.38-gnu/drivers/rtc/rtc-x1205.c linux-libre-2.6.39-gnu/drivers/rtc/rtc-x1205.c
--- linux-libre-2.6.38-gnu/drivers/rtc/rtc-x1205.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/rtc/rtc-x1205.c	2011-05-19 00:06:34.000000000 -0400
@@ -573,7 +573,7 @@
 
 	i2c_set_clientdata(client, rtc);
 
-	/* Check for power failures and eventualy enable the osc */
+	/* Check for power failures and eventually enable the osc */
 	if ((err = x1205_get_status(client, &sr)) == 0) {
 		if (sr & X1205_SR_RTCF) {
 			dev_err(&client->dev,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_3990_erp.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_3990_erp.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_3990_erp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_3990_erp.c	2011-05-19 00:06:34.000000000 -0400
@@ -2207,7 +2207,7 @@
  * DASD_3990_ERP_CONTROL_CHECK
  *
  * DESCRIPTION
- *   Does a generic inspection if a control check occured and sets up
+ *   Does a generic inspection if a control check occurred and sets up
  *   the related error recovery procedure
  *
  * PARAMETER
@@ -2250,7 +2250,7 @@
 	struct dasd_ccw_req *erp_new = NULL;
 	char *sense;
 
-	/* if this problem occured on an alias retry on base */
+	/* if this problem occurred on an alias retry on base */
 	erp_new = dasd_3990_erp_inspect_alias(erp);
 	if (erp_new)
 		return erp_new;
@@ -2282,7 +2282,7 @@
  * DASD_3990_ERP_ADD_ERP
  *
  * DESCRIPTION
- *   This funtion adds an additional request block (ERP) to the head of
+ *   This function adds an additional request block (ERP) to the head of
  *   the given cqr (or erp).
  *   For a command mode cqr the erp is initialized as an default erp
  *   (retry TIC).
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd.c	2011-05-19 00:06:34.000000000 -0400
@@ -1742,11 +1742,20 @@
 static inline int _dasd_term_running_cqr(struct dasd_device *device)
 {
 	struct dasd_ccw_req *cqr;
+	int rc;
 
 	if (list_empty(&device->ccw_queue))
 		return 0;
 	cqr = list_entry(device->ccw_queue.next, struct dasd_ccw_req, devlist);
-	return device->discipline->term_IO(cqr);
+	rc = device->discipline->term_IO(cqr);
+	if (!rc)
+		/*
+		 * CQR terminated because a more important request is pending.
+		 * Undo decreasing of retry counter because this is
+		 * not an error case.
+		 */
+		cqr->retries++;
+	return rc;
 }
 
 int dasd_sleep_on_immediatly(struct dasd_ccw_req *cqr)
@@ -1917,7 +1926,7 @@
 		return;
 	}
 	/* Now we try to fetch requests from the request queue */
-	while (!blk_queue_plugged(queue) && (req = blk_peek_request(queue))) {
+	while ((req = blk_peek_request(queue))) {
 		if (basedev->features & DASD_FEATURE_READONLY &&
 		    rq_data_dir(req) == WRITE) {
 			DBF_DEV_EVENT(DBF_ERR, basedev,
@@ -2314,15 +2323,14 @@
 
 static int dasd_open(struct block_device *bdev, fmode_t mode)
 {
-	struct dasd_block *block = bdev->bd_disk->private_data;
 	struct dasd_device *base;
 	int rc;
 
-	if (!block)
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
 		return -ENODEV;
 
-	base = block->base;
-	atomic_inc(&block->open_count);
+	atomic_inc(&base->block->open_count);
 	if (test_bit(DASD_FLAG_OFFLINE, &base->flags)) {
 		rc = -ENODEV;
 		goto unlock;
@@ -2355,21 +2363,28 @@
 		goto out;
 	}
 
+	dasd_put_device(base);
 	return 0;
 
 out:
 	module_put(base->discipline->owner);
 unlock:
-	atomic_dec(&block->open_count);
+	atomic_dec(&base->block->open_count);
+	dasd_put_device(base);
 	return rc;
 }
 
 static int dasd_release(struct gendisk *disk, fmode_t mode)
 {
-	struct dasd_block *block = disk->private_data;
+	struct dasd_device *base;
 
-	atomic_dec(&block->open_count);
-	module_put(block->base->discipline->owner);
+	base = dasd_device_from_gendisk(disk);
+	if (!base)
+		return -ENODEV;
+
+	atomic_dec(&base->block->open_count);
+	module_put(base->discipline->owner);
+	dasd_put_device(base);
 	return 0;
 }
 
@@ -2378,20 +2393,20 @@
  */
 static int dasd_getgeo(struct block_device *bdev, struct hd_geometry *geo)
 {
-	struct dasd_block *block;
 	struct dasd_device *base;
 
-	block = bdev->bd_disk->private_data;
-	if (!block)
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
 		return -ENODEV;
-	base = block->base;
 
 	if (!base->discipline ||
-	    !base->discipline->fill_geometry)
+	    !base->discipline->fill_geometry) {
+		dasd_put_device(base);
 		return -EINVAL;
-
-	base->discipline->fill_geometry(block, geo);
-	geo->start = get_start_sect(bdev) >> block->s2b_shift;
+	}
+	base->discipline->fill_geometry(base->block, geo);
+	geo->start = get_start_sect(bdev) >> base->block->s2b_shift;
+	dasd_put_device(base);
 	return 0;
 }
 
@@ -2528,7 +2543,6 @@
 	dasd_set_target_state(device, DASD_STATE_NEW);
 	/* dasd_delete_device destroys the device reference. */
 	block = device->block;
-	device->block = NULL;
 	dasd_delete_device(device);
 	/*
 	 * life cycle of block is bound to device, so delete it after
@@ -2650,7 +2664,6 @@
 	dasd_set_target_state(device, DASD_STATE_NEW);
 	/* dasd_delete_device destroys the device reference. */
 	block = device->block;
-	device->block = NULL;
 	dasd_delete_device(device);
 	/*
 	 * life cycle of block is bound to device, so delete it after
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_devmap.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_devmap.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_devmap.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_devmap.c	2011-05-19 00:06:34.000000000 -0400
@@ -302,7 +302,7 @@
 /*
  * Try to interprete the first element on the comma separated parse string
  * as a device number or a range of devices. If the interpretation is
- * successfull, create the matching dasd_devmap entries and return a pointer
+ * successful, create the matching dasd_devmap entries and return a pointer
  * to the residual string.
  * If interpretation fails or in case of an error, return an error code.
  */
@@ -674,6 +674,36 @@
 	return device;
 }
 
+void dasd_add_link_to_gendisk(struct gendisk *gdp, struct dasd_device *device)
+{
+	struct dasd_devmap *devmap;
+
+	devmap = dasd_find_busid(dev_name(&device->cdev->dev));
+	if (IS_ERR(devmap))
+		return;
+	spin_lock(&dasd_devmap_lock);
+	gdp->private_data = devmap;
+	spin_unlock(&dasd_devmap_lock);
+}
+
+struct dasd_device *dasd_device_from_gendisk(struct gendisk *gdp)
+{
+	struct dasd_device *device;
+	struct dasd_devmap *devmap;
+
+	if (!gdp->private_data)
+		return NULL;
+	device = NULL;
+	spin_lock(&dasd_devmap_lock);
+	devmap = gdp->private_data;
+	if (devmap && devmap->device) {
+		device = devmap->device;
+		dasd_get_device(device);
+	}
+	spin_unlock(&dasd_devmap_lock);
+	return device;
+}
+
 /*
  * SECTION: files in sysfs
  */
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_diag.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_diag.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_diag.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_diag.c	2011-05-19 00:06:34.000000000 -0400
@@ -239,7 +239,6 @@
 	addr_t ip;
 	int rc;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
 	switch (ext_int_code >> 24) {
 	case DASD_DIAG_CODE_31BIT:
 		ip = (addr_t) param32;
@@ -250,6 +249,7 @@
 	default:
 		return;
 	}
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
 	if (!ip) {		/* no intparm: unsolicited interrupt */
 		DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
 			      "interrupt");
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_eckd.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_eckd.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_eckd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_eckd.c	2011-05-19 00:06:34.000000000 -0400
@@ -2037,7 +2037,7 @@
 		return;
 
 	/* summary unit check */
-	if ((sense[7] == 0x0D) &&
+	if ((sense[27] & DASD_SENSE_BIT_0) && (sense[7] == 0x0D) &&
 	    (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK)) {
 		dasd_alias_handle_summary_unit_check(device, irb);
 		return;
@@ -2053,7 +2053,8 @@
 	/* loss of device reservation is handled via base devices only
 	 * as alias devices may be used with several bases
 	 */
-	if (device->block && (sense[7] == 0x3F) &&
+	if (device->block && (sense[27] & DASD_SENSE_BIT_0) &&
+	    (sense[7] == 0x3F) &&
 	    (scsw_dstat(&irb->scsw) & DEV_STAT_UNIT_CHECK) &&
 	    test_bit(DASD_FLAG_IS_RESERVED, &device->flags)) {
 		if (device->features & DASD_FEATURE_FAILONSLCK)
@@ -2648,6 +2649,7 @@
 		dasd_sfree_request(cqr, startdev);
 		return ERR_PTR(-EAGAIN);
 	}
+	len_to_track_end = 0;
 	/*
 	 * A tidaw can address 4k of memory, but must not cross page boundaries
 	 * We can let the block layer handle this by setting
@@ -2857,7 +2859,7 @@
 	/*
 	 * struct PFX_eckd_data has up to 2 byte as extended parameter
 	 * this is needed for write full track and has to be mentioned
-	 * seperately
+	 * separately
 	 * add 8 instead of 2 to keep 8 byte boundary
 	 */
 	pfx_datasize = sizeof(struct PFX_eckd_data) + 8;
@@ -3981,8 +3983,10 @@
 }
 
 static struct ccw_driver dasd_eckd_driver = {
-	.name	     = "dasd-eckd",
-	.owner	     = THIS_MODULE,
+	.driver = {
+		.name	= "dasd-eckd",
+		.owner	= THIS_MODULE,
+	},
 	.ids	     = dasd_eckd_ids,
 	.probe	     = dasd_eckd_probe,
 	.remove      = dasd_generic_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_fba.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_fba.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_fba.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_fba.c	2011-05-19 00:06:34.000000000 -0400
@@ -65,8 +65,10 @@
 }
 
 static struct ccw_driver dasd_fba_driver = {
-	.name        = "dasd-fba",
-	.owner       = THIS_MODULE,
+	.driver = {
+		.name	= "dasd-fba",
+		.owner	= THIS_MODULE,
+	},
 	.ids         = dasd_fba_ids,
 	.probe       = dasd_fba_probe,
 	.remove      = dasd_generic_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_genhd.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_genhd.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_genhd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_genhd.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,7 +73,7 @@
 	if (base->features & DASD_FEATURE_READONLY ||
 	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags))
 		set_disk_ro(gdp, 1);
-	gdp->private_data = block;
+	dasd_add_link_to_gendisk(gdp, base);
 	gdp->queue = block->request_queue;
 	block->gdp = gdp;
 	set_capacity(block->gdp, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_int.h linux-libre-2.6.39-gnu/drivers/s390/block/dasd_int.h
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_int.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_int.h	2011-05-19 00:06:34.000000000 -0400
@@ -686,6 +686,9 @@
 struct dasd_device *dasd_device_from_cdev_locked(struct ccw_device *);
 struct dasd_device *dasd_device_from_devindex(int);
 
+void dasd_add_link_to_gendisk(struct gendisk *, struct dasd_device *);
+struct dasd_device *dasd_device_from_gendisk(struct gendisk *);
+
 int dasd_parse(void);
 int dasd_busid_known(const char *);
 
diff -druN linux-libre-2.6.38-gnu/drivers/s390/block/dasd_ioctl.c linux-libre-2.6.39-gnu/drivers/s390/block/dasd_ioctl.c
--- linux-libre-2.6.38-gnu/drivers/s390/block/dasd_ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/block/dasd_ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,16 +42,22 @@
 static int
 dasd_ioctl_enable(struct block_device *bdev)
 {
-	struct dasd_block *block = bdev->bd_disk->private_data;
+	struct dasd_device *base;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
-	dasd_enable_device(block->base);
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
+		return -ENODEV;
+
+	dasd_enable_device(base);
 	/* Formatting the dasd device can change the capacity. */
 	mutex_lock(&bdev->bd_mutex);
-	i_size_write(bdev->bd_inode, (loff_t)get_capacity(block->gdp) << 9);
+	i_size_write(bdev->bd_inode,
+		     (loff_t)get_capacity(base->block->gdp) << 9);
 	mutex_unlock(&bdev->bd_mutex);
+	dasd_put_device(base);
 	return 0;
 }
 
@@ -62,11 +68,14 @@
 static int
 dasd_ioctl_disable(struct block_device *bdev)
 {
-	struct dasd_block *block = bdev->bd_disk->private_data;
+	struct dasd_device *base;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
+		return -ENODEV;
 	/*
 	 * Man this is sick. We don't do a real disable but only downgrade
 	 * the device to DASD_STATE_BASIC. The reason is that dasdfmt uses
@@ -75,7 +84,7 @@
 	 * using the BIODASDFMT ioctl. Therefore the correct state for the
 	 * device is DASD_STATE_BASIC that allows to do basic i/o.
 	 */
-	dasd_set_target_state(block->base, DASD_STATE_BASIC);
+	dasd_set_target_state(base, DASD_STATE_BASIC);
 	/*
 	 * Set i_size to zero, since read, write, etc. check against this
 	 * value.
@@ -83,6 +92,7 @@
 	mutex_lock(&bdev->bd_mutex);
 	i_size_write(bdev->bd_inode, 0);
 	mutex_unlock(&bdev->bd_mutex);
+	dasd_put_device(base);
 	return 0;
 }
 
@@ -191,26 +201,36 @@
 static int
 dasd_ioctl_format(struct block_device *bdev, void __user *argp)
 {
-	struct dasd_block *block = bdev->bd_disk->private_data;
+	struct dasd_device *base;
 	struct format_data_t fdata;
+	int rc;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
 	if (!argp)
 		return -EINVAL;
-
-	if (block->base->features & DASD_FEATURE_READONLY ||
-	    test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
+		return -ENODEV;
+	if (base->features & DASD_FEATURE_READONLY ||
+	    test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+		dasd_put_device(base);
 		return -EROFS;
-	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t)))
+	}
+	if (copy_from_user(&fdata, argp, sizeof(struct format_data_t))) {
+		dasd_put_device(base);
 		return -EFAULT;
+	}
 	if (bdev != bdev->bd_contains) {
 		pr_warning("%s: The specified DASD is a partition and cannot "
 			   "be formatted\n",
-			   dev_name(&block->base->cdev->dev));
+			   dev_name(&base->cdev->dev));
+		dasd_put_device(base);
 		return -EINVAL;
 	}
-	return dasd_format(block, &fdata);
+	rc = dasd_format(base->block, &fdata);
+	dasd_put_device(base);
+	return rc;
 }
 
 #ifdef CONFIG_DASD_PROFILE
@@ -340,8 +360,8 @@
 static int
 dasd_ioctl_set_ro(struct block_device *bdev, void __user *argp)
 {
-	struct dasd_block *block =  bdev->bd_disk->private_data;
-	int intval;
+	struct dasd_device *base;
+	int intval, rc;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EACCES;
@@ -350,10 +370,17 @@
 		return -EINVAL;
 	if (get_user(intval, (int __user *)argp))
 		return -EFAULT;
-	if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &block->base->flags))
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
+		return -ENODEV;
+	if (!intval && test_bit(DASD_FLAG_DEVICE_RO, &base->flags)) {
+		dasd_put_device(base);
 		return -EROFS;
+	}
 	set_disk_ro(bdev->bd_disk, intval);
-	return dasd_set_feature(block->base->cdev, DASD_FEATURE_READONLY, intval);
+	rc = dasd_set_feature(base->cdev, DASD_FEATURE_READONLY, intval);
+	dasd_put_device(base);
+	return rc;
 }
 
 static int dasd_ioctl_readall_cmb(struct dasd_block *block, unsigned int cmd,
@@ -372,59 +399,78 @@
 int dasd_ioctl(struct block_device *bdev, fmode_t mode,
 	       unsigned int cmd, unsigned long arg)
 {
-	struct dasd_block *block = bdev->bd_disk->private_data;
+	struct dasd_block *block;
+	struct dasd_device *base;
 	void __user *argp;
+	int rc;
 
 	if (is_compat_task())
 		argp = compat_ptr(arg);
 	else
 		argp = (void __user *)arg;
 
-	if (!block)
-                return -ENODEV;
-
 	if ((_IOC_DIR(cmd) != _IOC_NONE) && !arg) {
 		PRINT_DEBUG("empty data ptr");
 		return -EINVAL;
 	}
 
+	base = dasd_device_from_gendisk(bdev->bd_disk);
+	if (!base)
+		return -ENODEV;
+	block = base->block;
+	rc = 0;
 	switch (cmd) {
 	case BIODASDDISABLE:
-		return dasd_ioctl_disable(bdev);
+		rc = dasd_ioctl_disable(bdev);
+		break;
 	case BIODASDENABLE:
-		return dasd_ioctl_enable(bdev);
+		rc = dasd_ioctl_enable(bdev);
+		break;
 	case BIODASDQUIESCE:
-		return dasd_ioctl_quiesce(block);
+		rc = dasd_ioctl_quiesce(block);
+		break;
 	case BIODASDRESUME:
-		return dasd_ioctl_resume(block);
+		rc = dasd_ioctl_resume(block);
+		break;
 	case BIODASDFMT:
-		return dasd_ioctl_format(bdev, argp);
+		rc = dasd_ioctl_format(bdev, argp);
+		break;
 	case BIODASDINFO:
-		return dasd_ioctl_information(block, cmd, argp);
+		rc = dasd_ioctl_information(block, cmd, argp);
+		break;
 	case BIODASDINFO2:
-		return dasd_ioctl_information(block, cmd, argp);
+		rc = dasd_ioctl_information(block, cmd, argp);
+		break;
 	case BIODASDPRRD:
-		return dasd_ioctl_read_profile(block, argp);
+		rc = dasd_ioctl_read_profile(block, argp);
+		break;
 	case BIODASDPRRST:
-		return dasd_ioctl_reset_profile(block);
+		rc = dasd_ioctl_reset_profile(block);
+		break;
 	case BLKROSET:
-		return dasd_ioctl_set_ro(bdev, argp);
+		rc = dasd_ioctl_set_ro(bdev, argp);
+		break;
 	case DASDAPIVER:
-		return dasd_ioctl_api_version(argp);
+		rc = dasd_ioctl_api_version(argp);
+		break;
 	case BIODASDCMFENABLE:
-		return enable_cmf(block->base->cdev);
+		rc = enable_cmf(base->cdev);
+		break;
 	case BIODASDCMFDISABLE:
-		return disable_cmf(block->base->cdev);
+		rc = disable_cmf(base->cdev);
+		break;
 	case BIODASDREADALLCMB:
-		return dasd_ioctl_readall_cmb(block, cmd, argp);
+		rc = dasd_ioctl_readall_cmb(block, cmd, argp);
+		break;
 	default:
 		/* if the discipline has an ioctl method try it. */
-		if (block->base->discipline->ioctl) {
-			int rval = block->base->discipline->ioctl(block, cmd, argp);
-			if (rval != -ENOIOCTLCMD)
-				return rval;
-		}
-
-		return -EINVAL;
+		if (base->discipline->ioctl) {
+			rc = base->discipline->ioctl(block, cmd, argp);
+			if (rc == -ENOIOCTLCMD)
+				rc = -EINVAL;
+		} else
+			rc = -EINVAL;
 	}
+	dasd_put_device(base);
+	return rc;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/con3215.c linux-libre-2.6.39-gnu/drivers/s390/char/con3215.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/con3215.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/con3215.c	2011-05-19 00:06:34.000000000 -0400
@@ -764,8 +764,10 @@
 };
 
 static struct ccw_driver raw3215_ccw_driver = {
-	.name		= "3215",
-	.owner		= THIS_MODULE,
+	.driver = {
+		.name	= "3215",
+		.owner	= THIS_MODULE,
+	},
 	.ids		= raw3215_id,
 	.probe		= &raw3215_probe,
 	.remove		= &raw3215_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/keyboard.c linux-libre-2.6.39-gnu/drivers/s390/char/keyboard.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/keyboard.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/keyboard.c	2011-05-19 00:06:34.000000000 -0400
@@ -455,9 +455,7 @@
 	return 0;
 }
 
-int
-kbd_ioctl(struct kbd_data *kbd, struct file *file,
-	  unsigned int cmd, unsigned long arg)
+int kbd_ioctl(struct kbd_data *kbd, unsigned int cmd, unsigned long arg)
 {
 	void __user *argp;
 	unsigned int ct;
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/keyboard.h linux-libre-2.6.39-gnu/drivers/s390/char/keyboard.h
--- linux-libre-2.6.38-gnu/drivers/s390/char/keyboard.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/keyboard.h	2011-05-19 00:06:34.000000000 -0400
@@ -36,7 +36,7 @@
 void kbd_ascebc(struct kbd_data *, unsigned char *);
 
 void kbd_keycode(struct kbd_data *, unsigned int);
-int kbd_ioctl(struct kbd_data *, struct file *, unsigned int, unsigned long);
+int kbd_ioctl(struct kbd_data *, unsigned int, unsigned long);
 
 /*
  * Helper Functions.
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/raw3270.c linux-libre-2.6.39-gnu/drivers/s390/char/raw3270.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/raw3270.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/raw3270.c	2011-05-19 00:06:34.000000000 -0400
@@ -604,7 +604,7 @@
 	/*
 	 * To determine the size of the 3270 device we need to do:
 	 * 1) send a 'read partition' data stream to the device
-	 * 2) wait for the attn interrupt that preceeds the query reply
+	 * 2) wait for the attn interrupt that precedes the query reply
 	 * 3) do a read modified to get the query reply
 	 * To make things worse we have to cope with intervention
 	 * required (3270 device switched to 'stand-by') and command
@@ -1388,8 +1388,10 @@
 };
 
 static struct ccw_driver raw3270_ccw_driver = {
-	.name		= "3270",
-	.owner		= THIS_MODULE,
+	.driver = {
+		.name	= "3270",
+		.owner	= THIS_MODULE,
+	},
 	.ids		= raw3270_id,
 	.probe		= &raw3270_probe,
 	.remove		= &raw3270_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/sclp_cmd.c linux-libre-2.6.39-gnu/drivers/s390/char/sclp_cmd.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/sclp_cmd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/sclp_cmd.c	2011-05-19 00:06:34.000000000 -0400
@@ -518,6 +518,8 @@
 		return;
 	new_incr->rn = rn;
 	new_incr->standby = standby;
+	if (!standby)
+		new_incr->usecount = 1;
 	last_rn = 0;
 	prev = &sclp_mem_list;
 	list_for_each_entry(incr, &sclp_mem_list, list) {
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/tape_34xx.c linux-libre-2.6.39-gnu/drivers/s390/char/tape_34xx.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/tape_34xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/tape_34xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -1320,8 +1320,10 @@
 }
 
 static struct ccw_driver tape_34xx_driver = {
-	.name = "tape_34xx",
-	.owner = THIS_MODULE,
+	.driver = {
+		.name = "tape_34xx",
+		.owner = THIS_MODULE,
+	},
 	.ids = tape_34xx_ids,
 	.probe = tape_generic_probe,
 	.remove = tape_generic_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/tape_3590.c linux-libre-2.6.39-gnu/drivers/s390/char/tape_3590.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/tape_3590.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/tape_3590.c	2011-05-19 00:06:34.000000000 -0400
@@ -1761,8 +1761,10 @@
 }
 
 static struct ccw_driver tape_3590_driver = {
-	.name = "tape_3590",
-	.owner = THIS_MODULE,
+	.driver = {
+		.name = "tape_3590",
+		.owner = THIS_MODULE,
+	},
 	.ids = tape_3590_ids,
 	.probe = tape_generic_probe,
 	.remove = tape_generic_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/tape_block.c linux-libre-2.6.39-gnu/drivers/s390/char/tape_block.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/tape_block.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/tape_block.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,14 +48,14 @@
 static DEFINE_MUTEX(tape_block_mutex);
 static int tapeblock_open(struct block_device *, fmode_t);
 static int tapeblock_release(struct gendisk *, fmode_t);
-static int tapeblock_medium_changed(struct gendisk *);
+static unsigned int tapeblock_check_events(struct gendisk *, unsigned int);
 static int tapeblock_revalidate_disk(struct gendisk *);
 
 static const struct block_device_operations tapeblock_fops = {
 	.owner		 = THIS_MODULE,
 	.open		 = tapeblock_open,
 	.release	 = tapeblock_release,
-	.media_changed   = tapeblock_medium_changed,
+	.check_events	 = tapeblock_check_events,
 	.revalidate_disk = tapeblock_revalidate_disk,
 };
 
@@ -161,7 +161,6 @@
 
 	spin_lock_irq(&device->blk_data.request_queue_lock);
 	while (
-		!blk_queue_plugged(queue) &&
 		blk_peek_request(queue) &&
 		nr_queued < TAPEBLOCK_MIN_REQUEUE
 	) {
@@ -340,8 +339,8 @@
 	return 0;
 }
 
-static int
-tapeblock_medium_changed(struct gendisk *disk)
+static unsigned int
+tapeblock_check_events(struct gendisk *disk, unsigned int clearing)
 {
 	struct tape_device *device;
 
@@ -349,7 +348,7 @@
 	DBF_LH(6, "tapeblock_medium_changed(%p) = %d\n",
 		device, device->blk_data.medium_changed);
 
-	return device->blk_data.medium_changed;
+	return device->blk_data.medium_changed ? DISK_EVENT_MEDIA_CHANGE : 0;
 }
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/tape_char.c linux-libre-2.6.39-gnu/drivers/s390/char/tape_char.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/tape_char.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/tape_char.c	2011-05-19 00:06:34.000000000 -0400
@@ -139,7 +139,7 @@
 	/*
 	 * If the tape isn't terminated yet, do it now. And since we then
 	 * are at the end of the tape there wouldn't be anything to read
-	 * anyways. So we return immediatly.
+	 * anyways. So we return immediately.
 	 */
 	if(device->required_tapemarks) {
 		return tape_std_terminate_write(device);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/tty3270.c linux-libre-2.6.39-gnu/drivers/s390/char/tty3270.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/tty3270.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/tty3270.c	2011-05-19 00:06:34.000000000 -0400
@@ -328,7 +328,7 @@
 
 	tp = (struct tty3270 *) rq->view;
 	if (rq->rc != 0) {
-		/* Write wasn't successfull. Refresh all. */
+		/* Write wasn't successful. Refresh all. */
 		tp->update_flags = TTY_UPDATE_ALL;
 		tty3270_set_timer(tp, 1);
 	}
@@ -1718,9 +1718,8 @@
 {
 }
 
-static int
-tty3270_ioctl(struct tty_struct *tty, struct file *file,
-	      unsigned int cmd, unsigned long arg)
+static int tty3270_ioctl(struct tty_struct *tty, unsigned int cmd,
+			 unsigned long arg)
 {
 	struct tty3270 *tp;
 
@@ -1729,13 +1728,12 @@
 		return -ENODEV;
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
-	return kbd_ioctl(tp->kbd, file, cmd, arg);
+	return kbd_ioctl(tp->kbd, cmd, arg);
 }
 
 #ifdef CONFIG_COMPAT
-static long
-tty3270_compat_ioctl(struct tty_struct *tty, struct file *file,
-	      unsigned int cmd, unsigned long arg)
+static long tty3270_compat_ioctl(struct tty_struct *tty,
+				 unsigned int cmd, unsigned long arg)
 {
 	struct tty3270 *tp;
 
@@ -1744,7 +1742,7 @@
 		return -ENODEV;
 	if (tty->flags & (1 << TTY_IO_ERROR))
 		return -EIO;
-	return kbd_ioctl(tp->kbd, file, cmd, (unsigned long)compat_ptr(arg));
+	return kbd_ioctl(tp->kbd, cmd, (unsigned long)compat_ptr(arg));
 }
 #endif
 
diff -druN linux-libre-2.6.38-gnu/drivers/s390/char/vmur.c linux-libre-2.6.39-gnu/drivers/s390/char/vmur.c
--- linux-libre-2.6.38-gnu/drivers/s390/char/vmur.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/char/vmur.c	2011-05-19 00:06:34.000000000 -0400
@@ -64,8 +64,10 @@
 static int ur_pm_suspend(struct ccw_device *cdev);
 
 static struct ccw_driver ur_driver = {
-	.name		= "vmur",
-	.owner		= THIS_MODULE,
+	.driver = {
+		.name	= "vmur",
+		.owner	= THIS_MODULE,
+	},
 	.ids		= ur_ids,
 	.probe		= ur_probe,
 	.remove		= ur_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/ccwgroup.c linux-libre-2.6.39-gnu/drivers/s390/cio/ccwgroup.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/ccwgroup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/ccwgroup.c	2011-05-19 00:06:34.000000000 -0400
@@ -428,7 +428,7 @@
 	gdev = to_ccwgroupdev(dev);
 	gdrv = to_ccwgroupdrv(dev->driver);
 
-	if (!try_module_get(gdrv->owner))
+	if (!try_module_get(gdrv->driver.owner))
 		return -EINVAL;
 
 	ret = strict_strtoul(buf, 0, &value);
@@ -442,7 +442,7 @@
 	else
 		ret = -EINVAL;
 out:
-	module_put(gdrv->owner);
+	module_put(gdrv->driver.owner);
 	return (ret == 0) ? count : ret;
 }
 
@@ -616,8 +616,6 @@
 {
 	/* register our new driver with the core */
 	cdriver->driver.bus = &ccwgroup_bus_type;
-	cdriver->driver.name = cdriver->name;
-	cdriver->driver.owner = cdriver->owner;
 
 	return driver_register(&cdriver->driver);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/chsc_sch.c linux-libre-2.6.39-gnu/drivers/s390/cio/chsc_sch.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/chsc_sch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/chsc_sch.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
 
 static void chsc_subchannel_irq(struct subchannel *sch)
 {
-	struct chsc_private *private = sch->private;
+	struct chsc_private *private = dev_get_drvdata(&sch->dev);
 	struct chsc_request *request = private->request;
 	struct irb *irb = (struct irb *)&S390_lowcore.irb;
 
@@ -80,13 +80,14 @@
 	private = kzalloc(sizeof(*private), GFP_KERNEL);
 	if (!private)
 		return -ENOMEM;
+	dev_set_drvdata(&sch->dev, private);
 	ret = cio_enable_subchannel(sch, (u32)(unsigned long)sch);
 	if (ret) {
 		CHSC_MSG(0, "Failed to enable 0.%x.%04x: %d\n",
 			 sch->schid.ssid, sch->schid.sch_no, ret);
+		dev_set_drvdata(&sch->dev, NULL);
 		kfree(private);
 	} else {
-		sch->private = private;
 		if (dev_get_uevent_suppress(&sch->dev)) {
 			dev_set_uevent_suppress(&sch->dev, 0);
 			kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
@@ -100,8 +101,8 @@
 	struct chsc_private *private;
 
 	cio_disable_subchannel(sch);
-	private = sch->private;
-	sch->private = NULL;
+	private = dev_get_drvdata(&sch->dev);
+	dev_set_drvdata(&sch->dev, NULL);
 	if (private->request) {
 		complete(&private->request->completion);
 		put_device(&sch->dev);
@@ -147,7 +148,10 @@
 MODULE_DEVICE_TABLE(css, chsc_subchannel_ids);
 
 static struct css_driver chsc_subchannel_driver = {
-	.owner = THIS_MODULE,
+	.drv = {
+		.owner = THIS_MODULE,
+		.name = "chsc_subchannel",
+	},
 	.subchannel_type = chsc_subchannel_ids,
 	.irq = chsc_subchannel_irq,
 	.probe = chsc_subchannel_probe,
@@ -157,7 +161,6 @@
 	.freeze = chsc_subchannel_freeze,
 	.thaw = chsc_subchannel_restore,
 	.restore = chsc_subchannel_restore,
-	.name = "chsc_subchannel",
 };
 
 static int __init chsc_init_dbfs(void)
@@ -241,7 +244,7 @@
 	chsc_area->header.key = PAGE_DEFAULT_KEY >> 4;
 	while ((sch = chsc_get_next_subchannel(sch))) {
 		spin_lock(sch->lock);
-		private = sch->private;
+		private = dev_get_drvdata(&sch->dev);
 		if (private->request) {
 			spin_unlock(sch->lock);
 			ret = -EBUSY;
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/cio.c linux-libre-2.6.39-gnu/drivers/s390/cio/cio.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/cio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/cio.c	2011-05-19 00:06:34.000000000 -0400
@@ -84,29 +84,14 @@
 
 arch_initcall (cio_debug_init);
 
-int
-cio_set_options (struct subchannel *sch, int flags)
-{
-       sch->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
-       sch->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
-       sch->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
-       return 0;
-}
-
-/* FIXME: who wants to use this? */
-int
-cio_get_options (struct subchannel *sch)
+int cio_set_options(struct subchannel *sch, int flags)
 {
-       int flags;
+	struct io_subchannel_private *priv = to_io_private(sch);
 
-       flags = 0;
-       if (sch->options.suspend)
-		flags |= DOIO_ALLOW_SUSPEND;
-       if (sch->options.prefetch)
-		flags |= DOIO_DENY_PREFETCH;
-       if (sch->options.inter)
-		flags |= DOIO_SUPPRESS_INTER;
-       return flags;
+	priv->options.suspend = (flags & DOIO_ALLOW_SUSPEND) != 0;
+	priv->options.prefetch = (flags & DOIO_DENY_PREFETCH) != 0;
+	priv->options.inter = (flags & DOIO_SUPPRESS_INTER) != 0;
+	return 0;
 }
 
 static int
@@ -139,21 +124,21 @@
 	       __u8 lpm,		/* logical path mask */
 	       __u8 key)                /* storage key */
 {
+	struct io_subchannel_private *priv = to_io_private(sch);
+	union orb *orb = &priv->orb;
 	int ccode;
-	union orb *orb;
 
 	CIO_TRACE_EVENT(5, "stIO");
 	CIO_TRACE_EVENT(5, dev_name(&sch->dev));
 
-	orb = &to_io_private(sch)->orb;
 	memset(orb, 0, sizeof(union orb));
 	/* sch is always under 2G. */
 	orb->cmd.intparm = (u32)(addr_t)sch;
 	orb->cmd.fmt = 1;
 
-	orb->cmd.pfch = sch->options.prefetch == 0;
-	orb->cmd.spnd = sch->options.suspend;
-	orb->cmd.ssic = sch->options.suspend && sch->options.inter;
+	orb->cmd.pfch = priv->options.prefetch == 0;
+	orb->cmd.spnd = priv->options.suspend;
+	orb->cmd.ssic = priv->options.suspend && priv->options.inter;
 	orb->cmd.lpm = (lpm != 0) ? lpm : sch->lpm;
 #ifdef CONFIG_64BIT
 	/*
@@ -630,11 +615,7 @@
 	irb = (struct irb *)&S390_lowcore.irb;
 	do {
 		kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
-		/*
-		 * Non I/O-subchannel thin interrupts are processed differently
-		 */
-		if (tpi_info->adapter_IO == 1 &&
-		    tpi_info->int_type == IO_INTERRUPT_TYPE) {
+		if (tpi_info->adapter_IO) {
 			do_adapter_IO(tpi_info->isc);
 			continue;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/cio.h linux-libre-2.6.39-gnu/drivers/s390/cio/cio.h
--- linux-libre-2.6.38-gnu/drivers/s390/cio/cio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/cio.h	2011-05-19 00:06:34.000000000 -0400
@@ -84,13 +84,6 @@
 		SUBCHANNEL_TYPE_MSG = 2,
 		SUBCHANNEL_TYPE_ADM = 3,
 	} st;			/* subchannel type */
-
-	struct {
-		unsigned int suspend:1; /* allow suspend */
-		unsigned int prefetch:1;/* deny prefetch */
-		unsigned int inter:1;   /* suppress intermediate interrupts */
-	} __attribute__ ((packed)) options;
-
 	__u8 vpm;		/* verified path mask */
 	__u8 lpm;		/* logical path mask */
 	__u8 opm;               /* operational path mask */
@@ -99,14 +92,11 @@
 	struct chsc_ssd_info ssd_info;	/* subchannel description */
 	struct device dev;	/* entry in device tree */
 	struct css_driver *driver;
-	void *private; /* private per subchannel type data */
 	enum sch_todo todo;
 	struct work_struct todo_work;
 	struct schib_config config;
 } __attribute__ ((aligned(8)));
 
-#define IO_INTERRUPT_TYPE	   0 /* I/O interrupt type */
-
 #define to_subchannel(n) container_of(n, struct subchannel, dev)
 
 extern int cio_validate_subchannel (struct subchannel *, struct subchannel_id);
@@ -120,7 +110,6 @@
 extern int cio_start_key (struct subchannel *, struct ccw1 *, __u8, __u8);
 extern int cio_cancel (struct subchannel *);
 extern int cio_set_options (struct subchannel *, int);
-extern int cio_get_options (struct subchannel *);
 extern int cio_update_schib(struct subchannel *sch);
 extern int cio_commit_config(struct subchannel *sch);
 
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/css.c linux-libre-2.6.39-gnu/drivers/s390/cio/css.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/css.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/css.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,7 @@
 int max_ssid;
 
 struct channel_subsystem *channel_subsystems[__MAX_CSSID + 1];
+static struct bus_type css_bus_type;
 
 int
 for_each_subchannel(int(*fn)(struct subchannel_id, void *), void *data)
@@ -1214,7 +1215,7 @@
 	.restore = css_pm_restore,
 };
 
-struct bus_type css_bus_type = {
+static struct bus_type css_bus_type = {
 	.name     = "css",
 	.match    = css_bus_match,
 	.probe    = css_probe,
@@ -1233,9 +1234,7 @@
  */
 int css_driver_register(struct css_driver *cdrv)
 {
-	cdrv->drv.name = cdrv->name;
 	cdrv->drv.bus = &css_bus_type;
-	cdrv->drv.owner = cdrv->owner;
 	return driver_register(&cdrv->drv);
 }
 EXPORT_SYMBOL_GPL(css_driver_register);
@@ -1253,4 +1252,3 @@
 EXPORT_SYMBOL_GPL(css_driver_unregister);
 
 MODULE_LICENSE("GPL");
-EXPORT_SYMBOL(css_bus_type);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/css.h linux-libre-2.6.39-gnu/drivers/s390/cio/css.h
--- linux-libre-2.6.38-gnu/drivers/s390/cio/css.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/css.h	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,6 @@
 struct chp_link;
 /**
  * struct css_driver - device driver for subchannels
- * @owner: owning module
  * @subchannel_type: subchannel type supported by this driver
  * @drv: embedded device driver structure
  * @irq: called on interrupts
@@ -78,10 +77,8 @@
  * @thaw: undo work done in @freeze
  * @restore: callback for restoring after hibernation
  * @settle: wait for asynchronous work to finish
- * @name: name of the device driver
  */
 struct css_driver {
-	struct module *owner;
 	struct css_device_id *subchannel_type;
 	struct device_driver drv;
 	void (*irq)(struct subchannel *);
@@ -96,16 +93,10 @@
 	int (*thaw) (struct subchannel *);
 	int (*restore)(struct subchannel *);
 	int (*settle)(void);
-	const char *name;
 };
 
 #define to_cssdriver(n) container_of(n, struct css_driver, drv)
 
-/*
- * all css_drivers have the css_bus_type
- */
-extern struct bus_type css_bus_type;
-
 extern int css_driver_register(struct css_driver *);
 extern void css_driver_unregister(struct css_driver *);
 
@@ -140,7 +131,6 @@
 };
 #define to_css(dev) container_of(dev, struct channel_subsystem, device)
 
-extern struct bus_type css_bus_type;
 extern struct channel_subsystem *channel_subsystems[];
 
 /* Helper functions to build lists for the slow path. */
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/device.c linux-libre-2.6.39-gnu/drivers/s390/cio/device.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/device.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/device.c	2011-05-19 00:06:34.000000000 -0400
@@ -127,7 +127,7 @@
 	return ret;
 }
 
-struct bus_type ccw_bus_type;
+static struct bus_type ccw_bus_type;
 
 static void io_subchannel_irq(struct subchannel *);
 static int io_subchannel_probe(struct subchannel *);
@@ -172,9 +172,11 @@
 }
 
 static struct css_driver io_subchannel_driver = {
-	.owner = THIS_MODULE,
+	.drv = {
+		.owner = THIS_MODULE,
+		.name = "io_subchannel",
+	},
 	.subchannel_type = io_subchannel_ids,
-	.name = "io_subchannel",
 	.irq = io_subchannel_irq,
 	.sch_event = io_subchannel_sch_event,
 	.chp_event = io_subchannel_chp_event,
@@ -539,15 +541,24 @@
 	int force, ret;
 	unsigned long i;
 
-	if (!dev_fsm_final_state(cdev) &&
-	    cdev->private->state != DEV_STATE_DISCONNECTED)
-		return -EAGAIN;
+	/* Prevent conflict between multiple on-/offline processing requests. */
 	if (atomic_cmpxchg(&cdev->private->onoff, 0, 1) != 0)
 		return -EAGAIN;
+	/* Prevent conflict between internal I/Os and on-/offline processing. */
+	if (!dev_fsm_final_state(cdev) &&
+	    cdev->private->state != DEV_STATE_DISCONNECTED) {
+		ret = -EAGAIN;
+		goto out_onoff;
+	}
+	/* Prevent conflict between pending work and on-/offline processing.*/
+	if (work_pending(&cdev->private->todo_work)) {
+		ret = -EAGAIN;
+		goto out_onoff;
+	}
 
-	if (cdev->drv && !try_module_get(cdev->drv->owner)) {
-		atomic_set(&cdev->private->onoff, 0);
-		return -EINVAL;
+	if (cdev->drv && !try_module_get(cdev->drv->driver.owner)) {
+		ret = -EINVAL;
+		goto out_onoff;
 	}
 	if (!strncmp(buf, "force\n", count)) {
 		force = 1;
@@ -571,7 +582,8 @@
 	}
 out:
 	if (cdev->drv)
-		module_put(cdev->drv->owner);
+		module_put(cdev->drv->driver.owner);
+out_onoff:
 	atomic_set(&cdev->private->onoff, 0);
 	return (ret < 0) ? ret : count;
 }
@@ -1030,6 +1042,7 @@
  */
 static int io_subchannel_probe(struct subchannel *sch)
 {
+	struct io_subchannel_private *io_priv;
 	struct ccw_device *cdev;
 	int rc;
 
@@ -1073,10 +1086,11 @@
 	if (rc)
 		goto out_schedule;
 	/* Allocate I/O subchannel private data. */
-	sch->private = kzalloc(sizeof(struct io_subchannel_private),
-			       GFP_KERNEL | GFP_DMA);
-	if (!sch->private)
+	io_priv = kzalloc(sizeof(*io_priv), GFP_KERNEL | GFP_DMA);
+	if (!io_priv)
 		goto out_schedule;
+
+	set_io_private(sch, io_priv);
 	css_schedule_eval(sch->schid);
 	return 0;
 
@@ -1090,6 +1104,7 @@
 static int
 io_subchannel_remove (struct subchannel *sch)
 {
+	struct io_subchannel_private *io_priv = to_io_private(sch);
 	struct ccw_device *cdev;
 
 	cdev = sch_get_cdev(sch);
@@ -1099,11 +1114,12 @@
 	/* Set ccw device to not operational and drop reference. */
 	spin_lock_irq(cdev->ccwlock);
 	sch_set_cdev(sch, NULL);
+	set_io_private(sch, NULL);
 	cdev->private->state = DEV_STATE_NOT_OPER;
 	spin_unlock_irq(cdev->ccwlock);
 	ccw_device_unregister(cdev);
 out_free:
-	kfree(sch->private);
+	kfree(io_priv);
 	sysfs_remove_group(&sch->dev.kobj, &io_subchannel_attr_group);
 	return 0;
 }
@@ -1305,10 +1321,12 @@
 
 	spin_lock_irq(cdev->ccwlock);
 	if (is_blacklisted(id->ssid, id->devno) &&
-	    (cdev->private->state == DEV_STATE_OFFLINE)) {
+	    (cdev->private->state == DEV_STATE_OFFLINE) &&
+	    (atomic_cmpxchg(&cdev->private->onoff, 0, 1) == 0)) {
 		CIO_MSG_EVENT(3, "ccw: purging 0.%x.%04x\n", id->ssid,
 			      id->devno);
 		ccw_device_sched_todo(cdev, CDEV_TODO_UNREG);
+		atomic_set(&cdev->private->onoff, 0);
 	}
 	spin_unlock_irq(cdev->ccwlock);
 	/* Abort loop in case of pending signal. */
@@ -1553,11 +1571,12 @@
 static int ccw_device_console_enable(struct ccw_device *cdev,
 				     struct subchannel *sch)
 {
+	struct io_subchannel_private *io_priv = cio_get_console_priv();
 	int rc;
 
 	/* Attach subchannel private data. */
-	sch->private = cio_get_console_priv();
-	memset(sch->private, 0, sizeof(struct io_subchannel_private));
+	memset(io_priv, 0, sizeof(*io_priv));
+	set_io_private(sch, io_priv);
 	io_subchannel_init_fields(sch);
 	rc = cio_commit_config(sch);
 	if (rc)
@@ -1963,7 +1982,7 @@
 	.restore = ccw_device_pm_restore,
 };
 
-struct bus_type ccw_bus_type = {
+static struct bus_type ccw_bus_type = {
 	.name   = "ccw",
 	.match  = ccw_bus_match,
 	.uevent = ccw_uevent,
@@ -1986,8 +2005,6 @@
 	struct device_driver *drv = &cdriver->driver;
 
 	drv->bus = &ccw_bus_type;
-	drv->name = cdriver->name;
-	drv->owner = cdriver->owner;
 
 	return driver_register(drv);
 }
@@ -2105,5 +2122,4 @@
 EXPORT_SYMBOL(ccw_driver_register);
 EXPORT_SYMBOL(ccw_driver_unregister);
 EXPORT_SYMBOL(get_ccwdev_by_busid);
-EXPORT_SYMBOL(ccw_bus_type);
 EXPORT_SYMBOL_GPL(ccw_device_get_subchannel_id);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/device_fsm.c linux-libre-2.6.39-gnu/drivers/s390/cio/device_fsm.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/device_fsm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/device_fsm.c	2011-05-19 00:06:34.000000000 -0400
@@ -318,7 +318,7 @@
 
 /**
   * ccw_device_notify() - inform the device's driver about an event
-  * @cdev: device for which an event occured
+  * @cdev: device for which an event occurred
   * @event: event that occurred
   *
   * Returns:
@@ -688,7 +688,7 @@
 	    (scsw_stctl(&cdev->private->irb.scsw) & SCSW_STCTL_STATUS_PEND)) {
 		/*
 		 * No final status yet or final status not yet delivered
-		 * to the device driver. Can't do path verfication now,
+		 * to the device driver. Can't do path verification now,
 		 * delay until final status was delivered.
 		 */
 		cdev->private->flags.doverify = 1;
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/device.h linux-libre-2.6.39-gnu/drivers/s390/cio/device.h
--- linux-libre-2.6.38-gnu/drivers/s390/cio/device.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/device.h	2011-05-19 00:06:34.000000000 -0400
@@ -133,7 +133,6 @@
 /* qdio needs this. */
 void ccw_device_set_timeout(struct ccw_device *, int);
 extern struct subchannel_id ccw_device_get_subchannel_id(struct ccw_device *);
-extern struct bus_type ccw_bus_type;
 
 /* Channel measurement facility related */
 void retry_set_schib(struct ccw_device *cdev);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/ioasm.h linux-libre-2.6.39-gnu/drivers/s390/cio/ioasm.h
--- linux-libre-2.6.38-gnu/drivers/s390/cio/ioasm.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/ioasm.h	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,8 @@
 
 #include <asm/chpid.h>
 #include <asm/schid.h>
+#include "orb.h"
+#include "cio.h"
 
 /*
  * TPI info structure
@@ -86,6 +88,38 @@
 		: "cc");
 	return ccode;
 }
+
+static inline int ssch(struct subchannel_id schid, union orb *addr)
+{
+	register struct subchannel_id reg1 asm("1") = schid;
+	int ccode = -EIO;
+
+	asm volatile(
+		"	ssch	0(%2)\n"
+		"0:	ipm	%0\n"
+		"	srl	%0,28\n"
+		"1:\n"
+		EX_TABLE(0b, 1b)
+		: "+d" (ccode)
+		: "d" (reg1), "a" (addr), "m" (*addr)
+		: "cc", "memory");
+	return ccode;
+}
+
+static inline int csch(struct subchannel_id schid)
+{
+	register struct subchannel_id reg1 asm("1") = schid;
+	int ccode;
+
+	asm volatile(
+		"	csch\n"
+		"	ipm	%0\n"
+		"	srl	%0,28"
+		: "=d" (ccode)
+		: "d" (reg1)
+		: "cc");
+	return ccode;
+}
 
 static inline int tpi(struct tpi_info *addr)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/io_sch.h linux-libre-2.6.39-gnu/drivers/s390/cio/io_sch.h
--- linux-libre-2.6.38-gnu/drivers/s390/cio/io_sch.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/io_sch.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,68 +5,36 @@
 #include <asm/schid.h>
 #include <asm/ccwdev.h>
 #include "css.h"
-
-/*
- * command-mode operation request block
- */
-struct cmd_orb {
-	u32 intparm;	/* interruption parameter */
-	u32 key  : 4;	/* flags, like key, suspend control, etc. */
-	u32 spnd : 1;	/* suspend control */
-	u32 res1 : 1;	/* reserved */
-	u32 mod  : 1;	/* modification control */
-	u32 sync : 1;	/* synchronize control */
-	u32 fmt  : 1;	/* format control */
-	u32 pfch : 1;	/* prefetch control */
-	u32 isic : 1;	/* initial-status-interruption control */
-	u32 alcc : 1;	/* address-limit-checking control */
-	u32 ssic : 1;	/* suppress-suspended-interr. control */
-	u32 res2 : 1;	/* reserved */
-	u32 c64  : 1;	/* IDAW/QDIO 64 bit control  */
-	u32 i2k  : 1;	/* IDAW 2/4kB block size control */
-	u32 lpm  : 8;	/* logical path mask */
-	u32 ils  : 1;	/* incorrect length */
-	u32 zero : 6;	/* reserved zeros */
-	u32 orbx : 1;	/* ORB extension control */
-	u32 cpa;	/* channel program address */
-}  __attribute__ ((packed, aligned(4)));
-
-/*
- * transport-mode operation request block
- */
-struct tm_orb {
-	u32 intparm;
-	u32 key:4;
-	u32 :9;
-	u32 b:1;
-	u32 :2;
-	u32 lpm:8;
-	u32 :7;
-	u32 x:1;
-	u32 tcw;
-	u32 prio:8;
-	u32 :8;
-	u32 rsvpgm:8;
-	u32 :8;
-	u32 :32;
-	u32 :32;
-	u32 :32;
-	u32 :32;
-}  __attribute__ ((packed, aligned(4)));
-
-union orb {
-	struct cmd_orb cmd;
-	struct tm_orb tm;
-}  __attribute__ ((packed, aligned(4)));
+#include "orb.h"
 
 struct io_subchannel_private {
 	union orb orb;		/* operation request block */
 	struct ccw1 sense_ccw;	/* static ccw for sense command */
-} __attribute__ ((aligned(8)));
+	struct ccw_device *cdev;/* pointer to the child ccw device */
+	struct {
+		unsigned int suspend:1;	/* allow suspend */
+		unsigned int prefetch:1;/* deny prefetch */
+		unsigned int inter:1;	/* suppress intermediate interrupts */
+	} __packed options;
+} __aligned(8);
 
-#define to_io_private(n) ((struct io_subchannel_private *)n->private)
-#define sch_get_cdev(n) (dev_get_drvdata(&n->dev))
-#define sch_set_cdev(n, c) (dev_set_drvdata(&n->dev, c))
+#define to_io_private(n) ((struct io_subchannel_private *) \
+			  dev_get_drvdata(&(n)->dev))
+#define set_io_private(n, p) (dev_set_drvdata(&(n)->dev, p))
+
+static inline struct ccw_device *sch_get_cdev(struct subchannel *sch)
+{
+	struct io_subchannel_private *priv = to_io_private(sch);
+	return priv ? priv->cdev : NULL;
+}
+
+static inline void sch_set_cdev(struct subchannel *sch,
+				struct ccw_device *cdev)
+{
+	struct io_subchannel_private *priv = to_io_private(sch);
+	if (priv)
+		priv->cdev = cdev;
+}
 
 #define MAX_CIWS 8
 
@@ -191,23 +159,6 @@
 	void *cmb_wait;			/* deferred cmb enable/disable */
 };
 
-static inline int ssch(struct subchannel_id schid, union orb *addr)
-{
-	register struct subchannel_id reg1 asm("1") = schid;
-	int ccode = -EIO;
-
-	asm volatile(
-		"	ssch	0(%2)\n"
-		"0:	ipm	%0\n"
-		"	srl	%0,28\n"
-		"1:\n"
-		EX_TABLE(0b, 1b)
-		: "+d" (ccode)
-		: "d" (reg1), "a" (addr), "m" (*addr)
-		: "cc", "memory");
-	return ccode;
-}
-
 static inline int rsch(struct subchannel_id schid)
 {
 	register struct subchannel_id reg1 asm("1") = schid;
@@ -223,21 +174,6 @@
 	return ccode;
 }
 
-static inline int csch(struct subchannel_id schid)
-{
-	register struct subchannel_id reg1 asm("1") = schid;
-	int ccode;
-
-	asm volatile(
-		"	csch\n"
-		"	ipm	%0\n"
-		"	srl	%0,28"
-		: "=d" (ccode)
-		: "d" (reg1)
-		: "cc");
-	return ccode;
-}
-
 static inline int hsch(struct subchannel_id schid)
 {
 	register struct subchannel_id reg1 asm("1") = schid;
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/orb.h linux-libre-2.6.39-gnu/drivers/s390/cio/orb.h
--- linux-libre-2.6.38-gnu/drivers/s390/cio/orb.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/orb.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,67 @@
+/*
+ * Orb related data structures.
+ *
+ * Copyright IBM Corp. 2007, 2011
+ *
+ * Author(s): Cornelia Huck <cornelia.huck@de.ibm.com>
+ *	      Peter Oberparleiter <peter.oberparleiter@de.ibm.com>
+ *	      Sebastian Ott <sebott@linux.vnet.ibm.com>
+ */
+
+#ifndef S390_ORB_H
+#define S390_ORB_H
+
+/*
+ * Command-mode operation request block
+ */
+struct cmd_orb {
+	u32 intparm;	/* interruption parameter */
+	u32 key:4;	/* flags, like key, suspend control, etc. */
+	u32 spnd:1;	/* suspend control */
+	u32 res1:1;	/* reserved */
+	u32 mod:1;	/* modification control */
+	u32 sync:1;	/* synchronize control */
+	u32 fmt:1;	/* format control */
+	u32 pfch:1;	/* prefetch control */
+	u32 isic:1;	/* initial-status-interruption control */
+	u32 alcc:1;	/* address-limit-checking control */
+	u32 ssic:1;	/* suppress-suspended-interr. control */
+	u32 res2:1;	/* reserved */
+	u32 c64:1;	/* IDAW/QDIO 64 bit control  */
+	u32 i2k:1;	/* IDAW 2/4kB block size control */
+	u32 lpm:8;	/* logical path mask */
+	u32 ils:1;	/* incorrect length */
+	u32 zero:6;	/* reserved zeros */
+	u32 orbx:1;	/* ORB extension control */
+	u32 cpa;	/* channel program address */
+}  __packed __aligned(4);
+
+/*
+ * Transport-mode operation request block
+ */
+struct tm_orb {
+	u32 intparm;
+	u32 key:4;
+	u32:9;
+	u32 b:1;
+	u32:2;
+	u32 lpm:8;
+	u32:7;
+	u32 x:1;
+	u32 tcw;
+	u32 prio:8;
+	u32:8;
+	u32 rsvpgm:8;
+	u32:8;
+	u32:32;
+	u32:32;
+	u32:32;
+	u32:32;
+}  __packed __aligned(4);
+
+union orb {
+	struct cmd_orb cmd;
+	struct tm_orb tm;
+}  __packed __aligned(4);
+
+#endif /* S390_ORB_H */
diff -druN linux-libre-2.6.38-gnu/drivers/s390/cio/qdio_main.c linux-libre-2.6.39-gnu/drivers/s390/cio/qdio_main.c
--- linux-libre-2.6.38-gnu/drivers/s390/cio/qdio_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/cio/qdio_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -407,8 +407,11 @@
 	q->q_stats.nr_sbals[pos]++;
 }
 
-static void announce_buffer_error(struct qdio_q *q, int count)
+static void process_buffer_error(struct qdio_q *q, int count)
 {
+	unsigned char state = (q->is_input_q) ? SLSB_P_INPUT_NOT_INIT :
+					SLSB_P_OUTPUT_NOT_INIT;
+
 	q->qdio_error |= QDIO_ERROR_SLSB_STATE;
 
 	/* special handling for no target buffer empty */
@@ -426,6 +429,12 @@
 	DBF_ERROR("F14:%2x F15:%2x",
 		  q->sbal[q->first_to_check]->element[14].flags & 0xff,
 		  q->sbal[q->first_to_check]->element[15].flags & 0xff);
+
+	/*
+	 * Interrupts may be avoided as long as the error is present
+	 * so change the buffer state immediately to avoid starvation.
+	 */
+	set_buf_states(q, q->first_to_check, state, count);
 }
 
 static inline void inbound_primed(struct qdio_q *q, int count)
@@ -506,8 +515,7 @@
 			account_sbals(q, count);
 		break;
 	case SLSB_P_INPUT_ERROR:
-		announce_buffer_error(q, count);
-		/* process the buffer, the upper layer will take care of it */
+		process_buffer_error(q, count);
 		q->first_to_check = add_buf(q->first_to_check, count);
 		atomic_sub(count, &q->nr_buf_used);
 		if (q->irq_ptr->perf_stat_enabled)
@@ -677,8 +685,7 @@
 			account_sbals(q, count);
 		break;
 	case SLSB_P_OUTPUT_ERROR:
-		announce_buffer_error(q, count);
-		/* process the buffer, the upper layer will take care of it */
+		process_buffer_error(q, count);
 		q->first_to_check = add_buf(q->first_to_check, count);
 		atomic_sub(count, &q->nr_buf_used);
 		if (q->irq_ptr->perf_stat_enabled)
@@ -1508,7 +1515,8 @@
 
 	if (irq_ptr->state != QDIO_IRQ_STATE_ACTIVE)
 		return -EBUSY;
-
+	if (!count)
+		return 0;
 	if (callflags & QDIO_FLAG_SYNC_INPUT)
 		return handle_inbound(irq_ptr->input_qs[q_nr],
 				      callflags, bufnr, count);
@@ -1648,26 +1656,26 @@
 {
 	int rc;
 
-	rc = qdio_setup_init();
+	rc = qdio_debug_init();
 	if (rc)
 		return rc;
+	rc = qdio_setup_init();
+	if (rc)
+		goto out_debug;
 	rc = tiqdio_allocate_memory();
 	if (rc)
 		goto out_cache;
-	rc = qdio_debug_init();
-	if (rc)
-		goto out_ti;
 	rc = tiqdio_register_thinints();
 	if (rc)
-		goto out_debug;
+		goto out_ti;
 	return 0;
 
-out_debug:
-	qdio_debug_exit();
 out_ti:
 	tiqdio_free_memory();
 out_cache:
 	qdio_setup_exit();
+out_debug:
+	qdio_debug_exit();
 	return rc;
 }
 
@@ -1675,8 +1683,8 @@
 {
 	tiqdio_unregister_thinints();
 	tiqdio_free_memory();
-	qdio_debug_exit();
 	qdio_setup_exit();
+	qdio_debug_exit();
 }
 
 module_init(init_QDIO);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/crypto/zcrypt_api.h linux-libre-2.6.39-gnu/drivers/s390/crypto/zcrypt_api.h
--- linux-libre-2.6.38-gnu/drivers/s390/crypto/zcrypt_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/crypto/zcrypt_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -76,7 +76,7 @@
 
 /**
  * Large random numbers are pulled in 4096 byte chunks from the crypto cards
- * and stored in a page. Be carefull when increasing this buffer due to size
+ * and stored in a page. Be careful when increasing this buffer due to size
  * limitations for AP requests.
  */
 #define ZCRYPT_RNG_BUFFER_SIZE	4096
diff -druN linux-libre-2.6.38-gnu/drivers/s390/kvm/kvm_virtio.c linux-libre-2.6.39-gnu/drivers/s390/kvm/kvm_virtio.c
--- linux-libre-2.6.38-gnu/drivers/s390/kvm/kvm_virtio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/kvm/kvm_virtio.c	2011-05-19 00:06:34.000000000 -0400
@@ -381,10 +381,10 @@
 	u16 subcode;
 	u32 param;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
 	subcode = ext_int_code >> 16;
 	if ((subcode & 0xff00) != VIRTIO_SUBCODE_64)
 		return;
+	kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
 
 	/* The LSB might be overloaded, we have to mask it */
 	vq = (struct virtqueue *)(param64 & ~1UL);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/claw.c linux-libre-2.6.39-gnu/drivers/s390/net/claw.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/claw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/claw.c	2011-05-19 00:06:34.000000000 -0400
@@ -264,8 +264,10 @@
 /* ccwgroup table  */
 
 static struct ccwgroup_driver claw_group_driver = {
-        .owner       = THIS_MODULE,
-        .name        = "claw",
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "claw",
+	},
         .max_slaves  = 2,
         .driver_id   = 0xC3D3C1E6,
         .probe       = claw_probe,
@@ -282,8 +284,10 @@
 MODULE_DEVICE_TABLE(ccw, claw_ids);
 
 static struct ccw_driver claw_ccw_driver = {
-	.owner	= THIS_MODULE,
-	.name	= "claw",
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "claw",
+	},
 	.ids	= claw_ids,
 	.probe	= ccwgroup_probe_ccwdev,
 	.remove	= ccwgroup_remove_ccwdev,
@@ -775,7 +779,7 @@
 	case CLAW_START_WRITE:
 		if (p_ch->irb->scsw.cmd.dstat & DEV_STAT_UNIT_CHECK) {
 			dev_info(&cdev->dev,
-				"%s: Unit Check Occured in "
+				"%s: Unit Check Occurred in "
 				"write channel\n", dev->name);
 			clear_bit(0, (void *)&p_ch->IO_active);
 			if (p_ch->irb->ecw[0] & 0x80) {
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/ctcm_fsms.c linux-libre-2.6.39-gnu/drivers/s390/net/ctcm_fsms.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/ctcm_fsms.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/ctcm_fsms.c	2011-05-19 00:06:34.000000000 -0400
@@ -184,7 +184,7 @@
 static void ctcmpc_chx_send_sweep(fsm_instance *fsm, int event, void *arg);
 
 /**
- * Check return code of a preceeding ccw_device call, halt_IO etc...
+ * Check return code of a preceding ccw_device call, halt_IO etc...
  *
  * ch	:	The channel, the error belongs to.
  * Returns the error code (!= 0) to inspect.
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/ctcm_main.c linux-libre-2.6.39-gnu/drivers/s390/net/ctcm_main.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/ctcm_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/ctcm_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -1764,16 +1764,20 @@
 MODULE_DEVICE_TABLE(ccw, ctcm_ids);
 
 static struct ccw_driver ctcm_ccw_driver = {
-	.owner	= THIS_MODULE,
-	.name	= "ctcm",
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "ctcm",
+	},
 	.ids	= ctcm_ids,
 	.probe	= ccwgroup_probe_ccwdev,
 	.remove	= ccwgroup_remove_ccwdev,
 };
 
 static struct ccwgroup_driver ctcm_group_driver = {
-	.owner       = THIS_MODULE,
-	.name        = CTC_DRIVER_NAME,
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= CTC_DRIVER_NAME,
+	},
 	.max_slaves  = 2,
 	.driver_id   = 0xC3E3C3D4,	/* CTCM */
 	.probe       = ctcm_probe_device,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/lcs.c linux-libre-2.6.39-gnu/drivers/s390/net/lcs.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/lcs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/lcs.c	2011-05-19 00:06:34.000000000 -0400
@@ -1123,7 +1123,7 @@
 	list_for_each_entry_safe(ipm, tmp, &card->ipm_list, list){
 		switch (ipm->ipm_state) {
 		case LCS_IPM_STATE_SET_REQUIRED:
-			/* del from ipm_list so noone else can tamper with
+			/* del from ipm_list so no one else can tamper with
 			 * this entry */
 			list_del_init(&ipm->list);
 			spin_unlock_irqrestore(&card->ipm_lock, flags);
@@ -2396,8 +2396,10 @@
 MODULE_DEVICE_TABLE(ccw, lcs_ids);
 
 static struct ccw_driver lcs_ccw_driver = {
-	.owner	= THIS_MODULE,
-	.name	= "lcs",
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "lcs",
+	},
 	.ids	= lcs_ids,
 	.probe	= ccwgroup_probe_ccwdev,
 	.remove	= ccwgroup_remove_ccwdev,
@@ -2407,8 +2409,10 @@
  * LCS ccwgroup driver registration
  */
 static struct ccwgroup_driver lcs_group_driver = {
-	.owner       = THIS_MODULE,
-	.name        = "lcs",
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "lcs",
+	},
 	.max_slaves  = 2,
 	.driver_id   = 0xD3C3E2,
 	.probe       = lcs_probe_device,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/qeth_core.h linux-libre-2.6.39-gnu/drivers/s390/net/qeth_core.h
--- linux-libre-2.6.38-gnu/drivers/s390/net/qeth_core.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/qeth_core.h	2011-05-19 00:06:34.000000000 -0400
@@ -225,7 +225,8 @@
 /*****************************************************************************/
 #define QETH_MAX_QUEUES 4
 #define QETH_IN_BUF_SIZE_DEFAULT 65536
-#define QETH_IN_BUF_COUNT_DEFAULT 16
+#define QETH_IN_BUF_COUNT_DEFAULT 64
+#define QETH_IN_BUF_COUNT_HSDEFAULT 128
 #define QETH_IN_BUF_COUNT_MIN 8
 #define QETH_IN_BUF_COUNT_MAX 128
 #define QETH_MAX_BUFFER_ELEMENTS(card) ((card)->qdio.in_buf_size >> 12)
@@ -741,7 +742,6 @@
 	/* QDIO buffer handling */
 	struct qeth_qdio_info qdio;
 	struct qeth_perf_stats perf_stats;
-	int use_hard_stop;
 	int read_or_write_problem;
 	struct qeth_osn_info osn_info;
 	struct qeth_discipline discipline;
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/qeth_core_main.c linux-libre-2.6.39-gnu/drivers/s390/net/qeth_core_main.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/qeth_core_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/qeth_core_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -302,12 +302,15 @@
 	int com = cmd->hdr.command;
 	ipa_name = qeth_get_ipa_cmd_name(com);
 	if (rc)
-		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s returned x%X \"%s\"\n",
-				ipa_name, com, QETH_CARD_IFNAME(card),
-					rc, qeth_get_ipa_msg(rc));
+		QETH_DBF_MESSAGE(2, "IPA: %s(x%X) for %s/%s returned "
+				"x%X \"%s\"\n",
+				ipa_name, com, dev_name(&card->gdev->dev),
+				QETH_CARD_IFNAME(card), rc,
+				qeth_get_ipa_msg(rc));
 	else
-		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s succeeded\n",
-				ipa_name, com, QETH_CARD_IFNAME(card));
+		QETH_DBF_MESSAGE(5, "IPA: %s(x%X) for %s/%s succeeded\n",
+				ipa_name, com, dev_name(&card->gdev->dev),
+				QETH_CARD_IFNAME(card));
 }
 
 static struct qeth_ipa_cmd *qeth_check_ipa_data(struct qeth_card *card,
@@ -1023,7 +1026,10 @@
 	atomic_set(&card->qdio.state, QETH_QDIO_UNINITIALIZED);
 	/* inbound */
 	card->qdio.in_buf_size = QETH_IN_BUF_SIZE_DEFAULT;
-	card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
+	if (card->info.type == QETH_CARD_TYPE_IQD)
+		card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_HSDEFAULT;
+	else
+		card->qdio.init_pool.buf_count = QETH_IN_BUF_COUNT_DEFAULT;
 	card->qdio.in_buf_pool.buf_count = card->qdio.init_pool.buf_count;
 	INIT_LIST_HEAD(&card->qdio.in_buf_pool.entry_list);
 	INIT_LIST_HEAD(&card->qdio.init_pool.entry_list);
@@ -1083,7 +1089,6 @@
 	card->data.state  = CH_STATE_DOWN;
 	card->state = CARD_STATE_DOWN;
 	card->lan_online = 0;
-	card->use_hard_stop = 0;
 	card->read_or_write_problem = 0;
 	card->dev = NULL;
 	spin_lock_init(&card->vlanlock);
@@ -1102,7 +1107,7 @@
 	INIT_LIST_HEAD(card->ip_tbd_list);
 	INIT_LIST_HEAD(&card->cmd_waiter_list);
 	init_waitqueue_head(&card->wait_q);
-	/* intial options */
+	/* initial options */
 	qeth_set_intial_options(card);
 	/* IP address takeover */
 	INIT_LIST_HEAD(&card->ipato.entries);
@@ -1732,20 +1737,22 @@
 		};
 	}
 
+	if (reply->rc == -EIO)
+		goto error;
 	rc = reply->rc;
 	qeth_put_reply(reply);
 	return rc;
 
 time_err:
+	reply->rc = -ETIME;
 	spin_lock_irqsave(&reply->card->lock, flags);
 	list_del_init(&reply->list);
 	spin_unlock_irqrestore(&reply->card->lock, flags);
-	reply->rc = -ETIME;
 	atomic_inc(&reply->received);
+error:
 	atomic_set(&card->write.irq_pending, 0);
 	qeth_release_buffer(iob->channel, iob);
 	card->write.buf_no = (card->write.buf_no + 1) % QETH_CMD_BUFFER_NO;
-	wake_up(&reply->wait_q);
 	rc = reply->rc;
 	qeth_put_reply(reply);
 	return rc;
@@ -2490,45 +2497,19 @@
 }
 EXPORT_SYMBOL_GPL(qeth_send_ipa_cmd);
 
-static int qeth_send_startstoplan(struct qeth_card *card,
-		enum qeth_ipa_cmds ipacmd, enum qeth_prot_versions prot)
-{
-	int rc;
-	struct qeth_cmd_buffer *iob;
-
-	iob = qeth_get_ipacmd_buffer(card, ipacmd, prot);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-
-	return rc;
-}
-
 int qeth_send_startlan(struct qeth_card *card)
 {
 	int rc;
+	struct qeth_cmd_buffer *iob;
 
 	QETH_DBF_TEXT(SETUP, 2, "strtlan");
 
-	rc = qeth_send_startstoplan(card, IPA_CMD_STARTLAN, 0);
+	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_STARTLAN, 0);
+	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
 	return rc;
 }
 EXPORT_SYMBOL_GPL(qeth_send_startlan);
 
-int qeth_send_stoplan(struct qeth_card *card)
-{
-	int rc = 0;
-
-	/*
-	 * TODO: according to the IPA format document page 14,
-	 * TCP/IP (we!) never issue a STOPLAN
-	 * is this right ?!?
-	 */
-	QETH_DBF_TEXT(SETUP, 2, "stoplan");
-
-	rc = qeth_send_startstoplan(card, IPA_CMD_STOPLAN, 0);
-	return rc;
-}
-EXPORT_SYMBOL_GPL(qeth_send_stoplan);
-
 int qeth_default_setadapterparms_cb(struct qeth_card *card,
 		struct qeth_reply *reply, unsigned long data)
 {
@@ -3921,7 +3902,9 @@
 MODULE_DEVICE_TABLE(ccw, qeth_ids);
 
 static struct ccw_driver qeth_ccw_driver = {
-	.name = "qeth",
+	.driver = {
+		.name = "qeth",
+	},
 	.ids = qeth_ids,
 	.probe = ccwgroup_probe_ccwdev,
 	.remove = ccwgroup_remove_ccwdev,
@@ -4447,8 +4430,10 @@
 }
 
 static struct ccwgroup_driver qeth_core_ccwgroup_driver = {
-	.owner = THIS_MODULE,
-	.name = "qeth",
+	.driver = {
+		.owner = THIS_MODULE,
+		.name = "qeth",
+	},
 	.driver_id = 0xD8C5E3C8,
 	.probe = qeth_core_probe_device,
 	.remove = qeth_core_remove_device,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/qeth_l2_main.c linux-libre-2.6.39-gnu/drivers/s390/net/qeth_l2_main.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/qeth_l2_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/qeth_l2_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -202,17 +202,19 @@
 		kfree(mc);
 }
 
-static void qeth_l2_del_all_mc(struct qeth_card *card)
+static void qeth_l2_del_all_mc(struct qeth_card *card, int del)
 {
 	struct qeth_mc_mac *mc, *tmp;
 
 	spin_lock_bh(&card->mclock);
 	list_for_each_entry_safe(mc, tmp, &card->mc_list, list) {
-		if (mc->is_vmac)
-			qeth_l2_send_setdelmac(card, mc->mc_addr,
+		if (del) {
+			if (mc->is_vmac)
+				qeth_l2_send_setdelmac(card, mc->mc_addr,
 					IPA_CMD_DELVMAC, NULL);
-		else
-			qeth_l2_send_delgroupmac(card, mc->mc_addr);
+			else
+				qeth_l2_send_delgroupmac(card, mc->mc_addr);
+		}
 		list_del(&mc->list);
 		kfree(mc);
 	}
@@ -288,18 +290,13 @@
 				 qeth_l2_send_setdelvlan_cb, NULL);
 }
 
-static void qeth_l2_process_vlans(struct qeth_card *card, int clear)
+static void qeth_l2_process_vlans(struct qeth_card *card)
 {
 	struct qeth_vlan_vid *id;
 	QETH_CARD_TEXT(card, 3, "L2prcvln");
 	spin_lock_bh(&card->vlanlock);
 	list_for_each_entry(id, &card->vid_list, list) {
-		if (clear)
-			qeth_l2_send_setdelvlan(card, id->vid,
-				IPA_CMD_DELVLAN);
-		else
-			qeth_l2_send_setdelvlan(card, id->vid,
-				IPA_CMD_SETVLAN);
+		qeth_l2_send_setdelvlan(card, id->vid, IPA_CMD_SETVLAN);
 	}
 	spin_unlock_bh(&card->vlanlock);
 }
@@ -379,19 +376,11 @@
 			dev_close(card->dev);
 			rtnl_unlock();
 		}
-		if (!card->use_hard_stop ||
-			recovery_mode) {
-			__u8 *mac = &card->dev->dev_addr[0];
-			rc = qeth_l2_send_delmac(card, mac);
-			QETH_DBF_TEXT_(SETUP, 2, "Lerr%d", rc);
-		}
+		card->info.mac_bits &= ~QETH_LAYER2_MAC_REGISTERED;
 		card->state = CARD_STATE_SOFTSETUP;
 	}
 	if (card->state == CARD_STATE_SOFTSETUP) {
-		qeth_l2_process_vlans(card, 1);
-		if (!card->use_hard_stop ||
-			recovery_mode)
-			qeth_l2_del_all_mc(card);
+		qeth_l2_del_all_mc(card, 0);
 		qeth_clear_ipacmd_list(card);
 		card->state = CARD_STATE_HARDSETUP;
 	}
@@ -405,7 +394,6 @@
 		qeth_clear_cmd_buffers(&card->read);
 		qeth_clear_cmd_buffers(&card->write);
 	}
-	card->use_hard_stop = 0;
 	return rc;
 }
 
@@ -705,7 +693,7 @@
 	if (qeth_threads_running(card, QETH_RECOVER_THREAD) &&
 	    (card->state != CARD_STATE_UP))
 		return;
-	qeth_l2_del_all_mc(card);
+	qeth_l2_del_all_mc(card, 1);
 	spin_lock_bh(&card->mclock);
 	netdev_for_each_mc_addr(ha, dev)
 		qeth_l2_add_mc(card, ha->addr, 0);
@@ -907,10 +895,8 @@
 	qeth_set_allowed_threads(card, 0, 1);
 	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
-	if (cgdev->state == CCWGROUP_ONLINE) {
-		card->use_hard_stop = 1;
+	if (cgdev->state == CCWGROUP_ONLINE)
 		qeth_l2_set_offline(cgdev);
-	}
 
 	if (card->dev) {
 		unregister_netdev(card->dev);
@@ -1040,7 +1026,7 @@
 
 	if (card->info.type != QETH_CARD_TYPE_OSN &&
 	    card->info.type != QETH_CARD_TYPE_OSM)
-		qeth_l2_process_vlans(card, 0);
+		qeth_l2_process_vlans(card);
 
 	netif_tx_disable(card->dev);
 
@@ -1076,7 +1062,6 @@
 	return 0;
 
 out_remove:
-	card->use_hard_stop = 1;
 	qeth_l2_stop_card(card, 0);
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
@@ -1144,7 +1129,6 @@
 	QETH_CARD_TEXT(card, 2, "recover2");
 	dev_warn(&card->gdev->dev,
 		"A recovery process has been started for the device\n");
-	card->use_hard_stop = 1;
 	__qeth_l2_set_offline(card->gdev, 1);
 	rc = __qeth_l2_set_online(card->gdev, 1);
 	if (!rc)
@@ -1191,7 +1175,6 @@
 	if (gdev->state == CCWGROUP_OFFLINE)
 		return 0;
 	if (card->state == CARD_STATE_UP) {
-		card->use_hard_stop = 1;
 		__qeth_l2_set_offline(card->gdev, 1);
 	} else
 		__qeth_l2_set_offline(card->gdev, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/net/qeth_l3_main.c linux-libre-2.6.39-gnu/drivers/s390/net/qeth_l3_main.c
--- linux-libre-2.6.38-gnu/drivers/s390/net/qeth_l3_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/net/qeth_l3_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -510,8 +510,7 @@
 	kfree(tbd_list);
 }
 
-static void qeth_l3_clear_ip_list(struct qeth_card *card, int clean,
-					int recover)
+static void qeth_l3_clear_ip_list(struct qeth_card *card, int recover)
 {
 	struct qeth_ipaddr *addr, *tmp;
 	unsigned long flags;
@@ -530,11 +529,6 @@
 		addr = list_entry(card->ip_list.next,
 				  struct qeth_ipaddr, entry);
 		list_del_init(&addr->entry);
-		if (clean) {
-			spin_unlock_irqrestore(&card->ip_lock, flags);
-			qeth_l3_deregister_addr_entry(card, addr);
-			spin_lock_irqsave(&card->ip_lock, flags);
-		}
 		if (!recover || addr->is_multicast) {
 			kfree(addr);
 			continue;
@@ -1611,29 +1605,6 @@
 	return 0;
 }
 
-static int qeth_l3_put_unique_id(struct qeth_card *card)
-{
-
-	int rc = 0;
-	struct qeth_cmd_buffer *iob;
-	struct qeth_ipa_cmd *cmd;
-
-	QETH_CARD_TEXT(card, 2, "puniqeid");
-
-	if ((card->info.unique_id & UNIQUE_ID_NOT_BY_CARD) ==
-		UNIQUE_ID_NOT_BY_CARD)
-		return -1;
-	iob = qeth_get_ipacmd_buffer(card, IPA_CMD_DESTROY_ADDR,
-				     QETH_PROT_IPV6);
-	cmd = (struct qeth_ipa_cmd *)(iob->data+IPA_PDU_HEADER_SIZE);
-	*((__u16 *) &cmd->data.create_destroy_addr.unique_id[6]) =
-				card->info.unique_id;
-	memcpy(&cmd->data.create_destroy_addr.unique_id[0],
-	       card->dev->dev_addr, OSA_ADDR_LEN);
-	rc = qeth_send_ipa_cmd(card, iob, NULL, NULL);
-	return rc;
-}
-
 static int qeth_l3_iqd_read_initial_mac_cb(struct qeth_card *card,
 		struct qeth_reply *reply, unsigned long data)
 {
@@ -2324,25 +2295,14 @@
 			dev_close(card->dev);
 			rtnl_unlock();
 		}
-		if (!card->use_hard_stop) {
-			rc = qeth_send_stoplan(card);
-			if (rc)
-				QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
-		}
 		card->state = CARD_STATE_SOFTSETUP;
 	}
 	if (card->state == CARD_STATE_SOFTSETUP) {
-		qeth_l3_clear_ip_list(card, !card->use_hard_stop, 1);
+		qeth_l3_clear_ip_list(card, 1);
 		qeth_clear_ipacmd_list(card);
 		card->state = CARD_STATE_HARDSETUP;
 	}
 	if (card->state == CARD_STATE_HARDSETUP) {
-		if (!card->use_hard_stop &&
-		    (card->info.type != QETH_CARD_TYPE_IQD)) {
-			rc = qeth_l3_put_unique_id(card);
-			if (rc)
-				QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
-		}
 		qeth_qdio_clear_card(card, 0);
 		qeth_clear_qdio_buffers(card);
 		qeth_clear_working_pool_list(card);
@@ -2352,7 +2312,6 @@
 		qeth_clear_cmd_buffers(&card->read);
 		qeth_clear_cmd_buffers(&card->write);
 	}
-	card->use_hard_stop = 0;
 	return rc;
 }
 
@@ -3433,6 +3392,8 @@
 			if (!(card->info.unique_id & UNIQUE_ID_NOT_BY_CARD))
 				card->dev->dev_id = card->info.unique_id &
 							 0xffff;
+			if (!card->info.guestlan)
+				card->dev->features |= NETIF_F_GRO;
 		}
 	} else if (card->info.type == QETH_CARD_TYPE_IQD) {
 		card->dev = alloc_netdev(0, "hsi%d", ether_setup);
@@ -3471,6 +3432,9 @@
 	card->discipline.output_handler = (qdio_handler_t *)
 		qeth_qdio_output_handler;
 	card->discipline.recover = qeth_l3_recover;
+	if ((card->info.type == QETH_CARD_TYPE_OSD) ||
+	    (card->info.type == QETH_CARD_TYPE_OSX))
+		card->options.checksum_type = HW_CHECKSUMMING;
 	return 0;
 }
 
@@ -3483,17 +3447,15 @@
 	qeth_set_allowed_threads(card, 0, 1);
 	wait_event(card->wait_q, qeth_threads_running(card, 0xffffffff) == 0);
 
-	if (cgdev->state == CCWGROUP_ONLINE) {
-		card->use_hard_stop = 1;
+	if (cgdev->state == CCWGROUP_ONLINE)
 		qeth_l3_set_offline(cgdev);
-	}
 
 	if (card->dev) {
 		unregister_netdev(card->dev);
 		card->dev = NULL;
 	}
 
-	qeth_l3_clear_ip_list(card, 0, 0);
+	qeth_l3_clear_ip_list(card, 0);
 	qeth_l3_clear_ipato_list(card);
 	return;
 }
@@ -3594,7 +3556,6 @@
 	mutex_unlock(&card->discipline_mutex);
 	return 0;
 out_remove:
-	card->use_hard_stop = 1;
 	qeth_l3_stop_card(card, 0);
 	ccw_device_set_offline(CARD_DDEV(card));
 	ccw_device_set_offline(CARD_WDEV(card));
@@ -3663,7 +3624,6 @@
 	QETH_CARD_TEXT(card, 2, "recover2");
 	dev_warn(&card->gdev->dev,
 		"A recovery process has been started for the device\n");
-	card->use_hard_stop = 1;
 	__qeth_l3_set_offline(card->gdev, 1);
 	rc = __qeth_l3_set_online(card->gdev, 1);
 	if (!rc)
@@ -3684,7 +3644,6 @@
 static void qeth_l3_shutdown(struct ccwgroup_device *gdev)
 {
 	struct qeth_card *card = dev_get_drvdata(&gdev->dev);
-	qeth_l3_clear_ip_list(card, 0, 0);
 	qeth_qdio_clear_card(card, 0);
 	qeth_clear_qdio_buffers(card);
 }
@@ -3700,7 +3659,6 @@
 	if (gdev->state == CCWGROUP_OFFLINE)
 		return 0;
 	if (card->state == CARD_STATE_UP) {
-		card->use_hard_stop = 1;
 		__qeth_l3_set_offline(card->gdev, 1);
 	} else
 		__qeth_l3_set_offline(card->gdev, 0);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_aux.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_aux.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_aux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_aux.c	2011-05-19 00:06:34.000000000 -0400
@@ -122,36 +122,21 @@
 {
 	int retval = -ENOMEM;
 
-	zfcp_data.gpn_ft_cache = zfcp_cache_hw_align("zfcp_gpn",
-					sizeof(struct zfcp_fc_gpn_ft_req));
-	if (!zfcp_data.gpn_ft_cache)
-		goto out;
-
-	zfcp_data.qtcb_cache = zfcp_cache_hw_align("zfcp_qtcb",
-					sizeof(struct fsf_qtcb));
-	if (!zfcp_data.qtcb_cache)
+	zfcp_fsf_qtcb_cache = zfcp_cache_hw_align("zfcp_fsf_qtcb",
+						  sizeof(struct fsf_qtcb));
+	if (!zfcp_fsf_qtcb_cache)
 		goto out_qtcb_cache;
 
-	zfcp_data.sr_buffer_cache = zfcp_cache_hw_align("zfcp_sr",
-					sizeof(struct fsf_status_read_buffer));
-	if (!zfcp_data.sr_buffer_cache)
-		goto out_sr_cache;
-
-	zfcp_data.gid_pn_cache = zfcp_cache_hw_align("zfcp_gid",
-					sizeof(struct zfcp_fc_gid_pn));
-	if (!zfcp_data.gid_pn_cache)
-		goto out_gid_cache;
-
-	zfcp_data.adisc_cache = zfcp_cache_hw_align("zfcp_adisc",
-					sizeof(struct zfcp_fc_els_adisc));
-	if (!zfcp_data.adisc_cache)
-		goto out_adisc_cache;
+	zfcp_fc_req_cache = zfcp_cache_hw_align("zfcp_fc_req",
+						sizeof(struct zfcp_fc_req));
+	if (!zfcp_fc_req_cache)
+		goto out_fc_cache;
 
-	zfcp_data.scsi_transport_template =
+	zfcp_scsi_transport_template =
 		fc_attach_transport(&zfcp_transport_functions);
-	if (!zfcp_data.scsi_transport_template)
+	if (!zfcp_scsi_transport_template)
 		goto out_transport;
-	scsi_transport_reserve_device(zfcp_data.scsi_transport_template,
+	scsi_transport_reserve_device(zfcp_scsi_transport_template,
 				      sizeof(struct zfcp_scsi_dev));
 
 
@@ -175,18 +160,12 @@
 out_ccw_register:
 	misc_deregister(&zfcp_cfdc_misc);
 out_misc:
-	fc_release_transport(zfcp_data.scsi_transport_template);
+	fc_release_transport(zfcp_scsi_transport_template);
 out_transport:
-	kmem_cache_destroy(zfcp_data.adisc_cache);
-out_adisc_cache:
-	kmem_cache_destroy(zfcp_data.gid_pn_cache);
-out_gid_cache:
-	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
-out_sr_cache:
-	kmem_cache_destroy(zfcp_data.qtcb_cache);
+	kmem_cache_destroy(zfcp_fc_req_cache);
+out_fc_cache:
+	kmem_cache_destroy(zfcp_fsf_qtcb_cache);
 out_qtcb_cache:
-	kmem_cache_destroy(zfcp_data.gpn_ft_cache);
-out:
 	return retval;
 }
 
@@ -196,12 +175,9 @@
 {
 	ccw_driver_unregister(&zfcp_ccw_driver);
 	misc_deregister(&zfcp_cfdc_misc);
-	fc_release_transport(zfcp_data.scsi_transport_template);
-	kmem_cache_destroy(zfcp_data.adisc_cache);
-	kmem_cache_destroy(zfcp_data.gid_pn_cache);
-	kmem_cache_destroy(zfcp_data.sr_buffer_cache);
-	kmem_cache_destroy(zfcp_data.qtcb_cache);
-	kmem_cache_destroy(zfcp_data.gpn_ft_cache);
+	fc_release_transport(zfcp_scsi_transport_template);
+	kmem_cache_destroy(zfcp_fc_req_cache);
+	kmem_cache_destroy(zfcp_fsf_qtcb_cache);
 }
 
 module_exit(zfcp_module_exit);
@@ -260,18 +236,18 @@
 		return -ENOMEM;
 
 	adapter->pool.qtcb_pool =
-		mempool_create_slab_pool(4, zfcp_data.qtcb_cache);
+		mempool_create_slab_pool(4, zfcp_fsf_qtcb_cache);
 	if (!adapter->pool.qtcb_pool)
 		return -ENOMEM;
 
-	adapter->pool.status_read_data =
-		mempool_create_slab_pool(FSF_STATUS_READS_RECOM,
-					 zfcp_data.sr_buffer_cache);
-	if (!adapter->pool.status_read_data)
+	BUILD_BUG_ON(sizeof(struct fsf_status_read_buffer) > PAGE_SIZE);
+	adapter->pool.sr_data =
+		mempool_create_page_pool(FSF_STATUS_READS_RECOM, 0);
+	if (!adapter->pool.sr_data)
 		return -ENOMEM;
 
 	adapter->pool.gid_pn =
-		mempool_create_slab_pool(1, zfcp_data.gid_pn_cache);
+		mempool_create_slab_pool(1, zfcp_fc_req_cache);
 	if (!adapter->pool.gid_pn)
 		return -ENOMEM;
 
@@ -290,8 +266,8 @@
 		mempool_destroy(adapter->pool.qtcb_pool);
 	if (adapter->pool.status_read_req)
 		mempool_destroy(adapter->pool.status_read_req);
-	if (adapter->pool.status_read_data)
-		mempool_destroy(adapter->pool.status_read_data);
+	if (adapter->pool.sr_data)
+		mempool_destroy(adapter->pool.sr_data);
 	if (adapter->pool.gid_pn)
 		mempool_destroy(adapter->pool.gid_pn);
 }
@@ -386,6 +362,7 @@
 
 	INIT_WORK(&adapter->stat_work, _zfcp_status_read_scheduler);
 	INIT_WORK(&adapter->scan_work, zfcp_fc_scan_ports);
+	INIT_WORK(&adapter->ns_up_work, zfcp_fc_sym_name_update);
 
 	if (zfcp_qdio_setup(adapter))
 		goto failed;
@@ -437,7 +414,7 @@
 	adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
 	adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
-	if (!zfcp_adapter_scsi_register(adapter))
+	if (!zfcp_scsi_adapter_register(adapter))
 		return adapter;
 
 failed:
@@ -451,10 +428,11 @@
 
 	cancel_work_sync(&adapter->scan_work);
 	cancel_work_sync(&adapter->stat_work);
+	cancel_work_sync(&adapter->ns_up_work);
 	zfcp_destroy_adapter_work_queue(adapter);
 
 	zfcp_fc_wka_ports_force_offline(adapter->gs);
-	zfcp_adapter_scsi_unregister(adapter);
+	zfcp_scsi_adapter_unregister(adapter);
 	sysfs_remove_group(&cdev->dev.kobj, &zfcp_sysfs_adapter_attrs);
 
 	zfcp_erp_thread_kill(adapter);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_ccw.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_ccw.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_ccw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_ccw.c	2011-05-19 00:06:34.000000000 -0400
@@ -251,8 +251,10 @@
 }
 
 struct ccw_driver zfcp_ccw_driver = {
-	.owner       = THIS_MODULE,
-	.name        = "zfcp",
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= "zfcp",
+	},
 	.ids         = zfcp_ccw_device_id,
 	.probe       = zfcp_ccw_probe,
 	.remove      = zfcp_ccw_remove,
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_def.h linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_def.h
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -89,7 +89,6 @@
 #define ZFCP_STATUS_LUN_READONLY		0x00000008
 
 /* FSF request status (this does not have a common part) */
-#define ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT	0x00000002
 #define ZFCP_STATUS_FSFREQ_ERROR		0x00000008
 #define ZFCP_STATUS_FSFREQ_CLEANUP		0x00000010
 #define ZFCP_STATUS_FSFREQ_ABORTSUCCEEDED	0x00000040
@@ -108,7 +107,7 @@
 	mempool_t *scsi_req;
 	mempool_t *scsi_abort;
 	mempool_t *status_read_req;
-	mempool_t *status_read_data;
+	mempool_t *sr_data;
 	mempool_t *gid_pn;
 	mempool_t *qtcb_pool;
 };
@@ -190,6 +189,7 @@
 	struct fsf_qtcb_bottom_port *stats_reset_data;
 	unsigned long		stats_reset;
 	struct work_struct	scan_work;
+	struct work_struct	ns_up_work;
 	struct service_level	service_level;
 	struct workqueue_struct	*work_queue;
 	struct device_dma_parameters dma_parms;
@@ -314,15 +314,4 @@
 	void			(*handler)(struct zfcp_fsf_req *);
 };
 
-/* driver data */
-struct zfcp_data {
-	struct scsi_host_template scsi_host_template;
-	struct scsi_transport_template *scsi_transport_template;
-	struct kmem_cache	*gpn_ft_cache;
-	struct kmem_cache	*qtcb_cache;
-	struct kmem_cache	*sr_buffer_cache;
-	struct kmem_cache	*gid_pn_cache;
-	struct kmem_cache	*adisc_cache;
-};
-
 #endif /* ZFCP_DEF_H */
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_erp.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_erp.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_erp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_erp.c	2011-05-19 00:06:34.000000000 -0400
@@ -732,7 +732,7 @@
 	if (zfcp_erp_adapter_strategy_open_fsf_xport(act) == ZFCP_ERP_FAILED)
 		return ZFCP_ERP_FAILED;
 
-	if (mempool_resize(act->adapter->pool.status_read_data,
+	if (mempool_resize(act->adapter->pool.sr_data,
 			   act->adapter->stat_read_buf_num, GFP_KERNEL))
 		return ZFCP_ERP_FAILED;
 
@@ -1231,8 +1231,10 @@
 		if (result == ZFCP_ERP_SUCCEEDED) {
 			register_service_level(&adapter->service_level);
 			queue_work(adapter->work_queue, &adapter->scan_work);
+			queue_work(adapter->work_queue, &adapter->ns_up_work);
 		} else
 			unregister_service_level(&adapter->service_level);
+
 		kref_put(&adapter->ref, zfcp_adapter_release);
 		break;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_ext.h linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_ext.h
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_ext.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_ext.h	2011-05-19 00:06:34.000000000 -0400
@@ -80,6 +80,7 @@
 extern void zfcp_erp_timeout_handler(unsigned long);
 
 /* zfcp_fc.c */
+extern struct kmem_cache *zfcp_fc_req_cache;
 extern void zfcp_fc_enqueue_event(struct zfcp_adapter *,
 				enum fc_host_event_code event_code, u32);
 extern void zfcp_fc_post_event(struct work_struct *);
@@ -95,8 +96,10 @@
 extern void zfcp_fc_gs_destroy(struct zfcp_adapter *);
 extern int zfcp_fc_exec_bsg_job(struct fc_bsg_job *);
 extern int zfcp_fc_timeout_bsg_job(struct fc_bsg_job *);
+extern void zfcp_fc_sym_name_update(struct work_struct *);
 
 /* zfcp_fsf.c */
+extern struct kmem_cache *zfcp_fsf_qtcb_cache;
 extern int zfcp_fsf_open_port(struct zfcp_erp_action *);
 extern int zfcp_fsf_open_wka_port(struct zfcp_fc_wka_port *);
 extern int zfcp_fsf_close_wka_port(struct zfcp_fc_wka_port *);
@@ -139,9 +142,9 @@
 					     struct qdio_buffer *);
 
 /* zfcp_scsi.c */
-extern struct zfcp_data zfcp_data;
-extern int zfcp_adapter_scsi_register(struct zfcp_adapter *);
-extern void zfcp_adapter_scsi_unregister(struct zfcp_adapter *);
+extern struct scsi_transport_template *zfcp_scsi_transport_template;
+extern int zfcp_scsi_adapter_register(struct zfcp_adapter *);
+extern void zfcp_scsi_adapter_unregister(struct zfcp_adapter *);
 extern struct fc_function_template zfcp_transport_functions;
 extern void zfcp_scsi_rport_work(struct work_struct *);
 extern void zfcp_scsi_schedule_rport_register(struct zfcp_port *);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_fc.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_fc.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_fc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_fc.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,11 +11,14 @@
 
 #include <linux/types.h>
 #include <linux/slab.h>
+#include <linux/utsname.h>
 #include <scsi/fc/fc_els.h>
 #include <scsi/libfc.h>
 #include "zfcp_ext.h"
 #include "zfcp_fc.h"
 
+struct kmem_cache *zfcp_fc_req_cache;
+
 static u32 zfcp_fc_rscn_range_mask[] = {
 	[ELS_ADDR_FMT_PORT]		= 0xFFFFFF,
 	[ELS_ADDR_FMT_AREA]		= 0xFFFF00,
@@ -260,24 +263,18 @@
 		zfcp_fc_incoming_rscn(fsf_req);
 }
 
-static void zfcp_fc_ns_gid_pn_eval(void *data)
+static void zfcp_fc_ns_gid_pn_eval(struct zfcp_fc_req *fc_req)
 {
-	struct zfcp_fc_gid_pn *gid_pn = data;
-	struct zfcp_fsf_ct_els *ct = &gid_pn->ct;
-	struct zfcp_fc_gid_pn_req *gid_pn_req = sg_virt(ct->req);
-	struct zfcp_fc_gid_pn_resp *gid_pn_resp = sg_virt(ct->resp);
-	struct zfcp_port *port = gid_pn->port;
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp;
 
-	if (ct->status)
+	if (ct_els->status)
 		return;
-	if (gid_pn_resp->ct_hdr.ct_cmd != FC_FS_ACC)
+	if (gid_pn_rsp->ct_hdr.ct_cmd != FC_FS_ACC)
 		return;
 
-	/* paranoia */
-	if (gid_pn_req->gid_pn.fn_wwpn != port->wwpn)
-		return;
 	/* looks like a valid d_id */
-	port->d_id = ntoh24(gid_pn_resp->gid_pn.fp_fid);
+	ct_els->port->d_id = ntoh24(gid_pn_rsp->gid_pn.fp_fid);
 }
 
 static void zfcp_fc_complete(void *data)
@@ -285,69 +282,73 @@
 	complete(data);
 }
 
+static void zfcp_fc_ct_ns_init(struct fc_ct_hdr *ct_hdr, u16 cmd, u16 mr_size)
+{
+	ct_hdr->ct_rev = FC_CT_REV;
+	ct_hdr->ct_fs_type = FC_FST_DIR;
+	ct_hdr->ct_fs_subtype = FC_NS_SUBTYPE;
+	ct_hdr->ct_cmd = cmd;
+	ct_hdr->ct_mr_size = mr_size / 4;
+}
+
 static int zfcp_fc_ns_gid_pn_request(struct zfcp_port *port,
-				     struct zfcp_fc_gid_pn *gid_pn)
+				     struct zfcp_fc_req *fc_req)
 {
 	struct zfcp_adapter *adapter = port->adapter;
 	DECLARE_COMPLETION_ONSTACK(completion);
+	struct zfcp_fc_gid_pn_req *gid_pn_req = &fc_req->u.gid_pn.req;
+	struct zfcp_fc_gid_pn_rsp *gid_pn_rsp = &fc_req->u.gid_pn.rsp;
 	int ret;
 
 	/* setup parameters for send generic command */
-	gid_pn->port = port;
-	gid_pn->ct.handler = zfcp_fc_complete;
-	gid_pn->ct.handler_data = &completion;
-	gid_pn->ct.req = &gid_pn->sg_req;
-	gid_pn->ct.resp = &gid_pn->sg_resp;
-	sg_init_one(&gid_pn->sg_req, &gid_pn->gid_pn_req,
-		    sizeof(struct zfcp_fc_gid_pn_req));
-	sg_init_one(&gid_pn->sg_resp, &gid_pn->gid_pn_resp,
-		    sizeof(struct zfcp_fc_gid_pn_resp));
+	fc_req->ct_els.port = port;
+	fc_req->ct_els.handler = zfcp_fc_complete;
+	fc_req->ct_els.handler_data = &completion;
+	fc_req->ct_els.req = &fc_req->sg_req;
+	fc_req->ct_els.resp = &fc_req->sg_rsp;
+	sg_init_one(&fc_req->sg_req, gid_pn_req, sizeof(*gid_pn_req));
+	sg_init_one(&fc_req->sg_rsp, gid_pn_rsp, sizeof(*gid_pn_rsp));
 
-	/* setup nameserver request */
-	gid_pn->gid_pn_req.ct_hdr.ct_rev = FC_CT_REV;
-	gid_pn->gid_pn_req.ct_hdr.ct_fs_type = FC_FST_DIR;
-	gid_pn->gid_pn_req.ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE;
-	gid_pn->gid_pn_req.ct_hdr.ct_options = 0;
-	gid_pn->gid_pn_req.ct_hdr.ct_cmd = FC_NS_GID_PN;
-	gid_pn->gid_pn_req.ct_hdr.ct_mr_size = ZFCP_FC_CT_SIZE_PAGE / 4;
-	gid_pn->gid_pn_req.gid_pn.fn_wwpn = port->wwpn;
+	zfcp_fc_ct_ns_init(&gid_pn_req->ct_hdr,
+			   FC_NS_GID_PN, ZFCP_FC_CT_SIZE_PAGE);
+	gid_pn_req->gid_pn.fn_wwpn = port->wwpn;
 
-	ret = zfcp_fsf_send_ct(&adapter->gs->ds, &gid_pn->ct,
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, &fc_req->ct_els,
 			       adapter->pool.gid_pn_req,
 			       ZFCP_FC_CTELS_TMO);
 	if (!ret) {
 		wait_for_completion(&completion);
-		zfcp_fc_ns_gid_pn_eval(gid_pn);
+		zfcp_fc_ns_gid_pn_eval(fc_req);
 	}
 	return ret;
 }
 
 /**
- * zfcp_fc_ns_gid_pn_request - initiate GID_PN nameserver request
+ * zfcp_fc_ns_gid_pn - initiate GID_PN nameserver request
  * @port: port where GID_PN request is needed
  * return: -ENOMEM on error, 0 otherwise
  */
 static int zfcp_fc_ns_gid_pn(struct zfcp_port *port)
 {
 	int ret;
-	struct zfcp_fc_gid_pn *gid_pn;
+	struct zfcp_fc_req *fc_req;
 	struct zfcp_adapter *adapter = port->adapter;
 
-	gid_pn = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC);
-	if (!gid_pn)
+	fc_req = mempool_alloc(adapter->pool.gid_pn, GFP_ATOMIC);
+	if (!fc_req)
 		return -ENOMEM;
 
-	memset(gid_pn, 0, sizeof(*gid_pn));
+	memset(fc_req, 0, sizeof(*fc_req));
 
 	ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
 	if (ret)
 		goto out;
 
-	ret = zfcp_fc_ns_gid_pn_request(port, gid_pn);
+	ret = zfcp_fc_ns_gid_pn_request(port, fc_req);
 
 	zfcp_fc_wka_port_put(&adapter->gs->ds);
 out:
-	mempool_free(gid_pn, adapter->pool.gid_pn);
+	mempool_free(fc_req, adapter->pool.gid_pn);
 	return ret;
 }
 
@@ -419,11 +420,11 @@
 
 static void zfcp_fc_adisc_handler(void *data)
 {
-	struct zfcp_fc_els_adisc *adisc = data;
-	struct zfcp_port *port = adisc->els.port;
-	struct fc_els_adisc *adisc_resp = &adisc->adisc_resp;
+	struct zfcp_fc_req *fc_req = data;
+	struct zfcp_port *port = fc_req->ct_els.port;
+	struct fc_els_adisc *adisc_resp = &fc_req->u.adisc.rsp;
 
-	if (adisc->els.status) {
+	if (fc_req->ct_els.status) {
 		/* request rejected or timed out */
 		zfcp_erp_port_forced_reopen(port, ZFCP_STATUS_COMMON_ERP_FAILED,
 					    "fcadh_1");
@@ -445,42 +446,42 @@
  out:
 	atomic_clear_mask(ZFCP_STATUS_PORT_LINK_TEST, &port->status);
 	put_device(&port->dev);
-	kmem_cache_free(zfcp_data.adisc_cache, adisc);
+	kmem_cache_free(zfcp_fc_req_cache, fc_req);
 }
 
 static int zfcp_fc_adisc(struct zfcp_port *port)
 {
-	struct zfcp_fc_els_adisc *adisc;
+	struct zfcp_fc_req *fc_req;
 	struct zfcp_adapter *adapter = port->adapter;
+	struct Scsi_Host *shost = adapter->scsi_host;
 	int ret;
 
-	adisc = kmem_cache_zalloc(zfcp_data.adisc_cache, GFP_ATOMIC);
-	if (!adisc)
+	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_ATOMIC);
+	if (!fc_req)
 		return -ENOMEM;
 
-	adisc->els.port = port;
-	adisc->els.req = &adisc->req;
-	adisc->els.resp = &adisc->resp;
-	sg_init_one(adisc->els.req, &adisc->adisc_req,
+	fc_req->ct_els.port = port;
+	fc_req->ct_els.req = &fc_req->sg_req;
+	fc_req->ct_els.resp = &fc_req->sg_rsp;
+	sg_init_one(&fc_req->sg_req, &fc_req->u.adisc.req,
 		    sizeof(struct fc_els_adisc));
-	sg_init_one(adisc->els.resp, &adisc->adisc_resp,
+	sg_init_one(&fc_req->sg_rsp, &fc_req->u.adisc.rsp,
 		    sizeof(struct fc_els_adisc));
 
-	adisc->els.handler = zfcp_fc_adisc_handler;
-	adisc->els.handler_data = adisc;
+	fc_req->ct_els.handler = zfcp_fc_adisc_handler;
+	fc_req->ct_els.handler_data = fc_req;
 
 	/* acc. to FC-FS, hard_nport_id in ADISC should not be set for ports
 	   without FC-AL-2 capability, so we don't set it */
-	adisc->adisc_req.adisc_wwpn = fc_host_port_name(adapter->scsi_host);
-	adisc->adisc_req.adisc_wwnn = fc_host_node_name(adapter->scsi_host);
-	adisc->adisc_req.adisc_cmd = ELS_ADISC;
-	hton24(adisc->adisc_req.adisc_port_id,
-	       fc_host_port_id(adapter->scsi_host));
+	fc_req->u.adisc.req.adisc_wwpn = fc_host_port_name(shost);
+	fc_req->u.adisc.req.adisc_wwnn = fc_host_node_name(shost);
+	fc_req->u.adisc.req.adisc_cmd = ELS_ADISC;
+	hton24(fc_req->u.adisc.req.adisc_port_id, fc_host_port_id(shost));
 
-	ret = zfcp_fsf_send_els(adapter, port->d_id, &adisc->els,
+	ret = zfcp_fsf_send_els(adapter, port->d_id, &fc_req->ct_els,
 				ZFCP_FC_CTELS_TMO);
 	if (ret)
-		kmem_cache_free(zfcp_data.adisc_cache, adisc);
+		kmem_cache_free(zfcp_fc_req_cache, fc_req);
 
 	return ret;
 }
@@ -528,68 +529,42 @@
 		put_device(&port->dev);
 }
 
-static void zfcp_free_sg_env(struct zfcp_fc_gpn_ft *gpn_ft, int buf_num)
-{
-	struct scatterlist *sg = &gpn_ft->sg_req;
-
-	kmem_cache_free(zfcp_data.gpn_ft_cache, sg_virt(sg));
-	zfcp_sg_free_table(gpn_ft->sg_resp, buf_num);
-
-	kfree(gpn_ft);
-}
-
-static struct zfcp_fc_gpn_ft *zfcp_alloc_sg_env(int buf_num)
+static struct zfcp_fc_req *zfcp_alloc_sg_env(int buf_num)
 {
-	struct zfcp_fc_gpn_ft *gpn_ft;
-	struct zfcp_fc_gpn_ft_req *req;
+	struct zfcp_fc_req *fc_req;
 
-	gpn_ft = kzalloc(sizeof(*gpn_ft), GFP_KERNEL);
-	if (!gpn_ft)
+	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL);
+	if (!fc_req)
 		return NULL;
 
-	req = kmem_cache_zalloc(zfcp_data.gpn_ft_cache, GFP_KERNEL);
-	if (!req) {
-		kfree(gpn_ft);
-		gpn_ft = NULL;
-		goto out;
+	if (zfcp_sg_setup_table(&fc_req->sg_rsp, buf_num)) {
+		kmem_cache_free(zfcp_fc_req_cache, fc_req);
+		return NULL;
 	}
-	sg_init_one(&gpn_ft->sg_req, req, sizeof(*req));
 
-	if (zfcp_sg_setup_table(gpn_ft->sg_resp, buf_num)) {
-		zfcp_free_sg_env(gpn_ft, buf_num);
-		gpn_ft = NULL;
-	}
-out:
-	return gpn_ft;
-}
+	sg_init_one(&fc_req->sg_req, &fc_req->u.gpn_ft.req,
+		    sizeof(struct zfcp_fc_gpn_ft_req));
 
+	return fc_req;
+}
 
-static int zfcp_fc_send_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
+static int zfcp_fc_send_gpn_ft(struct zfcp_fc_req *fc_req,
 			       struct zfcp_adapter *adapter, int max_bytes)
 {
-	struct zfcp_fsf_ct_els *ct = &gpn_ft->ct;
-	struct zfcp_fc_gpn_ft_req *req = sg_virt(&gpn_ft->sg_req);
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_gpn_ft_req *req = &fc_req->u.gpn_ft.req;
 	DECLARE_COMPLETION_ONSTACK(completion);
 	int ret;
 
-	/* prepare CT IU for GPN_FT */
-	req->ct_hdr.ct_rev = FC_CT_REV;
-	req->ct_hdr.ct_fs_type = FC_FST_DIR;
-	req->ct_hdr.ct_fs_subtype = FC_NS_SUBTYPE;
-	req->ct_hdr.ct_options = 0;
-	req->ct_hdr.ct_cmd = FC_NS_GPN_FT;
-	req->ct_hdr.ct_mr_size = max_bytes / 4;
-	req->gpn_ft.fn_domain_id_scope = 0;
-	req->gpn_ft.fn_area_id_scope = 0;
+	zfcp_fc_ct_ns_init(&req->ct_hdr, FC_NS_GPN_FT, max_bytes);
 	req->gpn_ft.fn_fc4_type = FC_TYPE_FCP;
 
-	/* prepare zfcp_send_ct */
-	ct->handler = zfcp_fc_complete;
-	ct->handler_data = &completion;
-	ct->req = &gpn_ft->sg_req;
-	ct->resp = gpn_ft->sg_resp;
+	ct_els->handler = zfcp_fc_complete;
+	ct_els->handler_data = &completion;
+	ct_els->req = &fc_req->sg_req;
+	ct_els->resp = &fc_req->sg_rsp;
 
-	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct, NULL,
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
 			       ZFCP_FC_CTELS_TMO);
 	if (!ret)
 		wait_for_completion(&completion);
@@ -610,11 +585,11 @@
 	list_move_tail(&port->list, lh);
 }
 
-static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_gpn_ft *gpn_ft,
+static int zfcp_fc_eval_gpn_ft(struct zfcp_fc_req *fc_req,
 			       struct zfcp_adapter *adapter, int max_entries)
 {
-	struct zfcp_fsf_ct_els *ct = &gpn_ft->ct;
-	struct scatterlist *sg = gpn_ft->sg_resp;
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct scatterlist *sg = &fc_req->sg_rsp;
 	struct fc_ct_hdr *hdr = sg_virt(sg);
 	struct fc_gpn_ft_resp *acc = sg_virt(sg);
 	struct zfcp_port *port, *tmp;
@@ -623,7 +598,7 @@
 	u32 d_id;
 	int ret = 0, x, last = 0;
 
-	if (ct->status)
+	if (ct_els->status)
 		return -EIO;
 
 	if (hdr->ct_cmd != FC_FS_ACC) {
@@ -687,7 +662,7 @@
 	struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
 						    scan_work);
 	int ret, i;
-	struct zfcp_fc_gpn_ft *gpn_ft;
+	struct zfcp_fc_req *fc_req;
 	int chain, max_entries, buf_num, max_bytes;
 
 	chain = adapter->adapter_features & FSF_FEATURE_ELS_CT_CHAINED_SBALS;
@@ -702,25 +677,145 @@
 	if (zfcp_fc_wka_port_get(&adapter->gs->ds))
 		return;
 
-	gpn_ft = zfcp_alloc_sg_env(buf_num);
-	if (!gpn_ft)
+	fc_req = zfcp_alloc_sg_env(buf_num);
+	if (!fc_req)
 		goto out;
 
 	for (i = 0; i < 3; i++) {
-		ret = zfcp_fc_send_gpn_ft(gpn_ft, adapter, max_bytes);
+		ret = zfcp_fc_send_gpn_ft(fc_req, adapter, max_bytes);
 		if (!ret) {
-			ret = zfcp_fc_eval_gpn_ft(gpn_ft, adapter, max_entries);
+			ret = zfcp_fc_eval_gpn_ft(fc_req, adapter, max_entries);
 			if (ret == -EAGAIN)
 				ssleep(1);
 			else
 				break;
 		}
 	}
-	zfcp_free_sg_env(gpn_ft, buf_num);
+	zfcp_sg_free_table(&fc_req->sg_rsp, buf_num);
+	kmem_cache_free(zfcp_fc_req_cache, fc_req);
 out:
 	zfcp_fc_wka_port_put(&adapter->gs->ds);
 }
 
+static int zfcp_fc_gspn(struct zfcp_adapter *adapter,
+			struct zfcp_fc_req *fc_req)
+{
+	DECLARE_COMPLETION_ONSTACK(completion);
+	char devno[] = "DEVNO:";
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_gspn_req *gspn_req = &fc_req->u.gspn.req;
+	struct zfcp_fc_gspn_rsp *gspn_rsp = &fc_req->u.gspn.rsp;
+	int ret;
+
+	zfcp_fc_ct_ns_init(&gspn_req->ct_hdr, FC_NS_GSPN_ID,
+			   FC_SYMBOLIC_NAME_SIZE);
+	hton24(gspn_req->gspn.fp_fid, fc_host_port_id(adapter->scsi_host));
+
+	sg_init_one(&fc_req->sg_req, gspn_req, sizeof(*gspn_req));
+	sg_init_one(&fc_req->sg_rsp, gspn_rsp, sizeof(*gspn_rsp));
+
+	ct_els->handler = zfcp_fc_complete;
+	ct_els->handler_data = &completion;
+	ct_els->req = &fc_req->sg_req;
+	ct_els->resp = &fc_req->sg_rsp;
+
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
+			       ZFCP_FC_CTELS_TMO);
+	if (ret)
+		return ret;
+
+	wait_for_completion(&completion);
+	if (ct_els->status)
+		return ct_els->status;
+
+	if (fc_host_port_type(adapter->scsi_host) == FC_PORTTYPE_NPIV &&
+	    !(strstr(gspn_rsp->gspn.fp_name, devno)))
+		snprintf(fc_host_symbolic_name(adapter->scsi_host),
+			 FC_SYMBOLIC_NAME_SIZE, "%s%s %s NAME: %s",
+			 gspn_rsp->gspn.fp_name, devno,
+			 dev_name(&adapter->ccw_device->dev),
+			 init_utsname()->nodename);
+	else
+		strlcpy(fc_host_symbolic_name(adapter->scsi_host),
+			gspn_rsp->gspn.fp_name, FC_SYMBOLIC_NAME_SIZE);
+
+	return 0;
+}
+
+static void zfcp_fc_rspn(struct zfcp_adapter *adapter,
+			 struct zfcp_fc_req *fc_req)
+{
+	DECLARE_COMPLETION_ONSTACK(completion);
+	struct Scsi_Host *shost = adapter->scsi_host;
+	struct zfcp_fsf_ct_els *ct_els = &fc_req->ct_els;
+	struct zfcp_fc_rspn_req *rspn_req = &fc_req->u.rspn.req;
+	struct fc_ct_hdr *rspn_rsp = &fc_req->u.rspn.rsp;
+	int ret, len;
+
+	zfcp_fc_ct_ns_init(&rspn_req->ct_hdr, FC_NS_RSPN_ID,
+			   FC_SYMBOLIC_NAME_SIZE);
+	hton24(rspn_req->rspn.fr_fid.fp_fid, fc_host_port_id(shost));
+	len = strlcpy(rspn_req->rspn.fr_name, fc_host_symbolic_name(shost),
+		      FC_SYMBOLIC_NAME_SIZE);
+	rspn_req->rspn.fr_name_len = len;
+
+	sg_init_one(&fc_req->sg_req, rspn_req, sizeof(*rspn_req));
+	sg_init_one(&fc_req->sg_rsp, rspn_rsp, sizeof(*rspn_rsp));
+
+	ct_els->handler = zfcp_fc_complete;
+	ct_els->handler_data = &completion;
+	ct_els->req = &fc_req->sg_req;
+	ct_els->resp = &fc_req->sg_rsp;
+
+	ret = zfcp_fsf_send_ct(&adapter->gs->ds, ct_els, NULL,
+			       ZFCP_FC_CTELS_TMO);
+	if (!ret)
+		wait_for_completion(&completion);
+}
+
+/**
+ * zfcp_fc_sym_name_update - Retrieve and update the symbolic port name
+ * @work: ns_up_work of the adapter where to update the symbolic port name
+ *
+ * Retrieve the current symbolic port name that may have been set by
+ * the hardware using the GSPN request and update the fc_host
+ * symbolic_name sysfs attribute. When running in NPIV mode (and hence
+ * the port name is unique for this system), update the symbolic port
+ * name to add Linux specific information and update the FC nameserver
+ * using the RSPN request.
+ */
+void zfcp_fc_sym_name_update(struct work_struct *work)
+{
+	struct zfcp_adapter *adapter = container_of(work, struct zfcp_adapter,
+						    ns_up_work);
+	int ret;
+	struct zfcp_fc_req *fc_req;
+
+	if (fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPORT &&
+	    fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
+		return;
+
+	fc_req = kmem_cache_zalloc(zfcp_fc_req_cache, GFP_KERNEL);
+	if (!fc_req)
+		return;
+
+	ret = zfcp_fc_wka_port_get(&adapter->gs->ds);
+	if (ret)
+		goto out_free;
+
+	ret = zfcp_fc_gspn(adapter, fc_req);
+	if (ret || fc_host_port_type(adapter->scsi_host) != FC_PORTTYPE_NPIV)
+		goto out_ds_put;
+
+	memset(fc_req, 0, sizeof(*fc_req));
+	zfcp_fc_rspn(adapter, fc_req);
+
+out_ds_put:
+	zfcp_fc_wka_port_put(&adapter->gs->ds);
+out_free:
+	kmem_cache_free(zfcp_fc_req_cache, fc_req);
+}
+
 static void zfcp_fc_ct_els_job_handler(void *data)
 {
 	struct fc_bsg_job *job = data;
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_fc.h linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_fc.h
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_fc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_fc.h	2011-05-19 00:06:34.000000000 -0400
@@ -64,33 +64,16 @@
 } __packed;
 
 /**
- * struct zfcp_fc_gid_pn_resp - container for ct header plus gid_pn response
+ * struct zfcp_fc_gid_pn_rsp - container for ct header plus gid_pn response
  * @ct_hdr: FC GS common transport header
  * @gid_pn: GID_PN response
  */
-struct zfcp_fc_gid_pn_resp {
+struct zfcp_fc_gid_pn_rsp {
 	struct fc_ct_hdr	ct_hdr;
 	struct fc_gid_pn_resp	gid_pn;
 } __packed;
 
 /**
- * struct zfcp_fc_gid_pn - everything required in zfcp for gid_pn request
- * @ct: data passed to zfcp_fsf for issuing fsf request
- * @sg_req: scatterlist entry for request data
- * @sg_resp: scatterlist entry for response data
- * @gid_pn_req: GID_PN request data
- * @gid_pn_resp: GID_PN response data
- */
-struct zfcp_fc_gid_pn {
-	struct zfcp_fsf_ct_els ct;
-	struct scatterlist sg_req;
-	struct scatterlist sg_resp;
-	struct zfcp_fc_gid_pn_req gid_pn_req;
-	struct zfcp_fc_gid_pn_resp gid_pn_resp;
-	struct zfcp_port *port;
-};
-
-/**
  * struct zfcp_fc_gpn_ft - container for ct header plus gpn_ft request
  * @ct_hdr: FC GS common transport header
  * @gpn_ft: GPN_FT request
@@ -101,41 +84,72 @@
 } __packed;
 
 /**
- * struct zfcp_fc_gpn_ft_resp - container for ct header plus gpn_ft response
+ * struct zfcp_fc_gspn_req - container for ct header plus GSPN_ID request
  * @ct_hdr: FC GS common transport header
- * @gpn_ft: Array of gpn_ft response data to fill one memory page
+ * @gspn: GSPN_ID request
  */
-struct zfcp_fc_gpn_ft_resp {
+struct zfcp_fc_gspn_req {
 	struct fc_ct_hdr	ct_hdr;
-	struct fc_gpn_ft_resp	gpn_ft[ZFCP_FC_GPN_FT_ENT_PAGE];
+	struct fc_gid_pn_resp	gspn;
 } __packed;
 
 /**
- * struct zfcp_fc_gpn_ft - zfcp data for gpn_ft request
- * @ct: data passed to zfcp_fsf for issuing fsf request
- * @sg_req: scatter list entry for gpn_ft request
- * @sg_resp: scatter list entries for gpn_ft responses (per memory page)
+ * struct zfcp_fc_gspn_rsp - container for ct header plus GSPN_ID response
+ * @ct_hdr: FC GS common transport header
+ * @gspn: GSPN_ID response
+ * @name: The name string of the GSPN_ID response
  */
-struct zfcp_fc_gpn_ft {
-	struct zfcp_fsf_ct_els ct;
-	struct scatterlist sg_req;
-	struct scatterlist sg_resp[ZFCP_FC_GPN_FT_NUM_BUFS];
-};
+struct zfcp_fc_gspn_rsp {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_gspn_resp	gspn;
+	char			name[FC_SYMBOLIC_NAME_SIZE];
+} __packed;
 
 /**
- * struct zfcp_fc_els_adisc - everything required in zfcp for issuing ELS ADISC
- * @els: data required for issuing els fsf command
- * @req: scatterlist entry for ELS ADISC request
- * @resp: scatterlist entry for ELS ADISC response
- * @adisc_req: ELS ADISC request data
- * @adisc_resp: ELS ADISC response data
+ * struct zfcp_fc_rspn_req - container for ct header plus RSPN_ID request
+ * @ct_hdr: FC GS common transport header
+ * @rspn: RSPN_ID request
+ * @name: The name string of the RSPN_ID request
  */
-struct zfcp_fc_els_adisc {
-	struct zfcp_fsf_ct_els els;
-	struct scatterlist req;
-	struct scatterlist resp;
-	struct fc_els_adisc adisc_req;
-	struct fc_els_adisc adisc_resp;
+struct zfcp_fc_rspn_req {
+	struct fc_ct_hdr	ct_hdr;
+	struct fc_ns_rspn	rspn;
+	char			name[FC_SYMBOLIC_NAME_SIZE];
+} __packed;
+
+/**
+ * struct zfcp_fc_req - Container for FC ELS and CT requests sent from zfcp
+ * @ct_els: data required for issuing fsf command
+ * @sg_req: scatterlist entry for request data
+ * @sg_rsp: scatterlist entry for response data
+ * @u: request specific data
+ */
+struct zfcp_fc_req {
+	struct zfcp_fsf_ct_els				ct_els;
+	struct scatterlist				sg_req;
+	struct scatterlist				sg_rsp;
+	union {
+		struct {
+			struct fc_els_adisc		req;
+			struct fc_els_adisc		rsp;
+		} adisc;
+		struct {
+			struct zfcp_fc_gid_pn_req	req;
+			struct zfcp_fc_gid_pn_rsp	rsp;
+		} gid_pn;
+		struct {
+			struct scatterlist sg_rsp2[ZFCP_FC_GPN_FT_NUM_BUFS - 1];
+			struct zfcp_fc_gpn_ft_req	req;
+		} gpn_ft;
+		struct {
+			struct zfcp_fc_gspn_req		req;
+			struct zfcp_fc_gspn_rsp		rsp;
+		} gspn;
+		struct {
+			struct zfcp_fc_rspn_req		req;
+			struct fc_ct_hdr		rsp;
+		} rspn;
+	} u;
 };
 
 /**
@@ -192,14 +206,21 @@
  * zfcp_fc_scsi_to_fcp - setup FCP command with data from scsi_cmnd
  * @fcp: fcp_cmnd to setup
  * @scsi: scsi_cmnd where to get LUN, task attributes/flags and CDB
+ * @tm: task management flags to setup task management command
  */
 static inline
-void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi)
+void zfcp_fc_scsi_to_fcp(struct fcp_cmnd *fcp, struct scsi_cmnd *scsi,
+			 u8 tm_flags)
 {
 	char tag[2];
 
 	int_to_scsilun(scsi->device->lun, (struct scsi_lun *) &fcp->fc_lun);
 
+	if (unlikely(tm_flags)) {
+		fcp->fc_tm_flags = tm_flags;
+		return;
+	}
+
 	if (scsi_populate_tag_msg(scsi, tag)) {
 		switch (tag[0]) {
 		case MSG_ORDERED_TAG:
@@ -226,19 +247,6 @@
 }
 
 /**
- * zfcp_fc_fcp_tm - setup FCP command as task management command
- * @fcp: fcp_cmnd to setup
- * @dev: scsi_device where to send the task management command
- * @tm: task management flags to setup tm command
- */
-static inline
-void zfcp_fc_fcp_tm(struct fcp_cmnd *fcp, struct scsi_device *dev, u8 tm_flags)
-{
-	int_to_scsilun(dev->lun, (struct scsi_lun *) &fcp->fc_lun);
-	fcp->fc_tm_flags |= tm_flags;
-}
-
-/**
  * zfcp_fc_evap_fcp_rsp - evaluate FCP RSP IU and update scsi_cmnd accordingly
  * @fcp_rsp: FCP RSP IU to evaluate
  * @scsi: SCSI command where to update status and sense buffer
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_fsf.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_fsf.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_fsf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_fsf.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,8 @@
 #include "zfcp_qdio.h"
 #include "zfcp_reqlist.h"
 
+struct kmem_cache *zfcp_fsf_qtcb_cache;
+
 static void zfcp_fsf_request_timeout_handler(unsigned long data)
 {
 	struct zfcp_adapter *adapter = (struct zfcp_adapter *) data;
@@ -83,7 +85,7 @@
 	}
 
 	if (likely(req->qtcb))
-		kmem_cache_free(zfcp_data.qtcb_cache, req->qtcb);
+		kmem_cache_free(zfcp_fsf_qtcb_cache, req->qtcb);
 	kfree(req);
 }
 
@@ -212,7 +214,7 @@
 
 	if (req->status & ZFCP_STATUS_FSFREQ_DISMISSED) {
 		zfcp_dbf_hba_fsf_uss("fssrh_1", req);
-		mempool_free(sr_buf, adapter->pool.status_read_data);
+		mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
 		zfcp_fsf_req_free(req);
 		return;
 	}
@@ -265,7 +267,7 @@
 		break;
 	}
 
-	mempool_free(sr_buf, adapter->pool.status_read_data);
+	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
 	zfcp_fsf_req_free(req);
 
 	atomic_inc(&adapter->stat_miss);
@@ -628,7 +630,7 @@
 	if (likely(pool))
 		qtcb = mempool_alloc(pool, GFP_ATOMIC);
 	else
-		qtcb = kmem_cache_alloc(zfcp_data.qtcb_cache, GFP_ATOMIC);
+		qtcb = kmem_cache_alloc(zfcp_fsf_qtcb_cache, GFP_ATOMIC);
 
 	if (unlikely(!qtcb))
 		return NULL;
@@ -723,6 +725,7 @@
 	struct zfcp_adapter *adapter = qdio->adapter;
 	struct zfcp_fsf_req *req;
 	struct fsf_status_read_buffer *sr_buf;
+	struct page *page;
 	int retval = -EIO;
 
 	spin_lock_irq(&qdio->req_q_lock);
@@ -736,11 +739,12 @@
 		goto out;
 	}
 
-	sr_buf = mempool_alloc(adapter->pool.status_read_data, GFP_ATOMIC);
-	if (!sr_buf) {
+	page = mempool_alloc(adapter->pool.sr_data, GFP_ATOMIC);
+	if (!page) {
 		retval = -ENOMEM;
 		goto failed_buf;
 	}
+	sr_buf = page_address(page);
 	memset(sr_buf, 0, sizeof(*sr_buf));
 	req->data = sr_buf;
 
@@ -755,7 +759,7 @@
 
 failed_req_send:
 	req->data = NULL;
-	mempool_free(sr_buf, adapter->pool.status_read_data);
+	mempool_free(virt_to_page(sr_buf), adapter->pool.sr_data);
 failed_buf:
 	zfcp_dbf_hba_fsf_uss("fssr__1", req);
 	zfcp_fsf_req_free(req);
@@ -1079,7 +1083,7 @@
 		}
 		break;
 	case FSF_SBAL_MISMATCH:
-		/* should never occure, avoided in zfcp_fsf_send_els */
+		/* should never occur, avoided in zfcp_fsf_send_els */
 		/* fall through */
 	default:
 		req->status |= ZFCP_STATUS_FSFREQ_ERROR;
@@ -1552,7 +1556,7 @@
 				  SBAL_FLAGS0_TYPE_READ,
 				  qdio->adapter->pool.erp_req);
 
-	if (unlikely(IS_ERR(req))) {
+	if (IS_ERR(req)) {
 		retval = PTR_ERR(req);
 		goto out;
 	}
@@ -1605,7 +1609,7 @@
 				  SBAL_FLAGS0_TYPE_READ,
 				  qdio->adapter->pool.erp_req);
 
-	if (unlikely(IS_ERR(req))) {
+	if (IS_ERR(req)) {
 		retval = PTR_ERR(req);
 		goto out;
 	}
@@ -2206,7 +2210,7 @@
 	zfcp_fsf_set_data_dir(scsi_cmnd, &io->data_direction);
 
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
-	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd);
+	zfcp_fc_scsi_to_fcp(fcp_cmnd, scsi_cmnd, 0);
 
 	if (scsi_prot_sg_count(scsi_cmnd)) {
 		zfcp_qdio_set_data_div(qdio, &req->qdio_req,
@@ -2284,7 +2288,6 @@
 		goto out;
 	}
 
-	req->status |= ZFCP_STATUS_FSFREQ_TASK_MANAGEMENT;
 	req->data = scmnd;
 	req->handler = zfcp_fsf_fcp_task_mgmt_handler;
 	req->qtcb->header.lun_handle = zfcp_sdev->lun_handle;
@@ -2296,7 +2299,7 @@
 	zfcp_qdio_set_sbale_last(qdio, &req->qdio_req);
 
 	fcp_cmnd = (struct fcp_cmnd *) &req->qtcb->bottom.io.fcp_cmnd;
-	zfcp_fc_fcp_tm(fcp_cmnd, scmnd->device, tm_flags);
+	zfcp_fc_scsi_to_fcp(fcp_cmnd, scmnd, tm_flags);
 
 	zfcp_fsf_start_timer(req, ZFCP_SCSI_ER_TIMEOUT);
 	if (!zfcp_fsf_req_send(req))
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_qdio.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_qdio.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_qdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_qdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -391,7 +391,7 @@
 	if (do_QDIO(cdev, QDIO_FLAG_SYNC_INPUT, 0, 0, QDIO_MAX_BUFFERS_PER_Q))
 		goto failed_qdio;
 
-	/* set index of first avalable SBALS / number of available SBALS */
+	/* set index of first available SBALS / number of available SBALS */
 	qdio->req_q_idx = 0;
 	atomic_set(&qdio->req_q_free, QDIO_MAX_BUFFERS_PER_Q);
 	atomic_set_mask(ZFCP_STATUS_ADAPTER_QDIOUP, &qdio->adapter->status);
diff -druN linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_scsi.c linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_scsi.c
--- linux-libre-2.6.38-gnu/drivers/s390/scsi/zfcp_scsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/s390/scsi/zfcp_scsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -292,7 +292,37 @@
 	return SUCCESS;
 }
 
-int zfcp_adapter_scsi_register(struct zfcp_adapter *adapter)
+struct scsi_transport_template *zfcp_scsi_transport_template;
+
+static struct scsi_host_template zfcp_scsi_host_template = {
+	.module			 = THIS_MODULE,
+	.name			 = "zfcp",
+	.queuecommand		 = zfcp_scsi_queuecommand,
+	.eh_abort_handler	 = zfcp_scsi_eh_abort_handler,
+	.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
+	.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
+	.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
+	.slave_alloc		 = zfcp_scsi_slave_alloc,
+	.slave_configure	 = zfcp_scsi_slave_configure,
+	.slave_destroy		 = zfcp_scsi_slave_destroy,
+	.change_queue_depth	 = zfcp_scsi_change_queue_depth,
+	.proc_name		 = "zfcp",
+	.can_queue		 = 4096,
+	.this_id		 = -1,
+	.sg_tablesize		 = ZFCP_QDIO_MAX_SBALES_PER_REQ,
+	.max_sectors		 = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8),
+	.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
+	.cmd_per_lun		 = 1,
+	.use_clustering		 = 1,
+	.shost_attrs		 = zfcp_sysfs_shost_attrs,
+	.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
+};
+
+/**
+ * zfcp_scsi_adapter_register - Register SCSI and FC host with SCSI midlayer
+ * @adapter: The zfcp adapter to register with the SCSI midlayer
+ */
+int zfcp_scsi_adapter_register(struct zfcp_adapter *adapter)
 {
 	struct ccw_dev_id dev_id;
 
@@ -301,7 +331,7 @@
 
 	ccw_device_get_id(adapter->ccw_device, &dev_id);
 	/* register adapter as SCSI host with mid layer of SCSI stack */
-	adapter->scsi_host = scsi_host_alloc(&zfcp_data.scsi_host_template,
+	adapter->scsi_host = scsi_host_alloc(&zfcp_scsi_host_template,
 					     sizeof (struct zfcp_adapter *));
 	if (!adapter->scsi_host) {
 		dev_err(&adapter->ccw_device->dev,
@@ -316,7 +346,7 @@
 	adapter->scsi_host->max_channel = 0;
 	adapter->scsi_host->unique_id = dev_id.devno;
 	adapter->scsi_host->max_cmd_len = 16; /* in struct fcp_cmnd */
-	adapter->scsi_host->transportt = zfcp_data.scsi_transport_template;
+	adapter->scsi_host->transportt = zfcp_scsi_transport_template;
 
 	adapter->scsi_host->hostdata[0] = (unsigned long) adapter;
 
@@ -328,7 +358,11 @@
 	return 0;
 }
 
-void zfcp_adapter_scsi_unregister(struct zfcp_adapter *adapter)
+/**
+ * zfcp_scsi_adapter_unregister - Unregister SCSI and FC host from SCSI midlayer
+ * @adapter: The zfcp adapter to unregister.
+ */
+void zfcp_scsi_adapter_unregister(struct zfcp_adapter *adapter)
 {
 	struct Scsi_Host *shost;
 	struct zfcp_port *port;
@@ -346,8 +380,6 @@
 	scsi_remove_host(shost);
 	scsi_host_put(shost);
 	adapter->scsi_host = NULL;
-
-	return;
 }
 
 static struct fc_host_statistics*
@@ -688,33 +720,8 @@
 	/* no functions registered for following dynamic attributes but
 	   directly set by LLDD */
 	.show_host_port_type = 1,
+	.show_host_symbolic_name = 1,
 	.show_host_speed = 1,
 	.show_host_port_id = 1,
 	.dd_bsg_size = sizeof(struct zfcp_fsf_ct_els),
 };
-
-struct zfcp_data zfcp_data = {
-	.scsi_host_template = {
-		.name			 = "zfcp",
-		.module			 = THIS_MODULE,
-		.proc_name		 = "zfcp",
-		.change_queue_depth	 = zfcp_scsi_change_queue_depth,
-		.slave_alloc		 = zfcp_scsi_slave_alloc,
-		.slave_configure	 = zfcp_scsi_slave_configure,
-		.slave_destroy		 = zfcp_scsi_slave_destroy,
-		.queuecommand		 = zfcp_scsi_queuecommand,
-		.eh_abort_handler	 = zfcp_scsi_eh_abort_handler,
-		.eh_device_reset_handler = zfcp_scsi_eh_device_reset_handler,
-		.eh_target_reset_handler = zfcp_scsi_eh_target_reset_handler,
-		.eh_host_reset_handler	 = zfcp_scsi_eh_host_reset_handler,
-		.can_queue		 = 4096,
-		.this_id		 = -1,
-		.sg_tablesize		 = ZFCP_QDIO_MAX_SBALES_PER_REQ,
-		.cmd_per_lun		 = 1,
-		.use_clustering		 = 1,
-		.sdev_attrs		 = zfcp_sysfs_sdev_attrs,
-		.max_sectors		 = (ZFCP_QDIO_MAX_SBALES_PER_REQ * 8),
-		.dma_boundary		 = ZFCP_QDIO_SBALE_LEN - 1,
-		.shost_attrs		 = zfcp_sysfs_shost_attrs,
-	},
-};
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/bbc_i2c.c linux-libre-2.6.39-gnu/drivers/sbus/char/bbc_i2c.c
--- linux-libre-2.6.38-gnu/drivers/sbus/char/bbc_i2c.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/bbc_i2c.c	2011-05-19 00:06:34.000000000 -0400
@@ -361,8 +361,7 @@
 extern int bbc_envctrl_init(struct bbc_i2c_bus *bp);
 extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp);
 
-static int __devinit bbc_i2c_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static int __devinit bbc_i2c_probe(struct platform_device *op)
 {
 	struct bbc_i2c_bus *bp;
 	int err, index = 0;
@@ -413,7 +412,7 @@
 };
 MODULE_DEVICE_TABLE(of, bbc_i2c_match);
 
-static struct of_platform_driver bbc_i2c_driver = {
+static struct platform_driver bbc_i2c_driver = {
 	.driver = {
 		.name = "bbc_i2c",
 		.owner = THIS_MODULE,
@@ -425,12 +424,12 @@
 
 static int __init bbc_i2c_init(void)
 {
-	return of_register_platform_driver(&bbc_i2c_driver);
+	return platform_driver_register(&bbc_i2c_driver);
 }
 
 static void __exit bbc_i2c_exit(void)
 {
-	of_unregister_platform_driver(&bbc_i2c_driver);
+	platform_driver_unregister(&bbc_i2c_driver);
 }
 
 module_init(bbc_i2c_init);
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/display7seg.c linux-libre-2.6.39-gnu/drivers/sbus/char/display7seg.c
--- linux-libre-2.6.38-gnu/drivers/sbus/char/display7seg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/display7seg.c	2011-05-19 00:06:34.000000000 -0400
@@ -171,8 +171,7 @@
 	.fops		= &d7s_fops
 };
 
-static int __devinit d7s_probe(struct platform_device *op,
-			       const struct of_device_id *match)
+static int __devinit d7s_probe(struct platform_device *op)
 {
 	struct device_node *opts;
 	int err = -EINVAL;
@@ -266,7 +265,7 @@
 };
 MODULE_DEVICE_TABLE(of, d7s_match);
 
-static struct of_platform_driver d7s_driver = {
+static struct platform_driver d7s_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -278,12 +277,12 @@
 
 static int __init d7s_init(void)
 {
-	return of_register_platform_driver(&d7s_driver);
+	return platform_driver_register(&d7s_driver);
 }
 
 static void __exit d7s_exit(void)
 {
-	of_unregister_platform_driver(&d7s_driver);
+	platform_driver_unregister(&d7s_driver);
 }
 
 module_init(d7s_init);
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/envctrl.c linux-libre-2.6.39-gnu/drivers/sbus/char/envctrl.c
--- linux-libre-2.6.38-gnu/drivers/sbus/char/envctrl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/envctrl.c	2011-05-19 00:06:34.000000000 -0400
@@ -1028,8 +1028,7 @@
 	return 0;
 }
 
-static int __devinit envctrl_probe(struct platform_device *op,
-				   const struct of_device_id *match)
+static int __devinit envctrl_probe(struct platform_device *op)
 {
 	struct device_node *dp;
 	int index, err;
@@ -1129,7 +1128,7 @@
 };
 MODULE_DEVICE_TABLE(of, envctrl_match);
 
-static struct of_platform_driver envctrl_driver = {
+static struct platform_driver envctrl_driver = {
 	.driver = {
 		.name = DRIVER_NAME,
 		.owner = THIS_MODULE,
@@ -1141,12 +1140,12 @@
 
 static int __init envctrl_init(void)
 {
-	return of_register_platform_driver(&envctrl_driver);
+	return platform_driver_register(&envctrl_driver);
 }
 
 static void __exit envctrl_exit(void)
 {
-	of_unregister_platform_driver(&envctrl_driver);
+	platform_driver_unregister(&envctrl_driver);
 }
 
 module_init(envctrl_init);
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/flash.c linux-libre-2.6.39-gnu/drivers/sbus/char/flash.c
--- linux-libre-2.6.38-gnu/drivers/sbus/char/flash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/flash.c	2011-05-19 00:06:34.000000000 -0400
@@ -160,8 +160,7 @@
 
 static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops };
 
-static int __devinit flash_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit flash_probe(struct platform_device *op)
 {
 	struct device_node *dp = op->dev.of_node;
 	struct device_node *parent;
@@ -207,7 +206,7 @@
 };
 MODULE_DEVICE_TABLE(of, flash_match);
 
-static struct of_platform_driver flash_driver = {
+static struct platform_driver flash_driver = {
 	.driver = {
 		.name = "flash",
 		.owner = THIS_MODULE,
@@ -219,12 +218,12 @@
 
 static int __init flash_init(void)
 {
-	return of_register_platform_driver(&flash_driver);
+	return platform_driver_register(&flash_driver);
 }
 
 static void __exit flash_cleanup(void)
 {
-	of_unregister_platform_driver(&flash_driver);
+	platform_driver_unregister(&flash_driver);
 }
 
 module_init(flash_init);
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/jsflash.c linux-libre-2.6.39-gnu/drivers/sbus/char/jsflash.c
--- linux-libre-2.6.38-gnu/drivers/sbus/char/jsflash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/jsflash.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,7 +13,7 @@
  * TODO: Erase/program both banks of a 8MB SIMM.
  *
  * It is anticipated that programming an OS Flash will be a routine
- * procedure. In the same time it is exeedingly dangerous because
+ * procedure. In the same time it is exceedingly dangerous because
  * a user can program its OBP flash with OS image and effectively
  * kill the machine.
  *
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/max1617.h linux-libre-2.6.39-gnu/drivers/sbus/char/max1617.h
--- linux-libre-2.6.38-gnu/drivers/sbus/char/max1617.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/max1617.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
 #define MAX1617_CPU_TEMP	0x01 /* Processor die temp in C	*/
 #define MAX1617_STATUS		0x02 /* Chip status bits	*/
 
-/* Read-only versions of changable registers. */
+/* Read-only versions of changeable registers. */
 #define MAX1617_RD_CFG_BYTE	0x03 /* Config register		*/
 #define MAX1617_RD_CVRATE_BYTE	0x04 /* Temp conversion rate	*/
 #define MAX1617_RD_AMB_HIGHLIM	0x05 /* Ambient high limit	*/
diff -druN linux-libre-2.6.38-gnu/drivers/sbus/char/uctrl.c linux-libre-2.6.39-gnu/drivers/sbus/char/uctrl.c
--- linux-libre-2.6.38-gnu/drivers/sbus/char/uctrl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sbus/char/uctrl.c	2011-05-19 00:06:34.000000000 -0400
@@ -348,8 +348,7 @@
 	
 }
 
-static int __devinit uctrl_probe(struct platform_device *op,
-				 const struct of_device_id *match)
+static int __devinit uctrl_probe(struct platform_device *op)
 {
 	struct uctrl_driver *p;
 	int err = -ENOMEM;
@@ -425,7 +424,7 @@
 };
 MODULE_DEVICE_TABLE(of, uctrl_match);
 
-static struct of_platform_driver uctrl_driver = {
+static struct platform_driver uctrl_driver = {
 	.driver = {
 		.name = "uctrl",
 		.owner = THIS_MODULE,
@@ -438,12 +437,12 @@
 
 static int __init uctrl_init(void)
 {
-	return of_register_platform_driver(&uctrl_driver);
+	return platform_driver_register(&uctrl_driver);
 }
 
 static void __exit uctrl_exit(void)
 {
-	of_unregister_platform_driver(&uctrl_driver);
+	platform_driver_unregister(&uctrl_driver);
 }
 
 module_init(uctrl_init);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/3w-9xxx.h linux-libre-2.6.39-gnu/drivers/scsi/3w-9xxx.h
--- linux-libre-2.6.38-gnu/drivers/scsi/3w-9xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/3w-9xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,7 +61,7 @@
 	{0x0000, "AEN queue empty"},
 	{0x0001, "Controller reset occurred"},
 	{0x0002, "Degraded unit detected"},
-	{0x0003, "Controller error occured"},
+	{0x0003, "Controller error occurred"},
 	{0x0004, "Background rebuild failed"},
 	{0x0005, "Background rebuild done"},
 	{0x0006, "Incomplete unit detected"},
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/3w-xxxx.h linux-libre-2.6.39-gnu/drivers/scsi/3w-xxxx.h
--- linux-libre-2.6.38-gnu/drivers/scsi/3w-xxxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/3w-xxxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
 
    Copyright (C) 1999-2010 3ware Inc.
 
-   Kernel compatiblity By:	Andre Hedrick <andre@suse.com>
+   Kernel compatibility By:	Andre Hedrick <andre@suse.com>
    Non-Copyright (C) 2000	Andre Hedrick <andre@suse.com>
 
    This program is free software; you can redistribute it and/or modify
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/53c700_d.h_shipped linux-libre-2.6.39-gnu/drivers/scsi/53c700_d.h_shipped
--- linux-libre-2.6.38-gnu/drivers/scsi/53c700_d.h_shipped	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/53c700_d.h_shipped	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 ABSOLUTE	ReceiveMsgAddress = 0	; Addr to receive msg
 ;
 ; This is the magic component for handling scatter-gather.  Each of the
-; SG components is preceeded by a script fragment which moves the
+; SG components is preceded by a script fragment which moves the
 ; necessary amount of data and jumps to the next SG segment.  The final
 ; SG segment jumps back to .  However, this address is the first SG script
 ; segment.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/53c700.scr linux-libre-2.6.39-gnu/drivers/scsi/53c700.scr
--- linux-libre-2.6.38-gnu/drivers/scsi/53c700.scr	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/53c700.scr	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 ABSOLUTE	ReceiveMsgAddress = 0	; Addr to receive msg
 ;
 ; This is the magic component for handling scatter-gather.  Each of the
-; SG components is preceeded by a script fragment which moves the
+; SG components is preceded by a script fragment which moves the
 ; necessary amount of data and jumps to the next SG segment.  The final
 ; SG segment jumps back to .  However, this address is the first SG script
 ; segment.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/aachba.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/aachba.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/aachba.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/aachba.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -746,8 +747,8 @@
  * Arguments: [1] pointer to void [1] int
  *
  * Purpose: Sets SCSI inquiry data strings for vendor, product
- * and revision level. Allows strings to be set in platform dependant
- * files instead of in OS dependant driver source.
+ * and revision level. Allows strings to be set in platform dependent
+ * files instead of in OS dependent driver source.
  */
 
 static void setinqstr(struct aac_dev *dev, void *data, int tindex)
@@ -1486,7 +1487,9 @@
 			dev->a_ops.adapter_write = aac_write_block;
 		}
 		dev->scsi_host_ptr->max_sectors = AAC_MAX_32BIT_SGBCOUNT;
-		if(!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
+		if (dev->adapter_info.options & AAC_OPT_NEW_COMM_TYPE1)
+			dev->adapter_info.options |= AAC_OPT_NEW_COMM;
+		if (!(dev->adapter_info.options & AAC_OPT_NEW_COMM)) {
 			/*
 			 * Worst case size that could cause sg overflow when
 			 * we break up SG elements that are larger than 64KB.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/aacraid.h linux-libre-2.6.39-gnu/drivers/scsi/aacraid/aacraid.h
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/aacraid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/aacraid.h	2011-05-19 00:06:34.000000000 -0400
@@ -12,7 +12,7 @@
  *----------------------------------------------------------------------------*/
 
 #ifndef AAC_DRIVER_BUILD
-# define AAC_DRIVER_BUILD 26400
+# define AAC_DRIVER_BUILD 28000
 # define AAC_DRIVER_BRANCH "-ms"
 #endif
 #define MAXIMUM_NUM_CONTAINERS	32
@@ -277,6 +277,16 @@
 
 #define		FsaNormal	1
 
+/* transport FIB header (PMC) */
+struct aac_fib_xporthdr {
+	u64	HostAddress;	/* FIB host address w/o xport header */
+	u32	Size;		/* FIB size excluding xport header */
+	u32	Handle;		/* driver handle to reference the FIB */
+	u64	Reserved[2];
+};
+
+#define		ALIGN32		32
+
 /*
  * Define the FIB. The FIB is the where all the requested data and
  * command information are put to the application on the FSA adapter.
@@ -394,7 +404,9 @@
 	AdapterMicroFib			= (1<<17),
 	BIOSFibPath			= (1<<18),
 	FastResponseCapable		= (1<<19),
-	ApiFib				= (1<<20)	// Its an API Fib.
+	ApiFib				= (1<<20),	/* Its an API Fib */
+	/* PMC NEW COMM: There is no more AIF data pending */
+	NoMoreAifDataAvailable		= (1<<21)
 };
 
 /*
@@ -404,6 +416,7 @@
 
 #define ADAPTER_INIT_STRUCT_REVISION		3
 #define ADAPTER_INIT_STRUCT_REVISION_4		4 // rocket science
+#define ADAPTER_INIT_STRUCT_REVISION_6		6 /* PMC src */
 
 struct aac_init
 {
@@ -428,9 +441,15 @@
 #define INITFLAGS_NEW_COMM_SUPPORTED	0x00000001
 #define INITFLAGS_DRIVER_USES_UTC_TIME	0x00000010
 #define INITFLAGS_DRIVER_SUPPORTS_PM	0x00000020
+#define INITFLAGS_NEW_COMM_TYPE1_SUPPORTED	0x00000041
 	__le32	MaxIoCommands;	/* max outstanding commands */
 	__le32	MaxIoSize;	/* largest I/O command */
 	__le32	MaxFibSize;	/* largest FIB to adapter */
+	/* ADAPTER_INIT_STRUCT_REVISION_5 begins here */
+	__le32	MaxNumAif;	/* max number of aif */
+	/* ADAPTER_INIT_STRUCT_REVISION_6 begins here */
+	__le32	HostRRQ_AddrLow;
+	__le32	HostRRQ_AddrHigh;	/* Host RRQ (response queue) for SRC */
 };
 
 enum aac_log_level {
@@ -685,7 +704,7 @@
 #define OutboundDoorbellReg	MUnit.ODR
 
 struct rx_registers {
-	struct rx_mu_registers		MUnit;		/* 1300h - 1344h */
+	struct rx_mu_registers		MUnit;		/* 1300h - 1347h */
 	__le32				reserved1[2];	/* 1348h - 134ch */
 	struct rx_inbound		IndexRegs;
 };
@@ -703,7 +722,7 @@
 #define rkt_inbound rx_inbound
 
 struct rkt_registers {
-	struct rkt_mu_registers		MUnit;		 /* 1300h - 1344h */
+	struct rkt_mu_registers		MUnit;		 /* 1300h - 1347h */
 	__le32				reserved1[1006]; /* 1348h - 22fch */
 	struct rkt_inbound		IndexRegs;	 /* 2300h - */
 };
@@ -713,6 +732,44 @@
 #define rkt_writeb(AEP, CSR, value)	writeb(value, &((AEP)->regs.rkt->CSR))
 #define rkt_writel(AEP, CSR, value)	writel(value, &((AEP)->regs.rkt->CSR))
 
+/*
+ * PMC SRC message unit registers
+ */
+
+#define src_inbound rx_inbound
+
+struct src_mu_registers {
+				/*	PCI*| Name */
+	__le32	reserved0[8];	/*	00h | Reserved */
+	__le32	IDR;		/*	20h | Inbound Doorbell Register */
+	__le32	IISR;		/*	24h | Inbound Int. Status Register */
+	__le32	reserved1[3];	/*	28h | Reserved */
+	__le32	OIMR;		/*	34h | Outbound Int. Mask Register */
+	__le32	reserved2[25];	/*	38h | Reserved */
+	__le32	ODR_R;		/*	9ch | Outbound Doorbell Read */
+	__le32	ODR_C;		/*	a0h | Outbound Doorbell Clear */
+	__le32	reserved3[6];	/*	a4h | Reserved */
+	__le32	OMR;		/*	bch | Outbound Message Register */
+	__le32	IQ_L;		/*  c0h | Inbound Queue (Low address) */
+	__le32	IQ_H;		/*  c4h | Inbound Queue (High address) */
+};
+
+struct src_registers {
+	struct src_mu_registers MUnit;	/* 00h - c7h */
+	__le32 reserved1[130790];	/* c8h - 7fc5fh */
+	struct src_inbound IndexRegs;	/* 7fc60h */
+};
+
+#define src_readb(AEP, CSR)		readb(&((AEP)->regs.src.bar0->CSR))
+#define src_readl(AEP, CSR)		readl(&((AEP)->regs.src.bar0->CSR))
+#define src_writeb(AEP, CSR, value)	writeb(value, \
+						&((AEP)->regs.src.bar0->CSR))
+#define src_writel(AEP, CSR, value)	writel(value, \
+						&((AEP)->regs.src.bar0->CSR))
+
+#define SRC_ODR_SHIFT		12
+#define SRC_IDR_SHIFT		9
+
 typedef void (*fib_callback)(void *ctxt, struct fib *fibctx);
 
 struct aac_fib_context {
@@ -879,6 +936,7 @@
 #define AAC_OPTION_MU_RESET		cpu_to_le32(0x00000001)
 #define AAC_OPTION_IGNORE_RESET		cpu_to_le32(0x00000002)
 #define AAC_OPTION_POWER_MANAGEMENT	cpu_to_le32(0x00000004)
+#define AAC_OPTION_DOORBELL_RESET	cpu_to_le32(0x00004000)
 #define AAC_SIS_VERSION_V3	3
 #define AAC_SIS_SLOT_UNKNOWN	0xFF
 
@@ -940,6 +998,7 @@
 #define AAC_OPT_SUPPLEMENT_ADAPTER_INFO	cpu_to_le32(1<<16)
 #define AAC_OPT_NEW_COMM		cpu_to_le32(1<<17)
 #define AAC_OPT_NEW_COMM_64		cpu_to_le32(1<<18)
+#define AAC_OPT_NEW_COMM_TYPE1		cpu_to_le32(1<<28)
 
 struct aac_dev
 {
@@ -952,6 +1011,7 @@
 	 */
 	unsigned		max_fib_size;
 	unsigned		sg_tablesize;
+	unsigned		max_num_aif;
 
 	/*
 	 *	Map for 128 fib objects (64k)
@@ -980,10 +1040,21 @@
 	struct adapter_ops	a_ops;
 	unsigned long		fsrev;		/* Main driver's revision number */
 
-	unsigned		base_size;	/* Size of mapped in region */
+	unsigned long		dbg_base;	/* address of UART
+						 * debug buffer */
+
+	unsigned		base_size, dbg_size;	/* Size of
+							 *  mapped in region */
+
 	struct aac_init		*init;		/* Holds initialization info to communicate with adapter */
 	dma_addr_t		init_pa;	/* Holds physical address of the init struct */
 
+	u32			*host_rrq;	/* response queue
+						 * if AAC_COMM_MESSAGE_TYPE1 */
+
+	dma_addr_t		host_rrq_pa;	/* phys. address */
+	u32			host_rrq_idx;	/* index into rrq buffer */
+
 	struct pci_dev		*pdev;		/* Our PCI interface */
 	void *			printfbuf;	/* pointer to buffer used for printf's from the adapter */
 	void *			comm_addr;	/* Base address of Comm area */
@@ -1003,14 +1074,20 @@
 	 */
 #ifndef AAC_MIN_FOOTPRINT_SIZE
 #	define AAC_MIN_FOOTPRINT_SIZE 8192
+#	define AAC_MIN_SRC_BAR0_SIZE 0x400000
+#	define AAC_MIN_SRC_BAR1_SIZE 0x800
 #endif
 	union
 	{
 		struct sa_registers __iomem *sa;
 		struct rx_registers __iomem *rx;
 		struct rkt_registers __iomem *rkt;
+		struct {
+			struct src_registers __iomem *bar0;
+			char __iomem *bar1;
+		} src;
 	} regs;
-	volatile void __iomem *base;
+	volatile void __iomem *base, *dbg_base_mapped;
 	volatile struct rx_inbound __iomem *IndexRegs;
 	u32			OIMR; /* Mask Register Cache */
 	/*
@@ -1031,9 +1108,8 @@
 	u8			comm_interface;
 #	define AAC_COMM_PRODUCER 0
 #	define AAC_COMM_MESSAGE  1
-	/* macro side-effects BEWARE */
-#	define			raw_io_interface \
-	  init->InitStructRevision==cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_4)
+#	define AAC_COMM_MESSAGE_TYPE1	3
+	u8			raw_io_interface;
 	u8			raw_io_64;
 	u8			printf_enabled;
 	u8			in_reset;
@@ -1183,7 +1259,7 @@
 #define CACHE_UNSTABLE		2
 
 /*
- *	Lets the client know at which level the data was commited on
+ *	Lets the client know at which level the data was committed on
  *	a write request
  */
 
@@ -1789,6 +1865,10 @@
 #define DoorBellAdapterNormCmdNotFull	(1<<3)	/* Adapter -> Host */
 #define DoorBellAdapterNormRespNotFull	(1<<4)	/* Adapter -> Host */
 #define DoorBellPrintfReady		(1<<5)	/* Adapter -> Host */
+#define DoorBellAifPending		(1<<6)	/* Adapter -> Host */
+
+/* PMC specific outbound doorbell bits */
+#define PmDoorBellResponseSent		(1<<1)	/* Adapter -> Host */
 
 /*
  *	For FIB communication, we need all of the following things
@@ -1831,6 +1911,9 @@
 #define		AifReqAPIJobUpdate	109	/* Update a job report from the API */
 #define		AifReqAPIJobFinish	110	/* Finish a job from the API */
 
+/* PMC NEW COMM: Request the event data */
+#define		AifReqEvent		200
+
 /*
  *	Adapter Initiated FIB command structures. Start with the adapter
  *	initiated FIBs that really come from the adapter, and get responded
@@ -1886,10 +1969,13 @@
 int aac_rkt_init(struct aac_dev *dev);
 int aac_nark_init(struct aac_dev *dev);
 int aac_sa_init(struct aac_dev *dev);
+int aac_src_init(struct aac_dev *dev);
 int aac_queue_get(struct aac_dev * dev, u32 * index, u32 qid, struct hw_fib * hw_fib, int wait, struct fib * fibptr, unsigned long *nonotify);
 unsigned int aac_response_normal(struct aac_queue * q);
 unsigned int aac_command_normal(struct aac_queue * q);
-unsigned int aac_intr_normal(struct aac_dev * dev, u32 Index);
+unsigned int aac_intr_normal(struct aac_dev *dev, u32 Index,
+			int isAif, int isFastResponse,
+			struct hw_fib *aif_fib);
 int aac_reset_adapter(struct aac_dev * dev, int forced);
 int aac_check_health(struct aac_dev * dev);
 int aac_command_thread(void *data);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/commctrl.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/commctrl.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/commctrl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/commctrl.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/comminit.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/comminit.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/comminit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/comminit.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -52,12 +53,16 @@
 	unsigned long size, align;
 	const unsigned long fibsize = 4096;
 	const unsigned long printfbufsiz = 256;
+	unsigned long host_rrq_size = 0;
 	struct aac_init *init;
 	dma_addr_t phys;
 	unsigned long aac_max_hostphysmempages;
 
-	size = fibsize + sizeof(struct aac_init) + commsize + commalign + printfbufsiz;
-
+	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1)
+		host_rrq_size = (dev->scsi_host_ptr->can_queue
+			+ AAC_NUM_MGT_FIB) * sizeof(u32);
+	size = fibsize + sizeof(struct aac_init) + commsize +
+			commalign + printfbufsiz + host_rrq_size;
  
 	base = pci_alloc_consistent(dev->pdev, size, &phys);
 
@@ -70,8 +75,14 @@
 	dev->comm_phys = phys;
 	dev->comm_size = size;
 	
-	dev->init = (struct aac_init *)(base + fibsize);
-	dev->init_pa = phys + fibsize;
+	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
+		dev->host_rrq = (u32 *)(base + fibsize);
+		dev->host_rrq_pa = phys + fibsize;
+		memset(dev->host_rrq, 0, host_rrq_size);
+	}
+
+	dev->init = (struct aac_init *)(base + fibsize + host_rrq_size);
+	dev->init_pa = phys + fibsize + host_rrq_size;
 
 	init = dev->init;
 
@@ -106,8 +117,13 @@
 
 	init->InitFlags = 0;
 	if (dev->comm_interface == AAC_COMM_MESSAGE) {
-		init->InitFlags = cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
+		init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_SUPPORTED);
 		dprintk((KERN_WARNING"aacraid: New Comm Interface enabled\n"));
+	} else if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
+		init->InitStructRevision = cpu_to_le32(ADAPTER_INIT_STRUCT_REVISION_6);
+		init->InitFlags |= cpu_to_le32(INITFLAGS_NEW_COMM_TYPE1_SUPPORTED);
+		dprintk((KERN_WARNING
+			"aacraid: New Comm Interface type1 enabled\n"));
 	}
 	init->InitFlags |= cpu_to_le32(INITFLAGS_DRIVER_USES_UTC_TIME |
 				       INITFLAGS_DRIVER_SUPPORTS_PM);
@@ -115,11 +131,18 @@
 	init->MaxIoSize = cpu_to_le32(dev->scsi_host_ptr->max_sectors << 9);
 	init->MaxFibSize = cpu_to_le32(dev->max_fib_size);
 
+	init->MaxNumAif = cpu_to_le32(dev->max_num_aif);
+	init->HostRRQ_AddrHigh = (u32)((u64)dev->host_rrq_pa >> 32);
+	init->HostRRQ_AddrLow = (u32)(dev->host_rrq_pa & 0xffffffff);
+
+
 	/*
 	 * Increment the base address by the amount already used
 	 */
-	base = base + fibsize + sizeof(struct aac_init);
-	phys = (dma_addr_t)((ulong)phys + fibsize + sizeof(struct aac_init));
+	base = base + fibsize + host_rrq_size + sizeof(struct aac_init);
+	phys = (dma_addr_t)((ulong)phys + fibsize + host_rrq_size +
+		sizeof(struct aac_init));
+
 	/*
 	 *	Align the beginning of Headers to commalign
 	 */
@@ -314,15 +337,22 @@
 		- sizeof(struct aac_write) + sizeof(struct sgentry))
 			/ sizeof(struct sgentry);
 	dev->comm_interface = AAC_COMM_PRODUCER;
-	dev->raw_io_64 = 0;
+	dev->raw_io_interface = dev->raw_io_64 = 0;
+
 	if ((!aac_adapter_sync_cmd(dev, GET_ADAPTER_PROPERTIES,
 		0, 0, 0, 0, 0, 0, status+0, status+1, status+2, NULL, NULL)) &&
 	 		(status[0] == 0x00000001)) {
 		if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_64))
 			dev->raw_io_64 = 1;
-		if (dev->a_ops.adapter_comm &&
-		    (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)))
-			dev->comm_interface = AAC_COMM_MESSAGE;
+		if (dev->a_ops.adapter_comm) {
+			if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM_TYPE1)) {
+				dev->comm_interface = AAC_COMM_MESSAGE_TYPE1;
+				dev->raw_io_interface = 1;
+			} else if (status[1] & le32_to_cpu(AAC_OPT_NEW_COMM)) {
+				dev->comm_interface = AAC_COMM_MESSAGE;
+				dev->raw_io_interface = 1;
+			}
+		}
 		if ((dev->comm_interface == AAC_COMM_MESSAGE) &&
 		    (status[2] > dev->base_size)) {
 			aac_adapter_ioremap(dev, 0);
@@ -350,10 +380,12 @@
 		 *	status[3] & 0xFFFF	maximum number FIBs outstanding
 		 */
 		host->max_sectors = (status[1] >> 16) << 1;
-		dev->max_fib_size = status[1] & 0xFFFF;
+		/* Multiple of 32 for PMC */
+		dev->max_fib_size = status[1] & 0xFFE0;
 		host->sg_tablesize = status[2] >> 16;
 		dev->sg_tablesize = status[2] & 0xFFFF;
 		host->can_queue = (status[3] & 0xFFFF) - AAC_NUM_MGT_FIB;
+		dev->max_num_aif = status[4] & 0xFFFF;
 		/*
 		 *	NOTE:
 		 *	All these overrides are based on a fixed internal
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/commsup.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/commsup.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/commsup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/commsup.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -63,9 +64,11 @@
 	  "allocate hardware fibs pci_alloc_consistent(%p, %d * (%d + %d), %p)\n",
 	  dev->pdev, dev->max_fib_size, dev->scsi_host_ptr->can_queue,
 	  AAC_NUM_MGT_FIB, &dev->hw_fib_pa));
-	if((dev->hw_fib_va = pci_alloc_consistent(dev->pdev, dev->max_fib_size
-	  * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB),
-	  &dev->hw_fib_pa))==NULL)
+	dev->hw_fib_va = pci_alloc_consistent(dev->pdev,
+		(dev->max_fib_size + sizeof(struct aac_fib_xporthdr))
+		* (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB) + (ALIGN32 - 1),
+		&dev->hw_fib_pa);
+	if (dev->hw_fib_va == NULL)
 		return -ENOMEM;
 	return 0;
 }
@@ -110,9 +113,22 @@
 	if (i<0)
 		return -ENOMEM;
 
+	/* 32 byte alignment for PMC */
+	hw_fib_pa = (dev->hw_fib_pa + (ALIGN32 - 1)) & ~(ALIGN32 - 1);
+	dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
+		(hw_fib_pa - dev->hw_fib_pa));
+	dev->hw_fib_pa = hw_fib_pa;
+	memset(dev->hw_fib_va, 0,
+		(dev->max_fib_size + sizeof(struct aac_fib_xporthdr)) *
+		(dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
+
+	/* add Xport header */
+	dev->hw_fib_va = (struct hw_fib *)((unsigned char *)dev->hw_fib_va +
+		sizeof(struct aac_fib_xporthdr));
+	dev->hw_fib_pa += sizeof(struct aac_fib_xporthdr);
+
 	hw_fib = dev->hw_fib_va;
 	hw_fib_pa = dev->hw_fib_pa;
-	memset(hw_fib, 0, dev->max_fib_size * (dev->scsi_host_ptr->can_queue + AAC_NUM_MGT_FIB));
 	/*
 	 *	Initialise the fibs
 	 */
@@ -129,8 +145,10 @@
 		hw_fib->header.XferState = cpu_to_le32(0xffffffff);
 		hw_fib->header.SenderSize = cpu_to_le16(dev->max_fib_size);
 		fibptr->hw_fib_pa = hw_fib_pa;
-		hw_fib = (struct hw_fib *)((unsigned char *)hw_fib + dev->max_fib_size);
-		hw_fib_pa = hw_fib_pa + dev->max_fib_size;
+		hw_fib = (struct hw_fib *)((unsigned char *)hw_fib +
+			dev->max_fib_size + sizeof(struct aac_fib_xporthdr));
+		hw_fib_pa = hw_fib_pa +
+			dev->max_fib_size + sizeof(struct aac_fib_xporthdr);
 	}
 	/*
 	 *	Add the fib chain to the free list
@@ -403,7 +421,7 @@
 	if (!(hw_fib->header.XferState & cpu_to_le32(HostOwned)))
 		return -EBUSY;
 	/*
-	 *	There are 5 cases with the wait and reponse requested flags.
+	 *	There are 5 cases with the wait and response requested flags.
 	 *	The only invalid cases are if the caller requests to wait and
 	 *	does not request a response and if the caller does not want a
 	 *	response and the Fib is not allocated from pool. If a response
@@ -664,9 +682,14 @@
 	unsigned long nointr = 0;
 	unsigned long qflags;
 
+	if (dev->comm_interface == AAC_COMM_MESSAGE_TYPE1) {
+		kfree(hw_fib);
+		return 0;
+	}
+
 	if (hw_fib->header.XferState == 0) {
 		if (dev->comm_interface == AAC_COMM_MESSAGE)
-			kfree (hw_fib);
+			kfree(hw_fib);
 		return 0;
 	}
 	/*
@@ -674,7 +697,7 @@
 	 */
 	if (hw_fib->header.StructType != FIB_MAGIC) {
 		if (dev->comm_interface == AAC_COMM_MESSAGE)
-			kfree (hw_fib);
+			kfree(hw_fib);
 		return -EINVAL;
 	}
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/dpcsup.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/dpcsup.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/dpcsup.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/dpcsup.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -228,6 +229,48 @@
 	return 0;
 }
 
+/*
+ *
+ * aac_aif_callback
+ * @context: the context set in the fib - here it is scsi cmd
+ * @fibptr: pointer to the fib
+ *
+ * Handles the AIFs - new method (SRC)
+ *
+ */
+
+static void aac_aif_callback(void *context, struct fib * fibptr)
+{
+	struct fib *fibctx;
+	struct aac_dev *dev;
+	struct aac_aifcmd *cmd;
+	int status;
+
+	fibctx = (struct fib *)context;
+	BUG_ON(fibptr == NULL);
+	dev = fibptr->dev;
+
+	if (fibptr->hw_fib_va->header.XferState &
+	    cpu_to_le32(NoMoreAifDataAvailable)) {
+		aac_fib_complete(fibptr);
+		aac_fib_free(fibptr);
+		return;
+	}
+
+	aac_intr_normal(dev, 0, 1, 0, fibptr->hw_fib_va);
+
+	aac_fib_init(fibctx);
+	cmd = (struct aac_aifcmd *) fib_data(fibctx);
+	cmd->command = cpu_to_le32(AifReqEvent);
+
+	status = aac_fib_send(AifRequest,
+		fibctx,
+		sizeof(struct hw_fib)-sizeof(struct aac_fibhdr),
+		FsaNormal,
+		0, 1,
+		(fib_callback)aac_aif_callback, fibctx);
+}
+
 
 /**
  *	aac_intr_normal	-	Handle command replies
@@ -238,19 +281,17 @@
  *	know there is a response on our normal priority queue. We will pull off
  *	all QE there are and wake up all the waiters before exiting.
  */
-
-unsigned int aac_intr_normal(struct aac_dev * dev, u32 index)
+unsigned int aac_intr_normal(struct aac_dev *dev, u32 index,
+			int isAif, int isFastResponse, struct hw_fib *aif_fib)
 {
 	unsigned long mflags;
 	dprintk((KERN_INFO "aac_intr_normal(%p,%x)\n", dev, index));
-	if ((index & 0x00000002L)) {
+	if (isAif == 1) {	/* AIF - common */
 		struct hw_fib * hw_fib;
 		struct fib * fib;
 		struct aac_queue *q = &dev->queues->queue[HostNormCmdQueue];
 		unsigned long flags;
 
-		if (index == 0xFFFFFFFEL) /* Special Case */
-			return 0;	  /* Do nothing */
 		/*
 		 *	Allocate a FIB. For non queued stuff we can just use
 		 * the stack so we are happy. We need a fib object in order to
@@ -263,8 +304,13 @@
 			kfree (fib);
 			return 1;
 		}
-		memcpy(hw_fib, (struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
-		  (index & ~0x00000002L)), sizeof(struct hw_fib));
+		if (aif_fib != NULL) {
+			memcpy(hw_fib, aif_fib, sizeof(struct hw_fib));
+		} else {
+			memcpy(hw_fib,
+				(struct hw_fib *)(((uintptr_t)(dev->regs.sa)) +
+				index), sizeof(struct hw_fib));
+		}
 		INIT_LIST_HEAD(&fib->fiblink);
 		fib->type = FSAFS_NTC_FIB_CONTEXT;
 		fib->size = sizeof(struct fib);
@@ -277,9 +323,26 @@
 	        wake_up_interruptible(&q->cmdready);
 		spin_unlock_irqrestore(q->lock, flags);
 		return 1;
+	} else if (isAif == 2) {	/* AIF - new (SRC) */
+		struct fib *fibctx;
+		struct aac_aifcmd *cmd;
+
+		fibctx = aac_fib_alloc(dev);
+		if (!fibctx)
+			return 1;
+		aac_fib_init(fibctx);
+
+		cmd = (struct aac_aifcmd *) fib_data(fibctx);
+		cmd->command = cpu_to_le32(AifReqEvent);
+
+		return aac_fib_send(AifRequest,
+			fibctx,
+			sizeof(struct hw_fib)-sizeof(struct aac_fibhdr),
+			FsaNormal,
+			0, 1,
+			(fib_callback)aac_aif_callback, fibctx);
 	} else {
-		int fast = index & 0x01;
-		struct fib * fib = &dev->fibs[index >> 2];
+		struct fib *fib = &dev->fibs[index];
 		struct hw_fib * hwfib = fib->hw_fib_va;
 
 		/*
@@ -298,7 +361,7 @@
 			return 0;
 		}
 
-		if (fast) {
+		if (isFastResponse) {
 			/*
 			 *	Doctor the fib
 			 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/linit.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/linit.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/linit.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/linit.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -54,7 +55,7 @@
 
 #include "aacraid.h"
 
-#define AAC_DRIVER_VERSION		"1.1-5"
+#define AAC_DRIVER_VERSION		"1.1-7"
 #ifndef AAC_DRIVER_BRANCH
 #define AAC_DRIVER_BRANCH		""
 #endif
@@ -161,6 +162,7 @@
 	{ 0x9005, 0x0285, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 59 }, /* Adaptec Catch All */
 	{ 0x9005, 0x0286, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 60 }, /* Adaptec Rocket Catch All */
 	{ 0x9005, 0x0288, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 61 }, /* Adaptec NEMER/ARK Catch All */
+	{ 0x9005, 0x028b, PCI_ANY_ID, PCI_ANY_ID, 0, 0, 62 }, /* Adaptec PMC Catch All */
 	{ 0,}
 };
 MODULE_DEVICE_TABLE(pci, aac_pci_tbl);
@@ -235,7 +237,8 @@
 	{ aac_rx_init, "aacraid",  "Legend  ", "RAID            ", 2, AAC_QUIRK_31BIT | AAC_QUIRK_34SG | AAC_QUIRK_SCSI_32 }, /* Legend Catchall */
 	{ aac_rx_init, "aacraid",  "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Catch All */
 	{ aac_rkt_init, "aacraid", "ADAPTEC ", "RAID            ", 2 }, /* Adaptec Rocket Catch All */
-	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec NEMER/ARK Catch All */
+	{ aac_nark_init, "aacraid", "ADAPTEC ", "RAID           ", 2 }, /* Adaptec NEMER/ARK Catch All */
+	{ aac_src_init, "aacraid", "ADAPTEC ", "RAID            ", 2 } /* Adaptec PMC Catch All */
 };
 
 /**
@@ -653,8 +656,10 @@
 	 * This adapter needs a blind reset, only do so for Adapters that
 	 * support a register, instead of a commanded, reset.
 	 */
-	if ((aac->supplement_adapter_info.SupportedOptions2 &
-	   AAC_OPTION_MU_RESET) &&
+	if (((aac->supplement_adapter_info.SupportedOptions2 &
+	  AAC_OPTION_MU_RESET) ||
+	  (aac->supplement_adapter_info.SupportedOptions2 &
+	  AAC_OPTION_DOORBELL_RESET)) &&
 	  aac_check_reset &&
 	  ((aac_check_reset != 1) ||
 	   !(aac->supplement_adapter_info.SupportedOptions2 &
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/Makefile linux-libre-2.6.39-gnu/drivers/scsi/aacraid/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -3,6 +3,6 @@
 obj-$(CONFIG_SCSI_AACRAID) := aacraid.o
 
 aacraid-objs	:= linit.o aachba.o commctrl.o comminit.o commsup.o \
-		   dpcsup.o rx.o sa.o rkt.o nark.o
+		   dpcsup.o rx.o sa.o rkt.o nark.o src.o
 
-EXTRA_CFLAGS	:= -Idrivers/scsi
+ccflags-y	:= -Idrivers/scsi
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/nark.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/nark.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/nark.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/nark.c	2011-05-19 00:06:34.000000000 -0400
@@ -4,7 +4,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2006-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/rkt.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/rkt.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/rkt.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/rkt.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/rx.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/rx.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/rx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/rx.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -84,15 +85,35 @@
 
 static irqreturn_t aac_rx_intr_message(int irq, void *dev_id)
 {
+	int isAif, isFastResponse, isSpecial;
 	struct aac_dev *dev = dev_id;
 	u32 Index = rx_readl(dev, MUnit.OutboundQueue);
 	if (unlikely(Index == 0xFFFFFFFFL))
 		Index = rx_readl(dev, MUnit.OutboundQueue);
 	if (likely(Index != 0xFFFFFFFFL)) {
 		do {
-			if (unlikely(aac_intr_normal(dev, Index))) {
-				rx_writel(dev, MUnit.OutboundQueue, Index);
-				rx_writel(dev, MUnit.ODR, DoorBellAdapterNormRespReady);
+			isAif = isFastResponse = isSpecial = 0;
+			if (Index & 0x00000002L) {
+				isAif = 1;
+				if (Index == 0xFFFFFFFEL)
+					isSpecial = 1;
+				Index &= ~0x00000002L;
+			} else {
+				if (Index & 0x00000001L)
+					isFastResponse = 1;
+				Index >>= 2;
+			}
+			if (!isSpecial) {
+				if (unlikely(aac_intr_normal(dev,
+						Index, isAif,
+						isFastResponse, NULL))) {
+					rx_writel(dev,
+						MUnit.OutboundQueue,
+						Index);
+					rx_writel(dev,
+						MUnit.ODR,
+						DoorBellAdapterNormRespReady);
+				}
 			}
 			Index = rx_readl(dev, MUnit.OutboundQueue);
 		} while (Index != 0xFFFFFFFFL);
@@ -631,6 +652,10 @@
 			name, instance);
 		goto error_iounmap;
 	}
+	dev->dbg_base = dev->scsi_host_ptr->base;
+	dev->dbg_base_mapped = dev->base;
+	dev->dbg_size = dev->base_size;
+
 	aac_adapter_enable_int(dev);
 	/*
 	 *	Tell the adapter that all is configured, and it can
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/sa.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/sa.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/sa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/sa.c	2011-05-19 00:06:34.000000000 -0400
@@ -5,7 +5,8 @@
  * based on the old aacraid driver that is..
  * Adaptec aacraid device driver for Linux.
  *
- * Copyright (c) 2000-2007 Adaptec, Inc. (aacraid@adaptec.com)
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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
@@ -391,6 +392,10 @@
 			name, instance);
 		goto error_iounmap;
 	}
+	dev->dbg_base = dev->scsi_host_ptr->base;
+	dev->dbg_base_mapped = dev->base;
+	dev->dbg_size = dev->base_size;
+
 	aac_adapter_enable_int(dev);
 
 	/*
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aacraid/src.c linux-libre-2.6.39-gnu/drivers/scsi/aacraid/src.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aacraid/src.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/aacraid/src.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,594 @@
+/*
+ *	Adaptec AAC series RAID controller driver
+ *	(c) Copyright 2001 Red Hat Inc.
+ *
+ * based on the old aacraid driver that is..
+ * Adaptec aacraid device driver for Linux.
+ *
+ * Copyright (c) 2000-2010 Adaptec, Inc.
+ *               2010 PMC-Sierra, Inc. (aacraid@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, 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, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * Module Name:
+ *  src.c
+ *
+ * Abstract: Hardware Device Interface for PMC SRC based controllers
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/pci.h>
+#include <linux/spinlock.h>
+#include <linux/slab.h>
+#include <linux/blkdev.h>
+#include <linux/delay.h>
+#include <linux/version.h>
+#include <linux/completion.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <scsi/scsi_host.h>
+
+#include "aacraid.h"
+
+static irqreturn_t aac_src_intr_message(int irq, void *dev_id)
+{
+	struct aac_dev *dev = dev_id;
+	unsigned long bellbits, bellbits_shifted;
+	int our_interrupt = 0;
+	int isFastResponse;
+	u32 index, handle;
+
+	bellbits = src_readl(dev, MUnit.ODR_R);
+	if (bellbits & PmDoorBellResponseSent) {
+		bellbits = PmDoorBellResponseSent;
+		/* handle async. status */
+		our_interrupt = 1;
+		index = dev->host_rrq_idx;
+		if (dev->host_rrq[index] == 0) {
+			u32 old_index = index;
+			/* adjust index */
+			do {
+				index++;
+				if (index == dev->scsi_host_ptr->can_queue +
+							AAC_NUM_MGT_FIB)
+					index = 0;
+				if (dev->host_rrq[index] != 0)
+					break;
+			} while (index != old_index);
+			dev->host_rrq_idx = index;
+		}
+		for (;;) {
+			isFastResponse = 0;
+			/* remove toggle bit (31) */
+			handle = (dev->host_rrq[index] & 0x7fffffff);
+			/* check fast response bit (30) */
+			if (handle & 0x40000000)
+				isFastResponse = 1;
+			handle &= 0x0000ffff;
+			if (handle == 0)
+				break;
+
+			aac_intr_normal(dev, handle-1, 0, isFastResponse, NULL);
+
+			dev->host_rrq[index++] = 0;
+			if (index == dev->scsi_host_ptr->can_queue +
+						AAC_NUM_MGT_FIB)
+				index = 0;
+			dev->host_rrq_idx = index;
+		}
+	} else {
+		bellbits_shifted = (bellbits >> SRC_ODR_SHIFT);
+		if (bellbits_shifted & DoorBellAifPending) {
+			our_interrupt = 1;
+			/* handle AIF */
+			aac_intr_normal(dev, 0, 2, 0, NULL);
+		}
+	}
+
+	if (our_interrupt) {
+		src_writel(dev, MUnit.ODR_C, bellbits);
+		return IRQ_HANDLED;
+	}
+	return IRQ_NONE;
+}
+
+/**
+ *	aac_src_disable_interrupt	-	Disable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_src_disable_interrupt(struct aac_dev *dev)
+{
+	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
+}
+
+/**
+ *	aac_src_enable_interrupt_message	-	Enable interrupts
+ *	@dev: Adapter
+ */
+
+static void aac_src_enable_interrupt_message(struct aac_dev *dev)
+{
+	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xfffffff8);
+}
+
+/**
+ *	src_sync_cmd	-	send a command and wait
+ *	@dev: Adapter
+ *	@command: Command to execute
+ *	@p1: first parameter
+ *	@ret: adapter status
+ *
+ *	This routine will send a synchronous command to the adapter and wait
+ *	for its	completion.
+ */
+
+static int src_sync_cmd(struct aac_dev *dev, u32 command,
+	u32 p1, u32 p2, u32 p3, u32 p4, u32 p5, u32 p6,
+	u32 *status, u32 * r1, u32 * r2, u32 * r3, u32 * r4)
+{
+	unsigned long start;
+	int ok;
+
+	/*
+	 *	Write the command into Mailbox 0
+	 */
+	writel(command, &dev->IndexRegs->Mailbox[0]);
+	/*
+	 *	Write the parameters into Mailboxes 1 - 6
+	 */
+	writel(p1, &dev->IndexRegs->Mailbox[1]);
+	writel(p2, &dev->IndexRegs->Mailbox[2]);
+	writel(p3, &dev->IndexRegs->Mailbox[3]);
+	writel(p4, &dev->IndexRegs->Mailbox[4]);
+
+	/*
+	 *	Clear the synch command doorbell to start on a clean slate.
+	 */
+	src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
+
+	/*
+	 *	Disable doorbell interrupts
+	 */
+	src_writel(dev, MUnit.OIMR, dev->OIMR = 0xffffffff);
+
+	/*
+	 *	Force the completion of the mask register write before issuing
+	 *	the interrupt.
+	 */
+	src_readl(dev, MUnit.OIMR);
+
+	/*
+	 *	Signal that there is a new synch command
+	 */
+	src_writel(dev, MUnit.IDR, INBOUNDDOORBELL_0 << SRC_IDR_SHIFT);
+
+	ok = 0;
+	start = jiffies;
+
+	/*
+	 *	Wait up to 30 seconds
+	 */
+	while (time_before(jiffies, start+30*HZ)) {
+		/* Delay 5 microseconds to let Mon960 get info. */
+		udelay(5);
+
+		/* Mon960 will set doorbell0 bit
+		 * when it has completed the command
+		 */
+		if ((src_readl(dev, MUnit.ODR_R) >> SRC_ODR_SHIFT) & OUTBOUNDDOORBELL_0) {
+			/* Clear the doorbell */
+			src_writel(dev,
+				MUnit.ODR_C,
+				OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
+			ok = 1;
+			break;
+		}
+
+		 /* Yield the processor in case we are slow */
+		msleep(1);
+	}
+	if (unlikely(ok != 1)) {
+		 /* Restore interrupt mask even though we timed out */
+		aac_adapter_enable_int(dev);
+		return -ETIMEDOUT;
+	}
+
+	 /* Pull the synch status from Mailbox 0 */
+	if (status)
+		*status = readl(&dev->IndexRegs->Mailbox[0]);
+	if (r1)
+		*r1 = readl(&dev->IndexRegs->Mailbox[1]);
+	if (r2)
+		*r2 = readl(&dev->IndexRegs->Mailbox[2]);
+	if (r3)
+		*r3 = readl(&dev->IndexRegs->Mailbox[3]);
+	if (r4)
+		*r4 = readl(&dev->IndexRegs->Mailbox[4]);
+
+	 /* Clear the synch command doorbell */
+	src_writel(dev, MUnit.ODR_C, OUTBOUNDDOORBELL_0 << SRC_ODR_SHIFT);
+
+	 /* Restore interrupt mask */
+	aac_adapter_enable_int(dev);
+	return 0;
+
+}
+
+/**
+ *	aac_src_interrupt_adapter	-	interrupt adapter
+ *	@dev: Adapter
+ *
+ *	Send an interrupt to the i960 and breakpoint it.
+ */
+
+static void aac_src_interrupt_adapter(struct aac_dev *dev)
+{
+	src_sync_cmd(dev, BREAKPOINT_REQUEST,
+		0, 0, 0, 0, 0, 0,
+		NULL, NULL, NULL, NULL, NULL);
+}
+
+/**
+ *	aac_src_notify_adapter		-	send an event to the adapter
+ *	@dev: Adapter
+ *	@event: Event to send
+ *
+ *	Notify the i960 that something it probably cares about has
+ *	happened.
+ */
+
+static void aac_src_notify_adapter(struct aac_dev *dev, u32 event)
+{
+	switch (event) {
+
+	case AdapNormCmdQue:
+		src_writel(dev, MUnit.ODR_C,
+			INBOUNDDOORBELL_1 << SRC_ODR_SHIFT);
+		break;
+	case HostNormRespNotFull:
+		src_writel(dev, MUnit.ODR_C,
+			INBOUNDDOORBELL_4 << SRC_ODR_SHIFT);
+		break;
+	case AdapNormRespQue:
+		src_writel(dev, MUnit.ODR_C,
+			INBOUNDDOORBELL_2 << SRC_ODR_SHIFT);
+		break;
+	case HostNormCmdNotFull:
+		src_writel(dev, MUnit.ODR_C,
+			INBOUNDDOORBELL_3 << SRC_ODR_SHIFT);
+		break;
+	case FastIo:
+		src_writel(dev, MUnit.ODR_C,
+			INBOUNDDOORBELL_6 << SRC_ODR_SHIFT);
+		break;
+	case AdapPrintfDone:
+		src_writel(dev, MUnit.ODR_C,
+			INBOUNDDOORBELL_5 << SRC_ODR_SHIFT);
+		break;
+	default:
+		BUG();
+		break;
+	}
+}
+
+/**
+ *	aac_src_start_adapter		-	activate adapter
+ *	@dev:	Adapter
+ *
+ *	Start up processing on an i960 based AAC adapter
+ */
+
+static void aac_src_start_adapter(struct aac_dev *dev)
+{
+	struct aac_init *init;
+
+	init = dev->init;
+	init->HostElapsedSeconds = cpu_to_le32(get_seconds());
+
+	/* We can only use a 32 bit address here */
+	src_sync_cmd(dev, INIT_STRUCT_BASE_ADDRESS, (u32)(ulong)dev->init_pa,
+	  0, 0, 0, 0, 0, NULL, NULL, NULL, NULL, NULL);
+}
+
+/**
+ *	aac_src_check_health
+ *	@dev: device to check if healthy
+ *
+ *	Will attempt to determine if the specified adapter is alive and
+ *	capable of handling requests, returning 0 if alive.
+ */
+static int aac_src_check_health(struct aac_dev *dev)
+{
+	u32 status = src_readl(dev, MUnit.OMR);
+
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	if (unlikely(status & SELF_TEST_FAILED))
+		return -1;
+
+	/*
+	 *	Check to see if the board panic'd.
+	 */
+	if (unlikely(status & KERNEL_PANIC))
+		return (status >> 16) & 0xFF;
+	/*
+	 *	Wait for the adapter to be up and running.
+	 */
+	if (unlikely(!(status & KERNEL_UP_AND_RUNNING)))
+		return -3;
+	/*
+	 *	Everything is OK
+	 */
+	return 0;
+}
+
+/**
+ *	aac_src_deliver_message
+ *	@fib: fib to issue
+ *
+ *	Will send a fib, returning 0 if successful.
+ */
+static int aac_src_deliver_message(struct fib *fib)
+{
+	struct aac_dev *dev = fib->dev;
+	struct aac_queue *q = &dev->queues->queue[AdapNormCmdQueue];
+	unsigned long qflags;
+	u32 fibsize;
+	u64 address;
+	struct aac_fib_xporthdr *pFibX;
+
+	spin_lock_irqsave(q->lock, qflags);
+	q->numpending++;
+	spin_unlock_irqrestore(q->lock, qflags);
+
+	/* Calculate the amount to the fibsize bits */
+	fibsize = (sizeof(struct aac_fib_xporthdr) +
+		fib->hw_fib_va->header.Size + 127) / 128 - 1;
+	if (fibsize > (ALIGN32 - 1))
+		fibsize = ALIGN32 - 1;
+
+    /* Fill XPORT header */
+	pFibX = (struct aac_fib_xporthdr *)
+		((unsigned char *)fib->hw_fib_va -
+		sizeof(struct aac_fib_xporthdr));
+	pFibX->Handle = fib->hw_fib_va->header.SenderData + 1;
+	pFibX->HostAddress = fib->hw_fib_pa;
+	pFibX->Size = fib->hw_fib_va->header.Size;
+	address = fib->hw_fib_pa - (u64)sizeof(struct aac_fib_xporthdr);
+
+	src_writel(dev, MUnit.IQ_H, (u32)(address >> 32));
+	src_writel(dev, MUnit.IQ_L, (u32)(address & 0xffffffff) + fibsize);
+	return 0;
+}
+
+/**
+ *	aac_src_ioremap
+ *	@size: mapping resize request
+ *
+ */
+static int aac_src_ioremap(struct aac_dev *dev, u32 size)
+{
+	if (!size) {
+		iounmap(dev->regs.src.bar0);
+		dev->regs.src.bar0 = NULL;
+		iounmap(dev->base);
+		dev->base = NULL;
+		return 0;
+	}
+	dev->regs.src.bar1 = ioremap(pci_resource_start(dev->pdev, 2),
+		AAC_MIN_SRC_BAR1_SIZE);
+	dev->base = NULL;
+	if (dev->regs.src.bar1 == NULL)
+		return -1;
+	dev->base = dev->regs.src.bar0 = ioremap(dev->scsi_host_ptr->base,
+				size);
+	if (dev->base == NULL) {
+		iounmap(dev->regs.src.bar1);
+		dev->regs.src.bar1 = NULL;
+		return -1;
+	}
+	dev->IndexRegs = &((struct src_registers __iomem *)
+		dev->base)->IndexRegs;
+	return 0;
+}
+
+static int aac_src_restart_adapter(struct aac_dev *dev, int bled)
+{
+	u32 var, reset_mask;
+
+	if (bled >= 0) {
+		if (bled)
+			printk(KERN_ERR "%s%d: adapter kernel panic'd %x.\n",
+				dev->name, dev->id, bled);
+		bled = aac_adapter_sync_cmd(dev, IOP_RESET_ALWAYS,
+			0, 0, 0, 0, 0, 0, &var, &reset_mask, NULL, NULL, NULL);
+			if (bled || (var != 0x00000001))
+				bled = -EINVAL;
+		if (dev->supplement_adapter_info.SupportedOptions2 &
+			AAC_OPTION_DOORBELL_RESET) {
+			src_writel(dev, MUnit.IDR, reset_mask);
+			msleep(5000); /* Delay 5 seconds */
+		}
+	}
+
+	if (src_readl(dev, MUnit.OMR) & KERNEL_PANIC)
+		return -ENODEV;
+
+	if (startup_timeout < 300)
+		startup_timeout = 300;
+
+	return 0;
+}
+
+/**
+ *	aac_src_select_comm	-	Select communications method
+ *	@dev: Adapter
+ *	@comm: communications method
+ */
+int aac_src_select_comm(struct aac_dev *dev, int comm)
+{
+	switch (comm) {
+	case AAC_COMM_MESSAGE:
+		dev->a_ops.adapter_enable_int = aac_src_enable_interrupt_message;
+		dev->a_ops.adapter_intr = aac_src_intr_message;
+		dev->a_ops.adapter_deliver = aac_src_deliver_message;
+		break;
+	default:
+		return 1;
+	}
+	return 0;
+}
+
+/**
+ *  aac_src_init	-	initialize an Cardinal Frey Bar card
+ *  @dev: device to configure
+ *
+ */
+
+int aac_src_init(struct aac_dev *dev)
+{
+	unsigned long start;
+	unsigned long status;
+	int restart = 0;
+	int instance = dev->id;
+	const char *name = dev->name;
+
+	dev->a_ops.adapter_ioremap = aac_src_ioremap;
+	dev->a_ops.adapter_comm = aac_src_select_comm;
+
+	dev->base_size = AAC_MIN_SRC_BAR0_SIZE;
+	if (aac_adapter_ioremap(dev, dev->base_size)) {
+		printk(KERN_WARNING "%s: unable to map adapter.\n", name);
+		goto error_iounmap;
+	}
+
+	/* Failure to reset here is an option ... */
+	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
+	dev->a_ops.adapter_enable_int = aac_src_disable_interrupt;
+	if ((aac_reset_devices || reset_devices) &&
+		!aac_src_restart_adapter(dev, 0))
+		++restart;
+	/*
+	 *	Check to see if the board panic'd while booting.
+	 */
+	status = src_readl(dev, MUnit.OMR);
+	if (status & KERNEL_PANIC) {
+		if (aac_src_restart_adapter(dev, aac_src_check_health(dev)))
+			goto error_iounmap;
+		++restart;
+	}
+	/*
+	 *	Check to see if the board failed any self tests.
+	 */
+	status = src_readl(dev, MUnit.OMR);
+	if (status & SELF_TEST_FAILED) {
+		printk(KERN_ERR "%s%d: adapter self-test failed.\n",
+			dev->name, instance);
+		goto error_iounmap;
+	}
+	/*
+	 *	Check to see if the monitor panic'd while booting.
+	 */
+	if (status & MONITOR_PANIC) {
+		printk(KERN_ERR "%s%d: adapter monitor panic.\n",
+			dev->name, instance);
+		goto error_iounmap;
+	}
+	start = jiffies;
+	/*
+	 *	Wait for the adapter to be up and running. Wait up to 3 minutes
+	 */
+	while (!((status = src_readl(dev, MUnit.OMR)) &
+		KERNEL_UP_AND_RUNNING)) {
+		if ((restart &&
+		  (status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC))) ||
+		  time_after(jiffies, start+HZ*startup_timeout)) {
+			printk(KERN_ERR "%s%d: adapter kernel failed to start, init status = %lx.\n",
+					dev->name, instance, status);
+			goto error_iounmap;
+		}
+		if (!restart &&
+		  ((status & (KERNEL_PANIC|SELF_TEST_FAILED|MONITOR_PANIC)) ||
+		  time_after(jiffies, start + HZ *
+		  ((startup_timeout > 60)
+		    ? (startup_timeout - 60)
+		    : (startup_timeout / 2))))) {
+			if (likely(!aac_src_restart_adapter(dev,
+			    aac_src_check_health(dev))))
+				start = jiffies;
+			++restart;
+		}
+		msleep(1);
+	}
+	if (restart && aac_commit)
+		aac_commit = 1;
+	/*
+	 *	Fill in the common function dispatch table.
+	 */
+	dev->a_ops.adapter_interrupt = aac_src_interrupt_adapter;
+	dev->a_ops.adapter_disable_int = aac_src_disable_interrupt;
+	dev->a_ops.adapter_notify = aac_src_notify_adapter;
+	dev->a_ops.adapter_sync_cmd = src_sync_cmd;
+	dev->a_ops.adapter_check_health = aac_src_check_health;
+	dev->a_ops.adapter_restart = aac_src_restart_adapter;
+
+	/*
+	 *	First clear out all interrupts.  Then enable the one's that we
+	 *	can handle.
+	 */
+	aac_adapter_comm(dev, AAC_COMM_MESSAGE);
+	aac_adapter_disable_int(dev);
+	src_writel(dev, MUnit.ODR_C, 0xffffffff);
+	aac_adapter_enable_int(dev);
+
+	if (aac_init_adapter(dev) == NULL)
+		goto error_iounmap;
+	if (dev->comm_interface != AAC_COMM_MESSAGE_TYPE1)
+		goto error_iounmap;
+
+	dev->msi = aac_msi && !pci_enable_msi(dev->pdev);
+
+	if (request_irq(dev->pdev->irq, dev->a_ops.adapter_intr,
+			IRQF_SHARED|IRQF_DISABLED, "aacraid", dev) < 0) {
+
+		if (dev->msi)
+			pci_disable_msi(dev->pdev);
+
+		printk(KERN_ERR "%s%d: Interrupt unavailable.\n",
+			name, instance);
+		goto error_iounmap;
+	}
+	dev->dbg_base = pci_resource_start(dev->pdev, 2);
+	dev->dbg_base_mapped = dev->regs.src.bar1;
+	dev->dbg_size = AAC_MIN_SRC_BAR1_SIZE;
+
+	aac_adapter_enable_int(dev);
+	/*
+	 *	Tell the adapter that all is configured, and it can
+	 * start accepting requests
+	 */
+	aac_src_start_adapter(dev);
+
+	return 0;
+
+error_iounmap:
+
+	return -1;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/advansys.c linux-libre-2.6.39-gnu/drivers/scsi/advansys.c
--- linux-libre-2.6.38-gnu/drivers/scsi/advansys.c	2012-03-24 01:17:54.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/advansys.c	2012-03-24 03:36:27.000000000 -0400
@@ -4544,7 +4544,7 @@
  * Copy 4 bytes to LRAM.
  *
  * The source data is assumed to be in little-endian order in memory
- * and is maintained in little-endian order when writen to LRAM.
+ * and is maintained in little-endian order when written to LRAM.
  */
 static void
 AscMemDWordCopyPtrToLram(PortAddr iop_base,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aha1740.c linux-libre-2.6.39-gnu/drivers/scsi/aha1740.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aha1740.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aha1740.c	2011-05-19 00:06:34.000000000 -0400
@@ -461,7 +461,7 @@
 	/* The Adaptec Spec says the card is so fast that the loops
            will only be executed once in the code below. Even if this
            was true with the fastest processors when the spec was
-           written, it doesn't seem to be true with todays fast
+           written, it doesn't seem to be true with today's fast
            processors. We print a warning if the code is executed more
            often than LOOPCNT_WARN. If this happens, it should be
            investigated. If the count reaches LOOPCNT_MAX, we assume
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx_core.c linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx_core.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -562,7 +562,7 @@
 }
 #endif
 
-/*********************** Miscelaneous Support Functions ***********************/
+/*********************** Miscellaneous Support Functions ***********************/
 /*
  * Return pointers to the transfer negotiation information
  * for the specified our_id/remote_id pair.
@@ -599,7 +599,7 @@
 ahd_outw(struct ahd_softc *ahd, u_int port, u_int value)
 {
 	/*
-	 * Write low byte first to accomodate registers
+	 * Write low byte first to accommodate registers
 	 * such as PRGMCNT where the order maters.
 	 */
 	ahd_outb(ahd, port, value & 0xFF);
@@ -2067,7 +2067,7 @@
 		 * that requires host assistance for completion.
 		 * While handling the message phase(s), we will be
 		 * notified by the sequencer after each byte is
-		 * transfered so we can track bus phase changes.
+		 * transferred so we can track bus phase changes.
 		 *
 		 * If this is the first time we've seen a HOST_MSG_LOOP
 		 * interrupt, initialize the state of the host message
@@ -2487,7 +2487,7 @@
 		/*
 		 * Although the driver does not care about the
 		 * 'Selection in Progress' status bit, the busy
-		 * LED does.  SELINGO is only cleared by a successfull
+		 * LED does.  SELINGO is only cleared by a successful
 		 * selection, so we must manually clear it to insure
 		 * the LED turns off just incase no future successful
 		 * selections occur (e.g. no devices on the bus).
@@ -3548,7 +3548,7 @@
 		ahd_outb(ahd, SEQCTL0, ahd_inb(ahd, SEQCTL0) & ~STEP);
   		ahd_outb(ahd, SIMODE1, simode1);
 		/*
-		 * SCSIINT seems to glitch occassionally when
+		 * SCSIINT seems to glitch occasionally when
 		 * the interrupt masks are restored.  Clear SCSIINT
 		 * one more time so that only persistent errors
 		 * are seen as a real interrupt.
@@ -3838,7 +3838,7 @@
 
 /*
  * Update the bitmask of targets for which the controller should
- * negotiate with at the next convenient oportunity.  This currently
+ * negotiate with at the next convenient opportunity.  This currently
  * means the next time we send the initial identify messages for
  * a new transaction.
  */
@@ -4200,7 +4200,7 @@
 
 	/*
 	 * During packetized transfers, the target will
-	 * give us the oportunity to send command packets
+	 * give us the opportunity to send command packets
 	 * without us asserting attention.
 	 */
 	if ((tinfo->ppr_options & MSG_EXT_PPR_IU_REQ) == 0)
@@ -5651,7 +5651,7 @@
 
 		/*
 		 * Requeue all tagged commands for this target
-		 * currently in our posession so they can be
+		 * currently in our possession so they can be
 		 * converted to untagged commands.
 		 */
 		ahd_search_qinfifo(ahd, SCB_GET_TARGET(ahd, scb),
@@ -6245,7 +6245,7 @@
 /*
  * Reset the controller and record some information about it
  * that is only available just after a reset.  If "reinit" is
- * non-zero, this reset occured after initial configuration
+ * non-zero, this reset occurred after initial configuration
  * and the caller requests that the chip be fully reinitialized
  * to a runable state.  Chip interrupts are *not* enabled after
  * a reinitialization.  The caller must enable interrupts via
@@ -6495,7 +6495,7 @@
 	}
 
 	/*
-	 * Note that we were successfull
+	 * Note that we were successful
 	 */
 	return (0); 
 
@@ -7079,7 +7079,7 @@
 		return (ENOMEM);
 
 	/*
-	 * Verify that the compiler hasn't over-agressively
+	 * Verify that the compiler hasn't over-aggressively
 	 * padded important structures.
 	 */
 	if (sizeof(struct hardware_scb) != 64)
@@ -10087,7 +10087,7 @@
 		return (error);
 
 	/*
-	 * Write the data.  If we don't get throught the loop at
+	 * Write the data.  If we don't get through the loop at
 	 * least once, the arguments were invalid.
 	 */
 	retval = EINVAL;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx.h linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx.h
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx.h	2011-05-19 00:06:34.000000000 -0400
@@ -473,7 +473,7 @@
  *	o A residual has occurred if SG_FULL_RESID is set in sgptr,
  *	  or residual_sgptr does not have SG_LIST_NULL set.
  *
- *	o We are transfering the last segment if residual_datacnt has
+ *	o We are transferring the last segment if residual_datacnt has
  *	  the SG_LAST_SEG flag set.
  *
  * Host:
@@ -516,7 +516,7 @@
  */
 
 /*
- * Definition of a scatter/gather element as transfered to the controller.
+ * Definition of a scatter/gather element as transferred to the controller.
  * The aic7xxx chips only support a 24bit length.  We use the top byte of
  * the length to store additional address bits and a flag to indicate
  * that a given segment terminates the transfer.  This gives us an
@@ -672,7 +672,7 @@
 /************************ Target Mode Definitions *****************************/
 
 /*
- * Connection desciptor for select-in requests in target mode.
+ * Connection descriptor for select-in requests in target mode.
  */
 struct target_cmd {
 	uint8_t scsiid;		/* Our ID and the initiator's ID */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx_osm.c	2011-05-19 00:06:34.000000000 -0400
@@ -1441,7 +1441,7 @@
 		usertags = ahd_linux_user_tagdepth(ahd, devinfo);
 		if (!was_queuing) {
 			/*
-			 * Start out agressively and allow our
+			 * Start out aggressively and allow our
 			 * dynamic queue depth algorithm to take
 			 * care of the rest.
 			 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx.reg linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx.reg
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx.reg	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx.reg	2011-05-19 00:06:34.000000000 -0400
@@ -305,7 +305,7 @@
 }
 
 /*
- * Sequencer Interupt Status
+ * Sequencer Interrupt Status
  */
 register SEQINTSTAT {
 	address			0x00C
@@ -685,7 +685,7 @@
 }
 
 /*
- * CMC Recieve Message 0
+ * CMC Receive Message 0
  */
 register CMCRXMSG0 {
 	address			0x090
@@ -696,7 +696,7 @@
 }
 
 /*
- * Overlay Recieve Message 0
+ * Overlay Receive Message 0
  */
 register OVLYRXMSG0 {
 	address			0x090
@@ -732,7 +732,7 @@
 }
 
 /*
- * CMC Recieve Message 1
+ * CMC Receive Message 1
  */
 register CMCRXMSG1 {
 	address			0x091
@@ -742,7 +742,7 @@
 }
 
 /*
- * Overlay Recieve Message 1
+ * Overlay Receive Message 1
  */
 register OVLYRXMSG1 {
 	address			0x091
@@ -777,7 +777,7 @@
 }
 
 /*
- * CMC Recieve Message 2
+ * CMC Receive Message 2
  */
 register CMCRXMSG2 {
 	address			0x092
@@ -787,7 +787,7 @@
 }
 
 /*
- * Overlay Recieve Message 2
+ * Overlay Receive Message 2
  */
 register OVLYRXMSG2 {
 	address			0x092
@@ -816,7 +816,7 @@
 }
 
 /*
- * CMC Recieve Message 3
+ * CMC Receive Message 3
  */
 register CMCRXMSG3 {
 	address			0x093
@@ -826,7 +826,7 @@
 }
 
 /*
- * Overlay Recieve Message 3
+ * Overlay Receive Message 3
  */
 register OVLYRXMSG3 {
 	address			0x093
@@ -1249,7 +1249,7 @@
 
 /*
  * LQ Packet In
- * The last LQ Packet recieved
+ * The last LQ Packet received
  */
 register LQIN {
 	address			0x020
@@ -2573,7 +2573,7 @@
 }
 
 /*
- * Shaddow Host Address.
+ * Shadow Host Address.
  */
 register SHADDR {
 	address			0x060
@@ -3983,7 +3983,7 @@
 
 	/*
 	 * The maximum amount of time to wait, when interrupt coalescing
-	 * is enabled, before issueing a CMDCMPLT interrupt for a completed
+	 * is enabled, before issuing a CMDCMPLT interrupt for a completed
 	 * command.
 	 */
 	INT_COALESCING_TIMER {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx.seq linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx.seq
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic79xx.seq	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic79xx.seq	2011-05-19 00:06:34.000000000 -0400
@@ -567,7 +567,7 @@
 	shr	SELOID, 4, SCB_SCSIID;
 	/*
 	 * If we want to send a message to the device, ensure
-	 * we are selecting with atn irregardless of our packetized
+	 * we are selecting with atn regardless of our packetized
 	 * agreement.  Since SPI4 only allows target reset or PPR
 	 * messages if this is a packetized connection, the change
 	 * to our negotiation table entry for this selection will
@@ -960,7 +960,7 @@
  * This is done to allow the host to send messages outside of an identify
  * sequence while protecting the seqencer from testing the MK_MESSAGE bit
  * on an SCB that might not be for the current nexus. (For example, a
- * BDR message in responce to a bad reselection would leave us pointed to
+ * BDR message in response to a bad reselection would leave us pointed to
  * an SCB that doesn't have anything to do with the current target).
  *
  * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
@@ -1507,7 +1507,7 @@
 		 * If the other FIFO needs loading, then it
 		 * must not have claimed the S/G cache yet
 		 * (SG_CACHE_AVAIL would have been cleared in
-		 * the orginal FIFO mode and we test this above).
+		 * the original FIFO mode and we test this above).
 		 * Return to the idle loop so we can process the
 		 * FIFO not currently on the bus first.
 		 */
@@ -1521,7 +1521,7 @@
 idle_sgfetch_start:
 	/*
 	 * We fetch a "cacheline aligned" and sized amount of data
-	 * so we don't end up referencing a non-existant page.
+	 * so we don't end up referencing a non-existent page.
 	 * Cacheline aligned is in quotes because the kernel will
 	 * set the prefetch amount to a reasonable level if the
 	 * cacheline size is unknown.
@@ -1551,7 +1551,7 @@
 	test	DFSTATUS, PRELOAD_AVAIL jz return;
 	/*
 	 * On the A, preloading a segment before HDMAENACK
-	 * comes true can clobber the shaddow address of the
+	 * comes true can clobber the shadow address of the
 	 * first segment in the S/G FIFO.  Wait until it is
 	 * safe to proceed.
 	 */
@@ -2004,10 +2004,10 @@
 	 * Defer handling of this NONPACKREQ until we
 	 * can be sure it pertains to this FIFO.  SAVEPTRS
 	 * will not be asserted if the NONPACKREQ is for us,
-	 * so we must simulate it if shaddow is valid.  If
-	 * shaddow is not valid, keep running this FIFO until we
+	 * so we must simulate it if shadow is valid.  If
+	 * shadow is not valid, keep running this FIFO until we
 	 * have satisfied the transfer by loading segments and
-	 * waiting for either shaddow valid or last_seg_done.
+	 * waiting for either shadow valid or last_seg_done.
 	 */
 	test	MDFFSTAT, SHVALID jnz pkt_saveptrs;
 pkt_service_fifo:
@@ -2171,7 +2171,7 @@
 	/*
 	 * The unexpected nonpkt phase handler assumes that any
 	 * data channel use will have a FIFO reference count.  It
-	 * turns out that the status handler doesn't need a refernce
+	 * turns out that the status handler doesn't need a references
 	 * count since the status received flag, and thus completion
 	 * processing, cannot be set until the handler is finished.
 	 * We increment the count here to make the nonpkt handler
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx_core.c linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx_core.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -427,7 +427,7 @@
 }
 #endif
 
-/*********************** Miscelaneous Support Functions ***********************/
+/*********************** Miscellaneous Support Functions ***********************/
 /*
  * Determine whether the sequencer reported a residual
  * for this SCB/transaction.
@@ -1243,7 +1243,7 @@
 		 * that requires host assistance for completion.
 		 * While handling the message phase(s), we will be
 		 * notified by the sequencer after each byte is
-		 * transfered so we can track bus phase changes.
+		 * transferred so we can track bus phase changes.
 		 *
 		 * If this is the first time we've seen a HOST_MSG_LOOP
 		 * interrupt, initialize the state of the host message
@@ -1487,7 +1487,7 @@
 		       scbptr, ahc_inb(ahc, ARG_1),
 		       ahc->scb_data->hscbs[scbptr].tag);
 		ahc_dump_card_state(ahc);
-		panic("for saftey");
+		panic("for safety");
 		break;
 	}
 	case OUT_OF_RANGE:
@@ -1733,7 +1733,7 @@
 		/*
 		 * Although the driver does not care about the
 		 * 'Selection in Progress' status bit, the busy
-		 * LED does.  SELINGO is only cleared by a successfull
+		 * LED does.  SELINGO is only cleared by a successful
 		 * selection, so we must manually clear it to insure
 		 * the LED turns off just incase no future successful
 		 * selections occur (e.g. no devices on the bus).
@@ -1943,7 +1943,7 @@
 			if (lastphase != P_BUSFREE) {
 				/*
 				 * Renegotiate with this device at the
-				 * next oportunity just in case this busfree
+				 * next opportunity just in case this busfree
 				 * is due to a negotiation mismatch with the
 				 * device.
 				 */
@@ -2442,7 +2442,7 @@
 
 /*
  * Update the bitmask of targets for which the controller should
- * negotiate with at the next convenient oportunity.  This currently
+ * negotiate with at the next convenient opportunity.  This currently
  * means the next time we send the initial identify messages for
  * a new transaction.
  */
@@ -4131,7 +4131,7 @@
 
 		/*
 		 * Requeue all tagged commands for this target
-		 * currently in our posession so they can be
+		 * currently in our possession so they can be
 		 * converted to untagged commands.
 		 */
 		ahc_search_qinfifo(ahc, SCB_GET_TARGET(ahc, scb),
@@ -4581,7 +4581,7 @@
 /*
  * Reset the controller and record some information about it
  * that is only available just after a reset.  If "reinit" is
- * non-zero, this reset occured after initial configuration
+ * non-zero, this reset occurred after initial configuration
  * and the caller requests that the chip be fully reinitialized
  * to a runable state.  Chip interrupts are *not* enabled after
  * a reinitialization.  The caller must enable interrupts via
@@ -4780,7 +4780,7 @@
 	SLIST_INIT(&scb_data->sg_maps);
 
 	/* Allocate SCB resources */
-	scb_data->scbarray = (struct scb *)kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC);
+	scb_data->scbarray = kmalloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC, GFP_ATOMIC);
 	if (scb_data->scbarray == NULL)
 		return (ENOMEM);
 	memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC);
@@ -4899,7 +4899,7 @@
 	ahc->next_queued_scb = ahc_get_scb(ahc);
 
 	/*
-	 * Note that we were successfull
+	 * Note that we were successful
 	 */
 	return (0); 
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx.h linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx.h
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx.h	2011-05-19 00:06:34.000000000 -0400
@@ -440,7 +440,7 @@
  *	o A residual has occurred if SG_FULL_RESID is set in sgptr,
  *	  or residual_sgptr does not have SG_LIST_NULL set.
  *
- *	o We are transfering the last segment if residual_datacnt has
+ *	o We are transferring the last segment if residual_datacnt has
  *	  the SG_LAST_SEG flag set.
  *
  * Host:
@@ -494,7 +494,7 @@
  */
 
 /*
- * Definition of a scatter/gather element as transfered to the controller.
+ * Definition of a scatter/gather element as transferred to the controller.
  * The aic7xxx chips only support a 24bit length.  We use the top byte of
  * the length to store additional address bits and a flag to indicate
  * that a given segment terminates the transfer.  This gives us an
@@ -618,7 +618,7 @@
 /************************ Target Mode Definitions *****************************/
 
 /*
- * Connection desciptor for select-in requests in target mode.
+ * Connection descriptor for select-in requests in target mode.
  */
 struct target_cmd {
 	uint8_t scsiid;		/* Our ID and the initiator's ID */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx_osm.c	2011-05-19 00:06:34.000000000 -0400
@@ -294,7 +294,7 @@
  * dubious at best.  To my knowledge, this option has never actually
  * solved a PCI parity problem, but on certain machines with broken PCI
  * chipset configurations where stray PCI transactions with bad parity are
- * the norm rather than the exception, the error messages can be overwelming.
+ * the norm rather than the exception, the error messages can be overwhelming.
  * It's included in the driver for completeness.
  *   0	   = Shut off PCI parity check
  *   non-0 = reverse polarity pci parity checking
@@ -1318,7 +1318,7 @@
 		usertags = ahc_linux_user_tagdepth(ahc, devinfo);
 		if (!was_queuing) {
 			/*
-			 * Start out agressively and allow our
+			 * Start out aggressively and allow our
 			 * dynamic queue depth algorithm to take
 			 * care of the rest.
 			 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx_pci.c linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx_pci.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -789,7 +789,7 @@
 	ahc->bus_intr = ahc_pci_intr;
 	ahc->bus_chip_init = ahc_pci_chip_init;
 
-	/* Remeber how the card was setup in case there is no SEEPROM */
+	/* Remember how the card was setup in case there is no SEEPROM */
 	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
 		ahc_pause(ahc);
 		if ((ahc->features & AHC_ULTRA2) != 0)
@@ -860,7 +860,7 @@
 	}
 
 	/*
-	 * We cannot perform ULTRA speeds without the presense
+	 * We cannot perform ULTRA speeds without the presence
 	 * of the external precision resistor.
 	 */
 	if ((ahc->features & AHC_ULTRA) != 0) {
@@ -969,7 +969,7 @@
 }
 
 /*
- * Test for the presense of external sram in an
+ * Test for the presence of external sram in an
  * "unshared" configuration.
  */
 static int
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx.reg linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx.reg
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx.reg	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx.reg	2011-05-19 00:06:34.000000000 -0400
@@ -351,7 +351,7 @@
 	address			0x00d
 	access_mode RO
 	field	OVERRUN		0x80
-	field	SHVALID		0x40	/* Shaddow Layer non-zero */
+	field	SHVALID		0x40	/* Shadow Layer non-zero */
 	field	EXP_ACTIVE	0x10	/* SCSI Expander Active */
 	field	CRCVALERR	0x08	/* CRC doesn't match (U3 only) */
 	field	CRCENDERR	0x04	/* No terminal CRC packet (U3 only) */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx.seq linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx.seq
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aic7xxx.seq	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aic7xxx.seq	2011-05-19 00:06:34.000000000 -0400
@@ -57,10 +57,10 @@
  * a later time.  This problem cannot be resolved by holding a single entry
  * in scratch ram since a reconnecting target can request sense and this will
  * create yet another SCB waiting for selection.  The solution used here is to 
- * use byte 27 of the SCB as a psuedo-next pointer and to thread a list
+ * use byte 27 of the SCB as a pseudo-next pointer and to thread a list
  * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes, 
  * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to
- * this list everytime a request sense occurs or after completing a non-tagged
+ * this list every time a request sense occurs or after completing a non-tagged
  * command for which a second SCB has been queued.  The sequencer will
  * automatically consume the entries.
  */
@@ -752,7 +752,7 @@
 
 	/*
 	 * We fetch a "cacheline aligned" and sized amount of data
-	 * so we don't end up referencing a non-existant page.
+	 * so we don't end up referencing a non-existent page.
 	 * Cacheline aligned is in quotes because the kernel will
 	 * set the prefetch amount to a reasonable level if the
 	 * cacheline size is unknown.
@@ -1485,7 +1485,7 @@
  * This is done to allow the host to send messages outside of an identify
  * sequence while protecting the seqencer from testing the MK_MESSAGE bit
  * on an SCB that might not be for the current nexus. (For example, a
- * BDR message in responce to a bad reselection would leave us pointed to
+ * BDR message in response to a bad reselection would leave us pointed to
  * an SCB that doesn't have anything to do with the current target).
  *
  * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
@@ -1999,7 +1999,7 @@
  * from out to in, wait an additional data release delay before continuing.
  */
 change_phase:
-	/* Wait for preceeding I/O session to complete. */
+	/* Wait for preceding I/O session to complete. */
 	test	SCSISIGI, ACKI jnz .;
 
 	/* Change the phase */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_gram.y	2011-05-19 00:06:34.000000000 -0400
@@ -803,7 +803,7 @@
 |	macro_arglist ',' T_ARG
 	{
 		if ($1 == 0) {
-			stop("Comma without preceeding argument in arg list",
+			stop("Comma without preceding argument in arg list",
 			     EX_DATAERR);
 			/* NOTREACHED */
 		}
@@ -1319,8 +1319,8 @@
 ;
 
 	/*
-	 * This grammer differs from the one in the aic7xxx
-	 * reference manual since the grammer listed there is
+	 * This grammar differs from the one in the aic7xxx
+	 * reference manual since the grammar listed there is
 	 * ambiguous and causes a shift/reduce conflict.
 	 * It also seems more logical as the "immediate"
 	 * argument is listed as the second arg like the
@@ -1799,7 +1799,7 @@
 	instr = seq_alloc();
 	f3_instr = &instr->format.format3;
 	if (address->symbol == NULL) {
-		/* 'dot' referrence.  Use the current instruction pointer */
+		/* 'dot' reference.  Use the current instruction pointer */
 		addr = instruction_ptr + address->offset;
 	} else if (address->symbol->type == UNINITIALIZED) {
 		/* forward reference */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx/aicasm/aicasm_macro_gram.y	2011-05-19 00:06:34.000000000 -0400
@@ -115,7 +115,7 @@
 |	macro_arglist ',' T_ARG
 	{
 		if ($1 == 0) {
-			stop("Comma without preceeding argument in arg list",
+			stop("Comma without preceding argument in arg list",
 			     EX_DATAERR);
 			/* NOTREACHED */
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx_old/aic7xxx.seq linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx_old/aic7xxx.seq
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx_old/aic7xxx.seq	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx_old/aic7xxx.seq	2011-05-19 00:06:34.000000000 -0400
@@ -51,7 +51,7 @@
  * use byte 27 of the SCB as a pseudo-next pointer and to thread a list
  * of SCBs that are awaiting selection.  Since 0-0xfe are valid SCB indexes, 
  * SCB_LIST_NULL is 0xff which is out of range.  An entry is also added to
- * this list everytime a request sense occurs or after completing a non-tagged
+ * this list every time a request sense occurs or after completing a non-tagged
  * command for which a second SCB has been queued.  The sequencer will
  * automatically consume the entries.
  */
@@ -696,7 +696,7 @@
  * This is done to allow the hsot to send messages outside of an identify
  * sequence while protecting the seqencer from testing the MK_MESSAGE bit
  * on an SCB that might not be for the current nexus. (For example, a
- * BDR message in responce to a bad reselection would leave us pointed to
+ * BDR message in response to a bad reselection would leave us pointed to
  * an SCB that doesn't have anything to do with the current target).
  * Otherwise, treat MSG_OUT as a 1 byte message to send (abort, abort tag,
  * bus device reset).
@@ -716,8 +716,8 @@
 	} else {
 		and	SINDEX,0x7,SCB_TCL;	/* lun */
 	}
-	and	A,DISCENB,SCB_CONTROL;	/* mask off disconnect privledge */
-	or	SINDEX,A;		/* or in disconnect privledge */
+	and	A,DISCENB,SCB_CONTROL;	/* mask off disconnect privilege */
+	or	SINDEX,A;		/* or in disconnect privilege */
 	or	SINDEX,MSG_IDENTIFYFLAG;
 p_mesgout_mk_message:
 	test	SCB_CONTROL,MK_MESSAGE  jz p_mesgout_tag;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx_old.c linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx_old.c
--- linux-libre-2.6.38-gnu/drivers/scsi/aic7xxx_old.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic7xxx_old.c	2011-05-19 00:06:34.000000000 -0400
@@ -905,7 +905,7 @@
  * problems with architectures I can't test on (because I don't have one,
  * such as the Alpha based systems) which happen to give faults for
  * non-aligned memory accesses, care was taken to align this structure
- * in a way that gauranteed all accesses larger than 8 bits were aligned
+ * in a way that guaranteed all accesses larger than 8 bits were aligned
  * on the appropriate boundary.  It's also organized to try and be more
  * cache line efficient.  Be careful when changing this lest you might hurt
  * overall performance and bring down the wrath of the masses.
@@ -1180,7 +1180,7 @@
  * the card's registers in a hex dump format tailored to each model of
  * controller.
  * 
- * NOTE: THE CONTROLLER IS LEFT IN AN UNUSEABLE STATE BY THIS OPTION.
+ * NOTE: THE CONTROLLER IS LEFT IN AN UNUSABLE STATE BY THIS OPTION.
  *       YOU CANNOT BOOT UP WITH THIS OPTION, IT IS FOR DEBUGGING PURPOSES
  *       ONLY
  */
@@ -3467,7 +3467,7 @@
   /* Turn off the bus' current operations, after all, we shouldn't have any
    * valid commands left to cause a RSELI and SELO once we've tossed the
    * bus away with this reset, so we might as well shut down the sequencer
-   * until the bus is restarted as oppossed to saving the current settings
+   * until the bus is restarted as opposed to saving the current settings
    * and restoring them (which makes no sense to me). */
 
   /* Turn on the bus reset. */
@@ -4070,7 +4070,7 @@
             aic_dev->max_q_depth = aic_dev->temp_q_depth = 1;
             /*
              * We set this command up as a bus device reset.  However, we have
-             * to clear the tag type as it's causing us problems.  We shouldnt
+             * to clear the tag type as it's causing us problems.  We shouldn't
              * have to worry about any other commands being active, since if
              * the device is refusing tagged commands, this should be the
              * first tagged command sent to the device, however, we do have
@@ -9748,7 +9748,7 @@
     }
 
     /*
-     * We are commited now, everything has been checked and this card
+     * We are committed now, everything has been checked and this card
      * has been found, now we just set it up
      */
 
@@ -9906,7 +9906,7 @@
    *  2: All PCI controllers with BIOS_ENABLED next, according to BIOS
    *     address, going from lowest to highest.
    *  3: Remaining VLB/EISA controllers going in slot order.
-   *  4: Remaining PCI controllers, going in PCI device order (reversable)
+   *  4: Remaining PCI controllers, going in PCI device order (reversible)
    */
 
   {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic94xx/aic94xx_reg_def.h linux-libre-2.6.39-gnu/drivers/scsi/aic94xx/aic94xx_reg_def.h
--- linux-libre-2.6.38-gnu/drivers/scsi/aic94xx/aic94xx_reg_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic94xx/aic94xx_reg_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -2134,7 +2134,7 @@
 * The host accesses this scratch in a different manner from the
 * link sequencer. The sequencer has to use LSEQ registers
 * LmSCRPAGE and LmMnSCRPAGE to access the scratch memory. A flat
-* mapping of the scratch memory is avaliable for software
+* mapping of the scratch memory is available for software
 * convenience and to prevent corruption while the sequencer is
 * running. This memory is mapped onto addresses 800h - 9FFh.
 *
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/aic94xx/Makefile linux-libre-2.6.39-gnu/drivers/scsi/aic94xx/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/aic94xx/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/aic94xx/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -22,9 +22,7 @@
 # along with the aic94xx driver; if not, write to the Free Software
 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
 
-ifeq ($(CONFIG_AIC94XX_DEBUG),y)
-	EXTRA_CFLAGS += -DASD_DEBUG -DASD_ENTER_EXIT
-endif
+ccflags-$(CONFIG_AIC94XX_DEBUG) := -DASD_DEBUG -DASD_ENTER_EXIT
 
 obj-$(CONFIG_SCSI_AIC94XX) += aic94xx.o
 aic94xx-y += aic94xx_init.o \
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arcmsr/arcmsr_hba.c linux-libre-2.6.39-gnu/drivers/scsi/arcmsr/arcmsr_hba.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arcmsr/arcmsr_hba.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arcmsr/arcmsr_hba.c	2011-05-19 00:06:34.000000000 -0400
@@ -1020,7 +1020,7 @@
 	int poll_count = 0;
 	arcmsr_free_sysfs_attr(acb);
 	scsi_remove_host(host);
-	flush_scheduled_work();
+	flush_work_sync(&acb->arcmsr_do_message_isr_bh);
 	del_timer_sync(&acb->eternal_timer);
 	arcmsr_disable_outbound_ints(acb);
 	arcmsr_stop_adapter_bgrb(acb);
@@ -1066,7 +1066,7 @@
 		(struct AdapterControlBlock *)host->hostdata;
 	del_timer_sync(&acb->eternal_timer);
 	arcmsr_disable_outbound_ints(acb);
-	flush_scheduled_work();
+	flush_work_sync(&acb->arcmsr_do_message_isr_bh);
 	arcmsr_stop_adapter_bgrb(acb);
 	arcmsr_flush_adapter_cache(acb);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/acornscsi.c linux-libre-2.6.39-gnu/drivers/scsi/arm/acornscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/acornscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/acornscsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -100,7 +100,7 @@
  */
 #define TIMEOUT_TIME 10
 /*
- * Define this if you want to have verbose explaination of SCSI
+ * Define this if you want to have verbose explanation of SCSI
  * status/messages.
  */
 #undef CONFIG_ACORNSCSI_CONSTANTS
@@ -1561,7 +1561,7 @@
 	/*
 	 * If we were negociating sync transfer, we don't yet know if
 	 * this REJECT is for the sync transfer or for the tagged queue/wide
-	 * transfer.  Re-initiate sync transfer negociation now, and if
+	 * transfer.  Re-initiate sync transfer negotiation now, and if
 	 * we got a REJECT in response to SDTR, then it'll be set to DONE.
 	 */
 	if (host->device[host->SCpnt->device->id].sync_state == SYNC_SENT_REQUEST)
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/acornscsi.h linux-libre-2.6.39-gnu/drivers/scsi/arm/acornscsi.h
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/acornscsi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/acornscsi.h	2011-05-19 00:06:34.000000000 -0400
@@ -223,8 +223,8 @@
  * Synchronous transfer state
  */
 typedef enum {					/* Synchronous transfer state		*/
-    SYNC_ASYNCHRONOUS,				/* don't negociate synchronous transfers*/
-    SYNC_NEGOCIATE,				/* start negociation			*/
+    SYNC_ASYNCHRONOUS,				/* don't negotiate synchronous transfers*/
+    SYNC_NEGOCIATE,				/* start negotiation			*/
     SYNC_SENT_REQUEST,				/* sent SDTR message			*/
     SYNC_COMPLETED,				/* received SDTR reply			*/
 } syncxfer_t;
@@ -322,7 +322,7 @@
     /* per-device info */
     struct {
 	unsigned char	sync_xfer;		/* synchronous transfer (SBIC value)	*/
-	syncxfer_t	sync_state;		/* sync xfer negociation state		*/
+	syncxfer_t	sync_state;		/* sync xfer negotiation state		*/
 	unsigned char	disconnect_ok:1;	/* device can disconnect		*/
     } device[8];
     unsigned long	busyluns[64 / sizeof(unsigned long)];/* array of bits indicating LUNs busy	*/
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/arxescsi.c linux-libre-2.6.39-gnu/drivers/scsi/arm/arxescsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/arxescsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/arxescsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -228,7 +228,7 @@
  * Params  : buffer - a buffer to write information to
  *	     start  - a pointer into this buffer set by this routine to the start
  *		      of the required information.
- *	     offset - offset into information that we have read upto.
+ *	     offset - offset into information that we have read up to.
  *	     length - length of buffer
  *	     host_no - host number to return information for
  *	     inout  - 0 for reading, 1 for writing.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/cumana_2.c linux-libre-2.6.39-gnu/drivers/scsi/arm/cumana_2.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/cumana_2.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/cumana_2.c	2011-05-19 00:06:34.000000000 -0400
@@ -344,7 +344,7 @@
  * Params   : buffer - a buffer to write information to
  *	      start  - a pointer into this buffer set by this routine to the start
  *		       of the required information.
- *	      offset - offset into information that we have read upto.
+ *	      offset - offset into information that we have read up to.
  *	      length - length of buffer
  *	      host_no - host number to return information for
  *	      inout  - 0 for reading, 1 for writing.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/eesox.c linux-libre-2.6.39-gnu/drivers/scsi/arm/eesox.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/eesox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/eesox.c	2011-05-19 00:06:34.000000000 -0400
@@ -429,7 +429,7 @@
  * Params   : buffer - a buffer to write information to
  *	      start  - a pointer into this buffer set by this routine to the start
  *		       of the required information.
- *	      offset - offset into information that we have read upto.
+ *	      offset - offset into information that we have read up to.
  *	      length - length of buffer
  *	      host_no - host number to return information for
  *	      inout  - 0 for reading, 1 for writing.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/fas216.c linux-libre-2.6.39-gnu/drivers/scsi/arm/fas216.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/fas216.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/fas216.c	2011-05-19 00:06:34.000000000 -0400
@@ -2119,7 +2119,7 @@
 	 * executed, unless a target connects to us.
 	 */
 	if (info->reqSCpnt)
-		printk(KERN_WARNING "scsi%d.%c: loosing request command\n",
+		printk(KERN_WARNING "scsi%d.%c: losing request command\n",
 			info->host->host_no, '0' + SCpnt->device->id);
 	info->reqSCpnt = SCpnt;
 }
@@ -2294,7 +2294,7 @@
 		 * If we don't have an IRQ, then we must poll the card for
 		 * it's interrupt, and use that to call this driver's
 		 * interrupt routine.  That way, we keep the command
-		 * progressing.  Maybe we can add some inteligence here
+		 * progressing.  Maybe we can add some intelligence here
 		 * and go to sleep if we know that the device is going
 		 * to be some time (eg, disconnected).
 		 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/fas216.h linux-libre-2.6.39-gnu/drivers/scsi/arm/fas216.h
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/fas216.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/fas216.h	2011-05-19 00:06:34.000000000 -0400
@@ -203,11 +203,11 @@
 } fasdmatype_t;
 
 typedef enum {
-	neg_wait,					/* Negociate with device		*/
-	neg_inprogress,					/* Negociation sent			*/
-	neg_complete,					/* Negociation complete			*/
-	neg_targcomplete,				/* Target completed negociation		*/
-	neg_invalid					/* Negociation not supported		*/
+	neg_wait,					/* Negotiate with device		*/
+	neg_inprogress,					/* Negotiation sent			*/
+	neg_complete,					/* Negotiation complete			*/
+	neg_targcomplete,				/* Target completed negotiation		*/
+	neg_invalid					/* Negotiation not supported		*/
 } neg_t;
 
 #define MAGIC	0x441296bdUL
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/arm/powertec.c linux-libre-2.6.39-gnu/drivers/scsi/arm/powertec.c
--- linux-libre-2.6.38-gnu/drivers/scsi/arm/powertec.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/arm/powertec.c	2011-05-19 00:06:34.000000000 -0400
@@ -232,7 +232,7 @@
  * Params   : buffer  - a buffer to write information to
  *	      start   - a pointer into this buffer set by this routine to the start
  *		        of the required information.
- *	      offset  - offset into information that we have read upto.
+ *	      offset  - offset into information that we have read up to.
  *	      length  - length of buffer
  *	      inout   - 0 for reading, 1 for writing.
  * Returns  : length of data written to buffer.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/atari_NCR5380.c linux-libre-2.6.39-gnu/drivers/scsi/atari_NCR5380.c
--- linux-libre-2.6.38-gnu/drivers/scsi/atari_NCR5380.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/atari_NCR5380.c	2011-05-19 00:06:34.000000000 -0400
@@ -464,7 +464,7 @@
  *
  * Parameters: Scsi_Cmnd *cmd
  *    The command to work on. The first scatter buffer's data are
- *    assumed to be already transfered into ptr/this_residual.
+ *    assumed to be already transferred into ptr/this_residual.
  */
 
 static void merge_contiguous_buffers(Scsi_Cmnd *cmd)
@@ -1720,7 +1720,7 @@
  *	bytes to transfer, **data - pointer to data pointer.
  *
  * Returns : -1 when different phase is entered without transferring
- *	maximum number of bytes, 0 if all bytes are transfered or exit
+ *	maximum number of bytes, 0 if all bytes are transferred or exit
  *	is in same phase.
  *
  *	Also, *phase, *count, *data are modified in place.
@@ -1911,7 +1911,7 @@
  *	bytes to transfer, **data - pointer to data pointer.
  *
  * Returns : -1 when different phase is entered without transferring
- *	maximum number of bytes, 0 if all bytes or transfered or exit
+ *	maximum number of bytes, 0 if all bytes or transferred or exit
  *	is in same phase.
  *
  *	Also, *phase, *count, *data are modified in place.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/atp870u.c linux-libre-2.6.39-gnu/drivers/scsi/atp870u.c
--- linux-libre-2.6.38-gnu/drivers/scsi/atp870u.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/atp870u.c	2011-05-19 00:06:34.000000000 -0400
@@ -1228,7 +1228,7 @@
 	printk(" \n%x %x %x %s\n ",assignid_map,mbuf[0],mbuf[1],&mbuf[2]); */
 	i = 15;
 	j = mbuf[0];
-	if ((j & 0x20) != 0) {	/* bit5=1:ID upto 7      */
+	if ((j & 0x20) != 0) {	/* bit5=1:ID up to 7      */
 		i = 7;
 	}
 	if ((j & 0x06) == 0) {	/* IDvalid?             */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_cmds.h linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_cmds.h
--- linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_cmds.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_cmds.h	2011-05-19 00:06:34.000000000 -0400
@@ -877,7 +877,7 @@
 						 */
 #define CXN_KILLED_PDU_SIZE_EXCEEDS_DSL 3	/* Connection got invalidated
 						 * internally
-						 * due to a recieved PDU
+						 * due to a received PDU
 						 * size > DSL
 						 */
 #define CXN_KILLED_BURST_LEN_MISMATCH   4	/* Connection got invalidated
@@ -886,7 +886,7 @@
 						 * FBL/MBL.
 						 */
 #define CXN_KILLED_AHS_RCVD		5	/* Connection got invalidated
-						 * internally due to a recieved
+						 * internally due to a received
 						 * PDU Hdr that has
 						 * AHS */
 #define CXN_KILLED_HDR_DIGEST_ERR	6	/* Connection got invalidated
@@ -899,12 +899,12 @@
 						 * pdu hdr
 						 */
 #define CXN_KILLED_STALE_ITT_TTT_RCVD	8	/* Connection got invalidated
-						 * internally due to a recieved
+						 * internally due to a received
 						 * ITT/TTT that does not belong
 						 * to this Connection
 						 */
 #define CXN_KILLED_INVALID_ITT_TTT_RCVD 9	/* Connection got invalidated
-						 * internally due to recieved
+						 * internally due to received
 						 * ITT/TTT value > Max
 						 * Supported ITTs/TTTs
 						 */
@@ -936,21 +936,21 @@
 						 * index.
 						 */
 #define CXN_KILLED_OVER_RUN_RESIDUAL	16	/* Command got invalidated
-						 * internally due to recived
+						 * internally due to received
 						 * command has residual
 						 * over run bytes.
 						 */
 #define CXN_KILLED_UNDER_RUN_RESIDUAL	17	/* Command got invalidated
-						 * internally due to recived
+						 * internally due to received
 						 * command has residual under
 						 * run bytes.
 						 */
 #define CMD_KILLED_INVALID_STATSN_RCVD	18	/* Command got invalidated
-						 * internally due to a recieved
+						 * internally due to a received
 						 * PDU has an invalid StatusSN
 						 */
 #define CMD_KILLED_INVALID_R2T_RCVD	19	/* Command got invalidated
-						 * internally due to a recieved
+						 * internally due to a received
 						 * an R2T with some invalid
 						 * fields in it
 						 */
@@ -973,7 +973,7 @@
 						 */
 #define CMD_CXN_KILLED_INVALID_DATASN_RCVD 24	/* Command got invalidated
 						 * internally due to a
-						 * recieved PDU has an invalid
+						 * received PDU has an invalid
 						 * DataSN
 						 */
 #define CXN_INVALIDATE_NOTIFY		25	/* Connection invalidation
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_iscsi.c linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_iscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_iscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_iscsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -210,28 +210,20 @@
 }
 
 /**
- * beiscsi_conn_get_param - get the iscsi parameter
- * @cls_conn: pointer to iscsi cls conn
+ * beiscsi_ep_get_param - get the iscsi parameter
+ * @ep: pointer to iscsi ep
  * @param: parameter type identifier
  * @buf: buffer pointer
  *
  * returns iscsi parameter
  */
-int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
+int beiscsi_ep_get_param(struct iscsi_endpoint *ep,
 			   enum iscsi_param param, char *buf)
 {
-	struct beiscsi_endpoint *beiscsi_ep;
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct beiscsi_conn *beiscsi_conn = conn->dd_data;
+	struct beiscsi_endpoint *beiscsi_ep = ep->dd_data;
 	int len = 0;
 
 	SE_DEBUG(DBG_LVL_8, "In beiscsi_conn_get_param, param= %d\n", param);
-	beiscsi_ep = beiscsi_conn->ep;
-	if (!beiscsi_ep) {
-		SE_DEBUG(DBG_LVL_1,
-			 "In beiscsi_conn_get_param , no beiscsi_ep\n");
-		return -ENODEV;
-	}
 
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
@@ -244,7 +236,7 @@
 			len = sprintf(buf, "%pI6\n", &beiscsi_ep->dst6_addr);
 		break;
 	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
+		return -ENOSYS;
 	}
 	return len;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_iscsi.h linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_iscsi.h
--- linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_iscsi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_iscsi.h	2011-05-19 00:06:34.000000000 -0400
@@ -48,8 +48,8 @@
 		      struct iscsi_cls_conn *cls_conn,
 		      uint64_t transport_fd, int is_leading);
 
-int beiscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
-			   enum iscsi_param param, char *buf);
+int beiscsi_ep_get_param(struct iscsi_endpoint *ep, enum iscsi_param param,
+			 char *buf);
 
 int beiscsi_get_host_param(struct Scsi_Host *shost,
 			   enum iscsi_host_param param, char *buf);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_main.c linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_main.c
--- linux-libre-2.6.38-gnu/drivers/scsi/be2iscsi/be_main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/be2iscsi/be_main.c	2011-05-19 00:06:34.000000000 -0400
@@ -4277,7 +4277,7 @@
 
 	snprintf(phba->wq_name, sizeof(phba->wq_name), "beiscsi_q_irq%u",
 		 phba->shost->host_no);
-	phba->wq = create_workqueue(phba->wq_name);
+	phba->wq = alloc_workqueue(phba->wq_name, WQ_MEM_RECLAIM, 1);
 	if (!phba->wq) {
 		shost_printk(KERN_ERR, phba->shost, "beiscsi_dev_probe-"
 				"Failed to allocate work queue\n");
@@ -4384,7 +4384,7 @@
 	.bind_conn = beiscsi_conn_bind,
 	.destroy_conn = iscsi_conn_teardown,
 	.set_param = beiscsi_set_param,
-	.get_conn_param = beiscsi_conn_get_param,
+	.get_conn_param = iscsi_conn_get_param,
 	.get_session_param = iscsi_session_get_param,
 	.get_host_param = beiscsi_get_host_param,
 	.start_conn = beiscsi_conn_start,
@@ -4395,6 +4395,7 @@
 	.alloc_pdu = beiscsi_alloc_pdu,
 	.parse_pdu_itt = beiscsi_parse_pdu,
 	.get_stats = beiscsi_conn_get_stats,
+	.get_ep_param = beiscsi_ep_get_param,
 	.ep_connect = beiscsi_ep_connect,
 	.ep_poll = beiscsi_ep_poll,
 	.ep_disconnect = beiscsi_ep_disconnect,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_core.c linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_core.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -355,7 +355,7 @@
 			/*
 			 * ERR_PSS bit needs to be cleared as well in case
 			 * interrups are shared so driver's interrupt handler is
-			 * still called eventhough it is already masked out.
+			 * still called even though it is already masked out.
 			 */
 			curr_value = readl(
 					bfa->ioc.ioc_regs.pss_err_status_reg);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfad.c linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfad.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfad.c	2012-03-24 01:18:21.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfad.c	2012-03-24 03:36:42.000000000 -0400
@@ -1276,7 +1276,7 @@
 			 * interrupts into one vector, so even if we
 			 * can try to request less vectors, we don't
 			 * know how to associate interrupt events to
-			 *  vectors. Linux doesn't dupicate vectors
+			 *  vectors. Linux doesn't duplicate vectors
 			 * in the MSIX table for this case.
 			 */
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_defs_svc.h linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_defs_svc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_defs_svc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_defs_svc.h	2011-05-19 00:06:34.000000000 -0400
@@ -145,7 +145,7 @@
 	u32	ioh_data_oor_event;	/*  Data out of range */
 	u32	ioh_ro_ooo_event;	/*  Relative offset out of range */
 	u32	ioh_cpu_owned_event;	/*  IOH hit -iost owned by f/w */
-	u32	ioh_unexp_frame_event;	/*  unexpected frame recieved
+	u32	ioh_unexp_frame_event;	/*  unexpected frame received
 						 *   count */
 	u32	ioh_err_int;		/*  IOH error int during data-phase
 						 *   for scsi write
@@ -566,8 +566,8 @@
 	u32	input_reqs;		/*  Data in-bound requests	*/
 	u32	output_reqs;		/*  Data out-bound requests	*/
 	u32	io_comps;		/*  Total IO Completions	*/
-	u32	wr_throughput;		/*  Write data transfered in bytes */
-	u32	rd_throughput;		/*  Read data transfered in bytes  */
+	u32	wr_throughput;		/*  Write data transferred in bytes */
+	u32	rd_throughput;		/*  Read data transferred in bytes  */
 
 	u32	iocomp_ok;		/*  Slowpath IO completions	*/
 	u32	iocomp_underrun;	/*  IO underrun		*/
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fc.h linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fc.h	2011-05-19 00:06:34.000000000 -0400
@@ -315,7 +315,7 @@
 			query_dbc:1,
 			hg_supp:1;
 #endif
-	__be16		rxsz;		/* recieve data_field size */
+	__be16		rxsz;		/* receive data_field size */
 	__be16		conseq;
 	__be16		ro_bitmap;
 	__be32		e_d_tov;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fcs.c linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fcs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fcs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fcs.c	2011-05-19 00:06:34.000000000 -0400
@@ -1033,7 +1033,7 @@
 
 
 /*
- * Lookup for a vport withing a fabric given its pwwn
+ * Lookup for a vport within a fabric given its pwwn
  */
 struct bfa_fcs_vport_s *
 bfa_fcs_fabric_vport_lookup(struct bfa_fcs_fabric_s *fabric, wwn_t pwwn)
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fcs.h linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fcs.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fcs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fcs.h	2011-05-19 00:06:34.000000000 -0400
@@ -705,7 +705,7 @@
 	RPSM_EVENT_ADDRESS_CHANGE = 15, /*  Rport's PID has changed     */
 	RPSM_EVENT_ADDRESS_DISC = 16,   /*  Need to Discover rport's PID */
 	RPSM_EVENT_PRLO_RCVD   = 17,    /*  PRLO from remote device     */
-	RPSM_EVENT_PLOGI_RETRY = 18,    /*  Retry PLOGI continously */
+	RPSM_EVENT_PLOGI_RETRY = 18,    /*  Retry PLOGI continuously */
 };
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fcs_lport.c linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fcs_lport.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_fcs_lport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_fcs_lport.c	2011-05-19 00:06:34.000000000 -0400
@@ -1149,7 +1149,7 @@
 		} else {
 			/*
 			 * For a base port, we should first register the HBA
-			 * atribute. The HBA attribute also contains the base
+			 * attribute. The HBA attribute also contains the base
 			 *  port registration.
 			 */
 			bfa_sm_set_state(fdmi,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_svc.c linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_svc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_svc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_svc.c	2011-05-19 00:06:34.000000000 -0400
@@ -1035,7 +1035,7 @@
  * @param[in]	rport	BFA rport pointer. Could be left NULL for WKA rports
  * @param[in]	vf_id	virtual Fabric ID
  * @param[in]	lp_tag	lport tag
- * @param[in]	cts	use Continous sequence
+ * @param[in]	cts	use Continuous sequence
  * @param[in]	cos	fc Class of Service
  * @param[in]	reqlen	request length, does not include FCHS length
  * @param[in]	fchs	fc Header Pointer. The header content will be copied
@@ -5022,7 +5022,7 @@
 }
 
 /*
- * Register handler for all unsolicted recieve frames.
+ * Register handler for all unsolicted receive frames.
  *
  * @param[in]	bfa		BFA instance
  * @param[in]	ufrecv	receive handler function
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_svc.h linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_svc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bfa/bfa_svc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bfa/bfa_svc.h	2011-05-19 00:06:34.000000000 -0400
@@ -127,7 +127,7 @@
 					 * rport nexus is established
 					 */
 	struct fchs_s	fchs;	/*  request FC header structure */
-	u8		cts;	/*  continous sequence */
+	u8		cts;	/*  continuous sequence */
 	u8		class;	/*  FC class for the request/response */
 	u16	max_frmsz;	/*  max send frame size */
 	u16	vf_id;	/*  vsan tag if applicable */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/57xx_hsi_bnx2fc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1080 @@
+#ifndef __57XX_FCOE_HSI_LINUX_LE__
+#define __57XX_FCOE_HSI_LINUX_LE__
+
+/*
+ * common data for all protocols
+ */
+struct b577xx_doorbell_hdr {
+	u8 header;
+#define B577XX_DOORBELL_HDR_RX (0x1<<0)
+#define B577XX_DOORBELL_HDR_RX_SHIFT 0
+#define B577XX_DOORBELL_HDR_DB_TYPE (0x1<<1)
+#define B577XX_DOORBELL_HDR_DB_TYPE_SHIFT 1
+#define B577XX_DOORBELL_HDR_DPM_SIZE (0x3<<2)
+#define B577XX_DOORBELL_HDR_DPM_SIZE_SHIFT 2
+#define B577XX_DOORBELL_HDR_CONN_TYPE (0xF<<4)
+#define B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT 4
+};
+
+/*
+ * doorbell message sent to the chip
+ */
+struct b577xx_doorbell_set_prod {
+#if defined(__BIG_ENDIAN)
+	u16 prod;
+	u8 zero_fill1;
+	struct b577xx_doorbell_hdr header;
+#elif defined(__LITTLE_ENDIAN)
+	struct b577xx_doorbell_hdr header;
+	u8 zero_fill1;
+	u16 prod;
+#endif
+};
+
+
+struct regpair {
+	__le32 lo;
+	__le32 hi;
+};
+
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ */
+struct fcoe_abts_rsp_union {
+	u32 r_ctl;
+	u32 abts_rsp_payload[7];
+};
+
+
+/*
+ * 4 regs size
+ */
+struct fcoe_bd_ctx {
+	u32 buf_addr_hi;
+	u32 buf_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 rsrv0;
+	u16 buf_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 buf_len;
+	u16 rsrv0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 rsrv1;
+	u16 flags;
+#elif defined(__LITTLE_ENDIAN)
+	u16 flags;
+	u16 rsrv1;
+#endif
+};
+
+
+struct fcoe_cleanup_flow_info {
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u16 task_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 task_id;
+	u16 reserved1;
+#endif
+	u32 reserved2[7];
+};
+
+
+struct fcoe_fcp_cmd_payload {
+	u32 opaque[8];
+};
+
+struct fcoe_fc_hdr {
+#if defined(__BIG_ENDIAN)
+	u8 cs_ctl;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 cs_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 r_ctl;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 r_ctl;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 seq_id;
+	u8 df_ctl;
+	u16 seq_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u16 seq_cnt;
+	u8 df_ctl;
+	u8 seq_id;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 type;
+	u8 f_ctl[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 f_ctl[3];
+	u8 type;
+#endif
+	u32 parameters;
+#if defined(__BIG_ENDIAN)
+	u16 ox_id;
+	u16 rx_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_id;
+	u16 ox_id;
+#endif
+};
+
+struct fcoe_fc_frame {
+	struct fcoe_fc_hdr fc_hdr;
+	u32 reserved0[2];
+};
+
+union fcoe_cmd_flow_info {
+	struct fcoe_fcp_cmd_payload fcp_cmd_payload;
+	struct fcoe_fc_frame mp_fc_frame;
+};
+
+
+
+struct fcoe_fcp_rsp_flags {
+	u8 flags;
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID (0x1<<0)
+#define FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID_SHIFT 0
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID (0x1<<1)
+#define FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID_SHIFT 1
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER (0x1<<2)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_OVER_SHIFT 2
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER (0x1<<3)
+#define FCOE_FCP_RSP_FLAGS_FCP_RESID_UNDER_SHIFT 3
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ (0x1<<4)
+#define FCOE_FCP_RSP_FLAGS_FCP_CONF_REQ_SHIFT 4
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS (0x7<<5)
+#define FCOE_FCP_RSP_FLAGS_FCP_BIDI_FLAGS_SHIFT 5
+};
+
+
+struct fcoe_fcp_rsp_payload {
+	struct regpair reserved0;
+	u32 fcp_resid;
+#if defined(__BIG_ENDIAN)
+	u16 retry_delay_timer;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	u8 scsi_status_code;
+#elif defined(__LITTLE_ENDIAN)
+	u8 scsi_status_code;
+	struct fcoe_fcp_rsp_flags fcp_flags;
+	u16 retry_delay_timer;
+#endif
+	u32 fcp_rsp_len;
+	u32 fcp_sns_len;
+};
+
+
+/*
+ * Fixed size structure in order to plant it in Union structure
+ */
+struct fcoe_fcp_rsp_union {
+	struct fcoe_fcp_rsp_payload payload;
+	struct regpair reserved0;
+};
+
+
+struct fcoe_fcp_xfr_rdy_payload {
+	u32 burst_len;
+	u32 data_ro;
+};
+
+struct fcoe_read_flow_info {
+	struct fcoe_fc_hdr fc_data_in_hdr;
+	u32 reserved[2];
+};
+
+struct fcoe_write_flow_info {
+	struct fcoe_fc_hdr fc_data_out_hdr;
+	struct fcoe_fcp_xfr_rdy_payload fcp_xfr_payload;
+};
+
+union fcoe_rsp_flow_info {
+	struct fcoe_fcp_rsp_union fcp_rsp;
+	struct fcoe_abts_rsp_union abts_rsp;
+};
+
+/*
+ * 32 bytes used for general purposes
+ */
+union fcoe_general_task_ctx {
+	union fcoe_cmd_flow_info cmd_info;
+	struct fcoe_read_flow_info read_info;
+	struct fcoe_write_flow_info write_info;
+	union fcoe_rsp_flow_info rsp_info;
+	struct fcoe_cleanup_flow_info cleanup_info;
+	u32 comp_info[8];
+};
+
+
+/*
+ * FCoE KCQ CQE parameters
+ */
+union fcoe_kcqe_params {
+	u32 reserved0[4];
+};
+
+/*
+ * FCoE KCQ CQE
+ */
+struct fcoe_kcqe {
+	u32 fcoe_conn_id;
+	u32 completion_status;
+	u32 fcoe_conn_context_id;
+	union fcoe_kcqe_params params;
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+	u8 op_code;
+	u16 qe_self_seq;
+#elif defined(__LITTLE_ENDIAN)
+	u16 qe_self_seq;
+	u8 op_code;
+	u8 flags;
+#define FCOE_KCQE_RESERVED0 (0x7<<0)
+#define FCOE_KCQE_RESERVED0_SHIFT 0
+#define FCOE_KCQE_RAMROD_COMPLETION (0x1<<3)
+#define FCOE_KCQE_RAMROD_COMPLETION_SHIFT 3
+#define FCOE_KCQE_LAYER_CODE (0x7<<4)
+#define FCOE_KCQE_LAYER_CODE_SHIFT 4
+#define FCOE_KCQE_LINKED_WITH_NEXT (0x1<<7)
+#define FCOE_KCQE_LINKED_WITH_NEXT_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE KWQE header
+ */
+struct fcoe_kwqe_header {
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+	u8 op_code;
+#elif defined(__LITTLE_ENDIAN)
+	u8 op_code;
+	u8 flags;
+#define FCOE_KWQE_HEADER_RESERVED0 (0xF<<0)
+#define FCOE_KWQE_HEADER_RESERVED0_SHIFT 0
+#define FCOE_KWQE_HEADER_LAYER_CODE (0x7<<4)
+#define FCOE_KWQE_HEADER_LAYER_CODE_SHIFT 4
+#define FCOE_KWQE_HEADER_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_HEADER_RESERVED1_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE firmware init request 1
+ */
+struct fcoe_kwqe_init1 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 num_tasks;
+#elif defined(__LITTLE_ENDIAN)
+	u16 num_tasks;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 task_list_pbl_addr_lo;
+	u32 task_list_pbl_addr_hi;
+	u32 dummy_buffer_addr_lo;
+	u32 dummy_buffer_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 rq_num_wqes;
+	u16 sq_num_wqes;
+#elif defined(__LITTLE_ENDIAN)
+	u16 sq_num_wqes;
+	u16 rq_num_wqes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 cq_num_wqes;
+	u16 rq_buffer_log_size;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_buffer_log_size;
+	u16 cq_num_wqes;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+	u8 num_sessions_log;
+	u16 mtu;
+#elif defined(__LITTLE_ENDIAN)
+	u16 mtu;
+	u8 num_sessions_log;
+	u8 flags;
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE (0xF<<0)
+#define FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT 0
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC (0x7<<4)
+#define FCOE_KWQE_INIT1_LOG_CACHED_PBES_PER_FUNC_SHIFT 4
+#define FCOE_KWQE_INIT1_RESERVED1 (0x1<<7)
+#define FCOE_KWQE_INIT1_RESERVED1_SHIFT 7
+#endif
+};
+
+/*
+ * FCoE firmware init request 2
+ */
+struct fcoe_kwqe_init2 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 hash_tbl_pbl_addr_lo;
+	u32 hash_tbl_pbl_addr_hi;
+	u32 t2_hash_tbl_addr_lo;
+	u32 t2_hash_tbl_addr_hi;
+	u32 t2_ptr_hash_tbl_addr_lo;
+	u32 t2_ptr_hash_tbl_addr_hi;
+	u32 free_list_count;
+};
+
+/*
+ * FCoE firmware init request 3
+ */
+struct fcoe_kwqe_init3 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 error_bit_map_lo;
+	u32 error_bit_map_hi;
+#if defined(__BIG_ENDIAN)
+	u8 reserved21[3];
+	u8 cached_session_enable;
+#elif defined(__LITTLE_ENDIAN)
+	u8 cached_session_enable;
+	u8 reserved21[3];
+#endif
+	u32 reserved2[4];
+};
+
+/*
+ * FCoE connection offload request 1
+ */
+struct fcoe_kwqe_conn_offload1 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 fcoe_conn_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 fcoe_conn_id;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 sq_addr_lo;
+	u32 sq_addr_hi;
+	u32 rq_pbl_addr_lo;
+	u32 rq_pbl_addr_hi;
+	u32 rq_first_pbe_addr_lo;
+	u32 rq_first_pbe_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u16 rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_prod;
+	u16 reserved0;
+#endif
+};
+
+/*
+ * FCoE connection offload request 2
+ */
+struct fcoe_kwqe_conn_offload2 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 tx_max_fc_pay_len;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_max_fc_pay_len;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 cq_addr_lo;
+	u32 cq_addr_hi;
+	u32 xferq_addr_lo;
+	u32 xferq_addr_hi;
+	u32 conn_db_addr_lo;
+	u32 conn_db_addr_hi;
+	u32 reserved1;
+};
+
+/*
+ * FCoE connection offload request 3
+ */
+struct fcoe_kwqe_conn_offload3 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+#elif defined(__LITTLE_ENDIAN)
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_OFFLOAD3_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT 13
+	struct fcoe_kwqe_header hdr;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 tx_max_conc_seqs_c3;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 tx_max_conc_seqs_c3;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 flags;
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS (0x1<<0)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT 0
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES (0x1<<1)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT 1
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT (0x1<<2)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT 2
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ (0x1<<3)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_CONF_REQ_SHIFT 3
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID (0x1<<4)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_REC_VALID_SHIFT 4
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID (0x1<<5)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_C2_VALID_SHIFT 5
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0 (0x1<<6)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_ACK_0_SHIFT 6
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG (0x1<<7)
+#define FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT 7
+#endif
+	u32 reserved;
+	u32 confq_first_pbe_addr_lo;
+	u32 confq_first_pbe_addr_hi;
+#if defined(__BIG_ENDIAN)
+	u16 rx_max_fc_pay_len;
+	u16 tx_total_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 tx_total_conc_seqs;
+	u16 rx_max_fc_pay_len;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 rx_open_seqs_exch_c3;
+	u8 rx_max_conc_seqs_c3;
+	u16 rx_total_conc_seqs;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_total_conc_seqs;
+	u8 rx_max_conc_seqs_c3;
+	u8 rx_open_seqs_exch_c3;
+#endif
+};
+
+/*
+ * FCoE connection offload request 4
+ */
+struct fcoe_kwqe_conn_offload4 {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u8 reserved2;
+	u8 e_d_tov_timer_val;
+#elif defined(__LITTLE_ENDIAN)
+	u8 e_d_tov_timer_val;
+	u8 reserved2;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u8 src_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u8 dst_mac_addr_hi16[2];
+	u8 src_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 src_mac_addr_hi16[2];
+	u8 dst_mac_addr_hi16[2];
+#endif
+	u8 dst_mac_addr_lo32[4];
+	u32 lcq_addr_lo;
+	u32 lcq_addr_hi;
+	u32 confq_pbl_base_addr_lo;
+	u32 confq_pbl_base_addr_hi;
+};
+
+/*
+ * FCoE connection enable request
+ */
+struct fcoe_kwqe_conn_enable_disable {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u8 src_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+	u8 src_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 src_mac_addr_hi16[2];
+	u16 vlan_tag;
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID (0xFFF<<0)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT 0
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI (0x1<<12)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_CFI_SHIFT 12
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY (0x7<<13)
+#define FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT 13
+#endif
+	u8 dst_mac_addr_lo32[4];
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 dst_mac_addr_hi16[2];
+#elif defined(__LITTLE_ENDIAN)
+	u8 dst_mac_addr_hi16[2];
+	u16 reserved1;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 vlan_flag;
+	u8 s_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id[3];
+	u8 vlan_flag;
+#endif
+#if defined(__BIG_ENDIAN)
+	u8 reserved3;
+	u8 d_id[3];
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id[3];
+	u8 reserved3;
+#endif
+	u32 context_id;
+	u32 conn_id;
+	u32 reserved4;
+};
+
+/*
+ * FCoE connection destroy request
+ */
+struct fcoe_kwqe_conn_destroy {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 context_id;
+	u32 conn_id;
+	u32 reserved1[5];
+};
+
+/*
+ * FCoe destroy request
+ */
+struct fcoe_kwqe_destroy {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 reserved1[7];
+};
+
+/*
+ * FCoe statistics request
+ */
+struct fcoe_kwqe_stat {
+#if defined(__BIG_ENDIAN)
+	struct fcoe_kwqe_header hdr;
+	u16 reserved0;
+#elif defined(__LITTLE_ENDIAN)
+	u16 reserved0;
+	struct fcoe_kwqe_header hdr;
+#endif
+	u32 stat_params_addr_lo;
+	u32 stat_params_addr_hi;
+	u32 reserved1[5];
+};
+
+/*
+ * FCoE KWQ WQE
+ */
+union fcoe_kwqe {
+	struct fcoe_kwqe_init1 init1;
+	struct fcoe_kwqe_init2 init2;
+	struct fcoe_kwqe_init3 init3;
+	struct fcoe_kwqe_conn_offload1 conn_offload1;
+	struct fcoe_kwqe_conn_offload2 conn_offload2;
+	struct fcoe_kwqe_conn_offload3 conn_offload3;
+	struct fcoe_kwqe_conn_offload4 conn_offload4;
+	struct fcoe_kwqe_conn_enable_disable conn_enable_disable;
+	struct fcoe_kwqe_conn_destroy conn_destroy;
+	struct fcoe_kwqe_destroy destroy;
+	struct fcoe_kwqe_stat statistics;
+};
+
+struct fcoe_mul_sges_ctx {
+	struct regpair cur_sge_addr;
+#if defined(__BIG_ENDIAN)
+	u8 sgl_size;
+	u8 cur_sge_idx;
+	u16 cur_sge_off;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cur_sge_off;
+	u8 cur_sge_idx;
+	u8 sgl_size;
+#endif
+};
+
+struct fcoe_s_stat_ctx {
+	u8 flags;
+#define FCOE_S_STAT_CTX_ACTIVE (0x1<<0)
+#define FCOE_S_STAT_CTX_ACTIVE_SHIFT 0
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND (0x1<<1)
+#define FCOE_S_STAT_CTX_ACK_ABORT_SEQ_COND_SHIFT 1
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED (0x1<<2)
+#define FCOE_S_STAT_CTX_ABTS_PERFORMED_SHIFT 2
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT (0x1<<3)
+#define FCOE_S_STAT_CTX_SEQ_TIMEOUT_SHIFT 3
+#define FCOE_S_STAT_CTX_P_RJT (0x1<<4)
+#define FCOE_S_STAT_CTX_P_RJT_SHIFT 4
+#define FCOE_S_STAT_CTX_ACK_EOFT (0x1<<5)
+#define FCOE_S_STAT_CTX_ACK_EOFT_SHIFT 5
+#define FCOE_S_STAT_CTX_RSRV1 (0x3<<6)
+#define FCOE_S_STAT_CTX_RSRV1_SHIFT 6
+};
+
+struct fcoe_seq_ctx {
+#if defined(__BIG_ENDIAN)
+	u16 low_seq_cnt;
+	struct fcoe_s_stat_ctx s_stat;
+	u8 seq_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 seq_id;
+	struct fcoe_s_stat_ctx s_stat;
+	u16 low_seq_cnt;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 err_seq_cnt;
+	u16 high_seq_cnt;
+#elif defined(__LITTLE_ENDIAN)
+	u16 high_seq_cnt;
+	u16 err_seq_cnt;
+#endif
+	u32 low_exp_ro;
+	u32 high_exp_ro;
+};
+
+
+struct fcoe_single_sge_ctx {
+	struct regpair cur_buf_addr;
+#if defined(__BIG_ENDIAN)
+	u16 reserved0;
+	u16 cur_buf_rem;
+#elif defined(__LITTLE_ENDIAN)
+	u16 cur_buf_rem;
+	u16 reserved0;
+#endif
+};
+
+union fcoe_sgl_ctx {
+	struct fcoe_single_sge_ctx single_sge;
+	struct fcoe_mul_sges_ctx mul_sges;
+};
+
+
+
+/*
+ * FCoE SQ element
+ */
+struct fcoe_sqe {
+	u16 wqe;
+#define FCOE_SQE_TASK_ID (0x7FFF<<0)
+#define FCOE_SQE_TASK_ID_SHIFT 0
+#define FCOE_SQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_SQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+struct fcoe_task_ctx_entry_tx_only {
+	union fcoe_sgl_ctx sgl_ctx;
+};
+
+struct fcoe_task_ctx_entry_txwr_rxrd {
+#if defined(__BIG_ENDIAN)
+	u16 verify_tx_seq;
+	u8 init_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
+	u8 tx_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+#elif defined(__LITTLE_ENDIAN)
+	u8 tx_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4 (0xF<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV4_SHIFT 4
+	u8 init_flags;
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE (0x7<<0)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE (0x1<<3)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT 3
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE (0x1<<4)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE (0x1<<5)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT 5
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5 (0x3<<6)
+#define FCOE_TASK_CTX_ENTRY_TXWR_RXRD_RSRV5_SHIFT 6
+	u16 verify_tx_seq;
+#endif
+};
+
+/*
+ * Common section. Both TX and RX processing might write and read from it in
+ * different flows
+ */
+struct fcoe_task_ctx_entry_tx_rx_cmn {
+	u32 data_2_trns;
+	union fcoe_general_task_ctx general;
+#if defined(__BIG_ENDIAN)
+	u16 tx_low_seq_cnt;
+	struct fcoe_s_stat_ctx tx_s_stat;
+	u8 tx_seq_id;
+#elif defined(__LITTLE_ENDIAN)
+	u8 tx_seq_id;
+	struct fcoe_s_stat_ctx tx_s_stat;
+	u16 tx_low_seq_cnt;
+#endif
+	u32 common_flags;
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID (0xFFFFFF<<0)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID (0x1<<24)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT 24
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT (0x1<<25)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT_SHIFT 25
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER (0x1<<26)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_XFER_SHIFT 26
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF (0x1<<27)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_PEND_CONF_SHIFT 27
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME (0x1<<28)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT 28
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV (0x7<<29)
+#define FCOE_TASK_CTX_ENTRY_TX_RX_CMN_RSRV_SHIFT 29
+};
+
+struct fcoe_task_ctx_entry_rxwr_txrd {
+#if defined(__BIG_ENDIAN)
+	u16 rx_id;
+	u16 rx_flags;
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
+#elif defined(__LITTLE_ENDIAN)
+	u16 rx_flags;
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE (0xF<<0)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT 0
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE (0x7<<4)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT 4
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ (0x1<<7)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_CONF_REQ_SHIFT 7
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME (0x1<<8)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_MISS_FRAME_SHIFT 8
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0 (0x7F<<9)
+#define FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RESERVED0_SHIFT 9
+	u16 rx_id;
+#endif
+};
+
+struct fcoe_task_ctx_entry_rx_only {
+	struct fcoe_seq_ctx seq_ctx;
+	struct fcoe_seq_ctx ooo_seq_ctx;
+	u32 rsrv3;
+	union fcoe_sgl_ctx sgl_ctx;
+};
+
+struct fcoe_task_ctx_entry {
+	struct fcoe_task_ctx_entry_tx_only tx_wr_only;
+	struct fcoe_task_ctx_entry_txwr_rxrd tx_wr_rx_rd;
+	struct fcoe_task_ctx_entry_tx_rx_cmn cmn;
+	struct fcoe_task_ctx_entry_rxwr_txrd rx_wr_tx_rd;
+	struct fcoe_task_ctx_entry_rx_only rx_wr_only;
+	u32 reserved[4];
+};
+
+
+/*
+ * FCoE XFRQ element
+ */
+struct fcoe_xfrqe {
+	u16 wqe;
+#define FCOE_XFRQE_TASK_ID (0x7FFF<<0)
+#define FCOE_XFRQE_TASK_ID_SHIFT 0
+#define FCOE_XFRQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_XFRQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * FCoE CONFQ element
+ */
+struct fcoe_confqe {
+#if defined(__BIG_ENDIAN)
+	u16 rx_id;
+	u16 ox_id;
+#elif defined(__LITTLE_ENDIAN)
+	u16 ox_id;
+	u16 rx_id;
+#endif
+	u32 param;
+};
+
+
+/*
+ * FCoE connection data base
+ */
+struct fcoe_conn_db {
+#if defined(__BIG_ENDIAN)
+	u16 rsrv0;
+	u16 rq_prod;
+#elif defined(__LITTLE_ENDIAN)
+	u16 rq_prod;
+	u16 rsrv0;
+#endif
+	u32 rsrv1;
+	struct regpair cq_arm;
+};
+
+
+/*
+ * FCoE CQ element
+ */
+struct fcoe_cqe {
+	u16 wqe;
+#define FCOE_CQE_CQE_INFO (0x3FFF<<0)
+#define FCOE_CQE_CQE_INFO_SHIFT 0
+#define FCOE_CQE_CQE_TYPE (0x1<<14)
+#define FCOE_CQE_CQE_TYPE_SHIFT 14
+#define FCOE_CQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_CQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * FCoE error/warning resporting entry
+ */
+struct fcoe_err_report_entry {
+	u32 err_warn_bitmap_lo;
+	u32 err_warn_bitmap_hi;
+	u32 tx_buf_off;
+	u32 rx_buf_off;
+	struct fcoe_fc_hdr fc_hdr;
+};
+
+
+/*
+ * FCoE hash table entry (32 bytes)
+ */
+struct fcoe_hash_table_entry {
+#if defined(__BIG_ENDIAN)
+	u8 d_id_0;
+	u8 s_id_2;
+	u8 s_id_1;
+	u8 s_id_0;
+#elif defined(__LITTLE_ENDIAN)
+	u8 s_id_0;
+	u8 s_id_1;
+	u8 s_id_2;
+	u8 d_id_0;
+#endif
+#if defined(__BIG_ENDIAN)
+	u16 dst_mac_addr_hi;
+	u8 d_id_2;
+	u8 d_id_1;
+#elif defined(__LITTLE_ENDIAN)
+	u8 d_id_1;
+	u8 d_id_2;
+	u16 dst_mac_addr_hi;
+#endif
+	u32 dst_mac_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 vlan_id;
+	u16 src_mac_addr_hi;
+#elif defined(__LITTLE_ENDIAN)
+	u16 src_mac_addr_hi;
+	u16 vlan_id;
+#endif
+	u32 src_mac_addr_lo;
+#if defined(__BIG_ENDIAN)
+	u16 reserved1;
+	u8 reserved0;
+	u8 vlan_flag;
+#elif defined(__LITTLE_ENDIAN)
+	u8 vlan_flag;
+	u8 reserved0;
+	u16 reserved1;
+#endif
+	u32 reserved2;
+	u32 field_id;
+#define FCOE_HASH_TABLE_ENTRY_CID (0xFFFFFF<<0)
+#define FCOE_HASH_TABLE_ENTRY_CID_SHIFT 0
+#define FCOE_HASH_TABLE_ENTRY_RESERVED3 (0x7F<<24)
+#define FCOE_HASH_TABLE_ENTRY_RESERVED3_SHIFT 24
+#define FCOE_HASH_TABLE_ENTRY_VALID (0x1<<31)
+#define FCOE_HASH_TABLE_ENTRY_VALID_SHIFT 31
+};
+
+/*
+ * FCoE pending work request CQE
+ */
+struct fcoe_pend_wq_cqe {
+	u16 wqe;
+#define FCOE_PEND_WQ_CQE_TASK_ID (0x3FFF<<0)
+#define FCOE_PEND_WQ_CQE_TASK_ID_SHIFT 0
+#define FCOE_PEND_WQ_CQE_CQE_TYPE (0x1<<14)
+#define FCOE_PEND_WQ_CQE_CQE_TYPE_SHIFT 14
+#define FCOE_PEND_WQ_CQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_PEND_WQ_CQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+/*
+ * FCoE RX statistics parameters section#0
+ */
+struct fcoe_rx_stat_params_section0 {
+	u32 fcoe_ver_cnt;
+	u32 fcoe_rx_pkt_cnt;
+	u32 fcoe_rx_byte_cnt;
+	u32 fcoe_rx_drop_pkt_cnt;
+};
+
+
+/*
+ * FCoE RX statistics parameters section#1
+ */
+struct fcoe_rx_stat_params_section1 {
+	u32 fc_crc_cnt;
+	u32 eofa_del_cnt;
+	u32 miss_frame_cnt;
+	u32 seq_timeout_cnt;
+	u32 drop_seq_cnt;
+	u32 fcoe_rx_drop_pkt_cnt;
+	u32 fcp_rx_pkt_cnt;
+	u32 reserved0;
+};
+
+
+/*
+ * FCoE TX statistics parameters
+ */
+struct fcoe_tx_stat_params {
+	u32 fcoe_tx_pkt_cnt;
+	u32 fcoe_tx_byte_cnt;
+	u32 fcp_tx_pkt_cnt;
+	u32 reserved0;
+};
+
+/*
+ * FCoE statistics parameters
+ */
+struct fcoe_statistics_params {
+	struct fcoe_tx_stat_params tx_stat;
+	struct fcoe_rx_stat_params_section0 rx_stat0;
+	struct fcoe_rx_stat_params_section1 rx_stat1;
+};
+
+
+/*
+ * FCoE t2 hash table entry (64 bytes)
+ */
+struct fcoe_t2_hash_table_entry {
+	struct fcoe_hash_table_entry data;
+	struct regpair next;
+	struct regpair reserved0[3];
+};
+
+/*
+ * FCoE unsolicited CQE
+ */
+struct fcoe_unsolicited_cqe {
+	u16 wqe;
+#define FCOE_UNSOLICITED_CQE_SUBTYPE (0x3<<0)
+#define FCOE_UNSOLICITED_CQE_SUBTYPE_SHIFT 0
+#define FCOE_UNSOLICITED_CQE_PKT_LEN (0xFFF<<2)
+#define FCOE_UNSOLICITED_CQE_PKT_LEN_SHIFT 2
+#define FCOE_UNSOLICITED_CQE_CQE_TYPE (0x1<<14)
+#define FCOE_UNSOLICITED_CQE_CQE_TYPE_SHIFT 14
+#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT (0x1<<15)
+#define FCOE_UNSOLICITED_CQE_TOGGLE_BIT_SHIFT 15
+};
+
+
+
+#endif /* __57XX_FCOE_HSI_LINUX_LE__ */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_constants.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,206 @@
+#ifndef __BNX2FC_CONSTANTS_H_
+#define __BNX2FC_CONSTANTS_H_
+
+/**
+ * This file defines HSI constants for the FCoE flows
+ */
+
+/* KWQ/KCQ FCoE layer code */
+#define FCOE_KWQE_LAYER_CODE   (7)
+
+/* KWQ (kernel work queue) request op codes */
+#define FCOE_KWQE_OPCODE_INIT1			(0)
+#define FCOE_KWQE_OPCODE_INIT2			(1)
+#define FCOE_KWQE_OPCODE_INIT3			(2)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN1	(3)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN2	(4)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN3	(5)
+#define FCOE_KWQE_OPCODE_OFFLOAD_CONN4	(6)
+#define FCOE_KWQE_OPCODE_ENABLE_CONN	(7)
+#define FCOE_KWQE_OPCODE_DISABLE_CONN	(8)
+#define FCOE_KWQE_OPCODE_DESTROY_CONN	(9)
+#define FCOE_KWQE_OPCODE_DESTROY		(10)
+#define FCOE_KWQE_OPCODE_STAT			(11)
+
+/* KCQ (kernel completion queue) response op codes */
+#define FCOE_KCQE_OPCODE_INIT_FUNC				(0x10)
+#define FCOE_KCQE_OPCODE_DESTROY_FUNC			(0x11)
+#define FCOE_KCQE_OPCODE_STAT_FUNC				(0x12)
+#define FCOE_KCQE_OPCODE_OFFLOAD_CONN			(0x15)
+#define FCOE_KCQE_OPCODE_ENABLE_CONN			(0x16)
+#define FCOE_KCQE_OPCODE_DISABLE_CONN			(0x17)
+#define FCOE_KCQE_OPCODE_DESTROY_CONN			(0x18)
+#define FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION  (0x20)
+#define FCOE_KCQE_OPCODE_FCOE_ERROR				(0x21)
+
+/* KCQ (kernel completion queue) completion status */
+#define FCOE_KCQE_COMPLETION_STATUS_SUCCESS				(0x0)
+#define FCOE_KCQE_COMPLETION_STATUS_ERROR				(0x1)
+#define FCOE_KCQE_COMPLETION_STATUS_INVALID_OPCODE		(0x2)
+#define FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE	(0x3)
+#define FCOE_KCQE_COMPLETION_STATUS_CTX_FREE_FAILURE	(0x4)
+#define FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR			(0x5)
+
+/* Unsolicited CQE type */
+#define FCOE_UNSOLICITED_FRAME_CQE_TYPE			0
+#define FCOE_ERROR_DETECTION_CQE_TYPE			1
+#define FCOE_WARNING_DETECTION_CQE_TYPE			2
+
+/* Task context constants */
+/* After driver has initialize the task in case timer services required */
+#define	FCOE_TASK_TX_STATE_INIT					0
+/* In case timer services are required then shall be updated by Xstorm after
+ * start processing the task. In case no timer facilities are required then the
+ * driver would initialize the state to this value */
+#define	FCOE_TASK_TX_STATE_NORMAL				1
+/* Task is under abort procedure. Updated in order to stop processing of
+ * pending WQEs on this task */
+#define	FCOE_TASK_TX_STATE_ABORT				2
+/* For E_D_T_TOV timer expiration in Xstorm (Class 2 only) */
+#define	FCOE_TASK_TX_STATE_ERROR				3
+/* For REC_TOV timer expiration indication received from Xstorm */
+#define	FCOE_TASK_TX_STATE_WARNING				4
+/* For completed unsolicited task */
+#define	FCOE_TASK_TX_STATE_UNSOLICITED_COMPLETED		5
+/* For exchange cleanup request task */
+#define	FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP			6
+/* For sequence cleanup request task */
+#define	FCOE_TASK_TX_STATE_SEQUENCE_CLEANUP			7
+/* Mark task as aborted and indicate that ABTS was not transmitted */
+#define	FCOE_TASK_TX_STATE_BEFORE_ABTS_TX			8
+/* Mark task as aborted and indicate that ABTS was transmitted */
+#define	FCOE_TASK_TX_STATE_AFTER_ABTS_TX			9
+/* For completion the ABTS task. */
+#define	FCOE_TASK_TX_STATE_ABTS_TX_COMPLETED			10
+/* Mark task as aborted and indicate that Exchange cleanup was not transmitted
+ */
+#define	FCOE_TASK_TX_STATE_BEFORE_EXCHANGE_CLEANUP_TX		11
+/* Mark task as aborted and indicate that Exchange cleanup was transmitted */
+#define	FCOE_TASK_TX_STATE_AFTER_EXCHANGE_CLEANUP_TX		12
+
+#define	FCOE_TASK_RX_STATE_NORMAL				0
+#define	FCOE_TASK_RX_STATE_COMPLETED				1
+/* Obsolete: Intermediate completion (middle path with local completion) */
+#define	FCOE_TASK_RX_STATE_INTER_COMP				2
+/* For REC_TOV timer expiration indication received from Xstorm */
+#define	FCOE_TASK_RX_STATE_WARNING				3
+/* For E_D_T_TOV timer expiration in Ustorm */
+#define	FCOE_TASK_RX_STATE_ERROR				4
+/* ABTS ACC arrived wait for local completion to finally complete the task. */
+#define	FCOE_TASK_RX_STATE_ABTS_ACC_ARRIVED			5
+/* local completion arrived wait for ABTS ACC to finally complete the task. */
+#define	FCOE_TASK_RX_STATE_ABTS_LOCAL_COMP_ARRIVED		6
+/* Special completion indication in case of task was aborted. */
+#define FCOE_TASK_RX_STATE_ABTS_COMPLETED			7
+/* Special completion indication in case of task was cleaned. */
+#define FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED		8
+/* Special completion indication (in task requested the exchange cleanup) in
+ * case cleaned task is in non-valid. */
+#define FCOE_TASK_RX_STATE_ABORT_CLEANUP_COMPLETED		9
+/* Special completion indication (in task requested the sequence cleanup) in
+ * case cleaned task was already returned to normal. */
+#define FCOE_TASK_RX_STATE_IGNORED_SEQUENCE_CLEANUP		10
+/* Exchange cleanup arrived wait until xfer will be handled to finally
+ * complete the task. */
+#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_ARRIVED		11
+/* Xfer handled, wait for exchange cleanup to finally complete the task. */
+#define	FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_HANDLED_XFER	12
+
+#define	FCOE_TASK_TYPE_WRITE			0
+#define	FCOE_TASK_TYPE_READ				1
+#define	FCOE_TASK_TYPE_MIDPATH			2
+#define	FCOE_TASK_TYPE_UNSOLICITED		3
+#define	FCOE_TASK_TYPE_ABTS				4
+#define	FCOE_TASK_TYPE_EXCHANGE_CLEANUP	5
+#define	FCOE_TASK_TYPE_SEQUENCE_CLEANUP	6
+
+#define FCOE_TASK_DEV_TYPE_DISK			0
+#define FCOE_TASK_DEV_TYPE_TAPE			1
+
+#define FCOE_TASK_CLASS_TYPE_3			0
+#define FCOE_TASK_CLASS_TYPE_2			1
+
+/* Everest FCoE connection type */
+#define B577XX_FCOE_CONNECTION_TYPE		4
+
+/* Error codes for Error Reporting in fast path flows */
+/* XFER error codes */
+#define FCOE_ERROR_CODE_XFER_OOO_RO					0
+#define FCOE_ERROR_CODE_XFER_RO_NOT_ALIGNED				1
+#define FCOE_ERROR_CODE_XFER_NULL_BURST_LEN				2
+#define FCOE_ERROR_CODE_XFER_RO_GREATER_THAN_DATA2TRNS			3
+#define FCOE_ERROR_CODE_XFER_INVALID_PAYLOAD_SIZE			4
+#define FCOE_ERROR_CODE_XFER_TASK_TYPE_NOT_WRITE			5
+#define FCOE_ERROR_CODE_XFER_PEND_XFER_SET				6
+#define FCOE_ERROR_CODE_XFER_OPENED_SEQ					7
+#define FCOE_ERROR_CODE_XFER_FCTL					8
+
+/* FCP RSP error codes */
+#define FCOE_ERROR_CODE_FCP_RSP_BIDI_FLAGS_SET				9
+#define FCOE_ERROR_CODE_FCP_RSP_UNDERFLOW				10
+#define FCOE_ERROR_CODE_FCP_RSP_OVERFLOW				11
+#define FCOE_ERROR_CODE_FCP_RSP_INVALID_LENGTH_FIELD			12
+#define FCOE_ERROR_CODE_FCP_RSP_INVALID_SNS_FIELD			13
+#define FCOE_ERROR_CODE_FCP_RSP_INVALID_PAYLOAD_SIZE			14
+#define FCOE_ERROR_CODE_FCP_RSP_PEND_XFER_SET				15
+#define FCOE_ERROR_CODE_FCP_RSP_OPENED_SEQ				16
+#define FCOE_ERROR_CODE_FCP_RSP_FCTL					17
+#define FCOE_ERROR_CODE_FCP_RSP_LAST_SEQ_RESET				18
+#define FCOE_ERROR_CODE_FCP_RSP_CONF_REQ_NOT_SUPPORTED_YET		19
+
+/* FCP DATA error codes */
+#define FCOE_ERROR_CODE_DATA_OOO_RO					20
+#define FCOE_ERROR_CODE_DATA_EXCEEDS_DEFINED_MAX_FRAME_SIZE		21
+#define FCOE_ERROR_CODE_DATA_EXCEEDS_DATA2TRNS				22
+#define FCOE_ERROR_CODE_DATA_SOFI3_SEQ_ACTIVE_SET			23
+#define FCOE_ERROR_CODE_DATA_SOFN_SEQ_ACTIVE_RESET			24
+#define FCOE_ERROR_CODE_DATA_EOFN_END_SEQ_SET				25
+#define FCOE_ERROR_CODE_DATA_EOFT_END_SEQ_RESET			26
+#define FCOE_ERROR_CODE_DATA_TASK_TYPE_NOT_READ			27
+#define FCOE_ERROR_CODE_DATA_FCTL					28
+
+/* Middle path error codes */
+#define FCOE_ERROR_CODE_MIDPATH_TYPE_NOT_ELS				29
+#define FCOE_ERROR_CODE_MIDPATH_SOFI3_SEQ_ACTIVE_SET			30
+#define FCOE_ERROR_CODE_MIDPATH_SOFN_SEQ_ACTIVE_RESET			31
+#define FCOE_ERROR_CODE_MIDPATH_EOFN_END_SEQ_SET			32
+#define FCOE_ERROR_CODE_MIDPATH_EOFT_END_SEQ_RESET			33
+#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_FCTL				34
+#define FCOE_ERROR_CODE_MIDPATH_INVALID_REPLY				35
+#define FCOE_ERROR_CODE_MIDPATH_ELS_REPLY_RCTL				36
+
+/* ABTS error codes */
+#define FCOE_ERROR_CODE_ABTS_REPLY_F_CTL				37
+#define FCOE_ERROR_CODE_ABTS_REPLY_DDF_RCTL_FIELD			38
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_BLS_RCTL			39
+#define FCOE_ERROR_CODE_ABTS_REPLY_INVALID_RCTL			40
+#define FCOE_ERROR_CODE_ABTS_REPLY_RCTL_GENERAL_MISMATCH		41
+
+/* Common error codes */
+#define FCOE_ERROR_CODE_COMMON_MIDDLE_FRAME_WITH_PAD			42
+#define FCOE_ERROR_CODE_COMMON_SEQ_INIT_IN_TCE				43
+#define FCOE_ERROR_CODE_COMMON_FC_HDR_RX_ID_MISMATCH			44
+#define FCOE_ERROR_CODE_COMMON_INCORRECT_SEQ_CNT			45
+#define FCOE_ERROR_CODE_COMMON_DATA_FC_HDR_FCP_TYPE_MISMATCH		46
+#define FCOE_ERROR_CODE_COMMON_DATA_NO_MORE_SGES			47
+#define FCOE_ERROR_CODE_COMMON_OPTIONAL_FC_HDR				48
+#define FCOE_ERROR_CODE_COMMON_READ_TCE_OX_ID_TOO_BIG			49
+#define FCOE_ERROR_CODE_COMMON_DATA_WAS_NOT_TRANSMITTED		50
+
+/* Unsolicited Rx error codes */
+#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_ELS			51
+#define FCOE_ERROR_CODE_UNSOLICITED_TYPE_NOT_BLS			52
+#define FCOE_ERROR_CODE_UNSOLICITED_FCTL_ELS				53
+#define FCOE_ERROR_CODE_UNSOLICITED_FCTL_BLS				54
+#define FCOE_ERROR_CODE_UNSOLICITED_R_CTL				55
+
+#define FCOE_ERROR_CODE_RW_TASK_DDF_RCTL_INFO_FIELD			56
+#define FCOE_ERROR_CODE_RW_TASK_INVALID_RCTL				57
+#define FCOE_ERROR_CODE_RW_TASK_RCTL_GENERAL_MISMATCH			58
+
+/* Timer error codes */
+#define FCOE_ERROR_CODE_E_D_TOV_TIMER_EXPIRATION			60
+#define FCOE_ERROR_CODE_REC_TOV_TIMER_EXPIRATION			61
+
+
+#endif /* BNX2FC_CONSTANTS_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,70 @@
+#ifndef __BNX2FC_DEBUG__
+#define __BNX2FC_DEBUG__
+
+/* Log level bit mask */
+#define LOG_IO		0x01	/* scsi cmd error, cleanup */
+#define LOG_TGT		0x02	/* Session setup, cleanup, etc' */
+#define LOG_HBA		0x04	/* lport events, link, mtu, etc' */
+#define LOG_ELS		0x08	/* ELS logs */
+#define LOG_MISC	0x10	/* fcoe L2 frame related logs*/
+#define LOG_ALL		0xff	/* LOG all messages */
+
+extern unsigned int bnx2fc_debug_level;
+
+#define BNX2FC_CHK_LOGGING(LEVEL, CMD)					\
+	do {								\
+		if (unlikely(bnx2fc_debug_level & LEVEL))		\
+			do {						\
+				CMD;					\
+			} while (0);					\
+	} while (0)
+
+#define BNX2FC_ELS_DBG(fmt, arg...)					\
+	BNX2FC_CHK_LOGGING(LOG_ELS,					\
+			   printk(KERN_ALERT PFX fmt, ##arg))
+
+#define BNX2FC_MISC_DBG(fmt, arg...)					\
+	BNX2FC_CHK_LOGGING(LOG_MISC,					\
+			   printk(KERN_ALERT PFX fmt, ##arg))
+
+#define BNX2FC_IO_DBG(io_req, fmt, arg...)				\
+	do {								\
+		if (!io_req || !io_req->port || !io_req->port->lport ||	\
+		    !io_req->port->lport->host)				\
+			BNX2FC_CHK_LOGGING(LOG_IO,			\
+			   printk(KERN_ALERT PFX "NULL " fmt, ##arg));	\
+		else							\
+			BNX2FC_CHK_LOGGING(LOG_IO,			\
+			   shost_printk(KERN_ALERT,			\
+				   (io_req)->port->lport->host,		\
+				   PFX "xid:0x%x " fmt,			\
+				   (io_req)->xid, ##arg));		\
+	} while (0)
+
+#define BNX2FC_TGT_DBG(tgt, fmt, arg...)				\
+	do {								\
+		if (!tgt || !tgt->port || !tgt->port->lport ||		\
+		    !tgt->port->lport->host || !tgt->rport)		\
+			BNX2FC_CHK_LOGGING(LOG_TGT,			\
+			   printk(KERN_ALERT PFX "NULL " fmt, ##arg));	\
+		else							\
+			BNX2FC_CHK_LOGGING(LOG_TGT,			\
+			   shost_printk(KERN_ALERT,			\
+				   (tgt)->port->lport->host,		\
+				   PFX "port:%x " fmt,			\
+				   (tgt)->rport->port_id, ##arg));	\
+	} while (0)
+
+
+#define BNX2FC_HBA_DBG(lport, fmt, arg...)				\
+	do {								\
+		if (!lport || !lport->host)				\
+			BNX2FC_CHK_LOGGING(LOG_HBA,			\
+			   printk(KERN_ALERT PFX "NULL " fmt, ##arg));	\
+		else							\
+			BNX2FC_CHK_LOGGING(LOG_HBA,			\
+			   shost_printk(KERN_ALERT, lport->host,	\
+				   PFX fmt, ##arg));			\
+	} while (0)
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_els.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,515 @@
+/*
+ * bnx2fc_els.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * This file contains helper routines that handle ELS requests
+ * and responses.
+ *
+ * Copyright (c) 2008 - 2010 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.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
+			     void *arg);
+static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
+			      void *arg);
+static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
+			void *data, u32 data_len,
+			void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
+			struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec);
+
+static void bnx2fc_rrq_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+	struct bnx2fc_cmd *orig_io_req;
+	struct bnx2fc_cmd *rrq_req;
+	int rc = 0;
+
+	BUG_ON(!cb_arg);
+	rrq_req = cb_arg->io_req;
+	orig_io_req = cb_arg->aborted_io_req;
+	BUG_ON(!orig_io_req);
+	BNX2FC_ELS_DBG("rrq_compl: orig xid = 0x%x, rrq_xid = 0x%x\n",
+		   orig_io_req->xid, rrq_req->xid);
+
+	kref_put(&orig_io_req->refcount, bnx2fc_cmd_release);
+
+	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &rrq_req->req_flags)) {
+		/*
+		 * els req is timed out. cleanup the IO with FW and
+		 * drop the completion. Remove from active_cmd_queue.
+		 */
+		BNX2FC_ELS_DBG("rrq xid - 0x%x timed out, clean it up\n",
+			   rrq_req->xid);
+
+		if (rrq_req->on_active_queue) {
+			list_del_init(&rrq_req->link);
+			rrq_req->on_active_queue = 0;
+			rc = bnx2fc_initiate_cleanup(rrq_req);
+			BUG_ON(rc);
+		}
+	}
+	kfree(cb_arg);
+}
+int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req)
+{
+
+	struct fc_els_rrq rrq;
+	struct bnx2fc_rport *tgt = aborted_io_req->tgt;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	struct bnx2fc_els_cb_arg *cb_arg = NULL;
+	u32 sid = tgt->sid;
+	u32 r_a_tov = lport->r_a_tov;
+	unsigned long start = jiffies;
+	int rc;
+
+	BNX2FC_ELS_DBG("Sending RRQ orig_xid = 0x%x\n",
+		   aborted_io_req->xid);
+	memset(&rrq, 0, sizeof(rrq));
+
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_NOIO);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for RRQ\n");
+		rc = -ENOMEM;
+		goto rrq_err;
+	}
+
+	cb_arg->aborted_io_req = aborted_io_req;
+
+	rrq.rrq_cmd = ELS_RRQ;
+	hton24(rrq.rrq_s_id, sid);
+	rrq.rrq_ox_id = htons(aborted_io_req->xid);
+	rrq.rrq_rx_id = htons(aborted_io_req->task->rx_wr_tx_rd.rx_id);
+
+retry_rrq:
+	rc = bnx2fc_initiate_els(tgt, ELS_RRQ, &rrq, sizeof(rrq),
+				 bnx2fc_rrq_compl, cb_arg,
+				 r_a_tov);
+	if (rc == -ENOMEM) {
+		if (time_after(jiffies, start + (10 * HZ))) {
+			BNX2FC_ELS_DBG("rrq Failed\n");
+			rc = FAILED;
+			goto rrq_err;
+		}
+		msleep(20);
+		goto retry_rrq;
+	}
+rrq_err:
+	if (rc) {
+		BNX2FC_ELS_DBG("RRQ failed - release orig io req 0x%x\n",
+			aborted_io_req->xid);
+		kfree(cb_arg);
+		spin_lock_bh(&tgt->tgt_lock);
+		kref_put(&aborted_io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+	}
+	return rc;
+}
+
+static void bnx2fc_l2_els_compl(struct bnx2fc_els_cb_arg *cb_arg)
+{
+	struct bnx2fc_cmd *els_req;
+	struct bnx2fc_rport *tgt;
+	struct bnx2fc_mp_req *mp_req;
+	struct fc_frame_header *fc_hdr;
+	unsigned char *buf;
+	void *resp_buf;
+	u32 resp_len, hdr_len;
+	u16 l2_oxid;
+	int frame_len;
+	int rc = 0;
+
+	l2_oxid = cb_arg->l2_oxid;
+	BNX2FC_ELS_DBG("ELS COMPL - l2_oxid = 0x%x\n", l2_oxid);
+
+	els_req = cb_arg->io_req;
+	if (test_and_clear_bit(BNX2FC_FLAG_ELS_TIMEOUT, &els_req->req_flags)) {
+		/*
+		 * els req is timed out. cleanup the IO with FW and
+		 * drop the completion. libfc will handle the els timeout
+		 */
+		if (els_req->on_active_queue) {
+			list_del_init(&els_req->link);
+			els_req->on_active_queue = 0;
+			rc = bnx2fc_initiate_cleanup(els_req);
+			BUG_ON(rc);
+		}
+		goto free_arg;
+	}
+
+	tgt = els_req->tgt;
+	mp_req = &(els_req->mp_req);
+	fc_hdr = &(mp_req->resp_fc_hdr);
+	resp_len = mp_req->resp_len;
+	resp_buf = mp_req->resp_buf;
+
+	buf = kzalloc(PAGE_SIZE, GFP_ATOMIC);
+	if (!buf) {
+		printk(KERN_ERR PFX "Unable to alloc mp buf\n");
+		goto free_arg;
+	}
+	hdr_len = sizeof(*fc_hdr);
+	if (hdr_len + resp_len > PAGE_SIZE) {
+		printk(KERN_ERR PFX "l2_els_compl: resp len is "
+				    "beyond page size\n");
+		goto free_buf;
+	}
+	memcpy(buf, fc_hdr, hdr_len);
+	memcpy(buf + hdr_len, resp_buf, resp_len);
+	frame_len = hdr_len + resp_len;
+
+	bnx2fc_process_l2_frame_compl(tgt, buf, frame_len, l2_oxid);
+
+free_buf:
+	kfree(buf);
+free_arg:
+	kfree(cb_arg);
+}
+
+int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp)
+{
+	struct fc_els_adisc *adisc;
+	struct fc_frame_header *fh;
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	u32 r_a_tov = lport->r_a_tov;
+	int rc;
+
+	fh = fc_frame_header_get(fp);
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for ADISC\n");
+		return -ENOMEM;
+	}
+
+	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
+
+	BNX2FC_ELS_DBG("send ADISC: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
+	adisc = fc_frame_payload_get(fp, sizeof(*adisc));
+	/* adisc is initialized by libfc */
+	rc = bnx2fc_initiate_els(tgt, ELS_ADISC, adisc, sizeof(*adisc),
+				 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
+	if (rc)
+		kfree(cb_arg);
+	return rc;
+}
+
+int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp)
+{
+	struct fc_els_logo *logo;
+	struct fc_frame_header *fh;
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	u32 r_a_tov = lport->r_a_tov;
+	int rc;
+
+	fh = fc_frame_header_get(fp);
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
+		return -ENOMEM;
+	}
+
+	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
+
+	BNX2FC_ELS_DBG("Send LOGO: l2_oxid = 0x%x\n", cb_arg->l2_oxid);
+	logo = fc_frame_payload_get(fp, sizeof(*logo));
+	/* logo is initialized by libfc */
+	rc = bnx2fc_initiate_els(tgt, ELS_LOGO, logo, sizeof(*logo),
+				 bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
+	if (rc)
+		kfree(cb_arg);
+	return rc;
+}
+
+int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp)
+{
+	struct fc_els_rls *rls;
+	struct fc_frame_header *fh;
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct fc_lport *lport = tgt->rdata->local_port;
+	u32 r_a_tov = lport->r_a_tov;
+	int rc;
+
+	fh = fc_frame_header_get(fp);
+	cb_arg = kzalloc(sizeof(struct bnx2fc_els_cb_arg), GFP_ATOMIC);
+	if (!cb_arg) {
+		printk(KERN_ERR PFX "Unable to allocate cb_arg for LOGO\n");
+		return -ENOMEM;
+	}
+
+	cb_arg->l2_oxid = ntohs(fh->fh_ox_id);
+
+	rls = fc_frame_payload_get(fp, sizeof(*rls));
+	/* rls is initialized by libfc */
+	rc = bnx2fc_initiate_els(tgt, ELS_RLS, rls, sizeof(*rls),
+				  bnx2fc_l2_els_compl, cb_arg, 2 * r_a_tov);
+	if (rc)
+		kfree(cb_arg);
+	return rc;
+}
+
+static int bnx2fc_initiate_els(struct bnx2fc_rport *tgt, unsigned int op,
+			void *data, u32 data_len,
+			void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg),
+			struct bnx2fc_els_cb_arg *cb_arg, u32 timer_msec)
+{
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct fc_rport *rport = tgt->rport;
+	struct fc_lport *lport = port->lport;
+	struct bnx2fc_cmd *els_req;
+	struct bnx2fc_mp_req *mp_req;
+	struct fc_frame_header *fc_hdr;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	int rc = 0;
+	int task_idx, index;
+	u32 did, sid;
+	u16 xid;
+
+	rc = fc_remote_port_chkready(rport);
+	if (rc) {
+		printk(KERN_ALERT PFX "els 0x%x: rport not ready\n", op);
+		rc = -EINVAL;
+		goto els_err;
+	}
+	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+		printk(KERN_ALERT PFX "els 0x%x: link is not ready\n", op);
+		rc = -EINVAL;
+		goto els_err;
+	}
+	if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) ||
+	     (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags))) {
+		printk(KERN_ERR PFX "els 0x%x: tgt not ready\n", op);
+		rc = -EINVAL;
+		goto els_err;
+	}
+	els_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ELS);
+	if (!els_req) {
+		rc = -ENOMEM;
+		goto els_err;
+	}
+
+	els_req->sc_cmd = NULL;
+	els_req->port = port;
+	els_req->tgt = tgt;
+	els_req->cb_func = cb_func;
+	cb_arg->io_req = els_req;
+	els_req->cb_arg = cb_arg;
+
+	mp_req = (struct bnx2fc_mp_req *)&(els_req->mp_req);
+	rc = bnx2fc_init_mp_req(els_req);
+	if (rc == FAILED) {
+		printk(KERN_ALERT PFX "ELS MP request init failed\n");
+		spin_lock_bh(&tgt->tgt_lock);
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		rc = -ENOMEM;
+		goto els_err;
+	} else {
+		/* rc SUCCESS */
+		rc = 0;
+	}
+
+	/* Set the data_xfer_len to the size of ELS payload */
+	mp_req->req_len = data_len;
+	els_req->data_xfer_len = mp_req->req_len;
+
+	/* Fill ELS Payload */
+	if ((op >= ELS_LS_RJT) && (op <= ELS_AUTH_ELS)) {
+		memcpy(mp_req->req_buf, data, data_len);
+	} else {
+		printk(KERN_ALERT PFX "Invalid ELS op 0x%x\n", op);
+		els_req->cb_func = NULL;
+		els_req->cb_arg = NULL;
+		spin_lock_bh(&tgt->tgt_lock);
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		rc = -EINVAL;
+	}
+
+	if (rc)
+		goto els_err;
+
+	/* Fill FC header */
+	fc_hdr = &(mp_req->req_fc_hdr);
+
+	did = tgt->rport->port_id;
+	sid = tgt->sid;
+
+	__fc_fill_fc_hdr(fc_hdr, FC_RCTL_ELS_REQ, did, sid,
+			   FC_TYPE_ELS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+			   FC_FC_SEQ_INIT, 0);
+
+	/* Obtain exchange id */
+	xid = els_req->xid;
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_mp_task(els_req, task);
+
+	spin_lock_bh(&tgt->tgt_lock);
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		printk(KERN_ERR PFX "initiate_els.. session not ready\n");
+		els_req->cb_func = NULL;
+		els_req->cb_arg = NULL;
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return -EINVAL;
+	}
+
+	if (timer_msec)
+		bnx2fc_cmd_timer_set(els_req, timer_msec);
+	bnx2fc_add_2_sq(tgt, xid);
+
+	els_req->on_active_queue = 1;
+	list_add_tail(&els_req->link, &tgt->els_queue);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+	spin_unlock_bh(&tgt->tgt_lock);
+
+els_err:
+	return rc;
+}
+
+void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
+			      struct fcoe_task_ctx_entry *task, u8 num_rq)
+{
+	struct bnx2fc_mp_req *mp_req;
+	struct fc_frame_header *fc_hdr;
+	u64 *hdr;
+	u64 *temp_hdr;
+
+	BNX2FC_ELS_DBG("Entered process_els_compl xid = 0x%x"
+			"cmd_type = %d\n", els_req->xid, els_req->cmd_type);
+
+	if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
+			     &els_req->req_flags)) {
+		BNX2FC_ELS_DBG("Timer context finished processing this "
+			   "els - 0x%x\n", els_req->xid);
+		/* This IO doesn't receive cleanup completion */
+		kref_put(&els_req->refcount, bnx2fc_cmd_release);
+		return;
+	}
+
+	/* Cancel the timeout_work, as we received the response */
+	if (cancel_delayed_work(&els_req->timeout_work))
+		kref_put(&els_req->refcount,
+			 bnx2fc_cmd_release); /* drop timer hold */
+
+	if (els_req->on_active_queue) {
+		list_del_init(&els_req->link);
+		els_req->on_active_queue = 0;
+	}
+
+	mp_req = &(els_req->mp_req);
+	fc_hdr = &(mp_req->resp_fc_hdr);
+
+	hdr = (u64 *)fc_hdr;
+	temp_hdr = (u64 *)
+		&task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	hdr[0] = cpu_to_be64(temp_hdr[0]);
+	hdr[1] = cpu_to_be64(temp_hdr[1]);
+	hdr[2] = cpu_to_be64(temp_hdr[2]);
+
+	mp_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+
+	/* Parse ELS response */
+	if ((els_req->cb_func) && (els_req->cb_arg)) {
+		els_req->cb_func(els_req->cb_arg);
+		els_req->cb_arg = NULL;
+	}
+
+	kref_put(&els_req->refcount, bnx2fc_cmd_release);
+}
+
+static void bnx2fc_flogi_resp(struct fc_seq *seq, struct fc_frame *fp,
+			      void *arg)
+{
+	struct fcoe_ctlr *fip = arg;
+	struct fc_exch *exch = fc_seq_exch(seq);
+	struct fc_lport *lport = exch->lp;
+	u8 *mac;
+	struct fc_frame_header *fh;
+	u8 op;
+
+	if (IS_ERR(fp))
+		goto done;
+
+	mac = fr_cb(fp)->granted_mac;
+	if (is_zero_ether_addr(mac)) {
+		fh = fc_frame_header_get(fp);
+		if (fh->fh_type != FC_TYPE_ELS) {
+			printk(KERN_ERR PFX "bnx2fc_flogi_resp:"
+				"fh_type != FC_TYPE_ELS\n");
+			fc_frame_free(fp);
+			return;
+		}
+		op = fc_frame_payload_op(fp);
+		if (lport->vport) {
+			if (op == ELS_LS_RJT) {
+				printk(KERN_ERR PFX "bnx2fc_flogi_resp is LS_RJT\n");
+				fc_vport_terminate(lport->vport);
+				fc_frame_free(fp);
+				return;
+			}
+		}
+		if (fcoe_ctlr_recv_flogi(fip, lport, fp)) {
+			fc_frame_free(fp);
+			return;
+		}
+	}
+	fip->update_mac(lport, mac);
+done:
+	fc_lport_flogi_resp(seq, fp, lport);
+}
+
+static void bnx2fc_logo_resp(struct fc_seq *seq, struct fc_frame *fp,
+			     void *arg)
+{
+	struct fcoe_ctlr *fip = arg;
+	struct fc_exch *exch = fc_seq_exch(seq);
+	struct fc_lport *lport = exch->lp;
+	static u8 zero_mac[ETH_ALEN] = { 0 };
+
+	if (!IS_ERR(fp))
+		fip->update_mac(lport, zero_mac);
+	fc_lport_logo_resp(seq, fp, lport);
+}
+
+struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
+				      struct fc_frame *fp, unsigned int op,
+				      void (*resp)(struct fc_seq *,
+						   struct fc_frame *,
+						   void *),
+				      void *arg, u32 timeout)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_ctlr *fip = &hba->ctlr;
+	struct fc_frame_header *fh = fc_frame_header_get(fp);
+
+	switch (op) {
+	case ELS_FLOGI:
+	case ELS_FDISC:
+		return fc_elsct_send(lport, did, fp, op, bnx2fc_flogi_resp,
+				     fip, timeout);
+	case ELS_LOGO:
+		/* only hook onto fabric logouts, not port logouts */
+		if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
+			break;
+		return fc_elsct_send(lport, did, fp, op, bnx2fc_logo_resp,
+				     fip, timeout);
+	}
+	return fc_elsct_send(lport, did, fp, op, resp, arg, timeout);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_fcoe.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2461 @@
+/* bnx2fc_fcoe.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * This file contains the code that interacts with libfc, libfcoe,
+ * cnic modules to create FCoE instances, send/receive non-offloaded
+ * FIP/FCoE packets, listen to link events etc.
+ *
+ * Copyright (c) 2008 - 2010 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.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+static struct list_head adapter_list;
+static u32 adapter_count;
+static DEFINE_MUTEX(bnx2fc_dev_lock);
+DEFINE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
+
+#define DRV_MODULE_NAME		"bnx2fc"
+#define DRV_MODULE_VERSION	BNX2FC_VERSION
+#define DRV_MODULE_RELDATE	"Mar 17, 2011"
+
+
+static char version[] __devinitdata =
+		"Broadcom NetXtreme II FCoE Driver " DRV_MODULE_NAME \
+		" v" DRV_MODULE_VERSION " (" DRV_MODULE_RELDATE ")\n";
+
+
+MODULE_AUTHOR("Bhanu Prakash Gollapudi <bprakash@broadcom.com>");
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM57710 FCoE Driver");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+#define BNX2FC_MAX_QUEUE_DEPTH	256
+#define BNX2FC_MIN_QUEUE_DEPTH	32
+#define FCOE_WORD_TO_BYTE  4
+
+static struct scsi_transport_template	*bnx2fc_transport_template;
+static struct scsi_transport_template	*bnx2fc_vport_xport_template;
+
+struct workqueue_struct *bnx2fc_wq;
+
+/* bnx2fc structure needs only one instance of the fcoe_percpu_s structure.
+ * Here the io threads are per cpu but the l2 thread is just one
+ */
+struct fcoe_percpu_s bnx2fc_global;
+DEFINE_SPINLOCK(bnx2fc_global_lock);
+
+static struct cnic_ulp_ops bnx2fc_cnic_cb;
+static struct libfc_function_template bnx2fc_libfc_fcn_templ;
+static struct scsi_host_template bnx2fc_shost_template;
+static struct fc_function_template bnx2fc_transport_function;
+static struct fc_function_template bnx2fc_vport_xport_function;
+static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode);
+static int bnx2fc_destroy(struct net_device *net_device);
+static int bnx2fc_enable(struct net_device *netdev);
+static int bnx2fc_disable(struct net_device *netdev);
+
+static void bnx2fc_recv_frame(struct sk_buff *skb);
+
+static void bnx2fc_start_disc(struct bnx2fc_hba *hba);
+static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev);
+static int bnx2fc_net_config(struct fc_lport *lp);
+static int bnx2fc_lport_config(struct fc_lport *lport);
+static int bnx2fc_em_config(struct fc_lport *lport);
+static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba);
+static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba);
+static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba);
+static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba);
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+				  struct device *parent, int npiv);
+static void bnx2fc_destroy_work(struct work_struct *work);
+
+static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev);
+static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic);
+
+static int bnx2fc_fw_init(struct bnx2fc_hba *hba);
+static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba);
+
+static void bnx2fc_port_shutdown(struct fc_lport *lport);
+static void bnx2fc_stop(struct bnx2fc_hba *hba);
+static int __init bnx2fc_mod_init(void);
+static void __exit bnx2fc_mod_exit(void);
+
+unsigned int bnx2fc_debug_level;
+module_param_named(debug_logging, bnx2fc_debug_level, int, S_IRUGO|S_IWUSR);
+
+static int bnx2fc_cpu_callback(struct notifier_block *nfb,
+			     unsigned long action, void *hcpu);
+/* notification function for CPU hotplug events */
+static struct notifier_block bnx2fc_cpu_notifier = {
+	.notifier_call = bnx2fc_cpu_callback,
+};
+
+static void bnx2fc_clean_rx_queue(struct fc_lport *lp)
+{
+	struct fcoe_percpu_s *bg;
+	struct fcoe_rcv_info *fr;
+	struct sk_buff_head *list;
+	struct sk_buff *skb, *next;
+	struct sk_buff *head;
+
+	bg = &bnx2fc_global;
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+	list = &bg->fcoe_rx_list;
+	head = list->next;
+	for (skb = head; skb != (struct sk_buff *)list;
+	     skb = next) {
+		next = skb->next;
+		fr = fcoe_dev_from_skb(skb);
+		if (fr->fr_dev == lp) {
+			__skb_unlink(skb, list);
+			kfree_skb(skb);
+		}
+	}
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+}
+
+int bnx2fc_get_paged_crc_eof(struct sk_buff *skb, int tlen)
+{
+	int rc;
+	spin_lock(&bnx2fc_global_lock);
+	rc = fcoe_get_paged_crc_eof(skb, tlen, &bnx2fc_global);
+	spin_unlock(&bnx2fc_global_lock);
+
+	return rc;
+}
+
+static void bnx2fc_abort_io(struct fc_lport *lport)
+{
+	/*
+	 * This function is no-op for bnx2fc, but we do
+	 * not want to leave it as NULL either, as libfc
+	 * can call the default function which is
+	 * fc_fcp_abort_io.
+	 */
+}
+
+static void bnx2fc_cleanup(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_rport *tgt;
+	int i;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	mutex_lock(&hba->hba_mutex);
+	spin_lock_bh(&hba->hba_lock);
+	for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
+		tgt = hba->tgt_ofld_list[i];
+		if (tgt) {
+			/* Cleanup IOs belonging to requested vport */
+			if (tgt->port == port) {
+				spin_unlock_bh(&hba->hba_lock);
+				BNX2FC_TGT_DBG(tgt, "flush/cleanup\n");
+				bnx2fc_flush_active_ios(tgt);
+				spin_lock_bh(&hba->hba_lock);
+			}
+		}
+	}
+	spin_unlock_bh(&hba->hba_lock);
+	mutex_unlock(&hba->hba_mutex);
+}
+
+static int bnx2fc_xmit_l2_frame(struct bnx2fc_rport *tgt,
+			     struct fc_frame *fp)
+{
+	struct fc_rport_priv *rdata = tgt->rdata;
+	struct fc_frame_header *fh;
+	int rc = 0;
+
+	fh = fc_frame_header_get(fp);
+	BNX2FC_TGT_DBG(tgt, "Xmit L2 frame rport = 0x%x, oxid = 0x%x, "
+			"r_ctl = 0x%x\n", rdata->ids.port_id,
+			ntohs(fh->fh_ox_id), fh->fh_r_ctl);
+	if ((fh->fh_type == FC_TYPE_ELS) &&
+	    (fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
+
+		switch (fc_frame_payload_op(fp)) {
+		case ELS_ADISC:
+			rc = bnx2fc_send_adisc(tgt, fp);
+			break;
+		case ELS_LOGO:
+			rc = bnx2fc_send_logo(tgt, fp);
+			break;
+		case ELS_RLS:
+			rc = bnx2fc_send_rls(tgt, fp);
+			break;
+		default:
+			break;
+		}
+	} else if ((fh->fh_type ==  FC_TYPE_BLS) &&
+	    (fh->fh_r_ctl == FC_RCTL_BA_ABTS))
+		BNX2FC_TGT_DBG(tgt, "ABTS frame\n");
+	else {
+		BNX2FC_TGT_DBG(tgt, "Send L2 frame type 0x%x "
+				"rctl 0x%x thru non-offload path\n",
+				fh->fh_type, fh->fh_r_ctl);
+		return -ENODEV;
+	}
+	if (rc)
+		return -ENOMEM;
+	else
+		return 0;
+}
+
+/**
+ * bnx2fc_xmit - bnx2fc's FCoE frame transmit function
+ *
+ * @lport:	the associated local port
+ * @fp:	the fc_frame to be transmitted
+ */
+static int bnx2fc_xmit(struct fc_lport *lport, struct fc_frame *fp)
+{
+	struct ethhdr		*eh;
+	struct fcoe_crc_eof	*cp;
+	struct sk_buff		*skb;
+	struct fc_frame_header	*fh;
+	struct bnx2fc_hba	*hba;
+	struct fcoe_port	*port;
+	struct fcoe_hdr		*hp;
+	struct bnx2fc_rport	*tgt;
+	struct fcoe_dev_stats	*stats;
+	u8			sof, eof;
+	u32			crc;
+	unsigned int		hlen, tlen, elen;
+	int			wlen, rc = 0;
+
+	port = (struct fcoe_port *)lport_priv(lport);
+	hba = port->priv;
+
+	fh = fc_frame_header_get(fp);
+
+	skb = fp_skb(fp);
+	if (!lport->link_up) {
+		BNX2FC_HBA_DBG(lport, "bnx2fc_xmit link down\n");
+		kfree_skb(skb);
+		return 0;
+	}
+
+	if (unlikely(fh->fh_r_ctl == FC_RCTL_ELS_REQ)) {
+		if (!hba->ctlr.sel_fcf) {
+			BNX2FC_HBA_DBG(lport, "FCF not selected yet!\n");
+			kfree_skb(skb);
+			return -EINVAL;
+		}
+		if (fcoe_ctlr_els_send(&hba->ctlr, lport, skb))
+			return 0;
+	}
+
+	sof = fr_sof(fp);
+	eof = fr_eof(fp);
+
+	/*
+	 * Snoop the frame header to check if the frame is for
+	 * an offloaded session
+	 */
+	/*
+	 * tgt_ofld_list access is synchronized using
+	 * both hba mutex and hba lock. Atleast hba mutex or
+	 * hba lock needs to be held for read access.
+	 */
+
+	spin_lock_bh(&hba->hba_lock);
+	tgt = bnx2fc_tgt_lookup(port, ntoh24(fh->fh_d_id));
+	if (tgt && (test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
+		/* This frame is for offloaded session */
+		BNX2FC_HBA_DBG(lport, "xmit: Frame is for offloaded session "
+				"port_id = 0x%x\n", ntoh24(fh->fh_d_id));
+		spin_unlock_bh(&hba->hba_lock);
+		rc = bnx2fc_xmit_l2_frame(tgt, fp);
+		if (rc != -ENODEV) {
+			kfree_skb(skb);
+			return rc;
+		}
+	} else {
+		spin_unlock_bh(&hba->hba_lock);
+	}
+
+	elen = sizeof(struct ethhdr);
+	hlen = sizeof(struct fcoe_hdr);
+	tlen = sizeof(struct fcoe_crc_eof);
+	wlen = (skb->len - tlen + sizeof(crc)) / FCOE_WORD_TO_BYTE;
+
+	skb->ip_summed = CHECKSUM_NONE;
+	crc = fcoe_fc_crc(fp);
+
+	/* copy port crc and eof to the skb buff */
+	if (skb_is_nonlinear(skb)) {
+		skb_frag_t *frag;
+		if (bnx2fc_get_paged_crc_eof(skb, tlen)) {
+			kfree_skb(skb);
+			return -ENOMEM;
+		}
+		frag = &skb_shinfo(skb)->frags[skb_shinfo(skb)->nr_frags - 1];
+		cp = kmap_atomic(frag->page, KM_SKB_DATA_SOFTIRQ)
+				+ frag->page_offset;
+	} else {
+		cp = (struct fcoe_crc_eof *)skb_put(skb, tlen);
+	}
+
+	memset(cp, 0, sizeof(*cp));
+	cp->fcoe_eof = eof;
+	cp->fcoe_crc32 = cpu_to_le32(~crc);
+	if (skb_is_nonlinear(skb)) {
+		kunmap_atomic(cp, KM_SKB_DATA_SOFTIRQ);
+		cp = NULL;
+	}
+
+	/* adjust skb network/transport offsets to match mac/fcoe/port */
+	skb_push(skb, elen + hlen);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	skb->mac_len = elen;
+	skb->protocol = htons(ETH_P_FCOE);
+	skb->dev = hba->netdev;
+
+	/* fill up mac and fcoe headers */
+	eh = eth_hdr(skb);
+	eh->h_proto = htons(ETH_P_FCOE);
+	if (hba->ctlr.map_dest)
+		fc_fcoe_set_mac(eh->h_dest, fh->fh_d_id);
+	else
+		/* insert GW address */
+		memcpy(eh->h_dest, hba->ctlr.dest_addr, ETH_ALEN);
+
+	if (unlikely(hba->ctlr.flogi_oxid != FC_XID_UNKNOWN))
+		memcpy(eh->h_source, hba->ctlr.ctl_src_addr, ETH_ALEN);
+	else
+		memcpy(eh->h_source, port->data_src_addr, ETH_ALEN);
+
+	hp = (struct fcoe_hdr *)(eh + 1);
+	memset(hp, 0, sizeof(*hp));
+	if (FC_FCOE_VER)
+		FC_FCOE_ENCAPS_VER(hp, FC_FCOE_VER);
+	hp->fcoe_sof = sof;
+
+	/* fcoe lso, mss is in max_payload which is non-zero for FCP data */
+	if (lport->seq_offload && fr_max_payload(fp)) {
+		skb_shinfo(skb)->gso_type = SKB_GSO_FCOE;
+		skb_shinfo(skb)->gso_size = fr_max_payload(fp);
+	} else {
+		skb_shinfo(skb)->gso_type = 0;
+		skb_shinfo(skb)->gso_size = 0;
+	}
+
+	/*update tx stats */
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->TxFrames++;
+	stats->TxWords += wlen;
+	put_cpu();
+
+	/* send down to lld */
+	fr_dev(fp) = lport;
+	if (port->fcoe_pending_queue.qlen)
+		fcoe_check_wait_queue(lport, skb);
+	else if (fcoe_start_io(skb))
+		fcoe_check_wait_queue(lport, skb);
+
+	return 0;
+}
+
+/**
+ * bnx2fc_rcv - This is bnx2fc's receive function called by NET_RX_SOFTIRQ
+ *
+ * @skb:	the receive socket buffer
+ * @dev:	associated net device
+ * @ptype:	context
+ * @olddev:	last device
+ *
+ * This function receives the packet and builds FC frame and passes it up
+ */
+static int bnx2fc_rcv(struct sk_buff *skb, struct net_device *dev,
+		struct packet_type *ptype, struct net_device *olddev)
+{
+	struct fc_lport *lport;
+	struct bnx2fc_hba *hba;
+	struct fc_frame_header *fh;
+	struct fcoe_rcv_info *fr;
+	struct fcoe_percpu_s *bg;
+	unsigned short oxid;
+
+	hba = container_of(ptype, struct bnx2fc_hba, fcoe_packet_type);
+	lport = hba->ctlr.lp;
+
+	if (unlikely(lport == NULL)) {
+		printk(KERN_ALERT PFX "bnx2fc_rcv: lport is NULL\n");
+		goto err;
+	}
+
+	if (unlikely(eth_hdr(skb)->h_proto != htons(ETH_P_FCOE))) {
+		printk(KERN_ALERT PFX "bnx2fc_rcv: Wrong FC type frame\n");
+		goto err;
+	}
+
+	/*
+	 * Check for minimum frame length, and make sure required FCoE
+	 * and FC headers are pulled into the linear data area.
+	 */
+	if (unlikely((skb->len < FCOE_MIN_FRAME) ||
+	    !pskb_may_pull(skb, FCOE_HEADER_LEN)))
+		goto err;
+
+	skb_set_transport_header(skb, sizeof(struct fcoe_hdr));
+	fh = (struct fc_frame_header *) skb_transport_header(skb);
+
+	oxid = ntohs(fh->fh_ox_id);
+
+	fr = fcoe_dev_from_skb(skb);
+	fr->fr_dev = lport;
+	fr->ptype = ptype;
+
+	bg = &bnx2fc_global;
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+
+	__skb_queue_tail(&bg->fcoe_rx_list, skb);
+	if (bg->fcoe_rx_list.qlen == 1)
+		wake_up_process(bg->thread);
+
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+
+	return 0;
+err:
+	kfree_skb(skb);
+	return -1;
+}
+
+static int bnx2fc_l2_rcv_thread(void *arg)
+{
+	struct fcoe_percpu_s *bg = arg;
+	struct sk_buff *skb;
+
+	set_user_nice(current, -20);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (!kthread_should_stop()) {
+		schedule();
+		spin_lock_bh(&bg->fcoe_rx_list.lock);
+		while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL) {
+			spin_unlock_bh(&bg->fcoe_rx_list.lock);
+			bnx2fc_recv_frame(skb);
+			spin_lock_bh(&bg->fcoe_rx_list.lock);
+		}
+		__set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_bh(&bg->fcoe_rx_list.lock);
+	}
+	__set_current_state(TASK_RUNNING);
+	return 0;
+}
+
+
+static void bnx2fc_recv_frame(struct sk_buff *skb)
+{
+	u32 fr_len;
+	struct fc_lport *lport;
+	struct fcoe_rcv_info *fr;
+	struct fcoe_dev_stats *stats;
+	struct fc_frame_header *fh;
+	struct fcoe_crc_eof crc_eof;
+	struct fc_frame *fp;
+	struct fc_lport *vn_port;
+	struct fcoe_port *port;
+	u8 *mac = NULL;
+	u8 *dest_mac = NULL;
+	struct fcoe_hdr *hp;
+
+	fr = fcoe_dev_from_skb(skb);
+	lport = fr->fr_dev;
+	if (unlikely(lport == NULL)) {
+		printk(KERN_ALERT PFX "Invalid lport struct\n");
+		kfree_skb(skb);
+		return;
+	}
+
+	if (skb_is_nonlinear(skb))
+		skb_linearize(skb);
+	mac = eth_hdr(skb)->h_source;
+	dest_mac = eth_hdr(skb)->h_dest;
+
+	/* Pull the header */
+	hp = (struct fcoe_hdr *) skb_network_header(skb);
+	fh = (struct fc_frame_header *) skb_transport_header(skb);
+	skb_pull(skb, sizeof(struct fcoe_hdr));
+	fr_len = skb->len - sizeof(struct fcoe_crc_eof);
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->RxFrames++;
+	stats->RxWords += fr_len / FCOE_WORD_TO_BYTE;
+
+	fp = (struct fc_frame *)skb;
+	fc_frame_init(fp);
+	fr_dev(fp) = lport;
+	fr_sof(fp) = hp->fcoe_sof;
+	if (skb_copy_bits(skb, fr_len, &crc_eof, sizeof(crc_eof))) {
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+	fr_eof(fp) = crc_eof.fcoe_eof;
+	fr_crc(fp) = crc_eof.fcoe_crc32;
+	if (pskb_trim(skb, fr_len)) {
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+
+	fh = fc_frame_header_get(fp);
+
+	vn_port = fc_vport_id_lookup(lport, ntoh24(fh->fh_d_id));
+	if (vn_port) {
+		port = lport_priv(vn_port);
+		if (compare_ether_addr(port->data_src_addr, dest_mac)
+		    != 0) {
+			BNX2FC_HBA_DBG(lport, "fpma mismatch\n");
+			put_cpu();
+			kfree_skb(skb);
+			return;
+		}
+	}
+	if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA &&
+	    fh->fh_type == FC_TYPE_FCP) {
+		/* Drop FCP data. We dont this in L2 path */
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+	if (fh->fh_r_ctl == FC_RCTL_ELS_REQ &&
+	    fh->fh_type == FC_TYPE_ELS) {
+		switch (fc_frame_payload_op(fp)) {
+		case ELS_LOGO:
+			if (ntoh24(fh->fh_s_id) == FC_FID_FLOGI) {
+				/* drop non-FIP LOGO */
+				put_cpu();
+				kfree_skb(skb);
+				return;
+			}
+			break;
+		}
+	}
+	if (le32_to_cpu(fr_crc(fp)) !=
+			~crc32(~0, skb->data, fr_len)) {
+		if (stats->InvalidCRCCount < 5)
+			printk(KERN_WARNING PFX "dropping frame with "
+			       "CRC error\n");
+		stats->InvalidCRCCount++;
+		put_cpu();
+		kfree_skb(skb);
+		return;
+	}
+	put_cpu();
+	fc_exch_recv(lport, fp);
+}
+
+/**
+ * bnx2fc_percpu_io_thread - thread per cpu for ios
+ *
+ * @arg:	ptr to bnx2fc_percpu_info structure
+ */
+int bnx2fc_percpu_io_thread(void *arg)
+{
+	struct bnx2fc_percpu_s *p = arg;
+	struct bnx2fc_work *work, *tmp;
+	LIST_HEAD(work_list);
+
+	set_user_nice(current, -20);
+	set_current_state(TASK_INTERRUPTIBLE);
+	while (!kthread_should_stop()) {
+		schedule();
+		spin_lock_bh(&p->fp_work_lock);
+		while (!list_empty(&p->work_list)) {
+			list_splice_init(&p->work_list, &work_list);
+			spin_unlock_bh(&p->fp_work_lock);
+
+			list_for_each_entry_safe(work, tmp, &work_list, list) {
+				list_del_init(&work->list);
+				bnx2fc_process_cq_compl(work->tgt, work->wqe);
+				kfree(work);
+			}
+
+			spin_lock_bh(&p->fp_work_lock);
+		}
+		__set_current_state(TASK_INTERRUPTIBLE);
+		spin_unlock_bh(&p->fp_work_lock);
+	}
+	__set_current_state(TASK_RUNNING);
+
+	return 0;
+}
+
+static struct fc_host_statistics *bnx2fc_get_host_stats(struct Scsi_Host *shost)
+{
+	struct fc_host_statistics *bnx2fc_stats;
+	struct fc_lport *lport = shost_priv(shost);
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_statistics_params *fw_stats;
+	int rc = 0;
+
+	fw_stats = (struct fcoe_statistics_params *)hba->stats_buffer;
+	if (!fw_stats)
+		return NULL;
+
+	bnx2fc_stats = fc_get_host_stats(shost);
+
+	init_completion(&hba->stat_req_done);
+	if (bnx2fc_send_stat_req(hba))
+		return bnx2fc_stats;
+	rc = wait_for_completion_timeout(&hba->stat_req_done, (2 * HZ));
+	if (!rc) {
+		BNX2FC_HBA_DBG(lport, "FW stat req timed out\n");
+		return bnx2fc_stats;
+	}
+	bnx2fc_stats->invalid_crc_count += fw_stats->rx_stat1.fc_crc_cnt;
+	bnx2fc_stats->tx_frames += fw_stats->tx_stat.fcoe_tx_pkt_cnt;
+	bnx2fc_stats->tx_words += (fw_stats->tx_stat.fcoe_tx_byte_cnt) / 4;
+	bnx2fc_stats->rx_frames += fw_stats->rx_stat0.fcoe_rx_pkt_cnt;
+	bnx2fc_stats->rx_words += (fw_stats->rx_stat0.fcoe_rx_byte_cnt) / 4;
+
+	bnx2fc_stats->dumped_frames = 0;
+	bnx2fc_stats->lip_count = 0;
+	bnx2fc_stats->nos_count = 0;
+	bnx2fc_stats->loss_of_sync_count = 0;
+	bnx2fc_stats->loss_of_signal_count = 0;
+	bnx2fc_stats->prim_seq_protocol_err_count = 0;
+
+	return bnx2fc_stats;
+}
+
+static int bnx2fc_shost_config(struct fc_lport *lport, struct device *dev)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct Scsi_Host *shost = lport->host;
+	int rc = 0;
+
+	shost->max_cmd_len = BNX2FC_MAX_CMD_LEN;
+	shost->max_lun = BNX2FC_MAX_LUN;
+	shost->max_id = BNX2FC_MAX_FCP_TGT;
+	shost->max_channel = 0;
+	if (lport->vport)
+		shost->transportt = bnx2fc_vport_xport_template;
+	else
+		shost->transportt = bnx2fc_transport_template;
+
+	/* Add the new host to SCSI-ml */
+	rc = scsi_add_host(lport->host, dev);
+	if (rc) {
+		printk(KERN_ERR PFX "Error on scsi_add_host\n");
+		return rc;
+	}
+	if (!lport->vport)
+		fc_host_max_npiv_vports(lport->host) = USHRT_MAX;
+	sprintf(fc_host_symbolic_name(lport->host), "%s v%s over %s",
+		BNX2FC_NAME, BNX2FC_VERSION,
+		hba->netdev->name);
+
+	return 0;
+}
+
+static void bnx2fc_link_speed_update(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *netdev = hba->netdev;
+	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
+
+	if (!dev_ethtool_get_settings(netdev, &ecmd)) {
+		lport->link_supported_speeds &=
+			~(FC_PORTSPEED_1GBIT | FC_PORTSPEED_10GBIT);
+		if (ecmd.supported & (SUPPORTED_1000baseT_Half |
+				      SUPPORTED_1000baseT_Full))
+			lport->link_supported_speeds |= FC_PORTSPEED_1GBIT;
+		if (ecmd.supported & SUPPORTED_10000baseT_Full)
+			lport->link_supported_speeds |= FC_PORTSPEED_10GBIT;
+
+		if (ecmd.speed == SPEED_1000)
+			lport->link_speed = FC_PORTSPEED_1GBIT;
+		if (ecmd.speed == SPEED_10000)
+			lport->link_speed = FC_PORTSPEED_10GBIT;
+	}
+	return;
+}
+static int bnx2fc_link_ok(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *dev = hba->phys_dev;
+	int rc = 0;
+
+	if ((dev->flags & IFF_UP) && netif_carrier_ok(dev))
+		clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+	else {
+		set_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+		rc = -1;
+	}
+	return rc;
+}
+
+/**
+ * bnx2fc_get_link_state - get network link state
+ *
+ * @hba:	adapter instance pointer
+ *
+ * updates adapter structure flag based on netdev state
+ */
+void bnx2fc_get_link_state(struct bnx2fc_hba *hba)
+{
+	if (test_bit(__LINK_STATE_NOCARRIER, &hba->netdev->state))
+		set_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+	else
+		clear_bit(ADAPTER_STATE_LINK_DOWN, &hba->adapter_state);
+}
+
+static int bnx2fc_net_config(struct fc_lport *lport)
+{
+	struct bnx2fc_hba *hba;
+	struct fcoe_port *port;
+	u64 wwnn, wwpn;
+
+	port = lport_priv(lport);
+	hba = port->priv;
+
+	/* require support for get_pauseparam ethtool op. */
+	if (!hba->phys_dev->ethtool_ops ||
+	    !hba->phys_dev->ethtool_ops->get_pauseparam)
+		return -EOPNOTSUPP;
+
+	if (fc_set_mfs(lport, BNX2FC_MFS))
+		return -EINVAL;
+
+	skb_queue_head_init(&port->fcoe_pending_queue);
+	port->fcoe_pending_queue_active = 0;
+	setup_timer(&port->timer, fcoe_queue_timer, (unsigned long) lport);
+
+	bnx2fc_link_speed_update(lport);
+
+	if (!lport->vport) {
+		wwnn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 1, 0);
+		BNX2FC_HBA_DBG(lport, "WWNN = 0x%llx\n", wwnn);
+		fc_set_wwnn(lport, wwnn);
+
+		wwpn = fcoe_wwn_from_mac(hba->ctlr.ctl_src_addr, 2, 0);
+		BNX2FC_HBA_DBG(lport, "WWPN = 0x%llx\n", wwpn);
+		fc_set_wwpn(lport, wwpn);
+	}
+
+	return 0;
+}
+
+static void bnx2fc_destroy_timer(unsigned long data)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)data;
+
+	BNX2FC_HBA_DBG(hba->ctlr.lp, "ERROR:bnx2fc_destroy_timer - "
+		   "Destroy compl not received!!\n");
+	hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+	wake_up_interruptible(&hba->destroy_wait);
+}
+
+/**
+ * bnx2fc_indicate_netevent - Generic netdev event handler
+ *
+ * @context:	adapter structure pointer
+ * @event:	event type
+ *
+ * Handles NETDEV_UP, NETDEV_DOWN, NETDEV_GOING_DOWN,NETDEV_CHANGE and
+ * NETDEV_CHANGE_MTU events
+ */
+static void bnx2fc_indicate_netevent(void *context, unsigned long event)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
+	struct fc_lport *lport = hba->ctlr.lp;
+	struct fc_lport *vport;
+	u32 link_possible = 1;
+
+	if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		BNX2FC_MISC_DBG("driver not ready. event=%s %ld\n",
+			   hba->netdev->name, event);
+		return;
+	}
+
+	/*
+	 * ASSUMPTION:
+	 * indicate_netevent cannot be called from cnic unless bnx2fc
+	 * does register_device
+	 */
+	BUG_ON(!lport);
+
+	BNX2FC_HBA_DBG(lport, "enter netevent handler - event=%s %ld\n",
+				hba->netdev->name, event);
+
+	switch (event) {
+	case NETDEV_UP:
+		BNX2FC_HBA_DBG(lport, "Port up, adapter_state = %ld\n",
+			hba->adapter_state);
+		if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state))
+			printk(KERN_ERR "indicate_netevent: "\
+					"adapter is not UP!!\n");
+		break;
+
+	case NETDEV_DOWN:
+		BNX2FC_HBA_DBG(lport, "Port down\n");
+		clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+		clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+		link_possible = 0;
+		break;
+
+	case NETDEV_GOING_DOWN:
+		BNX2FC_HBA_DBG(lport, "Port going down\n");
+		set_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+		link_possible = 0;
+		break;
+
+	case NETDEV_CHANGE:
+		BNX2FC_HBA_DBG(lport, "NETDEV_CHANGE\n");
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unkonwn netevent %ld", event);
+		return;
+	}
+
+	bnx2fc_link_speed_update(lport);
+
+	if (link_possible && !bnx2fc_link_ok(lport)) {
+		printk(KERN_ERR "indicate_netevent: call ctlr_link_up\n");
+		fcoe_ctlr_link_up(&hba->ctlr);
+	} else {
+		printk(KERN_ERR "indicate_netevent: call ctlr_link_down\n");
+		if (fcoe_ctlr_link_down(&hba->ctlr)) {
+			clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+			mutex_lock(&lport->lp_mutex);
+			list_for_each_entry(vport, &lport->vports, list)
+				fc_host_port_type(vport->host) =
+							FC_PORTTYPE_UNKNOWN;
+			mutex_unlock(&lport->lp_mutex);
+			fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+			per_cpu_ptr(lport->dev_stats,
+				    get_cpu())->LinkFailureCount++;
+			put_cpu();
+			fcoe_clean_pending_queue(lport);
+
+			init_waitqueue_head(&hba->shutdown_wait);
+			BNX2FC_HBA_DBG(lport, "indicate_netevent "
+					     "num_ofld_sess = %d\n",
+				   hba->num_ofld_sess);
+			hba->wait_for_link_down = 1;
+			BNX2FC_HBA_DBG(lport, "waiting for uploads to "
+					     "compl proc = %s\n",
+				   current->comm);
+			wait_event_interruptible(hba->shutdown_wait,
+						 (hba->num_ofld_sess == 0));
+			BNX2FC_HBA_DBG(lport, "wakeup - num_ofld_sess = %d\n",
+				hba->num_ofld_sess);
+			hba->wait_for_link_down = 0;
+
+			if (signal_pending(current))
+				flush_signals(current);
+		}
+	}
+}
+
+static int bnx2fc_libfc_config(struct fc_lport *lport)
+{
+
+	/* Set the function pointers set by bnx2fc driver */
+	memcpy(&lport->tt, &bnx2fc_libfc_fcn_templ,
+		sizeof(struct libfc_function_template));
+	fc_elsct_init(lport);
+	fc_exch_init(lport);
+	fc_rport_init(lport);
+	fc_disc_init(lport);
+	return 0;
+}
+
+static int bnx2fc_em_config(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+
+	if (!fc_exch_mgr_alloc(lport, FC_CLASS_3, FCOE_MIN_XID,
+				FCOE_MAX_XID, NULL)) {
+		printk(KERN_ERR PFX "em_config:fc_exch_mgr_alloc failed\n");
+		return -ENOMEM;
+	}
+
+	hba->cmd_mgr = bnx2fc_cmd_mgr_alloc(hba, BNX2FC_MIN_XID,
+					    BNX2FC_MAX_XID);
+
+	if (!hba->cmd_mgr) {
+		printk(KERN_ERR PFX "em_config:bnx2fc_cmd_mgr_alloc failed\n");
+		fc_exch_mgr_free(lport);
+		return -ENOMEM;
+	}
+	return 0;
+}
+
+static int bnx2fc_lport_config(struct fc_lport *lport)
+{
+	lport->link_up = 0;
+	lport->qfull = 0;
+	lport->max_retry_count = 3;
+	lport->max_rport_retry_count = 3;
+	lport->e_d_tov = 2 * 1000;
+	lport->r_a_tov = 10 * 1000;
+
+	/* REVISIT: enable when supporting tape devices
+	lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS |
+				FCP_SPPF_RETRY | FCP_SPPF_CONF_COMPL);
+	*/
+	lport->service_params = (FCP_SPPF_INIT_FCN | FCP_SPPF_RD_XRDY_DIS);
+	lport->does_npiv = 1;
+
+	memset(&lport->rnid_gen, 0, sizeof(struct fc_els_rnid_gen));
+	lport->rnid_gen.rnid_atype = BNX2FC_RNID_HBA;
+
+	/* alloc stats structure */
+	if (fc_lport_init_stats(lport))
+		return -ENOMEM;
+
+	/* Finish fc_lport configuration */
+	fc_lport_config(lport);
+
+	return 0;
+}
+
+/**
+ * bnx2fc_fip_recv - handle a received FIP frame.
+ *
+ * @skb: the received skb
+ * @dev: associated &net_device
+ * @ptype: the &packet_type structure which was used to register this handler.
+ * @orig_dev: original receive &net_device, in case @ dev is a bond.
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_fip_recv(struct sk_buff *skb, struct net_device *dev,
+			   struct packet_type *ptype,
+			   struct net_device *orig_dev)
+{
+	struct bnx2fc_hba *hba;
+	hba = container_of(ptype, struct bnx2fc_hba, fip_packet_type);
+	fcoe_ctlr_recv(&hba->ctlr, skb);
+	return 0;
+}
+
+/**
+ * bnx2fc_update_src_mac - Update Ethernet MAC filters.
+ *
+ * @fip: FCoE controller.
+ * @old: Unicast MAC address to delete if the MAC is non-zero.
+ * @new: Unicast MAC address to add.
+ *
+ * Remove any previously-set unicast MAC filter.
+ * Add secondary FCoE MAC address filter for our OUI.
+ */
+static void bnx2fc_update_src_mac(struct fc_lport *lport, u8 *addr)
+{
+	struct fcoe_port *port = lport_priv(lport);
+
+	memcpy(port->data_src_addr, addr, ETH_ALEN);
+}
+
+/**
+ * bnx2fc_get_src_mac - return the ethernet source address for an lport
+ *
+ * @lport: libfc port
+ */
+static u8 *bnx2fc_get_src_mac(struct fc_lport *lport)
+{
+	struct fcoe_port *port;
+
+	port = (struct fcoe_port *)lport_priv(lport);
+	return port->data_src_addr;
+}
+
+/**
+ * bnx2fc_fip_send - send an Ethernet-encapsulated FIP frame.
+ *
+ * @fip: FCoE controller.
+ * @skb: FIP Packet.
+ */
+static void bnx2fc_fip_send(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	skb->dev = bnx2fc_from_ctlr(fip)->netdev;
+	dev_queue_xmit(skb);
+}
+
+static int bnx2fc_vport_create(struct fc_vport *vport, bool disabled)
+{
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_lport *n_port = shost_priv(shost);
+	struct fcoe_port *port = lport_priv(n_port);
+	struct bnx2fc_hba *hba = port->priv;
+	struct net_device *netdev = hba->netdev;
+	struct fc_lport *vn_port;
+
+	if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "vn ports cannot be created on"
+			"this hba\n");
+		return -EIO;
+	}
+	mutex_lock(&bnx2fc_dev_lock);
+	vn_port = bnx2fc_if_create(hba, &vport->dev, 1);
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	if (IS_ERR(vn_port)) {
+		printk(KERN_ERR PFX "bnx2fc_vport_create (%s) failed\n",
+			netdev->name);
+		return -EIO;
+	}
+
+	if (disabled) {
+		fc_vport_set_state(vport, FC_VPORT_DISABLED);
+	} else {
+		vn_port->boot_time = jiffies;
+		fc_lport_init(vn_port);
+		fc_fabric_login(vn_port);
+		fc_vport_setlink(vn_port);
+	}
+	return 0;
+}
+
+static int bnx2fc_vport_destroy(struct fc_vport *vport)
+{
+	struct Scsi_Host *shost = vport_to_shost(vport);
+	struct fc_lport *n_port = shost_priv(shost);
+	struct fc_lport *vn_port = vport->dd_data;
+	struct fcoe_port *port = lport_priv(vn_port);
+
+	mutex_lock(&n_port->lp_mutex);
+	list_del(&vn_port->list);
+	mutex_unlock(&n_port->lp_mutex);
+	queue_work(bnx2fc_wq, &port->destroy_work);
+	return 0;
+}
+
+static int bnx2fc_vport_disable(struct fc_vport *vport, bool disable)
+{
+	struct fc_lport *lport = vport->dd_data;
+
+	if (disable) {
+		fc_vport_set_state(vport, FC_VPORT_DISABLED);
+		fc_fabric_logoff(lport);
+	} else {
+		lport->boot_time = jiffies;
+		fc_fabric_login(lport);
+		fc_vport_setlink(lport);
+	}
+	return 0;
+}
+
+
+static int bnx2fc_netdev_setup(struct bnx2fc_hba *hba)
+{
+	struct net_device *netdev = hba->netdev;
+	struct net_device *physdev = hba->phys_dev;
+	struct netdev_hw_addr *ha;
+	int sel_san_mac = 0;
+
+	/* setup Source MAC Address */
+	rcu_read_lock();
+	for_each_dev_addr(physdev, ha) {
+		BNX2FC_MISC_DBG("net_config: ha->type = %d, fip_mac = ",
+				ha->type);
+		printk(KERN_INFO "%2x:%2x:%2x:%2x:%2x:%2x\n", ha->addr[0],
+				ha->addr[1], ha->addr[2], ha->addr[3],
+				ha->addr[4], ha->addr[5]);
+
+		if ((ha->type == NETDEV_HW_ADDR_T_SAN) &&
+		    (is_valid_ether_addr(ha->addr))) {
+			memcpy(hba->ctlr.ctl_src_addr, ha->addr, ETH_ALEN);
+			sel_san_mac = 1;
+			BNX2FC_MISC_DBG("Found SAN MAC\n");
+		}
+	}
+	rcu_read_unlock();
+
+	if (!sel_san_mac)
+		return -ENODEV;
+
+	hba->fip_packet_type.func = bnx2fc_fip_recv;
+	hba->fip_packet_type.type = htons(ETH_P_FIP);
+	hba->fip_packet_type.dev = netdev;
+	dev_add_pack(&hba->fip_packet_type);
+
+	hba->fcoe_packet_type.func = bnx2fc_rcv;
+	hba->fcoe_packet_type.type = __constant_htons(ETH_P_FCOE);
+	hba->fcoe_packet_type.dev = netdev;
+	dev_add_pack(&hba->fcoe_packet_type);
+
+	return 0;
+}
+
+static int bnx2fc_attach_transport(void)
+{
+	bnx2fc_transport_template =
+		fc_attach_transport(&bnx2fc_transport_function);
+
+	if (bnx2fc_transport_template == NULL) {
+		printk(KERN_ERR PFX "Failed to attach FC transport\n");
+		return -ENODEV;
+	}
+
+	bnx2fc_vport_xport_template =
+		fc_attach_transport(&bnx2fc_vport_xport_function);
+	if (bnx2fc_vport_xport_template == NULL) {
+		printk(KERN_ERR PFX
+		       "Failed to attach FC transport for vport\n");
+		fc_release_transport(bnx2fc_transport_template);
+		bnx2fc_transport_template = NULL;
+		return -ENODEV;
+	}
+	return 0;
+}
+static void bnx2fc_release_transport(void)
+{
+	fc_release_transport(bnx2fc_transport_template);
+	fc_release_transport(bnx2fc_vport_xport_template);
+	bnx2fc_transport_template = NULL;
+	bnx2fc_vport_xport_template = NULL;
+}
+
+static void bnx2fc_interface_release(struct kref *kref)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *netdev;
+	struct net_device *phys_dev;
+
+	hba = container_of(kref, struct bnx2fc_hba, kref);
+	BNX2FC_HBA_DBG(hba->ctlr.lp, "Interface is being released\n");
+
+	netdev = hba->netdev;
+	phys_dev = hba->phys_dev;
+
+	/* tear-down FIP controller */
+	if (test_and_clear_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done))
+		fcoe_ctlr_destroy(&hba->ctlr);
+
+	/* Free the command manager */
+	if (hba->cmd_mgr) {
+		bnx2fc_cmd_mgr_free(hba->cmd_mgr);
+		hba->cmd_mgr = NULL;
+	}
+	dev_put(netdev);
+	module_put(THIS_MODULE);
+}
+
+static inline void bnx2fc_interface_get(struct bnx2fc_hba *hba)
+{
+	kref_get(&hba->kref);
+}
+
+static inline void bnx2fc_interface_put(struct bnx2fc_hba *hba)
+{
+	kref_put(&hba->kref, bnx2fc_interface_release);
+}
+static void bnx2fc_interface_destroy(struct bnx2fc_hba *hba)
+{
+	bnx2fc_unbind_pcidev(hba);
+	kfree(hba);
+}
+
+/**
+ * bnx2fc_interface_create - create a new fcoe instance
+ *
+ * @cnic:	pointer to cnic device
+ *
+ * Creates a new FCoE instance on the given device which include allocating
+ *	hba structure, scsi_host and lport structures.
+ */
+static struct bnx2fc_hba *bnx2fc_interface_create(struct cnic_dev *cnic)
+{
+	struct bnx2fc_hba *hba;
+	int rc;
+
+	hba = kzalloc(sizeof(*hba), GFP_KERNEL);
+	if (!hba) {
+		printk(KERN_ERR PFX "Unable to allocate hba structure\n");
+		return NULL;
+	}
+	spin_lock_init(&hba->hba_lock);
+	mutex_init(&hba->hba_mutex);
+
+	hba->cnic = cnic;
+	rc = bnx2fc_bind_pcidev(hba);
+	if (rc)
+		goto bind_err;
+	hba->phys_dev = cnic->netdev;
+	/* will get overwritten after we do vlan discovery */
+	hba->netdev = hba->phys_dev;
+
+	init_waitqueue_head(&hba->shutdown_wait);
+	init_waitqueue_head(&hba->destroy_wait);
+
+	return hba;
+bind_err:
+	printk(KERN_ERR PFX "create_interface: bind error\n");
+	kfree(hba);
+	return NULL;
+}
+
+static int bnx2fc_interface_setup(struct bnx2fc_hba *hba,
+				  enum fip_state fip_mode)
+{
+	int rc = 0;
+	struct net_device *netdev = hba->netdev;
+	struct fcoe_ctlr *fip = &hba->ctlr;
+
+	dev_hold(netdev);
+	kref_init(&hba->kref);
+
+	hba->flags = 0;
+
+	/* Initialize FIP */
+	memset(fip, 0, sizeof(*fip));
+	fcoe_ctlr_init(fip, fip_mode);
+	hba->ctlr.send = bnx2fc_fip_send;
+	hba->ctlr.update_mac = bnx2fc_update_src_mac;
+	hba->ctlr.get_src_addr = bnx2fc_get_src_mac;
+	set_bit(BNX2FC_CTLR_INIT_DONE, &hba->init_done);
+
+	rc = bnx2fc_netdev_setup(hba);
+	if (rc)
+		goto setup_err;
+
+	hba->next_conn_id = 0;
+
+	memset(hba->tgt_ofld_list, 0, sizeof(hba->tgt_ofld_list));
+	hba->num_ofld_sess = 0;
+
+	return 0;
+
+setup_err:
+	fcoe_ctlr_destroy(&hba->ctlr);
+	dev_put(netdev);
+	bnx2fc_interface_put(hba);
+	return rc;
+}
+
+/**
+ * bnx2fc_if_create - Create FCoE instance on a given interface
+ *
+ * @hba:	FCoE interface to create a local port on
+ * @parent:	Device pointer to be the parent in sysfs for the SCSI host
+ * @npiv:	Indicates if the port is vport or not
+ *
+ * Creates a fc_lport instance and a Scsi_Host instance and configure them.
+ *
+ * Returns:	Allocated fc_lport or an error pointer
+ */
+static struct fc_lport *bnx2fc_if_create(struct bnx2fc_hba *hba,
+				  struct device *parent, int npiv)
+{
+	struct fc_lport		*lport = NULL;
+	struct fcoe_port	*port;
+	struct Scsi_Host	*shost;
+	struct fc_vport		*vport = dev_to_vport(parent);
+	int			rc = 0;
+
+	/* Allocate Scsi_Host structure */
+	if (!npiv) {
+		lport = libfc_host_alloc(&bnx2fc_shost_template,
+					  sizeof(struct fcoe_port));
+	} else {
+		lport = libfc_vport_create(vport,
+					   sizeof(struct fcoe_port));
+	}
+
+	if (!lport) {
+		printk(KERN_ERR PFX "could not allocate scsi host structure\n");
+		return NULL;
+	}
+	shost = lport->host;
+	port = lport_priv(lport);
+	port->lport = lport;
+	port->priv = hba;
+	INIT_WORK(&port->destroy_work, bnx2fc_destroy_work);
+
+	/* Configure fcoe_port */
+	rc = bnx2fc_lport_config(lport);
+	if (rc)
+		goto lp_config_err;
+
+	if (npiv) {
+		vport = dev_to_vport(parent);
+		printk(KERN_ERR PFX "Setting vport names, 0x%llX 0x%llX\n",
+			vport->node_name, vport->port_name);
+		fc_set_wwnn(lport, vport->node_name);
+		fc_set_wwpn(lport, vport->port_name);
+	}
+	/* Configure netdev and networking properties of the lport */
+	rc = bnx2fc_net_config(lport);
+	if (rc) {
+		printk(KERN_ERR PFX "Error on bnx2fc_net_config\n");
+		goto lp_config_err;
+	}
+
+	rc = bnx2fc_shost_config(lport, parent);
+	if (rc) {
+		printk(KERN_ERR PFX "Couldnt configure shost for %s\n",
+			hba->netdev->name);
+		goto lp_config_err;
+	}
+
+	/* Initialize the libfc library */
+	rc = bnx2fc_libfc_config(lport);
+	if (rc) {
+		printk(KERN_ERR PFX "Couldnt configure libfc\n");
+		goto shost_err;
+	}
+	fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+
+	/* Allocate exchange manager */
+	if (!npiv) {
+		rc = bnx2fc_em_config(lport);
+		if (rc) {
+			printk(KERN_ERR PFX "Error on bnx2fc_em_config\n");
+			goto shost_err;
+		}
+	}
+
+	bnx2fc_interface_get(hba);
+	return lport;
+
+shost_err:
+	scsi_remove_host(shost);
+lp_config_err:
+	scsi_host_put(lport->host);
+	return NULL;
+}
+
+static void bnx2fc_netdev_cleanup(struct bnx2fc_hba *hba)
+{
+	/* Dont listen for Ethernet packets anymore */
+	__dev_remove_pack(&hba->fcoe_packet_type);
+	__dev_remove_pack(&hba->fip_packet_type);
+	synchronize_net();
+}
+
+static void bnx2fc_if_destroy(struct fc_lport *lport)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+
+	BNX2FC_HBA_DBG(hba->ctlr.lp, "ENTERED bnx2fc_if_destroy\n");
+	/* Stop the transmit retry timer */
+	del_timer_sync(&port->timer);
+
+	/* Free existing transmit skbs */
+	fcoe_clean_pending_queue(lport);
+
+	bnx2fc_interface_put(hba);
+
+	/* Free queued packets for the receive thread */
+	bnx2fc_clean_rx_queue(lport);
+
+	/* Detach from scsi-ml */
+	fc_remove_host(lport->host);
+	scsi_remove_host(lport->host);
+
+	/*
+	 * Note that only the physical lport will have the exchange manager.
+	 * for vports, this function is NOP
+	 */
+	fc_exch_mgr_free(lport);
+
+	/* Free memory used by statistical counters */
+	fc_lport_free_stats(lport);
+
+	/* Release Scsi_Host */
+	scsi_host_put(lport->host);
+}
+
+/**
+ * bnx2fc_destroy - Destroy a bnx2fc FCoE interface
+ *
+ * @buffer: The name of the Ethernet interface to be destroyed
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_destroy(struct net_device *netdev)
+{
+	struct bnx2fc_hba *hba = NULL;
+	struct net_device *phys_dev;
+	int rc = 0;
+
+	rtnl_lock();
+
+	mutex_lock(&bnx2fc_dev_lock);
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN)
+		phys_dev = vlan_dev_real_dev(netdev);
+	else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -ENODEV;
+		goto netdev_err;
+	}
+
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba || !hba->ctlr.lp) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_destroy: hba or lport not found\n");
+		goto netdev_err;
+	}
+
+	if (!test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "bnx2fc_destroy: Create not called\n");
+		goto netdev_err;
+	}
+
+	bnx2fc_netdev_cleanup(hba);
+
+	bnx2fc_stop(hba);
+
+	bnx2fc_if_destroy(hba->ctlr.lp);
+
+	destroy_workqueue(hba->timer_work_queue);
+
+	if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
+		bnx2fc_fw_destroy(hba);
+
+	clear_bit(BNX2FC_CREATE_DONE, &hba->init_done);
+netdev_err:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+static void bnx2fc_destroy_work(struct work_struct *work)
+{
+	struct fcoe_port *port;
+	struct fc_lport *lport;
+
+	port = container_of(work, struct fcoe_port, destroy_work);
+	lport = port->lport;
+
+	BNX2FC_HBA_DBG(lport, "Entered bnx2fc_destroy_work\n");
+
+	bnx2fc_port_shutdown(lport);
+	rtnl_lock();
+	mutex_lock(&bnx2fc_dev_lock);
+	bnx2fc_if_destroy(lport);
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+}
+
+static void bnx2fc_unbind_adapter_devices(struct bnx2fc_hba *hba)
+{
+	bnx2fc_free_fw_resc(hba);
+	bnx2fc_free_task_ctx(hba);
+}
+
+/**
+ * bnx2fc_bind_adapter_devices - binds bnx2fc adapter with the associated
+ *			pci structure
+ *
+ * @hba:		Adapter instance
+ */
+static int bnx2fc_bind_adapter_devices(struct bnx2fc_hba *hba)
+{
+	if (bnx2fc_setup_task_ctx(hba))
+		goto mem_err;
+
+	if (bnx2fc_setup_fw_resc(hba))
+		goto mem_err;
+
+	return 0;
+mem_err:
+	bnx2fc_unbind_adapter_devices(hba);
+	return -ENOMEM;
+}
+
+static int bnx2fc_bind_pcidev(struct bnx2fc_hba *hba)
+{
+	struct cnic_dev *cnic;
+
+	if (!hba->cnic) {
+		printk(KERN_ERR PFX "cnic is NULL\n");
+		return -ENODEV;
+	}
+	cnic = hba->cnic;
+	hba->pcidev = cnic->pcidev;
+	if (hba->pcidev)
+		pci_dev_get(hba->pcidev);
+
+	return 0;
+}
+
+static void bnx2fc_unbind_pcidev(struct bnx2fc_hba *hba)
+{
+	if (hba->pcidev)
+		pci_dev_put(hba->pcidev);
+	hba->pcidev = NULL;
+}
+
+
+
+/**
+ * bnx2fc_ulp_start - cnic callback to initialize & start adapter instance
+ *
+ * @handle:	transport handle pointing to adapter struture
+ *
+ * This function maps adapter structure to pcidev structure and initiates
+ *	firmware handshake to enable/initialize on-chip FCoE components.
+ *	This bnx2fc - cnic interface api callback is used after following
+ *	conditions are met -
+ *	a) underlying network interface is up (marked by event NETDEV_UP
+ *		from netdev
+ *	b) bnx2fc adatper structure is registered.
+ */
+static void bnx2fc_ulp_start(void *handle)
+{
+	struct bnx2fc_hba *hba = handle;
+	struct fc_lport *lport = hba->ctlr.lp;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	mutex_lock(&bnx2fc_dev_lock);
+
+	if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done))
+		goto start_disc;
+
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done))
+		bnx2fc_fw_init(hba);
+
+start_disc:
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	BNX2FC_MISC_DBG("bnx2fc started.\n");
+
+	/* Kick off Fabric discovery*/
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "ulp_init: start discovery\n");
+		lport->tt.frame_send = bnx2fc_xmit;
+		bnx2fc_start_disc(hba);
+	}
+}
+
+static void bnx2fc_port_shutdown(struct fc_lport *lport)
+{
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	fc_fabric_logoff(lport);
+	fc_lport_destroy(lport);
+}
+
+static void bnx2fc_stop(struct bnx2fc_hba *hba)
+{
+	struct fc_lport *lport;
+	struct fc_lport *vport;
+
+	BNX2FC_MISC_DBG("ENTERED %s - init_done = %ld\n", __func__,
+		   hba->init_done);
+	if (test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done) &&
+	    test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		lport = hba->ctlr.lp;
+		bnx2fc_port_shutdown(lport);
+		BNX2FC_HBA_DBG(lport, "bnx2fc_stop: waiting for %d "
+				"offloaded sessions\n",
+				hba->num_ofld_sess);
+		wait_event_interruptible(hba->shutdown_wait,
+					 (hba->num_ofld_sess == 0));
+		mutex_lock(&lport->lp_mutex);
+		list_for_each_entry(vport, &lport->vports, list)
+			fc_host_port_type(vport->host) = FC_PORTTYPE_UNKNOWN;
+		mutex_unlock(&lport->lp_mutex);
+		fc_host_port_type(lport->host) = FC_PORTTYPE_UNKNOWN;
+		fcoe_ctlr_link_down(&hba->ctlr);
+		fcoe_clean_pending_queue(lport);
+
+		mutex_lock(&hba->hba_mutex);
+		clear_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+		clear_bit(ADAPTER_STATE_GOING_DOWN, &hba->adapter_state);
+
+		clear_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+		mutex_unlock(&hba->hba_mutex);
+	}
+}
+
+static int bnx2fc_fw_init(struct bnx2fc_hba *hba)
+{
+#define BNX2FC_INIT_POLL_TIME		(1000 / HZ)
+	int rc = -1;
+	int i = HZ;
+
+	rc = bnx2fc_bind_adapter_devices(hba);
+	if (rc) {
+		printk(KERN_ALERT PFX
+			"bnx2fc_bind_adapter_devices failed - rc = %d\n", rc);
+		goto err_out;
+	}
+
+	rc = bnx2fc_send_fw_fcoe_init_msg(hba);
+	if (rc) {
+		printk(KERN_ALERT PFX
+			"bnx2fc_send_fw_fcoe_init_msg failed - rc = %d\n", rc);
+		goto err_unbind;
+	}
+
+	/*
+	 * Wait until the adapter init message is complete, and adapter
+	 * state is UP.
+	 */
+	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
+		msleep(BNX2FC_INIT_POLL_TIME);
+
+	if (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state)) {
+		printk(KERN_ERR PFX "bnx2fc_start: %s failed to initialize.  "
+				"Ignoring...\n",
+				hba->cnic->netdev->name);
+		rc = -1;
+		goto err_unbind;
+	}
+
+
+	/* Mark HBA to indicate that the FW INIT is done */
+	set_bit(BNX2FC_FW_INIT_DONE, &hba->init_done);
+	return 0;
+
+err_unbind:
+	bnx2fc_unbind_adapter_devices(hba);
+err_out:
+	return rc;
+}
+
+static void bnx2fc_fw_destroy(struct bnx2fc_hba *hba)
+{
+	if (test_and_clear_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		if (bnx2fc_send_fw_fcoe_destroy_msg(hba) == 0) {
+			init_timer(&hba->destroy_timer);
+			hba->destroy_timer.expires = BNX2FC_FW_TIMEOUT +
+								jiffies;
+			hba->destroy_timer.function = bnx2fc_destroy_timer;
+			hba->destroy_timer.data = (unsigned long)hba;
+			add_timer(&hba->destroy_timer);
+			wait_event_interruptible(hba->destroy_wait,
+						 (hba->flags &
+						  BNX2FC_FLAG_DESTROY_CMPL));
+			/* This should never happen */
+			if (signal_pending(current))
+				flush_signals(current);
+
+			del_timer_sync(&hba->destroy_timer);
+		}
+		bnx2fc_unbind_adapter_devices(hba);
+	}
+}
+
+/**
+ * bnx2fc_ulp_stop - cnic callback to shutdown adapter instance
+ *
+ * @handle:	transport handle pointing to adapter structure
+ *
+ * Driver checks if adapter is already in shutdown mode, if not start
+ *	the shutdown process.
+ */
+static void bnx2fc_ulp_stop(void *handle)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)handle;
+
+	printk(KERN_ERR "ULP_STOP\n");
+
+	mutex_lock(&bnx2fc_dev_lock);
+	bnx2fc_stop(hba);
+	bnx2fc_fw_destroy(hba);
+	mutex_unlock(&bnx2fc_dev_lock);
+}
+
+static void bnx2fc_start_disc(struct bnx2fc_hba *hba)
+{
+	struct fc_lport *lport;
+	int wait_cnt = 0;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	/* Kick off FIP/FLOGI */
+	if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		printk(KERN_ERR PFX "Init not done yet\n");
+		return;
+	}
+
+	lport = hba->ctlr.lp;
+	BNX2FC_HBA_DBG(lport, "calling fc_fabric_login\n");
+
+	if (!bnx2fc_link_ok(lport)) {
+		BNX2FC_HBA_DBG(lport, "ctlr_link_up\n");
+		fcoe_ctlr_link_up(&hba->ctlr);
+		fc_host_port_type(lport->host) = FC_PORTTYPE_NPORT;
+		set_bit(ADAPTER_STATE_READY, &hba->adapter_state);
+	}
+
+	/* wait for the FCF to be selected before issuing FLOGI */
+	while (!hba->ctlr.sel_fcf) {
+		msleep(250);
+		/* give up after 3 secs */
+		if (++wait_cnt > 12)
+			break;
+	}
+	fc_lport_init(lport);
+	fc_fabric_login(lport);
+}
+
+
+/**
+ * bnx2fc_ulp_init - Initialize an adapter instance
+ *
+ * @dev :	cnic device handle
+ * Called from cnic_register_driver() context to initialize all
+ *	enumerated cnic devices. This routine allocates adapter structure
+ *	and other device specific resources.
+ */
+static void bnx2fc_ulp_init(struct cnic_dev *dev)
+{
+	struct bnx2fc_hba *hba;
+	int rc = 0;
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	/* bnx2fc works only when bnx2x is loaded */
+	if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+		printk(KERN_ERR PFX "bnx2fc FCoE not supported on %s,"
+				    " flags: %lx\n",
+			dev->netdev->name, dev->flags);
+		return;
+	}
+
+	/* Configure FCoE interface */
+	hba = bnx2fc_interface_create(dev);
+	if (!hba) {
+		printk(KERN_ERR PFX "hba initialization failed\n");
+		return;
+	}
+
+	/* Add HBA to the adapter list */
+	mutex_lock(&bnx2fc_dev_lock);
+	list_add_tail(&hba->link, &adapter_list);
+	adapter_count++;
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
+	rc = dev->register_device(dev, CNIC_ULP_FCOE,
+						(void *) hba);
+	if (rc)
+		printk(KERN_ALERT PFX "register_device failed, rc = %d\n", rc);
+	else
+		set_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic);
+}
+
+
+static int bnx2fc_disable(struct net_device *netdev)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *phys_dev;
+	struct ethtool_drvinfo drvinfo;
+	int rc = 0;
+
+	rtnl_lock();
+
+	mutex_lock(&bnx2fc_dev_lock);
+
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN)
+		phys_dev = vlan_dev_real_dev(netdev);
+	else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	/* verify if the physical device is a netxtreme2 device */
+	if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
+		if (strcmp(drvinfo.driver, "bnx2x")) {
+			printk(KERN_ERR PFX "Not a netxtreme2 device\n");
+			rc = -ENODEV;
+			goto nodev;
+		}
+	} else {
+		printk(KERN_ERR PFX "unable to obtain drv_info\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	printk(KERN_ERR PFX "phys_dev is netxtreme2 device\n");
+
+	/* obtain hba and initialize rest of the structure */
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba || !hba->ctlr.lp) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_disable: hba or lport not found\n");
+	} else {
+		fcoe_ctlr_link_down(&hba->ctlr);
+		fcoe_clean_pending_queue(hba->ctlr.lp);
+	}
+
+nodev:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+
+static int bnx2fc_enable(struct net_device *netdev)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *phys_dev;
+	struct ethtool_drvinfo drvinfo;
+	int rc = 0;
+
+	rtnl_lock();
+
+	BNX2FC_MISC_DBG("Entered %s\n", __func__);
+	mutex_lock(&bnx2fc_dev_lock);
+
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN)
+		phys_dev = vlan_dev_real_dev(netdev);
+	else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+	/* verify if the physical device is a netxtreme2 device */
+	if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
+		if (strcmp(drvinfo.driver, "bnx2x")) {
+			printk(KERN_ERR PFX "Not a netxtreme2 device\n");
+			rc = -ENODEV;
+			goto nodev;
+		}
+	} else {
+		printk(KERN_ERR PFX "unable to obtain drv_info\n");
+		rc = -ENODEV;
+		goto nodev;
+	}
+
+	/* obtain hba and initialize rest of the structure */
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba || !hba->ctlr.lp) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_enable: hba or lport not found\n");
+	} else if (!bnx2fc_link_ok(hba->ctlr.lp))
+		fcoe_ctlr_link_up(&hba->ctlr);
+
+nodev:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+/**
+ * bnx2fc_create - Create bnx2fc FCoE interface
+ *
+ * @buffer: The name of Ethernet interface to create on
+ * @kp:     The associated kernel param
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int bnx2fc_create(struct net_device *netdev, enum fip_state fip_mode)
+{
+	struct bnx2fc_hba *hba;
+	struct net_device *phys_dev;
+	struct fc_lport *lport;
+	struct ethtool_drvinfo drvinfo;
+	int rc = 0;
+	int vlan_id;
+
+	BNX2FC_MISC_DBG("Entered bnx2fc_create\n");
+	if (fip_mode != FIP_MODE_FABRIC) {
+		printk(KERN_ERR "fip mode not FABRIC\n");
+		return -EIO;
+	}
+
+	rtnl_lock();
+
+	mutex_lock(&bnx2fc_dev_lock);
+
+	if (!try_module_get(THIS_MODULE)) {
+		rc = -EINVAL;
+		goto mod_err;
+	}
+
+	/* obtain physical netdev */
+	if (netdev->priv_flags & IFF_802_1Q_VLAN) {
+		phys_dev = vlan_dev_real_dev(netdev);
+		vlan_id = vlan_dev_vlan_id(netdev);
+	} else {
+		printk(KERN_ERR PFX "Not a vlan device\n");
+		rc = -EINVAL;
+		goto netdev_err;
+	}
+	/* verify if the physical device is a netxtreme2 device */
+	if (phys_dev->ethtool_ops && phys_dev->ethtool_ops->get_drvinfo) {
+		memset(&drvinfo, 0, sizeof(drvinfo));
+		phys_dev->ethtool_ops->get_drvinfo(phys_dev, &drvinfo);
+		if (strcmp(drvinfo.driver, "bnx2x")) {
+			printk(KERN_ERR PFX "Not a netxtreme2 device\n");
+			rc = -EINVAL;
+			goto netdev_err;
+		}
+	} else {
+		printk(KERN_ERR PFX "unable to obtain drv_info\n");
+		rc = -EINVAL;
+		goto netdev_err;
+	}
+
+	/* obtain hba and initialize rest of the structure */
+	hba = bnx2fc_hba_lookup(phys_dev);
+	if (!hba) {
+		rc = -ENODEV;
+		printk(KERN_ERR PFX "bnx2fc_create: hba not found\n");
+		goto netdev_err;
+	}
+
+	if (!test_bit(BNX2FC_FW_INIT_DONE, &hba->init_done)) {
+		rc = bnx2fc_fw_init(hba);
+		if (rc)
+			goto netdev_err;
+	}
+
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		rc = -EEXIST;
+		goto netdev_err;
+	}
+
+	/* update netdev with vlan netdev */
+	hba->netdev = netdev;
+	hba->vlan_id = vlan_id;
+	hba->vlan_enabled = 1;
+
+	rc = bnx2fc_interface_setup(hba, fip_mode);
+	if (rc) {
+		printk(KERN_ERR PFX "bnx2fc_interface_setup failed\n");
+		goto ifput_err;
+	}
+
+	hba->timer_work_queue =
+			create_singlethread_workqueue("bnx2fc_timer_wq");
+	if (!hba->timer_work_queue) {
+		printk(KERN_ERR PFX "ulp_init could not create timer_wq\n");
+		rc = -EINVAL;
+		goto ifput_err;
+	}
+
+	lport = bnx2fc_if_create(hba, &hba->pcidev->dev, 0);
+	if (!lport) {
+		printk(KERN_ERR PFX "Failed to create interface (%s)\n",
+			netdev->name);
+		bnx2fc_netdev_cleanup(hba);
+		rc = -EINVAL;
+		goto if_create_err;
+	}
+
+	lport->boot_time = jiffies;
+
+	/* Make this master N_port */
+	hba->ctlr.lp = lport;
+
+	set_bit(BNX2FC_CREATE_DONE, &hba->init_done);
+	printk(KERN_ERR PFX "create: START DISC\n");
+	bnx2fc_start_disc(hba);
+	/*
+	 * Release from kref_init in bnx2fc_interface_setup, on success
+	 * lport should be holding a reference taken in bnx2fc_if_create
+	 */
+	bnx2fc_interface_put(hba);
+	/* put netdev that was held while calling dev_get_by_name */
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return 0;
+
+if_create_err:
+	destroy_workqueue(hba->timer_work_queue);
+ifput_err:
+	bnx2fc_interface_put(hba);
+netdev_err:
+	module_put(THIS_MODULE);
+mod_err:
+	mutex_unlock(&bnx2fc_dev_lock);
+	rtnl_unlock();
+	return rc;
+}
+
+/**
+ * bnx2fc_find_hba_for_cnic - maps cnic instance to bnx2fc adapter instance
+ *
+ * @cnic:	Pointer to cnic device instance
+ *
+ **/
+static struct bnx2fc_hba *bnx2fc_find_hba_for_cnic(struct cnic_dev *cnic)
+{
+	struct list_head *list;
+	struct list_head *temp;
+	struct bnx2fc_hba *hba;
+
+	/* Called with bnx2fc_dev_lock held */
+	list_for_each_safe(list, temp, &adapter_list) {
+		hba = (struct bnx2fc_hba *)list;
+		if (hba->cnic == cnic)
+			return hba;
+	}
+	return NULL;
+}
+
+static struct bnx2fc_hba *bnx2fc_hba_lookup(struct net_device *phys_dev)
+{
+	struct list_head *list;
+	struct list_head *temp;
+	struct bnx2fc_hba *hba;
+
+	/* Called with bnx2fc_dev_lock held */
+	list_for_each_safe(list, temp, &adapter_list) {
+		hba = (struct bnx2fc_hba *)list;
+		if (hba->phys_dev == phys_dev)
+			return hba;
+	}
+	printk(KERN_ERR PFX "hba_lookup: hba NULL\n");
+	return NULL;
+}
+
+/**
+ * bnx2fc_ulp_exit - shuts down adapter instance and frees all resources
+ *
+ * @dev		cnic device handle
+ */
+static void bnx2fc_ulp_exit(struct cnic_dev *dev)
+{
+	struct bnx2fc_hba *hba;
+
+	BNX2FC_MISC_DBG("Entered bnx2fc_ulp_exit\n");
+
+	if (!test_bit(CNIC_F_BNX2X_CLASS, &dev->flags)) {
+		printk(KERN_ERR PFX "bnx2fc port check: %s, flags: %lx\n",
+			dev->netdev->name, dev->flags);
+		return;
+	}
+
+	mutex_lock(&bnx2fc_dev_lock);
+	hba = bnx2fc_find_hba_for_cnic(dev);
+	if (!hba) {
+		printk(KERN_ERR PFX "bnx2fc_ulp_exit: hba not found, dev 0%p\n",
+		       dev);
+		mutex_unlock(&bnx2fc_dev_lock);
+		return;
+	}
+
+	list_del_init(&hba->link);
+	adapter_count--;
+
+	if (test_bit(BNX2FC_CREATE_DONE, &hba->init_done)) {
+		/* destroy not called yet, move to quiesced list */
+		bnx2fc_netdev_cleanup(hba);
+		bnx2fc_if_destroy(hba->ctlr.lp);
+	}
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	bnx2fc_ulp_stop(hba);
+	/* unregister cnic device */
+	if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED, &hba->reg_with_cnic))
+		hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
+	bnx2fc_interface_destroy(hba);
+}
+
+/**
+ * bnx2fc_fcoe_reset - Resets the fcoe
+ *
+ * @shost: shost the reset is from
+ *
+ * Returns: always 0
+ */
+static int bnx2fc_fcoe_reset(struct Scsi_Host *shost)
+{
+	struct fc_lport *lport = shost_priv(shost);
+	fc_lport_reset(lport);
+	return 0;
+}
+
+
+static bool bnx2fc_match(struct net_device *netdev)
+{
+	mutex_lock(&bnx2fc_dev_lock);
+	if (netdev->priv_flags & IFF_802_1Q_VLAN) {
+		struct net_device *phys_dev = vlan_dev_real_dev(netdev);
+
+		if (bnx2fc_hba_lookup(phys_dev)) {
+			mutex_unlock(&bnx2fc_dev_lock);
+			return true;
+		}
+	}
+	mutex_unlock(&bnx2fc_dev_lock);
+	return false;
+}
+
+
+static struct fcoe_transport bnx2fc_transport = {
+	.name = {"bnx2fc"},
+	.attached = false,
+	.list = LIST_HEAD_INIT(bnx2fc_transport.list),
+	.match = bnx2fc_match,
+	.create = bnx2fc_create,
+	.destroy = bnx2fc_destroy,
+	.enable = bnx2fc_enable,
+	.disable = bnx2fc_disable,
+};
+
+/**
+ * bnx2fc_percpu_thread_create - Create a receive thread for an
+ *				 online CPU
+ *
+ * @cpu: cpu index for the online cpu
+ */
+static void bnx2fc_percpu_thread_create(unsigned int cpu)
+{
+	struct bnx2fc_percpu_s *p;
+	struct task_struct *thread;
+
+	p = &per_cpu(bnx2fc_percpu, cpu);
+
+	thread = kthread_create(bnx2fc_percpu_io_thread,
+				(void *)p,
+				"bnx2fc_thread/%d", cpu);
+	/* bind thread to the cpu */
+	if (likely(!IS_ERR(p->iothread))) {
+		kthread_bind(thread, cpu);
+		p->iothread = thread;
+		wake_up_process(thread);
+	}
+}
+
+static void bnx2fc_percpu_thread_destroy(unsigned int cpu)
+{
+	struct bnx2fc_percpu_s *p;
+	struct task_struct *thread;
+	struct bnx2fc_work *work, *tmp;
+	LIST_HEAD(work_list);
+
+	BNX2FC_MISC_DBG("destroying io thread for CPU %d\n", cpu);
+
+	/* Prevent any new work from being queued for this CPU */
+	p = &per_cpu(bnx2fc_percpu, cpu);
+	spin_lock_bh(&p->fp_work_lock);
+	thread = p->iothread;
+	p->iothread = NULL;
+
+
+	/* Free all work in the list */
+	list_for_each_entry_safe(work, tmp, &work_list, list) {
+		list_del_init(&work->list);
+		bnx2fc_process_cq_compl(work->tgt, work->wqe);
+		kfree(work);
+	}
+
+	spin_unlock_bh(&p->fp_work_lock);
+
+	if (thread)
+		kthread_stop(thread);
+}
+
+/**
+ * bnx2fc_cpu_callback - Handler for CPU hotplug events
+ *
+ * @nfb:    The callback data block
+ * @action: The event triggering the callback
+ * @hcpu:   The index of the CPU that the event is for
+ *
+ * This creates or destroys per-CPU data for fcoe
+ *
+ * Returns NOTIFY_OK always.
+ */
+static int bnx2fc_cpu_callback(struct notifier_block *nfb,
+			     unsigned long action, void *hcpu)
+{
+	unsigned cpu = (unsigned long)hcpu;
+
+	switch (action) {
+	case CPU_ONLINE:
+	case CPU_ONLINE_FROZEN:
+		printk(PFX "CPU %x online: Create Rx thread\n", cpu);
+		bnx2fc_percpu_thread_create(cpu);
+		break;
+	case CPU_DEAD:
+	case CPU_DEAD_FROZEN:
+		printk(PFX "CPU %x offline: Remove Rx thread\n", cpu);
+		bnx2fc_percpu_thread_destroy(cpu);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+/**
+ * bnx2fc_mod_init - module init entry point
+ *
+ * Initialize driver wide global data structures, and register
+ * with cnic module
+ **/
+static int __init bnx2fc_mod_init(void)
+{
+	struct fcoe_percpu_s *bg;
+	struct task_struct *l2_thread;
+	int rc = 0;
+	unsigned int cpu = 0;
+	struct bnx2fc_percpu_s *p;
+
+	printk(KERN_INFO PFX "%s", version);
+
+	/* register as a fcoe transport */
+	rc = fcoe_transport_attach(&bnx2fc_transport);
+	if (rc) {
+		printk(KERN_ERR "failed to register an fcoe transport, check "
+			"if libfcoe is loaded\n");
+		goto out;
+	}
+
+	INIT_LIST_HEAD(&adapter_list);
+	mutex_init(&bnx2fc_dev_lock);
+	adapter_count = 0;
+
+	/* Attach FC transport template */
+	rc = bnx2fc_attach_transport();
+	if (rc)
+		goto detach_ft;
+
+	bnx2fc_wq = alloc_workqueue("bnx2fc", 0, 0);
+	if (!bnx2fc_wq) {
+		rc = -ENOMEM;
+		goto release_bt;
+	}
+
+	bg = &bnx2fc_global;
+	skb_queue_head_init(&bg->fcoe_rx_list);
+	l2_thread = kthread_create(bnx2fc_l2_rcv_thread,
+				   (void *)bg,
+				   "bnx2fc_l2_thread");
+	if (IS_ERR(l2_thread)) {
+		rc = PTR_ERR(l2_thread);
+		goto free_wq;
+	}
+	wake_up_process(l2_thread);
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+	bg->thread = l2_thread;
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+
+	for_each_possible_cpu(cpu) {
+		p = &per_cpu(bnx2fc_percpu, cpu);
+		INIT_LIST_HEAD(&p->work_list);
+		spin_lock_init(&p->fp_work_lock);
+	}
+
+	for_each_online_cpu(cpu) {
+		bnx2fc_percpu_thread_create(cpu);
+	}
+
+	/* Initialize per CPU interrupt thread */
+	register_hotcpu_notifier(&bnx2fc_cpu_notifier);
+
+	cnic_register_driver(CNIC_ULP_FCOE, &bnx2fc_cnic_cb);
+
+	return 0;
+
+free_wq:
+	destroy_workqueue(bnx2fc_wq);
+release_bt:
+	bnx2fc_release_transport();
+detach_ft:
+	fcoe_transport_detach(&bnx2fc_transport);
+out:
+	return rc;
+}
+
+static void __exit bnx2fc_mod_exit(void)
+{
+	LIST_HEAD(to_be_deleted);
+	struct bnx2fc_hba *hba, *next;
+	struct fcoe_percpu_s *bg;
+	struct task_struct *l2_thread;
+	struct sk_buff *skb;
+	unsigned int cpu = 0;
+
+	/*
+	 * NOTE: Since cnic calls register_driver routine rtnl_lock,
+	 * it will have higher precedence than bnx2fc_dev_lock.
+	 * unregister_device() cannot be called with bnx2fc_dev_lock
+	 * held.
+	 */
+	mutex_lock(&bnx2fc_dev_lock);
+	list_splice(&adapter_list, &to_be_deleted);
+	INIT_LIST_HEAD(&adapter_list);
+	adapter_count = 0;
+	mutex_unlock(&bnx2fc_dev_lock);
+
+	/* Unregister with cnic */
+	list_for_each_entry_safe(hba, next, &to_be_deleted, link) {
+		list_del_init(&hba->link);
+		printk(KERN_ERR PFX "MOD_EXIT:destroy hba = 0x%p, kref = %d\n",
+			hba, atomic_read(&hba->kref.refcount));
+		bnx2fc_ulp_stop(hba);
+		/* unregister cnic device */
+		if (test_and_clear_bit(BNX2FC_CNIC_REGISTERED,
+				       &hba->reg_with_cnic))
+			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_FCOE);
+		bnx2fc_interface_destroy(hba);
+	}
+	cnic_unregister_driver(CNIC_ULP_FCOE);
+
+	/* Destroy global thread */
+	bg = &bnx2fc_global;
+	spin_lock_bh(&bg->fcoe_rx_list.lock);
+	l2_thread = bg->thread;
+	bg->thread = NULL;
+	while ((skb = __skb_dequeue(&bg->fcoe_rx_list)) != NULL)
+		kfree_skb(skb);
+
+	spin_unlock_bh(&bg->fcoe_rx_list.lock);
+
+	if (l2_thread)
+		kthread_stop(l2_thread);
+
+	unregister_hotcpu_notifier(&bnx2fc_cpu_notifier);
+
+	/* Destroy per cpu threads */
+	for_each_online_cpu(cpu) {
+		bnx2fc_percpu_thread_destroy(cpu);
+	}
+
+	destroy_workqueue(bnx2fc_wq);
+	/*
+	 * detach from scsi transport
+	 * must happen after all destroys are done
+	 */
+	bnx2fc_release_transport();
+
+	/* detach from fcoe transport */
+	fcoe_transport_detach(&bnx2fc_transport);
+}
+
+module_init(bnx2fc_mod_init);
+module_exit(bnx2fc_mod_exit);
+
+static struct fc_function_template bnx2fc_transport_function = {
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_active_fc4s = 1,
+	.show_host_maxframe_size = 1,
+
+	.show_host_port_id = 1,
+	.show_host_supported_speeds = 1,
+	.get_host_speed = fc_get_host_speed,
+	.show_host_speed = 1,
+	.show_host_port_type = 1,
+	.get_host_port_state = fc_get_host_port_state,
+	.show_host_port_state = 1,
+	.show_host_symbolic_name = 1,
+
+	.dd_fcrport_size = (sizeof(struct fc_rport_libfc_priv) +
+				sizeof(struct bnx2fc_rport)),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.show_host_fabric_name = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+	.show_starget_port_id = 1,
+	.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+	.get_fc_host_stats = bnx2fc_get_host_stats,
+
+	.issue_fc_host_lip = bnx2fc_fcoe_reset,
+
+	.terminate_rport_io = fc_rport_terminate_io,
+
+	.vport_create = bnx2fc_vport_create,
+	.vport_delete = bnx2fc_vport_destroy,
+	.vport_disable = bnx2fc_vport_disable,
+};
+
+static struct fc_function_template bnx2fc_vport_xport_function = {
+	.show_host_node_name = 1,
+	.show_host_port_name = 1,
+	.show_host_supported_classes = 1,
+	.show_host_supported_fc4s = 1,
+	.show_host_active_fc4s = 1,
+	.show_host_maxframe_size = 1,
+
+	.show_host_port_id = 1,
+	.show_host_supported_speeds = 1,
+	.get_host_speed = fc_get_host_speed,
+	.show_host_speed = 1,
+	.show_host_port_type = 1,
+	.get_host_port_state = fc_get_host_port_state,
+	.show_host_port_state = 1,
+	.show_host_symbolic_name = 1,
+
+	.dd_fcrport_size = (sizeof(struct fc_rport_libfc_priv) +
+				sizeof(struct bnx2fc_rport)),
+	.show_rport_maxframe_size = 1,
+	.show_rport_supported_classes = 1,
+
+	.show_host_fabric_name = 1,
+	.show_starget_node_name = 1,
+	.show_starget_port_name = 1,
+	.show_starget_port_id = 1,
+	.set_rport_dev_loss_tmo = fc_set_rport_loss_tmo,
+	.show_rport_dev_loss_tmo = 1,
+	.get_fc_host_stats = fc_get_host_stats,
+	.issue_fc_host_lip = bnx2fc_fcoe_reset,
+	.terminate_rport_io = fc_rport_terminate_io,
+};
+
+/**
+ * scsi_host_template structure used while registering with SCSI-ml
+ */
+static struct scsi_host_template bnx2fc_shost_template = {
+	.module			= THIS_MODULE,
+	.name			= "Broadcom Offload FCoE Initiator",
+	.queuecommand		= bnx2fc_queuecommand,
+	.eh_abort_handler	= bnx2fc_eh_abort,	  /* abts */
+	.eh_device_reset_handler = bnx2fc_eh_device_reset, /* lun reset */
+	.eh_target_reset_handler = bnx2fc_eh_target_reset, /* tgt reset */
+	.eh_host_reset_handler	= fc_eh_host_reset,
+	.slave_alloc		= fc_slave_alloc,
+	.change_queue_depth	= fc_change_queue_depth,
+	.change_queue_type	= fc_change_queue_type,
+	.this_id		= -1,
+	.cmd_per_lun		= 3,
+	.can_queue		= BNX2FC_CAN_QUEUE,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.sg_tablesize		= BNX2FC_MAX_BDS_PER_CMD,
+	.max_sectors		= 512,
+};
+
+static struct libfc_function_template bnx2fc_libfc_fcn_templ = {
+	.frame_send		= bnx2fc_xmit,
+	.elsct_send		= bnx2fc_elsct_send,
+	.fcp_abort_io		= bnx2fc_abort_io,
+	.fcp_cleanup		= bnx2fc_cleanup,
+	.rport_event_callback	= bnx2fc_rport_event_handler,
+};
+
+/**
+ * bnx2fc_cnic_cb - global template of bnx2fc - cnic driver interface
+ *			structure carrying callback function pointers
+ */
+static struct cnic_ulp_ops bnx2fc_cnic_cb = {
+	.owner			= THIS_MODULE,
+	.cnic_init		= bnx2fc_ulp_init,
+	.cnic_exit		= bnx2fc_ulp_exit,
+	.cnic_start		= bnx2fc_ulp_start,
+	.cnic_stop		= bnx2fc_ulp_stop,
+	.indicate_kcqes		= bnx2fc_indicate_kcqe,
+	.indicate_netevent	= bnx2fc_indicate_netevent,
+};
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc.h linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,517 @@
+#ifndef _BNX2FC_H_
+#define _BNX2FC_H_
+/* bnx2fc.h: Broadcom NetXtreme II Linux FCoE offload driver.
+ *
+ * Copyright (c) 2008 - 2010 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.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include <linux/module.h>
+#include <linux/moduleparam.h>
+#include <linux/kernel.h>
+#include <linux/skbuff.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/kthread.h>
+#include <linux/crc32.h>
+#include <linux/cpu.h>
+#include <linux/types.h>
+#include <linux/list.h>
+#include <linux/delay.h>
+#include <linux/timer.h>
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/init.h>
+#include <linux/dma-mapping.h>
+#include <linux/workqueue.h>
+#include <linux/mutex.h>
+#include <linux/spinlock.h>
+#include <linux/bitops.h>
+#include <linux/log2.h>
+#include <linux/interrupt.h>
+#include <linux/sched.h>
+#include <linux/io.h>
+
+#include <scsi/scsi.h>
+#include <scsi/scsi_host.h>
+#include <scsi/scsi_device.h>
+#include <scsi/scsi_cmnd.h>
+#include <scsi/scsi_eh.h>
+#include <scsi/scsi_tcq.h>
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+#include <scsi/fc_encode.h>
+#include <scsi/scsi_transport.h>
+#include <scsi/scsi_transport_fc.h>
+#include <scsi/fc/fc_fip.h>
+#include <scsi/fc/fc_fc2.h>
+#include <scsi/fc_frame.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/fc/fc_fcp.h>
+
+#include "57xx_hsi_bnx2fc.h"
+#include "bnx2fc_debug.h"
+#include "../../net/cnic_if.h"
+#include "bnx2fc_constants.h"
+
+#define BNX2FC_NAME		"bnx2fc"
+#define BNX2FC_VERSION		"1.0.1"
+
+#define PFX			"bnx2fc: "
+
+#define BNX2X_DOORBELL_PCI_BAR		2
+
+#define BNX2FC_MAX_BD_LEN		0xffff
+#define BNX2FC_BD_SPLIT_SZ		0x8000
+#define BNX2FC_MAX_BDS_PER_CMD		256
+
+#define BNX2FC_SQ_WQES_MAX	256
+
+#define BNX2FC_SCSI_MAX_SQES	((3 * BNX2FC_SQ_WQES_MAX) / 8)
+#define BNX2FC_TM_MAX_SQES	((BNX2FC_SQ_WQES_MAX) / 2)
+#define BNX2FC_ELS_MAX_SQES	(BNX2FC_TM_MAX_SQES - 1)
+
+#define BNX2FC_RQ_WQES_MAX	16
+#define BNX2FC_CQ_WQES_MAX	(BNX2FC_SQ_WQES_MAX + BNX2FC_RQ_WQES_MAX)
+
+#define BNX2FC_NUM_MAX_SESS	128
+#define BNX2FC_NUM_MAX_SESS_LOG	(ilog2(BNX2FC_NUM_MAX_SESS))
+
+#define BNX2FC_MAX_OUTSTANDING_CMNDS	2048
+#define BNX2FC_CAN_QUEUE		BNX2FC_MAX_OUTSTANDING_CMNDS
+#define BNX2FC_ELSTM_XIDS		BNX2FC_CAN_QUEUE
+#define BNX2FC_MIN_PAYLOAD		256
+#define BNX2FC_MAX_PAYLOAD		2048
+#define BNX2FC_MFS			\
+			(BNX2FC_MAX_PAYLOAD + sizeof(struct fc_frame_header))
+#define BNX2FC_MINI_JUMBO_MTU		2500
+
+
+#define BNX2FC_RQ_BUF_SZ		256
+#define BNX2FC_RQ_BUF_LOG_SZ		(ilog2(BNX2FC_RQ_BUF_SZ))
+
+#define BNX2FC_SQ_WQE_SIZE		(sizeof(struct fcoe_sqe))
+#define BNX2FC_CQ_WQE_SIZE		(sizeof(struct fcoe_cqe))
+#define BNX2FC_RQ_WQE_SIZE		(BNX2FC_RQ_BUF_SZ)
+#define BNX2FC_XFERQ_WQE_SIZE		(sizeof(struct fcoe_xfrqe))
+#define BNX2FC_CONFQ_WQE_SIZE		(sizeof(struct fcoe_confqe))
+#define BNX2FC_5771X_DB_PAGE_SIZE	128
+
+#define BNX2FC_MAX_TASKS		\
+			     (BNX2FC_MAX_OUTSTANDING_CMNDS + BNX2FC_ELSTM_XIDS)
+#define BNX2FC_TASK_SIZE		128
+#define	BNX2FC_TASKS_PER_PAGE		(PAGE_SIZE/BNX2FC_TASK_SIZE)
+#define BNX2FC_TASK_CTX_ARR_SZ		(BNX2FC_MAX_TASKS/BNX2FC_TASKS_PER_PAGE)
+
+#define BNX2FC_MAX_ROWS_IN_HASH_TBL	8
+#define BNX2FC_HASH_TBL_CHUNK_SIZE	(16 * 1024)
+
+#define BNX2FC_MAX_SEQS			255
+
+#define BNX2FC_READ			(1 << 1)
+#define BNX2FC_WRITE			(1 << 0)
+
+#define BNX2FC_MIN_XID			0
+#define BNX2FC_MAX_XID			\
+			(BNX2FC_MAX_OUTSTANDING_CMNDS + BNX2FC_ELSTM_XIDS - 1)
+#define FCOE_MIN_XID			(BNX2FC_MAX_XID + 1)
+#define FCOE_MAX_XID			(FCOE_MIN_XID + 4095)
+#define BNX2FC_MAX_LUN			0xFFFF
+#define BNX2FC_MAX_FCP_TGT		256
+#define BNX2FC_MAX_CMD_LEN		16
+
+#define BNX2FC_TM_TIMEOUT		60	/* secs */
+#define BNX2FC_IO_TIMEOUT		20000UL	/* msecs */
+
+#define BNX2FC_WAIT_CNT			120
+#define BNX2FC_FW_TIMEOUT		(3 * HZ)
+#define PORT_MAX			2
+
+#define CMD_SCSI_STATUS(Cmnd)		((Cmnd)->SCp.Status)
+
+/* FC FCP Status */
+#define	FC_GOOD				0
+
+#define BNX2FC_RNID_HBA			0x7
+
+/* bnx2fc driver uses only one instance of fcoe_percpu_s */
+extern struct fcoe_percpu_s bnx2fc_global;
+
+extern struct workqueue_struct *bnx2fc_wq;
+
+struct bnx2fc_percpu_s {
+	struct task_struct *iothread;
+	struct list_head work_list;
+	spinlock_t fp_work_lock;
+};
+
+
+struct bnx2fc_hba {
+	struct list_head link;
+	struct cnic_dev *cnic;
+	struct pci_dev *pcidev;
+	struct net_device *netdev;
+	struct net_device *phys_dev;
+	unsigned long reg_with_cnic;
+		#define BNX2FC_CNIC_REGISTERED           1
+	struct packet_type fcoe_packet_type;
+	struct packet_type fip_packet_type;
+	struct bnx2fc_cmd_mgr *cmd_mgr;
+	struct workqueue_struct *timer_work_queue;
+	struct kref kref;
+	spinlock_t hba_lock;
+	struct mutex hba_mutex;
+	unsigned long adapter_state;
+		#define ADAPTER_STATE_UP		0
+		#define ADAPTER_STATE_GOING_DOWN	1
+		#define ADAPTER_STATE_LINK_DOWN		2
+		#define ADAPTER_STATE_READY		3
+	u32 flags;
+	unsigned long init_done;
+		#define BNX2FC_FW_INIT_DONE		0
+		#define BNX2FC_CTLR_INIT_DONE		1
+		#define BNX2FC_CREATE_DONE		2
+	struct fcoe_ctlr ctlr;
+	u8 vlan_enabled;
+	int vlan_id;
+	u32 next_conn_id;
+	struct fcoe_task_ctx_entry **task_ctx;
+	dma_addr_t *task_ctx_dma;
+	struct regpair *task_ctx_bd_tbl;
+	dma_addr_t task_ctx_bd_dma;
+
+	int hash_tbl_segment_count;
+	void **hash_tbl_segments;
+	void *hash_tbl_pbl;
+	dma_addr_t hash_tbl_pbl_dma;
+	struct fcoe_t2_hash_table_entry *t2_hash_tbl;
+	dma_addr_t t2_hash_tbl_dma;
+	char *t2_hash_tbl_ptr;
+	dma_addr_t t2_hash_tbl_ptr_dma;
+
+	char *dummy_buffer;
+	dma_addr_t dummy_buf_dma;
+
+	struct fcoe_statistics_params *stats_buffer;
+	dma_addr_t stats_buf_dma;
+
+	/*
+	 * PCI related info.
+	 */
+	u16 pci_did;
+	u16 pci_vid;
+	u16 pci_sdid;
+	u16 pci_svid;
+	u16 pci_func;
+	u16 pci_devno;
+
+	struct task_struct *l2_thread;
+
+	/* linkdown handling */
+	wait_queue_head_t shutdown_wait;
+	int wait_for_link_down;
+
+	/*destroy handling */
+	struct timer_list destroy_timer;
+	wait_queue_head_t destroy_wait;
+
+	/* Active list of offloaded sessions */
+	struct bnx2fc_rport *tgt_ofld_list[BNX2FC_NUM_MAX_SESS];
+	int num_ofld_sess;
+
+	/* statistics */
+	struct completion stat_req_done;
+};
+
+#define bnx2fc_from_ctlr(fip) container_of(fip, struct bnx2fc_hba, ctlr)
+
+struct bnx2fc_cmd_mgr {
+	struct bnx2fc_hba *hba;
+	u16 next_idx;
+	struct list_head *free_list;
+	spinlock_t *free_list_lock;
+	struct io_bdt **io_bdt_pool;
+	struct bnx2fc_cmd **cmds;
+};
+
+struct bnx2fc_rport {
+	struct fcoe_port *port;
+	struct fc_rport *rport;
+	struct fc_rport_priv *rdata;
+	void __iomem *ctx_base;
+#define DPM_TRIGER_TYPE		0x40
+	u32 fcoe_conn_id;
+	u32 context_id;
+	u32 sid;
+
+	unsigned long flags;
+#define BNX2FC_FLAG_SESSION_READY	0x1
+#define BNX2FC_FLAG_OFFLOADED		0x2
+#define BNX2FC_FLAG_DISABLED		0x3
+#define BNX2FC_FLAG_DESTROYED		0x4
+#define BNX2FC_FLAG_OFLD_REQ_CMPL	0x5
+#define BNX2FC_FLAG_DESTROY_CMPL	0x6
+#define BNX2FC_FLAG_CTX_ALLOC_FAILURE	0x7
+#define BNX2FC_FLAG_UPLD_REQ_COMPL	0x8
+#define BNX2FC_FLAG_EXPL_LOGO		0x9
+
+	u32 max_sqes;
+	u32 max_rqes;
+	u32 max_cqes;
+
+	struct fcoe_sqe *sq;
+	dma_addr_t sq_dma;
+	u16 sq_prod_idx;
+	u8 sq_curr_toggle_bit;
+	u32 sq_mem_size;
+
+	struct fcoe_cqe *cq;
+	dma_addr_t cq_dma;
+	u32 cq_cons_idx;
+	u8 cq_curr_toggle_bit;
+	u32 cq_mem_size;
+
+	void *rq;
+	dma_addr_t rq_dma;
+	u32 rq_prod_idx;
+	u32 rq_cons_idx;
+	u32 rq_mem_size;
+
+	void *rq_pbl;
+	dma_addr_t rq_pbl_dma;
+	u32 rq_pbl_size;
+
+	struct fcoe_xfrqe *xferq;
+	dma_addr_t xferq_dma;
+	u32 xferq_mem_size;
+
+	struct fcoe_confqe *confq;
+	dma_addr_t confq_dma;
+	u32 confq_mem_size;
+
+	void *confq_pbl;
+	dma_addr_t confq_pbl_dma;
+	u32 confq_pbl_size;
+
+	struct fcoe_conn_db *conn_db;
+	dma_addr_t conn_db_dma;
+	u32 conn_db_mem_size;
+
+	struct fcoe_sqe *lcq;
+	dma_addr_t lcq_dma;
+	u32 lcq_mem_size;
+
+	void *ofld_req[4];
+	dma_addr_t ofld_req_dma[4];
+	void *enbl_req;
+	dma_addr_t enbl_req_dma;
+
+	spinlock_t tgt_lock;
+	spinlock_t cq_lock;
+	atomic_t num_active_ios;
+	u32 flush_in_prog;
+	unsigned long work_time_slice;
+	unsigned long timestamp;
+	struct list_head free_task_list;
+	struct bnx2fc_cmd *pending_queue[BNX2FC_SQ_WQES_MAX+1];
+	atomic_t pi;
+	atomic_t ci;
+	struct list_head active_cmd_queue;
+	struct list_head els_queue;
+	struct list_head io_retire_queue;
+	struct list_head active_tm_queue;
+
+	struct timer_list ofld_timer;
+	wait_queue_head_t ofld_wait;
+
+	struct timer_list upld_timer;
+	wait_queue_head_t upld_wait;
+};
+
+struct bnx2fc_mp_req {
+	u8 tm_flags;
+
+	u32 req_len;
+	void *req_buf;
+	dma_addr_t req_buf_dma;
+	struct fcoe_bd_ctx *mp_req_bd;
+	dma_addr_t mp_req_bd_dma;
+	struct fc_frame_header req_fc_hdr;
+
+	u32 resp_len;
+	void *resp_buf;
+	dma_addr_t resp_buf_dma;
+	struct fcoe_bd_ctx *mp_resp_bd;
+	dma_addr_t mp_resp_bd_dma;
+	struct fc_frame_header resp_fc_hdr;
+};
+
+struct bnx2fc_els_cb_arg {
+	struct bnx2fc_cmd *aborted_io_req;
+	struct bnx2fc_cmd *io_req;
+	u16 l2_oxid;
+};
+
+/* bnx2fc command structure */
+struct bnx2fc_cmd {
+	struct list_head link;
+	u8 on_active_queue;
+	u8 on_tmf_queue;
+	u8 cmd_type;
+#define BNX2FC_SCSI_CMD		1
+#define BNX2FC_TASK_MGMT_CMD		2
+#define BNX2FC_ABTS			3
+#define BNX2FC_ELS			4
+#define BNX2FC_CLEANUP			5
+	u8 io_req_flags;
+	struct kref refcount;
+	struct fcoe_port *port;
+	struct bnx2fc_rport *tgt;
+	struct scsi_cmnd *sc_cmd;
+	struct bnx2fc_cmd_mgr *cmd_mgr;
+	struct bnx2fc_mp_req mp_req;
+	void (*cb_func)(struct bnx2fc_els_cb_arg *cb_arg);
+	struct bnx2fc_els_cb_arg *cb_arg;
+	struct delayed_work timeout_work; /* timer for ULP timeouts */
+	struct completion tm_done;
+	int wait_for_comp;
+	u16 xid;
+	struct fcoe_task_ctx_entry *task;
+	struct io_bdt *bd_tbl;
+	struct fcp_rsp *rsp;
+	size_t data_xfer_len;
+	unsigned long req_flags;
+#define BNX2FC_FLAG_ISSUE_RRQ		0x1
+#define BNX2FC_FLAG_ISSUE_ABTS		0x2
+#define BNX2FC_FLAG_ABTS_DONE		0x3
+#define BNX2FC_FLAG_TM_COMPL		0x4
+#define BNX2FC_FLAG_TM_TIMEOUT		0x5
+#define BNX2FC_FLAG_IO_CLEANUP		0x6
+#define BNX2FC_FLAG_RETIRE_OXID		0x7
+#define	BNX2FC_FLAG_EH_ABORT		0x8
+#define BNX2FC_FLAG_IO_COMPL		0x9
+#define BNX2FC_FLAG_ELS_DONE		0xa
+#define BNX2FC_FLAG_ELS_TIMEOUT		0xb
+	u32 fcp_resid;
+	u32 fcp_rsp_len;
+	u32 fcp_sns_len;
+	u8 cdb_status; /* SCSI IO status */
+	u8 fcp_status; /* FCP IO status */
+	u8 fcp_rsp_code;
+	u8 scsi_comp_flags;
+};
+
+struct io_bdt {
+	struct bnx2fc_cmd *io_req;
+	struct fcoe_bd_ctx *bd_tbl;
+	dma_addr_t bd_tbl_dma;
+	u16 bd_valid;
+};
+
+struct bnx2fc_work {
+	struct list_head list;
+	struct bnx2fc_rport *tgt;
+	u16 wqe;
+};
+struct bnx2fc_unsol_els {
+	struct fc_lport *lport;
+	struct fc_frame *fp;
+	struct work_struct unsol_els_work;
+};
+
+
+
+struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type);
+void bnx2fc_cmd_release(struct kref *ref);
+int bnx2fc_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *sc_cmd);
+int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba);
+int bnx2fc_send_fw_fcoe_destroy_msg(struct bnx2fc_hba *hba);
+int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt);
+int bnx2fc_send_session_disable_req(struct fcoe_port *port,
+				    struct bnx2fc_rport *tgt);
+int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
+					struct bnx2fc_rport *tgt);
+int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt);
+void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
+					u32 num_cqe);
+int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba);
+void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba);
+int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba);
+void bnx2fc_free_fw_resc(struct bnx2fc_hba *hba);
+struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
+						u16 min_xid, u16 max_xid);
+void bnx2fc_cmd_mgr_free(struct bnx2fc_cmd_mgr *cmgr);
+void bnx2fc_get_link_state(struct bnx2fc_hba *hba);
+char *bnx2fc_get_next_rqe(struct bnx2fc_rport *tgt, u8 num_items);
+void bnx2fc_return_rqe(struct bnx2fc_rport *tgt, u8 num_items);
+int bnx2fc_get_paged_crc_eof(struct sk_buff *skb, int tlen);
+int bnx2fc_send_rrq(struct bnx2fc_cmd *aborted_io_req);
+int bnx2fc_send_adisc(struct bnx2fc_rport *tgt, struct fc_frame *fp);
+int bnx2fc_send_logo(struct bnx2fc_rport *tgt, struct fc_frame *fp);
+int bnx2fc_send_rls(struct bnx2fc_rport *tgt, struct fc_frame *fp);
+int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req);
+int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req);
+void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
+			  unsigned int timer_msec);
+int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req);
+void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
+			      struct fcoe_task_ctx_entry *task,
+			      u16 orig_xid);
+void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
+			 struct fcoe_task_ctx_entry *task);
+void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task);
+void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid);
+void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt);
+int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd);
+int bnx2fc_eh_host_reset(struct scsi_cmnd *sc_cmd);
+int bnx2fc_eh_target_reset(struct scsi_cmnd *sc_cmd);
+int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd);
+void bnx2fc_rport_event_handler(struct fc_lport *lport,
+				struct fc_rport_priv *rport,
+				enum fc_rport_event event);
+void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
+				   struct fcoe_task_ctx_entry *task,
+				   u8 num_rq);
+void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
+			       struct fcoe_task_ctx_entry *task,
+			       u8 num_rq);
+void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
+			       struct fcoe_task_ctx_entry *task,
+			       u8 num_rq);
+void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task,
+			     u8 num_rq);
+void bnx2fc_process_els_compl(struct bnx2fc_cmd *els_req,
+			      struct fcoe_task_ctx_entry *task,
+			      u8 num_rq);
+void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
+			   struct fcp_cmnd *fcp_cmnd);
+
+
+
+void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt);
+struct fc_seq *bnx2fc_elsct_send(struct fc_lport *lport, u32 did,
+				      struct fc_frame *fp, unsigned int op,
+				      void (*resp)(struct fc_seq *,
+						   struct fc_frame *,
+						   void *),
+				      void *arg, u32 timeout);
+int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt);
+void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe);
+struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
+					     u32 port_id);
+void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
+				   unsigned char *buf,
+				   u32 frame_len, u16 l2_oxid);
+int bnx2fc_send_stat_req(struct bnx2fc_hba *hba);
+
+#endif
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_hwi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1877 @@
+/* bnx2fc_hwi.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * This file contains the code that low level functions that interact
+ * with 57712 FCoE firmware.
+ *
+ * Copyright (c) 2008 - 2010 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.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+DECLARE_PER_CPU(struct bnx2fc_percpu_s, bnx2fc_percpu);
+
+static void bnx2fc_fastpath_notification(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *new_cqe_kcqe);
+static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *ofld_kcqe);
+static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
+						struct fcoe_kcqe *ofld_kcqe);
+static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code);
+static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *conn_destroy);
+
+int bnx2fc_send_stat_req(struct bnx2fc_hba *hba)
+{
+	struct fcoe_kwqe_stat stat_req;
+	struct kwqe *kwqe_arr[2];
+	int num_kwqes = 1;
+	int rc = 0;
+
+	memset(&stat_req, 0x00, sizeof(struct fcoe_kwqe_stat));
+	stat_req.hdr.op_code = FCOE_KWQE_OPCODE_STAT;
+	stat_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	stat_req.stat_params_addr_lo = (u32) hba->stats_buf_dma;
+	stat_req.stat_params_addr_hi = (u32) ((u64)hba->stats_buf_dma >> 32);
+
+	kwqe_arr[0] = (struct kwqe *) &stat_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+/**
+ * bnx2fc_send_fw_fcoe_init_msg - initiates initial handshake with FCoE f/w
+ *
+ * @hba:	adapter structure pointer
+ *
+ * Send down FCoE firmware init KWQEs which initiates the initial handshake
+ *	with the f/w.
+ *
+ */
+int bnx2fc_send_fw_fcoe_init_msg(struct bnx2fc_hba *hba)
+{
+	struct fcoe_kwqe_init1 fcoe_init1;
+	struct fcoe_kwqe_init2 fcoe_init2;
+	struct fcoe_kwqe_init3 fcoe_init3;
+	struct kwqe *kwqe_arr[3];
+	int num_kwqes = 3;
+	int rc = 0;
+
+	if (!hba->cnic) {
+		printk(KERN_ALERT PFX "hba->cnic NULL during fcoe fw init\n");
+		return -ENODEV;
+	}
+
+	/* fill init1 KWQE */
+	memset(&fcoe_init1, 0x00, sizeof(struct fcoe_kwqe_init1));
+	fcoe_init1.hdr.op_code = FCOE_KWQE_OPCODE_INIT1;
+	fcoe_init1.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	fcoe_init1.num_tasks = BNX2FC_MAX_TASKS;
+	fcoe_init1.sq_num_wqes = BNX2FC_SQ_WQES_MAX;
+	fcoe_init1.rq_num_wqes = BNX2FC_RQ_WQES_MAX;
+	fcoe_init1.rq_buffer_log_size = BNX2FC_RQ_BUF_LOG_SZ;
+	fcoe_init1.cq_num_wqes = BNX2FC_CQ_WQES_MAX;
+	fcoe_init1.dummy_buffer_addr_lo = (u32) hba->dummy_buf_dma;
+	fcoe_init1.dummy_buffer_addr_hi = (u32) ((u64)hba->dummy_buf_dma >> 32);
+	fcoe_init1.task_list_pbl_addr_lo = (u32) hba->task_ctx_bd_dma;
+	fcoe_init1.task_list_pbl_addr_hi =
+				(u32) ((u64) hba->task_ctx_bd_dma >> 32);
+	fcoe_init1.mtu = BNX2FC_MINI_JUMBO_MTU;
+
+	fcoe_init1.flags = (PAGE_SHIFT <<
+				FCOE_KWQE_INIT1_LOG_PAGE_SIZE_SHIFT);
+
+	fcoe_init1.num_sessions_log = BNX2FC_NUM_MAX_SESS_LOG;
+
+	/* fill init2 KWQE */
+	memset(&fcoe_init2, 0x00, sizeof(struct fcoe_kwqe_init2));
+	fcoe_init2.hdr.op_code = FCOE_KWQE_OPCODE_INIT2;
+	fcoe_init2.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	fcoe_init2.hash_tbl_pbl_addr_lo = (u32) hba->hash_tbl_pbl_dma;
+	fcoe_init2.hash_tbl_pbl_addr_hi = (u32)
+					   ((u64) hba->hash_tbl_pbl_dma >> 32);
+
+	fcoe_init2.t2_hash_tbl_addr_lo = (u32) hba->t2_hash_tbl_dma;
+	fcoe_init2.t2_hash_tbl_addr_hi = (u32)
+					  ((u64) hba->t2_hash_tbl_dma >> 32);
+
+	fcoe_init2.t2_ptr_hash_tbl_addr_lo = (u32) hba->t2_hash_tbl_ptr_dma;
+	fcoe_init2.t2_ptr_hash_tbl_addr_hi = (u32)
+					((u64) hba->t2_hash_tbl_ptr_dma >> 32);
+
+	fcoe_init2.free_list_count = BNX2FC_NUM_MAX_SESS;
+
+	/* fill init3 KWQE */
+	memset(&fcoe_init3, 0x00, sizeof(struct fcoe_kwqe_init3));
+	fcoe_init3.hdr.op_code = FCOE_KWQE_OPCODE_INIT3;
+	fcoe_init3.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+	fcoe_init3.error_bit_map_lo = 0xffffffff;
+	fcoe_init3.error_bit_map_hi = 0xffffffff;
+
+
+	kwqe_arr[0] = (struct kwqe *) &fcoe_init1;
+	kwqe_arr[1] = (struct kwqe *) &fcoe_init2;
+	kwqe_arr[2] = (struct kwqe *) &fcoe_init3;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+int bnx2fc_send_fw_fcoe_destroy_msg(struct bnx2fc_hba *hba)
+{
+	struct fcoe_kwqe_destroy fcoe_destroy;
+	struct kwqe *kwqe_arr[2];
+	int num_kwqes = 1;
+	int rc = -1;
+
+	/* fill destroy KWQE */
+	memset(&fcoe_destroy, 0x00, sizeof(struct fcoe_kwqe_destroy));
+	fcoe_destroy.hdr.op_code = FCOE_KWQE_OPCODE_DESTROY;
+	fcoe_destroy.hdr.flags = (FCOE_KWQE_LAYER_CODE <<
+					FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+	kwqe_arr[0] = (struct kwqe *) &fcoe_destroy;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_ofld_req - initiates FCoE Session offload process
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+int bnx2fc_send_session_ofld_req(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt)
+{
+	struct fc_lport *lport = port->lport;
+	struct bnx2fc_hba *hba = port->priv;
+	struct kwqe *kwqe_arr[4];
+	struct fcoe_kwqe_conn_offload1 ofld_req1;
+	struct fcoe_kwqe_conn_offload2 ofld_req2;
+	struct fcoe_kwqe_conn_offload3 ofld_req3;
+	struct fcoe_kwqe_conn_offload4 ofld_req4;
+	struct fc_rport_priv *rdata = tgt->rdata;
+	struct fc_rport *rport = tgt->rport;
+	int num_kwqes = 4;
+	u32 port_id;
+	int rc = 0;
+	u16 conn_id;
+
+	/* Initialize offload request 1 structure */
+	memset(&ofld_req1, 0x00, sizeof(struct fcoe_kwqe_conn_offload1));
+
+	ofld_req1.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN1;
+	ofld_req1.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+
+	conn_id = (u16)tgt->fcoe_conn_id;
+	ofld_req1.fcoe_conn_id = conn_id;
+
+
+	ofld_req1.sq_addr_lo = (u32) tgt->sq_dma;
+	ofld_req1.sq_addr_hi = (u32)((u64) tgt->sq_dma >> 32);
+
+	ofld_req1.rq_pbl_addr_lo = (u32) tgt->rq_pbl_dma;
+	ofld_req1.rq_pbl_addr_hi = (u32)((u64) tgt->rq_pbl_dma >> 32);
+
+	ofld_req1.rq_first_pbe_addr_lo = (u32) tgt->rq_dma;
+	ofld_req1.rq_first_pbe_addr_hi =
+				(u32)((u64) tgt->rq_dma >> 32);
+
+	ofld_req1.rq_prod = 0x8000;
+
+	/* Initialize offload request 2 structure */
+	memset(&ofld_req2, 0x00, sizeof(struct fcoe_kwqe_conn_offload2));
+
+	ofld_req2.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN2;
+	ofld_req2.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	ofld_req2.tx_max_fc_pay_len = rdata->maxframe_size;
+
+	ofld_req2.cq_addr_lo = (u32) tgt->cq_dma;
+	ofld_req2.cq_addr_hi = (u32)((u64)tgt->cq_dma >> 32);
+
+	ofld_req2.xferq_addr_lo = (u32) tgt->xferq_dma;
+	ofld_req2.xferq_addr_hi = (u32)((u64)tgt->xferq_dma >> 32);
+
+	ofld_req2.conn_db_addr_lo = (u32)tgt->conn_db_dma;
+	ofld_req2.conn_db_addr_hi = (u32)((u64)tgt->conn_db_dma >> 32);
+
+	/* Initialize offload request 3 structure */
+	memset(&ofld_req3, 0x00, sizeof(struct fcoe_kwqe_conn_offload3));
+
+	ofld_req3.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN3;
+	ofld_req3.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	ofld_req3.vlan_tag = hba->vlan_id <<
+				FCOE_KWQE_CONN_OFFLOAD3_VLAN_ID_SHIFT;
+	ofld_req3.vlan_tag |= 3 << FCOE_KWQE_CONN_OFFLOAD3_PRIORITY_SHIFT;
+
+	port_id = fc_host_port_id(lport->host);
+	if (port_id == 0) {
+		BNX2FC_HBA_DBG(lport, "ofld_req: port_id = 0, link down?\n");
+		return -EINVAL;
+	}
+
+	/*
+	 * Store s_id of the initiator for further reference. This will
+	 * be used during disable/destroy during linkdown processing as
+	 * when the lport is reset, the port_id also is reset to 0
+	 */
+	tgt->sid = port_id;
+	ofld_req3.s_id[0] = (port_id & 0x000000FF);
+	ofld_req3.s_id[1] = (port_id & 0x0000FF00) >> 8;
+	ofld_req3.s_id[2] = (port_id & 0x00FF0000) >> 16;
+
+	port_id = rport->port_id;
+	ofld_req3.d_id[0] = (port_id & 0x000000FF);
+	ofld_req3.d_id[1] = (port_id & 0x0000FF00) >> 8;
+	ofld_req3.d_id[2] = (port_id & 0x00FF0000) >> 16;
+
+	ofld_req3.tx_total_conc_seqs = rdata->max_seq;
+
+	ofld_req3.tx_max_conc_seqs_c3 = rdata->max_seq;
+	ofld_req3.rx_max_fc_pay_len  = lport->mfs;
+
+	ofld_req3.rx_total_conc_seqs = BNX2FC_MAX_SEQS;
+	ofld_req3.rx_max_conc_seqs_c3 = BNX2FC_MAX_SEQS;
+	ofld_req3.rx_open_seqs_exch_c3 = 1;
+
+	ofld_req3.confq_first_pbe_addr_lo = tgt->confq_dma;
+	ofld_req3.confq_first_pbe_addr_hi = (u32)((u64) tgt->confq_dma >> 32);
+
+	/* set mul_n_port_ids supported flag to 0, until it is supported */
+	ofld_req3.flags = 0;
+	/*
+	ofld_req3.flags |= (((lport->send_sp_features & FC_SP_FT_MNA) ? 1:0) <<
+			    FCOE_KWQE_CONN_OFFLOAD3_B_MUL_N_PORT_IDS_SHIFT);
+	*/
+	/* Info from PLOGI response */
+	ofld_req3.flags |= (((rdata->sp_features & FC_SP_FT_EDTR) ? 1 : 0) <<
+			     FCOE_KWQE_CONN_OFFLOAD3_B_E_D_TOV_RES_SHIFT);
+
+	ofld_req3.flags |= (((rdata->sp_features & FC_SP_FT_SEQC) ? 1 : 0) <<
+			     FCOE_KWQE_CONN_OFFLOAD3_B_CONT_INCR_SEQ_CNT_SHIFT);
+
+	/* vlan flag */
+	ofld_req3.flags |= (hba->vlan_enabled <<
+			    FCOE_KWQE_CONN_OFFLOAD3_B_VLAN_FLAG_SHIFT);
+
+	/* C2_VALID and ACK flags are not set as they are not suppported */
+
+
+	/* Initialize offload request 4 structure */
+	memset(&ofld_req4, 0x00, sizeof(struct fcoe_kwqe_conn_offload4));
+	ofld_req4.hdr.op_code = FCOE_KWQE_OPCODE_OFFLOAD_CONN4;
+	ofld_req4.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	ofld_req4.e_d_tov_timer_val = lport->e_d_tov / 20;
+
+
+	ofld_req4.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+							/* local mac */
+	ofld_req4.src_mac_addr_lo32[1] =  port->data_src_addr[4];
+	ofld_req4.src_mac_addr_lo32[2] =  port->data_src_addr[3];
+	ofld_req4.src_mac_addr_lo32[3] =  port->data_src_addr[2];
+	ofld_req4.src_mac_addr_hi16[0] =  port->data_src_addr[1];
+	ofld_req4.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+	ofld_req4.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	ofld_req4.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
+	ofld_req4.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
+	ofld_req4.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
+	ofld_req4.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
+	ofld_req4.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+
+	ofld_req4.lcq_addr_lo = (u32) tgt->lcq_dma;
+	ofld_req4.lcq_addr_hi = (u32)((u64) tgt->lcq_dma >> 32);
+
+	ofld_req4.confq_pbl_base_addr_lo = (u32) tgt->confq_pbl_dma;
+	ofld_req4.confq_pbl_base_addr_hi =
+					(u32)((u64) tgt->confq_pbl_dma >> 32);
+
+	kwqe_arr[0] = (struct kwqe *) &ofld_req1;
+	kwqe_arr[1] = (struct kwqe *) &ofld_req2;
+	kwqe_arr[2] = (struct kwqe *) &ofld_req3;
+	kwqe_arr[3] = (struct kwqe *) &ofld_req4;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_enable_req - initiates FCoE Session enablement
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+static int bnx2fc_send_session_enable_req(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt)
+{
+	struct kwqe *kwqe_arr[2];
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_kwqe_conn_enable_disable enbl_req;
+	struct fc_lport *lport = port->lport;
+	struct fc_rport *rport = tgt->rport;
+	int num_kwqes = 1;
+	int rc = 0;
+	u32 port_id;
+
+	memset(&enbl_req, 0x00,
+	       sizeof(struct fcoe_kwqe_conn_enable_disable));
+	enbl_req.hdr.op_code = FCOE_KWQE_OPCODE_ENABLE_CONN;
+	enbl_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	enbl_req.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+							/* local mac */
+	enbl_req.src_mac_addr_lo32[1] =  port->data_src_addr[4];
+	enbl_req.src_mac_addr_lo32[2] =  port->data_src_addr[3];
+	enbl_req.src_mac_addr_lo32[3] =  port->data_src_addr[2];
+	enbl_req.src_mac_addr_hi16[0] =  port->data_src_addr[1];
+	enbl_req.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+
+	enbl_req.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	enbl_req.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
+	enbl_req.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
+	enbl_req.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
+	enbl_req.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
+	enbl_req.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+
+	port_id = fc_host_port_id(lport->host);
+	if (port_id != tgt->sid) {
+		printk(KERN_ERR PFX "WARN: enable_req port_id = 0x%x,"
+				"sid = 0x%x\n", port_id, tgt->sid);
+		port_id = tgt->sid;
+	}
+	enbl_req.s_id[0] = (port_id & 0x000000FF);
+	enbl_req.s_id[1] = (port_id & 0x0000FF00) >> 8;
+	enbl_req.s_id[2] = (port_id & 0x00FF0000) >> 16;
+
+	port_id = rport->port_id;
+	enbl_req.d_id[0] = (port_id & 0x000000FF);
+	enbl_req.d_id[1] = (port_id & 0x0000FF00) >> 8;
+	enbl_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
+	enbl_req.vlan_tag = hba->vlan_id <<
+				FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
+	enbl_req.vlan_tag |= 3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
+	enbl_req.vlan_flag = hba->vlan_enabled;
+	enbl_req.context_id = tgt->context_id;
+	enbl_req.conn_id = tgt->fcoe_conn_id;
+
+	kwqe_arr[0] = (struct kwqe *) &enbl_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_disable_req - initiates FCoE Session disable
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+int bnx2fc_send_session_disable_req(struct fcoe_port *port,
+				    struct bnx2fc_rport *tgt)
+{
+	struct bnx2fc_hba *hba = port->priv;
+	struct fcoe_kwqe_conn_enable_disable disable_req;
+	struct kwqe *kwqe_arr[2];
+	struct fc_rport *rport = tgt->rport;
+	int num_kwqes = 1;
+	int rc = 0;
+	u32 port_id;
+
+	memset(&disable_req, 0x00,
+	       sizeof(struct fcoe_kwqe_conn_enable_disable));
+	disable_req.hdr.op_code = FCOE_KWQE_OPCODE_DISABLE_CONN;
+	disable_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	disable_req.src_mac_addr_lo32[0] =  port->data_src_addr[5];
+	disable_req.src_mac_addr_lo32[2] =  port->data_src_addr[3];
+	disable_req.src_mac_addr_lo32[3] =  port->data_src_addr[2];
+	disable_req.src_mac_addr_hi16[0] =  port->data_src_addr[1];
+	disable_req.src_mac_addr_hi16[1] =  port->data_src_addr[0];
+
+	disable_req.dst_mac_addr_lo32[0] =  hba->ctlr.dest_addr[5];/* fcf mac */
+	disable_req.dst_mac_addr_lo32[1] =  hba->ctlr.dest_addr[4];
+	disable_req.dst_mac_addr_lo32[2] =  hba->ctlr.dest_addr[3];
+	disable_req.dst_mac_addr_lo32[3] =  hba->ctlr.dest_addr[2];
+	disable_req.dst_mac_addr_hi16[0] =  hba->ctlr.dest_addr[1];
+	disable_req.dst_mac_addr_hi16[1] =  hba->ctlr.dest_addr[0];
+
+	port_id = tgt->sid;
+	disable_req.s_id[0] = (port_id & 0x000000FF);
+	disable_req.s_id[1] = (port_id & 0x0000FF00) >> 8;
+	disable_req.s_id[2] = (port_id & 0x00FF0000) >> 16;
+
+
+	port_id = rport->port_id;
+	disable_req.d_id[0] = (port_id & 0x000000FF);
+	disable_req.d_id[1] = (port_id & 0x0000FF00) >> 8;
+	disable_req.d_id[2] = (port_id & 0x00FF0000) >> 16;
+	disable_req.context_id = tgt->context_id;
+	disable_req.conn_id = tgt->fcoe_conn_id;
+	disable_req.vlan_tag = hba->vlan_id <<
+				FCOE_KWQE_CONN_ENABLE_DISABLE_VLAN_ID_SHIFT;
+	disable_req.vlan_tag |=
+			3 << FCOE_KWQE_CONN_ENABLE_DISABLE_PRIORITY_SHIFT;
+	disable_req.vlan_flag = hba->vlan_enabled;
+
+	kwqe_arr[0] = (struct kwqe *) &disable_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+/**
+ * bnx2fc_send_session_destroy_req - initiates FCoE Session destroy
+ *
+ * @port:		port structure pointer
+ * @tgt:		bnx2fc_rport structure pointer
+ */
+int bnx2fc_send_session_destroy_req(struct bnx2fc_hba *hba,
+					struct bnx2fc_rport *tgt)
+{
+	struct fcoe_kwqe_conn_destroy destroy_req;
+	struct kwqe *kwqe_arr[2];
+	int num_kwqes = 1;
+	int rc = 0;
+
+	memset(&destroy_req, 0x00, sizeof(struct fcoe_kwqe_conn_destroy));
+	destroy_req.hdr.op_code = FCOE_KWQE_OPCODE_DESTROY_CONN;
+	destroy_req.hdr.flags =
+		(FCOE_KWQE_LAYER_CODE << FCOE_KWQE_HEADER_LAYER_CODE_SHIFT);
+
+	destroy_req.context_id = tgt->context_id;
+	destroy_req.conn_id = tgt->fcoe_conn_id;
+
+	kwqe_arr[0] = (struct kwqe *) &destroy_req;
+
+	if (hba->cnic && hba->cnic->submit_kwqes)
+		rc = hba->cnic->submit_kwqes(hba->cnic, kwqe_arr, num_kwqes);
+
+	return rc;
+}
+
+static void bnx2fc_unsol_els_work(struct work_struct *work)
+{
+	struct bnx2fc_unsol_els *unsol_els;
+	struct fc_lport *lport;
+	struct fc_frame *fp;
+
+	unsol_els = container_of(work, struct bnx2fc_unsol_els, unsol_els_work);
+	lport = unsol_els->lport;
+	fp = unsol_els->fp;
+	fc_exch_recv(lport, fp);
+	kfree(unsol_els);
+}
+
+void bnx2fc_process_l2_frame_compl(struct bnx2fc_rport *tgt,
+				   unsigned char *buf,
+				   u32 frame_len, u16 l2_oxid)
+{
+	struct fcoe_port *port = tgt->port;
+	struct fc_lport *lport = port->lport;
+	struct bnx2fc_unsol_els *unsol_els;
+	struct fc_frame_header *fh;
+	struct fc_frame *fp;
+	struct sk_buff *skb;
+	u32 payload_len;
+	u32 crc;
+	u8 op;
+
+
+	unsol_els = kzalloc(sizeof(*unsol_els), GFP_ATOMIC);
+	if (!unsol_els) {
+		BNX2FC_TGT_DBG(tgt, "Unable to allocate unsol_work\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, "l2_frame_compl l2_oxid = 0x%x, frame_len = %d\n",
+		l2_oxid, frame_len);
+
+	payload_len = frame_len - sizeof(struct fc_frame_header);
+
+	fp = fc_frame_alloc(lport, payload_len);
+	if (!fp) {
+		printk(KERN_ERR PFX "fc_frame_alloc failure\n");
+		return;
+	}
+
+	fh = (struct fc_frame_header *) fc_frame_header_get(fp);
+	/* Copy FC Frame header and payload into the frame */
+	memcpy(fh, buf, frame_len);
+
+	if (l2_oxid != FC_XID_UNKNOWN)
+		fh->fh_ox_id = htons(l2_oxid);
+
+	skb = fp_skb(fp);
+
+	if ((fh->fh_r_ctl == FC_RCTL_ELS_REQ) ||
+	    (fh->fh_r_ctl == FC_RCTL_ELS_REP)) {
+
+		if (fh->fh_type == FC_TYPE_ELS) {
+			op = fc_frame_payload_op(fp);
+			if ((op == ELS_TEST) ||	(op == ELS_ESTC) ||
+			    (op == ELS_FAN) || (op == ELS_CSU)) {
+				/*
+				 * No need to reply for these
+				 * ELS requests
+				 */
+				printk(KERN_ERR PFX "dropping ELS 0x%x\n", op);
+				kfree_skb(skb);
+				return;
+			}
+		}
+		crc = fcoe_fc_crc(fp);
+		fc_frame_init(fp);
+		fr_dev(fp) = lport;
+		fr_sof(fp) = FC_SOF_I3;
+		fr_eof(fp) = FC_EOF_T;
+		fr_crc(fp) = cpu_to_le32(~crc);
+		unsol_els->lport = lport;
+		unsol_els->fp = fp;
+		INIT_WORK(&unsol_els->unsol_els_work, bnx2fc_unsol_els_work);
+		queue_work(bnx2fc_wq, &unsol_els->unsol_els_work);
+	} else {
+		BNX2FC_HBA_DBG(lport, "fh_r_ctl = 0x%x\n", fh->fh_r_ctl);
+		kfree_skb(skb);
+	}
+}
+
+static void bnx2fc_process_unsol_compl(struct bnx2fc_rport *tgt, u16 wqe)
+{
+	u8 num_rq;
+	struct fcoe_err_report_entry *err_entry;
+	unsigned char *rq_data;
+	unsigned char *buf = NULL, *buf1;
+	int i;
+	u16 xid;
+	u32 frame_len, len;
+	struct bnx2fc_cmd *io_req = NULL;
+	struct fcoe_task_ctx_entry *task, *task_page;
+	struct bnx2fc_hba *hba = tgt->port->priv;
+	int task_idx, index;
+	int rc = 0;
+
+
+	BNX2FC_TGT_DBG(tgt, "Entered UNSOL COMPLETION wqe = 0x%x\n", wqe);
+	switch (wqe & FCOE_UNSOLICITED_CQE_SUBTYPE) {
+	case FCOE_UNSOLICITED_FRAME_CQE_TYPE:
+		frame_len = (wqe & FCOE_UNSOLICITED_CQE_PKT_LEN) >>
+			     FCOE_UNSOLICITED_CQE_PKT_LEN_SHIFT;
+
+		num_rq = (frame_len + BNX2FC_RQ_BUF_SZ - 1) / BNX2FC_RQ_BUF_SZ;
+
+		spin_lock_bh(&tgt->tgt_lock);
+		rq_data = (unsigned char *)bnx2fc_get_next_rqe(tgt, num_rq);
+		spin_unlock_bh(&tgt->tgt_lock);
+
+		if (rq_data) {
+			buf = rq_data;
+		} else {
+			buf1 = buf = kmalloc((num_rq * BNX2FC_RQ_BUF_SZ),
+					      GFP_ATOMIC);
+
+			if (!buf1) {
+				BNX2FC_TGT_DBG(tgt, "Memory alloc failure\n");
+				break;
+			}
+
+			for (i = 0; i < num_rq; i++) {
+				spin_lock_bh(&tgt->tgt_lock);
+				rq_data = (unsigned char *)
+					   bnx2fc_get_next_rqe(tgt, 1);
+				spin_unlock_bh(&tgt->tgt_lock);
+				len = BNX2FC_RQ_BUF_SZ;
+				memcpy(buf1, rq_data, len);
+				buf1 += len;
+			}
+		}
+		bnx2fc_process_l2_frame_compl(tgt, buf, frame_len,
+					      FC_XID_UNKNOWN);
+
+		if (buf != rq_data)
+			kfree(buf);
+		spin_lock_bh(&tgt->tgt_lock);
+		bnx2fc_return_rqe(tgt, num_rq);
+		spin_unlock_bh(&tgt->tgt_lock);
+		break;
+
+	case FCOE_ERROR_DETECTION_CQE_TYPE:
+		/*
+		 * In case of error reporting CQE a single RQ entry
+		 * is consumed.
+		 */
+		spin_lock_bh(&tgt->tgt_lock);
+		num_rq = 1;
+		err_entry = (struct fcoe_err_report_entry *)
+			     bnx2fc_get_next_rqe(tgt, 1);
+		xid = err_entry->fc_hdr.ox_id;
+		BNX2FC_TGT_DBG(tgt, "Unsol Error Frame OX_ID = 0x%x\n", xid);
+		BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x\n",
+			err_entry->err_warn_bitmap_hi,
+			err_entry->err_warn_bitmap_lo);
+		BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x\n",
+			err_entry->tx_buf_off, err_entry->rx_buf_off);
+
+		bnx2fc_return_rqe(tgt, 1);
+
+		if (xid > BNX2FC_MAX_XID) {
+			BNX2FC_TGT_DBG(tgt, "xid(0x%x) out of FW range\n",
+				   xid);
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+		index = xid % BNX2FC_TASKS_PER_PAGE;
+		task_page = (struct fcoe_task_ctx_entry *)
+						hba->task_ctx[task_idx];
+		task = &(task_page[index]);
+
+		io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
+		if (!io_req) {
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		if (io_req->cmd_type != BNX2FC_SCSI_CMD) {
+			printk(KERN_ERR PFX "err_warn: Not a SCSI cmd\n");
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		if (test_and_clear_bit(BNX2FC_FLAG_IO_CLEANUP,
+				       &io_req->req_flags)) {
+			BNX2FC_IO_DBG(io_req, "unsol_err: cleanup in "
+					    "progress.. ignore unsol err\n");
+			spin_unlock_bh(&tgt->tgt_lock);
+			break;
+		}
+
+		/*
+		 * If ABTS is already in progress, and FW error is
+		 * received after that, do not cancel the timeout_work
+		 * and let the error recovery continue by explicitly
+		 * logging out the target, when the ABTS eventually
+		 * times out.
+		 */
+		if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+				      &io_req->req_flags)) {
+			/*
+			 * Cancel the timeout_work, as we received IO
+			 * completion with FW error.
+			 */
+			if (cancel_delayed_work(&io_req->timeout_work))
+				kref_put(&io_req->refcount,
+					 bnx2fc_cmd_release); /* timer hold */
+
+			rc = bnx2fc_initiate_abts(io_req);
+			if (rc != SUCCESS) {
+				BNX2FC_IO_DBG(io_req, "err_warn: initiate_abts "
+					"failed. issue cleanup\n");
+				rc = bnx2fc_initiate_cleanup(io_req);
+				BUG_ON(rc);
+			}
+		} else
+			printk(KERN_ERR PFX "err_warn: io_req (0x%x) already "
+					    "in ABTS processing\n", xid);
+		spin_unlock_bh(&tgt->tgt_lock);
+		break;
+
+	case FCOE_WARNING_DETECTION_CQE_TYPE:
+		/*
+		 *In case of warning reporting CQE a single RQ entry
+		 * is consumes.
+		 */
+		spin_lock_bh(&tgt->tgt_lock);
+		num_rq = 1;
+		err_entry = (struct fcoe_err_report_entry *)
+			     bnx2fc_get_next_rqe(tgt, 1);
+		xid = cpu_to_be16(err_entry->fc_hdr.ox_id);
+		BNX2FC_TGT_DBG(tgt, "Unsol Warning Frame OX_ID = 0x%x\n", xid);
+		BNX2FC_TGT_DBG(tgt, "err_warn_bitmap = %08x:%08x",
+			err_entry->err_warn_bitmap_hi,
+			err_entry->err_warn_bitmap_lo);
+		BNX2FC_TGT_DBG(tgt, "buf_offsets - tx = 0x%x, rx = 0x%x",
+			err_entry->tx_buf_off, err_entry->rx_buf_off);
+
+		bnx2fc_return_rqe(tgt, 1);
+		spin_unlock_bh(&tgt->tgt_lock);
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unsol Compl: Invalid CQE Subtype\n");
+		break;
+	}
+}
+
+void bnx2fc_process_cq_compl(struct bnx2fc_rport *tgt, u16 wqe)
+{
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_cmd *io_req;
+	int task_idx, index;
+	u16 xid;
+	u8  cmd_type;
+	u8 rx_state = 0;
+	u8 num_rq;
+
+	spin_lock_bh(&tgt->tgt_lock);
+	xid = wqe & FCOE_PEND_WQ_CQE_TASK_ID;
+	if (xid >= BNX2FC_MAX_TASKS) {
+		printk(KERN_ALERT PFX "ERROR:xid out of range\n");
+		spin_unlock_bh(&tgt->tgt_lock);
+		return;
+	}
+	task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+	task_page = (struct fcoe_task_ctx_entry *)hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+
+	num_rq = ((task->rx_wr_tx_rd.rx_flags &
+		   FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE) >>
+		   FCOE_TASK_CTX_ENTRY_RXWR_TXRD_NUM_RQ_WQE_SHIFT);
+
+	io_req = (struct bnx2fc_cmd *)hba->cmd_mgr->cmds[xid];
+
+	if (io_req == NULL) {
+		printk(KERN_ERR PFX "ERROR? cq_compl - io_req is NULL\n");
+		spin_unlock_bh(&tgt->tgt_lock);
+		return;
+	}
+
+	/* Timestamp IO completion time */
+	cmd_type = io_req->cmd_type;
+
+	/* optimized completion path */
+	if (cmd_type == BNX2FC_SCSI_CMD) {
+		rx_state = ((task->rx_wr_tx_rd.rx_flags &
+			    FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE) >>
+			    FCOE_TASK_CTX_ENTRY_RXWR_TXRD_RX_STATE_SHIFT);
+
+		if (rx_state == FCOE_TASK_RX_STATE_COMPLETED) {
+			bnx2fc_process_scsi_cmd_compl(io_req, task, num_rq);
+			spin_unlock_bh(&tgt->tgt_lock);
+			return;
+		}
+	}
+
+	/* Process other IO completion types */
+	switch (cmd_type) {
+	case BNX2FC_SCSI_CMD:
+		if (rx_state == FCOE_TASK_RX_STATE_ABTS_COMPLETED)
+			bnx2fc_process_abts_compl(io_req, task, num_rq);
+		else if (rx_state ==
+			 FCOE_TASK_RX_STATE_EXCHANGE_CLEANUP_COMPLETED)
+			bnx2fc_process_cleanup_compl(io_req, task, num_rq);
+		else
+			printk(KERN_ERR PFX "Invalid rx state - %d\n",
+				rx_state);
+		break;
+
+	case BNX2FC_TASK_MGMT_CMD:
+		BNX2FC_IO_DBG(io_req, "Processing TM complete\n");
+		bnx2fc_process_tm_compl(io_req, task, num_rq);
+		break;
+
+	case BNX2FC_ABTS:
+		/*
+		 * ABTS request received by firmware. ABTS response
+		 * will be delivered to the task belonging to the IO
+		 * that was aborted
+		 */
+		BNX2FC_IO_DBG(io_req, "cq_compl- ABTS sent out by fw\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		break;
+
+	case BNX2FC_ELS:
+		BNX2FC_IO_DBG(io_req, "cq_compl - call process_els_compl\n");
+		bnx2fc_process_els_compl(io_req, task, num_rq);
+		break;
+
+	case BNX2FC_CLEANUP:
+		BNX2FC_IO_DBG(io_req, "cq_compl- cleanup resp rcvd\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Invalid cmd_type %d\n", cmd_type);
+		break;
+	}
+	spin_unlock_bh(&tgt->tgt_lock);
+}
+
+struct bnx2fc_work *bnx2fc_alloc_work(struct bnx2fc_rport *tgt, u16 wqe)
+{
+	struct bnx2fc_work *work;
+	work = kzalloc(sizeof(struct bnx2fc_work), GFP_ATOMIC);
+	if (!work)
+		return NULL;
+
+	INIT_LIST_HEAD(&work->list);
+	work->tgt = tgt;
+	work->wqe = wqe;
+	return work;
+}
+
+int bnx2fc_process_new_cqes(struct bnx2fc_rport *tgt)
+{
+	struct fcoe_cqe *cq;
+	u32 cq_cons;
+	struct fcoe_cqe *cqe;
+	u16 wqe;
+	bool more_cqes_found = false;
+
+	/*
+	 * cq_lock is a low contention lock used to protect
+	 * the CQ data structure from being freed up during
+	 * the upload operation
+	 */
+	spin_lock_bh(&tgt->cq_lock);
+
+	if (!tgt->cq) {
+		printk(KERN_ERR PFX "process_new_cqes: cq is NULL\n");
+		spin_unlock_bh(&tgt->cq_lock);
+		return 0;
+	}
+	cq = tgt->cq;
+	cq_cons = tgt->cq_cons_idx;
+	cqe = &cq[cq_cons];
+
+	do {
+		more_cqes_found ^= true;
+
+		while (((wqe = cqe->wqe) & FCOE_CQE_TOGGLE_BIT) ==
+		       (tgt->cq_curr_toggle_bit <<
+		       FCOE_CQE_TOGGLE_BIT_SHIFT)) {
+
+			/* new entry on the cq */
+			if (wqe & FCOE_CQE_CQE_TYPE) {
+				/* Unsolicited event notification */
+				bnx2fc_process_unsol_compl(tgt, wqe);
+			} else {
+				struct bnx2fc_work *work = NULL;
+				struct bnx2fc_percpu_s *fps = NULL;
+				unsigned int cpu = wqe % num_possible_cpus();
+
+				fps = &per_cpu(bnx2fc_percpu, cpu);
+				spin_lock_bh(&fps->fp_work_lock);
+				if (unlikely(!fps->iothread))
+					goto unlock;
+
+				work = bnx2fc_alloc_work(tgt, wqe);
+				if (work)
+					list_add_tail(&work->list,
+							&fps->work_list);
+unlock:
+				spin_unlock_bh(&fps->fp_work_lock);
+
+				/* Pending work request completion */
+				if (fps->iothread && work)
+					wake_up_process(fps->iothread);
+				else
+					bnx2fc_process_cq_compl(tgt, wqe);
+			}
+			cqe++;
+			tgt->cq_cons_idx++;
+
+			if (tgt->cq_cons_idx == BNX2FC_CQ_WQES_MAX) {
+				tgt->cq_cons_idx = 0;
+				cqe = cq;
+				tgt->cq_curr_toggle_bit =
+					1 - tgt->cq_curr_toggle_bit;
+			}
+		}
+		/* Re-arm CQ */
+		if (more_cqes_found) {
+			tgt->conn_db->cq_arm.lo = -1;
+			wmb();
+		}
+	} while (more_cqes_found);
+
+	/*
+	 * Commit tgt->cq_cons_idx change to the memory
+	 * spin_lock implies full memory barrier, no need to smp_wmb
+	 */
+
+	spin_unlock_bh(&tgt->cq_lock);
+	return 0;
+}
+
+/**
+ * bnx2fc_fastpath_notification - process global event queue (KCQ)
+ *
+ * @hba:		adapter structure pointer
+ * @new_cqe_kcqe:	pointer to newly DMA'd KCQ entry
+ *
+ * Fast path event notification handler
+ */
+static void bnx2fc_fastpath_notification(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *new_cqe_kcqe)
+{
+	u32 conn_id = new_cqe_kcqe->fcoe_conn_id;
+	struct bnx2fc_rport *tgt = hba->tgt_ofld_list[conn_id];
+
+	if (!tgt) {
+		printk(KERN_ALERT PFX "conn_id 0x%x not valid\n", conn_id);
+		return;
+	}
+
+	bnx2fc_process_new_cqes(tgt);
+}
+
+/**
+ * bnx2fc_process_ofld_cmpl - process FCoE session offload completion
+ *
+ * @hba:	adapter structure pointer
+ * @ofld_kcqe:	connection offload kcqe pointer
+ *
+ * handle session offload completion, enable the session if offload is
+ * successful.
+ */
+static void bnx2fc_process_ofld_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *ofld_kcqe)
+{
+	struct bnx2fc_rport		*tgt;
+	struct fcoe_port		*port;
+	u32				conn_id;
+	u32				context_id;
+	int				rc;
+
+	conn_id = ofld_kcqe->fcoe_conn_id;
+	context_id = ofld_kcqe->fcoe_conn_context_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "ERROR:ofld_cmpl: No pending ofld req\n");
+		return;
+	}
+	BNX2FC_TGT_DBG(tgt, "Entered ofld compl - context_id = 0x%x\n",
+		ofld_kcqe->fcoe_conn_context_id);
+	port = tgt->port;
+	if (hba != tgt->port->priv) {
+		printk(KERN_ALERT PFX "ERROR:ofld_cmpl: HBA mis-match\n");
+		goto ofld_cmpl_err;
+	}
+	/*
+	 * cnic has allocated a context_id for this session; use this
+	 * while enabling the session.
+	 */
+	tgt->context_id = context_id;
+	if (ofld_kcqe->completion_status) {
+		if (ofld_kcqe->completion_status ==
+				FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE) {
+			printk(KERN_ERR PFX "unable to allocate FCoE context "
+				"resources\n");
+			set_bit(BNX2FC_FLAG_CTX_ALLOC_FAILURE, &tgt->flags);
+		}
+		goto ofld_cmpl_err;
+	} else {
+
+		/* now enable the session */
+		rc = bnx2fc_send_session_enable_req(port, tgt);
+		if (rc) {
+			printk(KERN_ALERT PFX "enable session failed\n");
+			goto ofld_cmpl_err;
+		}
+	}
+	return;
+ofld_cmpl_err:
+	set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->ofld_wait);
+}
+
+/**
+ * bnx2fc_process_enable_conn_cmpl - process FCoE session enable completion
+ *
+ * @hba:	adapter structure pointer
+ * @ofld_kcqe:	connection offload kcqe pointer
+ *
+ * handle session enable completion, mark the rport as ready
+ */
+
+static void bnx2fc_process_enable_conn_cmpl(struct bnx2fc_hba *hba,
+						struct fcoe_kcqe *ofld_kcqe)
+{
+	struct bnx2fc_rport		*tgt;
+	u32				conn_id;
+	u32				context_id;
+
+	context_id = ofld_kcqe->fcoe_conn_context_id;
+	conn_id = ofld_kcqe->fcoe_conn_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "ERROR:enbl_cmpl: No pending ofld req\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, "Enable compl - context_id = 0x%x\n",
+		ofld_kcqe->fcoe_conn_context_id);
+
+	/*
+	 * context_id should be the same for this target during offload
+	 * and enable
+	 */
+	if (tgt->context_id != context_id) {
+		printk(KERN_ALERT PFX "context id mis-match\n");
+		return;
+	}
+	if (hba != tgt->port->priv) {
+		printk(KERN_ALERT PFX "bnx2fc-enbl_cmpl: HBA mis-match\n");
+		goto enbl_cmpl_err;
+	}
+	if (ofld_kcqe->completion_status) {
+		goto enbl_cmpl_err;
+	} else {
+		/* enable successful - rport ready for issuing IOs */
+		set_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+		wake_up_interruptible(&tgt->ofld_wait);
+	}
+	return;
+
+enbl_cmpl_err:
+	set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->ofld_wait);
+}
+
+static void bnx2fc_process_conn_disable_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *disable_kcqe)
+{
+
+	struct bnx2fc_rport		*tgt;
+	u32				conn_id;
+
+	conn_id = disable_kcqe->fcoe_conn_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "ERROR: disable_cmpl: No disable req\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, PFX "disable_cmpl: conn_id %d\n", conn_id);
+
+	if (disable_kcqe->completion_status) {
+		printk(KERN_ALERT PFX "ERROR: Disable failed with cmpl status %d\n",
+			disable_kcqe->completion_status);
+		return;
+	} else {
+		/* disable successful */
+		BNX2FC_TGT_DBG(tgt, "disable successful\n");
+		clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_DISABLED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+		wake_up_interruptible(&tgt->upld_wait);
+	}
+}
+
+static void bnx2fc_process_conn_destroy_cmpl(struct bnx2fc_hba *hba,
+					struct fcoe_kcqe *destroy_kcqe)
+{
+	struct bnx2fc_rport		*tgt;
+	u32				conn_id;
+
+	conn_id = destroy_kcqe->fcoe_conn_id;
+	tgt = hba->tgt_ofld_list[conn_id];
+	if (!tgt) {
+		printk(KERN_ALERT PFX "destroy_cmpl: No destroy req\n");
+		return;
+	}
+
+	BNX2FC_TGT_DBG(tgt, "destroy_cmpl: conn_id %d\n", conn_id);
+
+	if (destroy_kcqe->completion_status) {
+		printk(KERN_ALERT PFX "Destroy conn failed, cmpl status %d\n",
+			destroy_kcqe->completion_status);
+		return;
+	} else {
+		/* destroy successful */
+		BNX2FC_TGT_DBG(tgt, "upload successful\n");
+		clear_bit(BNX2FC_FLAG_DISABLED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_DESTROYED, &tgt->flags);
+		set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+		wake_up_interruptible(&tgt->upld_wait);
+	}
+}
+
+static void bnx2fc_init_failure(struct bnx2fc_hba *hba, u32 err_code)
+{
+	switch (err_code) {
+	case FCOE_KCQE_COMPLETION_STATUS_INVALID_OPCODE:
+		printk(KERN_ERR PFX "init_failure due to invalid opcode\n");
+		break;
+
+	case FCOE_KCQE_COMPLETION_STATUS_CTX_ALLOC_FAILURE:
+		printk(KERN_ERR PFX "init failed due to ctx alloc failure\n");
+		break;
+
+	case FCOE_KCQE_COMPLETION_STATUS_NIC_ERROR:
+		printk(KERN_ERR PFX "init_failure due to NIC error\n");
+		break;
+
+	default:
+		printk(KERN_ERR PFX "Unknown Error code %d\n", err_code);
+	}
+}
+
+/**
+ * bnx2fc_indicae_kcqe - process KCQE
+ *
+ * @hba:	adapter structure pointer
+ * @kcqe:	kcqe pointer
+ * @num_cqe:	Number of completion queue elements
+ *
+ * Generic KCQ event handler
+ */
+void bnx2fc_indicate_kcqe(void *context, struct kcqe *kcq[],
+					u32 num_cqe)
+{
+	struct bnx2fc_hba *hba = (struct bnx2fc_hba *)context;
+	int i = 0;
+	struct fcoe_kcqe *kcqe = NULL;
+
+	while (i < num_cqe) {
+		kcqe = (struct fcoe_kcqe *) kcq[i++];
+
+		switch (kcqe->op_code) {
+		case FCOE_KCQE_OPCODE_CQ_EVENT_NOTIFICATION:
+			bnx2fc_fastpath_notification(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_OFFLOAD_CONN:
+			bnx2fc_process_ofld_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_ENABLE_CONN:
+			bnx2fc_process_enable_conn_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_INIT_FUNC:
+			if (kcqe->completion_status !=
+					FCOE_KCQE_COMPLETION_STATUS_SUCCESS) {
+				bnx2fc_init_failure(hba,
+						kcqe->completion_status);
+			} else {
+				set_bit(ADAPTER_STATE_UP, &hba->adapter_state);
+				bnx2fc_get_link_state(hba);
+				printk(KERN_INFO PFX "[%.2x]: FCOE_INIT passed\n",
+					(u8)hba->pcidev->bus->number);
+			}
+			break;
+
+		case FCOE_KCQE_OPCODE_DESTROY_FUNC:
+			if (kcqe->completion_status !=
+					FCOE_KCQE_COMPLETION_STATUS_SUCCESS) {
+
+				printk(KERN_ERR PFX "DESTROY failed\n");
+			} else {
+				printk(KERN_ERR PFX "DESTROY success\n");
+			}
+			hba->flags |= BNX2FC_FLAG_DESTROY_CMPL;
+			wake_up_interruptible(&hba->destroy_wait);
+			break;
+
+		case FCOE_KCQE_OPCODE_DISABLE_CONN:
+			bnx2fc_process_conn_disable_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_DESTROY_CONN:
+			bnx2fc_process_conn_destroy_cmpl(hba, kcqe);
+			break;
+
+		case FCOE_KCQE_OPCODE_STAT_FUNC:
+			if (kcqe->completion_status !=
+			    FCOE_KCQE_COMPLETION_STATUS_SUCCESS)
+				printk(KERN_ERR PFX "STAT failed\n");
+			complete(&hba->stat_req_done);
+			break;
+
+		case FCOE_KCQE_OPCODE_FCOE_ERROR:
+			/* fall thru */
+		default:
+			printk(KERN_ALERT PFX "unknown opcode 0x%x\n",
+								kcqe->op_code);
+		}
+	}
+}
+
+void bnx2fc_add_2_sq(struct bnx2fc_rport *tgt, u16 xid)
+{
+	struct fcoe_sqe *sqe;
+
+	sqe = &tgt->sq[tgt->sq_prod_idx];
+
+	/* Fill SQ WQE */
+	sqe->wqe = xid << FCOE_SQE_TASK_ID_SHIFT;
+	sqe->wqe |= tgt->sq_curr_toggle_bit << FCOE_SQE_TOGGLE_BIT_SHIFT;
+
+	/* Advance SQ Prod Idx */
+	if (++tgt->sq_prod_idx == BNX2FC_SQ_WQES_MAX) {
+		tgt->sq_prod_idx = 0;
+		tgt->sq_curr_toggle_bit = 1 - tgt->sq_curr_toggle_bit;
+	}
+}
+
+void bnx2fc_ring_doorbell(struct bnx2fc_rport *tgt)
+{
+	struct b577xx_doorbell_set_prod ev_doorbell;
+	u32 msg;
+
+	wmb();
+
+	memset(&ev_doorbell, 0, sizeof(struct b577xx_doorbell_set_prod));
+	ev_doorbell.header.header = B577XX_DOORBELL_HDR_DB_TYPE;
+
+	ev_doorbell.prod = tgt->sq_prod_idx |
+				(tgt->sq_curr_toggle_bit << 15);
+	ev_doorbell.header.header |= B577XX_FCOE_CONNECTION_TYPE <<
+					B577XX_DOORBELL_HDR_CONN_TYPE_SHIFT;
+	msg = *((u32 *)&ev_doorbell);
+	writel(cpu_to_le32(msg), tgt->ctx_base);
+
+	mmiowb();
+
+}
+
+int bnx2fc_map_doorbell(struct bnx2fc_rport *tgt)
+{
+	u32 context_id = tgt->context_id;
+	struct fcoe_port *port = tgt->port;
+	u32 reg_off;
+	resource_size_t reg_base;
+	struct bnx2fc_hba *hba = port->priv;
+
+	reg_base = pci_resource_start(hba->pcidev,
+					BNX2X_DOORBELL_PCI_BAR);
+	reg_off = BNX2FC_5771X_DB_PAGE_SIZE *
+			(context_id & 0x1FFFF) + DPM_TRIGER_TYPE;
+	tgt->ctx_base = ioremap_nocache(reg_base + reg_off, 4);
+	if (!tgt->ctx_base)
+		return -ENOMEM;
+	return 0;
+}
+
+char *bnx2fc_get_next_rqe(struct bnx2fc_rport *tgt, u8 num_items)
+{
+	char *buf = (char *)tgt->rq + (tgt->rq_cons_idx * BNX2FC_RQ_BUF_SZ);
+
+	if (tgt->rq_cons_idx + num_items > BNX2FC_RQ_WQES_MAX)
+		return NULL;
+
+	tgt->rq_cons_idx += num_items;
+
+	if (tgt->rq_cons_idx >= BNX2FC_RQ_WQES_MAX)
+		tgt->rq_cons_idx -= BNX2FC_RQ_WQES_MAX;
+
+	return buf;
+}
+
+void bnx2fc_return_rqe(struct bnx2fc_rport *tgt, u8 num_items)
+{
+	/* return the rq buffer */
+	u32 next_prod_idx = tgt->rq_prod_idx + num_items;
+	if ((next_prod_idx & 0x7fff) == BNX2FC_RQ_WQES_MAX) {
+		/* Wrap around RQ */
+		next_prod_idx += 0x8000 - BNX2FC_RQ_WQES_MAX;
+	}
+	tgt->rq_prod_idx = next_prod_idx;
+	tgt->conn_db->rq_prod = tgt->rq_prod_idx;
+}
+
+void bnx2fc_init_cleanup_task(struct bnx2fc_cmd *io_req,
+			      struct fcoe_task_ctx_entry *task,
+			      u16 orig_xid)
+{
+	u8 task_type = FCOE_TASK_TYPE_EXCHANGE_CLEANUP;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	u32 context_id = tgt->context_id;
+
+	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+	/* Tx Write Rx Read */
+	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_EXCHANGE_CLEANUP <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
+	task->tx_wr_rx_rd.init_flags = task_type <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+	/* Common */
+	task->cmn.common_flags = context_id <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
+	task->cmn.general.cleanup_info.task_id = orig_xid;
+
+
+}
+
+void bnx2fc_init_mp_task(struct bnx2fc_cmd *io_req,
+				struct fcoe_task_ctx_entry *task)
+{
+	struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct fc_frame_header *fc_hdr;
+	u8 task_type = 0;
+	u64 *hdr;
+	u64 temp_hdr[3];
+	u32 context_id;
+
+
+	/* Obtain task_type */
+	if ((io_req->cmd_type == BNX2FC_TASK_MGMT_CMD) ||
+	    (io_req->cmd_type == BNX2FC_ELS)) {
+		task_type = FCOE_TASK_TYPE_MIDPATH;
+	} else if (io_req->cmd_type == BNX2FC_ABTS) {
+		task_type = FCOE_TASK_TYPE_ABTS;
+	}
+
+	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+	/* Setup the task from io_req for easy reference */
+	io_req->task = task;
+
+	BNX2FC_IO_DBG(io_req, "Init MP task for cmd_type = %d task_type = %d\n",
+		io_req->cmd_type, task_type);
+
+	/* Tx only */
+	if ((task_type == FCOE_TASK_TYPE_MIDPATH) ||
+	    (task_type == FCOE_TASK_TYPE_UNSOLICITED)) {
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+				(u32)mp_req->mp_req_bd_dma;
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+				(u32)((u64)mp_req->mp_req_bd_dma >> 32);
+		task->tx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+		BNX2FC_IO_DBG(io_req, "init_mp_task - bd_dma = 0x%llx\n",
+			      (unsigned long long)mp_req->mp_req_bd_dma);
+	}
+
+	/* Tx Write Rx Read */
+	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_INIT <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
+	task->tx_wr_rx_rd.init_flags = task_type <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+
+	/* Common */
+	task->cmn.data_2_trns = io_req->data_xfer_len;
+	context_id = tgt->context_id;
+	task->cmn.common_flags = context_id <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+			FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+
+	/* Rx Write Tx Read */
+	fc_hdr = &(mp_req->req_fc_hdr);
+	if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+		fc_hdr->fh_ox_id = cpu_to_be16(io_req->xid);
+		fc_hdr->fh_rx_id = htons(0xffff);
+		task->rx_wr_tx_rd.rx_id = 0xffff;
+	} else if (task_type == FCOE_TASK_TYPE_UNSOLICITED) {
+		fc_hdr->fh_rx_id = cpu_to_be16(io_req->xid);
+	}
+
+	/* Fill FC Header into middle path buffer */
+	hdr = (u64 *) &task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	memcpy(temp_hdr, fc_hdr, sizeof(temp_hdr));
+	hdr[0] = cpu_to_be64(temp_hdr[0]);
+	hdr[1] = cpu_to_be64(temp_hdr[1]);
+	hdr[2] = cpu_to_be64(temp_hdr[2]);
+
+	/* Rx Only */
+	if (task_type == FCOE_TASK_TYPE_MIDPATH) {
+
+		task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+				(u32)mp_req->mp_resp_bd_dma;
+		task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+				(u32)((u64)mp_req->mp_resp_bd_dma >> 32);
+		task->rx_wr_only.sgl_ctx.mul_sges.sgl_size = 1;
+	}
+}
+
+void bnx2fc_init_task(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task)
+{
+	u8 task_type;
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct io_bdt *bd_tbl = io_req->bd_tbl;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	u64 *fcp_cmnd;
+	u64 tmp_fcp_cmnd[4];
+	u32 context_id;
+	int cnt, i;
+	int bd_count;
+
+	memset(task, 0, sizeof(struct fcoe_task_ctx_entry));
+
+	/* Setup the task from io_req for easy reference */
+	io_req->task = task;
+
+	if (sc_cmd->sc_data_direction == DMA_TO_DEVICE)
+		task_type = FCOE_TASK_TYPE_WRITE;
+	else
+		task_type = FCOE_TASK_TYPE_READ;
+
+	/* Tx only */
+	if (task_type == FCOE_TASK_TYPE_WRITE) {
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+				(u32)bd_tbl->bd_tbl_dma;
+		task->tx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+				(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+		task->tx_wr_only.sgl_ctx.mul_sges.sgl_size =
+				bd_tbl->bd_valid;
+	}
+
+	/*Tx Write Rx Read */
+	/* Init state to NORMAL */
+	task->tx_wr_rx_rd.tx_flags = FCOE_TASK_TX_STATE_NORMAL <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TX_STATE_SHIFT;
+	task->tx_wr_rx_rd.init_flags = task_type <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_TASK_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_DEV_TYPE_DISK <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_DEV_TYPE_SHIFT;
+	task->tx_wr_rx_rd.init_flags |= FCOE_TASK_CLASS_TYPE_3 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_CLASS_TYPE_SHIFT;
+
+	/* Common */
+	task->cmn.data_2_trns = io_req->data_xfer_len;
+	context_id = tgt->context_id;
+	task->cmn.common_flags = context_id <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_CID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+				FCOE_TASK_CTX_ENTRY_TX_RX_CMN_VALID_SHIFT;
+	task->cmn.common_flags |= 1 <<
+			FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME_SHIFT;
+
+	/* Set initiative ownership */
+	task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_SEQ_INIT;
+
+	/* Set initial seq counter */
+	task->cmn.tx_low_seq_cnt = 1;
+
+	/* Set state to "waiting for the first packet" */
+	task->cmn.common_flags |= FCOE_TASK_CTX_ENTRY_TX_RX_CMN_EXP_FIRST_FRAME;
+
+	/* Fill FCP_CMND IU */
+	fcp_cmnd = (u64 *)
+		    task->cmn.general.cmd_info.fcp_cmd_payload.opaque;
+	bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)&tmp_fcp_cmnd);
+
+	/* swap fcp_cmnd */
+	cnt = sizeof(struct fcp_cmnd) / sizeof(u64);
+
+	for (i = 0; i < cnt; i++) {
+		*fcp_cmnd = cpu_to_be64(tmp_fcp_cmnd[i]);
+		fcp_cmnd++;
+	}
+
+	/* Rx Write Tx Read */
+	task->rx_wr_tx_rd.rx_id = 0xffff;
+
+	/* Rx Only */
+	if (task_type == FCOE_TASK_TYPE_READ) {
+
+		bd_count = bd_tbl->bd_valid;
+		if (bd_count == 1) {
+
+			struct fcoe_bd_ctx *fcoe_bd_tbl = bd_tbl->bd_tbl;
+
+			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.lo =
+					fcoe_bd_tbl->buf_addr_lo;
+			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_addr.hi =
+					fcoe_bd_tbl->buf_addr_hi;
+			task->rx_wr_only.sgl_ctx.single_sge.cur_buf_rem =
+					fcoe_bd_tbl->buf_len;
+			task->tx_wr_rx_rd.init_flags |= 1 <<
+				FCOE_TASK_CTX_ENTRY_TXWR_RXRD_SINGLE_SGE_SHIFT;
+		} else {
+
+			task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.lo =
+					(u32)bd_tbl->bd_tbl_dma;
+			task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_addr.hi =
+					(u32)((u64)bd_tbl->bd_tbl_dma >> 32);
+			task->rx_wr_only.sgl_ctx.mul_sges.sgl_size =
+					bd_tbl->bd_valid;
+		}
+	}
+}
+
+/**
+ * bnx2fc_setup_task_ctx - allocate and map task context
+ *
+ * @hba:	pointer to adapter structure
+ *
+ * allocate memory for task context, and associated BD table to be used
+ * by firmware
+ *
+ */
+int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
+{
+	int rc = 0;
+	struct regpair *task_ctx_bdt;
+	dma_addr_t addr;
+	int i;
+
+	/*
+	 * Allocate task context bd table. A page size of bd table
+	 * can map 256 buffers. Each buffer contains 32 task context
+	 * entries. Hence the limit with one page is 8192 task context
+	 * entries.
+	 */
+	hba->task_ctx_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+						  PAGE_SIZE,
+						  &hba->task_ctx_bd_dma,
+						  GFP_KERNEL);
+	if (!hba->task_ctx_bd_tbl) {
+		printk(KERN_ERR PFX "unable to allocate task context BDT\n");
+		rc = -1;
+		goto out;
+	}
+	memset(hba->task_ctx_bd_tbl, 0, PAGE_SIZE);
+
+	/*
+	 * Allocate task_ctx which is an array of pointers pointing to
+	 * a page containing 32 task contexts
+	 */
+	hba->task_ctx = kzalloc((BNX2FC_TASK_CTX_ARR_SZ * sizeof(void *)),
+				 GFP_KERNEL);
+	if (!hba->task_ctx) {
+		printk(KERN_ERR PFX "unable to allocate task context array\n");
+		rc = -1;
+		goto out1;
+	}
+
+	/*
+	 * Allocate task_ctx_dma which is an array of dma addresses
+	 */
+	hba->task_ctx_dma = kmalloc((BNX2FC_TASK_CTX_ARR_SZ *
+					sizeof(dma_addr_t)), GFP_KERNEL);
+	if (!hba->task_ctx_dma) {
+		printk(KERN_ERR PFX "unable to alloc context mapping array\n");
+		rc = -1;
+		goto out2;
+	}
+
+	task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl;
+	for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+
+		hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev,
+						      PAGE_SIZE,
+						      &hba->task_ctx_dma[i],
+						      GFP_KERNEL);
+		if (!hba->task_ctx[i]) {
+			printk(KERN_ERR PFX "unable to alloc task context\n");
+			rc = -1;
+			goto out3;
+		}
+		memset(hba->task_ctx[i], 0, PAGE_SIZE);
+		addr = (u64)hba->task_ctx_dma[i];
+		task_ctx_bdt->hi = cpu_to_le32((u64)addr >> 32);
+		task_ctx_bdt->lo = cpu_to_le32((u32)addr);
+		task_ctx_bdt++;
+	}
+	return 0;
+
+out3:
+	for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+		if (hba->task_ctx[i]) {
+
+			dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				hba->task_ctx[i], hba->task_ctx_dma[i]);
+			hba->task_ctx[i] = NULL;
+		}
+	}
+
+	kfree(hba->task_ctx_dma);
+	hba->task_ctx_dma = NULL;
+out2:
+	kfree(hba->task_ctx);
+	hba->task_ctx = NULL;
+out1:
+	dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+			hba->task_ctx_bd_tbl, hba->task_ctx_bd_dma);
+	hba->task_ctx_bd_tbl = NULL;
+out:
+	return rc;
+}
+
+void bnx2fc_free_task_ctx(struct bnx2fc_hba *hba)
+{
+	int i;
+
+	if (hba->task_ctx_bd_tbl) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				    hba->task_ctx_bd_tbl,
+				    hba->task_ctx_bd_dma);
+		hba->task_ctx_bd_tbl = NULL;
+	}
+
+	if (hba->task_ctx) {
+		for (i = 0; i < BNX2FC_TASK_CTX_ARR_SZ; i++) {
+			if (hba->task_ctx[i]) {
+				dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+						    hba->task_ctx[i],
+						    hba->task_ctx_dma[i]);
+				hba->task_ctx[i] = NULL;
+			}
+		}
+		kfree(hba->task_ctx);
+		hba->task_ctx = NULL;
+	}
+
+	kfree(hba->task_ctx_dma);
+	hba->task_ctx_dma = NULL;
+}
+
+static void bnx2fc_free_hash_table(struct bnx2fc_hba *hba)
+{
+	int i;
+	int segment_count;
+	int hash_table_size;
+	u32 *pbl;
+
+	segment_count = hba->hash_tbl_segment_count;
+	hash_table_size = BNX2FC_NUM_MAX_SESS * BNX2FC_MAX_ROWS_IN_HASH_TBL *
+		sizeof(struct fcoe_hash_table_entry);
+
+	pbl = hba->hash_tbl_pbl;
+	for (i = 0; i < segment_count; ++i) {
+		dma_addr_t dma_address;
+
+		dma_address = le32_to_cpu(*pbl);
+		++pbl;
+		dma_address += ((u64)le32_to_cpu(*pbl)) << 32;
+		++pbl;
+		dma_free_coherent(&hba->pcidev->dev,
+				  BNX2FC_HASH_TBL_CHUNK_SIZE,
+				  hba->hash_tbl_segments[i],
+				  dma_address);
+
+	}
+
+	if (hba->hash_tbl_pbl) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				    hba->hash_tbl_pbl,
+				    hba->hash_tbl_pbl_dma);
+		hba->hash_tbl_pbl = NULL;
+	}
+}
+
+static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba)
+{
+	int i;
+	int hash_table_size;
+	int segment_count;
+	int segment_array_size;
+	int dma_segment_array_size;
+	dma_addr_t *dma_segment_array;
+	u32 *pbl;
+
+	hash_table_size = BNX2FC_NUM_MAX_SESS * BNX2FC_MAX_ROWS_IN_HASH_TBL *
+		sizeof(struct fcoe_hash_table_entry);
+
+	segment_count = hash_table_size + BNX2FC_HASH_TBL_CHUNK_SIZE - 1;
+	segment_count /= BNX2FC_HASH_TBL_CHUNK_SIZE;
+	hba->hash_tbl_segment_count = segment_count;
+
+	segment_array_size = segment_count * sizeof(*hba->hash_tbl_segments);
+	hba->hash_tbl_segments = kzalloc(segment_array_size, GFP_KERNEL);
+	if (!hba->hash_tbl_segments) {
+		printk(KERN_ERR PFX "hash table pointers alloc failed\n");
+		return -ENOMEM;
+	}
+	dma_segment_array_size = segment_count * sizeof(*dma_segment_array);
+	dma_segment_array = kzalloc(dma_segment_array_size, GFP_KERNEL);
+	if (!dma_segment_array) {
+		printk(KERN_ERR PFX "hash table pointers (dma) alloc failed\n");
+		return -ENOMEM;
+	}
+
+	for (i = 0; i < segment_count; ++i) {
+		hba->hash_tbl_segments[i] =
+			dma_alloc_coherent(&hba->pcidev->dev,
+					   BNX2FC_HASH_TBL_CHUNK_SIZE,
+					   &dma_segment_array[i],
+					   GFP_KERNEL);
+		if (!hba->hash_tbl_segments[i]) {
+			printk(KERN_ERR PFX "hash segment alloc failed\n");
+			while (--i >= 0) {
+				dma_free_coherent(&hba->pcidev->dev,
+						    BNX2FC_HASH_TBL_CHUNK_SIZE,
+						    hba->hash_tbl_segments[i],
+						    dma_segment_array[i]);
+				hba->hash_tbl_segments[i] = NULL;
+			}
+			kfree(dma_segment_array);
+			return -ENOMEM;
+		}
+		memset(hba->hash_tbl_segments[i], 0,
+		       BNX2FC_HASH_TBL_CHUNK_SIZE);
+	}
+
+	hba->hash_tbl_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+					       PAGE_SIZE,
+					       &hba->hash_tbl_pbl_dma,
+					       GFP_KERNEL);
+	if (!hba->hash_tbl_pbl) {
+		printk(KERN_ERR PFX "hash table pbl alloc failed\n");
+		kfree(dma_segment_array);
+		return -ENOMEM;
+	}
+	memset(hba->hash_tbl_pbl, 0, PAGE_SIZE);
+
+	pbl = hba->hash_tbl_pbl;
+	for (i = 0; i < segment_count; ++i) {
+		u64 paddr = dma_segment_array[i];
+		*pbl = cpu_to_le32((u32) paddr);
+		++pbl;
+		*pbl = cpu_to_le32((u32) (paddr >> 32));
+		++pbl;
+	}
+	pbl = hba->hash_tbl_pbl;
+	i = 0;
+	while (*pbl && *(pbl + 1)) {
+		u32 lo;
+		u32 hi;
+		lo = *pbl;
+		++pbl;
+		hi = *pbl;
+		++pbl;
+		++i;
+	}
+	kfree(dma_segment_array);
+	return 0;
+}
+
+/**
+ * bnx2fc_setup_fw_resc - Allocate and map hash table and dummy buffer
+ *
+ * @hba:	Pointer to adapter structure
+ *
+ */
+int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
+{
+	u64 addr;
+	u32 mem_size;
+	int i;
+
+	if (bnx2fc_allocate_hash_table(hba))
+		return -ENOMEM;
+
+	mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
+	hba->t2_hash_tbl_ptr = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+						  &hba->t2_hash_tbl_ptr_dma,
+						  GFP_KERNEL);
+	if (!hba->t2_hash_tbl_ptr) {
+		printk(KERN_ERR PFX "unable to allocate t2 hash table ptr\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+	memset(hba->t2_hash_tbl_ptr, 0x00, mem_size);
+
+	mem_size = BNX2FC_NUM_MAX_SESS *
+				sizeof(struct fcoe_t2_hash_table_entry);
+	hba->t2_hash_tbl = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+					      &hba->t2_hash_tbl_dma,
+					      GFP_KERNEL);
+	if (!hba->t2_hash_tbl) {
+		printk(KERN_ERR PFX "unable to allocate t2 hash table\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+	memset(hba->t2_hash_tbl, 0x00, mem_size);
+	for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
+		addr = (unsigned long) hba->t2_hash_tbl_dma +
+			 ((i+1) * sizeof(struct fcoe_t2_hash_table_entry));
+		hba->t2_hash_tbl[i].next.lo = addr & 0xffffffff;
+		hba->t2_hash_tbl[i].next.hi = addr >> 32;
+	}
+
+	hba->dummy_buffer = dma_alloc_coherent(&hba->pcidev->dev,
+					       PAGE_SIZE, &hba->dummy_buf_dma,
+					       GFP_KERNEL);
+	if (!hba->dummy_buffer) {
+		printk(KERN_ERR PFX "unable to alloc MP Dummy Buffer\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+
+	hba->stats_buffer = dma_alloc_coherent(&hba->pcidev->dev,
+					       PAGE_SIZE,
+					       &hba->stats_buf_dma,
+					       GFP_KERNEL);
+	if (!hba->stats_buffer) {
+		printk(KERN_ERR PFX "unable to alloc Stats Buffer\n");
+		bnx2fc_free_fw_resc(hba);
+		return -ENOMEM;
+	}
+	memset(hba->stats_buffer, 0x00, PAGE_SIZE);
+
+	return 0;
+}
+
+void bnx2fc_free_fw_resc(struct bnx2fc_hba *hba)
+{
+	u32 mem_size;
+
+	if (hba->stats_buffer) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				  hba->stats_buffer, hba->stats_buf_dma);
+		hba->stats_buffer = NULL;
+	}
+
+	if (hba->dummy_buffer) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				  hba->dummy_buffer, hba->dummy_buf_dma);
+		hba->dummy_buffer = NULL;
+	}
+
+	if (hba->t2_hash_tbl_ptr) {
+		mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
+		dma_free_coherent(&hba->pcidev->dev, mem_size,
+				    hba->t2_hash_tbl_ptr,
+				    hba->t2_hash_tbl_ptr_dma);
+		hba->t2_hash_tbl_ptr = NULL;
+	}
+
+	if (hba->t2_hash_tbl) {
+		mem_size = BNX2FC_NUM_MAX_SESS *
+			    sizeof(struct fcoe_t2_hash_table_entry);
+		dma_free_coherent(&hba->pcidev->dev, mem_size,
+				    hba->t2_hash_tbl, hba->t2_hash_tbl_dma);
+		hba->t2_hash_tbl = NULL;
+	}
+	bnx2fc_free_hash_table(hba);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_io.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1856 @@
+/* bnx2fc_io.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * IO manager and SCSI IO processing.
+ *
+ * Copyright (c) 2008 - 2010 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.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+
+#define RESERVE_FREE_LIST_INDEX num_possible_cpus()
+
+static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
+			   int bd_index);
+static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req);
+static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req);
+static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
+			       struct bnx2fc_cmd *io_req);
+static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req);
+static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req);
+static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
+				 struct fcoe_fcp_rsp_payload *fcp_rsp,
+				 u8 num_rq);
+
+void bnx2fc_cmd_timer_set(struct bnx2fc_cmd *io_req,
+			  unsigned int timer_msec)
+{
+	struct bnx2fc_hba *hba = io_req->port->priv;
+
+	if (queue_delayed_work(hba->timer_work_queue, &io_req->timeout_work,
+				  msecs_to_jiffies(timer_msec)))
+		kref_get(&io_req->refcount);
+}
+
+static void bnx2fc_cmd_timeout(struct work_struct *work)
+{
+	struct bnx2fc_cmd *io_req = container_of(work, struct bnx2fc_cmd,
+						 timeout_work.work);
+	struct fc_lport *lport;
+	struct fc_rport_priv *rdata;
+	u8 cmd_type = io_req->cmd_type;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	int logo_issued;
+	int rc;
+
+	BNX2FC_IO_DBG(io_req, "cmd_timeout, cmd_type = %d,"
+		      "req_flags = %lx\n", cmd_type, io_req->req_flags);
+
+	spin_lock_bh(&tgt->tgt_lock);
+	if (test_and_clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags)) {
+		clear_bit(BNX2FC_FLAG_RETIRE_OXID, &io_req->req_flags);
+		/*
+		 * ideally we should hold the io_req until RRQ complets,
+		 * and release io_req from timeout hold.
+		 */
+		spin_unlock_bh(&tgt->tgt_lock);
+		bnx2fc_send_rrq(io_req);
+		return;
+	}
+	if (test_and_clear_bit(BNX2FC_FLAG_RETIRE_OXID, &io_req->req_flags)) {
+		BNX2FC_IO_DBG(io_req, "IO ready for reuse now\n");
+		goto done;
+	}
+
+	switch (cmd_type) {
+	case BNX2FC_SCSI_CMD:
+		if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+							&io_req->req_flags)) {
+			/* Handle eh_abort timeout */
+			BNX2FC_IO_DBG(io_req, "eh_abort timed out\n");
+			complete(&io_req->tm_done);
+		} else if (test_bit(BNX2FC_FLAG_ISSUE_ABTS,
+				    &io_req->req_flags)) {
+			/* Handle internally generated ABTS timeout */
+			BNX2FC_IO_DBG(io_req, "ABTS timed out refcnt = %d\n",
+					io_req->refcount.refcount.counter);
+			if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+					       &io_req->req_flags))) {
+
+				lport = io_req->port->lport;
+				rdata = io_req->tgt->rdata;
+				logo_issued = test_and_set_bit(
+						BNX2FC_FLAG_EXPL_LOGO,
+						&tgt->flags);
+				kref_put(&io_req->refcount, bnx2fc_cmd_release);
+				spin_unlock_bh(&tgt->tgt_lock);
+
+				/* Explicitly logo the target */
+				if (!logo_issued) {
+					BNX2FC_IO_DBG(io_req, "Explicit "
+						   "logo - tgt flags = 0x%lx\n",
+						   tgt->flags);
+
+					mutex_lock(&lport->disc.disc_mutex);
+					lport->tt.rport_logoff(rdata);
+					mutex_unlock(&lport->disc.disc_mutex);
+				}
+				return;
+			}
+		} else {
+			/* Hanlde IO timeout */
+			BNX2FC_IO_DBG(io_req, "IO timed out. issue ABTS\n");
+			if (test_and_set_bit(BNX2FC_FLAG_IO_COMPL,
+					     &io_req->req_flags)) {
+				BNX2FC_IO_DBG(io_req, "IO completed before "
+							   " timer expiry\n");
+				goto done;
+			}
+
+			if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+					      &io_req->req_flags)) {
+				rc = bnx2fc_initiate_abts(io_req);
+				if (rc == SUCCESS)
+					goto done;
+				/*
+				 * Explicitly logo the target if
+				 * abts initiation fails
+				 */
+				lport = io_req->port->lport;
+				rdata = io_req->tgt->rdata;
+				logo_issued = test_and_set_bit(
+						BNX2FC_FLAG_EXPL_LOGO,
+						&tgt->flags);
+				kref_put(&io_req->refcount, bnx2fc_cmd_release);
+				spin_unlock_bh(&tgt->tgt_lock);
+
+				if (!logo_issued) {
+					BNX2FC_IO_DBG(io_req, "Explicit "
+						   "logo - tgt flags = 0x%lx\n",
+						   tgt->flags);
+
+
+					mutex_lock(&lport->disc.disc_mutex);
+					lport->tt.rport_logoff(rdata);
+					mutex_unlock(&lport->disc.disc_mutex);
+				}
+				return;
+			} else {
+				BNX2FC_IO_DBG(io_req, "IO already in "
+						      "ABTS processing\n");
+			}
+		}
+		break;
+	case BNX2FC_ELS:
+
+		if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
+			BNX2FC_IO_DBG(io_req, "ABTS for ELS timed out\n");
+
+			if (!test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+					      &io_req->req_flags)) {
+				lport = io_req->port->lport;
+				rdata = io_req->tgt->rdata;
+				logo_issued = test_and_set_bit(
+						BNX2FC_FLAG_EXPL_LOGO,
+						&tgt->flags);
+				kref_put(&io_req->refcount, bnx2fc_cmd_release);
+				spin_unlock_bh(&tgt->tgt_lock);
+
+				/* Explicitly logo the target */
+				if (!logo_issued) {
+					BNX2FC_IO_DBG(io_req, "Explicitly logo"
+						   "(els)\n");
+					mutex_lock(&lport->disc.disc_mutex);
+					lport->tt.rport_logoff(rdata);
+					mutex_unlock(&lport->disc.disc_mutex);
+				}
+				return;
+			}
+		} else {
+			/*
+			 * Handle ELS timeout.
+			 * tgt_lock is used to sync compl path and timeout
+			 * path. If els compl path is processing this IO, we
+			 * have nothing to do here, just release the timer hold
+			 */
+			BNX2FC_IO_DBG(io_req, "ELS timed out\n");
+			if (test_and_set_bit(BNX2FC_FLAG_ELS_DONE,
+					       &io_req->req_flags))
+				goto done;
+
+			/* Indicate the cb_func that this ELS is timed out */
+			set_bit(BNX2FC_FLAG_ELS_TIMEOUT, &io_req->req_flags);
+
+			if ((io_req->cb_func) && (io_req->cb_arg)) {
+				io_req->cb_func(io_req->cb_arg);
+				io_req->cb_arg = NULL;
+			}
+		}
+		break;
+	default:
+		printk(KERN_ERR PFX "cmd_timeout: invalid cmd_type %d\n",
+			cmd_type);
+		break;
+	}
+
+done:
+	/* release the cmd that was held when timer was set */
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	spin_unlock_bh(&tgt->tgt_lock);
+}
+
+static void bnx2fc_scsi_done(struct bnx2fc_cmd *io_req, int err_code)
+{
+	/* Called with host lock held */
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+
+	/*
+	 * active_cmd_queue may have other command types as well,
+	 * and during flush operation,  we want to error back only
+	 * scsi commands.
+	 */
+	if (io_req->cmd_type != BNX2FC_SCSI_CMD)
+		return;
+
+	BNX2FC_IO_DBG(io_req, "scsi_done. err_code = 0x%x\n", err_code);
+	bnx2fc_unmap_sg_list(io_req);
+	io_req->sc_cmd = NULL;
+	if (!sc_cmd) {
+		printk(KERN_ERR PFX "scsi_done - sc_cmd NULL. "
+				    "IO(0x%x) already cleaned up\n",
+		       io_req->xid);
+		return;
+	}
+	sc_cmd->result = err_code << 16;
+
+	BNX2FC_IO_DBG(io_req, "sc=%p, result=0x%x, retries=%d, allowed=%d\n",
+		sc_cmd, host_byte(sc_cmd->result), sc_cmd->retries,
+		sc_cmd->allowed);
+	scsi_set_resid(sc_cmd, scsi_bufflen(sc_cmd));
+	sc_cmd->SCp.ptr = NULL;
+	sc_cmd->scsi_done(sc_cmd);
+}
+
+struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba,
+						u16 min_xid, u16 max_xid)
+{
+	struct bnx2fc_cmd_mgr *cmgr;
+	struct io_bdt *bdt_info;
+	struct bnx2fc_cmd *io_req;
+	size_t len;
+	u32 mem_size;
+	u16 xid;
+	int i;
+	int num_ios, num_pri_ios;
+	size_t bd_tbl_sz;
+	int arr_sz = num_possible_cpus() + 1;
+
+	if (max_xid <= min_xid || max_xid == FC_XID_UNKNOWN) {
+		printk(KERN_ERR PFX "cmd_mgr_alloc: Invalid min_xid 0x%x \
+					and max_xid 0x%x\n", min_xid, max_xid);
+		return NULL;
+	}
+	BNX2FC_MISC_DBG("min xid 0x%x, max xid 0x%x\n", min_xid, max_xid);
+
+	num_ios = max_xid - min_xid + 1;
+	len = (num_ios * (sizeof(struct bnx2fc_cmd *)));
+	len += sizeof(struct bnx2fc_cmd_mgr);
+
+	cmgr = kzalloc(len, GFP_KERNEL);
+	if (!cmgr) {
+		printk(KERN_ERR PFX "failed to alloc cmgr\n");
+		return NULL;
+	}
+
+	cmgr->free_list = kzalloc(sizeof(*cmgr->free_list) *
+				  arr_sz, GFP_KERNEL);
+	if (!cmgr->free_list) {
+		printk(KERN_ERR PFX "failed to alloc free_list\n");
+		goto mem_err;
+	}
+
+	cmgr->free_list_lock = kzalloc(sizeof(*cmgr->free_list_lock) *
+				       arr_sz, GFP_KERNEL);
+	if (!cmgr->free_list_lock) {
+		printk(KERN_ERR PFX "failed to alloc free_list_lock\n");
+		goto mem_err;
+	}
+
+	cmgr->hba = hba;
+	cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
+
+	for (i = 0; i < arr_sz; i++)  {
+		INIT_LIST_HEAD(&cmgr->free_list[i]);
+		spin_lock_init(&cmgr->free_list_lock[i]);
+	}
+
+	/*
+	 * Pre-allocated pool of bnx2fc_cmds.
+	 * Last entry in the free list array is the free list
+	 * of slow path requests.
+	 */
+	xid = BNX2FC_MIN_XID;
+	num_pri_ios = num_ios - BNX2FC_ELSTM_XIDS;
+	for (i = 0; i < num_ios; i++) {
+		io_req = kzalloc(sizeof(*io_req), GFP_KERNEL);
+
+		if (!io_req) {
+			printk(KERN_ERR PFX "failed to alloc io_req\n");
+			goto mem_err;
+		}
+
+		INIT_LIST_HEAD(&io_req->link);
+		INIT_DELAYED_WORK(&io_req->timeout_work, bnx2fc_cmd_timeout);
+
+		io_req->xid = xid++;
+		if (i < num_pri_ios)
+			list_add_tail(&io_req->link,
+				&cmgr->free_list[io_req->xid %
+						 num_possible_cpus()]);
+		else
+			list_add_tail(&io_req->link,
+				&cmgr->free_list[num_possible_cpus()]);
+		io_req++;
+	}
+
+	/* Allocate pool of io_bdts - one for each bnx2fc_cmd */
+	mem_size = num_ios * sizeof(struct io_bdt *);
+	cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL);
+	if (!cmgr->io_bdt_pool) {
+		printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n");
+		goto mem_err;
+	}
+
+	mem_size = sizeof(struct io_bdt);
+	for (i = 0; i < num_ios; i++) {
+		cmgr->io_bdt_pool[i] = kmalloc(mem_size, GFP_KERNEL);
+		if (!cmgr->io_bdt_pool[i]) {
+			printk(KERN_ERR PFX "failed to alloc "
+				"io_bdt_pool[%d]\n", i);
+			goto mem_err;
+		}
+	}
+
+	/* Allocate an map fcoe_bdt_ctx structures */
+	bd_tbl_sz = BNX2FC_MAX_BDS_PER_CMD * sizeof(struct fcoe_bd_ctx);
+	for (i = 0; i < num_ios; i++) {
+		bdt_info = cmgr->io_bdt_pool[i];
+		bdt_info->bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+						      bd_tbl_sz,
+						      &bdt_info->bd_tbl_dma,
+						      GFP_KERNEL);
+		if (!bdt_info->bd_tbl) {
+			printk(KERN_ERR PFX "failed to alloc "
+				"bdt_tbl[%d]\n", i);
+			goto mem_err;
+		}
+	}
+
+	return cmgr;
+
+mem_err:
+	bnx2fc_cmd_mgr_free(cmgr);
+	return NULL;
+}
+
+void bnx2fc_cmd_mgr_free(struct bnx2fc_cmd_mgr *cmgr)
+{
+	struct io_bdt *bdt_info;
+	struct bnx2fc_hba *hba = cmgr->hba;
+	size_t bd_tbl_sz;
+	u16 min_xid = BNX2FC_MIN_XID;
+	u16 max_xid = BNX2FC_MAX_XID;
+	int num_ios;
+	int i;
+
+	num_ios = max_xid - min_xid + 1;
+
+	/* Free fcoe_bdt_ctx structures */
+	if (!cmgr->io_bdt_pool)
+		goto free_cmd_pool;
+
+	bd_tbl_sz = BNX2FC_MAX_BDS_PER_CMD * sizeof(struct fcoe_bd_ctx);
+	for (i = 0; i < num_ios; i++) {
+		bdt_info = cmgr->io_bdt_pool[i];
+		if (bdt_info->bd_tbl) {
+			dma_free_coherent(&hba->pcidev->dev, bd_tbl_sz,
+					    bdt_info->bd_tbl,
+					    bdt_info->bd_tbl_dma);
+			bdt_info->bd_tbl = NULL;
+		}
+	}
+
+	/* Destroy io_bdt pool */
+	for (i = 0; i < num_ios; i++) {
+		kfree(cmgr->io_bdt_pool[i]);
+		cmgr->io_bdt_pool[i] = NULL;
+	}
+
+	kfree(cmgr->io_bdt_pool);
+	cmgr->io_bdt_pool = NULL;
+
+free_cmd_pool:
+	kfree(cmgr->free_list_lock);
+
+	/* Destroy cmd pool */
+	if (!cmgr->free_list)
+		goto free_cmgr;
+
+	for (i = 0; i < num_possible_cpus() + 1; i++)  {
+		struct list_head *list;
+		struct list_head *tmp;
+
+		list_for_each_safe(list, tmp, &cmgr->free_list[i]) {
+			struct bnx2fc_cmd *io_req = (struct bnx2fc_cmd *)list;
+			list_del(&io_req->link);
+			kfree(io_req);
+		}
+	}
+	kfree(cmgr->free_list);
+free_cmgr:
+	/* Free command manager itself */
+	kfree(cmgr);
+}
+
+struct bnx2fc_cmd *bnx2fc_elstm_alloc(struct bnx2fc_rport *tgt, int type)
+{
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+	struct bnx2fc_cmd *io_req;
+	struct list_head *listp;
+	struct io_bdt *bd_tbl;
+	int index = RESERVE_FREE_LIST_INDEX;
+	u32 max_sqes;
+	u16 xid;
+
+	max_sqes = tgt->max_sqes;
+	switch (type) {
+	case BNX2FC_TASK_MGMT_CMD:
+		max_sqes = BNX2FC_TM_MAX_SQES;
+		break;
+	case BNX2FC_ELS:
+		max_sqes = BNX2FC_ELS_MAX_SQES;
+		break;
+	default:
+		break;
+	}
+
+	/*
+	 * NOTE: Free list insertions and deletions are protected with
+	 * cmgr lock
+	 */
+	spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+	if ((list_empty(&(cmd_mgr->free_list[index]))) ||
+	    (tgt->num_active_ios.counter  >= max_sqes)) {
+		BNX2FC_TGT_DBG(tgt, "No free els_tm cmds available "
+			"ios(%d):sqes(%d)\n",
+			tgt->num_active_ios.counter, tgt->max_sqes);
+		if (list_empty(&(cmd_mgr->free_list[index])))
+			printk(KERN_ERR PFX "elstm_alloc: list_empty\n");
+		spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
+		return NULL;
+	}
+
+	listp = (struct list_head *)
+			cmd_mgr->free_list[index].next;
+	list_del_init(listp);
+	io_req = (struct bnx2fc_cmd *) listp;
+	xid = io_req->xid;
+	cmd_mgr->cmds[xid] = io_req;
+	atomic_inc(&tgt->num_active_ios);
+	spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
+
+	INIT_LIST_HEAD(&io_req->link);
+
+	io_req->port = port;
+	io_req->cmd_mgr = cmd_mgr;
+	io_req->req_flags = 0;
+	io_req->cmd_type = type;
+
+	/* Bind io_bdt for this io_req */
+	/* Have a static link between io_req and io_bdt_pool */
+	bd_tbl = io_req->bd_tbl = cmd_mgr->io_bdt_pool[xid];
+	bd_tbl->io_req = io_req;
+
+	/* Hold the io_req  against deletion */
+	kref_init(&io_req->refcount);
+	return io_req;
+}
+static struct bnx2fc_cmd *bnx2fc_cmd_alloc(struct bnx2fc_rport *tgt)
+{
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_cmd_mgr *cmd_mgr = hba->cmd_mgr;
+	struct bnx2fc_cmd *io_req;
+	struct list_head *listp;
+	struct io_bdt *bd_tbl;
+	u32 max_sqes;
+	u16 xid;
+	int index = get_cpu();
+
+	max_sqes = BNX2FC_SCSI_MAX_SQES;
+	/*
+	 * NOTE: Free list insertions and deletions are protected with
+	 * cmgr lock
+	 */
+	spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+	if ((list_empty(&cmd_mgr->free_list[index])) ||
+	    (tgt->num_active_ios.counter  >= max_sqes)) {
+		spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
+		put_cpu();
+		return NULL;
+	}
+
+	listp = (struct list_head *)
+		cmd_mgr->free_list[index].next;
+	list_del_init(listp);
+	io_req = (struct bnx2fc_cmd *) listp;
+	xid = io_req->xid;
+	cmd_mgr->cmds[xid] = io_req;
+	atomic_inc(&tgt->num_active_ios);
+	spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
+	put_cpu();
+
+	INIT_LIST_HEAD(&io_req->link);
+
+	io_req->port = port;
+	io_req->cmd_mgr = cmd_mgr;
+	io_req->req_flags = 0;
+
+	/* Bind io_bdt for this io_req */
+	/* Have a static link between io_req and io_bdt_pool */
+	bd_tbl = io_req->bd_tbl = cmd_mgr->io_bdt_pool[xid];
+	bd_tbl->io_req = io_req;
+
+	/* Hold the io_req  against deletion */
+	kref_init(&io_req->refcount);
+	return io_req;
+}
+
+void bnx2fc_cmd_release(struct kref *ref)
+{
+	struct bnx2fc_cmd *io_req = container_of(ref,
+						struct bnx2fc_cmd, refcount);
+	struct bnx2fc_cmd_mgr *cmd_mgr = io_req->cmd_mgr;
+	int index;
+
+	if (io_req->cmd_type == BNX2FC_SCSI_CMD)
+		index = io_req->xid % num_possible_cpus();
+	else
+		index = RESERVE_FREE_LIST_INDEX;
+
+
+	spin_lock_bh(&cmd_mgr->free_list_lock[index]);
+	if (io_req->cmd_type != BNX2FC_SCSI_CMD)
+		bnx2fc_free_mp_resc(io_req);
+	cmd_mgr->cmds[io_req->xid] = NULL;
+	/* Delete IO from retire queue */
+	list_del_init(&io_req->link);
+	/* Add it to the free list */
+	list_add(&io_req->link,
+			&cmd_mgr->free_list[index]);
+	atomic_dec(&io_req->tgt->num_active_ios);
+	spin_unlock_bh(&cmd_mgr->free_list_lock[index]);
+
+}
+
+static void bnx2fc_free_mp_resc(struct bnx2fc_cmd *io_req)
+{
+	struct bnx2fc_mp_req *mp_req = &(io_req->mp_req);
+	struct bnx2fc_hba *hba = io_req->port->priv;
+	size_t sz = sizeof(struct fcoe_bd_ctx);
+
+	/* clear tm flags */
+	mp_req->tm_flags = 0;
+	if (mp_req->mp_req_bd) {
+		dma_free_coherent(&hba->pcidev->dev, sz,
+				     mp_req->mp_req_bd,
+				     mp_req->mp_req_bd_dma);
+		mp_req->mp_req_bd = NULL;
+	}
+	if (mp_req->mp_resp_bd) {
+		dma_free_coherent(&hba->pcidev->dev, sz,
+				     mp_req->mp_resp_bd,
+				     mp_req->mp_resp_bd_dma);
+		mp_req->mp_resp_bd = NULL;
+	}
+	if (mp_req->req_buf) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				     mp_req->req_buf,
+				     mp_req->req_buf_dma);
+		mp_req->req_buf = NULL;
+	}
+	if (mp_req->resp_buf) {
+		dma_free_coherent(&hba->pcidev->dev, PAGE_SIZE,
+				     mp_req->resp_buf,
+				     mp_req->resp_buf_dma);
+		mp_req->resp_buf = NULL;
+	}
+}
+
+int bnx2fc_init_mp_req(struct bnx2fc_cmd *io_req)
+{
+	struct bnx2fc_mp_req *mp_req;
+	struct fcoe_bd_ctx *mp_req_bd;
+	struct fcoe_bd_ctx *mp_resp_bd;
+	struct bnx2fc_hba *hba = io_req->port->priv;
+	dma_addr_t addr;
+	size_t sz;
+
+	mp_req = (struct bnx2fc_mp_req *)&(io_req->mp_req);
+	memset(mp_req, 0, sizeof(struct bnx2fc_mp_req));
+
+	mp_req->req_len = sizeof(struct fcp_cmnd);
+	io_req->data_xfer_len = mp_req->req_len;
+	mp_req->req_buf = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+					     &mp_req->req_buf_dma,
+					     GFP_ATOMIC);
+	if (!mp_req->req_buf) {
+		printk(KERN_ERR PFX "unable to alloc MP req buffer\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+
+	mp_req->resp_buf = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+					      &mp_req->resp_buf_dma,
+					      GFP_ATOMIC);
+	if (!mp_req->resp_buf) {
+		printk(KERN_ERR PFX "unable to alloc TM resp buffer\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+	memset(mp_req->req_buf, 0, PAGE_SIZE);
+	memset(mp_req->resp_buf, 0, PAGE_SIZE);
+
+	/* Allocate and map mp_req_bd and mp_resp_bd */
+	sz = sizeof(struct fcoe_bd_ctx);
+	mp_req->mp_req_bd = dma_alloc_coherent(&hba->pcidev->dev, sz,
+						 &mp_req->mp_req_bd_dma,
+						 GFP_ATOMIC);
+	if (!mp_req->mp_req_bd) {
+		printk(KERN_ERR PFX "unable to alloc MP req bd\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+	mp_req->mp_resp_bd = dma_alloc_coherent(&hba->pcidev->dev, sz,
+						 &mp_req->mp_resp_bd_dma,
+						 GFP_ATOMIC);
+	if (!mp_req->mp_req_bd) {
+		printk(KERN_ERR PFX "unable to alloc MP resp bd\n");
+		bnx2fc_free_mp_resc(io_req);
+		return FAILED;
+	}
+	/* Fill bd table */
+	addr = mp_req->req_buf_dma;
+	mp_req_bd = mp_req->mp_req_bd;
+	mp_req_bd->buf_addr_lo = (u32)addr & 0xffffffff;
+	mp_req_bd->buf_addr_hi = (u32)((u64)addr >> 32);
+	mp_req_bd->buf_len = PAGE_SIZE;
+	mp_req_bd->flags = 0;
+
+	/*
+	 * MP buffer is either a task mgmt command or an ELS.
+	 * So the assumption is that it consumes a single bd
+	 * entry in the bd table
+	 */
+	mp_resp_bd = mp_req->mp_resp_bd;
+	addr = mp_req->resp_buf_dma;
+	mp_resp_bd->buf_addr_lo = (u32)addr & 0xffffffff;
+	mp_resp_bd->buf_addr_hi = (u32)((u64)addr >> 32);
+	mp_resp_bd->buf_len = PAGE_SIZE;
+	mp_resp_bd->flags = 0;
+
+	return SUCCESS;
+}
+
+static int bnx2fc_initiate_tmf(struct scsi_cmnd *sc_cmd, u8 tm_flags)
+{
+	struct fc_lport *lport;
+	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct fcoe_port *port;
+	struct bnx2fc_hba *hba;
+	struct bnx2fc_rport *tgt;
+	struct bnx2fc_cmd *io_req;
+	struct bnx2fc_mp_req *tm_req;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct Scsi_Host *host = sc_cmd->device->host;
+	struct fc_frame_header *fc_hdr;
+	struct fcp_cmnd *fcp_cmnd;
+	int task_idx, index;
+	int rc = SUCCESS;
+	u16 xid;
+	u32 sid, did;
+	unsigned long start = jiffies;
+
+	lport = shost_priv(host);
+	port = lport_priv(lport);
+	hba = port->priv;
+
+	if (rport == NULL) {
+		printk(KERN_ALERT PFX "device_reset: rport is NULL\n");
+		rc = FAILED;
+		goto tmf_err;
+	}
+
+	rc = fc_block_scsi_eh(sc_cmd);
+	if (rc)
+		return rc;
+
+	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+		printk(KERN_ERR PFX "device_reset: link is not ready\n");
+		rc = FAILED;
+		goto tmf_err;
+	}
+	/* rport and tgt are allocated together, so tgt should be non-NULL */
+	tgt = (struct bnx2fc_rport *)&rp[1];
+
+	if (!(test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags))) {
+		printk(KERN_ERR PFX "device_reset: tgt not offloaded\n");
+		rc = FAILED;
+		goto tmf_err;
+	}
+retry_tmf:
+	io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_TASK_MGMT_CMD);
+	if (!io_req) {
+		if (time_after(jiffies, start + HZ)) {
+			printk(KERN_ERR PFX "tmf: Failed TMF");
+			rc = FAILED;
+			goto tmf_err;
+		}
+		msleep(20);
+		goto retry_tmf;
+	}
+	/* Initialize rest of io_req fields */
+	io_req->sc_cmd = sc_cmd;
+	io_req->port = port;
+	io_req->tgt = tgt;
+
+	tm_req = (struct bnx2fc_mp_req *)&(io_req->mp_req);
+
+	rc = bnx2fc_init_mp_req(io_req);
+	if (rc == FAILED) {
+		printk(KERN_ERR PFX "Task mgmt MP request init failed\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		goto tmf_err;
+	}
+
+	/* Set TM flags */
+	io_req->io_req_flags = 0;
+	tm_req->tm_flags = tm_flags;
+
+	/* Fill FCP_CMND */
+	bnx2fc_build_fcp_cmnd(io_req, (struct fcp_cmnd *)tm_req->req_buf);
+	fcp_cmnd = (struct fcp_cmnd *)tm_req->req_buf;
+	memset(fcp_cmnd->fc_cdb, 0,  sc_cmd->cmd_len);
+	fcp_cmnd->fc_dl = 0;
+
+	/* Fill FC header */
+	fc_hdr = &(tm_req->req_fc_hdr);
+	sid = tgt->sid;
+	did = rport->port_id;
+	__fc_fill_fc_hdr(fc_hdr, FC_RCTL_DD_UNSOL_CMD, did, sid,
+			   FC_TYPE_FCP, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+			   FC_FC_SEQ_INIT, 0);
+	/* Obtain exchange id */
+	xid = io_req->xid;
+
+	BNX2FC_TGT_DBG(tgt, "Initiate TMF - xid = 0x%x\n", xid);
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_mp_task(io_req, task);
+
+	sc_cmd->SCp.ptr = (char *)io_req;
+
+	/* Obtain free SQ entry */
+	spin_lock_bh(&tgt->tgt_lock);
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Enqueue the io_req to active_tm_queue */
+	io_req->on_tmf_queue = 1;
+	list_add_tail(&io_req->link, &tgt->active_tm_queue);
+
+	init_completion(&io_req->tm_done);
+	io_req->wait_for_comp = 1;
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+	spin_unlock_bh(&tgt->tgt_lock);
+
+	rc = wait_for_completion_timeout(&io_req->tm_done,
+					 BNX2FC_TM_TIMEOUT * HZ);
+	spin_lock_bh(&tgt->tgt_lock);
+
+	io_req->wait_for_comp = 0;
+	if (!(test_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags)))
+		set_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags);
+
+	spin_unlock_bh(&tgt->tgt_lock);
+
+	if (!rc) {
+		printk(KERN_ERR PFX "task mgmt command failed...\n");
+		rc = FAILED;
+	} else {
+		printk(KERN_ERR PFX "task mgmt command success...\n");
+		rc = SUCCESS;
+	}
+tmf_err:
+	return rc;
+}
+
+int bnx2fc_initiate_abts(struct bnx2fc_cmd *io_req)
+{
+	struct fc_lport *lport;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct fc_rport *rport = tgt->rport;
+	struct fc_rport_priv *rdata = tgt->rdata;
+	struct bnx2fc_hba *hba;
+	struct fcoe_port *port;
+	struct bnx2fc_cmd *abts_io_req;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct fc_frame_header *fc_hdr;
+	struct bnx2fc_mp_req *abts_req;
+	int task_idx, index;
+	u32 sid, did;
+	u16 xid;
+	int rc = SUCCESS;
+	u32 r_a_tov = rdata->r_a_tov;
+
+	/* called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_abts\n");
+
+	port = io_req->port;
+	hba = port->priv;
+	lport = port->lport;
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		printk(KERN_ERR PFX "initiate_abts: tgt not offloaded\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	if (rport == NULL) {
+		printk(KERN_ALERT PFX "initiate_abts: rport is NULL\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	if (lport->state != LPORT_ST_READY || !(lport->link_up)) {
+		printk(KERN_ERR PFX "initiate_abts: link is not ready\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	abts_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_ABTS);
+	if (!abts_io_req) {
+		printk(KERN_ERR PFX "abts: couldnt allocate cmd\n");
+		rc = FAILED;
+		goto abts_err;
+	}
+
+	/* Initialize rest of io_req fields */
+	abts_io_req->sc_cmd = NULL;
+	abts_io_req->port = port;
+	abts_io_req->tgt = tgt;
+	abts_io_req->data_xfer_len = 0; /* No data transfer for ABTS */
+
+	abts_req = (struct bnx2fc_mp_req *)&(abts_io_req->mp_req);
+	memset(abts_req, 0, sizeof(struct bnx2fc_mp_req));
+
+	/* Fill FC header */
+	fc_hdr = &(abts_req->req_fc_hdr);
+
+	/* Obtain oxid and rxid for the original exchange to be aborted */
+	fc_hdr->fh_ox_id = htons(io_req->xid);
+	fc_hdr->fh_rx_id = htons(io_req->task->rx_wr_tx_rd.rx_id);
+
+	sid = tgt->sid;
+	did = rport->port_id;
+
+	__fc_fill_fc_hdr(fc_hdr, FC_RCTL_BA_ABTS, did, sid,
+			   FC_TYPE_BLS, FC_FC_FIRST_SEQ | FC_FC_END_SEQ |
+			   FC_FC_SEQ_INIT, 0);
+
+	xid = abts_io_req->xid;
+	BNX2FC_IO_DBG(abts_io_req, "ABTS io_req\n");
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_mp_task(abts_io_req, task);
+
+	/*
+	 * ABTS task is a temporary task that will be cleaned up
+	 * irrespective of ABTS response. We need to start the timer
+	 * for the original exchange, as the CQE is posted for the original
+	 * IO request.
+	 *
+	 * Timer for ABTS is started only when it is originated by a
+	 * TM request. For the ABTS issued as part of ULP timeout,
+	 * scsi-ml maintains the timers.
+	 */
+
+	/* if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags))*/
+	bnx2fc_cmd_timer_set(io_req, 2 * r_a_tov);
+
+	/* Obtain free SQ entry */
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+
+abts_err:
+	return rc;
+}
+
+int bnx2fc_initiate_cleanup(struct bnx2fc_cmd *io_req)
+{
+	struct fc_lport *lport;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct bnx2fc_hba *hba;
+	struct fcoe_port *port;
+	struct bnx2fc_cmd *cleanup_io_req;
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	int task_idx, index;
+	u16 xid, orig_xid;
+	int rc = 0;
+
+	/* ASSUMPTION: called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_initiate_cleanup\n");
+
+	port = io_req->port;
+	hba = port->priv;
+	lport = port->lport;
+
+	cleanup_io_req = bnx2fc_elstm_alloc(tgt, BNX2FC_CLEANUP);
+	if (!cleanup_io_req) {
+		printk(KERN_ERR PFX "cleanup: couldnt allocate cmd\n");
+		rc = -1;
+		goto cleanup_err;
+	}
+
+	/* Initialize rest of io_req fields */
+	cleanup_io_req->sc_cmd = NULL;
+	cleanup_io_req->port = port;
+	cleanup_io_req->tgt = tgt;
+	cleanup_io_req->data_xfer_len = 0; /* No data transfer for cleanup */
+
+	xid = cleanup_io_req->xid;
+
+	task_idx = xid/BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	orig_xid = io_req->xid;
+
+	BNX2FC_IO_DBG(io_req, "CLEANUP io_req xid = 0x%x\n", xid);
+
+	bnx2fc_init_cleanup_task(cleanup_io_req, task, orig_xid);
+
+	/* Obtain free SQ entry */
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+
+cleanup_err:
+	return rc;
+}
+
+/**
+ * bnx2fc_eh_target_reset: Reset a target
+ *
+ * @sc_cmd:	SCSI command
+ *
+ * Set from SCSI host template to send task mgmt command to the target
+ *	and wait for the response
+ */
+int bnx2fc_eh_target_reset(struct scsi_cmnd *sc_cmd)
+{
+	return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_TGT_RESET);
+}
+
+/**
+ * bnx2fc_eh_device_reset - Reset a single LUN
+ *
+ * @sc_cmd:	SCSI command
+ *
+ * Set from SCSI host template to send task mgmt command to the target
+ *	and wait for the response
+ */
+int bnx2fc_eh_device_reset(struct scsi_cmnd *sc_cmd)
+{
+	return bnx2fc_initiate_tmf(sc_cmd, FCP_TMF_LUN_RESET);
+}
+
+/**
+ * bnx2fc_eh_abort - eh_abort_handler api to abort an outstanding
+ *			SCSI command
+ *
+ * @sc_cmd:	SCSI_ML command pointer
+ *
+ * SCSI abort request handler
+ */
+int bnx2fc_eh_abort(struct scsi_cmnd *sc_cmd)
+{
+	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct bnx2fc_cmd *io_req;
+	struct fc_lport *lport;
+	struct bnx2fc_rport *tgt;
+	int rc = FAILED;
+
+
+	rc = fc_block_scsi_eh(sc_cmd);
+	if (rc)
+		return rc;
+
+	lport = shost_priv(sc_cmd->device->host);
+	if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
+		printk(KERN_ALERT PFX "eh_abort: link not ready\n");
+		return rc;
+	}
+
+	tgt = (struct bnx2fc_rport *)&rp[1];
+
+	BNX2FC_TGT_DBG(tgt, "Entered bnx2fc_eh_abort\n");
+
+	spin_lock_bh(&tgt->tgt_lock);
+	io_req = (struct bnx2fc_cmd *)sc_cmd->SCp.ptr;
+	if (!io_req) {
+		/* Command might have just completed */
+		printk(KERN_ERR PFX "eh_abort: io_req is NULL\n");
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+	BNX2FC_IO_DBG(io_req, "eh_abort - refcnt = %d\n",
+		      io_req->refcount.refcount.counter);
+
+	/* Hold IO request across abort processing */
+	kref_get(&io_req->refcount);
+
+	BUG_ON(tgt != io_req->tgt);
+
+	/* Remove the io_req from the active_q. */
+	/*
+	 * Task Mgmt functions (LUN RESET & TGT RESET) will not
+	 * issue an ABTS on this particular IO req, as the
+	 * io_req is no longer in the active_q.
+	 */
+	if (tgt->flush_in_prog) {
+		printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+			"flush in progress\n", io_req->xid);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+
+	if (io_req->on_active_queue == 0) {
+		printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+				"not on active_q\n", io_req->xid);
+		/*
+		 * This condition can happen only due to the FW bug,
+		 * where we do not receive cleanup response from
+		 * the FW. Handle this case gracefully by erroring
+		 * back the IO request to SCSI-ml
+		 */
+		bnx2fc_scsi_done(io_req, DID_ABORT);
+
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+
+	/*
+	 * Only eh_abort processing will remove the IO from
+	 * active_cmd_q before processing the request. this is
+	 * done to avoid race conditions between IOs aborted
+	 * as part of task management completion and eh_abort
+	 * processing
+	 */
+	list_del_init(&io_req->link);
+	io_req->on_active_queue = 0;
+	/* Move IO req to retire queue */
+	list_add_tail(&io_req->link, &tgt->io_retire_queue);
+
+	init_completion(&io_req->tm_done);
+	io_req->wait_for_comp = 1;
+
+	if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags)) {
+		/* Cancel the current timer running on this io_req */
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+		set_bit(BNX2FC_FLAG_EH_ABORT, &io_req->req_flags);
+		rc = bnx2fc_initiate_abts(io_req);
+	} else {
+		printk(KERN_ALERT PFX "eh_abort: io_req (xid = 0x%x) "
+				"already in abts processing\n", io_req->xid);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return SUCCESS;
+	}
+	if (rc == FAILED) {
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return rc;
+	}
+	spin_unlock_bh(&tgt->tgt_lock);
+
+	wait_for_completion(&io_req->tm_done);
+
+	spin_lock_bh(&tgt->tgt_lock);
+	io_req->wait_for_comp = 0;
+	if (!(test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+				    &io_req->req_flags))) {
+		/* Let the scsi-ml try to recover this command */
+		printk(KERN_ERR PFX "abort failed, xid = 0x%x\n",
+		       io_req->xid);
+		rc = FAILED;
+	} else {
+		/*
+		 * We come here even when there was a race condition
+		 * between timeout and abts completion, and abts
+		 * completion happens just in time.
+		 */
+		BNX2FC_IO_DBG(io_req, "abort succeeded\n");
+		rc = SUCCESS;
+		bnx2fc_scsi_done(io_req, DID_ABORT);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	}
+
+	/* release the reference taken in eh_abort */
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	spin_unlock_bh(&tgt->tgt_lock);
+	return rc;
+}
+
+void bnx2fc_process_cleanup_compl(struct bnx2fc_cmd *io_req,
+				  struct fcoe_task_ctx_entry *task,
+				  u8 num_rq)
+{
+	BNX2FC_IO_DBG(io_req, "Entered process_cleanup_compl "
+			      "refcnt = %d, cmd_type = %d\n",
+		   io_req->refcount.refcount.counter, io_req->cmd_type);
+	bnx2fc_scsi_done(io_req, DID_ERROR);
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+}
+
+void bnx2fc_process_abts_compl(struct bnx2fc_cmd *io_req,
+			       struct fcoe_task_ctx_entry *task,
+			       u8 num_rq)
+{
+	u32 r_ctl;
+	u32 r_a_tov = FC_DEF_R_A_TOV;
+	u8 issue_rrq = 0;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+
+	BNX2FC_IO_DBG(io_req, "Entered process_abts_compl xid = 0x%x"
+			      "refcnt = %d, cmd_type = %d\n",
+		   io_req->xid,
+		   io_req->refcount.refcount.counter, io_req->cmd_type);
+
+	if (test_and_set_bit(BNX2FC_FLAG_ABTS_DONE,
+				       &io_req->req_flags)) {
+		BNX2FC_IO_DBG(io_req, "Timer context finished processing"
+				" this io\n");
+		return;
+	}
+
+	/* Do not issue RRQ as this IO is already cleanedup */
+	if (test_and_set_bit(BNX2FC_FLAG_IO_CLEANUP,
+				&io_req->req_flags))
+		goto io_compl;
+
+	/*
+	 * For ABTS issued due to SCSI eh_abort_handler, timeout
+	 * values are maintained by scsi-ml itself. Cancel timeout
+	 * in case ABTS issued as part of task management function
+	 * or due to FW error.
+	 */
+	if (test_bit(BNX2FC_FLAG_ISSUE_ABTS, &io_req->req_flags))
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+
+	r_ctl = task->cmn.general.rsp_info.abts_rsp.r_ctl;
+
+	switch (r_ctl) {
+	case FC_RCTL_BA_ACC:
+		/*
+		 * Dont release this cmd yet. It will be relesed
+		 * after we get RRQ response
+		 */
+		BNX2FC_IO_DBG(io_req, "ABTS response - ACC Send RRQ\n");
+		issue_rrq = 1;
+		break;
+
+	case FC_RCTL_BA_RJT:
+		BNX2FC_IO_DBG(io_req, "ABTS response - RJT\n");
+		break;
+	default:
+		printk(KERN_ERR PFX "Unknown ABTS response\n");
+		break;
+	}
+
+	if (issue_rrq) {
+		BNX2FC_IO_DBG(io_req, "Issue RRQ after R_A_TOV\n");
+		set_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags);
+	}
+	set_bit(BNX2FC_FLAG_RETIRE_OXID, &io_req->req_flags);
+	bnx2fc_cmd_timer_set(io_req, r_a_tov);
+
+io_compl:
+	if (io_req->wait_for_comp) {
+		if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+				       &io_req->req_flags))
+			complete(&io_req->tm_done);
+	} else {
+		/*
+		 * We end up here when ABTS is issued as
+		 * in asynchronous context, i.e., as part
+		 * of task management completion, or
+		 * when FW error is received or when the
+		 * ABTS is issued when the IO is timed
+		 * out.
+		 */
+
+		if (io_req->on_active_queue) {
+			list_del_init(&io_req->link);
+			io_req->on_active_queue = 0;
+			/* Move IO req to retire queue */
+			list_add_tail(&io_req->link, &tgt->io_retire_queue);
+		}
+		bnx2fc_scsi_done(io_req, DID_ERROR);
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	}
+}
+
+static void bnx2fc_lun_reset_cmpl(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct list_head *list;
+	struct list_head *tmp;
+	struct bnx2fc_cmd *cmd;
+	int tm_lun = sc_cmd->device->lun;
+	int rc = 0;
+	int lun;
+
+	/* called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_lun_reset_cmpl\n");
+	/*
+	 * Walk thru the active_ios queue and ABORT the IO
+	 * that matches with the LUN that was reset
+	 */
+	list_for_each_safe(list, tmp, &tgt->active_cmd_queue) {
+		BNX2FC_TGT_DBG(tgt, "LUN RST cmpl: scan for pending IOs\n");
+		cmd = (struct bnx2fc_cmd *)list;
+		lun = cmd->sc_cmd->device->lun;
+		if (lun == tm_lun) {
+			/* Initiate ABTS on this cmd */
+			if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+					      &cmd->req_flags)) {
+				/* cancel the IO timeout */
+				if (cancel_delayed_work(&io_req->timeout_work))
+					kref_put(&io_req->refcount,
+						 bnx2fc_cmd_release);
+							/* timer hold */
+				rc = bnx2fc_initiate_abts(cmd);
+				/* abts shouldn't fail in this context */
+				WARN_ON(rc != SUCCESS);
+			} else
+				printk(KERN_ERR PFX "lun_rst: abts already in"
+					" progress for this IO 0x%x\n",
+					cmd->xid);
+		}
+	}
+}
+
+static void bnx2fc_tgt_reset_cmpl(struct bnx2fc_cmd *io_req)
+{
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct list_head *list;
+	struct list_head *tmp;
+	struct bnx2fc_cmd *cmd;
+	int rc = 0;
+
+	/* called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered bnx2fc_tgt_reset_cmpl\n");
+	/*
+	 * Walk thru the active_ios queue and ABORT the IO
+	 * that matches with the LUN that was reset
+	 */
+	list_for_each_safe(list, tmp, &tgt->active_cmd_queue) {
+		BNX2FC_TGT_DBG(tgt, "TGT RST cmpl: scan for pending IOs\n");
+		cmd = (struct bnx2fc_cmd *)list;
+		/* Initiate ABTS */
+		if (!test_and_set_bit(BNX2FC_FLAG_ISSUE_ABTS,
+							&cmd->req_flags)) {
+			/* cancel the IO timeout */
+			if (cancel_delayed_work(&io_req->timeout_work))
+				kref_put(&io_req->refcount,
+					 bnx2fc_cmd_release); /* timer hold */
+			rc = bnx2fc_initiate_abts(cmd);
+			/* abts shouldn't fail in this context */
+			WARN_ON(rc != SUCCESS);
+
+		} else
+			printk(KERN_ERR PFX "tgt_rst: abts already in progress"
+				" for this IO 0x%x\n", cmd->xid);
+	}
+}
+
+void bnx2fc_process_tm_compl(struct bnx2fc_cmd *io_req,
+			     struct fcoe_task_ctx_entry *task, u8 num_rq)
+{
+	struct bnx2fc_mp_req *tm_req;
+	struct fc_frame_header *fc_hdr;
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	u64 *hdr;
+	u64 *temp_hdr;
+	void *rsp_buf;
+
+	/* Called with tgt_lock held */
+	BNX2FC_IO_DBG(io_req, "Entered process_tm_compl\n");
+
+	if (!(test_bit(BNX2FC_FLAG_TM_TIMEOUT, &io_req->req_flags)))
+		set_bit(BNX2FC_FLAG_TM_COMPL, &io_req->req_flags);
+	else {
+		/* TM has already timed out and we got
+		 * delayed completion. Ignore completion
+		 * processing.
+		 */
+		return;
+	}
+
+	tm_req = &(io_req->mp_req);
+	fc_hdr = &(tm_req->resp_fc_hdr);
+	hdr = (u64 *)fc_hdr;
+	temp_hdr = (u64 *)
+		&task->cmn.general.cmd_info.mp_fc_frame.fc_hdr;
+	hdr[0] = cpu_to_be64(temp_hdr[0]);
+	hdr[1] = cpu_to_be64(temp_hdr[1]);
+	hdr[2] = cpu_to_be64(temp_hdr[2]);
+
+	tm_req->resp_len = task->rx_wr_only.sgl_ctx.mul_sges.cur_sge_off;
+
+	rsp_buf = tm_req->resp_buf;
+
+	if (fc_hdr->fh_r_ctl == FC_RCTL_DD_CMD_STATUS) {
+		bnx2fc_parse_fcp_rsp(io_req,
+				     (struct fcoe_fcp_rsp_payload *)
+				     rsp_buf, num_rq);
+		if (io_req->fcp_rsp_code == 0) {
+			/* TM successful */
+			if (tm_req->tm_flags & FCP_TMF_LUN_RESET)
+				bnx2fc_lun_reset_cmpl(io_req);
+			else if (tm_req->tm_flags & FCP_TMF_TGT_RESET)
+				bnx2fc_tgt_reset_cmpl(io_req);
+		}
+	} else {
+		printk(KERN_ERR PFX "tmf's fc_hdr r_ctl = 0x%x\n",
+			fc_hdr->fh_r_ctl);
+	}
+	if (!sc_cmd->SCp.ptr) {
+		printk(KERN_ALERT PFX "tm_compl: SCp.ptr is NULL\n");
+		return;
+	}
+	switch (io_req->fcp_status) {
+	case FC_GOOD:
+		if (io_req->cdb_status == 0) {
+			/* Good IO completion */
+			sc_cmd->result = DID_OK << 16;
+		} else {
+			/* Transport status is good, SCSI status not good */
+			sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+		}
+		if (io_req->fcp_resid)
+			scsi_set_resid(sc_cmd, io_req->fcp_resid);
+		break;
+
+	default:
+		BNX2FC_IO_DBG(io_req, "process_tm_compl: fcp_status = %d\n",
+			   io_req->fcp_status);
+		break;
+	}
+
+	sc_cmd = io_req->sc_cmd;
+	io_req->sc_cmd = NULL;
+
+	/* check if the io_req exists in tgt's tmf_q */
+	if (io_req->on_tmf_queue) {
+
+		list_del_init(&io_req->link);
+		io_req->on_tmf_queue = 0;
+	} else {
+
+		printk(KERN_ALERT PFX "Command not on active_cmd_queue!\n");
+		return;
+	}
+
+	sc_cmd->SCp.ptr = NULL;
+	sc_cmd->scsi_done(sc_cmd);
+
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+	if (io_req->wait_for_comp) {
+		BNX2FC_IO_DBG(io_req, "tm_compl - wake up the waiter\n");
+		complete(&io_req->tm_done);
+	}
+}
+
+static int bnx2fc_split_bd(struct bnx2fc_cmd *io_req, u64 addr, int sg_len,
+			   int bd_index)
+{
+	struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
+	int frag_size, sg_frags;
+
+	sg_frags = 0;
+	while (sg_len) {
+		if (sg_len >= BNX2FC_BD_SPLIT_SZ)
+			frag_size = BNX2FC_BD_SPLIT_SZ;
+		else
+			frag_size = sg_len;
+		bd[bd_index + sg_frags].buf_addr_lo = addr & 0xffffffff;
+		bd[bd_index + sg_frags].buf_addr_hi  = addr >> 32;
+		bd[bd_index + sg_frags].buf_len = (u16)frag_size;
+		bd[bd_index + sg_frags].flags = 0;
+
+		addr += (u64) frag_size;
+		sg_frags++;
+		sg_len -= frag_size;
+	}
+	return sg_frags;
+
+}
+
+static int bnx2fc_map_sg(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc = io_req->sc_cmd;
+	struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
+	struct scatterlist *sg;
+	int byte_count = 0;
+	int sg_count = 0;
+	int bd_count = 0;
+	int sg_frags;
+	unsigned int sg_len;
+	u64 addr;
+	int i;
+
+	sg_count = scsi_dma_map(sc);
+	scsi_for_each_sg(sc, sg, sg_count, i) {
+		sg_len = sg_dma_len(sg);
+		addr = sg_dma_address(sg);
+		if (sg_len > BNX2FC_MAX_BD_LEN) {
+			sg_frags = bnx2fc_split_bd(io_req, addr, sg_len,
+						   bd_count);
+		} else {
+
+			sg_frags = 1;
+			bd[bd_count].buf_addr_lo = addr & 0xffffffff;
+			bd[bd_count].buf_addr_hi  = addr >> 32;
+			bd[bd_count].buf_len = (u16)sg_len;
+			bd[bd_count].flags = 0;
+		}
+		bd_count += sg_frags;
+		byte_count += sg_len;
+	}
+	if (byte_count != scsi_bufflen(sc))
+		printk(KERN_ERR PFX "byte_count = %d != scsi_bufflen = %d, "
+			"task_id = 0x%x\n", byte_count, scsi_bufflen(sc),
+			io_req->xid);
+	return bd_count;
+}
+
+static void bnx2fc_build_bd_list_from_sg(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc = io_req->sc_cmd;
+	struct fcoe_bd_ctx *bd = io_req->bd_tbl->bd_tbl;
+	int bd_count;
+
+	if (scsi_sg_count(sc))
+		bd_count = bnx2fc_map_sg(io_req);
+	else {
+		bd_count = 0;
+		bd[0].buf_addr_lo = bd[0].buf_addr_hi = 0;
+		bd[0].buf_len = bd[0].flags = 0;
+	}
+	io_req->bd_tbl->bd_valid = bd_count;
+}
+
+static void bnx2fc_unmap_sg_list(struct bnx2fc_cmd *io_req)
+{
+	struct scsi_cmnd *sc = io_req->sc_cmd;
+
+	if (io_req->bd_tbl->bd_valid && sc) {
+		scsi_dma_unmap(sc);
+		io_req->bd_tbl->bd_valid = 0;
+	}
+}
+
+void bnx2fc_build_fcp_cmnd(struct bnx2fc_cmd *io_req,
+				  struct fcp_cmnd *fcp_cmnd)
+{
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	char tag[2];
+
+	memset(fcp_cmnd, 0, sizeof(struct fcp_cmnd));
+
+	int_to_scsilun(sc_cmd->device->lun,
+			(struct scsi_lun *) fcp_cmnd->fc_lun);
+
+
+	fcp_cmnd->fc_dl = htonl(io_req->data_xfer_len);
+	memcpy(fcp_cmnd->fc_cdb, sc_cmd->cmnd, sc_cmd->cmd_len);
+
+	fcp_cmnd->fc_cmdref = 0;
+	fcp_cmnd->fc_pri_ta = 0;
+	fcp_cmnd->fc_tm_flags = io_req->mp_req.tm_flags;
+	fcp_cmnd->fc_flags = io_req->io_req_flags;
+
+	if (scsi_populate_tag_msg(sc_cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			fcp_cmnd->fc_pri_ta = FCP_PTA_HEADQ;
+			break;
+		case ORDERED_QUEUE_TAG:
+			fcp_cmnd->fc_pri_ta = FCP_PTA_ORDERED;
+			break;
+		default:
+			fcp_cmnd->fc_pri_ta = FCP_PTA_SIMPLE;
+			break;
+		}
+	} else {
+		fcp_cmnd->fc_pri_ta = 0;
+	}
+}
+
+static void bnx2fc_parse_fcp_rsp(struct bnx2fc_cmd *io_req,
+				 struct fcoe_fcp_rsp_payload *fcp_rsp,
+				 u8 num_rq)
+{
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	u8 rsp_flags = fcp_rsp->fcp_flags.flags;
+	u32 rq_buff_len = 0;
+	int i;
+	unsigned char *rq_data;
+	unsigned char *dummy;
+	int fcp_sns_len = 0;
+	int fcp_rsp_len = 0;
+
+	io_req->fcp_status = FC_GOOD;
+	io_req->fcp_resid = fcp_rsp->fcp_resid;
+
+	io_req->scsi_comp_flags = rsp_flags;
+	CMD_SCSI_STATUS(sc_cmd) = io_req->cdb_status =
+				fcp_rsp->scsi_status_code;
+
+	/* Fetch fcp_rsp_info and fcp_sns_info if available */
+	if (num_rq) {
+
+		/*
+		 * We do not anticipate num_rq >1, as the linux defined
+		 * SCSI_SENSE_BUFFERSIZE is 96 bytes + 8 bytes of FCP_RSP_INFO
+		 * 256 bytes of single rq buffer is good enough to hold this.
+		 */
+
+		if (rsp_flags &
+		    FCOE_FCP_RSP_FLAGS_FCP_RSP_LEN_VALID) {
+			fcp_rsp_len = rq_buff_len
+					= fcp_rsp->fcp_rsp_len;
+		}
+
+		if (rsp_flags &
+		    FCOE_FCP_RSP_FLAGS_FCP_SNS_LEN_VALID) {
+			fcp_sns_len = fcp_rsp->fcp_sns_len;
+			rq_buff_len += fcp_rsp->fcp_sns_len;
+		}
+
+		io_req->fcp_rsp_len = fcp_rsp_len;
+		io_req->fcp_sns_len = fcp_sns_len;
+
+		if (rq_buff_len > num_rq * BNX2FC_RQ_BUF_SZ) {
+			/* Invalid sense sense length. */
+			printk(KERN_ALERT PFX "invalid sns length %d\n",
+				rq_buff_len);
+			/* reset rq_buff_len */
+			rq_buff_len =  num_rq * BNX2FC_RQ_BUF_SZ;
+		}
+
+		rq_data = bnx2fc_get_next_rqe(tgt, 1);
+
+		if (num_rq > 1) {
+			/* We do not need extra sense data */
+			for (i = 1; i < num_rq; i++)
+				dummy = bnx2fc_get_next_rqe(tgt, 1);
+		}
+
+		/* fetch fcp_rsp_code */
+		if ((fcp_rsp_len == 4) || (fcp_rsp_len == 8)) {
+			/* Only for task management function */
+			io_req->fcp_rsp_code = rq_data[3];
+			printk(KERN_ERR PFX "fcp_rsp_code = %d\n",
+				io_req->fcp_rsp_code);
+		}
+
+		/* fetch sense data */
+		rq_data += fcp_rsp_len;
+
+		if (fcp_sns_len > SCSI_SENSE_BUFFERSIZE) {
+			printk(KERN_ERR PFX "Truncating sense buffer\n");
+			fcp_sns_len = SCSI_SENSE_BUFFERSIZE;
+		}
+
+		memset(sc_cmd->sense_buffer, 0, sizeof(sc_cmd->sense_buffer));
+		if (fcp_sns_len)
+			memcpy(sc_cmd->sense_buffer, rq_data, fcp_sns_len);
+
+		/* return RQ entries */
+		for (i = 0; i < num_rq; i++)
+			bnx2fc_return_rqe(tgt, 1);
+	}
+}
+
+/**
+ * bnx2fc_queuecommand - Queuecommand function of the scsi template
+ *
+ * @host:	The Scsi_Host the command was issued to
+ * @sc_cmd:	struct scsi_cmnd to be executed
+ *
+ * This is the IO strategy routine, called by SCSI-ML
+ **/
+int bnx2fc_queuecommand(struct Scsi_Host *host,
+			struct scsi_cmnd *sc_cmd)
+{
+	struct fc_lport *lport = shost_priv(host);
+	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
+	struct fc_rport_libfc_priv *rp = rport->dd_data;
+	struct bnx2fc_rport *tgt;
+	struct bnx2fc_cmd *io_req;
+	int rc = 0;
+	int rval;
+
+	rval = fc_remote_port_chkready(rport);
+	if (rval) {
+		sc_cmd->result = rval;
+		sc_cmd->scsi_done(sc_cmd);
+		return 0;
+	}
+
+	if ((lport->state != LPORT_ST_READY) || !(lport->link_up)) {
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit_qcmd;
+	}
+
+	/* rport and tgt are allocated together, so tgt should be non-NULL */
+	tgt = (struct bnx2fc_rport *)&rp[1];
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		/*
+		 * Session is not offloaded yet. Let SCSI-ml retry
+		 * the command.
+		 */
+		rc = SCSI_MLQUEUE_TARGET_BUSY;
+		goto exit_qcmd;
+	}
+
+	io_req = bnx2fc_cmd_alloc(tgt);
+	if (!io_req) {
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit_qcmd;
+	}
+	io_req->sc_cmd = sc_cmd;
+
+	if (bnx2fc_post_io_req(tgt, io_req)) {
+		printk(KERN_ERR PFX "Unable to post io_req\n");
+		rc = SCSI_MLQUEUE_HOST_BUSY;
+		goto exit_qcmd;
+	}
+exit_qcmd:
+	return rc;
+}
+
+void bnx2fc_process_scsi_cmd_compl(struct bnx2fc_cmd *io_req,
+				   struct fcoe_task_ctx_entry *task,
+				   u8 num_rq)
+{
+	struct fcoe_fcp_rsp_payload *fcp_rsp;
+	struct bnx2fc_rport *tgt = io_req->tgt;
+	struct scsi_cmnd *sc_cmd;
+	struct Scsi_Host *host;
+
+
+	/* scsi_cmd_cmpl is called with tgt lock held */
+
+	if (test_and_set_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags)) {
+		/* we will not receive ABTS response for this IO */
+		BNX2FC_IO_DBG(io_req, "Timer context finished processing "
+			   "this scsi cmd\n");
+	}
+
+	/* Cancel the timeout_work, as we received IO completion */
+	if (cancel_delayed_work(&io_req->timeout_work))
+		kref_put(&io_req->refcount,
+			 bnx2fc_cmd_release); /* drop timer hold */
+
+	sc_cmd = io_req->sc_cmd;
+	if (sc_cmd == NULL) {
+		printk(KERN_ERR PFX "scsi_cmd_compl - sc_cmd is NULL\n");
+		return;
+	}
+
+	/* Fetch fcp_rsp from task context and perform cmd completion */
+	fcp_rsp = (struct fcoe_fcp_rsp_payload *)
+		   &(task->cmn.general.rsp_info.fcp_rsp.payload);
+
+	/* parse fcp_rsp and obtain sense data from RQ if available */
+	bnx2fc_parse_fcp_rsp(io_req, fcp_rsp, num_rq);
+
+	host = sc_cmd->device->host;
+	if (!sc_cmd->SCp.ptr) {
+		printk(KERN_ERR PFX "SCp.ptr is NULL\n");
+		return;
+	}
+	io_req->sc_cmd = NULL;
+
+	if (io_req->on_active_queue) {
+		list_del_init(&io_req->link);
+		io_req->on_active_queue = 0;
+		/* Move IO req to retire queue */
+		list_add_tail(&io_req->link, &tgt->io_retire_queue);
+	} else {
+		/* This should not happen, but could have been pulled
+		 * by bnx2fc_flush_active_ios(), or during a race
+		 * between command abort and (late) completion.
+		 */
+		BNX2FC_IO_DBG(io_req, "xid not on active_cmd_queue\n");
+		if (io_req->wait_for_comp)
+			if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+					       &io_req->req_flags))
+				complete(&io_req->tm_done);
+	}
+
+	bnx2fc_unmap_sg_list(io_req);
+
+	switch (io_req->fcp_status) {
+	case FC_GOOD:
+		if (io_req->cdb_status == 0) {
+			/* Good IO completion */
+			sc_cmd->result = DID_OK << 16;
+		} else {
+			/* Transport status is good, SCSI status not good */
+			BNX2FC_IO_DBG(io_req, "scsi_cmpl: cdb_status = %d"
+				 " fcp_resid = 0x%x\n",
+				io_req->cdb_status, io_req->fcp_resid);
+			sc_cmd->result = (DID_OK << 16) | io_req->cdb_status;
+		}
+		if (io_req->fcp_resid)
+			scsi_set_resid(sc_cmd, io_req->fcp_resid);
+		break;
+	default:
+		printk(KERN_ALERT PFX "scsi_cmd_compl: fcp_status = %d\n",
+			io_req->fcp_status);
+		break;
+	}
+	sc_cmd->SCp.ptr = NULL;
+	sc_cmd->scsi_done(sc_cmd);
+	kref_put(&io_req->refcount, bnx2fc_cmd_release);
+}
+
+static int bnx2fc_post_io_req(struct bnx2fc_rport *tgt,
+			       struct bnx2fc_cmd *io_req)
+{
+	struct fcoe_task_ctx_entry *task;
+	struct fcoe_task_ctx_entry *task_page;
+	struct scsi_cmnd *sc_cmd = io_req->sc_cmd;
+	struct fcoe_port *port = tgt->port;
+	struct bnx2fc_hba *hba = port->priv;
+	struct fc_lport *lport = port->lport;
+	struct fcoe_dev_stats *stats;
+	int task_idx, index;
+	u16 xid;
+
+	/* Initialize rest of io_req fields */
+	io_req->cmd_type = BNX2FC_SCSI_CMD;
+	io_req->port = port;
+	io_req->tgt = tgt;
+	io_req->data_xfer_len = scsi_bufflen(sc_cmd);
+	sc_cmd->SCp.ptr = (char *)io_req;
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	if (sc_cmd->sc_data_direction == DMA_FROM_DEVICE) {
+		io_req->io_req_flags = BNX2FC_READ;
+		stats->InputRequests++;
+		stats->InputBytes += io_req->data_xfer_len;
+	} else if (sc_cmd->sc_data_direction == DMA_TO_DEVICE) {
+		io_req->io_req_flags = BNX2FC_WRITE;
+		stats->OutputRequests++;
+		stats->OutputBytes += io_req->data_xfer_len;
+	} else {
+		io_req->io_req_flags = 0;
+		stats->ControlRequests++;
+	}
+	put_cpu();
+
+	xid = io_req->xid;
+
+	/* Build buffer descriptor list for firmware from sg list */
+	bnx2fc_build_bd_list_from_sg(io_req);
+
+	task_idx = xid / BNX2FC_TASKS_PER_PAGE;
+	index = xid % BNX2FC_TASKS_PER_PAGE;
+
+	/* Initialize task context for this IO request */
+	task_page = (struct fcoe_task_ctx_entry *) hba->task_ctx[task_idx];
+	task = &(task_page[index]);
+	bnx2fc_init_task(io_req, task);
+
+	spin_lock_bh(&tgt->tgt_lock);
+
+	if (tgt->flush_in_prog) {
+		printk(KERN_ERR PFX "Flush in progress..Host Busy\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return -EAGAIN;
+	}
+
+	if (!test_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags)) {
+		printk(KERN_ERR PFX "Session not ready...post_io\n");
+		kref_put(&io_req->refcount, bnx2fc_cmd_release);
+		spin_unlock_bh(&tgt->tgt_lock);
+		return -EAGAIN;
+	}
+
+	/* Time IO req */
+	bnx2fc_cmd_timer_set(io_req, BNX2FC_IO_TIMEOUT);
+	/* Obtain free SQ entry */
+	bnx2fc_add_2_sq(tgt, xid);
+
+	/* Enqueue the io_req to active_cmd_queue */
+
+	io_req->on_active_queue = 1;
+	/* move io_req from pending_queue to active_queue */
+	list_add_tail(&io_req->link, &tgt->active_cmd_queue);
+
+	/* Ring doorbell */
+	bnx2fc_ring_doorbell(tgt);
+	spin_unlock_bh(&tgt->tgt_lock);
+	return 0;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/bnx2fc_tgt.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,844 @@
+/* bnx2fc_tgt.c: Broadcom NetXtreme II Linux FCoE offload driver.
+ * Handles operations such as session offload/upload etc, and manages
+ * session resources such as connection id and qp resources.
+ *
+ * Copyright (c) 2008 - 2010 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.
+ *
+ * Written by: Bhanu Prakash Gollapudi (bprakash@broadcom.com)
+ */
+
+#include "bnx2fc.h"
+static void bnx2fc_upld_timer(unsigned long data);
+static void bnx2fc_ofld_timer(unsigned long data);
+static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
+			   struct fcoe_port *port,
+			   struct fc_rport_priv *rdata);
+static u32 bnx2fc_alloc_conn_id(struct bnx2fc_hba *hba,
+				struct bnx2fc_rport *tgt);
+static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
+			      struct bnx2fc_rport *tgt);
+static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
+			      struct bnx2fc_rport *tgt);
+static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id);
+
+static void bnx2fc_upld_timer(unsigned long data)
+{
+
+	struct bnx2fc_rport *tgt = (struct bnx2fc_rport *)data;
+
+	BNX2FC_TGT_DBG(tgt, "upld_timer - Upload compl not received!!\n");
+	/* fake upload completion */
+	clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+	set_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->upld_wait);
+}
+
+static void bnx2fc_ofld_timer(unsigned long data)
+{
+
+	struct bnx2fc_rport *tgt = (struct bnx2fc_rport *)data;
+
+	BNX2FC_TGT_DBG(tgt, "entered bnx2fc_ofld_timer\n");
+	/* NOTE: This function should never be called, as
+	 * offload should never timeout
+	 */
+	/*
+	 * If the timer has expired, this session is dead
+	 * Clear offloaded flag and logout of this device.
+	 * Since OFFLOADED flag is cleared, this case
+	 * will be considered as offload error and the
+	 * port will be logged off, and conn_id, session
+	 * resources are freed up in bnx2fc_offload_session
+	 */
+	clear_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags);
+	set_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	wake_up_interruptible(&tgt->ofld_wait);
+}
+
+static void bnx2fc_offload_session(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt,
+					struct fc_rport_priv *rdata)
+{
+	struct fc_lport *lport = rdata->local_port;
+	struct fc_rport *rport = rdata->rport;
+	struct bnx2fc_hba *hba = port->priv;
+	int rval;
+	int i = 0;
+
+	/* Initialize bnx2fc_rport */
+	/* NOTE: tgt is already bzero'd */
+	rval = bnx2fc_init_tgt(tgt, port, rdata);
+	if (rval) {
+		printk(KERN_ERR PFX "Failed to allocate conn id for "
+			"port_id (%6x)\n", rport->port_id);
+		goto ofld_err;
+	}
+
+	/* Allocate session resources */
+	rval = bnx2fc_alloc_session_resc(hba, tgt);
+	if (rval) {
+		printk(KERN_ERR PFX "Failed to allocate resources\n");
+		goto ofld_err;
+	}
+
+	/*
+	 * Initialize FCoE session offload process.
+	 * Upon completion of offload process add
+	 * rport to list of rports
+	 */
+retry_ofld:
+	clear_bit(BNX2FC_FLAG_OFLD_REQ_CMPL, &tgt->flags);
+	rval = bnx2fc_send_session_ofld_req(port, tgt);
+	if (rval) {
+		printk(KERN_ERR PFX "ofld_req failed\n");
+		goto ofld_err;
+	}
+
+	/*
+	 * wait for the session is offloaded and enabled. 3 Secs
+	 * should be ample time for this process to complete.
+	 */
+	setup_timer(&tgt->ofld_timer, bnx2fc_ofld_timer, (unsigned long)tgt);
+	mod_timer(&tgt->ofld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+	wait_event_interruptible(tgt->ofld_wait,
+				 (test_bit(
+				  BNX2FC_FLAG_OFLD_REQ_CMPL,
+				  &tgt->flags)));
+	if (signal_pending(current))
+		flush_signals(current);
+
+	del_timer_sync(&tgt->ofld_timer);
+
+	if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) {
+		if (test_and_clear_bit(BNX2FC_FLAG_CTX_ALLOC_FAILURE,
+				       &tgt->flags)) {
+			BNX2FC_TGT_DBG(tgt, "ctx_alloc_failure, "
+				"retry ofld..%d\n", i++);
+			msleep_interruptible(1000);
+			if (i > 3) {
+				i = 0;
+				goto ofld_err;
+			}
+			goto retry_ofld;
+		}
+		goto ofld_err;
+	}
+	if (bnx2fc_map_doorbell(tgt)) {
+		printk(KERN_ERR PFX "map doorbell failed - no mem\n");
+		/* upload will take care of cleaning up sess resc */
+		lport->tt.rport_logoff(rdata);
+	}
+	return;
+
+ofld_err:
+	/* couldn't offload the session. log off from this rport */
+	BNX2FC_TGT_DBG(tgt, "bnx2fc_offload_session - offload error\n");
+	lport->tt.rport_logoff(rdata);
+	/* Free session resources */
+	bnx2fc_free_session_resc(hba, tgt);
+	if (tgt->fcoe_conn_id != -1)
+		bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+}
+
+void bnx2fc_flush_active_ios(struct bnx2fc_rport *tgt)
+{
+	struct bnx2fc_cmd *io_req;
+	struct list_head *list;
+	struct list_head *tmp;
+	int rc;
+	int i = 0;
+	BNX2FC_TGT_DBG(tgt, "Entered flush_active_ios - %d\n",
+		       tgt->num_active_ios.counter);
+
+	spin_lock_bh(&tgt->tgt_lock);
+	tgt->flush_in_prog = 1;
+
+	list_for_each_safe(list, tmp, &tgt->active_cmd_queue) {
+		i++;
+		io_req = (struct bnx2fc_cmd *)list;
+		list_del_init(&io_req->link);
+		io_req->on_active_queue = 0;
+		BNX2FC_IO_DBG(io_req, "cmd_queue cleanup\n");
+
+		if (cancel_delayed_work(&io_req->timeout_work)) {
+			if (test_and_clear_bit(BNX2FC_FLAG_EH_ABORT,
+						&io_req->req_flags)) {
+				/* Handle eh_abort timeout */
+				BNX2FC_IO_DBG(io_req, "eh_abort for IO "
+					      "cleaned up\n");
+				complete(&io_req->tm_done);
+			}
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+		}
+
+		set_bit(BNX2FC_FLAG_IO_COMPL, &io_req->req_flags);
+		set_bit(BNX2FC_FLAG_IO_CLEANUP, &io_req->req_flags);
+		rc = bnx2fc_initiate_cleanup(io_req);
+		BUG_ON(rc);
+	}
+
+	list_for_each_safe(list, tmp, &tgt->els_queue) {
+		i++;
+		io_req = (struct bnx2fc_cmd *)list;
+		list_del_init(&io_req->link);
+		io_req->on_active_queue = 0;
+
+		BNX2FC_IO_DBG(io_req, "els_queue cleanup\n");
+
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount,
+				 bnx2fc_cmd_release); /* drop timer hold */
+
+		if ((io_req->cb_func) && (io_req->cb_arg)) {
+			io_req->cb_func(io_req->cb_arg);
+			io_req->cb_arg = NULL;
+		}
+
+		rc = bnx2fc_initiate_cleanup(io_req);
+		BUG_ON(rc);
+	}
+
+	list_for_each_safe(list, tmp, &tgt->io_retire_queue) {
+		i++;
+		io_req = (struct bnx2fc_cmd *)list;
+		list_del_init(&io_req->link);
+
+		BNX2FC_IO_DBG(io_req, "retire_queue flush\n");
+
+		if (cancel_delayed_work(&io_req->timeout_work))
+			kref_put(&io_req->refcount, bnx2fc_cmd_release);
+
+		clear_bit(BNX2FC_FLAG_ISSUE_RRQ, &io_req->req_flags);
+	}
+
+	BNX2FC_TGT_DBG(tgt, "IOs flushed = %d\n", i);
+	i = 0;
+	spin_unlock_bh(&tgt->tgt_lock);
+	/* wait for active_ios to go to 0 */
+	while ((tgt->num_active_ios.counter != 0) && (i++ < BNX2FC_WAIT_CNT))
+		msleep(25);
+	if (tgt->num_active_ios.counter != 0)
+		printk(KERN_ERR PFX "CLEANUP on port 0x%x:"
+				    " active_ios = %d\n",
+			tgt->rdata->ids.port_id, tgt->num_active_ios.counter);
+	spin_lock_bh(&tgt->tgt_lock);
+	tgt->flush_in_prog = 0;
+	spin_unlock_bh(&tgt->tgt_lock);
+}
+
+static void bnx2fc_upload_session(struct fcoe_port *port,
+					struct bnx2fc_rport *tgt)
+{
+	struct bnx2fc_hba *hba = port->priv;
+
+	BNX2FC_TGT_DBG(tgt, "upload_session: active_ios = %d\n",
+		tgt->num_active_ios.counter);
+
+	/*
+	 * Called with hba->hba_mutex held.
+	 * This is a blocking call
+	 */
+	clear_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+	bnx2fc_send_session_disable_req(port, tgt);
+
+	/*
+	 * wait for upload to complete. 3 Secs
+	 * should be sufficient time for this process to complete.
+	 */
+	setup_timer(&tgt->upld_timer, bnx2fc_upld_timer, (unsigned long)tgt);
+	mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+	BNX2FC_TGT_DBG(tgt, "waiting for disable compl\n");
+	wait_event_interruptible(tgt->upld_wait,
+				 (test_bit(
+				  BNX2FC_FLAG_UPLD_REQ_COMPL,
+				  &tgt->flags)));
+
+	if (signal_pending(current))
+		flush_signals(current);
+
+	del_timer_sync(&tgt->upld_timer);
+
+	/*
+	 * traverse thru the active_q and tmf_q and cleanup
+	 * IOs in these lists
+	 */
+	BNX2FC_TGT_DBG(tgt, "flush/upload - disable wait flags = 0x%lx\n",
+		       tgt->flags);
+	bnx2fc_flush_active_ios(tgt);
+
+	/* Issue destroy KWQE */
+	if (test_bit(BNX2FC_FLAG_DISABLED, &tgt->flags)) {
+		BNX2FC_TGT_DBG(tgt, "send destroy req\n");
+		clear_bit(BNX2FC_FLAG_UPLD_REQ_COMPL, &tgt->flags);
+		bnx2fc_send_session_destroy_req(hba, tgt);
+
+		/* wait for destroy to complete */
+		setup_timer(&tgt->upld_timer,
+			    bnx2fc_upld_timer, (unsigned long)tgt);
+		mod_timer(&tgt->upld_timer, jiffies + BNX2FC_FW_TIMEOUT);
+
+		wait_event_interruptible(tgt->upld_wait,
+					 (test_bit(
+					  BNX2FC_FLAG_UPLD_REQ_COMPL,
+					  &tgt->flags)));
+
+		if (!(test_bit(BNX2FC_FLAG_DESTROYED, &tgt->flags)))
+			printk(KERN_ERR PFX "ERROR!! destroy timed out\n");
+
+		BNX2FC_TGT_DBG(tgt, "destroy wait complete flags = 0x%lx\n",
+			tgt->flags);
+		if (signal_pending(current))
+			flush_signals(current);
+
+		del_timer_sync(&tgt->upld_timer);
+
+	} else
+		printk(KERN_ERR PFX "ERROR!! DISABLE req timed out, destroy"
+				" not sent to FW\n");
+
+	/* Free session resources */
+	bnx2fc_free_session_resc(hba, tgt);
+	bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+}
+
+static int bnx2fc_init_tgt(struct bnx2fc_rport *tgt,
+			   struct fcoe_port *port,
+			   struct fc_rport_priv *rdata)
+{
+
+	struct fc_rport *rport = rdata->rport;
+	struct bnx2fc_hba *hba = port->priv;
+
+	tgt->rport = rport;
+	tgt->rdata = rdata;
+	tgt->port = port;
+
+	if (hba->num_ofld_sess >= BNX2FC_NUM_MAX_SESS) {
+		BNX2FC_TGT_DBG(tgt, "exceeded max sessions. logoff this tgt\n");
+		tgt->fcoe_conn_id = -1;
+		return -1;
+	}
+
+	tgt->fcoe_conn_id = bnx2fc_alloc_conn_id(hba, tgt);
+	if (tgt->fcoe_conn_id == -1)
+		return -1;
+
+	BNX2FC_TGT_DBG(tgt, "init_tgt - conn_id = 0x%x\n", tgt->fcoe_conn_id);
+
+	tgt->max_sqes = BNX2FC_SQ_WQES_MAX;
+	tgt->max_rqes = BNX2FC_RQ_WQES_MAX;
+	tgt->max_cqes = BNX2FC_CQ_WQES_MAX;
+
+	/* Initialize the toggle bit */
+	tgt->sq_curr_toggle_bit = 1;
+	tgt->cq_curr_toggle_bit = 1;
+	tgt->sq_prod_idx = 0;
+	tgt->cq_cons_idx = 0;
+	tgt->rq_prod_idx = 0x8000;
+	tgt->rq_cons_idx = 0;
+	atomic_set(&tgt->num_active_ios, 0);
+
+	tgt->work_time_slice = 2;
+
+	spin_lock_init(&tgt->tgt_lock);
+	spin_lock_init(&tgt->cq_lock);
+
+	/* Initialize active_cmd_queue list */
+	INIT_LIST_HEAD(&tgt->active_cmd_queue);
+
+	/* Initialize IO retire queue */
+	INIT_LIST_HEAD(&tgt->io_retire_queue);
+
+	INIT_LIST_HEAD(&tgt->els_queue);
+
+	/* Initialize active_tm_queue list */
+	INIT_LIST_HEAD(&tgt->active_tm_queue);
+
+	init_waitqueue_head(&tgt->ofld_wait);
+	init_waitqueue_head(&tgt->upld_wait);
+
+	return 0;
+}
+
+/**
+ * This event_callback is called after successful completion of libfc
+ * initiated target login. bnx2fc can proceed with initiating the session
+ * establishment.
+ */
+void bnx2fc_rport_event_handler(struct fc_lport *lport,
+				struct fc_rport_priv *rdata,
+				enum fc_rport_event event)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	struct bnx2fc_hba *hba = port->priv;
+	struct fc_rport *rport = rdata->rport;
+	struct fc_rport_libfc_priv *rp;
+	struct bnx2fc_rport *tgt;
+	u32 port_id;
+
+	BNX2FC_HBA_DBG(lport, "rport_event_hdlr: event = %d, port_id = 0x%x\n",
+		event, rdata->ids.port_id);
+	switch (event) {
+	case RPORT_EV_READY:
+		if (!rport) {
+			printk(KERN_ALERT PFX "rport is NULL: ERROR!\n");
+			break;
+		}
+
+		rp = rport->dd_data;
+		if (rport->port_id == FC_FID_DIR_SERV) {
+			/*
+			 * bnx2fc_rport structure doesn't exist for
+			 * directory server.
+			 * We should not come here, as lport will
+			 * take care of fabric login
+			 */
+			printk(KERN_ALERT PFX "%x - rport_event_handler ERROR\n",
+				rdata->ids.port_id);
+			break;
+		}
+
+		if (rdata->spp_type != FC_TYPE_FCP) {
+			BNX2FC_HBA_DBG(lport, "not FCP type target."
+				   " not offloading\n");
+			break;
+		}
+		if (!(rdata->ids.roles & FC_RPORT_ROLE_FCP_TARGET)) {
+			BNX2FC_HBA_DBG(lport, "not FCP_TARGET"
+				   " not offloading\n");
+			break;
+		}
+
+		/*
+		 * Offlaod process is protected with hba mutex.
+		 * Use the same mutex_lock for upload process too
+		 */
+		mutex_lock(&hba->hba_mutex);
+		tgt = (struct bnx2fc_rport *)&rp[1];
+
+		/* This can happen when ADISC finds the same target */
+		if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) {
+			BNX2FC_TGT_DBG(tgt, "already offloaded\n");
+			mutex_unlock(&hba->hba_mutex);
+			return;
+		}
+
+		/*
+		 * Offload the session. This is a blocking call, and will
+		 * wait until the session is offloaded.
+		 */
+		bnx2fc_offload_session(port, tgt, rdata);
+
+		BNX2FC_TGT_DBG(tgt, "OFFLOAD num_ofld_sess = %d\n",
+			hba->num_ofld_sess);
+
+		if (test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags)) {
+			/*
+			 * Session is offloaded and enabled. Map
+			 * doorbell register for this target
+			 */
+			BNX2FC_TGT_DBG(tgt, "sess offloaded\n");
+			/* This counter is protected with hba mutex */
+			hba->num_ofld_sess++;
+
+			set_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
+		} else {
+			/*
+			 * Offload or enable would have failed.
+			 * In offload/enable completion path, the
+			 * rport would have already been removed
+			 */
+			BNX2FC_TGT_DBG(tgt, "Port is being logged off as "
+				   "offloaded flag not set\n");
+		}
+		mutex_unlock(&hba->hba_mutex);
+		break;
+	case RPORT_EV_LOGO:
+	case RPORT_EV_FAILED:
+	case RPORT_EV_STOP:
+		port_id = rdata->ids.port_id;
+		if (port_id == FC_FID_DIR_SERV)
+			break;
+
+		if (!rport) {
+			printk(KERN_ALERT PFX "%x - rport not created Yet!!\n",
+				port_id);
+			break;
+		}
+		rp = rport->dd_data;
+		mutex_lock(&hba->hba_mutex);
+		/*
+		 * Perform session upload. Note that rdata->peers is already
+		 * removed from disc->rports list before we get this event.
+		 */
+		tgt = (struct bnx2fc_rport *)&rp[1];
+
+		if (!(test_bit(BNX2FC_FLAG_OFFLOADED, &tgt->flags))) {
+			mutex_unlock(&hba->hba_mutex);
+			break;
+		}
+		clear_bit(BNX2FC_FLAG_SESSION_READY, &tgt->flags);
+
+		bnx2fc_upload_session(port, tgt);
+		hba->num_ofld_sess--;
+		BNX2FC_TGT_DBG(tgt, "UPLOAD num_ofld_sess = %d\n",
+			hba->num_ofld_sess);
+		/*
+		 * Try to wake up the linkdown wait thread. If num_ofld_sess
+		 * is 0, the waiting therad wakes up
+		 */
+		if ((hba->wait_for_link_down) &&
+		    (hba->num_ofld_sess == 0)) {
+			wake_up_interruptible(&hba->shutdown_wait);
+		}
+		if (test_bit(BNX2FC_FLAG_EXPL_LOGO, &tgt->flags)) {
+			printk(KERN_ERR PFX "Relogin to the tgt\n");
+			mutex_lock(&lport->disc.disc_mutex);
+			lport->tt.rport_login(rdata);
+			mutex_unlock(&lport->disc.disc_mutex);
+		}
+		mutex_unlock(&hba->hba_mutex);
+
+		break;
+
+	case RPORT_EV_NONE:
+		break;
+	}
+}
+
+/**
+ * bnx2fc_tgt_lookup() - Lookup a bnx2fc_rport by port_id
+ *
+ * @port:  fcoe_port struct to lookup the target port on
+ * @port_id: The remote port ID to look up
+ */
+struct bnx2fc_rport *bnx2fc_tgt_lookup(struct fcoe_port *port,
+					     u32 port_id)
+{
+	struct bnx2fc_hba *hba = port->priv;
+	struct bnx2fc_rport *tgt;
+	struct fc_rport_priv *rdata;
+	int i;
+
+	for (i = 0; i < BNX2FC_NUM_MAX_SESS; i++) {
+		tgt = hba->tgt_ofld_list[i];
+		if ((tgt) && (tgt->port == port)) {
+			rdata = tgt->rdata;
+			if (rdata->ids.port_id == port_id) {
+				if (rdata->rp_state != RPORT_ST_DELETE) {
+					BNX2FC_TGT_DBG(tgt, "rport "
+						"obtained\n");
+					return tgt;
+				} else {
+					printk(KERN_ERR PFX "rport 0x%x "
+						"is in DELETED state\n",
+						rdata->ids.port_id);
+					return NULL;
+				}
+			}
+		}
+	}
+	return NULL;
+}
+
+
+/**
+ * bnx2fc_alloc_conn_id - allocates FCOE Connection id
+ *
+ * @hba:	pointer to adapter structure
+ * @tgt:	pointer to bnx2fc_rport structure
+ */
+static u32 bnx2fc_alloc_conn_id(struct bnx2fc_hba *hba,
+				struct bnx2fc_rport *tgt)
+{
+	u32 conn_id, next;
+
+	/* called with hba mutex held */
+
+	/*
+	 * tgt_ofld_list access is synchronized using
+	 * both hba mutex and hba lock. Atleast hba mutex or
+	 * hba lock needs to be held for read access.
+	 */
+
+	spin_lock_bh(&hba->hba_lock);
+	next = hba->next_conn_id;
+	conn_id = hba->next_conn_id++;
+	if (hba->next_conn_id == BNX2FC_NUM_MAX_SESS)
+		hba->next_conn_id = 0;
+
+	while (hba->tgt_ofld_list[conn_id] != NULL) {
+		conn_id++;
+		if (conn_id == BNX2FC_NUM_MAX_SESS)
+			conn_id = 0;
+
+		if (conn_id == next) {
+			/* No free conn_ids are available */
+			spin_unlock_bh(&hba->hba_lock);
+			return -1;
+		}
+	}
+	hba->tgt_ofld_list[conn_id] = tgt;
+	tgt->fcoe_conn_id = conn_id;
+	spin_unlock_bh(&hba->hba_lock);
+	return conn_id;
+}
+
+static void bnx2fc_free_conn_id(struct bnx2fc_hba *hba, u32 conn_id)
+{
+	/* called with hba mutex held */
+	spin_lock_bh(&hba->hba_lock);
+	hba->tgt_ofld_list[conn_id] = NULL;
+	hba->next_conn_id = conn_id;
+	spin_unlock_bh(&hba->hba_lock);
+}
+
+/**
+ *bnx2fc_alloc_session_resc - Allocate qp resources for the session
+ *
+ */
+static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
+					struct bnx2fc_rport *tgt)
+{
+	dma_addr_t page;
+	int num_pages;
+	u32 *pbl;
+
+	/* Allocate and map SQ */
+	tgt->sq_mem_size = tgt->max_sqes * BNX2FC_SQ_WQE_SIZE;
+	tgt->sq_mem_size = (tgt->sq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+				     &tgt->sq_dma, GFP_KERNEL);
+	if (!tgt->sq) {
+		printk(KERN_ALERT PFX "unable to allocate SQ memory %d\n",
+			tgt->sq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->sq, 0, tgt->sq_mem_size);
+
+	/* Allocate and map CQ */
+	tgt->cq_mem_size = tgt->max_cqes * BNX2FC_CQ_WQE_SIZE;
+	tgt->cq_mem_size = (tgt->cq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+				     &tgt->cq_dma, GFP_KERNEL);
+	if (!tgt->cq) {
+		printk(KERN_ALERT PFX "unable to allocate CQ memory %d\n",
+			tgt->cq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->cq, 0, tgt->cq_mem_size);
+
+	/* Allocate and map RQ and RQ PBL */
+	tgt->rq_mem_size = tgt->max_rqes * BNX2FC_RQ_WQE_SIZE;
+	tgt->rq_mem_size = (tgt->rq_mem_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+					&tgt->rq_dma, GFP_KERNEL);
+	if (!tgt->rq) {
+		printk(KERN_ALERT PFX "unable to allocate RQ memory %d\n",
+			tgt->rq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->rq, 0, tgt->rq_mem_size);
+
+	tgt->rq_pbl_size = (tgt->rq_mem_size / PAGE_SIZE) * sizeof(void *);
+	tgt->rq_pbl_size = (tgt->rq_pbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+					 &tgt->rq_pbl_dma, GFP_KERNEL);
+	if (!tgt->rq_pbl) {
+		printk(KERN_ALERT PFX "unable to allocate RQ PBL %d\n",
+			tgt->rq_pbl_size);
+		goto mem_alloc_failure;
+	}
+
+	memset(tgt->rq_pbl, 0, tgt->rq_pbl_size);
+	num_pages = tgt->rq_mem_size / PAGE_SIZE;
+	page = tgt->rq_dma;
+	pbl = (u32 *)tgt->rq_pbl;
+
+	while (num_pages--) {
+		*pbl = (u32)page;
+		pbl++;
+		*pbl = (u32)((u64)page >> 32);
+		pbl++;
+		page += PAGE_SIZE;
+	}
+
+	/* Allocate and map XFERQ */
+	tgt->xferq_mem_size = tgt->max_sqes * BNX2FC_XFERQ_WQE_SIZE;
+	tgt->xferq_mem_size = (tgt->xferq_mem_size + (PAGE_SIZE - 1)) &
+			       PAGE_MASK;
+
+	tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
+					&tgt->xferq_dma, GFP_KERNEL);
+	if (!tgt->xferq) {
+		printk(KERN_ALERT PFX "unable to allocate XFERQ %d\n",
+			tgt->xferq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->xferq, 0, tgt->xferq_mem_size);
+
+	/* Allocate and map CONFQ & CONFQ PBL */
+	tgt->confq_mem_size = tgt->max_sqes * BNX2FC_CONFQ_WQE_SIZE;
+	tgt->confq_mem_size = (tgt->confq_mem_size + (PAGE_SIZE - 1)) &
+			       PAGE_MASK;
+
+	tgt->confq = dma_alloc_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
+					&tgt->confq_dma, GFP_KERNEL);
+	if (!tgt->confq) {
+		printk(KERN_ALERT PFX "unable to allocate CONFQ %d\n",
+			tgt->confq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->confq, 0, tgt->confq_mem_size);
+
+	tgt->confq_pbl_size =
+		(tgt->confq_mem_size / PAGE_SIZE) * sizeof(void *);
+	tgt->confq_pbl_size =
+		(tgt->confq_pbl_size + (PAGE_SIZE - 1)) & PAGE_MASK;
+
+	tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+					    tgt->confq_pbl_size,
+					    &tgt->confq_pbl_dma, GFP_KERNEL);
+	if (!tgt->confq_pbl) {
+		printk(KERN_ALERT PFX "unable to allocate CONFQ PBL %d\n",
+			tgt->confq_pbl_size);
+		goto mem_alloc_failure;
+	}
+
+	memset(tgt->confq_pbl, 0, tgt->confq_pbl_size);
+	num_pages = tgt->confq_mem_size / PAGE_SIZE;
+	page = tgt->confq_dma;
+	pbl = (u32 *)tgt->confq_pbl;
+
+	while (num_pages--) {
+		*pbl = (u32)page;
+		pbl++;
+		*pbl = (u32)((u64)page >> 32);
+		pbl++;
+		page += PAGE_SIZE;
+	}
+
+	/* Allocate and map ConnDB */
+	tgt->conn_db_mem_size = sizeof(struct fcoe_conn_db);
+
+	tgt->conn_db = dma_alloc_coherent(&hba->pcidev->dev,
+					  tgt->conn_db_mem_size,
+					  &tgt->conn_db_dma, GFP_KERNEL);
+	if (!tgt->conn_db) {
+		printk(KERN_ALERT PFX "unable to allocate conn_db %d\n",
+						tgt->conn_db_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->conn_db, 0, tgt->conn_db_mem_size);
+
+
+	/* Allocate and map LCQ */
+	tgt->lcq_mem_size = (tgt->max_sqes + 8) * BNX2FC_SQ_WQE_SIZE;
+	tgt->lcq_mem_size = (tgt->lcq_mem_size + (PAGE_SIZE - 1)) &
+			     PAGE_MASK;
+
+	tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+				      &tgt->lcq_dma, GFP_KERNEL);
+
+	if (!tgt->lcq) {
+		printk(KERN_ALERT PFX "unable to allocate lcq %d\n",
+		       tgt->lcq_mem_size);
+		goto mem_alloc_failure;
+	}
+	memset(tgt->lcq, 0, tgt->lcq_mem_size);
+
+	/* Arm CQ */
+	tgt->conn_db->cq_arm.lo = -1;
+	tgt->conn_db->rq_prod = 0x8000;
+
+	return 0;
+
+mem_alloc_failure:
+	bnx2fc_free_session_resc(hba, tgt);
+	bnx2fc_free_conn_id(hba, tgt->fcoe_conn_id);
+	return -ENOMEM;
+}
+
+/**
+ * bnx2i_free_session_resc - free qp resources for the session
+ *
+ * @hba:	adapter structure pointer
+ * @tgt:	bnx2fc_rport structure pointer
+ *
+ * Free QP resources - SQ/RQ/CQ/XFERQ memory and PBL
+ */
+static void bnx2fc_free_session_resc(struct bnx2fc_hba *hba,
+						struct bnx2fc_rport *tgt)
+{
+	BNX2FC_TGT_DBG(tgt, "Freeing up session resources\n");
+
+	if (tgt->ctx_base) {
+		iounmap(tgt->ctx_base);
+		tgt->ctx_base = NULL;
+	}
+	/* Free LCQ */
+	if (tgt->lcq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+				    tgt->lcq, tgt->lcq_dma);
+		tgt->lcq = NULL;
+	}
+	/* Free connDB */
+	if (tgt->conn_db) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->conn_db_mem_size,
+				    tgt->conn_db, tgt->conn_db_dma);
+		tgt->conn_db = NULL;
+	}
+	/* Free confq  and confq pbl */
+	if (tgt->confq_pbl) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->confq_pbl_size,
+				    tgt->confq_pbl, tgt->confq_pbl_dma);
+		tgt->confq_pbl = NULL;
+	}
+	if (tgt->confq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->confq_mem_size,
+				    tgt->confq, tgt->confq_dma);
+		tgt->confq = NULL;
+	}
+	/* Free XFERQ */
+	if (tgt->xferq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->xferq_mem_size,
+				    tgt->xferq, tgt->xferq_dma);
+		tgt->xferq = NULL;
+	}
+	/* Free RQ PBL and RQ */
+	if (tgt->rq_pbl) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+				    tgt->rq_pbl, tgt->rq_pbl_dma);
+		tgt->rq_pbl = NULL;
+	}
+	if (tgt->rq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+				    tgt->rq, tgt->rq_dma);
+		tgt->rq = NULL;
+	}
+	/* Free CQ */
+	spin_lock_bh(&tgt->cq_lock);
+	if (tgt->cq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+				    tgt->cq, tgt->cq_dma);
+		tgt->cq = NULL;
+	}
+	spin_unlock_bh(&tgt->cq_lock);
+	/* Free SQ */
+	if (tgt->sq) {
+		dma_free_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+				    tgt->sq, tgt->sq_dma);
+		tgt->sq = NULL;
+	}
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/Kconfig linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/Kconfig
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,11 @@
+config SCSI_BNX2X_FCOE
+	tristate "Broadcom NetXtreme II FCoE support"
+	depends on PCI
+	select NETDEVICES
+	select NETDEV_1000
+	select LIBFC
+	select LIBFCOE
+	select CNIC
+	---help---
+	This driver supports FCoE offload for the Broadcom NetXtreme II
+	devices.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/Makefile linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2fc/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2fc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3 @@
+obj-$(CONFIG_SCSI_BNX2X_FCOE) += bnx2fc.o
+
+bnx2fc-y := bnx2fc_els.o bnx2fc_fcoe.o bnx2fc_hwi.o bnx2fc_io.o bnx2fc_tgt.o
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i.h linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i.h
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i.h	2011-05-19 00:06:34.000000000 -0400
@@ -360,7 +360,7 @@
 		#define ADAPTER_STATE_LINK_DOWN		2
 		#define ADAPTER_STATE_INIT_FAILED	31
 	unsigned int mtu_supported;
-		#define BNX2I_MAX_MTU_SUPPORTED		1500
+		#define BNX2I_MAX_MTU_SUPPORTED		9000
 
 	struct Scsi_Host *shost;
 
@@ -751,6 +751,8 @@
 				  struct iscsi_task *mtask);
 extern int bnx2i_send_iscsi_tmf(struct bnx2i_conn *conn,
 				  struct iscsi_task *mtask);
+extern int bnx2i_send_iscsi_text(struct bnx2i_conn *conn,
+				 struct iscsi_task *mtask);
 extern int bnx2i_send_iscsi_scsicmd(struct bnx2i_conn *conn,
 				    struct bnx2i_cmd *cmnd);
 extern int bnx2i_send_iscsi_nopout(struct bnx2i_conn *conn,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i_hwi.c	2011-05-19 00:06:34.000000000 -0400
@@ -173,7 +173,7 @@
 
 /**
  * bnx2i_get_rq_buf - copy RQ buffer contents to driver buffer
- * @conn:		iscsi connection on which RQ event occured
+ * @conn:		iscsi connection on which RQ event occurred
  * @ptr:		driver buffer to which RQ buffer contents is to
  *			be copied
  * @len:		length of valid data inside RQ buf
@@ -445,6 +445,56 @@
 }
 
 /**
+ * bnx2i_send_iscsi_text - post iSCSI text WQE to hardware
+ * @conn:	iscsi connection
+ * @mtask:	driver command structure which is requesting
+ *		a WQE to sent to chip for further processing
+ *
+ * prepare and post an iSCSI Text request WQE to CNIC firmware
+ */
+int bnx2i_send_iscsi_text(struct bnx2i_conn *bnx2i_conn,
+			  struct iscsi_task *mtask)
+{
+	struct bnx2i_cmd *bnx2i_cmd;
+	struct bnx2i_text_request *text_wqe;
+	struct iscsi_text *text_hdr;
+	u32 dword;
+
+	bnx2i_cmd = (struct bnx2i_cmd *)mtask->dd_data;
+	text_hdr = (struct iscsi_text *)mtask->hdr;
+	text_wqe = (struct bnx2i_text_request *) bnx2i_conn->ep->qp.sq_prod_qe;
+
+	memset(text_wqe, 0, sizeof(struct bnx2i_text_request));
+
+	text_wqe->op_code = text_hdr->opcode;
+	text_wqe->op_attr = text_hdr->flags;
+	text_wqe->data_length = ntoh24(text_hdr->dlength);
+	text_wqe->itt = mtask->itt |
+		(ISCSI_TASK_TYPE_MPATH << ISCSI_TEXT_REQUEST_TYPE_SHIFT);
+	text_wqe->ttt = be32_to_cpu(text_hdr->ttt);
+
+	text_wqe->cmd_sn = be32_to_cpu(text_hdr->cmdsn);
+
+	text_wqe->resp_bd_list_addr_lo = (u32) bnx2i_conn->gen_pdu.resp_bd_dma;
+	text_wqe->resp_bd_list_addr_hi =
+			(u32) ((u64) bnx2i_conn->gen_pdu.resp_bd_dma >> 32);
+
+	dword = ((1 << ISCSI_TEXT_REQUEST_NUM_RESP_BDS_SHIFT) |
+		 (bnx2i_conn->gen_pdu.resp_buf_size <<
+		  ISCSI_TEXT_REQUEST_RESP_BUFFER_LENGTH_SHIFT));
+	text_wqe->resp_buffer = dword;
+	text_wqe->bd_list_addr_lo = (u32) bnx2i_conn->gen_pdu.req_bd_dma;
+	text_wqe->bd_list_addr_hi =
+			(u32) ((u64) bnx2i_conn->gen_pdu.req_bd_dma >> 32);
+	text_wqe->num_bds = 1;
+	text_wqe->cq_index = 0; /* CQ# used for completion, 5771x only */
+
+	bnx2i_ring_dbell_update_sq_params(bnx2i_conn, 1);
+	return 0;
+}
+
+
+/**
  * bnx2i_send_iscsi_scsicmd - post iSCSI scsicmd request WQE to hardware
  * @conn:	iscsi connection
  * @cmd:	driver command structure which is requesting
@@ -490,15 +540,18 @@
 	bnx2i_cmd = (struct bnx2i_cmd *)task->dd_data;
 	nopout_hdr = (struct iscsi_nopout *)task->hdr;
 	nopout_wqe = (struct bnx2i_nop_out_request *)ep->qp.sq_prod_qe;
+
+	memset(nopout_wqe, 0x00, sizeof(struct bnx2i_nop_out_request));
+
 	nopout_wqe->op_code = nopout_hdr->opcode;
 	nopout_wqe->op_attr = ISCSI_FLAG_CMD_FINAL;
 	memcpy(nopout_wqe->lun, nopout_hdr->lun, 8);
 
 	if (test_bit(BNX2I_NX2_DEV_57710, &ep->hba->cnic_dev_type)) {
-		u32 tmp = nopout_hdr->lun[0];
+		u32 tmp = nopout_wqe->lun[0];
 		/* 57710 requires LUN field to be swapped */
-		nopout_hdr->lun[0] = nopout_hdr->lun[1];
-		nopout_hdr->lun[1] = tmp;
+		nopout_wqe->lun[0] = nopout_wqe->lun[1];
+		nopout_wqe->lun[1] = tmp;
 	}
 
 	nopout_wqe->itt = ((u16)task->itt |
@@ -1425,6 +1478,68 @@
 	return 0;
 }
 
+
+/**
+ * bnx2i_process_text_resp - this function handles iscsi text response
+ * @session:	iscsi session pointer
+ * @bnx2i_conn:	iscsi connection pointer
+ * @cqe:	pointer to newly DMA'ed CQE entry for processing
+ *
+ * process iSCSI Text Response CQE&  complete it to open-iscsi user daemon
+ */
+static int bnx2i_process_text_resp(struct iscsi_session *session,
+				   struct bnx2i_conn *bnx2i_conn,
+				   struct cqe *cqe)
+{
+	struct iscsi_conn *conn = bnx2i_conn->cls_conn->dd_data;
+	struct iscsi_task *task;
+	struct bnx2i_text_response *text;
+	struct iscsi_text_rsp *resp_hdr;
+	int pld_len;
+	int pad_len;
+
+	text = (struct bnx2i_text_response *) cqe;
+	spin_lock(&session->lock);
+	task = iscsi_itt_to_task(conn, text->itt & ISCSI_LOGIN_RESPONSE_INDEX);
+	if (!task)
+		goto done;
+
+	resp_hdr = (struct iscsi_text_rsp *)&bnx2i_conn->gen_pdu.resp_hdr;
+	memset(resp_hdr, 0, sizeof(struct iscsi_hdr));
+	resp_hdr->opcode = text->op_code;
+	resp_hdr->flags = text->response_flags;
+	resp_hdr->hlength = 0;
+
+	hton24(resp_hdr->dlength, text->data_length);
+	resp_hdr->itt = task->hdr->itt;
+	resp_hdr->ttt = cpu_to_be32(text->ttt);
+	resp_hdr->statsn = task->hdr->exp_statsn;
+	resp_hdr->exp_cmdsn = cpu_to_be32(text->exp_cmd_sn);
+	resp_hdr->max_cmdsn = cpu_to_be32(text->max_cmd_sn);
+	pld_len = text->data_length;
+	bnx2i_conn->gen_pdu.resp_wr_ptr = bnx2i_conn->gen_pdu.resp_buf +
+					  pld_len;
+	pad_len = 0;
+	if (pld_len & 0x3)
+		pad_len = 4 - (pld_len % 4);
+
+	if (pad_len) {
+		int i = 0;
+		for (i = 0; i < pad_len; i++) {
+			bnx2i_conn->gen_pdu.resp_wr_ptr[0] = 0;
+			bnx2i_conn->gen_pdu.resp_wr_ptr++;
+		}
+	}
+	__iscsi_complete_pdu(conn, (struct iscsi_hdr *)resp_hdr,
+			     bnx2i_conn->gen_pdu.resp_buf,
+			     bnx2i_conn->gen_pdu.resp_wr_ptr -
+			     bnx2i_conn->gen_pdu.resp_buf);
+done:
+	spin_unlock(&session->lock);
+	return 0;
+}
+
+
 /**
  * bnx2i_process_tmf_resp - this function handles iscsi TMF response
  * @session:		iscsi session pointer
@@ -1766,6 +1881,10 @@
 			bnx2i_process_tmf_resp(session, bnx2i_conn,
 					       qp->cq_cons_qe);
 			break;
+		case ISCSI_OP_TEXT_RSP:
+			bnx2i_process_text_resp(session, bnx2i_conn,
+						qp->cq_cons_qe);
+			break;
 		case ISCSI_OP_LOGOUT_RSP:
 			bnx2i_process_logout_resp(session, bnx2i_conn,
 						  qp->cq_cons_qe);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_init.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,8 +18,8 @@
 static u32 adapter_count;
 
 #define DRV_MODULE_NAME		"bnx2i"
-#define DRV_MODULE_VERSION	"2.6.2.2"
-#define DRV_MODULE_RELDATE	"Nov 23, 2010"
+#define DRV_MODULE_VERSION	"2.6.2.3"
+#define DRV_MODULE_RELDATE	"Dec 31, 2010"
 
 static char version[] __devinitdata =
 		"Broadcom NetXtreme II iSCSI Driver " DRV_MODULE_NAME \
@@ -29,7 +29,7 @@
 MODULE_AUTHOR("Anil Veerabhadrappa <anilgv@broadcom.com> and "
 	      "Eddie Wai <eddie.wai@broadcom.com>");
 
-MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711"
+MODULE_DESCRIPTION("Broadcom NetXtreme II BCM5706/5708/5709/57710/57711/57712"
 		   " iSCSI Driver");
 MODULE_LICENSE("GPL");
 MODULE_VERSION(DRV_MODULE_VERSION);
@@ -88,9 +88,11 @@
 	    (hba->pci_did == PCI_DEVICE_ID_NX2_5709S)) {
 		set_bit(BNX2I_NX2_DEV_5709, &hba->cnic_dev_type);
 		hba->mail_queue_access = BNX2I_MQ_BIN_MODE;
-	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710 ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711 ||
-		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E)
+	} else if (hba->pci_did == PCI_DEVICE_ID_NX2_57710  ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711  ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57711E ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57712  ||
+		   hba->pci_did == PCI_DEVICE_ID_NX2_57712E)
 		set_bit(BNX2I_NX2_DEV_57710, &hba->cnic_dev_type);
 	else
 		printk(KERN_ALERT "bnx2i: unknown device, 0x%x\n",
@@ -161,6 +163,21 @@
 	struct bnx2i_hba *hba = handle;
 	int i = HZ;
 
+	if (!hba->cnic->max_iscsi_conn) {
+		printk(KERN_ALERT "bnx2i: dev %s does not support "
+			"iSCSI\n", hba->netdev->name);
+
+		if (test_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic)) {
+			mutex_lock(&bnx2i_dev_lock);
+			list_del_init(&hba->link);
+			adapter_count--;
+			hba->cnic->unregister_device(hba->cnic, CNIC_ULP_ISCSI);
+			clear_bit(BNX2I_CNIC_REGISTERED, &hba->reg_with_cnic);
+			mutex_unlock(&bnx2i_dev_lock);
+			bnx2i_free_hba(hba);
+		}
+		return;
+	}
 	bnx2i_send_fw_iscsi_init_msg(hba);
 	while (!test_bit(ADAPTER_STATE_UP, &hba->adapter_state) && i--)
 		msleep(BNX2I_INIT_POLL_TIME);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/bnx2i/bnx2i_iscsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1092,6 +1092,9 @@
 	case ISCSI_OP_SCSI_TMFUNC:
 		rc = bnx2i_send_iscsi_tmf(bnx2i_conn, task);
 		break;
+	case ISCSI_OP_TEXT:
+		rc = bnx2i_send_iscsi_text(bnx2i_conn, task);
+		break;
 	default:
 		iscsi_conn_printk(KERN_ALERT, bnx2i_conn->cls_conn->dd_data,
 				  "send_gen: unsupported op 0x%x\n",
@@ -1455,42 +1458,40 @@
 
 
 /**
- * bnx2i_conn_get_param - return iscsi connection parameter to caller
- * @cls_conn:	pointer to iscsi cls conn
+ * bnx2i_ep_get_param - return iscsi ep parameter to caller
+ * @ep:		pointer to iscsi endpoint
  * @param:	parameter type identifier
  * @buf: 	buffer pointer
  *
- * returns iSCSI connection parameters
+ * returns iSCSI ep parameters
  */
-static int bnx2i_conn_get_param(struct iscsi_cls_conn *cls_conn,
-				enum iscsi_param param, char *buf)
+static int bnx2i_ep_get_param(struct iscsi_endpoint *ep,
+			      enum iscsi_param param, char *buf)
 {
-	struct iscsi_conn *conn = cls_conn->dd_data;
-	struct bnx2i_conn *bnx2i_conn = conn->dd_data;
-	int len = 0;
+	struct bnx2i_endpoint *bnx2i_ep = ep->dd_data;
+	struct bnx2i_hba *hba = bnx2i_ep->hba;
+	int len = -ENOTCONN;
 
-	if (!(bnx2i_conn && bnx2i_conn->ep && bnx2i_conn->ep->hba))
-		goto out;
+	if (!hba)
+		return -ENOTCONN;
 
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
-		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
-		if (bnx2i_conn->ep->cm_sk)
-			len = sprintf(buf, "%hu\n",
-				      bnx2i_conn->ep->cm_sk->dst_port);
-		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
+		mutex_lock(&hba->net_dev_lock);
+		if (bnx2i_ep->cm_sk)
+			len = sprintf(buf, "%hu\n", bnx2i_ep->cm_sk->dst_port);
+		mutex_unlock(&hba->net_dev_lock);
 		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
-		mutex_lock(&bnx2i_conn->ep->hba->net_dev_lock);
-		if (bnx2i_conn->ep->cm_sk)
-			len = sprintf(buf, "%pI4\n",
-				      &bnx2i_conn->ep->cm_sk->dst_ip);
-		mutex_unlock(&bnx2i_conn->ep->hba->net_dev_lock);
+		mutex_lock(&hba->net_dev_lock);
+		if (bnx2i_ep->cm_sk)
+			len = sprintf(buf, "%pI4\n", &bnx2i_ep->cm_sk->dst_ip);
+		mutex_unlock(&hba->net_dev_lock);
 		break;
 	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
+		return -ENOSYS;
 	}
-out:
+
 	return len;
 }
 
@@ -1935,13 +1936,13 @@
 		cnic_dev_10g = 1;
 
 	switch (bnx2i_ep->state) {
-	case EP_STATE_CONNECT_FAILED:
 	case EP_STATE_CLEANUP_FAILED:
 	case EP_STATE_OFLD_FAILED:
 	case EP_STATE_DISCONN_TIMEDOUT:
 		ret = 0;
 		break;
 	case EP_STATE_CONNECT_START:
+	case EP_STATE_CONNECT_FAILED:
 	case EP_STATE_CONNECT_COMPL:
 	case EP_STATE_ULP_UPDATE_START:
 	case EP_STATE_ULP_UPDATE_COMPL:
@@ -2167,7 +2168,8 @@
 	.name			= "bnx2i",
 	.caps			= CAP_RECOVERY_L0 | CAP_HDRDGST |
 				  CAP_MULTI_R2T | CAP_DATADGST |
-				  CAP_DATA_PATH_OFFLOAD,
+				  CAP_DATA_PATH_OFFLOAD |
+				  CAP_TEXT_NEGO,
 	.param_mask		= ISCSI_MAX_RECV_DLENGTH |
 				  ISCSI_MAX_XMIT_DLENGTH |
 				  ISCSI_HDRDGST_EN |
@@ -2200,7 +2202,7 @@
 	.bind_conn		= bnx2i_conn_bind,
 	.destroy_conn		= bnx2i_conn_destroy,
 	.set_param		= iscsi_set_param,
-	.get_conn_param		= bnx2i_conn_get_param,
+	.get_conn_param		= iscsi_conn_get_param,
 	.get_session_param	= iscsi_session_get_param,
 	.get_host_param		= bnx2i_host_get_param,
 	.start_conn		= bnx2i_conn_start,
@@ -2209,6 +2211,7 @@
 	.xmit_task		= bnx2i_task_xmit,
 	.get_stats		= bnx2i_conn_get_stats,
 	/* TCP connect - disconnect - option-2 interface calls */
+	.get_ep_param		= bnx2i_ep_get_param,
 	.ep_connect		= bnx2i_ep_connect,
 	.ep_poll		= bnx2i_ep_poll,
 	.ep_disconnect		= bnx2i_ep_disconnect,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.c	2011-05-19 00:06:34.000000000 -0400
@@ -105,7 +105,7 @@
 	/* owner and name should be set already */
 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST
 				| CAP_DATADGST | CAP_DIGEST_OFFLOAD |
-				CAP_PADDING_OFFLOAD,
+				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
 	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
 				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
@@ -137,7 +137,7 @@
 	.destroy_conn	= iscsi_tcp_conn_teardown,
 	.start_conn	= iscsi_conn_start,
 	.stop_conn	= iscsi_conn_stop,
-	.get_conn_param	= cxgbi_get_conn_param,
+	.get_conn_param	= iscsi_conn_get_param,
 	.set_param	= cxgbi_set_conn_param,
 	.get_stats	= cxgbi_get_conn_stats,
 	/* pdu xmit req from user space */
@@ -152,6 +152,7 @@
 	.xmit_pdu	= cxgbi_conn_xmit_pdu,
 	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
 	/* TCP connect/disconnect */
+	.get_ep_param	= cxgbi_get_ep_param,
 	.ep_connect	= cxgbi_ep_connect,
 	.ep_poll	= cxgbi_ep_poll,
 	.ep_disconnect	= cxgbi_ep_disconnect,
@@ -1108,10 +1109,11 @@
 		csk, idx, npods, gl);
 
 	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
+		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
+						PPOD_SIZE, 0, GFP_ATOMIC);
 
-		/* hold on to the skb until we clear the ddp mapping */
-		skb_get(skb);
+		if (!skb)
+			return -ENOMEM;
 
 		ulp_mem_io_set_hdr(skb, pm_addr);
 		cxgbi_ddp_ppod_set((struct cxgbi_pagepod *)(skb->head +
@@ -1136,56 +1138,20 @@
 		cdev, idx, npods, tag);
 
 	for (i = 0; i < npods; i++, idx++, pm_addr += PPOD_SIZE) {
-		struct sk_buff *skb = ddp->gl_skb[idx];
+		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
+						PPOD_SIZE, 0, GFP_ATOMIC);
 
 		if (!skb) {
-			pr_err("tag 0x%x, 0x%x, %d/%u, skb NULL.\n",
+			pr_err("tag 0x%x, 0x%x, %d/%u, skb OOM.\n",
 				tag, idx, i, npods);
 			continue;
 		}
-		ddp->gl_skb[idx] = NULL;
-		memset(skb->head + sizeof(struct ulp_mem_io), 0, PPOD_SIZE);
 		ulp_mem_io_set_hdr(skb, pm_addr);
 		skb->priority = CPL_PRIORITY_CONTROL;
 		cxgb3_ofld_send(cdev->lldev, skb);
 	}
 }
 
-static void ddp_free_gl_skb(struct cxgbi_ddp_info *ddp, int idx, int cnt)
-{
-	int i;
-
-	log_debug(1 << CXGBI_DBG_DDP,
-		"ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
-
-	for (i = 0; i < cnt; i++, idx++)
-		if (ddp->gl_skb[idx]) {
-			kfree_skb(ddp->gl_skb[idx]);
-			ddp->gl_skb[idx] = NULL;
-		}
-}
-
-static int ddp_alloc_gl_skb(struct cxgbi_ddp_info *ddp, int idx,
-				   int cnt, gfp_t gfp)
-{
-	int i;
-
-	log_debug(1 << CXGBI_DBG_DDP,
-		"ddp 0x%p, idx %d, cnt %d.\n", ddp, idx, cnt);
-
-	for (i = 0; i < cnt; i++) {
-		struct sk_buff *skb = alloc_wr(sizeof(struct ulp_mem_io) +
-						PPOD_SIZE, 0, gfp);
-		if (skb)
-			ddp->gl_skb[idx + i] = skb;
-		else {
-			ddp_free_gl_skb(ddp, idx, i);
-			return -ENOMEM;
-		}
-	}
-	return 0;
-}
-
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
 				       unsigned int tid, int pg_idx, bool reply)
 {
@@ -1316,8 +1282,6 @@
 	}
 	tdev->ulp_iscsi = ddp;
 
-	cdev->csk_ddp_free_gl_skb = ddp_free_gl_skb;
-	cdev->csk_ddp_alloc_gl_skb = ddp_alloc_gl_skb;
 	cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
 	cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
 	cdev->csk_ddp_set = ddp_set_map;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb3i/cxgb3i.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,10 +24,21 @@
 
 extern cxgb3_cpl_handler_func cxgb3i_cpl_handlers[NUM_CPL_CMDS];
 
-#define cxgb3i_get_private_ipv4addr(ndev) \
-	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr)
-#define cxgb3i_set_private_ipv4addr(ndev, addr) \
-	(((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr) = addr
+static inline unsigned int cxgb3i_get_private_ipv4addr(struct net_device *ndev)
+{
+	return ((struct port_info *)(netdev_priv(ndev)))->iscsi_ipv4addr;
+}
+
+static inline void cxgb3i_set_private_ipv4addr(struct net_device *ndev,
+						unsigned int addr)
+{
+	struct port_info *pi =  (struct port_info *)netdev_priv(ndev);
+
+	pi->iscsic.flags = addr ? 1 : 0;
+	pi->iscsi_ipv4addr = addr;
+	if (addr)
+		memcpy(pi->iscsic.mac_addr, ndev->dev_addr, ETH_ALEN);
+}
 
 struct cpl_iscsi_hdr_norss {
 	union opcode_tid ot;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb3i/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,8 @@
 config SCSI_CXGB3_ISCSI
 	tristate "Chelsio T3 iSCSI support"
-	depends on CHELSIO_T3_DEPENDS
+	depends on PCI && INET
+	select NETDEVICES
+	select NETDEV_10000
 	select CHELSIO_T3
 	select SCSI_ISCSI_ATTRS
 	---help---
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb4i/cxgb4i.c	2011-05-19 00:06:34.000000000 -0400
@@ -106,7 +106,7 @@
 	.name		= DRV_MODULE_NAME,
 	.caps		= CAP_RECOVERY_L0 | CAP_MULTI_R2T | CAP_HDRDGST |
 				CAP_DATADGST | CAP_DIGEST_OFFLOAD |
-				CAP_PADDING_OFFLOAD,
+				CAP_PADDING_OFFLOAD | CAP_TEXT_NEGO,
 	.param_mask	= ISCSI_MAX_RECV_DLENGTH | ISCSI_MAX_XMIT_DLENGTH |
 				ISCSI_HDRDGST_EN | ISCSI_DATADGST_EN |
 				ISCSI_INITIAL_R2T_EN | ISCSI_MAX_R2T |
@@ -138,7 +138,7 @@
 	.destroy_conn	= iscsi_tcp_conn_teardown,
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_conn_stop,
-	.get_conn_param	= cxgbi_get_conn_param,
+	.get_conn_param	= iscsi_conn_get_param,
 	.set_param	= cxgbi_set_conn_param,
 	.get_stats	= cxgbi_get_conn_stats,
 	/* pdu xmit req from user space */
@@ -153,6 +153,7 @@
 	.xmit_pdu	= cxgbi_conn_xmit_pdu,
 	.parse_pdu_itt	= cxgbi_parse_pdu_itt,
 	/* TCP connect/disconnect */
+	.get_ep_param	= cxgbi_get_ep_param,
 	.ep_connect	= cxgbi_ep_connect,
 	.ep_poll	= cxgbi_ep_poll,
 	.ep_disconnect	= cxgbi_ep_disconnect,
@@ -1425,8 +1426,6 @@
 	cxgbi_ddp_page_size_factor(pgsz_factor);
 	cxgb4_iscsi_init(lldi->ports[0], tagmask, pgsz_factor);
 
-	cdev->csk_ddp_free_gl_skb = NULL;
-	cdev->csk_ddp_alloc_gl_skb = NULL;
 	cdev->csk_ddp_setup_digest = ddp_setup_conn_digest;
 	cdev->csk_ddp_setup_pgidx = ddp_setup_conn_pgidx;
 	cdev->csk_ddp_set = ddp_set_map;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/cxgb4i/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,8 @@
 config SCSI_CXGB4_ISCSI
 	tristate "Chelsio T4 iSCSI support"
-	depends on CHELSIO_T4_DEPENDS
+	depends on PCI && INET
+	select NETDEVICES
+	select NETDEV_10000
 	select CHELSIO_T4
 	select SCSI_ISCSI_ATTRS
 	---help---
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/libcxgbi.c linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/libcxgbi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/libcxgbi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/libcxgbi.c	2011-05-19 00:06:34.000000000 -0400
@@ -451,26 +451,13 @@
 }
 
 static struct rtable *find_route_ipv4(__be32 saddr, __be32 daddr,
-					__be16 sport, __be16 dport, u8 tos)
+				      __be16 sport, __be16 dport, u8 tos)
 {
 	struct rtable *rt;
-	struct flowi fl = {
-		.oif = 0,
-		.nl_u = {
-			.ip4_u = {
-				.daddr = daddr,
-				.saddr = saddr,
-				.tos = tos }
-			},
-		.proto = IPPROTO_TCP,
-		.uli_u = {
-			.ports = {
-				.sport = sport,
-				.dport = dport }
-			}
-	};
 
-	if (ip_route_output_flow(&init_net, &rt, &fl, NULL, 0))
+	rt = ip_route_output_ports(&init_net, NULL, daddr, saddr,
+				   dport, sport, IPPROTO_TCP, tos, 0);
+	if (IS_ERR(rt))
 		return NULL;
 
 	return rt;
@@ -543,6 +530,7 @@
 	csk->dst = dst;
 	csk->daddr.sin_addr.s_addr = daddr->sin_addr.s_addr;
 	csk->daddr.sin_port = daddr->sin_port;
+	csk->daddr.sin_family = daddr->sin_family;
 	csk->saddr.sin_addr.s_addr = rt->rt_src;
 
 	return csk;
@@ -1277,12 +1265,6 @@
 		return idx;
 	}
 
-	if (cdev->csk_ddp_alloc_gl_skb) {
-		err = cdev->csk_ddp_alloc_gl_skb(ddp, idx, npods, gfp);
-		if (err < 0)
-			goto unmark_entries;
-	}
-
 	tag = cxgbi_ddp_tag_base(tformat, sw_tag);
 	tag |= idx << PPOD_IDX_SHIFT;
 
@@ -1293,11 +1275,8 @@
 	hdr.page_offset = htonl(gl->offset);
 
 	err = cdev->csk_ddp_set(csk, &hdr, idx, npods, gl);
-	if (err < 0) {
-		if (cdev->csk_ddp_free_gl_skb)
-			cdev->csk_ddp_free_gl_skb(ddp, idx, npods);
+	if (err < 0)
 		goto unmark_entries;
-	}
 
 	ddp->idx_last = idx;
 	log_debug(1 << CXGBI_DBG_DDP,
@@ -1363,8 +1342,6 @@
 					>> PPOD_PAGES_SHIFT;
 			pr_info("cdev 0x%p, ddp %d + %d.\n", cdev, i, npods);
 			kfree(gl);
-			if (cdev->csk_ddp_free_gl_skb)
-				cdev->csk_ddp_free_gl_skb(ddp, i, npods);
 			i += npods;
 		} else
 			i++;
@@ -1407,8 +1384,6 @@
 		return -ENOMEM;
 	}
 	ddp->gl_map = (struct cxgbi_gather_list **)(ddp + 1);
-	ddp->gl_skb = (struct sk_buff **)(((char *)ddp->gl_map) +
-				ppmax * sizeof(struct cxgbi_gather_list *));
 	cdev->ddp = ddp;
 
 	spin_lock_init(&ddp->map_lock);
@@ -1908,13 +1883,16 @@
 
 static inline void tx_skb_setmode(struct sk_buff *skb, int hcrc, int dcrc)
 {
-	u8 submode = 0;
+	if (hcrc || dcrc) {
+		u8 submode = 0;
 
-	if (hcrc)
-		submode |= 1;
-	if (dcrc)
-		submode |= 2;
-	cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+		if (hcrc)
+			submode |= 1;
+		if (dcrc)
+			submode |= 2;
+		cxgbi_skcb_ulp_mode(skb) = (ULP2_MODE_ISCSI << 4) | submode;
+	} else
+		cxgbi_skcb_ulp_mode(skb) = 0;
 }
 
 int cxgbi_conn_init_pdu(struct iscsi_task *task, unsigned int offset,
@@ -2210,32 +2188,34 @@
 }
 EXPORT_SYMBOL_GPL(cxgbi_set_conn_param);
 
-int cxgbi_get_conn_param(struct iscsi_cls_conn *cls_conn,
-			enum iscsi_param param, char *buf)
+int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param param,
+		       char *buf)
 {
-	struct iscsi_conn *iconn = cls_conn->dd_data;
+	struct cxgbi_endpoint *cep = ep->dd_data;
+	struct cxgbi_sock *csk;
 	int len;
 
 	log_debug(1 << CXGBI_DBG_ISCSI,
-		"cls_conn 0x%p, param %d.\n", cls_conn, param);
+		"cls_conn 0x%p, param %d.\n", ep, param);
 
 	switch (param) {
 	case ISCSI_PARAM_CONN_PORT:
-		spin_lock_bh(&iconn->session->lock);
-		len = sprintf(buf, "%hu\n", iconn->portal_port);
-		spin_unlock_bh(&iconn->session->lock);
-		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
-		spin_lock_bh(&iconn->session->lock);
-		len = sprintf(buf, "%s\n", iconn->portal_address);
-		spin_unlock_bh(&iconn->session->lock);
-		break;
+		if (!cep)
+			return -ENOTCONN;
+
+		csk = cep->csk;
+		if (!csk)
+			return -ENOTCONN;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+						 &csk->daddr, param, buf);
 	default:
-		return iscsi_conn_get_param(cls_conn, param, buf);
+		return -ENOSYS;
 	}
 	return len;
 }
-EXPORT_SYMBOL_GPL(cxgbi_get_conn_param);
+EXPORT_SYMBOL_GPL(cxgbi_get_ep_param);
 
 struct iscsi_cls_conn *
 cxgbi_create_conn(struct iscsi_cls_session *cls_session, u32 cid)
@@ -2302,11 +2282,6 @@
 	cxgbi_conn_max_xmit_dlength(conn);
 	cxgbi_conn_max_recv_dlength(conn);
 
-	spin_lock_bh(&conn->session->lock);
-	sprintf(conn->portal_address, "%pI4", &csk->daddr.sin_addr.s_addr);
-	conn->portal_port = ntohs(csk->daddr.sin_port);
-	spin_unlock_bh(&conn->session->lock);
-
 	log_debug(1 << CXGBI_DBG_ISCSI,
 		"cls 0x%p,0x%p, ep 0x%p, cconn 0x%p, csk 0x%p.\n",
 		cls_session, cls_conn, ep, cconn, csk);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/libcxgbi.h linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/libcxgbi.h
--- linux-libre-2.6.38-gnu/drivers/scsi/cxgbi/libcxgbi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/cxgbi/libcxgbi.h	2011-05-19 00:06:34.000000000 -0400
@@ -131,7 +131,6 @@
 	unsigned int rsvd_tag_mask;
 	spinlock_t map_lock;
 	struct cxgbi_gather_list **gl_map;
-	struct sk_buff **gl_skb;
 };
 
 #define DDP_PGIDX_MAX		4
@@ -263,9 +262,9 @@
 enum cxgbi_skcb_flags {
 	SKCBF_TX_NEED_HDR,	/* packet needs a header */
 	SKCBF_RX_COALESCED,	/* received whole pdu */
-	SKCBF_RX_HDR,		/* recieved pdu header */
-	SKCBF_RX_DATA,		/* recieved pdu payload */
-	SKCBF_RX_STATUS,	/* recieved ddp status */
+	SKCBF_RX_HDR,		/* received pdu header */
+	SKCBF_RX_DATA,		/* received pdu payload */
+	SKCBF_RX_STATUS,	/* received ddp status */
 	SKCBF_RX_DATA_DDPD,	/* pdu payload ddp'd */
 	SKCBF_RX_HCRC_ERR,	/* header digest error */
 	SKCBF_RX_DCRC_ERR,	/* data digest error */
@@ -536,8 +535,6 @@
 	struct cxgbi_ddp_info *ddp;
 
 	void (*dev_ddp_cleanup)(struct cxgbi_device *);
-	void (*csk_ddp_free_gl_skb)(struct cxgbi_ddp_info *, int, int);
-	int (*csk_ddp_alloc_gl_skb)(struct cxgbi_ddp_info *, int, int, gfp_t);
 	int (*csk_ddp_set)(struct cxgbi_sock *, struct cxgbi_pagepod_hdr *,
 				unsigned int, unsigned int,
 				struct cxgbi_gather_list *);
@@ -715,7 +712,7 @@
 void cxgbi_get_conn_stats(struct iscsi_cls_conn *, struct iscsi_stats *);
 int cxgbi_set_conn_param(struct iscsi_cls_conn *,
 			enum iscsi_param, char *, int);
-int cxgbi_get_conn_param(struct iscsi_cls_conn *, enum iscsi_param, char *);
+int cxgbi_get_ep_param(struct iscsi_endpoint *ep, enum iscsi_param, char *);
 struct iscsi_cls_conn *cxgbi_create_conn(struct iscsi_cls_session *, u32);
 int cxgbi_bind_conn(struct iscsi_cls_session *,
 			struct iscsi_cls_conn *, u64, int);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/dc395x.c linux-libre-2.6.39-gnu/drivers/scsi/dc395x.c
--- linux-libre-2.6.38-gnu/drivers/scsi/dc395x.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/dc395x.c	2011-05-19 00:06:34.000000000 -0400
@@ -235,7 +235,7 @@
 
 	u8 sg_count;			/* No of HW sg entries for this request */
 	u8 sg_index;			/* Index of HW sg entry for this request */
-	size_t total_xfer_length;	/* Total number of bytes remaining to be transfered */
+	size_t total_xfer_length;	/* Total number of bytes remaining to be transferred */
 	size_t request_length;		/* Total number of bytes in this request */
 	/*
 	 * The sense buffer handling function, request_sense, uses
@@ -1774,7 +1774,7 @@
 		dc395x_statev(acb, srb, &scsi_status);
 
 		/* 
-		 * if there were any exception occured scsi_status
+		 * if there were any exception occurred scsi_status
 		 * will be modify to bus free phase new scsi_status
 		 * transfer out from ... previous dc395x_statev
 		 */
@@ -1954,11 +1954,11 @@
 static void sg_update_list(struct ScsiReqBlk *srb, u32 left)
 {
 	u8 idx;
-	u32 xferred = srb->total_xfer_length - left; /* bytes transfered */
+	u32 xferred = srb->total_xfer_length - left; /* bytes transferred */
 	struct SGentry *psge = srb->segment_x + srb->sg_index;
 
 	dprintkdbg(DBG_0,
-		"sg_update_list: Transfered %i of %i bytes, %i remain\n",
+		"sg_update_list: Transferred %i of %i bytes, %i remain\n",
 		xferred, srb->total_xfer_length, left);
 	if (xferred == 0) {
 		/* nothing to update since we did not transfer any data */
@@ -1990,7 +1990,7 @@
 
 
 /*
- * We have transfered a single byte (PIO mode?) and need to update
+ * We have transferred a single byte (PIO mode?) and need to update
  * the count of bytes remaining (total_xfer_length) and update the sg
  * entry to either point to next byte in the current sg entry, or of
  * already at the end to point to the start of the next sg entry
@@ -2029,7 +2029,7 @@
 
 
 /*
- * Those no of bytes will be transfered w/ PIO through the SCSI FIFO
+ * Those no of bytes will be transferred w/ PIO through the SCSI FIFO
  * Seems to be needed for unknown reasons; could be a hardware bug :-(
  */
 #define DC395x_LASTPIO 4
@@ -2256,7 +2256,7 @@
 			DC395x_read32(acb, TRM_S1040_DMA_CXCNT),
 			srb->total_xfer_length, d_left_counter);
 #if DC395x_LASTPIO
-		/* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */
+		/* KG: Less than or equal to 4 bytes can not be transferred via DMA, it seems. */
 		if (d_left_counter
 		    && srb->total_xfer_length <= DC395x_LASTPIO) {
 			size_t left_io = srb->total_xfer_length;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/dc395x.h linux-libre-2.6.39-gnu/drivers/scsi/dc395x.h
--- linux-libre-2.6.38-gnu/drivers/scsi/dc395x.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/dc395x.h	2011-05-19 00:06:34.000000000 -0400
@@ -617,7 +617,7 @@
 #define NTC_DO_SEND_START		0x08	/* Send start command SPINUP		*/
 #define NTC_DO_DISCONNECT		0x04	/* Enable SCSI disconnect		*/
 #define NTC_DO_SYNC_NEGO		0x02	/* Sync negotiation			*/
-#define NTC_DO_PARITY_CHK		0x01	/* (it sould define at NAC)		*/
+#define NTC_DO_PARITY_CHK		0x01	/* (it should define at NAC)		*/
 						/* Parity check enable			*/
 
 /************************************************************************/
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_alua.c linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_alua.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_alua.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_alua.c	2011-05-19 00:06:34.000000000 -0400
@@ -253,13 +253,15 @@
 {
 	struct alua_dh_data *h = req->end_io_data;
 	struct scsi_sense_hdr sense_hdr;
-	unsigned err = SCSI_DH_IO;
+	unsigned err = SCSI_DH_OK;
 
 	if (error || host_byte(req->errors) != DID_OK ||
-			msg_byte(req->errors) != COMMAND_COMPLETE)
+			msg_byte(req->errors) != COMMAND_COMPLETE) {
+		err = SCSI_DH_IO;
 		goto done;
+	}
 
-	if (err == SCSI_DH_IO && h->senselen > 0) {
+	if (h->senselen > 0) {
 		err = scsi_normalize_sense(h->sense, SCSI_SENSE_BUFFERSIZE,
 					   &sense_hdr);
 		if (!err) {
@@ -285,7 +287,8 @@
 			    print_alua_state(h->state));
 	}
 done:
-	blk_put_request(req);
+	req->end_io_data = NULL;
+	__blk_put_request(req->q, req);
 	if (h->callback_fn) {
 		h->callback_fn(h->callback_data, err);
 		h->callback_fn = h->callback_data = NULL;
@@ -303,7 +306,6 @@
 static unsigned submit_stpg(struct alua_dh_data *h)
 {
 	struct request *rq;
-	int err = SCSI_DH_RES_TEMP_UNAVAIL;
 	int stpg_len = 8;
 	struct scsi_device *sdev = h->sdev;
 
@@ -332,7 +334,7 @@
 	rq->end_io_data = h;
 
 	blk_execute_rq_nowait(rq->q, NULL, rq, 1, stpg_endio);
-	return err;
+	return SCSI_DH_OK;
 }
 
 /*
@@ -539,7 +541,7 @@
  *
  * Evaluate the Target Port Group State.
  * Returns SCSI_DH_DEV_OFFLINED if the path is
- * found to be unuseable.
+ * found to be unusable.
  */
 static int alua_rtpg(struct scsi_device *sdev, struct alua_dh_data *h)
 {
@@ -618,7 +620,7 @@
 		break;
 	case TPGS_STATE_OFFLINE:
 	case TPGS_STATE_UNAVAILABLE:
-		/* Path unuseable for unavailable/offline */
+		/* Path unusable for unavailable/offline */
 		err = SCSI_DH_DEV_OFFLINED;
 		break;
 	default:
@@ -730,7 +732,9 @@
 	{"Pillar", "Axiom" },
 	{"Intel", "Multi-Flex"},
 	{"NETAPP", "LUN"},
+	{"NETAPP", "LUN C-Mode"},
 	{"AIX", "NVDISK"},
+	{"Promise", "VTrak"},
 	{NULL, NULL}
 };
 
@@ -759,7 +763,7 @@
 	unsigned long flags;
 	int err = SCSI_DH_OK;
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh.c linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,16 +25,9 @@
 #include <scsi/scsi_dh.h>
 #include "../scsi_priv.h"
 
-struct scsi_dh_devinfo_list {
-	struct list_head node;
-	char vendor[9];
-	char model[17];
-	struct scsi_device_handler *handler;
-};
-
 static DEFINE_SPINLOCK(list_lock);
 static LIST_HEAD(scsi_dh_list);
-static LIST_HEAD(scsi_dh_dev_list);
+static int scsi_dh_list_idx = 1;
 
 static struct scsi_device_handler *get_device_handler(const char *name)
 {
@@ -51,40 +44,18 @@
 	return found;
 }
 
-
-static struct scsi_device_handler *
-scsi_dh_cache_lookup(struct scsi_device *sdev)
+static struct scsi_device_handler *get_device_handler_by_idx(int idx)
 {
-	struct scsi_dh_devinfo_list *tmp;
-	struct scsi_device_handler *found_dh = NULL;
+	struct scsi_device_handler *tmp, *found = NULL;
 
 	spin_lock(&list_lock);
-	list_for_each_entry(tmp, &scsi_dh_dev_list, node) {
-		if (!strncmp(sdev->vendor, tmp->vendor, strlen(tmp->vendor)) &&
-		    !strncmp(sdev->model, tmp->model, strlen(tmp->model))) {
-			found_dh = tmp->handler;
+	list_for_each_entry(tmp, &scsi_dh_list, list) {
+		if (tmp->idx == idx) {
+			found = tmp;
 			break;
 		}
 	}
 	spin_unlock(&list_lock);
-
-	return found_dh;
-}
-
-static int scsi_dh_handler_lookup(struct scsi_device_handler *scsi_dh,
-				  struct scsi_device *sdev)
-{
-	int i, found = 0;
-
-	for(i = 0; scsi_dh->devlist[i].vendor; i++) {
-		if (!strncmp(sdev->vendor, scsi_dh->devlist[i].vendor,
-			     strlen(scsi_dh->devlist[i].vendor)) &&
-		    !strncmp(sdev->model, scsi_dh->devlist[i].model,
-			     strlen(scsi_dh->devlist[i].model))) {
-			found = 1;
-			break;
-		}
-	}
 	return found;
 }
 
@@ -102,41 +73,14 @@
 		     struct scsi_device *sdev)
 {
 	struct scsi_device_handler *found_dh = NULL;
-	struct scsi_dh_devinfo_list *tmp;
-
-	found_dh = scsi_dh_cache_lookup(sdev);
-	if (found_dh)
-		return found_dh;
-
-	if (scsi_dh) {
-		if (scsi_dh_handler_lookup(scsi_dh, sdev))
-			found_dh = scsi_dh;
-	} else {
-		struct scsi_device_handler *tmp_dh;
+	int idx;
 
-		spin_lock(&list_lock);
-		list_for_each_entry(tmp_dh, &scsi_dh_list, list) {
-			if (scsi_dh_handler_lookup(tmp_dh, sdev))
-				found_dh = tmp_dh;
-		}
-		spin_unlock(&list_lock);
-	}
+	idx = scsi_get_device_flags_keyed(sdev, sdev->vendor, sdev->model,
+					  SCSI_DEVINFO_DH);
+	found_dh = get_device_handler_by_idx(idx);
 
-	if (found_dh) { /* If device is found, add it to the cache */
-		tmp = kmalloc(sizeof(*tmp), GFP_KERNEL);
-		if (tmp) {
-			strncpy(tmp->vendor, sdev->vendor, 8);
-			strncpy(tmp->model, sdev->model, 16);
-			tmp->vendor[8] = '\0';
-			tmp->model[16] = '\0';
-			tmp->handler = found_dh;
-			spin_lock(&list_lock);
-			list_add(&tmp->node, &scsi_dh_dev_list);
-			spin_unlock(&list_lock);
-		} else {
-			found_dh = NULL;
-		}
-	}
+	if (scsi_dh && found_dh != scsi_dh)
+		found_dh = NULL;
 
 	return found_dh;
 }
@@ -373,12 +317,25 @@
  */
 int scsi_register_device_handler(struct scsi_device_handler *scsi_dh)
 {
+	int i;
+
 	if (get_device_handler(scsi_dh->name))
 		return -EBUSY;
 
 	spin_lock(&list_lock);
+	scsi_dh->idx = scsi_dh_list_idx++;
 	list_add(&scsi_dh->list, &scsi_dh_list);
 	spin_unlock(&list_lock);
+
+	for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+		scsi_dev_info_list_add_keyed(0,
+					scsi_dh->devlist[i].vendor,
+					scsi_dh->devlist[i].model,
+					NULL,
+					scsi_dh->idx,
+					SCSI_DEVINFO_DH);
+	}
+
 	bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh, scsi_dh_notifier_add);
 	printk(KERN_INFO "%s: device handler registered\n", scsi_dh->name);
 
@@ -395,7 +352,7 @@
  */
 int scsi_unregister_device_handler(struct scsi_device_handler *scsi_dh)
 {
-	struct scsi_dh_devinfo_list *tmp, *pos;
+	int i;
 
 	if (!get_device_handler(scsi_dh->name))
 		return -ENODEV;
@@ -403,14 +360,14 @@
 	bus_for_each_dev(&scsi_bus_type, NULL, scsi_dh,
 			 scsi_dh_notifier_remove);
 
+	for (i = 0; scsi_dh->devlist[i].vendor; i++) {
+		scsi_dev_info_list_del_keyed(scsi_dh->devlist[i].vendor,
+					     scsi_dh->devlist[i].model,
+					     SCSI_DEVINFO_DH);
+	}
+
 	spin_lock(&list_lock);
 	list_del(&scsi_dh->list);
-	list_for_each_entry_safe(pos, tmp, &scsi_dh_dev_list, node) {
-		if (pos->handler == scsi_dh) {
-			list_del(&pos->node);
-			kfree(pos);
-		}
-	}
 	spin_unlock(&list_lock);
 	printk(KERN_INFO "%s: device handler unregistered\n", scsi_dh->name);
 
@@ -437,12 +394,14 @@
 	unsigned long flags;
 	struct scsi_device *sdev;
 	struct scsi_device_handler *scsi_dh = NULL;
+	struct device *dev = NULL;
 
 	spin_lock_irqsave(q->queue_lock, flags);
 	sdev = q->queuedata;
 	if (sdev && sdev->scsi_dh_data)
 		scsi_dh = sdev->scsi_dh_data->scsi_dh;
-	if (!scsi_dh || !get_device(&sdev->sdev_gendev) ||
+	dev = get_device(&sdev->sdev_gendev);
+	if (!scsi_dh || !dev ||
 	    sdev->sdev_state == SDEV_CANCEL ||
 	    sdev->sdev_state == SDEV_DEL)
 		err = SCSI_DH_NOSYS;
@@ -453,12 +412,13 @@
 	if (err) {
 		if (fn)
 			fn(data, err);
-		return err;
+		goto out;
 	}
 
 	if (scsi_dh->activate)
 		err = scsi_dh->activate(sdev, fn, data);
-	put_device(&sdev->sdev_gendev);
+out:
+	put_device(dev);
 	return err;
 }
 EXPORT_SYMBOL_GPL(scsi_dh_activate);
@@ -576,6 +536,10 @@
 {
 	int r;
 
+	r = scsi_dev_info_add_list(SCSI_DEVINFO_DH, "SCSI Device Handler");
+	if (r)
+		return r;
+
 	r = bus_register_notifier(&scsi_bus_type, &scsi_dh_nb);
 
 	if (!r)
@@ -590,6 +554,7 @@
 	bus_for_each_dev(&scsi_bus_type, NULL, NULL,
 			 scsi_dh_sysfs_attr_remove);
 	bus_unregister_notifier(&scsi_bus_type, &scsi_dh_nb);
+	scsi_dev_info_remove_list(SCSI_DEVINFO_DH);
 }
 
 module_init(scsi_dh_init);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_emc.c linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_emc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_emc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_emc.c	2011-05-19 00:06:34.000000000 -0400
@@ -650,7 +650,7 @@
 	unsigned long flags;
 	int err;
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_hp_sw.c linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_hp_sw.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_hp_sw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_hp_sw.c	2011-05-19 00:06:34.000000000 -0400
@@ -225,7 +225,8 @@
 		}
 	}
 done:
-	blk_put_request(req);
+	req->end_io_data = NULL;
+	__blk_put_request(req->q, req);
 	if (h->callback_fn) {
 		h->callback_fn(h->callback_data, err);
 		h->callback_fn = h->callback_data = NULL;
@@ -338,8 +339,8 @@
 	unsigned long flags;
 	int ret;
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
-			       + sizeof(struct hp_sw_dh_data) , GFP_KERNEL);
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
+			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach Failed\n",
 			    HP_SW_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c
--- linux-libre-2.6.38-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/device_handler/scsi_dh_rdac.c	2011-05-19 00:06:34.000000000 -0400
@@ -281,11 +281,13 @@
 }
 
 static struct request *rdac_failover_get(struct scsi_device *sdev,
-					 struct rdac_dh_data *h)
+			struct rdac_dh_data *h, struct list_head *list)
 {
 	struct request *rq;
 	struct rdac_mode_common *common;
 	unsigned data_size;
+	struct rdac_queue_data *qdata;
+	u8 *lun_table;
 
 	if (h->ctlr->use_ms10) {
 		struct rdac_pg_expanded *rdac_pg;
@@ -298,6 +300,7 @@
 		rdac_pg->subpage_code = 0x1;
 		rdac_pg->page_len[0] = 0x01;
 		rdac_pg->page_len[1] = 0x28;
+		lun_table = rdac_pg->lun_table;
 	} else {
 		struct rdac_pg_legacy *rdac_pg;
 
@@ -307,11 +310,16 @@
 		common = &rdac_pg->common;
 		rdac_pg->page_code = RDAC_PAGE_CODE_REDUNDANT_CONTROLLER;
 		rdac_pg->page_len = 0x68;
+		lun_table = rdac_pg->lun_table;
 	}
 	common->rdac_mode[1] = RDAC_MODE_TRANSFER_SPECIFIED_LUNS;
 	common->quiescence_timeout = RDAC_QUIESCENCE_TIME;
 	common->rdac_options = RDAC_FORCED_QUIESENCE;
 
+	list_for_each_entry(qdata, list, entry) {
+		lun_table[qdata->h->lun] = 0x81;
+	}
+
 	/* get request for block layer packet command */
 	rq = get_rdac_req(sdev, &h->ctlr->mode_select, data_size, WRITE);
 	if (!rq)
@@ -565,7 +573,6 @@
 	int err, retry_cnt = RDAC_RETRY_COUNT;
 	struct rdac_queue_data *tmp, *qdata;
 	LIST_HEAD(list);
-	u8 *lun_table;
 
 	spin_lock(&ctlr->ms_lock);
 	list_splice_init(&ctlr->ms_head, &list);
@@ -573,21 +580,12 @@
 	ctlr->ms_sdev = NULL;
 	spin_unlock(&ctlr->ms_lock);
 
-	if (ctlr->use_ms10)
-		lun_table = ctlr->mode_select.expanded.lun_table;
-	else
-		lun_table = ctlr->mode_select.legacy.lun_table;
-
 retry:
 	err = SCSI_DH_RES_TEMP_UNAVAIL;
-	rq = rdac_failover_get(sdev, h);
+	rq = rdac_failover_get(sdev, h, &list);
 	if (!rq)
 		goto done;
 
-	list_for_each_entry(qdata, &list, entry) {
-		lun_table[qdata->h->lun] = 0x81;
-	}
-
 	RDAC_LOG(RDAC_LOG_FAILOVER, sdev, "array %s, ctlr %d, "
 		"%s MODE_SELECT command",
 		(char *) h->ctlr->array_name, h->ctlr->index,
@@ -769,6 +767,7 @@
 	{"DELL", "MD32xx"},
 	{"DELL", "MD32xxi"},
 	{"DELL", "MD36xxi"},
+	{"DELL", "MD36xxf"},
 	{"LSI", "INF-01-00"},
 	{"ENGENIO", "INF-01-00"},
 	{"STK", "FLEXLINE 380"},
@@ -800,7 +799,7 @@
 	int err;
 	char array_name[ARRAY_LABEL_LEN];
 
-	scsi_dh_data = kzalloc(sizeof(struct scsi_device_handler *)
+	scsi_dh_data = kzalloc(sizeof(*scsi_dh_data)
 			       + sizeof(*h) , GFP_KERNEL);
 	if (!scsi_dh_data) {
 		sdev_printk(KERN_ERR, sdev, "%s: Attach failed\n",
@@ -906,4 +905,5 @@
 
 MODULE_DESCRIPTION("Multipath LSI/Engenio RDAC driver");
 MODULE_AUTHOR("Mike Christie, Chandra Seetharaman");
+MODULE_VERSION("01.00.0000.0000");
 MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/dpt/sys_info.h linux-libre-2.6.39-gnu/drivers/scsi/dpt/sys_info.h
--- linux-libre-2.6.38-gnu/drivers/scsi/dpt/sys_info.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/dpt/sys_info.h	2011-05-19 00:06:34.000000000 -0400
@@ -79,9 +79,9 @@
    typedef struct  {
 #endif
 
-   uSHORT       cylinders;      /* Upto 1024 */
-   uCHAR        heads;          /* Upto 255 */
-   uCHAR        sectors;        /* Upto 63 */
+   uSHORT       cylinders;      /* Up to 1024 */
+   uCHAR        heads;          /* Up to 255 */
+   uCHAR        sectors;        /* Up to 63 */
 
 #ifdef  __cplusplus
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/eata.c linux-libre-2.6.39-gnu/drivers/scsi/eata.c
--- linux-libre-2.6.38-gnu/drivers/scsi/eata.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/eata.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,7 +63,7 @@
  *          ep:[y|n]      eisa_probe=[1|0]  CONFIG_EISA defined
  *          pp:[y|n]      pci_probe=[1|0]   CONFIG_PCI  defined
  *
- *          The default action is to perform probing if the corrisponding
+ *          The default action is to perform probing if the corresponding
  *          bus is configured and to skip probing otherwise.
  *
  *        + If pci_probe is in effect and a list of I/O  ports is specified
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe.c linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe.c	2011-05-19 00:06:34.000000000 -0400
@@ -31,6 +31,7 @@
 #include <linux/fs.h>
 #include <linux/sysfs.h>
 #include <linux/ctype.h>
+#include <linux/workqueue.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/scsicam.h>
 #include <scsi/scsi_transport.h>
@@ -58,6 +59,8 @@
 
 DEFINE_MUTEX(fcoe_config_mutex);
 
+static struct workqueue_struct *fcoe_wq;
+
 /* fcoe_percpu_clean completion.  Waiter protected by fcoe_create_mutex */
 static DECLARE_COMPLETION(fcoe_flush_completion);
 
@@ -72,7 +75,6 @@
 static int fcoe_rcv(struct sk_buff *, struct net_device *,
 		    struct packet_type *, struct net_device *);
 static int fcoe_percpu_receive_thread(void *);
-static void fcoe_clean_pending_queue(struct fc_lport *);
 static void fcoe_percpu_clean(struct fc_lport *);
 static int fcoe_link_speed_update(struct fc_lport *);
 static int fcoe_link_ok(struct fc_lport *);
@@ -80,7 +82,6 @@
 static struct fc_lport *fcoe_hostlist_lookup(const struct net_device *);
 static int fcoe_hostlist_add(const struct fc_lport *);
 
-static void fcoe_check_wait_queue(struct fc_lport *, struct sk_buff *);
 static int fcoe_device_notification(struct notifier_block *, ulong, void *);
 static void fcoe_dev_setup(void);
 static void fcoe_dev_cleanup(void);
@@ -101,10 +102,11 @@
 
 static int fcoe_cpu_callback(struct notifier_block *, unsigned long, void *);
 
-static int fcoe_create(const char *, struct kernel_param *);
-static int fcoe_destroy(const char *, struct kernel_param *);
-static int fcoe_enable(const char *, struct kernel_param *);
-static int fcoe_disable(const char *, struct kernel_param *);
+static bool fcoe_match(struct net_device *netdev);
+static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode);
+static int fcoe_destroy(struct net_device *netdev);
+static int fcoe_enable(struct net_device *netdev);
+static int fcoe_disable(struct net_device *netdev);
 
 static struct fc_seq *fcoe_elsct_send(struct fc_lport *,
 				      u32 did, struct fc_frame *,
@@ -117,24 +119,6 @@
 
 static void fcoe_get_lesb(struct fc_lport *, struct fc_els_lesb *);
 
-module_param_call(create, fcoe_create, NULL, (void *)FIP_MODE_FABRIC, S_IWUSR);
-__MODULE_PARM_TYPE(create, "string");
-MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
-module_param_call(create_vn2vn, fcoe_create, NULL,
-		  (void *)FIP_MODE_VN2VN, S_IWUSR);
-__MODULE_PARM_TYPE(create_vn2vn, "string");
-MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
-		 "on an Ethernet interface");
-module_param_call(destroy, fcoe_destroy, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(destroy, "string");
-MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
-module_param_call(enable, fcoe_enable, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(enable, "string");
-MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
-module_param_call(disable, fcoe_disable, NULL, NULL, S_IWUSR);
-__MODULE_PARM_TYPE(disable, "string");
-MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
-
 /* notification function for packets from net device */
 static struct notifier_block fcoe_notifier = {
 	.notifier_call = fcoe_device_notification,
@@ -145,8 +129,8 @@
 	.notifier_call = fcoe_cpu_callback,
 };
 
-static struct scsi_transport_template *fcoe_transport_template;
-static struct scsi_transport_template *fcoe_vport_transport_template;
+static struct scsi_transport_template *fcoe_nport_scsi_transport;
+static struct scsi_transport_template *fcoe_vport_scsi_transport;
 
 static int fcoe_vport_destroy(struct fc_vport *);
 static int fcoe_vport_create(struct fc_vport *, bool disabled);
@@ -163,7 +147,7 @@
 	.lport_set_port_id = fcoe_set_port_id,
 };
 
-struct fc_function_template fcoe_transport_function = {
+struct fc_function_template fcoe_nport_fc_functions = {
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
 	.show_host_supported_classes = 1,
@@ -203,7 +187,7 @@
 	.bsg_request = fc_lport_bsg_request,
 };
 
-struct fc_function_template fcoe_vport_transport_function = {
+struct fc_function_template fcoe_vport_fc_functions = {
 	.show_host_node_name = 1,
 	.show_host_port_name = 1,
 	.show_host_supported_classes = 1,
@@ -285,9 +269,7 @@
 	}
 
 	/* Do not support for bonding device */
-	if ((netdev->priv_flags & IFF_MASTER_ALB) ||
-	    (netdev->priv_flags & IFF_SLAVE_INACTIVE) ||
-	    (netdev->priv_flags & IFF_MASTER_8023AD)) {
+	if (netdev->priv_flags & IFF_BONDING && netdev->flags & IFF_MASTER) {
 		FCOE_NETDEV_DBG(netdev, "Bonded interfaces not supported\n");
 		return -EOPNOTSUPP;
 	}
@@ -356,10 +338,18 @@
 	struct fcoe_interface *fcoe;
 	int err;
 
+	if (!try_module_get(THIS_MODULE)) {
+		FCOE_NETDEV_DBG(netdev,
+				"Could not get a reference to the module\n");
+		fcoe = ERR_PTR(-EBUSY);
+		goto out;
+	}
+
 	fcoe = kzalloc(sizeof(*fcoe), GFP_KERNEL);
 	if (!fcoe) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate fcoe structure\n");
-		return NULL;
+		fcoe = ERR_PTR(-ENOMEM);
+		goto out_nomod;
 	}
 
 	dev_hold(netdev);
@@ -378,9 +368,15 @@
 		fcoe_ctlr_destroy(&fcoe->ctlr);
 		kfree(fcoe);
 		dev_put(netdev);
-		return NULL;
+		fcoe = ERR_PTR(err);
+		goto out_nomod;
 	}
 
+	goto out;
+
+out_nomod:
+	module_put(THIS_MODULE);
+out:
 	return fcoe;
 }
 
@@ -442,6 +438,7 @@
 	fcoe_ctlr_destroy(&fcoe->ctlr);
 	kfree(fcoe);
 	dev_put(netdev);
+	module_put(THIS_MODULE);
 }
 
 /**
@@ -505,7 +502,7 @@
 static void fcoe_update_src_mac(struct fc_lport *lport, u8 *addr)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 
 	rtnl_lock();
 	if (!is_zero_ether_addr(port->data_src_addr))
@@ -561,17 +558,6 @@
 }
 
 /**
- * fcoe_queue_timer() - The fcoe queue timer
- * @lport: The local port
- *
- * Calls fcoe_check_wait_queue on timeout
- */
-static void fcoe_queue_timer(ulong lport)
-{
-	fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
-}
-
-/**
  * fcoe_get_wwn() - Get the world wide name from LLD if it supports it
  * @netdev: the associated net device
  * @wwn: the output WWN
@@ -650,7 +636,7 @@
 
 	/* Setup lport private data to point to fcoe softc */
 	port = lport_priv(lport);
-	fcoe = port->fcoe;
+	fcoe = port->priv;
 
 	/*
 	 * Determine max frame size based on underlying device and optional
@@ -708,9 +694,9 @@
 	lport->host->max_cmd_len = FCOE_MAX_CMD_LEN;
 
 	if (lport->vport)
-		lport->host->transportt = fcoe_vport_transport_template;
+		lport->host->transportt = fcoe_vport_scsi_transport;
 	else
-		lport->host->transportt = fcoe_transport_template;
+		lport->host->transportt = fcoe_nport_scsi_transport;
 
 	/* add the new host to the SCSI-ml */
 	rc = scsi_add_host(lport->host, dev);
@@ -760,7 +746,7 @@
 static inline int fcoe_em_config(struct fc_lport *lport)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct fcoe_interface *oldfcoe = NULL;
 	struct net_device *old_real_dev, *cur_real_dev;
 	u16 min_xid = FCOE_MIN_XID;
@@ -844,7 +830,7 @@
 static void fcoe_if_destroy(struct fc_lport *lport)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct net_device *netdev = fcoe->netdev;
 
 	FCOE_NETDEV_DBG(netdev, "Destroying interface\n");
@@ -886,7 +872,6 @@
 
 	/* Release the Scsi_Host */
 	scsi_host_put(lport->host);
-	module_put(THIS_MODULE);
 }
 
 /**
@@ -941,8 +926,9 @@
 				       struct device *parent, int npiv)
 {
 	struct net_device *netdev = fcoe->netdev;
-	struct fc_lport *lport = NULL;
+	struct fc_lport *lport, *n_port;
 	struct fcoe_port *port;
+	struct Scsi_Host *shost;
 	int rc;
 	/*
 	 * parent is only a vport if npiv is 1,
@@ -952,13 +938,11 @@
 
 	FCOE_NETDEV_DBG(netdev, "Create Interface\n");
 
-	if (!npiv) {
-		lport = libfc_host_alloc(&fcoe_shost_template,
-					 sizeof(struct fcoe_port));
-	} else	{
-		lport = libfc_vport_create(vport,
-					   sizeof(struct fcoe_port));
-	}
+	if (!npiv)
+		lport = libfc_host_alloc(&fcoe_shost_template, sizeof(*port));
+	else
+		lport = libfc_vport_create(vport, sizeof(*port));
+
 	if (!lport) {
 		FCOE_NETDEV_DBG(netdev, "Could not allocate host structure\n");
 		rc = -ENOMEM;
@@ -966,7 +950,9 @@
 	}
 	port = lport_priv(lport);
 	port->lport = lport;
-	port->fcoe = fcoe;
+	port->priv = fcoe;
+	port->max_queue_depth = FCOE_MAX_QUEUE_DEPTH;
+	port->min_queue_depth = FCOE_MIN_QUEUE_DEPTH;
 	INIT_WORK(&port->destroy_work, fcoe_destroy_work);
 
 	/* configure a fc_lport including the exchange manager */
@@ -1009,24 +995,27 @@
 		goto out_lp_destroy;
 	}
 
-	if (!npiv) {
-		/*
-		 * fcoe_em_alloc() and fcoe_hostlist_add() both
-		 * need to be atomic with respect to other changes to the
-		 * hostlist since fcoe_em_alloc() looks for an existing EM
-		 * instance on host list updated by fcoe_hostlist_add().
-		 *
-		 * This is currently handled through the fcoe_config_mutex
-		 * begin held.
-		 */
-
+	/*
+	 * fcoe_em_alloc() and fcoe_hostlist_add() both
+	 * need to be atomic with respect to other changes to the
+	 * hostlist since fcoe_em_alloc() looks for an existing EM
+	 * instance on host list updated by fcoe_hostlist_add().
+	 *
+	 * This is currently handled through the fcoe_config_mutex
+	 * begin held.
+	 */
+	if (!npiv)
 		/* lport exch manager allocation */
 		rc = fcoe_em_config(lport);
-		if (rc) {
-			FCOE_NETDEV_DBG(netdev, "Could not configure the EM "
-					"for the interface\n");
-			goto out_lp_destroy;
-		}
+	else {
+		shost = vport_to_shost(vport);
+		n_port = shost_priv(shost);
+		rc = fc_exch_mgr_list_clone(n_port, lport);
+	}
+
+	if (rc) {
+		FCOE_NETDEV_DBG(netdev, "Could not configure the EM\n");
+		goto out_lp_destroy;
 	}
 
 	fcoe_interface_get(fcoe);
@@ -1050,11 +1039,12 @@
 static int __init fcoe_if_init(void)
 {
 	/* attach to scsi transport */
-	fcoe_transport_template = fc_attach_transport(&fcoe_transport_function);
-	fcoe_vport_transport_template =
-		fc_attach_transport(&fcoe_vport_transport_function);
+	fcoe_nport_scsi_transport =
+		fc_attach_transport(&fcoe_nport_fc_functions);
+	fcoe_vport_scsi_transport =
+		fc_attach_transport(&fcoe_vport_fc_functions);
 
-	if (!fcoe_transport_template) {
+	if (!fcoe_nport_scsi_transport) {
 		printk(KERN_ERR "fcoe: Failed to attach to the FC transport\n");
 		return -ENODEV;
 	}
@@ -1071,10 +1061,10 @@
  */
 int __exit fcoe_if_exit(void)
 {
-	fc_release_transport(fcoe_transport_template);
-	fc_release_transport(fcoe_vport_transport_template);
-	fcoe_transport_template = NULL;
-	fcoe_vport_transport_template = NULL;
+	fc_release_transport(fcoe_nport_scsi_transport);
+	fc_release_transport(fcoe_vport_scsi_transport);
+	fcoe_nport_scsi_transport = NULL;
+	fcoe_vport_scsi_transport = NULL;
 	return 0;
 }
 
@@ -1361,108 +1351,22 @@
 }
 
 /**
- * fcoe_start_io() - Start FCoE I/O
- * @skb: The packet to be transmitted
- *
- * This routine is called from the net device to start transmitting
- * FCoE packets.
- *
- * Returns: 0 for success
- */
-static inline int fcoe_start_io(struct sk_buff *skb)
-{
-	struct sk_buff *nskb;
-	int rc;
-
-	nskb = skb_clone(skb, GFP_ATOMIC);
-	rc = dev_queue_xmit(nskb);
-	if (rc != 0)
-		return rc;
-	kfree_skb(skb);
-	return 0;
-}
-
-/**
- * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
+ * fcoe_alloc_paged_crc_eof() - Allocate a page to be used for the trailer CRC
  * @skb:  The packet to be transmitted
  * @tlen: The total length of the trailer
  *
- * This routine allocates a page for frame trailers. The page is re-used if
- * there is enough room left on it for the current trailer. If there isn't
- * enough buffer left a new page is allocated for the trailer. Reference to
- * the page from this function as well as the skbs using the page fragments
- * ensure that the page is freed at the appropriate time.
- *
  * Returns: 0 for success
  */
-static int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen)
+static int fcoe_alloc_paged_crc_eof(struct sk_buff *skb, int tlen)
 {
 	struct fcoe_percpu_s *fps;
-	struct page *page;
+	int rc;
 
 	fps = &get_cpu_var(fcoe_percpu);
-	page = fps->crc_eof_page;
-	if (!page) {
-		page = alloc_page(GFP_ATOMIC);
-		if (!page) {
-			put_cpu_var(fcoe_percpu);
-			return -ENOMEM;
-		}
-		fps->crc_eof_page = page;
-		fps->crc_eof_offset = 0;
-	}
-
-	get_page(page);
-	skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
-			   fps->crc_eof_offset, tlen);
-	skb->len += tlen;
-	skb->data_len += tlen;
-	skb->truesize += tlen;
-	fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
-
-	if (fps->crc_eof_offset >= PAGE_SIZE) {
-		fps->crc_eof_page = NULL;
-		fps->crc_eof_offset = 0;
-		put_page(page);
-	}
+	rc = fcoe_get_paged_crc_eof(skb, tlen, fps);
 	put_cpu_var(fcoe_percpu);
-	return 0;
-}
-
-/**
- * fcoe_fc_crc() - Calculates the CRC for a given frame
- * @fp: The frame to be checksumed
- *
- * This uses crc32() routine to calculate the CRC for a frame
- *
- * Return: The 32 bit CRC value
- */
-u32 fcoe_fc_crc(struct fc_frame *fp)
-{
-	struct sk_buff *skb = fp_skb(fp);
-	struct skb_frag_struct *frag;
-	unsigned char *data;
-	unsigned long off, len, clen;
-	u32 crc;
-	unsigned i;
-
-	crc = crc32(~0, skb->data, skb_headlen(skb));
 
-	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
-		frag = &skb_shinfo(skb)->frags[i];
-		off = frag->page_offset;
-		len = frag->size;
-		while (len > 0) {
-			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
-			data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
-					   KM_SKB_DATA_SOFTIRQ);
-			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
-			kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
-			off += clen;
-			len -= clen;
-		}
-	}
-	return crc;
+	return rc;
 }
 
 /**
@@ -1485,7 +1389,7 @@
 	unsigned int tlen;		/* trailer length */
 	unsigned int elen;		/* eth header, may include vlan */
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	u8 sof, eof;
 	struct fcoe_hdr *hp;
 
@@ -1526,7 +1430,7 @@
 	/* copy port crc and eof to the skb buff */
 	if (skb_is_nonlinear(skb)) {
 		skb_frag_t *frag;
-		if (fcoe_get_paged_crc_eof(skb, tlen)) {
+		if (fcoe_alloc_paged_crc_eof(skb, tlen)) {
 			kfree_skb(skb);
 			return -ENOMEM;
 		}
@@ -1606,6 +1510,56 @@
 }
 
 /**
+ * fcoe_filter_frames() - filter out bad fcoe frames, i.e. bad CRC
+ * @lport: The local port the frame was received on
+ * @fp:	   The received frame
+ *
+ * Return: 0 on passing filtering checks
+ */
+static inline int fcoe_filter_frames(struct fc_lport *lport,
+				     struct fc_frame *fp)
+{
+	struct fcoe_interface *fcoe;
+	struct fc_frame_header *fh;
+	struct sk_buff *skb = (struct sk_buff *)fp;
+	struct fcoe_dev_stats *stats;
+
+	/*
+	 * We only check CRC if no offload is available and if it is
+	 * it's solicited data, in which case, the FCP layer would
+	 * check it during the copy.
+	 */
+	if (lport->crc_offload && skb->ip_summed == CHECKSUM_UNNECESSARY)
+		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+	else
+		fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
+
+	fh = (struct fc_frame_header *) skb_transport_header(skb);
+	fh = fc_frame_header_get(fp);
+	if (fh->fh_r_ctl == FC_RCTL_DD_SOL_DATA && fh->fh_type == FC_TYPE_FCP)
+		return 0;
+
+	fcoe = ((struct fcoe_port *)lport_priv(lport))->priv;
+	if (is_fip_mode(&fcoe->ctlr) && fc_frame_payload_op(fp) == ELS_LOGO &&
+	    ntoh24(fh->fh_s_id) == FC_FID_FLOGI) {
+		FCOE_DBG("fcoe: dropping FCoE lport LOGO in fip mode\n");
+		return -EINVAL;
+	}
+
+	if (!(fr_flags(fp) & FCPHF_CRC_UNCHECKED) ||
+	    le32_to_cpu(fr_crc(fp)) == ~crc32(~0, skb->data, skb->len)) {
+		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+		return 0;
+	}
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->InvalidCRCCount++;
+	if (stats->InvalidCRCCount < 5)
+		printk(KERN_WARNING "fcoe: dropping frame with CRC error\n");
+	return -EINVAL;
+}
+
+/**
  * fcoe_recv_frame() - process a single received frame
  * @skb: frame to process
  */
@@ -1615,7 +1569,6 @@
 	struct fc_lport *lport;
 	struct fcoe_rcv_info *fr;
 	struct fcoe_dev_stats *stats;
-	struct fc_frame_header *fh;
 	struct fcoe_crc_eof crc_eof;
 	struct fc_frame *fp;
 	struct fcoe_port *port;
@@ -1646,7 +1599,6 @@
 	 * was done in fcoe_rcv already.
 	 */
 	hp = (struct fcoe_hdr *) skb_network_header(skb);
-	fh = (struct fc_frame_header *) skb_transport_header(skb);
 
 	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
 	if (unlikely(FC_FCOE_DECAPS_VER(hp) != FC_FCOE_VER)) {
@@ -1679,35 +1631,11 @@
 	if (pskb_trim(skb, fr_len))
 		goto drop;
 
-	/*
-	 * We only check CRC if no offload is available and if it is
-	 * it's solicited data, in which case, the FCP layer would
-	 * check it during the copy.
-	 */
-	if (lport->crc_offload &&
-	    skb->ip_summed == CHECKSUM_UNNECESSARY)
-		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
-	else
-		fr_flags(fp) |= FCPHF_CRC_UNCHECKED;
-
-	fh = fc_frame_header_get(fp);
-	if ((fh->fh_r_ctl != FC_RCTL_DD_SOL_DATA ||
-	    fh->fh_type != FC_TYPE_FCP) &&
-	    (fr_flags(fp) & FCPHF_CRC_UNCHECKED)) {
-		if (le32_to_cpu(fr_crc(fp)) !=
-		    ~crc32(~0, skb->data, fr_len)) {
-			if (stats->InvalidCRCCount < 5)
-				printk(KERN_WARNING "fcoe: dropping "
-				       "frame with CRC error\n");
-			stats->InvalidCRCCount++;
-			goto drop;
-		}
-		fr_flags(fp) &= ~FCPHF_CRC_UNCHECKED;
+	if (!fcoe_filter_frames(lport, fp)) {
+		put_cpu();
+		fc_exch_recv(lport, fp);
+		return;
 	}
-	put_cpu();
-	fc_exch_recv(lport, fp);
-	return;
-
 drop:
 	stats->ErrorFrames++;
 	put_cpu();
@@ -1746,64 +1674,6 @@
 }
 
 /**
- * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
- * @lport: The local port whose backlog is to be cleared
- *
- * This empties the wait_queue, dequeues the head of the wait_queue queue
- * and calls fcoe_start_io() for each packet. If all skb have been
- * transmitted it returns the qlen. If an error occurs it restores
- * wait_queue (to try again later) and returns -1.
- *
- * The wait_queue is used when the skb transmit fails. The failed skb
- * will go in the wait_queue which will be emptied by the timer function or
- * by the next skb transmit.
- */
-static void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
-{
-	struct fcoe_port *port = lport_priv(lport);
-	int rc;
-
-	spin_lock_bh(&port->fcoe_pending_queue.lock);
-
-	if (skb)
-		__skb_queue_tail(&port->fcoe_pending_queue, skb);
-
-	if (port->fcoe_pending_queue_active)
-		goto out;
-	port->fcoe_pending_queue_active = 1;
-
-	while (port->fcoe_pending_queue.qlen) {
-		/* keep qlen > 0 until fcoe_start_io succeeds */
-		port->fcoe_pending_queue.qlen++;
-		skb = __skb_dequeue(&port->fcoe_pending_queue);
-
-		spin_unlock_bh(&port->fcoe_pending_queue.lock);
-		rc = fcoe_start_io(skb);
-		spin_lock_bh(&port->fcoe_pending_queue.lock);
-
-		if (rc) {
-			__skb_queue_head(&port->fcoe_pending_queue, skb);
-			/* undo temporary increment above */
-			port->fcoe_pending_queue.qlen--;
-			break;
-		}
-		/* undo temporary increment above */
-		port->fcoe_pending_queue.qlen--;
-	}
-
-	if (port->fcoe_pending_queue.qlen < FCOE_LOW_QUEUE_DEPTH)
-		lport->qfull = 0;
-	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
-		mod_timer(&port->timer, jiffies + 2);
-	port->fcoe_pending_queue_active = 0;
-out:
-	if (port->fcoe_pending_queue.qlen > FCOE_MAX_QUEUE_DEPTH)
-		lport->qfull = 1;
-	spin_unlock_bh(&port->fcoe_pending_queue.lock);
-	return;
-}
-
-/**
  * fcoe_dev_setup() - Setup the link change notification interface
  */
 static void fcoe_dev_setup(void)
@@ -1874,7 +1744,7 @@
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
 		fcoe_interface_cleanup(fcoe);
-		schedule_work(&port->destroy_work);
+		queue_work(fcoe_wq, &port->destroy_work);
 		goto out;
 		break;
 	case NETDEV_FEAT_CHANGE:
@@ -1900,39 +1770,16 @@
 }
 
 /**
- * fcoe_if_to_netdev() - Parse a name buffer to get a net device
- * @buffer: The name of the net device
- *
- * Returns: NULL or a ptr to net_device
- */
-static struct net_device *fcoe_if_to_netdev(const char *buffer)
-{
-	char *cp;
-	char ifname[IFNAMSIZ + 2];
-
-	if (buffer) {
-		strlcpy(ifname, buffer, IFNAMSIZ);
-		cp = ifname + strlen(ifname);
-		while (--cp >= ifname && *cp == '\n')
-			*cp = '\0';
-		return dev_get_by_name(&init_net, ifname);
-	}
-	return NULL;
-}
-
-/**
  * fcoe_disable() - Disables a FCoE interface
- * @buffer: The name of the Ethernet interface to be disabled
- * @kp:	    The associated kernel parameter
+ * @netdev  : The net_device object the Ethernet interface to create on
  *
- * Called from sysfs.
+ * Called from fcoe transport.
  *
  * Returns: 0 for success
  */
-static int fcoe_disable(const char *buffer, struct kernel_param *kp)
+static int fcoe_disable(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -1948,16 +1795,9 @@
 	}
 #endif
 
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
-		goto out_nodev;
-	}
-
 	if (!rtnl_trylock()) {
-		dev_put(netdev);
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 	fcoe = fcoe_hostlist_lookup_port(netdev);
@@ -1969,7 +1809,6 @@
 	} else
 		rc = -ENODEV;
 
-	dev_put(netdev);
 out_nodev:
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -1977,17 +1816,15 @@
 
 /**
  * fcoe_enable() - Enables a FCoE interface
- * @buffer: The name of the Ethernet interface to be enabled
- * @kp:     The associated kernel parameter
+ * @netdev  : The net_device object the Ethernet interface to create on
  *
- * Called from sysfs.
+ * Called from fcoe transport.
  *
  * Returns: 0 for success
  */
-static int fcoe_enable(const char *buffer, struct kernel_param *kp)
+static int fcoe_enable(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -2002,17 +1839,9 @@
 		goto out_nodev;
 	}
 #endif
-
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
-		goto out_nodev;
-	}
-
 	if (!rtnl_trylock()) {
-		dev_put(netdev);
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 	fcoe = fcoe_hostlist_lookup_port(netdev);
@@ -2023,7 +1852,6 @@
 	else if (!fcoe_link_ok(fcoe->ctlr.lp))
 		fcoe_ctlr_link_up(&fcoe->ctlr);
 
-	dev_put(netdev);
 out_nodev:
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -2031,17 +1859,15 @@
 
 /**
  * fcoe_destroy() - Destroy a FCoE interface
- * @buffer: The name of the Ethernet interface to be destroyed
- * @kp:	    The associated kernel parameter
+ * @netdev  : The net_device object the Ethernet interface to create on
  *
- * Called from sysfs.
+ * Called from fcoe transport
  *
  * Returns: 0 for success
  */
-static int fcoe_destroy(const char *buffer, struct kernel_param *kp)
+static int fcoe_destroy(struct net_device *netdev)
 {
 	struct fcoe_interface *fcoe;
-	struct net_device *netdev;
 	int rc = 0;
 
 	mutex_lock(&fcoe_config_mutex);
@@ -2056,32 +1882,21 @@
 		goto out_nodev;
 	}
 #endif
-
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
-		goto out_nodev;
-	}
-
 	if (!rtnl_trylock()) {
-		dev_put(netdev);
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 	fcoe = fcoe_hostlist_lookup_port(netdev);
 	if (!fcoe) {
 		rtnl_unlock();
 		rc = -ENODEV;
-		goto out_putdev;
+		goto out_nodev;
 	}
 	fcoe_interface_cleanup(fcoe);
 	list_del(&fcoe->list);
 	/* RTNL mutex is dropped by fcoe_if_destroy */
 	fcoe_if_destroy(fcoe->ctlr.lp);
-
-out_putdev:
-	dev_put(netdev);
 out_nodev:
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -2104,27 +1919,39 @@
 }
 
 /**
+ * fcoe_match() - Check if the FCoE is supported on the given netdevice
+ * @netdev  : The net_device object the Ethernet interface to create on
+ *
+ * Called from fcoe transport.
+ *
+ * Returns: always returns true as this is the default FCoE transport,
+ * i.e., support all netdevs.
+ */
+static bool fcoe_match(struct net_device *netdev)
+{
+	return true;
+}
+
+/**
  * fcoe_create() - Create a fcoe interface
- * @buffer: The name of the Ethernet interface to create on
- * @kp:	    The associated kernel param
+ * @netdev  : The net_device object the Ethernet interface to create on
+ * @fip_mode: The FIP mode for this creation
  *
- * Called from sysfs.
+ * Called from fcoe transport
  *
  * Returns: 0 for success
  */
-static int fcoe_create(const char *buffer, struct kernel_param *kp)
+static int fcoe_create(struct net_device *netdev, enum fip_state fip_mode)
 {
-	enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
 	int rc;
 	struct fcoe_interface *fcoe;
 	struct fc_lport *lport;
-	struct net_device *netdev;
 
 	mutex_lock(&fcoe_config_mutex);
 
 	if (!rtnl_trylock()) {
 		mutex_unlock(&fcoe_config_mutex);
-		return restart_syscall();
+		return -ERESTARTSYS;
 	}
 
 #ifdef CONFIG_FCOE_MODULE
@@ -2135,31 +1962,20 @@
 	 */
 	if (THIS_MODULE->state != MODULE_STATE_LIVE) {
 		rc = -ENODEV;
-		goto out_nomod;
-	}
-#endif
-
-	if (!try_module_get(THIS_MODULE)) {
-		rc = -EINVAL;
-		goto out_nomod;
-	}
-
-	netdev = fcoe_if_to_netdev(buffer);
-	if (!netdev) {
-		rc = -ENODEV;
 		goto out_nodev;
 	}
+#endif
 
 	/* look for existing lport */
 	if (fcoe_hostlist_lookup(netdev)) {
 		rc = -EEXIST;
-		goto out_putdev;
+		goto out_nodev;
 	}
 
 	fcoe = fcoe_interface_create(netdev, fip_mode);
-	if (!fcoe) {
-		rc = -ENOMEM;
-		goto out_putdev;
+	if (IS_ERR(fcoe)) {
+		rc = PTR_ERR(fcoe);
+		goto out_nodev;
 	}
 
 	lport = fcoe_if_create(fcoe, &netdev->dev, 0);
@@ -2188,18 +2004,13 @@
 	 * should be holding a reference taken in fcoe_if_create().
 	 */
 	fcoe_interface_put(fcoe);
-	dev_put(netdev);
 	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
 
 	return 0;
 out_free:
 	fcoe_interface_put(fcoe);
-out_putdev:
-	dev_put(netdev);
 out_nodev:
-	module_put(THIS_MODULE);
-out_nomod:
 	rtnl_unlock();
 	mutex_unlock(&fcoe_config_mutex);
 	return rc;
@@ -2214,8 +2025,7 @@
  */
 int fcoe_link_speed_update(struct fc_lport *lport)
 {
-	struct fcoe_port *port = lport_priv(lport);
-	struct net_device *netdev = port->fcoe->netdev;
+	struct net_device *netdev = fcoe_netdev(lport);
 	struct ethtool_cmd ecmd = { ETHTOOL_GSET };
 
 	if (!dev_ethtool_get_settings(netdev, &ecmd)) {
@@ -2246,8 +2056,7 @@
  */
 int fcoe_link_ok(struct fc_lport *lport)
 {
-	struct fcoe_port *port = lport_priv(lport);
-	struct net_device *netdev = port->fcoe->netdev;
+	struct net_device *netdev = fcoe_netdev(lport);
 
 	if (netif_oper_up(netdev))
 		return 0;
@@ -2311,24 +2120,6 @@
 }
 
 /**
- * fcoe_clean_pending_queue() - Dequeue a skb and free it
- * @lport: The local port to dequeue a skb on
- */
-void fcoe_clean_pending_queue(struct fc_lport *lport)
-{
-	struct fcoe_port  *port = lport_priv(lport);
-	struct sk_buff *skb;
-
-	spin_lock_bh(&port->fcoe_pending_queue.lock);
-	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
-		spin_unlock_bh(&port->fcoe_pending_queue.lock);
-		kfree_skb(skb);
-		spin_lock_bh(&port->fcoe_pending_queue.lock);
-	}
-	spin_unlock_bh(&port->fcoe_pending_queue.lock);
-}
-
-/**
  * fcoe_reset() - Reset a local port
  * @shost: The SCSI host associated with the local port to be reset
  *
@@ -2337,7 +2128,13 @@
 int fcoe_reset(struct Scsi_Host *shost)
 {
 	struct fc_lport *lport = shost_priv(shost);
-	fc_lport_reset(lport);
+	struct fcoe_port *port = lport_priv(lport);
+	struct fcoe_interface *fcoe = port->priv;
+
+	fcoe_ctlr_link_down(&fcoe->ctlr);
+	fcoe_clean_pending_queue(fcoe->ctlr.lp);
+	if (!fcoe_link_ok(fcoe->ctlr.lp))
+		fcoe_ctlr_link_up(&fcoe->ctlr);
 	return 0;
 }
 
@@ -2395,12 +2192,24 @@
 	fcoe = fcoe_hostlist_lookup_port(fcoe_netdev(lport));
 	if (!fcoe) {
 		port = lport_priv(lport);
-		fcoe = port->fcoe;
+		fcoe = port->priv;
 		list_add_tail(&fcoe->list, &fcoe_hostlist);
 	}
 	return 0;
 }
 
+
+static struct fcoe_transport fcoe_sw_transport = {
+	.name = {FCOE_TRANSPORT_DEFAULT},
+	.attached = false,
+	.list = LIST_HEAD_INIT(fcoe_sw_transport.list),
+	.match = fcoe_match,
+	.create = fcoe_create,
+	.destroy = fcoe_destroy,
+	.enable = fcoe_enable,
+	.disable = fcoe_disable,
+};
+
 /**
  * fcoe_init() - Initialize fcoe.ko
  *
@@ -2412,6 +2221,18 @@
 	unsigned int cpu;
 	int rc = 0;
 
+	fcoe_wq = alloc_workqueue("fcoe", 0, 0);
+	if (!fcoe_wq)
+		return -ENOMEM;
+
+	/* register as a fcoe transport */
+	rc = fcoe_transport_attach(&fcoe_sw_transport);
+	if (rc) {
+		printk(KERN_ERR "failed to register an fcoe transport, check "
+			"if libfcoe is loaded\n");
+		return rc;
+	}
+
 	mutex_lock(&fcoe_config_mutex);
 
 	for_each_possible_cpu(cpu) {
@@ -2442,6 +2263,7 @@
 		fcoe_percpu_thread_destroy(cpu);
 	}
 	mutex_unlock(&fcoe_config_mutex);
+	destroy_workqueue(fcoe_wq);
 	return rc;
 }
 module_init(fcoe_init);
@@ -2467,7 +2289,7 @@
 		list_del(&fcoe->list);
 		port = lport_priv(fcoe->ctlr.lp);
 		fcoe_interface_cleanup(fcoe);
-		schedule_work(&port->destroy_work);
+		queue_work(fcoe_wq, &port->destroy_work);
 	}
 	rtnl_unlock();
 
@@ -2478,16 +2300,21 @@
 
 	mutex_unlock(&fcoe_config_mutex);
 
-	/* flush any asyncronous interface destroys,
-	 * this should happen after the netdev notifier is unregistered */
-	flush_scheduled_work();
-	/* That will flush out all the N_Ports on the hostlist, but now we
-	 * may have NPIV VN_Ports scheduled for destruction */
-	flush_scheduled_work();
+	/*
+	 * destroy_work's may be chained but destroy_workqueue()
+	 * can take care of them. Just kill the fcoe_wq.
+	 */
+	destroy_workqueue(fcoe_wq);
 
-	/* detach from scsi transport
-	 * must happen after all destroys are done, therefor after the flush */
+	/*
+	 * Detaching from the scsi transport must happen after all
+	 * destroys are done on the fcoe_wq. destroy_workqueue will
+	 * enusre the fcoe_wq is flushed.
+	 */
 	fcoe_if_exit();
+
+	/* detach from fcoe transport */
+	fcoe_transport_detach(&fcoe_sw_transport);
 }
 module_exit(fcoe_exit);
 
@@ -2559,7 +2386,7 @@
 				      void *arg, u32 timeout)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct fcoe_ctlr *fip = &fcoe->ctlr;
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 
@@ -2592,7 +2419,7 @@
 	struct Scsi_Host *shost = vport_to_shost(vport);
 	struct fc_lport *n_port = shost_priv(shost);
 	struct fcoe_port *port = lport_priv(n_port);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 	struct net_device *netdev = fcoe->netdev;
 	struct fc_lport *vn_port;
 
@@ -2632,7 +2459,7 @@
 	mutex_lock(&n_port->lp_mutex);
 	list_del(&vn_port->list);
 	mutex_unlock(&n_port->lp_mutex);
-	schedule_work(&port->destroy_work);
+	queue_work(fcoe_wq, &port->destroy_work);
 	return 0;
 }
 
@@ -2736,7 +2563,7 @@
 			     u32 port_id, struct fc_frame *fp)
 {
 	struct fcoe_port *port = lport_priv(lport);
-	struct fcoe_interface *fcoe = port->fcoe;
+	struct fcoe_interface *fcoe = port->priv;
 
 	if (fp && fc_frame_payload_op(fp) == ELS_FLOGI)
 		fcoe_ctlr_recv_flogi(&fcoe->ctlr, lport, fp);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe_ctlr.c linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe_ctlr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe_ctlr.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe_ctlr.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2682 @@
+/*
+ * Copyright (c) 2008-2009 Cisco Systems, Inc.  All rights reserved.
+ * Copyright (c) 2009 Intel Corporation.  All rights reserved.
+ *
+ * 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.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/spinlock.h>
+#include <linux/timer.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/ethtool.h>
+#include <linux/if_ether.h>
+#include <linux/if_vlan.h>
+#include <linux/errno.h>
+#include <linux/bitops.h>
+#include <linux/slab.h>
+#include <net/rtnetlink.h>
+
+#include <scsi/fc/fc_els.h>
+#include <scsi/fc/fc_fs.h>
+#include <scsi/fc/fc_fip.h>
+#include <scsi/fc/fc_encaps.h>
+#include <scsi/fc/fc_fcoe.h>
+#include <scsi/fc/fc_fcp.h>
+
+#include <scsi/libfc.h>
+#include <scsi/libfcoe.h>
+
+#include "libfcoe.h"
+
+#define	FCOE_CTLR_MIN_FKA	500		/* min keep alive (mS) */
+#define	FCOE_CTLR_DEF_FKA	FIP_DEF_FKA	/* default keep alive (mS) */
+
+static void fcoe_ctlr_timeout(unsigned long);
+static void fcoe_ctlr_timer_work(struct work_struct *);
+static void fcoe_ctlr_recv_work(struct work_struct *);
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
+
+static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
+static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
+static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
+static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
+
+static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
+static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
+static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
+static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS;
+
+static const char * const fcoe_ctlr_states[] = {
+	[FIP_ST_DISABLED] =	"DISABLED",
+	[FIP_ST_LINK_WAIT] =	"LINK_WAIT",
+	[FIP_ST_AUTO] =		"AUTO",
+	[FIP_ST_NON_FIP] =	"NON_FIP",
+	[FIP_ST_ENABLED] =	"ENABLED",
+	[FIP_ST_VNMP_START] =	"VNMP_START",
+	[FIP_ST_VNMP_PROBE1] =	"VNMP_PROBE1",
+	[FIP_ST_VNMP_PROBE2] =	"VNMP_PROBE2",
+	[FIP_ST_VNMP_CLAIM] =	"VNMP_CLAIM",
+	[FIP_ST_VNMP_UP] =	"VNMP_UP",
+};
+
+static const char *fcoe_ctlr_state(enum fip_state state)
+{
+	const char *cp = "unknown";
+
+	if (state < ARRAY_SIZE(fcoe_ctlr_states))
+		cp = fcoe_ctlr_states[state];
+	if (!cp)
+		cp = "unknown";
+	return cp;
+}
+
+/**
+ * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state.
+ * @fip: The FCoE controller
+ * @state: The new state
+ */
+static void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state)
+{
+	if (state == fip->state)
+		return;
+	if (fip->lp)
+		LIBFCOE_FIP_DBG(fip, "state %s -> %s\n",
+			fcoe_ctlr_state(fip->state), fcoe_ctlr_state(state));
+	fip->state = state;
+}
+
+/**
+ * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid
+ * @fcf: The FCF to check
+ *
+ * Return non-zero if FCF fcoe_size has been validated.
+ */
+static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf)
+{
+	return (fcf->flags & FIP_FL_SOL) != 0;
+}
+
+/**
+ * fcoe_ctlr_fcf_usable() - Check if a FCF is usable
+ * @fcf: The FCF to check
+ *
+ * Return non-zero if the FCF is usable.
+ */
+static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf)
+{
+	u16 flags = FIP_FL_SOL | FIP_FL_AVAIL;
+
+	return (fcf->flags & flags) == flags;
+}
+
+/**
+ * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses
+ * @fip: The FCoE controller
+ */
+static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip)
+{
+	if (fip->mode == FIP_MODE_VN2VN)
+		hton24(fip->dest_addr, FIP_VN_FC_MAP);
+	else
+		hton24(fip->dest_addr, FIP_DEF_FC_MAP);
+	hton24(fip->dest_addr + 3, 0);
+	fip->map_dest = 1;
+}
+
+/**
+ * fcoe_ctlr_init() - Initialize the FCoE Controller instance
+ * @fip: The FCoE controller to initialize
+ */
+void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
+{
+	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
+	fip->mode = mode;
+	INIT_LIST_HEAD(&fip->fcfs);
+	mutex_init(&fip->ctlr_mutex);
+	spin_lock_init(&fip->ctlr_lock);
+	fip->flogi_oxid = FC_XID_UNKNOWN;
+	setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
+	INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
+	INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
+	skb_queue_head_init(&fip->fip_recv_list);
+}
+EXPORT_SYMBOL(fcoe_ctlr_init);
+
+/**
+ * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller
+ * @fip: The FCoE controller whose FCFs are to be reset
+ *
+ * Called with &fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf *next;
+
+	fip->sel_fcf = NULL;
+	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
+		list_del(&fcf->list);
+		kfree(fcf);
+	}
+	fip->fcf_count = 0;
+	fip->sel_time = 0;
+}
+
+/**
+ * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller
+ * @fip: The FCoE controller to tear down
+ *
+ * This is called by FCoE drivers before freeing the &fcoe_ctlr.
+ *
+ * The receive handler will have been deleted before this to guarantee
+ * that no more recv_work will be scheduled.
+ *
+ * The timer routine will simply return once we set FIP_ST_DISABLED.
+ * This guarantees that no further timeouts or work will be scheduled.
+ */
+void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
+{
+	cancel_work_sync(&fip->recv_work);
+	skb_queue_purge(&fip->fip_recv_list);
+
+	mutex_lock(&fip->ctlr_mutex);
+	fcoe_ctlr_set_state(fip, FIP_ST_DISABLED);
+	fcoe_ctlr_reset_fcfs(fip);
+	mutex_unlock(&fip->ctlr_mutex);
+	del_timer_sync(&fip->timer);
+	cancel_work_sync(&fip->timer_work);
+}
+EXPORT_SYMBOL(fcoe_ctlr_destroy);
+
+/**
+ * fcoe_ctlr_announce() - announce new FCF selection
+ * @fip: The FCoE controller
+ *
+ * Also sets the destination MAC for FCoE and control packets
+ *
+ * Called with neither ctlr_mutex nor ctlr_lock held.
+ */
+static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *sel;
+	struct fcoe_fcf *fcf;
+
+	mutex_lock(&fip->ctlr_mutex);
+	spin_lock_bh(&fip->ctlr_lock);
+
+	kfree_skb(fip->flogi_req);
+	fip->flogi_req = NULL;
+	list_for_each_entry(fcf, &fip->fcfs, list)
+		fcf->flogi_sent = 0;
+
+	spin_unlock_bh(&fip->ctlr_lock);
+	sel = fip->sel_fcf;
+
+	if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
+		goto unlock;
+	if (!is_zero_ether_addr(fip->dest_addr)) {
+		printk(KERN_NOTICE "libfcoe: host%d: "
+		       "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
+		       fip->lp->host->host_no, fip->dest_addr);
+		memset(fip->dest_addr, 0, ETH_ALEN);
+	}
+	if (sel) {
+		printk(KERN_INFO "libfcoe: host%d: FIP selected "
+		       "Fibre-Channel Forwarder MAC %pM\n",
+		       fip->lp->host->host_no, sel->fcf_mac);
+		memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
+		fip->map_dest = 0;
+	}
+unlock:
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
+ * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port
+ * @fip: The FCoE controller to get the maximum FCoE size from
+ *
+ * Returns the maximum packet size including the FCoE header and trailer,
+ * but not including any Ethernet or VLAN headers.
+ */
+static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip)
+{
+	/*
+	 * Determine the max FCoE frame size allowed, including
+	 * FCoE header and trailer.
+	 * Note:  lp->mfs is currently the payload size, not the frame size.
+	 */
+	return fip->lp->mfs + sizeof(struct fc_frame_header) +
+		sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof);
+}
+
+/**
+ * fcoe_ctlr_solicit() - Send a FIP solicitation
+ * @fip: The FCoE controller to send the solicitation on
+ * @fcf: The destination FCF (if NULL, a multicast solicitation is sent)
+ */
+static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
+{
+	struct sk_buff *skb;
+	struct fip_sol {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct {
+			struct fip_mac_desc mac;
+			struct fip_wwn_desc wwnn;
+			struct fip_size_desc size;
+		} __packed desc;
+	}  __packed * sol;
+	u32 fcoe_size;
+
+	skb = dev_alloc_skb(sizeof(*sol));
+	if (!skb)
+		return;
+
+	sol = (struct fip_sol *)skb->data;
+
+	memset(sol, 0, sizeof(*sol));
+	memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN);
+	memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+	sol->eth.h_proto = htons(ETH_P_FIP);
+
+	sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	sol->fip.fip_op = htons(FIP_OP_DISC);
+	sol->fip.fip_subcode = FIP_SC_SOL;
+	sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW);
+	sol->fip.fip_flags = htons(FIP_FL_FPMA);
+	if (fip->spma)
+		sol->fip.fip_flags |= htons(FIP_FL_SPMA);
+
+	sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
+	sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW;
+	memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+	sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+	sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
+	put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
+
+	fcoe_size = fcoe_ctlr_fcoe_size(fip);
+	sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
+	sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW;
+	sol->desc.size.fd_size = htons(fcoe_size);
+
+	skb_put(skb, sizeof(*sol));
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	fip->send(fip, skb);
+
+	if (!fcf)
+		fip->sol_time = jiffies;
+}
+
+/**
+ * fcoe_ctlr_link_up() - Start FCoE controller
+ * @fip: The FCoE controller to start
+ *
+ * Called from the LLD when the network link is ready.
+ */
+void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
+{
+	mutex_lock(&fip->ctlr_mutex);
+	if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
+		mutex_unlock(&fip->ctlr_mutex);
+		fc_linkup(fip->lp);
+	} else if (fip->state == FIP_ST_LINK_WAIT) {
+		fcoe_ctlr_set_state(fip, fip->mode);
+		switch (fip->mode) {
+		default:
+			LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode);
+			/* fall-through */
+		case FIP_MODE_AUTO:
+			LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
+			/* fall-through */
+		case FIP_MODE_FABRIC:
+		case FIP_MODE_NON_FIP:
+			mutex_unlock(&fip->ctlr_mutex);
+			fc_linkup(fip->lp);
+			fcoe_ctlr_solicit(fip, NULL);
+			break;
+		case FIP_MODE_VN2VN:
+			fcoe_ctlr_vn_start(fip);
+			mutex_unlock(&fip->ctlr_mutex);
+			fc_linkup(fip->lp);
+			break;
+		}
+	} else
+		mutex_unlock(&fip->ctlr_mutex);
+}
+EXPORT_SYMBOL(fcoe_ctlr_link_up);
+
+/**
+ * fcoe_ctlr_reset() - Reset a FCoE controller
+ * @fip:       The FCoE controller to reset
+ */
+static void fcoe_ctlr_reset(struct fcoe_ctlr *fip)
+{
+	fcoe_ctlr_reset_fcfs(fip);
+	del_timer(&fip->timer);
+	fip->ctlr_ka_time = 0;
+	fip->port_ka_time = 0;
+	fip->sol_time = 0;
+	fip->flogi_oxid = FC_XID_UNKNOWN;
+	fcoe_ctlr_map_dest(fip);
+}
+
+/**
+ * fcoe_ctlr_link_down() - Stop a FCoE controller
+ * @fip: The FCoE controller to be stopped
+ *
+ * Returns non-zero if the link was up and now isn't.
+ *
+ * Called from the LLD when the network link is not ready.
+ * There may be multiple calls while the link is down.
+ */
+int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
+{
+	int link_dropped;
+
+	LIBFCOE_FIP_DBG(fip, "link down.\n");
+	mutex_lock(&fip->ctlr_mutex);
+	fcoe_ctlr_reset(fip);
+	link_dropped = fip->state != FIP_ST_LINK_WAIT;
+	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
+	mutex_unlock(&fip->ctlr_mutex);
+
+	if (link_dropped)
+		fc_linkdown(fip->lp);
+	return link_dropped;
+}
+EXPORT_SYMBOL(fcoe_ctlr_link_down);
+
+/**
+ * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF
+ * @fip:   The FCoE controller to send the FKA on
+ * @lport: libfc fc_lport to send from
+ * @ports: 0 for controller keep-alive, 1 for port keep-alive
+ * @sa:	   The source MAC address
+ *
+ * A controller keep-alive is sent every fka_period (typically 8 seconds).
+ * The source MAC is the native MAC address.
+ *
+ * A port keep-alive is sent every 90 seconds while logged in.
+ * The source MAC is the assigned mapped source address.
+ * The destination is the FCF's F-port.
+ */
+static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
+				      struct fc_lport *lport,
+				      int ports, u8 *sa)
+{
+	struct sk_buff *skb;
+	struct fip_kal {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct fip_mac_desc mac;
+	} __packed * kal;
+	struct fip_vn_desc *vn;
+	u32 len;
+	struct fc_lport *lp;
+	struct fcoe_fcf *fcf;
+
+	fcf = fip->sel_fcf;
+	lp = fip->lp;
+	if (!fcf || (ports && !lp->port_id))
+		return;
+
+	len = sizeof(*kal) + ports * sizeof(*vn);
+	skb = dev_alloc_skb(len);
+	if (!skb)
+		return;
+
+	kal = (struct fip_kal *)skb->data;
+	memset(kal, 0, len);
+	memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
+	memcpy(kal->eth.h_source, sa, ETH_ALEN);
+	kal->eth.h_proto = htons(ETH_P_FIP);
+
+	kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	kal->fip.fip_op = htons(FIP_OP_CTRL);
+	kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE;
+	kal->fip.fip_dl_len = htons((sizeof(kal->mac) +
+				     ports * sizeof(*vn)) / FIP_BPW);
+	kal->fip.fip_flags = htons(FIP_FL_FPMA);
+	if (fip->spma)
+		kal->fip.fip_flags |= htons(FIP_FL_SPMA);
+
+	kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
+	kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
+	memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+	if (ports) {
+		vn = (struct fip_vn_desc *)(kal + 1);
+		vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
+		vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
+		memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
+		hton24(vn->fd_fc_id, lport->port_id);
+		put_unaligned_be64(lport->wwpn, &vn->fd_wwpn);
+	}
+	skb_put(skb, len);
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	fip->send(fip, skb);
+}
+
+/**
+ * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it
+ * @fip:   The FCoE controller for the ELS frame
+ * @dtype: The FIP descriptor type for the frame
+ * @skb:   The FCoE ELS frame including FC header but no FCoE headers
+ * @d_id:  The destination port ID.
+ *
+ * Returns non-zero error code on failure.
+ *
+ * The caller must check that the length is a multiple of 4.
+ *
+ * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes).
+ * Headroom includes the FIP encapsulation description, FIP header, and
+ * Ethernet header.  The tailroom is for the FIP MAC descriptor.
+ */
+static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
+			    u8 dtype, struct sk_buff *skb, u32 d_id)
+{
+	struct fip_encaps_head {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct fip_encaps encaps;
+	} __packed * cap;
+	struct fc_frame_header *fh;
+	struct fip_mac_desc *mac;
+	struct fcoe_fcf *fcf;
+	size_t dlen;
+	u16 fip_flags;
+	u8 op;
+
+	fh = (struct fc_frame_header *)skb->data;
+	op = *(u8 *)(fh + 1);
+	dlen = sizeof(struct fip_encaps) + skb->len;	/* len before push */
+	cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
+	memset(cap, 0, sizeof(*cap));
+
+	if (lport->point_to_multipoint) {
+		if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest))
+			return -ENODEV;
+		fip_flags = 0;
+	} else {
+		fcf = fip->sel_fcf;
+		if (!fcf)
+			return -ENODEV;
+		fip_flags = fcf->flags;
+		fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA :
+					 FIP_FL_FPMA;
+		if (!fip_flags)
+			return -ENODEV;
+		memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
+	}
+	memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+	cap->eth.h_proto = htons(ETH_P_FIP);
+
+	cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	cap->fip.fip_op = htons(FIP_OP_LS);
+	if (op == ELS_LS_ACC || op == ELS_LS_RJT)
+		cap->fip.fip_subcode = FIP_SC_REP;
+	else
+		cap->fip.fip_subcode = FIP_SC_REQ;
+	cap->fip.fip_flags = htons(fip_flags);
+
+	cap->encaps.fd_desc.fip_dtype = dtype;
+	cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
+
+	if (op != ELS_LS_RJT) {
+		dlen += sizeof(*mac);
+		mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
+		memset(mac, 0, sizeof(*mac));
+		mac->fd_desc.fip_dtype = FIP_DT_MAC;
+		mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
+		if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) {
+			memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
+		} else if (fip->mode == FIP_MODE_VN2VN) {
+			hton24(mac->fd_mac, FIP_VN_FC_MAP);
+			hton24(mac->fd_mac + 3, fip->port_id);
+		} else if (fip_flags & FIP_FL_SPMA) {
+			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n");
+			memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN);
+		} else {
+			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n");
+			/* FPMA only FLOGI.  Must leave the MAC desc zeroed. */
+		}
+	}
+	cap->fip.fip_dl_len = htons(dlen / FIP_BPW);
+
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+	return 0;
+}
+
+/**
+ * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate.
+ * @fip:	FCoE controller.
+ * @lport:	libfc fc_lport to send from
+ * @skb:	FCoE ELS frame including FC header but no FCoE headers.
+ *
+ * Returns a non-zero error code if the frame should not be sent.
+ * Returns zero if the caller should send the frame with FCoE encapsulation.
+ *
+ * The caller must check that the length is a multiple of 4.
+ * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
+ * The the skb must also be an fc_frame.
+ *
+ * This is called from the lower-level driver with spinlocks held,
+ * so we must not take a mutex here.
+ */
+int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
+		       struct sk_buff *skb)
+{
+	struct fc_frame *fp;
+	struct fc_frame_header *fh;
+	u16 old_xid;
+	u8 op;
+	u8 mac[ETH_ALEN];
+
+	fp = container_of(skb, struct fc_frame, skb);
+	fh = (struct fc_frame_header *)skb->data;
+	op = *(u8 *)(fh + 1);
+
+	if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) {
+		old_xid = fip->flogi_oxid;
+		fip->flogi_oxid = ntohs(fh->fh_ox_id);
+		if (fip->state == FIP_ST_AUTO) {
+			if (old_xid == FC_XID_UNKNOWN)
+				fip->flogi_count = 0;
+			fip->flogi_count++;
+			if (fip->flogi_count < 3)
+				goto drop;
+			fcoe_ctlr_map_dest(fip);
+			return 0;
+		}
+		if (fip->state == FIP_ST_NON_FIP)
+			fcoe_ctlr_map_dest(fip);
+	}
+
+	if (fip->state == FIP_ST_NON_FIP)
+		return 0;
+	if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN)
+		goto drop;
+	switch (op) {
+	case ELS_FLOGI:
+		op = FIP_DT_FLOGI;
+		if (fip->mode == FIP_MODE_VN2VN)
+			break;
+		spin_lock_bh(&fip->ctlr_lock);
+		kfree_skb(fip->flogi_req);
+		fip->flogi_req = skb;
+		fip->flogi_req_send = 1;
+		spin_unlock_bh(&fip->ctlr_lock);
+		schedule_work(&fip->timer_work);
+		return -EINPROGRESS;
+	case ELS_FDISC:
+		if (ntoh24(fh->fh_s_id))
+			return 0;
+		op = FIP_DT_FDISC;
+		break;
+	case ELS_LOGO:
+		if (fip->mode == FIP_MODE_VN2VN) {
+			if (fip->state != FIP_ST_VNMP_UP)
+				return -EINVAL;
+			if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI)
+				return -EINVAL;
+		} else {
+			if (fip->state != FIP_ST_ENABLED)
+				return 0;
+			if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
+				return 0;
+		}
+		op = FIP_DT_LOGO;
+		break;
+	case ELS_LS_ACC:
+		/*
+		 * If non-FIP, we may have gotten an SID by accepting an FLOGI
+		 * from a point-to-point connection.  Switch to using
+		 * the source mac based on the SID.  The destination
+		 * MAC in this case would have been set by receiving the
+		 * FLOGI.
+		 */
+		if (fip->state == FIP_ST_NON_FIP) {
+			if (fip->flogi_oxid == FC_XID_UNKNOWN)
+				return 0;
+			fip->flogi_oxid = FC_XID_UNKNOWN;
+			fc_fcoe_set_mac(mac, fh->fh_d_id);
+			fip->update_mac(lport, mac);
+		}
+		/* fall through */
+	case ELS_LS_RJT:
+		op = fr_encaps(fp);
+		if (op)
+			break;
+		return 0;
+	default:
+		if (fip->state != FIP_ST_ENABLED &&
+		    fip->state != FIP_ST_VNMP_UP)
+			goto drop;
+		return 0;
+	}
+	LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n",
+			op, ntoh24(fh->fh_d_id));
+	if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id)))
+		goto drop;
+	fip->send(fip, skb);
+	return -EINPROGRESS;
+drop:
+	kfree_skb(skb);
+	return -EINVAL;
+}
+EXPORT_SYMBOL(fcoe_ctlr_els_send);
+
+/**
+ * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller
+ * @fip: The FCoE controller to free FCFs on
+ *
+ * Called with lock held and preemption disabled.
+ *
+ * An FCF is considered old if we have missed two advertisements.
+ * That is, there have been no valid advertisement from it for 2.5
+ * times its keep-alive period.
+ *
+ * In addition, determine the time when an FCF selection can occur.
+ *
+ * Also, increment the MissDiscAdvCount when no advertisement is received
+ * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB).
+ *
+ * Returns the time in jiffies for the next call.
+ */
+static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf *next;
+	unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
+	unsigned long deadline;
+	unsigned long sel_time = 0;
+	struct fcoe_dev_stats *stats;
+
+	stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());
+
+	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
+		deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
+		if (fip->sel_fcf == fcf) {
+			if (time_after(jiffies, deadline)) {
+				stats->MissDiscAdvCount++;
+				printk(KERN_INFO "libfcoe: host%d: "
+				       "Missing Discovery Advertisement "
+				       "for fab %16.16llx count %lld\n",
+				       fip->lp->host->host_no, fcf->fabric_name,
+				       stats->MissDiscAdvCount);
+			} else if (time_after(next_timer, deadline))
+				next_timer = deadline;
+		}
+
+		deadline += fcf->fka_period;
+		if (time_after_eq(jiffies, deadline)) {
+			if (fip->sel_fcf == fcf)
+				fip->sel_fcf = NULL;
+			list_del(&fcf->list);
+			WARN_ON(!fip->fcf_count);
+			fip->fcf_count--;
+			kfree(fcf);
+			stats->VLinkFailureCount++;
+		} else {
+			if (time_after(next_timer, deadline))
+				next_timer = deadline;
+			if (fcoe_ctlr_mtu_valid(fcf) &&
+			    (!sel_time || time_before(sel_time, fcf->time)))
+				sel_time = fcf->time;
+		}
+	}
+	put_cpu();
+	if (sel_time && !fip->sel_fcf && !fip->sel_time) {
+		sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+		fip->sel_time = sel_time;
+	}
+
+	return next_timer;
+}
+
+/**
+ * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry
+ * @fip: The FCoE controller receiving the advertisement
+ * @skb: The received FIP advertisement frame
+ * @fcf: The resulting FCF entry
+ *
+ * Returns zero on a valid parsed advertisement,
+ * otherwise returns non zero value.
+ */
+static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip,
+			       struct sk_buff *skb, struct fcoe_fcf *fcf)
+{
+	struct fip_header *fiph;
+	struct fip_desc *desc = NULL;
+	struct fip_wwn_desc *wwn;
+	struct fip_fab_desc *fab;
+	struct fip_fka_desc *fka;
+	unsigned long t;
+	size_t rlen;
+	size_t dlen;
+	u32 desc_mask;
+
+	memset(fcf, 0, sizeof(*fcf));
+	fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA);
+
+	fiph = (struct fip_header *)skb->data;
+	fcf->flags = ntohs(fiph->fip_flags);
+
+	/*
+	 * mask of required descriptors. validating each one clears its bit.
+	 */
+	desc_mask = BIT(FIP_DT_PRI) | BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
+			BIT(FIP_DT_FAB) | BIT(FIP_DT_FKA);
+
+	rlen = ntohs(fiph->fip_dl_len) * 4;
+	if (rlen + sizeof(*fiph) > skb->len)
+		return -EINVAL;
+
+	desc = (struct fip_desc *)(fiph + 1);
+	while (rlen > 0) {
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen < sizeof(*desc) || dlen > rlen)
+			return -EINVAL;
+		/* Drop Adv if there are duplicate critical descriptors */
+		if ((desc->fip_dtype < 32) &&
+		    !(desc_mask & 1U << desc->fip_dtype)) {
+			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
+					"Descriptors in FIP adv\n");
+			return -EINVAL;
+		}
+		switch (desc->fip_dtype) {
+		case FIP_DT_PRI:
+			if (dlen != sizeof(struct fip_pri_desc))
+				goto len_err;
+			fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri;
+			desc_mask &= ~BIT(FIP_DT_PRI);
+			break;
+		case FIP_DT_MAC:
+			if (dlen != sizeof(struct fip_mac_desc))
+				goto len_err;
+			memcpy(fcf->fcf_mac,
+			       ((struct fip_mac_desc *)desc)->fd_mac,
+			       ETH_ALEN);
+			if (!is_valid_ether_addr(fcf->fcf_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC addr %pM in FIP adv\n",
+					fcf->fcf_mac);
+				return -EINVAL;
+			}
+			desc_mask &= ~BIT(FIP_DT_MAC);
+			break;
+		case FIP_DT_NAME:
+			if (dlen != sizeof(struct fip_wwn_desc))
+				goto len_err;
+			wwn = (struct fip_wwn_desc *)desc;
+			fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn);
+			desc_mask &= ~BIT(FIP_DT_NAME);
+			break;
+		case FIP_DT_FAB:
+			if (dlen != sizeof(struct fip_fab_desc))
+				goto len_err;
+			fab = (struct fip_fab_desc *)desc;
+			fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn);
+			fcf->vfid = ntohs(fab->fd_vfid);
+			fcf->fc_map = ntoh24(fab->fd_map);
+			desc_mask &= ~BIT(FIP_DT_FAB);
+			break;
+		case FIP_DT_FKA:
+			if (dlen != sizeof(struct fip_fka_desc))
+				goto len_err;
+			fka = (struct fip_fka_desc *)desc;
+			if (fka->fd_flags & FIP_FKA_ADV_D)
+				fcf->fd_flags = 1;
+			t = ntohl(fka->fd_fka_period);
+			if (t >= FCOE_CTLR_MIN_FKA)
+				fcf->fka_period = msecs_to_jiffies(t);
+			desc_mask &= ~BIT(FIP_DT_FKA);
+			break;
+		case FIP_DT_MAP_OUI:
+		case FIP_DT_FCOE_SIZE:
+		case FIP_DT_FLOGI:
+		case FIP_DT_FDISC:
+		case FIP_DT_LOGO:
+		case FIP_DT_ELP:
+		default:
+			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+					"in FIP adv\n", desc->fip_dtype);
+			/* standard says ignore unknown descriptors >= 128 */
+			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+				return -EINVAL;
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+	if (!fcf->fc_map || (fcf->fc_map & 0x10000))
+		return -EINVAL;
+	if (!fcf->switch_name)
+		return -EINVAL;
+	if (desc_mask) {
+		LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n",
+				desc_mask);
+		return -EINVAL;
+	}
+	return 0;
+
+len_err:
+	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
+			desc->fip_dtype, dlen);
+	return -EINVAL;
+}
+
+/**
+ * fcoe_ctlr_recv_adv() - Handle an incoming advertisement
+ * @fip: The FCoE controller receiving the advertisement
+ * @skb: The received FIP packet
+ */
+static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf new;
+	struct fcoe_fcf *found;
+	unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
+	int first = 0;
+	int mtu_valid;
+
+	if (fcoe_ctlr_parse_adv(fip, skb, &new))
+		return;
+
+	mutex_lock(&fip->ctlr_mutex);
+	first = list_empty(&fip->fcfs);
+	found = NULL;
+	list_for_each_entry(fcf, &fip->fcfs, list) {
+		if (fcf->switch_name == new.switch_name &&
+		    fcf->fabric_name == new.fabric_name &&
+		    fcf->fc_map == new.fc_map &&
+		    compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
+			found = fcf;
+			break;
+		}
+	}
+	if (!found) {
+		if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT)
+			goto out;
+
+		fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC);
+		if (!fcf)
+			goto out;
+
+		fip->fcf_count++;
+		memcpy(fcf, &new, sizeof(new));
+		list_add(&fcf->list, &fip->fcfs);
+	} else {
+		/*
+		 * Update the FCF's keep-alive descriptor flags.
+		 * Other flag changes from new advertisements are
+		 * ignored after a solicited advertisement is
+		 * received and the FCF is selectable (usable).
+		 */
+		fcf->fd_flags = new.fd_flags;
+		if (!fcoe_ctlr_fcf_usable(fcf))
+			fcf->flags = new.flags;
+
+		if (fcf == fip->sel_fcf && !fcf->fd_flags) {
+			fip->ctlr_ka_time -= fcf->fka_period;
+			fip->ctlr_ka_time += new.fka_period;
+			if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+				mod_timer(&fip->timer, fip->ctlr_ka_time);
+		}
+		fcf->fka_period = new.fka_period;
+		memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
+	}
+	mtu_valid = fcoe_ctlr_mtu_valid(fcf);
+	fcf->time = jiffies;
+	if (!found)
+		LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
+				fcf->fabric_name, fcf->fcf_mac);
+
+	/*
+	 * If this advertisement is not solicited and our max receive size
+	 * hasn't been verified, send a solicited advertisement.
+	 */
+	if (!mtu_valid)
+		fcoe_ctlr_solicit(fip, fcf);
+
+	/*
+	 * If its been a while since we did a solicit, and this is
+	 * the first advertisement we've received, do a multicast
+	 * solicitation to gather as many advertisements as we can
+	 * before selection occurs.
+	 */
+	if (first && time_after(jiffies, fip->sol_time + sol_tov))
+		fcoe_ctlr_solicit(fip, NULL);
+
+	/*
+	 * Put this FCF at the head of the list for priority among equals.
+	 * This helps in the case of an NPV switch which insists we use
+	 * the FCF that answers multicast solicitations, not the others that
+	 * are sending periodic multicast advertisements.
+	 */
+	if (mtu_valid) {
+		list_del(&fcf->list);
+		list_add(&fcf->list, &fip->fcfs);
+	}
+
+	/*
+	 * If this is the first validated FCF, note the time and
+	 * set a timer to trigger selection.
+	 */
+	if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) {
+		fip->sel_time = jiffies +
+			msecs_to_jiffies(FCOE_CTLR_START_DELAY);
+		if (!timer_pending(&fip->timer) ||
+		    time_before(fip->sel_time, fip->timer.expires))
+			mod_timer(&fip->timer, fip->sel_time);
+	}
+out:
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
+ * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame
+ * @fip: The FCoE controller which received the packet
+ * @skb: The received FIP packet
+ */
+static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fip_header *fiph;
+	struct fc_frame *fp = (struct fc_frame *)skb;
+	struct fc_frame_header *fh = NULL;
+	struct fip_desc *desc;
+	struct fip_encaps *els;
+	struct fcoe_dev_stats *stats;
+	enum fip_desc_type els_dtype = 0;
+	u8 els_op;
+	u8 sub;
+	u8 granted_mac[ETH_ALEN] = { 0 };
+	size_t els_len = 0;
+	size_t rlen;
+	size_t dlen;
+	u32 desc_mask = 0;
+	u32 desc_cnt = 0;
+
+	fiph = (struct fip_header *)skb->data;
+	sub = fiph->fip_subcode;
+	if (sub != FIP_SC_REQ && sub != FIP_SC_REP)
+		goto drop;
+
+	rlen = ntohs(fiph->fip_dl_len) * 4;
+	if (rlen + sizeof(*fiph) > skb->len)
+		goto drop;
+
+	desc = (struct fip_desc *)(fiph + 1);
+	while (rlen > 0) {
+		desc_cnt++;
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen < sizeof(*desc) || dlen > rlen)
+			goto drop;
+		/* Drop ELS if there are duplicate critical descriptors */
+		if (desc->fip_dtype < 32) {
+			if (desc_mask & 1U << desc->fip_dtype) {
+				LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
+						"Descriptors in FIP ELS\n");
+				goto drop;
+			}
+			desc_mask |= (1 << desc->fip_dtype);
+		}
+		switch (desc->fip_dtype) {
+		case FIP_DT_MAC:
+			if (desc_cnt == 1) {
+				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
+						"received out of order\n");
+				goto drop;
+			}
+
+			if (dlen != sizeof(struct fip_mac_desc))
+				goto len_err;
+			memcpy(granted_mac,
+			       ((struct fip_mac_desc *)desc)->fd_mac,
+			       ETH_ALEN);
+			break;
+		case FIP_DT_FLOGI:
+		case FIP_DT_FDISC:
+		case FIP_DT_LOGO:
+		case FIP_DT_ELP:
+			if (desc_cnt != 1) {
+				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
+						"received out of order\n");
+				goto drop;
+			}
+			if (fh)
+				goto drop;
+			if (dlen < sizeof(*els) + sizeof(*fh) + 1)
+				goto len_err;
+			els_len = dlen - sizeof(*els);
+			els = (struct fip_encaps *)desc;
+			fh = (struct fc_frame_header *)(els + 1);
+			els_dtype = desc->fip_dtype;
+			break;
+		default:
+			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+					"in FIP adv\n", desc->fip_dtype);
+			/* standard says ignore unknown descriptors >= 128 */
+			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+				goto drop;
+			if (desc_cnt <= 2) {
+				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
+						"received out of order\n");
+				goto drop;
+			}
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+
+	if (!fh)
+		goto drop;
+	els_op = *(u8 *)(fh + 1);
+
+	if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
+	    sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
+		if (els_op == ELS_LS_ACC) {
+			if (!is_valid_ether_addr(granted_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC address %pM in FIP ELS\n",
+					granted_mac);
+				goto drop;
+			}
+			memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
+
+			if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+				fip->flogi_oxid = FC_XID_UNKNOWN;
+				if (els_dtype == FIP_DT_FLOGI)
+					fcoe_ctlr_announce(fip);
+			}
+		} else if (els_dtype == FIP_DT_FLOGI &&
+			   !fcoe_ctlr_flogi_retry(fip))
+			goto drop;	/* retrying FLOGI so drop reject */
+	}
+
+	if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
+	    (!(1U << FIP_DT_MAC & desc_mask)))) {
+		LIBFCOE_FIP_DBG(fip, "Missing critical descriptors "
+				"in FIP ELS\n");
+		goto drop;
+	}
+
+	/*
+	 * Convert skb into an fc_frame containing only the ELS.
+	 */
+	skb_pull(skb, (u8 *)fh - skb->data);
+	skb_trim(skb, els_len);
+	fp = (struct fc_frame *)skb;
+	fc_frame_init(fp);
+	fr_sof(fp) = FC_SOF_I3;
+	fr_eof(fp) = FC_EOF_T;
+	fr_dev(fp) = lport;
+	fr_encaps(fp) = els_dtype;
+
+	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
+	stats->RxFrames++;
+	stats->RxWords += skb->len / FIP_BPW;
+	put_cpu();
+
+	fc_exch_recv(lport, fp);
+	return;
+
+len_err:
+	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
+			desc->fip_dtype, dlen);
+drop:
+	kfree_skb(skb);
+}
+
+/**
+ * fcoe_ctlr_recv_els() - Handle an incoming link reset frame
+ * @fip: The FCoE controller that received the frame
+ * @fh:	 The received FIP header
+ *
+ * There may be multiple VN_Port descriptors.
+ * The overall length has already been checked.
+ */
+static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
+				     struct fip_header *fh)
+{
+	struct fip_desc *desc;
+	struct fip_mac_desc *mp;
+	struct fip_wwn_desc *wp;
+	struct fip_vn_desc *vp;
+	size_t rlen;
+	size_t dlen;
+	struct fcoe_fcf *fcf = fip->sel_fcf;
+	struct fc_lport *lport = fip->lp;
+	struct fc_lport *vn_port = NULL;
+	u32 desc_mask;
+	int is_vn_port = 0;
+
+	LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
+
+	if (!fcf || !lport->port_id)
+		return;
+
+	/*
+	 * mask of required descriptors.  Validating each one clears its bit.
+	 */
+	desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID);
+
+	rlen = ntohs(fh->fip_dl_len) * FIP_BPW;
+	desc = (struct fip_desc *)(fh + 1);
+	while (rlen >= sizeof(*desc)) {
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen > rlen)
+			return;
+		/* Drop CVL if there are duplicate critical descriptors */
+		if ((desc->fip_dtype < 32) &&
+		    !(desc_mask & 1U << desc->fip_dtype)) {
+			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
+					"Descriptors in FIP CVL\n");
+			return;
+		}
+		switch (desc->fip_dtype) {
+		case FIP_DT_MAC:
+			mp = (struct fip_mac_desc *)desc;
+			if (dlen < sizeof(*mp))
+				return;
+			if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac))
+				return;
+			desc_mask &= ~BIT(FIP_DT_MAC);
+			break;
+		case FIP_DT_NAME:
+			wp = (struct fip_wwn_desc *)desc;
+			if (dlen < sizeof(*wp))
+				return;
+			if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name)
+				return;
+			desc_mask &= ~BIT(FIP_DT_NAME);
+			break;
+		case FIP_DT_VN_ID:
+			vp = (struct fip_vn_desc *)desc;
+			if (dlen < sizeof(*vp))
+				return;
+			if (compare_ether_addr(vp->fd_mac,
+					       fip->get_src_addr(lport)) == 0 &&
+			    get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
+			    ntoh24(vp->fd_fc_id) == lport->port_id) {
+				desc_mask &= ~BIT(FIP_DT_VN_ID);
+				break;
+			}
+			/* check if clr_vlink is for NPIV port */
+			mutex_lock(&lport->lp_mutex);
+			list_for_each_entry(vn_port, &lport->vports, list) {
+				if (compare_ether_addr(vp->fd_mac,
+				    fip->get_src_addr(vn_port)) == 0 &&
+				    (get_unaligned_be64(&vp->fd_wwpn)
+							== vn_port->wwpn) &&
+				    (ntoh24(vp->fd_fc_id) ==
+					    fc_host_port_id(vn_port->host))) {
+					desc_mask &= ~BIT(FIP_DT_VN_ID);
+					is_vn_port = 1;
+					break;
+				}
+			}
+			mutex_unlock(&lport->lp_mutex);
+
+			break;
+		default:
+			/* standard says ignore unknown descriptors >= 128 */
+			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
+				return;
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+
+	/*
+	 * reset only if all required descriptors were present and valid.
+	 */
+	if (desc_mask) {
+		LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n",
+				desc_mask);
+	} else {
+		LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
+
+		if (is_vn_port)
+			fc_lport_reset(vn_port);
+		else {
+			mutex_lock(&fip->ctlr_mutex);
+			per_cpu_ptr(lport->dev_stats,
+				    get_cpu())->VLinkFailureCount++;
+			put_cpu();
+			fcoe_ctlr_reset(fip);
+			mutex_unlock(&fip->ctlr_mutex);
+
+			fc_lport_reset(fip->lp);
+			fcoe_ctlr_solicit(fip, NULL);
+		}
+	}
+}
+
+/**
+ * fcoe_ctlr_recv() - Receive a FIP packet
+ * @fip: The FCoE controller that received the packet
+ * @skb: The received FIP packet
+ *
+ * This may be called from either NET_RX_SOFTIRQ or IRQ.
+ */
+void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	skb_queue_tail(&fip->fip_recv_list, skb);
+	schedule_work(&fip->recv_work);
+}
+EXPORT_SYMBOL(fcoe_ctlr_recv);
+
+/**
+ * fcoe_ctlr_recv_handler() - Receive a FIP frame
+ * @fip: The FCoE controller that received the frame
+ * @skb: The received FIP frame
+ *
+ * Returns non-zero if the frame is dropped.
+ */
+static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fip_header *fiph;
+	struct ethhdr *eh;
+	enum fip_state state;
+	u16 op;
+	u8 sub;
+
+	if (skb_linearize(skb))
+		goto drop;
+	if (skb->len < sizeof(*fiph))
+		goto drop;
+	eh = eth_hdr(skb);
+	if (fip->mode == FIP_MODE_VN2VN) {
+		if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
+		    compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) &&
+		    compare_ether_addr(eh->h_dest, fcoe_all_p2p))
+			goto drop;
+	} else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
+		   compare_ether_addr(eh->h_dest, fcoe_all_enode))
+		goto drop;
+	fiph = (struct fip_header *)skb->data;
+	op = ntohs(fiph->fip_op);
+	sub = fiph->fip_subcode;
+
+	if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
+		goto drop;
+	if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
+		goto drop;
+
+	mutex_lock(&fip->ctlr_mutex);
+	state = fip->state;
+	if (state == FIP_ST_AUTO) {
+		fip->map_dest = 0;
+		fcoe_ctlr_set_state(fip, FIP_ST_ENABLED);
+		state = FIP_ST_ENABLED;
+		LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
+	}
+	mutex_unlock(&fip->ctlr_mutex);
+
+	if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
+		return fcoe_ctlr_vn_recv(fip, skb);
+
+	if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
+	    state != FIP_ST_VNMP_CLAIM)
+		goto drop;
+
+	if (op == FIP_OP_LS) {
+		fcoe_ctlr_recv_els(fip, skb);	/* consumes skb */
+		return 0;
+	}
+
+	if (state != FIP_ST_ENABLED)
+		goto drop;
+
+	if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
+		fcoe_ctlr_recv_adv(fip, skb);
+	else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
+		fcoe_ctlr_recv_clr_vlink(fip, fiph);
+	kfree_skb(skb);
+	return 0;
+drop:
+	kfree_skb(skb);
+	return -1;
+}
+
+/**
+ * fcoe_ctlr_select() - Select the best FCF (if possible)
+ * @fip: The FCoE controller
+ *
+ * Returns the selected FCF, or NULL if none are usable.
+ *
+ * If there are conflicting advertisements, no FCF can be chosen.
+ *
+ * If there is already a selected FCF, this will choose a better one or
+ * an equivalent one that hasn't already been sent a FLOGI.
+ *
+ * Called with lock held.
+ */
+static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	struct fcoe_fcf *best = fip->sel_fcf;
+	struct fcoe_fcf *first;
+
+	first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
+
+	list_for_each_entry(fcf, &fip->fcfs, list) {
+		LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
+				"VFID %d mac %pM map %x val %d "
+				"sent %u pri %u\n",
+				fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
+				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
+				fcf->flogi_sent, fcf->pri);
+		if (fcf->fabric_name != first->fabric_name ||
+		    fcf->vfid != first->vfid ||
+		    fcf->fc_map != first->fc_map) {
+			LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
+					"or FC-MAP\n");
+			return NULL;
+		}
+		if (fcf->flogi_sent)
+			continue;
+		if (!fcoe_ctlr_fcf_usable(fcf)) {
+			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
+					"map %x %svalid %savailable\n",
+					fcf->fabric_name, fcf->fc_map,
+					(fcf->flags & FIP_FL_SOL) ? "" : "in",
+					(fcf->flags & FIP_FL_AVAIL) ?
+					"" : "un");
+			continue;
+		}
+		if (!best || fcf->pri < best->pri || best->flogi_sent)
+			best = fcf;
+	}
+	fip->sel_fcf = best;
+	if (best) {
+		LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac);
+		fip->port_ka_time = jiffies +
+			msecs_to_jiffies(FIP_VN_KA_PERIOD);
+		fip->ctlr_ka_time = jiffies + best->fka_period;
+		if (time_before(fip->ctlr_ka_time, fip->timer.expires))
+			mod_timer(&fip->timer, fip->ctlr_ka_time);
+	}
+	return best;
+}
+
+/**
+ * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error if it could not be sent.
+ *
+ * Called with ctlr_mutex and ctlr_lock held.
+ * Caller must verify that fip->sel_fcf is not NULL.
+ */
+static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
+{
+	struct sk_buff *skb;
+	struct sk_buff *skb_orig;
+	struct fc_frame_header *fh;
+	int error;
+
+	skb_orig = fip->flogi_req;
+	if (!skb_orig)
+		return -EINVAL;
+
+	/*
+	 * Clone and send the FLOGI request.  If clone fails, use original.
+	 */
+	skb = skb_clone(skb_orig, GFP_ATOMIC);
+	if (!skb) {
+		skb = skb_orig;
+		fip->flogi_req = NULL;
+	}
+	fh = (struct fc_frame_header *)skb->data;
+	error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
+				 ntoh24(fh->fh_d_id));
+	if (error) {
+		kfree_skb(skb);
+		return error;
+	}
+	fip->send(fip, skb);
+	fip->sel_fcf->flogi_sent = 1;
+	return 0;
+}
+
+/**
+ * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
+ * @fip: The FCoE controller
+ *
+ * Returns non-zero error code if there's no FLOGI request to retry or
+ * no alternate FCF available.
+ */
+static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+	int error;
+
+	mutex_lock(&fip->ctlr_mutex);
+	spin_lock_bh(&fip->ctlr_lock);
+	LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
+	fcf = fcoe_ctlr_select(fip);
+	if (!fcf || fcf->flogi_sent) {
+		kfree_skb(fip->flogi_req);
+		fip->flogi_req = NULL;
+		error = -ENOENT;
+	} else {
+		fcoe_ctlr_solicit(fip, NULL);
+		error = fcoe_ctlr_flogi_send_locked(fip);
+	}
+	spin_unlock_bh(&fip->ctlr_lock);
+	mutex_unlock(&fip->ctlr_mutex);
+	return error;
+}
+
+
+/**
+ * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
+ * @fip: The FCoE controller that timed out
+ *
+ * Done here because fcoe_ctlr_els_send() can't get mutex.
+ *
+ * Called with ctlr_mutex held.  The caller must not hold ctlr_lock.
+ */
+static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
+{
+	struct fcoe_fcf *fcf;
+
+	spin_lock_bh(&fip->ctlr_lock);
+	fcf = fip->sel_fcf;
+	if (!fcf || !fip->flogi_req_send)
+		goto unlock;
+
+	LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
+
+	/*
+	 * If this FLOGI is being sent due to a timeout retry
+	 * to the same FCF as before, select a different FCF if possible.
+	 */
+	if (fcf->flogi_sent) {
+		LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
+		fcf = fcoe_ctlr_select(fip);
+		if (!fcf || fcf->flogi_sent) {
+			LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
+			list_for_each_entry(fcf, &fip->fcfs, list)
+				fcf->flogi_sent = 0;
+			fcf = fcoe_ctlr_select(fip);
+		}
+	}
+	if (fcf) {
+		fcoe_ctlr_flogi_send_locked(fip);
+		fip->flogi_req_send = 0;
+	} else /* XXX */
+		LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
+unlock:
+	spin_unlock_bh(&fip->ctlr_lock);
+}
+
+/**
+ * fcoe_ctlr_timeout() - FIP timeout handler
+ * @arg: The FCoE controller that timed out
+ */
+static void fcoe_ctlr_timeout(unsigned long arg)
+{
+	struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
+
+	schedule_work(&fip->timer_work);
+}
+
+/**
+ * fcoe_ctlr_timer_work() - Worker thread function for timer work
+ * @work: Handle to a FCoE controller
+ *
+ * Ages FCFs.  Triggers FCF selection if possible.
+ * Sends keep-alives and resets.
+ */
+static void fcoe_ctlr_timer_work(struct work_struct *work)
+{
+	struct fcoe_ctlr *fip;
+	struct fc_lport *vport;
+	u8 *mac;
+	u8 reset = 0;
+	u8 send_ctlr_ka = 0;
+	u8 send_port_ka = 0;
+	struct fcoe_fcf *sel;
+	struct fcoe_fcf *fcf;
+	unsigned long next_timer;
+
+	fip = container_of(work, struct fcoe_ctlr, timer_work);
+	if (fip->mode == FIP_MODE_VN2VN)
+		return fcoe_ctlr_vn_timeout(fip);
+	mutex_lock(&fip->ctlr_mutex);
+	if (fip->state == FIP_ST_DISABLED) {
+		mutex_unlock(&fip->ctlr_mutex);
+		return;
+	}
+
+	fcf = fip->sel_fcf;
+	next_timer = fcoe_ctlr_age_fcfs(fip);
+
+	sel = fip->sel_fcf;
+	if (!sel && fip->sel_time) {
+		if (time_after_eq(jiffies, fip->sel_time)) {
+			sel = fcoe_ctlr_select(fip);
+			fip->sel_time = 0;
+		} else if (time_after(next_timer, fip->sel_time))
+			next_timer = fip->sel_time;
+	}
+
+	if (sel && fip->flogi_req_send)
+		fcoe_ctlr_flogi_send(fip);
+	else if (!sel && fcf)
+		reset = 1;
+
+	if (sel && !sel->fd_flags) {
+		if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
+			fip->ctlr_ka_time = jiffies + sel->fka_period;
+			send_ctlr_ka = 1;
+		}
+		if (time_after(next_timer, fip->ctlr_ka_time))
+			next_timer = fip->ctlr_ka_time;
+
+		if (time_after_eq(jiffies, fip->port_ka_time)) {
+			fip->port_ka_time = jiffies +
+				msecs_to_jiffies(FIP_VN_KA_PERIOD);
+			send_port_ka = 1;
+		}
+		if (time_after(next_timer, fip->port_ka_time))
+			next_timer = fip->port_ka_time;
+	}
+	if (!list_empty(&fip->fcfs))
+		mod_timer(&fip->timer, next_timer);
+	mutex_unlock(&fip->ctlr_mutex);
+
+	if (reset) {
+		fc_lport_reset(fip->lp);
+		/* restart things with a solicitation */
+		fcoe_ctlr_solicit(fip, NULL);
+	}
+
+	if (send_ctlr_ka)
+		fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr);
+
+	if (send_port_ka) {
+		mutex_lock(&fip->lp->lp_mutex);
+		mac = fip->get_src_addr(fip->lp);
+		fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac);
+		list_for_each_entry(vport, &fip->lp->vports, list) {
+			mac = fip->get_src_addr(vport);
+			fcoe_ctlr_send_keep_alive(fip, vport, 1, mac);
+		}
+		mutex_unlock(&fip->lp->lp_mutex);
+	}
+}
+
+/**
+ * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames
+ * @recv_work: Handle to a FCoE controller
+ */
+static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
+{
+	struct fcoe_ctlr *fip;
+	struct sk_buff *skb;
+
+	fip = container_of(recv_work, struct fcoe_ctlr, recv_work);
+	while ((skb = skb_dequeue(&fip->fip_recv_list)))
+		fcoe_ctlr_recv_handler(fip, skb);
+}
+
+/**
+ * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response
+ * @fip: The FCoE controller
+ * @fp:	 The FC frame to snoop
+ *
+ * Snoop potential response to FLOGI or even incoming FLOGI.
+ *
+ * The caller has checked that we are waiting for login as indicated
+ * by fip->flogi_oxid != FC_XID_UNKNOWN.
+ *
+ * The caller is responsible for freeing the frame.
+ * Fill in the granted_mac address.
+ *
+ * Return non-zero if the frame should not be delivered to libfc.
+ */
+int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport,
+			 struct fc_frame *fp)
+{
+	struct fc_frame_header *fh;
+	u8 op;
+	u8 *sa;
+
+	sa = eth_hdr(&fp->skb)->h_source;
+	fh = fc_frame_header_get(fp);
+	if (fh->fh_type != FC_TYPE_ELS)
+		return 0;
+
+	op = fc_frame_payload_op(fp);
+	if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
+	    fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
+
+		mutex_lock(&fip->ctlr_mutex);
+		if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) {
+			mutex_unlock(&fip->ctlr_mutex);
+			return -EINVAL;
+		}
+		fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
+		LIBFCOE_FIP_DBG(fip,
+				"received FLOGI LS_ACC using non-FIP mode\n");
+
+		/*
+		 * FLOGI accepted.
+		 * If the src mac addr is FC_OUI-based, then we mark the
+		 * address_mode flag to use FC_OUI-based Ethernet DA.
+		 * Otherwise we use the FCoE gateway addr
+		 */
+		if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) {
+			fcoe_ctlr_map_dest(fip);
+		} else {
+			memcpy(fip->dest_addr, sa, ETH_ALEN);
+			fip->map_dest = 0;
+		}
+		fip->flogi_oxid = FC_XID_UNKNOWN;
+		mutex_unlock(&fip->ctlr_mutex);
+		fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id);
+	} else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
+		/*
+		 * Save source MAC for point-to-point responses.
+		 */
+		mutex_lock(&fip->ctlr_mutex);
+		if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
+			memcpy(fip->dest_addr, sa, ETH_ALEN);
+			fip->map_dest = 0;
+			if (fip->state == FIP_ST_AUTO)
+				LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. "
+						"Setting non-FIP mode\n");
+			fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
+		}
+		mutex_unlock(&fip->ctlr_mutex);
+	}
+	return 0;
+}
+EXPORT_SYMBOL(fcoe_ctlr_recv_flogi);
+
+/**
+ * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN
+ * @mac:    The MAC address to convert
+ * @scheme: The scheme to use when converting
+ * @port:   The port indicator for converting
+ *
+ * Returns: u64 fc world wide name
+ */
+u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
+		      unsigned int scheme, unsigned int port)
+{
+	u64 wwn;
+	u64 host_mac;
+
+	/* The MAC is in NO, so flip only the low 48 bits */
+	host_mac = ((u64) mac[0] << 40) |
+		((u64) mac[1] << 32) |
+		((u64) mac[2] << 24) |
+		((u64) mac[3] << 16) |
+		((u64) mac[4] << 8) |
+		(u64) mac[5];
+
+	WARN_ON(host_mac >= (1ULL << 48));
+	wwn = host_mac | ((u64) scheme << 60);
+	switch (scheme) {
+	case 1:
+		WARN_ON(port != 0);
+		break;
+	case 2:
+		WARN_ON(port >= 0xfff);
+		wwn |= (u64) port << 48;
+		break;
+	default:
+		WARN_ON(1);
+		break;
+	}
+
+	return wwn;
+}
+EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
+
+/**
+ * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv
+ * @rdata: libfc remote port
+ */
+static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
+{
+	return (struct fcoe_rport *)(rdata + 1);
+}
+
+/**
+ * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply.
+ * @fip: The FCoE controller
+ * @sub: sub-opcode for probe request, reply, or advertisement.
+ * @dest: The destination Ethernet MAC address
+ * @min_len: minimum size of the Ethernet payload to be sent
+ */
+static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
+			      enum fip_vn2vn_subcode sub,
+			      const u8 *dest, size_t min_len)
+{
+	struct sk_buff *skb;
+	struct fip_frame {
+		struct ethhdr eth;
+		struct fip_header fip;
+		struct fip_mac_desc mac;
+		struct fip_wwn_desc wwnn;
+		struct fip_vn_desc vn;
+	} __packed * frame;
+	struct fip_fc4_feat *ff;
+	struct fip_size_desc *size;
+	u32 fcp_feat;
+	size_t len;
+	size_t dlen;
+
+	len = sizeof(*frame);
+	dlen = 0;
+	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
+		dlen = sizeof(struct fip_fc4_feat) +
+		       sizeof(struct fip_size_desc);
+		len += dlen;
+	}
+	dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn);
+	len = max(len, min_len + sizeof(struct ethhdr));
+
+	skb = dev_alloc_skb(len);
+	if (!skb)
+		return;
+
+	frame = (struct fip_frame *)skb->data;
+	memset(frame, 0, len);
+	memcpy(frame->eth.h_dest, dest, ETH_ALEN);
+	memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
+	frame->eth.h_proto = htons(ETH_P_FIP);
+
+	frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
+	frame->fip.fip_op = htons(FIP_OP_VN2VN);
+	frame->fip.fip_subcode = sub;
+	frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
+
+	frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
+	frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
+	memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
+
+	frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
+	frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW;
+	put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn);
+
+	frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID;
+	frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW;
+	hton24(frame->vn.fd_mac, FIP_VN_FC_MAP);
+	hton24(frame->vn.fd_mac + 3, fip->port_id);
+	hton24(frame->vn.fd_fc_id, fip->port_id);
+	put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn);
+
+	/*
+	 * For claims, add FC-4 features.
+	 * TBD: Add interface to get fc-4 types and features from libfc.
+	 */
+	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
+		ff = (struct fip_fc4_feat *)(frame + 1);
+		ff->fd_desc.fip_dtype = FIP_DT_FC4F;
+		ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW;
+		ff->fd_fts = fip->lp->fcts;
+
+		fcp_feat = 0;
+		if (fip->lp->service_params & FCP_SPPF_INIT_FCN)
+			fcp_feat |= FCP_FEAT_INIT;
+		if (fip->lp->service_params & FCP_SPPF_TARG_FCN)
+			fcp_feat |= FCP_FEAT_TARG;
+		fcp_feat <<= (FC_TYPE_FCP * 4) % 32;
+		ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat);
+
+		size = (struct fip_size_desc *)(ff + 1);
+		size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
+		size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW;
+		size->fd_size = htons(fcoe_ctlr_fcoe_size(fip));
+	}
+
+	skb_put(skb, len);
+	skb->protocol = htons(ETH_P_FIP);
+	skb_reset_mac_header(skb);
+	skb_reset_network_header(skb);
+
+	fip->send(fip, skb);
+}
+
+/**
+ * fcoe_ctlr_vn_rport_callback - Event handler for rport events.
+ * @lport: The lport which is receiving the event
+ * @rdata: remote port private data
+ * @event: The event that occurred
+ *
+ * Locking Note:  The rport lock must not be held when calling this function.
+ */
+static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport,
+					struct fc_rport_priv *rdata,
+					enum fc_rport_event event)
+{
+	struct fcoe_ctlr *fip = lport->disc.priv;
+	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
+
+	LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n",
+			rdata->ids.port_id, event);
+
+	mutex_lock(&fip->ctlr_mutex);
+	switch (event) {
+	case RPORT_EV_READY:
+		frport->login_count = 0;
+		break;
+	case RPORT_EV_LOGO:
+	case RPORT_EV_FAILED:
+	case RPORT_EV_STOP:
+		frport->login_count++;
+		if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) {
+			LIBFCOE_FIP_DBG(fip,
+					"rport FLOGI limited port_id %6.6x\n",
+					rdata->ids.port_id);
+			lport->tt.rport_logoff(rdata);
+		}
+		break;
+	default:
+		break;
+	}
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = {
+	.event_callback = fcoe_ctlr_vn_rport_callback,
+};
+
+/**
+ * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
+{
+	mutex_lock(&lport->disc.disc_mutex);
+	lport->disc.disc_callback = NULL;
+	mutex_unlock(&lport->disc.disc_mutex);
+}
+
+/**
+ * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called through the local port template for discovery.
+ * Called without the ctlr_mutex held.
+ */
+static void fcoe_ctlr_disc_stop(struct fc_lport *lport)
+{
+	struct fcoe_ctlr *fip = lport->disc.priv;
+
+	mutex_lock(&fip->ctlr_mutex);
+	fcoe_ctlr_disc_stop_locked(lport);
+	mutex_unlock(&fip->ctlr_mutex);
+}
+
+/**
+ * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called through the local port template for discovery.
+ * Called without the ctlr_mutex held.
+ */
+static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport)
+{
+	fcoe_ctlr_disc_stop(lport);
+	lport->tt.rport_flush_queue();
+	synchronize_rcu();
+}
+
+/**
+ * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id
+ * @fip: The FCoE controller
+ *
+ * Called with fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
+{
+	unsigned long wait;
+	u32 port_id;
+
+	fcoe_ctlr_disc_stop_locked(fip->lp);
+
+	/*
+	 * Get proposed port ID.
+	 * If this is the first try after link up, use any previous port_id.
+	 * If there was none, use the low bits of the port_name.
+	 * On subsequent tries, get the next random one.
+	 * Don't use reserved IDs, use another non-zero value, just as random.
+	 */
+	port_id = fip->port_id;
+	if (fip->probe_tries)
+		port_id = prandom32(&fip->rnd_state) & 0xffff;
+	else if (!port_id)
+		port_id = fip->lp->wwpn & 0xffff;
+	if (!port_id || port_id == 0xffff)
+		port_id = 1;
+	fip->port_id = port_id;
+
+	if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
+		fip->probe_tries++;
+		wait = random32() % FIP_VN_PROBE_WAIT;
+	} else
+		wait = FIP_VN_RLIM_INT;
+	mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
+	fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START);
+}
+
+/**
+ * fcoe_ctlr_vn_start() - Start in VN2VN mode
+ * @fip: The FCoE controller
+ *
+ * Called with fcoe_ctlr lock held.
+ */
+static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
+{
+	fip->probe_tries = 0;
+	prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
+	fcoe_ctlr_vn_restart(fip);
+}
+
+/**
+ * fcoe_ctlr_vn_parse - parse probe request or response
+ * @fip: The FCoE controller
+ * @skb: incoming packet
+ * @rdata: buffer for resulting parsed VN entry plus fcoe_rport
+ *
+ * Returns non-zero error number on error.
+ * Does not consume the packet.
+ */
+static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
+			      struct sk_buff *skb,
+			      struct fc_rport_priv *rdata)
+{
+	struct fip_header *fiph;
+	struct fip_desc *desc = NULL;
+	struct fip_mac_desc *macd = NULL;
+	struct fip_wwn_desc *wwn = NULL;
+	struct fip_vn_desc *vn = NULL;
+	struct fip_size_desc *size = NULL;
+	struct fcoe_rport *frport;
+	size_t rlen;
+	size_t dlen;
+	u32 desc_mask = 0;
+	u32 dtype;
+	u8 sub;
+
+	memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
+	frport = fcoe_ctlr_rport(rdata);
+
+	fiph = (struct fip_header *)skb->data;
+	frport->flags = ntohs(fiph->fip_flags);
+
+	sub = fiph->fip_subcode;
+	switch (sub) {
+	case FIP_SC_VN_PROBE_REQ:
+	case FIP_SC_VN_PROBE_REP:
+	case FIP_SC_VN_BEACON:
+		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
+			    BIT(FIP_DT_VN_ID);
+		break;
+	case FIP_SC_VN_CLAIM_NOTIFY:
+	case FIP_SC_VN_CLAIM_REP:
+		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
+			    BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) |
+			    BIT(FIP_DT_FCOE_SIZE);
+		break;
+	default:
+		LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
+		return -EINVAL;
+	}
+
+	rlen = ntohs(fiph->fip_dl_len) * 4;
+	if (rlen + sizeof(*fiph) > skb->len)
+		return -EINVAL;
+
+	desc = (struct fip_desc *)(fiph + 1);
+	while (rlen > 0) {
+		dlen = desc->fip_dlen * FIP_BPW;
+		if (dlen < sizeof(*desc) || dlen > rlen)
+			return -EINVAL;
+
+		dtype = desc->fip_dtype;
+		if (dtype < 32) {
+			if (!(desc_mask & BIT(dtype))) {
+				LIBFCOE_FIP_DBG(fip,
+						"unexpected or duplicated desc "
+						"desc type %u in "
+						"FIP VN2VN subtype %u\n",
+						dtype, sub);
+				return -EINVAL;
+			}
+			desc_mask &= ~BIT(dtype);
+		}
+
+		switch (dtype) {
+		case FIP_DT_MAC:
+			if (dlen != sizeof(struct fip_mac_desc))
+				goto len_err;
+			macd = (struct fip_mac_desc *)desc;
+			if (!is_valid_ether_addr(macd->fd_mac)) {
+				LIBFCOE_FIP_DBG(fip,
+					"Invalid MAC addr %pM in FIP VN2VN\n",
+					 macd->fd_mac);
+				return -EINVAL;
+			}
+			memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
+			break;
+		case FIP_DT_NAME:
+			if (dlen != sizeof(struct fip_wwn_desc))
+				goto len_err;
+			wwn = (struct fip_wwn_desc *)desc;
+			rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
+			break;
+		case FIP_DT_VN_ID:
+			if (dlen != sizeof(struct fip_vn_desc))
+				goto len_err;
+			vn = (struct fip_vn_desc *)desc;
+			memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
+			rdata->ids.port_id = ntoh24(vn->fd_fc_id);
+			rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
+			break;
+		case FIP_DT_FC4F:
+			if (dlen != sizeof(struct fip_fc4_feat))
+				goto len_err;
+			break;
+		case FIP_DT_FCOE_SIZE:
+			if (dlen != sizeof(struct fip_size_desc))
+				goto len_err;
+			size = (struct fip_size_desc *)desc;
+			frport->fcoe_len = ntohs(size->fd_size);
+			break;
+		default:
+			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
+					"in FIP probe\n", dtype);
+			/* standard says ignore unknown descriptors >= 128 */
+			if (dtype < FIP_DT_VENDOR_BASE)
+				return -EINVAL;
+			break;
+		}
+		desc = (struct fip_desc *)((char *)desc + dlen);
+		rlen -= dlen;
+	}
+	return 0;
+
+len_err:
+	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
+			dtype, dlen);
+	return -EINVAL;
+}
+
+/**
+ * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification.
+ * @fip: The FCoE controller
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
+{
+	fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0);
+	fip->sol_time = jiffies;
+}
+
+/**
+ * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
+ * @fip: The FCoE controller
+ * @rdata: parsed remote port with frport from the probe request
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
+				   struct fc_rport_priv *rdata)
+{
+	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
+
+	if (rdata->ids.port_id != fip->port_id)
+		return;
+
+	switch (fip->state) {
+	case FIP_ST_VNMP_CLAIM:
+	case FIP_ST_VNMP_UP:
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
+				  frport->enode_mac, 0);
+		break;
+	case FIP_ST_VNMP_PROBE1:
+	case FIP_ST_VNMP_PROBE2:
+		/*
+		 * Decide whether to reply to the Probe.
+		 * Our selected address is never a "recorded" one, so
+		 * only reply if our WWPN is greater and the
+		 * Probe's REC bit is not set.
+		 * If we don't reply, we will change our address.
+		 */
+		if (fip->lp->wwpn > rdata->ids.port_name &&
+		    !(frport->flags & FIP_FL_REC_OR_P2P)) {
+			fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
+					  frport->enode_mac, 0);
+			break;
+		}
+		/* fall through */
+	case FIP_ST_VNMP_START:
+		fcoe_ctlr_vn_restart(fip);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
+ * @fip: The FCoE controller
+ * @rdata: parsed remote port with frport from the probe request
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
+				   struct fc_rport_priv *rdata)
+{
+	if (rdata->ids.port_id != fip->port_id)
+		return;
+	switch (fip->state) {
+	case FIP_ST_VNMP_START:
+	case FIP_ST_VNMP_PROBE1:
+	case FIP_ST_VNMP_PROBE2:
+	case FIP_ST_VNMP_CLAIM:
+		fcoe_ctlr_vn_restart(fip);
+		break;
+	case FIP_ST_VNMP_UP:
+		fcoe_ctlr_vn_send_claim(fip);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
+ * @fip: The FCoE controller
+ * @new: newly-parsed remote port with frport as a template for new rdata
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fc_rport_identifiers *ids;
+	struct fcoe_rport *frport;
+	u32 port_id;
+
+	port_id = new->ids.port_id;
+	if (port_id == fip->port_id)
+		return;
+
+	mutex_lock(&lport->disc.disc_mutex);
+	rdata = lport->tt.rport_create(lport, port_id);
+	if (!rdata) {
+		mutex_unlock(&lport->disc.disc_mutex);
+		return;
+	}
+
+	rdata->ops = &fcoe_ctlr_vn_rport_ops;
+	rdata->disc_id = lport->disc.disc_id;
+
+	ids = &rdata->ids;
+	if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
+	    (ids->node_name != -1 && ids->node_name != new->ids.node_name))
+		lport->tt.rport_logoff(rdata);
+	ids->port_name = new->ids.port_name;
+	ids->node_name = new->ids.node_name;
+	mutex_unlock(&lport->disc.disc_mutex);
+
+	frport = fcoe_ctlr_rport(rdata);
+	LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
+			port_id, frport->fcoe_len ? "old" : "new");
+	*frport = *fcoe_ctlr_rport(new);
+	frport->time = 0;
+}
+
+/**
+ * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address
+ * @fip: The FCoE controller
+ * @port_id:  The port_id of the remote VN_node
+ * @mac: buffer which will hold the VN_NODE destination MAC address, if found.
+ *
+ * Returns non-zero error if no remote port found.
+ */
+static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+	int ret = -1;
+
+	rcu_read_lock();
+	rdata = lport->tt.rport_lookup(lport, port_id);
+	if (rdata) {
+		frport = fcoe_ctlr_rport(rdata);
+		memcpy(mac, frport->enode_mac, ETH_ALEN);
+		ret = 0;
+	}
+	rcu_read_unlock();
+	return ret;
+}
+
+/**
+ * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
+ * @fip: The FCoE controller
+ * @new: newly-parsed remote port with frport as a template for new rdata
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
+				      struct fc_rport_priv *new)
+{
+	struct fcoe_rport *frport = fcoe_ctlr_rport(new);
+
+	if (frport->flags & FIP_FL_REC_OR_P2P) {
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		return;
+	}
+	switch (fip->state) {
+	case FIP_ST_VNMP_START:
+	case FIP_ST_VNMP_PROBE1:
+	case FIP_ST_VNMP_PROBE2:
+		if (new->ids.port_id == fip->port_id)
+			fcoe_ctlr_vn_restart(fip);
+		break;
+	case FIP_ST_VNMP_CLAIM:
+	case FIP_ST_VNMP_UP:
+		if (new->ids.port_id == fip->port_id) {
+			if (new->ids.port_name > fip->lp->wwpn) {
+				fcoe_ctlr_vn_restart(fip);
+				break;
+			}
+			fcoe_ctlr_vn_send_claim(fip);
+			break;
+		}
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
+				  min((u32)frport->fcoe_len,
+				      fcoe_ctlr_fcoe_size(fip)));
+		fcoe_ctlr_vn_add(fip, new);
+		break;
+	default:
+		break;
+	}
+}
+
+/**
+ * fcoe_ctlr_vn_claim_resp() - handle received Claim Response
+ * @fip: The FCoE controller that received the frame
+ * @new: newly-parsed remote port with frport from the Claim Response
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
+				    struct fc_rport_priv *new)
+{
+	LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
+			new->ids.port_id, fcoe_ctlr_state(fip->state));
+	if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
+		fcoe_ctlr_vn_add(fip, new);
+}
+
+/**
+ * fcoe_ctlr_vn_beacon() - handle received beacon.
+ * @fip: The FCoE controller that received the frame
+ * @new: newly-parsed remote port with frport from the Beacon
+ *
+ * Called with ctlr_mutex held.
+ */
+static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
+				struct fc_rport_priv *new)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+
+	frport = fcoe_ctlr_rport(new);
+	if (frport->flags & FIP_FL_REC_OR_P2P) {
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		return;
+	}
+	mutex_lock(&lport->disc.disc_mutex);
+	rdata = lport->tt.rport_lookup(lport, new->ids.port_id);
+	if (rdata)
+		kref_get(&rdata->kref);
+	mutex_unlock(&lport->disc.disc_mutex);
+	if (rdata) {
+		if (rdata->ids.node_name == new->ids.node_name &&
+		    rdata->ids.port_name == new->ids.port_name) {
+			frport = fcoe_ctlr_rport(rdata);
+			if (!frport->time && fip->state == FIP_ST_VNMP_UP)
+				lport->tt.rport_login(rdata);
+			frport->time = jiffies;
+		}
+		kref_put(&rdata->kref, lport->tt.rport_destroy);
+		return;
+	}
+	if (fip->state != FIP_ST_VNMP_UP)
+		return;
+
+	/*
+	 * Beacon from a new neighbor.
+	 * Send a claim notify if one hasn't been sent recently.
+	 * Don't add the neighbor yet.
+	 */
+	LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
+			new->ids.port_id);
+	if (time_after(jiffies,
+		       fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
+		fcoe_ctlr_vn_send_claim(fip);
+}
+
+/**
+ * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons
+ * @fip: The FCoE controller
+ *
+ * Called with ctlr_mutex held.
+ * Called only in state FIP_ST_VNMP_UP.
+ * Returns the soonest time for next age-out or a time far in the future.
+ */
+static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+	unsigned long next_time;
+	unsigned long deadline;
+
+	next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
+	mutex_lock(&lport->disc.disc_mutex);
+	list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
+		frport = fcoe_ctlr_rport(rdata);
+		if (!frport->time)
+			continue;
+		deadline = frport->time +
+			   msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
+		if (time_after_eq(jiffies, deadline)) {
+			frport->time = 0;
+			LIBFCOE_FIP_DBG(fip,
+				"port %16.16llx fc_id %6.6x beacon expired\n",
+				rdata->ids.port_name, rdata->ids.port_id);
+			lport->tt.rport_logoff(rdata);
+		} else if (time_before(deadline, next_time))
+			next_time = deadline;
+	}
+	mutex_unlock(&lport->disc.disc_mutex);
+	return next_time;
+}
+
+/**
+ * fcoe_ctlr_vn_recv() - Receive a FIP frame
+ * @fip: The FCoE controller that received the frame
+ * @skb: The received FIP frame
+ *
+ * Returns non-zero if the frame is dropped.
+ * Always consumes the frame.
+ */
+static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
+{
+	struct fip_header *fiph;
+	enum fip_vn2vn_subcode sub;
+	struct {
+		struct fc_rport_priv rdata;
+		struct fcoe_rport frport;
+	} buf;
+	int rc;
+
+	fiph = (struct fip_header *)skb->data;
+	sub = fiph->fip_subcode;
+
+	rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
+	if (rc) {
+		LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
+		goto drop;
+	}
+
+	mutex_lock(&fip->ctlr_mutex);
+	switch (sub) {
+	case FIP_SC_VN_PROBE_REQ:
+		fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_PROBE_REP:
+		fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_CLAIM_NOTIFY:
+		fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_CLAIM_REP:
+		fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
+		break;
+	case FIP_SC_VN_BEACON:
+		fcoe_ctlr_vn_beacon(fip, &buf.rdata);
+		break;
+	default:
+		LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
+		rc = -1;
+		break;
+	}
+	mutex_unlock(&fip->ctlr_mutex);
+drop:
+	kfree_skb(skb);
+	return rc;
+}
+
+/**
+ * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
+ * @lport: The local port
+ * @fp: The received frame
+ *
+ * This should never be called since we don't see RSCNs or other
+ * fabric-generated ELSes.
+ */
+static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp)
+{
+	struct fc_seq_els_data rjt_data;
+
+	rjt_data.reason = ELS_RJT_UNSUP;
+	rjt_data.explan = ELS_EXPL_NONE;
+	lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
+	fc_frame_free(fp);
+}
+
+/**
+ * fcoe_ctlr_disc_recv - start discovery for VN2VN mode.
+ * @fip: The FCoE controller
+ *
+ * This sets a flag indicating that remote ports should be created
+ * and started for the peers we discover.  We use the disc_callback
+ * pointer as that flag.  Peers already discovered are created here.
+ *
+ * The lport lock is held during this call. The callback must be done
+ * later, without holding either the lport or discovery locks.
+ * The fcoe_ctlr lock may also be held during this call.
+ */
+static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *,
+						  enum fc_disc_event),
+				 struct fc_lport *lport)
+{
+	struct fc_disc *disc = &lport->disc;
+	struct fcoe_ctlr *fip = disc->priv;
+
+	mutex_lock(&disc->disc_mutex);
+	disc->disc_callback = callback;
+	disc->disc_id = (disc->disc_id + 2) | 1;
+	disc->pending = 1;
+	schedule_work(&fip->timer_work);
+	mutex_unlock(&disc->disc_mutex);
+}
+
+/**
+ * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state.
+ * @fip: The FCoE controller
+ *
+ * Starts the FLOGI and PLOGI login process to each discovered rport for which
+ * we've received at least one beacon.
+ * Performs the discovery complete callback.
+ */
+static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
+{
+	struct fc_lport *lport = fip->lp;
+	struct fc_disc *disc = &lport->disc;
+	struct fc_rport_priv *rdata;
+	struct fcoe_rport *frport;
+	void (*callback)(struct fc_lport *, enum fc_disc_event);
+
+	mutex_lock(&disc->disc_mutex);
+	callback = disc->pending ? disc->disc_callback : NULL;
+	disc->pending = 0;
+	list_for_each_entry_rcu(rdata, &disc->rports, peers) {
+		frport = fcoe_ctlr_rport(rdata);
+		if (frport->time)
+			lport->tt.rport_login(rdata);
+	}
+	mutex_unlock(&disc->disc_mutex);
+	if (callback)
+		callback(lport, DISC_EV_SUCCESS);
+}
+
+/**
+ * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode.
+ * @fip: The FCoE controller
+ */
+static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
+{
+	unsigned long next_time;
+	u8 mac[ETH_ALEN];
+	u32 new_port_id = 0;
+
+	mutex_lock(&fip->ctlr_mutex);
+	switch (fip->state) {
+	case FIP_ST_VNMP_START:
+		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
+		break;
+	case FIP_ST_VNMP_PROBE1:
+		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
+		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
+		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+		break;
+	case FIP_ST_VNMP_PROBE2:
+		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM);
+		new_port_id = fip->port_id;
+		hton24(mac, FIP_VN_FC_MAP);
+		hton24(mac + 3, new_port_id);
+		fcoe_ctlr_map_dest(fip);
+		fip->update_mac(fip->lp, mac);
+		fcoe_ctlr_vn_send_claim(fip);
+		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+		break;
+	case FIP_ST_VNMP_CLAIM:
+		/*
+		 * This may be invoked either by starting discovery so don't
+		 * go to the next state unless it's been long enough.
+		 */
+		next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+		if (time_after_eq(jiffies, next_time)) {
+			fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
+			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
+					  fcoe_all_vn2vn, 0);
+			next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
+			fip->port_ka_time = next_time;
+		}
+		fcoe_ctlr_vn_disc(fip);
+		break;
+	case FIP_ST_VNMP_UP:
+		next_time = fcoe_ctlr_vn_age(fip);
+		if (time_after_eq(jiffies, fip->port_ka_time)) {
+			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
+					  fcoe_all_vn2vn, 0);
+			fip->port_ka_time = jiffies +
+				 msecs_to_jiffies(FIP_VN_BEACON_INT +
+					(random32() % FIP_VN_BEACON_FUZZ));
+		}
+		if (time_before(fip->port_ka_time, next_time))
+			next_time = fip->port_ka_time;
+		break;
+	case FIP_ST_LINK_WAIT:
+		goto unlock;
+	default:
+		WARN(1, "unexpected state %d\n", fip->state);
+		goto unlock;
+	}
+	mod_timer(&fip->timer, next_time);
+unlock:
+	mutex_unlock(&fip->ctlr_mutex);
+
+	/* If port ID is new, notify local port after dropping ctlr_mutex */
+	if (new_port_id)
+		fc_lport_set_local_id(fip->lp, new_port_id);
+}
+
+/**
+ * fcoe_libfc_config() - Sets up libfc related properties for local port
+ * @lp: The local port to configure libfc for
+ * @fip: The FCoE controller in use by the local port
+ * @tt: The libfc function template
+ * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
+ *
+ * Returns : 0 for success
+ */
+int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
+		      const struct libfc_function_template *tt, int init_fcp)
+{
+	/* Set the function pointers set by the LLDD */
+	memcpy(&lport->tt, tt, sizeof(*tt));
+	if (init_fcp && fc_fcp_init(lport))
+		return -ENOMEM;
+	fc_exch_init(lport);
+	fc_elsct_init(lport);
+	fc_lport_init(lport);
+	if (fip->mode == FIP_MODE_VN2VN)
+		lport->rport_priv_size = sizeof(struct fcoe_rport);
+	fc_rport_init(lport);
+	if (fip->mode == FIP_MODE_VN2VN) {
+		lport->point_to_multipoint = 1;
+		lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
+		lport->tt.disc_start = fcoe_ctlr_disc_start;
+		lport->tt.disc_stop = fcoe_ctlr_disc_stop;
+		lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
+		mutex_init(&lport->disc.disc_mutex);
+		INIT_LIST_HEAD(&lport->disc.rports);
+		lport->disc.priv = fip;
+	} else {
+		fc_disc_init(lport);
+	}
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_libfc_config);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe.h linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe.h
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,7 +24,7 @@
 #include <linux/kthread.h>
 
 #define FCOE_MAX_QUEUE_DEPTH	256
-#define FCOE_LOW_QUEUE_DEPTH	32
+#define FCOE_MIN_QUEUE_DEPTH	32
 
 #define FCOE_WORD_TO_BYTE	4
 
@@ -40,12 +40,6 @@
 #define FCOE_MIN_XID		0x0000	/* the min xid supported by fcoe_sw */
 #define FCOE_MAX_XID		0x0FFF	/* the max xid supported by fcoe_sw */
 
-/*
- * Max MTU for FCoE: 14 (FCoE header) + 24 (FC header) + 2112 (max FC payload)
- * + 4 (FC CRC) + 4 (FCoE trailer) =  2158 bytes
- */
-#define FCOE_MTU	2158
-
 unsigned int fcoe_debug_logging;
 module_param_named(debug_logging, fcoe_debug_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
@@ -71,21 +65,6 @@
 				  netdev->name, ##args);)
 
 /**
- * struct fcoe_percpu_s - The per-CPU context for FCoE receive threads
- * @thread:	    The thread context
- * @fcoe_rx_list:   The queue of pending packets to process
- * @page:	    The memory page for calculating frame trailer CRCs
- * @crc_eof_offset: The offset into the CRC page pointing to available
- *		    memory for a new trailer
- */
-struct fcoe_percpu_s {
-	struct task_struct *thread;
-	struct sk_buff_head fcoe_rx_list;
-	struct page *crc_eof_page;
-	int crc_eof_offset;
-};
-
-/**
  * struct fcoe_interface - A FCoE interface
  * @list:	      Handle for a list of FCoE interfaces
  * @netdev:	      The associated net device
@@ -108,30 +87,6 @@
 	struct kref	   kref;
 };
 
-/**
- * struct fcoe_port - The FCoE private structure
- * @fcoe:		       The associated fcoe interface
- * @lport:		       The associated local port
- * @fcoe_pending_queue:	       The pending Rx queue of skbs
- * @fcoe_pending_queue_active: Indicates if the pending queue is active
- * @timer:		       The queue timer
- * @destroy_work:	       Handle for work context
- *			       (to prevent RTNL deadlocks)
- * @data_srt_addr:	       Source address for data
- *
- * An instance of this structure is to be allocated along with the
- * Scsi_Host and libfc fc_lport structures.
- */
-struct fcoe_port {
-	struct fcoe_interface *fcoe;
-	struct fc_lport	      *lport;
-	struct sk_buff_head   fcoe_pending_queue;
-	u8		      fcoe_pending_queue_active;
-	struct timer_list     timer;
-	struct work_struct    destroy_work;
-	u8		      data_src_addr[ETH_ALEN];
-};
-
 #define fcoe_from_ctlr(fip) container_of(fip, struct fcoe_interface, ctlr)
 
 /**
@@ -140,7 +95,8 @@
  */
 static inline struct net_device *fcoe_netdev(const struct fc_lport *lport)
 {
-	return ((struct fcoe_port *)lport_priv(lport))->fcoe->netdev;
+	return ((struct fcoe_interface *)
+			((struct fcoe_port *)lport_priv(lport))->priv)->netdev;
 }
 
 #endif /* _FCOE_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe_transport.c linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe_transport.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/fcoe_transport.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/fcoe_transport.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,770 @@
+/*
+ * Copyright(c) 2008 - 2011 Intel Corporation. All rights reserved.
+ *
+ * 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.
+ *
+ * Maintained at www.Open-FCoE.org
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/netdevice.h>
+#include <linux/errno.h>
+#include <linux/crc32.h>
+#include <scsi/libfcoe.h>
+
+#include "libfcoe.h"
+
+MODULE_AUTHOR("Open-FCoE.org");
+MODULE_DESCRIPTION("FIP discovery protocol and FCoE transport for FCoE HBAs");
+MODULE_LICENSE("GPL v2");
+
+static int fcoe_transport_create(const char *, struct kernel_param *);
+static int fcoe_transport_destroy(const char *, struct kernel_param *);
+static int fcoe_transport_show(char *buffer, const struct kernel_param *kp);
+static struct fcoe_transport *fcoe_transport_lookup(struct net_device *device);
+static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *device);
+static int fcoe_transport_enable(const char *, struct kernel_param *);
+static int fcoe_transport_disable(const char *, struct kernel_param *);
+static int libfcoe_device_notification(struct notifier_block *notifier,
+				    ulong event, void *ptr);
+
+static LIST_HEAD(fcoe_transports);
+static DEFINE_MUTEX(ft_mutex);
+static LIST_HEAD(fcoe_netdevs);
+static DEFINE_MUTEX(fn_mutex);
+
+unsigned int libfcoe_debug_logging;
+module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
+
+module_param_call(show, NULL, fcoe_transport_show, NULL, S_IRUSR);
+__MODULE_PARM_TYPE(show, "string");
+MODULE_PARM_DESC(show, " Show attached FCoE transports");
+
+module_param_call(create, fcoe_transport_create, NULL,
+		  (void *)FIP_MODE_FABRIC, S_IWUSR);
+__MODULE_PARM_TYPE(create, "string");
+MODULE_PARM_DESC(create, " Creates fcoe instance on a ethernet interface");
+
+module_param_call(create_vn2vn, fcoe_transport_create, NULL,
+		  (void *)FIP_MODE_VN2VN, S_IWUSR);
+__MODULE_PARM_TYPE(create_vn2vn, "string");
+MODULE_PARM_DESC(create_vn2vn, " Creates a VN_node to VN_node FCoE instance "
+		 "on an Ethernet interface");
+
+module_param_call(destroy, fcoe_transport_destroy, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(destroy, "string");
+MODULE_PARM_DESC(destroy, " Destroys fcoe instance on a ethernet interface");
+
+module_param_call(enable, fcoe_transport_enable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(enable, "string");
+MODULE_PARM_DESC(enable, " Enables fcoe on a ethernet interface.");
+
+module_param_call(disable, fcoe_transport_disable, NULL, NULL, S_IWUSR);
+__MODULE_PARM_TYPE(disable, "string");
+MODULE_PARM_DESC(disable, " Disables fcoe on a ethernet interface.");
+
+/* notification function for packets from net device */
+static struct notifier_block libfcoe_notifier = {
+	.notifier_call = libfcoe_device_notification,
+};
+
+/**
+ * fcoe_fc_crc() - Calculates the CRC for a given frame
+ * @fp: The frame to be checksumed
+ *
+ * This uses crc32() routine to calculate the CRC for a frame
+ *
+ * Return: The 32 bit CRC value
+ */
+u32 fcoe_fc_crc(struct fc_frame *fp)
+{
+	struct sk_buff *skb = fp_skb(fp);
+	struct skb_frag_struct *frag;
+	unsigned char *data;
+	unsigned long off, len, clen;
+	u32 crc;
+	unsigned i;
+
+	crc = crc32(~0, skb->data, skb_headlen(skb));
+
+	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+		frag = &skb_shinfo(skb)->frags[i];
+		off = frag->page_offset;
+		len = frag->size;
+		while (len > 0) {
+			clen = min(len, PAGE_SIZE - (off & ~PAGE_MASK));
+			data = kmap_atomic(frag->page + (off >> PAGE_SHIFT),
+					   KM_SKB_DATA_SOFTIRQ);
+			crc = crc32(crc, data + (off & ~PAGE_MASK), clen);
+			kunmap_atomic(data, KM_SKB_DATA_SOFTIRQ);
+			off += clen;
+			len -= clen;
+		}
+	}
+	return crc;
+}
+EXPORT_SYMBOL_GPL(fcoe_fc_crc);
+
+/**
+ * fcoe_start_io() - Start FCoE I/O
+ * @skb: The packet to be transmitted
+ *
+ * This routine is called from the net device to start transmitting
+ * FCoE packets.
+ *
+ * Returns: 0 for success
+ */
+int fcoe_start_io(struct sk_buff *skb)
+{
+	struct sk_buff *nskb;
+	int rc;
+
+	nskb = skb_clone(skb, GFP_ATOMIC);
+	if (!nskb)
+		return -ENOMEM;
+	rc = dev_queue_xmit(nskb);
+	if (rc != 0)
+		return rc;
+	kfree_skb(skb);
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_start_io);
+
+
+/**
+ * fcoe_clean_pending_queue() - Dequeue a skb and free it
+ * @lport: The local port to dequeue a skb on
+ */
+void fcoe_clean_pending_queue(struct fc_lport *lport)
+{
+	struct fcoe_port  *port = lport_priv(lport);
+	struct sk_buff *skb;
+
+	spin_lock_bh(&port->fcoe_pending_queue.lock);
+	while ((skb = __skb_dequeue(&port->fcoe_pending_queue)) != NULL) {
+		spin_unlock_bh(&port->fcoe_pending_queue.lock);
+		kfree_skb(skb);
+		spin_lock_bh(&port->fcoe_pending_queue.lock);
+	}
+	spin_unlock_bh(&port->fcoe_pending_queue.lock);
+}
+EXPORT_SYMBOL_GPL(fcoe_clean_pending_queue);
+
+/**
+ * fcoe_check_wait_queue() - Attempt to clear the transmit backlog
+ * @lport: The local port whose backlog is to be cleared
+ *
+ * This empties the wait_queue, dequeues the head of the wait_queue queue
+ * and calls fcoe_start_io() for each packet. If all skb have been
+ * transmitted it returns the qlen. If an error occurs it restores
+ * wait_queue (to try again later) and returns -1.
+ *
+ * The wait_queue is used when the skb transmit fails. The failed skb
+ * will go in the wait_queue which will be emptied by the timer function or
+ * by the next skb transmit.
+ */
+void fcoe_check_wait_queue(struct fc_lport *lport, struct sk_buff *skb)
+{
+	struct fcoe_port *port = lport_priv(lport);
+	int rc;
+
+	spin_lock_bh(&port->fcoe_pending_queue.lock);
+
+	if (skb)
+		__skb_queue_tail(&port->fcoe_pending_queue, skb);
+
+	if (port->fcoe_pending_queue_active)
+		goto out;
+	port->fcoe_pending_queue_active = 1;
+
+	while (port->fcoe_pending_queue.qlen) {
+		/* keep qlen > 0 until fcoe_start_io succeeds */
+		port->fcoe_pending_queue.qlen++;
+		skb = __skb_dequeue(&port->fcoe_pending_queue);
+
+		spin_unlock_bh(&port->fcoe_pending_queue.lock);
+		rc = fcoe_start_io(skb);
+		spin_lock_bh(&port->fcoe_pending_queue.lock);
+
+		if (rc) {
+			__skb_queue_head(&port->fcoe_pending_queue, skb);
+			/* undo temporary increment above */
+			port->fcoe_pending_queue.qlen--;
+			break;
+		}
+		/* undo temporary increment above */
+		port->fcoe_pending_queue.qlen--;
+	}
+
+	if (port->fcoe_pending_queue.qlen < port->min_queue_depth)
+		lport->qfull = 0;
+	if (port->fcoe_pending_queue.qlen && !timer_pending(&port->timer))
+		mod_timer(&port->timer, jiffies + 2);
+	port->fcoe_pending_queue_active = 0;
+out:
+	if (port->fcoe_pending_queue.qlen > port->max_queue_depth)
+		lport->qfull = 1;
+	spin_unlock_bh(&port->fcoe_pending_queue.lock);
+}
+EXPORT_SYMBOL_GPL(fcoe_check_wait_queue);
+
+/**
+ * fcoe_queue_timer() - The fcoe queue timer
+ * @lport: The local port
+ *
+ * Calls fcoe_check_wait_queue on timeout
+ */
+void fcoe_queue_timer(ulong lport)
+{
+	fcoe_check_wait_queue((struct fc_lport *)lport, NULL);
+}
+EXPORT_SYMBOL_GPL(fcoe_queue_timer);
+
+/**
+ * fcoe_get_paged_crc_eof() - Allocate a page to be used for the trailer CRC
+ * @skb:  The packet to be transmitted
+ * @tlen: The total length of the trailer
+ * @fps:  The fcoe context
+ *
+ * This routine allocates a page for frame trailers. The page is re-used if
+ * there is enough room left on it for the current trailer. If there isn't
+ * enough buffer left a new page is allocated for the trailer. Reference to
+ * the page from this function as well as the skbs using the page fragments
+ * ensure that the page is freed at the appropriate time.
+ *
+ * Returns: 0 for success
+ */
+int fcoe_get_paged_crc_eof(struct sk_buff *skb, int tlen,
+			   struct fcoe_percpu_s *fps)
+{
+	struct page *page;
+
+	page = fps->crc_eof_page;
+	if (!page) {
+		page = alloc_page(GFP_ATOMIC);
+		if (!page)
+			return -ENOMEM;
+
+		fps->crc_eof_page = page;
+		fps->crc_eof_offset = 0;
+	}
+
+	get_page(page);
+	skb_fill_page_desc(skb, skb_shinfo(skb)->nr_frags, page,
+			   fps->crc_eof_offset, tlen);
+	skb->len += tlen;
+	skb->data_len += tlen;
+	skb->truesize += tlen;
+	fps->crc_eof_offset += sizeof(struct fcoe_crc_eof);
+
+	if (fps->crc_eof_offset >= PAGE_SIZE) {
+		fps->crc_eof_page = NULL;
+		fps->crc_eof_offset = 0;
+		put_page(page);
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(fcoe_get_paged_crc_eof);
+
+/**
+ * fcoe_transport_lookup - find an fcoe transport that matches a netdev
+ * @netdev: The netdev to look for from all attached transports
+ *
+ * Returns : ptr to the fcoe transport that supports this netdev or NULL
+ * if not found.
+ *
+ * The ft_mutex should be held when this is called
+ */
+static struct fcoe_transport *fcoe_transport_lookup(struct net_device *netdev)
+{
+	struct fcoe_transport *ft = NULL;
+
+	list_for_each_entry(ft, &fcoe_transports, list)
+		if (ft->match && ft->match(netdev))
+			return ft;
+	return NULL;
+}
+
+/**
+ * fcoe_transport_attach - Attaches an FCoE transport
+ * @ft: The fcoe transport to be attached
+ *
+ * Returns : 0 for success
+ */
+int fcoe_transport_attach(struct fcoe_transport *ft)
+{
+	int rc = 0;
+
+	mutex_lock(&ft_mutex);
+	if (ft->attached) {
+		LIBFCOE_TRANSPORT_DBG("transport %s already attached\n",
+				       ft->name);
+		rc = -EEXIST;
+		goto out_attach;
+	}
+
+	/* Add default transport to the tail */
+	if (strcmp(ft->name, FCOE_TRANSPORT_DEFAULT))
+		list_add(&ft->list, &fcoe_transports);
+	else
+		list_add_tail(&ft->list, &fcoe_transports);
+
+	ft->attached = true;
+	LIBFCOE_TRANSPORT_DBG("attaching transport %s\n", ft->name);
+
+out_attach:
+	mutex_unlock(&ft_mutex);
+	return rc;
+}
+EXPORT_SYMBOL(fcoe_transport_attach);
+
+/**
+ * fcoe_transport_attach - Detaches an FCoE transport
+ * @ft: The fcoe transport to be attached
+ *
+ * Returns : 0 for success
+ */
+int fcoe_transport_detach(struct fcoe_transport *ft)
+{
+	int rc = 0;
+
+	mutex_lock(&ft_mutex);
+	if (!ft->attached) {
+		LIBFCOE_TRANSPORT_DBG("transport %s already detached\n",
+			ft->name);
+		rc = -ENODEV;
+		goto out_attach;
+	}
+
+	list_del(&ft->list);
+	ft->attached = false;
+	LIBFCOE_TRANSPORT_DBG("detaching transport %s\n", ft->name);
+
+out_attach:
+	mutex_unlock(&ft_mutex);
+	return rc;
+
+}
+EXPORT_SYMBOL(fcoe_transport_detach);
+
+static int fcoe_transport_show(char *buffer, const struct kernel_param *kp)
+{
+	int i, j;
+	struct fcoe_transport *ft = NULL;
+
+	i = j = sprintf(buffer, "Attached FCoE transports:");
+	mutex_lock(&ft_mutex);
+	list_for_each_entry(ft, &fcoe_transports, list) {
+		i += snprintf(&buffer[i], IFNAMSIZ, "%s ", ft->name);
+		if (i >= PAGE_SIZE)
+			break;
+	}
+	mutex_unlock(&ft_mutex);
+	if (i == j)
+		i += snprintf(&buffer[i], IFNAMSIZ, "none");
+	return i;
+}
+
+static int __init fcoe_transport_init(void)
+{
+	register_netdevice_notifier(&libfcoe_notifier);
+	return 0;
+}
+
+static int __exit fcoe_transport_exit(void)
+{
+	struct fcoe_transport *ft;
+
+	unregister_netdevice_notifier(&libfcoe_notifier);
+	mutex_lock(&ft_mutex);
+	list_for_each_entry(ft, &fcoe_transports, list)
+		printk(KERN_ERR "FCoE transport %s is still attached!\n",
+		      ft->name);
+	mutex_unlock(&ft_mutex);
+	return 0;
+}
+
+
+static int fcoe_add_netdev_mapping(struct net_device *netdev,
+					struct fcoe_transport *ft)
+{
+	struct fcoe_netdev_mapping *nm;
+
+	nm = kmalloc(sizeof(*nm), GFP_KERNEL);
+	if (!nm) {
+		printk(KERN_ERR "Unable to allocate netdev_mapping");
+		return -ENOMEM;
+	}
+
+	nm->netdev = netdev;
+	nm->ft = ft;
+
+	mutex_lock(&fn_mutex);
+	list_add(&nm->list, &fcoe_netdevs);
+	mutex_unlock(&fn_mutex);
+	return 0;
+}
+
+
+static void fcoe_del_netdev_mapping(struct net_device *netdev)
+{
+	struct fcoe_netdev_mapping *nm = NULL, *tmp;
+
+	mutex_lock(&fn_mutex);
+	list_for_each_entry_safe(nm, tmp, &fcoe_netdevs, list) {
+		if (nm->netdev == netdev) {
+			list_del(&nm->list);
+			kfree(nm);
+			mutex_unlock(&fn_mutex);
+			return;
+		}
+	}
+	mutex_unlock(&fn_mutex);
+}
+
+
+/**
+ * fcoe_netdev_map_lookup - find the fcoe transport that matches the netdev on which
+ * it was created
+ *
+ * Returns : ptr to the fcoe transport that supports this netdev or NULL
+ * if not found.
+ *
+ * The ft_mutex should be held when this is called
+ */
+static struct fcoe_transport *fcoe_netdev_map_lookup(struct net_device *netdev)
+{
+	struct fcoe_transport *ft = NULL;
+	struct fcoe_netdev_mapping *nm;
+
+	mutex_lock(&fn_mutex);
+	list_for_each_entry(nm, &fcoe_netdevs, list) {
+		if (netdev == nm->netdev) {
+			ft = nm->ft;
+			mutex_unlock(&fn_mutex);
+			return ft;
+		}
+	}
+
+	mutex_unlock(&fn_mutex);
+	return NULL;
+}
+
+/**
+ * fcoe_if_to_netdev() - Parse a name buffer to get a net device
+ * @buffer: The name of the net device
+ *
+ * Returns: NULL or a ptr to net_device
+ */
+static struct net_device *fcoe_if_to_netdev(const char *buffer)
+{
+	char *cp;
+	char ifname[IFNAMSIZ + 2];
+
+	if (buffer) {
+		strlcpy(ifname, buffer, IFNAMSIZ);
+		cp = ifname + strlen(ifname);
+		while (--cp >= ifname && *cp == '\n')
+			*cp = '\0';
+		return dev_get_by_name(&init_net, ifname);
+	}
+	return NULL;
+}
+
+/**
+ * libfcoe_device_notification() - Handler for net device events
+ * @notifier: The context of the notification
+ * @event:    The type of event
+ * @ptr:      The net device that the event was on
+ *
+ * This function is called by the Ethernet driver in case of link change event.
+ *
+ * Returns: 0 for success
+ */
+static int libfcoe_device_notification(struct notifier_block *notifier,
+				    ulong event, void *ptr)
+{
+	struct net_device *netdev = ptr;
+
+	switch (event) {
+	case NETDEV_UNREGISTER:
+		printk(KERN_ERR "libfcoe_device_notification: NETDEV_UNREGISTER %s\n",
+				netdev->name);
+		fcoe_del_netdev_mapping(netdev);
+		break;
+	}
+	return NOTIFY_OK;
+}
+
+
+/**
+ * fcoe_transport_create() - Create a fcoe interface
+ * @buffer: The name of the Ethernet interface to create on
+ * @kp:	    The associated kernel param
+ *
+ * Called from sysfs. This holds the ft_mutex while calling the
+ * registered fcoe transport's create function.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_create(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+	enum fip_state fip_mode = (enum fip_state)(long)kp->arg;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev) {
+		LIBFCOE_TRANSPORT_DBG("Invalid device %s.\n", buffer);
+		goto out_nodev;
+	}
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (ft) {
+		LIBFCOE_TRANSPORT_DBG("transport %s already has existing "
+				      "FCoE instance on %s.\n",
+				      ft->name, netdev->name);
+		rc = -EEXIST;
+		goto out_putdev;
+	}
+
+	ft = fcoe_transport_lookup(netdev);
+	if (!ft) {
+		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
+				      netdev->name);
+		goto out_putdev;
+	}
+
+	rc = fcoe_add_netdev_mapping(netdev, ft);
+	if (rc) {
+		LIBFCOE_TRANSPORT_DBG("failed to add new netdev mapping "
+				      "for FCoE transport %s for %s.\n",
+				      ft->name, netdev->name);
+		goto out_putdev;
+	}
+
+	/* pass to transport create */
+	rc = ft->create ? ft->create(netdev, fip_mode) : -ENODEV;
+	if (rc)
+		fcoe_del_netdev_mapping(netdev);
+
+	LIBFCOE_TRANSPORT_DBG("transport %s %s to create fcoe on %s.\n",
+			      ft->name, (rc) ? "failed" : "succeeded",
+			      netdev->name);
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * fcoe_transport_destroy() - Destroy a FCoE interface
+ * @buffer: The name of the Ethernet interface to be destroyed
+ * @kp:	    The associated kernel parameter
+ *
+ * Called from sysfs. This holds the ft_mutex while calling the
+ * registered fcoe transport's destroy function.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_destroy(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev) {
+		LIBFCOE_TRANSPORT_DBG("invalid device %s.\n", buffer);
+		goto out_nodev;
+	}
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (!ft) {
+		LIBFCOE_TRANSPORT_DBG("no FCoE transport found for %s.\n",
+				      netdev->name);
+		goto out_putdev;
+	}
+
+	/* pass to transport destroy */
+	rc = ft->destroy ? ft->destroy(netdev) : -ENODEV;
+	fcoe_del_netdev_mapping(netdev);
+	LIBFCOE_TRANSPORT_DBG("transport %s %s to destroy fcoe on %s.\n",
+			      ft->name, (rc) ? "failed" : "succeeded",
+			      netdev->name);
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * fcoe_transport_disable() - Disables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be disabled
+ * @kp:	    The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_disable(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev)
+		goto out_nodev;
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (!ft)
+		goto out_putdev;
+
+	rc = ft->disable ? ft->disable(netdev) : -ENODEV;
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * fcoe_transport_enable() - Enables a FCoE interface
+ * @buffer: The name of the Ethernet interface to be enabled
+ * @kp:     The associated kernel parameter
+ *
+ * Called from sysfs.
+ *
+ * Returns: 0 for success
+ */
+static int fcoe_transport_enable(const char *buffer, struct kernel_param *kp)
+{
+	int rc = -ENODEV;
+	struct net_device *netdev = NULL;
+	struct fcoe_transport *ft = NULL;
+
+	if (!mutex_trylock(&ft_mutex))
+		return restart_syscall();
+
+#ifdef CONFIG_LIBFCOE_MODULE
+	/*
+	 * Make sure the module has been initialized, and is not about to be
+	 * removed.  Module parameter sysfs files are writable before the
+	 * module_init function is called and after module_exit.
+	 */
+	if (THIS_MODULE->state != MODULE_STATE_LIVE)
+		goto out_nodev;
+#endif
+
+	netdev = fcoe_if_to_netdev(buffer);
+	if (!netdev)
+		goto out_nodev;
+
+	ft = fcoe_netdev_map_lookup(netdev);
+	if (!ft)
+		goto out_putdev;
+
+	rc = ft->enable ? ft->enable(netdev) : -ENODEV;
+
+out_putdev:
+	dev_put(netdev);
+out_nodev:
+	mutex_unlock(&ft_mutex);
+	if (rc == -ERESTARTSYS)
+		return restart_syscall();
+	else
+		return rc;
+}
+
+/**
+ * libfcoe_init() - Initialization routine for libfcoe.ko
+ */
+static int __init libfcoe_init(void)
+{
+	fcoe_transport_init();
+
+	return 0;
+}
+module_init(libfcoe_init);
+
+/**
+ * libfcoe_exit() - Tear down libfcoe.ko
+ */
+static void __exit libfcoe_exit(void)
+{
+	fcoe_transport_exit();
+}
+module_exit(libfcoe_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/libfcoe.c linux-libre-2.6.39-gnu/drivers/scsi/fcoe/libfcoe.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/libfcoe.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/libfcoe.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,2708 +0,0 @@
-/*
- * Copyright (c) 2008-2009 Cisco Systems, Inc.  All rights reserved.
- * Copyright (c) 2009 Intel Corporation.  All rights reserved.
- *
- * 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.
- *
- * Maintained at www.Open-FCoE.org
- */
-
-#include <linux/types.h>
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/timer.h>
-#include <linux/netdevice.h>
-#include <linux/etherdevice.h>
-#include <linux/ethtool.h>
-#include <linux/if_ether.h>
-#include <linux/if_vlan.h>
-#include <linux/errno.h>
-#include <linux/bitops.h>
-#include <linux/slab.h>
-#include <net/rtnetlink.h>
-
-#include <scsi/fc/fc_els.h>
-#include <scsi/fc/fc_fs.h>
-#include <scsi/fc/fc_fip.h>
-#include <scsi/fc/fc_encaps.h>
-#include <scsi/fc/fc_fcoe.h>
-#include <scsi/fc/fc_fcp.h>
-
-#include <scsi/libfc.h>
-#include <scsi/libfcoe.h>
-
-MODULE_AUTHOR("Open-FCoE.org");
-MODULE_DESCRIPTION("FIP discovery protocol support for FCoE HBAs");
-MODULE_LICENSE("GPL v2");
-
-#define	FCOE_CTLR_MIN_FKA	500		/* min keep alive (mS) */
-#define	FCOE_CTLR_DEF_FKA	FIP_DEF_FKA	/* default keep alive (mS) */
-
-static void fcoe_ctlr_timeout(unsigned long);
-static void fcoe_ctlr_timer_work(struct work_struct *);
-static void fcoe_ctlr_recv_work(struct work_struct *);
-static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *);
-
-static void fcoe_ctlr_vn_start(struct fcoe_ctlr *);
-static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *, struct sk_buff *);
-static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *);
-static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *, u32, u8 *);
-
-static u8 fcoe_all_fcfs[ETH_ALEN] = FIP_ALL_FCF_MACS;
-static u8 fcoe_all_enode[ETH_ALEN] = FIP_ALL_ENODE_MACS;
-static u8 fcoe_all_vn2vn[ETH_ALEN] = FIP_ALL_VN2VN_MACS;
-static u8 fcoe_all_p2p[ETH_ALEN] = FIP_ALL_P2P_MACS;
-
-unsigned int libfcoe_debug_logging;
-module_param_named(debug_logging, libfcoe_debug_logging, int, S_IRUGO|S_IWUSR);
-MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
-
-#define LIBFCOE_LOGGING	    0x01 /* General logging, not categorized */
-#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
-
-#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD)		\
-do {							\
-	if (unlikely(libfcoe_debug_logging & LEVEL))	\
-		do {					\
-			CMD;				\
-		} while (0);				\
-} while (0)
-
-#define LIBFCOE_DBG(fmt, args...)					\
-	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\
-			      printk(KERN_INFO "libfcoe: " fmt, ##args);)
-
-#define LIBFCOE_FIP_DBG(fip, fmt, args...)				\
-	LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING,			\
-			      printk(KERN_INFO "host%d: fip: " fmt, 	\
-				     (fip)->lp->host->host_no, ##args);)
-
-static const char *fcoe_ctlr_states[] = {
-	[FIP_ST_DISABLED] =	"DISABLED",
-	[FIP_ST_LINK_WAIT] =	"LINK_WAIT",
-	[FIP_ST_AUTO] =		"AUTO",
-	[FIP_ST_NON_FIP] =	"NON_FIP",
-	[FIP_ST_ENABLED] =	"ENABLED",
-	[FIP_ST_VNMP_START] =	"VNMP_START",
-	[FIP_ST_VNMP_PROBE1] =	"VNMP_PROBE1",
-	[FIP_ST_VNMP_PROBE2] =	"VNMP_PROBE2",
-	[FIP_ST_VNMP_CLAIM] =	"VNMP_CLAIM",
-	[FIP_ST_VNMP_UP] =	"VNMP_UP",
-};
-
-static const char *fcoe_ctlr_state(enum fip_state state)
-{
-	const char *cp = "unknown";
-
-	if (state < ARRAY_SIZE(fcoe_ctlr_states))
-		cp = fcoe_ctlr_states[state];
-	if (!cp)
-		cp = "unknown";
-	return cp;
-}
-
-/**
- * fcoe_ctlr_set_state() - Set and do debug printing for the new FIP state.
- * @fip: The FCoE controller
- * @state: The new state
- */
-static void fcoe_ctlr_set_state(struct fcoe_ctlr *fip, enum fip_state state)
-{
-	if (state == fip->state)
-		return;
-	if (fip->lp)
-		LIBFCOE_FIP_DBG(fip, "state %s -> %s\n",
-			fcoe_ctlr_state(fip->state), fcoe_ctlr_state(state));
-	fip->state = state;
-}
-
-/**
- * fcoe_ctlr_mtu_valid() - Check if a FCF's MTU is valid
- * @fcf: The FCF to check
- *
- * Return non-zero if FCF fcoe_size has been validated.
- */
-static inline int fcoe_ctlr_mtu_valid(const struct fcoe_fcf *fcf)
-{
-	return (fcf->flags & FIP_FL_SOL) != 0;
-}
-
-/**
- * fcoe_ctlr_fcf_usable() - Check if a FCF is usable
- * @fcf: The FCF to check
- *
- * Return non-zero if the FCF is usable.
- */
-static inline int fcoe_ctlr_fcf_usable(struct fcoe_fcf *fcf)
-{
-	u16 flags = FIP_FL_SOL | FIP_FL_AVAIL;
-
-	return (fcf->flags & flags) == flags;
-}
-
-/**
- * fcoe_ctlr_map_dest() - Set flag and OUI for mapping destination addresses
- * @fip: The FCoE controller
- */
-static void fcoe_ctlr_map_dest(struct fcoe_ctlr *fip)
-{
-	if (fip->mode == FIP_MODE_VN2VN)
-		hton24(fip->dest_addr, FIP_VN_FC_MAP);
-	else
-		hton24(fip->dest_addr, FIP_DEF_FC_MAP);
-	hton24(fip->dest_addr + 3, 0);
-	fip->map_dest = 1;
-}
-
-/**
- * fcoe_ctlr_init() - Initialize the FCoE Controller instance
- * @fip: The FCoE controller to initialize
- */
-void fcoe_ctlr_init(struct fcoe_ctlr *fip, enum fip_state mode)
-{
-	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
-	fip->mode = mode;
-	INIT_LIST_HEAD(&fip->fcfs);
-	mutex_init(&fip->ctlr_mutex);
-	spin_lock_init(&fip->ctlr_lock);
-	fip->flogi_oxid = FC_XID_UNKNOWN;
-	setup_timer(&fip->timer, fcoe_ctlr_timeout, (unsigned long)fip);
-	INIT_WORK(&fip->timer_work, fcoe_ctlr_timer_work);
-	INIT_WORK(&fip->recv_work, fcoe_ctlr_recv_work);
-	skb_queue_head_init(&fip->fip_recv_list);
-}
-EXPORT_SYMBOL(fcoe_ctlr_init);
-
-/**
- * fcoe_ctlr_reset_fcfs() - Reset and free all FCFs for a controller
- * @fip: The FCoE controller whose FCFs are to be reset
- *
- * Called with &fcoe_ctlr lock held.
- */
-static void fcoe_ctlr_reset_fcfs(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *next;
-
-	fip->sel_fcf = NULL;
-	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
-		list_del(&fcf->list);
-		kfree(fcf);
-	}
-	fip->fcf_count = 0;
-	fip->sel_time = 0;
-}
-
-/**
- * fcoe_ctlr_destroy() - Disable and tear down a FCoE controller
- * @fip: The FCoE controller to tear down
- *
- * This is called by FCoE drivers before freeing the &fcoe_ctlr.
- *
- * The receive handler will have been deleted before this to guarantee
- * that no more recv_work will be scheduled.
- *
- * The timer routine will simply return once we set FIP_ST_DISABLED.
- * This guarantees that no further timeouts or work will be scheduled.
- */
-void fcoe_ctlr_destroy(struct fcoe_ctlr *fip)
-{
-	cancel_work_sync(&fip->recv_work);
-	skb_queue_purge(&fip->fip_recv_list);
-
-	mutex_lock(&fip->ctlr_mutex);
-	fcoe_ctlr_set_state(fip, FIP_ST_DISABLED);
-	fcoe_ctlr_reset_fcfs(fip);
-	mutex_unlock(&fip->ctlr_mutex);
-	del_timer_sync(&fip->timer);
-	cancel_work_sync(&fip->timer_work);
-}
-EXPORT_SYMBOL(fcoe_ctlr_destroy);
-
-/**
- * fcoe_ctlr_announce() - announce new FCF selection
- * @fip: The FCoE controller
- *
- * Also sets the destination MAC for FCoE and control packets
- *
- * Called with neither ctlr_mutex nor ctlr_lock held.
- */
-static void fcoe_ctlr_announce(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *sel;
-	struct fcoe_fcf *fcf;
-
-	mutex_lock(&fip->ctlr_mutex);
-	spin_lock_bh(&fip->ctlr_lock);
-
-	kfree_skb(fip->flogi_req);
-	fip->flogi_req = NULL;
-	list_for_each_entry(fcf, &fip->fcfs, list)
-		fcf->flogi_sent = 0;
-
-	spin_unlock_bh(&fip->ctlr_lock);
-	sel = fip->sel_fcf;
-
-	if (sel && !compare_ether_addr(sel->fcf_mac, fip->dest_addr))
-		goto unlock;
-	if (!is_zero_ether_addr(fip->dest_addr)) {
-		printk(KERN_NOTICE "libfcoe: host%d: "
-		       "FIP Fibre-Channel Forwarder MAC %pM deselected\n",
-		       fip->lp->host->host_no, fip->dest_addr);
-		memset(fip->dest_addr, 0, ETH_ALEN);
-	}
-	if (sel) {
-		printk(KERN_INFO "libfcoe: host%d: FIP selected "
-		       "Fibre-Channel Forwarder MAC %pM\n",
-		       fip->lp->host->host_no, sel->fcf_mac);
-		memcpy(fip->dest_addr, sel->fcf_mac, ETH_ALEN);
-		fip->map_dest = 0;
-	}
-unlock:
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-/**
- * fcoe_ctlr_fcoe_size() - Return the maximum FCoE size required for VN_Port
- * @fip: The FCoE controller to get the maximum FCoE size from
- *
- * Returns the maximum packet size including the FCoE header and trailer,
- * but not including any Ethernet or VLAN headers.
- */
-static inline u32 fcoe_ctlr_fcoe_size(struct fcoe_ctlr *fip)
-{
-	/*
-	 * Determine the max FCoE frame size allowed, including
-	 * FCoE header and trailer.
-	 * Note:  lp->mfs is currently the payload size, not the frame size.
-	 */
-	return fip->lp->mfs + sizeof(struct fc_frame_header) +
-		sizeof(struct fcoe_hdr) + sizeof(struct fcoe_crc_eof);
-}
-
-/**
- * fcoe_ctlr_solicit() - Send a FIP solicitation
- * @fip: The FCoE controller to send the solicitation on
- * @fcf: The destination FCF (if NULL, a multicast solicitation is sent)
- */
-static void fcoe_ctlr_solicit(struct fcoe_ctlr *fip, struct fcoe_fcf *fcf)
-{
-	struct sk_buff *skb;
-	struct fip_sol {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct {
-			struct fip_mac_desc mac;
-			struct fip_wwn_desc wwnn;
-			struct fip_size_desc size;
-		} __attribute__((packed)) desc;
-	}  __attribute__((packed)) *sol;
-	u32 fcoe_size;
-
-	skb = dev_alloc_skb(sizeof(*sol));
-	if (!skb)
-		return;
-
-	sol = (struct fip_sol *)skb->data;
-
-	memset(sol, 0, sizeof(*sol));
-	memcpy(sol->eth.h_dest, fcf ? fcf->fcf_mac : fcoe_all_fcfs, ETH_ALEN);
-	memcpy(sol->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
-	sol->eth.h_proto = htons(ETH_P_FIP);
-
-	sol->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	sol->fip.fip_op = htons(FIP_OP_DISC);
-	sol->fip.fip_subcode = FIP_SC_SOL;
-	sol->fip.fip_dl_len = htons(sizeof(sol->desc) / FIP_BPW);
-	sol->fip.fip_flags = htons(FIP_FL_FPMA);
-	if (fip->spma)
-		sol->fip.fip_flags |= htons(FIP_FL_SPMA);
-
-	sol->desc.mac.fd_desc.fip_dtype = FIP_DT_MAC;
-	sol->desc.mac.fd_desc.fip_dlen = sizeof(sol->desc.mac) / FIP_BPW;
-	memcpy(sol->desc.mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-
-	sol->desc.wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
-	sol->desc.wwnn.fd_desc.fip_dlen = sizeof(sol->desc.wwnn) / FIP_BPW;
-	put_unaligned_be64(fip->lp->wwnn, &sol->desc.wwnn.fd_wwn);
-
-	fcoe_size = fcoe_ctlr_fcoe_size(fip);
-	sol->desc.size.fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
-	sol->desc.size.fd_desc.fip_dlen = sizeof(sol->desc.size) / FIP_BPW;
-	sol->desc.size.fd_size = htons(fcoe_size);
-
-	skb_put(skb, sizeof(*sol));
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	fip->send(fip, skb);
-
-	if (!fcf)
-		fip->sol_time = jiffies;
-}
-
-/**
- * fcoe_ctlr_link_up() - Start FCoE controller
- * @fip: The FCoE controller to start
- *
- * Called from the LLD when the network link is ready.
- */
-void fcoe_ctlr_link_up(struct fcoe_ctlr *fip)
-{
-	mutex_lock(&fip->ctlr_mutex);
-	if (fip->state == FIP_ST_NON_FIP || fip->state == FIP_ST_AUTO) {
-		mutex_unlock(&fip->ctlr_mutex);
-		fc_linkup(fip->lp);
-	} else if (fip->state == FIP_ST_LINK_WAIT) {
-		fcoe_ctlr_set_state(fip, fip->mode);
-		switch (fip->mode) {
-		default:
-			LIBFCOE_FIP_DBG(fip, "invalid mode %d\n", fip->mode);
-			/* fall-through */
-		case FIP_MODE_AUTO:
-			LIBFCOE_FIP_DBG(fip, "%s", "setting AUTO mode.\n");
-			/* fall-through */
-		case FIP_MODE_FABRIC:
-		case FIP_MODE_NON_FIP:
-			mutex_unlock(&fip->ctlr_mutex);
-			fc_linkup(fip->lp);
-			fcoe_ctlr_solicit(fip, NULL);
-			break;
-		case FIP_MODE_VN2VN:
-			fcoe_ctlr_vn_start(fip);
-			mutex_unlock(&fip->ctlr_mutex);
-			fc_linkup(fip->lp);
-			break;
-		}
-	} else
-		mutex_unlock(&fip->ctlr_mutex);
-}
-EXPORT_SYMBOL(fcoe_ctlr_link_up);
-
-/**
- * fcoe_ctlr_reset() - Reset a FCoE controller
- * @fip:       The FCoE controller to reset
- */
-static void fcoe_ctlr_reset(struct fcoe_ctlr *fip)
-{
-	fcoe_ctlr_reset_fcfs(fip);
-	del_timer(&fip->timer);
-	fip->ctlr_ka_time = 0;
-	fip->port_ka_time = 0;
-	fip->sol_time = 0;
-	fip->flogi_oxid = FC_XID_UNKNOWN;
-	fcoe_ctlr_map_dest(fip);
-}
-
-/**
- * fcoe_ctlr_link_down() - Stop a FCoE controller
- * @fip: The FCoE controller to be stopped
- *
- * Returns non-zero if the link was up and now isn't.
- *
- * Called from the LLD when the network link is not ready.
- * There may be multiple calls while the link is down.
- */
-int fcoe_ctlr_link_down(struct fcoe_ctlr *fip)
-{
-	int link_dropped;
-
-	LIBFCOE_FIP_DBG(fip, "link down.\n");
-	mutex_lock(&fip->ctlr_mutex);
-	fcoe_ctlr_reset(fip);
-	link_dropped = fip->state != FIP_ST_LINK_WAIT;
-	fcoe_ctlr_set_state(fip, FIP_ST_LINK_WAIT);
-	mutex_unlock(&fip->ctlr_mutex);
-
-	if (link_dropped)
-		fc_linkdown(fip->lp);
-	return link_dropped;
-}
-EXPORT_SYMBOL(fcoe_ctlr_link_down);
-
-/**
- * fcoe_ctlr_send_keep_alive() - Send a keep-alive to the selected FCF
- * @fip:   The FCoE controller to send the FKA on
- * @lport: libfc fc_lport to send from
- * @ports: 0 for controller keep-alive, 1 for port keep-alive
- * @sa:	   The source MAC address
- *
- * A controller keep-alive is sent every fka_period (typically 8 seconds).
- * The source MAC is the native MAC address.
- *
- * A port keep-alive is sent every 90 seconds while logged in.
- * The source MAC is the assigned mapped source address.
- * The destination is the FCF's F-port.
- */
-static void fcoe_ctlr_send_keep_alive(struct fcoe_ctlr *fip,
-				      struct fc_lport *lport,
-				      int ports, u8 *sa)
-{
-	struct sk_buff *skb;
-	struct fip_kal {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct fip_mac_desc mac;
-	} __attribute__((packed)) *kal;
-	struct fip_vn_desc *vn;
-	u32 len;
-	struct fc_lport *lp;
-	struct fcoe_fcf *fcf;
-
-	fcf = fip->sel_fcf;
-	lp = fip->lp;
-	if (!fcf || (ports && !lp->port_id))
-		return;
-
-	len = sizeof(*kal) + ports * sizeof(*vn);
-	skb = dev_alloc_skb(len);
-	if (!skb)
-		return;
-
-	kal = (struct fip_kal *)skb->data;
-	memset(kal, 0, len);
-	memcpy(kal->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
-	memcpy(kal->eth.h_source, sa, ETH_ALEN);
-	kal->eth.h_proto = htons(ETH_P_FIP);
-
-	kal->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	kal->fip.fip_op = htons(FIP_OP_CTRL);
-	kal->fip.fip_subcode = FIP_SC_KEEP_ALIVE;
-	kal->fip.fip_dl_len = htons((sizeof(kal->mac) +
-				     ports * sizeof(*vn)) / FIP_BPW);
-	kal->fip.fip_flags = htons(FIP_FL_FPMA);
-	if (fip->spma)
-		kal->fip.fip_flags |= htons(FIP_FL_SPMA);
-
-	kal->mac.fd_desc.fip_dtype = FIP_DT_MAC;
-	kal->mac.fd_desc.fip_dlen = sizeof(kal->mac) / FIP_BPW;
-	memcpy(kal->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-	if (ports) {
-		vn = (struct fip_vn_desc *)(kal + 1);
-		vn->fd_desc.fip_dtype = FIP_DT_VN_ID;
-		vn->fd_desc.fip_dlen = sizeof(*vn) / FIP_BPW;
-		memcpy(vn->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
-		hton24(vn->fd_fc_id, lport->port_id);
-		put_unaligned_be64(lport->wwpn, &vn->fd_wwpn);
-	}
-	skb_put(skb, len);
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	fip->send(fip, skb);
-}
-
-/**
- * fcoe_ctlr_encaps() - Encapsulate an ELS frame for FIP, without sending it
- * @fip:   The FCoE controller for the ELS frame
- * @dtype: The FIP descriptor type for the frame
- * @skb:   The FCoE ELS frame including FC header but no FCoE headers
- * @d_id:  The destination port ID.
- *
- * Returns non-zero error code on failure.
- *
- * The caller must check that the length is a multiple of 4.
- *
- * The @skb must have enough headroom (28 bytes) and tailroom (8 bytes).
- * Headroom includes the FIP encapsulation description, FIP header, and
- * Ethernet header.  The tailroom is for the FIP MAC descriptor.
- */
-static int fcoe_ctlr_encaps(struct fcoe_ctlr *fip, struct fc_lport *lport,
-			    u8 dtype, struct sk_buff *skb, u32 d_id)
-{
-	struct fip_encaps_head {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct fip_encaps encaps;
-	} __attribute__((packed)) *cap;
-	struct fc_frame_header *fh;
-	struct fip_mac_desc *mac;
-	struct fcoe_fcf *fcf;
-	size_t dlen;
-	u16 fip_flags;
-	u8 op;
-
-	fh = (struct fc_frame_header *)skb->data;
-	op = *(u8 *)(fh + 1);
-	dlen = sizeof(struct fip_encaps) + skb->len;	/* len before push */
-	cap = (struct fip_encaps_head *)skb_push(skb, sizeof(*cap));
-	memset(cap, 0, sizeof(*cap));
-
-	if (lport->point_to_multipoint) {
-		if (fcoe_ctlr_vn_lookup(fip, d_id, cap->eth.h_dest))
-			return -ENODEV;
-		fip_flags = 0;
-	} else {
-		fcf = fip->sel_fcf;
-		if (!fcf)
-			return -ENODEV;
-		fip_flags = fcf->flags;
-		fip_flags &= fip->spma ? FIP_FL_SPMA | FIP_FL_FPMA :
-					 FIP_FL_FPMA;
-		if (!fip_flags)
-			return -ENODEV;
-		memcpy(cap->eth.h_dest, fcf->fcf_mac, ETH_ALEN);
-	}
-	memcpy(cap->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
-	cap->eth.h_proto = htons(ETH_P_FIP);
-
-	cap->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	cap->fip.fip_op = htons(FIP_OP_LS);
-	if (op == ELS_LS_ACC || op == ELS_LS_RJT)
-		cap->fip.fip_subcode = FIP_SC_REP;
-	else
-		cap->fip.fip_subcode = FIP_SC_REQ;
-	cap->fip.fip_flags = htons(fip_flags);
-
-	cap->encaps.fd_desc.fip_dtype = dtype;
-	cap->encaps.fd_desc.fip_dlen = dlen / FIP_BPW;
-
-	if (op != ELS_LS_RJT) {
-		dlen += sizeof(*mac);
-		mac = (struct fip_mac_desc *)skb_put(skb, sizeof(*mac));
-		memset(mac, 0, sizeof(*mac));
-		mac->fd_desc.fip_dtype = FIP_DT_MAC;
-		mac->fd_desc.fip_dlen = sizeof(*mac) / FIP_BPW;
-		if (dtype != FIP_DT_FLOGI && dtype != FIP_DT_FDISC) {
-			memcpy(mac->fd_mac, fip->get_src_addr(lport), ETH_ALEN);
-		} else if (fip->mode == FIP_MODE_VN2VN) {
-			hton24(mac->fd_mac, FIP_VN_FC_MAP);
-			hton24(mac->fd_mac + 3, fip->port_id);
-		} else if (fip_flags & FIP_FL_SPMA) {
-			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with SPMA\n");
-			memcpy(mac->fd_mac, fip->ctl_src_addr, ETH_ALEN);
-		} else {
-			LIBFCOE_FIP_DBG(fip, "FLOGI/FDISC sent with FPMA\n");
-			/* FPMA only FLOGI.  Must leave the MAC desc zeroed. */
-		}
-	}
-	cap->fip.fip_dl_len = htons(dlen / FIP_BPW);
-
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-	return 0;
-}
-
-/**
- * fcoe_ctlr_els_send() - Send an ELS frame encapsulated by FIP if appropriate.
- * @fip:	FCoE controller.
- * @lport:	libfc fc_lport to send from
- * @skb:	FCoE ELS frame including FC header but no FCoE headers.
- *
- * Returns a non-zero error code if the frame should not be sent.
- * Returns zero if the caller should send the frame with FCoE encapsulation.
- *
- * The caller must check that the length is a multiple of 4.
- * The SKB must have enough headroom (28 bytes) and tailroom (8 bytes).
- * The the skb must also be an fc_frame.
- *
- * This is called from the lower-level driver with spinlocks held,
- * so we must not take a mutex here.
- */
-int fcoe_ctlr_els_send(struct fcoe_ctlr *fip, struct fc_lport *lport,
-		       struct sk_buff *skb)
-{
-	struct fc_frame *fp;
-	struct fc_frame_header *fh;
-	u16 old_xid;
-	u8 op;
-	u8 mac[ETH_ALEN];
-
-	fp = container_of(skb, struct fc_frame, skb);
-	fh = (struct fc_frame_header *)skb->data;
-	op = *(u8 *)(fh + 1);
-
-	if (op == ELS_FLOGI && fip->mode != FIP_MODE_VN2VN) {
-		old_xid = fip->flogi_oxid;
-		fip->flogi_oxid = ntohs(fh->fh_ox_id);
-		if (fip->state == FIP_ST_AUTO) {
-			if (old_xid == FC_XID_UNKNOWN)
-				fip->flogi_count = 0;
-			fip->flogi_count++;
-			if (fip->flogi_count < 3)
-				goto drop;
-			fcoe_ctlr_map_dest(fip);
-			return 0;
-		}
-		if (fip->state == FIP_ST_NON_FIP)
-			fcoe_ctlr_map_dest(fip);
-	}
-
-	if (fip->state == FIP_ST_NON_FIP)
-		return 0;
-	if (!fip->sel_fcf && fip->mode != FIP_MODE_VN2VN)
-		goto drop;
-	switch (op) {
-	case ELS_FLOGI:
-		op = FIP_DT_FLOGI;
-		if (fip->mode == FIP_MODE_VN2VN)
-			break;
-		spin_lock_bh(&fip->ctlr_lock);
-		kfree_skb(fip->flogi_req);
-		fip->flogi_req = skb;
-		fip->flogi_req_send = 1;
-		spin_unlock_bh(&fip->ctlr_lock);
-		schedule_work(&fip->timer_work);
-		return -EINPROGRESS;
-	case ELS_FDISC:
-		if (ntoh24(fh->fh_s_id))
-			return 0;
-		op = FIP_DT_FDISC;
-		break;
-	case ELS_LOGO:
-		if (fip->mode == FIP_MODE_VN2VN) {
-			if (fip->state != FIP_ST_VNMP_UP)
-				return -EINVAL;
-			if (ntoh24(fh->fh_d_id) == FC_FID_FLOGI)
-				return -EINVAL;
-		} else {
-			if (fip->state != FIP_ST_ENABLED)
-				return 0;
-			if (ntoh24(fh->fh_d_id) != FC_FID_FLOGI)
-				return 0;
-		}
-		op = FIP_DT_LOGO;
-		break;
-	case ELS_LS_ACC:
-		/*
-		 * If non-FIP, we may have gotten an SID by accepting an FLOGI
-		 * from a point-to-point connection.  Switch to using
-		 * the source mac based on the SID.  The destination
-		 * MAC in this case would have been set by receving the
-		 * FLOGI.
-		 */
-		if (fip->state == FIP_ST_NON_FIP) {
-			if (fip->flogi_oxid == FC_XID_UNKNOWN)
-				return 0;
-			fip->flogi_oxid = FC_XID_UNKNOWN;
-			fc_fcoe_set_mac(mac, fh->fh_d_id);
-			fip->update_mac(lport, mac);
-		}
-		/* fall through */
-	case ELS_LS_RJT:
-		op = fr_encaps(fp);
-		if (op)
-			break;
-		return 0;
-	default:
-		if (fip->state != FIP_ST_ENABLED &&
-		    fip->state != FIP_ST_VNMP_UP)
-			goto drop;
-		return 0;
-	}
-	LIBFCOE_FIP_DBG(fip, "els_send op %u d_id %x\n",
-			op, ntoh24(fh->fh_d_id));
-	if (fcoe_ctlr_encaps(fip, lport, op, skb, ntoh24(fh->fh_d_id)))
-		goto drop;
-	fip->send(fip, skb);
-	return -EINPROGRESS;
-drop:
-	kfree_skb(skb);
-	return -EINVAL;
-}
-EXPORT_SYMBOL(fcoe_ctlr_els_send);
-
-/**
- * fcoe_ctlr_age_fcfs() - Reset and free all old FCFs for a controller
- * @fip: The FCoE controller to free FCFs on
- *
- * Called with lock held and preemption disabled.
- *
- * An FCF is considered old if we have missed two advertisements.
- * That is, there have been no valid advertisement from it for 2.5
- * times its keep-alive period.
- *
- * In addition, determine the time when an FCF selection can occur.
- *
- * Also, increment the MissDiscAdvCount when no advertisement is received
- * for the corresponding FCF for 1.5 * FKA_ADV_PERIOD (FC-BB-5 LESB).
- *
- * Returns the time in jiffies for the next call.
- */
-static unsigned long fcoe_ctlr_age_fcfs(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *next;
-	unsigned long next_timer = jiffies + msecs_to_jiffies(FIP_VN_KA_PERIOD);
-	unsigned long deadline;
-	unsigned long sel_time = 0;
-	struct fcoe_dev_stats *stats;
-
-	stats = per_cpu_ptr(fip->lp->dev_stats, get_cpu());
-
-	list_for_each_entry_safe(fcf, next, &fip->fcfs, list) {
-		deadline = fcf->time + fcf->fka_period + fcf->fka_period / 2;
-		if (fip->sel_fcf == fcf) {
-			if (time_after(jiffies, deadline)) {
-				stats->MissDiscAdvCount++;
-				printk(KERN_INFO "libfcoe: host%d: "
-				       "Missing Discovery Advertisement "
-				       "for fab %16.16llx count %lld\n",
-				       fip->lp->host->host_no, fcf->fabric_name,
-				       stats->MissDiscAdvCount);
-			} else if (time_after(next_timer, deadline))
-				next_timer = deadline;
-		}
-
-		deadline += fcf->fka_period;
-		if (time_after_eq(jiffies, deadline)) {
-			if (fip->sel_fcf == fcf)
-				fip->sel_fcf = NULL;
-			list_del(&fcf->list);
-			WARN_ON(!fip->fcf_count);
-			fip->fcf_count--;
-			kfree(fcf);
-			stats->VLinkFailureCount++;
-		} else {
-			if (time_after(next_timer, deadline))
-				next_timer = deadline;
-			if (fcoe_ctlr_mtu_valid(fcf) &&
-			    (!sel_time || time_before(sel_time, fcf->time)))
-				sel_time = fcf->time;
-		}
-	}
-	put_cpu();
-	if (sel_time && !fip->sel_fcf && !fip->sel_time) {
-		sel_time += msecs_to_jiffies(FCOE_CTLR_START_DELAY);
-		fip->sel_time = sel_time;
-	}
-
-	return next_timer;
-}
-
-/**
- * fcoe_ctlr_parse_adv() - Decode a FIP advertisement into a new FCF entry
- * @fip: The FCoE controller receiving the advertisement
- * @skb: The received FIP advertisement frame
- * @fcf: The resulting FCF entry
- *
- * Returns zero on a valid parsed advertisement,
- * otherwise returns non zero value.
- */
-static int fcoe_ctlr_parse_adv(struct fcoe_ctlr *fip,
-			       struct sk_buff *skb, struct fcoe_fcf *fcf)
-{
-	struct fip_header *fiph;
-	struct fip_desc *desc = NULL;
-	struct fip_wwn_desc *wwn;
-	struct fip_fab_desc *fab;
-	struct fip_fka_desc *fka;
-	unsigned long t;
-	size_t rlen;
-	size_t dlen;
-	u32 desc_mask;
-
-	memset(fcf, 0, sizeof(*fcf));
-	fcf->fka_period = msecs_to_jiffies(FCOE_CTLR_DEF_FKA);
-
-	fiph = (struct fip_header *)skb->data;
-	fcf->flags = ntohs(fiph->fip_flags);
-
-	/*
-	 * mask of required descriptors. validating each one clears its bit.
-	 */
-	desc_mask = BIT(FIP_DT_PRI) | BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
-			BIT(FIP_DT_FAB) | BIT(FIP_DT_FKA);
-
-	rlen = ntohs(fiph->fip_dl_len) * 4;
-	if (rlen + sizeof(*fiph) > skb->len)
-		return -EINVAL;
-
-	desc = (struct fip_desc *)(fiph + 1);
-	while (rlen > 0) {
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen < sizeof(*desc) || dlen > rlen)
-			return -EINVAL;
-		/* Drop Adv if there are duplicate critical descriptors */
-		if ((desc->fip_dtype < 32) &&
-		    !(desc_mask & 1U << desc->fip_dtype)) {
-			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
-					"Descriptors in FIP adv\n");
-			return -EINVAL;
-		}
-		switch (desc->fip_dtype) {
-		case FIP_DT_PRI:
-			if (dlen != sizeof(struct fip_pri_desc))
-				goto len_err;
-			fcf->pri = ((struct fip_pri_desc *)desc)->fd_pri;
-			desc_mask &= ~BIT(FIP_DT_PRI);
-			break;
-		case FIP_DT_MAC:
-			if (dlen != sizeof(struct fip_mac_desc))
-				goto len_err;
-			memcpy(fcf->fcf_mac,
-			       ((struct fip_mac_desc *)desc)->fd_mac,
-			       ETH_ALEN);
-			if (!is_valid_ether_addr(fcf->fcf_mac)) {
-				LIBFCOE_FIP_DBG(fip,
-					"Invalid MAC addr %pM in FIP adv\n",
-					fcf->fcf_mac);
-				return -EINVAL;
-			}
-			desc_mask &= ~BIT(FIP_DT_MAC);
-			break;
-		case FIP_DT_NAME:
-			if (dlen != sizeof(struct fip_wwn_desc))
-				goto len_err;
-			wwn = (struct fip_wwn_desc *)desc;
-			fcf->switch_name = get_unaligned_be64(&wwn->fd_wwn);
-			desc_mask &= ~BIT(FIP_DT_NAME);
-			break;
-		case FIP_DT_FAB:
-			if (dlen != sizeof(struct fip_fab_desc))
-				goto len_err;
-			fab = (struct fip_fab_desc *)desc;
-			fcf->fabric_name = get_unaligned_be64(&fab->fd_wwn);
-			fcf->vfid = ntohs(fab->fd_vfid);
-			fcf->fc_map = ntoh24(fab->fd_map);
-			desc_mask &= ~BIT(FIP_DT_FAB);
-			break;
-		case FIP_DT_FKA:
-			if (dlen != sizeof(struct fip_fka_desc))
-				goto len_err;
-			fka = (struct fip_fka_desc *)desc;
-			if (fka->fd_flags & FIP_FKA_ADV_D)
-				fcf->fd_flags = 1;
-			t = ntohl(fka->fd_fka_period);
-			if (t >= FCOE_CTLR_MIN_FKA)
-				fcf->fka_period = msecs_to_jiffies(t);
-			desc_mask &= ~BIT(FIP_DT_FKA);
-			break;
-		case FIP_DT_MAP_OUI:
-		case FIP_DT_FCOE_SIZE:
-		case FIP_DT_FLOGI:
-		case FIP_DT_FDISC:
-		case FIP_DT_LOGO:
-		case FIP_DT_ELP:
-		default:
-			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
-					"in FIP adv\n", desc->fip_dtype);
-			/* standard says ignore unknown descriptors >= 128 */
-			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
-				return -EINVAL;
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-	if (!fcf->fc_map || (fcf->fc_map & 0x10000))
-		return -EINVAL;
-	if (!fcf->switch_name)
-		return -EINVAL;
-	if (desc_mask) {
-		LIBFCOE_FIP_DBG(fip, "adv missing descriptors mask %x\n",
-				desc_mask);
-		return -EINVAL;
-	}
-	return 0;
-
-len_err:
-	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
-			desc->fip_dtype, dlen);
-	return -EINVAL;
-}
-
-/**
- * fcoe_ctlr_recv_adv() - Handle an incoming advertisement
- * @fip: The FCoE controller receiving the advertisement
- * @skb: The received FIP packet
- */
-static void fcoe_ctlr_recv_adv(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf new;
-	struct fcoe_fcf *found;
-	unsigned long sol_tov = msecs_to_jiffies(FCOE_CTRL_SOL_TOV);
-	int first = 0;
-	int mtu_valid;
-
-	if (fcoe_ctlr_parse_adv(fip, skb, &new))
-		return;
-
-	mutex_lock(&fip->ctlr_mutex);
-	first = list_empty(&fip->fcfs);
-	found = NULL;
-	list_for_each_entry(fcf, &fip->fcfs, list) {
-		if (fcf->switch_name == new.switch_name &&
-		    fcf->fabric_name == new.fabric_name &&
-		    fcf->fc_map == new.fc_map &&
-		    compare_ether_addr(fcf->fcf_mac, new.fcf_mac) == 0) {
-			found = fcf;
-			break;
-		}
-	}
-	if (!found) {
-		if (fip->fcf_count >= FCOE_CTLR_FCF_LIMIT)
-			goto out;
-
-		fcf = kmalloc(sizeof(*fcf), GFP_ATOMIC);
-		if (!fcf)
-			goto out;
-
-		fip->fcf_count++;
-		memcpy(fcf, &new, sizeof(new));
-		list_add(&fcf->list, &fip->fcfs);
-	} else {
-		/*
-		 * Update the FCF's keep-alive descriptor flags.
-		 * Other flag changes from new advertisements are
-		 * ignored after a solicited advertisement is
-		 * received and the FCF is selectable (usable).
-		 */
-		fcf->fd_flags = new.fd_flags;
-		if (!fcoe_ctlr_fcf_usable(fcf))
-			fcf->flags = new.flags;
-
-		if (fcf == fip->sel_fcf && !fcf->fd_flags) {
-			fip->ctlr_ka_time -= fcf->fka_period;
-			fip->ctlr_ka_time += new.fka_period;
-			if (time_before(fip->ctlr_ka_time, fip->timer.expires))
-				mod_timer(&fip->timer, fip->ctlr_ka_time);
-		}
-		fcf->fka_period = new.fka_period;
-		memcpy(fcf->fcf_mac, new.fcf_mac, ETH_ALEN);
-	}
-	mtu_valid = fcoe_ctlr_mtu_valid(fcf);
-	fcf->time = jiffies;
-	if (!found)
-		LIBFCOE_FIP_DBG(fip, "New FCF fab %16.16llx mac %pM\n",
-				fcf->fabric_name, fcf->fcf_mac);
-
-	/*
-	 * If this advertisement is not solicited and our max receive size
-	 * hasn't been verified, send a solicited advertisement.
-	 */
-	if (!mtu_valid)
-		fcoe_ctlr_solicit(fip, fcf);
-
-	/*
-	 * If its been a while since we did a solicit, and this is
-	 * the first advertisement we've received, do a multicast
-	 * solicitation to gather as many advertisements as we can
-	 * before selection occurs.
-	 */
-	if (first && time_after(jiffies, fip->sol_time + sol_tov))
-		fcoe_ctlr_solicit(fip, NULL);
-
-	/*
-	 * Put this FCF at the head of the list for priority among equals.
-	 * This helps in the case of an NPV switch which insists we use
-	 * the FCF that answers multicast solicitations, not the others that
-	 * are sending periodic multicast advertisements.
-	 */
-	if (mtu_valid) {
-		list_del(&fcf->list);
-		list_add(&fcf->list, &fip->fcfs);
-	}
-
-	/*
-	 * If this is the first validated FCF, note the time and
-	 * set a timer to trigger selection.
-	 */
-	if (mtu_valid && !fip->sel_fcf && fcoe_ctlr_fcf_usable(fcf)) {
-		fip->sel_time = jiffies +
-			msecs_to_jiffies(FCOE_CTLR_START_DELAY);
-		if (!timer_pending(&fip->timer) ||
-		    time_before(fip->sel_time, fip->timer.expires))
-			mod_timer(&fip->timer, fip->sel_time);
-	}
-out:
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-/**
- * fcoe_ctlr_recv_els() - Handle an incoming FIP encapsulated ELS frame
- * @fip: The FCoE controller which received the packet
- * @skb: The received FIP packet
- */
-static void fcoe_ctlr_recv_els(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fip_header *fiph;
-	struct fc_frame *fp = (struct fc_frame *)skb;
-	struct fc_frame_header *fh = NULL;
-	struct fip_desc *desc;
-	struct fip_encaps *els;
-	struct fcoe_dev_stats *stats;
-	enum fip_desc_type els_dtype = 0;
-	u8 els_op;
-	u8 sub;
-	u8 granted_mac[ETH_ALEN] = { 0 };
-	size_t els_len = 0;
-	size_t rlen;
-	size_t dlen;
-	u32 desc_mask = 0;
-	u32 desc_cnt = 0;
-
-	fiph = (struct fip_header *)skb->data;
-	sub = fiph->fip_subcode;
-	if (sub != FIP_SC_REQ && sub != FIP_SC_REP)
-		goto drop;
-
-	rlen = ntohs(fiph->fip_dl_len) * 4;
-	if (rlen + sizeof(*fiph) > skb->len)
-		goto drop;
-
-	desc = (struct fip_desc *)(fiph + 1);
-	while (rlen > 0) {
-		desc_cnt++;
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen < sizeof(*desc) || dlen > rlen)
-			goto drop;
-		/* Drop ELS if there are duplicate critical descriptors */
-		if (desc->fip_dtype < 32) {
-			if (desc_mask & 1U << desc->fip_dtype) {
-				LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
-						"Descriptors in FIP ELS\n");
-				goto drop;
-			}
-			desc_mask |= (1 << desc->fip_dtype);
-		}
-		switch (desc->fip_dtype) {
-		case FIP_DT_MAC:
-			if (desc_cnt == 1) {
-				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
-						"received out of order\n");
-				goto drop;
-			}
-
-			if (dlen != sizeof(struct fip_mac_desc))
-				goto len_err;
-			memcpy(granted_mac,
-			       ((struct fip_mac_desc *)desc)->fd_mac,
-			       ETH_ALEN);
-			break;
-		case FIP_DT_FLOGI:
-		case FIP_DT_FDISC:
-		case FIP_DT_LOGO:
-		case FIP_DT_ELP:
-			if (desc_cnt != 1) {
-				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
-						"received out of order\n");
-				goto drop;
-			}
-			if (fh)
-				goto drop;
-			if (dlen < sizeof(*els) + sizeof(*fh) + 1)
-				goto len_err;
-			els_len = dlen - sizeof(*els);
-			els = (struct fip_encaps *)desc;
-			fh = (struct fc_frame_header *)(els + 1);
-			els_dtype = desc->fip_dtype;
-			break;
-		default:
-			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
-					"in FIP adv\n", desc->fip_dtype);
-			/* standard says ignore unknown descriptors >= 128 */
-			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
-				goto drop;
-			if (desc_cnt <= 2) {
-				LIBFCOE_FIP_DBG(fip, "FIP descriptors "
-						"received out of order\n");
-				goto drop;
-			}
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-
-	if (!fh)
-		goto drop;
-	els_op = *(u8 *)(fh + 1);
-
-	if ((els_dtype == FIP_DT_FLOGI || els_dtype == FIP_DT_FDISC) &&
-	    sub == FIP_SC_REP && fip->mode != FIP_MODE_VN2VN) {
-		if (els_op == ELS_LS_ACC) {
-			if (!is_valid_ether_addr(granted_mac)) {
-				LIBFCOE_FIP_DBG(fip,
-					"Invalid MAC address %pM in FIP ELS\n",
-					granted_mac);
-				goto drop;
-			}
-			memcpy(fr_cb(fp)->granted_mac, granted_mac, ETH_ALEN);
-
-			if (fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
-				fip->flogi_oxid = FC_XID_UNKNOWN;
-				if (els_dtype == FIP_DT_FLOGI)
-					fcoe_ctlr_announce(fip);
-			}
-		} else if (els_dtype == FIP_DT_FLOGI &&
-			   !fcoe_ctlr_flogi_retry(fip))
-			goto drop;	/* retrying FLOGI so drop reject */
-	}
-
-	if ((desc_cnt == 0) || ((els_op != ELS_LS_RJT) &&
-	    (!(1U << FIP_DT_MAC & desc_mask)))) {
-		LIBFCOE_FIP_DBG(fip, "Missing critical descriptors "
-				"in FIP ELS\n");
-		goto drop;
-	}
-
-	/*
-	 * Convert skb into an fc_frame containing only the ELS.
-	 */
-	skb_pull(skb, (u8 *)fh - skb->data);
-	skb_trim(skb, els_len);
-	fp = (struct fc_frame *)skb;
-	fc_frame_init(fp);
-	fr_sof(fp) = FC_SOF_I3;
-	fr_eof(fp) = FC_EOF_T;
-	fr_dev(fp) = lport;
-	fr_encaps(fp) = els_dtype;
-
-	stats = per_cpu_ptr(lport->dev_stats, get_cpu());
-	stats->RxFrames++;
-	stats->RxWords += skb->len / FIP_BPW;
-	put_cpu();
-
-	fc_exch_recv(lport, fp);
-	return;
-
-len_err:
-	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
-			desc->fip_dtype, dlen);
-drop:
-	kfree_skb(skb);
-}
-
-/**
- * fcoe_ctlr_recv_els() - Handle an incoming link reset frame
- * @fip: The FCoE controller that received the frame
- * @fh:	 The received FIP header
- *
- * There may be multiple VN_Port descriptors.
- * The overall length has already been checked.
- */
-static void fcoe_ctlr_recv_clr_vlink(struct fcoe_ctlr *fip,
-				     struct fip_header *fh)
-{
-	struct fip_desc *desc;
-	struct fip_mac_desc *mp;
-	struct fip_wwn_desc *wp;
-	struct fip_vn_desc *vp;
-	size_t rlen;
-	size_t dlen;
-	struct fcoe_fcf *fcf = fip->sel_fcf;
-	struct fc_lport *lport = fip->lp;
-	struct fc_lport *vn_port = NULL;
-	u32 desc_mask;
-	int is_vn_port = 0;
-
-	LIBFCOE_FIP_DBG(fip, "Clear Virtual Link received\n");
-
-	if (!fcf || !lport->port_id)
-		return;
-
-	/*
-	 * mask of required descriptors.  Validating each one clears its bit.
-	 */
-	desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) | BIT(FIP_DT_VN_ID);
-
-	rlen = ntohs(fh->fip_dl_len) * FIP_BPW;
-	desc = (struct fip_desc *)(fh + 1);
-	while (rlen >= sizeof(*desc)) {
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen > rlen)
-			return;
-		/* Drop CVL if there are duplicate critical descriptors */
-		if ((desc->fip_dtype < 32) &&
-		    !(desc_mask & 1U << desc->fip_dtype)) {
-			LIBFCOE_FIP_DBG(fip, "Duplicate Critical "
-					"Descriptors in FIP CVL\n");
-			return;
-		}
-		switch (desc->fip_dtype) {
-		case FIP_DT_MAC:
-			mp = (struct fip_mac_desc *)desc;
-			if (dlen < sizeof(*mp))
-				return;
-			if (compare_ether_addr(mp->fd_mac, fcf->fcf_mac))
-				return;
-			desc_mask &= ~BIT(FIP_DT_MAC);
-			break;
-		case FIP_DT_NAME:
-			wp = (struct fip_wwn_desc *)desc;
-			if (dlen < sizeof(*wp))
-				return;
-			if (get_unaligned_be64(&wp->fd_wwn) != fcf->switch_name)
-				return;
-			desc_mask &= ~BIT(FIP_DT_NAME);
-			break;
-		case FIP_DT_VN_ID:
-			vp = (struct fip_vn_desc *)desc;
-			if (dlen < sizeof(*vp))
-				return;
-			if (compare_ether_addr(vp->fd_mac,
-					       fip->get_src_addr(lport)) == 0 &&
-			    get_unaligned_be64(&vp->fd_wwpn) == lport->wwpn &&
-			    ntoh24(vp->fd_fc_id) == lport->port_id) {
-				desc_mask &= ~BIT(FIP_DT_VN_ID);
-				break;
-			}
-			/* check if clr_vlink is for NPIV port */
-			mutex_lock(&lport->lp_mutex);
-			list_for_each_entry(vn_port, &lport->vports, list) {
-				if (compare_ether_addr(vp->fd_mac,
-				    fip->get_src_addr(vn_port)) == 0 &&
-				    (get_unaligned_be64(&vp->fd_wwpn)
-							== vn_port->wwpn) &&
-				    (ntoh24(vp->fd_fc_id) ==
-					    fc_host_port_id(vn_port->host))) {
-					desc_mask &= ~BIT(FIP_DT_VN_ID);
-					is_vn_port = 1;
-					break;
-				}
-			}
-			mutex_unlock(&lport->lp_mutex);
-
-			break;
-		default:
-			/* standard says ignore unknown descriptors >= 128 */
-			if (desc->fip_dtype < FIP_DT_VENDOR_BASE)
-				return;
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-
-	/*
-	 * reset only if all required descriptors were present and valid.
-	 */
-	if (desc_mask) {
-		LIBFCOE_FIP_DBG(fip, "missing descriptors mask %x\n",
-				desc_mask);
-	} else {
-		LIBFCOE_FIP_DBG(fip, "performing Clear Virtual Link\n");
-
-		if (is_vn_port)
-			fc_lport_reset(vn_port);
-		else {
-			mutex_lock(&fip->ctlr_mutex);
-			per_cpu_ptr(lport->dev_stats,
-				    get_cpu())->VLinkFailureCount++;
-			put_cpu();
-			fcoe_ctlr_reset(fip);
-			mutex_unlock(&fip->ctlr_mutex);
-
-			fc_lport_reset(fip->lp);
-			fcoe_ctlr_solicit(fip, NULL);
-		}
-	}
-}
-
-/**
- * fcoe_ctlr_recv() - Receive a FIP packet
- * @fip: The FCoE controller that received the packet
- * @skb: The received FIP packet
- *
- * This may be called from either NET_RX_SOFTIRQ or IRQ.
- */
-void fcoe_ctlr_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	skb_queue_tail(&fip->fip_recv_list, skb);
-	schedule_work(&fip->recv_work);
-}
-EXPORT_SYMBOL(fcoe_ctlr_recv);
-
-/**
- * fcoe_ctlr_recv_handler() - Receive a FIP frame
- * @fip: The FCoE controller that received the frame
- * @skb: The received FIP frame
- *
- * Returns non-zero if the frame is dropped.
- */
-static int fcoe_ctlr_recv_handler(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fip_header *fiph;
-	struct ethhdr *eh;
-	enum fip_state state;
-	u16 op;
-	u8 sub;
-
-	if (skb_linearize(skb))
-		goto drop;
-	if (skb->len < sizeof(*fiph))
-		goto drop;
-	eh = eth_hdr(skb);
-	if (fip->mode == FIP_MODE_VN2VN) {
-		if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
-		    compare_ether_addr(eh->h_dest, fcoe_all_vn2vn) &&
-		    compare_ether_addr(eh->h_dest, fcoe_all_p2p))
-			goto drop;
-	} else if (compare_ether_addr(eh->h_dest, fip->ctl_src_addr) &&
-		   compare_ether_addr(eh->h_dest, fcoe_all_enode))
-		goto drop;
-	fiph = (struct fip_header *)skb->data;
-	op = ntohs(fiph->fip_op);
-	sub = fiph->fip_subcode;
-
-	if (FIP_VER_DECAPS(fiph->fip_ver) != FIP_VER)
-		goto drop;
-	if (ntohs(fiph->fip_dl_len) * FIP_BPW + sizeof(*fiph) > skb->len)
-		goto drop;
-
-	mutex_lock(&fip->ctlr_mutex);
-	state = fip->state;
-	if (state == FIP_ST_AUTO) {
-		fip->map_dest = 0;
-		fcoe_ctlr_set_state(fip, FIP_ST_ENABLED);
-		state = FIP_ST_ENABLED;
-		LIBFCOE_FIP_DBG(fip, "Using FIP mode\n");
-	}
-	mutex_unlock(&fip->ctlr_mutex);
-
-	if (fip->mode == FIP_MODE_VN2VN && op == FIP_OP_VN2VN)
-		return fcoe_ctlr_vn_recv(fip, skb);
-
-	if (state != FIP_ST_ENABLED && state != FIP_ST_VNMP_UP &&
-	    state != FIP_ST_VNMP_CLAIM)
-		goto drop;
-
-	if (op == FIP_OP_LS) {
-		fcoe_ctlr_recv_els(fip, skb);	/* consumes skb */
-		return 0;
-	}
-
-	if (state != FIP_ST_ENABLED)
-		goto drop;
-
-	if (op == FIP_OP_DISC && sub == FIP_SC_ADV)
-		fcoe_ctlr_recv_adv(fip, skb);
-	else if (op == FIP_OP_CTRL && sub == FIP_SC_CLR_VLINK)
-		fcoe_ctlr_recv_clr_vlink(fip, fiph);
-	kfree_skb(skb);
-	return 0;
-drop:
-	kfree_skb(skb);
-	return -1;
-}
-
-/**
- * fcoe_ctlr_select() - Select the best FCF (if possible)
- * @fip: The FCoE controller
- *
- * Returns the selected FCF, or NULL if none are usable.
- *
- * If there are conflicting advertisements, no FCF can be chosen.
- *
- * If there is already a selected FCF, this will choose a better one or
- * an equivalent one that hasn't already been sent a FLOGI.
- *
- * Called with lock held.
- */
-static struct fcoe_fcf *fcoe_ctlr_select(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	struct fcoe_fcf *best = fip->sel_fcf;
-	struct fcoe_fcf *first;
-
-	first = list_first_entry(&fip->fcfs, struct fcoe_fcf, list);
-
-	list_for_each_entry(fcf, &fip->fcfs, list) {
-		LIBFCOE_FIP_DBG(fip, "consider FCF fab %16.16llx "
-				"VFID %d mac %pM map %x val %d "
-				"sent %u pri %u\n",
-				fcf->fabric_name, fcf->vfid, fcf->fcf_mac,
-				fcf->fc_map, fcoe_ctlr_mtu_valid(fcf),
-				fcf->flogi_sent, fcf->pri);
-		if (fcf->fabric_name != first->fabric_name ||
-		    fcf->vfid != first->vfid ||
-		    fcf->fc_map != first->fc_map) {
-			LIBFCOE_FIP_DBG(fip, "Conflicting fabric, VFID, "
-					"or FC-MAP\n");
-			return NULL;
-		}
-		if (fcf->flogi_sent)
-			continue;
-		if (!fcoe_ctlr_fcf_usable(fcf)) {
-			LIBFCOE_FIP_DBG(fip, "FCF for fab %16.16llx "
-					"map %x %svalid %savailable\n",
-					fcf->fabric_name, fcf->fc_map,
-					(fcf->flags & FIP_FL_SOL) ? "" : "in",
-					(fcf->flags & FIP_FL_AVAIL) ?
-					"" : "un");
-			continue;
-		}
-		if (!best || fcf->pri < best->pri || best->flogi_sent)
-			best = fcf;
-	}
-	fip->sel_fcf = best;
-	if (best) {
-		LIBFCOE_FIP_DBG(fip, "using FCF mac %pM\n", best->fcf_mac);
-		fip->port_ka_time = jiffies +
-			msecs_to_jiffies(FIP_VN_KA_PERIOD);
-		fip->ctlr_ka_time = jiffies + best->fka_period;
-		if (time_before(fip->ctlr_ka_time, fip->timer.expires))
-			mod_timer(&fip->timer, fip->ctlr_ka_time);
-	}
-	return best;
-}
-
-/**
- * fcoe_ctlr_flogi_send_locked() - send FIP-encapsulated FLOGI to current FCF
- * @fip: The FCoE controller
- *
- * Returns non-zero error if it could not be sent.
- *
- * Called with ctlr_mutex and ctlr_lock held.
- * Caller must verify that fip->sel_fcf is not NULL.
- */
-static int fcoe_ctlr_flogi_send_locked(struct fcoe_ctlr *fip)
-{
-	struct sk_buff *skb;
-	struct sk_buff *skb_orig;
-	struct fc_frame_header *fh;
-	int error;
-
-	skb_orig = fip->flogi_req;
-	if (!skb_orig)
-		return -EINVAL;
-
-	/*
-	 * Clone and send the FLOGI request.  If clone fails, use original.
-	 */
-	skb = skb_clone(skb_orig, GFP_ATOMIC);
-	if (!skb) {
-		skb = skb_orig;
-		fip->flogi_req = NULL;
-	}
-	fh = (struct fc_frame_header *)skb->data;
-	error = fcoe_ctlr_encaps(fip, fip->lp, FIP_DT_FLOGI, skb,
-				 ntoh24(fh->fh_d_id));
-	if (error) {
-		kfree_skb(skb);
-		return error;
-	}
-	fip->send(fip, skb);
-	fip->sel_fcf->flogi_sent = 1;
-	return 0;
-}
-
-/**
- * fcoe_ctlr_flogi_retry() - resend FLOGI request to a new FCF if possible
- * @fip: The FCoE controller
- *
- * Returns non-zero error code if there's no FLOGI request to retry or
- * no alternate FCF available.
- */
-static int fcoe_ctlr_flogi_retry(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-	int error;
-
-	mutex_lock(&fip->ctlr_mutex);
-	spin_lock_bh(&fip->ctlr_lock);
-	LIBFCOE_FIP_DBG(fip, "re-sending FLOGI - reselect\n");
-	fcf = fcoe_ctlr_select(fip);
-	if (!fcf || fcf->flogi_sent) {
-		kfree_skb(fip->flogi_req);
-		fip->flogi_req = NULL;
-		error = -ENOENT;
-	} else {
-		fcoe_ctlr_solicit(fip, NULL);
-		error = fcoe_ctlr_flogi_send_locked(fip);
-	}
-	spin_unlock_bh(&fip->ctlr_lock);
-	mutex_unlock(&fip->ctlr_mutex);
-	return error;
-}
-
-
-/**
- * fcoe_ctlr_flogi_send() - Handle sending of FIP FLOGI.
- * @fip: The FCoE controller that timed out
- *
- * Done here because fcoe_ctlr_els_send() can't get mutex.
- *
- * Called with ctlr_mutex held.  The caller must not hold ctlr_lock.
- */
-static void fcoe_ctlr_flogi_send(struct fcoe_ctlr *fip)
-{
-	struct fcoe_fcf *fcf;
-
-	spin_lock_bh(&fip->ctlr_lock);
-	fcf = fip->sel_fcf;
-	if (!fcf || !fip->flogi_req_send)
-		goto unlock;
-
-	LIBFCOE_FIP_DBG(fip, "sending FLOGI\n");
-
-	/*
-	 * If this FLOGI is being sent due to a timeout retry
-	 * to the same FCF as before, select a different FCF if possible.
-	 */
-	if (fcf->flogi_sent) {
-		LIBFCOE_FIP_DBG(fip, "sending FLOGI - reselect\n");
-		fcf = fcoe_ctlr_select(fip);
-		if (!fcf || fcf->flogi_sent) {
-			LIBFCOE_FIP_DBG(fip, "sending FLOGI - clearing\n");
-			list_for_each_entry(fcf, &fip->fcfs, list)
-				fcf->flogi_sent = 0;
-			fcf = fcoe_ctlr_select(fip);
-		}
-	}
-	if (fcf) {
-		fcoe_ctlr_flogi_send_locked(fip);
-		fip->flogi_req_send = 0;
-	} else /* XXX */
-		LIBFCOE_FIP_DBG(fip, "No FCF selected - defer send\n");
-unlock:
-	spin_unlock_bh(&fip->ctlr_lock);
-}
-
-/**
- * fcoe_ctlr_timeout() - FIP timeout handler
- * @arg: The FCoE controller that timed out
- */
-static void fcoe_ctlr_timeout(unsigned long arg)
-{
-	struct fcoe_ctlr *fip = (struct fcoe_ctlr *)arg;
-
-	schedule_work(&fip->timer_work);
-}
-
-/**
- * fcoe_ctlr_timer_work() - Worker thread function for timer work
- * @work: Handle to a FCoE controller
- *
- * Ages FCFs.  Triggers FCF selection if possible.
- * Sends keep-alives and resets.
- */
-static void fcoe_ctlr_timer_work(struct work_struct *work)
-{
-	struct fcoe_ctlr *fip;
-	struct fc_lport *vport;
-	u8 *mac;
-	u8 reset = 0;
-	u8 send_ctlr_ka = 0;
-	u8 send_port_ka = 0;
-	struct fcoe_fcf *sel;
-	struct fcoe_fcf *fcf;
-	unsigned long next_timer;
-
-	fip = container_of(work, struct fcoe_ctlr, timer_work);
-	if (fip->mode == FIP_MODE_VN2VN)
-		return fcoe_ctlr_vn_timeout(fip);
-	mutex_lock(&fip->ctlr_mutex);
-	if (fip->state == FIP_ST_DISABLED) {
-		mutex_unlock(&fip->ctlr_mutex);
-		return;
-	}
-
-	fcf = fip->sel_fcf;
-	next_timer = fcoe_ctlr_age_fcfs(fip);
-
-	sel = fip->sel_fcf;
-	if (!sel && fip->sel_time) {
-		if (time_after_eq(jiffies, fip->sel_time)) {
-			sel = fcoe_ctlr_select(fip);
-			fip->sel_time = 0;
-		} else if (time_after(next_timer, fip->sel_time))
-			next_timer = fip->sel_time;
-	}
-
-	if (sel && fip->flogi_req_send)
-		fcoe_ctlr_flogi_send(fip);
-	else if (!sel && fcf)
-		reset = 1;
-
-	if (sel && !sel->fd_flags) {
-		if (time_after_eq(jiffies, fip->ctlr_ka_time)) {
-			fip->ctlr_ka_time = jiffies + sel->fka_period;
-			send_ctlr_ka = 1;
-		}
-		if (time_after(next_timer, fip->ctlr_ka_time))
-			next_timer = fip->ctlr_ka_time;
-
-		if (time_after_eq(jiffies, fip->port_ka_time)) {
-			fip->port_ka_time = jiffies +
-				msecs_to_jiffies(FIP_VN_KA_PERIOD);
-			send_port_ka = 1;
-		}
-		if (time_after(next_timer, fip->port_ka_time))
-			next_timer = fip->port_ka_time;
-	}
-	if (!list_empty(&fip->fcfs))
-		mod_timer(&fip->timer, next_timer);
-	mutex_unlock(&fip->ctlr_mutex);
-
-	if (reset) {
-		fc_lport_reset(fip->lp);
-		/* restart things with a solicitation */
-		fcoe_ctlr_solicit(fip, NULL);
-	}
-
-	if (send_ctlr_ka)
-		fcoe_ctlr_send_keep_alive(fip, NULL, 0, fip->ctl_src_addr);
-
-	if (send_port_ka) {
-		mutex_lock(&fip->lp->lp_mutex);
-		mac = fip->get_src_addr(fip->lp);
-		fcoe_ctlr_send_keep_alive(fip, fip->lp, 1, mac);
-		list_for_each_entry(vport, &fip->lp->vports, list) {
-			mac = fip->get_src_addr(vport);
-			fcoe_ctlr_send_keep_alive(fip, vport, 1, mac);
-		}
-		mutex_unlock(&fip->lp->lp_mutex);
-	}
-}
-
-/**
- * fcoe_ctlr_recv_work() - Worker thread function for receiving FIP frames
- * @recv_work: Handle to a FCoE controller
- */
-static void fcoe_ctlr_recv_work(struct work_struct *recv_work)
-{
-	struct fcoe_ctlr *fip;
-	struct sk_buff *skb;
-
-	fip = container_of(recv_work, struct fcoe_ctlr, recv_work);
-	while ((skb = skb_dequeue(&fip->fip_recv_list)))
-		fcoe_ctlr_recv_handler(fip, skb);
-}
-
-/**
- * fcoe_ctlr_recv_flogi() - Snoop pre-FIP receipt of FLOGI response
- * @fip: The FCoE controller
- * @fp:	 The FC frame to snoop
- *
- * Snoop potential response to FLOGI or even incoming FLOGI.
- *
- * The caller has checked that we are waiting for login as indicated
- * by fip->flogi_oxid != FC_XID_UNKNOWN.
- *
- * The caller is responsible for freeing the frame.
- * Fill in the granted_mac address.
- *
- * Return non-zero if the frame should not be delivered to libfc.
- */
-int fcoe_ctlr_recv_flogi(struct fcoe_ctlr *fip, struct fc_lport *lport,
-			 struct fc_frame *fp)
-{
-	struct fc_frame_header *fh;
-	u8 op;
-	u8 *sa;
-
-	sa = eth_hdr(&fp->skb)->h_source;
-	fh = fc_frame_header_get(fp);
-	if (fh->fh_type != FC_TYPE_ELS)
-		return 0;
-
-	op = fc_frame_payload_op(fp);
-	if (op == ELS_LS_ACC && fh->fh_r_ctl == FC_RCTL_ELS_REP &&
-	    fip->flogi_oxid == ntohs(fh->fh_ox_id)) {
-
-		mutex_lock(&fip->ctlr_mutex);
-		if (fip->state != FIP_ST_AUTO && fip->state != FIP_ST_NON_FIP) {
-			mutex_unlock(&fip->ctlr_mutex);
-			return -EINVAL;
-		}
-		fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
-		LIBFCOE_FIP_DBG(fip,
-				"received FLOGI LS_ACC using non-FIP mode\n");
-
-		/*
-		 * FLOGI accepted.
-		 * If the src mac addr is FC_OUI-based, then we mark the
-		 * address_mode flag to use FC_OUI-based Ethernet DA.
-		 * Otherwise we use the FCoE gateway addr
-		 */
-		if (!compare_ether_addr(sa, (u8[6])FC_FCOE_FLOGI_MAC)) {
-			fcoe_ctlr_map_dest(fip);
-		} else {
-			memcpy(fip->dest_addr, sa, ETH_ALEN);
-			fip->map_dest = 0;
-		}
-		fip->flogi_oxid = FC_XID_UNKNOWN;
-		mutex_unlock(&fip->ctlr_mutex);
-		fc_fcoe_set_mac(fr_cb(fp)->granted_mac, fh->fh_d_id);
-	} else if (op == ELS_FLOGI && fh->fh_r_ctl == FC_RCTL_ELS_REQ && sa) {
-		/*
-		 * Save source MAC for point-to-point responses.
-		 */
-		mutex_lock(&fip->ctlr_mutex);
-		if (fip->state == FIP_ST_AUTO || fip->state == FIP_ST_NON_FIP) {
-			memcpy(fip->dest_addr, sa, ETH_ALEN);
-			fip->map_dest = 0;
-			if (fip->state == FIP_ST_AUTO)
-				LIBFCOE_FIP_DBG(fip, "received non-FIP FLOGI. "
-						"Setting non-FIP mode\n");
-			fcoe_ctlr_set_state(fip, FIP_ST_NON_FIP);
-		}
-		mutex_unlock(&fip->ctlr_mutex);
-	}
-	return 0;
-}
-EXPORT_SYMBOL(fcoe_ctlr_recv_flogi);
-
-/**
- * fcoe_wwn_from_mac() - Converts a 48-bit IEEE MAC address to a 64-bit FC WWN
- * @mac:    The MAC address to convert
- * @scheme: The scheme to use when converting
- * @port:   The port indicator for converting
- *
- * Returns: u64 fc world wide name
- */
-u64 fcoe_wwn_from_mac(unsigned char mac[MAX_ADDR_LEN],
-		      unsigned int scheme, unsigned int port)
-{
-	u64 wwn;
-	u64 host_mac;
-
-	/* The MAC is in NO, so flip only the low 48 bits */
-	host_mac = ((u64) mac[0] << 40) |
-		((u64) mac[1] << 32) |
-		((u64) mac[2] << 24) |
-		((u64) mac[3] << 16) |
-		((u64) mac[4] << 8) |
-		(u64) mac[5];
-
-	WARN_ON(host_mac >= (1ULL << 48));
-	wwn = host_mac | ((u64) scheme << 60);
-	switch (scheme) {
-	case 1:
-		WARN_ON(port != 0);
-		break;
-	case 2:
-		WARN_ON(port >= 0xfff);
-		wwn |= (u64) port << 48;
-		break;
-	default:
-		WARN_ON(1);
-		break;
-	}
-
-	return wwn;
-}
-EXPORT_SYMBOL_GPL(fcoe_wwn_from_mac);
-
-/**
- * fcoe_ctlr_rport() - return the fcoe_rport for a given fc_rport_priv
- * @rdata: libfc remote port
- */
-static inline struct fcoe_rport *fcoe_ctlr_rport(struct fc_rport_priv *rdata)
-{
-	return (struct fcoe_rport *)(rdata + 1);
-}
-
-/**
- * fcoe_ctlr_vn_send() - Send a FIP VN2VN Probe Request or Reply.
- * @fip: The FCoE controller
- * @sub: sub-opcode for probe request, reply, or advertisement.
- * @dest: The destination Ethernet MAC address
- * @min_len: minimum size of the Ethernet payload to be sent
- */
-static void fcoe_ctlr_vn_send(struct fcoe_ctlr *fip,
-			      enum fip_vn2vn_subcode sub,
-			      const u8 *dest, size_t min_len)
-{
-	struct sk_buff *skb;
-	struct fip_frame {
-		struct ethhdr eth;
-		struct fip_header fip;
-		struct fip_mac_desc mac;
-		struct fip_wwn_desc wwnn;
-		struct fip_vn_desc vn;
-	} __attribute__((packed)) *frame;
-	struct fip_fc4_feat *ff;
-	struct fip_size_desc *size;
-	u32 fcp_feat;
-	size_t len;
-	size_t dlen;
-
-	len = sizeof(*frame);
-	dlen = 0;
-	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
-		dlen = sizeof(struct fip_fc4_feat) +
-		       sizeof(struct fip_size_desc);
-		len += dlen;
-	}
-	dlen += sizeof(frame->mac) + sizeof(frame->wwnn) + sizeof(frame->vn);
-	len = max(len, min_len + sizeof(struct ethhdr));
-
-	skb = dev_alloc_skb(len);
-	if (!skb)
-		return;
-
-	frame = (struct fip_frame *)skb->data;
-	memset(frame, 0, len);
-	memcpy(frame->eth.h_dest, dest, ETH_ALEN);
-	memcpy(frame->eth.h_source, fip->ctl_src_addr, ETH_ALEN);
-	frame->eth.h_proto = htons(ETH_P_FIP);
-
-	frame->fip.fip_ver = FIP_VER_ENCAPS(FIP_VER);
-	frame->fip.fip_op = htons(FIP_OP_VN2VN);
-	frame->fip.fip_subcode = sub;
-	frame->fip.fip_dl_len = htons(dlen / FIP_BPW);
-
-	frame->mac.fd_desc.fip_dtype = FIP_DT_MAC;
-	frame->mac.fd_desc.fip_dlen = sizeof(frame->mac) / FIP_BPW;
-	memcpy(frame->mac.fd_mac, fip->ctl_src_addr, ETH_ALEN);
-
-	frame->wwnn.fd_desc.fip_dtype = FIP_DT_NAME;
-	frame->wwnn.fd_desc.fip_dlen = sizeof(frame->wwnn) / FIP_BPW;
-	put_unaligned_be64(fip->lp->wwnn, &frame->wwnn.fd_wwn);
-
-	frame->vn.fd_desc.fip_dtype = FIP_DT_VN_ID;
-	frame->vn.fd_desc.fip_dlen = sizeof(frame->vn) / FIP_BPW;
-	hton24(frame->vn.fd_mac, FIP_VN_FC_MAP);
-	hton24(frame->vn.fd_mac + 3, fip->port_id);
-	hton24(frame->vn.fd_fc_id, fip->port_id);
-	put_unaligned_be64(fip->lp->wwpn, &frame->vn.fd_wwpn);
-
-	/*
-	 * For claims, add FC-4 features.
-	 * TBD: Add interface to get fc-4 types and features from libfc.
-	 */
-	if (sub == FIP_SC_VN_CLAIM_NOTIFY || sub == FIP_SC_VN_CLAIM_REP) {
-		ff = (struct fip_fc4_feat *)(frame + 1);
-		ff->fd_desc.fip_dtype = FIP_DT_FC4F;
-		ff->fd_desc.fip_dlen = sizeof(*ff) / FIP_BPW;
-		ff->fd_fts = fip->lp->fcts;
-
-		fcp_feat = 0;
-		if (fip->lp->service_params & FCP_SPPF_INIT_FCN)
-			fcp_feat |= FCP_FEAT_INIT;
-		if (fip->lp->service_params & FCP_SPPF_TARG_FCN)
-			fcp_feat |= FCP_FEAT_TARG;
-		fcp_feat <<= (FC_TYPE_FCP * 4) % 32;
-		ff->fd_ff.fd_feat[FC_TYPE_FCP * 4 / 32] = htonl(fcp_feat);
-
-		size = (struct fip_size_desc *)(ff + 1);
-		size->fd_desc.fip_dtype = FIP_DT_FCOE_SIZE;
-		size->fd_desc.fip_dlen = sizeof(*size) / FIP_BPW;
-		size->fd_size = htons(fcoe_ctlr_fcoe_size(fip));
-	}
-
-	skb_put(skb, len);
-	skb->protocol = htons(ETH_P_FIP);
-	skb_reset_mac_header(skb);
-	skb_reset_network_header(skb);
-
-	fip->send(fip, skb);
-}
-
-/**
- * fcoe_ctlr_vn_rport_callback - Event handler for rport events.
- * @lport: The lport which is receiving the event
- * @rdata: remote port private data
- * @event: The event that occured
- *
- * Locking Note:  The rport lock must not be held when calling this function.
- */
-static void fcoe_ctlr_vn_rport_callback(struct fc_lport *lport,
-					struct fc_rport_priv *rdata,
-					enum fc_rport_event event)
-{
-	struct fcoe_ctlr *fip = lport->disc.priv;
-	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
-
-	LIBFCOE_FIP_DBG(fip, "vn_rport_callback %x event %d\n",
-			rdata->ids.port_id, event);
-
-	mutex_lock(&fip->ctlr_mutex);
-	switch (event) {
-	case RPORT_EV_READY:
-		frport->login_count = 0;
-		break;
-	case RPORT_EV_LOGO:
-	case RPORT_EV_FAILED:
-	case RPORT_EV_STOP:
-		frport->login_count++;
-		if (frport->login_count > FCOE_CTLR_VN2VN_LOGIN_LIMIT) {
-			LIBFCOE_FIP_DBG(fip,
-					"rport FLOGI limited port_id %6.6x\n",
-					rdata->ids.port_id);
-			lport->tt.rport_logoff(rdata);
-		}
-		break;
-	default:
-		break;
-	}
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-static struct fc_rport_operations fcoe_ctlr_vn_rport_ops = {
-	.event_callback = fcoe_ctlr_vn_rport_callback,
-};
-
-/**
- * fcoe_ctlr_disc_stop_locked() - stop discovery in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_disc_stop_locked(struct fc_lport *lport)
-{
-	mutex_lock(&lport->disc.disc_mutex);
-	lport->disc.disc_callback = NULL;
-	mutex_unlock(&lport->disc.disc_mutex);
-}
-
-/**
- * fcoe_ctlr_disc_stop() - stop discovery in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called through the local port template for discovery.
- * Called without the ctlr_mutex held.
- */
-static void fcoe_ctlr_disc_stop(struct fc_lport *lport)
-{
-	struct fcoe_ctlr *fip = lport->disc.priv;
-
-	mutex_lock(&fip->ctlr_mutex);
-	fcoe_ctlr_disc_stop_locked(lport);
-	mutex_unlock(&fip->ctlr_mutex);
-}
-
-/**
- * fcoe_ctlr_disc_stop_final() - stop discovery for shutdown in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called through the local port template for discovery.
- * Called without the ctlr_mutex held.
- */
-static void fcoe_ctlr_disc_stop_final(struct fc_lport *lport)
-{
-	fcoe_ctlr_disc_stop(lport);
-	lport->tt.rport_flush_queue();
-	synchronize_rcu();
-}
-
-/**
- * fcoe_ctlr_vn_restart() - VN2VN probe restart with new port_id
- * @fip: The FCoE controller
- *
- * Called with fcoe_ctlr lock held.
- */
-static void fcoe_ctlr_vn_restart(struct fcoe_ctlr *fip)
-{
-	unsigned long wait;
-	u32 port_id;
-
-	fcoe_ctlr_disc_stop_locked(fip->lp);
-
-	/*
-	 * Get proposed port ID.
-	 * If this is the first try after link up, use any previous port_id.
-	 * If there was none, use the low bits of the port_name.
-	 * On subsequent tries, get the next random one.
-	 * Don't use reserved IDs, use another non-zero value, just as random.
-	 */
-	port_id = fip->port_id;
-	if (fip->probe_tries)
-		port_id = prandom32(&fip->rnd_state) & 0xffff;
-	else if (!port_id)
-		port_id = fip->lp->wwpn & 0xffff;
-	if (!port_id || port_id == 0xffff)
-		port_id = 1;
-	fip->port_id = port_id;
-
-	if (fip->probe_tries < FIP_VN_RLIM_COUNT) {
-		fip->probe_tries++;
-		wait = random32() % FIP_VN_PROBE_WAIT;
-	} else
-		wait = FIP_VN_RLIM_INT;
-	mod_timer(&fip->timer, jiffies + msecs_to_jiffies(wait));
-	fcoe_ctlr_set_state(fip, FIP_ST_VNMP_START);
-}
-
-/**
- * fcoe_ctlr_vn_start() - Start in VN2VN mode
- * @fip: The FCoE controller
- *
- * Called with fcoe_ctlr lock held.
- */
-static void fcoe_ctlr_vn_start(struct fcoe_ctlr *fip)
-{
-	fip->probe_tries = 0;
-	prandom32_seed(&fip->rnd_state, fip->lp->wwpn);
-	fcoe_ctlr_vn_restart(fip);
-}
-
-/**
- * fcoe_ctlr_vn_parse - parse probe request or response
- * @fip: The FCoE controller
- * @skb: incoming packet
- * @rdata: buffer for resulting parsed VN entry plus fcoe_rport
- *
- * Returns non-zero error number on error.
- * Does not consume the packet.
- */
-static int fcoe_ctlr_vn_parse(struct fcoe_ctlr *fip,
-			      struct sk_buff *skb,
-			      struct fc_rport_priv *rdata)
-{
-	struct fip_header *fiph;
-	struct fip_desc *desc = NULL;
-	struct fip_mac_desc *macd = NULL;
-	struct fip_wwn_desc *wwn = NULL;
-	struct fip_vn_desc *vn = NULL;
-	struct fip_size_desc *size = NULL;
-	struct fcoe_rport *frport;
-	size_t rlen;
-	size_t dlen;
-	u32 desc_mask = 0;
-	u32 dtype;
-	u8 sub;
-
-	memset(rdata, 0, sizeof(*rdata) + sizeof(*frport));
-	frport = fcoe_ctlr_rport(rdata);
-
-	fiph = (struct fip_header *)skb->data;
-	frport->flags = ntohs(fiph->fip_flags);
-
-	sub = fiph->fip_subcode;
-	switch (sub) {
-	case FIP_SC_VN_PROBE_REQ:
-	case FIP_SC_VN_PROBE_REP:
-	case FIP_SC_VN_BEACON:
-		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
-			    BIT(FIP_DT_VN_ID);
-		break;
-	case FIP_SC_VN_CLAIM_NOTIFY:
-	case FIP_SC_VN_CLAIM_REP:
-		desc_mask = BIT(FIP_DT_MAC) | BIT(FIP_DT_NAME) |
-			    BIT(FIP_DT_VN_ID) | BIT(FIP_DT_FC4F) |
-			    BIT(FIP_DT_FCOE_SIZE);
-		break;
-	default:
-		LIBFCOE_FIP_DBG(fip, "vn_parse unknown subcode %u\n", sub);
-		return -EINVAL;
-	}
-
-	rlen = ntohs(fiph->fip_dl_len) * 4;
-	if (rlen + sizeof(*fiph) > skb->len)
-		return -EINVAL;
-
-	desc = (struct fip_desc *)(fiph + 1);
-	while (rlen > 0) {
-		dlen = desc->fip_dlen * FIP_BPW;
-		if (dlen < sizeof(*desc) || dlen > rlen)
-			return -EINVAL;
-
-		dtype = desc->fip_dtype;
-		if (dtype < 32) {
-			if (!(desc_mask & BIT(dtype))) {
-				LIBFCOE_FIP_DBG(fip,
-						"unexpected or duplicated desc "
-						"desc type %u in "
-						"FIP VN2VN subtype %u\n",
-						dtype, sub);
-				return -EINVAL;
-			}
-			desc_mask &= ~BIT(dtype);
-		}
-
-		switch (dtype) {
-		case FIP_DT_MAC:
-			if (dlen != sizeof(struct fip_mac_desc))
-				goto len_err;
-			macd = (struct fip_mac_desc *)desc;
-			if (!is_valid_ether_addr(macd->fd_mac)) {
-				LIBFCOE_FIP_DBG(fip,
-					"Invalid MAC addr %pM in FIP VN2VN\n",
-					 macd->fd_mac);
-				return -EINVAL;
-			}
-			memcpy(frport->enode_mac, macd->fd_mac, ETH_ALEN);
-			break;
-		case FIP_DT_NAME:
-			if (dlen != sizeof(struct fip_wwn_desc))
-				goto len_err;
-			wwn = (struct fip_wwn_desc *)desc;
-			rdata->ids.node_name = get_unaligned_be64(&wwn->fd_wwn);
-			break;
-		case FIP_DT_VN_ID:
-			if (dlen != sizeof(struct fip_vn_desc))
-				goto len_err;
-			vn = (struct fip_vn_desc *)desc;
-			memcpy(frport->vn_mac, vn->fd_mac, ETH_ALEN);
-			rdata->ids.port_id = ntoh24(vn->fd_fc_id);
-			rdata->ids.port_name = get_unaligned_be64(&vn->fd_wwpn);
-			break;
-		case FIP_DT_FC4F:
-			if (dlen != sizeof(struct fip_fc4_feat))
-				goto len_err;
-			break;
-		case FIP_DT_FCOE_SIZE:
-			if (dlen != sizeof(struct fip_size_desc))
-				goto len_err;
-			size = (struct fip_size_desc *)desc;
-			frport->fcoe_len = ntohs(size->fd_size);
-			break;
-		default:
-			LIBFCOE_FIP_DBG(fip, "unexpected descriptor type %x "
-					"in FIP probe\n", dtype);
-			/* standard says ignore unknown descriptors >= 128 */
-			if (dtype < FIP_DT_VENDOR_BASE)
-				return -EINVAL;
-			break;
-		}
-		desc = (struct fip_desc *)((char *)desc + dlen);
-		rlen -= dlen;
-	}
-	return 0;
-
-len_err:
-	LIBFCOE_FIP_DBG(fip, "FIP length error in descriptor type %x len %zu\n",
-			dtype, dlen);
-	return -EINVAL;
-}
-
-/**
- * fcoe_ctlr_vn_send_claim() - send multicast FIP VN2VN Claim Notification.
- * @fip: The FCoE controller
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_send_claim(struct fcoe_ctlr *fip)
-{
-	fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_NOTIFY, fcoe_all_vn2vn, 0);
-	fip->sol_time = jiffies;
-}
-
-/**
- * fcoe_ctlr_vn_probe_req() - handle incoming VN2VN probe request.
- * @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_probe_req(struct fcoe_ctlr *fip,
-				   struct fc_rport_priv *rdata)
-{
-	struct fcoe_rport *frport = fcoe_ctlr_rport(rdata);
-
-	if (rdata->ids.port_id != fip->port_id)
-		return;
-
-	switch (fip->state) {
-	case FIP_ST_VNMP_CLAIM:
-	case FIP_ST_VNMP_UP:
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
-				  frport->enode_mac, 0);
-		break;
-	case FIP_ST_VNMP_PROBE1:
-	case FIP_ST_VNMP_PROBE2:
-		/*
-		 * Decide whether to reply to the Probe.
-		 * Our selected address is never a "recorded" one, so
-		 * only reply if our WWPN is greater and the
-		 * Probe's REC bit is not set.
-		 * If we don't reply, we will change our address.
-		 */
-		if (fip->lp->wwpn > rdata->ids.port_name &&
-		    !(frport->flags & FIP_FL_REC_OR_P2P)) {
-			fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REP,
-					  frport->enode_mac, 0);
-			break;
-		}
-		/* fall through */
-	case FIP_ST_VNMP_START:
-		fcoe_ctlr_vn_restart(fip);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- * fcoe_ctlr_vn_probe_reply() - handle incoming VN2VN probe reply.
- * @fip: The FCoE controller
- * @rdata: parsed remote port with frport from the probe request
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_probe_reply(struct fcoe_ctlr *fip,
-				   struct fc_rport_priv *rdata)
-{
-	if (rdata->ids.port_id != fip->port_id)
-		return;
-	switch (fip->state) {
-	case FIP_ST_VNMP_START:
-	case FIP_ST_VNMP_PROBE1:
-	case FIP_ST_VNMP_PROBE2:
-	case FIP_ST_VNMP_CLAIM:
-		fcoe_ctlr_vn_restart(fip);
-		break;
-	case FIP_ST_VNMP_UP:
-		fcoe_ctlr_vn_send_claim(fip);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- * fcoe_ctlr_vn_add() - Add a VN2VN entry to the list, based on a claim reply.
- * @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_add(struct fcoe_ctlr *fip, struct fc_rport_priv *new)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fc_rport_identifiers *ids;
-	struct fcoe_rport *frport;
-	u32 port_id;
-
-	port_id = new->ids.port_id;
-	if (port_id == fip->port_id)
-		return;
-
-	mutex_lock(&lport->disc.disc_mutex);
-	rdata = lport->tt.rport_create(lport, port_id);
-	if (!rdata) {
-		mutex_unlock(&lport->disc.disc_mutex);
-		return;
-	}
-
-	rdata->ops = &fcoe_ctlr_vn_rport_ops;
-	rdata->disc_id = lport->disc.disc_id;
-
-	ids = &rdata->ids;
-	if ((ids->port_name != -1 && ids->port_name != new->ids.port_name) ||
-	    (ids->node_name != -1 && ids->node_name != new->ids.node_name))
-		lport->tt.rport_logoff(rdata);
-	ids->port_name = new->ids.port_name;
-	ids->node_name = new->ids.node_name;
-	mutex_unlock(&lport->disc.disc_mutex);
-
-	frport = fcoe_ctlr_rport(rdata);
-	LIBFCOE_FIP_DBG(fip, "vn_add rport %6.6x %s\n",
-			port_id, frport->fcoe_len ? "old" : "new");
-	*frport = *fcoe_ctlr_rport(new);
-	frport->time = 0;
-}
-
-/**
- * fcoe_ctlr_vn_lookup() - Find VN remote port's MAC address
- * @fip: The FCoE controller
- * @port_id:  The port_id of the remote VN_node
- * @mac: buffer which will hold the VN_NODE destination MAC address, if found.
- *
- * Returns non-zero error if no remote port found.
- */
-static int fcoe_ctlr_vn_lookup(struct fcoe_ctlr *fip, u32 port_id, u8 *mac)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-	int ret = -1;
-
-	rcu_read_lock();
-	rdata = lport->tt.rport_lookup(lport, port_id);
-	if (rdata) {
-		frport = fcoe_ctlr_rport(rdata);
-		memcpy(mac, frport->enode_mac, ETH_ALEN);
-		ret = 0;
-	}
-	rcu_read_unlock();
-	return ret;
-}
-
-/**
- * fcoe_ctlr_vn_claim_notify() - handle received FIP VN2VN Claim Notification
- * @fip: The FCoE controller
- * @new: newly-parsed remote port with frport as a template for new rdata
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_claim_notify(struct fcoe_ctlr *fip,
-				      struct fc_rport_priv *new)
-{
-	struct fcoe_rport *frport = fcoe_ctlr_rport(new);
-
-	if (frport->flags & FIP_FL_REC_OR_P2P) {
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		return;
-	}
-	switch (fip->state) {
-	case FIP_ST_VNMP_START:
-	case FIP_ST_VNMP_PROBE1:
-	case FIP_ST_VNMP_PROBE2:
-		if (new->ids.port_id == fip->port_id)
-			fcoe_ctlr_vn_restart(fip);
-		break;
-	case FIP_ST_VNMP_CLAIM:
-	case FIP_ST_VNMP_UP:
-		if (new->ids.port_id == fip->port_id) {
-			if (new->ids.port_name > fip->lp->wwpn) {
-				fcoe_ctlr_vn_restart(fip);
-				break;
-			}
-			fcoe_ctlr_vn_send_claim(fip);
-			break;
-		}
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_CLAIM_REP, frport->enode_mac,
-				  min((u32)frport->fcoe_len,
-				      fcoe_ctlr_fcoe_size(fip)));
-		fcoe_ctlr_vn_add(fip, new);
-		break;
-	default:
-		break;
-	}
-}
-
-/**
- * fcoe_ctlr_vn_claim_resp() - handle received Claim Response
- * @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Claim Response
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_claim_resp(struct fcoe_ctlr *fip,
-				    struct fc_rport_priv *new)
-{
-	LIBFCOE_FIP_DBG(fip, "claim resp from from rport %x - state %s\n",
-			new->ids.port_id, fcoe_ctlr_state(fip->state));
-	if (fip->state == FIP_ST_VNMP_UP || fip->state == FIP_ST_VNMP_CLAIM)
-		fcoe_ctlr_vn_add(fip, new);
-}
-
-/**
- * fcoe_ctlr_vn_beacon() - handle received beacon.
- * @fip: The FCoE controller that received the frame
- * @new: newly-parsed remote port with frport from the Beacon
- *
- * Called with ctlr_mutex held.
- */
-static void fcoe_ctlr_vn_beacon(struct fcoe_ctlr *fip,
-				struct fc_rport_priv *new)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-
-	frport = fcoe_ctlr_rport(new);
-	if (frport->flags & FIP_FL_REC_OR_P2P) {
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		return;
-	}
-	mutex_lock(&lport->disc.disc_mutex);
-	rdata = lport->tt.rport_lookup(lport, new->ids.port_id);
-	if (rdata)
-		kref_get(&rdata->kref);
-	mutex_unlock(&lport->disc.disc_mutex);
-	if (rdata) {
-		if (rdata->ids.node_name == new->ids.node_name &&
-		    rdata->ids.port_name == new->ids.port_name) {
-			frport = fcoe_ctlr_rport(rdata);
-			if (!frport->time && fip->state == FIP_ST_VNMP_UP)
-				lport->tt.rport_login(rdata);
-			frport->time = jiffies;
-		}
-		kref_put(&rdata->kref, lport->tt.rport_destroy);
-		return;
-	}
-	if (fip->state != FIP_ST_VNMP_UP)
-		return;
-
-	/*
-	 * Beacon from a new neighbor.
-	 * Send a claim notify if one hasn't been sent recently.
-	 * Don't add the neighbor yet.
-	 */
-	LIBFCOE_FIP_DBG(fip, "beacon from new rport %x. sending claim notify\n",
-			new->ids.port_id);
-	if (time_after(jiffies,
-		       fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT)))
-		fcoe_ctlr_vn_send_claim(fip);
-}
-
-/**
- * fcoe_ctlr_vn_age() - Check for VN_ports without recent beacons
- * @fip: The FCoE controller
- *
- * Called with ctlr_mutex held.
- * Called only in state FIP_ST_VNMP_UP.
- * Returns the soonest time for next age-out or a time far in the future.
- */
-static unsigned long fcoe_ctlr_vn_age(struct fcoe_ctlr *fip)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-	unsigned long next_time;
-	unsigned long deadline;
-
-	next_time = jiffies + msecs_to_jiffies(FIP_VN_BEACON_INT * 10);
-	mutex_lock(&lport->disc.disc_mutex);
-	list_for_each_entry_rcu(rdata, &lport->disc.rports, peers) {
-		frport = fcoe_ctlr_rport(rdata);
-		if (!frport->time)
-			continue;
-		deadline = frport->time +
-			   msecs_to_jiffies(FIP_VN_BEACON_INT * 25 / 10);
-		if (time_after_eq(jiffies, deadline)) {
-			frport->time = 0;
-			LIBFCOE_FIP_DBG(fip,
-				"port %16.16llx fc_id %6.6x beacon expired\n",
-				rdata->ids.port_name, rdata->ids.port_id);
-			lport->tt.rport_logoff(rdata);
-		} else if (time_before(deadline, next_time))
-			next_time = deadline;
-	}
-	mutex_unlock(&lport->disc.disc_mutex);
-	return next_time;
-}
-
-/**
- * fcoe_ctlr_vn_recv() - Receive a FIP frame
- * @fip: The FCoE controller that received the frame
- * @skb: The received FIP frame
- *
- * Returns non-zero if the frame is dropped.
- * Always consumes the frame.
- */
-static int fcoe_ctlr_vn_recv(struct fcoe_ctlr *fip, struct sk_buff *skb)
-{
-	struct fip_header *fiph;
-	enum fip_vn2vn_subcode sub;
-	struct {
-		struct fc_rport_priv rdata;
-		struct fcoe_rport frport;
-	} buf;
-	int rc;
-
-	fiph = (struct fip_header *)skb->data;
-	sub = fiph->fip_subcode;
-
-	rc = fcoe_ctlr_vn_parse(fip, skb, &buf.rdata);
-	if (rc) {
-		LIBFCOE_FIP_DBG(fip, "vn_recv vn_parse error %d\n", rc);
-		goto drop;
-	}
-
-	mutex_lock(&fip->ctlr_mutex);
-	switch (sub) {
-	case FIP_SC_VN_PROBE_REQ:
-		fcoe_ctlr_vn_probe_req(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_PROBE_REP:
-		fcoe_ctlr_vn_probe_reply(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_CLAIM_NOTIFY:
-		fcoe_ctlr_vn_claim_notify(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_CLAIM_REP:
-		fcoe_ctlr_vn_claim_resp(fip, &buf.rdata);
-		break;
-	case FIP_SC_VN_BEACON:
-		fcoe_ctlr_vn_beacon(fip, &buf.rdata);
-		break;
-	default:
-		LIBFCOE_FIP_DBG(fip, "vn_recv unknown subcode %d\n", sub);
-		rc = -1;
-		break;
-	}
-	mutex_unlock(&fip->ctlr_mutex);
-drop:
-	kfree_skb(skb);
-	return rc;
-}
-
-/**
- * fcoe_ctlr_disc_recv - discovery receive handler for VN2VN mode.
- * @lport: The local port
- * @fp: The received frame
- *
- * This should never be called since we don't see RSCNs or other
- * fabric-generated ELSes.
- */
-static void fcoe_ctlr_disc_recv(struct fc_lport *lport, struct fc_frame *fp)
-{
-	struct fc_seq_els_data rjt_data;
-
-	rjt_data.reason = ELS_RJT_UNSUP;
-	rjt_data.explan = ELS_EXPL_NONE;
-	lport->tt.seq_els_rsp_send(fp, ELS_LS_RJT, &rjt_data);
-	fc_frame_free(fp);
-}
-
-/**
- * fcoe_ctlr_disc_recv - start discovery for VN2VN mode.
- * @fip: The FCoE controller
- *
- * This sets a flag indicating that remote ports should be created
- * and started for the peers we discover.  We use the disc_callback
- * pointer as that flag.  Peers already discovered are created here.
- *
- * The lport lock is held during this call. The callback must be done
- * later, without holding either the lport or discovery locks.
- * The fcoe_ctlr lock may also be held during this call.
- */
-static void fcoe_ctlr_disc_start(void (*callback)(struct fc_lport *,
-						  enum fc_disc_event),
-				 struct fc_lport *lport)
-{
-	struct fc_disc *disc = &lport->disc;
-	struct fcoe_ctlr *fip = disc->priv;
-
-	mutex_lock(&disc->disc_mutex);
-	disc->disc_callback = callback;
-	disc->disc_id = (disc->disc_id + 2) | 1;
-	disc->pending = 1;
-	schedule_work(&fip->timer_work);
-	mutex_unlock(&disc->disc_mutex);
-}
-
-/**
- * fcoe_ctlr_vn_disc() - report FIP VN_port discovery results after claim state.
- * @fip: The FCoE controller
- *
- * Starts the FLOGI and PLOGI login process to each discovered rport for which
- * we've received at least one beacon.
- * Performs the discovery complete callback.
- */
-static void fcoe_ctlr_vn_disc(struct fcoe_ctlr *fip)
-{
-	struct fc_lport *lport = fip->lp;
-	struct fc_disc *disc = &lport->disc;
-	struct fc_rport_priv *rdata;
-	struct fcoe_rport *frport;
-	void (*callback)(struct fc_lport *, enum fc_disc_event);
-
-	mutex_lock(&disc->disc_mutex);
-	callback = disc->pending ? disc->disc_callback : NULL;
-	disc->pending = 0;
-	list_for_each_entry_rcu(rdata, &disc->rports, peers) {
-		frport = fcoe_ctlr_rport(rdata);
-		if (frport->time)
-			lport->tt.rport_login(rdata);
-	}
-	mutex_unlock(&disc->disc_mutex);
-	if (callback)
-		callback(lport, DISC_EV_SUCCESS);
-}
-
-/**
- * fcoe_ctlr_vn_timeout - timer work function for VN2VN mode.
- * @fip: The FCoE controller
- */
-static void fcoe_ctlr_vn_timeout(struct fcoe_ctlr *fip)
-{
-	unsigned long next_time;
-	u8 mac[ETH_ALEN];
-	u32 new_port_id = 0;
-
-	mutex_lock(&fip->ctlr_mutex);
-	switch (fip->state) {
-	case FIP_ST_VNMP_START:
-		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE1);
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		next_time = jiffies + msecs_to_jiffies(FIP_VN_PROBE_WAIT);
-		break;
-	case FIP_ST_VNMP_PROBE1:
-		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_PROBE2);
-		fcoe_ctlr_vn_send(fip, FIP_SC_VN_PROBE_REQ, fcoe_all_vn2vn, 0);
-		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-		break;
-	case FIP_ST_VNMP_PROBE2:
-		fcoe_ctlr_set_state(fip, FIP_ST_VNMP_CLAIM);
-		new_port_id = fip->port_id;
-		hton24(mac, FIP_VN_FC_MAP);
-		hton24(mac + 3, new_port_id);
-		fcoe_ctlr_map_dest(fip);
-		fip->update_mac(fip->lp, mac);
-		fcoe_ctlr_vn_send_claim(fip);
-		next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-		break;
-	case FIP_ST_VNMP_CLAIM:
-		/*
-		 * This may be invoked either by starting discovery so don't
-		 * go to the next state unless it's been long enough.
-		 */
-		next_time = fip->sol_time + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-		if (time_after_eq(jiffies, next_time)) {
-			fcoe_ctlr_set_state(fip, FIP_ST_VNMP_UP);
-			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
-					  fcoe_all_vn2vn, 0);
-			next_time = jiffies + msecs_to_jiffies(FIP_VN_ANN_WAIT);
-			fip->port_ka_time = next_time;
-		}
-		fcoe_ctlr_vn_disc(fip);
-		break;
-	case FIP_ST_VNMP_UP:
-		next_time = fcoe_ctlr_vn_age(fip);
-		if (time_after_eq(jiffies, fip->port_ka_time)) {
-			fcoe_ctlr_vn_send(fip, FIP_SC_VN_BEACON,
-					  fcoe_all_vn2vn, 0);
-			fip->port_ka_time = jiffies +
-				 msecs_to_jiffies(FIP_VN_BEACON_INT +
-					(random32() % FIP_VN_BEACON_FUZZ));
-		}
-		if (time_before(fip->port_ka_time, next_time))
-			next_time = fip->port_ka_time;
-		break;
-	case FIP_ST_LINK_WAIT:
-		goto unlock;
-	default:
-		WARN(1, "unexpected state %d\n", fip->state);
-		goto unlock;
-	}
-	mod_timer(&fip->timer, next_time);
-unlock:
-	mutex_unlock(&fip->ctlr_mutex);
-
-	/* If port ID is new, notify local port after dropping ctlr_mutex */
-	if (new_port_id)
-		fc_lport_set_local_id(fip->lp, new_port_id);
-}
-
-/**
- * fcoe_libfc_config() - Sets up libfc related properties for local port
- * @lp: The local port to configure libfc for
- * @fip: The FCoE controller in use by the local port
- * @tt: The libfc function template
- * @init_fcp: If non-zero, the FCP portion of libfc should be initialized
- *
- * Returns : 0 for success
- */
-int fcoe_libfc_config(struct fc_lport *lport, struct fcoe_ctlr *fip,
-		      const struct libfc_function_template *tt, int init_fcp)
-{
-	/* Set the function pointers set by the LLDD */
-	memcpy(&lport->tt, tt, sizeof(*tt));
-	if (init_fcp && fc_fcp_init(lport))
-		return -ENOMEM;
-	fc_exch_init(lport);
-	fc_elsct_init(lport);
-	fc_lport_init(lport);
-	if (fip->mode == FIP_MODE_VN2VN)
-		lport->rport_priv_size = sizeof(struct fcoe_rport);
-	fc_rport_init(lport);
-	if (fip->mode == FIP_MODE_VN2VN) {
-		lport->point_to_multipoint = 1;
-		lport->tt.disc_recv_req = fcoe_ctlr_disc_recv;
-		lport->tt.disc_start = fcoe_ctlr_disc_start;
-		lport->tt.disc_stop = fcoe_ctlr_disc_stop;
-		lport->tt.disc_stop_final = fcoe_ctlr_disc_stop_final;
-		mutex_init(&lport->disc.disc_mutex);
-		INIT_LIST_HEAD(&lport->disc.rports);
-		lport->disc.priv = fip;
-	} else {
-		fc_disc_init(lport);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(fcoe_libfc_config);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/libfcoe.h linux-libre-2.6.39-gnu/drivers/scsi/fcoe/libfcoe.h
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/libfcoe.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/libfcoe.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,31 @@
+#ifndef _FCOE_LIBFCOE_H_
+#define _FCOE_LIBFCOE_H_
+
+extern unsigned int libfcoe_debug_logging;
+#define LIBFCOE_LOGGING	    0x01 /* General logging, not categorized */
+#define LIBFCOE_FIP_LOGGING 0x02 /* FIP logging */
+#define LIBFCOE_TRANSPORT_LOGGING	0x04 /* FCoE transport logging */
+
+#define LIBFCOE_CHECK_LOGGING(LEVEL, CMD)		\
+do {							\
+	if (unlikely(libfcoe_debug_logging & LEVEL))	\
+		do {					\
+			CMD;				\
+		} while (0);				\
+} while (0)
+
+#define LIBFCOE_DBG(fmt, args...)					\
+	LIBFCOE_CHECK_LOGGING(LIBFCOE_LOGGING,				\
+			      printk(KERN_INFO "libfcoe: " fmt, ##args);)
+
+#define LIBFCOE_FIP_DBG(fip, fmt, args...)				\
+	LIBFCOE_CHECK_LOGGING(LIBFCOE_FIP_LOGGING,			\
+			      printk(KERN_INFO "host%d: fip: " fmt,	\
+				     (fip)->lp->host->host_no, ##args);)
+
+#define LIBFCOE_TRANSPORT_DBG(fmt, args...)				\
+	LIBFCOE_CHECK_LOGGING(LIBFCOE_TRANSPORT_LOGGING,		\
+			      printk(KERN_INFO "%s: " fmt,		\
+				     __func__, ##args);)
+
+#endif /* _FCOE_LIBFCOE_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fcoe/Makefile linux-libre-2.6.39-gnu/drivers/scsi/fcoe/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/fcoe/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fcoe/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,2 +1,4 @@
 obj-$(CONFIG_FCOE) += fcoe.o
 obj-$(CONFIG_LIBFCOE) += libfcoe.o
+
+libfcoe-objs := fcoe_ctlr.o fcoe_transport.o
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fdomain.c linux-libre-2.6.39-gnu/drivers/scsi/fdomain.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fdomain.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fdomain.c	2011-05-19 00:06:34.000000000 -0400
@@ -174,7 +174,7 @@
  Future Domain sold DOS BIOS source for $250 and the UN*X driver source was
  $750, but these required a non-disclosure agreement, so even if I could
  have afforded them, they would *not* have been useful for writing this
- publically distributable driver.  Future Domain technical support has
+ publicly distributable driver.  Future Domain technical support has
  provided some information on the phone and have sent a few useful FAXs.
  They have been much more helpful since they started to recognize that the
  word "Linux" refers to an operating system :-).
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/FlashPoint.c linux-libre-2.6.39-gnu/drivers/scsi/FlashPoint.c
--- linux-libre-2.6.38-gnu/drivers/scsi/FlashPoint.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/FlashPoint.c	2011-05-19 00:06:34.000000000 -0400
@@ -2509,7 +2509,7 @@
 				WR_HARPOON(port + hp_autostart_3,
 					   (SELECT + SELCHK_STRT));
 
-				/* Setup our STATE so we know what happend when
+				/* Setup our STATE so we know what happened when
 				   the wheels fall off. */
 				currSCCB->Sccb_scsistat = SELECT_ST;
 
@@ -2900,7 +2900,7 @@
  *
  * Function: FPT_sdecm
  *
- * Description: Determine the proper responce to the message from the
+ * Description: Determine the proper response to the message from the
  *              target device.
  *
  *---------------------------------------------------------------------*/
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fnic/fnic_fcs.c linux-libre-2.6.39-gnu/drivers/scsi/fnic/fnic_fcs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fnic/fnic_fcs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fnic/fnic_fcs.c	2011-05-19 00:06:34.000000000 -0400
@@ -411,7 +411,7 @@
 			err = vnic_rq_fill(&fnic->rq[i], fnic_alloc_rq_frame);
 			if (err)
 				shost_printk(KERN_ERR, fnic->lport->host,
-					     "fnic_alloc_rq_frame cant alloc"
+					     "fnic_alloc_rq_frame can't alloc"
 					     " frame\n");
 		}
 		tot_rq_work_done += cur_work_done;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fnic/fnic.h linux-libre-2.6.39-gnu/drivers/scsi/fnic/fnic.h
--- linux-libre-2.6.38-gnu/drivers/scsi/fnic/fnic.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fnic/fnic.h	2011-05-19 00:06:34.000000000 -0400
@@ -37,7 +37,7 @@
 
 #define DRV_NAME		"fnic"
 #define DRV_DESCRIPTION		"Cisco FCoE HBA Driver"
-#define DRV_VERSION		"1.4.0.145"
+#define DRV_VERSION		"1.5.0.1"
 #define PFX			DRV_NAME ": "
 #define DFX                     DRV_NAME "%d: "
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fnic/fnic_scsi.c linux-libre-2.6.39-gnu/drivers/scsi/fnic/fnic_scsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fnic/fnic_scsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fnic/fnic_scsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1123,7 +1123,7 @@
 					    fc_lun.scsi_lun, io_req)) {
 			/*
 			 * Revert the cmd state back to old state, if
-			 * it hasnt changed in between. This cmd will get
+			 * it hasn't changed in between. This cmd will get
 			 * aborted later by scsi_eh, or cleaned up during
 			 * lun reset
 			 */
@@ -1208,7 +1208,7 @@
 					    fc_lun.scsi_lun, io_req)) {
 			/*
 			 * Revert the cmd state back to old state, if
-			 * it hasnt changed in between. This cmd will get
+			 * it hasn't changed in between. This cmd will get
 			 * aborted later by scsi_eh, or cleaned up during
 			 * lun reset
 			 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/fnic/vnic_dev.c linux-libre-2.6.39-gnu/drivers/scsi/fnic/vnic_dev.c
--- linux-libre-2.6.38-gnu/drivers/scsi/fnic/vnic_dev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/fnic/vnic_dev.c	2011-05-19 00:06:34.000000000 -0400
@@ -654,7 +654,7 @@
 				vdev->linkstatus_pa);
 		if (vdev->stats)
 			pci_free_consistent(vdev->pdev,
-				sizeof(struct vnic_dev),
+				sizeof(struct vnic_stats),
 				vdev->stats, vdev->stats_pa);
 		if (vdev->fw_info)
 			pci_free_consistent(vdev->pdev,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/gdth.h linux-libre-2.6.39-gnu/drivers/scsi/gdth.h
--- linux-libre-2.6.38-gnu/drivers/scsi/gdth.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/gdth.h	2011-05-19 00:06:34.000000000 -0400
@@ -895,7 +895,7 @@
         u8          ldr_no;                 /* log. drive no. */
         u8          rw_attribs;             /* r/w attributes */
         u8          cluster_type;           /* cluster properties */
-        u8          media_changed;          /* Flag:MOUNT/UNMOUNT occured */
+        u8          media_changed;          /* Flag:MOUNT/UNMOUNT occurred */
         u32         start_sec;              /* start sector */
     } hdr[MAX_LDRIVES];                         /* host drives */
     struct {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/g_NCR5380.c linux-libre-2.6.39-gnu/drivers/scsi/g_NCR5380.c
--- linux-libre-2.6.38-gnu/drivers/scsi/g_NCR5380.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/g_NCR5380.c	2011-05-19 00:06:34.000000000 -0400
@@ -566,7 +566,7 @@
  *	@dst: buffer to read into
  *	@len: buffer length
  *
- *	Perform a psuedo DMA mode read from an NCR53C400 or equivalent
+ *	Perform a pseudo DMA mode read from an NCR53C400 or equivalent
  *	controller
  */
  
@@ -650,7 +650,7 @@
  *	@dst: buffer to read into
  *	@len: buffer length
  *
- *	Perform a psuedo DMA mode read from an NCR53C400 or equivalent
+ *	Perform a pseudo DMA mode read from an NCR53C400 or equivalent
  *	controller
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/gvp11.c linux-libre-2.6.39-gnu/drivers/scsi/gvp11.c
--- linux-libre-2.6.38-gnu/drivers/scsi/gvp11.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/gvp11.c	2011-05-19 00:06:34.000000000 -0400
@@ -300,7 +300,7 @@
 	/*
 	 * Rumors state that some GVP ram boards use the same product
 	 * code as the SCSI controllers. Therefore if the board-size
-	 * is not 64KB we asume it is a ram board and bail out.
+	 * is not 64KB we assume it is a ram board and bail out.
 	 */
 	if (zorro_resource_len(z) != 0x10000)
 		return -ENODEV;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/hpsa.c linux-libre-2.6.39-gnu/drivers/scsi/hpsa.c
--- linux-libre-2.6.38-gnu/drivers/scsi/hpsa.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/hpsa.c	2011-05-19 00:06:34.000000000 -0400
@@ -74,6 +74,10 @@
 module_param(hpsa_allow_any, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(hpsa_allow_any,
 		"Allow hpsa driver to access unknown HP Smart Array hardware");
+static int hpsa_simple_mode;
+module_param(hpsa_simple_mode, int, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(hpsa_simple_mode,
+	"Use 'simple mode' rather than 'performant mode'");
 
 /* define the PCI info for the cards we can control */
 static const struct pci_device_id hpsa_pci_device_id[] = {
@@ -85,11 +89,13 @@
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324a},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x324b},
 	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3233},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3250},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3251},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3252},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3253},
-	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSE,     0x103C, 0x3254},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3350},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3351},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3352},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3353},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3354},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3355},
+	{PCI_VENDOR_ID_HP,     PCI_DEVICE_ID_HP_CISSF,     0x103C, 0x3356},
 	{PCI_VENDOR_ID_HP,     PCI_ANY_ID,	PCI_ANY_ID, PCI_ANY_ID,
 		PCI_CLASS_STORAGE_RAID << 8, 0xffff << 8, 0},
 	{0,}
@@ -109,11 +115,13 @@
 	{0x3249103C, "Smart Array P812", &SA5_access},
 	{0x324a103C, "Smart Array P712m", &SA5_access},
 	{0x324b103C, "Smart Array P711m", &SA5_access},
-	{0x3250103C, "Smart Array", &SA5_access},
-	{0x3250113C, "Smart Array", &SA5_access},
-	{0x3250123C, "Smart Array", &SA5_access},
-	{0x3250133C, "Smart Array", &SA5_access},
-	{0x3250143C, "Smart Array", &SA5_access},
+	{0x3350103C, "Smart Array", &SA5_access},
+	{0x3351103C, "Smart Array", &SA5_access},
+	{0x3352103C, "Smart Array", &SA5_access},
+	{0x3353103C, "Smart Array", &SA5_access},
+	{0x3354103C, "Smart Array", &SA5_access},
+	{0x3355103C, "Smart Array", &SA5_access},
+	{0x3356103C, "Smart Array", &SA5_access},
 	{0xFFFF103C, "Unknown Smart Array", &SA5_access},
 };
 
@@ -147,17 +155,7 @@
 static int hpsa_slave_alloc(struct scsi_device *sdev);
 static void hpsa_slave_destroy(struct scsi_device *sdev);
 
-static ssize_t raid_level_show(struct device *dev,
-	struct device_attribute *attr, char *buf);
-static ssize_t lunid_show(struct device *dev,
-	struct device_attribute *attr, char *buf);
-static ssize_t unique_id_show(struct device *dev,
-	struct device_attribute *attr, char *buf);
-static ssize_t host_show_firmware_revision(struct device *dev,
-	     struct device_attribute *attr, char *buf);
 static void hpsa_update_scsi_devices(struct ctlr_info *h, int hostno);
-static ssize_t host_store_rescan(struct device *dev,
-	 struct device_attribute *attr, const char *buf, size_t count);
 static int check_for_unit_attention(struct ctlr_info *h,
 	struct CommandList *c);
 static void check_ioctl_unit_attention(struct ctlr_info *h,
@@ -173,47 +171,10 @@
 static int __devinit hpsa_pci_find_memory_BAR(struct pci_dev *pdev,
 	unsigned long *memory_bar);
 static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id);
-
-static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
-static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
-static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
-static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
-static DEVICE_ATTR(firmware_revision, S_IRUGO,
-	host_show_firmware_revision, NULL);
-
-static struct device_attribute *hpsa_sdev_attrs[] = {
-	&dev_attr_raid_level,
-	&dev_attr_lunid,
-	&dev_attr_unique_id,
-	NULL,
-};
-
-static struct device_attribute *hpsa_shost_attrs[] = {
-	&dev_attr_rescan,
-	&dev_attr_firmware_revision,
-	NULL,
-};
-
-static struct scsi_host_template hpsa_driver_template = {
-	.module			= THIS_MODULE,
-	.name			= "hpsa",
-	.proc_name		= "hpsa",
-	.queuecommand		= hpsa_scsi_queue_command,
-	.scan_start		= hpsa_scan_start,
-	.scan_finished		= hpsa_scan_finished,
-	.change_queue_depth	= hpsa_change_queue_depth,
-	.this_id		= -1,
-	.use_clustering		= ENABLE_CLUSTERING,
-	.eh_device_reset_handler = hpsa_eh_device_reset_handler,
-	.ioctl			= hpsa_ioctl,
-	.slave_alloc		= hpsa_slave_alloc,
-	.slave_destroy		= hpsa_slave_destroy,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl		= hpsa_compat_ioctl,
-#endif
-	.sdev_attrs = hpsa_sdev_attrs,
-	.shost_attrs = hpsa_shost_attrs,
-};
+static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
+	void __iomem *vaddr, int wait_for_ready);
+#define BOARD_NOT_READY 0
+#define BOARD_READY 1
 
 static inline struct ctlr_info *sdev_to_hba(struct scsi_device *sdev)
 {
@@ -291,67 +252,63 @@
 		fwrev[0], fwrev[1], fwrev[2], fwrev[3]);
 }
 
-/* Enqueuing and dequeuing functions for cmdlists. */
-static inline void addQ(struct hlist_head *list, struct CommandList *c)
+static ssize_t host_show_commands_outstanding(struct device *dev,
+	     struct device_attribute *attr, char *buf)
 {
-	hlist_add_head(&c->list, list);
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct ctlr_info *h = shost_to_hba(shost);
+
+	return snprintf(buf, 20, "%d\n", h->commands_outstanding);
 }
 
-static inline u32 next_command(struct ctlr_info *h)
+static ssize_t host_show_transport_mode(struct device *dev,
+	struct device_attribute *attr, char *buf)
 {
-	u32 a;
-
-	if (unlikely(h->transMethod != CFGTBL_Trans_Performant))
-		return h->access.command_completed(h);
+	struct ctlr_info *h;
+	struct Scsi_Host *shost = class_to_shost(dev);
 
-	if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
-		a = *(h->reply_pool_head); /* Next cmd in ring buffer */
-		(h->reply_pool_head)++;
-		h->commands_outstanding--;
-	} else {
-		a = FIFO_EMPTY;
-	}
-	/* Check for wraparound */
-	if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
-		h->reply_pool_head = h->reply_pool;
-		h->reply_pool_wraparound ^= 1;
-	}
-	return a;
+	h = shost_to_hba(shost);
+	return snprintf(buf, 20, "%s\n",
+		h->transMethod & CFGTBL_Trans_Performant ?
+			"performant" : "simple");
 }
 
-/* set_performant_mode: Modify the tag for cciss performant
- * set bit 0 for pull model, bits 3-1 for block fetch
- * register number
- */
-static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
-{
-	if (likely(h->transMethod == CFGTBL_Trans_Performant))
-		c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
-}
+/* List of controllers which cannot be reset on kexec with reset_devices */
+static u32 unresettable_controller[] = {
+	0x324a103C, /* Smart Array P712m */
+	0x324b103C, /* SmartArray P711m */
+	0x3223103C, /* Smart Array P800 */
+	0x3234103C, /* Smart Array P400 */
+	0x3235103C, /* Smart Array P400i */
+	0x3211103C, /* Smart Array E200i */
+	0x3212103C, /* Smart Array E200 */
+	0x3213103C, /* Smart Array E200i */
+	0x3214103C, /* Smart Array E200i */
+	0x3215103C, /* Smart Array E200i */
+	0x3237103C, /* Smart Array E500 */
+	0x323D103C, /* Smart Array P700m */
+	0x409C0E11, /* Smart Array 6400 */
+	0x409D0E11, /* Smart Array 6400 EM */
+};
 
-static void enqueue_cmd_and_start_io(struct ctlr_info *h,
-	struct CommandList *c)
+static int ctlr_is_resettable(struct ctlr_info *h)
 {
-	unsigned long flags;
+	int i;
 
-	set_performant_mode(h, c);
-	spin_lock_irqsave(&h->lock, flags);
-	addQ(&h->reqQ, c);
-	h->Qdepth++;
-	start_io(h);
-	spin_unlock_irqrestore(&h->lock, flags);
+	for (i = 0; i < ARRAY_SIZE(unresettable_controller); i++)
+		if (unresettable_controller[i] == h->board_id)
+			return 0;
+	return 1;
 }
 
-static inline void removeQ(struct CommandList *c)
+static ssize_t host_show_resettable(struct device *dev,
+	struct device_attribute *attr, char *buf)
 {
-	if (WARN_ON(hlist_unhashed(&c->list)))
-		return;
-	hlist_del_init(&c->list);
-}
+	struct ctlr_info *h;
+	struct Scsi_Host *shost = class_to_shost(dev);
 
-static inline int is_hba_lunid(unsigned char scsi3addr[])
-{
-	return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0;
+	h = shost_to_hba(shost);
+	return snprintf(buf, 20, "%d\n", ctlr_is_resettable(h));
 }
 
 static inline int is_logical_dev_addr_mode(unsigned char scsi3addr[])
@@ -359,15 +316,6 @@
 	return (scsi3addr[3] & 0xC0) == 0x40;
 }
 
-static inline int is_scsi_rev_5(struct ctlr_info *h)
-{
-	if (!h->hba_inquiry_data)
-		return 0;
-	if ((h->hba_inquiry_data[2] & 0x07) == 5)
-		return 1;
-	return 0;
-}
-
 static const char *raid_label[] = { "0", "4", "1(1+0)", "5", "5+1", "ADG",
 	"UNKNOWN"
 };
@@ -459,6 +407,129 @@
 			sn[12], sn[13], sn[14], sn[15]);
 }
 
+static DEVICE_ATTR(raid_level, S_IRUGO, raid_level_show, NULL);
+static DEVICE_ATTR(lunid, S_IRUGO, lunid_show, NULL);
+static DEVICE_ATTR(unique_id, S_IRUGO, unique_id_show, NULL);
+static DEVICE_ATTR(rescan, S_IWUSR, NULL, host_store_rescan);
+static DEVICE_ATTR(firmware_revision, S_IRUGO,
+	host_show_firmware_revision, NULL);
+static DEVICE_ATTR(commands_outstanding, S_IRUGO,
+	host_show_commands_outstanding, NULL);
+static DEVICE_ATTR(transport_mode, S_IRUGO,
+	host_show_transport_mode, NULL);
+static DEVICE_ATTR(resettable, S_IRUGO,
+	host_show_resettable, NULL);
+
+static struct device_attribute *hpsa_sdev_attrs[] = {
+	&dev_attr_raid_level,
+	&dev_attr_lunid,
+	&dev_attr_unique_id,
+	NULL,
+};
+
+static struct device_attribute *hpsa_shost_attrs[] = {
+	&dev_attr_rescan,
+	&dev_attr_firmware_revision,
+	&dev_attr_commands_outstanding,
+	&dev_attr_transport_mode,
+	&dev_attr_resettable,
+	NULL,
+};
+
+static struct scsi_host_template hpsa_driver_template = {
+	.module			= THIS_MODULE,
+	.name			= "hpsa",
+	.proc_name		= "hpsa",
+	.queuecommand		= hpsa_scsi_queue_command,
+	.scan_start		= hpsa_scan_start,
+	.scan_finished		= hpsa_scan_finished,
+	.change_queue_depth	= hpsa_change_queue_depth,
+	.this_id		= -1,
+	.use_clustering		= ENABLE_CLUSTERING,
+	.eh_device_reset_handler = hpsa_eh_device_reset_handler,
+	.ioctl			= hpsa_ioctl,
+	.slave_alloc		= hpsa_slave_alloc,
+	.slave_destroy		= hpsa_slave_destroy,
+#ifdef CONFIG_COMPAT
+	.compat_ioctl		= hpsa_compat_ioctl,
+#endif
+	.sdev_attrs = hpsa_sdev_attrs,
+	.shost_attrs = hpsa_shost_attrs,
+};
+
+
+/* Enqueuing and dequeuing functions for cmdlists. */
+static inline void addQ(struct list_head *list, struct CommandList *c)
+{
+	list_add_tail(&c->list, list);
+}
+
+static inline u32 next_command(struct ctlr_info *h)
+{
+	u32 a;
+
+	if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
+		return h->access.command_completed(h);
+
+	if ((*(h->reply_pool_head) & 1) == (h->reply_pool_wraparound)) {
+		a = *(h->reply_pool_head); /* Next cmd in ring buffer */
+		(h->reply_pool_head)++;
+		h->commands_outstanding--;
+	} else {
+		a = FIFO_EMPTY;
+	}
+	/* Check for wraparound */
+	if (h->reply_pool_head == (h->reply_pool + h->max_commands)) {
+		h->reply_pool_head = h->reply_pool;
+		h->reply_pool_wraparound ^= 1;
+	}
+	return a;
+}
+
+/* set_performant_mode: Modify the tag for cciss performant
+ * set bit 0 for pull model, bits 3-1 for block fetch
+ * register number
+ */
+static void set_performant_mode(struct ctlr_info *h, struct CommandList *c)
+{
+	if (likely(h->transMethod & CFGTBL_Trans_Performant))
+		c->busaddr |= 1 | (h->blockFetchTable[c->Header.SGList] << 1);
+}
+
+static void enqueue_cmd_and_start_io(struct ctlr_info *h,
+	struct CommandList *c)
+{
+	unsigned long flags;
+
+	set_performant_mode(h, c);
+	spin_lock_irqsave(&h->lock, flags);
+	addQ(&h->reqQ, c);
+	h->Qdepth++;
+	start_io(h);
+	spin_unlock_irqrestore(&h->lock, flags);
+}
+
+static inline void removeQ(struct CommandList *c)
+{
+	if (WARN_ON(list_empty(&c->list)))
+		return;
+	list_del_init(&c->list);
+}
+
+static inline int is_hba_lunid(unsigned char scsi3addr[])
+{
+	return memcmp(scsi3addr, RAID_CTLR_LUNID, 8) == 0;
+}
+
+static inline int is_scsi_rev_5(struct ctlr_info *h)
+{
+	if (!h->hba_inquiry_data)
+		return 0;
+	if ((h->hba_inquiry_data[2] & 0x07) == 5)
+		return 1;
+	return 0;
+}
+
 static int hpsa_find_target_lun(struct ctlr_info *h,
 	unsigned char scsi3addr[], int bus, int *target, int *lun)
 {
@@ -1130,6 +1201,10 @@
 		cmd->result = DID_TIME_OUT << 16;
 		dev_warn(&h->pdev->dev, "cp %p timedout\n", cp);
 		break;
+	case CMD_UNABORTABLE:
+		cmd->result = DID_ERROR << 16;
+		dev_warn(&h->pdev->dev, "Command unabortable\n");
+		break;
 	default:
 		cmd->result = DID_ERROR << 16;
 		dev_warn(&h->pdev->dev, "cp %p returned unknown status %x\n",
@@ -1160,7 +1235,7 @@
 	sh->sg_tablesize = h->maxsgentries;
 	h->scsi_host = sh;
 	sh->hostdata[0] = (unsigned long) h;
-	sh->irq = h->intr[PERF_MODE_INT];
+	sh->irq = h->intr[h->intr_mode];
 	sh->unique_id = sh->irq;
 	error = scsi_add_host(sh, &h->pdev->dev);
 	if (error)
@@ -1295,6 +1370,9 @@
 	case CMD_TIMEOUT:
 		dev_warn(d, "cp %p timed out\n", cp);
 		break;
+	case CMD_UNABORTABLE:
+		dev_warn(d, "Command unabortable\n");
+		break;
 	default:
 		dev_warn(d, "cp %p returned unknown status %x\n", cp,
 				ei->CommandStatus);
@@ -1595,6 +1673,8 @@
 	if (lun == 0) /* if lun is 0, then obviously we have a lun 0. */
 		return 0;
 
+	memset(scsi3addr, 0, 8);
+	scsi3addr[3] = target;
 	if (is_hba_lunid(scsi3addr))
 		return 0; /* Don't add the RAID controller here. */
 
@@ -1609,8 +1689,6 @@
 		return 0;
 	}
 
-	memset(scsi3addr, 0, 8);
-	scsi3addr[3] = target;
 	if (hpsa_update_device_info(h, scsi3addr, this_device))
 		return 0;
 	(*nmsa2xxx_enclosures)++;
@@ -2199,7 +2277,7 @@
 
 	c->cmdindex = i;
 
-	INIT_HLIST_NODE(&c->list);
+	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (u32) cmd_dma_handle;
 	temp64.val = (u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -2237,7 +2315,7 @@
 	}
 	memset(c->err_info, 0, sizeof(*c->err_info));
 
-	INIT_HLIST_NODE(&c->list);
+	INIT_LIST_HEAD(&c->list);
 	c->busaddr = (u32) cmd_dma_handle;
 	temp64.val = (u64) err_dma_handle;
 	c->ErrDesc.Addr.lower = temp64.val32.lower;
@@ -2267,7 +2345,7 @@
 	pci_free_consistent(h->pdev, sizeof(*c->err_info),
 			    c->err_info, (dma_addr_t) temp64.val);
 	pci_free_consistent(h->pdev, sizeof(*c),
-			    c, (dma_addr_t) c->busaddr);
+			    c, (dma_addr_t) (c->busaddr & DIRECT_LOOKUP_MASK));
 }
 
 #ifdef CONFIG_COMPAT
@@ -2281,6 +2359,7 @@
 	int err;
 	u32 cp;
 
+	memset(&arg64, 0, sizeof(arg64));
 	err = 0;
 	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
 			   sizeof(arg64.LUN_info));
@@ -2317,6 +2396,7 @@
 	int err;
 	u32 cp;
 
+	memset(&arg64, 0, sizeof(arg64));
 	err = 0;
 	err |= copy_from_user(&arg64.LUN_info, &arg32->LUN_info,
 			   sizeof(arg64.LUN_info));
@@ -2433,15 +2513,17 @@
 		buff = kmalloc(iocommand.buf_size, GFP_KERNEL);
 		if (buff == NULL)
 			return -EFAULT;
-	}
-	if (iocommand.Request.Type.Direction == XFER_WRITE) {
-		/* Copy the data into the buffer we created */
-		if (copy_from_user(buff, iocommand.buf, iocommand.buf_size)) {
-			kfree(buff);
-			return -EFAULT;
+		if (iocommand.Request.Type.Direction == XFER_WRITE) {
+			/* Copy the data into the buffer we created */
+			if (copy_from_user(buff, iocommand.buf,
+				iocommand.buf_size)) {
+				kfree(buff);
+				return -EFAULT;
+			}
+		} else {
+			memset(buff, 0, iocommand.buf_size);
 		}
-	} else
-		memset(buff, 0, iocommand.buf_size);
+	}
 	c = cmd_special_alloc(h);
 	if (c == NULL) {
 		kfree(buff);
@@ -2487,8 +2569,8 @@
 		cmd_special_free(h, c);
 		return -EFAULT;
 	}
-
-	if (iocommand.Request.Type.Direction == XFER_READ) {
+	if (iocommand.Request.Type.Direction == XFER_READ &&
+		iocommand.buf_size > 0) {
 		/* Copy the data out of the buffer we created */
 		if (copy_to_user(iocommand.buf, buff, iocommand.buf_size)) {
 			kfree(buff);
@@ -2581,14 +2663,7 @@
 	}
 	c->cmd_type = CMD_IOCTL_PEND;
 	c->Header.ReplyQueue = 0;
-
-	if (ioc->buf_size > 0) {
-		c->Header.SGList = sg_used;
-		c->Header.SGTotal = sg_used;
-	} else {
-		c->Header.SGList = 0;
-		c->Header.SGTotal = 0;
-	}
+	c->Header.SGList = c->Header.SGTotal = sg_used;
 	memcpy(&c->Header.LUN, &ioc->LUN_info, sizeof(c->Header.LUN));
 	c->Header.Tag.lower = c->busaddr;
 	memcpy(&c->Request, &ioc->Request, sizeof(c->Request));
@@ -2605,7 +2680,8 @@
 		}
 	}
 	hpsa_scsi_do_simple_cmd_core(h, c);
-	hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
+	if (sg_used)
+		hpsa_pci_unmap(h->pdev, c, sg_used, PCI_DMA_BIDIRECTIONAL);
 	check_ioctl_unit_attention(h, c);
 	/* Copy the error information out */
 	memcpy(&ioc->error_info, c->err_info, sizeof(ioc->error_info));
@@ -2614,7 +2690,7 @@
 		status = -EFAULT;
 		goto cleanup1;
 	}
-	if (ioc->Request.Type.Direction == XFER_READ) {
+	if (ioc->Request.Type.Direction == XFER_READ && ioc->buf_size > 0) {
 		/* Copy the data out of the buffer we created */
 		BYTE __user *ptr = ioc->buf;
 		for (i = 0; i < sg_used; i++) {
@@ -2810,8 +2886,8 @@
 {
 	struct CommandList *c;
 
-	while (!hlist_empty(&h->reqQ)) {
-		c = hlist_entry(h->reqQ.first, struct CommandList, list);
+	while (!list_empty(&h->reqQ)) {
+		c = list_entry(h->reqQ.next, struct CommandList, list);
 		/* can't do anything if fifo is full */
 		if ((h->access.fifo_full(h))) {
 			dev_warn(&h->pdev->dev, "fifo full\n");
@@ -2867,20 +2943,22 @@
 
 static inline u32 hpsa_tag_contains_index(u32 tag)
 {
-#define DIRECT_LOOKUP_BIT 0x10
 	return tag & DIRECT_LOOKUP_BIT;
 }
 
 static inline u32 hpsa_tag_to_index(u32 tag)
 {
-#define DIRECT_LOOKUP_SHIFT 5
 	return tag >> DIRECT_LOOKUP_SHIFT;
 }
 
-static inline u32 hpsa_tag_discard_error_bits(u32 tag)
+
+static inline u32 hpsa_tag_discard_error_bits(struct ctlr_info *h, u32 tag)
 {
-#define HPSA_ERROR_BITS 0x03
-	return tag & ~HPSA_ERROR_BITS;
+#define HPSA_PERF_ERROR_BITS ((1 << DIRECT_LOOKUP_SHIFT) - 1)
+#define HPSA_SIMPLE_ERROR_BITS 0x03
+	if (unlikely(!(h->transMethod & CFGTBL_Trans_Performant)))
+		return tag & ~HPSA_SIMPLE_ERROR_BITS;
+	return tag & ~HPSA_PERF_ERROR_BITS;
 }
 
 /* process completion of an indexed ("direct lookup") command */
@@ -2904,10 +2982,9 @@
 {
 	u32 tag;
 	struct CommandList *c = NULL;
-	struct hlist_node *tmp;
 
-	tag = hpsa_tag_discard_error_bits(raw_tag);
-	hlist_for_each_entry(c, tmp, &h->cmpQ, list) {
+	tag = hpsa_tag_discard_error_bits(h, raw_tag);
+	list_for_each_entry(c, &h->cmpQ, list) {
 		if ((c->busaddr & 0xFFFFFFE0) == (tag & 0xFFFFFFE0)) {
 			finish_cmd(c, raw_tag);
 			return next_command(h);
@@ -2957,7 +3034,10 @@
 	return IRQ_HANDLED;
 }
 
-/* Send a message CDB to the firmware. */
+/* Send a message CDB to the firmware. Careful, this only works
+ * in simple mode, not performant mode due to the tag lookup.
+ * We only ever use this immediately after a controller reset.
+ */
 static __devinit int hpsa_message(struct pci_dev *pdev, unsigned char opcode,
 						unsigned char type)
 {
@@ -3023,7 +3103,7 @@
 
 	for (i = 0; i < HPSA_MSG_SEND_RETRY_LIMIT; i++) {
 		tag = readl(vaddr + SA5_REPLY_PORT_OFFSET);
-		if (hpsa_tag_discard_error_bits(tag) == paddr32)
+		if ((tag & ~HPSA_SIMPLE_ERROR_BITS) == paddr32)
 			break;
 		msleep(HPSA_MSG_SEND_RETRY_INTERVAL_MSECS);
 	}
@@ -3055,38 +3135,6 @@
 #define hpsa_soft_reset_controller(p) hpsa_message(p, 1, 0)
 #define hpsa_noop(p) hpsa_message(p, 3, 0)
 
-static __devinit int hpsa_reset_msi(struct pci_dev *pdev)
-{
-/* the #defines are stolen from drivers/pci/msi.h. */
-#define msi_control_reg(base)		(base + PCI_MSI_FLAGS)
-#define PCI_MSIX_FLAGS_ENABLE		(1 << 15)
-
-	int pos;
-	u16 control = 0;
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSI);
-	if (pos) {
-		pci_read_config_word(pdev, msi_control_reg(pos), &control);
-		if (control & PCI_MSI_FLAGS_ENABLE) {
-			dev_info(&pdev->dev, "resetting MSI\n");
-			pci_write_config_word(pdev, msi_control_reg(pos),
-					control & ~PCI_MSI_FLAGS_ENABLE);
-		}
-	}
-
-	pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
-	if (pos) {
-		pci_read_config_word(pdev, msi_control_reg(pos), &control);
-		if (control & PCI_MSIX_FLAGS_ENABLE) {
-			dev_info(&pdev->dev, "resetting MSI-X\n");
-			pci_write_config_word(pdev, msi_control_reg(pos),
-					control & ~PCI_MSIX_FLAGS_ENABLE);
-		}
-	}
-
-	return 0;
-}
-
 static int hpsa_controller_hard_reset(struct pci_dev *pdev,
 	void * __iomem vaddr, bool use_doorbell)
 {
@@ -3142,17 +3190,17 @@
  */
 static __devinit int hpsa_kdump_hard_reset_controller(struct pci_dev *pdev)
 {
-	u16 saved_config_space[32];
 	u64 cfg_offset;
 	u32 cfg_base_addr;
 	u64 cfg_base_addr_index;
 	void __iomem *vaddr;
 	unsigned long paddr;
 	u32 misc_fw_support, active_transport;
-	int rc, i;
+	int rc;
 	struct CfgTable __iomem *cfgtable;
 	bool use_doorbell;
 	u32 board_id;
+	u16 command_register;
 
 	/* For controllers as old as the P600, this is very nearly
 	 * the same thing as
@@ -3162,14 +3210,6 @@
 	 * pci_set_power_state(pci_dev, PCI_D0);
 	 * pci_restore_state(pci_dev);
 	 *
-	 * but we can't use these nice canned kernel routines on
-	 * kexec, because they also check the MSI/MSI-X state in PCI
-	 * configuration space and do the wrong thing when it is
-	 * set/cleared.  Also, the pci_save/restore_state functions
-	 * violate the ordering requirements for restoring the
-	 * configuration space from the CCISS document (see the
-	 * comment below).  So we roll our own ....
-	 *
 	 * For controllers newer than the P600, the pci power state
 	 * method of resetting doesn't work so we have another way
 	 * using the doorbell register.
@@ -3182,13 +3222,21 @@
 	 * likely not be happy.  Just forbid resetting this conjoined mess.
 	 * The 640x isn't really supported by hpsa anyway.
 	 */
-	hpsa_lookup_board_id(pdev, &board_id);
+	rc = hpsa_lookup_board_id(pdev, &board_id);
+	if (rc < 0) {
+		dev_warn(&pdev->dev, "Not resetting device.\n");
+		return -ENODEV;
+	}
 	if (board_id == 0x409C0E11 || board_id == 0x409D0E11)
 		return -ENOTSUPP;
 
-	for (i = 0; i < 32; i++)
-		pci_read_config_word(pdev, 2*i, &saved_config_space[i]);
-
+	/* Save the PCI command register */
+	pci_read_config_word(pdev, 4, &command_register);
+	/* Turn the board off.  This is so that later pci_restore_state()
+	 * won't turn the board on before the rest of config space is ready.
+	 */
+	pci_disable_device(pdev);
+	pci_save_state(pdev);
 
 	/* find the first memory BAR, so we can find the cfg table */
 	rc = hpsa_pci_find_memory_BAR(pdev, &paddr);
@@ -3214,46 +3262,47 @@
 	misc_fw_support = readl(&cfgtable->misc_fw_support);
 	use_doorbell = misc_fw_support & MISC_FW_DOORBELL_RESET;
 
-	/* The doorbell reset seems to cause lockups on some Smart
-	 * Arrays (e.g. P410, P410i, maybe others).  Until this is
-	 * fixed or at least isolated, avoid the doorbell reset.
-	 */
-	use_doorbell = 0;
-
 	rc = hpsa_controller_hard_reset(pdev, vaddr, use_doorbell);
 	if (rc)
 		goto unmap_cfgtable;
 
-	/* Restore the PCI configuration space.  The Open CISS
-	 * Specification says, "Restore the PCI Configuration
-	 * Registers, offsets 00h through 60h. It is important to
-	 * restore the command register, 16-bits at offset 04h,
-	 * last. Do not restore the configuration status register,
-	 * 16-bits at offset 06h."  Note that the offset is 2*i.
-	 */
-	for (i = 0; i < 32; i++) {
-		if (i == 2 || i == 3)
-			continue;
-		pci_write_config_word(pdev, 2*i, saved_config_space[i]);
+	pci_restore_state(pdev);
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_warn(&pdev->dev, "failed to enable device.\n");
+		goto unmap_cfgtable;
 	}
-	wmb();
-	pci_write_config_word(pdev, 4, saved_config_space[2]);
+	pci_write_config_word(pdev, 4, command_register);
 
 	/* Some devices (notably the HP Smart Array 5i Controller)
 	   need a little pause here */
 	msleep(HPSA_POST_RESET_PAUSE_MSECS);
 
+	/* Wait for board to become not ready, then ready. */
+	dev_info(&pdev->dev, "Waiting for board to become ready.\n");
+	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_NOT_READY);
+	if (rc)
+		dev_warn(&pdev->dev,
+			"failed waiting for board to become not ready\n");
+	rc = hpsa_wait_for_board_state(pdev, vaddr, BOARD_READY);
+	if (rc) {
+		dev_warn(&pdev->dev,
+			"failed waiting for board to become ready\n");
+		goto unmap_cfgtable;
+	}
+	dev_info(&pdev->dev, "board ready.\n");
+
 	/* Controller should be in simple mode at this point.  If it's not,
 	 * It means we're on one of those controllers which doesn't support
 	 * the doorbell reset method and on which the PCI power management reset
 	 * method doesn't work (P800, for example.)
-	 * In those cases, pretend the reset worked and hope for the best.
+	 * In those cases, don't try to proceed, as it generally doesn't work.
 	 */
 	active_transport = readl(&cfgtable->TransportActive);
 	if (active_transport & PERFORMANT_MODE) {
 		dev_warn(&pdev->dev, "Unable to successfully reset controller,"
-			" proceeding anyway.\n");
-		rc = -ENOTSUPP;
+			" Ignoring controller.\n");
+		rc = -ENODEV;
 	}
 
 unmap_cfgtable:
@@ -3386,7 +3435,7 @@
 default_int_mode:
 #endif				/* CONFIG_PCI_MSI */
 	/* if we get here we're going to use the default interrupt mode */
-	h->intr[PERF_MODE_INT] = h->pdev->irq;
+	h->intr[h->intr_mode] = h->pdev->irq;
 }
 
 static int __devinit hpsa_lookup_board_id(struct pci_dev *pdev, u32 *board_id)
@@ -3438,18 +3487,28 @@
 	return -ENODEV;
 }
 
-static int __devinit hpsa_wait_for_board_ready(struct ctlr_info *h)
+static int __devinit hpsa_wait_for_board_state(struct pci_dev *pdev,
+	void __iomem *vaddr, int wait_for_ready)
 {
-	int i;
+	int i, iterations;
 	u32 scratchpad;
+	if (wait_for_ready)
+		iterations = HPSA_BOARD_READY_ITERATIONS;
+	else
+		iterations = HPSA_BOARD_NOT_READY_ITERATIONS;
 
-	for (i = 0; i < HPSA_BOARD_READY_ITERATIONS; i++) {
-		scratchpad = readl(h->vaddr + SA5_SCRATCHPAD_OFFSET);
-		if (scratchpad == HPSA_FIRMWARE_READY)
-			return 0;
+	for (i = 0; i < iterations; i++) {
+		scratchpad = readl(vaddr + SA5_SCRATCHPAD_OFFSET);
+		if (wait_for_ready) {
+			if (scratchpad == HPSA_FIRMWARE_READY)
+				return 0;
+		} else {
+			if (scratchpad != HPSA_FIRMWARE_READY)
+				return 0;
+		}
 		msleep(HPSA_BOARD_READY_POLL_INTERVAL_MSECS);
 	}
-	dev_warn(&h->pdev->dev, "board not ready, timed out.\n");
+	dev_warn(&pdev->dev, "board not ready, timed out.\n");
 	return -ENODEV;
 }
 
@@ -3497,6 +3556,11 @@
 static void __devinit hpsa_get_max_perf_mode_cmds(struct ctlr_info *h)
 {
 	h->max_commands = readl(&(h->cfgtable->MaxPerformantModeCommands));
+
+	/* Limit commands in memory limited kdump scenario. */
+	if (reset_devices && h->max_commands > 32)
+		h->max_commands = 32;
+
 	if (h->max_commands < 16) {
 		dev_warn(&h->pdev->dev, "Controller reports "
 			"max supported commands of %d, an obvious lie. "
@@ -3571,16 +3635,21 @@
 static void __devinit hpsa_wait_for_mode_change_ack(struct ctlr_info *h)
 {
 	int i;
+	u32 doorbell_value;
+	unsigned long flags;
 
 	/* under certain very rare conditions, this can take awhile.
 	 * (e.g.: hot replace a failed 144GB drive in a RAID 5 set right
 	 * as we enter this code.)
 	 */
 	for (i = 0; i < MAX_CONFIG_WAIT; i++) {
-		if (!(readl(h->vaddr + SA5_DOORBELL) & CFGTBL_ChangeReq))
+		spin_lock_irqsave(&h->lock, flags);
+		doorbell_value = readl(h->vaddr + SA5_DOORBELL);
+		spin_unlock_irqrestore(&h->lock, flags);
+		if (!(doorbell_value & CFGTBL_ChangeReq))
 			break;
 		/* delay and try again */
-		msleep(10);
+		usleep_range(10000, 20000);
 	}
 }
 
@@ -3603,6 +3672,7 @@
 			"unable to get board into simple mode\n");
 		return -ENODEV;
 	}
+	h->transMethod = CFGTBL_Trans_Simple;
 	return 0;
 }
 
@@ -3641,7 +3711,7 @@
 		err = -ENOMEM;
 		goto err_out_free_res;
 	}
-	err = hpsa_wait_for_board_ready(h);
+	err = hpsa_wait_for_board_state(h->pdev, h->vaddr, BOARD_READY);
 	if (err)
 		goto err_out_free_res;
 	err = hpsa_find_cfgtables(h);
@@ -3710,8 +3780,6 @@
 		return 0; /* just try to do the kdump anyhow. */
 	if (rc)
 		return -ENODEV;
-	if (hpsa_reset_msi(pdev))
-		return -ENODEV;
 
 	/* Now try to get the controller to respond to a no-op */
 	for (i = 0; i < HPSA_POST_RESET_NOOP_RETRIES; i++) {
@@ -3749,8 +3817,11 @@
 
 	h->pdev = pdev;
 	h->busy_initializing = 1;
-	INIT_HLIST_HEAD(&h->cmpQ);
-	INIT_HLIST_HEAD(&h->reqQ);
+	h->intr_mode = hpsa_simple_mode ? SIMPLE_MODE_INT : PERF_MODE_INT;
+	INIT_LIST_HEAD(&h->cmpQ);
+	INIT_LIST_HEAD(&h->reqQ);
+	spin_lock_init(&h->lock);
+	spin_lock_init(&h->scan_lock);
 	rc = hpsa_pci_init(h);
 	if (rc != 0)
 		goto clean1;
@@ -3777,20 +3848,20 @@
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
 
 	if (h->msix_vector || h->msi_vector)
-		rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_msi,
+		rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_msi,
 				IRQF_DISABLED, h->devname, h);
 	else
-		rc = request_irq(h->intr[PERF_MODE_INT], do_hpsa_intr_intx,
+		rc = request_irq(h->intr[h->intr_mode], do_hpsa_intr_intx,
 				IRQF_DISABLED, h->devname, h);
 	if (rc) {
 		dev_err(&pdev->dev, "unable to get irq %d for %s\n",
-		       h->intr[PERF_MODE_INT], h->devname);
+		       h->intr[h->intr_mode], h->devname);
 		goto clean2;
 	}
 
 	dev_info(&pdev->dev, "%s: <0x%x> at IRQ %d%s using DAC\n",
 	       h->devname, pdev->device,
-	       h->intr[PERF_MODE_INT], dac ? "" : " not");
+	       h->intr[h->intr_mode], dac ? "" : " not");
 
 	h->cmd_pool_bits =
 	    kmalloc(((h->nr_cmds + BITS_PER_LONG -
@@ -3810,8 +3881,6 @@
 	}
 	if (hpsa_allocate_sg_chain_blocks(h))
 		goto clean4;
-	spin_lock_init(&h->lock);
-	spin_lock_init(&h->scan_lock);
 	init_waitqueue_head(&h->scan_wait_queue);
 	h->scan_finished = 1; /* no scan currently in progress */
 
@@ -3843,7 +3912,7 @@
 			    h->nr_cmds * sizeof(struct ErrorInfo),
 			    h->errinfo_pool,
 			    h->errinfo_pool_dhandle);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 clean2:
 clean1:
 	h->busy_initializing = 0;
@@ -3887,7 +3956,7 @@
 	 */
 	hpsa_flush_cache(h);
 	h->access.set_intr_mask(h, HPSA_INTR_OFF);
-	free_irq(h->intr[PERF_MODE_INT], h);
+	free_irq(h->intr[h->intr_mode], h);
 #ifdef CONFIG_PCI_MSI
 	if (h->msix_vector)
 		pci_disable_msix(h->pdev);
@@ -3989,7 +4058,8 @@
 	}
 }
 
-static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h)
+static __devinit void hpsa_enter_performant_mode(struct ctlr_info *h,
+	u32 use_short_tags)
 {
 	int i;
 	unsigned long register_value;
@@ -4037,7 +4107,7 @@
 	writel(0, &h->transtable->RepQCtrAddrHigh32);
 	writel(h->reply_pool_dhandle, &h->transtable->RepQAddr0Low32);
 	writel(0, &h->transtable->RepQAddr0High32);
-	writel(CFGTBL_Trans_Performant,
+	writel(CFGTBL_Trans_Performant | use_short_tags,
 		&(h->cfgtable->HostWrite.TransportRequest));
 	writel(CFGTBL_ChangeReq, h->vaddr + SA5_DOORBELL);
 	hpsa_wait_for_mode_change_ack(h);
@@ -4047,12 +4117,18 @@
 					" performant mode\n");
 		return;
 	}
+	/* Change the access methods to the performant access methods */
+	h->access = SA5_performant_access;
+	h->transMethod = CFGTBL_Trans_Performant;
 }
 
 static __devinit void hpsa_put_ctlr_into_performant_mode(struct ctlr_info *h)
 {
 	u32 trans_support;
 
+	if (hpsa_simple_mode)
+		return;
+
 	trans_support = readl(&(h->cfgtable->TransportSupport));
 	if (!(trans_support & PERFORMANT_MODE))
 		return;
@@ -4072,11 +4148,8 @@
 		|| (h->blockFetchTable == NULL))
 		goto clean_up;
 
-	hpsa_enter_performant_mode(h);
-
-	/* Change the access methods to the performant access methods */
-	h->access = SA5_performant_access;
-	h->transMethod = CFGTBL_Trans_Performant;
+	hpsa_enter_performant_mode(h,
+		trans_support & CFGTBL_Trans_use_short_tags);
 
 	return;
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/hpsa_cmd.h linux-libre-2.6.39-gnu/drivers/scsi/hpsa_cmd.h
--- linux-libre-2.6.38-gnu/drivers/scsi/hpsa_cmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/hpsa_cmd.h	2011-05-19 00:06:34.000000000 -0400
@@ -104,6 +104,7 @@
 
 #define CFGTBL_Trans_Simple     0x00000002l
 #define CFGTBL_Trans_Performant 0x00000004l
+#define CFGTBL_Trans_use_short_tags 0x20000000l
 
 #define CFGTBL_BusType_Ultra2   0x00000001l
 #define CFGTBL_BusType_Ultra3   0x00000002l
@@ -265,6 +266,7 @@
 
 #define DIRECT_LOOKUP_SHIFT 5
 #define DIRECT_LOOKUP_BIT 0x10
+#define DIRECT_LOOKUP_MASK (~((1 << DIRECT_LOOKUP_SHIFT) - 1))
 
 #define HPSA_ERROR_BIT          0x02
 struct ctlr_info; /* defined in hpsa.h */
@@ -291,7 +293,7 @@
 	struct ctlr_info	   *h;
 	int			   cmd_type;
 	long			   cmdindex;
-	struct hlist_node list;
+	struct list_head list;
 	struct request *rq;
 	struct completion *waiting;
 	void   *scsi_cmd;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/hpsa.h linux-libre-2.6.39-gnu/drivers/scsi/hpsa.h
--- linux-libre-2.6.38-gnu/drivers/scsi/hpsa.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/hpsa.h	2011-05-19 00:06:34.000000000 -0400
@@ -72,11 +72,12 @@
 	unsigned int intr[4];
 	unsigned int msix_vector;
 	unsigned int msi_vector;
+	int intr_mode; /* either PERF_MODE_INT or SIMPLE_MODE_INT */
 	struct access_method access;
 
 	/* queue and queue Info */
-	struct hlist_head reqQ;
-	struct hlist_head cmpQ;
+	struct list_head reqQ;
+	struct list_head cmpQ;
 	unsigned int Qdepth;
 	unsigned int maxQsinceinit;
 	unsigned int maxSG;
@@ -154,12 +155,16 @@
  * HPSA_BOARD_READY_ITERATIONS are derived from those.
  */
 #define HPSA_BOARD_READY_WAIT_SECS (120)
+#define HPSA_BOARD_NOT_READY_WAIT_SECS (10)
 #define HPSA_BOARD_READY_POLL_INTERVAL_MSECS (100)
 #define HPSA_BOARD_READY_POLL_INTERVAL \
 	((HPSA_BOARD_READY_POLL_INTERVAL_MSECS * HZ) / 1000)
 #define HPSA_BOARD_READY_ITERATIONS \
 	((HPSA_BOARD_READY_WAIT_SECS * 1000) / \
 		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
+#define HPSA_BOARD_NOT_READY_ITERATIONS \
+	((HPSA_BOARD_NOT_READY_WAIT_SECS * 1000) / \
+		HPSA_BOARD_READY_POLL_INTERVAL_MSECS)
 #define HPSA_POST_RESET_PAUSE_MSECS (3000)
 #define HPSA_POST_RESET_NOOP_RETRIES (12)
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/imm.c linux-libre-2.6.39-gnu/drivers/scsi/imm.c
--- linux-libre-2.6.38-gnu/drivers/scsi/imm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/imm.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  * 
  * (The IMM is the embedded controller in the ZIP Plus drive.)
  * 
- * My unoffical company acronym list is 21 pages long:
+ * My unofficial company acronym list is 21 pages long:
  *      FLA:    Four letter acronym with built in facility for
  *              future expansion to five letters.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/initio.c linux-libre-2.6.39-gnu/drivers/scsi/initio.c
--- linux-libre-2.6.38-gnu/drivers/scsi/initio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/initio.c	2011-05-19 00:06:34.000000000 -0400
@@ -242,7 +242,7 @@
 
 static u8 initio_rate_tbl[8] =	/* fast 20      */
 {
-				/* nanosecond devide by 4 */
+				/* nanosecond divide by 4 */
 	12,			/* 50ns,  20M   */
 	18,			/* 75ns,  13.3M */
 	25,			/* 100ns, 10M   */
@@ -1917,7 +1917,7 @@
 }
 
 /**
- *	int_initio_scsi_resel	-	Reselection occured
+ *	int_initio_scsi_resel	-	Reselection occurred
  *	@host: InitIO host adapter
  *
  *	A SCSI reselection event has been signalled and the interrupt
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/initio.h linux-libre-2.6.39-gnu/drivers/scsi/initio.h
--- linux-libre-2.6.38-gnu/drivers/scsi/initio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/initio.h	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,7 @@
 #define TUL_SBusId      0x89	/* 09 R   SCSI BUS ID                   */
 #define TUL_STimeOut    0x8A	/* 0A W   Sel/Resel Time Out Register   */
 #define TUL_SIdent      0x8A	/* 0A R   Identify Message Register     */
-#define TUL_SAvail      0x8A	/* 0A R   Availiable Counter Register   */
+#define TUL_SAvail      0x8A	/* 0A R   Available Counter Register   */
 #define TUL_SData       0x8B	/* 0B R/W SCSI data in/out              */
 #define TUL_SFifo       0x8C	/* 0C R/W FIFO                          */
 #define TUL_SSignal     0x90	/* 10 R/W SCSI signal in/out            */
@@ -389,7 +389,7 @@
 /* Bit Definition for status */
 #define SCB_RENT        0x01
 #define SCB_PEND        0x02
-#define SCB_CONTIG      0x04	/* Contigent Allegiance */
+#define SCB_CONTIG      0x04	/* Contingent Allegiance */
 #define SCB_SELECT      0x08
 #define SCB_BUSY        0x10
 #define SCB_DONE        0x20
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ipr.c linux-libre-2.6.39-gnu/drivers/scsi/ipr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ipr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/ipr.c	2011-05-19 00:06:34.000000000 -0400
@@ -1301,7 +1301,7 @@
 			ipr_clear_res_target(res);
 			list_move_tail(&res->queue, &ioa_cfg->free_res_q);
 		}
-	} else if (!res->sdev) {
+	} else if (!res->sdev || res->del_from_ml) {
 		res->add_to_ml = 1;
 		if (ioa_cfg->allow_ml_add_del)
 			schedule_work(&ioa_cfg->work_q);
@@ -3104,7 +3104,10 @@
 				did_work = 1;
 				sdev = res->sdev;
 				if (!scsi_device_get(sdev)) {
-					list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+					if (!res->add_to_ml)
+						list_move_tail(&res->queue, &ioa_cfg->free_res_q);
+					else
+						res->del_from_ml = 0;
 					spin_unlock_irqrestore(ioa_cfg->host->host_lock, lock_flags);
 					scsi_remove_device(sdev);
 					scsi_device_put(sdev);
@@ -6219,11 +6222,10 @@
 };
 
 static struct ata_port_info sata_port_info = {
-	.flags	= ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
-	ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA,
-	.pio_mask	= 0x10, /* pio4 */
-	.mwdma_mask = 0x07,
-	.udma_mask	= 0x7f, /* udma0-6 */
+	.flags		= ATA_FLAG_SATA | ATA_FLAG_PIO_DMA,
+	.pio_mask	= ATA_PIO4_ONLY,
+	.mwdma_mask	= ATA_MWDMA2,
+	.udma_mask	= ATA_UDMA6,
 	.port_ops	= &ipr_sata_ops
 };
 
@@ -8865,7 +8867,7 @@
 
 	spin_unlock_irqrestore(ioa_cfg->host->host_lock, host_lock_flags);
 	wait_event(ioa_cfg->reset_wait_q, !ioa_cfg->in_reset_reload);
-	flush_scheduled_work();
+	flush_work_sync(&ioa_cfg->work_q);
 	spin_lock_irqsave(ioa_cfg->host->host_lock, host_lock_flags);
 
 	spin_lock(&ipr_driver_lock);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ips.c linux-libre-2.6.39-gnu/drivers/scsi/ips.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ips.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/ips.c	2011-05-19 00:06:34.000000000 -0400
@@ -137,7 +137,7 @@
 /*          - Fix path/name for scsi_hosts.h include for 2.6 kernels         */
 /*          - Fix sort order of 7k                                           */
 /*          - Remove 3 unused "inline" functions                             */
-/* 7.12.xx  - Use STATIC functions whereever possible                        */
+/* 7.12.xx  - Use STATIC functions wherever possible                        */
 /*          - Clean up deprecated MODULE_PARM calls                          */
 /* 7.12.05  - Remove Version Matching per IBM request                        */
 /*****************************************************************************/
@@ -1665,7 +1665,7 @@
 	int datasize;
 
 	/* Trombone is the only copperhead that can do packet flash, but only
-	 * for firmware. No one said it had to make sence. */
+	 * for firmware. No one said it had to make sense. */
 	if (IPS_IS_TROMBONE(ha) && pt->CoppCP.cmd.flashfw.type == IPS_FW_IMAGE) {
 		if (ips_usrcmd(ha, pt, scb))
 			return IPS_SUCCESS;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ips.h linux-libre-2.6.39-gnu/drivers/scsi/ips.h
--- linux-libre-2.6.38-gnu/drivers/scsi/ips.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/ips.h	2011-05-19 00:06:34.000000000 -0400
@@ -1193,7 +1193,7 @@
 #define IPS_VER_SEBRING "7.12.02"
 #define IPS_VER_KEYWEST "7.12.02"
 
-/* Compatability IDs for various adapters */
+/* Compatibility IDs for various adapters */
 #define IPS_COMPAT_UNKNOWN ""
 #define IPS_COMPAT_CURRENT "KW710"
 #define IPS_COMPAT_SERVERAID1 "2.25.01"
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/iscsi_tcp.c linux-libre-2.6.39-gnu/drivers/scsi/iscsi_tcp.c
--- linux-libre-2.6.38-gnu/drivers/scsi/iscsi_tcp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/iscsi_tcp.c	2011-05-19 00:06:34.000000000 -0400
@@ -295,7 +295,7 @@
 		rc = iscsi_sw_tcp_xmit_segment(tcp_conn, segment);
 		/*
 		 * We may not have been able to send data because the conn
-		 * is getting stopped. libiscsi will know so propogate err
+		 * is getting stopped. libiscsi will know so propagate err
 		 * for it to do the right thing.
 		 */
 		if (rc == -EAGAIN)
@@ -608,54 +608,12 @@
 	iscsi_sw_tcp_release_conn(conn);
 }
 
-static int iscsi_sw_tcp_get_addr(struct iscsi_conn *conn, struct socket *sock,
-				 char *buf, int *port,
-				 int (*getname)(struct socket *,
-						struct sockaddr *,
-						int *addrlen))
-{
-	struct sockaddr_storage *addr;
-	struct sockaddr_in6 *sin6;
-	struct sockaddr_in *sin;
-	int rc = 0, len;
-
-	addr = kmalloc(sizeof(*addr), GFP_KERNEL);
-	if (!addr)
-		return -ENOMEM;
-
-	if (getname(sock, (struct sockaddr *) addr, &len)) {
-		rc = -ENODEV;
-		goto free_addr;
-	}
-
-	switch (addr->ss_family) {
-	case AF_INET:
-		sin = (struct sockaddr_in *)addr;
-		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, "%pI4", &sin->sin_addr.s_addr);
-		*port = be16_to_cpu(sin->sin_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	case AF_INET6:
-		sin6 = (struct sockaddr_in6 *)addr;
-		spin_lock_bh(&conn->session->lock);
-		sprintf(buf, "%pI6", &sin6->sin6_addr);
-		*port = be16_to_cpu(sin6->sin6_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
-	}
-free_addr:
-	kfree(addr);
-	return rc;
-}
-
 static int
 iscsi_sw_tcp_conn_bind(struct iscsi_cls_session *cls_session,
 		       struct iscsi_cls_conn *cls_conn, uint64_t transport_eph,
 		       int is_leading)
 {
-	struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
-	struct iscsi_host *ihost = shost_priv(shost);
+	struct iscsi_session *session = cls_session->dd_data;
 	struct iscsi_conn *conn = cls_conn->dd_data;
 	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
 	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
@@ -670,27 +628,15 @@
 				  "sockfd_lookup failed %d\n", err);
 		return -EEXIST;
 	}
-	/*
-	 * copy these values now because if we drop the session
-	 * userspace may still want to query the values since we will
-	 * be using them for the reconnect
-	 */
-	err = iscsi_sw_tcp_get_addr(conn, sock, conn->portal_address,
-				    &conn->portal_port, kernel_getpeername);
-	if (err)
-		goto free_socket;
-
-	err = iscsi_sw_tcp_get_addr(conn, sock, ihost->local_address,
-				    &ihost->local_port, kernel_getsockname);
-	if (err)
-		goto free_socket;
 
 	err = iscsi_conn_bind(cls_session, cls_conn, is_leading);
 	if (err)
 		goto free_socket;
 
+	spin_lock_bh(&session->lock);
 	/* bind iSCSI connection and socket */
 	tcp_sw_conn->sock = sock;
+	spin_unlock_bh(&session->lock);
 
 	/* setup Socket parameters */
 	sk = sock->sk;
@@ -752,24 +698,74 @@
 				       enum iscsi_param param, char *buf)
 {
 	struct iscsi_conn *conn = cls_conn->dd_data;
-	int len;
+	struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
+	struct iscsi_sw_tcp_conn *tcp_sw_conn = tcp_conn->dd_data;
+	struct sockaddr_in6 addr;
+	int rc, len;
 
 	switch(param) {
 	case ISCSI_PARAM_CONN_PORT:
-		spin_lock_bh(&conn->session->lock);
-		len = sprintf(buf, "%hu\n", conn->portal_port);
-		spin_unlock_bh(&conn->session->lock);
-		break;
 	case ISCSI_PARAM_CONN_ADDRESS:
 		spin_lock_bh(&conn->session->lock);
-		len = sprintf(buf, "%s\n", conn->portal_address);
+		if (!tcp_sw_conn || !tcp_sw_conn->sock) {
+			spin_unlock_bh(&conn->session->lock);
+			return -ENOTCONN;
+		}
+		rc = kernel_getpeername(tcp_sw_conn->sock,
+					(struct sockaddr *)&addr, &len);
 		spin_unlock_bh(&conn->session->lock);
-		break;
+		if (rc)
+			return rc;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+						 &addr, param, buf);
 	default:
 		return iscsi_conn_get_param(cls_conn, param, buf);
 	}
 
-	return len;
+	return 0;
+}
+
+static int iscsi_sw_tcp_host_get_param(struct Scsi_Host *shost,
+				       enum iscsi_host_param param, char *buf)
+{
+	struct iscsi_sw_tcp_host *tcp_sw_host = iscsi_host_priv(shost);
+	struct iscsi_session *session = tcp_sw_host->session;
+	struct iscsi_conn *conn;
+	struct iscsi_tcp_conn *tcp_conn;
+	struct iscsi_sw_tcp_conn *tcp_sw_conn;
+	struct sockaddr_in6 addr;
+	int rc, len;
+
+	switch (param) {
+	case ISCSI_HOST_PARAM_IPADDRESS:
+		spin_lock_bh(&session->lock);
+		conn = session->leadconn;
+		if (!conn) {
+			spin_unlock_bh(&session->lock);
+			return -ENOTCONN;
+		}
+		tcp_conn = conn->dd_data;
+
+		tcp_sw_conn = tcp_conn->dd_data;
+		if (!tcp_sw_conn->sock) {
+			spin_unlock_bh(&session->lock);
+			return -ENOTCONN;
+		}
+
+		rc = kernel_getsockname(tcp_sw_conn->sock,
+					(struct sockaddr *)&addr, &len);
+		spin_unlock_bh(&session->lock);
+		if (rc)
+			return rc;
+
+		return iscsi_conn_get_addr_param((struct sockaddr_storage *)
+						 &addr, param, buf);
+	default:
+		return iscsi_host_get_param(shost, param, buf);
+	}
+
+	return 0;
 }
 
 static void
@@ -797,6 +793,7 @@
 {
 	struct iscsi_cls_session *cls_session;
 	struct iscsi_session *session;
+	struct iscsi_sw_tcp_host *tcp_sw_host;
 	struct Scsi_Host *shost;
 
 	if (ep) {
@@ -804,7 +801,8 @@
 		return NULL;
 	}
 
-	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht, 0, 1);
+	shost = iscsi_host_alloc(&iscsi_sw_tcp_sht,
+				 sizeof(struct iscsi_sw_tcp_host), 1);
 	if (!shost)
 		return NULL;
 	shost->transportt = iscsi_sw_tcp_scsi_transport;
@@ -825,6 +823,8 @@
 	if (!cls_session)
 		goto remove_host;
 	session = cls_session->dd_data;
+	tcp_sw_host = iscsi_host_priv(shost);
+	tcp_sw_host->session = session;
 
 	shost->can_queue = session->scsi_cmds_max;
 	if (iscsi_tcp_r2tpool_alloc(session))
@@ -929,7 +929,7 @@
 	.start_conn		= iscsi_conn_start,
 	.stop_conn		= iscsi_sw_tcp_conn_stop,
 	/* iscsi host params */
-	.get_host_param		= iscsi_host_get_param,
+	.get_host_param		= iscsi_sw_tcp_host_get_param,
 	.set_host_param		= iscsi_host_set_param,
 	/* IO */
 	.send_pdu		= iscsi_conn_send_pdu,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/iscsi_tcp.h linux-libre-2.6.39-gnu/drivers/scsi/iscsi_tcp.h
--- linux-libre-2.6.38-gnu/drivers/scsi/iscsi_tcp.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/iscsi_tcp.h	2011-05-19 00:06:34.000000000 -0400
@@ -55,6 +55,10 @@
 	ssize_t (*sendpage)(struct socket *, struct page *, int, size_t, int);
 };
 
+struct iscsi_sw_tcp_host {
+	struct iscsi_session	*session;
+};
+
 struct iscsi_sw_tcp_hdrbuf {
 	struct iscsi_hdr	hdrbuf;
 	char			hdrextbuf[ISCSI_MAX_AHS_SIZE +
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/Kconfig linux-libre-2.6.39-gnu/drivers/scsi/Kconfig
--- linux-libre-2.6.38-gnu/drivers/scsi/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -381,6 +381,7 @@
 
 source "drivers/scsi/cxgbi/Kconfig"
 source "drivers/scsi/bnx2i/Kconfig"
+source "drivers/scsi/bnx2fc/Kconfig"
 source "drivers/scsi/be2iscsi/Kconfig"
 
 config SGIWD93_SCSI
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_exch.c linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_exch.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_exch.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_exch.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 EXPORT_SYMBOL(fc_cpu_mask);
 static u16	fc_cpu_order;	/* 2's power to represent total possible cpus */
 static struct kmem_cache *fc_em_cachep;	       /* cache for exchanges */
-struct workqueue_struct *fc_exch_workqueue;
+static struct workqueue_struct *fc_exch_workqueue;
 
 /*
  * Structure and function definitions for managing Fibre Channel Exchanges
@@ -558,6 +558,22 @@
 	return sp;
 }
 
+/*
+ * Set the response handler for the exchange associated with a sequence.
+ */
+static void fc_seq_set_resp(struct fc_seq *sp,
+			    void (*resp)(struct fc_seq *, struct fc_frame *,
+					 void *),
+			    void *arg)
+{
+	struct fc_exch *ep = fc_seq_exch(sp);
+
+	spin_lock_bh(&ep->ex_lock);
+	ep->resp = resp;
+	ep->arg = arg;
+	spin_unlock_bh(&ep->ex_lock);
+}
+
 /**
  * fc_seq_exch_abort() - Abort an exchange and sequence
  * @req_sp:	The sequence to be aborted
@@ -650,13 +666,10 @@
 		if (e_stat & ESB_ST_ABNORMAL)
 			rc = fc_exch_done_locked(ep);
 		spin_unlock_bh(&ep->ex_lock);
+		if (!rc)
+			fc_exch_delete(ep);
 		if (resp)
 			resp(sp, ERR_PTR(-FC_EX_TIMEOUT), arg);
-		if (!rc) {
-			/* delete the exchange if it's already being aborted */
-			fc_exch_delete(ep);
-			return;
-		}
 		fc_seq_exch_abort(sp, 2 * ep->r_a_tov);
 		goto done;
 	}
@@ -1029,7 +1042,7 @@
 }
 
 /**
- * fc_seq_els_rsp_send() - Send an ELS response using infomation from
+ * fc_seq_els_rsp_send() - Send an ELS response using information from
  *			   the existing sequence/exchange.
  * @fp:	      The received frame
  * @els_cmd:  The ELS command to be sent
@@ -1140,7 +1153,7 @@
  * fc_exch_send_ba_rjt() - Send BLS Reject
  * @rx_fp:  The frame being rejected
  * @reason: The reason the frame is being rejected
- * @explan: The explaination for the rejection
+ * @explan: The explanation for the rejection
  *
  * This is for rejecting BA_ABTS only.
  */
@@ -1266,6 +1279,8 @@
  * @fp:    The request frame
  *
  * On success, the sequence pointer will be returned and also in fr_seq(@fp).
+ * A reference will be held on the exchange/sequence for the caller, which
+ * must call fc_seq_release().
  */
 static struct fc_seq *fc_seq_assign(struct fc_lport *lport, struct fc_frame *fp)
 {
@@ -1283,6 +1298,15 @@
 }
 
 /**
+ * fc_seq_release() - Release the hold
+ * @sp:    The sequence.
+ */
+static void fc_seq_release(struct fc_seq *sp)
+{
+	fc_exch_release(fc_seq_exch(sp));
+}
+
+/**
  * fc_exch_recv_req() - Handler for an incoming request
  * @lport: The local port that received the request
  * @mp:	   The EM that the exchange is on
@@ -2151,6 +2175,7 @@
 		fc_exch_mgr_del(ema);
 	return -ENOMEM;
 }
+EXPORT_SYMBOL(fc_exch_mgr_list_clone);
 
 /**
  * fc_exch_mgr_alloc() - Allocate an exchange manager
@@ -2254,16 +2279,45 @@
 EXPORT_SYMBOL(fc_exch_mgr_free);
 
 /**
+ * fc_find_ema() - Lookup and return appropriate Exchange Manager Anchor depending
+ * upon 'xid'.
+ * @f_ctl: f_ctl
+ * @lport: The local port the frame was received on
+ * @fh: The received frame header
+ */
+static struct fc_exch_mgr_anchor *fc_find_ema(u32 f_ctl,
+					      struct fc_lport *lport,
+					      struct fc_frame_header *fh)
+{
+	struct fc_exch_mgr_anchor *ema;
+	u16 xid;
+
+	if (f_ctl & FC_FC_EX_CTX)
+		xid = ntohs(fh->fh_ox_id);
+	else {
+		xid = ntohs(fh->fh_rx_id);
+		if (xid == FC_XID_UNKNOWN)
+			return list_entry(lport->ema_list.prev,
+					  typeof(*ema), ema_list);
+	}
+
+	list_for_each_entry(ema, &lport->ema_list, ema_list) {
+		if ((xid >= ema->mp->min_xid) &&
+		    (xid <= ema->mp->max_xid))
+			return ema;
+	}
+	return NULL;
+}
+/**
  * fc_exch_recv() - Handler for received frames
  * @lport: The local port the frame was received on
- * @fp:	   The received frame
+ * @fp:	The received frame
  */
 void fc_exch_recv(struct fc_lport *lport, struct fc_frame *fp)
 {
 	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	struct fc_exch_mgr_anchor *ema;
-	u32 f_ctl, found = 0;
-	u16 oxid;
+	u32 f_ctl;
 
 	/* lport lock ? */
 	if (!lport || lport->state == LPORT_ST_DISABLED) {
@@ -2274,24 +2328,17 @@
 	}
 
 	f_ctl = ntoh24(fh->fh_f_ctl);
-	oxid = ntohs(fh->fh_ox_id);
-	if (f_ctl & FC_FC_EX_CTX) {
-		list_for_each_entry(ema, &lport->ema_list, ema_list) {
-			if ((oxid >= ema->mp->min_xid) &&
-			    (oxid <= ema->mp->max_xid)) {
-				found = 1;
-				break;
-			}
-		}
-
-		if (!found) {
-			FC_LPORT_DBG(lport, "Received response for out "
-				     "of range oxid:%hx\n", oxid);
-			fc_frame_free(fp);
-			return;
-		}
-	} else
-		ema = list_entry(lport->ema_list.prev, typeof(*ema), ema_list);
+	ema = fc_find_ema(f_ctl, lport, fh);
+	if (!ema) {
+		FC_LPORT_DBG(lport, "Unable to find Exchange Manager Anchor,"
+				    "fc_ctl <0x%x>, xid <0x%x>\n",
+				     f_ctl,
+				     (f_ctl & FC_FC_EX_CTX) ?
+				     ntohs(fh->fh_ox_id) :
+				     ntohs(fh->fh_rx_id));
+		fc_frame_free(fp);
+		return;
+	}
 
 	/*
 	 * If frame is marked invalid, just drop it.
@@ -2329,6 +2376,9 @@
 	if (!lport->tt.seq_start_next)
 		lport->tt.seq_start_next = fc_seq_start_next;
 
+	if (!lport->tt.seq_set_resp)
+		lport->tt.seq_set_resp = fc_seq_set_resp;
+
 	if (!lport->tt.exch_seq_send)
 		lport->tt.exch_seq_send = fc_exch_seq_send;
 
@@ -2350,6 +2400,9 @@
 	if (!lport->tt.seq_assign)
 		lport->tt.seq_assign = fc_seq_assign;
 
+	if (!lport->tt.seq_release)
+		lport->tt.seq_release = fc_seq_release;
+
 	return 0;
 }
 EXPORT_SYMBOL(fc_exch_init);
@@ -2357,7 +2410,7 @@
 /**
  * fc_setup_exch_mgr() - Setup an exchange manager
  */
-int fc_setup_exch_mgr()
+int fc_setup_exch_mgr(void)
 {
 	fc_em_cachep = kmem_cache_create("libfc_em", sizeof(struct fc_exch),
 					 0, SLAB_HWCACHE_ALIGN, NULL);
@@ -2395,7 +2448,7 @@
 /**
  * fc_destroy_exch_mgr() - Destroy an exchange manager
  */
-void fc_destroy_exch_mgr()
+void fc_destroy_exch_mgr(void)
 {
 	destroy_workqueue(fc_exch_workqueue);
 	kmem_cache_destroy(fc_em_cachep);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_fcp.c linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_fcp.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_fcp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_fcp.c	2011-05-19 00:06:34.000000000 -0400
@@ -42,7 +42,7 @@
 
 #include "fc_libfc.h"
 
-struct kmem_cache *scsi_pkt_cachep;
+static struct kmem_cache *scsi_pkt_cachep;
 
 /* SRB state definitions */
 #define FC_SRB_FREE		0		/* cmd is free */
@@ -155,6 +155,7 @@
 	if (fsp) {
 		memset(fsp, 0, sizeof(*fsp));
 		fsp->lp = lport;
+		fsp->xfer_ddp = FC_XID_UNKNOWN;
 		atomic_set(&fsp->ref_cnt, 1);
 		init_timer(&fsp->timer);
 		INIT_LIST_HEAD(&fsp->list);
@@ -869,7 +870,7 @@
 				fsp->scsi_resid = ntohl(rp_ex->fr_resid);
 				/*
 				 * The cmnd->underflow is the minimum number of
-				 * bytes that must be transfered for this
+				 * bytes that must be transferred for this
 				 * command.  Provided a sense condition is not
 				 * present, make sure the actual amount
 				 * transferred is at least the underflow value
@@ -1201,6 +1202,7 @@
 static int fc_fcp_pkt_abort(struct fc_fcp_pkt *fsp)
 {
 	int rc = FAILED;
+	unsigned long ticks_left;
 
 	if (fc_fcp_send_abort(fsp))
 		return FAILED;
@@ -1209,13 +1211,13 @@
 	fsp->wait_for_comp = 1;
 
 	spin_unlock_bh(&fsp->scsi_pkt_lock);
-	rc = wait_for_completion_timeout(&fsp->tm_done, FC_SCSI_TM_TOV);
+	ticks_left = wait_for_completion_timeout(&fsp->tm_done,
+							FC_SCSI_TM_TOV);
 	spin_lock_bh(&fsp->scsi_pkt_lock);
 	fsp->wait_for_comp = 0;
 
-	if (!rc) {
+	if (!ticks_left) {
 		FC_FCP_DBG(fsp, "target abort cmd  failed\n");
-		rc = FAILED;
 	} else if (fsp->state & FC_SRB_ABORTED) {
 		FC_FCP_DBG(fsp, "target abort cmd  passed\n");
 		rc = SUCCESS;
@@ -1304,7 +1306,7 @@
 }
 
 /**
- * fc_tm_done() - Task Managment response handler
+ * fc_tm_done() - Task Management response handler
  * @seq: The sequence that the response is on
  * @fp:	 The response frame
  * @arg: The FCP packet the response is for
@@ -1321,7 +1323,7 @@
 		 *
 		 * scsi-eh will escalate for when either happens.
 		 */
-		goto out;
+		return;
 	}
 
 	if (fc_fcp_lock_pkt(fsp))
@@ -1787,15 +1789,14 @@
 
 /**
  * fc_queuecommand() - The queuecommand function of the SCSI template
+ * @shost: The Scsi_Host that the command was issued to
  * @cmd:   The scsi_cmnd to be executed
- * @done:  The callback function to be called when the scsi_cmnd is complete
  *
- * This is the i/o strategy routine, called by the SCSI layer. This routine
- * is called with the host_lock held.
+ * This is the i/o strategy routine, called by the SCSI layer.
  */
-static int fc_queuecommand_lck(struct scsi_cmnd *sc_cmd, void (*done)(struct scsi_cmnd *))
+int fc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *sc_cmd)
 {
-	struct fc_lport *lport;
+	struct fc_lport *lport = shost_priv(shost);
 	struct fc_rport *rport = starget_to_rport(scsi_target(sc_cmd->device));
 	struct fc_fcp_pkt *fsp;
 	struct fc_rport_libfc_priv *rpriv;
@@ -1803,15 +1804,12 @@
 	int rc = 0;
 	struct fcoe_dev_stats *stats;
 
-	lport = shost_priv(sc_cmd->device->host);
-
 	rval = fc_remote_port_chkready(rport);
 	if (rval) {
 		sc_cmd->result = rval;
-		done(sc_cmd);
+		sc_cmd->scsi_done(sc_cmd);
 		return 0;
 	}
-	spin_unlock_irq(lport->host->host_lock);
 
 	if (!*(struct fc_remote_port **)rport->dd_data) {
 		/*
@@ -1819,7 +1817,7 @@
 		 * online
 		 */
 		sc_cmd->result = DID_IMM_RETRY << 16;
-		done(sc_cmd);
+		sc_cmd->scsi_done(sc_cmd);
 		goto out;
 	}
 
@@ -1842,10 +1840,7 @@
 	 * build the libfc request pkt
 	 */
 	fsp->cmd = sc_cmd;	/* save the cmd */
-	fsp->lp = lport;	/* save the softc ptr */
 	fsp->rport = rport;	/* set the remote port ptr */
-	fsp->xfer_ddp = FC_XID_UNKNOWN;
-	sc_cmd->scsi_done = done;
 
 	/*
 	 * set up the transfer length
@@ -1886,11 +1881,8 @@
 		rc = SCSI_MLQUEUE_HOST_BUSY;
 	}
 out:
-	spin_lock_irq(lport->host->host_lock);
 	return rc;
 }
-
-DEF_SCSI_QCMD(fc_queuecommand)
 EXPORT_SYMBOL(fc_queuecommand);
 
 /**
@@ -2112,7 +2104,6 @@
 	 * the sc passed in is not setup for execution like when sent
 	 * through the queuecommand callout.
 	 */
-	fsp->lp = lport;	/* save the softc ptr */
 	fsp->rport = rport;	/* set the remote port ptr */
 
 	/*
@@ -2245,7 +2236,7 @@
 }
 EXPORT_SYMBOL(fc_fcp_destroy);
 
-int fc_setup_fcp()
+int fc_setup_fcp(void)
 {
 	int rc = 0;
 
@@ -2261,7 +2252,7 @@
 	return rc;
 }
 
-void fc_destroy_fcp()
+void fc_destroy_fcp(void)
 {
 	if (scsi_pkt_cachep)
 		kmem_cache_destroy(scsi_pkt_cachep);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_libfc.c linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_libfc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_libfc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_libfc.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,6 +35,27 @@
 module_param_named(debug_logging, fc_debug_logging, int, S_IRUGO|S_IWUSR);
 MODULE_PARM_DESC(debug_logging, "a bit mask of logging levels");
 
+DEFINE_MUTEX(fc_prov_mutex);
+static LIST_HEAD(fc_local_ports);
+struct blocking_notifier_head fc_lport_notifier_head =
+		BLOCKING_NOTIFIER_INIT(fc_lport_notifier_head);
+EXPORT_SYMBOL(fc_lport_notifier_head);
+
+/*
+ * Providers which primarily send requests and PRLIs.
+ */
+struct fc4_prov *fc_active_prov[FC_FC4_PROV_SIZE] = {
+	[0] = &fc_rport_t0_prov,
+	[FC_TYPE_FCP] = &fc_rport_fcp_init,
+};
+
+/*
+ * Providers which receive requests.
+ */
+struct fc4_prov *fc_passive_prov[FC_FC4_PROV_SIZE] = {
+	[FC_TYPE_ELS] = &fc_lport_els_prov,
+};
+
 /**
  * libfc_init() - Initialize libfc.ko
  */
@@ -210,3 +231,102 @@
 	fc_fill_hdr(fp, in_fp, r_ctl, FC_FCTL_RESP, 0, parm_offset);
 }
 EXPORT_SYMBOL(fc_fill_reply_hdr);
+
+/**
+ * fc_fc4_conf_lport_params() - Modify "service_params" of specified lport
+ * if there is service provider (target provider) registered with libfc
+ * for specified "fc_ft_type"
+ * @lport: Local port which service_params needs to be modified
+ * @type: FC-4 type, such as FC_TYPE_FCP
+ */
+void fc_fc4_conf_lport_params(struct fc_lport *lport, enum fc_fh_type type)
+{
+	struct fc4_prov *prov_entry;
+	BUG_ON(type >= FC_FC4_PROV_SIZE);
+	BUG_ON(!lport);
+	prov_entry = fc_passive_prov[type];
+	if (type == FC_TYPE_FCP) {
+		if (prov_entry && prov_entry->recv)
+			lport->service_params |= FCP_SPPF_TARG_FCN;
+	}
+}
+
+void fc_lport_iterate(void (*notify)(struct fc_lport *, void *), void *arg)
+{
+	struct fc_lport *lport;
+
+	mutex_lock(&fc_prov_mutex);
+	list_for_each_entry(lport, &fc_local_ports, lport_list)
+		notify(lport, arg);
+	mutex_unlock(&fc_prov_mutex);
+}
+EXPORT_SYMBOL(fc_lport_iterate);
+
+/**
+ * fc_fc4_register_provider() - register FC-4 upper-level provider.
+ * @type: FC-4 type, such as FC_TYPE_FCP
+ * @prov: structure describing provider including ops vector.
+ *
+ * Returns 0 on success, negative error otherwise.
+ */
+int fc_fc4_register_provider(enum fc_fh_type type, struct fc4_prov *prov)
+{
+	struct fc4_prov **prov_entry;
+	int ret = 0;
+
+	if (type >= FC_FC4_PROV_SIZE)
+		return -EINVAL;
+	mutex_lock(&fc_prov_mutex);
+	prov_entry = (prov->recv ? fc_passive_prov : fc_active_prov) + type;
+	if (*prov_entry)
+		ret = -EBUSY;
+	else
+		*prov_entry = prov;
+	mutex_unlock(&fc_prov_mutex);
+	return ret;
+}
+EXPORT_SYMBOL(fc_fc4_register_provider);
+
+/**
+ * fc_fc4_deregister_provider() - deregister FC-4 upper-level provider.
+ * @type: FC-4 type, such as FC_TYPE_FCP
+ * @prov: structure describing provider including ops vector.
+ */
+void fc_fc4_deregister_provider(enum fc_fh_type type, struct fc4_prov *prov)
+{
+	BUG_ON(type >= FC_FC4_PROV_SIZE);
+	mutex_lock(&fc_prov_mutex);
+	if (prov->recv)
+		rcu_assign_pointer(fc_passive_prov[type], NULL);
+	else
+		rcu_assign_pointer(fc_active_prov[type], NULL);
+	mutex_unlock(&fc_prov_mutex);
+	synchronize_rcu();
+}
+EXPORT_SYMBOL(fc_fc4_deregister_provider);
+
+/**
+ * fc_fc4_add_lport() - add new local port to list and run notifiers.
+ * @lport:  The new local port.
+ */
+void fc_fc4_add_lport(struct fc_lport *lport)
+{
+	mutex_lock(&fc_prov_mutex);
+	list_add_tail(&lport->lport_list, &fc_local_ports);
+	blocking_notifier_call_chain(&fc_lport_notifier_head,
+				     FC_LPORT_EV_ADD, lport);
+	mutex_unlock(&fc_prov_mutex);
+}
+
+/**
+ * fc_fc4_del_lport() - remove local port from list and run notifiers.
+ * @lport:  The new local port.
+ */
+void fc_fc4_del_lport(struct fc_lport *lport)
+{
+	mutex_lock(&fc_prov_mutex);
+	list_del(&lport->lport_list);
+	blocking_notifier_call_chain(&fc_lport_notifier_head,
+				     FC_LPORT_EV_DEL, lport);
+	mutex_unlock(&fc_prov_mutex);
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_libfc.h linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_libfc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_libfc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_libfc.h	2011-05-19 00:06:34.000000000 -0400
@@ -94,6 +94,17 @@
 				(lport)->host->host_no,	##args))
 
 /*
+ * FC-4 Providers.
+ */
+extern struct fc4_prov *fc_active_prov[];	/* providers without recv */
+extern struct fc4_prov *fc_passive_prov[];	/* providers with recv */
+extern struct mutex fc_prov_mutex;		/* lock over table changes */
+
+extern struct fc4_prov fc_rport_t0_prov;	/* type 0 provider */
+extern struct fc4_prov fc_lport_els_prov;	/* ELS provider */
+extern struct fc4_prov fc_rport_fcp_init;	/* FCP initiator provider */
+
+/*
  * Set up direct-data placement for this I/O request
  */
 void fc_fcp_ddp_setup(struct fc_fcp_pkt *fsp, u16 xid);
@@ -112,6 +123,9 @@
  * Internal libfc functions
  */
 const char *fc_els_resp_type(struct fc_frame *);
+extern void fc_fc4_add_lport(struct fc_lport *);
+extern void fc_fc4_del_lport(struct fc_lport *);
+extern void fc_fc4_conf_lport_params(struct fc_lport *, enum fc_fh_type);
 
 /*
  * Copies a buffer into an sg list
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_lport.c linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_lport.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_lport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_lport.c	2011-05-19 00:06:34.000000000 -0400
@@ -52,7 +52,7 @@
  * while making the callback. To ensure that the rport is not free'd while
  * processing the callback the rport callbacks are serialized through a
  * single-threaded workqueue. An rport would never be free'd while in a
- * callback handler becuase no other rport work in this queue can be executed
+ * callback handler because no other rport work in this queue can be executed
  * at the same time.
  *
  * When discovery succeeds or fails a callback is made to the lport as
@@ -163,7 +163,7 @@
  * fc_lport_rport_callback() - Event handler for rport events
  * @lport: The lport which is receiving the event
  * @rdata: private remote port data
- * @event: The event that occured
+ * @event: The event that occurred
  *
  * Locking Note: The rport lock should not be held when calling
  *		 this function.
@@ -379,7 +379,7 @@
 
 /**
  * fc_lport_recv_rlir_req() - Handle received Registered Link Incident Report.
- * @lport: Fibre Channel local port recieving the RLIR
+ * @lport: Fibre Channel local port receiving the RLIR
  * @fp:	   The RLIR request frame
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -396,7 +396,7 @@
 
 /**
  * fc_lport_recv_echo_req() - Handle received ECHO request
- * @lport: The local port recieving the ECHO
+ * @lport: The local port receiving the ECHO
  * @fp:	   ECHO request frame
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -432,7 +432,7 @@
 
 /**
  * fc_lport_recv_rnid_req() - Handle received Request Node ID data request
- * @lport: The local port recieving the RNID
+ * @lport: The local port receiving the RNID
  * @fp:	   The RNID request frame
  *
  * Locking Note: The lport lock is expected to be held before calling
@@ -491,7 +491,7 @@
 
 /**
  * fc_lport_recv_logo_req() - Handle received fabric LOGO request
- * @lport: The local port recieving the LOGO
+ * @lport: The local port receiving the LOGO
  * @fp:	   The LOGO request frame
  *
  * Locking Note: The lport lock is exected to be held before calling
@@ -633,6 +633,7 @@
 	lport->tt.fcp_abort_io(lport);
 	lport->tt.disc_stop_final(lport);
 	lport->tt.exch_mgr_reset(lport, 0, 0);
+	fc_fc4_del_lport(lport);
 	return 0;
 }
 EXPORT_SYMBOL(fc_lport_destroy);
@@ -770,7 +771,7 @@
 
 /**
  * fc_lport_recv_flogi_req() - Receive a FLOGI request
- * @lport: The local port that recieved the request
+ * @lport: The local port that received the request
  * @rx_fp: The FLOGI frame
  *
  * A received FLOGI request indicates a point-to-point connection.
@@ -849,7 +850,7 @@
 }
 
 /**
- * fc_lport_recv_req() - The generic lport request handler
+ * fc_lport_recv_els_req() - The generic lport ELS request handler
  * @lport: The local port that received the request
  * @fp:	   The request frame
  *
@@ -857,11 +858,11 @@
  * if an rport should handle the request.
  *
  * Locking Note: This function should not be called with the lport
- *		 lock held becuase it will grab the lock.
+ *		 lock held because it will grab the lock.
  */
-static void fc_lport_recv_req(struct fc_lport *lport, struct fc_frame *fp)
+static void fc_lport_recv_els_req(struct fc_lport *lport,
+				  struct fc_frame *fp)
 {
-	struct fc_frame_header *fh = fc_frame_header_get(fp);
 	void (*recv)(struct fc_lport *, struct fc_frame *);
 
 	mutex_lock(&lport->lp_mutex);
@@ -873,8 +874,7 @@
 	 */
 	if (!lport->link_up)
 		fc_frame_free(fp);
-	else if (fh->fh_type == FC_TYPE_ELS &&
-		 fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
+	else {
 		/*
 		 * Check opcode.
 		 */
@@ -903,14 +903,62 @@
 		}
 
 		recv(lport, fp);
-	} else {
-		FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
-			     fr_eof(fp));
-		fc_frame_free(fp);
 	}
 	mutex_unlock(&lport->lp_mutex);
 }
 
+static int fc_lport_els_prli(struct fc_rport_priv *rdata, u32 spp_len,
+			     const struct fc_els_spp *spp_in,
+			     struct fc_els_spp *spp_out)
+{
+	return FC_SPP_RESP_INVL;
+}
+
+struct fc4_prov fc_lport_els_prov = {
+	.prli = fc_lport_els_prli,
+	.recv = fc_lport_recv_els_req,
+};
+
+/**
+ * fc_lport_recv_req() - The generic lport request handler
+ * @lport: The lport that received the request
+ * @fp: The frame the request is in
+ *
+ * Locking Note: This function should not be called with the lport
+ *		 lock held because it may grab the lock.
+ */
+static void fc_lport_recv_req(struct fc_lport *lport,
+			      struct fc_frame *fp)
+{
+	struct fc_frame_header *fh = fc_frame_header_get(fp);
+	struct fc_seq *sp = fr_seq(fp);
+	struct fc4_prov *prov;
+
+	/*
+	 * Use RCU read lock and module_lock to be sure module doesn't
+	 * deregister and get unloaded while we're calling it.
+	 * try_module_get() is inlined and accepts a NULL parameter.
+	 * Only ELSes and FCP target ops should come through here.
+	 * The locking is unfortunate, and a better scheme is being sought.
+	 */
+
+	rcu_read_lock();
+	if (fh->fh_type >= FC_FC4_PROV_SIZE)
+		goto drop;
+	prov = rcu_dereference(fc_passive_prov[fh->fh_type]);
+	if (!prov || !try_module_get(prov->module))
+		goto drop;
+	rcu_read_unlock();
+	prov->recv(lport, fp);
+	module_put(prov->module);
+	return;
+drop:
+	rcu_read_unlock();
+	FC_LPORT_DBG(lport, "dropping unexpected frame type %x\n", fh->fh_type);
+	fc_frame_free(fp);
+	lport->tt.exch_done(sp);
+}
+
 /**
  * fc_lport_reset() - Reset a local port
  * @lport: The local port which should be reset
@@ -1542,6 +1590,7 @@
  */
 int fc_lport_config(struct fc_lport *lport)
 {
+	INIT_LIST_HEAD(&lport->ema_list);
 	INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
 	mutex_init(&lport->lp_mutex);
 
@@ -1549,6 +1598,7 @@
 
 	fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
 	fc_lport_add_fc4_type(lport, FC_TYPE_CT);
+	fc_fc4_conf_lport_params(lport, FC_TYPE_FCP);
 
 	return 0;
 }
@@ -1586,6 +1636,7 @@
 		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_1GBIT;
 	if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
 		fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
+	fc_fc4_add_lport(lport);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_npiv.c linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_npiv.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_npiv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_npiv.c	2011-05-19 00:06:34.000000000 -0400
@@ -37,9 +37,7 @@
 
 	vn_port = libfc_host_alloc(shost->hostt, privsize);
 	if (!vn_port)
-		goto err_out;
-	if (fc_exch_mgr_list_clone(n_port, vn_port))
-		goto err_put;
+		return vn_port;
 
 	vn_port->vport = vport;
 	vport->dd_data = vn_port;
@@ -49,11 +47,6 @@
 	mutex_unlock(&n_port->lp_mutex);
 
 	return vn_port;
-
-err_put:
-	scsi_host_put(vn_port->host);
-err_out:
-	return NULL;
 }
 EXPORT_SYMBOL(libfc_vport_create);
 
@@ -86,6 +79,7 @@
 
 	return lport;
 }
+EXPORT_SYMBOL(fc_vport_id_lookup);
 
 /*
  * When setting the link state of vports during an lport state change, it's
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_rport.c linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_rport.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libfc/fc_rport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libfc/fc_rport.c	2011-05-19 00:06:34.000000000 -0400
@@ -58,7 +58,7 @@
 
 #include "fc_libfc.h"
 
-struct workqueue_struct *rport_event_queue;
+static struct workqueue_struct *rport_event_queue;
 
 static void fc_rport_enter_flogi(struct fc_rport_priv *);
 static void fc_rport_enter_plogi(struct fc_rport_priv *);
@@ -145,8 +145,10 @@
 	rdata->maxframe_size = FC_MIN_MAX_PAYLOAD;
 	INIT_DELAYED_WORK(&rdata->retry_work, fc_rport_timeout);
 	INIT_WORK(&rdata->event_work, fc_rport_work);
-	if (port_id != FC_FID_DIR_SERV)
+	if (port_id != FC_FID_DIR_SERV) {
+		rdata->lld_event_callback = lport->tt.rport_event_callback;
 		list_add_rcu(&rdata->peers, &lport->disc.rports);
+	}
 	return rdata;
 }
 
@@ -257,6 +259,8 @@
 	struct fc_rport_operations *rport_ops;
 	struct fc_rport_identifiers ids;
 	struct fc_rport *rport;
+	struct fc4_prov *prov;
+	u8 type;
 
 	mutex_lock(&rdata->rp_mutex);
 	event = rdata->event;
@@ -300,12 +304,25 @@
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
 		}
+		if (rdata->lld_event_callback) {
+			FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
+			rdata->lld_event_callback(lport, rdata, event);
+		}
 		kref_put(&rdata->kref, lport->tt.rport_destroy);
 		break;
 
 	case RPORT_EV_FAILED:
 	case RPORT_EV_LOGO:
 	case RPORT_EV_STOP:
+		if (rdata->prli_count) {
+			mutex_lock(&fc_prov_mutex);
+			for (type = 1; type < FC_FC4_PROV_SIZE; type++) {
+				prov = fc_passive_prov[type];
+				if (prov && prov->prlo)
+					prov->prlo(rdata);
+			}
+			mutex_unlock(&fc_prov_mutex);
+		}
 		port_id = rdata->ids.port_id;
 		mutex_unlock(&rdata->rp_mutex);
 
@@ -313,6 +330,10 @@
 			FC_RPORT_DBG(rdata, "callback ev %d\n", event);
 			rport_ops->event_callback(lport, rdata, event);
 		}
+		if (rdata->lld_event_callback) {
+			FC_RPORT_DBG(rdata, "lld callback ev %d\n", event);
+			rdata->lld_event_callback(lport, rdata, event);
+		}
 		cancel_delayed_work_sync(&rdata->retry_work);
 
 		/*
@@ -336,6 +357,7 @@
 			if (port_id == FC_FID_DIR_SERV) {
 				rdata->event = RPORT_EV_NONE;
 				mutex_unlock(&rdata->rp_mutex);
+				kref_put(&rdata->kref, lport->tt.rport_destroy);
 			} else if ((rdata->flags & FC_RP_STARTED) &&
 				   rdata->major_retries <
 				   lport->max_rport_retry_count) {
@@ -575,7 +597,7 @@
 
 	/* make sure this isn't an FC_EX_CLOSED error, never retry those */
 	if (PTR_ERR(fp) == -FC_EX_CLOSED)
-		return fc_rport_error(rdata, fp);
+		goto out;
 
 	if (rdata->retries < rdata->local_port->max_rport_retry_count) {
 		FC_RPORT_DBG(rdata, "Error %ld in state %s, retrying\n",
@@ -588,7 +610,8 @@
 		return;
 	}
 
-	return fc_rport_error(rdata, fp);
+out:
+	fc_rport_error(rdata, fp);
 }
 
 /**
@@ -878,6 +901,9 @@
 		rdata->ids.port_name = get_unaligned_be64(&plp->fl_wwpn);
 		rdata->ids.node_name = get_unaligned_be64(&plp->fl_wwnn);
 
+		/* save plogi response sp_features for further reference */
+		rdata->sp_features = ntohs(plp->fl_csp.sp_features);
+
 		if (lport->point_to_multipoint)
 			fc_rport_login_complete(rdata, fp);
 		csp_seq = ntohs(plp->fl_csp.sp_tot_seq);
@@ -949,6 +975,8 @@
 		struct fc_els_prli prli;
 		struct fc_els_spp spp;
 	} *pp;
+	struct fc_els_spp temp_spp;
+	struct fc4_prov *prov;
 	u32 roles = FC_RPORT_ROLE_UNKNOWN;
 	u32 fcp_parm = 0;
 	u8 op;
@@ -983,6 +1011,7 @@
 		resp_code = (pp->spp.spp_flags & FC_SPP_RESP_MASK);
 		FC_RPORT_DBG(rdata, "PRLI spp_flags = 0x%x\n",
 			     pp->spp.spp_flags);
+		rdata->spp_type = pp->spp.spp_type;
 		if (resp_code != FC_SPP_RESP_ACK) {
 			if (resp_code == FC_SPP_RESP_CONF)
 				fc_rport_error(rdata, fp);
@@ -996,6 +1025,15 @@
 		fcp_parm = ntohl(pp->spp.spp_params);
 		if (fcp_parm & FCP_SPPF_RETRY)
 			rdata->flags |= FC_RP_FLAGS_RETRY;
+		if (fcp_parm & FCP_SPPF_CONF_COMPL)
+			rdata->flags |= FC_RP_FLAGS_CONF_REQ;
+
+		prov = fc_passive_prov[FC_TYPE_FCP];
+		if (prov) {
+			memset(&temp_spp, 0, sizeof(temp_spp));
+			prov->prli(rdata, pp->prli.prli_spp_len,
+				   &pp->spp, &temp_spp);
+		}
 
 		rdata->supported_classes = FC_COS_CLASS3;
 		if (fcp_parm & FCP_SPPF_INIT_FCN)
@@ -1033,6 +1071,7 @@
 		struct fc_els_spp spp;
 	} *pp;
 	struct fc_frame *fp;
+	struct fc4_prov *prov;
 
 	/*
 	 * If the rport is one of the well known addresses
@@ -1054,9 +1093,20 @@
 		return;
 	}
 
-	if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI,
-				  fc_rport_prli_resp, rdata,
-				  2 * lport->r_a_tov))
+	fc_prli_fill(lport, fp);
+
+	prov = fc_passive_prov[FC_TYPE_FCP];
+	if (prov) {
+		pp = fc_frame_payload_get(fp, sizeof(*pp));
+		prov->prli(rdata, sizeof(pp->spp), NULL, &pp->spp);
+	}
+
+	fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rdata->ids.port_id,
+		       fc_host_port_id(lport->host), FC_TYPE_ELS,
+		       FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0);
+
+	if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp,
+				    NULL, rdata, 2 * lport->r_a_tov))
 		fc_rport_error_retry(rdata, NULL);
 	else
 		kref_get(&rdata->kref);
@@ -1642,9 +1692,9 @@
 	unsigned int len;
 	unsigned int plen;
 	enum fc_els_spp_resp resp;
+	enum fc_els_spp_resp passive;
 	struct fc_seq_els_data rjt_data;
-	u32 fcp_parm;
-	u32 roles = FC_RPORT_ROLE_UNKNOWN;
+	struct fc4_prov *prov;
 
 	FC_RPORT_DBG(rdata, "Received PRLI request while in state %s\n",
 		     fc_rport_state(rdata));
@@ -1678,46 +1728,42 @@
 	pp->prli.prli_len = htons(len);
 	len -= sizeof(struct fc_els_prli);
 
-	/* reinitialize remote port roles */
-	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
-
 	/*
 	 * Go through all the service parameter pages and build
 	 * response.  If plen indicates longer SPP than standard,
 	 * use that.  The entire response has been pre-cleared above.
 	 */
 	spp = &pp->spp;
+	mutex_lock(&fc_prov_mutex);
 	while (len >= plen) {
+		rdata->spp_type = rspp->spp_type;
 		spp->spp_type = rspp->spp_type;
 		spp->spp_type_ext = rspp->spp_type_ext;
-		spp->spp_flags = rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
-		resp = FC_SPP_RESP_ACK;
-
-		switch (rspp->spp_type) {
-		case 0:	/* common to all FC-4 types */
-			break;
-		case FC_TYPE_FCP:
-			fcp_parm = ntohl(rspp->spp_params);
-			if (fcp_parm & FCP_SPPF_RETRY)
-				rdata->flags |= FC_RP_FLAGS_RETRY;
-			rdata->supported_classes = FC_COS_CLASS3;
-			if (fcp_parm & FCP_SPPF_INIT_FCN)
-				roles |= FC_RPORT_ROLE_FCP_INITIATOR;
-			if (fcp_parm & FCP_SPPF_TARG_FCN)
-				roles |= FC_RPORT_ROLE_FCP_TARGET;
-			rdata->ids.roles = roles;
+		resp = 0;
 
-			spp->spp_params = htonl(lport->service_params);
-			break;
-		default:
-			resp = FC_SPP_RESP_INVL;
-			break;
+		if (rspp->spp_type < FC_FC4_PROV_SIZE) {
+			prov = fc_active_prov[rspp->spp_type];
+			if (prov)
+				resp = prov->prli(rdata, plen, rspp, spp);
+			prov = fc_passive_prov[rspp->spp_type];
+			if (prov) {
+				passive = prov->prli(rdata, plen, rspp, spp);
+				if (!resp || passive == FC_SPP_RESP_ACK)
+					resp = passive;
+			}
+		}
+		if (!resp) {
+			if (spp->spp_flags & FC_SPP_EST_IMG_PAIR)
+				resp |= FC_SPP_RESP_CONF;
+			else
+				resp |= FC_SPP_RESP_INVL;
 		}
 		spp->spp_flags |= resp;
 		len -= plen;
 		rspp = (struct fc_els_spp *)((char *)rspp + plen);
 		spp = (struct fc_els_spp *)((char *)spp + plen);
 	}
+	mutex_unlock(&fc_prov_mutex);
 
 	/*
 	 * Send LS_ACC.	 If this fails, the originator should retry.
@@ -1887,9 +1933,82 @@
 EXPORT_SYMBOL(fc_rport_init);
 
 /**
+ * fc_rport_fcp_prli() - Handle incoming PRLI for the FCP initiator.
+ * @rdata: remote port private
+ * @spp_len: service parameter page length
+ * @rspp: received service parameter page
+ * @spp: response service parameter page
+ *
+ * Returns the value for the response code to be placed in spp_flags;
+ * Returns 0 if not an initiator.
+ */
+static int fc_rport_fcp_prli(struct fc_rport_priv *rdata, u32 spp_len,
+			     const struct fc_els_spp *rspp,
+			     struct fc_els_spp *spp)
+{
+	struct fc_lport *lport = rdata->local_port;
+	u32 fcp_parm;
+
+	fcp_parm = ntohl(rspp->spp_params);
+	rdata->ids.roles = FC_RPORT_ROLE_UNKNOWN;
+	if (fcp_parm & FCP_SPPF_INIT_FCN)
+		rdata->ids.roles |= FC_RPORT_ROLE_FCP_INITIATOR;
+	if (fcp_parm & FCP_SPPF_TARG_FCN)
+		rdata->ids.roles |= FC_RPORT_ROLE_FCP_TARGET;
+	if (fcp_parm & FCP_SPPF_RETRY)
+		rdata->flags |= FC_RP_FLAGS_RETRY;
+	rdata->supported_classes = FC_COS_CLASS3;
+
+	if (!(lport->service_params & FC_RPORT_ROLE_FCP_INITIATOR))
+		return 0;
+
+	spp->spp_flags |= rspp->spp_flags & FC_SPP_EST_IMG_PAIR;
+
+	/*
+	 * OR in our service parameters with other providers (target), if any.
+	 */
+	fcp_parm = ntohl(spp->spp_params);
+	spp->spp_params = htonl(fcp_parm | lport->service_params);
+	return FC_SPP_RESP_ACK;
+}
+
+/*
+ * FC-4 provider ops for FCP initiator.
+ */
+struct fc4_prov fc_rport_fcp_init = {
+	.prli = fc_rport_fcp_prli,
+};
+
+/**
+ * fc_rport_t0_prli() - Handle incoming PRLI parameters for type 0
+ * @rdata: remote port private
+ * @spp_len: service parameter page length
+ * @rspp: received service parameter page
+ * @spp: response service parameter page
+ */
+static int fc_rport_t0_prli(struct fc_rport_priv *rdata, u32 spp_len,
+			    const struct fc_els_spp *rspp,
+			    struct fc_els_spp *spp)
+{
+	if (rspp->spp_flags & FC_SPP_EST_IMG_PAIR)
+		return FC_SPP_RESP_INVL;
+	return FC_SPP_RESP_ACK;
+}
+
+/*
+ * FC-4 provider ops for type 0 service parameters.
+ *
+ * This handles the special case of type 0 which is always successful
+ * but doesn't do anything otherwise.
+ */
+struct fc4_prov fc_rport_t0_prov = {
+	.prli = fc_rport_t0_prli,
+};
+
+/**
  * fc_setup_rport() - Initialize the rport_event_queue
  */
-int fc_setup_rport()
+int fc_setup_rport(void)
 {
 	rport_event_queue = create_singlethread_workqueue("fc_rport_eq");
 	if (!rport_event_queue)
@@ -1900,7 +2019,7 @@
 /**
  * fc_destroy_rport() - Destroy the rport_event_queue
  */
-void fc_destroy_rport()
+void fc_destroy_rport(void)
 {
 	destroy_workqueue(rport_event_queue);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libiscsi.c linux-libre-2.6.39-gnu/drivers/scsi/libiscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libiscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libiscsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -3352,6 +3352,47 @@
 }
 EXPORT_SYMBOL_GPL(iscsi_session_get_param);
 
+int iscsi_conn_get_addr_param(struct sockaddr_storage *addr,
+			      enum iscsi_param param, char *buf)
+{
+	struct sockaddr_in6 *sin6 = NULL;
+	struct sockaddr_in *sin = NULL;
+	int len;
+
+	switch (addr->ss_family) {
+	case AF_INET:
+		sin = (struct sockaddr_in *)addr;
+		break;
+	case AF_INET6:
+		sin6 = (struct sockaddr_in6 *)addr;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	switch (param) {
+	case ISCSI_PARAM_CONN_ADDRESS:
+	case ISCSI_HOST_PARAM_IPADDRESS:
+		if (sin)
+			len = sprintf(buf, "%pI4\n", &sin->sin_addr.s_addr);
+		else
+			len = sprintf(buf, "%pI6\n", &sin6->sin6_addr);
+		break;
+	case ISCSI_PARAM_CONN_PORT:
+		if (sin)
+			len = sprintf(buf, "%hu\n", be16_to_cpu(sin->sin_port));
+		else
+			len = sprintf(buf, "%hu\n",
+				      be16_to_cpu(sin6->sin6_port));
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return len;
+}
+EXPORT_SYMBOL_GPL(iscsi_conn_get_addr_param);
+
 int iscsi_conn_get_param(struct iscsi_cls_conn *cls_conn,
 			 enum iscsi_param param, char *buf)
 {
@@ -3416,9 +3457,6 @@
 	case ISCSI_HOST_PARAM_INITIATOR_NAME:
 		len = sprintf(buf, "%s\n", ihost->initiatorname);
 		break;
-	case ISCSI_HOST_PARAM_IPADDRESS:
-		len = sprintf(buf, "%s\n", ihost->local_address);
-		break;
 	default:
 		return -ENOSYS;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libiscsi_tcp.c linux-libre-2.6.39-gnu/drivers/scsi/libiscsi_tcp.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libiscsi_tcp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libiscsi_tcp.c	2011-05-19 00:06:34.000000000 -0400
@@ -132,14 +132,25 @@
 	if (page_count(sg_page(sg)) >= 1 && !recv)
 		return;
 
-	segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+	if (recv) {
+		segment->atomic_mapped = true;
+		segment->sg_mapped = kmap_atomic(sg_page(sg), KM_SOFTIRQ0);
+	} else {
+		segment->atomic_mapped = false;
+		/* the xmit path can sleep with the page mapped so use kmap */
+		segment->sg_mapped = kmap(sg_page(sg));
+	}
+
 	segment->data = segment->sg_mapped + sg->offset + segment->sg_offset;
 }
 
 void iscsi_tcp_segment_unmap(struct iscsi_segment *segment)
 {
 	if (segment->sg_mapped) {
-		kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
+		if (segment->atomic_mapped)
+			kunmap_atomic(segment->sg_mapped, KM_SOFTIRQ0);
+		else
+			kunmap(sg_page(segment->sg));
 		segment->sg_mapped = NULL;
 		segment->data = NULL;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/Kconfig linux-libre-2.6.39-gnu/drivers/scsi/libsas/Kconfig
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -46,11 +46,3 @@
 		Allows sas hosts to receive SMP frames.  Selecting this
 		option builds an SMP interpreter into libsas.  Say
 		N here if you want to save the few kb this consumes.
-
-config SCSI_SAS_LIBSAS_DEBUG
-	bool "Compile the SAS Domain Transport Attributes in debug mode"
-	default y
-	depends on SCSI_SAS_LIBSAS
-	help
-		Compiles the SAS Layer in debug mode.  In debug mode, the
-		SAS Layer prints diagnostic and debug messages.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/Makefile linux-libre-2.6.39-gnu/drivers/scsi/libsas/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -21,10 +21,6 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-ifeq ($(CONFIG_SCSI_SAS_LIBSAS_DEBUG),y)
-	EXTRA_CFLAGS += -DSAS_DEBUG
-endif
-
 obj-$(CONFIG_SCSI_SAS_LIBSAS) += libsas.o
 libsas-y +=  sas_init.o     \
 		sas_phy.o      \
@@ -36,4 +32,4 @@
 		sas_scsi_host.o \
 		sas_task.o
 libsas-$(CONFIG_SCSI_SAS_ATA) +=	sas_ata.o
-libsas-$(CONFIG_SCSI_SAS_HOST_SMP) +=	sas_host_smp.o
\ No newline at end of file
+libsas-$(CONFIG_SCSI_SAS_HOST_SMP) +=	sas_host_smp.o
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_ata.c linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_ata.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_ata.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_ata.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,13 +71,13 @@
 		case SAS_SG_ERR:
 			return AC_ERR_INVALID;
 
-		case SAM_STAT_CHECK_CONDITION:
 		case SAS_OPEN_TO:
 		case SAS_OPEN_REJECT:
 			SAS_DPRINTK("%s: Saw error %d.  What to do?\n",
 				    __func__, ts->stat);
 			return AC_ERR_OTHER;
 
+		case SAM_STAT_CHECK_CONDITION:
 		case SAS_ABORTED_TASK:
 			return AC_ERR_DEV;
 
@@ -107,13 +107,15 @@
 	sas_ha = dev->port->ha;
 
 	spin_lock_irqsave(dev->sata_dev.ap->lock, flags);
-	if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD) {
+	if (stat->stat == SAS_PROTO_RESPONSE || stat->stat == SAM_STAT_GOOD ||
+	    ((stat->stat == SAM_STAT_CHECK_CONDITION &&
+	      dev->sata_dev.command_set == ATAPI_COMMAND_SET))) {
 		ata_tf_from_fis(resp->ending_fis, &dev->sata_dev.tf);
 		qc->err_mask |= ac_err_mask(dev->sata_dev.tf.command);
 		dev->sata_dev.sstatus = resp->sstatus;
 		dev->sata_dev.serror = resp->serror;
 		dev->sata_dev.scontrol = resp->scontrol;
-	} else if (stat->stat != SAM_STAT_GOOD) {
+	} else {
 		ac = sas_to_ata_err(stat);
 		if (ac) {
 			SAS_DPRINTK("%s: SAS error %x\n", __func__,
@@ -238,37 +240,43 @@
 	return true;
 }
 
-static void sas_ata_phy_reset(struct ata_port *ap)
+static int sas_ata_hard_reset(struct ata_link *link, unsigned int *class,
+			       unsigned long deadline)
 {
+	struct ata_port *ap = link->ap;
 	struct domain_device *dev = ap->private_data;
 	struct sas_internal *i =
 		to_sas_internal(dev->port->ha->core.shost->transportt);
 	int res = TMF_RESP_FUNC_FAILED;
+	int ret = 0;
 
 	if (i->dft->lldd_I_T_nexus_reset)
 		res = i->dft->lldd_I_T_nexus_reset(dev);
 
-	if (res != TMF_RESP_FUNC_COMPLETE)
+	if (res != TMF_RESP_FUNC_COMPLETE) {
 		SAS_DPRINTK("%s: Unable to reset I T nexus?\n", __func__);
+		ret = -EAGAIN;
+	}
 
 	switch (dev->sata_dev.command_set) {
 		case ATA_COMMAND_SET:
 			SAS_DPRINTK("%s: Found ATA device.\n", __func__);
-			ap->link.device[0].class = ATA_DEV_ATA;
+			*class = ATA_DEV_ATA;
 			break;
 		case ATAPI_COMMAND_SET:
 			SAS_DPRINTK("%s: Found ATAPI device.\n", __func__);
-			ap->link.device[0].class = ATA_DEV_ATAPI;
+			*class = ATA_DEV_ATAPI;
 			break;
 		default:
 			SAS_DPRINTK("%s: Unknown SATA command set: %d.\n",
 				    __func__,
 				    dev->sata_dev.command_set);
-			ap->link.device[0].class = ATA_DEV_UNKNOWN;
+			*class = ATA_DEV_UNKNOWN;
 			break;
 	}
 
 	ap->cbl = ATA_CBL_SATA;
+	return ret;
 }
 
 static void sas_ata_post_internal(struct ata_queued_cmd *qc)
@@ -299,57 +307,12 @@
 	}
 }
 
-static int sas_ata_scr_write(struct ata_link *link, unsigned int sc_reg_in,
-			      u32 val)
-{
-	struct domain_device *dev = link->ap->private_data;
-
-	SAS_DPRINTK("STUB %s\n", __func__);
-	switch (sc_reg_in) {
-		case SCR_STATUS:
-			dev->sata_dev.sstatus = val;
-			break;
-		case SCR_CONTROL:
-			dev->sata_dev.scontrol = val;
-			break;
-		case SCR_ERROR:
-			dev->sata_dev.serror = val;
-			break;
-		case SCR_ACTIVE:
-			dev->sata_dev.ap->link.sactive = val;
-			break;
-		default:
-			return -EINVAL;
-	}
-	return 0;
-}
-
-static int sas_ata_scr_read(struct ata_link *link, unsigned int sc_reg_in,
-			    u32 *val)
-{
-	struct domain_device *dev = link->ap->private_data;
-
-	SAS_DPRINTK("STUB %s\n", __func__);
-	switch (sc_reg_in) {
-		case SCR_STATUS:
-			*val = dev->sata_dev.sstatus;
-			return 0;
-		case SCR_CONTROL:
-			*val = dev->sata_dev.scontrol;
-			return 0;
-		case SCR_ERROR:
-			*val = dev->sata_dev.serror;
-			return 0;
-		case SCR_ACTIVE:
-			*val = dev->sata_dev.ap->link.sactive;
-			return 0;
-		default:
-			return -EINVAL;
-	}
-}
-
 static struct ata_port_operations sas_sata_ops = {
-	.phy_reset		= sas_ata_phy_reset,
+	.prereset		= ata_std_prereset,
+	.softreset		= NULL,
+	.hardreset		= sas_ata_hard_reset,
+	.postreset		= ata_std_postreset,
+	.error_handler		= ata_std_error_handler,
 	.post_internal_cmd	= sas_ata_post_internal,
 	.qc_defer               = ata_std_qc_defer,
 	.qc_prep		= ata_noop_qc_prep,
@@ -357,15 +320,12 @@
 	.qc_fill_rtf		= sas_ata_qc_fill_rtf,
 	.port_start		= ata_sas_port_start,
 	.port_stop		= ata_sas_port_stop,
-	.scr_read		= sas_ata_scr_read,
-	.scr_write		= sas_ata_scr_write
 };
 
 static struct ata_port_info sata_port_info = {
-	.flags = ATA_FLAG_SATA | ATA_FLAG_NO_LEGACY | ATA_FLAG_SATA_RESET |
-		ATA_FLAG_MMIO | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ,
-	.pio_mask = 0x1f, /* PIO0-4 */
-	.mwdma_mask = 0x07, /* MWDMA0-2 */
+	.flags = ATA_FLAG_SATA | ATA_FLAG_PIO_DMA | ATA_FLAG_NCQ,
+	.pio_mask = ATA_PIO4,
+	.mwdma_mask = ATA_MWDMA2,
 	.udma_mask = ATA_UDMA6,
 	.port_ops = &sas_sata_ops
 };
@@ -781,3 +741,81 @@
 
 	return res;
 }
+
+void sas_ata_strategy_handler(struct Scsi_Host *shost)
+{
+	struct scsi_device *sdev;
+
+	shost_for_each_device(sdev, shost) {
+		struct domain_device *ddev = sdev_to_domain_dev(sdev);
+		struct ata_port *ap = ddev->sata_dev.ap;
+
+		if (!dev_is_sata(ddev))
+			continue;
+
+		ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata port error handler");
+		ata_scsi_port_error_handler(shost, ap);
+	}
+}
+
+int sas_ata_timed_out(struct scsi_cmnd *cmd, struct sas_task *task,
+		      enum blk_eh_timer_return *rtn)
+{
+	struct domain_device *ddev = cmd_to_domain_dev(cmd);
+
+	if (!dev_is_sata(ddev) || task)
+		return 0;
+
+	/* we're a sata device with no task, so this must be a libata
+	 * eh timeout.  Ideally should hook into libata timeout
+	 * handling, but there's no point, it just wants to activate
+	 * the eh thread */
+	*rtn = BLK_EH_NOT_HANDLED;
+	return 1;
+}
+
+int sas_ata_eh(struct Scsi_Host *shost, struct list_head *work_q,
+	       struct list_head *done_q)
+{
+	int rtn = 0;
+	struct scsi_cmnd *cmd, *n;
+	struct ata_port *ap;
+
+	do {
+		LIST_HEAD(sata_q);
+
+		ap = NULL;
+
+		list_for_each_entry_safe(cmd, n, work_q, eh_entry) {
+			struct domain_device *ddev = cmd_to_domain_dev(cmd);
+
+			if (!dev_is_sata(ddev) || TO_SAS_TASK(cmd))
+				continue;
+			if (ap && ap != ddev->sata_dev.ap)
+				continue;
+			ap = ddev->sata_dev.ap;
+			rtn = 1;
+			list_move(&cmd->eh_entry, &sata_q);
+		}
+
+		if (!list_empty(&sata_q)) {
+			ata_port_printk(ap, KERN_DEBUG, "sas eh calling libata cmd error handler\n");
+			ata_scsi_cmd_error_handler(shost, ap, &sata_q);
+			/*
+			 * ata's error handler may leave the cmd on the list
+			 * so make sure they don't remain on a stack list
+			 * about to go out of scope.
+			 *
+			 * This looks strange, since the commands are
+			 * now part of no list, but the next error
+			 * action will be ata_port_error_handler()
+			 * which takes no list and sweeps them up
+			 * anyway from the ata tag array.
+			 */
+			while (!list_empty(&sata_q))
+				list_del_init(sata_q.next);
+		}
+	} while (ap);
+
+	return rtn;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_dump.c linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_dump.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_dump.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_dump.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,8 +24,6 @@
 
 #include "sas_dump.h"
 
-#ifdef SAS_DEBUG
-
 static const char *sas_hae_str[] = {
 	[0] = "HAE_RESET",
 };
@@ -72,5 +70,3 @@
 	SAS_DPRINTK("port%d: oob_mode:0x%x\n", port->id, port->oob_mode);
 	SAS_DPRINTK("port%d: num_phys:%d\n", port->id, port->num_phys);
 }
-
-#endif /* SAS_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_dump.h linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_dump.h
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_dump.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_dump.h	2011-05-19 00:06:34.000000000 -0400
@@ -24,19 +24,7 @@
 
 #include "sas_internal.h"
 
-#ifdef SAS_DEBUG
-
 void sas_dprint_porte(int phyid, enum port_event pe);
 void sas_dprint_phye(int phyid, enum phy_event pe);
 void sas_dprint_hae(struct sas_ha_struct *sas_ha, enum ha_event he);
 void sas_dump_port(struct asd_sas_port *port);
-
-#else /* SAS_DEBUG */
-
-static inline void sas_dprint_porte(int phyid, enum port_event pe) { }
-static inline void sas_dprint_phye(int phyid, enum phy_event pe) { }
-static inline void sas_dprint_hae(struct sas_ha_struct *sas_ha,
-				  enum ha_event he) { }
-static inline void sas_dump_port(struct asd_sas_port *port) { }
-
-#endif /* SAS_DEBUG */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_expander.c linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_expander.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_expander.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_expander.c	2011-05-19 00:06:34.000000000 -0400
@@ -240,10 +240,15 @@
 				       disc_resp, DISCOVER_RESP_SIZE);
 		if (res)
 			return res;
-		/* This is detecting a failure to transmit inital
+		/* This is detecting a failure to transmit initial
 		 * dev to host FIS as described in section G.5 of
 		 * sas-2 r 04b */
 		dr = &((struct smp_resp *)disc_resp)->disc;
+		if (memcmp(dev->sas_addr, dr->attached_sas_addr,
+			  SAS_ADDR_SIZE) == 0) {
+			sas_printk("Found loopback topology, just ignore it!\n");
+			return 0;
+		}
 		if (!(dr->attached_dev_type == 0 &&
 		      dr->attached_sata_dev))
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_internal.h linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_internal.h
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,11 +33,7 @@
 
 #define sas_printk(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__)
 
-#ifdef SAS_DEBUG
-#define SAS_DPRINTK(fmt, ...) printk(KERN_NOTICE "sas: " fmt, ## __VA_ARGS__)
-#else
-#define SAS_DPRINTK(fmt, ...)
-#endif
+#define SAS_DPRINTK(fmt, ...) printk(KERN_DEBUG "sas: " fmt, ## __VA_ARGS__)
 
 #define TO_SAS_TASK(_scsi_cmd)  ((void *)(_scsi_cmd)->host_scribble)
 #define ASSIGN_SAS_TASK(_sc, _t) do { (_sc)->host_scribble = (void *) _t; } while (0)
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_scsi_host.c linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_scsi_host.c
--- linux-libre-2.6.38-gnu/drivers/scsi/libsas/sas_scsi_host.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/libsas/sas_scsi_host.c	2011-05-19 00:06:34.000000000 -0400
@@ -663,11 +663,16 @@
 	 * scsi_unjam_host does, but we skip scsi_eh_abort_cmds because any
 	 * command we see here has no sas_task and is thus unknown to the HA.
 	 */
-	if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
-		scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
+	if (!sas_ata_eh(shost, &eh_work_q, &ha->eh_done_q))
+		if (!scsi_eh_get_sense(&eh_work_q, &ha->eh_done_q))
+			scsi_eh_ready_devs(shost, &eh_work_q, &ha->eh_done_q);
 
 out:
+	/* now link into libata eh --- if we have any ata devices */
+	sas_ata_strategy_handler(shost);
+
 	scsi_eh_flush_done_q(&ha->eh_done_q);
+
 	SAS_DPRINTK("--- Exit %s\n", __func__);
 	return;
 }
@@ -676,6 +681,10 @@
 {
 	struct sas_task *task = TO_SAS_TASK(cmd);
 	unsigned long flags;
+	enum blk_eh_timer_return rtn;
+
+	if (sas_ata_timed_out(cmd, task, &rtn))
+		return rtn;
 
 	if (!task) {
 		cmd->request->timeout /= 2;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_attr.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_attr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_attr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_attr.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -623,10 +623,14 @@
 	int status = 0;
 	int cnt = 0;
 	int i;
+	int rc;
 
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &status, &online_compl,
+	rc = lpfc_workq_post_event(phba, &status, &online_compl,
 			      LPFC_EVT_OFFLINE_PREP);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
@@ -652,7 +656,10 @@
 	}
 
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &status, &online_compl, type);
+	rc = lpfc_workq_post_event(phba, &status, &online_compl, type);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
@@ -671,17 +678,19 @@
  *
  * Notes:
  * Assumes any error from lpfc_do_offline() will be negative.
+ * Do not make this function static.
  *
  * Returns:
  * lpfc_do_offline() return code if not zero
  * -EIO reset not configured or error posting the event
  * zero for success
  **/
-static int
+int
 lpfc_selective_reset(struct lpfc_hba *phba)
 {
 	struct completion online_compl;
 	int status = 0;
+	int rc;
 
 	if (!phba->cfg_enable_hba_reset)
 		return -EIO;
@@ -692,8 +701,11 @@
 		return status;
 
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &status, &online_compl,
+	rc = lpfc_workq_post_event(phba, &status, &online_compl,
 			      LPFC_EVT_ONLINE);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 
 	if (status != 0)
@@ -734,7 +746,7 @@
 	int status = -EINVAL;
 
 	if (strncmp(buf, "selective", sizeof("selective") - 1) == 0)
-		status = lpfc_selective_reset(phba);
+		status = phba->lpfc_selective_reset(phba);
 
 	if (status == 0)
 		return strlen(buf);
@@ -812,14 +824,17 @@
 	struct lpfc_hba   *phba = vport->phba;
 	struct completion online_compl;
 	int status=0;
+	int rc;
 
 	if (!phba->cfg_enable_hba_reset)
 		return -EACCES;
 	init_completion(&online_compl);
 
 	if(strncmp(buf, "online", sizeof("online") - 1) == 0) {
-		lpfc_workq_post_event(phba, &status, &online_compl,
+		rc = lpfc_workq_post_event(phba, &status, &online_compl,
 				      LPFC_EVT_ONLINE);
+		if (rc == 0)
+			return -ENOMEM;
 		wait_for_completion(&online_compl);
 	} else if (strncmp(buf, "offline", sizeof("offline") - 1) == 0)
 		status = lpfc_do_offline(phba, LPFC_EVT_OFFLINE);
@@ -1209,7 +1224,10 @@
 	if (val & ENABLE_FCP_RING_POLLING) {
 		if ((val & DISABLE_FCP_RING_INT) &&
 		    !(old_val & DISABLE_FCP_RING_INT)) {
-			creg_val = readl(phba->HCregaddr);
+			if (lpfc_readl(phba->HCregaddr, &creg_val)) {
+				spin_unlock_irq(&phba->hbalock);
+				return -EINVAL;
+			}
 			creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
 			writel(creg_val, phba->HCregaddr);
 			readl(phba->HCregaddr); /* flush */
@@ -1227,7 +1245,10 @@
 		spin_unlock_irq(&phba->hbalock);
 		del_timer(&phba->fcp_poll_timer);
 		spin_lock_irq(&phba->hbalock);
-		creg_val = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &creg_val)) {
+			spin_unlock_irq(&phba->hbalock);
+			return -EINVAL;
+		}
 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
 		readl(phba->HCregaddr); /* flush */
@@ -1279,6 +1300,28 @@
 }
 
 /**
+ * lpfc_dss_show - Return the current state of dss and the configured state
+ * @dev: class converted to a Scsi_host structure.
+ * @attr: device attribute, not used.
+ * @buf: on return contains the formatted text.
+ *
+ * Returns: size of formatted string.
+ **/
+static ssize_t
+lpfc_dss_show(struct device *dev, struct device_attribute *attr,
+	      char *buf)
+{
+	struct Scsi_Host *shost = class_to_shost(dev);
+	struct lpfc_vport *vport = (struct lpfc_vport *) shost->hostdata;
+	struct lpfc_hba   *phba = vport->phba;
+
+	return snprintf(buf, PAGE_SIZE, "%s - %sOperational\n",
+			(phba->cfg_enable_dss) ? "Enabled" : "Disabled",
+			(phba->sli3_options & LPFC_SLI3_DSS_ENABLED) ?
+				"" : "Not ");
+}
+
+/**
  * lpfc_param_show - Return a cfg attribute value in decimal
  *
  * Description:
@@ -1597,13 +1640,13 @@
 
 #define LPFC_ATTR(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_init(name, defval, minval, maxval)
 
 #define LPFC_ATTR_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1611,7 +1654,7 @@
 
 #define LPFC_ATTR_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1622,7 +1665,7 @@
 
 #define LPFC_ATTR_HEX_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_hex_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1630,7 +1673,7 @@
 
 #define LPFC_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_param_hex_show(name)\
 lpfc_param_init(name, defval, minval, maxval)\
@@ -1641,13 +1684,13 @@
 
 #define LPFC_VPORT_ATTR(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_init(name, defval, minval, maxval)
 
 #define LPFC_VPORT_ATTR_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1655,7 +1698,7 @@
 
 #define LPFC_VPORT_ATTR_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1666,7 +1709,7 @@
 
 #define LPFC_VPORT_ATTR_HEX_R(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_hex_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1674,7 +1717,7 @@
 
 #define LPFC_VPORT_ATTR_HEX_RW(name, defval, minval, maxval, desc) \
 static uint lpfc_##name = defval;\
-module_param(lpfc_##name, uint, 0);\
+module_param(lpfc_##name, uint, S_IRUGO);\
 MODULE_PARM_DESC(lpfc_##name, desc);\
 lpfc_vport_param_hex_show(name)\
 lpfc_vport_param_init(name, defval, minval, maxval)\
@@ -1718,7 +1761,7 @@
 static DEVICE_ATTR(lpfc_temp_sensor, S_IRUGO, lpfc_temp_sensor_show, NULL);
 static DEVICE_ATTR(lpfc_fips_level, S_IRUGO, lpfc_fips_level_show, NULL);
 static DEVICE_ATTR(lpfc_fips_rev, S_IRUGO, lpfc_fips_rev_show, NULL);
-
+static DEVICE_ATTR(lpfc_dss, S_IRUGO, lpfc_dss_show, NULL);
 
 static char *lpfc_soft_wwn_key = "C99G71SL8032A";
 
@@ -1813,6 +1856,7 @@
 	int stat1=0, stat2=0;
 	unsigned int i, j, cnt=count;
 	u8 wwpn[8];
+	int rc;
 
 	if (!phba->cfg_enable_hba_reset)
 		return -EACCES;
@@ -1863,7 +1907,11 @@
 				"0463 lpfc_soft_wwpn attribute set failed to "
 				"reinit adapter - %d\n", stat1);
 	init_completion(&online_compl);
-	lpfc_workq_post_event(phba, &stat2, &online_compl, LPFC_EVT_ONLINE);
+	rc = lpfc_workq_post_event(phba, &stat2, &online_compl,
+				   LPFC_EVT_ONLINE);
+	if (rc == 0)
+		return -ENOMEM;
+
 	wait_for_completion(&online_compl);
 	if (stat2)
 		lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -1954,7 +2002,7 @@
 
 
 static int lpfc_poll = 0;
-module_param(lpfc_poll, int, 0);
+module_param(lpfc_poll, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_poll, "FCP ring polling mode control:"
 		 " 0 - none,"
 		 " 1 - poll with interrupts enabled"
@@ -1964,21 +2012,21 @@
 		   lpfc_poll_show, lpfc_poll_store);
 
 int  lpfc_sli_mode = 0;
-module_param(lpfc_sli_mode, int, 0);
+module_param(lpfc_sli_mode, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_sli_mode, "SLI mode selector:"
 		 " 0 - auto (SLI-3 if supported),"
 		 " 2 - select SLI-2 even on SLI-3 capable HBAs,"
 		 " 3 - select SLI-3");
 
 int lpfc_enable_npiv = 1;
-module_param(lpfc_enable_npiv, int, 0);
+module_param(lpfc_enable_npiv, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_enable_npiv, "Enable NPIV functionality");
 lpfc_param_show(enable_npiv);
 lpfc_param_init(enable_npiv, 1, 0, 1);
 static DEVICE_ATTR(lpfc_enable_npiv, S_IRUGO, lpfc_enable_npiv_show, NULL);
 
 int lpfc_enable_rrq;
-module_param(lpfc_enable_rrq, int, 0);
+module_param(lpfc_enable_rrq, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_enable_rrq, "Enable RRQ functionality");
 lpfc_param_show(enable_rrq);
 lpfc_param_init(enable_rrq, 0, 0, 1);
@@ -2040,7 +2088,7 @@
 			 lpfc_txcmplq_hw_show, NULL);
 
 int lpfc_iocb_cnt = 2;
-module_param(lpfc_iocb_cnt, int, 1);
+module_param(lpfc_iocb_cnt, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_iocb_cnt,
 	"Number of IOCBs alloc for ELS, CT, and ABTS: 1k to 5k IOCBs");
 lpfc_param_show(iocb_cnt);
@@ -2192,7 +2240,7 @@
 # disappear until the timer expires. Value range is [0,255]. Default
 # value is 30.
 */
-module_param(lpfc_devloss_tmo, int, 0);
+module_param(lpfc_devloss_tmo, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_devloss_tmo,
 		 "Seconds driver will hold I/O waiting "
 		 "for a device to come back");
@@ -2302,7 +2350,7 @@
 # Default value of this parameter is 1.
 */
 static int lpfc_restrict_login = 1;
-module_param(lpfc_restrict_login, int, 0);
+module_param(lpfc_restrict_login, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_restrict_login,
 		 "Restrict virtual ports login to remote initiators.");
 lpfc_vport_param_show(restrict_login);
@@ -2473,7 +2521,7 @@
 	return -EINVAL;
 }
 static int lpfc_topology = 0;
-module_param(lpfc_topology, int, 0);
+module_param(lpfc_topology, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_topology, "Select Fibre Channel topology");
 lpfc_param_show(topology)
 lpfc_param_init(topology, 0, 0, 6)
@@ -2915,7 +2963,7 @@
 }
 
 static int lpfc_link_speed = 0;
-module_param(lpfc_link_speed, int, 0);
+module_param(lpfc_link_speed, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_link_speed, "Select link speed");
 lpfc_param_show(link_speed)
 
@@ -3043,7 +3091,7 @@
 }
 
 static int lpfc_aer_support = 1;
-module_param(lpfc_aer_support, int, 1);
+module_param(lpfc_aer_support, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_aer_support, "Enable PCIe device AER support");
 lpfc_param_show(aer_support)
 
@@ -3155,7 +3203,7 @@
 # The value is set in milliseconds.
 */
 static int lpfc_max_scsicmpl_time;
-module_param(lpfc_max_scsicmpl_time, int, 0);
+module_param(lpfc_max_scsicmpl_time, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_max_scsicmpl_time,
 	"Use command completion time to control queue depth");
 lpfc_vport_param_show(max_scsicmpl_time);
@@ -3331,7 +3379,7 @@
 */
 unsigned int lpfc_prot_mask = SHOST_DIF_TYPE1_PROTECTION;
 
-module_param(lpfc_prot_mask, uint, 0);
+module_param(lpfc_prot_mask, uint, S_IRUGO);
 MODULE_PARM_DESC(lpfc_prot_mask, "host protection mask");
 
 /*
@@ -3343,9 +3391,28 @@
 #
 */
 unsigned char lpfc_prot_guard = SHOST_DIX_GUARD_IP;
-module_param(lpfc_prot_guard, byte, 0);
+module_param(lpfc_prot_guard, byte, S_IRUGO);
 MODULE_PARM_DESC(lpfc_prot_guard, "host protection guard type");
 
+/*
+ * Delay initial NPort discovery when Clean Address bit is cleared in
+ * FLOGI/FDISC accept and FCID/Fabric name/Fabric portname is changed.
+ * This parameter can have value 0 or 1.
+ * When this parameter is set to 0, no delay is added to the initial
+ * discovery.
+ * When this parameter is set to non-zero value, initial Nport discovery is
+ * delayed by ra_tov seconds when Clean Address bit is cleared in FLOGI/FDISC
+ * accept and FCID/Fabric name/Fabric portname is changed.
+ * Driver always delay Nport discovery for subsequent FLOGI/FDISC completion
+ * when Clean Address bit is cleared in FLOGI/FDISC
+ * accept and FCID/Fabric name/Fabric portname is changed.
+ * Default value is 0.
+ */
+int lpfc_delay_discovery;
+module_param(lpfc_delay_discovery, int, S_IRUGO);
+MODULE_PARM_DESC(lpfc_delay_discovery,
+	"Delay NPort discovery when Clean Address bit is cleared. "
+	"Allowed values: 0,1.");
 
 /*
  * lpfc_sg_seg_cnt - Initial Maximum DMA Segment Count
@@ -3437,6 +3504,7 @@
 	&dev_attr_txcmplq_hw,
 	&dev_attr_lpfc_fips_level,
 	&dev_attr_lpfc_fips_rev,
+	&dev_attr_lpfc_dss,
 	NULL,
 };
 
@@ -4447,7 +4515,7 @@
  * Description:
  * This function is called by the transport after the @fc_vport's symbolic name
  * has been changed. This function re-registers the symbolic name with the
- * switch to propogate the change into the fabric if the vport is active.
+ * switch to propagate the change into the fabric if the vport is active.
  **/
 static void
 lpfc_set_vport_symbolic_name(struct fc_vport *fc_vport)
@@ -4639,6 +4707,7 @@
 	lpfc_aer_support_init(phba, lpfc_aer_support);
 	lpfc_suppress_link_up_init(phba, lpfc_suppress_link_up);
 	lpfc_iocb_cnt_init(phba, lpfc_iocb_cnt);
+	phba->cfg_enable_dss = 1;
 	return;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_bsg.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_bsg.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_bsg.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_bsg.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2009-2010 Emulex.  All rights reserved.                *
+ * Copyright (C) 2009-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -348,7 +348,10 @@
 	dd_data->context_un.iocb.bmp = bmp;
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-		creg_val = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &creg_val)) {
+			rc = -EIO ;
+			goto free_cmdiocbq;
+		}
 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
 		readl(phba->HCregaddr); /* flush */
@@ -599,7 +602,10 @@
 	dd_data->context_un.iocb.ndlp = ndlp;
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-		creg_val = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &creg_val)) {
+			rc = -EIO;
+			goto linkdown_err;
+		}
 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
 		readl(phba->HCregaddr); /* flush */
@@ -613,6 +619,7 @@
 	else
 		rc = -EIO;
 
+linkdown_err:
 	pci_unmap_sg(phba->pcidev, job->request_payload.sg_list,
 		     job->request_payload.sg_cnt, DMA_TO_DEVICE);
 	pci_unmap_sg(phba->pcidev, job->reply_payload.sg_list,
@@ -1357,7 +1364,10 @@
 	dd_data->context_un.iocb.ndlp = ndlp;
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-		creg_val = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &creg_val)) {
+			rc = -IOCB_ERROR;
+			goto issue_ct_rsp_exit;
+		}
 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
 		readl(phba->HCregaddr); /* flush */
@@ -1929,7 +1939,7 @@
  * @rxxri: Receive exchange id
  * @len: Number of data bytes
  *
- * This function allocates and posts a data buffer of sufficient size to recieve
+ * This function allocates and posts a data buffer of sufficient size to receive
  * an unsolicted CT command.
  **/
 static int lpfcdiag_loop_post_rxbufs(struct lpfc_hba *phba, uint16_t rxxri,
@@ -2479,16 +2489,18 @@
 
 	from = (uint8_t *)dd_data->context_un.mbox.mb;
 	job = dd_data->context_un.mbox.set_job;
-	size = job->reply_payload.payload_len;
-	job->reply->reply_payload_rcv_len =
-		sg_copy_from_buffer(job->reply_payload.sg_list,
-				job->reply_payload.sg_cnt,
-				from, size);
-	job->reply->result = 0;
+	if (job) {
+		size = job->reply_payload.payload_len;
+		job->reply->reply_payload_rcv_len =
+			sg_copy_from_buffer(job->reply_payload.sg_list,
+					job->reply_payload.sg_cnt,
+					from, size);
+		job->reply->result = 0;
 
+		job->dd_data = NULL;
+		job->job_done(job);
+	}
 	dd_data->context_un.mbox.set_job = NULL;
-	job->dd_data = NULL;
-	job->job_done(job);
 	/* need to hold the lock until we call job done to hold off
 	 * the timeout handler returning to the midlayer while
 	 * we are stillprocessing the job
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_crtn.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_crtn.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_crtn.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_crtn.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -53,9 +53,9 @@
 void lpfc_init_link(struct lpfc_hba *, LPFC_MBOXQ_t *, uint32_t, uint32_t);
 void lpfc_request_features(struct lpfc_hba *, struct lpfcMboxq *);
 void lpfc_supported_pages(struct lpfcMboxq *);
-void lpfc_sli4_params(struct lpfcMboxq *);
+void lpfc_pc_sli4_params(struct lpfcMboxq *);
 int lpfc_pc_sli4_params_get(struct lpfc_hba *, LPFC_MBOXQ_t *);
-
+int lpfc_get_sli4_parameters(struct lpfc_hba *, LPFC_MBOXQ_t *);
 struct lpfc_vport *lpfc_find_vport_by_did(struct lpfc_hba *, uint32_t);
 void lpfc_cleanup_rcv_buffers(struct lpfc_vport *);
 void lpfc_rcv_seq_check_edtov(struct lpfc_vport *);
@@ -167,6 +167,8 @@
 int lpfc_fdmi_cmd(struct lpfc_vport *, struct lpfc_nodelist *, int);
 void lpfc_fdmi_tmo(unsigned long);
 void lpfc_fdmi_timeout_handler(struct lpfc_vport *);
+void lpfc_delayed_disc_tmo(unsigned long);
+void lpfc_delayed_disc_timeout_handler(struct lpfc_vport *);
 
 int lpfc_config_port_prep(struct lpfc_hba *);
 int lpfc_config_port_post(struct lpfc_hba *);
@@ -252,8 +254,8 @@
 void lpfc_sli_cancel_iocbs(struct lpfc_hba *, struct list_head *, uint32_t,
 			   uint32_t);
 void lpfc_sli_wake_mbox_wait(struct lpfc_hba *, LPFC_MBOXQ_t *);
-
-void lpfc_reset_barrier(struct lpfc_hba * phba);
+int lpfc_selective_reset(struct lpfc_hba *);
+void lpfc_reset_barrier(struct lpfc_hba *);
 int lpfc_sli_brdready(struct lpfc_hba *, uint32_t);
 int lpfc_sli_brdkill(struct lpfc_hba *);
 int lpfc_sli_brdreset(struct lpfc_hba *);
@@ -341,6 +343,7 @@
 extern struct fc_function_template lpfc_vport_transport_functions;
 extern int lpfc_sli_mode;
 extern int lpfc_enable_npiv;
+extern int lpfc_delay_discovery;
 
 int  lpfc_vport_symbolic_node_name(struct lpfc_vport *, char *, size_t);
 int  lpfc_vport_symbolic_port_name(struct lpfc_vport *, char *,	size_t);
@@ -423,6 +426,6 @@
 int lpfc_set_rrq_active(struct lpfc_hba *, struct lpfc_nodelist *,
 	uint16_t, uint16_t, uint16_t);
 void lpfc_cleanup_wt_rrqs(struct lpfc_hba *);
-void lpfc_cleanup_vports_rrqs(struct lpfc_vport *);
+void lpfc_cleanup_vports_rrqs(struct lpfc_vport *, struct lpfc_nodelist *);
 struct lpfc_node_rrq *lpfc_get_active_rrq(struct lpfc_vport *, uint16_t,
 	uint32_t);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_ct.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_ct.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_ct.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_ct.c	2011-05-19 00:06:34.000000000 -0400
@@ -1738,6 +1738,55 @@
 	return 1;
 }
 
+/**
+ * lpfc_delayed_disc_tmo - Timeout handler for delayed discovery timer.
+ * @ptr - Context object of the timer.
+ *
+ * This function set the WORKER_DELAYED_DISC_TMO flag and wake up
+ * the worker thread.
+ **/
+void
+lpfc_delayed_disc_tmo(unsigned long ptr)
+{
+	struct lpfc_vport *vport = (struct lpfc_vport *)ptr;
+	struct lpfc_hba   *phba = vport->phba;
+	uint32_t tmo_posted;
+	unsigned long iflag;
+
+	spin_lock_irqsave(&vport->work_port_lock, iflag);
+	tmo_posted = vport->work_port_events & WORKER_DELAYED_DISC_TMO;
+	if (!tmo_posted)
+		vport->work_port_events |= WORKER_DELAYED_DISC_TMO;
+	spin_unlock_irqrestore(&vport->work_port_lock, iflag);
+
+	if (!tmo_posted)
+		lpfc_worker_wake_up(phba);
+	return;
+}
+
+/**
+ * lpfc_delayed_disc_timeout_handler - Function called by worker thread to
+ *      handle delayed discovery.
+ * @vport: pointer to a host virtual N_Port data structure.
+ *
+ * This function start nport discovery of the vport.
+ **/
+void
+lpfc_delayed_disc_timeout_handler(struct lpfc_vport *vport)
+{
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	spin_lock_irq(shost->host_lock);
+	if (!(vport->fc_flag & FC_DISC_DELAYED)) {
+		spin_unlock_irq(shost->host_lock);
+		return;
+	}
+	vport->fc_flag &= ~FC_DISC_DELAYED;
+	spin_unlock_irq(shost->host_lock);
+
+	lpfc_do_scr_ns_plogi(vport->phba, vport);
+}
+
 void
 lpfc_fdmi_tmo(unsigned long ptr)
 {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_debugfs.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_debugfs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_debugfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_debugfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2007-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2007-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -57,8 +57,8 @@
  * # mount -t debugfs none /sys/kernel/debug
  *
  * The lpfc debugfs directory hierarchy is:
- * lpfc/lpfcX/vportY
- * where X is the lpfc hba unique_id
+ * /sys/kernel/debug/lpfc/fnX/vportY
+ * where X is the lpfc hba function unique_id
  * where Y is the vport VPI on that hba
  *
  * Debugging services available per vport:
@@ -82,52 +82,34 @@
  *                               the HBA. X MUST also be a power of 2.
  */
 static int lpfc_debugfs_enable = 1;
-module_param(lpfc_debugfs_enable, int, 0);
+module_param(lpfc_debugfs_enable, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_enable, "Enable debugfs services");
 
 /* This MUST be a power of 2 */
 static int lpfc_debugfs_max_disc_trc;
-module_param(lpfc_debugfs_max_disc_trc, int, 0);
+module_param(lpfc_debugfs_max_disc_trc, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_max_disc_trc,
 	"Set debugfs discovery trace depth");
 
 /* This MUST be a power of 2 */
 static int lpfc_debugfs_max_slow_ring_trc;
-module_param(lpfc_debugfs_max_slow_ring_trc, int, 0);
+module_param(lpfc_debugfs_max_slow_ring_trc, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_max_slow_ring_trc,
 	"Set debugfs slow ring trace depth");
 
 static int lpfc_debugfs_mask_disc_trc;
-module_param(lpfc_debugfs_mask_disc_trc, int, 0);
+module_param(lpfc_debugfs_mask_disc_trc, int, S_IRUGO);
 MODULE_PARM_DESC(lpfc_debugfs_mask_disc_trc,
 	"Set debugfs discovery trace mask");
 
 #include <linux/debugfs.h>
 
-/* size of output line, for discovery_trace and slow_ring_trace */
-#define LPFC_DEBUG_TRC_ENTRY_SIZE 100
-
-/* nodelist output buffer size */
-#define LPFC_NODELIST_SIZE 8192
-#define LPFC_NODELIST_ENTRY_SIZE 120
-
-/* dumpHBASlim output buffer size */
-#define LPFC_DUMPHBASLIM_SIZE 4096
-
-/* dumpHostSlim output buffer size */
-#define LPFC_DUMPHOSTSLIM_SIZE 4096
-
-/* hbqinfo output buffer size */
-#define LPFC_HBQINFO_SIZE 8192
-
-struct lpfc_debug {
-	char *buffer;
-	int  len;
-};
-
 static atomic_t lpfc_debugfs_seq_trc_cnt = ATOMIC_INIT(0);
 static unsigned long lpfc_debugfs_start_time = 0L;
 
+/* iDiag */
+static struct lpfc_idiag idiag;
+
 /**
  * lpfc_debugfs_disc_trc_data - Dump discovery logging to a buffer
  * @vport: The vport to gather the log info from.
@@ -926,7 +908,7 @@
 	if (!debug)
 		goto out;
 
-	/* Round to page boundry */
+	/* Round to page boundary */
 	printk(KERN_ERR "9059 BLKGRD:  %s: _dump_buf_data=0x%p\n",
 			__func__, _dump_buf_data);
 	debug->buffer = _dump_buf_data;
@@ -956,7 +938,7 @@
 	if (!debug)
 		goto out;
 
-	/* Round to page boundry */
+	/* Round to page boundary */
 	printk(KERN_ERR	"9060 BLKGRD: %s: _dump_buf_dif=0x%p file=%s\n",
 		__func__, _dump_buf_dif, file->f_dentry->d_name.name);
 	debug->buffer = _dump_buf_dif;
@@ -996,8 +978,6 @@
 	return nbytes;
 }
 
-
-
 /**
  * lpfc_debugfs_nodelist_open - Open the nodelist debugfs file
  * @inode: The inode pointer that contains a vport pointer.
@@ -1099,6 +1079,7 @@
 		  size_t nbytes, loff_t *ppos)
 {
 	struct lpfc_debug *debug = file->private_data;
+
 	return simple_read_from_buffer(buf, nbytes, ppos, debug->buffer,
 				       debug->len);
 }
@@ -1137,6 +1118,776 @@
 	return 0;
 }
 
+/*
+ * iDiag debugfs file access methods
+ */
+
+/*
+ * iDiag PCI config space register access methods:
+ *
+ * The PCI config space register accessees of read, write, read-modify-write
+ * for set bits, and read-modify-write for clear bits to SLI4 PCI functions
+ * are provided. In the proper SLI4 PCI function's debugfs iDiag directory,
+ *
+ *      /sys/kernel/debug/lpfc/fn<#>/iDiag
+ *
+ * the access is through the debugfs entry pciCfg:
+ *
+ * 1. For PCI config space register read access, there are two read methods:
+ *    A) read a single PCI config space register in the size of a byte
+ *    (8 bits), a word (16 bits), or a dword (32 bits); or B) browse through
+ *    the 4K extended PCI config space.
+ *
+ *    A) Read a single PCI config space register consists of two steps:
+ *
+ *    Step-1: Set up PCI config space register read command, the command
+ *    syntax is,
+ *
+ *        echo 1 <where> <count> > pciCfg
+ *
+ *    where, 1 is the iDiag command for PCI config space read, <where> is the
+ *    offset from the beginning of the device's PCI config space to read from,
+ *    and <count> is the size of PCI config space register data to read back,
+ *    it will be 1 for reading a byte (8 bits), 2 for reading a word (16 bits
+ *    or 2 bytes), or 4 for reading a dword (32 bits or 4 bytes).
+ *
+ *    Setp-2: Perform the debugfs read operation to execute the idiag command
+ *    set up in Step-1,
+ *
+ *        cat pciCfg
+ *
+ *    Examples:
+ *    To read PCI device's vendor-id and device-id from PCI config space,
+ *
+ *        echo 1 0 4 > pciCfg
+ *        cat pciCfg
+ *
+ *    To read PCI device's currnt command from config space,
+ *
+ *        echo 1 4 2 > pciCfg
+ *        cat pciCfg
+ *
+ *    B) Browse through the entire 4K extended PCI config space also consists
+ *    of two steps:
+ *
+ *    Step-1: Set up PCI config space register browsing command, the command
+ *    syntax is,
+ *
+ *        echo 1 0 4096 > pciCfg
+ *
+ *    where, 1 is the iDiag command for PCI config space read, 0 must be used
+ *    as the offset for PCI config space register browse, and 4096 must be
+ *    used as the count for PCI config space register browse.
+ *
+ *    Step-2: Repeately issue the debugfs read operation to browse through
+ *    the entire PCI config space registers:
+ *
+ *        cat pciCfg
+ *        cat pciCfg
+ *        cat pciCfg
+ *        ...
+ *
+ *    When browsing to the end of the 4K PCI config space, the browse method
+ *    shall wrap around to start reading from beginning again, and again...
+ *
+ * 2. For PCI config space register write access, it supports a single PCI
+ *    config space register write in the size of a byte (8 bits), a word
+ *    (16 bits), or a dword (32 bits). The command syntax is,
+ *
+ *        echo 2 <where> <count> <value> > pciCfg
+ *
+ *    where, 2 is the iDiag command for PCI config space write, <where> is
+ *    the offset from the beginning of the device's PCI config space to write
+ *    into, <count> is the size of data to write into the PCI config space,
+ *    it will be 1 for writing a byte (8 bits), 2 for writing a word (16 bits
+ *    or 2 bytes), or 4 for writing a dword (32 bits or 4 bytes), and <value>
+ *    is the data to be written into the PCI config space register at the
+ *    offset.
+ *
+ *    Examples:
+ *    To disable PCI device's interrupt assertion,
+ *
+ *    1) Read in device's PCI config space register command field <cmd>:
+ *
+ *           echo 1 4 2 > pciCfg
+ *           cat pciCfg
+ *
+ *    2) Set bit 10 (Interrupt Disable bit) in the <cmd>:
+ *
+ *           <cmd> = <cmd> | (1 < 10)
+ *
+ *    3) Write the modified command back:
+ *
+ *           echo 2 4 2 <cmd> > pciCfg
+ *
+ * 3. For PCI config space register set bits access, it supports a single PCI
+ *    config space register set bits in the size of a byte (8 bits), a word
+ *    (16 bits), or a dword (32 bits). The command syntax is,
+ *
+ *        echo 3 <where> <count> <bitmask> > pciCfg
+ *
+ *    where, 3 is the iDiag command for PCI config space set bits, <where> is
+ *    the offset from the beginning of the device's PCI config space to set
+ *    bits into, <count> is the size of the bitmask to set into the PCI config
+ *    space, it will be 1 for setting a byte (8 bits), 2 for setting a word
+ *    (16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4 bytes), and
+ *    <bitmask> is the bitmask, indicating the bits to be set into the PCI
+ *    config space register at the offset. The logic performed to the content
+ *    of the PCI config space register, regval, is,
+ *
+ *        regval |= <bitmask>
+ *
+ * 4. For PCI config space register clear bits access, it supports a single
+ *    PCI config space register clear bits in the size of a byte (8 bits),
+ *    a word (16 bits), or a dword (32 bits). The command syntax is,
+ *
+ *        echo 4 <where> <count> <bitmask> > pciCfg
+ *
+ *    where, 4 is the iDiag command for PCI config space clear bits, <where>
+ *    is the offset from the beginning of the device's PCI config space to
+ *    clear bits from, <count> is the size of the bitmask to set into the PCI
+ *    config space, it will be 1 for setting a byte (8 bits), 2 for setting
+ *    a word(16 bits or 2 bytes), or 4 for setting a dword (32 bits or 4
+ *    bytes), and <bitmask> is the bitmask, indicating the bits to be cleared
+ *    from the PCI config space register at the offset. the logic performed
+ *    to the content of the PCI config space register, regval, is,
+ *
+ *        regval &= ~<bitmask>
+ *
+ * Note, for all single register read, write, set bits, or clear bits access,
+ * the offset (<where>) must be aligned with the size of the data:
+ *
+ * For data size of byte (8 bits), the offset must be aligned to the byte
+ * boundary; for data size of word (16 bits), the offset must be aligned
+ * to the word boundary; while for data size of dword (32 bits), the offset
+ * must be aligned to the dword boundary. Otherwise, the interface will
+ * return the error:
+ *
+ *     "-bash: echo: write error: Invalid argument".
+ *
+ * For example:
+ *
+ *     echo 1 2 4 > pciCfg
+ *     -bash: echo: write error: Invalid argument
+ *
+ * Note also, all of the numbers in the command fields for all read, write,
+ * set bits, and clear bits PCI config space register command fields can be
+ * either decimal or hex.
+ *
+ * For example,
+ *     echo 1 0 4096 > pciCfg
+ *
+ * will be the same as
+ *     echo 1 0 0x1000 > pciCfg
+ *
+ * And,
+ *     echo 2 155 1 10 > pciCfg
+ *
+ * will be
+ *     echo 2 0x9b 1 0xa > pciCfg
+ */
+
+/**
+ * lpfc_idiag_cmd_get - Get and parse idiag debugfs comands from user space
+ * @buf: The pointer to the user space buffer.
+ * @nbytes: The number of bytes in the user space buffer.
+ * @idiag_cmd: pointer to the idiag command struct.
+ *
+ * This routine reads data from debugfs user space buffer and parses the
+ * buffer for getting the idiag command and arguments. The while space in
+ * between the set of data is used as the parsing separator.
+ *
+ * This routine returns 0 when successful, it returns proper error code
+ * back to the user space in error conditions.
+ */
+static int lpfc_idiag_cmd_get(const char __user *buf, size_t nbytes,
+			      struct lpfc_idiag_cmd *idiag_cmd)
+{
+	char mybuf[64];
+	char *pbuf, *step_str;
+	int bsize, i;
+
+	/* Protect copy from user */
+	if (!access_ok(VERIFY_READ, buf, nbytes))
+		return -EFAULT;
+
+	memset(mybuf, 0, sizeof(mybuf));
+	memset(idiag_cmd, 0, sizeof(*idiag_cmd));
+	bsize = min(nbytes, (sizeof(mybuf)-1));
+
+	if (copy_from_user(mybuf, buf, bsize))
+		return -EFAULT;
+	pbuf = &mybuf[0];
+	step_str = strsep(&pbuf, "\t ");
+
+	/* The opcode must present */
+	if (!step_str)
+		return -EINVAL;
+
+	idiag_cmd->opcode = simple_strtol(step_str, NULL, 0);
+	if (idiag_cmd->opcode == 0)
+		return -EINVAL;
+
+	for (i = 0; i < LPFC_IDIAG_CMD_DATA_SIZE; i++) {
+		step_str = strsep(&pbuf, "\t ");
+		if (!step_str)
+			return 0;
+		idiag_cmd->data[i] = simple_strtol(step_str, NULL, 0);
+	}
+	return 0;
+}
+
+/**
+ * lpfc_idiag_open - idiag open debugfs
+ * @inode: The inode pointer that contains a pointer to phba.
+ * @file: The file pointer to attach the file operation.
+ *
+ * Description:
+ * This routine is the entry point for the debugfs open file operation. It
+ * gets the reference to phba from the i_private field in @inode, it then
+ * allocates buffer for the file operation, performs the necessary PCI config
+ * space read into the allocated buffer according to the idiag user command
+ * setup, and then returns a pointer to buffer in the private_data field in
+ * @file.
+ *
+ * Returns:
+ * This function returns zero if successful. On error it will return an
+ * negative error value.
+ **/
+static int
+lpfc_idiag_open(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug;
+
+	debug = kmalloc(sizeof(*debug), GFP_KERNEL);
+	if (!debug)
+		return -ENOMEM;
+
+	debug->i_private = inode->i_private;
+	debug->buffer = NULL;
+	file->private_data = debug;
+
+	return 0;
+}
+
+/**
+ * lpfc_idiag_release - Release idiag access file operation
+ * @inode: The inode pointer that contains a vport pointer. (unused)
+ * @file: The file pointer that contains the buffer to release.
+ *
+ * Description:
+ * This routine is the generic release routine for the idiag access file
+ * operation, it frees the buffer that was allocated when the debugfs file
+ * was opened.
+ *
+ * Returns:
+ * This function returns zero.
+ **/
+static int
+lpfc_idiag_release(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug = file->private_data;
+
+	/* Free the buffers to the file operation */
+	kfree(debug->buffer);
+	kfree(debug);
+
+	return 0;
+}
+
+/**
+ * lpfc_idiag_cmd_release - Release idiag cmd access file operation
+ * @inode: The inode pointer that contains a vport pointer. (unused)
+ * @file: The file pointer that contains the buffer to release.
+ *
+ * Description:
+ * This routine frees the buffer that was allocated when the debugfs file
+ * was opened. It also reset the fields in the idiag command struct in the
+ * case the command is not continuous browsing of the data structure.
+ *
+ * Returns:
+ * This function returns zero.
+ **/
+static int
+lpfc_idiag_cmd_release(struct inode *inode, struct file *file)
+{
+	struct lpfc_debug *debug = file->private_data;
+
+	/* Read PCI config register, if not read all, clear command fields */
+	if ((debug->op == LPFC_IDIAG_OP_RD) &&
+	    (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD))
+		if ((idiag.cmd.data[1] == sizeof(uint8_t)) ||
+		    (idiag.cmd.data[1] == sizeof(uint16_t)) ||
+		    (idiag.cmd.data[1] == sizeof(uint32_t)))
+			memset(&idiag, 0, sizeof(idiag));
+
+	/* Write PCI config register, clear command fields */
+	if ((debug->op == LPFC_IDIAG_OP_WR) &&
+	    (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR))
+		memset(&idiag, 0, sizeof(idiag));
+
+	/* Free the buffers to the file operation */
+	kfree(debug->buffer);
+	kfree(debug);
+
+	return 0;
+}
+
+/**
+ * lpfc_idiag_pcicfg_read - idiag debugfs read pcicfg
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba pci config space according to the
+ * idiag command, and copies to user @buf. Depending on the PCI config space
+ * read command setup, it does either a single register read of a byte
+ * (8 bits), a word (16 bits), or a dword (32 bits) or browsing through all
+ * registers from the 4K extended PCI config space.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_pcicfg_read(struct file *file, char __user *buf, size_t nbytes,
+		       loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+	int offset_label, offset, len = 0, index = LPFC_PCI_CFG_RD_SIZE;
+	int where, count;
+	char *pbuffer;
+	struct pci_dev *pdev;
+	uint32_t u32val;
+	uint16_t u16val;
+	uint8_t u8val;
+
+	pdev = phba->pcidev;
+	if (!pdev)
+		return 0;
+
+	/* This is a user read operation */
+	debug->op = LPFC_IDIAG_OP_RD;
+
+	if (!debug->buffer)
+		debug->buffer = kmalloc(LPFC_PCI_CFG_SIZE, GFP_KERNEL);
+	if (!debug->buffer)
+		return 0;
+	pbuffer = debug->buffer;
+
+	if (*ppos)
+		return 0;
+
+	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
+		where = idiag.cmd.data[0];
+		count = idiag.cmd.data[1];
+	} else
+		return 0;
+
+	/* Read single PCI config space register */
+	switch (count) {
+	case SIZE_U8: /* byte (8 bits) */
+		pci_read_config_byte(pdev, where, &u8val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%03x: %02x\n", where, u8val);
+		break;
+	case SIZE_U16: /* word (16 bits) */
+		pci_read_config_word(pdev, where, &u16val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%03x: %04x\n", where, u16val);
+		break;
+	case SIZE_U32: /* double word (32 bits) */
+		pci_read_config_dword(pdev, where, &u32val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%03x: %08x\n", where, u32val);
+		break;
+	case LPFC_PCI_CFG_SIZE: /* browse all */
+		goto pcicfg_browse;
+		break;
+	default:
+		/* illegal count */
+		len = 0;
+		break;
+	}
+	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+
+pcicfg_browse:
+
+	/* Browse all PCI config space registers */
+	offset_label = idiag.offset.last_rd;
+	offset = offset_label;
+
+	/* Read PCI config space */
+	len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+			"%03x: ", offset_label);
+	while (index > 0) {
+		pci_read_config_dword(pdev, offset, &u32val);
+		len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+				"%08x ", u32val);
+		offset += sizeof(uint32_t);
+		index -= sizeof(uint32_t);
+		if (!index)
+			len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+					"\n");
+		else if (!(index % (8 * sizeof(uint32_t)))) {
+			offset_label += (8 * sizeof(uint32_t));
+			len += snprintf(pbuffer+len, LPFC_PCI_CFG_SIZE-len,
+					"\n%03x: ", offset_label);
+		}
+	}
+
+	/* Set up the offset for next portion of pci cfg read */
+	idiag.offset.last_rd += LPFC_PCI_CFG_RD_SIZE;
+	if (idiag.offset.last_rd >= LPFC_PCI_CFG_SIZE)
+		idiag.offset.last_rd = 0;
+
+	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
+/**
+ * lpfc_idiag_pcicfg_write - Syntax check and set up idiag pcicfg commands
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the user data from.
+ * @nbytes: The number of bytes to get.
+ * @ppos: The position in the file to start reading from.
+ *
+ * This routine get the debugfs idiag command struct from user space and
+ * then perform the syntax check for PCI config space read or write command
+ * accordingly. In the case of PCI config space read command, it sets up
+ * the command in the idiag command struct for the debugfs read operation.
+ * In the case of PCI config space write operation, it executes the write
+ * operation into the PCI config space accordingly.
+ *
+ * It returns the @nbytges passing in from debugfs user space when successful.
+ * In case of error conditions, it returns proper error code back to the user
+ * space.
+ */
+static ssize_t
+lpfc_idiag_pcicfg_write(struct file *file, const char __user *buf,
+			size_t nbytes, loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+	uint32_t where, value, count;
+	uint32_t u32val;
+	uint16_t u16val;
+	uint8_t u8val;
+	struct pci_dev *pdev;
+	int rc;
+
+	pdev = phba->pcidev;
+	if (!pdev)
+		return -EFAULT;
+
+	/* This is a user write operation */
+	debug->op = LPFC_IDIAG_OP_WR;
+
+	rc = lpfc_idiag_cmd_get(buf, nbytes, &idiag.cmd);
+	if (rc)
+		return rc;
+
+	if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_RD) {
+		/* Read command from PCI config space, set up command fields */
+		where = idiag.cmd.data[0];
+		count = idiag.cmd.data[1];
+		if (count == LPFC_PCI_CFG_SIZE) {
+			if (where != 0)
+				goto error_out;
+		} else if ((count != sizeof(uint8_t)) &&
+			   (count != sizeof(uint16_t)) &&
+			   (count != sizeof(uint32_t)))
+			goto error_out;
+		if (count == sizeof(uint8_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
+				goto error_out;
+			if (where % sizeof(uint8_t))
+				goto error_out;
+		}
+		if (count == sizeof(uint16_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
+				goto error_out;
+			if (where % sizeof(uint16_t))
+				goto error_out;
+		}
+		if (count == sizeof(uint32_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
+				goto error_out;
+			if (where % sizeof(uint32_t))
+				goto error_out;
+		}
+	} else if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR ||
+		   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST ||
+		   idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+		/* Write command to PCI config space, read-modify-write */
+		where = idiag.cmd.data[0];
+		count = idiag.cmd.data[1];
+		value = idiag.cmd.data[2];
+		/* Sanity checks */
+		if ((count != sizeof(uint8_t)) &&
+		    (count != sizeof(uint16_t)) &&
+		    (count != sizeof(uint32_t)))
+			goto error_out;
+		if (count == sizeof(uint8_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint8_t))
+				goto error_out;
+			if (where % sizeof(uint8_t))
+				goto error_out;
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
+				pci_write_config_byte(pdev, where,
+						      (uint8_t)value);
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
+				rc = pci_read_config_byte(pdev, where, &u8val);
+				if (!rc) {
+					u8val |= (uint8_t)value;
+					pci_write_config_byte(pdev, where,
+							      u8val);
+				}
+			}
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+				rc = pci_read_config_byte(pdev, where, &u8val);
+				if (!rc) {
+					u8val &= (uint8_t)(~value);
+					pci_write_config_byte(pdev, where,
+							      u8val);
+				}
+			}
+		}
+		if (count == sizeof(uint16_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint16_t))
+				goto error_out;
+			if (where % sizeof(uint16_t))
+				goto error_out;
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
+				pci_write_config_word(pdev, where,
+						      (uint16_t)value);
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
+				rc = pci_read_config_word(pdev, where, &u16val);
+				if (!rc) {
+					u16val |= (uint16_t)value;
+					pci_write_config_word(pdev, where,
+							      u16val);
+				}
+			}
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+				rc = pci_read_config_word(pdev, where, &u16val);
+				if (!rc) {
+					u16val &= (uint16_t)(~value);
+					pci_write_config_word(pdev, where,
+							      u16val);
+				}
+			}
+		}
+		if (count == sizeof(uint32_t)) {
+			if (where > LPFC_PCI_CFG_SIZE - sizeof(uint32_t))
+				goto error_out;
+			if (where % sizeof(uint32_t))
+				goto error_out;
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_WR)
+				pci_write_config_dword(pdev, where, value);
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_ST) {
+				rc = pci_read_config_dword(pdev, where,
+							   &u32val);
+				if (!rc) {
+					u32val |= value;
+					pci_write_config_dword(pdev, where,
+							       u32val);
+				}
+			}
+			if (idiag.cmd.opcode == LPFC_IDIAG_CMD_PCICFG_CL) {
+				rc = pci_read_config_dword(pdev, where,
+							   &u32val);
+				if (!rc) {
+					u32val &= ~value;
+					pci_write_config_dword(pdev, where,
+							       u32val);
+				}
+			}
+		}
+	} else
+		/* All other opecodes are illegal for now */
+		goto error_out;
+
+	return nbytes;
+error_out:
+	memset(&idiag, 0, sizeof(idiag));
+	return -EINVAL;
+}
+
+/**
+ * lpfc_idiag_queinfo_read - idiag debugfs read queue information
+ * @file: The file pointer to read from.
+ * @buf: The buffer to copy the data to.
+ * @nbytes: The number of bytes to read.
+ * @ppos: The position in the file to start reading from.
+ *
+ * Description:
+ * This routine reads data from the @phba SLI4 PCI function queue information,
+ * and copies to user @buf.
+ *
+ * Returns:
+ * This function returns the amount of data that was read (this could be less
+ * than @nbytes if the end of the file was reached) or a negative error value.
+ **/
+static ssize_t
+lpfc_idiag_queinfo_read(struct file *file, char __user *buf, size_t nbytes,
+			loff_t *ppos)
+{
+	struct lpfc_debug *debug = file->private_data;
+	struct lpfc_hba *phba = (struct lpfc_hba *)debug->i_private;
+	int len = 0, fcp_qidx;
+	char *pbuffer;
+
+	if (!debug->buffer)
+		debug->buffer = kmalloc(LPFC_QUE_INFO_GET_BUF_SIZE, GFP_KERNEL);
+	if (!debug->buffer)
+		return 0;
+	pbuffer = debug->buffer;
+
+	if (*ppos)
+		return 0;
+
+	/* Get slow-path event queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path EQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], EQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.sp_eq->queue_id,
+			phba->sli4_hba.sp_eq->entry_count,
+			phba->sli4_hba.sp_eq->host_index,
+			phba->sli4_hba.sp_eq->hba_index);
+
+	/* Get fast-path event queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Fast-path EQ information:\n");
+	for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) {
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\tID [%02d], EQE-COUNT [%04d], "
+				"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+				phba->sli4_hba.fp_eq[fcp_qidx]->queue_id,
+				phba->sli4_hba.fp_eq[fcp_qidx]->entry_count,
+				phba->sli4_hba.fp_eq[fcp_qidx]->host_index,
+				phba->sli4_hba.fp_eq[fcp_qidx]->hba_index);
+	}
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+
+	/* Get mailbox complete queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Mailbox CQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated EQ-ID [%02d]:\n",
+			phba->sli4_hba.mbx_cq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], CQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.mbx_cq->queue_id,
+			phba->sli4_hba.mbx_cq->entry_count,
+			phba->sli4_hba.mbx_cq->host_index,
+			phba->sli4_hba.mbx_cq->hba_index);
+
+	/* Get slow-path complete queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path CQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated EQ-ID [%02d]:\n",
+			phba->sli4_hba.els_cq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], CQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.els_cq->queue_id,
+			phba->sli4_hba.els_cq->entry_count,
+			phba->sli4_hba.els_cq->host_index,
+			phba->sli4_hba.els_cq->hba_index);
+
+	/* Get fast-path complete queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Fast-path CQ information:\n");
+	for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_eq_count; fcp_qidx++) {
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\t\tAssociated EQ-ID [%02d]:\n",
+				phba->sli4_hba.fcp_cq[fcp_qidx]->assoc_qid);
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+		"\tID [%02d], EQE-COUNT [%04d], "
+		"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+		phba->sli4_hba.fcp_cq[fcp_qidx]->queue_id,
+		phba->sli4_hba.fcp_cq[fcp_qidx]->entry_count,
+		phba->sli4_hba.fcp_cq[fcp_qidx]->host_index,
+		phba->sli4_hba.fcp_cq[fcp_qidx]->hba_index);
+	}
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+
+	/* Get mailbox queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Mailbox MQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated CQ-ID [%02d]:\n",
+			phba->sli4_hba.mbx_wq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], MQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.mbx_wq->queue_id,
+			phba->sli4_hba.mbx_wq->entry_count,
+			phba->sli4_hba.mbx_wq->host_index,
+			phba->sli4_hba.mbx_wq->hba_index);
+
+	/* Get slow-path work queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path WQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated CQ-ID [%02d]:\n",
+			phba->sli4_hba.els_wq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], WQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n\n",
+			phba->sli4_hba.els_wq->queue_id,
+			phba->sli4_hba.els_wq->entry_count,
+			phba->sli4_hba.els_wq->host_index,
+			phba->sli4_hba.els_wq->hba_index);
+
+	/* Get fast-path work queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Fast-path WQ information:\n");
+	for (fcp_qidx = 0; fcp_qidx < phba->cfg_fcp_wq_count; fcp_qidx++) {
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\t\tAssociated CQ-ID [%02d]:\n",
+				phba->sli4_hba.fcp_wq[fcp_qidx]->assoc_qid);
+		len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+				"\tID [%02d], WQE-COUNT [%04d], "
+				"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+				phba->sli4_hba.fcp_wq[fcp_qidx]->queue_id,
+				phba->sli4_hba.fcp_wq[fcp_qidx]->entry_count,
+				phba->sli4_hba.fcp_wq[fcp_qidx]->host_index,
+				phba->sli4_hba.fcp_wq[fcp_qidx]->hba_index);
+	}
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len, "\n");
+
+	/* Get receive queue information */
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"Slow-path RQ information:\n");
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\t\tAssociated CQ-ID [%02d]:\n",
+			phba->sli4_hba.hdr_rq->assoc_qid);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], RHQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+			phba->sli4_hba.hdr_rq->queue_id,
+			phba->sli4_hba.hdr_rq->entry_count,
+			phba->sli4_hba.hdr_rq->host_index,
+			phba->sli4_hba.hdr_rq->hba_index);
+	len += snprintf(pbuffer+len, LPFC_QUE_INFO_GET_BUF_SIZE-len,
+			"\tID [%02d], RDQE-COUNT [%04d], "
+			"HOST-INDEX [%04x], PORT-INDEX [%04x]\n",
+			phba->sli4_hba.dat_rq->queue_id,
+			phba->sli4_hba.dat_rq->entry_count,
+			phba->sli4_hba.dat_rq->host_index,
+			phba->sli4_hba.dat_rq->hba_index);
+
+	return simple_read_from_buffer(buf, nbytes, ppos, pbuffer, len);
+}
+
 #undef lpfc_debugfs_op_disc_trc
 static const struct file_operations lpfc_debugfs_op_disc_trc = {
 	.owner =        THIS_MODULE,
@@ -1213,6 +1964,28 @@
 
 static struct dentry *lpfc_debugfs_root = NULL;
 static atomic_t lpfc_debugfs_hba_count;
+
+/*
+ * File operations for the iDiag debugfs
+ */
+#undef lpfc_idiag_op_pciCfg
+static const struct file_operations lpfc_idiag_op_pciCfg = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_idiag_open,
+	.llseek =       lpfc_debugfs_lseek,
+	.read =         lpfc_idiag_pcicfg_read,
+	.write =        lpfc_idiag_pcicfg_write,
+	.release =      lpfc_idiag_cmd_release,
+};
+
+#undef lpfc_idiag_op_queInfo
+static const struct file_operations lpfc_idiag_op_queInfo = {
+	.owner =        THIS_MODULE,
+	.open =         lpfc_idiag_open,
+	.read =         lpfc_idiag_queinfo_read,
+	.release =      lpfc_idiag_release,
+};
+
 #endif
 
 /**
@@ -1249,8 +2022,8 @@
 	if (!lpfc_debugfs_start_time)
 		lpfc_debugfs_start_time = jiffies;
 
-	/* Setup lpfcX directory for specific HBA */
-	snprintf(name, sizeof(name), "lpfc%d", phba->brd_no);
+	/* Setup funcX directory for specific HBA PCI function */
+	snprintf(name, sizeof(name), "fn%d", phba->brd_no);
 	if (!phba->hba_debugfs_root) {
 		phba->hba_debugfs_root =
 			debugfs_create_dir(name, lpfc_debugfs_root);
@@ -1275,28 +2048,38 @@
 		}
 
 		/* Setup dumpHBASlim */
-		snprintf(name, sizeof(name), "dumpHBASlim");
-		phba->debug_dumpHBASlim =
-			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
-				 phba->hba_debugfs_root,
-				 phba, &lpfc_debugfs_op_dumpHBASlim);
-		if (!phba->debug_dumpHBASlim) {
-			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-				"0413 Cannot create debugfs dumpHBASlim\n");
-			goto debug_failed;
-		}
+		if (phba->sli_rev < LPFC_SLI_REV4) {
+			snprintf(name, sizeof(name), "dumpHBASlim");
+			phba->debug_dumpHBASlim =
+				debugfs_create_file(name,
+					S_IFREG|S_IRUGO|S_IWUSR,
+					phba->hba_debugfs_root,
+					phba, &lpfc_debugfs_op_dumpHBASlim);
+			if (!phba->debug_dumpHBASlim) {
+				lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+						 "0413 Cannot create debugfs "
+						"dumpHBASlim\n");
+				goto debug_failed;
+			}
+		} else
+			phba->debug_dumpHBASlim = NULL;
 
 		/* Setup dumpHostSlim */
-		snprintf(name, sizeof(name), "dumpHostSlim");
-		phba->debug_dumpHostSlim =
-			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
-				 phba->hba_debugfs_root,
-				 phba, &lpfc_debugfs_op_dumpHostSlim);
-		if (!phba->debug_dumpHostSlim) {
-			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-				"0414 Cannot create debugfs dumpHostSlim\n");
-			goto debug_failed;
-		}
+		if (phba->sli_rev < LPFC_SLI_REV4) {
+			snprintf(name, sizeof(name), "dumpHostSlim");
+			phba->debug_dumpHostSlim =
+				debugfs_create_file(name,
+					S_IFREG|S_IRUGO|S_IWUSR,
+					phba->hba_debugfs_root,
+					phba, &lpfc_debugfs_op_dumpHostSlim);
+			if (!phba->debug_dumpHostSlim) {
+				lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+						 "0414 Cannot create debugfs "
+						 "dumpHostSlim\n");
+				goto debug_failed;
+			}
+		} else
+			phba->debug_dumpHBASlim = NULL;
 
 		/* Setup dumpData */
 		snprintf(name, sizeof(name), "dumpData");
@@ -1322,8 +2105,6 @@
 			goto debug_failed;
 		}
 
-
-
 		/* Setup slow ring trace */
 		if (lpfc_debugfs_max_slow_ring_trc) {
 			num = lpfc_debugfs_max_slow_ring_trc - 1;
@@ -1342,7 +2123,6 @@
 			}
 		}
 
-
 		snprintf(name, sizeof(name), "slow_ring_trace");
 		phba->debug_slow_ring_trc =
 			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
@@ -1378,7 +2158,7 @@
 			debugfs_create_dir(name, phba->hba_debugfs_root);
 		if (!vport->vport_debugfs_root) {
 			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-					 "0417 Cant create debugfs\n");
+					 "0417 Can't create debugfs\n");
 			goto debug_failed;
 		}
 		atomic_inc(&phba->debugfs_vport_count);
@@ -1431,9 +2211,56 @@
 				 vport, &lpfc_debugfs_op_nodelist);
 	if (!vport->debug_nodelist) {
 		lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
-				 "0409 Cant create debugfs nodelist\n");
+				 "0409 Can't create debugfs nodelist\n");
 		goto debug_failed;
 	}
+
+	/*
+	 * iDiag debugfs root entry points for SLI4 device only
+	 */
+	if (phba->sli_rev < LPFC_SLI_REV4)
+		goto debug_failed;
+
+	snprintf(name, sizeof(name), "iDiag");
+	if (!phba->idiag_root) {
+		phba->idiag_root =
+			debugfs_create_dir(name, phba->hba_debugfs_root);
+		if (!phba->idiag_root) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "2922 Can't create idiag debugfs\n");
+			goto debug_failed;
+		}
+		/* Initialize iDiag data structure */
+		memset(&idiag, 0, sizeof(idiag));
+	}
+
+	/* iDiag read PCI config space */
+	snprintf(name, sizeof(name), "pciCfg");
+	if (!phba->idiag_pci_cfg) {
+		phba->idiag_pci_cfg =
+			debugfs_create_file(name, S_IFREG|S_IRUGO|S_IWUSR,
+				phba->idiag_root, phba, &lpfc_idiag_op_pciCfg);
+		if (!phba->idiag_pci_cfg) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "2923 Can't create idiag debugfs\n");
+			goto debug_failed;
+		}
+		idiag.offset.last_rd = 0;
+	}
+
+	/* iDiag get PCI function queue information */
+	snprintf(name, sizeof(name), "queInfo");
+	if (!phba->idiag_que_info) {
+		phba->idiag_que_info =
+			debugfs_create_file(name, S_IFREG|S_IRUGO,
+			phba->idiag_root, phba, &lpfc_idiag_op_queInfo);
+		if (!phba->idiag_que_info) {
+			lpfc_printf_vlog(vport, KERN_ERR, LOG_INIT,
+					 "2924 Can't create idiag debugfs\n");
+			goto debug_failed;
+		}
+	}
+
 debug_failed:
 	return;
 #endif
@@ -1508,8 +2335,31 @@
 			phba->debug_slow_ring_trc = NULL;
 		}
 
+		/*
+		 * iDiag release
+		 */
+		if (phba->sli_rev == LPFC_SLI_REV4) {
+			if (phba->idiag_que_info) {
+				/* iDiag queInfo */
+				debugfs_remove(phba->idiag_que_info);
+				phba->idiag_que_info = NULL;
+			}
+			if (phba->idiag_pci_cfg) {
+				/* iDiag pciCfg */
+				debugfs_remove(phba->idiag_pci_cfg);
+				phba->idiag_pci_cfg = NULL;
+			}
+
+			/* Finally remove the iDiag debugfs root */
+			if (phba->idiag_root) {
+				/* iDiag root */
+				debugfs_remove(phba->idiag_root);
+				phba->idiag_root = NULL;
+			}
+		}
+
 		if (phba->hba_debugfs_root) {
-			debugfs_remove(phba->hba_debugfs_root); /* lpfcX */
+			debugfs_remove(phba->hba_debugfs_root); /* fnX */
 			phba->hba_debugfs_root = NULL;
 			atomic_dec(&lpfc_debugfs_hba_count);
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_debugfs.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_debugfs.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_debugfs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_debugfs.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2007 Emulex.  All rights reserved.                *
+ * Copyright (C) 2007-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -22,6 +22,44 @@
 #define _H_LPFC_DEBUG_FS
 
 #ifdef CONFIG_SCSI_LPFC_DEBUG_FS
+
+/* size of output line, for discovery_trace and slow_ring_trace */
+#define LPFC_DEBUG_TRC_ENTRY_SIZE 100
+
+/* nodelist output buffer size */
+#define LPFC_NODELIST_SIZE 8192
+#define LPFC_NODELIST_ENTRY_SIZE 120
+
+/* dumpHBASlim output buffer size */
+#define LPFC_DUMPHBASLIM_SIZE 4096
+
+/* dumpHostSlim output buffer size */
+#define LPFC_DUMPHOSTSLIM_SIZE 4096
+
+/* hbqinfo output buffer size */
+#define LPFC_HBQINFO_SIZE 8192
+
+/* rdPciConf output buffer size */
+#define LPFC_PCI_CFG_SIZE 4096
+#define LPFC_PCI_CFG_RD_BUF_SIZE (LPFC_PCI_CFG_SIZE/2)
+#define LPFC_PCI_CFG_RD_SIZE (LPFC_PCI_CFG_SIZE/4)
+
+/* queue info output buffer size */
+#define LPFC_QUE_INFO_GET_BUF_SIZE 2048
+
+#define SIZE_U8  sizeof(uint8_t)
+#define SIZE_U16 sizeof(uint16_t)
+#define SIZE_U32 sizeof(uint32_t)
+
+struct lpfc_debug {
+	char *i_private;
+	char op;
+#define LPFC_IDIAG_OP_RD 1
+#define LPFC_IDIAG_OP_WR 2
+	char *buffer;
+	int  len;
+};
+
 struct lpfc_debugfs_trc {
 	char *fmt;
 	uint32_t data1;
@@ -30,6 +68,26 @@
 	uint32_t seq_cnt;
 	unsigned long jif;
 };
+
+struct lpfc_idiag_offset {
+	uint32_t last_rd;
+};
+
+#define LPFC_IDIAG_CMD_DATA_SIZE 4
+struct lpfc_idiag_cmd {
+	uint32_t opcode;
+#define LPFC_IDIAG_CMD_PCICFG_RD 0x00000001
+#define LPFC_IDIAG_CMD_PCICFG_WR 0x00000002
+#define LPFC_IDIAG_CMD_PCICFG_ST 0x00000003
+#define LPFC_IDIAG_CMD_PCICFG_CL 0x00000004
+	uint32_t data[LPFC_IDIAG_CMD_DATA_SIZE];
+};
+
+struct lpfc_idiag {
+	uint32_t active;
+	struct lpfc_idiag_cmd cmd;
+	struct lpfc_idiag_offset offset;
+};
 #endif
 
 /* Mask for discovery_trace */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_els.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_els.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_els.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_els.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -89,7 +89,8 @@
 		return 0;
 
 	/* Read the HBA Host Attention Register */
-	ha_copy = readl(phba->HAregaddr);
+	if (lpfc_readl(phba->HAregaddr, &ha_copy))
+		return 1;
 
 	if (!(ha_copy & HA_LATT))
 		return 0;
@@ -101,7 +102,7 @@
 			 phba->pport->port_state);
 
 	/* CLEAR_LA should re-enable link attention events and
-	 * we should then imediately take a LATT event. The
+	 * we should then immediately take a LATT event. The
 	 * LATT processing should call lpfc_linkdown() which
 	 * will cleanup any left over in-progress discovery
 	 * events.
@@ -485,6 +486,59 @@
 }
 
 /**
+ * lpfc_check_clean_addr_bit - Check whether assigned FCID is clean.
+ * @vport: pointer to a host virtual N_Port data structure.
+ * @sp: pointer to service parameter data structure.
+ *
+ * This routine is called from FLOGI/FDISC completion handler functions.
+ * lpfc_check_clean_addr_bit return 1 when FCID/Fabric portname/ Fabric
+ * node nodename is changed in the completion service parameter else return
+ * 0. This function also set flag in the vport data structure to delay
+ * NP_Port discovery after the FLOGI/FDISC completion if Clean address bit
+ * in FLOGI/FDISC response is cleared and FCID/Fabric portname/ Fabric
+ * node nodename is changed in the completion service parameter.
+ *
+ * Return code
+ *   0 - FCID and Fabric Nodename and Fabric portname is not changed.
+ *   1 - FCID or Fabric Nodename or Fabric portname is changed.
+ *
+ **/
+static uint8_t
+lpfc_check_clean_addr_bit(struct lpfc_vport *vport,
+		struct serv_parm *sp)
+{
+	uint8_t fabric_param_changed = 0;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	if ((vport->fc_prevDID != vport->fc_myDID) ||
+		memcmp(&vport->fabric_portname, &sp->portName,
+			sizeof(struct lpfc_name)) ||
+		memcmp(&vport->fabric_nodename, &sp->nodeName,
+			sizeof(struct lpfc_name)))
+		fabric_param_changed = 1;
+
+	/*
+	 * Word 1 Bit 31 in common service parameter is overloaded.
+	 * Word 1 Bit 31 in FLOGI request is multiple NPort request
+	 * Word 1 Bit 31 in FLOGI response is clean address bit
+	 *
+	 * If fabric parameter is changed and clean address bit is
+	 * cleared delay nport discovery if
+	 * - vport->fc_prevDID != 0 (not initial discovery) OR
+	 * - lpfc_delay_discovery module parameter is set.
+	 */
+	if (fabric_param_changed && !sp->cmn.clean_address_bit &&
+	    (vport->fc_prevDID || lpfc_delay_discovery)) {
+		spin_lock_irq(shost->host_lock);
+		vport->fc_flag |= FC_DISC_DELAYED;
+		spin_unlock_irq(shost->host_lock);
+	}
+
+	return fabric_param_changed;
+}
+
+
+/**
  * lpfc_cmpl_els_flogi_fabric - Completion function for flogi to a fabric port
  * @vport: pointer to a host virtual N_Port data structure.
  * @ndlp: pointer to a node-list data structure.
@@ -512,6 +566,7 @@
 	struct lpfc_hba  *phba = vport->phba;
 	struct lpfc_nodelist *np;
 	struct lpfc_nodelist *next_np;
+	uint8_t fabric_param_changed;
 
 	spin_lock_irq(shost->host_lock);
 	vport->fc_flag |= FC_FABRIC;
@@ -544,6 +599,12 @@
 		ndlp->nlp_class_sup |= FC_COS_CLASS4;
 	ndlp->nlp_maxframe = ((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) |
 				sp->cmn.bbRcvSizeLsb;
+
+	fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
+	memcpy(&vport->fabric_portname, &sp->portName,
+			sizeof(struct lpfc_name));
+	memcpy(&vport->fabric_nodename, &sp->nodeName,
+			sizeof(struct lpfc_name));
 	memcpy(&phba->fc_fabparam, sp, sizeof(struct serv_parm));
 
 	if (phba->sli3_options & LPFC_SLI3_NPIV_ENABLED) {
@@ -565,7 +626,7 @@
 		}
 	}
 
-	if ((vport->fc_prevDID != vport->fc_myDID) &&
+	if (fabric_param_changed &&
 		!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
 
 		/* If our NportID changed, we need to ensure all
@@ -1538,7 +1599,7 @@
  * This routine is the completion callback function for issuing the Port
  * Login (PLOGI) command. For PLOGI completion, there must be an active
  * ndlp on the vport node list that matches the remote node ID from the
- * PLOGI reponse IOCB. If such ndlp does not exist, the PLOGI is simply
+ * PLOGI response IOCB. If such ndlp does not exist, the PLOGI is simply
  * ignored and command IOCB released. The PLOGI response IOCB status is
  * checked for error conditons. If there is error status reported, PLOGI
  * retry shall be attempted by invoking the lpfc_els_retry() routine.
@@ -2203,6 +2264,7 @@
 	struct Scsi_Host  *shost = lpfc_shost_from_vport(vport);
 	IOCB_t *irsp;
 	struct lpfc_sli *psli;
+	struct lpfcMboxq *mbox;
 
 	psli = &phba->sli;
 	/* we pass cmdiocb to state machine which needs rspiocb as well */
@@ -2260,6 +2322,21 @@
 					NLP_EVT_CMPL_LOGO);
 out:
 	lpfc_els_free_iocb(phba, cmdiocb);
+	/* If we are in pt2pt mode, we could rcv new S_ID on PLOGI */
+	if ((vport->fc_flag & FC_PT2PT) &&
+		!(vport->fc_flag & FC_PT2PT_PLOGI)) {
+		phba->pport->fc_myDID = 0;
+		mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
+		if (mbox) {
+			lpfc_config_link(phba, mbox);
+			mbox->mbox_cmpl = lpfc_sli_def_mbox_cmpl;
+			mbox->vport = vport;
+			if (lpfc_sli_issue_mbox(phba, mbox, MBX_NOWAIT) ==
+				MBX_NOT_FINISHED) {
+				mempool_free(mbox, phba->mbox_mem_pool);
+			}
+		}
+	}
 	return;
 }
 
@@ -2745,7 +2822,8 @@
 		}
 		break;
 	case ELS_CMD_FDISC:
-		lpfc_issue_els_fdisc(vport, ndlp, retry);
+		if (!(vport->fc_flag & FC_VPORT_NEEDS_INIT_VPI))
+			lpfc_issue_els_fdisc(vport, ndlp, retry);
 		break;
 	}
 	return;
@@ -2815,9 +2893,17 @@
 
 	switch (irsp->ulpStatus) {
 	case IOSTAT_FCP_RSP_ERROR:
+		break;
 	case IOSTAT_REMOTE_STOP:
+		if (phba->sli_rev == LPFC_SLI_REV4) {
+			/* This IO was aborted by the target, we don't
+			 * know the rxid and because we did not send the
+			 * ABTS we cannot generate and RRQ.
+			 */
+			lpfc_set_rrq_active(phba, ndlp,
+					 cmdiocb->sli4_xritag, 0, 0);
+		}
 		break;
-
 	case IOSTAT_LOCAL_REJECT:
 		switch ((irsp->un.ulpWord[4] & 0xff)) {
 		case IOERR_LOOP_OPEN_FAILURE:
@@ -4013,28 +4099,34 @@
 	uint8_t *pcmd;
 	struct RRQ *rrq;
 	uint16_t rxid;
+	uint16_t xri;
 	struct lpfc_node_rrq *prrq;
 
 
 	pcmd = (uint8_t *) (((struct lpfc_dmabuf *) iocb->context2)->virt);
 	pcmd += sizeof(uint32_t);
 	rrq = (struct RRQ *)pcmd;
-	rxid = bf_get(rrq_oxid, rrq);
+	rrq->rrq_exchg = be32_to_cpu(rrq->rrq_exchg);
+	rxid = be16_to_cpu(bf_get(rrq_rxid, rrq));
 
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 			"2883 Clear RRQ for SID:x%x OXID:x%x RXID:x%x"
 			" x%x x%x\n",
-			bf_get(rrq_did, rrq),
-			bf_get(rrq_oxid, rrq),
+			be32_to_cpu(bf_get(rrq_did, rrq)),
+			be16_to_cpu(bf_get(rrq_oxid, rrq)),
 			rxid,
 			iocb->iotag, iocb->iocb.ulpContext);
 
 	lpfc_debugfs_disc_trc(vport, LPFC_DISC_TRC_ELS_RSP,
 		"Clear RRQ:  did:x%x flg:x%x exchg:x%.08x",
 		ndlp->nlp_DID, ndlp->nlp_flag, rrq->rrq_exchg);
-	prrq = lpfc_get_active_rrq(vport, rxid, ndlp->nlp_DID);
+	if (vport->fc_myDID == be32_to_cpu(bf_get(rrq_did, rrq)))
+		xri = be16_to_cpu(bf_get(rrq_oxid, rrq));
+	else
+		xri = rxid;
+	prrq = lpfc_get_active_rrq(vport, xri, ndlp->nlp_DID);
 	if (prrq)
-		lpfc_clr_rrq_active(phba, rxid, prrq);
+		lpfc_clr_rrq_active(phba, xri, prrq);
 	return;
 }
 
@@ -6166,6 +6258,11 @@
 	if (vport->load_flag & FC_UNLOADING)
 		goto dropit;
 
+	/* If NPort discovery is delayed drop incoming ELS */
+	if ((vport->fc_flag & FC_DISC_DELAYED) &&
+			(cmd != ELS_CMD_PLOGI))
+		goto dropit;
+
 	ndlp = lpfc_findnode_did(vport, did);
 	if (!ndlp) {
 		/* Cannot find existing Fabric ndlp, so allocate a new one */
@@ -6218,6 +6315,12 @@
 		ndlp = lpfc_plogi_confirm_nport(phba, payload, ndlp);
 
 		lpfc_send_els_event(vport, ndlp, payload);
+
+		/* If Nport discovery is delayed, reject PLOGIs */
+		if (vport->fc_flag & FC_DISC_DELAYED) {
+			rjt_err = LSRJT_UNABLE_TPC;
+			break;
+		}
 		if (vport->port_state < LPFC_DISC_AUTH) {
 			if (!(phba->pport->fc_flag & FC_PT2PT) ||
 				(phba->pport->fc_flag & FC_PT2PT_PLOGI)) {
@@ -6596,6 +6699,21 @@
 lpfc_do_scr_ns_plogi(struct lpfc_hba *phba, struct lpfc_vport *vport)
 {
 	struct lpfc_nodelist *ndlp, *ndlp_fdmi;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
+
+	/*
+	 * If lpfc_delay_discovery parameter is set and the clean address
+	 * bit is cleared and fc fabric parameters chenged, delay FC NPort
+	 * discovery.
+	 */
+	spin_lock_irq(shost->host_lock);
+	if (vport->fc_flag & FC_DISC_DELAYED) {
+		spin_unlock_irq(shost->host_lock);
+		mod_timer(&vport->delayed_disc_tmo,
+			jiffies + HZ * phba->fc_ratov);
+		return;
+	}
+	spin_unlock_irq(shost->host_lock);
 
 	ndlp = lpfc_findnode_did(vport, NameServer_DID);
 	if (!ndlp) {
@@ -6938,6 +7056,9 @@
 	struct lpfc_nodelist *next_np;
 	IOCB_t *irsp = &rspiocb->iocb;
 	struct lpfc_iocbq *piocb;
+	struct lpfc_dmabuf *pcmd = cmdiocb->context2, *prsp;
+	struct serv_parm *sp;
+	uint8_t fabric_param_changed;
 
 	lpfc_printf_vlog(vport, KERN_INFO, LOG_ELS,
 			 "0123 FDISC completes. x%x/x%x prevDID: x%x\n",
@@ -6981,7 +7102,14 @@
 
 	vport->fc_myDID = irsp->un.ulpWord[4] & Mask_DID;
 	lpfc_vport_set_state(vport, FC_VPORT_ACTIVE);
-	if ((vport->fc_prevDID != vport->fc_myDID) &&
+	prsp = list_get_first(&pcmd->list, struct lpfc_dmabuf, list);
+	sp = prsp->virt + sizeof(uint32_t);
+	fabric_param_changed = lpfc_check_clean_addr_bit(vport, sp);
+	memcpy(&vport->fabric_portname, &sp->portName,
+		sizeof(struct lpfc_name));
+	memcpy(&vport->fabric_nodename, &sp->nodeName,
+		sizeof(struct lpfc_name));
+	if (fabric_param_changed &&
 		!(vport->fc_flag & FC_VPORT_NEEDS_REG_VPI)) {
 		/* If our NportID changed, we need to ensure all
 		 * remaining NPORTs get unreg_login'ed so we can
@@ -7582,6 +7710,32 @@
 }
 
 /**
+ * lpfc_sli4_vport_delete_els_xri_aborted -Remove all ndlp references for vport
+ * @vport: pointer to lpfc vport data structure.
+ *
+ * This routine is invoked by the vport cleanup for deletions and the cleanup
+ * for an ndlp on removal.
+ **/
+void
+lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *vport)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_sglq *sglq_entry = NULL, *sglq_next = NULL;
+	unsigned long iflag = 0;
+
+	spin_lock_irqsave(&phba->hbalock, iflag);
+	spin_lock(&phba->sli4_hba.abts_sgl_list_lock);
+	list_for_each_entry_safe(sglq_entry, sglq_next,
+			&phba->sli4_hba.lpfc_abts_els_sgl_list, list) {
+		if (sglq_entry->ndlp && sglq_entry->ndlp->vport == vport)
+			sglq_entry->ndlp = NULL;
+	}
+	spin_unlock(&phba->sli4_hba.abts_sgl_list_lock);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
+	return;
+}
+
+/**
  * lpfc_sli4_els_xri_aborted - Slow-path process of els xri abort
  * @phba: pointer to lpfc hba data structure.
  * @axri: pointer to the els xri abort wcqe structure.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -325,6 +325,7 @@
 #define FC_VPORT_CVL_RCVD	0x400000 /* VLink failed due to CVL	 */
 #define FC_VFI_REGISTERED	0x800000 /* VFI is registered */
 #define FC_FDISC_COMPLETED	0x1000000/* FDISC completed */
+#define FC_DISC_DELAYED		0x2000000/* Delay NPort discovery */
 
 	uint32_t ct_flags;
 #define FC_CT_RFF_ID		0x1	 /* RFF_ID accepted by switch */
@@ -348,6 +349,8 @@
 
 	uint32_t fc_myDID;	/* fibre channel S_ID */
 	uint32_t fc_prevDID;	/* previous fibre channel S_ID */
+	struct lpfc_name fabric_portname;
+	struct lpfc_name fabric_nodename;
 
 	int32_t stopped;   /* HBA has not been restarted since last ERATT */
 	uint8_t fc_linkspeed;	/* Link speed after last READ_LA */
@@ -372,6 +375,7 @@
 #define WORKER_DISC_TMO                0x1	/* vport: Discovery timeout */
 #define WORKER_ELS_TMO                 0x2	/* vport: ELS timeout */
 #define WORKER_FDMI_TMO                0x4	/* vport: FDMI timeout */
+#define WORKER_DELAYED_DISC_TMO        0x8	/* vport: delayed discovery */
 
 #define WORKER_MBOX_TMO                0x100	/* hba: MBOX timeout */
 #define WORKER_HB_TMO                  0x200	/* hba: Heart beat timeout */
@@ -382,6 +386,7 @@
 
 	struct timer_list fc_fdmitmo;
 	struct timer_list els_tmofunc;
+	struct timer_list delayed_disc_tmo;
 
 	int unreg_vpi_cmpl;
 
@@ -534,6 +539,8 @@
 		(struct lpfc_hba *, uint32_t);
 	int (*lpfc_hba_down_link)
 		(struct lpfc_hba *, uint32_t);
+	int (*lpfc_selective_reset)
+		(struct lpfc_hba *);
 
 	/* SLI4 specific HBA data structure */
 	struct lpfc_sli4_hba sli4_hba;
@@ -548,6 +555,8 @@
 #define LPFC_SLI3_CRP_ENABLED		0x08
 #define LPFC_SLI3_BG_ENABLED		0x20
 #define LPFC_SLI3_DSS_ENABLED		0x40
+#define LPFC_SLI4_PERFH_ENABLED		0x80
+#define LPFC_SLI4_PHWQ_ENABLED		0x100
 	uint32_t iocb_cmd_size;
 	uint32_t iocb_rsp_size;
 
@@ -655,7 +664,7 @@
 #define LPFC_INITIALIZE_LINK              0	/* do normal init_link mbox */
 #define LPFC_DELAY_INIT_LINK              1	/* layered driver hold off */
 #define LPFC_DELAY_INIT_LINK_INDEFINITELY 2	/* wait, manual intervention */
-
+	uint32_t cfg_enable_dss;
 	lpfc_vpd_t vpd;		/* vital product data */
 
 	struct pci_dev *pcidev;
@@ -792,6 +801,10 @@
 	struct dentry *debug_slow_ring_trc;
 	struct lpfc_debugfs_trc *slow_ring_trc;
 	atomic_t slow_ring_trc_cnt;
+	/* iDiag debugfs sub-directory */
+	struct dentry *idiag_root;
+	struct dentry *idiag_pci_cfg;
+	struct dentry *idiag_que_info;
 #endif
 
 	/* Used for deferred freeing of ELS data buffers */
@@ -884,7 +897,18 @@
 	return;
 }
 
-static inline void
+static inline int
+lpfc_readl(void __iomem *addr, uint32_t *data)
+{
+	uint32_t temp;
+	temp = readl(addr);
+	if (temp == 0xffffffff)
+		return -EIO;
+	*data = temp;
+	return 0;
+}
+
+static inline int
 lpfc_sli_read_hs(struct lpfc_hba *phba)
 {
 	/*
@@ -893,15 +917,17 @@
 	 */
 	phba->sli.slistat.err_attn_event++;
 
-	/* Save status info */
-	phba->work_hs = readl(phba->HSregaddr);
-	phba->work_status[0] = readl(phba->MBslimaddr + 0xa8);
-	phba->work_status[1] = readl(phba->MBslimaddr + 0xac);
+	/* Save status info and check for unplug error */
+	if (lpfc_readl(phba->HSregaddr, &phba->work_hs) ||
+		lpfc_readl(phba->MBslimaddr + 0xa8, &phba->work_status[0]) ||
+		lpfc_readl(phba->MBslimaddr + 0xac, &phba->work_status[1])) {
+		return -EIO;
+	}
 
 	/* Clear chip Host Attention error bit */
 	writel(HA_ERATT, phba->HAregaddr);
 	readl(phba->HAregaddr); /* flush */
 	phba->pport->stopped = 1;
 
-	return;
+	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_hbadisc.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_hbadisc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_hbadisc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_hbadisc.c	2011-05-19 00:06:34.000000000 -0400
@@ -658,6 +658,8 @@
 				lpfc_ramp_down_queue_handler(phba);
 			if (work_port_events & WORKER_RAMP_UP_QUEUE)
 				lpfc_ramp_up_queue_handler(phba);
+			if (work_port_events & WORKER_DELAYED_DISC_TMO)
+				lpfc_delayed_disc_timeout_handler(vport);
 		}
 	lpfc_destroy_vport_work_array(phba, vports);
 
@@ -737,7 +739,7 @@
 
 /*
  * This is only called to handle FC worker events. Since this a rare
- * occurance, we allocate a struct lpfc_work_evt structure here instead of
+ * occurrence, we allocate a struct lpfc_work_evt structure here instead of
  * embedding it in the IOCB.
  */
 int
@@ -838,6 +840,11 @@
 
 	lpfc_port_link_failure(vport);
 
+	/* Stop delayed Nport discovery */
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag &= ~FC_DISC_DELAYED;
+	spin_unlock_irq(shost->host_lock);
+	del_timer_sync(&vport->delayed_disc_tmo);
 }
 
 int
@@ -1341,7 +1348,7 @@
 	int rc;
 
 	spin_lock_irq(&phba->hbalock);
-	/* If the FCF is not availabe do nothing. */
+	/* If the FCF is not available do nothing. */
 	if (!(phba->fcf.fcf_flag & FCF_AVAILABLE)) {
 		phba->hba_flag &= ~(FCF_TS_INPROG | FCF_RR_INPROG);
 		spin_unlock_irq(&phba->hbalock);
@@ -1531,7 +1538,7 @@
 
 		/*
 		 * If user did not specify any addressing mode, or if the
-		 * prefered addressing mode specified by user is not supported
+		 * preferred addressing mode specified by user is not supported
 		 * by FCF, allow fabric to pick the addressing mode.
 		 */
 		*addr_mode = bf_get(lpfc_fcf_record_mac_addr_prov,
@@ -1546,7 +1553,7 @@
 				FCFCNCT_AM_SPMA) ?
 				LPFC_FCF_SPMA : LPFC_FCF_FPMA;
 		/*
-		 * If the user specified a prefered address mode, use the
+		 * If the user specified a preferred address mode, use the
 		 * addr mode only if FCF support the addr_mode.
 		 */
 		else if ((conn_entry->conn_rec.flags & FCFCNCT_AM_VALID) &&
@@ -3110,7 +3117,7 @@
 		 * back at reg login state so this
 		 * mbox needs to be ignored becase
 		 * there is another reg login in
-		 * proccess.
+		 * process.
 		 */
 		spin_lock_irq(shost->host_lock);
 		ndlp->nlp_flag &= ~NLP_IGNR_REG_CMPL;
@@ -3160,7 +3167,7 @@
 	spin_unlock_irq(shost->host_lock);
 	vport->unreg_vpi_cmpl = VPORT_OK;
 	mempool_free(pmb, phba->mbox_mem_pool);
-	lpfc_cleanup_vports_rrqs(vport);
+	lpfc_cleanup_vports_rrqs(vport, NULL);
 	/*
 	 * This shost reference might have been taken at the beginning of
 	 * lpfc_vport_delete()
@@ -3900,6 +3907,8 @@
 	if (ndlp->nlp_state == NLP_STE_UNUSED_NODE)
 		return;
 	lpfc_nlp_set_state(vport, ndlp, NLP_STE_UNUSED_NODE);
+	if (vport->phba->sli_rev == LPFC_SLI_REV4)
+		lpfc_cleanup_vports_rrqs(vport, ndlp);
 	lpfc_nlp_put(ndlp);
 	return;
 }
@@ -4289,7 +4298,7 @@
 
 	list_del_init(&ndlp->els_retry_evt.evt_listp);
 	list_del_init(&ndlp->dev_loss_evt.evt_listp);
-
+	lpfc_cleanup_vports_rrqs(vport, ndlp);
 	lpfc_unreg_rpi(vport, ndlp);
 
 	return 0;
@@ -4426,10 +4435,11 @@
 {
 	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 	struct lpfc_nodelist *ndlp;
+	unsigned long iflags;
 
-	spin_lock_irq(shost->host_lock);
+	spin_lock_irqsave(shost->host_lock, iflags);
 	ndlp = __lpfc_findnode_did(vport, did);
-	spin_unlock_irq(shost->host_lock);
+	spin_unlock_irqrestore(shost->host_lock, iflags);
 	return ndlp;
 }
 
@@ -4467,7 +4477,7 @@
 	if ((vport->fc_flag & FC_RSCN_MODE) &&
 	    !(vport->fc_flag & FC_NDISC_ACTIVE)) {
 		if (lpfc_rscn_payload_check(vport, did)) {
-			/* If we've already recieved a PLOGI from this NPort
+			/* If we've already received a PLOGI from this NPort
 			 * we don't need to try to discover it again.
 			 */
 			if (ndlp->nlp_flag & NLP_RCV_PLOGI)
@@ -4483,7 +4493,7 @@
 		} else
 			ndlp = NULL;
 	} else {
-		/* If we've already recieved a PLOGI from this NPort,
+		/* If we've already received a PLOGI from this NPort,
 		 * or we are already in the process of discovery on it,
 		 * we don't need to try to discover it again.
 		 */
@@ -5746,7 +5756,7 @@
  * @size: Size of the data buffer.
  * @rec_type: Record type to be searched.
  *
- * This function searches config region data to find the begining
+ * This function searches config region data to find the beginning
  * of the record specified by record_type. If record found, this
  * function return pointer to the record else return NULL.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_hw4.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_hw4.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_hw4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_hw4.h	2011-05-19 00:06:34.000000000 -0400
@@ -215,7 +215,7 @@
 #define lpfc_fip_flag_WORD word0
 };
 
-struct sli4_bls_acc {
+struct sli4_bls_rsp {
 	uint32_t word0_rsvd;      /* Word0 must be reserved */
 	uint32_t word1;
 #define lpfc_abts_orig_SHIFT      0
@@ -231,6 +231,16 @@
 #define lpfc_abts_oxid_MASK       0x0000FFFF
 #define lpfc_abts_oxid_WORD       word2
 	uint32_t word3;
+#define lpfc_vndr_code_SHIFT	0
+#define lpfc_vndr_code_MASK	0x000000FF
+#define lpfc_vndr_code_WORD	word3
+#define lpfc_rsn_expln_SHIFT	8
+#define lpfc_rsn_expln_MASK	0x000000FF
+#define lpfc_rsn_expln_WORD	word3
+#define lpfc_rsn_code_SHIFT	16
+#define lpfc_rsn_code_MASK	0x000000FF
+#define lpfc_rsn_code_WORD	word3
+
 	uint32_t word4;
 	uint32_t word5_rsvd;	/* Word5 must be reserved */
 };
@@ -711,21 +721,27 @@
 union lpfc_sli4_cfg_shdr {
 	struct {
 		uint32_t word6;
-#define lpfc_mbox_hdr_opcode_SHIFT		0
-#define lpfc_mbox_hdr_opcode_MASK		0x000000FF
-#define lpfc_mbox_hdr_opcode_WORD		word6
-#define lpfc_mbox_hdr_subsystem_SHIFT		8
-#define lpfc_mbox_hdr_subsystem_MASK		0x000000FF
-#define lpfc_mbox_hdr_subsystem_WORD		word6
-#define lpfc_mbox_hdr_port_number_SHIFT		16
-#define lpfc_mbox_hdr_port_number_MASK		0x000000FF
-#define lpfc_mbox_hdr_port_number_WORD		word6
-#define lpfc_mbox_hdr_domain_SHIFT		24
-#define lpfc_mbox_hdr_domain_MASK		0x000000FF
-#define lpfc_mbox_hdr_domain_WORD		word6
+#define lpfc_mbox_hdr_opcode_SHIFT	0
+#define lpfc_mbox_hdr_opcode_MASK	0x000000FF
+#define lpfc_mbox_hdr_opcode_WORD	word6
+#define lpfc_mbox_hdr_subsystem_SHIFT	8
+#define lpfc_mbox_hdr_subsystem_MASK	0x000000FF
+#define lpfc_mbox_hdr_subsystem_WORD	word6
+#define lpfc_mbox_hdr_port_number_SHIFT	16
+#define lpfc_mbox_hdr_port_number_MASK	0x000000FF
+#define lpfc_mbox_hdr_port_number_WORD	word6
+#define lpfc_mbox_hdr_domain_SHIFT	24
+#define lpfc_mbox_hdr_domain_MASK	0x000000FF
+#define lpfc_mbox_hdr_domain_WORD	word6
 		uint32_t timeout;
 		uint32_t request_length;
-		uint32_t reserved9;
+		uint32_t word9;
+#define lpfc_mbox_hdr_version_SHIFT	0
+#define lpfc_mbox_hdr_version_MASK	0x000000FF
+#define lpfc_mbox_hdr_version_WORD	word9
+#define LPFC_Q_CREATE_VERSION_2	2
+#define LPFC_Q_CREATE_VERSION_1	1
+#define LPFC_Q_CREATE_VERSION_0	0
 	} request;
 	struct {
 		uint32_t word6;
@@ -778,6 +794,7 @@
 #define LPFC_MBOX_OPCODE_QUERY_FW_CFG		0x3A
 #define LPFC_MBOX_OPCODE_FUNCTION_RESET		0x3D
 #define LPFC_MBOX_OPCODE_MQ_CREATE_EXT		0x5A
+#define LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS	0xB5
 
 /* FCoE Opcodes */
 #define LPFC_MBOX_OPCODE_FCOE_WQ_CREATE			0x01
@@ -916,9 +933,12 @@
 #define LPFC_CQ_CNT_512		0x1
 #define LPFC_CQ_CNT_1024	0x2
 	uint32_t word1;
-#define lpfc_cq_eq_id_SHIFT		22
+#define lpfc_cq_eq_id_SHIFT		22	/* Version 0 Only */
 #define lpfc_cq_eq_id_MASK		0x000000FF
 #define lpfc_cq_eq_id_WORD		word1
+#define lpfc_cq_eq_id_2_SHIFT		0 	/* Version 2 Only */
+#define lpfc_cq_eq_id_2_MASK		0x0000FFFF
+#define lpfc_cq_eq_id_2_WORD		word1
 	uint32_t reserved0;
 	uint32_t reserved1;
 };
@@ -928,6 +948,9 @@
 	union {
 		struct {
 			uint32_t word0;
+#define lpfc_mbx_cq_create_page_size_SHIFT	16	/* Version 2 Only */
+#define lpfc_mbx_cq_create_page_size_MASK	0x000000FF
+#define lpfc_mbx_cq_create_page_size_WORD	word0
 #define lpfc_mbx_cq_create_num_pages_SHIFT	0
 #define lpfc_mbx_cq_create_num_pages_MASK	0x0000FFFF
 #define lpfc_mbx_cq_create_num_pages_WORD	word0
@@ -968,7 +991,7 @@
 struct lpfc_mbx_wq_create {
 	struct mbox_header header;
 	union {
-		struct {
+		struct {	/* Version 0 Request */
 			uint32_t word0;
 #define lpfc_mbx_wq_create_num_pages_SHIFT	0
 #define lpfc_mbx_wq_create_num_pages_MASK	0x0000FFFF
@@ -978,6 +1001,23 @@
 #define lpfc_mbx_wq_create_cq_id_WORD		word0
 			struct dma_address page[LPFC_MAX_WQ_PAGE];
 		} request;
+		struct {	/* Version 1 Request */
+			uint32_t word0;	/* Word 0 is the same as in v0 */
+			uint32_t word1;
+#define lpfc_mbx_wq_create_page_size_SHIFT	0
+#define lpfc_mbx_wq_create_page_size_MASK	0x000000FF
+#define lpfc_mbx_wq_create_page_size_WORD	word1
+#define lpfc_mbx_wq_create_wqe_size_SHIFT	8
+#define lpfc_mbx_wq_create_wqe_size_MASK	0x0000000F
+#define lpfc_mbx_wq_create_wqe_size_WORD	word1
+#define LPFC_WQ_WQE_SIZE_64	0x5
+#define LPFC_WQ_WQE_SIZE_128	0x6
+#define lpfc_mbx_wq_create_wqe_count_SHIFT	16
+#define lpfc_mbx_wq_create_wqe_count_MASK	0x0000FFFF
+#define lpfc_mbx_wq_create_wqe_count_WORD	word1
+			uint32_t word2;
+			struct dma_address page[LPFC_MAX_WQ_PAGE-1];
+		} request_1;
 		struct {
 			uint32_t word0;
 #define lpfc_mbx_wq_create_q_id_SHIFT	0
@@ -1006,13 +1046,22 @@
 #define LPFC_DATA_BUF_SIZE 2048
 struct rq_context {
 	uint32_t word0;
-#define lpfc_rq_context_rq_size_SHIFT	16
-#define lpfc_rq_context_rq_size_MASK	0x0000000F
-#define lpfc_rq_context_rq_size_WORD	word0
+#define lpfc_rq_context_rqe_count_SHIFT	16	/* Version 0 Only */
+#define lpfc_rq_context_rqe_count_MASK	0x0000000F
+#define lpfc_rq_context_rqe_count_WORD	word0
 #define LPFC_RQ_RING_SIZE_512		9	/* 512 entries */
 #define LPFC_RQ_RING_SIZE_1024		10	/* 1024 entries */
 #define LPFC_RQ_RING_SIZE_2048		11	/* 2048 entries */
 #define LPFC_RQ_RING_SIZE_4096		12	/* 4096 entries */
+#define lpfc_rq_context_rqe_count_1_SHIFT	16	/* Version 1 Only */
+#define lpfc_rq_context_rqe_count_1_MASK	0x0000FFFF
+#define lpfc_rq_context_rqe_count_1_WORD	word0
+#define lpfc_rq_context_rqe_size_SHIFT	8		/* Version 1 Only */
+#define lpfc_rq_context_rqe_size_MASK	0x0000000F
+#define lpfc_rq_context_rqe_size_WORD	word0
+#define lpfc_rq_context_page_size_SHIFT	0		/* Version 1 Only */
+#define lpfc_rq_context_page_size_MASK	0x000000FF
+#define lpfc_rq_context_page_size_WORD	word0
 	uint32_t reserved1;
 	uint32_t word2;
 #define lpfc_rq_context_cq_id_SHIFT	16
@@ -1021,7 +1070,7 @@
 #define lpfc_rq_context_buf_size_SHIFT	0
 #define lpfc_rq_context_buf_size_MASK	0x0000FFFF
 #define lpfc_rq_context_buf_size_WORD	word2
-	uint32_t reserved3;
+	uint32_t buffer_size;				/* Version 1 Only */
 };
 
 struct lpfc_mbx_rq_create {
@@ -1061,16 +1110,16 @@
 
 struct mq_context {
 	uint32_t word0;
-#define lpfc_mq_context_cq_id_SHIFT	22
+#define lpfc_mq_context_cq_id_SHIFT	22 	/* Version 0 Only */
 #define lpfc_mq_context_cq_id_MASK	0x000003FF
 #define lpfc_mq_context_cq_id_WORD	word0
-#define lpfc_mq_context_count_SHIFT	16
-#define lpfc_mq_context_count_MASK	0x0000000F
-#define lpfc_mq_context_count_WORD	word0
-#define LPFC_MQ_CNT_16		0x5
-#define LPFC_MQ_CNT_32		0x6
-#define LPFC_MQ_CNT_64		0x7
-#define LPFC_MQ_CNT_128		0x8
+#define lpfc_mq_context_ring_size_SHIFT	16
+#define lpfc_mq_context_ring_size_MASK	0x0000000F
+#define lpfc_mq_context_ring_size_WORD	word0
+#define LPFC_MQ_RING_SIZE_16		0x5
+#define LPFC_MQ_RING_SIZE_32		0x6
+#define LPFC_MQ_RING_SIZE_64		0x7
+#define LPFC_MQ_RING_SIZE_128		0x8
 	uint32_t word1;
 #define lpfc_mq_context_valid_SHIFT	31
 #define lpfc_mq_context_valid_MASK	0x00000001
@@ -1104,9 +1153,12 @@
 	union {
 		struct {
 			uint32_t word0;
-#define lpfc_mbx_mq_create_ext_num_pages_SHIFT		0
-#define lpfc_mbx_mq_create_ext_num_pages_MASK		0x0000FFFF
-#define lpfc_mbx_mq_create_ext_num_pages_WORD		word0
+#define lpfc_mbx_mq_create_ext_num_pages_SHIFT	0
+#define lpfc_mbx_mq_create_ext_num_pages_MASK	0x0000FFFF
+#define lpfc_mbx_mq_create_ext_num_pages_WORD	word0
+#define lpfc_mbx_mq_create_ext_cq_id_SHIFT	16	/* Version 1 Only */
+#define lpfc_mbx_mq_create_ext_cq_id_MASK	0x0000FFFF
+#define lpfc_mbx_mq_create_ext_cq_id_WORD	word0
 			uint32_t async_evt_bmap;
 #define lpfc_mbx_mq_create_ext_async_evt_link_SHIFT	LPFC_TRAILER_CODE_LINK
 #define lpfc_mbx_mq_create_ext_async_evt_link_MASK	0x00000001
@@ -1852,6 +1904,9 @@
 #define lpfc_mbx_rq_ftr_rq_ifip_SHIFT		7
 #define lpfc_mbx_rq_ftr_rq_ifip_MASK		0x00000001
 #define lpfc_mbx_rq_ftr_rq_ifip_WORD		word2
+#define lpfc_mbx_rq_ftr_rq_perfh_SHIFT		11
+#define lpfc_mbx_rq_ftr_rq_perfh_MASK		0x00000001
+#define lpfc_mbx_rq_ftr_rq_perfh_WORD		word2
 	uint32_t word3;
 #define lpfc_mbx_rq_ftr_rsp_iaab_SHIFT		0
 #define lpfc_mbx_rq_ftr_rsp_iaab_MASK		0x00000001
@@ -1877,6 +1932,9 @@
 #define lpfc_mbx_rq_ftr_rsp_ifip_SHIFT		7
 #define lpfc_mbx_rq_ftr_rsp_ifip_MASK		0x00000001
 #define lpfc_mbx_rq_ftr_rsp_ifip_WORD		word3
+#define lpfc_mbx_rq_ftr_rsp_perfh_SHIFT		11
+#define lpfc_mbx_rq_ftr_rsp_perfh_MASK		0x00000001
+#define lpfc_mbx_rq_ftr_rsp_perfh_WORD		word3
 };
 
 struct lpfc_mbx_supp_pages {
@@ -1935,7 +1993,7 @@
 #define LPFC_SLI4_PARAMETERS		2
 };
 
-struct lpfc_mbx_sli4_params {
+struct lpfc_mbx_pc_sli4_params {
 	uint32_t word1;
 #define qs_SHIFT				0
 #define qs_MASK					0x00000001
@@ -2051,6 +2109,88 @@
 	uint32_t rsvd_13_63[51];
 };
 
+struct lpfc_sli4_parameters {
+	uint32_t word0;
+#define cfg_prot_type_SHIFT			0
+#define cfg_prot_type_MASK			0x000000FF
+#define cfg_prot_type_WORD			word0
+	uint32_t word1;
+#define cfg_ft_SHIFT				0
+#define cfg_ft_MASK				0x00000001
+#define cfg_ft_WORD				word1
+#define cfg_sli_rev_SHIFT			4
+#define cfg_sli_rev_MASK			0x0000000f
+#define cfg_sli_rev_WORD			word1
+#define cfg_sli_family_SHIFT			8
+#define cfg_sli_family_MASK			0x0000000f
+#define cfg_sli_family_WORD			word1
+#define cfg_if_type_SHIFT			12
+#define cfg_if_type_MASK			0x0000000f
+#define cfg_if_type_WORD			word1
+#define cfg_sli_hint_1_SHIFT			16
+#define cfg_sli_hint_1_MASK			0x000000ff
+#define cfg_sli_hint_1_WORD			word1
+#define cfg_sli_hint_2_SHIFT			24
+#define cfg_sli_hint_2_MASK			0x0000001f
+#define cfg_sli_hint_2_WORD			word1
+	uint32_t word2;
+	uint32_t word3;
+	uint32_t word4;
+#define cfg_cqv_SHIFT				14
+#define cfg_cqv_MASK				0x00000003
+#define cfg_cqv_WORD				word4
+	uint32_t word5;
+	uint32_t word6;
+#define cfg_mqv_SHIFT				14
+#define cfg_mqv_MASK				0x00000003
+#define cfg_mqv_WORD				word6
+	uint32_t word7;
+	uint32_t word8;
+#define cfg_wqv_SHIFT				14
+#define cfg_wqv_MASK				0x00000003
+#define cfg_wqv_WORD				word8
+	uint32_t word9;
+	uint32_t word10;
+#define cfg_rqv_SHIFT				14
+#define cfg_rqv_MASK				0x00000003
+#define cfg_rqv_WORD				word10
+	uint32_t word11;
+#define cfg_rq_db_window_SHIFT			28
+#define cfg_rq_db_window_MASK			0x0000000f
+#define cfg_rq_db_window_WORD			word11
+	uint32_t word12;
+#define cfg_fcoe_SHIFT				0
+#define cfg_fcoe_MASK				0x00000001
+#define cfg_fcoe_WORD				word12
+#define cfg_phwq_SHIFT				15
+#define cfg_phwq_MASK				0x00000001
+#define cfg_phwq_WORD				word12
+#define cfg_loopbk_scope_SHIFT			28
+#define cfg_loopbk_scope_MASK			0x0000000f
+#define cfg_loopbk_scope_WORD			word12
+	uint32_t sge_supp_len;
+	uint32_t word14;
+#define cfg_sgl_page_cnt_SHIFT			0
+#define cfg_sgl_page_cnt_MASK			0x0000000f
+#define cfg_sgl_page_cnt_WORD			word14
+#define cfg_sgl_page_size_SHIFT			8
+#define cfg_sgl_page_size_MASK			0x000000ff
+#define cfg_sgl_page_size_WORD			word14
+#define cfg_sgl_pp_align_SHIFT			16
+#define cfg_sgl_pp_align_MASK			0x000000ff
+#define cfg_sgl_pp_align_WORD			word14
+	uint32_t word15;
+	uint32_t word16;
+	uint32_t word17;
+	uint32_t word18;
+	uint32_t word19;
+};
+
+struct lpfc_mbx_get_sli4_parameters {
+	struct mbox_header header;
+	struct lpfc_sli4_parameters sli4_parameters;
+};
+
 /* Mailbox Completion Queue Error Messages */
 #define MB_CQE_STATUS_SUCCESS 			0x0
 #define MB_CQE_STATUS_INSUFFICIENT_PRIVILEGES	0x1
@@ -2103,7 +2243,8 @@
 		struct lpfc_mbx_post_hdr_tmpl hdr_tmpl;
 		struct lpfc_mbx_query_fw_cfg query_fw_cfg;
 		struct lpfc_mbx_supp_pages supp_pages;
-		struct lpfc_mbx_sli4_params sli4_params;
+		struct lpfc_mbx_pc_sli4_params sli4_params;
+		struct lpfc_mbx_get_sli4_parameters get_sli4_parameters;
 		struct lpfc_mbx_nop nop;
 	} un;
 };
@@ -2381,6 +2522,10 @@
 #define wqe_wqes_SHIFT        15
 #define wqe_wqes_MASK         0x00000001
 #define wqe_wqes_WORD         word10
+/* Note that this field overlaps above fields */
+#define wqe_wqid_SHIFT        1
+#define wqe_wqid_MASK         0x0000007f
+#define wqe_wqid_WORD         word10
 #define wqe_pri_SHIFT         16
 #define wqe_pri_MASK          0x00000007
 #define wqe_pri_WORD          word10
@@ -2599,7 +2744,8 @@
 	uint32_t total_xfer_len;
 	uint32_t initial_xfer_len;
 	struct wqe_common wqe_com;     /* words 6-11 */
-	uint32_t rsvd_12_15[4];         /* word 12-15 */
+	uint32_t rsrvd12;
+	struct ulp_bde64 ph_bde;       /* words 13-15 */
 };
 
 struct fcp_iread64_wqe {
@@ -2608,7 +2754,8 @@
 	uint32_t total_xfer_len;       /* word 4 */
 	uint32_t rsrvd5;               /* word 5 */
 	struct wqe_common wqe_com;     /* words 6-11 */
-	uint32_t rsvd_12_15[4];         /* word 12-15 */
+	uint32_t rsrvd12;
+	struct ulp_bde64 ph_bde;       /* words 13-15 */
 };
 
 struct fcp_icmnd64_wqe {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_hw.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_hw.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_hw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_hw.h	2011-05-19 00:06:34.000000000 -0400
@@ -341,6 +341,12 @@
 	uint8_t bbCreditMsb;
 	uint8_t bbCreditlsb;	/* FC Word 0, byte 3 */
 
+/*
+ * Word 1 Bit 31 in common service parameter is overloaded.
+ * Word 1 Bit 31 in FLOGI request is multiple NPort request
+ * Word 1 Bit 31 in FLOGI response is clean address bit
+ */
+#define clean_address_bit request_multiple_Nport /* Word 1, bit 31 */
 #ifdef __BIG_ENDIAN_BITFIELD
 	uint16_t request_multiple_Nport:1;	/* FC Word 1, bit 31 */
 	uint16_t randomOffset:1;	/* FC Word 1, bit 30 */
@@ -1338,7 +1344,7 @@
 #define HS_FFER1       0x80000000	/* Bit 31 */
 #define HS_CRIT_TEMP   0x00000100	/* Bit 8  */
 #define HS_FFERM       0xFF000100	/* Mask for error bits 31:24 and 8 */
-
+#define UNPLUG_ERR     0x00000001	/* Indicate pci hot unplug */
 /* Host Control Register */
 
 #define HC_REG_OFFSET  12	/* Byte offset from register base address */
@@ -1707,6 +1713,17 @@
 #define pde6_apptagval_WORD	word2
 };
 
+struct lpfc_pde7 {
+	uint32_t word0;
+#define pde7_type_SHIFT		24
+#define pde7_type_MASK		0x000000ff
+#define pde7_type_WORD		word0
+#define pde7_rsvd0_SHIFT	0
+#define pde7_rsvd0_MASK		0x00ffffff
+#define pde7_rsvd0_WORD		word0
+	uint32_t addrHigh;
+	uint32_t addrLow;
+};
 
 /* Structure for MB Command LOAD_SM and DOWN_LOAD */
 
@@ -3198,7 +3215,10 @@
 #define IOERR_SLER_RRQ_RJT_ERR        0x4C
 #define IOERR_SLER_RRQ_RETRY_ERR      0x4D
 #define IOERR_SLER_ABTS_ERR           0x4E
-
+#define IOERR_ELXSEC_KEY_UNWRAP_ERROR		0xF0
+#define IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR	0xF1
+#define IOERR_ELXSEC_CRYPTO_ERROR		0xF2
+#define IOERR_ELXSEC_CRYPTO_COMPARE_ERROR	0xF3
 #define IOERR_DRVR_MASK               0x100
 #define IOERR_SLI_DOWN                0x101  /* ulpStatus  - Driver defined */
 #define IOERR_SLI_BRESET              0x102
@@ -3612,7 +3632,7 @@
 		ASYNCSTAT_FIELDS asyncstat; /* async_status iocb */
 		QUE_XRI64_CX_FIELDS quexri64cx; /* que_xri64_cx fields */
 		struct rcv_seq64 rcvseq64;	/* RCV_SEQ64 and RCV_CONT64 */
-		struct sli4_bls_acc bls_acc; /* UNSOL ABTS BLS_ACC params */
+		struct sli4_bls_rsp bls_rsp; /* UNSOL ABTS BLS_RSP params */
 		uint32_t ulpWord[IOCB_WORD_SZ - 2];	/* generic 6 'words' */
 	} un;
 	union {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_init.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -460,7 +460,7 @@
 	    || ((phba->cfg_link_speed == LPFC_USER_LINK_SPEED_16G)
 		&& !(phba->lmt & LMT_16Gb))) {
 		/* Reset link speed to auto */
-		lpfc_printf_log(phba, KERN_WARNING, LOG_LINK_EVENT,
+		lpfc_printf_log(phba, KERN_ERR, LOG_LINK_EVENT,
 			"1302 Invalid speed for this board: "
 			"Reset link speed to auto: x%x\n",
 			phba->cfg_link_speed);
@@ -507,7 +507,10 @@
 	phba->hba_flag &= ~HBA_ERATT_HANDLED;
 
 	/* Enable appropriate host interrupts */
-	status = readl(phba->HCregaddr);
+	if (lpfc_readl(phba->HCregaddr, &status)) {
+		spin_unlock_irq(&phba->hbalock);
+		return -EIO;
+	}
 	status |= HC_MBINT_ENA | HC_ERINT_ENA | HC_LAINT_ENA;
 	if (psli->num_rings > 0)
 		status |= HC_R0INT_ENA;
@@ -945,17 +948,13 @@
 lpfc_rrq_timeout(unsigned long ptr)
 {
 	struct lpfc_hba *phba;
-	uint32_t tmo_posted;
 	unsigned long iflag;
 
 	phba = (struct lpfc_hba *)ptr;
 	spin_lock_irqsave(&phba->pport->work_port_lock, iflag);
-	tmo_posted = phba->hba_flag & HBA_RRQ_ACTIVE;
-	if (!tmo_posted)
-		phba->hba_flag |= HBA_RRQ_ACTIVE;
+	phba->hba_flag |= HBA_RRQ_ACTIVE;
 	spin_unlock_irqrestore(&phba->pport->work_port_lock, iflag);
-	if (!tmo_posted)
-		lpfc_worker_wake_up(phba);
+	lpfc_worker_wake_up(phba);
 }
 
 /**
@@ -1226,7 +1225,10 @@
 	/* Wait for the ER1 bit to clear.*/
 	while (phba->work_hs & HS_FFER1) {
 		msleep(100);
-		phba->work_hs = readl(phba->HSregaddr);
+		if (lpfc_readl(phba->HSregaddr, &phba->work_hs)) {
+			phba->work_hs = UNPLUG_ERR ;
+			break;
+		}
 		/* If driver is unloading let the worker thread continue */
 		if (phba->pport->load_flag & FC_UNLOADING) {
 			phba->work_hs = 0;
@@ -2280,6 +2282,7 @@
 		/* Wait for any activity on ndlps to settle */
 		msleep(10);
 	}
+	lpfc_cleanup_vports_rrqs(vport, NULL);
 }
 
 /**
@@ -2295,6 +2298,7 @@
 {
 	del_timer_sync(&vport->els_tmofunc);
 	del_timer_sync(&vport->fc_fdmitmo);
+	del_timer_sync(&vport->delayed_disc_tmo);
 	lpfc_can_disctmo(vport);
 	return;
 }
@@ -2355,6 +2359,10 @@
 	del_timer_sync(&phba->fabric_block_timer);
 	del_timer_sync(&phba->eratt_poll);
 	del_timer_sync(&phba->hb_tmofunc);
+	if (phba->sli_rev == LPFC_SLI_REV4) {
+		del_timer_sync(&phba->rrq_tmr);
+		phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+	}
 	phba->hb_outstanding = 0;
 
 	switch (phba->pci_dev_grp) {
@@ -2732,6 +2740,11 @@
 	init_timer(&vport->els_tmofunc);
 	vport->els_tmofunc.function = lpfc_els_timeout;
 	vport->els_tmofunc.data = (unsigned long)vport;
+
+	init_timer(&vport->delayed_disc_tmo);
+	vport->delayed_disc_tmo.function = lpfc_delayed_disc_tmo;
+	vport->delayed_disc_tmo.data = (unsigned long)vport;
+
 	error = scsi_add_host_with_dma(shost, dev, &phba->pcidev->dev);
 	if (error)
 		goto out_put_shost;
@@ -4283,36 +4296,37 @@
 		goto out_free_bsmbx;
 	}
 
-	/* Get the Supported Pages. It is always available. */
+	/* Get the Supported Pages if PORT_CAPABILITIES is supported by port. */
 	lpfc_supported_pages(mboxq);
 	rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
-	if (unlikely(rc)) {
-		rc = -EIO;
-		mempool_free(mboxq, phba->mbox_mem_pool);
-		goto out_free_bsmbx;
-	}
-
-	mqe = &mboxq->u.mqe;
-	memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3),
-	       LPFC_MAX_SUPPORTED_PAGES);
-	for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) {
-		switch (pn_page[i]) {
-		case LPFC_SLI4_PARAMETERS:
-			phba->sli4_hba.pc_sli4_params.supported = 1;
-			break;
-		default:
-			break;
+	if (!rc) {
+		mqe = &mboxq->u.mqe;
+		memcpy(&pn_page[0], ((uint8_t *)&mqe->un.supp_pages.word3),
+		       LPFC_MAX_SUPPORTED_PAGES);
+		for (i = 0; i < LPFC_MAX_SUPPORTED_PAGES; i++) {
+			switch (pn_page[i]) {
+			case LPFC_SLI4_PARAMETERS:
+				phba->sli4_hba.pc_sli4_params.supported = 1;
+				break;
+			default:
+				break;
+			}
+		}
+		/* Read the port's SLI4 Parameters capabilities if supported. */
+		if (phba->sli4_hba.pc_sli4_params.supported)
+			rc = lpfc_pc_sli4_params_get(phba, mboxq);
+		if (rc) {
+			mempool_free(mboxq, phba->mbox_mem_pool);
+			rc = -EIO;
+			goto out_free_bsmbx;
 		}
 	}
-
-	/* Read the port's SLI4 Parameters capabilities if supported. */
-	if (phba->sli4_hba.pc_sli4_params.supported)
-		rc = lpfc_pc_sli4_params_get(phba, mboxq);
+	/*
+	 * Get sli4 parameters that override parameters from Port capabilities.
+	 * If this call fails it is not a critical error so continue loading.
+	 */
+	lpfc_get_sli4_parameters(phba, mboxq);
 	mempool_free(mboxq, phba->mbox_mem_pool);
-	if (rc) {
-		rc = -EIO;
-		goto out_free_bsmbx;
-	}
 	/* Create all the SLI4 queues */
 	rc = lpfc_sli4_queue_create(phba);
 	if (rc)
@@ -4452,7 +4466,7 @@
 }
 
 /**
- * lpfc_init_api_table_setup - Set up init api fucntion jump table
+ * lpfc_init_api_table_setup - Set up init api function jump table
  * @phba: The hba struct for which this call is being executed.
  * @dev_grp: The HBA PCI-Device group number.
  *
@@ -4466,6 +4480,7 @@
 {
 	phba->lpfc_hba_init_link = lpfc_hba_init_link;
 	phba->lpfc_hba_down_link = lpfc_hba_down_link;
+	phba->lpfc_selective_reset = lpfc_selective_reset;
 	switch (dev_grp) {
 	case LPFC_PCI_DEV_LP:
 		phba->lpfc_hba_down_post = lpfc_hba_down_post_s3;
@@ -4835,7 +4850,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	-ENOMEM - No availble memory
+ * 	-ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 int
@@ -5377,13 +5392,16 @@
 	int i, port_error = 0;
 	uint32_t if_type;
 
+	memset(&portsmphr_reg, 0, sizeof(portsmphr_reg));
+	memset(&reg_data, 0, sizeof(reg_data));
 	if (!phba->sli4_hba.PSMPHRregaddr)
 		return -ENODEV;
 
 	/* Wait up to 30 seconds for the SLI Port POST done and ready */
 	for (i = 0; i < 3000; i++) {
-		portsmphr_reg.word0 = readl(phba->sli4_hba.PSMPHRregaddr);
-		if (bf_get(lpfc_port_smphr_perr, &portsmphr_reg)) {
+		if (lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
+			&portsmphr_reg.word0) ||
+			(bf_get(lpfc_port_smphr_perr, &portsmphr_reg))) {
 			/* Port has a fatal POST error, break out */
 			port_error = -ENODEV;
 			break;
@@ -5464,9 +5482,9 @@
 			break;
 		case LPFC_SLI_INTF_IF_TYPE_2:
 			/* Final checks.  The port status should be clean. */
-			reg_data.word0 =
-				readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
-			if (bf_get(lpfc_sliport_status_err, &reg_data)) {
+			if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+				&reg_data.word0) ||
+				bf_get(lpfc_sliport_status_err, &reg_data)) {
 				phba->work_status[0] =
 					readl(phba->sli4_hba.u.if_type2.
 					      ERR1regaddr);
@@ -5712,7 +5730,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	-ENOMEM - No availble memory
+ * 	-ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
@@ -5817,7 +5835,7 @@
  *
  * Return codes
  * 	0 - successful
- * 	-ENOMEM - No availble memory
+ * 	-ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
@@ -5876,7 +5894,7 @@
  *
  * Return codes
  *      0 - successful
- *      -ENOMEM - No availble memory
+ *      -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 static int
@@ -6171,7 +6189,7 @@
  *
  * Return codes
  *      0 - successful
- *      -ENOMEM - No availble memory
+ *      -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 static void
@@ -6235,7 +6253,7 @@
  *
  * Return codes
  *      0 - successful
- *      -ENOMEM - No availble memory
+ *      -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 int
@@ -6480,7 +6498,7 @@
  *
  * Return codes
  *      0 - successful
- *      -ENOMEM - No availble memory
+ *      -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 void
@@ -6525,7 +6543,7 @@
  *
  * Return codes
  *      0 - successful
- *      -ENOMEM - No availble memory
+ *      -ENOMEM - No available memory
  **/
 static int
 lpfc_sli4_cq_event_pool_create(struct lpfc_hba *phba)
@@ -6686,7 +6704,7 @@
  *
  * Return codes
  *      0 - successful
- *      -ENOMEM - No availble memory
+ *      -ENOMEM - No available memory
  *      -EIO - The mailbox failed to complete successfully.
  **/
 int
@@ -6752,9 +6770,11 @@
 			 * the loop again.
 			 */
 			for (rdy_chk = 0; rdy_chk < 1000; rdy_chk++) {
-				reg_data.word0 =
-					readl(phba->sli4_hba.u.if_type2.
-					      STATUSregaddr);
+				if (lpfc_readl(phba->sli4_hba.u.if_type2.
+					      STATUSregaddr, &reg_data.word0)) {
+					rc = -ENODEV;
+					break;
+				}
 				if (bf_get(lpfc_sliport_status_rdy, &reg_data))
 					break;
 				if (bf_get(lpfc_sliport_status_rn, &reg_data)) {
@@ -6775,8 +6795,11 @@
 			}
 
 			/* Detect any port errors. */
-			reg_data.word0 = readl(phba->sli4_hba.u.if_type2.
-					       STATUSregaddr);
+			if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+				 &reg_data.word0)) {
+				rc = -ENODEV;
+				break;
+			}
 			if ((bf_get(lpfc_sliport_status_err, &reg_data)) ||
 			    (rdy_chk >= 1000)) {
 				phba->work_status[0] = readl(
@@ -7810,7 +7833,7 @@
 	mqe = &mboxq->u.mqe;
 
 	/* Read the port's SLI4 Parameters port capabilities */
-	lpfc_sli4_params(mboxq);
+	lpfc_pc_sli4_params(mboxq);
 	if (!phba->sli4_hba.intr_enable)
 		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
 	else {
@@ -7854,6 +7877,66 @@
 }
 
 /**
+ * lpfc_get_sli4_parameters - Get the SLI4 Config PARAMETERS.
+ * @phba: Pointer to HBA context object.
+ * @mboxq: Pointer to the mailboxq memory for the mailbox command response.
+ *
+ * This function is called in the SLI4 code path to read the port's
+ * sli4 capabilities.
+ *
+ * This function may be be called from any context that can block-wait
+ * for the completion.  The expectation is that this routine is called
+ * typically from probe_one or from the online routine.
+ **/
+int
+lpfc_get_sli4_parameters(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq)
+{
+	int rc;
+	struct lpfc_mqe *mqe = &mboxq->u.mqe;
+	struct lpfc_pc_sli4_params *sli4_params;
+	int length;
+	struct lpfc_sli4_parameters *mbx_sli4_parameters;
+
+	/* Read the port's SLI4 Config Parameters */
+	length = (sizeof(struct lpfc_mbx_get_sli4_parameters) -
+		  sizeof(struct lpfc_sli4_cfg_mhdr));
+	lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_COMMON,
+			 LPFC_MBOX_OPCODE_GET_SLI4_PARAMETERS,
+			 length, LPFC_SLI4_MBX_EMBED);
+	if (!phba->sli4_hba.intr_enable)
+		rc = lpfc_sli_issue_mbox(phba, mboxq, MBX_POLL);
+	else
+		rc = lpfc_sli_issue_mbox_wait(phba, mboxq,
+			lpfc_mbox_tmo_val(phba, MBX_SLI4_CONFIG));
+	if (unlikely(rc))
+		return rc;
+	sli4_params = &phba->sli4_hba.pc_sli4_params;
+	mbx_sli4_parameters = &mqe->un.get_sli4_parameters.sli4_parameters;
+	sli4_params->if_type = bf_get(cfg_if_type, mbx_sli4_parameters);
+	sli4_params->sli_rev = bf_get(cfg_sli_rev, mbx_sli4_parameters);
+	sli4_params->sli_family = bf_get(cfg_sli_family, mbx_sli4_parameters);
+	sli4_params->featurelevel_1 = bf_get(cfg_sli_hint_1,
+					     mbx_sli4_parameters);
+	sli4_params->featurelevel_2 = bf_get(cfg_sli_hint_2,
+					     mbx_sli4_parameters);
+	if (bf_get(cfg_phwq, mbx_sli4_parameters))
+		phba->sli3_options |= LPFC_SLI4_PHWQ_ENABLED;
+	else
+		phba->sli3_options &= ~LPFC_SLI4_PHWQ_ENABLED;
+	sli4_params->sge_supp_len = mbx_sli4_parameters->sge_supp_len;
+	sli4_params->loopbk_scope = bf_get(loopbk_scope, mbx_sli4_parameters);
+	sli4_params->cqv = bf_get(cfg_cqv, mbx_sli4_parameters);
+	sli4_params->mqv = bf_get(cfg_mqv, mbx_sli4_parameters);
+	sli4_params->wqv = bf_get(cfg_wqv, mbx_sli4_parameters);
+	sli4_params->rqv = bf_get(cfg_rqv, mbx_sli4_parameters);
+	sli4_params->sgl_pages_max = bf_get(cfg_sgl_page_cnt,
+					    mbx_sli4_parameters);
+	sli4_params->sgl_pp_align = bf_get(cfg_sgl_pp_align,
+					   mbx_sli4_parameters);
+	return 0;
+}
+
+/**
  * lpfc_pci_probe_one_s3 - PCI probe func to reg SLI-3 device to PCI subsystem.
  * @pdev: pointer to PCI device
  * @pid: pointer to PCI device identifier
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_mbox.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_mbox.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_mbox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_mbox.c	2011-05-19 00:06:34.000000000 -0400
@@ -1263,7 +1263,8 @@
 	if (phba->sli_rev == LPFC_SLI_REV3 && phba->vpd.sli3Feat.cerbm) {
 		if (phba->cfg_enable_bg)
 			mb->un.varCfgPort.cbg = 1; /* configure BlockGuard */
-		mb->un.varCfgPort.cdss = 1; /* Configure Security */
+		if (phba->cfg_enable_dss)
+			mb->un.varCfgPort.cdss = 1; /* Configure Security */
 		mb->un.varCfgPort.cerbm = 1; /* Request HBQs */
 		mb->un.varCfgPort.ccrp = 1; /* Command Ring Polling */
 		mb->un.varCfgPort.max_hbq = lpfc_sli_hbq_count();
@@ -1692,7 +1693,7 @@
  * @mbox: pointer to lpfc mbox command.
  * @subsystem: The sli4 config sub mailbox subsystem.
  * @opcode: The sli4 config sub mailbox command opcode.
- * @length: Length of the sli4 config mailbox command.
+ * @length: Length of the sli4 config mailbox command (including sub-header).
  *
  * This routine sets up the header fields of SLI4 specific mailbox command
  * for sending IOCTL command.
@@ -1723,14 +1724,14 @@
 	if (emb) {
 		/* Set up main header fields */
 		bf_set(lpfc_mbox_hdr_emb, &sli4_config->header.cfg_mhdr, 1);
-		sli4_config->header.cfg_mhdr.payload_length =
-					LPFC_MBX_CMD_HDR_LENGTH + length;
+		sli4_config->header.cfg_mhdr.payload_length = length;
 		/* Set up sub-header fields following main header */
 		bf_set(lpfc_mbox_hdr_opcode,
 			&sli4_config->header.cfg_shdr.request, opcode);
 		bf_set(lpfc_mbox_hdr_subsystem,
 			&sli4_config->header.cfg_shdr.request, subsystem);
-		sli4_config->header.cfg_shdr.request.request_length = length;
+		sli4_config->header.cfg_shdr.request.request_length =
+			length - LPFC_MBX_CMD_HDR_LENGTH;
 		return length;
 	}
 
@@ -1833,7 +1834,7 @@
  * @fcf_index: index to fcf table.
  *
  * This routine routine allocates and constructs non-embedded mailbox command
- * for reading a FCF table entry refered by @fcf_index.
+ * for reading a FCF table entry referred by @fcf_index.
  *
  * Return: pointer to the mailbox command constructed if successful, otherwise
  * NULL.
@@ -1902,6 +1903,7 @@
 
 	/* Set up host requested features. */
 	bf_set(lpfc_mbx_rq_ftr_rq_fcpi, &mboxq->u.mqe.un.req_ftrs, 1);
+	bf_set(lpfc_mbx_rq_ftr_rq_perfh, &mboxq->u.mqe.un.req_ftrs, 1);
 
 	/* Enable DIF (block guard) only if configured to do so. */
 	if (phba->cfg_enable_bg)
@@ -2159,17 +2161,16 @@
 }
 
 /**
- * lpfc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params
- *                    mailbox command.
+ * lpfc_pc_sli4_params - Initialize the PORT_CAPABILITIES SLI4 Params mbox cmd.
  * @mbox: pointer to lpfc mbox command to initialize.
  *
  * The PORT_CAPABILITIES SLI4 parameters mailbox command is issued to
  * retrieve the particular SLI4 features supported by the port.
  **/
 void
-lpfc_sli4_params(struct lpfcMboxq *mbox)
+lpfc_pc_sli4_params(struct lpfcMboxq *mbox)
 {
-	struct lpfc_mbx_sli4_params *sli4_params;
+	struct lpfc_mbx_pc_sli4_params *sli4_params;
 
 	memset(mbox, 0, sizeof(*mbox));
 	sli4_params = &mbox->u.mqe.un.sli4_params;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_nl.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_nl.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_nl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_nl.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
  * and subcategory. The event type must come first.
  * The subcategory further defines the data that follows in the rest
  * of the payload. Each category will have its own unique header plus
- * any addtional data unique to the subcategory.
+ * any additional data unique to the subcategory.
  * The payload sent via the fc transport is one-way driver->application.
  */
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_nportdisc.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_nportdisc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_nportdisc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_nportdisc.c	2011-05-19 00:06:34.000000000 -0400
@@ -350,7 +350,11 @@
 	ndlp->nlp_maxframe =
 		((sp->cmn.bbRcvSizeMsb & 0x0F) << 8) | sp->cmn.bbRcvSizeLsb;
 
-	/* no need to reg_login if we are already in one of these states */
+	/*
+	 * Need to unreg_login if we are already in one of these states and
+	 * change to NPR state. This will block the port until after the ACC
+	 * completes and the reg_login is issued and completed.
+	 */
 	switch (ndlp->nlp_state) {
 	case  NLP_STE_NPR_NODE:
 		if (!(ndlp->nlp_flag & NLP_NPR_ADISC))
@@ -359,8 +363,9 @@
 	case  NLP_STE_PRLI_ISSUE:
 	case  NLP_STE_UNMAPPED_NODE:
 	case  NLP_STE_MAPPED_NODE:
-		lpfc_els_rsp_acc(vport, ELS_CMD_PLOGI, cmdiocb, ndlp, NULL);
-		return 1;
+		lpfc_unreg_rpi(vport, ndlp);
+		ndlp->nlp_prev_state = ndlp->nlp_state;
+		lpfc_nlp_set_state(vport, ndlp, NLP_STE_NPR_NODE);
 	}
 
 	if ((vport->fc_flag & FC_PT2PT) &&
@@ -653,7 +658,7 @@
 	return 0;
 }
 /**
- * lpfc_release_rpi - Release a RPI by issueing unreg_login mailbox cmd.
+ * lpfc_release_rpi - Release a RPI by issuing unreg_login mailbox cmd.
  * @phba : Pointer to lpfc_hba structure.
  * @vport: Pointer to lpfc_vport structure.
  * @rpi  : rpi to be release.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_scsi.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_scsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_scsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_scsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -577,7 +577,7 @@
 			iocb->un.fcpi64.bdl.addrHigh = 0;
 			iocb->ulpBdeCount = 0;
 			iocb->ulpLe = 0;
-			/* fill in responce BDE */
+			/* fill in response BDE */
 			iocb->unsli3.fcp_ext.rbde.tus.f.bdeFlags =
 							BUFF_TYPE_BDE_64;
 			iocb->unsli3.fcp_ext.rbde.tus.f.bdeSize =
@@ -609,6 +609,32 @@
 }
 
 /**
+ * lpfc_sli4_vport_delete_fcp_xri_aborted -Remove all ndlp references for vport
+ * @vport: pointer to lpfc vport data structure.
+ *
+ * This routine is invoked by the vport cleanup for deletions and the cleanup
+ * for an ndlp on removal.
+ **/
+void
+lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *vport)
+{
+	struct lpfc_hba *phba = vport->phba;
+	struct lpfc_scsi_buf *psb, *next_psb;
+	unsigned long iflag = 0;
+
+	spin_lock_irqsave(&phba->hbalock, iflag);
+	spin_lock(&phba->sli4_hba.abts_scsi_buf_list_lock);
+	list_for_each_entry_safe(psb, next_psb,
+				&phba->sli4_hba.lpfc_abts_scsi_buf_list, list) {
+		if (psb->rdata && psb->rdata->pnode
+			&& psb->rdata->pnode->vport == vport)
+			psb->rdata = NULL;
+	}
+	spin_unlock(&phba->sli4_hba.abts_scsi_buf_list_lock);
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
+}
+
+/**
  * lpfc_sli4_fcp_xri_aborted - Fast-path process of fcp xri abort
  * @phba: pointer to lpfc hba data structure.
  * @axri: pointer to the fcp xri abort wcqe structure.
@@ -640,7 +666,11 @@
 			psb->status = IOSTAT_SUCCESS;
 			spin_unlock(
 				&phba->sli4_hba.abts_scsi_buf_list_lock);
-			ndlp = psb->rdata->pnode;
+			if (psb->rdata && psb->rdata->pnode)
+				ndlp = psb->rdata->pnode;
+			else
+				ndlp = NULL;
+
 			rrq_empty = list_empty(&phba->active_rrq_list);
 			spin_unlock_irqrestore(&phba->hbalock, iflag);
 			if (ndlp)
@@ -964,36 +994,29 @@
 static struct lpfc_scsi_buf*
 lpfc_get_scsi_buf_s4(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp)
 {
-	struct  lpfc_scsi_buf *lpfc_cmd = NULL;
-	struct  lpfc_scsi_buf *start_lpfc_cmd = NULL;
-	struct list_head *scsi_buf_list = &phba->lpfc_scsi_buf_list;
+	struct lpfc_scsi_buf *lpfc_cmd ;
 	unsigned long iflag = 0;
 	int found = 0;
 
 	spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-	list_remove_head(scsi_buf_list, lpfc_cmd, struct lpfc_scsi_buf, list);
-	spin_unlock_irqrestore(&phba->scsi_buf_list_lock, iflag);
-	while (!found && lpfc_cmd) {
+	list_for_each_entry(lpfc_cmd, &phba->lpfc_scsi_buf_list,
+							list) {
 		if (lpfc_test_rrq_active(phba, ndlp,
-					 lpfc_cmd->cur_iocbq.sli4_xritag)) {
-			lpfc_release_scsi_buf_s4(phba, lpfc_cmd);
-			spin_lock_irqsave(&phba->scsi_buf_list_lock, iflag);
-			list_remove_head(scsi_buf_list, lpfc_cmd,
-					 struct lpfc_scsi_buf, list);
-			spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
-						 iflag);
-			if (lpfc_cmd == start_lpfc_cmd) {
-				lpfc_cmd = NULL;
-				break;
-			} else
-				continue;
-		}
+					 lpfc_cmd->cur_iocbq.sli4_xritag))
+			continue;
+		list_del(&lpfc_cmd->list);
 		found = 1;
 		lpfc_cmd->seg_cnt = 0;
 		lpfc_cmd->nonsg_phys = 0;
 		lpfc_cmd->prot_seg_cnt = 0;
+		break;
 	}
-	return  lpfc_cmd;
+	spin_unlock_irqrestore(&phba->scsi_buf_list_lock,
+						 iflag);
+	if (!found)
+		return NULL;
+	else
+		return  lpfc_cmd;
 }
 /**
  * lpfc_get_scsi_buf - Get a scsi buffer from lpfc_scsi_buf_list of the HBA
@@ -1194,10 +1217,10 @@
 				     (2 * sizeof(struct ulp_bde64)));
 			data_bde->addrHigh = putPaddrHigh(physaddr);
 			data_bde->addrLow = putPaddrLow(physaddr);
-			/* ebde count includes the responce bde and data bpl */
+			/* ebde count includes the response bde and data bpl */
 			iocb_cmd->unsli3.fcp_ext.ebde_count = 2;
 		} else {
-			/* ebde count includes the responce bde and data bdes */
+			/* ebde count includes the response bde and data bdes */
 			iocb_cmd->unsli3.fcp_ext.ebde_count = (num_bde + 1);
 		}
 	} else {
@@ -1491,10 +1514,11 @@
 	struct scatterlist *sgpe = NULL; /* s/g prot entry */
 	struct lpfc_pde5 *pde5 = NULL;
 	struct lpfc_pde6 *pde6 = NULL;
-	struct ulp_bde64 *prot_bde = NULL;
+	struct lpfc_pde7 *pde7 = NULL;
 	dma_addr_t dataphysaddr, protphysaddr;
 	unsigned short curr_data = 0, curr_prot = 0;
-	unsigned int split_offset, protgroup_len;
+	unsigned int split_offset;
+	unsigned int protgroup_len, protgroup_offset = 0, protgroup_remainder;
 	unsigned int protgrp_blks, protgrp_bytes;
 	unsigned int remainder, subtotal;
 	int status;
@@ -1562,23 +1586,33 @@
 		bpl++;
 
 		/* setup the first BDE that points to protection buffer */
-		prot_bde = (struct ulp_bde64 *) bpl;
-		protphysaddr = sg_dma_address(sgpe);
-		prot_bde->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
-		prot_bde->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
-		protgroup_len = sg_dma_len(sgpe);
+		protphysaddr = sg_dma_address(sgpe) + protgroup_offset;
+		protgroup_len = sg_dma_len(sgpe) - protgroup_offset;
 
 		/* must be integer multiple of the DIF block length */
 		BUG_ON(protgroup_len % 8);
 
+		pde7 = (struct lpfc_pde7 *) bpl;
+		memset(pde7, 0, sizeof(struct lpfc_pde7));
+		bf_set(pde7_type, pde7, LPFC_PDE7_DESCRIPTOR);
+
+		pde7->addrHigh = le32_to_cpu(putPaddrLow(protphysaddr));
+		pde7->addrLow = le32_to_cpu(putPaddrHigh(protphysaddr));
+
 		protgrp_blks = protgroup_len / 8;
 		protgrp_bytes = protgrp_blks * blksize;
 
-		prot_bde->tus.f.bdeSize = protgroup_len;
-		prot_bde->tus.f.bdeFlags = LPFC_PDE7_DESCRIPTOR;
-		prot_bde->tus.w = le32_to_cpu(bpl->tus.w);
+		/* check if this pde is crossing the 4K boundary; if so split */
+		if ((pde7->addrLow & 0xfff) + protgroup_len > 0x1000) {
+			protgroup_remainder = 0x1000 - (pde7->addrLow & 0xfff);
+			protgroup_offset += protgroup_remainder;
+			protgrp_blks = protgroup_remainder / 8;
+			protgrp_bytes = protgroup_remainder * blksize;
+		} else {
+			protgroup_offset = 0;
+			curr_prot++;
+		}
 
-		curr_prot++;
 		num_bde++;
 
 		/* setup BDE's for data blocks associated with DIF data */
@@ -1630,6 +1664,13 @@
 
 		}
 
+		if (protgroup_offset) {
+			/* update the reference tag */
+			reftag += protgrp_blks;
+			bpl++;
+			continue;
+		}
+
 		/* are we done ? */
 		if (curr_prot == protcnt) {
 			alldone = 1;
@@ -1652,6 +1693,7 @@
 
 	return num_bde;
 }
+
 /*
  * Given a SCSI command that supports DIF, determine composition of protection
  * groups involved in setting up buffer lists
@@ -1981,12 +2023,14 @@
 	struct scatterlist *sgel = NULL;
 	struct fcp_cmnd *fcp_cmnd = lpfc_cmd->fcp_cmnd;
 	struct sli4_sge *sgl = (struct sli4_sge *)lpfc_cmd->fcp_bpl;
+	struct sli4_sge *first_data_sgl;
 	IOCB_t *iocb_cmd = &lpfc_cmd->cur_iocbq.iocb;
 	dma_addr_t physaddr;
 	uint32_t num_bde = 0;
 	uint32_t dma_len;
 	uint32_t dma_offset = 0;
 	int nseg;
+	struct ulp_bde64 *bde;
 
 	/*
 	 * There are three possibilities here - use scatter-gather segment, use
@@ -2011,7 +2055,7 @@
 		bf_set(lpfc_sli4_sge_last, sgl, 0);
 		sgl->word2 = cpu_to_le32(sgl->word2);
 		sgl += 1;
-
+		first_data_sgl = sgl;
 		lpfc_cmd->seg_cnt = nseg;
 		if (lpfc_cmd->seg_cnt > phba->cfg_sg_seg_cnt) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_BG, "9074 BLKGRD:"
@@ -2047,6 +2091,17 @@
 			dma_offset += dma_len;
 			sgl++;
 		}
+		/* setup the performance hint (first data BDE) if enabled */
+		if (phba->sli3_options & LPFC_SLI4_PERFH_ENABLED) {
+			bde = (struct ulp_bde64 *)
+					&(iocb_cmd->unsli3.sli3Words[5]);
+			bde->addrLow = first_data_sgl->addr_lo;
+			bde->addrHigh = first_data_sgl->addr_hi;
+			bde->tus.f.bdeSize =
+					le32_to_cpu(first_data_sgl->sge_len);
+			bde->tus.f.bdeFlags = BUFF_TYPE_BDE_64;
+			bde->tus.w = cpu_to_le32(bde->tus.w);
+		}
 	} else {
 		sgl += 1;
 		/* clear the last flag in the fcp_rsp map entry */
@@ -2325,7 +2380,7 @@
 		}
 		/*
 		 * The cmnd->underflow is the minimum number of bytes that must
-		 * be transfered for this command.  Provided a sense condition
+		 * be transferred for this command.  Provided a sense condition
 		 * is not present, make sure the actual amount transferred is at
 		 * least the underflow value or fail.
 		 */
@@ -2471,6 +2526,16 @@
 			lpfc_worker_wake_up(phba);
 			break;
 		case IOSTAT_LOCAL_REJECT:
+		case IOSTAT_REMOTE_STOP:
+			if (lpfc_cmd->result == IOERR_ELXSEC_KEY_UNWRAP_ERROR ||
+			    lpfc_cmd->result ==
+					IOERR_ELXSEC_KEY_UNWRAP_COMPARE_ERROR ||
+			    lpfc_cmd->result == IOERR_ELXSEC_CRYPTO_ERROR ||
+			    lpfc_cmd->result ==
+					IOERR_ELXSEC_CRYPTO_COMPARE_ERROR) {
+				cmd->result = ScsiResult(DID_NO_CONNECT, 0);
+				break;
+			}
 			if (lpfc_cmd->result == IOERR_INVALID_RPI ||
 			    lpfc_cmd->result == IOERR_NO_RESOURCES ||
 			    lpfc_cmd->result == IOERR_ABORT_REQUESTED ||
@@ -2478,7 +2543,6 @@
 				cmd->result = ScsiResult(DID_REQUEUE, 0);
 				break;
 			}
-
 			if ((lpfc_cmd->result == IOERR_RX_DMA_FAILED ||
 			     lpfc_cmd->result == IOERR_TX_DMA_FAILED) &&
 			     pIocbOut->iocb.unsli3.sli3_bg.bgstat) {
@@ -2497,7 +2561,17 @@
 							"on unprotected cmd\n");
 				}
 			}
-
+			if ((lpfc_cmd->status == IOSTAT_REMOTE_STOP)
+				&& (phba->sli_rev == LPFC_SLI_REV4)
+				&& (pnode && NLP_CHK_NODE_ACT(pnode))) {
+				/* This IO was aborted by the target, we don't
+				 * know the rxid and because we did not send the
+				 * ABTS we cannot generate and RRQ.
+				 */
+				lpfc_set_rrq_active(phba, pnode,
+						lpfc_cmd->cur_iocbq.sli4_xritag,
+						0, 0);
+			}
 		/* else: fall through */
 		default:
 			cmd->result = ScsiResult(DID_ERROR, 0);
@@ -2508,9 +2582,8 @@
 		    || (pnode->nlp_state != NLP_STE_MAPPED_NODE))
 			cmd->result = ScsiResult(DID_TRANSPORT_DISRUPTED,
 						 SAM_STAT_BUSY);
-	} else {
+	} else
 		cmd->result = ScsiResult(DID_OK, 0);
-	}
 
 	if (cmd->result || lpfc_cmd->fcp_rsp->rspSnsLen) {
 		uint32_t *lp = (uint32_t *)cmd->sense_buffer;
@@ -2800,7 +2873,7 @@
 }
 
 /**
- * lpfc_scsi_api_table_setup - Set up scsi api fucntion jump table
+ * lpfc_scsi_api_table_setup - Set up scsi api function jump table
  * @phba: The hba struct for which this call is being executed.
  * @dev_grp: The HBA PCI-Device group number.
  *
@@ -3004,11 +3077,11 @@
 	 * transport is still transitioning.
 	 */
 	if (!ndlp || !NLP_CHK_NODE_ACT(ndlp)) {
-		cmnd->result = ScsiResult(DID_TRANSPORT_DISRUPTED, 0);
+		cmnd->result = ScsiResult(DID_IMM_RETRY, 0);
 		goto out_fail_command;
 	}
 	if (atomic_read(&ndlp->cmd_pending) >= ndlp->cmd_qdepth)
-		goto out_host_busy;
+		goto out_tgt_busy;
 
 	lpfc_cmd = lpfc_get_scsi_buf(phba, ndlp);
 	if (lpfc_cmd == NULL) {
@@ -3125,6 +3198,9 @@
  out_host_busy:
 	return SCSI_MLQUEUE_HOST_BUSY;
 
+ out_tgt_busy:
+	return SCSI_MLQUEUE_TARGET_BUSY;
+
  out_fail_command:
 	done(cmnd);
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_scsi.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_scsi.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_scsi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_scsi.h	2011-05-19 00:06:34.000000000 -0400
@@ -130,7 +130,7 @@
 	dma_addr_t nonsg_phys;	/* Non scatter-gather physical address. */
 
 	/*
-	 * data and dma_handle are the kernel virutal and bus address of the
+	 * data and dma_handle are the kernel virtual and bus address of the
 	 * dma-able buffer containing the fcp_cmd, fcp_rsp and a scatter
 	 * gather bde list that supports the sg_tablesize value.
 	 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_sli4.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_sli4.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_sli4.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_sli4.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2009 Emulex.  All rights reserved.                *
+ * Copyright (C) 2009-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -125,9 +125,9 @@
 	uint32_t entry_count;	/* Number of entries to support on the queue */
 	uint32_t entry_size;	/* Size of each queue entry. */
 	uint32_t queue_id;	/* Queue ID assigned by the hardware */
+	uint32_t assoc_qid;     /* Queue ID associated with, for CQ/WQ/MQ */
 	struct list_head page_list;
 	uint32_t page_count;	/* Number of pages allocated for this queue */
-
 	uint32_t host_index;	/* The host's index for putting or getting */
 	uint32_t hba_index;	/* The last known hba index for get or put */
 	union sli4_qe qe[1];	/* array to index entries (must be last) */
@@ -359,6 +359,10 @@
 	uint32_t hdr_pp_align;
 	uint32_t sgl_pages_max;
 	uint32_t sgl_pp_align;
+	uint8_t cqv;
+	uint8_t mqv;
+	uint8_t wqv;
+	uint8_t rqv;
 };
 
 /* SLI4 HBA data structure entries */
@@ -562,6 +566,8 @@
 			       struct sli4_wcqe_xri_aborted *);
 void lpfc_sli4_els_xri_aborted(struct lpfc_hba *,
 			       struct sli4_wcqe_xri_aborted *);
+void lpfc_sli4_vport_delete_els_xri_aborted(struct lpfc_vport *);
+void lpfc_sli4_vport_delete_fcp_xri_aborted(struct lpfc_vport *);
 int lpfc_sli4_brdreset(struct lpfc_hba *);
 int lpfc_sli4_add_fcf_record(struct lpfc_hba *, struct fcf_record *);
 void lpfc_sli_remove_dflt_fcf(struct lpfc_hba *);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_sli.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_sli.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_sli.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_sli.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2009 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  * Portions Copyright (C) 2004-2005 Christoph Hellwig              *
@@ -96,7 +96,8 @@
 	/* set consumption flag every once in a while */
 	if (!((q->host_index + 1) % LPFC_RELEASE_NOTIFICATION_INTERVAL))
 		bf_set(wqe_wqec, &wqe->generic.wqe_com, 1);
-
+	if (q->phba->sli3_options & LPFC_SLI4_PHWQ_ENABLED)
+		bf_set(wqe_wqid, &wqe->generic.wqe_com, q->queue_id);
 	lpfc_sli_pcimem_bcopy(wqe, temp_wqe, q->entry_size);
 
 	/* Update the host index before invoking device */
@@ -534,15 +535,35 @@
 	uint16_t adj_xri;
 	struct lpfc_node_rrq *rrq;
 	int empty;
+	uint32_t did = 0;
+
+
+	if (!ndlp)
+		return -EINVAL;
+
+	if (!phba->cfg_enable_rrq)
+		return -EINVAL;
+
+	if (phba->pport->load_flag & FC_UNLOADING) {
+		phba->hba_flag &= ~HBA_RRQ_ACTIVE;
+		goto out;
+	}
+	did = ndlp->nlp_DID;
 
 	/*
 	 * set the active bit even if there is no mem available.
 	 */
 	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
-	if (!ndlp)
-		return -EINVAL;
+
+	if (NLP_CHK_FREE_REQ(ndlp))
+		goto out;
+
+	if (ndlp->vport && (ndlp->vport->load_flag & FC_UNLOADING))
+		goto out;
+
 	if (test_and_set_bit(adj_xri, ndlp->active_rrqs.xri_bitmap))
-		return -EINVAL;
+		goto out;
+
 	rrq = mempool_alloc(phba->rrq_pool, GFP_KERNEL);
 	if (rrq) {
 		rrq->send_rrq = send_rrq;
@@ -553,14 +574,7 @@
 		rrq->vport = ndlp->vport;
 		rrq->rxid = rxid;
 		empty = list_empty(&phba->active_rrq_list);
-		if (phba->cfg_enable_rrq && send_rrq)
-			/*
-			 * We need the xri before we can add this to the
-			 * phba active rrq list.
-			 */
-			rrq->send_rrq = send_rrq;
-		else
-			rrq->send_rrq = 0;
+		rrq->send_rrq = send_rrq;
 		list_add_tail(&rrq->list, &phba->active_rrq_list);
 		if (!(phba->hba_flag & HBA_RRQ_ACTIVE)) {
 			phba->hba_flag |= HBA_RRQ_ACTIVE;
@@ -569,40 +583,49 @@
 		}
 		return 0;
 	}
-	return -ENOMEM;
+out:
+	lpfc_printf_log(phba, KERN_INFO, LOG_SLI,
+			"2921 Can't set rrq active xri:0x%x rxid:0x%x"
+			" DID:0x%x Send:%d\n",
+			xritag, rxid, did, send_rrq);
+	return -EINVAL;
 }
 
 /**
- * __lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
+ * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
  * @phba: Pointer to HBA context object.
  * @xritag: xri used in this exchange.
  * @rrq: The RRQ to be cleared.
  *
- * This function is called with hbalock held. This function
  **/
-static void
-__lpfc_clr_rrq_active(struct lpfc_hba *phba,
-			uint16_t xritag,
-			struct lpfc_node_rrq *rrq)
+void
+lpfc_clr_rrq_active(struct lpfc_hba *phba,
+		    uint16_t xritag,
+		    struct lpfc_node_rrq *rrq)
 {
 	uint16_t adj_xri;
-	struct lpfc_nodelist *ndlp;
+	struct lpfc_nodelist *ndlp = NULL;
 
-	ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
+	if ((rrq->vport) && NLP_CHK_NODE_ACT(rrq->ndlp))
+		ndlp = lpfc_findnode_did(rrq->vport, rrq->nlp_DID);
 
 	/* The target DID could have been swapped (cable swap)
 	 * we should use the ndlp from the findnode if it is
 	 * available.
 	 */
-	if (!ndlp)
+	if ((!ndlp) && rrq->ndlp)
 		ndlp = rrq->ndlp;
 
+	if (!ndlp)
+		goto out;
+
 	adj_xri = xritag - phba->sli4_hba.max_cfg_param.xri_base;
 	if (test_and_clear_bit(adj_xri, ndlp->active_rrqs.xri_bitmap)) {
 		rrq->send_rrq = 0;
 		rrq->xritag = 0;
 		rrq->rrq_stop_time = 0;
 	}
+out:
 	mempool_free(rrq, phba->rrq_pool);
 }
 
@@ -627,34 +650,34 @@
 	struct lpfc_node_rrq *nextrrq;
 	unsigned long next_time;
 	unsigned long iflags;
+	LIST_HEAD(send_rrq);
 
 	spin_lock_irqsave(&phba->hbalock, iflags);
 	phba->hba_flag &= ~HBA_RRQ_ACTIVE;
 	next_time = jiffies + HZ * (phba->fc_ratov + 1);
 	list_for_each_entry_safe(rrq, nextrrq,
-			&phba->active_rrq_list, list) {
-		if (time_after(jiffies, rrq->rrq_stop_time)) {
-			list_del(&rrq->list);
-			if (!rrq->send_rrq)
-				/* this call will free the rrq */
-				__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
-			else {
-			/* if we send the rrq then the completion handler
-			 *  will clear the bit in the xribitmap.
-			 */
-				spin_unlock_irqrestore(&phba->hbalock, iflags);
-				if (lpfc_send_rrq(phba, rrq)) {
-					lpfc_clr_rrq_active(phba, rrq->xritag,
-								 rrq);
-				}
-				spin_lock_irqsave(&phba->hbalock, iflags);
-			}
-		} else if  (time_before(rrq->rrq_stop_time, next_time))
+				 &phba->active_rrq_list, list) {
+		if (time_after(jiffies, rrq->rrq_stop_time))
+			list_move(&rrq->list, &send_rrq);
+		else if (time_before(rrq->rrq_stop_time, next_time))
 			next_time = rrq->rrq_stop_time;
 	}
 	spin_unlock_irqrestore(&phba->hbalock, iflags);
 	if (!list_empty(&phba->active_rrq_list))
 		mod_timer(&phba->rrq_tmr, next_time);
+	list_for_each_entry_safe(rrq, nextrrq, &send_rrq, list) {
+		list_del(&rrq->list);
+		if (!rrq->send_rrq)
+			/* this call will free the rrq */
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+		else if (lpfc_send_rrq(phba, rrq)) {
+			/* if we send the rrq then the completion handler
+			*  will clear the bit in the xribitmap.
+			*/
+			lpfc_clr_rrq_active(phba, rrq->xritag,
+					    rrq);
+		}
+	}
 }
 
 /**
@@ -692,29 +715,37 @@
 /**
  * lpfc_cleanup_vports_rrqs - Remove and clear the active RRQ for this vport.
  * @vport: Pointer to vport context object.
- *
- * Remove all active RRQs for this vport from the phba->active_rrq_list and
- * clear the rrq.
+ * @ndlp: Pointer to the lpfc_node_list structure.
+ * If ndlp is NULL Remove all active RRQs for this vport from the
+ * phba->active_rrq_list and clear the rrq.
+ * If ndlp is not NULL then only remove rrqs for this vport & this ndlp.
  **/
 void
-lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport)
+lpfc_cleanup_vports_rrqs(struct lpfc_vport *vport, struct lpfc_nodelist *ndlp)
 
 {
 	struct lpfc_hba *phba = vport->phba;
 	struct lpfc_node_rrq *rrq;
 	struct lpfc_node_rrq *nextrrq;
 	unsigned long iflags;
+	LIST_HEAD(rrq_list);
 
 	if (phba->sli_rev != LPFC_SLI_REV4)
 		return;
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
-		if (rrq->vport == vport) {
-			list_del(&rrq->list);
-			__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
-		}
+	if (!ndlp) {
+		lpfc_sli4_vport_delete_els_xri_aborted(vport);
+		lpfc_sli4_vport_delete_fcp_xri_aborted(vport);
 	}
+	spin_lock_irqsave(&phba->hbalock, iflags);
+	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list)
+		if ((rrq->vport == vport) && (!ndlp  || rrq->ndlp == ndlp))
+			list_move(&rrq->list, &rrq_list);
 	spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+	list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
+		list_del(&rrq->list);
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+	}
 }
 
 /**
@@ -732,24 +763,27 @@
 	struct lpfc_node_rrq *nextrrq;
 	unsigned long next_time;
 	unsigned long iflags;
+	LIST_HEAD(rrq_list);
 
 	if (phba->sli_rev != LPFC_SLI_REV4)
 		return;
 	spin_lock_irqsave(&phba->hbalock, iflags);
 	phba->hba_flag &= ~HBA_RRQ_ACTIVE;
 	next_time = jiffies + HZ * (phba->fc_ratov * 2);
-	list_for_each_entry_safe(rrq, nextrrq, &phba->active_rrq_list, list) {
+	list_splice_init(&phba->active_rrq_list, &rrq_list);
+	spin_unlock_irqrestore(&phba->hbalock, iflags);
+
+	list_for_each_entry_safe(rrq, nextrrq, &rrq_list, list) {
 		list_del(&rrq->list);
-		__lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
+		lpfc_clr_rrq_active(phba, rrq->xritag, rrq);
 	}
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
 	if (!list_empty(&phba->active_rrq_list))
 		mod_timer(&phba->rrq_tmr, next_time);
 }
 
 
 /**
- * __lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
+ * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
  * @phba: Pointer to HBA context object.
  * @ndlp: Targets nodelist pointer for this exchange.
  * @xritag the xri in the bitmap to test.
@@ -758,8 +792,8 @@
  * returns 0 = rrq not active for this xri
  *         1 = rrq is valid for this xri.
  **/
-static int
-__lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
+int
+lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
 			uint16_t  xritag)
 {
 	uint16_t adj_xri;
@@ -802,52 +836,6 @@
 }
 
 /**
- * lpfc_clr_rrq_active - Clears RRQ active bit in xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @xritag: xri used in this exchange.
- * @rrq: The RRQ to be cleared.
- *
- * This function is takes the hbalock.
- **/
-void
-lpfc_clr_rrq_active(struct lpfc_hba *phba,
-			uint16_t xritag,
-			struct lpfc_node_rrq *rrq)
-{
-	unsigned long iflags;
-
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	__lpfc_clr_rrq_active(phba, xritag, rrq);
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
-	return;
-}
-
-
-
-/**
- * lpfc_test_rrq_active - Test RRQ bit in xri_bitmap.
- * @phba: Pointer to HBA context object.
- * @ndlp: Targets nodelist pointer for this exchange.
- * @xritag the xri in the bitmap to test.
- *
- * This function takes the hbalock.
- * returns 0 = rrq not active for this xri
- *         1 = rrq is valid for this xri.
- **/
-int
-lpfc_test_rrq_active(struct lpfc_hba *phba, struct lpfc_nodelist *ndlp,
-			uint16_t  xritag)
-{
-	int ret;
-	unsigned long iflags;
-
-	spin_lock_irqsave(&phba->hbalock, iflags);
-	ret = __lpfc_test_rrq_active(phba, ndlp, xritag);
-	spin_unlock_irqrestore(&phba->hbalock, iflags);
-	return ret;
-}
-
-/**
  * __lpfc_sli_get_sglq - Allocates an iocb object from sgl pool
  * @phba: Pointer to HBA context object.
  * @piocb: Pointer to the iocbq.
@@ -884,7 +872,7 @@
 			return NULL;
 		adj_xri = sglq->sli4_xritag -
 				phba->sli4_hba.max_cfg_param.xri_base;
-		if (__lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
+		if (lpfc_test_rrq_active(phba, ndlp, sglq->sli4_xritag)) {
 			/* This xri has an rrq outstanding for this DID.
 			 * put it back in the list and get another xri.
 			 */
@@ -969,7 +957,8 @@
 		} else {
 			sglq->state = SGL_FREED;
 			sglq->ndlp = NULL;
-			list_add(&sglq->list, &phba->sli4_hba.lpfc_sgl_list);
+			list_add_tail(&sglq->list,
+				&phba->sli4_hba.lpfc_sgl_list);
 
 			/* Check if TXQ queue needs to be serviced */
 			if (pring->txq_cnt)
@@ -2828,7 +2817,7 @@
  * This function is called from the interrupt context when there is a ring
  * event for the fcp ring. The caller does not hold any lock.
  * The function processes each response iocb in the response ring until it
- * finds an iocb with LE bit set and chains all the iocbs upto the iocb with
+ * finds an iocb with LE bit set and chains all the iocbs up to the iocb with
  * LE bit set. The function will call the completion handler of the command iocb
  * if the response iocb indicates a completion for a command iocb or it is
  * an abort completion. The function will call lpfc_sli_process_unsol_iocb
@@ -3488,7 +3477,8 @@
 	int retval = 0;
 
 	/* Read the HBA Host Status Register */
-	status = readl(phba->HSregaddr);
+	if (lpfc_readl(phba->HSregaddr, &status))
+		return 1;
 
 	/*
 	 * Check status register every 100ms for 5 retries, then every
@@ -3513,7 +3503,10 @@
 			lpfc_sli_brdrestart(phba);
 		}
 		/* Read the HBA Host Status Register */
-		status = readl(phba->HSregaddr);
+		if (lpfc_readl(phba->HSregaddr, &status)) {
+			retval = 1;
+			break;
+		}
 	}
 
 	/* Check to see if any errors occurred during init */
@@ -3595,7 +3588,7 @@
 	uint32_t __iomem *resp_buf;
 	uint32_t __iomem *mbox_buf;
 	volatile uint32_t mbox;
-	uint32_t hc_copy;
+	uint32_t hc_copy, ha_copy, resp_data;
 	int  i;
 	uint8_t hdrtype;
 
@@ -3612,12 +3605,15 @@
 	resp_buf = phba->MBslimaddr;
 
 	/* Disable the error attention */
-	hc_copy = readl(phba->HCregaddr);
+	if (lpfc_readl(phba->HCregaddr, &hc_copy))
+		return;
 	writel((hc_copy & ~HC_ERINT_ENA), phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
 	phba->link_flag |= LS_IGNORE_ERATT;
 
-	if (readl(phba->HAregaddr) & HA_ERATT) {
+	if (lpfc_readl(phba->HAregaddr, &ha_copy))
+		return;
+	if (ha_copy & HA_ERATT) {
 		/* Clear Chip error bit */
 		writel(HA_ERATT, phba->HAregaddr);
 		phba->pport->stopped = 1;
@@ -3631,11 +3627,18 @@
 	mbox_buf = phba->MBslimaddr;
 	writel(mbox, mbox_buf);
 
-	for (i = 0;
-	     readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN) && i < 50; i++)
-		mdelay(1);
-
-	if (readl(resp_buf + 1) != ~(BARRIER_TEST_PATTERN)) {
+	for (i = 0; i < 50; i++) {
+		if (lpfc_readl((resp_buf + 1), &resp_data))
+			return;
+		if (resp_data != ~(BARRIER_TEST_PATTERN))
+			mdelay(1);
+		else
+			break;
+	}
+	resp_data = 0;
+	if (lpfc_readl((resp_buf + 1), &resp_data))
+		return;
+	if (resp_data  != ~(BARRIER_TEST_PATTERN)) {
 		if (phba->sli.sli_flag & LPFC_SLI_ACTIVE ||
 		    phba->pport->stopped)
 			goto restore_hc;
@@ -3644,13 +3647,26 @@
 	}
 
 	((MAILBOX_t *)&mbox)->mbxOwner = OWN_HOST;
-	for (i = 0; readl(resp_buf) != mbox &&  i < 500; i++)
-		mdelay(1);
+	resp_data = 0;
+	for (i = 0; i < 500; i++) {
+		if (lpfc_readl(resp_buf, &resp_data))
+			return;
+		if (resp_data != mbox)
+			mdelay(1);
+		else
+			break;
+	}
 
 clear_errat:
 
-	while (!(readl(phba->HAregaddr) & HA_ERATT) && ++i < 500)
-		mdelay(1);
+	while (++i < 500) {
+		if (lpfc_readl(phba->HAregaddr, &ha_copy))
+			return;
+		if (!(ha_copy & HA_ERATT))
+			mdelay(1);
+		else
+			break;
+	}
 
 	if (readl(phba->HAregaddr) & HA_ERATT) {
 		writel(HA_ERATT, phba->HAregaddr);
@@ -3697,7 +3713,11 @@
 
 	/* Disable the error attention */
 	spin_lock_irq(&phba->hbalock);
-	status = readl(phba->HCregaddr);
+	if (lpfc_readl(phba->HCregaddr, &status)) {
+		spin_unlock_irq(&phba->hbalock);
+		mempool_free(pmb, phba->mbox_mem_pool);
+		return 1;
+	}
 	status &= ~HC_ERINT_ENA;
 	writel(status, phba->HCregaddr);
 	readl(phba->HCregaddr); /* flush */
@@ -3731,11 +3751,12 @@
 	 * 3 seconds we still set HBA_ERROR state because the status of the
 	 * board is now undefined.
 	 */
-	ha_copy = readl(phba->HAregaddr);
-
+	if (lpfc_readl(phba->HAregaddr, &ha_copy))
+		return 1;
 	while ((i++ < 30) && !(ha_copy & HA_ERATT)) {
 		mdelay(100);
-		ha_copy = readl(phba->HAregaddr);
+		if (lpfc_readl(phba->HAregaddr, &ha_copy))
+			return 1;
 	}
 
 	del_timer_sync(&psli->mbox_tmo);
@@ -4029,7 +4050,8 @@
 	uint32_t status, i = 0;
 
 	/* Read the HBA Host Status Register */
-	status = readl(phba->HSregaddr);
+	if (lpfc_readl(phba->HSregaddr, &status))
+		return -EIO;
 
 	/* Check status register to see what current state is */
 	i = 0;
@@ -4084,7 +4106,8 @@
 			lpfc_sli_brdrestart(phba);
 		}
 		/* Read the HBA Host Status Register */
-		status = readl(phba->HSregaddr);
+		if (lpfc_readl(phba->HSregaddr, &status))
+			return -EIO;
 	}
 
 	/* Check to see if any errors occurred during init */
@@ -4817,7 +4840,10 @@
 				"0378 No support for fcpi mode.\n");
 		ftr_rsp++;
 	}
-
+	if (bf_get(lpfc_mbx_rq_ftr_rsp_perfh, &mqe->un.req_ftrs))
+		phba->sli3_options |= LPFC_SLI4_PERFH_ENABLED;
+	else
+		phba->sli3_options &= ~LPFC_SLI4_PERFH_ENABLED;
 	/*
 	 * If the port cannot support the host's requested features
 	 * then turn off the global config parameters to disable the
@@ -5004,7 +5030,8 @@
 	spin_lock_irq(&phba->hbalock);
 	phba->link_state = LPFC_LINK_DOWN;
 	spin_unlock_irq(&phba->hbalock);
-	rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
+	if (phba->cfg_suppress_link_up == LPFC_INITIALIZE_LINK)
+		rc = phba->lpfc_hba_init_link(phba, MBX_NOWAIT);
 out_unset_queue:
 	/* Unset all the queues set up in this routine when error out */
 	if (rc)
@@ -5090,7 +5117,7 @@
 
 	/* Setting state unknown so lpfc_sli_abort_iocb_ring
 	 * would get IOCB_ERROR from lpfc_sli_issue_iocb, allowing
-	 * it to fail all oustanding SCSI IO.
+	 * it to fail all outstanding SCSI IO.
 	 */
 	spin_lock_irq(&phba->pport->work_port_lock);
 	phba->pport->work_port_events &= ~WORKER_MBOX_TMO;
@@ -5143,7 +5170,7 @@
 	MAILBOX_t *mb;
 	struct lpfc_sli *psli = &phba->sli;
 	uint32_t status, evtctr;
-	uint32_t ha_copy;
+	uint32_t ha_copy, hc_copy;
 	int i;
 	unsigned long timeout;
 	unsigned long drvr_flag = 0;
@@ -5209,15 +5236,17 @@
 		goto out_not_finished;
 	}
 
-	if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT &&
-	    !(readl(phba->HCregaddr) & HC_MBINT_ENA)) {
-		spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
-		lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
+	if (mb->mbxCommand != MBX_KILL_BOARD && flag & MBX_NOWAIT) {
+		if (lpfc_readl(phba->HCregaddr, &hc_copy) ||
+			!(hc_copy & HC_MBINT_ENA)) {
+			spin_unlock_irqrestore(&phba->hbalock, drvr_flag);
+			lpfc_printf_log(phba, KERN_ERR, LOG_MBOX | LOG_SLI,
 				"(%d):2528 Mailbox command x%x cannot "
 				"issue Data: x%x x%x\n",
 				pmbox->vport ? pmbox->vport->vpi : 0,
 				pmbox->u.mb.mbxCommand, psli->sli_flag, flag);
-		goto out_not_finished;
+			goto out_not_finished;
+		}
 	}
 
 	if (psli->sli_flag & LPFC_SLI_MBOX_ACTIVE) {
@@ -5415,11 +5444,19 @@
 			word0 = le32_to_cpu(word0);
 		} else {
 			/* First read mbox status word */
-			word0 = readl(phba->MBslimaddr);
+			if (lpfc_readl(phba->MBslimaddr, &word0)) {
+				spin_unlock_irqrestore(&phba->hbalock,
+						       drvr_flag);
+				goto out_not_finished;
+			}
 		}
 
 		/* Read the HBA Host Attention Register */
-		ha_copy = readl(phba->HAregaddr);
+		if (lpfc_readl(phba->HAregaddr, &ha_copy)) {
+			spin_unlock_irqrestore(&phba->hbalock,
+						       drvr_flag);
+			goto out_not_finished;
+		}
 		timeout = msecs_to_jiffies(lpfc_mbox_tmo_val(phba,
 							     mb->mbxCommand) *
 					   1000) + jiffies;
@@ -5470,7 +5507,11 @@
 				word0 = readl(phba->MBslimaddr);
 			}
 			/* Read the HBA Host Attention Register */
-			ha_copy = readl(phba->HAregaddr);
+			if (lpfc_readl(phba->HAregaddr, &ha_copy)) {
+				spin_unlock_irqrestore(&phba->hbalock,
+						       drvr_flag);
+				goto out_not_finished;
+			}
 		}
 
 		if (psli->sli_flag & LPFC_SLI_ACTIVE) {
@@ -5990,7 +6031,7 @@
 }
 
 /**
- * lpfc_mbox_api_table_setup - Set up mbox api fucntion jump table
+ * lpfc_mbox_api_table_setup - Set up mbox api function jump table
  * @phba: The hba struct for which this call is being executed.
  * @dev_grp: The HBA PCI-Device group number.
  *
@@ -6270,7 +6311,6 @@
 				bf_set(lpfc_sli4_sge_last, sgl, 1);
 			else
 				bf_set(lpfc_sli4_sge_last, sgl, 0);
-			sgl->word2 = cpu_to_le32(sgl->word2);
 			/* swap the size field back to the cpu so we
 			 * can assign it to the sgl.
 			 */
@@ -6290,6 +6330,7 @@
 				bf_set(lpfc_sli4_sge_offset, sgl, offset);
 				offset += bde.tus.f.bdeSize;
 			}
+			sgl->word2 = cpu_to_le32(sgl->word2);
 			bpl++;
 			sgl++;
 		}
@@ -6535,9 +6576,9 @@
 		numBdes = iocbq->iocb.un.genreq64.bdl.bdeSize /
 			sizeof(struct ulp_bde64);
 		for (i = 0; i < numBdes; i++) {
-			if (bpl[i].tus.f.bdeFlags != BUFF_TYPE_BDE_64)
-				break;
 			bde.tus.w = le32_to_cpu(bpl[i].tus.w);
+			if (bde.tus.f.bdeFlags != BUFF_TYPE_BDE_64)
+				break;
 			xmit_len += bde.tus.f.bdeSize;
 		}
 		/* word3 iocb=IO_TAG wqe=request_payload_len */
@@ -6627,15 +6668,15 @@
 		xritag = 0;
 	break;
 	case CMD_XMIT_BLS_RSP64_CX:
-		/* As BLS ABTS-ACC WQE is very different from other WQEs,
+		/* As BLS ABTS RSP WQE is very different from other WQEs,
 		 * we re-construct this WQE here based on information in
 		 * iocbq from scratch.
 		 */
 		memset(wqe, 0, sizeof(union lpfc_wqe));
 		/* OX_ID is invariable to who sent ABTS to CT exchange */
 		bf_set(xmit_bls_rsp64_oxid, &wqe->xmit_bls_rsp,
-		       bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_acc));
-		if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_acc) ==
+		       bf_get(lpfc_abts_oxid, &iocbq->iocb.un.bls_rsp));
+		if (bf_get(lpfc_abts_orig, &iocbq->iocb.un.bls_rsp) ==
 		    LPFC_ABTS_UNSOL_INT) {
 			/* ABTS sent by initiator to CT exchange, the
 			 * RX_ID field will be filled with the newly
@@ -6649,7 +6690,7 @@
 			 * RX_ID from ABTS.
 			 */
 			bf_set(xmit_bls_rsp64_rxid, &wqe->xmit_bls_rsp,
-			       bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_acc));
+			       bf_get(lpfc_abts_rxid, &iocbq->iocb.un.bls_rsp));
 		}
 		bf_set(xmit_bls_rsp64_seqcnthi, &wqe->xmit_bls_rsp, 0xffff);
 		bf_set(wqe_xmit_bls_pt, &wqe->xmit_bls_rsp.wqe_dest, 0x1);
@@ -6660,6 +6701,15 @@
 		       LPFC_WQE_LENLOC_NONE);
 		/* Overwrite the pre-set comnd type with OTHER_COMMAND */
 		command_type = OTHER_COMMAND;
+		if (iocbq->iocb.un.xseq64.w5.hcsw.Rctl == FC_RCTL_BA_RJT) {
+			bf_set(xmit_bls_rsp64_rjt_vspec, &wqe->xmit_bls_rsp,
+			       bf_get(lpfc_vndr_code, &iocbq->iocb.un.bls_rsp));
+			bf_set(xmit_bls_rsp64_rjt_expc, &wqe->xmit_bls_rsp,
+			       bf_get(lpfc_rsn_expln, &iocbq->iocb.un.bls_rsp));
+			bf_set(xmit_bls_rsp64_rjt_rsnc, &wqe->xmit_bls_rsp,
+			       bf_get(lpfc_rsn_code, &iocbq->iocb.un.bls_rsp));
+		}
+
 	break;
 	case CMD_XRI_ABORTED_CX:
 	case CMD_CREATE_XRI_CR: /* Do we expect to use this? */
@@ -6708,7 +6758,8 @@
 
 	if (piocb->sli4_xritag == NO_XRI) {
 		if (piocb->iocb.ulpCommand == CMD_ABORT_XRI_CN ||
-		    piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN)
+		    piocb->iocb.ulpCommand == CMD_CLOSE_XRI_CN ||
+		    piocb->iocb.ulpCommand == CMD_XMIT_BLS_RSP64_CX)
 			sglq = NULL;
 		else {
 			if (pring->txq_cnt) {
@@ -6796,7 +6847,7 @@
 }
 
 /**
- * lpfc_sli_api_table_setup - Set up sli api fucntion jump table
+ * lpfc_sli_api_table_setup - Set up sli api function jump table
  * @phba: The hba struct for which this call is being executed.
  * @dev_grp: The HBA PCI-Device group number.
  *
@@ -7470,7 +7521,7 @@
 	struct lpfc_dmabuf *mp, *next_mp;
 	struct list_head *slp = &pring->postbufq;
 
-	/* Search postbufq, from the begining, looking for a match on tag */
+	/* Search postbufq, from the beginning, looking for a match on tag */
 	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
 		if (mp->buffer_tag == tag) {
@@ -7514,7 +7565,7 @@
 	struct lpfc_dmabuf *mp, *next_mp;
 	struct list_head *slp = &pring->postbufq;
 
-	/* Search postbufq, from the begining, looking for a match on phys */
+	/* Search postbufq, from the beginning, looking for a match on phys */
 	spin_lock_irq(&phba->hbalock);
 	list_for_each_entry_safe(mp, next_mp, &pring->postbufq, list) {
 		if (mp->phys == phys) {
@@ -8201,7 +8252,8 @@
 	piocb->iocb_flag &= ~LPFC_IO_WAKE;
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-		creg_val = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &creg_val))
+			return IOCB_ERROR;
 		creg_val |= (HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
 		readl(phba->HCregaddr); /* flush */
@@ -8243,7 +8295,8 @@
 	}
 
 	if (phba->cfg_poll & DISABLE_FCP_RING_INT) {
-		creg_val = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &creg_val))
+			return IOCB_ERROR;
 		creg_val &= ~(HC_R0INT_ENA << LPFC_FCP_RING);
 		writel(creg_val, phba->HCregaddr);
 		readl(phba->HCregaddr); /* flush */
@@ -8385,7 +8438,7 @@
  * for possible error attention events. The caller must hold the hostlock
  * with spin_lock_irq().
  *
- * This fucntion returns 1 when there is Error Attention in the Host Attention
+ * This function returns 1 when there is Error Attention in the Host Attention
  * Register and returns 0 otherwise.
  **/
 static int
@@ -8394,10 +8447,13 @@
 	uint32_t ha_copy;
 
 	/* Read chip Host Attention (HA) register */
-	ha_copy = readl(phba->HAregaddr);
+	if (lpfc_readl(phba->HAregaddr, &ha_copy))
+		goto unplug_err;
+
 	if (ha_copy & HA_ERATT) {
 		/* Read host status register to retrieve error event */
-		lpfc_sli_read_hs(phba);
+		if (lpfc_sli_read_hs(phba))
+			goto unplug_err;
 
 		/* Check if there is a deferred error condition is active */
 		if ((HS_FFER1 & phba->work_hs) &&
@@ -8416,6 +8472,15 @@
 		return 1;
 	}
 	return 0;
+
+unplug_err:
+	/* Set the driver HS work bitmap */
+	phba->work_hs |= UNPLUG_ERR;
+	/* Set the driver HA work bitmap */
+	phba->work_ha |= HA_ERATT;
+	/* Indicate polling handles this ERATT */
+	phba->hba_flag |= HBA_ERATT_HANDLED;
+	return 1;
 }
 
 /**
@@ -8426,7 +8491,7 @@
  * for possible error attention events. The caller must hold the hostlock
  * with spin_lock_irq().
  *
- * This fucntion returns 1 when there is Error Attention in the Host Attention
+ * This function returns 1 when there is Error Attention in the Host Attention
  * Register and returns 0 otherwise.
  **/
 static int
@@ -8443,8 +8508,15 @@
 	if_type = bf_get(lpfc_sli_intf_if_type, &phba->sli4_hba.sli_intf);
 	switch (if_type) {
 	case LPFC_SLI_INTF_IF_TYPE_0:
-		uerr_sta_lo = readl(phba->sli4_hba.u.if_type0.UERRLOregaddr);
-		uerr_sta_hi = readl(phba->sli4_hba.u.if_type0.UERRHIregaddr);
+		if (lpfc_readl(phba->sli4_hba.u.if_type0.UERRLOregaddr,
+			&uerr_sta_lo) ||
+			lpfc_readl(phba->sli4_hba.u.if_type0.UERRHIregaddr,
+			&uerr_sta_hi)) {
+			phba->work_hs |= UNPLUG_ERR;
+			phba->work_ha |= HA_ERATT;
+			phba->hba_flag |= HBA_ERATT_HANDLED;
+			return 1;
+		}
 		if ((~phba->sli4_hba.ue_mask_lo & uerr_sta_lo) ||
 		    (~phba->sli4_hba.ue_mask_hi & uerr_sta_hi)) {
 			lpfc_printf_log(phba, KERN_ERR, LOG_INIT,
@@ -8463,9 +8535,15 @@
 		}
 		break;
 	case LPFC_SLI_INTF_IF_TYPE_2:
-		portstat_reg.word0 =
-			readl(phba->sli4_hba.u.if_type2.STATUSregaddr);
-		portsmphr = readl(phba->sli4_hba.PSMPHRregaddr);
+		if (lpfc_readl(phba->sli4_hba.u.if_type2.STATUSregaddr,
+			&portstat_reg.word0) ||
+			lpfc_readl(phba->sli4_hba.PSMPHRregaddr,
+			&portsmphr)){
+			phba->work_hs |= UNPLUG_ERR;
+			phba->work_ha |= HA_ERATT;
+			phba->hba_flag |= HBA_ERATT_HANDLED;
+			return 1;
+		}
 		if (bf_get(lpfc_sliport_status_err, &portstat_reg)) {
 			phba->work_status[0] =
 				readl(phba->sli4_hba.u.if_type2.ERR1regaddr);
@@ -8503,7 +8581,7 @@
  * This function is called from timer soft interrupt context to check HBA's
  * error attention register bit for error attention events.
  *
- * This fucntion returns 1 when there is Error Attention in the Host Attention
+ * This function returns 1 when there is Error Attention in the Host Attention
  * Register and returns 0 otherwise.
  **/
 int
@@ -8646,7 +8724,8 @@
 			return IRQ_NONE;
 		/* Need to read HA REG for slow-path events */
 		spin_lock_irqsave(&phba->hbalock, iflag);
-		ha_copy = readl(phba->HAregaddr);
+		if (lpfc_readl(phba->HAregaddr, &ha_copy))
+			goto unplug_error;
 		/* If somebody is waiting to handle an eratt don't process it
 		 * here. The brdkill function will do this.
 		 */
@@ -8672,7 +8751,9 @@
 		}
 
 		/* Clear up only attention source related to slow-path */
-		hc_copy = readl(phba->HCregaddr);
+		if (lpfc_readl(phba->HCregaddr, &hc_copy))
+			goto unplug_error;
+
 		writel(hc_copy & ~(HC_MBINT_ENA | HC_R2INT_ENA |
 			HC_LAINT_ENA | HC_ERINT_ENA),
 			phba->HCregaddr);
@@ -8695,7 +8776,8 @@
 				 */
 				spin_lock_irqsave(&phba->hbalock, iflag);
 				phba->sli.sli_flag &= ~LPFC_PROCESS_LA;
-				control = readl(phba->HCregaddr);
+				if (lpfc_readl(phba->HCregaddr, &control))
+					goto unplug_error;
 				control &= ~HC_LAINT_ENA;
 				writel(control, phba->HCregaddr);
 				readl(phba->HCregaddr); /* flush */
@@ -8715,7 +8797,8 @@
 			status >>= (4*LPFC_ELS_RING);
 			if (status & HA_RXMASK) {
 				spin_lock_irqsave(&phba->hbalock, iflag);
-				control = readl(phba->HCregaddr);
+				if (lpfc_readl(phba->HCregaddr, &control))
+					goto unplug_error;
 
 				lpfc_debugfs_slow_ring_trc(phba,
 				"ISR slow ring:   ctl:x%x stat:x%x isrcnt:x%x",
@@ -8748,7 +8831,8 @@
 		}
 		spin_lock_irqsave(&phba->hbalock, iflag);
 		if (work_ha_copy & HA_ERATT) {
-			lpfc_sli_read_hs(phba);
+			if (lpfc_sli_read_hs(phba))
+				goto unplug_error;
 			/*
 			 * Check if there is a deferred error condition
 			 * is active
@@ -8879,6 +8963,9 @@
 		lpfc_worker_wake_up(phba);
 	}
 	return IRQ_HANDLED;
+unplug_error:
+	spin_unlock_irqrestore(&phba->hbalock, iflag);
+	return IRQ_HANDLED;
 
 } /* lpfc_sli_sp_intr_handler */
 
@@ -8926,7 +9013,8 @@
 		if (lpfc_intr_state_check(phba))
 			return IRQ_NONE;
 		/* Need to read HA REG for FCP ring and other ring events */
-		ha_copy = readl(phba->HAregaddr);
+		if (lpfc_readl(phba->HAregaddr, &ha_copy))
+			return IRQ_HANDLED;
 		/* Clear up only attention source related to fast-path */
 		spin_lock_irqsave(&phba->hbalock, iflag);
 		/*
@@ -9011,7 +9099,11 @@
 		return IRQ_NONE;
 
 	spin_lock(&phba->hbalock);
-	phba->ha_copy = readl(phba->HAregaddr);
+	if (lpfc_readl(phba->HAregaddr, &phba->ha_copy)) {
+		spin_unlock(&phba->hbalock);
+		return IRQ_HANDLED;
+	}
+
 	if (unlikely(!phba->ha_copy)) {
 		spin_unlock(&phba->hbalock);
 		return IRQ_NONE;
@@ -9033,7 +9125,10 @@
 	}
 
 	/* Clear attention sources except link and error attentions */
-	hc_copy = readl(phba->HCregaddr);
+	if (lpfc_readl(phba->HCregaddr, &hc_copy)) {
+		spin_unlock(&phba->hbalock);
+		return IRQ_HANDLED;
+	}
 	writel(hc_copy & ~(HC_MBINT_ENA | HC_R0INT_ENA | HC_R1INT_ENA
 		| HC_R2INT_ENA | HC_LAINT_ENA | HC_ERINT_ENA),
 		phba->HCregaddr);
@@ -9589,7 +9684,7 @@
  * @cq: Pointer to the completion queue.
  * @wcqe: Pointer to a completion queue entry.
  *
- * This routine process a slow-path work-queue or recieve queue completion queue
+ * This routine process a slow-path work-queue or receive queue completion queue
  * entry.
  *
  * Return: true if work posted to worker thread, otherwise false.
@@ -10410,7 +10505,6 @@
 	if (!phba->sli4_hba.pc_sli4_params.supported)
 		hw_page_size = SLI4_PAGE_SIZE;
 
-
 	mbox = mempool_alloc(phba->mbox_mem_pool, GFP_KERNEL);
 	if (!mbox)
 		return -ENOMEM;
@@ -10420,11 +10514,22 @@
 			 LPFC_MBOX_OPCODE_CQ_CREATE,
 			 length, LPFC_SLI4_MBX_EMBED);
 	cq_create = &mbox->u.mqe.un.cq_create;
+	shdr = (union lpfc_sli4_cfg_shdr *) &cq_create->header.cfg_shdr;
 	bf_set(lpfc_mbx_cq_create_num_pages, &cq_create->u.request,
 		    cq->page_count);
 	bf_set(lpfc_cq_context_event, &cq_create->u.request.context, 1);
 	bf_set(lpfc_cq_context_valid, &cq_create->u.request.context, 1);
-	bf_set(lpfc_cq_eq_id, &cq_create->u.request.context, eq->queue_id);
+	bf_set(lpfc_mbox_hdr_version, &shdr->request,
+	       phba->sli4_hba.pc_sli4_params.cqv);
+	if (phba->sli4_hba.pc_sli4_params.cqv == LPFC_Q_CREATE_VERSION_2) {
+		bf_set(lpfc_mbx_cq_create_page_size, &cq_create->u.request,
+		       (PAGE_SIZE/SLI4_PAGE_SIZE));
+		bf_set(lpfc_cq_eq_id_2, &cq_create->u.request.context,
+		       eq->queue_id);
+	} else {
+		bf_set(lpfc_cq_eq_id, &cq_create->u.request.context,
+		       eq->queue_id);
+	}
 	switch (cq->entry_count) {
 	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -10456,7 +10561,6 @@
 	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
 
 	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr = (union lpfc_sli4_cfg_shdr *) &cq_create->header.cfg_shdr;
 	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
 	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
 	if (shdr_status || shdr_add_status || rc) {
@@ -10478,6 +10582,7 @@
 	cq->type = type;
 	cq->subtype = subtype;
 	cq->queue_id = bf_get(lpfc_mbx_cq_create_q_id, &cq_create->u.response);
+	cq->assoc_qid = eq->queue_id;
 	cq->host_index = 0;
 	cq->hba_index = 0;
 
@@ -10521,20 +10626,20 @@
 	bf_set(lpfc_mq_context_valid, &mq_create->u.request.context, 1);
 	switch (mq->entry_count) {
 	case 16:
-		bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
-		       LPFC_MQ_CNT_16);
+		bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+		       LPFC_MQ_RING_SIZE_16);
 		break;
 	case 32:
-		bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
-		       LPFC_MQ_CNT_32);
+		bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+		       LPFC_MQ_RING_SIZE_32);
 		break;
 	case 64:
-		bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
-		       LPFC_MQ_CNT_64);
+		bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+		       LPFC_MQ_RING_SIZE_64);
 		break;
 	case 128:
-		bf_set(lpfc_mq_context_count, &mq_create->u.request.context,
-		       LPFC_MQ_CNT_128);
+		bf_set(lpfc_mq_context_ring_size, &mq_create->u.request.context,
+		       LPFC_MQ_RING_SIZE_128);
 		break;
 	}
 	list_for_each_entry(dmabuf, &mq->page_list, list) {
@@ -10592,6 +10697,7 @@
 			 length, LPFC_SLI4_MBX_EMBED);
 
 	mq_create_ext = &mbox->u.mqe.un.mq_create_ext;
+	shdr = (union lpfc_sli4_cfg_shdr *) &mq_create_ext->header.cfg_shdr;
 	bf_set(lpfc_mbx_mq_create_ext_num_pages,
 	       &mq_create_ext->u.request, mq->page_count);
 	bf_set(lpfc_mbx_mq_create_ext_async_evt_link,
@@ -10604,9 +10710,15 @@
 	       &mq_create_ext->u.request, 1);
 	bf_set(lpfc_mbx_mq_create_ext_async_evt_sli,
 	       &mq_create_ext->u.request, 1);
-	bf_set(lpfc_mq_context_cq_id,
-	       &mq_create_ext->u.request.context, cq->queue_id);
 	bf_set(lpfc_mq_context_valid, &mq_create_ext->u.request.context, 1);
+	bf_set(lpfc_mbox_hdr_version, &shdr->request,
+	       phba->sli4_hba.pc_sli4_params.mqv);
+	if (phba->sli4_hba.pc_sli4_params.mqv == LPFC_Q_CREATE_VERSION_1)
+		bf_set(lpfc_mbx_mq_create_ext_cq_id, &mq_create_ext->u.request,
+		       cq->queue_id);
+	else
+		bf_set(lpfc_mq_context_cq_id, &mq_create_ext->u.request.context,
+		       cq->queue_id);
 	switch (mq->entry_count) {
 	default:
 		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
@@ -10616,20 +10728,24 @@
 			return -EINVAL;
 		/* otherwise default to smallest count (drop through) */
 	case 16:
-		bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
-		       LPFC_MQ_CNT_16);
+		bf_set(lpfc_mq_context_ring_size,
+		       &mq_create_ext->u.request.context,
+		       LPFC_MQ_RING_SIZE_16);
 		break;
 	case 32:
-		bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
-		       LPFC_MQ_CNT_32);
+		bf_set(lpfc_mq_context_ring_size,
+		       &mq_create_ext->u.request.context,
+		       LPFC_MQ_RING_SIZE_32);
 		break;
 	case 64:
-		bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
-		       LPFC_MQ_CNT_64);
+		bf_set(lpfc_mq_context_ring_size,
+		       &mq_create_ext->u.request.context,
+		       LPFC_MQ_RING_SIZE_64);
 		break;
 	case 128:
-		bf_set(lpfc_mq_context_count, &mq_create_ext->u.request.context,
-		       LPFC_MQ_CNT_128);
+		bf_set(lpfc_mq_context_ring_size,
+		       &mq_create_ext->u.request.context,
+		       LPFC_MQ_RING_SIZE_128);
 		break;
 	}
 	list_for_each_entry(dmabuf, &mq->page_list, list) {
@@ -10640,7 +10756,6 @@
 					putPaddrHigh(dmabuf->phys);
 	}
 	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
-	shdr = (union lpfc_sli4_cfg_shdr *) &mq_create_ext->header.cfg_shdr;
 	mq->queue_id = bf_get(lpfc_mbx_mq_create_q_id,
 			      &mq_create_ext->u.response);
 	if (rc != MBX_SUCCESS) {
@@ -10672,6 +10787,7 @@
 		goto out;
 	}
 	mq->type = LPFC_MQ;
+	mq->assoc_qid = cq->queue_id;
 	mq->subtype = subtype;
 	mq->host_index = 0;
 	mq->hba_index = 0;
@@ -10716,6 +10832,7 @@
 	uint32_t shdr_status, shdr_add_status;
 	union lpfc_sli4_cfg_shdr *shdr;
 	uint32_t hw_page_size = phba->sli4_hba.pc_sli4_params.if_page_sz;
+	struct dma_address *page;
 
 	if (!phba->sli4_hba.pc_sli4_params.supported)
 		hw_page_size = SLI4_PAGE_SIZE;
@@ -10729,20 +10846,42 @@
 			 LPFC_MBOX_OPCODE_FCOE_WQ_CREATE,
 			 length, LPFC_SLI4_MBX_EMBED);
 	wq_create = &mbox->u.mqe.un.wq_create;
+	shdr = (union lpfc_sli4_cfg_shdr *) &wq_create->header.cfg_shdr;
 	bf_set(lpfc_mbx_wq_create_num_pages, &wq_create->u.request,
 		    wq->page_count);
 	bf_set(lpfc_mbx_wq_create_cq_id, &wq_create->u.request,
 		    cq->queue_id);
+	bf_set(lpfc_mbox_hdr_version, &shdr->request,
+	       phba->sli4_hba.pc_sli4_params.wqv);
+	if (phba->sli4_hba.pc_sli4_params.wqv == LPFC_Q_CREATE_VERSION_1) {
+		bf_set(lpfc_mbx_wq_create_wqe_count, &wq_create->u.request_1,
+		       wq->entry_count);
+		switch (wq->entry_size) {
+		default:
+		case 64:
+			bf_set(lpfc_mbx_wq_create_wqe_size,
+			       &wq_create->u.request_1,
+			       LPFC_WQ_WQE_SIZE_64);
+			break;
+		case 128:
+			bf_set(lpfc_mbx_wq_create_wqe_size,
+			       &wq_create->u.request_1,
+			       LPFC_WQ_WQE_SIZE_128);
+			break;
+		}
+		bf_set(lpfc_mbx_wq_create_page_size, &wq_create->u.request_1,
+		       (PAGE_SIZE/SLI4_PAGE_SIZE));
+		page = wq_create->u.request_1.page;
+	} else {
+		page = wq_create->u.request.page;
+	}
 	list_for_each_entry(dmabuf, &wq->page_list, list) {
 		memset(dmabuf->virt, 0, hw_page_size);
-		wq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
-					putPaddrLow(dmabuf->phys);
-		wq_create->u.request.page[dmabuf->buffer_tag].addr_hi =
-					putPaddrHigh(dmabuf->phys);
+		page[dmabuf->buffer_tag].addr_lo = putPaddrLow(dmabuf->phys);
+		page[dmabuf->buffer_tag].addr_hi = putPaddrHigh(dmabuf->phys);
 	}
 	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
 	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr = (union lpfc_sli4_cfg_shdr *) &wq_create->header.cfg_shdr;
 	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
 	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
 	if (shdr_status || shdr_add_status || rc) {
@@ -10759,6 +10898,7 @@
 		goto out;
 	}
 	wq->type = LPFC_WQ;
+	wq->assoc_qid = cq->queue_id;
 	wq->subtype = subtype;
 	wq->host_index = 0;
 	wq->hba_index = 0;
@@ -10819,37 +10959,51 @@
 			 LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
 			 length, LPFC_SLI4_MBX_EMBED);
 	rq_create = &mbox->u.mqe.un.rq_create;
-	switch (hrq->entry_count) {
-	default:
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2535 Unsupported RQ count. (%d)\n",
-				hrq->entry_count);
-		if (hrq->entry_count < 512)
-			return -EINVAL;
-		/* otherwise default to smallest count (drop through) */
-	case 512:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_512);
-		break;
-	case 1024:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_1024);
-		break;
-	case 2048:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_2048);
-		break;
-	case 4096:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_4096);
-		break;
+	shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
+	bf_set(lpfc_mbox_hdr_version, &shdr->request,
+	       phba->sli4_hba.pc_sli4_params.rqv);
+	if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
+		bf_set(lpfc_rq_context_rqe_count_1,
+		       &rq_create->u.request.context,
+		       hrq->entry_count);
+		rq_create->u.request.context.buffer_size = LPFC_HDR_BUF_SIZE;
+	} else {
+		switch (hrq->entry_count) {
+		default:
+			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+					"2535 Unsupported RQ count. (%d)\n",
+					hrq->entry_count);
+			if (hrq->entry_count < 512)
+				return -EINVAL;
+			/* otherwise default to smallest count (drop through) */
+		case 512:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_512);
+			break;
+		case 1024:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_1024);
+			break;
+		case 2048:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_2048);
+			break;
+		case 4096:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_4096);
+			break;
+		}
+		bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
+		       LPFC_HDR_BUF_SIZE);
 	}
 	bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
 	       cq->queue_id);
 	bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
 	       hrq->page_count);
-	bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
-	       LPFC_HDR_BUF_SIZE);
 	list_for_each_entry(dmabuf, &hrq->page_list, list) {
 		memset(dmabuf->virt, 0, hw_page_size);
 		rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
@@ -10859,7 +11013,6 @@
 	}
 	rc = lpfc_sli_issue_mbox(phba, mbox, MBX_POLL);
 	/* The IOCTL status is embedded in the mailbox subheader. */
-	shdr = (union lpfc_sli4_cfg_shdr *) &rq_create->header.cfg_shdr;
 	shdr_status = bf_get(lpfc_mbox_hdr_status, &shdr->response);
 	shdr_add_status = bf_get(lpfc_mbox_hdr_add_status, &shdr->response);
 	if (shdr_status || shdr_add_status || rc) {
@@ -10876,6 +11029,7 @@
 		goto out;
 	}
 	hrq->type = LPFC_HRQ;
+	hrq->assoc_qid = cq->queue_id;
 	hrq->subtype = subtype;
 	hrq->host_index = 0;
 	hrq->hba_index = 0;
@@ -10884,37 +11038,50 @@
 	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
 			 LPFC_MBOX_OPCODE_FCOE_RQ_CREATE,
 			 length, LPFC_SLI4_MBX_EMBED);
-	switch (drq->entry_count) {
-	default:
-		lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
-				"2536 Unsupported RQ count. (%d)\n",
-				drq->entry_count);
-		if (drq->entry_count < 512)
-			return -EINVAL;
-		/* otherwise default to smallest count (drop through) */
-	case 512:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_512);
-		break;
-	case 1024:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_1024);
-		break;
-	case 2048:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_2048);
-		break;
-	case 4096:
-		bf_set(lpfc_rq_context_rq_size, &rq_create->u.request.context,
-		       LPFC_RQ_RING_SIZE_4096);
-		break;
+	bf_set(lpfc_mbox_hdr_version, &shdr->request,
+	       phba->sli4_hba.pc_sli4_params.rqv);
+	if (phba->sli4_hba.pc_sli4_params.rqv == LPFC_Q_CREATE_VERSION_1) {
+		bf_set(lpfc_rq_context_rqe_count_1,
+		       &rq_create->u.request.context,
+		       hrq->entry_count);
+		rq_create->u.request.context.buffer_size = LPFC_DATA_BUF_SIZE;
+	} else {
+		switch (drq->entry_count) {
+		default:
+			lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
+					"2536 Unsupported RQ count. (%d)\n",
+					drq->entry_count);
+			if (drq->entry_count < 512)
+				return -EINVAL;
+			/* otherwise default to smallest count (drop through) */
+		case 512:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_512);
+			break;
+		case 1024:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_1024);
+			break;
+		case 2048:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_2048);
+			break;
+		case 4096:
+			bf_set(lpfc_rq_context_rqe_count,
+			       &rq_create->u.request.context,
+			       LPFC_RQ_RING_SIZE_4096);
+			break;
+		}
+		bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
+		       LPFC_DATA_BUF_SIZE);
 	}
 	bf_set(lpfc_rq_context_cq_id, &rq_create->u.request.context,
 	       cq->queue_id);
 	bf_set(lpfc_mbx_rq_create_num_pages, &rq_create->u.request,
 	       drq->page_count);
-	bf_set(lpfc_rq_context_buf_size, &rq_create->u.request.context,
-	       LPFC_DATA_BUF_SIZE);
 	list_for_each_entry(dmabuf, &drq->page_list, list) {
 		rq_create->u.request.page[dmabuf->buffer_tag].addr_lo =
 					putPaddrLow(dmabuf->phys);
@@ -10936,6 +11103,7 @@
 		goto out;
 	}
 	drq->type = LPFC_DRQ;
+	drq->assoc_qid = cq->queue_id;
 	drq->subtype = subtype;
 	drq->host_index = 0;
 	drq->hba_index = 0;
@@ -11189,7 +11357,7 @@
 	if (!mbox)
 		return -ENOMEM;
 	length = (sizeof(struct lpfc_mbx_rq_destroy) -
-		  sizeof(struct mbox_header));
+		  sizeof(struct lpfc_sli4_cfg_mhdr));
 	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
 			 LPFC_MBOX_OPCODE_FCOE_RQ_DESTROY,
 			 length, LPFC_SLI4_MBX_EMBED);
@@ -11279,7 +11447,7 @@
 	lpfc_sli4_config(phba, mbox, LPFC_MBOX_SUBSYSTEM_FCOE,
 			LPFC_MBOX_OPCODE_FCOE_POST_SGL_PAGES,
 			sizeof(struct lpfc_mbx_post_sgl_pages) -
-			sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED);
+			sizeof(struct lpfc_sli4_cfg_mhdr), LPFC_SLI4_MBX_EMBED);
 
 	post_sgl_pages = (struct lpfc_mbx_post_sgl_pages *)
 				&mbox->u.mqe.un.post_sgl_pages;
@@ -11582,6 +11750,7 @@
 	static char *rctl_names[] = FC_RCTL_NAMES_INIT;
 	char *type_names[] = FC_TYPE_NAMES_INIT;
 	struct fc_vft_header *fc_vft_hdr;
+	uint32_t *header = (uint32_t *) fc_hdr;
 
 	switch (fc_hdr->fh_r_ctl) {
 	case FC_RCTL_DD_UNCAT:		/* uncategorized information */
@@ -11630,10 +11799,15 @@
 	default:
 		goto drop;
 	}
+
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"2538 Received frame rctl:%s type:%s\n",
+			"2538 Received frame rctl:%s type:%s "
+			"Frame Data:%08x %08x %08x %08x %08x %08x\n",
 			rctl_names[fc_hdr->fh_r_ctl],
-			type_names[fc_hdr->fh_type]);
+			type_names[fc_hdr->fh_type],
+			be32_to_cpu(header[0]), be32_to_cpu(header[1]),
+			be32_to_cpu(header[2]), be32_to_cpu(header[3]),
+			be32_to_cpu(header[4]), be32_to_cpu(header[5]));
 	return 0;
 drop:
 	lpfc_printf_log(phba, KERN_WARNING, LOG_ELS,
@@ -11930,17 +12104,17 @@
 }
 
 /**
- * lpfc_sli4_seq_abort_acc_cmpl - Accept seq abort iocb complete handler
+ * lpfc_sli4_seq_abort_rsp_cmpl - BLS ABORT RSP seq abort iocb complete handler
  * @phba: Pointer to HBA context object.
  * @cmd_iocbq: pointer to the command iocbq structure.
  * @rsp_iocbq: pointer to the response iocbq structure.
  *
- * This function handles the sequence abort accept iocb command complete
+ * This function handles the sequence abort response iocb command complete
  * event. It properly releases the memory allocated to the sequence abort
  * accept iocb.
  **/
 static void
-lpfc_sli4_seq_abort_acc_cmpl(struct lpfc_hba *phba,
+lpfc_sli4_seq_abort_rsp_cmpl(struct lpfc_hba *phba,
 			     struct lpfc_iocbq *cmd_iocbq,
 			     struct lpfc_iocbq *rsp_iocbq)
 {
@@ -11949,15 +12123,15 @@
 }
 
 /**
- * lpfc_sli4_seq_abort_acc - Accept sequence abort
+ * lpfc_sli4_seq_abort_rsp - bls rsp to sequence abort
  * @phba: Pointer to HBA context object.
  * @fc_hdr: pointer to a FC frame header.
  *
- * This function sends a basic accept to a previous unsol sequence abort
+ * This function sends a basic response to a previous unsol sequence abort
  * event after aborting the sequence handling.
  **/
 static void
-lpfc_sli4_seq_abort_acc(struct lpfc_hba *phba,
+lpfc_sli4_seq_abort_rsp(struct lpfc_hba *phba,
 			struct fc_frame_header *fc_hdr)
 {
 	struct lpfc_iocbq *ctiocb = NULL;
@@ -11965,6 +12139,7 @@
 	uint16_t oxid, rxid;
 	uint32_t sid, fctl;
 	IOCB_t *icmd;
+	int rc;
 
 	if (!lpfc_is_link_up(phba))
 		return;
@@ -11985,7 +12160,7 @@
 		+ phba->sli4_hba.max_cfg_param.xri_base))
 		lpfc_set_rrq_active(phba, ndlp, rxid, oxid, 0);
 
-	/* Allocate buffer for acc iocb */
+	/* Allocate buffer for rsp iocb */
 	ctiocb = lpfc_sli_get_iocbq(phba);
 	if (!ctiocb)
 		return;
@@ -12010,32 +12185,54 @@
 
 	ctiocb->iocb_cmpl = NULL;
 	ctiocb->vport = phba->pport;
-	ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_acc_cmpl;
+	ctiocb->iocb_cmpl = lpfc_sli4_seq_abort_rsp_cmpl;
+	ctiocb->sli4_xritag = NO_XRI;
+
+	/* If the oxid maps to the FCP XRI range or if it is out of range,
+	 * send a BLS_RJT.  The driver no longer has that exchange.
+	 * Override the IOCB for a BA_RJT.
+	 */
+	if (oxid > (phba->sli4_hba.max_cfg_param.max_xri +
+		    phba->sli4_hba.max_cfg_param.xri_base) ||
+	    oxid > (lpfc_sli4_get_els_iocb_cnt(phba) +
+		    phba->sli4_hba.max_cfg_param.xri_base)) {
+		icmd->un.xseq64.w5.hcsw.Rctl = FC_RCTL_BA_RJT;
+		bf_set(lpfc_vndr_code, &icmd->un.bls_rsp, 0);
+		bf_set(lpfc_rsn_expln, &icmd->un.bls_rsp, FC_BA_RJT_INV_XID);
+		bf_set(lpfc_rsn_code, &icmd->un.bls_rsp, FC_BA_RJT_UNABLE);
+	}
 
 	if (fctl & FC_FC_EX_CTX) {
 		/* ABTS sent by responder to CT exchange, construction
 		 * of BA_ACC will use OX_ID from ABTS for the XRI_TAG
 		 * field and RX_ID from ABTS for RX_ID field.
 		 */
-		bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_RSP);
-		bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, rxid);
-		ctiocb->sli4_xritag = oxid;
+		bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_RSP);
+		bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, rxid);
 	} else {
 		/* ABTS sent by initiator to CT exchange, construction
 		 * of BA_ACC will need to allocate a new XRI as for the
 		 * XRI_TAG and RX_ID fields.
 		 */
-		bf_set(lpfc_abts_orig, &icmd->un.bls_acc, LPFC_ABTS_UNSOL_INT);
-		bf_set(lpfc_abts_rxid, &icmd->un.bls_acc, NO_XRI);
-		ctiocb->sli4_xritag = NO_XRI;
+		bf_set(lpfc_abts_orig, &icmd->un.bls_rsp, LPFC_ABTS_UNSOL_INT);
+		bf_set(lpfc_abts_rxid, &icmd->un.bls_rsp, NO_XRI);
 	}
-	bf_set(lpfc_abts_oxid, &icmd->un.bls_acc, oxid);
+	bf_set(lpfc_abts_oxid, &icmd->un.bls_rsp, oxid);
 
-	/* Xmit CT abts accept on exchange <xid> */
+	/* Xmit CT abts response on exchange <xid> */
 	lpfc_printf_log(phba, KERN_INFO, LOG_ELS,
-			"1200 Xmit CT ABTS ACC on exchange x%x Data: x%x\n",
-			CMD_XMIT_BLS_RSP64_CX, phba->link_state);
-	lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
+			"1200 Send BLS cmd x%x on oxid x%x Data: x%x\n",
+			icmd->un.xseq64.w5.hcsw.Rctl, oxid, phba->link_state);
+
+	rc = lpfc_sli_issue_iocb(phba, LPFC_ELS_RING, ctiocb, 0);
+	if (rc == IOCB_ERROR) {
+		lpfc_printf_log(phba, KERN_ERR, LOG_ELS,
+				"2925 Failed to issue CT ABTS RSP x%x on "
+				"xri x%x, Data x%x\n",
+				icmd->un.xseq64.w5.hcsw.Rctl, oxid,
+				phba->link_state);
+		lpfc_sli_release_iocbq(phba, ctiocb);
+	}
 }
 
 /**
@@ -12083,7 +12280,7 @@
 			lpfc_in_buf_free(phba, &dmabuf->dbuf);
 	}
 	/* Send basic accept (BA_ACC) to the abort requester */
-	lpfc_sli4_seq_abort_acc(phba, &fc_hdr);
+	lpfc_sli4_seq_abort_rsp(phba, &fc_hdr);
 }
 
 /**
@@ -12402,7 +12599,8 @@
 	lpfc_sli4_config(phba, mboxq, LPFC_MBOX_SUBSYSTEM_FCOE,
 			 LPFC_MBOX_OPCODE_FCOE_POST_HDR_TEMPLATE,
 			 sizeof(struct lpfc_mbx_post_hdr_tmpl) -
-			 sizeof(struct mbox_header), LPFC_SLI4_MBX_EMBED);
+			 sizeof(struct lpfc_sli4_cfg_mhdr),
+			 LPFC_SLI4_MBX_EMBED);
 	bf_set(lpfc_mbx_post_hdr_tmpl_page_cnt,
 	       hdr_tmpl, rpi_page->page_count);
 	bf_set(lpfc_mbx_post_hdr_tmpl_rpi_offset, hdr_tmpl,
@@ -12773,7 +12971,7 @@
  * record and processing it one at a time starting from the @fcf_index
  * for initial FCF discovery or fast FCF failover rediscovery.
  *
- * Return 0 if the mailbox command is submitted sucessfully, none 0
+ * Return 0 if the mailbox command is submitted successfully, none 0
  * otherwise.
  **/
 int
@@ -12834,7 +13032,7 @@
  * This routine is invoked to read an FCF record indicated by @fcf_index
  * and to use it for FLOGI roundrobin FCF failover.
  *
- * Return 0 if the mailbox command is submitted sucessfully, none 0
+ * Return 0 if the mailbox command is submitted successfully, none 0
  * otherwise.
  **/
 int
@@ -12880,7 +13078,7 @@
  * This routine is invoked to read an FCF record indicated by @fcf_index to
  * determine whether it's eligible for FLOGI roundrobin failover list.
  *
- * Return 0 if the mailbox command is submitted sucessfully, none 0
+ * Return 0 if the mailbox command is submitted successfully, none 0
  * otherwise.
  **/
 int
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_version.h linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_version.h
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_version.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_version.h	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 /*******************************************************************
  * This file is part of the Emulex Linux Device Driver for         *
  * Fibre Channel Host Bus Adapters.                                *
- * Copyright (C) 2004-2010 Emulex.  All rights reserved.           *
+ * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
  * EMULEX and SLI are trademarks of Emulex.                        *
  * www.emulex.com                                                  *
  *                                                                 *
@@ -18,7 +18,7 @@
  * included with this package.                                     *
  *******************************************************************/
 
-#define LPFC_DRIVER_VERSION "8.3.20"
+#define LPFC_DRIVER_VERSION "8.3.22"
 #define LPFC_DRIVER_NAME		"lpfc"
 #define LPFC_SP_DRIVER_HANDLER_NAME	"lpfc:sp"
 #define LPFC_FP_DRIVER_HANDLER_NAME	"lpfc:fp"
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_vport.c linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_vport.c
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/lpfc_vport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/lpfc_vport.c	2011-05-19 00:06:34.000000000 -0400
@@ -464,6 +464,7 @@
 	struct lpfc_hba   *phba = vport->phba;
 	struct lpfc_nodelist *ndlp = NULL, *next_ndlp = NULL;
 	long timeout;
+	struct Scsi_Host *shost = lpfc_shost_from_vport(vport);
 
 	ndlp = lpfc_findnode_did(vport, Fabric_DID);
 	if (ndlp && NLP_CHK_NODE_ACT(ndlp)
@@ -498,6 +499,9 @@
 	 * scsi_host_put() to release the vport.
 	 */
 	lpfc_mbx_unreg_vpi(vport);
+	spin_lock_irq(shost->host_lock);
+	vport->fc_flag |= FC_VPORT_NEEDS_INIT_VPI;
+	spin_unlock_irq(shost->host_lock);
 
 	lpfc_vport_set_state(vport, FC_VPORT_DISABLED);
 	lpfc_printf_vlog(vport, KERN_ERR, LOG_VPORT,
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/lpfc/Makefile linux-libre-2.6.39-gnu/drivers/scsi/lpfc/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/lpfc/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/lpfc/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,7 +1,7 @@
 #/*******************************************************************
 # * This file is part of the Emulex Linux Device Driver for         *
 # * Fibre Channel Host Bus Adapters.                                *
-# * Copyright (C) 2004-2006 Emulex.  All rights reserved.           *
+# * Copyright (C) 2004-2011 Emulex.  All rights reserved.           *
 # * EMULEX and SLI are trademarks of Emulex.                        *
 # * www.emulex.com                                                  *
 # *                                                                 *
@@ -19,10 +19,8 @@
 # *******************************************************************/
 ######################################################################
 
-ifneq ($(GCOV),)
-  EXTRA_CFLAGS += -fprofile-arcs -ftest-coverage
-  EXTRA_CFLAGS += -O0
-endif
+ccflags-$(GCOV) := -fprofile-arcs -ftest-coverage
+ccflags-$(GCOV) += -O0
 
 obj-$(CONFIG_SCSI_LPFC) := lpfc.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/Makefile linux-libre-2.6.39-gnu/drivers/scsi/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -40,6 +40,7 @@
 obj-$(CONFIG_LIBFCOE)		+= fcoe/
 obj-$(CONFIG_FCOE)		+= fcoe/
 obj-$(CONFIG_FCOE_FNIC)		+= fnic/
+obj-$(CONFIG_SCSI_BNX2X_FCOE)	+= libfc/ fcoe/ bnx2fc/
 obj-$(CONFIG_ISCSI_TCP) 	+= libiscsi.o	libiscsi_tcp.o iscsi_tcp.o
 obj-$(CONFIG_INFINIBAND_ISER) 	+= libiscsi.o
 obj-$(CONFIG_ISCSI_BOOT_SYSFS)	+= iscsi_boot_sysfs.o
@@ -165,7 +166,7 @@
 scsi_mod-$(CONFIG_SYSCTL)	+= scsi_sysctl.o
 scsi_mod-$(CONFIG_SCSI_PROC_FS)	+= scsi_proc.o
 scsi_mod-y			+= scsi_trace.o
-scsi_mod-$(CONFIG_PM_OPS)	+= scsi_pm.o
+scsi_mod-$(CONFIG_PM)		+= scsi_pm.o
 
 scsi_tgt-y			+= scsi_tgt_lib.o scsi_tgt_if.o
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/mbox_defs.h linux-libre-2.6.39-gnu/drivers/scsi/megaraid/mbox_defs.h
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/mbox_defs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid/mbox_defs.h	2011-05-19 00:06:34.000000000 -0400
@@ -660,7 +660,7 @@
  * @lparam	: logical drives parameters
  * @span	: span
  *
- * 8-LD logical drive with upto 8 spans
+ * 8-LD logical drive with up to 8 spans
  */
 typedef struct {
 	logdrv_param_t	lparam;
@@ -673,7 +673,7 @@
  * @lparam	: logical drives parameters
  * @span	: span
  *
- * 8-LD logical drive with upto 4 spans
+ * 8-LD logical drive with up to 4 spans
  */
 typedef struct {
 	logdrv_param_t	lparam;
@@ -720,7 +720,7 @@
  * @ldrv	: logical drives information
  * @pdrv	: physical drives information
  *
- * Disk array for 8LD logical drives with upto 8 spans
+ * Disk array for 8LD logical drives with up to 8 spans
  */
 typedef struct {
 	uint8_t			numldrv;
@@ -737,7 +737,7 @@
  * @ldrv	: logical drives information
  * @pdrv	: physical drives information
  *
- * Disk array for 8LD logical drives with upto 4 spans
+ * Disk array for 8LD logical drives with up to 4 spans
  */
 typedef struct {
 	uint8_t			numldrv;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_mbox.c linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_mbox.c
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_mbox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_mbox.c	2011-05-19 00:06:34.000000000 -0400
@@ -2689,7 +2689,7 @@
 				(MBOX_RESET_WAIT + MBOX_RESET_EXT_WAIT) - i));
 		}
 
-		// bailout if no recovery happended in reset time
+		// bailout if no recovery happened in reset time
 		if (adapter->outstanding_cmds == 0) {
 			break;
 		}
@@ -3452,7 +3452,7 @@
  * megaraid_mbox_setup_device_map - manage device ids
  * @adapter	: Driver's soft state
  *
- * Manange the device ids to have an appropraite mapping between the kernel
+ * Manange the device ids to have an appropriate mapping between the kernel
  * scsi addresses and megaraid scsi and logical drive addresses. We export
  * scsi devices on their actual addresses, whereas the logical drives are
  * exported on a virtual scsi channel.
@@ -3973,7 +3973,7 @@
  * NOTE: The commands issuance functionality is not generalized and
  * implemented in context of "get ld map" command only. If required, the
  * command issuance logical can be trivially pulled out and implemented as a
- * standalone libary. For now, this should suffice since there is no other
+ * standalone library. For now, this should suffice since there is no other
  * user of this interface.
  *
  * Return 0 on success.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_base.c linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas_base.c
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas_base.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,12 +18,13 @@
  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  *
  *  FILE: megaraid_sas_base.c
- *  Version : v00.00.05.29-rc1
+ *  Version : v00.00.05.34-rc1
  *
  *  Authors: LSI Corporation
  *           Sreenivas Bagalkote
  *           Sumant Patro
  *           Bo Yang
+ *           Adam Radford <linuxraid@lsi.com>
  *
  *  Send feedback to: <megaraidlinux@lsi.com>
  *
@@ -134,7 +135,11 @@
 void
 megasas_complete_cmd(struct megasas_instance *instance, struct megasas_cmd *cmd,
 		     u8 alt_status);
-
+static u32
+megasas_read_fw_status_reg_gen2(struct megasas_register_set __iomem *regs);
+static int
+megasas_adp_reset_gen2(struct megasas_instance *instance,
+		       struct megasas_register_set __iomem *reg_set);
 static irqreturn_t megasas_isr(int irq, void *devp);
 static u32
 megasas_init_adapter_mfi(struct megasas_instance *instance);
@@ -554,6 +559,8 @@
 megasas_clear_intr_skinny(struct megasas_register_set __iomem *regs)
 {
 	u32 status;
+	u32 mfiStatus = 0;
+
 	/*
 	 * Check if it is our interrupt
 	 */
@@ -564,6 +571,15 @@
 	}
 
 	/*
+	 * Check if it is our interrupt
+	 */
+	if ((megasas_read_fw_status_reg_gen2(regs) & MFI_STATE_MASK) ==
+	    MFI_STATE_FAULT) {
+		mfiStatus = MFI_INTR_FLAG_FIRMWARE_STATE_CHANGE;
+	} else
+		mfiStatus = MFI_INTR_FLAG_REPLY_MESSAGE;
+
+	/*
 	 * Clear the interrupt by writing back the same value
 	 */
 	writel(status, &regs->outbound_intr_status);
@@ -573,7 +589,7 @@
 	*/
 	readl(&regs->outbound_intr_status);
 
-	return 1;
+	return mfiStatus;
 }
 
 /**
@@ -597,17 +613,6 @@
 }
 
 /**
- * megasas_adp_reset_skinny -	For controller reset
- * @regs:				MFI register set
- */
-static int
-megasas_adp_reset_skinny(struct megasas_instance *instance,
-			struct megasas_register_set __iomem *regs)
-{
-	return 0;
-}
-
-/**
  * megasas_check_reset_skinny -	For controller reset check
  * @regs:				MFI register set
  */
@@ -625,7 +630,7 @@
 	.disable_intr = megasas_disable_intr_skinny,
 	.clear_intr = megasas_clear_intr_skinny,
 	.read_fw_status_reg = megasas_read_fw_status_reg_skinny,
-	.adp_reset = megasas_adp_reset_skinny,
+	.adp_reset = megasas_adp_reset_gen2,
 	.check_reset = megasas_check_reset_skinny,
 	.service_isr = megasas_isr,
 	.tasklet = megasas_complete_cmd_dpc,
@@ -740,20 +745,28 @@
 {
 	u32			retry = 0 ;
 	u32			HostDiag;
+	u32			*seq_offset = &reg_set->seq_offset;
+	u32			*hostdiag_offset = &reg_set->host_diag;
+
+	if (instance->instancet == &megasas_instance_template_skinny) {
+		seq_offset = &reg_set->fusion_seq_offset;
+		hostdiag_offset = &reg_set->fusion_host_diag;
+	}
+
+	writel(0, seq_offset);
+	writel(4, seq_offset);
+	writel(0xb, seq_offset);
+	writel(2, seq_offset);
+	writel(7, seq_offset);
+	writel(0xd, seq_offset);
 
-	writel(0, &reg_set->seq_offset);
-	writel(4, &reg_set->seq_offset);
-	writel(0xb, &reg_set->seq_offset);
-	writel(2, &reg_set->seq_offset);
-	writel(7, &reg_set->seq_offset);
-	writel(0xd, &reg_set->seq_offset);
 	msleep(1000);
 
-	HostDiag = (u32)readl(&reg_set->host_diag);
+	HostDiag = (u32)readl(hostdiag_offset);
 
 	while ( !( HostDiag & DIAG_WRITE_ENABLE) ) {
 		msleep(100);
-		HostDiag = (u32)readl(&reg_set->host_diag);
+		HostDiag = (u32)readl(hostdiag_offset);
 		printk(KERN_NOTICE "RESETGEN2: retry=%x, hostdiag=%x\n",
 					retry, HostDiag);
 
@@ -764,14 +777,14 @@
 
 	printk(KERN_NOTICE "ADP_RESET_GEN2: HostDiag=%x\n", HostDiag);
 
-	writel((HostDiag | DIAG_RESET_ADAPTER), &reg_set->host_diag);
+	writel((HostDiag | DIAG_RESET_ADAPTER), hostdiag_offset);
 
 	ssleep(10);
 
-	HostDiag = (u32)readl(&reg_set->host_diag);
+	HostDiag = (u32)readl(hostdiag_offset);
 	while ( ( HostDiag & DIAG_RESET_ADAPTER) ) {
 		msleep(100);
-		HostDiag = (u32)readl(&reg_set->host_diag);
+		HostDiag = (u32)readl(hostdiag_offset);
 		printk(KERN_NOTICE "RESET_GEN2: retry=%x, hostdiag=%x\n",
 				retry, HostDiag);
 
@@ -877,7 +890,7 @@
  * @instance:				Adapter soft state
  * @cmd_to_abort:			Previously issued cmd to be aborted
  *
- * MFI firmware can abort previously issued AEN comamnd (automatic event
+ * MFI firmware can abort previously issued AEN command (automatic event
  * notification). The megasas_issue_blocked_abort_cmd() issues such abort
  * cmd and waits for return status.
  * Max wait time is MEGASAS_INTERNAL_CMD_WAIT_TIME secs
@@ -1685,7 +1698,7 @@
  * megasas_wait_for_outstanding -	Wait for all outstanding cmds
  * @instance:				Adapter soft state
  *
- * This function waits for upto MEGASAS_RESET_WAIT_TIME seconds for FW to
+ * This function waits for up to MEGASAS_RESET_WAIT_TIME seconds for FW to
  * complete all its outstanding commands. Returns error if one or more IOs
  * are pending after this time period. It also marks the controller dead.
  */
@@ -2503,7 +2516,9 @@
 	if ((mfiStatus = instance->instancet->clear_intr(
 						instance->reg_set)
 						) == 0) {
-		return IRQ_NONE;
+		/* Hardware may not set outbound_intr_status in MSI-X mode */
+		if (!instance->msi_flag)
+			return IRQ_NONE;
 	}
 
 	instance->mfiStatus = mfiStatus;
@@ -2611,7 +2626,9 @@
 		case MFI_STATE_FAULT:
 
 			printk(KERN_DEBUG "megasas: FW in FAULT state!!\n");
-			return -ENODEV;
+			max_wait = MEGASAS_RESET_WAIT_TIME;
+			cur_state = MFI_STATE_FAULT;
+			break;
 
 		case MFI_STATE_WAIT_HANDSHAKE:
 			/*
@@ -3424,7 +3441,6 @@
 	megasas_free_cmds(instance);
 
 fail_alloc_cmds:
-	iounmap(instance->reg_set);
 	return 1;
 }
 
@@ -3494,7 +3510,7 @@
 
 	/* Get operational params, sge flags, send init cmd to controller */
 	if (instance->instancet->init_adapter(instance))
-		return -ENODEV;
+		goto fail_init_adapter;
 
 	printk(KERN_ERR "megasas: INIT adapter done\n");
 
@@ -3543,7 +3559,7 @@
 	* Setup tasklet for cmd completion
 	*/
 
-	tasklet_init(&instance->isr_tasklet, megasas_complete_cmd_dpc,
+	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
 		(unsigned long)instance);
 
 	/* Initialize the cmd completion timer */
@@ -3553,6 +3569,7 @@
 				MEGASAS_COMPLETION_TIMER_INTERVAL);
 	return 0;
 
+fail_init_adapter:
 fail_ready_state:
 	iounmap(instance->reg_set);
 
@@ -3820,6 +3837,10 @@
 			instance->max_fw_cmds - MEGASAS_INT_CMDS;
 	host->this_id = instance->init_id;
 	host->sg_tablesize = instance->max_num_sge;
+
+	if (instance->fw_support_ieee)
+		instance->max_sectors_per_req = MEGASAS_MAX_SECTORS_IEEE;
+
 	/*
 	 * Check if the module parameter value for max_sectors can be used
 	 */
@@ -3899,9 +3920,26 @@
 static int __devinit
 megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-	int rval;
+	int rval, pos;
 	struct Scsi_Host *host;
 	struct megasas_instance *instance;
+	u16 control = 0;
+
+	/* Reset MSI-X in the kdump kernel */
+	if (reset_devices) {
+		pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
+		if (pos) {
+			pci_read_config_word(pdev, msi_control_reg(pos),
+					     &control);
+			if (control & PCI_MSIX_FLAGS_ENABLE) {
+				dev_info(&pdev->dev, "resetting MSI-X\n");
+				pci_write_config_word(pdev,
+						      msi_control_reg(pos),
+						      control &
+						      ~PCI_MSIX_FLAGS_ENABLE);
+			}
+		}
+	}
 
 	/*
 	 * Announce PCI information
@@ -4039,12 +4077,6 @@
 	else
 		INIT_WORK(&instance->work_init, process_fw_state_change_wq);
 
-	/*
-	 * Initialize MFI Firmware
-	 */
-	if (megasas_init_fw(instance))
-		goto fail_init_mfi;
-
 	/* Try to enable MSI-X */
 	if ((instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078R) &&
 	    (instance->pdev->device != PCI_DEVICE_ID_LSI_SAS1078DE) &&
@@ -4054,6 +4086,12 @@
 		instance->msi_flag = 1;
 
 	/*
+	 * Initialize MFI Firmware
+	 */
+	if (megasas_init_fw(instance))
+		goto fail_init_mfi;
+
+	/*
 	 * Register IRQ
 	 */
 	if (request_irq(instance->msi_flag ? instance->msixentry.vector :
@@ -4105,24 +4143,23 @@
 	instance->instancet->disable_intr(instance->reg_set);
 	free_irq(instance->msi_flag ? instance->msixentry.vector :
 		 instance->pdev->irq, instance);
+fail_irq:
+	if (instance->pdev->device == PCI_DEVICE_ID_LSI_FUSION)
+		megasas_release_fusion(instance);
+	else
+		megasas_release_mfi(instance);
+      fail_init_mfi:
 	if (instance->msi_flag)
 		pci_disable_msix(instance->pdev);
-
-      fail_irq:
-      fail_init_mfi:
       fail_alloc_dma_buf:
 	if (instance->evt_detail)
 		pci_free_consistent(pdev, sizeof(struct megasas_evt_detail),
 				    instance->evt_detail,
 				    instance->evt_detail_h);
 
-	if (instance->producer) {
+	if (instance->producer)
 		pci_free_consistent(pdev, sizeof(u32), instance->producer,
 				    instance->producer_h);
-		megasas_release_mfi(instance);
-	} else {
-		megasas_release_fusion(instance);
-	}
 	if (instance->consumer)
 		pci_free_consistent(pdev, sizeof(u32), instance->consumer,
 				    instance->consumer_h);
@@ -4242,9 +4279,8 @@
 	/* cancel the delayed work if this work still in queue */
 	if (instance->ev != NULL) {
 		struct megasas_aen_event *ev = instance->ev;
-		cancel_delayed_work(
+		cancel_delayed_work_sync(
 			(struct delayed_work *)&ev->hotplug_work);
-		flush_scheduled_work();
 		instance->ev = NULL;
 	}
 
@@ -4297,6 +4333,10 @@
 	if (megasas_set_dma_mask(pdev))
 		goto fail_set_dma_mask;
 
+	/* Now re-enable MSI-X */
+	if (instance->msi_flag)
+		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
+
 	/*
 	 * Initialize MFI Firmware
 	 */
@@ -4333,10 +4373,6 @@
 	tasklet_init(&instance->isr_tasklet, instance->instancet->tasklet,
 		     (unsigned long)instance);
 
-	/* Now re-enable MSI-X */
-	if (instance->msi_flag)
-		pci_enable_msix(instance->pdev, &instance->msixentry, 1);
-
 	/*
 	 * Register IRQ
 	 */
@@ -4417,9 +4453,8 @@
 	/* cancel the delayed work if this work still in queue*/
 	if (instance->ev != NULL) {
 		struct megasas_aen_event *ev = instance->ev;
-		cancel_delayed_work(
+		cancel_delayed_work_sync(
 			(struct delayed_work *)&ev->hotplug_work);
-		flush_scheduled_work();
 		instance->ev = NULL;
 	}
 
@@ -4611,6 +4646,9 @@
 	 * For each user buffer, create a mirror buffer and copy in
 	 */
 	for (i = 0; i < ioc->sge_count; i++) {
+		if (!ioc->sgl[i].iov_len)
+			continue;
+
 		kbuff_arr[i] = dma_alloc_coherent(&instance->pdev->dev,
 						    ioc->sgl[i].iov_len,
 						    &buf_handle, GFP_KERNEL);
@@ -5177,6 +5215,7 @@
 			break;
 
 		case MR_EVT_LD_OFFLINE:
+		case MR_EVT_CFG_CLEARED:
 		case MR_EVT_LD_DELETED:
 			megasas_get_ld_list(instance);
 			for (i = 0; i < MEGASAS_MAX_LD_CHANNELS; i++) {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_fp.c linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas_fp.c
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_fp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas_fp.c	2011-05-19 00:06:34.000000000 -0400
@@ -39,7 +39,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas_fusion.c	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,6 @@
 #include <linux/spinlock.h>
 #include <linux/interrupt.h>
 #include <linux/delay.h>
-#include <linux/smp_lock.h>
 #include <linux/uio.h>
 #include <linux/uaccess.h>
 #include <linux/fs.h>
@@ -82,6 +81,10 @@
 struct MR_LD_RAID *MR_LdRaidGet(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
 
 u16 MR_GetLDTgtId(u32 ld, struct MR_FW_RAID_MAP_ALL *map);
+
+void
+megasas_check_and_restore_queue_depth(struct megasas_instance *instance);
+
 u8 MR_ValidateMapInfo(struct MR_FW_RAID_MAP_ALL *map,
 		      struct LD_LOAD_BALANCE_INFO *lbInfo);
 u16 get_updated_dev_handle(struct LD_LOAD_BALANCE_INFO *lbInfo,
@@ -984,13 +987,15 @@
 
 	return 0;
 
-fail_alloc_cmds:
-fail_alloc_mfi_cmds:
 fail_map_info:
 	if (i == 1)
 		dma_free_coherent(&instance->pdev->dev, fusion->map_sz,
 				  fusion->ld_map[0], fusion->ld_map_phys[0]);
 fail_ioc_init:
+	megasas_free_cmds_fusion(instance);
+fail_alloc_cmds:
+	megasas_free_cmds(instance);
+fail_alloc_mfi_cmds:
 	return 1;
 }
 
@@ -1432,8 +1437,7 @@
 	local_map_ptr = fusion->ld_map[(instance->map_id & 1)];
 
 	/* Check if this is a system PD I/O */
-	if ((instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) &&
-	    (instance->pd_list[pd_index].driveType == TYPE_DISK)) {
+	if (instance->pd_list[pd_index].driveState == MR_PD_STATE_SYSTEM) {
 		io_request->Function = 0;
 		io_request->DevHandle =
 			local_map_ptr->raidMap.devHndlInfo[device_id].curDevHdl;
@@ -1456,7 +1460,7 @@
 			 MEGASAS_REQ_DESCRIPT_FLAGS_TYPE_SHIFT);
 	}
 	io_request->RaidContext.VirtualDiskTgtId = device_id;
-	io_request->LUN[0] = scmd->device->lun;
+	io_request->LUN[1] = scmd->device->lun;
 	io_request->DataLength = scsi_bufflen(scmd);
 }
 
@@ -1480,7 +1484,7 @@
 	device_id = MEGASAS_DEV_INDEX(instance, scp);
 
 	/* Zero out some fields so they don't get reused */
-	io_request->LUN[0] = 0;
+	io_request->LUN[1] = 0;
 	io_request->CDB.EEDP32.PrimaryReferenceTag = 0;
 	io_request->CDB.EEDP32.PrimaryApplicationTagMask = 0;
 	io_request->EEDPFlags = 0;
@@ -1744,7 +1748,7 @@
 	wmb();
 	writel(fusion->last_reply_idx,
 	       &instance->reg_set->reply_post_host_index);
-
+	megasas_check_and_restore_queue_depth(instance);
 	return IRQ_HANDLED;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas.h linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas.h
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid/megaraid_sas.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid/megaraid_sas.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,9 +33,9 @@
 /*
  * MegaRAID SAS Driver meta data
  */
-#define MEGASAS_VERSION				"00.00.05.29-rc1"
-#define MEGASAS_RELDATE				"Dec. 7, 2010"
-#define MEGASAS_EXT_VERSION			"Tue. Dec. 7 17:00:00 PDT 2010"
+#define MEGASAS_VERSION				"00.00.05.34-rc1"
+#define MEGASAS_RELDATE				"Feb. 24, 2011"
+#define MEGASAS_EXT_VERSION			"Thu. Feb. 24 17:00:00 PDT 2011"
 
 /*
  * Device IDs
@@ -723,6 +723,7 @@
 						MEGASAS_MAX_DEV_PER_CHANNEL)
 
 #define MEGASAS_MAX_SECTORS                    (2*1024)
+#define MEGASAS_MAX_SECTORS_IEEE		(2*128)
 #define MEGASAS_DBG_LVL				1
 
 #define MEGASAS_FW_BUSY				1
@@ -1346,7 +1347,7 @@
 	struct timer_list io_completion_timer;
 	struct list_head internal_reset_pending_q;
 
-	/* Ptr to hba specfic information */
+	/* Ptr to hba specific information */
 	void *ctrl_context;
 	u8	msi_flag;
 	struct msix_entry msixentry;
@@ -1477,4 +1478,7 @@
 	int max_index;
 };
 
+#define msi_control_reg(base) (base + PCI_MSI_FLAGS)
+#define PCI_MSIX_FLAGS_ENABLE (1 << 15)
+
 #endif				/*LSI_MEGARAID_SAS_H */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid.c linux-libre-2.6.39-gnu/drivers/scsi/megaraid.c
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid.c	2011-05-19 00:06:34.000000000 -0400
@@ -284,7 +284,7 @@
 
 	adapter->host->max_id = 16;	/* max targets per channel */
 
-	adapter->host->max_lun = 7;	/* Upto 7 luns for non disk devices */
+	adapter->host->max_lun = 7;	/* Up to 7 luns for non disk devices */
 
 	adapter->host->cmd_per_lun = max_cmd_per_lun;
 
@@ -1412,7 +1412,7 @@
  * @nstatus - number of completed commands
  * @status - status of the last command completed
  *
- * Complete the comamnds and call the scsi mid-layer callback hooks.
+ * Complete the commands and call the scsi mid-layer callback hooks.
  */
 static void
 mega_cmd_done(adapter_t *adapter, u8 completed[], int nstatus, int status)
@@ -3734,7 +3734,7 @@
 	 * check is the application conforms to NIT. We do not have to do much
 	 * in that case.
 	 * We exploit the fact that the signature is stored in the very
-	 * begining of the structure.
+	 * beginning of the structure.
 	 */
 
 	if( copy_from_user(signature, arg, 7) )
@@ -4296,7 +4296,7 @@
  * @adapter - pointer to our soft state
  * @dma_handle - DMA address of the buffer
  *
- * Issue internal comamnds while interrupts are available.
+ * Issue internal commands while interrupts are available.
  * We only issue direct mailbox commands from within the driver. ioctl()
  * interface using these routines can issue passthru commands.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/megaraid.h linux-libre-2.6.39-gnu/drivers/scsi/megaraid.h
--- linux-libre-2.6.38-gnu/drivers/scsi/megaraid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/megaraid.h	2011-05-19 00:06:34.000000000 -0400
@@ -532,9 +532,9 @@
 
 /*
  * struct mcontroller is used to pass information about the controllers in the
- * system. Its upto the application how to use the information. We are passing
+ * system. Its up to the application how to use the information. We are passing
  * as much info about the cards as possible and useful. Before issuing the
- * call to find information about the cards, the applicaiton needs to issue a
+ * call to find information about the cards, the application needs to issue a
  * ioctl first to find out the number of controllers in the system.
  */
 #define MAX_CONTROLLERS 32
@@ -804,7 +804,7 @@
 	unsigned long		base;
 	void __iomem		*mmio_base;
 
-	/* mbox64 with mbox not aligned on 16-byte boundry */
+	/* mbox64 with mbox not aligned on 16-byte boundary */
 	mbox64_t	*una_mbox64;
 	dma_addr_t	una_mbox64_dma;
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_cnfg.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  *          Title:  MPI Configuration messages and pages
  *  Creation Date:  November 10, 2006
  *
- *    mpi2_cnfg.h Version:  02.00.15
+ *    mpi2_cnfg.h Version:  02.00.16
  *
  *  Version History
  *  ---------------
@@ -125,6 +125,8 @@
  *                      define.
  *                      Added MPI2_PHYSDISK0_INCOMPATIBLE_MEDIA_TYPE define.
  *                      Added MPI2_SAS_NEG_LINK_RATE_UNSUPPORTED_PHY define.
+ *  08-11-10  02.00.16  Removed IO Unit Page 1 device path (multi-pathing)
+ *                      defines.
  *  --------------------------------------------------------------------------
  */
 
@@ -745,8 +747,6 @@
 #define MPI2_IOUNITPAGE1_DISABLE_IR                     (0x00000040)
 #define MPI2_IOUNITPAGE1_DISABLE_TASK_SET_FULL_HANDLING (0x00000020)
 #define MPI2_IOUNITPAGE1_IR_USE_STATIC_VOLUME_ID        (0x00000004)
-#define MPI2_IOUNITPAGE1_MULTI_PATHING                  (0x00000002)
-#define MPI2_IOUNITPAGE1_SINGLE_PATHING                 (0x00000000)
 
 
 /* IO Unit Page 3 */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2.h linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2.h
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2.h	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
  *                  scatter/gather formats.
  *  Creation Date:  June 21, 2006
  *
- *  mpi2.h Version:  02.00.16
+ *  mpi2.h Version:  02.00.17
  *
  *  Version History
  *  ---------------
@@ -63,6 +63,7 @@
  *                      function codes, 0xF0 to 0xFF.
  *  05-12-10  02.00.16  Bumped MPI2_HEADER_VERSION_UNIT.
  *                      Added alternative defines for the SGE Direction bit.
+ *  08-11-10  02.00.17  Bumped MPI2_HEADER_VERSION_UNIT.
  *  --------------------------------------------------------------------------
  */
 
@@ -88,7 +89,7 @@
 #define MPI2_VERSION_02_00                  (0x0200)
 
 /* versioning for this MPI header set */
-#define MPI2_HEADER_VERSION_UNIT            (0x10)
+#define MPI2_HEADER_VERSION_UNIT            (0x11)
 #define MPI2_HEADER_VERSION_DEV             (0x00)
 #define MPI2_HEADER_VERSION_UNIT_MASK       (0xFF00)
 #define MPI2_HEADER_VERSION_UNIT_SHIFT      (8)
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_history.txt linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_history.txt
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_history.txt	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_history.txt	1969-12-31 19:00:00.000000000 -0500
@@ -1,384 +0,0 @@
- ==============================
- Fusion-MPT MPI 2.0 Header File Change History
- ==============================
-
- Copyright (c) 2000-2010 LSI Corporation.
-
- ---------------------------------------
- Header Set Release Version:    02.00.14
- Header Set Release Date:       10-28-09
- ---------------------------------------
-
- Filename               Current version     Prior version
- ----------             ---------------     -------------
- mpi2.h                 02.00.14            02.00.13
- mpi2_cnfg.h            02.00.13            02.00.12
- mpi2_init.h            02.00.08            02.00.07
- mpi2_ioc.h             02.00.13            02.00.12
- mpi2_raid.h            02.00.04            02.00.04
- mpi2_sas.h             02.00.03            02.00.02
- mpi2_targ.h            02.00.03            02.00.03
- mpi2_tool.h            02.00.04            02.00.04
- mpi2_type.h            02.00.00            02.00.00
- mpi2_ra.h              02.00.00            02.00.00
- mpi2_hbd.h             02.00.00
- mpi2_history.txt       02.00.14            02.00.13
-
-
- *  Date      Version   Description
- *  --------  --------  ------------------------------------------------------
-
-mpi2.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-04-07  02.00.01  Bumped MPI2_HEADER_VERSION_UNIT.
- *  06-26-07  02.00.02  Bumped MPI2_HEADER_VERSION_UNIT.
- *  08-31-07  02.00.03  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Moved ReplyPostHostIndex register to offset 0x6C of the
- *                      MPI2_SYSTEM_INTERFACE_REGS and modified the define for
- *                      MPI2_REPLY_POST_HOST_INDEX_OFFSET.
- *                      Added union of request descriptors.
- *                      Added union of reply descriptors.
- *  10-31-07  02.00.04  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added define for MPI2_VERSION_02_00.
- *                      Fixed the size of the FunctionDependent5 field in the
- *                      MPI2_DEFAULT_REPLY structure.
- *  12-18-07  02.00.05  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Removed the MPI-defined Fault Codes and extended the
- *                      product specific codes up to 0xEFFF.
- *                      Added a sixth key value for the WriteSequence register
- *                      and changed the flush value to 0x0.
- *                      Added message function codes for Diagnostic Buffer Post
- *                      and Diagnsotic Release.
- *                      New IOCStatus define: MPI2_IOCSTATUS_DIAGNOSTIC_RELEASED
- *                      Moved MPI2_VERSION_UNION from mpi2_ioc.h.
- *  02-29-08  02.00.06  Bumped MPI2_HEADER_VERSION_UNIT.
- *  03-03-08  02.00.07  Bumped MPI2_HEADER_VERSION_UNIT.
- *  05-21-08  02.00.08  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added #defines for marking a reply descriptor as unused.
- *  06-27-08  02.00.09  Bumped MPI2_HEADER_VERSION_UNIT.
- *  10-02-08  02.00.10  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Moved LUN field defines from mpi2_init.h.
- *  01-19-09  02.00.11  Bumped MPI2_HEADER_VERSION_UNIT.
- *  05-06-09  02.00.12  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      In all request and reply descriptors, replaced VF_ID
- *                      field with MSIxIndex field.
- *                      Removed DevHandle field from
- *                      MPI2_SCSI_IO_SUCCESS_REPLY_DESCRIPTOR and made those
- *                      bytes reserved.
- *                      Added RAID Accelerator functionality.
- *  07-30-09  02.00.13  Bumped MPI2_HEADER_VERSION_UNIT.
- *  10-28-09  02.00.14  Bumped MPI2_HEADER_VERSION_UNIT.
- *                      Added MSI-x index mask and shift for Reply Post Host
- *                      Index register.
- *                      Added function code for Host Based Discovery Action.
- *  --------------------------------------------------------------------------
-
-mpi2_cnfg.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-04-07  02.00.01  Added defines for SAS IO Unit Page 2 PhyFlags.
- *                      Added Manufacturing Page 11.
- *                      Added MPI2_SAS_EXPANDER0_FLAGS_CONNECTOR_END_DEVICE
- *                      define.
- *  06-26-07  02.00.02  Adding generic structure for product-specific
- *                      Manufacturing pages: MPI2_CONFIG_PAGE_MANUFACTURING_PS.
- *                      Rework of BIOS Page 2 configuration page.
- *                      Fixed MPI2_BIOSPAGE2_BOOT_DEVICE to be a union of the
- *                      forms.
- *                      Added configuration pages IOC Page 8 and Driver
- *                      Persistent Mapping Page 0.
- *  08-31-07  02.00.03  Modified configuration pages dealing with Integrated
- *                      RAID (Manufacturing Page 4, RAID Volume Pages 0 and 1,
- *                      RAID Physical Disk Pages 0 and 1, RAID Configuration
- *                      Page 0).
- *                      Added new value for AccessStatus field of SAS Device
- *                      Page 0 (_SATA_NEEDS_INITIALIZATION).
- *  10-31-07  02.00.04  Added missing SEPDevHandle field to
- *                      MPI2_CONFIG_PAGE_SAS_ENCLOSURE_0.
- *  12-18-07  02.00.05  Modified IO Unit Page 0 to use 32-bit version fields for
- *                      NVDATA.
- *                      Modified IOC Page 7 to use masks and added field for
- *                      SASBroadcastPrimitiveMasks.
- *                      Added MPI2_CONFIG_PAGE_BIOS_4.
- *                      Added MPI2_CONFIG_PAGE_LOG_0.
- *  02-29-08  02.00.06  Modified various names to make them 32-character unique.
- *                      Added SAS Device IDs.
- *                      Updated Integrated RAID configuration pages including
- *                      Manufacturing Page 4, IOC Page 6, and RAID Configuration
- *                      Page 0.
- *  05-21-08  02.00.07  Added define MPI2_MANPAGE4_MIX_SSD_SAS_SATA.
- *                      Added define MPI2_MANPAGE4_PHYSDISK_128MB_COERCION.
- *                      Fixed define MPI2_IOCPAGE8_FLAGS_ENCLOSURE_SLOT_MAPPING.
- *                      Added missing MaxNumRoutedSasAddresses field to
- *                      MPI2_CONFIG_PAGE_EXPANDER_0.
- *                      Added SAS Port Page 0.
- *                      Modified structure layout for
- *                      MPI2_CONFIG_PAGE_DRIVER_MAPPING_0.
- *  06-27-08  02.00.08  Changed MPI2_CONFIG_PAGE_RD_PDISK_1 to use
- *                      MPI2_RAID_PHYS_DISK1_PATH_MAX to size the array.
- *  10-02-08  02.00.09  Changed MPI2_RAID_PGAD_CONFIGNUM_MASK from 0x0000FFFF
- *                      to 0x000000FF.
- *                      Added two new values for the Physical Disk Coercion Size
- *                      bits in the Flags field of Manufacturing Page 4.
- *                      Added product-specific Manufacturing pages 16 to 31.
- *                      Modified Flags bits for controlling write cache on SATA
- *                      drives in IO Unit Page 1.
- *                      Added new bit to AdditionalControlFlags of SAS IO Unit
- *                      Page 1 to control Invalid Topology Correction.
- *                      Added SupportedPhysDisks field to RAID Volume Page 1 and
- *                      added related defines.
- *                      Added additional defines for RAID Volume Page 0
- *                      VolumeStatusFlags field.
- *                      Modified meaning of RAID Volume Page 0 VolumeSettings
- *                      define for auto-configure of hot-swap drives.
- *                      Added PhysDiskAttributes field (and related defines) to
- *                      RAID Physical Disk Page 0.
- *                      Added MPI2_SAS_PHYINFO_PHY_VACANT define.
- *                      Added three new DiscoveryStatus bits for SAS IO Unit
- *                      Page 0 and SAS Expander Page 0.
- *                      Removed multiplexing information from SAS IO Unit pages.
- *                      Added BootDeviceWaitTime field to SAS IO Unit Page 4.
- *                      Removed Zone Address Resolved bit from PhyInfo and from
- *                      Expander Page 0 Flags field.
- *                      Added two new AccessStatus values to SAS Device Page 0
- *                      for indicating routing problems. Added 3 reserved words
- *                      to this page.
- *  01-19-09  02.00.10  Fixed defines for GPIOVal field of IO Unit Page 3.
- *                      Inserted missing reserved field into structure for IOC
- *                      Page 6.
- *                      Added more pending task bits to RAID Volume Page 0
- *                      VolumeStatusFlags defines.
- *                      Added MPI2_PHYSDISK0_STATUS_FLAG_NOT_CERTIFIED define.
- *                      Added a new DiscoveryStatus bit for SAS IO Unit Page 0
- *                      and SAS Expander Page 0 to flag a downstream initiator
- *                      when in simplified routing mode.
- *                      Removed SATA Init Failure defines for DiscoveryStatus
- *                      fields of SAS IO Unit Page 0 and SAS Expander Page 0.
- *                      Added MPI2_SAS_DEVICE0_ASTATUS_DEVICE_BLOCKED define.
- *                      Added PortGroups, DmaGroup, and ControlGroup fields to
- *                      SAS Device Page 0.
- *  05-06-09  02.00.11  Added structures and defines for IO Unit Page 5 and IO
- *                      Unit Page 6.
- *                      Added expander reduced functionality data to SAS
- *                      Expander Page 0.
- *                      Added SAS PHY Page 2 and SAS PHY Page 3.
- *  07-30-09  02.00.12  Added IO Unit Page 7.
- *                      Added new device ids.
- *                      Added SAS IO Unit Page 5.
- *                      Added partial and slumber power management capable flags
- *                      to SAS Device Page 0 Flags field.
- *                      Added PhyInfo defines for power condition.
- *                      Added Ethernet configuration pages.
- *  10-28-09  02.00.13  Added MPI2_IOUNITPAGE1_ENABLE_HOST_BASED_DISCOVERY.
- *                      Added SAS PHY Page 4 structure and defines.
- *  --------------------------------------------------------------------------
-
-mpi2_init.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  10-31-07  02.00.01  Fixed name for pMpi2SCSITaskManagementRequest_t.
- *  12-18-07  02.00.02  Modified Task Management Target Reset Method defines.
- *  02-29-08  02.00.03  Added Query Task Set and Query Unit Attention.
- *  03-03-08  02.00.04  Fixed name of struct _MPI2_SCSI_TASK_MANAGE_REPLY.
- *  05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
- *  10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
- *                      Control field Task Attribute flags.
- *                      Moved LUN field defines to mpi2.h becasue they are
- *                      common to many structures.
- *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
- *                      Query Asynchronous Event.
- *                      Defined two new bits in the SlotStatus field of the SCSI
- *                      Enclosure Processor Request and Reply.
- *  10-28-09  02.00.08  Added defines for decoding the ResponseInfo bytes for
- *                      both SCSI IO Error Reply and SCSI Task Management Reply.
- *                      Added ResponseInfo field to MPI2_SCSI_TASK_MANAGE_REPLY.
- *                      Added MPI2_SCSITASKMGMT_RSP_TM_OVERLAPPED_TAG define.
- *  --------------------------------------------------------------------------
-
-mpi2_ioc.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-04-07  02.00.01  In IOCFacts Reply structure, renamed MaxDevices to
- *                      MaxTargets.
- *                      Added TotalImageSize field to FWDownload Request.
- *                      Added reserved words to FWUpload Request.
- *  06-26-07  02.00.02  Added IR Configuration Change List Event.
- *  08-31-07  02.00.03  Removed SystemReplyQueueDepth field from the IOCInit
- *                      request and replaced it with
- *                      ReplyDescriptorPostQueueDepth and ReplyFreeQueueDepth.
- *                      Replaced the MinReplyQueueDepth field of the IOCFacts
- *                      reply with MaxReplyDescriptorPostQueueDepth.
- *                      Added MPI2_RDPQ_DEPTH_MIN define to specify the minimum
- *                      depth for the Reply Descriptor Post Queue.
- *                      Added SASAddress field to Initiator Device Table
- *                      Overflow Event data.
- *  10-31-07  02.00.04  Added ReasonCode MPI2_EVENT_SAS_INIT_RC_NOT_RESPONDING
- *                      for SAS Initiator Device Status Change Event data.
- *                      Modified Reason Code defines for SAS Topology Change
- *                      List Event data, including adding a bit for PHY Vacant
- *                      status, and adding a mask for the Reason Code.
- *                      Added define for
- *                      MPI2_EVENT_SAS_TOPO_ES_DELAY_NOT_RESPONDING.
- *                      Added define for MPI2_EXT_IMAGE_TYPE_MEGARAID.
- *  12-18-07  02.00.05  Added Boot Status defines for the IOCExceptions field of
- *                      the IOCFacts Reply.
- *                      Removed MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- *                      Moved MPI2_VERSION_UNION to mpi2.h.
- *                      Changed MPI2_EVENT_NOTIFICATION_REQUEST to use masks
- *                      instead of enables, and added SASBroadcastPrimitiveMasks
- *                      field.
- *                      Added Log Entry Added Event and related structure.
- *  02-29-08  02.00.06  Added define MPI2_IOCFACTS_CAPABILITY_INTEGRATED_RAID.
- *                      Removed define MPI2_IOCFACTS_PROTOCOL_SMP_TARGET.
- *                      Added MaxVolumes and MaxPersistentEntries fields to
- *                      IOCFacts reply.
- *                      Added ProtocalFlags and IOCCapabilities fields to
- *                      MPI2_FW_IMAGE_HEADER.
- *                      Removed MPI2_PORTENABLE_FLAGS_ENABLE_SINGLE_PORT.
- *  03-03-08  02.00.07  Fixed MPI2_FW_IMAGE_HEADER by changing Reserved26 to
- *                      a U16 (from a U32).
- *                      Removed extra 's' from EventMasks name.
- *  06-27-08  02.00.08  Fixed an offset in a comment.
- *  10-02-08  02.00.09  Removed SystemReplyFrameSize from MPI2_IOC_INIT_REQUEST.
- *                      Removed CurReplyFrameSize from MPI2_IOC_FACTS_REPLY and
- *                      renamed MinReplyFrameSize to ReplyFrameSize.
- *                      Added MPI2_IOCFACTS_EXCEPT_IR_FOREIGN_CONFIG_MAX.
- *                      Added two new RAIDOperation values for Integrated RAID
- *                      Operations Status Event data.
- *                      Added four new IR Configuration Change List Event data
- *                      ReasonCode values.
- *                      Added two new ReasonCode defines for SAS Device Status
- *                      Change Event data.
- *                      Added three new DiscoveryStatus bits for the SAS
- *                      Discovery event data.
- *                      Added Multiplexing Status Change bit to the PhyStatus
- *                      field of the SAS Topology Change List event data.
- *                      Removed define for MPI2_INIT_IMAGE_BOOTFLAGS_XMEMCOPY.
- *                      BootFlags are now product-specific.
- *                      Added defines for the indivdual signature bytes
- *                      for MPI2_INIT_IMAGE_FOOTER.
- *  01-19-09  02.00.10  Added MPI2_IOCFACTS_CAPABILITY_EVENT_REPLAY define.
- *                      Added MPI2_EVENT_SAS_DISC_DS_DOWNSTREAM_INITIATOR
- *                      define.
- *                      Added MPI2_EVENT_SAS_DEV_STAT_RC_SATA_INIT_FAILURE
- *                      define.
- *                      Removed MPI2_EVENT_SAS_DISC_DS_SATA_INIT_FAILURE define.
- *  05-06-09  02.00.11  Added MPI2_IOCFACTS_CAPABILITY_RAID_ACCELERATOR define.
- *                      Added MPI2_IOCFACTS_CAPABILITY_MSI_X_INDEX define.
- *                      Added two new reason codes for SAS Device Status Change
- *                      Event.
- *                      Added new event: SAS PHY Counter.
- *  07-30-09  02.00.12  Added GPIO Interrupt event define and structure.
- *                      Added MPI2_IOCFACTS_CAPABILITY_EXTENDED_BUFFER define.
- *                      Added new product id family for 2208.
- *  10-28-09  02.00.13  Added HostMSIxVectors field to MPI2_IOC_INIT_REQUEST.
- *                      Added MaxMSIxVectors field to MPI2_IOC_FACTS_REPLY.
- *                      Added MinDevHandle field to MPI2_IOC_FACTS_REPLY.
- *                      Added MPI2_IOCFACTS_CAPABILITY_HOST_BASED_DISCOVERY.
- *                      Added MPI2_EVENT_HOST_BASED_DISCOVERY_PHY define.
- *                      Added MPI2_EVENT_SAS_TOPO_ES_NO_EXPANDER define.
- *                      Added Host Based Discovery Phy Event data.
- *                      Added defines for ProductID Product field
- *                      (MPI2_FW_HEADER_PID_).
- *                      Modified values for SAS ProductID Family
- *                      (MPI2_FW_HEADER_PID_FAMILY_).
- *  --------------------------------------------------------------------------
-
-mpi2_raid.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  08-31-07  02.00.01  Modifications to RAID Action request and reply,
- *                      including the Actions and ActionData.
- *  02-29-08  02.00.02  Added MPI2_RAID_ACTION_ADATA_DISABL_FULL_REBUILD.
- *  05-21-08  02.00.03  Added MPI2_RAID_VOL_CREATION_NUM_PHYSDISKS so that
- *                      the PhysDisk array in MPI2_RAID_VOLUME_CREATION_STRUCT
- *                      can be sized by the build environment.
- *  07-30-09  02.00.04  Added proper define for the Use Default Settings bit of
- *                      VolumeCreationFlags and marked the old one as obsolete.
- *  05-12-10  02.00.05  Added MPI2_RAID_VOL_FLAGS_OP_MDC define.
- *  --------------------------------------------------------------------------
-
-mpi2_sas.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  06-26-07  02.00.01  Added Clear All Persistent Operation to SAS IO Unit
- *                      Control Request.
- *  10-02-08  02.00.02  Added Set IOC Parameter Operation to SAS IO Unit Control
- *                      Request.
- *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
- *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
- *  05-12-10  02.00.04  Modified some comments.
- *  --------------------------------------------------------------------------
-
-mpi2_targ.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  08-31-07  02.00.01  Added Command Buffer Data Location Address Space bits to
- *                      BufferPostFlags field of CommandBufferPostBase Request.
- *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
- *  10-02-08  02.00.03  Removed NextCmdBufferOffset from
- *                      MPI2_TARGET_CMD_BUF_POST_BASE_REQUEST.
- *                      Target Status Send Request only takes a single SGE for
- *                      response data.
- *  --------------------------------------------------------------------------
-
-mpi2_tool.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  12-18-07  02.00.01  Added Diagnostic Buffer Post and Diagnostic Release
- *                      structures and defines.
- *  02-29-08  02.00.02  Modified various names to make them 32-character unique.
- *  05-06-09  02.00.03  Added ISTWI Read Write Tool and Diagnostic CLI Tool.
- *  07-30-09  02.00.04  Added ExtendedType field to DiagnosticBufferPost request
- *                      and reply messages.
- *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
- *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
- *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
- *  --------------------------------------------------------------------------
-
-mpi2_type.h
- *  04-30-07  02.00.00  Corresponds to Fusion-MPT MPI Specification Rev A.
- *  --------------------------------------------------------------------------
-
-mpi2_ra.h
- *  05-06-09  02.00.00  Initial version.
- *  --------------------------------------------------------------------------
-
-mpi2_hbd.h
- *  10-28-09  02.00.00  Initial version.
- *  --------------------------------------------------------------------------
-
-
-mpi2_history.txt         Parts list history
-
-Filename     02.00.14  02.00.13  02.00.12
-----------   --------  --------  --------
-mpi2.h       02.00.14  02.00.13  02.00.12
-mpi2_cnfg.h  02.00.13  02.00.12  02.00.11
-mpi2_init.h  02.00.08  02.00.07  02.00.07
-mpi2_ioc.h   02.00.13  02.00.12  02.00.11
-mpi2_raid.h  02.00.04  02.00.04  02.00.03
-mpi2_sas.h   02.00.03  02.00.02  02.00.02
-mpi2_targ.h  02.00.03  02.00.03  02.00.03
-mpi2_tool.h  02.00.04  02.00.04  02.00.03
-mpi2_type.h  02.00.00  02.00.00  02.00.00
-mpi2_ra.h    02.00.00  02.00.00  02.00.00
-mpi2_hbd.h   02.00.00
-
-Filename     02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
-----------   --------  --------  --------  --------  --------  --------
-mpi2.h       02.00.11  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06
-mpi2_cnfg.h  02.00.10  02.00.09  02.00.08  02.00.07  02.00.06  02.00.06
-mpi2_init.h  02.00.06  02.00.06  02.00.05  02.00.05  02.00.04  02.00.03
-mpi2_ioc.h   02.00.10  02.00.09  02.00.08  02.00.07  02.00.07  02.00.06
-mpi2_raid.h  02.00.03  02.00.03  02.00.03  02.00.03  02.00.02  02.00.02
-mpi2_sas.h   02.00.02  02.00.02  02.00.01  02.00.01  02.00.01  02.00.01
-mpi2_targ.h  02.00.03  02.00.03  02.00.02  02.00.02  02.00.02  02.00.02
-mpi2_tool.h  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02  02.00.02
-mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
-
-Filename     02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-----------   --------  --------  --------  --------  --------  --------
-mpi2.h       02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-mpi2_cnfg.h  02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-mpi2_init.h  02.00.02  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00
-mpi2_ioc.h   02.00.05  02.00.04  02.00.03  02.00.02  02.00.01  02.00.00
-mpi2_raid.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
-mpi2_sas.h   02.00.01  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00
-mpi2_targ.h  02.00.01  02.00.01  02.00.01  02.00.00  02.00.00  02.00.00
-mpi2_tool.h  02.00.01  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
-mpi2_type.h  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00  02.00.00
-
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_init.h linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_init.h
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_init.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_init.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
  *  05-21-08  02.00.05  Fixed typo in name of Mpi2SepRequest_t.
  *  10-02-08  02.00.06  Removed Untagged and No Disconnect values from SCSI IO
  *                      Control field Task Attribute flags.
- *                      Moved LUN field defines to mpi2.h becasue they are
+ *                      Moved LUN field defines to mpi2.h because they are
  *                      common to many structures.
  *  05-06-09  02.00.07  Changed task management type of Query Unit Attention to
  *                      Query Asynchronous Event.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_sas.h linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_sas.h
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_sas.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_sas.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  *          Title:  MPI Serial Attached SCSI structures and definitions
  *  Creation Date:  February 9, 2007
  *
- *  mpi2_sas.h Version:  02.00.04
+ *  mpi2_sas.h Version:  02.00.05
  *
  *  Version History
  *  ---------------
@@ -21,6 +21,7 @@
  *  10-28-09  02.00.03  Changed the type of SGL in MPI2_SATA_PASSTHROUGH_REQUEST
  *                      to MPI2_SGE_IO_UNION since it supports chained SGLs.
  *  05-12-10  02.00.04  Modified some comments.
+ *  08-11-10  02.00.05  Added NCQ operations to SAS IO Unit Control.
  *  --------------------------------------------------------------------------
  */
 
@@ -163,7 +164,7 @@
     U32                     Reserved4;          /* 0x14 */
     U32                     DataLength;         /* 0x18 */
     U8                      CommandFIS[20];     /* 0x1C */
-    MPI2_SGE_IO_UNION       SGL;                /* 0x20 */
+    MPI2_SGE_IO_UNION       SGL;                /* 0x30 */
 } MPI2_SATA_PASSTHROUGH_REQUEST, MPI2_POINTER PTR_MPI2_SATA_PASSTHROUGH_REQUEST,
   Mpi2SataPassthroughRequest_t, MPI2_POINTER pMpi2SataPassthroughRequest_t;
 
@@ -246,6 +247,8 @@
 #define MPI2_SAS_OP_REMOVE_DEVICE               (0x0D)
 #define MPI2_SAS_OP_LOOKUP_MAPPING              (0x0E)
 #define MPI2_SAS_OP_SET_IOC_PARAMETER           (0x0F)
+#define MPI2_SAS_OP_DEV_ENABLE_NCQ              (0x14)
+#define MPI2_SAS_OP_DEV_DISABLE_NCQ             (0x15)
 #define MPI2_SAS_OP_PRODUCT_SPECIFIC_MIN        (0x80)
 
 /* values for the PrimFlags field */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_tool.h linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_tool.h
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpi/mpi2_tool.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpi/mpi2_tool.h	2011-05-19 00:06:34.000000000 -0400
@@ -6,7 +6,7 @@
  *          Title:  MPI diagnostic tool structures and definitions
  *  Creation Date:  March 26, 2007
  *
- *    mpi2_tool.h Version:  02.00.05
+ *    mpi2_tool.h Version:  02.00.06
  *
  *  Version History
  *  ---------------
@@ -23,6 +23,8 @@
  *                      Added MPI2_DIAG_BUF_TYPE_EXTENDED.
  *                      Incremented MPI2_DIAG_BUF_TYPE_COUNT.
  *  05-12-10  02.00.05  Added Diagnostic Data Upload tool.
+ *  08-11-10  02.00.06  Added defines that were missing for Diagnostic Buffer
+ *                      Post Request.
  *  --------------------------------------------------------------------------
  */
 
@@ -354,6 +356,10 @@
 /* count of the number of buffer types */
 #define MPI2_DIAG_BUF_TYPE_COUNT                    (0x03)
 
+/* values for the Flags field */
+#define MPI2_DIAG_BUF_FLAG_RELEASE_ON_FULL          (0x00000002)
+#define MPI2_DIAG_BUF_FLAG_IMMEDIATE_RELEASE        (0x00000001)
+
 
 /****************************************************************************
 *  Diagnostic Buffer Post reply
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_base.c	2011-05-19 00:06:34.000000000 -0400
@@ -752,20 +752,19 @@
 _base_get_cb_idx(struct MPT2SAS_ADAPTER *ioc, u16 smid)
 {
 	int i;
-	u8 cb_idx = 0xFF;
+	u8 cb_idx;
 
-	if (smid >= ioc->hi_priority_smid) {
-		if (smid < ioc->internal_smid) {
-			i = smid - ioc->hi_priority_smid;
-			cb_idx = ioc->hpr_lookup[i].cb_idx;
-		} else if (smid <= ioc->hba_queue_depth)  {
-			i = smid - ioc->internal_smid;
-			cb_idx = ioc->internal_lookup[i].cb_idx;
-		}
-	} else {
+	if (smid < ioc->hi_priority_smid) {
 		i = smid - 1;
 		cb_idx = ioc->scsi_lookup[i].cb_idx;
-	}
+	} else if (smid < ioc->internal_smid) {
+		i = smid - ioc->hi_priority_smid;
+		cb_idx = ioc->hpr_lookup[i].cb_idx;
+	} else if (smid <= ioc->hba_queue_depth) {
+		i = smid - ioc->internal_smid;
+		cb_idx = ioc->internal_lookup[i].cb_idx;
+	} else
+		cb_idx = 0xFF;
 	return cb_idx;
 }
 
@@ -926,7 +925,7 @@
 }
 
 /**
- * mpt2sas_base_release_callback_handler - clear interupt callback handler
+ * mpt2sas_base_release_callback_handler - clear interrupt callback handler
  * @cb_idx: callback index
  *
  * Return nothing.
@@ -1114,7 +1113,7 @@
  * @ioc: per adapter object
  *
  * Check to see if card is capable of MSIX, and set number
- * of avaliable msix vectors
+ * of available msix vectors
  */
 static int
 _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
@@ -1430,7 +1429,7 @@
     struct scsi_cmnd *scmd)
 {
 	unsigned long flags;
-	struct request_tracker *request;
+	struct scsiio_tracker *request;
 	u16 smid;
 
 	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
@@ -1442,7 +1441,7 @@
 	}
 
 	request = list_entry(ioc->free_list.next,
-	    struct request_tracker, tracker_list);
+	    struct scsiio_tracker, tracker_list);
 	request->scmd = scmd;
 	request->cb_idx = cb_idx;
 	smid = request->smid;
@@ -1496,48 +1495,47 @@
 	struct chain_tracker *chain_req, *next;
 
 	spin_lock_irqsave(&ioc->scsi_lookup_lock, flags);
-	if (smid >= ioc->hi_priority_smid) {
-		if (smid < ioc->internal_smid) {
-			/* hi-priority */
-			i = smid - ioc->hi_priority_smid;
-			ioc->hpr_lookup[i].cb_idx = 0xFF;
-			list_add_tail(&ioc->hpr_lookup[i].tracker_list,
-			    &ioc->hpr_free_list);
-		} else {
-			/* internal queue */
-			i = smid - ioc->internal_smid;
-			ioc->internal_lookup[i].cb_idx = 0xFF;
-			list_add_tail(&ioc->internal_lookup[i].tracker_list,
-			    &ioc->internal_free_list);
+	if (smid < ioc->hi_priority_smid) {
+		/* scsiio queue */
+		i = smid - 1;
+		if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
+			list_for_each_entry_safe(chain_req, next,
+			    &ioc->scsi_lookup[i].chain_list, tracker_list) {
+				list_del_init(&chain_req->tracker_list);
+				list_add_tail(&chain_req->tracker_list,
+				    &ioc->free_chain_list);
+			}
 		}
+		ioc->scsi_lookup[i].cb_idx = 0xFF;
+		ioc->scsi_lookup[i].scmd = NULL;
+		list_add_tail(&ioc->scsi_lookup[i].tracker_list,
+		    &ioc->free_list);
 		spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-		return;
-	}
 
-	/* scsiio queue */
-	i = smid - 1;
-	if (!list_empty(&ioc->scsi_lookup[i].chain_list)) {
-		list_for_each_entry_safe(chain_req, next,
-		    &ioc->scsi_lookup[i].chain_list, tracker_list) {
-			list_del_init(&chain_req->tracker_list);
-			list_add_tail(&chain_req->tracker_list,
-			    &ioc->free_chain_list);
+		/*
+		 * See _wait_for_commands_to_complete() call with regards
+		 * to this code.
+		 */
+		if (ioc->shost_recovery && ioc->pending_io_count) {
+			if (ioc->pending_io_count == 1)
+				wake_up(&ioc->reset_wq);
+			ioc->pending_io_count--;
 		}
+		return;
+	} else if (smid < ioc->internal_smid) {
+		/* hi-priority */
+		i = smid - ioc->hi_priority_smid;
+		ioc->hpr_lookup[i].cb_idx = 0xFF;
+		list_add_tail(&ioc->hpr_lookup[i].tracker_list,
+		    &ioc->hpr_free_list);
+	} else if (smid <= ioc->hba_queue_depth) {
+		/* internal queue */
+		i = smid - ioc->internal_smid;
+		ioc->internal_lookup[i].cb_idx = 0xFF;
+		list_add_tail(&ioc->internal_lookup[i].tracker_list,
+		    &ioc->internal_free_list);
 	}
-	ioc->scsi_lookup[i].cb_idx = 0xFF;
-	ioc->scsi_lookup[i].scmd = NULL;
-	list_add_tail(&ioc->scsi_lookup[i].tracker_list,
-	    &ioc->free_list);
 	spin_unlock_irqrestore(&ioc->scsi_lookup_lock, flags);
-
-	/*
-	 * See _wait_for_commands_to_complete() call with regards to this code.
-	 */
-	if (ioc->shost_recovery && ioc->pending_io_count) {
-		if (ioc->pending_io_count == 1)
-			wake_up(&ioc->reset_wq);
-		ioc->pending_io_count--;
-	}
 }
 
 /**
@@ -1597,7 +1595,7 @@
 
 
 /**
- * mpt2sas_base_put_smid_hi_priority - send Task Managment request to firmware
+ * mpt2sas_base_put_smid_hi_priority - send Task Management request to firmware
  * @ioc: per adapter object
  * @smid: system request message index
  *
@@ -1725,6 +1723,79 @@
 }
 
 /**
+ * _base_display_intel_branding - Display branding string
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_intel_branding(struct MPT2SAS_ADAPTER *ioc)
+{
+	if (ioc->pdev->subsystem_vendor == PCI_VENDOR_ID_INTEL &&
+	    ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008) {
+
+		switch (ioc->pdev->subsystem_device) {
+		case MPT2SAS_INTEL_RMS2LL080_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_INTEL_RMS2LL080_BRANDING);
+			break;
+		case MPT2SAS_INTEL_RMS2LL040_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_INTEL_RMS2LL040_BRANDING);
+			break;
+		}
+	}
+}
+
+/**
+ * _base_display_hp_branding - Display branding string
+ * @ioc: per adapter object
+ *
+ * Return nothing.
+ */
+static void
+_base_display_hp_branding(struct MPT2SAS_ADAPTER *ioc)
+{
+	if (ioc->pdev->subsystem_vendor != MPT2SAS_HP_3PAR_SSVID)
+		return;
+
+	switch (ioc->pdev->device) {
+	case MPI2_MFGPAGE_DEVID_SAS2004:
+		switch (ioc->pdev->subsystem_device) {
+		case MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING);
+			break;
+		default:
+			break;
+		}
+	case MPI2_MFGPAGE_DEVID_SAS2308_2:
+		switch (ioc->pdev->subsystem_device) {
+		case MPT2SAS_HP_2_4_INTERNAL_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_HP_2_4_INTERNAL_BRANDING);
+			break;
+		case MPT2SAS_HP_2_4_EXTERNAL_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_HP_2_4_EXTERNAL_BRANDING);
+			break;
+		case MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING);
+			break;
+		case MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID:
+			printk(MPT2SAS_INFO_FMT "%s\n", ioc->name,
+			    MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING);
+			break;
+		default:
+			break;
+		}
+	default:
+		break;
+	}
+}
+
+/**
  * _base_display_ioc_capabilities - Disply IOC's capabilities.
  * @ioc: per adapter object
  *
@@ -1754,6 +1825,8 @@
 	    ioc->bios_pg3.BiosVersion & 0x000000FF);
 
 	_base_display_dell_branding(ioc);
+	_base_display_intel_branding(ioc);
+	_base_display_hp_branding(ioc);
 
 	printk(MPT2SAS_INFO_FMT "Protocol=(", ioc->name);
 
@@ -2252,9 +2325,9 @@
 	    ioc->name, (unsigned long long) ioc->request_dma));
 	total_sz += sz;
 
-	sz = ioc->scsiio_depth * sizeof(struct request_tracker);
+	sz = ioc->scsiio_depth * sizeof(struct scsiio_tracker);
 	ioc->scsi_lookup_pages = get_order(sz);
-	ioc->scsi_lookup = (struct request_tracker *)__get_free_pages(
+	ioc->scsi_lookup = (struct scsiio_tracker *)__get_free_pages(
 	    GFP_KERNEL, ioc->scsi_lookup_pages);
 	if (!ioc->scsi_lookup) {
 		printk(MPT2SAS_ERR_FMT "scsi_lookup: get_free_pages failed, "
@@ -2526,7 +2599,7 @@
 		int_status = readl(&ioc->chip->HostInterruptStatus);
 		if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
 			dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-			    "successfull count(%d), timeout(%d)\n", ioc->name,
+			    "successful count(%d), timeout(%d)\n", ioc->name,
 			    __func__, count, timeout));
 			return 0;
 		}
@@ -2567,7 +2640,7 @@
 		int_status = readl(&ioc->chip->HostInterruptStatus);
 		if (!(int_status & MPI2_HIS_SYS2IOC_DB_STATUS)) {
 			dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-			    "successfull count(%d), timeout(%d)\n", ioc->name,
+			    "successful count(%d), timeout(%d)\n", ioc->name,
 			    __func__, count, timeout));
 			return 0;
 		} else if (int_status & MPI2_HIS_IOC2SYS_DB_STATUS) {
@@ -2615,7 +2688,7 @@
 		doorbell_reg = readl(&ioc->chip->Doorbell);
 		if (!(doorbell_reg & MPI2_DOORBELL_USED)) {
 			dhsprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: "
-			    "successfull count(%d), timeout(%d)\n", ioc->name,
+			    "successful count(%d), timeout(%d)\n", ioc->name,
 			    __func__, count, timeout));
 			return 0;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_base.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,8 +69,8 @@
 #define MPT2SAS_DRIVER_NAME		"mpt2sas"
 #define MPT2SAS_AUTHOR	"LSI Corporation <DL-MPTFusionLinux@lsi.com>"
 #define MPT2SAS_DESCRIPTION	"LSI MPT Fusion SAS 2.0 Device Driver"
-#define MPT2SAS_DRIVER_VERSION		"07.100.00.00"
-#define MPT2SAS_MAJOR_VERSION		07
+#define MPT2SAS_DRIVER_VERSION		"08.100.00.00"
+#define MPT2SAS_MAJOR_VERSION		08
 #define MPT2SAS_MINOR_VERSION		100
 #define MPT2SAS_BUILD_VERSION		00
 #define MPT2SAS_RELEASE_VERSION		00
@@ -101,7 +101,8 @@
 #define MPT_NAME_LENGTH			32	/* generic length of strings */
 #define MPT_STRING_LENGTH		64
 
-#define	MPT_MAX_CALLBACKS		16
+#define MPT_MAX_CALLBACKS		16
+
 
 #define	 CAN_SLEEP			1
 #define  NO_SLEEP			0
@@ -154,6 +155,40 @@
 #define MPT2SAS_DELL_6GBPS_SAS_SSDID               0x1F22
 
 /*
+ * Intel HBA branding
+ */
+#define MPT2SAS_INTEL_RMS2LL080_BRANDING	\
+				"Intel Integrated RAID Module RMS2LL080"
+#define MPT2SAS_INTEL_RMS2LL040_BRANDING	\
+				"Intel Integrated RAID Module RMS2LL040"
+
+/*
+ * Intel HBA SSDIDs
+ */
+#define MPT2SAS_INTEL_RMS2LL080_SSDID          0x350E
+#define MPT2SAS_INTEL_RMS2LL040_SSDID          0x350F
+
+
+/*
+ * HP HBA branding
+ */
+#define MPT2SAS_HP_3PAR_SSVID                0x1590
+#define MPT2SAS_HP_2_4_INTERNAL_BRANDING        "HP H220 Host Bus Adapter"
+#define MPT2SAS_HP_2_4_EXTERNAL_BRANDING        "HP H221 Host Bus Adapter"
+#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_BRANDING "HP H222 Host Bus Adapter"
+#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_BRANDING    "HP H220i Host Bus Adapter"
+#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_BRANDING    "HP H210i Host Bus Adapter"
+
+/*
+ * HO HBA SSDIDs
+ */
+#define MPT2SAS_HP_2_4_INTERNAL_SSDID            0x0041
+#define MPT2SAS_HP_2_4_EXTERNAL_SSDID            0x0042
+#define MPT2SAS_HP_1_4_INTERNAL_1_4_EXTERNAL_SSDID    0x0043
+#define MPT2SAS_HP_EMBEDDED_2_4_INTERNAL_SSDID        0x0044
+#define MPT2SAS_HP_DAUGHTER_2_4_INTERNAL_SSDID        0x0046
+
+/*
  * per target private data
  */
 #define MPT_TARGET_FLAGS_RAID_COMPONENT	0x01
@@ -431,14 +466,14 @@
 };
 
 /**
- * struct request_tracker - firmware request tracker
+ * struct scsiio_tracker - scsi mf request tracker
  * @smid: system message id
  * @scmd: scsi request pointer
  * @cb_idx: callback index
  * @chain_list: list of chains associated to this IO
  * @tracker_list: list of free request (ioc->free_list)
  */
-struct request_tracker {
+struct scsiio_tracker {
 	u16	smid;
 	struct scsi_cmnd *scmd;
 	u8	cb_idx;
@@ -447,6 +482,19 @@
 };
 
 /**
+ * struct request_tracker - misc mf request tracker
+ * @smid: system message id
+ * @scmd: scsi request pointer
+ * @cb_idx: callback index
+ * @tracker_list: list of free request (ioc->free_list)
+ */
+struct request_tracker {
+	u16	smid;
+	u8	cb_idx;
+	struct list_head tracker_list;
+};
+
+/**
  * struct _tr_list - target reset list
  * @handle: device handle
  * @state: state machine
@@ -709,7 +757,7 @@
 	u8		*request;
 	dma_addr_t	request_dma;
 	u32		request_dma_sz;
-	struct request_tracker *scsi_lookup;
+	struct scsiio_tracker *scsi_lookup;
 	ulong		scsi_lookup_pages;
 	spinlock_t 	scsi_lookup_lock;
 	struct list_head free_list;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_config.c linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_config.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_config.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_config.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
  * @mpi_reply: reply message frame
  * Context: none.
  *
- * Function for displaying debug info helpfull when debugging issues
+ * Function for displaying debug info helpful when debugging issues
  * in this module.
  */
 static void
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_ctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -116,7 +116,7 @@
  * @mpi_reply: reply message frame
  * Context: none.
  *
- * Function for displaying debug info helpfull when debugging issues
+ * Function for displaying debug info helpful when debugging issues
  * in this module.
  */
 static void
@@ -688,6 +688,13 @@
 		goto out;
 	}
 
+	/* Check for overflow and wraparound */
+	if (karg.data_sge_offset * 4 > ioc->request_sz ||
+	    karg.data_sge_offset > (UINT_MAX / 4)) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	/* copy in request message frame from user */
 	if (copy_from_user(mpi_request, mf, karg.data_sge_offset*4)) {
 		printk(KERN_ERR "failure at %s:%d/%s()!\n", __FILE__, __LINE__,
@@ -1963,7 +1970,7 @@
 	Mpi2DiagBufferPostReply_t *mpi_reply;
 	int rc, i;
 	u8 buffer_type;
-	unsigned long timeleft;
+	unsigned long timeleft, request_size, copy_size;
 	u16 smid;
 	u16 ioc_status;
 	u8 issue_reset = 0;
@@ -1999,6 +2006,8 @@
 		return -ENOMEM;
 	}
 
+	request_size = ioc->diag_buffer_sz[buffer_type];
+
 	if ((karg.starting_offset % 4) || (karg.bytes_to_read % 4)) {
 		printk(MPT2SAS_ERR_FMT "%s: either the starting_offset "
 		    "or bytes_to_read are not 4 byte aligned\n", ioc->name,
@@ -2006,13 +2015,23 @@
 		return -EINVAL;
 	}
 
+	if (karg.starting_offset > request_size)
+		return -EINVAL;
+
 	diag_data = (void *)(request_data + karg.starting_offset);
 	dctlprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: diag_buffer(%p), "
 	    "offset(%d), sz(%d)\n", ioc->name, __func__,
 	    diag_data, karg.starting_offset, karg.bytes_to_read));
 
+	/* Truncate data on requests that are too large */
+	if ((diag_data + karg.bytes_to_read < diag_data) ||
+	    (diag_data + karg.bytes_to_read > request_data + request_size))
+		copy_size = request_size - karg.starting_offset;
+	else
+		copy_size = karg.bytes_to_read;
+
 	if (copy_to_user((void __user *)uarg->diagnostic_data,
-	    diag_data, karg.bytes_to_read)) {
+	    diag_data, copy_size)) {
 		printk(MPT2SAS_ERR_FMT "%s: Unable to write "
 		    "mpt_diag_read_buffer_t data @ %p\n", ioc->name,
 		    __func__, diag_data);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mpt2sas/mpt2sas_scsih.c	2011-05-19 00:06:34.000000000 -0400
@@ -397,7 +397,7 @@
  * @is_raid: [flag] 1 = raid object, 0 = sas object
  *
  * Determines whether this device should be first reported device to
- * to scsi-ml or sas transport, this purpose is for persistant boot device.
+ * to scsi-ml or sas transport, this purpose is for persistent boot device.
  * There are primary, alternate, and current entries in bios page 2. The order
  * priority is primary, alternate, then current.  This routine saves
  * the corresponding device object and is_raid flag in the ioc object.
@@ -2671,10 +2671,10 @@
  * @handle: device handle
  * Context: interrupt time.
  *
- * This code is to initiate the device removal handshake protocal
+ * This code is to initiate the device removal handshake protocol
  * with controller firmware.  This function will issue target reset
  * using high priority request queue.  It will send a sas iounit
- * controll request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
+ * control request (MPI2_SAS_OP_REMOVE_DEVICE) from this completion.
  *
  * This is designed to send muliple task management request at the same
  * time to the fifo. If the fifo is full, we will append the request,
@@ -2749,9 +2749,9 @@
  * @reply: reply message frame(lower 32bit addr)
  * Context: interrupt time.
  *
- * This is the sas iounit controll completion routine.
+ * This is the sas iounit control completion routine.
  * This code is part of the code to initiate the device removal
- * handshake protocal with controller firmware.
+ * handshake protocol with controller firmware.
  *
  * Return 1 meaning mf should be freed from _base_interrupt
  *        0 means the mf is freed from this function.
@@ -2878,8 +2878,8 @@
  *
  * This is the target reset completion routine.
  * This code is part of the code to initiate the device removal
- * handshake protocal with controller firmware.
- * It will send a sas iounit controll request (MPI2_SAS_OP_REMOVE_DEVICE)
+ * handshake protocol with controller firmware.
+ * It will send a sas iounit control request (MPI2_SAS_OP_REMOVE_DEVICE)
  *
  * Return 1 meaning mf should be freed from _base_interrupt
  *        0 means the mf is freed from this function.
@@ -2984,7 +2984,7 @@
  *
  * This routine added to better handle cable breaker.
  *
- * This handles the case where driver recieves multiple expander
+ * This handles the case where driver receives multiple expander
  * add and delete events in a single shot.  When there is a delete event
  * the routine will void any pending add events waiting in the event queue.
  *
@@ -3511,7 +3511,7 @@
 
 #ifdef CONFIG_SCSI_MPT2SAS_LOGGING
 /**
- * _scsih_scsi_ioc_info - translated non-successfull SCSI_IO request
+ * _scsih_scsi_ioc_info - translated non-successful SCSI_IO request
  * @ioc: per adapter object
  * @scmd: pointer to scsi command object
  * @mpi_reply: reply mf payload returned from firmware
@@ -5138,7 +5138,7 @@
 	unsigned long flags;
 	int r;
 
-	dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primative: "
+	dewtprintk(ioc, printk(MPT2SAS_INFO_FMT "broadcast primitive: "
 	    "phy number(%d), width(%d)\n", ioc->name, event_data->PhyNum,
 	    event_data->PortWidth));
 	dtmprintk(ioc, printk(MPT2SAS_INFO_FMT "%s: enter\n", ioc->name,
@@ -6975,7 +6975,6 @@
 	u32 device_state;
 
 	mpt2sas_base_stop_watchdog(ioc);
-	flush_scheduled_work();
 	scsi_block_requests(shost);
 	device_state = pci_choose_state(pdev, state);
 	printk(MPT2SAS_INFO_FMT "pdev=0x%p, slot=%s, entering "
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mvsas/Makefile linux-libre-2.6.39-gnu/drivers/scsi/mvsas/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/mvsas/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mvsas/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -21,9 +21,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
 # USA
 
-ifeq ($(CONFIG_SCSI_MVSAS_DEBUG),y)
-	EXTRA_CFLAGS += -DMV_DEBUG
-endif
+ccflags-$(CONFIG_SCSI_MVSAS_DEBUG) := -DMV_DEBUG
 
 obj-$(CONFIG_SCSI_MVSAS) += mvsas.o
 mvsas-y +=  mv_init.o  \
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/mvsas/mv_init.c linux-libre-2.6.39-gnu/drivers/scsi/mvsas/mv_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/mvsas/mv_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/mvsas/mv_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -663,6 +663,13 @@
 	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1300), chip_1300 },
 	{ PCI_VDEVICE(ARECA, PCI_DEVICE_ID_ARECA_1320), chip_1320 },
 	{ PCI_VDEVICE(ADAPTEC2, 0x0450), chip_6440 },
+	{ PCI_VDEVICE(TTI, 0x2710), chip_9480 },
+	{ PCI_VDEVICE(TTI, 0x2720), chip_9480 },
+	{ PCI_VDEVICE(TTI, 0x2721), chip_9480 },
+	{ PCI_VDEVICE(TTI, 0x2722), chip_9480 },
+	{ PCI_VDEVICE(TTI, 0x2740), chip_9480 },
+	{ PCI_VDEVICE(TTI, 0x2744), chip_9480 },
+	{ PCI_VDEVICE(TTI, 0x2760), chip_9480 },
 
 	{ }	/* terminate list */
 };
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/NCR5380.c linux-libre-2.6.39-gnu/drivers/scsi/NCR5380.c
--- linux-libre-2.6.38-gnu/drivers/scsi/NCR5380.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/NCR5380.c	2011-05-19 00:06:34.000000000 -0400
@@ -936,8 +936,7 @@
 {
 	struct NCR5380_hostdata *hostdata = (struct NCR5380_hostdata *) instance->hostdata;
 
-	cancel_delayed_work(&hostdata->coroutine);
-	flush_scheduled_work();
+	cancel_delayed_work_sync(&hostdata->coroutine);
 }
 
 /**
@@ -1199,12 +1198,12 @@
 				 */
 
 				if ((NCR5380_read(MODE_REG) & MR_DMA) && ((basr & BASR_END_DMA_TRANSFER) || !(basr & BASR_PHASE_MATCH))) {
-					int transfered;
+					int transferred;
 
 					if (!hostdata->connected)
 						panic("scsi%d : received end of DMA interrupt with no connected cmd\n", instance->hostno);
 
-					transfered = (hostdata->dmalen - NCR5380_dma_residual(instance));
+					transferred = (hostdata->dmalen - NCR5380_dma_residual(instance));
 					hostdata->connected->SCp.this_residual -= transferred;
 					hostdata->connected->SCp.ptr += transferred;
 					hostdata->dmalen = 0;
@@ -1564,7 +1563,7 @@
  *      bytes to transfer, **data - pointer to data pointer.
  * 
  * Returns : -1 when different phase is entered without transferring
- *      maximum number of bytes, 0 if all bytes or transfered or exit
+ *      maximum number of bytes, 0 if all bytes or transferred or exit
  *      is in same phase.
  *
  *      Also, *phase, *count, *data are modified in place.
@@ -1801,7 +1800,7 @@
  *      bytes to transfer, **data - pointer to data pointer.
  * 
  * Returns : -1 when different phase is entered without transferring
- *      maximum number of bytes, 0 if all bytes or transfered or exit
+ *      maximum number of bytes, 0 if all bytes or transferred or exit
  *      is in same phase.
  *
  *      Also, *phase, *count, *data are modified in place.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ncr53c8xx.c linux-libre-2.6.39-gnu/drivers/scsi/ncr53c8xx.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ncr53c8xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/ncr53c8xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -2679,7 +2679,7 @@
 }/*-------------------------< RESEL_TAG >-------------------*/,{
 	/*
 	**	Read IDENTIFY + SIMPLE + TAG using a single MOVE.
-	**	Agressive optimization, is'nt it?
+	**	Aggressive optimization, is'nt it?
 	**	No need to test the SIMPLE TAG message, since the 
 	**	driver only supports conformant devices for tags. ;-)
 	*/
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/nsp32.c linux-libre-2.6.39-gnu/drivers/scsi/nsp32.c
--- linux-libre-2.6.38-gnu/drivers/scsi/nsp32.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/nsp32.c	2011-05-19 00:06:34.000000000 -0400
@@ -1288,7 +1288,7 @@
 			nsp32_dbg(NSP32_DEBUG_INTR, "SSACK=0x%lx", 
 				    nsp32_read4(base, SAVED_SACK_CNT));
 
-			scsi_set_resid(SCpnt, 0); /* all data transfered! */
+			scsi_set_resid(SCpnt, 0); /* all data transferred! */
 		}
 
 		/*
@@ -1630,7 +1630,7 @@
 
 			/*
 			 * If SAVEDSACKCNT == 0, it means SavedDataPointer is
-			 * come after data transfering.
+			 * come after data transferring.
 			 */
 			if (s_sacklen > 0) {
 				/*
@@ -1785,7 +1785,7 @@
 		   the head element of the sg. restlen is correctly calculated. */
 	}
 
-	/* calculate the rest length for transfering */
+	/* calculate the rest length for transferring */
 	restlen = sentlen - s_sacklen;
 
 	/* update adjusting current SG table entry */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/nsp32.h linux-libre-2.6.39-gnu/drivers/scsi/nsp32.h
--- linux-libre-2.6.38-gnu/drivers/scsi/nsp32.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/nsp32.h	2011-05-19 00:06:34.000000000 -0400
@@ -507,7 +507,7 @@
 /*
  * SCSI TARGET/LUN definition
  */
-#define NSP32_HOST_SCSIID    7  /* SCSI initiator is everytime defined as 7 */
+#define NSP32_HOST_SCSIID    7  /* SCSI initiator is every time defined as 7 */
 #define MAX_TARGET	     8
 #define MAX_LUN		     8	/* XXX: In SPI3, max number of LUN is 64. */
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/osd/osd_initiator.c linux-libre-2.6.39-gnu/drivers/scsi/osd/osd_initiator.c
--- linux-libre-2.6.38-gnu/drivers/scsi/osd/osd_initiator.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/osd/osd_initiator.c	2011-05-19 00:06:34.000000000 -0400
@@ -1005,11 +1005,23 @@
 	const struct osd_sg_entry *sglist, unsigned numentries)
 {
 	u64 len;
-	int ret = _add_sg_continuation_descriptor(or, sglist, numentries, &len);
+	u64 off;
+	int ret;
 
-	if (ret)
-		return ret;
-	osd_req_read(or, obj, 0, bio, len);
+	if (numentries > 1) {
+		off = 0;
+		ret = _add_sg_continuation_descriptor(or, sglist, numentries,
+						      &len);
+		if (ret)
+			return ret;
+	} else {
+		/* Optimize the case of single segment, read_sg is a
+		 * bidi operation.
+		 */
+		len = sglist->len;
+		off = sglist->offset;
+	}
+	osd_req_read(or, obj, off, bio, len);
 
 	return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/osst.c linux-libre-2.6.39-gnu/drivers/scsi/osst.c
--- linux-libre-2.6.38-gnu/drivers/scsi/osst.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/osst.c	2011-05-19 00:06:34.000000000 -0400
@@ -1366,7 +1366,7 @@
 /* The values below are based on the OnStream frame payload size of 32K == 2**15,
  * that is, OSST_FRAME_SHIFT + OSST_SECTOR_SHIFT must be 15. With a minimum block
  * size of 512 bytes, we need to be able to resolve 32K/512 == 64 == 2**6 positions
- * inside each frame. Finaly, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
+ * inside each frame. Finally, OSST_SECTOR_MASK == 2**OSST_FRAME_SHIFT - 1.
  */
 #define OSST_FRAME_SHIFT  6
 #define OSST_SECTOR_SHIFT 9
@@ -1484,7 +1484,7 @@
 	int			dbg              = debugging;
 #endif
 
-	if ((buffer = (unsigned char *)vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
+	if ((buffer = vmalloc((nframes + 1) * OS_DATA_SIZE)) == NULL)
 		return (-EIO);
 
 	printk(KERN_INFO "%s:I: Reading back %d frames from drive buffer%s\n",
@@ -2296,7 +2296,7 @@
 	if (STp->raw) return 0;
 
 	if (STp->header_cache == NULL) {
-		if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
+		if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
 			printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
 			return (-ENOMEM);
 		}
@@ -2484,7 +2484,7 @@
 				   name, ppos, update_frame_cntr);
 #endif
 		if (STp->header_cache == NULL) {
-			if ((STp->header_cache = (os_header_t *)vmalloc(sizeof(os_header_t))) == NULL) {
+			if ((STp->header_cache = vmalloc(sizeof(os_header_t))) == NULL) {
 				printk(KERN_ERR "%s:E: Failed to allocate header cache\n", name);
 				return 0;
 			}
@@ -3131,7 +3131,7 @@
 		}
 #if DEBUG
 		if (debugging)
-			printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transfering %d bytes in %d lblocks.\n",
+			printk(OSST_DEB_MSG "%s:D: Flushing %d bytes, Transferring %d bytes in %d lblocks.\n",
 			  			 name, offset, transfer, blks);
 #endif
 
@@ -3811,7 +3811,7 @@
 
 			if (transfer == 0) {
 				printk(KERN_WARNING
-				  "%s:W: Nothing can be transfered, requested %Zd, tape block size (%d%c).\n",
+				  "%s:W: Nothing can be transferred, requested %Zd, tape block size (%d%c).\n",
 			   		name, count, STp->block_size < 1024?
 					STp->block_size:STp->block_size/1024,
 				       	STp->block_size<1024?'b':'k');
@@ -5851,9 +5851,7 @@
 	/* if this is the first attach, build the infrastructure */
 	write_lock(&os_scsi_tapes_lock);
 	if (os_scsi_tapes == NULL) {
-		os_scsi_tapes =
-			(struct osst_tape **)kmalloc(osst_max_dev * sizeof(struct osst_tape *),
-				   GFP_ATOMIC);
+		os_scsi_tapes = kmalloc(osst_max_dev * sizeof(struct osst_tape *), GFP_ATOMIC);
 		if (os_scsi_tapes == NULL) {
 			write_unlock(&os_scsi_tapes_lock);
 			printk(KERN_ERR "osst :E: Unable to allocate array for OnStream SCSI tapes.\n");
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/osst.h linux-libre-2.6.39-gnu/drivers/scsi/osst.h
--- linux-libre-2.6.38-gnu/drivers/scsi/osst.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/osst.h	2011-05-19 00:06:34.000000000 -0400
@@ -413,7 +413,7 @@
  * AUX
  */
 typedef struct os_aux_s {
-        __be32          format_id;              /* hardware compability AUX is based on */
+        __be32          format_id;              /* hardware compatibility AUX is based on */
         char            application_sig[4];     /* driver used to write this media */
         __be32          hdwr;                   /* reserved */
         __be32          update_frame_cntr;      /* for configuration frame */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pcmcia/Makefile linux-libre-2.6.39-gnu/drivers/scsi/pcmcia/Makefile
--- linux-libre-2.6.38-gnu/drivers/scsi/pcmcia/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pcmcia/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -1,5 +1,5 @@
 
-EXTRA_CFLAGS		+= -Idrivers/scsi
+ccflags-y		:= -Idrivers/scsi
 
 # 16-bit client drivers
 obj-$(CONFIG_PCMCIA_QLOGIC)	+= qlogic_cs.o
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pcmcia/nsp_cs.c linux-libre-2.6.39-gnu/drivers/scsi/pcmcia/nsp_cs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/pcmcia/nsp_cs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pcmcia/nsp_cs.c	2011-05-19 00:06:34.000000000 -0400
@@ -742,7 +742,7 @@
 
 		res = nsp_fifo_count(SCpnt) - ocount;
 		//nsp_dbg(NSP_DEBUG_DATA_IO, "ptr=0x%p this=0x%x ocount=0x%x res=0x%x", SCpnt->SCp.ptr, SCpnt->SCp.this_residual, ocount, res);
-		if (res == 0) { /* if some data avilable ? */
+		if (res == 0) { /* if some data available ? */
 			if (stat == BUSPHASE_DATA_IN) { /* phase changed? */
 				//nsp_dbg(NSP_DEBUG_DATA_IO, " wait for data this=%d", SCpnt->SCp.this_residual);
 				continue;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_hwi.c linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_hwi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_hwi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_hwi.c	2011-05-19 00:06:34.000000000 -0400
@@ -339,7 +339,7 @@
 
 /**
  * bar4_shift - function is called to shift BAR base address
- * @pm8001_ha : our hba card infomation
+ * @pm8001_ha : our hba card information
  * @shiftValue : shifting value in memory bar.
  */
 static int bar4_shift(struct pm8001_hba_info *pm8001_ha, u32 shiftValue)
@@ -1382,53 +1382,50 @@
 	return MPI_IO_STATUS_BUSY;
 }
 
-static void pm8001_work_queue(struct work_struct *work)
+static void pm8001_work_fn(struct work_struct *work)
 {
-	struct delayed_work *dw = container_of(work, struct delayed_work, work);
-	struct pm8001_wq *wq = container_of(dw, struct pm8001_wq, work_q);
+	struct pm8001_work *pw = container_of(work, struct pm8001_work, work);
 	struct pm8001_device *pm8001_dev;
-	struct domain_device	*dev;
+	struct domain_device *dev;
 
-	switch (wq->handler) {
+	switch (pw->handler) {
 	case IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	case IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	case IO_DS_IN_ERROR:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	case IO_DS_NON_OPERATIONAL:
-		pm8001_dev = wq->data;
+		pm8001_dev = pw->data;
 		dev = pm8001_dev->sas_device;
 		pm8001_I_T_nexus_reset(dev);
 		break;
 	}
-	list_del(&wq->entry);
-	kfree(wq);
+	kfree(pw);
 }
 
 static int pm8001_handle_event(struct pm8001_hba_info *pm8001_ha, void *data,
 			       int handler)
 {
-	struct pm8001_wq *wq;
+	struct pm8001_work *pw;
 	int ret = 0;
 
-	wq = kmalloc(sizeof(struct pm8001_wq), GFP_ATOMIC);
-	if (wq) {
-		wq->pm8001_ha = pm8001_ha;
-		wq->data = data;
-		wq->handler = handler;
-		INIT_DELAYED_WORK(&wq->work_q, pm8001_work_queue);
-		list_add_tail(&wq->entry, &pm8001_ha->wq_list);
-		schedule_delayed_work(&wq->work_q, 0);
+	pw = kmalloc(sizeof(struct pm8001_work), GFP_ATOMIC);
+	if (pw) {
+		pw->pm8001_ha = pm8001_ha;
+		pw->data = data;
+		pw->handler = handler;
+		INIT_WORK(&pw->work, pm8001_work_fn);
+		queue_work(pm8001_wq, &pw->work);
 	} else
 		ret = -ENOMEM;
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_hwi.h linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_hwi.h
--- linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_hwi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_hwi.h	2011-05-19 00:06:34.000000000 -0400
@@ -209,7 +209,7 @@
 
 /*
  * brief the data structure of SATA Completion Response
- * use to discribe the sata task response (64 bytes)
+ * use to describe the sata task response (64 bytes)
  */
 struct sata_completion_resp {
 	__le32	tag;
@@ -951,7 +951,7 @@
 #define PCIE_EVENT_INTERRUPT		0x003044
 #define PCIE_ERROR_INTERRUPT_ENABLE	0x003048
 #define PCIE_ERROR_INTERRUPT		0x00304C
-/* signature defintion for host scratch pad0 register */
+/* signature definition for host scratch pad0 register */
 #define SPC_SOFT_RESET_SIGNATURE	0x252acbcd
 /* Signature for Soft Reset */
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_init.c linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -51,6 +51,8 @@
 
 LIST_HEAD(hba_list);
 
+struct workqueue_struct *pm8001_wq;
+
 /**
  * The main structure which LLDD must register for scsi core.
  */
@@ -134,7 +136,6 @@
 static void pm8001_free(struct pm8001_hba_info *pm8001_ha)
 {
 	int i;
-	struct pm8001_wq *wq;
 
 	if (!pm8001_ha)
 		return;
@@ -150,8 +151,7 @@
 	PM8001_CHIP_DISP->chip_iounmap(pm8001_ha);
 	if (pm8001_ha->shost)
 		scsi_host_put(pm8001_ha->shost);
-	list_for_each_entry(wq, &pm8001_ha->wq_list, entry)
-		cancel_delayed_work(&wq->work_q);
+	flush_workqueue(pm8001_wq);
 	kfree(pm8001_ha->tags);
 	kfree(pm8001_ha);
 }
@@ -381,7 +381,6 @@
 	pm8001_ha->sas = sha;
 	pm8001_ha->shost = shost;
 	pm8001_ha->id = pm8001_id++;
-	INIT_LIST_HEAD(&pm8001_ha->wq_list);
 	pm8001_ha->logging_level = 0x01;
 	sprintf(pm8001_ha->name, "%s%d", DRV_NAME, pm8001_ha->id);
 #ifdef PM8001_USE_TASKLET
@@ -758,7 +757,7 @@
 	int i , pos;
 	u32 device_state;
 	pm8001_ha = sha->lldd_ha;
-	flush_scheduled_work();
+	flush_workqueue(pm8001_wq);
 	scsi_block_requests(pm8001_ha->shost);
 	pos = pci_find_capability(pdev, PCI_CAP_ID_PM);
 	if (pos == 0) {
@@ -870,17 +869,26 @@
  */
 static int __init pm8001_init(void)
 {
-	int rc;
+	int rc = -ENOMEM;
+
+	pm8001_wq = alloc_workqueue("pm8001", 0, 0);
+	if (!pm8001_wq)
+		goto err;
+
 	pm8001_id = 0;
 	pm8001_stt = sas_domain_attach_transport(&pm8001_transport_ops);
 	if (!pm8001_stt)
-		return -ENOMEM;
+		goto err_wq;
 	rc = pci_register_driver(&pm8001_pci_driver);
 	if (rc)
-		goto err_out;
+		goto err_tp;
 	return 0;
-err_out:
+
+err_tp:
 	sas_release_transport(pm8001_stt);
+err_wq:
+	destroy_workqueue(pm8001_wq);
+err:
 	return rc;
 }
 
@@ -888,6 +896,7 @@
 {
 	pci_unregister_driver(&pm8001_pci_driver);
 	sas_release_transport(pm8001_stt);
+	destroy_workqueue(pm8001_wq);
 }
 
 module_init(pm8001_init);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_sas.h linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_sas.h
--- linux-libre-2.6.38-gnu/drivers/scsi/pm8001/pm8001_sas.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pm8001/pm8001_sas.h	2011-05-19 00:06:34.000000000 -0400
@@ -50,6 +50,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/pci.h>
 #include <linux/interrupt.h>
+#include <linux/workqueue.h>
 #include <scsi/libsas.h>
 #include <scsi/scsi_tcq.h>
 #include <scsi/sas_ata.h>
@@ -379,18 +380,16 @@
 #ifdef PM8001_USE_TASKLET
 	struct tasklet_struct	tasklet;
 #endif
-	struct list_head 	wq_list;
 	u32			logging_level;
 	u32			fw_status;
 	const struct firmware 	*fw_image;
 };
 
-struct pm8001_wq {
-	struct delayed_work work_q;
+struct pm8001_work {
+	struct work_struct work;
 	struct pm8001_hba_info *pm8001_ha;
 	void *data;
 	int handler;
-	struct list_head entry;
 };
 
 struct pm8001_fw_image_header {
@@ -446,7 +445,7 @@
 struct fw_control_ex {
 	struct fw_control_info *fw_control;
 	void			*buffer;/* keep buffer pointer to be
-	freed when the responce comes*/
+	freed when the response comes*/
 	void			*virtAddr;/* keep virtual address of the data */
 	void			*usrAddr;/* keep virtual address of the
 	user data */
@@ -460,6 +459,9 @@
 	void			*param3;
 };
 
+/* pm8001 workqueue */
+extern struct workqueue_struct *pm8001_wq;
+
 /******************** function prototype *********************/
 int pm8001_tag_alloc(struct pm8001_hba_info *pm8001_ha, u32 *tag_out);
 void pm8001_tag_init(struct pm8001_hba_info *pm8001_ha);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pmcraid.c linux-libre-2.6.39-gnu/drivers/scsi/pmcraid.c
--- linux-libre-2.6.38-gnu/drivers/scsi/pmcraid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pmcraid.c	2011-05-19 00:06:34.000000000 -0400
@@ -213,7 +213,7 @@
  * pmcraid_slave_configure - Configures a SCSI device
  * @scsi_dev: scsi device struct
  *
- * This fucntion is executed by SCSI mid layer just after a device is first
+ * This function is executed by SCSI mid layer just after a device is first
  * scanned (i.e. it has responded to an INQUIRY). For VSET resources, the
  * timeout value (default 30s) will be over-written to a higher value (60s)
  * and max_sectors value will be over-written to 512. It also sets queue depth
@@ -2122,7 +2122,7 @@
  *
  * This function executes most of the steps required for IOA reset. This gets
  * called by user threads (modprobe/insmod/rmmod) timer, tasklet and midlayer's
- * 'eh_' thread. Access to variables used for controling the reset sequence is
+ * 'eh_' thread. Access to variables used for controlling the reset sequence is
  * synchronized using host lock. Various functions called during reset process
  * would make use of a single command block, pointer to which is also stored in
  * adapter instance structure.
@@ -2994,7 +2994,7 @@
 
 	/* If the abort task is not timed out we will get a Good completion
 	 * as sense_key, otherwise we may get one the following responses
-	 * due to subsquent bus reset or device reset. In case IOASC is
+	 * due to subsequent bus reset or device reset. In case IOASC is
 	 * NR_SYNC_REQUIRED, set sync_reqd flag for the corresponding resource
 	 */
 	if (ioasc == PMCRAID_IOASC_UA_BUS_WAS_RESET ||
@@ -3814,6 +3814,9 @@
 			rc = -EFAULT;
 			goto out_free_buffer;
 		}
+	} else if (request_size < 0) {
+		rc = -EINVAL;
+		goto out_free_buffer;
 	}
 
 	/* check if we have any additional command parameters */
@@ -3933,7 +3936,7 @@
 
 			/* if abort task couldn't find the command i.e it got
 			 * completed prior to aborting, return good completion.
-			 * if command got aborted succesfully or there was IOA
+			 * if command got aborted successfully or there was IOA
 			 * reset due to abort task itself getting timedout then
 			 * return -ETIMEDOUT
 			 */
@@ -5454,7 +5457,7 @@
 	pmcraid_shutdown(pdev);
 
 	pmcraid_disable_interrupts(pinstance, ~0);
-	flush_scheduled_work();
+	flush_work_sync(&pinstance->worker_q);
 
 	pmcraid_kill_tasklets(pinstance);
 	pmcraid_unregister_interrupt_handler(pinstance);
@@ -5932,7 +5935,7 @@
 	 * However, firmware supports 64-bit streaming DMA buffers, whereas
 	 * coherent buffers are to be 32-bit. Since pci_alloc_consistent always
 	 * returns memory within 4GB (if not, change this logic), coherent
-	 * buffers are within firmware acceptible address ranges.
+	 * buffers are within firmware acceptable address ranges.
 	 */
 	if ((sizeof(dma_addr_t) == 4) ||
 	    pci_set_dma_mask(pdev, DMA_BIT_MASK(64)))
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/pmcraid.h linux-libre-2.6.39-gnu/drivers/scsi/pmcraid.h
--- linux-libre-2.6.38-gnu/drivers/scsi/pmcraid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/pmcraid.h	2011-05-19 00:06:34.000000000 -0400
@@ -1024,7 +1024,7 @@
 
 
 /*
- * pmcraid_ioctl_header - definition of header structure that preceeds all the
+ * pmcraid_ioctl_header - definition of header structure that precedes all the
  * buffers given as ioctl arguments.
  *
  * .signature           : always ASCII string, "PMCRAID"
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla1280.c linux-libre-2.6.39-gnu/drivers/scsi/qla1280.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla1280.c	2012-03-24 01:18:02.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla1280.c	2012-03-24 03:36:32.000000000 -0400
@@ -78,7 +78,7 @@
 	- Clean up vchan handling
     Rev  3.23.33 July 3, 2003, Jes Sorensen
 	- Don't define register access macros before define determining MMIO.
-	  This just happend to work out on ia64 but not elsewhere.
+	  This just happened to work out on ia64 but not elsewhere.
 	- Don't try and read from the card while it is in reset as
 	  it won't respond and causes an MCA
     Rev  3.23.32 June 23, 2003, Jes Sorensen
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_def.h linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_def.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -2086,7 +2086,7 @@
 };
 
 /*
- * SNS command structures -- for 2200 compatability.
+ * SNS command structures -- for 2200 compatibility.
  */
 #define	RFT_ID_SNS_SCMD_LEN	22
 #define	RFT_ID_SNS_CMD_SIZE	60
@@ -2402,13 +2402,13 @@
 	volatile struct {
 		uint32_t	mbox_int		:1;
 		uint32_t	mbox_busy		:1;
-
 		uint32_t	disable_risc_code_load	:1;
 		uint32_t	enable_64bit_addressing	:1;
 		uint32_t	enable_lip_reset	:1;
 		uint32_t	enable_target_reset	:1;
 		uint32_t	enable_lip_full_login	:1;
 		uint32_t	enable_led_scheme	:1;
+
 		uint32_t	msi_enabled		:1;
 		uint32_t	msix_enabled		:1;
 		uint32_t	disable_serdes		:1;
@@ -2417,6 +2417,7 @@
 		uint32_t	pci_channel_io_perm_failure	:1;
 		uint32_t	fce_enabled		:1;
 		uint32_t	fac_supported		:1;
+
 		uint32_t	chip_reset_done		:1;
 		uint32_t	port0			:1;
 		uint32_t	running_gold_fw		:1;
@@ -2424,9 +2425,11 @@
 		uint32_t	cpu_affinity_enabled	:1;
 		uint32_t	disable_msix_handshake	:1;
 		uint32_t	fcp_prio_enabled	:1;
-		uint32_t	fw_hung	:1;
-		uint32_t        quiesce_owner:1;
+		uint32_t	isp82xx_fw_hung:1;
+
+		uint32_t	quiesce_owner:1;
 		uint32_t	thermal_supported:1;
+		uint32_t	isp82xx_reset_hdlr_active:1;
 		/* 26 bits */
 	} flags;
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_fw.h linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_fw.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_fw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_fw.h	2011-05-19 00:06:34.000000000 -0400
@@ -539,7 +539,7 @@
 	 * If DIF Error is set in comp_status, these additional fields are
 	 * defined:
 	 * &data[10] : uint8_t report_runt_bg[2];	- computed guard
-	 * &data[12] : uint8_t actual_dif[8];		- DIF Data recieved
+	 * &data[12] : uint8_t actual_dif[8];		- DIF Data received
 	 * &data[20] : uint8_t expected_dif[8];		- DIF Data computed
 	*/
 };
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_gbl.h linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_gbl.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_gbl.h	2012-03-24 01:18:21.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_gbl.h	2012-03-24 03:36:42.000000000 -0400
@@ -565,6 +565,7 @@
 extern int qla82xx_mbx_intr_disable(scsi_qla_host_t *);
 extern void qla82xx_start_iocbs(srb_t *);
 extern int qla82xx_fcoe_ctx_reset(scsi_qla_host_t *);
+extern void qla82xx_chip_reset_cleanup(scsi_qla_host_t *);
 
 /* BSG related functions */
 extern int qla24xx_bsg_request(struct fc_bsg_job *);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_gs.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_gs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_gs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_gs.c	2011-05-19 00:06:34.000000000 -0400
@@ -121,8 +121,11 @@
 
 	rval = QLA_FUNCTION_FAILED;
 	if (ms_pkt->entry_status != 0) {
-		DEBUG2_3(printk("scsi(%ld): %s failed, error status (%x).\n",
-		    vha->host_no, routine, ms_pkt->entry_status));
+		DEBUG2_3(printk(KERN_WARNING "scsi(%ld): %s failed, error status "
+		    "(%x) on port_id: %02x%02x%02x.\n",
+		    vha->host_no, routine, ms_pkt->entry_status,
+		    vha->d_id.b.domain, vha->d_id.b.area,
+		    vha->d_id.b.al_pa));
 	} else {
 		if (IS_FWI2_CAPABLE(ha))
 			comp_status = le16_to_cpu(
@@ -136,8 +139,10 @@
 			if (ct_rsp->header.response !=
 			    __constant_cpu_to_be16(CT_ACCEPT_RESPONSE)) {
 				DEBUG2_3(printk("scsi(%ld): %s failed, "
-				    "rejected request:\n", vha->host_no,
-				    routine));
+				    "rejected request on port_id: %02x%02x%02x\n",
+				    vha->host_no, routine,
+				    vha->d_id.b.domain, vha->d_id.b.area,
+				    vha->d_id.b.al_pa));
 				DEBUG2_3(qla2x00_dump_buffer(
 				    (uint8_t *)&ct_rsp->header,
 				    sizeof(struct ct_rsp_hdr)));
@@ -147,8 +152,10 @@
 			break;
 		default:
 			DEBUG2_3(printk("scsi(%ld): %s failed, completion "
-			    "status (%x).\n", vha->host_no, routine,
-			    comp_status));
+			    "status (%x) on port_id: %02x%02x%02x.\n",
+			    vha->host_no, routine, comp_status,
+			    vha->d_id.b.domain, vha->d_id.b.area,
+			    vha->d_id.b.al_pa));
 			break;
 		}
 	}
@@ -1965,7 +1972,7 @@
 			    "scsi(%ld): GFF_ID issue IOCB failed "
 			    "(%d).\n", vha->host_no, rval));
 		} else if (qla2x00_chk_ms_status(vha, ms_pkt, ct_rsp,
-			       "GPN_ID") != QLA_SUCCESS) {
+			       "GFF_ID") != QLA_SUCCESS) {
 			DEBUG2_3(printk(KERN_INFO
 			    "scsi(%ld): GFF_ID IOCB status had a "
 			    "failure status code\n", vha->host_no));
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_init.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_init.c	2012-03-24 01:18:21.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_init.c	2012-03-24 03:36:42.000000000 -0400
@@ -1967,7 +1967,7 @@
 		} else {
 			/* Mailbox cmd failed. Timeout on min_wait. */
 			if (time_after_eq(jiffies, mtime) ||
-			    (IS_QLA82XX(ha) && ha->flags.fw_hung))
+				ha->flags.isp82xx_fw_hung)
 				break;
 		}
 
@@ -3945,8 +3945,13 @@
 	struct qla_hw_data *ha = vha->hw;
 	struct scsi_qla_host *vp;
 	unsigned long flags;
+	fc_port_t *fcport;
 
-	vha->flags.online = 0;
+	/* For ISP82XX, driver waits for completion of the commands.
+	 * online flag should be set.
+	 */
+	if (!IS_QLA82XX(ha))
+		vha->flags.online = 0;
 	ha->flags.chip_reset_done = 0;
 	clear_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 	ha->qla_stats.total_isp_aborts++;
@@ -3954,7 +3959,10 @@
 	qla_printk(KERN_INFO, ha,
 	    "Performing ISP error recovery - ha= %p.\n", ha);
 
-	/* Chip reset does not apply to 82XX */
+	/* For ISP82XX, reset_chip is just disabling interrupts.
+	 * Driver waits for the completion of the commands.
+	 * the interrupts need to be enabled.
+	 */
 	if (!IS_QLA82XX(ha))
 		ha->isp_ops->reset_chip(vha);
 
@@ -3980,14 +3988,31 @@
 			    LOOP_DOWN_TIME);
 	}
 
+	/* Clear all async request states across all VPs. */
+	list_for_each_entry(fcport, &vha->vp_fcports, list)
+		fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+	spin_lock_irqsave(&ha->vport_slock, flags);
+	list_for_each_entry(vp, &ha->vp_list, list) {
+		atomic_inc(&vp->vref_count);
+		spin_unlock_irqrestore(&ha->vport_slock, flags);
+
+		list_for_each_entry(fcport, &vp->vp_fcports, list)
+			fcport->flags &= ~(FCF_LOGIN_NEEDED | FCF_ASYNC_SENT);
+
+		spin_lock_irqsave(&ha->vport_slock, flags);
+		atomic_dec(&vp->vref_count);
+	}
+	spin_unlock_irqrestore(&ha->vport_slock, flags);
+
 	if (!ha->flags.eeh_busy) {
 		/* Make sure for ISP 82XX IO DMA is complete */
 		if (IS_QLA82XX(ha)) {
-			if (qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
-				WAIT_HOST) == QLA_SUCCESS) {
-				DEBUG2(qla_printk(KERN_INFO, ha,
-				"Done wait for pending commands\n"));
-			}
+			qla82xx_chip_reset_cleanup(vha);
+
+			/* Done waiting for pending commands.
+			 * Reset the online flag.
+			 */
+			vha->flags.online = 0;
 		}
 
 		/* Requeue all commands in outstanding command list. */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_iocb.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_iocb.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_iocb.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_iocb.c	2011-05-19 00:06:34.000000000 -0400
@@ -328,6 +328,7 @@
 	struct qla_hw_data *ha;
 	struct req_que *req;
 	struct rsp_que *rsp;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -406,7 +407,22 @@
 	cmd_pkt->lun = cpu_to_le16(sp->cmd->device->lun);
 
 	/* Update tagged queuing modifier */
-	cmd_pkt->control_flags = __constant_cpu_to_le16(CF_SIMPLE_TAG);
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_HEAD_TAG);
+			break;
+		case ORDERED_QUEUE_TAG:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_ORDERED_TAG);
+			break;
+		default:
+			cmd_pkt->control_flags =
+			    __constant_cpu_to_le16(CF_SIMPLE_TAG);
+			break;
+		}
+	}
 
 	/* Load SCSI command packet. */
 	memcpy(cmd_pkt->scsi_cdb, cmd->cmnd, cmd->cmd_len);
@@ -971,6 +987,7 @@
 	uint16_t		fcp_cmnd_len;
 	struct fcp_cmnd		*fcp_cmnd;
 	dma_addr_t		crc_ctx_dma;
+	char			tag[2];
 
 	cmd = sp->cmd;
 
@@ -1068,9 +1085,27 @@
 	    LSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
 	cmd_pkt->fcp_cmnd_dseg_address[1] = cpu_to_le32(
 	    MSD(crc_ctx_dma + CRC_CONTEXT_FCPCMND_OFF));
-	fcp_cmnd->task_attribute = 0;
 	fcp_cmnd->task_management = 0;
 
+	/*
+	 * Update tagged queuing modifier if using command tag queuing
+	 */
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+		    fcp_cmnd->task_attribute = TSK_HEAD_OF_QUEUE;
+		    break;
+		case ORDERED_QUEUE_TAG:
+		    fcp_cmnd->task_attribute = TSK_ORDERED;
+		    break;
+		default:
+		    fcp_cmnd->task_attribute = 0;
+		    break;
+		}
+	} else {
+		fcp_cmnd->task_attribute = 0;
+	}
+
 	cmd_pkt->fcp_rsp_dseg_len = 0; /* Let response come in status iocb */
 
 	DEBUG18(printk(KERN_INFO "%s(%ld): Total SG(s) Entries %d, Data"
@@ -1177,6 +1212,7 @@
 	struct scsi_cmnd *cmd = sp->cmd;
 	struct scsi_qla_host *vha = sp->fcport->vha;
 	struct qla_hw_data *ha = vha->hw;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -1260,6 +1296,18 @@
 	int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
 	host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
+	/* Update tagged queuing modifier -- default is TSK_SIMPLE (0). */
+	if (scsi_populate_tag_msg(cmd, tag)) {
+		switch (tag[0]) {
+		case HEAD_OF_QUEUE_TAG:
+			cmd_pkt->task = TSK_HEAD_OF_QUEUE;
+			break;
+		case ORDERED_QUEUE_TAG:
+			cmd_pkt->task = TSK_ORDERED;
+			break;
+		}
+	}
+
 	/* Load SCSI command packet. */
 	memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
 	host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_isr.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_isr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_isr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_isr.c	2011-05-19 00:06:34.000000000 -0400
@@ -414,7 +414,7 @@
 				    "marked OFFLINE!\n");
 				vha->flags.online = 0;
 			} else {
-				/* Check to see if MPI timeout occured */
+				/* Check to see if MPI timeout occurred */
 				if ((mbx & MBX_3) && (ha->flags.port0))
 					set_bit(MPI_RESET_NEEDED,
 					    &vha->dpc_flags);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_mbx.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_mbx.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_mbx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_mbx.c	2011-05-19 00:06:34.000000000 -0400
@@ -71,6 +71,13 @@
 		return QLA_FUNCTION_TIMEOUT;
 	}
 
+	if (ha->flags.isp82xx_fw_hung) {
+		/* Setting Link-Down error */
+		mcp->mb[0] = MBS_LINK_DOWN_ERROR;
+		rval = QLA_FUNCTION_FAILED;
+		goto premature_exit;
+	}
+
 	/*
 	 * Wait for active mailbox commands to finish by waiting at most tov
 	 * seconds. This is to serialize actual issuing of mailbox cmds during
@@ -83,13 +90,6 @@
 		return QLA_FUNCTION_TIMEOUT;
 	}
 
-	if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
-		/* Setting Link-Down error */
-		mcp->mb[0] = MBS_LINK_DOWN_ERROR;
-		rval = QLA_FUNCTION_FAILED;
-		goto premature_exit;
-	}
-
 	ha->flags.mbox_busy = 1;
 	/* Save mailbox command for debug */
 	ha->mcp = mcp;
@@ -223,7 +223,7 @@
 		ha->flags.mbox_int = 0;
 		clear_bit(MBX_INTERRUPT, &ha->mbx_cmd_flags);
 
-		if (IS_QLA82XX(ha) && ha->flags.fw_hung) {
+		if (ha->flags.isp82xx_fw_hung) {
 			ha->flags.mbox_busy = 0;
 			/* Setting Link-Down error */
 			mcp->mb[0] = MBS_LINK_DOWN_ERROR;
@@ -303,7 +303,7 @@
 			    !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 
 				qla_printk(KERN_WARNING, ha,
-				    "Mailbox command timeout occured. "
+				    "Mailbox command timeout occurred. "
 				    "Scheduling ISP " "abort. eeh_busy: 0x%x\n",
 				    ha->flags.eeh_busy);
 				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
@@ -321,7 +321,7 @@
 			    !test_bit(ISP_ABORT_RETRY, &vha->dpc_flags)) {
 
 				qla_printk(KERN_WARNING, ha,
-				    "Mailbox command timeout occured. "
+				    "Mailbox command timeout occurred. "
 				    "Issuing ISP abort.\n");
 
 				set_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags);
@@ -2462,22 +2462,19 @@
 		    "-- completion status (%x).\n", __func__,
 		    vha->host_no, le16_to_cpu(sts->comp_status)));
 		rval = QLA_FUNCTION_FAILED;
-	} else if (!(le16_to_cpu(sts->scsi_status) &
-	    SS_RESPONSE_INFO_LEN_VALID)) {
-		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-		    "-- no response info (%x).\n", __func__, vha->host_no,
-		    le16_to_cpu(sts->scsi_status)));
-		rval = QLA_FUNCTION_FAILED;
-	} else if (le32_to_cpu(sts->rsp_data_len) < 4) {
-		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-		    "-- not enough response info (%d).\n", __func__,
-		    vha->host_no, le32_to_cpu(sts->rsp_data_len)));
-		rval = QLA_FUNCTION_FAILED;
-	} else if (sts->data[3]) {
-		DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
-		    "-- response (%x).\n", __func__,
-		    vha->host_no, sts->data[3]));
-		rval = QLA_FUNCTION_FAILED;
+	} else if (le16_to_cpu(sts->scsi_status) &
+	    SS_RESPONSE_INFO_LEN_VALID) {
+		if (le32_to_cpu(sts->rsp_data_len) < 4) {
+			DEBUG2_3_11(printk("%s(%ld): ignoring inconsistent "
+			    "data length -- not enough response info (%d).\n",
+			    __func__, vha->host_no,
+			    le32_to_cpu(sts->rsp_data_len)));
+		} else if (sts->data[3]) {
+			DEBUG2_3_11(printk("%s(%ld): failed to complete IOCB "
+			    "-- response (%x).\n", __func__,
+			    vha->host_no, sts->data[3]));
+			rval = QLA_FUNCTION_FAILED;
+		}
 	}
 
 	/* Issue marker IOCB. */
@@ -3792,7 +3789,7 @@
 	mcp->mb[20] = LSW(MSD(mreq->send_dma));
 	mcp->mb[21] = MSW(MSD(mreq->send_dma));
 
-	/* recieve data address */
+	/* receive data address */
 	mcp->mb[16] = LSW(mreq->rcv_dma);
 	mcp->mb[17] = MSW(mreq->rcv_dma);
 	mcp->mb[6] = LSW(MSD(mreq->rcv_dma));
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_nx.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_nx.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_nx.c	2012-03-24 01:18:21.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_nx.c	2012-03-24 03:36:42.000000000 -0400
@@ -7,6 +7,7 @@
 #include "qla_def.h"
 #include <linux/delay.h>
 #include <linux/pci.h>
+#include <scsi/scsi_tcq.h>
 
 #define MASK(n)			((1ULL<<(n))-1)
 #define MN_WIN(addr) (((addr & 0x1fc0000) >> 1) | \
@@ -2547,7 +2548,7 @@
 			dsd_seg = (uint32_t *)&cmd_pkt->fcp_data_dseg_address;
 			*dsd_seg++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
 			*dsd_seg++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
-			*dsd_seg++ = dsd_list_len;
+			cmd_pkt->fcp_data_dseg_len = dsd_list_len;
 		} else {
 			*cur_dsd++ = cpu_to_le32(LSD(dsd_ptr->dsd_list_dma));
 			*cur_dsd++ = cpu_to_le32(MSD(dsd_ptr->dsd_list_dma));
@@ -2597,7 +2598,7 @@
  * qla82xx_start_scsi() - Send a SCSI command to the ISP
  * @sp: command to send to the ISP
  *
- * Returns non-zero if a failure occured, else zero.
+ * Returns non-zero if a failure occurred, else zero.
  */
 int
 qla82xx_start_scsi(srb_t *sp)
@@ -2620,6 +2621,7 @@
 	struct qla_hw_data *ha = vha->hw;
 	struct req_que *req = NULL;
 	struct rsp_que *rsp = NULL;
+	char		tag[2];
 
 	/* Setup device pointers. */
 	ret = 0;
@@ -2770,6 +2772,22 @@
 		int_to_scsilun(sp->cmd->device->lun, &cmd_pkt->lun);
 		host_to_fcp_swap((uint8_t *)&cmd_pkt->lun, sizeof(cmd_pkt->lun));
 
+		/*
+		 * Update tagged queuing modifier -- default is TSK_SIMPLE (0).
+		 */
+		if (scsi_populate_tag_msg(cmd, tag)) {
+			switch (tag[0]) {
+			case HEAD_OF_QUEUE_TAG:
+				ctx->fcp_cmnd->task_attribute =
+				    TSK_HEAD_OF_QUEUE;
+				break;
+			case ORDERED_QUEUE_TAG:
+				ctx->fcp_cmnd->task_attribute =
+				    TSK_ORDERED;
+				break;
+			}
+		}
+
 		/* build FCP_CMND IU */
 		memset(ctx->fcp_cmnd, 0, sizeof(struct fcp_cmnd));
 		int_to_scsilun(sp->cmd->device->lun, &ctx->fcp_cmnd->lun);
@@ -2835,6 +2853,20 @@
 		host_to_fcp_swap((uint8_t *)&cmd_pkt->lun,
 			sizeof(cmd_pkt->lun));
 
+		/*
+		 * Update tagged queuing modifier -- default is TSK_SIMPLE (0).
+		 */
+		if (scsi_populate_tag_msg(cmd, tag)) {
+			switch (tag[0]) {
+			case HEAD_OF_QUEUE_TAG:
+				cmd_pkt->task = TSK_HEAD_OF_QUEUE;
+				break;
+			case ORDERED_QUEUE_TAG:
+				cmd_pkt->task = TSK_ORDERED;
+				break;
+			}
+		}
+
 		/* Load SCSI command packet. */
 		memcpy(cmd_pkt->fcp_cdb, cmd->cmnd, cmd->cmd_len);
 		host_to_fcp_swap(cmd_pkt->fcp_cdb, sizeof(cmd_pkt->fcp_cdb));
@@ -3457,46 +3489,28 @@
 	}
 }
 
-static void
+int
 qla82xx_check_fw_alive(scsi_qla_host_t *vha)
 {
-	uint32_t fw_heartbeat_counter, halt_status;
-	struct qla_hw_data *ha = vha->hw;
+	uint32_t fw_heartbeat_counter;
+	int status = 0;
 
-	fw_heartbeat_counter = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
+	fw_heartbeat_counter = qla82xx_rd_32(vha->hw,
+		QLA82XX_PEG_ALIVE_COUNTER);
 	/* all 0xff, assume AER/EEH in progress, ignore */
 	if (fw_heartbeat_counter == 0xffffffff)
-		return;
+		return status;
 	if (vha->fw_heartbeat_counter == fw_heartbeat_counter) {
 		vha->seconds_since_last_heartbeat++;
 		/* FW not alive after 2 seconds */
 		if (vha->seconds_since_last_heartbeat == 2) {
 			vha->seconds_since_last_heartbeat = 0;
-			halt_status = qla82xx_rd_32(ha,
-				QLA82XX_PEG_HALT_STATUS1);
-			if (halt_status & HALT_STATUS_UNRECOVERABLE) {
-				set_bit(ISP_UNRECOVERABLE, &vha->dpc_flags);
-			} else {
-				qla_printk(KERN_INFO, ha,
-					"scsi(%ld): %s - detect abort needed\n",
-					vha->host_no, __func__);
-				set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
-			}
-			qla2xxx_wake_dpc(vha);
-			ha->flags.fw_hung = 1;
-			if (ha->flags.mbox_busy) {
-				ha->flags.mbox_int = 1;
-				DEBUG2(qla_printk(KERN_ERR, ha,
-					"Due to fw hung, doing premature "
-					"completion of mbx command\n"));
-				if (test_bit(MBX_INTR_WAIT,
-					&ha->mbx_cmd_flags))
-					complete(&ha->mbx_intr_comp);
-			}
+			status = 1;
 		}
 	} else
 		vha->seconds_since_last_heartbeat = 0;
 	vha->fw_heartbeat_counter = fw_heartbeat_counter;
+	return status;
 }
 
 /*
@@ -3557,6 +3571,8 @@
 			break;
 		case QLA82XX_DEV_NEED_RESET:
 			qla82xx_need_reset_handler(vha);
+			dev_init_timeout = jiffies +
+				(ha->nx_dev_init_timeout * HZ);
 			break;
 		case QLA82XX_DEV_NEED_QUIESCENT:
 			qla82xx_need_qsnt_handler(vha);
@@ -3596,30 +3612,18 @@
 
 void qla82xx_watchdog(scsi_qla_host_t *vha)
 {
-	uint32_t dev_state;
+	uint32_t dev_state, halt_status;
 	struct qla_hw_data *ha = vha->hw;
 
-	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
-
 	/* don't poll if reset is going on */
-	if (!(test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags) ||
-		test_bit(ABORT_ISP_ACTIVE, &vha->dpc_flags) ||
-		test_bit(ISP_ABORT_RETRY, &vha->dpc_flags))) {
-		if (dev_state == QLA82XX_DEV_NEED_RESET) {
+	if (!ha->flags.isp82xx_reset_hdlr_active) {
+		dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		if (dev_state == QLA82XX_DEV_NEED_RESET &&
+		    !test_bit(ISP_ABORT_NEEDED, &vha->dpc_flags)) {
 			qla_printk(KERN_WARNING, ha,
-				"%s(): Adapter reset needed!\n", __func__);
+			    "%s(): Adapter reset needed!\n", __func__);
 			set_bit(ISP_ABORT_NEEDED, &vha->dpc_flags);
 			qla2xxx_wake_dpc(vha);
-			ha->flags.fw_hung = 1;
-			if (ha->flags.mbox_busy) {
-				ha->flags.mbox_int = 1;
-				DEBUG2(qla_printk(KERN_ERR, ha,
-					"Need reset, doing premature "
-					"completion of mbx command\n"));
-				if (test_bit(MBX_INTR_WAIT,
-					&ha->mbx_cmd_flags))
-					complete(&ha->mbx_intr_comp);
-			}
 		} else if (dev_state == QLA82XX_DEV_NEED_QUIESCENT &&
 			!test_bit(ISP_QUIESCE_NEEDED, &vha->dpc_flags)) {
 			DEBUG(qla_printk(KERN_INFO, ha,
@@ -3629,6 +3633,31 @@
 			qla2xxx_wake_dpc(vha);
 		} else {
 			qla82xx_check_fw_alive(vha);
+			if (qla82xx_check_fw_alive(vha)) {
+				halt_status = qla82xx_rd_32(ha,
+				    QLA82XX_PEG_HALT_STATUS1);
+				if (halt_status & HALT_STATUS_UNRECOVERABLE) {
+					set_bit(ISP_UNRECOVERABLE,
+					    &vha->dpc_flags);
+				} else {
+					qla_printk(KERN_INFO, ha,
+					    "scsi(%ld): %s - detect abort needed\n",
+					    vha->host_no, __func__);
+					set_bit(ISP_ABORT_NEEDED,
+					    &vha->dpc_flags);
+				}
+				qla2xxx_wake_dpc(vha);
+				ha->flags.isp82xx_fw_hung = 1;
+				if (ha->flags.mbox_busy) {
+					ha->flags.mbox_int = 1;
+					DEBUG2(qla_printk(KERN_ERR, ha,
+					    "Due to fw hung, doing premature "
+					    "completion of mbx command\n"));
+					if (test_bit(MBX_INTR_WAIT,
+					    &ha->mbx_cmd_flags))
+						complete(&ha->mbx_intr_comp);
+				}
+			}
 		}
 	}
 }
@@ -3663,6 +3692,7 @@
 			"Exiting.\n", __func__, vha->host_no);
 		return QLA_SUCCESS;
 	}
+	ha->flags.isp82xx_reset_hdlr_active = 1;
 
 	qla82xx_idc_lock(ha);
 	dev_state = qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
@@ -3683,7 +3713,8 @@
 	qla82xx_idc_unlock(ha);
 
 	if (rval == QLA_SUCCESS) {
-		ha->flags.fw_hung = 0;
+		ha->flags.isp82xx_fw_hung = 0;
+		ha->flags.isp82xx_reset_hdlr_active = 0;
 		qla82xx_restart_isp(vha);
 	}
 
@@ -3791,3 +3822,71 @@
 
 	return status;
 }
+
+void
+qla82xx_chip_reset_cleanup(scsi_qla_host_t *vha)
+{
+	int i;
+	unsigned long flags;
+	struct qla_hw_data *ha = vha->hw;
+
+	/* Check if 82XX firmware is alive or not
+	 * We may have arrived here from NEED_RESET
+	 * detection only
+	 */
+	if (!ha->flags.isp82xx_fw_hung) {
+		for (i = 0; i < 2; i++) {
+			msleep(1000);
+			if (qla82xx_check_fw_alive(vha)) {
+				ha->flags.isp82xx_fw_hung = 1;
+				if (ha->flags.mbox_busy) {
+					ha->flags.mbox_int = 1;
+					complete(&ha->mbx_intr_comp);
+				}
+				break;
+			}
+		}
+	}
+
+	/* Abort all commands gracefully if fw NOT hung */
+	if (!ha->flags.isp82xx_fw_hung) {
+		int cnt, que;
+		srb_t *sp;
+		struct req_que *req;
+
+		spin_lock_irqsave(&ha->hardware_lock, flags);
+		for (que = 0; que < ha->max_req_queues; que++) {
+			req = ha->req_q_map[que];
+			if (!req)
+				continue;
+			for (cnt = 1; cnt < MAX_OUTSTANDING_COMMANDS; cnt++) {
+				sp = req->outstanding_cmds[cnt];
+				if (sp) {
+					if (!sp->ctx ||
+					    (sp->flags & SRB_FCP_CMND_DMA_VALID)) {
+						spin_unlock_irqrestore(
+						    &ha->hardware_lock, flags);
+						if (ha->isp_ops->abort_command(sp)) {
+							qla_printk(KERN_INFO, ha,
+							    "scsi(%ld): mbx abort command failed in %s\n",
+							    vha->host_no, __func__);
+						} else {
+							qla_printk(KERN_INFO, ha,
+							    "scsi(%ld): mbx abort command success in %s\n",
+							    vha->host_no, __func__);
+						}
+						spin_lock_irqsave(&ha->hardware_lock, flags);
+					}
+				}
+			}
+		}
+		spin_unlock_irqrestore(&ha->hardware_lock, flags);
+
+		/* Wait for pending cmds (physical and virtual) to complete */
+		if (!qla2x00_eh_wait_for_pending_commands(vha, 0, 0,
+		    WAIT_HOST) == QLA_SUCCESS) {
+			DEBUG2(qla_printk(KERN_INFO, ha,
+			    "Done wait for pending commands\n"));
+		}
+	}
+}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_os.c linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_os.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_os.c	2012-03-24 01:18:28.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_os.c	2012-03-24 03:36:46.000000000 -0400
@@ -349,7 +349,7 @@
 				"Can't create request queue\n");
 			goto fail;
 		}
-		ha->wq = create_workqueue("qla2xxx_wq");
+		ha->wq = alloc_workqueue("qla2xxx_wq", WQ_MEM_RECLAIM, 1);
 		vha->req = ha->req_q_map[req];
 		options |= BIT_1;
 		for (ques = 1; ques < ha->max_rsp_queues; ques++) {
@@ -506,7 +506,7 @@
 
 static inline srb_t *
 qla2x00_get_new_sp(scsi_qla_host_t *vha, fc_port_t *fcport,
-    struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+	struct scsi_cmnd *cmd)
 {
 	srb_t *sp;
 	struct qla_hw_data *ha = vha->hw;
@@ -520,14 +520,13 @@
 	sp->cmd = cmd;
 	sp->flags = 0;
 	CMD_SP(cmd) = (void *)sp;
-	cmd->scsi_done = done;
 	sp->ctx = NULL;
 
 	return sp;
 }
 
 static int
-qla2xxx_queuecommand_lck(struct scsi_cmnd *cmd, void (*done)(struct scsi_cmnd *))
+qla2xxx_queuecommand(struct Scsi_Host *host, struct scsi_cmnd *cmd)
 {
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
@@ -537,7 +536,6 @@
 	srb_t *sp;
 	int rval;
 
-	spin_unlock_irq(vha->host->host_lock);
 	if (ha->flags.eeh_busy) {
 		if (ha->flags.pci_channel_io_perm_failure)
 			cmd->result = DID_NO_CONNECT << 16;
@@ -569,40 +567,32 @@
 		goto qc24_target_busy;
 	}
 
-	sp = qla2x00_get_new_sp(base_vha, fcport, cmd, done);
+	sp = qla2x00_get_new_sp(base_vha, fcport, cmd);
 	if (!sp)
-		goto qc24_host_busy_lock;
+		goto qc24_host_busy;
 
 	rval = ha->isp_ops->start_scsi(sp);
 	if (rval != QLA_SUCCESS)
 		goto qc24_host_busy_free_sp;
 
-	spin_lock_irq(vha->host->host_lock);
-
 	return 0;
 
 qc24_host_busy_free_sp:
 	qla2x00_sp_free_dma(sp);
 	mempool_free(sp, ha->srb_mempool);
 
-qc24_host_busy_lock:
-	spin_lock_irq(vha->host->host_lock);
+qc24_host_busy:
 	return SCSI_MLQUEUE_HOST_BUSY;
 
 qc24_target_busy:
-	spin_lock_irq(vha->host->host_lock);
 	return SCSI_MLQUEUE_TARGET_BUSY;
 
 qc24_fail_command:
-	spin_lock_irq(vha->host->host_lock);
-	done(cmd);
+	cmd->scsi_done(cmd);
 
 	return 0;
 }
 
-static DEF_SCSI_QCMD(qla2xxx_queuecommand)
-
-
 /*
  * qla2x00_eh_wait_on_command
  *    Waits for the command to be returned by the Firmware for some
@@ -821,17 +811,20 @@
 {
 	scsi_qla_host_t *vha = shost_priv(cmd->device->host);
 	srb_t *sp;
-	int ret = SUCCESS;
+	int ret;
 	unsigned int id, lun;
 	unsigned long flags;
 	int wait = 0;
 	struct qla_hw_data *ha = vha->hw;
 
-	fc_block_scsi_eh(cmd);
-
 	if (!CMD_SP(cmd))
 		return SUCCESS;
 
+	ret = fc_block_scsi_eh(cmd);
+	if (ret != 0)
+		return ret;
+	ret = SUCCESS;
+
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
@@ -940,11 +933,13 @@
 	fc_port_t *fcport = (struct fc_port *) cmd->device->hostdata;
 	int err;
 
-	fc_block_scsi_eh(cmd);
-
 	if (!fcport)
 		return FAILED;
 
+	err = fc_block_scsi_eh(cmd);
+	if (err != 0)
+		return err;
+
 	qla_printk(KERN_INFO, vha->hw, "scsi(%ld:%d:%d): %s RESET ISSUED.\n",
 	    vha->host_no, cmd->device->id, cmd->device->lun, name);
 
@@ -1018,14 +1013,17 @@
 	int ret = FAILED;
 	unsigned int id, lun;
 
-	fc_block_scsi_eh(cmd);
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
 	if (!fcport)
 		return ret;
 
+	ret = fc_block_scsi_eh(cmd);
+	if (ret != 0)
+		return ret;
+	ret = FAILED;
+
 	qla_printk(KERN_INFO, vha->hw,
 	    "scsi(%ld:%d:%d): BUS RESET ISSUED.\n", vha->host_no, id, lun);
 
@@ -1048,7 +1046,7 @@
 
 eh_bus_reset_done:
 	qla_printk(KERN_INFO, vha->hw, "%s: reset %s\n", __func__,
-	    (ret == FAILED) ? "failed" : "succeded");
+	    (ret == FAILED) ? "failed" : "succeeded");
 
 	return ret;
 }
@@ -1078,14 +1076,17 @@
 	unsigned int id, lun;
 	scsi_qla_host_t *base_vha = pci_get_drvdata(ha->pdev);
 
-	fc_block_scsi_eh(cmd);
-
 	id = cmd->device->id;
 	lun = cmd->device->lun;
 
 	if (!fcport)
 		return ret;
 
+	ret = fc_block_scsi_eh(cmd);
+	if (ret != 0)
+		return ret;
+	ret = FAILED;
+
 	qla_printk(KERN_INFO, ha,
 	    "scsi(%ld:%d:%d): ADAPTER RESET ISSUED.\n", vha->host_no, id, lun);
 
@@ -1135,7 +1136,7 @@
 
 eh_host_reset_lock:
 	qla_printk(KERN_INFO, ha, "%s: reset %s\n", __func__,
-	    (ret == FAILED) ? "failed" : "succeded");
+	    (ret == FAILED) ? "failed" : "succeeded");
 
 	return ret;
 }
@@ -3805,7 +3806,7 @@
 		ha->flags.eeh_busy = 1;
 		/* For ISP82XX complete any pending mailbox cmd */
 		if (IS_QLA82XX(ha)) {
-			ha->flags.fw_hung = 1;
+			ha->flags.isp82xx_fw_hung = 1;
 			if (ha->flags.mbox_busy) {
 				ha->flags.mbox_int = 1;
 				DEBUG2(qla_printk(KERN_ERR, ha,
@@ -3901,7 +3902,7 @@
 			continue;
 		if (atomic_read(&other_pdev->enable_cnt)) {
 			DEBUG17(qla_printk(KERN_INFO, ha,
-			    "Found PCI func availabe and enabled at 0x%x\n",
+			    "Found PCI func available and enabled at 0x%x\n",
 			    fn));
 			pci_dev_put(other_pdev);
 			break;
@@ -3945,7 +3946,7 @@
 			qla82xx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
 			    QLA82XX_DEV_READY);
 			qla82xx_idc_unlock(ha);
-			ha->flags.fw_hung = 0;
+			ha->flags.isp82xx_fw_hung = 0;
 			rval = qla82xx_restart_isp(base_vha);
 			qla82xx_idc_lock(ha);
 			/* Clear driver state register */
@@ -3958,7 +3959,7 @@
 		    "This devfn is not reset owner = 0x%x\n", ha->pdev->devfn));
 		if ((qla82xx_rd_32(ha, QLA82XX_CRB_DEV_STATE) ==
 		    QLA82XX_DEV_READY)) {
-			ha->flags.fw_hung = 0;
+			ha->flags.isp82xx_fw_hung = 0;
 			rval = qla82xx_restart_isp(base_vha);
 			qla82xx_idc_lock(ha);
 			qla82xx_set_drv_active(base_vha);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_version.h linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_version.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla2xxx/qla_version.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla2xxx/qla_version.h	2011-05-19 00:06:34.000000000 -0400
@@ -7,9 +7,9 @@
 /*
  * Driver version
  */
-#define QLA2XXX_VERSION      "8.03.05-k0"
+#define QLA2XXX_VERSION      "8.03.07.00"
 
 #define QLA_DRIVER_MAJOR_VER	8
 #define QLA_DRIVER_MINOR_VER	3
-#define QLA_DRIVER_PATCH_VER	5
+#define QLA_DRIVER_PATCH_VER	7
 #define QLA_DRIVER_BETA_VER	0
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_def.h linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_def.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_def.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_def.h	2011-05-19 00:06:34.000000000 -0400
@@ -53,6 +53,9 @@
 #define PCI_DEVICE_ID_QLOGIC_ISP8022	0x8022
 #endif
 
+#define ISP4XXX_PCI_FN_1	0x1
+#define ISP4XXX_PCI_FN_2	0x3
+
 #define QLA_SUCCESS			0
 #define QLA_ERROR			1
 
@@ -179,7 +182,7 @@
 	uint16_t flags;		/* (1) Status flags. */
 
 #define SRB_DMA_VALID		BIT_3	/* DMA Buffer mapped. */
-#define SRB_GOT_SENSE		BIT_4	/* sense data recieved. */
+#define SRB_GOT_SENSE		BIT_4	/* sense data received. */
 	uint8_t state;		/* (1) Status flags. */
 
 #define SRB_NO_QUEUE_STATE	 0	/* Request is in between states */
@@ -233,9 +236,6 @@
 
 	unsigned long flags;	/* DDB Flags */
 
-	unsigned long dev_scan_wait_to_start_relogin;
-	unsigned long dev_scan_wait_to_complete_relogin;
-
 	uint16_t fw_ddb_index;	/* DDB firmware index */
 	uint16_t options;
 	uint32_t fw_ddb_device_state; /* F/W Device State  -- see ql4_fw.h */
@@ -289,8 +289,6 @@
  * DDB flags.
  */
 #define DF_RELOGIN		0	/* Relogin to device */
-#define DF_NO_RELOGIN		1	/* Do not relogin if IOCTL
-					 * logged it out */
 #define DF_ISNS_DISCOVERED	2	/* Device was discovered via iSNS */
 #define DF_FO_MASKED		3
 
@@ -376,7 +374,7 @@
 #define AF_LINK_UP			8 /* 0x00000100 */
 #define AF_IRQ_ATTACHED			10 /* 0x00000400 */
 #define AF_DISABLE_ACB_COMPLETE		11 /* 0x00000800 */
-#define AF_HBA_GOING_AWAY		12 /* 0x00001000 */
+#define AF_HA_REMOVAL			12 /* 0x00001000 */
 #define AF_INTx_ENABLED			15 /* 0x00008000 */
 #define AF_MSI_ENABLED			16 /* 0x00010000 */
 #define AF_MSIX_ENABLED			17 /* 0x00020000 */
@@ -479,7 +477,6 @@
 	uint32_t timer_active;
 
 	/* Recovery Timers */
-	uint32_t discovery_wait;
 	atomic_t check_relogin_timeouts;
 	uint32_t retry_reset_ha_cnt;
 	uint32_t isp_reset_timer;	/* reset test timer */
@@ -765,6 +762,5 @@
 /* Defines for process_aen() */
 #define PROCESS_ALL_AENS	 0
 #define FLUSH_DDB_CHANGED_AENS	 1
-#define RELOGIN_DDB_CHANGED_AENS 2
 
 #endif	/*_QLA4XXX_H */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_fw.h linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_fw.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_fw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_fw.h	2011-05-19 00:06:34.000000000 -0400
@@ -455,6 +455,7 @@
 	uint8_t res0;	/* 07 */
 	uint16_t eth_mtu_size;	/* 08-09 */
 	uint16_t add_fw_options;	/* 0A-0B */
+#define SERIALIZE_TASK_MGMT		0x0400
 
 	uint8_t hb_interval;	/* 0C */
 	uint8_t inst_num; /* 0D */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_glbl.h linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_glbl.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_glbl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_glbl.h	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,6 @@
 void qla4_8xxx_set_drv_active(struct scsi_qla_host *ha);
 
 extern int ql4xextended_error_logging;
-extern int ql4xdiscoverywait;
 extern int ql4xdontresethba;
 extern int ql4xenablemsix;
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_init.c linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_init.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_init.c	2011-05-19 00:06:34.000000000 -0400
@@ -723,13 +723,38 @@
 	return relogin;
 }
 
+static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
+{
+	unsigned long wtime;
+
+	/* Flush the 0x8014 AEN from the firmware as a result of
+	 * Auto connect. We are basically doing get_firmware_ddb()
+	 * to determine whether we need to log back in or not.
+	 * Trying to do a set ddb before we have processed 0x8014
+	 * will result in another set_ddb() for the same ddb. In other
+	 * words there will be stale entries in the aen_q.
+	 */
+	wtime = jiffies + (2 * HZ);
+	do {
+		if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
+			if (ha->firmware_state & (BIT_2 | BIT_0))
+				return;
+
+		if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
+			qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
+
+		msleep(1000);
+	} while (!time_after_eq(jiffies, wtime));
+}
+
 /**
- * qla4xxx_configure_ddbs - builds driver ddb list
+ * qla4xxx_build_ddb_list - builds driver ddb list
  * @ha: Pointer to host adapter structure.
  *
  * This routine searches for all valid firmware ddb entries and builds
  * an internal ddb list. Ddbs that are considered valid are those with
  * a device state of SESSION_ACTIVE.
+ * A relogin (set_ddb) is issued for DDBs that are not online.
  **/
 static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha)
 {
@@ -744,6 +769,8 @@
 	uint32_t ipv6_device;
 	uint32_t new_tgt;
 
+	qla4xxx_flush_AENS(ha);
+
 	fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry),
 			&fw_ddb_entry_dma, GFP_KERNEL);
 	if (fw_ddb_entry == NULL) {
@@ -847,144 +874,6 @@
 	return status;
 }
 
-struct qla4_relog_scan {
-	int halt_wait;
-	uint32_t conn_err;
-	uint32_t fw_ddb_index;
-	uint32_t next_fw_ddb_index;
-	uint32_t fw_ddb_device_state;
-};
-
-static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs)
-{
-	struct ddb_entry *ddb_entry;
-
-	if (qla4_is_relogin_allowed(ha, rs->conn_err)) {
-		/* We either have a device that is in
-		 * the process of relogging in or a
-		 * device that is waiting to be
-		 * relogged in */
-		rs->halt_wait = 0;
-
-		ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha,
-							   rs->fw_ddb_index);
-		if (ddb_entry == NULL)
-			return QLA_ERROR;
-
-		if (ddb_entry->dev_scan_wait_to_start_relogin != 0
-		    && time_after_eq(jiffies,
-				     ddb_entry->
-				     dev_scan_wait_to_start_relogin))
-		{
-			ddb_entry->dev_scan_wait_to_start_relogin = 0;
-			qla4xxx_set_ddb_entry(ha, rs->fw_ddb_index, 0);
-		}
-	}
-	return QLA_SUCCESS;
-}
-
-static int qla4_scan_for_relogin(struct scsi_qla_host *ha,
-				 struct qla4_relog_scan *rs)
-{
-	int error;
-
-	/* scan for relogins
-	 * ----------------- */
-	for (rs->fw_ddb_index = 0; rs->fw_ddb_index < MAX_DDB_ENTRIES;
-	     rs->fw_ddb_index = rs->next_fw_ddb_index) {
-		if (qla4xxx_get_fwddb_entry(ha, rs->fw_ddb_index, NULL, 0,
-					    NULL, &rs->next_fw_ddb_index,
-					    &rs->fw_ddb_device_state,
-					    &rs->conn_err, NULL, NULL)
-		    == QLA_ERROR)
-			return QLA_ERROR;
-
-		if (rs->fw_ddb_device_state == DDB_DS_LOGIN_IN_PROCESS)
-			rs->halt_wait = 0;
-
-		if (rs->fw_ddb_device_state == DDB_DS_SESSION_FAILED ||
-		    rs->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE) {
-			error = qla4_test_rdy(ha, rs);
-			if (error)
-				return error;
-		}
-
-		/* We know we've reached the last device when
-		 * next_fw_ddb_index is 0 */
-		if (rs->next_fw_ddb_index == 0)
-			break;
-	}
-	return QLA_SUCCESS;
-}
-
-/**
- * qla4xxx_devices_ready - wait for target devices to be logged in
- * @ha: pointer to adapter structure
- *
- * This routine waits up to ql4xdiscoverywait seconds
- * F/W database during driver load time.
- **/
-static int qla4xxx_devices_ready(struct scsi_qla_host *ha)
-{
-	int error;
-	unsigned long discovery_wtime;
-	struct qla4_relog_scan rs;
-
-	discovery_wtime = jiffies + (ql4xdiscoverywait * HZ);
-
-	DEBUG(printk("Waiting (%d) for devices ...\n", ql4xdiscoverywait));
-	do {
-		/* poll for AEN. */
-		qla4xxx_get_firmware_state(ha);
-		if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) {
-			/* Set time-between-relogin timer */
-			qla4xxx_process_aen(ha, RELOGIN_DDB_CHANGED_AENS);
-		}
-
-		/* if no relogins active or needed, halt discvery wait */
-		rs.halt_wait = 1;
-
-		error = qla4_scan_for_relogin(ha, &rs);
-
-		if (rs.halt_wait) {
-			DEBUG2(printk("scsi%ld: %s: Delay halted.  Devices "
-				      "Ready.\n", ha->host_no, __func__));
-			return QLA_SUCCESS;
-		}
-
-		msleep(2000);
-	} while (!time_after_eq(jiffies, discovery_wtime));
-
-	DEBUG3(qla4xxx_get_conn_event_log(ha));
-
-	return QLA_SUCCESS;
-}
-
-static void qla4xxx_flush_AENS(struct scsi_qla_host *ha)
-{
-	unsigned long wtime;
-
-	/* Flush the 0x8014 AEN from the firmware as a result of
-	 * Auto connect. We are basically doing get_firmware_ddb()
-	 * to determine whether we need to log back in or not.
-	 *  Trying to do a set ddb before we have processed 0x8014
-	 *  will result in another set_ddb() for the same ddb. In other
-	 *  words there will be stale entries in the aen_q.
-	 */
-	wtime = jiffies + (2 * HZ);
-	do {
-		if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS)
-			if (ha->firmware_state & (BIT_2 | BIT_0))
-				return;
-
-		if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
-			qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS);
-
-		msleep(1000);
-	} while (!time_after_eq(jiffies, wtime));
-
-}
-
 static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha)
 {
 	uint16_t fw_ddb_index;
@@ -996,29 +885,12 @@
 
 	for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++)
 		ha->fw_ddb_index_map[fw_ddb_index] =
-			(struct ddb_entry *)INVALID_ENTRY;
+		    (struct ddb_entry *)INVALID_ENTRY;
 
 	ha->tot_ddbs = 0;
 
-	qla4xxx_flush_AENS(ha);
-
-	/* Wait for an AEN */
-	qla4xxx_devices_ready(ha);
-
-	/*
-	 * First perform device discovery for active
-	 * fw ddb indexes and build
-	 * ddb list.
-	 */
-	if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR)
-		return status;
-
-	/*
-	 * Targets can come online after the inital discovery, so processing
-	 * the aens here will catch them.
-	 */
-	if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags))
-		qla4xxx_process_aen(ha, PROCESS_ALL_AENS);
+	/* Perform device discovery and build ddb list. */
+	status = qla4xxx_build_ddb_list(ha);
 
 	return status;
 }
@@ -1466,7 +1338,7 @@
 	}
 
 	DEBUG2(printk("scsi%ld: initialize adapter: %s\n", ha->host_no,
-	    status == QLA_ERROR ? "FAILED" : "SUCCEDED"));
+	    status == QLA_ERROR ? "FAILED" : "SUCCEEDED"));
 	return status;
 }
 
@@ -1537,7 +1409,6 @@
 		uint32_t state, uint32_t conn_err)
 {
 	struct ddb_entry * ddb_entry;
-	uint32_t old_fw_ddb_device_state;
 
 	/* check for out of range index */
 	if (fw_ddb_index >= MAX_DDB_ENTRIES)
@@ -1553,27 +1424,18 @@
 	}
 
 	/* Device already exists in our database. */
-	old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
 	DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for "
 		      "index [%d]\n", ha->host_no, __func__,
 		      ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
-	if (old_fw_ddb_device_state == state &&
-	    state == DDB_DS_SESSION_ACTIVE) {
-		if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) {
-			atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
-			iscsi_unblock_session(ddb_entry->sess);
-		}
-		return QLA_SUCCESS;
-	}
 
 	ddb_entry->fw_ddb_device_state = state;
 	/* Device is back online. */
-	if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) {
+	if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) &&
+	   (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) {
 		atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
 		atomic_set(&ddb_entry->relogin_retry_count, 0);
 		atomic_set(&ddb_entry->relogin_timer, 0);
 		clear_bit(DF_RELOGIN, &ddb_entry->flags);
-		clear_bit(DF_NO_RELOGIN, &ddb_entry->flags);
 		iscsi_unblock_session(ddb_entry->sess);
 		iscsi_session_event(ddb_entry->sess,
 				    ISCSI_KEVENT_CREATE_SESSION);
@@ -1581,7 +1443,7 @@
 		 * Change the lun state to READY in case the lun TIMEOUT before
 		 * the device came back.
 		 */
-	} else {
+	} else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) {
 		/* Device went away, mark device missing */
 		if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
 			DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing "
@@ -1598,7 +1460,6 @@
 		 */
 		if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED &&
 		    !test_bit(DF_RELOGIN, &ddb_entry->flags) &&
-		    !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) &&
 		    qla4_is_relogin_allowed(ha, conn_err)) {
 			/*
 			 * This triggers a relogin.  After the relogin_timer
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_isr.c linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_isr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_isr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_isr.c	2011-05-19 00:06:34.000000000 -0400
@@ -801,7 +801,7 @@
 			       &ha->reg->ctrl_status);
 			readl(&ha->reg->ctrl_status);
 
-			if (!test_bit(AF_HBA_GOING_AWAY, &ha->flags))
+			if (!test_bit(AF_HA_REMOVAL, &ha->flags))
 				set_bit(DPC_RESET_HA_INTR, &ha->dpc_flags);
 
 			break;
@@ -1008,34 +1008,9 @@
 					      mbox_sts[0], mbox_sts[2],
 					      mbox_sts[3]));
 				break;
-			} else if (process_aen == RELOGIN_DDB_CHANGED_AENS) {
-				/* for use during init time, we only want to
-				 * relogin non-active ddbs */
-				struct ddb_entry *ddb_entry;
-
-				ddb_entry =
-					/* FIXME: name length? */
-					qla4xxx_lookup_ddb_by_fw_index(ha,
-								       mbox_sts[2]);
-				if (!ddb_entry)
-					break;
-
-				ddb_entry->dev_scan_wait_to_complete_relogin =
-					0;
-				ddb_entry->dev_scan_wait_to_start_relogin =
-					jiffies +
-					((ddb_entry->default_time2wait +
-					  4) * HZ);
-
-				DEBUG2(printk("scsi%ld: ddb [%d] initate"
-					      " RELOGIN after %d seconds\n",
-					      ha->host_no,
-					      ddb_entry->fw_ddb_index,
-					      ddb_entry->default_time2wait +
-					      4));
-				break;
 			}
-
+		case PROCESS_ALL_AENS:
+		default:
 			if (mbox_sts[1] == 0) {	/* Global DB change. */
 				qla4xxx_reinitialize_ddb_list(ha);
 			} else if (mbox_sts[1] == 1) {	/* Specific device. */
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_mbx.c linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_mbx.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_mbx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_mbx.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,6 +32,7 @@
 	u_long wait_count;
 	uint32_t intr_status;
 	unsigned long flags = 0;
+	uint32_t dev_state;
 
 	/* Make sure that pointers are valid */
 	if (!mbx_cmd || !mbx_sts) {
@@ -40,12 +41,23 @@
 		return status;
 	}
 
-	if (is_qla8022(ha) &&
-	    test_bit(AF_FW_RECOVERY, &ha->flags)) {
-		DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: prematurely "
-		    "completing mbx cmd as firmware recovery detected\n",
-		    ha->host_no, __func__));
-		return status;
+	if (is_qla8022(ha)) {
+		if (test_bit(AF_FW_RECOVERY, &ha->flags)) {
+			DEBUG2(ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: "
+			    "prematurely completing mbx cmd as firmware "
+			    "recovery detected\n", ha->host_no, __func__));
+			return status;
+		}
+		/* Do not send any mbx cmd if h/w is in failed state*/
+		qla4_8xxx_idc_lock(ha);
+		dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+		qla4_8xxx_idc_unlock(ha);
+		if (dev_state == QLA82XX_DEV_FAILED) {
+			ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: H/W is in "
+			    "failed state, do not send any mailbox commands\n",
+			    ha->host_no, __func__);
+			return status;
+		}
 	}
 
 	if ((is_aer_supported(ha)) &&
@@ -139,7 +151,7 @@
 	if (test_bit(AF_IRQ_ATTACHED, &ha->flags) &&
 	    test_bit(AF_INTERRUPTS_ON, &ha->flags) &&
 	    test_bit(AF_ONLINE, &ha->flags) &&
-	    !test_bit(AF_HBA_GOING_AWAY, &ha->flags)) {
+	    !test_bit(AF_HA_REMOVAL, &ha->flags)) {
 		/* Do not poll for completion. Use completion queue */
 		set_bit(AF_MBOX_COMMAND_NOPOLL, &ha->flags);
 		wait_for_completion_timeout(&ha->mbx_intr_comp, MBOX_TOV * HZ);
@@ -395,9 +407,6 @@
 	/*memcpy(ha->alias, init_fw_cb->Alias,
 	       min(sizeof(ha->alias), sizeof(init_fw_cb->Alias)));*/
 
-	/* Save Command Line Paramater info */
-	ha->discovery_wait = ql4xdiscoverywait;
-
 	if (ha->acb_version == ACB_SUPPORTED) {
 		ha->ipv6_options = init_fw_cb->ipv6_opts;
 		ha->ipv6_addl_options = init_fw_cb->ipv6_addtl_opts;
@@ -467,6 +476,11 @@
 
 	init_fw_cb->fw_options &= __constant_cpu_to_le16(~FWOPT_TARGET_MODE);
 
+	/* Set bit for "serialize task mgmt" all other bits need to be zero */
+	init_fw_cb->add_fw_options = 0;
+	init_fw_cb->add_fw_options |=
+	    __constant_cpu_to_le16(SERIALIZE_TASK_MGMT);
+
 	if (qla4xxx_set_ifcb(ha, &mbox_cmd[0], &mbox_sts[0], init_fw_cb_dma)
 		!= QLA_SUCCESS) {
 		DEBUG2(printk(KERN_WARNING
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_nvram.h linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_nvram.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_nvram.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_nvram.h	2011-05-19 00:06:34.000000000 -0400
@@ -28,7 +28,7 @@
 #define	 FM93C56A_ERASE	      0x3
 #define	 FM93C56A_ERASE_ALL   0x0
 
-/* Command Extentions */
+/* Command Extensions */
 #define	 FM93C56A_WEN_EXT	 0x3
 #define	 FM93C56A_WRITE_ALL_EXT	 0x1
 #define	 FM93C56A_WDS_EXT	 0x0
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_nx.c linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_nx.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_nx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_nx.c	2011-05-19 00:06:34.000000000 -0400
@@ -2304,14 +2304,13 @@
 void
 qla4_8xxx_disable_intrs(struct scsi_qla_host *ha)
 {
-	if (test_bit(AF_INTERRUPTS_ON, &ha->flags))
+	if (test_and_clear_bit(AF_INTERRUPTS_ON, &ha->flags))
 		qla4_8xxx_mbx_intr_disable(ha);
 
 	spin_lock_irq(&ha->hardware_lock);
 	/* BIT 10 - set */
 	qla4_8xxx_wr_32(ha, ha->nx_legacy_intr.tgt_mask_reg, 0x0400);
 	spin_unlock_irq(&ha->hardware_lock);
-	clear_bit(AF_INTERRUPTS_ON, &ha->flags);
 }
 
 struct ql4_init_msix_entry {
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_os.c linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_os.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_os.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_os.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,10 +29,6 @@
 /*
  * Module parameter information and variables
  */
-int ql4xdiscoverywait = 60;
-module_param(ql4xdiscoverywait, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ql4xdiscoverywait, "Discovery wait time");
-
 int ql4xdontresethba = 0;
 module_param(ql4xdontresethba, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(ql4xdontresethba,
@@ -55,6 +51,17 @@
 		" 2 = enable MSI interrupt mechanism.");
 
 #define QL4_DEF_QDEPTH 32
+static int ql4xmaxqdepth = QL4_DEF_QDEPTH;
+module_param(ql4xmaxqdepth, int, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(ql4xmaxqdepth,
+		"Maximum queue depth to report for target devices.\n"
+		" Default: 32.");
+
+static int ql4xsess_recovery_tmo = QL4_SESS_RECOVERY_TMO;
+module_param(ql4xsess_recovery_tmo, int, S_IRUGO);
+MODULE_PARM_DESC(ql4xsess_recovery_tmo,
+		"Target Session Recovery Timeout.\n"
+		" Default: 30 sec.");
 
 /*
  * SCSI host template entry points
@@ -165,7 +172,7 @@
 		DEBUG2(printk("scsi%ld: %s: ddb [%d] session recovery timeout "
 			      "of (%d) secs exhausted, marking device DEAD.\n",
 			      ha->host_no, __func__, ddb_entry->fw_ddb_index,
-			      QL4_SESS_RECOVERY_TMO));
+			      ddb_entry->sess->recovery_tmo));
 	}
 }
 
@@ -295,7 +302,7 @@
 {
 	int err;
 
-	ddb_entry->sess->recovery_tmo = QL4_SESS_RECOVERY_TMO;
+	ddb_entry->sess->recovery_tmo = ql4xsess_recovery_tmo;
 
 	err = iscsi_add_session(ddb_entry->sess, ddb_entry->fw_ddb_index);
 	if (err) {
@@ -753,12 +760,6 @@
 	if (!pci_channel_offline(ha->pdev))
 		pci_read_config_word(ha->pdev, PCI_VENDOR_ID, &w);
 
-	if (test_bit(AF_HBA_GOING_AWAY, &ha->flags)) {
-		DEBUG2(ql4_printk(KERN_INFO, ha, "%s exited. HBA GOING AWAY\n",
-		    __func__));
-		return;
-	}
-
 	if (is_qla8022(ha)) {
 		qla4_8xxx_watchdog(ha);
 	}
@@ -812,7 +813,7 @@
 					);
 				start_dpc++;
 				DEBUG(printk("scsi%ld:%d:%d: ddb [%d] "
-					     "initate relogin after"
+					     "initiate relogin after"
 					     " %d seconds\n",
 					     ha->host_no, ddb_entry->bus,
 					     ddb_entry->target,
@@ -1067,7 +1068,6 @@
 
 	/* Disable the board */
 	ql4_printk(KERN_INFO, ha, "Disabling the board\n");
-	set_bit(AF_HBA_GOING_AWAY, &ha->flags);
 
 	qla4xxx_abort_active_cmds(ha, DID_NO_CONNECT << 16);
 	qla4xxx_mark_all_devices_missing(ha);
@@ -1213,11 +1213,32 @@
 
 	clear_bit(DPC_RESET_ACTIVE, &ha->dpc_flags);
 	DEBUG2(printk("scsi%ld: recover adapter: %s\n", ha->host_no,
-	    status == QLA_ERROR ? "FAILED" : "SUCCEDED"));
+	    status == QLA_ERROR ? "FAILED" : "SUCCEEDED"));
 
 	return status;
 }
 
+static void qla4xxx_relogin_all_devices(struct scsi_qla_host *ha)
+{
+	struct ddb_entry *ddb_entry, *dtemp;
+
+	list_for_each_entry_safe(ddb_entry, dtemp, &ha->ddb_list, list) {
+		if ((atomic_read(&ddb_entry->state) == DDB_STATE_MISSING) ||
+		    (atomic_read(&ddb_entry->state) == DDB_STATE_DEAD)) {
+			if (ddb_entry->fw_ddb_device_state ==
+			    DDB_DS_SESSION_ACTIVE) {
+				atomic_set(&ddb_entry->state, DDB_STATE_ONLINE);
+				ql4_printk(KERN_INFO, ha, "scsi%ld: %s: ddb[%d]"
+				    " marked ONLINE\n",	ha->host_no, __func__,
+				    ddb_entry->fw_ddb_index);
+
+				iscsi_unblock_session(ddb_entry->sess);
+			} else
+				qla4xxx_relogin_device(ha, ddb_entry);
+		}
+	}
+}
+
 void qla4xxx_wake_dpc(struct scsi_qla_host *ha)
 {
 	if (ha->dpc_thread &&
@@ -1259,11 +1280,6 @@
 		goto do_dpc_exit;
 	}
 
-	/* HBA is in the process of being permanently disabled.
-	 * Don't process anything */
-	if (test_bit(AF_HBA_GOING_AWAY, &ha->flags))
-		return;
-
 	if (is_qla8022(ha)) {
 		if (test_bit(DPC_HA_UNRECOVERABLE, &ha->dpc_flags)) {
 			qla4_8xxx_idc_lock(ha);
@@ -1331,13 +1347,7 @@
 	if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
 		if (!test_bit(AF_LINK_UP, &ha->flags)) {
 			/* ---- link down? --- */
-			list_for_each_entry_safe(ddb_entry, dtemp,
-						 &ha->ddb_list, list) {
-				if (atomic_read(&ddb_entry->state) ==
-						DDB_STATE_ONLINE)
-					qla4xxx_mark_device_missing(ha,
-							ddb_entry);
-			}
+			qla4xxx_mark_all_devices_missing(ha);
 		} else {
 			/* ---- link up? --- *
 			 * F/W will auto login to all devices ONLY ONCE after
@@ -1346,30 +1356,7 @@
 			 * manually relogin to devices when recovering from
 			 * connection failures, logouts, expired KATO, etc. */
 
-			list_for_each_entry_safe(ddb_entry, dtemp,
-							&ha->ddb_list, list) {
-				if ((atomic_read(&ddb_entry->state) ==
-						 DDB_STATE_MISSING) ||
-				    (atomic_read(&ddb_entry->state) ==
-						 DDB_STATE_DEAD)) {
-					if (ddb_entry->fw_ddb_device_state ==
-					    DDB_DS_SESSION_ACTIVE) {
-						atomic_set(&ddb_entry->state,
-							   DDB_STATE_ONLINE);
-						ql4_printk(KERN_INFO, ha,
-						    "scsi%ld: %s: ddb[%d]"
-						    " marked ONLINE\n",
-						    ha->host_no, __func__,
-						    ddb_entry->fw_ddb_index);
-
-						iscsi_unblock_session(
-						    ddb_entry->sess);
-					} else
-						qla4xxx_relogin_device(
-						    ha, ddb_entry);
-				}
-
-			}
+			qla4xxx_relogin_all_devices(ha);
 		}
 	}
 
@@ -1630,6 +1617,7 @@
 	uint8_t init_retry_count = 0;
 	char buf[34];
 	struct qla4_8xxx_legacy_intr_set *nx_legacy_intr;
+	uint32_t dev_state;
 
 	if (pci_enable_device(pdev))
 		return -1;
@@ -1713,6 +1701,18 @@
 	status = qla4xxx_initialize_adapter(ha, REBUILD_DDB_LIST);
 	while ((!test_bit(AF_ONLINE, &ha->flags)) &&
 	    init_retry_count++ < MAX_INIT_RETRIES) {
+
+		if (is_qla8022(ha)) {
+			qla4_8xxx_idc_lock(ha);
+			dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
+			qla4_8xxx_idc_unlock(ha);
+			if (dev_state == QLA82XX_DEV_FAILED) {
+				ql4_printk(KERN_WARNING, ha, "%s: don't retry "
+				    "initialize adapter. H/W is in failed state\n",
+				    __func__);
+				break;
+			}
+		}
 		DEBUG2(printk("scsi: %s: retrying adapter initialization "
 			      "(%d)\n", __func__, init_retry_count));
 
@@ -1815,6 +1815,44 @@
 }
 
 /**
+ * qla4xxx_prevent_other_port_reinit - prevent other port from re-initialize
+ * @ha: pointer to adapter structure
+ *
+ * Mark the other ISP-4xxx port to indicate that the driver is being removed,
+ * so that the other port will not re-initialize while in the process of
+ * removing the ha due to driver unload or hba hotplug.
+ **/
+static void qla4xxx_prevent_other_port_reinit(struct scsi_qla_host *ha)
+{
+	struct scsi_qla_host *other_ha = NULL;
+	struct pci_dev *other_pdev = NULL;
+	int fn = ISP4XXX_PCI_FN_2;
+
+	/*iscsi function numbers for ISP4xxx is 1 and 3*/
+	if (PCI_FUNC(ha->pdev->devfn) & BIT_1)
+		fn = ISP4XXX_PCI_FN_1;
+
+	other_pdev =
+		pci_get_domain_bus_and_slot(pci_domain_nr(ha->pdev->bus),
+		ha->pdev->bus->number, PCI_DEVFN(PCI_SLOT(ha->pdev->devfn),
+		fn));
+
+	/* Get other_ha if other_pdev is valid and state is enable*/
+	if (other_pdev) {
+		if (atomic_read(&other_pdev->enable_cnt)) {
+			other_ha = pci_get_drvdata(other_pdev);
+			if (other_ha) {
+				set_bit(AF_HA_REMOVAL, &other_ha->flags);
+				DEBUG2(ql4_printk(KERN_INFO, ha, "%s: "
+				    "Prevent %s reinit\n", __func__,
+				    dev_name(&other_ha->pdev->dev)));
+			}
+		}
+		pci_dev_put(other_pdev);
+	}
+}
+
+/**
  * qla4xxx_remove_adapter - calback function to remove adapter.
  * @pci_dev: PCI device pointer
  **/
@@ -1824,7 +1862,8 @@
 
 	ha = pci_get_drvdata(pdev);
 
-	set_bit(AF_HBA_GOING_AWAY, &ha->flags);
+	if (!is_qla8022(ha))
+		qla4xxx_prevent_other_port_reinit(ha);
 
 	/* remove devs from iscsi_sessions to scsi_devices */
 	qla4xxx_free_ddb_list(ha);
@@ -1868,10 +1907,15 @@
 {
 	struct iscsi_cls_session *sess = starget_to_session(sdev->sdev_target);
 	struct ddb_entry *ddb = sess->dd_data;
+	int queue_depth = QL4_DEF_QDEPTH;
 
 	sdev->hostdata = ddb;
 	sdev->tagged_supported = 1;
-	scsi_activate_tcq(sdev, QL4_DEF_QDEPTH);
+
+	if (ql4xmaxqdepth != 0 && ql4xmaxqdepth <= 0xffffU)
+		queue_depth = ql4xmaxqdepth;
+
+	scsi_activate_tcq(sdev, queue_depth);
 	return 0;
 }
 
@@ -2066,7 +2110,7 @@
 
 	ql4_printk(KERN_INFO, ha,
 	    "scsi%ld:%d:%d: Abort command - %s\n",
-	    ha->host_no, id, lun, (ret == SUCCESS) ? "succeded" : "failed");
+	    ha->host_no, id, lun, (ret == SUCCESS) ? "succeeded" : "failed");
 
 	return ret;
 }
@@ -2234,7 +2278,7 @@
 		return_status = SUCCESS;
 
 	ql4_printk(KERN_INFO, ha, "HOST RESET %s.\n",
-		   return_status == FAILED ? "FAILED" : "SUCCEDED");
+		   return_status == FAILED ? "FAILED" : "SUCCEEDED");
 
 	return return_status;
 }
@@ -2448,7 +2492,7 @@
 	/* Initialize device or resume if in suspended state */
 	rc = pci_enable_device(pdev);
 	if (rc) {
-		ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Cant re-enable "
+		ql4_printk(KERN_WARNING, ha, "scsi%ld: %s: Can't re-enable "
 		    "device after reset\n", ha->host_no, __func__);
 		goto exit_slot_reset;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_version.h linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_version.h
--- linux-libre-2.6.38-gnu/drivers/scsi/qla4xxx/ql4_version.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qla4xxx/ql4_version.h	2011-05-19 00:06:34.000000000 -0400
@@ -5,4 +5,4 @@
  * See LICENSE.qla4xxx for copyright and licensing details.
  */
 
-#define QLA4XXX_DRIVER_VERSION	"5.02.00-k5"
+#define QLA4XXX_DRIVER_VERSION	"5.02.00-k6"
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/qlogicpti.c linux-libre-2.6.39-gnu/drivers/scsi/qlogicpti.c
--- linux-libre-2.6.38-gnu/drivers/scsi/qlogicpti.c	2012-03-24 01:17:39.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/qlogicpti.c	2012-03-24 03:36:18.000000000 -0400
@@ -1292,15 +1292,22 @@
 	.use_clustering		= ENABLE_CLUSTERING,
 };
 
-static int __devinit qpti_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static const struct of_device_id qpti_match[];
+static int __devinit qpti_sbus_probe(struct platform_device *op)
 {
-	struct scsi_host_template *tpnt = match->data;
+	const struct of_device_id *match;
+	struct scsi_host_template *tpnt;
 	struct device_node *dp = op->dev.of_node;
 	struct Scsi_Host *host;
 	struct qlogicpti *qpti;
 	static int nqptis;
 	const char *fcode;
 
+	match = of_match_device(qpti_match, &op->dev);
+	if (!match)
+		return -EINVAL;
+	tpnt = match->data;
+
 	/* Sometimes Antares cards come up not completely
 	 * setup, and we get a report of a zero IRQ.
 	 */
@@ -1457,7 +1464,7 @@
 };
 MODULE_DEVICE_TABLE(of, qpti_match);
 
-static struct of_platform_driver qpti_sbus_driver = {
+static struct platform_driver qpti_sbus_driver = {
 	.driver = {
 		.name = "qpti",
 		.owner = THIS_MODULE,
@@ -1469,12 +1476,12 @@
 
 static int __init qpti_init(void)
 {
-	return of_register_platform_driver(&qpti_sbus_driver);
+	return platform_driver_register(&qpti_sbus_driver);
 }
 
 static void __exit qpti_exit(void)
 {
-	of_unregister_platform_driver(&qpti_sbus_driver);
+	platform_driver_unregister(&qpti_sbus_driver);
 }
 
 MODULE_DESCRIPTION("QlogicISP SBUS driver");
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_debug.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_debug.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_debug.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_debug.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,32 +89,34 @@
 /* With these defaults, this driver will make 1 host with 1 target
  * (id 0) containing 1 logical unit (lun 0). That is 1 device.
  */
+#define DEF_ATO 1
 #define DEF_DELAY   1
 #define DEF_DEV_SIZE_MB   8
-#define DEF_EVERY_NTH   0
-#define DEF_NUM_PARTS   0
-#define DEF_OPTS   0
-#define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
-#define DEF_PTYPE   0
+#define DEF_DIF 0
+#define DEF_DIX 0
 #define DEF_D_SENSE   0
-#define DEF_NO_LUN_0   0
-#define DEF_VIRTUAL_GB   0
+#define DEF_EVERY_NTH   0
 #define DEF_FAKE_RW	0
-#define DEF_VPD_USE_HOSTNO 1
-#define DEF_SECTOR_SIZE 512
-#define DEF_DIX 0
-#define DEF_DIF 0
 #define DEF_GUARD 0
-#define DEF_ATO 1
-#define DEF_PHYSBLK_EXP 0
+#define DEF_LBPU 0
+#define DEF_LBPWS 0
+#define DEF_LBPWS10 0
 #define DEF_LOWEST_ALIGNED 0
+#define DEF_NO_LUN_0   0
+#define DEF_NUM_PARTS   0
+#define DEF_OPTS   0
 #define DEF_OPT_BLKS 64
+#define DEF_PHYSBLK_EXP 0
+#define DEF_PTYPE   0
+#define DEF_SCSI_LEVEL   5    /* INQUIRY, byte2 [5->SPC-3] */
+#define DEF_SECTOR_SIZE 512
+#define DEF_UNMAP_ALIGNMENT 0
+#define DEF_UNMAP_GRANULARITY 1
 #define DEF_UNMAP_MAX_BLOCKS 0xFFFFFFFF
 #define DEF_UNMAP_MAX_DESC 256
-#define DEF_UNMAP_GRANULARITY 1
-#define DEF_UNMAP_ALIGNMENT 0
-#define DEF_TPWS 0
-#define DEF_TPU 0
+#define DEF_VIRTUAL_GB   0
+#define DEF_VPD_USE_HOSTNO 1
+#define DEF_WRITESAME_LENGTH 0xFFFF
 
 /* bit mask values for scsi_debug_opts */
 #define SCSI_DEBUG_OPT_NOISE   1
@@ -144,6 +146,7 @@
 /* when 1==SCSI_DEBUG_OPT_MEDIUM_ERR, a medium error is simulated at this
  * sector on read commands: */
 #define OPT_MEDIUM_ERR_ADDR   0x1234 /* that's sector 4660 in decimal */
+#define OPT_MEDIUM_ERR_NUM    10     /* number of consecutive medium errs */
 
 /* If REPORT LUNS has luns >= 256 it can choose "flat space" (value 1)
  * or "peripheral device" addressing (value 0) */
@@ -155,36 +158,38 @@
 #define SCSI_DEBUG_CANQUEUE  255
 
 static int scsi_debug_add_host = DEF_NUM_HOST;
+static int scsi_debug_ato = DEF_ATO;
 static int scsi_debug_delay = DEF_DELAY;
 static int scsi_debug_dev_size_mb = DEF_DEV_SIZE_MB;
+static int scsi_debug_dif = DEF_DIF;
+static int scsi_debug_dix = DEF_DIX;
+static int scsi_debug_dsense = DEF_D_SENSE;
 static int scsi_debug_every_nth = DEF_EVERY_NTH;
+static int scsi_debug_fake_rw = DEF_FAKE_RW;
+static int scsi_debug_guard = DEF_GUARD;
+static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
 static int scsi_debug_max_luns = DEF_MAX_LUNS;
 static int scsi_debug_max_queue = SCSI_DEBUG_CANQUEUE;
-static int scsi_debug_num_parts = DEF_NUM_PARTS;
+static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
 static int scsi_debug_no_uld = 0;
+static int scsi_debug_num_parts = DEF_NUM_PARTS;
 static int scsi_debug_num_tgts = DEF_NUM_TGTS; /* targets per host */
+static int scsi_debug_opt_blks = DEF_OPT_BLKS;
 static int scsi_debug_opts = DEF_OPTS;
-static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
+static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
 static int scsi_debug_ptype = DEF_PTYPE; /* SCSI peripheral type (0==disk) */
-static int scsi_debug_dsense = DEF_D_SENSE;
-static int scsi_debug_no_lun_0 = DEF_NO_LUN_0;
+static int scsi_debug_scsi_level = DEF_SCSI_LEVEL;
+static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
 static int scsi_debug_virtual_gb = DEF_VIRTUAL_GB;
-static int scsi_debug_fake_rw = DEF_FAKE_RW;
 static int scsi_debug_vpd_use_hostno = DEF_VPD_USE_HOSTNO;
-static int scsi_debug_sector_size = DEF_SECTOR_SIZE;
-static int scsi_debug_dix = DEF_DIX;
-static int scsi_debug_dif = DEF_DIF;
-static int scsi_debug_guard = DEF_GUARD;
-static int scsi_debug_ato = DEF_ATO;
-static int scsi_debug_physblk_exp = DEF_PHYSBLK_EXP;
-static int scsi_debug_lowest_aligned = DEF_LOWEST_ALIGNED;
-static int scsi_debug_opt_blks = DEF_OPT_BLKS;
-static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
-static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
-static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
+static unsigned int scsi_debug_lbpu = DEF_LBPU;
+static unsigned int scsi_debug_lbpws = DEF_LBPWS;
+static unsigned int scsi_debug_lbpws10 = DEF_LBPWS10;
 static unsigned int scsi_debug_unmap_alignment = DEF_UNMAP_ALIGNMENT;
-static unsigned int scsi_debug_tpws = DEF_TPWS;
-static unsigned int scsi_debug_tpu = DEF_TPU;
+static unsigned int scsi_debug_unmap_granularity = DEF_UNMAP_GRANULARITY;
+static unsigned int scsi_debug_unmap_max_blocks = DEF_UNMAP_MAX_BLOCKS;
+static unsigned int scsi_debug_unmap_max_desc = DEF_UNMAP_MAX_DESC;
+static unsigned int scsi_debug_write_same_length = DEF_WRITESAME_LENGTH;
 
 static int scsi_debug_cmnd_count = 0;
 
@@ -206,6 +211,11 @@
 
 #define SCSI_DEBUG_MAX_CMD_LEN 32
 
+static unsigned int scsi_debug_lbp(void)
+{
+	return scsi_debug_lbpu | scsi_debug_lbpws | scsi_debug_lbpws10;
+}
+
 struct sdebug_dev_info {
 	struct list_head dev_list;
 	unsigned char sense_buff[SDEBUG_SENSE_LEN];	/* weak nexus */
@@ -727,7 +737,7 @@
 	/* Optimal Transfer Length */
 	put_unaligned_be32(scsi_debug_opt_blks, &arr[8]);
 
-	if (scsi_debug_tpu) {
+	if (scsi_debug_lbpu) {
 		/* Maximum Unmap LBA Count */
 		put_unaligned_be32(scsi_debug_unmap_max_blocks, &arr[16]);
 
@@ -744,7 +754,10 @@
 	/* Optimal Unmap Granularity */
 	put_unaligned_be32(scsi_debug_unmap_granularity, &arr[24]);
 
-	return 0x3c; /* Mandatory page length for thin provisioning */
+	/* Maximum WRITE SAME Length */
+	put_unaligned_be64(scsi_debug_write_same_length, &arr[32]);
+
+	return 0x3c; /* Mandatory page length for Logical Block Provisioning */
 
 	return sizeof(vpdb0_data);
 }
@@ -767,12 +780,15 @@
 	memset(arr, 0, 0x8);
 	arr[0] = 0;			/* threshold exponent */
 
-	if (scsi_debug_tpu)
+	if (scsi_debug_lbpu)
 		arr[1] = 1 << 7;
 
-	if (scsi_debug_tpws)
+	if (scsi_debug_lbpws)
 		arr[1] |= 1 << 6;
 
+	if (scsi_debug_lbpws10)
+		arr[1] |= 1 << 5;
+
 	return 0x8;
 }
 
@@ -831,7 +847,8 @@
 			arr[n++] = 0x89;  /* ATA information */
 			arr[n++] = 0xb0;  /* Block limits (SBC) */
 			arr[n++] = 0xb1;  /* Block characteristics (SBC) */
-			arr[n++] = 0xb2;  /* Thin provisioning (SBC) */
+			if (scsi_debug_lbp()) /* Logical Block Prov. (SBC) */
+				arr[n++] = 0xb2;
 			arr[3] = n - 4;	  /* number of supported VPD pages */
 		} else if (0x80 == cmd[2]) { /* unit serial number */
 			arr[1] = cmd[2];	/*sanity */
@@ -879,7 +896,7 @@
 		} else if (0xb1 == cmd[2]) { /* Block characteristics (SBC) */
 			arr[1] = cmd[2];        /*sanity */
 			arr[3] = inquiry_evpd_b1(&arr[4]);
-		} else if (0xb2 == cmd[2]) { /* Thin provisioning (SBC) */
+		} else if (0xb2 == cmd[2]) { /* Logical Block Prov. (SBC) */
 			arr[1] = cmd[2];        /*sanity */
 			arr[3] = inquiry_evpd_b2(&arr[4]);
 		} else {
@@ -1053,8 +1070,8 @@
 	arr[13] = scsi_debug_physblk_exp & 0xf;
 	arr[14] = (scsi_debug_lowest_aligned >> 8) & 0x3f;
 
-	if (scsi_debug_tpu || scsi_debug_tpws)
-		arr[14] |= 0x80; /* TPE */
+	if (scsi_debug_lbp())
+		arr[14] |= 0x80; /* LBPME */
 
 	arr[15] = scsi_debug_lowest_aligned & 0xff;
 
@@ -1791,15 +1808,15 @@
 		return ret;
 
 	if ((SCSI_DEBUG_OPT_MEDIUM_ERR & scsi_debug_opts) &&
-	    (lba <= OPT_MEDIUM_ERR_ADDR) &&
+	    (lba <= (OPT_MEDIUM_ERR_ADDR + OPT_MEDIUM_ERR_NUM - 1)) &&
 	    ((lba + num) > OPT_MEDIUM_ERR_ADDR)) {
 		/* claim unrecoverable read error */
-		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR,
-				0);
+		mk_sense_buffer(devip, MEDIUM_ERROR, UNRECOVERED_READ_ERR, 0);
 		/* set info field and valid bit for fixed descriptor */
 		if (0x70 == (devip->sense_buff[0] & 0x7f)) {
 			devip->sense_buff[0] |= 0x80;	/* Valid bit */
-			ret = OPT_MEDIUM_ERR_ADDR;
+			ret = (lba < OPT_MEDIUM_ERR_ADDR)
+			      ? OPT_MEDIUM_ERR_ADDR : (int)lba;
 			devip->sense_buff[3] = (ret >> 24) & 0xff;
 			devip->sense_buff[4] = (ret >> 16) & 0xff;
 			devip->sense_buff[5] = (ret >> 8) & 0xff;
@@ -2084,6 +2101,12 @@
 	if (ret)
 		return ret;
 
+	if (num > scsi_debug_write_same_length) {
+		mk_sense_buffer(devip, ILLEGAL_REQUEST, INVALID_FIELD_IN_CDB,
+				0);
+		return check_condition_result;
+	}
+
 	write_lock_irqsave(&atomic_rw, iflags);
 
 	if (unmap && scsi_debug_unmap_granularity) {
@@ -2431,7 +2454,7 @@
 		printk(KERN_INFO "scsi_debug: slave_destroy <%u %u %u %u>\n",
 		       sdp->host->host_no, sdp->channel, sdp->id, sdp->lun);
 	if (devip) {
-		/* make this slot avaliable for re-use */
+		/* make this slot available for re-use */
 		devip->used = 0;
 		sdp->hostdata = NULL;
 	}
@@ -2695,37 +2718,40 @@
    /sys/bus/pseudo/drivers/scsi_debug directory is changed.
  */
 module_param_named(add_host, scsi_debug_add_host, int, S_IRUGO | S_IWUSR);
+module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
 module_param_named(delay, scsi_debug_delay, int, S_IRUGO | S_IWUSR);
 module_param_named(dev_size_mb, scsi_debug_dev_size_mb, int, S_IRUGO);
+module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
+module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
 module_param_named(dsense, scsi_debug_dsense, int, S_IRUGO | S_IWUSR);
 module_param_named(every_nth, scsi_debug_every_nth, int, S_IRUGO | S_IWUSR);
 module_param_named(fake_rw, scsi_debug_fake_rw, int, S_IRUGO | S_IWUSR);
+module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
+module_param_named(lbpu, scsi_debug_lbpu, int, S_IRUGO);
+module_param_named(lbpws, scsi_debug_lbpws, int, S_IRUGO);
+module_param_named(lbpws10, scsi_debug_lbpws10, int, S_IRUGO);
+module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
 module_param_named(max_luns, scsi_debug_max_luns, int, S_IRUGO | S_IWUSR);
 module_param_named(max_queue, scsi_debug_max_queue, int, S_IRUGO | S_IWUSR);
 module_param_named(no_lun_0, scsi_debug_no_lun_0, int, S_IRUGO | S_IWUSR);
 module_param_named(no_uld, scsi_debug_no_uld, int, S_IRUGO);
 module_param_named(num_parts, scsi_debug_num_parts, int, S_IRUGO);
 module_param_named(num_tgts, scsi_debug_num_tgts, int, S_IRUGO | S_IWUSR);
+module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
 module_param_named(opts, scsi_debug_opts, int, S_IRUGO | S_IWUSR);
+module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
 module_param_named(ptype, scsi_debug_ptype, int, S_IRUGO | S_IWUSR);
 module_param_named(scsi_level, scsi_debug_scsi_level, int, S_IRUGO);
-module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
-module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
-		   S_IRUGO | S_IWUSR);
 module_param_named(sector_size, scsi_debug_sector_size, int, S_IRUGO);
-module_param_named(dix, scsi_debug_dix, int, S_IRUGO);
-module_param_named(dif, scsi_debug_dif, int, S_IRUGO);
-module_param_named(guard, scsi_debug_guard, int, S_IRUGO);
-module_param_named(ato, scsi_debug_ato, int, S_IRUGO);
-module_param_named(physblk_exp, scsi_debug_physblk_exp, int, S_IRUGO);
-module_param_named(opt_blks, scsi_debug_opt_blks, int, S_IRUGO);
-module_param_named(lowest_aligned, scsi_debug_lowest_aligned, int, S_IRUGO);
+module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
+module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
 module_param_named(unmap_max_blocks, scsi_debug_unmap_max_blocks, int, S_IRUGO);
 module_param_named(unmap_max_desc, scsi_debug_unmap_max_desc, int, S_IRUGO);
-module_param_named(unmap_granularity, scsi_debug_unmap_granularity, int, S_IRUGO);
-module_param_named(unmap_alignment, scsi_debug_unmap_alignment, int, S_IRUGO);
-module_param_named(tpu, scsi_debug_tpu, int, S_IRUGO);
-module_param_named(tpws, scsi_debug_tpws, int, S_IRUGO);
+module_param_named(virtual_gb, scsi_debug_virtual_gb, int, S_IRUGO | S_IWUSR);
+module_param_named(vpd_use_hostno, scsi_debug_vpd_use_hostno, int,
+		   S_IRUGO | S_IWUSR);
+module_param_named(write_same_length, scsi_debug_write_same_length, int,
+		   S_IRUGO | S_IWUSR);
 
 MODULE_AUTHOR("Eric Youngdale + Douglas Gilbert");
 MODULE_DESCRIPTION("SCSI debug adapter driver");
@@ -2733,36 +2759,38 @@
 MODULE_VERSION(SCSI_DEBUG_VERSION);
 
 MODULE_PARM_DESC(add_host, "0..127 hosts allowed(def=1)");
+MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
 MODULE_PARM_DESC(delay, "# of jiffies to delay response(def=1)");
 MODULE_PARM_DESC(dev_size_mb, "size in MB of ram shared by devs(def=8)");
+MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
+MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
 MODULE_PARM_DESC(dsense, "use descriptor sense format(def=0 -> fixed)");
 MODULE_PARM_DESC(every_nth, "timeout every nth command(def=0)");
 MODULE_PARM_DESC(fake_rw, "fake reads/writes instead of copying (def=0)");
+MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
+MODULE_PARM_DESC(lbpu, "enable LBP, support UNMAP command (def=0)");
+MODULE_PARM_DESC(lbpws, "enable LBP, support WRITE SAME(16) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(lbpws10, "enable LBP, support WRITE SAME(10) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
 MODULE_PARM_DESC(max_luns, "number of LUNs per target to simulate(def=1)");
 MODULE_PARM_DESC(max_queue, "max number of queued commands (1 to 255(def))");
 MODULE_PARM_DESC(no_lun_0, "no LU number 0 (def=0 -> have lun 0)");
 MODULE_PARM_DESC(no_uld, "stop ULD (e.g. sd driver) attaching (def=0))");
 MODULE_PARM_DESC(num_parts, "number of partitions(def=0)");
 MODULE_PARM_DESC(num_tgts, "number of targets per host to simulate(def=1)");
+MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
 MODULE_PARM_DESC(opts, "1->noise, 2->medium_err, 4->timeout, 8->recovered_err... (def=0)");
+MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
 MODULE_PARM_DESC(ptype, "SCSI peripheral type(def=0[disk])");
 MODULE_PARM_DESC(scsi_level, "SCSI level to simulate(def=5[SPC-3])");
-MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
-MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
 MODULE_PARM_DESC(sector_size, "logical block size in bytes (def=512)");
-MODULE_PARM_DESC(physblk_exp, "physical block exponent (def=0)");
-MODULE_PARM_DESC(opt_blks, "optimal transfer length in block (def=64)");
-MODULE_PARM_DESC(lowest_aligned, "lowest aligned lba (def=0)");
-MODULE_PARM_DESC(dix, "data integrity extensions mask (def=0)");
-MODULE_PARM_DESC(dif, "data integrity field type: 0-3 (def=0)");
-MODULE_PARM_DESC(guard, "protection checksum: 0=crc, 1=ip (def=0)");
-MODULE_PARM_DESC(ato, "application tag ownership: 0=disk 1=host (def=1)");
+MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
+MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
 MODULE_PARM_DESC(unmap_max_blocks, "max # of blocks can be unmapped in one cmd (def=0xffffffff)");
 MODULE_PARM_DESC(unmap_max_desc, "max # of ranges that can be unmapped in one cmd (def=256)");
-MODULE_PARM_DESC(unmap_granularity, "thin provisioning granularity in blocks (def=1)");
-MODULE_PARM_DESC(unmap_alignment, "lowest aligned thin provisioning lba (def=0)");
-MODULE_PARM_DESC(tpu, "enable TP, support UNMAP command (def=0)");
-MODULE_PARM_DESC(tpws, "enable TP, support WRITE SAME(16) with UNMAP bit (def=0)");
+MODULE_PARM_DESC(virtual_gb, "virtual gigabyte size (def=0 -> use dev_size_mb)");
+MODULE_PARM_DESC(vpd_use_hostno, "0 -> dev ids ignore hostno (def=1 -> unique dev ids)");
+MODULE_PARM_DESC(write_same_length, "Maximum blocks per WRITE SAME cmd (def=0xffff)");
 
 static char sdebug_info[256];
 
@@ -3150,7 +3178,7 @@
 {
 	ssize_t count;
 
-	if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0)
+	if (!scsi_debug_lbp())
 		return scnprintf(buf, PAGE_SIZE, "0-%u\n",
 				 sdebug_store_sectors);
 
@@ -3333,8 +3361,8 @@
 		memset(dif_storep, 0xff, dif_size);
 	}
 
-	/* Thin Provisioning */
-	if (scsi_debug_tpu || scsi_debug_tpws) {
+	/* Logical Block Provisioning */
+	if (scsi_debug_lbp()) {
 		unsigned int map_bytes;
 
 		scsi_debug_unmap_max_blocks =
@@ -3664,7 +3692,7 @@
 			errsts = resp_readcap16(SCpnt, devip);
 		else if (cmd[1] == SAI_GET_LBA_STATUS) {
 
-			if (scsi_debug_tpu == 0 && scsi_debug_tpws == 0) {
+			if (scsi_debug_lbp() == 0) {
 				mk_sense_buffer(devip, ILLEGAL_REQUEST,
 						INVALID_COMMAND_OPCODE, 0);
 				errsts = check_condition_result;
@@ -3775,8 +3803,10 @@
 		}
 		break;
 	case WRITE_SAME_16:
+	case WRITE_SAME:
 		if (cmd[1] & 0x8) {
-			if (scsi_debug_tpws == 0) {
+			if ((*cmd == WRITE_SAME_16 && scsi_debug_lbpws == 0) ||
+			    (*cmd == WRITE_SAME && scsi_debug_lbpws10 == 0)) {
 				mk_sense_buffer(devip, ILLEGAL_REQUEST,
 						INVALID_FIELD_IN_CDB, 0);
 				errsts = check_condition_result;
@@ -3785,8 +3815,6 @@
 		}
 		if (errsts)
 			break;
-		/* fall through */
-	case WRITE_SAME:
 		errsts = check_readiness(SCpnt, 0, devip);
 		if (errsts)
 			break;
@@ -3798,7 +3826,7 @@
 		if (errsts)
 			break;
 
-		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_tpu == 0) {
+		if (scsi_debug_unmap_max_desc == 0 || scsi_debug_lbpu == 0) {
 			mk_sense_buffer(devip, ILLEGAL_REQUEST,
 					INVALID_COMMAND_OPCODE, 0);
 			errsts = check_condition_result;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_devinfo.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_devinfo.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_devinfo.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_devinfo.c	2011-05-19 00:06:34.000000000 -0400
@@ -382,6 +382,91 @@
 EXPORT_SYMBOL(scsi_dev_info_list_add_keyed);
 
 /**
+ * scsi_dev_info_list_del_keyed - remove one dev_info list entry.
+ * @vendor:	vendor string
+ * @model:	model (product) string
+ * @key:	specify list to use
+ *
+ * Description:
+ * 	Remove and destroy one dev_info entry for @vendor, @model
+ * 	in list specified by @key.
+ *
+ * Returns: 0 OK, -error on failure.
+ **/
+int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key)
+{
+	struct scsi_dev_info_list *devinfo, *found = NULL;
+	struct scsi_dev_info_list_table *devinfo_table =
+		scsi_devinfo_lookup_by_key(key);
+
+	if (IS_ERR(devinfo_table))
+		return PTR_ERR(devinfo_table);
+
+	list_for_each_entry(devinfo, &devinfo_table->scsi_dev_info_list,
+			    dev_info_list) {
+		if (devinfo->compatible) {
+			/*
+			 * Behave like the older version of get_device_flags.
+			 */
+			size_t max;
+			/*
+			 * XXX why skip leading spaces? If an odd INQUIRY
+			 * value, that should have been part of the
+			 * scsi_static_device_list[] entry, such as "  FOO"
+			 * rather than "FOO". Since this code is already
+			 * here, and we don't know what device it is
+			 * trying to work with, leave it as-is.
+			 */
+			max = 8;	/* max length of vendor */
+			while ((max > 0) && *vendor == ' ') {
+				max--;
+				vendor++;
+			}
+			/*
+			 * XXX removing the following strlen() would be
+			 * good, using it means that for a an entry not in
+			 * the list, we scan every byte of every vendor
+			 * listed in scsi_static_device_list[], and never match
+			 * a single one (and still have to compare at
+			 * least the first byte of each vendor).
+			 */
+			if (memcmp(devinfo->vendor, vendor,
+				    min(max, strlen(devinfo->vendor))))
+				continue;
+			/*
+			 * Skip spaces again.
+			 */
+			max = 16;	/* max length of model */
+			while ((max > 0) && *model == ' ') {
+				max--;
+				model++;
+			}
+			if (memcmp(devinfo->model, model,
+				   min(max, strlen(devinfo->model))))
+				continue;
+			found = devinfo;
+		} else {
+			if (!memcmp(devinfo->vendor, vendor,
+				     sizeof(devinfo->vendor)) &&
+			     !memcmp(devinfo->model, model,
+				      sizeof(devinfo->model)))
+				found = devinfo;
+		}
+		if (found)
+			break;
+	}
+
+	if (found) {
+		list_del(&found->dev_info_list);
+		kfree(found);
+		return 0;
+	}
+
+	return -ENOENT;
+}
+EXPORT_SYMBOL(scsi_dev_info_list_del_keyed);
+
+/**
  * scsi_dev_info_list_add_str - parse dev_list and add to the scsi_dev_info_list.
  * @dev_list:	string of device flags to add
  *
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_error.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_error.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_error.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_error.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,14 +3,14 @@
  *
  *  SCSI error/timeout handling
  *      Initial versions: Eric Youngdale.  Based upon conversations with
- *                        Leonard Zubkoff and David Miller at Linux Expo, 
+ *                        Leonard Zubkoff and David Miller at Linux Expo,
  *                        ideas originating from all over the place.
  *
  *	Restructured scsi_unjam_host and associated functions.
  *	September 04, 2002 Mike Anderson (andmike@us.ibm.com)
  *
  *	Forward port of Russell King's (rmk@arm.linux.org.uk) changes and
- *	minor  cleanups.
+ *	minor cleanups.
  *	September 30, 2002 Mike Anderson (andmike@us.ibm.com)
  */
 
@@ -129,14 +129,15 @@
 {
 	struct scsi_cmnd *scmd = req->special;
 	enum blk_eh_timer_return rtn = BLK_EH_NOT_HANDLED;
+	struct Scsi_Host *host = scmd->device->host;
 
 	trace_scsi_dispatch_cmd_timeout(scmd);
 	scsi_log_completion(scmd, TIMEOUT_ERROR);
 
-	if (scmd->device->host->transportt->eh_timed_out)
-		rtn = scmd->device->host->transportt->eh_timed_out(scmd);
-	else if (scmd->device->host->hostt->eh_timed_out)
-		rtn = scmd->device->host->hostt->eh_timed_out(scmd);
+	if (host->transportt->eh_timed_out)
+		rtn = host->transportt->eh_timed_out(scmd);
+	else if (host->hostt->eh_timed_out)
+		rtn = host->hostt->eh_timed_out(scmd);
 
 	if (unlikely(rtn == BLK_EH_NOT_HANDLED &&
 		     !scsi_eh_scmd_add(scmd, SCSI_EH_CANCEL_CMD))) {
@@ -195,7 +196,7 @@
 				++total_failures;
 				if (scmd->eh_eflags & SCSI_EH_CANCEL_CMD)
 					++cmd_cancel;
-				else 
+				else
 					++cmd_failed;
 			}
 		}
@@ -214,7 +215,7 @@
 
 	SCSI_LOG_ERROR_RECOVERY(2, printk("Total of %d commands on %d"
 					  " devices require eh work\n",
-				  total_failures, devices_failed));
+				   total_failures, devices_failed));
 }
 #endif
 
@@ -223,7 +224,7 @@
  * @scmd:	Cmd to have sense checked.
  *
  * Return value:
- * 	SUCCESS or FAILED or NEEDS_RETRY
+ *	SUCCESS or FAILED or NEEDS_RETRY or TARGET_ERROR
  *
  * Notes:
  *	When a deferred error is detected the current command has
@@ -294,7 +295,7 @@
 			return NEEDS_RETRY;
 		}
 		/*
-		 * if the device is in the process of becoming ready, we 
+		 * if the device is in the process of becoming ready, we
 		 * should retry.
 		 */
 		if ((sshdr.asc == 0x04) && (sshdr.ascq == 0x01))
@@ -326,17 +327,19 @@
 		 */
 		return SUCCESS;
 
-		/* these three are not supported */
+		/* these are not supported */
 	case COPY_ABORTED:
 	case VOLUME_OVERFLOW:
 	case MISCOMPARE:
-		return SUCCESS;
+	case BLANK_CHECK:
+	case DATA_PROTECT:
+		return TARGET_ERROR;
 
 	case MEDIUM_ERROR:
 		if (sshdr.asc == 0x11 || /* UNRECOVERED READ ERR */
 		    sshdr.asc == 0x13 || /* AMNF DATA FIELD */
 		    sshdr.asc == 0x14) { /* RECORD NOT FOUND */
-			return SUCCESS;
+			return TARGET_ERROR;
 		}
 		return NEEDS_RETRY;
 
@@ -344,11 +347,9 @@
 		if (scmd->device->retry_hwerror)
 			return ADD_TO_MLQUEUE;
 		else
-			return SUCCESS;
+			return TARGET_ERROR;
 
 	case ILLEGAL_REQUEST:
-	case BLANK_CHECK:
-	case DATA_PROTECT:
 	default:
 		return SUCCESS;
 	}
@@ -488,7 +489,7 @@
  */
 static void scsi_eh_done(struct scsi_cmnd *scmd)
 {
-	struct completion     *eh_action;
+	struct completion *eh_action;
 
 	SCSI_LOG_ERROR_RECOVERY(3,
 		printk("%s scmd: %p result: %x\n",
@@ -507,22 +508,23 @@
 {
 	unsigned long flags;
 	int rtn;
+	struct Scsi_Host *host = scmd->device->host;
+	struct scsi_host_template *hostt = host->hostt;
 
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Host RST\n",
 					  __func__));
 
-	if (!scmd->device->host->hostt->eh_host_reset_handler)
+	if (!hostt->eh_host_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_host_reset_handler(scmd);
+	rtn = hostt->eh_host_reset_handler(scmd);
 
 	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
+		if (!hostt->skip_settle_delay)
 			ssleep(HOST_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+		spin_lock_irqsave(host->host_lock, flags);
+		scsi_report_bus_reset(host, scmd_channel(scmd));
+		spin_unlock_irqrestore(host->host_lock, flags);
 	}
 
 	return rtn;
@@ -536,22 +538,23 @@
 {
 	unsigned long flags;
 	int rtn;
+	struct Scsi_Host *host = scmd->device->host;
+	struct scsi_host_template *hostt = host->hostt;
 
 	SCSI_LOG_ERROR_RECOVERY(3, printk("%s: Snd Bus RST\n",
 					  __func__));
 
-	if (!scmd->device->host->hostt->eh_bus_reset_handler)
+	if (!hostt->eh_bus_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_bus_reset_handler(scmd);
+	rtn = hostt->eh_bus_reset_handler(scmd);
 
 	if (rtn == SUCCESS) {
-		if (!scmd->device->host->hostt->skip_settle_delay)
+		if (!hostt->skip_settle_delay)
 			ssleep(BUS_RESET_SETTLE_TIME);
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
-		scsi_report_bus_reset(scmd->device->host,
-				      scmd_channel(scmd));
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+		spin_lock_irqsave(host->host_lock, flags);
+		scsi_report_bus_reset(host, scmd_channel(scmd));
+		spin_unlock_irqrestore(host->host_lock, flags);
 	}
 
 	return rtn;
@@ -577,16 +580,18 @@
 {
 	unsigned long flags;
 	int rtn;
+	struct Scsi_Host *host = scmd->device->host;
+	struct scsi_host_template *hostt = host->hostt;
 
-	if (!scmd->device->host->hostt->eh_target_reset_handler)
+	if (!hostt->eh_target_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_target_reset_handler(scmd);
+	rtn = hostt->eh_target_reset_handler(scmd);
 	if (rtn == SUCCESS) {
-		spin_lock_irqsave(scmd->device->host->host_lock, flags);
+		spin_lock_irqsave(host->host_lock, flags);
 		__starget_for_each_device(scsi_target(scmd->device), NULL,
 					  __scsi_report_device_reset);
-		spin_unlock_irqrestore(scmd->device->host->host_lock, flags);
+		spin_unlock_irqrestore(host->host_lock, flags);
 	}
 
 	return rtn;
@@ -605,27 +610,28 @@
 static int scsi_try_bus_device_reset(struct scsi_cmnd *scmd)
 {
 	int rtn;
+	struct scsi_host_template *hostt = scmd->device->host->hostt;
 
-	if (!scmd->device->host->hostt->eh_device_reset_handler)
+	if (!hostt->eh_device_reset_handler)
 		return FAILED;
 
-	rtn = scmd->device->host->hostt->eh_device_reset_handler(scmd);
+	rtn = hostt->eh_device_reset_handler(scmd);
 	if (rtn == SUCCESS)
 		__scsi_report_device_reset(scmd->device, NULL);
 	return rtn;
 }
 
-static int scsi_try_to_abort_cmd(struct scsi_cmnd *scmd)
+static int scsi_try_to_abort_cmd(struct scsi_host_template *hostt, struct scsi_cmnd *scmd)
 {
-	if (!scmd->device->host->hostt->eh_abort_handler)
+	if (!hostt->eh_abort_handler)
 		return FAILED;
 
-	return scmd->device->host->hostt->eh_abort_handler(scmd);
+	return hostt->eh_abort_handler(scmd);
 }
 
 static void scsi_abort_eh_cmnd(struct scsi_cmnd *scmd)
 {
-	if (scsi_try_to_abort_cmd(scmd) != SUCCESS)
+	if (scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd) != SUCCESS)
 		if (scsi_try_bus_device_reset(scmd) != SUCCESS)
 			if (scsi_try_target_reset(scmd) != SUCCESS)
 				if (scsi_try_bus_reset(scmd) != SUCCESS)
@@ -787,6 +793,7 @@
 		case SUCCESS:
 		case NEEDS_RETRY:
 		case FAILED:
+		case TARGET_ERROR:
 			break;
 		case ADD_TO_MLQUEUE:
 			rtn = NEEDS_RETRY;
@@ -845,7 +852,7 @@
  *
  * Description:
  *    See if we need to request sense information.  if so, then get it
- *    now, so we have a better idea of what to do.  
+ *    now, so we have a better idea of what to do.
  *
  * Notes:
  *    This has the unfortunate side effect that if a shost adapter does
@@ -957,7 +964,7 @@
 		SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting cmd:"
 						  "0x%p\n", current->comm,
 						  scmd));
-		rtn = scsi_try_to_abort_cmd(scmd);
+		rtn = scsi_try_to_abort_cmd(scmd->device->host->hostt, scmd);
 		if (rtn == SUCCESS || rtn == FAST_IO_FAIL) {
 			scmd->eh_eflags &= ~SCSI_EH_CANCEL_CMD;
 			if (!scsi_device_online(scmd->device) ||
@@ -965,7 +972,6 @@
 			    !scsi_eh_tur(scmd)) {
 				scsi_eh_finish_cmd(scmd, done_q);
 			}
-				
 		} else
 			SCSI_LOG_ERROR_RECOVERY(3, printk("%s: aborting"
 							  " cmd failed:"
@@ -1009,7 +1015,7 @@
  *
  * Notes:
  *    If commands are failing due to not ready, initializing command required,
- *	try revalidating the device, which will end up sending a start unit. 
+ *	try revalidating the device, which will end up sending a start unit.
  */
 static int scsi_eh_stu(struct Scsi_Host *shost,
 			      struct list_head *work_q,
@@ -1063,7 +1069,7 @@
  *    Try a bus device reset.  Still, look to see whether we have multiple
  *    devices that are jammed or not - if we have multiple devices, it
  *    makes no sense to try bus_device_reset - we really would need to try
- *    a bus_reset instead. 
+ *    a bus_reset instead.
  */
 static int scsi_eh_bus_device_reset(struct Scsi_Host *shost,
 				    struct list_head *work_q,
@@ -1163,7 +1169,7 @@
 }
 
 /**
- * scsi_eh_bus_reset - send a bus reset 
+ * scsi_eh_bus_reset - send a bus reset
  * @shost:	&scsi host being recovered.
  * @work_q:     &list_head for pending commands.
  * @done_q:	&list_head for processed commands.
@@ -1180,7 +1186,7 @@
 	 * we really want to loop over the various channels, and do this on
 	 * a channel by channel basis.  we should also check to see if any
 	 * of the failed commands are on soft_reset devices, and if so, skip
-	 * the reset.  
+	 * the reset.
 	 */
 
 	for (channel = 0; channel <= shost->max_channel; channel++) {
@@ -1222,7 +1228,7 @@
 }
 
 /**
- * scsi_eh_host_reset - send a host reset 
+ * scsi_eh_host_reset - send a host reset
  * @work_q:	list_head for processed commands.
  * @done_q:	list_head for processed commands.
  */
@@ -1375,7 +1381,7 @@
 		return SUCCESS;
 		/*
 		 * when the low level driver returns did_soft_error,
-		 * it is responsible for keeping an internal retry counter 
+		 * it is responsible for keeping an internal retry counter
 		 * in order to avoid endless loops (db)
 		 *
 		 * actually this is a bug in this function here.  we should
@@ -1413,7 +1419,6 @@
 			 */
 			break;
 		/* fallthrough */
-
 	case DID_BUS_BUSY:
 	case DID_PARITY:
 		goto maybe_retry;
@@ -1469,6 +1474,14 @@
 		rtn = scsi_check_sense(scmd);
 		if (rtn == NEEDS_RETRY)
 			goto maybe_retry;
+		else if (rtn == TARGET_ERROR) {
+			/*
+			 * Need to modify host byte to signal a
+			 * permanent target failure
+			 */
+			scmd->result |= (DID_TARGET_FAILURE << 16);
+			rtn = SUCCESS;
+		}
 		/* if rtn == FAILED, we have no sense information;
 		 * returning FAILED will wake the error handler thread
 		 * to collect the sense and redo the decide
@@ -1486,6 +1499,7 @@
 	case RESERVATION_CONFLICT:
 		sdev_printk(KERN_INFO, scmd->device,
 			    "reservation conflict\n");
+		scmd->result |= (DID_NEXUS_FAILURE << 16);
 		return SUCCESS; /* causes immediate i/o error */
 	default:
 		return FAILED;
@@ -1972,7 +1986,7 @@
 		if (sb_len > 7)
 			sshdr->additional_length = sense_buffer[7];
 	} else {
-		/* 
+		/*
 		 * fixed format
 		 */
 		if (sb_len > 2)
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_lib.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_lib.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -67,7 +67,12 @@
 
 struct kmem_cache *scsi_sdb_cache;
 
-static void scsi_run_queue(struct request_queue *q);
+/*
+ * When to reinvoke queueing after a resource shortage. It's 3 msecs to
+ * not change behaviour from the previous unplug mechanism, experimentation
+ * may prove this needs changing.
+ */
+#define SCSI_QUEUE_DELAY	3
 
 /*
  * Function:	scsi_unprep_request()
@@ -149,19 +154,12 @@
 	/*
 	 * Requeue this command.  It will go before all other commands
 	 * that are already in the queue.
-	 *
-	 * NOTE: there is magic here about the way the queue is plugged if
-	 * we have no outstanding commands.
-	 * 
-	 * Although we *don't* plug the queue, we call the request
-	 * function.  The SCSI request function detects the blocked condition
-	 * and plugs the queue appropriately.
-         */
+	 */
 	spin_lock_irqsave(q->queue_lock, flags);
 	blk_requeue_request(q, cmd->request);
 	spin_unlock_irqrestore(q->queue_lock, flags);
 
-	scsi_run_queue(q);
+	kblockd_schedule_work(q, &device->requeue_work);
 
 	return 0;
 }
@@ -400,10 +398,15 @@
 static void scsi_run_queue(struct request_queue *q)
 {
 	struct scsi_device *sdev = q->queuedata;
-	struct Scsi_Host *shost = sdev->host;
+	struct Scsi_Host *shost;
 	LIST_HEAD(starved_list);
 	unsigned long flags;
 
+	/* if the device is dead, sdev will be NULL, so no queue to run */
+	if (!sdev)
+		return;
+
+	shost = sdev->host;
 	if (scsi_target(sdev)->single_lun)
 		scsi_single_lun_run(sdev);
 
@@ -411,8 +414,6 @@
 	list_splice_init(&shost->starved_list, &starved_list);
 
 	while (!list_empty(&starved_list)) {
-		int flagset;
-
 		/*
 		 * As long as shost is accepting commands and we have
 		 * starved queues, call blk_run_queue. scsi_request_fn
@@ -436,18 +437,9 @@
 		}
 
 		spin_unlock(shost->host_lock);
-
 		spin_lock(sdev->request_queue->queue_lock);
-		flagset = test_bit(QUEUE_FLAG_REENTER, &q->queue_flags) &&
-				!test_bit(QUEUE_FLAG_REENTER,
-					&sdev->request_queue->queue_flags);
-		if (flagset)
-			queue_flag_set(QUEUE_FLAG_REENTER, sdev->request_queue);
-		__blk_run_queue(sdev->request_queue, false);
-		if (flagset)
-			queue_flag_clear(QUEUE_FLAG_REENTER, sdev->request_queue);
+		__blk_run_queue(sdev->request_queue);
 		spin_unlock(sdev->request_queue->queue_lock);
-
 		spin_lock(shost->host_lock);
 	}
 	/* put any unprocessed entries back */
@@ -457,6 +449,16 @@
 	blk_run_queue(q);
 }
 
+void scsi_requeue_run_queue(struct work_struct *work)
+{
+	struct scsi_device *sdev;
+	struct request_queue *q;
+
+	sdev = container_of(work, struct scsi_device, requeue_work);
+	q = sdev->request_queue;
+	scsi_run_queue(q);
+}
+
 /*
  * Function:	scsi_requeue_command()
  *
@@ -667,6 +669,30 @@
 }
 EXPORT_SYMBOL(scsi_release_buffers);
 
+static int __scsi_error_from_host_byte(struct scsi_cmnd *cmd, int result)
+{
+	int error = 0;
+
+	switch(host_byte(result)) {
+	case DID_TRANSPORT_FAILFAST:
+		error = -ENOLINK;
+		break;
+	case DID_TARGET_FAILURE:
+		cmd->result |= (DID_OK << 16);
+		error = -EREMOTEIO;
+		break;
+	case DID_NEXUS_FAILURE:
+		cmd->result |= (DID_OK << 16);
+		error = -EBADE;
+		break;
+	default:
+		error = -EIO;
+		break;
+	}
+
+	return error;
+}
+
 /*
  * Function:    scsi_io_completion()
  *
@@ -737,7 +763,7 @@
 				req->sense_len = len;
 			}
 			if (!sense_deferred)
-				error = -EIO;
+				error = __scsi_error_from_host_byte(cmd, result);
 		}
 
 		req->resid_len = scsi_get_resid(cmd);
@@ -796,7 +822,7 @@
 	if (scsi_end_request(cmd, error, good_bytes, result == 0) == NULL)
 		return;
 
-	error = -EIO;
+	error = __scsi_error_from_host_byte(cmd, result);
 
 	if (host_byte(result) == DID_RESET) {
 		/* Third party bus reset or reset for error recovery
@@ -843,6 +869,13 @@
 				description = "Host Data Integrity Failure";
 				action = ACTION_FAIL;
 				error = -EILSEQ;
+			/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
+			} else if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
+				   (cmd->cmnd[0] == UNMAP ||
+				    cmd->cmnd[0] == WRITE_SAME_16 ||
+				    cmd->cmnd[0] == WRITE_SAME)) {
+				description = "Discard failure";
+				action = ACTION_FAIL;
 			} else
 				action = ACTION_FAIL;
 			break;
@@ -1038,6 +1071,7 @@
 	cmd->request = req;
 
 	cmd->cmnd = req->cmd;
+	cmd->prot_op = SCSI_PROT_NORMAL;
 
 	return cmd;
 }
@@ -1194,11 +1228,11 @@
 	case BLKPREP_DEFER:
 		/*
 		 * If we defer, the blk_peek_request() returns NULL, but the
-		 * queue must be restarted, so we plug here if no returning
-		 * command will automatically do that.
+		 * queue must be restarted, so we schedule a callback to happen
+		 * shortly.
 		 */
 		if (sdev->device_busy == 0)
-			blk_plug_device(q);
+			blk_delay_queue(q, SCSI_QUEUE_DELAY);
 		break;
 	default:
 		req->cmd_flags |= REQ_DONTPREP;
@@ -1237,7 +1271,7 @@
 				   sdev_printk(KERN_INFO, sdev,
 				   "unblocking device at zero depth\n"));
 		} else {
-			blk_plug_device(q);
+			blk_delay_queue(q, SCSI_QUEUE_DELAY);
 			return 0;
 		}
 	}
@@ -1467,7 +1501,7 @@
 	 * the host is no longer able to accept any more requests.
 	 */
 	shost = sdev->host;
-	while (!blk_queue_plugged(q)) {
+	for (;;) {
 		int rtn;
 		/*
 		 * get next queueable request.  We do this early to make sure
@@ -1546,15 +1580,8 @@
 		 */
 		rtn = scsi_dispatch_cmd(cmd);
 		spin_lock_irq(q->queue_lock);
-		if(rtn) {
-			/* we're refusing the command; because of
-			 * the way locks get dropped, we need to 
-			 * check here if plugging is required */
-			if(sdev->device_busy == 0)
-				blk_plug_device(q);
-
-			break;
-		}
+		if (rtn)
+			goto out_delay;
 	}
 
 	goto out;
@@ -1573,9 +1600,10 @@
 	spin_lock_irq(q->queue_lock);
 	blk_requeue_request(q, req);
 	sdev->device_busy--;
-	if(sdev->device_busy == 0)
-		blk_plug_device(q);
- out:
+out_delay:
+	if (sdev->device_busy == 0)
+		blk_delay_queue(q, SCSI_QUEUE_DELAY);
+out:
 	/* must be careful here...if we trigger the ->remove() function
 	 * we cannot be holding the q lock */
 	spin_unlock_irq(q->queue_lock);
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_netlink.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_netlink.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_netlink.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_netlink.c	2011-05-19 00:06:34.000000000 -0400
@@ -499,7 +499,7 @@
 				SCSI_NL_GRP_CNT, scsi_nl_rcv_msg, NULL,
 				THIS_MODULE);
 	if (!scsi_nl_sock) {
-		printk(KERN_ERR "%s: register of recieve handler failed\n",
+		printk(KERN_ERR "%s: register of receive handler failed\n",
 				__func__);
 		netlink_unregister_notifier(&scsi_netlink_notifier);
 		return;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_priv.h linux-libre-2.6.39-gnu/drivers/scsi/scsi_priv.h
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_priv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_priv.h	2011-05-19 00:06:34.000000000 -0400
@@ -45,6 +45,7 @@
 enum {
 	SCSI_DEVINFO_GLOBAL = 0,
 	SCSI_DEVINFO_SPI,
+	SCSI_DEVINFO_DH,
 };
 
 extern int scsi_get_device_flags(struct scsi_device *sdev,
@@ -56,6 +57,7 @@
 extern int scsi_dev_info_list_add_keyed(int compatible, char *vendor,
 					char *model, char *strflags,
 					int flags, int key);
+extern int scsi_dev_info_list_del_keyed(char *vendor, char *model, int key);
 extern int scsi_dev_info_add_list(int key, const char *name);
 extern int scsi_dev_info_remove_list(int key);
 
@@ -146,7 +148,7 @@
 #endif
 
 /* scsi_pm.c */
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 extern const struct dev_pm_ops scsi_bus_pm_ops;
 #endif
 #ifdef CONFIG_PM_RUNTIME
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_scan.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_scan.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_scan.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_scan.c	2011-05-19 00:06:34.000000000 -0400
@@ -242,6 +242,7 @@
 	int display_failure_msg = 1, ret;
 	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
 	extern void scsi_evt_thread(struct work_struct *work);
+	extern void scsi_requeue_run_queue(struct work_struct *work);
 
 	sdev = kzalloc(sizeof(*sdev) + shost->transportt->device_size,
 		       GFP_ATOMIC);
@@ -264,6 +265,7 @@
 	INIT_LIST_HEAD(&sdev->event_list);
 	spin_lock_init(&sdev->list_lock);
 	INIT_WORK(&sdev->event_work, scsi_evt_thread);
+	INIT_WORK(&sdev->requeue_work, scsi_requeue_run_queue);
 
 	sdev->sdev_gendev.parent = get_device(&starget->dev);
 	sdev->sdev_target = starget;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_sysfs.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_sysfs.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_sysfs.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_sysfs.c	2011-05-19 00:06:34.000000000 -0400
@@ -322,14 +322,8 @@
 		kfree(evt);
 	}
 
-	if (sdev->request_queue) {
-		sdev->request_queue->queuedata = NULL;
-		/* user context needed to free queue */
-		scsi_free_queue(sdev->request_queue);
-		/* temporary expedient, try to catch use of queue lock
-		 * after free of sdev */
-		sdev->request_queue = NULL;
-	}
+	/* NULL queue means the device can't be used */
+	sdev->request_queue = NULL;
 
 	scsi_target_reap(scsi_target(sdev));
 
@@ -383,7 +377,7 @@
         .name		= "scsi",
         .match		= scsi_bus_match,
 	.uevent		= scsi_bus_uevent,
-#ifdef CONFIG_PM_OPS
+#ifdef CONFIG_PM
 	.pm		= &scsi_bus_pm_ops,
 #endif
 };
@@ -937,6 +931,12 @@
 	if (sdev->host->hostt->slave_destroy)
 		sdev->host->hostt->slave_destroy(sdev);
 	transport_destroy_device(dev);
+
+	/* cause the request function to reject all I/O requests */
+	sdev->request_queue->queuedata = NULL;
+
+	/* Freeing the queue signals to block that we're done */
+	scsi_free_queue(sdev->request_queue);
 	put_device(dev);
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_tgt_lib.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_tgt_lib.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_tgt_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_tgt_lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -93,7 +93,7 @@
 
 	/*
 	 * The blk helpers are used to the READ/WRITE requests
-	 * transfering data from a initiator point of view. Since
+	 * transferring data from a initiator point of view. Since
 	 * we are in target mode we want the opposite.
 	 */
 	rq = blk_get_request(shost->uspace_req_q, !write, gfp_mask);
@@ -629,7 +629,7 @@
 	if (!scsi_tgt_cmd_cache)
 		return -ENOMEM;
 
-	scsi_tgtd = create_workqueue("scsi_tgtd");
+	scsi_tgtd = alloc_workqueue("scsi_tgtd", 0, 1);
 	if (!scsi_tgtd) {
 		err = -ENOMEM;
 		goto free_kmemcache;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_fc.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_transport_fc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_fc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_transport_fc.c	2011-05-19 00:06:34.000000000 -0400
@@ -2378,7 +2378,7 @@
  * fc_remove_host - called to terminate any fc_transport-related elements for a scsi host.
  * @shost:	Which &Scsi_Host
  *
- * This routine is expected to be called immediately preceeding the
+ * This routine is expected to be called immediately preceding the
  * a driver's call to scsi_remove_host().
  *
  * WARNING: A driver utilizing the fc_transport, which fails to call
@@ -2458,7 +2458,7 @@
 }
 
 /**
- * fc_starget_delete - called to delete the scsi decendents of an rport
+ * fc_starget_delete - called to delete the scsi descendants of an rport
  * @work:	remote port to be operated on.
  *
  * Deletes target and all sdevs.
@@ -3816,28 +3816,17 @@
 static void
 fc_bsg_goose_queue(struct fc_rport *rport)
 {
-	int flagset;
-	unsigned long flags;
-
 	if (!rport->rqst_q)
 		return;
 
+	/*
+	 * This get/put dance makes no sense
+	 */
 	get_device(&rport->dev);
-
-	spin_lock_irqsave(rport->rqst_q->queue_lock, flags);
-	flagset = test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags) &&
-		  !test_bit(QUEUE_FLAG_REENTER, &rport->rqst_q->queue_flags);
-	if (flagset)
-		queue_flag_set(QUEUE_FLAG_REENTER, rport->rqst_q);
-	__blk_run_queue(rport->rqst_q, false);
-	if (flagset)
-		queue_flag_clear(QUEUE_FLAG_REENTER, rport->rqst_q);
-	spin_unlock_irqrestore(rport->rqst_q->queue_lock, flags);
-
+	blk_run_queue_async(rport->rqst_q);
 	put_device(&rport->dev);
 }
 
-
 /**
  * fc_bsg_rport_dispatch - process rport bsg requests and dispatch to LLDD
  * @q:		rport request queue
@@ -3913,7 +3902,7 @@
 	if (!get_device(dev))
 		return;
 
-	while (!blk_queue_plugged(q)) {
+	while (1) {
 		if (rport && (rport->port_state == FC_PORTSTATE_BLOCKED) &&
 		    !(rport->flags & FC_RPORT_FAST_FAIL_TIMEDOUT))
 			break;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_iscsi.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_transport_iscsi.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_iscsi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_transport_iscsi.c	2011-05-19 00:06:34.000000000 -0400
@@ -954,6 +954,7 @@
 	if (dd_size)
 		conn->dd_data = &conn[1];
 
+	mutex_init(&conn->ep_mutex);
 	INIT_LIST_HEAD(&conn->conn_list);
 	conn->transport = transport;
 	conn->cid = cid;
@@ -975,7 +976,6 @@
 
 	spin_lock_irqsave(&connlock, flags);
 	list_add(&conn->conn_list, &connlist);
-	conn->active = 1;
 	spin_unlock_irqrestore(&connlock, flags);
 
 	ISCSI_DBG_TRANS_CONN(conn, "Completed conn creation\n");
@@ -1001,7 +1001,6 @@
 	unsigned long flags;
 
 	spin_lock_irqsave(&connlock, flags);
-	conn->active = 0;
 	list_del(&conn->conn_list);
 	spin_unlock_irqrestore(&connlock, flags);
 
@@ -1430,6 +1429,29 @@
 	return err;
 }
 
+static int iscsi_if_ep_disconnect(struct iscsi_transport *transport,
+				  u64 ep_handle)
+{
+	struct iscsi_cls_conn *conn;
+	struct iscsi_endpoint *ep;
+
+	if (!transport->ep_disconnect)
+		return -EINVAL;
+
+	ep = iscsi_lookup_endpoint(ep_handle);
+	if (!ep)
+		return -EINVAL;
+	conn = ep->conn;
+	if (conn) {
+		mutex_lock(&conn->ep_mutex);
+		conn->ep = NULL;
+		mutex_unlock(&conn->ep_mutex);
+	}
+
+	transport->ep_disconnect(ep);
+	return 0;
+}
+
 static int
 iscsi_if_transport_ep(struct iscsi_transport *transport,
 		      struct iscsi_uevent *ev, int msg_type)
@@ -1454,14 +1476,8 @@
 						   ev->u.ep_poll.timeout_ms);
 		break;
 	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:
-		if (!transport->ep_disconnect)
-			return -EINVAL;
-
-		ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle);
-		if (!ep)
-			return -EINVAL;
-
-		transport->ep_disconnect(ep);
+		rc = iscsi_if_ep_disconnect(transport,
+					    ev->u.ep_disconnect.ep_handle);
 		break;
 	}
 	return rc;
@@ -1609,12 +1625,31 @@
 		session = iscsi_session_lookup(ev->u.b_conn.sid);
 		conn = iscsi_conn_lookup(ev->u.b_conn.sid, ev->u.b_conn.cid);
 
-		if (session && conn)
-			ev->r.retcode =	transport->bind_conn(session, conn,
-					ev->u.b_conn.transport_eph,
-					ev->u.b_conn.is_leading);
-		else
+		if (conn && conn->ep)
+			iscsi_if_ep_disconnect(transport, conn->ep->id);
+
+		if (!session || !conn) {
 			err = -EINVAL;
+			break;
+		}
+
+		ev->r.retcode =	transport->bind_conn(session, conn,
+						ev->u.b_conn.transport_eph,
+						ev->u.b_conn.is_leading);
+		if (ev->r.retcode || !transport->ep_connect)
+			break;
+
+		ep = iscsi_lookup_endpoint(ev->u.b_conn.transport_eph);
+		if (ep) {
+			ep->conn = conn;
+
+			mutex_lock(&conn->ep_mutex);
+			conn->ep = ep;
+			mutex_unlock(&conn->ep_mutex);
+		} else
+			iscsi_cls_conn_printk(KERN_ERR, conn,
+					      "Could not set ep conn "
+					      "binding\n");
 		break;
 	case ISCSI_UEVENT_SET_PARAM:
 		err = iscsi_set_param(transport, ev);
@@ -1747,13 +1782,48 @@
 iscsi_conn_attr(ifmarker, ISCSI_PARAM_IFMARKER_EN);
 iscsi_conn_attr(ofmarker, ISCSI_PARAM_OFMARKER_EN);
 iscsi_conn_attr(persistent_port, ISCSI_PARAM_PERSISTENT_PORT);
-iscsi_conn_attr(port, ISCSI_PARAM_CONN_PORT);
 iscsi_conn_attr(exp_statsn, ISCSI_PARAM_EXP_STATSN);
 iscsi_conn_attr(persistent_address, ISCSI_PARAM_PERSISTENT_ADDRESS);
-iscsi_conn_attr(address, ISCSI_PARAM_CONN_ADDRESS);
 iscsi_conn_attr(ping_tmo, ISCSI_PARAM_PING_TMO);
 iscsi_conn_attr(recv_tmo, ISCSI_PARAM_RECV_TMO);
 
+#define iscsi_conn_ep_attr_show(param)					\
+static ssize_t show_conn_ep_param_##param(struct device *dev,		\
+					  struct device_attribute *attr,\
+					  char *buf)			\
+{									\
+	struct iscsi_cls_conn *conn = iscsi_dev_to_conn(dev->parent);	\
+	struct iscsi_transport *t = conn->transport;			\
+	struct iscsi_endpoint *ep;					\
+	ssize_t rc;							\
+									\
+	/*								\
+	 * Need to make sure ep_disconnect does not free the LLD's	\
+	 * interconnect resources while we are trying to read them.	\
+	 */								\
+	mutex_lock(&conn->ep_mutex);					\
+	ep = conn->ep;							\
+	if (!ep && t->ep_connect) {					\
+		mutex_unlock(&conn->ep_mutex);				\
+		return -ENOTCONN;					\
+	}								\
+									\
+	if (ep)								\
+		rc = t->get_ep_param(ep, param, buf);			\
+	else								\
+		rc = t->get_conn_param(conn, param, buf);		\
+	mutex_unlock(&conn->ep_mutex);					\
+	return rc;							\
+}
+
+#define iscsi_conn_ep_attr(field, param)				\
+	iscsi_conn_ep_attr_show(param)					\
+static ISCSI_CLASS_ATTR(conn, field, S_IRUGO,				\
+			show_conn_ep_param_##param, NULL);
+
+iscsi_conn_ep_attr(address, ISCSI_PARAM_CONN_ADDRESS);
+iscsi_conn_ep_attr(port, ISCSI_PARAM_CONN_PORT);
+
 /*
  * iSCSI session attrs
  */
@@ -1847,7 +1917,7 @@
 #define iscsi_priv_session_rw_attr(field, format)			\
 	iscsi_priv_session_attr_show(field, format)			\
 	iscsi_priv_session_attr_store(field)				\
-static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUGO,		\
+static ISCSI_CLASS_ATTR(priv_sess, field, S_IRUGO | S_IWUSR,		\
 			show_priv_session_##field,			\
 			store_priv_session_##field)
 iscsi_priv_session_rw_attr(recovery_tmo, "%d");
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_sas.c linux-libre-2.6.39-gnu/drivers/scsi/scsi_transport_sas.c
--- linux-libre-2.6.38-gnu/drivers/scsi/scsi_transport_sas.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/scsi_transport_sas.c	2011-05-19 00:06:34.000000000 -0400
@@ -173,11 +173,7 @@
 	int ret;
 	int (*handler)(struct Scsi_Host *, struct sas_rphy *, struct request *);
 
-	while (!blk_queue_plugged(q)) {
-		req = blk_fetch_request(q);
-		if (!req)
-			break;
-
+	while ((req = blk_fetch_request(q)) != NULL) {
 		spin_unlock_irq(q->queue_lock);
 
 		handler = to_sas_internal(shost->transportt)->f->smp_handler;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sd.c linux-libre-2.6.39-gnu/drivers/scsi/sd.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sd.c	2011-05-19 00:06:34.000000000 -0400
@@ -96,6 +96,7 @@
 #define SD_MINORS	0
 #endif
 
+static void sd_config_discard(struct scsi_disk *, unsigned int);
 static int  sd_revalidate_disk(struct gendisk *);
 static void sd_unlock_native_capacity(struct gendisk *disk);
 static int  sd_probe(struct device *);
@@ -294,7 +295,54 @@
 {
 	struct scsi_disk *sdkp = to_scsi_disk(dev);
 
-	return snprintf(buf, 20, "%u\n", sdkp->thin_provisioning);
+	return snprintf(buf, 20, "%u\n", sdkp->lbpme);
+}
+
+static const char *lbp_mode[] = {
+	[SD_LBP_FULL]		= "full",
+	[SD_LBP_UNMAP]		= "unmap",
+	[SD_LBP_WS16]		= "writesame_16",
+	[SD_LBP_WS10]		= "writesame_10",
+	[SD_LBP_ZERO]		= "writesame_zero",
+	[SD_LBP_DISABLE]	= "disabled",
+};
+
+static ssize_t
+sd_show_provisioning_mode(struct device *dev, struct device_attribute *attr,
+			  char *buf)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+
+	return snprintf(buf, 20, "%s\n", lbp_mode[sdkp->provisioning_mode]);
+}
+
+static ssize_t
+sd_store_provisioning_mode(struct device *dev, struct device_attribute *attr,
+			   const char *buf, size_t count)
+{
+	struct scsi_disk *sdkp = to_scsi_disk(dev);
+	struct scsi_device *sdp = sdkp->device;
+
+	if (!capable(CAP_SYS_ADMIN))
+		return -EACCES;
+
+	if (sdp->type != TYPE_DISK)
+		return -EINVAL;
+
+	if (!strncmp(buf, lbp_mode[SD_LBP_UNMAP], 20))
+		sd_config_discard(sdkp, SD_LBP_UNMAP);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_WS16], 20))
+		sd_config_discard(sdkp, SD_LBP_WS16);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_WS10], 20))
+		sd_config_discard(sdkp, SD_LBP_WS10);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_ZERO], 20))
+		sd_config_discard(sdkp, SD_LBP_ZERO);
+	else if (!strncmp(buf, lbp_mode[SD_LBP_DISABLE], 20))
+		sd_config_discard(sdkp, SD_LBP_DISABLE);
+	else
+		return -EINVAL;
+
+	return count;
 }
 
 static struct device_attribute sd_disk_attrs[] = {
@@ -309,6 +357,8 @@
 	__ATTR(protection_mode, S_IRUGO, sd_show_protection_mode, NULL),
 	__ATTR(app_tag_own, S_IRUGO, sd_show_app_tag_own, NULL),
 	__ATTR(thin_provisioning, S_IRUGO, sd_show_thin_provisioning, NULL),
+	__ATTR(provisioning_mode, S_IRUGO|S_IWUSR, sd_show_provisioning_mode,
+	       sd_store_provisioning_mode),
 	__ATTR_NULL,
 };
 
@@ -433,6 +483,49 @@
 	scsi_set_prot_type(scmd, dif);
 }
 
+static void sd_config_discard(struct scsi_disk *sdkp, unsigned int mode)
+{
+	struct request_queue *q = sdkp->disk->queue;
+	unsigned int logical_block_size = sdkp->device->sector_size;
+	unsigned int max_blocks = 0;
+
+	q->limits.discard_zeroes_data = sdkp->lbprz;
+	q->limits.discard_alignment = sdkp->unmap_alignment;
+	q->limits.discard_granularity =
+		max(sdkp->physical_block_size,
+		    sdkp->unmap_granularity * logical_block_size);
+
+	switch (mode) {
+
+	case SD_LBP_DISABLE:
+		q->limits.max_discard_sectors = 0;
+		queue_flag_clear_unlocked(QUEUE_FLAG_DISCARD, q);
+		return;
+
+	case SD_LBP_UNMAP:
+		max_blocks = min_not_zero(sdkp->max_unmap_blocks, 0xffffffff);
+		break;
+
+	case SD_LBP_WS16:
+		max_blocks = min_not_zero(sdkp->max_ws_blocks, 0xffffffff);
+		break;
+
+	case SD_LBP_WS10:
+		max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+		break;
+
+	case SD_LBP_ZERO:
+		max_blocks = min_not_zero(sdkp->max_ws_blocks, (u32)0xffff);
+		q->limits.discard_zeroes_data = 1;
+		break;
+	}
+
+	q->limits.max_discard_sectors = max_blocks * (logical_block_size >> 9);
+	queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+
+	sdkp->provisioning_mode = mode;
+}
+
 /**
  * scsi_setup_discard_cmnd - unmap blocks on thinly provisioned device
  * @sdp: scsi device to operate one
@@ -449,6 +542,7 @@
 	unsigned int nr_sectors = bio_sectors(bio);
 	unsigned int len;
 	int ret;
+	char *buf;
 	struct page *page;
 
 	if (sdkp->device->sector_size == 4096) {
@@ -464,8 +558,9 @@
 	if (!page)
 		return BLKPREP_DEFER;
 
-	if (sdkp->unmap) {
-		char *buf = page_address(page);
+	switch (sdkp->provisioning_mode) {
+	case SD_LBP_UNMAP:
+		buf = page_address(page);
 
 		rq->cmd_len = 10;
 		rq->cmd[0] = UNMAP;
@@ -477,7 +572,9 @@
 		put_unaligned_be32(nr_sectors, &buf[16]);
 
 		len = 24;
-	} else {
+		break;
+
+	case SD_LBP_WS16:
 		rq->cmd_len = 16;
 		rq->cmd[0] = WRITE_SAME_16;
 		rq->cmd[1] = 0x8; /* UNMAP */
@@ -485,11 +582,30 @@
 		put_unaligned_be32(nr_sectors, &rq->cmd[10]);
 
 		len = sdkp->device->sector_size;
+		break;
+
+	case SD_LBP_WS10:
+	case SD_LBP_ZERO:
+		rq->cmd_len = 10;
+		rq->cmd[0] = WRITE_SAME;
+		if (sdkp->provisioning_mode == SD_LBP_WS10)
+			rq->cmd[1] = 0x8; /* UNMAP */
+		put_unaligned_be32(sector, &rq->cmd[2]);
+		put_unaligned_be16(nr_sectors, &rq->cmd[7]);
+
+		len = sdkp->device->sector_size;
+		break;
+
+	default:
+		ret = BLKPREP_KILL;
+		goto out;
 	}
 
 	blk_add_request_payload(rq, page, len);
 	ret = scsi_setup_blk_pc_cmnd(sdp, rq);
 	rq->buffer = page_address(page);
+
+out:
 	if (ret != BLKPREP_OK) {
 		__free_page(page);
 		rq->buffer = NULL;
@@ -939,7 +1055,7 @@
  *	@arg: this is third argument given to ioctl(2) system call.
  *	Often contains a pointer.
  *
- *	Returns 0 if successful (some ioctls return postive numbers on
+ *	Returns 0 if successful (some ioctls return positive numbers on
  *	success as well). Returns a negated errno value in case of error.
  *
  *	Note: most ioctls are forward onto the block subsystem or further
@@ -1251,12 +1367,10 @@
 	struct scsi_disk *sdkp = scsi_disk(SCpnt->request->rq_disk);
 	int sense_valid = 0;
 	int sense_deferred = 0;
+	unsigned char op = SCpnt->cmnd[0];
 
-	if (SCpnt->request->cmd_flags & REQ_DISCARD) {
-		if (!result)
-			scsi_set_resid(SCpnt, 0);
-		return good_bytes;
-	}
+	if ((SCpnt->request->cmd_flags & REQ_DISCARD) && !result)
+		scsi_set_resid(SCpnt, 0);
 
 	if (result) {
 		sense_valid = scsi_command_normalize_sense(SCpnt, &sshdr);
@@ -1295,11 +1409,18 @@
 		SCpnt->result = 0;
 		memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
 		break;
-	case ABORTED_COMMAND: /* DIF: Target detected corruption */
-	case ILLEGAL_REQUEST: /* DIX: Host detected corruption */
-		if (sshdr.asc == 0x10)
+	case ABORTED_COMMAND:
+		if (sshdr.asc == 0x10)  /* DIF: Target detected corruption */
 			good_bytes = sd_completed_bytes(SCpnt);
 		break;
+	case ILLEGAL_REQUEST:
+		if (sshdr.asc == 0x10)  /* DIX: Host detected corruption */
+			good_bytes = sd_completed_bytes(SCpnt);
+		/* INVALID COMMAND OPCODE or INVALID FIELD IN CDB */
+		if ((sshdr.asc == 0x20 || sshdr.asc == 0x24) &&
+		    (op == UNMAP || op == WRITE_SAME_16 || op == WRITE_SAME))
+			sd_config_discard(sdkp, SD_LBP_DISABLE);
+		break;
 	default:
 		break;
 	}
@@ -1596,17 +1717,13 @@
 		sd_printk(KERN_NOTICE, sdkp,
 			  "physical block alignment offset: %u\n", alignment);
 
-	if (buffer[14] & 0x80) { /* TPE */
-		struct request_queue *q = sdp->request_queue;
-
-		sdkp->thin_provisioning = 1;
-		q->limits.discard_granularity = sdkp->physical_block_size;
-		q->limits.max_discard_sectors = 0xffffffff;
+	if (buffer[14] & 0x80) { /* LBPME */
+		sdkp->lbpme = 1;
 
-		if (buffer[14] & 0x40) /* TPRZ */
-			q->limits.discard_zeroes_data = 1;
+		if (buffer[14] & 0x40) /* LBPRZ */
+			sdkp->lbprz = 1;
 
-		queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, q);
+		sd_config_discard(sdkp, SD_LBP_WS16);
 	}
 
 	sdkp->capacity = lba + 1;
@@ -1910,14 +2027,10 @@
 	int old_rcd = sdkp->RCD;
 	int old_dpofua = sdkp->DPOFUA;
 
-	if (sdp->skip_ms_page_8) {
-		if (sdp->type == TYPE_RBC)
-			goto defaults;
-		else {
-			modepage = 0x3F;
-			dbd = 0;
-		}
-	} else if (sdp->type == TYPE_RBC) {
+	if (sdp->skip_ms_page_8)
+		goto defaults;
+
+	if (sdp->type == TYPE_RBC) {
 		modepage = 6;
 		dbd = 8;
 	} else {
@@ -1945,11 +2058,13 @@
 	 */
 	if (len < 3)
 		goto bad_sense;
-	else if (len > SD_BUF_SIZE) {
-		sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter "
-			  "data from %d to %d bytes\n", len, SD_BUF_SIZE);
-		len = SD_BUF_SIZE;
-	}
+	if (len > 20)
+		len = 20;
+
+	/* Take headers and block descriptors into account */
+	len += data.header_length + data.block_descriptor_length;
+	if (len > SD_BUF_SIZE)
+		goto bad_sense;
 
 	/* Get the data */
 	res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr);
@@ -1957,45 +2072,16 @@
 	if (scsi_status_is_good(res)) {
 		int offset = data.header_length + data.block_descriptor_length;
 
-		while (offset < len) {
-			u8 page_code = buffer[offset] & 0x3F;
-			u8 spf       = buffer[offset] & 0x40;
-
-			if (page_code == 8 || page_code == 6) {
-				/* We're interested only in the first 3 bytes.
-				 */
-				if (len - offset <= 2) {
-					sd_printk(KERN_ERR, sdkp, "Incomplete "
-						  "mode parameter data\n");
-					goto defaults;
-				} else {
-					modepage = page_code;
-					goto Page_found;
-				}
-			} else {
-				/* Go to the next page */
-				if (spf && len - offset > 3)
-					offset += 4 + (buffer[offset+2] << 8) +
-						buffer[offset+3];
-				else if (!spf && len - offset > 1)
-					offset += 2 + buffer[offset+1];
-				else {
-					sd_printk(KERN_ERR, sdkp, "Incomplete "
-						  "mode parameter data\n");
-					goto defaults;
-				}
-			}
+		if (offset >= SD_BUF_SIZE - 2) {
+			sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n");
+			goto defaults;
 		}
 
-		if (modepage == 0x3F) {
-			sd_printk(KERN_ERR, sdkp, "No Caching mode page "
-				  "present\n");
-			goto defaults;
-		} else if ((buffer[offset] & 0x3f) != modepage) {
+		if ((buffer[offset] & 0x3f) != modepage) {
 			sd_printk(KERN_ERR, sdkp, "Got wrong page\n");
 			goto defaults;
 		}
-	Page_found:
+
 		if (modepage == 8) {
 			sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0);
 			sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0);
@@ -2091,7 +2177,6 @@
  */
 static void sd_read_block_limits(struct scsi_disk *sdkp)
 {
-	struct request_queue *q = sdkp->disk->queue;
 	unsigned int sector_sz = sdkp->device->sector_size;
 	const int vpd_len = 64;
 	unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL);
@@ -2106,39 +2191,46 @@
 	blk_queue_io_opt(sdkp->disk->queue,
 			 get_unaligned_be32(&buffer[12]) * sector_sz);
 
-	/* Thin provisioning enabled and page length indicates TP support */
-	if (sdkp->thin_provisioning && buffer[3] == 0x3c) {
-		unsigned int lba_count, desc_count, granularity;
-
-		lba_count = get_unaligned_be32(&buffer[20]);
-		desc_count = get_unaligned_be32(&buffer[24]);
+	if (buffer[3] == 0x3c) {
+		unsigned int lba_count, desc_count;
 
-		if (lba_count && desc_count) {
-			if (sdkp->tpvpd && !sdkp->tpu)
-				sdkp->unmap = 0;
-			else
-				sdkp->unmap = 1;
-		}
+		sdkp->max_ws_blocks =
+			(u32) min_not_zero(get_unaligned_be64(&buffer[36]),
+					   (u64)0xffffffff);
 
-		if (sdkp->tpvpd && !sdkp->tpu && !sdkp->tpws) {
-			sd_printk(KERN_ERR, sdkp, "Thin provisioning is " \
-				  "enabled but neither TPU, nor TPWS are " \
-				  "set. Disabling discard!\n");
+		if (!sdkp->lbpme)
 			goto out;
-		}
 
-		if (lba_count)
-			q->limits.max_discard_sectors =
-				lba_count * sector_sz >> 9;
+		lba_count = get_unaligned_be32(&buffer[20]);
+		desc_count = get_unaligned_be32(&buffer[24]);
 
-		granularity = get_unaligned_be32(&buffer[28]);
+		if (lba_count && desc_count)
+			sdkp->max_unmap_blocks = lba_count;
 
-		if (granularity)
-			q->limits.discard_granularity = granularity * sector_sz;
+		sdkp->unmap_granularity = get_unaligned_be32(&buffer[28]);
 
 		if (buffer[32] & 0x80)
-			q->limits.discard_alignment =
+			sdkp->unmap_alignment =
 				get_unaligned_be32(&buffer[32]) & ~(1 << 31);
+
+		if (!sdkp->lbpvpd) { /* LBP VPD page not provided */
+
+			if (sdkp->max_unmap_blocks)
+				sd_config_discard(sdkp, SD_LBP_UNMAP);
+			else
+				sd_config_discard(sdkp, SD_LBP_WS16);
+
+		} else {	/* LBP VPD page tells us what to use */
+
+			if (sdkp->lbpu && sdkp->max_unmap_blocks)
+				sd_config_discard(sdkp, SD_LBP_UNMAP);
+			else if (sdkp->lbpws)
+				sd_config_discard(sdkp, SD_LBP_WS16);
+			else if (sdkp->lbpws10)
+				sd_config_discard(sdkp, SD_LBP_WS10);
+			else
+				sd_config_discard(sdkp, SD_LBP_DISABLE);
+		}
 	}
 
  out:
@@ -2172,15 +2264,15 @@
 }
 
 /**
- * sd_read_thin_provisioning - Query thin provisioning VPD page
+ * sd_read_block_provisioning - Query provisioning VPD page
  * @disk: disk to query
  */
-static void sd_read_thin_provisioning(struct scsi_disk *sdkp)
+static void sd_read_block_provisioning(struct scsi_disk *sdkp)
 {
 	unsigned char *buffer;
 	const int vpd_len = 8;
 
-	if (sdkp->thin_provisioning == 0)
+	if (sdkp->lbpme == 0)
 		return;
 
 	buffer = kmalloc(vpd_len, GFP_KERNEL);
@@ -2188,9 +2280,10 @@
 	if (!buffer || scsi_get_vpd_page(sdkp->device, 0xb2, buffer, vpd_len))
 		goto out;
 
-	sdkp->tpvpd = 1;
-	sdkp->tpu   = (buffer[5] >> 7) & 1;	/* UNMAP */
-	sdkp->tpws  = (buffer[5] >> 6) & 1;	/* WRITE SAME(16) with UNMAP */
+	sdkp->lbpvpd	= 1;
+	sdkp->lbpu	= (buffer[5] >> 7) & 1;	/* UNMAP */
+	sdkp->lbpws	= (buffer[5] >> 6) & 1;	/* WRITE SAME(16) with UNMAP */
+	sdkp->lbpws10	= (buffer[5] >> 5) & 1;	/* WRITE SAME(10) with UNMAP */
 
  out:
 	kfree(buffer);
@@ -2247,7 +2340,7 @@
 		sd_read_capacity(sdkp, buffer);
 
 		if (sd_try_extended_inquiry(sdp)) {
-			sd_read_thin_provisioning(sdkp);
+			sd_read_block_provisioning(sdkp);
 			sd_read_block_limits(sdkp);
 			sd_read_block_characteristics(sdkp);
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sd.h linux-libre-2.6.39-gnu/drivers/scsi/sd.h
--- linux-libre-2.6.38-gnu/drivers/scsi/sd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sd.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,6 +43,15 @@
 	SD_MEMPOOL_SIZE = 2,	/* CDB pool size */
 };
 
+enum {
+	SD_LBP_FULL = 0,	/* Full logical block provisioning */
+	SD_LBP_UNMAP,		/* Use UNMAP command */
+	SD_LBP_WS16,		/* Use WRITE SAME(16) with UNMAP bit */
+	SD_LBP_WS10,		/* Use WRITE SAME(10) with UNMAP bit */
+	SD_LBP_ZERO,		/* Use WRITE SAME(10) with zero payload */
+	SD_LBP_DISABLE,		/* Discard disabled due to failed cmd */
+};
+
 struct scsi_disk {
 	struct scsi_driver *driver;	/* always &sd_template */
 	struct scsi_device *device;
@@ -50,21 +59,27 @@
 	struct gendisk	*disk;
 	atomic_t	openers;
 	sector_t	capacity;	/* size in 512-byte sectors */
+	u32		max_ws_blocks;
+	u32		max_unmap_blocks;
+	u32		unmap_granularity;
+	u32		unmap_alignment;
 	u32		index;
 	unsigned int	physical_block_size;
 	u8		media_present;
 	u8		write_prot;
 	u8		protection_type;/* Data Integrity Field */
+	u8		provisioning_mode;
 	unsigned	ATO : 1;	/* state of disk ATO bit */
 	unsigned	WCE : 1;	/* state of disk WCE bit */
 	unsigned	RCD : 1;	/* state of disk RCD bit, unused */
 	unsigned	DPOFUA : 1;	/* state of disk DPOFUA bit */
 	unsigned	first_scan : 1;
-	unsigned	thin_provisioning : 1;
-	unsigned	unmap : 1;
-	unsigned	tpws : 1;
-	unsigned	tpu : 1;
-	unsigned	tpvpd : 1;
+	unsigned	lbpme : 1;
+	unsigned	lbprz : 1;
+	unsigned	lbpu : 1;
+	unsigned	lbpws : 1;
+	unsigned	lbpws10 : 1;
+	unsigned	lbpvpd : 1;
 };
 #define to_scsi_disk(obj) container_of(obj,struct scsi_disk,dev)
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ses.c linux-libre-2.6.39-gnu/drivers/scsi/ses.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ses.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/ses.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,9 +35,11 @@
 
 struct ses_device {
 	unsigned char *page1;
+	unsigned char *page1_types;
 	unsigned char *page2;
 	unsigned char *page10;
 	short page1_len;
+	short page1_num_types;
 	short page2_len;
 	short page10_len;
 };
@@ -110,12 +112,12 @@
 	int i, j, count = 0, descriptor = ecomp->number;
 	struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
 	struct ses_device *ses_dev = edev->scratch;
-	unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+	unsigned char *type_ptr = ses_dev->page1_types;
 	unsigned char *desc_ptr = ses_dev->page2 + 8;
 
 	/* Clear everything */
 	memset(desc_ptr, 0, ses_dev->page2_len - 8);
-	for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) {
+	for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
 		for (j = 0; j < type_ptr[1]; j++) {
 			desc_ptr += 4;
 			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
@@ -140,12 +142,12 @@
 	int i, j, count = 0, descriptor = ecomp->number;
 	struct scsi_device *sdev = to_scsi_device(edev->edev.parent);
 	struct ses_device *ses_dev = edev->scratch;
-	unsigned char *type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+	unsigned char *type_ptr = ses_dev->page1_types;
 	unsigned char *desc_ptr = ses_dev->page2 + 8;
 
 	ses_recv_diag(sdev, 2, ses_dev->page2, ses_dev->page2_len);
 
-	for (i = 0; i < ses_dev->page1[10]; i++, type_ptr += 4) {
+	for (i = 0; i < ses_dev->page1_num_types; i++, type_ptr += 4) {
 		for (j = 0; j < type_ptr[1]; j++) {
 			desc_ptr += 4;
 			if (type_ptr[0] != ENCLOSURE_COMPONENT_DEVICE &&
@@ -358,7 +360,7 @@
 	unsigned char *buf = NULL, *type_ptr, *desc_ptr, *addl_desc_ptr = NULL;
 	int i, j, page7_len, len, components;
 	struct ses_device *ses_dev = edev->scratch;
-	int types = ses_dev->page1[10];
+	int types = ses_dev->page1_num_types;
 	unsigned char *hdr_buf = kzalloc(INIT_ALLOC_SIZE, GFP_KERNEL);
 
 	if (!hdr_buf)
@@ -390,10 +392,10 @@
 		len = (desc_ptr[2] << 8) + desc_ptr[3];
 		/* skip past overall descriptor */
 		desc_ptr += len + 4;
-		if (ses_dev->page10)
-			addl_desc_ptr = ses_dev->page10 + 8;
 	}
-	type_ptr = ses_dev->page1 + 12 + ses_dev->page1[11];
+	if (ses_dev->page10)
+		addl_desc_ptr = ses_dev->page10 + 8;
+	type_ptr = ses_dev->page1_types;
 	components = 0;
 	for (i = 0; i < types; i++, type_ptr += 4) {
 		for (j = 0; j < type_ptr[1]; j++) {
@@ -503,6 +505,7 @@
 	u32 result;
 	int i, types, len, components = 0;
 	int err = -ENOMEM;
+	int num_enclosures;
 	struct enclosure_device *edev;
 	struct ses_component *scomp = NULL;
 
@@ -530,16 +533,6 @@
 	if (result)
 		goto recv_failed;
 
-	if (hdr_buf[1] != 0) {
-		/* FIXME: need subenclosure support; I've just never
-		 * seen a device with subenclosures and it makes the
-		 * traversal routines more complex */
-		sdev_printk(KERN_ERR, sdev,
-			"FIXME driver has no support for subenclosures (%d)\n",
-			hdr_buf[1]);
-		goto err_free;
-	}
-
 	len = (hdr_buf[2] << 8) + hdr_buf[3] + 4;
 	buf = kzalloc(len, GFP_KERNEL);
 	if (!buf)
@@ -549,11 +542,24 @@
 	if (result)
 		goto recv_failed;
 
-	types = buf[10];
+	types = 0;
 
-	type_ptr = buf + 12 + buf[11];
+	/* we always have one main enclosure and the rest are referred
+	 * to as secondary subenclosures */
+	num_enclosures = buf[1] + 1;
 
-	for (i = 0; i < types; i++, type_ptr += 4) {
+	/* begin at the enclosure descriptor */
+	type_ptr = buf + 8;
+	/* skip all the enclosure descriptors */
+	for (i = 0; i < num_enclosures && type_ptr < buf + len; i++) {
+		types += type_ptr[2];
+		type_ptr += type_ptr[3] + 4;
+	}
+
+	ses_dev->page1_types = type_ptr;
+	ses_dev->page1_num_types = types;
+
+	for (i = 0; i < types && type_ptr < buf + len; i++, type_ptr += 4) {
 		if (type_ptr[0] == ENCLOSURE_COMPONENT_DEVICE ||
 		    type_ptr[0] == ENCLOSURE_COMPONENT_ARRAY_DEVICE)
 			components += type_ptr[1];
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sr.c linux-libre-2.6.39-gnu/drivers/scsi/sr.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sr.c	2011-05-19 00:06:34.000000000 -0400
@@ -567,7 +567,7 @@
 	.revalidate_disk = sr_block_revalidate_disk,
 	/* 
 	 * No compat_ioctl for now because sr_block_ioctl never
-	 * seems to pass arbitary ioctls down to host drivers.
+	 * seems to pass arbitrary ioctls down to host drivers.
 	 */
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sun3_NCR5380.c linux-libre-2.6.39-gnu/drivers/scsi/sun3_NCR5380.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sun3_NCR5380.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sun3_NCR5380.c	2011-05-19 00:06:34.000000000 -0400
@@ -467,7 +467,7 @@
  *
  * Parameters: struct scsi_cmnd *cmd
  *    The command to work on. The first scatter buffer's data are
- *    assumed to be already transfered into ptr/this_residual.
+ *    assumed to be already transferred into ptr/this_residual.
  */
 
 static void merge_contiguous_buffers(struct scsi_cmnd *cmd)
@@ -1717,7 +1717,7 @@
  *	bytes to transfer, **data - pointer to data pointer.
  * 
  * Returns : -1 when different phase is entered without transferring
- *	maximum number of bytes, 0 if all bytes are transfered or exit
+ *	maximum number of bytes, 0 if all bytes are transferred or exit
  *	is in same phase.
  *
  * 	Also, *phase, *count, *data are modified in place.
@@ -1904,7 +1904,7 @@
  *	bytes to transfer, **data - pointer to data pointer.
  * 
  * Returns : -1 when different phase is entered without transferring
- *	maximum number of bytes, 0 if all bytes or transfered or exit
+ *	maximum number of bytes, 0 if all bytes or transferred or exit
  *	is in same phase.
  *
  * 	Also, *phase, *count, *data are modified in place.
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sun_esp.c linux-libre-2.6.39-gnu/drivers/scsi/sun_esp.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sun_esp.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sun_esp.c	2011-05-19 00:06:34.000000000 -0400
@@ -562,7 +562,7 @@
 	return err;
 }
 
-static int __devinit esp_sbus_probe(struct platform_device *op, const struct of_device_id *match)
+static int __devinit esp_sbus_probe(struct platform_device *op)
 {
 	struct device_node *dma_node = NULL;
 	struct device_node *dp = op->dev.of_node;
@@ -632,7 +632,7 @@
 };
 MODULE_DEVICE_TABLE(of, esp_match);
 
-static struct of_platform_driver esp_sbus_driver = {
+static struct platform_driver esp_sbus_driver = {
 	.driver = {
 		.name = "esp",
 		.owner = THIS_MODULE,
@@ -644,12 +644,12 @@
 
 static int __init sunesp_init(void)
 {
-	return of_register_platform_driver(&esp_sbus_driver);
+	return platform_driver_register(&esp_sbus_driver);
 }
 
 static void __exit sunesp_exit(void)
 {
-	of_unregister_platform_driver(&esp_sbus_driver);
+	platform_driver_unregister(&esp_sbus_driver);
 }
 
 MODULE_DESCRIPTION("Sun ESP SCSI driver");
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sym53c416.c linux-libre-2.6.39-gnu/drivers/scsi/sym53c416.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sym53c416.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sym53c416.c	2011-05-19 00:06:34.000000000 -0400
@@ -774,7 +774,7 @@
 
 	/* printk("sym53c416_reset\n"); */
 	base = SCpnt->device->host->io_port;
-	/* search scsi_id - fixme, we shouldnt need to iterate for this! */
+	/* search scsi_id - fixme, we shouldn't need to iterate for this! */
 	for(i = 0; i < host_index && scsi_id == -1; i++)
 		if(hosts[i].base == base)
 			scsi_id = hosts[i].scsi_id;
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_fw1.h linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_fw1.h
--- linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_fw1.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_fw1.h	2011-05-19 00:06:34.000000000 -0400
@@ -1449,7 +1449,7 @@
 		PADDR_B (msg_weird_seen),
 	/*
 	 *  We donnot handle extended messages from SCRIPTS.
-	 *  Read the amount of data correponding to the 
+	 *  Read the amount of data corresponding to the 
 	 *  message length and call the C code.
 	 */
 	SCR_COPY (1),
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_fw2.h linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_fw2.h
--- linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_fw2.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_fw2.h	2011-05-19 00:06:34.000000000 -0400
@@ -1326,7 +1326,7 @@
 		PADDR_B (msg_weird_seen),
 	/*
 	 *  We donnot handle extended messages from SCRIPTS.
-	 *  Read the amount of data correponding to the 
+	 *  Read the amount of data corresponding to the 
 	 *  message length and call the C code.
 	 */
 	SCR_STORE_REL (scratcha, 1),
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.c linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_hipd.c	2011-05-19 00:06:34.000000000 -0400
@@ -2457,7 +2457,7 @@
 		}
 
 		/*
-		 *  The data in the dma fifo has not been transfered to
+		 *  The data in the dma fifo has not been transferred to
 		 *  the target -> add the amount to the rest
 		 *  and clear the data.
 		 *  Check the sstat2 register in case of wide transfer.
@@ -5094,7 +5094,7 @@
 }
 
 /*
- *  Lun control block deallocation. Returns the number of valid remaing LCBs
+ *  Lun control block deallocation. Returns the number of valid remaining LCBs
  *  for the target.
  */
 int sym_free_lcb(struct sym_hcb *np, u_char tn, u_char ln)
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_malloc.c linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_malloc.c
--- linux-libre-2.6.38-gnu/drivers/scsi/sym53c8xx_2/sym_malloc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/sym53c8xx_2/sym_malloc.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,7 +50,7 @@
  *  from the SCRIPTS code. In addition, cache line alignment 
  *  is guaranteed for power of 2 cache line size.
  *
- *  This allocator has been developped for the Linux sym53c8xx  
+ *  This allocator has been developed for the Linux sym53c8xx  
  *  driver, since this O/S does not provide naturally aligned 
  *  allocations.
  *  It has the advantage of allowing the driver to use private 
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/ultrastor.c linux-libre-2.6.39-gnu/drivers/scsi/ultrastor.c
--- linux-libre-2.6.38-gnu/drivers/scsi/ultrastor.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/ultrastor.c	2011-05-19 00:06:34.000000000 -0400
@@ -138,6 +138,7 @@
 #include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/bitops.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/system.h>
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/wd33c93.c linux-libre-2.6.39-gnu/drivers/scsi/wd33c93.c
--- linux-libre-2.6.38-gnu/drivers/scsi/wd33c93.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/wd33c93.c	2011-05-19 00:06:34.000000000 -0400
@@ -1843,7 +1843,7 @@
  *
  * The original driver used to rely on a fixed sx_table, containing periods
  * for (only) the lower limits of the respective input-clock-frequency ranges
- * (8-10/12-15/16-20 MHz). Although it seems, that no problems ocurred with
+ * (8-10/12-15/16-20 MHz). Although it seems, that no problems occurred with
  * this setting so far, it might be desirable to adjust the transfer periods
  * closer to the really attached, possibly 25% higher, input-clock, since
  * - the wd33c93 may really use a significant shorter period, than it has
diff -druN linux-libre-2.6.38-gnu/drivers/scsi/wd7000.c linux-libre-2.6.39-gnu/drivers/scsi/wd7000.c
--- linux-libre-2.6.38-gnu/drivers/scsi/wd7000.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/scsi/wd7000.c	2011-05-19 00:06:34.000000000 -0400
@@ -837,7 +837,7 @@
 		}
 	}
 
-	/* Take the lock, then check we didnt get beaten, if so try again */
+	/* Take the lock, then check we didn't get beaten, if so try again */
 	spin_lock_irqsave(&scbpool_lock, flags);
 	if (freescbs < needed) {
 		spin_unlock_irqrestore(&scbpool_lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/sfi/sfi_core.c linux-libre-2.6.39-gnu/drivers/sfi/sfi_core.c
--- linux-libre-2.6.38-gnu/drivers/sfi/sfi_core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sfi/sfi_core.c	2011-05-19 00:06:34.000000000 -0400
@@ -515,7 +515,7 @@
 }
 
 /*
- * The reason we put it here becasue we need wait till the /sys/firmware
+ * The reason we put it here because we need wait till the /sys/firmware
  * is setup, then our interface can be registered in /sys/firmware/sfi
  */
 core_initcall(sfi_sysfs_init);
diff -druN linux-libre-2.6.38-gnu/drivers/sh/clk/core.c linux-libre-2.6.39-gnu/drivers/sh/clk/core.c
--- linux-libre-2.6.38-gnu/drivers/sh/clk/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sh/clk/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 #include <linux/module.h>
 #include <linux/mutex.h>
 #include <linux/list.h>
-#include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/seq_file.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -630,68 +630,36 @@
 EXPORT_SYMBOL_GPL(clk_round_parent);
 
 #ifdef CONFIG_PM
-static int clks_sysdev_suspend(struct sys_device *dev, pm_message_t state)
+static void clks_core_resume(void)
 {
-	static pm_message_t prev_state;
 	struct clk *clkp;
 
-	switch (state.event) {
-	case PM_EVENT_ON:
-		/* Resumeing from hibernation */
-		if (prev_state.event != PM_EVENT_FREEZE)
-			break;
-
-		list_for_each_entry(clkp, &clock_list, node) {
-			if (likely(clkp->ops)) {
-				unsigned long rate = clkp->rate;
+	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);
-				else if (likely(clkp->ops->recalc))
-					clkp->rate = clkp->ops->recalc(clkp);
-			}
+			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);
+			else if (likely(clkp->ops->recalc))
+				clkp->rate = clkp->ops->recalc(clkp);
 		}
-		break;
-	case PM_EVENT_FREEZE:
-		break;
-	case PM_EVENT_SUSPEND:
-		break;
 	}
-
-	prev_state = state;
-	return 0;
 }
 
-static int clks_sysdev_resume(struct sys_device *dev)
-{
-	return clks_sysdev_suspend(dev, PMSG_ON);
-}
-
-static struct sysdev_class clks_sysdev_class = {
-	.name = "clks",
-};
-
-static struct sysdev_driver clks_sysdev_driver = {
-	.suspend = clks_sysdev_suspend,
-	.resume = clks_sysdev_resume,
-};
-
-static struct sys_device clks_sysdev_dev = {
-	.cls = &clks_sysdev_class,
+static struct syscore_ops clks_syscore_ops = {
+	.resume = clks_core_resume,
 };
 
-static int __init clk_sysdev_init(void)
+static int __init clk_syscore_init(void)
 {
-	sysdev_class_register(&clks_sysdev_class);
-	sysdev_driver_register(&clks_sysdev_class, &clks_sysdev_driver);
-	sysdev_register(&clks_sysdev_dev);
+	register_syscore_ops(&clks_syscore_ops);
 
 	return 0;
 }
-subsys_initcall(clk_sysdev_init);
+subsys_initcall(clk_syscore_init);
 #endif
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/sh/intc/core.c linux-libre-2.6.39-gnu/drivers/sh/intc/core.c
--- linux-libre-2.6.38-gnu/drivers/sh/intc/core.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sh/intc/core.c	2011-05-19 00:06:34.000000000 -0400
@@ -25,6 +25,7 @@
 #include <linux/interrupt.h>
 #include <linux/sh_intc.h>
 #include <linux/sysdev.h>
+#include <linux/syscore_ops.h>
 #include <linux/list.h>
 #include <linux/spinlock.h>
 #include <linux/radix-tree.h>
@@ -62,7 +63,7 @@
 
 static void intc_redirect_irq(unsigned int irq, struct irq_desc *desc)
 {
-	generic_handle_irq((unsigned int)get_irq_data(irq));
+	generic_handle_irq((unsigned int)irq_get_handler_data(irq));
 }
 
 static void __init intc_register_irq(struct intc_desc *desc,
@@ -115,9 +116,9 @@
 	irq_data = irq_get_irq_data(irq);
 
 	disable_irq_nosync(irq);
-	set_irq_chip_and_handler_name(irq, &d->chip,
-				      handle_level_irq, "level");
-	set_irq_chip_data(irq, (void *)data[primary]);
+	irq_set_chip_and_handler_name(irq, &d->chip, handle_level_irq,
+				      "level");
+	irq_set_chip_data(irq, (void *)data[primary]);
 
 	/*
 	 * set priority level
@@ -339,9 +340,9 @@
 			vect2->enum_id = 0;
 
 			/* redirect this interrupts to the first one */
-			set_irq_chip(irq2, &dummy_irq_chip);
-			set_irq_chained_handler(irq2, intc_redirect_irq);
-			set_irq_data(irq2, (void *)irq);
+			irq_set_chip(irq2, &dummy_irq_chip);
+			irq_set_chained_handler(irq2, intc_redirect_irq);
+			irq_set_handler_data(irq2, (void *)irq);
 		}
 	}
 
@@ -376,91 +377,84 @@
 	return -ENOMEM;
 }
 
-static ssize_t
-show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
+static int intc_suspend(void)
 {
 	struct intc_desc_int *d;
 
-	d = container_of(dev, struct intc_desc_int, sysdev);
+	list_for_each_entry(d, &intc_list, list) {
+		int irq;
 
-	return sprintf(buf, "%s\n", d->chip.name);
-}
+		/* enable wakeup irqs belonging to this intc controller */
+		for_each_active_irq(irq) {
+			struct irq_data *data;
+			struct irq_chip *chip;
 
-static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
+			data = irq_get_irq_data(irq);
+			chip = irq_data_get_irq_chip(data);
+			if (chip != &d->chip)
+				continue;
+			if (irqd_is_wakeup_set(data))
+				chip->irq_enable(data);
+		}
+	}
+	return 0;
+}
 
-static int intc_suspend(struct sys_device *dev, pm_message_t state)
+static void intc_resume(void)
 {
 	struct intc_desc_int *d;
-	struct irq_data *data;
-	struct irq_desc *desc;
-	struct irq_chip *chip;
-	int irq;
-
-	/* get intc controller associated with this sysdev */
-	d = container_of(dev, struct intc_desc_int, sysdev);
 
-	switch (state.event) {
-	case PM_EVENT_ON:
-		if (d->state.event != PM_EVENT_FREEZE)
-			break;
+	list_for_each_entry(d, &intc_list, list) {
+		int irq;
 
 		for_each_active_irq(irq) {
-			desc = irq_to_desc(irq);
+			struct irq_data *data;
+			struct irq_chip *chip;
+
 			data = irq_get_irq_data(irq);
 			chip = irq_data_get_irq_chip(data);
-
 			/*
 			 * This will catch the redirect and VIRQ cases
 			 * due to the dummy_irq_chip being inserted.
 			 */
 			if (chip != &d->chip)
 				continue;
-			if (desc->status & IRQ_DISABLED)
+			if (irqd_irq_disabled(data))
 				chip->irq_disable(data);
 			else
 				chip->irq_enable(data);
 		}
-		break;
-	case PM_EVENT_FREEZE:
-		/* nothing has to be done */
-		break;
-	case PM_EVENT_SUSPEND:
-		/* enable wakeup irqs belonging to this intc controller */
-		for_each_active_irq(irq) {
-			desc = irq_to_desc(irq);
-			data = irq_get_irq_data(irq);
-			chip = irq_data_get_irq_chip(data);
-
-			if (chip != &d->chip)
-				continue;
-			if ((desc->status & IRQ_WAKEUP))
-				chip->irq_enable(data);
-		}
-		break;
 	}
-
-	d->state = state;
-
-	return 0;
 }
 
-static int intc_resume(struct sys_device *dev)
-{
-	return intc_suspend(dev, PMSG_ON);
-}
+struct syscore_ops intc_syscore_ops = {
+	.suspend	= intc_suspend,
+	.resume		= intc_resume,
+};
 
 struct sysdev_class intc_sysdev_class = {
 	.name		= "intc",
-	.suspend	= intc_suspend,
-	.resume		= intc_resume,
 };
 
-/* register this intc as sysdev to allow suspend/resume */
+static ssize_t
+show_intc_name(struct sys_device *dev, struct sysdev_attribute *attr, char *buf)
+{
+	struct intc_desc_int *d;
+
+	d = container_of(dev, struct intc_desc_int, sysdev);
+
+	return sprintf(buf, "%s\n", d->chip.name);
+}
+
+static SYSDEV_ATTR(name, S_IRUGO, show_intc_name, NULL);
+
 static int __init register_intc_sysdevs(void)
 {
 	struct intc_desc_int *d;
 	int error;
 
+	register_syscore_ops(&intc_syscore_ops);
+
 	error = sysdev_class_register(&intc_sysdev_class);
 	if (!error) {
 		list_for_each_entry(d, &intc_list, list) {
diff -druN linux-libre-2.6.38-gnu/drivers/sh/intc/internals.h linux-libre-2.6.39-gnu/drivers/sh/intc/internals.h
--- linux-libre-2.6.38-gnu/drivers/sh/intc/internals.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sh/intc/internals.h	2011-05-19 00:06:34.000000000 -0400
@@ -53,7 +53,6 @@
 	struct list_head list;
 	struct sys_device sysdev;
 	struct radix_tree_root tree;
-	pm_message_t state;
 	raw_spinlock_t lock;
 	unsigned int index;
 	unsigned long *reg;
@@ -87,7 +86,7 @@
 
 static inline struct intc_desc_int *get_intc_desc(unsigned int irq)
 {
-	struct irq_chip *chip = get_irq_chip(irq);
+	struct irq_chip *chip = irq_get_chip(irq);
 
 	return container_of(chip, struct intc_desc_int, chip);
 }
@@ -104,7 +103,7 @@
 	set_irq_flags(irq, IRQF_VALID);
 #else
 	/* same effect on other architectures */
-	set_irq_noprobe(irq);
+	irq_set_noprobe(irq);
 #endif
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/sh/intc/virq.c linux-libre-2.6.39-gnu/drivers/sh/intc/virq.c
--- linux-libre-2.6.38-gnu/drivers/sh/intc/virq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/sh/intc/virq.c	2011-05-19 00:06:34.000000000 -0400
@@ -110,7 +110,7 @@
 {
 	struct irq_data *data = irq_get_irq_data(irq);
 	struct irq_chip *chip = irq_data_get_irq_chip(data);
-	struct intc_virq_list *entry, *vlist = irq_data_get_irq_data(data);
+	struct intc_virq_list *entry, *vlist = irq_data_get_irq_handler_data(data);
 	struct intc_desc_int *d = get_intc_desc(irq);
 
 	chip->irq_mask_ack(data);
@@ -118,7 +118,7 @@
 	for_each_virq(entry, vlist) {
 		unsigned long addr, handle;
 
-		handle = (unsigned long)get_irq_data(entry->irq);
+		handle = (unsigned long)irq_get_handler_data(entry->irq);
 		addr = INTC_REG(d, _INTC_ADDR_E(handle), 0);
 
 		if (intc_reg_fns[_INTC_FN(handle)](addr, handle, 0))
@@ -229,13 +229,13 @@
 
 		intc_irq_xlate_set(irq, entry->enum_id, d);
 
-		set_irq_chip_and_handler_name(irq, get_irq_chip(entry->pirq),
+		irq_set_chip_and_handler_name(irq, irq_get_chip(entry->pirq),
 					      handle_simple_irq, "virq");
-		set_irq_chip_data(irq, get_irq_chip_data(entry->pirq));
+		irq_set_chip_data(irq, irq_get_chip_data(entry->pirq));
 
-		set_irq_data(irq, (void *)entry->handle);
+		irq_set_handler_data(irq, (void *)entry->handle);
 
-		set_irq_chained_handler(entry->pirq, intc_virq_handler);
+		irq_set_chained_handler(entry->pirq, intc_virq_handler);
 		add_virq_to_pirq(entry->pirq, irq);
 
 		radix_tree_tag_clear(&d->tree, entry->enum_id,
diff -druN linux-libre-2.6.38-gnu/drivers/spi/amba-pl022.c linux-libre-2.6.39-gnu/drivers/spi/amba-pl022.c
--- linux-libre-2.6.38-gnu/drivers/spi/amba-pl022.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/amba-pl022.c	2011-05-19 00:06:34.000000000 -0400
@@ -324,20 +324,22 @@
 	bool unidir;
 	bool extended_cr;
 	bool pl023;
+	bool loopback;
 };
 
 /**
  * struct pl022 - This is the private SSP driver data structure
  * @adev: AMBA device model hookup
- * @vendor: Vendor data for the IP block
- * @phybase: The physical memory where the SSP device resides
- * @virtbase: The virtual memory where the SSP is mapped
+ * @vendor: vendor data for the IP block
+ * @phybase: the physical memory where the SSP device resides
+ * @virtbase: the virtual memory where the SSP is mapped
+ * @clk: outgoing clock "SPICLK" for the SPI bus
  * @master: SPI framework hookup
  * @master_info: controller-specific data from machine setup
- * @regs: SSP controller register's virtual address
- * @pump_messages: Work struct for scheduling work to the workqueue
- * @lock: spinlock to syncronise access to driver data
  * @workqueue: a workqueue on which any spi_message request is queued
+ * @pump_messages: work struct for scheduling work to the workqueue
+ * @queue_lock: spinlock to syncronise access to message queue
+ * @queue: message queue
  * @busy: workqueue is busy
  * @running: workqueue is running
  * @pump_transfers: Tasklet used in Interrupt Transfer mode
@@ -348,8 +350,14 @@
  * @tx_end: end position in TX buffer to be read
  * @rx: current position in RX buffer to be written
  * @rx_end: end position in RX buffer to be written
- * @readingtype: the type of read currently going on
- * @writingtype: the type or write currently going on
+ * @read: the type of read currently going on
+ * @write: the type of write currently going on
+ * @exp_fifo_level: expected FIFO level
+ * @dma_rx_channel: optional channel for RX DMA
+ * @dma_tx_channel: optional channel for TX DMA
+ * @sgt_rx: scattertable for the RX transfer
+ * @sgt_tx: scattertable for the TX transfer
+ * @dummypage: a dummy page used for driving data on the bus with DMA
  */
 struct pl022 {
 	struct amba_device		*adev;
@@ -397,8 +405,8 @@
  * @cpsr: Value of Clock prescale register
  * @n_bytes: how many bytes(power of 2) reqd for a given data width of client
  * @enable_dma: Whether to enable DMA or not
- * @write: function ptr to be used to write when doing xfer for this chip
  * @read: function ptr to be used to read when doing xfer for this chip
+ * @write: function ptr to be used to write when doing xfer for this chip
  * @cs_control: chip select callback provided by chip
  * @xfer_type: polling/interrupt/DMA
  *
@@ -508,9 +516,10 @@
 	msg->state = NULL;
 	if (msg->complete)
 		msg->complete(msg->context);
-	/* This message is completed, so let's turn off the clocks! */
+	/* This message is completed, so let's turn off the clocks & power */
 	clk_disable(pl022->clk);
 	amba_pclk_disable(pl022->adev);
+	amba_vcore_disable(pl022->adev);
 }
 
 /**
@@ -652,7 +661,7 @@
 {
 
 	/*
-	 * The FIFO depth is different inbetween primecell variants.
+	 * The FIFO depth is different between primecell variants.
 	 * I believe filling in too much in the FIFO might cause
 	 * errons in 8bit wide transfers on ARM variants (just 8 words
 	 * FIFO, means only 8x8 = 64 bits in FIFO) at least.
@@ -713,7 +722,7 @@
 		 * This inner reader takes care of things appearing in the RX
 		 * FIFO as we're transmitting. This will happen a lot since the
 		 * clock starts running when you put things into the TX FIFO,
-		 * and then things are continously clocked into the RX FIFO.
+		 * and then things are continuously clocked into the RX FIFO.
 		 */
 		while ((readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
 		       && (pl022->rx < pl022->rx_end)) {
@@ -833,7 +842,7 @@
 
 	unmap_free_dma_scatter(pl022);
 
-	/* Update total bytes transfered */
+	/* Update total bytes transferred */
 	msg->actual_length += pl022->cur_transfer->len;
 	if (pl022->cur_transfer->cs_change)
 		pl022->cur_chip->
@@ -917,7 +926,6 @@
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 	struct dma_async_tx_descriptor *rxdesc;
 	struct dma_async_tx_descriptor *txdesc;
-	dma_cookie_t cookie;
 
 	/* Check that the channels are available */
 	if (!rxchan || !txchan)
@@ -962,10 +970,8 @@
 		tx_conf.dst_addr_width = rx_conf.src_addr_width;
 	BUG_ON(rx_conf.src_addr_width != tx_conf.dst_addr_width);
 
-	rxchan->device->device_control(rxchan, DMA_SLAVE_CONFIG,
-				       (unsigned long) &rx_conf);
-	txchan->device->device_control(txchan, DMA_SLAVE_CONFIG,
-				       (unsigned long) &tx_conf);
+	dmaengine_slave_config(rxchan, &rx_conf);
+	dmaengine_slave_config(txchan, &tx_conf);
 
 	/* Create sglists for the transfers */
 	pages = (pl022->cur_transfer->len >> PAGE_SHIFT) + 1;
@@ -1018,23 +1024,17 @@
 	rxdesc->callback_param = pl022;
 
 	/* Submit and fire RX and TX with TX last so we're ready to read! */
-	cookie = rxdesc->tx_submit(rxdesc);
-	if (dma_submit_error(cookie))
-		goto err_submit_rx;
-	cookie = txdesc->tx_submit(txdesc);
-	if (dma_submit_error(cookie))
-		goto err_submit_tx;
-	rxchan->device->device_issue_pending(rxchan);
-	txchan->device->device_issue_pending(txchan);
+	dmaengine_submit(rxdesc);
+	dmaengine_submit(txdesc);
+	dma_async_issue_pending(rxchan);
+	dma_async_issue_pending(txchan);
 
 	return 0;
 
-err_submit_tx:
-err_submit_rx:
 err_txdesc:
-	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+	dmaengine_terminate_all(txchan);
 err_rxdesc:
-	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
+	dmaengine_terminate_all(rxchan);
 	dma_unmap_sg(txchan->device->dev, pl022->sgt_tx.sgl,
 		     pl022->sgt_tx.nents, DMA_TO_DEVICE);
 err_tx_sgmap:
@@ -1101,8 +1101,8 @@
 	struct dma_chan *rxchan = pl022->dma_rx_channel;
 	struct dma_chan *txchan = pl022->dma_tx_channel;
 
-	rxchan->device->device_control(rxchan, DMA_TERMINATE_ALL, 0);
-	txchan->device->device_control(txchan, DMA_TERMINATE_ALL, 0);
+	dmaengine_terminate_all(rxchan);
+	dmaengine_terminate_all(txchan);
 	unmap_free_dma_scatter(pl022);
 }
 
@@ -1224,7 +1224,7 @@
 				 "number of bytes on a 16bit bus?)\n",
 				 (u32) (pl022->rx - pl022->rx_end));
 		}
-		/* Update total bytes transfered */
+		/* Update total bytes transferred */
 		msg->actual_length += pl022->cur_transfer->len;
 		if (pl022->cur_transfer->cs_change)
 			pl022->cur_chip->
@@ -1415,11 +1415,11 @@
 		       SSP_CR1(pl022->virtbase));
 
 		dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n");
-		/* FIXME: insert a timeout so we don't hang here indefinately */
+		/* FIXME: insert a timeout so we don't hang here indefinitely */
 		while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end)
 			readwriter(pl022);
 
-		/* Update total byte transfered */
+		/* Update total byte transferred */
 		message->actual_length += pl022->cur_transfer->len;
 		if (pl022->cur_transfer->cs_change)
 			pl022->cur_chip->cs_control(SSP_CHIP_DESELECT);
@@ -1482,9 +1482,11 @@
 	/* Setup the SPI using the per chip configuration */
 	pl022->cur_chip = spi_get_ctldata(pl022->cur_msg->spi);
 	/*
-	 * We enable the clocks here, then the clocks will be disabled when
-	 * giveback() is called in each method (poll/interrupt/DMA)
+	 * We enable the core voltage and clocks here, then the clocks
+	 * and core will be disabled when giveback() is called in each method
+	 * (poll/interrupt/DMA)
 	 */
+	amba_vcore_enable(pl022->adev);
 	amba_pclk_enable(pl022->adev);
 	clk_enable(pl022->clk);
 	restore_state(pl022);
@@ -1553,7 +1555,7 @@
 	 * A wait_queue on the pl022->busy could be used, but then the common
 	 * execution path (pump_messages) would be required to call wake_up or
 	 * friends on every SPI message. Do this instead */
-	while (!list_empty(&pl022->queue) && pl022->busy && limit--) {
+	while ((!list_empty(&pl022->queue) || pl022->busy) && limit--) {
 		spin_unlock_irqrestore(&pl022->queue_lock, flags);
 		msleep(10);
 		spin_lock_irqsave(&pl022->queue_lock, flags);
@@ -1910,8 +1912,6 @@
 	    && ((pl022->master_info)->enable_dma)) {
 		chip->enable_dma = true;
 		dev_dbg(&spi->dev, "DMA mode set in controller state\n");
-		if (status < 0)
-			goto err_config_params;
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
 			       SSP_DMACR_MASK_RXDMAE, 0);
 		SSP_WRITE_BITS(chip->dmacr, SSP_DMA_ENABLED,
@@ -1984,7 +1984,7 @@
 
 	SSP_WRITE_BITS(chip->cr0, clk_freq.scr, SSP_CR0_MASK_SCR, 8);
 	/* Loopback is available on all versions except PL023 */
-	if (!pl022->vendor->pl023) {
+	if (pl022->vendor->loopback) {
 		if (spi->mode & SPI_LOOP)
 			tmp = LOOPBACK_ENABLED;
 		else
@@ -2021,7 +2021,7 @@
 
 
 static int __devinit
-pl022_probe(struct amba_device *adev, struct amba_id *id)
+pl022_probe(struct amba_device *adev, const struct amba_id *id)
 {
 	struct device *dev = &adev->dev;
 	struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
@@ -2129,9 +2129,13 @@
 			"probe - problem registering spi master\n");
 		goto err_spi_register;
 	}
-	dev_dbg(dev, "probe succeded\n");
-	/* Disable the silicon block pclk and clock it when needed */
+	dev_dbg(dev, "probe succeeded\n");
+	/*
+	 * Disable the silicon block pclk and any voltage domain and just
+	 * power it up and clock it when it's needed
+	 */
 	amba_pclk_disable(adev);
+	amba_vcore_disable(adev);
 	return 0;
 
  err_spi_register:
@@ -2180,7 +2184,7 @@
 	spi_unregister_master(pl022->master);
 	spi_master_put(pl022->master);
 	amba_set_drvdata(adev, NULL);
-	dev_dbg(&adev->dev, "remove succeded\n");
+	dev_dbg(&adev->dev, "remove succeeded\n");
 	return 0;
 }
 
@@ -2196,9 +2200,11 @@
 		return status;
 	}
 
+	amba_vcore_enable(adev);
 	amba_pclk_enable(adev);
 	load_ssp_default_config(pl022);
 	amba_pclk_disable(adev);
+	amba_vcore_disable(adev);
 	dev_dbg(&adev->dev, "suspended\n");
 	return 0;
 }
@@ -2228,6 +2234,7 @@
 	.unidir = false,
 	.extended_cr = false,
 	.pl023 = false,
+	.loopback = true,
 };
 
 
@@ -2237,6 +2244,7 @@
 	.unidir = false,
 	.extended_cr = true,
 	.pl023 = false,
+	.loopback = true,
 };
 
 static struct vendor_data vendor_st_pl023 = {
@@ -2245,6 +2253,16 @@
 	.unidir = false,
 	.extended_cr = true,
 	.pl023 = true,
+	.loopback = false,
+};
+
+static struct vendor_data vendor_db5500_pl023 = {
+	.fifodepth = 32,
+	.max_bpw = 32,
+	.unidir = false,
+	.extended_cr = true,
+	.pl023 = true,
+	.loopback = true,
 };
 
 static struct amba_id pl022_ids[] = {
@@ -2278,6 +2296,11 @@
 		.mask   = 0xffffffff,
 		.data   = &vendor_st_pl023,
 	},
+	{
+		.id	= 0x10080023,
+		.mask	= 0xffffffff,
+		.data	= &vendor_db5500_pl023,
+	},
 	{ 0, 0 },
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/au1550_spi.c linux-libre-2.6.39-gnu/drivers/spi/au1550_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/au1550_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/au1550_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -480,7 +480,7 @@
 		au1xxx_dbdma_stop(hw->dma_rx_ch);
 		au1xxx_dbdma_stop(hw->dma_tx_ch);
 
-		/* get number of transfered bytes */
+		/* get number of transferred bytes */
 		hw->rx_count = hw->len - au1xxx_get_dma_residue(hw->dma_rx_ch);
 		hw->tx_count = hw->len - au1xxx_get_dma_residue(hw->dma_tx_ch);
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/davinci_spi.c linux-libre-2.6.39-gnu/drivers/spi/davinci_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/davinci_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/davinci_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -571,6 +571,7 @@
 		unsigned long tx_reg, rx_reg;
 		struct edmacc_param param;
 		void *rx_buf;
+		int b, c;
 
 		dma = &dspi->dma;
 
@@ -591,22 +592,38 @@
 
 		if (t->tx_buf) {
 			t->tx_dma = dma_map_single(&spi->dev, (void *)t->tx_buf,
-						dspi->wcount, DMA_TO_DEVICE);
+						t->len, DMA_TO_DEVICE);
 			if (dma_mapping_error(&spi->dev, t->tx_dma)) {
 				dev_dbg(sdev, "Unable to DMA map %d bytes"
-						"TX buffer\n", dspi->wcount);
+						"TX buffer\n", t->len);
 				return -ENOMEM;
 			}
 		}
 
+		/*
+		 * If number of words is greater than 65535, then we need
+		 * to configure a 3 dimension transfer.  Use the BCNTRLD
+		 * feature to allow for transfers that aren't even multiples
+		 * of 65535 (or any other possible b size) by first transferring
+		 * the remainder amount then grabbing the next N blocks of
+		 * 65535 words.
+		 */
+
+		c = dspi->wcount / (SZ_64K - 1);	/* N 65535 Blocks */
+		b = dspi->wcount - c * (SZ_64K - 1);	/* Remainder */
+		if (b)
+			c++;
+		else
+			b = SZ_64K - 1;
+
 		param.opt = TCINTEN | EDMA_TCC(dma->tx_channel);
 		param.src = t->tx_buf ? t->tx_dma : tx_reg;
-		param.a_b_cnt = dspi->wcount << 16 | data_type;
+		param.a_b_cnt = b << 16 | data_type;
 		param.dst = tx_reg;
 		param.src_dst_bidx = t->tx_buf ? data_type : 0;
-		param.link_bcntrld = 0xffff;
-		param.src_dst_cidx = 0;
-		param.ccnt = 1;
+		param.link_bcntrld = 0xffffffff;
+		param.src_dst_cidx = t->tx_buf ? data_type : 0;
+		param.ccnt = c;
 		edma_write_slot(dma->tx_channel, &param);
 		edma_link(dma->tx_channel, dma->dummy_param_slot);
 
@@ -624,7 +641,7 @@
 
 		if (t->rx_buf) {
 			rx_buf = t->rx_buf;
-			rx_buf_count = dspi->rcount;
+			rx_buf_count = t->len;
 		} else {
 			rx_buf = dspi->rx_tmp_buf;
 			rx_buf_count = sizeof(dspi->rx_tmp_buf);
@@ -636,19 +653,19 @@
 			dev_dbg(sdev, "Couldn't DMA map a %d bytes RX buffer\n",
 								rx_buf_count);
 			if (t->tx_buf)
-				dma_unmap_single(NULL, t->tx_dma, dspi->wcount,
+				dma_unmap_single(NULL, t->tx_dma, t->len,
 								DMA_TO_DEVICE);
 			return -ENOMEM;
 		}
 
 		param.opt = TCINTEN | EDMA_TCC(dma->rx_channel);
 		param.src = rx_reg;
-		param.a_b_cnt = dspi->rcount << 16 | data_type;
+		param.a_b_cnt = b << 16 | data_type;
 		param.dst = t->rx_dma;
 		param.src_dst_bidx = (t->rx_buf ? data_type : 0) << 16;
-		param.link_bcntrld = 0xffff;
-		param.src_dst_cidx = 0;
-		param.ccnt = 1;
+		param.link_bcntrld = 0xffffffff;
+		param.src_dst_cidx = (t->rx_buf ? data_type : 0) << 16;
+		param.ccnt = c;
 		edma_write_slot(dma->rx_channel, &param);
 
 		if (pdata->cshold_bug)
@@ -675,7 +692,7 @@
 	if (spicfg->io_type == SPI_IO_TYPE_DMA) {
 
 		if (t->tx_buf)
-			dma_unmap_single(NULL, t->tx_dma, dspi->wcount,
+			dma_unmap_single(NULL, t->tx_dma, t->len,
 								DMA_TO_DEVICE);
 
 		dma_unmap_single(NULL, t->rx_dma, rx_buf_count,
@@ -790,7 +807,6 @@
 	struct resource *r, *mem;
 	resource_size_t dma_rx_chan = SPI_NO_RESOURCE;
 	resource_size_t	dma_tx_chan = SPI_NO_RESOURCE;
-	resource_size_t	dma_eventq = SPI_NO_RESOURCE;
 	int i = 0, ret = 0;
 	u32 spipc0;
 
@@ -878,17 +894,13 @@
 	r = platform_get_resource(pdev, IORESOURCE_DMA, 1);
 	if (r)
 		dma_tx_chan = r->start;
-	r = platform_get_resource(pdev, IORESOURCE_DMA, 2);
-	if (r)
-		dma_eventq = r->start;
 
 	dspi->bitbang.txrx_bufs = davinci_spi_bufs;
 	if (dma_rx_chan != SPI_NO_RESOURCE &&
-	    dma_tx_chan != SPI_NO_RESOURCE &&
-	    dma_eventq != SPI_NO_RESOURCE) {
+	    dma_tx_chan != SPI_NO_RESOURCE) {
 		dspi->dma.rx_channel = dma_rx_chan;
 		dspi->dma.tx_channel = dma_tx_chan;
-		dspi->dma.eventq = dma_eventq;
+		dspi->dma.eventq = pdata->dma_event_q;
 
 		ret = davinci_spi_request_dma(dspi);
 		if (ret)
@@ -897,7 +909,7 @@
 		dev_info(&pdev->dev, "DMA: supported\n");
 		dev_info(&pdev->dev, "DMA: RX channel: %d, TX channel: %d, "
 				"event queue: %d\n", dma_rx_chan, dma_tx_chan,
-				dma_eventq);
+				pdata->dma_event_q);
 	}
 
 	dspi->get_rx = davinci_spi_rx_buf_u8;
diff -druN linux-libre-2.6.38-gnu/drivers/spi/dw_spi.c linux-libre-2.6.39-gnu/drivers/spi/dw_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/dw_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/dw_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,10 +22,10 @@
 #include <linux/highmem.h>
 #include <linux/delay.h>
 #include <linux/slab.h>
-
-#include <linux/spi/dw_spi.h>
 #include <linux/spi/spi.h>
 
+#include "dw_spi.h"
+
 #ifdef CONFIG_DEBUG_FS
 #include <linux/debugfs.h>
 #endif
@@ -345,7 +345,7 @@
 
 void dw_spi_xfer_done(struct dw_spi *dws)
 {
-	/* Update total byte transfered return count actual bytes read */
+	/* Update total byte transferred return count actual bytes read */
 	dws->cur_msg->actual_length += dws->len;
 
 	/* Move to next transfer */
@@ -821,7 +821,7 @@
 
 	spin_lock_irqsave(&dws->lock, flags);
 	dws->run = QUEUE_STOPPED;
-	while (!list_empty(&dws->queue) && dws->busy && limit--) {
+	while ((!list_empty(&dws->queue) || dws->busy) && limit--) {
 		spin_unlock_irqrestore(&dws->lock, flags);
 		msleep(10);
 		spin_lock_irqsave(&dws->lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/dw_spi.h linux-libre-2.6.39-gnu/drivers/spi/dw_spi.h
--- linux-libre-2.6.38-gnu/drivers/spi/dw_spi.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/spi/dw_spi.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,234 @@
+#ifndef DW_SPI_HEADER_H
+#define DW_SPI_HEADER_H
+
+#include <linux/io.h>
+#include <linux/scatterlist.h>
+
+/* Bit fields in CTRLR0 */
+#define SPI_DFS_OFFSET			0
+
+#define SPI_FRF_OFFSET			4
+#define SPI_FRF_SPI			0x0
+#define SPI_FRF_SSP			0x1
+#define SPI_FRF_MICROWIRE		0x2
+#define SPI_FRF_RESV			0x3
+
+#define SPI_MODE_OFFSET			6
+#define SPI_SCPH_OFFSET			6
+#define SPI_SCOL_OFFSET			7
+
+#define SPI_TMOD_OFFSET			8
+#define SPI_TMOD_MASK			(0x3 << SPI_TMOD_OFFSET)
+#define	SPI_TMOD_TR			0x0		/* xmit & recv */
+#define SPI_TMOD_TO			0x1		/* xmit only */
+#define SPI_TMOD_RO			0x2		/* recv only */
+#define SPI_TMOD_EPROMREAD		0x3		/* eeprom read mode */
+
+#define SPI_SLVOE_OFFSET		10
+#define SPI_SRL_OFFSET			11
+#define SPI_CFS_OFFSET			12
+
+/* Bit fields in SR, 7 bits */
+#define SR_MASK				0x7f		/* cover 7 bits */
+#define SR_BUSY				(1 << 0)
+#define SR_TF_NOT_FULL			(1 << 1)
+#define SR_TF_EMPT			(1 << 2)
+#define SR_RF_NOT_EMPT			(1 << 3)
+#define SR_RF_FULL			(1 << 4)
+#define SR_TX_ERR			(1 << 5)
+#define SR_DCOL				(1 << 6)
+
+/* Bit fields in ISR, IMR, RISR, 7 bits */
+#define SPI_INT_TXEI			(1 << 0)
+#define SPI_INT_TXOI			(1 << 1)
+#define SPI_INT_RXUI			(1 << 2)
+#define SPI_INT_RXOI			(1 << 3)
+#define SPI_INT_RXFI			(1 << 4)
+#define SPI_INT_MSTI			(1 << 5)
+
+/* TX RX interrupt level threshold, max can be 256 */
+#define SPI_INT_THRESHOLD		32
+
+enum dw_ssi_type {
+	SSI_MOTO_SPI = 0,
+	SSI_TI_SSP,
+	SSI_NS_MICROWIRE,
+};
+
+struct dw_spi_reg {
+	u32	ctrl0;
+	u32	ctrl1;
+	u32	ssienr;
+	u32	mwcr;
+	u32	ser;
+	u32	baudr;
+	u32	txfltr;
+	u32	rxfltr;
+	u32	txflr;
+	u32	rxflr;
+	u32	sr;
+	u32	imr;
+	u32	isr;
+	u32	risr;
+	u32	txoicr;
+	u32	rxoicr;
+	u32	rxuicr;
+	u32	msticr;
+	u32	icr;
+	u32	dmacr;
+	u32	dmatdlr;
+	u32	dmardlr;
+	u32	idr;
+	u32	version;
+	u32	dr;		/* Currently oper as 32 bits,
+				though only low 16 bits matters */
+} __packed;
+
+struct dw_spi;
+struct dw_spi_dma_ops {
+	int (*dma_init)(struct dw_spi *dws);
+	void (*dma_exit)(struct dw_spi *dws);
+	int (*dma_transfer)(struct dw_spi *dws, int cs_change);
+};
+
+struct dw_spi {
+	struct spi_master	*master;
+	struct spi_device	*cur_dev;
+	struct device		*parent_dev;
+	enum dw_ssi_type	type;
+
+	void __iomem		*regs;
+	unsigned long		paddr;
+	u32			iolen;
+	int			irq;
+	u32			fifo_len;	/* depth of the FIFO buffer */
+	u32			max_freq;	/* max bus freq supported */
+
+	u16			bus_num;
+	u16			num_cs;		/* supported slave numbers */
+
+	/* Driver message queue */
+	struct workqueue_struct	*workqueue;
+	struct work_struct	pump_messages;
+	spinlock_t		lock;
+	struct list_head	queue;
+	int			busy;
+	int			run;
+
+	/* Message Transfer pump */
+	struct tasklet_struct	pump_transfers;
+
+	/* Current message transfer state info */
+	struct spi_message	*cur_msg;
+	struct spi_transfer	*cur_transfer;
+	struct chip_data	*cur_chip;
+	struct chip_data	*prev_chip;
+	size_t			len;
+	void			*tx;
+	void			*tx_end;
+	void			*rx;
+	void			*rx_end;
+	int			dma_mapped;
+	dma_addr_t		rx_dma;
+	dma_addr_t		tx_dma;
+	size_t			rx_map_len;
+	size_t			tx_map_len;
+	u8			n_bytes;	/* current is a 1/2 bytes op */
+	u8			max_bits_per_word;	/* maxim is 16b */
+	u32			dma_width;
+	int			cs_change;
+	int			(*write)(struct dw_spi *dws);
+	int			(*read)(struct dw_spi *dws);
+	irqreturn_t		(*transfer_handler)(struct dw_spi *dws);
+	void			(*cs_control)(u32 command);
+
+	/* Dma info */
+	int			dma_inited;
+	struct dma_chan		*txchan;
+	struct scatterlist	tx_sgl;
+	struct dma_chan		*rxchan;
+	struct scatterlist	rx_sgl;
+	int			dma_chan_done;
+	struct device		*dma_dev;
+	dma_addr_t		dma_addr; /* phy address of the Data register */
+	struct dw_spi_dma_ops	*dma_ops;
+	void			*dma_priv; /* platform relate info */
+	struct pci_dev		*dmac;
+
+	/* Bus interface info */
+	void			*priv;
+#ifdef CONFIG_DEBUG_FS
+	struct dentry *debugfs;
+#endif
+};
+
+#define dw_readl(dw, name) \
+	__raw_readl(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writel(dw, name, val) \
+	__raw_writel((val), &(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_readw(dw, name) \
+	__raw_readw(&(((struct dw_spi_reg *)dw->regs)->name))
+#define dw_writew(dw, name, val) \
+	__raw_writew((val), &(((struct dw_spi_reg *)dw->regs)->name))
+
+static inline void spi_enable_chip(struct dw_spi *dws, int enable)
+{
+	dw_writel(dws, ssienr, (enable ? 1 : 0));
+}
+
+static inline void spi_set_clk(struct dw_spi *dws, u16 div)
+{
+	dw_writel(dws, baudr, div);
+}
+
+static inline void spi_chip_sel(struct dw_spi *dws, u16 cs)
+{
+	if (cs > dws->num_cs)
+		return;
+
+	if (dws->cs_control)
+		dws->cs_control(1);
+
+	dw_writel(dws, ser, 1 << cs);
+}
+
+/* Disable IRQ bits */
+static inline void spi_mask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) & ~mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/* Enable IRQ bits */
+static inline void spi_umask_intr(struct dw_spi *dws, u32 mask)
+{
+	u32 new_mask;
+
+	new_mask = dw_readl(dws, imr) | mask;
+	dw_writel(dws, imr, new_mask);
+}
+
+/*
+ * Each SPI slave device to work with dw_api controller should
+ * has such a structure claiming its working mode (PIO/DMA etc),
+ * which can be save in the "controller_data" member of the
+ * struct spi_device
+ */
+struct dw_spi_chip {
+	u8 poll_mode;	/* 0 for contoller polling mode */
+	u8 type;	/* SPI/SSP/Micrwire */
+	u8 enable_dma;
+	void (*cs_control)(u32 command);
+};
+
+extern int dw_spi_add_host(struct dw_spi *dws);
+extern void dw_spi_remove_host(struct dw_spi *dws);
+extern int dw_spi_suspend_host(struct dw_spi *dws);
+extern int dw_spi_resume_host(struct dw_spi *dws);
+extern void dw_spi_xfer_done(struct dw_spi *dws);
+
+/* platform related setup */
+extern int dw_spi_mid_init(struct dw_spi *dws); /* Intel MID platforms */
+#endif /* DW_SPI_HEADER_H */
diff -druN linux-libre-2.6.38-gnu/drivers/spi/dw_spi_mid.c linux-libre-2.6.39-gnu/drivers/spi/dw_spi_mid.c
--- linux-libre-2.6.38-gnu/drivers/spi/dw_spi_mid.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/dw_spi_mid.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,7 +22,8 @@
 #include <linux/interrupt.h>
 #include <linux/slab.h>
 #include <linux/spi/spi.h>
-#include <linux/spi/dw_spi.h>
+
+#include "dw_spi.h"
 
 #ifdef CONFIG_SPI_DW_MID_DMA
 #include <linux/intel_mid_dma.h>
diff -druN linux-libre-2.6.38-gnu/drivers/spi/dw_spi_mmio.c linux-libre-2.6.39-gnu/drivers/spi/dw_spi_mmio.c
--- linux-libre-2.6.38-gnu/drivers/spi/dw_spi_mmio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/dw_spi_mmio.c	2011-05-19 00:06:34.000000000 -0400
@@ -13,8 +13,10 @@
 #include <linux/interrupt.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
-#include <linux/spi/dw_spi.h>
 #include <linux/spi/spi.h>
+#include <linux/scatterlist.h>
+
+#include "dw_spi.h"
 
 #define DRIVER_NAME "dw_spi_mmio"
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/dw_spi_pci.c linux-libre-2.6.39-gnu/drivers/spi/dw_spi_pci.c
--- linux-libre-2.6.38-gnu/drivers/spi/dw_spi_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/dw_spi_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -20,9 +20,10 @@
 #include <linux/interrupt.h>
 #include <linux/pci.h>
 #include <linux/slab.h>
-#include <linux/spi/dw_spi.h>
 #include <linux/spi/spi.h>
 
+#include "dw_spi.h"
+
 #define DRIVER_NAME "dw_spi_pci"
 
 struct dw_spi_pci {
diff -druN linux-libre-2.6.38-gnu/drivers/spi/ep93xx_spi.c linux-libre-2.6.39-gnu/drivers/spi/ep93xx_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/ep93xx_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/ep93xx_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -512,7 +512,7 @@
  *
  * This function processes one SPI transfer given in @t. Function waits until
  * transfer is complete (may sleep) and updates @msg->status based on whether
- * transfer was succesfully processed or not.
+ * transfer was successfully processed or not.
  */
 static void ep93xx_spi_process_transfer(struct ep93xx_spi *espi,
 					struct spi_message *msg,
diff -druN linux-libre-2.6.38-gnu/drivers/spi/Kconfig linux-libre-2.6.39-gnu/drivers/spi/Kconfig
--- linux-libre-2.6.38-gnu/drivers/spi/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -53,6 +53,12 @@
 
 comment "SPI Master Controller Drivers"
 
+config SPI_ALTERA
+	tristate "Altera SPI Controller"
+	select SPI_BITBANG
+	help
+	  This is the driver for the Altera SPI Controller.
+
 config SPI_ATH79
 	tristate "Atheros AR71XX/AR724X/AR913X SPI controller driver"
 	depends on ATH79 && GENERIC_GPIO
@@ -161,13 +167,13 @@
 	def_bool y if SOC_IMX21 || SOC_IMX27
 
 config SPI_IMX_VER_0_4
-	def_bool y if ARCH_MX31
+	def_bool y if SOC_IMX31
 
 config SPI_IMX_VER_0_7
-	def_bool y if ARCH_MX25 || ARCH_MX35 || ARCH_MX51 || ARCH_MX53
+	def_bool y if ARCH_MX25 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
 
 config SPI_IMX_VER_2_3
-	def_bool y if ARCH_MX51 || ARCH_MX53
+	def_bool y if SOC_IMX51 || SOC_IMX53
 
 config SPI_IMX
 	tristate "Freescale i.MX SPI controllers"
@@ -231,6 +237,13 @@
 	  From MPC8536, 85xx platform uses the controller, and all P10xx,
 	  P20xx, P30xx,P40xx, P50xx uses this controller.
 
+config SPI_OC_TINY
+	tristate "OpenCores tiny SPI"
+	depends on GENERIC_GPIO
+	select SPI_BITBANG
+	help
+	  This is the driver for OpenCores tiny SPI master controller.
+
 config SPI_OMAP_UWIRE
 	tristate "OMAP1 MicroWire"
 	depends on ARCH_OMAP1
@@ -330,6 +343,12 @@
 	help
 	  SPI driver for SuperH MSIOF blocks.
 
+config SPI_SH
+	tristate "SuperH SPI controller"
+	depends on SUPERH
+	help
+	  SPI driver for SuperH SPI blocks.
+
 config SPI_SH_SCI
 	tristate "SuperH SCI SPI controller"
 	depends on SUPERH
@@ -350,6 +369,16 @@
 	help
 	  SPI driver for NVidia Tegra SoCs
 
+config SPI_TI_SSP
+	tristate "TI Sequencer Serial Port - SPI Support"
+	depends on MFD_TI_SSP
+	help
+	  This selects an SPI master implementation using a TI sequencer
+	  serial port.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called ti-ssp-spi.
+
 config SPI_TOPCLIFF_PCH
 	tristate "Topcliff PCH SPI Controller"
 	depends on PCI
diff -druN linux-libre-2.6.38-gnu/drivers/spi/Makefile linux-libre-2.6.39-gnu/drivers/spi/Makefile
--- linux-libre-2.6.38-gnu/drivers/spi/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -9,6 +9,7 @@
 obj-$(CONFIG_SPI_MASTER)		+= spi.o
 
 # SPI master controller drivers (bus)
+obj-$(CONFIG_SPI_ALTERA)		+= spi_altera.o
 obj-$(CONFIG_SPI_ATMEL)			+= atmel_spi.o
 obj-$(CONFIG_SPI_ATH79)			+= ath79_spi.o
 obj-$(CONFIG_SPI_BFIN)			+= spi_bfin5xx.o
@@ -27,6 +28,7 @@
 obj-$(CONFIG_SPI_LM70_LLP)		+= spi_lm70llp.o
 obj-$(CONFIG_SPI_PXA2XX)		+= pxa2xx_spi.o
 obj-$(CONFIG_SPI_PXA2XX_PCI)		+= pxa2xx_spi_pci.o
+obj-$(CONFIG_SPI_OC_TINY)		+= spi_oc_tiny.o
 obj-$(CONFIG_SPI_OMAP_UWIRE)		+= omap_uwire.o
 obj-$(CONFIG_SPI_OMAP24XX)		+= omap2_mcspi.o
 obj-$(CONFIG_SPI_OMAP_100K)		+= omap_spi_100k.o
@@ -43,9 +45,11 @@
 obj-$(CONFIG_SPI_S3C24XX)		+= spi_s3c24xx_hw.o
 obj-$(CONFIG_SPI_S3C64XX)		+= spi_s3c64xx.o
 obj-$(CONFIG_SPI_TEGRA)			+= spi_tegra.o
+obj-$(CONFIG_SPI_TI_SSP)		+= ti-ssp-spi.o
 obj-$(CONFIG_SPI_TOPCLIFF_PCH)		+= spi_topcliff_pch.o
 obj-$(CONFIG_SPI_TXX9)			+= spi_txx9.o
 obj-$(CONFIG_SPI_XILINX)		+= xilinx_spi.o
+obj-$(CONFIG_SPI_SH)			+= spi_sh.o
 obj-$(CONFIG_SPI_SH_SCI)		+= spi_sh_sci.o
 obj-$(CONFIG_SPI_SH_MSIOF)		+= spi_sh_msiof.o
 obj-$(CONFIG_SPI_STMP3XXX)		+= spi_stmp.o
diff -druN linux-libre-2.6.38-gnu/drivers/spi/mpc512x_psc_spi.c linux-libre-2.6.39-gnu/drivers/spi/mpc512x_psc_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/mpc512x_psc_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/mpc512x_psc_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -507,8 +507,7 @@
 	return 0;
 }
 
-static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op,
-					      const struct of_device_id *match)
+static int __devinit mpc512x_psc_spi_of_probe(struct platform_device *op)
 {
 	const u32 *regaddr_p;
 	u64 regaddr64, size64;
@@ -551,7 +550,7 @@
 
 MODULE_DEVICE_TABLE(of, mpc512x_psc_spi_of_match);
 
-static struct of_platform_driver mpc512x_psc_spi_of_driver = {
+static struct platform_driver mpc512x_psc_spi_of_driver = {
 	.probe = mpc512x_psc_spi_of_probe,
 	.remove = __devexit_p(mpc512x_psc_spi_of_remove),
 	.driver = {
@@ -563,13 +562,13 @@
 
 static int __init mpc512x_psc_spi_init(void)
 {
-	return of_register_platform_driver(&mpc512x_psc_spi_of_driver);
+	return platform_driver_register(&mpc512x_psc_spi_of_driver);
 }
 module_init(mpc512x_psc_spi_init);
 
 static void __exit mpc512x_psc_spi_exit(void)
 {
-	of_unregister_platform_driver(&mpc512x_psc_spi_of_driver);
+	platform_driver_unregister(&mpc512x_psc_spi_of_driver);
 }
 module_exit(mpc512x_psc_spi_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/mpc52xx_psc_spi.c linux-libre-2.6.39-gnu/drivers/spi/mpc52xx_psc_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/mpc52xx_psc_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/mpc52xx_psc_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -450,8 +450,7 @@
 	return ret;
 }
 
-static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op,
-	const struct of_device_id *match)
+static int __devinit mpc52xx_psc_spi_of_probe(struct platform_device *op)
 {
 	const u32 *regaddr_p;
 	u64 regaddr64, size64;
@@ -503,7 +502,7 @@
 
 MODULE_DEVICE_TABLE(of, mpc52xx_psc_spi_of_match);
 
-static struct of_platform_driver mpc52xx_psc_spi_of_driver = {
+static struct platform_driver mpc52xx_psc_spi_of_driver = {
 	.probe = mpc52xx_psc_spi_of_probe,
 	.remove = __devexit_p(mpc52xx_psc_spi_of_remove),
 	.driver = {
@@ -515,13 +514,13 @@
 
 static int __init mpc52xx_psc_spi_init(void)
 {
-	return of_register_platform_driver(&mpc52xx_psc_spi_of_driver);
+	return platform_driver_register(&mpc52xx_psc_spi_of_driver);
 }
 module_init(mpc52xx_psc_spi_init);
 
 static void __exit mpc52xx_psc_spi_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_psc_spi_of_driver);
+	platform_driver_unregister(&mpc52xx_psc_spi_of_driver);
 }
 module_exit(mpc52xx_psc_spi_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/mpc52xx_spi.c linux-libre-2.6.39-gnu/drivers/spi/mpc52xx_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/mpc52xx_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/mpc52xx_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -390,8 +390,7 @@
 /*
  * OF Platform Bus Binding
  */
-static int __devinit mpc52xx_spi_probe(struct platform_device *op,
-				       const struct of_device_id *match)
+static int __devinit mpc52xx_spi_probe(struct platform_device *op)
 {
 	struct spi_master *master;
 	struct mpc52xx_spi *ms;
@@ -556,7 +555,7 @@
 };
 MODULE_DEVICE_TABLE(of, mpc52xx_spi_match);
 
-static struct of_platform_driver mpc52xx_spi_of_driver = {
+static struct platform_driver mpc52xx_spi_of_driver = {
 	.driver = {
 		.name = "mpc52xx-spi",
 		.owner = THIS_MODULE,
@@ -568,13 +567,13 @@
 
 static int __init mpc52xx_spi_init(void)
 {
-	return of_register_platform_driver(&mpc52xx_spi_of_driver);
+	return platform_driver_register(&mpc52xx_spi_of_driver);
 }
 module_init(mpc52xx_spi_init);
 
 static void __exit mpc52xx_spi_exit(void)
 {
-	of_unregister_platform_driver(&mpc52xx_spi_of_driver);
+	platform_driver_unregister(&mpc52xx_spi_of_driver);
 }
 module_exit(mpc52xx_spi_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/omap2_mcspi.c linux-libre-2.6.39-gnu/drivers/spi/omap2_mcspi.c
--- linux-libre-2.6.38-gnu/drivers/spi/omap2_mcspi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/omap2_mcspi.c	2011-05-19 00:06:34.000000000 -0400
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2005, 2006 Nokia Corporation
  * Author:	Samuel Ortiz <samuel.ortiz@nokia.com> and
- *		Juha Yrjölä <juha.yrjola@nokia.com>
+ *		Juha Yrjï¿½lï¿½ <juha.yrjola@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
@@ -33,6 +33,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/slab.h>
+#include <linux/pm_runtime.h>
 
 #include <linux/spi/spi.h>
 
@@ -46,7 +47,6 @@
 #define OMAP2_MCSPI_MAX_CTRL 		4
 
 #define OMAP2_MCSPI_REVISION		0x00
-#define OMAP2_MCSPI_SYSCONFIG		0x10
 #define OMAP2_MCSPI_SYSSTATUS		0x14
 #define OMAP2_MCSPI_IRQSTATUS		0x18
 #define OMAP2_MCSPI_IRQENABLE		0x1c
@@ -63,13 +63,6 @@
 
 /* per-register bitmasks: */
 
-#define OMAP2_MCSPI_SYSCONFIG_SMARTIDLE	BIT(4)
-#define OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP	BIT(2)
-#define OMAP2_MCSPI_SYSCONFIG_AUTOIDLE	BIT(0)
-#define OMAP2_MCSPI_SYSCONFIG_SOFTRESET	BIT(1)
-
-#define OMAP2_MCSPI_SYSSTATUS_RESETDONE	BIT(0)
-
 #define OMAP2_MCSPI_MODULCTRL_SINGLE	BIT(0)
 #define OMAP2_MCSPI_MODULCTRL_MS	BIT(2)
 #define OMAP2_MCSPI_MODULCTRL_STEST	BIT(3)
@@ -122,13 +115,12 @@
 	spinlock_t		lock;
 	struct list_head	msg_queue;
 	struct spi_master	*master;
-	struct clk		*ick;
-	struct clk		*fck;
 	/* Virtual base address of the controller */
 	void __iomem		*base;
 	unsigned long		phys;
 	/* SPI1 has 4 channels, while SPI2 has 2 */
 	struct omap2_mcspi_dma	*dma_channels;
+	struct  device		*dev;
 };
 
 struct omap2_mcspi_cs {
@@ -144,7 +136,6 @@
  * corresponding registers are modified.
  */
 struct omap2_mcspi_regs {
-	u32 sysconfig;
 	u32 modulctrl;
 	u32 wakeupenable;
 	struct list_head cs;
@@ -268,9 +259,6 @@
 	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_MODULCTRL,
 			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].modulctrl);
 
-	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_SYSCONFIG,
-			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].sysconfig);
-
 	mcspi_write_reg(spi_cntrl, OMAP2_MCSPI_WAKEUPENABLE,
 			omap2_mcspi_ctx[spi_cntrl->bus_num - 1].wakeupenable);
 
@@ -280,20 +268,12 @@
 }
 static void omap2_mcspi_disable_clocks(struct omap2_mcspi *mcspi)
 {
-	clk_disable(mcspi->ick);
-	clk_disable(mcspi->fck);
+	pm_runtime_put_sync(mcspi->dev);
 }
 
 static int omap2_mcspi_enable_clocks(struct omap2_mcspi *mcspi)
 {
-	if (clk_enable(mcspi->ick))
-		return -ENODEV;
-	if (clk_enable(mcspi->fck))
-		return -ENODEV;
-
-	omap2_mcspi_restore_ctx(mcspi);
-
-	return 0;
+	return pm_runtime_get_sync(mcspi->dev);
 }
 
 static int mcspi_wait_for_reg_bit(void __iomem *reg, unsigned long bit)
@@ -487,6 +467,9 @@
 	rx_reg		= base + OMAP2_MCSPI_RX0;
 	chstat_reg	= base + OMAP2_MCSPI_CHSTAT0;
 
+	if (c < (word_len>>3))
+		return 0;
+
 	if (word_len <= 8) {
 		u8		*rx;
 		const u8	*tx;
@@ -581,7 +564,7 @@
 				dev_vdbg(&spi->dev, "read-%d %04x\n",
 						word_len, *(rx - 1));
 			}
-		} while (c);
+		} while (c >= 2);
 	} else if (word_len <= 32) {
 		u32		*rx;
 		const u32	*tx;
@@ -628,7 +611,7 @@
 				dev_vdbg(&spi->dev, "read-%d %08x\n",
 						word_len, *(rx - 1));
 			}
-		} while (c);
+		} while (c >= 4);
 	}
 
 	/* for TX_ONLY mode, be sure all words have shifted out */
@@ -651,6 +634,17 @@
 	return count - c;
 }
 
+static u32 omap2_mcspi_calc_divisor(u32 speed_hz)
+{
+	u32 div;
+
+	for (div = 0; div < 15; div++)
+		if (speed_hz >= (OMAP2_MCSPI_MAX_FREQ >> div))
+			return div;
+
+	return 15;
+}
+
 /* called only when no transfer is active to this device */
 static int omap2_mcspi_setup_transfer(struct spi_device *spi,
 		struct spi_transfer *t)
@@ -673,12 +667,8 @@
 	if (t && t->speed_hz)
 		speed_hz = t->speed_hz;
 
-	if (speed_hz) {
-		while (div <= 15 && (OMAP2_MCSPI_MAX_FREQ / (1 << div))
-					> speed_hz)
-			div++;
-	} else
-		div = 15;
+	speed_hz = min_t(u32, speed_hz, OMAP2_MCSPI_MAX_FREQ);
+	div = omap2_mcspi_calc_divisor(speed_hz);
 
 	l = mcspi_cached_chconf0(spi);
 
@@ -715,7 +705,7 @@
 	mcspi_write_chconf0(spi, l);
 
 	dev_dbg(&spi->dev, "setup: speed %d, sample %s edge, clk %s\n",
-			OMAP2_MCSPI_MAX_FREQ / (1 << div),
+			OMAP2_MCSPI_MAX_FREQ >> div,
 			(spi->mode & SPI_CPHA) ? "trailing" : "leading",
 			(spi->mode & SPI_CPOL) ? "inverted" : "normal");
 
@@ -819,8 +809,9 @@
 			return ret;
 	}
 
-	if (omap2_mcspi_enable_clocks(mcspi))
-		return -ENODEV;
+	ret = omap2_mcspi_enable_clocks(mcspi);
+	if (ret < 0)
+		return ret;
 
 	ret = omap2_mcspi_setup_transfer(spi, NULL);
 	omap2_mcspi_disable_clocks(mcspi);
@@ -863,10 +854,11 @@
 	struct omap2_mcspi	*mcspi;
 
 	mcspi = container_of(work, struct omap2_mcspi, work);
-	spin_lock_irq(&mcspi->lock);
 
-	if (omap2_mcspi_enable_clocks(mcspi))
-		goto out;
+	if (omap2_mcspi_enable_clocks(mcspi) < 0)
+		return;
+
+	spin_lock_irq(&mcspi->lock);
 
 	/* We only enable one channel at a time -- the one whose message is
 	 * at the head of the queue -- although this controller would gladly
@@ -979,10 +971,9 @@
 		spin_lock_irq(&mcspi->lock);
 	}
 
-	omap2_mcspi_disable_clocks(mcspi);
-
-out:
 	spin_unlock_irq(&mcspi->lock);
+
+	omap2_mcspi_disable_clocks(mcspi);
 }
 
 static int omap2_mcspi_transfer(struct spi_device *spi, struct spi_message *m)
@@ -1015,10 +1006,10 @@
 					t->bits_per_word);
 			return -EINVAL;
 		}
-		if (t->speed_hz && t->speed_hz < OMAP2_MCSPI_MAX_FREQ/(1<<16)) {
-			dev_dbg(&spi->dev, "%d Hz max exceeds %d\n",
-					t->speed_hz,
-					OMAP2_MCSPI_MAX_FREQ/(1<<16));
+		if (t->speed_hz && t->speed_hz < (OMAP2_MCSPI_MAX_FREQ >> 15)) {
+			dev_dbg(&spi->dev, "speed_hz %d below minimum %d Hz\n",
+				t->speed_hz,
+				OMAP2_MCSPI_MAX_FREQ >> 15);
 			return -EINVAL;
 		}
 
@@ -1058,25 +1049,15 @@
 	return 0;
 }
 
-static int __init omap2_mcspi_reset(struct omap2_mcspi *mcspi)
+static int __init omap2_mcspi_master_setup(struct omap2_mcspi *mcspi)
 {
 	struct spi_master	*master = mcspi->master;
 	u32			tmp;
+	int ret = 0;
 
-	if (omap2_mcspi_enable_clocks(mcspi))
-		return -1;
-
-	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG,
-			OMAP2_MCSPI_SYSCONFIG_SOFTRESET);
-	do {
-		tmp = mcspi_read_reg(master, OMAP2_MCSPI_SYSSTATUS);
-	} while (!(tmp & OMAP2_MCSPI_SYSSTATUS_RESETDONE));
-
-	tmp = OMAP2_MCSPI_SYSCONFIG_AUTOIDLE |
-		OMAP2_MCSPI_SYSCONFIG_ENAWAKEUP |
-		OMAP2_MCSPI_SYSCONFIG_SMARTIDLE;
-	mcspi_write_reg(master, OMAP2_MCSPI_SYSCONFIG, tmp);
-	omap2_mcspi_ctx[master->bus_num - 1].sysconfig = tmp;
+	ret = omap2_mcspi_enable_clocks(mcspi);
+	if (ret < 0)
+		return ret;
 
 	tmp = OMAP2_MCSPI_WAKEUPENABLE_WKEN;
 	mcspi_write_reg(master, OMAP2_MCSPI_WAKEUPENABLE, tmp);
@@ -1087,91 +1068,26 @@
 	return 0;
 }
 
-static u8 __initdata spi1_rxdma_id [] = {
-	OMAP24XX_DMA_SPI1_RX0,
-	OMAP24XX_DMA_SPI1_RX1,
-	OMAP24XX_DMA_SPI1_RX2,
-	OMAP24XX_DMA_SPI1_RX3,
-};
-
-static u8 __initdata spi1_txdma_id [] = {
-	OMAP24XX_DMA_SPI1_TX0,
-	OMAP24XX_DMA_SPI1_TX1,
-	OMAP24XX_DMA_SPI1_TX2,
-	OMAP24XX_DMA_SPI1_TX3,
-};
-
-static u8 __initdata spi2_rxdma_id[] = {
-	OMAP24XX_DMA_SPI2_RX0,
-	OMAP24XX_DMA_SPI2_RX1,
-};
-
-static u8 __initdata spi2_txdma_id[] = {
-	OMAP24XX_DMA_SPI2_TX0,
-	OMAP24XX_DMA_SPI2_TX1,
-};
-
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \
-	|| defined(CONFIG_ARCH_OMAP4)
-static u8 __initdata spi3_rxdma_id[] = {
-	OMAP24XX_DMA_SPI3_RX0,
-	OMAP24XX_DMA_SPI3_RX1,
-};
+static int omap_mcspi_runtime_resume(struct device *dev)
+{
+	struct omap2_mcspi	*mcspi;
+	struct spi_master	*master;
 
-static u8 __initdata spi3_txdma_id[] = {
-	OMAP24XX_DMA_SPI3_TX0,
-	OMAP24XX_DMA_SPI3_TX1,
-};
-#endif
+	master = dev_get_drvdata(dev);
+	mcspi = spi_master_get_devdata(master);
+	omap2_mcspi_restore_ctx(mcspi);
 
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-static u8 __initdata spi4_rxdma_id[] = {
-	OMAP34XX_DMA_SPI4_RX0,
-};
+	return 0;
+}
 
-static u8 __initdata spi4_txdma_id[] = {
-	OMAP34XX_DMA_SPI4_TX0,
-};
-#endif
 
 static int __init omap2_mcspi_probe(struct platform_device *pdev)
 {
 	struct spi_master	*master;
+	struct omap2_mcspi_platform_config *pdata = pdev->dev.platform_data;
 	struct omap2_mcspi	*mcspi;
 	struct resource		*r;
 	int			status = 0, i;
-	const u8		*rxdma_id, *txdma_id;
-	unsigned		num_chipselect;
-
-	switch (pdev->id) {
-	case 1:
-		rxdma_id = spi1_rxdma_id;
-		txdma_id = spi1_txdma_id;
-		num_chipselect = 4;
-		break;
-	case 2:
-		rxdma_id = spi2_rxdma_id;
-		txdma_id = spi2_txdma_id;
-		num_chipselect = 2;
-		break;
-#if defined(CONFIG_ARCH_OMAP2430) || defined(CONFIG_ARCH_OMAP3) \
-	|| defined(CONFIG_ARCH_OMAP4)
-	case 3:
-		rxdma_id = spi3_rxdma_id;
-		txdma_id = spi3_txdma_id;
-		num_chipselect = 2;
-		break;
-#endif
-#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4)
-	case 4:
-		rxdma_id = spi4_rxdma_id;
-		txdma_id = spi4_txdma_id;
-		num_chipselect = 1;
-		break;
-#endif
-	default:
-		return -EINVAL;
-	}
 
 	master = spi_alloc_master(&pdev->dev, sizeof *mcspi);
 	if (master == NULL) {
@@ -1188,7 +1104,7 @@
 	master->setup = omap2_mcspi_setup;
 	master->transfer = omap2_mcspi_transfer;
 	master->cleanup = omap2_mcspi_cleanup;
-	master->num_chipselect = num_chipselect;
+	master->num_chipselect = pdata->num_cs;
 
 	dev_set_drvdata(&pdev->dev, master);
 
@@ -1206,49 +1122,62 @@
 		goto err1;
 	}
 
+	r->start += pdata->regs_offset;
+	r->end += pdata->regs_offset;
 	mcspi->phys = r->start;
 	mcspi->base = ioremap(r->start, r->end - r->start + 1);
 	if (!mcspi->base) {
 		dev_dbg(&pdev->dev, "can't ioremap MCSPI\n");
 		status = -ENOMEM;
-		goto err1aa;
+		goto err2;
 	}
 
+	mcspi->dev = &pdev->dev;
 	INIT_WORK(&mcspi->work, omap2_mcspi_work);
 
 	spin_lock_init(&mcspi->lock);
 	INIT_LIST_HEAD(&mcspi->msg_queue);
 	INIT_LIST_HEAD(&omap2_mcspi_ctx[master->bus_num - 1].cs);
 
-	mcspi->ick = clk_get(&pdev->dev, "ick");
-	if (IS_ERR(mcspi->ick)) {
-		dev_dbg(&pdev->dev, "can't get mcspi_ick\n");
-		status = PTR_ERR(mcspi->ick);
-		goto err1a;
-	}
-	mcspi->fck = clk_get(&pdev->dev, "fck");
-	if (IS_ERR(mcspi->fck)) {
-		dev_dbg(&pdev->dev, "can't get mcspi_fck\n");
-		status = PTR_ERR(mcspi->fck);
-		goto err2;
-	}
-
 	mcspi->dma_channels = kcalloc(master->num_chipselect,
 			sizeof(struct omap2_mcspi_dma),
 			GFP_KERNEL);
 
 	if (mcspi->dma_channels == NULL)
-		goto err3;
+		goto err2;
+
+	for (i = 0; i < master->num_chipselect; i++) {
+		char dma_ch_name[14];
+		struct resource *dma_res;
+
+		sprintf(dma_ch_name, "rx%d", i);
+		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+							dma_ch_name);
+		if (!dma_res) {
+			dev_dbg(&pdev->dev, "cannot get DMA RX channel\n");
+			status = -ENODEV;
+			break;
+		}
 
-	for (i = 0; i < num_chipselect; i++) {
 		mcspi->dma_channels[i].dma_rx_channel = -1;
-		mcspi->dma_channels[i].dma_rx_sync_dev = rxdma_id[i];
+		mcspi->dma_channels[i].dma_rx_sync_dev = dma_res->start;
+		sprintf(dma_ch_name, "tx%d", i);
+		dma_res = platform_get_resource_byname(pdev, IORESOURCE_DMA,
+							dma_ch_name);
+		if (!dma_res) {
+			dev_dbg(&pdev->dev, "cannot get DMA TX channel\n");
+			status = -ENODEV;
+			break;
+		}
+
 		mcspi->dma_channels[i].dma_tx_channel = -1;
-		mcspi->dma_channels[i].dma_tx_sync_dev = txdma_id[i];
+		mcspi->dma_channels[i].dma_tx_sync_dev = dma_res->start;
 	}
 
-	if (omap2_mcspi_reset(mcspi) < 0)
-		goto err4;
+	pm_runtime_enable(&pdev->dev);
+
+	if (status || omap2_mcspi_master_setup(mcspi) < 0)
+		goto err3;
 
 	status = spi_register_master(master);
 	if (status < 0)
@@ -1257,17 +1186,13 @@
 	return status;
 
 err4:
-	kfree(mcspi->dma_channels);
+	spi_master_put(master);
 err3:
-	clk_put(mcspi->fck);
+	kfree(mcspi->dma_channels);
 err2:
-	clk_put(mcspi->ick);
-err1a:
-	iounmap(mcspi->base);
-err1aa:
 	release_mem_region(r->start, (r->end - r->start) + 1);
+	iounmap(mcspi->base);
 err1:
-	spi_master_put(master);
 	return status;
 }
 
@@ -1283,9 +1208,7 @@
 	mcspi = spi_master_get_devdata(master);
 	dma_channels = mcspi->dma_channels;
 
-	clk_put(mcspi->fck);
-	clk_put(mcspi->ick);
-
+	omap2_mcspi_disable_clocks(mcspi);
 	r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	release_mem_region(r->start, (r->end - r->start) + 1);
 
@@ -1336,6 +1259,7 @@
 
 static const struct dev_pm_ops omap2_mcspi_pm_ops = {
 	.resume = omap2_mcspi_resume,
+	.runtime_resume	= omap_mcspi_runtime_resume,
 };
 
 static struct platform_driver omap2_mcspi_driver = {
diff -druN linux-libre-2.6.38-gnu/drivers/spi/pxa2xx_spi.c linux-libre-2.6.39-gnu/drivers/spi/pxa2xx_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/pxa2xx_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/pxa2xx_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -700,7 +700,7 @@
 	if (!pxa25x_ssp_comp(drv_data))
 		write_SSTO(0, reg);
 
-	/* Update total byte transfered return count actual bytes read */
+	/* Update total byte transferred return count actual bytes read */
 	drv_data->cur_msg->actual_length += drv_data->len -
 				(drv_data->rx_end - drv_data->rx);
 
@@ -759,7 +759,7 @@
 
 		/*
 		 * PXA25x_SSP has no timeout, set up rx threshould for the
-		 * remaing RX bytes.
+		 * remaining RX bytes.
 		 */
 		if (pxa25x_ssp_comp(drv_data)) {
 
@@ -1493,7 +1493,7 @@
 	 * execution path (pump_messages) would be required to call wake_up or
 	 * friends on every SPI message. Do this instead */
 	drv_data->run = QUEUE_STOPPED;
-	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+	while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 		msleep(10);
 		spin_lock_irqsave(&drv_data->lock, flags);
@@ -1557,9 +1557,7 @@
 	drv_data->ssp = ssp;
 
 	master->dev.parent = &pdev->dev;
-#ifdef CONFIG_OF
 	master->dev.of_node = pdev->dev.of_node;
-#endif
 	/* the spi->mode bits understood by this driver: */
 	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/pxa2xx_spi_pci.c linux-libre-2.6.39-gnu/drivers/spi/pxa2xx_spi_pci.c
--- linux-libre-2.6.38-gnu/drivers/spi/pxa2xx_spi_pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/pxa2xx_spi_pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -89,9 +89,7 @@
 		goto err_nomem;
 
 	pdev->dev.parent = &dev->dev;
-#ifdef CONFIG_OF
 	pdev->dev.of_node = dev->dev.of_node;
-#endif
 	ssp = &spi_info->ssp;
 	ssp->phys_base = pci_resource_start(dev, 0);
 	ssp->mmio_base = ioremap(phys_beg, phys_len);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_altera.c linux-libre-2.6.39-gnu/drivers/spi/spi_altera.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_altera.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_altera.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,339 @@
+/*
+ * Altera SPI driver
+ *
+ * Copyright (C) 2008 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on spi_s3c24xx.c, which is:
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/io.h>
+#include <linux/of.h>
+
+#define DRV_NAME "spi_altera"
+
+#define ALTERA_SPI_RXDATA	0
+#define ALTERA_SPI_TXDATA	4
+#define ALTERA_SPI_STATUS	8
+#define ALTERA_SPI_CONTROL	12
+#define ALTERA_SPI_SLAVE_SEL	20
+
+#define ALTERA_SPI_STATUS_ROE_MSK	0x8
+#define ALTERA_SPI_STATUS_TOE_MSK	0x10
+#define ALTERA_SPI_STATUS_TMT_MSK	0x20
+#define ALTERA_SPI_STATUS_TRDY_MSK	0x40
+#define ALTERA_SPI_STATUS_RRDY_MSK	0x80
+#define ALTERA_SPI_STATUS_E_MSK		0x100
+
+#define ALTERA_SPI_CONTROL_IROE_MSK	0x8
+#define ALTERA_SPI_CONTROL_ITOE_MSK	0x10
+#define ALTERA_SPI_CONTROL_ITRDY_MSK	0x40
+#define ALTERA_SPI_CONTROL_IRRDY_MSK	0x80
+#define ALTERA_SPI_CONTROL_IE_MSK	0x100
+#define ALTERA_SPI_CONTROL_SSO_MSK	0x400
+
+struct altera_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem *base;
+	int irq;
+	int len;
+	int count;
+	int bytes_per_word;
+	unsigned long imr;
+
+	/* data buffers */
+	const unsigned char *tx;
+	unsigned char *rx;
+};
+
+static inline struct altera_spi *altera_spi_to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static void altera_spi_chipsel(struct spi_device *spi, int value)
+{
+	struct altera_spi *hw = altera_spi_to_hw(spi);
+
+	if (spi->mode & SPI_CS_HIGH) {
+		switch (value) {
+		case BITBANG_CS_INACTIVE:
+			writel(1 << spi->chip_select,
+			       hw->base + ALTERA_SPI_SLAVE_SEL);
+			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+
+		case BITBANG_CS_ACTIVE:
+			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			writel(0, hw->base + ALTERA_SPI_SLAVE_SEL);
+			break;
+		}
+	} else {
+		switch (value) {
+		case BITBANG_CS_INACTIVE:
+			hw->imr &= ~ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+
+		case BITBANG_CS_ACTIVE:
+			writel(1 << spi->chip_select,
+			       hw->base + ALTERA_SPI_SLAVE_SEL);
+			hw->imr |= ALTERA_SPI_CONTROL_SSO_MSK;
+			writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+			break;
+		}
+	}
+}
+
+static int altera_spi_setupxfer(struct spi_device *spi, struct spi_transfer *t)
+{
+	return 0;
+}
+
+static int altera_spi_setup(struct spi_device *spi)
+{
+	return 0;
+}
+
+static inline unsigned int hw_txbyte(struct altera_spi *hw, int count)
+{
+	if (hw->tx) {
+		switch (hw->bytes_per_word) {
+		case 1:
+			return hw->tx[count];
+		case 2:
+			return (hw->tx[count * 2]
+				| (hw->tx[count * 2 + 1] << 8));
+		}
+	}
+	return 0;
+}
+
+static int altera_spi_txrx(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct altera_spi *hw = altera_spi_to_hw(spi);
+
+	hw->tx = t->tx_buf;
+	hw->rx = t->rx_buf;
+	hw->count = 0;
+	hw->bytes_per_word = (t->bits_per_word ? : spi->bits_per_word) / 8;
+	hw->len = t->len / hw->bytes_per_word;
+
+	if (hw->irq >= 0) {
+		/* enable receive interrupt */
+		hw->imr |= ALTERA_SPI_CONTROL_IRRDY_MSK;
+		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+
+		/* send the first byte */
+		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
+
+		wait_for_completion(&hw->done);
+		/* disable receive interrupt */
+		hw->imr &= ~ALTERA_SPI_CONTROL_IRRDY_MSK;
+		writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+	} else {
+		/* send the first byte */
+		writel(hw_txbyte(hw, 0), hw->base + ALTERA_SPI_TXDATA);
+
+		while (1) {
+			unsigned int rxd;
+
+			while (!(readl(hw->base + ALTERA_SPI_STATUS) &
+				 ALTERA_SPI_STATUS_RRDY_MSK))
+				cpu_relax();
+
+			rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+			if (hw->rx) {
+				switch (hw->bytes_per_word) {
+				case 1:
+					hw->rx[hw->count] = rxd;
+					break;
+				case 2:
+					hw->rx[hw->count * 2] = rxd;
+					hw->rx[hw->count * 2 + 1] = rxd >> 8;
+					break;
+				}
+			}
+
+			hw->count++;
+
+			if (hw->count < hw->len)
+				writel(hw_txbyte(hw, hw->count),
+				       hw->base + ALTERA_SPI_TXDATA);
+			else
+				break;
+		}
+
+	}
+
+	return hw->count * hw->bytes_per_word;
+}
+
+static irqreturn_t altera_spi_irq(int irq, void *dev)
+{
+	struct altera_spi *hw = dev;
+	unsigned int rxd;
+
+	rxd = readl(hw->base + ALTERA_SPI_RXDATA);
+	if (hw->rx) {
+		switch (hw->bytes_per_word) {
+		case 1:
+			hw->rx[hw->count] = rxd;
+			break;
+		case 2:
+			hw->rx[hw->count * 2] = rxd;
+			hw->rx[hw->count * 2 + 1] = rxd >> 8;
+			break;
+		}
+	}
+
+	hw->count++;
+
+	if (hw->count < hw->len)
+		writel(hw_txbyte(hw, hw->count), hw->base + ALTERA_SPI_TXDATA);
+	else
+		complete(&hw->done);
+
+	return IRQ_HANDLED;
+}
+
+static int __devinit altera_spi_probe(struct platform_device *pdev)
+{
+	struct altera_spi_platform_data *platp = pdev->dev.platform_data;
+	struct altera_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	int err = -ENODEV;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct altera_spi));
+	if (!master)
+		return err;
+
+	/* setup the master state. */
+	master->bus_num = pdev->id;
+	master->num_chipselect = 16;
+	master->mode_bits = SPI_CS_HIGH;
+	master->setup = altera_spi_setup;
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	/* setup the state for the bitbang driver */
+	hw->bitbang.master = spi_master_get(master);
+	if (!hw->bitbang.master)
+		return err;
+	hw->bitbang.setup_transfer = altera_spi_setupxfer;
+	hw->bitbang.chipselect = altera_spi_chipsel;
+	hw->bitbang.txrx_bufs = altera_spi_txrx;
+
+	/* find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     pdev->name))
+		goto exit_busy;
+	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!hw->base)
+		goto exit_busy;
+	/* program defaults into the registers */
+	hw->imr = 0;		/* disable spi interrupts */
+	writel(hw->imr, hw->base + ALTERA_SPI_CONTROL);
+	writel(0, hw->base + ALTERA_SPI_STATUS);	/* clear status reg */
+	if (readl(hw->base + ALTERA_SPI_STATUS) & ALTERA_SPI_STATUS_RRDY_MSK)
+		readl(hw->base + ALTERA_SPI_RXDATA);	/* flush rxdata */
+	/* irq is optional */
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq >= 0) {
+		init_completion(&hw->done);
+		err = devm_request_irq(&pdev->dev, hw->irq, altera_spi_irq, 0,
+				       pdev->name, hw);
+		if (err)
+			goto exit;
+	}
+	/* find platform data */
+	if (!platp)
+		hw->bitbang.master->dev.of_node = pdev->dev.of_node;
+
+	/* register our spi controller */
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err)
+		goto exit;
+	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
+
+	return 0;
+
+exit_busy:
+	err = -EBUSY;
+exit:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return err;
+}
+
+static int __devexit altera_spi_remove(struct platform_device *dev)
+{
+	struct altera_spi *hw = platform_get_drvdata(dev);
+	struct spi_master *master = hw->bitbang.master;
+
+	spi_bitbang_stop(&hw->bitbang);
+	platform_set_drvdata(dev, NULL);
+	spi_master_put(master);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id altera_spi_match[] = {
+	{ .compatible = "ALTR,spi-1.0", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, altera_spi_match);
+#else /* CONFIG_OF */
+#define altera_spi_match NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver altera_spi_driver = {
+	.probe = altera_spi_probe,
+	.remove = __devexit_p(altera_spi_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = NULL,
+		.of_match_table = altera_spi_match,
+	},
+};
+
+static int __init altera_spi_init(void)
+{
+	return platform_driver_register(&altera_spi_driver);
+}
+module_init(altera_spi_init);
+
+static void __exit altera_spi_exit(void)
+{
+	platform_driver_unregister(&altera_spi_driver);
+}
+module_exit(altera_spi_exit);
+
+MODULE_DESCRIPTION("Altera SPI driver");
+MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_bfin5xx.c linux-libre-2.6.39-gnu/drivers/spi/spi_bfin5xx.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_bfin5xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_bfin5xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -425,6 +425,7 @@
 	struct bfin_spi_slave_data *chip = drv_data->cur_chip;
 	struct spi_message *msg = drv_data->cur_msg;
 	int n_bytes = drv_data->n_bytes;
+	int loop = 0;
 
 	/* wait until transfer finished. */
 	while (!(read_STAT(drv_data) & BIT_STAT_RXS))
@@ -435,10 +436,15 @@
 		/* last read */
 		if (drv_data->rx) {
 			dev_dbg(&drv_data->pdev->dev, "last read\n");
-			if (n_bytes == 2)
-				*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-			else if (n_bytes == 1)
-				*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
+			if (n_bytes % 2) {
+				u16 *buf = (u16 *)drv_data->rx;
+				for (loop = 0; loop < n_bytes / 2; loop++)
+					*buf++ = read_RDBR(drv_data);
+			} else {
+				u8 *buf = (u8 *)drv_data->rx;
+				for (loop = 0; loop < n_bytes; loop++)
+					*buf++ = read_RDBR(drv_data);
+			}
 			drv_data->rx += n_bytes;
 		}
 
@@ -458,29 +464,53 @@
 	if (drv_data->rx && drv_data->tx) {
 		/* duplex */
 		dev_dbg(&drv_data->pdev->dev, "duplex: write_TDBR\n");
-		if (drv_data->n_bytes == 2) {
-			*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-			write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		} else if (drv_data->n_bytes == 1) {
-			*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-			write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->rx;
+			u16 *buf2 = (u16 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf2++);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->rx;
+			u8 *buf2 = (u8 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf2++);
+			}
 		}
 	} else if (drv_data->rx) {
 		/* read */
 		dev_dbg(&drv_data->pdev->dev, "read: write_TDBR\n");
-		if (drv_data->n_bytes == 2)
-			*(u16 *) (drv_data->rx) = read_RDBR(drv_data);
-		else if (drv_data->n_bytes == 1)
-			*(u8 *) (drv_data->rx) = read_RDBR(drv_data);
-		write_TDBR(drv_data, chip->idle_tx_val);
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->rx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, chip->idle_tx_val);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->rx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				*buf++ = read_RDBR(drv_data);
+				write_TDBR(drv_data, chip->idle_tx_val);
+			}
+		}
 	} else if (drv_data->tx) {
 		/* write */
 		dev_dbg(&drv_data->pdev->dev, "write: write_TDBR\n");
-		bfin_spi_dummy_read(drv_data);
-		if (drv_data->n_bytes == 2)
-			write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
-		else if (drv_data->n_bytes == 1)
-			write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
+		if (n_bytes % 2) {
+			u16 *buf = (u16 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes / 2; loop++) {
+				read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf++);
+			}
+		} else {
+			u8 *buf = (u8 *)drv_data->tx;
+			for (loop = 0; loop < n_bytes; loop++) {
+				read_RDBR(drv_data);
+				write_TDBR(drv_data, *buf++);
+			}
+		}
 	}
 
 	if (drv_data->tx)
@@ -623,6 +653,7 @@
 		message->state = bfin_spi_next_transfer(drv_data);
 		/* Schedule next transfer tasklet */
 		tasklet_schedule(&drv_data->pump_transfers);
+		return;
 	}
 
 	if (transfer->tx_buf != NULL) {
@@ -651,16 +682,16 @@
 
 	/* Bits per word setup */
 	bits_per_word = transfer->bits_per_word ? : message->spi->bits_per_word;
-	if (bits_per_word == 8) {
-		drv_data->n_bytes = 1;
-		drv_data->len = transfer->len;
-		cr_width = 0;
-		drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
-	} else if (bits_per_word == 16) {
-		drv_data->n_bytes = 2;
+	if ((bits_per_word > 0) && (bits_per_word % 16 == 0)) {
+		drv_data->n_bytes = bits_per_word/8;
 		drv_data->len = (transfer->len) >> 1;
 		cr_width = BIT_CTL_WORDSIZE;
 		drv_data->ops = &bfin_bfin_spi_transfer_ops_u16;
+	} else if ((bits_per_word > 0) && (bits_per_word % 8 == 0)) {
+		drv_data->n_bytes = bits_per_word/8;
+		drv_data->len = transfer->len;
+		cr_width = 0;
+		drv_data->ops = &bfin_bfin_spi_transfer_ops_u8;
 	} else {
 		dev_err(&drv_data->pdev->dev, "transfer: unsupported bits_per_word\n");
 		message->status = -EINVAL;
@@ -815,10 +846,19 @@
 		if (drv_data->tx == NULL)
 			write_TDBR(drv_data, chip->idle_tx_val);
 		else {
-			if (bits_per_word == 8)
-				write_TDBR(drv_data, (*(u8 *) (drv_data->tx)));
-			else
-				write_TDBR(drv_data, (*(u16 *) (drv_data->tx)));
+			int loop;
+			if (bits_per_word % 16 == 0) {
+				u16 *buf = (u16 *)drv_data->tx;
+				for (loop = 0; loop < bits_per_word / 16;
+						loop++) {
+					write_TDBR(drv_data, *buf++);
+				}
+			} else if (bits_per_word % 8 == 0) {
+				u8 *buf = (u8 *)drv_data->tx;
+				for (loop = 0; loop < bits_per_word / 8; loop++)
+					write_TDBR(drv_data, *buf++);
+			}
+
 			drv_data->tx += drv_data->n_bytes;
 		}
 
@@ -865,7 +905,7 @@
 			"IO write error!\n");
 		message->state = ERROR_STATE;
 	} else {
-		/* Update total byte transfered */
+		/* Update total byte transferred */
 		message->actual_length += drv_data->len_in_bytes;
 		/* Move to next transfer of this msg */
 		message->state = bfin_spi_next_transfer(drv_data);
@@ -1031,7 +1071,7 @@
 		chip->ctl_reg &= bfin_ctl_reg;
 	}
 
-	if (spi->bits_per_word != 8 && spi->bits_per_word != 16) {
+	if (spi->bits_per_word % 8) {
 		dev_err(&spi->dev, "%d bits_per_word is not supported\n",
 				spi->bits_per_word);
 		goto error;
@@ -1244,7 +1284,7 @@
 	 * friends on every SPI message. Do this instead
 	 */
 	drv_data->running = false;
-	while (!list_empty(&drv_data->queue) && drv_data->busy && limit--) {
+	while ((!list_empty(&drv_data->queue) || drv_data->busy) && limit--) {
 		spin_unlock_irqrestore(&drv_data->lock, flags);
 		msleep(10);
 		spin_lock_irqsave(&drv_data->lock, flags);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_bitbang.c linux-libre-2.6.39-gnu/drivers/spi/spi_bitbang.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_bitbang.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_bitbang.c	2011-05-19 00:06:34.000000000 -0400
@@ -259,10 +259,6 @@
 	struct spi_bitbang	*bitbang =
 		container_of(work, struct spi_bitbang, work);
 	unsigned long		flags;
-	int			(*setup_transfer)(struct spi_device *,
-					struct spi_transfer *);
-
-	setup_transfer = bitbang->setup_transfer;
 
 	spin_lock_irqsave(&bitbang->lock, flags);
 	bitbang->busy = 1;
@@ -300,11 +296,7 @@
 
 			/* init (-1) or override (1) transfer params */
 			if (do_setup != 0) {
-				if (!setup_transfer) {
-					status = -ENOPROTOOPT;
-					break;
-				}
-				status = setup_transfer(spi, t);
+				status = bitbang->setup_transfer(spi, t);
 				if (status < 0)
 					break;
 				if (do_setup == -1)
@@ -465,6 +457,9 @@
 		}
 	} else if (!bitbang->master->setup)
 		return -EINVAL;
+	if (bitbang->master->transfer == spi_bitbang_transfer &&
+			!bitbang->setup_transfer)
+		return -EINVAL;
 
 	/* this task is the only thing to touch the SPI bits */
 	bitbang->busy = 0;
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi.c linux-libre-2.6.39-gnu/drivers/spi/spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -957,7 +957,7 @@
  * drivers may DMA directly into and out of the message buffers.
  *
  * This call should be used by drivers that require exclusive access to the
- * SPI bus. It has to be preceeded by a spi_bus_lock call. The SPI bus must
+ * SPI bus. It has to be preceded by a spi_bus_lock call. The SPI bus must
  * be released by a spi_bus_unlock call when the exclusive access is over.
  *
  * It returns zero on success, else a negative error code.
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spidev.c linux-libre-2.6.39-gnu/drivers/spi/spidev.c
--- linux-libre-2.6.38-gnu/drivers/spi/spidev.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spidev.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,6 +30,7 @@
 #include <linux/errno.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
+#include <linux/compat.h>
 
 #include <linux/spi/spi.h>
 #include <linux/spi/spidev.h>
@@ -471,6 +472,16 @@
 	return retval;
 }
 
+#ifdef CONFIG_COMPAT
+static long
+spidev_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
+{
+	return spidev_ioctl(filp, cmd, (unsigned long)compat_ptr(arg));
+}
+#else
+#define spidev_compat_ioctl NULL
+#endif /* CONFIG_COMPAT */
+
 static int spidev_open(struct inode *inode, struct file *filp)
 {
 	struct spidev_data	*spidev;
@@ -543,6 +554,7 @@
 	.write =	spidev_write,
 	.read =		spidev_read,
 	.unlocked_ioctl = spidev_ioctl,
+	.compat_ioctl = spidev_compat_ioctl,
 	.open =		spidev_open,
 	.release =	spidev_release,
 	.llseek =	no_llseek,
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_espi.c linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_espi.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_espi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_espi.c	2011-05-19 00:06:34.000000000 -0400
@@ -474,7 +474,7 @@
 	mpc8xxx_spi = spi_master_get_devdata(spi->master);
 	reg_base = mpc8xxx_spi->reg_base;
 
-	hw_mode = cs->hw_mode; /* Save orginal settings */
+	hw_mode = cs->hw_mode; /* Save original settings */
 	cs->hw_mode = mpc8xxx_spi_read_reg(
 			&reg_base->csmode[spi->chip_select]);
 	/* mask out bits we are going to set */
@@ -685,8 +685,7 @@
 	return 0;
 }
 
-static int __devinit of_fsl_espi_probe(struct platform_device *ofdev,
-					const struct of_device_id *ofid)
+static int __devinit of_fsl_espi_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -695,7 +694,7 @@
 	struct resource irq;
 	int ret = -ENOMEM;
 
-	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	ret = of_mpc8xxx_spi_probe(ofdev);
 	if (ret)
 		return ret;
 
@@ -736,7 +735,7 @@
 };
 MODULE_DEVICE_TABLE(of, of_fsl_espi_match);
 
-static struct of_platform_driver fsl_espi_driver = {
+static struct platform_driver fsl_espi_driver = {
 	.driver = {
 		.name = "fsl_espi",
 		.owner = THIS_MODULE,
@@ -748,13 +747,13 @@
 
 static int __init fsl_espi_init(void)
 {
-	return of_register_platform_driver(&fsl_espi_driver);
+	return platform_driver_register(&fsl_espi_driver);
 }
 module_init(fsl_espi_init);
 
 static void __exit fsl_espi_exit(void)
 {
-	of_unregister_platform_driver(&fsl_espi_driver);
+	platform_driver_unregister(&fsl_espi_driver);
 }
 module_exit(fsl_espi_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_lib.c linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_lib.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_lib.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_lib.c	2011-05-19 00:06:34.000000000 -0400
@@ -189,8 +189,7 @@
 	return 0;
 }
 
-int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-					const struct of_device_id *ofid)
+int __devinit of_mpc8xxx_spi_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_lib.h linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_lib.h
--- linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_lib.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_lib.h	2011-05-19 00:06:34.000000000 -0400
@@ -118,7 +118,6 @@
 extern int mpc8xxx_spi_probe(struct device *dev, struct resource *mem,
 		unsigned int irq);
 extern int mpc8xxx_spi_remove(struct device *dev);
-extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev,
-				const struct of_device_id *ofid);
+extern int of_mpc8xxx_spi_probe(struct platform_device *ofdev);
 
 #endif /* __SPI_FSL_LIB_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_spi.c linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_fsl_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_fsl_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -1042,8 +1042,7 @@
 	return 0;
 }
 
-static int __devinit of_fsl_spi_probe(struct platform_device *ofdev,
-					const struct of_device_id *ofid)
+static int __devinit of_fsl_spi_probe(struct platform_device *ofdev)
 {
 	struct device *dev = &ofdev->dev;
 	struct device_node *np = ofdev->dev.of_node;
@@ -1052,7 +1051,7 @@
 	struct resource irq;
 	int ret = -ENOMEM;
 
-	ret = of_mpc8xxx_spi_probe(ofdev, ofid);
+	ret = of_mpc8xxx_spi_probe(ofdev);
 	if (ret)
 		return ret;
 
@@ -1100,7 +1099,7 @@
 };
 MODULE_DEVICE_TABLE(of, of_fsl_spi_match);
 
-static struct of_platform_driver of_fsl_spi_driver = {
+static struct platform_driver of_fsl_spi_driver = {
 	.driver = {
 		.name = "fsl_spi",
 		.owner = THIS_MODULE,
@@ -1177,13 +1176,13 @@
 static int __init fsl_spi_init(void)
 {
 	legacy_driver_register();
-	return of_register_platform_driver(&of_fsl_spi_driver);
+	return platform_driver_register(&of_fsl_spi_driver);
 }
 module_init(fsl_spi_init);
 
 static void __exit fsl_spi_exit(void)
 {
-	of_unregister_platform_driver(&of_fsl_spi_driver);
+	platform_driver_unregister(&of_fsl_spi_driver);
 	legacy_driver_unregister();
 }
 module_exit(fsl_spi_exit);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_imx.c linux-libre-2.6.39-gnu/drivers/spi/spi_imx.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_imx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_imx.c	2011-05-19 00:06:34.000000000 -0400
@@ -174,7 +174,7 @@
 #define SPI_IMX2_3_CTRL		0x08
 #define SPI_IMX2_3_CTRL_ENABLE		(1 <<  0)
 #define SPI_IMX2_3_CTRL_XCH		(1 <<  2)
-#define SPI_IMX2_3_CTRL_MODE(cs)	(1 << ((cs) +  4))
+#define SPI_IMX2_3_CTRL_MODE_MASK	(0xf << 4)
 #define SPI_IMX2_3_CTRL_POSTDIV_OFFSET	8
 #define SPI_IMX2_3_CTRL_PREDIV_OFFSET	12
 #define SPI_IMX2_3_CTRL_CS(cs)		((cs) << 18)
@@ -253,8 +253,14 @@
 {
 	u32 ctrl = SPI_IMX2_3_CTRL_ENABLE, cfg = 0;
 
-	/* set master mode */
-	ctrl |= SPI_IMX2_3_CTRL_MODE(config->cs);
+	/*
+	 * The hardware seems to have a race condition when changing modes. The
+	 * current assumption is that the selection of the channel arrives
+	 * earlier in the hardware than the mode bits when they are written at
+	 * the same time.
+	 * So set master mode for all channels as we do not support slave mode.
+	 */
+	ctrl |= SPI_IMX2_3_CTRL_MODE_MASK;
 
 	/* set clock speed */
 	ctrl |= spi_imx2_3_clkdiv(spi_imx->spi_clk, config->speed_hz);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_oc_tiny.c linux-libre-2.6.39-gnu/drivers/spi/spi_oc_tiny.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_oc_tiny.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_oc_tiny.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,425 @@
+/*
+ * OpenCores tiny SPI master driver
+ *
+ * http://opencores.org/project,tiny_spi
+ *
+ * Copyright (C) 2011 Thomas Chou <thomas@wytron.com.tw>
+ *
+ * Based on spi_s3c24xx.c, which is:
+ * Copyright (c) 2006 Ben Dooks
+ * Copyright (c) 2006 Simtec Electronics
+ *	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.
+ */
+
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/spi/spi_bitbang.h>
+#include <linux/spi/spi_oc_tiny.h>
+#include <linux/io.h>
+#include <linux/gpio.h>
+#include <linux/of.h>
+
+#define DRV_NAME "spi_oc_tiny"
+
+#define TINY_SPI_RXDATA 0
+#define TINY_SPI_TXDATA 4
+#define TINY_SPI_STATUS 8
+#define TINY_SPI_CONTROL 12
+#define TINY_SPI_BAUD 16
+
+#define TINY_SPI_STATUS_TXE 0x1
+#define TINY_SPI_STATUS_TXR 0x2
+
+struct tiny_spi {
+	/* bitbang has to be first */
+	struct spi_bitbang bitbang;
+	struct completion done;
+
+	void __iomem *base;
+	int irq;
+	unsigned int freq;
+	unsigned int baudwidth;
+	unsigned int baud;
+	unsigned int speed_hz;
+	unsigned int mode;
+	unsigned int len;
+	unsigned int txc, rxc;
+	const u8 *txp;
+	u8 *rxp;
+	unsigned int gpio_cs_count;
+	int *gpio_cs;
+};
+
+static inline struct tiny_spi *tiny_spi_to_hw(struct spi_device *sdev)
+{
+	return spi_master_get_devdata(sdev->master);
+}
+
+static unsigned int tiny_spi_baud(struct spi_device *spi, unsigned int hz)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	return min(DIV_ROUND_UP(hw->freq, hz * 2), (1U << hw->baudwidth)) - 1;
+}
+
+static void tiny_spi_chipselect(struct spi_device *spi, int is_active)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	if (hw->gpio_cs_count) {
+		gpio_set_value(hw->gpio_cs[spi->chip_select],
+			(spi->mode & SPI_CS_HIGH) ? is_active : !is_active);
+	}
+}
+
+static int tiny_spi_setup_transfer(struct spi_device *spi,
+				   struct spi_transfer *t)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+	unsigned int baud = hw->baud;
+
+	if (t) {
+		if (t->speed_hz && t->speed_hz != hw->speed_hz)
+			baud = tiny_spi_baud(spi, t->speed_hz);
+	}
+	writel(baud, hw->base + TINY_SPI_BAUD);
+	writel(hw->mode, hw->base + TINY_SPI_CONTROL);
+	return 0;
+}
+
+static int tiny_spi_setup(struct spi_device *spi)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+
+	if (spi->max_speed_hz != hw->speed_hz) {
+		hw->speed_hz = spi->max_speed_hz;
+		hw->baud = tiny_spi_baud(spi, hw->speed_hz);
+	}
+	hw->mode = spi->mode & (SPI_CPOL | SPI_CPHA);
+	return 0;
+}
+
+static inline void tiny_spi_wait_txr(struct tiny_spi *hw)
+{
+	while (!(readb(hw->base + TINY_SPI_STATUS) &
+		 TINY_SPI_STATUS_TXR))
+		cpu_relax();
+}
+
+static inline void tiny_spi_wait_txe(struct tiny_spi *hw)
+{
+	while (!(readb(hw->base + TINY_SPI_STATUS) &
+		 TINY_SPI_STATUS_TXE))
+		cpu_relax();
+}
+
+static int tiny_spi_txrx_bufs(struct spi_device *spi, struct spi_transfer *t)
+{
+	struct tiny_spi *hw = tiny_spi_to_hw(spi);
+	const u8 *txp = t->tx_buf;
+	u8 *rxp = t->rx_buf;
+	unsigned int i;
+
+	if (hw->irq >= 0) {
+		/* use intrrupt driven data transfer */
+		hw->len = t->len;
+		hw->txp = t->tx_buf;
+		hw->rxp = t->rx_buf;
+		hw->txc = 0;
+		hw->rxc = 0;
+
+		/* send the first byte */
+		if (t->len > 1) {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXR, hw->base + TINY_SPI_STATUS);
+		} else {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXE, hw->base + TINY_SPI_STATUS);
+		}
+
+		wait_for_completion(&hw->done);
+	} else if (txp && rxp) {
+		/* we need to tighten the transfer loop */
+		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 rx, tx = *txp++;
+				tiny_spi_wait_txr(hw);
+				rx = readb(hw->base + TINY_SPI_TXDATA);
+				writeb(tx, hw->base + TINY_SPI_TXDATA);
+				*rxp++ = rx;
+			}
+			tiny_spi_wait_txr(hw);
+			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		}
+		tiny_spi_wait_txe(hw);
+		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+	} else if (rxp) {
+		writeb(0, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(0,
+			       hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 rx;
+				tiny_spi_wait_txr(hw);
+				rx = readb(hw->base + TINY_SPI_TXDATA);
+				writeb(0, hw->base + TINY_SPI_TXDATA);
+				*rxp++ = rx;
+			}
+			tiny_spi_wait_txr(hw);
+			*rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		}
+		tiny_spi_wait_txe(hw);
+		*rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+	} else if (txp) {
+		writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(*txp++, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				u8 tx = *txp++;
+				tiny_spi_wait_txr(hw);
+				writeb(tx, hw->base + TINY_SPI_TXDATA);
+			}
+		}
+		tiny_spi_wait_txe(hw);
+	} else {
+		writeb(0, hw->base + TINY_SPI_TXDATA);
+		if (t->len > 1) {
+			writeb(0, hw->base + TINY_SPI_TXDATA);
+			for (i = 2; i < t->len; i++) {
+				tiny_spi_wait_txr(hw);
+				writeb(0, hw->base + TINY_SPI_TXDATA);
+			}
+		}
+		tiny_spi_wait_txe(hw);
+	}
+	return t->len;
+}
+
+static irqreturn_t tiny_spi_irq(int irq, void *dev)
+{
+	struct tiny_spi *hw = dev;
+
+	writeb(0, hw->base + TINY_SPI_STATUS);
+	if (hw->rxc + 1 == hw->len) {
+		if (hw->rxp)
+			*hw->rxp++ = readb(hw->base + TINY_SPI_RXDATA);
+		hw->rxc++;
+		complete(&hw->done);
+	} else {
+		if (hw->rxp)
+			*hw->rxp++ = readb(hw->base + TINY_SPI_TXDATA);
+		hw->rxc++;
+		if (hw->txc < hw->len) {
+			writeb(hw->txp ? *hw->txp++ : 0,
+			       hw->base + TINY_SPI_TXDATA);
+			hw->txc++;
+			writeb(TINY_SPI_STATUS_TXR,
+			       hw->base + TINY_SPI_STATUS);
+		} else {
+			writeb(TINY_SPI_STATUS_TXE,
+			       hw->base + TINY_SPI_STATUS);
+		}
+	}
+	return IRQ_HANDLED;
+}
+
+#ifdef CONFIG_OF
+#include <linux/of_gpio.h>
+
+static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+{
+	struct tiny_spi *hw = platform_get_drvdata(pdev);
+	struct device_node *np = pdev->dev.of_node;
+	unsigned int i;
+	const __be32 *val;
+	int len;
+
+	if (!np)
+		return 0;
+	hw->gpio_cs_count = of_gpio_count(np);
+	if (hw->gpio_cs_count) {
+		hw->gpio_cs = devm_kzalloc(&pdev->dev,
+				hw->gpio_cs_count * sizeof(unsigned int),
+				GFP_KERNEL);
+		if (!hw->gpio_cs)
+			return -ENOMEM;
+	}
+	for (i = 0; i < hw->gpio_cs_count; i++) {
+		hw->gpio_cs[i] = of_get_gpio_flags(np, i, NULL);
+		if (hw->gpio_cs[i] < 0)
+			return -ENODEV;
+	}
+	hw->bitbang.master->dev.of_node = pdev->dev.of_node;
+	val = of_get_property(pdev->dev.of_node,
+			      "clock-frequency", &len);
+	if (val && len >= sizeof(__be32))
+		hw->freq = be32_to_cpup(val);
+	val = of_get_property(pdev->dev.of_node, "baud-width", &len);
+	if (val && len >= sizeof(__be32))
+		hw->baudwidth = be32_to_cpup(val);
+	return 0;
+}
+#else /* !CONFIG_OF */
+static int __devinit tiny_spi_of_probe(struct platform_device *pdev)
+{
+	return 0;
+}
+#endif /* CONFIG_OF */
+
+static int __devinit tiny_spi_probe(struct platform_device *pdev)
+{
+	struct tiny_spi_platform_data *platp = pdev->dev.platform_data;
+	struct tiny_spi *hw;
+	struct spi_master *master;
+	struct resource *res;
+	unsigned int i;
+	int err = -ENODEV;
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct tiny_spi));
+	if (!master)
+		return err;
+
+	/* setup the master state. */
+	master->bus_num = pdev->id;
+	master->num_chipselect = 255;
+	master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
+	master->setup = tiny_spi_setup;
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	/* setup the state for the bitbang driver */
+	hw->bitbang.master = spi_master_get(master);
+	if (!hw->bitbang.master)
+		return err;
+	hw->bitbang.setup_transfer = tiny_spi_setup_transfer;
+	hw->bitbang.chipselect = tiny_spi_chipselect;
+	hw->bitbang.txrx_bufs = tiny_spi_txrx_bufs;
+
+	/* find and map our resources */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		goto exit_busy;
+	if (!devm_request_mem_region(&pdev->dev, res->start, resource_size(res),
+				     pdev->name))
+		goto exit_busy;
+	hw->base = devm_ioremap_nocache(&pdev->dev, res->start,
+					resource_size(res));
+	if (!hw->base)
+		goto exit_busy;
+	/* irq is optional */
+	hw->irq = platform_get_irq(pdev, 0);
+	if (hw->irq >= 0) {
+		init_completion(&hw->done);
+		err = devm_request_irq(&pdev->dev, hw->irq, tiny_spi_irq, 0,
+				       pdev->name, hw);
+		if (err)
+			goto exit;
+	}
+	/* find platform data */
+	if (platp) {
+		hw->gpio_cs_count = platp->gpio_cs_count;
+		hw->gpio_cs = platp->gpio_cs;
+		if (platp->gpio_cs_count && !platp->gpio_cs)
+			goto exit_busy;
+		hw->freq = platp->freq;
+		hw->baudwidth = platp->baudwidth;
+	} else {
+		err = tiny_spi_of_probe(pdev);
+		if (err)
+			goto exit;
+	}
+	for (i = 0; i < hw->gpio_cs_count; i++) {
+		err = gpio_request(hw->gpio_cs[i], dev_name(&pdev->dev));
+		if (err)
+			goto exit_gpio;
+		gpio_direction_output(hw->gpio_cs[i], 1);
+	}
+	hw->bitbang.master->num_chipselect = max(1U, hw->gpio_cs_count);
+
+	/* register our spi controller */
+	err = spi_bitbang_start(&hw->bitbang);
+	if (err)
+		goto exit;
+	dev_info(&pdev->dev, "base %p, irq %d\n", hw->base, hw->irq);
+
+	return 0;
+
+exit_gpio:
+	while (i-- > 0)
+		gpio_free(hw->gpio_cs[i]);
+exit_busy:
+	err = -EBUSY;
+exit:
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return err;
+}
+
+static int __devexit tiny_spi_remove(struct platform_device *pdev)
+{
+	struct tiny_spi *hw = platform_get_drvdata(pdev);
+	struct spi_master *master = hw->bitbang.master;
+	unsigned int i;
+
+	spi_bitbang_stop(&hw->bitbang);
+	for (i = 0; i < hw->gpio_cs_count; i++)
+		gpio_free(hw->gpio_cs[i]);
+	platform_set_drvdata(pdev, NULL);
+	spi_master_put(master);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static const struct of_device_id tiny_spi_match[] = {
+	{ .compatible = "opencores,tiny-spi-rtlsvn2", },
+	{},
+};
+MODULE_DEVICE_TABLE(of, tiny_spi_match);
+#else /* CONFIG_OF */
+#define tiny_spi_match NULL
+#endif /* CONFIG_OF */
+
+static struct platform_driver tiny_spi_driver = {
+	.probe = tiny_spi_probe,
+	.remove = __devexit_p(tiny_spi_remove),
+	.driver = {
+		.name = DRV_NAME,
+		.owner = THIS_MODULE,
+		.pm = NULL,
+		.of_match_table = tiny_spi_match,
+	},
+};
+
+static int __init tiny_spi_init(void)
+{
+	return platform_driver_register(&tiny_spi_driver);
+}
+module_init(tiny_spi_init);
+
+static void __exit tiny_spi_exit(void)
+{
+	platform_driver_unregister(&tiny_spi_driver);
+}
+module_exit(tiny_spi_exit);
+
+MODULE_DESCRIPTION("OpenCores tiny SPI driver");
+MODULE_AUTHOR("Thomas Chou <thomas@wytron.com.tw>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:" DRV_NAME);
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_ppc4xx.c linux-libre-2.6.39-gnu/drivers/spi/spi_ppc4xx.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_ppc4xx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_ppc4xx.c	2011-05-19 00:06:34.000000000 -0400
@@ -390,8 +390,7 @@
 /*
  * platform_device layer stuff...
  */
-static int __init spi_ppc4xx_of_probe(struct platform_device *op,
-				      const struct of_device_id *match)
+static int __init spi_ppc4xx_of_probe(struct platform_device *op)
 {
 	struct ppc4xx_spi *hw;
 	struct spi_master *master;
@@ -586,7 +585,7 @@
 
 MODULE_DEVICE_TABLE(of, spi_ppc4xx_of_match);
 
-static struct of_platform_driver spi_ppc4xx_of_driver = {
+static struct platform_driver spi_ppc4xx_of_driver = {
 	.probe = spi_ppc4xx_of_probe,
 	.remove = __exit_p(spi_ppc4xx_of_remove),
 	.driver = {
@@ -598,13 +597,13 @@
 
 static int __init spi_ppc4xx_init(void)
 {
-	return of_register_platform_driver(&spi_ppc4xx_of_driver);
+	return platform_driver_register(&spi_ppc4xx_of_driver);
 }
 module_init(spi_ppc4xx_init);
 
 static void __exit spi_ppc4xx_exit(void)
 {
-	of_unregister_platform_driver(&spi_ppc4xx_of_driver);
+	platform_driver_unregister(&spi_ppc4xx_of_driver);
 }
 module_exit(spi_ppc4xx_exit);
 
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_sh.c linux-libre-2.6.39-gnu/drivers/spi/spi_sh.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_sh.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_sh.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,543 @@
+/*
+ * SH SPI bus driver
+ *
+ * Copyright (C) 2011  Renesas Solutions Corp.
+ *
+ * Based on pxa2xx_spi.c:
+ * Copyright (C) 2005 Stephen Street / StreetFire Sound 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; 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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/timer.h>
+#include <linux/delay.h>
+#include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/interrupt.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/spi/spi.h>
+
+#define SPI_SH_TBR		0x00
+#define SPI_SH_RBR		0x00
+#define SPI_SH_CR1		0x08
+#define SPI_SH_CR2		0x10
+#define SPI_SH_CR3		0x18
+#define SPI_SH_CR4		0x20
+#define SPI_SH_CR5		0x28
+
+/* CR1 */
+#define SPI_SH_TBE		0x80
+#define SPI_SH_TBF		0x40
+#define SPI_SH_RBE		0x20
+#define SPI_SH_RBF		0x10
+#define SPI_SH_PFONRD		0x08
+#define SPI_SH_SSDB		0x04
+#define SPI_SH_SSD		0x02
+#define SPI_SH_SSA		0x01
+
+/* CR2 */
+#define SPI_SH_RSTF		0x80
+#define SPI_SH_LOOPBK		0x40
+#define SPI_SH_CPOL		0x20
+#define SPI_SH_CPHA		0x10
+#define SPI_SH_L1M0		0x08
+
+/* CR3 */
+#define SPI_SH_MAX_BYTE		0xFF
+
+/* CR4 */
+#define SPI_SH_TBEI		0x80
+#define SPI_SH_TBFI		0x40
+#define SPI_SH_RBEI		0x20
+#define SPI_SH_RBFI		0x10
+#define SPI_SH_WPABRT		0x04
+#define SPI_SH_SSS		0x01
+
+/* CR8 */
+#define SPI_SH_P1L0		0x80
+#define SPI_SH_PP1L0		0x40
+#define SPI_SH_MUXI		0x20
+#define SPI_SH_MUXIRQ		0x10
+
+#define SPI_SH_FIFO_SIZE	32
+#define SPI_SH_SEND_TIMEOUT	(3 * HZ)
+#define SPI_SH_RECEIVE_TIMEOUT	(HZ >> 3)
+
+#undef DEBUG
+
+struct spi_sh_data {
+	void __iomem *addr;
+	int irq;
+	struct spi_master *master;
+	struct list_head queue;
+	struct workqueue_struct *workqueue;
+	struct work_struct ws;
+	unsigned long cr1;
+	wait_queue_head_t wait;
+	spinlock_t lock;
+};
+
+static void spi_sh_write(struct spi_sh_data *ss, unsigned long data,
+			     unsigned long offset)
+{
+	writel(data, ss->addr + offset);
+}
+
+static unsigned long spi_sh_read(struct spi_sh_data *ss, unsigned long offset)
+{
+	return readl(ss->addr + offset);
+}
+
+static void spi_sh_set_bit(struct spi_sh_data *ss, unsigned long val,
+				unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = spi_sh_read(ss, offset);
+	tmp |= val;
+	spi_sh_write(ss, tmp, offset);
+}
+
+static void spi_sh_clear_bit(struct spi_sh_data *ss, unsigned long val,
+				unsigned long offset)
+{
+	unsigned long tmp;
+
+	tmp = spi_sh_read(ss, offset);
+	tmp &= ~val;
+	spi_sh_write(ss, tmp, offset);
+}
+
+static void clear_fifo(struct spi_sh_data *ss)
+{
+	spi_sh_set_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
+	spi_sh_clear_bit(ss, SPI_SH_RSTF, SPI_SH_CR2);
+}
+
+static int spi_sh_wait_receive_buffer(struct spi_sh_data *ss)
+{
+	int timeout = 100000;
+
+	while (spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
+		udelay(10);
+		if (timeout-- < 0)
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int spi_sh_wait_write_buffer_empty(struct spi_sh_data *ss)
+{
+	int timeout = 100000;
+
+	while (!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBE)) {
+		udelay(10);
+		if (timeout-- < 0)
+			return -ETIMEDOUT;
+	}
+	return 0;
+}
+
+static int spi_sh_send(struct spi_sh_data *ss, struct spi_message *mesg,
+			struct spi_transfer *t)
+{
+	int i, retval = 0;
+	int remain = t->len;
+	int cur_len;
+	unsigned char *data;
+	unsigned long tmp;
+	long ret;
+
+	if (t->len)
+		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	data = (unsigned char *)t->tx_buf;
+	while (remain > 0) {
+		cur_len = min(SPI_SH_FIFO_SIZE, remain);
+		for (i = 0; i < cur_len &&
+				!(spi_sh_read(ss, SPI_SH_CR4) &
+							SPI_SH_WPABRT) &&
+				!(spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_TBF);
+				i++)
+			spi_sh_write(ss, (unsigned long)data[i], SPI_SH_TBR);
+
+		if (spi_sh_read(ss, SPI_SH_CR4) & SPI_SH_WPABRT) {
+			/* Abort SPI operation */
+			spi_sh_set_bit(ss, SPI_SH_WPABRT, SPI_SH_CR4);
+			retval = -EIO;
+			break;
+		}
+
+		cur_len = i;
+
+		remain -= cur_len;
+		data += cur_len;
+
+		if (remain > 0) {
+			ss->cr1 &= ~SPI_SH_TBE;
+			spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
+			ret = wait_event_interruptible_timeout(ss->wait,
+						 ss->cr1 & SPI_SH_TBE,
+						 SPI_SH_SEND_TIMEOUT);
+			if (ret == 0 && !(ss->cr1 & SPI_SH_TBE)) {
+				printk(KERN_ERR "%s: timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+		}
+	}
+
+	if (list_is_last(&t->transfer_list, &mesg->transfers)) {
+		tmp = spi_sh_read(ss, SPI_SH_CR1);
+		tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
+		spi_sh_write(ss, tmp, SPI_SH_CR1);
+		spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+		ss->cr1 &= ~SPI_SH_TBE;
+		spi_sh_set_bit(ss, SPI_SH_TBE, SPI_SH_CR4);
+		ret = wait_event_interruptible_timeout(ss->wait,
+					 ss->cr1 & SPI_SH_TBE,
+					 SPI_SH_SEND_TIMEOUT);
+		if (ret == 0 && (ss->cr1 & SPI_SH_TBE)) {
+			printk(KERN_ERR "%s: timeout\n", __func__);
+			return -ETIMEDOUT;
+		}
+	}
+
+	return retval;
+}
+
+static int spi_sh_receive(struct spi_sh_data *ss, struct spi_message *mesg,
+			  struct spi_transfer *t)
+{
+	int i;
+	int remain = t->len;
+	int cur_len;
+	unsigned char *data;
+	unsigned long tmp;
+	long ret;
+
+	if (t->len > SPI_SH_MAX_BYTE)
+		spi_sh_write(ss, SPI_SH_MAX_BYTE, SPI_SH_CR3);
+	else
+		spi_sh_write(ss, t->len, SPI_SH_CR3);
+
+	tmp = spi_sh_read(ss, SPI_SH_CR1);
+	tmp = tmp & ~(SPI_SH_SSD | SPI_SH_SSDB);
+	spi_sh_write(ss, tmp, SPI_SH_CR1);
+	spi_sh_set_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	spi_sh_wait_write_buffer_empty(ss);
+
+	data = (unsigned char *)t->rx_buf;
+	while (remain > 0) {
+		if (remain >= SPI_SH_FIFO_SIZE) {
+			ss->cr1 &= ~SPI_SH_RBF;
+			spi_sh_set_bit(ss, SPI_SH_RBF, SPI_SH_CR4);
+			ret = wait_event_interruptible_timeout(ss->wait,
+						 ss->cr1 & SPI_SH_RBF,
+						 SPI_SH_RECEIVE_TIMEOUT);
+			if (ret == 0 &&
+			    spi_sh_read(ss, SPI_SH_CR1) & SPI_SH_RBE) {
+				printk(KERN_ERR "%s: timeout\n", __func__);
+				return -ETIMEDOUT;
+			}
+		}
+
+		cur_len = min(SPI_SH_FIFO_SIZE, remain);
+		for (i = 0; i < cur_len; i++) {
+			if (spi_sh_wait_receive_buffer(ss))
+				break;
+			data[i] = (unsigned char)spi_sh_read(ss, SPI_SH_RBR);
+		}
+
+		remain -= cur_len;
+		data += cur_len;
+	}
+
+	/* deassert CS when SPI is receiving. */
+	if (t->len > SPI_SH_MAX_BYTE) {
+		clear_fifo(ss);
+		spi_sh_write(ss, 1, SPI_SH_CR3);
+	} else {
+		spi_sh_write(ss, 0, SPI_SH_CR3);
+	}
+
+	return 0;
+}
+
+static void spi_sh_work(struct work_struct *work)
+{
+	struct spi_sh_data *ss = container_of(work, struct spi_sh_data, ws);
+	struct spi_message *mesg;
+	struct spi_transfer *t;
+	unsigned long flags;
+	int ret;
+
+	pr_debug("%s: enter\n", __func__);
+
+	spin_lock_irqsave(&ss->lock, flags);
+	while (!list_empty(&ss->queue)) {
+		mesg = list_entry(ss->queue.next, struct spi_message, queue);
+		list_del_init(&mesg->queue);
+
+		spin_unlock_irqrestore(&ss->lock, flags);
+		list_for_each_entry(t, &mesg->transfers, transfer_list) {
+			pr_debug("tx_buf = %p, rx_buf = %p\n",
+					t->tx_buf, t->rx_buf);
+			pr_debug("len = %d, delay_usecs = %d\n",
+					t->len, t->delay_usecs);
+
+			if (t->tx_buf) {
+				ret = spi_sh_send(ss, mesg, t);
+				if (ret < 0)
+					goto error;
+			}
+			if (t->rx_buf) {
+				ret = spi_sh_receive(ss, mesg, t);
+				if (ret < 0)
+					goto error;
+			}
+			mesg->actual_length += t->len;
+		}
+		spin_lock_irqsave(&ss->lock, flags);
+
+		mesg->status = 0;
+		mesg->complete(mesg->context);
+	}
+
+	clear_fifo(ss);
+	spi_sh_set_bit(ss, SPI_SH_SSD, SPI_SH_CR1);
+	udelay(100);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+
+	clear_fifo(ss);
+
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return;
+
+ error:
+	mesg->status = ret;
+	mesg->complete(mesg->context);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+	clear_fifo(ss);
+
+}
+
+static int spi_sh_setup(struct spi_device *spi)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+
+	if (!spi->bits_per_word)
+		spi->bits_per_word = 8;
+
+	pr_debug("%s: enter\n", __func__);
+
+	spi_sh_write(ss, 0xfe, SPI_SH_CR1);	/* SPI sycle stop */
+	spi_sh_write(ss, 0x00, SPI_SH_CR1);	/* CR1 init */
+	spi_sh_write(ss, 0x00, SPI_SH_CR3);	/* CR3 init */
+
+	clear_fifo(ss);
+
+	/* 1/8 clock */
+	spi_sh_write(ss, spi_sh_read(ss, SPI_SH_CR2) | 0x07, SPI_SH_CR2);
+	udelay(10);
+
+	return 0;
+}
+
+static int spi_sh_transfer(struct spi_device *spi, struct spi_message *mesg)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+	unsigned long flags;
+
+	pr_debug("%s: enter\n", __func__);
+	pr_debug("\tmode = %02x\n", spi->mode);
+
+	spin_lock_irqsave(&ss->lock, flags);
+
+	mesg->actual_length = 0;
+	mesg->status = -EINPROGRESS;
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA, SPI_SH_CR1);
+
+	list_add_tail(&mesg->queue, &ss->queue);
+	queue_work(ss->workqueue, &ss->ws);
+
+	spin_unlock_irqrestore(&ss->lock, flags);
+
+	return 0;
+}
+
+static void spi_sh_cleanup(struct spi_device *spi)
+{
+	struct spi_sh_data *ss = spi_master_get_devdata(spi->master);
+
+	pr_debug("%s: enter\n", __func__);
+
+	spi_sh_clear_bit(ss, SPI_SH_SSA | SPI_SH_SSDB | SPI_SH_SSD,
+			 SPI_SH_CR1);
+}
+
+static irqreturn_t spi_sh_irq(int irq, void *_ss)
+{
+	struct spi_sh_data *ss = (struct spi_sh_data *)_ss;
+	unsigned long cr1;
+
+	cr1 = spi_sh_read(ss, SPI_SH_CR1);
+	if (cr1 & SPI_SH_TBE)
+		ss->cr1 |= SPI_SH_TBE;
+	if (cr1 & SPI_SH_TBF)
+		ss->cr1 |= SPI_SH_TBF;
+	if (cr1 & SPI_SH_RBE)
+		ss->cr1 |= SPI_SH_RBE;
+	if (cr1 & SPI_SH_RBF)
+		ss->cr1 |= SPI_SH_RBF;
+
+	if (ss->cr1) {
+		spi_sh_clear_bit(ss, ss->cr1, SPI_SH_CR4);
+		wake_up(&ss->wait);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __devexit spi_sh_remove(struct platform_device *pdev)
+{
+	struct spi_sh_data *ss = dev_get_drvdata(&pdev->dev);
+
+	destroy_workqueue(ss->workqueue);
+	free_irq(ss->irq, ss);
+	iounmap(ss->addr);
+	spi_master_put(ss->master);
+
+	return 0;
+}
+
+static int __devinit spi_sh_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	struct spi_master *master;
+	struct spi_sh_data *ss;
+	int ret, irq;
+
+	/* get base addr */
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (unlikely(res == NULL)) {
+		dev_err(&pdev->dev, "invalid resource\n");
+		return -EINVAL;
+	}
+
+	irq = platform_get_irq(pdev, 0);
+	if (irq < 0) {
+		dev_err(&pdev->dev, "platform_get_irq error\n");
+		return -ENODEV;
+	}
+
+	master = spi_alloc_master(&pdev->dev, sizeof(struct spi_sh_data));
+	if (master == NULL) {
+		dev_err(&pdev->dev, "spi_alloc_master error.\n");
+		return -ENOMEM;
+	}
+
+	ss = spi_master_get_devdata(master);
+	dev_set_drvdata(&pdev->dev, ss);
+
+	ss->irq = irq;
+	ss->master = master;
+	ss->addr = ioremap(res->start, resource_size(res));
+	if (ss->addr == NULL) {
+		dev_err(&pdev->dev, "ioremap error.\n");
+		ret = -ENOMEM;
+		goto error1;
+	}
+	INIT_LIST_HEAD(&ss->queue);
+	spin_lock_init(&ss->lock);
+	INIT_WORK(&ss->ws, spi_sh_work);
+	init_waitqueue_head(&ss->wait);
+	ss->workqueue = create_singlethread_workqueue(
+					dev_name(master->dev.parent));
+	if (ss->workqueue == NULL) {
+		dev_err(&pdev->dev, "create workqueue error\n");
+		ret = -EBUSY;
+		goto error2;
+	}
+
+	ret = request_irq(irq, spi_sh_irq, IRQF_DISABLED, "spi_sh", ss);
+	if (ret < 0) {
+		dev_err(&pdev->dev, "request_irq error\n");
+		goto error3;
+	}
+
+	master->num_chipselect = 2;
+	master->bus_num = pdev->id;
+	master->setup = spi_sh_setup;
+	master->transfer = spi_sh_transfer;
+	master->cleanup = spi_sh_cleanup;
+
+	ret = spi_register_master(master);
+	if (ret < 0) {
+		printk(KERN_ERR "spi_register_master error.\n");
+		goto error4;
+	}
+
+	return 0;
+
+ error4:
+	free_irq(irq, ss);
+ error3:
+	destroy_workqueue(ss->workqueue);
+ error2:
+	iounmap(ss->addr);
+ error1:
+	spi_master_put(master);
+
+	return ret;
+}
+
+static struct platform_driver spi_sh_driver = {
+	.probe = spi_sh_probe,
+	.remove = __devexit_p(spi_sh_remove),
+	.driver = {
+		.name = "sh_spi",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init spi_sh_init(void)
+{
+	return platform_driver_register(&spi_sh_driver);
+}
+module_init(spi_sh_init);
+
+static void __exit spi_sh_exit(void)
+{
+	platform_driver_unregister(&spi_sh_driver);
+}
+module_exit(spi_sh_exit);
+
+MODULE_DESCRIPTION("SH SPI bus driver");
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Yoshihiro Shimoda");
+MODULE_ALIAS("platform:sh_spi");
diff -druN linux-libre-2.6.38-gnu/drivers/spi/spi_sh_msiof.c linux-libre-2.6.39-gnu/drivers/spi/spi_sh_msiof.c
--- linux-libre-2.6.38-gnu/drivers/spi/spi_sh_msiof.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/spi_sh_msiof.c	2011-05-19 00:06:34.000000000 -0400
@@ -9,22 +9,22 @@
  *
  */
 
-#include <linux/kernel.h>
-#include <linux/init.h>
+#include <linux/bitmap.h>
+#include <linux/clk.h>
+#include <linux/completion.h>
 #include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/init.h>
 #include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/kernel.h>
 #include <linux/platform_device.h>
-#include <linux/completion.h>
 #include <linux/pm_runtime.h>
-#include <linux/gpio.h>
-#include <linux/bitmap.h>
-#include <linux/clk.h>
-#include <linux/io.h>
-#include <linux/err.h>
 
+#include <linux/spi/sh_msiof.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
-#include <linux/spi/sh_msiof.h>
 
 #include <asm/unaligned.h>
 
@@ -67,7 +67,7 @@
 #define STR_TEOF  (1 << 23)
 #define STR_REOF  (1 << 7)
 
-static unsigned long sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
+static u32 sh_msiof_read(struct sh_msiof_spi_priv *p, int reg_offs)
 {
 	switch (reg_offs) {
 	case TSCR:
@@ -79,7 +79,7 @@
 }
 
 static void sh_msiof_write(struct sh_msiof_spi_priv *p, int reg_offs,
-			   unsigned long value)
+			   u32 value)
 {
 	switch (reg_offs) {
 	case TSCR:
@@ -93,10 +93,10 @@
 }
 
 static int sh_msiof_modify_ctr_wait(struct sh_msiof_spi_priv *p,
-				    unsigned long clr, unsigned long set)
+				    u32 clr, u32 set)
 {
-	unsigned long mask = clr | set;
-	unsigned long data;
+	u32 mask = clr | set;
+	u32 data;
 	int k;
 
 	data = sh_msiof_read(p, CTR);
@@ -166,10 +166,10 @@
 }
 
 static void sh_msiof_spi_set_pin_regs(struct sh_msiof_spi_priv *p,
-				      int cpol, int cpha,
-				      int tx_hi_z, int lsb_first)
+				      u32 cpol, u32 cpha,
+				      u32 tx_hi_z, u32 lsb_first)
 {
-	unsigned long tmp;
+	u32 tmp;
 	int edge;
 
 	/*
@@ -187,7 +187,7 @@
 	tmp |= cpol << 30; /* TSCKIZ */
 	tmp |= cpol << 28; /* RSCKIZ */
 
-	edge = cpol ? cpha : !cpha;
+	edge = cpol ^ !cpha;
 
 	tmp |= edge << 27; /* TEDG */
 	tmp |= edge << 26; /* REDG */
@@ -197,11 +197,9 @@
 
 static void sh_msiof_spi_set_mode_regs(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, void *rx_buf,
-				       int bits, int words)
+				       u32 bits, u32 words)
 {
-	unsigned long dr2;
-
-	dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
+	u32 dr2 = ((bits - 1) << 24) | ((words - 1) << 16);
 
 	if (tx_buf)
 		sh_msiof_write(p, TMDR2, dr2);
@@ -222,7 +220,7 @@
 static void sh_msiof_spi_write_fifo_8(struct sh_msiof_spi_priv *p,
 				      const void *tx_buf, int words, int fs)
 {
-	const unsigned char *buf_8 = tx_buf;
+	const u8 *buf_8 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -232,7 +230,7 @@
 static void sh_msiof_spi_write_fifo_16(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, int words, int fs)
 {
-	const unsigned short *buf_16 = tx_buf;
+	const u16 *buf_16 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -242,7 +240,7 @@
 static void sh_msiof_spi_write_fifo_16u(struct sh_msiof_spi_priv *p,
 					const void *tx_buf, int words, int fs)
 {
-	const unsigned short *buf_16 = tx_buf;
+	const u16 *buf_16 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -252,7 +250,7 @@
 static void sh_msiof_spi_write_fifo_32(struct sh_msiof_spi_priv *p,
 				       const void *tx_buf, int words, int fs)
 {
-	const unsigned int *buf_32 = tx_buf;
+	const u32 *buf_32 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -262,17 +260,37 @@
 static void sh_msiof_spi_write_fifo_32u(struct sh_msiof_spi_priv *p,
 					const void *tx_buf, int words, int fs)
 {
-	const unsigned int *buf_32 = tx_buf;
+	const u32 *buf_32 = tx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
 		sh_msiof_write(p, TFDR, get_unaligned(&buf_32[k]) << fs);
 }
 
+static void sh_msiof_spi_write_fifo_s32(struct sh_msiof_spi_priv *p,
+					const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, swab32(buf_32[k] << fs));
+}
+
+static void sh_msiof_spi_write_fifo_s32u(struct sh_msiof_spi_priv *p,
+					 const void *tx_buf, int words, int fs)
+{
+	const u32 *buf_32 = tx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		sh_msiof_write(p, TFDR, swab32(get_unaligned(&buf_32[k]) << fs));
+}
+
 static void sh_msiof_spi_read_fifo_8(struct sh_msiof_spi_priv *p,
 				     void *rx_buf, int words, int fs)
 {
-	unsigned char *buf_8 = rx_buf;
+	u8 *buf_8 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -282,7 +300,7 @@
 static void sh_msiof_spi_read_fifo_16(struct sh_msiof_spi_priv *p,
 				      void *rx_buf, int words, int fs)
 {
-	unsigned short *buf_16 = rx_buf;
+	u16 *buf_16 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -292,7 +310,7 @@
 static void sh_msiof_spi_read_fifo_16u(struct sh_msiof_spi_priv *p,
 				       void *rx_buf, int words, int fs)
 {
-	unsigned short *buf_16 = rx_buf;
+	u16 *buf_16 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -302,7 +320,7 @@
 static void sh_msiof_spi_read_fifo_32(struct sh_msiof_spi_priv *p,
 				      void *rx_buf, int words, int fs)
 {
-	unsigned int *buf_32 = rx_buf;
+	u32 *buf_32 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
@@ -312,19 +330,40 @@
 static void sh_msiof_spi_read_fifo_32u(struct sh_msiof_spi_priv *p,
 				       void *rx_buf, int words, int fs)
 {
-	unsigned int *buf_32 = rx_buf;
+	u32 *buf_32 = rx_buf;
 	int k;
 
 	for (k = 0; k < words; k++)
 		put_unaligned(sh_msiof_read(p, RFDR) >> fs, &buf_32[k]);
 }
 
+static void sh_msiof_spi_read_fifo_s32(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		buf_32[k] = swab32(sh_msiof_read(p, RFDR) >> fs);
+}
+
+static void sh_msiof_spi_read_fifo_s32u(struct sh_msiof_spi_priv *p,
+				       void *rx_buf, int words, int fs)
+{
+	u32 *buf_32 = rx_buf;
+	int k;
+
+	for (k = 0; k < words; k++)
+		put_unaligned(swab32(sh_msiof_read(p, RFDR) >> fs), &buf_32[k]);
+}
+
 static int sh_msiof_spi_bits(struct spi_device *spi, struct spi_transfer *t)
 {
 	int bits;
 
 	bits = t ? t->bits_per_word : 0;
-	bits = bits ? bits : spi->bits_per_word;
+	if (!bits)
+		bits = spi->bits_per_word;
 	return bits;
 }
 
@@ -334,7 +373,8 @@
 	unsigned long hz;
 
 	hz = t ? t->speed_hz : 0;
-	hz = hz ? hz : spi->max_speed_hz;
+	if (!hz)
+		hz = spi->max_speed_hz;
 	return hz;
 }
 
@@ -468,9 +508,17 @@
 	int bytes_done;
 	int words;
 	int n;
+	bool swab;
 
 	bits = sh_msiof_spi_bits(spi, t);
 
+	if (bits <= 8 && t->len > 15 && !(t->len & 3)) {
+		bits = 32;
+		swab = true;
+	} else {
+		swab = false;
+	}
+
 	/* setup bytes per word and fifo read/write functions */
 	if (bits <= 8) {
 		bytes_per_word = 1;
@@ -487,6 +535,17 @@
 			rx_fifo = sh_msiof_spi_read_fifo_16u;
 		else
 			rx_fifo = sh_msiof_spi_read_fifo_16;
+	} else if (swab) {
+		bytes_per_word = 4;
+		if ((unsigned long)t->tx_buf & 0x03)
+			tx_fifo = sh_msiof_spi_write_fifo_s32u;
+		else
+			tx_fifo = sh_msiof_spi_write_fifo_s32;
+
+		if ((unsigned long)t->rx_buf & 0x03)
+			rx_fifo = sh_msiof_spi_read_fifo_s32u;
+		else
+			rx_fifo = sh_msiof_spi_read_fifo_s32;
 	} else {
 		bytes_per_word = 4;
 		if ((unsigned long)t->tx_buf & 0x03)
diff -druN linux-libre-2.6.38-gnu/drivers/spi/ti-ssp-spi.c linux-libre-2.6.39-gnu/drivers/spi/ti-ssp-spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/ti-ssp-spi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/spi/ti-ssp-spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,402 @@
+/*
+ * Sequencer Serial Port (SSP) based SPI master driver
+ *
+ * Copyright (C) 2010 Texas Instruments 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/completion.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/spi/spi.h>
+#include <linux/mfd/ti_ssp.h>
+
+#define MODE_BITS	(SPI_CPHA | SPI_CPOL | SPI_CS_HIGH)
+
+struct ti_ssp_spi {
+	struct spi_master		*master;
+	struct device			*dev;
+	spinlock_t			lock;
+	struct list_head		msg_queue;
+	struct completion		complete;
+	bool				shutdown;
+	struct workqueue_struct		*workqueue;
+	struct work_struct		work;
+	u8				mode, bpw;
+	int				cs_active;
+	u32				pc_en, pc_dis, pc_wr, pc_rd;
+	void				(*select)(int cs);
+};
+
+static u32 ti_ssp_spi_rx(struct ti_ssp_spi *hw)
+{
+	u32 ret;
+
+	ti_ssp_run(hw->dev, hw->pc_rd, 0, &ret);
+	return ret;
+}
+
+static void ti_ssp_spi_tx(struct ti_ssp_spi *hw, u32 data)
+{
+	ti_ssp_run(hw->dev, hw->pc_wr, data << (32 - hw->bpw), NULL);
+}
+
+static int ti_ssp_spi_txrx(struct ti_ssp_spi *hw, struct spi_message *msg,
+		       struct spi_transfer *t)
+{
+	int count;
+
+	if (hw->bpw <= 8) {
+		u8		*rx = t->rx_buf;
+		const u8	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 1) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	} else if (hw->bpw <= 16) {
+		u16		*rx = t->rx_buf;
+		const u16	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 2) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	} else {
+		u32		*rx = t->rx_buf;
+		const u32	*tx = t->tx_buf;
+
+		for (count = 0; count < t->len; count += 4) {
+			if (t->tx_buf)
+				ti_ssp_spi_tx(hw, *tx++);
+			if (t->rx_buf)
+				*rx++ = ti_ssp_spi_rx(hw);
+		}
+	}
+
+	msg->actual_length += count; /* bytes transferred */
+
+	dev_dbg(&msg->spi->dev, "xfer %s%s, %d bytes, %d bpw, count %d%s\n",
+		t->tx_buf ? "tx" : "", t->rx_buf ? "rx" : "", t->len,
+		hw->bpw, count, (count < t->len) ? " (under)" : "");
+
+	return (count < t->len) ? -EIO : 0; /* left over data */
+}
+
+static void ti_ssp_spi_chip_select(struct ti_ssp_spi *hw, int cs_active)
+{
+	cs_active = !!cs_active;
+	if (cs_active == hw->cs_active)
+		return;
+	ti_ssp_run(hw->dev, cs_active ? hw->pc_en : hw->pc_dis, 0, NULL);
+	hw->cs_active = cs_active;
+}
+
+#define __SHIFT_OUT(bits)	(SSP_OPCODE_SHIFT | SSP_OUT_MODE | \
+				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
+#define __SHIFT_IN(bits)	(SSP_OPCODE_SHIFT | SSP_IN_MODE  | \
+				 cs_en | clk | SSP_COUNT((bits) * 2 - 1))
+
+static int ti_ssp_spi_setup_transfer(struct ti_ssp_spi *hw, u8 bpw, u8 mode)
+{
+	int error, idx = 0;
+	u32 seqram[16];
+	u32 cs_en, cs_dis, clk;
+	u32 topbits, botbits;
+
+	mode &= MODE_BITS;
+	if (mode == hw->mode && bpw == hw->bpw)
+		return 0;
+
+	cs_en  = (mode & SPI_CS_HIGH) ? SSP_CS_HIGH : SSP_CS_LOW;
+	cs_dis = (mode & SPI_CS_HIGH) ? SSP_CS_LOW  : SSP_CS_HIGH;
+	clk    = (mode & SPI_CPOL)    ? SSP_CLK_HIGH : SSP_CLK_LOW;
+
+	/* Construct instructions */
+
+	/* Disable Chip Select */
+	hw->pc_dis = idx;
+	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_dis | clk;
+	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_dis | clk;
+
+	/* Enable Chip Select */
+	hw->pc_en = idx;
+	seqram[idx++] = SSP_OPCODE_DIRECT | SSP_OUT_MODE | cs_en | clk;
+	seqram[idx++] = SSP_OPCODE_STOP   | SSP_OUT_MODE | cs_en | clk;
+
+	/* Reads and writes need to be split for bpw > 16 */
+	topbits = (bpw > 16) ? 16 : bpw;
+	botbits = bpw - topbits;
+
+	/* Write */
+	hw->pc_wr = idx;
+	seqram[idx++] = __SHIFT_OUT(topbits) | SSP_ADDR_REG;
+	if (botbits)
+		seqram[idx++] = __SHIFT_OUT(botbits)  | SSP_DATA_REG;
+	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
+
+	/* Read */
+	hw->pc_rd = idx;
+	if (botbits)
+		seqram[idx++] = __SHIFT_IN(botbits) | SSP_ADDR_REG;
+	seqram[idx++] = __SHIFT_IN(topbits) | SSP_DATA_REG;
+	seqram[idx++] = SSP_OPCODE_STOP | SSP_OUT_MODE | cs_en | clk;
+
+	error = ti_ssp_load(hw->dev, 0, seqram, idx);
+	if (error < 0)
+		return error;
+
+	error = ti_ssp_set_mode(hw->dev, ((mode & SPI_CPHA) ?
+					  0 : SSP_EARLY_DIN));
+	if (error < 0)
+		return error;
+
+	hw->bpw = bpw;
+	hw->mode = mode;
+
+	return error;
+}
+
+static void ti_ssp_spi_work(struct work_struct *work)
+{
+	struct ti_ssp_spi *hw = container_of(work, struct ti_ssp_spi, work);
+
+	spin_lock(&hw->lock);
+
+	 while (!list_empty(&hw->msg_queue)) {
+		struct spi_message	*m;
+		struct spi_device	*spi;
+		struct spi_transfer	*t = NULL;
+		int			status = 0;
+
+		m = container_of(hw->msg_queue.next, struct spi_message,
+				 queue);
+
+		list_del_init(&m->queue);
+
+		spin_unlock(&hw->lock);
+
+		spi = m->spi;
+
+		if (hw->select)
+			hw->select(spi->chip_select);
+
+		list_for_each_entry(t, &m->transfers, transfer_list) {
+			int bpw = spi->bits_per_word;
+			int xfer_status;
+
+			if (t->bits_per_word)
+				bpw = t->bits_per_word;
+
+			if (ti_ssp_spi_setup_transfer(hw, bpw, spi->mode) < 0)
+				break;
+
+			ti_ssp_spi_chip_select(hw, 1);
+
+			xfer_status = ti_ssp_spi_txrx(hw, m, t);
+			if (xfer_status < 0)
+				status = xfer_status;
+
+			if (t->delay_usecs)
+				udelay(t->delay_usecs);
+
+			if (t->cs_change)
+				ti_ssp_spi_chip_select(hw, 0);
+		}
+
+		ti_ssp_spi_chip_select(hw, 0);
+		m->status = status;
+		m->complete(m->context);
+
+		spin_lock(&hw->lock);
+	}
+
+	if (hw->shutdown)
+		complete(&hw->complete);
+
+	spin_unlock(&hw->lock);
+}
+
+static int ti_ssp_spi_setup(struct spi_device *spi)
+{
+	if (spi->bits_per_word > 32)
+		return -EINVAL;
+
+	return 0;
+}
+
+static int ti_ssp_spi_transfer(struct spi_device *spi, struct spi_message *m)
+{
+	struct ti_ssp_spi	*hw;
+	struct spi_transfer	*t;
+	int			error = 0;
+
+	m->actual_length = 0;
+	m->status = -EINPROGRESS;
+
+	hw = spi_master_get_devdata(spi->master);
+
+	if (list_empty(&m->transfers) || !m->complete)
+		return -EINVAL;
+
+	list_for_each_entry(t, &m->transfers, transfer_list) {
+		if (t->len && !(t->rx_buf || t->tx_buf)) {
+			dev_err(&spi->dev, "invalid xfer, no buffer\n");
+			return -EINVAL;
+		}
+
+		if (t->len && t->rx_buf && t->tx_buf) {
+			dev_err(&spi->dev, "invalid xfer, full duplex\n");
+			return -EINVAL;
+		}
+
+		if (t->bits_per_word > 32) {
+			dev_err(&spi->dev, "invalid xfer width %d\n",
+				t->bits_per_word);
+			return -EINVAL;
+		}
+	}
+
+	spin_lock(&hw->lock);
+	if (hw->shutdown) {
+		error = -ESHUTDOWN;
+		goto error_unlock;
+	}
+	list_add_tail(&m->queue, &hw->msg_queue);
+	queue_work(hw->workqueue, &hw->work);
+error_unlock:
+	spin_unlock(&hw->lock);
+	return error;
+}
+
+static int __devinit ti_ssp_spi_probe(struct platform_device *pdev)
+{
+	const struct ti_ssp_spi_data *pdata;
+	struct ti_ssp_spi *hw;
+	struct spi_master *master;
+	struct device *dev = &pdev->dev;
+	int error = 0;
+
+	pdata = dev->platform_data;
+	if (!pdata) {
+		dev_err(dev, "platform data not found\n");
+		return -EINVAL;
+	}
+
+	master = spi_alloc_master(dev, sizeof(struct ti_ssp_spi));
+	if (!master) {
+		dev_err(dev, "cannot allocate SPI master\n");
+		return -ENOMEM;
+	}
+
+	hw = spi_master_get_devdata(master);
+	platform_set_drvdata(pdev, hw);
+
+	hw->master = master;
+	hw->dev = dev;
+	hw->select = pdata->select;
+
+	spin_lock_init(&hw->lock);
+	init_completion(&hw->complete);
+	INIT_LIST_HEAD(&hw->msg_queue);
+	INIT_WORK(&hw->work, ti_ssp_spi_work);
+
+	hw->workqueue = create_singlethread_workqueue(dev_name(dev));
+	if (!hw->workqueue) {
+		error = -ENOMEM;
+		dev_err(dev, "work queue creation failed\n");
+		goto error_wq;
+	}
+
+	error = ti_ssp_set_iosel(hw->dev, pdata->iosel);
+	if (error < 0) {
+		dev_err(dev, "io setup failed\n");
+		goto error_iosel;
+	}
+
+	master->bus_num		= pdev->id;
+	master->num_chipselect	= pdata->num_cs;
+	master->mode_bits	= MODE_BITS;
+	master->flags		= SPI_MASTER_HALF_DUPLEX;
+	master->setup		= ti_ssp_spi_setup;
+	master->transfer	= ti_ssp_spi_transfer;
+
+	error = spi_register_master(master);
+	if (error) {
+		dev_err(dev, "master registration failed\n");
+		goto error_reg;
+	}
+
+	return 0;
+
+error_reg:
+error_iosel:
+	destroy_workqueue(hw->workqueue);
+error_wq:
+	spi_master_put(master);
+	return error;
+}
+
+static int __devexit ti_ssp_spi_remove(struct platform_device *pdev)
+{
+	struct ti_ssp_spi *hw = platform_get_drvdata(pdev);
+	int error;
+
+	hw->shutdown = 1;
+	while (!list_empty(&hw->msg_queue)) {
+		error = wait_for_completion_interruptible(&hw->complete);
+		if (error < 0) {
+			hw->shutdown = 0;
+			return error;
+		}
+	}
+	destroy_workqueue(hw->workqueue);
+	spi_unregister_master(hw->master);
+
+	return 0;
+}
+
+static struct platform_driver ti_ssp_spi_driver = {
+	.probe		= ti_ssp_spi_probe,
+	.remove		= __devexit_p(ti_ssp_spi_remove),
+	.driver		= {
+		.name	= "ti-ssp-spi",
+		.owner	= THIS_MODULE,
+	},
+};
+
+static int __init ti_ssp_spi_init(void)
+{
+	return platform_driver_register(&ti_ssp_spi_driver);
+}
+module_init(ti_ssp_spi_init);
+
+static void __exit ti_ssp_spi_exit(void)
+{
+	platform_driver_unregister(&ti_ssp_spi_driver);
+}
+module_exit(ti_ssp_spi_exit);
+
+MODULE_DESCRIPTION("SSP SPI Master");
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:ti-ssp-spi");
diff -druN linux-libre-2.6.38-gnu/drivers/spi/xilinx_spi.c linux-libre-2.6.39-gnu/drivers/spi/xilinx_spi.c
--- linux-libre-2.6.38-gnu/drivers/spi/xilinx_spi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/spi/xilinx_spi.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,6 +18,7 @@
 #include <linux/interrupt.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
+#include <linux/mfd/core.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi_bitbang.h>
 #include <linux/spi/xilinx_spi.h>
@@ -351,14 +352,12 @@
 	return IRQ_HANDLED;
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id xilinx_spi_of_match[] = {
 	{ .compatible = "xlnx,xps-spi-2.00.a", },
 	{ .compatible = "xlnx,xps-spi-2.00.b", },
 	{}
 };
 MODULE_DEVICE_TABLE(of, xilinx_spi_of_match);
-#endif
 
 struct spi_master *xilinx_spi_init(struct device *dev, struct resource *mem,
 	u32 irq, s16 bus_num, int num_cs, int little_endian, int bits_per_word)
@@ -394,9 +393,7 @@
 
 	master->bus_num = bus_num;
 	master->num_chipselect = num_cs;
-#ifdef CONFIG_OF
 	master->dev.of_node = dev->of_node;
-#endif
 
 	xspi->mem = *mem;
 	xspi->irq = irq;
@@ -474,7 +471,7 @@
 	struct spi_master *master;
 	u8 i;
 
-	pdata = dev->dev.platform_data;
+	pdata = mfd_get_data(dev);
 	if (pdata) {
 		num_cs = pdata->num_chipselect;
 		little_endian = pdata->little_endian;
@@ -539,9 +536,7 @@
 	.driver = {
 		.name = XILINX_SPI_NAME,
 		.owner = THIS_MODULE,
-#ifdef CONFIG_OF
 		.of_match_table = xilinx_spi_of_match,
-#endif
 	},
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/ssb/main.c linux-libre-2.6.39-gnu/drivers/ssb/main.c
--- linux-libre-2.6.38-gnu/drivers/ssb/main.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ssb/main.c	2011-05-19 00:06:34.000000000 -0400
@@ -1192,10 +1192,10 @@
 }
 EXPORT_SYMBOL(ssb_device_enable);
 
-/* Wait for a bit in a register to get set or unset.
+/* Wait for bitmask in a register to get set or cleared.
  * timeout is in units of ten-microseconds */
-static int ssb_wait_bit(struct ssb_device *dev, u16 reg, u32 bitmask,
-			int timeout, int set)
+static int ssb_wait_bits(struct ssb_device *dev, u16 reg, u32 bitmask,
+			 int timeout, int set)
 {
 	int i;
 	u32 val;
@@ -1203,7 +1203,7 @@
 	for (i = 0; i < timeout; i++) {
 		val = ssb_read32(dev, reg);
 		if (set) {
-			if (val & bitmask)
+			if ((val & bitmask) == bitmask)
 				return 0;
 		} else {
 			if (!(val & bitmask))
@@ -1220,20 +1220,38 @@
 
 void ssb_device_disable(struct ssb_device *dev, u32 core_specific_flags)
 {
-	u32 reject;
+	u32 reject, val;
 
 	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_RESET)
 		return;
 
 	reject = ssb_tmslow_reject_bitmask(dev);
-	ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
-	ssb_wait_bit(dev, SSB_TMSLOW, reject, 1000, 1);
-	ssb_wait_bit(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
-	ssb_write32(dev, SSB_TMSLOW,
-		    SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
-		    reject | SSB_TMSLOW_RESET |
-		    core_specific_flags);
-	ssb_flush_tmslow(dev);
+
+	if (ssb_read32(dev, SSB_TMSLOW) & SSB_TMSLOW_CLOCK) {
+		ssb_write32(dev, SSB_TMSLOW, reject | SSB_TMSLOW_CLOCK);
+		ssb_wait_bits(dev, SSB_TMSLOW, reject, 1000, 1);
+		ssb_wait_bits(dev, SSB_TMSHIGH, SSB_TMSHIGH_BUSY, 1000, 0);
+
+		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) {
+			val = ssb_read32(dev, SSB_IMSTATE);
+			val |= SSB_IMSTATE_REJECT;
+			ssb_write32(dev, SSB_IMSTATE, val);
+			ssb_wait_bits(dev, SSB_IMSTATE, SSB_IMSTATE_BUSY, 1000,
+				      0);
+		}
+
+		ssb_write32(dev, SSB_TMSLOW,
+			SSB_TMSLOW_FGC | SSB_TMSLOW_CLOCK |
+			reject | SSB_TMSLOW_RESET |
+			core_specific_flags);
+		ssb_flush_tmslow(dev);
+
+		if (ssb_read32(dev, SSB_IDLOW) & SSB_IDLOW_INITIATOR) {
+			val = ssb_read32(dev, SSB_IMSTATE);
+			val &= ~SSB_IMSTATE_REJECT;
+			ssb_write32(dev, SSB_IMSTATE, val);
+		}
+	}
 
 	ssb_write32(dev, SSB_TMSLOW,
 		    reject | SSB_TMSLOW_RESET |
diff -druN linux-libre-2.6.38-gnu/drivers/ssb/pci.c linux-libre-2.6.39-gnu/drivers/ssb/pci.c
--- linux-libre-2.6.38-gnu/drivers/ssb/pci.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ssb/pci.c	2011-05-19 00:06:34.000000000 -0400
@@ -468,10 +468,14 @@
 		SPEX(country_code, SSB_SPROM4_CCODE, 0xFFFF, 0);
 		SPEX(boardflags_lo, SSB_SPROM4_BFLLO, 0xFFFF, 0);
 		SPEX(boardflags_hi, SSB_SPROM4_BFLHI, 0xFFFF, 0);
+		SPEX(boardflags2_lo, SSB_SPROM4_BFL2LO, 0xFFFF, 0);
+		SPEX(boardflags2_hi, SSB_SPROM4_BFL2HI, 0xFFFF, 0);
 	} else {
 		SPEX(country_code, SSB_SPROM5_CCODE, 0xFFFF, 0);
 		SPEX(boardflags_lo, SSB_SPROM5_BFLLO, 0xFFFF, 0);
 		SPEX(boardflags_hi, SSB_SPROM5_BFLHI, 0xFFFF, 0);
+		SPEX(boardflags2_lo, SSB_SPROM5_BFL2LO, 0xFFFF, 0);
+		SPEX(boardflags2_hi, SSB_SPROM5_BFL2HI, 0xFFFF, 0);
 	}
 	SPEX(ant_available_a, SSB_SPROM4_ANTAVAIL, SSB_SPROM4_ANTAVAIL_A,
 	     SSB_SPROM4_ANTAVAIL_A_SHIFT);
@@ -641,7 +645,7 @@
 		break;
 	default:
 		ssb_printk(KERN_WARNING PFX "Unsupported SPROM"
-			   "  revision %d detected. Will extract"
+			   " revision %d detected. Will extract"
 			   " v1\n", out->revision);
 		out->revision = 1;
 		sprom_extract_r123(out, in);
@@ -666,7 +670,7 @@
 		ssb_printk(KERN_ERR PFX "No SPROM available!\n");
 		return -ENODEV;
 	}
-	if (bus->chipco.dev) {	/* can be unavailible! */
+	if (bus->chipco.dev) {	/* can be unavailable! */
 		/*
 		 * get SPROM offset: SSB_SPROM_BASE1 except for
 		 * chipcommon rev >= 31 or chip ID is 0x4312 and
diff -druN linux-libre-2.6.38-gnu/drivers/ssb/sprom.c linux-libre-2.6.39-gnu/drivers/ssb/sprom.c
--- linux-libre-2.6.38-gnu/drivers/ssb/sprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/ssb/sprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -185,7 +185,7 @@
 	/* this routine differs from specs as we do not access SPROM directly
 	   on PCMCIA */
 	if (bus->bustype == SSB_BUSTYPE_PCI &&
-	    bus->chipco.dev &&	/* can be unavailible! */
+	    bus->chipco.dev &&	/* can be unavailable! */
 	    bus->chipco.dev->id.revision >= 31)
 		return bus->chipco.capabilities & SSB_CHIPCO_CAP_SPROM;
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera.c linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera.c
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,2527 @@
+/*
+ * altera.c
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010,2011 NetUP Inc.
+ * Copyright (C) 2010,2011 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 <asm/unaligned.h>
+#include <linux/ctype.h>
+#include <linux/string.h>
+#include <linux/firmware.h>
+#include <linux/slab.h>
+#include <staging/altera.h>
+#include "altera-exprt.h"
+#include "altera-jtag.h"
+
+static int debug = 1;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debugging information");
+
+MODULE_DESCRIPTION("altera FPGA kernel module");
+MODULE_AUTHOR("Igor M. Liplianin  <liplianin@netup.ru>");
+MODULE_LICENSE("GPL");
+
+#define dprintk(args...) \
+	if (debug) { \
+		printk(KERN_DEBUG args); \
+	}
+
+enum altera_fpga_opcode {
+	OP_NOP = 0,
+	OP_DUP,
+	OP_SWP,
+	OP_ADD,
+	OP_SUB,
+	OP_MULT,
+	OP_DIV,
+	OP_MOD,
+	OP_SHL,
+	OP_SHR,
+	OP_NOT,
+	OP_AND,
+	OP_OR,
+	OP_XOR,
+	OP_INV,
+	OP_GT,
+	OP_LT,
+	OP_RET,
+	OP_CMPS,
+	OP_PINT,
+	OP_PRNT,
+	OP_DSS,
+	OP_DSSC,
+	OP_ISS,
+	OP_ISSC,
+	OP_DPR = 0x1c,
+	OP_DPRL,
+	OP_DPO,
+	OP_DPOL,
+	OP_IPR,
+	OP_IPRL,
+	OP_IPO,
+	OP_IPOL,
+	OP_PCHR,
+	OP_EXIT,
+	OP_EQU,
+	OP_POPT,
+	OP_ABS = 0x2c,
+	OP_BCH0,
+	OP_PSH0 = 0x2f,
+	OP_PSHL = 0x40,
+	OP_PSHV,
+	OP_JMP,
+	OP_CALL,
+	OP_NEXT,
+	OP_PSTR,
+	OP_SINT = 0x47,
+	OP_ST,
+	OP_ISTP,
+	OP_DSTP,
+	OP_SWPN,
+	OP_DUPN,
+	OP_POPV,
+	OP_POPE,
+	OP_POPA,
+	OP_JMPZ,
+	OP_DS,
+	OP_IS,
+	OP_DPRA,
+	OP_DPOA,
+	OP_IPRA,
+	OP_IPOA,
+	OP_EXPT,
+	OP_PSHE,
+	OP_PSHA,
+	OP_DYNA,
+	OP_EXPV = 0x5c,
+	OP_COPY = 0x80,
+	OP_REVA,
+	OP_DSC,
+	OP_ISC,
+	OP_WAIT,
+	OP_VS,
+	OP_CMPA = 0xc0,
+	OP_VSC,
+};
+
+struct altera_procinfo {
+	char			*name;
+	u8			attrs;
+	struct altera_procinfo	*next;
+};
+
+/* This function checks if enough parameters are available on the stack. */
+static int altera_check_stack(int stack_ptr, int count, int *status)
+{
+	if (stack_ptr < count) {
+		*status = -EOVERFLOW;
+		return 0;
+	}
+
+	return 1;
+}
+
+static void altera_export_int(char *key, s32 value)
+{
+	dprintk("Export: key = \"%s\", value = %d\n", key, value);
+}
+
+#define HEX_LINE_CHARS 72
+#define HEX_LINE_BITS (HEX_LINE_CHARS * 4)
+
+static void altera_export_bool_array(char *key, u8 *data, s32 count)
+{
+	char string[HEX_LINE_CHARS + 1];
+	s32 i, offset;
+	u32 size, line, lines, linebits, value, j, k;
+
+	if (count > HEX_LINE_BITS) {
+		dprintk("Export: key = \"%s\", %d bits, value = HEX\n",
+							key, count);
+		lines = (count + (HEX_LINE_BITS - 1)) / HEX_LINE_BITS;
+
+		for (line = 0; line < lines; ++line) {
+			if (line < (lines - 1)) {
+				linebits = HEX_LINE_BITS;
+				size = HEX_LINE_CHARS;
+				offset = count - ((line + 1) * HEX_LINE_BITS);
+			} else {
+				linebits =
+					count - ((lines - 1) * HEX_LINE_BITS);
+				size = (linebits + 3) / 4;
+				offset = 0L;
+			}
+
+			string[size] = '\0';
+			j = size - 1;
+			value = 0;
+
+			for (k = 0; k < linebits; ++k) {
+				i = k + offset;
+				if (data[i >> 3] & (1 << (i & 7)))
+					value |= (1 << (i & 3));
+				if ((i & 3) == 3) {
+					sprintf(&string[j], "%1x", value);
+					value = 0;
+					--j;
+				}
+			}
+			if ((k & 3) > 0)
+				sprintf(&string[j], "%1x", value);
+
+			dprintk("%s\n", string);
+		}
+
+	} else {
+		size = (count + 3) / 4;
+		string[size] = '\0';
+		j = size - 1;
+		value = 0;
+
+		for (i = 0; i < count; ++i) {
+			if (data[i >> 3] & (1 << (i & 7)))
+				value |= (1 << (i & 3));
+			if ((i & 3) == 3) {
+				sprintf(&string[j], "%1x", value);
+				value = 0;
+				--j;
+			}
+		}
+		if ((i & 3) > 0)
+			sprintf(&string[j], "%1x", value);
+
+		dprintk("Export: key = \"%s\", %d bits, value = HEX %s\n",
+			key, count, string);
+	}
+}
+
+static int altera_execute(struct altera_state *astate,
+				u8 *p,
+				s32 program_size,
+				s32 *error_address,
+				int *exit_code,
+				int *format_version)
+{
+	struct altera_config *aconf = astate->config;
+	char *msg_buff = astate->msg_buff;
+	long *stack = astate->stack;
+	int status = 0;
+	u32 first_word = 0L;
+	u32 action_table = 0L;
+	u32 proc_table = 0L;
+	u32 str_table = 0L;
+	u32 sym_table = 0L;
+	u32 data_sect = 0L;
+	u32 code_sect = 0L;
+	u32 debug_sect = 0L;
+	u32 action_count = 0L;
+	u32 proc_count = 0L;
+	u32 sym_count = 0L;
+	long *vars = NULL;
+	s32 *var_size = NULL;
+	char *attrs = NULL;
+	u8 *proc_attributes = NULL;
+	u32 pc;
+	u32 opcode_address;
+	u32 args[3];
+	u32 opcode;
+	u32 name_id;
+	u8 charbuf[4];
+	long long_tmp;
+	u32 variable_id;
+	u8 *charptr_tmp;
+	u8 *charptr_tmp2;
+	long *longptr_tmp;
+	int version = 0;
+	int delta = 0;
+	int stack_ptr = 0;
+	u32 arg_count;
+	int done = 0;
+	int bad_opcode = 0;
+	u32 count;
+	u32 index;
+	u32 index2;
+	s32 long_count;
+	s32 long_idx;
+	s32 long_idx2;
+	u32 i;
+	u32 j;
+	u32 uncomp_size;
+	u32 offset;
+	u32 value;
+	int current_proc = 0;
+	int reverse;
+
+	char *name;
+
+	dprintk("%s\n", __func__);
+
+	/* Read header information */
+	if (program_size > 52L) {
+		first_word    = get_unaligned_be32(&p[0]);
+		version = (first_word & 1L);
+		*format_version = version + 1;
+		delta = version * 8;
+
+		action_table  = get_unaligned_be32(&p[4]);
+		proc_table    = get_unaligned_be32(&p[8]);
+		str_table  = get_unaligned_be32(&p[4 + delta]);
+		sym_table  = get_unaligned_be32(&p[16 + delta]);
+		data_sect  = get_unaligned_be32(&p[20 + delta]);
+		code_sect  = get_unaligned_be32(&p[24 + delta]);
+		debug_sect = get_unaligned_be32(&p[28 + delta]);
+		action_count  = get_unaligned_be32(&p[40 + delta]);
+		proc_count    = get_unaligned_be32(&p[44 + delta]);
+		sym_count  = get_unaligned_be32(&p[48 + (2 * delta)]);
+	}
+
+	if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L)) {
+		done = 1;
+		status = -EIO;
+		goto exit_done;
+	}
+
+	if (sym_count <= 0)
+		goto exit_done;
+
+	vars = kzalloc(sym_count * sizeof(long), GFP_KERNEL);
+
+	if (vars == NULL)
+		status = -ENOMEM;
+
+	if (status == 0) {
+		var_size = kzalloc(sym_count * sizeof(s32), GFP_KERNEL);
+
+		if (var_size == NULL)
+			status = -ENOMEM;
+	}
+
+	if (status == 0) {
+		attrs = kzalloc(sym_count, GFP_KERNEL);
+
+		if (attrs == NULL)
+			status = -ENOMEM;
+	}
+
+	if ((status == 0) && (version > 0)) {
+		proc_attributes = kzalloc(proc_count, GFP_KERNEL);
+
+		if (proc_attributes == NULL)
+			status = -ENOMEM;
+	}
+
+	if (status != 0)
+		goto exit_done;
+
+	delta = version * 2;
+
+	for (i = 0; i < sym_count; ++i) {
+		offset = (sym_table + ((11 + delta) * i));
+
+		value = get_unaligned_be32(&p[offset + 3 + delta]);
+
+		attrs[i] = p[offset];
+
+		/*
+		 * use bit 7 of attribute byte to indicate that
+		 * this buffer was dynamically allocated
+		 * and should be freed later
+		 */
+		attrs[i] &= 0x7f;
+
+		var_size[i] = get_unaligned_be32(&p[offset + 7 + delta]);
+
+		/*
+		 * Attribute bits:
+		 * bit 0: 0 = read-only, 1 = read-write
+		 * bit 1: 0 = not compressed, 1 = compressed
+		 * bit 2: 0 = not initialized, 1 = initialized
+		 * bit 3: 0 = scalar, 1 = array
+		 * bit 4: 0 = Boolean, 1 = integer
+		 * bit 5: 0 = declared variable,
+		 *	1 = compiler created temporary variable
+		 */
+
+		if ((attrs[i] & 0x0c) == 0x04)
+			/* initialized scalar variable */
+			vars[i] = value;
+		else if ((attrs[i] & 0x1e) == 0x0e) {
+			/* initialized compressed Boolean array */
+			uncomp_size = get_unaligned_le32(&p[data_sect + value]);
+
+			/* allocate a buffer for the uncompressed data */
+			vars[i] = (long)kzalloc(uncomp_size, GFP_KERNEL);
+			if (vars[i] == 0L)
+				status = -ENOMEM;
+			else {
+				/* set flag so buffer will be freed later */
+				attrs[i] |= 0x80;
+
+				/* uncompress the data */
+				if (altera_shrink(&p[data_sect + value],
+						var_size[i],
+						(u8 *)vars[i],
+						uncomp_size,
+						version) != uncomp_size)
+					/* decompression failed */
+					status = -EIO;
+				else
+					var_size[i] = uncomp_size * 8L;
+
+			}
+		} else if ((attrs[i] & 0x1e) == 0x0c) {
+			/* initialized Boolean array */
+			vars[i] = value + data_sect + (long)p;
+		} else if ((attrs[i] & 0x1c) == 0x1c) {
+			/* initialized integer array */
+			vars[i] = value + data_sect;
+		} else if ((attrs[i] & 0x0c) == 0x08) {
+			/* uninitialized array */
+
+			/* flag attrs so that memory is freed */
+			attrs[i] |= 0x80;
+
+			if (var_size[i] > 0) {
+				u32 size;
+
+				if (attrs[i] & 0x10)
+					/* integer array */
+					size = (var_size[i] * sizeof(s32));
+				else
+					/* Boolean array */
+					size = ((var_size[i] + 7L) / 8L);
+
+				vars[i] = (long)kzalloc(size, GFP_KERNEL);
+
+				if (vars[i] == 0) {
+					status = -ENOMEM;
+				} else {
+					/* zero out memory */
+					for (j = 0; j < size; ++j)
+						((u8 *)(vars[i]))[j] = 0;
+
+				}
+			} else
+				vars[i] = 0;
+
+		} else
+			vars[i] = 0;
+
+	}
+
+exit_done:
+	if (status != 0)
+		done = 1;
+
+	altera_jinit(astate);
+
+	pc = code_sect;
+	msg_buff[0] = '\0';
+
+	/*
+	 * For JBC version 2, we will execute the procedures corresponding to
+	 * the selected ACTION
+	 */
+	if (version > 0) {
+		if (aconf->action == NULL) {
+			status = -EINVAL;
+			done = 1;
+		} else {
+			int action_found = 0;
+			for (i = 0; (i < action_count) && !action_found; ++i) {
+				name_id = get_unaligned_be32(&p[action_table +
+								(12 * i)]);
+
+				name = &p[str_table + name_id];
+
+				if (strnicmp(aconf->action, name, strlen(name)) == 0) {
+					action_found = 1;
+					current_proc =
+						get_unaligned_be32(&p[action_table +
+								(12 * i) + 8]);
+				}
+			}
+
+			if (!action_found) {
+				status = -EINVAL;
+				done = 1;
+			}
+		}
+
+		if (status == 0) {
+			int first_time = 1;
+			i = current_proc;
+			while ((i != 0) || first_time) {
+				first_time = 0;
+				/* check procedure attribute byte */
+				proc_attributes[i] =
+						(p[proc_table +
+								(13 * i) + 8] &
+									0x03);
+
+				/*
+				 * BIT0 - OPTIONAL
+				 * BIT1 - RECOMMENDED
+				 * BIT6 - FORCED OFF
+				 * BIT7 - FORCED ON
+				 */
+
+				i = get_unaligned_be32(&p[proc_table +
+							(13 * i) + 4]);
+			}
+
+			/*
+			 * Set current_proc to the first procedure
+			 * to be executed
+			 */
+			i = current_proc;
+			while ((i != 0) &&
+				((proc_attributes[i] == 1) ||
+				((proc_attributes[i] & 0xc0) == 0x40))) {
+				i = get_unaligned_be32(&p[proc_table +
+							(13 * i) + 4]);
+			}
+
+			if ((i != 0) || ((i == 0) && (current_proc == 0) &&
+				((proc_attributes[0] != 1) &&
+				((proc_attributes[0] & 0xc0) != 0x40)))) {
+				current_proc = i;
+				pc = code_sect +
+					get_unaligned_be32(&p[proc_table +
+								(13 * i) + 9]);
+				if ((pc < code_sect) || (pc >= debug_sect))
+					status = -ERANGE;
+			} else
+				/* there are no procedures to execute! */
+				done = 1;
+
+		}
+	}
+
+	msg_buff[0] = '\0';
+
+	while (!done) {
+		opcode = (p[pc] & 0xff);
+		opcode_address = pc;
+		++pc;
+
+		if (debug > 1)
+			printk("opcode: %02x\n", opcode);
+
+		arg_count = (opcode >> 6) & 3;
+		for (i = 0; i < arg_count; ++i) {
+			args[i] = get_unaligned_be32(&p[pc]);
+			pc += 4;
+		}
+
+		switch (opcode) {
+		case OP_NOP:
+			break;
+		case OP_DUP:
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				stack[stack_ptr] = stack[stack_ptr - 1];
+				++stack_ptr;
+			}
+			break;
+		case OP_SWP:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				long_tmp = stack[stack_ptr - 2];
+				stack[stack_ptr - 2] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+			break;
+		case OP_ADD:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] += stack[stack_ptr];
+			}
+			break;
+		case OP_SUB:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] -= stack[stack_ptr];
+			}
+			break;
+		case OP_MULT:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] *= stack[stack_ptr];
+			}
+			break;
+		case OP_DIV:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] /= stack[stack_ptr];
+			}
+			break;
+		case OP_MOD:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] %= stack[stack_ptr];
+			}
+			break;
+		case OP_SHL:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] <<= stack[stack_ptr];
+			}
+			break;
+		case OP_SHR:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] >>= stack[stack_ptr];
+			}
+			break;
+		case OP_NOT:
+			if (altera_check_stack(stack_ptr, 1, &status))
+				stack[stack_ptr - 1] ^= (-1L);
+
+			break;
+		case OP_AND:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] &= stack[stack_ptr];
+			}
+			break;
+		case OP_OR:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] |= stack[stack_ptr];
+			}
+			break;
+		case OP_XOR:
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				--stack_ptr;
+				stack[stack_ptr - 1] ^= stack[stack_ptr];
+			}
+			break;
+		case OP_INV:
+			if (!altera_check_stack(stack_ptr, 1, &status))
+				break;
+			stack[stack_ptr - 1] = stack[stack_ptr - 1] ? 0L : 1L;
+			break;
+		case OP_GT:
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			--stack_ptr;
+			stack[stack_ptr - 1] =
+				(stack[stack_ptr - 1] > stack[stack_ptr]) ?
+									1L : 0L;
+
+			break;
+		case OP_LT:
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			--stack_ptr;
+			stack[stack_ptr - 1] =
+				(stack[stack_ptr - 1] < stack[stack_ptr]) ?
+									1L : 0L;
+
+			break;
+		case OP_RET:
+			if ((version > 0) && (stack_ptr == 0)) {
+				/*
+				 * We completed one of the main procedures
+				 * of an ACTION.
+				 * Find the next procedure
+				 * to be executed and jump to it.
+				 * If there are no more procedures, then EXIT.
+				 */
+				i = get_unaligned_be32(&p[proc_table +
+						(13 * current_proc) + 4]);
+				while ((i != 0) &&
+					((proc_attributes[i] == 1) ||
+					((proc_attributes[i] & 0xc0) == 0x40)))
+					i = get_unaligned_be32(&p[proc_table +
+								(13 * i) + 4]);
+
+				if (i == 0) {
+					/* no procedures to execute! */
+					done = 1;
+					*exit_code = 0;	/* success */
+				} else {
+					current_proc = i;
+					pc = code_sect + get_unaligned_be32(
+								&p[proc_table +
+								(13 * i) + 9]);
+					if ((pc < code_sect) ||
+					    (pc >= debug_sect))
+						status = -ERANGE;
+				}
+
+			} else
+				if (altera_check_stack(stack_ptr, 1, &status)) {
+					pc = stack[--stack_ptr] + code_sect;
+					if ((pc <= code_sect) ||
+					    (pc >= debug_sect))
+						status = -ERANGE;
+
+				}
+
+			break;
+		case OP_CMPS:
+			/*
+			 * Array short compare
+			 * ...stack 0 is source 1 value
+			 * ...stack 1 is source 2 value
+			 * ...stack 2 is mask value
+			 * ...stack 3 is count
+			 */
+			if (altera_check_stack(stack_ptr, 4, &status)) {
+				s32 a = stack[--stack_ptr];
+				s32 b = stack[--stack_ptr];
+				long_tmp = stack[--stack_ptr];
+				count = stack[stack_ptr - 1];
+
+				if ((count < 1) || (count > 32))
+					status = -ERANGE;
+				else {
+					long_tmp &= ((-1L) >> (32 - count));
+
+					stack[stack_ptr - 1] =
+					((a & long_tmp) == (b & long_tmp))
+								? 1L : 0L;
+				}
+			}
+			break;
+		case OP_PINT:
+			/*
+			 * PRINT add integer
+			 * ...stack 0 is integer value
+			 */
+			if (!altera_check_stack(stack_ptr, 1, &status))
+				break;
+			sprintf(&msg_buff[strlen(msg_buff)],
+					"%ld", stack[--stack_ptr]);
+			break;
+		case OP_PRNT:
+			/* PRINT finish */
+			if (debug)
+				printk(msg_buff, "\n");
+
+			msg_buff[0] = '\0';
+			break;
+		case OP_DSS:
+			/*
+			 * DRSCAN short
+			 * ...stack 0 is scan data
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			long_tmp = stack[--stack_ptr];
+			count = stack[--stack_ptr];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_drscan(astate, count, charbuf, 0);
+			break;
+		case OP_DSSC:
+			/*
+			 * DRSCAN short with capture
+			 * ...stack 0 is scan data
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			long_tmp = stack[--stack_ptr];
+			count = stack[stack_ptr - 1];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_swap_dr(astate, count, charbuf,
+							0, charbuf, 0);
+			stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]);
+			break;
+		case OP_ISS:
+			/*
+			 * IRSCAN short
+			 * ...stack 0 is scan data
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			long_tmp = stack[--stack_ptr];
+			count = stack[--stack_ptr];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_irscan(astate, count, charbuf, 0);
+			break;
+		case OP_ISSC:
+			/*
+			 * IRSCAN short with capture
+			 * ...stack 0 is scan data
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			long_tmp = stack[--stack_ptr];
+			count = stack[stack_ptr - 1];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_swap_ir(astate, count, charbuf,
+							0, charbuf, 0);
+			stack[stack_ptr - 1] = get_unaligned_le32(&charbuf[0]);
+			break;
+		case OP_DPR:
+			if (!altera_check_stack(stack_ptr, 1, &status))
+				break;
+			count = stack[--stack_ptr];
+			status = altera_set_dr_pre(&astate->js, count, 0, NULL);
+			break;
+		case OP_DPRL:
+			/*
+			 * DRPRE with literal data
+			 * ...stack 0 is count
+			 * ...stack 1 is literal data
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			count = stack[--stack_ptr];
+			long_tmp = stack[--stack_ptr];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_set_dr_pre(&astate->js, count, 0,
+						charbuf);
+			break;
+		case OP_DPO:
+			/*
+			 * DRPOST
+			 * ...stack 0 is count
+			 */
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				count = stack[--stack_ptr];
+				status = altera_set_dr_post(&astate->js, count,
+								0, NULL);
+			}
+			break;
+		case OP_DPOL:
+			/*
+			 * DRPOST with literal data
+			 * ...stack 0 is count
+			 * ...stack 1 is literal data
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			count = stack[--stack_ptr];
+			long_tmp = stack[--stack_ptr];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_set_dr_post(&astate->js, count, 0,
+							charbuf);
+			break;
+		case OP_IPR:
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				count = stack[--stack_ptr];
+				status = altera_set_ir_pre(&astate->js, count,
+								0, NULL);
+			}
+			break;
+		case OP_IPRL:
+			/*
+			 * IRPRE with literal data
+			 * ...stack 0 is count
+			 * ...stack 1 is literal data
+			 */
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				count = stack[--stack_ptr];
+				long_tmp = stack[--stack_ptr];
+				put_unaligned_le32(long_tmp, &charbuf[0]);
+				status = altera_set_ir_pre(&astate->js, count,
+							0, charbuf);
+			}
+			break;
+		case OP_IPO:
+			/*
+			 * IRPOST
+			 * ...stack 0 is count
+			 */
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				count = stack[--stack_ptr];
+				status = altera_set_ir_post(&astate->js, count,
+							0, NULL);
+			}
+			break;
+		case OP_IPOL:
+			/*
+			 * IRPOST with literal data
+			 * ...stack 0 is count
+			 * ...stack 1 is literal data
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			count = stack[--stack_ptr];
+			long_tmp = stack[--stack_ptr];
+			put_unaligned_le32(long_tmp, &charbuf[0]);
+			status = altera_set_ir_post(&astate->js, count, 0,
+							charbuf);
+			break;
+		case OP_PCHR:
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				u8 ch;
+				count = strlen(msg_buff);
+				ch = (char) stack[--stack_ptr];
+				if ((ch < 1) || (ch > 127)) {
+					/*
+					 * character code out of range
+					 * instead of flagging an error,
+					 * force the value to 127
+					 */
+					ch = 127;
+				}
+				msg_buff[count] = ch;
+				msg_buff[count + 1] = '\0';
+			}
+			break;
+		case OP_EXIT:
+			if (altera_check_stack(stack_ptr, 1, &status))
+				*exit_code = stack[--stack_ptr];
+
+			done = 1;
+			break;
+		case OP_EQU:
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			--stack_ptr;
+			stack[stack_ptr - 1] =
+				(stack[stack_ptr - 1] == stack[stack_ptr]) ?
+									1L : 0L;
+			break;
+		case OP_POPT:
+			if (altera_check_stack(stack_ptr, 1, &status))
+				--stack_ptr;
+
+			break;
+		case OP_ABS:
+			if (!altera_check_stack(stack_ptr, 1, &status))
+				break;
+			if (stack[stack_ptr - 1] < 0)
+				stack[stack_ptr - 1] = 0 - stack[stack_ptr - 1];
+
+			break;
+		case OP_BCH0:
+			/*
+			 * Batch operation 0
+			 * SWP
+			 * SWPN 7
+			 * SWP
+			 * SWPN 6
+			 * DUPN 8
+			 * SWPN 2
+			 * SWP
+			 * DUPN 6
+			 * DUPN 6
+			 */
+
+			/* SWP  */
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				long_tmp = stack[stack_ptr - 2];
+				stack[stack_ptr - 2] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+
+			/* SWPN 7 */
+			index = 7 + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				long_tmp = stack[stack_ptr - index];
+				stack[stack_ptr - index] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+
+			/* SWP  */
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				long_tmp = stack[stack_ptr - 2];
+				stack[stack_ptr - 2] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+
+			/* SWPN 6 */
+			index = 6 + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				long_tmp = stack[stack_ptr - index];
+				stack[stack_ptr - index] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+
+			/* DUPN 8 */
+			index = 8 + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				stack[stack_ptr] = stack[stack_ptr - index];
+				++stack_ptr;
+			}
+
+			/* SWPN 2 */
+			index = 2 + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				long_tmp = stack[stack_ptr - index];
+				stack[stack_ptr - index] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+
+			/* SWP  */
+			if (altera_check_stack(stack_ptr, 2, &status)) {
+				long_tmp = stack[stack_ptr - 2];
+				stack[stack_ptr - 2] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+
+			/* DUPN 6 */
+			index = 6 + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				stack[stack_ptr] = stack[stack_ptr - index];
+				++stack_ptr;
+			}
+
+			/* DUPN 6 */
+			index = 6 + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				stack[stack_ptr] = stack[stack_ptr - index];
+				++stack_ptr;
+			}
+			break;
+		case OP_PSH0:
+			stack[stack_ptr++] = 0;
+			break;
+		case OP_PSHL:
+			stack[stack_ptr++] = (s32) args[0];
+			break;
+		case OP_PSHV:
+			stack[stack_ptr++] = vars[args[0]];
+			break;
+		case OP_JMP:
+			pc = args[0] + code_sect;
+			if ((pc < code_sect) || (pc >= debug_sect))
+				status = -ERANGE;
+			break;
+		case OP_CALL:
+			stack[stack_ptr++] = pc;
+			pc = args[0] + code_sect;
+			if ((pc < code_sect) || (pc >= debug_sect))
+				status = -ERANGE;
+			break;
+		case OP_NEXT:
+			/*
+			 * Process FOR / NEXT loop
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is step value
+			 * ...stack 1 is end value
+			 * ...stack 2 is top address
+			 */
+			if (altera_check_stack(stack_ptr, 3, &status)) {
+				s32 step = stack[stack_ptr - 1];
+				s32 end = stack[stack_ptr - 2];
+				s32 top = stack[stack_ptr - 3];
+				s32 iterator = vars[args[0]];
+				int break_out = 0;
+
+				if (step < 0) {
+					if (iterator <= end)
+						break_out = 1;
+				} else if (iterator >= end)
+					break_out = 1;
+
+				if (break_out) {
+					stack_ptr -= 3;
+				} else {
+					vars[args[0]] = iterator + step;
+					pc = top + code_sect;
+					if ((pc < code_sect) ||
+					    (pc >= debug_sect))
+						status = -ERANGE;
+				}
+			}
+			break;
+		case OP_PSTR:
+			/*
+			 * PRINT add string
+			 * ...argument 0 is string ID
+			 */
+			count = strlen(msg_buff);
+			strlcpy(&msg_buff[count],
+				&p[str_table + args[0]],
+				ALTERA_MESSAGE_LENGTH - count);
+			break;
+		case OP_SINT:
+			/*
+			 * STATE intermediate state
+			 * ...argument 0 is state code
+			 */
+			status = altera_goto_jstate(astate, args[0]);
+			break;
+		case OP_ST:
+			/*
+			 * STATE final state
+			 * ...argument 0 is state code
+			 */
+			status = altera_goto_jstate(astate, args[0]);
+			break;
+		case OP_ISTP:
+			/*
+			 * IRSTOP state
+			 * ...argument 0 is state code
+			 */
+			status = altera_set_irstop(&astate->js, args[0]);
+			break;
+		case OP_DSTP:
+			/*
+			 * DRSTOP state
+			 * ...argument 0 is state code
+			 */
+			status = altera_set_drstop(&astate->js, args[0]);
+			break;
+
+		case OP_SWPN:
+			/*
+			 * Exchange top with Nth stack value
+			 * ...argument 0 is 0-based stack entry
+			 * to swap with top element
+			 */
+			index = (args[0]) + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				long_tmp = stack[stack_ptr - index];
+				stack[stack_ptr - index] = stack[stack_ptr - 1];
+				stack[stack_ptr - 1] = long_tmp;
+			}
+			break;
+		case OP_DUPN:
+			/*
+			 * Duplicate Nth stack value
+			 * ...argument 0 is 0-based stack entry to duplicate
+			 */
+			index = (args[0]) + 1;
+			if (altera_check_stack(stack_ptr, index, &status)) {
+				stack[stack_ptr] = stack[stack_ptr - index];
+				++stack_ptr;
+			}
+			break;
+		case OP_POPV:
+			/*
+			 * Pop stack into scalar variable
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is value
+			 */
+			if (altera_check_stack(stack_ptr, 1, &status))
+				vars[args[0]] = stack[--stack_ptr];
+
+			break;
+		case OP_POPE:
+			/*
+			 * Pop stack into integer array element
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is array index
+			 * ...stack 1 is value
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			variable_id = args[0];
+
+			/*
+			 * If variable is read-only,
+			 * convert to writable array
+			 */
+			if ((version > 0) &&
+				((attrs[variable_id] & 0x9c) == 0x1c)) {
+				/* Allocate a writable buffer for this array */
+				count = var_size[variable_id];
+				long_tmp = vars[variable_id];
+				longptr_tmp = kzalloc(count * sizeof(long),
+								GFP_KERNEL);
+				vars[variable_id] = (long)longptr_tmp;
+
+				if (vars[variable_id] == 0) {
+					status = -ENOMEM;
+					break;
+				}
+
+				/* copy previous contents into buffer */
+				for (i = 0; i < count; ++i) {
+					longptr_tmp[i] =
+						get_unaligned_be32(&p[long_tmp]);
+					long_tmp += sizeof(long);
+				}
+
+				/*
+				 * set bit 7 - buffer was
+				 * dynamically allocated
+				 */
+				attrs[variable_id] |= 0x80;
+
+				/* clear bit 2 - variable is writable */
+				attrs[variable_id] &= ~0x04;
+				attrs[variable_id] |= 0x01;
+
+			}
+
+			/* check that variable is a writable integer array */
+			if ((attrs[variable_id] & 0x1c) != 0x18)
+				status = -ERANGE;
+			else {
+				longptr_tmp = (long *)vars[variable_id];
+
+				/* pop the array index */
+				index = stack[--stack_ptr];
+
+				/* pop the value and store it into the array */
+				longptr_tmp[index] = stack[--stack_ptr];
+			}
+
+			break;
+		case OP_POPA:
+			/*
+			 * Pop stack into Boolean array
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is count
+			 * ...stack 1 is array index
+			 * ...stack 2 is value
+			 */
+			if (!altera_check_stack(stack_ptr, 3, &status))
+				break;
+			variable_id = args[0];
+
+			/*
+			 * If variable is read-only,
+			 * convert to writable array
+			 */
+			if ((version > 0) &&
+				((attrs[variable_id] & 0x9c) == 0x0c)) {
+				/* Allocate a writable buffer for this array */
+				long_tmp =
+					(var_size[variable_id] + 7L) >> 3L;
+				charptr_tmp2 = (u8 *)vars[variable_id];
+				charptr_tmp =
+					kzalloc(long_tmp, GFP_KERNEL);
+				vars[variable_id] = (long)charptr_tmp;
+
+				if (vars[variable_id] == 0) {
+					status = -ENOMEM;
+					break;
+				}
+
+				/* zero the buffer */
+				for (long_idx = 0L;
+					long_idx < long_tmp;
+					++long_idx) {
+					charptr_tmp[long_idx] = 0;
+				}
+
+				/* copy previous contents into buffer */
+				for (long_idx = 0L;
+					long_idx < var_size[variable_id];
+					++long_idx) {
+					long_idx2 = long_idx;
+
+					if (charptr_tmp2[long_idx2 >> 3] &
+						(1 << (long_idx2 & 7))) {
+						charptr_tmp[long_idx >> 3] |=
+							(1 << (long_idx & 7));
+					}
+				}
+
+				/*
+				 * set bit 7 - buffer was
+				 * dynamically allocated
+				 */
+				attrs[variable_id] |= 0x80;
+
+				/* clear bit 2 - variable is writable */
+				attrs[variable_id] &= ~0x04;
+				attrs[variable_id] |= 0x01;
+
+			}
+
+			/*
+			 * check that variable is
+			 * a writable Boolean array
+			 */
+			if ((attrs[variable_id] & 0x1c) != 0x08) {
+				status = -ERANGE;
+				break;
+			}
+
+			charptr_tmp = (u8 *)vars[variable_id];
+
+			/* pop the count (number of bits to copy) */
+			long_count = stack[--stack_ptr];
+
+			/* pop the array index */
+			long_idx = stack[--stack_ptr];
+
+			reverse = 0;
+
+			if (version > 0) {
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 */
+
+				if (long_idx > long_count) {
+					reverse = 1;
+					long_tmp = long_count;
+					long_count = 1 + long_idx -
+								long_count;
+					long_idx = long_tmp;
+
+					/* reverse POPA is not supported */
+					status = -ERANGE;
+					break;
+				} else
+					long_count = 1 + long_count -
+								long_idx;
+
+			}
+
+			/* pop the data */
+			long_tmp = stack[--stack_ptr];
+
+			if (long_count < 1) {
+				status = -ERANGE;
+				break;
+			}
+
+			for (i = 0; i < long_count; ++i) {
+				if (long_tmp & (1L << (s32) i))
+					charptr_tmp[long_idx >> 3L] |=
+						(1L << (long_idx & 7L));
+				else
+					charptr_tmp[long_idx >> 3L] &=
+						~(1L << (long_idx & 7L));
+
+				++long_idx;
+			}
+
+			break;
+		case OP_JMPZ:
+			/*
+			 * Pop stack and branch if zero
+			 * ...argument 0 is address
+			 * ...stack 0 is condition value
+			 */
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				if (stack[--stack_ptr] == 0) {
+					pc = args[0] + code_sect;
+					if ((pc < code_sect) ||
+					    (pc >= debug_sect))
+						status = -ERANGE;
+				}
+			}
+			break;
+		case OP_DS:
+		case OP_IS:
+			/*
+			 * DRSCAN
+			 * IRSCAN
+			 * ...argument 0 is scan data variable ID
+			 * ...stack 0 is array index
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			long_idx = stack[--stack_ptr];
+			long_count = stack[--stack_ptr];
+			reverse = 0;
+			if (version > 0) {
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 * stack 2 = count
+				 */
+				long_tmp = long_count;
+				long_count = stack[--stack_ptr];
+
+				if (long_idx > long_tmp) {
+					reverse = 1;
+					long_idx = long_tmp;
+				}
+			}
+
+			charptr_tmp = (u8 *)vars[args[0]];
+
+			if (reverse) {
+				/*
+				 * allocate a buffer
+				 * and reverse the data order
+				 */
+				charptr_tmp2 = charptr_tmp;
+				charptr_tmp = kzalloc((long_count >> 3) + 1,
+								GFP_KERNEL);
+				if (charptr_tmp == NULL) {
+					status = -ENOMEM;
+					break;
+				}
+
+				long_tmp = long_idx + long_count - 1;
+				long_idx2 = 0;
+				while (long_idx2 < long_count) {
+					if (charptr_tmp2[long_tmp >> 3] &
+							(1 << (long_tmp & 7)))
+						charptr_tmp[long_idx2 >> 3] |=
+							(1 << (long_idx2 & 7));
+					else
+						charptr_tmp[long_idx2 >> 3] &=
+							~(1 << (long_idx2 & 7));
+
+					--long_tmp;
+					++long_idx2;
+				}
+			}
+
+			if (opcode == 0x51) /* DS */
+				status = altera_drscan(astate, long_count,
+						charptr_tmp, long_idx);
+			else /* IS */
+				status = altera_irscan(astate, long_count,
+						charptr_tmp, long_idx);
+
+			if (reverse)
+				kfree(charptr_tmp);
+
+			break;
+		case OP_DPRA:
+			/*
+			 * DRPRE with array data
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is array index
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			index = stack[--stack_ptr];
+			count = stack[--stack_ptr];
+
+			if (version > 0)
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 */
+				count = 1 + count - index;
+
+			charptr_tmp = (u8 *)vars[args[0]];
+			status = altera_set_dr_pre(&astate->js, count, index,
+							charptr_tmp);
+			break;
+		case OP_DPOA:
+			/*
+			 * DRPOST with array data
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is array index
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			index = stack[--stack_ptr];
+			count = stack[--stack_ptr];
+
+			if (version > 0)
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 */
+				count = 1 + count - index;
+
+			charptr_tmp = (u8 *)vars[args[0]];
+			status = altera_set_dr_post(&astate->js, count, index,
+							charptr_tmp);
+			break;
+		case OP_IPRA:
+			/*
+			 * IRPRE with array data
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is array index
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			index = stack[--stack_ptr];
+			count = stack[--stack_ptr];
+
+			if (version > 0)
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 */
+				count = 1 + count - index;
+
+			charptr_tmp = (u8 *)vars[args[0]];
+			status = altera_set_ir_pre(&astate->js, count, index,
+							charptr_tmp);
+
+			break;
+		case OP_IPOA:
+			/*
+			 * IRPOST with array data
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is array index
+			 * ...stack 1 is count
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			index = stack[--stack_ptr];
+			count = stack[--stack_ptr];
+
+			if (version > 0)
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 */
+				count = 1 + count - index;
+
+			charptr_tmp = (u8 *)vars[args[0]];
+			status = altera_set_ir_post(&astate->js, count, index,
+							charptr_tmp);
+
+			break;
+		case OP_EXPT:
+			/*
+			 * EXPORT
+			 * ...argument 0 is string ID
+			 * ...stack 0 is integer expression
+			 */
+			if (altera_check_stack(stack_ptr, 1, &status)) {
+				name = &p[str_table + args[0]];
+				long_tmp = stack[--stack_ptr];
+				altera_export_int(name, long_tmp);
+			}
+			break;
+		case OP_PSHE:
+			/*
+			 * Push integer array element
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is array index
+			 */
+			if (!altera_check_stack(stack_ptr, 1, &status))
+				break;
+			variable_id = args[0];
+			index = stack[stack_ptr - 1];
+
+			/* check variable type */
+			if ((attrs[variable_id] & 0x1f) == 0x19) {
+				/* writable integer array */
+				longptr_tmp = (long *)vars[variable_id];
+				stack[stack_ptr - 1] = longptr_tmp[index];
+			} else if ((attrs[variable_id] & 0x1f) == 0x1c) {
+				/* read-only integer array */
+				long_tmp = vars[variable_id] +
+						(index * sizeof(long));
+				stack[stack_ptr - 1] =
+					get_unaligned_be32(&p[long_tmp]);
+			} else
+				status = -ERANGE;
+
+			break;
+		case OP_PSHA:
+			/*
+			 * Push Boolean array
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is count
+			 * ...stack 1 is array index
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			variable_id = args[0];
+
+			/* check that variable is a Boolean array */
+			if ((attrs[variable_id] & 0x18) != 0x08) {
+				status = -ERANGE;
+				break;
+			}
+
+			charptr_tmp = (u8 *)vars[variable_id];
+
+			/* pop the count (number of bits to copy) */
+			count = stack[--stack_ptr];
+
+			/* pop the array index */
+			index = stack[stack_ptr - 1];
+
+			if (version > 0)
+				/*
+				 * stack 0 = array right index
+				 * stack 1 = array left index
+				 */
+				count = 1 + count - index;
+
+			if ((count < 1) || (count > 32)) {
+				status = -ERANGE;
+				break;
+			}
+
+			long_tmp = 0L;
+
+			for (i = 0; i < count; ++i)
+				if (charptr_tmp[(i + index) >> 3] &
+						(1 << ((i + index) & 7)))
+					long_tmp |= (1L << i);
+
+			stack[stack_ptr - 1] = long_tmp;
+
+			break;
+		case OP_DYNA:
+			/*
+			 * Dynamically change size of array
+			 * ...argument 0 is variable ID
+			 * ...stack 0 is new size
+			 */
+			if (!altera_check_stack(stack_ptr, 1, &status))
+				break;
+			variable_id = args[0];
+			long_tmp = stack[--stack_ptr];
+
+			if (long_tmp > var_size[variable_id]) {
+				var_size[variable_id] = long_tmp;
+
+				if (attrs[variable_id] & 0x10)
+					/* allocate integer array */
+					long_tmp *= sizeof(long);
+				else
+					/* allocate Boolean array */
+					long_tmp = (long_tmp + 7) >> 3;
+
+				/*
+				 * If the buffer was previously allocated,
+				 * free it
+				 */
+				if (attrs[variable_id] & 0x80) {
+					kfree((void *)vars[variable_id]);
+					vars[variable_id] = 0;
+				}
+
+				/*
+				 * Allocate a new buffer
+				 * of the requested size
+				 */
+				vars[variable_id] = (long)
+					kzalloc(long_tmp, GFP_KERNEL);
+
+				if (vars[variable_id] == 0) {
+					status = -ENOMEM;
+					break;
+				}
+
+				/*
+				 * Set the attribute bit to indicate that
+				 * this buffer was dynamically allocated and
+				 * should be freed later
+				 */
+				attrs[variable_id] |= 0x80;
+
+				/* zero out memory */
+				count = ((var_size[variable_id] + 7L) /
+									8L);
+				charptr_tmp = (u8 *)(vars[variable_id]);
+				for (index = 0; index < count; ++index)
+					charptr_tmp[index] = 0;
+
+			}
+
+			break;
+		case OP_EXPV:
+			/*
+			 * Export Boolean array
+			 * ...argument 0 is string ID
+			 * ...stack 0 is variable ID
+			 * ...stack 1 is array right index
+			 * ...stack 2 is array left index
+			 */
+			if (!altera_check_stack(stack_ptr, 3, &status))
+				break;
+			if (version == 0) {
+				/* EXPV is not supported in JBC 1.0 */
+				bad_opcode = 1;
+				break;
+			}
+			name = &p[str_table + args[0]];
+			variable_id = stack[--stack_ptr];
+			long_idx = stack[--stack_ptr];/* right indx */
+			long_idx2 = stack[--stack_ptr];/* left indx */
+
+			if (long_idx > long_idx2) {
+				/* reverse indices not supported */
+				status = -ERANGE;
+				break;
+			}
+
+			long_count = 1 + long_idx2 - long_idx;
+
+			charptr_tmp = (u8 *)vars[variable_id];
+			charptr_tmp2 = NULL;
+
+			if ((long_idx & 7L) != 0) {
+				s32 k = long_idx;
+				charptr_tmp2 =
+					kzalloc(((long_count + 7L) / 8L),
+							GFP_KERNEL);
+				if (charptr_tmp2 == NULL) {
+					status = -ENOMEM;
+					break;
+				}
+
+				for (i = 0; i < long_count; ++i) {
+					if (charptr_tmp[k >> 3] &
+							(1 << (k & 7)))
+						charptr_tmp2[i >> 3] |=
+								(1 << (i & 7));
+					else
+						charptr_tmp2[i >> 3] &=
+								~(1 << (i & 7));
+
+					++k;
+				}
+				charptr_tmp = charptr_tmp2;
+
+			} else if (long_idx != 0)
+				charptr_tmp = &charptr_tmp[long_idx >> 3];
+
+			altera_export_bool_array(name, charptr_tmp,
+							long_count);
+
+			/* free allocated buffer */
+			if ((long_idx & 7L) != 0)
+				kfree(charptr_tmp2);
+
+			break;
+		case OP_COPY: {
+			/*
+			 * Array copy
+			 * ...argument 0 is dest ID
+			 * ...argument 1 is source ID
+			 * ...stack 0 is count
+			 * ...stack 1 is dest index
+			 * ...stack 2 is source index
+			 */
+			s32 copy_count;
+			s32 copy_index;
+			s32 copy_index2;
+			s32 destleft;
+			s32 src_count;
+			s32 dest_count;
+			int src_reverse = 0;
+			int dest_reverse = 0;
+
+			if (!altera_check_stack(stack_ptr, 3, &status))
+				break;
+
+			copy_count = stack[--stack_ptr];
+			copy_index = stack[--stack_ptr];
+			copy_index2 = stack[--stack_ptr];
+			reverse = 0;
+
+			if (version > 0) {
+				/*
+				 * stack 0 = source right index
+				 * stack 1 = source left index
+				 * stack 2 = destination right index
+				 * stack 3 = destination left index
+				 */
+				destleft = stack[--stack_ptr];
+
+				if (copy_count > copy_index) {
+					src_reverse = 1;
+					reverse = 1;
+					src_count = 1 + copy_count - copy_index;
+					/* copy_index = source start index */
+				} else {
+					src_count = 1 + copy_index - copy_count;
+					/* source start index */
+					copy_index = copy_count;
+				}
+
+				if (copy_index2 > destleft) {
+					dest_reverse = 1;
+					reverse = !reverse;
+					dest_count = 1 + copy_index2 - destleft;
+					/* destination start index */
+					copy_index2 = destleft;
+				} else
+					dest_count = 1 + destleft - copy_index2;
+
+				copy_count = (src_count < dest_count) ?
+							src_count : dest_count;
+
+				if ((src_reverse || dest_reverse) &&
+					(src_count != dest_count))
+					/*
+					 * If either the source or destination
+					 * is reversed, we can't tolerate
+					 * a length mismatch, because we
+					 * "left justify" arrays when copying.
+					 * This won't work correctly
+					 * with reversed arrays.
+					 */
+					status = -ERANGE;
+
+			}
+
+			count = copy_count;
+			index = copy_index;
+			index2 = copy_index2;
+
+			/*
+			 * If destination is a read-only array,
+			 * allocate a buffer and convert it to a writable array
+			 */
+			variable_id = args[1];
+			if ((version > 0) &&
+				((attrs[variable_id] & 0x9c) == 0x0c)) {
+				/* Allocate a writable buffer for this array */
+				long_tmp =
+					(var_size[variable_id] + 7L) >> 3L;
+				charptr_tmp2 = (u8 *)vars[variable_id];
+				charptr_tmp =
+					kzalloc(long_tmp, GFP_KERNEL);
+				vars[variable_id] = (long)charptr_tmp;
+
+				if (vars[variable_id] == 0) {
+					status = -ENOMEM;
+					break;
+				}
+
+				/* zero the buffer */
+				for (long_idx = 0L; long_idx < long_tmp;
+								++long_idx)
+					charptr_tmp[long_idx] = 0;
+
+				/* copy previous contents into buffer */
+				for (long_idx = 0L;
+					long_idx < var_size[variable_id];
+								++long_idx) {
+					long_idx2 = long_idx;
+
+					if (charptr_tmp2[long_idx2 >> 3] &
+						(1 << (long_idx2 & 7)))
+						charptr_tmp[long_idx >> 3] |=
+							(1 << (long_idx & 7));
+
+				}
+
+				/*
+				set bit 7 - buffer was dynamically allocated */
+				attrs[variable_id] |= 0x80;
+
+				/* clear bit 2 - variable is writable */
+				attrs[variable_id] &= ~0x04;
+				attrs[variable_id] |= 0x01;
+			}
+
+			charptr_tmp = (u8 *)vars[args[1]];
+			charptr_tmp2 = (u8 *)vars[args[0]];
+
+			/* check if destination is a writable Boolean array */
+			if ((attrs[args[1]] & 0x1c) != 0x08) {
+				status = -ERANGE;
+				break;
+			}
+
+			if (count < 1) {
+				status = -ERANGE;
+				break;
+			}
+
+			if (reverse)
+				index2 += (count - 1);
+
+			for (i = 0; i < count; ++i) {
+				if (charptr_tmp2[index >> 3] &
+							(1 << (index & 7)))
+					charptr_tmp[index2 >> 3] |=
+							(1 << (index2 & 7));
+				else
+					charptr_tmp[index2 >> 3] &=
+						~(1 << (index2 & 7));
+
+				++index;
+				if (reverse)
+					--index2;
+				else
+					++index2;
+			}
+
+			break;
+		}
+		case OP_DSC:
+		case OP_ISC: {
+			/*
+			 * DRSCAN with capture
+			 * IRSCAN with capture
+			 * ...argument 0 is scan data variable ID
+			 * ...argument 1 is capture variable ID
+			 * ...stack 0 is capture index
+			 * ...stack 1 is scan data index
+			 * ...stack 2 is count
+			 */
+			s32 scan_right, scan_left;
+			s32 capture_count = 0;
+			s32 scan_count = 0;
+			s32 capture_index;
+			s32 scan_index;
+
+			if (!altera_check_stack(stack_ptr, 3, &status))
+				break;
+
+			capture_index = stack[--stack_ptr];
+			scan_index = stack[--stack_ptr];
+
+			if (version > 0) {
+				/*
+				 * stack 0 = capture right index
+				 * stack 1 = capture left index
+				 * stack 2 = scan right index
+				 * stack 3 = scan left index
+				 * stack 4 = count
+				 */
+				scan_right = stack[--stack_ptr];
+				scan_left = stack[--stack_ptr];
+				capture_count = 1 + scan_index - capture_index;
+				scan_count = 1 + scan_left - scan_right;
+				scan_index = scan_right;
+			}
+
+			long_count = stack[--stack_ptr];
+			/*
+			 * If capture array is read-only, allocate a buffer
+			 * and convert it to a writable array
+			 */
+			variable_id = args[1];
+			if ((version > 0) &&
+				((attrs[variable_id] & 0x9c) == 0x0c)) {
+				/* Allocate a writable buffer for this array */
+				long_tmp =
+					(var_size[variable_id] + 7L) >> 3L;
+				charptr_tmp2 = (u8 *)vars[variable_id];
+				charptr_tmp =
+					kzalloc(long_tmp, GFP_KERNEL);
+				vars[variable_id] = (long)charptr_tmp;
+
+				if (vars[variable_id] == 0) {
+					status = -ENOMEM;
+					break;
+				}
+
+				/* zero the buffer */
+				for (long_idx = 0L; long_idx < long_tmp;
+								++long_idx)
+					charptr_tmp[long_idx] = 0;
+
+				/* copy previous contents into buffer */
+				for (long_idx = 0L;
+					long_idx < var_size[variable_id];
+								++long_idx) {
+					long_idx2 = long_idx;
+
+					if (charptr_tmp2[long_idx2 >> 3] &
+						(1 << (long_idx2 & 7)))
+						charptr_tmp[long_idx >> 3] |=
+							(1 << (long_idx & 7));
+
+				}
+
+				/*
+				 * set bit 7 - buffer was
+				 * dynamically allocated
+				 */
+				attrs[variable_id] |= 0x80;
+
+				/* clear bit 2 - variable is writable */
+				attrs[variable_id] &= ~0x04;
+				attrs[variable_id] |= 0x01;
+
+			}
+
+			charptr_tmp = (u8 *)vars[args[0]];
+			charptr_tmp2 = (u8 *)vars[args[1]];
+
+			if ((version > 0) &&
+					((long_count > capture_count) ||
+					(long_count > scan_count))) {
+				status = -ERANGE;
+				break;
+			}
+
+			/*
+			 * check that capture array
+			 * is a writable Boolean array
+			 */
+			if ((attrs[args[1]] & 0x1c) != 0x08) {
+				status = -ERANGE;
+				break;
+			}
+
+			if (status == 0) {
+				if (opcode == 0x82) /* DSC */
+					status = altera_swap_dr(astate,
+							long_count,
+							charptr_tmp,
+							scan_index,
+							charptr_tmp2,
+							capture_index);
+				else /* ISC */
+					status = altera_swap_ir(astate,
+							long_count,
+							charptr_tmp,
+							scan_index,
+							charptr_tmp2,
+							capture_index);
+
+			}
+
+			break;
+		}
+		case OP_WAIT:
+			/*
+			 * WAIT
+			 * ...argument 0 is wait state
+			 * ...argument 1 is end state
+			 * ...stack 0 is cycles
+			 * ...stack 1 is microseconds
+			 */
+			if (!altera_check_stack(stack_ptr, 2, &status))
+				break;
+			long_tmp = stack[--stack_ptr];
+
+			if (long_tmp != 0L)
+				status = altera_wait_cycles(astate, long_tmp,
+								args[0]);
+
+			long_tmp = stack[--stack_ptr];
+
+			if ((status == 0) && (long_tmp != 0L))
+				status = altera_wait_msecs(astate,
+								long_tmp,
+								args[0]);
+
+			if ((status == 0) && (args[1] != args[0]))
+				status = altera_goto_jstate(astate,
+								args[1]);
+
+			if (version > 0) {
+				--stack_ptr; /* throw away MAX cycles */
+				--stack_ptr; /* throw away MAX microseconds */
+			}
+			break;
+		case OP_CMPA: {
+			/*
+			 * Array compare
+			 * ...argument 0 is source 1 ID
+			 * ...argument 1 is source 2 ID
+			 * ...argument 2 is mask ID
+			 * ...stack 0 is source 1 index
+			 * ...stack 1 is source 2 index
+			 * ...stack 2 is mask index
+			 * ...stack 3 is count
+			 */
+			s32 a, b;
+			u8 *source1 = (u8 *)vars[args[0]];
+			u8 *source2 = (u8 *)vars[args[1]];
+			u8 *mask = (u8 *)vars[args[2]];
+			u32 index1;
+			u32 index2;
+			u32 mask_index;
+
+			if (!altera_check_stack(stack_ptr, 4, &status))
+				break;
+
+			index1 = stack[--stack_ptr];
+			index2 = stack[--stack_ptr];
+			mask_index = stack[--stack_ptr];
+			long_count = stack[--stack_ptr];
+
+			if (version > 0) {
+				/*
+				 * stack 0 = source 1 right index
+				 * stack 1 = source 1 left index
+				 * stack 2 = source 2 right index
+				 * stack 3 = source 2 left index
+				 * stack 4 = mask right index
+				 * stack 5 = mask left index
+				 */
+				s32 mask_right = stack[--stack_ptr];
+				s32 mask_left = stack[--stack_ptr];
+				/* source 1 count */
+				a = 1 + index2 - index1;
+				/* source 2 count */
+				b = 1 + long_count - mask_index;
+				a = (a < b) ? a : b;
+				/* mask count */
+				b = 1 + mask_left - mask_right;
+				a = (a < b) ? a : b;
+				/* source 2 start index */
+				index2 = mask_index;
+				/* mask start index */
+				mask_index = mask_right;
+				long_count = a;
+			}
+
+			long_tmp = 1L;
+
+			if (long_count < 1)
+				status = -ERANGE;
+			else {
+				count = long_count;
+
+				for (i = 0; i < count; ++i) {
+					if (mask[mask_index >> 3] &
+						(1 << (mask_index & 7))) {
+						a = source1[index1 >> 3] &
+							(1 << (index1 & 7))
+								? 1 : 0;
+						b = source2[index2 >> 3] &
+							(1 << (index2 & 7))
+								? 1 : 0;
+
+						if (a != b) /* failure */
+							long_tmp = 0L;
+					}
+					++index1;
+					++index2;
+					++mask_index;
+				}
+			}
+
+			stack[stack_ptr++] = long_tmp;
+
+			break;
+		}
+		default:
+			/* Unrecognized opcode -- ERROR! */
+			bad_opcode = 1;
+			break;
+		}
+
+		if (bad_opcode)
+			status = -ENOSYS;
+
+		if ((stack_ptr < 0) || (stack_ptr >= ALTERA_STACK_SIZE))
+			status = -EOVERFLOW;
+
+		if (status != 0) {
+			done = 1;
+			*error_address = (s32)(opcode_address - code_sect);
+		}
+	}
+
+	altera_free_buffers(astate);
+
+	/* Free all dynamically allocated arrays */
+	if ((attrs != NULL) && (vars != NULL))
+		for (i = 0; i < sym_count; ++i)
+			if (attrs[i] & 0x80)
+				kfree((void *)vars[i]);
+
+	kfree(vars);
+	kfree(var_size);
+	kfree(attrs);
+	kfree(proc_attributes);
+
+	return status;
+}
+
+static int altera_get_note(u8 *p, s32 program_size,
+			s32 *offset, char *key, char *value, int length)
+/*
+ * Gets key and value of NOTE fields in the JBC file.
+ * Can be called in two modes:  if offset pointer is NULL,
+ * then the function searches for note fields which match
+ * the key string provided.  If offset is not NULL, then
+ * the function finds the next note field of any key,
+ * starting at the offset specified by the offset pointer.
+ * Returns 0 for success, else appropriate error code
+ */
+{
+	int status = -ENODATA;
+	u32 note_strings = 0L;
+	u32 note_table = 0L;
+	u32 note_count = 0L;
+	u32 first_word = 0L;
+	int version = 0;
+	int delta = 0;
+	char *key_ptr;
+	char *value_ptr;
+	int i;
+
+	/* Read header information */
+	if (program_size > 52L) {
+		first_word    = get_unaligned_be32(&p[0]);
+		version = (first_word & 1L);
+		delta = version * 8;
+
+		note_strings  = get_unaligned_be32(&p[8 + delta]);
+		note_table    = get_unaligned_be32(&p[12 + delta]);
+		note_count    = get_unaligned_be32(&p[44 + (2 * delta)]);
+	}
+
+	if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L))
+		return -EIO;
+
+	if (note_count <= 0L)
+		return status;
+
+	if (offset == NULL) {
+		/*
+		 * We will search for the first note with a specific key,
+		 * and return only the value
+		 */
+		for (i = 0; (i < note_count) &&
+						(status != 0); ++i) {
+			key_ptr = &p[note_strings +
+					get_unaligned_be32(
+					&p[note_table + (8 * i)])];
+			if ((strnicmp(key, key_ptr, strlen(key_ptr)) == 0) &&
+						(key != NULL)) {
+				status = 0;
+
+				value_ptr = &p[note_strings +
+						get_unaligned_be32(
+						&p[note_table + (8 * i) + 4])];
+
+				if (value != NULL)
+					strlcpy(value, value_ptr, length);
+
+			}
+		}
+	} else {
+		/*
+		 * We will search for the next note, regardless of the key,
+		 * and return both the value and the key
+		 */
+
+		i = *offset;
+
+		if ((i >= 0) && (i < note_count)) {
+			status = 0;
+
+			if (key != NULL)
+				strlcpy(key, &p[note_strings +
+						get_unaligned_be32(
+						&p[note_table + (8 * i)])],
+					length);
+
+			if (value != NULL)
+				strlcpy(value, &p[note_strings +
+						get_unaligned_be32(
+						&p[note_table + (8 * i) + 4])],
+					length);
+
+			*offset = i + 1;
+		}
+	}
+
+	return status;
+}
+
+static int altera_check_crc(u8 *p, s32 program_size)
+{
+	int status = 0;
+	u16 local_expected = 0,
+	    local_actual = 0,
+	    shift_reg = 0xffff;
+	int bit, feedback;
+	u8 databyte;
+	u32 i;
+	u32 crc_section = 0L;
+	u32 first_word = 0L;
+	int version = 0;
+	int delta = 0;
+
+	if (program_size > 52L) {
+		first_word  = get_unaligned_be32(&p[0]);
+		version = (first_word & 1L);
+		delta = version * 8;
+
+		crc_section = get_unaligned_be32(&p[32 + delta]);
+	}
+
+	if ((first_word != 0x4A414D00L) && (first_word != 0x4A414D01L))
+		status = -EIO;
+
+	if (crc_section >= program_size)
+		status = -EIO;
+
+	if (status == 0) {
+		local_expected = (u16)get_unaligned_be16(&p[crc_section]);
+
+		for (i = 0; i < crc_section; ++i) {
+			databyte = p[i];
+			for (bit = 0; bit < 8; bit++) {
+				feedback = (databyte ^ shift_reg) & 0x01;
+				shift_reg >>= 1;
+				if (feedback)
+					shift_reg ^= 0x8408;
+
+				databyte >>= 1;
+			}
+		}
+
+		local_actual = (u16)~shift_reg;
+
+		if (local_expected != local_actual)
+			status = -EILSEQ;
+
+	}
+
+	if (debug || status) {
+		switch (status) {
+		case 0:
+			printk(KERN_INFO "%s: CRC matched: %04x\n", __func__,
+				local_actual);
+			break;
+		case -EILSEQ:
+			printk(KERN_ERR "%s: CRC mismatch: expected %04x, "
+				"actual %04x\n", __func__, local_expected,
+				local_actual);
+			break;
+		case -ENODATA:
+			printk(KERN_ERR "%s: expected CRC not found, "
+				"actual CRC = %04x\n", __func__,
+				local_actual);
+			break;
+		case -EIO:
+			printk(KERN_ERR "%s: error: format isn't "
+				"recognized.\n", __func__);
+			break;
+		default:
+			printk(KERN_ERR "%s: CRC function returned error "
+				"code %d\n", __func__, status);
+			break;
+		}
+	}
+
+	return status;
+}
+
+static int altera_get_file_info(u8 *p,
+					s32 program_size,
+					int *format_version,
+					int *action_count,
+					int *procedure_count)
+{
+	int status = -EIO;
+	u32 first_word = 0;
+	int version = 0;
+
+	if (program_size <= 52L)
+		return status;
+
+	first_word = get_unaligned_be32(&p[0]);
+
+	if ((first_word == 0x4A414D00L) || (first_word == 0x4A414D01L)) {
+		status = 0;
+
+		version = (first_word & 1L);
+		*format_version = version + 1;
+
+		if (version > 0) {
+			*action_count = get_unaligned_be32(&p[48]);
+			*procedure_count = get_unaligned_be32(&p[52]);
+		}
+	}
+
+	return status;
+}
+
+static int altera_get_act_info(u8 *p,
+					s32 program_size,
+					int index,
+					char **name,
+					char **description,
+					struct altera_procinfo **proc_list)
+{
+	int status = -EIO;
+	struct altera_procinfo *procptr = NULL;
+	struct altera_procinfo *tmpptr = NULL;
+	u32 first_word = 0L;
+	u32 action_table = 0L;
+	u32 proc_table = 0L;
+	u32 str_table = 0L;
+	u32 note_strings = 0L;
+	u32 action_count = 0L;
+	u32 proc_count = 0L;
+	u32 act_name_id = 0L;
+	u32 act_desc_id = 0L;
+	u32 act_proc_id = 0L;
+	u32 act_proc_name = 0L;
+	u8 act_proc_attribute = 0;
+
+	if (program_size <= 52L)
+		return status;
+	/* Read header information */
+	first_word = get_unaligned_be32(&p[0]);
+
+	if (first_word != 0x4A414D01L)
+		return status;
+
+	action_table = get_unaligned_be32(&p[4]);
+	proc_table   = get_unaligned_be32(&p[8]);
+	str_table = get_unaligned_be32(&p[12]);
+	note_strings = get_unaligned_be32(&p[16]);
+	action_count = get_unaligned_be32(&p[48]);
+	proc_count   = get_unaligned_be32(&p[52]);
+
+	if (index >= action_count)
+		return status;
+
+	act_name_id = get_unaligned_be32(&p[action_table + (12 * index)]);
+	act_desc_id = get_unaligned_be32(&p[action_table + (12 * index) + 4]);
+	act_proc_id = get_unaligned_be32(&p[action_table + (12 * index) + 8]);
+
+	*name = &p[str_table + act_name_id];
+
+	if (act_desc_id < (note_strings - str_table))
+		*description = &p[str_table + act_desc_id];
+
+	do {
+		act_proc_name = get_unaligned_be32(
+					&p[proc_table + (13 * act_proc_id)]);
+		act_proc_attribute =
+			(p[proc_table + (13 * act_proc_id) + 8] & 0x03);
+
+		procptr = (struct altera_procinfo *)
+				kzalloc(sizeof(struct altera_procinfo),
+								GFP_KERNEL);
+
+		if (procptr == NULL)
+			status = -ENOMEM;
+		else {
+			procptr->name = &p[str_table + act_proc_name];
+			procptr->attrs = act_proc_attribute;
+			procptr->next = NULL;
+
+			/* add record to end of linked list */
+			if (*proc_list == NULL)
+				*proc_list = procptr;
+			else {
+				tmpptr = *proc_list;
+				while (tmpptr->next != NULL)
+					tmpptr = tmpptr->next;
+				tmpptr->next = procptr;
+			}
+		}
+
+		act_proc_id = get_unaligned_be32(
+				&p[proc_table + (13 * act_proc_id) + 4]);
+	} while ((act_proc_id != 0) && (act_proc_id < proc_count));
+
+	return status;
+}
+
+int altera_init(struct altera_config *config, const struct firmware *fw)
+{
+	struct altera_state *astate = NULL;
+	struct altera_procinfo *proc_list = NULL;
+	struct altera_procinfo *procptr = NULL;
+	char *key = NULL;
+	char *value = NULL;
+	char *action_name = NULL;
+	char *description = NULL;
+	int exec_result = 0;
+	int exit_code = 0;
+	int format_version = 0;
+	int action_count = 0;
+	int procedure_count = 0;
+	int index = 0;
+	s32 offset = 0L;
+	s32 error_address = 0L;
+
+	key = kzalloc(33 * sizeof(char), GFP_KERNEL);
+	if (!key)
+		return -ENOMEM;
+	value = kzalloc(257 * sizeof(char), GFP_KERNEL);
+	if (!value)
+		return -ENOMEM;
+	astate = kzalloc(sizeof(struct altera_state), GFP_KERNEL);
+	if (!astate)
+		return -ENOMEM;
+
+	astate->config = config;
+	if (!astate->config->jtag_io) {
+		dprintk(KERN_INFO "%s: using byteblaster!\n", __func__);
+		astate->config->jtag_io = netup_jtag_io_lpt;
+	}
+
+	altera_check_crc((u8 *)fw->data, fw->size);
+
+	if (debug) {
+		altera_get_file_info((u8 *)fw->data, fw->size, &format_version,
+					&action_count, &procedure_count);
+		printk(KERN_INFO "%s: File format is %s ByteCode format\n",
+			__func__, (format_version == 2) ? "Jam STAPL" :
+						"pre-standardized Jam 1.1");
+		while (altera_get_note((u8 *)fw->data, fw->size,
+					&offset, key, value, 256) == 0)
+			printk(KERN_INFO "%s: NOTE \"%s\" = \"%s\"\n",
+					__func__, key, value);
+	}
+
+	if (debug && (format_version == 2) && (action_count > 0)) {
+		printk(KERN_INFO "%s: Actions available:\n", __func__);
+		for (index = 0; index < action_count; ++index) {
+			altera_get_act_info((u8 *)fw->data, fw->size,
+						index, &action_name,
+						&description,
+						&proc_list);
+
+			if (description == NULL)
+				printk(KERN_INFO "%s: %s\n",
+						__func__,
+						action_name);
+			else
+				printk(KERN_INFO "%s: %s \"%s\"\n",
+						__func__,
+						action_name,
+						description);
+
+			procptr = proc_list;
+			while (procptr != NULL) {
+				if (procptr->attrs != 0)
+					printk(KERN_INFO "%s:    %s (%s)\n",
+						__func__,
+						procptr->name,
+						(procptr->attrs == 1) ?
+						"optional" : "recommended");
+
+				proc_list = procptr->next;
+				kfree(procptr);
+				procptr = proc_list;
+			}
+		}
+
+		printk(KERN_INFO "\n");
+	}
+
+	exec_result = altera_execute(astate, (u8 *)fw->data, fw->size,
+				&error_address, &exit_code, &format_version);
+
+	if (exit_code)
+		exec_result = -EREMOTEIO;
+
+	if ((format_version == 2) && (exec_result == -EINVAL)) {
+		if (astate->config->action == NULL)
+			printk(KERN_ERR "%s: error: no action specified for "
+				"Jam STAPL file.\nprogram terminated.\n",
+				__func__);
+		else
+			printk(KERN_ERR "%s: error: action \"%s\""
+				" is not supported "
+				"for this Jam STAPL file.\n"
+				"Program terminated.\n", __func__,
+				astate->config->action);
+
+	} else if (exec_result)
+		printk(KERN_ERR "%s: error %d\n", __func__, exec_result);
+
+	kfree(key);
+	kfree(value);
+	kfree(astate);
+
+	return 0;
+}
+EXPORT_SYMBOL(altera_init);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-comp.c linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-comp.c
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-comp.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-comp.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,142 @@
+/*
+ * altera-comp.c
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 "altera-exprt.h"
+
+#define	SHORT_BITS		16
+#define	CHAR_BITS		8
+#define	DATA_BLOB_LENGTH	3
+#define	MATCH_DATA_LENGTH	8192
+#define ALTERA_REQUEST_SIZE	1024
+#define ALTERA_BUFFER_SIZE	(MATCH_DATA_LENGTH + ALTERA_REQUEST_SIZE)
+
+static u32 altera_bits_req(u32 n)
+{
+	u32 result = SHORT_BITS;
+
+	if (n == 0)
+		result = 1;
+	else {
+		/* Look for the highest non-zero bit position */
+		while ((n & (1 << (SHORT_BITS - 1))) == 0) {
+			n <<= 1;
+			--result;
+		}
+	}
+
+	return result;
+}
+
+static u32 altera_read_packed(u8 *buffer, u32 bits, u32 *bits_avail,
+							u32 *in_index)
+{
+	u32 result = 0;
+	u32 shift = 0;
+	u32 databyte = 0;
+
+	while (bits > 0) {
+		databyte = buffer[*in_index];
+		result |= (((databyte >> (CHAR_BITS - *bits_avail))
+			& (0xff >> (CHAR_BITS - *bits_avail))) << shift);
+
+		if (bits <= *bits_avail) {
+			result &= (0xffff >> (SHORT_BITS - (bits + shift)));
+			*bits_avail -= bits;
+			bits = 0;
+		} else {
+			++(*in_index);
+			shift += *bits_avail;
+			bits -= *bits_avail;
+			*bits_avail = CHAR_BITS;
+		}
+	}
+
+	return result;
+}
+
+u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version)
+{
+	u32 i, j, data_length = 0L;
+	u32 offset, length;
+	u32 match_data_length = MATCH_DATA_LENGTH;
+	u32 bits_avail = CHAR_BITS;
+	u32 in_index = 0L;
+
+	if (version > 0)
+		--match_data_length;
+
+	for (i = 0; i < out_length; ++i)
+		out[i] = 0;
+
+	/* Read number of bytes in data. */
+	for (i = 0; i < sizeof(in_length); ++i) {
+		data_length = data_length | (
+			altera_read_packed(in,
+					CHAR_BITS,
+					&bits_avail,
+					&in_index) << (i * CHAR_BITS));
+	}
+
+	if (data_length > out_length) {
+		data_length = 0L;
+		return data_length;
+	}
+
+	i = 0;
+	while (i < data_length) {
+		/* A 0 bit indicates literal data. */
+		if (altera_read_packed(in, 1, &bits_avail,
+						&in_index) == 0) {
+			for (j = 0; j < DATA_BLOB_LENGTH; ++j) {
+				if (i < data_length) {
+					out[i] = (u8)altera_read_packed(in,
+							CHAR_BITS,
+							&bits_avail,
+							&in_index);
+					i++;
+				}
+			}
+		} else {
+			/* A 1 bit indicates offset/length to follow. */
+			offset = altera_read_packed(in, altera_bits_req((s16)
+					(i > match_data_length ?
+						match_data_length : i)),
+					&bits_avail,
+					&in_index);
+			length = altera_read_packed(in, CHAR_BITS,
+					&bits_avail,
+					&in_index);
+			for (j = 0; j < length; ++j) {
+				if (i < data_length) {
+					out[i] = out[i - offset];
+					i++;
+				}
+			}
+		}
+	}
+
+	return data_length;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-exprt.h linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-exprt.h
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-exprt.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-exprt.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,33 @@
+/*
+ * altera-exprt.h
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 ALTERA_EXPRT_H
+#define ALTERA_EXPRT_H
+
+
+u32 altera_shrink(u8 *in, u32 in_length, u8 *out, u32 out_length, s32 version);
+int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo);
+
+#endif /* ALTERA_EXPRT_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-jtag.c linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-jtag.c
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-jtag.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-jtag.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1021 @@
+/*
+ * altera-jtag.c
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/firmware.h>
+#include <linux/slab.h>
+#include <staging/altera.h>
+#include "altera-exprt.h"
+#include "altera-jtag.h"
+
+#define	alt_jtag_io(a, b, c)\
+		astate->config->jtag_io(astate->config->dev, a, b, c);
+
+#define	alt_malloc(a)	kzalloc(a, GFP_KERNEL);
+
+/*
+ * This structure shows, for each JTAG state, which state is reached after
+ * a single TCK clock cycle with TMS high or TMS low, respectively.  This
+ * describes all possible state transitions in the JTAG state machine.
+ */
+struct altera_jtag_machine {
+	enum altera_jtag_state tms_high;
+	enum altera_jtag_state tms_low;
+};
+
+static const struct altera_jtag_machine altera_transitions[] = {
+	/* RESET     */	{ RESET,	IDLE },
+	/* IDLE      */	{ DRSELECT,	IDLE },
+	/* DRSELECT  */	{ IRSELECT,	DRCAPTURE },
+	/* DRCAPTURE */	{ DREXIT1,	DRSHIFT },
+	/* DRSHIFT   */	{ DREXIT1,	DRSHIFT },
+	/* DREXIT1   */	{ DRUPDATE,	DRPAUSE },
+	/* DRPAUSE   */	{ DREXIT2,	DRPAUSE },
+	/* DREXIT2   */	{ DRUPDATE,	DRSHIFT },
+	/* DRUPDATE  */	{ DRSELECT,	IDLE },
+	/* IRSELECT  */	{ RESET,	IRCAPTURE },
+	/* IRCAPTURE */	{ IREXIT1,	IRSHIFT },
+	/* IRSHIFT   */	{ IREXIT1,	IRSHIFT },
+	/* IREXIT1   */	{ IRUPDATE,	IRPAUSE },
+	/* IRPAUSE   */	{ IREXIT2,	IRPAUSE },
+	/* IREXIT2   */	{ IRUPDATE,	IRSHIFT },
+	/* IRUPDATE  */	{ DRSELECT,	IDLE }
+};
+
+/*
+ * This table contains the TMS value to be used to take the NEXT STEP on
+ * the path to the desired state.  The array index is the current state,
+ * and the bit position is the desired endstate.  To find out which state
+ * is used as the intermediate state, look up the TMS value in the
+ * altera_transitions[] table.
+ */
+static const u16 altera_jtag_path_map[16] = {
+	/* RST	RTI	SDRS	CDR	SDR	E1DR	PDR	E2DR */
+	0x0001,	0xFFFD,	0xFE01,	0xFFE7,	0xFFEF,	0xFF0F,	0xFFBF,	0xFFFF,
+	/* UDR	SIRS	CIR	SIR	E1IR	PIR	E2IR	UIR */
+	0xFEFD,	0x0001,	0xF3FF,	0xF7FF,	0x87FF,	0xDFFF,	0xFFFF,	0x7FFD
+};
+
+/* Flag bits for alt_jtag_io() function */
+#define TMS_HIGH   1
+#define TMS_LOW    0
+#define TDI_HIGH   1
+#define TDI_LOW    0
+#define READ_TDO   1
+#define IGNORE_TDO 0
+
+int altera_jinit(struct altera_state *astate)
+{
+	struct altera_jtag *js = &astate->js;
+
+	/* initial JTAG state is unknown */
+	js->jtag_state = ILLEGAL_JTAG_STATE;
+
+	/* initialize to default state */
+	js->drstop_state = IDLE;
+	js->irstop_state = IDLE;
+	js->dr_pre  = 0;
+	js->dr_post = 0;
+	js->ir_pre  = 0;
+	js->ir_post = 0;
+	js->dr_length    = 0;
+	js->ir_length    = 0;
+
+	js->dr_pre_data  = NULL;
+	js->dr_post_data = NULL;
+	js->ir_pre_data  = NULL;
+	js->ir_post_data = NULL;
+	js->dr_buffer	 = NULL;
+	js->ir_buffer	 = NULL;
+
+	return 0;
+}
+
+int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state)
+{
+	js->drstop_state = state;
+
+	return 0;
+}
+
+int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state)
+{
+	js->irstop_state = state;
+
+	return 0;
+}
+
+int altera_set_dr_pre(struct altera_jtag *js,
+				u32 count, u32 start_index,
+				u8 *preamble_data)
+{
+	int status = 0;
+	u32 i;
+	u32 j;
+
+	if (count > js->dr_pre) {
+		kfree(js->dr_pre_data);
+		js->dr_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
+		if (js->dr_pre_data == NULL)
+			status = -ENOMEM;
+		else
+			js->dr_pre = count;
+	} else
+		js->dr_pre = count;
+
+	if (status == 0) {
+		for (i = 0; i < count; ++i) {
+			j = i + start_index;
+
+			if (preamble_data == NULL)
+				js->dr_pre_data[i >> 3] |= (1 << (i & 7));
+			else {
+				if (preamble_data[j >> 3] & (1 << (j & 7)))
+					js->dr_pre_data[i >> 3] |=
+							(1 << (i & 7));
+				else
+					js->dr_pre_data[i >> 3] &=
+							~(u32)(1 << (i & 7));
+
+			}
+		}
+	}
+
+	return status;
+}
+
+int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
+							u8 *preamble_data)
+{
+	int status = 0;
+	u32 i;
+	u32 j;
+
+	if (count > js->ir_pre) {
+		kfree(js->ir_pre_data);
+		js->ir_pre_data = (u8 *)alt_malloc((count + 7) >> 3);
+		if (js->ir_pre_data == NULL)
+			status = -ENOMEM;
+		else
+			js->ir_pre = count;
+
+	} else
+		js->ir_pre = count;
+
+	if (status == 0) {
+		for (i = 0; i < count; ++i) {
+			j = i + start_index;
+			if (preamble_data == NULL)
+				js->ir_pre_data[i >> 3] |= (1 << (i & 7));
+			else {
+				if (preamble_data[j >> 3] & (1 << (j & 7)))
+					js->ir_pre_data[i >> 3] |=
+							(1 << (i & 7));
+				else
+					js->ir_pre_data[i >> 3] &=
+							~(u32)(1 << (i & 7));
+
+			}
+		}
+	}
+
+	return status;
+}
+
+int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
+						u8 *postamble_data)
+{
+	int status = 0;
+	u32 i;
+	u32 j;
+
+	if (count > js->dr_post) {
+		kfree(js->dr_post_data);
+		js->dr_post_data = (u8 *)alt_malloc((count + 7) >> 3);
+
+		if (js->dr_post_data == NULL)
+			status = -ENOMEM;
+		else
+			js->dr_post = count;
+
+	} else
+		js->dr_post = count;
+
+	if (status == 0) {
+		for (i = 0; i < count; ++i) {
+			j = i + start_index;
+
+			if (postamble_data == NULL)
+				js->dr_post_data[i >> 3] |= (1 << (i & 7));
+			else {
+				if (postamble_data[j >> 3] & (1 << (j & 7)))
+					js->dr_post_data[i >> 3] |=
+								(1 << (i & 7));
+				else
+					js->dr_post_data[i >> 3] &=
+					    ~(u32)(1 << (i & 7));
+
+			}
+		}
+	}
+
+	return status;
+}
+
+int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
+						u8 *postamble_data)
+{
+	int status = 0;
+	u32 i;
+	u32 j;
+
+	if (count > js->ir_post) {
+		kfree(js->ir_post_data);
+		js->ir_post_data = (u8 *)alt_malloc((count + 7) >> 3);
+		if (js->ir_post_data == NULL)
+			status = -ENOMEM;
+		else
+			js->ir_post = count;
+
+	} else
+		js->ir_post = count;
+
+	if (status != 0)
+		return status;
+
+	for (i = 0; i < count; ++i) {
+		j = i + start_index;
+
+		if (postamble_data == NULL)
+			js->ir_post_data[i >> 3] |= (1 << (i & 7));
+		else {
+			if (postamble_data[j >> 3] & (1 << (j & 7)))
+				js->ir_post_data[i >> 3] |= (1 << (i & 7));
+			else
+				js->ir_post_data[i >> 3] &=
+				    ~(u32)(1 << (i & 7));
+
+		}
+	}
+
+	return status;
+}
+
+static void altera_jreset_idle(struct altera_state *astate)
+{
+	struct altera_jtag *js = &astate->js;
+	int i;
+	/* Go to Test Logic Reset (no matter what the starting state may be) */
+	for (i = 0; i < 5; ++i)
+		alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
+
+	/* Now step to Run Test / Idle */
+	alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
+	js->jtag_state = IDLE;
+}
+
+int altera_goto_jstate(struct altera_state *astate,
+					enum altera_jtag_state state)
+{
+	struct altera_jtag *js = &astate->js;
+	int tms;
+	int count = 0;
+	int status = 0;
+
+	if (js->jtag_state == ILLEGAL_JTAG_STATE)
+		/* initialize JTAG chain to known state */
+		altera_jreset_idle(astate);
+
+	if (js->jtag_state == state) {
+		/*
+		 * We are already in the desired state.
+		 * If it is a stable state, loop here.
+		 * Otherwise do nothing (no clock cycles).
+		 */
+		if ((state == IDLE) || (state == DRSHIFT) ||
+			(state == DRPAUSE) || (state == IRSHIFT) ||
+				(state == IRPAUSE)) {
+			alt_jtag_io(TMS_LOW, TDI_LOW, IGNORE_TDO);
+		} else if (state == RESET)
+			alt_jtag_io(TMS_HIGH, TDI_LOW, IGNORE_TDO);
+
+	} else {
+		while ((js->jtag_state != state) && (count < 9)) {
+			/* Get TMS value to take a step toward desired state */
+			tms = (altera_jtag_path_map[js->jtag_state] &
+							(1 << state))
+							? TMS_HIGH : TMS_LOW;
+
+			/* Take a step */
+			alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
+
+			if (tms)
+				js->jtag_state =
+					altera_transitions[js->jtag_state].tms_high;
+			else
+				js->jtag_state =
+					altera_transitions[js->jtag_state].tms_low;
+
+			++count;
+		}
+	}
+
+	if (js->jtag_state != state)
+		status = -EREMOTEIO;
+
+	return status;
+}
+
+int altera_wait_cycles(struct altera_state *astate,
+					s32 cycles,
+					enum altera_jtag_state wait_state)
+{
+	struct altera_jtag *js = &astate->js;
+	int tms;
+	s32 count;
+	int status = 0;
+
+	if (js->jtag_state != wait_state)
+		status = altera_goto_jstate(astate, wait_state);
+
+	if (status == 0) {
+		/*
+		 * Set TMS high to loop in RESET state
+		 * Set TMS low to loop in any other stable state
+		 */
+		tms = (wait_state == RESET) ? TMS_HIGH : TMS_LOW;
+
+		for (count = 0L; count < cycles; count++)
+			alt_jtag_io(tms, TDI_LOW, IGNORE_TDO);
+
+	}
+
+	return status;
+}
+
+int altera_wait_msecs(struct altera_state *astate,
+			s32 microseconds, enum altera_jtag_state wait_state)
+/*
+ * Causes JTAG hardware to sit in the specified stable
+ * state for the specified duration of real time.  If
+ * no JTAG operations have been performed yet, then only
+ * a delay is performed.  This permits the WAIT USECS
+ * statement to be used in VECTOR programs without causing
+ * any JTAG operations.
+ * Returns 0 for success, else appropriate error code.
+ */
+{
+	struct altera_jtag *js = &astate->js;
+	int status = 0;
+
+	if ((js->jtag_state != ILLEGAL_JTAG_STATE) &&
+	    (js->jtag_state != wait_state))
+		status = altera_goto_jstate(astate, wait_state);
+
+	if (status == 0)
+		/* Wait for specified time interval */
+		udelay(microseconds);
+
+	return status;
+}
+
+static void altera_concatenate_data(u8 *buffer,
+				u8 *preamble_data,
+				u32 preamble_count,
+				u8 *target_data,
+				u32 start_index,
+				u32 target_count,
+				u8 *postamble_data,
+				u32 postamble_count)
+/*
+ * Copies preamble data, target data, and postamble data
+ * into one buffer for IR or DR scans.
+ */
+{
+	u32 i, j, k;
+
+	for (i = 0L; i < preamble_count; ++i) {
+		if (preamble_data[i >> 3L] & (1L << (i & 7L)))
+			buffer[i >> 3L] |= (1L << (i & 7L));
+		else
+			buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
+
+	}
+
+	j = start_index;
+	k = preamble_count + target_count;
+	for (; i < k; ++i, ++j) {
+		if (target_data[j >> 3L] & (1L << (j & 7L)))
+			buffer[i >> 3L] |= (1L << (i & 7L));
+		else
+			buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
+
+	}
+
+	j = 0L;
+	k = preamble_count + target_count + postamble_count;
+	for (; i < k; ++i, ++j) {
+		if (postamble_data[j >> 3L] & (1L << (j & 7L)))
+			buffer[i >> 3L] |= (1L << (i & 7L));
+		else
+			buffer[i >> 3L] &= ~(u32)(1L << (i & 7L));
+
+	}
+}
+
+static int alt_jtag_drscan(struct altera_state *astate,
+			int start_state,
+			int count,
+			u8 *tdi,
+			u8 *tdo)
+{
+	int i = 0;
+	int tdo_bit = 0;
+	int status = 1;
+
+	/* First go to DRSHIFT state */
+	switch (start_state) {
+	case 0:						/* IDLE */
+		alt_jtag_io(1, 0, 0);	/* DRSELECT */
+		alt_jtag_io(0, 0, 0);	/* DRCAPTURE */
+		alt_jtag_io(0, 0, 0);	/* DRSHIFT */
+		break;
+
+	case 1:						/* DRPAUSE */
+		alt_jtag_io(1, 0, 0);	/* DREXIT2 */
+		alt_jtag_io(1, 0, 0);	/* DRUPDATE */
+		alt_jtag_io(1, 0, 0);	/* DRSELECT */
+		alt_jtag_io(0, 0, 0);	/* DRCAPTURE */
+		alt_jtag_io(0, 0, 0);	/* DRSHIFT */
+		break;
+
+	case 2:						/* IRPAUSE */
+		alt_jtag_io(1, 0, 0);	/* IREXIT2 */
+		alt_jtag_io(1, 0, 0);	/* IRUPDATE */
+		alt_jtag_io(1, 0, 0);	/* DRSELECT */
+		alt_jtag_io(0, 0, 0);	/* DRCAPTURE */
+		alt_jtag_io(0, 0, 0);	/* DRSHIFT */
+		break;
+
+	default:
+		status = 0;
+	}
+
+	if (status) {
+		/* loop in the SHIFT-DR state */
+		for (i = 0; i < count; i++) {
+			tdo_bit = alt_jtag_io(
+					(i == count - 1),
+					tdi[i >> 3] & (1 << (i & 7)),
+					(tdo != NULL));
+
+			if (tdo != NULL) {
+				if (tdo_bit)
+					tdo[i >> 3] |= (1 << (i & 7));
+				else
+					tdo[i >> 3] &= ~(u32)(1 << (i & 7));
+
+			}
+		}
+
+		alt_jtag_io(0, 0, 0);	/* DRPAUSE */
+	}
+
+	return status;
+}
+
+static int alt_jtag_irscan(struct altera_state *astate,
+		    int start_state,
+		    int count,
+		    u8 *tdi,
+		    u8 *tdo)
+{
+	int i = 0;
+	int tdo_bit = 0;
+	int status = 1;
+
+	/* First go to IRSHIFT state */
+	switch (start_state) {
+	case 0:						/* IDLE */
+		alt_jtag_io(1, 0, 0);	/* DRSELECT */
+		alt_jtag_io(1, 0, 0);	/* IRSELECT */
+		alt_jtag_io(0, 0, 0);	/* IRCAPTURE */
+		alt_jtag_io(0, 0, 0);	/* IRSHIFT */
+		break;
+
+	case 1:						/* DRPAUSE */
+		alt_jtag_io(1, 0, 0);	/* DREXIT2 */
+		alt_jtag_io(1, 0, 0);	/* DRUPDATE */
+		alt_jtag_io(1, 0, 0);	/* DRSELECT */
+		alt_jtag_io(1, 0, 0);	/* IRSELECT */
+		alt_jtag_io(0, 0, 0);	/* IRCAPTURE */
+		alt_jtag_io(0, 0, 0);	/* IRSHIFT */
+		break;
+
+	case 2:						/* IRPAUSE */
+		alt_jtag_io(1, 0, 0);	/* IREXIT2 */
+		alt_jtag_io(1, 0, 0);	/* IRUPDATE */
+		alt_jtag_io(1, 0, 0);	/* DRSELECT */
+		alt_jtag_io(1, 0, 0);	/* IRSELECT */
+		alt_jtag_io(0, 0, 0);	/* IRCAPTURE */
+		alt_jtag_io(0, 0, 0);	/* IRSHIFT */
+		break;
+
+	default:
+		status = 0;
+	}
+
+	if (status) {
+		/* loop in the SHIFT-IR state */
+		for (i = 0; i < count; i++) {
+			tdo_bit = alt_jtag_io(
+				      (i == count - 1),
+				      tdi[i >> 3] & (1 << (i & 7)),
+				      (tdo != NULL));
+			if (tdo != NULL) {
+				if (tdo_bit)
+					tdo[i >> 3] |= (1 << (i & 7));
+				else
+					tdo[i >> 3] &= ~(u32)(1 << (i & 7));
+
+			}
+		}
+
+		alt_jtag_io(0, 0, 0);	/* IRPAUSE */
+	}
+
+	return status;
+}
+
+static void altera_extract_target_data(u8 *buffer,
+				u8 *target_data,
+				u32 start_index,
+				u32 preamble_count,
+				u32 target_count)
+/*
+ * Copies target data from scan buffer, filtering out
+ * preamble and postamble data.
+ */
+{
+	u32 i;
+	u32 j;
+	u32 k;
+
+	j = preamble_count;
+	k = start_index + target_count;
+	for (i = start_index; i < k; ++i, ++j) {
+		if (buffer[j >> 3] & (1 << (j & 7)))
+			target_data[i >> 3] |= (1 << (i & 7));
+		else
+			target_data[i >> 3] &= ~(u32)(1 << (i & 7));
+
+	}
+}
+
+int altera_irscan(struct altera_state *astate,
+				u32 count,
+				u8 *tdi_data,
+				u32 start_index)
+/* Shifts data into instruction register */
+{
+	struct altera_jtag *js = &astate->js;
+	int start_code = 0;
+	u32 alloc_chars = 0;
+	u32 shift_count = js->ir_pre + count + js->ir_post;
+	int status = 0;
+	enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
+
+	switch (js->jtag_state) {
+	case ILLEGAL_JTAG_STATE:
+	case RESET:
+	case IDLE:
+		start_code = 0;
+		start_state = IDLE;
+		break;
+
+	case DRSELECT:
+	case DRCAPTURE:
+	case DRSHIFT:
+	case DREXIT1:
+	case DRPAUSE:
+	case DREXIT2:
+	case DRUPDATE:
+		start_code = 1;
+		start_state = DRPAUSE;
+		break;
+
+	case IRSELECT:
+	case IRCAPTURE:
+	case IRSHIFT:
+	case IREXIT1:
+	case IRPAUSE:
+	case IREXIT2:
+	case IRUPDATE:
+		start_code = 2;
+		start_state = IRPAUSE;
+		break;
+
+	default:
+		status = -EREMOTEIO;
+		break;
+	}
+
+	if (status == 0)
+		if (js->jtag_state != start_state)
+			status = altera_goto_jstate(astate, start_state);
+
+	if (status == 0) {
+		if (shift_count > js->ir_length) {
+			alloc_chars = (shift_count + 7) >> 3;
+			kfree(js->ir_buffer);
+			js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
+			if (js->ir_buffer == NULL)
+				status = -ENOMEM;
+			else
+				js->ir_length = alloc_chars * 8;
+
+		}
+	}
+
+	if (status == 0) {
+		/*
+		 * Copy preamble data, IR data,
+		 * and postamble data into a buffer
+		 */
+		altera_concatenate_data(js->ir_buffer,
+					js->ir_pre_data,
+					js->ir_pre,
+					tdi_data,
+					start_index,
+					count,
+					js->ir_post_data,
+					js->ir_post);
+		/* Do the IRSCAN */
+		alt_jtag_irscan(astate,
+				start_code,
+				shift_count,
+				js->ir_buffer,
+				NULL);
+
+		/* alt_jtag_irscan() always ends in IRPAUSE state */
+		js->jtag_state = IRPAUSE;
+	}
+
+	if (status == 0)
+		if (js->irstop_state != IRPAUSE)
+			status = altera_goto_jstate(astate, js->irstop_state);
+
+
+	return status;
+}
+
+int altera_swap_ir(struct altera_state *astate,
+			    u32 count,
+			    u8 *in_data,
+			    u32 in_index,
+			    u8 *out_data,
+			    u32 out_index)
+/* Shifts data into instruction register, capturing output data */
+{
+	struct altera_jtag *js = &astate->js;
+	int start_code = 0;
+	u32 alloc_chars = 0;
+	u32 shift_count = js->ir_pre + count + js->ir_post;
+	int status = 0;
+	enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
+
+	switch (js->jtag_state) {
+	case ILLEGAL_JTAG_STATE:
+	case RESET:
+	case IDLE:
+		start_code = 0;
+		start_state = IDLE;
+		break;
+
+	case DRSELECT:
+	case DRCAPTURE:
+	case DRSHIFT:
+	case DREXIT1:
+	case DRPAUSE:
+	case DREXIT2:
+	case DRUPDATE:
+		start_code = 1;
+		start_state = DRPAUSE;
+		break;
+
+	case IRSELECT:
+	case IRCAPTURE:
+	case IRSHIFT:
+	case IREXIT1:
+	case IRPAUSE:
+	case IREXIT2:
+	case IRUPDATE:
+		start_code = 2;
+		start_state = IRPAUSE;
+		break;
+
+	default:
+		status = -EREMOTEIO;
+		break;
+	}
+
+	if (status == 0)
+		if (js->jtag_state != start_state)
+			status = altera_goto_jstate(astate, start_state);
+
+	if (status == 0) {
+		if (shift_count > js->ir_length) {
+			alloc_chars = (shift_count + 7) >> 3;
+			kfree(js->ir_buffer);
+			js->ir_buffer = (u8 *)alt_malloc(alloc_chars);
+			if (js->ir_buffer == NULL)
+				status = -ENOMEM;
+			else
+				js->ir_length = alloc_chars * 8;
+
+		}
+	}
+
+	if (status == 0) {
+		/*
+		 * Copy preamble data, IR data,
+		 * and postamble data into a buffer
+		 */
+		altera_concatenate_data(js->ir_buffer,
+					js->ir_pre_data,
+					js->ir_pre,
+					in_data,
+					in_index,
+					count,
+					js->ir_post_data,
+					js->ir_post);
+
+		/* Do the IRSCAN */
+		alt_jtag_irscan(astate,
+				start_code,
+				shift_count,
+				js->ir_buffer,
+				js->ir_buffer);
+
+		/* alt_jtag_irscan() always ends in IRPAUSE state */
+		js->jtag_state = IRPAUSE;
+	}
+
+	if (status == 0)
+		if (js->irstop_state != IRPAUSE)
+			status = altera_goto_jstate(astate, js->irstop_state);
+
+
+	if (status == 0)
+		/* Now extract the returned data from the buffer */
+		altera_extract_target_data(js->ir_buffer,
+					out_data, out_index,
+					js->ir_pre, count);
+
+	return status;
+}
+
+int altera_drscan(struct altera_state *astate,
+				u32 count,
+				u8 *tdi_data,
+				u32 start_index)
+/* Shifts data into data register (ignoring output data) */
+{
+	struct altera_jtag *js = &astate->js;
+	int start_code = 0;
+	u32 alloc_chars = 0;
+	u32 shift_count = js->dr_pre + count + js->dr_post;
+	int status = 0;
+	enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
+
+	switch (js->jtag_state) {
+	case ILLEGAL_JTAG_STATE:
+	case RESET:
+	case IDLE:
+		start_code = 0;
+		start_state = IDLE;
+		break;
+
+	case DRSELECT:
+	case DRCAPTURE:
+	case DRSHIFT:
+	case DREXIT1:
+	case DRPAUSE:
+	case DREXIT2:
+	case DRUPDATE:
+		start_code = 1;
+		start_state = DRPAUSE;
+		break;
+
+	case IRSELECT:
+	case IRCAPTURE:
+	case IRSHIFT:
+	case IREXIT1:
+	case IRPAUSE:
+	case IREXIT2:
+	case IRUPDATE:
+		start_code = 2;
+		start_state = IRPAUSE;
+		break;
+
+	default:
+		status = -EREMOTEIO;
+		break;
+	}
+
+	if (status == 0)
+		if (js->jtag_state != start_state)
+			status = altera_goto_jstate(astate, start_state);
+
+	if (status == 0) {
+		if (shift_count > js->dr_length) {
+			alloc_chars = (shift_count + 7) >> 3;
+			kfree(js->dr_buffer);
+			js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
+			if (js->dr_buffer == NULL)
+				status = -ENOMEM;
+			else
+				js->dr_length = alloc_chars * 8;
+
+		}
+	}
+
+	if (status == 0) {
+		/*
+		 * Copy preamble data, DR data,
+		 * and postamble data into a buffer
+		 */
+		altera_concatenate_data(js->dr_buffer,
+					js->dr_pre_data,
+					js->dr_pre,
+					tdi_data,
+					start_index,
+					count,
+					js->dr_post_data,
+					js->dr_post);
+		/* Do the DRSCAN */
+		alt_jtag_drscan(astate, start_code, shift_count,
+				js->dr_buffer, NULL);
+		/* alt_jtag_drscan() always ends in DRPAUSE state */
+		js->jtag_state = DRPAUSE;
+	}
+
+	if (status == 0)
+		if (js->drstop_state != DRPAUSE)
+			status = altera_goto_jstate(astate, js->drstop_state);
+
+	return status;
+}
+
+int altera_swap_dr(struct altera_state *astate, u32 count,
+				u8 *in_data, u32 in_index,
+				u8 *out_data, u32 out_index)
+/* Shifts data into data register, capturing output data */
+{
+	struct altera_jtag *js = &astate->js;
+	int start_code = 0;
+	u32 alloc_chars = 0;
+	u32 shift_count = js->dr_pre + count + js->dr_post;
+	int status = 0;
+	enum altera_jtag_state start_state = ILLEGAL_JTAG_STATE;
+
+	switch (js->jtag_state) {
+	case ILLEGAL_JTAG_STATE:
+	case RESET:
+	case IDLE:
+		start_code = 0;
+		start_state = IDLE;
+		break;
+
+	case DRSELECT:
+	case DRCAPTURE:
+	case DRSHIFT:
+	case DREXIT1:
+	case DRPAUSE:
+	case DREXIT2:
+	case DRUPDATE:
+		start_code = 1;
+		start_state = DRPAUSE;
+		break;
+
+	case IRSELECT:
+	case IRCAPTURE:
+	case IRSHIFT:
+	case IREXIT1:
+	case IRPAUSE:
+	case IREXIT2:
+	case IRUPDATE:
+		start_code = 2;
+		start_state = IRPAUSE;
+		break;
+
+	default:
+		status = -EREMOTEIO;
+		break;
+	}
+
+	if (status == 0)
+		if (js->jtag_state != start_state)
+			status = altera_goto_jstate(astate, start_state);
+
+	if (status == 0) {
+		if (shift_count > js->dr_length) {
+			alloc_chars = (shift_count + 7) >> 3;
+			kfree(js->dr_buffer);
+			js->dr_buffer = (u8 *)alt_malloc(alloc_chars);
+
+			if (js->dr_buffer == NULL)
+				status = -ENOMEM;
+			else
+				js->dr_length = alloc_chars * 8;
+
+		}
+	}
+
+	if (status == 0) {
+		/*
+		 * Copy preamble data, DR data,
+		 * and postamble data into a buffer
+		 */
+		altera_concatenate_data(js->dr_buffer,
+				js->dr_pre_data,
+				js->dr_pre,
+				in_data,
+				in_index,
+				count,
+				js->dr_post_data,
+				js->dr_post);
+
+		/* Do the DRSCAN */
+		alt_jtag_drscan(astate,
+				start_code,
+				shift_count,
+				js->dr_buffer,
+				js->dr_buffer);
+
+		/* alt_jtag_drscan() always ends in DRPAUSE state */
+		js->jtag_state = DRPAUSE;
+	}
+
+	if (status == 0)
+		if (js->drstop_state != DRPAUSE)
+			status = altera_goto_jstate(astate, js->drstop_state);
+
+	if (status == 0)
+		/* Now extract the returned data from the buffer */
+		altera_extract_target_data(js->dr_buffer,
+					out_data,
+					out_index,
+					js->dr_pre,
+					count);
+
+	return status;
+}
+
+void altera_free_buffers(struct altera_state *astate)
+{
+	struct altera_jtag *js = &astate->js;
+	/* If the JTAG interface was used, reset it to TLR */
+	if (js->jtag_state != ILLEGAL_JTAG_STATE)
+		altera_jreset_idle(astate);
+
+	kfree(js->dr_pre_data);
+	js->dr_pre_data = NULL;
+
+	kfree(js->dr_post_data);
+	js->dr_post_data = NULL;
+
+	kfree(js->dr_buffer);
+	js->dr_buffer = NULL;
+
+	kfree(js->ir_pre_data);
+	js->ir_pre_data = NULL;
+
+	kfree(js->ir_post_data);
+	js->ir_post_data = NULL;
+
+	kfree(js->ir_buffer);
+	js->ir_buffer = NULL;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-jtag.h linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-jtag.h
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-jtag.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-jtag.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * altera-jtag.h
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Igor M. Liplianin <liplianin@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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 ALTERA_JTAG_H
+#define ALTERA_JTAG_H
+
+/* Function Prototypes */
+enum altera_jtag_state {
+	ILLEGAL_JTAG_STATE = -1,
+	RESET = 0,
+	IDLE = 1,
+	DRSELECT = 2,
+	DRCAPTURE = 3,
+	DRSHIFT = 4,
+	DREXIT1 = 5,
+	DRPAUSE = 6,
+	DREXIT2 = 7,
+	DRUPDATE = 8,
+	IRSELECT = 9,
+	IRCAPTURE = 10,
+	IRSHIFT = 11,
+	IREXIT1 = 12,
+	IRPAUSE = 13,
+	IREXIT2 = 14,
+	IRUPDATE = 15
+
+};
+
+struct altera_jtag {
+	/* Global variable to store the current JTAG state */
+	enum altera_jtag_state jtag_state;
+
+	/* Store current stop-state for DR and IR scan commands */
+	enum altera_jtag_state drstop_state;
+	enum altera_jtag_state irstop_state;
+
+	/* Store current padding values */
+	u32 dr_pre;
+	u32 dr_post;
+	u32 ir_pre;
+	u32 ir_post;
+	u32 dr_length;
+	u32 ir_length;
+	u8 *dr_pre_data;
+	u8 *dr_post_data;
+	u8 *ir_pre_data;
+	u8 *ir_post_data;
+	u8 *dr_buffer;
+	u8 *ir_buffer;
+};
+
+#define ALTERA_STACK_SIZE 128
+#define ALTERA_MESSAGE_LENGTH 1024
+
+struct altera_state {
+	struct altera_config	*config;
+	struct altera_jtag	js;
+	char			msg_buff[ALTERA_MESSAGE_LENGTH + 1];
+	long			stack[ALTERA_STACK_SIZE];
+};
+
+int altera_jinit(struct altera_state *astate);
+int altera_set_drstop(struct altera_jtag *js, enum altera_jtag_state state);
+int altera_set_irstop(struct altera_jtag *js, enum altera_jtag_state state);
+int altera_set_dr_pre(struct altera_jtag *js, u32 count, u32 start_index,
+				u8 *preamble_data);
+int altera_set_ir_pre(struct altera_jtag *js, u32 count, u32 start_index,
+				u8 *preamble_data);
+int altera_set_dr_post(struct altera_jtag *js, u32 count, u32 start_index,
+				u8 *postamble_data);
+int altera_set_ir_post(struct altera_jtag *js, u32 count, u32 start_index,
+				u8 *postamble_data);
+int altera_goto_jstate(struct altera_state *astate,
+				enum altera_jtag_state state);
+int altera_wait_cycles(struct altera_state *astate, s32 cycles,
+				enum altera_jtag_state wait_state);
+int altera_wait_msecs(struct altera_state *astate, s32 microseconds,
+				enum altera_jtag_state wait_state);
+int altera_irscan(struct altera_state *astate, u32 count,
+				u8 *tdi_data, u32 start_index);
+int altera_swap_ir(struct altera_state *astate,
+				u32 count, u8 *in_data,
+				u32 in_index, u8 *out_data,
+				u32 out_index);
+int altera_drscan(struct altera_state *astate, u32 count,
+				u8 *tdi_data, u32 start_index);
+int altera_swap_dr(struct altera_state *astate, u32 count,
+				u8 *in_data, u32 in_index,
+				u8 *out_data, u32 out_index);
+void altera_free_buffers(struct altera_state *astate);
+#endif /* ALTERA_JTAG_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-lpt.c linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-lpt.c
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/altera-lpt.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/altera-lpt.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,70 @@
+/*
+ * altera-lpt.c
+ *
+ * altera FPGA driver
+ *
+ * Copyright (C) Altera Corporation 1998-2001
+ * Copyright (C) 2010 NetUP Inc.
+ * Copyright (C) 2010 Abylay Ospan <aospan@netup.ru>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the 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/io.h>
+#include <linux/kernel.h>
+#include "altera-exprt.h"
+
+static int lpt_hardware_initialized;
+
+static void byteblaster_write(int port, int data)
+{
+	outb((u8)data, (u16)(port + 0x378));
+};
+
+static int byteblaster_read(int port)
+{
+	int data = 0;
+	data = inb((u16)(port + 0x378));
+	return data & 0xff;
+};
+
+int netup_jtag_io_lpt(void *device, int tms, int tdi, int read_tdo)
+{
+	int data = 0;
+	int tdo = 0;
+	int initial_lpt_ctrl = 0;
+
+	if (!lpt_hardware_initialized) {
+		initial_lpt_ctrl = byteblaster_read(2);
+		byteblaster_write(2, (initial_lpt_ctrl | 0x02) & 0xdf);
+		lpt_hardware_initialized = 1;
+	}
+
+	data = ((tdi ? 0x40 : 0) | (tms ? 0x02 : 0));
+
+	byteblaster_write(0, data);
+
+	if (read_tdo) {
+		tdo = byteblaster_read(1);
+		tdo = ((tdo & 0x80) ? 0 : 1);
+	}
+
+	byteblaster_write(0, data | 0x01);
+
+	byteblaster_write(0, data);
+
+	return tdo;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/Kconfig linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/Kconfig
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/Kconfig	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/Kconfig	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,8 @@
+comment "Altera FPGA firmware download module"
+
+config ALTERA_STAPL
+	tristate "Altera FPGA firmware download module"
+	depends on I2C
+	default n
+	help
+	  An Altera FPGA module. Say Y when you want to support this tool.
diff -druN linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/Makefile linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/Makefile
--- linux-libre-2.6.38-gnu/drivers/staging/altera-stapl/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/altera-stapl/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3 @@
+altera-stapl-objs = altera-lpt.o altera-jtag.o altera-comp.o altera.o
+
+obj-$(CONFIG_ALTERA_STAPL) += altera-stapl.o
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/bmi/include/bmi_internal.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/bmi/include/bmi_internal.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/bmi/include/bmi_internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/bmi/include/bmi_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,17 +39,17 @@
 #define BMI_COMMUNICATION_TIMEOUT       100000
 
 /* ------ Global Variable Declarations ------- */
-static A_BOOL bmiDone;
+static bool bmiDone;
 
-A_STATUS
-bmiBufferSend(HIF_DEVICE *device,
-              A_UCHAR *buffer,
-              A_UINT32 length);
+int
+bmiBufferSend(struct hif_device *device,
+              u8 *buffer,
+              u32 length);
 
-A_STATUS
-bmiBufferReceive(HIF_DEVICE *device,
-                 A_UCHAR *buffer,
-                 A_UINT32 length,
-                 A_BOOL want_timeout);
+int
+bmiBufferReceive(struct hif_device *device,
+                 u8 *buffer,
+                 u32 length,
+                 bool want_timeout);
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/bmi/src/bmi.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/bmi/src/bmi.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/bmi/src/bmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/bmi/src/bmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,7 +33,7 @@
 #include "bmi_internal.h"
 
 #ifdef ATH_DEBUG_MODULE
-static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
+static struct ath_debug_mask_description bmi_debug_desc[] = {
     { ATH_DEBUG_BMI , "BMI Tracing"},
 };
 
@@ -53,21 +53,21 @@
 very simple.
 */
 
-static A_BOOL pendingEventsFuncCheck = FALSE; 
-static A_UINT32 *pBMICmdCredits;
-static A_UCHAR *pBMICmdBuf;
+static bool pendingEventsFuncCheck = false;
+static u32 *pBMICmdCredits;
+static u8 *pBMICmdBuf;
 #define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
-                       sizeof(A_UINT32) /* cmd */ + \
-                       sizeof(A_UINT32) /* addr */ + \
-                       sizeof(A_UINT32))/* length */
+                       sizeof(u32) /* cmd */ + \
+                       sizeof(u32) /* addr */ + \
+                       sizeof(u32))/* length */
 #define BMI_COMMAND_FITS(sz) ((sz) <= MAX_BMI_CMDBUF_SZ)
     
 /* APIs visible to the driver */
 void
 BMIInit(void)
 {
-    bmiDone = FALSE;
-    pendingEventsFuncCheck = FALSE;
+    bmiDone = false;
+    pendingEventsFuncCheck = false;
 
     /*
      * On some platforms, it's not possible to DMA to a static variable
@@ -79,12 +79,12 @@
      * bus stack.
      */
     if (!pBMICmdCredits) {
-        pBMICmdCredits = (A_UINT32 *)A_MALLOC_NOWAIT(4);
+        pBMICmdCredits = (u32 *)A_MALLOC_NOWAIT(4);
         A_ASSERT(pBMICmdCredits);
     }
 
     if (!pBMICmdBuf) {
-        pBMICmdBuf = (A_UCHAR *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
+        pBMICmdBuf = (u8 *)A_MALLOC_NOWAIT(MAX_BMI_CMDBUF_SZ);
         A_ASSERT(pBMICmdBuf);
     }
     
@@ -105,23 +105,23 @@
     }
 }
 
-A_STATUS
-BMIDone(HIF_DEVICE *device)
+int
+BMIDone(struct hif_device *device)
 {
-    A_STATUS status;
-    A_UINT32 cid;
+    int status;
+    u32 cid;
 
     if (bmiDone) {
         AR_DEBUG_PRINTF (ATH_DEBUG_BMI, ("BMIDone skipped\n"));
-        return A_OK;
+        return 0;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Enter (device: 0x%p)\n", device));
-    bmiDone = TRUE;
+    bmiDone = true;
     cid = BMI_DONE;
 
-    status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
-    if (status != A_OK) {
+    status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
@@ -138,14 +138,14 @@
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Done: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info)
+int
+BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info)
 {
-    A_STATUS status;
-    A_UINT32 cid;
+    int status;
+    u32 cid;
 
     if (bmiDone) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Command disallowed\n"));
@@ -155,24 +155,24 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Enter (device: 0x%p)\n", device));
     cid = BMI_GET_TARGET_INFO;
 
-    status = bmiBufferSend(device, (A_UCHAR *)&cid, sizeof(cid));
-    if (status != A_OK) {
+    status = bmiBufferSend(device, (u8 *)&cid, sizeof(cid));
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_ver,
-                                                sizeof(targ_info->target_ver), TRUE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, (u8 *)&targ_info->target_ver,
+                                                sizeof(targ_info->target_ver), true);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Version from the device\n"));
         return A_ERROR;
     }
 
     if (targ_info->target_ver == TARGET_VERSION_SENTINAL) {
         /* Determine how many bytes are in the Target's targ_info */
-        status = bmiBufferReceive(device, (A_UCHAR *)&targ_info->target_info_byte_count,
-                                            sizeof(targ_info->target_info_byte_count), TRUE);
-        if (status != A_OK) {
+        status = bmiBufferReceive(device, (u8 *)&targ_info->target_info_byte_count,
+                                            sizeof(targ_info->target_info_byte_count), true);
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info Byte Count from the device\n"));
             return A_ERROR;
         }
@@ -185,9 +185,9 @@
 
         /* Read the remainder of the targ_info */
         status = bmiBufferReceive(device,
-                        ((A_UCHAR *)targ_info)+sizeof(targ_info->target_info_byte_count),
-                        sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), TRUE);
-        if (status != A_OK) {
+                        ((u8 *)targ_info)+sizeof(targ_info->target_info_byte_count),
+                        sizeof(*targ_info)-sizeof(targ_info->target_info_byte_count), true);
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read Target Info (%d bytes) from the device\n",
                         					targ_info->target_info_byte_count));
             return A_ERROR;
@@ -197,19 +197,19 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Get Target Info: Exit (ver: 0x%x type: 0x%x)\n",
         							targ_info->target_ver, targ_info->target_type));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIReadMemory(HIF_DEVICE *device,
-              A_UINT32 address,
-              A_UCHAR *buffer,
-              A_UINT32 length)
+int
+BMIReadMemory(struct hif_device *device,
+              u32 address,
+              u8 *buffer,
+              u32 length)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 remaining, rxlen;
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 remaining, rxlen;
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length)));
     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(address) + sizeof(length));
@@ -231,44 +231,44 @@
     {
         rxlen = (remaining < BMI_DATASZ_MAX) ? remaining : BMI_DATASZ_MAX;
         offset = 0;
-        A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
         offset += sizeof(cid);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+        memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
         offset += sizeof(address);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
+        memcpy(&(pBMICmdBuf[offset]), &rxlen, sizeof(rxlen));
         offset += sizeof(length);
 
         status = bmiBufferSend(device, pBMICmdBuf, offset);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
             return A_ERROR;
         }
-        status = bmiBufferReceive(device, pBMICmdBuf, rxlen, TRUE);
-        if (status != A_OK) {
+        status = bmiBufferReceive(device, pBMICmdBuf, rxlen, true);
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
             return A_ERROR;
         }
-        A_MEMCPY(&buffer[length - remaining], pBMICmdBuf, rxlen);
+        memcpy(&buffer[length - remaining], pBMICmdBuf, rxlen);
         remaining -= rxlen; address += rxlen;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read Memory: Exit\n"));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIWriteMemory(HIF_DEVICE *device,
-               A_UINT32 address,
-               A_UCHAR *buffer,
-               A_UINT32 length)
+int
+BMIWriteMemory(struct hif_device *device,
+               u32 address,
+               u8 *buffer,
+               u32 length)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 remaining, txlen;
-    const A_UINT32 header = sizeof(cid) + sizeof(address) + sizeof(length);
-    A_UCHAR alignedBuffer[BMI_DATASZ_MAX];
-    A_UCHAR *src;
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 remaining, txlen;
+    const u32 header = sizeof(cid) + sizeof(address) + sizeof(length);
+    u8 alignedBuffer[BMI_DATASZ_MAX];
+    u8 *src;
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + header));
     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX + header);
@@ -300,16 +300,16 @@
             txlen = (BMI_DATASZ_MAX - header);
         }
         offset = 0;
-        A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
         offset += sizeof(cid);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+        memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
         offset += sizeof(address);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
+        memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
         offset += sizeof(txlen);
-        A_MEMCPY(&(pBMICmdBuf[offset]), src, txlen);
+        memcpy(&(pBMICmdBuf[offset]), src, txlen);
         offset += txlen;
         status = bmiBufferSend(device, pBMICmdBuf, offset);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
             return A_ERROR;
         }
@@ -318,17 +318,17 @@
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Write Memory: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIExecute(HIF_DEVICE *device,
-           A_UINT32 address,
-           A_UINT32 *param)
+int
+BMIExecute(struct hif_device *device,
+           u32 address,
+           u32 *param)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
@@ -345,37 +345,37 @@
     cid = BMI_EXECUTE;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
-    A_MEMCPY(&(pBMICmdBuf[offset]), param, sizeof(*param));
+    memcpy(&(pBMICmdBuf[offset]), param, sizeof(*param));
     offset += sizeof(*param);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), FALSE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), false);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
         return A_ERROR;
     }
 
-    A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
+    memcpy(param, pBMICmdBuf, sizeof(*param));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Execute: Exit (param: %d)\n", *param));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMISetAppStart(HIF_DEVICE *device,
-               A_UINT32 address)
+int
+BMISetAppStart(struct hif_device *device,
+               u32 address)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
@@ -392,28 +392,28 @@
     cid = BMI_SET_APP_START;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Set App Start: Exit\n"));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIReadSOCRegister(HIF_DEVICE *device,
-                   A_UINT32 address,
-                   A_UINT32 *param)
+int
+BMIReadSOCRegister(struct hif_device *device,
+                   u32 address,
+                   u32 *param)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
@@ -430,36 +430,36 @@
     cid = BMI_READ_SOC_REGISTER;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
 
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), TRUE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*param), true);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
         return A_ERROR;
     }
-    A_MEMCPY(param, pBMICmdBuf, sizeof(*param));
+    memcpy(param, pBMICmdBuf, sizeof(*param));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit (value: %d)\n", *param));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIWriteSOCRegister(HIF_DEVICE *device,
-                    A_UINT32 address,
-                    A_UINT32 param)
+int
+BMIWriteSOCRegister(struct hif_device *device,
+                    u32 address,
+                    u32 param)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address) + sizeof(param)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address) + sizeof(param));
@@ -476,33 +476,33 @@
     cid = BMI_WRITE_SOC_REGISTER;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &param, sizeof(param));
+    memcpy(&(pBMICmdBuf[offset]), &param, sizeof(param));
     offset += sizeof(param);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Read SOC Register: Exit\n"));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIrompatchInstall(HIF_DEVICE *device,
-                   A_UINT32 ROM_addr,
-                   A_UINT32 RAM_addr,
-                   A_UINT32 nbytes,
-                   A_UINT32 do_activate,
-                   A_UINT32 *rompatch_id)
+int
+BMIrompatchInstall(struct hif_device *device,
+                   u32 ROM_addr,
+                   u32 RAM_addr,
+                   u32 nbytes,
+                   u32 do_activate,
+                   u32 *rompatch_id)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(ROM_addr) + sizeof(RAM_addr) +
 				sizeof(nbytes) + sizeof(do_activate)));
@@ -521,40 +521,40 @@
     cid = BMI_ROMPATCH_INSTALL;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
+    memcpy(&(pBMICmdBuf[offset]), &ROM_addr, sizeof(ROM_addr));
     offset += sizeof(ROM_addr);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
+    memcpy(&(pBMICmdBuf[offset]), &RAM_addr, sizeof(RAM_addr));
     offset += sizeof(RAM_addr);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
+    memcpy(&(pBMICmdBuf[offset]), &nbytes, sizeof(nbytes));
     offset += sizeof(nbytes);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
+    memcpy(&(pBMICmdBuf[offset]), &do_activate, sizeof(do_activate));
     offset += sizeof(do_activate);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
-    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), TRUE);
-    if (status != A_OK) {
+    status = bmiBufferReceive(device, pBMICmdBuf, sizeof(*rompatch_id), true);
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read from the device\n"));
         return A_ERROR;
     }
-    A_MEMCPY(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
+    memcpy(rompatch_id, pBMICmdBuf, sizeof(*rompatch_id));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch Install: (rompatch_id=%d)\n", *rompatch_id));
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIrompatchUninstall(HIF_DEVICE *device,
-                     A_UINT32 rompatch_id)
+int
+BMIrompatchUninstall(struct hif_device *device,
+                     u32 rompatch_id)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(rompatch_id)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(rompatch_id));
@@ -571,30 +571,30 @@
     cid = BMI_ROMPATCH_UNINSTALL;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
+    memcpy(&(pBMICmdBuf[offset]), &rompatch_id, sizeof(rompatch_id));
     offset += sizeof(rompatch_id);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI rompatch UNinstall: (rompatch_id=0x%x)\n", rompatch_id));
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-_BMIrompatchChangeActivation(HIF_DEVICE *device,
-                             A_UINT32 rompatch_count,
-                             A_UINT32 *rompatch_list,
-                             A_UINT32 do_activate)
+static int
+_BMIrompatchChangeActivation(struct hif_device *device,
+                             u32 rompatch_count,
+                             u32 *rompatch_list,
+                             u32 do_activate)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 length;
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 length;
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count)));
     memset(pBMICmdBuf, 0, BMI_DATASZ_MAX + sizeof(cid) + sizeof(rompatch_count));
@@ -611,50 +611,50 @@
     cid = do_activate ? BMI_ROMPATCH_ACTIVATE : BMI_ROMPATCH_DEACTIVATE;
 
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
+    memcpy(&(pBMICmdBuf[offset]), &rompatch_count, sizeof(rompatch_count));
     offset += sizeof(rompatch_count);
     length = rompatch_count * sizeof(*rompatch_list);
-    A_MEMCPY(&(pBMICmdBuf[offset]), rompatch_list, length);
+    memcpy(&(pBMICmdBuf[offset]), rompatch_list, length);
     offset += length;
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI Change rompatch Activation: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIrompatchActivate(HIF_DEVICE *device,
-                    A_UINT32 rompatch_count,
-                    A_UINT32 *rompatch_list)
+int
+BMIrompatchActivate(struct hif_device *device,
+                    u32 rompatch_count,
+                    u32 *rompatch_list)
 {
     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 1);
 }
 
-A_STATUS
-BMIrompatchDeactivate(HIF_DEVICE *device,
-                      A_UINT32 rompatch_count,
-                      A_UINT32 *rompatch_list)
+int
+BMIrompatchDeactivate(struct hif_device *device,
+                      u32 rompatch_count,
+                      u32 *rompatch_list)
 {
     return _BMIrompatchChangeActivation(device, rompatch_count, rompatch_list, 0);
 }
 
-A_STATUS
-BMILZData(HIF_DEVICE *device,
-          A_UCHAR *buffer,
-          A_UINT32 length)
+int
+BMILZData(struct hif_device *device,
+          u8 *buffer,
+          u32 length)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
-    A_UINT32 remaining, txlen;
-    const A_UINT32 header = sizeof(cid) + sizeof(length);
+    u32 cid;
+    int status;
+    u32 offset;
+    u32 remaining, txlen;
+    const u32 header = sizeof(cid) + sizeof(length);
 
     A_ASSERT(BMI_COMMAND_FITS(BMI_DATASZ_MAX+header));
     memset (pBMICmdBuf, 0, BMI_DATASZ_MAX+header);
@@ -676,14 +676,14 @@
         txlen = (remaining < (BMI_DATASZ_MAX - header)) ?
                                        remaining : (BMI_DATASZ_MAX - header);
         offset = 0;
-        A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+        memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
         offset += sizeof(cid);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
+        memcpy(&(pBMICmdBuf[offset]), &txlen, sizeof(txlen));
         offset += sizeof(txlen);
-        A_MEMCPY(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
+        memcpy(&(pBMICmdBuf[offset]), &buffer[length - remaining], txlen);
         offset += txlen;
         status = bmiBufferSend(device, pBMICmdBuf, offset);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to write to the device\n"));
             return A_ERROR;
         }
@@ -692,16 +692,16 @@
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Data: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMILZStreamStart(HIF_DEVICE *device,
-                 A_UINT32 address)
+int
+BMILZStreamStart(struct hif_device *device,
+                 u32 address)
 {
-    A_UINT32 cid;
-    A_STATUS status;
-    A_UINT32 offset;
+    u32 cid;
+    int status;
+    u32 offset;
 
     A_ASSERT(BMI_COMMAND_FITS(sizeof(cid) + sizeof(address)));
     memset (pBMICmdBuf, 0, sizeof(cid) + sizeof(address));
@@ -717,31 +717,31 @@
 
     cid = BMI_LZ_STREAM_START;
     offset = 0;
-    A_MEMCPY(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
+    memcpy(&(pBMICmdBuf[offset]), &cid, sizeof(cid));
     offset += sizeof(cid);
-    A_MEMCPY(&(pBMICmdBuf[offset]), &address, sizeof(address));
+    memcpy(&(pBMICmdBuf[offset]), &address, sizeof(address));
     offset += sizeof(address);
     status = bmiBufferSend(device, pBMICmdBuf, offset);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to Start LZ Stream to the device\n"));
         return A_ERROR;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_BMI, ("BMI LZ Stream Start: Exit\n"));
 
-    return A_OK;
+    return 0;
 }
 
 /* BMI Access routines */
-A_STATUS
-bmiBufferSend(HIF_DEVICE *device,
-              A_UCHAR *buffer,
-              A_UINT32 length)
+int
+bmiBufferSend(struct hif_device *device,
+              u8 *buffer,
+              u32 length)
 {
-    A_STATUS status;
-    A_UINT32 timeout;
-    A_UINT32 address;
-    A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
+    int status;
+    u32 timeout;
+    u32 address;
+    u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
 
     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
                        &mboxAddress[0], sizeof(mboxAddress));
@@ -755,9 +755,9 @@
         /* hit the credit counter with a 4-byte access, the first byte read will hit the counter and cause
          * a decrement, while the remaining 3 bytes has no effect.  The rationale behind this is to
          * make all HIF accesses 4-byte aligned */
-        status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, 4,
+        status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, 4,
             HIF_RD_SYNC_BYTE_INC, NULL);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to decrement the command credit count register\n"));
             return A_ERROR;
         }
@@ -769,7 +769,7 @@
         address = mboxAddress[ENDPOINT1];
         status = HIFReadWrite(device, address, buffer, length,
             HIF_WR_SYNC_BYTE_INC, NULL);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to send the BMI data to the device\n"));
             return A_ERROR;
         }
@@ -781,16 +781,16 @@
     return status;
 }
 
-A_STATUS
-bmiBufferReceive(HIF_DEVICE *device,
-                 A_UCHAR *buffer,
-                 A_UINT32 length,
-                 A_BOOL want_timeout)
+int
+bmiBufferReceive(struct hif_device *device,
+                 u8 *buffer,
+                 u32 length,
+                 bool want_timeout)
 {
-    A_STATUS status;
-    A_UINT32 address;
-    A_UINT32 mboxAddress[HTC_MAILBOX_NUM_MAX];
-    HIF_PENDING_EVENTS_INFO     hifPendingEvents;
+    int status;
+    u32 address;
+    u32 mboxAddress[HTC_MAILBOX_NUM_MAX];
+    struct hif_pending_events_info     hifPendingEvents;
     static HIF_PENDING_EVENTS_FUNC getPendingEventsFunc = NULL;
     
     if (!pendingEventsFuncCheck) {
@@ -800,7 +800,7 @@
                            HIF_DEVICE_GET_PENDING_EVENTS_FUNC,
                            &getPendingEventsFunc,
                            sizeof(getPendingEventsFunc));
-        pendingEventsFuncCheck = TRUE;
+        pendingEventsFuncCheck = true;
     }
                        
     HIFConfigureDevice(device, HIF_DEVICE_GET_MBOX_ADDR,
@@ -857,8 +857,8 @@
          * NB: word_available is declared static for esoteric reasons
          * having to do with protection on some OSes.
          */
-        static A_UINT32 word_available;
-        A_UINT32 timeout;
+        static u32 word_available;
+        u32 timeout;
 
         word_available = 0;
         timeout = BMI_COMMUNICATION_TIMEOUT;
@@ -868,20 +868,20 @@
                 status = getPendingEventsFunc(device,
                                               &hifPendingEvents,
                                               NULL);
-                if (status != A_OK) {
+                if (status) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMI: Failed to get pending events \n"));
                     break;
                 }
   
-                if (hifPendingEvents.AvailableRecvBytes >= sizeof(A_UINT32)) {
+                if (hifPendingEvents.AvailableRecvBytes >= sizeof(u32)) {
                     word_available = 1;    
                 }
                 continue;    
             }
             
-            status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (A_UINT8 *)&word_available,
+            status = HIFReadWrite(device, RX_LOOKAHEAD_VALID_ADDRESS, (u8 *)&word_available,
                 sizeof(word_available), HIF_RD_SYNC_BYTE_INC, NULL);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read RX_LOOKAHEAD_VALID register\n"));
                 return A_ERROR;
             }
@@ -920,7 +920,7 @@
      *   reduce BMI_DATASZ_MAX to 32 or 64
      */
     if ((length > 4) && (length < 128)) { /* check against MBOX FIFO size */
-        A_UINT32 timeout;
+        u32 timeout;
 
         *pBMICmdCredits = 0;
         timeout = BMI_COMMUNICATION_TIMEOUT;
@@ -930,9 +930,9 @@
             /* read the counter using a 4-byte read.  Since the counter is NOT auto-decrementing,
              * we can read this counter multiple times using a non-incrementing address mode.
              * The rationale here is to make all HIF accesses a multiple of 4 bytes */
-            status = HIFReadWrite(device, address, (A_UINT8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
+            status = HIFReadWrite(device, address, (u8 *)pBMICmdCredits, sizeof(*pBMICmdCredits),
                 HIF_RD_SYNC_BYTE_FIX, NULL);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the command credit count register\n"));
                 return A_ERROR;
             }
@@ -949,62 +949,62 @@
 
     address = mboxAddress[ENDPOINT1];
     status = HIFReadWrite(device, address, buffer, length, HIF_RD_SYNC_BYTE_INC, NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to read the BMI data from the device\n"));
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-BMIFastDownload(HIF_DEVICE *device, A_UINT32 address, A_UCHAR *buffer, A_UINT32 length)
+int
+BMIFastDownload(struct hif_device *device, u32 address, u8 *buffer, u32 length)
 {
-    A_STATUS status = A_ERROR;
-    A_UINT32  lastWord = 0;
-    A_UINT32  lastWordOffset = length & ~0x3;
-    A_UINT32  unalignedBytes = length & 0x3;
+    int status = A_ERROR;
+    u32 lastWord = 0;
+    u32 lastWordOffset = length & ~0x3;
+    u32 unalignedBytes = length & 0x3;
 
     status = BMILZStreamStart (device, address);
-    if (A_FAILED(status)) {
+    if (status) {
             return A_ERROR;
     }
 
     if (unalignedBytes) {
             /* copy the last word into a zero padded buffer */
-        A_MEMCPY(&lastWord, &buffer[lastWordOffset], unalignedBytes);
+        memcpy(&lastWord, &buffer[lastWordOffset], unalignedBytes);
     }
 
     status = BMILZData(device, buffer, lastWordOffset);
 
-    if (A_FAILED(status)) {
+    if (status) {
         return A_ERROR;
     }
 
     if (unalignedBytes) {
-        status = BMILZData(device, (A_UINT8 *)&lastWord, 4);
+        status = BMILZData(device, (u8 *)&lastWord, 4);
     }
 
-    if (A_SUCCESS(status)) {
+    if (!status) {
         //
         // Close compressed stream and open a new (fake) one.  This serves mainly to flush Target caches.
         //
         status = BMILZStreamStart (device, 0x00);
-        if (A_FAILED(status)) {
+        if (status) {
            return A_ERROR;
         }
     }
 	return status;
 }
 
-A_STATUS
-BMIRawWrite(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length)
+int
+BMIRawWrite(struct hif_device *device, u8 *buffer, u32 length)
 {
     return bmiBufferSend(device, buffer, length);
 }
 
-A_STATUS
-BMIRawRead(HIF_DEVICE *device, A_UCHAR *buffer, A_UINT32 length, A_BOOL want_timeout)
+int
+BMIRawRead(struct hif_device *device, u8 *buffer, u32 length, bool want_timeout)
 {
     return bmiBufferReceive(device, buffer, length, want_timeout);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/common/hif_sdio_common.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/common/hif_sdio_common.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/common/hif_sdio_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/common/hif_sdio_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -58,7 +58,7 @@
 #define HIF_DEFAULT_IO_BLOCK_SIZE          128
 
     /* set extended MBOX window information for SDIO interconnects */
-static INLINE void SetExtendedMboxWindowInfo(A_UINT16 Manfid, HIF_DEVICE_MBOX_INFO *pInfo)
+static INLINE void SetExtendedMboxWindowInfo(u16 Manfid, struct hif_device_mbox_info *pInfo)
 {
     switch (Manfid & MANUFACTURER_ID_AR6K_BASE_MASK) {                   
         case MANUFACTURER_ID_AR6002_BASE :
@@ -74,7 +74,7 @@
             pInfo->GMboxSize = HIF_GMBOX_WIDTH;
             break;
         default:
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
     }
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/include/hif_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -47,19 +47,17 @@
 #define HIF_MBOX2_BLOCK_SIZE               HIF_MBOX_BLOCK_SIZE
 #define HIF_MBOX3_BLOCK_SIZE               HIF_MBOX_BLOCK_SIZE
 
-struct _HIF_SCATTER_REQ_PRIV;
-
 typedef struct bus_request {
     struct bus_request *next;       /* link list of available requests */
     struct bus_request *inusenext;  /* link list of in use requests */
     struct semaphore sem_req;
-    A_UINT32 address;               /* request data */
-    A_UCHAR *buffer;
-    A_UINT32 length;
-    A_UINT32 request;
+    u32 address;               /* request data */
+    u8 *buffer;
+    u32 length;
+    u32 request;
     void *context;
-    A_STATUS status;
-    struct _HIF_SCATTER_REQ_PRIV *pScatterReq;      /* this request is a scatter request */
+    int status;
+    struct hif_scatter_req_priv *pScatterReq;      /* this request is a scatter request */
 } BUS_REQUEST;
 
 struct hif_device {
@@ -76,11 +74,11 @@
     BUS_REQUEST busRequest[BUS_REQUEST_MAX_NUM]; /* available bus requests */
     void     *claimedContext;
     HTC_CALLBACKS htcCallbacks;
-    A_UINT8     *dma_buffer;
-    DL_LIST      ScatterReqHead;                /* scatter request list head */
-    A_BOOL       scatter_enabled;               /* scatter enabled flag */
-    A_BOOL   is_suspend;
-    A_BOOL   is_disabled;
+    u8 *dma_buffer;
+    struct dl_list      ScatterReqHead;                /* scatter request list head */
+    bool       scatter_enabled;               /* scatter enabled flag */
+    bool   is_suspend;
+    bool   is_disabled;
     atomic_t   irqHandling;
     HIF_DEVICE_POWER_CHANGE_TYPE powerConfig;
     const struct sdio_device_id *id;
@@ -90,9 +88,9 @@
 #define CMD53_FIXED_ADDRESS 1
 #define CMD53_INCR_ADDRESS  2
 
-BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device);
-void hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest);
-void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device);
+void hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest);
+void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest);
 
 #ifdef HIF_LINUX_MMC_SCATTER_SUPPORT
 
@@ -100,28 +98,28 @@
 #define MAX_SCATTER_ENTRIES_PER_REQ      16
 #define MAX_SCATTER_REQ_TRANSFER_SIZE    32*1024
 
-typedef struct _HIF_SCATTER_REQ_PRIV {
-    HIF_SCATTER_REQ     *pHifScatterReq;  /* HIF scatter request with allocated entries */   
-    HIF_DEVICE          *device;          /* this device */
+struct hif_scatter_req_priv {
+    struct hif_scatter_req     *pHifScatterReq;  /* HIF scatter request with allocated entries */   
+    struct hif_device          *device;          /* this device */
     BUS_REQUEST         *busrequest;      /* request associated with request */
         /* scatter list for linux */    
     struct scatterlist  sgentries[MAX_SCATTER_ENTRIES_PER_REQ];   
-} HIF_SCATTER_REQ_PRIV;
+};
 
 #define ATH_DEBUG_SCATTER  ATH_DEBUG_MAKE_MODULE_MASK(0)
 
-A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo);
-void CleanupHIFScatterResources(HIF_DEVICE *device);
-A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest);
+int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo);
+void CleanupHIFScatterResources(struct hif_device *device);
+int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest);
 
 #else  // HIF_LINUX_MMC_SCATTER_SUPPORT
 
-static inline A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo) 
+static inline int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo)
 {
     return A_ENOTSUP;
 }
 
-static inline A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest) 
+static inline int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     return A_ENOTSUP;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif.c	2011-05-19 00:06:34.000000000 -0400
@@ -46,7 +46,7 @@
  */
 #define BUFFER_NEEDS_BOUNCE(buffer)  (((unsigned long)(buffer) & 0x3) || !virt_addr_valid((buffer)))
 #else
-#define BUFFER_NEEDS_BOUNCE(buffer)   (FALSE)
+#define BUFFER_NEEDS_BOUNCE(buffer)   (false)
 #endif
 
 /* ATHENV */
@@ -58,16 +58,16 @@
 #endif /* CONFIG_PM */
 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id);
 static void hifDeviceRemoved(struct sdio_func *func);
-static HIF_DEVICE *addHifDevice(struct sdio_func *func);
-static HIF_DEVICE *getHifDevice(struct sdio_func *func);
-static void delHifDevice(HIF_DEVICE * device);
+static struct hif_device *addHifDevice(struct sdio_func *func);
+static struct hif_device *getHifDevice(struct sdio_func *func);
+static void delHifDevice(struct hif_device * device);
 static int Func0_CMD52WriteByte(struct mmc_card *card, unsigned int address, unsigned char byte);
 static int Func0_CMD52ReadByte(struct mmc_card *card, unsigned int address, unsigned char *byte);
 
 int reset_sdio_on_unload = 0;
 module_param(reset_sdio_on_unload, int, 0644);
 
-extern A_UINT32 nohifscattersupport;
+extern u32 nohifscattersupport;
 
 
 /* ------ Static Variables ------ */
@@ -102,13 +102,13 @@
 static int registered = 0;
 
 OSDRV_CALLBACKS osdrvCallbacks;
-extern A_UINT32 onebitmode;
-extern A_UINT32 busspeedlow;
-extern A_UINT32 debughif;
+extern u32 onebitmode;
+extern u32 busspeedlow;
+extern u32 debughif;
 
 static void ResetAllCards(void);
-static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func);
-static A_STATUS hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func);
+static int hifDisableFunc(struct hif_device *device, struct sdio_func *func);
+static int hifEnableFunc(struct hif_device *device, struct sdio_func *func);
 
 #ifdef DEBUG
 
@@ -123,7 +123,7 @@
 
 
 /* ------ Functions ------ */
-A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks)
+int HIFInit(OSDRV_CALLBACKS *callbacks)
 {
     int status;
     AR_DEBUG_ASSERT(callbacks != NULL);
@@ -148,23 +148,23 @@
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 
 }
 
-static A_STATUS
-__HIFReadWrite(HIF_DEVICE *device,
-             A_UINT32 address,
-             A_UCHAR *buffer,
-             A_UINT32 length,
-             A_UINT32 request,
+static int
+__HIFReadWrite(struct hif_device *device,
+             u32 address,
+             u8 *buffer,
+             u32 length,
+             u32 request,
              void *context)
 {
-    A_UINT8 opcode;
-    A_STATUS    status = A_OK;
+    u8 opcode;
+    int    status = 0;
     int     ret;
-    A_UINT8 *tbuffer;
-    A_BOOL   bounced = FALSE;
+    u8 *tbuffer;
+    bool   bounced = false;
 
     AR_DEBUG_ASSERT(device != NULL);
     AR_DEBUG_ASSERT(device->func != NULL);
@@ -243,7 +243,7 @@
                     /* copy the write data to the dma buffer */
                 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
                 memcpy(tbuffer, buffer, length);
-                bounced = TRUE;
+                bounced = true;
             } else {
                 tbuffer = buffer;    
             }
@@ -265,7 +265,7 @@
                 AR_DEBUG_ASSERT(device->dma_buffer != NULL);
                 AR_DEBUG_ASSERT(length <= HIF_DMA_BUFFER_SIZE);
                 tbuffer = device->dma_buffer;
-                bounced = TRUE;
+                bounced = true;
             } else {
                 tbuffer = buffer;    
             }
@@ -299,12 +299,12 @@
                             ("AR6000: SDIO bus operation failed! MMC stack returned : %d \n", ret));
             status = A_ERROR;
         }
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
-void AddToAsyncList(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+void AddToAsyncList(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     unsigned long flags;
     BUS_REQUEST *async;
@@ -329,15 +329,15 @@
 
 
 /* queue a read/write request */
-A_STATUS
-HIFReadWrite(HIF_DEVICE *device,
-             A_UINT32 address,
-             A_UCHAR *buffer,
-             A_UINT32 length,
-             A_UINT32 request,
+int
+HIFReadWrite(struct hif_device *device,
+             u32 address,
+             u8 *buffer,
+             u32 length,
+             u32 request,
              void *context)
 {
-    A_STATUS    status = A_OK;
+    int    status = 0;
     BUS_REQUEST *busrequest;
 
 
@@ -375,7 +375,7 @@
                     /* interrupted, exit */
                     return A_ERROR;
                 } else {
-                    A_STATUS status = busrequest->status;
+                    int status = busrequest->status;
                     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: sync return freeing 0x%lX: 0x%X\n", 
 						      (unsigned long)busrequest, busrequest->status));
                     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: freeing req: 0x%X\n", (unsigned int)request));
@@ -400,12 +400,12 @@
 /* thread to serialize all requests, both sync and async */
 static int async_task(void *param)
  {
-    HIF_DEVICE *device;
+    struct hif_device *device;
     BUS_REQUEST *request;
-    A_STATUS status;
+    int status;
     unsigned long flags;
 
-    device = (HIF_DEVICE *)param;
+    device = (struct hif_device *)param;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: async task\n"));
     set_current_state(TASK_INTERRUPTIBLE);
     while(!device->async_shutdown) {
@@ -465,10 +465,10 @@
     return 0;
 }
 
-static A_INT32 IssueSDCommand(HIF_DEVICE *device, A_UINT32 opcode, A_UINT32 arg, A_UINT32 flags, A_UINT32 *resp)
+static s32 IssueSDCommand(struct hif_device *device, u32 opcode, u32 arg, u32 flags, u32 *resp)
 {
     struct mmc_command cmd;
-    A_INT32 err;
+    s32 err;
     struct mmc_host *host;
     struct sdio_func *func;
 
@@ -488,14 +488,14 @@
     return err;
 }
 
-A_STATUS ReinitSDIO(HIF_DEVICE *device)
+int ReinitSDIO(struct hif_device *device)
 {
-    A_INT32 err;
+    s32 err;
     struct mmc_host *host;
     struct mmc_card *card;
 	struct sdio_func *func;
-    A_UINT8  cmd52_resp;
-    A_UINT32 clock;
+    u8 cmd52_resp;
+    u32 clock;
 
     func = device->func;
     card = func->card;
@@ -506,9 +506,9 @@
 
     do {
         if (!device->is_suspend) {
-            A_UINT32 resp;
-            A_UINT16 rca;
-            A_UINT32 i;
+            u32 resp;
+            u16 rca;
+            u32 i;
             int bit = fls(host->ocr_avail) - 1;
             /* emulate the mmc_power_up(...) */
             host->ios.vdd = bit;
@@ -644,13 +644,13 @@
     sdio_release_host(func);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -ReinitSDIO \n"));
 
-    return (err) ? A_ERROR : A_OK;
+    return (err) ? A_ERROR : 0;
 }
 
-A_STATUS
-PowerStateChangeNotify(HIF_DEVICE *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
+int
+PowerStateChangeNotify(struct hif_device *device, HIF_DEVICE_POWER_CHANGE_TYPE config)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 #if defined(CONFIG_PM)
 	struct sdio_func *func = device->func;
     int old_reset_val;
@@ -678,7 +678,7 @@
             if (device->powerConfig == HIF_DEVICE_POWER_CUT) {
                 status = ReinitSDIO(device);
             }
-            if (status == A_OK) {
+            if (status == 0) {
                 status = hifEnableFunc(device, func);
             }
             break;
@@ -690,29 +690,29 @@
     return status;
 }
 
-A_STATUS
-HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
-                   void *config, A_UINT32 configLen)
+int
+HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode,
+                   void *config, u32 configLen)
 {
-    A_UINT32 count;
-    A_STATUS status = A_OK;
+    u32 count;
+    int status = 0;
     
     switch(opcode) {
         case HIF_DEVICE_GET_MBOX_BLOCK_SIZE:
-            ((A_UINT32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
-            ((A_UINT32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
-            ((A_UINT32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
-            ((A_UINT32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
+            ((u32 *)config)[0] = HIF_MBOX0_BLOCK_SIZE;
+            ((u32 *)config)[1] = HIF_MBOX1_BLOCK_SIZE;
+            ((u32 *)config)[2] = HIF_MBOX2_BLOCK_SIZE;
+            ((u32 *)config)[3] = HIF_MBOX3_BLOCK_SIZE;
             break;
 
         case HIF_DEVICE_GET_MBOX_ADDR:
             for (count = 0; count < 4; count ++) {
-                ((A_UINT32 *)config)[count] = HIF_MBOX_START_ADDR(count);
+                ((u32 *)config)[count] = HIF_MBOX_START_ADDR(count);
             }
             
-            if (configLen >= sizeof(HIF_DEVICE_MBOX_INFO)) {    
-                SetExtendedMboxWindowInfo((A_UINT16)device->func->device,
-                                          (HIF_DEVICE_MBOX_INFO *)config);
+            if (configLen >= sizeof(struct hif_device_mbox_info)) {    
+                SetExtendedMboxWindowInfo((u16)device->func->device,
+                                          (struct hif_device_mbox_info *)config);
             }
                         
             break;
@@ -723,14 +723,14 @@
             if (!device->scatter_enabled) {
                 return A_ENOTSUP;    
             }
-            status = SetupHIFScatterSupport(device, (HIF_DEVICE_SCATTER_SUPPORT_INFO *)config);
-            if (A_FAILED(status)) {
-                device->scatter_enabled = FALSE;           
+            status = SetupHIFScatterSupport(device, (struct hif_device_scatter_support_info *)config);
+            if (status) {
+                device->scatter_enabled = false;
             }
             break; 
         case HIF_DEVICE_GET_OS_DEVICE:
                 /* pass back a pointer to the SDIO function's "dev" struct */
-            ((HIF_DEVICE_OS_DEVICE_INFO *)config)->pOSDevice = &device->func->dev;
+            ((struct hif_device_os_device_info *)config)->pOSDevice = &device->func->dev;
             break; 
         case HIF_DEVICE_POWER_STATE_CHANGE:
             status = PowerStateChangeNotify(device, *(HIF_DEVICE_POWER_CHANGE_TYPE *)config);
@@ -745,7 +745,7 @@
 }
 
 void
-HIFShutDownDevice(HIF_DEVICE *device)
+HIFShutDownDevice(struct hif_device *device)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +HIFShutDownDevice\n"));
     if (device != NULL) {
@@ -774,8 +774,8 @@
 static void
 hifIRQHandler(struct sdio_func *func)
 {
-    A_STATUS status;
-    HIF_DEVICE *device;
+    int status;
+    struct hif_device *device;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifIRQHandler\n"));
 
     device = getHifDevice(func);
@@ -785,19 +785,19 @@
     status = device->htcCallbacks.dsrHandler(device->htcCallbacks.context);
     sdio_claim_host(device->func);
     atomic_set(&device->irqHandling, 0);
-    AR_DEBUG_ASSERT(status == A_OK || status == A_ECANCELED);
+    AR_DEBUG_ASSERT(status == 0 || status == A_ECANCELED);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifIRQHandler\n"));
 }
 
 /* handle HTC startup via thread*/
 static int startup_task(void *param)
 {
-    HIF_DEVICE *device;
+    struct hif_device *device;
 
-    device = (HIF_DEVICE *)param;
+    device = (struct hif_device *)param;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call HTC from startup_task\n"));
         /* start  up inform DRV layer */
-    if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != A_OK) {
+    if ((osdrvCallbacks.deviceInsertedHandler(osdrvCallbacks.context,device)) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
     }
     return 0;
@@ -806,15 +806,15 @@
 #if defined(CONFIG_PM)
 static int enable_task(void *param)
 {
-    HIF_DEVICE *device;
-    device = (HIF_DEVICE *)param;
+    struct hif_device *device;
+    device = (struct hif_device *)param;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: call  from resume_task\n"));
 
         /* start  up inform DRV layer */
     if (device && 
         device->claimedContext && 
         osdrvCallbacks.devicePowerChangeHandler &&
-        osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != A_OK) 
+        osdrvCallbacks.devicePowerChangeHandler(device->claimedContext, HIF_DEVICE_POWER_UP) != 0)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: Device rejected\n"));
     }
@@ -826,7 +826,7 @@
 static int hifDeviceInserted(struct sdio_func *func, const struct sdio_device_id *id)
 {
     int ret;
-    HIF_DEVICE * device;
+    struct hif_device * device;
     int count;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE,
@@ -837,7 +837,7 @@
     device = getHifDevice(func);
 
     device->id = id;
-    device->is_disabled = TRUE;
+    device->is_disabled = true;
 
     spin_lock_init(&device->lock);
 
@@ -848,7 +848,7 @@
     if (!nohifscattersupport) {
             /* try to allow scatter operation on all instances,
              * unless globally overridden */
-        device->scatter_enabled = TRUE;
+        device->scatter_enabled = true;
     }
 
     /* Initialize the bus requests to be used later */
@@ -866,7 +866,7 @@
 
 
 void
-HIFAckInterrupt(HIF_DEVICE *device)
+HIFAckInterrupt(struct hif_device *device)
 {
     AR_DEBUG_ASSERT(device != NULL);
 
@@ -874,7 +874,7 @@
 }
 
 void
-HIFUnMaskInterrupt(HIF_DEVICE *device)
+HIFUnMaskInterrupt(struct hif_device *device)
 {
     int ret;
 
@@ -890,7 +890,7 @@
     AR_DEBUG_ASSERT(ret == 0);
 }
 
-void HIFMaskInterrupt(HIF_DEVICE *device)
+void HIFMaskInterrupt(struct hif_device *device)
 {
     int ret;
     AR_DEBUG_ASSERT(device != NULL);
@@ -910,7 +910,7 @@
     AR_DEBUG_ASSERT(ret == 0);
 }
 
-BUS_REQUEST *hifAllocateBusRequest(HIF_DEVICE *device)
+BUS_REQUEST *hifAllocateBusRequest(struct hif_device *device)
 {
     BUS_REQUEST *busrequest;
     unsigned long flag;
@@ -930,7 +930,7 @@
 }
 
 void
-hifFreeBusRequest(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+hifFreeBusRequest(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     unsigned long flag;
 
@@ -949,10 +949,10 @@
     spin_unlock_irqrestore(&device->lock, flag);
 }
 
-static A_STATUS hifDisableFunc(HIF_DEVICE *device, struct sdio_func *func)
+static int hifDisableFunc(struct hif_device *device, struct sdio_func *func)
 {
     int ret;
-    A_STATUS status = A_OK;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDisableFunc\n"));
     device = getHifDevice(func);
@@ -988,20 +988,20 @@
 
     sdio_release_host(device->func);
 
-    if (status == A_OK) {
-        device->is_disabled = TRUE;
+    if (status == 0) {
+        device->is_disabled = true;
     }
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDisableFunc\n"));
 
     return status;
 }
 
-static int hifEnableFunc(HIF_DEVICE *device, struct sdio_func *func)
+static int hifEnableFunc(struct hif_device *device, struct sdio_func *func)
 {
     struct task_struct* pTask;
     const char *taskName = NULL;
     int (*taskFunc)(void *) = NULL;
-    int ret = A_OK;
+    int ret = 0;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifEnableFunc\n"));
     device = getHifDevice(func);
@@ -1036,7 +1036,7 @@
 					  __FUNCTION__, HIF_MBOX_BLOCK_SIZE, ret));
             return A_ERROR;
         }
-        device->is_disabled = FALSE;
+        device->is_disabled = false;
         /* create async I/O thread */
         if (!device->async_task) {
             device->async_shutdown = 0;
@@ -1055,7 +1055,7 @@
     if (!device->claimedContext) {
         taskFunc = startup_task;
         taskName = "AR6K startup";
-        ret = A_OK;
+        ret = 0;
 #if defined(CONFIG_PM)
     } else {
         taskFunc = enable_task;
@@ -1080,22 +1080,23 @@
 static int hifDeviceSuspend(struct device *dev)
 {
     struct sdio_func *func=dev_to_sdio_func(dev);
-    A_STATUS status = A_OK;
-    HIF_DEVICE *device;   
+    int status = 0;
+    struct hif_device *device;   
 
     device = getHifDevice(func);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceSuspend\n"));
     if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
-        device->is_suspend = TRUE; /* set true first for PowerStateChangeNotify(..) */
+        device->is_suspend = true; /* set true first for PowerStateChangeNotify(..) */
         status = osdrvCallbacks.deviceSuspendHandler(device->claimedContext);
-        if (status != A_OK) {
-            device->is_suspend = FALSE;
+        if (status) {
+            device->is_suspend = false;
         }
     }
+    CleanupHIFScatterResources(device);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceSuspend\n"));
 
     switch (status) {
-    case A_OK:
+    case 0:
         return 0;
     case A_EBUSY:
         return -EBUSY; /* Hack for kernel in order to support deep sleep and wow */
@@ -1107,27 +1108,27 @@
 static int hifDeviceResume(struct device *dev)
 {
     struct sdio_func *func=dev_to_sdio_func(dev);
-    A_STATUS status = A_OK;
-    HIF_DEVICE *device;   
+    int status = 0;
+    struct hif_device *device;   
 
     device = getHifDevice(func);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceResume\n"));
     if (device && device->claimedContext && osdrvCallbacks.deviceSuspendHandler) {
         status = osdrvCallbacks.deviceResumeHandler(device->claimedContext);
-        if (status == A_OK) {
-            device->is_suspend = FALSE;
+        if (status == 0) {
+            device->is_suspend = false;
         }
     }
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceResume\n"));
 
-    return A_SUCCESS(status) ? 0 : status;
+    return status;
 }
 #endif /* CONFIG_PM */
 
 static void hifDeviceRemoved(struct sdio_func *func)
 {
-    A_STATUS status = A_OK;
-    HIF_DEVICE *device;
+    int status = 0;
+    struct hif_device *device;
     AR_DEBUG_ASSERT(func != NULL);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: +hifDeviceRemoved\n"));
@@ -1137,25 +1138,25 @@
     }
 
     if (device->is_disabled) {
-        device->is_disabled = FALSE;
+        device->is_disabled = false;
     } else {
         status = hifDisableFunc(device, func);
     }
     CleanupHIFScatterResources(device);
      
     delHifDevice(device);
-    AR_DEBUG_ASSERT(status == A_OK);
+    AR_DEBUG_ASSERT(status == 0);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: -hifDeviceRemoved\n"));
 }
 
 /*
  * This should be moved to AR6K HTC layer.
  */
-A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device)
+int hifWaitForPendingRecv(struct hif_device *device)
 {
-    A_INT32 cnt = 10;
-    A_UINT8 host_int_status;
-    A_STATUS status = A_OK;
+    s32 cnt = 10;
+    u8 host_int_status;
+    int status = 0;
 
     do {            		    
         while (atomic_read(&device->irqHandling)) {
@@ -1165,9 +1166,9 @@
 		/* check if there is any pending irq due to force done */
 		host_int_status = 0;
 	    status = HIFReadWrite(device, HOST_INT_STATUS_ADDRESS,
-				    (A_UINT8 *)&host_int_status, sizeof(host_int_status),
+				    (u8 *)&host_int_status, sizeof(host_int_status),
 			  	     HIF_RD_SYNC_BYTE_INC, NULL);
-	    host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)) : 0;
+	    host_int_status = !status ? (host_int_status & (1 << 0)) : 0;
 		if (host_int_status) {
 	        schedule(); /* schedule for next dsrHandler */
 		}
@@ -1178,17 +1179,17 @@
                             ("AR6000: %s(), Unable clear up pending IRQ before the system suspended\n", __FUNCTION__));
      }
 
-    return A_OK;
+    return 0;
 }
     
 
-static HIF_DEVICE *
+static struct hif_device *
 addHifDevice(struct sdio_func *func)
 {
-    HIF_DEVICE *hifdevice;
+    struct hif_device *hifdevice;
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: addHifDevice\n"));
     AR_DEBUG_ASSERT(func != NULL);
-    hifdevice = kzalloc(sizeof(HIF_DEVICE), GFP_KERNEL);
+    hifdevice = kzalloc(sizeof(struct hif_device), GFP_KERNEL);
     AR_DEBUG_ASSERT(hifdevice != NULL);
 #if HIF_USE_DMA_BOUNCE_BUFFER
     hifdevice->dma_buffer = kmalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
@@ -1201,21 +1202,19 @@
     return hifdevice;
 }
 
-static HIF_DEVICE *
+static struct hif_device *
 getHifDevice(struct sdio_func *func)
 {
     AR_DEBUG_ASSERT(func != NULL);
-    return (HIF_DEVICE *)sdio_get_drvdata(func);
+    return (struct hif_device *)sdio_get_drvdata(func);
 }
 
 static void
-delHifDevice(HIF_DEVICE * device)
+delHifDevice(struct hif_device * device)
 {
     AR_DEBUG_ASSERT(device!= NULL);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRACE, ("AR6000: delHifDevice; 0x%p\n", device));
-    if (device->dma_buffer != NULL) {
-        kfree(device->dma_buffer);
-    }
+    kfree(device->dma_buffer);
     kfree(device);
 }
 
@@ -1223,27 +1222,27 @@
 {
 }
 
-void HIFClaimDevice(HIF_DEVICE  *device, void *context)
+void HIFClaimDevice(struct hif_device  *device, void *context)
 {
     device->claimedContext = context;
 }
 
-void HIFReleaseDevice(HIF_DEVICE  *device)
+void HIFReleaseDevice(struct hif_device  *device)
 {
     device->claimedContext = NULL;
 }
 
-A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks)
+int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks)
 {
     if (device->htcCallbacks.context != NULL) {
             /* already in use! */
         return A_ERROR;
     }
     device->htcCallbacks = *callbacks;
-    return A_OK;
+    return 0;
 }
 
-void HIFDetachHTC(HIF_DEVICE *device)
+void HIFDetachHTC(struct hif_device *device)
 {
     A_MEMZERO(&device->htcCallbacks,sizeof(device->htcCallbacks));
 }
@@ -1280,7 +1279,7 @@
 {
     struct mmc_command ioCmd;
     unsigned long      arg;
-    A_INT32 err;
+    s32 err;
     
     memset(&ioCmd,0,sizeof(ioCmd));
     SDIO_SET_CMD52_READ_ARG(arg,0,address);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/hif/sdio/linux_sdio/src/hif_scatter.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
             (((address) & 0x1FFFF) << 9)        | \
             ((bytes_blocks) & 0x1FF)
             
-static void FreeScatterReq(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
+static void FreeScatterReq(struct hif_device *device, struct hif_scatter_req *pReq)
 {   
     unsigned long flag;
 
@@ -60,9 +60,9 @@
         
 }
 
-static HIF_SCATTER_REQ *AllocScatterReq(HIF_DEVICE *device) 
+static struct hif_scatter_req *AllocScatterReq(struct hif_device *device) 
 {
-    DL_LIST       *pItem; 
+    struct dl_list       *pItem; 
     unsigned long flag;
 
     spin_lock_irqsave(&device->lock, flag);
@@ -72,24 +72,24 @@
     spin_unlock_irqrestore(&device->lock, flag);
     
     if (pItem != NULL) {
-        return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink);
     }
     
     return NULL;   
 }
 
     /* called by async task to perform the operation synchronously using direct MMC APIs  */
-A_STATUS DoHifReadWriteScatter(HIF_DEVICE *device, BUS_REQUEST *busrequest)
+int DoHifReadWriteScatter(struct hif_device *device, BUS_REQUEST *busrequest)
 {
     int                     i;
-    A_UINT8                 rw;
-    A_UINT8                 opcode;
+    u8 rw;
+    u8 opcode;
     struct mmc_request      mmcreq;
     struct mmc_command      cmd;
     struct mmc_data         data;
-    HIF_SCATTER_REQ_PRIV   *pReqPriv;   
-    HIF_SCATTER_REQ        *pReq;       
-    A_STATUS                status = A_OK;
+    struct hif_scatter_req_priv   *pReqPriv;   
+    struct hif_scatter_req        *pReq;       
+    int                status = 0;
     struct                  scatterlist *pSg;
     
     pReqPriv = busrequest->pScatterReq;
@@ -176,7 +176,7 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: data error: %d \n",data.error));   
     }
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERROR, ("HIF-SCATTER: FAILED!!! (%s) Address: 0x%X, Block mode (BlockLen: %d, BlockCount: %d)\n",
               (pReq->Request & HIF_WRITE) ? "WRITE":"READ",pReq->Address, data.blksz, data.blocks));        
     }
@@ -199,11 +199,11 @@
 }
 
     /* callback to issue a read-write scatter request */
-static A_STATUS HifReadWriteScatter(HIF_DEVICE *device, HIF_SCATTER_REQ *pReq)
+static int HifReadWriteScatter(struct hif_device *device, struct hif_scatter_req *pReq)
 {
-    A_STATUS             status = A_EINVAL;
-    A_UINT32             request = pReq->Request;
-    HIF_SCATTER_REQ_PRIV *pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0];
+    int             status = A_EINVAL;
+    u32 request = pReq->Request;
+    struct hif_scatter_req_priv *pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0];
     
     do {
         
@@ -237,7 +237,7 @@
         }
         
         if (pReq->TotalLength == 0) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;    
         }
         
@@ -260,26 +260,26 @@
             AR_DEBUG_PRINTF(ATH_DEBUG_SCATTER, ("HIF-SCATTER: queued async req: 0x%lX\n", (unsigned long)pReqPriv->busrequest));
                 /* wake thread, it will process and then take care of the async callback */
             up(&device->sem_async);
-            status = A_OK;
+            status = 0;
         }           
        
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
+    if (status && (request & HIF_ASYNCHRONOUS)) {
         pReq->CompletionStatus = status;
         pReq->CompletionRoutine(pReq);
-        status = A_OK;
+        status = 0;
     }
         
     return status;  
 }
 
     /* setup of HIF scatter resources */
-A_STATUS SetupHIFScatterSupport(HIF_DEVICE *device, HIF_DEVICE_SCATTER_SUPPORT_INFO *pInfo)
+int SetupHIFScatterSupport(struct hif_device *device, struct hif_device_scatter_support_info *pInfo)
 {
-    A_STATUS              status = A_ERROR;   
+    int              status = A_ERROR;
     int                   i;
-    HIF_SCATTER_REQ_PRIV *pReqPriv;
+    struct hif_scatter_req_priv *pReqPriv;
     BUS_REQUEST          *busrequest;
         
     do {
@@ -297,23 +297,23 @@
         
         for (i = 0; i < MAX_SCATTER_REQUESTS; i++) {    
                 /* allocate the private request blob */
-            pReqPriv = (HIF_SCATTER_REQ_PRIV *)A_MALLOC(sizeof(HIF_SCATTER_REQ_PRIV));
+            pReqPriv = (struct hif_scatter_req_priv *)A_MALLOC(sizeof(struct hif_scatter_req_priv));
             if (NULL == pReqPriv) {
                 break;    
             }
-            A_MEMZERO(pReqPriv, sizeof(HIF_SCATTER_REQ_PRIV));
+            A_MEMZERO(pReqPriv, sizeof(struct hif_scatter_req_priv));
                 /* save the device instance*/
             pReqPriv->device = device;      
                 /* allocate the scatter request */
-            pReqPriv->pHifScatterReq = (HIF_SCATTER_REQ *)A_MALLOC(sizeof(HIF_SCATTER_REQ) + 
-                                         (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM))); 
+            pReqPriv->pHifScatterReq = (struct hif_scatter_req *)A_MALLOC(sizeof(struct hif_scatter_req) + 
+                                         (MAX_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item))); 
            
             if (NULL == pReqPriv->pHifScatterReq) {
                 A_FREE(pReqPriv);
                 break;      
             }           
                 /* just zero the main part of the scatter request */
-            A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(HIF_SCATTER_REQ));
+            A_MEMZERO(pReqPriv->pHifScatterReq, sizeof(struct hif_scatter_req));
                 /* back pointer to the private struct */
             pReqPriv->pHifScatterReq->HIFPrivate[0] = pReqPriv;
                 /* allocate a bus request for this scatter request */
@@ -344,11 +344,11 @@
         pInfo->MaxScatterEntries = MAX_SCATTER_ENTRIES_PER_REQ;
         pInfo->MaxTransferSizePerScatterReq = MAX_SCATTER_REQ_TRANSFER_SIZE;
      
-        status = A_OK;
+        status = 0;
         
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         CleanupHIFScatterResources(device);   
     }
     
@@ -356,10 +356,10 @@
 }
 
     /* clean up scatter support */
-void CleanupHIFScatterResources(HIF_DEVICE *device)
+void CleanupHIFScatterResources(struct hif_device *device)
 {
-    HIF_SCATTER_REQ_PRIV    *pReqPriv;
-    HIF_SCATTER_REQ         *pReq;
+    struct hif_scatter_req_priv    *pReqPriv;
+    struct hif_scatter_req         *pReq;
     
         /* empty the free list */
         
@@ -371,7 +371,7 @@
             break;    
         }   
         
-        pReqPriv = (HIF_SCATTER_REQ_PRIV *)pReq->HIFPrivate[0];
+        pReqPriv = (struct hif_scatter_req_priv *)pReq->HIFPrivate[0];
         A_ASSERT(pReqPriv != NULL);
         
         if (pReqPriv->busrequest != NULL) {
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.c	2011-05-19 00:06:34.000000000 -0400
@@ -35,21 +35,21 @@
 
 #define MAILBOX_FOR_BLOCK_SIZE          1
 
-A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
+int DevEnableInterrupts(struct ar6k_device *pDev);
+int DevDisableInterrupts(struct ar6k_device *pDev);
 
-static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev);
+static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev);
 
-void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket)
+void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket)
 {
     LOCK_AR6K(pDev);
     HTC_PACKET_ENQUEUE(&pDev->RegisterIOList,pPacket);
     UNLOCK_AR6K(pDev);
 }
 
-HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev)
+struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev)
 {
-    HTC_PACKET *pPacket;
+    struct htc_packet *pPacket;
 
     LOCK_AR6K(pDev);
     pPacket = HTC_PACKET_DEQUEUE(&pDev->RegisterIOList);
@@ -58,13 +58,13 @@
     return pPacket;
 }
 
-void DevCleanup(AR6K_DEVICE *pDev)
+void DevCleanup(struct ar6k_device *pDev)
 {
     DevCleanupGMbox(pDev);
 
     if (pDev->HifAttached) {
         HIFDetachHTC(pDev->HIFDevice);
-        pDev->HifAttached = FALSE;
+        pDev->HifAttached = false;
     }
 
     DevCleanupVirtualScatterSupport(pDev);
@@ -74,10 +74,10 @@
     }
 }
 
-A_STATUS DevSetup(AR6K_DEVICE *pDev)
+int DevSetup(struct ar6k_device *pDev)
 {
-    A_UINT32 blocksizes[AR6K_MAILBOXES];
-    A_STATUS status = A_OK;
+    u32 blocksizes[AR6K_MAILBOXES];
+    int status = 0;
     int      i;
     HTC_CALLBACKS htcCallbacks;
 
@@ -96,24 +96,24 @@
 
         status = HIFAttachHTC(pDev->HIFDevice, &htcCallbacks);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
-        pDev->HifAttached = TRUE;
+        pDev->HifAttached = true;
 
             /* get the addresses for all 4 mailboxes */
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
                                     &pDev->MailBoxInfo, sizeof(pDev->MailBoxInfo));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
             /* carve up register I/O packets (these are for ASYNC register I/O ) */
         for (i = 0; i < AR6K_MAX_REG_IO_BUFFERS; i++) {
-            HTC_PACKET *pIOPacket;
+            struct htc_packet *pIOPacket;
             pIOPacket = &pDev->RegIOBuffers[i].HtcPacket;
             SET_HTC_PACKET_INFO_RX_REFILL(pIOPacket,
                                           pDev,
@@ -127,8 +127,8 @@
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     blocksizes, sizeof(blocksizes));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
@@ -174,14 +174,14 @@
                     AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
                         ("HIF requests that DSR yield per %d RECV packets \n",
                         pDev->HifIRQYieldParams.RecvPacketYieldCount));
-                    pDev->DSRCanYield = TRUE;
+                    pDev->DSRCanYield = true;
                 }
                 break;
             case HIF_DEVICE_IRQ_ASYNC_SYNC:
                 AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("HIF Interrupt processing is ASYNC and SYNC\n"));
                 break;
             default:
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
         }
 
         pDev->HifMaskUmaskRecvEvent = NULL;
@@ -197,18 +197,18 @@
 
         status = DevDisableInterrupts(pDev);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
         status = DevSetupGMbox(pDev);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (pDev->HifAttached) {
             HIFDetachHTC(pDev->HIFDevice);
-            pDev->HifAttached = FALSE;
+            pDev->HifAttached = false;
         }
     }
 
@@ -216,10 +216,10 @@
 
 }
 
-A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev)
+int DevEnableInterrupts(struct ar6k_device *pDev)
 {
-    A_STATUS                  status;
-    AR6K_IRQ_ENABLE_REGISTERS regs;
+    int                  status;
+    struct ar6k_irq_enable_registers regs;
 
     LOCK_AR6K(pDev);
 
@@ -254,7 +254,7 @@
         COUNTER_INT_STATUS_ENABLE_BIT_SET(AR6K_TARGET_DEBUG_INTR_MASK);
 
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
     UNLOCK_AR6K(pDev);
 
@@ -266,7 +266,7 @@
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         /* Can't write it for some reason */
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Failed to update interrupt control registers err: %d\n", status));
@@ -276,9 +276,9 @@
     return status;
 }
 
-A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev)
+int DevDisableInterrupts(struct ar6k_device *pDev)
 {
-    AR6K_IRQ_ENABLE_REGISTERS regs;
+    struct ar6k_irq_enable_registers regs;
 
     LOCK_AR6K(pDev);
         /* Disable all interrupts */
@@ -287,7 +287,7 @@
     pDev->IrqEnableRegisters.error_status_enable = 0;
     pDev->IrqEnableRegisters.counter_int_status_enable = 0;
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
     UNLOCK_AR6K(pDev);
 
@@ -301,7 +301,7 @@
 }
 
 /* enable device interrupts */
-A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev)
+int DevUnmaskInterrupts(struct ar6k_device *pDev)
 {
     /* for good measure, make sure interrupt are disabled before unmasking at the HIF
      * layer.
@@ -309,7 +309,7 @@
      * and when HTC is finally ready to handle interrupts, other software can perform target "soft" resets.
      * The AR6K interrupt enables reset back to an "enabled" state when this happens.
      *  */
-    A_STATUS IntStatus = A_OK;
+    int IntStatus = 0;
     DevDisableInterrupts(pDev);
 
 #ifdef THREAD_X
@@ -327,7 +327,7 @@
 }
 
 /* disable all device interrupts */
-A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev)
+int DevMaskInterrupts(struct ar6k_device *pDev)
 {
         /* mask the interrupt at the HIF layer, we don't want a stray interrupt taken while
          * we zero out our shadow registers in DevDisableInterrupts()*/
@@ -337,13 +337,13 @@
 }
 
 /* callback when our fetch to enable/disable completes */
-static void DevDoEnableDisableRecvAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevDoEnableDisableRecvAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDoEnableDisableRecvAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" Failed to disable receiver, status:%d \n", pPacket->Status));
     }
@@ -355,10 +355,10 @@
 /* disable packet reception (used in case the host runs out of buffers)
  * this is the "override" method when the HIF reports another methods to
  * disable recv events */
-static A_STATUS DevDoEnableDisableRecvOverride(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
+static int DevDoEnableDisableRecvOverride(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode)
 {
-    A_STATUS                  status = A_OK;
-    HTC_PACKET                *pIOPacket = NULL;
+    int                  status = 0;
+    struct htc_packet                *pIOPacket = NULL;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("DevDoEnableDisableRecvOverride: Enable:%d Mode:%d\n",
             EnableRecv,AsyncMode));
@@ -371,7 +371,7 @@
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
@@ -391,9 +391,9 @@
                                              EnableRecv ? HIF_UNMASK_RECV : HIF_MASK_RECV,
                                              NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status) && (pIOPacket != NULL)) {
+    if (status && (pIOPacket != NULL)) {
         AR6KFreeIOPacket(pDev,pIOPacket);
     }
 
@@ -403,11 +403,11 @@
 /* disable packet reception (used in case the host runs out of buffers)
  * this is the "normal" method using the interrupt enable registers through
  * the host I/F */
-static A_STATUS DevDoEnableDisableRecvNormal(AR6K_DEVICE *pDev, A_BOOL EnableRecv, A_BOOL AsyncMode)
+static int DevDoEnableDisableRecvNormal(struct ar6k_device *pDev, bool EnableRecv, bool AsyncMode)
 {
-    A_STATUS                  status = A_OK;
-    HTC_PACKET                *pIOPacket = NULL;
-    AR6K_IRQ_ENABLE_REGISTERS regs;
+    int                  status = 0;
+    struct htc_packet                *pIOPacket = NULL;
+    struct ar6k_irq_enable_registers regs;
 
         /* take the lock to protect interrupt enable shadows */
     LOCK_AR6K(pDev);
@@ -419,7 +419,7 @@
     }
 
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
     UNLOCK_AR6K(pDev);
 
     do {
@@ -430,12 +430,12 @@
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
                 /* copy values to write to our async I/O buffer */
-            A_MEMCPY(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
+            memcpy(pIOPacket->pBuffer,&regs,AR6K_IRQ_ENABLE_REGS_SIZE);
 
                 /* stick in our completion routine when the I/O operation completes */
             pIOPacket->Completion = DevDoEnableDisableRecvAsyncHandler;
@@ -460,9 +460,9 @@
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status) && (pIOPacket != NULL)) {
+    if (status && (pIOPacket != NULL)) {
         AR6KFreeIOPacket(pDev,pIOPacket);
     }
 
@@ -470,29 +470,29 @@
 }
 
 
-A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
+int DevStopRecv(struct ar6k_device *pDev, bool AsyncMode)
 {
     if (NULL == pDev->HifMaskUmaskRecvEvent) {
-        return DevDoEnableDisableRecvNormal(pDev,FALSE,AsyncMode);
+        return DevDoEnableDisableRecvNormal(pDev,false,AsyncMode);
     } else {
-        return DevDoEnableDisableRecvOverride(pDev,FALSE,AsyncMode);
+        return DevDoEnableDisableRecvOverride(pDev,false,AsyncMode);
     }
 }
 
-A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL AsyncMode)
+int DevEnableRecv(struct ar6k_device *pDev, bool AsyncMode)
 {
     if (NULL == pDev->HifMaskUmaskRecvEvent) {
-        return DevDoEnableDisableRecvNormal(pDev,TRUE,AsyncMode);
+        return DevDoEnableDisableRecvNormal(pDev,true,AsyncMode);
     } else {
-        return DevDoEnableDisableRecvOverride(pDev,TRUE,AsyncMode);
+        return DevDoEnableDisableRecvOverride(pDev,true,AsyncMode);
     }
 }
 
-A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending)
+int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending)
 {
-    A_STATUS    status          = A_OK;
-    A_UCHAR     host_int_status = 0x0;
-    A_UINT32    counter         = 0x0;
+    int    status          = 0;
+    u8     host_int_status = 0x0;
+    u32 counter         = 0x0;
 
     if(TimeoutInMs < 100)
     {
@@ -507,25 +507,25 @@
         status = HIFReadWrite(pDev->HIFDevice,
                               HOST_INT_STATUS_ADDRESS,
                              &host_int_status,
-                              sizeof(A_UCHAR),
+                              sizeof(u8),
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
-        if(A_FAILED(status))
+        if (status)
         {
             AR_DEBUG_PRINTF(ATH_LOG_ERR,("DevWaitForPendingRecv:Read HOST_INT_STATUS_ADDRESS Failed 0x%X\n",status));
             break;
         }
 
-        host_int_status = A_SUCCESS(status) ? (host_int_status & (1 << 0)):0;
+        host_int_status = !status ? (host_int_status & (1 << 0)):0;
         if(!host_int_status)
         {
-            status          = A_OK;
-           *pbIsRecvPending = FALSE;
+            status          = 0;
+           *pbIsRecvPending = false;
             break;
         }
         else
         {
-            *pbIsRecvPending = TRUE;
+            *pbIsRecvPending = true;
         }
 
         A_MDELAY(100);
@@ -536,9 +536,9 @@
     return status;
 }
 
-void DevDumpRegisters(AR6K_DEVICE               *pDev,
-                      AR6K_IRQ_PROC_REGISTERS   *pIrqProcRegs,
-                      AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs)
+void DevDumpRegisters(struct ar6k_device               *pDev,
+                      struct ar6k_irq_proc_registers   *pIrqProcRegs,
+                      struct ar6k_irq_enable_registers *pIrqEnableRegs)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("\n<------- Register Table -------->\n"));
@@ -585,39 +585,39 @@
 }
 
 
-#define DEV_GET_VIRT_DMA_INFO(p)  ((DEV_SCATTER_DMA_VIRTUAL_INFO *)((p)->HIFPrivate[0]))
+#define DEV_GET_VIRT_DMA_INFO(p)  ((struct dev_scatter_dma_virtual_info *)((p)->HIFPrivate[0]))
 
-static HIF_SCATTER_REQ *DevAllocScatterReq(HIF_DEVICE *Context)
+static struct hif_scatter_req *DevAllocScatterReq(struct hif_device *Context)
 {
-    DL_LIST *pItem;
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct dl_list *pItem;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
     LOCK_AR6K(pDev);
     pItem = DL_ListRemoveItemFromHead(&pDev->ScatterReqHead);
     UNLOCK_AR6K(pDev);
     if (pItem != NULL) {
-        return A_CONTAINING_STRUCT(pItem, HIF_SCATTER_REQ, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct hif_scatter_req, ListLink);
     }
     return NULL;
 }
 
-static void DevFreeScatterReq(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
+static void DevFreeScatterReq(struct hif_device *Context, struct hif_scatter_req *pReq)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
     LOCK_AR6K(pDev);
     DL_ListInsertTail(&pDev->ScatterReqHead, &pReq->ListLink);
     UNLOCK_AR6K(pDev);
 }
 
-A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA)
+int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA)
 {
-    A_UINT8         *pDMABuffer = NULL;
+    u8 *pDMABuffer = NULL;
     int             i, remaining;
-    A_UINT32        length;
+    u32 length;
 
     pDMABuffer = pReq->pScatterBounceBuffer;
 
     if (pDMABuffer == NULL) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return A_EINVAL;
     }
 
@@ -628,30 +628,30 @@
         length = min((int)pReq->ScatterList[i].Length, remaining);
 
         if (length != (int)pReq->ScatterList[i].Length) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
                 /* there is a problem with the scatter list */
             return A_EINVAL;
         }
 
         if (FromDMA) {
                 /* from DMA buffer */
-            A_MEMCPY(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
+            memcpy(pReq->ScatterList[i].pBuffer, pDMABuffer , length);
         } else {
                 /* to DMA buffer */
-            A_MEMCPY(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
+            memcpy(pDMABuffer, pReq->ScatterList[i].pBuffer, length);
         }
 
         pDMABuffer += length;
         remaining -= length;
     }
 
-    return A_OK;
+    return 0;
 }
 
-static void DevReadWriteScatterAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevReadWriteScatterAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE     *pDev = (AR6K_DEVICE *)Context;
-    HIF_SCATTER_REQ *pReq = (HIF_SCATTER_REQ *)pPacket->pPktContext;
+    struct ar6k_device     *pDev = (struct ar6k_device *)Context;
+    struct hif_scatter_req *pReq = (struct hif_scatter_req *)pPacket->pPktContext;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevReadWriteScatterAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
     
@@ -664,12 +664,12 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-DevReadWriteScatterAsyncHandler \n"));
 }
 
-static A_STATUS DevReadWriteScatter(HIF_DEVICE *Context, HIF_SCATTER_REQ *pReq)
+static int DevReadWriteScatter(struct hif_device *Context, struct hif_scatter_req *pReq)
 {
-    AR6K_DEVICE     *pDev = (AR6K_DEVICE *)Context;
-    A_STATUS        status = A_OK;
-    HTC_PACKET      *pIOPacket = NULL;
-    A_UINT32        request = pReq->Request;
+    struct ar6k_device     *pDev = (struct ar6k_device *)Context;
+    int        status = 0;
+    struct htc_packet      *pIOPacket = NULL;
+    u32 request = pReq->Request;
 
     do {
 
@@ -680,7 +680,7 @@
         }
 
         if (pReq->TotalLength == 0) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -719,27 +719,27 @@
                               request,
                               (request & HIF_ASYNCHRONOUS) ? pIOPacket : NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if ((status != A_PENDING) && A_FAILED(status) && (request & HIF_ASYNCHRONOUS)) {
+    if ((status != A_PENDING) && status && (request & HIF_ASYNCHRONOUS)) {
         if (pIOPacket != NULL) {
             AR6KFreeIOPacket(pDev,pIOPacket);
         }
         pReq->CompletionStatus = status;
         pReq->CompletionRoutine(pReq);
-        status = A_OK;
+        status = 0;
     }
 
     return status;
 }
 
 
-static void DevCleanupVirtualScatterSupport(AR6K_DEVICE *pDev)
+static void DevCleanupVirtualScatterSupport(struct ar6k_device *pDev)
 {
-    HIF_SCATTER_REQ *pReq;
+    struct hif_scatter_req *pReq;
 
     while (1) {
-        pReq = DevAllocScatterReq((HIF_DEVICE *)pDev);
+        pReq = DevAllocScatterReq((struct hif_device *)pDev);
         if (NULL == pReq) {
             break;
         }
@@ -749,23 +749,23 @@
 }
 
     /* function to set up virtual scatter support if HIF layer has not implemented the interface */
-static A_STATUS DevSetupVirtualScatterSupport(AR6K_DEVICE *pDev)
+static int DevSetupVirtualScatterSupport(struct ar6k_device *pDev)
 {
-    A_STATUS                     status = A_OK;
+    int                     status = 0;
     int                          bufferSize, sgreqSize;
     int                          i;
-    DEV_SCATTER_DMA_VIRTUAL_INFO *pVirtualInfo;
-    HIF_SCATTER_REQ              *pReq;
+    struct dev_scatter_dma_virtual_info *pVirtualInfo;
+    struct hif_scatter_req              *pReq;
 
-    bufferSize = sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO) +
+    bufferSize = sizeof(struct dev_scatter_dma_virtual_info) +
                 2 * (A_GET_CACHE_LINE_BYTES()) + AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
 
-    sgreqSize = sizeof(HIF_SCATTER_REQ) +
-                    (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(HIF_SCATTER_ITEM));
+    sgreqSize = sizeof(struct hif_scatter_req) +
+                    (AR6K_SCATTER_ENTRIES_PER_REQ - 1) * (sizeof(struct hif_scatter_item));
 
     for (i = 0; i < AR6K_SCATTER_REQS; i++) {
             /* allocate the scatter request, buffer info and the actual virtual buffer itself */
-        pReq = (HIF_SCATTER_REQ *)A_MALLOC(sgreqSize + bufferSize);
+        pReq = (struct hif_scatter_req *)A_MALLOC(sgreqSize + bufferSize);
 
         if (NULL == pReq) {
             status = A_NO_MEMORY;
@@ -775,8 +775,8 @@
         A_MEMZERO(pReq, sgreqSize);
 
             /* the virtual DMA starts after the scatter request struct */
-        pVirtualInfo = (DEV_SCATTER_DMA_VIRTUAL_INFO *)((A_UINT8 *)pReq + sgreqSize);
-        A_MEMZERO(pVirtualInfo, sizeof(DEV_SCATTER_DMA_VIRTUAL_INFO));
+        pVirtualInfo = (struct dev_scatter_dma_virtual_info *)((u8 *)pReq + sgreqSize);
+        A_MEMZERO(pVirtualInfo, sizeof(struct dev_scatter_dma_virtual_info));
 
         pVirtualInfo->pVirtDmaBuffer = &pVirtualInfo->DataArea[0];
             /* align buffer to cache line in case host controller can actually DMA this */
@@ -787,10 +787,10 @@
         pReq->ScatterMethod = HIF_SCATTER_DMA_BOUNCE;
         pReq->pScatterBounceBuffer = pVirtualInfo->pVirtDmaBuffer;
             /* free request to the list */
-        DevFreeScatterReq((HIF_DEVICE *)pDev,pReq);
+        DevFreeScatterReq((struct hif_device *)pDev,pReq);
     }
 
-    if (A_FAILED(status)) {
+    if (status) {
         DevCleanupVirtualScatterSupport(pDev);
     } else {
         pDev->HifScatterInfo.pAllocateReqFunc = DevAllocScatterReq;
@@ -804,16 +804,25 @@
             pDev->HifScatterInfo.MaxScatterEntries = AR6K_SCATTER_ENTRIES_PER_REQ;
             pDev->HifScatterInfo.MaxTransferSizePerScatterReq = AR6K_MAX_TRANSFER_SIZE_PER_SCATTER;
         }
-        pDev->ScatterIsVirtual = TRUE;
+        pDev->ScatterIsVirtual = true;
     }
 
     return status;
 }
 
+int DevCleanupMsgBundling(struct ar6k_device *pDev)
+{
+    if(NULL != pDev)
+    {
+        DevCleanupVirtualScatterSupport(pDev);
+    }
+
+    return 0;
+}
 
-A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer)
+int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer)
 {
-    A_STATUS status;
+    int status;
 
     if (pDev->MailBoxInfo.Flags & HIF_MBOX_FLAG_NO_BUNDLING) {
         AR_DEBUG_PRINTF(ATH_DEBUG_WARN, ("HIF requires bundling disabled\n"));
@@ -825,14 +834,14 @@
                                 &pDev->HifScatterInfo,
                                 sizeof(pDev->HifScatterInfo));
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
             ("AR6K: ** HIF layer does not support scatter requests (%d) \n",status));
 
             /* we can try to use a virtual DMA scatter mechanism using legacy HIFReadWrite() */
         status = DevSetupVirtualScatterSupport(pDev);
 
-        if (A_SUCCESS(status)) {
+        if (!status) {
              AR_DEBUG_PRINTF(ATH_DEBUG_ANY,
                 ("AR6K: virtual scatter transfers enabled (max scatter items:%d: maxlen:%d) \n",
                     DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
@@ -844,7 +853,7 @@
                     DEV_GET_MAX_MSG_PER_BUNDLE(pDev), DEV_GET_MAX_BUNDLE_LENGTH(pDev)));
     }
 
-    if (A_SUCCESS(status)) {
+    if (!status) {
             /* for the recv path, the maximum number of bytes per recv bundle is just limited
              * by the maximum transfer size at the HIF layer */
         pDev->MaxRecvBundleSize = pDev->HifScatterInfo.MaxTransferSizePerScatterReq;
@@ -876,21 +885,21 @@
     return status;
 }
 
-A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async)
+int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async)
 {
-    A_STATUS status;
+    int status;
 
     if (Read) {
             /* read operation */
         pScatterReq->Request = (Async) ? HIF_RD_ASYNC_BLOCK_FIX : HIF_RD_SYNC_BLOCK_FIX;
         pScatterReq->Address = pDev->MailBoxInfo.MboxAddresses[HTC_MAILBOX];
-        A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
+        A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev));
     } else {
-        A_UINT32 mailboxWidth;
+        u32 mailboxWidth;
 
             /* write operation */
         pScatterReq->Request = (Async) ? HIF_WR_ASYNC_BLOCK_INC : HIF_WR_SYNC_BLOCK_INC;
-        A_ASSERT(pScatterReq->TotalLength <= (A_UINT32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
+        A_ASSERT(pScatterReq->TotalLength <= (u32)DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev));
         if (pScatterReq->TotalLength > AR6K_LEGACY_MAX_WRITE_LENGTH) {
                 /* for large writes use the extended address */
             pScatterReq->Address = pDev->MailBoxInfo.MboxProp[HTC_MAILBOX].ExtendedAddress;
@@ -919,11 +928,11 @@
 
     status = DEV_PREPARE_SCATTER_OPERATION(pScatterReq);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (Async) {
             pScatterReq->CompletionStatus = status;
             pScatterReq->CompletionRoutine(pScatterReq);
-            return A_OK;
+            return 0;
         }
         return status;
     }
@@ -936,7 +945,7 @@
         DEV_FINISH_SCATTER_OPERATION(pScatterReq);
     } else {
         if (status == A_PENDING) {
-            status = A_OK;
+            status = 0;
         }
     }
 
@@ -1002,16 +1011,16 @@
 
 #define TEST_CREDITS_RECV_TIMEOUT 100
 
-static A_UINT8  g_Buffer[TOTAL_BYTES];
-static A_UINT32 g_MailboxAddrs[AR6K_MAILBOXES];
-static A_UINT32 g_BlockSizes[AR6K_MAILBOXES];
+static u8 g_Buffer[TOTAL_BYTES];
+static u32 g_MailboxAddrs[AR6K_MAILBOXES];
+static u32 g_BlockSizes[AR6K_MAILBOXES];
 
 #define BUFFER_PROC_LIST_DEPTH 4
 
-typedef struct _BUFFER_PROC_LIST{
-    A_UINT8  *pBuffer;
-    A_UINT32 length;
-}BUFFER_PROC_LIST;
+struct buffer_proc_list {
+    u8 *pBuffer;
+    u32 length;
+};
 
 
 #define PUSH_BUFF_PROC_ENTRY(pList,len,pCurrpos) \
@@ -1023,9 +1032,9 @@
 }
 
 /* a simple and crude way to send different "message" sizes */
-static void AssembleBufferList(BUFFER_PROC_LIST *pList)
+static void AssembleBufferList(struct buffer_proc_list *pList)
 {
-    A_UINT8 *pBuffer = g_Buffer;
+    u8 *pBuffer = g_Buffer;
 
 #if BUFFER_PROC_LIST_DEPTH < 4
 #error "Buffer processing list depth is not deep enough!!"
@@ -1038,17 +1047,17 @@
 
 }
 
-#define FILL_ZERO     TRUE
-#define FILL_COUNTING FALSE
-static void InitBuffers(A_BOOL Zero)
+#define FILL_ZERO     true
+#define FILL_COUNTING false
+static void InitBuffers(bool Zero)
 {
-    A_UINT16 *pBuffer16 = (A_UINT16 *)g_Buffer;
+    u16 *pBuffer16 = (u16 *)g_Buffer;
     int      i;
 
         /* fill buffer with 16 bit counting pattern or zeros */
     for (i = 0; i <  (TOTAL_BYTES / 2) ; i++) {
         if (!Zero) {
-            pBuffer16[i] = (A_UINT16)i;
+            pBuffer16[i] = (u16)i;
         } else {
             pBuffer16[i] = 0;
         }
@@ -1056,11 +1065,11 @@
 }
 
 
-static A_BOOL CheckOneBuffer(A_UINT16 *pBuffer16, int Length)
+static bool CheckOneBuffer(u16 *pBuffer16, int Length)
 {
     int      i;
-    A_UINT16 startCount;
-    A_BOOL   success = TRUE;
+    u16 startCount;
+    bool   success = true;
 
         /* get the starting count */
     startCount = pBuffer16[0];
@@ -1069,10 +1078,10 @@
         /* scan the buffer and verify */
     for (i = 0; i < (Length / 2) ; i++,startCount++) {
             /* target will invert all the data */
-        if ((A_UINT16)pBuffer16[i] != (A_UINT16)~startCount) {
-            success = FALSE;
+        if ((u16)pBuffer16[i] != (u16)~startCount) {
+            success = false;
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Data Got:0x%X, Expecting:0x%X (offset:%d, total:%d) \n",
-                        pBuffer16[i], ((A_UINT16)~startCount), i, Length));
+                        pBuffer16[i], ((u16)~startCount), i, Length));
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("0x%X 0x%X 0x%X 0x%X \n",
                         pBuffer16[i], pBuffer16[i + 1], pBuffer16[i + 2],pBuffer16[i+3]));
             break;
@@ -1082,21 +1091,21 @@
     return success;
 }
 
-static A_BOOL CheckBuffers(void)
+static bool CheckBuffers(void)
 {
     int      i;
-    A_BOOL   success = TRUE;
-    BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
+    bool   success = true;
+    struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH];
 
         /* assemble the list */
     AssembleBufferList(checkList);
 
         /* scan the buffers and verify */
     for (i = 0; i < BUFFER_PROC_LIST_DEPTH ; i++) {
-        success = CheckOneBuffer((A_UINT16 *)checkList[i].pBuffer, checkList[i].length);
+        success = CheckOneBuffer((u16 *)checkList[i].pBuffer, checkList[i].length);
         if (!success) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Buffer : 0x%X, Length:%d failed verify \n",
-                        (A_UINT32)checkList[i].pBuffer, checkList[i].length));
+                        (u32)checkList[i].pBuffer, checkList[i].length));
             break;
         }
     }
@@ -1105,10 +1114,10 @@
 }
 
     /* find the end marker for the last buffer we will be sending */
-static A_UINT16 GetEndMarker(void)
+static u16 GetEndMarker(void)
 {
-    A_UINT8  *pBuffer;
-    BUFFER_PROC_LIST checkList[BUFFER_PROC_LIST_DEPTH];
+    u8 *pBuffer;
+    struct buffer_proc_list checkList[BUFFER_PROC_LIST_DEPTH];
 
         /* fill up buffers with the normal counting pattern */
     InitBuffers(FILL_COUNTING);
@@ -1119,17 +1128,17 @@
     pBuffer = &(checkList[BUFFER_PROC_LIST_DEPTH - 1].pBuffer[(checkList[BUFFER_PROC_LIST_DEPTH - 1].length) - 2]);
 
         /* the last count in the last buffer is the marker */
-    return (A_UINT16)pBuffer[0] | ((A_UINT16)pBuffer[1] << 8);
+    return (u16)pBuffer[0] | ((u16)pBuffer[1] << 8);
 }
 
 #define ATH_PRINT_OUT_ZONE ATH_DEBUG_ERR
 
 /* send the ordered buffers to the target */
-static A_STATUS SendBuffers(AR6K_DEVICE *pDev, int mbox)
+static int SendBuffers(struct ar6k_device *pDev, int mbox)
 {
-    A_STATUS         status = A_OK;
-    A_UINT32         request = HIF_WR_SYNC_BLOCK_INC;
-    BUFFER_PROC_LIST sendList[BUFFER_PROC_LIST_DEPTH];
+    int         status = 0;
+    u32 request = HIF_WR_SYNC_BLOCK_INC;
+    struct buffer_proc_list sendList[BUFFER_PROC_LIST_DEPTH];
     int              i;
     int              totalBytes = 0;
     int              paddedLength;
@@ -1156,7 +1165,7 @@
                               paddedLength,
                               request,
                               NULL);
-        if (status != A_OK) {
+        if (status) {
             break;
         }
         totalBytes += sendList[i].length;
@@ -1169,20 +1178,20 @@
 }
 
 /* poll the mailbox credit counter until we get a credit or timeout */
-static A_STATUS GetCredits(AR6K_DEVICE *pDev, int mbox, int *pCredits)
+static int GetCredits(struct ar6k_device *pDev, int mbox, int *pCredits)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      timeout = TEST_CREDITS_RECV_TIMEOUT;
-    A_UINT8  credits = 0;
-    A_UINT32 address;
+    u8 credits = 0;
+    u32 address;
 
-    while (TRUE) {
+    while (true) {
 
             /* Read the counter register to get credits, this auto-decrements  */
         address = COUNT_DEC_ADDRESS + (AR6K_MAILBOXES + mbox) * 4;
         status = HIFReadWrite(pDev->HIFDevice, address, &credits, sizeof(credits),
                               HIF_RD_SYNC_BYTE_FIX, NULL);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("Unable to decrement the command credit count register (mbox=%d)\n",mbox));
             status = A_ERROR;
@@ -1207,7 +1216,7 @@
 
     }
 
-    if (status == A_OK) {
+    if (status == 0) {
         *pCredits = credits;
     }
 
@@ -1216,11 +1225,11 @@
 
 
 /* wait for the buffers to come back */
-static A_STATUS RecvBuffers(AR6K_DEVICE *pDev, int mbox)
+static int RecvBuffers(struct ar6k_device *pDev, int mbox)
 {
-    A_STATUS         status = A_OK;
-    A_UINT32         request = HIF_RD_SYNC_BLOCK_INC;
-    BUFFER_PROC_LIST recvList[BUFFER_PROC_LIST_DEPTH];
+    int         status = 0;
+    u32 request = HIF_RD_SYNC_BLOCK_INC;
+    struct buffer_proc_list recvList[BUFFER_PROC_LIST_DEPTH];
     int              curBuffer;
     int              credits;
     int              i;
@@ -1244,7 +1253,7 @@
              * until we get at least 1 credit or it times out */
         status = GetCredits(pDev, mbox, &credits);
 
-        if (status != A_OK) {
+        if (status) {
             break;
         }
 
@@ -1264,7 +1273,7 @@
                                   paddedLength,
                                   request,
                                   NULL);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to read %d bytes on mailbox:%d : address:0x%X \n",
                         recvList[curBuffer].length, mbox, g_MailboxAddrs[mbox]));
                 break;
@@ -1275,7 +1284,7 @@
             curBuffer++;
         }
 
-        if (status != A_OK) {
+        if (status) {
             break;
         }
             /* go back and get some more */
@@ -1283,7 +1292,7 @@
     }
 
     if (totalBytes != TEST_BYTES) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
     }  else {
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("Got all buffers on mbox:%d total recv :%d (w/Padding : %d) \n",
             mbox, totalBytes, totalwPadding));
@@ -1294,15 +1303,15 @@
 
 }
 
-static A_STATUS DoOneMboxHWTest(AR6K_DEVICE *pDev, int mbox)
+static int DoOneMboxHWTest(struct ar6k_device *pDev, int mbox)
 {
-    A_STATUS status;
+    int status;
 
     do {
             /* send out buffers */
         status = SendBuffers(pDev,mbox);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Sending buffers Failed : %d mbox:%d\n",status,mbox));
             break;
         }
@@ -1310,7 +1319,7 @@
             /* go get them, this will block */
         status =  RecvBuffers(pDev, mbox);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Recv buffers Failed : %d mbox:%d\n",status,mbox));
             break;
         }
@@ -1324,21 +1333,21 @@
 
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" Send/Recv success! mailbox : %d \n",mbox));
 
-    }  while (FALSE);
+    }  while (false);
 
     return status;
 }
 
 /* here is where the test starts */
-A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev)
+int DoMboxHWTest(struct ar6k_device *pDev)
 {
     int      i;
-    A_STATUS status;
+    int status;
     int      credits = 0;
-    A_UINT8  params[4];
+    u8 params[4];
     int      numBufs;
     int      bufferSize;
-    A_UINT16 temp;
+    u16 temp;
 
 
     AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest START -  \n"));
@@ -1348,8 +1357,8 @@
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_ADDR,
                                     g_MailboxAddrs, sizeof(g_MailboxAddrs));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
@@ -1357,8 +1366,8 @@
         status = HIFConfigureDevice(pDev->HIFDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     g_BlockSizes, sizeof(g_BlockSizes));
 
-        if (status != A_OK) {
-            A_ASSERT(FALSE);
+        if (status) {
+            A_ASSERT(false);
             break;
         }
 
@@ -1380,7 +1389,7 @@
              * mailbox 0 */
         status = GetCredits(pDev, 0, &credits);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait for target ready \n"));
             break;
         }
@@ -1395,13 +1404,13 @@
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to wait get parameters \n"));
             break;
         }
 
         numBufs = params[0];
-        bufferSize = (int)(((A_UINT16)params[2] << 8) | (A_UINT16)params[1]);
+        bufferSize = (int)(((u16)params[2] << 8) | (u16)params[1]);
 
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE,
             ("Target parameters: bufs per mailbox:%d, buffer size:%d bytes (total space: %d, minimum required space (w/padding): %d) \n",
@@ -1418,29 +1427,29 @@
 
         status = HIFReadWrite(pDev->HIFDevice,
                               SCRATCH_ADDRESS + 4,
-                              (A_UINT8 *)&temp,
+                              (u8 *)&temp,
                               2,
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write end marker \n"));
             break;
         }
 
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, ("End Marker: 0x%X \n",temp));
 
-        temp = (A_UINT16)g_BlockSizes[1];
+        temp = (u16)g_BlockSizes[1];
             /* convert to a mask */
         temp = temp - 1;
         status = HIFReadWrite(pDev->HIFDevice,
                               SCRATCH_ADDRESS + 6,
-                              (A_UINT8 *)&temp,
+                              (u8 *)&temp,
                               2,
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);
 
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to write block mask \n"));
             break;
         }
@@ -1450,14 +1459,14 @@
             /* execute the test on each mailbox */
         for (i = 0; i < AR6K_MAILBOXES; i++) {
             status = DoOneMboxHWTest(pDev, i);
-            if (status != A_OK) {
+            if (status) {
                 break;
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
-    if (status == A_OK) {
+    if (status == 0) {
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - SUCCESS! -  \n"));
     } else {
         AR_DEBUG_PRINTF(ATH_PRINT_OUT_ZONE, (" DoMboxHWTest DONE - FAILED! -  \n"));
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_events.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,17 +33,17 @@
 #include "htc_packet.h"
 #include "ar6k.h"
 
-extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
-extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
+extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket);
+extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev);
 
-static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev);
+static int DevServiceDebugInterrupt(struct ar6k_device *pDev);
 
 #define DELAY_PER_INTERVAL_MS 10  /* 10 MS delay per polling interval */
 
 /* completion routine for ALL HIF layer async I/O */
-A_STATUS DevRWCompletionHandler(void *context, A_STATUS status)
+int DevRWCompletionHandler(void *context, int status)
 {
-    HTC_PACKET *pPacket = (HTC_PACKET *)context;
+    struct htc_packet *pPacket = (struct htc_packet *)context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                 ("+DevRWCompletionHandler (Pkt:0x%lX) , Status: %d \n",
@@ -55,26 +55,26 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                 ("-DevRWCompletionHandler\n"));
 
-    return A_OK;
+    return 0;
 }
 
 /* mailbox recv message polling */
-A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
-                            A_UINT32    *pLookAhead,
+int DevPollMboxMsgRecv(struct ar6k_device *pDev,
+                            u32 *pLookAhead,
                             int          TimeoutMS)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      timeout = TimeoutMS/DELAY_PER_INTERVAL_MS;
 
     A_ASSERT(timeout > 0);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+DevPollMboxMsgRecv \n"));
 
-    while (TRUE) {
+    while (true) {
 
         if (pDev->GetPendingEventsFunc != NULL) {
 
-            HIF_PENDING_EVENTS_INFO events;
+            struct hif_pending_events_info events;
 
 #ifdef THREAD_X
 			events.Polling =1;
@@ -85,7 +85,7 @@
             status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
                                             &events,
                                             NULL);
-            if (A_FAILED(status))
+            if (status)
             {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get pending events \n"));
                 break;
@@ -104,12 +104,12 @@
                 /* load the register table */
             status = HIFReadWrite(pDev->HIFDevice,
                                   HOST_INT_STATUS_ADDRESS,
-                                  (A_UINT8 *)&pDev->IrqProcRegisters,
+                                  (u8 *)&pDev->IrqProcRegisters,
                                   AR6K_IRQ_PROC_REGS_SIZE,
                                   HIF_RD_SYNC_BYTE_INC,
                                   NULL);
 
-            if (A_FAILED(status)){
+            if (status){
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to read register table \n"));
                 break;
             }
@@ -152,11 +152,11 @@
     return status;
 }
 
-static A_STATUS DevServiceCPUInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceCPUInterrupt(struct ar6k_device *pDev)
 {
-    A_STATUS status;
-    A_UINT8  cpu_int_status;
-    A_UINT8  regBuffer[4];
+    int status;
+    u8 cpu_int_status;
+    u8 regBuffer[4];
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("CPU Interrupt\n"));
     cpu_int_status = pDev->IrqProcRegisters.cpu_int_status &
@@ -187,16 +187,16 @@
                           HIF_WR_SYNC_BYTE_FIX,
                           NULL);
 
-    A_ASSERT(status == A_OK);
+    A_ASSERT(status == 0);
     return status;
 }
 
 
-static A_STATUS DevServiceErrorInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceErrorInterrupt(struct ar6k_device *pDev)
 {
-    A_STATUS status;
-    A_UINT8  error_int_status;
-    A_UINT8  regBuffer[4];
+    int status;
+    u8 error_int_status;
+    u8 regBuffer[4];
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Error Interrupt\n"));
     error_int_status = pDev->IrqProcRegisters.error_int_status & 0x0F;
@@ -241,14 +241,14 @@
                           HIF_WR_SYNC_BYTE_FIX,
                           NULL);
 
-    A_ASSERT(status == A_OK);
+    A_ASSERT(status == 0);
     return status;
 }
 
-static A_STATUS DevServiceDebugInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceDebugInterrupt(struct ar6k_device *pDev)
 {
-    A_UINT32 dummy;
-    A_STATUS status;
+    u32 dummy;
+    int status;
 
     /* Send a target failure event to the application */
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Target debug interrupt\n"));
@@ -266,18 +266,18 @@
         /* read counter to clear interrupt */
     status = HIFReadWrite(pDev->HIFDevice,
                           COUNT_DEC_ADDRESS,
-                          (A_UINT8 *)&dummy,
+                          (u8 *)&dummy,
                           4,
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
 
-    A_ASSERT(status == A_OK);
+    A_ASSERT(status == 0);
     return status;
 }
 
-static A_STATUS DevServiceCounterInterrupt(AR6K_DEVICE *pDev)
+static int DevServiceCounterInterrupt(struct ar6k_device *pDev)
 {
-    A_UINT8 counter_int_status;
+    u8 counter_int_status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("Counter Interrupt\n"));
 
@@ -296,21 +296,21 @@
         return DevServiceDebugInterrupt(pDev);
     }
 
-    return A_OK;
+    return 0;
 }
 
 /* callback when our fetch to get interrupt status registers completes */
-static void DevGetEventAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevGetEventAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
-    A_UINT32    lookAhead = 0;
-    A_BOOL      otherInts = FALSE;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
+    u32 lookAhead = 0;
+    bool      otherInts = false;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGetEventAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
     do {
 
-        if (A_FAILED(pPacket->Status)) {
+        if (pPacket->Status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     (" GetEvents I/O request failed, status:%d \n", pPacket->Status));
             /* bail out, don't unmask HIF interrupt */
@@ -319,7 +319,7 @@
 
         if (pDev->GetPendingEventsFunc != NULL) {
                 /* the HIF layer collected the information for us */
-            HIF_PENDING_EVENTS_INFO *pEvents = (HIF_PENDING_EVENTS_INFO *)pPacket->pBuffer;
+            struct hif_pending_events_info *pEvents = (struct hif_pending_events_info *)pPacket->pBuffer;
             if (pEvents->Events & HIF_RECV_MSG_AVAIL) {
                 lookAhead = pEvents->LookAhead;
                 if (0 == lookAhead) {
@@ -327,12 +327,12 @@
                 }
             }
             if (pEvents->Events & HIF_OTHER_EVENTS) {
-                otherInts = TRUE;
+                otherInts = true;
             }
         } else {
                 /* standard interrupt table handling.... */
-            AR6K_IRQ_PROC_REGISTERS *pReg = (AR6K_IRQ_PROC_REGISTERS *)pPacket->pBuffer;
-            A_UINT8                 host_int_status;
+            struct ar6k_irq_proc_registers *pReg = (struct ar6k_irq_proc_registers *)pPacket->pBuffer;
+            u8 host_int_status;
 
             host_int_status = pReg->host_int_status & pDev->IrqEnableRegisters.int_status_enable;
 
@@ -349,7 +349,7 @@
 
             if (host_int_status) {
                     /* there are other interrupts to handle */
-                otherInts = TRUE;
+                otherInts = true;
             }
         }
 
@@ -363,7 +363,7 @@
             HIFAckInterrupt(pDev->HIFDevice);
         } else {
             int      fetched = 0;
-            A_STATUS status;
+            int status;
 
             AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,
                     (" DevGetEventAsyncHandler : detected another message, lookahead :0x%X \n",
@@ -372,14 +372,14 @@
                  * go get the next message */
             status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, NULL, &fetched);
 
-            if (A_SUCCESS(status) && !fetched) {
+            if (!status && !fetched) {
                     /* HTC layer could not pull out messages due to lack of resources, stop IRQ processing */
                 AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("MessagePendingCallback did not pull any messages, force-ack \n"));
                 DevAsyncIrqProcessComplete(pDev);
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
         /* free this IO packet */
     AR6KFreeIOPacket(pDev,pPacket);
@@ -388,11 +388,11 @@
 
 /* called by the HTC layer when it wants us to check if the device has any more pending
  * recv messages, this starts off a series of async requests to read interrupt registers  */
-A_STATUS DevCheckPendingRecvMsgsAsync(void *context)
+int DevCheckPendingRecvMsgsAsync(void *context)
 {
-    AR6K_DEVICE  *pDev = (AR6K_DEVICE *)context;
-    A_STATUS      status = A_OK;
-    HTC_PACKET   *pIOPacket;
+    struct ar6k_device  *pDev = (struct ar6k_device *)context;
+    int      status = 0;
+    struct htc_packet   *pIOPacket;
 
     /* this is called in an ASYNC only context, we may NOT block, sleep or call any apis that can
      * cause us to switch contexts */
@@ -428,7 +428,7 @@
                 /* there should be only 1 asynchronous request out at a time to read these registers
                  * so this should actually never happen */
             status = A_NO_MEMORY;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -439,7 +439,7 @@
         if (pDev->GetPendingEventsFunc) {
                 /* HIF layer has it's own mechanism, pass the IO to it.. */
             status = pDev->GetPendingEventsFunc(pDev->HIFDevice,
-                                                (HIF_PENDING_EVENTS_INFO *)pIOPacket->pBuffer,
+                                                (struct hif_pending_events_info *)pIOPacket->pBuffer,
                                                 pIOPacket);
 
         } else {
@@ -453,25 +453,25 @@
         }
 
         AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,(" Async IO issued to get interrupt status...\n"));
-   } while (FALSE);
+   } while (false);
 
    AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevCheckPendingRecvMsgsAsync \n"));
 
    return status;
 }
 
-void DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev)
+void DevAsyncIrqProcessComplete(struct ar6k_device *pDev)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("DevAsyncIrqProcessComplete - forcing HIF IRQ ACK \n"));
     HIFAckInterrupt(pDev->HIFDevice);
 }
 
 /* process pending interrupts synchronously */
-static A_STATUS ProcessPendingIRQs(AR6K_DEVICE *pDev, A_BOOL *pDone, A_BOOL *pASyncProcessing)
+static int ProcessPendingIRQs(struct ar6k_device *pDev, bool *pDone, bool *pASyncProcessing)
 {
-    A_STATUS    status = A_OK;
-    A_UINT8     host_int_status = 0;
-    A_UINT32    lookAhead = 0;
+    int    status = 0;
+    u8 host_int_status = 0;
+    u32 lookAhead = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+ProcessPendingIRQs: (dev: 0x%lX)\n", (unsigned long)pDev));
 
@@ -490,7 +490,7 @@
             }
 
             if (pDev->GetPendingEventsFunc != NULL) {
-                HIF_PENDING_EVENTS_INFO events;
+                struct hif_pending_events_info events;
 
 #ifdef THREAD_X
             events.Polling= 0;
@@ -501,7 +501,7 @@
                                                 &events,
                                                 NULL);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
@@ -545,12 +545,12 @@
 #endif /* CONFIG_MMC_SDHCI_S3C */
         status = HIFReadWrite(pDev->HIFDevice,
                               HOST_INT_STATUS_ADDRESS,
-                              (A_UINT8 *)&pDev->IrqProcRegisters,
+                              (u8 *)&pDev->IrqProcRegisters,
                               AR6K_IRQ_PROC_REGS_SIZE,
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -591,19 +591,19 @@
             status = DevCheckGMboxInterrupts(pDev);
         }
 
-    } while (FALSE);
+    } while (false);
 
 
     do {
 
             /* did the interrupt status fetches succeed? */
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
         if ((0 == host_int_status) && (0 == lookAhead)) {
                 /* nothing to process, the caller can use this to break out of a loop */
-            *pDone = TRUE;
+            *pDone = true;
             break;
         }
 
@@ -617,14 +617,14 @@
                  * completion routine of the callers read request. This can improve performance
                  * by reducing context switching when we rapidly pull packets */
             status = pDev->MessagePendingCallback(pDev->HTCContext, &lookAhead, 1, pASyncProcessing, &fetched);
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
             if (!fetched) {
                     /* HTC could not pull any messages out due to lack of resources */
                     /* force DSR handler to ack the interrupt */
-                *pASyncProcessing = FALSE;
+                *pASyncProcessing = false;
                 pDev->RecheckIRQStatusCnt = 0;
             }
         }
@@ -637,7 +637,7 @@
         if (HOST_INT_STATUS_CPU_GET(host_int_status)) {
                 /* CPU Interrupt */
             status = DevServiceCPUInterrupt(pDev);
-            if (A_FAILED(status)){
+            if (status){
                 break;
             }
         }
@@ -645,7 +645,7 @@
         if (HOST_INT_STATUS_ERROR_GET(host_int_status)) {
                 /* Error Interrupt */
             status = DevServiceErrorInterrupt(pDev);
-            if (A_FAILED(status)){
+            if (status){
                 break;
             }
         }
@@ -653,12 +653,12 @@
         if (HOST_INT_STATUS_COUNTER_GET(host_int_status)) {
                 /* Counter Interrupt */
             status = DevServiceCounterInterrupt(pDev);
-            if (A_FAILED(status)){
+            if (status){
                 break;
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
         /* an optimization to bypass reading the IRQ status registers unecessarily which can re-wake
          * the target, if upper layers determine that we are in a low-throughput mode, we can
@@ -670,7 +670,7 @@
          * messages from the mailbox before exiting the ISR routine. */
     if (!(*pASyncProcessing) && (pDev->RecheckIRQStatusCnt == 0) && (pDev->GetPendingEventsFunc == NULL)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("Bypassing IRQ Status re-check, forcing done \n"));
-        *pDone = TRUE;
+        *pDone = true;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-ProcessPendingIRQs: (done:%d, async:%d) status=%d \n",
@@ -681,12 +681,12 @@
 
 
 /* Synchronousinterrupt handler, this handler kicks off all interrupt processing.*/
-A_STATUS DevDsrHandler(void *context)
+int DevDsrHandler(void *context)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)context;
-    A_STATUS    status = A_OK;
-    A_BOOL      done = FALSE;
-    A_BOOL      asyncProc = FALSE;
+    struct ar6k_device *pDev = (struct ar6k_device *)context;
+    int    status = 0;
+    bool      done = false;
+    bool      asyncProc = false;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevDsrHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
@@ -697,13 +697,13 @@
 
     while (!done) {
         status = ProcessPendingIRQs(pDev, &done, &asyncProc);
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
         if (HIF_DEVICE_IRQ_SYNC_ONLY == pDev->HifIRQProcessingMode) {
             /* the HIF layer does not allow async IRQ processing, override the asyncProc flag */
-            asyncProc = FALSE;
+            asyncProc = false;
             /* this will cause us to re-enter ProcessPendingIRQ() and re-read interrupt status registers.
              * this has a nice side effect of blocking us until all async read requests are completed.
              * This behavior is required on some HIF implementations that do not allow ASYNC
@@ -725,7 +725,7 @@
 
     }
 
-    if (A_SUCCESS(status) && !asyncProc) {
+    if (!status && !asyncProc) {
             /* Ack the interrupt only if :
              *  1. we did not get any errors in processing interrupts
              *  2. there are no outstanding async processing requests */
@@ -744,26 +744,26 @@
 }
 
 #ifdef ATH_DEBUG_MODULE
-void DumpAR6KDevState(AR6K_DEVICE *pDev)
+void DumpAR6KDevState(struct ar6k_device *pDev)
 {
-    A_STATUS                    status;
-    AR6K_IRQ_ENABLE_REGISTERS   regs;
-    AR6K_IRQ_PROC_REGISTERS     procRegs;
+    int                    status;
+    struct ar6k_irq_enable_registers   regs;
+    struct ar6k_irq_proc_registers     procRegs;
 
     LOCK_AR6K(pDev);
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
     UNLOCK_AR6K(pDev);
 
         /* load the register table from the device */
     status = HIFReadWrite(pDev->HIFDevice,
                           HOST_INT_STATUS_ADDRESS,
-                          (A_UINT8 *)&procRegs,
+                          (u8 *)&procRegs,
                           AR6K_IRQ_PROC_REGS_SIZE,
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
             ("DumpAR6KDevState : Failed to read register table (%d) \n",status));
         return;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox.c	2011-05-19 00:06:34.000000000 -0400
@@ -54,18 +54,18 @@
 
 
     /* external APIs for allocating and freeing internal I/O packets to handle ASYNC I/O */ 
-extern void AR6KFreeIOPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket);
-extern HTC_PACKET *AR6KAllocIOPacket(AR6K_DEVICE *pDev);
+extern void AR6KFreeIOPacket(struct ar6k_device *pDev, struct htc_packet *pPacket);
+extern struct htc_packet *AR6KAllocIOPacket(struct ar6k_device *pDev);
 
 
 /* callback when our fetch to enable/disable completes */
-static void DevGMboxIRQActionAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevGMboxIRQActionAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxIRQActionAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("IRQAction Operation (%d) failed! status:%d \n", pPacket->PktInfo.AsRx.HTCRxFlags,pPacket->Status));
     }
@@ -74,26 +74,26 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxIRQActionAsyncHandler \n"));
 }
 
-static A_STATUS DevGMboxCounterEnableDisable(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
+static int DevGMboxCounterEnableDisable(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode)
 {
-    A_STATUS                  status = A_OK;
-    AR6K_IRQ_ENABLE_REGISTERS regs;
-    HTC_PACKET                *pIOPacket = NULL;  
+    int                  status = 0;
+    struct ar6k_irq_enable_registers regs;
+    struct htc_packet                *pIOPacket = NULL;  
     
     LOCK_AR6K(pDev);
     
     if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
-        pDev->GMboxInfo.CreditCountIRQEnabled = TRUE;
+        pDev->GMboxInfo.CreditCountIRQEnabled = true;
         pDev->IrqEnableRegisters.counter_int_status_enable |=
             COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER);
         pDev->IrqEnableRegisters.int_status_enable |= INT_STATUS_ENABLE_COUNTER_SET(0x01);
     } else {
-        pDev->GMboxInfo.CreditCountIRQEnabled = FALSE;
+        pDev->GMboxInfo.CreditCountIRQEnabled = false;
         pDev->IrqEnableRegisters.counter_int_status_enable &=
             ~(COUNTER_INT_STATUS_ENABLE_BIT_SET(1 << AR6K_GMBOX_CREDIT_COUNTER));    
     }
         /* copy into our temp area */
-    A_MEMCPY(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+    memcpy(&regs,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
     UNLOCK_AR6K(pDev);
 
@@ -105,12 +105,12 @@
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
                 /* copy values to write to our async I/O buffer */
-            A_MEMCPY(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
+            memcpy(pIOPacket->pBuffer,&pDev->IrqEnableRegisters,AR6K_IRQ_ENABLE_REGS_SIZE);
 
                 /* stick in our completion routine when the I/O operation completes */
             pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
@@ -135,9 +135,9 @@
                               AR6K_IRQ_ENABLE_REGS_SIZE,
                               HIF_WR_SYNC_BYTE_INC,
                               NULL);    
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));    
     } else {
@@ -155,11 +155,11 @@
 }
 
 
-A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, A_BOOL AsyncMode)
+int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE IrqAction, bool AsyncMode)
 {
-    A_STATUS      status = A_OK;
-    HTC_PACKET    *pIOPacket = NULL;   
-    A_UINT8       GMboxIntControl[4];
+    int      status = 0;
+    struct htc_packet    *pIOPacket = NULL;   
+    u8 GMboxIntControl[4];
 
     if (GMBOX_CREDIT_IRQ_ENABLE == IrqAction) {
         return DevGMboxCounterEnableDisable(pDev, GMBOX_CREDIT_IRQ_ENABLE, AsyncMode);
@@ -192,7 +192,7 @@
             break;
         case GMBOX_ACTION_NONE:
         default:
-            A_ASSERT(FALSE);    
+            A_ASSERT(false);
             break;
     }
     
@@ -211,12 +211,12 @@
 
             if (NULL == pIOPacket) {
                 status = A_NO_MEMORY;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
             }
 
                 /* copy values to write to our async I/O buffer */
-            A_MEMCPY(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
+            memcpy(pIOPacket->pBuffer,GMboxIntControl,sizeof(GMboxIntControl));
 
                 /* stick in our completion routine when the I/O operation completes */
             pIOPacket->Completion = DevGMboxIRQActionAsyncHandler;
@@ -242,9 +242,9 @@
                               HIF_WR_SYNC_BYTE_FIX,
                               NULL);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" IRQAction Operation (%d) failed! status:%d \n", IrqAction, status));    
     } else {
@@ -261,18 +261,18 @@
     return status;
 }
 
-void DevCleanupGMbox(AR6K_DEVICE *pDev)
+void DevCleanupGMbox(struct ar6k_device *pDev)
 {
     if (pDev->GMboxEnabled) {
-        pDev->GMboxEnabled = FALSE;
+        pDev->GMboxEnabled = false;
         GMboxProtocolUninstall(pDev);        
     }
 }
 
-A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev)
+int DevSetupGMbox(struct ar6k_device *pDev)
 {
-    A_STATUS    status = A_OK;
-    A_UINT8     muxControl[4];
+    int    status = 0;
+    u8 muxControl[4];
     
     do {
         
@@ -285,7 +285,7 @@
                     
         status = DevGMboxIRQAction(pDev, GMBOX_DISABLE_ALL, PROC_IO_SYNC);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
        
@@ -305,29 +305,29 @@
                               HIF_WR_SYNC_BYTE_FIX,  /* hit this register 4 times */
                               NULL);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
         status = GMboxProtocolInstall(pDev);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
-        pDev->GMboxEnabled = TRUE;
+        pDev->GMboxEnabled = true;
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
-A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev)
+int DevCheckGMboxInterrupts(struct ar6k_device *pDev)
 {
-    A_STATUS status = A_OK;
-    A_UINT8  counter_int_status;
+    int status = 0;
+    u8 counter_int_status;
     int      credits;
-    A_UINT8  host_int_status2;
+    u8 host_int_status2;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("+DevCheckGMboxInterrupts \n"));
      
@@ -348,7 +348,7 @@
             status = A_ECOMM;    
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
                 pDev->GMboxInfo.pTargetFailureCallback(pDev->GMboxInfo.pProtocolContext, status);        
             }
@@ -360,12 +360,12 @@
                 A_ASSERT(pDev->GMboxInfo.pMessagePendingCallBack != NULL);
                 status = pDev->GMboxInfo.pMessagePendingCallBack(
                                 pDev->GMboxInfo.pProtocolContext,
-                                (A_UINT8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
+                                (u8 *)&pDev->IrqProcRegisters.rx_gmbox_lookahead_alias[0],
                                 pDev->IrqProcRegisters.gmbox_rx_avail);
             }
         } 
         
-        if (A_FAILED(status)) {
+        if (status) {
            break;                
         }
         
@@ -378,7 +378,7 @@
                 /* do synchronous read */
             status = DevGMboxReadCreditCounter(pDev, PROC_IO_SYNC, &credits);
             
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
             
@@ -388,7 +388,7 @@
                                                              pDev->GMboxInfo.CreditCountIRQEnabled);
         }
         
-    } while (FALSE);
+    } while (false);
     
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ, ("-DevCheckGMboxInterrupts (%d) \n",status));
     
@@ -396,12 +396,12 @@
 }
 
 
-A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength) 
+int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength)
 {
-    A_UINT32 paddedLength;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
-    A_STATUS status;
-    A_UINT32 address;
+    u32 paddedLength;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
+    int status;
+    u32 address;
     
        /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, WriteLength);
@@ -426,31 +426,31 @@
         pPacket->Status = status;
     } else {
         if (status == A_PENDING) {
-            status = A_OK;    
+            status = 0;
         }    
     }
 
     return status;
 }
 
-A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength) 
+int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength)
 {
     
-    A_UINT32 paddedLength;
-    A_STATUS status;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+    u32 paddedLength;
+    int status;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
 
         /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, ReadLength);
                     
     if (paddedLength > pPacket->BufferLength) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("DevGMboxRead, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
                     paddedLength,ReadLength,pPacket->BufferLength));
         if (pPacket->Completion != NULL) {
             COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
-            return A_OK;
+            return 0;
         }
         return A_EINVAL;
     }
@@ -477,7 +477,7 @@
 }
 
 
-static int ProcessCreditCounterReadBuffer(A_UINT8 *pBuffer, int Length)
+static int ProcessCreditCounterReadBuffer(u8 *pBuffer, int Length)
 {
     int     credits = 0;
     
@@ -516,13 +516,13 @@
    
 
 /* callback when our fetch to enable/disable completes */
-static void DevGMboxReadCreditsAsyncHandler(void *Context, HTC_PACKET *pPacket)
+static void DevGMboxReadCreditsAsyncHandler(void *Context, struct htc_packet *pPacket)
 {
-    AR6K_DEVICE *pDev = (AR6K_DEVICE *)Context;
+    struct ar6k_device *pDev = (struct ar6k_device *)Context;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("+DevGMboxReadCreditsAsyncHandler: (dev: 0x%lX)\n", (unsigned long)pDev));
 
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("Read Credit Operation failed! status:%d \n", pPacket->Status));
     } else {
@@ -539,10 +539,10 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_IRQ,("-DevGMboxReadCreditsAsyncHandler \n"));
 }
 
-A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits)
+int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits)
 {
-    A_STATUS    status = A_OK;
-    HTC_PACKET  *pIOPacket = NULL;  
+    int    status = 0;
+    struct htc_packet  *pIOPacket = NULL;  
     
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+DevGMboxReadCreditCounter (%s) \n", AsyncMode ? "ASYNC" : "SYNC"));
                                             
@@ -552,7 +552,7 @@
 
         if (NULL == pIOPacket) {
             status = A_NO_MEMORY;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
         
@@ -581,15 +581,15 @@
                               AR6K_REG_IO_BUFFER_SIZE,
                               HIF_RD_SYNC_BYTE_FIX,
                               NULL);    
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 (" DevGMboxReadCreditCounter failed! status:%d \n", status));          
     }
     
     if (pIOPacket != NULL) {
-        if (A_SUCCESS(status)) {
+        if (!status) {
                 /* sync mode processing */
             *pCredits = ProcessCreditCounterReadBuffer(pIOPacket->pBuffer, AR6K_REG_IO_BUFFER_SIZE);     
         }
@@ -602,10 +602,10 @@
     return status;
 }
 
-A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize)
+int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize)
 {
-    A_STATUS    status;
-    A_UINT8     buffer[4];
+    int    status;
+    u8 buffer[4];
        
     status = HIFReadWrite(pDev->HIFDevice,
                           AR6K_GMBOX_CREDIT_SIZE_ADDRESS,
@@ -614,7 +614,7 @@
                           HIF_RD_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
                           NULL);    
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         if (buffer[0] == 0) {
             *pCreditSize = 256;    
         } else {   
@@ -626,7 +626,7 @@
     return status;
 }
 
-void DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev)
+void DevNotifyGMboxTargetFailure(struct ar6k_device *pDev)
 {
         /* Target ASSERTED!!! */
     if (pDev->GMboxInfo.pTargetFailureCallback != NULL) {
@@ -634,17 +634,17 @@
     }
 }
 
-A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes)
+int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes)
 {
 
-    A_STATUS                    status = A_OK;
-    AR6K_IRQ_PROC_REGISTERS     procRegs;
+    int                    status = 0;
+    struct ar6k_irq_proc_registers     procRegs;
     int                         maxCopy;
   
     do {
             /* on entry the caller provides the length of the lookahead buffer */
         if (*pLookAheadBytes > sizeof(procRegs.rx_gmbox_lookahead_alias)) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             status = A_EINVAL;
             break;    
         }
@@ -654,12 +654,12 @@
             /* load the register table from the device */
         status = HIFReadWrite(pDev->HIFDevice,
                               HOST_INT_STATUS_ADDRESS,
-                              (A_UINT8 *)&procRegs,
+                              (u8 *)&procRegs,
                               AR6K_IRQ_PROC_REGS_SIZE,
                               HIF_RD_SYNC_BYTE_INC,
                               NULL);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("DevGMboxRecvLookAheadPeek : Failed to read register table (%d) \n",status));
             break;
@@ -667,20 +667,20 @@
         
         if (procRegs.gmbox_rx_avail > 0) {
             int bytes = procRegs.gmbox_rx_avail > maxCopy ? maxCopy : procRegs.gmbox_rx_avail;
-            A_MEMCPY(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
+            memcpy(pLookAheadBuffer,&procRegs.rx_gmbox_lookahead_alias[0],bytes);
             *pLookAheadBytes = bytes;
         }
         
-    } while (FALSE);
+    } while (false);
        
     return status; 
 }
 
-A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int Signal, int AckTimeoutMS)
+int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int Signal, int AckTimeoutMS)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      i;
-    A_UINT8  buffer[4];
+    u8 buffer[4];
     
     A_MEMZERO(buffer, sizeof(buffer));
     
@@ -701,14 +701,14 @@
                               HIF_WR_SYNC_BYTE_FIX, /* hit the register 4 times to align the I/O */
                               NULL);    
                           
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
-    } while (FALSE);
+    } while (false);
     
     
-    if (A_SUCCESS(status)) {        
+    if (!status) {
             /* now read back the register to see if the bit cleared */
         while (AckTimeoutMS) {        
             status = HIFReadWrite(pDev->HIFDevice,
@@ -718,7 +718,7 @@
                                   HIF_RD_SYNC_BYTE_FIX,
                                   NULL);    
                           
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
                             
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k_gmbox_hciuart.c	2011-05-19 00:06:34.000000000 -0400
@@ -56,17 +56,17 @@
 #define BAUD_TIMEOUT_MS           1
 #define BTPWRSAV_TIMEOUT_MS       1  
 
-typedef struct {
-    HCI_TRANSPORT_CONFIG_INFO   HCIConfig;
-    A_BOOL                      HCIAttached;
-    A_BOOL                      HCIStopped;
-    A_UINT32                    RecvStateFlags;
-    A_UINT32                    SendStateFlags;
+struct gmbox_proto_hci_uart {
+    struct hci_transport_config_info   HCIConfig;
+    bool                      HCIAttached;
+    bool                      HCIStopped;
+    u32 RecvStateFlags;
+    u32 SendStateFlags;
     HCI_TRANSPORT_PACKET_TYPE   WaitBufferType;
-    HTC_PACKET_QUEUE            SendQueue;         /* write queue holding HCI Command and ACL packets */
-    HTC_PACKET_QUEUE            HCIACLRecvBuffers;  /* recv queue holding buffers for incomming ACL packets */
-    HTC_PACKET_QUEUE            HCIEventBuffers;    /* recv queue holding buffers for incomming event packets */
-    AR6K_DEVICE                 *pDev;
+    struct htc_packet_queue            SendQueue;         /* write queue holding HCI Command and ACL packets */
+    struct htc_packet_queue            HCIACLRecvBuffers;  /* recv queue holding buffers for incomming ACL packets */
+    struct htc_packet_queue            HCIEventBuffers;    /* recv queue holding buffers for incomming event packets */
+    struct ar6k_device                 *pDev;
     A_MUTEX_T                   HCIRxLock;
     A_MUTEX_T                   HCITxLock;
     int                         CreditsMax;
@@ -75,18 +75,23 @@
     int                         CreditSize;
     int                         CreditsCurrentSeek;
     int                         SendProcessCount;
-} GMBOX_PROTO_HCI_UART;
+};
 
 #define LOCK_HCI_RX(t)   A_MUTEX_LOCK(&(t)->HCIRxLock);
 #define UNLOCK_HCI_RX(t) A_MUTEX_UNLOCK(&(t)->HCIRxLock);
 #define LOCK_HCI_TX(t)   A_MUTEX_LOCK(&(t)->HCITxLock);
 #define UNLOCK_HCI_TX(t) A_MUTEX_UNLOCK(&(t)->HCITxLock);
 
-#define DO_HCI_RECV_INDICATION(p,pt) \
-{   AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n",  \
-      (unsigned long)(pt),(pt)->Status, A_SUCCESS((pt)->Status) ? (pt)->ActualLength : 0, HCI_GET_PACKET_TYPE(pt))); \
-    (p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt));                                 \
-}
+#define DO_HCI_RECV_INDICATION(p, pt)				\
+do {								\
+	AR_DEBUG_PRINTF(ATH_DEBUG_RECV,					\
+			("HCI: Indicate Recv on packet:0x%lX status:%d len:%d type:%d \n", \
+			 (unsigned long)(pt),				\
+			 (pt)->Status,					\
+			 !(pt)->Status ? (pt)->ActualLength : 0,	\
+			 HCI_GET_PACKET_TYPE(pt)));			\
+	(p)->HCIConfig.pHCIPktRecv((p)->HCIConfig.pContext, (pt));	\
+} while (0)
 
 #define DO_HCI_SEND_INDICATION(p,pt) \
 {   AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("HCI: Indicate Send on packet:0x%lX status:%d type:%d \n",  \
@@ -94,9 +99,9 @@
     (p)->HCIConfig.pHCISendComplete((p)->HCIConfig.pContext, (pt));                            \
 }
     
-static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous);
+static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous);
 
-static void HCIUartCleanup(GMBOX_PROTO_HCI_UART *pProtocol)
+static void HCIUartCleanup(struct gmbox_proto_hci_uart *pProtocol)
 {
     A_ASSERT(pProtocol != NULL);
     
@@ -106,12 +111,12 @@
     A_FREE(pProtocol);    
 }
 
-static A_STATUS InitTxCreditState(GMBOX_PROTO_HCI_UART *pProt)
+static int InitTxCreditState(struct gmbox_proto_hci_uart *pProt)
 {
-    A_STATUS    status;
+    int    status;
     int         credits;
     int         creditPollCount = CREDIT_POLL_COUNT;
-    A_BOOL      gotCredits = FALSE;
+    bool      gotCredits = false;
 
     pProt->CreditsConsumed = 0;
     
@@ -120,7 +125,7 @@
         if (pProt->CreditsMax != 0) {
             /* we can only call this only once per target reset */
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI: InitTxCreditState - already called!  \n"));
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             status = A_EINVAL;
             break; 
         }
@@ -135,7 +140,7 @@
 
             status = DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);
     
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
             
@@ -145,7 +150,7 @@
                 A_MDELAY(HCI_DELAY_PER_INTERVAL_MS);
                 continue;  
             } else {
-                gotCredits = TRUE;    
+                gotCredits = true;
             }
             
             if (0 == credits) {
@@ -155,7 +160,7 @@
             pProt->CreditsMax += credits;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -169,13 +174,13 @@
             /* now get the size */
         status = DevGMboxReadCreditSize(pProt->pDev, &pProt->CreditSize);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
                
-    } while (FALSE);
+    } while (false);
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         pProt->CreditsAvailable = pProt->CreditsMax;
         AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("HCI : InitTxCreditState - credits avail: %d, size: %d \n",
             pProt->CreditsAvailable, pProt->CreditSize));    
@@ -184,13 +189,13 @@
     return status;
 }
 
-static A_STATUS CreditsAvailableCallback(void *pContext, int Credits, A_BOOL CreditIRQEnabled)
+static int CreditsAvailableCallback(void *pContext, int Credits, bool CreditIRQEnabled)
 {
-    GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)pContext;    
-    A_BOOL               enableCreditIrq = FALSE;   
-    A_BOOL               disableCreditIrq = FALSE;
-    A_BOOL               doPendingSends = FALSE;
-    A_STATUS             status = A_OK;
+    struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)pContext;    
+    bool               enableCreditIrq = false;
+    bool               disableCreditIrq = false;
+    bool               doPendingSends = false;
+    int             status = 0;
     
     /** this callback is called under 2 conditions:
      *   1. The credit IRQ interrupt was enabled and signaled.
@@ -209,7 +214,7 @@
         if (0 == Credits) {
             if (!CreditIRQEnabled) {
                     /* enable credit IRQ */
-                enableCreditIrq = TRUE;    
+                enableCreditIrq = true;
             }
             break;
         }
@@ -232,22 +237,22 @@
                          pProt->CreditsCurrentSeek));
         
         if (pProt->CreditsAvailable >= pProt->CreditsCurrentSeek) {
-                /* we have enough credits to fullfill at least 1 packet waiting in the queue */
+                /* we have enough credits to fulfill at least 1 packet waiting in the queue */
             pProt->CreditsCurrentSeek = 0;
             pProt->SendStateFlags &= ~HCI_SEND_WAIT_CREDITS;  
-            doPendingSends = TRUE;  
+            doPendingSends = true;
             if (CreditIRQEnabled) {
                     /* credit IRQ was enabled, we shouldn't need it anymore */
-                disableCreditIrq = TRUE;    
+                disableCreditIrq = true;
             }      
         } else {
                 /* not enough credits yet, enable credit IRQ if we haven't already */
             if (!CreditIRQEnabled) {               
-                enableCreditIrq = TRUE;    
+                enableCreditIrq = true;
             }    
         }
                       
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_HCI_TX(pProt);
 
@@ -262,31 +267,31 @@
     }
        
     if (doPendingSends) {
-        HCITrySend(pProt, NULL, FALSE);
+        HCITrySend(pProt, NULL, false);
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+CreditsAvailableCallback \n"));
     return status;
 }
 
-static INLINE void NotifyTransportFailure(GMBOX_PROTO_HCI_UART  *pProt, A_STATUS status)
+static INLINE void NotifyTransportFailure(struct gmbox_proto_hci_uart  *pProt, int status)
 {
     if (pProt->HCIConfig.TransportFailure != NULL) {
         pProt->HCIConfig.TransportFailure(pProt->HCIConfig.pContext, status);
     }
 }
 
-static void FailureCallback(void *pContext, A_STATUS Status)
+static void FailureCallback(void *pContext, int Status)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)pContext; 
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)pContext; 
     
-        /* target assertion occured */           
+        /* target assertion occurred */           
     NotifyTransportFailure(pProt, Status);  
 }
 
 static void StateDumpCallback(void *pContext)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)pContext;
    
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("============ HCIUart State ======================\n"));    
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("RecvStateFlags   :  0x%X \n",pProt->RecvStateFlags));
@@ -299,15 +304,15 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("==================================================\n"));
 }
 
-static A_STATUS HCIUartMessagePending(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes)
+static int HCIUartMessagePending(void *pContext, u8 LookAheadBytes[], int ValidBytes)
 {
-    GMBOX_PROTO_HCI_UART        *pProt = (GMBOX_PROTO_HCI_UART *)pContext;
-    A_STATUS                    status = A_OK;
+    struct gmbox_proto_hci_uart        *pProt = (struct gmbox_proto_hci_uart *)pContext;
+    int                    status = 0;
     int                         totalRecvLength = 0;
     HCI_TRANSPORT_PACKET_TYPE   pktType = HCI_PACKET_INVALID;
-    A_BOOL                      recvRefillCalled = FALSE;
-    A_BOOL                      blockRecv = FALSE;
-    HTC_PACKET                  *pPacket = NULL;
+    bool                      recvRefillCalled = false;
+    bool                      blockRecv = false;
+    struct htc_packet                  *pPacket = NULL;
     
     /** caller guarantees that this is a fully block-able context (synch I/O is allowed) */
     
@@ -348,7 +353,7 @@
                 break;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
                 
@@ -361,7 +366,7 @@
             LOCK_HCI_RX(pProt);
     
         } else {
-            HTC_PACKET_QUEUE *pQueue;
+            struct htc_packet_queue *pQueue;
                 /* user is using a refill handler that can refill multiple HTC buffers */
             
                 /* select buffer queue */
@@ -377,7 +382,7 @@
                     pktType));
                     /* check for refill handler */
                 if (pProt->HCIConfig.pHCIPktRecvRefill != NULL) {
-                    recvRefillCalled = TRUE;
+                    recvRefillCalled = true;
                     UNLOCK_HCI_RX(pProt);
                         /* call the re-fill handler */
                     pProt->HCIConfig.pHCIPktRecvRefill(pProt->HCIConfig.pContext,
@@ -402,7 +407,7 @@
                 /* this is not an error, we simply need to mark that we are waiting for buffers.*/
             pProt->RecvStateFlags |= HCI_RECV_WAIT_BUFFERS;
             pProt->WaitBufferType = pktType;
-            blockRecv = TRUE;
+            blockRecv = true;
             break;
         }
         
@@ -413,7 +418,7 @@
             break;
         }
         
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_HCI_RX(pProt);
     
@@ -421,7 +426,7 @@
         
     do {
         
-        if (A_FAILED(status) || (NULL == pPacket)) {
+        if (status || (NULL == pPacket)) {
             break;    
         } 
         
@@ -433,7 +438,7 @@
                 
         status = DevGMboxRead(pProt->pDev, pPacket, totalRecvLength);     
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -471,14 +476,14 @@
             /* adjust buffer to move past packet ID */
         pPacket->pBuffer++;
         pPacket->ActualLength = totalRecvLength - 1;
-        pPacket->Status = A_OK;
+        pPacket->Status = 0;
             /* indicate packet */
         DO_HCI_RECV_INDICATION(pProt,pPacket);
         pPacket = NULL;
         
             /* check if we need to refill recv buffers */        
         if ((pProt->HCIConfig.pHCIPktRecvRefill != NULL) && !recvRefillCalled) {           
-            HTC_PACKET_QUEUE *pQueue;
+            struct htc_packet_queue *pQueue;
             int              watermark;
 
             if (pktType == HCI_ACL_TYPE) {
@@ -500,16 +505,16 @@
             }
         }   
         
-    } while (FALSE);
+    } while (false);
         
-        /* check if we need to disable the reciever */
-    if (A_FAILED(status) || blockRecv) {
+        /* check if we need to disable the receiver */
+    if (status || blockRecv) {
         DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_DISABLE, PROC_IO_SYNC); 
     }
     
         /* see if we need to recycle the recv buffer */    
-    if (A_FAILED(status) && (pPacket != NULL)) {
-        HTC_PACKET_QUEUE queue;
+    if (status && (pPacket != NULL)) {
+        struct htc_packet_queue queue;
         
         if (A_EPROTO == status) {
             DebugDumpBytes(pPacket->pBuffer, totalRecvLength, "Bad HCI-UART Recv packet");    
@@ -527,12 +532,12 @@
     return status;
 }
 
-static void HCISendPacketCompletion(void *Context, HTC_PACKET *pPacket)
+static void HCISendPacketCompletion(void *Context, struct htc_packet *pPacket)
 {
-    GMBOX_PROTO_HCI_UART *pProt = (GMBOX_PROTO_HCI_UART *)Context;
+    struct gmbox_proto_hci_uart *pProt = (struct gmbox_proto_hci_uart *)Context;
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion (pPacket:0x%lX) \n",(unsigned long)pPacket));
     
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Send Packet (0x%lX) failed: %d , len:%d \n",
             (unsigned long)pPacket, pPacket->Status, pPacket->ActualLength));        
     }
@@ -542,16 +547,16 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCISendPacketCompletion \n"));
 }
 
-static A_STATUS SeekCreditsSynch(GMBOX_PROTO_HCI_UART *pProt)
+static int SeekCreditsSynch(struct gmbox_proto_hci_uart *pProt)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     int      credits;
     int      retry = 100;
     
-    while (TRUE) {                
+    while (true) {
         credits = 0;
         status =  DevGMboxReadCreditCounter(pProt->pDev, PROC_IO_SYNC, &credits);   
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         LOCK_HCI_TX(pProt);
@@ -574,13 +579,13 @@
     return status;
 }
 
-static A_STATUS HCITrySend(GMBOX_PROTO_HCI_UART *pProt, HTC_PACKET *pPacket, A_BOOL Synchronous)
+static int HCITrySend(struct gmbox_proto_hci_uart *pProt, struct htc_packet *pPacket, bool Synchronous)
 {   
-    A_STATUS    status = A_OK;
+    int    status = 0;
     int         transferLength;
     int         creditsRequired, remainder;
-    A_UINT8     hciUartType;
-    A_BOOL      synchSendComplete = FALSE;
+    u8 hciUartType;
+    bool      synchSendComplete = false;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+HCITrySend (pPacket:0x%lX) %s \n",(unsigned long)pPacket,
             Synchronous ? "SYNC" :"ASYNC"));
@@ -603,14 +608,14 @@
                     /* in synchronous mode, the send queue can only hold 1 packet */
                 if (!HTC_QUEUE_EMPTY(&pProt->SendQueue)) {
                     status = A_EBUSY;
-                    A_ASSERT(FALSE);
+                    A_ASSERT(false);
                     break;    
                 }             
                 
                 if (pProt->SendProcessCount > 1) {
                         /* another thread or task is draining the TX queues  */
                     status = A_EBUSY;
-                    A_ASSERT(FALSE);
+                    A_ASSERT(false);
                     break;
                 } 
                   
@@ -667,11 +672,11 @@
                     break;
                 default:
                     status = A_EINVAL;
-                    A_ASSERT(FALSE);
+                    A_ASSERT(false);
                     break;
             }
                        
-            if (A_FAILED(status)) {
+            if (status) {
                 break;   
             }
             
@@ -701,7 +706,7 @@
                     UNLOCK_HCI_TX(pProt);
                     status = SeekCreditsSynch(pProt);
                     LOCK_HCI_TX(pProt);
-                    if (A_FAILED(status)) {
+                    if (status) {
                         break;    
                     }                    
                     /* fall through and continue processing this send op */                    
@@ -751,7 +756,7 @@
             
             status = DevGMboxWrite(pProt->pDev,pPacket,transferLength);            
             if (Synchronous) {            
-                synchSendComplete = TRUE;
+                synchSendComplete = true;
             } else {
                 pPacket = NULL;    
             }
@@ -760,7 +765,7 @@
               
         }
         
-    } while (FALSE);
+    } while (false);
         
     pProt->SendProcessCount--;
     A_ASSERT(pProt->SendProcessCount >= 0);
@@ -768,9 +773,9 @@
     
     if (Synchronous) {
         A_ASSERT(pPacket != NULL);
-        if (A_SUCCESS(status) && (!synchSendComplete)) {
+        if (!status && (!synchSendComplete)) {
             status = A_EBUSY;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             LOCK_HCI_TX(pProt);
             if (pPacket->ListLink.pNext != NULL) {
                     /* remove from the queue */
@@ -779,7 +784,7 @@
             UNLOCK_HCI_TX(pProt);
         }
     } else {   
-        if (A_FAILED(status) && (pPacket != NULL)) {
+        if (status && (pPacket != NULL)) {
             pPacket->Status = status;
             DO_HCI_SEND_INDICATION(pProt,pPacket); 
         }
@@ -789,10 +794,10 @@
     return status;    
 }
 
-static void FlushSendQueue(GMBOX_PROTO_HCI_UART *pProt)
+static void FlushSendQueue(struct gmbox_proto_hci_uart *pProt)
 {
-    HTC_PACKET          *pPacket;
-    HTC_PACKET_QUEUE    discardQueue;
+    struct htc_packet          *pPacket;
+    struct htc_packet_queue    discardQueue;
     
     INIT_HTC_PACKET_QUEUE(&discardQueue);
     
@@ -813,10 +818,10 @@
     
 }
 
-static void FlushRecvBuffers(GMBOX_PROTO_HCI_UART *pProt)
+static void FlushRecvBuffers(struct gmbox_proto_hci_uart *pProt)
 {
-    HTC_PACKET_QUEUE discardQueue;
-    HTC_PACKET *pPacket;
+    struct htc_packet_queue discardQueue;
+    struct htc_packet *pPacket;
     
     INIT_HTC_PACKET_QUEUE(&discardQueue);
     
@@ -841,14 +846,14 @@
 
 /*** protocol module install entry point ***/
 
-A_STATUS GMboxProtocolInstall(AR6K_DEVICE *pDev)
+int GMboxProtocolInstall(struct ar6k_device *pDev)
 {
-    A_STATUS                status = A_OK;
-    GMBOX_PROTO_HCI_UART    *pProtocol = NULL;
+    int                status = 0;
+    struct gmbox_proto_hci_uart    *pProtocol = NULL;
         
     do {
         
-        pProtocol = A_MALLOC(sizeof(GMBOX_PROTO_HCI_UART));
+        pProtocol = A_MALLOC(sizeof(struct gmbox_proto_hci_uart));
         
         if (NULL == pProtocol) {
             status = A_NO_MEMORY;
@@ -863,9 +868,9 @@
         A_MUTEX_INIT(&pProtocol->HCIRxLock);
         A_MUTEX_INIT(&pProtocol->HCITxLock);
      
-    } while (FALSE);
+    } while (false);
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         LOCK_AR6K(pDev);
         DEV_GMBOX_SET_PROTOCOL(pDev,
                                HCIUartMessagePending,
@@ -884,9 +889,9 @@
 }
 
 /*** protocol module uninstall entry point ***/
-void GMboxProtocolUninstall(AR6K_DEVICE *pDev)
+void GMboxProtocolUninstall(struct ar6k_device *pDev)
 {
-    GMBOX_PROTO_HCI_UART *pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
+    struct gmbox_proto_hci_uart *pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev);
     
     if (pProtocol != NULL) {
         
@@ -894,7 +899,7 @@
         if (pProtocol->HCIAttached) {
             A_ASSERT(pProtocol->HCIConfig.TransportRemoved != NULL);
             pProtocol->HCIConfig.TransportRemoved(pProtocol->HCIConfig.pContext);
-            pProtocol->HCIAttached = FALSE;    
+            pProtocol->HCIAttached = false;
         }
         
         HCIUartCleanup(pProtocol);
@@ -903,10 +908,10 @@
     
 }
 
-static A_STATUS NotifyTransportReady(GMBOX_PROTO_HCI_UART  *pProt)
+static int NotifyTransportReady(struct gmbox_proto_hci_uart  *pProt)
 {
-    HCI_TRANSPORT_PROPERTIES props;
-    A_STATUS                 status = A_OK;
+    struct hci_transport_properties props;
+    int                 status = 0;
     
     do {
         
@@ -924,17 +929,17 @@
                                                     pProt->HCIConfig.pContext);
         }
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
 /***********  HCI UART protocol implementation ************************************************/
 
-HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo)
+HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo)
 {
-    GMBOX_PROTO_HCI_UART  *pProtocol = NULL; 
-    AR6K_DEVICE           *pDev;
+    struct gmbox_proto_hci_uart  *pProtocol = NULL; 
+    struct ar6k_device           *pDev;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportAttach \n"));
     
@@ -944,7 +949,7 @@
     
     do {
         
-        pProtocol = (GMBOX_PROTO_HCI_UART *)DEV_GMBOX_GET_PROTOCOL(pDev);
+        pProtocol = (struct gmbox_proto_hci_uart *)DEV_GMBOX_GET_PROTOCOL(pDev);
         
         if (NULL == pProtocol) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("GMBOX protocol not installed! \n"));
@@ -956,14 +961,14 @@
             break;    
         }
         
-        A_MEMCPY(&pProtocol->HCIConfig, pInfo, sizeof(HCI_TRANSPORT_CONFIG_INFO));
+        memcpy(&pProtocol->HCIConfig, pInfo, sizeof(struct hci_transport_config_info));
         
         A_ASSERT(pProtocol->HCIConfig.pHCIPktRecv != NULL);
         A_ASSERT(pProtocol->HCIConfig.pHCISendComplete != NULL);
         
-        pProtocol->HCIAttached = TRUE;
+        pProtocol->HCIAttached = true;
         
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_AR6K(pDev);
     
@@ -978,8 +983,8 @@
 
 void HCI_TransportDetach(HCI_TRANSPORT_HANDLE HciTrans)
 {
-    GMBOX_PROTO_HCI_UART  *pProtocol = (GMBOX_PROTO_HCI_UART *)HciTrans; 
-    AR6K_DEVICE           *pDev = pProtocol->pDev;
+    struct gmbox_proto_hci_uart  *pProtocol = (struct gmbox_proto_hci_uart *)HciTrans; 
+    struct ar6k_device           *pDev = pProtocol->pDev;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportDetach \n"));
     
@@ -989,19 +994,19 @@
         UNLOCK_AR6K(pDev);
         return;
     }
-    pProtocol->HCIAttached = FALSE;
+    pProtocol->HCIAttached = false;
     UNLOCK_AR6K(pDev);
     
     HCI_TransportStop(HciTrans);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportAttach \n"));
 }
 
-A_STATUS HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue)
+int HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans; 
-    A_STATUS              status = A_OK;
-    A_BOOL                unblockRecv = FALSE;
-    HTC_PACKET            *pPacket;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans; 
+    int              status = 0;
+    bool                unblockRecv = false;
+    struct htc_packet            *pPacket;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HCI_TransportAddReceivePkt \n"));
     
@@ -1039,15 +1044,15 @@
                         pProt->WaitBufferType));
                 pProt->RecvStateFlags &= ~HCI_RECV_WAIT_BUFFERS;
                 pProt->WaitBufferType = HCI_PACKET_INVALID;
-                unblockRecv = TRUE;
+                unblockRecv = true;
             }
         }
         
-    } while (FALSE);
+    } while (false);
     
     UNLOCK_HCI_RX(pProt);
     
-    if (A_FAILED(status)) {
+    if (status) {
         while (!HTC_QUEUE_EMPTY(pQueue)) {
             pPacket = HTC_PACKET_DEQUEUE(pQueue);      
             pPacket->Status = A_ECANCELED;
@@ -1061,19 +1066,19 @@
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HCI_TransportAddReceivePkt \n"));
     
-    return A_OK;    
+    return 0;
 }
 
-A_STATUS HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous)
+int HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;  
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;  
     
     return HCITrySend(pProt,pPacket,Synchronous);
 }
 
 void HCI_TransportStop(HCI_TRANSPORT_HANDLE HciTrans)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans; 
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans; 
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStop \n"));
      
@@ -1083,7 +1088,7 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
         return;    
     }
-    pProt->HCIStopped = TRUE;
+    pProt->HCIStopped = true;
     UNLOCK_AR6K(pProt->pDev);
      
         /* disable interrupts */
@@ -1097,69 +1102,69 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStop \n"));
 }
 
-A_STATUS HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
+int HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans)
 {
-    A_STATUS              status;
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+    int              status;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("+HCI_TransportStart \n"));
     
         /* set stopped in case we have a problem in starting */
-    pProt->HCIStopped = TRUE;
+    pProt->HCIStopped = true;
     
     do {
         
         status = InitTxCreditState(pProt);   
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }     
         
         status = DevGMboxIRQAction(pProt->pDev, GMBOX_ERRORS_IRQ_ENABLE, PROC_IO_SYNC);   
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;   
         } 
             /* enable recv */   
         status = DevGMboxIRQAction(pProt->pDev, GMBOX_RECV_IRQ_ENABLE, PROC_IO_SYNC);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;   
         } 
             /* signal bridge side to power up BT */
         status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BT_ON, BTON_TIMEOUT_MS);
         
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI_TransportStart : Failed to trigger BT ON \n"));
             break;   
         } 
         
             /* we made it */
-        pProt->HCIStopped = FALSE;
+        pProt->HCIStopped = false;
         
-    } while (FALSE);
+    } while (false);
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC,("-HCI_TransportStart \n"));
     
     return status;
 }
 
-A_STATUS HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
+int HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
     return DevGMboxIRQAction(pProt->pDev, 
                              Enable ? GMBOX_RECV_IRQ_ENABLE : GMBOX_RECV_IRQ_DISABLE, 
                              PROC_IO_SYNC);
                              
 }
 
-A_STATUS HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
-                                       HTC_PACKET           *pPacket,
+int HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
+                                       struct htc_packet           *pPacket,
                                        int                  MaxPollMS)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
-    A_STATUS              status = A_OK;
-    A_UINT8               lookAhead[8];
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
+    int              status = 0;
+    u8 lookAhead[8];
     int                   bytes;
     int                   totalRecvLength;
     
@@ -1173,7 +1178,7 @@
         
         bytes = sizeof(lookAhead);
         status = DevGMboxRecvLookAheadPeek(pProt->pDev,lookAhead,&bytes);
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }        
                 
@@ -1199,19 +1204,19 @@
                 break;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
         pPacket->Completion = NULL;
         status = DevGMboxRead(pProt->pDev,pPacket,totalRecvLength); 
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
         pPacket->pBuffer++;
         pPacket->ActualLength = totalRecvLength - 1;
-        pPacket->Status = A_OK;        
+        pPacket->Status = 0;
         break; 
     }
     
@@ -1225,12 +1230,12 @@
 
 #define LSB_SCRATCH_IDX     4
 #define MSB_SCRATCH_IDX     5
-A_STATUS HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud)
+int HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud)
 {
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
-    HIF_DEVICE *pHIFDevice = (HIF_DEVICE *)(pProt->pDev->HIFDevice);
-    A_UINT32 scaledBaud, scratchAddr;
-    A_STATUS status = A_OK;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
+    struct hif_device *pHIFDevice = (struct hif_device *)(pProt->pDev->HIFDevice);
+    u32 scaledBaud, scratchAddr;
+    int status = 0;
 
     /* Divide the desired baud rate by 100
      * Store the LSB in the local scratch register 4 and the MSB in the local
@@ -1242,24 +1247,24 @@
     scratchAddr = MBOX_BASE_ADDRESS | (LOCAL_SCRATCH_ADDRESS + 4 * MSB_SCRATCH_IDX);
     scaledBaud = ((Baud / 100) >> (LOCAL_SCRATCH_VALUE_MSB+1)) & LOCAL_SCRATCH_VALUE_MASK;
     status |= ar6000_WriteRegDiag(pHIFDevice, &scratchAddr, &scaledBaud);                     
-    if (A_OK != status) {
+    if (0 != status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to set up baud rate in scratch register!"));            
         return status;
     }
 
     /* Now interrupt the target to tell it about the baud rate */
     status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_BAUD_SET, BAUD_TIMEOUT_MS);
-    if (A_OK != status) {
+    if (0 != status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Failed to tell target to change baud rate!"));            
     }
     
     return status;
 }
 
-A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable)
+int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable)
 {
-    A_STATUS status;
-    GMBOX_PROTO_HCI_UART  *pProt = (GMBOX_PROTO_HCI_UART *)HciTrans;
+    int status;
+    struct gmbox_proto_hci_uart  *pProt = (struct gmbox_proto_hci_uart *)HciTrans;
                              
     if (Enable) {
         status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_ON, BTPWRSAV_TIMEOUT_MS);
@@ -1267,7 +1272,7 @@
         status = DevGMboxSetTargetInterrupt(pProt->pDev, MBOX_SIG_HCI_BRIDGE_PWR_SAV_OFF, BTPWRSAV_TIMEOUT_MS);
     }
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to enable/disable HCI power management!\n"));
     } else {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HCI power management enabled/disabled!\n"));
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/AR6000/ar6k.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,40 +43,40 @@
 //#define MBOXHW_UNIT_TEST 1
 
 #include "athstartpack.h"
-typedef PREPACK struct _AR6K_IRQ_PROC_REGISTERS {
-    A_UINT8                      host_int_status;
-    A_UINT8                      cpu_int_status;
-    A_UINT8                      error_int_status;
-    A_UINT8                      counter_int_status;
-    A_UINT8                      mbox_frame;
-    A_UINT8                      rx_lookahead_valid;
-    A_UINT8                      host_int_status2;
-    A_UINT8                      gmbox_rx_avail;
-    A_UINT32                     rx_lookahead[2];
-    A_UINT32                     rx_gmbox_lookahead_alias[2];
-} POSTPACK AR6K_IRQ_PROC_REGISTERS;
+PREPACK struct ar6k_irq_proc_registers {
+    u8 host_int_status;
+    u8 cpu_int_status;
+    u8 error_int_status;
+    u8 counter_int_status;
+    u8 mbox_frame;
+    u8 rx_lookahead_valid;
+    u8 host_int_status2;
+    u8 gmbox_rx_avail;
+    u32 rx_lookahead[2];
+    u32 rx_gmbox_lookahead_alias[2];
+} POSTPACK;
 
-#define AR6K_IRQ_PROC_REGS_SIZE sizeof(AR6K_IRQ_PROC_REGISTERS)
+#define AR6K_IRQ_PROC_REGS_SIZE sizeof(struct ar6k_irq_proc_registers)
 
-typedef PREPACK struct _AR6K_IRQ_ENABLE_REGISTERS {
-    A_UINT8                      int_status_enable;
-    A_UINT8                      cpu_int_status_enable;
-    A_UINT8                      error_status_enable;
-    A_UINT8                      counter_int_status_enable;
-} POSTPACK AR6K_IRQ_ENABLE_REGISTERS;
+PREPACK struct ar6k_irq_enable_registers {
+    u8 int_status_enable;
+    u8 cpu_int_status_enable;
+    u8 error_status_enable;
+    u8 counter_int_status_enable;
+} POSTPACK;
 
-typedef PREPACK struct _AR6K_GMBOX_CTRL_REGISTERS {
-    A_UINT8                      int_status_enable;
-} POSTPACK AR6K_GMBOX_CTRL_REGISTERS;
+PREPACK struct ar6k_gmbox_ctrl_registers {
+    u8 int_status_enable;
+} POSTPACK;
 
 #include "athendpack.h"
 
-#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(AR6K_IRQ_ENABLE_REGISTERS)
+#define AR6K_IRQ_ENABLE_REGS_SIZE sizeof(struct ar6k_irq_enable_registers)
 
 #define AR6K_REG_IO_BUFFER_SIZE     32
 #define AR6K_MAX_REG_IO_BUFFERS     8
-#define FROM_DMA_BUFFER TRUE
-#define TO_DMA_BUFFER   FALSE
+#define FROM_DMA_BUFFER true
+#define TO_DMA_BUFFER   false
 #define AR6K_SCATTER_ENTRIES_PER_REQ            16
 #define AR6K_MAX_TRANSFER_SIZE_PER_SCATTER      16*1024
 #define AR6K_SCATTER_REQS                       4
@@ -89,107 +89,107 @@
 #define AR6K_MIN_TRANSFER_SIZE_PER_SCATTER      4*1024
 
 /* buffers for ASYNC I/O */
-typedef struct AR6K_ASYNC_REG_IO_BUFFER {
-    HTC_PACKET    HtcPacket;   /* we use an HTC packet as a wrapper for our async register-based I/O */
-    A_UINT8       _Pad1[A_CACHE_LINE_PAD];
-    A_UINT8       Buffer[AR6K_REG_IO_BUFFER_SIZE];  /* cache-line safe with pads around */
-    A_UINT8       _Pad2[A_CACHE_LINE_PAD];
-} AR6K_ASYNC_REG_IO_BUFFER;
+struct ar6k_async_reg_io_buffer {
+    struct htc_packet    HtcPacket;   /* we use an HTC packet as a wrapper for our async register-based I/O */
+    u8 _Pad1[A_CACHE_LINE_PAD];
+    u8 Buffer[AR6K_REG_IO_BUFFER_SIZE];  /* cache-line safe with pads around */
+    u8 _Pad2[A_CACHE_LINE_PAD];
+};
 
-typedef struct _AR6K_GMBOX_INFO { 
+struct ar6k_gmbox_info { 
     void        *pProtocolContext;
-    A_STATUS    (*pMessagePendingCallBack)(void *pContext, A_UINT8 LookAheadBytes[], int ValidBytes);
-    A_STATUS    (*pCreditsPendingCallback)(void *pContext, int NumCredits,  A_BOOL CreditIRQEnabled);
-    void        (*pTargetFailureCallback)(void *pContext, A_STATUS Status);
+    int    (*pMessagePendingCallBack)(void *pContext, u8 LookAheadBytes[], int ValidBytes);
+    int    (*pCreditsPendingCallback)(void *pContext, int NumCredits,  bool CreditIRQEnabled);
+    void        (*pTargetFailureCallback)(void *pContext, int Status);
     void        (*pStateDumpCallback)(void *pContext);
-    A_BOOL      CreditCountIRQEnabled;    
-} AR6K_GMBOX_INFO; 
+    bool      CreditCountIRQEnabled;
+}; 
 
-typedef struct _AR6K_DEVICE {
+struct ar6k_device {
     A_MUTEX_T                   Lock;
-    A_UINT8       _Pad1[A_CACHE_LINE_PAD];
-    AR6K_IRQ_PROC_REGISTERS     IrqProcRegisters;   /* cache-line safe with pads around */
-    A_UINT8       _Pad2[A_CACHE_LINE_PAD];
-    AR6K_IRQ_ENABLE_REGISTERS   IrqEnableRegisters; /* cache-line safe with pads around */
-    A_UINT8       _Pad3[A_CACHE_LINE_PAD];
+    u8 _Pad1[A_CACHE_LINE_PAD];
+    struct ar6k_irq_proc_registers     IrqProcRegisters;   /* cache-line safe with pads around */
+    u8 _Pad2[A_CACHE_LINE_PAD];
+    struct ar6k_irq_enable_registers   IrqEnableRegisters; /* cache-line safe with pads around */
+    u8 _Pad3[A_CACHE_LINE_PAD];
     void                        *HIFDevice;
-    A_UINT32                    BlockSize;
-    A_UINT32                    BlockMask;
-    HIF_DEVICE_MBOX_INFO        MailBoxInfo;
+    u32 BlockSize;
+    u32 BlockMask;
+    struct hif_device_mbox_info        MailBoxInfo;
     HIF_PENDING_EVENTS_FUNC     GetPendingEventsFunc;
     void                        *HTCContext;
-    HTC_PACKET_QUEUE            RegisterIOList;
-    AR6K_ASYNC_REG_IO_BUFFER    RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
+    struct htc_packet_queue            RegisterIOList;
+    struct ar6k_async_reg_io_buffer    RegIOBuffers[AR6K_MAX_REG_IO_BUFFERS];
     void                        (*TargetFailureCallback)(void *Context);
-    A_STATUS                    (*MessagePendingCallback)(void *Context, 
-                                                          A_UINT32 LookAheads[], 
+    int                    (*MessagePendingCallback)(void *Context,
+                                                          u32 LookAheads[],
                                                           int NumLookAheads, 
-                                                          A_BOOL *pAsyncProc,
+                                                          bool *pAsyncProc,
                                                           int *pNumPktsFetched);
     HIF_DEVICE_IRQ_PROCESSING_MODE  HifIRQProcessingMode;
     HIF_MASK_UNMASK_RECV_EVENT      HifMaskUmaskRecvEvent;
-    A_BOOL                          HifAttached;
-    HIF_DEVICE_IRQ_YIELD_PARAMS     HifIRQYieldParams;
-    A_BOOL                          DSRCanYield;
+    bool                          HifAttached;
+    struct hif_device_irq_yield_params     HifIRQYieldParams;
+    bool                          DSRCanYield;
     int                             CurrentDSRRecvCount;
-    HIF_DEVICE_SCATTER_SUPPORT_INFO HifScatterInfo;
-    DL_LIST                         ScatterReqHead; 
-    A_BOOL                          ScatterIsVirtual;    
+    struct hif_device_scatter_support_info HifScatterInfo;
+    struct dl_list                         ScatterReqHead; 
+    bool                          ScatterIsVirtual;
     int                             MaxRecvBundleSize;
     int                             MaxSendBundleSize;
-    AR6K_GMBOX_INFO                 GMboxInfo;
-    A_BOOL                          GMboxEnabled; 
-    AR6K_GMBOX_CTRL_REGISTERS       GMboxControlRegisters;
+    struct ar6k_gmbox_info                 GMboxInfo;
+    bool                          GMboxEnabled;
+    struct ar6k_gmbox_ctrl_registers       GMboxControlRegisters;
     int                             RecheckIRQStatusCnt;
-} AR6K_DEVICE;
+};
 
 #define LOCK_AR6K(p)      A_MUTEX_LOCK(&(p)->Lock);
 #define UNLOCK_AR6K(p)    A_MUTEX_UNLOCK(&(p)->Lock);
 #define REF_IRQ_STATUS_RECHECK(p) (p)->RecheckIRQStatusCnt = 1  /* note: no need to lock this, it only gets set */
 
-A_STATUS DevSetup(AR6K_DEVICE *pDev);
-void     DevCleanup(AR6K_DEVICE *pDev);
-A_STATUS DevUnmaskInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevMaskInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevPollMboxMsgRecv(AR6K_DEVICE *pDev,
-                            A_UINT32    *pLookAhead,
+int DevSetup(struct ar6k_device *pDev);
+void     DevCleanup(struct ar6k_device *pDev);
+int DevUnmaskInterrupts(struct ar6k_device *pDev);
+int DevMaskInterrupts(struct ar6k_device *pDev);
+int DevPollMboxMsgRecv(struct ar6k_device *pDev,
+                            u32 *pLookAhead,
                             int          TimeoutMS);
-A_STATUS DevRWCompletionHandler(void *context, A_STATUS status);
-A_STATUS DevDsrHandler(void *context);
-A_STATUS DevCheckPendingRecvMsgsAsync(void *context);
-void     DevAsyncIrqProcessComplete(AR6K_DEVICE *pDev);
-void     DevDumpRegisters(AR6K_DEVICE               *pDev,
-                          AR6K_IRQ_PROC_REGISTERS   *pIrqProcRegs,
-                          AR6K_IRQ_ENABLE_REGISTERS *pIrqEnableRegs);
+int DevRWCompletionHandler(void *context, int status);
+int DevDsrHandler(void *context);
+int DevCheckPendingRecvMsgsAsync(void *context);
+void     DevAsyncIrqProcessComplete(struct ar6k_device *pDev);
+void     DevDumpRegisters(struct ar6k_device               *pDev,
+                          struct ar6k_irq_proc_registers   *pIrqProcRegs,
+                          struct ar6k_irq_enable_registers *pIrqEnableRegs);
 
-#define DEV_STOP_RECV_ASYNC TRUE
-#define DEV_STOP_RECV_SYNC  FALSE
-#define DEV_ENABLE_RECV_ASYNC TRUE
-#define DEV_ENABLE_RECV_SYNC  FALSE
-A_STATUS DevStopRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
-A_STATUS DevEnableRecv(AR6K_DEVICE *pDev, A_BOOL ASyncMode);
-A_STATUS DevEnableInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevDisableInterrupts(AR6K_DEVICE *pDev);
-A_STATUS DevWaitForPendingRecv(AR6K_DEVICE *pDev,A_UINT32 TimeoutInMs,A_BOOL *pbIsRecvPending);
+#define DEV_STOP_RECV_ASYNC true
+#define DEV_STOP_RECV_SYNC  false
+#define DEV_ENABLE_RECV_ASYNC true
+#define DEV_ENABLE_RECV_SYNC  false
+int DevStopRecv(struct ar6k_device *pDev, bool ASyncMode);
+int DevEnableRecv(struct ar6k_device *pDev, bool ASyncMode);
+int DevEnableInterrupts(struct ar6k_device *pDev);
+int DevDisableInterrupts(struct ar6k_device *pDev);
+int DevWaitForPendingRecv(struct ar6k_device *pDev,u32 TimeoutInMs,bool *pbIsRecvPending);
 
 #define DEV_CALC_RECV_PADDED_LEN(pDev, length) (((length) + (pDev)->BlockMask) & (~((pDev)->BlockMask)))
 #define DEV_CALC_SEND_PADDED_LEN(pDev, length) DEV_CALC_RECV_PADDED_LEN(pDev,length)
 #define DEV_IS_LEN_BLOCK_ALIGNED(pDev, length) (((length) % (pDev)->BlockSize) == 0)
 
-static INLINE A_STATUS DevSendPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 SendLength) {
-    A_UINT32 paddedLength;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
-    A_STATUS status;
+static INLINE int DevSendPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 SendLength) {
+    u32 paddedLength;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
+    int status;
 
        /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_SEND_PADDED_LEN(pDev, SendLength);
 
 #if 0                    
     if (paddedLength > pPacket->BufferLength) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         if (pPacket->Completion != NULL) {
             COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
-            return A_OK;
+            return 0;
         }
         return A_EINVAL;
     }
@@ -212,29 +212,29 @@
         pPacket->Status = status;
     } else {
         if (status == A_PENDING) {
-            status = A_OK;    
+            status = 0;
         }    
     }
 
     return status;
 }
                     
-static INLINE A_STATUS DevRecvPacket(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 RecvLength) {
-    A_UINT32 paddedLength;
-    A_STATUS status;
-    A_BOOL   sync = (pPacket->Completion == NULL) ? TRUE : FALSE;
+static INLINE int DevRecvPacket(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 RecvLength) {
+    u32 paddedLength;
+    int status;
+    bool   sync = (pPacket->Completion == NULL) ? true : false;
 
         /* adjust the length to be a multiple of block size if appropriate */
     paddedLength = DEV_CALC_RECV_PADDED_LEN(pDev, RecvLength);
                     
     if (paddedLength > pPacket->BufferLength) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("DevRecvPacket, Not enough space for padlen:%d recvlen:%d bufferlen:%d \n",
                     paddedLength,RecvLength,pPacket->BufferLength));
         if (pPacket->Completion != NULL) {
             COMPLETE_HTC_PACKET(pPacket,A_EINVAL);
-            return A_OK;
+            return 0;
         }
         return A_EINVAL;
     }
@@ -272,27 +272,33 @@
  *  
  */
   
-A_STATUS DevCopyScatterListToFromDMABuffer(HIF_SCATTER_REQ *pReq, A_BOOL FromDMA);
+int DevCopyScatterListToFromDMABuffer(struct hif_scatter_req *pReq, bool FromDMA);
     
     /* copy any READ data back into scatter list */        
-#define DEV_FINISH_SCATTER_OPERATION(pR)                      \
-    if (A_SUCCESS((pR)->CompletionStatus) &&                  \
-        !((pR)->Request & HIF_WRITE) &&                       \
-         ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {   \
-         (pR)->CompletionStatus = DevCopyScatterListToFromDMABuffer((pR),FROM_DMA_BUFFER); \
-    }
+#define DEV_FINISH_SCATTER_OPERATION(pR)				\
+do {									\
+	if (!((pR)->CompletionStatus) &&				\
+	    !((pR)->Request & HIF_WRITE) &&				\
+	    ((pR)->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {		\
+		(pR)->CompletionStatus =				\
+			DevCopyScatterListToFromDMABuffer((pR),		\
+							  FROM_DMA_BUFFER); \
+	}								\
+} while (0)
     
     /* copy any WRITE data to bounce buffer */
-static INLINE A_STATUS DEV_PREPARE_SCATTER_OPERATION(HIF_SCATTER_REQ *pReq)  { 
+static INLINE int DEV_PREPARE_SCATTER_OPERATION(struct hif_scatter_req *pReq)  {
     if ((pReq->Request & HIF_WRITE) && (pReq->ScatterMethod == HIF_SCATTER_DMA_BOUNCE)) {
         return DevCopyScatterListToFromDMABuffer(pReq,TO_DMA_BUFFER);    
     } else {
-        return A_OK;    
+        return 0;
     }
 }
         
     
-A_STATUS DevSetupMsgBundling(AR6K_DEVICE *pDev, int MaxMsgsPerTransfer);
+int DevSetupMsgBundling(struct ar6k_device *pDev, int MaxMsgsPerTransfer);
+
+int DevCleanupMsgBundling(struct ar6k_device *pDev);
                                   
 #define DEV_GET_MAX_MSG_PER_BUNDLE(pDev)        (pDev)->HifScatterInfo.MaxScatterEntries
 #define DEV_GET_MAX_BUNDLE_LENGTH(pDev)         (pDev)->HifScatterInfo.MaxTransferSizePerScatterReq
@@ -305,25 +311,25 @@
 #define DEV_GET_MAX_BUNDLE_RECV_LENGTH(pDev)   (pDev)->MaxRecvBundleSize
 #define DEV_GET_MAX_BUNDLE_SEND_LENGTH(pDev)   (pDev)->MaxSendBundleSize
 
-#define DEV_SCATTER_READ  TRUE
-#define DEV_SCATTER_WRITE FALSE
-#define DEV_SCATTER_ASYNC TRUE
-#define DEV_SCATTER_SYNC  FALSE
-A_STATUS DevSubmitScatterRequest(AR6K_DEVICE *pDev, HIF_SCATTER_REQ *pScatterReq, A_BOOL Read, A_BOOL Async);
+#define DEV_SCATTER_READ  true
+#define DEV_SCATTER_WRITE false
+#define DEV_SCATTER_ASYNC true
+#define DEV_SCATTER_SYNC  false
+int DevSubmitScatterRequest(struct ar6k_device *pDev, struct hif_scatter_req *pScatterReq, bool Read, bool Async);
 
 #ifdef MBOXHW_UNIT_TEST
-A_STATUS DoMboxHWTest(AR6K_DEVICE *pDev);
+int DoMboxHWTest(struct ar6k_device *pDev);
 #endif
 
     /* completely virtual */
-typedef struct _DEV_SCATTER_DMA_VIRTUAL_INFO {
-    A_UINT8            *pVirtDmaBuffer;      /* dma-able buffer - CPU accessible address */
-    A_UINT8            DataArea[1];      /* start of data area */
-} DEV_SCATTER_DMA_VIRTUAL_INFO;
+struct dev_scatter_dma_virtual_info {
+    u8 *pVirtDmaBuffer;      /* dma-able buffer - CPU accessible address */
+    u8 DataArea[1];      /* start of data area */
+};
 
 
 
-void     DumpAR6KDevState(AR6K_DEVICE *pDev);
+void     DumpAR6KDevState(struct ar6k_device *pDev);
 
 /**************************************************/
 /****** GMBOX functions and definitions
@@ -333,21 +339,21 @@
 
 #ifdef ATH_AR6K_ENABLE_GMBOX
 
-void     DevCleanupGMbox(AR6K_DEVICE *pDev);
-A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev);
-A_STATUS DevCheckGMboxInterrupts(AR6K_DEVICE *pDev);
-void     DevNotifyGMboxTargetFailure(AR6K_DEVICE *pDev);
+void     DevCleanupGMbox(struct ar6k_device *pDev);
+int DevSetupGMbox(struct ar6k_device *pDev);
+int DevCheckGMboxInterrupts(struct ar6k_device *pDev);
+void     DevNotifyGMboxTargetFailure(struct ar6k_device *pDev);
 
 #else
 
     /* compiled out */
 #define DevCleanupGMbox(p)
-#define DevCheckGMboxInterrupts(p) A_OK
+#define DevCheckGMboxInterrupts(p) 0
 #define DevNotifyGMboxTargetFailure(p)
 
-static INLINE A_STATUS DevSetupGMbox(AR6K_DEVICE *pDev) {
-    pDev->GMboxEnabled = FALSE;
-    return A_OK;    
+static INLINE int DevSetupGMbox(struct ar6k_device *pDev) {
+    pDev->GMboxEnabled = false;
+    return 0;
 }
 
 #endif
@@ -355,12 +361,12 @@
 #ifdef ATH_AR6K_ENABLE_GMBOX
 
     /* GMBOX protocol modules must expose each of these internal APIs */
-HCI_TRANSPORT_HANDLE GMboxAttachProtocol(AR6K_DEVICE *pDev, HCI_TRANSPORT_CONFIG_INFO *pInfo);
-A_STATUS             GMboxProtocolInstall(AR6K_DEVICE *pDev);
-void                 GMboxProtocolUninstall(AR6K_DEVICE *pDev);
+HCI_TRANSPORT_HANDLE GMboxAttachProtocol(struct ar6k_device *pDev, struct hci_transport_config_info *pInfo);
+int             GMboxProtocolInstall(struct ar6k_device *pDev);
+void                 GMboxProtocolUninstall(struct ar6k_device *pDev);
 
     /* API used by GMBOX protocol modules */
-AR6K_DEVICE  *HTCGetAR6KDevice(void *HTCHandle);
+struct ar6k_device  *HTCGetAR6KDevice(void *HTCHandle);
 #define DEV_GMBOX_SET_PROTOCOL(pDev,recv_callback,credits_pending,failure,statedump,context) \
 {                                                                  \
     (pDev)->GMboxInfo.pProtocolContext = (context);                \
@@ -372,11 +378,11 @@
 
 #define DEV_GMBOX_GET_PROTOCOL(pDev)  (pDev)->GMboxInfo.pProtocolContext
 
-A_STATUS DevGMboxWrite(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 WriteLength);
-A_STATUS DevGMboxRead(AR6K_DEVICE *pDev, HTC_PACKET *pPacket, A_UINT32 ReadLength);
+int DevGMboxWrite(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 WriteLength);
+int DevGMboxRead(struct ar6k_device *pDev, struct htc_packet *pPacket, u32 ReadLength);
 
-#define PROC_IO_ASYNC TRUE
-#define PROC_IO_SYNC  FALSE
+#define PROC_IO_ASYNC true
+#define PROC_IO_SYNC  false
 typedef enum GMBOX_IRQ_ACTION_TYPE {
     GMBOX_ACTION_NONE = 0,
     GMBOX_DISABLE_ALL,
@@ -387,11 +393,11 @@
     GMBOX_CREDIT_IRQ_DISABLE,
 } GMBOX_IRQ_ACTION_TYPE;
 
-A_STATUS DevGMboxIRQAction(AR6K_DEVICE *pDev, GMBOX_IRQ_ACTION_TYPE, A_BOOL AsyncMode);
-A_STATUS DevGMboxReadCreditCounter(AR6K_DEVICE *pDev, A_BOOL AsyncMode, int *pCredits);
-A_STATUS DevGMboxReadCreditSize(AR6K_DEVICE *pDev, int *pCreditSize);
-A_STATUS DevGMboxRecvLookAheadPeek(AR6K_DEVICE *pDev, A_UINT8 *pLookAheadBuffer, int *pLookAheadBytes);
-A_STATUS DevGMboxSetTargetInterrupt(AR6K_DEVICE *pDev, int SignalNumber, int AckTimeoutMS);
+int DevGMboxIRQAction(struct ar6k_device *pDev, GMBOX_IRQ_ACTION_TYPE, bool AsyncMode);
+int DevGMboxReadCreditCounter(struct ar6k_device *pDev, bool AsyncMode, int *pCredits);
+int DevGMboxReadCreditSize(struct ar6k_device *pDev, int *pCreditSize);
+int DevGMboxRecvLookAheadPeek(struct ar6k_device *pDev, u8 *pLookAheadBuffer, int *pLookAheadBytes);
+int DevGMboxSetTargetInterrupt(struct ar6k_device *pDev, int SignalNumber, int AckTimeoutMS);
 
 #endif
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc.c	2011-05-19 00:06:34.000000000 -0400
@@ -23,7 +23,7 @@
 #include "htc_internal.h"
 
 #ifdef ATH_DEBUG_MODULE
-static ATH_DEBUG_MASK_DESCRIPTION g_HTCDebugDescription[] = {
+static struct ath_debug_mask_description g_HTCDebugDescription[] = {
     { ATH_DEBUG_SEND , "Send"},
     { ATH_DEBUG_RECV , "Recv"},
     { ATH_DEBUG_SYNC , "Sync"},
@@ -41,18 +41,18 @@
 #endif
 
 static void HTCReportFailure(void *Context);
-static void ResetEndpointStates(HTC_TARGET *target);
+static void ResetEndpointStates(struct htc_target *target);
 
-void HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList)
+void HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList)
 {
     LOCK_HTC(target);
     HTC_PACKET_ENQUEUE(pList,pPacket);
     UNLOCK_HTC(target);
 }
 
-HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target,  HTC_PACKET_QUEUE *pList)
+struct htc_packet *HTCAllocControlBuffer(struct htc_target *target,  struct htc_packet_queue *pList)
 {
-    HTC_PACKET *pPacket;
+    struct htc_packet *pPacket;
 
     LOCK_HTC(target);
     pPacket = HTC_PACKET_DEQUEUE(pList);
@@ -62,9 +62,9 @@
 }
 
 /* cleanup the HTC instance */
-static void HTCCleanup(HTC_TARGET *target)
+static void HTCCleanup(struct htc_target *target)
 {
-    A_INT32 i;
+    s32 i;
 
     DevCleanup(&target->Device);
     
@@ -90,13 +90,13 @@
 }
 
 /* registered target arrival callback from the HIF layer */
-HTC_HANDLE HTCCreate(void *hif_handle, HTC_INIT_INFO *pInfo)
+HTC_HANDLE HTCCreate(void *hif_handle, struct htc_init_info *pInfo)
 {
-    HTC_TARGET              *target = NULL;
-    A_STATUS                 status = A_OK;
+    struct htc_target              *target = NULL;
+    int                 status = 0;
     int                      i;
-    A_UINT32                 ctrl_bufsz;
-    A_UINT32                 blocksizes[HTC_MAILBOX_NUM_MAX];
+    u32 ctrl_bufsz;
+    u32 blocksizes[HTC_MAILBOX_NUM_MAX];
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCCreate - Enter\n"));
 
@@ -105,13 +105,13 @@
     do {
 
             /* allocate target memory */
-        if ((target = (HTC_TARGET *)A_MALLOC(sizeof(HTC_TARGET))) == NULL) {
+        if ((target = (struct htc_target *)A_MALLOC(sizeof(struct htc_target))) == NULL) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unable to allocate memory\n"));
             status = A_ERROR;
             break;
         }
 
-        A_MEMZERO(target, sizeof(HTC_TARGET));
+        A_MEMZERO(target, sizeof(struct htc_target));
         A_MUTEX_INIT(&target->HTCLock);
         A_MUTEX_INIT(&target->HTCRxLock);
         A_MUTEX_INIT(&target->HTCTxLock);
@@ -130,14 +130,14 @@
         target->Device.MessagePendingCallback = HTCRecvMessagePendingHandler;
         target->EpWaitingForBuffers = ENDPOINT_MAX;
 
-        A_MEMCPY(&target->HTCInitInfo,pInfo,sizeof(HTC_INIT_INFO));
+        memcpy(&target->HTCInitInfo,pInfo,sizeof(struct htc_init_info));
         
         ResetEndpointStates(target);
           
             /* setup device layer */
         status = DevSetup(&target->Device);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -145,7 +145,7 @@
         /* get the block sizes */
         status = HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     blocksizes, sizeof(blocksizes));
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to get block size info from HIF layer...\n"));
             break;
         }
@@ -165,13 +165,13 @@
             }
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
             /* carve up buffers/packets for control messages */
         for (i = 0; i < NUM_CONTROL_RX_BUFFERS; i++) {
-            HTC_PACKET *pControlPacket;
+            struct htc_packet *pControlPacket;
             pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
             SET_HTC_PACKET_INFO_RX_REFILL(pControlPacket,
                                           target,
@@ -182,7 +182,7 @@
         }
 
         for (;i < NUM_CONTROL_BUFFERS;i++) {
-             HTC_PACKET *pControlPacket;
+             struct htc_packet *pControlPacket;
              pControlPacket = &target->HTCControlBuffers[i].HtcPacket;
              INIT_HTC_PACKET_INFO(pControlPacket,
                                   target->HTCControlBuffers[i].Buffer,
@@ -190,9 +190,9 @@
              HTC_FREE_CONTROL_TX(target,pControlPacket);
         }
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (target != NULL) {
             HTCCleanup(target);
             target = NULL;
@@ -206,7 +206,7 @@
 
 void  HTCDestroy(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCDestroy ..  Destroying :0x%lX \n",(unsigned long)target));
     HTCCleanup(target);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCDestroy \n"));
@@ -216,21 +216,21 @@
  * HIF requests */
 void *HTCGetHifDevice(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     return target->Device.HIFDevice;
 }
 
 /* wait for the target to arrive (sends HTC Ready message)
  * this operation is fully synchronous and the message is polled for */
-A_STATUS HTCWaitTarget(HTC_HANDLE HTCHandle)
+int HTCWaitTarget(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET              *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_STATUS                 status;
-    HTC_PACKET              *pPacket = NULL;
+    struct htc_target              *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    int                 status;
+    struct htc_packet              *pPacket = NULL;
     HTC_READY_EX_MSG        *pRdyMsg;
 
-    HTC_SERVICE_CONNECT_REQ  connect;
-    HTC_SERVICE_CONNECT_RESP resp;
+    struct htc_service_connect_req  connect;
+    struct htc_service_connect_resp resp;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCWaitTarget - Enter (target:0x%lX) \n", (unsigned long)target));
 
@@ -240,7 +240,7 @@
 
         status = DoMboxHWTest(&target->Device);
 
-        if (status != A_OK) {
+        if (status) {
             break;
         }
 
@@ -249,7 +249,7 @@
             /* we should be getting 1 control message that the target is ready */
         status = HTCWaitforControlMessage(target, &pPacket);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, (" Target Not Available!!\n"));
             break;
         }
@@ -260,7 +260,7 @@
         if ((pRdyMsg->Version2_0_Info.MessageID != HTC_MSG_READY_ID) ||
             (pPacket->ActualLength < sizeof(HTC_READY_MSG))) {
                 /* this message is not valid */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -268,7 +268,7 @@
         
         if (pRdyMsg->Version2_0_Info.CreditCount == 0 || pRdyMsg->Version2_0_Info.CreditSize == 0) {
               /* this message is not valid */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -305,7 +305,7 @@
                 /* limit what HTC can handle */
             target->MaxMsgPerBundle = min(HTC_HOST_MAX_MSG_PER_BUNDLE, target->MaxMsgPerBundle);          
                 /* target supports message bundling, setup device layer */
-            if (A_FAILED(DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle))) {
+            if (DevSetupMsgBundling(&target->Device,target->MaxMsgPerBundle)) {
                     /* device layer can't handle bundling */
                 target->MaxMsgPerBundle = 0;        
             } else {
@@ -320,10 +320,10 @@
                     (" HTC bundling allowed. Max Msg Per HTC Bundle: %d\n", target->MaxMsgPerBundle));    
            
             if (DEV_GET_MAX_BUNDLE_SEND_LENGTH(&target->Device) != 0) {           
-                target->SendBundlingEnabled = TRUE;
+                target->SendBundlingEnabled = true;
             }            
             if (DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device) != 0) {    
-                target->RecvBundlingEnabled = TRUE;    
+                target->RecvBundlingEnabled = true;
             }
                             
             if (!DEV_IS_LEN_BLOCK_ALIGNED(&target->Device,target->TargetCreditSize)) {
@@ -331,7 +331,7 @@
                         target->TargetCreditSize));    
                     /* disallow send bundling since the credit size is not aligned to a block size
                      * the I/O block padding will spill into the next credit buffer which is fatal */
-                target->SendBundlingEnabled = FALSE;
+                target->SendBundlingEnabled = false;
             }
         }
            
@@ -351,11 +351,11 @@
                                    &connect,
                                    &resp);
 
-        if (!A_FAILED(status)) {
+        if (!status) {
             break;
         }
 
-    } while (FALSE);
+    } while (false);
 
     if (pPacket != NULL) {
         HTC_FREE_CONTROL_RX(target,pPacket);
@@ -369,11 +369,11 @@
 
 
 /* Start HTC, enable interrupts and let the target know host has finished setup */
-A_STATUS HTCStart(HTC_HANDLE HTCHandle)
+int HTCStart(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_PACKET *pPacket;
-    A_STATUS   status;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_packet *pPacket;
+    int   status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Enter\n"));
 
@@ -419,26 +419,26 @@
             * target that the setup phase is complete */
         status = HTCSendSetupComplete(target);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
             /* unmask interrupts */
         status = DevUnmaskInterrupts(&target->Device);
 
-        if (A_FAILED(status)) {
+        if (status) {
             HTCStop(target);
         }
 
-    } while (FALSE);
+    } while (false);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HTCStart Exit\n"));
     return status;
 }
 
-static void ResetEndpointStates(HTC_TARGET *target)
+static void ResetEndpointStates(struct htc_target *target)
 {
-    HTC_ENDPOINT        *pEndpoint;
+    struct htc_endpoint        *pEndpoint;
     int                  i;
 
     for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
@@ -463,7 +463,7 @@
 /* stop HTC communications, i.e. stop interrupt reception, and flush all queued buffers */
 void HTCStop(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCStop \n"));
 
     LOCK_HTC(target);
@@ -486,6 +486,8 @@
         /* flush all recv buffers */
     HTCFlushRecvBuffers(target);
 
+    DevCleanupMsgBundling(&target->Device);
+
     ResetEndpointStates(target);
    
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("-HTCStop \n"));
@@ -494,7 +496,7 @@
 #ifdef ATH_DEBUG_MODULE
 void HTCDumpCreditStates(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     LOCK_HTC_TX(target);
 
@@ -509,9 +511,9 @@
  * which uses a mechanism to report errors from the target (i.e. special interrupts) */
 static void HTCReportFailure(void *Context)
 {
-    HTC_TARGET *target = (HTC_TARGET *)Context;
+    struct htc_target *target = (struct htc_target *)Context;
 
-    target->TargetFailure = TRUE;
+    target->TargetFailure = true;
 
     if (target->HTCInitInfo.TargetFailure != NULL) {
             /* let upper layer know, it needs to call HTCStop() */
@@ -519,27 +521,27 @@
     }
 }
 
-A_BOOL HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
+bool HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
                                 HTC_ENDPOINT_ID          Endpoint,
                                 HTC_ENDPOINT_STAT_ACTION Action,
-                                HTC_ENDPOINT_STATS       *pStats)
+                                struct htc_endpoint_stats       *pStats)
 {
 
 #ifdef HTC_EP_STAT_PROFILING
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_BOOL     clearStats = FALSE;
-    A_BOOL     sample = FALSE;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    bool     clearStats = false;
+    bool     sample = false;
 
     switch (Action) {
         case HTC_EP_STAT_SAMPLE :
-            sample = TRUE;
+            sample = true;
             break;
         case HTC_EP_STAT_SAMPLE_AND_CLEAR :
-            sample = TRUE;
-            clearStats = TRUE;
+            sample = true;
+            clearStats = true;
             break;
         case HTC_EP_STAT_CLEAR :
-            clearStats = TRUE;
+            clearStats = true;
             break;
         default:
             break;
@@ -554,26 +556,26 @@
     if (sample) {
         A_ASSERT(pStats != NULL);
             /* return the stats to the caller */
-        A_MEMCPY(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
+        memcpy(pStats, &target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
     }
 
     if (clearStats) {
             /* reset stats */
-        A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(HTC_ENDPOINT_STATS));
+        A_MEMZERO(&target->EndPoint[Endpoint].EndPointStats, sizeof(struct htc_endpoint_stats));
     }
 
     UNLOCK_HTC_RX(target);
     UNLOCK_HTC_TX(target);
 
-    return TRUE;
+    return true;
 #else
-    return FALSE;
+    return false;
 #endif
 }
 
-AR6K_DEVICE  *HTCGetAR6KDevice(void *HTCHandle)
+struct ar6k_device  *HTCGetAR6KDevice(void *HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     return &target->Device;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_internal.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_internal.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -65,27 +65,27 @@
 
 #define HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE  (1 << 0)
 
-typedef struct _HTC_ENDPOINT {
+struct htc_endpoint {
     HTC_ENDPOINT_ID             Id;
     HTC_SERVICE_ID              ServiceID;      /* service ID this endpoint is bound to
                                                    non-zero value means this endpoint is in use */
-    HTC_PACKET_QUEUE            TxQueue;        /* HTC frame buffer TX queue */
-    HTC_PACKET_QUEUE            RxBuffers;      /* HTC frame buffer RX list */
-    HTC_ENDPOINT_CREDIT_DIST    CreditDist;     /* credit distribution structure (exposed to driver layer) */
-    HTC_EP_CALLBACKS            EpCallBacks;    /* callbacks associated with this endpoint */
+    struct htc_packet_queue            TxQueue;        /* HTC frame buffer TX queue */
+    struct htc_packet_queue            RxBuffers;      /* HTC frame buffer RX list */
+    struct htc_endpoint_credit_dist    CreditDist;     /* credit distribution structure (exposed to driver layer) */
+    struct htc_ep_callbacks            EpCallBacks;    /* callbacks associated with this endpoint */
     int                         MaxTxQueueDepth;   /* max depth of the TX queue before we need to
                                                       call driver's full handler */
     int                         MaxMsgLength;        /* max length of endpoint message */
     int                         TxProcessCount;  /* reference count to continue tx processing */
-    HTC_PACKET_QUEUE            RecvIndicationQueue;    /* recv packets ready to be indicated */
+    struct htc_packet_queue            RecvIndicationQueue;    /* recv packets ready to be indicated */
     int                         RxProcessCount;         /* reference count to allow single processing context */
-    struct  _HTC_TARGET         *target;                /* back pointer to target */
-    A_UINT8                     SeqNo;                  /* TX seq no (helpful) for debugging */
-    A_UINT32                    LocalConnectionFlags;   /* local connection flags */
+    struct htc_target           *target;                /* back pointer to target */
+    u8 SeqNo;                  /* TX seq no (helpful) for debugging */
+    u32 LocalConnectionFlags;   /* local connection flags */
 #ifdef HTC_EP_STAT_PROFILING
-    HTC_ENDPOINT_STATS          EndPointStats;          /* endpoint statistics */
+    struct htc_endpoint_stats          EndPointStats;          /* endpoint statistics */
 #endif
-} HTC_ENDPOINT;
+};
 
 #ifdef HTC_EP_STAT_PROFILING
 #define INC_HTC_EP_STAT(p,stat,count) (p)->EndPointStats.stat += (count);
@@ -99,21 +99,21 @@
 #define NUM_CONTROL_TX_BUFFERS  2
 #define NUM_CONTROL_RX_BUFFERS  (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
 
-typedef struct HTC_CONTROL_BUFFER {
-    HTC_PACKET    HtcPacket;
-    A_UINT8       *Buffer;
-} HTC_CONTROL_BUFFER;
+struct htc_control_buffer {
+    struct htc_packet    HtcPacket;
+    u8 *Buffer;
+};
 
 #define HTC_RECV_WAIT_BUFFERS        (1 << 0)
 #define HTC_OP_STATE_STOPPING        (1 << 0)
 
 /* our HTC target state */
-typedef struct _HTC_TARGET {
-    HTC_ENDPOINT                EndPoint[ENDPOINT_MAX];
-    HTC_CONTROL_BUFFER          HTCControlBuffers[NUM_CONTROL_BUFFERS];
-    HTC_ENDPOINT_CREDIT_DIST   *EpCreditDistributionListHead;
-    HTC_PACKET_QUEUE            ControlBufferTXFreeList;
-    HTC_PACKET_QUEUE            ControlBufferRXFreeList;
+struct htc_target {
+    struct htc_endpoint                EndPoint[ENDPOINT_MAX];
+    struct htc_control_buffer          HTCControlBuffers[NUM_CONTROL_BUFFERS];
+    struct htc_endpoint_credit_dist   *EpCreditDistributionListHead;
+    struct htc_packet_queue            ControlBufferTXFreeList;
+    struct htc_packet_queue            ControlBufferRXFreeList;
     HTC_CREDIT_DIST_CALLBACK    DistributeCredits;
     HTC_CREDIT_INIT_CALLBACK    InitCredits;
     void                       *pCredDistContext;
@@ -122,22 +122,22 @@
     A_MUTEX_T                   HTCLock;
     A_MUTEX_T                   HTCRxLock;
     A_MUTEX_T                   HTCTxLock;
-    AR6K_DEVICE                 Device;         /* AR6K - specific state */
-    A_UINT32                    OpStateFlags;
-    A_UINT32                    RecvStateFlags;
+    struct ar6k_device                 Device;         /* AR6K - specific state */
+    u32 OpStateFlags;
+    u32 RecvStateFlags;
     HTC_ENDPOINT_ID             EpWaitingForBuffers;
-    A_BOOL                      TargetFailure;
+    bool                      TargetFailure;
 #ifdef HTC_CAPTURE_LAST_FRAME
-    HTC_FRAME_HDR               LastFrameHdr;  /* useful for debugging */
-    A_UINT8                     LastTrailer[256];
-    A_UINT8                     LastTrailerLength;
+    struct htc_frame_hdr               LastFrameHdr;  /* useful for debugging */
+    u8 LastTrailer[256];
+    u8 LastTrailerLength;
 #endif
-    HTC_INIT_INFO               HTCInitInfo;
-    A_UINT8                     HTCTargetVersion;
+    struct htc_init_info               HTCInitInfo;
+    u8 HTCTargetVersion;
     int                         MaxMsgPerBundle;       /* max messages per bundle for HTC */
-    A_BOOL                      SendBundlingEnabled;   /* run time enable for send bundling (dynamic) */
+    bool                      SendBundlingEnabled;   /* run time enable for send bundling (dynamic) */
     int                         RecvBundlingEnabled;   /* run time enable for recv bundling (dynamic) */
-} HTC_TARGET;
+};
 
 #define HTC_STOPPING(t) ((t)->OpStateFlags & HTC_OP_STATE_STOPPING)
 #define LOCK_HTC(t)      A_MUTEX_LOCK(&(t)->HTCLock);
@@ -147,7 +147,7 @@
 #define LOCK_HTC_TX(t)   A_MUTEX_LOCK(&(t)->HTCTxLock);
 #define UNLOCK_HTC_TX(t) A_MUTEX_UNLOCK(&(t)->HTCTxLock);
 
-#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((HTC_TARGET *)(hnd))
+#define GET_HTC_TARGET_FROM_HANDLE(hnd) ((struct htc_target *)(hnd))
 #define HTC_RECYCLE_RX_PKT(target,p,e)                           \
 {                                                                \
     if ((p)->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_NO_RECYCLE) {  \
@@ -162,27 +162,27 @@
 }
 
 /* internal HTC functions */
-void        HTCControlTxComplete(void *Context, HTC_PACKET *pPacket);
-void        HTCControlRecv(void *Context, HTC_PACKET *pPacket);
-A_STATUS    HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket);
-HTC_PACKET *HTCAllocControlBuffer(HTC_TARGET *target, HTC_PACKET_QUEUE *pList);
-void        HTCFreeControlBuffer(HTC_TARGET *target, HTC_PACKET *pPacket, HTC_PACKET_QUEUE *pList);
-A_STATUS    HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket);
-void        HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket);
-A_STATUS    HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], int NumLookAheads, A_BOOL *pAsyncProc, int *pNumPktsFetched);
-void        HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
-A_STATUS    HTCSendSetupComplete(HTC_TARGET *target);
-void        HTCFlushRecvBuffers(HTC_TARGET *target);
-void        HTCFlushSendPkts(HTC_TARGET *target);
+void        HTCControlTxComplete(void *Context, struct htc_packet *pPacket);
+void        HTCControlRecv(void *Context, struct htc_packet *pPacket);
+int    HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket);
+struct htc_packet *HTCAllocControlBuffer(struct htc_target *target, struct htc_packet_queue *pList);
+void        HTCFreeControlBuffer(struct htc_target *target, struct htc_packet *pPacket, struct htc_packet_queue *pList);
+int    HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket);
+void        HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket);
+int    HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched);
+void        HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint);
+int    HTCSendSetupComplete(struct htc_target *target);
+void        HTCFlushRecvBuffers(struct htc_target *target);
+void        HTCFlushSendPkts(struct htc_target *target);
 
 #ifdef ATH_DEBUG_MODULE
-void        DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist);
-void        DumpCreditDistStates(HTC_TARGET *target);
-void 		DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
+void        DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist);
+void        DumpCreditDistStates(struct htc_target *target);
+void 		DebugDumpBytes(u8 *buffer, u16 length, char *pDescription);
 #endif
 
-static INLINE HTC_PACKET *HTC_ALLOC_CONTROL_TX(HTC_TARGET *target) {
-    HTC_PACKET *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
+static INLINE struct htc_packet *HTC_ALLOC_CONTROL_TX(struct htc_target *target) {
+    struct htc_packet *pPacket = HTCAllocControlBuffer(target,&target->ControlBufferTXFreeList);
     if (pPacket != NULL) {
             /* set payload pointer area with some headroom */
         pPacket->pBuffer = pPacket->pBufferStart + HTC_HDR_LENGTH;
@@ -200,14 +200,14 @@
 
 #define HTC_PREPARE_SEND_PKT(pP,sendflags,ctrl0,ctrl1)       \
 {                                                   \
-    A_UINT8 *pHdrBuf;                               \
+    u8 *pHdrBuf;                               \
     (pP)->pBuffer -= HTC_HDR_LENGTH;                \
     pHdrBuf = (pP)->pBuffer;                        \
-    A_SET_UINT16_FIELD(pHdrBuf,HTC_FRAME_HDR,PayloadLen,(A_UINT16)(pP)->ActualLength);  \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,Flags,(sendflags));                         \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,EndpointID, (A_UINT8)(pP)->Endpoint); \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,ControlBytes[0], (A_UINT8)(ctrl0));   \
-    A_SET_UINT8_FIELD(pHdrBuf,HTC_FRAME_HDR,ControlBytes[1], (A_UINT8)(ctrl1));   \
+    A_SET_UINT16_FIELD(pHdrBuf,struct htc_frame_hdr,PayloadLen,(u16)(pP)->ActualLength);  \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,Flags,(sendflags));                         \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,EndpointID, (u8)(pP)->Endpoint); \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[0], (u8)(ctrl0));   \
+    A_SET_UINT8_FIELD(pHdrBuf,struct htc_frame_hdr,ControlBytes[1], (u8)(ctrl1));   \
 }
 
 #define HTC_UNPREPARE_SEND_PKT(pP)     \
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_recv.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_recv.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_recv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_recv.c	2011-05-19 00:06:34.000000000 -0400
@@ -50,8 +50,8 @@
 #define HTC_RX_STAT_PROFILE(t,ep,lookAhead)
 #endif
 
-static void DoRecvCompletion(HTC_ENDPOINT     *pEndpoint,
-                             HTC_PACKET_QUEUE *pQueueToIndicate)
+static void DoRecvCompletion(struct htc_endpoint     *pEndpoint,
+                             struct htc_packet_queue *pQueueToIndicate)
 {           
     
     do {
@@ -69,7 +69,7 @@
                                                      pQueueToIndicate);
             INIT_HTC_PACKET_QUEUE(pQueueToIndicate);        
         } else {
-            HTC_PACKET *pPacket;  
+            struct htc_packet *pPacket;  
             /* using legacy EpRecv */         
             do {
                 pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
@@ -79,23 +79,23 @@
             } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));                                              
         }
         
-    } while (FALSE);
+    } while (false);
 
 }
 
-static INLINE A_STATUS HTCProcessTrailer(HTC_TARGET *target,
-                                         A_UINT8    *pBuffer,
+static INLINE int HTCProcessTrailer(struct htc_target *target,
+                                         u8 *pBuffer,
                                          int         Length,
-                                         A_UINT32   *pNextLookAheads,
+                                         u32 *pNextLookAheads,
                                          int        *pNumLookAheads,
                                          HTC_ENDPOINT_ID FromEndpoint)
 {
     HTC_RECORD_HDR          *pRecord;
-    A_UINT8                 *pRecordBuf;
+    u8 *pRecordBuf;
     HTC_LOOKAHEAD_REPORT    *pLookAhead;
-    A_UINT8                 *pOrigBuffer;
+    u8 *pOrigBuffer;
     int                     origLength;
-    A_STATUS                status;
+    int                status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCProcessTrailer (length:%d) \n", Length));
 
@@ -105,7 +105,7 @@
 
     pOrigBuffer = pBuffer;
     origLength = Length;
-    status = A_OK;
+    status = 0;
     
     while (Length > 0) {
 
@@ -149,14 +149,14 @@
                                 pLookAhead->PostValid));
 
                         /* look ahead bytes are valid, copy them over */
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
-                    ((A_UINT8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
+                    ((u8 *)(&pNextLookAheads[0]))[0] = pLookAhead->LookAhead[0];
+                    ((u8 *)(&pNextLookAheads[0]))[1] = pLookAhead->LookAhead[1];
+                    ((u8 *)(&pNextLookAheads[0]))[2] = pLookAhead->LookAhead[2];
+                    ((u8 *)(&pNextLookAheads[0]))[3] = pLookAhead->LookAhead[3];
 
 #ifdef ATH_DEBUG_MODULE
                     if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
-                        DebugDumpBytes((A_UINT8 *)pNextLookAheads,4,"Next Look Ahead");
+                        DebugDumpBytes((u8 *)pNextLookAheads,4,"Next Look Ahead");
                     }
 #endif
                         /* just one normal lookahead */
@@ -182,16 +182,16 @@
                             HTC_HOST_MAX_MSG_PER_BUNDLE) {
                             /* this should never happen, the target restricts the number
                              * of messages per bundle configured by the host */        
-                        A_ASSERT(FALSE);
+                        A_ASSERT(false);
                         status = A_EPROTO;
                         break;        
                     }
                                          
                     for (i = 0; i < (int)(pRecord->Length / (sizeof(HTC_BUNDLED_LOOKAHEAD_REPORT))); i++) {
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
-                        ((A_UINT8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
+                        ((u8 *)(&pNextLookAheads[i]))[0] = pBundledLookAheadRpt->LookAhead[0];
+                        ((u8 *)(&pNextLookAheads[i]))[1] = pBundledLookAheadRpt->LookAhead[1];
+                        ((u8 *)(&pNextLookAheads[i]))[2] = pBundledLookAheadRpt->LookAhead[2];
+                        ((u8 *)(&pNextLookAheads[i]))[3] = pBundledLookAheadRpt->LookAhead[3];
                         pBundledLookAheadRpt++;
                     }
                     
@@ -204,7 +204,7 @@
                 break;
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -214,7 +214,7 @@
     }
 
 #ifdef ATH_DEBUG_MODULE
-    if (A_FAILED(status)) {
+    if (status) {
         DebugDumpBytes(pOrigBuffer,origLength,"BAD Recv Trailer");
     }
 #endif
@@ -226,16 +226,16 @@
 
 /* process a received message (i.e. strip off header, process any trailer data)
  * note : locks must be released when this function is called */
-static A_STATUS HTCProcessRecvHeader(HTC_TARGET *target, 
-                                     HTC_PACKET *pPacket, 
-                                     A_UINT32   *pNextLookAheads, 
+static int HTCProcessRecvHeader(struct htc_target *target,
+                                     struct htc_packet *pPacket, 
+                                     u32 *pNextLookAheads,
                                      int        *pNumLookAheads)
 {
-    A_UINT8   temp;
-    A_UINT8   *pBuf;
-    A_STATUS  status = A_OK;
-    A_UINT16  payloadLen;
-    A_UINT32  lookAhead;
+    u8 temp;
+    u8 *pBuf;
+    int  status = 0;
+    u16 payloadLen;
+    u32 lookAhead;
 
     pBuf = pPacket->pBuffer;
     
@@ -252,12 +252,12 @@
     do {
         /* note, we cannot assume the alignment of pBuffer, so we use the safe macros to
          * retrieve 16 bit fields */
-        payloadLen = A_GET_UINT16_FIELD(pBuf, HTC_FRAME_HDR, PayloadLen);
+        payloadLen = A_GET_UINT16_FIELD(pBuf, struct htc_frame_hdr, PayloadLen);
         
-        ((A_UINT8 *)&lookAhead)[0] = pBuf[0];
-        ((A_UINT8 *)&lookAhead)[1] = pBuf[1];
-        ((A_UINT8 *)&lookAhead)[2] = pBuf[2];
-        ((A_UINT8 *)&lookAhead)[3] = pBuf[3];
+        ((u8 *)&lookAhead)[0] = pBuf[0];
+        ((u8 *)&lookAhead)[1] = pBuf[1];
+        ((u8 *)&lookAhead)[2] = pBuf[2];
+        ((u8 *)&lookAhead)[3] = pBuf[3];
 
         if (pPacket->PktInfo.AsRx.HTCRxFlags & HTC_RX_PKT_REFRESH_HDR) {
                 /* refresh expected hdr, since this was unknown at the time we grabbed the packets
@@ -277,10 +277,10 @@
                 break;    
             }
             
-            if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, EndpointID)) {
+            if (pPacket->Endpoint != A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID)) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     ("Refreshed HDR endpoint (%d) does not match expected endpoint (%d) \n", 
-                    A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, EndpointID), pPacket->Endpoint));
+                    A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, EndpointID), pPacket->Endpoint));
                 status = A_EPROTO;
                 break;      
             }   
@@ -293,10 +293,10 @@
                     ("HTCProcessRecvHeader, lookahead mismatch! (pPkt:0x%lX flags:0x%X) \n", 
                         (unsigned long)pPacket, pPacket->PktInfo.AsRx.HTCRxFlags));
 #ifdef ATH_DEBUG_MODULE
-             DebugDumpBytes((A_UINT8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
-             DebugDumpBytes(pBuf,sizeof(HTC_FRAME_HDR),"Current Frame Header");
+             DebugDumpBytes((u8 *)&pPacket->PktInfo.AsRx.ExpectedHdr,4,"Expected Message LookAhead");
+             DebugDumpBytes(pBuf,sizeof(struct htc_frame_hdr),"Current Frame Header");
 #ifdef HTC_CAPTURE_LAST_FRAME
-            DebugDumpBytes((A_UINT8 *)&target->LastFrameHdr,sizeof(HTC_FRAME_HDR),"Last Frame Header");
+            DebugDumpBytes((u8 *)&target->LastFrameHdr,sizeof(struct htc_frame_hdr),"Last Frame Header");
             if (target->LastTrailerLength != 0) {
                 DebugDumpBytes(target->LastTrailer,
                                target->LastTrailerLength,
@@ -309,13 +309,13 @@
         }
 
             /* get flags */
-        temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, Flags);
+        temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, Flags);
 
         if (temp & HTC_FLAGS_RECV_TRAILER) {
             /* this packet has a trailer */
 
                 /* extract the trailer length in control byte 0 */
-            temp = A_GET_UINT8_FIELD(pBuf, HTC_FRAME_HDR, ControlBytes[0]);
+            temp = A_GET_UINT8_FIELD(pBuf, struct htc_frame_hdr, ControlBytes[0]);
 
             if ((temp < sizeof(HTC_RECORD_HDR)) || (temp > payloadLen)) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
@@ -341,12 +341,12 @@
                                        pNumLookAheads,
                                        pPacket->Endpoint);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
 #ifdef HTC_CAPTURE_LAST_FRAME
-            A_MEMCPY(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
+            memcpy(target->LastTrailer, (pBuf + HTC_HDR_LENGTH + payloadLen - temp), temp);
             target->LastTrailerLength = temp;
 #endif
                 /* trim length by trailer bytes */
@@ -363,16 +363,16 @@
         pPacket->pBuffer += HTC_HDR_LENGTH;
         pPacket->ActualLength -= HTC_HDR_LENGTH;
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
             /* dump the whole packet */
 #ifdef ATH_DEBUG_MODULE
         DebugDumpBytes(pBuf,pPacket->ActualLength < 256 ? pPacket->ActualLength : 256 ,"BAD HTC Recv PKT");
 #endif
     } else {
 #ifdef HTC_CAPTURE_LAST_FRAME
-        A_MEMCPY(&target->LastFrameHdr,pBuf,sizeof(HTC_FRAME_HDR));
+        memcpy(&target->LastFrameHdr,pBuf,sizeof(struct htc_frame_hdr));
 #endif
         if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_RECV)) {
             if (pPacket->ActualLength > 0) {
@@ -385,14 +385,14 @@
     return status;
 }
 
-static INLINE void HTCAsyncRecvCheckMorePackets(HTC_TARGET  *target, 
-                                                A_UINT32    NextLookAheads[], 
+static INLINE void HTCAsyncRecvCheckMorePackets(struct htc_target  *target, 
+                                                u32 NextLookAheads[],
                                                 int         NumLookAheads,
-                                                A_BOOL      CheckMoreMsgs)
+                                                bool      CheckMoreMsgs)
 {
         /* was there a lookahead for the next packet? */
     if (NumLookAheads > 0) {
-        A_STATUS nextStatus;
+        int nextStatus;
         int      fetched = 0;
         AR_DEBUG_PRINTF(ATH_DEBUG_RECV,
                         ("HTCAsyncRecvCheckMorePackets - num lookaheads were non-zero : %d \n",
@@ -405,12 +405,12 @@
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Next look ahead from recv header was INVALID\n"));
 #ifdef ATH_DEBUG_MODULE
-            DebugDumpBytes((A_UINT8 *)NextLookAheads,
-                            NumLookAheads * (sizeof(A_UINT32)),
+            DebugDumpBytes((u8 *)NextLookAheads,
+                            NumLookAheads * (sizeof(u32)),
                             "BAD lookaheads from lookahead report");
 #endif
         }
-        if (A_SUCCESS(nextStatus) && !fetched) {
+        if (!nextStatus && !fetched) {
                 /* we could not fetch any more packets due to resources */
             DevAsyncIrqProcessComplete(&target->Device);        
         }
@@ -432,9 +432,9 @@
 }      
 
     /* unload the recv completion queue */
-static INLINE void DrainRecvIndicationQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
+static INLINE void DrainRecvIndicationQueue(struct htc_target *target, struct htc_endpoint *pEndpoint)
 {
-    HTC_PACKET_QUEUE     recvCompletions;
+    struct htc_packet_queue     recvCompletions;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+DrainRecvIndicationQueue \n"));
                 
@@ -454,7 +454,7 @@
     
     /******* at this point only 1 thread may enter ******/
      
-    while (TRUE) { 
+    while (true) {
                 
             /* transfer items from main recv queue to the local one so we can release the lock */ 
         HTC_PACKET_QUEUE_TRANSFER_TO_TAIL(&recvCompletions, &pEndpoint->RecvIndicationQueue);
@@ -496,11 +496,11 @@
     (P)->PktInfo.AsRx.IndicationFlags |= HTC_RX_FLAGS_INDICATE_MORE_PKTS; 
    
    /* note: this function can be called with the RX lock held */     
-static INLINE void SetRxPacketIndicationFlags(A_UINT32      LookAhead, 
-                                              HTC_ENDPOINT  *pEndpoint, 
-                                              HTC_PACKET    *pPacket)
+static INLINE void SetRxPacketIndicationFlags(u32 LookAhead,
+                                              struct htc_endpoint  *pEndpoint, 
+                                              struct htc_packet    *pPacket)
 {
-    HTC_FRAME_HDR *pHdr = (HTC_FRAME_HDR *)&LookAhead;
+    struct htc_frame_hdr *pHdr = (struct htc_frame_hdr *)&LookAhead;
         /* check to see if the "next" packet is from the same endpoint of the
            completing packet */
     if (pHdr->EndpointID == pPacket->Endpoint) {
@@ -515,14 +515,14 @@
      
 /* asynchronous completion handler for recv packet fetching, when the device layer
  * completes a read request, it will call this completion handler */
-void HTCRecvCompleteHandler(void *Context, HTC_PACKET *pPacket)
+void HTCRecvCompleteHandler(void *Context, struct htc_packet *pPacket)
 {
-    HTC_TARGET      *target = (HTC_TARGET *)Context;
-    HTC_ENDPOINT    *pEndpoint;
-    A_UINT32        nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+    struct htc_target      *target = (struct htc_target *)Context;
+    struct htc_endpoint    *pEndpoint;
+    u32 nextLookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
     int             numLookAheads = 0;
-    A_STATUS        status;
-    A_BOOL          checkMorePkts = TRUE;
+    int        status;
+    bool          checkMorePkts = true;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV, ("+HTCRecvCompleteHandler (pkt:0x%lX, status:%d, ep:%d) \n",
                 (unsigned long)pPacket, pPacket->Status, pPacket->Endpoint));
@@ -537,7 +537,7 @@
 
     do {
         
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HTCRecvCompleteHandler: request failed (status:%d, ep:%d) \n",
                 pPacket->Status, pPacket->Endpoint));
             break;
@@ -545,7 +545,7 @@
             /* process the header for any trailer data */
         status = HTCProcessRecvHeader(target,pPacket,nextLookAheads,&numLookAheads);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
         
@@ -554,7 +554,7 @@
                  * It was fetched one message at a time.  There may be other asynchronous reads queued behind this one.
                  * Do no issue another check for more packets since the last one in the series of requests
                  * will handle it */
-            checkMorePkts = FALSE;    
+            checkMorePkts = false;
         }
           
         DUMP_RECV_PKT_INFO(pPacket);    
@@ -568,9 +568,9 @@
             /* check for more recv packets before indicating */
         HTCAsyncRecvCheckMorePackets(target,nextLookAheads,numLookAheads,checkMorePkts);
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
          AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                          ("HTCRecvCompleteHandler , message fetch failed (status = %d) \n",
                          status));
@@ -587,12 +587,12 @@
 /* synchronously wait for a control message from the target,
  * This function is used at initialization time ONLY.  At init messages
  * on ENDPOINT 0 are expected. */
-A_STATUS HTCWaitforControlMessage(HTC_TARGET *target, HTC_PACKET **ppControlPacket)
+int HTCWaitforControlMessage(struct htc_target *target, struct htc_packet **ppControlPacket)
 {
-    A_STATUS        status;
-    A_UINT32        lookAhead;
-    HTC_PACKET      *pPacket = NULL;
-    HTC_FRAME_HDR   *pHdr;
+    int        status;
+    u32 lookAhead;
+    struct htc_packet      *pPacket = NULL;
+    struct htc_frame_hdr   *pHdr;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCWaitforControlMessage \n"));
 
@@ -605,7 +605,7 @@
                                     &lookAhead,
                                     HTC_TARGET_RESPONSE_TIMEOUT);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -613,18 +613,18 @@
                 ("HTCWaitforControlMessage : lookAhead : 0x%X \n", lookAhead));
 
             /* check the lookahead */
-        pHdr = (HTC_FRAME_HDR *)&lookAhead;
+        pHdr = (struct htc_frame_hdr *)&lookAhead;
 
         if (pHdr->EndpointID != ENDPOINT_0) {
                 /* unexpected endpoint number, should be zero */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
                 /* bad message */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -632,7 +632,7 @@
         pPacket = HTC_ALLOC_CONTROL_RX(target);
 
         if (pPacket == NULL) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_NO_MEMORY;
             break;
         }
@@ -642,7 +642,7 @@
         pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
 
         if (pPacket->ActualLength > pPacket->BufferLength) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             status = A_EPROTO;
             break;
         }
@@ -653,7 +653,7 @@
             /* get the message from the device, this will block */
         status = HTCIssueRecv(target, pPacket);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -662,7 +662,7 @@
 
         pPacket->Status = status;
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     ("HTCWaitforControlMessage, HTCProcessRecvHeader failed (status = %d) \n",
                      status));
@@ -672,9 +672,9 @@
             /* give the caller this control message packet, they are responsible to free */
         *ppControlPacket = pPacket;
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         if (pPacket != NULL) {
                 /* cleanup buffer on error */
             HTC_FREE_CONTROL_RX(target,pPacket);
@@ -686,26 +686,26 @@
     return status;
 }
 
-static A_STATUS AllocAndPrepareRxPackets(HTC_TARGET       *target, 
-                                         A_UINT32         LookAheads[], 
+static int AllocAndPrepareRxPackets(struct htc_target       *target,
+                                         u32 LookAheads[],
                                          int              Messages,                                        
-                                         HTC_ENDPOINT     *pEndpoint, 
-                                         HTC_PACKET_QUEUE *pQueue)
+                                         struct htc_endpoint     *pEndpoint, 
+                                         struct htc_packet_queue *pQueue)
 {
-    A_STATUS         status = A_OK;
-    HTC_PACKET      *pPacket;
-    HTC_FRAME_HDR   *pHdr;
+    int         status = 0;
+    struct htc_packet      *pPacket;
+    struct htc_frame_hdr   *pHdr;
     int              i,j;
     int              numMessages;
     int              fullLength;
-    A_BOOL           noRecycle;
+    bool           noRecycle;
             
         /* lock RX while we assemble the packet buffers */
     LOCK_HTC_RX(target);
                         
     for (i = 0; i < Messages; i++) {   
          
-        pHdr = (HTC_FRAME_HDR *)&LookAheads[i];
+        pHdr = (struct htc_frame_hdr *)&LookAheads[i];
 
         if (pHdr->EndpointID >= ENDPOINT_MAX) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Endpoint in look-ahead: %d \n",pHdr->EndpointID));
@@ -724,7 +724,7 @@
        
         if (pHdr->PayloadLen > HTC_MAX_PAYLOAD_LENGTH) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Payload length %d exceeds max HTC : %d !\n",
-                    pHdr->PayloadLen, (A_UINT32)HTC_MAX_PAYLOAD_LENGTH));
+                    pHdr->PayloadLen, (u32)HTC_MAX_PAYLOAD_LENGTH));
             status = A_EPROTO;
             break;
         }
@@ -751,7 +751,7 @@
                 ("HTC header indicates :%d messages can be fetched as a bundle \n",numMessages));           
         }
      
-        fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(HTC_FRAME_HDR));
+        fullLength = DEV_CALC_RECV_PADDED_LEN(&target->Device,pHdr->PayloadLen + sizeof(struct htc_frame_hdr));
             
             /* get packet buffers for each message, if there was a bundle detected in the header,
              * use pHdr as a template to fetch all packets in the bundle */        
@@ -759,11 +759,11 @@
             
                 /* reset flag, any packets allocated using the RecvAlloc() API cannot be recycled on cleanup,
                  * they must be explicitly returned */
-            noRecycle = FALSE;
+            noRecycle = false;
                                                                                    
             if (pEndpoint->EpCallBacks.EpRecvAlloc != NULL) {
                 UNLOCK_HTC_RX(target);
-                noRecycle = TRUE;
+                noRecycle = true;
                     /* user is using a per-packet allocation callback */
                 pPacket = pEndpoint->EpCallBacks.EpRecvAlloc(pEndpoint->EpCallBacks.pContext,
                                                              pEndpoint->Id,
@@ -776,7 +776,7 @@
                 INC_HTC_EP_STAT(pEndpoint,RxAllocThreshBytes,pHdr->PayloadLen);                
                     /* threshold was hit, call the special recv allocation callback */        
                 UNLOCK_HTC_RX(target);
-                noRecycle = TRUE;
+                noRecycle = true;
                     /* user wants to allocate packets above a certain threshold */
                 pPacket = pEndpoint->EpCallBacks.EpRecvAllocThresh(pEndpoint->EpCallBacks.pContext,
                                                                    pEndpoint->Id,
@@ -816,7 +816,7 @@
                 /* clear flags */
             pPacket->PktInfo.AsRx.HTCRxFlags = 0;
             pPacket->PktInfo.AsRx.IndicationFlags = 0;
-            pPacket->Status = A_OK;
+            pPacket->Status = 0;
             
             if (noRecycle) {
                     /* flag that these packets cannot be recycled, they have to be returned to the 
@@ -832,7 +832,7 @@
             }
     
                 /* make sure this message can fit in the endpoint buffer */
-            if ((A_UINT32)fullLength > pPacket->BufferLength) {
+            if ((u32)fullLength > pPacket->BufferLength) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Payload Length Error : header reports payload of: %d (%d) endpoint buffer size: %d \n",
                         pHdr->PayloadLen, fullLength, pPacket->BufferLength));
@@ -856,10 +856,10 @@
             pPacket->ActualLength = pHdr->PayloadLen + HTC_HDR_LENGTH;
         }
         
-        if (A_FAILED(status)) {
+        if (status) {
             if (A_NO_RESOURCE == status) {
                     /* this is actually okay */
-                status = A_OK;    
+                status = 0;
             }
             break;    
         }
@@ -868,7 +868,7 @@
     
     UNLOCK_HTC_RX(target);
     
-    if (A_FAILED(status)) {
+    if (status) {
         while (!HTC_QUEUE_EMPTY(pQueue)) {
             pPacket = HTC_PACKET_DEQUEUE(pQueue);
                 /* recycle all allocated packets */
@@ -879,37 +879,37 @@
     return status; 
 }
 
-static void HTCAsyncRecvScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
+static void HTCAsyncRecvScatterCompletion(struct hif_scatter_req *pScatterReq)
 {
     int                 i;    
-    HTC_PACKET          *pPacket;
-    HTC_ENDPOINT        *pEndpoint;
-    A_UINT32            lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+    struct htc_packet          *pPacket;
+    struct htc_endpoint        *pEndpoint;
+    u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
     int                 numLookAheads = 0;
-    HTC_TARGET          *target = (HTC_TARGET *)pScatterReq->Context;
-    A_STATUS            status;
-    A_BOOL              partialBundle = FALSE;
-    HTC_PACKET_QUEUE    localRecvQueue;
-    A_BOOL              procError = FALSE;
+    struct htc_target          *target = (struct htc_target *)pScatterReq->Context;
+    int            status;
+    bool              partialBundle = false;
+    struct htc_packet_queue    localRecvQueue;
+    bool              procError = false;
            
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("+HTCAsyncRecvScatterCompletion  TotLen: %d  Entries: %d\n",
         pScatterReq->TotalLength, pScatterReq->ValidScatterEntries));
     
     A_ASSERT(!IS_DEV_IRQ_PROC_SYNC_MODE(&target->Device));
            
-    if (A_FAILED(pScatterReq->CompletionStatus)) {
+    if (pScatterReq->CompletionStatus) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Recv Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));            
     }
     
     if (pScatterReq->CallerFlags & HTC_SCATTER_REQ_FLAGS_PARTIAL_BUNDLE) {
-        partialBundle = TRUE;    
+        partialBundle = true;
     }
     
     DEV_FINISH_SCATTER_OPERATION(pScatterReq);
     
     INIT_HTC_PACKET_QUEUE(&localRecvQueue);
         
-    pPacket = (HTC_PACKET *)pScatterReq->ScatterList[0].pCallerContexts[0];
+    pPacket = (struct htc_packet *)pScatterReq->ScatterList[0].pCallerContexts[0];
         /* note: all packets in a scatter req are for the same endpoint ! */
     pEndpoint = &target->EndPoint[pPacket->Endpoint];
          
@@ -917,20 +917,20 @@
         /* **** NOTE: DO NOT HOLD ANY LOCKS here, HTCProcessRecvHeader can take the TX lock
          * as it processes credit reports */
     for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
-        pPacket = (HTC_PACKET *)pScatterReq->ScatterList[i].pCallerContexts[0];
+        pPacket = (struct htc_packet *)pScatterReq->ScatterList[i].pCallerContexts[0];
         A_ASSERT(pPacket != NULL);       
             /* reset count, we are only interested in the look ahead in the last packet when we
              * break out of this loop */
         numLookAheads = 0;
         
-        if (A_SUCCESS(pScatterReq->CompletionStatus)) {      
+        if (!pScatterReq->CompletionStatus) {
                 /* process header for each of the recv packets */            
             status = HTCProcessRecvHeader(target,pPacket,lookAheads,&numLookAheads);
         } else {
             status = A_ERROR;    
         }
         
-        if (A_SUCCESS(status)) {    
+        if (!status) {
 #ifdef HTC_EP_STAT_PROFILING
             LOCK_HTC_RX(target);              
             HTC_RX_STAT_PROFILE(target,pEndpoint,numLookAheads);
@@ -956,7 +956,7 @@
                 /* recycle failed recv */
             HTC_RECYCLE_RX_PKT(target, pPacket, pEndpoint);
                 /* set flag and continue processing the remaining scatter entries */
-            procError = TRUE;
+            procError = true;
         }   
     
     }
@@ -975,7 +975,7 @@
         HTCAsyncRecvCheckMorePackets(target,
                                      lookAheads,
                                      numLookAheads,
-                                     partialBundle ? FALSE : TRUE);
+                                     partialBundle ? false : true);
     }
     
         /* now drain the indication queue */
@@ -984,18 +984,18 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCAsyncRecvScatterCompletion \n"));
 }
 
-static A_STATUS HTCIssueRecvPacketBundle(HTC_TARGET        *target,
-                                         HTC_PACKET_QUEUE  *pRecvPktQueue, 
-                                         HTC_PACKET_QUEUE  *pSyncCompletionQueue,
+static int HTCIssueRecvPacketBundle(struct htc_target        *target,
+                                         struct htc_packet_queue  *pRecvPktQueue, 
+                                         struct htc_packet_queue  *pSyncCompletionQueue,
                                          int               *pNumPacketsFetched,
-                                         A_BOOL             PartialBundle)
+                                         bool             PartialBundle)
 {
-    A_STATUS        status = A_OK;
-    HIF_SCATTER_REQ *pScatterReq;
+    int        status = 0;
+    struct hif_scatter_req *pScatterReq;
     int             i, totalLength;
     int             pktsToScatter;
-    HTC_PACKET      *pPacket;
-    A_BOOL          asyncMode = (pSyncCompletionQueue == NULL) ? TRUE : FALSE;
+    struct htc_packet      *pPacket;
+    bool          asyncMode = (pSyncCompletionQueue == NULL) ? true : false;
     int             scatterSpaceRemaining = DEV_GET_MAX_BUNDLE_RECV_LENGTH(&target->Device);
         
     pktsToScatter = HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue);
@@ -1004,7 +1004,7 @@
     if ((HTC_PACKET_QUEUE_DEPTH(pRecvPktQueue) - pktsToScatter) > 0) {
             /* we were forced to split this bundle receive operation
              * all packets in this partial bundle must have their lookaheads ignored */
-        PartialBundle = TRUE;
+        PartialBundle = true;
             /* this would only happen if the target ignored our max bundle limit */
         AR_DEBUG_PRINTF(ATH_DEBUG_WARN,
                          ("HTCIssueRecvPacketBundle : partial bundle detected num:%d , %d \n",
@@ -1085,7 +1085,7 @@
         
         status = DevSubmitScatterRequest(&target->Device, pScatterReq, DEV_SCATTER_READ, asyncMode);
         
-        if (A_SUCCESS(status)) {
+        if (!status) {
             *pNumPacketsFetched = i;    
         }
         
@@ -1094,7 +1094,7 @@
             DEV_FREE_SCATTER_REQ(&target->Device, pScatterReq);   
         }
         
-    } while (FALSE);
+    } while (false);
    
     AR_DEBUG_PRINTF(ATH_DEBUG_RECV,("-HTCIssueRecvPacketBundle (status:%d) (fetched:%d) \n",
             status,*pNumPacketsFetched));
@@ -1102,7 +1102,7 @@
     return status;
 }
 
-static INLINE void CheckRecvWaterMark(HTC_ENDPOINT    *pEndpoint)
+static INLINE void CheckRecvWaterMark(struct htc_endpoint    *pEndpoint)
 {  
         /* see if endpoint is using a refill watermark 
          * ** no need to use a lock here, since we are only inspecting...
@@ -1117,17 +1117,17 @@
 }
 
 /* callback when device layer or lookahead report parsing detects a pending message */
-A_STATUS HTCRecvMessagePendingHandler(void *Context, A_UINT32 MsgLookAheads[], int NumLookAheads, A_BOOL *pAsyncProc, int *pNumPktsFetched)
+int HTCRecvMessagePendingHandler(void *Context, u32 MsgLookAheads[], int NumLookAheads, bool *pAsyncProc, int *pNumPktsFetched)
 {
-    HTC_TARGET      *target = (HTC_TARGET *)Context;
-    A_STATUS         status = A_OK;
-    HTC_PACKET      *pPacket;
-    HTC_ENDPOINT    *pEndpoint;
-    A_BOOL          asyncProc = FALSE;
-    A_UINT32        lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
+    struct htc_target      *target = (struct htc_target *)Context;
+    int         status = 0;
+    struct htc_packet      *pPacket;
+    struct htc_endpoint    *pEndpoint;
+    bool          asyncProc = false;
+    u32 lookAheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
     int             pktsFetched;
-    HTC_PACKET_QUEUE recvPktQueue, syncCompletedPktsQueue;
-    A_BOOL          partialBundle;
+    struct htc_packet_queue recvPktQueue, syncCompletedPktsQueue;
+    bool          partialBundle;
     HTC_ENDPOINT_ID id;
     int             totalFetched = 0;
     
@@ -1141,7 +1141,7 @@
             /* We use async mode to get the packets if the device layer supports it.
              * The device layer interfaces with HIF in which HIF may have restrictions on
              * how interrupts are processed */
-        asyncProc = TRUE;
+        asyncProc = true;
     }
 
     if (pAsyncProc != NULL) {
@@ -1150,14 +1150,14 @@
     }
     
     if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return A_EPROTO; 
     }
         
         /* on first entry copy the lookaheads into our temp array for processing */
-    A_MEMCPY(lookAheads, MsgLookAheads, (sizeof(A_UINT32)) * NumLookAheads);  
+    memcpy(lookAheads, MsgLookAheads, (sizeof(u32)) * NumLookAheads);
             
-    while (TRUE) {
+    while (true) {
         
             /* reset packets queues */
         INIT_HTC_PACKET_QUEUE(&recvPktQueue);
@@ -1165,12 +1165,12 @@
         
         if (NumLookAheads > HTC_HOST_MAX_MSG_PER_BUNDLE) {
             status = A_EPROTO;
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;    
         }
    
             /* first lookahead sets the expected endpoint IDs for all packets in a bundle */
-        id = ((HTC_FRAME_HDR *)&lookAheads[0])->EndpointID;
+        id = ((struct htc_frame_hdr *)&lookAheads[0])->EndpointID;
         pEndpoint = &target->EndPoint[id];
         
         if (id >= ENDPOINT_MAX) {
@@ -1186,7 +1186,7 @@
                                           NumLookAheads,
                                           pEndpoint, 
                                           &recvPktQueue);        
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
  
@@ -1200,7 +1200,7 @@
             /* we've got packet buffers for all we can currently fetch, 
              * this count is not valid anymore  */
         NumLookAheads = 0;
-        partialBundle = FALSE;
+        partialBundle = false;
        
             /* now go fetch the list of HTC packets */
         while (!HTC_QUEUE_EMPTY(&recvPktQueue)) {   
@@ -1214,14 +1214,14 @@
                                                   asyncProc ? NULL : &syncCompletedPktsQueue,
                                                   &pktsFetched,
                                                   partialBundle);                                                   
-                if (A_FAILED(status)) {
+                if (status) {
                     break;
                 }
                 
                 if (HTC_PACKET_QUEUE_DEPTH(&recvPktQueue) != 0) {
                         /* we couldn't fetch all packets at one time, this creates a broken
                          * bundle  */
-                    partialBundle = TRUE;    
+                    partialBundle = true;
                 }                                                                     
             }
             
@@ -1248,7 +1248,7 @@
                                     
                     /* go fetch the packet */
                 status = HTCIssueRecv(target, pPacket);              
-                if (A_FAILED(status)) {
+                if (status) {
                     break;
                 }  
                                
@@ -1261,7 +1261,7 @@
             
         }
 
-        if (A_SUCCESS(status)) {  
+        if (!status) {
             CheckRecvWaterMark(pEndpoint);
         }
             
@@ -1283,7 +1283,7 @@
              
              /* unload sync completion queue */      
         while (!HTC_QUEUE_EMPTY(&syncCompletedPktsQueue)) {
-            HTC_PACKET_QUEUE    container;
+            struct htc_packet_queue    container;
            
             pPacket = HTC_PACKET_DEQUEUE(&syncCompletedPktsQueue);
             A_ASSERT(pPacket != NULL);
@@ -1295,7 +1295,7 @@
                 /* process header for each of the recv packets
                  * note: the lookahead of the last packet is useful for us to continue in this loop */            
             status = HTCProcessRecvHeader(target,pPacket,lookAheads,&NumLookAheads);
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
             
@@ -1317,7 +1317,7 @@
             DO_RCV_COMPLETION(pEndpoint,&container);
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
             
@@ -1346,7 +1346,7 @@
         REF_IRQ_STATUS_RECHECK(&target->Device);
     }
     
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("Failed to get pending recv messages (%d) \n",status));
             /* cleanup any packets we allocated but didn't use to actually fetch any packets */                        
@@ -1385,18 +1385,18 @@
     return status;
 }
 
-A_STATUS HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
+int HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint;
-    A_BOOL          unblockRecv = FALSE;
-    A_STATUS        status = A_OK;
-    HTC_PACKET      *pFirstPacket;
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint;
+    bool          unblockRecv = false;
+    int        status = 0;
+    struct htc_packet      *pFirstPacket;
 
     pFirstPacket = HTC_GET_PKT_AT_HEAD(pPktQueue);
     
     if (NULL == pFirstPacket) {
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return A_EINVAL;    
     }
     
@@ -1415,7 +1415,7 @@
         LOCK_HTC_RX(target);
 
         if (HTC_STOPPING(target)) {
-            HTC_PACKET *pPacket;
+            struct htc_packet *pPacket;
             
             UNLOCK_HTC_RX(target);
             
@@ -1438,7 +1438,7 @@
                     target->EpWaitingForBuffers));
                 target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
                 target->EpWaitingForBuffers = ENDPOINT_MAX;
-                unblockRecv = TRUE;
+                unblockRecv = true;
             }
         }
 
@@ -1449,23 +1449,23 @@
             DevEnableRecv(&target->Device,DEV_ENABLE_RECV_SYNC);
         }
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
 /* Makes a buffer available to the HTC module */
-A_STATUS HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
+int HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
 {
-    HTC_PACKET_QUEUE queue;
+    struct htc_packet_queue queue;
     INIT_HTC_PACKET_QUEUE_AND_ADD(&queue,pPacket); 
     return HTCAddReceivePktMultiple(HTCHandle, &queue);       
 }
 
 void HTCUnblockRecv(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_BOOL      unblockRecv = FALSE;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    bool      unblockRecv = false;
 
     LOCK_HTC_RX(target);
 
@@ -1475,7 +1475,7 @@
             target->EpWaitingForBuffers));
         target->RecvStateFlags &= ~HTC_RECV_WAIT_BUFFERS;
         target->EpWaitingForBuffers = ENDPOINT_MAX;
-        unblockRecv = TRUE;
+        unblockRecv = true;
     }
 
     UNLOCK_HTC_RX(target);
@@ -1486,10 +1486,10 @@
     }
 }
 
-static void HTCFlushRxQueue(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET_QUEUE *pQueue)
+static void HTCFlushRxQueue(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet_queue *pQueue)
 {
-    HTC_PACKET  *pPacket;
-    HTC_PACKET_QUEUE container;
+    struct htc_packet  *pPacket;
+    struct htc_packet_queue container;
     
     LOCK_HTC_RX(target);
 
@@ -1512,7 +1512,7 @@
     UNLOCK_HTC_RX(target);
 }
 
-static void HTCFlushEndpointRX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint)
+static void HTCFlushEndpointRX(struct htc_target *target, struct htc_endpoint *pEndpoint)
 {
         /* flush any recv indications not already made */
     HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RecvIndicationQueue);
@@ -1520,9 +1520,9 @@
     HTCFlushRxQueue(target,pEndpoint,&pEndpoint->RxBuffers);
 }
 
-void HTCFlushRecvBuffers(HTC_TARGET *target)
+void HTCFlushRecvBuffers(struct htc_target *target)
 {
-    HTC_ENDPOINT    *pEndpoint;
+    struct htc_endpoint    *pEndpoint;
     int             i;
 
     for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
@@ -1538,7 +1538,7 @@
 
 void HTCEnableRecv(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     if (!HTC_STOPPING(target)) {
             /* re-enable */
@@ -1548,7 +1548,7 @@
 
 void HTCDisableRecv(HTC_HANDLE HTCHandle)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     if (!HTC_STOPPING(target)) {
             /* disable */
@@ -1559,16 +1559,16 @@
 int HTCGetNumRecvBuffers(HTC_HANDLE      HTCHandle,
                          HTC_ENDPOINT_ID Endpoint)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);    
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);    
     return HTC_PACKET_QUEUE_DEPTH(&(target->EndPoint[Endpoint].RxBuffers));
 }
 
-A_STATUS HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
-                               A_UINT32     TimeoutInMs,
-                               A_BOOL      *pbIsRecvPending)
+int HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
+                               u32 TimeoutInMs,
+                               bool      *pbIsRecvPending)
 {
-    A_STATUS    status  = A_OK;
-    HTC_TARGET *target  = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    int    status  = 0;
+    struct htc_target *target  = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
 
     status = DevWaitForPendingRecv(&target->Device,
                                     TimeoutInMs,
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_send.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_send.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_send.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_send.c	2011-05-19 00:06:34.000000000 -0400
@@ -43,8 +43,8 @@
                            (reason));                                    \
 }
 
-static void DoSendCompletion(HTC_ENDPOINT       *pEndpoint,
-                             HTC_PACKET_QUEUE   *pQueueToIndicate)
+static void DoSendCompletion(struct htc_endpoint       *pEndpoint,
+                             struct htc_packet_queue   *pQueueToIndicate)
 {           
     do {
                 
@@ -62,7 +62,7 @@
                 /* all packets are now owned by the callback, reset queue to be safe */
             INIT_HTC_PACKET_QUEUE(pQueueToIndicate);                                                      
         } else {
-            HTC_PACKET *pPacket;  
+            struct htc_packet *pPacket;  
             /* using legacy EpTxComplete */         
             do {
                 pPacket = HTC_PACKET_DEQUEUE(pQueueToIndicate);
@@ -72,16 +72,16 @@
             } while (!HTC_QUEUE_EMPTY(pQueueToIndicate));                                              
         }
         
-    } while (FALSE);
+    } while (false);
 
 }
 
 /* do final completion on sent packet */
-static INLINE void CompleteSentPacket(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_PACKET *pPacket)
+static INLINE void CompleteSentPacket(struct htc_target *target, struct htc_endpoint *pEndpoint, struct htc_packet *pPacket)
 {
     pPacket->Completion = NULL;  
     
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
             ("CompleteSentPacket: request failed (status:%d, ep:%d, length:%d creds:%d) \n",
                 pPacket->Status, pPacket->Endpoint, pPacket->ActualLength, pPacket->PktInfo.AsTx.CreditsUsed));                
@@ -101,11 +101,11 @@
 
 /* our internal send packet completion handler when packets are submited to the AR6K device
  * layer */
-static void HTCSendPktCompletionHandler(void *Context, HTC_PACKET *pPacket)
+static void HTCSendPktCompletionHandler(void *Context, struct htc_packet *pPacket)
 {
-    HTC_TARGET      *target = (HTC_TARGET *)Context;
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[pPacket->Endpoint];
-    HTC_PACKET_QUEUE container;
+    struct htc_target      *target = (struct htc_target *)Context;
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[pPacket->Endpoint];
+    struct htc_packet_queue container;
     
     CompleteSentPacket(target,pEndpoint,pPacket);
     INIT_HTC_PACKET_QUEUE_AND_ADD(&container,pPacket);
@@ -113,19 +113,19 @@
     DO_EP_TX_COMPLETION(pEndpoint,&container);
 }
 
-A_STATUS HTCIssueSend(HTC_TARGET *target, HTC_PACKET *pPacket)
+int HTCIssueSend(struct htc_target *target, struct htc_packet *pPacket)
 {
-    A_STATUS status;
-    A_BOOL   sync = FALSE;
+    int status;
+    bool   sync = false;
 
     if (pPacket->Completion == NULL) {
             /* mark that this request was synchronously issued */
-        sync = TRUE;
+        sync = true;
     }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
                     ("+-HTCIssueSend: transmit length : %d (%s) \n",
-                    pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH,
+                    pPacket->ActualLength + (u32)HTC_HDR_LENGTH,
                     sync ? "SYNC" : "ASYNC" ));
 
         /* send message to device */
@@ -146,21 +146,21 @@
 }
 
     /* get HTC send packets from the TX queue on an endpoint */
-static INLINE void GetHTCSendPackets(HTC_TARGET        *target, 
-                                     HTC_ENDPOINT      *pEndpoint, 
-                                     HTC_PACKET_QUEUE  *pQueue)
+static INLINE void GetHTCSendPackets(struct htc_target        *target, 
+                                     struct htc_endpoint      *pEndpoint, 
+                                     struct htc_packet_queue  *pQueue)
 {
     int          creditsRequired;
     int          remainder;
-    A_UINT8      sendFlags;
-    HTC_PACKET   *pPacket;
+    u8 sendFlags;
+    struct htc_packet   *pPacket;
     unsigned int transferLength;
 
     /****** NOTE : the TX lock is held when this function is called *****************/
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("+GetHTCSendPackets \n"));
      
         /* loop until we can grab as many packets out of the queue as we can */       
-    while (TRUE) {    
+    while (true) {
         
         sendFlags = 0;   
             /* get packet at head, but don't remove it */
@@ -264,14 +264,14 @@
      
 }
 
-static void HTCAsyncSendScatterCompletion(HIF_SCATTER_REQ *pScatterReq)
+static void HTCAsyncSendScatterCompletion(struct hif_scatter_req *pScatterReq)
 {
     int                 i;    
-    HTC_PACKET          *pPacket;
-    HTC_ENDPOINT        *pEndpoint = (HTC_ENDPOINT *)pScatterReq->Context;
-    HTC_TARGET          *target = (HTC_TARGET *)pEndpoint->target;
-    A_STATUS            status = A_OK;
-    HTC_PACKET_QUEUE    sendCompletes;
+    struct htc_packet          *pPacket;
+    struct htc_endpoint        *pEndpoint = (struct htc_endpoint *)pScatterReq->Context;
+    struct htc_target          *target = (struct htc_target *)pEndpoint->target;
+    int            status = 0;
+    struct htc_packet_queue    sendCompletes;
     
     INIT_HTC_PACKET_QUEUE(&sendCompletes);
           
@@ -280,14 +280,14 @@
     
     DEV_FINISH_SCATTER_OPERATION(pScatterReq);
            
-    if (A_FAILED(pScatterReq->CompletionStatus)) {
+    if (pScatterReq->CompletionStatus) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("** Send Scatter Request Failed: %d \n",pScatterReq->CompletionStatus));            
         status = A_ERROR;
     }
     
         /* walk through the scatter list and process */
     for (i = 0; i < pScatterReq->ValidScatterEntries; i++) {
-        pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
+        pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
         A_ASSERT(pPacket != NULL);
         pPacket->Status = status;
         CompleteSentPacket(target,pEndpoint,pPacket);
@@ -309,21 +309,21 @@
      *    - a message that will consume a partial credit will stop the bundling process early 
      *    - we drop below the minimum number of messages for a bundle 
      * */
-static void HTCIssueSendBundle(HTC_ENDPOINT      *pEndpoint, 
-                               HTC_PACKET_QUEUE  *pQueue, 
+static void HTCIssueSendBundle(struct htc_endpoint      *pEndpoint, 
+                               struct htc_packet_queue  *pQueue, 
                                int               *pBundlesSent, 
                                int               *pTotalBundlesPkts)
 {
     int                 pktsToScatter;
     unsigned int        scatterSpaceRemaining;
-    HIF_SCATTER_REQ     *pScatterReq = NULL;
+    struct hif_scatter_req     *pScatterReq = NULL;
     int                 i, packetsInScatterReq;
     unsigned int        transferLength;
-    HTC_PACKET          *pPacket;
-    A_BOOL              done = FALSE;
+    struct htc_packet          *pPacket;
+    bool              done = false;
     int                 bundlesSent = 0;
     int                 totalPktsInBundle = 0;
-    HTC_TARGET          *target = pEndpoint->target;
+    struct htc_target          *target = pEndpoint->target;
     int                 creditRemainder = 0;
     int                 creditPad;
     
@@ -361,7 +361,7 @@
             
             pPacket = HTC_GET_PKT_AT_HEAD(pQueue);        
             if (pPacket == NULL) {
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;    
             }
             
@@ -400,7 +400,7 @@
                        
             if (NULL == pPacket) {
                     /* can't bundle */
-                done = TRUE;
+                done = true;
                 break;    
             }         
                
@@ -450,7 +450,7 @@
             if (packetsInScatterReq > 0) {
                     /* work backwards to requeue requests */
                 for (i = (packetsInScatterReq - 1); i >= 0; i--) {
-                    pPacket = (HTC_PACKET *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
+                    pPacket = (struct htc_packet *)(pScatterReq->ScatterList[i].pCallerContexts[0]);
                     if (pPacket != NULL) {
                             /* undo any prep */
                         HTC_UNPREPARE_SEND_PKT(pPacket);
@@ -477,12 +477,12 @@
 /*
  * if there are no credits, the packet(s) remains in the queue.
  * this function returns the result of the attempt to send a queue of HTC packets */
-static HTC_SEND_QUEUE_RESULT HTCTrySend(HTC_TARGET       *target,
-                                        HTC_ENDPOINT     *pEndpoint,
-                                        HTC_PACKET_QUEUE *pCallersSendQueue)
+static HTC_SEND_QUEUE_RESULT HTCTrySend(struct htc_target       *target,
+                                        struct htc_endpoint     *pEndpoint,
+                                        struct htc_packet_queue *pCallersSendQueue)
 {
-    HTC_PACKET_QUEUE      sendQueue; /* temp queue to hold packets at various stages */
-    HTC_PACKET            *pPacket;
+    struct htc_packet_queue      sendQueue; /* temp queue to hold packets at various stages */
+    struct htc_packet            *pPacket;
     int                   bundlesSent;
     int                   pktsInBundles;
     int                   overflow;
@@ -546,7 +546,7 @@
             
                 /* the caller's queue has all the packets that won't fit*/                
                 /* walk through the caller's queue and indicate each one to the send full handler */            
-            ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, HTC_PACKET, ListLink) {            
+            ITERATE_OVER_LIST_ALLOW_REMOVE(&pCallersSendQueue->QueueHead, pPacket, struct htc_packet, ListLink) {            
                 
                 AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Indicating overflowed TX packet: 0x%lX \n", 
                                             (unsigned long)pPacket));    
@@ -571,7 +571,7 @@
             } 
         }
         
-    } while (FALSE);
+    } while (false);
     
     if (result != HTC_SEND_QUEUE_OK) {
         AR_DEBUG_PRINTF(ATH_DEBUG_SEND,("-HTCTrySend:  \n"));
@@ -602,7 +602,7 @@
             
         /* now drain the endpoint TX queue for transmission as long as we have enough
          * credits */
-    while (TRUE) {
+    while (true) {
           
         if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) == 0) {
             break;
@@ -623,7 +623,7 @@
         bundlesSent = 0;
         pktsInBundles = 0;
      
-        while (TRUE) {
+        while (true) {
             
                 /* try to send a bundle on each pass */            
             if ((target->SendBundlingEnabled) &&
@@ -668,11 +668,11 @@
     return HTC_SEND_QUEUE_OK;
 }
 
-A_STATUS  HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue)
+int  HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint;
-    HTC_PACKET      *pPacket;
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint;
+    struct htc_packet      *pPacket;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCSendPktsMultiple: Queue: 0x%lX, Pkts %d \n",
                     (unsigned long)pPktQueue, HTC_PACKET_QUEUE_DEPTH(pPktQueue)));
@@ -705,13 +705,13 @@
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("-HTCSendPktsMultiple \n"));
 
-    return A_OK;   
+    return 0;
 }
 
 /* HTC API - HTCSendPkt */
-A_STATUS HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket)
+int HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket)
 {
-    HTC_PACKET_QUEUE queue;
+    struct htc_packet_queue queue;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND,
                     ("+-HTCSendPkt: Enter endPointId: %d, buffer: 0x%lX, length: %d \n",
@@ -721,10 +721,10 @@
 }
 
 /* check TX queues to drain because of credit distribution update */
-static INLINE void HTCCheckEndpointTxQueues(HTC_TARGET *target)
+static INLINE void HTCCheckEndpointTxQueues(struct htc_target *target)
 {
-    HTC_ENDPOINT                *pEndpoint;
-    HTC_ENDPOINT_CREDIT_DIST    *pDistItem;
+    struct htc_endpoint                *pEndpoint;
+    struct htc_endpoint_credit_dist    *pDistItem;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCCheckEndpointTxQueues \n"));
     pDistItem = target->EpCreditDistributionListHead;
@@ -734,7 +734,7 @@
          * NOTE: no locks need to be taken since the distribution list
          * is not dynamic (cannot be re-ordered) and we are not modifying any state */
     while (pDistItem != NULL) {
-        pEndpoint = (HTC_ENDPOINT *)pDistItem->pHTCReserved;
+        pEndpoint = (struct htc_endpoint *)pDistItem->pHTCReserved;
 
         if (HTC_PACKET_QUEUE_DEPTH(&pEndpoint->TxQueue) > 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_SEND, (" Ep %d has %d credits and %d Packets in TX Queue \n",
@@ -753,12 +753,12 @@
 }
 
 /* process credit reports and call distribution function */
-void HTCProcessCreditRpt(HTC_TARGET *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
+void HTCProcessCreditRpt(struct htc_target *target, HTC_CREDIT_REPORT *pRpt, int NumEntries, HTC_ENDPOINT_ID FromEndpoint)
 {
     int             i;
-    HTC_ENDPOINT    *pEndpoint;
+    struct htc_endpoint    *pEndpoint;
     int             totalCredits = 0;
-    A_BOOL          doDist = FALSE;
+    bool          doDist = false;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_SEND, ("+HTCProcessCreditRpt, Credit Report Entries:%d \n", NumEntries));
 
@@ -767,7 +767,7 @@
 
     for (i = 0; i < NumEntries; i++, pRpt++) {
         if (pRpt->EndpointID >= ENDPOINT_MAX) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
@@ -807,7 +807,7 @@
                  * will handle giving out credits back to the endpoints */
             pEndpoint->CreditDist.TxCreditsToDist += pRpt->Credits;
                 /* flag that we have to do the distribution */
-            doDist = TRUE;
+            doDist = true;
         }
         
             /* refresh tx depth for distribution function that will recover these credits
@@ -838,11 +838,11 @@
 }
 
 /* flush endpoint TX queue */
-static void HTCFlushEndpointTX(HTC_TARGET *target, HTC_ENDPOINT *pEndpoint, HTC_TX_TAG Tag)
+static void HTCFlushEndpointTX(struct htc_target *target, struct htc_endpoint *pEndpoint, HTC_TX_TAG Tag)
 {
-    HTC_PACKET          *pPacket;
-    HTC_PACKET_QUEUE    discardQueue;
-    HTC_PACKET_QUEUE    container;
+    struct htc_packet          *pPacket;
+    struct htc_packet_queue    discardQueue;
+    struct htc_packet_queue    container;
 
         /* initialize the discard queue */
     INIT_HTC_PACKET_QUEUE(&discardQueue);
@@ -850,7 +850,7 @@
     LOCK_HTC_TX(target);
 
         /* interate from the front of the TX queue and flush out packets */
-    ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, HTC_PACKET, ListLink) {
+    ITERATE_OVER_LIST_ALLOW_REMOVE(&pEndpoint->TxQueue.QueueHead, pPacket, struct htc_packet, ListLink) {
 
             /* check for removal */
         if ((HTC_TX_PACKET_TAG_ALL == Tag) || (Tag == pPacket->PktInfo.AsTx.Tag)) {
@@ -879,7 +879,7 @@
 
 }
 
-void DumpCreditDist(HTC_ENDPOINT_CREDIT_DIST *pEPDist)
+void DumpCreditDist(struct htc_endpoint_credit_dist *pEPDist)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("--- EP : %d  ServiceID: 0x%X    --------------\n",
                         pEPDist->Endpoint, pEPDist->ServiceID));
@@ -895,13 +895,13 @@
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsPerMaxMsg : %d \n", pEPDist->TxCreditsPerMaxMsg));
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxCreditsToDist    : %d \n", pEPDist->TxCreditsToDist));
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, (" TxQueueDepth       : %d \n", 
-                    HTC_PACKET_QUEUE_DEPTH(&((HTC_ENDPOINT *)pEPDist->pHTCReserved)->TxQueue)));                                      
+                    HTC_PACKET_QUEUE_DEPTH(&((struct htc_endpoint *)pEPDist->pHTCReserved)->TxQueue)));                                      
     AR_DEBUG_PRINTF(ATH_DEBUG_ANY, ("----------------------------------------------------\n"));
 }
 
-void DumpCreditDistStates(HTC_TARGET *target)
+void DumpCreditDistStates(struct htc_target *target)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pEPList = target->EpCreditDistributionListHead;
+    struct htc_endpoint_credit_dist *pEPList = target->EpCreditDistributionListHead;
 
     while (pEPList != NULL) {
         DumpCreditDist(pEPList);
@@ -917,9 +917,9 @@
 }
 
 /* flush all send packets from all endpoint queues */
-void HTCFlushSendPkts(HTC_TARGET *target)
+void HTCFlushSendPkts(struct htc_target *target)
 {
-    HTC_ENDPOINT    *pEndpoint;
+    struct htc_endpoint    *pEndpoint;
     int             i;
 
     if (AR_DEBUG_LVL_CHECK(ATH_DEBUG_TRC)) {
@@ -941,11 +941,11 @@
 /* HTC API to flush an endpoint's TX queue*/
 void HTCFlushEndpoint(HTC_HANDLE HTCHandle, HTC_ENDPOINT_ID Endpoint, HTC_TX_TAG Tag)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[Endpoint];
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[Endpoint];
 
     if (pEndpoint->ServiceID == 0) {
-        AR_DEBUG_ASSERT(FALSE);
+        AR_DEBUG_ASSERT(false);
         /* not in use.. */
         return;
     }
@@ -956,14 +956,14 @@
 /* HTC API to indicate activity to the credit distribution function */
 void HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
                                HTC_ENDPOINT_ID Endpoint,
-                               A_BOOL          Active)
+                               bool          Active)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[Endpoint];
-    A_BOOL          doDist = FALSE;
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[Endpoint];
+    bool          doDist = false;
 
     if (pEndpoint->ServiceID == 0) {
-        AR_DEBUG_ASSERT(FALSE);
+        AR_DEBUG_ASSERT(false);
         /* not in use.. */
         return;
     }
@@ -974,13 +974,13 @@
         if (!(pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE)) {
                 /* mark active now */
             pEndpoint->CreditDist.DistFlags |= HTC_EP_ACTIVE;
-            doDist = TRUE;
+            doDist = true;
         }
     } else {
         if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
                 /* mark inactive now */
             pEndpoint->CreditDist.DistFlags &= ~HTC_EP_ACTIVE;
-            doDist = TRUE;
+            doDist = true;
         }
     }
 
@@ -1005,19 +1005,19 @@
     }
 }
 
-A_BOOL HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
+bool HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
                            HTC_ENDPOINT_ID Endpoint)
 {
-    HTC_TARGET      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    HTC_ENDPOINT    *pEndpoint = &target->EndPoint[Endpoint];
+    struct htc_target      *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_endpoint    *pEndpoint = &target->EndPoint[Endpoint];
 
     if (pEndpoint->ServiceID == 0) {
-        return FALSE;
+        return false;
     }
     
     if (pEndpoint->CreditDist.DistFlags & HTC_EP_ACTIVE) {
-        return TRUE;
+        return true;
     }
     
-    return FALSE;
+    return false;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_services.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_services.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/htc2/htc_services.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/htc2/htc_services.c	2011-05-19 00:06:34.000000000 -0400
@@ -22,21 +22,21 @@
 //==============================================================================
 #include "htc_internal.h"
 
-void HTCControlTxComplete(void *Context, HTC_PACKET *pPacket)
+void HTCControlTxComplete(void *Context, struct htc_packet *pPacket)
 {
         /* not implemented
          * we do not send control TX frames during normal runtime, only during setup  */
-    AR_DEBUG_ASSERT(FALSE);
+    AR_DEBUG_ASSERT(false);
 }
 
     /* callback when a control message arrives on this endpoint */
-void HTCControlRecv(void *Context, HTC_PACKET *pPacket)
+void HTCControlRecv(void *Context, struct htc_packet *pPacket)
 {
     AR_DEBUG_ASSERT(pPacket->Endpoint == ENDPOINT_0);
 
     if (pPacket->Status == A_ECANCELED) {
         /* this is a flush operation, return the control packet back to the pool */
-        HTC_FREE_CONTROL_RX((HTC_TARGET*)Context,pPacket);    
+        HTC_FREE_CONTROL_RX((struct htc_target*)Context,pPacket);    
         return;
     }  
     
@@ -44,7 +44,7 @@
     if (pPacket->ActualLength > 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("HTCControlRecv, got message with length:%d \n",
-                        pPacket->ActualLength + (A_UINT32)HTC_HDR_LENGTH));
+                        pPacket->ActualLength + (u32)HTC_HDR_LENGTH));
 
 #ifdef ATH_DEBUG_MODULE
             /* dump header and message */
@@ -54,13 +54,13 @@
 #endif
     }
 
-    HTC_RECYCLE_RX_PKT((HTC_TARGET*)Context,pPacket,&((HTC_TARGET*)Context)->EndPoint[0]);
+    HTC_RECYCLE_RX_PKT((struct htc_target*)Context,pPacket,&((struct htc_target*)Context)->EndPoint[0]);
 }
 
-A_STATUS HTCSendSetupComplete(HTC_TARGET *target)
+int HTCSendSetupComplete(struct htc_target *target)
 {
-    HTC_PACKET             *pSendPacket = NULL;
-    A_STATUS                status;
+    struct htc_packet             *pSendPacket = NULL;
+    int                status;
 
     do {
            /* allocate a packet to send to the target */
@@ -73,7 +73,7 @@
 
         if (target->HTCTargetVersion >= HTC_VERSION_2P1) {
             HTC_SETUP_COMPLETE_EX_MSG *pSetupCompleteEx;
-            A_UINT32                  setupFlags = 0;
+            u32 setupFlags = 0;
                    
             pSetupCompleteEx = (HTC_SETUP_COMPLETE_EX_MSG *)pSendPacket->pBuffer;
             A_MEMZERO(pSetupCompleteEx, sizeof(HTC_SETUP_COMPLETE_EX_MSG));
@@ -83,10 +83,10 @@
                 setupFlags |= HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV; 
                 pSetupCompleteEx->MaxMsgsPerBundledRecv = target->MaxMsgPerBundle;
             }    
-            A_MEMCPY(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags));            
+            memcpy(&pSetupCompleteEx->SetupFlags, &setupFlags, sizeof(pSetupCompleteEx->SetupFlags));            
             SET_HTC_PACKET_INFO_TX(pSendPacket,
                                    NULL,
-                                   (A_UINT8 *)pSetupCompleteEx,
+                                   (u8 *)pSetupCompleteEx,
                                    sizeof(HTC_SETUP_COMPLETE_EX_MSG),
                                    ENDPOINT_0,
                                    HTC_SERVICE_TX_PACKET_TAG);
@@ -99,7 +99,7 @@
             pSetupComplete->MessageID = HTC_MSG_SETUP_COMPLETE_ID;   
             SET_HTC_PACKET_INFO_TX(pSendPacket,
                                    NULL,
-                                   (A_UINT8 *)pSetupComplete,
+                                   (u8 *)pSetupComplete,
                                    sizeof(HTC_SETUP_COMPLETE_MSG),
                                    ENDPOINT_0,
                                    HTC_SERVICE_TX_PACKET_TAG);
@@ -111,7 +111,7 @@
             /* send the message */
         status = HTCIssueSend(target,pSendPacket);
 
-    } while (FALSE);
+    } while (false);
 
     if (pSendPacket != NULL) {
         HTC_FREE_CONTROL_TX(target,pSendPacket);
@@ -121,18 +121,18 @@
 }
 
 
-A_STATUS HTCConnectService(HTC_HANDLE               HTCHandle,
-                           HTC_SERVICE_CONNECT_REQ  *pConnectReq,
-                           HTC_SERVICE_CONNECT_RESP *pConnectResp)
+int HTCConnectService(HTC_HANDLE               HTCHandle,
+                           struct htc_service_connect_req  *pConnectReq,
+                           struct htc_service_connect_resp *pConnectResp)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
-    A_STATUS                            status = A_OK;
-    HTC_PACKET                          *pRecvPacket = NULL;
-    HTC_PACKET                          *pSendPacket = NULL;
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    int                            status = 0;
+    struct htc_packet                          *pRecvPacket = NULL;
+    struct htc_packet                          *pSendPacket = NULL;
     HTC_CONNECT_SERVICE_RESPONSE_MSG    *pResponseMsg;
     HTC_CONNECT_SERVICE_MSG             *pConnectMsg;
     HTC_ENDPOINT_ID                     assignedEndpoint = ENDPOINT_MAX;
-    HTC_ENDPOINT                        *pEndpoint;
+    struct htc_endpoint                        *pEndpoint;
     unsigned int                        maxMsgSize = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("+HTCConnectService, target:0x%lX SvcID:0x%X \n",
@@ -151,7 +151,7 @@
             pSendPacket = HTC_ALLOC_CONTROL_TX(target);
 
             if (NULL == pSendPacket) {
-                AR_DEBUG_ASSERT(FALSE);
+                AR_DEBUG_ASSERT(false);
                 status = A_NO_MEMORY;
                 break;
             }
@@ -166,7 +166,7 @@
             if ((pConnectReq->pMetaData != NULL) &&
                 (pConnectReq->MetaDataLength <= HTC_SERVICE_META_DATA_MAX_LENGTH)) {
                     /* copy meta data into message buffer (after header ) */
-                A_MEMCPY((A_UINT8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
+                memcpy((u8 *)pConnectMsg + sizeof(HTC_CONNECT_SERVICE_MSG),
                          pConnectReq->pMetaData,
                          pConnectReq->MetaDataLength);
                 pConnectMsg->ServiceMetaLength = pConnectReq->MetaDataLength;
@@ -174,7 +174,7 @@
 
             SET_HTC_PACKET_INFO_TX(pSendPacket,
                                    NULL,
-                                   (A_UINT8 *)pConnectMsg,
+                                   (u8 *)pConnectMsg,
                                    sizeof(HTC_CONNECT_SERVICE_MSG) + pConnectMsg->ServiceMetaLength,
                                    ENDPOINT_0,
                                    HTC_SERVICE_TX_PACKET_TAG);
@@ -184,14 +184,14 @@
             HTC_PREPARE_SEND_PKT(pSendPacket,0,0,0);
             status = HTCIssueSend(target,pSendPacket);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
 
                 /* wait for response */
             status = HTCWaitforControlMessage(target, &pRecvPacket);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
                 /* we controlled the buffer creation so it has to be properly aligned */
@@ -200,7 +200,7 @@
             if ((pResponseMsg->MessageID != HTC_MSG_CONNECT_SERVICE_RESPONSE_ID) ||
                 (pRecvPacket->ActualLength < sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG))) {
                     /* this message is not valid */
-                AR_DEBUG_ASSERT(FALSE);
+                AR_DEBUG_ASSERT(false);
                 status = A_EPROTO;
                 break;
             }
@@ -224,8 +224,8 @@
                     /* caller supplied a buffer and the target responded with data */
                 int copyLength = min((int)pConnectResp->BufferLength, (int)pResponseMsg->ServiceMetaLength);
                     /* copy the meta data */
-                A_MEMCPY(pConnectResp->pMetaData,
-                         ((A_UINT8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
+                memcpy(pConnectResp->pMetaData,
+                         ((u8 *)pResponseMsg) + sizeof(HTC_CONNECT_SERVICE_RESPONSE_MSG),
                          copyLength);
                 pConnectResp->ActualLength = copyLength;
             }
@@ -236,12 +236,12 @@
         status = A_EPROTO;
 
         if (assignedEndpoint >= ENDPOINT_MAX) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
         if (0 == maxMsgSize) {
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
@@ -249,7 +249,7 @@
         pEndpoint->Id = assignedEndpoint;
         if (pEndpoint->ServiceID != 0) {
             /* endpoint already in use! */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
 
@@ -275,7 +275,7 @@
                  * since the host will actually issue smaller messages in the Send path */
             if (pConnectReq->MaxSendMsgSize > maxMsgSize) {
                     /* can't be larger than the maximum the target can support */
-                AR_DEBUG_ASSERT(FALSE);
+                AR_DEBUG_ASSERT(false);
                 break;       
             }
             pEndpoint->CreditDist.TxCreditsPerMaxMsg = pConnectReq->MaxSendMsgSize / target->TargetCreditSize;
@@ -290,9 +290,9 @@
             /* save local connection flags */
         pEndpoint->LocalConnectionFlags = pConnectReq->LocalConnectionFlags;
         
-        status = A_OK;
+        status = 0;
 
-    } while (FALSE);
+    } while (false);
 
     if (pSendPacket != NULL) {
         HTC_FREE_CONTROL_TX(target,pSendPacket);
@@ -307,9 +307,9 @@
     return status;
 }
 
-static void AddToEndpointDistList(HTC_TARGET *target, HTC_ENDPOINT_CREDIT_DIST *pEpDist)
+static void AddToEndpointDistList(struct htc_target *target, struct htc_endpoint_credit_dist *pEpDist)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEntry,*pLastEntry;
+    struct htc_endpoint_credit_dist *pCurEntry,*pLastEntry;
 
     if (NULL == target->EpCreditDistributionListHead) {
         target->EpCreditDistributionListHead = pEpDist;
@@ -336,10 +336,10 @@
 
 /* default credit init callback */
 static void HTCDefaultCreditInit(void                     *Context,
-                                 HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                                 struct htc_endpoint_credit_dist *pEPList,
                                  int                      TotalCredits)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
     int                      totalEps = 0;
     int                      creditsPerEndpoint;
 
@@ -360,7 +360,7 @@
 
         if (creditsPerEndpoint < pCurEpDist->TxCreditsPerMaxMsg) {
                 /* too many endpoints and not enough credits */
-            AR_DEBUG_ASSERT(FALSE);
+            AR_DEBUG_ASSERT(false);
             break;
         }
             /* our minimum is set for at least 1 max message */
@@ -379,10 +379,10 @@
 
 /* default credit distribution callback, NOTE, this callback holds the TX lock */
 void HTCDefaultCreditDist(void                     *Context,
-                          HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
+                          struct htc_endpoint_credit_dist *pEPDistList,
                           HTC_CREDIT_DIST_REASON   Reason)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
 
     if (Reason == HTC_CREDIT_DIST_SEND_COMPLETE) {
         pCurEpDist = pEPDistList;
@@ -408,7 +408,7 @@
                               HTC_SERVICE_ID           ServicePriorityOrder[],
                               int                      ListLength)
 {
-    HTC_TARGET *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
+    struct htc_target *target = GET_HTC_TARGET_FROM_HANDLE(HTCHandle);
     int i;
     int ep;
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/a_debug.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/a_debug.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/a_debug.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/a_debug.h	2011-05-19 00:06:34.000000000 -0400
@@ -57,7 +57,7 @@
     /* macro to make a module-specific masks */
 #define ATH_DEBUG_MAKE_MODULE_MASK(index)  (1 << (ATH_DEBUG_MODULE_MASK_SHIFT + (index)))
 
-void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription);
+void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription);
 
 /* Debug support on a per-module basis
  *
@@ -95,7 +95,7 @@
  *   #define ATH_DEBUG_BMI  ATH_DEBUG_MAKE_MODULE_MASK(0)
  *
  *   #ifdef DEBUG
- *   static ATH_DEBUG_MASK_DESCRIPTION bmi_debug_desc[] = {
+ *   static struct ath_debug_mask_description bmi_debug_desc[] = {
  *       { ATH_DEBUG_BMI , "BMI Tracing"},   <== description of the module specific mask
  *   };
  *
@@ -118,24 +118,24 @@
 #define ATH_DEBUG_MAX_MASK_DESC_LENGTH   32
 #define ATH_DEBUG_MAX_MOD_DESC_LENGTH    64
 
-typedef struct {
-    A_UINT32 Mask;
-    A_CHAR   Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH];
-} ATH_DEBUG_MASK_DESCRIPTION;
+struct ath_debug_mask_description {
+    u32 Mask;
+    char Description[ATH_DEBUG_MAX_MASK_DESC_LENGTH];
+};
 
 #define ATH_DEBUG_INFO_FLAGS_REGISTERED (1 << 0)
 
 typedef struct  _ATH_DEBUG_MODULE_DBG_INFO{
     struct _ATH_DEBUG_MODULE_DBG_INFO *pNext;
-    A_CHAR                      ModuleName[16];
-    A_CHAR                      ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH];
-    A_UINT32                    Flags;
-    A_UINT32                    CurrentMask;
+    char ModuleName[16];
+    char ModuleDescription[ATH_DEBUG_MAX_MOD_DESC_LENGTH];
+    u32 Flags;
+    u32 CurrentMask;
     int                         MaxDescriptions;
-    ATH_DEBUG_MASK_DESCRIPTION  *pMaskDescriptions; /* pointer to array of descriptions */
+    struct ath_debug_mask_description  *pMaskDescriptions; /* pointer to array of descriptions */
 } ATH_DEBUG_MODULE_DBG_INFO;
 
-#define ATH_DEBUG_DESCRIPTION_COUNT(d)  (int)((sizeof((d))) / (sizeof(ATH_DEBUG_MASK_DESCRIPTION)))
+#define ATH_DEBUG_DESCRIPTION_COUNT(d)  (int)((sizeof((d))) / (sizeof(struct ath_debug_mask_description)))
 
 #define GET_ATH_MODULE_DEBUG_VAR_NAME(s) _XGET_ATH_MODULE_NAME_DEBUG_(s)
 #define GET_ATH_MODULE_DEBUG_VAR_MASK(s) _XGET_ATH_MODULE_NAME_DEBUG_(s).CurrentMask
@@ -181,9 +181,9 @@
 
 #endif
 
-A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask);
-A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask);
-void a_dump_module_debug_info_by_name(A_CHAR *module_name);
+int a_get_module_mask(char *module_name, u32 *pMask);
+int a_set_module_mask(char *module_name, u32 Mask);
+void a_dump_module_debug_info_by_name(char *module_name);
 void a_module_debug_support_init(void);
 void a_module_debug_support_cleanup(void);
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/a_drv_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/a_drv_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/a_drv_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/a_drv_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -188,10 +188,10 @@
     ar6000_dbglog_event((ar), (dropped), (buffer), (length));
 
 #define A_WMI_STREAM_TX_ACTIVE(devt,trafficClass) \
-    ar6000_indicate_tx_activity((devt),(trafficClass), TRUE)
+    ar6000_indicate_tx_activity((devt),(trafficClass), true)
 
 #define A_WMI_STREAM_TX_INACTIVE(devt,trafficClass) \
-    ar6000_indicate_tx_activity((devt),(trafficClass), FALSE)
+    ar6000_indicate_tx_activity((devt),(trafficClass), false)
 #define A_WMI_Ac2EndpointID(devht, ac)\
     ar6000_ac2_endpoint_id((devht), (ac))
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/aggr_recv_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/aggr_recv_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/aggr_recv_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/aggr_recv_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 
 typedef void (* RX_CALLBACK)(void * dev, void *osbuf);
 
-typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, A_UINT16 num);
+typedef void (* ALLOC_NETBUFS)(A_NETBUF_QUEUE_T *q, u16 num);
 
 /*
  * aggr_init:
@@ -64,7 +64,7 @@
  * up to the indicated sequence number.
  */
 void
-aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no);
+aggr_process_bar(void *cntxt, u8 tid, u16 seq_no);
 
 
 /*
@@ -72,7 +72,7 @@
  * This event is to initiate/modify the receive side window.
  * Target will send WMI_ADDBA_REQ_EVENTID event to host - to setup 
  * recv re-ordering queues. Target will negotiate ADDBA with peer, 
- * and indicate via this event after succesfully completing the 
+ * and indicate via this event after successfully completing the 
  * negotiation. This happens in two situations:
  *  1. Initial setup of aggregation
  *  2. Renegotiation of current recv window.
@@ -82,7 +82,7 @@
  * in hold_q to OS.
  */
 void
-aggr_recv_addba_req_evt(void * cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_sz);
+aggr_recv_addba_req_evt(void * cntxt, u8 tid, u16 seq_no, u8 win_sz);
 
 
 /*
@@ -93,7 +93,7 @@
  * aggr is not enabled on any tid.
  */
 void
-aggr_recv_delba_req_evt(void * cntxt, A_UINT8 tid);
+aggr_recv_delba_req_evt(void * cntxt, u8 tid);
 
 
 
@@ -108,7 +108,7 @@
  * callback may be called to deliver frames in order.
  */
 void
-aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu, void **osbuf);
+aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf);
 
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/ar3kconfig.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/ar3kconfig.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/ar3kconfig.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/ar3kconfig.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,25 +38,25 @@
 #define AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP        (1 << 3)
 
 
-typedef struct {
-    A_UINT32                 Flags;           /* config flags */
+struct ar3k_config_info {
+    u32 Flags;           /* config flags */
     void                     *pHCIDev;        /* HCI bridge device     */
-    HCI_TRANSPORT_PROPERTIES *pHCIProps;      /* HCI bridge props      */
-    HIF_DEVICE               *pHIFDevice;     /* HIF layer device      */
+    struct hci_transport_properties *pHCIProps;      /* HCI bridge props      */
+    struct hif_device               *pHIFDevice;     /* HIF layer device      */
     
-    A_UINT32                 AR3KBaudRate;    /* AR3K operational baud rate */
-    A_UINT16                 AR6KScale;       /* AR6K UART scale value */    
-    A_UINT16                 AR6KStep;        /* AR6K UART step value  */
+    u32 AR3KBaudRate;    /* AR3K operational baud rate */
+    u16 AR6KScale;       /* AR6K UART scale value */
+    u16 AR6KStep;        /* AR6K UART step value  */
     struct hci_dev           *pBtStackHCIDev; /* BT Stack HCI dev */
-    A_UINT32                 PwrMgmtEnabled;  /* TLPM enabled? */  
-    A_UINT16                 IdleTimeout;     /* TLPM idle timeout */
-    A_UINT16                 WakeupTimeout;   /* TLPM wakeup timeout */
-    A_UINT8                  bdaddr[6];       /* Bluetooth device address */
-} AR3K_CONFIG_INFO;
+    u32 PwrMgmtEnabled;  /* TLPM enabled? */
+    u16 IdleTimeout;     /* TLPM idle timeout */
+    u16 WakeupTimeout;   /* TLPM wakeup timeout */
+    u8 bdaddr[6];       /* Bluetooth device address */
+};
                                                                                         
-A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfigInfo);
+int AR3KConfigure(struct ar3k_config_info *pConfigInfo);
 
-A_STATUS AR3KConfigureExit(void *config);
+int AR3KConfigureExit(void *config);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/ar6000_diag.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/ar6000_diag.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/ar6000_diag.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/ar6000_diag.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,24 +25,24 @@
 #define AR6000_DIAG_H_
 
 
-A_STATUS
-ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int
+ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS
-ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int
+ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS
-ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                    A_UCHAR *data, A_UINT32 length);
+int
+ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,
+                    u8 *data, u32 length);
 
-A_STATUS
-ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                     A_UCHAR *data, A_UINT32 length);
+int
+ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address,
+                     u8 *data, u32 length);
 
-A_STATUS
-ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval);
+int
+ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval);
 
 void
-ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs);
+ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs);
 
 #endif /*AR6000_DIAG_H_*/
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/ar6kap_common.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/ar6kap_common.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/ar6kap_common.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/ar6kap_common.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,11 +32,11 @@
  * Used with AR6000_XIOCTL_AP_GET_STA_LIST
  */
 typedef struct {
-    A_UINT8     mac[ATH_MAC_LEN];
-    A_UINT8     aid;
-    A_UINT8     keymgmt;
-    A_UINT8     ucipher;
-    A_UINT8     auth;
+    u8 mac[ATH_MAC_LEN];
+    u8 aid;
+    u8 keymgmt;
+    u8 ucipher;
+    u8 auth;
 } station_t;
 typedef struct {
     station_t sta[AP_MAX_NUM_STA];
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/athbtfilter.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/athbtfilter.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/athbtfilter.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/athbtfilter.h	2011-05-19 00:06:34.000000000 -0400
@@ -61,11 +61,11 @@
 
 typedef void   (*ATHBT_INDICATE_STATE_FN)(void *pContext, ATHBT_STATE_INDICATION Indication, ATHBT_STATE State, unsigned char LMPVersion);
 
-typedef struct _ATHBT_FILTER_INSTANCE {
+struct athbt_filter_instance {
 #ifdef UNDER_CE
     WCHAR                       *pWlanAdapterName;  /* filled in by user */
 #else
-    char                        *pWlanAdapterName;  /* filled in by user */
+    char *pWlanAdapterName;  /* filled in by user */
 #endif /* UNDER_CE */
     int                         FilterEnabled;      /* filtering is enabled */
     int                         Attached;           /* filter library is attached */
@@ -74,7 +74,7 @@
     ATHBT_FILTER_DATA_FN        pFilterAclDataOut;  /* function ptr to filter ACL data out (to radio) */
     ATHBT_FILTER_DATA_FN        pFilterAclDataIn;   /* function ptr to filter ACL data in (from radio) */
     ATHBT_INDICATE_STATE_FN     pIndicateState;     /* function ptr to indicate a state */
-} ATH_BT_FILTER_INSTANCE;
+}; /* XXX: unused ? */
 
 
 /* API MACROS */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/bmi.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/bmi.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/bmi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/bmi.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,90 +43,90 @@
 void
 BMICleanup(void);
 
-A_STATUS
-BMIDone(HIF_DEVICE *device);
+int
+BMIDone(struct hif_device *device);
 
-A_STATUS
-BMIGetTargetInfo(HIF_DEVICE *device, struct bmi_target_info *targ_info);
+int
+BMIGetTargetInfo(struct hif_device *device, struct bmi_target_info *targ_info);
 
-A_STATUS
-BMIReadMemory(HIF_DEVICE *device,
-              A_UINT32 address,
-              A_UCHAR *buffer,
-              A_UINT32 length);
+int
+BMIReadMemory(struct hif_device *device,
+              u32 address,
+              u8 *buffer,
+              u32 length);
 
-A_STATUS
-BMIWriteMemory(HIF_DEVICE *device,
-               A_UINT32 address,
-               A_UCHAR *buffer,
-               A_UINT32 length);
+int
+BMIWriteMemory(struct hif_device *device,
+               u32 address,
+               u8 *buffer,
+               u32 length);
 
-A_STATUS
-BMIExecute(HIF_DEVICE *device,
-           A_UINT32 address,
-           A_UINT32 *param);
+int
+BMIExecute(struct hif_device *device,
+           u32 address,
+           u32 *param);
 
-A_STATUS
-BMISetAppStart(HIF_DEVICE *device,
-               A_UINT32 address);
+int
+BMISetAppStart(struct hif_device *device,
+               u32 address);
 
-A_STATUS
-BMIReadSOCRegister(HIF_DEVICE *device,
-                   A_UINT32 address,
-                   A_UINT32 *param);
+int
+BMIReadSOCRegister(struct hif_device *device,
+                   u32 address,
+                   u32 *param);
 
-A_STATUS
-BMIWriteSOCRegister(HIF_DEVICE *device,
-                    A_UINT32 address,
-                    A_UINT32 param);
+int
+BMIWriteSOCRegister(struct hif_device *device,
+                    u32 address,
+                    u32 param);
 
-A_STATUS
-BMIrompatchInstall(HIF_DEVICE *device,
-                   A_UINT32 ROM_addr,
-                   A_UINT32 RAM_addr,
-                   A_UINT32 nbytes,
-                   A_UINT32 do_activate,
-                   A_UINT32 *patch_id);
+int
+BMIrompatchInstall(struct hif_device *device,
+                   u32 ROM_addr,
+                   u32 RAM_addr,
+                   u32 nbytes,
+                   u32 do_activate,
+                   u32 *patch_id);
 
-A_STATUS
-BMIrompatchUninstall(HIF_DEVICE *device,
-                     A_UINT32 rompatch_id);
+int
+BMIrompatchUninstall(struct hif_device *device,
+                     u32 rompatch_id);
 
-A_STATUS
-BMIrompatchActivate(HIF_DEVICE *device,
-                    A_UINT32 rompatch_count,
-                    A_UINT32 *rompatch_list);
+int
+BMIrompatchActivate(struct hif_device *device,
+                    u32 rompatch_count,
+                    u32 *rompatch_list);
 
-A_STATUS
-BMIrompatchDeactivate(HIF_DEVICE *device,
-                      A_UINT32 rompatch_count,
-                      A_UINT32 *rompatch_list);
+int
+BMIrompatchDeactivate(struct hif_device *device,
+                      u32 rompatch_count,
+                      u32 *rompatch_list);
 
-A_STATUS
-BMILZStreamStart(HIF_DEVICE *device,
-                 A_UINT32 address);
+int
+BMILZStreamStart(struct hif_device *device,
+                 u32 address);
 
-A_STATUS
-BMILZData(HIF_DEVICE *device,
-          A_UCHAR *buffer,
-          A_UINT32 length);
+int
+BMILZData(struct hif_device *device,
+          u8 *buffer,
+          u32 length);
 
-A_STATUS
-BMIFastDownload(HIF_DEVICE *device,
-                A_UINT32 address,
-                A_UCHAR *buffer,
-                A_UINT32 length);
+int
+BMIFastDownload(struct hif_device *device,
+                u32 address,
+                u8 *buffer,
+                u32 length);
 
-A_STATUS
-BMIRawWrite(HIF_DEVICE *device,
-            A_UCHAR *buffer,
-            A_UINT32 length);
+int
+BMIRawWrite(struct hif_device *device,
+            u8 *buffer,
+            u32 length);
 
-A_STATUS
-BMIRawRead(HIF_DEVICE *device, 
-           A_UCHAR *buffer, 
-           A_UINT32 length, 
-           A_BOOL want_timeout);
+int
+BMIRawRead(struct hif_device *device, 
+           u8 *buffer, 
+           u32 length,
+           bool want_timeout);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/a_hci.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/a_hci.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/a_hci.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/a_hci.h	2011-05-19 00:06:34.000000000 -0400
@@ -124,7 +124,7 @@
 #define PAL_NUM_COMPL_DATA_BLOCK_EVENT              0x48
 #define PAL_SHORT_RANGE_MODE_CHANGE_COMPL_EVENT     0x4C
 #define PAL_AMP_STATUS_CHANGE_EVENT                 0x4D
-/*======== End of PAL events definiton =================*/
+/*======== End of PAL events definition =================*/
 
 
 /*======== Timeouts (not part of HCI cmd, but input to PAL engine) =========*/
@@ -242,161 +242,161 @@
 
 /* Command pkt */
 typedef struct  hci_cmd_pkt_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     params[255];
+    u16 opcode;
+    u8 param_length;
+    u8 params[255];
 } POSTPACK HCI_CMD_PKT;
 
 #define ACL_DATA_HDR_SIZE   4   /* hdl_and flags + data_len */
 /* Data pkt */
 typedef struct  hci_acl_data_pkt_t {
-    A_UINT16    hdl_and_flags;
-    A_UINT16    data_len;
-    A_UINT8     data[Max80211_PAL_PDU_Size];
+    u16 hdl_and_flags;
+    u16 data_len;
+    u8 data[Max80211_PAL_PDU_Size];
 } POSTPACK HCI_ACL_DATA_PKT;
 
 /* Event pkt */
 typedef struct  hci_event_pkt_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     params[256];
+    u8 event_code;
+    u8 param_len;
+    u8 params[256];
 } POSTPACK HCI_EVENT_PKT;
 
 
 /*============== HCI Command definitions ======================= */
 typedef struct hci_cmd_phy_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     link_key_len;
-    A_UINT8     link_key_type;
-    A_UINT8     link_key[LINK_KEY_LEN];
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u8 link_key_len;
+    u8 link_key_type;
+    u8 link_key[LINK_KEY_LEN];
 } POSTPACK HCI_CMD_PHY_LINK;
 
 typedef struct  hci_cmd_write_rem_amp_assoc_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT16    len_so_far;
-    A_UINT16    amp_assoc_remaining_len;
-    A_UINT8     amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u16 len_so_far;
+    u16 amp_assoc_remaining_len;
+    u8 amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
 } POSTPACK HCI_CMD_WRITE_REM_AMP_ASSOC;
 
 
 typedef struct  hci_cmd_opcode_hdl_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
 } POSTPACK HCI_CMD_READ_LINK_QUAL,
            HCI_CMD_FLUSH,
            HCI_CMD_READ_LINK_SUPERVISION_TIMEOUT;
 
 typedef struct  hci_cmd_read_local_amp_assoc_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT16    len_so_far;
-    A_UINT16    max_rem_amp_assoc_len;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u16 len_so_far;
+    u16 max_rem_amp_assoc_len;
 } POSTPACK HCI_CMD_READ_LOCAL_AMP_ASSOC;
 
 
 typedef struct hci_cmd_set_event_mask_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT64    mask;
+    u16 opcode;
+    u8 param_length;
+    u64 mask;
 }POSTPACK HCI_CMD_SET_EVT_MASK, HCI_CMD_SET_EVT_MASK_PG_2;
 
 
 typedef struct  hci_cmd_enhanced_flush_t{
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
-    A_UINT8     type;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
+    u8 type;
 } POSTPACK HCI_CMD_ENHANCED_FLUSH;
 
 
 typedef struct  hci_cmd_write_timeout_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    timeout;
+    u16 opcode;
+    u8 param_length;
+    u16 timeout;
 } POSTPACK  HCI_CMD_WRITE_TIMEOUT;
 
 typedef struct  hci_cmd_write_link_supervision_timeout_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
-    A_UINT16    timeout;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
+    u16 timeout;
 } POSTPACK HCI_CMD_WRITE_LINK_SUPERVISION_TIMEOUT;
 
 typedef struct  hci_cmd_write_flow_control_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     mode;
+    u16 opcode;
+    u8 param_length;
+    u8 mode;
 } POSTPACK  HCI_CMD_WRITE_FLOW_CONTROL;
 
 typedef struct  location_data_cfg_t {
-    A_UINT8     reg_domain_aware;
-    A_UINT8     reg_domain[3];
-    A_UINT8     reg_options;
+    u8 reg_domain_aware;
+    u8 reg_domain[3];
+    u8 reg_options;
 } POSTPACK LOCATION_DATA_CFG;
 
 typedef struct  hci_cmd_write_location_data_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
+    u16 opcode;
+    u8 param_length;
     LOCATION_DATA_CFG   cfg;
 } POSTPACK  HCI_CMD_WRITE_LOCATION_DATA;
 
 
 typedef struct  flow_spec_t {
-    A_UINT8     id;
-    A_UINT8     service_type;
-    A_UINT16    max_sdu;
-    A_UINT32    sdu_inter_arrival_time;
-    A_UINT32    access_latency;
-    A_UINT32    flush_timeout;
+    u8 id;
+    u8 service_type;
+    u16 max_sdu;
+    u32 sdu_inter_arrival_time;
+    u32 access_latency;
+    u32 flush_timeout;
 } POSTPACK FLOW_SPEC;
 
 
 typedef struct  hci_cmd_create_logical_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
     FLOW_SPEC   tx_flow_spec;
     FLOW_SPEC   rx_flow_spec;
 } POSTPACK HCI_CMD_CREATE_LOGICAL_LINK;
 
 typedef struct  hci_cmd_flow_spec_modify_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    hdl;
+    u16 opcode;
+    u8 param_length;
+    u16 hdl;
     FLOW_SPEC   tx_flow_spec;
     FLOW_SPEC   rx_flow_spec;
 } POSTPACK HCI_CMD_FLOW_SPEC_MODIFY;
 
 typedef struct hci_cmd_logical_link_cancel_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     tx_flow_spec_id;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u8 tx_flow_spec_id;
 } POSTPACK HCI_CMD_LOGICAL_LINK_CANCEL;
 
 typedef struct  hci_cmd_disconnect_logical_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT16    logical_link_hdl;
+    u16 opcode;
+    u8 param_length;
+    u16 logical_link_hdl;
 } POSTPACK HCI_CMD_DISCONNECT_LOGICAL_LINK;
 
 typedef struct  hci_cmd_disconnect_phy_link_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
 } POSTPACK HCI_CMD_DISCONNECT_PHY_LINK;
 
 typedef struct  hci_cmd_srm_t {
-    A_UINT16    opcode;
-    A_UINT8     param_length;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     mode;
+    u16 opcode;
+    u8 param_length;
+    u8 phy_link_hdl;
+    u8 mode;
 } POSTPACK HCI_CMD_SHORT_RANGE_MODE;
 /*============== HCI Command definitions end ======================= */
 
@@ -406,175 +406,175 @@
 
 /* Command complete event */
 typedef struct  hci_event_cmd_complete_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     num_hci_cmd_pkts;
-    A_UINT16    opcode;
-    A_UINT8     params[255];
+    u8 event_code;
+    u8 param_len;
+    u8 num_hci_cmd_pkts;
+    u16 opcode;
+    u8 params[255];
 } POSTPACK HCI_EVENT_CMD_COMPLETE;
 
 
 /* Command status event */
 typedef struct  hci_event_cmd_status_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     num_hci_cmd_pkts;
-    A_UINT16    opcode;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 num_hci_cmd_pkts;
+    u16 opcode;
 } POSTPACK HCI_EVENT_CMD_STATUS;
 
 /* Hardware Error event */
 typedef struct  hci_event_hw_err_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     hw_err_code;
+    u8 event_code;
+    u8 param_len;
+    u8 hw_err_code;
 } POSTPACK HCI_EVENT_HW_ERR;
 
-/* Flush occured event */
+/* Flush occurred event */
 /* Qos Violation event */
 typedef struct  hci_event_handle_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT16    handle;
+    u8 event_code;
+    u8 param_len;
+    u16 handle;
 } POSTPACK HCI_EVENT_FLUSH_OCCRD,
            HCI_EVENT_QOS_VIOLATION;
 
 /* Loopback command event */
 typedef struct hci_loopback_cmd_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     params[252];
+    u8 event_code;
+    u8 param_len;
+    u8 params[252];
 } POSTPACK HCI_EVENT_LOOPBACK_CMD;
 
 /* Data buffer overflow event */
 typedef struct  hci_data_buf_overflow_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     link_type;
+    u8 event_code;
+    u8 param_len;
+    u8 link_type;
 } POSTPACK  HCI_EVENT_DATA_BUF_OVERFLOW;
 
 /* Enhanced Flush complete event */
 typedef struct hci_enhanced_flush_complt_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT16    hdl;
+    u8 event_code;
+    u8 param_len;
+    u16 hdl;
 } POSTPACK  HCI_EVENT_ENHANCED_FLUSH_COMPLT;
 
 /* Channel select event */
 typedef struct  hci_event_chan_select_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     phy_link_hdl;
+    u8 event_code;
+    u8 param_len;
+    u8 phy_link_hdl;
 } POSTPACK HCI_EVENT_CHAN_SELECT;
 
 /* Physical Link Complete event */
 typedef struct  hci_event_phy_link_complete_event_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     phy_link_hdl;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 phy_link_hdl;
 } POSTPACK HCI_EVENT_PHY_LINK_COMPLETE;
 
 /* Logical Link complete event */
 typedef struct hci_event_logical_link_complete_event_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT16    logical_link_hdl;
-    A_UINT8     phy_hdl;
-    A_UINT8     tx_flow_id;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u16 logical_link_hdl;
+    u8 phy_hdl;
+    u8 tx_flow_id;
 } POSTPACK HCI_EVENT_LOGICAL_LINK_COMPLETE_EVENT;
 
 /* Disconnect Logical Link complete event */
 typedef struct hci_event_disconnect_logical_link_event_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT16    logical_link_hdl;
-    A_UINT8     reason;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u16 logical_link_hdl;
+    u8 reason;
 } POSTPACK HCI_EVENT_DISCONNECT_LOGICAL_LINK_EVENT;
 
 /* Disconnect Physical Link complete event */
 typedef struct hci_event_disconnect_phy_link_complete_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     phy_link_hdl;
-    A_UINT8     reason;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 phy_link_hdl;
+    u8 reason;
 } POSTPACK HCI_EVENT_DISCONNECT_PHY_LINK_COMPLETE;
 
 typedef struct hci_event_physical_link_loss_early_warning_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     phy_hdl;
-    A_UINT8     reason;
+    u8 event_code;
+    u8 param_len;
+    u8 phy_hdl;
+    u8 reason;
 } POSTPACK HCI_EVENT_PHY_LINK_LOSS_EARLY_WARNING;
 
 typedef struct hci_event_physical_link_recovery_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     phy_hdl;
+    u8 event_code;
+    u8 param_len;
+    u8 phy_hdl;
 } POSTPACK HCI_EVENT_PHY_LINK_RECOVERY;
 
 
 /* Flow spec modify complete event */
 /* Flush event */
 typedef struct hci_event_status_handle_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT16    handle;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u16 handle;
 } POSTPACK HCI_EVENT_FLOW_SPEC_MODIFY,
            HCI_EVENT_FLUSH;
 
 
 /* Num of completed data blocks event */
 typedef struct hci_event_num_of_compl_data_blks_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT16    num_data_blks;
-    A_UINT8     num_handles;
-    A_UINT8     params[255];
+    u8 event_code;
+    u8 param_len;
+    u16 num_data_blks;
+    u8 num_handles;
+    u8 params[255];
 } POSTPACK HCI_EVENT_NUM_COMPL_DATA_BLKS;
 
 /* Short range mode change complete event */
 typedef struct  hci_srm_cmpl_t {
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     phy_link;
-    A_UINT8     state;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 phy_link;
+    u8 state;
 } POSTPACK HCI_EVENT_SRM_COMPL;
 
 typedef struct hci_event_amp_status_change_t{
-    A_UINT8     event_code;
-    A_UINT8     param_len;
-    A_UINT8     status;
-    A_UINT8     amp_status;
+    u8 event_code;
+    u8 param_len;
+    u8 status;
+    u8 amp_status;
 } POSTPACK HCI_EVENT_AMP_STATUS_CHANGE;
 
 /*============== Event definitions end =========================== */
 
 
 typedef struct  local_amp_info_resp_t {
-    A_UINT8     status;
-    A_UINT8     amp_status;
-    A_UINT32    total_bw;           /* kbps */
-    A_UINT32    max_guranteed_bw;   /* kbps */
-    A_UINT32    min_latency;
-    A_UINT32    max_pdu_size;
-    A_UINT8     amp_type;
-    A_UINT16    pal_capabilities;
-    A_UINT16    amp_assoc_len;
-    A_UINT32    max_flush_timeout;  /* in ms */
-    A_UINT32    be_flush_timeout;   /* in ms */
+    u8 status;
+    u8 amp_status;
+    u32 total_bw;           /* kbps */
+    u32 max_guranteed_bw;   /* kbps */
+    u32 min_latency;
+    u32 max_pdu_size;
+    u8 amp_type;
+    u16 pal_capabilities;
+    u16 amp_assoc_len;
+    u32 max_flush_timeout;  /* in ms */
+    u32 be_flush_timeout;   /* in ms */
 } POSTPACK  LOCAL_AMP_INFO;
 
 typedef struct  amp_assoc_cmd_resp_t{
-    A_UINT8     status;
-    A_UINT8     phy_hdl;
-    A_UINT16    amp_assoc_len;
-    A_UINT8     amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
+    u8 status;
+    u8 phy_hdl;
+    u16 amp_assoc_len;
+    u8 amp_assoc_frag[AMP_ASSOC_MAX_FRAG_SZ];
 }POSTPACK AMP_ASSOC_CMD_RESP;
 
 
@@ -618,64 +618,64 @@
 /* Following are event return parameters.. part of HCI events 
  */
 typedef struct  timeout_read_t {
-    A_UINT8     status;
-    A_UINT16    timeout;
+    u8 status;
+    u16 timeout;
 }POSTPACK TIMEOUT_INFO;
 
 typedef struct  link_supervision_timeout_read_t {
-    A_UINT8     status;
-    A_UINT16    hdl;
-    A_UINT16    timeout;
+    u8 status;
+    u16 hdl;
+    u16 timeout;
 }POSTPACK LINK_SUPERVISION_TIMEOUT_INFO;
 
 typedef struct  status_hdl_t {
-    A_UINT8     status;
-    A_UINT16    hdl;
+    u8 status;
+    u16 hdl;
 }POSTPACK INFO_STATUS_HDL;
 
 typedef struct write_remote_amp_assoc_t{
-    A_UINT8     status;
-    A_UINT8     hdl;
+    u8 status;
+    u8 hdl;
 }POSTPACK WRITE_REMOTE_AMP_ASSOC_INFO;
 
 typedef struct  read_loc_info_t {
-    A_UINT8             status;
+    u8 status;
     LOCATION_DATA_CFG   loc;
 }POSTPACK READ_LOC_INFO;
 
 typedef struct  read_flow_ctrl_mode_t {
-    A_UINT8     status;
-    A_UINT8     mode;
+    u8 status;
+    u8 mode;
 }POSTPACK READ_FLWCTRL_INFO;
 
 typedef struct  read_data_blk_size_t {
-    A_UINT8     status;
-    A_UINT16    max_acl_data_pkt_len;
-    A_UINT16    data_block_len;
-    A_UINT16    total_num_data_blks;
+    u8 status;
+    u16 max_acl_data_pkt_len;
+    u16 data_block_len;
+    u16 total_num_data_blks;
 }POSTPACK READ_DATA_BLK_SIZE_INFO;
 
 /* Read Link quality info */
 typedef struct link_qual_t {
-    A_UINT8     status;
-    A_UINT16    hdl;
-    A_UINT8     link_qual;
+    u8 status;
+    u16 hdl;
+    u8 link_qual;
 } POSTPACK READ_LINK_QUAL_INFO,
             READ_RSSI_INFO;
 
 typedef struct ll_cancel_resp_t {
-    A_UINT8 status;
-    A_UINT8 phy_link_hdl;
-    A_UINT8 tx_flow_spec_id;
+    u8 status;
+    u8 phy_link_hdl;
+    u8 tx_flow_spec_id;
 } POSTPACK LL_CANCEL_RESP;
 
 typedef struct read_local_ver_info_t {
-    A_UINT8     status;
-    A_UINT8     hci_version;
-    A_UINT16    hci_revision;
-    A_UINT8     pal_version;
-    A_UINT16    manf_name;
-    A_UINT16    pal_sub_ver;
+    u8 status;
+    u8 hci_version;
+    u16 hci_revision;
+    u8 pal_version;
+    u16 manf_name;
+    u16 pal_sub_ver;
 } POSTPACK READ_LOCAL_VER_INFO;
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/AR6002/addrs.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/AR6002/addrs.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/AR6002/addrs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/AR6002/addrs.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,13 +29,13 @@
 
 #if defined(AR6002_REV2)
 #define AR6K_RAM_START 0x00500000
-#define TARG_RAM_OFFSET(vaddr) ((A_UINT32)(vaddr) & 0xfffff)
+#define TARG_RAM_OFFSET(vaddr) ((u32)(vaddr) & 0xfffff)
 #define TARG_RAM_SZ (184*1024)
 #define TARG_ROM_SZ (80*1024)
 #endif
 #if defined(AR6002_REV4) || defined(AR6003)
 #define AR6K_RAM_START 0x00540000
-#define TARG_RAM_OFFSET(vaddr) (((A_UINT32)(vaddr) & 0xfffff) - 0x40000)
+#define TARG_RAM_OFFSET(vaddr) (((u32)(vaddr) & 0xfffff) - 0x40000)
 #define TARG_RAM_SZ (256*1024)
 #define TARG_ROM_SZ (256*1024)
 #endif
@@ -49,7 +49,7 @@
 #define TARG_RAM_ADDRS(byte_offset) AR6K_RAM_ADDR(byte_offset)
 
 #define AR6K_ROM_START 0x004e0000
-#define TARG_ROM_OFFSET(vaddr) (((A_UINT32)(vaddr) & 0x1fffff) - 0xe0000)
+#define TARG_ROM_OFFSET(vaddr) (((u32)(vaddr) & 0x1fffff) - 0xe0000)
 #define AR6K_ROM_ADDR(byte_offset) (AR6K_ROM_START+(byte_offset))
 #define TARG_ROM_ADDRS(byte_offset) AR6K_ROM_ADDR(byte_offset)
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/AR6002/AR6002_regdump.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,28 +29,28 @@
  * This must match the state saved by the target exception handler.
  */
 struct XTensa_exception_frame_s {
-    A_UINT32 xt_pc;
-    A_UINT32 xt_ps;
-    A_UINT32 xt_sar;
-    A_UINT32 xt_vpri;
-    A_UINT32 xt_a2;
-    A_UINT32 xt_a3;
-    A_UINT32 xt_a4;
-    A_UINT32 xt_a5;
-    A_UINT32 xt_exccause;
-    A_UINT32 xt_lcount;
-    A_UINT32 xt_lbeg;
-    A_UINT32 xt_lend;
+    u32 xt_pc;
+    u32 xt_ps;
+    u32 xt_sar;
+    u32 xt_vpri;
+    u32 xt_a2;
+    u32 xt_a3;
+    u32 xt_a4;
+    u32 xt_a5;
+    u32 xt_exccause;
+    u32 xt_lcount;
+    u32 xt_lbeg;
+    u32 xt_lend;
 
-    A_UINT32 epc1, epc2, epc3, epc4;
+    u32 epc1, epc2, epc3, epc4;
 
     /* Extra info to simplify post-mortem stack walkback */
 #define AR6002_REGDUMP_FRAMES 10
     struct {
-        A_UINT32 a0;  /* pc */
-        A_UINT32 a1;  /* sp */
-        A_UINT32 a2;
-        A_UINT32 a3;
+        u32 a0;  /* pc */
+        u32 a1;  /* sp */
+        u32 a2;
+        u32 a3;
     } wb[AR6002_REGDUMP_FRAMES];
 };
 typedef struct XTensa_exception_frame_s CPU_exception_frame_t; 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/athdefs.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/athdefs.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/athdefs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/athdefs.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,54 +31,45 @@
 
 /*
  * Generic error codes that can be used by hw, sta, ap, sim, dk
- * and any other environments. Since these are enums, feel free to
- * add any more codes that you need.
+ * and any other environments.
+ * Feel free to add any more non-zero codes that you need.
  */
 
-typedef enum {
-    A_ERROR = -1,               /* Generic error return */
-    A_OK = 0,                   /* success */
-                                /* Following values start at 1 */
-    A_DEVICE_NOT_FOUND,         /* not able to find PCI device */
-    A_NO_MEMORY,                /* not able to allocate memory, not available */
-    A_MEMORY_NOT_AVAIL,         /* memory region is not free for mapping */
-    A_NO_FREE_DESC,             /* no free descriptors available */
-    A_BAD_ADDRESS,              /* address does not match descriptor */
-    A_WIN_DRIVER_ERROR,         /* used in NT_HW version, if problem at init */
-    A_REGS_NOT_MAPPED,          /* registers not correctly mapped */
-    A_EPERM,                    /* Not superuser */
-    A_EACCES,                   /* Access denied */
-    A_ENOENT,                   /* No such entry, search failed, etc. */
-    A_EEXIST,                   /* The object already exists (can't create) */
-    A_EFAULT,                   /* Bad address fault */
-    A_EBUSY,                    /* Object is busy */
-    A_EINVAL,                   /* Invalid parameter */
-    A_EMSGSIZE,                 /* Inappropriate message buffer length */
-    A_ECANCELED,                /* Operation canceled */
-    A_ENOTSUP,                  /* Operation not supported */
-    A_ECOMM,                    /* Communication error on send */
-    A_EPROTO,                   /* Protocol error */
-    A_ENODEV,                   /* No such device */
-    A_EDEVNOTUP,                /* device is not UP */
-    A_NO_RESOURCE,              /* No resources for requested operation */
-    A_HARDWARE,                 /* Hardware failure */
-    A_PENDING,                  /* Asynchronous routine; will send up results la
-ter (typically in callback) */
-    A_EBADCHANNEL,              /* The channel cannot be used */
-    A_DECRYPT_ERROR,            /* Decryption error */
-    A_PHY_ERROR,                /* RX PHY error */
-    A_CONSUMED                  /* Object was consumed */
-} A_STATUS;
-
-#define A_SUCCESS(x)        (x == A_OK)
-#define A_FAILED(x)         (!A_SUCCESS(x))
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef FALSE
-#define FALSE 0
-#endif
+#define A_ERROR			(-1)	/* Generic error return */
+#define A_DEVICE_NOT_FOUND	1	/* not able to find PCI device */
+#define A_NO_MEMORY		2	/* not able to allocate memory,
+					 * not avail#defineable */
+#define A_MEMORY_NOT_AVAIL	3	/* memory region is not free for
+					 * mapping */
+#define A_NO_FREE_DESC		4	/* no free descriptors available */
+#define A_BAD_ADDRESS		5	/* address does not match descriptor */
+#define A_WIN_DRIVER_ERROR	6	/* used in NT_HW version,
+					 * if problem at init */
+#define A_REGS_NOT_MAPPED	7	/* registers not correctly mapped */
+#define A_EPERM			8	/* Not superuser */
+#define A_EACCES		0	/* Access denied */
+#define A_ENOENT		10	/* No such entry, search failed, etc. */
+#define A_EEXIST		11	/* The object already exists
+					 * (can't create) */
+#define A_EFAULT		12	/* Bad address fault */
+#define A_EBUSY			13	/* Object is busy */
+#define A_EINVAL		14	/* Invalid parameter */
+#define A_EMSGSIZE		15	/* Bad message buffer length */
+#define A_ECANCELED		16	/* Operation canceled */
+#define A_ENOTSUP		17	/* Operation not supported */
+#define A_ECOMM			18	/* Communication error on send */
+#define A_EPROTO		19	/* Protocol error */
+#define A_ENODEV		20	/* No such device */
+#define A_EDEVNOTUP		21	/* device is not UP */
+#define A_NO_RESOURCE		22	/* No resources for
+					 * requested operation */
+#define A_HARDWARE		23	/* Hardware failure */
+#define A_PENDING		24	/* Asynchronous routine; will send up
+					 * results later
+					 * (typically in callback) */
+#define A_EBADCHANNEL		25	/* The channel cannot be used */
+#define A_DECRYPT_ERROR		26	/* Decryption error */
+#define A_PHY_ERROR		27	/* RX PHY error */
+#define A_CONSUMED		28	/* Object was consumed */
 
 #endif /* __ATHDEFS_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/bmi_msg.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/bmi_msg.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/bmi_msg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/bmi_msg.h	2011-05-19 00:06:34.000000000 -0400
@@ -65,7 +65,7 @@
         /*
          * Semantics: Host is done using BMI
          * Request format:
-         *    A_UINT32      command (BMI_DONE)
+         *    u32 command (BMI_DONE)
          * Response format: none
          */
 
@@ -73,21 +73,21 @@
         /*
          * Semantics: Host reads AR6K memory
          * Request format:
-         *    A_UINT32      command (BMI_READ_MEMORY)
-         *    A_UINT32      address
-         *    A_UINT32      length, at most BMI_DATASZ_MAX
+         *    u32 command (BMI_READ_MEMORY)
+         *    u32 address
+         *    u32 length, at most BMI_DATASZ_MAX
          * Response format:
-         *    A_UINT8       data[length]
+         *    u8 data[length]
          */
 
 #define BMI_WRITE_MEMORY                    3
         /*
          * Semantics: Host writes AR6K memory
          * Request format:
-         *    A_UINT32       command (BMI_WRITE_MEMORY)
-         *    A_UINT32      address
-         *    A_UINT32      length, at most BMI_DATASZ_MAX
-         *    A_UINT8       data[length]
+         *    u32 command (BMI_WRITE_MEMORY)
+         *    u32 address
+         *    u32 length, at most BMI_DATASZ_MAX
+         *    u8 data[length]
          * Response format: none
          */
 
@@ -95,19 +95,19 @@
         /*
          * Semantics: Causes AR6K to execute code
          * Request format:
-         *    A_UINT32      command (BMI_EXECUTE)
-         *    A_UINT32      address
-         *    A_UINT32      parameter
+         *    u32 command (BMI_EXECUTE)
+         *    u32 address
+         *    u32 parameter
          * Response format:
-         *    A_UINT32      return value
+         *    u32 return value
          */
 
 #define BMI_SET_APP_START                   5
         /*
          * Semantics: Set Target application starting address
          * Request format:
-         *    A_UINT32      command (BMI_SET_APP_START)
-         *    A_UINT32      address
+         *    u32 command (BMI_SET_APP_START)
+         *    u32 address
          * Response format: none
          */
 
@@ -115,19 +115,19 @@
         /*
          * Semantics: Read a 32-bit Target SOC register.
          * Request format:
-         *    A_UINT32      command (BMI_READ_REGISTER)
-         *    A_UINT32      address
+         *    u32 command (BMI_READ_REGISTER)
+         *    u32 address
          * Response format: 
-         *    A_UINT32      value
+         *    u32 value
          */
 
 #define BMI_WRITE_SOC_REGISTER              7
         /*
          * Semantics: Write a 32-bit Target SOC register.
          * Request format:
-         *    A_UINT32      command (BMI_WRITE_REGISTER)
-         *    A_UINT32      address
-         *    A_UINT32      value
+         *    u32 command (BMI_WRITE_REGISTER)
+         *    u32 address
+         *    u32 value
          *
          * Response format: none
          */
@@ -137,18 +137,18 @@
         /*
          * Semantics: Fetch the 4-byte Target information
          * Request format:
-         *    A_UINT32      command (BMI_GET_TARGET_ID/INFO)
+         *    u32 command (BMI_GET_TARGET_ID/INFO)
          * Response format1 (old firmware):
-         *    A_UINT32      TargetVersionID
+         *    u32 TargetVersionID
          * Response format2 (newer firmware):
-         *    A_UINT32      TARGET_VERSION_SENTINAL
+         *    u32 TARGET_VERSION_SENTINAL
          *    struct bmi_target_info;
          */
 
 PREPACK struct bmi_target_info {
-    A_UINT32 target_info_byte_count; /* size of this structure */
-    A_UINT32 target_ver;             /* Target Version ID */
-    A_UINT32 target_type;            /* Target type */
+    u32 target_info_byte_count; /* size of this structure */
+    u32 target_ver;             /* Target Version ID */
+    u32 target_type;            /* Target type */
 } POSTPACK;
 #define TARGET_VERSION_SENTINAL 0xffffffff
 #define TARGET_TYPE_AR6001 1
@@ -160,14 +160,14 @@
         /*
          * Semantics: Install a ROM Patch.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_INSTALL)
-         *    A_UINT32      Target ROM Address
-         *    A_UINT32      Target RAM Address or Value (depending on Target Type)
-         *    A_UINT32      Size, in bytes
-         *    A_UINT32      Activate? 1-->activate;
+         *    u32 command (BMI_ROMPATCH_INSTALL)
+         *    u32 Target ROM Address
+         *    u32 Target RAM Address or Value (depending on Target Type)
+         *    u32 Size, in bytes
+         *    u32 Activate? 1-->activate;
          *                            0-->install but do not activate
          * Response format:
-         *    A_UINT32      PatchID
+         *    u32 PatchID
          */
 
 #define BMI_ROMPATCH_UNINSTALL             10
@@ -175,8 +175,8 @@
          * Semantics: Uninstall a previously-installed ROM Patch,
          * automatically deactivating, if necessary.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_UNINSTALL)
-         *    A_UINT32      PatchID
+         *    u32 command (BMI_ROMPATCH_UNINSTALL)
+         *    u32 PatchID
          *
          * Response format: none
          */
@@ -185,9 +185,9 @@
         /*
          * Semantics: Activate a list of previously-installed ROM Patches.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_ACTIVATE)
-         *    A_UINT32      rompatch_count
-         *    A_UINT32      PatchID[rompatch_count]
+         *    u32 command (BMI_ROMPATCH_ACTIVATE)
+         *    u32 rompatch_count
+         *    u32 PatchID[rompatch_count]
          *
          * Response format: none
          */
@@ -196,9 +196,9 @@
         /*
          * Semantics: Deactivate a list of active ROM Patches.
          * Request format:
-         *    A_UINT32      command (BMI_ROMPATCH_DEACTIVATE)
-         *    A_UINT32      rompatch_count
-         *    A_UINT32      PatchID[rompatch_count]
+         *    u32 command (BMI_ROMPATCH_DEACTIVATE)
+         *    u32 rompatch_count
+         *    u32 PatchID[rompatch_count]
          *
          * Response format: none
          */
@@ -213,8 +213,8 @@
          * output from the compressed input stream.  This BMI
          * command should be followed by a series of 1 or more
          * BMI_LZ_DATA commands.
-         *    A_UINT32      command (BMI_LZ_STREAM_START)
-         *    A_UINT32      address
+         *    u32 command (BMI_LZ_STREAM_START)
+         *    u32 address
          * Note: Not supported on all versions of ROM firmware.
          */
 
@@ -226,10 +226,10 @@
          * of BMI_LZ_DATA commands are considered part of a single
          * input stream until another BMI_LZ_STREAM_START is issued.
          * Request format:
-         *    A_UINT32      command (BMI_LZ_DATA)
-         *    A_UINT32      length (of compressed data),
+         *    u32 command (BMI_LZ_DATA)
+         *    u32 length (of compressed data),
          *                  at most BMI_DATASZ_MAX
-         *    A_UINT8       CompressedData[length]
+         *    u8 CompressedData[length]
          * Response format: none
          * Note: Not supported on all versions of ROM firmware.
          */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/btcoexGpio.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/btcoexGpio.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/btcoexGpio.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/btcoexGpio.h	2011-05-19 00:06:34.000000000 -0400
@@ -71,8 +71,8 @@
 
 
 
-extern void btcoexDbgPulseWord(A_UINT32 gpioPinMask);
-extern void btcoexDbgPulse(A_UINT32 pin);
+extern void btcoexDbgPulseWord(u32 gpioPinMask);
+extern void btcoexDbgPulse(u32 pin);
 
 #ifdef CONFIG_BTCOEX_ENABLE_GPIO_DEBUG
 #define BTCOEX_DBG_PULSE_WORD(gpioPinMask)  (btcoexDbgPulseWord(gpioPinMask))
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/dbglog.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/dbglog.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/dbglog.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/dbglog.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,7 +44,7 @@
 #define DBGLOG_MODULEID_NUM_MAX          16 /* Upper limit is width of mask */
 
 /*
- * Please ensure that the definition of any new module intrduced is captured
+ * Please ensure that the definition of any new module introduced is captured
  * between the DBGLOG_MODULEID_START and DBGLOG_MODULEID_END defines. The 
  * structure is required for the parser to correctly pick up the values for
  * different modules.
@@ -89,31 +89,31 @@
 
 PREPACK struct dbglog_buf_s {
     struct dbglog_buf_s *next;
-    A_UINT8             *buffer;
-    A_UINT32             bufsize;
-    A_UINT32             length;
-    A_UINT32             count;
-    A_UINT32             free;
+    u8 *buffer;
+    u32 bufsize;
+    u32 length;
+    u32 count;
+    u32 free;
 } POSTPACK;
 
 PREPACK struct dbglog_hdr_s {
     struct dbglog_buf_s *dbuf;
-    A_UINT32             dropped;
+    u32 dropped;
 } POSTPACK;
 
 PREPACK struct dbglog_config_s {
-    A_UINT32                    cfgvalid; /* Mask with valid config bits */
+    u32 cfgvalid; /* Mask with valid config bits */
     union {
         /* TODO: Take care of endianness */
         struct {
-            A_UINT32            mmask:16; /* Mask of modules with logging on */
-            A_UINT32            rep:1; /* Reporting enabled or not */
-            A_UINT32            tsr:3; /* Time stamp resolution. Def: 1 ms */
-            A_UINT32            size:10; /* Report size in number of messages */
-            A_UINT32            reserved:2;
+            u32 mmask:16; /* Mask of modules with logging on */
+            u32 rep:1; /* Reporting enabled or not */
+            u32 tsr:3; /* Time stamp resolution. Def: 1 ms */
+            u32 size:10; /* Report size in number of messages */
+            u32 reserved:2;
         } dbglog_config;
 
-        A_UINT32                value;
+        u32 value;
     } u;
 } POSTPACK;
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/dsetid.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/dsetid.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/dsetid.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/dsetid.h	2011-05-19 00:06:34.000000000 -0400
@@ -81,8 +81,8 @@
  * This allows for patches to be stored in flash.
  */
 PREPACK struct patch_s {
-    A_UINT32 *address;
-    A_UINT32  data;
+    u32 *address;
+    u32 data;
 } POSTPACK ;
 
 /*
@@ -92,23 +92,23 @@
  * patch code.  The "data" in a PATCH_SKIP tells how many
  * bytes of length "patch_s" to skip.
  */
-#define PATCH_SKIP      ((A_UINT32 *)0x00000000)
+#define PATCH_SKIP      ((u32 *)0x00000000)
 
 /*
  * Execute code at the address specified by "data".
  * The address of the patch structure is passed as
  * the one parameter.
  */
-#define PATCH_CODE_ABS  ((A_UINT32 *)0x00000001)
+#define PATCH_CODE_ABS  ((u32 *)0x00000001)
 
 /*
  * Same as PATCH_CODE_ABS, but treat "data" as an
  * offset from the start of the patch word.
  */
-#define PATCH_CODE_REL  ((A_UINT32 *)0x00000002)
+#define PATCH_CODE_REL  ((u32 *)0x00000002)
 
 /* Mark the end of this patch DataSet. */
-#define PATCH_END       ((A_UINT32 *)0xffffffff)
+#define PATCH_END       ((u32 *)0xffffffff)
 
 /*
  * A DataSet which contains a Binary Patch to some other DataSet
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/dset_internal.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/dset_internal.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/dset_internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/dset_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -42,13 +42,13 @@
 typedef PREPACK struct dset_descriptor_s {
   struct dset_descriptor_s  *next;         /* List link. NULL only at the last
                                               descriptor */
-  A_UINT16                   id;           /* Dset ID */
-  A_UINT16                   size;         /* Dset size. */
+  u16 id;           /* Dset ID */
+  u16 size;         /* Dset size. */
   void                      *DataPtr;      /* Pointer to raw data for standard
                                               DataSet or pointer to original
                                               dset_descriptor for patched
                                               DataSet */
-  A_UINT32                   data_type;    /* DSET_TYPE_*, above */
+  u32 data_type;    /* DSET_TYPE_*, above */
 
   void                      *AuxPtr;       /* Additional data that might
                                               needed for data_type. For
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/epping_test.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/epping_test.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/epping_test.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/epping_test.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,7 +30,7 @@
 #endif
 
     /* alignment to 4-bytes */
-#define EPPING_ALIGNMENT_PAD  (((sizeof(HTC_FRAME_HDR) + 3) & (~0x3)) - sizeof(HTC_FRAME_HDR))
+#define EPPING_ALIGNMENT_PAD  (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) - sizeof(struct htc_frame_hdr))
 
 #ifndef A_OFFSETOF
 #define A_OFFSETOF(type,field) (int)(&(((type *)NULL)->field))
@@ -41,28 +41,28 @@
 #define HCI_RSVD_EXPECTED_PKT_TYPE_RECV_OFFSET  7 
   
 typedef PREPACK struct {    
-    A_UINT8     _HCIRsvd[8];           /* reserved for HCI packet header (GMBOX) testing */
-    A_UINT8     StreamEcho_h;          /* stream no. to echo this packet on (filled by host) */
-    A_UINT8     StreamEchoSent_t;      /* stream no. packet was echoed to (filled by target)
+    u8 _HCIRsvd[8];           /* reserved for HCI packet header (GMBOX) testing */
+    u8 StreamEcho_h;          /* stream no. to echo this packet on (filled by host) */
+    u8 StreamEchoSent_t;      /* stream no. packet was echoed to (filled by target)
                                           When echoed: StreamEchoSent_t == StreamEcho_h */
-    A_UINT8     StreamRecv_t;          /* stream no. that target received this packet on (filled by target) */
-    A_UINT8     StreamNo_h;            /* stream number to send on (filled by host) */   
-    A_UINT8     Magic_h[4];            /* magic number to filter for this packet on the host*/
-    A_UINT8     _rsvd[6];              /* reserved fields that must be set to a "reserved" value
+    u8 StreamRecv_t;          /* stream no. that target received this packet on (filled by target) */
+    u8 StreamNo_h;            /* stream number to send on (filled by host) */
+    u8 Magic_h[4];            /* magic number to filter for this packet on the host*/
+    u8 _rsvd[6];              /* reserved fields that must be set to a "reserved" value
                                           since this packet maps to a 14-byte ethernet frame we want 
                                           to make sure ethertype field is set to something unknown */
                                           
-    A_UINT8     _pad[2];               /* padding for alignment */                      
-    A_UINT8     TimeStamp[8];          /* timestamp of packet (host or target) */
-    A_UINT32    HostContext_h;         /* 4 byte host context, target echos this back */
-    A_UINT32    SeqNo;                 /* sequence number (set by host or target) */   
-    A_UINT16    Cmd_h;                 /* ping command (filled by host) */  
-    A_UINT16    CmdFlags_h;            /* optional flags */
-    A_UINT8     CmdBuffer_h[8];        /* buffer for command (host -> target) */
-    A_UINT8     CmdBuffer_t[8];        /* buffer for command (target -> host) */  
-    A_UINT16    DataLength;            /* length of data */
-    A_UINT16    DataCRC;               /* 16 bit CRC of data */
-    A_UINT16    HeaderCRC;             /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */                       
+    u8 _pad[2];               /* padding for alignment */
+    u8 TimeStamp[8];          /* timestamp of packet (host or target) */
+    u32 HostContext_h;         /* 4 byte host context, target echos this back */
+    u32 SeqNo;                 /* sequence number (set by host or target) */
+    u16 Cmd_h;                 /* ping command (filled by host) */
+    u16 CmdFlags_h;            /* optional flags */
+    u8 CmdBuffer_h[8];        /* buffer for command (host -> target) */
+    u8 CmdBuffer_t[8];        /* buffer for command (target -> host) */
+    u16 DataLength;            /* length of data */
+    u16 DataCRC;               /* 16 bit CRC of data */
+    u16 HeaderCRC;             /* header CRC (fields : StreamNo_h to end, minus HeaderCRC) */
 } POSTPACK EPPING_HEADER;
 
 #define EPPING_PING_MAGIC_0               0xAA
@@ -92,14 +92,14 @@
 #define EPPING_CMD_RESET_RECV_CNT       2   /* reset recv count */
 #define EPPING_CMD_CAPTURE_RECV_CNT     3   /* fetch recv count, 4-byte count returned in CmdBuffer_t */
 #define EPPING_CMD_NO_ECHO              4   /* non-echo packet test (tx-only) */
-#define EPPING_CMD_CONT_RX_START        5   /* continous RX packets, parameters are in CmdBuffer_h */
+#define EPPING_CMD_CONT_RX_START        5   /* continuous RX packets, parameters are in CmdBuffer_h */
 #define EPPING_CMD_CONT_RX_STOP         6   /* stop continuous RX packet transmission */
 
     /* test command parameters may be no more than 8 bytes */
 typedef PREPACK struct {    
-    A_UINT16  BurstCnt;       /* number of packets to burst together (for HTC 2.1 testing) */
-    A_UINT16  PacketLength;   /* length of packet to generate including header */      
-    A_UINT16  Flags;          /* flags */
+    u16 BurstCnt;       /* number of packets to burst together (for HTC 2.1 testing) */
+    u16 PacketLength;   /* length of packet to generate including header */
+    u16 Flags;          /* flags */
 
 #define EPPING_CONT_RX_DATA_CRC     (1 << 0)  /* Add CRC to all data */
 #define EPPING_CONT_RX_RANDOM_DATA  (1 << 1)  /* randomize the data pattern */
@@ -107,7 +107,7 @@
 } POSTPACK EPPING_CONT_RX_PARAMS;
 
 #define EPPING_HDR_CRC_OFFSET    A_OFFSETOF(EPPING_HEADER,StreamNo_h)
-#define EPPING_HDR_BYTES_CRC     (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(A_UINT16)))
+#define EPPING_HDR_BYTES_CRC     (sizeof(EPPING_HEADER) - EPPING_HDR_CRC_OFFSET - (sizeof(u16)))
 
 #define HCI_TRANSPORT_STREAM_NUM  16  /* this number is higher than the define WMM AC classes so we
                                          can use this to distinguish packets */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/gmboxif.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/gmboxif.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/gmboxif.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/gmboxif.h	2011-05-19 00:06:34.000000000 -0400
@@ -41,23 +41,23 @@
 
     /* definitions for BT HCI packets */
 typedef PREPACK struct {
-    A_UINT16 Flags_ConnHandle;
-    A_UINT16 Length;
+    u16 Flags_ConnHandle;
+    u16 Length;
 } POSTPACK BT_HCI_ACL_HEADER;
 
 typedef PREPACK struct {
-    A_UINT16 Flags_ConnHandle;
-    A_UINT8  Length;
+    u16 Flags_ConnHandle;
+    u8 Length;
 } POSTPACK BT_HCI_SCO_HEADER;
 
 typedef PREPACK struct {
-    A_UINT16 OpCode;
-    A_UINT8  ParamLength;
+    u16 OpCode;
+    u8 ParamLength;
 } POSTPACK BT_HCI_COMMAND_HEADER;
 
 typedef PREPACK struct {
-    A_UINT8  EventCode;
-    A_UINT8  ParamLength;
+    u8 EventCode;
+    u8 ParamLength;
 } POSTPACK BT_HCI_EVENT_HEADER;
 
 /* MBOX host interrupt signal assignments */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/htc.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/htc.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/htc.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/htc.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
 #define A_OFFSETOF(type,field) (unsigned long)(&(((type *)NULL)->field))
 
 #define ASSEMBLE_UNALIGNED_UINT16(p,highbyte,lowbyte) \
-        (((A_UINT16)(((A_UINT8 *)(p))[(highbyte)])) << 8 | (A_UINT16)(((A_UINT8 *)(p))[(lowbyte)]))
+        (((u16)(((u8 *)(p))[(highbyte)])) << 8 | (u16)(((u8 *)(p))[(lowbyte)]))
         
 /* alignment independent macros (little-endian) to fetch UINT16s or UINT8s from a 
  * structure using only the type and field name.
@@ -43,15 +43,15 @@
 
 #define A_SET_UINT16_FIELD(p,type,field,value) \
 {                                              \
-    ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (A_UINT8)(value);        \
-    ((A_UINT8 *)(p))[A_OFFSETOF(type,field) + 1] = (A_UINT8)((value) >> 8); \
+    ((u8 *)(p))[A_OFFSETOF(type,field)] = (u8)(value);        \
+    ((u8 *)(p))[A_OFFSETOF(type,field) + 1] = (u8)((value) >> 8); \
 }
   
 #define A_GET_UINT8_FIELD(p,type,field) \
-            ((A_UINT8 *)(p))[A_OFFSETOF(type,field)]
+            ((u8 *)(p))[A_OFFSETOF(type,field)]
             
 #define A_SET_UINT8_FIELD(p,type,field,value) \
-    ((A_UINT8 *)(p))[A_OFFSETOF(type,field)] = (value)
+    ((u8 *)(p))[A_OFFSETOF(type,field)] = (value)
 
 /****** DANGER DANGER ***************
  * 
@@ -66,20 +66,20 @@
  */
 
 /* HTC frame header */
-typedef PREPACK struct _HTC_FRAME_HDR{
+PREPACK struct htc_frame_hdr {
         /* do not remove or re-arrange these fields, these are minimally required
          * to take advantage of 4-byte lookaheads in some hardware implementations */
-    A_UINT8   EndpointID;
-    A_UINT8   Flags;
-    A_UINT16  PayloadLen;       /* length of data (including trailer) that follows the header */
+    u8 EndpointID;
+    u8 Flags;
+    u16 PayloadLen;       /* length of data (including trailer) that follows the header */
     
     /***** end of 4-byte lookahead ****/
     
-    A_UINT8   ControlBytes[2];
+    u8 ControlBytes[2];
     
     /* message payload starts after the header */
     
-} POSTPACK HTC_FRAME_HDR;
+} POSTPACK;
 
 /* frame header flags */
 
@@ -94,9 +94,9 @@
 #define HTC_FLAGS_RECV_BUNDLE_CNT_MASK (0xF0)  /* bits 7..4  */
 #define HTC_FLAGS_RECV_BUNDLE_CNT_SHIFT 4
 
-#define HTC_HDR_LENGTH  (sizeof(HTC_FRAME_HDR))
+#define HTC_HDR_LENGTH  (sizeof(struct htc_frame_hdr))
 #define HTC_MAX_TRAILER_LENGTH   255
-#define HTC_MAX_PAYLOAD_LENGTH   (4096 - sizeof(HTC_FRAME_HDR))
+#define HTC_MAX_PAYLOAD_LENGTH   (4096 - sizeof(struct htc_frame_hdr))
 
 /* HTC control message IDs */
 
@@ -110,25 +110,25 @@
          
 /* base message ID header */
 typedef PREPACK struct {
-    A_UINT16 MessageID;    
+    u16 MessageID;
 } POSTPACK HTC_UNKNOWN_MSG;
                                                      
 /* HTC ready message
  * direction : target-to-host  */
 typedef PREPACK struct {
-    A_UINT16  MessageID;    /* ID */
-    A_UINT16  CreditCount;  /* number of credits the target can offer */       
-    A_UINT16  CreditSize;   /* size of each credit */
-    A_UINT8   MaxEndpoints; /* maximum number of endpoints the target has resources for */
-    A_UINT8   _Pad1;
+    u16 MessageID;    /* ID */
+    u16 CreditCount;  /* number of credits the target can offer */
+    u16 CreditSize;   /* size of each credit */
+    u8 MaxEndpoints; /* maximum number of endpoints the target has resources for */
+    u8 _Pad1;
 } POSTPACK HTC_READY_MSG;
 
     /* extended HTC ready message */
 typedef PREPACK struct {
     HTC_READY_MSG   Version2_0_Info;   /* legacy version 2.0 information at the front... */
     /* extended information */
-    A_UINT8         HTCVersion;
-    A_UINT8         MaxMsgsPerHTCBundle;
+    u8 HTCVersion;
+    u8 MaxMsgsPerHTCBundle;
 } POSTPACK HTC_READY_EX_MSG;
 
 #define HTC_VERSION_2P0  0x00  
@@ -139,9 +139,9 @@
 /* connect service
  * direction : host-to-target */
 typedef PREPACK struct {
-    A_UINT16  MessageID;
-    A_UINT16  ServiceID;           /* service ID of the service to connect to */       
-    A_UINT16  ConnectionFlags;     /* connection flags */
+    u16 MessageID;
+    u16 ServiceID;           /* service ID of the service to connect to */
+    u16 ConnectionFlags;     /* connection flags */
 
 #define HTC_CONNECT_FLAGS_REDUCE_CREDIT_DRIBBLE (1 << 2)  /* reduce credit dribbling when 
                                                              the host needs credits */  
@@ -151,8 +151,8 @@
 #define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_THREE_FOURTHS     0x2
 #define HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_UNITY             0x3
                                                              
-    A_UINT8   ServiceMetaLength;   /* length of meta data that follows */
-    A_UINT8   _Pad1;
+    u8 ServiceMetaLength;   /* length of meta data that follows */
+    u8 _Pad1;
     
     /* service-specific meta data starts after the header */
     
@@ -161,29 +161,29 @@
 /* connect response
  * direction : target-to-host */
 typedef PREPACK struct {
-    A_UINT16  MessageID;
-    A_UINT16  ServiceID;            /* service ID that the connection request was made */
-    A_UINT8   Status;               /* service connection status */ 
-    A_UINT8   EndpointID;           /* assigned endpoint ID */
-    A_UINT16  MaxMsgSize;           /* maximum expected message size on this endpoint */
-    A_UINT8   ServiceMetaLength;    /* length of meta data that follows */
-    A_UINT8   _Pad1;               
+    u16 MessageID;
+    u16 ServiceID;            /* service ID that the connection request was made */
+    u8 Status;               /* service connection status */
+    u8 EndpointID;           /* assigned endpoint ID */
+    u16 MaxMsgSize;           /* maximum expected message size on this endpoint */
+    u8 ServiceMetaLength;    /* length of meta data that follows */
+    u8 _Pad1;
     
     /* service-specific meta data starts after the header */
     
 } POSTPACK HTC_CONNECT_SERVICE_RESPONSE_MSG;
 
 typedef PREPACK struct {
-    A_UINT16  MessageID;
+    u16 MessageID;
     /* currently, no other fields */
 } POSTPACK HTC_SETUP_COMPLETE_MSG;
 
     /* extended setup completion message */
 typedef PREPACK struct {
-    A_UINT16  MessageID;
-    A_UINT32  SetupFlags;
-    A_UINT8   MaxMsgsPerBundledRecv;
-    A_UINT8   Rsvd[3];
+    u16 MessageID;
+    u32 SetupFlags;
+    u8 MaxMsgsPerBundledRecv;
+    u8 Rsvd[3];
 } POSTPACK HTC_SETUP_COMPLETE_EX_MSG;
 
 #define HTC_SETUP_COMPLETE_FLAGS_ENABLE_BUNDLE_RECV     (1 << 0)
@@ -204,19 +204,19 @@
 #define HTC_RECORD_LOOKAHEAD_BUNDLE 3
 
 typedef PREPACK struct {
-    A_UINT8 RecordID;     /* Record ID */
-    A_UINT8 Length;       /* Length of record */
+    u8 RecordID;     /* Record ID */
+    u8 Length;       /* Length of record */
 } POSTPACK HTC_RECORD_HDR;
 
 typedef PREPACK struct {
-    A_UINT8 EndpointID;     /* Endpoint that owns these credits */
-    A_UINT8 Credits;        /* credits to report since last report */
+    u8 EndpointID;     /* Endpoint that owns these credits */
+    u8 Credits;        /* credits to report since last report */
 } POSTPACK HTC_CREDIT_REPORT;
 
 typedef PREPACK struct {    
-    A_UINT8 PreValid;         /* pre valid guard */
-    A_UINT8 LookAhead[4];     /* 4 byte lookahead */
-    A_UINT8 PostValid;        /* post valid guard */
+    u8 PreValid;         /* pre valid guard */
+    u8 LookAhead[4];     /* 4 byte lookahead */
+    u8 PostValid;        /* post valid guard */
     
    /* NOTE: the LookAhead array is guarded by a PreValid and Post Valid guard bytes.
     * The PreValid bytes must equal the inverse of the PostValid byte */
@@ -224,7 +224,7 @@
 } POSTPACK HTC_LOOKAHEAD_REPORT;
 
 typedef PREPACK struct {    
-    A_UINT8 LookAhead[4];     /* 4 byte lookahead */    
+    u8 LookAhead[4];     /* 4 byte lookahead */
 } POSTPACK HTC_BUNDLED_LOOKAHEAD_REPORT;
 
 #ifndef ATH_TARGET
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/ini_dset.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/ini_dset.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/ini_dset.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/ini_dset.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,7 +31,7 @@
  */
 typedef enum {
 #if defined(AR6002_REV4) || defined(AR6003)
-/* Add these definitions for compatability  */
+/* Add these definitions for compatibility  */
 #define WHAL_INI_DATA_ID_BB_RFGAIN_LNA1 WHAL_INI_DATA_ID_BB_RFGAIN
 #define WHAL_INI_DATA_ID_BB_RFGAIN_LNA2 WHAL_INI_DATA_ID_BB_RFGAIN
     WHAL_INI_DATA_ID_NULL               =0,
@@ -74,9 +74,9 @@
 } WHAL_INI_DATA_ID;
 
 typedef PREPACK struct {
-    A_UINT16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common
-    A_UINT16 offset;
-    A_UINT32 newValue;
+    u16 freqIndex; // 1 - A mode 2 - B or G mode 0 - common
+    u16 offset;
+    u32 newValue;
 } POSTPACK INI_DSET_REG_OVERRIDE;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/pkt_log.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/pkt_log.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/pkt_log.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/pkt_log.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,11 +31,11 @@
 /* Pkt log info */
 typedef PREPACK struct pkt_log_t {
     struct info_t {
-        A_UINT16    st;
-        A_UINT16    end;
-        A_UINT16    cur;
+        u16 st;
+        u16 end;
+        u16 cur;
     }info[4096];
-    A_UINT16    last_idx;
+    u16 last_idx;
 }POSTPACK PACKET_LOG;
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/regdump.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/regdump.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/regdump.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/regdump.h	2011-05-19 00:06:34.000000000 -0400
@@ -42,10 +42,10 @@
  * the diagnostic window.
  */
 PREPACK struct register_dump_s {
-    A_UINT32 target_id;               /* Target ID */
-    A_UINT32 assline;                 /* Line number (if assertion failure) */
-    A_UINT32 pc;                      /* Program Counter at time of exception */
-    A_UINT32 badvaddr;                /* Virtual address causing exception */
+    u32 target_id;               /* Target ID */
+    u32 assline;                 /* Line number (if assertion failure) */
+    u32 pc;                      /* Program Counter at time of exception */
+    u32 badvaddr;                /* Virtual address causing exception */
     CPU_exception_frame_t exc_frame;  /* CPU-specific exception info */
 
     /* Could copy top of stack here, too.... */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/regulatory/reg_dbschema.h	2011-05-19 00:06:34.000000000 -0400
@@ -124,12 +124,12 @@
  * instance of table).
  */
 typedef PREPACK struct dbMasterTable_t {    /* Hold ptrs to Table data structures */
-    A_UCHAR     numOfEntries;
-    A_CHAR      entrySize;      /* Entry size per table row */
-    A_CHAR      searchType;     /* Index based access or key based */
-    A_CHAR      reserved[3];    /* for alignment */
-    A_UINT16    tableSize;      /* Size of this table */
-    A_CHAR      *dataPtr;       /* Ptr to the actual Table */
+    u8     numOfEntries;
+    char entrySize;      /* Entry size per table row */
+    char searchType;     /* Index based access or key based */
+    char reserved[3];    /* for alignment */
+    u16 tableSize;      /* Size of this table */
+    char *dataPtr;       /* Ptr to the actual Table */
 } POSTPACK dbMasterTable;    /* Master table - table of tables */
 
 
@@ -145,22 +145,22 @@
 #define BMZERO {0,0}    /* BMLEN zeros */
 
 #define BM(_fa, _fb, _fc, _fd, _fe, _ff, _fg, _fh) \
-      {((((_fa >= 0) && (_fa < 32)) ? (((A_UINT32) 1) << _fa) : 0) | \
-    (((_fb >= 0) && (_fb < 32)) ? (((A_UINT32) 1) << _fb) : 0) | \
-    (((_fc >= 0) && (_fc < 32)) ? (((A_UINT32) 1) << _fc) : 0) | \
-    (((_fd >= 0) && (_fd < 32)) ? (((A_UINT32) 1) << _fd) : 0) | \
-    (((_fe >= 0) && (_fe < 32)) ? (((A_UINT32) 1) << _fe) : 0) | \
-    (((_ff >= 0) && (_ff < 32)) ? (((A_UINT32) 1) << _ff) : 0) | \
-    (((_fg >= 0) && (_fg < 32)) ? (((A_UINT32) 1) << _fg) : 0) | \
-    (((_fh >= 0) && (_fh < 32)) ? (((A_UINT32) 1) << _fh) : 0)), \
-       ((((_fa > 31) && (_fa < 64)) ? (((A_UINT32) 1) << (_fa - 32)) : 0) | \
-        (((_fb > 31) && (_fb < 64)) ? (((A_UINT32) 1) << (_fb - 32)) : 0) | \
-        (((_fc > 31) && (_fc < 64)) ? (((A_UINT32) 1) << (_fc - 32)) : 0) | \
-        (((_fd > 31) && (_fd < 64)) ? (((A_UINT32) 1) << (_fd - 32)) : 0) | \
-        (((_fe > 31) && (_fe < 64)) ? (((A_UINT32) 1) << (_fe - 32)) : 0) | \
-        (((_ff > 31) && (_ff < 64)) ? (((A_UINT32) 1) << (_ff - 32)) : 0) | \
-        (((_fg > 31) && (_fg < 64)) ? (((A_UINT32) 1) << (_fg - 32)) : 0) | \
-        (((_fh > 31) && (_fh < 64)) ? (((A_UINT32) 1) << (_fh - 32)) : 0))}
+      {((((_fa >= 0) && (_fa < 32)) ? (((u32) 1) << _fa) : 0) | \
+    (((_fb >= 0) && (_fb < 32)) ? (((u32) 1) << _fb) : 0) | \
+    (((_fc >= 0) && (_fc < 32)) ? (((u32) 1) << _fc) : 0) | \
+    (((_fd >= 0) && (_fd < 32)) ? (((u32) 1) << _fd) : 0) | \
+    (((_fe >= 0) && (_fe < 32)) ? (((u32) 1) << _fe) : 0) | \
+    (((_ff >= 0) && (_ff < 32)) ? (((u32) 1) << _ff) : 0) | \
+    (((_fg >= 0) && (_fg < 32)) ? (((u32) 1) << _fg) : 0) | \
+    (((_fh >= 0) && (_fh < 32)) ? (((u32) 1) << _fh) : 0)), \
+       ((((_fa > 31) && (_fa < 64)) ? (((u32) 1) << (_fa - 32)) : 0) | \
+        (((_fb > 31) && (_fb < 64)) ? (((u32) 1) << (_fb - 32)) : 0) | \
+        (((_fc > 31) && (_fc < 64)) ? (((u32) 1) << (_fc - 32)) : 0) | \
+        (((_fd > 31) && (_fd < 64)) ? (((u32) 1) << (_fd - 32)) : 0) | \
+        (((_fe > 31) && (_fe < 64)) ? (((u32) 1) << (_fe - 32)) : 0) | \
+        (((_ff > 31) && (_ff < 64)) ? (((u32) 1) << (_ff - 32)) : 0) | \
+        (((_fg > 31) && (_fg < 64)) ? (((u32) 1) << (_fg - 32)) : 0) | \
+        (((_fh > 31) && (_fh < 64)) ? (((u32) 1) << (_fh - 32)) : 0))}
 
 
 /*
@@ -169,12 +169,12 @@
  */
 
 typedef PREPACK struct reg_dmn_pair_mapping {
-    A_UINT16 regDmnEnum;    /* 16 bit reg domain pair */
-    A_UINT16 regDmn5GHz;    /* 5GHz reg domain */
-    A_UINT16 regDmn2GHz;    /* 2GHz reg domain */
-    A_UINT8  flags5GHz;     /* Requirements flags (AdHoc disallow etc) */
-    A_UINT8  flags2GHz;     /* Requirements flags (AdHoc disallow etc) */
-    A_UINT32 pscanMask;     /* Passive Scan flags which can override unitary domain passive scan
+    u16 regDmnEnum;    /* 16 bit reg domain pair */
+    u16 regDmn5GHz;    /* 5GHz reg domain */
+    u16 regDmn2GHz;    /* 2GHz reg domain */
+    u8 flags5GHz;     /* Requirements flags (AdHoc disallow etc) */
+    u8 flags2GHz;     /* Requirements flags (AdHoc disallow etc) */
+    u32 pscanMask;     /* Passive Scan flags which can override unitary domain passive scan
                                    flags.  This value is used as a mask on the unitary flags*/
 } POSTPACK REG_DMN_PAIR_MAPPING;
 
@@ -188,10 +188,10 @@
 #define MCS_HT40_G_NO  (0 << 3)
 
 typedef PREPACK struct {
-    A_UINT16    countryCode;       
-    A_UINT16    regDmnEnum;
-    A_CHAR      isoName[3];
-    A_CHAR      allowMode;  /* what mode is allowed - bit 0: OFDM; bit 1: MCS_HT20; bit 2: MCS_HT40_A; bit 3: MCS_HT40_G */
+    u16 countryCode;
+    u16 regDmnEnum;
+    char isoName[3];
+    char allowMode;  /* what mode is allowed - bit 0: OFDM; bit 1: MCS_HT20; bit 2: MCS_HT40_A; bit 3: MCS_HT40_G */
 } POSTPACK COUNTRY_CODE_TO_ENUM_RD;
 
 /* lower 16 bits of ht40ChanMask */
@@ -209,29 +209,29 @@
 #define FREQ_QUARTER_RATE   0x20000
 
 typedef PREPACK struct RegDmnFreqBand {
-    A_UINT16    lowChannel;     /* Low channel center in MHz */
-    A_UINT16    highChannel;    /* High Channel center in MHz */
-    A_UINT8     power;          /* Max power (dBm) for channel range */
-    A_UINT8     channelSep;     /* Channel separation within the band */
-    A_UINT8     useDfs;         /* Use DFS in the RegDomain if corresponding bit is set */
-    A_UINT8     mode;           /* Mode of operation */
-    A_UINT32    usePassScan;    /* Use Passive Scan in the RegDomain if corresponding bit is set */
-    A_UINT32    ht40ChanMask;   /* lower 16 bits: indicate which frequencies in the block is HT40 capable 
+    u16 lowChannel;     /* Low channel center in MHz */
+    u16 highChannel;    /* High Channel center in MHz */
+    u8 power;          /* Max power (dBm) for channel range */
+    u8 channelSep;     /* Channel separation within the band */
+    u8 useDfs;         /* Use DFS in the RegDomain if corresponding bit is set */
+    u8 mode;           /* Mode of operation */
+    u32 usePassScan;    /* Use Passive Scan in the RegDomain if corresponding bit is set */
+    u32 ht40ChanMask;   /* lower 16 bits: indicate which frequencies in the block is HT40 capable
                                    upper 16 bits: what rate (half/quarter) the channel is  */
 } POSTPACK REG_DMN_FREQ_BAND;
 
 
 
 typedef PREPACK struct regDomain {
-    A_UINT16    regDmnEnum;     /* value from EnumRd table */
-    A_UINT8     rdCTL;
-    A_UINT8     maxAntGain;
-    A_UINT8     dfsMask;        /* DFS bitmask for 5Ghz tables */
-    A_UINT8     flags;          /* Requirement flags (AdHoc disallow etc) */
-    A_UINT16    reserved;       /* for alignment */
-    A_UINT32    pscan;          /* Bitmask for passive scan */
-    A_UINT32    chan11a[BMLEN]; /* 64 bit bitmask for channel/band selection */
-    A_UINT32    chan11bg[BMLEN];/* 64 bit bitmask for channel/band selection */
+    u16 regDmnEnum;     /* value from EnumRd table */
+    u8 rdCTL;
+    u8 maxAntGain;
+    u8 dfsMask;        /* DFS bitmask for 5Ghz tables */
+    u8 flags;          /* Requirement flags (AdHoc disallow etc) */
+    u16 reserved;       /* for alignment */
+    u32 pscan;          /* Bitmask for passive scan */
+    u32 chan11a[BMLEN]; /* 64 bit bitmask for channel/band selection */
+    u32 chan11bg[BMLEN];/* 64 bit bitmask for channel/band selection */
 } POSTPACK REG_DOMAIN;
 
 #endif /* __REG_DBSCHEMA_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/targaddrs.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/targaddrs.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/targaddrs.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/targaddrs.h	2011-05-19 00:06:34.000000000 -0400
@@ -83,13 +83,13 @@
      * Pointer to application-defined area, if any.
      * Set by Target application during startup.
      */
-    A_UINT32               hi_app_host_interest;                      /* 0x00 */
+    u32 hi_app_host_interest;                      /* 0x00 */
 
     /* Pointer to register dump area, valid after Target crash. */
-    A_UINT32               hi_failure_state;                          /* 0x04 */
+    u32 hi_failure_state;                          /* 0x04 */
 
     /* Pointer to debug logging header */
-    A_UINT32               hi_dbglog_hdr;                             /* 0x08 */
+    u32 hi_dbglog_hdr;                             /* 0x08 */
 
     /* Indicates whether or not flash is present on Target.
      * NB: flash_is_present indicator is here not just
@@ -99,36 +99,36 @@
      * so that it doesn't get reinitialized with the rest
      * of data.
      */
-    A_UINT32               hi_flash_is_present;                       /* 0x0c */
+    u32 hi_flash_is_present;                       /* 0x0c */
 
     /*
      * General-purpose flag bits, similar to AR6000_OPTION_* flags.
      * Can be used by application rather than by OS.
      */
-    A_UINT32               hi_option_flag;                            /* 0x10 */
+    u32 hi_option_flag;                            /* 0x10 */
 
     /*
      * Boolean that determines whether or not to
      * display messages on the serial port.
      */
-    A_UINT32               hi_serial_enable;                          /* 0x14 */
+    u32 hi_serial_enable;                          /* 0x14 */
 
     /* Start address of Flash DataSet index, if any */
-    A_UINT32               hi_dset_list_head;                         /* 0x18 */
+    u32 hi_dset_list_head;                         /* 0x18 */
 
     /* Override Target application start address */
-    A_UINT32               hi_app_start;                              /* 0x1c */
+    u32 hi_app_start;                              /* 0x1c */
 
     /* Clock and voltage tuning */
-    A_UINT32               hi_skip_clock_init;                        /* 0x20 */
-    A_UINT32               hi_core_clock_setting;                     /* 0x24 */
-    A_UINT32               hi_cpu_clock_setting;                      /* 0x28 */
-    A_UINT32               hi_system_sleep_setting;                   /* 0x2c */
-    A_UINT32               hi_xtal_control_setting;                   /* 0x30 */
-    A_UINT32               hi_pll_ctrl_setting_24ghz;                 /* 0x34 */
-    A_UINT32               hi_pll_ctrl_setting_5ghz;                  /* 0x38 */
-    A_UINT32               hi_ref_voltage_trim_setting;               /* 0x3c */
-    A_UINT32               hi_clock_info;                             /* 0x40 */
+    u32 hi_skip_clock_init;                        /* 0x20 */
+    u32 hi_core_clock_setting;                     /* 0x24 */
+    u32 hi_cpu_clock_setting;                      /* 0x28 */
+    u32 hi_system_sleep_setting;                   /* 0x2c */
+    u32 hi_xtal_control_setting;                   /* 0x30 */
+    u32 hi_pll_ctrl_setting_24ghz;                 /* 0x34 */
+    u32 hi_pll_ctrl_setting_5ghz;                  /* 0x38 */
+    u32 hi_ref_voltage_trim_setting;               /* 0x3c */
+    u32 hi_clock_info;                             /* 0x40 */
 
     /*
      * Flash configuration overrides, used only
@@ -136,49 +136,49 @@
      * (When using flash, modify the global variables
      * with equivalent names.)
      */
-    A_UINT32               hi_bank0_addr_value;                       /* 0x44 */
-    A_UINT32               hi_bank0_read_value;                       /* 0x48 */
-    A_UINT32               hi_bank0_write_value;                      /* 0x4c */
-    A_UINT32               hi_bank0_config_value;                     /* 0x50 */
+    u32 hi_bank0_addr_value;                       /* 0x44 */
+    u32 hi_bank0_read_value;                       /* 0x48 */
+    u32 hi_bank0_write_value;                      /* 0x4c */
+    u32 hi_bank0_config_value;                     /* 0x50 */
 
     /* Pointer to Board Data  */
-    A_UINT32               hi_board_data;                             /* 0x54 */
-    A_UINT32               hi_board_data_initialized;                 /* 0x58 */
+    u32 hi_board_data;                             /* 0x54 */
+    u32 hi_board_data_initialized;                 /* 0x58 */
 
-    A_UINT32               hi_dset_RAM_index_table;                   /* 0x5c */
+    u32 hi_dset_RAM_index_table;                   /* 0x5c */
 
-    A_UINT32               hi_desired_baud_rate;                      /* 0x60 */
-    A_UINT32               hi_dbglog_config;                          /* 0x64 */
-    A_UINT32               hi_end_RAM_reserve_sz;                     /* 0x68 */
-    A_UINT32               hi_mbox_io_block_sz;                       /* 0x6c */
+    u32 hi_desired_baud_rate;                      /* 0x60 */
+    u32 hi_dbglog_config;                          /* 0x64 */
+    u32 hi_end_RAM_reserve_sz;                     /* 0x68 */
+    u32 hi_mbox_io_block_sz;                       /* 0x6c */
 
-    A_UINT32               hi_num_bpatch_streams;                     /* 0x70 -- unused */
-    A_UINT32               hi_mbox_isr_yield_limit;                   /* 0x74 */
+    u32 hi_num_bpatch_streams;                     /* 0x70 -- unused */
+    u32 hi_mbox_isr_yield_limit;                   /* 0x74 */
 
-    A_UINT32               hi_refclk_hz;                              /* 0x78 */
-    A_UINT32               hi_ext_clk_detected;                       /* 0x7c */
-    A_UINT32               hi_dbg_uart_txpin;                         /* 0x80 */
-    A_UINT32               hi_dbg_uart_rxpin;                         /* 0x84 */
-    A_UINT32               hi_hci_uart_baud;                          /* 0x88 */
-    A_UINT32               hi_hci_uart_pin_assignments;               /* 0x8C */
+    u32 hi_refclk_hz;                              /* 0x78 */
+    u32 hi_ext_clk_detected;                       /* 0x7c */
+    u32 hi_dbg_uart_txpin;                         /* 0x80 */
+    u32 hi_dbg_uart_rxpin;                         /* 0x84 */
+    u32 hi_hci_uart_baud;                          /* 0x88 */
+    u32 hi_hci_uart_pin_assignments;               /* 0x8C */
         /* NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts pin */
-    A_UINT32               hi_hci_uart_baud_scale_val;                /* 0x90 */
-    A_UINT32               hi_hci_uart_baud_step_val;                 /* 0x94 */
+    u32 hi_hci_uart_baud_scale_val;                /* 0x90 */
+    u32 hi_hci_uart_baud_step_val;                 /* 0x94 */
 
-    A_UINT32               hi_allocram_start;                         /* 0x98 */
-    A_UINT32               hi_allocram_sz;                            /* 0x9c */
-    A_UINT32               hi_hci_bridge_flags;                       /* 0xa0 */
-    A_UINT32               hi_hci_uart_support_pins;                  /* 0xa4 */
+    u32 hi_allocram_start;                         /* 0x98 */
+    u32 hi_allocram_sz;                            /* 0x9c */
+    u32 hi_hci_bridge_flags;                       /* 0xa0 */
+    u32 hi_hci_uart_support_pins;                  /* 0xa4 */
         /* NOTE: byte [0] = RESET pin (bit 7 is polarity), bytes[1]..bytes[3] are for future use */
-    A_UINT32               hi_hci_uart_pwr_mgmt_params;               /* 0xa8 */
+    u32 hi_hci_uart_pwr_mgmt_params;               /* 0xa8 */
         /* 0xa8 - [0]: 1 = enable, 0 = disable
          *        [1]: 0 = UART FC active low, 1 = UART FC active high
          * 0xa9 - [7:0]: wakeup timeout in ms
          * 0xaa, 0xab - [15:0]: idle timeout in ms
          */       
     /* Pointer to extended board Data  */
-    A_UINT32               hi_board_ext_data;                         /* 0xac */
-    A_UINT32               hi_board_ext_data_initialized;             /* 0xb0 */
+    u32 hi_board_ext_data;                         /* 0xac */
+    u32 hi_board_ext_data_initialized;             /* 0xb0 */
 } POSTPACK;
 
 /* Bits defined in hi_option_flag */
@@ -207,10 +207,10 @@
  * Example: target_addr = AR6002_HOST_INTEREST_ITEM_ADDRESS(hi_board_data);
  */
 #define AR6002_HOST_INTEREST_ITEM_ADDRESS(item) \
-    (A_UINT32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
+    (u32)((unsigned long)&((((struct host_interest_s *)(AR6002_HOST_INTEREST_ADDRESS))->item)))
 
 #define AR6003_HOST_INTEREST_ITEM_ADDRESS(item) \
-    (A_UINT32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item)))
+    (u32)((unsigned long)&((((struct host_interest_s *)(AR6003_HOST_INTEREST_ADDRESS))->item)))
 
 #define HOST_INTEREST_DBGLOG_IS_ENABLED() \
         (!(HOST_INTEREST->hi_option_flag & HI_OPTION_DISABLE_DBGLOG))
@@ -233,7 +233,7 @@
 #define AR6003_BOARD_EXT_DATA_ADDRESS     0x57E600
 
 
-/* # of A_UINT32 entries in targregs, used by DIAG_FETCH_TARG_REGS */
+/* # of u32 entries in targregs, used by DIAG_FETCH_TARG_REGS */
 #define AR6003_FETCH_TARG_REGS_COUNT 64
 
 #endif /* !__ASSEMBLER__ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/testcmd.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/testcmd.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/testcmd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/testcmd.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,8 +43,8 @@
     PN15_PATTERN
 }TX_DATA_PATTERN;
 
-/* Continous tx
-   mode : TCMD_CONT_TX_OFF - Disabling continous tx
+/* Continuous tx
+   mode : TCMD_CONT_TX_OFF - Disabling continuous tx
           TCMD_CONT_TX_SINE - Enable continuous unmodulated tx
           TCMD_CONT_TX_FRAME- Enable continuous modulated tx
    freq : Channel freq in Mhz. (e.g 2412 for channel 1 in 11 g)
@@ -82,20 +82,20 @@
 } TCMD_WLAN_MODE;
 
 typedef PREPACK struct {
-    A_UINT32                testCmdId;
-    A_UINT32                mode;
-    A_UINT32                freq;
-    A_UINT32                dataRate;
-    A_INT32                 txPwr;
-    A_UINT32                antenna;
-    A_UINT32                enANI;
-    A_UINT32                scramblerOff;
-    A_UINT32                aifsn;
-    A_UINT16                pktSz;
-    A_UINT16                txPattern;
-    A_UINT32                shortGuard;
-    A_UINT32                numPackets;
-    A_UINT32                wlanMode;
+    u32 testCmdId;
+    u32 mode;
+    u32 freq;
+    u32 dataRate;
+    s32 txPwr;
+    u32 antenna;
+    u32 enANI;
+    u32 scramblerOff;
+    u32 aifsn;
+    u16 pktSz;
+    u16 txPattern;
+    u32 shortGuard;
+    u32 numPackets;
+    u32 wlanMode;
 } POSTPACK TCMD_CONT_TX;
 
 #define TCMD_TXPATTERN_ZERONE                 0x1
@@ -124,29 +124,29 @@
 } TCMD_CONT_RX_ACT;
 
 typedef PREPACK struct {
-    A_UINT32         testCmdId;
-    A_UINT32        act;
-    A_UINT32        enANI;
+    u32 testCmdId;
+    u32 act;
+    u32 enANI;
     PREPACK union {
         struct PREPACK TCMD_CONT_RX_PARA {
-            A_UINT32    freq;
-            A_UINT32    antenna;
-            A_UINT32    wlanMode;
+            u32 freq;
+            u32 antenna;
+            u32 wlanMode;
         } POSTPACK para;
         struct PREPACK TCMD_CONT_RX_REPORT {
-            A_UINT32    totalPkt;
-            A_INT32     rssiInDBm;
-            A_UINT32    crcErrPkt;
-            A_UINT32    secErrPkt;
-            A_UINT16    rateCnt[TCMD_MAX_RATES];
-            A_UINT16    rateCntShortGuard[TCMD_MAX_RATES];
+            u32 totalPkt;
+            s32 rssiInDBm;
+            u32 crcErrPkt;
+            u32 secErrPkt;
+            u16 rateCnt[TCMD_MAX_RATES];
+            u16 rateCntShortGuard[TCMD_MAX_RATES];
         } POSTPACK report;
         struct PREPACK TCMD_CONT_RX_MAC {
-            A_UCHAR    addr[ATH_MAC_LEN];
+            u8    addr[ATH_MAC_LEN];
         } POSTPACK mac;
         struct PREPACK TCMD_CONT_RX_ANT_SWITCH_TABLE {
-            A_UINT32                antswitch1;
-            A_UINT32                antswitch2;
+            u32 antswitch1;
+            u32 antswitch2;
         }POSTPACK antswitchtable;
     } POSTPACK u;
 } POSTPACK TCMD_CONT_RX;
@@ -162,8 +162,8 @@
 } TCMD_PM_MODE;
 
 typedef PREPACK struct {
-    A_UINT32  testCmdId;
-    A_UINT32  mode;
+    u32 testCmdId;
+    u32 mode;
 } POSTPACK TCMD_PM;
 
 typedef enum {
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wlan_dset.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wlan_dset.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wlan_dset.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wlan_dset.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,9 +25,9 @@
 
 typedef PREPACK struct wow_config_dset {
 
-    A_UINT8 valid_dset;
-    A_UINT8 gpio_enable;
-    A_UINT16 gpio_pin;
+    u8 valid_dset;
+    u8 gpio_enable;
+    u16 gpio_pin;
 } POSTPACK WOW_CONFIG_DSET;
 
 #endif
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wmi.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wmi.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wmi.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wmi.h	2011-05-19 00:06:34.000000000 -0400
@@ -70,24 +70,24 @@
 #endif
 
 PREPACK struct host_app_area_s {
-    A_UINT32 wmi_protocol_ver;
+    u32 wmi_protocol_ver;
 } POSTPACK;
 
 /*
  * Data Path
  */
 typedef PREPACK struct {
-    A_UINT8     dstMac[ATH_MAC_LEN];
-    A_UINT8     srcMac[ATH_MAC_LEN];
-    A_UINT16    typeOrLen;
+    u8 dstMac[ATH_MAC_LEN];
+    u8 srcMac[ATH_MAC_LEN];
+    u16 typeOrLen;
 } POSTPACK ATH_MAC_HDR;
 
 typedef PREPACK struct {
-    A_UINT8     dsap;
-    A_UINT8     ssap;
-    A_UINT8     cntl;
-    A_UINT8     orgCode[3];
-    A_UINT16    etherType;
+    u8 dsap;
+    u8 ssap;
+    u8 cntl;
+    u8 orgCode[3];
+    u16 etherType;
 } POSTPACK ATH_LLC_SNAP_HDR;
 
 typedef enum {
@@ -160,8 +160,8 @@
 #define WMI_DATA_HDR_SET_META(h, _v)    ((h)->info2 = ((h)->info2 & ~(WMI_DATA_HDR_META_MASK << WMI_DATA_HDR_META_SHIFT)) | ((_v) << WMI_DATA_HDR_META_SHIFT))
 
 typedef PREPACK struct {
-    A_INT8      rssi;
-    A_UINT8     info;               /* usage of 'info' field(8-bit):
+    s8 rssi;
+    u8 info;               /* usage of 'info' field(8-bit):
                                      *  b1:b0       - WMI_MSG_TYPE
                                      *  b4:b3:b2    - UP(tid)
                                      *  b5          - Used in AP mode. More-data in tx dir, PS in rx.
@@ -170,12 +170,12 @@
                                      *                 ACL data(2)
                                      */
 
-    A_UINT16    info2;              /* usage of 'info2' field(16-bit):
+    u16 info2;              /* usage of 'info2' field(16-bit):
                                      * b11:b0       - seq_no
                                      * b12          - A-MSDU?
                                      * b15:b13      - META_DATA_VERSION 0 - 7
                                      */
-    A_UINT16    reserved;
+    u16 reserved;
 } POSTPACK WMI_DATA_HDR;
 
 /*
@@ -195,17 +195,17 @@
 #endif
 
 typedef PREPACK struct {
-    A_UINT8     pktID;           /* The packet ID to identify the tx request */
-    A_UINT8     ratePolicyID;    /* The rate policy to be used for the tx of this frame */
+    u8 pktID;           /* The packet ID to identify the tx request */
+    u8 ratePolicyID;    /* The rate policy to be used for the tx of this frame */
 } POSTPACK WMI_TX_META_V1;
 
 
 #define WMI_CSUM_DIR_TX (0x1)
 #define TX_CSUM_CALC_FILL (0x1)
 typedef PREPACK struct {
-    A_UINT8    csumStart;       /*Offset from start of the WMI header for csum calculation to begin */
-    A_UINT8    csumDest;        /*Offset from start of WMI header where final csum goes*/
-    A_UINT8     csumFlags;    /*number of bytes over which csum is calculated*/
+    u8 csumStart;       /*Offset from start of the WMI header for csum calculation to begin */
+    u8 csumDest;        /*Offset from start of WMI header where final csum goes*/
+    u8 csumFlags;    /*number of bytes over which csum is calculated*/
 } POSTPACK WMI_TX_META_V2;
 
 
@@ -242,17 +242,17 @@
 #endif
 
 typedef PREPACK struct {
-    A_UINT8     status; /* one of WMI_RX_STATUS_... */
-    A_UINT8     rix;    /* rate index mapped to rate at which this packet was received. */
-    A_UINT8     rssi;   /* rssi of packet */
-    A_UINT8     channel;/* rf channel during packet reception */
-    A_UINT16    flags;  /* a combination of WMI_RX_FLAGS_... */
+    u8 status; /* one of WMI_RX_STATUS_... */
+    u8 rix;    /* rate index mapped to rate at which this packet was received. */
+    u8 rssi;   /* rssi of packet */
+    u8 channel;/* rf channel during packet reception */
+    u16 flags;  /* a combination of WMI_RX_FLAGS_... */
 } POSTPACK WMI_RX_META_V1;
 
 #define RX_CSUM_VALID_FLAG (0x1)
 typedef PREPACK struct {
-    A_UINT16    csum;
-    A_UINT8     csumFlags;/* bit 0 set -partial csum valid
+    u16 csum;
+    u8 csumFlags;/* bit 0 set -partial csum valid
                              bit 1 set -test mode */
 } POSTPACK WMI_RX_META_V2;
 
@@ -264,15 +264,15 @@
  * Control Path
  */
 typedef PREPACK struct {
-    A_UINT16    commandId;
+    u16 commandId;
 /*
  * info1 - 16 bits
  * b03:b00 - id
  * b15:b04 - unused
  */
-    A_UINT16    info1;
+    u16 info1;
 
-    A_UINT16    reserved;      /* For alignment */
+    u16 reserved;      /* For alignment */
 } POSTPACK WMI_CMD_HDR;        /* used for commands and events */
 
 /*
@@ -422,17 +422,24 @@
     WMI_AP_SET_11BG_RATESET_CMDID,
     WMI_SET_PMK_CMDID,
     WMI_MCAST_FILTER_CMDID,
-	/* COEX CMDID AR6003*/
-	WMI_SET_BTCOEX_FE_ANT_CMDID,
-	WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
-	WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
-	WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
-	WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
-	WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
-	WMI_SET_BTCOEX_DEBUG_CMDID,
-	WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
-	WMI_GET_BTCOEX_STATS_CMDID,
-	WMI_GET_BTCOEX_CONFIG_CMDID,
+    /* COEX CMDID AR6003*/
+    WMI_SET_BTCOEX_FE_ANT_CMDID,
+    WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
+    WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
+    WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
+    WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
+    WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
+    WMI_SET_BTCOEX_DEBUG_CMDID,
+    WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
+    WMI_GET_BTCOEX_STATS_CMDID,
+    WMI_GET_BTCOEX_CONFIG_CMDID,
+    WMI_GET_PMK_CMDID,
+    WMI_SET_PASSPHRASE_CMDID,
+    WMI_ENABLE_WAC_CMDID,
+    WMI_WAC_SCAN_REPLY_CMDID,
+    WMI_WAC_CTRL_REQ_CMDID,
+    WMI_SET_DIV_PARAMS_CMDID,
+    WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
 } WMI_COMMAND_ID;
 
 /*
@@ -522,34 +529,41 @@
 #define DEFAULT_CONNECT_CTRL_FLAGS    (CONNECT_CSA_FOLLOW_BSS)
 
 typedef PREPACK struct {
-    A_UINT8     networkType;
-    A_UINT8     dot11AuthMode;
-    A_UINT8     authMode;
-    A_UINT8     pairwiseCryptoType;
-    A_UINT8     pairwiseCryptoLen;
-    A_UINT8     groupCryptoType;
-    A_UINT8     groupCryptoLen;
-    A_UINT8     ssidLength;
-    A_UCHAR     ssid[WMI_MAX_SSID_LEN];
-    A_UINT16    channel;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT32    ctrl_flags;
+    u8 networkType;
+    u8 dot11AuthMode;
+    u8 authMode;
+    u8 pairwiseCryptoType;
+    u8 pairwiseCryptoLen;
+    u8 groupCryptoType;
+    u8 groupCryptoLen;
+    u8 ssidLength;
+    u8     ssid[WMI_MAX_SSID_LEN];
+    u16 channel;
+    u8 bssid[ATH_MAC_LEN];
+    u32 ctrl_flags;
 } POSTPACK WMI_CONNECT_CMD;
 
 /*
  * WMI_RECONNECT_CMDID
  */
 typedef PREPACK struct {
-    A_UINT16    channel;                    /* hint */
-    A_UINT8     bssid[ATH_MAC_LEN];         /* mandatory if set */
+    u16 channel;                    /* hint */
+    u8 bssid[ATH_MAC_LEN];         /* mandatory if set */
 } POSTPACK WMI_RECONNECT_CMD;
 
 #define WMI_PMK_LEN     32
 typedef PREPACK struct {
-    A_UINT8 pmk[WMI_PMK_LEN];
+    u8 pmk[WMI_PMK_LEN];
 } POSTPACK WMI_SET_PMK_CMD;
 
 /*
+ * WMI_SET_EXCESS_TX_RETRY_THRES_CMDID
+ */
+typedef PREPACK struct {
+    A_UINT32 threshold;
+} POSTPACK WMI_SET_EXCESS_TX_RETRY_THRES_CMD;
+
+/*
  * WMI_ADD_CIPHER_KEY_CMDID
  */
 typedef enum {
@@ -572,21 +586,21 @@
 #define KEY_OP_VALID_MASK   0x03
 
 typedef PREPACK struct {
-    A_UINT8     keyIndex;
-    A_UINT8     keyType;
-    A_UINT8     keyUsage;           /* KEY_USAGE */
-    A_UINT8     keyLength;
-    A_UINT8     keyRSC[8];          /* key replay sequence counter */
-    A_UINT8     key[WMI_MAX_KEY_LEN];
-    A_UINT8     key_op_ctrl;       /* Additional Key Control information */
-    A_UINT8    key_macaddr[ATH_MAC_LEN];
+    u8 keyIndex;
+    u8 keyType;
+    u8 keyUsage;           /* KEY_USAGE */
+    u8 keyLength;
+    u8 keyRSC[8];          /* key replay sequence counter */
+    u8 key[WMI_MAX_KEY_LEN];
+    u8 key_op_ctrl;       /* Additional Key Control information */
+    u8 key_macaddr[ATH_MAC_LEN];
 } POSTPACK WMI_ADD_CIPHER_KEY_CMD;
 
 /*
  * WMI_DELETE_CIPHER_KEY_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     keyIndex;
+    u8 keyIndex;
 } POSTPACK WMI_DELETE_CIPHER_KEY_CMD;
 
 #define WMI_KRK_LEN     16
@@ -594,7 +608,7 @@
  * WMI_ADD_KRK_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     krk[WMI_KRK_LEN];
+    u8 krk[WMI_KRK_LEN];
 } POSTPACK WMI_ADD_KRK_CMD;
 
 /*
@@ -606,7 +620,7 @@
 } WMI_TKIP_CM_CONTROL;
 
 typedef PREPACK struct {
-    A_UINT8  cm_en;                     /* WMI_TKIP_CM_CONTROL */
+    u8 cm_en;                     /* WMI_TKIP_CM_CONTROL */
 } POSTPACK WMI_SET_TKIP_COUNTERMEASURES_CMD;
 
 /*
@@ -621,9 +635,9 @@
 } PMKID_ENABLE_FLG;
 
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT8     enable;                 /* PMKID_ENABLE_FLG */
-    A_UINT8     pmkid[WMI_PMKID_LEN];
+    u8 bssid[ATH_MAC_LEN];
+    u8 enable;                 /* PMKID_ENABLE_FLG */
+    u8 pmkid[WMI_PMKID_LEN];
 } POSTPACK WMI_SET_PMKID_CMD;
 
 /*
@@ -635,13 +649,13 @@
 } WMI_SCAN_TYPE;
 
 typedef PREPACK struct {
-    A_BOOL   forceFgScan;
-    A_BOOL   isLegacy;        /* For Legacy Cisco AP compatibility */
-    A_UINT32 homeDwellTime;   /* Maximum duration in the home channel(milliseconds) */
-    A_UINT32 forceScanInterval;    /* Time interval between scans (milliseconds)*/
-    A_UINT8  scanType;           /* WMI_SCAN_TYPE */
-    A_UINT8  numChannels;            /* how many channels follow */
-    A_UINT16 channelList[1];         /* channels in Mhz */
+    u32   forceFgScan;
+    u32   isLegacy;        /* For Legacy Cisco AP compatibility */
+    u32 homeDwellTime;   /* Maximum duration in the home channel(milliseconds) */
+    u32 forceScanInterval;    /* Time interval between scans (milliseconds)*/
+    u8 scanType;           /* WMI_SCAN_TYPE */
+    u8 numChannels;            /* how many channels follow */
+    u16 channelList[1];         /* channels in Mhz */
 } POSTPACK WMI_START_SCAN_CMD;
 
 /*
@@ -676,16 +690,16 @@
 
 
 typedef PREPACK struct {
-    A_UINT16    fg_start_period;        /* seconds */
-    A_UINT16    fg_end_period;          /* seconds */
-    A_UINT16    bg_period;              /* seconds */
-    A_UINT16    maxact_chdwell_time;    /* msec */
-    A_UINT16    pas_chdwell_time;       /* msec */
-    A_UINT8     shortScanRatio;         /* how many shorts scan for one long */
-    A_UINT8     scanCtrlFlags;
-    A_UINT16    minact_chdwell_time;    /* msec */
-    A_UINT16    maxact_scan_per_ssid;   /* max active scans per ssid */
-    A_UINT32    max_dfsch_act_time;  /* msecs */
+    u16 fg_start_period;        /* seconds */
+    u16 fg_end_period;          /* seconds */
+    u16 bg_period;              /* seconds */
+    u16 maxact_chdwell_time;    /* msec */
+    u16 pas_chdwell_time;       /* msec */
+    u8 shortScanRatio;         /* how many shorts scan for one long */
+    u8 scanCtrlFlags;
+    u16 minact_chdwell_time;    /* msec */
+    u16 maxact_scan_per_ssid;   /* max active scans per ssid */
+    u32 max_dfsch_act_time;  /* msecs */
 } POSTPACK WMI_SCAN_PARAMS_CMD;
 
 /*
@@ -703,10 +717,10 @@
 } WMI_BSS_FILTER;
 
 typedef PREPACK struct {
-    A_UINT8    bssFilter;                      /* see WMI_BSS_FILTER */
-    A_UINT8    reserved1;                      /* For alignment */
-    A_UINT16   reserved2;                      /* For alignment */
-    A_UINT32   ieMask;
+    u8 bssFilter;                      /* see WMI_BSS_FILTER */
+    u8 reserved1;                      /* For alignment */
+    u16 reserved2;                      /* For alignment */
+    u32 ieMask;
 } POSTPACK WMI_BSS_FILTER_CMD;
 
 /*
@@ -721,10 +735,10 @@
 } WMI_SSID_FLAG;
 
 typedef PREPACK struct {
-    A_UINT8     entryIndex;                     /* 0 to MAX_PROBED_SSID_INDEX */
-    A_UINT8     flag;                           /* WMI_SSID_FLG */
-    A_UINT8     ssidLength;
-    A_UINT8     ssid[32];
+    u8 entryIndex;                     /* 0 to MAX_PROBED_SSID_INDEX */
+    u8 flag;                           /* WMI_SSID_FLG */
+    u8 ssidLength;
+    u8 ssid[32];
 } POSTPACK WMI_PROBED_SSID_CMD;
 
 /*
@@ -737,15 +751,15 @@
 #define MAX_LISTEN_BEACONS 50
 
 typedef PREPACK struct {
-    A_UINT16     listenInterval;
-    A_UINT16     numBeacons;
+    u16 listenInterval;
+    u16 numBeacons;
 } POSTPACK WMI_LISTEN_INT_CMD;
 
 /*
  * WMI_SET_BEACON_INT_CMDID
  */
 typedef PREPACK struct {
-    A_UINT16     beaconInterval;
+    u16 beaconInterval;
 } POSTPACK WMI_BEACON_INT_CMD;
 
 /*
@@ -759,8 +773,8 @@
 #define MAX_BMISS_BEACONS  50
 
 typedef PREPACK struct {
-    A_UINT16     bmissTime;
-    A_UINT16     numBeacons;
+    u16 bmissTime;
+    u16 numBeacons;
 } POSTPACK WMI_BMISS_TIME_CMD;
 
 /*
@@ -772,25 +786,25 @@
 } WMI_POWER_MODE;
 
 typedef PREPACK struct {
-    A_UINT8     powerMode;      /* WMI_POWER_MODE */
+    u8 powerMode;      /* WMI_POWER_MODE */
 } POSTPACK WMI_POWER_MODE_CMD;
 
 typedef PREPACK struct {
-    A_INT8 status;      /* WMI_SET_PARAMS_REPLY */
+    s8 status;      /* WMI_SET_PARAMS_REPLY */
 } POSTPACK WMI_SET_PARAMS_REPLY;
 
 typedef PREPACK struct {
-    A_UINT32 opcode;
-    A_UINT32 length;
-    A_CHAR buffer[1];      /* WMI_SET_PARAMS */
+    u32 opcode;
+    u32 length;
+    char buffer[1];      /* WMI_SET_PARAMS */
 } POSTPACK WMI_SET_PARAMS_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 multicast_mac[ATH_MAC_LEN];      /* WMI_SET_MCAST_FILTER */
+    u8 multicast_mac[ATH_MAC_LEN];      /* WMI_SET_MCAST_FILTER */
 } POSTPACK WMI_SET_MCAST_FILTER_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 enable;      /* WMI_MCAST_FILTER */
+    u8 enable;      /* WMI_MCAST_FILTER */
 } POSTPACK WMI_MCAST_FILTER_CMD;
 
 /*
@@ -819,12 +833,12 @@
 } POWER_SAVE_FAIL_EVENT_POLICY;
 
 typedef PREPACK struct {
-    A_UINT16    idle_period;             /* msec */
-    A_UINT16    pspoll_number;
-    A_UINT16    dtim_policy;
-    A_UINT16    tx_wakeup_policy;
-    A_UINT16    num_tx_to_wakeup;
-    A_UINT16    ps_fail_event_policy;
+    u16 idle_period;             /* msec */
+    u16 pspoll_number;
+    u16 dtim_policy;
+    u16 tx_wakeup_policy;
+    u16 num_tx_to_wakeup;
+    u16 ps_fail_event_policy;
 } POSTPACK WMI_POWER_PARAMS_CMD;
 
 /* Adhoc power save types */
@@ -836,10 +850,10 @@
 } WMI_ADHOC_PS_TYPE;
 
 typedef PREPACK struct {
-    A_UINT8    power_saving;
-    A_UINT8    ttl; /* number of beacon periods */
-    A_UINT16   atim_windows;          /* msec */
-    A_UINT16   timeout_value;         /* msec */
+    u8 power_saving;
+    u8 ttl; /* number of beacon periods */
+    u16 atim_windows;          /* msec */
+    u16 timeout_value;         /* msec */
 } POSTPACK WMI_IBSS_PM_CAPS_CMD;
 
 /* AP power save types */
@@ -849,10 +863,10 @@
 } WMI_AP_PS_TYPE;
 
 typedef PREPACK struct {
-    A_UINT32   idle_time;   /* in msec */
-    A_UINT32   ps_period;   /* in usec */
-    A_UINT8    sleep_period; /* in ps periods */
-    A_UINT8    psType;
+    u32 idle_time;   /* in msec */
+    u32 ps_period;   /* in usec */
+    u8 sleep_period; /* in ps periods */
+    u8 psType;
 } POSTPACK WMI_AP_PS_CMD;
 
 /*
@@ -866,17 +880,17 @@
 } APSD_TIM_POLICY;
 
 typedef PREPACK struct {
-    A_UINT16    psPollTimeout;          /* msec */
-    A_UINT16    triggerTimeout;         /* msec */
-    A_UINT32    apsdTimPolicy;      /* TIM behavior with  ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */
-    A_UINT32    simulatedAPSDTimPolicy;      /* TIM behavior with  simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */
+    u16 psPollTimeout;          /* msec */
+    u16 triggerTimeout;         /* msec */
+    u32 apsdTimPolicy;      /* TIM behavior with  ques APSD enabled. Default is IGNORE_TIM_ALL_QUEUES_APSD */
+    u32 simulatedAPSDTimPolicy;      /* TIM behavior with  simulated APSD enabled. Default is PROCESS_TIM_SIMULATED_APSD */
 } POSTPACK WMI_POWERSAVE_TIMERS_POLICY_CMD;
 
 /*
  * WMI_SET_VOICE_PKT_SIZE_CMDID
  */
 typedef PREPACK struct {
-    A_UINT16    voicePktSize;
+    u16 voicePktSize;
 } POSTPACK WMI_SET_VOICE_PKT_SIZE_CMD;
 
 /*
@@ -890,14 +904,14 @@
 } APSD_SP_LEN_TYPE;
 
 typedef PREPACK struct {
-    A_UINT8    maxSPLen;
+    u8 maxSPLen;
 } POSTPACK WMI_SET_MAX_SP_LEN_CMD;
 
 /*
  * WMI_SET_DISC_TIMEOUT_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     disconnectTimeout;          /* seconds */
+    u8 disconnectTimeout;          /* seconds */
 } POSTPACK WMI_DISC_TIMEOUT_CMD;
 
 typedef enum {
@@ -921,47 +935,47 @@
  * WMI_SYNCHRONIZE_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8 dataSyncMap;
+    u8 dataSyncMap;
 } POSTPACK WMI_SYNC_CMD;
 
 /*
  * WMI_CREATE_PSTREAM_CMDID
  */
 typedef PREPACK struct {
-    A_UINT32        minServiceInt;           /* in milli-sec */
-    A_UINT32        maxServiceInt;           /* in milli-sec */
-    A_UINT32        inactivityInt;           /* in milli-sec */
-    A_UINT32        suspensionInt;           /* in milli-sec */
-    A_UINT32        serviceStartTime;
-    A_UINT32        minDataRate;             /* in bps */
-    A_UINT32        meanDataRate;            /* in bps */
-    A_UINT32        peakDataRate;            /* in bps */
-    A_UINT32        maxBurstSize;
-    A_UINT32        delayBound;
-    A_UINT32        minPhyRate;              /* in bps */
-    A_UINT32        sba;
-    A_UINT32        mediumTime;
-    A_UINT16        nominalMSDU;             /* in octects */
-    A_UINT16        maxMSDU;                 /* in octects */
-    A_UINT8         trafficClass;
-    A_UINT8         trafficDirection;        /* DIR_TYPE */
-    A_UINT8         rxQueueNum;
-    A_UINT8         trafficType;             /* TRAFFIC_TYPE */
-    A_UINT8         voicePSCapability;       /* VOICEPS_CAP_TYPE */
-    A_UINT8         tsid;
-    A_UINT8         userPriority;            /* 802.1D user priority */
-    A_UINT8         nominalPHY;              /* nominal phy rate */
+    u32 minServiceInt;           /* in milli-sec */
+    u32 maxServiceInt;           /* in milli-sec */
+    u32 inactivityInt;           /* in milli-sec */
+    u32 suspensionInt;           /* in milli-sec */
+    u32 serviceStartTime;
+    u32 minDataRate;             /* in bps */
+    u32 meanDataRate;            /* in bps */
+    u32 peakDataRate;            /* in bps */
+    u32 maxBurstSize;
+    u32 delayBound;
+    u32 minPhyRate;              /* in bps */
+    u32 sba;
+    u32 mediumTime;
+    u16 nominalMSDU;             /* in octects */
+    u16 maxMSDU;                 /* in octects */
+    u8 trafficClass;
+    u8 trafficDirection;        /* DIR_TYPE */
+    u8 rxQueueNum;
+    u8 trafficType;             /* TRAFFIC_TYPE */
+    u8 voicePSCapability;       /* VOICEPS_CAP_TYPE */
+    u8 tsid;
+    u8 userPriority;            /* 802.1D user priority */
+    u8 nominalPHY;              /* nominal phy rate */
 } POSTPACK WMI_CREATE_PSTREAM_CMD;
 
 /*
  * WMI_DELETE_PSTREAM_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficDirection;
-    A_UINT8     trafficClass;
-    A_UINT8     tsid;
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficDirection;
+    u8 trafficClass;
+    u8 tsid;
 } POSTPACK WMI_DELETE_PSTREAM_CMD;
 
 /*
@@ -978,11 +992,11 @@
 #define WMI_MAX_CHANNELS        32
 
 typedef PREPACK struct {
-    A_UINT8     reserved1;
-    A_UINT8     scanParam;              /* set if enable scan */
-    A_UINT8     phyMode;                /* see WMI_PHY_MODE */
-    A_UINT8     numChannels;            /* how many channels follow */
-    A_UINT16    channelList[1];         /* channels in Mhz */
+    u8 reserved1;
+    u8 scanParam;              /* set if enable scan */
+    u8 phyMode;                /* see WMI_PHY_MODE */
+    u8 numChannels;            /* how many channels follow */
+    u16 channelList[1];         /* channels in Mhz */
 } POSTPACK WMI_CHANNEL_PARAMS_CMD;
 
 
@@ -995,21 +1009,21 @@
  */
 
 typedef PREPACK struct WMI_RSSI_THRESHOLD_PARAMS{
-    A_UINT32    pollTime;               /* Polling time as a factor of LI */
-    A_INT16     thresholdAbove1_Val;          /* lowest of upper */
-    A_INT16     thresholdAbove2_Val;
-    A_INT16     thresholdAbove3_Val;
-    A_INT16     thresholdAbove4_Val;
-    A_INT16     thresholdAbove5_Val;
-    A_INT16     thresholdAbove6_Val;          /* highest of upper */
-    A_INT16     thresholdBelow1_Val;         /* lowest of bellow */
-    A_INT16     thresholdBelow2_Val;
-    A_INT16     thresholdBelow3_Val;
-    A_INT16     thresholdBelow4_Val;
-    A_INT16     thresholdBelow5_Val;
-    A_INT16     thresholdBelow6_Val;         /* highest of bellow */
-    A_UINT8     weight;                  /* "alpha" */
-    A_UINT8     reserved[3];
+    u32 pollTime;               /* Polling time as a factor of LI */
+    s16 thresholdAbove1_Val;          /* lowest of upper */
+    s16 thresholdAbove2_Val;
+    s16 thresholdAbove3_Val;
+    s16 thresholdAbove4_Val;
+    s16 thresholdAbove5_Val;
+    s16 thresholdAbove6_Val;          /* highest of upper */
+    s16 thresholdBelow1_Val;         /* lowest of bellow */
+    s16 thresholdBelow2_Val;
+    s16 thresholdBelow3_Val;
+    s16 thresholdBelow4_Val;
+    s16 thresholdBelow5_Val;
+    s16 thresholdBelow6_Val;         /* highest of bellow */
+    u8 weight;                  /* "alpha" */
+    u8 reserved[3];
 } POSTPACK  WMI_RSSI_THRESHOLD_PARAMS_CMD;
 
 /*
@@ -1018,33 +1032,33 @@
  */
 
 typedef PREPACK struct WMI_SNR_THRESHOLD_PARAMS{
-    A_UINT32    pollTime;               /* Polling time as a factor of LI */
-    A_UINT8     weight;                  /* "alpha" */
-    A_UINT8     thresholdAbove1_Val;      /* lowest of uppper*/
-    A_UINT8     thresholdAbove2_Val;
-    A_UINT8     thresholdAbove3_Val;
-    A_UINT8     thresholdAbove4_Val;      /* highest of upper */
-    A_UINT8     thresholdBelow1_Val;     /* lowest of bellow */
-    A_UINT8     thresholdBelow2_Val;
-    A_UINT8     thresholdBelow3_Val;
-    A_UINT8     thresholdBelow4_Val;     /* highest of bellow */
-    A_UINT8     reserved[3];
+    u32 pollTime;               /* Polling time as a factor of LI */
+    u8 weight;                  /* "alpha" */
+    u8 thresholdAbove1_Val;      /* lowest of uppper*/
+    u8 thresholdAbove2_Val;
+    u8 thresholdAbove3_Val;
+    u8 thresholdAbove4_Val;      /* highest of upper */
+    u8 thresholdBelow1_Val;     /* lowest of bellow */
+    u8 thresholdBelow2_Val;
+    u8 thresholdBelow3_Val;
+    u8 thresholdBelow4_Val;     /* highest of bellow */
+    u8 reserved[3];
 } POSTPACK WMI_SNR_THRESHOLD_PARAMS_CMD;
 
 /*
  *  WMI_LQ_THRESHOLD_PARAMS_CMDID
  */
 typedef PREPACK struct WMI_LQ_THRESHOLD_PARAMS {
-    A_UINT8     enable;
-    A_UINT8     thresholdAbove1_Val;
-    A_UINT8     thresholdAbove2_Val;
-    A_UINT8     thresholdAbove3_Val;
-    A_UINT8     thresholdAbove4_Val;
-    A_UINT8     thresholdBelow1_Val;
-    A_UINT8     thresholdBelow2_Val;
-    A_UINT8     thresholdBelow3_Val;
-    A_UINT8     thresholdBelow4_Val;
-    A_UINT8     reserved[3];
+    u8 enable;
+    u8 thresholdAbove1_Val;
+    u8 thresholdAbove2_Val;
+    u8 thresholdAbove3_Val;
+    u8 thresholdAbove4_Val;
+    u8 thresholdBelow1_Val;
+    u8 thresholdBelow2_Val;
+    u8 thresholdBelow3_Val;
+    u8 thresholdBelow4_Val;
+    u8 reserved[3];
 } POSTPACK  WMI_LQ_THRESHOLD_PARAMS_CMD;
 
 typedef enum {
@@ -1058,12 +1072,12 @@
 } WMI_PREAMBLE_POLICY;
 
 typedef PREPACK struct {
-    A_UINT8     status;
-    A_UINT8     preamblePolicy;
+    u8 status;
+    u8 preamblePolicy;
 }POSTPACK WMI_SET_LPREAMBLE_CMD;
 
 typedef PREPACK struct {
-    A_UINT16    threshold;
+    u16 threshold;
 }POSTPACK WMI_SET_RTS_CMD;
 
 /*
@@ -1073,14 +1087,14 @@
  *  via event, unless the bitmask is set again.
  */
 typedef PREPACK struct {
-    A_UINT32    bitmask;
+    u32 bitmask;
 } POSTPACK  WMI_TARGET_ERROR_REPORT_BITMASK;
 
 /*
  * WMI_SET_TX_PWR_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     dbM;                  /* in dbM units */
+    u8 dbM;                  /* in dbM units */
 } POSTPACK WMI_SET_TX_PWR_CMD, WMI_TX_PWR_REPLY;
 
 /*
@@ -1095,9 +1109,9 @@
 #define WMI_MAX_ASSOC_INFO_LEN     240
 
 typedef PREPACK struct {
-    A_UINT8     ieType;
-    A_UINT8     bufferSize;
-    A_UINT8     assocInfo[1];       /* up to WMI_MAX_ASSOC_INFO_LEN */
+    u8 ieType;
+    u8 bufferSize;
+    u8 assocInfo[1];       /* up to WMI_MAX_ASSOC_INFO_LEN */
 } POSTPACK WMI_SET_ASSOC_INFO_CMD;
 
 
@@ -1111,15 +1125,15 @@
 #define WMI_MAX_BAD_AP_INDEX      1
 
 typedef PREPACK struct {
-    A_UINT8     badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u8 badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_ADD_BAD_AP_CMD;
 
 /*
  * WMI_DELETE_BAD_AP_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
+    u8 badApIndex;         /* 0 to WMI_MAX_BAD_AP_INDEX */
 } POSTPACK WMI_DELETE_BAD_AP_CMD;
 
 /*
@@ -1132,11 +1146,11 @@
 #define WMI_DEFAULT_AIFSN_ACPARAM   2
 #define WMI_MAX_AIFSN_ACPARAM       15
 typedef PREPACK struct {
-    A_UINT16 txop;                      /* in units of 32 usec */
-    A_UINT8  eCWmin;
-    A_UINT8  eCWmax;
-    A_UINT8  aifsn;
-    A_UINT8  ac;
+    u16 txop;                      /* in units of 32 usec */
+    u8 eCWmin;
+    u8 eCWmax;
+    u8 aifsn;
+    u8 ac;
 } POSTPACK WMI_SET_ACCESS_PARAMS_CMD;
 
 
@@ -1155,10 +1169,10 @@
 } WMI_FRAMETYPE;
 
 typedef PREPACK struct {
-    A_UINT8 frameType;                      /* WMI_FRAMETYPE */
-    A_UINT8 trafficClass;                   /* applies only to DATA_FRAMETYPE */
-    A_UINT8 maxRetries;
-    A_UINT8 enableNotify;
+    u8 frameType;                      /* WMI_FRAMETYPE */
+    u8 trafficClass;                   /* applies only to DATA_FRAMETYPE */
+    u8 maxRetries;
+    u8 enableNotify;
 } POSTPACK WMI_SET_RETRY_LIMITS_CMD;
 
 /*
@@ -1198,31 +1212,31 @@
  */
 
 typedef PREPACK struct {
-        A_UINT8 bssid[ATH_MAC_LEN];
-        A_INT8  bias;
+        u8 bssid[ATH_MAC_LEN];
+        s8 bias;
 } POSTPACK WMI_BSS_BIAS;
 
 typedef PREPACK struct {
-        A_UINT8 numBss;
+        u8 numBss;
         WMI_BSS_BIAS bssBias[1];
 } POSTPACK WMI_BSS_BIAS_INFO;
 
 typedef PREPACK struct WMI_LOWRSSI_SCAN_PARAMS {
-        A_UINT16 lowrssi_scan_period;
-        A_INT16  lowrssi_scan_threshold;
-        A_INT16  lowrssi_roam_threshold;
-        A_UINT8  roam_rssi_floor;
-        A_UINT8  reserved[1];              /* For alignment */
+        u16 lowrssi_scan_period;
+        s16 lowrssi_scan_threshold;
+        s16 lowrssi_roam_threshold;
+        u8 roam_rssi_floor;
+        u8 reserved[1];              /* For alignment */
 } POSTPACK WMI_LOWRSSI_SCAN_PARAMS;
 
 typedef PREPACK struct {
     PREPACK union {
-        A_UINT8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */
-        A_UINT8 roamMode;           /* WMI_SET_ROAM_MODE  */
+        u8 bssid[ATH_MAC_LEN]; /* WMI_FORCE_ROAM */
+        u8 roamMode;           /* WMI_SET_ROAM_MODE  */
         WMI_BSS_BIAS_INFO bssBiasInfo; /* WMI_SET_HOST_BIAS */
         WMI_LOWRSSI_SCAN_PARAMS lrScanParams;
     } POSTPACK info;
-    A_UINT8   roamCtrlType ;
+    u8 roamCtrlType ;
 } POSTPACK WMI_SET_ROAM_CTRL_CMD;
 
 /*
@@ -1234,26 +1248,26 @@
 } BT_WLAN_CONN_PRECEDENCE;
 
 typedef PREPACK struct {
-    A_UINT8 precedence;
+    u8 precedence;
 } POSTPACK WMI_SET_BT_WLAN_CONN_PRECEDENCE;
 
 /*
  * WMI_ENABLE_RM_CMDID
  */
 typedef PREPACK struct {
-        A_BOOL enable_radio_measurements;
+        u32 enable_radio_measurements;
 } POSTPACK WMI_ENABLE_RM_CMD;
 
 /*
  * WMI_SET_MAX_OFFHOME_DURATION_CMDID
  */
 typedef PREPACK struct {
-        A_UINT8 max_offhome_duration;
+        u8 max_offhome_duration;
 } POSTPACK WMI_SET_MAX_OFFHOME_DURATION_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 frequency;
-    A_UINT8  threshold;
+    u32 frequency;
+    u8 threshold;
 } POSTPACK WMI_SET_HB_CHALLENGE_RESP_PARAMS_CMD;
 /*---------------------- BTCOEX RELATED -------------------------------------*/
 /*----------------------COMMON to AR6002 and AR6003 -------------------------*/
@@ -1286,8 +1300,8 @@
 } BT_STREAM_STATUS;
 
 typedef PREPACK struct {
-    A_UINT8 streamType;
-    A_UINT8 status;
+    u8 streamType;
+    u8 status;
 } POSTPACK WMI_SET_BT_STATUS_CMD;
 
 typedef enum {
@@ -1329,13 +1343,13 @@
 #define BT_SCO_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16)
 
 typedef PREPACK struct {
-    A_UINT32 numScoCyclesForceTrigger;  /* Number SCO cycles after which
+    u32 numScoCyclesForceTrigger;  /* Number SCO cycles after which
                                            force a pspoll. default = 10 */
-    A_UINT32 dataResponseTimeout;       /* Timeout Waiting for Downlink pkt
+    u32 dataResponseTimeout;       /* Timeout Waiting for Downlink pkt
                                            in response for ps-poll,
                                            default = 10 msecs */
-    A_UINT32  stompScoRules;
-    A_UINT32 scoOptFlags;               /* SCO Options Flags :
+    u32 stompScoRules;
+    u32 scoOptFlags;               /* SCO Options Flags :
                                             bits:     meaning:
                                              0        Allow Close Range Optimization
                                              1        Force awake during close range
@@ -1346,23 +1360,23 @@
                                              16..23   Low Data Rate Max Cnt
                                         */
 
-    A_UINT8 stompDutyCyleVal;           /* Sco cycles to limit ps-poll queuing
+    u8 stompDutyCyleVal;           /* Sco cycles to limit ps-poll queuing
                                            if stomped */
-    A_UINT8 stompDutyCyleMaxVal;        /*firm ware increases stomp duty cycle
+    u8 stompDutyCyleMaxVal;        /*firm ware increases stomp duty cycle
                                           gradually uptill this value on need basis*/
-    A_UINT8 psPollLatencyFraction;      /* Fraction of idle
+    u8 psPollLatencyFraction;      /* Fraction of idle
                                            period, within which
                                            additional ps-polls
                                            can be queued */
-    A_UINT8 noSCOSlots;                 /* Number of SCO Tx/Rx slots.
+    u8 noSCOSlots;                 /* Number of SCO Tx/Rx slots.
                                            HVx, EV3, 2EV3 = 2 */
-    A_UINT8 noIdleSlots;                /* Number of Bluetooth idle slots between
+    u8 noIdleSlots;                /* Number of Bluetooth idle slots between
                                            consecutive SCO Tx/Rx slots
                                            HVx, EV3 = 4
                                            2EV3 = 10 */
-    A_UINT8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/
-    A_UINT8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/
-    A_UINT8 scoOptRtsCount;
+    u8 scoOptOffRssi;/*RSSI value below which we go to ps poll*/
+    u8 scoOptOnRssi; /*RSSI value above which we reenter opt mode*/
+    u8 scoOptRtsCount;
 } POSTPACK BT_PARAMS_SCO;
 
 #define BT_A2DP_ALLOW_CLOSE_RANGE_OPT  (1 << 0)
@@ -1377,13 +1391,13 @@
 #define BT_A2DP_SET_MAX_LOW_RATE_CNT(flags,val) (flags) |= (((val) & 0xFF) << 16)
 
 typedef PREPACK struct {
-    A_UINT32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for
+    u32 a2dpWlanUsageLimit; /* MAX time firmware uses the medium for
                                     wlan, after it identifies the idle time
                                     default (30 msecs) */
-    A_UINT32 a2dpBurstCntMin;   /* Minimum number of bluetooth data frames
+    u32 a2dpBurstCntMin;   /* Minimum number of bluetooth data frames
                                    to replenish Wlan Usage  limit (default 3) */
-    A_UINT32 a2dpDataRespTimeout;
-    A_UINT32 a2dpOptFlags;      /* A2DP Option flags:
+    u32 a2dpDataRespTimeout;
+    u32 a2dpOptFlags;      /* A2DP Option flags:
                                        bits:    meaning:
                                         0       Allow Close Range Optimization
                                         1       Force awake during close range
@@ -1393,23 +1407,23 @@
                                         8..15   Low Data Rate Min Cnt
                                         16..23  Low Data Rate Max Cnt
                                  */
-    A_UINT8 isCoLocatedBtRoleMaster;
-    A_UINT8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/
-    A_UINT8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/
-    A_UINT8 a2dpOptRtsCount;
+    u8 isCoLocatedBtRoleMaster;
+    u8 a2dpOptOffRssi;/*RSSI value below which we go to ps poll*/
+    u8 a2dpOptOnRssi; /*RSSI value above which we reenter opt mode*/
+    u8 a2dpOptRtsCount;
 }POSTPACK BT_PARAMS_A2DP;
 
 /* During BT ftp/ BT OPP or any another data based acl profile on bluetooth
    (non a2dp).*/
 typedef PREPACK struct {
-    A_UINT32 aclWlanMediumUsageTime;  /* Wlan usage time during Acl (non-a2dp)
+    u32 aclWlanMediumUsageTime;  /* Wlan usage time during Acl (non-a2dp)
                                        coexistence (default 30 msecs) */
-    A_UINT32 aclBtMediumUsageTime;   /* Bt usage time during acl coexistence
+    u32 aclBtMediumUsageTime;   /* Bt usage time during acl coexistence
                                        (default 30 msecs)*/
-    A_UINT32 aclDataRespTimeout;
-    A_UINT32 aclDetectTimeout;      /* ACL coexistence enabled if we get
+    u32 aclDataRespTimeout;
+    u32 aclDetectTimeout;      /* ACL coexistence enabled if we get
                                        10 Pkts in X msec(default 100 msecs) */
-    A_UINT32 aclmaxPktCnt;          /* No of ACL pkts to receive before
+    u32 aclmaxPktCnt;          /* No of ACL pkts to receive before
                                          enabling ACL coex */
 
 }POSTPACK BT_PARAMS_ACLCOEX;
@@ -1419,16 +1433,16 @@
         BT_PARAMS_SCO scoParams;
         BT_PARAMS_A2DP a2dpParams;
         BT_PARAMS_ACLCOEX  aclCoexParams;
-        A_UINT8 antType;         /* 0 -Disabled (default)
+        u8 antType;         /* 0 -Disabled (default)
                                      1 - BT_ANT_TYPE_DUAL
                                      2 - BT_ANT_TYPE_SPLITTER
                                      3 - BT_ANT_TYPE_SWITCH */
-        A_UINT8 coLocatedBtDev;  /* 0 - BT_COLOCATED_DEV_BTS4020 (default)
+        u8 coLocatedBtDev;  /* 0 - BT_COLOCATED_DEV_BTS4020 (default)
                                      1 - BT_COLCATED_DEV_CSR
                                      2 - BT_COLOCATED_DEV_VALKYRIe
                                    */
     } POSTPACK info;
-    A_UINT8 paramType ;
+    u8 paramType ;
 } POSTPACK WMI_SET_BT_PARAMS_CMD;
 
 /************************ END AR6002 BTCOEX *******************************/
@@ -1448,7 +1462,7 @@
 }WMI_BTCOEX_FE_ANT_TYPE;
 
 typedef PREPACK struct {
-	A_UINT8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end
+	u8 btcoexFeAntType; /* 1 - WMI_BTCOEX_FE_ANT_SINGLE for single antenna front end
                                 2 - WMI_BTCOEX_FE_ANT_DUAL for dual antenna front end
                                     (for isolations less 35dB, for higher isolation there
                                     is not need to pass this command).
@@ -1461,7 +1475,7 @@
  * bluetooth chip type.Based on bluetooth device, different coexistence protocol would be used.
  */
 typedef PREPACK struct {
-	A_UINT8	btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA)
+	u8 btcoexCoLocatedBTdev; /*1 - Qcom BT (3 -wire PTA)
                                     2 - CSR BT  (3 wire PTA)
                                     3 - Atheros 3001 BT (3 wire PTA)
                                     4 - STE bluetooth (4-wire ePTA)
@@ -1478,20 +1492,20 @@
  * During this the station will be  power-save mode.
  */
 typedef PREPACK struct {
-	A_UINT32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data
+	u32 btInquiryDataFetchFrequency;/* The frequency of querying the AP for data
                                             (via pspoll) is configured by this parameter.
                                             "default = 10 ms" */
 
-	A_UINT32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state
+	u32 protectBmissDurPostBtInquiry;/* The firmware will continue to be in inquiry state
                                              for configured duration, after inquiry completion
                                              . This is to ensure other bluetooth transactions
                                              (RDP, SDP profiles, link key exchange ...etc)
                                              goes through smoothly without wifi stomping.
                                              default = 10 secs*/
 
-	A_UINT32 maxpageStomp;                 /*Applicable only for STE-BT interface. Currently not
+	u32 maxpageStomp;                 /*Applicable only for STE-BT interface. Currently not
                                              used */
-	A_UINT32 btInquiryPageFlag;           /* Not used */
+	u32 btInquiryPageFlag;           /* Not used */
 }POSTPACK WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD;
 
 /*---------------------WMI_SET_BTCOEX_SCO_CONFIG_CMDID ---------------*/
@@ -1509,14 +1523,14 @@
 #define WMI_SCO_CONFIG_FLAG_IS_BT_MASTER         (1 << 2)
 #define WMI_SCO_CONFIG_FLAG_FW_DETECT_OF_PER     (1 << 3)
 typedef PREPACK struct {
-	A_UINT32 scoSlots;					/* Number of SCO Tx/Rx slots.
+	u32 scoSlots;					/* Number of SCO Tx/Rx slots.
 										   HVx, EV3, 2EV3 = 2 */
-	A_UINT32 scoIdleSlots;				/* Number of Bluetooth idle slots between
+	u32 scoIdleSlots;				/* Number of Bluetooth idle slots between
 										   consecutive SCO Tx/Rx slots
 										   HVx, EV3 = 4
 										   2EV3 = 10
                                          */
- 	A_UINT32 scoFlags;				   /* SCO Options Flags :
+	u32 scoFlags;				   /* SCO Options Flags :
 										  bits:	   meaning:
  										  0   Allow Close Range Optimization
  										  1   Is EDR capable or Not
@@ -1524,21 +1538,21 @@
                                           3   Firmware determines the periodicity of SCO.
 							  			 */
 
-    A_UINT32 linkId;                      /* applicable to STE-BT - not used */
+    u32 linkId;                      /* applicable to STE-BT - not used */
 }POSTPACK BTCOEX_SCO_CONFIG;
 
 typedef PREPACK struct {
-	A_UINT32  scoCyclesForceTrigger;	/* Number SCO cycles after which
+	u32 scoCyclesForceTrigger;	/* Number SCO cycles after which
 											force a pspoll. default = 10 */
-    A_UINT32 scoDataResponseTimeout;	 /* Timeout Waiting for Downlink pkt
+    u32 scoDataResponseTimeout;	 /* Timeout Waiting for Downlink pkt
 											in response for ps-poll,
 											default = 20 msecs */
 
-	A_UINT32 scoStompDutyCyleVal;		 /* not implemented */
+	u32 scoStompDutyCyleVal;		 /* not implemented */
 
-	A_UINT32 scoStompDutyCyleMaxVal;     /*Not implemented */
+	u32 scoStompDutyCyleMaxVal;     /*Not implemented */
 
-	A_UINT32 scoPsPollLatencyFraction; 	 /* Fraction of idle
+	u32 scoPsPollLatencyFraction; 	 /* Fraction of idle
 											period, within which
 											additional ps-polls can be queued
                                             1 - 1/4 of idle duration
@@ -1549,29 +1563,29 @@
 }POSTPACK BTCOEX_PSPOLLMODE_SCO_CONFIG;
 
 typedef PREPACK struct {
-	A_UINT32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in
+	u32 scoStompCntIn100ms;/*max number of SCO stomp in 100ms allowed in
                                    opt mode. If exceeds the configured value,
                                    switch to ps-poll mode
                                   default = 3 */
 
-	A_UINT32 scoContStompMax;   /* max number of continous stomp allowed in opt mode.
-                                   if excedded switch to pspoll mode
+	u32 scoContStompMax;   /* max number of continuous stomp allowed in opt mode.
+                                   if exceeded switch to pspoll mode
                                     default = 3 */
 
-	A_UINT32 scoMinlowRateMbps; /* Low rate threshold */
+	u32 scoMinlowRateMbps; /* Low rate threshold */
 
-	A_UINT32 scoLowRateCnt;     /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms.
+	u32 scoLowRateCnt;     /* number of low rate pkts (< scoMinlowRateMbps) allowed in 100 ms.
                                    If exceeded switch/stay to ps-poll mode, lower stay in opt mode.
                                    default = 36
                                  */
 
-	A_UINT32 scoHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
+	u32 scoHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
                                   ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms,
                                   if exceeded switch/stay in opt mode and if lower switch/stay in  pspoll mode.
                                   default = 5 (80% of high rates)
                                  */
 
-	A_UINT32 scoMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
+	u32 scoMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
                                    max number of aggregates if it was negogiated to higher value
                                    default = 1
                                    Recommended value Basic rate headsets = 1, EDR (2-EV3)  =4.
@@ -1579,8 +1593,8 @@
 }POSTPACK BTCOEX_OPTMODE_SCO_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 scanInterval;
-    A_UINT32 maxScanStompCnt;
+    u32 scanInterval;
+    u32 maxScanStompCnt;
 }POSTPACK BTCOEX_WLANSCAN_SCO_CONFIG;
 
 typedef PREPACK struct {
@@ -1608,7 +1622,7 @@
 #define WMI_A2DP_CONFIG_FLAG_FIND_BT_ROLE          (1 << 4)
 
 typedef PREPACK struct {
-    A_UINT32 a2dpFlags;      /* A2DP Option flags:
+    u32 a2dpFlags;      /* A2DP Option flags:
 		                        bits:    meaning:
                		            0       Allow Close Range Optimization
        	                     	1       IS EDR capable
@@ -1616,19 +1630,19 @@
                                 3       a2dp traffic is high priority
                                 4       Fw detect the role of bluetooth.
                              */
-	A_UINT32 linkId;         /* Applicable only to STE-BT - not used */
+	u32 linkId;         /* Applicable only to STE-BT - not used */
 
 }POSTPACK BTCOEX_A2DP_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for
+    u32 a2dpWlanMaxDur; /* MAX time firmware uses the medium for
                       			wlan, after it identifies the idle time
                                 default (30 msecs) */
 
-    A_UINT32 a2dpMinBurstCnt;   /* Minimum number of bluetooth data frames
+    u32 a2dpMinBurstCnt;   /* Minimum number of bluetooth data frames
                   				to replenish Wlan Usage  limit (default 3) */
 
-    A_UINT32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink
+    u32 a2dpDataRespTimeout; /* Max duration firmware waits for downlink
                                      by stomping on  bluetooth
                                      after ps-poll is acknowledged.
                                      default = 20 ms
@@ -1636,25 +1650,25 @@
 }POSTPACK BTCOEX_PSPOLLMODE_A2DP_CONFIG;
 
 typedef PREPACK struct {
-	A_UINT32 a2dpMinlowRateMbps;  /* Low rate threshold */
+	u32 a2dpMinlowRateMbps;  /* Low rate threshold */
 
-	A_UINT32 a2dpLowRateCnt;    /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms.
+	u32 a2dpLowRateCnt;    /* number of low rate pkts (< a2dpMinlowRateMbps) allowed in 100 ms.
                                    If exceeded switch/stay to ps-poll mode, lower stay in opt mode.
                                    default = 36
                                  */
 
-	A_UINT32 a2dpHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
+	u32 a2dpHighPktRatio;   /*(Total Rx pkts in 100 ms + 1)/
                                   ((Total tx pkts in 100 ms - No of high rate pkts in 100 ms) + 1) in 100 ms,
                                   if exceeded switch/stay in opt mode and if lower switch/stay in  pspoll mode.
                                   default = 5 (80% of high rates)
                                  */
 
-	A_UINT32 a2dpMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
+	u32 a2dpMaxAggrSize;    /* Max number of Rx subframes allowed in this mode. (Firmware re-negogiates
                                    max number of aggregates if it was negogiated to higher value
                                    default = 1
                                   Recommended value Basic rate headsets = 1, EDR (2-EV3)  =8.
                                  */
-	A_UINT32 a2dpPktStompCnt;    /*number of a2dp pkts that can be stomped per burst.
+	u32 a2dpPktStompCnt;    /*number of a2dp pkts that can be stomped per burst.
                                    default = 6*/
 
 }POSTPACK BTCOEX_OPTMODE_A2DP_CONFIG;
@@ -1683,15 +1697,15 @@
 #define WMI_ACLCOEX_FLAGS_DISABLE_FW_DETECTION (1 << 1)
 
 typedef PREPACK struct {
-    A_UINT32 aclWlanMediumDur; 	    /* Wlan usage time during Acl (non-a2dp)
+    u32 aclWlanMediumDur; 	    /* Wlan usage time during Acl (non-a2dp)
                      					coexistence (default 30 msecs)
                                     */
 
-    A_UINT32 aclBtMediumDur; 	   /* Bt usage time during acl coexistence
+    u32 aclBtMediumDur; 	   /* Bt usage time during acl coexistence
 					                     (default 30 msecs)
                                    */
 
-	A_UINT32 aclDetectTimeout;	   /* BT activity observation time limit.
+	u32 aclDetectTimeout;	   /* BT activity observation time limit.
 									  In this time duration, number of bt pkts are counted.
 									  If the Cnt reaches "aclPktCntLowerLimit" value
 									  for "aclIterToEnableCoex" iteration continuously,
@@ -1703,7 +1717,7 @@
     								  -default 100 msecs
                                     */
 
-	 A_UINT32 aclPktCntLowerLimit;   /* Acl Pkt Cnt to be received in duration of
+	 u32 aclPktCntLowerLimit;   /* Acl Pkt Cnt to be received in duration of
 										"aclDetectTimeout" for
 										"aclIterForEnDis" times to enabling ACL coex.
                                         Similar logic is used to disable acl coexistence.
@@ -1713,28 +1727,28 @@
                                         default = 10
                                    */
 
-	 A_UINT32 aclIterForEnDis;      /* number of Iteration of "aclPktCntLowerLimit" for Enabling and
+	 u32 aclIterForEnDis;      /* number of Iteration of "aclPktCntLowerLimit" for Enabling and
                                        Disabling Acl Coexistence.
                                        default = 3
                                      */
 
-	 A_UINT32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than
+	 u32 aclPktCntUpperLimit; /* This is upperBound limit, if there is more than
 									  "aclPktCntUpperLimit" seen in "aclDetectTimeout",
 									  ACL coexistence is enabled right away.
 									  - default 15*/
 
-	A_UINT32 aclCoexFlags;			/* A2DP Option flags:
+	u32 aclCoexFlags;			/* A2DP Option flags:
 		  	                          bits:    meaning:
        		                          0       Allow Close Range Optimization
                     		          1       disable Firmware detection
                                       (Currently supported configuration is aclCoexFlags =0)
                       			 	*/
-	A_UINT32 linkId;                /* Applicable only for STE-BT - not used */
+	u32 linkId;                /* Applicable only for STE-BT - not used */
 
 }POSTPACK BTCOEX_ACLCOEX_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 aclDataRespTimeout;   /* Max duration firmware waits for downlink
+    u32 aclDataRespTimeout;   /* Max duration firmware waits for downlink
                                       by stomping on  bluetooth
                                       after ps-poll is acknowledged.
                                      default = 20 ms */
@@ -1744,11 +1758,11 @@
 
 /* Not implemented yet*/
 typedef PREPACK struct {
-	A_UINT32 aclCoexMinlowRateMbps;
-	A_UINT32 aclCoexLowRateCnt;
-	A_UINT32 aclCoexHighPktRatio;
-	A_UINT32 aclCoexMaxAggrSize;
-	A_UINT32 aclPktStompCnt;
+	u32 aclCoexMinlowRateMbps;
+	u32 aclCoexLowRateCnt;
+	u32 aclCoexHighPktRatio;
+	u32 aclCoexMaxAggrSize;
+	u32 aclPktStompCnt;
 }POSTPACK BTCOEX_OPTMODE_ACLCOEX_CONFIG;
 
 typedef PREPACK struct {
@@ -1766,39 +1780,39 @@
 }WMI_BTCOEX_BT_PROFILE;
 
 typedef PREPACK struct {
-	A_UINT32 btProfileType;
-	A_UINT32 btOperatingStatus;
-	A_UINT32 btLinkId;
+	u32 btProfileType;
+	u32 btOperatingStatus;
+	u32 btLinkId;
 }WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD;
 
 /*--------------------- WMI_SET_BTCOEX_DEBUG_CMDID ---------------------*/
 /* Used for firmware development and debugging */
 typedef PREPACK struct {
-	A_UINT32 btcoexDbgParam1;
-	A_UINT32 btcoexDbgParam2;
-	A_UINT32 btcoexDbgParam3;
-	A_UINT32 btcoexDbgParam4;
-	A_UINT32 btcoexDbgParam5;
+	u32 btcoexDbgParam1;
+	u32 btcoexDbgParam2;
+	u32 btcoexDbgParam3;
+	u32 btcoexDbgParam4;
+	u32 btcoexDbgParam5;
 }WMI_SET_BTCOEX_DEBUG_CMD;
 
 /*---------------------WMI_GET_BTCOEX_CONFIG_CMDID --------------------- */
 /* Command to firmware to get configuration parameters of the bt profile
  * reported via WMI_BTCOEX_CONFIG_EVENTID */
 typedef PREPACK struct {
-	A_UINT32 btProfileType; /* 1 - SCO
+	u32 btProfileType; /* 1 - SCO
                                2 - A2DP
                                3 - INQUIRY_PAGE
                                4 - ACLCOEX
                             */
-	A_UINT32 linkId;    /* not used */
+	u32 linkId;    /* not used */
 }WMI_GET_BTCOEX_CONFIG_CMD;
 
 /*------------------WMI_REPORT_BTCOEX_CONFIG_EVENTID------------------- */
 /* Event from firmware to host, sent in response to WMI_GET_BTCOEX_CONFIG_CMDID
  * */
 typedef PREPACK struct {
-	A_UINT32 btProfileType;
-	A_UINT32 linkId; /* not used */
+	u32 btProfileType;
+	u32 linkId; /* not used */
 	PREPACK union {
 		WMI_SET_BTCOEX_SCO_CONFIG_CMD scoConfigCmd;
 		WMI_SET_BTCOEX_A2DP_CONFIG_CMD a2dpConfigCmd;
@@ -1810,32 +1824,32 @@
 /*------------- WMI_REPORT_BTCOEX_BTCOEX_STATS_EVENTID--------------------*/
 /* Used for firmware development and debugging*/
 typedef PREPACK struct {
-	A_UINT32 highRatePktCnt;
-	A_UINT32 firstBmissCnt;
-	A_UINT32 psPollFailureCnt;
-	A_UINT32 nullFrameFailureCnt;
-	A_UINT32 optModeTransitionCnt;
+	u32 highRatePktCnt;
+	u32 firstBmissCnt;
+	u32 psPollFailureCnt;
+	u32 nullFrameFailureCnt;
+	u32 optModeTransitionCnt;
 }BTCOEX_GENERAL_STATS;
 
 typedef PREPACK struct {
-	A_UINT32	scoStompCntAvg;
-	A_UINT32	scoStompIn100ms;
-	A_UINT32 	scoMaxContStomp;
-	A_UINT32	scoAvgNoRetries;
-	A_UINT32	scoMaxNoRetriesIn100ms;
+	u32 scoStompCntAvg;
+	u32 scoStompIn100ms;
+	u32 scoMaxContStomp;
+	u32 scoAvgNoRetries;
+	u32 scoMaxNoRetriesIn100ms;
 }BTCOEX_SCO_STATS;
 
 typedef PREPACK struct {
-	A_UINT32  	a2dpBurstCnt;
-	A_UINT32	a2dpMaxBurstCnt;
-	A_UINT32	a2dpAvgIdletimeIn100ms;
-	A_UINT32	a2dpAvgStompCnt;
+	u32 a2dpBurstCnt;
+	u32 a2dpMaxBurstCnt;
+	u32 a2dpAvgIdletimeIn100ms;
+	u32 a2dpAvgStompCnt;
 }BTCOEX_A2DP_STATS;
 
 typedef PREPACK struct {
-	A_UINT32	aclPktCntInBtTime;
-	A_UINT32	aclStompCntInWlanTime;
-	A_UINT32	aclPktCntIn100ms;
+	u32 aclPktCntInBtTime;
+	u32 aclStompCntInWlanTime;
+	u32 aclPktCntIn100ms;
 }BTCOEX_ACLCOEX_STATS;
 
 typedef PREPACK struct {
@@ -1848,7 +1862,7 @@
 
 /*--------------------------END OF BTCOEX -------------------------------------*/
 typedef PREPACK struct {
-    A_UINT32 sleepState;
+    u32 sleepState;
 }WMI_REPORT_SLEEP_STATE_EVENT;
 
 typedef enum {
@@ -1861,13 +1875,13 @@
 } TARGET_EVENT_REPORT_CONFIG;
 
 typedef PREPACK struct {
-    A_UINT32 evtConfig;
+    u32 evtConfig;
 } POSTPACK WMI_SET_TARGET_EVENT_REPORT_CMD;
 
 
 typedef PREPACK struct {
-    A_UINT16    cmd_buf_sz;     /* HCI cmd buffer size */
-    A_UINT8     buf[1];         /* Absolute HCI cmd */
+    u16 cmd_buf_sz;     /* HCI cmd buffer size */
+    u8 buf[1];         /* Absolute HCI cmd */
 } POSTPACK WMI_HCI_CMD;
 
 /*
@@ -1878,13 +1892,13 @@
  * WMI_GET_CHANNEL_LIST_CMDID reply
  */
 typedef PREPACK struct {
-    A_UINT8     reserved1;
-    A_UINT8     numChannels;            /* number of channels in reply */
-    A_UINT16    channelList[1];         /* channel in Mhz */
+    u8 reserved1;
+    u8 numChannels;            /* number of channels in reply */
+    u16 channelList[1];         /* channel in Mhz */
 } POSTPACK WMI_CHANNEL_LIST_REPLY;
 
 typedef enum {
-    A_SUCCEEDED = A_OK,
+    A_SUCCEEDED = 0,
     A_FAILED_DELETE_STREAM_DOESNOT_EXIST=250,
     A_SUCCEEDED_MODIFY_STREAM=251,
     A_FAILED_INVALID_STREAM = 252,
@@ -1893,19 +1907,19 @@
 } PSTREAM_REPLY_STATUS;
 
 typedef PREPACK struct {
-    A_UINT8     status;                 /* PSTREAM_REPLY_STATUS */
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficClass;
-    A_UINT8     trafficDirection;       /* DIR_TYPE */
+    u8 status;                 /* PSTREAM_REPLY_STATUS */
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficClass;
+    u8 trafficDirection;       /* DIR_TYPE */
 } POSTPACK WMI_CRE_PRIORITY_STREAM_REPLY;
 
 typedef PREPACK struct {
-    A_UINT8     status;                 /* PSTREAM_REPLY_STATUS */
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficDirection;       /* DIR_TYPE */
-    A_UINT8     trafficClass;
+    u8 status;                 /* PSTREAM_REPLY_STATUS */
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficDirection;       /* DIR_TYPE */
+    u8 trafficClass;
 } POSTPACK WMI_DEL_PRIORITY_STREAM_REPLY;
 
 /*
@@ -1976,15 +1990,15 @@
 } WMI_PHY_CAPABILITY;
 
 typedef PREPACK struct {
-    A_UINT8     macaddr[ATH_MAC_LEN];
-    A_UINT8     phyCapability;              /* WMI_PHY_CAPABILITY */
+    u8 macaddr[ATH_MAC_LEN];
+    u8 phyCapability;              /* WMI_PHY_CAPABILITY */
 } POSTPACK WMI_READY_EVENT_1;
 
 typedef PREPACK struct {
-    A_UINT32    sw_version;
-    A_UINT32    abi_version;
-    A_UINT8     macaddr[ATH_MAC_LEN];
-    A_UINT8     phyCapability;              /* WMI_PHY_CAPABILITY */
+    u32 sw_version;
+    u32 abi_version;
+    u8 macaddr[ATH_MAC_LEN];
+    u8 phyCapability;              /* WMI_PHY_CAPABILITY */
 } POSTPACK WMI_READY_EVENT_2;
 
 #if defined(ATH_TARGET)
@@ -2002,15 +2016,15 @@
  * Connect Event
  */
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT16    listenInterval;
-    A_UINT16    beaconInterval;
-    A_UINT32    networkType;
-    A_UINT8     beaconIeLen;
-    A_UINT8     assocReqLen;
-    A_UINT8     assocRespLen;
-    A_UINT8     assocInfo[1];
+    u16 channel;
+    u8 bssid[ATH_MAC_LEN];
+    u16 listenInterval;
+    u16 beaconInterval;
+    u32 networkType;
+    u8 beaconIeLen;
+    u8 assocReqLen;
+    u8 assocRespLen;
+    u8 assocInfo[1];
 } POSTPACK WMI_CONNECT_EVENT;
 
 /*
@@ -2033,11 +2047,11 @@
 } WMI_DISCONNECT_REASON;
 
 typedef PREPACK struct {
-    A_UINT16    protocolReasonStatus;  /* reason code, see 802.11 spec. */
-    A_UINT8     bssid[ATH_MAC_LEN];    /* set if known */
-    A_UINT8     disconnectReason ;      /* see WMI_DISCONNECT_REASON */
-    A_UINT8     assocRespLen;
-    A_UINT8     assocInfo[1];
+    u16 protocolReasonStatus;  /* reason code, see 802.11 spec. */
+    u8 bssid[ATH_MAC_LEN];    /* set if known */
+    u8 disconnectReason ;      /* see WMI_DISCONNECT_REASON */
+    u8 assocRespLen;
+    u8 assocInfo[1];
 } POSTPACK WMI_DISCONNECT_EVENT;
 
 /*
@@ -2059,28 +2073,28 @@
 };
 
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     frameType;          /* see WMI_BI_FTYPE */
-    A_UINT8     snr;
-    A_INT16     rssi;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT32    ieMask;
+    u16 channel;
+    u8 frameType;          /* see WMI_BI_FTYPE */
+    u8 snr;
+    s16 rssi;
+    u8 bssid[ATH_MAC_LEN];
+    u32 ieMask;
 } POSTPACK WMI_BSS_INFO_HDR;
 
 /*
  * BSS INFO HDR version 2.0
  * With 6 bytes HTC header and 6 bytes of WMI header
- * WMI_BSS_INFO_HDR cannot be accomodated in the removed 802.11 management
+ * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management
  * header space.
  * - Reduce the ieMask to 2 bytes as only two bit flags are used
  * - Remove rssi and compute it on the host. rssi = snr - 95
  */
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     frameType;          /* see WMI_BI_FTYPE */
-    A_UINT8     snr;
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT16    ieMask;
+    u16 channel;
+    u8 frameType;          /* see WMI_BI_FTYPE */
+    u8 snr;
+    u8 bssid[ATH_MAC_LEN];
+    u16 ieMask;
 } POSTPACK WMI_BSS_INFO_HDR2;
 
 /*
@@ -2093,29 +2107,29 @@
 } WMI_ERROR_CODE;
 
 typedef PREPACK struct {
-    A_UINT16    commandId;
-    A_UINT8     errorCode;
+    u16 commandId;
+    u8 errorCode;
 } POSTPACK WMI_CMD_ERROR_EVENT;
 
 /*
  * New Regulatory Domain Event
  */
 typedef PREPACK struct {
-    A_UINT32    regDomain;
+    u32 regDomain;
 } POSTPACK WMI_REG_DOMAIN_EVENT;
 
 typedef PREPACK struct {
-    A_UINT8     txQueueNumber;
-    A_UINT8     rxQueueNumber;
-    A_UINT8     trafficDirection;
-    A_UINT8     trafficClass;
+    u8 txQueueNumber;
+    u8 rxQueueNumber;
+    u8 trafficDirection;
+    u8 trafficClass;
 } POSTPACK WMI_PSTREAM_TIMEOUT_EVENT;
 
 typedef PREPACK struct {
-    A_UINT8     reserve1;
-    A_UINT8     reserve2;
-    A_UINT8     reserve3;
-    A_UINT8     trafficClass;
+    u8 reserve1;
+    u8 reserve2;
+    u8 reserve3;
+    u8 trafficClass;
 } POSTPACK WMI_ACM_REJECT_EVENT;
 
 /*
@@ -2134,12 +2148,12 @@
 } WMI_BSS_FLAGS;
 
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT8     bssFlags;            /* see WMI_BSS_FLAGS */
+    u8 bssid[ATH_MAC_LEN];
+    u8 bssFlags;            /* see WMI_BSS_FLAGS */
 } POSTPACK WMI_NEIGHBOR_INFO;
 
 typedef PREPACK struct {
-    A_INT8      numberOfAps;
+    s8 numberOfAps;
     WMI_NEIGHBOR_INFO neighbor[1];
 } POSTPACK WMI_NEIGHBOR_REPORT_EVENT;
 
@@ -2147,15 +2161,15 @@
  * TKIP MIC Error Event
  */
 typedef PREPACK struct {
-    A_UINT8 keyid;
-    A_UINT8 ismcast;
+    u8 keyid;
+    u8 ismcast;
 } POSTPACK WMI_TKIP_MICERR_EVENT;
 
 /*
  * WMI_SCAN_COMPLETE_EVENTID - no parameters (old), staus parameter (new)
  */
 typedef PREPACK struct {
-    A_INT32 status;
+    s32 status;
 } POSTPACK WMI_SCAN_COMPLETE_EVENT;
 
 #define MAX_OPT_DATA_LEN 1400
@@ -2164,7 +2178,7 @@
  * WMI_SET_ADHOC_BSSID_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_SET_ADHOC_BSSID_CMD;
 
 /*
@@ -2176,7 +2190,7 @@
 } OPT_MODE_TYPE;
 
 typedef PREPACK struct {
-    A_UINT8     optMode;
+    u8 optMode;
 } POSTPACK WMI_SET_OPT_MODE_CMD;
 
 /*
@@ -2190,12 +2204,12 @@
 } WMI_OPT_FTYPE;
 
 typedef PREPACK struct {
-    A_UINT16    optIEDataLen;
-    A_UINT8     frmType;
-    A_UINT8     dstAddr[ATH_MAC_LEN];
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT8     reserved;               /* For alignment */
-    A_UINT8     optIEData[1];
+    u16 optIEDataLen;
+    u8 frmType;
+    u8 dstAddr[ATH_MAC_LEN];
+    u8 bssid[ATH_MAC_LEN];
+    u8 reserved;               /* For alignment */
+    u8 optIEData[1];
 } POSTPACK WMI_OPT_TX_FRAME_CMD;
 
 /*
@@ -2205,84 +2219,84 @@
  * The 802.11 header is not included.
  */
 typedef PREPACK struct {
-    A_UINT16    channel;
-    A_UINT8     frameType;          /* see WMI_OPT_FTYPE */
-    A_INT8      snr;
-    A_UINT8     srcAddr[ATH_MAC_LEN];
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u16 channel;
+    u8 frameType;          /* see WMI_OPT_FTYPE */
+    s8 snr;
+    u8 srcAddr[ATH_MAC_LEN];
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_OPT_RX_INFO_HDR;
 
 /*
  * Reporting statistics.
  */
 typedef PREPACK struct {
-    A_UINT32   tx_packets;
-    A_UINT32   tx_bytes;
-    A_UINT32   tx_unicast_pkts;
-    A_UINT32   tx_unicast_bytes;
-    A_UINT32   tx_multicast_pkts;
-    A_UINT32   tx_multicast_bytes;
-    A_UINT32   tx_broadcast_pkts;
-    A_UINT32   tx_broadcast_bytes;
-    A_UINT32   tx_rts_success_cnt;
-    A_UINT32   tx_packet_per_ac[4];
-    A_UINT32   tx_errors_per_ac[4];
+    u32 tx_packets;
+    u32 tx_bytes;
+    u32 tx_unicast_pkts;
+    u32 tx_unicast_bytes;
+    u32 tx_multicast_pkts;
+    u32 tx_multicast_bytes;
+    u32 tx_broadcast_pkts;
+    u32 tx_broadcast_bytes;
+    u32 tx_rts_success_cnt;
+    u32 tx_packet_per_ac[4];
+    u32 tx_errors_per_ac[4];
 
-    A_UINT32   tx_errors;
-    A_UINT32   tx_failed_cnt;
-    A_UINT32   tx_retry_cnt;
-    A_UINT32   tx_mult_retry_cnt;
-    A_UINT32   tx_rts_fail_cnt;
-    A_INT32    tx_unicast_rate;
+    u32 tx_errors;
+    u32 tx_failed_cnt;
+    u32 tx_retry_cnt;
+    u32 tx_mult_retry_cnt;
+    u32 tx_rts_fail_cnt;
+    s32 tx_unicast_rate;
 }POSTPACK tx_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32   rx_packets;
-    A_UINT32   rx_bytes;
-    A_UINT32   rx_unicast_pkts;
-    A_UINT32   rx_unicast_bytes;
-    A_UINT32   rx_multicast_pkts;
-    A_UINT32   rx_multicast_bytes;
-    A_UINT32   rx_broadcast_pkts;
-    A_UINT32   rx_broadcast_bytes;
-    A_UINT32   rx_fragment_pkt;
+    u32 rx_packets;
+    u32 rx_bytes;
+    u32 rx_unicast_pkts;
+    u32 rx_unicast_bytes;
+    u32 rx_multicast_pkts;
+    u32 rx_multicast_bytes;
+    u32 rx_broadcast_pkts;
+    u32 rx_broadcast_bytes;
+    u32 rx_fragment_pkt;
 
-    A_UINT32   rx_errors;
-    A_UINT32   rx_crcerr;
-    A_UINT32   rx_key_cache_miss;
-    A_UINT32   rx_decrypt_err;
-    A_UINT32   rx_duplicate_frames;
-    A_INT32    rx_unicast_rate;
+    u32 rx_errors;
+    u32 rx_crcerr;
+    u32 rx_key_cache_miss;
+    u32 rx_decrypt_err;
+    u32 rx_duplicate_frames;
+    s32 rx_unicast_rate;
 }POSTPACK rx_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32   tkip_local_mic_failure;
-    A_UINT32   tkip_counter_measures_invoked;
-    A_UINT32   tkip_replays;
-    A_UINT32   tkip_format_errors;
-    A_UINT32   ccmp_format_errors;
-    A_UINT32   ccmp_replays;
+    u32 tkip_local_mic_failure;
+    u32 tkip_counter_measures_invoked;
+    u32 tkip_replays;
+    u32 tkip_format_errors;
+    u32 ccmp_format_errors;
+    u32 ccmp_replays;
 }POSTPACK tkip_ccmp_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32   power_save_failure_cnt;
-    A_UINT16   stop_tx_failure_cnt;
-    A_UINT16   atim_tx_failure_cnt;
-    A_UINT16   atim_rx_failure_cnt;
-    A_UINT16   bcn_rx_failure_cnt;
+    u32 power_save_failure_cnt;
+    u16 stop_tx_failure_cnt;
+    u16 atim_tx_failure_cnt;
+    u16 atim_rx_failure_cnt;
+    u16 bcn_rx_failure_cnt;
 }POSTPACK pm_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32    cs_bmiss_cnt;
-    A_UINT32    cs_lowRssi_cnt;
-    A_UINT16    cs_connect_cnt;
-    A_UINT16    cs_disconnect_cnt;
-    A_INT16     cs_aveBeacon_rssi;
-    A_UINT16    cs_roam_count;
-    A_INT16     cs_rssi;
-    A_UINT8     cs_snr;
-    A_UINT8     cs_aveBeacon_snr;
-    A_UINT8     cs_lastRoam_msec;
+    u32 cs_bmiss_cnt;
+    u32 cs_lowRssi_cnt;
+    u16 cs_connect_cnt;
+    u16 cs_disconnect_cnt;
+    s16 cs_aveBeacon_rssi;
+    u16 cs_roam_count;
+    s16 cs_rssi;
+    u8 cs_snr;
+    u8 cs_aveBeacon_snr;
+    u8 cs_lastRoam_msec;
 } POSTPACK cserv_stats_t;
 
 typedef PREPACK struct {
@@ -2292,21 +2306,21 @@
 }POSTPACK wlan_net_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32    arp_received;
-    A_UINT32    arp_matched;
-    A_UINT32    arp_replied;
+    u32 arp_received;
+    u32 arp_matched;
+    u32 arp_replied;
 } POSTPACK arp_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32    wow_num_pkts_dropped;
-    A_UINT16    wow_num_events_discarded;
-    A_UINT8     wow_num_host_pkt_wakeups;
-    A_UINT8     wow_num_host_event_wakeups;
+    u32 wow_num_pkts_dropped;
+    u16 wow_num_events_discarded;
+    u8 wow_num_host_pkt_wakeups;
+    u8 wow_num_host_event_wakeups;
 } POSTPACK wlan_wow_stats_t;
 
 typedef PREPACK struct {
-    A_UINT32            lqVal;
-    A_INT32             noise_floor_calibation;
+    u32 lqVal;
+    s32 noise_floor_calibation;
     pm_stats_t          pmStats;
     wlan_net_stats_t    txrxStats;
     wlan_wow_stats_t    wowStats;
@@ -2335,8 +2349,8 @@
 }WMI_RSSI_THRESHOLD_VAL;
 
 typedef PREPACK struct {
-    A_INT16 rssi;
-    A_UINT8 range;
+    s16 rssi;
+    u8 range;
 }POSTPACK WMI_RSSI_THRESHOLD_EVENT;
 
 /*
@@ -2353,11 +2367,11 @@
 } WMI_TARGET_ERROR_VAL;
 
 typedef PREPACK struct {
-    A_UINT32 errorVal;
+    u32 errorVal;
 }POSTPACK  WMI_TARGET_ERROR_REPORT_EVENT;
 
 typedef PREPACK struct {
-    A_UINT8 retrys;
+    u8 retrys;
 }POSTPACK  WMI_TX_RETRY_ERR_EVENT;
 
 typedef enum{
@@ -2372,8 +2386,8 @@
 } WMI_SNR_THRESHOLD_VAL;
 
 typedef PREPACK struct {
-    A_UINT8 range;  /* WMI_SNR_THRESHOLD_VAL */
-    A_UINT8 snr;
+    u8 range;  /* WMI_SNR_THRESHOLD_VAL */
+    u8 snr;
 }POSTPACK  WMI_SNR_THRESHOLD_EVENT;
 
 typedef enum{
@@ -2388,8 +2402,8 @@
 } WMI_LQ_THRESHOLD_VAL;
 
 typedef PREPACK struct {
-    A_INT32 lq;
-    A_UINT8 range;  /* WMI_LQ_THRESHOLD_VAL */
+    s32 lq;
+    u8 range;  /* WMI_LQ_THRESHOLD_VAL */
 }POSTPACK  WMI_LQ_THRESHOLD_EVENT;
 /*
  * WMI_REPORT_ROAM_TBL_EVENTID
@@ -2397,20 +2411,20 @@
 #define MAX_ROAM_TBL_CAND   5
 
 typedef PREPACK struct {
-    A_INT32 roam_util;
-    A_UINT8 bssid[ATH_MAC_LEN];
-    A_INT8  rssi;
-    A_INT8  rssidt;
-    A_INT8  last_rssi;
-    A_INT8  util;
-    A_INT8  bias;
-    A_UINT8 reserved; /* For alignment */
+    s32 roam_util;
+    u8 bssid[ATH_MAC_LEN];
+    s8 rssi;
+    s8 rssidt;
+    s8 last_rssi;
+    s8 util;
+    s8 bias;
+    u8 reserved; /* For alignment */
 } POSTPACK WMI_BSS_ROAM_INFO;
 
 
 typedef PREPACK struct {
-    A_UINT16  roamMode;
-    A_UINT16  numEntries;
+    u16 roamMode;
+    u16 numEntries;
     WMI_BSS_ROAM_INFO bssRoamInfo[1];
 } POSTPACK WMI_TARGET_ROAM_TBL;
 
@@ -2418,8 +2432,8 @@
  * WMI_HCI_EVENT_EVENTID
  */
 typedef PREPACK struct {
-    A_UINT16    evt_buf_sz;     /* HCI event buffer size */
-    A_UINT8     buf[1];         /* HCI  event */
+    u16 evt_buf_sz;     /* HCI event buffer size */
+    u8 buf[1];         /* HCI  event */
 } POSTPACK WMI_HCI_EVENT;
 
 /*
@@ -2435,10 +2449,10 @@
 #define WMM_TSPEC_IE_LEN   63
 
 typedef PREPACK struct {
-    A_UINT8 ac;
-    A_UINT8 cac_indication;
-    A_UINT8 statusCode;
-    A_UINT8 tspecSuggestion[WMM_TSPEC_IE_LEN];
+    u8 ac;
+    u8 cac_indication;
+    u8 statusCode;
+    u8 tspecSuggestion[WMM_TSPEC_IE_LEN];
 }POSTPACK  WMI_CAC_EVENT;
 
 /*
@@ -2450,8 +2464,8 @@
 } APLIST_VER;
 
 typedef PREPACK struct {
-    A_UINT8     bssid[ATH_MAC_LEN];
-    A_UINT16    channel;
+    u8 bssid[ATH_MAC_LEN];
+    u16 channel;
 } POSTPACK  WMI_AP_INFO_V1;
 
 typedef PREPACK union {
@@ -2459,8 +2473,8 @@
 } POSTPACK WMI_AP_INFO;
 
 typedef PREPACK struct {
-    A_UINT8     apListVer;
-    A_UINT8     numAP;
+    u8 apListVer;
+    u8 numAP;
     WMI_AP_INFO apList[1];
 } POSTPACK WMI_APLIST_EVENT;
 
@@ -2506,14 +2520,14 @@
 } WMI_BIT_RATE;
 
 typedef PREPACK struct {
-    A_INT8      rateIndex;          /* see WMI_BIT_RATE */
-    A_INT8      mgmtRateIndex;
-    A_INT8      ctlRateIndex;
+    s8 rateIndex;          /* see WMI_BIT_RATE */
+    s8 mgmtRateIndex;
+    s8 ctlRateIndex;
 } POSTPACK WMI_BIT_RATE_CMD;
 
 
 typedef PREPACK struct {
-    A_INT8      rateIndex;          /* see WMI_BIT_RATE */
+    s8 rateIndex;          /* see WMI_BIT_RATE */
 } POSTPACK  WMI_BIT_RATE_REPLY;
 
 
@@ -2522,43 +2536,43 @@
  *
  * Get fix rates cmd uses same definition as set fix rates cmd
  */
-#define FIX_RATE_1Mb            ((A_UINT32)0x1)
-#define FIX_RATE_2Mb            ((A_UINT32)0x2)
-#define FIX_RATE_5_5Mb          ((A_UINT32)0x4)
-#define FIX_RATE_11Mb           ((A_UINT32)0x8)
-#define FIX_RATE_6Mb            ((A_UINT32)0x10)
-#define FIX_RATE_9Mb            ((A_UINT32)0x20)
-#define FIX_RATE_12Mb           ((A_UINT32)0x40)
-#define FIX_RATE_18Mb           ((A_UINT32)0x80)
-#define FIX_RATE_24Mb           ((A_UINT32)0x100)
-#define FIX_RATE_36Mb           ((A_UINT32)0x200)
-#define FIX_RATE_48Mb           ((A_UINT32)0x400)
-#define FIX_RATE_54Mb           ((A_UINT32)0x800)
-#define FIX_RATE_MCS_0_20       ((A_UINT32)0x1000)
-#define FIX_RATE_MCS_1_20       ((A_UINT32)0x2000)
-#define FIX_RATE_MCS_2_20       ((A_UINT32)0x4000)
-#define FIX_RATE_MCS_3_20       ((A_UINT32)0x8000)
-#define FIX_RATE_MCS_4_20       ((A_UINT32)0x10000)
-#define FIX_RATE_MCS_5_20       ((A_UINT32)0x20000)
-#define FIX_RATE_MCS_6_20       ((A_UINT32)0x40000)
-#define FIX_RATE_MCS_7_20       ((A_UINT32)0x80000)
-#define FIX_RATE_MCS_0_40       ((A_UINT32)0x100000)
-#define FIX_RATE_MCS_1_40       ((A_UINT32)0x200000)
-#define FIX_RATE_MCS_2_40       ((A_UINT32)0x400000)
-#define FIX_RATE_MCS_3_40       ((A_UINT32)0x800000)
-#define FIX_RATE_MCS_4_40       ((A_UINT32)0x1000000)
-#define FIX_RATE_MCS_5_40       ((A_UINT32)0x2000000)
-#define FIX_RATE_MCS_6_40       ((A_UINT32)0x4000000)
-#define FIX_RATE_MCS_7_40       ((A_UINT32)0x8000000)
+#define FIX_RATE_1Mb            ((u32)0x1)
+#define FIX_RATE_2Mb            ((u32)0x2)
+#define FIX_RATE_5_5Mb          ((u32)0x4)
+#define FIX_RATE_11Mb           ((u32)0x8)
+#define FIX_RATE_6Mb            ((u32)0x10)
+#define FIX_RATE_9Mb            ((u32)0x20)
+#define FIX_RATE_12Mb           ((u32)0x40)
+#define FIX_RATE_18Mb           ((u32)0x80)
+#define FIX_RATE_24Mb           ((u32)0x100)
+#define FIX_RATE_36Mb           ((u32)0x200)
+#define FIX_RATE_48Mb           ((u32)0x400)
+#define FIX_RATE_54Mb           ((u32)0x800)
+#define FIX_RATE_MCS_0_20       ((u32)0x1000)
+#define FIX_RATE_MCS_1_20       ((u32)0x2000)
+#define FIX_RATE_MCS_2_20       ((u32)0x4000)
+#define FIX_RATE_MCS_3_20       ((u32)0x8000)
+#define FIX_RATE_MCS_4_20       ((u32)0x10000)
+#define FIX_RATE_MCS_5_20       ((u32)0x20000)
+#define FIX_RATE_MCS_6_20       ((u32)0x40000)
+#define FIX_RATE_MCS_7_20       ((u32)0x80000)
+#define FIX_RATE_MCS_0_40       ((u32)0x100000)
+#define FIX_RATE_MCS_1_40       ((u32)0x200000)
+#define FIX_RATE_MCS_2_40       ((u32)0x400000)
+#define FIX_RATE_MCS_3_40       ((u32)0x800000)
+#define FIX_RATE_MCS_4_40       ((u32)0x1000000)
+#define FIX_RATE_MCS_5_40       ((u32)0x2000000)
+#define FIX_RATE_MCS_6_40       ((u32)0x4000000)
+#define FIX_RATE_MCS_7_40       ((u32)0x8000000)
 
 typedef PREPACK struct {
-    A_UINT32      fixRateMask;          /* see WMI_BIT_RATE */
+    u32 fixRateMask;          /* see WMI_BIT_RATE */
 } POSTPACK WMI_FIX_RATES_CMD, WMI_FIX_RATES_REPLY;
 
 typedef PREPACK struct {
-    A_UINT8        bEnableMask;
-    A_UINT8        frameType;               /*type and subtype*/
-    A_UINT32     frameRateMask;          /* see WMI_BIT_RATE */
+    u8 bEnableMask;
+    u8 frameType;               /*type and subtype*/
+    u32 frameRateMask;          /* see WMI_BIT_RATE */
 } POSTPACK WMI_FRAME_RATES_CMD, WMI_FRAME_RATES_REPLY;
 
 /*
@@ -2572,7 +2586,7 @@
 } WMI_AUTH_MODE;
 
 typedef PREPACK struct {
-    A_UINT8 mode;
+    u8 mode;
 } POSTPACK WMI_SET_AUTH_MODE_CMD;
 
 /*
@@ -2586,7 +2600,7 @@
 } WMI_REASSOC_MODE;
 
 typedef PREPACK struct {
-    A_UINT8 mode;
+    u8 mode;
 }POSTPACK WMI_SET_REASSOC_MODE_CMD;
 
 typedef enum {
@@ -2594,21 +2608,21 @@
 } ROAM_DATA_TYPE;
 
 typedef PREPACK struct {
-    A_UINT32        disassoc_time;
-    A_UINT32        no_txrx_time;
-    A_UINT32        assoc_time;
-    A_UINT32        allow_txrx_time;
-    A_UINT8         disassoc_bssid[ATH_MAC_LEN];
-    A_INT8          disassoc_bss_rssi;
-    A_UINT8         assoc_bssid[ATH_MAC_LEN];
-    A_INT8          assoc_bss_rssi;
+    u32 disassoc_time;
+    u32 no_txrx_time;
+    u32 assoc_time;
+    u32 allow_txrx_time;
+    u8 disassoc_bssid[ATH_MAC_LEN];
+    s8 disassoc_bss_rssi;
+    u8 assoc_bssid[ATH_MAC_LEN];
+    s8 assoc_bss_rssi;
 } POSTPACK WMI_TARGET_ROAM_TIME;
 
 typedef PREPACK struct {
     PREPACK union {
         WMI_TARGET_ROAM_TIME roamTime;
     } POSTPACK u;
-    A_UINT8 roamDataType ;
+    u8 roamDataType ;
 } POSTPACK WMI_TARGET_ROAM_DATA;
 
 typedef enum {
@@ -2617,11 +2631,11 @@
 } WMI_WMM_STATUS;
 
 typedef PREPACK struct {
-    A_UINT8    status;
+    u8 status;
 }POSTPACK WMI_SET_WMM_CMD;
 
 typedef PREPACK struct {
-    A_UINT8    status;
+    u8 status;
 }POSTPACK WMI_SET_QOS_SUPP_CMD;
 
 typedef enum {
@@ -2630,16 +2644,16 @@
 } WMI_TXOP_CFG;
 
 typedef PREPACK struct {
-    A_UINT8    txopEnable;
+    u8 txopEnable;
 }POSTPACK WMI_SET_WMM_TXOP_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 keepaliveInterval;
+    u8 keepaliveInterval;
 } POSTPACK WMI_SET_KEEPALIVE_CMD;
 
 typedef PREPACK struct {
-    A_BOOL configured;
-    A_UINT8 keepaliveInterval;
+    u32 configured;
+    u8 keepaliveInterval;
 } POSTPACK WMI_GET_KEEPALIVE_CMD;
 
 /*
@@ -2648,9 +2662,9 @@
 #define WMI_MAX_IE_LEN  255
 
 typedef PREPACK struct {
-    A_UINT8 mgmtFrmType;  /* one of WMI_MGMT_FRAME_TYPE */
-    A_UINT8 ieLen;    /* Length  of the IE that should be added to the MGMT frame */
-    A_UINT8 ieInfo[1];
+    u8 mgmtFrmType;  /* one of WMI_MGMT_FRAME_TYPE */
+    u8 ieLen;    /* Length  of the IE that should be added to the MGMT frame */
+    u8 ieInfo[1];
 } POSTPACK WMI_SET_APPIE_CMD;
 
 /*
@@ -2665,12 +2679,12 @@
 }WHAL_CMDID;
 
 typedef PREPACK struct {
-    A_UINT8 cabTimeOut;
+    u8 cabTimeOut;
 } POSTPACK WHAL_SETCABTO_PARAM;
 
 typedef PREPACK struct {
-    A_UINT8  whalCmdId;
-    A_UINT8 data[1];
+    u8 whalCmdId;
+    u8 data[1];
 } POSTPACK WHAL_PARAMCMD;
 
 
@@ -2682,43 +2696,43 @@
 #define MAC_MAX_FILTERS_PER_LIST 4
 
 typedef PREPACK struct {
-    A_UINT8 wow_valid_filter;
-    A_UINT8 wow_filter_id;
-    A_UINT8 wow_filter_size;
-    A_UINT8 wow_filter_offset;
-    A_UINT8 wow_filter_mask[WOW_MASK_SIZE];
-    A_UINT8 wow_filter_pattern[WOW_PATTERN_SIZE];
+    u8 wow_valid_filter;
+    u8 wow_filter_id;
+    u8 wow_filter_size;
+    u8 wow_filter_offset;
+    u8 wow_filter_mask[WOW_MASK_SIZE];
+    u8 wow_filter_pattern[WOW_PATTERN_SIZE];
 } POSTPACK WOW_FILTER;
 
 
 typedef PREPACK struct {
-    A_UINT8 wow_valid_list;
-    A_UINT8 wow_list_id;
-    A_UINT8 wow_num_filters;
-    A_UINT8 wow_total_list_size;
+    u8 wow_valid_list;
+    u8 wow_list_id;
+    u8 wow_num_filters;
+    u8 wow_total_list_size;
     WOW_FILTER list[WOW_MAX_FILTERS_PER_LIST];
 } POSTPACK WOW_FILTER_LIST;
 
 typedef PREPACK struct {
-    A_UINT8 valid_filter;
-    A_UINT8 mac_addr[ATH_MAC_LEN];
+    u8 valid_filter;
+    u8 mac_addr[ATH_MAC_LEN];
 } POSTPACK MAC_FILTER;
 
 
 typedef PREPACK struct {
-    A_UINT8 total_list_size;
-    A_UINT8 enable;
+    u8 total_list_size;
+    u8 enable;
     MAC_FILTER list[MAC_MAX_FILTERS_PER_LIST];
 } POSTPACK MAC_FILTER_LIST;
 
 #define MAX_IP_ADDRS  2
 typedef PREPACK struct {
-    A_UINT32 ips[MAX_IP_ADDRS];  /* IP in Network Byte Order */
+    u32 ips[MAX_IP_ADDRS];  /* IP in Network Byte Order */
 } POSTPACK WMI_SET_IP_CMD;
 
 typedef PREPACK struct {
-    A_BOOL awake;
-    A_BOOL asleep;
+    u32 awake;
+    u32 asleep;
 } POSTPACK WMI_SET_HOST_SLEEP_MODE_CMD;
 
 typedef enum {
@@ -2726,40 +2740,40 @@
 } WMI_WOW_FILTER;
 
 typedef PREPACK struct {
-    A_BOOL enable_wow;
+    u32 enable_wow;
     WMI_WOW_FILTER filter;
-    A_UINT16 hostReqDelay;
+    u16 hostReqDelay;
 } POSTPACK WMI_SET_WOW_MODE_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 filter_list_id;
+    u8 filter_list_id;
 } POSTPACK WMI_GET_WOW_LIST_CMD;
 
 /*
  * WMI_GET_WOW_LIST_CMD reply
  */
 typedef PREPACK struct {
-    A_UINT8     num_filters;     /* number of patterns in reply */
-    A_UINT8     this_filter_num; /*  this is filter # x of total num_filters */
-    A_UINT8     wow_mode;
-    A_UINT8     host_mode;
+    u8 num_filters;     /* number of patterns in reply */
+    u8 this_filter_num; /*  this is filter # x of total num_filters */
+    u8 wow_mode;
+    u8 host_mode;
     WOW_FILTER  wow_filters[1];
 } POSTPACK WMI_GET_WOW_LIST_REPLY;
 
 typedef PREPACK struct {
-    A_UINT8 filter_list_id;
-    A_UINT8 filter_size;
-    A_UINT8 filter_offset;
-    A_UINT8 filter[1];
+    u8 filter_list_id;
+    u8 filter_size;
+    u8 filter_offset;
+    u8 filter[1];
 } POSTPACK WMI_ADD_WOW_PATTERN_CMD;
 
 typedef PREPACK struct {
-    A_UINT16 filter_list_id;
-    A_UINT16 filter_id;
+    u16 filter_list_id;
+    u16 filter_id;
 } POSTPACK WMI_DEL_WOW_PATTERN_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 macaddr[ATH_MAC_LEN];
+    u8 macaddr[ATH_MAC_LEN];
 } POSTPACK WMI_SET_MAC_ADDRESS_CMD;
 
 /*
@@ -2769,11 +2783,11 @@
 #define WMI_AKMP_MULTI_PMKID_EN   0x000001
 
 typedef PREPACK struct {
-    A_UINT32    akmpInfo;
+    u32 akmpInfo;
 } POSTPACK WMI_SET_AKMP_PARAMS_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 pmkid[WMI_PMKID_LEN];
+    u8 pmkid[WMI_PMKID_LEN];
 } POSTPACK WMI_PMKID;
 
 /*
@@ -2782,7 +2796,7 @@
 #define WMI_MAX_PMKID_CACHE   8
 
 typedef PREPACK struct {
-    A_UINT32    numPMKID;
+    u32 numPMKID;
     WMI_PMKID   pmkidList[WMI_MAX_PMKID_CACHE];
 } POSTPACK WMI_SET_PMKID_LIST_CMD;
 
@@ -2791,34 +2805,34 @@
  * Following the Number of PMKIDs is the list of PMKIDs
  */
 typedef PREPACK struct {
-    A_UINT32    numPMKID;
-    A_UINT8     bssidList[ATH_MAC_LEN][1];
+    u32 numPMKID;
+    u8 bssidList[ATH_MAC_LEN][1];
     WMI_PMKID   pmkidList[1];
 } POSTPACK WMI_PMKID_LIST_REPLY;
 
 typedef PREPACK struct {
-    A_UINT16 oldChannel;
-    A_UINT32 newChannel;
+    u16 oldChannel;
+    u32 newChannel;
 } POSTPACK WMI_CHANNEL_CHANGE_EVENT;
 
 typedef PREPACK struct {
-    A_UINT32 version;
+    u32 version;
 } POSTPACK WMI_WLAN_VERSION_EVENT;
 
 
 /* WMI_ADDBA_REQ_EVENTID */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     win_sz;
-    A_UINT16    st_seq_no;
-    A_UINT8     status;         /* f/w response for ADDBA Req; OK(0) or failure(!=0) */
+    u8 tid;
+    u8 win_sz;
+    u16 st_seq_no;
+    u8 status;         /* f/w response for ADDBA Req; OK(0) or failure(!=0) */
 } POSTPACK WMI_ADDBA_REQ_EVENT;
 
 /* WMI_ADDBA_RESP_EVENTID */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     status;         /* OK(0), failure (!=0) */
-    A_UINT16    amsdu_sz;       /* Three values: Not supported(0), 3839, 8k */
+    u8 tid;
+    u8 status;         /* OK(0), failure (!=0) */
+    u16 amsdu_sz;       /* Three values: Not supported(0), 3839, 8k */
 } POSTPACK WMI_ADDBA_RESP_EVENT;
 
 /* WMI_DELBA_EVENTID
@@ -2826,9 +2840,9 @@
  * Host is notified of this
  */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     is_peer_initiator;
-    A_UINT16    reason_code;
+    u8 tid;
+    u8 is_peer_initiator;
+    u16 reason_code;
 } POSTPACK WMI_DELBA_EVENT;
 
 
@@ -2836,8 +2850,8 @@
 #define WAPI_REKEY_UCAST    1
 #define WAPI_REKEY_MCAST    2
 typedef PREPACK struct {
-    A_UINT8     type;
-    A_UINT8     macAddr[ATH_MAC_LEN];
+    u8 type;
+    u8 macAddr[ATH_MAC_LEN];
 } POSTPACK WMI_WAPIREKEY_EVENT;
 #endif
 
@@ -2847,8 +2861,8 @@
  * on each tid, in each direction
  */
 typedef PREPACK struct {
-    A_UINT16    tx_allow_aggr;  /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/
-    A_UINT16    rx_allow_aggr;  /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/
+    u16 tx_allow_aggr;  /* 16-bit mask to allow uplink ADDBA negotiation - bit position indicates tid*/
+    u16 rx_allow_aggr;  /* 16-bit mask to allow donwlink ADDBA negotiation - bit position indicates tid*/
 } POSTPACK WMI_ALLOW_AGGR_CMD;
 
 /* WMI_ADDBA_REQ_CMDID
@@ -2856,7 +2870,7 @@
  * on the given tid
  */
 typedef PREPACK struct {
-    A_UINT8     tid;
+    u8 tid;
 } POSTPACK WMI_ADDBA_REQ_CMD;
 
 /* WMI_DELBA_REQ_CMDID
@@ -2864,8 +2878,8 @@
  * is_send_initiator indicates if it's or tx or rx side
  */
 typedef PREPACK struct {
-    A_UINT8     tid;
-    A_UINT8     is_sender_initiator;
+    u8 tid;
+    u8 is_sender_initiator;
 
 } POSTPACK WMI_DELBA_REQ_CMD;
 
@@ -2874,8 +2888,8 @@
 #define PEER_FIRST_NODE_JOIN_EVENT 0x10
 #define PEER_LAST_NODE_LEAVE_EVENT 0x11
 typedef PREPACK struct {
-    A_UINT8 eventCode;
-    A_UINT8 peerMacAddr[ATH_MAC_LEN];
+    u8 eventCode;
+    u8 peerMacAddr[ATH_MAC_LEN];
 } POSTPACK WMI_PEER_NODE_EVENT;
 
 #define IEEE80211_FRAME_TYPE_MGT          0x00
@@ -2893,21 +2907,21 @@
 #define TX_COMPLETE_STATUS_TIMEOUT 3
 #define TX_COMPLETE_STATUS_OTHER   4
 
-    A_UINT8 status; /* one of TX_COMPLETE_STATUS_... */
-    A_UINT8 pktID; /* packet ID to identify parent packet */
-    A_UINT8 rateIdx; /* rate index on successful transmission */
-    A_UINT8 ackFailures; /* number of ACK failures in tx attempt */
-#if 0 /* optional params currently ommitted. */
-    A_UINT32 queueDelay; // usec delay measured Tx Start time - host delivery time
-    A_UINT32 mediaDelay; // usec delay measured ACK rx time - host delivery time
+    u8 status; /* one of TX_COMPLETE_STATUS_... */
+    u8 pktID; /* packet ID to identify parent packet */
+    u8 rateIdx; /* rate index on successful transmission */
+    u8 ackFailures; /* number of ACK failures in tx attempt */
+#if 0 /* optional params currently omitted. */
+    u32 queueDelay; // usec delay measured Tx Start time - host delivery time
+    u32 mediaDelay; // usec delay measured ACK rx time - host delivery time
 #endif
 } POSTPACK TX_COMPLETE_MSG_V1; /* version 1 of tx complete msg */
 
 typedef PREPACK struct {
-    A_UINT8 numMessages; /* number of tx comp msgs following this struct */
-    A_UINT8 msgLen; /* length in bytes for each individual msg following this struct */
-    A_UINT8 msgType; /* version of tx complete msg data following this struct */
-    A_UINT8 reserved; /* individual messages follow this header */
+    u8 numMessages; /* number of tx comp msgs following this struct */
+    u8 msgLen; /* length in bytes for each individual msg following this struct */
+    u8 msgType; /* version of tx complete msg data following this struct */
+    u8 reserved; /* individual messages follow this header */
 } POSTPACK WMI_TX_COMPLETE_EVENT;
 
 #define WMI_TXCOMPLETE_VERSION_1 (0x01)
@@ -2946,7 +2960,7 @@
 #define HIDDEN_SSID_FALSE   0
 #define HIDDEN_SSID_TRUE    1
 typedef PREPACK struct {
-    A_UINT8     hidden_ssid;
+    u8 hidden_ssid;
 } POSTPACK WMI_AP_HIDDEN_SSID_CMD;
 
 /*
@@ -2957,7 +2971,7 @@
 #define AP_ACL_DENY_MAC         0x02
 #define AP_ACL_RETAIN_LIST_MASK 0x80
 typedef PREPACK struct {
-    A_UINT8     policy;
+    u8 policy;
 } POSTPACK WMI_AP_ACL_POLICY_CMD;
 
 /*
@@ -2966,33 +2980,33 @@
 #define ADD_MAC_ADDR    1
 #define DEL_MAC_ADDR    2
 typedef PREPACK struct {
-    A_UINT8     action;
-    A_UINT8     index;
-    A_UINT8     mac[ATH_MAC_LEN];
-    A_UINT8     wildcard;
+    u8 action;
+    u8 index;
+    u8 mac[ATH_MAC_LEN];
+    u8 wildcard;
 } POSTPACK WMI_AP_ACL_MAC_CMD;
 
 typedef PREPACK struct {
-    A_UINT16    index;
-    A_UINT8     acl_mac[AP_ACL_SIZE][ATH_MAC_LEN];
-    A_UINT8     wildcard[AP_ACL_SIZE];
-    A_UINT8     policy;
+    u16 index;
+    u8 acl_mac[AP_ACL_SIZE][ATH_MAC_LEN];
+    u8 wildcard[AP_ACL_SIZE];
+    u8 policy;
 } POSTPACK WMI_AP_ACL;
 
 /*
  * Used with WMI_AP_SET_NUM_STA_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8     num_sta;
+    u8 num_sta;
 } POSTPACK WMI_AP_SET_NUM_STA_CMD;
 
 /*
  * Used with WMI_AP_SET_MLME_CMDID
  */
 typedef PREPACK struct {
-    A_UINT8    mac[ATH_MAC_LEN];
-    A_UINT16   reason;              /* 802.11 reason code */
-    A_UINT8    cmd;                 /* operation to perform */
+    u8 mac[ATH_MAC_LEN];
+    u16 reason;              /* 802.11 reason code */
+    u8 cmd;                 /* operation to perform */
 #define WMI_AP_MLME_ASSOC       1   /* associate station */
 #define WMI_AP_DISASSOC         2   /* disassociate station */
 #define WMI_AP_DEAUTH           3   /* deauthenticate station */
@@ -3001,108 +3015,108 @@
 } POSTPACK WMI_AP_SET_MLME_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 period;
+    u32 period;
 } POSTPACK WMI_AP_CONN_INACT_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 period_min;
-    A_UINT32 dwell_ms;
+    u32 period_min;
+    u32 dwell_ms;
 } POSTPACK WMI_AP_PROT_SCAN_TIME_CMD;
 
 typedef PREPACK struct {
-    A_BOOL flag;
-    A_UINT16 aid;
+    u32 flag;
+    u16 aid;
 } POSTPACK WMI_AP_SET_PVB_CMD;
 
 #define WMI_DISABLE_REGULATORY_CODE "FF"
 
 typedef PREPACK struct {
-    A_UCHAR countryCode[3];
+    u8 countryCode[3];
 } POSTPACK WMI_AP_SET_COUNTRY_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 dtim;
+    u8 dtim;
 } POSTPACK WMI_AP_SET_DTIM_CMD;
 
 typedef PREPACK struct {
-    A_UINT8  band; /* specifies which band to apply these values */
-    A_UINT8  enable; /* allows 11n to be disabled on a per band basis */    
-    A_UINT8  chan_width_40M_supported;
-    A_UINT8  short_GI_20MHz;
-    A_UINT8  short_GI_40MHz;
-    A_UINT8  intolerance_40MHz;
-    A_UINT8  max_ampdu_len_exp;
+    u8 band; /* specifies which band to apply these values */
+    u8 enable; /* allows 11n to be disabled on a per band basis */
+    u8 chan_width_40M_supported;
+    u8 short_GI_20MHz;
+    u8 short_GI_40MHz;
+    u8 intolerance_40MHz;
+    u8 max_ampdu_len_exp;
 } POSTPACK WMI_SET_HT_CAP_CMD;
 
 typedef PREPACK struct {
-    A_UINT8   sta_chan_width;
+    u8 sta_chan_width;
 } POSTPACK WMI_SET_HT_OP_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 rateMasks[8];
+    u32 rateMasks[8];
 } POSTPACK WMI_SET_TX_SELECT_RATES_CMD;
 
 typedef PREPACK struct {
-    A_UINT32    sgiMask;
-    A_UINT8     sgiPERThreshold;
+    u32 sgiMask;
+    u8 sgiPERThreshold;
 } POSTPACK WMI_SET_TX_SGI_PARAM_CMD;
 
 #define DEFAULT_SGI_MASK 0x08080000
 #define DEFAULT_SGI_PER 10
 
 typedef PREPACK struct {
-    A_UINT32 rateField; /* 1 bit per rate corresponding to index */
-    A_UINT8 id;
-    A_UINT8 shortTrys;
-    A_UINT8 longTrys;
-    A_UINT8 reserved; /* padding */
+    u32 rateField; /* 1 bit per rate corresponding to index */
+    u8 id;
+    u8 shortTrys;
+    u8 longTrys;
+    u8 reserved; /* padding */
 } POSTPACK WMI_SET_RATE_POLICY_CMD;
 
 typedef PREPACK struct {
-    A_UINT8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */
-    A_UINT8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 <default> */
-    A_UINT8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target <default> */
-    A_UINT8 reserved[1]; /* alignment */
+    u8 metaVersion; /* version of meta data for rx packets <0 = default> (0-7 = valid) */
+    u8 dot11Hdr; /* 1 == leave .11 header intact , 0 == replace .11 header with .3 <default> */
+    u8 defragOnHost; /* 1 == defragmentation is performed by host, 0 == performed by target <default> */
+    u8 reserved[1]; /* alignment */
 } POSTPACK WMI_RX_FRAME_FORMAT_CMD;
 
 
 typedef PREPACK struct {
-    A_UINT8 enable;     /* 1 == device operates in thin mode , 0 == normal mode <default> */
-    A_UINT8 reserved[3];
+    u8 enable;     /* 1 == device operates in thin mode , 0 == normal mode <default> */
+    u8 reserved[3];
 } POSTPACK WMI_SET_THIN_MODE_CMD;
 
 /* AP mode events */
 /* WMI_PS_POLL_EVENT */
 typedef PREPACK struct {
-    A_UINT16 aid;
+    u16 aid;
 } POSTPACK WMI_PSPOLL_EVENT;
 
 typedef PREPACK struct {
-    A_UINT32 tx_bytes;
-    A_UINT32 tx_pkts;
-    A_UINT32 tx_error;
-    A_UINT32 tx_discard;
-    A_UINT32 rx_bytes;
-    A_UINT32 rx_pkts;
-    A_UINT32 rx_error;
-    A_UINT32 rx_discard;
-    A_UINT32 aid;
+    u32 tx_bytes;
+    u32 tx_pkts;
+    u32 tx_error;
+    u32 tx_discard;
+    u32 rx_bytes;
+    u32 rx_pkts;
+    u32 rx_error;
+    u32 rx_discard;
+    u32 aid;
 } POSTPACK WMI_PER_STA_STAT;
 
 #define AP_GET_STATS    0
 #define AP_CLEAR_STATS  1
 
 typedef PREPACK struct {
-    A_UINT32            action;
+    u32 action;
     WMI_PER_STA_STAT    sta[AP_MAX_NUM_STA+1];
 } POSTPACK WMI_AP_MODE_STAT;
-#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(A_UINT32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT)))
+#define WMI_AP_MODE_STAT_SIZE(numSta) (sizeof(u32) + ((numSta + 1) * sizeof(WMI_PER_STA_STAT)))
 
 #define AP_11BG_RATESET1        1
 #define AP_11BG_RATESET2        2
 #define DEF_AP_11BG_RATESET     AP_11BG_RATESET1
 typedef PREPACK struct {
-    A_UINT8 rateset;
+    u8 rateset;
 } POSTPACK WMI_AP_SET_11BG_RATESET_CMD;
 /*
  * End of AP mode definitions
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wmi_thin.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wmi_thin.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wmi_thin.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wmi_thin.h	2011-05-19 00:06:34.000000000 -0400
@@ -101,9 +101,9 @@
  *  disabled by default but can be enabled using this structure and the 
  *  WMI_THIN_CONFIG_CMDID. */
 typedef PREPACK struct {
-    A_UINT8     version; /* the versioned type of messages to use or 0 to disable */
-    A_UINT8     countThreshold; /* msg count threshold triggering a tx complete message */
-    A_UINT16    timeThreshold; /* timeout interval in MSEC triggering a tx complete message */       
+    u8 version; /* the versioned type of messages to use or 0 to disable */
+    u8 countThreshold; /* msg count threshold triggering a tx complete message */
+    u16 timeThreshold; /* timeout interval in MSEC triggering a tx complete message */
 } POSTPACK WMI_THIN_CONFIG_TXCOMPLETE;
 
 /* WMI_THIN_CONFIG_DECRYPT_ERR -- Used to configure behavior for received frames 
@@ -111,22 +111,22 @@
  *  without notification. Alternately, the MAC Header is forwarded to the host 
  *  with the failed status. */
 typedef PREPACK struct {
-    A_UINT8     enable; /* 1 == send decrypt errors to the host, 0 == don't */
-    A_UINT8     reserved[3]; /* align padding */
+    u8 enable; /* 1 == send decrypt errors to the host, 0 == don't */
+    u8 reserved[3]; /* align padding */
 } POSTPACK WMI_THIN_CONFIG_DECRYPT_ERR;
 
 /* WMI_THIN_CONFIG_TX_MAC_RULES -- Used to configure behavior for transmitted
  *  frames that require partial MAC header construction. These rules 
  *  are used by the target to indicate which fields need to be written. */
 typedef PREPACK struct {
-    A_UINT32    rules; /* combination of WMI_WRT_... values */     
+    u32 rules; /* combination of WMI_WRT_... values */
 } POSTPACK WMI_THIN_CONFIG_TX_MAC_RULES;
 
 /* WMI_THIN_CONFIG_RX_FILTER_RULES -- Used to configure behavior for received
  *  frames as to which frames should get forwarded to the host and which
  *  should get processed internally. */
 typedef PREPACK struct {
-    A_UINT32    rules; /* combination of WMI_FILT_... values */     
+    u32 rules; /* combination of WMI_FILT_... values */
 } POSTPACK WMI_THIN_CONFIG_RX_FILTER_RULES;
 
 /* WMI_THIN_CONFIG_CMD -- Used to contain some combination of the above
@@ -138,9 +138,9 @@
 #define WMI_THIN_CFG_DECRYPT        0x00000002
 #define WMI_THIN_CFG_MAC_RULES      0x00000004
 #define WMI_THIN_CFG_FILTER_RULES   0x00000008
-    A_UINT32    cfgField;   /* combination of WMI_THIN_CFG_... describes contents of config command */
-    A_UINT16    length;     /* length in bytes of appended sub-commands */        
-    A_UINT8     reserved[2];   /* align padding */
+    u32 cfgField;   /* combination of WMI_THIN_CFG_... describes contents of config command */
+    u16 length;     /* length in bytes of appended sub-commands */
+    u8 reserved[2];   /* align padding */
 } POSTPACK WMI_THIN_CONFIG_CMD;
 
 /* MIB Access Identifiers tailored for Symbian. */
@@ -176,35 +176,35 @@
 };
 
 typedef PREPACK struct {
-    A_UINT8 addr[ATH_MAC_LEN];
+    u8 addr[ATH_MAC_LEN];
 } POSTPACK WMI_THIN_MIB_STA_MAC;
 
 typedef PREPACK struct {
-    A_UINT32 time; // units == msec
+    u32 time; // units == msec
 } POSTPACK WMI_THIN_MIB_RX_LIFE_TIME;
 
 typedef PREPACK struct {
-    A_UINT8 enable; //1 = on, 0 = off
+    u8 enable; //1 = on, 0 = off
 } POSTPACK WMI_THIN_MIB_CTS_TO_SELF;
 
 typedef PREPACK struct {
-    A_UINT32 time; // units == usec
+    u32 time; // units == usec
 } POSTPACK WMI_THIN_MIB_SLOT_TIME;
 
 typedef PREPACK struct {
-    A_UINT16 length; //units == bytes
+    u16 length; //units == bytes
 } POSTPACK WMI_THIN_MIB_RTS_THRESHOLD;
 
 typedef PREPACK struct {
-    A_UINT8 type; // type of frame
-    A_UINT8 rate; // tx rate to be used (one of WMI_BIT_RATE)
-    A_UINT16 length; // num bytes following this structure as the template data
+    u8 type; // type of frame
+    u8 rate; // tx rate to be used (one of WMI_BIT_RATE)
+    u16 length; // num bytes following this structure as the template data
 } POSTPACK WMI_THIN_MIB_TEMPLATE_FRAME;
 
 typedef PREPACK struct {
 #define FRAME_FILTER_PROMISCUOUS 0x00000001
 #define FRAME_FILTER_BSSID       0x00000002
-    A_UINT32 filterMask; 
+    u32 filterMask;
 } POSTPACK WMI_THIN_MIB_RXFRAME_FILTER;
 
 
@@ -212,110 +212,110 @@
 #define IE_FILTER_TREATMENT_APPEAR 2
 
 typedef PREPACK struct {
-    A_UINT8 ie;
-    A_UINT8 treatment;
+    u8 ie;
+    u8 treatment;
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER_TABLE;
 
 typedef PREPACK struct {
-    A_UINT8 ie;
-    A_UINT8 treatment;
-    A_UINT8 oui[3];
-    A_UINT8 type;
-    A_UINT16 version;
+    u8 ie;
+    u8 treatment;
+    u8 oui[3];
+    u8 type;
+    u16 version;
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER_TABLE_OUI;
 
 typedef PREPACK struct {
-    A_UINT16 numElements;
-    A_UINT8 entrySize; // sizeof(WMI_THIN_MIB_BEACON_FILTER_TABLE) on host cpu may be 2 may be 4
-    A_UINT8 reserved;
+    u16 numElements;
+    u8 entrySize; // sizeof(WMI_THIN_MIB_BEACON_FILTER_TABLE) on host cpu may be 2 may be 4
+    u8 reserved;
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER_TABLE_HEADER; 
 
 typedef PREPACK struct {
-    A_UINT32 count; /* num beacons between deliveries */
-    A_UINT8 enable;
-    A_UINT8 reserved[3];
+    u32 count; /* num beacons between deliveries */
+    u8 enable;
+    u8 reserved[3];
 } POSTPACK WMI_THIN_MIB_BEACON_FILTER;
 
 typedef PREPACK struct {
-    A_UINT32 count; /* num consec lost beacons after which send event */
+    u32 count; /* num consec lost beacons after which send event */
 } POSTPACK WMI_THIN_MIB_BEACON_LOST_COUNT;
 
 typedef PREPACK struct {
-    A_UINT8 rssi; /* the low threshold which can trigger an event warning */
-    A_UINT8 tolerance; /* the range above and below the threshold to prevent event flooding to the host. */
-    A_UINT8 count; /* the sample count of consecutive frames necessary to trigger an event. */
-    A_UINT8 reserved[1]; /* padding */
+    u8 rssi; /* the low threshold which can trigger an event warning */
+    u8 tolerance; /* the range above and below the threshold to prevent event flooding to the host. */
+    u8 count; /* the sample count of consecutive frames necessary to trigger an event. */
+    u8 reserved[1]; /* padding */
 } POSTPACK WMI_THIN_MIB_RSSI_THRESHOLD;
 
 
 typedef PREPACK struct {
-    A_UINT32 cap;
-    A_UINT32 rxRateField;
-    A_UINT32 beamForming;
-    A_UINT8 addr[ATH_MAC_LEN];
-    A_UINT8 enable;        
-    A_UINT8 stbc;
-    A_UINT8 maxAMPDU;    
-    A_UINT8 msduSpacing;
-    A_UINT8 mcsFeedback;   
-    A_UINT8 antennaSelCap;    
+    u32 cap;
+    u32 rxRateField;
+    u32 beamForming;
+    u8 addr[ATH_MAC_LEN];
+    u8 enable;
+    u8 stbc;
+    u8 maxAMPDU;
+    u8 msduSpacing;
+    u8 mcsFeedback;
+    u8 antennaSelCap;
 } POSTPACK WMI_THIN_MIB_HT_CAP;
 
 typedef PREPACK struct {
-    A_UINT32 infoField;
-    A_UINT32 basicRateField;
-    A_UINT8 protection;
-    A_UINT8 secondChanneloffset;
-    A_UINT8 channelWidth;
-    A_UINT8 reserved;
+    u32 infoField;
+    u32 basicRateField;
+    u8 protection;
+    u8 secondChanneloffset;
+    u8 channelWidth;
+    u8 reserved;
 } POSTPACK WMI_THIN_MIB_HT_OP;
 
 typedef PREPACK struct {
 #define SECOND_BEACON_PRIMARY   1
 #define SECOND_BEACON_EITHER    2
 #define SECOND_BEACON_SECONDARY 3
-    A_UINT8 cfg;
-    A_UINT8 reserved[3]; /* padding */
+    u8 cfg;
+    u8 reserved[3]; /* padding */
 } POSTPACK WMI_THIN_MIB_HT_2ND_BEACON;
 
 typedef PREPACK struct {
-    A_UINT8 txTIDField;
-    A_UINT8 rxTIDField;
-    A_UINT8 reserved[2]; /* padding */
+    u8 txTIDField;
+    u8 rxTIDField;
+    u8 reserved[2]; /* padding */
 } POSTPACK WMI_THIN_MIB_HT_BLOCK_ACK;
 
 typedef PREPACK struct {
-    A_UINT8 enableLong; // 1 == long preamble, 0 == short preamble
-    A_UINT8 reserved[3];
+    u8 enableLong; // 1 == long preamble, 0 == short preamble
+    u8 reserved[3];
 } POSTPACK WMI_THIN_MIB_PREAMBLE;
 
 typedef PREPACK struct {    
-    A_UINT16    length;     /* the length in bytes of the appended MIB data */
-    A_UINT8     mibID;      /* the ID of the MIB element being set */
-    A_UINT8     reserved; /* align padding */
+    u16 length;     /* the length in bytes of the appended MIB data */
+    u8 mibID;      /* the ID of the MIB element being set */
+    u8 reserved; /* align padding */
 } POSTPACK WMI_THIN_SET_MIB_CMD;
 
 typedef PREPACK struct {    
-    A_UINT8     mibID;      /* the ID of the MIB element being set */
-    A_UINT8     reserved[3]; /* align padding */
+    u8 mibID;      /* the ID of the MIB element being set */
+    u8 reserved[3]; /* align padding */
 } POSTPACK WMI_THIN_GET_MIB_CMD;
 
 typedef PREPACK struct {
-    A_UINT32    basicRateMask; /* bit mask of basic rates */
-    A_UINT32    beaconIntval; /* TUs */
-    A_UINT16    atimWindow; /* TUs */
-    A_UINT16    channel; /* frequency in Mhz */
-    A_UINT8     networkType; /* INFRA_NETWORK | ADHOC_NETWORK */
-    A_UINT8     ssidLength; /* 0 - 32 */
-    A_UINT8     probe;      /* != 0 : issue probe req at start */
-    A_UINT8     reserved;   /* alignment */    
-    A_UCHAR     ssid[WMI_MAX_SSID_LEN];    
-    A_UINT8     bssid[ATH_MAC_LEN];
+    u32 basicRateMask; /* bit mask of basic rates */
+    u32 beaconIntval; /* TUs */
+    u16 atimWindow; /* TUs */
+    u16 channel; /* frequency in Mhz */
+    u8 networkType; /* INFRA_NETWORK | ADHOC_NETWORK */
+    u8 ssidLength; /* 0 - 32 */
+    u8 probe;      /* != 0 : issue probe req at start */
+    u8 reserved;   /* alignment */
+    u8     ssid[WMI_MAX_SSID_LEN];    
+    u8 bssid[ATH_MAC_LEN];
 } POSTPACK WMI_THIN_JOIN_CMD;
 
 typedef PREPACK struct {
-    A_UINT16 dtim; /* dtim interval in num beacons */
-    A_UINT16 aid; /* 80211 AID from Assoc resp */   
+    u16 dtim; /* dtim interval in num beacons */
+    u16 aid; /* 80211 AID from Assoc resp */
 } POSTPACK WMI_THIN_POST_ASSOC_CMD;
 
 typedef enum {
@@ -336,8 +336,8 @@
 }WMI_THIN_JOIN_RESULT;
 
 typedef PREPACK struct {
-    A_UINT8 result; /* the result of the join cmd. one of WMI_THIN_JOIN_RESULT */
-    A_UINT8 reserved[3]; /* alignment */
+    u8 result; /* the result of the join cmd. one of WMI_THIN_JOIN_RESULT */
+    u8 reserved[3]; /* alignment */
 } POSTPACK WMI_THIN_JOIN_EVENT;
 
 #ifdef __cplusplus
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wmix.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wmix.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common/wmix.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common/wmix.h	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,7 @@
  * WMI_EVENT_ID=WMI_EXTENSION_EVENTID.
  */
 typedef PREPACK struct {
-    A_UINT32    commandId;
+    u32 commandId;
 } POSTPACK WMIX_CMD_HDR;
 
 typedef enum {
@@ -96,10 +96,10 @@
  * DataSet Open Request Event
  */
 typedef PREPACK struct {
-    A_UINT32 dset_id;
-    A_UINT32 targ_dset_handle;  /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_fn;     /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_arg;    /* echo'ed, not used by Host, */
+    u32 dset_id;
+    u32 targ_dset_handle;  /* echo'ed, not used by Host, */
+    u32 targ_reply_fn;     /* echo'ed, not used by Host, */
+    u32 targ_reply_arg;    /* echo'ed, not used by Host, */
 } POSTPACK WMIX_DSETOPENREQ_EVENT;
 
 /*
@@ -107,7 +107,7 @@
  * DataSet Close Event
  */
 typedef PREPACK struct {
-    A_UINT32 access_cookie;
+    u32 access_cookie;
 } POSTPACK WMIX_DSETCLOSE_EVENT;
 
 /*
@@ -115,31 +115,31 @@
  * DataSet Data Request Event
  */
 typedef PREPACK struct {
-    A_UINT32 access_cookie;
-    A_UINT32 offset;
-    A_UINT32 length;
-    A_UINT32 targ_buf;         /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_fn;    /* echo'ed, not used by Host, */
-    A_UINT32 targ_reply_arg;   /* echo'ed, not used by Host, */
+    u32 access_cookie;
+    u32 offset;
+    u32 length;
+    u32 targ_buf;         /* echo'ed, not used by Host, */
+    u32 targ_reply_fn;    /* echo'ed, not used by Host, */
+    u32 targ_reply_arg;   /* echo'ed, not used by Host, */
 } POSTPACK WMIX_DSETDATAREQ_EVENT;
 
 typedef PREPACK struct {
-    A_UINT32              status;
-    A_UINT32              targ_dset_handle;
-    A_UINT32              targ_reply_fn;
-    A_UINT32              targ_reply_arg;
-    A_UINT32              access_cookie;
-    A_UINT32              size;
-    A_UINT32              version;
+    u32 status;
+    u32 targ_dset_handle;
+    u32 targ_reply_fn;
+    u32 targ_reply_arg;
+    u32 access_cookie;
+    u32 size;
+    u32 version;
 } POSTPACK WMIX_DSETOPEN_REPLY_CMD;
 
 typedef PREPACK struct {
-    A_UINT32              status;
-    A_UINT32              targ_buf;
-    A_UINT32              targ_reply_fn;
-    A_UINT32              targ_reply_arg;
-    A_UINT32              length;
-    A_UINT8               buf[1];
+    u32 status;
+    u32 targ_buf;
+    u32 targ_reply_fn;
+    u32 targ_reply_arg;
+    u32 length;
+    u8 buf[1];
 } POSTPACK WMIX_DSETDATA_REPLY_CMD;
 
 
@@ -160,10 +160,10 @@
  * clear/disable or disable/enable, results are undefined.
  */
 typedef PREPACK struct {
-    A_UINT32              set_mask;             /* pins to set */
-    A_UINT32              clear_mask;           /* pins to clear */
-    A_UINT32              enable_mask;          /* pins to enable for output */
-    A_UINT32              disable_mask;         /* pins to disable/tristate */
+    u32 set_mask;             /* pins to set */
+    u32 clear_mask;           /* pins to clear */
+    u32 enable_mask;          /* pins to enable for output */
+    u32 disable_mask;         /* pins to disable/tristate */
 } POSTPACK WMIX_GPIO_OUTPUT_SET_CMD;
 
 /* 
@@ -172,13 +172,13 @@
  * platform-dependent header.
  */
 typedef PREPACK struct {
-    A_UINT32              gpioreg_id;           /* GPIO register ID */
-    A_UINT32              value;                /* value to write */
+    u32 gpioreg_id;           /* GPIO register ID */
+    u32 value;                /* value to write */
 } POSTPACK WMIX_GPIO_REGISTER_SET_CMD;
 
 /* Get a GPIO register.  For debug/exceptional cases. */
 typedef PREPACK struct {
-    A_UINT32              gpioreg_id;           /* GPIO register to read */
+    u32 gpioreg_id;           /* GPIO register to read */
 } POSTPACK WMIX_GPIO_REGISTER_GET_CMD;
 
 /*
@@ -187,18 +187,18 @@
  * were delivered in an earlier WMIX_GPIO_INTR_EVENT message.
  */
 typedef PREPACK struct {
-    A_UINT32              ack_mask;             /* interrupts to acknowledge */
+    u32 ack_mask;             /* interrupts to acknowledge */
 } POSTPACK WMIX_GPIO_INTR_ACK_CMD;
 
 /*
- * Target informs Host of GPIO interrupts that have ocurred since the
+ * Target informs Host of GPIO interrupts that have occurred since the
  * last WMIX_GIPO_INTR_ACK_CMD was received.  Additional information --
  * the current GPIO input values is provided -- in order to support
  * use of a GPIO interrupt as a Data Valid signal for other GPIO pins.
  */
 typedef PREPACK struct {
-    A_UINT32              intr_mask;            /* pending GPIO interrupts */
-    A_UINT32              input_values;         /* recent GPIO input values */
+    u32 intr_mask;            /* pending GPIO interrupts */
+    u32 input_values;         /* recent GPIO input values */
 } POSTPACK WMIX_GPIO_INTR_EVENT;
 
 /*
@@ -217,8 +217,8 @@
  * simplify Host GPIO support.
  */
 typedef PREPACK struct {
-    A_UINT32              value;
-    A_UINT32              reg_id;
+    u32 value;
+    u32 reg_id;
 } POSTPACK WMIX_GPIO_DATA_EVENT;
 
 /*
@@ -230,8 +230,8 @@
  * Heartbeat Challenge Response command
  */
 typedef PREPACK struct {
-    A_UINT32              cookie;
-    A_UINT32              source;
+    u32 cookie;
+    u32 source;
 } POSTPACK WMIX_HB_CHALLENGE_RESP_CMD;
 
 /*
@@ -249,12 +249,12 @@
  */
 
 typedef PREPACK struct {
-    A_UINT32 period; /* Time (in 30.5us ticks) between samples */
-    A_UINT32 nbins;
+    u32 period; /* Time (in 30.5us ticks) between samples */
+    u32 nbins;
 } POSTPACK WMIX_PROF_CFG_CMD;
 
 typedef PREPACK struct {
-    A_UINT32 addr;
+    u32 addr;
 } POSTPACK WMIX_PROF_ADDR_SET_CMD;
 
 /*
@@ -264,8 +264,8 @@
  *   count set to the corresponding count
  */
 typedef PREPACK struct {
-    A_UINT32              addr;
-    A_UINT32              count;
+    u32 addr;
+    u32 count;
 } POSTPACK WMIX_PROF_COUNT_EVENT;
 
 #ifndef ATH_TARGET
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common_drv.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common_drv.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/common_drv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/common_drv.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,23 +29,23 @@
 /* structure that is the state information for the default credit distribution callback
  * drivers should instantiate (zero-init as well) this structure in their driver instance
  * and pass it as a context to the HTC credit distribution functions */
-typedef struct _COMMON_CREDIT_STATE_INFO {
+struct common_credit_state_info {
     int TotalAvailableCredits;      /* total credits in the system at startup */
     int CurrentFreeCredits;         /* credits available in the pool that have not been
                                        given out to endpoints */
-    HTC_ENDPOINT_CREDIT_DIST *pLowestPriEpDist;  /* pointer to the lowest priority endpoint dist struct */
-} COMMON_CREDIT_STATE_INFO;
+    struct htc_endpoint_credit_dist *pLowestPriEpDist;  /* pointer to the lowest priority endpoint dist struct */
+};
 
-typedef struct {
-    A_INT32 (*setupTransport)(void *ar);
+struct hci_transport_callbacks {
+    s32 (*setupTransport)(void *ar);
     void (*cleanupTransport)(void *ar);
-} HCI_TRANSPORT_CALLBACKS;
+};
 
-typedef struct {
+struct hci_transport_misc_handles {
    void *netDevice;
    void *hifDevice;
    void *htcHandle;
-} HCI_TRANSPORT_MISC_HANDLES;
+};
 
 /* HTC TX packet tagging definitions */
 #define AR6K_CONTROL_PKT_TAG    HTC_TX_PACKET_TAG_USER_DEFINED
@@ -64,42 +64,42 @@
 #endif
 
 /* OS-independent APIs */
-A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo);
+int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo);
 
-A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
-A_STATUS ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,  A_UCHAR *data, A_UINT32 length);
+int ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,  u8 *data, u32 length);
 
-A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset);
+int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset);
 
-void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
+void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType);
 
-A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    MboxIsrYieldValue,
-                               A_UINT8     HtcControlBuffers);
+int ar6000_set_htc_params(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 MboxIsrYieldValue,
+                               u8 HtcControlBuffers);
 
-A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    TargetVersion);
+int ar6000_prepare_target(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 TargetVersion);
 
-A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
-                                     A_UINT32    TargetType,
-                                     A_UINT32    Flags);
+int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice,
+                                     u32 TargetType,
+                                     u32 Flags);
 
-void ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType);
+void ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType);
 
-A_UINT8 *ar6000_get_cust_data_buffer(A_UINT32 TargetType);
+u8 *ar6000_get_cust_data_buffer(u32 TargetType);
 
-A_STATUS ar6000_setBTState(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setBTState(void *context, u8 *pInBuf, u32 InBufSize);
 
-A_STATUS ar6000_setDevicePowerState(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setDevicePowerState(void *context, u8 *pInBuf, u32 InBufSize);
 
-A_STATUS ar6000_setWowMode(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setWowMode(void *context, u8 *pInBuf, u32 InBufSize);
 
-A_STATUS ar6000_setHostMode(void *context, A_UINT8 *pInBuf, A_UINT32 InBufSize);
+int ar6000_setHostMode(void *context, u8 *pInBuf, u32 InBufSize);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/dl_list.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/dl_list.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/dl_list.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/dl_list.h	2011-05-19 00:06:34.000000000 -0400
@@ -32,10 +32,10 @@
          
 /* list functions */
 /* pointers for the list */
-typedef struct _DL_LIST {
-    struct _DL_LIST *pPrev;
-    struct _DL_LIST *pNext;
-}DL_LIST, *PDL_LIST;
+struct dl_list {
+	struct dl_list *pPrev;
+	struct dl_list *pNext;
+};
 /*
  * DL_LIST_INIT , initialize doubly linked list
 */
@@ -67,7 +67,7 @@
  */
 #define ITERATE_OVER_LIST_ALLOW_REMOVE(pStart,pItem,st,offset)  \
 {                                                       \
-    PDL_LIST  pTemp;                                     \
+    struct dl_list *  pTemp;                                     \
     pTemp = (pStart)->pNext;                            \
     while (pTemp != (pStart)) {                         \
         (pItem) = A_CONTAINING_STRUCT(pTemp,st,offset);   \
@@ -78,7 +78,7 @@
 /*
  * DL_ListInsertTail - insert pAdd to the end of the list
 */
-static INLINE PDL_LIST DL_ListInsertTail(PDL_LIST pList, PDL_LIST pAdd) {
+static INLINE struct dl_list *DL_ListInsertTail(struct dl_list *pList, struct dl_list *pAdd) {
         /* insert at tail */
     pAdd->pPrev = pList->pPrev;
     pAdd->pNext = pList;
@@ -90,7 +90,7 @@
 /*
  * DL_ListInsertHead - insert pAdd into the head of the list
 */
-static INLINE PDL_LIST DL_ListInsertHead(PDL_LIST pList, PDL_LIST pAdd) {
+static INLINE struct dl_list * DL_ListInsertHead(struct dl_list * pList, struct dl_list * pAdd) {
         /* insert at head */
     pAdd->pPrev = pList;
     pAdd->pNext = pList->pNext;
@@ -103,7 +103,7 @@
 /*
  * DL_ListRemove - remove pDel from list
 */
-static INLINE PDL_LIST DL_ListRemove(PDL_LIST pDel) {
+static INLINE struct dl_list * DL_ListRemove(struct dl_list * pDel) {
     pDel->pNext->pPrev = pDel->pPrev;
     pDel->pPrev->pNext = pDel->pNext;
         /* point back to itself just to be safe, incase remove is called again */
@@ -115,8 +115,8 @@
 /*
  * DL_ListRemoveItemFromHead - get a list item from the head
 */
-static INLINE PDL_LIST DL_ListRemoveItemFromHead(PDL_LIST pList) {
-    PDL_LIST pItem = NULL;
+static INLINE struct dl_list * DL_ListRemoveItemFromHead(struct dl_list * pList) {
+    struct dl_list * pItem = NULL;
     if (pList->pNext != pList) {
         pItem = pList->pNext;
             /* remove the first item from head */
@@ -125,8 +125,8 @@
     return pItem;
 }
 
-static INLINE PDL_LIST DL_ListRemoveItemFromTail(PDL_LIST pList) {
-    PDL_LIST pItem = NULL;
+static INLINE struct dl_list * DL_ListRemoveItemFromTail(struct dl_list * pList) {
+    struct dl_list * pItem = NULL;
     if (pList->pPrev != pList) {
         pItem = pList->pPrev;
             /* remove the item from tail */
@@ -136,7 +136,7 @@
 }
 
 /* transfer src list items to the tail of the destination list */
-static INLINE void DL_ListTransferItemsToTail(PDL_LIST pDest, PDL_LIST pSrc) {
+static INLINE void DL_ListTransferItemsToTail(struct dl_list * pDest, struct dl_list * pSrc) {
         /* only concatenate if src is not empty */
     if (!DL_LIST_IS_EMPTY(pSrc)) {
             /* cut out circular list in src and re-attach to end of dest */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/dset_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/dset_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/dset_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/dset_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -39,23 +39,23 @@
 #endif
 
 /* Called to send a DataSet Open Reply back to the Target. */
-A_STATUS wmi_dset_open_reply(struct wmi_t *wmip,
-                             A_UINT32 status,
-                             A_UINT32 access_cookie,
-                             A_UINT32 size,
-                             A_UINT32 version,
-                             A_UINT32 targ_handle,
-                             A_UINT32 targ_reply_fn,
-                             A_UINT32 targ_reply_arg);
+int wmi_dset_open_reply(struct wmi_t *wmip,
+                             u32 status,
+                             u32 access_cookie,
+                             u32 size,
+                             u32 version,
+                             u32 targ_handle,
+                             u32 targ_reply_fn,
+                             u32 targ_reply_arg);
 
 /* Called to send a DataSet Data Reply back to the Target. */
-A_STATUS wmi_dset_data_reply(struct wmi_t *wmip,
-                             A_UINT32 status,
-                             A_UINT8 *host_buf,
-                             A_UINT32 length,
-                             A_UINT32 targ_buf,
-                             A_UINT32 targ_reply_fn,
-                             A_UINT32 targ_reply_arg);
+int wmi_dset_data_reply(struct wmi_t *wmip,
+                             u32 status,
+                             u8 *host_buf,
+                             u32 length,
+                             u32 targ_buf,
+                             u32 targ_reply_fn,
+                             u32 targ_reply_arg);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/gpio_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/gpio_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/gpio_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/gpio_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -28,32 +28,32 @@
 /*
  * Send a command to the Target in order to change output on GPIO pins.
  */
-A_STATUS wmi_gpio_output_set(struct wmi_t *wmip,
-                             A_UINT32 set_mask,
-                             A_UINT32 clear_mask,
-                             A_UINT32 enable_mask,
-                             A_UINT32 disable_mask);
+int wmi_gpio_output_set(struct wmi_t *wmip,
+                             u32 set_mask,
+                             u32 clear_mask,
+                             u32 enable_mask,
+                             u32 disable_mask);
 
 /*
  * Send a command to the Target requesting input state of GPIO pins.
  */
-A_STATUS wmi_gpio_input_get(struct wmi_t *wmip);
+int wmi_gpio_input_get(struct wmi_t *wmip);
 
 /*
  * Send a command to the Target to change the value of a GPIO register.
  */
-A_STATUS wmi_gpio_register_set(struct wmi_t *wmip,
-                               A_UINT32 gpioreg_id,
-                               A_UINT32 value);
+int wmi_gpio_register_set(struct wmi_t *wmip,
+                               u32 gpioreg_id,
+                               u32 value);
 
 /*
  * Send a command to the Target to fetch the value of a GPIO register.
  */
-A_STATUS wmi_gpio_register_get(struct wmi_t *wmip, A_UINT32 gpioreg_id);
+int wmi_gpio_register_get(struct wmi_t *wmip, u32 gpioreg_id);
 
 /*
  * Send a command to the Target, acknowledging some GPIO interrupts.
  */
-A_STATUS wmi_gpio_intr_ack(struct wmi_t *wmip, A_UINT32 ack_mask);
+int wmi_gpio_intr_ack(struct wmi_t *wmip, u32 ack_mask);
 
 #endif /* _GPIO_API_H_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/hci_transport_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/hci_transport_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/hci_transport_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/hci_transport_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -43,9 +43,9 @@
 #define HCI_SET_PACKET_TYPE(pP,s)  (pP)->Endpoint = (s)
 
 /* callback when an HCI packet was completely sent */
-typedef void   (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, HTC_PACKET *);
+typedef void   (*HCI_TRANSPORT_SEND_PKT_COMPLETE)(void *, struct htc_packet *);
 /* callback when an HCI packet is received */
-typedef void   (*HCI_TRANSPORT_RECV_PKT)(void *, HTC_PACKET *);
+typedef void   (*HCI_TRANSPORT_RECV_PKT)(void *, struct htc_packet *);
 /* Optional receive buffer re-fill callback,
  * On some OSes (like Linux) packets are allocated from a global pool and indicated up
  * to the network stack.  The driver never gets the packets back from the OS.  For these OSes
@@ -68,7 +68,7 @@
  * NOTE*** This callback is mutually exclusive with the the refill callback above.
  *
  * */
-typedef HTC_PACKET *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length);
+typedef struct htc_packet *(*HCI_TRANSPORT_RECV_ALLOC)(void *, HCI_TRANSPORT_PACKET_TYPE Type, int Length);
 
 typedef enum _HCI_SEND_FULL_ACTION {
     HCI_SEND_FULL_KEEP = 0,  /* packet that overflowed should be kept in the queue */
@@ -77,21 +77,21 @@
 
 /* callback when an HCI send queue exceeds the caller's MaxSendQueueDepth threshold,
  * the callback must return the send full action to take (either DROP or KEEP) */
-typedef HCI_SEND_FULL_ACTION  (*HCI_TRANSPORT_SEND_FULL)(void *, HTC_PACKET *);
+typedef HCI_SEND_FULL_ACTION  (*HCI_TRANSPORT_SEND_FULL)(void *, struct htc_packet *);
 
-typedef struct {
+struct hci_transport_properties {
     int    HeadRoom;      /* number of bytes in front of HCI packet for header space */
     int    TailRoom;      /* number of bytes at the end of the HCI packet for tail space */
     int    IOBlockPad;    /* I/O block padding required (always a power of 2) */
-} HCI_TRANSPORT_PROPERTIES;
+};
 
-typedef struct _HCI_TRANSPORT_CONFIG_INFO {
+struct hci_transport_config_info {
     int      ACLRecvBufferWaterMark;     /* low watermark to trigger recv refill */
     int      EventRecvBufferWaterMark;   /* low watermark to trigger recv refill */  
     int      MaxSendQueueDepth;          /* max number of packets in the single send queue */
     void     *pContext;                  /* context for all callbacks */
-    void     (*TransportFailure)(void *pContext, A_STATUS Status); /* transport failure callback */
-    A_STATUS (*TransportReady)(HCI_TRANSPORT_HANDLE, HCI_TRANSPORT_PROPERTIES *,void *pContext); /* transport is ready */
+    void     (*TransportFailure)(void *pContext, int Status); /* transport failure callback */
+    int (*TransportReady)(HCI_TRANSPORT_HANDLE, struct hci_transport_properties *,void *pContext); /* transport is ready */
     void     (*TransportRemoved)(void *pContext);                  /* transport was removed */
         /* packet processing callbacks */
     HCI_TRANSPORT_SEND_PKT_COMPLETE    pHCISendComplete;
@@ -99,7 +99,7 @@
     HCI_TRANSPORT_RECV_REFILL          pHCIPktRecvRefill;
     HCI_TRANSPORT_RECV_ALLOC           pHCIPktRecvAlloc;
     HCI_TRANSPORT_SEND_FULL            pHCISendFull;
-} HCI_TRANSPORT_CONFIG_INFO;
+};
 
 /* ------ Function Prototypes ------ */
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -113,7 +113,7 @@
   @example:
   @see also: HCI_TransportDetach
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+HCI_TRANSPORT_HANDLE HCI_TransportAttach(void *HTCHandle, struct hci_transport_config_info *pInfo);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Detach from the HCI transport module
@@ -134,14 +134,14 @@
   @input:  HciTrans - HCI transport handle
            pQueue - a queue holding one or more packets
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes:  user must supply HTC packets for capturing incomming HCI packets.  The caller
            must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
            macro. Each packet in the queue must be of the same type and length 
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
+int    HCI_TransportAddReceivePkts(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Send an HCI packet packet
@@ -150,12 +150,12 @@
            pPacket - packet to send
            Synchronous - send the packet synchronously (blocking)
   @output:
-  @return: A_OK
+  @return: 0
   @notes:  Caller must initialize packet using SET_HTC_PACKET_INFO_TX() and
            HCI_SET_PACKET_TYPE() macros to prepare the packet. 
-           If Synchronous is set to FALSE the call is fully asynchronous.  On error or completion, 
+           If Synchronous is set to false the call is fully asynchronous.  On error or completion,
            the registered send complete callback will be called.
-           If Synchronous is set to TRUE, the call will block until the packet is sent, if the
+           If Synchronous is set to true, the call will block until the packet is sent, if the
            interface cannot send the packet within a 2 second timeout, the function will return 
            the failure code : A_EBUSY.
            
@@ -166,7 +166,7 @@
   @example:
   @see also: 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
+int    HCI_TransportSendPkt(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
 
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -187,13 +187,13 @@
   @function name: HCI_TransportStart
   @input:  HciTrans - hci transport handle 
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes: HCI transport communication will begin, the caller can expect the arrival
           of HCI recv packets as soon as this call returns.
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
+int    HCI_TransportStart(HCI_TRANSPORT_HANDLE HciTrans);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Enable or Disable Asynchronous Recv
@@ -201,12 +201,12 @@
   @input:  HciTrans - hci transport handle 
            Enable - enable or disable asynchronous recv
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes: This API must be called when HCI recv is handled synchronously
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+int    HCI_TransportEnableDisableAsyncRecv(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Receive an event packet from the HCI transport synchronously using polling
@@ -215,15 +215,15 @@
            pPacket - HTC packet to hold the recv data
            MaxPollMS - maximum polling duration in Milliseconds;
   @output: 
-  @return: A_OK on success
+  @return: 0 on success
   @notes: This API should be used only during HCI device initialization, the caller must call
-          HCI_TransportEnableDisableAsyncRecv with Enable=FALSE prior to using this API. 
+          HCI_TransportEnableDisableAsyncRecv with Enable=false prior to using this API.
           This API will only capture HCI Event packets.
   @example:
   @see also: HCI_TransportEnableDisableAsyncRecv
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans, 
-                                          HTC_PACKET           *pPacket,
+int    HCI_TransportRecvHCIEventSync(HCI_TRANSPORT_HANDLE HciTrans,
+                                          struct htc_packet           *pPacket,
                                           int                  MaxPollMS);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -232,12 +232,12 @@
   @input:  HciTrans - hci transport handle 
            Baud - baud rate in bps
   @output: 
-  @return: A_OK on success
+  @return: 0 on success
   @notes: This API should be used only after HCI device initialization
   @example:
   @see also: 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
+int    HCI_TransportSetBaudRate(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Enable/Disable HCI Transport Power Management
@@ -245,12 +245,12 @@
   @input:  HciTrans - hci transport handle 
            Enable - 1 = Enable, 0 = Disable
   @output: 
-  @return: A_OK on success
+  @return: 0 on success
   @notes: 
   @example:
   @see also: 
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+int HCI_TransportEnablePowerMgmt(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/hif.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/hif.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/hif.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/hif.h	2011-05-19 00:06:34.000000000 -0400
@@ -38,7 +38,7 @@
 
 
 typedef struct htc_callbacks HTC_CALLBACKS;
-typedef struct hif_device HIF_DEVICE;
+struct hif_device;
 
 /*
  * direction - Direction of transfer (HIF_READ/HIF_WRITE).
@@ -153,7 +153,7 @@
  *
  *   HIF_DEVICE_GET_MBOX_ADDR
  *   input : none
- *   output : HIF_DEVICE_MBOX_INFO
+ *   output : struct hif_device_mbox_info
  *   notes: 
  *
  *   HIF_DEVICE_GET_PENDING_EVENTS_FUNC
@@ -190,7 +190,7 @@
  *   HIF_DEVICE_GET_IRQ_YIELD_PARAMS
  * 
  *   input : none
- *   output : HIF_DEVICE_IRQ_YIELD_PARAMS
+ *   output : struct hif_device_irq_yield_params
  *   note: This query checks if the HIF layer wishes to impose a processing yield count for the DSR handler.
  *   The DSR callback handler will exit after a fixed number of RX packets or events are processed.  
  *   This query is only made if the device reports an IRQ processing mode of HIF_DEVICE_IRQ_SYNC_ONLY. 
@@ -203,7 +203,7 @@
  *   
  *   HIF_CONFIGURE_QUERY_SCATTER_REQUEST_SUPPORT
  *   input : none
- *   output : HIF_DEVICE_SCATTER_SUPPORT_INFO
+ *   output : struct hif_device_scatter_support_info
  *   note:  This query checks if the HIF layer implements the SCATTER request interface.  Scatter requests
  *   allows upper layers to submit mailbox I/O operations using a list of buffers.  This is useful for
  *   multi-message transfers that can better utilize the bus interconnect.
@@ -211,7 +211,7 @@
  * 
  *   HIF_DEVICE_GET_OS_DEVICE
  *   intput : none
- *   output : HIF_DEVICE_OS_DEVICE_INFO;
+ *   output : struct hif_device_os_device_info;
  *   note: On some operating systems, the HIF layer has a parent device object for the bus.  This object
  *         may be required to register certain types of logical devices.
  * 
@@ -223,10 +223,10 @@
  * 
  */
 
-typedef struct {
-    A_UINT32    ExtendedAddress;  /* extended address for larger writes */  
-    A_UINT32    ExtendedSize;
-} HIF_MBOX_PROPERTIES;
+struct hif_mbox_properties {
+    u32 ExtendedAddress;  /* extended address for larger writes */
+    u32 ExtendedSize;
+};
 
 #define HIF_MBOX_FLAG_NO_BUNDLING   (1 << 0)   /* do not allow bundling over the mailbox */
 
@@ -235,19 +235,19 @@
     MBOX_BUS_IF_SPI = 1,    
 } MBOX_BUF_IF_TYPE;
 
-typedef struct {
-    A_UINT32 MboxAddresses[4];  /* must be first element for legacy HIFs that return the address in  
+struct hif_device_mbox_info {
+    u32 MboxAddresses[4];  /* must be first element for legacy HIFs that return the address in
                                    and ARRAY of 32-bit words */
     
         /* the following describe extended mailbox properties */
-    HIF_MBOX_PROPERTIES MboxProp[4];
+    struct hif_mbox_properties MboxProp[4];
         /* if the HIF supports the GMbox extended address region it can report it
          * here, some interfaces cannot support the GMBOX address range and not set this */
-    A_UINT32 GMboxAddress;  
-    A_UINT32 GMboxSize;
-    A_UINT32 Flags;             /* flags to describe mbox behavior or usage */
+    u32 GMboxAddress;
+    u32 GMboxSize;
+    u32 Flags;             /* flags to describe mbox behavior or usage */
     MBOX_BUF_IF_TYPE MboxBusIFType;   /* mailbox bus interface type */
-} HIF_DEVICE_MBOX_INFO;
+};
 
 typedef enum {
     HIF_DEVICE_IRQ_SYNC_ONLY,   /* for HIF implementations that require the DSR to process all
@@ -265,20 +265,19 @@
                             */
 } HIF_DEVICE_POWER_CHANGE_TYPE;
 
-typedef struct {
+struct hif_device_irq_yield_params {
     int     RecvPacketYieldCount; /* max number of packets to force DSR to return */
-} HIF_DEVICE_IRQ_YIELD_PARAMS;
+};
 
 
-typedef struct _HIF_SCATTER_ITEM {
-    A_UINT8     *pBuffer;             /* CPU accessible address of buffer */
+struct hif_scatter_item {
+    u8 *pBuffer;             /* CPU accessible address of buffer */
     int          Length;              /* length of transfer to/from this buffer */
     void        *pCallerContexts[2];  /* space for caller to insert a context associated with this item */
-} HIF_SCATTER_ITEM;
-
-struct _HIF_SCATTER_REQ;
+};
 
-typedef void ( *HIF_SCATTER_COMP_CB)(struct _HIF_SCATTER_REQ *);
+struct hif_scatter_req;
+typedef void ( *HIF_SCATTER_COMP_CB)(struct hif_scatter_req *);
 
 typedef enum _HIF_SCATTER_METHOD {
     HIF_SCATTER_NONE = 0,
@@ -286,84 +285,84 @@
     HIF_SCATTER_DMA_BOUNCE,            /* Uses SG DMA but HIF layer uses an internal bounce buffer */    
 } HIF_SCATTER_METHOD;
 
-typedef struct _HIF_SCATTER_REQ {
-    DL_LIST             ListLink;           /* link management */
-    A_UINT32            Address;            /* address for the read/write operation */
-    A_UINT32            Request;            /* request flags */
-    A_UINT32            TotalLength;        /* total length of entire transfer */
-    A_UINT32            CallerFlags;        /* caller specific flags can be stored here */
+struct hif_scatter_req {
+    struct dl_list             ListLink;           /* link management */
+    u32 Address;            /* address for the read/write operation */
+    u32 Request;            /* request flags */
+    u32 TotalLength;        /* total length of entire transfer */
+    u32 CallerFlags;        /* caller specific flags can be stored here */
     HIF_SCATTER_COMP_CB CompletionRoutine;  /* completion routine set by caller */
-    A_STATUS            CompletionStatus;   /* status of completion */
+    int            CompletionStatus;   /* status of completion */
     void                *Context;           /* caller context for this request */
     int                 ValidScatterEntries;  /* number of valid entries set by caller */
     HIF_SCATTER_METHOD  ScatterMethod;        /* scatter method handled by HIF */  
     void                *HIFPrivate[4];     /* HIF private area */
-    A_UINT8             *pScatterBounceBuffer;  /* bounce buffer for upper layers to copy to/from */
-    HIF_SCATTER_ITEM    ScatterList[1];     /* start of scatter list */
-} HIF_SCATTER_REQ;
+    u8 *pScatterBounceBuffer;  /* bounce buffer for upper layers to copy to/from */
+    struct hif_scatter_item    ScatterList[1];     /* start of scatter list */
+};
 
-typedef HIF_SCATTER_REQ * ( *HIF_ALLOCATE_SCATTER_REQUEST)(HIF_DEVICE *device);
-typedef void ( *HIF_FREE_SCATTER_REQUEST)(HIF_DEVICE *device, HIF_SCATTER_REQ *request);
-typedef A_STATUS ( *HIF_READWRITE_SCATTER)(HIF_DEVICE *device, HIF_SCATTER_REQ *request);
+typedef struct hif_scatter_req * ( *HIF_ALLOCATE_SCATTER_REQUEST)(struct hif_device *device);
+typedef void ( *HIF_FREE_SCATTER_REQUEST)(struct hif_device *device, struct hif_scatter_req *request);
+typedef int ( *HIF_READWRITE_SCATTER)(struct hif_device *device, struct hif_scatter_req *request);
 
-typedef struct _HIF_DEVICE_SCATTER_SUPPORT_INFO {
+struct hif_device_scatter_support_info {
         /* information returned from HIF layer */
     HIF_ALLOCATE_SCATTER_REQUEST    pAllocateReqFunc;
     HIF_FREE_SCATTER_REQUEST        pFreeReqFunc;
     HIF_READWRITE_SCATTER           pReadWriteScatterFunc;    
     int                             MaxScatterEntries;
     int                             MaxTransferSizePerScatterReq;
-} HIF_DEVICE_SCATTER_SUPPORT_INFO;
+};
                       
-typedef struct {
+struct hif_device_os_device_info {
     void    *pOSDevice;
-} HIF_DEVICE_OS_DEVICE_INFO;
+};
                       
 #define HIF_MAX_DEVICES                 1
 
 struct htc_callbacks {
     void      *context;     /* context to pass to the dsrhandler
                                note : rwCompletionHandler is provided the context passed to HIFReadWrite  */
-    A_STATUS (* rwCompletionHandler)(void *rwContext, A_STATUS status);
-    A_STATUS (* dsrHandler)(void *context);
+    int (* rwCompletionHandler)(void *rwContext, int status);
+    int (* dsrHandler)(void *context);
 };
 
 typedef struct osdrv_callbacks {
     void      *context;     /* context to pass for all callbacks except deviceRemovedHandler 
                                the deviceRemovedHandler is only called if the device is claimed */
-    A_STATUS (* deviceInsertedHandler)(void *context, void *hif_handle);
-    A_STATUS (* deviceRemovedHandler)(void *claimedContext, void *hif_handle);
-    A_STATUS (* deviceSuspendHandler)(void *context);
-    A_STATUS (* deviceResumeHandler)(void *context);
-    A_STATUS (* deviceWakeupHandler)(void *context);  
-    A_STATUS (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config);  
+    int (* deviceInsertedHandler)(void *context, void *hif_handle);
+    int (* deviceRemovedHandler)(void *claimedContext, void *hif_handle);
+    int (* deviceSuspendHandler)(void *context);
+    int (* deviceResumeHandler)(void *context);
+    int (* deviceWakeupHandler)(void *context);
+    int (* devicePowerChangeHandler)(void *context, HIF_DEVICE_POWER_CHANGE_TYPE config);
 } OSDRV_CALLBACKS;
 
 #define HIF_OTHER_EVENTS     (1 << 0)   /* other interrupts (non-Recv) are pending, host
                                            needs to read the register table to figure out what */
 #define HIF_RECV_MSG_AVAIL   (1 << 1)   /* pending recv packet */
 
-typedef struct _HIF_PENDING_EVENTS_INFO {
-    A_UINT32 Events;
-    A_UINT32 LookAhead;
-    A_UINT32 AvailableRecvBytes;
+struct hif_pending_events_info {
+    u32 Events;
+    u32 LookAhead;
+    u32 AvailableRecvBytes;
 #ifdef THREAD_X
-    A_UINT32 Polling;
-    A_UINT32 INT_CAUSE_REG;
+    u32 Polling;
+    u32 INT_CAUSE_REG;
 #endif
-} HIF_PENDING_EVENTS_INFO;
+};
 
     /* function to get pending events , some HIF modules use special mechanisms
      * to detect packet available and other interrupts */
-typedef A_STATUS ( *HIF_PENDING_EVENTS_FUNC)(HIF_DEVICE              *device,
-                                             HIF_PENDING_EVENTS_INFO *pEvents,
+typedef int ( *HIF_PENDING_EVENTS_FUNC)(struct hif_device              *device,
+                                             struct hif_pending_events_info *pEvents,
                                              void                    *AsyncContext);
 
-#define HIF_MASK_RECV    TRUE
-#define HIF_UNMASK_RECV  FALSE
+#define HIF_MASK_RECV    true
+#define HIF_UNMASK_RECV  false
     /* function to mask recv events */
-typedef A_STATUS ( *HIF_MASK_UNMASK_RECV_EVENT)(HIF_DEVICE  *device,
-                                                A_BOOL      Mask,
+typedef int ( *HIF_MASK_UNMASK_RECV_EVENT)(struct hif_device  *device,
+                                                bool      Mask,
                                                 void        *AsyncContext);
 
 
@@ -372,19 +371,19 @@
  * and to set OS driver callbacks (i.e. insertion/removal) to the HIF layer
  * 
  */
-A_STATUS HIFInit(OSDRV_CALLBACKS *callbacks);
+int HIFInit(OSDRV_CALLBACKS *callbacks);
 
 /* This API claims the HIF device and provides a context for handling removal.
  * The device removal callback is only called when the OSDRV layer claims
  * a device.  The claimed context must be non-NULL */
-void HIFClaimDevice(HIF_DEVICE *device, void *claimedContext);
+void HIFClaimDevice(struct hif_device *device, void *claimedContext);
 /* release the claimed device */
-void HIFReleaseDevice(HIF_DEVICE *device);
+void HIFReleaseDevice(struct hif_device *device);
 
 /* This API allows the HTC layer to attach to the HIF device */
-A_STATUS HIFAttachHTC(HIF_DEVICE *device, HTC_CALLBACKS *callbacks);
+int HIFAttachHTC(struct hif_device *device, HTC_CALLBACKS *callbacks);
 /* This API detaches the HTC layer from the HIF device */
-void     HIFDetachHTC(HIF_DEVICE *device);
+void     HIFDetachHTC(struct hif_device *device);
 
 /*
  * This API is used to provide the read/write interface over the specific bus
@@ -398,19 +397,19 @@
  * length - Amount of data to be transmitted or received.
  * request - Characterizes the attributes of the command.
  */
-A_STATUS
-HIFReadWrite(HIF_DEVICE    *device,
-             A_UINT32       address,
-             A_UCHAR       *buffer,
-             A_UINT32       length,
-             A_UINT32       request,
+int
+HIFReadWrite(struct hif_device    *device,
+             u32 address,
+             u8       *buffer,
+             u32 length,
+             u32 request,
              void          *context);
 
 /*
  * This can be initiated from the unload driver context when the OSDRV layer has no more use for
  * the device.
  */
-void HIFShutDownDevice(HIF_DEVICE *device);
+void HIFShutDownDevice(struct hif_device *device);
 
 /*
  * This should translate to an acknowledgment to the bus driver indicating that
@@ -419,11 +418,11 @@
  * This should prevent the bus driver from raising an interrupt unless the
  * previous one has been serviced and acknowledged using the previous API.
  */
-void HIFAckInterrupt(HIF_DEVICE *device);
+void HIFAckInterrupt(struct hif_device *device);
 
-void HIFMaskInterrupt(HIF_DEVICE *device);
+void HIFMaskInterrupt(struct hif_device *device);
 
-void HIFUnMaskInterrupt(HIF_DEVICE *device);
+void HIFUnMaskInterrupt(struct hif_device *device);
  
 #ifdef THREAD_X
 /*
@@ -441,15 +440,15 @@
 int HIFRWCompleteEventNotify(void);
 #endif
 
-A_STATUS
-HIFConfigureDevice(HIF_DEVICE *device, HIF_DEVICE_CONFIG_OPCODE opcode,
-                   void *config, A_UINT32 configLen);
+int
+HIFConfigureDevice(struct hif_device *device, HIF_DEVICE_CONFIG_OPCODE opcode,
+                   void *config, u32 configLen);
 
 /* 
  * This API wait for the remaining MBOX messages to be drained
  * This should be moved to HTC AR6K layer
  */
-A_STATUS hifWaitForPendingRecv(HIF_DEVICE *device);
+int hifWaitForPendingRecv(struct hif_device *device);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/htc_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/htc_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/htc_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/htc_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -41,31 +41,31 @@
 
 typedef void *HTC_HANDLE;
 
-typedef A_UINT16 HTC_SERVICE_ID;
+typedef u16 HTC_SERVICE_ID;
 
-typedef struct _HTC_INIT_INFO {
+struct htc_init_info {
     void   *pContext;           /* context for target failure notification */
-    void   (*TargetFailure)(void *Instance, A_STATUS Status);
-} HTC_INIT_INFO;
+    void   (*TargetFailure)(void *Instance, int Status);
+};
 
 /* per service connection send completion */
-typedef void   (*HTC_EP_SEND_PKT_COMPLETE)(void *,HTC_PACKET *);
+typedef void   (*HTC_EP_SEND_PKT_COMPLETE)(void *,struct htc_packet *);
 /* per service connection callback when a plurality of packets have been sent
- * The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback)
+ * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback)
  * to hold a list of completed send packets.
  * If the handler cannot fully traverse the packet queue before returning, it should
  * transfer the items of the queue into the caller's private queue using:
  *   HTC_PACKET_ENQUEUE() */
-typedef void   (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,HTC_PACKET_QUEUE *);
+typedef void   (*HTC_EP_SEND_PKT_COMP_MULTIPLE)(void *,struct htc_packet_queue *);
 /* per service connection pkt received */
-typedef void   (*HTC_EP_RECV_PKT)(void *,HTC_PACKET *);
+typedef void   (*HTC_EP_RECV_PKT)(void *,struct htc_packet *);
 /* per service connection callback when a plurality of packets are received
- * The HTC_PACKET_QUEUE is a temporary queue object (e.g. freed on return from the callback)
+ * The struct htc_packet_queue is a temporary queue object (e.g. freed on return from the callback)
  * to hold a list of recv packets.
  * If the handler cannot fully traverse the packet queue before returning, it should
  * transfer the items of the queue into the caller's private queue using:
  *   HTC_PACKET_ENQUEUE() */
-typedef void   (*HTC_EP_RECV_PKT_MULTIPLE)(void *,HTC_PACKET_QUEUE *);
+typedef void   (*HTC_EP_RECV_PKT_MULTIPLE)(void *,struct htc_packet_queue *);
 
 /* Optional per service connection receive buffer re-fill callback,
  * On some OSes (like Linux) packets are allocated from a global pool and indicated up
@@ -94,7 +94,7 @@
  * amount of "committed" memory used to receive packets.
  *  
  * */
-typedef HTC_PACKET *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length);
+typedef struct htc_packet *(*HTC_EP_RECV_ALLOC)(void *, HTC_ENDPOINT_ID Endpoint, int Length);
 
 typedef enum _HTC_SEND_FULL_ACTION {
     HTC_SEND_FULL_KEEP = 0,  /* packet that overflowed should be kept in the queue */
@@ -114,9 +114,9 @@
  * closed loop mechanism will prevent the network stack from overunning the NIC
  * The packet to keep or drop is passed for inspection to the registered handler the handler
  * must ONLY inspect the packet, it may not free or reclaim the packet. */
-typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, HTC_PACKET *pPacket);
+typedef HTC_SEND_FULL_ACTION (*HTC_EP_SEND_QUEUE_FULL)(void *, struct htc_packet *pPacket);
 
-typedef struct _HTC_EP_CALLBACKS {
+struct htc_ep_callbacks {
     void                     *pContext;     /* context for each callback */
     HTC_EP_SEND_PKT_COMPLETE EpTxComplete;  /* tx completion callback for connected endpoint */
     HTC_EP_RECV_PKT          EpRecv;        /* receive callback for connected endpoint */
@@ -136,39 +136,39 @@
                                                        when the recv queue drops below this value 
                                                        if set to 0, the refill is only called when packets 
                                                        are empty */
-} HTC_EP_CALLBACKS;
+};
 
 /* service connection information */
-typedef struct _HTC_SERVICE_CONNECT_REQ {
+struct htc_service_connect_req {
     HTC_SERVICE_ID   ServiceID;                 /* service ID to connect to */
-    A_UINT16         ConnectionFlags;           /* connection flags, see htc protocol definition */
-    A_UINT8         *pMetaData;                 /* ptr to optional service-specific meta-data */
-    A_UINT8          MetaDataLength;            /* optional meta data length */
-    HTC_EP_CALLBACKS EpCallbacks;               /* endpoint callbacks */
+    u16 ConnectionFlags;           /* connection flags, see htc protocol definition */
+    u8 *pMetaData;                 /* ptr to optional service-specific meta-data */
+    u8 MetaDataLength;            /* optional meta data length */
+    struct htc_ep_callbacks EpCallbacks;               /* endpoint callbacks */
     int              MaxSendQueueDepth;         /* maximum depth of any send queue */
-    A_UINT32         LocalConnectionFlags;      /* HTC flags for the host-side (local) connection */
+    u32 LocalConnectionFlags;      /* HTC flags for the host-side (local) connection */
     unsigned int     MaxSendMsgSize;            /* override max message size in send direction */
-} HTC_SERVICE_CONNECT_REQ;
+};
 
 #define HTC_LOCAL_CONN_FLAGS_ENABLE_SEND_BUNDLE_PADDING (1 << 0)  /* enable send bundle padding for this endpoint */
 
 /* service connection response information */
-typedef struct _HTC_SERVICE_CONNECT_RESP {
-    A_UINT8         *pMetaData;         /* caller supplied buffer to optional meta-data */
-    A_UINT8         BufferLength;       /* length of caller supplied buffer */
-    A_UINT8         ActualLength;       /* actual length of meta data */
+struct htc_service_connect_resp {
+    u8 *pMetaData;         /* caller supplied buffer to optional meta-data */
+    u8 BufferLength;       /* length of caller supplied buffer */
+    u8 ActualLength;       /* actual length of meta data */
     HTC_ENDPOINT_ID Endpoint;           /* endpoint to communicate over */
     unsigned int    MaxMsgLength;       /* max length of all messages over this endpoint */
-    A_UINT8         ConnectRespCode;    /* connect response code from target */
-} HTC_SERVICE_CONNECT_RESP;
+    u8 ConnectRespCode;    /* connect response code from target */
+};
 
 /* endpoint distribution structure */
-typedef struct _HTC_ENDPOINT_CREDIT_DIST {
-    struct _HTC_ENDPOINT_CREDIT_DIST *pNext;
-    struct _HTC_ENDPOINT_CREDIT_DIST *pPrev;
+struct htc_endpoint_credit_dist {
+    struct htc_endpoint_credit_dist *pNext;
+    struct htc_endpoint_credit_dist *pPrev;
     HTC_SERVICE_ID      ServiceID;          /* Service ID (set by HTC) */
     HTC_ENDPOINT_ID     Endpoint;           /* endpoint for this distribution struct (set by HTC) */
-    A_UINT32            DistFlags;          /* distribution flags, distribution function can
+    u32 DistFlags;          /* distribution flags, distribution function can
                                                set default activity using SET_EP_ACTIVE() macro */
     int                 TxCreditsNorm;      /* credits for normal operation, anything above this
                                                indicates the endpoint is over-subscribed, this field
@@ -195,9 +195,9 @@
                                                or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
                                                that has non-zero credits to recover
                                               */
-} HTC_ENDPOINT_CREDIT_DIST;
+};
 
-#define HTC_EP_ACTIVE                            ((A_UINT32) (1u << 31))
+#define HTC_EP_ACTIVE                            ((u32) (1u << 31))
 
 /* macro to check if an endpoint has gone active, useful for credit
  * distributions */
@@ -209,18 +209,18 @@
 typedef enum _HTC_CREDIT_DIST_REASON {
     HTC_CREDIT_DIST_SEND_COMPLETE = 0,     /* credits available as a result of completed
                                               send operations (MANDATORY) resulting in credit reports */
-    HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1,   /* a change in endpoint activity occured (OPTIONAL) */
+    HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1,   /* a change in endpoint activity occurred (OPTIONAL) */
     HTC_CREDIT_DIST_SEEK_CREDITS,          /* an endpoint needs to "seek" credits (OPTIONAL) */
     HTC_DUMP_CREDIT_STATE                  /* for debugging, dump any state information that is kept by
                                               the distribution function */
 } HTC_CREDIT_DIST_REASON;
 
 typedef void (*HTC_CREDIT_DIST_CALLBACK)(void                     *Context,
-                                         HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                                         struct htc_endpoint_credit_dist *pEPList,
                                          HTC_CREDIT_DIST_REASON   Reason);
 
 typedef void (*HTC_CREDIT_INIT_CALLBACK)(void *Context,
-                                         HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                                         struct htc_endpoint_credit_dist *pEPList,
                                          int                      TotalCredits);
 
     /* endpoint statistics action */
@@ -231,31 +231,31 @@
 } HTC_ENDPOINT_STAT_ACTION;
 
     /* endpoint statistics */
-typedef struct _HTC_ENDPOINT_STATS {
-    A_UINT32  TxCreditLowIndications;  /* number of times the host set the credit-low flag in a send message on
+struct htc_endpoint_stats {
+    u32 TxCreditLowIndications;  /* number of times the host set the credit-low flag in a send message on
                                         this endpoint */
-    A_UINT32  TxIssued;               /* running count of total TX packets issued */
-    A_UINT32  TxPacketsBundled;       /* running count of TX packets that were issued in bundles */
-    A_UINT32  TxBundles;              /* running count of TX bundles that were issued */
-    A_UINT32  TxDropped;              /* tx packets that were dropped */
-    A_UINT32  TxCreditRpts;           /* running count of total credit reports received for this endpoint */
-    A_UINT32  TxCreditRptsFromRx;     /* credit reports received from this endpoint's RX packets */
-    A_UINT32  TxCreditRptsFromOther;  /* credit reports received from RX packets of other endpoints */
-    A_UINT32  TxCreditRptsFromEp0;    /* credit reports received from endpoint 0 RX packets */
-    A_UINT32  TxCreditsFromRx;        /* count of credits received via Rx packets on this endpoint */
-    A_UINT32  TxCreditsFromOther;     /* count of credits received via another endpoint */
-    A_UINT32  TxCreditsFromEp0;       /* count of credits received via another endpoint */
-    A_UINT32  TxCreditsConsummed;     /* count of consummed credits */
-    A_UINT32  TxCreditsReturned;      /* count of credits returned */
-    A_UINT32  RxReceived;             /* count of RX packets received */
-    A_UINT32  RxLookAheads;           /* count of lookahead records
+    u32 TxIssued;               /* running count of total TX packets issued */
+    u32 TxPacketsBundled;       /* running count of TX packets that were issued in bundles */
+    u32 TxBundles;              /* running count of TX bundles that were issued */
+    u32 TxDropped;              /* tx packets that were dropped */
+    u32 TxCreditRpts;           /* running count of total credit reports received for this endpoint */
+    u32 TxCreditRptsFromRx;     /* credit reports received from this endpoint's RX packets */
+    u32 TxCreditRptsFromOther;  /* credit reports received from RX packets of other endpoints */
+    u32 TxCreditRptsFromEp0;    /* credit reports received from endpoint 0 RX packets */
+    u32 TxCreditsFromRx;        /* count of credits received via Rx packets on this endpoint */
+    u32 TxCreditsFromOther;     /* count of credits received via another endpoint */
+    u32 TxCreditsFromEp0;       /* count of credits received via another endpoint */
+    u32 TxCreditsConsummed;     /* count of consummed credits */
+    u32 TxCreditsReturned;      /* count of credits returned */
+    u32 RxReceived;             /* count of RX packets received */
+    u32 RxLookAheads;           /* count of lookahead records
                                          found in messages received on this endpoint */
-    A_UINT32  RxPacketsBundled;       /* count of recv packets received in a bundle */                                     
-    A_UINT32  RxBundleLookAheads;     /* count of number of bundled lookaheads */
-    A_UINT32  RxBundleIndFromHdr;     /* count of the number of bundle indications from the HTC header */
-    A_UINT32  RxAllocThreshHit;       /* count of the number of times the recv allocation threshhold was hit */
-    A_UINT32  RxAllocThreshBytes;     /* total number of bytes */
-} HTC_ENDPOINT_STATS;
+    u32 RxPacketsBundled;       /* count of recv packets received in a bundle */
+    u32 RxBundleLookAheads;     /* count of number of bundled lookaheads */
+    u32 RxBundleIndFromHdr;     /* count of the number of bundle indications from the HTC header */
+    u32 RxAllocThreshHit;       /* count of the number of times the recv allocation threshold was hit */
+    u32 RxAllocThreshBytes;     /* total number of bytes */
+};
 
 /* ------ Function Prototypes ------ */
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
@@ -269,7 +269,7 @@
   @example:
   @see also: HTCDestroy
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-HTC_HANDLE HTCCreate(void *HifDevice, HTC_INIT_INFO *pInfo);
+HTC_HANDLE HTCCreate(void *HifDevice, struct htc_init_info *pInfo);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Get the underlying HIF device handle
   @function name: HTCGetHifDevice
@@ -319,7 +319,7 @@
   @example:
   @see also: HTCConnectService
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCWaitTarget(HTC_HANDLE HTCHandle);
+int    HTCWaitTarget(HTC_HANDLE HTCHandle);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Start target service communications
   @function name: HTCStart
@@ -334,21 +334,21 @@
   @example:
   @see also: HTCConnectService
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCStart(HTC_HANDLE HTCHandle);
+int    HTCStart(HTC_HANDLE HTCHandle);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Add receive packet to HTC
   @function name: HTCAddReceivePkt
   @input:  HTCHandle - HTC handle
            pPacket - HTC receive packet to add
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes:  user must supply HTC packets for capturing incomming HTC frames.  The caller
            must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
            macro.
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCAddReceivePkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
+int    HTCAddReceivePkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Connect to an HTC service
   @function name: HTCConnectService
@@ -361,23 +361,23 @@
   @example:
   @see also: HTCStart
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCConnectService(HTC_HANDLE HTCHandle,
-                              HTC_SERVICE_CONNECT_REQ  *pReq,
-                              HTC_SERVICE_CONNECT_RESP *pResp);
+int    HTCConnectService(HTC_HANDLE HTCHandle,
+                              struct htc_service_connect_req  *pReq,
+                              struct htc_service_connect_resp *pResp);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Send an HTC packet
   @function name: HTCSendPkt
   @input:  HTCHandle - HTC handle
            pPacket - packet to send
   @output:
-  @return: A_OK
+  @return: 0
   @notes:  Caller must initialize packet using SET_HTC_PACKET_INFO_TX() macro.
            This interface is fully asynchronous.  On error, HTC SendPkt will
            call the registered Endpoint callback to cleanup the packet.
   @example:
   @see also: HTCFlushEndpoint
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCSendPkt(HTC_HANDLE HTCHandle, HTC_PACKET *pPacket);
+int    HTCSendPkt(HTC_HANDLE HTCHandle, struct htc_packet *pPacket);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Stop HTC service communications
   @function name: HTCStop
@@ -391,7 +391,7 @@
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 void        HTCStop(HTC_HANDLE HTCHandle);
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-  @desc: Destory HTC service
+  @desc: Destroy HTC service
   @function name: HTCDestroy
   @input: HTCHandle 
   @output:
@@ -431,7 +431,7 @@
   @function name: HTCIndicateActivityChange
   @input:  HTCHandle - HTC handle
            Endpoint - endpoint in which activity has changed
-           Active - TRUE if active, FALSE if it has become inactive
+           Active - true if active, false if it has become inactive
   @output:
   @return:
   @notes:  This triggers the registered credit distribution function to
@@ -441,7 +441,7 @@
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 void        HTCIndicateActivityChange(HTC_HANDLE      HTCHandle,
                                       HTC_ENDPOINT_ID Endpoint,
-                                      A_BOOL          Active);
+                                      bool          Active);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Get endpoint statistics
@@ -452,9 +452,9 @@
   @output:
            pStats - statistics that were sampled (can be NULL if Action is HTC_EP_STAT_CLEAR)
 
-  @return: TRUE if statistics profiling is enabled, otherwise FALSE.
+  @return: true if statistics profiling is enabled, otherwise false.
 
-  @notes:  Statistics is a compile-time option and this function may return FALSE
+  @notes:  Statistics is a compile-time option and this function may return false
            if HTC is not compiled with profiling.
 
            The caller can specify the statistic "action" to take when sampling
@@ -469,10 +469,10 @@
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_BOOL       HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
+bool       HTCGetEndpointStatistics(HTC_HANDLE               HTCHandle,
                                       HTC_ENDPOINT_ID          Endpoint,
                                       HTC_ENDPOINT_STAT_ACTION Action,
-                                      HTC_ENDPOINT_STATS       *pStats);
+                                      struct htc_endpoint_stats       *pStats);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Unblock HTC message reception
@@ -499,10 +499,10 @@
   @input:  HTCHandle - HTC handle
            pPktQueue - local queue holding packets to send
   @output:
-  @return: A_OK
+  @return: 0
   @notes:  Caller must initialize each packet using SET_HTC_PACKET_INFO_TX() macro.
            The queue must only contain packets directed at the same endpoint.
-           Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the TX packets in FIFO order.
+           Caller supplies a pointer to an struct htc_packet_queue structure holding the TX packets in FIFO order.
            This API will remove the packets from the pkt queue and place them into the HTC Tx Queue
            and bundle messages where possible.
            The caller may allocate the pkt queue on the stack to hold the packets.           
@@ -511,7 +511,7 @@
   @example:
   @see also: HTCFlushEndpoint
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCSendPktsMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue);
+int    HTCSendPktsMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Add multiple receive packets to HTC
@@ -519,18 +519,18 @@
   @input:  HTCHandle - HTC handle
            pPktQueue - HTC receive packet queue holding packets to add
   @output:
-  @return: A_OK on success
+  @return: 0 on success
   @notes:  user must supply HTC packets for capturing incomming HTC frames.  The caller
            must initialize each HTC packet using the SET_HTC_PACKET_INFO_RX_REFILL()
            macro. The queue must only contain recv packets for the same endpoint.
-           Caller supplies a pointer to an HTC_PACKET_QUEUE structure holding the recv packet.
+           Caller supplies a pointer to an struct htc_packet_queue structure holding the recv packet.
            This API will remove the packets from the pkt queue and place them into internal
            recv packet list.
            The caller may allocate the pkt queue on the stack to hold the packets.           
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_STATUS    HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, HTC_PACKET_QUEUE *pPktQueue);
+int    HTCAddReceivePktMultiple(HTC_HANDLE HTCHandle, struct htc_packet_queue *pPktQueue);
 
 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
   @desc: Check if an endpoint is marked active
@@ -538,12 +538,12 @@
   @input:  HTCHandle - HTC handle
            Endpoint - endpoint to check for active state
   @output:
-  @return: returns TRUE if Endpoint is Active
+  @return: returns true if Endpoint is Active
   @notes:  
   @example:
   @see also:
 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
-A_BOOL      HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
+bool      HTCIsEndpointActive(HTC_HANDLE      HTCHandle,
                                 HTC_ENDPOINT_ID Endpoint);
 
 
@@ -564,9 +564,9 @@
 /* internally used functions for testing... */
 void HTCEnableRecv(HTC_HANDLE HTCHandle);
 void HTCDisableRecv(HTC_HANDLE HTCHandle);
-A_STATUS HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
-                               A_UINT32     TimeoutInMs,
-                               A_BOOL      *pbIsRecvPending);
+int HTCWaitForPendingRecv(HTC_HANDLE   HTCHandle,
+                               u32 TimeoutInMs,
+                               bool      *pbIsRecvPending);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/htc_packet.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/htc_packet.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/htc_packet.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/htc_packet.h	2011-05-19 00:06:34.000000000 -0400
@@ -42,37 +42,37 @@
     ENDPOINT_MAX,
 } HTC_ENDPOINT_ID;
 
-struct _HTC_PACKET;
+struct htc_packet;
 
-typedef void (* HTC_PACKET_COMPLETION)(void *,struct _HTC_PACKET *);
+typedef void (* HTC_PACKET_COMPLETION)(void *,struct htc_packet *);
 
-typedef A_UINT16 HTC_TX_TAG;
+typedef u16 HTC_TX_TAG;
 
-typedef struct _HTC_TX_PACKET_INFO {
+struct htc_tx_packet_info {
     HTC_TX_TAG    Tag;            /* tag used to selective flush packets */
     int           CreditsUsed;    /* number of credits used for this TX packet (HTC internal) */
-    A_UINT8       SendFlags;      /* send flags (HTC internal) */
+    u8 SendFlags;      /* send flags (HTC internal) */
     int           SeqNo;          /* internal seq no for debugging (HTC internal) */
-} HTC_TX_PACKET_INFO;
+};
 
 #define HTC_TX_PACKET_TAG_ALL          0    /* a tag of zero is reserved and used to flush ALL packets */
 #define HTC_TX_PACKET_TAG_INTERNAL     1                                /* internal tags start here */
 #define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_TX_PACKET_TAG_INTERNAL + 9) /* user-defined tags start here */
 
-typedef struct _HTC_RX_PACKET_INFO {
-    A_UINT32    ExpectedHdr;        /* HTC internal use */
-    A_UINT32    HTCRxFlags;         /* HTC internal use */
-    A_UINT32    IndicationFlags;    /* indication flags set on each RX packet indication */
-} HTC_RX_PACKET_INFO;
+struct htc_rx_packet_info {
+    u32 ExpectedHdr;        /* HTC internal use */
+    u32 HTCRxFlags;         /* HTC internal use */
+    u32 IndicationFlags;    /* indication flags set on each RX packet indication */
+};
 
 #define HTC_RX_FLAGS_INDICATE_MORE_PKTS  (1 << 0)   /* more packets on this endpoint are being fetched */
 
 /* wrapper around endpoint-specific packets */
-typedef struct _HTC_PACKET {
-    DL_LIST         ListLink;       /* double link */
+struct htc_packet {
+    struct dl_list         ListLink;       /* double link */
     void            *pPktContext;   /* caller's per packet specific context */
 
-    A_UINT8         *pBufferStart;  /* the true buffer start , the caller can
+    u8 *pBufferStart;  /* the true buffer start , the caller can
                                        store the real buffer start here.  In
                                        receive callbacks, the HTC layer sets pBuffer
                                        to the start of the payload past the header. This
@@ -85,20 +85,20 @@
      * points to the start of the HTC header but when returned
      * to the caller points to the start of the payload
      */
-    A_UINT8         *pBuffer;       /* payload start (RX/TX) */
-    A_UINT32        BufferLength;   /* length of buffer */
-    A_UINT32        ActualLength;   /* actual length of payload */
+    u8 *pBuffer;       /* payload start (RX/TX) */
+    u32 BufferLength;   /* length of buffer */
+    u32 ActualLength;   /* actual length of payload */
     HTC_ENDPOINT_ID Endpoint;       /* endpoint that this packet was sent/recv'd from */
-    A_STATUS        Status;         /* completion status */
+    int        Status;         /* completion status */
     union {
-        HTC_TX_PACKET_INFO  AsTx;   /* Tx Packet specific info */
-        HTC_RX_PACKET_INFO  AsRx;   /* Rx Packet specific info */
+        struct htc_tx_packet_info  AsTx;   /* Tx Packet specific info */
+        struct htc_rx_packet_info  AsRx;   /* Rx Packet specific info */
     } PktInfo;
 
     /* the following fields are for internal HTC use */
     HTC_PACKET_COMPLETION Completion;   /* completion */
     void                  *pContext;    /* HTC private completion context */
-} HTC_PACKET;
+};
 
 
 
@@ -139,10 +139,10 @@
 }
 
 /* HTC Packet Queueing Macros */
-typedef struct _HTC_PACKET_QUEUE {
-    DL_LIST     QueueHead;
+struct htc_packet_queue {
+    struct dl_list     QueueHead;
     int         Depth;    
-} HTC_PACKET_QUEUE;
+};
  
 /* initialize queue */
 #define INIT_HTC_PACKET_QUEUE(pQ)   \
@@ -165,11 +165,11 @@
 /* test if a queue is empty */
 #define HTC_QUEUE_EMPTY(pQ)       ((pQ)->Depth == 0)
 /* get packet at head without removing it */
-static INLINE HTC_PACKET *HTC_GET_PKT_AT_HEAD(HTC_PACKET_QUEUE *queue)   {
+static INLINE struct htc_packet *HTC_GET_PKT_AT_HEAD(struct htc_packet_queue *queue)   {
     if (queue->Depth == 0) {
         return NULL; 
     }  
-    return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),HTC_PACKET,ListLink);
+    return A_CONTAINING_STRUCT((DL_LIST_GET_ITEM_AT_HEAD(&queue->QueueHead)),struct htc_packet,ListLink);
 }
 /* remove a packet from a queue, where-ever it is in the queue */
 #define HTC_PACKET_REMOVE(pQ,p)     \
@@ -179,21 +179,21 @@
 }
 
 /* dequeue an HTC packet from the head of the queue */
-static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE(HTC_PACKET_QUEUE *queue) {
-    DL_LIST    *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead);
+static INLINE struct htc_packet *HTC_PACKET_DEQUEUE(struct htc_packet_queue *queue) {
+    struct dl_list    *pItem = DL_ListRemoveItemFromHead(&queue->QueueHead);
     if (pItem != NULL) {
         queue->Depth--;
-        return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink);
     }
     return NULL;
 }
 
 /* dequeue an HTC packet from the tail of the queue */
-static INLINE HTC_PACKET *HTC_PACKET_DEQUEUE_TAIL(HTC_PACKET_QUEUE *queue) {
-    DL_LIST    *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead);
+static INLINE struct htc_packet *HTC_PACKET_DEQUEUE_TAIL(struct htc_packet_queue *queue) {
+    struct dl_list    *pItem = DL_ListRemoveItemFromTail(&queue->QueueHead);
     if (pItem != NULL) {
         queue->Depth--;
-        return A_CONTAINING_STRUCT(pItem, HTC_PACKET, ListLink);
+        return A_CONTAINING_STRUCT(pItem, struct htc_packet, ListLink);
     }
     return NULL;
 }
@@ -220,7 +220,7 @@
 }
     
 #define HTC_PACKET_QUEUE_ITERATE_ALLOW_REMOVE(pQ, pPTemp) \
-    ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), HTC_PACKET, ListLink) 
+    ITERATE_OVER_LIST_ALLOW_REMOVE(&(pQ)->QueueHead,(pPTemp), struct htc_packet, ListLink) 
 
 #define HTC_PACKET_QUEUE_ITERATE_END ITERATE_END
         
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/target_reg_table.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/target_reg_table.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/target_reg_table.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/target_reg_table.h	2011-05-19 00:06:34.000000000 -0400
@@ -30,48 +30,48 @@
 
 /*** WARNING : Add to the end of the TABLE! do not change the order ****/
 typedef struct targetdef_s {
-    A_UINT32 d_RTC_BASE_ADDRESS;
-    A_UINT32 d_SYSTEM_SLEEP_OFFSET;
-    A_UINT32 d_SYSTEM_SLEEP_DISABLE_LSB;
-    A_UINT32 d_SYSTEM_SLEEP_DISABLE_MASK;
-    A_UINT32 d_CLOCK_CONTROL_OFFSET;
-    A_UINT32 d_CLOCK_CONTROL_SI0_CLK_MASK;
-    A_UINT32 d_RESET_CONTROL_OFFSET;
-    A_UINT32 d_RESET_CONTROL_SI0_RST_MASK;
-    A_UINT32 d_GPIO_BASE_ADDRESS;
-    A_UINT32 d_GPIO_PIN0_OFFSET;
-    A_UINT32 d_GPIO_PIN1_OFFSET;
-    A_UINT32 d_GPIO_PIN0_CONFIG_MASK;
-    A_UINT32 d_GPIO_PIN1_CONFIG_MASK;
-    A_UINT32 d_SI_CONFIG_BIDIR_OD_DATA_LSB;
-    A_UINT32 d_SI_CONFIG_BIDIR_OD_DATA_MASK;
-    A_UINT32 d_SI_CONFIG_I2C_LSB;
-    A_UINT32 d_SI_CONFIG_I2C_MASK;
-    A_UINT32 d_SI_CONFIG_POS_SAMPLE_LSB;
-    A_UINT32 d_SI_CONFIG_POS_SAMPLE_MASK;
-    A_UINT32 d_SI_CONFIG_INACTIVE_CLK_LSB;
-    A_UINT32 d_SI_CONFIG_INACTIVE_CLK_MASK;
-    A_UINT32 d_SI_CONFIG_INACTIVE_DATA_LSB;
-    A_UINT32 d_SI_CONFIG_INACTIVE_DATA_MASK;
-    A_UINT32 d_SI_CONFIG_DIVIDER_LSB;
-    A_UINT32 d_SI_CONFIG_DIVIDER_MASK;
-    A_UINT32 d_SI_BASE_ADDRESS;
-    A_UINT32 d_SI_CONFIG_OFFSET;
-    A_UINT32 d_SI_TX_DATA0_OFFSET;
-    A_UINT32 d_SI_TX_DATA1_OFFSET;
-    A_UINT32 d_SI_RX_DATA0_OFFSET;
-    A_UINT32 d_SI_RX_DATA1_OFFSET;
-    A_UINT32 d_SI_CS_OFFSET;
-    A_UINT32 d_SI_CS_DONE_ERR_MASK;
-    A_UINT32 d_SI_CS_DONE_INT_MASK;
-    A_UINT32 d_SI_CS_START_LSB;
-    A_UINT32 d_SI_CS_START_MASK;
-    A_UINT32 d_SI_CS_RX_CNT_LSB;
-    A_UINT32 d_SI_CS_RX_CNT_MASK;
-    A_UINT32 d_SI_CS_TX_CNT_LSB;
-    A_UINT32 d_SI_CS_TX_CNT_MASK;
-    A_UINT32 d_BOARD_DATA_SZ;
-    A_UINT32 d_BOARD_EXT_DATA_SZ;
+    u32 d_RTC_BASE_ADDRESS;
+    u32 d_SYSTEM_SLEEP_OFFSET;
+    u32 d_SYSTEM_SLEEP_DISABLE_LSB;
+    u32 d_SYSTEM_SLEEP_DISABLE_MASK;
+    u32 d_CLOCK_CONTROL_OFFSET;
+    u32 d_CLOCK_CONTROL_SI0_CLK_MASK;
+    u32 d_RESET_CONTROL_OFFSET;
+    u32 d_RESET_CONTROL_SI0_RST_MASK;
+    u32 d_GPIO_BASE_ADDRESS;
+    u32 d_GPIO_PIN0_OFFSET;
+    u32 d_GPIO_PIN1_OFFSET;
+    u32 d_GPIO_PIN0_CONFIG_MASK;
+    u32 d_GPIO_PIN1_CONFIG_MASK;
+    u32 d_SI_CONFIG_BIDIR_OD_DATA_LSB;
+    u32 d_SI_CONFIG_BIDIR_OD_DATA_MASK;
+    u32 d_SI_CONFIG_I2C_LSB;
+    u32 d_SI_CONFIG_I2C_MASK;
+    u32 d_SI_CONFIG_POS_SAMPLE_LSB;
+    u32 d_SI_CONFIG_POS_SAMPLE_MASK;
+    u32 d_SI_CONFIG_INACTIVE_CLK_LSB;
+    u32 d_SI_CONFIG_INACTIVE_CLK_MASK;
+    u32 d_SI_CONFIG_INACTIVE_DATA_LSB;
+    u32 d_SI_CONFIG_INACTIVE_DATA_MASK;
+    u32 d_SI_CONFIG_DIVIDER_LSB;
+    u32 d_SI_CONFIG_DIVIDER_MASK;
+    u32 d_SI_BASE_ADDRESS;
+    u32 d_SI_CONFIG_OFFSET;
+    u32 d_SI_TX_DATA0_OFFSET;
+    u32 d_SI_TX_DATA1_OFFSET;
+    u32 d_SI_RX_DATA0_OFFSET;
+    u32 d_SI_RX_DATA1_OFFSET;
+    u32 d_SI_CS_OFFSET;
+    u32 d_SI_CS_DONE_ERR_MASK;
+    u32 d_SI_CS_DONE_INT_MASK;
+    u32 d_SI_CS_START_LSB;
+    u32 d_SI_CS_START_MASK;
+    u32 d_SI_CS_RX_CNT_LSB;
+    u32 d_SI_CS_RX_CNT_MASK;
+    u32 d_SI_CS_TX_CNT_LSB;
+    u32 d_SI_CS_TX_CNT_MASK;
+    u32 d_BOARD_DATA_SZ;
+    u32 d_BOARD_EXT_DATA_SZ;
 } TARGET_REGISTER_TABLE;
 
 #define BOARD_DATA_SZ_MAX 2048
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/wlan_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/wlan_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/wlan_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/wlan_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -35,48 +35,48 @@
 struct ieee80211_frame;
 
 struct ieee80211_common_ie {
-    A_UINT16    ie_chan;
-    A_UINT8     *ie_tstamp;
-    A_UINT8     *ie_ssid;
-    A_UINT8     *ie_rates;
-    A_UINT8     *ie_xrates;
-    A_UINT8     *ie_country;
-    A_UINT8     *ie_wpa;
-    A_UINT8     *ie_rsn;
-    A_UINT8     *ie_wmm;
-    A_UINT8     *ie_ath;
-    A_UINT16    ie_capInfo;
-    A_UINT16    ie_beaconInt;
-    A_UINT8     *ie_tim;
-    A_UINT8     *ie_chswitch;
-    A_UINT8     ie_erp;
-    A_UINT8     *ie_wsc;
-    A_UINT8     *ie_htcap;
-    A_UINT8     *ie_htop;
+    u16 ie_chan;
+    u8 *ie_tstamp;
+    u8 *ie_ssid;
+    u8 *ie_rates;
+    u8 *ie_xrates;
+    u8 *ie_country;
+    u8 *ie_wpa;
+    u8 *ie_rsn;
+    u8 *ie_wmm;
+    u8 *ie_ath;
+    u16 ie_capInfo;
+    u16 ie_beaconInt;
+    u8 *ie_tim;
+    u8 *ie_chswitch;
+    u8 ie_erp;
+    u8 *ie_wsc;
+    u8 *ie_htcap;
+    u8 *ie_htop;
 #ifdef WAPI_ENABLE
-    A_UINT8     *ie_wapi;
+    u8 *ie_wapi;
 #endif
 };
 
 typedef struct bss {
-    A_UINT8                      ni_macaddr[6];
-    A_UINT8                      ni_snr;
-    A_INT16                      ni_rssi;
+    u8 ni_macaddr[6];
+    u8 ni_snr;
+    s16 ni_rssi;
     struct bss                   *ni_list_next;
     struct bss                   *ni_list_prev;
     struct bss                   *ni_hash_next;
     struct bss                   *ni_hash_prev;
     struct ieee80211_common_ie   ni_cie;
-    A_UINT8                     *ni_buf;
-    A_UINT16                     ni_framelen;
+    u8 *ni_buf;
+    u16 ni_framelen;
     struct ieee80211_node_table *ni_table;
-    A_UINT32                     ni_refcnt;
+    u32 ni_refcnt;
     int                          ni_scangen;
 
-    A_UINT32                     ni_tstamp;
-    A_UINT32                     ni_actcnt;
+    u32 ni_tstamp;
+    u32 ni_actcnt;
 #ifdef OS_ROAM_MANAGEMENT
-    A_UINT32                     ni_si_gen;
+    u32 ni_si_gen;
 #endif
 } bss_t;
 
@@ -85,8 +85,8 @@
 bss_t *wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size);
 void wlan_node_free(bss_t *ni);
 void wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
-                const A_UINT8 *macaddr);
-bss_t *wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr);
+                const u8 *macaddr);
+bss_t *wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr);
 void wlan_node_reclaim(struct ieee80211_node_table *nt, bss_t *ni);
 void wlan_free_allnodes(struct ieee80211_node_table *nt);
 void wlan_iterate_nodes(struct ieee80211_node_table *nt, wlan_node_iter_func *f,
@@ -96,30 +96,30 @@
 void wlan_node_table_reset(struct ieee80211_node_table *nt);
 void wlan_node_table_cleanup(struct ieee80211_node_table *nt);
 
-A_STATUS wlan_parse_beacon(A_UINT8 *buf, int framelen,
+int wlan_parse_beacon(u8 *buf, int framelen,
                            struct ieee80211_common_ie *cie);
 
-A_UINT16 wlan_ieee2freq(int chan);
-A_UINT32 wlan_freq2ieee(A_UINT16 freq);
+u16 wlan_ieee2freq(int chan);
+u32 wlan_freq2ieee(u16 freq);
 
-void wlan_set_nodeage(struct ieee80211_node_table *nt, A_UINT32 nodeAge);
+void wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge);
 
 void
 wlan_refresh_inactive_nodes (struct ieee80211_node_table *nt);
 
 bss_t *
-wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID);
+wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, bool bIsWPA2, bool bMatchSSID);
 
 void
 wlan_node_return (struct ieee80211_node_table *nt, bss_t *ni);
 
-bss_t *wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid);
+bss_t *wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid);
 
 bss_t *
-wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp);
+wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/wmi_api.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/wmi_api.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/include/wmi_api.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/include/wmi_api.h	2011-05-19 00:06:34.000000000 -0400
@@ -69,26 +69,26 @@
 void wmi_shutdown(struct wmi_t *wmip);
 HTC_ENDPOINT_ID wmi_get_control_ep(struct wmi_t * wmip);
 void wmi_set_control_ep(struct wmi_t * wmip, HTC_ENDPOINT_ID eid);
-A_UINT16  wmi_get_mapped_qos_queue(struct wmi_t *, A_UINT8);
-A_STATUS wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
-A_STATUS wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_BOOL bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,A_UINT8 metaVersion, void *pTxMetaS);
-A_STATUS wmi_dot3_2_dix(void *osbuf);
+u16 wmi_get_mapped_qos_queue(struct wmi_t *, u8 );
+int wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf);
+int wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData, WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS);
+int wmi_dot3_2_dix(void *osbuf);
 
-A_STATUS wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf);
-A_STATUS wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode);
+int wmi_dot11_hdr_remove (struct wmi_t *wmip, void *osbuf);
+int wmi_dot11_hdr_add(struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode);
 
-A_STATUS wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
-A_STATUS wmi_syncpoint(struct wmi_t *wmip);
-A_STATUS wmi_syncpoint_reset(struct wmi_t *wmip);
-A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 layer2Priority, A_BOOL wmmEnabled);
+int wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf);
+int wmi_syncpoint(struct wmi_t *wmip);
+int wmi_syncpoint_reset(struct wmi_t *wmip);
+u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled);
 
-A_UINT8 wmi_determine_userPriority (A_UINT8 *pkt, A_UINT32 layer2Pri);
+u8 wmi_determine_userPriority (u8 *pkt, u32 layer2Pri);
 
-A_STATUS wmi_control_rx(struct wmi_t *wmip, void *osbuf);
+int wmi_control_rx(struct wmi_t *wmip, void *osbuf);
 void wmi_iterate_nodes(struct wmi_t *wmip, wlan_node_iter_func *f, void *arg);
 void wmi_free_allnodes(struct wmi_t *wmip);
-bss_t *wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
-void wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr);
+bss_t *wmi_find_node(struct wmi_t *wmip, const u8 *macaddr);
+void wmi_free_node(struct wmi_t *wmip, const u8 *macaddr);
 
 
 typedef enum {
@@ -99,340 +99,340 @@
     END_WMIFLAG                     /* end marker */
 } WMI_SYNC_FLAG;
 
-A_STATUS wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
+int wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
                       WMI_SYNC_FLAG flag);
 
-A_STATUS wmi_connect_cmd(struct wmi_t *wmip,
+int wmi_connect_cmd(struct wmi_t *wmip,
                          NETWORK_TYPE netType,
                          DOT11_AUTH_MODE dot11AuthMode,
                          AUTH_MODE authMode,
                          CRYPTO_TYPE pairwiseCrypto,
-                         A_UINT8 pairwiseCryptoLen,
+                         u8 pairwiseCryptoLen,
                          CRYPTO_TYPE groupCrypto,
-                         A_UINT8 groupCryptoLen,
+                         u8 groupCryptoLen,
                          int ssidLength,
-                         A_UCHAR *ssid,
-                         A_UINT8 *bssid,
-                         A_UINT16 channel,
-                         A_UINT32 ctrl_flags);
+                         u8 *ssid,
+                         u8 *bssid,
+                         u16 channel,
+                         u32 ctrl_flags);
 
-A_STATUS wmi_reconnect_cmd(struct wmi_t *wmip,
-                           A_UINT8 *bssid,
-                           A_UINT16 channel);
-A_STATUS wmi_disconnect_cmd(struct wmi_t *wmip);
-A_STATUS wmi_getrev_cmd(struct wmi_t *wmip);
-A_STATUS wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
-                           A_BOOL forceFgScan, A_BOOL isLegacy,
-                           A_UINT32 homeDwellTime, A_UINT32 forceScanInterval,
-                           A_INT8 numChan, A_UINT16 *channelList);
-A_STATUS wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
-                            A_UINT16 fg_end_sec, A_UINT16 bg_sec,
-                            A_UINT16 minact_chdw_msec,
-                            A_UINT16 maxact_chdw_msec, A_UINT16 pas_chdw_msec,
-                            A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
-                            A_UINT32 max_dfsch_act_time,
-                            A_UINT16 maxact_scan_per_ssid);
-A_STATUS wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask);
-A_STATUS wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
-                            A_UINT8 ssidLength, A_UCHAR *ssid);
-A_STATUS wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons);
-A_STATUS wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmisstime, A_UINT16 bmissbeacons);
-A_STATUS wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
-                           A_UINT8 ieLen, A_UINT8 *ieInfo);
-A_STATUS wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode);
-A_STATUS wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
-                            A_UINT16 atim_windows, A_UINT16 timeout_value);
-A_STATUS wmi_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time,
-                   A_UINT32 ps_period, A_UINT8 sleep_period);
-A_STATUS wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
-                           A_UINT16 psPollNum, A_UINT16 dtimPolicy,
-                           A_UINT16 wakup_tx_policy, A_UINT16 num_tx_to_wakeup,
-                           A_UINT16 ps_fail_event_policy);
-A_STATUS wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout);
-A_STATUS wmi_sync_cmd(struct wmi_t *wmip, A_UINT8 syncNumber);
-A_STATUS wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
-A_STATUS wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 streamID);
-A_STATUS wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8 subType, A_UINT16 rateMask);
-A_STATUS wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_INT32 ctlRate);
-A_STATUS wmi_get_bitrate_cmd(struct wmi_t *wmip);
-A_INT8   wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate, A_INT8 *rate_idx);
-A_STATUS wmi_get_regDomain_cmd(struct wmi_t *wmip);
-A_STATUS wmi_get_channelList_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
-                                   WMI_PHY_MODE mode, A_INT8 numChan,
-                                   A_UINT16 *channelList);
+int wmi_reconnect_cmd(struct wmi_t *wmip,
+                           u8 *bssid,
+                           u16 channel);
+int wmi_disconnect_cmd(struct wmi_t *wmip);
+int wmi_getrev_cmd(struct wmi_t *wmip);
+int wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
+                           u32 forceFgScan, u32 isLegacy,
+                           u32 homeDwellTime, u32 forceScanInterval,
+                           s8 numChan, u16 *channelList);
+int wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
+                            u16 fg_end_sec, u16 bg_sec,
+                            u16 minact_chdw_msec,
+                            u16 maxact_chdw_msec, u16 pas_chdw_msec,
+                            u8 shScanRatio, u8 scanCtrlFlags,
+                            u32 max_dfsch_act_time,
+                            u16 maxact_scan_per_ssid);
+int wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask);
+int wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
+                            u8 ssidLength, u8 *ssid);
+int wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons);
+int wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmisstime, u16 bmissbeacons);
+int wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
+                           u8 ieLen, u8 *ieInfo);
+int wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode);
+int wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
+                            u16 atim_windows, u16 timeout_value);
+int wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
+                   u32 ps_period, u8 sleep_period);
+int wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
+                           u16 psPollNum, u16 dtimPolicy,
+                           u16 wakup_tx_policy, u16 num_tx_to_wakeup,
+                           u16 ps_fail_event_policy);
+int wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout);
+int wmi_sync_cmd(struct wmi_t *wmip, u8 syncNumber);
+int wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *pstream);
+int wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 streamID);
+int wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask);
+int wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate);
+int wmi_get_bitrate_cmd(struct wmi_t *wmip);
+s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx);
+int wmi_get_regDomain_cmd(struct wmi_t *wmip);
+int wmi_get_channelList_cmd(struct wmi_t *wmip);
+int wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
+                                   WMI_PHY_MODE mode, s8 numChan,
+                                   u16 *channelList);
 
-A_STATUS wmi_set_snr_threshold_params(struct wmi_t *wmip,
+int wmi_set_snr_threshold_params(struct wmi_t *wmip,
                                        WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-A_STATUS wmi_set_rssi_threshold_params(struct wmi_t *wmip,
+int wmi_set_rssi_threshold_params(struct wmi_t *wmip,
                                         WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-A_STATUS wmi_clr_rssi_snr(struct wmi_t *wmip);
-A_STATUS wmi_set_lq_threshold_params(struct wmi_t *wmip,
+int wmi_clr_rssi_snr(struct wmi_t *wmip);
+int wmi_set_lq_threshold_params(struct wmi_t *wmip,
                                       WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd);
-A_STATUS wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold);
-A_STATUS wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status, A_UINT8 preamblePolicy);
+int wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold);
+int wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy);
 
-A_STATUS wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 bitmask);
+int wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 bitmask);
 
-A_STATUS wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie,
-                                    A_UINT32 source);
+int wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie,
+                                    u32 source);
 
-A_STATUS wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
-                                     A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
-                                     A_UINT32 valid);
+int wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
+                                     u16 tsr, bool rep, u16 size,
+                                     u32 valid);
 
-A_STATUS wmi_get_stats_cmd(struct wmi_t *wmip);
+int wmi_get_stats_cmd(struct wmi_t *wmip);
 
-A_STATUS wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex,
-                        CRYPTO_TYPE keyType, A_UINT8 keyUsage,
-                        A_UINT8 keyLength,A_UINT8 *keyRSC,
-                        A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, A_UINT8 *mac,
+int wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex,
+                        CRYPTO_TYPE keyType, u8 keyUsage,
+                        u8 keyLength,u8 *keyRSC,
+                        u8 *keyMaterial, u8 key_op_ctrl, u8 *mac,
                         WMI_SYNC_FLAG sync_flag);
-A_STATUS wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk);
-A_STATUS wmi_delete_krk_cmd(struct wmi_t *wmip);
-A_STATUS wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex);
-A_STATUS wmi_set_akmp_params_cmd(struct wmi_t *wmip,
+int wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk);
+int wmi_delete_krk_cmd(struct wmi_t *wmip);
+int wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex);
+int wmi_set_akmp_params_cmd(struct wmi_t *wmip,
                                  WMI_SET_AKMP_PARAMS_CMD *akmpParams);
-A_STATUS wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
+int wmi_get_pmkid_list_cmd(struct wmi_t *wmip);
+int wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
                                 WMI_SET_PMKID_LIST_CMD *pmkInfo);
-A_STATUS wmi_abort_scan_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM);
-A_STATUS wmi_get_txPwr_cmd(struct wmi_t *wmip);
-A_STATUS wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid);
-A_STATUS wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex);
-A_STATUS wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en);
-A_STATUS wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
-                          A_BOOL set);
-A_STATUS wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT8 ac, A_UINT16 txop,
-                                   A_UINT8 eCWmin, A_UINT8 eCWmax,
-                                   A_UINT8 aifsn);
-A_STATUS wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
-                                  A_UINT8 trafficClass, A_UINT8 maxRetries,
-                                  A_UINT8 enableNotify);
+int wmi_abort_scan_cmd(struct wmi_t *wmip);
+int wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM);
+int wmi_get_txPwr_cmd(struct wmi_t *wmip);
+int wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid);
+int wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex);
+int wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en);
+int wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
+                          bool set);
+int wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac, u16 txop,
+                                   u8 eCWmin, u8 eCWmax,
+                                   u8 aifsn);
+int wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
+                                  u8 trafficClass, u8 maxRetries,
+                                  u8 enableNotify);
 
-void wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid);
+void wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid);
 
-A_STATUS wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
-A_STATUS wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType);
-A_STATUS wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
-                               A_UINT8 size);
-A_STATUS wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
+int wmi_get_roam_tbl_cmd(struct wmi_t *wmip);
+int wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType);
+int wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
+                               u8 size);
+int wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
                             WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
-                            A_UINT8 size);
+                            u8 size);
 
-A_STATUS wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode);
-A_STATUS wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
-                              A_UINT8 frmType,
-                              A_UINT8 *dstMacAddr,
-                              A_UINT8 *bssid,
-                              A_UINT16 optIEDataLen,
-                              A_UINT8 *optIEData);
+int wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode);
+int wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
+                              u8 frmType,
+                              u8 *dstMacAddr,
+                              u8 *bssid,
+                              u16 optIEDataLen,
+                              u8 *optIEData);
 
-A_STATUS wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl);
-A_STATUS wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize);
-A_STATUS wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSpLen);
-A_UINT8  convert_userPriority_to_trafficClass(A_UINT8 userPriority);
-A_UINT8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
-A_STATUS wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance);
+int wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl);
+int wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize);
+int wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSpLen);
+u8 convert_userPriority_to_trafficClass(u8 userPriority);
+u8 wmi_get_power_mode_cmd(struct wmi_t *wmip);
+int wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance);
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-A_STATUS wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32  len);
+int wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len);
 #endif
 
-A_STATUS wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status);
-A_STATUS wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
+int wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status);
+int wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd);
 
-A_STATUS wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd);
+int wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
 		                                WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
                                			WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *cmd);
 
-A_STATUS wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
                    		              WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
+int wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
 		                                 WMI_SET_BTCOEX_A2DP_CONFIG_CMD* cmd);
 
 
-A_STATUS wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd);
+int wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD* cmd);
 
-A_STATUS wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd);
+int wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd);
 
-A_STATUS wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
+int wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
 							WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd);
 
-A_STATUS wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd);
+int wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd);
 
-A_STATUS wmi_get_btcoex_stats_cmd(struct wmi_t * wmip);
+int wmi_get_btcoex_stats_cmd(struct wmi_t * wmip);
 
-A_STATUS wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 sgiMask, A_UINT8 sgiPERThreshold);
+int wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold);
 
 /*
  *  This function is used to configure the fix rates mask to the target.
  */
-A_STATUS wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask);
-A_STATUS wmi_get_ratemask_cmd(struct wmi_t *wmip);
+int wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask);
+int wmi_get_ratemask_cmd(struct wmi_t *wmip);
 
-A_STATUS wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
+int wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode);
 
-A_STATUS wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode);
+int wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode);
 
-A_STATUS wmi_set_qos_supp_cmd(struct wmi_t *wmip,A_UINT8 status);
-A_STATUS wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
-A_STATUS wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
-A_STATUS wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode);
+int wmi_set_qos_supp_cmd(struct wmi_t *wmip,u8 status);
+int wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status);
+int wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG txEnable);
+int wmi_set_country(struct wmi_t *wmip, u8 *countryCode);
 
-A_STATUS wmi_get_keepalive_configured(struct wmi_t *wmip);
-A_UINT8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
-A_STATUS wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval);
+int wmi_get_keepalive_configured(struct wmi_t *wmip);
+u8 wmi_get_keepalive_cmd(struct wmi_t *wmip);
+int wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval);
 
-A_STATUS wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType,
-                           A_UINT8 ieLen,A_UINT8 *ieInfo);
+int wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType,
+                           u8 ieLen,u8 *ieInfo);
 
-A_STATUS wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen);
+int wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen);
 
-A_INT32 wmi_get_rate(A_INT8 rateindex);
+s32 wmi_get_rate(s8 rateindex);
 
-A_STATUS wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd);
+int wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *cmd);
 
 /*Wake on Wireless WMI commands*/
-A_STATUS wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
-A_STATUS wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
-A_STATUS wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
-A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
-                                 WMI_ADD_WOW_PATTERN_CMD *cmd, A_UINT8* pattern, A_UINT8* mask, A_UINT8 pattern_size);
-A_STATUS wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
+int wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip, WMI_SET_HOST_SLEEP_MODE_CMD *cmd);
+int wmi_set_wow_mode_cmd(struct wmi_t *wmip, WMI_SET_WOW_MODE_CMD *cmd);
+int wmi_get_wow_list_cmd(struct wmi_t *wmip, WMI_GET_WOW_LIST_CMD *cmd);
+int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
+                                 WMI_ADD_WOW_PATTERN_CMD *cmd, u8 *pattern, u8 *mask, u8 pattern_size);
+int wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
                                  WMI_DEL_WOW_PATTERN_CMD *cmd);
-A_STATUS wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status);
+int wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status);
 
-A_STATUS
-wmi_set_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR* buffer);
+int
+wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer);
 
-A_STATUS
-wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4);
+int
+wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4);
 
-A_STATUS
-wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4);
+int
+wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4);
 
-A_STATUS
-wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable);
+int
+wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable);
 
 bss_t *
-wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID);
+wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength, bool bIsWPA2, bool bMatchSSID);
 
 
 void
 wmi_node_return (struct wmi_t *wmip, bss_t *bss);
 
 void
-wmi_set_nodeage(struct wmi_t *wmip, A_UINT32 nodeAge);
+wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge);
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-A_STATUS wmi_prof_cfg_cmd(struct wmi_t *wmip, A_UINT32 period, A_UINT32 nbins);
-A_STATUS wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr);
-A_STATUS wmi_prof_start_cmd(struct wmi_t *wmip);
-A_STATUS wmi_prof_stop_cmd(struct wmi_t *wmip);
-A_STATUS wmi_prof_count_get_cmd(struct wmi_t *wmip);
+int wmi_prof_cfg_cmd(struct wmi_t *wmip, u32 period, u32 nbins);
+int wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr);
+int wmi_prof_start_cmd(struct wmi_t *wmip);
+int wmi_prof_stop_cmd(struct wmi_t *wmip);
+int wmi_prof_count_get_cmd(struct wmi_t *wmip);
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 #ifdef OS_ROAM_MANAGEMENT
 void wmi_scan_indication (struct wmi_t *wmip);
 #endif
 
-A_STATUS
+int
 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd);
 
-bss_t   *wmi_rm_current_bss (struct wmi_t *wmip, A_UINT8 *id);
-A_STATUS wmi_add_current_bss (struct wmi_t *wmip, A_UINT8 *id, bss_t *bss);
+bss_t   *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id);
+int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss);
 
 
 /*
  * AP mode
  */
-A_STATUS
+int
 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p);
 
-A_STATUS
-wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid);
+int
+wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid);
 
-A_STATUS
-wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta);
+int
+wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta);
 
-A_STATUS
-wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy);
+int
+wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy);
 
-A_STATUS
+int
 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *a);
 
-A_UINT8
-acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl);
+u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl);
 
-A_STATUS
-wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason);
+int
+wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason);
 
-A_STATUS
-wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag);
+int
+wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag);
 
-A_STATUS
-wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period);
+int
+wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period);
 
-A_STATUS
-wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell);
+int
+wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell);
 
-A_STATUS
-wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim);
+int
+wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim);
 
-A_STATUS
-wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset);
+int
+wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset);
 
-A_STATUS
+int
 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd);
 
-A_STATUS
-wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width);
+int
+wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width);
 
-A_STATUS
-wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz);
+int
+wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz);
 
-A_STATUS
-wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray);
+int
+wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray);
 
-A_STATUS
-wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid);
+int
+wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid);
 
-A_STATUS
-wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink);
+int
+wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink);
 
-A_STATUS
-wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask);
+int
+wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask);
 
-A_STATUS 
-wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion, A_BOOL rxDot11Hdr, A_BOOL defragOnHost);
+int
+wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion, bool rxDot11Hdr, bool defragOnHost);
 
-A_STATUS 
-wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode);
+int
+wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode);
 
-A_STATUS
+int
 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence);
 
-A_STATUS
-wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk);
+int
+wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk);
 
-A_UINT16
-wmi_ieee2freq (int chan);
+int
+wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd);
 
-A_UINT32
-wmi_freq2ieee (A_UINT16 freq);
+u16 wmi_ieee2freq (int chan);
+
+u32 wmi_freq2ieee (u16 freq);
 
 bss_t *
-wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength,
-                   A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp);
+wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength,
+                   u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp);
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kconfig.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kconfig.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kconfig.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kconfig.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,24 +47,24 @@
 #define HCI_MAX_EVT_RECV_LENGTH             257
 #define EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET  5
 
-A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
+int AthPSInitialize(struct ar3k_config_info *hdev);
 
-static A_STATUS SendHCICommand(AR3K_CONFIG_INFO *pConfig,
-                               A_UINT8          *pBuffer,
+static int SendHCICommand(struct ar3k_config_info *pConfig,
+                               u8 *pBuffer,
                                int              Length)
 {
-    HTC_PACKET  *pPacket = NULL;
-    A_STATUS    status = A_OK;
+    struct htc_packet  *pPacket = NULL;
+    int    status = 0;
        
     do {   
         
-        pPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));     
+        pPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));     
         if (NULL == pPacket) {
             status = A_NO_MEMORY;
             break;    
         }       
         
-        A_MEMZERO(pPacket,sizeof(HTC_PACKET));      
+        A_MEMZERO(pPacket,sizeof(struct htc_packet));      
         SET_HTC_PACKET_INFO_TX(pPacket,
                                NULL,
                                pBuffer, 
@@ -73,9 +73,9 @@
                                AR6K_CONTROL_PKT_TAG);
         
             /* issue synchronously */                                      
-        status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,TRUE);   
+        status = HCI_TransportSendPkt(pConfig->pHCIDev,pPacket,true);
         
-    } while (FALSE);
+    } while (false);
    
     if (pPacket != NULL) {
         A_FREE(pPacket);
@@ -84,36 +84,36 @@
     return status;
 }
 
-static A_STATUS RecvHCIEvent(AR3K_CONFIG_INFO *pConfig,
-                             A_UINT8          *pBuffer,
+static int RecvHCIEvent(struct ar3k_config_info *pConfig,
+                             u8 *pBuffer,
                              int              *pLength)
 {
-    A_STATUS    status = A_OK; 
-    HTC_PACKET  *pRecvPacket = NULL;
+    int    status = 0;
+    struct htc_packet  *pRecvPacket = NULL;
     
     do {
                  
-        pRecvPacket = (HTC_PACKET *)A_MALLOC(sizeof(HTC_PACKET));
+        pRecvPacket = (struct htc_packet *)A_MALLOC(sizeof(struct htc_packet));
         if (NULL == pRecvPacket) {
             status = A_NO_MEMORY;
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to alloc HTC struct \n"));
             break;    
         }     
         
-        A_MEMZERO(pRecvPacket,sizeof(HTC_PACKET)); 
+        A_MEMZERO(pRecvPacket,sizeof(struct htc_packet)); 
          
         SET_HTC_PACKET_INFO_RX_REFILL(pRecvPacket,NULL,pBuffer,*pLength,HCI_EVENT_TYPE);
         
         status = HCI_TransportRecvHCIEventSync(pConfig->pHCIDev,
                                                pRecvPacket,
                                                HCI_EVENT_RESP_TIMEOUTMS);
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
 
         *pLength = pRecvPacket->ActualLength;
         
-    } while (FALSE);
+    } while (false);
        
     if (pRecvPacket != NULL) {
         A_FREE(pRecvPacket);    
@@ -122,18 +122,18 @@
     return status;
 } 
     
-A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
-                                           A_UINT8          *pHCICommand,
+int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
+                                           u8 *pHCICommand,
                                            int              CmdLength,
-                                           A_UINT8          **ppEventBuffer,
-                                           A_UINT8          **ppBufferToFree)
+                                           u8 **ppEventBuffer,
+                                           u8 **ppBufferToFree)
 {
-    A_STATUS    status = A_OK;   
-    A_UINT8     *pBuffer = NULL;
-    A_UINT8     *pTemp;
+    int    status = 0;
+    u8 *pBuffer = NULL;
+    u8 *pTemp;
     int         length;
-    A_BOOL      commandComplete = FALSE;
-    A_UINT8     opCodeBytes[2];
+    bool      commandComplete = false;
+    u8 opCodeBytes[2];
                                
     do {
         
@@ -141,7 +141,7 @@
         length += pConfig->pHCIProps->HeadRoom + pConfig->pHCIProps->TailRoom;
         length += pConfig->pHCIProps->IOBlockPad;
                                      
-        pBuffer = (A_UINT8 *)A_MALLOC(length);        
+        pBuffer = (u8 *)A_MALLOC(length);
         if (NULL == pBuffer) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to allocate bt buffer \n"));
             status = A_NO_MEMORY;
@@ -153,12 +153,12 @@
         opCodeBytes[1] = pHCICommand[HCI_CMD_OPCODE_BYTE_HI_OFFSET];
         
             /* copy HCI command */
-        A_MEMCPY(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);         
+        memcpy(pBuffer + pConfig->pHCIProps->HeadRoom,pHCICommand,CmdLength);         
             /* send command */
         status = SendHCICommand(pConfig,
                                 pBuffer + pConfig->pHCIProps->HeadRoom,
                                 CmdLength);
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Failed to send HCI Command (%d) \n", status));
             AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
             break;    
@@ -167,7 +167,7 @@
             /* reuse buffer to capture command complete event */
         A_MEMZERO(pBuffer,length);
         status = RecvHCIEvent(pConfig,pBuffer,&length);        
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI event recv failed \n"));
             AR_DEBUG_PRINTBUF(pHCICommand,CmdLength,"HCI Bridge Failed HCI Command");
             break;    
@@ -177,7 +177,7 @@
         if (pTemp[0] == HCI_CMD_COMPLETE_EVENT_CODE) {
             if ((pTemp[HCI_EVENT_OPCODE_BYTE_LOW] == opCodeBytes[0]) &&
                 (pTemp[HCI_EVENT_OPCODE_BYTE_HI] == opCodeBytes[1])) {
-                commandComplete = TRUE;    
+                commandComplete = true;
             }
         }
         
@@ -200,7 +200,7 @@
             pBuffer = NULL;            
         }
         
-    } while (FALSE);
+    } while (false);
 
     if (pBuffer != NULL) {
         A_FREE(pBuffer);    
@@ -209,27 +209,27 @@
     return status;    
 }
 
-static A_STATUS AR3KConfigureHCIBaud(AR3K_CONFIG_INFO *pConfig)
+static int AR3KConfigureHCIBaud(struct ar3k_config_info *pConfig)
 {
-    A_STATUS    status = A_OK;
-    A_UINT8     hciBaudChangeCommand[] =  {0x0c,0xfc,0x2,0,0};
-    A_UINT16    baudVal; 
-    A_UINT8     *pEvent = NULL;
-    A_UINT8     *pBufferToFree = NULL;
+    int    status = 0;
+    u8 hciBaudChangeCommand[] =  {0x0c,0xfc,0x2,0,0};
+    u16 baudVal;
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
     
     do {
         
         if (pConfig->Flags & AR3K_CONFIG_FLAG_SET_AR3K_BAUD) {
-            baudVal = (A_UINT16)(pConfig->AR3KBaudRate / 100);
-            hciBaudChangeCommand[3] = (A_UINT8)baudVal;
-            hciBaudChangeCommand[4] = (A_UINT8)(baudVal >> 8);
+            baudVal = (u16)(pConfig->AR3KBaudRate / 100);
+            hciBaudChangeCommand[3] = (u8)baudVal;
+            hciBaudChangeCommand[4] = (u8)(baudVal >> 8);
             
             status = SendHCICommandWaitCommandComplete(pConfig,
                                                        hciBaudChangeCommand,
                                                        sizeof(hciBaudChangeCommand),
                                                        &pEvent,
                                                        &pBufferToFree);          
-            if (A_FAILED(status)) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: Baud rate change failed! \n"));  
                 break;    
             }
@@ -255,7 +255,7 @@
             /* Tell target to change UART baud rate for AR6K */
             status = HCI_TransportSetBaudRate(pConfig->pHCIDev, pConfig->AR3KBaudRate);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                     ("AR3K Config: failed to set scale and step values: %d \n", status));
                 break;    
@@ -265,7 +265,7 @@
                     ("AR3K Config: Baud changed to %d for AR6K\n", pConfig->AR3KBaudRate));            
         }
                 
-    } while (FALSE);
+    } while (false);
                         
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
@@ -274,13 +274,13 @@
     return status;
 }
 
-static A_STATUS AR3KExitMinBoot(AR3K_CONFIG_INFO *pConfig)
+static int AR3KExitMinBoot(struct ar3k_config_info *pConfig)
 {
-    A_STATUS  status;
-    A_CHAR    exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
+    int  status;
+    char exitMinBootCmd[] = {0x25,0xFC,0x0c,0x03,0x00,0x00,0x00,0x00,0x00,0x00,
                                   0x00,0x00,0x00,0x00,0x00};
-    A_UINT8   *pEvent = NULL;
-    A_UINT8   *pBufferToFree = NULL;
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
     
     status = SendHCICommandWaitCommandComplete(pConfig,
                                                exitMinBootCmd,
@@ -288,7 +288,7 @@
                                                &pEvent,
                                                &pBufferToFree);
     
-    if (A_SUCCESS(status)) {
+    if (!status) {
         if (pEvent[EXIT_MIN_BOOT_COMMAND_STATUS_OFFSET] != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                 ("AR3K Config: MinBoot exit command event status failed: %d \n", 
@@ -310,12 +310,12 @@
     return status;                                              
 }
                                  
-static A_STATUS AR3KConfigureSendHCIReset(AR3K_CONFIG_INFO *pConfig)
+static int AR3KConfigureSendHCIReset(struct ar3k_config_info *pConfig)
 {
-    A_STATUS status = A_OK;
-    A_UINT8 hciResetCommand[] = {0x03,0x0c,0x0};
-    A_UINT8 *pEvent = NULL;
-    A_UINT8 *pBufferToFree = NULL;
+    int status = 0;
+    u8 hciResetCommand[] = {0x03,0x0c,0x0};
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
 
     status = SendHCICommandWaitCommandComplete( pConfig,
                                                 hciResetCommand,
@@ -323,7 +323,7 @@
                                                 &pEvent,
                                                 &pBufferToFree );
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR3K Config: HCI reset failed! \n"));
     }
 
@@ -334,11 +334,11 @@
     return status;
 }
 
-static A_STATUS AR3KEnableTLPM(AR3K_CONFIG_INFO *pConfig)
+static int AR3KEnableTLPM(struct ar3k_config_info *pConfig)
 {
-    A_STATUS  status;
+    int  status;
     /* AR3K vendor specific command for Host Wakeup Config */
-    A_CHAR    hostWakeupConfig[] = {0x31,0xFC,0x18,
+    char hostWakeupConfig[] = {0x31,0xFC,0x18,
                                     0x02,0x00,0x00,0x00,
                                     0x01,0x00,0x00,0x00,
                                     TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00,    //idle timeout in ms
@@ -346,7 +346,7 @@
                                     TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00,    //wakeup timeout in ms
                                     0x00,0x00,0x00,0x00};
     /* AR3K vendor specific command for Target Wakeup Config */
-    A_CHAR    targetWakeupConfig[] = {0x31,0xFC,0x18,
+    char targetWakeupConfig[] = {0x31,0xFC,0x18,
                                       0x04,0x00,0x00,0x00,
                                       0x01,0x00,0x00,0x00,
                                       TLPM_DEFAULT_IDLE_TIMEOUT_LSB,TLPM_DEFAULT_IDLE_TIMEOUT_MSB,0x00,0x00,  //idle timeout in ms
@@ -354,20 +354,20 @@
                                       TLPM_DEFAULT_WAKEUP_TIMEOUT_MS,0x00,0x00,0x00,  //wakeup timeout in ms
                                       0x00,0x00,0x00,0x00};
     /* AR3K vendor specific command for Host Wakeup Enable */
-    A_CHAR    hostWakeupEnable[] = {0x31,0xFC,0x4,
+    char hostWakeupEnable[] = {0x31,0xFC,0x4,
                                     0x01,0x00,0x00,0x00};
     /* AR3K vendor specific command for Target Wakeup Enable */
-    A_CHAR    targetWakeupEnable[] = {0x31,0xFC,0x4,
+    char targetWakeupEnable[] = {0x31,0xFC,0x4,
                                       0x06,0x00,0x00,0x00};
     /* AR3K vendor specific command for Sleep Enable */
-    A_CHAR    sleepEnable[] = {0x4,0xFC,0x1,
+    char sleepEnable[] = {0x4,0xFC,0x1,
                                0x1};
-    A_UINT8   *pEvent = NULL;
-    A_UINT8   *pBufferToFree = NULL;
+    u8 *pEvent = NULL;
+    u8 *pBufferToFree = NULL;
     
     if (0 != pConfig->IdleTimeout) {
-        A_UINT8 idle_lsb = pConfig->IdleTimeout & 0xFF;
-        A_UINT8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
+        u8 idle_lsb = pConfig->IdleTimeout & 0xFF;
+        u8 idle_msb = (pConfig->IdleTimeout & 0xFF00) >> 8;
         hostWakeupConfig[11] = targetWakeupConfig[11] = idle_lsb;
         hostWakeupConfig[12] = targetWakeupConfig[12] = idle_msb;
     }
@@ -384,7 +384,7 @@
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Config Failed! \n"));    
         return status;
     }
@@ -399,7 +399,7 @@
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Config Failed! \n"));    
         return status;
     }
@@ -414,7 +414,7 @@
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HostWakeup Enable Failed! \n"));    
         return status;
     }
@@ -429,7 +429,7 @@
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Target Wakeup Enable Failed! \n"));    
         return status;
     }
@@ -444,7 +444,7 @@
     if (pBufferToFree != NULL) {
         A_FREE(pBufferToFree);    
     }
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Sleep Enable Failed! \n"));    
     }
     
@@ -453,9 +453,9 @@
     return status;                                              
 }
 
-A_STATUS AR3KConfigure(AR3K_CONFIG_INFO *pConfig)
+int AR3KConfigure(struct ar3k_config_info *pConfig)
 {
-    A_STATUS        status = A_OK; 
+    int        status = 0;
         
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuring AR3K ...\n"));
                                 
@@ -467,21 +467,21 @@
         }
         
             /* disable asynchronous recv while we issue commands and receive events synchronously */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
+        if (status) {
             break;    
         }
       
         if (pConfig->Flags & AR3K_CONFIG_FLAG_FORCE_MINBOOT_EXIT) {
             status =  AR3KExitMinBoot(pConfig);   
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }    
         }
         
        
         /* Load patching and PST file if available*/
-        if (A_OK != AthPSInitialize(pConfig)) {
+        if (0 != AthPSInitialize(pConfig)) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Patch Download Failed!\n"));
         }
 
@@ -491,7 +491,7 @@
  	if (pConfig->Flags & 
                 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
             status = AR3KConfigureHCIBaud(pConfig);      
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
         }     
@@ -507,13 +507,13 @@
         }
                
            /* re-enable asynchronous recv */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
+        if (status) {
             break;    
         }     
     
     
-    } while (FALSE);   
+    } while (false);
     
   
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Configuration Complete (status = %d) \n",status));
@@ -521,10 +521,10 @@
     return status;
 }
 
-A_STATUS AR3KConfigureExit(void *config)
+int AR3KConfigureExit(void *config)
 {
-    A_STATUS        status = A_OK; 
-    AR3K_CONFIG_INFO *pConfig = (AR3K_CONFIG_INFO *)config;
+    int        status = 0;
+    struct ar3k_config_info *pConfig = (struct ar3k_config_info *)config;
         
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleaning up AR3K ...\n"));
                                 
@@ -536,27 +536,27 @@
         }
         
             /* disable asynchronous recv while we issue commands and receive events synchronously */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,FALSE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,false);
+        if (status) {
             break;    
         }
       
         if (pConfig->Flags & 
                 (AR3K_CONFIG_FLAG_SET_AR3K_BAUD | AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP)) {
             status = AR3KConfigureHCIBaud(pConfig);      
-            if (A_FAILED(status)) {
+            if (status) {
                 break;    
             }
         }
 
            /* re-enable asynchronous recv */
-        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,TRUE);
-        if (A_FAILED(status)) {
+        status = HCI_TransportEnableDisableAsyncRecv(pConfig->pHCIDev,true);
+        if (status) {
             break;    
         }     
     
     
-    } while (FALSE);   
+    } while (false);
     
   
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR3K Config: Cleanup Complete (status = %d) \n",status));
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,41 +41,41 @@
  */
 typedef struct {
 
-    PSCmdPacket *HciCmdList;
-    A_UINT32  num_packets;
-    AR3K_CONFIG_INFO *dev;
+    struct ps_cmd_packet *HciCmdList;
+    u32 num_packets;
+    struct ar3k_config_info *dev;
 }HciCommandListParam;
 
-A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
-                                           A_UINT8          *pHCICommand,
+int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
+                                           u8 *pHCICommand,
                                            int              CmdLength,
-                                           A_UINT8          **ppEventBuffer,
-                                           A_UINT8          **ppBufferToFree);
+                                           u8 **ppEventBuffer,
+                                           u8 **ppBufferToFree);
 
-A_UINT32  Rom_Version;
-A_UINT32  Build_Version;
-extern A_BOOL BDADDR;
+u32 Rom_Version;
+u32 Build_Version;
+extern bool BDADDR;
 
-A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code);
-A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig);
+int getDeviceType(struct ar3k_config_info *pConfig, u32 *code);
+int ReadVersionInfo(struct ar3k_config_info *pConfig);
 #ifndef HCI_TRANSPORT_SDIO
 
 DECLARE_WAIT_QUEUE_HEAD(PsCompleteEvent);
 DECLARE_WAIT_QUEUE_HEAD(HciEvent);
-A_UCHAR *HciEventpacket;
+u8 *HciEventpacket;
 rwlock_t syncLock;
 wait_queue_t Eventwait;
 
-int PSHciWritepacket(struct hci_dev*,A_UCHAR* Data, A_UINT32 len);
+int PSHciWritepacket(struct hci_dev*,u8* Data, u32 len);
 extern char *bdaddr;
 #endif /* HCI_TRANSPORT_SDIO */
 
-A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type);
+int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type);
 
 int PSSendOps(void *arg);
 
 #ifdef BT_PS_DEBUG
-void Hci_log(A_UCHAR * log_string,A_UCHAR *data,A_UINT32 len)
+void Hci_log(u8 * log_string,u8 *data,u32 len)
 {
     int i;
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s : ",log_string));
@@ -91,9 +91,9 @@
 
 
 
-A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev)
+int AthPSInitialize(struct ar3k_config_info *hdev)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     if(hdev == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Invalid Device handle received\n"));
         return A_ERROR;
@@ -118,7 +118,7 @@
         remove_wait_queue(&PsCompleteEvent,&wait);
         return A_ERROR;
     }
-    wait_event_interruptible(PsCompleteEvent,(PSTagMode == FALSE));
+    wait_event_interruptible(PsCompleteEvent,(PSTagMode == false));
     set_current_state(TASK_RUNNING);
     remove_wait_queue(&PsCompleteEvent,&wait);
 
@@ -133,21 +133,21 @@
 {
     int i;
     int status = 0;
-    PSCmdPacket *HciCmdList; /* List storing the commands */
+    struct ps_cmd_packet *HciCmdList; /* List storing the commands */
     const struct firmware* firmware;
-    A_UINT32 numCmds;
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree;
+    u32 numCmds;
+    u8 *event;
+    u8 *bufferToFree;
     struct hci_dev *device;
-    A_UCHAR *buffer;
-    A_UINT32 len;
-    A_UINT32 DevType;
-    A_UCHAR *PsFileName;
-    A_UCHAR *patchFileName;
-    A_UCHAR *path = NULL;
-    A_UCHAR *config_path = NULL;
-    A_UCHAR config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
-    AR3K_CONFIG_INFO *hdev = (AR3K_CONFIG_INFO*)arg;
+    u8 *buffer;
+    u32 len;
+    u32 DevType;
+    u8 *PsFileName;
+    u8 *patchFileName;
+    u8 *path = NULL;
+    u8 *config_path = NULL;
+    u8 config_bdaddr[MAX_BDADDR_FORMAT_LENGTH];
+    struct ar3k_config_info *hdev = (struct ar3k_config_info*)arg;
     struct device *firmwareDev = NULL;
     status = 0;
     HciCmdList = NULL;
@@ -157,17 +157,17 @@
 #else 
     device = hdev;
     firmwareDev = &device->dev;
-    AthEnableSyncCommandOp(TRUE);    
+    AthEnableSyncCommandOp(true);
 #endif /* HCI_TRANSPORT_SDIO */
     /* First verify if the controller is an FPGA or ASIC, so depending on the device type the PS file to be written will be different.
      */
 
-    path =(A_UCHAR *)A_MALLOC(MAX_FW_PATH_LEN);
+    path =(u8 *)A_MALLOC(MAX_FW_PATH_LEN);
     if(path == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for path\n", MAX_FW_PATH_LEN));
         goto complete;
     }
-    config_path = (A_UCHAR *) A_MALLOC(MAX_FW_PATH_LEN);
+    config_path = (u8 *) A_MALLOC(MAX_FW_PATH_LEN);
     if(config_path == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Malloc failed to allocate %d bytes for config_path\n", MAX_FW_PATH_LEN));
         goto complete;
@@ -214,7 +214,7 @@
         status = 1;
         goto complete;
     }
-    buffer = (A_UCHAR *)A_MALLOC(firmware->size);
+    buffer = (u8 *)A_MALLOC(firmware->size);
     if(buffer != NULL) {
     /* Copy the read file to a local Dynamic buffer */
         memcpy(buffer,firmware->data,firmware->size);
@@ -248,7 +248,7 @@
         if(NULL == firmware || firmware->size == 0) {
             status = 0;
         } else {
-            buffer = (A_UCHAR *)A_MALLOC(firmware->size);
+            buffer = (u8 *)A_MALLOC(firmware->size);
             if(buffer != NULL) {
                 /* Copy the read file to a local Dynamic buffer */
                 memcpy(buffer,firmware->data,firmware->size);
@@ -280,8 +280,8 @@
     HciCmdList[0].Hcipacket,
     HciCmdList[0].packetLen,
     &event,
-    &bufferToFree) == A_OK) {
-        if(ReadPSEvent(event) == A_OK) { /* Exit if the status is success */
+    &bufferToFree) == 0) {
+        if(ReadPSEvent(event) == 0) { /* Exit if the status is success */
             if(bufferToFree != NULL) {
                 A_FREE(bufferToFree);
                 }
@@ -309,8 +309,8 @@
         HciCmdList[i].Hcipacket,
         HciCmdList[i].packetLen,
         &event,
-        &bufferToFree) == A_OK) {
-            if(ReadPSEvent(event) != A_OK) { /* Exit if the status is success */
+        &bufferToFree) == 0) {
+            if(ReadPSEvent(event) != 0) { /* Exit if the status is success */
                 if(bufferToFree != NULL) {
                     A_FREE(bufferToFree);
                     }
@@ -326,7 +326,7 @@
         }
     }
 #ifdef HCI_TRANSPORT_SDIO
-	if(BDADDR == FALSE)
+	if(BDADDR == false)
 		if(hdev->bdaddr[0] !=0x00 ||
 		   hdev->bdaddr[1] !=0x00 ||
 		   hdev->bdaddr[2] !=0x00 ||
@@ -360,7 +360,7 @@
         	status = 1;
         	goto complete;
     	}
-	len = min(firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1);
+	len = min_t(size_t, firmware->size, MAX_BDADDR_FORMAT_LENGTH - 1);
 	memcpy(config_bdaddr, firmware->data, len);
 	config_bdaddr[len] = '\0';
 	write_bdaddr(hdev,config_bdaddr,BDADDR_TYPE_STRING);
@@ -368,8 +368,8 @@
 	}
 complete:
 #ifndef HCI_TRANSPORT_SDIO
-    AthEnableSyncCommandOp(FALSE);    
-    PSTagMode = FALSE;
+    AthEnableSyncCommandOp(false);
+    PSTagMode = false;
     wake_up_interruptible(&PsCompleteEvent);
 #endif /* HCI_TRANSPORT_SDIO */
     if(NULL != HciCmdList) {
@@ -389,23 +389,23 @@
  *  with a HCI Command Complete event.
  *  For HCI SDIO transport, this will be internally defined. 
  */
-A_STATUS SendHCICommandWaitCommandComplete(AR3K_CONFIG_INFO *pConfig,
-                                           A_UINT8          *pHCICommand,
+int SendHCICommandWaitCommandComplete(struct ar3k_config_info *pConfig,
+                                           u8 *pHCICommand,
                                            int              CmdLength,
-                                           A_UINT8          **ppEventBuffer,
-                                           A_UINT8          **ppBufferToFree)
+                                           u8 **ppEventBuffer,
+                                           u8 **ppBufferToFree)
 {
     if(CmdLength == 0) {
         return A_ERROR;
     }
     Hci_log("COM Write -->",pHCICommand,CmdLength);
-    PSAcked = FALSE;
+    PSAcked = false;
     if(PSHciWritepacket(pConfig,pHCICommand,CmdLength) == 0) {
         /* If the controller is not available, return Error */
         return A_ERROR;
     }
     //add_timer(&psCmdTimer);
-    wait_event_interruptible(HciEvent,(PSAcked == TRUE));
+    wait_event_interruptible(HciEvent,(PSAcked == true));
     if(NULL != HciEventpacket) {
         *ppEventBuffer = HciEventpacket;
         *ppBufferToFree = HciEventpacket;
@@ -415,25 +415,25 @@
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 #endif /* HCI_TRANSPORT_SDIO */
 
-A_STATUS ReadPSEvent(A_UCHAR* Data){
+int ReadPSEvent(u8* Data){
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" PS Event %x %x %x\n",Data[4],Data[5],Data[3]));
                                 
     if(Data[4] == 0xFC && Data[5] == 0x00)
     {
          switch(Data[3]){
              case 0x0B:
-                     return A_OK;
+                     return 0;
                  break;
                  case 0x0C:
                     /* Change Baudrate */
-                        return A_OK;    
+                        return 0;
                  break;  
                  case 0x04:
-                     return A_OK;
+                     return 0;
                  break;  
 		case 0x1E:
 			Rom_Version = Data[9];
@@ -445,7 +445,7 @@
 			Build_Version = ((Build_Version << 8) |Data[12]);
 			Build_Version = ((Build_Version << 8) |Data[11]);
 			Build_Version = ((Build_Version << 8) |Data[10]);
-			return A_OK;
+			return 0;
 		break;
 
         
@@ -481,14 +481,14 @@
 	return 0; 
 }
 
-A_STATUS write_bdaddr(AR3K_CONFIG_INFO *pConfig,A_UCHAR *bdaddr,int type)
+int write_bdaddr(struct ar3k_config_info *pConfig,u8 *bdaddr,int type)
 {
-	A_UCHAR bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 
+	u8 bdaddr_cmd[] = { 0x0B, 0xFC, 0x0A, 0x01, 0x01, 
 							0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
 
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree = NULL;
-    A_STATUS result = A_ERROR;
+    u8 *event;
+    u8 *bufferToFree = NULL;
+    int result = A_ERROR;
 	int inc,outc;
 
 	if (type == BDADDR_TYPE_STRING)
@@ -499,13 +499,13 @@
 			bdaddr_cmd[outc] = bdaddr[inc];
 	}
 
-    if(A_OK == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
+    if(0 == SendHCICommandWaitCommandComplete(pConfig,bdaddr_cmd,
 												sizeof(bdaddr_cmd),
 												&event,&bufferToFree)) {
 
         if(event[4] == 0xFC && event[5] == 0x00){
                if(event[3] == 0x0B){
-                result = A_OK;
+                result = 0;
             }
         }
 
@@ -516,13 +516,13 @@
     return result;
 
 }
-A_STATUS ReadVersionInfo(AR3K_CONFIG_INFO *pConfig)
+int ReadVersionInfo(struct ar3k_config_info *pConfig)
 {
-    A_UINT8   hciCommand[] =  {0x1E,0xfc,0x00};
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree = NULL;
-    A_STATUS result = A_ERROR;
-    if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
+    u8 hciCommand[] =  {0x1E,0xfc,0x00};
+    u8 *event;
+    u8 *bufferToFree = NULL;
+    int result = A_ERROR;
+    if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
 	result = ReadPSEvent(event);
 
     }
@@ -531,19 +531,19 @@
    }
     return result;
 }
-A_STATUS getDeviceType(AR3K_CONFIG_INFO *pConfig, A_UINT32 * code)
+int getDeviceType(struct ar3k_config_info *pConfig, u32 *code)
 {
-    A_UINT8   hciCommand[] =  {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
-    A_UINT8 *event;
-    A_UINT8 *bufferToFree = NULL;
-    A_UINT32 reg;
-    A_STATUS result = A_ERROR;
+    u8 hciCommand[] =  {0x05,0xfc,0x05,0x00,0x00,0x00,0x00,0x04};
+    u8 *event;
+    u8 *bufferToFree = NULL;
+    u32 reg;
+    int result = A_ERROR;
     *code = 0;
-    hciCommand[3] = (A_UINT8)(FPGA_REGISTER & 0xFF);
-    hciCommand[4] = (A_UINT8)((FPGA_REGISTER >> 8) & 0xFF);
-    hciCommand[5] = (A_UINT8)((FPGA_REGISTER >> 16) & 0xFF);
-    hciCommand[6] = (A_UINT8)((FPGA_REGISTER >> 24) & 0xFF); 
-    if(A_OK == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
+    hciCommand[3] = (u8)(FPGA_REGISTER & 0xFF);
+    hciCommand[4] = (u8)((FPGA_REGISTER >> 8) & 0xFF);
+    hciCommand[5] = (u8)((FPGA_REGISTER >> 16) & 0xFF);
+    hciCommand[6] = (u8)((FPGA_REGISTER >> 24) & 0xFF);
+    if(0 == SendHCICommandWaitCommandComplete(pConfig,hciCommand,sizeof(hciCommand),&event,&bufferToFree)) {
 
         if(event[4] == 0xFC && event[5] == 0x00){
                switch(event[3]){
@@ -553,7 +553,7 @@
                 reg = ((reg << 8) |event[7]);
                 reg = ((reg << 8) |event[6]);
                 *code = reg;
-                result = A_OK;
+                result = 0;
 
                 break;
                 case 0x06:
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsconfig.h	2011-05-19 00:06:34.000000000 -0400
@@ -64,12 +64,12 @@
 
 
 #ifndef HCI_TRANSPORT_SDIO
-#define AR3K_CONFIG_INFO        struct hci_dev
+#define struct ar3k_config_info        struct hci_dev
 extern wait_queue_head_t HciEvent;
 extern wait_queue_t Eventwait;
-extern A_UCHAR *HciEventpacket;
+extern u8 *HciEventpacket;
 #endif /* #ifndef HCI_TRANSPORT_SDIO */
 
-A_STATUS AthPSInitialize(AR3K_CONFIG_INFO *hdev);
-A_STATUS ReadPSEvent(A_UCHAR* Data);
+int AthPSInitialize(struct ar3k_config_info *hdev);
+int ReadPSEvent(u8* Data);
 #endif /* __AR3KPSCONFIG_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.c	2011-05-19 00:06:34.000000000 -0400
@@ -87,53 +87,53 @@
 
 typedef struct tPsTagEntry
 {
-   A_UINT32   TagId;
-   A_UINT32   TagLen;
-   A_UINT8    *TagData;
+   u32 TagId;
+   u32 TagLen;
+   u8 *TagData;
 } tPsTagEntry, *tpPsTagEntry;
 
 typedef struct tRamPatch
 {
-   A_UINT16   Len;
-   A_UINT8    * Data;
+   u16 Len;
+   u8 *Data;
 } tRamPatch, *ptRamPatch;
 
 
 
-typedef struct ST_PS_DATA_FORMAT {
+struct st_ps_data_format {
    enum eType   eDataType;
-   A_BOOL    bIsArray;
-}ST_PS_DATA_FORMAT;
+   bool    bIsArray;
+};
 
-typedef struct ST_READ_STATUS {
+struct st_read_status {
     unsigned uTagID;
     unsigned uSection;
     unsigned uLineCount;
     unsigned uCharCount;
     unsigned uByteCount;
-}ST_READ_STATUS;
+};
 
 
 /* Stores the number of PS Tags */
-static A_UINT32 Tag_Count = 0;
+static u32 Tag_Count = 0;
 
 /* Stores the number of patch commands */
-static A_UINT32 Patch_Count = 0;
-static A_UINT32 Total_tag_lenght = 0;
-A_BOOL BDADDR = FALSE;
-A_UINT32      StartTagId;
+static u32 Patch_Count = 0;
+static u32 Total_tag_lenght = 0;
+bool BDADDR = false;
+u32 StartTagId;
 
 tPsTagEntry PsTagEntry[RAMPS_MAX_PS_TAGS_PER_FILE];
 tRamPatch   RamPatch[MAX_NUM_PATCH_ENTRY];
 
 
-A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat);
-char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos);
-char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos);
-static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index);
+int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat);
+char AthReadChar(u8 *buffer, u32 len,u32 *pos);
+char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos);
+static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index);
 
 /* Function to reads the next character from the input buffer */
-char AthReadChar(A_UCHAR *buffer, A_UINT32 len,A_UINT32 *pos) 
+char AthReadChar(u8 *buffer, u32 len,u32 *pos)
 {
     char Ch;
     if(buffer == NULL || *pos >=len )
@@ -146,7 +146,7 @@
     }
 }
 /* PS parser helper function */
-unsigned int uGetInputDataFormat(char* pCharLine, ST_PS_DATA_FORMAT *pstFormat) 
+unsigned int uGetInputDataFormat(char *pCharLine, struct st_ps_data_format *pstFormat)
 {
     if(pCharLine[0] != '[') {
         pstFormat->eDataType = eHex;
@@ -286,7 +286,7 @@
     }
 }
 
-unsigned int uReadDataInSection(char *pCharLine, ST_PS_DATA_FORMAT stPS_DataFormat)
+unsigned int uReadDataInSection(char *pCharLine, struct st_ps_data_format stPS_DataFormat)
 {
     char *pTokenPtr = pCharLine;
 
@@ -315,20 +315,20 @@
         return (0x0FFF);
     }
 }
-A_STATUS AthParseFilesUnified(A_UCHAR *srcbuffer,A_UINT32 srclen, int FileFormat)
+int AthParseFilesUnified(u8 *srcbuffer,u32 srclen, int FileFormat)
 {
-   char     *Buffer;
-   char     *pCharLine;
-   A_UINT8    TagCount;
-   A_UINT16   ByteCount;
-   A_UINT8    ParseSection=RAM_PS_SECTION;
-   A_UINT32 pos;
+   char *Buffer;
+   char *pCharLine;
+   u8 TagCount;
+   u16 ByteCount;
+   u8 ParseSection=RAM_PS_SECTION;
+   u32 pos;
 
 
 
    int uReadCount;
-   ST_PS_DATA_FORMAT stPS_DataFormat;
-   ST_READ_STATUS   stReadStatus = {0, 0, 0,0};
+   struct st_ps_data_format stPS_DataFormat;
+   struct st_read_status   stReadStatus = {0, 0, 0,0};
    pos = 0;
    Buffer = NULL;
 
@@ -438,7 +438,7 @@
                        return A_ERROR;
                     }
                     PsTagEntry[TagCount].TagLen = ByteCount;
-                    PsTagEntry[TagCount].TagData = (A_UINT8*)A_MALLOC(ByteCount);
+                    PsTagEntry[TagCount].TagData = (u8 *)A_MALLOC(ByteCount);
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" TAG Length %d  Tag Index %d \n",PsTagEntry[TagCount].TagLen,TagCount));
                     stReadStatus.uSection = 3;
                     stReadStatus.uLineCount = 0;
@@ -472,12 +472,12 @@
                     if((stPS_DataFormat.eDataType == eHex) && stPS_DataFormat.bIsArray == true) {
                        while(uReadCount > 0) {
                            PsTagEntry[TagCount].TagData[stReadStatus.uByteCount] =
-                                                     (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4)
-                                                     | (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1]));
+                                                     (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount]) << 4)
+                                                     | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 1]));
 
                            PsTagEntry[TagCount].TagData[stReadStatus.uByteCount+1] =
-                                                     (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4)
-                                                     | (A_UINT8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4]));
+                                                     (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 3]) << 4)
+                                                     | (u8)(hex_to_bin(pCharLine[stReadStatus.uCharCount + 4]));
 
                            stReadStatus.uCharCount += 6; // read two bytes, plus a space;
                            stReadStatus.uByteCount += 2;
@@ -549,7 +549,7 @@
    if(Buffer != NULL) {
         A_FREE(Buffer);
    }
-   return A_OK;
+   return 0;
 
 }
 
@@ -558,7 +558,7 @@
 /********************/
 
 
-A_STATUS GetNextTwoChar(A_UCHAR *srcbuffer,A_UINT32 len, A_UINT32 *pos, char * buffer)
+int GetNextTwoChar(u8 *srcbuffer,u32 len, u32 *pos, char *buffer)
 {
     unsigned char ch;
 
@@ -576,19 +576,19 @@
     {
         return A_ERROR;
     }
-    return A_OK;
+    return 0;
 }
 
-A_STATUS AthDoParsePatch(A_UCHAR *patchbuffer, A_UINT32 patchlen)
+int AthDoParsePatch(u8 *patchbuffer, u32 patchlen)
 {
 
-    char  Byte[3];
-    char   Line[MAX_BYTE_LENGTH + 1];
+    char Byte[3];
+    char Line[MAX_BYTE_LENGTH + 1];
     int    ByteCount,ByteCount_Org;
     int count;
     int i,j,k;
     int data;
-    A_UINT32 filepos;
+    u32 filepos;
     Byte[2] = '\0';
     j = 0;
     filepos = 0;
@@ -614,7 +614,7 @@
             return A_ERROR;
         }
         RamPatch[Patch_Count].Len= MAX_BYTE_LENGTH;
-        RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(MAX_BYTE_LENGTH);
+        RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(MAX_BYTE_LENGTH);
         Patch_Count ++;
 
 
@@ -623,7 +623,7 @@
 
     RamPatch[Patch_Count].Len= (ByteCount & 0xFF);
     if(ByteCount != 0) {
-        RamPatch[Patch_Count].Data = (A_UINT8*)A_MALLOC(ByteCount);
+        RamPatch[Patch_Count].Data = (u8 *)A_MALLOC(ByteCount);
         Patch_Count ++;
     }
     count = 0;
@@ -654,21 +654,21 @@
 
 
     }
-    return A_OK;
+    return 0;
 }
 
 
 /********************/
-A_STATUS AthDoParsePS(A_UCHAR *srcbuffer, A_UINT32 srclen)
+int AthDoParsePS(u8 *srcbuffer, u32 srclen)
 {
-    A_STATUS status;
+    int status;
     int i;
-    A_BOOL BDADDR_Present = A_ERROR;
+    bool BDADDR_Present = false;
 
     Tag_Count = 0;
 
     Total_tag_lenght = 0;
-    BDADDR = FALSE;
+    BDADDR = false;
 
 
     status = A_ERROR;
@@ -689,7 +689,7 @@
         else{
                 for(i=0; i<Tag_Count; i++){
                         if(PsTagEntry[i].TagId == 1){
-                                BDADDR_Present = A_OK;
+                                BDADDR_Present = true;
                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BD ADDR is present in Patch File \r\n"));
 
                         }
@@ -713,7 +713,7 @@
 
     return status;
 }
-char * AthGetLine(char * buffer, int maxlen, A_UCHAR *srcbuffer,A_UINT32 len,A_UINT32 *pos)
+char *AthGetLine(char *buffer, int maxlen, u8 *srcbuffer,u32 len,u32 *pos)
 {
 
     int count;
@@ -751,7 +751,7 @@
     return buffer;
 }
 
-static void LoadHeader(A_UCHAR *HCI_PS_Command,A_UCHAR opcode,int length,int index){
+static void LoadHeader(u8 *HCI_PS_Command,u8 opcode,int length,int index){
 
         HCI_PS_Command[0]= 0x0B;
         HCI_PS_Command[1]= 0xFC;
@@ -764,13 +764,13 @@
 
 /////////////////////////
 //
-int AthCreateCommandList(PSCmdPacket **HciPacketList, A_UINT32 *numPackets)
+int AthCreateCommandList(struct ps_cmd_packet **HciPacketList, u32 *numPackets)
 {
 
-    A_UINT8 count;
-    A_UINT32 NumcmdEntry = 0; 
+    u8 count;
+    u32 NumcmdEntry = 0;
 
-    A_UINT32 Crc = 0;
+    u32 Crc = 0;
     *numPackets = 0;
 
 
@@ -785,8 +785,8 @@
         if(Patch_Count > 0) {
             NumcmdEntry++; /* Patch Enable Command */
         }
-           AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size  %d  \r\n",NumcmdEntry,(A_UINT32)sizeof(PSCmdPacket) * NumcmdEntry));
-        (*HciPacketList) = A_MALLOC(sizeof(PSCmdPacket) * NumcmdEntry);
+           AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Num Cmd Entries %d Size  %d  \r\n",NumcmdEntry,(u32)sizeof(struct ps_cmd_packet) * NumcmdEntry));
+        (*HciPacketList) = A_MALLOC(sizeof(struct ps_cmd_packet) * NumcmdEntry);
     if(NULL == *HciPacketList) {
                AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("memory allocation failed  \r\n"));
         }
@@ -833,10 +833,10 @@
 ////////////////////////
 
 /////////////
-static A_STATUS AthPSCreateHCICommand(A_UCHAR Opcode, A_UINT32 Param1,PSCmdPacket *PSPatchPacket,A_UINT32 *index)
+static int AthPSCreateHCICommand(u8 Opcode, u32 Param1,struct ps_cmd_packet *PSPatchPacket,u32 *index)
 {
-    A_UCHAR *HCI_PS_Command;
-    A_UINT32 Length;
+    u8 *HCI_PS_Command;
+    u32 Length;
     int i,j;
     
     switch(Opcode)
@@ -846,7 +846,7 @@
 
          for(i=0;i< Param1;i++){
 
-             HCI_PS_Command = (A_UCHAR *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
+             HCI_PS_Command = (u8 *) A_MALLOC(RamPatch[i].Len+HCI_COMMAND_HEADER);
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Allocated Buffer Size %d\n",RamPatch[i].Len+HCI_COMMAND_HEADER));
                  if(HCI_PS_Command == NULL){
                      AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
@@ -871,7 +871,7 @@
 
          Length = 0;
          i= 0;
-         HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
+         HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
          if(HCI_PS_Command == NULL){
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
             return A_ERROR;
@@ -888,7 +888,7 @@
     case PS_RESET:
                         Length = 0x06;
                         i=0;
-                        HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
+                        HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
                         if(HCI_PS_Command == NULL){
                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
                                 return A_ERROR;
@@ -907,9 +907,9 @@
     case PS_WRITE:
                        for(i=0;i< Param1;i++){
                                 if(PsTagEntry[i].TagId ==1)
-                                        BDADDR = TRUE;
+                                        BDADDR = true;
 
-                                HCI_PS_Command = (A_UCHAR *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
+                                HCI_PS_Command = (u8 *) A_MALLOC(PsTagEntry[i].TagLen+HCI_COMMAND_HEADER);
                                 if(HCI_PS_Command == NULL){
                                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
                                         return A_ERROR;
@@ -936,7 +936,7 @@
 
                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("VALUE of CRC:%d At index %d\r\n",Param1,*index));
 
-                        HCI_PS_Command = (A_UCHAR *) A_MALLOC(Length+HCI_COMMAND_HEADER);
+                        HCI_PS_Command = (u8 *) A_MALLOC(Length+HCI_COMMAND_HEADER);
                         if(HCI_PS_Command == NULL){
                                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("MALLOC Failed\r\n"));
                                 return A_ERROR;
@@ -953,9 +953,9 @@
     case CHANGE_BDADDR:
     break;
     }
-    return A_OK;
+    return 0;
 }
-A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets)
+int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets)
 {
     int i;
     if(*HciPacketList == NULL) {
@@ -965,5 +965,5 @@
         A_FREE((*HciPacketList)[i].Hcipacket);
     }  
     A_FREE(*HciPacketList);
-    return A_OK;
+    return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/ar3kps/ar3kpsparser.h	2011-05-19 00:06:34.000000000 -0400
@@ -48,22 +48,14 @@
 
 /* Helper data type declaration */
 
-#ifndef A_UINT32
-#define A_UCHAR                 unsigned char
-#define A_UINT32                unsigned long
-#define A_UINT16                unsigned short
-#define A_UINT8                 unsigned char
-#define A_BOOL                  unsigned char
-#endif /* A_UINT32 */
-
 #define ATH_DEBUG_ERR          (1 << 0)
 #define ATH_DEBUG_WARN         (1 << 1)
 #define ATH_DEBUG_INFO         (1 << 2)
 
 
 
-#define FALSE   0
-#define TRUE    1
+#define false   0
+#define true    1
 
 #ifndef A_MALLOC
 #define A_MALLOC(size)  kmalloc((size),GFP_KERNEL)
@@ -97,17 +89,17 @@
 
 
 
-typedef struct PSCmdPacket
+struct ps_cmd_packet
 {
-    A_UCHAR *Hcipacket;
+    u8 *Hcipacket;
     int packetLen;
-} PSCmdPacket;
+};
 
 /* Parses a Patch information buffer and store it in global structure */
-A_STATUS AthDoParsePatch(A_UCHAR *, A_UINT32);
+int AthDoParsePatch(u8 *, u32 );
 
 /* parses a PS information buffer and stores it in a global structure */
-A_STATUS AthDoParsePS(A_UCHAR *, A_UINT32);
+int AthDoParsePS(u8 *, u32 );
 
 /* 
  *  Uses the output of Both AthDoParsePS and AthDoParsePatch APIs to form HCI command array with
@@ -120,8 +112,8 @@
  *  PS Tag Command(s)
  *
  */  
-int AthCreateCommandList(PSCmdPacket **, A_UINT32 *);
+int AthCreateCommandList(struct ps_cmd_packet **, u32 *);
 
 /* Cleanup the dynamically allicated HCI command list */
-A_STATUS AthFreeCommandList(PSCmdPacket **HciPacketList, A_UINT32 numPackets);
+int AthFreeCommandList(struct ps_cmd_packet **HciPacketList, u32 numPackets);
 #endif /* __AR3KPSPARSER_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/common_drv.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/common_drv.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/common_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/common_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,7 +47,7 @@
 
 static ATH_DEBUG_MODULE_DBG_INFO *g_pModuleInfoHead = NULL;
 static A_MUTEX_T                 g_ModuleListLock;
-static A_BOOL                    g_ModuleDebugInit = FALSE;
+static bool                    g_ModuleDebugInit = false;
 
 #ifdef ATH_DEBUG_MODULE
 
@@ -71,8 +71,8 @@
 #define CPU_DBG_SEL_ADDRESS                      0x00000483
 #define CPU_DBG_ADDRESS                          0x00000484
 
-static A_UINT8 custDataAR6002[AR6002_CUST_DATA_SIZE];
-static A_UINT8 custDataAR6003[AR6003_CUST_DATA_SIZE];
+static u8 custDataAR6002[AR6002_CUST_DATA_SIZE];
+static u8 custDataAR6003[AR6003_CUST_DATA_SIZE];
 
 /* Compile the 4BYTE version of the window register setup routine,
  * This mitigates host interconnect issues with non-4byte aligned bus requests, some
@@ -83,18 +83,18 @@
 #ifdef USE_4BYTE_REGISTER_ACCESS
 
     /* set the window address register (using 4-byte register access ). */
-A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
+int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address)
 {
-    A_STATUS status;
-    A_UINT8 addrValue[4];
-    A_INT32 i;
+    int status;
+    u8 addrValue[4];
+    s32 i;
 
         /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
          * last to initiate the access cycle */
 
     for (i = 1; i <= 3; i++) {
             /* fill the buffer with the address byte value we want to hit 4 times*/
-        addrValue[0] = ((A_UINT8 *)&Address)[i];
+        addrValue[0] = ((u8 *)&Address)[i];
         addrValue[1] = addrValue[0];
         addrValue[2] = addrValue[0];
         addrValue[3] = addrValue[0];
@@ -107,12 +107,12 @@
                               4,
                               HIF_WR_SYNC_BYTE_FIX,
                               NULL);
-        if (status != A_OK) {
+        if (status) {
             break;
         }
     }
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
             Address, RegisterAddr));
         return status;
@@ -123,18 +123,18 @@
          * 3 byte write to bytes 1,2,3 has no effect since we are writing the same values again */
     status = HIFReadWrite(hifDevice,
                           RegisterAddr,
-                          (A_UCHAR *)(&Address),
+                          (u8 *)(&Address),
                           4,
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
             Address, RegisterAddr));
         return status;
     }
 
-    return A_OK;
+    return 0;
 
 
 
@@ -144,20 +144,20 @@
 #else
 
     /* set the window address register */
-A_STATUS ar6000_SetAddressWindowRegister(HIF_DEVICE *hifDevice, A_UINT32 RegisterAddr, A_UINT32 Address)
+int ar6000_SetAddressWindowRegister(struct hif_device *hifDevice, u32 RegisterAddr, u32 Address)
 {
-    A_STATUS status;
+    int status;
 
         /* write bytes 1,2,3 of the register to set the upper address bytes, the LSB is written
          * last to initiate the access cycle */
     status = HIFReadWrite(hifDevice,
                           RegisterAddr+1,  /* write upper 3 bytes */
-                          ((A_UCHAR *)(&Address))+1,
-                          sizeof(A_UINT32)-1,
+                          ((u8 *)(&Address))+1,
+                          sizeof(u32)-1,
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write initial bytes of 0x%x to window reg: 0x%X \n",
              RegisterAddr, Address));
         return status;
@@ -166,18 +166,18 @@
         /* write the LSB of the register, this initiates the operation */
     status = HIFReadWrite(hifDevice,
                           RegisterAddr,
-                          (A_UCHAR *)(&Address),
-                          sizeof(A_UINT8),
+                          (u8 *)(&Address),
+                          sizeof(u8),
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to window reg: 0x%X \n",
             RegisterAddr, Address));
         return status;
     }
 
-    return A_OK;
+    return 0;
 }
 
 #endif
@@ -186,28 +186,28 @@
  * Read from the AR6000 through its diagnostic window.
  * No cooperation from the Target is required for this.
  */
-A_STATUS
-ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
+int
+ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data)
 {
-    A_STATUS status;
+    int status;
 
         /* set window register to start read cycle */
     status = ar6000_SetAddressWindowRegister(hifDevice,
                                              WINDOW_READ_ADDR_ADDRESS,
                                              *address);
 
-    if (status != A_OK) {
+    if (status) {
         return status;
     }
 
         /* read the data */
     status = HIFReadWrite(hifDevice,
                           WINDOW_DATA_ADDRESS,
-                          (A_UCHAR *)data,
-                          sizeof(A_UINT32),
+                          (u8 *)data,
+                          sizeof(u32),
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from WINDOW_DATA_ADDRESS\n"));
         return status;
     }
@@ -220,19 +220,19 @@
  * Write to the AR6000 through its diagnostic window.
  * No cooperation from the Target is required for this.
  */
-A_STATUS
-ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data)
+int
+ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data)
 {
-    A_STATUS status;
+    int status;
 
         /* set write data */
     status = HIFReadWrite(hifDevice,
                           WINDOW_DATA_ADDRESS,
-                          (A_UCHAR *)data,
-                          sizeof(A_UINT32),
+                          (u8 *)data,
+                          sizeof(u32),
                           HIF_WR_SYNC_BYTE_INC,
                           NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write 0x%x to WINDOW_DATA_ADDRESS\n", *data));
         return status;
     }
@@ -243,16 +243,16 @@
                                            *address);
     }
 
-A_STATUS
-ar6000_ReadDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                    A_UCHAR *data, A_UINT32 length)
+int
+ar6000_ReadDataDiag(struct hif_device *hifDevice, u32 address,
+                    u8 *data, u32 length)
 {
-    A_UINT32 count;
-    A_STATUS status = A_OK;
+    u32 count;
+    int status = 0;
 
     for (count = 0; count < length; count += 4, address += 4) {
         if ((status = ar6000_ReadRegDiag(hifDevice, &address,
-                                         (A_UINT32 *)&data[count])) != A_OK)
+                                         (u32 *)&data[count])) != 0)
         {
             break;
         }
@@ -261,16 +261,16 @@
     return status;
 }
 
-A_STATUS
-ar6000_WriteDataDiag(HIF_DEVICE *hifDevice, A_UINT32 address,
-                    A_UCHAR *data, A_UINT32 length)
+int
+ar6000_WriteDataDiag(struct hif_device *hifDevice, u32 address,
+                    u8 *data, u32 length)
 {
-    A_UINT32 count;
-    A_STATUS status = A_OK;
+    u32 count;
+    int status = 0;
 
     for (count = 0; count < length; count += 4, address += 4) {
         if ((status = ar6000_WriteRegDiag(hifDevice, &address,
-                                         (A_UINT32 *)&data[count])) != A_OK)
+                                         (u32 *)&data[count])) != 0)
         {
             break;
         }
@@ -279,12 +279,12 @@
     return status;
 }
 
-A_STATUS
-ar6k_ReadTargetRegister(HIF_DEVICE *hifDevice, int regsel, A_UINT32 *regval)
+int
+ar6k_ReadTargetRegister(struct hif_device *hifDevice, int regsel, u32 *regval)
 {
-    A_STATUS status;
-    A_UCHAR vals[4];
-    A_UCHAR register_selection[4];
+    int status;
+    u8 vals[4];
+    u8 register_selection[4];
 
     register_selection[0] = register_selection[1] = register_selection[2] = register_selection[3] = (regsel & 0xff);
     status = HIFReadWrite(hifDevice,
@@ -294,18 +294,18 @@
                           HIF_WR_SYNC_BYTE_FIX,
                           NULL);
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot write CPU_DBG_SEL (%d)\n", regsel));
         return status;
     }
 
     status = HIFReadWrite(hifDevice,
                           CPU_DBG_ADDRESS,
-                          (A_UCHAR *)vals,
+                          (u8 *)vals,
                           sizeof(vals),
                           HIF_RD_SYNC_BYTE_INC,
                           NULL);
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot read from CPU_DBG_ADDRESS\n"));
         return status;
     }
@@ -316,10 +316,10 @@
 }
 
 void
-ar6k_FetchTargetRegs(HIF_DEVICE *hifDevice, A_UINT32 *targregs)
+ar6k_FetchTargetRegs(struct hif_device *hifDevice, u32 *targregs)
 {
     int i;
-    A_UINT32 val;
+    u32 val;
 
     for (i=0; i<AR6003_FETCH_TARG_REGS_COUNT; i++) {
         val=0xffffffff;
@@ -329,13 +329,13 @@
 }
 
 #if 0
-static A_STATUS
-_do_write_diag(HIF_DEVICE *hifDevice, A_UINT32 addr, A_UINT32 value)
+static int
+_do_write_diag(struct hif_device *hifDevice, u32 addr, u32 value)
 {
-    A_STATUS status;
+    int status;
 
     status = ar6000_WriteRegDiag(hifDevice, &addr, &value);
-    if (status != A_OK)
+    if (status)
     {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Cannot force Target to execute ROM!\n"));
     }
@@ -357,12 +357,12 @@
  * TBD: Might want to add special handling for AR6K_OPTION_BMI_DISABLE.
  */
 #if 0
-static A_STATUS
-_delay_until_target_alive(HIF_DEVICE *hifDevice, A_INT32 wait_msecs, A_UINT32 TargetType)
+static int
+_delay_until_target_alive(struct hif_device *hifDevice, s32 wait_msecs, u32 TargetType)
 {
-    A_INT32 actual_wait;
-    A_INT32 i;
-    A_UINT32 address;
+    s32 actual_wait;
+    s32 i;
+    u32 address;
 
     actual_wait = 0;
 
@@ -376,19 +376,19 @@
     }
     address += 0x10;
     for (i=0; actual_wait < wait_msecs; i++) {
-        A_UINT32 data;
+        u32 data;
 
         A_MDELAY(100);
         actual_wait += 100;
 
         data = 0;
-        if (ar6000_ReadRegDiag(hifDevice, &address, &data) != A_OK) {
+        if (ar6000_ReadRegDiag(hifDevice, &address, &data) != 0) {
             return A_ERROR;
         }
 
         if (data != 0) {
             /* No need to wait longer -- we have a BMI credit */
-            return A_OK;
+            return 0;
         }
     }
     return A_ERROR; /* timed out */
@@ -399,11 +399,11 @@
 #define AR6002_RESET_CONTROL_ADDRESS 0x00004000
 #define AR6003_RESET_CONTROL_ADDRESS 0x00004000
 /* reset device */
-A_STATUS ar6000_reset_device(HIF_DEVICE *hifDevice, A_UINT32 TargetType, A_BOOL waitForCompletion, A_BOOL coldReset)
+int ar6000_reset_device(struct hif_device *hifDevice, u32 TargetType, bool waitForCompletion, bool coldReset)
 {
-    A_STATUS status = A_OK;
-    A_UINT32 address;
-    A_UINT32 data;
+    int status = 0;
+    u32 address;
+    u32 data;
 
     do {
 // Workaround BEGIN
@@ -428,7 +428,7 @@
 
         status = ar6000_WriteRegDiag(hifDevice, &address, &data);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -458,7 +458,7 @@
         data = 0;
         status = ar6000_ReadRegDiag(hifDevice, &address, &data);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -470,27 +470,27 @@
 #endif
 // Workaroud END
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_LOG_ERR, ("Failed to reset target \n"));
     }
 
-    return A_OK;
+    return 0;
 }
 
 /* This should be called in BMI phase after firmware is downloaded */
 void
-ar6000_copy_cust_data_from_target(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
+ar6000_copy_cust_data_from_target(struct hif_device *hifDevice, u32 TargetType)
 {
-    A_UINT32 eepHeaderAddr;
-    A_UINT8 AR6003CustDataShadow[AR6003_CUST_DATA_SIZE+4];
-    A_INT32 i;
+    u32 eepHeaderAddr;
+    u8 AR6003CustDataShadow[AR6003_CUST_DATA_SIZE+4];
+    s32 i;
 
     if (BMIReadMemory(hifDevice,
             HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_board_data),
-            (A_UCHAR *)&eepHeaderAddr,
-            4)!= A_OK)
+            (u8 *)&eepHeaderAddr,
+            4)!= 0)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadMemory for reading board data address failed \n"));
         return;
@@ -500,7 +500,7 @@
         eepHeaderAddr += 36;  /* AR6003 customer data section offset is 37 */
 
         for (i=0; i<AR6003_CUST_DATA_SIZE+4; i+=4){
-            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&AR6003CustDataShadow[i])!= A_OK) {
+            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (u32 *)&AR6003CustDataShadow[i])!= 0) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
                 return ;
             }  
@@ -514,7 +514,7 @@
         eepHeaderAddr += 64;  /* AR6002 customer data sectioin offset is 64 */
 
         for (i=0; i<AR6002_CUST_DATA_SIZE; i+=4){
-            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (A_UINT32 *)&custDataAR6002[i])!= A_OK) {
+            if (BMIReadSOCRegister(hifDevice, eepHeaderAddr, (u32 *)&custDataAR6002[i])!= 0) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMIReadSOCRegister () failed \n"));
                 return ;
             }  
@@ -526,8 +526,7 @@
 }
 
 /* This is the function to call when need to use the cust data */
-A_UINT8 *
-ar6000_get_cust_data_buffer(A_UINT32 TargetType)
+u8 *ar6000_get_cust_data_buffer(u32 TargetType)
 {
     if (TargetType == TARGET_TYPE_AR6003)
         return custDataAR6003;
@@ -553,14 +552,14 @@
 #endif
 
 
-void ar6000_dump_target_assert_info(HIF_DEVICE *hifDevice, A_UINT32 TargetType)
+void ar6000_dump_target_assert_info(struct hif_device *hifDevice, u32 TargetType)
 {
-    A_UINT32 address;
-    A_UINT32 regDumpArea = 0;
-    A_STATUS status;
-    A_UINT32 regDumpValues[REGISTER_DUMP_LEN_MAX];
-    A_UINT32 regDumpCount = 0;
-    A_UINT32 i;
+    u32 address;
+    u32 regDumpArea = 0;
+    int status;
+    u32 regDumpValues[REGISTER_DUMP_LEN_MAX];
+    u32 regDumpCount = 0;
+    u32 i;
 
     do {
 
@@ -579,7 +578,7 @@
             /* read RAM location through diagnostic window */
         status = ar6000_ReadRegDiag(hifDevice, &address, &regDumpArea);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get ptr to register dump area \n"));
             break;
         }
@@ -596,10 +595,10 @@
             /* fetch register dump data */
         status = ar6000_ReadDataDiag(hifDevice,
                                      regDumpArea,
-                                     (A_UCHAR *)&regDumpValues[0],
-                                     regDumpCount * (sizeof(A_UINT32)));
+                                     (u8 *)&regDumpValues[0],
+                                     regDumpCount * (sizeof(u32)));
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("AR6K: Failed to get register dump \n"));
             break;
         }
@@ -619,26 +618,26 @@
 #endif
         }
 
-    } while (FALSE);
+    } while (false);
 
 }
 
 /* set HTC/Mbox operational parameters, this can only be called when the target is in the
  * BMI phase */
-A_STATUS ar6000_set_htc_params(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    MboxIsrYieldValue,
-                               A_UINT8     HtcControlBuffers)
+int ar6000_set_htc_params(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 MboxIsrYieldValue,
+                               u8 HtcControlBuffers)
 {
-    A_STATUS status;
-    A_UINT32 blocksizes[HTC_MAILBOX_NUM_MAX];
+    int status;
+    u32 blocksizes[HTC_MAILBOX_NUM_MAX];
 
     do {
             /* get the block sizes */
         status = HIFConfigureDevice(hifDevice, HIF_DEVICE_GET_MBOX_BLOCK_SIZE,
                                     blocksizes, sizeof(blocksizes));
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_LOG_ERR,("Failed to get block size info from HIF layer...\n"));
             break;
         }
@@ -649,16 +648,16 @@
 
         if (HtcControlBuffers != 0) {
                 /* set override for number of control buffers to use */
-            blocksizes[1] |=  ((A_UINT32)HtcControlBuffers) << 16;
+            blocksizes[1] |=  ((u32)HtcControlBuffers) << 16;
         }
 
             /* set the host interest area for the block size */
         status = BMIWriteMemory(hifDevice,
                                 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_io_block_sz),
-                                (A_UCHAR *)&blocksizes[1],
+                                (u8 *)&blocksizes[1],
                                 4);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for IO block size failed \n"));
             break;
         }
@@ -670,33 +669,33 @@
                 /* set the host interest area for the mbox ISR yield limit */
             status = BMIWriteMemory(hifDevice,
                                     HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_mbox_isr_yield_limit),
-                                    (A_UCHAR *)&MboxIsrYieldValue,
+                                    (u8 *)&MboxIsrYieldValue,
                                     4);
 
-            if (A_FAILED(status)) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_LOG_ERR,("BMIWriteMemory for yield limit failed \n"));
                 break;
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
 
-static A_STATUS prepare_ar6002(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
+static int prepare_ar6002(struct hif_device *hifDevice, u32 TargetVersion)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     /* placeholder */
 
     return status;
 }
 
-static A_STATUS prepare_ar6003(HIF_DEVICE *hifDevice, A_UINT32 TargetVersion)
+static int prepare_ar6003(struct hif_device *hifDevice, u32 TargetVersion)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     /* placeholder */
 
@@ -704,9 +703,9 @@
 }
 
 /* this function assumes the caller has already initialized the BMI APIs */
-A_STATUS ar6000_prepare_target(HIF_DEVICE *hifDevice,
-                               A_UINT32    TargetType,
-                               A_UINT32    TargetVersion)
+int ar6000_prepare_target(struct hif_device *hifDevice,
+                               u32 TargetType,
+                               u32 TargetVersion)
 {
     if (TargetType == TARGET_TYPE_AR6002) {
             /* do any preparations for AR6002 devices */
@@ -715,7 +714,7 @@
         return prepare_ar6003(hifDevice,TargetVersion);
     }
 
-    return A_OK;
+    return 0;
 }
 
 #if defined(CONFIG_AR6002_REV1_FORCE_HOST)
@@ -725,19 +724,19 @@
  * THIS IS FOR USE ONLY WITH AR6002 REV 1.x.
  * TBDXXX: Remove this function when REV 1.x is desupported.
  */
-A_STATUS
-ar6002_REV1_reset_force_host (HIF_DEVICE *hifDevice)
+int
+ar6002_REV1_reset_force_host (struct hif_device *hifDevice)
 {
-    A_INT32 i;
+    s32 i;
     struct forceROM_s {
-        A_UINT32 addr;
-        A_UINT32 data;
+        u32 addr;
+        u32 data;
     };
     struct forceROM_s *ForceROM;
-    A_INT32 szForceROM;
-    A_STATUS status = A_OK;
-    A_UINT32 address;
-    A_UINT32 data;
+    s32 szForceROM;
+    int status = 0;
+    u32 address;
+    u32 data;
 
     /* Force AR6002 REV1.x to recognize Host presence.
      *
@@ -771,7 +770,7 @@
 
     address = 0x004ed4b0; /* REV1 target software ID is stored here */
     status = ar6000_ReadRegDiag(hifDevice, &address, &data);
-    if (A_FAILED(status) || (data != AR6002_VERSION_REV1)) {
+    if (status || (data != AR6002_VERSION_REV1)) {
         return A_ERROR; /* Not AR6002 REV1 */
     }
 
@@ -783,7 +782,7 @@
     {
         if (ar6000_WriteRegDiag(hifDevice,
                                 &ForceROM[i].addr,
-                                &ForceROM[i].data) != A_OK)
+                                &ForceROM[i].data) != 0)
         {
             ATH_DEBUG_PRINTF (DBG_MISC_DRV, ATH_DEBUG_TRC, ("Cannot force Target to recognize Host!\n"));
             return A_ERROR;
@@ -792,17 +791,17 @@
 
     A_MDELAY(1000);
 
-    return A_OK;
+    return 0;
 }
 
 #endif /* CONFIG_AR6002_REV1_FORCE_HOST */
 
-void DebugDumpBytes(A_UCHAR *buffer, A_UINT16 length, char *pDescription)
+void DebugDumpBytes(u8 *buffer, u16 length, char *pDescription)
 {
-    A_CHAR stream[60];
-    A_CHAR byteOffsetStr[10];
-    A_UINT32 i;
-    A_UINT16 offset, count, byteOffset;
+    char stream[60];
+    char byteOffsetStr[10];
+    u32 i;
+    u16 offset, count, byteOffset;
 
     A_PRINTF("<---------Dumping %d Bytes : %s ------>\n", length, pDescription);
 
@@ -835,7 +834,7 @@
 void a_dump_module_debug_info(ATH_DEBUG_MODULE_DBG_INFO *pInfo)
 {
     int                         i;
-    ATH_DEBUG_MASK_DESCRIPTION *pDesc;
+    struct ath_debug_mask_description *pDesc;
 
     if (pInfo == NULL) {
         return;
@@ -868,7 +867,7 @@
 }
 
 
-static ATH_DEBUG_MODULE_DBG_INFO *FindModule(A_CHAR *module_name)
+static ATH_DEBUG_MODULE_DBG_INFO *FindModule(char *module_name)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
 
@@ -878,7 +877,7 @@
 
     while (pInfo != NULL) {
             /* TODO: need to use something other than strlen */
-        if (A_MEMCMP(pInfo->ModuleName,module_name,strlen(module_name)) == 0) {
+        if (memcmp(pInfo->ModuleName,module_name,strlen(module_name)) == 0) {
             break;
         }
         pInfo = pInfo->pNext;
@@ -909,7 +908,7 @@
     A_MUTEX_UNLOCK(&g_ModuleListLock);
 }
 
-void a_dump_module_debug_info_by_name(A_CHAR *module_name)
+void a_dump_module_debug_info_by_name(char *module_name)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = g_pModuleInfoHead;
 
@@ -917,7 +916,7 @@
         return;
     }
 
-    if (A_MEMCMP(module_name,"all",3) == 0) {
+    if (memcmp(module_name,"all",3) == 0) {
             /* dump all */
         while (pInfo != NULL) {
             a_dump_module_debug_info(pInfo);
@@ -934,7 +933,7 @@
 
 }
 
-A_STATUS a_get_module_mask(A_CHAR *module_name, A_UINT32 *pMask)
+int a_get_module_mask(char *module_name, u32 *pMask)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
 
@@ -943,10 +942,10 @@
     }
 
     *pMask = pInfo->CurrentMask;
-    return A_OK;
+    return 0;
 }
 
-A_STATUS a_set_module_mask(A_CHAR *module_name, A_UINT32 Mask)
+int a_set_module_mask(char *module_name, u32 Mask)
 {
     ATH_DEBUG_MODULE_DBG_INFO *pInfo = FindModule(module_name);
 
@@ -956,7 +955,7 @@
 
     pInfo->CurrentMask = Mask;
     A_PRINTF("Module %s,  new mask: 0x%8.8X \n",module_name,pInfo->CurrentMask);
-    return A_OK;
+    return 0;
 }
 
 
@@ -967,7 +966,7 @@
     }
     A_MUTEX_INIT(&g_ModuleListLock);
     g_pModuleInfoHead = NULL;
-    g_ModuleDebugInit = TRUE;
+    g_ModuleDebugInit = true;
     A_REGISTER_MODULE_DEBUG_INFO(misc);
 }
 
@@ -980,7 +979,7 @@
         return;
     }
 
-    g_ModuleDebugInit = FALSE;
+    g_ModuleDebugInit = false;
 
     A_MUTEX_LOCK(&g_ModuleListLock);
 
@@ -999,11 +998,11 @@
 }
 
     /* can only be called during bmi init stage */
-A_STATUS ar6000_set_hci_bridge_flags(HIF_DEVICE *hifDevice,
-                                     A_UINT32    TargetType,
-                                     A_UINT32    Flags)
+int ar6000_set_hci_bridge_flags(struct hif_device *hifDevice,
+                                     u32 TargetType,
+                                     u32 Flags)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     do {
 
@@ -1016,11 +1015,11 @@
             /* set hci bridge flags */
         status = BMIWriteMemory(hifDevice,
                                 HOST_INTEREST_ITEM_ADDRESS(TargetType, hi_hci_bridge_flags),
-                                (A_UCHAR *)&Flags,
+                                (u8 *)&Flags,
                                 4);
 
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/credit_dist.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/credit_dist.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/credit_dist.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/credit_dist.c	2011-05-19 00:06:34.000000000 -0400
@@ -41,15 +41,15 @@
 #define DATA_SVCS_USED 4
 #endif
 
-static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                                HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
+static void RedistributeCredits(struct common_credit_state_info *pCredInfo,
+                                struct htc_endpoint_credit_dist *pEPDistList);
 
-static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                        HTC_ENDPOINT_CREDIT_DIST *pEPDistList);
+static void SeekCredits(struct common_credit_state_info *pCredInfo,
+                        struct htc_endpoint_credit_dist *pEPDistList);
 
 /* reduce an ep's credits back to a set limit */
-static INLINE void ReduceCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                                HTC_ENDPOINT_CREDIT_DIST  *pEpDist,
+static INLINE void ReduceCredits(struct common_credit_state_info *pCredInfo,
+                                struct htc_endpoint_credit_dist  *pEpDist,
                                 int                       Limit)
 {
     int credits;
@@ -81,12 +81,12 @@
  * This function is called in the context of HTCStart() to setup initial (application-specific)
  * credit distributions */
 static void ar6000_credit_init(void                     *Context,
-                               HTC_ENDPOINT_CREDIT_DIST *pEPList,
+                               struct htc_endpoint_credit_dist *pEPList,
                                int                      TotalCredits)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
     int                      count;
-    COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
+    struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context;
 
     pCredInfo->CurrentFreeCredits = TotalCredits;
     pCredInfo->TotalAvailableCredits = TotalCredits;
@@ -136,7 +136,7 @@
 
     if (pCredInfo->CurrentFreeCredits <= 0) {
         AR_DEBUG_PRINTF(ATH_LOG_INF, ("Not enough credits (%d) to do credit distributions \n", TotalCredits));
-        A_ASSERT(FALSE);
+        A_ASSERT(false);
         return;
     }
 
@@ -175,11 +175,11 @@
  *
  */
 static void ar6000_credit_distribute(void                     *Context,
-                                     HTC_ENDPOINT_CREDIT_DIST *pEPDistList,
+                                     struct htc_endpoint_credit_dist *pEPDistList,
                                      HTC_CREDIT_DIST_REASON   Reason)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
-    COMMON_CREDIT_STATE_INFO *pCredInfo = (COMMON_CREDIT_STATE_INFO *)Context;
+    struct htc_endpoint_credit_dist *pCurEpDist;
+    struct common_credit_state_info *pCredInfo = (struct common_credit_state_info *)Context;
 
     switch (Reason) {
         case HTC_CREDIT_DIST_SEND_COMPLETE :
@@ -243,10 +243,10 @@
 }
 
 /* redistribute credits based on activity change */
-static void RedistributeCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                                HTC_ENDPOINT_CREDIT_DIST *pEPDistList)
+static void RedistributeCredits(struct common_credit_state_info *pCredInfo,
+                                struct htc_endpoint_credit_dist *pEPDistList)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist = pEPDistList;
+    struct htc_endpoint_credit_dist *pCurEpDist = pEPDistList;
 
         /* walk through the list and remove credits from inactive endpoints */
     while (pCurEpDist != NULL) {
@@ -283,10 +283,10 @@
 }
 
 /* HTC has an endpoint that needs credits, pEPDist is the endpoint in question */
-static void SeekCredits(COMMON_CREDIT_STATE_INFO *pCredInfo,
-                        HTC_ENDPOINT_CREDIT_DIST *pEPDist)
+static void SeekCredits(struct common_credit_state_info *pCredInfo,
+                        struct htc_endpoint_credit_dist *pEPDist)
 {
-    HTC_ENDPOINT_CREDIT_DIST *pCurEpDist;
+    struct htc_endpoint_credit_dist *pCurEpDist;
     int                      credits = 0;
     int                      need;
 
@@ -341,7 +341,7 @@
         credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
 
         if (credits >= pEPDist->TxCreditsSeek) {
-                /* we found some to fullfill the seek request */
+                /* we found some to fulfill the seek request */
             break;
         }
 
@@ -364,8 +364,8 @@
 
             if ((pCurEpDist->TxCreditsAssigned - need) >= pCurEpDist->TxCreditsMin) {
                     /* the current one has been allocated more than it's minimum and it
-                     * has enough credits assigned above it's minimum to fullfill our need
-                     * try to take away just enough to fullfill our need */
+                     * has enough credits assigned above it's minimum to fulfill our need
+                     * try to take away just enough to fulfill our need */
                 ReduceCredits(pCredInfo,
                               pCurEpDist,
                               pCurEpDist->TxCreditsAssigned - need);
@@ -382,7 +382,7 @@
             /* return what we can get */
         credits = min(pCredInfo->CurrentFreeCredits,pEPDist->TxCreditsSeek);
 
-    } while (FALSE);
+    } while (false);
 
         /* did we find some credits? */
     if (credits) {
@@ -393,11 +393,11 @@
 }
 
 /* initialize and setup credit distribution */
-A_STATUS ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, COMMON_CREDIT_STATE_INFO *pCredInfo)
+int ar6000_setup_credit_dist(HTC_HANDLE HTCHandle, struct common_credit_state_info *pCredInfo)
 {
     HTC_SERVICE_ID servicepriority[5];
 
-    A_MEMZERO(pCredInfo,sizeof(COMMON_CREDIT_STATE_INFO));
+    A_MEMZERO(pCredInfo,sizeof(struct common_credit_state_info));
 
     servicepriority[0] = WMI_CONTROL_SVC;  /* highest */
     servicepriority[1] = WMI_DATA_VO_SVC;
@@ -413,6 +413,6 @@
                              servicepriority,
                              5);
 
-    return A_OK;
+    return 0;
 }
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/miscdrv.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/miscdrv.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/miscdrv/miscdrv.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/miscdrv/miscdrv.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 #define HOST_INTEREST_ITEM_ADDRESS(target, item)    \
    AR6002_HOST_INTEREST_ITEM_ADDRESS(item)
 
-A_UINT32 ar6kRev2Array[][128]   = {
+u32 ar6kRev2Array[][128]   = {
                                     {0xFFFF, 0xFFFF},      // No Patches
                                };
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_android.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_android.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_android.c	2012-03-24 01:13:19.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_android.c	2012-03-24 03:33:49.000000000 -0400
@@ -25,14 +25,11 @@
 #include <linux/vmalloc.h>
 #include <linux/fs.h>
 
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
 #ifdef CONFIG_HAS_EARLYSUSPEND
 #include <linux/earlysuspend.h>
 #endif
 
-A_BOOL enable_mmc_host_detect_change = 0;
+bool enable_mmc_host_detect_change = false;
 static void ar6000_enable_mmchost_detect_change(int enable);
 
 
@@ -44,11 +41,6 @@
 extern struct net_device *ar6000_devices[];
 extern char ifname[];
 
-#ifdef CONFIG_HAS_WAKELOCK
-extern struct wake_lock ar6k_wow_wake_lock;
-struct wake_lock ar6k_init_wake_lock;
-#endif
-
 const char def_ifname[] = "wlan0";
 module_param_string(fwpath, fwpath, sizeof(fwpath), 0644);
 module_param(enablelogcat, uint, 0644);
@@ -59,7 +51,7 @@
 static struct early_suspend ar6k_early_suspend;
 #endif
 
-static A_STATUS (*ar6000_avail_ev_p)(void *, void *);
+static int (*ar6000_avail_ev_p)(void *, void *);
 
 #if defined(CONFIG_ANDROID_LOGGER) && (!defined(CONFIG_MMC_MSM))
 int logger_write(const enum logidx index,
@@ -128,9 +120,7 @@
     }
     set_fs(oldfs);
 out_free_message:
-    if (msg) {
-        kfree(msg);
-    }
+    kfree(msg);
     return ret;
 }
 #endif
@@ -163,7 +153,7 @@
     }
 }
 
-static int android_readwrite_file(const A_CHAR *filename, A_CHAR *rbuf, const A_CHAR *wbuf, size_t length)
+static int android_readwrite_file(const char *filename, char *rbuf, const char *wbuf, size_t length)
 {
     int ret = 0;
     struct file *filp = (struct file *)-ENOENT;
@@ -278,17 +268,11 @@
     }
 }
 
-static A_STATUS ar6000_android_avail_ev(void *context, void *hif_handle)
+static int ar6000_android_avail_ev(void *context, void *hif_handle)
 {
-    A_STATUS ret;    
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock(&ar6k_init_wake_lock);
-#endif
+    int ret;
     ar6000_enable_mmchost_detect_change(0);
     ret = ar6000_avail_ev_p(context, hif_handle);
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_unlock(&ar6k_init_wake_lock);
-#endif
     return ret;
 }
 
@@ -329,9 +313,6 @@
     bmienable = 1;
     if (ifname[0] == '\0')
         strcpy(ifname, def_ifname);
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_init(&ar6k_init_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_init");
-#endif
 #ifdef CONFIG_HAS_EARLYSUSPEND
     ar6k_early_suspend.suspend = android_early_suspend;
     ar6k_early_suspend.resume  = android_late_resume;
@@ -350,28 +331,25 @@
 #ifdef CONFIG_HAS_EARLYSUSPEND
     unregister_early_suspend(&ar6k_early_suspend);
 #endif
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_destroy(&ar6k_init_wake_lock);
-#endif
     ar6000_enable_mmchost_detect_change(1);
 }
 
 #ifdef CONFIG_PM
-void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
+void android_ar6k_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent)
 {
     if (
 #ifdef CONFIG_HAS_EARLYSUSPEND
         screen_is_off && 
 #endif 
             skb && ar->arConnected) {
-        A_BOOL needWake = FALSE;
+        bool needWake = false;
         if (isEvent) {
-            if (A_NETBUF_LEN(skb) >= sizeof(A_UINT16)) {
-                A_UINT16 cmd = *(const A_UINT16 *)A_NETBUF_DATA(skb);
+            if (A_NETBUF_LEN(skb) >= sizeof(u16)) {
+                u16 cmd = *(const u16 *)A_NETBUF_DATA(skb);
                 switch (cmd) {
                 case WMI_CONNECT_EVENTID:
                 case WMI_DISCONNECT_EVENTID:
-                    needWake = TRUE;
+                    needWake = true;
                     break;
                 default:
                     /* dont wake lock the system for other event */
@@ -386,7 +364,7 @@
                 case 0x888e: /* EAPOL */
                 case 0x88c7: /* RSN_PREAUTH */
                 case 0x88b4: /* WAPI */
-                     needWake = TRUE;
+                     needWake = true;
                      break;
                 case 0x0806: /* ARP is not important to hold wake lock */
                 default:
@@ -395,10 +373,7 @@
             }
         }
         if (needWake) {
-            /* keep host wake up if there is any event and packate comming in*/
-#ifdef CONFIG_HAS_WAKELOCK
-            wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
-#endif
+            /* keep host wake up if there is any event and packate coming in*/
             if (wowledon) {
                 char buf[32];
                 int len = sprintf(buf, "on");
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_drv.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_drv.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_drv.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_drv.c	2011-05-19 00:06:34.000000000 -0400
@@ -47,8 +47,8 @@
 #define LINUX_HACK_FUDGE_FACTOR 16
 #define BDATA_BDADDR_OFFSET     28
 
-A_UINT8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
-A_UINT8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
+u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+u8 null_mac[] = {0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
 
 #ifdef DEBUG
 
@@ -60,7 +60,7 @@
 #define  ATH_DEBUG_HTC_RAW       ATH_DEBUG_MAKE_MODULE_MASK(5)
 #define  ATH_DEBUG_HCI_BRIDGE    ATH_DEBUG_MAKE_MODULE_MASK(6)
 
-static ATH_DEBUG_MASK_DESCRIPTION driver_debug_desc[] = {
+static struct ath_debug_mask_description driver_debug_desc[] = {
     { ATH_DEBUG_DBG_LOG      , "Target Debug Logs"},
     { ATH_DEBUG_WLAN_CONNECT , "WLAN connect"},
     { ATH_DEBUG_WLAN_SCAN    , "WLAN scan"},
@@ -102,7 +102,7 @@
 #define APTC_LOWER_THROUGHPUT_THRESHOLD    2000 /* Kbps */
 
 typedef struct aptc_traffic_record {
-    A_BOOL timerScheduled;
+    bool timerScheduled;
     struct timeval samplingTS;
     unsigned long bytesReceived;
     unsigned long bytesTransmitted;
@@ -114,7 +114,7 @@
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 // callbacks registered by HCI transport driver
-HCI_TRANSPORT_CALLBACKS ar6kHciTransCallbacks = { NULL };
+struct hci_transport_callbacks ar6kHciTransCallbacks = { NULL };
 #endif
 
 unsigned int processDot11Hdr = 0;
@@ -123,7 +123,7 @@
 char ifname[IFNAMSIZ] = {0,};
 
 int wlaninitmode = WLAN_INIT_MODE_DEFAULT;
-unsigned int bypasswmi = 0;
+static bool bypasswmi;
 unsigned int debuglevel = 0;
 int tspecCompliance = ATHEROS_COMPLIANCE;
 unsigned int busspeedlow = 0;
@@ -165,7 +165,7 @@
 module_param_string(ifname, ifname, sizeof(ifname), 0644);
 module_param(wlaninitmode, int, 0644);
 module_param(bmienable, int, 0644);
-module_param(bypasswmi, uint, 0644);
+module_param(bypasswmi, bool, 0644);
 module_param(debuglevel, uint, 0644);
 module_param(tspecCompliance, int, 0644);
 module_param(onebitmode, uint, 0644);
@@ -207,7 +207,7 @@
 #define mboxnum &_mboxnum
 
 #ifdef DEBUG
-A_UINT32 g_dbg_flags = DBG_DEFAULTS;
+u32 g_dbg_flags = DBG_DEFAULTS;
 unsigned int debugflags = 0;
 int debugdriver = 0;
 unsigned int debughtc = 0;
@@ -254,22 +254,22 @@
 #endif /* BLOCK_TX_PATH_FLAG */
 
 typedef struct user_rssi_compensation_t {
-    A_UINT16         customerID;
+    u16 customerID;
     union {
-    A_UINT16         a_enable;
-    A_UINT16         bg_enable;
-    A_UINT16         enable;
+    u16 a_enable;
+    u16 bg_enable;
+    u16 enable;
     };
-    A_INT16          bg_param_a;
-    A_INT16          bg_param_b;
-    A_INT16          a_param_a;
-    A_INT16          a_param_b;
-    A_UINT32         reserved;
+    s16 bg_param_a;
+    s16 bg_param_b;
+    s16 a_param_a;
+    s16 a_param_b;
+    u32 reserved;
 } USER_RSSI_CPENSATION;
 
 static USER_RSSI_CPENSATION rssi_compensation_param;
 
-static A_INT16 rssi_compensation_table[96];
+static s16 rssi_compensation_table[96];
 
 int reconnect_flag = 0;
 static ar6k_pal_config_t ar6k_pal_config_g;
@@ -281,7 +281,7 @@
 int ar6000_init(struct net_device *dev);
 static int ar6000_open(struct net_device *dev);
 static int ar6000_close(struct net_device *dev);
-static void ar6000_init_control_info(AR_SOFTC_T *ar);
+static void ar6000_init_control_info(struct ar6_softc *ar);
 static int ar6000_data_tx(struct sk_buff *skb, struct net_device *dev);
 
 void ar6000_destroy(struct net_device *dev, unsigned int unregister);
@@ -292,7 +292,7 @@
 
 static void disconnect_timer_handler(unsigned long ptr);
 
-void read_rssi_compensation_param(AR_SOFTC_T *ar);
+void read_rssi_compensation_param(struct ar6_softc *ar);
 
     /* for android builds we call external APIs that handle firmware download and configuration */
 #ifdef ANDROID_ENV
@@ -305,33 +305,33 @@
 /*
  * HTC service connection handlers
  */
-static A_STATUS ar6000_avail_ev(void *context, void *hif_handle);
+static int ar6000_avail_ev(void *context, void *hif_handle);
 
-static A_STATUS ar6000_unavail_ev(void *context, void *hif_handle);
+static int ar6000_unavail_ev(void *context, void *hif_handle);
 
-A_STATUS ar6000_configure_target(AR_SOFTC_T *ar);
+int ar6000_configure_target(struct ar6_softc *ar);
 
-static void ar6000_target_failure(void *Instance, A_STATUS Status);
+static void ar6000_target_failure(void *Instance, int Status);
 
-static void ar6000_rx(void *Context, HTC_PACKET *pPacket);
+static void ar6000_rx(void *Context, struct htc_packet *pPacket);
 
 static void ar6000_rx_refill(void *Context,HTC_ENDPOINT_ID Endpoint);
 
-static void ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPackets);
+static void ar6000_tx_complete(void *Context, struct htc_packet_queue *pPackets);
 
-static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPacket);
+static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket);
 
 #ifdef ATH_AR6K_11N_SUPPORT
-static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, A_UINT16 num);
+static void ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num);
 #endif
 static void ar6000_deliver_frames_to_nw_stack(void * dev, void *osbuf);
 //static void ar6000_deliver_frames_to_bt_stack(void * dev, void *osbuf);
 
-static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length);
+static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length);
 
-static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count);
+static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count);
 
-static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar);
+static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar);
 
 static ssize_t
 ar6000_sysfs_bmi_read(struct file *fp, struct kobject *kobj,
@@ -343,18 +343,18 @@
                        struct bin_attribute *bin_attr,
                        char *buf, loff_t pos, size_t count);
 
-static A_STATUS
-ar6000_sysfs_bmi_init(AR_SOFTC_T *ar);
+static int
+ar6000_sysfs_bmi_init(struct ar6_softc *ar);
 
 /* HCI PAL callback function declarations */
-A_STATUS ar6k_setup_hci_pal(AR_SOFTC_T *ar);
-void  ar6k_cleanup_hci_pal(AR_SOFTC_T *ar);
+int ar6k_setup_hci_pal(struct ar6_softc *ar);
+void  ar6k_cleanup_hci_pal(struct ar6_softc *ar);
 
 static void
-ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar);
+ar6000_sysfs_bmi_deinit(struct ar6_softc *ar);
 
-A_STATUS
-ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode);
+int
+ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode);
 
 /*
  * Static variables
@@ -364,13 +364,13 @@
 static int is_netdev_registered;
 extern struct iw_handler_def ath_iw_handler_def;
 DECLARE_WAIT_QUEUE_HEAD(arEvent);
-static void ar6000_cookie_init(AR_SOFTC_T *ar);
-static void ar6000_cookie_cleanup(AR_SOFTC_T *ar);
-static void ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie);
-static struct ar_cookie *ar6000_alloc_cookie(AR_SOFTC_T *ar);
+static void ar6000_cookie_init(struct ar6_softc *ar);
+static void ar6000_cookie_cleanup(struct ar6_softc *ar);
+static void ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie);
+static struct ar_cookie *ar6000_alloc_cookie(struct ar6_softc *ar);
 
 #ifdef USER_KEYS
-static A_STATUS ar6000_reinstall_keys(AR_SOFTC_T *ar,A_UINT8 key_op_ctrl);
+static int ar6000_reinstall_keys(struct ar6_softc *ar,u8 key_op_ctrl);
 #endif
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
@@ -402,39 +402,38 @@
  */
 #define REPORT_DEBUG_LOGS_TO_APP
 
-A_STATUS
-ar6000_set_host_app_area(AR_SOFTC_T *ar)
+int
+ar6000_set_host_app_area(struct ar6_softc *ar)
 {
-    A_UINT32 address, data;
+    u32 address, data;
     struct host_app_area_s host_app_area;
 
     /* Fetch the address of the host_app_area_s instance in the host interest area */
     address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest));
-    if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != A_OK) {
+    if (ar6000_ReadRegDiag(ar->arHifDevice, &address, &data) != 0) {
         return A_ERROR;
     }
     address = TARG_VTOP(ar->arTargetType, data);
     host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
     if (ar6000_WriteDataDiag(ar->arHifDevice, address,
-                             (A_UCHAR *)&host_app_area,
-                             sizeof(struct host_app_area_s)) != A_OK)
+                             (u8 *)&host_app_area,
+                             sizeof(struct host_app_area_s)) != 0)
     {
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 
-A_UINT32
-dbglog_get_debug_hdr_ptr(AR_SOFTC_T *ar)
+u32 dbglog_get_debug_hdr_ptr(struct ar6_softc *ar)
 {
-    A_UINT32 param;
-    A_UINT32 address;
-    A_STATUS status;
+    u32 param;
+    u32 address;
+    int status;
 
     address = TARG_VTOP(ar->arTargetType, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbglog_hdr));
     if ((status = ar6000_ReadDataDiag(ar->arHifDevice, address,
-                                      (A_UCHAR *)&param, 4)) != A_OK)
+                                      (u8 *)&param, 4)) != 0)
     {
         param = 0;
     }
@@ -447,22 +446,21 @@
  * data stuctures over the diagnostic window.
  */
 void
-ar6000_dbglog_init_done(AR_SOFTC_T *ar)
+ar6000_dbglog_init_done(struct ar6_softc *ar)
 {
-    ar->dbglog_init_done = TRUE;
+    ar->dbglog_init_done = true;
 }
 
-A_UINT32
-dbglog_get_debug_fragment(A_INT8 *datap, A_UINT32 len, A_UINT32 limit)
+u32 dbglog_get_debug_fragment(s8 *datap, u32 len, u32 limit)
 {
-    A_INT32 *buffer;
-    A_UINT32 count;
-    A_UINT32 numargs;
-    A_UINT32 length;
-    A_UINT32 fraglen;
+    s32 *buffer;
+    u32 count;
+    u32 numargs;
+    u32 length;
+    u32 fraglen;
 
     count = fraglen = 0;
-    buffer = (A_INT32 *)datap;
+    buffer = (s32 *)datap;
     length = (limit >> 2);
 
     if (len <= limit) {
@@ -479,18 +477,18 @@
 }
 
 void
-dbglog_parse_debug_logs(A_INT8 *datap, A_UINT32 len)
+dbglog_parse_debug_logs(s8 *datap, u32 len)
 {
-    A_INT32 *buffer;
-    A_UINT32 count;
-    A_UINT32 timestamp;
-    A_UINT32 debugid;
-    A_UINT32 moduleid;
-    A_UINT32 numargs;
-    A_UINT32 length;
+    s32 *buffer;
+    u32 count;
+    u32 timestamp;
+    u32 debugid;
+    u32 moduleid;
+    u32 numargs;
+    u32 length;
 
     count = 0;
-    buffer = (A_INT32 *)datap;
+    buffer = (s32 *)datap;
     length = (len >> 2);
     while (count < length) {
         debugid = DBGLOG_GET_DBGID(buffer[count]);
@@ -520,14 +518,14 @@
 }
 
 int
-ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar)
+ar6000_dbglog_get_debug_logs(struct ar6_softc *ar)
 {
-    A_UINT32 data[8]; /* Should be able to accomodate struct dbglog_buf_s */
-    A_UINT32 address;
-    A_UINT32 length;
-    A_UINT32 dropped;
-    A_UINT32 firstbuf;
-    A_UINT32 debug_hdr_ptr;
+    u32 data[8]; /* Should be able to accommodate struct dbglog_buf_s */
+    u32 address;
+    u32 length;
+    u32 dropped;
+    u32 firstbuf;
+    u32 debug_hdr_ptr;
 
     if (!ar->dbglog_init_done) return A_ERROR;
 
@@ -540,7 +538,7 @@
     }
 
         /* block out others */
-    ar->dbgLogFetchInProgress = TRUE;
+    ar->dbgLogFetchInProgress = true;
 
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
@@ -552,13 +550,13 @@
         address = TARG_VTOP(ar->arTargetType, debug_hdr_ptr);
         length = 4 /* sizeof(dbuf) */ + 4 /* sizeof(dropped) */;
         A_MEMZERO(data, sizeof(data));
-        ar6000_ReadDataDiag(ar->arHifDevice, address, (A_UCHAR *)data, length);
+        ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)data, length);
         address = TARG_VTOP(ar->arTargetType, data[0] /* dbuf */);
         firstbuf = address;
         dropped = data[1]; /* dropped */
         length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
         A_MEMZERO(data, sizeof(data));
-        ar6000_ReadDataDiag(ar->arHifDevice, address, (A_UCHAR *)&data, length);
+        ar6000_ReadDataDiag(ar->arHifDevice, address, (u8 *)&data, length);
 
         do {
             address = TARG_VTOP(ar->arTargetType, data[1] /* buffer*/);
@@ -568,12 +566,12 @@
                 if (ar->log_cnt > (DBGLOG_HOST_LOG_BUFFER_SIZE - length)) {
                     ar->log_cnt = 0;
                 }
-                if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
-                                    (A_UCHAR *)&ar->log_buffer[ar->log_cnt], length))
+                if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
+                                    (u8 *)&ar->log_buffer[ar->log_cnt], length))
                 {
                     break;
                 }
-                ar6000_dbglog_event(ar, dropped, (A_INT8*)&ar->log_buffer[ar->log_cnt], length);
+                ar6000_dbglog_event(ar, dropped, (s8 *)&ar->log_buffer[ar->log_cnt], length);
                 ar->log_cnt += length;
             } else {
                 AR_DEBUG_PRINTF(ATH_DEBUG_DBG_LOG,("Length: %d (Total size: %d)\n",
@@ -583,8 +581,8 @@
             address = TARG_VTOP(ar->arTargetType, data[0] /* next */);
             length = 4 /* sizeof(next) */ + 4 /* sizeof(buffer) */ + 4 /* sizeof(bufsize) */ + 4 /* sizeof(length) */ + 4 /* sizeof(count) */ + 4 /* sizeof(free) */;
             A_MEMZERO(data, sizeof(data));
-            if(A_OK != ar6000_ReadDataDiag(ar->arHifDevice, address,
-                                (A_UCHAR *)&data, length))
+            if(0 != ar6000_ReadDataDiag(ar->arHifDevice, address,
+                                (u8 *)&data, length))
             {
                 break;
             }
@@ -592,14 +590,14 @@
         } while (address != firstbuf);
     }
 
-    ar->dbgLogFetchInProgress = FALSE;
+    ar->dbgLogFetchInProgress = false;
 
-    return A_OK;
+    return 0;
 }
 
 void
-ar6000_dbglog_event(AR_SOFTC_T *ar, A_UINT32 dropped,
-                    A_INT8 *buffer, A_UINT32 length)
+ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
+                    s8 *buffer, u32 length)
 {
 #ifdef REPORT_DEBUG_LOGS_TO_APP
     #define MAX_WIRELESS_EVENT_SIZE 252
@@ -608,13 +606,13 @@
      * There seems to be a limitation on the length of message that could be
      * transmitted to the user app via this mechanism.
      */
-    A_UINT32 send, sent;
+    u32 send, sent;
 
     sent = 0;
     send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
                                      MAX_WIRELESS_EVENT_SIZE);
     while (send) {
-        ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, (A_UINT8*)&buffer[sent], send);
+        ar6000_send_event_to_app(ar, WMIX_DBGLOG_EVENTID, (u8 *)&buffer[sent], send);
         sent += send;
         send = dbglog_get_debug_fragment(&buffer[sent], length - sent,
                                          MAX_WIRELESS_EVENT_SIZE);
@@ -624,7 +622,7 @@
                     dropped, length));
 
     /* Interpret the debug logs */
-    dbglog_parse_debug_logs((A_INT8*)buffer, length);
+    dbglog_parse_debug_logs((s8 *)buffer, length);
 #endif /* REPORT_DEBUG_LOGS_TO_APP */
 }
 
@@ -633,7 +631,7 @@
 ar6000_init_module(void)
 {
     static int probed = 0;
-    A_STATUS status;
+    int status;
     OSDRV_CALLBACKS osdrvCallbacks;
 
     a_module_debug_support_init();
@@ -694,7 +692,7 @@
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
     status = HIFInit(&osdrvCallbacks);
-    if(status != A_OK)
+    if (status)
         return -ENODEV;
 
     return 0;
@@ -738,12 +736,12 @@
 void
 aptcTimerHandler(unsigned long arg)
 {
-    A_UINT32 numbytes;
-    A_UINT32 throughput;
-    AR_SOFTC_T *ar;
-    A_STATUS status;
+    u32 numbytes;
+    u32 throughput;
+    struct ar6_softc *ar;
+    int status;
 
-    ar = (AR_SOFTC_T *)arg;
+    ar = (struct ar6_softc *)arg;
     A_ASSERT(ar != NULL);
     A_ASSERT(!timer_pending(&aptcTimer));
 
@@ -757,12 +755,12 @@
     throughput = ((numbytes * 8)/APTC_TRAFFIC_SAMPLING_INTERVAL); /* Kbps */
     if (throughput < APTC_LOWER_THROUGHPUT_THRESHOLD) {
         /* Enable Sleep and delete the timer */
-        A_ASSERT(ar->arWmiReady == TRUE);
+        A_ASSERT(ar->arWmiReady == true);
         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         status = wmi_powermode_cmd(ar->arWmi, REC_POWER);
         AR6000_SPIN_LOCK(&ar->arLock, 0);
-        A_ASSERT(status == A_OK);
-        aptcTR.timerScheduled = FALSE;
+        A_ASSERT(status == 0);
+        aptcTR.timerScheduled = false;
     } else {
         A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
     }
@@ -773,7 +771,7 @@
 
 #ifdef ATH_AR6K_11N_SUPPORT
 static void
-ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, A_UINT16 num)
+ar6000_alloc_netbufs(A_NETBUF_QUEUE_T *q, u16 num)
 {
     void * osbuf;
 
@@ -804,12 +802,12 @@
                       char *buf, loff_t pos, size_t count)
 {
     int index;
-    AR_SOFTC_T *ar;
-    HIF_DEVICE_OS_DEVICE_INFO   *osDevInfo;
+    struct ar6_softc *ar;
+    struct hif_device_os_device_info   *osDevInfo;
 
-    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (A_UINT32)count));
+    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Read %d bytes\n", (u32)count));
     for (index=0; index < MAX_AR6000; index++) {
-        ar = (AR_SOFTC_T *)ar6k_priv(ar6000_devices[index]);
+        ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
         osDevInfo = &ar->osDevInfo;
         if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
             break;
@@ -818,7 +816,7 @@
 
     if (index == MAX_AR6000) return 0;
 
-    if ((BMIRawRead(ar->arHifDevice, (A_UCHAR*)buf, count, TRUE)) != A_OK) {
+    if ((BMIRawRead(ar->arHifDevice, (u8*)buf, count, true)) != 0) {
         return 0;
     }
 
@@ -831,12 +829,12 @@
                        char *buf, loff_t pos, size_t count)
 {
     int index;
-    AR_SOFTC_T *ar;
-    HIF_DEVICE_OS_DEVICE_INFO   *osDevInfo;
+    struct ar6_softc *ar;
+    struct hif_device_os_device_info   *osDevInfo;
 
-    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (A_UINT32)count));
+    AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Write %d bytes\n", (u32)count));
     for (index=0; index < MAX_AR6000; index++) {
-        ar = (AR_SOFTC_T *)ar6k_priv(ar6000_devices[index]);
+        ar = (struct ar6_softc *)ar6k_priv(ar6000_devices[index]);
         osDevInfo = &ar->osDevInfo;
         if (kobj == (&(((struct device *)osDevInfo->pOSDevice)->kobj))) {
             break;
@@ -845,28 +843,28 @@
 
     if (index == MAX_AR6000) return 0;
 
-    if ((BMIRawWrite(ar->arHifDevice, (A_UCHAR*)buf, count)) != A_OK) {
+    if ((BMIRawWrite(ar->arHifDevice, (u8*)buf, count)) != 0) {
         return 0;
     }
 
     return count;
 }
 
-static A_STATUS
-ar6000_sysfs_bmi_init(AR_SOFTC_T *ar)
+static int
+ar6000_sysfs_bmi_init(struct ar6_softc *ar)
 {
-    A_STATUS status;
+    int status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Creating sysfs entry\n"));
-    A_MEMZERO(&ar->osDevInfo, sizeof(HIF_DEVICE_OS_DEVICE_INFO));
+    A_MEMZERO(&ar->osDevInfo, sizeof(struct hif_device_os_device_info));
 
     /* Get the underlying OS device */
     status = HIFConfigureDevice(ar->arHifDevice,
                                 HIF_DEVICE_GET_OS_DEVICE,
                                 &ar->osDevInfo,
-                                sizeof(HIF_DEVICE_OS_DEVICE_INFO));
+                                sizeof(struct hif_device_os_device_info));
 
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI: Failed to get OS device info from HIF\n"));
         return A_ERROR;
     }
@@ -878,11 +876,11 @@
         return A_ERROR;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static void
-ar6000_sysfs_bmi_deinit(AR_SOFTC_T *ar)
+ar6000_sysfs_bmi_deinit(struct ar6_softc *ar)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Deleting sysfs entry\n"));
 
@@ -890,7 +888,7 @@
 }
 
 #define bmifn(fn) do { \
-    if ((fn) < A_OK) { \
+    if ((fn) < 0) { \
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__)); \
         return A_ERROR; \
     } \
@@ -902,28 +900,28 @@
 #define AR6002_MAC_ADDRESS_OFFSET     0x0A
 #define AR6003_MAC_ADDRESS_OFFSET     0x16
 static
-void calculate_crc(A_UINT32 TargetType, A_UCHAR *eeprom_data)
+void calculate_crc(u32 TargetType, u8 *eeprom_data)
 {
-    A_UINT16        *ptr_crc;
-    A_UINT16        *ptr16_eeprom;
-    A_UINT16        checksum;
-    A_UINT32        i;
-    A_UINT32        eeprom_size;
+    u16 *ptr_crc;
+    u16 *ptr16_eeprom;
+    u16 checksum;
+    u32 i;
+    u32 eeprom_size;
 
     if (TargetType == TARGET_TYPE_AR6001)
     {
         eeprom_size = 512;
-        ptr_crc = (A_UINT16 *)eeprom_data;
+        ptr_crc = (u16 *)eeprom_data;
     }
     else if (TargetType == TARGET_TYPE_AR6003)
     {
         eeprom_size = 1024;
-        ptr_crc = (A_UINT16 *)((A_UCHAR *)eeprom_data + 0x04);
+        ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
     }
     else
     {
         eeprom_size = 768;
-        ptr_crc = (A_UINT16 *)((A_UCHAR *)eeprom_data + 0x04);
+        ptr_crc = (u16 *)((u8 *)eeprom_data + 0x04);
     }
 
 
@@ -932,7 +930,7 @@
 
     // Recalculate new CRC
     checksum = 0;
-    ptr16_eeprom = (A_UINT16 *)eeprom_data;
+    ptr16_eeprom = (u16 *)eeprom_data;
     for (i = 0;i < eeprom_size; i += 2)
     {
         checksum = checksum ^ (*ptr16_eeprom);
@@ -943,17 +941,17 @@
 }
 
 static void 
-ar6000_softmac_update(AR_SOFTC_T *ar, A_UCHAR *eeprom_data, size_t size)
+ar6000_softmac_update(struct ar6_softc *ar, u8 *eeprom_data, size_t size)
 {
     const char *source = "random generated";
     const struct firmware *softmac_entry;
-    A_UCHAR *ptr_mac;
+    u8 *ptr_mac;
     switch (ar->arTargetType) {
     case TARGET_TYPE_AR6002:
-        ptr_mac = (A_UINT8 *)((A_UCHAR *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET);
+        ptr_mac = (u8 *)((u8 *)eeprom_data + AR6002_MAC_ADDRESS_OFFSET);
         break;
     case TARGET_TYPE_AR6003:
-        ptr_mac = (A_UINT8 *)((A_UCHAR *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET);
+        ptr_mac = (u8 *)((u8 *)eeprom_data + AR6003_MAC_ADDRESS_OFFSET);
         break;
     default:
 	AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Invalid Target Type\n"));
@@ -970,7 +968,7 @@
     ptr_mac[5] = random32() & 0xff; 
     if ((A_REQUEST_FIRMWARE(&softmac_entry, "softmac", ((struct device *)ar->osDevInfo.pOSDevice))) == 0)
     {
-        A_CHAR *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1);
+        char *macbuf = A_MALLOC_NOWAIT(softmac_entry->size+1);
         if (macbuf) {            
             unsigned int softmac[6];
             memcpy(macbuf, softmac_entry->data, softmac_entry->size);
@@ -993,13 +991,13 @@
 }
 #endif /* SOFTMAC_FILE_USED */
 
-static A_STATUS
-ar6000_transfer_bin_file(AR_SOFTC_T *ar, AR6K_BIN_FILE file, A_UINT32 address, A_BOOL compressed)
+static int
+ar6000_transfer_bin_file(struct ar6_softc *ar, AR6K_BIN_FILE file, u32 address, bool compressed)
 {
-    A_STATUS status;
+    int status;
     const char *filename;
     const struct firmware *fw_entry;
-    A_UINT32 fw_entry_size;
+    u32 fw_entry_size;
 
     switch (file) {
         case AR6K_OTP_FILE:
@@ -1024,7 +1022,7 @@
             }
             
             if (eppingtest) {
-                bypasswmi = TRUE;    
+                bypasswmi = true;
                 if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
                     filename = AR6003_REV1_EPPING_FIRMWARE_FILE;
                 } else if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
@@ -1034,7 +1032,7 @@
                         ar->arVersion.target_ver));
                     return A_ERROR;
                 }
-                compressed = 0;
+                compressed = false;
             }
             
 #ifdef CONFIG_HOST_TCMD_SUPPORT
@@ -1047,7 +1045,7 @@
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
                     return A_ERROR;
                 }
-                compressed = 0;
+                compressed = false;
             }
 #endif 
 #ifdef HTC_RAW_INTERFACE
@@ -1060,7 +1058,7 @@
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Unknown firmware revision: %d\n", ar->arVersion.target_ver));
                     return A_ERROR;
                 }
-                compressed = 0;                
+                compressed = false;
             }
 #endif 
             break;
@@ -1099,7 +1097,7 @@
 
 #ifdef SOFTMAC_FILE_USED
     if (file==AR6K_BOARD_DATA_FILE && fw_entry->data) {
-        ar6000_softmac_update(ar, (A_UCHAR *)fw_entry->data, fw_entry->size);
+        ar6000_softmac_update(ar, (u8 *)fw_entry->data, fw_entry->size);
     }
 #endif 
 
@@ -1108,9 +1106,9 @@
 
     /* Load extended board data for AR6003 */
     if ((file==AR6K_BOARD_DATA_FILE) && (fw_entry->data)) {
-        A_UINT32 board_ext_address;
-        A_UINT32 board_ext_data_size;
-        A_UINT32 board_data_size;
+        u32 board_ext_address;
+        u32 board_ext_data_size;
+        u32 board_data_size;
 
         board_ext_data_size = (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_BOARD_EXT_DATA_SZ : \
                                (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_EXT_DATA_SZ : 0));
@@ -1119,16 +1117,16 @@
                           (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_BOARD_DATA_SZ : 0));
         
         /* Determine where in Target RAM to write Board Data */
-        bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (A_UCHAR *)&board_ext_address, 4));
+        bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data), (u8 *)&board_ext_address, 4));
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board extended Data download address: 0x%x\n", board_ext_address));
 
         /* check whether the target has allocated memory for extended board data and file contains extended board data */
         if ((board_ext_address) && (fw_entry->size == (board_data_size + board_ext_data_size))) {
-            A_UINT32 param;
+            u32 param;
 
-            status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (A_UCHAR *)(fw_entry->data + board_data_size), board_ext_data_size);
+            status = BMIWriteMemory(ar->arHifDevice, board_ext_address, (u8 *)(fw_entry->data + board_data_size), board_ext_data_size);
 
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
                 A_RELEASE_FIRMWARE(fw_entry);
                 return A_ERROR;
@@ -1136,42 +1134,42 @@
 
             /* Record the fact that extended board Data IS initialized */
             param = 1;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_initialized), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data_initialized), (u8 *)&param, 4));
         }
         fw_entry_size = board_data_size;
     }
 
     if (compressed) {
-        status = BMIFastDownload(ar->arHifDevice, address, (A_UCHAR *)fw_entry->data, fw_entry_size);
+        status = BMIFastDownload(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
     } else {
-        status = BMIWriteMemory(ar->arHifDevice, address, (A_UCHAR *)fw_entry->data, fw_entry_size);
+        status = BMIWriteMemory(ar->arHifDevice, address, (u8 *)fw_entry->data, fw_entry_size);
     }
 
-    if (status != A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("BMI operation failed: %d\n", __LINE__));
         A_RELEASE_FIRMWARE(fw_entry);
         return A_ERROR;
     }
     A_RELEASE_FIRMWARE(fw_entry);
-    return A_OK;
+    return 0;
 }
 #endif /* INIT_MODE_DRV_ENABLED */
 
-A_STATUS
-ar6000_update_bdaddr(AR_SOFTC_T *ar)
+int
+ar6000_update_bdaddr(struct ar6_softc *ar)
 {
 
         if (setupbtdev != 0) {
-            A_UINT32 address;
+            u32 address;
 
            if (BMIReadMemory(ar->arHifDevice,
-           	HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (A_UCHAR *)&address, 4) != A_OK)
+		HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4) != 0)
            {
     	      	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for hi_board_data failed\n"));
            	return A_ERROR;
            }
 
-           if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (A_UCHAR *)ar->bdaddr, 6) != A_OK)
+           if (BMIReadMemory(ar->arHifDevice, address + BDATA_BDADDR_OFFSET, (u8 *)ar->bdaddr, 6) != 0)
            {
     	    	AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for BD address failed\n"));
            	return A_ERROR;
@@ -1181,16 +1179,16 @@
 								ar->bdaddr[4], ar->bdaddr[5]));
         }
 
-return A_OK;
+return 0;
 }
 
-A_STATUS
-ar6000_sysfs_bmi_get_config(AR_SOFTC_T *ar, A_UINT32 mode)
+int
+ar6000_sysfs_bmi_get_config(struct ar6_softc *ar, u32 mode)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("BMI: Requesting device specific configuration\n"));
 
     if (mode == WLAN_INIT_MODE_UDEV) {
-        A_CHAR version[16];
+        char version[16];
         const struct firmware *fw_entry;
 
         /* Get config using udev through a script in user space */
@@ -1205,8 +1203,8 @@
 #ifdef INIT_MODE_DRV_ENABLED
     } else {
         /* The config is contained within the driver itself */
-        A_STATUS status;
-        A_UINT32 param, options, sleep, address;
+        int status;
+        u32 param, options, sleep, address;
 
         /* Temporarily disable system sleep */
         address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
@@ -1236,7 +1234,7 @@
 
         param = 0;
         if (ar->arTargetType == TARGET_TYPE_AR6002) {
-            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (A_UCHAR *)&param, 4));
+            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)&param, 4));
         }
 
         /* LPO_CAL.ENABLE = 1 if no external clk is detected */
@@ -1269,7 +1267,7 @@
         if (ar->arTargetType == TARGET_TYPE_AR6003) {
             /* hi_ext_clk_detected = 0 */
             param = 0;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_ext_clk_detected), (u8 *)&param, 4));
 
             /* CLOCK_CONTROL &= ~LF_CLK32 */
             address = RTC_BASE_ADDRESS + CLOCK_CONTROL_ADDRESS;
@@ -1282,22 +1280,22 @@
         /* Transfer Board Data from Target EEPROM to Target RAM */
         if (ar->arTargetType == TARGET_TYPE_AR6003) {
             /* Determine where in Target RAM to write Board Data */
-            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (A_UCHAR *)&address, 4));
+            bmifn(BMIReadMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data), (u8 *)&address, 4));
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("Board Data download address: 0x%x\n", address));
 
             /* Write EEPROM data to Target RAM */
-            if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, FALSE)) != A_OK) {
+            if ((ar6000_transfer_bin_file(ar, AR6K_BOARD_DATA_FILE, address, false)) != 0) {
                 return A_ERROR;
             }
 
             /* Record the fact that Board Data IS initialized */
             param = 1;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_data_initialized), (u8 *)&param, 4));
 
             /* Transfer One time Programmable data */
             AR6K_DATA_DOWNLOAD_ADDRESS(address, ar->arVersion.target_ver);
-            status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, TRUE);
-            if (status == A_OK) {
+            status = ar6000_transfer_bin_file(ar, AR6K_OTP_FILE, address, true);
+            if (status == 0) {
                 /* Execute the OTP code */
                 param = 0;
                 AR6K_APP_START_OVERRIDE_ADDRESS(address, ar->arVersion.target_ver);
@@ -1312,7 +1310,7 @@
 
         /* Download Target firmware */
         AR6K_DATA_DOWNLOAD_ADDRESS(address, ar->arVersion.target_ver);
-        if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, TRUE)) != A_OK) {
+        if ((ar6000_transfer_bin_file(ar, AR6K_FIRMWARE_FILE, address, true)) != 0) {
             return A_ERROR;
         }
 
@@ -1322,12 +1320,12 @@
 
         /* Apply the patches */
         AR6K_PATCH_DOWNLOAD_ADDRESS(address, ar->arVersion.target_ver);
-        if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, address, FALSE)) != A_OK) {
+        if ((ar6000_transfer_bin_file(ar, AR6K_PATCH_FILE, address, false)) != 0) {
             return A_ERROR;
         }
 
         param = address;
-        bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), (A_UCHAR *)&param, 4));
+        bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dset_list_head), (u8 *)&param, 4));
 
         if (ar->arTargetType == TARGET_TYPE_AR6003) {
             if (ar->arVersion.target_ver == AR6003_REV1_VERSION) {
@@ -1337,7 +1335,7 @@
                 /* Reserve 6.5K of RAM */
                 param = 6656;
             }
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_end_RAM_reserve_sz), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_end_RAM_reserve_sz), (u8 *)&param, 4));
         }
 
         /* Restore system sleep */
@@ -1354,7 +1352,7 @@
 #define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
 #endif
             param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_dbg_uart_txpin), (u8 *)&param, 4));
 
 #if (CONFIG_AR600x_DEBUG_UART_TX_PIN == 23)
             {
@@ -1369,7 +1367,7 @@
 #ifdef ATH6KL_CONFIG_GPIO_BT_RESET
 #define CONFIG_AR600x_BT_RESET_PIN	0x16
             param = CONFIG_AR600x_BT_RESET_PIN;
-            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (A_UCHAR *)&param, 4));
+            bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_support_pins), (u8 *)&param, 4));
 #endif /* ATH6KL_CONFIG_GPIO_BT_RESET */
 
             /* Configure UART flow control polarity */
@@ -1380,7 +1378,7 @@
 #if (CONFIG_ATH6KL_BT_UART_FC_POLARITY == 1)
             if (ar->arVersion.target_ver == AR6003_REV2_VERSION) {
                 param = ((CONFIG_ATH6KL_BT_UART_FC_POLARITY << 1) & 0x2);
-                bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (A_UCHAR *)&param, 4));
+                bmifn(BMIWriteMemory(ar->arHifDevice, HOST_INTEREST_ITEM_ADDRESS(ar, hi_hci_uart_pwr_mgmt_params), (u8 *)&param, 4));
             }
 #endif /* CONFIG_ATH6KL_BT_UART_FC_POLARITY */
         }
@@ -1396,19 +1394,19 @@
 #endif /* INIT_MODE_DRV_ENABLED */
     }
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-ar6000_configure_target(AR_SOFTC_T *ar)
+int
+ar6000_configure_target(struct ar6_softc *ar)
 {
-    A_UINT32 param;
+    u32 param;
     if (enableuartprint) {
         param = 1;
         if (BMIWriteMemory(ar->arHifDevice,
                            HOST_INTEREST_ITEM_ADDRESS(ar, hi_serial_enable),
-                           (A_UCHAR *)&param,
-                           4)!= A_OK)
+                           (u8 *)&param,
+                           4)!= 0)
         {
              AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enableuartprint failed \n"));
              return A_ERROR;
@@ -1420,8 +1418,8 @@
     param = HTC_PROTOCOL_VERSION;
     if (BMIWriteMemory(ar->arHifDevice,
                        HOST_INTEREST_ITEM_ADDRESS(ar, hi_app_host_interest),
-                       (A_UCHAR *)&param,
-                       4)!= A_OK)
+                       (u8 *)&param,
+                       4)!= 0)
     {
          AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for htc version failed \n"));
          return A_ERROR;
@@ -1435,12 +1433,12 @@
     }
 #endif
     if (enabletimerwar) {
-        A_UINT32 param;
+        u32 param;
 
         if (BMIReadMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4)!= A_OK)
+            (u8 *)&param,
+            4)!= 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for enabletimerwar failed \n"));
             return A_ERROR;
@@ -1450,8 +1448,8 @@
 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for enabletimerwar failed \n"));
             return A_ERROR;
@@ -1461,12 +1459,12 @@
 
     /* set the firmware mode to STA/IBSS/AP */
     {
-        A_UINT32 param;
+        u32 param;
 
         if (BMIReadMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4)!= A_OK)
+            (u8 *)&param,
+            4)!= 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for setting fwmode failed \n"));
             return A_ERROR;
@@ -1476,8 +1474,8 @@
 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for setting fwmode failed \n"));
             return A_ERROR;
@@ -1487,12 +1485,12 @@
 
 #ifdef ATH6KL_DISABLE_TARGET_DBGLOGS
     {
-        A_UINT32 param;
+        u32 param;
 
         if (BMIReadMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4)!= A_OK)
+            (u8 *)&param,
+            4)!= 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIReadMemory for disabling debug logs failed\n"));
             return A_ERROR;
@@ -1502,8 +1500,8 @@
 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_option_flag),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for HI_OPTION_DISABLE_DBGLOG\n"));
             return A_ERROR;
@@ -1524,8 +1522,8 @@
         param = AR6003_BOARD_EXT_DATA_ADDRESS; 
         if (BMIWriteMemory(ar->arHifDevice,
             HOST_INTEREST_ITEM_ADDRESS(ar, hi_board_ext_data),
-            (A_UCHAR *)&param,
-            4) != A_OK)
+            (u8 *)&param,
+            4) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BMIWriteMemory for hi_board_ext_data failed \n"));
             return A_ERROR;
@@ -1536,22 +1534,20 @@
         /* since BMIInit is called in the driver layer, we have to set the block
          * size here for the target */
 
-    if (A_FAILED(ar6000_set_htc_params(ar->arHifDevice,
-                                       ar->arTargetType,
-                                       mbox_yield_limit,
-                                       0 /* use default number of control buffers */
-                                       ))) {
+    if (ar6000_set_htc_params(ar->arHifDevice, ar->arTargetType,
+			      mbox_yield_limit, 0)) {
+				/* use default number of control buffers */
         return A_ERROR;
     }
 
     if (setupbtdev != 0) {
-        if (A_FAILED(ar6000_set_hci_bridge_flags(ar->arHifDevice,
-                                                 ar->arTargetType,
-                                                 setupbtdev))) {
+        if (ar6000_set_hci_bridge_flags(ar->arHifDevice,
+					ar->arTargetType,
+					setupbtdev)) {
             return A_ERROR;
         }
     }
-    return A_OK;
+    return 0;
 }
 
 static void
@@ -1595,19 +1591,27 @@
 /*
  * HTC Event handlers
  */
-static A_STATUS
+static int
 ar6000_avail_ev(void *context, void *hif_handle)
 {
     int i;
     struct net_device *dev;
     void *ar_netif;
-    AR_SOFTC_T *ar;
+    struct ar6_softc *ar;
     int device_index = 0;
-    HTC_INIT_INFO  htcInfo;
+    struct htc_init_info  htcInfo;
 #ifdef ATH6K_CONFIG_CFG80211
     struct wireless_dev *wdev;
 #endif /* ATH6K_CONFIG_CFG80211 */
-    A_STATUS init_status = A_OK;
+    int init_status = 0;
+    struct hif_device_os_device_info osDevInfo;
+
+    memset(&osDevInfo, 0, sizeof(osDevInfo));
+    if (HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE,
+        &osDevInfo, sizeof(osDevInfo))) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s: Failed to get OS device instance\n", __func__));
+        return A_ERROR;
+    }
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("ar6000_available\n"));
 
@@ -1627,14 +1631,14 @@
     device_index = i;
 
 #ifdef ATH6K_CONFIG_CFG80211
-    wdev = ar6k_cfg80211_init(NULL);
+    wdev = ar6k_cfg80211_init(osDevInfo.pOSDevice);
     if (IS_ERR(wdev)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: ar6k_cfg80211_init failed\n", __func__));
         return A_ERROR;
     }
     ar_netif = wdev_priv(wdev);
 #else
-    dev = alloc_etherdev(sizeof(AR_SOFTC_T));
+    dev = alloc_etherdev(sizeof(struct ar6_softc));
     if (dev == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_available: can't alloc etherdev\n"));
         return A_ERROR;
@@ -1648,8 +1652,8 @@
         return A_ERROR;
     }
 
-    A_MEMZERO(ar_netif, sizeof(AR_SOFTC_T));
-    ar = (AR_SOFTC_T *)ar_netif;
+    A_MEMZERO(ar_netif, sizeof(struct ar6_softc));
+    ar = (struct ar6_softc *)ar_netif;
 
 #ifdef ATH6K_CONFIG_CFG80211
     ar->wdev = wdev;
@@ -1666,18 +1670,14 @@
     SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
     wdev->netdev = dev;
     ar->arNetworkType = INFRA_NETWORK;
+    ar->smeState = SME_DISCONNECTED;
 #endif /* ATH6K_CONFIG_CFG80211 */
 
     init_netdev(dev, ifname);
 
 #ifdef SET_NETDEV_DEV
     if (ar_netif) { 
-        HIF_DEVICE_OS_DEVICE_INFO osDevInfo;
-        A_MEMZERO(&osDevInfo, sizeof(osDevInfo));
-        if ( A_SUCCESS( HIFConfigureDevice(hif_handle, HIF_DEVICE_GET_OS_DEVICE,
-                        &osDevInfo, sizeof(osDevInfo))) ) {
-            SET_NETDEV_DEV(dev, osDevInfo.pOSDevice);
-        }
+        SET_NETDEV_DEV(dev, osDevInfo.pOSDevice);
     }
 #endif 
 
@@ -1687,10 +1687,10 @@
     ar->arDeviceIndex        = device_index;
 
     ar->arWlanPowerState     = WLAN_POWER_STATE_ON;
-    ar->arWlanOff            = FALSE;   /* We are in ON state */
+    ar->arWlanOff            = false;   /* We are in ON state */
 #ifdef CONFIG_PM
     ar->arWowState           = WLAN_WOW_STATE_NONE;
-    ar->arBTOff              = TRUE;   /* BT chip assumed to be OFF */
+    ar->arBTOff              = true;   /* BT chip assumed to be OFF */
     ar->arBTSharing          = WLAN_CONFIG_BT_SHARING; 
     ar->arWlanOffConfig      = WLAN_CONFIG_WLAN_OFF;
     ar->arSuspendConfig      = WLAN_CONFIG_PM_SUSPEND;
@@ -1699,7 +1699,7 @@
 
     A_INIT_TIMER(&ar->arHBChallengeResp.timer, ar6000_detect_error, dev);
     ar->arHBChallengeResp.seqNum = 0;
-    ar->arHBChallengeResp.outstanding = FALSE;
+    ar->arHBChallengeResp.outstanding = false;
     ar->arHBChallengeResp.missCnt = 0;
     ar->arHBChallengeResp.frequency = AR6000_HB_CHALLENGE_RESP_FREQ_DEFAULT;
     ar->arHBChallengeResp.missThres = AR6000_HB_CHALLENGE_RESP_MISS_THRES_DEFAULT;
@@ -1707,7 +1707,7 @@
     ar6000_init_control_info(ar);
     init_waitqueue_head(&arEvent);
     sema_init(&ar->arSem, 1);
-    ar->bIsDestroyProgress = FALSE;
+    ar->bIsDestroyProgress = false;
 
     INIT_HTC_PACKET_QUEUE(&ar->amsdu_rx_buffer_queue);
 
@@ -1726,7 +1726,7 @@
     {
         struct bmi_target_info targ_info;
 
-        if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != A_OK) {
+        if (BMIGetTargetInfo(ar->arHifDevice, &targ_info) != 0) {
             init_status = A_ERROR;
             goto avail_ev_failed;
         }
@@ -1737,14 +1737,14 @@
             /* do any target-specific preparation that can be done through BMI */
         if (ar6000_prepare_target(ar->arHifDevice,
                                   targ_info.target_type,
-                                  targ_info.target_ver) != A_OK) {
+                                  targ_info.target_ver) != 0) {
             init_status = A_ERROR;
             goto avail_ev_failed;
         }
 
     }
 
-    if (ar6000_configure_target(ar) != A_OK) {
+    if (ar6000_configure_target(ar) != 0) {
             init_status = A_ERROR;
             goto avail_ev_failed;
     }
@@ -1799,25 +1799,27 @@
         if ((wlaninitmode == WLAN_INIT_MODE_UDEV) ||
             (wlaninitmode == WLAN_INIT_MODE_DRV))
         {
-            A_STATUS status = A_OK;
+            int status = 0;
             do {
-                if ((status = ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != A_OK)
+                if ((status = ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0)
                 {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n"));
                     break;
                 }
 #ifdef HTC_RAW_INTERFACE
-                break; /* Don't call ar6000_init for ART */
+                if (!eppingtest && bypasswmi) {
+                    break; /* Don't call ar6000_init for ART */
+                }
 #endif 
                 rtnl_lock();
-                status = (ar6000_init(dev)==0) ? A_OK : A_ERROR;
+                status = (ar6000_init(dev)==0) ? 0 : A_ERROR;
                 rtnl_unlock();
-                if (status != A_OK) {
+                if (status) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_init\n"));
                 }
-            } while (FALSE);
+            } while (false);
 
-            if (status != A_OK) {
+            if (status) {
                 init_status = status;
                 goto avail_ev_failed;
             }
@@ -1841,7 +1843,7 @@
                     (unsigned long)ar));
 
 avail_ev_failed :
-    if (A_FAILED(init_status)) {
+    if (init_status) {
         if (bmienable) { 
             ar6000_sysfs_bmi_deinit(ar);  
         }
@@ -1850,13 +1852,13 @@
     return init_status;
 }
 
-static void ar6000_target_failure(void *Instance, A_STATUS Status)
+static void ar6000_target_failure(void *Instance, int Status)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)Instance;
+    struct ar6_softc *ar = (struct ar6_softc *)Instance;
     WMI_TARGET_ERROR_REPORT_EVENT errEvent;
-    static A_BOOL sip = FALSE;
+    static bool sip = false;
 
-    if (Status != A_OK) {
+    if (Status != 0) {
 
         printk(KERN_ERR "ar6000_target_failure: target asserted \n");
 
@@ -1875,47 +1877,47 @@
 
         /* Report the error only once */
         if (!sip) {
-            sip = TRUE;
+            sip = true;
             errEvent.errorVal = WMI_TARGET_COM_ERR |
                                 WMI_TARGET_FATAL_ERR;
             ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
-                                     (A_UINT8 *)&errEvent,
+                                     (u8 *)&errEvent,
                                      sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
         }
     }
 }
 
-static A_STATUS
+static int
 ar6000_unavail_ev(void *context, void *hif_handle)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
         /* NULL out it's entry in the global list */
     ar6000_devices[ar->arDeviceIndex] = NULL;
     ar6000_destroy(ar->arNetDev, 1);
 
-    return A_OK;
+    return 0;
 }
 
 void
 ar6000_restart_endpoint(struct net_device *dev)
 {
-    A_STATUS status = A_OK;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    int status = 0;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     BMIInit();
     do {
-        if ( (status=ar6000_configure_target(ar))!=A_OK)
+        if ( (status=ar6000_configure_target(ar))!= 0)
             break;
-        if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != A_OK)
+        if ( (status=ar6000_sysfs_bmi_get_config(ar, wlaninitmode)) != 0)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_avail: ar6000_sysfs_bmi_get_config failed\n"));
             break;
         }
         rtnl_lock();
-        status = (ar6000_init(dev)==0) ? A_OK : A_ERROR;
+        status = (ar6000_init(dev)==0) ? 0 : A_ERROR;
         rtnl_unlock();
 
-        if (status!=A_OK) {
+        if (status) {
             break;
         }
         if (ar->arSsidLen && ar->arWlanState == WLAN_ENABLED) {
@@ -1923,7 +1925,7 @@
         }  
     } while (0);
 
-    if (status==A_OK) {
+    if (status== 0) {
         return;
     }
 
@@ -1932,27 +1934,24 @@
 }
 
 void
-ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglogs)
+ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     /* Stop the transmit queues */
     netif_stop_queue(dev);
 
     /* Disable the target and the interrupts associated with it */
-    if (ar->arWmiReady == TRUE)
+    if (ar->arWmiReady == true)
     {
         if (!bypasswmi)
         {
-            if (ar->arConnected == TRUE || ar->arConnectPending == TRUE)
-            {
-                AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Disconnect\n", __func__));
-                if (!keepprofile) {
-                    AR6000_SPIN_LOCK(&ar->arLock, 0);
-                    ar6000_init_profile_info(ar);
-                    AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-                }
-                wmi_disconnect_cmd(ar->arWmi);
+            bool disconnectIssued;
+ 
+            disconnectIssued = (ar->arConnected) || (ar->arConnectPending);
+            ar6000_disconnect(ar);
+            if (!keepprofile) {
+                ar6000_init_profile_info(ar);
             }
 
             A_UNTIMEOUT(&ar->disconnect_timer);
@@ -1961,9 +1960,9 @@
                 ar6000_dbglog_get_debug_logs(ar);
             }
 
-            ar->arWmiReady  = FALSE;
+            ar->arWmiReady  = false;
             wmi_shutdown(ar->arWmi);
-            ar->arWmiEnabled = FALSE;
+            ar->arWmiEnabled = false;
             ar->arWmi = NULL;
             /* 
              * After wmi_shudown all WMI events will be dropped.
@@ -1974,14 +1973,12 @@
              * Sometimes disconnect_event will be received when the debug logs 
              * are collected.
              */
-            if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
+            if (disconnectIssued) {
                 if(ar->arNetworkType & AP_NETWORK) {
                     ar6000_disconnect_event(ar, DISCONNECT_CMD, bcast_mac, 0, NULL, 0);
                 } else {
                     ar6000_disconnect_event(ar, DISCONNECT_CMD, ar->arBssid, 0, NULL, 0);
                 }
-                ar->arConnected = FALSE;
-                ar->arConnectPending = FALSE;
             }
 #ifdef USER_KEYS
             ar->user_savedkeys_stat = USER_SAVEDKEYS_STAT_INIT;
@@ -1997,11 +1994,11 @@
             __func__, (unsigned long) ar, (unsigned long) ar->arWmi));
 
         /* Shut down WMI if we have started it */
-        if(ar->arWmiEnabled == TRUE)
+        if(ar->arWmiEnabled == true)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("%s(): Shut down WMI\n", __func__));
             wmi_shutdown(ar->arWmi);
-            ar->arWmiEnabled = FALSE;
+            ar->arWmiEnabled = false;
             ar->arWmi = NULL;
         }
     }
@@ -2014,13 +2011,13 @@
 #else
         // FIXME: workaround to reset BT's UART baud rate to default
         if (NULL != ar->exitCallback) {
-            AR3K_CONFIG_INFO ar3kconfig;
-            A_STATUS status;
+            struct ar3k_config_info ar3kconfig;
+            int status;
 
             A_MEMZERO(&ar3kconfig,sizeof(ar3kconfig));
             ar6000_set_default_ar3kconfig(ar, (void *)&ar3kconfig);
             status = ar->exitCallback(&ar3kconfig);
-            if (A_OK != status) {
+            if (0 != status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to reset AR3K baud rate! \n"));
             }
         }
@@ -2048,14 +2045,17 @@
          * a debug session */
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Attempting to reset target on instance destroy.... \n"));
         if (ar->arHifDevice != NULL) {
-            A_BOOL coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? TRUE: FALSE;
-            ar6000_reset_device(ar->arHifDevice, ar->arTargetType, TRUE, coldReset);
+            bool coldReset = (ar->arTargetType == TARGET_TYPE_AR6003) ? true: false;
+            ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, coldReset);
         }
     } else {
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO,(" Host does not want target reset. \n"));
     }
        /* Done with cookies */
     ar6000_cookie_cleanup(ar);
+
+    /* cleanup any allocated AMSDU buffers */
+    ar6000_cleanup_amsdu_rxbufs(ar);
 }
 /*
  * We need to differentiate between the surprise and planned removal of the
@@ -2063,7 +2063,7 @@
  * - In case of surprise removal, the hcd already frees up the pending
  *   for the device and hence there is no need to unregister the function
  *   driver inorder to get these requests. For planned removal, the function
- *   driver has to explictly unregister itself to have the hcd return all the
+ *   driver has to explicitly unregister itself to have the hcd return all the
  *   pending requests before the data structures for the devices are freed up.
  *   Note that as per the current implementation, the function driver will
  *   end up releasing all the devices since there is no API to selectively
@@ -2074,7 +2074,7 @@
 void
 ar6000_destroy(struct net_device *dev, unsigned int unregister)
 {
-    AR_SOFTC_T *ar;
+    struct ar6_softc *ar;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("+ar6000_destroy \n"));
     
@@ -2084,7 +2084,7 @@
         return;
     }
 
-    ar->bIsDestroyProgress = TRUE;
+    ar->bIsDestroyProgress = true;
 
     if (down_interruptible(&ar->arSem)) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s(): down_interruptible failed \n", __func__));
@@ -2093,7 +2093,7 @@
 
     if (ar->arWlanPowerState != WLAN_POWER_STATE_CUT_PWR) {
         /* only stop endpoint if we are not stop it in suspend_ev */
-        ar6000_stop_endpoint(dev, FALSE, TRUE);
+        ar6000_stop_endpoint(dev, false, true);
     } else {
         /* clear up the platform power state before rmmod */
         plat_setup_power(1,0);
@@ -2159,18 +2159,18 @@
 static void disconnect_timer_handler(unsigned long ptr)
 {
     struct net_device *dev = (struct net_device *)ptr;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     A_UNTIMEOUT(&ar->disconnect_timer);
 
     ar6000_init_profile_info(ar);
-    wmi_disconnect_cmd(ar->arWmi);
+    ar6000_disconnect(ar);
 }
 
 static void ar6000_detect_error(unsigned long ptr)
 {
     struct net_device *dev = (struct net_device *)ptr;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_TARGET_ERROR_REPORT_EVENT errEvent;
 
     AR6000_SPIN_LOCK(&ar->arLock, 0);
@@ -2188,19 +2188,19 @@
         errEvent.errorVal = WMI_TARGET_COM_ERR | WMI_TARGET_FATAL_ERR;
         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         ar6000_send_event_to_app(ar, WMI_ERROR_REPORT_EVENTID,
-                                 (A_UINT8 *)&errEvent,
+                                 (u8 *)&errEvent,
                                  sizeof(WMI_TARGET_ERROR_REPORT_EVENT));
         return;
     }
 
     /* Generate the sequence number for the next challenge */
     ar->arHBChallengeResp.seqNum++;
-    ar->arHBChallengeResp.outstanding = TRUE;
+    ar->arHBChallengeResp.outstanding = true;
 
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
     /* Send the challenge on the control channel */
-    if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != A_OK) {
+    if (wmi_get_challenge_resp_cmd(ar->arWmi, ar->arHBChallengeResp.seqNum, DRV_HB_CHALLENGE) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to send heart beat challenge\n"));
     }
 
@@ -2209,7 +2209,7 @@
     A_TIMEOUT_MS(&ar->arHBChallengeResp.timer, ar->arHBChallengeResp.frequency * 1000, 0);
 }
 
-void ar6000_init_profile_info(AR_SOFTC_T *ar)
+void ar6000_init_profile_info(struct ar6_softc *ar)
 {
     ar->arSsidLen            = 0;
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
@@ -2236,13 +2236,12 @@
     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
     ar->arBssChannel = 0;
-    ar->arConnected = FALSE;
 }
 
 static void
-ar6000_init_control_info(AR_SOFTC_T *ar)
+ar6000_init_control_info(struct ar6_softc *ar)
 {
-    ar->arWmiEnabled         = FALSE;
+    ar->arWmiEnabled         = false;
     ar6000_init_profile_info(ar);
     ar->arDefTxKeyIndex      = 0;
     A_MEMZERO(ar->arWepKeyList, sizeof(ar->arWepKeyList));
@@ -2252,12 +2251,12 @@
     ar->arVersion.host_ver   = AR6K_SW_VERSION;
     ar->arRssi               = 0;
     ar->arTxPwr              = 0;
-    ar->arTxPwrSet           = FALSE;
+    ar->arTxPwrSet           = false;
     ar->arSkipScan           = 0;
     ar->arBeaconInterval     = 0;
     ar->arBitRate            = 0;
     ar->arMaxRetries         = 0;
-    ar->arWmmEnabled         = TRUE;
+    ar->arWmmEnabled         = true;
     ar->intra_bss            = 1;
     ar->scan_triggered       = 0;
     A_MEMZERO(&ar->scParams, sizeof(ar->scParams));
@@ -2266,8 +2265,8 @@
 
     /* Initialize the AP mode state info */
     {
-        A_UINT8 ctr;
-        A_MEMZERO((A_UINT8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t));
+        u8 ctr;
+        A_MEMZERO((u8 *)ar->sta_list, AP_MAX_NUM_STA * sizeof(sta_t));
 
         /* init the Mutexes */
         A_MUTEX_INIT(&ar->mcastpsqLock);
@@ -2281,7 +2280,7 @@
         ar->ap_profile_flag = 0;
         A_NETBUF_QUEUE_INIT(&ar->mcastpsq);
 
-        A_MEMCPY(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
+        memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
         ar->ap_wmode = DEF_AP_WMODE_G;
         ar->ap_dtim_period = DEF_AP_DTIM;
         ar->ap_beacon_interval = DEF_BEACON_INTERVAL;
@@ -2292,7 +2291,7 @@
 ar6000_open(struct net_device *dev)
 {
     unsigned long  flags;
-    AR_SOFTC_T    *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc    *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     spin_lock_irqsave(&ar->arLock, flags);
 
@@ -2318,38 +2317,33 @@
 ar6000_close(struct net_device *dev)
 {
 #ifdef ATH6K_CONFIG_CFG80211
-    AR_SOFTC_T    *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc    *ar = (struct ar6_softc *)ar6k_priv(dev);
 #endif /* ATH6K_CONFIG_CFG80211 */
     netif_stop_queue(dev);
 
 #ifdef ATH6K_CONFIG_CFG80211
-    AR6000_SPIN_LOCK(&ar->arLock, 0);
-    if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
-        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-        wmi_disconnect_cmd(ar->arWmi);
-    } else {
-        AR6000_SPIN_UNLOCK(&ar->arLock, 0);
-    }
+    ar6000_disconnect(ar);
 
-    if(ar->arWmiReady == TRUE) {
+    if(ar->arWmiReady == true) {
         if (wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0,
-                               0, 0, 0, 0, 0, 0, 0, 0) != A_OK) {
+                               0, 0, 0, 0, 0, 0, 0, 0) != 0) {
             return -EIO;
         }
         ar->arWlanState = WLAN_DISABLED;
     }
+	ar6k_cfg80211_scanComplete_event(ar, A_ECANCELED);
 #endif /* ATH6K_CONFIG_CFG80211 */
 
     return 0;
 }
 
 /* connect to a service */
-static A_STATUS ar6000_connectservice(AR_SOFTC_T               *ar,
-                                      HTC_SERVICE_CONNECT_REQ  *pConnect,
-                                      char                     *pDesc)
+static int ar6000_connectservice(struct ar6_softc               *ar,
+                                      struct htc_service_connect_req  *pConnect,
+                                      char *pDesc)
 {
-    A_STATUS                 status;
-    HTC_SERVICE_CONNECT_RESP response;
+    int                 status;
+    struct htc_service_connect_resp response;
 
     do {
 
@@ -2359,7 +2353,7 @@
                                    pConnect,
                                    &response);
 
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,(" Failed to connect to %s service status:%d \n",
                               pDesc, status));
             break;
@@ -2391,12 +2385,12 @@
             break;
         }
 
-    } while (FALSE);
+    } while (false);
 
     return status;
 }
 
-void ar6000_TxDataCleanup(AR_SOFTC_T *ar)
+void ar6000_TxDataCleanup(struct ar6_softc *ar)
 {
         /* flush all the data (non-control) streams
          * we only flush packets that are tagged as data, we leave any control packets that
@@ -2416,32 +2410,148 @@
 }
 
 HTC_ENDPOINT_ID
-ar6000_ac2_endpoint_id ( void * devt, A_UINT8 ac)
+ar6000_ac2_endpoint_id ( void * devt, u8 ac)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *) devt;
+    struct ar6_softc *ar = (struct ar6_softc *) devt;
     return(arAc2EndpointID(ar, ac));
 }
 
-A_UINT8
-ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep )
+u8 ar6000_endpoint_id2_ac(void * devt, HTC_ENDPOINT_ID ep )
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *) devt;
+    struct ar6_softc *ar = (struct ar6_softc *) devt;
     return(arEndpoint2Ac(ar, ep ));
 }
 
-/* This function does one time initialization for the lifetime of the device */
-int ar6000_init(struct net_device *dev)
+/*
+ * This function applies WLAN specific configuration defined in wlan_config.h
+ */
+int ar6000_target_config_wlan_params(struct ar6_softc *ar)
 {
-    AR_SOFTC_T *ar;
-    A_STATUS    status;
-    A_INT32     timeleft;
-    A_INT16     i;
-    int         ret = 0;
+    int status = 0;
 #if defined(INIT_MODE_DRV_ENABLED) && defined(ENABLE_COEXISTENCE)
     WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD sbcb_cmd;
     WMI_SET_BTCOEX_FE_ANT_CMD sbfa_cmd;
 #endif /* INIT_MODE_DRV_ENABLED && ENABLE_COEXISTENCE */
 
+#ifdef CONFIG_HOST_TCMD_SUPPORT
+    if (ar->arTargetMode != AR6000_WLAN_MODE) {
+        return 0;
+    }
+#endif /* CONFIG_HOST_TCMD_SUPPORT */
+
+    /* 
+     * configure the device for rx dot11 header rules 0,0 are the default values
+     * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required
+     * if checksum offload is needed. Set RxMetaVersion to 2
+     */
+    if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n"));
+        status = A_ERROR;
+    }
+
+#if defined(INIT_MODE_DRV_ENABLED) && defined(ENABLE_COEXISTENCE)
+    /* Configure the type of BT collocated with WLAN */
+    memset(&sbcb_cmd, 0, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
+#ifdef CONFIG_AR600x_BT_QCOM
+    sbcb_cmd.btcoexCoLocatedBTdev = 1;
+#elif defined(CONFIG_AR600x_BT_CSR)
+    sbcb_cmd.btcoexCoLocatedBTdev = 2;
+#elif defined(CONFIG_AR600x_BT_AR3001)
+    sbcb_cmd.btcoexCoLocatedBTdev = 3;
+#else
+#error Unsupported Bluetooth Type
+#endif /* Collocated Bluetooth Type */
+
+    if ((wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set collocated BT type\n"));
+        status = A_ERROR;
+    }
+
+    /* Configure the type of BT collocated with WLAN */
+    memset(&sbfa_cmd, 0, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
+#ifdef CONFIG_AR600x_DUAL_ANTENNA
+    sbfa_cmd.btcoexFeAntType = 2;
+#elif defined(CONFIG_AR600x_SINGLE_ANTENNA)
+    sbfa_cmd.btcoexFeAntType = 1;
+#else
+#error Unsupported Front-End Antenna Configuration
+#endif /* AR600x Front-End Antenna Configuration */
+
+    if ((wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set fornt end antenna configuration\n"));
+        status = A_ERROR;
+    }
+#endif /* INIT_MODE_DRV_ENABLED && ENABLE_COEXISTENCE */
+
+#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
+    if ((wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power save fail event policy\n"));
+        status = A_ERROR;
+    }
+#endif
+
+#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
+    if ((wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set barker preamble policy\n"));
+        status = A_ERROR;
+    }
+#endif
+
+    if ((wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set keep alive interval\n"));
+        status = A_ERROR;
+    }
+
+#if WLAN_CONFIG_DISABLE_11N
+    {
+        WMI_SET_HT_CAP_CMD htCap;
+
+        memset(&htCap, 0, sizeof(WMI_SET_HT_CAP_CMD));
+        htCap.band = 0;
+        if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) {
+            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n"));
+            status = A_ERROR;
+        }
+
+        htCap.band = 1;
+        if ((wmi_set_ht_cap_cmd(ar->arWmi, &htCap)) != 0) {
+            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set ht capabilities \n"));
+            status = A_ERROR;
+        }
+    }
+#endif /* WLAN_CONFIG_DISABLE_11N */
+
+#ifdef ATH6K_CONFIG_OTA_MODE
+    if ((wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set power mode \n"));
+        status = A_ERROR;
+    }
+#endif
+
+    if ((wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set disconnect timeout \n"));
+        status = A_ERROR;
+    }
+
+#if WLAN_CONFIG_DISABLE_TX_BURSTING  
+    if ((wmi_set_wmm_txop(ar->arWmi, WMI_TXOP_DISABLED)) != 0) {
+        AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set txop bursting \n"));
+        status = A_ERROR;
+    }
+#endif 
+
+    return status;
+}
+
+/* This function does one time initialization for the lifetime of the device */
+int ar6000_init(struct net_device *dev)
+{
+    struct ar6_softc *ar;
+    int    status;
+    s32 timeleft;
+    s16 i;
+    int         ret = 0;
+
     if((ar = ar6k_priv(dev)) == NULL)
     {
         return -EIO;
@@ -2465,7 +2575,7 @@
 
     /* Do we need to finish the BMI phase */
     if ((wlaninitmode == WLAN_INIT_MODE_USR || wlaninitmode == WLAN_INIT_MODE_DRV) && 
-        (BMIDone(ar->arHifDevice) != A_OK))
+        (BMIDone(ar->arHifDevice) != 0))
     {
         ret = -EIO;
         goto ar6000_init_done;
@@ -2482,7 +2592,7 @@
 #endif
 
         /* Indicate that WMI is enabled (although not ready yet) */
-        ar->arWmiEnabled = TRUE;
+        ar->arWmiEnabled = true;
         if ((ar->arWmi = wmi_init((void *) ar)) == NULL)
         {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() Failed to initialize WMI.\n", __func__));
@@ -2495,14 +2605,14 @@
     }
 
     do {
-        HTC_SERVICE_CONNECT_REQ connect;
+        struct htc_service_connect_req connect;
 
             /* the reason we have to wait for the target here is that the driver layer
              * has to init BMI in order to set the host block size,
              */
         status = HTCWaitTarget(ar->arHtcTarget);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2533,7 +2643,7 @@
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI CONTROL");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2555,7 +2665,7 @@
              * of 0-3 */
             connect.ConnectionFlags &= ~HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
             connect.ConnectionFlags |=
-                        ((A_UINT16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
+                        ((u16)reduce_credit_dribble - 1) & HTC_CONNECT_FLAGS_THRESHOLD_LEVEL_MASK;
         }
             /* connect to best-effort service */
         connect.ServiceID = WMI_DATA_BE_SVC;
@@ -2563,7 +2673,7 @@
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA BE");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2573,7 +2683,7 @@
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA BK");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2583,7 +2693,7 @@
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA VI");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2596,7 +2706,7 @@
         status = ar6000_connectservice(ar,
                                        &connect,
                                        "WMI DATA VO");
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -2613,12 +2723,12 @@
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
         if (setuphci && (NULL != ar6kHciTransCallbacks.setupTransport)) {
-            HCI_TRANSPORT_MISC_HANDLES hciHandles;
+            struct hci_transport_misc_handles hciHandles;
 
             hciHandles.netDevice = ar->arNetDev;
             hciHandles.hifDevice = ar->arHifDevice;
             hciHandles.htcHandle = ar->arHtcTarget;
-            status = (A_STATUS)(ar6kHciTransCallbacks.setupTransport(&hciHandles));
+            status = (int)(ar6kHciTransCallbacks.setupTransport(&hciHandles));
         }
 #else
         if (setuphci) {
@@ -2634,9 +2744,9 @@
           status = ar6k_setup_hci_pal(ar);
 #endif
 
-    } while (FALSE);
+    } while (false);
 
-    if (A_FAILED(status)) {
+    if (status) {
         ret = -EIO;
         goto ar6000_init_done;
     }
@@ -2671,10 +2781,10 @@
     /* start HTC */
     status = HTCStart(ar->arHtcTarget);
 
-    if (status != A_OK) {
-        if (ar->arWmiEnabled == TRUE) {
+    if (status) {
+        if (ar->arWmiEnabled == true) {
             wmi_shutdown(ar->arWmi);
-            ar->arWmiEnabled = FALSE;
+            ar->arWmiEnabled = false;
             ar->arWmi = NULL;
         }
         ar6000_cookie_cleanup(ar);
@@ -2685,7 +2795,7 @@
     if (!bypasswmi) {
         /* Wait for Wmi event to be ready */
         timeleft = wait_event_interruptible_timeout(arEvent,
-            (ar->arWmiReady == TRUE), wmitimeout * HZ);
+            (ar->arWmiReady == true), wmitimeout * HZ);
 
         if (ar->arVersion.abi_ver != AR6K_ABI_VERSION) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ABI Version mismatch: Host(0x%x), Target(0x%x)\n", AR6K_ABI_VERSION, ar->arVersion.abi_ver));
@@ -2705,49 +2815,10 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("%s() WMI is ready\n", __func__));
 
         /* Communicate the wmi protocol verision to the target */
-        if ((ar6000_set_host_app_area(ar)) != A_OK) {
+        if ((ar6000_set_host_app_area(ar)) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the host app area\n"));
         }
-
-        /* configure the device for rx dot11 header rules 0,0 are the default values
-         * therefore this command can be skipped if the inputs are 0,FALSE,FALSE.Required
-         if checksum offload is needed. Set RxMetaVersion to 2*/
-        if ((wmi_set_rx_frame_format_cmd(ar->arWmi,ar->rxMetaVersion, processDot11Hdr, processDot11Hdr)) != A_OK) {
-            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set the rx frame format.\n"));
-        }
-
-#if defined(INIT_MODE_DRV_ENABLED) && defined(ENABLE_COEXISTENCE)
-        /* Configure the type of BT collocated with WLAN */
-        A_MEMZERO(&sbcb_cmd, sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
-#ifdef CONFIG_AR600x_BT_QCOM
-        sbcb_cmd.btcoexCoLocatedBTdev = 1;
-#elif defined(CONFIG_AR600x_BT_CSR)
-        sbcb_cmd.btcoexCoLocatedBTdev = 2;
-#elif defined(CONFIG_AR600x_BT_AR3001)
-        sbcb_cmd.btcoexCoLocatedBTdev = 3;
-#else
-#error Unsupported Bluetooth Type
-#endif /* Collocated Bluetooth Type */
-
-        if ((wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &sbcb_cmd)) != A_OK)
-        {
-            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set collocated BT type\n"));
-        }
-
-        /* Configure the type of BT collocated with WLAN */
-        A_MEMZERO(&sbfa_cmd, sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
-#ifdef CONFIG_AR600x_DUAL_ANTENNA
-        sbfa_cmd.btcoexFeAntType = 2;
-#elif defined(CONFIG_AR600x_SINGLE_ANTENNA)
-        sbfa_cmd.btcoexFeAntType = 1;
-#else
-#error Unsupported Front-End Antenna Configuration
-#endif /* AR600x Front-End Antenna Configuration */
-
-        if ((wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &sbfa_cmd)) != A_OK) {
-            AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to set fornt end antenna configuration\n"));
-        }
-#endif /* INIT_MODE_DRV_ENABLED && ENABLE_COEXISTENCE */
+        ar6000_target_config_wlan_params(ar);
     }
 
     ar->arNumDataEndPts = 1;
@@ -2772,27 +2843,27 @@
 
 
 void
-ar6000_bitrate_rx(void *devt, A_INT32 rateKbps)
+ar6000_bitrate_rx(void *devt, s32 rateKbps)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arBitRate = rateKbps;
     wake_up(&arEvent);
 }
 
 void
-ar6000_ratemask_rx(void *devt, A_UINT32 ratemask)
+ar6000_ratemask_rx(void *devt, u32 ratemask)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arRateMask = ratemask;
     wake_up(&arEvent);
 }
 
 void
-ar6000_txPwr_rx(void *devt, A_UINT8 txPwr)
+ar6000_txPwr_rx(void *devt, u8 txPwr)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arTxPwr = txPwr;
     wake_up(&arEvent);
@@ -2800,23 +2871,22 @@
 
 
 void
-ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList)
+ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
-    A_MEMCPY(ar->arChannelList, chanList, numChan * sizeof (A_UINT16));
+    memcpy(ar->arChannelList, chanList, numChan * sizeof (u16));
     ar->arNumChannels = numChan;
 
     wake_up(&arEvent);
 }
 
-A_UINT8
-ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, A_UINT32 * mapNo)
+u8 ar6000_ibss_map_epid(struct sk_buff *skb, struct net_device *dev, u32 *mapNo)
 {
-    AR_SOFTC_T      *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8         *datap;
+    struct ar6_softc      *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 *datap;
     ATH_MAC_HDR     *macHdr;
-    A_UINT32         i, eptMap;
+    u32 i, eptMap;
 
     (*mapNo) = 0;
     datap = A_NETBUF_DATA(skb);
@@ -2844,7 +2914,7 @@
         A_ASSERT(ar->arNodeNum <= MAX_NODE_NUM);
     }
 
-    A_MEMCPY(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
+    memcpy(ar->arNodeMap[eptMap].macAddress, macHdr->dstMac, IEEE80211_ADDR_LEN);
 
     for (i = ENDPOINT_2; i <= ENDPOINT_5; i ++) {
         if (!ar->arTxPending[i]) {
@@ -2882,22 +2952,22 @@
 #endif
 
 #ifdef HTC_TEST_SEND_PKTS
-static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb);
+static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *skb);
 #endif
 
 static int
 ar6000_data_tx(struct sk_buff *skb, struct net_device *dev)
 {
 #define AC_NOT_MAPPED   99
-    AR_SOFTC_T        *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8            ac = AC_NOT_MAPPED;
+    struct ar6_softc        *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 ac = AC_NOT_MAPPED;
     HTC_ENDPOINT_ID    eid = ENDPOINT_UNUSED;
-    A_UINT32          mapNo = 0;
+    u32 mapNo = 0;
     int               len;
     struct ar_cookie *cookie;
-    A_BOOL            checkAdHocPsMapping = FALSE,bMoreData = FALSE;
+    bool            checkAdHocPsMapping = false,bMoreData = false;
     HTC_TX_TAG        htc_tag = AR6K_DATA_PKT_TAG;
-    A_UINT8           dot11Hdr = processDot11Hdr;
+    u8 dot11Hdr = processDot11Hdr;
 #ifdef CONFIG_PM
     if (ar->arWowState != WLAN_WOW_STATE_NONE) {
         A_NETBUF_FREE(skb);
@@ -2912,7 +2982,7 @@
     /* If target is not associated */
     if( (!ar->arConnected && !bypasswmi)
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-     /* TCMD doesnt support any data, free the buf and return */
+     /* TCMD doesn't support any data, free the buf and return */
     || (ar->arTargetMode == AR6000_TCMD_MODE)
 #endif
                                             ) {
@@ -2922,7 +2992,7 @@
 
     do {
 
-        if (ar->arWmiReady == FALSE && bypasswmi == 0) {
+        if (ar->arWmiReady == false && bypasswmi == 0) {
             break;
         }
 
@@ -2944,20 +3014,20 @@
              * mcastq
              */
             if (IEEE80211_IS_MULTICAST(datap->dstMac)) {
-                A_UINT8 ctr=0;
-                A_BOOL qMcast=FALSE;
+                u8 ctr=0;
+                bool qMcast=false;
 
 
                 for (ctr=0; ctr<AP_MAX_NUM_STA; ctr++) {
                     if (STA_IS_PWR_SLEEP((&ar->sta_list[ctr]))) {
-                        qMcast = TRUE;
+                        qMcast = true;
                     }
                 }
                 if(qMcast) {
 
                     /* If this transmit is not because of a Dtim Expiry q it */
-                    if (ar->DTIMExpired == FALSE) {
-                        A_BOOL isMcastqEmpty = FALSE;
+                    if (ar->DTIMExpired == false) {
+                        bool isMcastqEmpty = false;
 
                         A_MUTEX_LOCK(&ar->mcastpsqLock);
                         isMcastqEmpty = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq);
@@ -2978,7 +3048,7 @@
                       */
                          A_MUTEX_LOCK(&ar->mcastpsqLock);
                          if(!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
-                             bMoreData = TRUE;
+                             bMoreData = true;
                          }
                          A_MUTEX_UNLOCK(&ar->mcastpsqLock);
                     }
@@ -2989,7 +3059,7 @@
                     if (STA_IS_PWR_SLEEP(conn)) {
                         /* If this transmit is not because of a PsPoll q it*/
                         if (!STA_IS_PS_POLLED(conn)) {
-                            A_BOOL isPsqEmpty = FALSE;
+                            bool isPsqEmpty = false;
                             /* Queue the frames if the STA is sleeping */
                             A_MUTEX_LOCK(&conn->psqLock);
                             isPsqEmpty = A_NETBUF_QUEUE_EMPTY(&conn->psq);
@@ -3010,7 +3080,7 @@
                           */
                              A_MUTEX_LOCK(&conn->psqLock);
                              if (!A_NETBUF_QUEUE_EMPTY(&conn->psq)) {
-                                 bMoreData = TRUE;
+                                 bMoreData = true;
                              }
                              A_MUTEX_UNLOCK(&conn->psqLock);
                          }
@@ -3026,9 +3096,9 @@
 
         if (ar->arWmiEnabled) {
 #ifdef CONFIG_CHECKSUM_OFFLOAD
-        A_UINT8 csumStart=0;
-        A_UINT8 csumDest=0;
-        A_UINT8 csum=skb->ip_summed;
+        u8 csumStart=0;
+        u8 csumDest=0;
+        u8 csum=skb->ip_summed;
         if(csumOffload && (csum==CHECKSUM_PARTIAL)){
             csumStart = (skb->head + skb->csum_start - skb_network_header(skb) +
 			 sizeof(ATH_LLC_SNAP_HDR));
@@ -3048,19 +3118,19 @@
                     break;
                 }
                 A_NETBUF_PUT(newbuf, len);
-                A_MEMCPY(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
+                memcpy(A_NETBUF_DATA(newbuf), A_NETBUF_DATA(skb), len);
                 A_NETBUF_FREE(skb);
                 skb = newbuf;
                 /* fall through and assemble header */
             }
 
             if (dot11Hdr) {
-                if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != A_OK) {
+                if (wmi_dot11_hdr_add(ar->arWmi,skb,ar->arNetworkType) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx-wmi_dot11_hdr_add failed\n"));
                     break;
                 }
             } else {
-                if (wmi_dix_2_dot3(ar->arWmi, skb) != A_OK) {
+                if (wmi_dix_2_dot3(ar->arWmi, skb) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_dix_2_dot3 failed\n"));
                     break;
                 }
@@ -3072,7 +3142,7 @@
                 metaV2.csumDest = csumDest;
                 metaV2.csumFlags = 0x1;/*instruct target to calculate checksum*/
                 if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,
-                                        WMI_META_VERSION_2,&metaV2) != A_OK) {
+                                        WMI_META_VERSION_2,&metaV2) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n"));
                     break;
                 }
@@ -3081,7 +3151,7 @@
             else
 #endif
             {
-                if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != A_OK) {
+                if (wmi_data_hdr_add(ar->arWmi, skb, DATA_MSGTYPE, bMoreData, dot11Hdr,0,NULL) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_data_tx - wmi_data_hdr_add failed\n"));
                     break;
                 }
@@ -3091,7 +3161,7 @@
             if ((ar->arNetworkType == ADHOC_NETWORK) &&
                 ar->arIbssPsEnable && ar->arConnected) {
                     /* flag to check adhoc mapping once we take the lock below: */
-                checkAdHocPsMapping = TRUE;
+                checkAdHocPsMapping = true;
 
             } else {
                     /* get the stream mapping */
@@ -3115,7 +3185,7 @@
                 if (ac == HCI_TRANSPORT_STREAM_NUM) {
                         /* pass this to HCI */
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
-                    if (A_SUCCESS(hci_test_send(ar,skb))) {
+                    if (!hci_test_send(ar,skb)) {
                         return 0;
                     }
 #endif
@@ -3136,7 +3206,7 @@
             }
         }
 
-    } while (FALSE);
+    } while (false);
 
         /* did we succeed ? */
     if ((ac == AC_NOT_MAPPED) && !checkAdHocPsMapping) {
@@ -3173,7 +3243,7 @@
             ar->arTotalTxDataPending++;
         }
 
-    } while (FALSE);
+    } while (false);
 
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
@@ -3211,7 +3281,7 @@
 int
 ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev)
 {
-    AR_SOFTC_T        *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc        *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct ar_cookie *cookie;
     HTC_ENDPOINT_ID    eid = ENDPOINT_UNUSED;
 
@@ -3267,13 +3337,13 @@
 }
 
 void
-applyAPTCHeuristics(AR_SOFTC_T *ar)
+applyAPTCHeuristics(struct ar6_softc *ar)
 {
-    A_UINT32 duration;
-    A_UINT32 numbytes;
-    A_UINT32 throughput;
+    u32 duration;
+    u32 numbytes;
+    u32 throughput;
     struct timeval ts;
-    A_STATUS status;
+    int status;
 
     AR6000_SPIN_LOCK(&ar->arLock, 0);
 
@@ -3292,12 +3362,12 @@
             throughput = ((numbytes * 8) / duration);
             if (throughput > APTC_UPPER_THROUGHPUT_THRESHOLD) {
                 /* Disable Sleep and schedule a timer */
-                A_ASSERT(ar->arWmiReady == TRUE);
+                A_ASSERT(ar->arWmiReady == true);
                 AR6000_SPIN_UNLOCK(&ar->arLock, 0);
                 status = wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
                 AR6000_SPIN_LOCK(&ar->arLock, 0);
                 A_TIMEOUT_MS(&aptcTimer, APTC_TRAFFIC_SAMPLING_INTERVAL, 0);
-                aptcTR.timerScheduled = TRUE;
+                aptcTR.timerScheduled = true;
             }
         }
     }
@@ -3306,11 +3376,11 @@
 }
 #endif /* ADAPTIVE_POWER_THROUGHPUT_CONTROL */
 
-static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, HTC_PACKET *pPacket)
+static HTC_SEND_FULL_ACTION ar6000_tx_queue_full(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T     *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc     *ar = (struct ar6_softc *)Context;
     HTC_SEND_FULL_ACTION    action = HTC_SEND_FULL_KEEP;
-    A_BOOL                  stopNet = FALSE;
+    bool                  stopNet = false;
     HTC_ENDPOINT_ID         Endpoint = HTC_GET_ENDPOINT_FROM_PKT(pPacket);
 
     do {
@@ -3327,10 +3397,10 @@
                 /* for endpoint ping testing drop Best Effort and Background */
             if ((accessClass == WMM_AC_BE) || (accessClass == WMM_AC_BK)) {
                 action = HTC_SEND_FULL_DROP;
-                stopNet = FALSE;
+                stopNet = false;
             } else {
                     /* keep but stop the netqueues */
-                stopNet = TRUE;
+                stopNet = true;
             }
             break;
         }
@@ -3341,11 +3411,11 @@
                  * the only exception to this is during testing using endpointping */
             AR6000_SPIN_LOCK(&ar->arLock, 0);
                 /* set flag to handle subsequent messages */
-            ar->arWMIControlEpFull = TRUE;
+            ar->arWMIControlEpFull = true;
             AR6000_SPIN_UNLOCK(&ar->arLock, 0);
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("WMI Control Endpoint is FULL!!! \n"));
                 /* no need to stop the network */
-            stopNet = FALSE;
+            stopNet = false;
             break;
         }
 
@@ -3359,7 +3429,7 @@
         if (ar->arNetworkType == ADHOC_NETWORK) {
             /* in adhoc mode, we cannot differentiate traffic priorities so there is no need to
              * continue, however we should stop the network */
-            stopNet = TRUE;
+            stopNet = true;
             break;
         }
         /* the last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for the highest
@@ -3371,15 +3441,15 @@
                  * HTC to drop the packet that overflowed */
             action = HTC_SEND_FULL_DROP;
                 /* since we are dropping packets, no need to stop the network */
-            stopNet = FALSE;
+            stopNet = false;
             break;
         }
 
-    } while (FALSE);
+    } while (false);
 
     if (stopNet) {
         AR6000_SPIN_LOCK(&ar->arLock, 0);
-        ar->arNetQueueStopped = TRUE;
+        ar->arNetQueueStopped = true;
         AR6000_SPIN_UNLOCK(&ar->arLock, 0);
         /* one of the data endpoints queues is getting full..need to stop network stack
          * the queue will resume in ar6000_tx_complete() */
@@ -3391,18 +3461,18 @@
 
 
 static void
-ar6000_tx_complete(void *Context, HTC_PACKET_QUEUE *pPacketQueue)
+ar6000_tx_complete(void *Context, struct htc_packet_queue *pPacketQueue)
 {
-    AR_SOFTC_T     *ar = (AR_SOFTC_T *)Context;
-    A_UINT32        mapNo = 0;
-    A_STATUS        status;
+    struct ar6_softc     *ar = (struct ar6_softc *)Context;
+    u32 mapNo = 0;
+    int        status;
     struct ar_cookie * ar_cookie;
     HTC_ENDPOINT_ID   eid;
-    A_BOOL          wakeEvent = FALSE;
+    bool          wakeEvent = false;
     struct sk_buff_head  skb_queue;
-    HTC_PACKET      *pPacket;
+    struct htc_packet      *pPacket;
     struct sk_buff  *pktSkb;
-    A_BOOL          flushing = FALSE;
+    bool          flushing = false;
 
     skb_queue_head_init(&skb_queue);
 
@@ -3428,7 +3498,7 @@
             /* add this to the list, use faster non-lock API */
         __skb_queue_tail(&skb_queue,pktSkb);
 
-        if (A_SUCCESS(status)) {
+        if (!status) {
             A_ASSERT(pPacket->ActualLength == A_NETBUF_LEN(pktSkb));
         }
 
@@ -3447,18 +3517,18 @@
         {
             if (ar->arWMIControlEpFull) {
                     /* since this packet completed, the WMI EP is no longer full */
-                ar->arWMIControlEpFull = FALSE;
+                ar->arWMIControlEpFull = false;
             }
 
             if (ar->arTxPending[eid] == 0) {
-                wakeEvent = TRUE;
+                wakeEvent = true;
             }
         }
 
-        if (A_FAILED(status)) {
+        if (status) {
             if (status == A_ECANCELED) {
                     /* a packet was flushed  */
-                flushing = TRUE;
+                flushing = true;
             }
             AR6000_STAT_INC(ar, tx_errors);
             if (status != A_NO_RESOURCE) {
@@ -3467,7 +3537,7 @@
             }
         } else {
             AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("OK\n"));
-            flushing = FALSE;
+            flushing = false;
             AR6000_STAT_INC(ar, tx_packets);
             ar->arNetStats.tx_bytes += A_NETBUF_LEN(pktSkb);
 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
@@ -3484,7 +3554,7 @@
             ar->arNodeMap[mapNo].txPending --;
 
             if (!ar->arNodeMap[mapNo].txPending && (mapNo == (ar->arNodeNum - 1))) {
-                A_UINT32 i;
+                u32 i;
                 for (i = ar->arNodeNum; i > 0; i --) {
                     if (!ar->arNodeMap[i - 1].txPending) {
                         A_MEMZERO(&ar->arNodeMap[i - 1], sizeof(struct ar_node_mapping));
@@ -3499,7 +3569,7 @@
         ar6000_free_cookie(ar, ar_cookie);
 
         if (ar->arNetQueueStopped) {
-            ar->arNetQueueStopped = FALSE;
+            ar->arNetQueueStopped = false;
         }
     }
 
@@ -3514,7 +3584,7 @@
         A_NETBUF_FREE(pktSkb);
     }
 
-    if ((ar->arConnected == TRUE) || (bypasswmi)) {
+    if ((ar->arConnected == true) || bypasswmi) {
         if (!flushing) {
                 /* don't wake the queue if we are flushing, other wise it will just
                  * keep queueing packets, which will keep failing */
@@ -3529,10 +3599,10 @@
 }
 
 sta_t *
-ieee80211_find_conn(AR_SOFTC_T *ar, A_UINT8 *node_addr)
+ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr)
 {
     sta_t *conn = NULL;
-    A_UINT8 i, max_conn;
+    u8 i, max_conn;
 
     switch(ar->arNetworkType) {
         case AP_NETWORK:
@@ -3553,10 +3623,10 @@
     return conn;
 }
 
-sta_t *ieee80211_find_conn_for_aid(AR_SOFTC_T *ar, A_UINT8 aid)
+sta_t *ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid)
 {
     sta_t *conn = NULL;
-    A_UINT8 ctr;
+    u8 ctr;
 
     for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
         if (ar->sta_list[ctr].aid == aid) {
@@ -3572,22 +3642,22 @@
  */
 int pktcount;
 static void
-ar6000_rx(void *Context, HTC_PACKET *pPacket)
+ar6000_rx(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc *ar = (struct ar6_softc *)Context;
     struct sk_buff *skb = (struct sk_buff *)pPacket->pPktContext;
     int minHdrLen;
-    A_UINT8 containsDot11Hdr = 0;
-    A_STATUS        status = pPacket->Status;
+    u8 containsDot11Hdr = 0;
+    int        status = pPacket->Status;
     HTC_ENDPOINT_ID   ept = pPacket->Endpoint;
 
-    A_ASSERT((status != A_OK) ||
+    A_ASSERT((status) ||
              (pPacket->pBuffer == (A_NETBUF_DATA(skb) + HTC_HEADER_LEN)));
 
     AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_rx ar=0x%lx eid=%d, skb=0x%lx, data=0x%lx, len=0x%x status:%d",
                     (unsigned long)ar, ept, (unsigned long)skb, (unsigned long)pPacket->pBuffer,
                     pPacket->ActualLength, status));
-    if (status != A_OK) {
+    if (status) {
         if (status != A_ECANCELED) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("RX ERR (%d) \n",status));
         }
@@ -3597,7 +3667,7 @@
          * and adaptive power throughput state */
     AR6000_SPIN_LOCK(&ar->arLock, 0);
 
-    if (A_SUCCESS(status)) {
+    if (!status) {
         AR6000_STAT_INC(ar, rx_packets);
         ar->arNetStats.rx_bytes += pPacket->ActualLength;
 #ifdef ADAPTIVE_POWER_THROUGHPUT_CONTROL
@@ -3618,24 +3688,26 @@
     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
 
     skb->dev = ar->arNetDev;
-    if (status != A_OK) {
+    if (status) {
         AR6000_STAT_INC(ar, rx_errors);
         A_NETBUF_FREE(skb);
-    } else if (ar->arWmiEnabled == TRUE) {
+    } else if (ar->arWmiEnabled == true) {
         if (ept == ar->arControlEp) {
            /*
             * this is a wmi control msg
             */
 #ifdef CONFIG_PM 
-            ar6000_check_wow_status(ar, skb, TRUE);
+            ar6000_check_wow_status(ar, skb, true);
 #endif /* CONFIG_PM */
             wmi_control_rx(ar->arWmi, skb);
         } else {
                 WMI_DATA_HDR *dhdr = (WMI_DATA_HDR *)A_NETBUF_DATA(skb);
-                A_UINT8 is_amsdu, tid, is_acl_data_frame;
+                bool is_amsdu;
+                u8 tid;
+                bool is_acl_data_frame;
                 is_acl_data_frame = WMI_DATA_HDR_GET_DATA_TYPE(dhdr) == WMI_DATA_HDR_DATA_TYPE_ACL;
 #ifdef CONFIG_PM 
-                ar6000_check_wow_status(ar, NULL, FALSE);
+                ar6000_check_wow_status(ar, NULL, false);
 #endif /* CONFIG_PM */
                 /*
                  * this is a wmi data packet
@@ -3667,8 +3739,8 @@
                     AR6000_STAT_INC(ar, rx_length_errors);
                     A_NETBUF_FREE(skb);
                 } else {
-                    A_UINT16 seq_no;
-                    A_UINT8 meta_type;
+                    u16 seq_no;
+                    u8 meta_type;
 
 #if 0
                     /* Access RSSI values here */
@@ -3678,9 +3750,9 @@
                     /* Get the Power save state of the STA */
                     if (ar->arNetworkType == AP_NETWORK) {
                         sta_t *conn = NULL;
-                        A_UINT8 psState=0,prevPsState;
+                        u8 psState=0,prevPsState;
                         ATH_MAC_HDR *datap=NULL;
-                        A_UINT16 offset;
+                        u16 offset;
 
                         meta_type = WMI_DATA_HDR_GET_META(dhdr);
 
@@ -3742,7 +3814,7 @@
                             }
                         } else {
                             /* This frame is from a STA that is not associated*/
-                            A_ASSERT(FALSE);
+                            A_ASSERT(false);
                         }
 
                         /* Drop NULL data frames here */
@@ -3753,7 +3825,7 @@
                         }
                     }
 
-                    is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr);
+                    is_amsdu = WMI_DATA_HDR_IS_AMSDU(dhdr) ? true : false;
                     tid = WMI_DATA_HDR_GET_UP(dhdr);
                     seq_no = WMI_DATA_HDR_GET_SEQNO(dhdr);
                     meta_type = WMI_DATA_HDR_GET_META(dhdr);
@@ -3785,7 +3857,7 @@
                             break;
                     }
 
-                    A_ASSERT(status == A_OK);
+                    A_ASSERT(status == 0);
 
                     /* NWF: print the 802.11 hdr bytes */
                     if(containsDot11Hdr) {
@@ -3794,7 +3866,7 @@
                         status = wmi_dot3_2_dix(skb);
                     }
 
-                    if (status != A_OK) {
+                    if (status) {
                         /* Drop frames that could not be processed (lack of memory, etc.) */
                         A_NETBUF_FREE(skb);
                         goto rx_done;
@@ -3805,7 +3877,7 @@
                         *((short *)A_NETBUF_DATA(skb)) = WMI_ACL_DATA_EVENTID;
 	                /* send the data packet to PAL driver */
 			if(ar6k_pal_config_g.fpar6k_pal_recv_pkt) {
-				if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, skb) == TRUE)
+				if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, skb) == true)
 					goto rx_done;
 			}
                     }
@@ -3870,7 +3942,7 @@
         skb->dev = dev;
         if ((skb->dev->flags & IFF_UP) == IFF_UP) {
 #ifdef CONFIG_PM 
-            ar6000_check_wow_status((AR_SOFTC_T *)ar6k_priv(dev), skb, FALSE);   
+            ar6000_check_wow_status((struct ar6_softc *)ar6k_priv(dev), skb, false);
 #endif /* CONFIG_PM */
             skb->protocol = eth_type_trans(skb, skb->dev);
         /*
@@ -3915,12 +3987,12 @@
 static void
 ar6000_rx_refill(void *Context, HTC_ENDPOINT_ID Endpoint)
 {
-    AR_SOFTC_T  *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc  *ar = (struct ar6_softc *)Context;
     void        *osBuf;
     int         RxBuffers;
     int         buffersToRefill;
-    HTC_PACKET  *pPacket;
-    HTC_PACKET_QUEUE queue;
+    struct htc_packet  *pPacket;
+    struct htc_packet_queue queue;
 
     buffersToRefill = (int)AR6000_MAX_RX_BUFFERS -
                                     HTCGetNumRecvBuffers(ar->arHtcTarget, Endpoint);
@@ -3942,7 +4014,7 @@
         }
             /* the HTC packet wrapper is at the head of the reserved area
              * in the skb */
-        pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
+        pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf));
             /* set re-fill info */
         SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_BUFFER_SIZE,Endpoint);
             /* add to queue */
@@ -3957,13 +4029,13 @@
 }
 
   /* clean up our amsdu buffer list */
-static void ar6000_cleanup_amsdu_rxbufs(AR_SOFTC_T *ar)
+static void ar6000_cleanup_amsdu_rxbufs(struct ar6_softc *ar)
 {
-    HTC_PACKET  *pPacket;
+    struct htc_packet  *pPacket;
     void        *osBuf;
 
         /* empty AMSDU buffer queue and free OS bufs */
-    while (TRUE) {
+    while (true) {
 
         AR6000_SPIN_LOCK(&ar->arLock, 0);
         pPacket = HTC_PACKET_DEQUEUE(&ar->amsdu_rx_buffer_queue);
@@ -3975,7 +4047,7 @@
 
         osBuf = pPacket->pPktContext;
         if (NULL == osBuf) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -3986,9 +4058,9 @@
 
 
     /* refill the amsdu buffer list */
-static void ar6000_refill_amsdu_rxbufs(AR_SOFTC_T *ar, int Count)
+static void ar6000_refill_amsdu_rxbufs(struct ar6_softc *ar, int Count)
 {
-    HTC_PACKET  *pPacket;
+    struct htc_packet  *pPacket;
     void        *osBuf;
 
     while (Count > 0) {
@@ -3998,7 +4070,7 @@
         }
             /* the HTC packet wrapper is at the head of the reserved area
              * in the skb */
-        pPacket = (HTC_PACKET *)(A_NETBUF_HEAD(osBuf));
+        pPacket = (struct htc_packet *)(A_NETBUF_HEAD(osBuf));
             /* set re-fill info */
         SET_HTC_PACKET_INFO_RX_REFILL(pPacket,osBuf,A_NETBUF_DATA(osBuf),AR6000_AMSDU_BUFFER_SIZE,0);
 
@@ -4018,10 +4090,10 @@
      * keep the allocation size the same to optimize cached-slab allocations.
      *
      * */
-static HTC_PACKET *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length)
+static struct htc_packet *ar6000_alloc_amsdu_rxbuf(void *Context, HTC_ENDPOINT_ID Endpoint, int Length)
 {
-    HTC_PACKET  *pPacket = NULL;
-    AR_SOFTC_T  *ar = (AR_SOFTC_T *)Context;
+    struct htc_packet  *pPacket = NULL;
+    struct ar6_softc  *ar = (struct ar6_softc *)Context;
     int         refillCount = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_RX,("ar6000_alloc_amsdu_rxbuf: eid=%d, Length:%d\n",Endpoint,Length));
@@ -4030,12 +4102,12 @@
 
         if (Length <= AR6000_BUFFER_SIZE) {
                 /* shouldn't be getting called on normal sized packets */
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
         if (Length > AR6000_AMSDU_BUFFER_SIZE) {
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
         }
 
@@ -4052,7 +4124,7 @@
             /* set actual endpoint ID */
         pPacket->Endpoint = Endpoint;
 
-    } while (FALSE);
+    } while (false);
 
     if (refillCount >= AR6000_AMSDU_REFILL_THRESHOLD) {
         ar6000_refill_amsdu_rxbufs(ar,refillCount);
@@ -4070,19 +4142,19 @@
 static struct net_device_stats *
 ar6000_get_stats(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     return &ar->arNetStats;
 }
 
 static struct iw_statistics *
 ar6000_get_iwstats(struct net_device * dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     TARGET_STATS *pStats = &ar->arTargetStats;
     struct iw_statistics * pIwStats = &ar->arIwStats;
     int rtnllocked;
 
-    if (ar->bIsDestroyProgress || ar->arWmiReady == FALSE || ar->arWlanState == WLAN_DISABLED)
+    if (ar->bIsDestroyProgress || ar->arWmiReady == false || ar->arWlanState == WLAN_DISABLED)
     {
         pIwStats->status = 0;
         pIwStats->qual.qual = 0;
@@ -4132,13 +4204,13 @@
             break;
         }
     
-        ar->statsUpdatePending = TRUE;
+        ar->statsUpdatePending = true;
     
-        if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+        if(wmi_get_stats_cmd(ar->arWmi) != 0) {
             break;
         }
     
-        wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+        wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
         if (signal_pending(current)) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000 : WMI get stats timeout \n"));
             break;
@@ -4162,12 +4234,12 @@
 }
 
 void
-ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap, A_UINT32 sw_ver, A_UINT32 abi_ver)
+ar6000_ready_event(void *devt, u8 *datap, u8 phyCap, u32 sw_ver, u32 abi_ver)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
     struct net_device *dev = ar->arNetDev;
 
-    A_MEMCPY(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
+    memcpy(dev->dev_addr, datap, AR6000_ETH_ADDR_LEN);
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("mac address = %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x\n",
         dev->dev_addr[0], dev->dev_addr[1],
         dev->dev_addr[2], dev->dev_addr[3],
@@ -4178,43 +4250,18 @@
     ar->arVersion.abi_ver = abi_ver;
 
     /* Indicate to the waiting thread that the ready event was received */
-    ar->arWmiReady = TRUE;
+    ar->arWmiReady = true;
     wake_up(&arEvent);
-
-#if WLAN_CONFIG_IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN
-    wmi_pmparams_cmd(ar->arWmi, 0, 1, 0, 0, 1, IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN);
-#endif
-#if WLAN_CONFIG_DONOT_IGNORE_BARKER_IN_ERP
-    wmi_set_lpreamble_cmd(ar->arWmi, 0, WMI_DONOT_IGNORE_BARKER_IN_ERP);
-#endif
-    wmi_set_keepalive_cmd(ar->arWmi, WLAN_CONFIG_KEEP_ALIVE_INTERVAL);
-#if WLAN_CONFIG_DISABLE_11N
-    {
-        WMI_SET_HT_CAP_CMD htCap;
-
-        A_MEMZERO(&htCap, sizeof(WMI_SET_HT_CAP_CMD));
-        htCap.band = 0;
-        wmi_set_ht_cap_cmd(ar->arWmi, &htCap);
-
-        htCap.band = 1;
-        wmi_set_ht_cap_cmd(ar->arWmi, &htCap);
-    }
-#endif /* WLAN_CONFIG_DISABLE_11N */
-
-#ifdef ATH6K_CONFIG_OTA_MODE
-    wmi_powermode_cmd(ar->arWmi, MAX_PERF_POWER);
-#endif
-    wmi_disctimeout_cmd(ar->arWmi, WLAN_CONFIG_DISCONNECT_TIMEOUT);
 }
 
 void
-add_new_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 aid, A_UINT8 *wpaie,
-            A_UINT8 ielen, A_UINT8 keymgmt, A_UINT8 ucipher, A_UINT8 auth)
+add_new_sta(struct ar6_softc *ar, u8 *mac, u16 aid, u8 *wpaie,
+            u8 ielen, u8 keymgmt, u8 ucipher, u8 auth)
 {
-    A_UINT8    free_slot=aid-1;
+    u8 free_slot=aid-1;
 
-        A_MEMCPY(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN);
-        A_MEMCPY(ar->sta_list[free_slot].wpa_ie, wpaie, ielen);
+        memcpy(ar->sta_list[free_slot].mac, mac, ATH_MAC_LEN);
+        memcpy(ar->sta_list[free_slot].wpa_ie, wpaie, ielen);
         ar->sta_list[free_slot].aid = aid;
         ar->sta_list[free_slot].keymgmt = keymgmt;
         ar->sta_list[free_slot].ucipher = ucipher;
@@ -4224,11 +4271,11 @@
 }
 
 void
-ar6000_connect_event(AR_SOFTC_T *ar, A_UINT16 channel, A_UINT8 *bssid,
-                     A_UINT16 listenInterval, A_UINT16 beaconInterval,
-                     NETWORK_TYPE networkType, A_UINT8 beaconIeLen,
-                     A_UINT8 assocReqLen, A_UINT8 assocRespLen,
-                     A_UINT8 *assocInfo)
+ar6000_connect_event(struct ar6_softc *ar, u16 channel, u8 *bssid,
+                     u16 listenInterval, u16 beaconInterval,
+                     NETWORK_TYPE networkType, u8 beaconIeLen,
+                     u8 assocReqLen, u8 assocRespLen,
+                     u8 *assocInfo)
 {
     union iwreq_data wrqu;
     int i, beacon_ie_pos, assoc_resp_ie_pos, assoc_req_ie_pos;
@@ -4237,14 +4284,14 @@
     static const char *beaconIetag = "BEACONIE=";
     char buf[WMI_CONTROL_MSG_MAX_LEN * 2 + strlen(tag1) + 1];
     char *pos;
-    A_UINT8 key_op_ctrl;
+    u8 key_op_ctrl;
     unsigned long flags;
     struct ieee80211req_key *ik;
     CRYPTO_TYPE keyType = NONE_CRYPT;
 
     if(ar->arNetworkType & AP_NETWORK) {
         struct net_device *dev = ar->arNetDev;
-        if(A_MEMCMP(dev->dev_addr, bssid, ATH_MAC_LEN)==0) {
+        if(memcmp(dev->dev_addr, bssid, ATH_MAC_LEN)==0) {
             ar->arACS = channel;
             ik = &ar->ap_mode_bkey;
 
@@ -4273,14 +4320,14 @@
                        goto skip_key;
                 }
                 wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, GROUP_USAGE,
-                                ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
+                                ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
                                 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
                                 SYNC_BOTH_WMIFLAG);
 
                 break;
             }
 skip_key:
-            ar->arConnected  = TRUE;
+            ar->arConnected  = true;
             return;
         }
 
@@ -4336,7 +4383,7 @@
 
         /* Send event to application */
         A_MEMZERO(&wrqu, sizeof(wrqu));
-        A_MEMCPY(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
+        memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
         wireless_send_event(ar->arNetDev, IWEVREGISTERED, &wrqu, NULL);
         /* In case the queue is stopped when we switch modes, this will
          * wake it up
@@ -4353,7 +4400,7 @@
                                 assocInfo);
 #endif /* ATH6K_CONFIG_CFG80211 */
 
-    A_MEMCPY(ar->arBssid, bssid, sizeof(ar->arBssid));
+    memcpy(ar->arBssid, bssid, sizeof(ar->arBssid));
     ar->arBssChannel = channel;
 
     A_PRINTF("AR6000 connected event on freq %d ", channel);
@@ -4400,9 +4447,9 @@
     if (assocRespLen && (sizeof(buf) > (12 + (assocRespLen * 2))))
     {
         assoc_resp_ie_pos = beaconIeLen + assocReqLen +
-                            sizeof(A_UINT16)  +  /* capinfo*/
-                            sizeof(A_UINT16)  +  /* status Code */
-                            sizeof(A_UINT16)  ;  /* associd */
+                            sizeof(u16)  +  /* capinfo*/
+                            sizeof(u16)  +  /* status Code */
+                            sizeof(u16)  ;  /* associd */
         A_MEMZERO(buf, sizeof(buf));
         sprintf(buf, "%s", tag2);
         pos = buf + 12;
@@ -4429,8 +4476,8 @@
          * assoc Request includes capability and listen interval. Skip these.
          */
         assoc_req_ie_pos =  beaconIeLen +
-                            sizeof(A_UINT16)  +  /* capinfo*/
-                            sizeof(A_UINT16);    /* listen interval */
+                            sizeof(u16)  +  /* capinfo*/
+                            sizeof(u16);    /* listen interval */
 
         A_MEMZERO(buf, sizeof(buf));
         sprintf(buf, "%s", tag1);
@@ -4450,7 +4497,7 @@
 
 #ifdef USER_KEYS
     if (ar->user_savedkeys_stat == USER_SAVEDKEYS_STAT_RUN &&
-        ar->user_saved_keys.keyOk == TRUE)
+        ar->user_saved_keys.keyOk == true)
     {
         key_op_ctrl = KEY_OP_VALID_MASK & ~KEY_OP_INIT_TSC;
 
@@ -4487,8 +4534,8 @@
 
     /* Update connect & link status atomically */
     spin_lock_irqsave(&ar->arLock, flags);
-    ar->arConnected  = TRUE;
-    ar->arConnectPending = FALSE;
+    ar->arConnected  = true;
+    ar->arConnectPending = false;
     netif_carrier_on(ar->arNetDev);
     spin_unlock_irqrestore(&ar->arLock, flags);
     /* reset the rx aggr state */
@@ -4496,7 +4543,7 @@
     reconnect_flag = 0;
 
     A_MEMZERO(&wrqu, sizeof(wrqu));
-    A_MEMCPY(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
+    memcpy(wrqu.addr.sa_data, bssid, IEEE80211_ADDR_LEN);
     wrqu.addr.sa_family = ARPHRD_ETHER;
     wireless_send_event(ar->arNetDev, SIOCGIWAP, &wrqu, NULL);
     if ((ar->arNetworkType == ADHOC_NETWORK) && ar->arIbssPsEnable) {
@@ -4510,14 +4557,14 @@
 
 }
 
-void ar6000_set_numdataendpts(AR_SOFTC_T *ar, A_UINT32 num)
+void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num)
 {
     A_ASSERT(num <= (HTC_MAILBOX_NUM_MAX - 1));
     ar->arNumDataEndPts = num;
 }
 
 void
-sta_cleanup(AR_SOFTC_T *ar, A_UINT8 i)
+sta_cleanup(struct ar6_softc *ar, u8 i)
 {
     struct sk_buff *skb;
 
@@ -4540,10 +4587,9 @@
 
 }
 
-A_UINT8
-remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason)
+u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason)
 {
-    A_UINT8 i, removed=0;
+    u8 i, removed=0;
 
     if(IS_MAC_NULL(mac)) {
         return removed;
@@ -4559,7 +4605,7 @@
         }
     } else {
         for(i=0; i < AP_MAX_NUM_STA; i++) {
-            if(A_MEMCMP(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) {
+            if(memcmp(ar->sta_list[i].mac, mac, ATH_MAC_LEN)==0) {
                 A_PRINTF("DEL STA %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x "
                 " aid=%d REASON=%d\n", mac[0], mac[1], mac[2],
                  mac[3], mac[4], mac[5], ar->sta_list[i].aid, reason);
@@ -4574,10 +4620,10 @@
 }
 
 void
-ar6000_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason, A_UINT8 *bssid,
-                        A_UINT8 assocRespLen, A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
+ar6000_disconnect_event(struct ar6_softc *ar, u8 reason, u8 *bssid,
+                        u8 assocRespLen, u8 *assocInfo, u16 protocolReasonStatus)
 {
-    A_UINT8 i;
+    u8 i;
     unsigned long flags;
     union iwreq_data wrqu;
 
@@ -4607,9 +4653,11 @@
         if(!IS_MAC_BCAST(bssid)) {
             /* Send event to application */
             A_MEMZERO(&wrqu, sizeof(wrqu));
-            A_MEMCPY(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
+            memcpy(wrqu.addr.sa_data, bssid, ATH_MAC_LEN);
             wireless_send_event(ar->arNetDev, IWEVEXPIRED, &wrqu, NULL);
         }
+
+        ar->arConnected = false;
         return;
     }
 
@@ -4654,15 +4702,14 @@
      */
     if( reason == DISCONNECT_CMD)
     {
-        ar->arConnectPending = FALSE;
         if ((!ar->arUserBssFilter) && (ar->arWmiReady)) {
             wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
         }
     } else {
-        ar->arConnectPending = TRUE;
+        ar->arConnectPending = true;
         if (((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x11)) ||
             ((reason == ASSOC_FAILED) && (protocolReasonStatus == 0x0) && (reconnect_flag == 1))) {
-            ar->arConnected = TRUE;
+            ar->arConnected = true;
             return;
         }
     }
@@ -4684,7 +4731,7 @@
              * Find the nodes based on SSID and remove it
              * NOTE :: This case will not work out for Hidden-SSID
              */
-            pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, FALSE, TRUE);
+            pWmiSsidnode = wmi_find_Ssidnode (ar->arWmi, ar->arSsid, ar->arSsidLen, false, true);
 
             if (pWmiSsidnode)
             {
@@ -4696,7 +4743,7 @@
 
     /* Update connect & link status atomically */
     spin_lock_irqsave(&ar->arLock, flags);
-    ar->arConnected = FALSE;
+    ar->arConnected = false;
     netif_carrier_off(ar->arNetDev);
     spin_unlock_irqrestore(&ar->arLock, flags);
 
@@ -4721,7 +4768,7 @@
 }
 
 void
-ar6000_regDomain_event(AR_SOFTC_T *ar, A_UINT32 regCode)
+ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode)
 {
     A_PRINTF("AR6000 Reg Code = 0x%x\n", regCode);
     ar->arRegCode = regCode;
@@ -4729,7 +4776,7 @@
 
 #ifdef ATH_AR6K_11N_SUPPORT
 void
-ar6000_aggr_rcv_addba_req_evt(AR_SOFTC_T *ar, WMI_ADDBA_REQ_EVENT *evt)
+ar6000_aggr_rcv_addba_req_evt(struct ar6_softc *ar, WMI_ADDBA_REQ_EVENT *evt)
 {
     if(evt->status == 0) {
         aggr_recv_addba_req_evt(ar->aggr_cntxt, evt->tid, evt->st_seq_no, evt->win_sz);
@@ -4737,7 +4784,7 @@
 }
 
 void
-ar6000_aggr_rcv_addba_resp_evt(AR_SOFTC_T *ar, WMI_ADDBA_RESP_EVENT *evt)
+ar6000_aggr_rcv_addba_resp_evt(struct ar6_softc *ar, WMI_ADDBA_RESP_EVENT *evt)
 {
     A_PRINTF("ADDBA RESP. tid %d status %d, sz %d\n", evt->tid, evt->status, evt->amsdu_sz);
     if(evt->status == 0) {
@@ -4745,7 +4792,7 @@
 }
 
 void
-ar6000_aggr_rcv_delba_req_evt(AR_SOFTC_T *ar, WMI_DELBA_EVENT *evt)
+ar6000_aggr_rcv_delba_req_evt(struct ar6_softc *ar, WMI_DELBA_EVENT *evt)
 {
     aggr_recv_delba_req_evt(ar->aggr_cntxt, evt->tid);
 }
@@ -4760,9 +4807,9 @@
 ar6000_hci_event_rcv_evt(struct ar6_softc *ar, WMI_HCI_EVENT *cmd)
 {
     void *osbuf = NULL;
-    A_INT8 i;
-    A_UINT8 size, *buf;
-    A_STATUS ret = A_OK;
+    s8 i;
+    u8 size, *buf;
+    int ret = 0;
 
     size = cmd->evt_buf_sz + 4;
     osbuf = A_NETBUF_ALLOC(size);
@@ -4773,18 +4820,18 @@
     }
 
     A_NETBUF_PUT(osbuf, size);
-    buf = (A_UINT8 *)A_NETBUF_DATA(osbuf);
+    buf = (u8 *)A_NETBUF_DATA(osbuf);
     /* First 2-bytes carry HCI event/ACL data type
      * the next 2 are free
      */
     *((short *)buf) = WMI_HCI_EVENT_EVENTID;
     buf += sizeof(int);
-    A_MEMCPY(buf, cmd->buf, cmd->evt_buf_sz);
+    memcpy(buf, cmd->buf, cmd->evt_buf_sz);
 
     if(ar6k_pal_config_g.fpar6k_pal_recv_pkt)
     {
       /* pass the cmd packet to PAL driver */
-      if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, osbuf) == TRUE)
+      if((*ar6k_pal_config_g.fpar6k_pal_recv_pkt)(ar->hcipal_info, osbuf) == true)
         return;
     }
     ar6000_deliver_frames_to_nw_stack(ar->arNetDev, osbuf);
@@ -4802,7 +4849,7 @@
 }
 
 void
-ar6000_neighborReport_event(AR_SOFTC_T *ar, int numAps, WMI_NEIGHBOR_INFO *info)
+ar6000_neighborReport_event(struct ar6_softc *ar, int numAps, WMI_NEIGHBOR_INFO *info)
 {
 #if WIRELESS_EXT >= 18
     struct iw_pmkid_cand *pmkcand;
@@ -4833,7 +4880,7 @@
         A_MEMZERO(pmkcand, sizeof(struct iw_pmkid_cand));
         pmkcand->index = i;
         pmkcand->flags = info->bssFlags;
-        A_MEMCPY(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN);
+        memcpy(pmkcand->bssid.sa_data, info->bssid, ATH_MAC_LEN);
         wrqu.data.length = sizeof(struct iw_pmkid_cand);
         wireless_send_event(ar->arNetDev, IWEVPMKIDCAND, &wrqu, (char *)pmkcand);
         A_FREE(pmkcand);
@@ -4850,7 +4897,7 @@
 }
 
 void
-ar6000_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
+ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast)
 {
     static const char *tag = "MLME-MICHAELMICFAILURE.indication";
     char buf[128];
@@ -4887,7 +4934,7 @@
 }
 
 void
-ar6000_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
+ar6000_scanComplete_event(struct ar6_softc *ar, int status)
 {
 
 #ifdef ATH6K_CONFIG_CFG80211
@@ -4898,7 +4945,7 @@
         wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
     }
     if (ar->scan_triggered) {
-        if (status==A_OK) {
+        if (status== 0) {
             union iwreq_data wrqu;
             A_MEMZERO(&wrqu, sizeof(wrqu));
             wireless_send_event(ar->arNetDev, SIOCGIWSCAN, &wrqu, NULL);
@@ -4910,9 +4957,9 @@
 }
 
 void
-ar6000_targetStats_event(AR_SOFTC_T *ar,  A_UINT8 *ptr, A_UINT32 len)
+ar6000_targetStats_event(struct ar6_softc *ar,  u8 *ptr, u32 len)
 {
-    A_UINT8 ac;
+    u8 ac;
 
     if(ar->arNetworkType == AP_NETWORK) {
         WMI_AP_MODE_STAT *p = (WMI_AP_MODE_STAT *)ptr;
@@ -5028,14 +5075,14 @@
         pStats->arp_replied  += pTarget->arpStats.arp_replied;
 
         if (ar->statsUpdatePending) {
-            ar->statsUpdatePending = FALSE;
+            ar->statsUpdatePending = false;
             wake_up(&arEvent);
         }
     }
 }
 
 void
-ar6000_rssiThreshold_event(AR_SOFTC_T *ar,  WMI_RSSI_THRESHOLD_VAL newThreshold, A_INT16 rssi)
+ar6000_rssiThreshold_event(struct ar6_softc *ar,  WMI_RSSI_THRESHOLD_VAL newThreshold, s16 rssi)
 {
     USER_RSSI_THOLD userRssiThold;
 
@@ -5051,28 +5098,28 @@
     A_PRINTF("rssi Threshold range = %d tag = %d  rssi = %d\n", newThreshold,
              userRssiThold.tag, userRssiThold.rssi);
 
-    ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(A_UINT8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
+    ar6000_send_event_to_app(ar, WMI_RSSI_THRESHOLD_EVENTID,(u8 *)&userRssiThold, sizeof(USER_RSSI_THOLD));
 }
 
 
 void
-ar6000_hbChallengeResp_event(AR_SOFTC_T *ar, A_UINT32 cookie, A_UINT32 source)
+ar6000_hbChallengeResp_event(struct ar6_softc *ar, u32 cookie, u32 source)
 {
     if (source == APP_HB_CHALLENGE) {
         /* Report it to the app in case it wants a positive acknowledgement */
         ar6000_send_event_to_app(ar, WMIX_HB_CHALLENGE_RESP_EVENTID,
-                                 (A_UINT8 *)&cookie, sizeof(cookie));
+                                 (u8 *)&cookie, sizeof(cookie));
     } else {
         /* This would ignore the replys that come in after their due time */
         if (cookie == ar->arHBChallengeResp.seqNum) {
-            ar->arHBChallengeResp.outstanding = FALSE;
+            ar->arHBChallengeResp.outstanding = false;
         }
     }
 }
 
 
 void
-ar6000_reportError_event(AR_SOFTC_T *ar, WMI_TARGET_ERROR_VAL errorVal)
+ar6000_reportError_event(struct ar6_softc *ar, WMI_TARGET_ERROR_VAL errorVal)
 {
 	static const char * const errString[] = {
 		[WMI_TARGET_PM_ERR_FAIL]    "WMI_TARGET_PM_ERR_FAIL",
@@ -5107,8 +5154,8 @@
 
 
 void
-ar6000_cac_event(AR_SOFTC_T *ar, A_UINT8 ac, A_UINT8 cacIndication,
-                 A_UINT8 statusCode, A_UINT8 *tspecSuggestion)
+ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cacIndication,
+                 u8 statusCode, u8 *tspecSuggestion)
 {
     WMM_TSPEC_IE    *tspecIe;
 
@@ -5130,8 +5177,8 @@
 }
 
 void
-ar6000_channel_change_event(AR_SOFTC_T *ar, A_UINT16 oldChannel,
-                            A_UINT16 newChannel)
+ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel,
+                            u16 newChannel)
 {
     A_PRINTF("Channel Change notification\nOld Channel: %d, New Channel: %d\n",
              oldChannel, newChannel);
@@ -5144,9 +5191,9 @@
 } while(0)
 
 void
-ar6000_roam_tbl_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_TBL *pTbl)
+ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl)
 {
-    A_UINT8 i;
+    u8 i;
 
     A_PRINTF("ROAM TABLE NO OF ENTRIES is %d ROAM MODE is %d\n",
               pTbl->numEntries, pTbl->roamMode);
@@ -5169,9 +5216,9 @@
 }
 
 void
-ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
+ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters, WMI_GET_WOW_LIST_REPLY *wow_reply)
 {
-    A_UINT8 i,j;
+    u8 i,j;
 
     /*Each event now contains exactly one filter, see bug 26613*/
     A_PRINTF("WOW pattern %d of %d patterns\n", wow_reply->this_filter_num,                 wow_reply->num_filters);
@@ -5223,7 +5270,7 @@
 }
 
 void
-ar6000_roam_data_event(AR_SOFTC_T *ar, WMI_TARGET_ROAM_DATA *p)
+ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p)
 {
     switch (p->roamDataType) {
         case ROAM_DATA_TIME:
@@ -5235,7 +5282,7 @@
 }
 
 void
-ar6000_bssInfo_event_rx(AR_SOFTC_T *ar, A_UINT8 *datap, int len)
+ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *datap, int len)
 {
     struct sk_buff *skb;
     WMI_BSS_INFO_HDR *bih = (WMI_BSS_INFO_HDR *)datap;
@@ -5255,9 +5302,9 @@
     if ((skb = A_NETBUF_ALLOC_RAW(len)) != NULL) {
 
         A_NETBUF_PUT(skb, len);
-        A_MEMCPY(A_NETBUF_DATA(skb), datap, len);
+        memcpy(A_NETBUF_DATA(skb), datap, len);
         skb->dev = ar->arNetDev;
-        A_MEMCPY(skb_mac_header(skb), A_NETBUF_DATA(skb), 6);
+        memcpy(skb_mac_header(skb), A_NETBUF_DATA(skb), 6);
         skb->ip_summed = CHECKSUM_NONE;
         skb->pkt_type = PACKET_OTHERHOST;
         skb->protocol = __constant_htons(0x0019);
@@ -5265,13 +5312,13 @@
     }
 }
 
-A_UINT32 wmiSendCmdNum;
+u32 wmiSendCmdNum;
 
-A_STATUS
+int
 ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid)
 {
-    AR_SOFTC_T       *ar = (AR_SOFTC_T *)devt;
-    A_STATUS         status = A_OK;
+    struct ar6_softc       *ar = (struct ar6_softc *)devt;
+    int         status = 0;
     struct ar_cookie *cookie = NULL;
     int i;
 #ifdef CONFIG_PM
@@ -5306,13 +5353,13 @@
         if(logWmiRawMsgs) {
             A_PRINTF("WMI cmd send, msgNo %d :", wmiSendCmdNum);
             for(i = 0; i < a_netbuf_to_len(osbuf); i++)
-                A_PRINTF("%x ", ((A_UINT8 *)a_netbuf_to_data(osbuf))[i]);
+                A_PRINTF("%x ", ((u8 *)a_netbuf_to_data(osbuf))[i]);
             A_PRINTF("\n");
         }
 
         wmiSendCmdNum++;
 
-    } while (FALSE);
+    } while (false);
 
     if (cookie != NULL) {
             /* got a structure to send it out on */
@@ -5337,19 +5384,19 @@
             /* this interface is asynchronous, if there is an error, cleanup will happen in the
              * TX completion callback */
         HTCSendPkt(ar->arHtcTarget, &cookie->HtcPkt);
-        status = A_OK;
+        status = 0;
     }
 
-    if (status != A_OK) {
+    if (status) {
         A_NETBUF_FREE(osbuf);
     }
     return status;
 }
 
 /* indicate tx activity or inactivity on a WMI stream */
-void ar6000_indicate_tx_activity(void *devt, A_UINT8 TrafficClass, A_BOOL Active)
+void ar6000_indicate_tx_activity(void *devt, u8 TrafficClass, bool Active)
 {
-    AR_SOFTC_T  *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc  *ar = (struct ar6_softc *)devt;
     HTC_ENDPOINT_ID eid ;
     int i;
 
@@ -5407,7 +5454,7 @@
 }
 
 void
-ar6000_btcoex_config_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len)
+ar6000_btcoex_config_event(struct ar6_softc *ar,  u8 *ptr, u32 len)
 {
 
     WMI_BTCOEX_CONFIG_EVENT *pBtcoexConfig = (WMI_BTCOEX_CONFIG_EVENT *)ptr;
@@ -5421,39 +5468,39 @@
 
     switch (pBtcoexConfig->btProfileType) {
         case WMI_BTCOEX_BT_PROFILE_SCO:
-            A_MEMCPY(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd,
+            memcpy(&pArbtcoexConfig->info.scoConfigCmd, &pBtcoexConfig->info.scoConfigCmd,
                                         sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
             break;
         case WMI_BTCOEX_BT_PROFILE_A2DP:
-            A_MEMCPY(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd,
+            memcpy(&pArbtcoexConfig->info.a2dpConfigCmd, &pBtcoexConfig->info.a2dpConfigCmd,
                                         sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
             break;
         case WMI_BTCOEX_BT_PROFILE_ACLCOEX:
-            A_MEMCPY(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig,
+            memcpy(&pArbtcoexConfig->info.aclcoexConfig, &pBtcoexConfig->info.aclcoexConfig,
                                         sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
             break;
         case WMI_BTCOEX_BT_PROFILE_INQUIRY_PAGE:
-           A_MEMCPY(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd,
+           memcpy(&pArbtcoexConfig->info.btinquiryPageConfigCmd, &pBtcoexConfig->info.btinquiryPageConfigCmd,
                                         sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
             break;
     }
     if (ar->statsUpdatePending) {
-         ar->statsUpdatePending = FALSE;
+         ar->statsUpdatePending = false;
           wake_up(&arEvent);
     }
 }
 
 void
-ar6000_btcoex_stats_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len)
+ar6000_btcoex_stats_event(struct ar6_softc *ar,  u8 *ptr, u32 len)
 {
     WMI_BTCOEX_STATS_EVENT *pBtcoexStats = (WMI_BTCOEX_STATS_EVENT *)ptr;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("AR6000 BTCOEX CONFIG EVENT \n"));
 
-    A_MEMCPY(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT));
+    memcpy(&ar->arBtcoexStats, pBtcoexStats, sizeof(WMI_BTCOEX_STATS_EVENT));
 
     if (ar->statsUpdatePending) {
-         ar->statsUpdatePending = FALSE;
+         ar->statsUpdatePending = false;
         wake_up(&arEvent);
     }
 
@@ -5463,9 +5510,9 @@
 
 /* Init cookie queue */
 static void
-ar6000_cookie_init(AR_SOFTC_T *ar)
+ar6000_cookie_init(struct ar6_softc *ar)
 {
-    A_UINT32    i;
+    u32 i;
 
     ar->arCookieList = NULL;
     ar->arCookieCount = 0;
@@ -5479,7 +5526,7 @@
 
 /* cleanup cookie queue */
 static void
-ar6000_cookie_cleanup(AR_SOFTC_T *ar)
+ar6000_cookie_cleanup(struct ar6_softc *ar)
 {
     /* It is gone .... */
     ar->arCookieList = NULL;
@@ -5488,7 +5535,7 @@
 
 /* Init cookie queue */
 static void
-ar6000_free_cookie(AR_SOFTC_T *ar, struct ar_cookie * cookie)
+ar6000_free_cookie(struct ar6_softc *ar, struct ar_cookie * cookie)
 {
     /* Insert first */
     A_ASSERT(ar != NULL);
@@ -5501,7 +5548,7 @@
 
 /* cleanup cookie queue */
 static struct ar_cookie *
-ar6000_alloc_cookie(AR_SOFTC_T  *ar)
+ar6000_alloc_cookie(struct ar6_softc  *ar)
 {
     struct ar_cookie   *cookie;
 
@@ -5522,8 +5569,8 @@
  * the event ID and event content.
  */
 #define EVENT_ID_LEN   2
-void ar6000_send_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
-                              A_UINT8 *datap, int len)
+void ar6000_send_event_to_app(struct ar6_softc *ar, u16 eventId,
+                              u8 *datap, int len)
 {
 
 #if (WIRELESS_EXT >= 15)
@@ -5531,7 +5578,7 @@
 /* note: IWEVCUSTOM only exists in wireless extensions after version 15 */
 
     char *buf;
-    A_UINT16 size;
+    u16 size;
     union iwreq_data wrqu;
 
     size = len + EVENT_ID_LEN;
@@ -5549,10 +5596,10 @@
     }
 
     A_MEMZERO(buf, size);
-    A_MEMCPY(buf, &eventId, EVENT_ID_LEN);
-    A_MEMCPY(buf+EVENT_ID_LEN, datap, len);
+    memcpy(buf, &eventId, EVENT_ID_LEN);
+    memcpy(buf+EVENT_ID_LEN, datap, len);
 
-    //AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("event ID = %d,len = %d\n",*(A_UINT16*)buf, size));
+    //AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("event ID = %d,len = %d\n",*(u16 *)buf, size));
     A_MEMZERO(&wrqu, sizeof(wrqu));
     wrqu.data.length = size;
     wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
@@ -5567,8 +5614,8 @@
  * to the application. The buf which is sent to application
  * includes the event ID and event content.
  */
-void ar6000_send_generic_event_to_app(AR_SOFTC_T *ar, A_UINT16 eventId,
-                                      A_UINT8 *datap, int len)
+void ar6000_send_generic_event_to_app(struct ar6_softc *ar, u16 eventId,
+                                      u8 *datap, int len)
 {
 
 #if (WIRELESS_EXT >= 18)
@@ -5576,7 +5623,7 @@
 /* IWEVGENIE exists in wireless extensions version 18 onwards */
 
     char *buf;
-    A_UINT16 size;
+    u16 size;
     union iwreq_data wrqu;
 
     size = len + EVENT_ID_LEN;
@@ -5594,8 +5641,8 @@
     }
 
     A_MEMZERO(buf, size);
-    A_MEMCPY(buf, &eventId, EVENT_ID_LEN);
-    A_MEMCPY(buf+EVENT_ID_LEN, datap, len);
+    memcpy(buf, &eventId, EVENT_ID_LEN);
+    memcpy(buf+EVENT_ID_LEN, datap, len);
 
     A_MEMZERO(&wrqu, sizeof(wrqu));
     wrqu.data.length = size;
@@ -5616,54 +5663,52 @@
 }
 
 void
-ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, A_UINT8 snr)
+ar6000_snrThresholdEvent_rx(void *devt, WMI_SNR_THRESHOLD_VAL newThreshold, u8 snr)
 {
     WMI_SNR_THRESHOLD_EVENT event;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     event.range = newThreshold;
     event.snr = snr;
 
-    ar6000_send_event_to_app(ar, WMI_SNR_THRESHOLD_EVENTID, (A_UINT8 *)&event,
+    ar6000_send_event_to_app(ar, WMI_SNR_THRESHOLD_EVENTID, (u8 *)&event,
                              sizeof(WMI_SNR_THRESHOLD_EVENT));
 }
 
 void
-ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, A_UINT8 lq)
+ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL newThreshold, u8 lq)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("lq threshold range %d, lq %d\n", newThreshold, lq));
 }
 
 
 
-A_UINT32
-a_copy_to_user(void *to, const void *from, A_UINT32 n)
+u32 a_copy_to_user(void *to, const void *from, u32 n)
 {
     return(copy_to_user(to, from, n));
 }
 
-A_UINT32
-a_copy_from_user(void *to, const void *from, A_UINT32 n)
+u32 a_copy_from_user(void *to, const void *from, u32 n)
 {
     return(copy_from_user(to, from, n));
 }
 
 
-A_STATUS
+int
 ar6000_get_driver_cfg(struct net_device *dev,
-                        A_UINT16 cfgParam,
+                        u16 cfgParam,
                         void *result)
 {
 
-    A_STATUS    ret = 0;
+    int    ret = 0;
 
     switch(cfgParam)
     {
         case AR6000_DRIVER_CFG_GET_WLANNODECACHING:
-           *((A_UINT32 *)result) = wlanNodeCaching;
+           *((u32 *)result) = wlanNodeCaching;
            break;
         case AR6000_DRIVER_CFG_LOG_RAW_WMI_MSGS:
-           *((A_UINT32 *)result) = logWmiRawMsgs;
+           *((u32 *)result) = logWmiRawMsgs;
             break;
         default:
            ret = EINVAL;
@@ -5674,19 +5719,19 @@
 }
 
 void
-ar6000_keepalive_rx(void *devt, A_UINT8 configured)
+ar6000_keepalive_rx(void *devt, u8 configured)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
 
     ar->arKeepaliveConfigured = configured;
     wake_up(&arEvent);
 }
 
 void
-ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID, WMI_PMKID *pmkidList,
-                        A_UINT8 *bssidList)
+ar6000_pmkid_list_event(void *devt, u8 numPMKID, WMI_PMKID *pmkidList,
+                        u8 *bssidList)
 {
-    A_UINT8 i, j;
+    u8 i, j;
 
     A_PRINTF("Number of Cached PMKIDs is %d\n", numPMKID);
 
@@ -5700,15 +5745,15 @@
             for (j = 0; j < WMI_PMKID_LEN; j++) {
                 A_PRINTF("%2.2x", pmkidList->pmkid[j]);
             }
-        pmkidList = (WMI_PMKID *)((A_UINT8 *)pmkidList + ATH_MAC_LEN +
+        pmkidList = (WMI_PMKID *)((u8 *)pmkidList + ATH_MAC_LEN +
                                   WMI_PMKID_LEN);
     }
 }
 
-void ar6000_pspoll_event(AR_SOFTC_T *ar,A_UINT8 aid)
+void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid)
 {
     sta_t *conn=NULL;
-    A_BOOL isPsqEmpty = FALSE;
+    bool isPsqEmpty = false;
 
     conn = ieee80211_find_conn_for_aid(ar, aid);
 
@@ -5745,9 +5790,9 @@
     }
 }
 
-void ar6000_dtimexpiry_event(AR_SOFTC_T *ar)
+void ar6000_dtimexpiry_event(struct ar6_softc *ar)
 {
-    A_BOOL isMcastQueued = FALSE;
+    bool isMcastQueued = false;
     struct sk_buff *skb = NULL;
 
     /* If there are no associated STAs, ignore the DTIM expiry event.
@@ -5766,11 +5811,11 @@
     isMcastQueued = A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq);
     A_MUTEX_UNLOCK(&ar->mcastpsqLock);
 
-    A_ASSERT(isMcastQueued == FALSE);
+    A_ASSERT(isMcastQueued == false);
 
     /* Flush the mcast psq to the target */
     /* Set the STA flag to DTIMExpired, so that the frame will go out */
-    ar->DTIMExpired = TRUE;
+    ar->DTIMExpired = true;
 
     A_MUTEX_LOCK(&ar->mcastpsqLock);
     while (!A_NETBUF_QUEUE_EMPTY(&ar->mcastpsq)) {
@@ -5784,37 +5829,37 @@
     A_MUTEX_UNLOCK(&ar->mcastpsqLock);
 
     /* Reset the DTIMExpired flag back to 0 */
-    ar->DTIMExpired = FALSE;
+    ar->DTIMExpired = false;
 
     /* Clear the LSB of the BitMapCtl field of the TIM IE */
     wmi_set_pvb_cmd(ar->arWmi, MCAST_AID, 0);
 }
 
 void
-read_rssi_compensation_param(AR_SOFTC_T *ar)
+read_rssi_compensation_param(struct ar6_softc *ar)
 {
-    A_UINT8 *cust_data_ptr;
+    u8 *cust_data_ptr;
 
 //#define RSSICOMPENSATION_PRINT
 
 #ifdef RSSICOMPENSATION_PRINT
-    A_INT16 i;
+    s16 i;
     cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType);
     for (i=0; i<16; i++) {
-        A_PRINTF("cust_data_%d = %x \n", i, *(A_UINT8 *)cust_data_ptr);
+        A_PRINTF("cust_data_%d = %x \n", i, *(u8 *)cust_data_ptr);
         cust_data_ptr += 1;
     }
 #endif
 
     cust_data_ptr = ar6000_get_cust_data_buffer(ar->arTargetType);
 
-    rssi_compensation_param.customerID = *(A_UINT16 *)cust_data_ptr & 0xffff;
-    rssi_compensation_param.enable = *(A_UINT16 *)(cust_data_ptr+2) & 0xffff;
-    rssi_compensation_param.bg_param_a = *(A_UINT16 *)(cust_data_ptr+4) & 0xffff;
-    rssi_compensation_param.bg_param_b = *(A_UINT16 *)(cust_data_ptr+6) & 0xffff;
-    rssi_compensation_param.a_param_a = *(A_UINT16 *)(cust_data_ptr+8) & 0xffff;
-    rssi_compensation_param.a_param_b = *(A_UINT16 *)(cust_data_ptr+10) &0xffff;
-    rssi_compensation_param.reserved = *(A_UINT32 *)(cust_data_ptr+12);
+    rssi_compensation_param.customerID = *(u16 *)cust_data_ptr & 0xffff;
+    rssi_compensation_param.enable = *(u16 *)(cust_data_ptr+2) & 0xffff;
+    rssi_compensation_param.bg_param_a = *(u16 *)(cust_data_ptr+4) & 0xffff;
+    rssi_compensation_param.bg_param_b = *(u16 *)(cust_data_ptr+6) & 0xffff;
+    rssi_compensation_param.a_param_a = *(u16 *)(cust_data_ptr+8) & 0xffff;
+    rssi_compensation_param.a_param_b = *(u16 *)(cust_data_ptr+10) &0xffff;
+    rssi_compensation_param.reserved = *(u32 *)(cust_data_ptr+12);
 
 #ifdef RSSICOMPENSATION_PRINT
     A_PRINTF("customerID = 0x%x \n", rssi_compensation_param.customerID);
@@ -5833,8 +5878,7 @@
    return;
 }
 
-A_INT32
-rssi_compensation_calc_tcmd(A_UINT32 freq, A_INT32 rssi, A_UINT32 totalPkt)
+s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt)
 {
 
     if (freq > 5000)
@@ -5863,8 +5907,7 @@
     return rssi;
 }
 
-A_INT16
-rssi_compensation_calc(AR_SOFTC_T *ar, A_INT16 rssi)
+s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi)
 {
     if (ar->arBssChannel > 5000)
     {
@@ -5892,10 +5935,9 @@
     return rssi;
 }
 
-A_INT16
-rssi_compensation_reverse_calc(AR_SOFTC_T *ar, A_INT16 rssi, A_BOOL Above)
+s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above)
 {
-    A_INT16 i;
+    s16 i;
 
     if (ar->arBssChannel > 5000)
     {
@@ -5938,16 +5980,16 @@
 }
 
 #ifdef WAPI_ENABLE
-void ap_wapi_rekey_event(AR_SOFTC_T *ar, A_UINT8 type, A_UINT8 *mac)
+void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac)
 {
     union iwreq_data wrqu;
-    A_CHAR buf[20];
+    char buf[20];
 
     A_MEMZERO(buf, sizeof(buf));
 
     strcpy(buf, "WAPI_REKEY");
     buf[10] = type;
-    A_MEMCPY(&buf[11], mac, ATH_MAC_LEN);
+    memcpy(&buf[11], mac, ATH_MAC_LEN);
 
     A_MEMZERO(&wrqu, sizeof(wrqu));
     wrqu.data.length = 10+1+ATH_MAC_LEN;
@@ -5958,11 +6000,11 @@
 #endif
 
 #ifdef USER_KEYS
-static A_STATUS
+static int
 
-ar6000_reinstall_keys(AR_SOFTC_T *ar, A_UINT8 key_op_ctrl)
+ar6000_reinstall_keys(struct ar6_softc *ar, u8 key_op_ctrl)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
     struct ieee80211req_key *uik = &ar->user_saved_keys.ucast_ik;
     struct ieee80211req_key *bik = &ar->user_saved_keys.bcast_ik;
     CRYPTO_TYPE  keyType = ar->user_saved_keys.keyType;
@@ -5975,7 +6017,7 @@
         if (uik->ik_keylen) {
             status = wmi_addKey_cmd(ar->arWmi, uik->ik_keyix,
                     ar->user_saved_keys.keyType, PAIRWISE_USAGE,
-                    uik->ik_keylen, (A_UINT8 *)&uik->ik_keyrsc,
+                    uik->ik_keylen, (u8 *)&uik->ik_keyrsc,
                     uik->ik_keydata, key_op_ctrl, uik->ik_macaddr, SYNC_BEFORE_WMIFLAG);
         }
 
@@ -5991,7 +6033,7 @@
         if (bik->ik_keylen) {
             status = wmi_addKey_cmd(ar->arWmi, bik->ik_keyix,
                     ar->user_saved_keys.keyType, GROUP_USAGE,
-                    bik->ik_keylen, (A_UINT8 *)&bik->ik_keyrsc,
+                    bik->ik_keylen, (u8 *)&bik->ik_keyrsc,
                     bik->ik_keydata, key_op_ctrl, bik->ik_macaddr, NO_SYNC_WMIFLAG);
         }
     } else {
@@ -6010,17 +6052,17 @@
 void
 ar6000_dset_open_req(
     void *context,
-    A_UINT32 id,
-    A_UINT32 targHandle,
-    A_UINT32 targReplyFn,
-    A_UINT32 targReplyArg)
+    u32 id,
+    u32 targHandle,
+    u32 targReplyFn,
+    u32 targReplyArg)
 {
 }
 
 void
 ar6000_dset_close(
     void *context,
-    A_UINT32 access_cookie)
+    u32 access_cookie)
 {
     return;
 }
@@ -6028,12 +6070,12 @@
 void
 ar6000_dset_data_req(
    void *context,
-   A_UINT32 accessCookie,
-   A_UINT32 offset,
-   A_UINT32 length,
-   A_UINT32 targBuf,
-   A_UINT32 targReplyFn,
-   A_UINT32 targReplyArg)
+   u32 accessCookie,
+   u32 offset,
+   u32 length,
+   u32 targBuf,
+   u32 targReplyFn,
+   u32 targReplyArg)
 {
 }
 
@@ -6079,7 +6121,7 @@
 
     A_MEMZERO(&p,sizeof(p));
     p.ssidLength = ar->arSsidLen;
-    A_MEMCPY(p.ssid,ar->arSsid,p.ssidLength);
+    memcpy(p.ssid,ar->arSsid,p.ssidLength);
     p.channel = ar->arChannelHint;
     p.networkType = ar->arNetworkType;
 
@@ -6091,26 +6133,24 @@
     p.groupCryptoLen = ar->arGroupCryptoLen;
     p.ctrl_flags = ar->arConnectCtrlFlags;
 
-    ar->arConnected = FALSE;
-
     wmi_ap_profile_commit(ar->arWmi, &p);
     spin_lock_irqsave(&ar->arLock, flags);
-    ar->arConnected  = TRUE;
+    ar->arConnected  = true;
     netif_carrier_on(ar->arNetDev);
     spin_unlock_irqrestore(&ar->arLock, flags);
     ar->ap_profile_flag = 0;
     return 0;
 }
 
-A_STATUS
+int
 ar6000_connect_to_ap(struct ar6_softc *ar)
 {
     /* The ssid length check prevents second "essid off" from the user,
        to be treated as a connect cmd. The second "essid off" is ignored.
     */
-    if((ar->arWmiReady == TRUE) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK)
+    if((ar->arWmiReady == true) && (ar->arSsidLen > 0) && ar->arNetworkType!=AP_NETWORK)
     {
-        A_STATUS status;
+        int status;
         if((ADHOC_NETWORK != ar->arNetworkType) &&
            (NONE_AUTH==ar->arAuthMode)          &&
            (WEP_CRYPT==ar->arPairwiseCrypto)) {
@@ -6118,7 +6158,7 @@
         }
 
         if (!ar->arUserBssFilter) {
-            if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
+            if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
                 return -EIO;
             }
         }
@@ -6142,7 +6182,7 @@
         /* Set the listen interval into 1000TUs or more. This value will be indicated to Ap in the conn.
            later set it back locally at the STA to 100/1000 TUs depending on the power mode */
         if ((ar->arNetworkType == INFRA_NETWORK)) {
-            wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (A_UINT16)A_MAX_WOW_LISTEN_INTERVAL), 0);
+            wmi_listeninterval_cmd(ar->arWmi, max(ar->arListenIntervalT, (u16)A_MAX_WOW_LISTEN_INTERVAL), 0);
         }
         status = wmi_connect_cmd(ar->arWmi, ar->arNetworkType,
                                  ar->arDot11AuthMode, ar->arAuthMode,
@@ -6151,7 +6191,7 @@
                                  ar->arSsidLen, ar->arSsid,
                                  ar->arReqBssid, ar->arChannelHint,
                                  ar->arConnectCtrlFlags);
-        if (status != A_OK) {
+        if (status) {
             wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB);
             if (!ar->arUserBssFilter) {
                 wmi_bssfilter_cmd(ar->arWmi, NONE_BSS_FILTER, 0);
@@ -6167,13 +6207,28 @@
 
         ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
         
-        ar->arConnectPending = TRUE;
+        ar->arConnectPending = true;
         return status;    
     }
     return A_ERROR;
 }
 
-A_STATUS
+int
+ar6000_disconnect(struct ar6_softc *ar)
+{
+    if ((ar->arConnected == true) || (ar->arConnectPending == true)) {
+        wmi_disconnect_cmd(ar->arWmi);
+        /* 
+         * Disconnect cmd is issued, clear connectPending.
+         * arConnected will be cleard in disconnect_event notification.
+         */
+        ar->arConnectPending = false;
+    }
+
+    return 0;
+}
+
+int
 ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie)
 {
     sta_t *conn = NULL;
@@ -6183,38 +6238,38 @@
     A_MEMZERO(wpaie->rsn_ie, IEEE80211_MAX_IE);
 
     if(conn) {
-        A_MEMCPY(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE);
+        memcpy(wpaie->wpa_ie, conn->wpa_ie, IEEE80211_MAX_IE);
     }
 
     return 0;
 }
 
-A_STATUS
-is_iwioctl_allowed(A_UINT8 mode, A_UINT16 cmd)
+int
+is_iwioctl_allowed(u8 mode, u16 cmd)
 {
     if(cmd >= SIOCSIWCOMMIT && cmd <= SIOCGIWPOWER) {
         cmd -= SIOCSIWCOMMIT;
-        if(sioctl_filter[cmd] == 0xFF) return A_OK;
-        if(sioctl_filter[cmd] & mode) return A_OK;
+        if(sioctl_filter[cmd] == 0xFF) return 0;
+        if(sioctl_filter[cmd] & mode) return 0;
     } else if(cmd >= SIOCIWFIRSTPRIV && cmd <= (SIOCIWFIRSTPRIV+30)) {
         cmd -= SIOCIWFIRSTPRIV;
-        if(pioctl_filter[cmd] == 0xFF) return A_OK;
-        if(pioctl_filter[cmd] & mode) return A_OK;
+        if(pioctl_filter[cmd] == 0xFF) return 0;
+        if(pioctl_filter[cmd] & mode) return 0;
     } else {
         return A_ERROR;
     }
     return A_ENOTSUP;
 }
 
-A_STATUS
-is_xioctl_allowed(A_UINT8 mode, int cmd)
+int
+is_xioctl_allowed(u8 mode, int cmd)
 {
     if(sizeof(xioctl_filter)-1 < cmd) {
         A_PRINTF("Filter for this cmd=%d not defined\n",cmd);
         return 0;
     }
-    if(xioctl_filter[cmd] == 0xFF) return A_OK;
-    if(xioctl_filter[cmd] & mode) return A_OK;
+    if(xioctl_filter[cmd] == 0xFF) return 0;
+    if(xioctl_filter[cmd] & mode) return 0;
     return A_ERROR;
 }
 
@@ -6224,9 +6279,9 @@
 {
     struct ieee80211req_key *ik = (struct ieee80211req_key *)ikey;
     KEY_USAGE   keyUsage = 0;
-    A_STATUS    status;
+    int    status;
 
-    if (A_MEMCMP(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) {
+    if (memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN) == 0) {
         keyUsage = GROUP_USAGE;
     } else {
         keyUsage = PAIRWISE_USAGE;
@@ -6236,11 +6291,11 @@
         ik->ik_keylen);
 
     status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, WAPI_CRYPT, keyUsage,
-                            ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
+                            ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
                             ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
                             SYNC_BOTH_WMIFLAG);
 
-    if (A_OK != status) {
+    if (0 != status) {
         return -EIO;
     }
     return 0;
@@ -6249,10 +6304,10 @@
 
 void ar6000_peer_event(
     void *context,
-    A_UINT8 eventCode,
-    A_UINT8 *macAddr)
+    u8 eventCode,
+    u8 *macAddr)
 {
-    A_UINT8 pos;
+    u8 pos;
 
     for (pos=0;pos<6;pos++)
         printk("%02x: ",*(macAddr+pos));
@@ -6261,14 +6316,14 @@
 
 #ifdef HTC_TEST_SEND_PKTS
 #define HTC_TEST_DUPLICATE 8
-static void DoHTCSendPktsTest(AR_SOFTC_T *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb)
+static void DoHTCSendPktsTest(struct ar6_softc *ar, int MapNo, HTC_ENDPOINT_ID eid, struct sk_buff *dupskb)
 {
     struct ar_cookie *cookie;
     struct ar_cookie *cookieArray[HTC_TEST_DUPLICATE];
     struct sk_buff   *new_skb;
     int    i;
     int    pkts = 0;
-    HTC_PACKET_QUEUE pktQueue;
+    struct htc_packet_queue pktQueue;
     EPPING_HEADER    *eppingHdr;
 
     eppingHdr = A_NETBUF_DATA(dupskb);
@@ -6338,44 +6393,44 @@
 /*
  * Add support for adding and removing a virtual adapter for soft AP.
  * Some OS requires different adapters names for station and soft AP mode.
- * To support these requirement, create and destory a netdevice  instance
+ * To support these requirement, create and destroy a netdevice  instance
  * when the AP mode is operational. A full fledged support for virual device
  * is not implemented. Rather a virtual interface is created and is linked
  * with the existing physical device instance during the operation of the 
  * AP mode.
  */
 
-A_STATUS ar6000_start_ap_interface(AR_SOFTC_T *ar)
+int ar6000_start_ap_interface(struct ar6_softc *ar)
 {
-    AR_VIRTUAL_INTERFACE_T *arApDev;
+    struct ar_virtual_interface *arApDev;
 
     /* Change net_device to point to AP instance */
-    arApDev = (AR_VIRTUAL_INTERFACE_T *)ar->arApDev;
+    arApDev = (struct ar_virtual_interface *)ar->arApDev;
     ar->arNetDev = arApDev->arNetDev;
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS ar6000_stop_ap_interface(AR_SOFTC_T *ar)
+int ar6000_stop_ap_interface(struct ar6_softc *ar)
 {
-    AR_VIRTUAL_INTERFACE_T *arApDev;
+    struct ar_virtual_interface *arApDev;
 
     /* Change net_device to point to sta instance */
-    arApDev = (AR_VIRTUAL_INTERFACE_T *)ar->arApDev;
+    arApDev = (struct ar_virtual_interface *)ar->arApDev;
     if (arApDev) {
         ar->arNetDev = arApDev->arStaNetDev;
     }
 
-    return A_OK;
+    return 0;
 }
 
 
-A_STATUS ar6000_create_ap_interface(AR_SOFTC_T *ar, char *ap_ifname) 
+int ar6000_create_ap_interface(struct ar6_softc *ar, char *ap_ifname)
 {
     struct net_device *dev;
-    AR_VIRTUAL_INTERFACE_T *arApDev;
+    struct ar_virtual_interface *arApDev;
 
-    dev = alloc_etherdev(sizeof(AR_VIRTUAL_INTERFACE_T));
+    dev = alloc_etherdev(sizeof(struct ar_virtual_interface));
     if (dev == NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_create_ap_interface: can't alloc etherdev\n"));
         return A_ERROR;
@@ -6398,20 +6453,20 @@
     arApNetDev = dev;
 
     /* Copy the MAC address */
-    A_MEMCPY(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN);
+    memcpy(dev->dev_addr, ar->arNetDev->dev_addr, AR6000_ETH_ADDR_LEN);
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS ar6000_add_ap_interface(AR_SOFTC_T *ar, char *ap_ifname) 
+int ar6000_add_ap_interface(struct ar6_softc *ar, char *ap_ifname)
 {
     /* Interface already added, need not proceed further */
     if (ar->arApDev != NULL) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000_add_ap_interface: interface already present \n"));
-        return A_OK;
+        return 0;
     }
 
-    if (ar6000_create_ap_interface(ar, ap_ifname) != A_OK) {
+    if (ar6000_create_ap_interface(ar, ap_ifname) != 0) {
         return A_ERROR;
     }
 
@@ -6420,7 +6475,7 @@
     return ar6000_start_ap_interface(ar);
 }
 
-A_STATUS ar6000_remove_ap_interface(AR_SOFTC_T *ar)
+int ar6000_remove_ap_interface(struct ar6_softc *ar)
 {
     if (arApNetDev) {
         ar6000_stop_ap_interface(ar);
@@ -6434,7 +6489,7 @@
     arApNetDev = NULL;
 
     
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_pm.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_pm.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_pm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_pm.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,32 +30,21 @@
 #include <linux/platform_device.h>
 #include "wlan_config.h"
 
-#ifdef CONFIG_HAS_WAKELOCK
-#include <linux/wakelock.h>
-#endif
-
 #define WOW_ENABLE_MAX_INTERVAL 0
 #define WOW_SET_SCAN_PARAMS     0
 
 extern unsigned int wmitimeout;
 extern wait_queue_head_t arEvent;
 
-#ifdef CONFIG_PM
-#ifdef CONFIG_HAS_WAKELOCK
-struct wake_lock ar6k_suspend_wake_lock;
-struct wake_lock ar6k_wow_wake_lock;
-#endif
-#endif /* CONFIG_PM */
-
 #ifdef ANDROID_ENV
-extern void android_ar6k_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent);
+extern void android_ar6k_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent);
 #endif
 #undef ATH_MODULE_NAME
 #define ATH_MODULE_NAME pm
 #define  ATH_DEBUG_PM       ATH_DEBUG_MAKE_MODULE_MASK(0)
 
 #ifdef DEBUG
-static ATH_DEBUG_MASK_DESCRIPTION pm_debug_desc[] = {
+static struct ath_debug_mask_description pm_debug_desc[] = {
     { ATH_DEBUG_PM     , "System power management"},
 };
 
@@ -68,10 +57,10 @@
 
 #endif /* DEBUG */
 
-A_STATUS ar6000_exit_cut_power_state(AR_SOFTC_T *ar);
+int ar6000_exit_cut_power_state(struct ar6_softc *ar);
 
 #ifdef CONFIG_PM
-static void ar6k_send_asleep_event_to_app(AR_SOFTC_T *ar, A_BOOL asleep)
+static void ar6k_send_asleep_event_to_app(struct ar6_softc *ar, bool asleep)
 {
     char buf[128];
     union iwreq_data wrqu;
@@ -82,17 +71,14 @@
     wireless_send_event(ar->arNetDev, IWEVCUSTOM, &wrqu, buf);
 }
 
-static void ar6000_wow_resume(AR_SOFTC_T *ar)
+static void ar6000_wow_resume(struct ar6_softc *ar)
 {
     if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
-        A_UINT16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
-        A_UINT16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period;
-        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {TRUE, FALSE};
+        u16 fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
+        u16 bg_period = (ar->scParams.bg_period==0) ? 60 : ar->scParams.bg_period;
+        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {true, false};
         ar->arWowState = WLAN_WOW_STATE_NONE;
-#ifdef CONFIG_HAS_WAKELOCK
-        wake_lock_timeout(&ar6k_wow_wake_lock, 3*HZ);
-#endif
-        if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!=A_OK) {
+        if (wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)!= 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup restore host awake\n"));
         }
 #if WOW_SET_SCAN_PARAMS
@@ -113,10 +99,10 @@
 
 
 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
-        if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == A_OK) {
+        if (wmi_listeninterval_cmd(ar->arWmi, ar->arListenIntervalT, ar->arListenIntervalB) == 0) {
         }
 #endif
-        ar6k_send_asleep_event_to_app(ar, FALSE);
+        ar6k_send_asleep_event_to_app(ar, false);
         AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Resume WoW successfully\n"));
     } else {
         AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("WoW does not invoked. skip resume"));
@@ -124,7 +110,7 @@
     ar->arWlanPowerState = WLAN_POWER_STATE_ON;
 }
 
-static void ar6000_wow_suspend(AR_SOFTC_T *ar)
+static void ar6000_wow_suspend(struct ar6_softc *ar)
 {
 #define WOW_LIST_ID 1
     if (ar->arNetworkType != AP_NETWORK) {
@@ -135,12 +121,12 @@
         struct in_ifaddr **ifap = NULL;
         struct in_ifaddr *ifa = NULL;
         struct in_device *in_dev;
-        A_UINT8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-        A_STATUS status;
+        u8 macMask[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
+        int status;
         WMI_ADD_WOW_PATTERN_CMD addWowCmd = { .filter = { 0 } };
         WMI_DEL_WOW_PATTERN_CMD delWowCmd;
-        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {FALSE, TRUE};
-        WMI_SET_WOW_MODE_CMD wowMode = {    .enable_wow = TRUE,
+        WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode = {false, true};
+        WMI_SET_WOW_MODE_CMD wowMode = {    .enable_wow = true,
                                             .hostReqDelay = 500 };/*500 ms delay*/
 
         if (ar->arWowState!= WLAN_WOW_STATE_NONE) {
@@ -151,7 +137,7 @@
         ar6000_TxDataCleanup(ar); /* IMPORTANT, otherwise there will be 11mA after listen interval as 1000*/
 
 #if WOW_ENABLE_MAX_INTERVAL /* we don't do it if the power consumption is already good enough. */
-        if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == A_OK) {
+        if (wmi_listeninterval_cmd(ar->arWmi, A_MAX_WOW_LISTEN_INTERVAL, 0) == 0) {
         }
 #endif
 
@@ -169,7 +155,7 @@
             addWowCmd.filter_size = 6; /* MAC address */
             addWowCmd.filter_offset = 0;
             status = wmi_add_wow_pattern_cmd(ar->arWmi, &addWowCmd, ar->arNetDev->dev_addr, macMask, addWowCmd.filter_size);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to add WoW pattern\n"));
             }
         }
@@ -186,7 +172,7 @@
             memset(&ipCmd, 0, sizeof(ipCmd));
             ipCmd.ips[0] = ifa->ifa_local;
             status = wmi_set_ip_cmd(ar->arWmi, &ipCmd);
-            if (status != A_OK) {
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup IP for ARP agent\n"));
             }
         }
@@ -196,19 +182,19 @@
 #endif
 
         status = wmi_set_wow_mode_cmd(ar->arWmi, &wowMode);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enable wow mode\n"));
         }
-        ar6k_send_asleep_event_to_app(ar, TRUE);
+        ar6k_send_asleep_event_to_app(ar, true);
 
         status = wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to set host asleep\n"));
         }
 
         ar->arWowState = WLAN_WOW_STATE_SUSPENDING;
         if (ar->arTxPending[ar->arControlEp]) {
-            A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
+            u32 timeleft = wait_event_interruptible_timeout(arEvent,
             ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
             if (!timeleft || signal_pending(current)) {
                /* what can I do? wow resume at once */
@@ -225,11 +211,11 @@
     }
 }
 
-A_STATUS ar6000_suspend_ev(void *context)
+int ar6000_suspend_ev(void *context)
 {
-    A_STATUS status = A_OK;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
-    A_INT16 pmmode = ar->arSuspendConfig;
+    int status = 0;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
+    s16 pmmode = ar->arSuspendConfig;
 wow_not_connected:
     switch (pmmode) {
     case WLAN_SUSPEND_WOW:
@@ -248,13 +234,13 @@
     case WLAN_SUSPEND_DEEP_SLEEP:
         /* fall through */
     default:
-        status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, TRUE);
+        status = ar6000_update_wlan_pwr_state(ar, WLAN_DISABLED, true);
         if (ar->arWlanPowerState==WLAN_POWER_STATE_ON ||
             ar->arWlanPowerState==WLAN_POWER_STATE_WOW) {
             AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("Strange suspend state for not wow mode %d", ar->arWlanPowerState));
         }
         AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Suspend for %d mode pwr %d status %d\n", __func__, pmmode, ar->arWlanPowerState, status));
-        status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? A_OK : A_EBUSY;
+        status = (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) ? 0 : A_EBUSY;
         break;
     }
 
@@ -262,14 +248,11 @@
     return status;
 }
 
-A_STATUS ar6000_resume_ev(void *context)
+int ar6000_resume_ev(void *context)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
-    A_UINT16 powerState = ar->arWlanPowerState;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
+    u16 powerState = ar->arWlanPowerState;
 
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock(&ar6k_suspend_wake_lock);
-#endif
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: enter previous state %d wowState %d\n", __func__, powerState, ar->arWowState));
     switch (powerState) {
     case WLAN_POWER_STATE_WOW:
@@ -278,7 +261,7 @@
     case WLAN_POWER_STATE_CUT_PWR:
         /* fall through */
     case WLAN_POWER_STATE_DEEP_SLEEP:
-        ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, TRUE);
+        ar6000_update_wlan_pwr_state(ar, WLAN_ENABLED, true);
         AR_DEBUG_PRINTF(ATH_DEBUG_PM,("%s:Resume for %d mode pwr %d\n", __func__, powerState, ar->arWlanPowerState));
         break;
     case WLAN_POWER_STATE_ON:
@@ -287,13 +270,10 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Strange SDIO bus power mode!!\n"));
         break;
     }
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_unlock(&ar6k_suspend_wake_lock);
-#endif
-    return A_OK;
+    return 0;
 }
 
-void ar6000_check_wow_status(AR_SOFTC_T *ar, struct sk_buff *skb, A_BOOL isEvent)
+void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent)
 {
     if (ar->arWowState!=WLAN_WOW_STATE_NONE) {
         if (ar->arWowState==WLAN_WOW_STATE_SUSPENDING) {
@@ -310,20 +290,20 @@
     }
 }
 
-A_STATUS ar6000_power_change_ev(void *context, A_UINT32 config)
+int ar6000_power_change_ev(void *context, u32 config)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)context;
-    A_STATUS status = A_OK;
+    struct ar6_softc *ar = (struct ar6_softc *)context;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: power change event callback %d \n", __func__, config));
     switch (config) {
        case HIF_DEVICE_POWER_UP:
             ar6000_restart_endpoint(ar->arNetDev);
-            status = A_OK;
+            status = 0;
             break;
        case HIF_DEVICE_POWER_DOWN:
        case HIF_DEVICE_POWER_CUT:
-            status = A_OK;
+            status = 0;
             break;
     }
     return status;
@@ -362,10 +342,10 @@
 };
 #endif /* CONFIG_PM */
 
-A_STATUS
+int
 ar6000_setup_cut_power_state(struct ar6_softc *ar,  AR6000_WLAN_STATE state)
 {
-    A_STATUS                      status = A_OK;
+    int                      status = 0;
     HIF_DEVICE_POWER_CHANGE_TYPE  config;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Cut power %d %d \n", __func__,state, ar->arWlanPowerState));
@@ -395,18 +375,18 @@
             if (status == A_PENDING) {
 #ifdef ANDROID_ENV
                  /* Wait for WMI ready event */
-                A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
-                            (ar->arWmiReady == TRUE), wmitimeout * HZ);
+                u32 timeleft = wait_event_interruptible_timeout(arEvent,
+                            (ar->arWmiReady == true), wmitimeout * HZ);
                 if (!timeleft || signal_pending(current)) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("ar6000 : Failed to get wmi ready \n"));
                     status = A_ERROR;
                     break;
                 }
 #endif
-                status = A_OK;
-            } else if (status == A_OK) {
+                status = 0;
+            } else if (status == 0) {
                 ar6000_restart_endpoint(ar->arNetDev);
-                status = A_OK;
+                status = 0;
             }
         } else if (state == WLAN_DISABLED) {
 
@@ -415,7 +395,7 @@
             if (ar->arWlanPowerState == WLAN_POWER_STATE_CUT_PWR) {
                 break;
             }
-            ar6000_stop_endpoint(ar->arNetDev, TRUE, FALSE);
+            ar6000_stop_endpoint(ar->arNetDev, true, false);
 
             config = HIF_DEVICE_POWER_CUT;
             status = HIFConfigureDevice(ar->arHifDevice,
@@ -432,10 +412,10 @@
     return status;
 }
 
-A_STATUS
+int
 ar6000_setup_deep_sleep_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
 {
-    A_STATUS status = A_OK;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("%s: Deep sleep %d %d \n", __func__,state, ar->arWlanPowerState));
 #ifdef CONFIG_PM
@@ -445,7 +425,7 @@
         WMI_SET_HOST_SLEEP_MODE_CMD hostSleepMode;
 
         if (state == WLAN_ENABLED) {
-            A_UINT16 fg_start_period;
+            u16 fg_start_period;
 
             /* Not in deep sleep state.. exit */
             if (ar->arWlanPowerState != WLAN_POWER_STATE_DEEP_SLEEP) {
@@ -456,10 +436,10 @@
             }
 
             fg_start_period = (ar->scParams.fg_start_period==0) ? 1 : ar->scParams.fg_start_period;
-            hostSleepMode.awake = TRUE;
-            hostSleepMode.asleep = FALSE;
+            hostSleepMode.awake = true;
+            hostSleepMode.asleep = false;
 
-            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != A_OK) {
+            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode)) != 0) {
                 break;
             }
 
@@ -476,7 +456,7 @@
                                         ar->scParams.shortScanRatio,
                                         ar->scParams.scanCtrlFlags,
                                         ar->scParams.max_dfsch_act_time,
-                                        ar->scParams.maxact_scan_per_ssid)) != A_OK)
+                                        ar->scParams.maxact_scan_per_ssid)) != 0)
                 {
                     break;
                 }
@@ -484,14 +464,14 @@
             if (ar->arNetworkType != AP_NETWORK)
             {
                 if (ar->arSsidLen) {
-                    if (ar6000_connect_to_ap(ar) != A_OK) {
+                    if (ar6000_connect_to_ap(ar) != 0) {
                         /* no need to report error if connection failed */
                         break;
                     }
                 }
             }
         } else if (state == WLAN_DISABLED){
-            WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = FALSE };
+            WMI_SET_WOW_MODE_CMD wowMode = { .enable_wow = false };
 
             /* Already in deep sleep state.. exit */
             if (ar->arWlanPowerState != WLAN_POWER_STATE_ON) {
@@ -505,7 +485,7 @@
             {
                 /* Disconnect from the AP and disable foreground scanning */
                 AR6000_SPIN_LOCK(&ar->arLock, 0);
-                if (ar->arConnected == TRUE || ar->arConnectPending == TRUE) {
+                if (ar->arConnected == true || ar->arConnectPending == true) {
                     AR6000_SPIN_UNLOCK(&ar->arLock, 0);
                     wmi_disconnect_cmd(ar->arWmi);
                 } else {
@@ -515,12 +495,12 @@
 
             ar->scan_triggered = 0;
 
-            if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != A_OK) {
+            if ((status=wmi_scanparams_cmd(ar->arWmi, 0xFFFF, 0, 0, 0, 0, 0, 0, 0, 0, 0)) != 0) {
                 break;
             }
 
             /* make sure we disable wow for deep sleep */
-            if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!=A_OK)
+            if ((status=wmi_set_wow_mode_cmd(ar->arWmi, &wowMode))!= 0)
             {
                 break;
             }
@@ -530,13 +510,13 @@
             wmi_powermode_cmd(ar->arWmi, REC_POWER);
 #endif
 
-            hostSleepMode.awake = FALSE;
-            hostSleepMode.asleep = TRUE;
-            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!=A_OK) {
+            hostSleepMode.awake = false;
+            hostSleepMode.asleep = true;
+            if ((status=wmi_set_host_sleep_mode_cmd(ar->arWmi, &hostSleepMode))!= 0) {
                 break;
             }
             if (ar->arTxPending[ar->arControlEp]) {
-                A_UINT32 timeleft = wait_event_interruptible_timeout(arEvent,
+                u32 timeleft = wait_event_interruptible_timeout(arEvent,
                                 ar->arTxPending[ar->arControlEp] == 0, wmitimeout * HZ);
                 if (!timeleft || signal_pending(current)) {
                     status = A_ERROR;
@@ -549,22 +529,22 @@
         }
     } while (0);
 
-    if (status!=A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to enter/exit deep sleep %d\n", state));
     }
 
     return status;
 }
 
-A_STATUS
-ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BOOL pmEvent)
+int
+ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool pmEvent)
 {
-    A_STATUS status = A_OK;
-    A_UINT16 powerState, oldPowerState;
+    int status = 0;
+    u16 powerState, oldPowerState;
     AR6000_WLAN_STATE oldstate = ar->arWlanState;
-    A_BOOL wlanOff = ar->arWlanOff;
+    bool wlanOff = ar->arWlanOff;
 #ifdef CONFIG_PM
-    A_BOOL btOff = ar->arBTOff;
+    bool btOff = ar->arBTOff;
 #endif /* CONFIG_PM */
 
     if ((state!=WLAN_DISABLED && state!=WLAN_ENABLED)) {
@@ -598,7 +578,7 @@
         }
 #ifdef CONFIG_PM
         else if (pmEvent && wlanOff) {
-            A_BOOL allowCutPwr = ((!ar->arBTSharing) || btOff);
+            bool allowCutPwr = ((!ar->arBTSharing) || btOff);
             if ((powerState==WLAN_POWER_STATE_CUT_PWR) && (!allowCutPwr)) {
                 /* Come out of cut power */
                 ar6000_setup_cut_power_state(ar, WLAN_ENABLED);
@@ -611,10 +591,10 @@
         powerState = WLAN_POWER_STATE_DEEP_SLEEP;
 #ifdef CONFIG_PM
         if (pmEvent) {  /* disable due to suspend */
-            A_BOOL suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR ||
+            bool suspendCutPwr = (ar->arSuspendConfig == WLAN_SUSPEND_CUT_PWR ||
                                     (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
                                         ar->arWow2Config==WLAN_SUSPEND_CUT_PWR));
-            A_BOOL suspendCutIfBtOff = ((ar->arSuspendConfig ==
+            bool suspendCutIfBtOff = ((ar->arSuspendConfig ==
                                             WLAN_SUSPEND_CUT_PWR_IF_BT_OFF ||
                                         (ar->arSuspendConfig == WLAN_SUSPEND_WOW &&
                                          ar->arWow2Config==WLAN_SUSPEND_CUT_PWR_IF_BT_OFF)) &&
@@ -648,10 +628,10 @@
 
     }
 
-    if (status!=A_OK) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Fail to setup WLAN state %d\n", ar->arWlanState));
         ar->arWlanState = oldstate;
-    } else if (status == A_OK) {
+    } else if (status == 0) {
         WMI_REPORT_SLEEP_STATE_EVENT  wmiSleepEvent, *pSleepEvent = NULL;
         if ((ar->arWlanPowerState == WLAN_POWER_STATE_ON) && (oldPowerState != WLAN_POWER_STATE_ON)) {
             wmiSleepEvent.sleepState = WMI_REPORT_SLEEP_STATUS_IS_AWAKE;
@@ -662,7 +642,7 @@
         }
         if (pSleepEvent) {
             AR_DEBUG_PRINTF(ATH_DEBUG_PM, ("SENT WLAN Sleep Event %d\n", wmiSleepEvent.sleepState));
-            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)pSleepEvent,
+            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (u8 *)pSleepEvent,
                                      sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
         }
     }
@@ -670,33 +650,33 @@
     return status;
 }
 
-A_STATUS
-ar6000_set_bt_hw_state(struct ar6_softc *ar, A_UINT32 enable)
+int
+ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 enable)
 {
 #ifdef CONFIG_PM
-    A_BOOL off = (enable == 0);
-    A_STATUS status;
+    bool off = (enable == 0);
+    int status;
     if (ar->arBTOff == off) {
-        return A_OK;
+        return 0;
     }
     ar->arBTOff = off;
-    status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, FALSE);
+    status = ar6000_update_wlan_pwr_state(ar, ar->arWlanOff ? WLAN_DISABLED : WLAN_ENABLED, false);
     return status;
 #else
-    return A_OK;
+    return 0;
 #endif
 }
 
-A_STATUS
+int
 ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state)
 {
-    A_STATUS status;
-    A_BOOL off = (state == WLAN_DISABLED);
+    int status;
+    bool off = (state == WLAN_DISABLED);
     if (ar->arWlanOff == off) {
-        return A_OK;
+        return 0;
     }
     ar->arWlanOff = off;
-    status = ar6000_update_wlan_pwr_state(ar, state, FALSE);
+    status = ar6000_update_wlan_pwr_state(ar, state, false);
     return status;
 }
 
@@ -704,10 +684,6 @@
 {
     A_REGISTER_MODULE_DEBUG_INFO(pm);
 #ifdef CONFIG_PM
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_init(&ar6k_suspend_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_suspend");
-    wake_lock_init(&ar6k_wow_wake_lock, WAKE_LOCK_SUSPEND, "ar6k_wow");
-#endif
     /*
      * Register ar6000_pm_device into system.
      * We should also add platform_device into the first item of array
@@ -723,9 +699,5 @@
 {
 #ifdef CONFIG_PM
     platform_driver_unregister(&ar6000_pm_device);
-#ifdef CONFIG_HAS_WAKELOCK
-    wake_lock_destroy(&ar6k_suspend_wake_lock);
-    wake_lock_destroy(&ar6k_wow_wake_lock);
-#endif
 #endif /* CONFIG_PM */
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6000_raw_if.c	2011-05-19 00:06:34.000000000 -0400
@@ -26,9 +26,9 @@
 #ifdef HTC_RAW_INTERFACE
 
 static void
-ar6000_htc_raw_read_cb(void *Context, HTC_PACKET *pPacket)
+ar6000_htc_raw_read_cb(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T        *ar = (AR_SOFTC_T *)Context;
+    struct ar6_softc        *ar = (struct ar6_softc *)Context;
     raw_htc_buffer    *busy;
     HTC_RAW_STREAM_ID streamID; 
     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
@@ -55,12 +55,12 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Unable to down the semaphore\n"));
     }
 
-    A_ASSERT((pPacket->Status != A_OK) || 
+    A_ASSERT((pPacket->Status != 0) ||
              (pPacket->pBuffer == (busy->data + HTC_HEADER_LEN)));
 
     busy->length = pPacket->ActualLength + HTC_HEADER_LEN;
     busy->currPtr = HTC_HEADER_LEN;
-    arRaw->read_buffer_available[streamID] = TRUE;
+    arRaw->read_buffer_available[streamID] = true;
     //AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("raw read cb:  0x%X 0x%X \n", busy->currPtr,busy->length);
     up(&arRaw->raw_htc_read_sem[streamID]);
 
@@ -70,9 +70,9 @@
 }
 
 static void
-ar6000_htc_raw_write_cb(void *Context, HTC_PACKET *pPacket)
+ar6000_htc_raw_write_cb(void *Context, struct htc_packet *pPacket)
 {
-    AR_SOFTC_T          *ar = (AR_SOFTC_T  *)Context;
+    struct ar6_softc          *ar = (struct ar6_softc  *)Context;
     raw_htc_buffer      *free;
     HTC_RAW_STREAM_ID   streamID;
     AR_RAW_HTC_T *arRaw = ar->arRawHtc;
@@ -102,7 +102,7 @@
     A_ASSERT(pPacket->pBuffer == (free->data + HTC_HEADER_LEN));
 
     free->length = 0;
-    arRaw->write_buffer_available[streamID] = TRUE;
+    arRaw->write_buffer_available[streamID] = true;
     up(&arRaw->raw_htc_write_sem[streamID]);
 
     /* Signal the waiting process */
@@ -111,21 +111,21 @@
 }
 
 /* connect to a service */
-static A_STATUS ar6000_connect_raw_service(AR_SOFTC_T        *ar,
+static int ar6000_connect_raw_service(struct ar6_softc        *ar,
                                            HTC_RAW_STREAM_ID StreamID)
 {
-    A_STATUS                 status;
-    HTC_SERVICE_CONNECT_RESP response;
-    A_UINT8                  streamNo;
-    HTC_SERVICE_CONNECT_REQ  connect;
+    int                 status;
+    struct htc_service_connect_resp response;
+    u8 streamNo;
+    struct htc_service_connect_req  connect;
     
     do {      
         
         A_MEMZERO(&connect,sizeof(connect));
             /* pass the stream ID as meta data to the RAW streams service */
-        streamNo = (A_UINT8)StreamID;
+        streamNo = (u8)StreamID;
         connect.pMetaData = &streamNo;
-        connect.MetaDataLength = sizeof(A_UINT8);
+        connect.MetaDataLength = sizeof(u8);
             /* these fields are the same for all endpoints */
         connect.EpCallbacks.pContext = ar;
         connect.EpCallbacks.EpTxComplete = ar6000_htc_raw_write_cb;   
@@ -147,10 +147,10 @@
                                    &connect,
                                    &response);
         
-        if (A_FAILED(status)) {
+        if (status) {
             if (response.ConnectRespCode == HTC_SERVICE_NO_MORE_EP) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTC RAW , No more streams allowed \n"));
-                status = A_OK;    
+                status = 0;
             }
             break;    
         }
@@ -161,14 +161,14 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("HTC RAW : stream ID: %d, endpoint: %d\n", 
                         StreamID, arRawStream2EndpointID(ar,StreamID)));
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
-int ar6000_htc_raw_open(AR_SOFTC_T *ar)
+int ar6000_htc_raw_open(struct ar6_softc *ar)
 {
-    A_STATUS status;
+    int status;
     int streamID, endPt, count2;
     raw_htc_buffer *buffer;
     HTC_SERVICE_ID servicepriority;
@@ -187,7 +187,7 @@
     /* wait for target */
     status = HTCWaitTarget(ar->arHtcTarget);
         
-    if (A_FAILED(status)) {
+    if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("HTCWaitTarget failed (%d)\n", status));
         return -ENODEV;  
     }
@@ -206,7 +206,7 @@
             /* try to connect to the raw service */
         status = ar6000_connect_raw_service(ar,streamID);
         
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -228,7 +228,7 @@
                                           arRawStream2EndpointID(ar,streamID));
             
             /* Queue buffers to HTC for receive */
-            if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != A_OK)
+            if ((status = HTCAddReceivePkt(ar->arHtcTarget, &buffer->HTCPacket)) != 0)
             {
                 BMIInit();
                 return -EIO;
@@ -241,11 +241,11 @@
             memset(buffer, 0, sizeof(raw_htc_buffer));
         }
 
-        arRaw->read_buffer_available[streamID] = FALSE;
-        arRaw->write_buffer_available[streamID] = TRUE;
+        arRaw->read_buffer_available[streamID] = false;
+        arRaw->write_buffer_available[streamID] = true;
     }
     
-    if (A_FAILED(status)) {
+    if (status) {
         return -EIO;    
     }
     
@@ -262,23 +262,23 @@
                              1);
 
     /* Start the HTC component */
-    if ((status = HTCStart(ar->arHtcTarget)) != A_OK) {
+    if ((status = HTCStart(ar->arHtcTarget)) != 0) {
         BMIInit();
         return -EIO;
     }
 
-    (ar)->arRawIfInit = TRUE;
+    (ar)->arRawIfInit = true;
     
     return 0;
 }
 
-int ar6000_htc_raw_close(AR_SOFTC_T *ar)
+int ar6000_htc_raw_close(struct ar6_softc *ar)
 {
     A_PRINTF("ar6000_htc_raw_close called \n");
     HTCStop(ar->arHtcTarget);
     
         /* reset the device */
-    ar6000_reset_device(ar->arHifDevice, ar->arTargetType, TRUE, FALSE);
+    ar6000_reset_device(ar->arHifDevice, ar->arTargetType, true, false);
     /* Initialize the BMI component */
     BMIInit();
 
@@ -286,7 +286,7 @@
 }
 
 raw_htc_buffer *
-get_filled_buffer(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID)
+get_filled_buffer(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID)
 {
     int count;
     raw_htc_buffer *busy;
@@ -300,15 +300,15 @@
         }
     }
     if (busy->length) {
-        arRaw->read_buffer_available[StreamID] = TRUE;
+        arRaw->read_buffer_available[StreamID] = true;
     } else {
-        arRaw->read_buffer_available[StreamID] = FALSE;
+        arRaw->read_buffer_available[StreamID] = false;
     }
 
     return busy;
 }
 
-ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID, 
+ssize_t ar6000_htc_raw_read(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID, 
                             char __user *buffer, size_t length)
 {
     int readPtr;
@@ -361,14 +361,14 @@
         //AR_DEBUG_PRINTF(ATH_DEBUG_HTC_RAW,("raw read ioctl:  ep for packet:%d \n", busy->HTCPacket.Endpoint));
         HTCAddReceivePkt(ar->arHtcTarget, &busy->HTCPacket);
     }
-    arRaw->read_buffer_available[StreamID] = FALSE;
+    arRaw->read_buffer_available[StreamID] = false;
     up(&arRaw->raw_htc_read_sem[StreamID]);
 
     return length;
 }
 
 static raw_htc_buffer *
-get_free_buffer(AR_SOFTC_T *ar, HTC_ENDPOINT_ID StreamID)
+get_free_buffer(struct ar6_softc *ar, HTC_ENDPOINT_ID StreamID)
 {
     int count;
     raw_htc_buffer *free;
@@ -382,15 +382,15 @@
         }
     }
     if (!free->length) {
-        arRaw->write_buffer_available[StreamID] = TRUE;
+        arRaw->write_buffer_available[StreamID] = true;
     } else {
-        arRaw->write_buffer_available[StreamID] = FALSE;
+        arRaw->write_buffer_available[StreamID] = false;
     }
 
     return free;
 }
 
-ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar, HTC_RAW_STREAM_ID StreamID,
+ssize_t ar6000_htc_raw_write(struct ar6_softc *ar, HTC_RAW_STREAM_ID StreamID,
                      char __user *buffer, size_t length)
 {
     int writePtr;
@@ -447,7 +447,7 @@
     
     HTCSendPkt(ar->arHtcTarget,&free->HTCPacket);
     
-    arRaw->write_buffer_available[StreamID] = FALSE;
+    arRaw->write_buffer_available[StreamID] = false;
     up(&arRaw->raw_htc_write_sem[StreamID]);
 
     return length;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6k_pal.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6k_pal.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ar6k_pal.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ar6k_pal.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,7 +49,7 @@
 #define HCI_NORMAL_MODE (1)
 #define HCI_REGISTERED (1<<1)
 	struct hci_dev *hdev;            /* BT Stack HCI dev */
-	AR_SOFTC_T *ar;
+	struct ar6_softc *ar;
 
 }ar6k_hci_pal_info_t;
 
@@ -120,9 +120,9 @@
 	struct hci_dev *hdev = (struct hci_dev *)skb->dev;
 	HCI_TRANSPORT_PACKET_TYPE type;
 	ar6k_hci_pal_info_t *pHciPalInfo;
-	A_STATUS status = A_OK;
+	int status = 0;
 	struct sk_buff *txSkb = NULL;
-	AR_SOFTC_T *ar;
+	struct ar6_softc *ar;
 
 	if (!hdev) {
 		PRIN_LOG("HCI PAL: btpal_send_frame - no device\n");
@@ -157,7 +157,7 @@
 			kfree_skb(skb);
 			return 0;
 		default:
-			A_ASSERT(FALSE);
+			A_ASSERT(false);
 			kfree_skb(skb);
 			return 0;
 	} 
@@ -178,13 +178,13 @@
 		{
 			PRIN_LOG("HCI command");
 
-			if (ar->arWmiReady == FALSE)
+			if (ar->arWmiReady == false)
 			{
 				PRIN_LOG("WMI not ready ");
 				break;
 			}
 
-			if (wmi_send_hci_cmd(ar->arWmi, skb->data, skb->len) != A_OK)
+			if (wmi_send_hci_cmd(ar->arWmi, skb->data, skb->len) != 0)
 			{
 				PRIN_LOG("send hci cmd error");
 				break;
@@ -195,7 +195,7 @@
 			void *osbuf;
 
 			PRIN_LOG("ACL data");
-			if (ar->arWmiReady == FALSE)
+			if (ar->arWmiReady == false)
 			{
 				PRIN_LOG("WMI not ready");
 				break;
@@ -215,12 +215,12 @@
 			bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
 			txSkb->dev = (void *)pHciPalInfo->hdev;
 			skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + WMI_MAX_TX_META_SZ + sizeof(WMI_DATA_HDR));
-			A_MEMCPY(txSkb->data, skb->data, skb->len);
+			memcpy(txSkb->data, skb->data, skb->len);
 			skb_put(txSkb,skb->len);
 			/* Add WMI packet type */
 			osbuf = (void *)txSkb;
 
-			if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != A_OK) {
+			if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
 				PRIN_LOG("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n");
 			} else {
 				/* Send data buffer over HTC */
@@ -229,7 +229,7 @@
 			}
 			txSkb = NULL;
 		}
-	} while (FALSE);
+	} while (false);
 
 	if (txSkb != NULL) {
 		PRIN_LOG("Free skb");
@@ -260,22 +260,20 @@
 		}          
 	}
 
-	if (pHciPalInfo->hdev != NULL) {
-		kfree(pHciPalInfo->hdev);
-		pHciPalInfo->hdev = NULL;
-	}
+	kfree(pHciPalInfo->hdev);
+	pHciPalInfo->hdev = NULL;
 }
 
 /*********************************************************
  * Allocate HCI device and store in PAL private info structure.
  *********************************************************/
-static A_STATUS bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
+static int bt_setup_hci_pal(ar6k_hci_pal_info_t *pHciPalInfo)
 {
-	A_STATUS status = A_OK;
+	int status = 0;
 	struct hci_dev *pHciDev = NULL;
 
 	if (!setupbtdev) {
-		return A_OK;    
+		return 0;
 	} 
 
 	do {
@@ -302,9 +300,9 @@
 		PRIN_LOG("Normal mode enabled");
 		bt_set_bit(pHciPalInfo->ulFlags, HCI_NORMAL_MODE);
 
-	} while (FALSE);
+	} while (false);
 
-	if (A_FAILED(status)) {
+	if (status) {
 		bt_cleanup_hci_pal(pHciPalInfo);    
 	}
 	return status;
@@ -315,7 +313,7 @@
  *********************************************/
 void ar6k_cleanup_hci_pal(void *ar_p)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar_p;
+	struct ar6_softc *ar = (struct ar6_softc *)ar_p;
 	ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)ar->hcipal_info;
 
 	if (pHciPalInfo != NULL) {
@@ -328,22 +326,22 @@
 /****************************
  *  Register HCI device
  ****************************/
-static A_BOOL ar6k_pal_transport_ready(void *pHciPal)
+static bool ar6k_pal_transport_ready(void *pHciPal)
 {
 	ar6k_hci_pal_info_t *pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
 
 	PRIN_LOG("HCI device transport ready");
 	if(pHciPalInfo == NULL)
-		return FALSE;
+		return false;
 
 	if (hci_register_dev(pHciPalInfo->hdev) < 0) {
 		PRIN_LOG("Can't register HCI device");
 		hci_free_dev(pHciPalInfo->hdev);
-		return FALSE;
+		return false;
 	}
 	PRIN_LOG("HCI device registered");
 	pHciPalInfo->ulFlags |= HCI_REGISTERED;
-	return TRUE;
+	return true;
 }
 
 /**************************************************
@@ -351,12 +349,12 @@
  * packet is received. Pass the packet to bluetooth
  * stack via hci_recv_frame.
  **************************************************/
-A_BOOL ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
+bool ar6k_pal_recv_pkt(void *pHciPal, void *osbuf)
 {
 	struct sk_buff *skb = (struct sk_buff *)osbuf;
 	ar6k_hci_pal_info_t *pHciPalInfo;
-	A_BOOL success = FALSE;
-	A_UINT8 btType = 0;
+	bool success = false;
+	u8 btType = 0;
 	pHciPalInfo = (ar6k_hci_pal_info_t *)pHciPal;
 
 	do {
@@ -391,8 +389,8 @@
 			PRIN_LOG("HCI PAL: Indicated RCV of type:%d, Length:%d \n",HCI_EVENT_PKT, skb->len);
 		}
 		PRIN_LOG("hci recv success");
-		success = TRUE;
-	}while(FALSE);
+		success = true;
+	}while(false);
 	return success;
 }
 
@@ -402,12 +400,12 @@
  * Registers a HCI device.
  * Registers packet receive callback function with ar6k 
  **********************************************************/
-A_STATUS ar6k_setup_hci_pal(void *ar_p)
+int ar6k_setup_hci_pal(void *ar_p)
 {
-	A_STATUS status = A_OK;
+	int status = 0;
 	ar6k_hci_pal_info_t *pHciPalInfo;
 	ar6k_pal_config_t ar6k_pal_config;
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar_p;
+	struct ar6_softc *ar = (struct ar6_softc *)ar_p;
 
 	do {
 
@@ -423,7 +421,7 @@
 		pHciPalInfo->ar = ar;
 
 		status = bt_setup_hci_pal(pHciPalInfo);
-		if (A_FAILED(status)) {
+		if (status) {
 			break;    
 		}
 
@@ -435,17 +433,17 @@
 		ar6k_pal_config.fpar6k_pal_recv_pkt = ar6k_pal_recv_pkt;
 		register_pal_cb(&ar6k_pal_config);
 		ar6k_pal_transport_ready(ar->hcipal_info);
-	} while (FALSE);
+	} while (false);
 
-	if (A_FAILED(status)) {
+	if (status) {
 		ar6k_cleanup_hci_pal(ar);    
 	}
 	return status;
 }
 #else  /* AR6K_ENABLE_HCI_PAL */
-A_STATUS ar6k_setup_hci_pal(void *ar_p)
+int ar6k_setup_hci_pal(void *ar_p)
 {
-	return A_OK;
+	return 0;
 }
 void ar6k_cleanup_hci_pal(void *ar_p)
 {
@@ -457,15 +455,15 @@
  * Register init and callback function with ar6k
  * when PAL driver is a separate kernel module.
  ****************************************************/
-A_STATUS ar6k_register_hci_pal(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks);
+int ar6k_register_hci_pal(struct hci_transport_callbacks *hciTransCallbacks);
 static int __init pal_init_module(void)
 {
-	HCI_TRANSPORT_CALLBACKS hciTransCallbacks;
+	struct hci_transport_callbacks hciTransCallbacks;
 
 	hciTransCallbacks.setupTransport = ar6k_setup_hci_pal;
 	hciTransCallbacks.cleanupTransport = ar6k_cleanup_hci_pal;
 
-	if(ar6k_register_hci_pal(&hciTransCallbacks) != A_OK)
+	if(ar6k_register_hci_pal(&hciTransCallbacks) != 0)
 		return -ENODEV;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/cfg80211.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/cfg80211.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/cfg80211.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/cfg80211.c	2011-05-19 00:06:34.000000000 -0400
@@ -136,7 +136,7 @@
 };
 
 static int
-ar6k_set_wpa_version(AR_SOFTC_T *ar, enum nl80211_wpa_versions wpa_version)
+ar6k_set_wpa_version(struct ar6_softc *ar, enum nl80211_wpa_versions wpa_version)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: %u\n", __func__, wpa_version));
@@ -153,11 +153,11 @@
         return -ENOTSUPP;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static int
-ar6k_set_auth_type(AR_SOFTC_T *ar, enum nl80211_auth_type auth_type)
+ar6k_set_auth_type(struct ar6_softc *ar, enum nl80211_auth_type auth_type)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, auth_type));
@@ -179,15 +179,15 @@
         return -ENOTSUPP;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static int
-ar6k_set_cipher(AR_SOFTC_T *ar, A_UINT32 cipher, A_BOOL ucast)
+ar6k_set_cipher(struct ar6_softc *ar, u32 cipher, bool ucast)
 {
-    A_UINT8  *ar_cipher = ucast ? &ar->arPairwiseCrypto :
+    u8 *ar_cipher = ucast ? &ar->arPairwiseCrypto :
                                 &ar->arGroupCrypto;
-    A_UINT8  *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen :
+    u8 *ar_cipher_len = ucast ? &ar->arPairwiseCryptoLen :
                                     &ar->arGroupCryptoLen;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
@@ -221,11 +221,11 @@
         return -ENOTSUPP;
     }
 
-    return A_OK;
+    return 0;
 }
 
 static void
-ar6k_set_key_mgmt(AR_SOFTC_T *ar, A_UINT32 key_mgmt)
+ar6k_set_key_mgmt(struct ar6_softc *ar, u32 key_mgmt)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: 0x%x\n", __func__, key_mgmt));
 
@@ -244,12 +244,13 @@
 ar6k_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                       struct cfg80211_connect_params *sme)
 {
-    AR_SOFTC_T *ar = ar6k_priv(dev);
-    A_STATUS status;
+    struct ar6_softc *ar = ar6k_priv(dev);
+    int status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
+    ar->smeState = SME_CONNECTING;
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready yet\n", __func__));
         return -EIO;
     }
@@ -269,7 +270,7 @@
         return -EINVAL;
     }
 
-    if(ar->arSkipScan == TRUE &&
+    if(ar->arSkipScan == true &&
        ((sme->channel && sme->channel->center_freq == 0) ||
         (sme->bssid && !sme->bssid[0] && !sme->bssid[1] && !sme->bssid[2] &&
          !sme->bssid[3] && !sme->bssid[4] && !sme->bssid[5])))
@@ -302,28 +303,28 @@
         }
     }
 
-    if(ar->arConnected == TRUE &&
+    if(ar->arConnected == true &&
        ar->arSsidLen == sme->ssid_len &&
-       !A_MEMCMP(ar->arSsid, sme->ssid, ar->arSsidLen)) {
-        reconnect_flag = TRUE;
+       !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) {
+        reconnect_flag = true;
         status = wmi_reconnect_cmd(ar->arWmi,
                                    ar->arReqBssid,
                                    ar->arChannelHint);
 
         up(&ar->arSem);
-        if (status != A_OK) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_reconnect_cmd failed\n", __func__));
             return -EIO;
         }
         return 0;
     } else if(ar->arSsidLen == sme->ssid_len &&
-              !A_MEMCMP(ar->arSsid, sme->ssid, ar->arSsidLen)) {
-	    wmi_disconnect_cmd(ar->arWmi);
+              !memcmp(ar->arSsid, sme->ssid, ar->arSsidLen)) {
+	    ar6000_disconnect(ar);
     }
 
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
     ar->arSsidLen = sme->ssid_len;
-    A_MEMCPY(ar->arSsid, sme->ssid, sme->ssid_len);
+    memcpy(ar->arSsid, sme->ssid, sme->ssid_len);
 
     if(sme->channel){
         ar->arChannelHint = sme->channel->center_freq;
@@ -331,8 +332,8 @@
 
     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     if(sme->bssid){
-        if(A_MEMCMP(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
-            A_MEMCPY(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid));
+        if(memcmp(&sme->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
+            memcpy(ar->arReqBssid, sme->bssid, sizeof(ar->arReqBssid));
         }
     }
 
@@ -364,7 +365,7 @@
 
         key = &ar->keys[sme->key_idx];
         key->key_len = sme->key_len;
-        A_MEMCPY(key->key, sme->key, key->key_len);
+        memcpy(key->key, sme->key, key->key_len);
         key->cipher = ar->arPairwiseCrypto;
         ar->arDefTxKeyIndex = sme->key_idx;
 
@@ -378,7 +379,7 @@
     }
 
     if (!ar->arUserBssFilter) {
-        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
+        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__));
             up(&ar->arSem);
             return -EIO;
@@ -410,7 +411,7 @@
         ar->arSsidLen = 0;
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Invalid request\n", __func__));
         return -ENOENT;
-    } else if (status != A_OK) {
+    } else if (status) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_connect_cmd failed\n", __func__));
         return -EIO;
     }
@@ -422,37 +423,37 @@
     }
 
     ar->arConnectCtrlFlags &= ~CONNECT_DO_WPA_OFFLOAD;
-    ar->arConnectPending = TRUE;
+    ar->arConnectPending = true;
 
     return 0;
 }
 
 void
-ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
-                A_UINT8 *bssid, A_UINT16 listenInterval,
-                A_UINT16 beaconInterval,NETWORK_TYPE networkType,
-                A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
-                A_UINT8 assocRespLen, A_UINT8 *assocInfo)
+ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
+                u8 *bssid, u16 listenInterval,
+                u16 beaconInterval,NETWORK_TYPE networkType,
+                u8 beaconIeLen, u8 assocReqLen,
+                u8 assocRespLen, u8 *assocInfo)
 {
-    A_UINT16 size = 0;
-    A_UINT16 capability = 0;
+    u16 size = 0;
+    u16 capability = 0;
     struct cfg80211_bss *bss = NULL;
     struct ieee80211_mgmt *mgmt = NULL;
     struct ieee80211_channel *ibss_channel = NULL;
     s32 signal = 50 * 100;
-    A_UINT8 ie_buf_len = 0;
+    u8 ie_buf_len = 0;
     unsigned char ie_buf[256];
     unsigned char *ptr_ie_buf = ie_buf;
     unsigned char *ieeemgmtbuf = NULL;
-    A_UINT8 source_mac[ATH_MAC_LEN];
+    u8 source_mac[ATH_MAC_LEN];
 
-    A_UINT8 assocReqIeOffset = sizeof(A_UINT16)  +  /* capinfo*/
-                               sizeof(A_UINT16);    /* listen interval */
-    A_UINT8 assocRespIeOffset = sizeof(A_UINT16) +  /* capinfo*/
-                                sizeof(A_UINT16) +  /* status Code */
-                                sizeof(A_UINT16);   /* associd */
-    A_UINT8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset;
-    A_UINT8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset;
+    u8 assocReqIeOffset = sizeof(u16)  +  /* capinfo*/
+                               sizeof(u16);    /* listen interval */
+    u8 assocRespIeOffset = sizeof(u16) +  /* capinfo*/
+                                sizeof(u16) +  /* status Code */
+                                sizeof(u16);   /* associd */
+    u8 *assocReqIe = assocInfo + beaconIeLen + assocReqIeOffset;
+    u8 *assocRespIe = assocInfo + beaconIeLen + assocReqLen + assocRespIeOffset;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
@@ -492,7 +493,7 @@
             if(ptr_ie_buf) {
                 *ptr_ie_buf++ = WLAN_EID_SSID;
                 *ptr_ie_buf++ = ar->arSsidLen;
-                A_MEMCPY(ptr_ie_buf, ar->arSsid, ar->arSsidLen);
+                memcpy(ptr_ie_buf, ar->arSsid, ar->arSsidLen);
                 ptr_ie_buf +=ar->arSsidLen;
 
                 *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS;
@@ -510,11 +511,11 @@
             if(WEP_CRYPT == ar->arPairwiseCrypto) {
                 capability |= IEEE80211_CAPINFO_PRIVACY;
             }
-            A_MEMCPY(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN);
+            memcpy(source_mac, ar->arNetDev->dev_addr, ATH_MAC_LEN);
             ptr_ie_buf = ie_buf;
         } else {
-            capability = *(A_UINT16 *)(&assocInfo[beaconIeLen]);
-            A_MEMCPY(source_mac, bssid, ATH_MAC_LEN);
+            capability = *(u16 *)(&assocInfo[beaconIeLen]);
+            memcpy(source_mac, bssid, ATH_MAC_LEN);
             ptr_ie_buf = assocReqIe;
             ie_buf_len = assocReqLen;
         }
@@ -533,12 +534,12 @@
         A_MEMZERO(ieeemgmtbuf, size);
         mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
         mgmt->frame_control = (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_BEACON);
-        A_MEMCPY(mgmt->da, bcast_mac, ATH_MAC_LEN);
-        A_MEMCPY(mgmt->sa, source_mac, ATH_MAC_LEN);
-        A_MEMCPY(mgmt->bssid, bssid, ATH_MAC_LEN);
+        memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN);
+        memcpy(mgmt->sa, source_mac, ATH_MAC_LEN);
+        memcpy(mgmt->bssid, bssid, ATH_MAC_LEN);
         mgmt->u.beacon.beacon_int = beaconInterval;
         mgmt->u.beacon.capab_info = capability;
-        A_MEMCPY(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len);
+        memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len);
 
         ibss_channel = ieee80211_get_channel(ar->wdev->wiphy, (int)channel);
 
@@ -560,8 +561,9 @@
         return;
     }
 
-    if (FALSE == ar->arConnected) {
+    if (false == ar->arConnected) {
         /* inform connect result to cfg80211 */
+        ar->smeState = SME_DISCONNECTED;
         cfg80211_connect_result(ar->arNetDev, bssid,
                                 assocReqIe, assocReqLen,
                                 assocRespIe, assocRespLen,
@@ -577,13 +579,13 @@
 
 static int
 ar6k_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
-                        A_UINT16 reason_code)
+                        u16 reason_code)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason_code));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -604,11 +606,11 @@
     }
 
     reconnect_flag = 0;
-    wmi_disconnect_cmd(ar->arWmi);
+    ar6000_disconnect(ar);
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
     ar->arSsidLen = 0;
 
-    if (ar->arSkipScan == FALSE) {
+    if (ar->arSkipScan == false) {
         A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     }
 
@@ -618,9 +620,9 @@
 }
 
 void
-ar6k_cfg80211_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason,
-                               A_UINT8 *bssid, A_UINT8 assocRespLen,
-                               A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus)
+ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
+                               u8 *bssid, u8 assocRespLen,
+                               u8 *assocInfo, u16 protocolReasonStatus)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: reason=%u\n", __func__, reason));
@@ -644,18 +646,28 @@
         }
     }
 
-    if(FALSE == ar->arConnected) {
+    if(true == ar->arConnectPending) {
         if(NO_NETWORK_AVAIL == reason) {
             /* connect cmd failed */
-            cfg80211_connect_result(ar->arNetDev, bssid,
-                                    NULL, 0,
-                                    NULL, 0,
-                                    WLAN_STATUS_UNSPECIFIED_FAILURE,
-                                    GFP_KERNEL);
+            wmi_disconnect_cmd(ar->arWmi);
+        } else if (reason == DISCONNECT_CMD) {
+            /* connection loss due to disconnect cmd or low rssi */
+            ar->arConnectPending = false;   
+            if (ar->smeState == SME_CONNECTING) {
+                cfg80211_connect_result(ar->arNetDev, bssid,
+                                        NULL, 0,
+                                        NULL, 0,
+                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
+                                        GFP_KERNEL);
+            } else {
+                cfg80211_disconnected(ar->arNetDev, reason, NULL, 0, GFP_KERNEL);
+            }
+            ar->smeState = SME_DISCONNECTED;
         }
     } else {
-        /* connection loss due to disconnect cmd or low rssi */
-        cfg80211_disconnected(ar->arNetDev, reason, NULL, 0, GFP_KERNEL);
+        if (reason != DISCONNECT_CMD) {
+            wmi_disconnect_cmd(ar->arWmi);
+        }
     }
 }
 
@@ -663,7 +675,7 @@
 ar6k_cfg80211_scan_node(void *arg, bss_t *ni)
 {
     struct wiphy *wiphy = (struct wiphy *)arg;
-    A_UINT16 size;
+    u16 size;
     unsigned char *ieeemgmtbuf = NULL;
     struct ieee80211_mgmt *mgmt;
     struct ieee80211_channel *channel;
@@ -700,10 +712,10 @@
        cfg80211 needs it, for time being just filling the da, sa and bssid fields alone.
     */
     mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
-    A_MEMCPY(mgmt->da, bcast_mac, ATH_MAC_LEN);
-    A_MEMCPY(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN);
-    A_MEMCPY(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN);
-    A_MEMCPY(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u),
+    memcpy(mgmt->da, bcast_mac, ATH_MAC_LEN);
+    memcpy(mgmt->sa, ni->ni_macaddr, ATH_MAC_LEN);
+    memcpy(mgmt->bssid, ni->ni_macaddr, ATH_MAC_LEN);
+    memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u),
              ni->ni_buf, ni->ni_framelen);
 
     freq    = cie->ie_chan;
@@ -724,13 +736,13 @@
 ar6k_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                    struct cfg80211_scan_request *request)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     int ret = 0;
-    A_BOOL forceFgScan = FALSE;
+    u32 forceFgScan = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -743,7 +755,7 @@
     if (!ar->arUserBssFilter) {
         if (wmi_bssfilter_cmd(ar->arWmi,
                              (ar->arConnected ? ALL_BUT_BSS_FILTER : ALL_BSS_FILTER),
-                             0) != A_OK) {
+                             0) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Couldn't set bss filtering\n", __func__));
             return -EIO;
         }
@@ -751,25 +763,25 @@
 
     if(request->n_ssids &&
        request->ssids[0].ssid_len) {
-        A_UINT8 i;
+        u8 i;
 
-        if(request->n_ssids > MAX_PROBED_SSID_INDEX) {
-            request->n_ssids = MAX_PROBED_SSID_INDEX;
+        if(request->n_ssids > (MAX_PROBED_SSID_INDEX - 1)) {
+            request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
         }
 
         for (i = 0; i < request->n_ssids; i++) {
-            wmi_probedSsid_cmd(ar->arWmi, i, SPECIFIC_SSID_FLAG,
+            wmi_probedSsid_cmd(ar->arWmi, i+1, SPECIFIC_SSID_FLAG,
                                request->ssids[i].ssid_len,
                                request->ssids[i].ssid);
         }
     }
 
     if(ar->arConnected) {
-        forceFgScan = TRUE;
+        forceFgScan = 1;
     }
 
-    if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, FALSE, \
-                         0, 0, 0, NULL) != A_OK) {
+    if(wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, forceFgScan, false, \
+                         0, 0, 0, NULL) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_startscan_cmd failed\n", __func__));
         ret = -EIO;
     }
@@ -780,7 +792,7 @@
 }
 
 void
-ar6k_cfg80211_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status)
+ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status)
 {
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: status %d\n", __func__, status));
@@ -791,14 +803,14 @@
         wmi_iterate_nodes(ar->arWmi, ar6k_cfg80211_scan_node, ar->wdev->wiphy);
 
         cfg80211_scan_done(ar->scan_request,
-                          (status & A_ECANCELED) ? true : false);
+            ((status & A_ECANCELED) || (status & A_EBUSY)) ? true : false);
 
         if(ar->scan_request->n_ssids &&
            ar->scan_request->ssids[0].ssid_len) {
-            A_UINT8 i;
+            u8 i;
 
             for (i = 0; i < ar->scan_request->n_ssids; i++) {
-                wmi_probedSsid_cmd(ar->arWmi, i, DISABLE_SSID_FLAG,
+                wmi_probedSsid_cmd(ar->arWmi, i+1, DISABLE_SSID_FLAG,
                                    0, NULL);
             }
         }
@@ -808,18 +820,18 @@
 
 static int
 ar6k_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
-                      A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr,
+                      u8 key_index, bool pairwise, const u8 *mac_addr,
                       struct key_params *params)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     struct ar_key *key = NULL;
-    A_UINT8 key_usage;
-    A_UINT8 key_type;
-    A_STATUS status = 0;
+    u8 key_usage;
+    u8 key_type;
+    int status = 0;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s:\n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -850,9 +862,9 @@
             return -EINVAL;
 
         key->key_len = params->key_len;
-        A_MEMCPY(key->key, params->key, key->key_len);
+        memcpy(key->key, params->key, key->key_len);
         key->seq_len = params->seq_len;
-        A_MEMCPY(key->seq, params->seq, key->seq_len);
+        memcpy(key->seq, params->seq, key->seq_len);
         key->cipher = params->cipher;
     }
 
@@ -889,10 +901,10 @@
     ar->arDefTxKeyIndex = key_index;
     status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex, key_type, key_usage,
                     key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
-                    (A_UINT8*)mac_addr, SYNC_BOTH_WMIFLAG);
+                    (u8 *)mac_addr, SYNC_BOTH_WMIFLAG);
 
 
-    if(status != A_OK) {
+    if (status) {
         return -EIO;
     }
 
@@ -901,13 +913,13 @@
 
 static int
 ar6k_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
-                      A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr)
+                      u8 key_index, bool pairwise, const u8 *mac_addr)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -936,17 +948,17 @@
 
 static int
 ar6k_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
-                      A_UINT8 key_index, bool pairwise, const A_UINT8 *mac_addr,
+                      u8 key_index, bool pairwise, const u8 *mac_addr,
                       void *cookie,
                       void (*callback)(void *cookie, struct key_params*))
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     struct ar_key *key = NULL;
     struct key_params params;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -978,15 +990,16 @@
 
 static int
 ar6k_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *ndev,
-                              A_UINT8 key_index)
+                              u8 key_index, bool unicast, bool multicast)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
     struct ar_key *key = NULL;
-    A_STATUS status = A_OK;
+    int status = 0;
+    u8 key_usage;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1011,11 +1024,16 @@
 
     ar->arDefTxKeyIndex = key_index;
     key = &ar->keys[ar->arDefTxKeyIndex];
+    key_usage = GROUP_USAGE;
+    if (WEP_CRYPT == ar->arPairwiseCrypto) {
+        key_usage |= TX_USAGE;
+    }
+
     status = wmi_addKey_cmd(ar->arWmi, ar->arDefTxKeyIndex,
-                            ar->arPairwiseCrypto, GROUP_USAGE | TX_USAGE,
+                            ar->arPairwiseCrypto, key_usage,
                             key->key_len, key->seq, key->key, KEY_OP_INIT_VAL,
                             NULL, SYNC_BOTH_WMIFLAG);
-    if (status != A_OK) {
+    if (status) {
         return -EIO;
     }
 
@@ -1024,13 +1042,13 @@
 
 static int
 ar6k_cfg80211_set_default_mgmt_key(struct wiphy *wiphy, struct net_device *ndev,
-                                   A_UINT8 key_index)
+                                   u8 key_index)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(ndev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(ndev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: index %d\n", __func__, key_index));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1045,7 +1063,7 @@
 }
 
 void
-ar6k_cfg80211_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast)
+ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO,
                     ("%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast));
@@ -1056,13 +1074,13 @@
 }
 
 static int
-ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, A_UINT32 changed)
+ar6k_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)wiphy_priv(wiphy);
+    struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: changed 0x%x\n", __func__, changed));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1073,7 +1091,7 @@
     }
 
     if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
-        if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != A_OK){
+        if (wmi_set_rts_cmd(ar->arWmi,wiphy->rts_threshold) != 0){
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_set_rts_cmd failed\n", __func__));
             return -EIO;
         }
@@ -1084,7 +1102,7 @@
 
 static int
 ar6k_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
-                               const A_UINT8 *peer,
+                               const u8 *peer,
                                const struct cfg80211_bitrate_mask *mask)
 {
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("Setting rates: Not supported\n"));
@@ -1095,12 +1113,12 @@
 static int
 ar6k_cfg80211_set_txpower(struct wiphy *wiphy, enum nl80211_tx_power_setting type, int dbm)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)wiphy_priv(wiphy);
-    A_UINT8 ar_dbm;
+    struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
+    u8 ar_dbm;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x, dbm %d\n", __func__, type, dbm));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1110,13 +1128,13 @@
         return -EIO;
     }
 
-    ar->arTxPwrSet = FALSE;
+    ar->arTxPwrSet = false;
     switch(type) {
     case NL80211_TX_POWER_AUTOMATIC:
         return 0;
     case NL80211_TX_POWER_LIMITED:
         ar->arTxPwr = ar_dbm = dbm;
-        ar->arTxPwrSet = TRUE;
+        ar->arTxPwrSet = true;
         break;
     default:
         AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type 0x%x not supported\n", __func__, type));
@@ -1131,11 +1149,11 @@
 static int
 ar6k_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)wiphy_priv(wiphy);
+    struct ar6_softc *ar = (struct ar6_softc *)wiphy_priv(wiphy);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1145,10 +1163,10 @@
         return -EIO;
     }
 
-    if((ar->arConnected == TRUE)) {
+    if((ar->arConnected == true)) {
         ar->arTxPwr = 0;
 
-        if(wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
+        if(wmi_get_txPwr_cmd(ar->arWmi) != 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_get_txPwr_cmd failed\n", __func__));
             return -EIO;
         }
@@ -1170,12 +1188,12 @@
                              struct net_device *dev,
                              bool pmgmt, int timeout)
 {
-    AR_SOFTC_T *ar = ar6k_priv(dev);
+    struct ar6_softc *ar = ar6k_priv(dev);
     WMI_POWER_MODE_CMD pwrMode;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: pmgmt %d, timeout %d\n", __func__, pmgmt, timeout));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1193,7 +1211,7 @@
         pwrMode.powerMode = REC_POWER;
     }
 
-    if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != A_OK) {
+    if(wmi_powermode_cmd(ar->arWmi, pwrMode.powerMode) != 0) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: wmi_powermode_cmd failed\n", __func__));
         return -EIO;
     }
@@ -1201,7 +1219,7 @@
     return 0;
 }
 
-static int
+static struct net_device *
 ar6k_cfg80211_add_virtual_intf(struct wiphy *wiphy, char *name,
             				    enum nl80211_iftype type, u32 *flags,
             				    struct vif_params *params)
@@ -1212,7 +1230,7 @@
     /* Multiple virtual interface is not supported.
      * The default interface supports STA and IBSS type
      */
-    return -EOPNOTSUPP;
+    return ERR_PTR(-EOPNOTSUPP);
 }
 
 static int
@@ -1232,12 +1250,12 @@
                            enum nl80211_iftype type, u32 *flags,
                            struct vif_params *params)
 {
-    AR_SOFTC_T *ar = ar6k_priv(ndev);
+    struct ar6_softc *ar = ar6k_priv(ndev);
     struct wireless_dev *wdev = ar->wdev;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: type %u\n", __func__, type));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1268,12 +1286,12 @@
 ar6k_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
                         struct cfg80211_ibss_params *ibss_param)
 {
-    AR_SOFTC_T *ar = ar6k_priv(dev);
-    A_STATUS status;
+    struct ar6_softc *ar = ar6k_priv(dev);
+    int status;
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1289,7 +1307,7 @@
     }
 
     ar->arSsidLen = ibss_param->ssid_len;
-    A_MEMCPY(ar->arSsid, ibss_param->ssid, ar->arSsidLen);
+    memcpy(ar->arSsid, ibss_param->ssid, ar->arSsidLen);
 
     if(ibss_param->channel) {
         ar->arChannelHint = ibss_param->channel->center_freq;
@@ -1303,8 +1321,8 @@
 
     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     if(ibss_param->bssid) {
-        if(A_MEMCMP(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
-            A_MEMCPY(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid));
+        if(memcmp(&ibss_param->bssid, bcast_mac, AR6000_ETH_ADDR_LEN)) {
+            memcpy(ar->arReqBssid, ibss_param->bssid, sizeof(ar->arReqBssid));
         }
     }
 
@@ -1335,6 +1353,7 @@
                             ar->arSsidLen, ar->arSsid,
                             ar->arReqBssid, ar->arChannelHint,
                             ar->arConnectCtrlFlags);
+    ar->arConnectPending = true;
 
     return 0;
 }
@@ -1342,11 +1361,11 @@
 static int
 ar6k_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     AR_DEBUG_PRINTF(ATH_DEBUG_INFO, ("%s: \n", __func__));
 
-    if(ar->arWmiReady == FALSE) {
+    if(ar->arWmiReady == false) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("%s: Wmi not ready\n", __func__));
         return -EIO;
     }
@@ -1356,7 +1375,7 @@
         return -EIO;
     }
 
-    wmi_disconnect_cmd(ar->arWmi);
+    ar6000_disconnect(ar);
     A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
     ar->arSsidLen = 0;
 
@@ -1365,7 +1384,7 @@
 
 
 static const
-A_UINT32 cipher_suites[] = {
+u32 cipher_suites[] = {
     WLAN_CIPHER_SUITE_WEP40,
     WLAN_CIPHER_SUITE_WEP104,
     WLAN_CIPHER_SUITE_TKIP,
@@ -1410,7 +1429,7 @@
     }
 
     /* create a new wiphy for use with cfg80211 */
-    wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(AR_SOFTC_T));
+    wdev->wiphy = wiphy_new(&ar6k_cfg80211_ops, sizeof(struct ar6_softc));
     if(!wdev->wiphy) {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,
                         ("%s: Couldn't allocate wiphy device\n", __func__));
@@ -1444,7 +1463,7 @@
 }
 
 void
-ar6k_cfg80211_deinit(AR_SOFTC_T *ar)
+ar6k_cfg80211_deinit(struct ar6_softc *ar)
 {
     struct wireless_dev *wdev = ar->wdev;
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/eeprom.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/eeprom.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/eeprom.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/eeprom.c	2011-05-19 00:06:34.000000000 -0400
@@ -53,9 +53,9 @@
 // static variables
 //
 
-static A_UCHAR eeprom_data[EEPROM_SZ];
-static A_UINT32 sys_sleep_reg;
-static HIF_DEVICE *p_bmi_device;
+static u8 eeprom_data[EEPROM_SZ];
+static u32 sys_sleep_reg;
+static struct hif_device *p_bmi_device;
 
 //
 // Functions
@@ -63,7 +63,7 @@
 
 /* soft mac */
 static int
-wmic_ether_aton(const char *orig, A_UINT8 *eth)
+wmic_ether_aton(const char *orig, u8 *eth)
 {
   const char *bufp;
   int i;
@@ -103,23 +103,23 @@
 }
 
 static void
-update_mac(unsigned char* eeprom, int size, unsigned char* macaddr)
+update_mac(unsigned char *eeprom, int size, unsigned char *macaddr)
 {
 	int i;
-	A_UINT16* ptr = (A_UINT16*)(eeprom+4);
-	A_UINT16  checksum = 0;
+	u16 *ptr = (u16 *)(eeprom+4);
+	u16 checksum = 0;
 
 	memcpy(eeprom+10,macaddr,6);
 
 	*ptr = 0;
-	ptr = (A_UINT16*)eeprom;
+	ptr = (u16 *)eeprom;
 
 	for (i=0; i<size; i+=2) {
 		checksum ^= *ptr++;
 	}
 	checksum = ~checksum;
 
-	ptr = (A_UINT16*)(eeprom+4);
+	ptr = (u16 *)(eeprom+4);
 	*ptr = checksum;
 	return;
 }
@@ -127,30 +127,30 @@
 
 /* Read a Target register and return its value. */
 inline void
-BMI_read_reg(A_UINT32 address, A_UINT32 *pvalue)
+BMI_read_reg(u32 address, u32 *pvalue)
 {
     BMIReadSOCRegister(p_bmi_device, address, pvalue);
 }
 
 /* Write a value to a Target register. */
 inline void
-BMI_write_reg(A_UINT32 address, A_UINT32 value)
+BMI_write_reg(u32 address, u32 value)
 {
     BMIWriteSOCRegister(p_bmi_device, address, value);
 }
 
 /* Read Target memory word and return its value. */
 inline void
-BMI_read_mem(A_UINT32 address, A_UINT32 *pvalue)
+BMI_read_mem(u32 address, u32 *pvalue)
 {
-    BMIReadMemory(p_bmi_device, address, (A_UCHAR*)(pvalue), 4);
+    BMIReadMemory(p_bmi_device, address, (u8*)(pvalue), 4);
 }
 
 /* Write a word to a Target memory. */
 inline void
-BMI_write_mem(A_UINT32 address, A_UINT8 *p_data, A_UINT32 sz)
+BMI_write_mem(u32 address, u8 *p_data, u32 sz)
 {
-    BMIWriteMemory(p_bmi_device, address, (A_UCHAR*)(p_data), sz); 
+    BMIWriteMemory(p_bmi_device, address, (u8*)(p_data), sz); 
 }
 
 /*
@@ -158,9 +158,9 @@
  * so we can access the EEPROM.
  */
 static void
-enable_SI(HIF_DEVICE *p_device)
+enable_SI(struct hif_device *p_device)
 {
-    A_UINT32 regval;
+    u32 regval;
 
     printk("%s\n", __FUNCTION__);
 
@@ -200,7 +200,7 @@
 static void
 disable_SI(void)
 {
-    A_UINT32 regval;
+    u32 regval;
     
     printk("%s\n", __FUNCTION__);
 
@@ -218,7 +218,7 @@
 static void
 request_8byte_read(int offset)
 {
-    A_UINT32 regval;
+    u32 regval;
 
 //    printk("%s: request_8byte_read from offset 0x%x\n", __FUNCTION__, offset);
 
@@ -241,9 +241,9 @@
  * writing values from Target TX_DATA registers.
  */
 static void
-request_4byte_write(int offset, A_UINT32 data)
+request_4byte_write(int offset, u32 data)
 {
-    A_UINT32 regval;
+    u32 regval;
 
     printk("%s: request_4byte_write (0x%x) to offset 0x%x\n", __FUNCTION__, data, offset);
 
@@ -266,10 +266,10 @@
  * Check whether or not an EEPROM request that was started
  * earlier has completed yet.
  */
-static A_BOOL
+static bool
 request_in_progress(void)
 {
-    A_UINT32 regval;
+    u32 regval;
 
     /* Wait for DONE_INT in SI_CS */
     BMI_read_reg(SI_BASE_ADDRESS+SI_CS_OFFSET, &regval);
@@ -288,8 +288,8 @@
 
 static void eeprom_type_detect(void)
 {
-    A_UINT32 regval;
-    A_UINT8 i = 0;
+    u32 regval;
+    u8 i = 0;
 
     request_8byte_read(0x100);
    /* Wait for DONE_INT in SI_CS */
@@ -310,7 +310,7 @@
  * and return them to the caller.
  */
 inline void
-read_8byte_results(A_UINT32 *data)
+read_8byte_results(u32 *data)
 {
     /* Read SI_RX_DATA0 and SI_RX_DATA1 */
     BMI_read_reg(SI_BASE_ADDRESS+SI_RX_DATA0_OFFSET, &data[0]);
@@ -339,7 +339,7 @@
  * waits for it to complete, and returns the result.
  */
 static void
-fetch_8bytes(int offset, A_UINT32 *data)
+fetch_8bytes(int offset, u32 *data)
 {
     request_8byte_read(offset);
     wait_for_eeprom_completion();
@@ -354,17 +354,17 @@
  * and waits for it to complete.
  */
 inline void
-commit_4bytes(int offset, A_UINT32 data)
+commit_4bytes(int offset, u32 data)
 {
     request_4byte_write(offset, data);
     wait_for_eeprom_completion();
 }
 /* ATHENV */
 #ifdef ANDROID_ENV
-void eeprom_ar6000_transfer(HIF_DEVICE *device, char *fake_file, char *p_mac)
+void eeprom_ar6000_transfer(struct hif_device *device, char *fake_file, char *p_mac)
 {
-    A_UINT32 first_word;
-    A_UINT32 board_data_addr;
+    u32 first_word;
+    u32 board_data_addr;
     int i;
 
     printk("%s: Enter\n", __FUNCTION__);
@@ -437,17 +437,17 @@
          * Fetch EEPROM_SZ Bytes of Board Data, 8 bytes at a time.
          */
 
-        fetch_8bytes(0, (A_UINT32 *)(&eeprom_data[0]));
+        fetch_8bytes(0, (u32 *)(&eeprom_data[0]));
 
         /* Check the first word of EEPROM for validity */
-        first_word = *((A_UINT32 *)eeprom_data);
+        first_word = *((u32 *)eeprom_data);
 
         if ((first_word == 0) || (first_word == 0xffffffff)) {
             printk("Did not find EEPROM with valid Board Data.\n");
         }
 
         for (i=8; i<EEPROM_SZ; i+=8) {
-            fetch_8bytes(i, (A_UINT32 *)(&eeprom_data[i]));
+            fetch_8bytes(i, (u32 *)(&eeprom_data[i]));
         }
     }
 
@@ -558,13 +558,13 @@
     /* soft mac */
 
     /* Write EEPROM data to Target RAM */
-    BMI_write_mem(board_data_addr, ((A_UINT8 *)eeprom_data), EEPROM_SZ);
+    BMI_write_mem(board_data_addr, ((u8 *)eeprom_data), EEPROM_SZ);
 
     /* Record the fact that Board Data IS initialized */
     {
-       A_UINT32 one = 1;
+       u32 one = 1;
        BMI_write_mem(HOST_INTEREST_ITEM_ADDRESS(hi_board_data_initialized),
-                     (A_UINT8 *)&one, sizeof(A_UINT32));
+                     (u8 *)&one, sizeof(u32));
     }
 
     disable_SI();
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/export_hci_transport.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/export_hci_transport.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/export_hci_transport.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/export_hci_transport.c	2011-05-19 00:06:34.000000000 -0400
@@ -36,22 +36,22 @@
 #include "AR6002/hw4.0/hw/uart_reg.h"
 #include "AR6002/hw4.0/hw/rtc_wlan_reg.h"
 
-HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo);
 void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans);
-A_STATUS    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
-A_STATUS    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
+int    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
+int    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
 void        (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans);
-A_STATUS    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
-A_STATUS    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
-A_STATUS    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, 
-                                          HTC_PACKET           *pPacket,
+int    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
+int    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
+int    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans,
+                                          struct htc_packet           *pPacket,
                                           int                  MaxPollMS);
-A_STATUS    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
-A_STATUS    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+int    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
+int    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
-extern HCI_TRANSPORT_CALLBACKS ar6kHciTransCallbacks;
+extern struct hci_transport_callbacks ar6kHciTransCallbacks;
 
-A_STATUS ar6000_register_hci_transport(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks)
+int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks)
 {
     ar6kHciTransCallbacks = *hciTransCallbacks;
 
@@ -66,41 +66,41 @@
     _HCI_TransportSetBaudRate = HCI_TransportSetBaudRate;
     _HCI_TransportEnablePowerMgmt = HCI_TransportEnablePowerMgmt;
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-ar6000_get_hif_dev(HIF_DEVICE *device, void *config)
+int
+ar6000_get_hif_dev(struct hif_device *device, void *config)
 {
-    A_STATUS status;
+    int status;
 
     status = HIFConfigureDevice(device,
                                 HIF_DEVICE_GET_OS_DEVICE,
-                                (HIF_DEVICE_OS_DEVICE_INFO *)config, 
-                                sizeof(HIF_DEVICE_OS_DEVICE_INFO));
+                                (struct hif_device_os_device_info *)config, 
+                                sizeof(struct hif_device_os_device_info));
     return status;
 }
 
-A_STATUS ar6000_set_uart_config(HIF_DEVICE *hifDevice, 
-                                A_UINT32 scale, 
-                                A_UINT32 step)
+int ar6000_set_uart_config(struct hif_device *hifDevice,
+                                u32 scale,
+                                u32 step)
 {
-    A_UINT32 regAddress;
-    A_UINT32 regVal;
-    A_STATUS status;
+    u32 regAddress;
+    u32 regVal;
+    int status;
 
     regAddress = WLAN_UART_BASE_ADDRESS | UART_CLKDIV_ADDRESS;
-    regVal = ((A_UINT32)scale << 16) | step;
+    regVal = ((u32)scale << 16) | step;
     /* change the HCI UART scale/step values through the diagnostic window */
     status = ar6000_WriteRegDiag(hifDevice, &regAddress, &regVal);                     
 
     return status;
 }
 
-A_STATUS ar6000_get_core_clock_config(HIF_DEVICE *hifDevice, A_UINT32 *data)
+int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data)
 {
-    A_UINT32 regAddress;
-    A_STATUS status;
+    u32 regAddress;
+    int status;
 
     regAddress = WLAN_RTC_BASE_ADDRESS | WLAN_CPU_CLOCK_ADDRESS;
     /* read CPU clock settings*/
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/hci_bridge.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/hci_bridge.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/hci_bridge.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/hci_bridge.c	2011-05-19 00:06:34.000000000 -0400
@@ -73,21 +73,21 @@
 extern unsigned int hciuartstep;
 #endif /* EXPORT_HCI_BRIDGE_INTERFACE */
 
-typedef struct {
+struct ar6k_hci_bridge_info {
     void                    *pHCIDev;          /* HCI bridge device */
-    HCI_TRANSPORT_PROPERTIES HCIProps;         /* HCI bridge props */
+    struct hci_transport_properties HCIProps;         /* HCI bridge props */
     struct hci_dev          *pBtStackHCIDev;   /* BT Stack HCI dev */
-    A_BOOL                  HciNormalMode;     /* Actual HCI mode enabled (non-TEST)*/
-    A_BOOL                  HciRegistered;     /* HCI device registered with stack */
-    HTC_PACKET_QUEUE        HTCPacketStructHead;
-    A_UINT8                 *pHTCStructAlloc;
+    bool                  HciNormalMode;     /* Actual HCI mode enabled (non-TEST)*/
+    bool                  HciRegistered;     /* HCI device registered with stack */
+    struct htc_packet_queue        HTCPacketStructHead;
+    u8 *pHTCStructAlloc;
     spinlock_t              BridgeLock;
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-    HCI_TRANSPORT_MISC_HANDLES    HCITransHdl; 
+    struct hci_transport_misc_handles    HCITransHdl; 
 #else
-    AR_SOFTC_T              *ar;
+    struct ar6_softc              *ar;
 #endif /* EXPORT_HCI_BRIDGE_INTERFACE */
-} AR6K_HCI_BRIDGE_INFO;
+};
 
 #define MAX_ACL_RECV_BUFS           16
 #define MAX_EVT_RECV_BUFS           8
@@ -97,39 +97,39 @@
 #define TX_PACKET_RSV_OFFSET        32
 #define NUM_HTC_PACKET_STRUCTS     ((MAX_ACL_RECV_BUFS + MAX_EVT_RECV_BUFS + MAX_HCI_WRITE_QUEUE_DEPTH) * 2)
 
-#define HCI_GET_OP_CODE(p)          (((A_UINT16)((p)[1])) << 8) | ((A_UINT16)((p)[0]))
+#define HCI_GET_OP_CODE(p)          (((u16)((p)[1])) << 8) | ((u16)((p)[0]))
 
 extern unsigned int setupbtdev;
-AR3K_CONFIG_INFO      ar3kconfig;
+struct ar3k_config_info      ar3kconfig;
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-AR6K_HCI_BRIDGE_INFO *g_pHcidevInfo;
+struct ar6k_hci_bridge_info *g_pHcidevInfo;
 #endif
 
-static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo);
-static void     bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo);
-static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo);
-static A_BOOL   bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
+static void     bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
+static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo);
+static bool   bt_indicate_recv(struct ar6k_hci_bridge_info      *pHcidevInfo,
                                  HCI_TRANSPORT_PACKET_TYPE Type, 
                                  struct sk_buff            *skb);
-static struct sk_buff *bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length);
-static void     bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb);   
+static struct sk_buff *bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length);
+static void     bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb);   
                                
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(void *ar);
+int ar6000_setup_hci(void *ar);
 void     ar6000_cleanup_hci(void *ar);
-A_STATUS hci_test_send(void *ar, struct sk_buff *skb);
+int hci_test_send(void *ar, struct sk_buff *skb);
 #else
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar);
-void     ar6000_cleanup_hci(AR_SOFTC_T *ar);
+int ar6000_setup_hci(struct ar6_softc *ar);
+void     ar6000_cleanup_hci(struct ar6_softc *ar);
 /* HCI bridge testing */
-A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb);
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb);
 #endif /* EXPORT_HCI_BRIDGE_INTERFACE */
 
 #define LOCK_BRIDGE(dev)   spin_lock_bh(&(dev)->BridgeLock)
 #define UNLOCK_BRIDGE(dev) spin_unlock_bh(&(dev)->BridgeLock)
 
-static inline void FreeBtOsBuf(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, void *osbuf)
+static inline void FreeBtOsBuf(struct ar6k_hci_bridge_info *pHcidevInfo, void *osbuf)
 {    
     if (pHcidevInfo->HciNormalMode) {
         bt_free_buffer(pHcidevInfo, (struct sk_buff *)osbuf);
@@ -139,16 +139,16 @@
     }
 }
 
-static void FreeHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, HTC_PACKET *pPacket)
+static void FreeHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo, struct htc_packet *pPacket)
 {
     LOCK_BRIDGE(pHcidevInfo);
     HTC_PACKET_ENQUEUE(&pHcidevInfo->HTCPacketStructHead,pPacket);
     UNLOCK_BRIDGE(pHcidevInfo);  
 }
 
-static HTC_PACKET * AllocHTCStruct(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static struct htc_packet * AllocHTCStruct(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    HTC_PACKET  *pPacket = NULL;
+    struct htc_packet  *pPacket = NULL;
     LOCK_BRIDGE(pHcidevInfo);
     pPacket = HTC_PACKET_DEQUEUE(&pHcidevInfo->HTCPacketStructHead);
     UNLOCK_BRIDGE(pHcidevInfo);  
@@ -157,14 +157,14 @@
 
 #define BLOCK_ROUND_UP_PWR2(x, align)    (((int) (x) + ((align)-1)) & ~((align)-1))
 
-static void RefillRecvBuffers(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static void RefillRecvBuffers(struct ar6k_hci_bridge_info      *pHcidevInfo, 
                               HCI_TRANSPORT_PACKET_TYPE Type, 
                               int                       NumBuffers)
 {
     int                 length, i;
     void                *osBuf = NULL;
-    HTC_PACKET_QUEUE    queue;
-    HTC_PACKET          *pPacket;
+    struct htc_packet_queue    queue;
+    struct htc_packet          *pPacket;
 
     INIT_HTC_PACKET_QUEUE(&queue);
     
@@ -215,18 +215,18 @@
 #define HOST_INTEREST_ITEM_ADDRESS(ar, item) \
         (((ar)->arTargetType == TARGET_TYPE_AR6002) ? AR6002_HOST_INTEREST_ITEM_ADDRESS(item) : \
         (((ar)->arTargetType == TARGET_TYPE_AR6003) ? AR6003_HOST_INTEREST_ITEM_ADDRESS(item) : 0))
-static A_STATUS ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle, 
-                                           HCI_TRANSPORT_PROPERTIES *pProps, 
+static int ar6000_hci_transport_ready(HCI_TRANSPORT_HANDLE     HCIHandle,
+                                           struct hci_transport_properties *pProps, 
                                            void                     *pContext)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
-    A_STATUS              status;
-    A_UINT32 address, hci_uart_pwr_mgmt_params;
-//    AR3K_CONFIG_INFO      ar3kconfig;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
+    int              status;
+    u32 address, hci_uart_pwr_mgmt_params;
+//    struct ar3k_config_info      ar3kconfig;
     
     pHcidevInfo->pHCIDev = HCIHandle;
     
-    A_MEMCPY(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
+    memcpy(&pHcidevInfo->HCIProps,pProps,sizeof(*pProps));
     
     AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE,("HCI ready (hci:0x%lX, headroom:%d, tailroom:%d blockpad:%d) \n", 
             (unsigned long)HCIHandle, 
@@ -248,7 +248,7 @@
             /* start transport */
         status = HCI_TransportStart(pHcidevInfo->pHCIDev);
          
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -270,7 +270,7 @@
         ar3kconfig.pHCIDev = pHcidevInfo->pHCIDev;
         ar3kconfig.pHCIProps = &pHcidevInfo->HCIProps;
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-        ar3kconfig.pHIFDevice = (HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice);
+        ar3kconfig.pHIFDevice = (struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice);
 #else
         ar3kconfig.pHIFDevice = pHcidevInfo->ar->arHifDevice;
 #endif
@@ -285,8 +285,8 @@
         
         if ((hciuartscale != 0) || (hciuartstep != 0)) {   
                 /* user wants to tune HCI bridge UART scale/step values */
-            ar3kconfig.AR6KScale = (A_UINT16)hciuartscale;
-            ar3kconfig.AR6KStep = (A_UINT16)hciuartstep;           
+            ar3kconfig.AR6KScale = (u16)hciuartscale;
+            ar3kconfig.AR6KStep = (u16)hciuartstep;
             ar3kconfig.Flags |= AR3K_CONFIG_FLAG_SET_AR6K_SCALE_STEP;
         }
         
@@ -294,7 +294,7 @@
         address = TARG_VTOP(pHcidevInfo->ar->arTargetType, 
                             HOST_INTEREST_ITEM_ADDRESS(pHcidevInfo->ar, hi_hci_uart_pwr_mgmt_params));
         status = ar6000_ReadRegDiag(pHcidevInfo->ar->arHifDevice, &address, &hci_uart_pwr_mgmt_params);
-        if (A_OK == status) {
+        if (0 == status) {
             ar3kconfig.PwrMgmtEnabled = (hci_uart_pwr_mgmt_params & 0x1);
             ar3kconfig.IdleTimeout = (hci_uart_pwr_mgmt_params & 0xFFFF0000) >> 16;
             ar3kconfig.WakeupTimeout = (hci_uart_pwr_mgmt_params & 0xFF00) >> 8;
@@ -304,28 +304,28 @@
         /* configure the AR3K device */         
 		memcpy(ar3kconfig.bdaddr,pHcidevInfo->ar->bdaddr,6);
         status = AR3KConfigure(&ar3kconfig);
-        if (A_FAILED(status)) {
+        if (status) {
             break; 
         }
 
         /* Make sure both AR6K and AR3K have power management enabled */
         if (ar3kconfig.PwrMgmtEnabled) {
-            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, TRUE);
-            if (A_FAILED(status)) {
+            status = HCI_TransportEnablePowerMgmt(pHcidevInfo->pHCIDev, true);
+            if (status) {
                 AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to enable TLPM for AR6K! \n"));
             }
         }
         
         status = bt_register_hci(pHcidevInfo);
         
-    } while (FALSE);
+    } while (false);
 
     return status; 
 }
 
-static void ar6000_hci_transport_failure(void *pContext, A_STATUS Status)
+static void ar6000_hci_transport_failure(void *pContext, int Status)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: transport failure! \n"));
     
@@ -336,7 +336,7 @@
 
 static void ar6000_hci_transport_removed(void *pContext)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     
     AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: transport removed. \n"));
     
@@ -347,14 +347,14 @@
     pHcidevInfo->pHCIDev = NULL;
 }
 
-static void ar6000_hci_send_complete(void *pContext, HTC_PACKET *pPacket)
+static void ar6000_hci_send_complete(void *pContext, struct htc_packet *pPacket)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     void                 *osbuf = pPacket->pPktContext;
     A_ASSERT(osbuf != NULL);
     A_ASSERT(pHcidevInfo != NULL);
     
-    if (A_FAILED(pPacket->Status)) {
+    if (pPacket->Status) {
         if ((pPacket->Status != A_ECANCELED) && (pPacket->Status != A_NO_RESOURCE)) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: Send Packet Failed: %d \n",pPacket->Status)); 
         }   
@@ -365,9 +365,9 @@
     
 }
 
-static void ar6000_hci_pkt_recv(void *pContext, HTC_PACKET *pPacket)
+static void ar6000_hci_pkt_recv(void *pContext, struct htc_packet *pPacket)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     struct sk_buff       *skb;
     
     A_ASSERT(pHcidevInfo != NULL);
@@ -376,7 +376,7 @@
           
     do {
         
-        if (A_FAILED(pPacket->Status)) {
+        if (pPacket->Status) {
             break;
         }
   
@@ -419,7 +419,7 @@
             skb = NULL;
         } 
         
-    } while (FALSE);
+    } while (false);
     
     FreeHTCStruct(pHcidevInfo,pPacket);
     
@@ -432,7 +432,7 @@
 
 static void  ar6000_hci_pkt_refill(void *pContext, HCI_TRANSPORT_PACKET_TYPE Type, int BuffersAvailable)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     int                  refillCount;
 
     if (Type == HCI_ACL_TYPE) {
@@ -447,9 +447,9 @@
     
 }
 
-static HCI_SEND_FULL_ACTION  ar6000_hci_pkt_send_full(void *pContext, HTC_PACKET *pPacket)
+static HCI_SEND_FULL_ACTION  ar6000_hci_pkt_send_full(void *pContext, struct htc_packet *pPacket)
 {
-    AR6K_HCI_BRIDGE_INFO    *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)pContext;
+    struct ar6k_hci_bridge_info    *pHcidevInfo = (struct ar6k_hci_bridge_info *)pContext;
     HCI_SEND_FULL_ACTION    action = HCI_SEND_FULL_KEEP;
     
     if (!pHcidevInfo->HciNormalMode) {
@@ -464,31 +464,31 @@
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(void *ar)
+int ar6000_setup_hci(void *ar)
 #else
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
+int ar6000_setup_hci(struct ar6_softc *ar)
 #endif
 {
-    HCI_TRANSPORT_CONFIG_INFO config;
-    A_STATUS                  status = A_OK;
+    struct hci_transport_config_info config;
+    int                  status = 0;
     int                       i;
-    HTC_PACKET                *pPacket;
-    AR6K_HCI_BRIDGE_INFO      *pHcidevInfo;
+    struct htc_packet                *pPacket;
+    struct ar6k_hci_bridge_info      *pHcidevInfo;
         
        
     do {
         
-        pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)A_MALLOC(sizeof(AR6K_HCI_BRIDGE_INFO));
+        pHcidevInfo = (struct ar6k_hci_bridge_info *)A_MALLOC(sizeof(struct ar6k_hci_bridge_info));
         
         if (NULL == pHcidevInfo) {
             status = A_NO_MEMORY;
             break;    
         }
         
-        A_MEMZERO(pHcidevInfo, sizeof(AR6K_HCI_BRIDGE_INFO));
+        A_MEMZERO(pHcidevInfo, sizeof(struct ar6k_hci_bridge_info));
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
         g_pHcidevInfo = pHcidevInfo;
-        pHcidevInfo->HCITransHdl = *(HCI_TRANSPORT_MISC_HANDLES *)ar;
+        pHcidevInfo->HCITransHdl = *(struct hci_transport_misc_handles *)ar;
 #else
         ar->hcidev_info = pHcidevInfo;
         pHcidevInfo->ar = ar;
@@ -499,7 +499,7 @@
         ar->exitCallback = AR3KConfigureExit;
     
         status = bt_setup_hci(pHcidevInfo);
-        if (A_FAILED(status)) {
+        if (status) {
             break;    
         }
         
@@ -509,19 +509,19 @@
             AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: running in test mode... \n"));     
         }
         
-        pHcidevInfo->pHTCStructAlloc = (A_UINT8 *)A_MALLOC((sizeof(HTC_PACKET)) * NUM_HTC_PACKET_STRUCTS);
+        pHcidevInfo->pHTCStructAlloc = (u8 *)A_MALLOC((sizeof(struct htc_packet)) * NUM_HTC_PACKET_STRUCTS);
         
         if (NULL == pHcidevInfo->pHTCStructAlloc) {
             status = A_NO_MEMORY;
             break;    
         }
         
-        pPacket = (HTC_PACKET *)pHcidevInfo->pHTCStructAlloc;
+        pPacket = (struct htc_packet *)pHcidevInfo->pHTCStructAlloc;
         for (i = 0; i < NUM_HTC_PACKET_STRUCTS; i++,pPacket++) {
             FreeHTCStruct(pHcidevInfo,pPacket);                
         }
         
-        A_MEMZERO(&config,sizeof(HCI_TRANSPORT_CONFIG_INFO));        
+        A_MEMZERO(&config,sizeof(struct hci_transport_config_info));        
         config.ACLRecvBufferWaterMark = MAX_ACL_RECV_BUFS / 2;
         config.EventRecvBufferWaterMark = MAX_EVT_RECV_BUFS / 2;
         config.MaxSendQueueDepth = MAX_HCI_WRITE_QUEUE_DEPTH;
@@ -544,14 +544,14 @@
             status = A_ERROR;      
         }
     
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         if (pHcidevInfo != NULL) {
             if (NULL == pHcidevInfo->pHCIDev) {
                 /* GMBOX may not be present in older chips */
                 /* just return success */ 
-                status = A_OK;
+                status = 0;
             }
         }
         ar6000_cleanup_hci(ar);    
@@ -563,13 +563,13 @@
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 void  ar6000_cleanup_hci(void *ar)
 #else
-void  ar6000_cleanup_hci(AR_SOFTC_T *ar)
+void  ar6000_cleanup_hci(struct ar6_softc *ar)
 #endif
 {
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo;
+    struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo;
 #else
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
 #endif
     
     if (pHcidevInfo != NULL) {
@@ -596,20 +596,20 @@
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS hci_test_send(void *ar, struct sk_buff *skb)
+int hci_test_send(void *ar, struct sk_buff *skb)
 #else
-A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb)
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb)
 #endif
 {
-    int              status = A_OK;
+    int              status = 0;
     int              length;
     EPPING_HEADER    *pHeader;
-    HTC_PACKET       *pPacket;   
+    struct htc_packet       *pPacket;   
     HTC_TX_TAG       htc_tag = AR6K_DATA_PKT_TAG;
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = g_pHcidevInfo;
+    struct ar6k_hci_bridge_info *pHcidevInfo = g_pHcidevInfo;
 #else
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
 #endif
             
     do {
@@ -656,18 +656,18 @@
                                HCI_ACL_TYPE,  /* send every thing out as ACL */
                                htc_tag);
              
-        HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE);                           
+        HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false);
         pPacket = NULL;
             
-    } while (FALSE);
+    } while (false);
             
     return status;
 }
 
-void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig)
+void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig)
 {
-    AR6K_HCI_BRIDGE_INFO *pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)ar->hcidev_info;
-    AR3K_CONFIG_INFO *config = (AR3K_CONFIG_INFO *)ar3kconfig;
+    struct ar6k_hci_bridge_info *pHcidevInfo = (struct ar6k_hci_bridge_info *)ar->hcidev_info;
+    struct ar3k_config_info *config = (struct ar3k_config_info *)ar3kconfig;
 
     config->pHCIDev = pHcidevInfo->pHCIDev;
     config->pHCIProps = &pHcidevInfo->HCIProps;
@@ -710,9 +710,9 @@
 {
     struct hci_dev             *hdev = (struct hci_dev *)skb->dev;
     HCI_TRANSPORT_PACKET_TYPE  type;
-    AR6K_HCI_BRIDGE_INFO       *pHcidevInfo;
-    HTC_PACKET                 *pPacket;
-    A_STATUS                   status = A_OK;
+    struct ar6k_hci_bridge_info       *pHcidevInfo;
+    struct htc_packet                 *pPacket;
+    int                   status = 0;
     struct sk_buff             *txSkb = NULL;
     
     if (!hdev) {
@@ -725,7 +725,7 @@
         return -EBUSY;
     }
   
-    pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)hdev->driver_data;   
+    pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data;   
     A_ASSERT(pHcidevInfo != NULL);
       
     AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("+bt_send_frame type: %d \n",bt_cb(skb)->pkt_type));
@@ -747,7 +747,7 @@
             kfree_skb(skb);
             return 0;
         default:
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             kfree_skb(skb);
             return 0;
     } 
@@ -757,7 +757,7 @@
                         (type == HCI_COMMAND_TYPE) ? "COMMAND" : "ACL",
                         skb->len));
         if (type == HCI_COMMAND_TYPE) {
-            A_UINT16 opcode = HCI_GET_OP_CODE(skb->data);
+            u16 opcode = HCI_GET_OP_CODE(skb->data);
             AR_DEBUG_PRINTF(ATH_DEBUG_ANY,("    HCI Command: OGF:0x%X OCF:0x%X \r\n", 
                   opcode >> 10, opcode & 0x3FF));
         }
@@ -778,7 +778,7 @@
         bt_cb(txSkb)->pkt_type = bt_cb(skb)->pkt_type;
         txSkb->dev = (void *)pHcidevInfo->pBtStackHCIDev;
         skb_reserve(txSkb, TX_PACKET_RSV_OFFSET + pHcidevInfo->HCIProps.HeadRoom);
-        A_MEMCPY(txSkb->data, skb->data, skb->len);
+        memcpy(txSkb->data, skb->data, skb->len);
         skb_put(txSkb,skb->len);
         
         pPacket = AllocHTCStruct(pHcidevInfo);        
@@ -802,11 +802,11 @@
         AR_DEBUG_PRINTF(ATH_DEBUG_HCI_SEND, ("HCI Bridge: type:%d, Total Length:%d Bytes \n",
                                       type, txSkb->len));
                                       
-        status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,FALSE);   
+        status = HCI_TransportSendPkt(pHcidevInfo->pHCIDev,pPacket,false);
         pPacket = NULL;
         txSkb = NULL;
         
-    } while (FALSE);
+    } while (false);
    
     if (txSkb != NULL) {
         kfree_skb(txSkb);    
@@ -832,11 +832,11 @@
 */
 static int bt_flush(struct hci_dev *hdev)
 {
-    AR6K_HCI_BRIDGE_INFO    *pHcidevInfo; 
+    struct ar6k_hci_bridge_info    *pHcidevInfo; 
     
     AR_DEBUG_PRINTF(ATH_DEBUG_TRC, ("HCI Bridge: bt_flush - enter\n"));
     
-    pHcidevInfo = (AR6K_HCI_BRIDGE_INFO *)hdev->driver_data;   
+    pHcidevInfo = (struct ar6k_hci_bridge_info *)hdev->driver_data;   
     
     /* TODO??? */   
     
@@ -853,14 +853,14 @@
     /* nothing to do here */
 }
 
-static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    A_STATUS                    status = A_OK;
+    int                    status = 0;
     struct hci_dev              *pHciDev = NULL;
-    HIF_DEVICE_OS_DEVICE_INFO   osDevInfo;
+    struct hif_device_os_device_info   osDevInfo;
     
     if (!setupbtdev) {
-        return A_OK;    
+        return 0;
     } 
         
     do {
@@ -868,7 +868,7 @@
         A_MEMZERO(&osDevInfo,sizeof(osDevInfo));
             /* get the underlying OS device */
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-        status = ar6000_get_hif_dev((HIF_DEVICE *)(pHcidevInfo->HCITransHdl.hifDevice), 
+        status = ar6000_get_hif_dev((struct hif_device *)(pHcidevInfo->HCITransHdl.hifDevice), 
                                     &osDevInfo);
 #else
         status = HIFConfigureDevice(pHcidevInfo->ar->arHifDevice, 
@@ -877,7 +877,7 @@
                                     sizeof(osDevInfo));
 #endif
                                     
-        if (A_FAILED(status)) {
+        if (status) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Failed to OS device info from HIF\n"));
             break;
         }
@@ -902,23 +902,23 @@
         pHciDev->destruct = bt_destruct;
         pHciDev->owner = THIS_MODULE; 
             /* driver is running in normal BT mode */
-        pHcidevInfo->HciNormalMode = TRUE;  
+        pHcidevInfo->HciNormalMode = true;
         
-    } while (FALSE);
+    } while (false);
     
-    if (A_FAILED(status)) {
+    if (status) {
         bt_cleanup_hci(pHcidevInfo);    
     }
     
     return status;
 }
 
-static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {   
     int   err;      
         
     if (pHcidevInfo->HciRegistered) {
-        pHcidevInfo->HciRegistered = FALSE;
+        pHcidevInfo->HciRegistered = false;
         clear_bit(HCI_RUNNING, &pHcidevInfo->pBtStackHCIDev->flags);
         clear_bit(HCI_UP, &pHcidevInfo->pBtStackHCIDev->flags);
         clear_bit(HCI_INIT, &pHcidevInfo->pBtStackHCIDev->flags);   
@@ -929,43 +929,41 @@
         }          
     }   
     
-    if (pHcidevInfo->pBtStackHCIDev != NULL) {
-        kfree(pHcidevInfo->pBtStackHCIDev);
-        pHcidevInfo->pBtStackHCIDev = NULL;
-    }  
+    kfree(pHcidevInfo->pBtStackHCIDev);
+    pHcidevInfo->pBtStackHCIDev = NULL;  
 }
 
-static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
     int       err;
-    A_STATUS  status = A_OK;
+    int  status = 0;
     
     do {          
         AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: registering HCI... \n"));
         A_ASSERT(pHcidevInfo->pBtStackHCIDev != NULL);
              /* mark that we are registered */
-        pHcidevInfo->HciRegistered = TRUE;
+        pHcidevInfo->HciRegistered = true;
         if ((err = hci_register_dev(pHcidevInfo->pBtStackHCIDev)) < 0) {
             AR_DEBUG_PRINTF(ATH_DEBUG_ERR, ("HCI Bridge: failed to register with bluetooth %d\n",err));
-            pHcidevInfo->HciRegistered = FALSE;
+            pHcidevInfo->HciRegistered = false;
             status = A_ERROR;
             break;
         }
     
         AR_DEBUG_PRINTF(ATH_DEBUG_HCI_BRIDGE, ("HCI Bridge: HCI registered \n"));
         
-    } while (FALSE);
+    } while (false);
     
     return status;
 }
 
-static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static bool bt_indicate_recv(struct ar6k_hci_bridge_info      *pHcidevInfo,
                                HCI_TRANSPORT_PACKET_TYPE Type, 
                                struct                    sk_buff *skb)
 {
-    A_UINT8               btType;
+    u8 btType;
     int                   len;
-    A_BOOL                success = FALSE;
+    bool                success = false;
     BT_HCI_EVENT_HEADER   *pEvent;
     
     do {
@@ -984,7 +982,7 @@
                 break;
             default:
                 btType = 0;
-                A_ASSERT(FALSE);
+                A_ASSERT(false);
                 break;
         } 
         
@@ -1015,14 +1013,14 @@
                     ("HCI Bridge: Indicated RCV of type:%d, Length:%d \n",btType,len));
         }
             
-        success = TRUE;
+        success = true;
     
-    } while (FALSE); 
+    } while (false);
     
     return success;
 }
 
-static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length) 
+static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) 
 { 
     struct sk_buff *skb;         
         /* in normal HCI mode we need to alloc from the bt core APIs */
@@ -1033,7 +1031,7 @@
     return skb;
 }
 
-static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb)
+static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb)
 {
     kfree_skb(skb);    
 }
@@ -1041,36 +1039,36 @@
 #else // { CONFIG_BLUEZ_HCI_BRIDGE
 
     /* stubs when we only want to test the HCI bridging Interface without the HT stack */
-static A_STATUS bt_setup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_setup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    return A_OK;    
+    return 0;
 }
-static void bt_cleanup_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static void bt_cleanup_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {   
      
 }
-static A_STATUS bt_register_hci(AR6K_HCI_BRIDGE_INFO *pHcidevInfo)
+static int bt_register_hci(struct ar6k_hci_bridge_info *pHcidevInfo)
 {
-    A_ASSERT(FALSE);
+    A_ASSERT(false);
     return A_ERROR;    
 }
 
-static A_BOOL bt_indicate_recv(AR6K_HCI_BRIDGE_INFO      *pHcidevInfo, 
+static bool bt_indicate_recv(struct ar6k_hci_bridge_info      *pHcidevInfo,
                                HCI_TRANSPORT_PACKET_TYPE Type, 
                                struct                    sk_buff *skb)
 {
-    A_ASSERT(FALSE);
-    return FALSE;    
+    A_ASSERT(false);
+    return false;
 }
 
-static struct sk_buff* bt_alloc_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, int Length) 
+static struct sk_buff* bt_alloc_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, int Length) 
 {
-    A_ASSERT(FALSE);
+    A_ASSERT(false);
     return NULL;
 }
-static void bt_free_buffer(AR6K_HCI_BRIDGE_INFO *pHcidevInfo, struct sk_buff *skb)
+static void bt_free_buffer(struct ar6k_hci_bridge_info *pHcidevInfo, struct sk_buff *skb)
 {
-    A_ASSERT(FALSE);
+    A_ASSERT(false);
 }
 
 #endif // } CONFIG_BLUEZ_HCI_BRIDGE
@@ -1080,25 +1078,25 @@
     /* stubs when GMBOX support is not needed */
     
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(void *ar)
+int ar6000_setup_hci(void *ar)
 #else
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar)
+int ar6000_setup_hci(struct ar6_softc *ar)
 #endif
 {
-    return A_OK;   
+    return 0;
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 void ar6000_cleanup_hci(void *ar)
 #else
-void ar6000_cleanup_hci(AR_SOFTC_T *ar)
+void ar6000_cleanup_hci(struct ar6_softc *ar)
 #endif
 {
     return;    
 }
 
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
-void ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig)
+void ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig)
 {
     return;
 }
@@ -1107,7 +1105,7 @@
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
 int hci_test_send(void *ar, struct sk_buff *skb)
 #else
-int hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb)
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb)
 #endif
 {
     return -EOPNOTSUPP;
@@ -1120,14 +1118,14 @@
 static int __init
 hcibridge_init_module(void)
 {
-    A_STATUS status;
-    HCI_TRANSPORT_CALLBACKS hciTransCallbacks;
+    int status;
+    struct hci_transport_callbacks hciTransCallbacks;
 
     hciTransCallbacks.setupTransport = ar6000_setup_hci;
     hciTransCallbacks.cleanupTransport = ar6000_cleanup_hci;
 
     status = ar6000_register_hci_transport(&hciTransCallbacks);
-    if(status != A_OK)
+    if (status)
         return -ENODEV;
 
     return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h	2012-03-24 01:13:24.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/ar6000_drv.h	2012-03-24 03:33:51.000000000 -0400
@@ -104,7 +104,7 @@
     struct ieee80211req_key   ucast_ik;
     struct ieee80211req_key   bcast_ik;
     CRYPTO_TYPE               keyType;
-    A_BOOL                    keyOk;
+    bool                    keyOk;
 };
 #endif
 
@@ -121,8 +121,8 @@
 #define DBG_DEFAULTS    (DBG_ERROR|DBG_WARNING)
 
 
-A_STATUS ar6000_ReadRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
-A_STATUS ar6000_WriteRegDiag(HIF_DEVICE *hifDevice, A_UINT32 *address, A_UINT32 *data);
+int ar6000_ReadRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
+int ar6000_WriteRegDiag(struct hif_device *hifDevice, u32 *address, u32 *data);
 
 #ifdef __cplusplus
 extern "C" {
@@ -362,7 +362,7 @@
     int currPtr;
     int length;
     unsigned char data[HTC_RAW_BUFFER_SIZE];
-    HTC_PACKET    HTCPacket;
+    struct htc_packet    HTCPacket;
 } raw_htc_buffer;
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
@@ -380,41 +380,47 @@
 #endif /* CONFIG_HOST_TCMD_SUPPORT */
 
 struct ar_wep_key {
-    A_UINT8                 arKeyIndex;
-    A_UINT8                 arKeyLen;
-    A_UINT8                 arKey[64];
+    u8 arKeyIndex;
+    u8 arKeyLen;
+    u8 arKey[64];
 } ;
 
 #ifdef ATH6K_CONFIG_CFG80211
 struct ar_key {
-    A_UINT8     key[WLAN_MAX_KEY_LEN];
-    A_UINT8     key_len;
-    A_UINT8     seq[IW_ENCODE_SEQ_MAX_SIZE];
-    A_UINT8     seq_len;
-    A_UINT32    cipher;
+    u8 key[WLAN_MAX_KEY_LEN];
+    u8 key_len;
+    u8 seq[IW_ENCODE_SEQ_MAX_SIZE];
+    u8 seq_len;
+    u32 cipher;
+};
+
+enum {
+    SME_DISCONNECTED,
+    SME_CONNECTING,
+    SME_CONNECTED
 };
 #endif /* ATH6K_CONFIG_CFG80211 */
 
 
 struct ar_node_mapping {
-    A_UINT8                 macAddress[6];
-    A_UINT8                 epId;
-    A_UINT8                 txPending;
+    u8 macAddress[6];
+    u8 epId;
+    u8 txPending;
 };
 
 struct ar_cookie {
     unsigned long          arc_bp[2];    /* Must be first field */
-    HTC_PACKET             HtcPkt;       /* HTC packet wrapper */
+    struct htc_packet             HtcPkt;       /* HTC packet wrapper */
     struct ar_cookie *arc_list_next;
 };
 
 struct ar_hb_chlng_resp {
     A_TIMER                 timer;
-    A_UINT32                frequency;
-    A_UINT32                seqNum;
-    A_BOOL                  outstanding;
-    A_UINT8                 missCnt;
-    A_UINT8                 missThres;
+    u32 frequency;
+    u32 seqNum;
+    bool                  outstanding;
+    u8 missCnt;
+    u8 missThres;
 };
 
 /* Per STA data, used in AP mode */
@@ -436,13 +442,13 @@
 #define STA_IS_PS_POLLED(sta) (sta->flags & (STA_PS_POLLED_MASK << STA_PS_POLLED_SHIFT))
 
 typedef struct {
-    A_UINT16                flags;
-    A_UINT8                 mac[ATH_MAC_LEN];
-    A_UINT8                 aid;
-    A_UINT8                 keymgmt;
-    A_UINT8                 ucipher;
-    A_UINT8                 auth;
-    A_UINT8                 wpa_ie[IEEE80211_MAX_IE];
+    u16 flags;
+    u8 mac[ATH_MAC_LEN];
+    u8 aid;
+    u8 keymgmt;
+    u8 ucipher;
+    u8 auth;
+    u8 wpa_ie[IEEE80211_MAX_IE];
     A_NETBUF_QUEUE_T        psq;    /* power save q */
     A_MUTEX_T               psqLock;
 } sta_t;
@@ -456,173 +462,174 @@
     wait_queue_head_t       raw_htc_write_queue[HTC_RAW_STREAM_NUM_MAX];
     raw_htc_buffer          raw_htc_read_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_READ_BUFFERS_NUM];
     raw_htc_buffer          raw_htc_write_buffer[HTC_RAW_STREAM_NUM_MAX][RAW_HTC_WRITE_BUFFERS_NUM];
-    A_BOOL                  write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
-    A_BOOL                  read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
+    bool                  write_buffer_available[HTC_RAW_STREAM_NUM_MAX];
+    bool                  read_buffer_available[HTC_RAW_STREAM_NUM_MAX];
 } AR_RAW_HTC_T;
 
-typedef struct ar6_softc {
+struct ar6_softc {
     struct net_device       *arNetDev;    /* net_device pointer */
     void                    *arWmi;
     int                     arTxPending[ENDPOINT_MAX];
     int                     arTotalTxDataPending;
-    A_UINT8                 arNumDataEndPts;
-    A_BOOL                  arWmiEnabled;
-    A_BOOL                  arWmiReady;
-    A_BOOL                  arConnected;
+    u8 arNumDataEndPts;
+    bool                  arWmiEnabled;
+    bool                  arWmiReady;
+    bool                  arConnected;
     HTC_HANDLE              arHtcTarget;
     void                    *arHifDevice;
     spinlock_t              arLock;
     struct semaphore        arSem;
     int                     arSsidLen;
     u_char                  arSsid[32];
-    A_UINT8                 arNextMode;
-    A_UINT8                 arNetworkType;
-    A_UINT8                 arDot11AuthMode;
-    A_UINT8                 arAuthMode;
-    A_UINT8                 arPairwiseCrypto;
-    A_UINT8                 arPairwiseCryptoLen;
-    A_UINT8                 arGroupCrypto;
-    A_UINT8                 arGroupCryptoLen;
-    A_UINT8                 arDefTxKeyIndex;
+    u8 arNextMode;
+    u8 arNetworkType;
+    u8 arDot11AuthMode;
+    u8 arAuthMode;
+    u8 arPairwiseCrypto;
+    u8 arPairwiseCryptoLen;
+    u8 arGroupCrypto;
+    u8 arGroupCryptoLen;
+    u8 arDefTxKeyIndex;
     struct ar_wep_key       arWepKeyList[WMI_MAX_KEY_INDEX + 1];
-    A_UINT8                 arBssid[6];
-    A_UINT8                 arReqBssid[6];
-    A_UINT16                arChannelHint;
-    A_UINT16                arBssChannel;
-    A_UINT16                arListenIntervalB;
-    A_UINT16                arListenIntervalT;
+    u8 arBssid[6];
+    u8 arReqBssid[6];
+    u16 arChannelHint;
+    u16 arBssChannel;
+    u16 arListenIntervalB;
+    u16 arListenIntervalT;
     struct ar6000_version   arVersion;
-    A_UINT32                arTargetType;
-    A_INT8                  arRssi;
-    A_UINT8                 arTxPwr;
-    A_BOOL                  arTxPwrSet;
-    A_INT32                 arBitRate;
+    u32 arTargetType;
+    s8 arRssi;
+    u8 arTxPwr;
+    bool                  arTxPwrSet;
+    s32 arBitRate;
     struct net_device_stats arNetStats;
     struct iw_statistics    arIwStats;
-    A_INT8                  arNumChannels;
-    A_UINT16                arChannelList[32];
-    A_UINT32                arRegCode;
-    A_BOOL                  statsUpdatePending;
+    s8 arNumChannels;
+    u16 arChannelList[32];
+    u32 arRegCode;
+    bool                  statsUpdatePending;
     TARGET_STATS            arTargetStats;
-    A_INT8                  arMaxRetries;
-    A_UINT8                 arPhyCapability;
+    s8 arMaxRetries;
+    u8 arPhyCapability;
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-    A_UINT8                 tcmdRxReport;
-    A_UINT32                tcmdRxTotalPkt;
-    A_INT32                 tcmdRxRssi;
-    A_UINT32                tcmdPm;
-    A_UINT32                arTargetMode;
-    A_UINT32                tcmdRxcrcErrPkt;
-    A_UINT32                tcmdRxsecErrPkt;
-    A_UINT16                tcmdRateCnt[TCMD_MAX_RATES];
-    A_UINT16                tcmdRateCntShortGuard[TCMD_MAX_RATES];
+    u8 tcmdRxReport;
+    u32 tcmdRxTotalPkt;
+    s32 tcmdRxRssi;
+    u32 tcmdPm;
+    u32 arTargetMode;
+    u32 tcmdRxcrcErrPkt;
+    u32 tcmdRxsecErrPkt;
+    u16 tcmdRateCnt[TCMD_MAX_RATES];
+    u16 tcmdRateCntShortGuard[TCMD_MAX_RATES];
 #endif
     AR6000_WLAN_STATE       arWlanState;
     struct ar_node_mapping  arNodeMap[MAX_NODE_NUM];
-    A_UINT8                 arIbssPsEnable;
-    A_UINT8                 arNodeNum;
-    A_UINT8                 arNexEpId;
+    u8 arIbssPsEnable;
+    u8 arNodeNum;
+    u8 arNexEpId;
     struct ar_cookie        *arCookieList;
-    A_UINT32                arCookieCount;
-    A_UINT32                arRateMask;
-    A_UINT8                 arSkipScan;
-    A_UINT16                arBeaconInterval;
-    A_BOOL                  arConnectPending;
-    A_BOOL                  arWmmEnabled;
+    u32 arCookieCount;
+    u32 arRateMask;
+    u8 arSkipScan;
+    u16 arBeaconInterval;
+    bool                  arConnectPending;
+    bool                  arWmmEnabled;
     struct ar_hb_chlng_resp arHBChallengeResp;
-    A_UINT8                 arKeepaliveConfigured;
-    A_UINT32                arMgmtFilter;
+    u8 arKeepaliveConfigured;
+    u32 arMgmtFilter;
     HTC_ENDPOINT_ID         arAc2EpMapping[WMM_NUM_AC];
-    A_BOOL                  arAcStreamActive[WMM_NUM_AC];
-    A_UINT8                 arAcStreamPriMap[WMM_NUM_AC];
-    A_UINT8                 arHiAcStreamActivePri;
-    A_UINT8                 arEp2AcMapping[ENDPOINT_MAX];
+    bool                  arAcStreamActive[WMM_NUM_AC];
+    u8 arAcStreamPriMap[WMM_NUM_AC];
+    u8 arHiAcStreamActivePri;
+    u8 arEp2AcMapping[ENDPOINT_MAX];
     HTC_ENDPOINT_ID         arControlEp;
 #ifdef HTC_RAW_INTERFACE
     AR_RAW_HTC_T            *arRawHtc;
 #endif
-    A_BOOL                  arNetQueueStopped;
-    A_BOOL                  arRawIfInit;
+    bool                  arNetQueueStopped;
+    bool                  arRawIfInit;
     int                     arDeviceIndex;
-    COMMON_CREDIT_STATE_INFO arCreditStateInfo;
-    A_BOOL                  arWMIControlEpFull;
-    A_BOOL                  dbgLogFetchInProgress;
-    A_UCHAR                 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE];
-    A_UINT32                log_cnt;
-    A_UINT32                dbglog_init_done;
-    A_UINT32                arConnectCtrlFlags;
+    struct common_credit_state_info arCreditStateInfo;
+    bool                  arWMIControlEpFull;
+    bool                  dbgLogFetchInProgress;
+    u8                 log_buffer[DBGLOG_HOST_LOG_BUFFER_SIZE];
+    u32 log_cnt;
+    u32 dbglog_init_done;
+    u32 arConnectCtrlFlags;
 #ifdef USER_KEYS
-    A_INT32                 user_savedkeys_stat;
-    A_UINT32                user_key_ctrl;
+    s32 user_savedkeys_stat;
+    u32 user_key_ctrl;
     struct USER_SAVEDKEYS   user_saved_keys;
 #endif
     USER_RSSI_THOLD rssi_map[12];
-    A_UINT8                arUserBssFilter;
-    A_UINT16                ap_profile_flag;    /* AP mode */
+    u8 arUserBssFilter;
+    u16 ap_profile_flag;    /* AP mode */
     WMI_AP_ACL              g_acl;              /* AP mode */
     sta_t                   sta_list[AP_MAX_NUM_STA]; /* AP mode */
-    A_UINT8                 sta_list_index;     /* AP mode */
+    u8 sta_list_index;     /* AP mode */
     struct ieee80211req_key ap_mode_bkey;           /* AP mode */
     A_NETBUF_QUEUE_T        mcastpsq;    /* power save q for Mcast frames */
     A_MUTEX_T               mcastpsqLock;
-    A_BOOL                  DTIMExpired; /* flag to indicate DTIM expired */
-    A_UINT8                 intra_bss;   /* enable/disable intra bss data forward */
+    bool                  DTIMExpired; /* flag to indicate DTIM expired */
+    u8 intra_bss;   /* enable/disable intra bss data forward */
     void                    *aggr_cntxt;
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
     void                    *hcidev_info;
 #endif
     void                    *hcipal_info;
     WMI_AP_MODE_STAT        arAPStats;
-    A_UINT8                 ap_hidden_ssid;
-    A_UINT8                 ap_country_code[3];
-    A_UINT8                 ap_wmode;
-    A_UINT8                 ap_dtim_period;
-    A_UINT16                ap_beacon_interval;
-    A_UINT16                arRTS;
-    A_UINT16                arACS; /* AP mode - Auto Channel Selection */
-    HTC_PACKET_QUEUE        amsdu_rx_buffer_queue;
-    A_BOOL                  bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */
+    u8 ap_hidden_ssid;
+    u8 ap_country_code[3];
+    u8 ap_wmode;
+    u8 ap_dtim_period;
+    u16 ap_beacon_interval;
+    u16 arRTS;
+    u16 arACS; /* AP mode - Auto Channel Selection */
+    struct htc_packet_queue        amsdu_rx_buffer_queue;
+    bool                  bIsDestroyProgress; /* flag to indicate ar6k destroy is in progress */
     A_TIMER                 disconnect_timer;
-    A_UINT8		    rxMetaVersion;
+    u8 rxMetaVersion;
 #ifdef WAPI_ENABLE
-    A_UINT8                 arWapiEnable;
+    u8 arWapiEnable;
 #endif
 	WMI_BTCOEX_CONFIG_EVENT arBtcoexConfig;
 	WMI_BTCOEX_STATS_EVENT  arBtcoexStats;
-    A_INT32                 (*exitCallback)(void *config);  /* generic callback at AR6K exit */
-    HIF_DEVICE_OS_DEVICE_INFO   osDevInfo;
+    s32 (*exitCallback)(void *config);  /* generic callback at AR6K exit */
+    struct hif_device_os_device_info   osDevInfo;
 #ifdef ATH6K_CONFIG_CFG80211
     struct wireless_dev *wdev;
     struct cfg80211_scan_request    *scan_request;
     struct ar_key   keys[WMI_MAX_KEY_INDEX + 1];
+    u32 smeState;
 #endif /* ATH6K_CONFIG_CFG80211 */
-    A_UINT16                arWlanPowerState;
-    A_BOOL                  arWlanOff;
+    u16 arWlanPowerState;
+    bool                  arWlanOff;
 #ifdef CONFIG_PM
-    A_UINT16                arWowState;
-    A_BOOL                  arBTOff;
-    A_BOOL                  arBTSharing;
-    A_UINT16                arSuspendConfig;
-    A_UINT16                arWlanOffConfig;
-    A_UINT16                arWow2Config;
+    u16 arWowState;
+    bool                  arBTOff;
+    bool                  arBTSharing;
+    u16 arSuspendConfig;
+    u16 arWlanOffConfig;
+    u16 arWow2Config;
 #endif
-    A_UINT8                 scan_triggered;
+    u8 scan_triggered;
     WMI_SCAN_PARAMS_CMD     scParams;
 #define AR_MCAST_FILTER_MAC_ADDR_SIZE  4
-    A_UINT8                 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE];
-    A_UINT8                 bdaddr[6];
-    A_BOOL                  scanSpecificSsid;
+    u8 mcast_filters[MAC_MAX_FILTERS_PER_LIST][AR_MCAST_FILTER_MAC_ADDR_SIZE];
+    u8 bdaddr[6];
+    bool                  scanSpecificSsid;
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
     void                    *arApDev;
 #endif
-} AR_SOFTC_T;
+};
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-typedef struct {
+struct ar_virtual_interface {
     struct net_device       *arNetDev;    /* net_device pointer */
-    AR_SOFTC_T              *arDev;       /* ar device pointer */
+    struct ar6_softc              *arDev;       /* ar device pointer */
     struct net_device       *arStaNetDev; /* net_device pointer */
-} AR_VIRTUAL_INTERFACE_T;
+};
 #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
 #ifdef ATH6K_CONFIG_CFG80211
@@ -638,7 +645,7 @@
 
     if (arApNetDev == dev) {
         /* return arDev saved in virtual interface context */
-        AR_VIRTUAL_INTERFACE_T *arVirDev;
+        struct ar_virtual_interface *arVirDev;
         arVirDev = netdev_priv(dev);
         return arVirDev->arDev;   
     } else {
@@ -672,9 +679,9 @@
 #define arEndpoint2RawStreamID(ar,ep)           (ar)->arRawHtc->arEp2RawMapping[(ep)]
 
 struct ar_giwscan_param {
-    char    *current_ev;
-    char    *end_buf;
-    A_UINT32 bytes_needed;
+    char *current_ev;
+    char *end_buf;
+    u32 bytes_needed;
     struct iw_request_info *info;
 };
 
@@ -697,14 +704,14 @@
 int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd);
 int ar6000_ioctl_dispatcher(struct net_device *dev, struct ifreq *rq, int cmd);
 void ar6000_gpio_init(void);
-void ar6000_init_profile_info(AR_SOFTC_T *ar);
-void ar6000_install_static_wep_keys(AR_SOFTC_T *ar);
+void ar6000_init_profile_info(struct ar6_softc *ar);
+void ar6000_install_static_wep_keys(struct ar6_softc *ar);
 int ar6000_init(struct net_device *dev);
-int ar6000_dbglog_get_debug_logs(AR_SOFTC_T *ar);
-void ar6000_TxDataCleanup(AR_SOFTC_T *ar);
+int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
+void ar6000_TxDataCleanup(struct ar6_softc *ar);
 int ar6000_acl_data_tx(struct sk_buff *skb, struct net_device *dev);
 void ar6000_restart_endpoint(struct net_device *dev);
-void ar6000_stop_endpoint(struct net_device *dev, A_BOOL keepprofile, A_BOOL getdbglogs);
+void ar6000_stop_endpoint(struct net_device *dev, bool keepprofile, bool getdbglogs);
 
 #ifdef HTC_RAW_INTERFACE
 
@@ -712,12 +719,12 @@
 #define __user
 #endif
 
-int ar6000_htc_raw_open(AR_SOFTC_T *ar);
-int ar6000_htc_raw_close(AR_SOFTC_T *ar);
-ssize_t ar6000_htc_raw_read(AR_SOFTC_T *ar,
+int ar6000_htc_raw_open(struct ar6_softc *ar);
+int ar6000_htc_raw_close(struct ar6_softc *ar);
+ssize_t ar6000_htc_raw_read(struct ar6_softc *ar,
                             HTC_RAW_STREAM_ID StreamID,
                             char __user *buffer, size_t count);
-ssize_t ar6000_htc_raw_write(AR_SOFTC_T *ar,
+ssize_t ar6000_htc_raw_write(struct ar6_softc *ar,
                              HTC_RAW_STREAM_ID StreamID,
                              char __user *buffer, size_t count);
 
@@ -726,23 +733,22 @@
 /* AP mode */
 /*TODO: These routines should be moved to a file that is common across OS */
 sta_t *
-ieee80211_find_conn(AR_SOFTC_T *ar, A_UINT8 *node_addr);
+ieee80211_find_conn(struct ar6_softc *ar, u8 *node_addr);
 
 sta_t *
-ieee80211_find_conn_for_aid(AR_SOFTC_T *ar, A_UINT8 aid);
+ieee80211_find_conn_for_aid(struct ar6_softc *ar, u8 aid);
 
-A_UINT8
-remove_sta(AR_SOFTC_T *ar, A_UINT8 *mac, A_UINT16 reason);
+u8 remove_sta(struct ar6_softc *ar, u8 *mac, u16 reason);
 
 /* HCI support */
 
 #ifndef EXPORT_HCI_BRIDGE_INTERFACE
-A_STATUS ar6000_setup_hci(AR_SOFTC_T *ar);
-void     ar6000_cleanup_hci(AR_SOFTC_T *ar);
-void     ar6000_set_default_ar3kconfig(AR_SOFTC_T *ar, void *ar3kconfig);
+int ar6000_setup_hci(struct ar6_softc *ar);
+void     ar6000_cleanup_hci(struct ar6_softc *ar);
+void     ar6000_set_default_ar3kconfig(struct ar6_softc *ar, void *ar3kconfig);
 
 /* HCI bridge testing */
-A_STATUS hci_test_send(AR_SOFTC_T *ar, struct sk_buff *skb);
+int hci_test_send(struct ar6_softc *ar, struct sk_buff *skb);
 #endif
 
 ATH_DEBUG_DECLARE_EXTERN(htc);
@@ -752,8 +758,8 @@
 ATH_DEBUG_DECLARE_EXTERN(wlan);
 ATH_DEBUG_DECLARE_EXTERN(misc);
 
-extern A_UINT8 bcast_mac[];
-extern A_UINT8 null_mac[];
+extern u8 bcast_mac[];
+extern u8 null_mac[];
 
 #ifdef __cplusplus
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/ar6k_pal.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,12 +21,12 @@
 //==============================================================================
 #ifndef _AR6K_PAL_H_
 #define _AR6K_PAL_H_
-#define HCI_GET_OP_CODE(p)          (((A_UINT16)((p)[1])) << 8) | ((A_UINT16)((p)[0]))
+#define HCI_GET_OP_CODE(p)          (((u16)((p)[1])) << 8) | ((u16)((p)[0]))
 
 /* transmit packet reserve offset */
 #define TX_PACKET_RSV_OFFSET        32
 /* pal specific config structure */
-typedef A_BOOL (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb);
+typedef bool (*ar6k_pal_recv_pkt_t)(void *pHciPalInfo, void *skb);
 typedef struct ar6k_pal_config_s
 {
 	ar6k_pal_recv_pkt_t fpar6k_pal_recv_pkt;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/ar6xapi_linux.h	2011-05-19 00:06:34.000000000 -0400
@@ -29,37 +29,37 @@
 
 struct ar6_softc;
 
-void ar6000_ready_event(void *devt, A_UINT8 *datap, A_UINT8 phyCap,
-                        A_UINT32 sw_ver, A_UINT32 abi_ver);
-A_STATUS ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid);
-void ar6000_connect_event(struct ar6_softc *ar, A_UINT16 channel,
-                          A_UINT8 *bssid, A_UINT16 listenInterval,
-                          A_UINT16 beaconInterval, NETWORK_TYPE networkType,
-                          A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
-                          A_UINT8 assocRespLen,A_UINT8 *assocInfo);
-void ar6000_disconnect_event(struct ar6_softc *ar, A_UINT8 reason,
-                             A_UINT8 *bssid, A_UINT8 assocRespLen,
-                             A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus);
-void ar6000_tkip_micerr_event(struct ar6_softc *ar, A_UINT8 keyid,
-                              A_BOOL ismcast);
-void ar6000_bitrate_rx(void *devt, A_INT32 rateKbps);
-void ar6000_channelList_rx(void *devt, A_INT8 numChan, A_UINT16 *chanList);
-void ar6000_regDomain_event(struct ar6_softc *ar, A_UINT32 regCode);
-void ar6000_txPwr_rx(void *devt, A_UINT8 txPwr);
-void ar6000_keepalive_rx(void *devt, A_UINT8 configured);
+void ar6000_ready_event(void *devt, u8 *datap, u8 phyCap,
+                        u32 sw_ver, u32 abi_ver);
+int ar6000_control_tx(void *devt, void *osbuf, HTC_ENDPOINT_ID eid);
+void ar6000_connect_event(struct ar6_softc *ar, u16 channel,
+                          u8 *bssid, u16 listenInterval,
+                          u16 beaconInterval, NETWORK_TYPE networkType,
+                          u8 beaconIeLen, u8 assocReqLen,
+                          u8 assocRespLen,u8 *assocInfo);
+void ar6000_disconnect_event(struct ar6_softc *ar, u8 reason,
+                             u8 *bssid, u8 assocRespLen,
+                             u8 *assocInfo, u16 protocolReasonStatus);
+void ar6000_tkip_micerr_event(struct ar6_softc *ar, u8 keyid,
+                              bool ismcast);
+void ar6000_bitrate_rx(void *devt, s32 rateKbps);
+void ar6000_channelList_rx(void *devt, s8 numChan, u16 *chanList);
+void ar6000_regDomain_event(struct ar6_softc *ar, u32 regCode);
+void ar6000_txPwr_rx(void *devt, u8 txPwr);
+void ar6000_keepalive_rx(void *devt, u8 configured);
 void ar6000_neighborReport_event(struct ar6_softc *ar, int numAps,
                                  WMI_NEIGHBOR_INFO *info);
-void ar6000_set_numdataendpts(struct ar6_softc *ar, A_UINT32 num);
-void ar6000_scanComplete_event(struct ar6_softc *ar, A_STATUS status);
-void ar6000_targetStats_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len);
+void ar6000_set_numdataendpts(struct ar6_softc *ar, u32 num);
+void ar6000_scanComplete_event(struct ar6_softc *ar, int status);
+void ar6000_targetStats_event(struct ar6_softc *ar,  u8 *ptr, u32 len);
 void ar6000_rssiThreshold_event(struct ar6_softc *ar,
                                 WMI_RSSI_THRESHOLD_VAL newThreshold,
-                                A_INT16 rssi);
+                                s16 rssi);
 void ar6000_reportError_event(struct ar6_softc *, WMI_TARGET_ERROR_VAL errorVal);
-void ar6000_cac_event(struct ar6_softc *ar, A_UINT8 ac, A_UINT8 cac_indication,
-                                A_UINT8 statusCode, A_UINT8 *tspecSuggestion);
-void ar6000_channel_change_event(struct ar6_softc *ar, A_UINT16 oldChannel, A_UINT16 newChannel);
-void ar6000_hbChallengeResp_event(struct ar6_softc *, A_UINT32 cookie, A_UINT32 source);
+void ar6000_cac_event(struct ar6_softc *ar, u8 ac, u8 cac_indication,
+                                u8 statusCode, u8 *tspecSuggestion);
+void ar6000_channel_change_event(struct ar6_softc *ar, u16 oldChannel, u16 newChannel);
+void ar6000_hbChallengeResp_event(struct ar6_softc *, u32 cookie, u32 source);
 void
 ar6000_roam_tbl_event(struct ar6_softc *ar, WMI_TARGET_ROAM_TBL *pTbl);
 
@@ -67,96 +67,96 @@
 ar6000_roam_data_event(struct ar6_softc *ar, WMI_TARGET_ROAM_DATA *p);
 
 void
-ar6000_wow_list_event(struct ar6_softc *ar, A_UINT8 num_filters,
+ar6000_wow_list_event(struct ar6_softc *ar, u8 num_filters,
                       WMI_GET_WOW_LIST_REPLY *wow_reply);
 
-void ar6000_pmkid_list_event(void *devt, A_UINT8 numPMKID,
-                             WMI_PMKID *pmkidList, A_UINT8 *bssidList);
+void ar6000_pmkid_list_event(void *devt, u8 numPMKID,
+                             WMI_PMKID *pmkidList, u8 *bssidList);
 
-void ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values);
-void ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value);
+void ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values);
+void ar6000_gpio_data_rx(u32 reg_id, u32 value);
 void ar6000_gpio_ack_rx(void);
 
-A_INT32 rssi_compensation_calc_tcmd(A_UINT32 freq, A_INT32 rssi, A_UINT32 totalPkt);
-A_INT16 rssi_compensation_calc(struct ar6_softc *ar, A_INT16 rssi);
-A_INT16 rssi_compensation_reverse_calc(struct ar6_softc *ar, A_INT16 rssi, A_BOOL Above);
+s32 rssi_compensation_calc_tcmd(u32 freq, s32 rssi, u32 totalPkt);
+s16 rssi_compensation_calc(struct ar6_softc *ar, s16 rssi);
+s16 rssi_compensation_reverse_calc(struct ar6_softc *ar, s16 rssi, bool Above);
 
 void ar6000_dbglog_init_done(struct ar6_softc *ar);
 
 #ifdef SEND_EVENT_TO_APP
-void ar6000_send_event_to_app(struct ar6_softc *ar, A_UINT16 eventId, A_UINT8 *datap, int len);
-void ar6000_send_generic_event_to_app(struct ar6_softc *ar, A_UINT16 eventId, A_UINT8 *datap, int len);
+void ar6000_send_event_to_app(struct ar6_softc *ar, u16 eventId, u8 *datap, int len);
+void ar6000_send_generic_event_to_app(struct ar6_softc *ar, u16 eventId, u8 *datap, int len);
 #endif
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-void ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len);
+void ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len);
 #endif
 
 void ar6000_tx_retry_err_event(void *devt);
 
 void ar6000_snrThresholdEvent_rx(void *devt,
                                  WMI_SNR_THRESHOLD_VAL newThreshold,
-                                 A_UINT8 snr);
+                                 u8 snr);
 
-void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, A_UINT8 lqVal);
+void ar6000_lqThresholdEvent_rx(void *devt, WMI_LQ_THRESHOLD_VAL range, u8 lqVal);
 
 
-void ar6000_ratemask_rx(void *devt, A_UINT32 ratemask);
+void ar6000_ratemask_rx(void *devt, u32 ratemask);
 
-A_STATUS ar6000_get_driver_cfg(struct net_device *dev,
-                                A_UINT16 cfgParam,
+int ar6000_get_driver_cfg(struct net_device *dev,
+                                u16 cfgParam,
                                 void *result);
-void ar6000_bssInfo_event_rx(struct ar6_softc *ar, A_UINT8 *data, int len);
+void ar6000_bssInfo_event_rx(struct ar6_softc *ar, u8 *data, int len);
 
-void ar6000_dbglog_event(struct ar6_softc *ar, A_UINT32 dropped,
-                         A_INT8 *buffer, A_UINT32 length);
+void ar6000_dbglog_event(struct ar6_softc *ar, u32 dropped,
+                         s8 *buffer, u32 length);
 
 int ar6000_dbglog_get_debug_logs(struct ar6_softc *ar);
 
-void ar6000_peer_event(void *devt, A_UINT8 eventCode, A_UINT8 *bssid);
+void ar6000_peer_event(void *devt, u8 eventCode, u8 *bssid);
 
-void ar6000_indicate_tx_activity(void *devt, A_UINT8 trafficClass, A_BOOL Active);
-HTC_ENDPOINT_ID  ar6000_ac2_endpoint_id ( void * devt, A_UINT8 ac);
-A_UINT8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep );
+void ar6000_indicate_tx_activity(void *devt, u8 trafficClass, bool Active);
+HTC_ENDPOINT_ID  ar6000_ac2_endpoint_id ( void * devt, u8 ac);
+u8 ar6000_endpoint_id2_ac (void * devt, HTC_ENDPOINT_ID ep );
 
-void ar6000_btcoex_config_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len);
+void ar6000_btcoex_config_event(struct ar6_softc *ar,  u8 *ptr, u32 len);
 
-void ar6000_btcoex_stats_event(struct ar6_softc *ar,  A_UINT8 *ptr, A_UINT32 len) ;
+void ar6000_btcoex_stats_event(struct ar6_softc *ar,  u8 *ptr, u32 len) ;
 
 void ar6000_dset_open_req(void *devt,
-                          A_UINT32 id,
-                          A_UINT32 targ_handle,
-                          A_UINT32 targ_reply_fn,
-                          A_UINT32 targ_reply_arg);
-void ar6000_dset_close(void *devt, A_UINT32 access_cookie);
+                          u32 id,
+                          u32 targ_handle,
+                          u32 targ_reply_fn,
+                          u32 targ_reply_arg);
+void ar6000_dset_close(void *devt, u32 access_cookie);
 void ar6000_dset_data_req(void *devt,
-                          A_UINT32 access_cookie,
-                          A_UINT32 offset,
-                          A_UINT32 length,
-                          A_UINT32 targ_buf,
-                          A_UINT32 targ_reply_fn,
-                          A_UINT32 targ_reply_arg);
+                          u32 access_cookie,
+                          u32 offset,
+                          u32 length,
+                          u32 targ_buf,
+                          u32 targ_reply_fn,
+                          u32 targ_reply_arg);
 
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
 void prof_count_rx(unsigned int addr, unsigned int count);
 #endif
 
-A_UINT32 ar6000_getnodeAge (void);
+u32 ar6000_getnodeAge (void);
 
-A_UINT32 ar6000_getclkfreq (void);
+u32 ar6000_getclkfreq (void);
 
 int ar6000_ap_mode_profile_commit(struct ar6_softc *ar);
 
 struct ieee80211req_wpaie;
-A_STATUS
+int
 ar6000_ap_mode_get_wpa_ie(struct ar6_softc *ar, struct ieee80211req_wpaie *wpaie);
 
-A_STATUS is_iwioctl_allowed(A_UINT8 mode, A_UINT16 cmd);
+int is_iwioctl_allowed(u8 mode, u16 cmd);
 
-A_STATUS is_xioctl_allowed(A_UINT8 mode, int cmd);
+int is_xioctl_allowed(u8 mode, int cmd);
 
-void ar6000_pspoll_event(struct ar6_softc *ar,A_UINT8 aid);
+void ar6000_pspoll_event(struct ar6_softc *ar,u8 aid);
 
 void ar6000_dtimexpiry_event(struct ar6_softc *ar);
 
@@ -167,27 +167,28 @@
 
 #ifdef WAPI_ENABLE
 int ap_set_wapi_key(struct ar6_softc *ar, void *ik);
-void ap_wapi_rekey_event(struct ar6_softc *ar, A_UINT8 type, A_UINT8 *mac);
+void ap_wapi_rekey_event(struct ar6_softc *ar, u8 type, u8 *mac);
 #endif
 
-A_STATUS ar6000_connect_to_ap(struct ar6_softc *ar);
-A_STATUS ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, A_BOOL suspending);
-A_STATUS ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state);
-A_STATUS ar6000_set_bt_hw_state(struct ar6_softc *ar, A_UINT32 state);
+int ar6000_connect_to_ap(struct ar6_softc *ar);
+int ar6000_disconnect(struct ar6_softc *ar);
+int ar6000_update_wlan_pwr_state(struct ar6_softc *ar, AR6000_WLAN_STATE state, bool suspending);
+int ar6000_set_wlan_state(struct ar6_softc *ar, AR6000_WLAN_STATE state);
+int ar6000_set_bt_hw_state(struct ar6_softc *ar, u32 state);
 
 #ifdef CONFIG_PM
-A_STATUS ar6000_suspend_ev(void *context);
-A_STATUS ar6000_resume_ev(void *context);
-A_STATUS ar6000_power_change_ev(void *context, A_UINT32 config);
-void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, A_BOOL isEvent);
+int ar6000_suspend_ev(void *context);
+int ar6000_resume_ev(void *context);
+int ar6000_power_change_ev(void *context, u32 config);
+void ar6000_check_wow_status(struct ar6_softc *ar, struct sk_buff *skb, bool isEvent);
 #endif
 
 void ar6000_pm_init(void);
 void ar6000_pm_exit(void);
 
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-A_STATUS ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname);
-A_STATUS ar6000_remove_ap_interface(struct ar6_softc *ar);
+int ar6000_add_ap_interface(struct ar6_softc *ar, char *ifname);
+int ar6000_remove_ap_interface(struct ar6_softc *ar);
 #endif /* CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT */
 
 #ifdef __cplusplus
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/athdrv_linux.h	2011-05-19 00:06:34.000000000 -0400
@@ -531,7 +531,7 @@
  *   UINT32 cmd (AR6000_XIOCTL_WMI_STARTSCAN)
  *   UINT8  scanType
  *   UINT8  scanConnected
- *   A_BOOL forceFgScan
+ *   u32 forceFgScan
  * uses: WMI_START_SCAN_CMDID
  */
 
@@ -625,7 +625,7 @@
  * arguments:
  * UINT32 cmd (AR6000_XIOCTL_USER_SETKEYS)
  * UINT32 keyOpCtrl
- * uses AR6000_USER_SETKEYS_INFO
+ * uses struct ar6000_user_setkeys_info
  */
 #define AR6000_XIOCTL_USER_SETKEYS                      58
 #endif /* USER_KEYS */
@@ -643,7 +643,7 @@
  * arguments:
  *   UINT8 cmd (AR6000_XIOCTL_WMI_GET_KEEPALIVE)
  *   UINT8 keepaliveInterval
- *   A_BOOL configured
+ *   u32 configured
  * uses: WMI_GET_KEEPALIVE_CMDID
  */
 
@@ -660,7 +660,7 @@
  *         UINT32 number of bytes
  *         UINT32 activate? (0 or 1)
  *       }
- *       A_UINT32 resulting rompatch ID
+ *       u32 resulting rompatch ID
  *     }
  * uses: BMI_ROMPATCH_INSTALL
  */
@@ -710,7 +710,7 @@
 #define AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER    66
 /*
  * arguments:
- *      A_UINT32 filter_type;
+ *      u32 filter_type;
  */
 
 #define AR6000_XIOCTL_DBGLOG_CFG_MODULE             67
@@ -720,15 +720,15 @@
 #define AR6000_XIOCTL_WMI_SET_WSC_STATUS            70
 /*
  * arguments:
- *      A_UINT32 wsc_status;
+ *      u32 wsc_status;
  *            (WSC_REG_INACTIVE or WSC_REG_ACTIVE)
  */
 
 /*
  * arguments:
  *      struct {
- *          A_UINT8 streamType;
- *          A_UINT8 status;
+ *          u8 streamType;
+ *          u8 status;
  *      }
  * uses: WMI_SET_BT_STATUS_CMDID
  */
@@ -737,9 +737,9 @@
 /*
  * arguments:
  *      struct {
- *           A_UINT8 paramType;
+ *           u8 paramType;
  *           union {
- *               A_UINT8 noSCOPkts;
+ *               u8 noSCOPkts;
  *               BT_PARAMS_A2DP a2dpParams;
  *               BT_COEX_REGS regs;
  *           };
@@ -760,8 +760,8 @@
 /*
  * arguments:
  *   UINT32 cmd (AR6000_XIOCTL_TARGET_INFO)
- *   A_UINT32 TargetVersion (returned)
- *   A_UINT32 TargetType    (returned)
+ *   u32 TargetVersion (returned)
+ *   u32 TargetType    (returned)
  * (See also bmi_msg.h target_ver and target_type)
  */
 
@@ -786,7 +786,7 @@
  * This ioctl is used to set the connect control flags
  *
  * arguments:
- *      A_UINT32 connectCtrlFlags
+ *      u32 connectCtrlFlags
  */
 
 #define AR6000_XIOCTL_WMI_SET_AKMP_PARAMS              82
@@ -798,7 +798,7 @@
  *
  * arguments:
  *      struct {
- *          A_UINT32    akmpInfo;
+ *          u32 akmpInfo;
  *      }
  * uses: WMI_SET_AKMP_PARAMS_CMD
  */
@@ -814,7 +814,7 @@
  *
  * arguments:
  *      struct {
- *          A_UINT32    numPMKID;
+ *          u32 numPMKID;
  *          WMI_PMKID   pmkidList[WMI_MAX_PMKID_CACHE];
  *      }
  * uses: WMI_SET_PMKIDLIST_CMD
@@ -850,14 +850,14 @@
 #define AR6000_XIOCTL_PROF_CFG                      93
 /*
  * arguments:
- *   A_UINT32 period
- *   A_UINT32 nbins
+ *   u32 period
+ *   u32 nbins
  */
 
 #define AR6000_XIOCTL_PROF_ADDR_SET                 94
 /*
  * arguments:
- *   A_UINT32 Target address
+ *   u32 Target address
  */
 
 #define AR6000_XIOCTL_PROF_START                    95
@@ -997,91 +997,92 @@
 
 #define AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM              154
 
+#define AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES     161
 
 /* used by AR6000_IOCTL_WMI_GETREV */
 struct ar6000_version {
-    A_UINT32        host_ver;
-    A_UINT32        target_ver;
-    A_UINT32        wlan_ver;
-    A_UINT32        abi_ver;
+    u32 host_ver;
+    u32 target_ver;
+    u32 wlan_ver;
+    u32 abi_ver;
 };
 
 /* used by AR6000_IOCTL_WMI_GET_QOS_QUEUE */
 struct ar6000_queuereq {
-    A_UINT8         trafficClass;
-    A_UINT16        activeTsids;
+    u8 trafficClass;
+    u16 activeTsids;
 };
 
 /* used by AR6000_IOCTL_WMI_GET_TARGET_STATS */
 typedef struct targetStats_t {
-    A_UINT64    tx_packets;
-    A_UINT64    tx_bytes;
-    A_UINT64    tx_unicast_pkts;
-    A_UINT64    tx_unicast_bytes;
-    A_UINT64    tx_multicast_pkts;
-    A_UINT64    tx_multicast_bytes;
-    A_UINT64    tx_broadcast_pkts;
-    A_UINT64    tx_broadcast_bytes;
-    A_UINT64    tx_rts_success_cnt;
-    A_UINT64    tx_packet_per_ac[4];
+    u64 tx_packets;
+    u64 tx_bytes;
+    u64 tx_unicast_pkts;
+    u64 tx_unicast_bytes;
+    u64 tx_multicast_pkts;
+    u64 tx_multicast_bytes;
+    u64 tx_broadcast_pkts;
+    u64 tx_broadcast_bytes;
+    u64 tx_rts_success_cnt;
+    u64 tx_packet_per_ac[4];
 
-    A_UINT64    tx_errors;
-    A_UINT64    tx_failed_cnt;
-    A_UINT64    tx_retry_cnt;
-    A_UINT64    tx_mult_retry_cnt;
-    A_UINT64    tx_rts_fail_cnt;
+    u64 tx_errors;
+    u64 tx_failed_cnt;
+    u64 tx_retry_cnt;
+    u64 tx_mult_retry_cnt;
+    u64 tx_rts_fail_cnt;
 
-    A_UINT64    rx_packets;
-    A_UINT64    rx_bytes;
-    A_UINT64    rx_unicast_pkts;
-    A_UINT64    rx_unicast_bytes;
-    A_UINT64    rx_multicast_pkts;
-    A_UINT64    rx_multicast_bytes;
-    A_UINT64    rx_broadcast_pkts;
-    A_UINT64    rx_broadcast_bytes;
-    A_UINT64    rx_fragment_pkt;
+    u64 rx_packets;
+    u64 rx_bytes;
+    u64 rx_unicast_pkts;
+    u64 rx_unicast_bytes;
+    u64 rx_multicast_pkts;
+    u64 rx_multicast_bytes;
+    u64 rx_broadcast_pkts;
+    u64 rx_broadcast_bytes;
+    u64 rx_fragment_pkt;
 
-    A_UINT64    rx_errors;
-    A_UINT64    rx_crcerr;
-    A_UINT64    rx_key_cache_miss;
-    A_UINT64    rx_decrypt_err;
-    A_UINT64    rx_duplicate_frames;
+    u64 rx_errors;
+    u64 rx_crcerr;
+    u64 rx_key_cache_miss;
+    u64 rx_decrypt_err;
+    u64 rx_duplicate_frames;
 
-    A_UINT64    tkip_local_mic_failure;
-    A_UINT64    tkip_counter_measures_invoked;
-    A_UINT64    tkip_replays;
-    A_UINT64    tkip_format_errors;
-    A_UINT64    ccmp_format_errors;
-    A_UINT64    ccmp_replays;
+    u64 tkip_local_mic_failure;
+    u64 tkip_counter_measures_invoked;
+    u64 tkip_replays;
+    u64 tkip_format_errors;
+    u64 ccmp_format_errors;
+    u64 ccmp_replays;
 
-    A_UINT64    power_save_failure_cnt;
+    u64 power_save_failure_cnt;
 
-    A_UINT64    cs_bmiss_cnt;
-    A_UINT64    cs_lowRssi_cnt;
-    A_UINT64    cs_connect_cnt;
-    A_UINT64    cs_disconnect_cnt;
+    u64 cs_bmiss_cnt;
+    u64 cs_lowRssi_cnt;
+    u64 cs_connect_cnt;
+    u64 cs_disconnect_cnt;
 
-    A_INT32     tx_unicast_rate;
-    A_INT32     rx_unicast_rate;
+    s32 tx_unicast_rate;
+    s32 rx_unicast_rate;
 
-    A_UINT32    lq_val;
+    u32 lq_val;
 
-    A_UINT32    wow_num_pkts_dropped;
-    A_UINT16    wow_num_events_discarded;
+    u32 wow_num_pkts_dropped;
+    u16 wow_num_events_discarded;
 
-    A_INT16     noise_floor_calibation;
-    A_INT16     cs_rssi;
-    A_INT16     cs_aveBeacon_rssi;
-    A_UINT8     cs_aveBeacon_snr;
-    A_UINT8     cs_lastRoam_msec;
-    A_UINT8     cs_snr;
+    s16 noise_floor_calibation;
+    s16 cs_rssi;
+    s16 cs_aveBeacon_rssi;
+    u8 cs_aveBeacon_snr;
+    u8 cs_lastRoam_msec;
+    u8 cs_snr;
 
-    A_UINT8     wow_num_host_pkt_wakeups;
-    A_UINT8     wow_num_host_event_wakeups;
+    u8 wow_num_host_pkt_wakeups;
+    u8 wow_num_host_event_wakeups;
 
-    A_UINT32   arp_received;
-    A_UINT32   arp_matched;
-    A_UINT32   arp_replied;
+    u32 arp_received;
+    u32 arp_matched;
+    u32 arp_replied;
 }TARGET_STATS;
 
 typedef struct targetStats_cmd_t {
@@ -1097,70 +1098,69 @@
 #define AR6000_XIOCTL_USER_SETKEYS_RSC_CTRL    1
 #define AR6000_USER_SETKEYS_RSC_UNCHANGED     0x00000002
 
-typedef struct {
-    A_UINT32  keyOpCtrl;  /* Bit Map of Key Mgmt Ctrl Flags */
-} AR6000_USER_SETKEYS_INFO;
-
+struct ar6000_user_setkeys_info {
+    u32 keyOpCtrl;  /* Bit Map of Key Mgmt Ctrl Flags */
+}; /* XXX: unused !? */
 
 /* used by AR6000_XIOCTL_GPIO_OUTPUT_SET */
 struct ar6000_gpio_output_set_cmd_s {
-    A_UINT32 set_mask;
-    A_UINT32 clear_mask;
-    A_UINT32 enable_mask;
-    A_UINT32 disable_mask;
+    u32 set_mask;
+    u32 clear_mask;
+    u32 enable_mask;
+    u32 disable_mask;
 };
 
 /*
  * used by AR6000_XIOCTL_GPIO_REGISTER_GET and AR6000_XIOCTL_GPIO_REGISTER_SET
  */
 struct ar6000_gpio_register_cmd_s {
-    A_UINT32 gpioreg_id;
-    A_UINT32 value;
+    u32 gpioreg_id;
+    u32 value;
 };
 
 /* used by AR6000_XIOCTL_GPIO_INTR_ACK */
 struct ar6000_gpio_intr_ack_cmd_s {
-    A_UINT32 ack_mask;
+    u32 ack_mask;
 };
 
 /* used by AR6000_XIOCTL_GPIO_INTR_WAIT */
 struct ar6000_gpio_intr_wait_cmd_s {
-    A_UINT32 intr_mask;
-    A_UINT32 input_values;
+    u32 intr_mask;
+    u32 input_values;
 };
 
 /* used by the AR6000_XIOCTL_DBGLOG_CFG_MODULE */
 typedef struct ar6000_dbglog_module_config_s {
-    A_UINT32 valid;
-    A_UINT16 mmask;
-    A_UINT16 tsr;
-    A_BOOL   rep;
-    A_UINT16 size;
+    u32 valid;
+    u16 mmask;
+    u16 tsr;
+    u32   rep;
+    u16 size;
 } DBGLOG_MODULE_CONFIG;
 
 typedef struct user_rssi_thold_t {
-    A_INT16     tag;
-    A_INT16     rssi;
+    s16 tag;
+    s16 rssi;
 } USER_RSSI_THOLD;
 
 typedef struct user_rssi_params_t {
-    A_UINT8            weight;
-    A_UINT32           pollTime;
+    u8 weight;
+    u32 pollTime;
     USER_RSSI_THOLD    tholds[12];
 } USER_RSSI_PARAMS;
 
 typedef struct ar6000_get_btcoex_config_cmd_t{
-	A_UINT32 btProfileType;
-	A_UINT32 linkId;
+	u32 btProfileType;
+	u32 linkId;
  }AR6000_GET_BTCOEX_CONFIG_CMD;
 
 typedef struct ar6000_btcoex_config_t {
     AR6000_GET_BTCOEX_CONFIG_CMD  configCmd;
-    A_UINT32 * configEvent;
+    u32 *configEvent;
 } AR6000_BTCOEX_CONFIG;
 
 typedef struct ar6000_btcoex_stats_t {
-    A_UINT32 * statsEvent;
+    u32 *statsEvent;
  }AR6000_BTCOEX_STATS;
 /*
  * Host driver may have some config parameters. Typically, these
@@ -1183,14 +1183,14 @@
 
 
 struct ar6000_traffic_activity_change {
-    A_UINT32    StreamID;   /* stream ID to indicate activity change */
-    A_UINT32    Active;     /* active (1) or inactive (0) */
+    u32 StreamID;   /* stream ID to indicate activity change */
+    u32 Active;     /* active (1) or inactive (0) */
 };
 
 /* Used with AR6000_XIOCTL_PROF_COUNT_GET */
 struct prof_count_s {
-    A_UINT32    addr;       /* bin start address */
-    A_UINT32    count;      /* hit count */
+    u32 addr;       /* bin start address */
+    u32 count;      /* hit count */
 };
 
 
@@ -1198,8 +1198,8 @@
 /*         AR6000_XIOCTL_MODULE_DEBUG_GET_MASK */
 /*         AR6000_XIOCTL_DUMP_MODULE_DEBUG_INFO */
 struct drv_debug_module_s {
-    A_CHAR      modulename[128];   /* name of module */
-    A_UINT32    mask;              /* new mask to set .. or .. current mask */
+    char modulename[128];   /* name of module */
+    u32 mask;              /* new mask to set .. or .. current mask */
 };
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/athtypes_linux.h	2011-05-19 00:06:34.000000000 -0400
@@ -44,9 +44,7 @@
 typedef u_int32_t    A_UINT32;
 typedef u_int64_t    A_UINT64;
 
-typedef int             A_BOOL;
 typedef char            A_CHAR;
-typedef unsigned char   A_UCHAR;
 typedef unsigned long   A_ATH_TIMER;
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/cfg80211.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/cfg80211.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/cfg80211.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/cfg80211.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,21 +25,21 @@
 #define _AR6K_CFG80211_H_
 
 struct wireless_dev *ar6k_cfg80211_init(struct device *dev);
-void ar6k_cfg80211_deinit(AR_SOFTC_T *ar);
+void ar6k_cfg80211_deinit(struct ar6_softc *ar);
 
-void ar6k_cfg80211_scanComplete_event(AR_SOFTC_T *ar, A_STATUS status);
+void ar6k_cfg80211_scanComplete_event(struct ar6_softc *ar, int status);
 
-void ar6k_cfg80211_connect_event(AR_SOFTC_T *ar, A_UINT16 channel,
-                                A_UINT8 *bssid, A_UINT16 listenInterval,
-                                A_UINT16 beaconInterval,NETWORK_TYPE networkType,
-                                A_UINT8 beaconIeLen, A_UINT8 assocReqLen,
-                                A_UINT8 assocRespLen, A_UINT8 *assocInfo);
+void ar6k_cfg80211_connect_event(struct ar6_softc *ar, u16 channel,
+                                u8 *bssid, u16 listenInterval,
+                                u16 beaconInterval,NETWORK_TYPE networkType,
+                                u8 beaconIeLen, u8 assocReqLen,
+                                u8 assocRespLen, u8 *assocInfo);
 
-void ar6k_cfg80211_disconnect_event(AR_SOFTC_T *ar, A_UINT8 reason,
-                                    A_UINT8 *bssid, A_UINT8 assocRespLen,
-                                    A_UINT8 *assocInfo, A_UINT16 protocolReasonStatus);
+void ar6k_cfg80211_disconnect_event(struct ar6_softc *ar, u8 reason,
+                                    u8 *bssid, u8 assocRespLen,
+                                    u8 *assocInfo, u16 protocolReasonStatus);
 
-void ar6k_cfg80211_tkip_micerr_event(AR_SOFTC_T *ar, A_UINT8 keyid, A_BOOL ismcast);
+void ar6k_cfg80211_tkip_micerr_event(struct ar6_softc *ar, u8 keyid, bool ismcast);
 
 #endif /* _AR6K_CFG80211_H_ */
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/export_hci_transport.h	2011-05-19 00:06:34.000000000 -0400
@@ -25,18 +25,18 @@
 #include "hci_transport_api.h"
 #include "common_drv.h"
 
-extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, HCI_TRANSPORT_CONFIG_INFO *pInfo);
+extern HCI_TRANSPORT_HANDLE (*_HCI_TransportAttach)(void *HTCHandle, struct hci_transport_config_info *pInfo);
 extern void (*_HCI_TransportDetach)(HCI_TRANSPORT_HANDLE HciTrans);
-extern A_STATUS    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET_QUEUE *pQueue);
-extern A_STATUS    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, HTC_PACKET *pPacket, A_BOOL Synchronous);
+extern int    (*_HCI_TransportAddReceivePkts)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet_queue *pQueue);
+extern int    (*_HCI_TransportSendPkt)(HCI_TRANSPORT_HANDLE HciTrans, struct htc_packet *pPacket, bool Synchronous);
 extern void        (*_HCI_TransportStop)(HCI_TRANSPORT_HANDLE HciTrans);
-extern A_STATUS    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
-extern A_STATUS    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
-extern A_STATUS    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans, 
-                                          HTC_PACKET           *pPacket,
+extern int    (*_HCI_TransportStart)(HCI_TRANSPORT_HANDLE HciTrans);
+extern int    (*_HCI_TransportEnableDisableAsyncRecv)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
+extern int    (*_HCI_TransportRecvHCIEventSync)(HCI_TRANSPORT_HANDLE HciTrans,
+                                          struct htc_packet           *pPacket,
                                           int                  MaxPollMS);
-extern A_STATUS    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, A_UINT32 Baud);
-extern A_STATUS    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, A_BOOL Enable);
+extern int    (*_HCI_TransportSetBaudRate)(HCI_TRANSPORT_HANDLE HciTrans, u32 Baud);
+extern int    (*_HCI_TransportEnablePowerMgmt)(HCI_TRANSPORT_HANDLE HciTrans, bool Enable);
 
 
 #define HCI_TransportAttach(HTCHandle, pInfo)   \
@@ -61,11 +61,11 @@
             _HCI_TransportEnablePowerMgmt((HciTrans), (Enable))
 
 
-extern A_STATUS ar6000_register_hci_transport(HCI_TRANSPORT_CALLBACKS *hciTransCallbacks);
+extern int ar6000_register_hci_transport(struct hci_transport_callbacks *hciTransCallbacks);
 
-extern A_STATUS ar6000_get_hif_dev(HIF_DEVICE *device, void *config);
+extern int ar6000_get_hif_dev(struct hif_device *device, void *config);
 
-extern A_STATUS ar6000_set_uart_config(HIF_DEVICE *hifDevice, A_UINT32 scale, A_UINT32 step);
+extern int ar6000_set_uart_config(struct hif_device *hifDevice, u32 scale, u32 step);
 
 /* get core clock register settings
  * data: 0 - 40/44MHz
@@ -73,4 +73,4 @@
  *       where (5G band/2.4G band)
  * assume 2.4G band for now
  */
-extern A_STATUS ar6000_get_core_clock_config(HIF_DEVICE *hifDevice, A_UINT32 *data);
+extern int ar6000_get_core_clock_config(struct hif_device *hifDevice, u32 *data);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/osapi_linux.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/osapi_linux.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/osapi_linux.h	2012-03-24 01:13:19.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/osapi_linux.h	2012-03-24 03:33:49.000000000 -0400
@@ -76,9 +76,7 @@
 #define A_CPU2BE16(x)      htons(x)
 #define A_CPU2BE32(x)      htonl(x)
 
-#define A_MEMCPY(dst, src, len)         memcpy((A_UINT8 *)(dst), (src), (len))
 #define A_MEMZERO(addr, len)            memset(addr, 0, len)
-#define A_MEMCMP(addr1, addr2, len)     memcmp((addr1), (addr2), (len))
 #define A_MALLOC(size)                  kmalloc((size), GFP_KERNEL)
 #define A_MALLOC_NOWAIT(size)           kmalloc((size), GFP_ATOMIC)
 #define A_FREE(addr)                    kfree(addr)
@@ -116,12 +114,12 @@
 #define A_MUTEX_INIT(mutex)             spin_lock_init(mutex)
 #define A_MUTEX_LOCK(mutex)             spin_lock_bh(mutex)
 #define A_MUTEX_UNLOCK(mutex)           spin_unlock_bh(mutex)
-#define A_IS_MUTEX_VALID(mutex)         TRUE  /* okay to return true, since A_MUTEX_DELETE does nothing */
+#define A_IS_MUTEX_VALID(mutex)         true  /* okay to return true, since A_MUTEX_DELETE does nothing */
 #define A_MUTEX_DELETE(mutex)           /* spin locks are not kernel resources so nothing to free.. */
 
 /* Get current time in ms adding a constant offset (in ms) */
 #define A_GET_MS(offset)    \
-	(jiffies + ((offset) / 1000) * HZ)
+	(((jiffies / HZ) * 1000) + (offset))
 
 /*
  * Timer Functions
@@ -247,7 +245,7 @@
 #define A_NETBUF_QUEUE_SIZE(q)  \
     a_netbuf_queue_size(q)
 #define A_NETBUF_QUEUE_EMPTY(q) \
-    a_netbuf_queue_empty(q)
+    (a_netbuf_queue_empty(q) ? true : false)
 
 /*
  * Network buffer support
@@ -306,17 +304,17 @@
 void *a_netbuf_alloc_raw(int size);
 void a_netbuf_free(void *bufPtr);
 void *a_netbuf_to_data(void *bufPtr);
-A_UINT32 a_netbuf_to_len(void *bufPtr);
-A_STATUS a_netbuf_push(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len);
-A_STATUS a_netbuf_put(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len);
-A_STATUS a_netbuf_pull(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len);
-A_STATUS a_netbuf_trim(void *bufPtr, A_INT32 len);
-A_STATUS a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len);
-A_STATUS a_netbuf_setlen(void *bufPtr, A_INT32 len);
-A_INT32 a_netbuf_headroom(void *bufPtr);
+u32 a_netbuf_to_len(void *bufPtr);
+int a_netbuf_push(void *bufPtr, s32 len);
+int a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len);
+int a_netbuf_put(void *bufPtr, s32 len);
+int a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len);
+int a_netbuf_pull(void *bufPtr, s32 len);
+int a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len);
+int a_netbuf_trim(void *bufPtr, s32 len);
+int a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len);
+int a_netbuf_setlen(void *bufPtr, s32 len);
+s32 a_netbuf_headroom(void *bufPtr);
 void a_netbuf_enqueue(A_NETBUF_QUEUE_T *q, void *pkt);
 void a_netbuf_prequeue(A_NETBUF_QUEUE_T *q, void *pkt);
 void *a_netbuf_dequeue(A_NETBUF_QUEUE_T *q);
@@ -328,8 +326,8 @@
 /*
  * Kernel v.s User space functions
  */
-A_UINT32 a_copy_to_user(void *to, const void *from, A_UINT32 n);
-A_UINT32 a_copy_from_user(void *to, const void *from, A_UINT32 n);
+u32 a_copy_to_user(void *to, const void *from, u32 n);
+u32 a_copy_from_user(void *to, const void *from, u32 n);
 
 /* In linux, WLAN Rx and Tx run in different contexts, so no need to check
  * for any commands/data queued for WLAN */
@@ -364,9 +362,7 @@
 #define PREPACK
 #define POSTPACK                __ATTRIB_PACK
 
-#define A_MEMCPY(dst, src, len)         memcpy((dst), (src), (len))
 #define A_MEMZERO(addr, len)            memset((addr), 0, (len))
-#define A_MEMCMP(addr1, addr2, len)     memcmp((addr1), (addr2), (len))
 #define A_MALLOC(size)                  malloc(size)
 #define A_FREE(addr)                    free(addr)
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/wlan_config.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/wlan_config.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/wlan_config.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/wlan_config.h	2011-05-19 00:06:34.000000000 -0400
@@ -103,6 +103,13 @@
 #define WLAN_CONFIG_PM_WOW2                 0
 
 /*
+ * This configuration item enables/disables transmit bursting 
+ * 0 - Enable tx Bursting (default)
+ * 1 - Disable tx bursting 
+ */
+#define WLAN_CONFIG_DISABLE_TX_BURSTING     0
+
+/*
  * Platform specific function to power ON/OFF AR6000 
  * and enable/disable SDIO card detection
  */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/include/wmi_filter_linux.h	2011-05-19 00:06:34.000000000 -0400
@@ -41,7 +41,7 @@
  * (0xFF) - Allow this cmd always irrespective of mode
  */
 
-A_UINT8 sioctl_filter[] = {
+u8 sioctl_filter[] = {
 (AP_NETWORK),                                   /* SIOCSIWCOMMIT   0x8B00   */
 (0xFF),                                         /* SIOCGIWNAME     0x8B01   */
 (0),                                            /* SIOCSIWNWID     0x8B02   */
@@ -96,7 +96,7 @@
 
 
 
-A_UINT8 pioctl_filter[] = {
+u8 pioctl_filter[] = {
 (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK),   /* IEEE80211_IOCTL_SETPARAM             (SIOCIWFIRSTPRIV+0)     */
 (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK),   /* IEEE80211_IOCTL_SETKEY               (SIOCIWFIRSTPRIV+1)     */
 (INFRA_NETWORK | ADHOC_NETWORK | AP_NETWORK),   /* IEEE80211_IOCTL_DELKEY               (SIOCIWFIRSTPRIV+2)     */
@@ -132,7 +132,7 @@
 
 
 
-A_UINT8 xioctl_filter[] = {
+u8 xioctl_filter[] = {
 (0xFF),                                         /* Dummy                                           0    */
 (0xFF),                                         /* AR6000_XIOCTL_BMI_DONE                          1    */
 (0xFF),                                         /* AR6000_XIOCTL_BMI_READ_MEMORY                   2    */
@@ -288,6 +288,13 @@
 (0xFF),                                         /* AR6000_XIOCTL_ADD_AP_INTERFACE                  152  */
 (0xFF),                                         /* AR6000_XIOCTL_REMOVE_AP_INTERFACE               153  */
 (0xFF),                                         /* AR6000_XIOCTL_WMI_SET_TX_SGI_PARAM              154  */
+(INFRA_NETWORK | ADHOC_NETWORK),                /* AR6000_XIOCTL_WMI_SET_WPA_OFFLOAD_STATE         155  */
+(INFRA_NETWORK | ADHOC_NETWORK),                /* AR6000_XIOCTL_WMI_SET_PASSPHRASE                156  */
+(0xFF),
+(0xFF),
+(0xFF),
+(0xFF),
+(INFRA_NETWORK | ADHOC_NETWORK),                /* AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES     161  */
 };
 
 #endif /*_WMI_FILTER_LINUX_H_*/
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ioctl.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ioctl.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/ioctl.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/ioctl.c	2011-05-19 00:06:34.000000000 -0400
@@ -29,24 +29,23 @@
 #include "wlan_config.h"
 
 extern int enablerssicompensation;
-A_UINT32 tcmdRxFreq;
+u32 tcmdRxFreq;
 extern unsigned int wmitimeout;
 extern A_WAITQUEUE_HEAD arEvent;
 extern int tspecCompliance;
 extern int bmienable;
-extern int bypasswmi;
 extern int loghci;
 
 static int
 ar6000_ioctl_get_roam_tbl(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
-    if(wmi_get_roam_tbl_cmd(ar->arWmi) != A_OK) {
+    if(wmi_get_roam_tbl_cmd(ar->arWmi) != 0) {
         return -EIO;
     }
 
@@ -56,15 +55,15 @@
 static int
 ar6000_ioctl_get_roam_data(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
 
     /* currently assume only roam times are required */
-    if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != A_OK) {
+    if(wmi_get_roam_data_cmd(ar->arWmi, ROAM_DATA_TIME) != 0) {
         return -EIO;
     }
 
@@ -75,11 +74,11 @@
 static int
 ar6000_ioctl_set_roam_ctrl(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_ROAM_CTRL_CMD cmd;
-    A_UINT8 size = sizeof(cmd);
+    u8 size = sizeof(cmd);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -98,7 +97,7 @@
         return -EFAULT;
     }
 
-    if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != A_OK) {
+    if(wmi_set_roam_ctrl_cmd(ar->arWmi, &cmd, size) != 0) {
         return -EIO;
     }
 
@@ -108,11 +107,11 @@
 static int
 ar6000_ioctl_set_powersave_timers(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWERSAVE_TIMERS_POLICY_CMD cmd;
-    A_UINT8 size = sizeof(cmd);
+    u8 size = sizeof(cmd);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -124,7 +123,7 @@
         return -EFAULT;
     }
 
-    if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != A_OK) {
+    if(wmi_set_powersave_timers_cmd(ar->arWmi, &cmd, size) != 0) {
         return -EIO;
     }
 
@@ -134,14 +133,14 @@
 static int
 ar6000_ioctl_set_qos_supp(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_QOS_SUPP_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -154,7 +153,7 @@
     ret = wmi_set_qos_supp_cmd(ar->arWmi, cmd.status);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -169,14 +168,14 @@
 static int
 ar6000_ioctl_set_wmm(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_WMM_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -187,15 +186,15 @@
     }
 
     if (cmd.status == WMI_WMM_ENABLED) {
-        ar->arWmmEnabled = TRUE;
+        ar->arWmmEnabled = true;
     } else {
-        ar->arWmmEnabled = FALSE;
+        ar->arWmmEnabled = false;
     }
 
     ret = wmi_set_wmm_cmd(ar->arWmi, cmd.status);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -210,14 +209,14 @@
 static int
 ar6000_ioctl_set_txop(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_WMM_TXOP_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -230,7 +229,7 @@
     ret = wmi_set_wmm_txop(ar->arWmi, cmd.txopEnable);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -245,10 +244,10 @@
 static int
 ar6000_ioctl_get_rd(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_STATUS ret = 0;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    int ret = 0;
 
-    if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == FALSE) {
+    if ((dev->flags & IFF_UP) != IFF_UP || ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -262,14 +261,14 @@
 static int
 ar6000_ioctl_set_country(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_AP_SET_COUNTRY_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
     if ((dev->flags & IFF_UP) != IFF_UP) {
         return -EIO;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -282,10 +281,10 @@
     ar->ap_profile_flag = 1; /* There is a change in profile */
 
     ret = wmi_set_country(ar->arWmi, cmd.countryCode);
-    A_MEMCPY(ar->ap_country_code, cmd.countryCode, 3);
+    memcpy(ar->ap_country_code, cmd.countryCode, 3);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -302,11 +301,11 @@
 static int
 ar6000_ioctl_get_power_mode(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWER_MODE_CMD power_mode;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -322,11 +321,11 @@
 static int
 ar6000_ioctl_set_channelParams(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_CHANNEL_PARAMS_CMD cmd, *cmdp;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -344,7 +343,7 @@
         cmdp = A_MALLOC(130);
         if (copy_from_user(cmdp, rq->ifr_data,
                            sizeof (*cmdp) +
-                           ((cmd.numChannels - 1) * sizeof(A_UINT16))))
+                           ((cmd.numChannels - 1) * sizeof(u16))))
         {
             kfree(cmdp);
             return -EFAULT;
@@ -362,7 +361,7 @@
     if (!ret &&
         (wmi_set_channelParams_cmd(ar->arWmi, cmdp->scanParam, cmdp->phyMode,
                                    cmdp->numChannels, cmdp->channelList)
-         != A_OK))
+         != 0))
     {
         ret = -EIO;
     }
@@ -383,11 +382,11 @@
 ar6000_ioctl_set_snr_threshold(struct net_device *dev, struct ifreq *rq)
 {
 
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -395,7 +394,7 @@
         return -EFAULT;
     }
 
-    if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != A_OK ) {
+    if( wmi_set_snr_threshold_params(ar->arWmi, &cmd) != 0 ) {
         ret = -EIO;
     }
 
@@ -415,13 +414,13 @@
     thold2.rssi = tmpThold.rssi;        \
 } while (0)
 
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
     USER_RSSI_PARAMS rssiParams;
-    A_INT32 i, j;
+    s32 i, j;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -431,7 +430,7 @@
     cmd.weight = rssiParams.weight;
     cmd.pollTime = rssiParams.pollTime;
 
-    A_MEMCPY(ar->rssi_map, &rssiParams.tholds, sizeof(ar->rssi_map));
+    memcpy(ar->rssi_map, &rssiParams.tholds, sizeof(ar->rssi_map));
     /*
      *  only 6 elements, so use bubble sorting, in ascending order
      */
@@ -440,7 +439,7 @@
             if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
                 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
             } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
-                return EFAULT;
+                return -EFAULT;
             }
         }
     }
@@ -449,7 +448,7 @@
             if (ar->rssi_map[j+1].rssi < ar->rssi_map[j].rssi) {
                 SWAP_THOLD(ar->rssi_map[j+1], ar->rssi_map[j]);
             } else if (ar->rssi_map[j+1].rssi == ar->rssi_map[j].rssi) {
-                return EFAULT;
+                return -EFAULT;
             }
         }
     }
@@ -463,9 +462,9 @@
 
     if (enablerssicompensation) {
         for (i = 0; i < 6; i++)
-            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, TRUE);
+            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, true);
         for (i = 6; i < 12; i++)
-            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, FALSE);
+            ar->rssi_map[i].rssi = rssi_compensation_reverse_calc(ar, ar->rssi_map[i].rssi, false);
     }
 
     cmd.thresholdAbove1_Val = ar->rssi_map[0].rssi;
@@ -481,7 +480,7 @@
     cmd.thresholdBelow5_Val = ar->rssi_map[10].rssi;
     cmd.thresholdBelow6_Val = ar->rssi_map[11].rssi;
 
-    if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != A_OK ) {
+    if( wmi_set_rssi_threshold_params(ar->arWmi, &cmd) != 0 ) {
         ret = -EIO;
     }
 
@@ -492,11 +491,11 @@
 ar6000_ioctl_set_lq_threshold(struct net_device *dev, struct ifreq *rq)
 {
 
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_LQ_THRESHOLD_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -504,7 +503,7 @@
         return -EFAULT;
     }
 
-    if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != A_OK ) {
+    if( wmi_set_lq_threshold_params(ar->arWmi, &cmd) != 0 ) {
         ret = -EIO;
     }
 
@@ -515,11 +514,11 @@
 static int
 ar6000_ioctl_set_probedSsid(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_PROBED_SSID_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -528,7 +527,7 @@
     }
 
     if (wmi_probedSsid_cmd(ar->arWmi, cmd.entryIndex, cmd.flag, cmd.ssidLength,
-                                  cmd.ssid) != A_OK)
+                                  cmd.ssid) != 0)
     {
         ret = -EIO;
     }
@@ -539,11 +538,11 @@
 static int
 ar6000_ioctl_set_badAp(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_ADD_BAD_AP_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -556,15 +555,15 @@
         return -EIO;
     }
 
-    if (A_MEMCMP(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
+    if (memcmp(cmd.bssid, null_mac, AR6000_ETH_ADDR_LEN) == 0) {
         /*
          * This is a delete badAP.
          */
-        if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != A_OK) {
+        if (wmi_deleteBadAp_cmd(ar->arWmi, cmd.badApIndex) != 0) {
             ret = -EIO;
         }
     } else {
-        if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != A_OK) {
+        if (wmi_addBadAp_cmd(ar->arWmi, cmd.badApIndex, cmd.bssid) != 0) {
             ret = -EIO;
         }
     }
@@ -575,11 +574,11 @@
 static int
 ar6000_ioctl_create_qos(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_CREATE_PSTREAM_CMD cmd;
-    A_STATUS ret;
+    int ret;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -589,11 +588,11 @@
     }
 
     ret = wmi_verify_tspec_params(&cmd, tspecCompliance);
-    if (ret == A_OK)
+    if (ret == 0)
         ret = wmi_create_pstream_cmd(ar->arWmi, &cmd);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -608,11 +607,11 @@
 static int
 ar6000_ioctl_delete_qos(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_DELETE_PSTREAM_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -623,7 +622,7 @@
     ret = wmi_delete_pstream_cmd(ar->arWmi, cmd.trafficClass, cmd.tsid);
 
     switch (ret) {
-        case A_OK:
+        case 0:
             return 0;
         case A_EBUSY :
             return -EBUSY;
@@ -638,11 +637,11 @@
 static int
 ar6000_ioctl_get_qos_queue(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct ar6000_queuereq qreq;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -662,19 +661,19 @@
 }
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-static A_STATUS
+static int
 ar6000_ioctl_tcmd_get_rx_report(struct net_device *dev,
-                                 struct ifreq *rq, A_UINT8 *data, A_UINT32 len)
+                                 struct ifreq *rq, u8 *data, u32 len)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT32    buf[4+TCMD_MAX_RATES];
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u32 buf[4+TCMD_MAX_RATES];
     int ret = 0;
 
     if (ar->bIsDestroyProgress) {
         return -EBUSY;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -688,7 +687,7 @@
     }
 
     ar->tcmdRxReport = 0;
-    if (wmi_test_cmd(ar->arWmi, data, len) != A_OK) {
+    if (wmi_test_cmd(ar->arWmi, data, len) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
@@ -703,8 +702,8 @@
     buf[1] = ar->tcmdRxRssi;
     buf[2] = ar->tcmdRxcrcErrPkt;
     buf[3] = ar->tcmdRxsecErrPkt;
-    A_MEMCPY(((A_UCHAR *)buf)+(4*sizeof(A_UINT32)), ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
-    A_MEMCPY(((A_UCHAR *)buf)+(4*sizeof(A_UINT32))+(TCMD_MAX_RATES *sizeof(A_UINT16)), ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
+    memcpy(((u8 *)buf)+(4*sizeof(u32)), ar->tcmdRateCnt, sizeof(ar->tcmdRateCnt));
+    memcpy(((u8 *)buf)+(4*sizeof(u32))+(TCMD_MAX_RATES *sizeof(u16)), ar->tcmdRateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
 
     if (!ret && copy_to_user(rq->ifr_data, buf, sizeof(buf))) {
         ret = -EFAULT;
@@ -716,9 +715,9 @@
 }
 
 void
-ar6000_tcmd_rx_report_event(void *devt, A_UINT8 * results, int len)
+ar6000_tcmd_rx_report_event(void *devt, u8 *results, int len)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)devt;
+    struct ar6_softc *ar = (struct ar6_softc *)devt;
     TCMD_CONT_RX * rx_rep = (TCMD_CONT_RX *)results;
 
     if (enablerssicompensation) {
@@ -733,8 +732,8 @@
     ar->tcmdRxReport = 1;
     A_MEMZERO(ar->tcmdRateCnt,  sizeof(ar->tcmdRateCnt));
     A_MEMZERO(ar->tcmdRateCntShortGuard,  sizeof(ar->tcmdRateCntShortGuard));
-    A_MEMCPY(ar->tcmdRateCnt, rx_rep->u.report.rateCnt, sizeof(ar->tcmdRateCnt));
-    A_MEMCPY(ar->tcmdRateCntShortGuard, rx_rep->u.report.rateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
+    memcpy(ar->tcmdRateCnt, rx_rep->u.report.rateCnt, sizeof(ar->tcmdRateCnt));
+    memcpy(ar->tcmdRateCntShortGuard, rx_rep->u.report.rateCntShortGuard, sizeof(ar->tcmdRateCntShortGuard));
 
     wake_up(&arEvent);
 }
@@ -743,11 +742,11 @@
 static int
 ar6000_ioctl_set_error_report_bitmask(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_TARGET_ERROR_REPORT_BITMASK cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -763,11 +762,11 @@
 static int
 ar6000_clear_target_stats(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     TARGET_STATS *pStats = &ar->arTargetStats;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
        return -EIO;
     }
     AR6000_SPIN_LOCK(&ar->arLock, 0);
@@ -779,7 +778,7 @@
 static int
 ar6000_ioctl_get_target_stats(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     TARGET_STATS_CMD cmd;
     TARGET_STATS *pStats = &ar->arTargetStats;
     int ret = 0;
@@ -787,7 +786,7 @@
     if (ar->bIsDestroyProgress) {
         return -EBUSY;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
     if (copy_from_user(&cmd, rq->ifr_data, sizeof(cmd))) {
@@ -801,14 +800,14 @@
         return -EBUSY;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+    if(wmi_get_stats_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
         ret = -EINTR;
@@ -830,21 +829,21 @@
 static int
 ar6000_ioctl_get_ap_stats(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT32 action; /* Allocating only the desired space on the frame. Declaring is as a WMI_AP_MODE_STAT variable results in exceeding the compiler imposed limit on the maximum frame size */
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u32 action; /* Allocating only the desired space on the frame. Declaring is as a WMI_AP_MODE_STAT variable results in exceeding the compiler imposed limit on the maximum frame size */
     WMI_AP_MODE_STAT *pStats = &ar->arAPStats;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
     if (copy_from_user(&action, (char *)((unsigned int*)rq->ifr_data + 1),
-                                sizeof(A_UINT32)))
+                                sizeof(u32)))
     {
         return -EFAULT;
     }
     if (action == AP_CLEAR_STATS) {
-        A_UINT8 i;
+        u8 i;
         AR6000_SPIN_LOCK(&ar->arLock, 0);
         for(i = 0; i < AP_MAX_NUM_STA; i++) {
             pStats->sta[i].tx_bytes = 0;
@@ -864,14 +863,14 @@
         return -ERESTARTSYS;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    if(wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+    if(wmi_get_stats_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
         ret = -EINTR;
@@ -889,11 +888,11 @@
 static int
 ar6000_ioctl_set_access_params(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_ACCESS_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -902,7 +901,7 @@
     }
 
     if (wmi_set_access_params_cmd(ar->arWmi, cmd.ac, cmd.txop, cmd.eCWmin, cmd.eCWmax,
-                                  cmd.aifsn) == A_OK)
+                                  cmd.aifsn) == 0)
     {
         ret = 0;
     } else {
@@ -915,11 +914,11 @@
 static int
 ar6000_ioctl_set_disconnect_timeout(struct net_device *dev, struct ifreq *rq)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_DISC_TIMEOUT_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -927,7 +926,7 @@
         return -EFAULT;
     }
 
-    if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == A_OK)
+    if (wmi_disctimeout_cmd(ar->arWmi, cmd.disconnectTimeout) == 0)
     {
         ret = 0;
     } else {
@@ -938,13 +937,13 @@
 }
 
 static int
-ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_voice_pkt_size(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_VOICE_PKT_SIZE_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -952,7 +951,7 @@
         return -EFAULT;
     }
 
-    if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == A_OK)
+    if (wmi_set_voice_pkt_size_cmd(ar->arWmi, cmd.voicePktSize) == 0)
     {
         ret = 0;
     } else {
@@ -964,13 +963,13 @@
 }
 
 static int
-ar6000_xioctl_set_max_sp_len(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_max_sp_len(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_MAX_SP_LEN_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -978,7 +977,7 @@
         return -EFAULT;
     }
 
-    if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == A_OK)
+    if (wmi_set_max_sp_len_cmd(ar->arWmi, cmd.maxSPLen) == 0)
     {
         ret = 0;
     } else {
@@ -990,13 +989,13 @@
 
 
 static int
-ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_bt_status_cmd(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_BT_STATUS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1004,7 +1003,7 @@
         return -EFAULT;
     }
 
-    if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == A_OK)
+    if (wmi_set_bt_status_cmd(ar->arWmi, cmd.streamType, cmd.status) == 0)
     {
         ret = 0;
     } else {
@@ -1015,13 +1014,13 @@
 }
 
 static int
-ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char * userdata)
+ar6000_xioctl_set_bt_params_cmd(struct net_device *dev, char *userdata)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_SET_BT_PARAMS_CMD cmd;
     int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1029,7 +1028,7 @@
         return -EFAULT;
     }
 
-    if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_bt_params_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1040,20 +1039,20 @@
 }
 
 static int
-ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_fe_ant_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_FE_ANT_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 	if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_fe_ant_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1064,13 +1063,13 @@
 }
 
 static int
-ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_colocated_bt_dev_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1078,7 +1077,7 @@
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_colocated_bt_dev_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1089,13 +1088,13 @@
 }
 
 static int
-ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  char * userdata)
+ar6000_xioctl_set_btcoex_btinquiry_page_config_cmd(struct net_device * dev,  char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1103,7 +1102,7 @@
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_btinquiry_page_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_btinquiry_page_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1114,13 +1113,13 @@
 }
 
 static int
-ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_sco_config_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_SCO_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1128,7 +1127,7 @@
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_sco_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_sco_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1140,13 +1139,13 @@
 
 static int
 ar6000_xioctl_set_btcoex_a2dp_config_cmd(struct net_device * dev,
-														char * userdata)
+														char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_A2DP_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1154,7 +1153,7 @@
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_a2dp_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_a2dp_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1165,13 +1164,13 @@
 }
 
 static int
-ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_aclcoex_config_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1179,7 +1178,7 @@
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_aclcoex_config_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_aclcoex_config_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1190,13 +1189,13 @@
 }
 
 static int
-ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char * userdata)
+ar60000_xioctl_set_btcoex_debug_cmd(struct net_device * dev, char *userdata)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 	WMI_SET_BTCOEX_DEBUG_CMD cmd;
     int ret = 0;
 
-	if (ar->arWmiReady == FALSE) {
+	if (ar->arWmiReady == false) {
 		return -EIO;
 	}
 
@@ -1204,7 +1203,7 @@
 		return -EFAULT;
 	}
 
-    if (wmi_set_btcoex_debug_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_debug_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1215,13 +1214,13 @@
 }
 
 static int
-ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char * userdata)
+ar6000_xioctl_set_btcoex_bt_operating_status_cmd(struct net_device * dev, char *userdata)
 {
-     AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+     struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
      WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD cmd;
      int ret = 0;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
 	return -EIO;
     }
 
@@ -1229,7 +1228,7 @@
 	return -EFAULT;
     }
 
-    if (wmi_set_btcoex_bt_operating_status_cmd(ar->arWmi, &cmd) == A_OK)
+    if (wmi_set_btcoex_bt_operating_status_cmd(ar->arWmi, &cmd) == 0)
     {
         ret = 0;
     } else {
@@ -1239,11 +1238,11 @@
 }
 
 static int
-ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char * userdata,
+ar6000_xioctl_get_btcoex_config_cmd(struct net_device * dev, char *userdata,
 											struct ifreq *rq)
 {
 
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     AR6000_BTCOEX_CONFIG btcoexConfig;
     WMI_BTCOEX_CONFIG_EVENT *pbtcoexConfigEv = &ar->arBtcoexConfig;
 
@@ -1252,7 +1251,7 @@
     if (ar->bIsDestroyProgress) {
             return -EBUSY;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
             return -EIO;
     }
 	if (copy_from_user(&btcoexConfig.configCmd, userdata, sizeof(AR6000_BTCOEX_CONFIG))) {
@@ -1262,15 +1261,15 @@
         return -ERESTARTSYS;
     }
 
-    if (wmi_get_btcoex_config_cmd(ar->arWmi, (WMI_GET_BTCOEX_CONFIG_CMD *)&btcoexConfig.configCmd) != A_OK)
+    if (wmi_get_btcoex_config_cmd(ar->arWmi, (WMI_GET_BTCOEX_CONFIG_CMD *)&btcoexConfig.configCmd) != 0)
     {
     	up(&ar->arSem);
     	return -EIO;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
        ret = -EINTR;
@@ -1284,9 +1283,9 @@
 }
 
 static int
-ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char * userdata, struct ifreq *rq)
+ar6000_xioctl_get_btcoex_stats_cmd(struct net_device * dev, char *userdata, struct ifreq *rq)
 {
-	AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+	struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     AR6000_BTCOEX_STATS btcoexStats;
     WMI_BTCOEX_STATS_EVENT *pbtcoexStats = &ar->arBtcoexStats;
     int ret = 0;
@@ -1294,7 +1293,7 @@
     if (ar->bIsDestroyProgress) {
             return -EBUSY;
     }
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
             return -EIO;
     }
 
@@ -1306,15 +1305,15 @@
 		return -EFAULT;
 	}
 
-    if (wmi_get_btcoex_stats_cmd(ar->arWmi) != A_OK)
+    if (wmi_get_btcoex_stats_cmd(ar->arWmi) != 0)
     {
     	up(&ar->arSem);
     	return -EIO;
     }
 
-    ar->statsUpdatePending = TRUE;
+    ar->statsUpdatePending = true;
 
-    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == FALSE, wmitimeout * HZ);
+    wait_event_interruptible_timeout(arEvent, ar->statsUpdatePending == false, wmitimeout * HZ);
 
     if (signal_pending(current)) {
        ret = -EINTR;
@@ -1330,20 +1329,42 @@
 	return(ret);
 }
 
+static int
+ar6000_xioctl_set_excess_tx_retry_thres_cmd(struct net_device * dev, char * userdata)
+{
+    struct ar6_softc     *ar     = (struct ar6_softc *)ar6k_priv(dev);
+    WMI_SET_EXCESS_TX_RETRY_THRES_CMD cmd;
+    int ret = 0;
+
+    if (ar->arWmiReady == false) {
+        return -EIO;
+    }
+
+    if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
+        return -EFAULT;
+    }
+
+    if (wmi_set_excess_tx_retry_thres_cmd(ar->arWmi, &cmd) != 0)
+    {
+        ret = -EINVAL;
+    }
+    return(ret);
+}
+
 #ifdef CONFIG_HOST_GPIO_SUPPORT
 struct ar6000_gpio_intr_wait_cmd_s  gpio_intr_results;
 /* gpio_reg_results and gpio_data_available are protected by arSem */
 static struct ar6000_gpio_register_cmd_s gpio_reg_results;
-static A_BOOL gpio_data_available; /* Requested GPIO data available */
-static A_BOOL gpio_intr_available; /* GPIO interrupt info available */
-static A_BOOL gpio_ack_received;   /* GPIO ack was received */
+static bool gpio_data_available; /* Requested GPIO data available */
+static bool gpio_intr_available; /* GPIO interrupt info available */
+static bool gpio_ack_received;   /* GPIO ack was received */
 
 /* Host-side initialization for General Purpose I/O support */
 void ar6000_gpio_init(void)
 {
-    gpio_intr_available = FALSE;
-    gpio_data_available = FALSE;
-    gpio_ack_received   = FALSE;
+    gpio_intr_available = false;
+    gpio_data_available = false;
+    gpio_ack_received   = false;
 }
 
 /*
@@ -1352,11 +1373,11 @@
  * input_values shows a recent value of GPIO pins.
  */
 void
-ar6000_gpio_intr_rx(A_UINT32 intr_mask, A_UINT32 input_values)
+ar6000_gpio_intr_rx(u32 intr_mask, u32 input_values)
 {
     gpio_intr_results.intr_mask = intr_mask;
     gpio_intr_results.input_values = input_values;
-    *((volatile A_BOOL *)&gpio_intr_available) = TRUE;
+    *((volatile bool *)&gpio_intr_available) = true;
     wake_up(&arEvent);
 }
 
@@ -1366,11 +1387,11 @@
  * call.
  */
 void
-ar6000_gpio_data_rx(A_UINT32 reg_id, A_UINT32 value)
+ar6000_gpio_data_rx(u32 reg_id, u32 value)
 {
     gpio_reg_results.gpioreg_id = reg_id;
     gpio_reg_results.value = value;
-    *((volatile A_BOOL *)&gpio_data_available) = TRUE;
+    *((volatile bool *)&gpio_data_available) = true;
     wake_up(&arEvent);
 }
 
@@ -1382,75 +1403,75 @@
 void
 ar6000_gpio_ack_rx(void)
 {
-    gpio_ack_received = TRUE;
+    gpio_ack_received = true;
     wake_up(&arEvent);
 }
 
-A_STATUS
+int
 ar6000_gpio_output_set(struct net_device *dev,
-                       A_UINT32 set_mask,
-                       A_UINT32 clear_mask,
-                       A_UINT32 enable_mask,
-                       A_UINT32 disable_mask)
+                       u32 set_mask,
+                       u32 clear_mask,
+                       u32 enable_mask,
+                       u32 disable_mask)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    gpio_ack_received = FALSE;
+    gpio_ack_received = false;
     return wmi_gpio_output_set(ar->arWmi,
                 set_mask, clear_mask, enable_mask, disable_mask);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_input_get(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    *((volatile A_BOOL *)&gpio_data_available) = FALSE;
+    *((volatile bool *)&gpio_data_available) = false;
     return wmi_gpio_input_get(ar->arWmi);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_register_set(struct net_device *dev,
-                         A_UINT32 gpioreg_id,
-                         A_UINT32 value)
+                         u32 gpioreg_id,
+                         u32 value)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    gpio_ack_received = FALSE;
+    gpio_ack_received = false;
     return wmi_gpio_register_set(ar->arWmi, gpioreg_id, value);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_register_get(struct net_device *dev,
-                         A_UINT32 gpioreg_id)
+                         u32 gpioreg_id)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    *((volatile A_BOOL *)&gpio_data_available) = FALSE;
+    *((volatile bool *)&gpio_data_available) = false;
     return wmi_gpio_register_get(ar->arWmi, gpioreg_id);
 }
 
-static A_STATUS
+static int
 ar6000_gpio_intr_ack(struct net_device *dev,
-                     A_UINT32 ack_mask)
+                     u32 ack_mask)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    gpio_intr_available = FALSE;
+    gpio_intr_available = false;
     return wmi_gpio_intr_ack(ar->arWmi, ack_mask);
 }
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
 static struct prof_count_s prof_count_results;
-static A_BOOL prof_count_available; /* Requested GPIO data available */
+static bool prof_count_available; /* Requested GPIO data available */
 
-static A_STATUS
+static int
 prof_count_get(struct net_device *dev)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    *((volatile A_BOOL *)&prof_count_available) = FALSE;
+    *((volatile bool *)&prof_count_available) = false;
     return wmi_prof_count_get_cmd(ar->arWmi);
 }
 
@@ -1459,24 +1480,24 @@
  * for a previous prof_count_get call.
  */
 void
-prof_count_rx(A_UINT32 addr, A_UINT32 count)
+prof_count_rx(u32 addr, u32 count)
 {
     prof_count_results.addr = addr;
     prof_count_results.count = count;
-    *((volatile A_BOOL *)&prof_count_available) = TRUE;
+    *((volatile bool *)&prof_count_available) = true;
     wake_up(&arEvent);
 }
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 
 
-static A_STATUS
-ar6000_create_acl_data_osbuf(struct net_device *dev, A_UINT8 *userdata, void **p_osbuf)
+static int
+ar6000_create_acl_data_osbuf(struct net_device *dev, u8 *userdata, void **p_osbuf)
 {
     void *osbuf = NULL;
-    A_UINT8 tmp_space[8];
+    u8 tmp_space[8];
     HCI_ACL_DATA_PKT *acl;
-    A_UINT8 hdr_size, *datap=NULL;
-    A_STATUS ret = A_OK;
+    u8 hdr_size, *datap=NULL;
+    int ret = 0;
 
     /* ACL is in data path. There is a need to create pool
      * mechanism for allocating and freeing NETBUFs - ToDo later.
@@ -1498,18 +1519,18 @@
            break;
         }
         A_NETBUF_PUT(osbuf, hdr_size + acl->data_len);
-        datap = (A_UINT8 *)A_NETBUF_DATA(osbuf);
+        datap = (u8 *)A_NETBUF_DATA(osbuf);
 
         /* Real copy to osbuf */
         acl = (HCI_ACL_DATA_PKT *)(datap);
-        A_MEMCPY(acl, tmp_space, hdr_size);
+        memcpy(acl, tmp_space, hdr_size);
         if (a_copy_from_user(acl->data, userdata + hdr_size, acl->data_len)) {
             ret = A_EFAULT;
             break;
         }
-    } while(FALSE);
+    } while(false);
 
-    if (ret == A_OK) {
+    if (ret == 0) {
         *p_osbuf = osbuf;
     } else {
         A_NETBUF_FREE(osbuf);
@@ -1520,7 +1541,7 @@
 
 
 int
-ar6000_ioctl_ap_setparam(AR_SOFTC_T *ar, int param, int value)
+ar6000_ioctl_ap_setparam(struct ar6_softc *ar, int param, int value)
 {
     int ret=0;
 
@@ -1600,9 +1621,9 @@
 }
 
 int
-ar6000_ioctl_setparam(AR_SOFTC_T *ar, int param, int value)
+ar6000_ioctl_setparam(struct ar6_softc *ar, int param, int value)
 {
-    A_BOOL profChanged = FALSE;
+    bool profChanged = false;
     int ret=0;
 
     if(ar->arNextMode == AP_NETWORK) {
@@ -1623,15 +1644,15 @@
             switch (value) {
                 case WPA_MODE_WPA1:
                     ar->arAuthMode = WPA_AUTH;
-                    profChanged    = TRUE;
+                    profChanged    = true;
                     break;
                 case WPA_MODE_WPA2:
                     ar->arAuthMode = WPA2_AUTH;
-                    profChanged    = TRUE;
+                    profChanged    = true;
                     break;
                 case WPA_MODE_NONE:
                     ar->arAuthMode = NONE_AUTH;
-                    profChanged    = TRUE;
+                    profChanged    = true;
                     break;
             }
             break;
@@ -1640,10 +1661,10 @@
                 case IEEE80211_AUTH_WPA_PSK:
                     if (WPA_AUTH == ar->arAuthMode) {
                         ar->arAuthMode = WPA_PSK_AUTH;
-                        profChanged    = TRUE;
+                        profChanged    = true;
                     } else if (WPA2_AUTH == ar->arAuthMode) {
                         ar->arAuthMode = WPA2_PSK_AUTH;
-                        profChanged    = TRUE;
+                        profChanged    = true;
                     } else {
                         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("Error -  Setting PSK "\
                             "mode when WPA param was set to %d\n",
@@ -1666,19 +1687,19 @@
             switch (value) {
                 case IEEE80211_CIPHER_AES_CCM:
                     ar->arPairwiseCrypto = AES_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
                 case IEEE80211_CIPHER_TKIP:
                     ar->arPairwiseCrypto = TKIP_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
                 case IEEE80211_CIPHER_WEP:
                     ar->arPairwiseCrypto = WEP_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
                 case IEEE80211_CIPHER_NONE:
                     ar->arPairwiseCrypto = NONE_CRYPT;
-                    profChanged          = TRUE;
+                    profChanged          = true;
                     break;
             }
             break;
@@ -1693,19 +1714,19 @@
             switch (value) {
                 case IEEE80211_CIPHER_AES_CCM:
                     ar->arGroupCrypto = AES_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
                 case IEEE80211_CIPHER_TKIP:
                     ar->arGroupCrypto = TKIP_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
                 case IEEE80211_CIPHER_WEP:
                     ar->arGroupCrypto = WEP_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
                 case IEEE80211_CIPHER_NONE:
                     ar->arGroupCrypto = NONE_CRYPT;
-                    profChanged       = TRUE;
+                    profChanged       = true;
                     break;
             }
             break;
@@ -1717,7 +1738,7 @@
             }
             break;
         case IEEE80211_PARAM_COUNTERMEASURES:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 return -EIO;
             }
             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
@@ -1725,7 +1746,7 @@
         default:
             break;
     }
-    if ((ar->arNextMode != AP_NETWORK) && (profChanged == TRUE)) {
+    if ((ar->arNextMode != AP_NETWORK) && (profChanged == true)) {
         /*
          * profile has changed.  Erase ssid to signal change
          */
@@ -1736,20 +1757,20 @@
 }
 
 int
-ar6000_ioctl_setkey(AR_SOFTC_T *ar, struct ieee80211req_key *ik)
+ar6000_ioctl_setkey(struct ar6_softc *ar, struct ieee80211req_key *ik)
 {
     KEY_USAGE keyUsage;
-    A_STATUS status;
+    int status;
     CRYPTO_TYPE keyType = NONE_CRYPT;
 
 #ifdef USER_KEYS
-    ar->user_saved_keys.keyOk = FALSE;
+    ar->user_saved_keys.keyOk = false;
 #endif
     if ( (0 == memcmp(ik->ik_macaddr, null_mac, IEEE80211_ADDR_LEN)) ||
          (0 == memcmp(ik->ik_macaddr, bcast_mac, IEEE80211_ADDR_LEN)) ) {
         keyUsage = GROUP_USAGE;
         if(ar->arNextMode == AP_NETWORK) {
-            A_MEMCPY(&ar->ap_mode_bkey, ik,
+            memcpy(&ar->ap_mode_bkey, ik,
                      sizeof(struct ieee80211req_key));
 #ifdef WAPI_ENABLE
             if(ar->arPairwiseCrypto == WAPI_CRYPT) {
@@ -1758,13 +1779,13 @@
 #endif
         }
 #ifdef USER_KEYS
-        A_MEMCPY(&ar->user_saved_keys.bcast_ik, ik,
+        memcpy(&ar->user_saved_keys.bcast_ik, ik,
                  sizeof(struct ieee80211req_key));
 #endif
     } else {
         keyUsage = PAIRWISE_USAGE;
 #ifdef USER_KEYS
-        A_MEMCPY(&ar->user_saved_keys.ucast_ik, ik,
+        memcpy(&ar->user_saved_keys.ucast_ik, ik,
                  sizeof(struct ieee80211req_key));
 #endif
 #ifdef WAPI_ENABLE
@@ -1806,7 +1827,7 @@
 
             A_MEMZERO(ar->arWepKeyList[index].arKey,
                             sizeof(ar->arWepKeyList[index].arKey));
-            A_MEMCPY(ar->arWepKeyList[index].arKey, ik->ik_keydata, ik->ik_keylen);
+            memcpy(ar->arWepKeyList[index].arKey, ik->ik_keydata, ik->ik_keylen);
             ar->arWepKeyList[index].arKeyLen = ik->ik_keylen;
 
             if(ik->ik_flags & IEEE80211_KEY_DEFAULT){
@@ -1823,11 +1844,11 @@
         }
 
         status = wmi_addKey_cmd(ar->arWmi, ik->ik_keyix, keyType, keyUsage,
-                                ik->ik_keylen, (A_UINT8 *)&ik->ik_keyrsc,
+                                ik->ik_keylen, (u8 *)&ik->ik_keyrsc,
                                 ik->ik_keydata, KEY_OP_INIT_VAL, ik->ik_macaddr,
                                 SYNC_BOTH_WMIFLAG);
 
-        if (status != A_OK) {
+        if (status) {
             return -EIO;
         }
     } else {
@@ -1835,7 +1856,7 @@
     }
 
 #ifdef USER_KEYS
-    ar->user_saved_keys.keyOk = TRUE;
+    ar->user_saved_keys.keyOk = true;
 #endif
 
     return 0;
@@ -1843,14 +1864,14 @@
 
 int ar6000_ioctl(struct net_device *dev, struct ifreq *rq, int cmd)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    HIF_DEVICE *hifDevice = ar->arHifDevice;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    struct hif_device *hifDevice = ar->arHifDevice;
     int ret = 0, param;
     unsigned int address = 0;
     unsigned int length = 0;
     unsigned char *buffer;
     char *userdata;
-    A_UINT32 connectCtrlFlags;
+    u32 connectCtrlFlags;
 
 
     WMI_SET_AKMP_PARAMS_CMD  akmpParams;
@@ -1879,13 +1900,13 @@
 	    goto ioctl_done;
 	}
         userdata = (char *)(((unsigned int *)rq->ifr_data)+1);
-        if(is_xioctl_allowed(ar->arNextMode, cmd) != A_OK) {
+        if(is_xioctl_allowed(ar->arNextMode, cmd) != 0) {
             A_PRINTF("xioctl: cmd=%d not allowed in this mode\n",cmd);
             ret = -EOPNOTSUPP;
             goto ioctl_done;
     }
     } else {
-        A_STATUS ret = is_iwioctl_allowed(ar->arNextMode, cmd);
+        int ret = is_iwioctl_allowed(ar->arNextMode, cmd);
         if(ret == A_ENOTSUP) {
             A_PRINTF("iwioctl: cmd=0x%x not allowed in this mode\n", cmd);
             ret = -EOPNOTSUPP;
@@ -1920,7 +1941,7 @@
         {
             int param, value;
             int *ptr = (int *)rq->ifr_ifru.ifru_newname;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else {
                 param = *ptr++;
@@ -1932,7 +1953,7 @@
         case IEEE80211_IOCTL_SETKEY:
         {
             struct ieee80211req_key keydata;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&keydata, userdata,
                             sizeof(struct ieee80211req_key))) {
@@ -1951,7 +1972,7 @@
         case IEEE80211_IOCTL_SETMLME:
         {
             struct ieee80211req_mlme mlme;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&mlme, userdata,
                             sizeof(struct ieee80211req_mlme))) {
@@ -1989,12 +2010,12 @@
         case IEEE80211_IOCTL_ADDPMKID:
         {
             struct ieee80211req_addpmkid  req;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&req, userdata, sizeof(struct ieee80211req_addpmkid))) {
                 ret = -EFAULT;
             } else {
-                A_STATUS status;
+                int status;
 
                 AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_CONNECT,("Add pmkid for %2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x en=%d\n",
                     req.pi_bssid[0], req.pi_bssid[1], req.pi_bssid[2],
@@ -2004,7 +2025,7 @@
                 status = wmi_setPmkid_cmd(ar->arWmi, req.pi_bssid, req.pi_pmkid,
                               req.pi_enable);
 
-                if (status != A_OK) {
+                if (status) {
                     ret = -EIO;
                     goto ioctl_done;
                 }
@@ -2028,7 +2049,7 @@
                     ret = -EFAULT;
                     goto ioctl_done;
                 } else {
-                    wmi_test_cmd(ar->arWmi,(A_UINT8 *)&txCmd, sizeof(TCMD_CONT_TX));
+                    wmi_test_cmd(ar->arWmi,(u8 *)&txCmd, sizeof(TCMD_CONT_TX));
                 }
             }
             break;
@@ -2054,13 +2075,13 @@
                     case TCMD_CONT_RX_FILTER:
                     case TCMD_CONT_RX_SETMAC:
                     case TCMD_CONT_RX_SET_ANT_SWITCH_TABLE:
-                         wmi_test_cmd(ar->arWmi,(A_UINT8 *)&rxCmd,
+                         wmi_test_cmd(ar->arWmi,(u8 *)&rxCmd,
                                                 sizeof(TCMD_CONT_RX));
                          tcmdRxFreq = rxCmd.u.para.freq;
                          break;
                     case TCMD_CONT_RX_REPORT:
                          ar6000_ioctl_tcmd_get_rx_report(dev, rq,
-                         (A_UINT8 *)&rxCmd, sizeof(TCMD_CONT_RX));
+                         (u8 *)&rxCmd, sizeof(TCMD_CONT_RX));
                          break;
                     default:
                          A_PRINTF("Unknown Cont Rx mode: %d\n",rxCmd.act);
@@ -2078,7 +2099,7 @@
                     goto ioctl_done;
                 }
                 ar->tcmdPm = pmCmd.mode;
-                wmi_test_cmd(ar->arWmi, (A_UINT8*)&pmCmd, sizeof(TCMD_PM));
+                wmi_test_cmd(ar->arWmi, (u8 *)&pmCmd, sizeof(TCMD_PM));
             }
             break;
 #endif /* CONFIG_HOST_TCMD_SUPPORT */
@@ -2153,7 +2174,7 @@
 	    }
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Execute (address: 0x%x, param: %d)\n",
                              address, param));
-            ret = BMIExecute(hifDevice, address, (A_UINT32*)&param);
+            ret = BMIExecute(hifDevice, address, (u32 *)&param);
 	    /* return value */
 	    if (put_user(param, (unsigned int *)rq->ifr_data)) {
 		ret = -EFAULT;
@@ -2175,7 +2196,7 @@
 		ret = -EFAULT;
 		break;
 	    }
-            ret = BMIReadSOCRegister(hifDevice, address, (A_UINT32*)&param);
+            ret = BMIReadSOCRegister(hifDevice, address, (u32 *)&param);
 	    /* return value */
 	    if (put_user(param, (unsigned int *)rq->ifr_data)) {
 		ret = -EFAULT;
@@ -2194,7 +2215,7 @@
 
 #ifdef HTC_RAW_INTERFACE
         case AR6000_XIOCTL_HTC_RAW_OPEN:
-            ret = A_OK;
+            ret = 0;
             if (!arRawIfEnabled(ar)) {
                 /* make sure block size is set in case the target was reset since last
                   * BMI phase (i.e. flashup downloads) */
@@ -2203,12 +2224,12 @@
                                             0,  /* use default yield */
                                             0   /* use default number of HTC ctrl buffers */
                                             );
-                if (A_FAILED(ret)) {
+                if (ret) {
                     break;
                 }
                 /* Terminate the BMI phase */
                 ret = BMIDone(hifDevice);
-                if (ret == A_OK) {
+                if (ret == 0) {
                     ret = ar6000_htc_raw_open(ar);
                 }
             }
@@ -2217,7 +2238,7 @@
         case AR6000_XIOCTL_HTC_RAW_CLOSE:
             if (arRawIfEnabled(ar)) {
                 ret = ar6000_htc_raw_close(ar);
-                arRawIfEnabled(ar) = FALSE;
+                arRawIfEnabled(ar) = false;
             } else {
                 ret = A_ERROR;
             }
@@ -2302,15 +2323,15 @@
         /* Configure Target-side profiling */
         case AR6000_XIOCTL_PROF_CFG:
         {
-            A_UINT32 period;
-            A_UINT32 nbins;
+            u32 period;
+            u32 nbins;
 	    if (get_user(period, (unsigned int *)userdata) ||
 		get_user(nbins, (unsigned int *)userdata + 1)) {
 		ret = -EFAULT;
 		break;
 	    }
 
-            if (wmi_prof_cfg_cmd(ar->arWmi, period, nbins) != A_OK) {
+            if (wmi_prof_cfg_cmd(ar->arWmi, period, nbins) != 0) {
                 ret = -EIO;
             }
 
@@ -2320,13 +2341,13 @@
         /* Start a profiling bucket/bin at the specified address */
         case AR6000_XIOCTL_PROF_ADDR_SET:
         {
-            A_UINT32 addr;
+            u32 addr;
 	    if (get_user(addr, (unsigned int *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
 
-            if (wmi_prof_addr_set_cmd(ar->arWmi, addr) != A_OK) {
+            if (wmi_prof_addr_set_cmd(ar->arWmi, addr) != 0) {
                 ret = -EIO;
             }
 
@@ -2348,7 +2369,7 @@
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2362,9 +2383,9 @@
                 goto ioctl_done;
             }
 
-            prof_count_available = FALSE;
+            prof_count_available = false;
             ret = prof_count_get(dev);
-            if (ret != A_OK) {
+            if (ret != 0) {
                 up(&ar->arSem);
                 ret = -EIO;
                 goto ioctl_done;
@@ -2399,7 +2420,7 @@
         {
             WMI_POWER_MODE_CMD pwrModeCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&pwrModeCmd, userdata,
                                    sizeof(pwrModeCmd)))
@@ -2407,7 +2428,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_powermode_cmd(ar->arWmi, pwrModeCmd.powerMode)
-                       != A_OK)
+                       != 0)
                 {
                     ret = -EIO;
                 }
@@ -2418,7 +2439,7 @@
         {
             WMI_IBSS_PM_CAPS_CMD ibssPmCaps;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&ibssPmCaps, userdata,
                                    sizeof(ibssPmCaps)))
@@ -2426,7 +2447,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_ibsspmcaps_cmd(ar->arWmi, ibssPmCaps.power_saving, ibssPmCaps.ttl,
-                    ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != A_OK)
+                    ibssPmCaps.atim_windows, ibssPmCaps.timeout_value) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2440,7 +2461,7 @@
         {
             WMI_AP_PS_CMD apPsCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&apPsCmd, userdata,
                                    sizeof(apPsCmd)))
@@ -2448,7 +2469,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_apps_cmd(ar->arWmi, apPsCmd.psType, apPsCmd.idle_time,
-                    apPsCmd.ps_period, apPsCmd.sleep_period) != A_OK)
+                    apPsCmd.ps_period, apPsCmd.sleep_period) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2459,7 +2480,7 @@
         {
             WMI_POWER_PARAMS_CMD pmParams;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&pmParams, userdata,
                                       sizeof(pmParams)))
@@ -2476,7 +2497,7 @@
 #else
                                      SEND_POWER_SAVE_FAIL_EVENT_ALWAYS
 #endif
-                                     ) != A_OK)
+                                     ) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2485,7 +2506,7 @@
         }
         case AR6000_IOCTL_WMI_SETSCAN:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&ar->scParams, userdata,
                                       sizeof(ar->scParams)))
@@ -2493,9 +2514,9 @@
                 ret = -EFAULT;
             } else {
                 if (CAN_SCAN_IN_CONNECT(ar->scParams.scanCtrlFlags)) {
-                    ar->arSkipScan = FALSE;
+                    ar->arSkipScan = false;
                 } else {
-                    ar->arSkipScan = TRUE;
+                    ar->arSkipScan = true;
                 }
 
                 if (wmi_scanparams_cmd(ar->arWmi, ar->scParams.fg_start_period,
@@ -2507,7 +2528,7 @@
                                        ar->scParams.shortScanRatio,
                                        ar->scParams.scanCtrlFlags,
                                        ar->scParams.max_dfsch_act_time,
-                                       ar->scParams.maxact_scan_per_ssid) != A_OK)
+                                       ar->scParams.maxact_scan_per_ssid) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2518,14 +2539,14 @@
         {
             WMI_LISTEN_INT_CMD listenCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&listenCmd, userdata,
                                       sizeof(listenCmd)))
             {
                 ret = -EFAULT;
             } else {
-                    if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != A_OK) {
+                    if (wmi_listeninterval_cmd(ar->arWmi, listenCmd.listenInterval, listenCmd.numBeacons) != 0) {
                         ret = -EIO;
                     } else {
                         AR6000_SPIN_LOCK(&ar->arLock, 0);
@@ -2541,14 +2562,14 @@
         {
             WMI_BMISS_TIME_CMD bmissCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&bmissCmd, userdata,
                                       sizeof(bmissCmd)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != A_OK) {
+                if (wmi_bmisstime_cmd(ar->arWmi, bmissCmd.bmissTime, bmissCmd.numBeacons) != 0) {
                     ret = -EIO;
                 }
             }
@@ -2558,7 +2579,7 @@
         {
             WMI_BSS_FILTER_CMD filt;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&filt, userdata,
                                    sizeof(filt)))
@@ -2566,10 +2587,10 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_bssfilter_cmd(ar->arWmi, filt.bssFilter, filt.ieMask)
-                        != A_OK) {
+                        != 0) {
                     ret = -EIO;
                 } else {
-                    ar->arUserBssFilter = param;
+                    ar->arUserBssFilter = filt.bssFilter;
                 }
             }
             break;
@@ -2587,7 +2608,7 @@
         }
         case AR6000_XIOCTL_WMI_CLR_RSSISNR:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             }
             ret = wmi_clr_rssi_snr(ar->arWmi);
@@ -2602,7 +2623,7 @@
         {
             WMI_SET_LPREAMBLE_CMD setLpreambleCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setLpreambleCmd, userdata,
                                    sizeof(setLpreambleCmd)))
@@ -2615,7 +2636,7 @@
 #else
                            WMI_IGNORE_BARKER_IN_ERP
 #endif
-                ) != A_OK)
+                ) != 0)
                 {
                     ret = -EIO;
                 }
@@ -2626,7 +2647,7 @@
         case AR6000_XIOCTL_WMI_SET_RTS:
         {
             WMI_SET_RTS_CMD rtsCmd;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&rtsCmd, userdata,
                                    sizeof(rtsCmd)))
@@ -2635,7 +2656,7 @@
             } else {
                 ar->arRTS = rtsCmd.threshold;
                 if (wmi_set_rts_cmd(ar->arWmi, rtsCmd.threshold)
-                       != A_OK)
+                       != 0)
                 {
                     ret = -EIO;
                 }
@@ -2706,9 +2727,9 @@
         case AR6000_IOCTL_WMI_SET_ASSOC_INFO:
         {
             WMI_SET_ASSOC_INFO_CMD cmd;
-            A_UINT8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
+            u8 assocInfo[WMI_MAX_ASSOC_INFO_LEN];
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
 		break;
 	    }
@@ -2729,7 +2750,7 @@
 		break;
 	    }
 	    if (wmi_associnfo_cmd(ar->arWmi, cmd.ieType,
-				  cmd.bufferSize, assocInfo) != A_OK) {
+				  cmd.bufferSize, assocInfo) != 0) {
 		ret = -EIO;
 		break;
 	    }
@@ -2763,12 +2784,12 @@
             /* If we made it to here, then the Target exists and is ready. */
 
             if (cmd == AR6000_XIOCTL_TARGET_INFO) {
-                if (copy_to_user((A_UINT32 *)rq->ifr_data, &ar->arVersion.target_ver,
+                if (copy_to_user((u32 *)rq->ifr_data, &ar->arVersion.target_ver,
                                  sizeof(ar->arVersion.target_ver)))
                 {
                     ret = -EFAULT;
                 }
-                if (copy_to_user(((A_UINT32 *)rq->ifr_data)+1, &ar->arTargetType,
+                if (copy_to_user(((u32 *)rq->ifr_data)+1, &ar->arTargetType,
                                  sizeof(ar->arTargetType)))
                 {
                     ret = -EFAULT;
@@ -2804,7 +2825,7 @@
         }
         case AR6000_XIOCTL_WMI_GET_HB_CHALLENGE_RESP:
         {
-            A_UINT32 cookie;
+            u32 cookie;
 
             if (copy_from_user(&cookie, userdata, sizeof(cookie))) {
                 ret = -EFAULT;
@@ -2812,7 +2833,7 @@
             }
 
             /* Send the challenge on the control channel */
-            if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != A_OK) {
+            if (wmi_get_challenge_resp_cmd(ar->arWmi, cookie, APP_HB_CHALLENGE) != 0) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2845,7 +2866,7 @@
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2869,8 +2890,8 @@
                                              gpio_output_set_cmd.clear_mask,
                                              gpio_output_set_cmd.enable_mask,
                                              gpio_output_set_cmd.disable_mask);
-                if (ret != A_OK) {
-                    ret = EIO;
+                if (ret != 0) {
+                    ret = -EIO;
                 }
             }
             up(&ar->arSem);
@@ -2882,7 +2903,7 @@
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2897,7 +2918,7 @@
             }
 
             ret = ar6000_gpio_input_get(dev);
-            if (ret != A_OK) {
+            if (ret != 0) {
                 up(&ar->arSem);
                 ret = -EIO;
                 goto ioctl_done;
@@ -2927,7 +2948,7 @@
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2949,8 +2970,8 @@
                 ret = ar6000_gpio_register_set(dev,
                                                gpio_register_cmd.gpioreg_id,
                                                gpio_register_cmd.value);
-                if (ret != A_OK) {
-                    ret = EIO;
+                if (ret != 0) {
+                    ret = -EIO;
                 }
 
                 /* Wait for acknowledgement from Target */
@@ -2970,7 +2991,7 @@
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -2990,7 +3011,7 @@
                 ret = -EFAULT;
             } else {
                 ret = ar6000_gpio_register_get(dev, gpio_register_cmd.gpioreg_id);
-                if (ret != A_OK) {
+                if (ret != 0) {
                     up(&ar->arSem);
                     ret = -EIO;
                     goto ioctl_done;
@@ -3020,7 +3041,7 @@
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -3040,8 +3061,8 @@
                 ret = -EFAULT;
             } else {
                 ret = ar6000_gpio_intr_ack(dev, gpio_intr_ack_cmd.ack_mask);
-                if (ret != A_OK) {
-                    ret = EIO;
+                if (ret != 0) {
+                    ret = -EIO;
                 }
             }
             up(&ar->arSem);
@@ -3077,7 +3098,7 @@
             /* Send the challenge on the control channel */
             if (wmi_config_debug_module_cmd(ar->arWmi, config.mmask,
                                             config.tsr, config.rep,
-                                            config.size, config.valid) != A_OK)
+                                            config.size, config.valid) != 0)
             {
                 ret = -EIO;
                 goto ioctl_done;
@@ -3088,7 +3109,7 @@
         case AR6000_XIOCTL_DBGLOG_GET_DEBUG_LOGS:
         {
             /* Send the challenge on the control channel */
-            if (ar6000_dbglog_get_debug_logs(ar) != A_OK)
+            if (ar6000_dbglog_get_debug_logs(ar) != 0)
             {
                 ret = -EIO;
                 goto ioctl_done;
@@ -3100,19 +3121,19 @@
         {
             WMI_SET_ADHOC_BSSID_CMD adhocBssid;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&adhocBssid, userdata,
                                       sizeof(adhocBssid)))
             {
                 ret = -EFAULT;
-            } else if (A_MEMCMP(adhocBssid.bssid, bcast_mac,
+            } else if (memcmp(adhocBssid.bssid, bcast_mac,
                                 AR6000_ETH_ADDR_LEN) == 0)
             {
                 ret = -EFAULT;
             } else {
 
-                A_MEMCPY(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
+                memcpy(ar->arReqBssid, adhocBssid.bssid, sizeof(ar->arReqBssid));
         }
             break;
         }
@@ -3120,9 +3141,9 @@
         case AR6000_XIOCTL_SET_OPT_MODE:
         {
         WMI_SET_OPT_MODE_CMD optModeCmd;
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&optModeCmd, userdata,
                                       sizeof(optModeCmd)))
@@ -3132,7 +3153,7 @@
                 ret = -EFAULT;
 
             } else if (wmi_set_opt_mode_cmd(ar->arWmi, optModeCmd.optMode)
-                       != A_OK)
+                       != 0)
             {
                 ret = -EIO;
             }
@@ -3141,36 +3162,43 @@
 
         case AR6000_XIOCTL_OPT_SEND_FRAME:
         {
-        WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
-            A_UINT8 data[MAX_OPT_DATA_LEN];
+            WMI_OPT_TX_FRAME_CMD optTxFrmCmd;
+            u8 data[MAX_OPT_DATA_LEN];
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
-            } else if (copy_from_user(&optTxFrmCmd, userdata,
-                                      sizeof(optTxFrmCmd)))
-            {
+                break;
+            }
+
+            if (copy_from_user(&optTxFrmCmd, userdata, sizeof(optTxFrmCmd))) {
                 ret = -EFAULT;
-            } else if (copy_from_user(data,
-                                      userdata+sizeof(WMI_OPT_TX_FRAME_CMD)-1,
-                                      optTxFrmCmd.optIEDataLen))
-            {
+                break;
+            }
+
+            if (optTxFrmCmd.optIEDataLen > MAX_OPT_DATA_LEN) {
+                ret = -EINVAL;
+                break;
+            }
+
+            if (copy_from_user(data, userdata+sizeof(WMI_OPT_TX_FRAME_CMD) - 1,
+                                   optTxFrmCmd.optIEDataLen)) {
                 ret = -EFAULT;
-            } else {
-                ret = wmi_opt_tx_frame_cmd(ar->arWmi,
+                break;
+            }
+
+            ret = wmi_opt_tx_frame_cmd(ar->arWmi,
                                            optTxFrmCmd.frmType,
                                            optTxFrmCmd.dstAddr,
                                            optTxFrmCmd.bssid,
                                            optTxFrmCmd.optIEDataLen,
                                            data);
-            }
-
             break;
         }
         case AR6000_XIOCTL_WMI_SETRETRYLIMITS:
         {
             WMI_SET_RETRY_LIMITS_CMD setRetryParams;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setRetryParams, userdata,
                                       sizeof(setRetryParams)))
@@ -3180,7 +3208,7 @@
                 if (wmi_set_retry_limits_cmd(ar->arWmi, setRetryParams.frameType,
                                           setRetryParams.trafficClass,
                                           setRetryParams.maxRetries,
-                                          setRetryParams.enableNotify) != A_OK)
+                                          setRetryParams.enableNotify) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3195,14 +3223,14 @@
         {
             WMI_BEACON_INT_CMD bIntvlCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&bIntvlCmd, userdata,
                        sizeof(bIntvlCmd)))
             {
                 ret = -EFAULT;
             } else if (wmi_set_adhoc_bconIntvl_cmd(ar->arWmi, bIntvlCmd.beaconInterval)
-                        != A_OK)
+                        != 0)
             {
                 ret = -EIO;
             }
@@ -3214,10 +3242,10 @@
         }
         case IEEE80211_IOCTL_SETAUTHALG:
         {
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
             struct ieee80211req_authalg req;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&req, userdata,
                        sizeof(struct ieee80211req_authalg)))
@@ -3267,7 +3295,7 @@
             AR6000_WLAN_STATE state;
 	    if (get_user(state, (unsigned int *)userdata))
 		ret = -EFAULT;
-	    else if (ar6000_set_wlan_state(ar, state) != A_OK)
+	    else if (ar6000_set_wlan_state(ar, state) != 0)
                 ret = -EIO;
             break;
         }
@@ -3327,7 +3355,7 @@
         {
             WMI_START_SCAN_CMD setStartScanCmd, *cmdp;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                     ret = -EIO;
                 } else if (copy_from_user(&setStartScanCmd, userdata,
                                           sizeof(setStartScanCmd)))
@@ -3339,7 +3367,7 @@
                         if (copy_from_user(cmdp, userdata,
                                            sizeof (*cmdp) +
                                            ((setStartScanCmd.numChannels - 1) *
-                                           sizeof(A_UINT16))))
+                                           sizeof(u16))))
                         {
                             kfree(cmdp);
                             ret = -EFAULT;
@@ -3355,7 +3383,7 @@
                                           cmdp->homeDwellTime,
                                           cmdp->forceScanInterval,
                                           cmdp->numChannels,
-                                          cmdp->channelList) != A_OK)
+                                          cmdp->channelList) != 0)
                     {
                         ret = -EIO;
                     }
@@ -3365,9 +3393,9 @@
         case AR6000_XIOCTL_WMI_SETFIXRATES:
         {
             WMI_FIX_RATES_CMD setFixRatesCmd;
-            A_STATUS returnStatus;
+            int returnStatus;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                     ret = -EIO;
                 } else if (copy_from_user(&setFixRatesCmd, userdata,
                                           sizeof(setFixRatesCmd)))
@@ -3377,7 +3405,7 @@
                     returnStatus = wmi_set_fixrates_cmd(ar->arWmi, setFixRatesCmd.fixRateMask);
                     if (returnStatus == A_EINVAL) {
                         ret = -EINVAL;
-                    } else if(returnStatus != A_OK) {
+                    } else if(returnStatus != 0) {
                         ret = -EIO;
                     } else {
                         ar->ap_profile_flag = 1; /* There is a change in profile */
@@ -3389,14 +3417,14 @@
         case AR6000_XIOCTL_WMI_GETFIXRATES:
         {
             WMI_FIX_RATES_CMD getFixRatesCmd;
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
             int ret = 0;
 
             if (ar->bIsDestroyProgress) {
                 ret = -EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
@@ -3416,7 +3444,7 @@
             } else {
                 ar->arRateMask = 0xFFFFFFFF;
 
-                if (wmi_get_ratemask_cmd(ar->arWmi) != A_OK) {
+                if (wmi_get_ratemask_cmd(ar->arWmi) != 0) {
                     up(&ar->arSem);
                     ret = -EIO;
                     goto ioctl_done;
@@ -3444,14 +3472,14 @@
         {
             WMI_SET_AUTH_MODE_CMD setAuthMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setAuthMode, userdata,
                                       sizeof(setAuthMode)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != A_OK)
+                if (wmi_set_authmode_cmd(ar->arWmi, setAuthMode.mode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3462,14 +3490,14 @@
         {
             WMI_SET_REASSOC_MODE_CMD setReassocMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setReassocMode, userdata,
                                       sizeof(setReassocMode)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != A_OK)
+                if (wmi_set_reassocmode_cmd(ar->arWmi, setReassocMode.mode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3478,13 +3506,13 @@
         }
         case AR6000_XIOCTL_DIAG_READ:
         {
-            A_UINT32 addr, data;
+            u32 addr, data;
 	    if (get_user(addr, (unsigned int *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
             addr = TARG_VTOP(ar->arTargetType, addr);
-            if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
+            if (ar6000_ReadRegDiag(ar->arHifDevice, &addr, &data) != 0) {
                 ret = -EIO;
             }
 	    if (put_user(data, (unsigned int *)userdata + 1)) {
@@ -3495,14 +3523,14 @@
         }
         case AR6000_XIOCTL_DIAG_WRITE:
         {
-            A_UINT32 addr, data;
+            u32 addr, data;
 	    if (get_user(addr, (unsigned int *)userdata) ||
 		get_user(data, (unsigned int *)userdata + 1)) {
 		ret = -EFAULT;
 		break;
 	    }
             addr = TARG_VTOP(ar->arTargetType, addr);
-            if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != A_OK) {
+            if (ar6000_WriteRegDiag(ar->arHifDevice, &addr, &data) != 0) {
                 ret = -EIO;
             }
             break;
@@ -3510,14 +3538,14 @@
         case AR6000_XIOCTL_WMI_SET_KEEPALIVE:
         {
              WMI_SET_KEEPALIVE_CMD setKeepAlive;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&setKeepAlive, userdata,
                         sizeof(setKeepAlive))){
                  ret = -EFAULT;
              } else {
-                 if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != A_OK) {
+                 if (wmi_set_keepalive_cmd(ar->arWmi, setKeepAlive.keepaliveInterval) != 0) {
                      ret = -EIO;
                }
              }
@@ -3526,7 +3554,7 @@
         case AR6000_XIOCTL_WMI_SET_PARAMS:
         {
              WMI_SET_PARAMS_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
@@ -3537,7 +3565,7 @@
             {
                 ret = -EFAULT;
             } else {
-                 if (wmi_set_params_cmd(ar->arWmi, cmd.opcode, cmd.length, cmd.buffer) != A_OK) {
+                 if (wmi_set_params_cmd(ar->arWmi, cmd.opcode, cmd.length, cmd.buffer) != 0) {
                      ret = -EIO;
                }
              }
@@ -3546,7 +3574,7 @@
         case AR6000_XIOCTL_WMI_SET_MCAST_FILTER:
         {
              WMI_SET_MCAST_FILTER_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
@@ -3556,7 +3584,7 @@
                  if (wmi_set_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
                                                                                      cmd.multicast_mac[1],
                                                                                      cmd.multicast_mac[2],
-                                                                                     cmd.multicast_mac[3]) != A_OK) {
+                                                                                     cmd.multicast_mac[3]) != 0) {
                      ret = -EIO;
                }
              }
@@ -3565,7 +3593,7 @@
         case AR6000_XIOCTL_WMI_DEL_MCAST_FILTER:
         {
              WMI_SET_MCAST_FILTER_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
@@ -3575,7 +3603,7 @@
                  if (wmi_del_mcast_filter_cmd(ar->arWmi, cmd.multicast_mac[0],
                                                                                      cmd.multicast_mac[1],
                                                                                      cmd.multicast_mac[2],
-                                                                                     cmd.multicast_mac[3]) != A_OK) {
+                                                                                     cmd.multicast_mac[3]) != 0) {
                      ret = -EIO;
                }
              }
@@ -3584,14 +3612,14 @@
         case AR6000_XIOCTL_WMI_MCAST_FILTER:
         {
              WMI_MCAST_FILTER_CMD cmd;
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
                  goto ioctl_done;
              } else if (copy_from_user(&cmd, userdata,
                         sizeof(cmd))){
                  ret = -EFAULT;
              } else {
-                 if (wmi_mcast_filter_cmd(ar->arWmi, cmd.enable)  != A_OK) {
+                 if (wmi_mcast_filter_cmd(ar->arWmi, cmd.enable)  != 0) {
                      ret = -EIO;
                }
              }
@@ -3599,14 +3627,14 @@
         }
         case AR6000_XIOCTL_WMI_GET_KEEPALIVE:
         {
-            AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+            struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
             WMI_GET_KEEPALIVE_CMD getKeepAlive;
             int ret = 0;
             if (ar->bIsDestroyProgress) {
                 ret =-EBUSY;
                 goto ioctl_done;
             }
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                ret = -EIO;
                goto ioctl_done;
             }
@@ -3624,7 +3652,7 @@
             } else {
             getKeepAlive.keepaliveInterval = wmi_get_keepalive_cmd(ar->arWmi);
             ar->arKeepaliveConfigured = 0xFF;
-            if (wmi_get_keepalive_configured(ar->arWmi) != A_OK){
+            if (wmi_get_keepalive_configured(ar->arWmi) != 0){
                 up(&ar->arSem);
                 ret = -EIO;
                 goto ioctl_done;
@@ -3647,14 +3675,14 @@
         case AR6000_XIOCTL_WMI_SET_APPIE:
         {
             WMI_SET_APPIE_CMD appIEcmd;
-            A_UINT8           appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
-            A_UINT32            fType,ieLen;
+            u8 appIeInfo[IEEE80211_APPIE_FRAME_MAX_LEN];
+            u32 fType,ieLen;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
             }
-	    if (get_user(fType, (A_UINT32 *)userdata)) {
+	    if (get_user(fType, (u32 *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
@@ -3662,7 +3690,7 @@
             if (appIEcmd.mgmtFrmType >= IEEE80211_APPIE_NUM_OF_FRAME) {
                 ret = -EIO;
             } else {
-		if (get_user(ieLen, (A_UINT32 *)(userdata + 4))) {
+		if (get_user(ieLen, (u32 *)(userdata + 4))) {
 		    ret = -EFAULT;
 		    break;
 		}
@@ -3676,7 +3704,7 @@
                     ret = -EFAULT;
                 } else {
                     if (wmi_set_appie_cmd(ar->arWmi, appIEcmd.mgmtFrmType,
-                                          appIEcmd.ieLen,  appIeInfo) != A_OK)
+                                          appIEcmd.ieLen,  appIeInfo) != 0)
                     {
                         ret = -EIO;
                     }
@@ -3687,9 +3715,9 @@
         case AR6000_XIOCTL_WMI_SET_MGMT_FRM_RX_FILTER:
         {
             WMI_BSS_FILTER_CMD cmd;
-            A_UINT32    filterType;
+            u32 filterType;
 
-            if (copy_from_user(&filterType, userdata, sizeof(A_UINT32)))
+            if (copy_from_user(&filterType, userdata, sizeof(u32)))
             {
                 ret = -EFAULT;
                 goto ioctl_done;
@@ -3701,7 +3729,7 @@
             } else {
                 cmd.bssFilter = NONE_BSS_FILTER;
             }
-            if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != A_OK) {
+            if (wmi_bssfilter_cmd(ar->arWmi, cmd.bssFilter, 0) != 0) {
                 ret = -EIO;
             } else {
                 ar->arUserBssFilter = cmd.bssFilter;
@@ -3714,33 +3742,33 @@
         }
         case AR6000_XIOCTL_WMI_SET_WSC_STATUS:
         {
-            A_UINT32    wsc_status;
+            u32 wsc_status;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
                 goto ioctl_done;
-            } else if (copy_from_user(&wsc_status, userdata, sizeof(A_UINT32)))
+            } else if (copy_from_user(&wsc_status, userdata, sizeof(u32)))
             {
                 ret = -EFAULT;
                 goto ioctl_done;
             }
-            if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != A_OK) {
+            if (wmi_set_wsc_status_cmd(ar->arWmi, wsc_status) != 0) {
                 ret = -EIO;
             }
             break;
         }
         case AR6000_XIOCTL_BMI_ROMPATCH_INSTALL:
         {
-            A_UINT32 ROM_addr;
-            A_UINT32 RAM_addr;
-            A_UINT32 nbytes;
-            A_UINT32 do_activate;
-            A_UINT32 rompatch_id;
+            u32 ROM_addr;
+            u32 RAM_addr;
+            u32 nbytes;
+            u32 do_activate;
+            u32 rompatch_id;
 
-	    if (get_user(ROM_addr, (A_UINT32 *)userdata) ||
-		get_user(RAM_addr, (A_UINT32 *)userdata + 1) ||
-		get_user(nbytes, (A_UINT32 *)userdata + 2) ||
-		get_user(do_activate, (A_UINT32 *)userdata + 3)) {
+	    if (get_user(ROM_addr, (u32 *)userdata) ||
+		get_user(RAM_addr, (u32 *)userdata + 1) ||
+		get_user(nbytes, (u32 *)userdata + 2) ||
+		get_user(do_activate, (u32 *)userdata + 3)) {
 		ret = -EFAULT;
 		break;
 	    }
@@ -3748,7 +3776,7 @@
                              ROM_addr, RAM_addr, nbytes));
             ret = BMIrompatchInstall(hifDevice, ROM_addr, RAM_addr,
                                         nbytes, do_activate, &rompatch_id);
-            if (ret == A_OK) {
+            if (ret == 0) {
 		/* return value */
 		if (put_user(rompatch_id, (unsigned int *)rq->ifr_data)) {
 		    ret = -EFAULT;
@@ -3760,9 +3788,9 @@
 
         case AR6000_XIOCTL_BMI_ROMPATCH_UNINSTALL:
         {
-            A_UINT32 rompatch_id;
+            u32 rompatch_id;
 
-	    if (get_user(rompatch_id, (A_UINT32 *)userdata)) {
+	    if (get_user(rompatch_id, (u32 *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
@@ -3774,14 +3802,14 @@
         case AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE:
         case AR6000_XIOCTL_BMI_ROMPATCH_DEACTIVATE:
         {
-            A_UINT32 rompatch_count;
+            u32 rompatch_count;
 
-	    if (get_user(rompatch_count, (A_UINT32 *)userdata)) {
+	    if (get_user(rompatch_count, (u32 *)userdata)) {
 		ret = -EFAULT;
 		break;
 	    }
             AR_DEBUG_PRINTF(ATH_DEBUG_INFO,("Change rompatch activation count=%d\n", rompatch_count));
-            length = sizeof(A_UINT32) * rompatch_count;
+            length = sizeof(u32) * rompatch_count;
             if ((buffer = (unsigned char *)A_MALLOC(length)) != NULL) {
                 A_MEMZERO(buffer, length);
                 if (copy_from_user(buffer, &userdata[sizeof(rompatch_count)], length))
@@ -3789,9 +3817,9 @@
                     ret = -EFAULT;
                 } else {
                     if (cmd == AR6000_XIOCTL_BMI_ROMPATCH_ACTIVATE) {
-                        ret = BMIrompatchActivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
+                        ret = BMIrompatchActivate(hifDevice, rompatch_count, (u32 *)buffer);
                     } else {
-                        ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (A_UINT32 *)buffer);
+                        ret = BMIrompatchDeactivate(hifDevice, rompatch_count, (u32 *)buffer);
                     }
                 }
                 A_FREE(buffer);
@@ -3805,7 +3833,7 @@
         {
             WMI_SET_IP_CMD setIP;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setIP, userdata,
                                       sizeof(setIP)))
@@ -3813,7 +3841,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_set_ip_cmd(ar->arWmi,
-                                &setIP) != A_OK)
+                                &setIP) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3825,7 +3853,7 @@
         {
             WMI_SET_HOST_SLEEP_MODE_CMD setHostSleepMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setHostSleepMode, userdata,
                                       sizeof(setHostSleepMode)))
@@ -3833,7 +3861,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_set_host_sleep_mode_cmd(ar->arWmi,
-                                &setHostSleepMode) != A_OK)
+                                &setHostSleepMode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3844,7 +3872,7 @@
         {
             WMI_SET_WOW_MODE_CMD setWowMode;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&setWowMode, userdata,
                                       sizeof(setWowMode)))
@@ -3852,7 +3880,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_set_wow_mode_cmd(ar->arWmi,
-                                &setWowMode) != A_OK)
+                                &setWowMode) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3863,7 +3891,7 @@
         {
             WMI_GET_WOW_LIST_CMD getWowList;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&getWowList, userdata,
                                       sizeof(getWowList)))
@@ -3871,7 +3899,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_get_wow_list_cmd(ar->arWmi,
-                                &getWowList) != A_OK)
+                                &getWowList) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3884,11 +3912,11 @@
 #define WOW_MASK_SIZE 64
 
             WMI_ADD_WOW_PATTERN_CMD cmd;
-            A_UINT8 mask_data[WOW_PATTERN_SIZE]={0};
-            A_UINT8 pattern_data[WOW_PATTERN_SIZE]={0};
+            u8 mask_data[WOW_PATTERN_SIZE]={0};
+            u8 pattern_data[WOW_PATTERN_SIZE]={0};
 
             do {
-                if (ar->arWmiReady == FALSE) {
+                if (ar->arWmiReady == false) {
                     ret = -EIO;
                     break;        
                 } 
@@ -3913,11 +3941,11 @@
                     break;
                 }
                 if (wmi_add_wow_pattern_cmd(ar->arWmi,
-                            &cmd, pattern_data, mask_data, cmd.filter_size) != A_OK)
+                            &cmd, pattern_data, mask_data, cmd.filter_size) != 0)
                 {
                     ret = -EIO;
                 }
-            } while(FALSE);
+            } while(false);
 #undef WOW_PATTERN_SIZE
 #undef WOW_MASK_SIZE
             break;
@@ -3926,7 +3954,7 @@
         {
             WMI_DEL_WOW_PATTERN_CMD delWowPattern;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&delWowPattern, userdata,
                                       sizeof(delWowPattern)))
@@ -3934,7 +3962,7 @@
                 ret = -EFAULT;
             } else {
                 if (wmi_del_wow_pattern_cmd(ar->arWmi,
-                                &delWowPattern) != A_OK)
+                                &delWowPattern) != 0)
                 {
                     ret = -EIO;
                 }
@@ -3948,7 +3976,7 @@
 #endif /* ATH_DEBUG_MODULE */
 #ifdef HTC_EP_STAT_PROFILING
                 {
-                    HTC_ENDPOINT_STATS stats;
+                    struct htc_endpoint_stats stats;
                     int i;
 
                     for (i = 0; i < 5; i++) {
@@ -3998,12 +4026,12 @@
                     /* note, this is used for testing (mbox ping testing), indicate activity
                      * change using the stream ID as the traffic class */
                 ar6000_indicate_tx_activity(ar,
-                                            (A_UINT8)data.StreamID,
-                                            data.Active ? TRUE : FALSE);
+                                            (u8)data.StreamID,
+                                            data.Active ? true : false);
             }
             break;
         case AR6000_XIOCTL_WMI_SET_CONNECT_CTRL_FLAGS:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&connectCtrlFlags, userdata,
                                       sizeof(connectCtrlFlags)))
@@ -4014,20 +4042,20 @@
             }
             break;
         case AR6000_XIOCTL_WMI_SET_AKMP_PARAMS:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&akmpParams, userdata,
                                       sizeof(WMI_SET_AKMP_PARAMS_CMD)))
             {
                 ret = -EFAULT;
             } else {
-                if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != A_OK) {
+                if (wmi_set_akmp_params_cmd(ar->arWmi, &akmpParams) != 0) {
                     ret = -EIO;
                 }
             }
             break;
         case AR6000_XIOCTL_WMI_SET_PMKID_LIST:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else {
                 if (copy_from_user(&pmkidInfo.numPMKID, userdata,
@@ -4043,30 +4071,30 @@
                     ret = -EFAULT;
                     break;
                 }
-                if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != A_OK) {
+                if (wmi_set_pmkid_list_cmd(ar->arWmi, &pmkidInfo) != 0) {
                     ret = -EIO;
                 }
             }
             break;
         case AR6000_XIOCTL_WMI_GET_PMKID_LIST:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else  {
-                if (wmi_get_pmkid_list_cmd(ar->arWmi) != A_OK) {
+                if (wmi_get_pmkid_list_cmd(ar->arWmi) != 0) {
                     ret = -EIO;
                 }
             }
             break;
         case AR6000_XIOCTL_WMI_ABORT_SCAN:
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             }
             ret = wmi_abort_scan_cmd(ar->arWmi);
             break;
         case AR6000_XIOCTL_AP_HIDDEN_SSID:
         {
-            A_UINT8    hidden_ssid;
-            if (ar->arWmiReady == FALSE) {
+            u8 hidden_ssid;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&hidden_ssid, userdata, sizeof(hidden_ssid))) {
                 ret = -EFAULT;
@@ -4079,14 +4107,14 @@
         }
         case AR6000_XIOCTL_AP_GET_STA_LIST:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else {
-                A_UINT8 i;
+                u8 i;
                 ap_get_sta_t temp;
                 A_MEMZERO(&temp, sizeof(temp));
                 for(i=0;i<AP_MAX_NUM_STA;i++) {
-                    A_MEMCPY(temp.sta[i].mac, ar->sta_list[i].mac, ATH_MAC_LEN);
+                    memcpy(temp.sta[i].mac, ar->sta_list[i].mac, ATH_MAC_LEN);
                     temp.sta[i].aid = ar->sta_list[i].aid;
                     temp.sta[i].keymgmt = ar->sta_list[i].keymgmt;
                     temp.sta[i].ucipher = ar->sta_list[i].ucipher;
@@ -4101,8 +4129,8 @@
         }
         case AR6000_XIOCTL_AP_SET_NUM_STA:
         {
-            A_UINT8    num_sta;
-            if (ar->arWmiReady == FALSE) {
+            u8 num_sta;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&num_sta, userdata, sizeof(num_sta))) {
                 ret = -EFAULT;
@@ -4116,8 +4144,8 @@
         }
         case AR6000_XIOCTL_AP_SET_ACL_POLICY:
         {
-            A_UINT8    policy;
-            if (ar->arWmiReady == FALSE) {
+            u8 policy;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&policy, userdata, sizeof(policy))) {
                 ret = -EFAULT;
@@ -4136,7 +4164,7 @@
         case AR6000_XIOCTL_AP_SET_ACL_MAC:
         {
             WMI_AP_ACL_MAC_CMD    acl;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&acl, userdata, sizeof(acl))) {
                 ret = -EFAULT;
@@ -4152,7 +4180,7 @@
         }
         case AR6000_XIOCTL_AP_GET_ACL_LIST:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_ACL *)rq->ifr_data, &ar->g_acl,
                                  sizeof(WMI_AP_ACL))) {
@@ -4168,7 +4196,7 @@
         case IEEE80211_IOCTL_GETWPAIE:
         {
             struct ieee80211req_wpaie wpaie;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&wpaie, userdata, sizeof(wpaie))) {
                 ret = -EFAULT;
@@ -4181,8 +4209,8 @@
         }
         case AR6000_XIOCTL_AP_CONN_INACT_TIME:
         {
-            A_UINT32    period;
-            if (ar->arWmiReady == FALSE) {
+            u32 period;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&period, userdata, sizeof(period))) {
                 ret = -EFAULT;
@@ -4194,7 +4222,7 @@
         case AR6000_XIOCTL_AP_PROT_SCAN_TIME:
         {
             WMI_AP_PROT_SCAN_TIME_CMD  bgscan;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&bgscan, userdata, sizeof(bgscan))) {
                 ret = -EFAULT;
@@ -4211,7 +4239,7 @@
         case AR6000_XIOCTL_AP_SET_DTIM:
         {
             WMI_AP_SET_DTIM_CMD  d;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&d, userdata, sizeof(d))) {
                 ret = -EFAULT;
@@ -4231,7 +4259,7 @@
         {
             WMI_SET_TARGET_EVENT_REPORT_CMD evtCfgCmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             }
             if (copy_from_user(&evtCfgCmd, userdata,
@@ -4244,8 +4272,8 @@
         }
         case AR6000_XIOCTL_AP_INTRA_BSS_COMM:
         {
-            A_UINT8    intra=0;
-            if (ar->arWmiReady == FALSE) {
+            u8 intra=0;
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&intra, userdata, sizeof(intra))) {
                 ret = -EFAULT;
@@ -4276,7 +4304,7 @@
                 break;
             }
 
-            if (A_FAILED(a_set_module_mask(moduleinfo.modulename, moduleinfo.mask))) {
+            if (a_set_module_mask(moduleinfo.modulename, moduleinfo.mask)) {
                 ret = -EFAULT;
             }
 
@@ -4291,7 +4319,7 @@
                 break;
             }
 
-            if (A_FAILED(a_get_module_mask(moduleinfo.modulename, &moduleinfo.mask))) {
+            if (a_get_module_mask(moduleinfo.modulename, &moduleinfo.mask)) {
                 ret = -EFAULT;
                 break;
             }
@@ -4318,7 +4346,7 @@
         {
             WMI_ADDBA_REQ_CMD cmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
@@ -4332,7 +4360,7 @@
         {
             WMI_DELBA_REQ_CMD cmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
@@ -4346,7 +4374,7 @@
         {
             WMI_ALLOW_AGGR_CMD cmd;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
@@ -4358,7 +4386,7 @@
 
         case AR6000_XIOCTL_SET_HT_CAP:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&htCap, userdata,
                                       sizeof(htCap)))
@@ -4366,7 +4394,7 @@
                 ret = -EFAULT;
             } else {
 
-                if (wmi_set_ht_cap_cmd(ar->arWmi, &htCap) != A_OK)
+                if (wmi_set_ht_cap_cmd(ar->arWmi, &htCap) != 0)
                 {
                     ret = -EIO;
                 }
@@ -4375,7 +4403,7 @@
         }
         case AR6000_XIOCTL_SET_HT_OP:
         {
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&htOp, userdata,
                                       sizeof(htOp)))
@@ -4383,7 +4411,7 @@
                  ret = -EFAULT;
              } else {
 
-                if (wmi_set_ht_op_cmd(ar->arWmi, htOp.sta_chan_width) != A_OK)
+                if (wmi_set_ht_op_cmd(ar->arWmi, htOp.sta_chan_width) != 0)
                 {
                      ret = -EIO;
                }
@@ -4394,12 +4422,12 @@
         case AR6000_XIOCTL_ACL_DATA:
         {
             void *osbuf = NULL;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
-            } else if (ar6000_create_acl_data_osbuf(dev, (A_UINT8*)userdata, &osbuf) != A_OK) {
+            } else if (ar6000_create_acl_data_osbuf(dev, (u8 *)userdata, &osbuf) != 0) {
                      ret = -EIO;
             } else {
-                if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != A_OK) {
+                if (wmi_data_hdr_add(ar->arWmi, osbuf, DATA_MSGTYPE, 0, WMI_DATA_HDR_DATA_TYPE_ACL,0,NULL) != 0) {
                     AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("XIOCTL_ACL_DATA - wmi_data_hdr_add failed\n"));
                 } else {
                     /* Send data buffer over HTC */
@@ -4411,19 +4439,19 @@
         case AR6000_XIOCTL_HCI_CMD:
         {
             char tmp_buf[512];
-            A_INT8 i;
+            s8 i;
             WMI_HCI_CMD *cmd = (WMI_HCI_CMD *)tmp_buf;
-            A_UINT8 size;
+            u8 size;
 
             size = sizeof(cmd->cmd_buf_sz);
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(cmd, userdata, size)) {
                  ret = -EFAULT;
             } else if(copy_from_user(cmd->buf, userdata + size, cmd->cmd_buf_sz)) {
                     ret = -EFAULT;
             } else {
-                if (wmi_send_hci_cmd(ar->arWmi, cmd->buf, cmd->cmd_buf_sz) != A_OK) {
+                if (wmi_send_hci_cmd(ar->arWmi, cmd->buf, cmd->cmd_buf_sz) != 0) {
                      ret = -EIO;
                 }else if(loghci) {
                     A_PRINTF_LOG("HCI Command To PAL --> \n");
@@ -4442,14 +4470,14 @@
         case AR6000_XIOCTL_WLAN_CONN_PRECEDENCE:
         {
             WMI_SET_BT_WLAN_CONN_PRECEDENCE cmd;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&cmd, userdata, sizeof(cmd))) {
                 ret = -EFAULT;
             } else {
                 if (cmd.precedence == BT_WLAN_CONN_PRECDENCE_WLAN ||
                             cmd.precedence == BT_WLAN_CONN_PRECDENCE_PAL) {
-                    if ( wmi_set_wlan_conn_precedence_cmd(ar->arWmi, cmd.precedence) != A_OK) {
+                    if ( wmi_set_wlan_conn_precedence_cmd(ar->arWmi, cmd.precedence) != 0) {
                         ret = -EIO;
                     }
                 } else {
@@ -4467,7 +4495,7 @@
         {
             WMI_SET_TX_SELECT_RATES_CMD masks;
 
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&masks, userdata,
                                       sizeof(masks)))
@@ -4475,7 +4503,7 @@
                  ret = -EFAULT;
              } else {
 
-                if (wmi_set_tx_select_rates_cmd(ar->arWmi, masks.rateMasks) != A_OK)
+                if (wmi_set_tx_select_rates_cmd(ar->arWmi, masks.rateMasks) != 0)
                 {
                      ret = -EIO;
                }
@@ -4487,7 +4515,7 @@
             WMI_AP_HIDDEN_SSID_CMD ssid;
             ssid.hidden_ssid = ar->ap_hidden_ssid;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_HIDDEN_SSID_CMD *)rq->ifr_data,
                                     &ssid, sizeof(WMI_AP_HIDDEN_SSID_CMD))) {
@@ -4498,9 +4526,9 @@
         case AR6000_XIOCTL_AP_GET_COUNTRY:
         {
             WMI_AP_SET_COUNTRY_CMD cty;
-            A_MEMCPY(cty.countryCode, ar->ap_country_code, 3);
+            memcpy(cty.countryCode, ar->ap_country_code, 3);
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_SET_COUNTRY_CMD *)rq->ifr_data,
                                     &cty, sizeof(WMI_AP_SET_COUNTRY_CMD))) {
@@ -4510,10 +4538,10 @@
         }
         case AR6000_XIOCTL_AP_GET_WMODE:
         {
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
-            } else if(copy_to_user((A_UINT8 *)rq->ifr_data,
-                                    &ar->ap_wmode, sizeof(A_UINT8))) {
+            } else if(copy_to_user((u8 *)rq->ifr_data,
+                                    &ar->ap_wmode, sizeof(u8))) {
                     ret = -EFAULT;
             }
             break;
@@ -4523,7 +4551,7 @@
             WMI_AP_SET_DTIM_CMD dtim;
             dtim.dtim = ar->ap_dtim_period;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_AP_SET_DTIM_CMD *)rq->ifr_data,
                                     &dtim, sizeof(WMI_AP_SET_DTIM_CMD))) {
@@ -4536,7 +4564,7 @@
             WMI_BEACON_INT_CMD bi;
             bi.beaconInterval = ar->ap_beacon_interval;
 
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_BEACON_INT_CMD *)rq->ifr_data,
                                     &bi, sizeof(WMI_BEACON_INT_CMD))) {
@@ -4549,7 +4577,7 @@
             WMI_SET_RTS_CMD rts;
             rts.threshold = ar->arRTS;
 	     
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if(copy_to_user((WMI_SET_RTS_CMD *)rq->ifr_data,
                                     &rts, sizeof(WMI_SET_RTS_CMD))) {
@@ -4559,11 +4587,11 @@
         }
         case AR6000_XIOCTL_FETCH_TARGET_REGS:
         {
-            A_UINT32 targregs[AR6003_FETCH_TARG_REGS_COUNT];
+            u32 targregs[AR6003_FETCH_TARG_REGS_COUNT];
 
             if (ar->arTargetType == TARGET_TYPE_AR6003) {
                 ar6k_FetchTargetRegs(hifDevice, targregs);
-                if (copy_to_user((A_UINT32 *)rq->ifr_data, &targregs, sizeof(targregs)))
+                if (copy_to_user((u32 *)rq->ifr_data, &targregs, sizeof(targregs)))
                 {
                     ret = -EFAULT;
                 }
@@ -4575,7 +4603,7 @@
         case AR6000_XIOCTL_AP_SET_11BG_RATESET:
         {
             WMI_AP_SET_11BG_RATESET_CMD  rate;
-            if (ar->arWmiReady == FALSE) {
+            if (ar->arWmiReady == false) {
                 ret = -EIO;
             } else if (copy_from_user(&rate, userdata, sizeof(rate))) {
                 ret = -EFAULT;
@@ -4595,7 +4623,7 @@
             }
             rq->ifr_ifru.ifru_ivalue = ar->arWlanState; /* return value */
 
-            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (A_UINT8*)&wmiSleepEvent,
+            ar6000_send_event_to_app(ar, WMI_REPORT_SLEEP_STATE_EVENTID, (u8 *)&wmiSleepEvent,
                                      sizeof(WMI_REPORT_SLEEP_STATE_EVENTID));
             break;
         }
@@ -4607,7 +4635,7 @@
 		ret = -EFAULT;
 		break;
 	    }
-            if (ar6000_set_bt_hw_state(ar, state)!=A_OK) {
+            if (ar6000_set_bt_hw_state(ar, state)!= 0) {
                 ret = -EIO;
             }       
         }
@@ -4621,13 +4649,13 @@
         {
              WMI_SET_TX_SGI_PARAM_CMD SGICmd;
 
-             if (ar->arWmiReady == FALSE) {
+             if (ar->arWmiReady == false) {
                  ret = -EIO;
              } else if (copy_from_user(&SGICmd, userdata,
                                        sizeof(SGICmd))){
                  ret = -EFAULT;
              } else{
-                     if (wmi_SGI_cmd(ar->arWmi, SGICmd.sgiMask, SGICmd.sgiPERThreshold) != A_OK) {
+                     if (wmi_SGI_cmd(ar->arWmi, SGICmd.sgiMask, SGICmd.sgiPERThreshold) != 0) {
                          ret = -EIO;
                      }
 
@@ -4642,7 +4670,7 @@
             if (copy_from_user(ap_ifname, userdata, IFNAMSIZ)) {
                 ret = -EFAULT;
             } else {
-                if (ar6000_add_ap_interface(ar, ap_ifname) != A_OK) {
+                if (ar6000_add_ap_interface(ar, ap_ifname) != 0) {
                     ret = -EIO;
                 } 
             }
@@ -4653,7 +4681,7 @@
             break;
         case AR6000_XIOCTL_REMOVE_AP_INTERFACE:
 #ifdef CONFIG_AP_VIRTUAL_ADAPTER_SUPPORT
-            if (ar6000_remove_ap_interface(ar) != A_OK) {
+            if (ar6000_remove_ap_interface(ar) != 0) {
                 ret = -EIO;
             } 
 #else
@@ -4661,6 +4689,12 @@
 #endif
             break;
 
+        case AR6000_XIOCTL_WMI_SET_EXCESS_TX_RETRY_THRES:
+        {
+            ret = ar6000_xioctl_set_excess_tx_retry_thres_cmd(dev, userdata);
+            break;
+        }
+
         default:
             ret = -EOPNOTSUPP;
     }
@@ -4672,15 +4706,15 @@
     return ret;
 }
 
-A_UINT8 mac_cmp_wild(A_UINT8 *mac, A_UINT8 *new_mac, A_UINT8 wild, A_UINT8 new_wild)
+u8 mac_cmp_wild(u8 *mac, u8 *new_mac, u8 wild, u8 new_wild)
 {
-    A_UINT8 i;
+    u8 i;
 
     for(i=0;i<ATH_MAC_LEN;i++) {
         if((wild & 1<<i) && (new_wild & 1<<i)) continue;
         if(mac[i] != new_mac[i]) return 1;
     }
-    if((A_MEMCMP(new_mac, null_mac, 6)==0) && new_wild &&
+    if((memcmp(new_mac, null_mac, 6)==0) && new_wild &&
         (wild != new_wild)) {
         return 1;
     }
@@ -4688,9 +4722,9 @@
     return 0;
 }
 
-A_UINT8    acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
+u8 acl_add_del_mac(WMI_AP_ACL *a, WMI_AP_ACL_MAC_CMD *acl)
 {
-    A_INT8    already_avail=-1, free_slot=-1, i;
+    s8 already_avail=-1, free_slot=-1, i;
 
     /* To check whether this mac is already there in our list */
     for(i=AP_ACL_SIZE-1;i>=0;i--)
@@ -4709,7 +4743,7 @@
         if((already_avail >= 0) || (free_slot == -1))
             return 0;
 
-        A_MEMCPY(a->acl_mac[free_slot], acl->mac, ATH_MAC_LEN);
+        memcpy(a->acl_mac[free_slot], acl->mac, ATH_MAC_LEN);
         a->index = a->index | (1 << free_slot);
         acl->index = free_slot;
         a->wildcard[free_slot] = acl->wildcard;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/netbuf.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/netbuf.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/netbuf.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/netbuf.c	2011-05-19 00:06:34.000000000 -0400
@@ -63,8 +63,8 @@
 {
     struct sk_buff *skb;
     size += 2 * (A_GET_CACHE_LINE_BYTES()); /* add some cacheline space at front and back of buffer */
-    skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + size);
-    skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(HTC_PACKET) + A_GET_CACHE_LINE_BYTES());    
+    skb = dev_alloc_skb(AR6000_DATA_OFFSET + sizeof(struct htc_packet) + size);
+    skb_reserve(skb, AR6000_DATA_OFFSET + sizeof(struct htc_packet) + A_GET_CACHE_LINE_BYTES());    
     return ((void *)skb);
 }
 
@@ -89,8 +89,7 @@
     dev_kfree_skb(skb);
 }
 
-A_UINT32
-a_netbuf_to_len(void *bufPtr)
+u32 a_netbuf_to_len(void *bufPtr)
 {
     return (((struct sk_buff *)bufPtr)->len);
 }
@@ -105,98 +104,97 @@
  * Add len # of bytes to the beginning of the network buffer
  * pointed to by bufPtr
  */
-A_STATUS
-a_netbuf_push(void *bufPtr, A_INT32 len)
+int
+a_netbuf_push(void *bufPtr, s32 len)
 {
     skb_push((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Add len # of bytes to the beginning of the network buffer
  * pointed to by bufPtr and also fill with data
  */
-A_STATUS
-a_netbuf_push_data(void *bufPtr, char *srcPtr, A_INT32 len)
+int
+a_netbuf_push_data(void *bufPtr, char *srcPtr, s32 len)
 {
     skb_push((struct sk_buff *) bufPtr, len);
-    A_MEMCPY(((struct sk_buff *)bufPtr)->data, srcPtr, len);
+    memcpy(((struct sk_buff *)bufPtr)->data, srcPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Add len # of bytes to the end of the network buffer
  * pointed to by bufPtr
  */
-A_STATUS
-a_netbuf_put(void *bufPtr, A_INT32 len)
+int
+a_netbuf_put(void *bufPtr, s32 len)
 {
     skb_put((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Add len # of bytes to the end of the network buffer
  * pointed to by bufPtr and also fill with data
  */
-A_STATUS
-a_netbuf_put_data(void *bufPtr, char *srcPtr, A_INT32 len)
+int
+a_netbuf_put_data(void *bufPtr, char *srcPtr, s32 len)
 {
     char *start = (char*)(((struct sk_buff *)bufPtr)->data +
         ((struct sk_buff *)bufPtr)->len);
     skb_put((struct sk_buff *)bufPtr, len);
-    A_MEMCPY(start, srcPtr, len);
+    memcpy(start, srcPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 
 /*
  * Trim the network buffer pointed to by bufPtr to len # of bytes 
  */
-A_STATUS
-a_netbuf_setlen(void *bufPtr, A_INT32 len)
+int
+a_netbuf_setlen(void *bufPtr, s32 len)
 {
     skb_trim((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Chop of len # of bytes from the end of the buffer.
  */
-A_STATUS
-a_netbuf_trim(void *bufPtr, A_INT32 len)
+int
+a_netbuf_trim(void *bufPtr, s32 len)
 {
     skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Chop of len # of bytes from the end of the buffer and return the data.
  */
-A_STATUS
-a_netbuf_trim_data(void *bufPtr, char *dstPtr, A_INT32 len)
+int
+a_netbuf_trim_data(void *bufPtr, char *dstPtr, s32 len)
 {
     char *start = (char*)(((struct sk_buff *)bufPtr)->data +
         (((struct sk_buff *)bufPtr)->len - len));
     
-    A_MEMCPY(dstPtr, start, len);
+    memcpy(dstPtr, start, len);
     skb_trim((struct sk_buff *)bufPtr, ((struct sk_buff *)bufPtr)->len - len);
 
-    return A_OK;
+    return 0;
 }
 
 
 /*
  * Returns the number of bytes available to a a_netbuf_push()
  */
-A_INT32
-a_netbuf_headroom(void *bufPtr)
+s32 a_netbuf_headroom(void *bufPtr)
 {
     return (skb_headroom((struct sk_buff *)bufPtr));
 }
@@ -204,25 +202,25 @@
 /*
  * Removes specified number of bytes from the beginning of the buffer
  */
-A_STATUS
-a_netbuf_pull(void *bufPtr, A_INT32 len)
+int
+a_netbuf_pull(void *bufPtr, s32 len)
 {
     skb_pull((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 /*
  * Removes specified number of bytes from the beginning of the buffer
  * and return the data
  */
-A_STATUS
-a_netbuf_pull_data(void *bufPtr, char *dstPtr, A_INT32 len)
+int
+a_netbuf_pull_data(void *bufPtr, char *dstPtr, s32 len)
 {
-    A_MEMCPY(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
+    memcpy(dstPtr, ((struct sk_buff *)bufPtr)->data, len);
     skb_pull((struct sk_buff *)bufPtr, len);
 
-    return A_OK;
+    return 0;
 }
 
 #ifdef EXPORT_HCI_BRIDGE_INTERFACE
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/wireless_ext.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/wireless_ext.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/os/linux/wireless_ext.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/os/linux/wireless_ext.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,7 +32,7 @@
 #define IWE_STREAM_ADD_VALUE(p1, p2, p3, p4, p5, p6) \
     iwe_stream_add_value((p1), (p2), (p3), (p4), (p5), (p6))
 
-static void ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi);
+static void ar6000_set_quality(struct iw_quality *iq, s8 rssi);
 extern unsigned int wmitimeout;
 extern A_WAITQUEUE_HEAD arEvent;
 
@@ -64,10 +64,9 @@
 }
 #endif /* WIRELESS_EXT > 14 */
 
-static A_UINT8
-get_bss_phy_capability(bss_t *bss)
+static u8 get_bss_phy_capability(bss_t *bss)
 {
-    A_UINT8 capability = 0;
+    u8 capability = 0;
     struct ieee80211_common_ie *cie = &bss->ni_cie;
 #define CHAN_IS_11A(x)              (!((x >= 2412) && (x <= 2484)))
     if (CHAN_IS_11A(cie->ie_chan)) {
@@ -94,12 +93,12 @@
     char buf[256];
 #endif
     struct ar_giwscan_param *param;
-    A_CHAR *current_ev;
-    A_CHAR *end_buf;
+    char *current_ev;
+    char *end_buf;
     struct ieee80211_common_ie  *cie;
-    A_CHAR *current_val;
-    A_INT32 j;
-    A_UINT32 rate_len, data_len = 0;
+    char *current_val;
+    s32 j;
+    u32 rate_len, data_len = 0;
 
     param = (struct ar_giwscan_param *)arg;
 
@@ -113,7 +112,7 @@
         A_MEMZERO(&iwe, sizeof(iwe));
         iwe.cmd = SIOCGIWAP;
         iwe.u.ap_addr.sa_family = ARPHRD_ETHER;
-        A_MEMCPY(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
+        memcpy(iwe.u.ap_addr.sa_data, ni->ni_macaddr, 6);
         current_ev = IWE_STREAM_ADD_EVENT(param->info, current_ev, end_buf,
                                           &iwe, IW_EV_ADDR_LEN);
     }
@@ -417,10 +416,10 @@
             struct iw_request_info *info,
             struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct ar_giwscan_param param;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -429,7 +428,7 @@
         return -EIO;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -462,12 +461,12 @@
                      struct iw_request_info *info,
                      struct iw_point *data, char *ssid)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_STATUS status;
-    A_UINT8     arNetworkType;
-    A_UINT8 prevMode = ar->arNetworkType;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    int status;
+    u8 arNetworkType;
+    u8 prevMode = ar->arNetworkType;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -480,7 +479,7 @@
         return -EIO;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -505,14 +504,14 @@
 
     if (ar->arNextMode == AP_NETWORK) {
         /* SSID change for AP network - Will take effect on commit */
-        if(A_MEMCMP(ar->arSsid,ssid,32) != 0) {
+        if(memcmp(ar->arSsid,ssid,32) != 0) {
              ar->arSsidLen = data->length - 1;
-            A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
+            memcpy(ar->arSsid, ssid, ar->arSsidLen);
             ar->ap_profile_flag = 1; /* There is a change in profile */
         }
         return 0;
     } else if(ar->arNetworkType == AP_NETWORK) {
-        A_UINT8 ctr;
+        u8 ctr;
         struct sk_buff *skb;
 
         /* We are switching from AP to STA | IBSS mode, cleanup the AP state */
@@ -532,7 +531,7 @@
        and we cannot scan during connect.
      */
     if (data->flags) {
-        if (ar->arSkipScan == TRUE &&
+        if (ar->arSkipScan == true &&
             (ar->arChannelHint == 0 ||
              (!ar->arReqBssid[0] && !ar->arReqBssid[1] && !ar->arReqBssid[2] &&
               !ar->arReqBssid[3] && !ar->arReqBssid[4] && !ar->arReqBssid[5])))
@@ -576,12 +575,13 @@
     /* Update the arNetworkType */
     ar->arNetworkType = ar->arNextMode;
 
-
     if ((prevMode != AP_NETWORK) &&
-        ((ar->arSsidLen) || ((ar->arSsidLen == 0) && ar->arConnected) || (!data->flags)))
+        ((ar->arSsidLen) || 
+        ((ar->arSsidLen == 0) && (ar->arConnected || ar->arConnectPending)) || 
+        (!data->flags)))
     {
         if ((!data->flags) ||
-            (A_MEMCMP(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
+            (memcmp(ar->arSsid, ssid, ar->arSsidLen) != 0) ||
             (ar->arSsidLen != (data->length - 1)))
         {
             /*
@@ -592,13 +592,13 @@
              * (2) essid off has been issued
              *
              */
-            if (ar->arWmiReady == TRUE) {
+            if (ar->arWmiReady == true) {
                 reconnect_flag = 0;
                 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
-                status = wmi_disconnect_cmd(ar->arWmi);
+                ar6000_disconnect(ar);
                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
                 ar->arSsidLen = 0;
-                if (ar->arSkipScan == FALSE) {
+                if (ar->arSkipScan == false) {
                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
                 }
                 if (!data->flags) {
@@ -617,13 +617,13 @@
              * a reconnect cmd. Issue a reconnect only we are already
              * connected.
              */
-            if((ar->arConnected == TRUE) && (ar->arWmiReady == TRUE))
+            if((ar->arConnected == true) && (ar->arWmiReady == true))
             {
-                reconnect_flag = TRUE;
+                reconnect_flag = true;
                 status = wmi_reconnect_cmd(ar->arWmi,ar->arReqBssid,
                                            ar->arChannelHint);
                 up(&ar->arSem);
-                if (status != A_OK) {
+                if (status) {
                     return -EIO;
                 }
                 return 0;
@@ -641,9 +641,9 @@
     }
 
     ar->arSsidLen = data->length - 1;
-    A_MEMCPY(ar->arSsid, ssid, ar->arSsidLen);
+    memcpy(ar->arSsid, ssid, ar->arSsidLen);
 
-    if (ar6000_connect_to_ap(ar)!= A_OK) {
+    if (ar6000_connect_to_ap(ar)!= 0) {
         up(&ar->arSem);
         return -EIO;
     }else{
@@ -658,9 +658,9 @@
                      struct iw_request_info *info,
                      struct iw_point *data, char *essid)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -675,16 +675,16 @@
 
     data->flags = 1;
     data->length = ar->arSsidLen;
-    A_MEMCPY(essid, ar->arSsid, ar->arSsidLen);
+    memcpy(essid, ar->arSsid, ar->arSsidLen);
 
     return 0;
 }
 
 
-void ar6000_install_static_wep_keys(AR_SOFTC_T *ar)
+void ar6000_install_static_wep_keys(struct ar6_softc *ar)
 {
-    A_UINT8 index;
-    A_UINT8 keyUsage;
+    u8 index;
+    u8 keyUsage;
 
     for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
         if (ar->arWepKeyList[index].arKeyLen) {
@@ -712,11 +712,11 @@
             struct iw_request_info *info,
             struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT32  kbps;
-    A_INT8  rate_idx;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u32 kbps;
+    s8 rate_idx;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -726,15 +726,15 @@
     } else {
         kbps = -1;                          /* -1 indicates auto rate */
     }
-    if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != A_OK)
+    if(kbps != -1 && wmi_validate_bitrate(ar->arWmi, kbps, &rate_idx) != 0)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_ERR,("BitRate is not Valid %d\n", kbps));
         return -EINVAL;
     }
     ar->arBitRate = kbps;
-    if(ar->arWmiReady == TRUE)
+    if(ar->arWmiReady == true)
     {
-        if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != A_OK) {
+        if (wmi_set_bitrate_cmd(ar->arWmi, kbps, -1, -1) != 0) {
             return -EINVAL;
         }
     }
@@ -749,10 +749,10 @@
             struct iw_request_info *info,
             struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -765,7 +765,7 @@
         return -EIO;
     }
 
-    if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == FALSE) {
+    if ((ar->arNextMode != AP_NETWORK && !ar->arConnected) || ar->arWmiReady == false) {
         rrq->value = 1000 * 1000;       
         return 0;
     }
@@ -780,7 +780,7 @@
     }
 
     ar->arBitRate = 0xFFFF;
-    if (wmi_get_bitrate_cmd(ar->arWmi) != A_OK) {
+    if (wmi_get_bitrate_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
@@ -792,7 +792,7 @@
        connected - return the value stored in the device structure */
     if (!ret) {
         if (ar->arBitRate == -1) {
-            rrq->fixed = TRUE;
+            rrq->fixed = true;
             rrq->value = 0;
         } else {
             rrq->value = ar->arBitRate * 1000;
@@ -812,10 +812,10 @@
              struct iw_request_info *info,
              struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8 dbM;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 dbM;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -833,12 +833,12 @@
             return -EOPNOTSUPP;
         }
         ar->arTxPwr= dbM = rrq->value;
-        ar->arTxPwrSet = TRUE;
+        ar->arTxPwrSet = true;
     } else {
         ar->arTxPwr = dbM = 0;
-        ar->arTxPwrSet = FALSE;
+        ar->arTxPwrSet = false;
     }
-    if(ar->arWmiReady == TRUE)
+    if(ar->arWmiReady == true)
     {
         AR_DEBUG_PRINTF(ATH_DEBUG_WLAN_TX,("Set tx pwr cmd %d dbM\n", dbM));
         wmi_set_txPwr_cmd(ar->arWmi, dbM);
@@ -854,10 +854,10 @@
             struct iw_request_info *info,
             struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -879,11 +879,11 @@
         return -EBUSY;
     }
 
-    if((ar->arWmiReady == TRUE) && (ar->arConnected == TRUE))
+    if((ar->arWmiReady == true) && (ar->arConnected == true))
     {
         ar->arTxPwr = 0;
 
-        if (wmi_get_txPwr_cmd(ar->arWmi) != A_OK) {
+        if (wmi_get_txPwr_cmd(ar->arWmi) != 0) {
             up(&ar->arSem);
             return -EIO;
         }
@@ -898,8 +898,8 @@
       then return value stored in the device structure */
 
     if (!ret) {
-         if (ar->arTxPwrSet == TRUE) {
-            rrq->fixed = TRUE;
+         if (ar->arTxPwrSet == true) {
+            rrq->fixed = true;
         }
         rrq->value = ar->arTxPwr;
         rrq->flags = IW_TXPOW_DBM;
@@ -924,9 +924,9 @@
              struct iw_request_info *info,
              struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -946,10 +946,10 @@
     if ( !(rrq->value >= WMI_MIN_RETRIES) || !(rrq->value <= WMI_MAX_RETRIES)) {
             return - EINVAL;
     }
-    if(ar->arWmiReady == TRUE)
+    if(ar->arWmiReady == true)
     {
         if (wmi_set_retry_limits_cmd(ar->arWmi, DATA_FRAMETYPE, WMM_AC_BE,
-                                     rrq->value, 0) != A_OK){
+                                     rrq->value, 0) != 0){
             return -EINVAL;
         }
     }
@@ -965,9 +965,9 @@
              struct iw_request_info *info,
              struct iw_param *rrq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1006,11 +1006,11 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *keybuf)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int index;
-    A_INT32 auth = 0;
+    s32 auth = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1080,7 +1080,7 @@
 
             A_MEMZERO(ar->arWepKeyList[index].arKey,
                       sizeof(ar->arWepKeyList[index].arKey));
-            A_MEMCPY(ar->arWepKeyList[index].arKey, keybuf, erq->length);
+            memcpy(ar->arWepKeyList[index].arKey, keybuf, erq->length);
             ar->arWepKeyList[index].arKeyLen = erq->length;
             ar->arDot11AuthMode       = auth;
         } else {
@@ -1122,11 +1122,11 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *key)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT8 keyIndex;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u8 keyIndex;
     struct ar_wep_key *wk;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1158,14 +1158,14 @@
                 erq->length = wk->arKeyLen;
             }
             if (wk->arKeyLen) {
-                A_MEMCPY(key, wk->arKey, erq->length);
+                memcpy(key, wk->arKey, erq->length);
             }
         } else {
             erq->flags &= ~IW_ENCODE_DISABLED;
             if (ar->user_saved_keys.keyOk) {
                 erq->length = ar->user_saved_keys.ucast_ik.ik_keylen;
                 if (erq->length) {
-                    A_MEMCPY(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
+                    memcpy(key, ar->user_saved_keys.ucast_ik.ik_keydata, erq->length);
                 }
             } else {
                 erq->length = 1;    // not really printing any key but let iwconfig know enc is on
@@ -1192,16 +1192,16 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
 #ifdef WAPI_ENABLE
-    A_UINT8    *ie = erq->pointer;
-    A_UINT8    ie_type = ie[0];
-    A_UINT16   ie_length = erq->length;
-    A_UINT8    wapi_ie[128];
+    u8 *ie = erq->pointer;
+    u8 ie_type = ie[0];
+    u16 ie_length = erq->length;
+    u8 wapi_ie[128];
 #endif
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 #ifdef WAPI_ENABLE
@@ -1228,9 +1228,9 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
     erq->length = 0;
@@ -1247,14 +1247,14 @@
               struct iw_request_info *info,
               struct iw_param *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    A_BOOL profChanged;
-    A_UINT16 param;
-    A_INT32 ret;
-    A_INT32 value;
+    bool profChanged;
+    u16 param;
+    s32 ret;
+    s32 value;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1264,7 +1264,7 @@
 
     param = data->flags & IW_AUTH_INDEX;
     value = data->value;
-    profChanged = TRUE;
+    profChanged = true;
     ret = 0;
 
     switch (param) {
@@ -1277,7 +1277,7 @@
                     ar->arAuthMode = WPA2_AUTH;
             } else {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_CIPHER_PAIRWISE:
@@ -1298,7 +1298,7 @@
                 ar->arPairwiseCryptoLen = 13;
             } else {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_CIPHER_GROUP:
@@ -1319,7 +1319,7 @@
                 ar->arGroupCryptoLen = 13;
             } else {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_KEY_MGMT:
@@ -1337,10 +1337,10 @@
             break;
         case IW_AUTH_TKIP_COUNTERMEASURES:
             wmi_set_tkip_countermeasures_cmd(ar->arWmi, value);
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_DROP_UNENCRYPTED:
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_80211_AUTH_ALG:
             ar->arDot11AuthMode = 0;
@@ -1355,7 +1355,7 @@
             }
             if(ar->arDot11AuthMode == 0) {
                 ret = -1;
-                profChanged    = FALSE;
+                profChanged    = false;
             }
             break;
         case IW_AUTH_WPA_ENABLED:
@@ -1374,10 +1374,10 @@
             }
             break;
         case IW_AUTH_RX_UNENCRYPTED_EAPOL:
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_ROAMING_CONTROL:
-            profChanged    = FALSE;
+            profChanged    = false;
             break;
         case IW_AUTH_PRIVACY_INVOKED:
             if (!value) {
@@ -1394,11 +1394,11 @@
 #endif
         default:
            ret = -1;
-           profChanged    = FALSE;
+           profChanged    = false;
            break;
     }
 
-    if (profChanged == TRUE) {
+    if (profChanged == true) {
         /*
          * profile has changed.  Erase ssid to signal change
          */
@@ -1418,11 +1418,11 @@
               struct iw_request_info *info,
               struct iw_param *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_UINT16 param;
-    A_INT32 ret;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    u16 param;
+    s32 ret;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1546,29 +1546,29 @@
               struct iw_request_info *info,
               struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_INT32 ret;
-    A_STATUS status;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    s32 ret;
+    int status;
     struct iw_pmksa *pmksa;
 
     pmksa = (struct iw_pmksa *)extra;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
     ret = 0;
-    status = A_OK;
+    status = 0;
 
     switch (pmksa->cmd) {
         case IW_PMKSA_ADD:
-            status = wmi_setPmkid_cmd(ar->arWmi, (A_UINT8*)pmksa->bssid.sa_data, pmksa->pmkid, TRUE);
+            status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, true);
             break;
         case IW_PMKSA_REMOVE:
-            status = wmi_setPmkid_cmd(ar->arWmi, (A_UINT8*)pmksa->bssid.sa_data, pmksa->pmkid, FALSE);
+            status = wmi_setPmkid_cmd(ar->arWmi, (u8 *)pmksa->bssid.sa_data, pmksa->pmkid, false);
             break;
         case IW_PMKSA_FLUSH:
-            if (ar->arConnected == TRUE) {
+            if (ar->arConnected == true) {
                 status = wmi_setPmkid_cmd(ar->arWmi, ar->arBssid, NULL, 0);
             }
             break;
@@ -1576,7 +1576,7 @@
             ret=-1;
             break;
     }
-    if (status != A_OK) {
+    if (status) {
         ret = -1;
     }
 
@@ -1591,18 +1591,18 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct iw_encode_ext *ext = (struct iw_encode_ext *)extra;
     KEY_USAGE   keyUsage = 0;
-    A_INT32     keyLen;
-    A_UINT8     *keyData;
-    A_INT32     index;
-    A_UINT32    *PN;
-    A_INT32     i;
-    A_STATUS    status;
-    A_UINT8     wapiKeyRsc[16];
+    s32 keyLen;
+    u8 *keyData;
+    s32 index;
+    u32 *PN;
+    s32 i;
+    int    status;
+    u8 wapiKeyRsc[16];
     CRYPTO_TYPE keyType = WAPI_CRYPT;
-    const A_UINT8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
+    const u8 broadcastMac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 
     index = erq->flags & IW_ENCODE_INDEX;
     if (index && (((index - 1) < WMI_MIN_KEY_INDEX) ||
@@ -1614,13 +1614,13 @@
     if (index < 0 || index > 4) {
         return -EIO;
     }
-    keyData = (A_UINT8 *)(ext + 1);
+    keyData = (u8 *)(ext + 1);
     keyLen = erq->length - sizeof(struct iw_encode_ext);
-    A_MEMCPY(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
+    memcpy(wapiKeyRsc, ext->tx_seq, sizeof(wapiKeyRsc));
 
-    if (A_MEMCMP(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
+    if (memcmp(ext->addr.sa_data, broadcastMac, sizeof(broadcastMac)) == 0) {
         keyUsage |= GROUP_USAGE;
-        PN = (A_UINT32 *)wapiKeyRsc;
+        PN = (u32 *)wapiKeyRsc;
         for (i = 0; i < 4; i++) {
             PN[i] = PN_INIT;
         }
@@ -1637,7 +1637,7 @@
                             KEY_OP_INIT_WAPIPN,
                             NULL,
                             SYNC_BEFORE_WMIFLAG);
-    if (A_OK != status) {
+    if (0 != status) {
         return -EIO;
     }
     return 0;
@@ -1653,14 +1653,14 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
-    A_INT32 index;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
+    s32 index;
     struct iw_encode_ext *ext;
     KEY_USAGE keyUsage;
-    A_INT32 keyLen;
-    A_UINT8 *keyData;
-    A_UINT8 keyRsc[8];
-    A_STATUS status;
+    s32 keyLen;
+    u8 *keyData;
+    u8 keyRsc[8];
+    int status;
     CRYPTO_TYPE keyType;
 #ifdef USER_KEYS
     struct ieee80211req_key ik;
@@ -1671,7 +1671,7 @@
     }
 
 #ifdef USER_KEYS
-    ar->user_saved_keys.keyOk = FALSE;
+    ar->user_saved_keys.keyOk = false;
 #endif /* USER_KEYS */
 
     index = erq->flags & IW_ENCODE_INDEX;
@@ -1721,7 +1721,7 @@
         }
 
         /* key follows iw_encode_ext */
-        keyData = (A_UINT8 *)(ext + 1);
+        keyData = (u8 *)(ext + 1);
 
         switch (ext->alg) {
             case IW_ENCODE_ALG_WEP:
@@ -1737,7 +1737,7 @@
                 if (!ar->arConnected) {
                     A_MEMZERO(ar->arWepKeyList[index].arKey,
                           sizeof(ar->arWepKeyList[index].arKey));
-                    A_MEMCPY(ar->arWepKeyList[index].arKey, keyData, keyLen);
+                    memcpy(ar->arWepKeyList[index].arKey, keyData, keyLen);
                     ar->arWepKeyList[index].arKeyLen = keyLen;
 
                     return 0;
@@ -1778,7 +1778,7 @@
         }
 
         if (ext->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
-            A_MEMCPY(keyRsc, ext->rx_seq, sizeof(keyRsc));
+            memcpy(keyRsc, ext->rx_seq, sizeof(keyRsc));
         } else {
             A_MEMZERO(keyRsc, sizeof(keyRsc));
         }
@@ -1792,9 +1792,9 @@
          status = wmi_addKey_cmd(ar->arWmi, index, keyType, keyUsage,
                             keyLen, keyRsc,
                             keyData, KEY_OP_INIT_VAL,
-                            (A_UINT8*)ext->addr.sa_data,
+                            (u8 *)ext->addr.sa_data,
                             SYNC_BOTH_WMIFLAG);
-         if (status != A_OK) {
+         if (status) {
             return -EIO;
          }
 
@@ -1811,7 +1811,7 @@
             memcpy(&ar->user_saved_keys.ucast_ik, &ik,
                       sizeof(struct ieee80211req_key));
         }
-        ar->user_saved_keys.keyOk = TRUE;
+        ar->user_saved_keys.keyOk = true;
 #endif /* USER_KEYS */
     }
 
@@ -1827,7 +1827,7 @@
               struct iw_request_info *info,
               struct iw_point *erq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
     if (ar->arWlanState == WLAN_DISABLED) {
         return -EIO;
@@ -1850,10 +1850,10 @@
                  union iwreq_data *wrqu, char *extra)
 {
 #ifndef ATH6K_CONFIG_OTA_MODE
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWER_MODE power_mode;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1876,10 +1876,10 @@
                  struct iw_request_info *info,
                  union iwreq_data *wrqu, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     WMI_POWER_MODE power_mode;
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -1906,10 +1906,10 @@
            struct iw_request_info *info,
            char *name, char *extra)
 {
-    A_UINT8 capability;
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    u8 capability;
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -1961,9 +1961,9 @@
             struct iw_request_info *info,
             struct iw_freq *freq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2006,9 +2006,9 @@
                 struct iw_request_info *info,
                 struct iw_freq *freq, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2026,7 +2026,7 @@
             return -EINVAL;
         }
     } else {
-        if (ar->arConnected != TRUE) {
+        if (ar->arConnected != true) {
             return -EINVAL;
         } else {
             freq->m = ar->arBssChannel * 100000;
@@ -2046,9 +2046,9 @@
             struct iw_request_info *info,
             __u32 *mode, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2060,7 +2060,7 @@
     /*
      * clear SSID during mode switch in connected state
      */
-    if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == TRUE) ){
+    if(!(ar->arNetworkType == (((*mode) == IW_MODE_INFRA) ? INFRA_NETWORK : ADHOC_NETWORK)) && (ar->arConnected == true) ){
         A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
         ar->arSsidLen = 0;
     }
@@ -2117,9 +2117,9 @@
             struct iw_request_info *info,
             __u32 *mode, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2177,11 +2177,11 @@
              struct iw_request_info *info,
              struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     struct iw_range *range = (struct iw_range *) extra;
     int i, ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2190,7 +2190,7 @@
         return -EBUSY;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2206,7 +2206,7 @@
     ar->arNumChannels = -1;
     A_MEMZERO(ar->arChannelList, sizeof (ar->arChannelList));
 
-    if (wmi_get_channelList_cmd(ar->arWmi) != A_OK) {
+    if (wmi_get_channelList_cmd(ar->arWmi) != 0) {
         up(&ar->arSem);
         return -EIO;
     }
@@ -2300,9 +2300,9 @@
               struct iw_request_info *info,
               struct sockaddr *ap_addr, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2315,10 +2315,10 @@
         return -EIO;
     }
 
-    if (A_MEMCMP(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
+    if (memcmp(&ap_addr->sa_data, bcast_mac, AR6000_ETH_ADDR_LEN) == 0) {
         A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
     } else {
-        A_MEMCPY(ar->arReqBssid, &ap_addr->sa_data,  sizeof(ar->arReqBssid));
+        memcpy(ar->arReqBssid, &ap_addr->sa_data,  sizeof(ar->arReqBssid));
     }
 
     return 0;
@@ -2332,9 +2332,9 @@
               struct iw_request_info *info,
               struct sockaddr *ap_addr, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2344,16 +2344,16 @@
     }
 
     if (ar->arNetworkType == AP_NETWORK) {
-        A_MEMCPY(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
+        memcpy(&ap_addr->sa_data, dev->dev_addr, ATH_MAC_LEN);
         ap_addr->sa_family = ARPHRD_ETHER;
         return 0;
     }
 
-    if (ar->arConnected != TRUE) {
+    if (ar->arConnected != true) {
         return -EINVAL;
     }
 
-    A_MEMCPY(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
+    memcpy(&ap_addr->sa_data, ar->arBssid, sizeof(ar->arBssid));
     ap_addr->sa_family = ARPHRD_ETHER;
 
     return 0;
@@ -2368,9 +2368,9 @@
             struct iw_request_info *info,
             struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
@@ -2383,7 +2383,7 @@
         return -EIO;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2393,7 +2393,7 @@
 
     if (data->pointer && data->length == sizeof(struct iw_mlme)) {
 
-        A_UINT8 arNetworkType;
+        u8 arNetworkType;
         struct iw_mlme mlme;
 
         if (copy_from_user(&mlme, data->pointer, sizeof(struct iw_mlme)))
@@ -2404,7 +2404,7 @@
             case IW_MLME_DEAUTH:
                 /* fall through */
             case IW_MLME_DISASSOC:
-                if ((ar->arConnected != TRUE) ||
+                if ((ar->arConnected != true) ||
                     (memcmp(ar->arBssid, mlme.addr.sa_data, 6) != 0)) {
 
                     up(&ar->arSem);
@@ -2415,10 +2415,10 @@
                 ar6000_init_profile_info(ar);
                 ar->arNetworkType = arNetworkType;
                 reconnect_flag = 0;
-                wmi_disconnect_cmd(ar->arWmi);
+                ar6000_disconnect(ar);
                 A_MEMZERO(ar->arSsid, sizeof(ar->arSsid));
                 ar->arSsidLen = 0;
-                if (ar->arSkipScan == FALSE) {
+                if (ar->arSkipScan == false) {
                     A_MEMZERO(ar->arReqBssid, sizeof(ar->arReqBssid));
                 }
                 break;
@@ -2460,15 +2460,15 @@
 #define ACT_DWELLTIME_DEFAULT   105
 #define HOME_TXDRAIN_TIME       100
 #define SCAN_INT                HOME_TXDRAIN_TIME + ACT_DWELLTIME_DEFAULT
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
     int ret = 0;
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2488,13 +2488,13 @@
     } 
 
     if (!ar->arUserBssFilter) {
-        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != A_OK) {
+        if (wmi_bssfilter_cmd(ar->arWmi, ALL_BSS_FILTER, 0) != 0) {
             return -EIO;
         }
     }
 
     if (ar->arConnected) {
-        if  (wmi_get_stats_cmd(ar->arWmi) != A_OK) {
+        if  (wmi_get_stats_cmd(ar->arWmi) != 0) {
             return -EIO;
         }
     }
@@ -2508,32 +2508,32 @@
             struct iw_scan_req req;
             if (copy_from_user(&req, data->pointer, sizeof(struct iw_scan_req)))
                 return -EIO;
-            if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != A_OK)
+            if (wmi_probedSsid_cmd(ar->arWmi, 1, SPECIFIC_SSID_FLAG, req.essid_len, req.essid) != 0)
                 return -EIO;
-            ar->scanSpecificSsid = 1;
+            ar->scanSpecificSsid = true;
         }
         else
         {
             if (ar->scanSpecificSsid) {
-                if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
+                if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != 0)
                     return -EIO;
-                 ar->scanSpecificSsid = 0;
+                 ar->scanSpecificSsid = false;
             }
         }
     }
     else
     {
         if (ar->scanSpecificSsid) {
-            if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != A_OK)
+            if (wmi_probedSsid_cmd(ar->arWmi, 1, DISABLE_SSID_FLAG, 0, NULL) != 0)
                 return -EIO;
-             ar->scanSpecificSsid = 0;
+             ar->scanSpecificSsid = false;
         }
     }
 #endif
 #endif /* ANDROID_ENV */
 
-    if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, FALSE, FALSE, \
-                          0, 0, 0, NULL) != A_OK) {
+    if (wmi_startscan_cmd(ar->arWmi, WMI_LONG_SCAN, false, false, \
+                          0, 0, 0, NULL) != 0) {
         ret = -EIO;
     }
 
@@ -2565,7 +2565,7 @@
  *     drivers for compatibility
  */
 static void
-ar6000_set_quality(struct iw_quality *iq, A_INT8 rssi)
+ar6000_set_quality(struct iw_quality *iq, s8 rssi)
 {
     if (rssi < 0) {
         iq->qual = 0;
@@ -2588,14 +2588,14 @@
                      struct iw_request_info *info,
                      struct iw_point *data, char *extra)
 {
-    AR_SOFTC_T *ar = (AR_SOFTC_T *)ar6k_priv(dev);
+    struct ar6_softc *ar = (struct ar6_softc *)ar6k_priv(dev);
 
-    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != A_OK) {
+    if (is_iwioctl_allowed(ar->arNextMode, info->cmd) != 0) {
         A_PRINTF("wext_ioctl: cmd=0x%x not allowed in this mode\n", info->cmd);
         return -EOPNOTSUPP;
     }
 
-    if (ar->arWmiReady == FALSE) {
+    if (ar->arWmiReady == false) {
         return -EIO;
     }
 
@@ -2615,8 +2615,6 @@
      * update the host driver association state for the STA|IBSS mode.
      */
     if (ar->arNetworkType != AP_NETWORK && ar->arNextMode == AP_NETWORK) {
-        ar->arConnectPending = FALSE;
-        ar->arConnected = FALSE;
         /* Stop getting pkts from upper stack */
         netif_stop_queue(ar->arNetDev);
         A_MEMZERO(ar->arBssid, sizeof(ar->arBssid));
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/reorder/aggr_rx_internal.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/reorder/aggr_rx_internal.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/reorder/aggr_rx_internal.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/reorder/aggr_rx_internal.h	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
 #define AGGR_GET_RXTID(_p, _x)    (&(_p->RxTid[(_x)]))
 
 /* Hold q is a function of win_sz, which is negotiated per tid */
-#define HOLD_Q_SZ(_x)   (TID_WINDOW_SZ((_x))*sizeof(OSBUF_HOLD_Q))
+#define HOLD_Q_SZ(_x)   (TID_WINDOW_SZ((_x))*sizeof(struct osbuf_hold_q))
 /* AGGR_RX_TIMEOUT value is important as a (too) small value can cause frames to be 
  * delivered out of order and a (too) large value can cause undesirable latency in
  * certain situations. */
@@ -59,58 +59,59 @@
     CONTIGUOUS_SEQNO = 1,
 }DELIVERY_ORDER;
 
-typedef struct {
+struct osbuf_hold_q {
     void        *osbuf;
-    A_BOOL      is_amsdu;
-    A_UINT16    seq_no;
-}OSBUF_HOLD_Q;
+    bool      is_amsdu;
+    u16 seq_no;
+};
 
 
 #if 0
-typedef struct {
-    A_UINT16    seqno_st;
-    A_UINT16    seqno_end;
-}WINDOW_SNAPSHOT;
+/* XXX: unused ? */
+struct window_snapshot {
+    u16 seqno_st;
+    u16 seqno_end;
+};
 #endif
 
-typedef struct {
-    A_BOOL              aggr;       /* is it ON or OFF */
-    A_BOOL              progress;   /* TRUE when frames have arrived after a timer start */
-    A_BOOL              timerMon;   /* TRUE if the timer started for the sake of this TID */
-    A_UINT16            win_sz;     /* negotiated window size */
-    A_UINT16            seq_next;   /* Next seq no, in current window */
-    A_UINT32            hold_q_sz;  /* Num of frames that can be held in hold q */
-    OSBUF_HOLD_Q        *hold_q;    /* Hold q for re-order */
+struct rxtid {
+    bool              aggr;       /* is it ON or OFF */
+    bool              progress;   /* true when frames have arrived after a timer start */
+    bool              timerMon;   /* true if the timer started for the sake of this TID */
+    u16 win_sz;     /* negotiated window size */
+    u16 seq_next;   /* Next seq no, in current window */
+    u32 hold_q_sz;  /* Num of frames that can be held in hold q */
+    struct osbuf_hold_q        *hold_q;    /* Hold q for re-order */
 #if 0    
-    WINDOW_SNAPSHOT     old_win;    /* Sliding window snapshot - for timeout */
+    struct window_snapshot     old_win;    /* Sliding window snapshot - for timeout */
 #endif    
     A_NETBUF_QUEUE_T    q;          /* q head for enqueuing frames for dispatch */
     A_MUTEX_T           lock;
-}RXTID;
+};
 
-typedef struct {
-    A_UINT32    num_into_aggr;      /* hitting at the input of this module */
-    A_UINT32    num_dups;           /* duplicate */
-    A_UINT32    num_oow;            /* out of window */
-    A_UINT32    num_mpdu;           /* single payload 802.3/802.11 frame */
-    A_UINT32    num_amsdu;          /* AMSDU */
-    A_UINT32    num_delivered;      /* frames delivered to IP stack */
-    A_UINT32    num_timeouts;       /* num of timeouts, during which frames delivered */
-    A_UINT32    num_hole;           /* frame not present, when window moved over */
-    A_UINT32    num_bar;            /* num of resets of seq_num, via BAR */
-}RXTID_STATS;
+struct rxtid_stats {
+    u32 num_into_aggr;      /* hitting at the input of this module */
+    u32 num_dups;           /* duplicate */
+    u32 num_oow;            /* out of window */
+    u32 num_mpdu;           /* single payload 802.3/802.11 frame */
+    u32 num_amsdu;          /* AMSDU */
+    u32 num_delivered;      /* frames delivered to IP stack */
+    u32 num_timeouts;       /* num of timeouts, during which frames delivered */
+    u32 num_hole;           /* frame not present, when window moved over */
+    u32 num_bar;            /* num of resets of seq_num, via BAR */
+};
 
-typedef struct {
-    A_UINT8             aggr_sz;            /* config value of aggregation size */    
-    A_UINT8             timerScheduled;
+struct aggr_info {
+    u8 aggr_sz;            /* config value of aggregation size */
+    u8 timerScheduled;
     A_TIMER             timer;              /* timer for returning held up pkts in re-order que */    
     void                *dev;               /* dev handle */
     RX_CALLBACK         rx_fn;              /* callback function to return frames; to upper layer */
-    RXTID               RxTid[NUM_OF_TIDS]; /* Per tid window */
+    struct rxtid               RxTid[NUM_OF_TIDS]; /* Per tid window */
     ALLOC_NETBUFS       netbuf_allocator;   /* OS netbuf alloc fn */
     A_NETBUF_QUEUE_T    freeQ;              /* pre-allocated buffers - for A_MSDU slicing */
-    RXTID_STATS         stat[NUM_OF_TIDS];  /* Tid based statistics */
+    struct rxtid_stats         stat[NUM_OF_TIDS];  /* Tid based statistics */
     PACKET_LOG          pkt_log;            /* Log info of the packets */
-}AGGR_INFO;
+};
 
 #endif /* __AGGR_RX_INTERNAL_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/reorder/rcv_aggr.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/reorder/rcv_aggr.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/reorder/rcv_aggr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/reorder/rcv_aggr.c	2011-05-19 00:06:34.000000000 -0400
@@ -33,36 +33,36 @@
 #include "aggr_rx_internal.h"
 #include "wmi.h"
 
-extern A_STATUS
+extern int
 wmi_dot3_2_dix(void *osbuf);
 
 static void
-aggr_slice_amsdu(AGGR_INFO *p_aggr, RXTID *rxtid, void **osbuf);
+aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf);
 
 static void
 aggr_timeout(A_ATH_TIMER arg);
 
 static void
-aggr_deque_frms(AGGR_INFO *p_aggr, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 order);
+aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order);
 
 static void
-aggr_dispatch_frames(AGGR_INFO *p_aggr, A_NETBUF_QUEUE_T *q);
+aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q);
 
 static void *
-aggr_get_osbuf(AGGR_INFO *p_aggr);
+aggr_get_osbuf(struct aggr_info *p_aggr);
 
 void *
 aggr_init(ALLOC_NETBUFS netbuf_allocator)
 {
-    AGGR_INFO   *p_aggr = NULL;
-    RXTID *rxtid;
-    A_UINT8 i;
-    A_STATUS status = A_OK;
+    struct aggr_info   *p_aggr = NULL;
+    struct rxtid *rxtid;
+    u8 i;
+    int status = 0;
 
     A_PRINTF("In aggr_init..\n");
 
     do {
-        p_aggr = A_MALLOC(sizeof(AGGR_INFO));
+        p_aggr = A_MALLOC(sizeof(struct aggr_info));
         if(!p_aggr) {
             A_PRINTF("Failed to allocate memory for aggr_node\n");
             status = A_ERROR;
@@ -70,10 +70,10 @@
         }
 
         /* Init timer and data structures */
-        A_MEMZERO(p_aggr, sizeof(AGGR_INFO));
+        A_MEMZERO(p_aggr, sizeof(struct aggr_info));
         p_aggr->aggr_sz = AGGR_SZ_DEFAULT;
         A_INIT_TIMER(&p_aggr->timer, aggr_timeout, p_aggr);
-        p_aggr->timerScheduled = FALSE;
+        p_aggr->timerScheduled = false;
         A_NETBUF_QUEUE_INIT(&p_aggr->freeQ);
 
         p_aggr->netbuf_allocator = netbuf_allocator;
@@ -81,30 +81,30 @@
 
         for(i = 0; i < NUM_OF_TIDS; i++) {
             rxtid = AGGR_GET_RXTID(p_aggr, i);
-            rxtid->aggr = FALSE;
-            rxtid->progress = FALSE;
-            rxtid->timerMon = FALSE;
+            rxtid->aggr = false;
+            rxtid->progress = false;
+            rxtid->timerMon = false;
             A_NETBUF_QUEUE_INIT(&rxtid->q);
             A_MUTEX_INIT(&rxtid->lock);
         }
-    }while(FALSE);
+    }while(false);
 
     A_PRINTF("going out of aggr_init..status %s\n",
-                    (status == A_OK) ? "OK":"Error");
+                    (status == 0) ? "OK":"Error");
 
-    if(status != A_OK) {
+    if (status) {
         /* Cleanup */
         aggr_module_destroy(p_aggr);
     }
-    return ((status == A_OK) ? p_aggr : NULL);
+    return ((status == 0) ? p_aggr : NULL);
 }
 
 /* utility function to clear rx hold_q for a tid */
 static void
-aggr_delete_tid_state(AGGR_INFO *p_aggr, A_UINT8 tid)
+aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
 {
-    RXTID *rxtid;
-    RXTID_STATS *stats;
+    struct rxtid *rxtid;
+    struct rxtid_stats *stats;
 
     A_ASSERT(tid < NUM_OF_TIDS && p_aggr);
 
@@ -115,9 +115,9 @@
         aggr_deque_frms(p_aggr, tid, 0, ALL_SEQNO);
     }
 
-    rxtid->aggr = FALSE;
-    rxtid->progress = FALSE;
-    rxtid->timerMon = FALSE;
+    rxtid->aggr = false;
+    rxtid->progress = false;
+    rxtid->timerMon = false;
     rxtid->win_sz = 0;
     rxtid->seq_next = 0;
     rxtid->hold_q_sz = 0;
@@ -127,22 +127,22 @@
         rxtid->hold_q = NULL;
     }
 
-    A_MEMZERO(stats, sizeof(RXTID_STATS));
+    A_MEMZERO(stats, sizeof(struct rxtid_stats));
 }
 
 void
 aggr_module_destroy(void *cntxt)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
-    A_UINT8 i, k;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
+    u8 i, k;
     A_PRINTF("%s(): aggr = %p\n",_A_FUNCNAME_, p_aggr);
     A_ASSERT(p_aggr);
 
     if(p_aggr) {
         if(p_aggr->timerScheduled) {
             A_UNTIMEOUT(&p_aggr->timer);
-            p_aggr->timerScheduled = FALSE;
+            p_aggr->timerScheduled = false;
         }
 
         for(i = 0; i < NUM_OF_TIDS; i++) {
@@ -177,7 +177,7 @@
 void
 aggr_register_rx_dispatcher(void *cntxt, void * dev, RX_CALLBACK fn)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
 
     A_ASSERT(p_aggr && fn && dev);
 
@@ -187,10 +187,10 @@
 
 
 void
-aggr_process_bar(void *cntxt, A_UINT8 tid, A_UINT16 seq_no)
+aggr_process_bar(void *cntxt, u8 tid, u16 seq_no)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID_STATS *stats;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid_stats *stats;
 
     A_ASSERT(p_aggr);
     stats = AGGR_GET_RXTID_STATS(p_aggr, tid);
@@ -201,11 +201,11 @@
 
 
 void
-aggr_recv_addba_req_evt(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 win_sz)
+aggr_recv_addba_req_evt(void *cntxt, u8 tid, u16 seq_no, u8 win_sz)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
-    RXTID_STATS *stats;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
+    struct rxtid_stats *stats;
 
     A_ASSERT(p_aggr);
     rxtid = AGGR_GET_RXTID(p_aggr, tid);
@@ -249,14 +249,14 @@
         A_ASSERT(0);
     }
 
-    rxtid->aggr = TRUE;
+    rxtid->aggr = true;
 }
 
 void
-aggr_recv_delba_req_evt(void *cntxt, A_UINT8 tid)
+aggr_recv_delba_req_evt(void *cntxt, u8 tid)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
 
     A_ASSERT(p_aggr);
     A_PRINTF("%s(): tid %d\n", _A_FUNCNAME_, tid);
@@ -269,12 +269,12 @@
 }
 
 static void
-aggr_deque_frms(AGGR_INFO *p_aggr, A_UINT8 tid, A_UINT16 seq_no, A_UINT8 order)
+aggr_deque_frms(struct aggr_info *p_aggr, u8 tid, u16 seq_no, u8 order)
 {
-    RXTID *rxtid;
-    OSBUF_HOLD_Q *node;
-    A_UINT16 idx, idx_end, seq_end;
-    RXTID_STATS *stats;
+    struct rxtid *rxtid;
+    struct osbuf_hold_q *node;
+    u16 idx, idx_end, seq_end;
+    struct rxtid_stats *stats;
 
     A_ASSERT(p_aggr);
     rxtid = AGGR_GET_RXTID(p_aggr, tid);
@@ -334,7 +334,7 @@
 }
 
 static void *
-aggr_get_osbuf(AGGR_INFO *p_aggr)
+aggr_get_osbuf(struct aggr_info *p_aggr)
 {
     void *buf = NULL;
 
@@ -356,11 +356,11 @@
 
 
 static void
-aggr_slice_amsdu(AGGR_INFO *p_aggr, RXTID *rxtid, void **osbuf)
+aggr_slice_amsdu(struct aggr_info *p_aggr, struct rxtid *rxtid, void **osbuf)
 {
     void *new_buf;
-    A_UINT16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
-    A_UINT8 *framep;
+    u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
+    u8 *framep;
 
     /* Frame format at this point:
      *  [DIX hdr | 802.3 | 802.3 | ... | 802.3]
@@ -397,9 +397,9 @@
             break;
         }
 
-        A_MEMCPY(A_NETBUF_DATA(new_buf), framep, frame_8023_len);
+        memcpy(A_NETBUF_DATA(new_buf), framep, frame_8023_len);
         A_NETBUF_PUT(new_buf, frame_8023_len);
-        if (wmi_dot3_2_dix(new_buf) != A_OK) {
+        if (wmi_dot3_2_dix(new_buf) != 0) {
             A_PRINTF("dot3_2_dix err..\n");
             A_NETBUF_FREE(new_buf);
             break;
@@ -426,14 +426,14 @@
 }
 
 void
-aggr_process_recv_frm(void *cntxt, A_UINT8 tid, A_UINT16 seq_no, A_BOOL is_amsdu, void **osbuf)
+aggr_process_recv_frm(void *cntxt, u8 tid, u16 seq_no, bool is_amsdu, void **osbuf)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID *rxtid;
-    RXTID_STATS *stats;
-    A_UINT16 idx, st, cur, end;
-    A_UINT16 *log_idx;
-    OSBUF_HOLD_Q *node;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid *rxtid;
+    struct rxtid_stats *stats;
+    u16 idx, st, cur, end;
+    u16 *log_idx;
+    struct osbuf_hold_q *node;
     PACKET_LOG *log;
 
     A_ASSERT(p_aggr);
@@ -472,7 +472,7 @@
          * be assumed that the window has moved for some valid reason.
          * Therefore, we dequeue all frames and start fresh.
          */
-        A_UINT16 extended_end;
+        u16 extended_end;
 
         extended_end = (end + rxtid->hold_q_sz-1) & IEEE80211_MAX_SEQ_NO;
 
@@ -536,17 +536,17 @@
     aggr_deque_frms(p_aggr, tid, 0, CONTIGUOUS_SEQNO);
 
     if(p_aggr->timerScheduled) {
-        rxtid->progress = TRUE;
+        rxtid->progress = true;
     }else{
         for(idx=0 ; idx<rxtid->hold_q_sz ; idx++) {
             if(rxtid->hold_q[idx].osbuf) {
                 /* there is a frame in the queue and no timer so
                  * start a timer to ensure that the frame doesn't remain
                  * stuck forever. */
-                p_aggr->timerScheduled = TRUE;
+                p_aggr->timerScheduled = true;
                 A_TIMEOUT_MS(&p_aggr->timer, AGGR_RX_TIMEOUT, 0);
-                rxtid->progress = FALSE;
-                rxtid->timerMon = TRUE;
+                rxtid->progress = false;
+                rxtid->timerMon = true;
                 break;
             }
         }
@@ -561,8 +561,8 @@
 void
 aggr_reset_state(void *cntxt)
 {
-    A_UINT8 tid;
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
+    u8 tid;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
 
     A_ASSERT(p_aggr);
 
@@ -575,10 +575,10 @@
 static void
 aggr_timeout(A_ATH_TIMER arg)
 {
-    A_UINT8 i,j;
-    AGGR_INFO *p_aggr = (AGGR_INFO *)arg;
-    RXTID   *rxtid;
-    RXTID_STATS *stats;
+    u8 i,j;
+    struct aggr_info *p_aggr = (struct aggr_info *)arg;
+    struct rxtid   *rxtid;
+    struct rxtid_stats *stats;
     /*
      * If the q for which the timer was originally started has
      * not progressed then it is necessary to dequeue all the
@@ -588,9 +588,9 @@
         rxtid = AGGR_GET_RXTID(p_aggr, i);
         stats = AGGR_GET_RXTID_STATS(p_aggr, i);
 
-        if(rxtid->aggr == FALSE ||
-           rxtid->timerMon == FALSE ||
-           rxtid->progress == TRUE) {
+        if(rxtid->aggr == false ||
+           rxtid->timerMon == false ||
+           rxtid->progress == true) {
             continue;
         }
         // dequeue all frames in for this tid
@@ -599,25 +599,25 @@
         aggr_deque_frms(p_aggr, i, 0, ALL_SEQNO);
     }
 
-    p_aggr->timerScheduled = FALSE;
+    p_aggr->timerScheduled = false;
     // determine whether a new timer should be started.
     for(i = 0; i < NUM_OF_TIDS; i++) {
         rxtid = AGGR_GET_RXTID(p_aggr, i);
 
-        if(rxtid->aggr == TRUE && rxtid->hold_q) {
+        if(rxtid->aggr == true && rxtid->hold_q) {
             for(j = 0 ; j < rxtid->hold_q_sz ; j++)
             {
                 if(rxtid->hold_q[j].osbuf)
                 {
-                    p_aggr->timerScheduled = TRUE;
-                    rxtid->timerMon = TRUE;
-                    rxtid->progress = FALSE;
+                    p_aggr->timerScheduled = true;
+                    rxtid->timerMon = true;
+                    rxtid->progress = false;
                     break;
                 }
             }
 
             if(j >= rxtid->hold_q_sz) {
-                rxtid->timerMon = FALSE;
+                rxtid->timerMon = false;
             }
         }
     }
@@ -630,7 +630,7 @@
 }
 
 static void
-aggr_dispatch_frames(AGGR_INFO *p_aggr, A_NETBUF_QUEUE_T *q)
+aggr_dispatch_frames(struct aggr_info *p_aggr, A_NETBUF_QUEUE_T *q)
 {
     void *osbuf;
 
@@ -642,10 +642,10 @@
 void
 aggr_dump_stats(void *cntxt, PACKET_LOG **log_buf)
 {
-    AGGR_INFO *p_aggr = (AGGR_INFO *)cntxt;
-    RXTID   *rxtid;
-    RXTID_STATS *stats;
-    A_UINT8 i;
+    struct aggr_info *p_aggr = (struct aggr_info *)cntxt;
+    struct rxtid   *rxtid;
+    struct rxtid_stats *stats;
+    u8 i;
 
     *log_buf = &p_aggr->pkt_log;
     A_PRINTF("\n\n================================================\n");
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/TODO linux-libre-2.6.39-gnu/drivers/staging/ath6kl/TODO
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/TODO	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/TODO	2011-05-19 00:06:34.000000000 -0400
@@ -1,8 +1,25 @@
-- The driver is a stop-gap measure until a proper mac80211 driver is available.
-- The driver does not conform to the Linux coding style.
-- The driver has been tested on a wide variety of embedded platforms running different versions of the Linux kernel but may still have bringup/performance issues with a new platform.
-- Pls use the following link to get information about the driver's architecture, exposed APIs, supported features, limitations, testing, hardware availability and other details.
-	http://wireless.kernel.org/en/users/Drivers/ath6kl
-- Pls send any patches to
+TODO:
+
+We are working hard on cleaning up the driver. There's sooooooooo much todo
+so instead of editign this file please use the wiki:
+
+http://wireless.kernel.org/en/users/Drivers/ath6kl
+
+There's a respective TODO page there. Please also subscribe to the wiki page
+to get e-mail updates on changes.
+
+IRC:
+
+We *really* need to coordinate development for ath6kl as the cleanup
+patches will break pretty much any other patches. Please use IRC to
+help coordinate better:
+
+irc.freenode.net
+#ath6kl
+
+Send patches to:
+
 	- Greg Kroah-Hartman <greg@kroah.com>
-	- Vipin Mehta <vmehta@atheros.com>
+	- Luis R. Rodriguez <mcgrof@gmail.com>
+	- Joe Perches <joe@perches.com>
+	- Naveen Singh <nsingh@atheros.com>
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/include/ieee80211.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/include/ieee80211.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/include/ieee80211.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/include/ieee80211.h	2011-05-19 00:06:34.000000000 -0400
@@ -68,9 +68,9 @@
 
 
 #define IEEE80211_ADDR_EQ(addr1, addr2)     \
-    (A_MEMCMP(addr1, addr2, IEEE80211_ADDR_LEN) == 0)
+    (memcmp(addr1, addr2, IEEE80211_ADDR_LEN) == 0)
 
-#define IEEE80211_ADDR_COPY(dst,src)    A_MEMCPY(dst,src,IEEE80211_ADDR_LEN)
+#define IEEE80211_ADDR_COPY(dst,src)    memcpy(dst,src,IEEE80211_ADDR_LEN)
 
 #define IEEE80211_KEYBUF_SIZE 16
 #define IEEE80211_MICBUF_SIZE (8+8)  /* space for both tx and rx */
@@ -99,24 +99,24 @@
  * generic definitions for IEEE 802.11 frames
  */
 PREPACK struct ieee80211_frame {
-    A_UINT8    i_fc[2];
-    A_UINT8    i_dur[2];
-    A_UINT8    i_addr1[IEEE80211_ADDR_LEN];
-    A_UINT8    i_addr2[IEEE80211_ADDR_LEN];
-    A_UINT8    i_addr3[IEEE80211_ADDR_LEN];
-    A_UINT8    i_seq[2];
+    u8 i_fc[2];
+    u8 i_dur[2];
+    u8 i_addr1[IEEE80211_ADDR_LEN];
+    u8 i_addr2[IEEE80211_ADDR_LEN];
+    u8 i_addr3[IEEE80211_ADDR_LEN];
+    u8 i_seq[2];
     /* possibly followed by addr4[IEEE80211_ADDR_LEN]; */
     /* see below */
 } POSTPACK;
 
 PREPACK struct ieee80211_qosframe {
-    A_UINT8 i_fc[2];
-    A_UINT8 i_dur[2];
-    A_UINT8 i_addr1[IEEE80211_ADDR_LEN];
-    A_UINT8 i_addr2[IEEE80211_ADDR_LEN];
-    A_UINT8 i_addr3[IEEE80211_ADDR_LEN];
-    A_UINT8 i_seq[2];
-    A_UINT8 i_qos[2];
+    u8 i_fc[2];
+    u8 i_dur[2];
+    u8 i_addr1[IEEE80211_ADDR_LEN];
+    u8 i_addr2[IEEE80211_ADDR_LEN];
+    u8 i_addr3[IEEE80211_ADDR_LEN];
+    u8 i_seq[2];
+    u8 i_qos[2];
 } POSTPACK;
 
 #define IEEE80211_FC0_VERSION_MASK          0x03
@@ -320,29 +320,29 @@
  * WMM/802.11e Tspec Element
  */
 typedef PREPACK struct wmm_tspec_ie_t {
-    A_UINT8     elementId;
-    A_UINT8     len;
-    A_UINT8     oui[3];
-    A_UINT8     ouiType;
-    A_UINT8     ouiSubType;
-    A_UINT8     version;
-    A_UINT16    tsInfo_info;
-    A_UINT8     tsInfo_reserved;
-    A_UINT16    nominalMSDU;
-    A_UINT16    maxMSDU;
-    A_UINT32    minServiceInt;
-    A_UINT32    maxServiceInt;
-    A_UINT32    inactivityInt;
-    A_UINT32    suspensionInt;
-    A_UINT32    serviceStartTime;
-    A_UINT32    minDataRate;
-    A_UINT32    meanDataRate;
-    A_UINT32    peakDataRate;
-    A_UINT32    maxBurstSize;
-    A_UINT32    delayBound;
-    A_UINT32    minPhyRate;
-    A_UINT16    sba;
-    A_UINT16    mediumTime;
+    u8 elementId;
+    u8 len;
+    u8 oui[3];
+    u8 ouiType;
+    u8 ouiSubType;
+    u8 version;
+    u16 tsInfo_info;
+    u8 tsInfo_reserved;
+    u16 nominalMSDU;
+    u16 maxMSDU;
+    u32 minServiceInt;
+    u32 maxServiceInt;
+    u32 inactivityInt;
+    u32 suspensionInt;
+    u32 serviceStartTime;
+    u32 minDataRate;
+    u32 meanDataRate;
+    u32 peakDataRate;
+    u32 maxBurstSize;
+    u32 delayBound;
+    u32 minPhyRate;
+    u16 sba;
+    u16 mediumTime;
 } POSTPACK WMM_TSPEC_IE;
 
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/include/ieee80211_node.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/include/ieee80211_node.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/include/ieee80211_node.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/include/ieee80211_node.h	2011-05-19 00:06:34.000000000 -0400
@@ -55,7 +55,7 @@
 #define IEEE80211_NODE_HASHSIZE 32
 /* simple hash is enough for variation of macaddr */
 #define IEEE80211_NODE_HASH(addr)   \
-    (((const A_UINT8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \
+    (((const u8 *)(addr))[IEEE80211_ADDR_LEN - 1] % \
         IEEE80211_NODE_HASHSIZE)
 
 /*
@@ -71,14 +71,14 @@
     struct bss              *nt_node_last;  /* information of all nodes */
     struct bss              *nt_hash[IEEE80211_NODE_HASHSIZE];
     const char              *nt_name;   /* for debugging */
-    A_UINT32                nt_scangen; /* gen# for timeout scan */
+    u32 nt_scangen; /* gen# for timeout scan */
 #ifdef THREAD_X
     A_TIMER                 nt_inact_timer;
-    A_UINT8                 isTimerArmed;   /* is the node timer armed */
+    u8 isTimerArmed;   /* is the node timer armed */
 #endif
-    A_UINT32                nt_nodeAge; /* node aging time */
+    u32 nt_nodeAge; /* node aging time */
 #ifdef OS_ROAM_MANAGEMENT
-    A_UINT32                nt_si_gen; /* gen# for scan indication*/
+    u32 nt_si_gen; /* gen# for scan indication*/
 #endif
 };
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/src/wlan_node.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/src/wlan_node.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/src/wlan_node.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/src/wlan_node.c	2011-05-19 00:06:34.000000000 -0400
@@ -40,7 +40,7 @@
 
 #ifdef ATH_DEBUG_MODULE
 
-static ATH_DEBUG_MASK_DESCRIPTION wlan_debug_desc[] = {
+static struct ath_debug_mask_description wlan_debug_desc[] = {
     { ATH_DEBUG_WLAN , "General WLAN Node Tracing"},
 };
 
@@ -58,7 +58,7 @@
 #endif
 
 static bss_t * _ieee80211_find_node (struct ieee80211_node_table *nt,
-                                     const A_UINT8 *macaddr);
+                                     const u8 *macaddr);
 
 bss_t *
 wlan_node_alloc(struct ieee80211_node_table *nt, int wh_size)
@@ -111,18 +111,18 @@
 
 void
 wlan_setup_node(struct ieee80211_node_table *nt, bss_t *ni,
-                const A_UINT8 *macaddr)
+                const u8 *macaddr)
 {
     int hash;
-    A_UINT32 timeoutValue = 0;
+    u32 timeoutValue = 0;
 
-    A_MEMCPY(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
+    memcpy(ni->ni_macaddr, macaddr, IEEE80211_ADDR_LEN);
     hash = IEEE80211_NODE_HASH (macaddr);
     ieee80211_node_initref (ni);     /* mark referenced */
 
     timeoutValue = nt->nt_nodeAge;
 
-    ni->ni_tstamp = A_GET_MS (timeoutValue);
+    ni->ni_tstamp = A_GET_MS (0);
     ni->ni_actcnt = WLAN_NODE_INACT_CNT;
 
     IEEE80211_NODE_LOCK_BH(nt);
@@ -151,7 +151,7 @@
 #ifdef THREAD_X
     if (!nt->isTimerArmed) {
         A_TIMEOUT_MS(&nt->nt_inact_timer, timeoutValue, 0);
-        nt->isTimerArmed = TRUE;
+        nt->isTimerArmed = true;
     }
 #endif
 
@@ -160,7 +160,7 @@
 
 static bss_t *
 _ieee80211_find_node(struct ieee80211_node_table *nt,
-    const A_UINT8 *macaddr)
+    const u8 *macaddr)
 {
     bss_t *ni;
     int hash;
@@ -178,7 +178,7 @@
 }
 
 bss_t *
-wlan_find_node(struct ieee80211_node_table *nt, const A_UINT8 *macaddr)
+wlan_find_node(struct ieee80211_node_table *nt, const u8 *macaddr)
 {
     bss_t *ni;
 
@@ -262,7 +262,7 @@
                    void *arg)
 {
     bss_t *ni;
-    A_UINT32 gen;
+    u32 gen;
 
     gen = ++nt->nt_scangen;
 
@@ -299,7 +299,7 @@
 
 #ifdef THREAD_X
     A_INIT_TIMER(&nt->nt_inact_timer, wlan_node_timeout, nt);
-    nt->isTimerArmed = FALSE;
+    nt->isTimerArmed = false;
 #endif
     nt->nt_wmip = wmip;
     nt->nt_nodeAge = WLAN_NODE_INACT_TIMEOUT_MSEC;
@@ -316,7 +316,7 @@
 }
 
 void
-wlan_set_nodeage(struct ieee80211_node_table *nt, A_UINT32 nodeAge)
+wlan_set_nodeage(struct ieee80211_node_table *nt, u32 nodeAge)
 {
     nt->nt_nodeAge = nodeAge;
     return;
@@ -326,7 +326,7 @@
 {
 #ifdef THREAD_X
     bss_t *bss, *nextBss;
-    A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
+    u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false;
 
     wmi_get_current_bssid(nt->nt_wmip, myBssid);
 
@@ -334,7 +334,7 @@
     while (bss != NULL)
     {
         nextBss = bss->ni_list_next;
-        if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
+        if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
         {
                /*
                 * free up all but the current bss - if set
@@ -346,9 +346,9 @@
     }
 #else
     bss_t *bss, *nextBss;
-    A_UINT8 myBssid[IEEE80211_ADDR_LEN];
-    A_UINT32 timeoutValue = 0;
-    A_UINT32 now = A_GET_MS(0);
+    u8 myBssid[IEEE80211_ADDR_LEN];
+    u32 timeoutValue = 0;
+    u32 now = A_GET_MS(0);
     timeoutValue = nt->nt_nodeAge;
 
     wmi_get_current_bssid(nt->nt_wmip, myBssid);
@@ -357,10 +357,10 @@
     while (bss != NULL)
     {
         nextBss = bss->ni_list_next;
-        if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
+        if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
         {
 
-            if (bss->ni_tstamp <= now || --bss->ni_actcnt == 0)
+            if (((now - bss->ni_tstamp) > timeoutValue)  || --bss->ni_actcnt == 0)
             {
                /*
                 * free up all but the current bss - if set
@@ -379,8 +379,9 @@
 {
     struct ieee80211_node_table *nt = (struct ieee80211_node_table *)arg;
     bss_t *bss, *nextBss;
-    A_UINT8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = FALSE;
-    A_UINT32 timeoutValue = 0;
+    u8 myBssid[IEEE80211_ADDR_LEN], reArmTimer = false;
+    u32 timeoutValue = 0;
+    u32 now = A_GET_MS(0);
 
     timeoutValue = nt->nt_nodeAge;
 
@@ -390,10 +391,10 @@
     while (bss != NULL)
     {
         nextBss = bss->ni_list_next;
-        if (A_MEMCMP(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
+        if (memcmp(myBssid, bss->ni_macaddr, sizeof(myBssid)) != 0)
         {
 
-            if (bss->ni_tstamp <= A_GET_MS(0))
+            if ((now - bss->ni_tstamp) > timeoutValue)
             {
                /*
                 * free up all but the current bss - if set
@@ -406,7 +407,7 @@
                  * Re-arm timer, only when we have a bss other than
                  * current bss AND it is not aged-out.
                  */
-                reArmTimer = TRUE;
+                reArmTimer = true;
             }
         }
         bss = nextBss;
@@ -431,11 +432,11 @@
 }
 
 bss_t *
-wlan_find_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID)
+wlan_find_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
 {
     bss_t   *ni = NULL;
-    A_UCHAR *pIESsid = NULL;
+    u8 *pIESsid = NULL;
 
     IEEE80211_NODE_LOCK (nt);
 
@@ -447,22 +448,22 @@
             if (0x00 == memcmp (pSsid, &pIESsid[2], ssidLength)) {
 
                 //
-                // Step 2.1 : Check MatchSSID is TRUE, if so, return Matched SSID
+                // Step 2.1 : Check MatchSSID is true, if so, return Matched SSID
                 // Profile, otherwise check whether WPA2 or WPA
                 //
-                if (TRUE == bMatchSSID) {
+                if (true == bMatchSSID) {
                     ieee80211_node_incref (ni);  /* mark referenced */
                     IEEE80211_NODE_UNLOCK (nt);
                     return ni;
                 }
 
                 // Step 2 : if SSID matches, check WPA or WPA2
-                if (TRUE == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
+                if (true == bIsWPA2 && NULL != ni->ni_cie.ie_rsn) {
                     ieee80211_node_incref (ni);  /* mark referenced */
                     IEEE80211_NODE_UNLOCK (nt);
                     return ni;
                 }
-                if (FALSE == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
+                if (false == bIsWPA2 && NULL != ni->ni_cie.ie_wpa) {
                     ieee80211_node_incref(ni);  /* mark referenced */
                     IEEE80211_NODE_UNLOCK (nt);
                     return ni;
@@ -526,7 +527,7 @@
 }
 
 bss_t *
-wlan_node_remove(struct ieee80211_node_table *nt, A_UINT8 *bssid)
+wlan_node_remove(struct ieee80211_node_table *nt, u8 *bssid)
 {
     bss_t *bss, *nextBss;
 
@@ -538,7 +539,7 @@
     {
         nextBss = bss->ni_list_next;
 
-        if (A_MEMCMP(bssid, bss->ni_macaddr, 6) == 0)
+        if (memcmp(bssid, bss->ni_macaddr, 6) == 0)
         {
             wlan_node_remove_core (nt, bss);
             IEEE80211_NODE_UNLOCK(nt);
@@ -553,13 +554,13 @@
 }
 
 bss_t *
-wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, A_UCHAR *pSsid,
-                    A_UINT32 ssidLength, A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp)
+wlan_find_matching_Ssidnode (struct ieee80211_node_table *nt, u8 *pSsid,
+                    u32 ssidLength, u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
 {
     bss_t   *ni = NULL;
     bss_t   *best_ni = NULL;
-    A_UCHAR *pIESsid = NULL;
+    u8 *pIESsid = NULL;
 
     IEEE80211_NODE_LOCK (nt);
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/src/wlan_recv_beacon.c	2011-05-19 00:06:34.000000000 -0400
@@ -49,23 +49,23 @@
 
 /* unaligned little endian access */
 #define LE_READ_2(p)                            \
-    ((A_UINT16)                            \
-     ((((A_UINT8 *)(p))[0]      ) | (((A_UINT8 *)(p))[1] <<  8)))
+    ((u16)                            \
+     ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8)))
 
 #define LE_READ_4(p)                            \
-    ((A_UINT32)                            \
-     ((((A_UINT8 *)(p))[0]      ) | (((A_UINT8 *)(p))[1] <<  8) | \
-      (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
+    ((u32)                            \
+     ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8) | \
+      (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
 
 
 static int __inline
-iswpaoui(const A_UINT8 *frm)
+iswpaoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((WPA_OUI_TYPE<<24)|WPA_OUI);
 }
 
 static int __inline
-iswmmoui(const A_UINT8 *frm)
+iswmmoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
 }
@@ -73,38 +73,38 @@
 /* unused functions for now */
 #if 0
 static int __inline
-iswmmparam(const A_UINT8 *frm)
+iswmmparam(const u8 *frm)
 {
     return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
 }
 
 static int __inline
-iswmminfo(const A_UINT8 *frm)
+iswmminfo(const u8 *frm)
 {
     return frm[1] > 5 && frm[6] == WMM_INFO_OUI_SUBTYPE;
 }
 #endif
 
 static int __inline
-isatherosoui(const A_UINT8 *frm)
+isatherosoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((ATH_OUI_TYPE<<24)|ATH_OUI);
 }
 
 static int __inline
-iswscoui(const A_UINT8 *frm)
+iswscoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((0x04<<24)|WPA_OUI);
 }
 
-A_STATUS
-wlan_parse_beacon(A_UINT8 *buf, int framelen, struct ieee80211_common_ie *cie)
+int
+wlan_parse_beacon(u8 *buf, int framelen, struct ieee80211_common_ie *cie)
 {
-    A_UINT8 *frm, *efrm;
-    A_UINT8 elemid_ssid = FALSE;
+    u8 *frm, *efrm;
+    u8 elemid_ssid = false;
 
     frm = buf;
-    efrm = (A_UINT8 *) (frm + framelen);
+    efrm = (u8 *) (frm + framelen);
 
     /*
      * beacon/probe response frame format
@@ -125,8 +125,8 @@
     A_MEMZERO(cie, sizeof(*cie));
 
     cie->ie_tstamp = frm; frm += 8;
-    cie->ie_beaconInt = A_LE2CPU16(*(A_UINT16 *)frm);  frm += 2;
-    cie->ie_capInfo = A_LE2CPU16(*(A_UINT16 *)frm);  frm += 2;
+    cie->ie_beaconInt = A_LE2CPU16(*(u16 *)frm);  frm += 2;
+    cie->ie_capInfo = A_LE2CPU16(*(u16 *)frm);  frm += 2;
     cie->ie_chan = 0;
 
     while (frm < efrm) {
@@ -134,7 +134,7 @@
         case IEEE80211_ELEMID_SSID:
             if (!elemid_ssid) {
                 cie->ie_ssid = frm;
-                elemid_ssid = TRUE;
+                elemid_ssid = true;
             }
             break;
         case IEEE80211_ELEMID_RATES:
@@ -196,5 +196,5 @@
     IEEE80211_VERIFY_ELEMENT(cie->ie_rates, IEEE80211_RATE_MAXSIZE);
     IEEE80211_VERIFY_ELEMENT(cie->ie_ssid, IEEE80211_NWID_LEN);
 
-    return A_OK;
+    return 0;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/src/wlan_utils.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/src/wlan_utils.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wlan/src/wlan_utils.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wlan/src/wlan_utils.c	2011-05-19 00:06:34.000000000 -0400
@@ -30,8 +30,7 @@
 /*
  * converts ieee channel number to frequency
  */
-A_UINT16
-wlan_ieee2freq(int chan)
+u16 wlan_ieee2freq(int chan)
 {
     if (chan == 14) {
         return 2484;
@@ -48,8 +47,7 @@
 /*
  * Converts MHz frequency to IEEE channel number.
  */
-A_UINT32
-wlan_freq2ieee(A_UINT16 freq)
+u32 wlan_freq2ieee(u16 freq)
 {
     if (freq == 2484)
         return 14;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wmi/wmi.c linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wmi/wmi.c
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wmi/wmi.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wmi/wmi.c	2011-05-19 00:06:34.000000000 -0400
@@ -48,7 +48,7 @@
 
 #ifdef ATH_DEBUG_MODULE
 
-static ATH_DEBUG_MASK_DESCRIPTION wmi_debug_desc[] = {
+static struct ath_debug_mask_description wmi_debug_desc[] = {
     { ATH_DEBUG_WMI , "General WMI Tracing"},
 };
 
@@ -70,134 +70,134 @@
 #define A_DPRINTF   AR_DEBUG_PRINTF
 #endif
 
-static A_STATUS wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap,
                                         int len);
 
-static A_STATUS wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap,
                                         int len);
-static A_STATUS wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap,
                                        int len);
-static A_STATUS wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_sync_point(struct wmi_t *wmip);
+static int wmi_sync_point(struct wmi_t *wmip);
 
-static A_STATUS wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap,
                                          int len);
-static A_STATUS wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap,
                                        int len);
-static A_STATUS wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap,
                                              int len);
 
-static A_STATUS wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 #ifdef CONFIG_HOST_DSET_SUPPORT
-static A_STATUS wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 #endif /* CONFIG_HOST_DSET_SUPPORT */
 
 
-static A_STATUS wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_channel_change_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap,
                                       int len);
-static A_STATUS wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap,
                                       int len);
-static A_STATUS wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap,
                                       int len);
-static A_STATUS
-wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
+static int
+wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
 
-static A_STATUS
-wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
+static int
+wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
 
-static A_STATUS
-wmi_acm_reject_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len);
+static int
+wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len);
 
 #ifdef CONFIG_HOST_GPIO_SUPPORT
-static A_STATUS wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-static A_STATUS
-wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif
 
-static A_STATUS
-wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS
-wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS
-wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_BOOL
-wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_INT32 rateIndex);
+static bool
+wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex);
 
-static A_STATUS
-wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS
-wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-static A_STATUS wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len);
 
-A_STATUS wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
+int wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
                   WMI_SYNC_FLAG syncflag);
 
-A_UINT8 ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, A_UINT32 size);
-A_UINT8 ar6000_get_lower_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, A_UINT32 size);
+u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
+u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh, u32 size);
 
 void wmi_cache_configure_rssithreshold(struct wmi_t *wmip, WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
 void wmi_cache_configure_snrthreshold(struct wmi_t *wmip, WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
-static A_STATUS wmi_send_rssi_threshold_params(struct wmi_t *wmip,
+static int wmi_send_rssi_threshold_params(struct wmi_t *wmip,
                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd);
-static A_STATUS wmi_send_snr_threshold_params(struct wmi_t *wmip,
+static int wmi_send_snr_threshold_params(struct wmi_t *wmip,
                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd);
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-static A_STATUS
-wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int
+wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 
-static A_STATUS wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
-static A_STATUS wmi_dtimexpiry_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 
-static A_STATUS wmi_peer_node_event_rx (struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_peer_node_event_rx (struct wmi_t *wmip, u8 *datap,
                                         int len);
 #ifdef ATH_AR6K_11N_SUPPORT
-static A_STATUS wmi_addba_req_event_rx(struct wmi_t *, A_UINT8 *, int);
-static A_STATUS wmi_addba_resp_event_rx(struct wmi_t *, A_UINT8 *, int);
-static A_STATUS wmi_delba_req_event_rx(struct wmi_t *, A_UINT8 *, int);
-static A_STATUS wmi_btcoex_config_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
-static A_STATUS wmi_btcoex_stats_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len);
+static int wmi_addba_req_event_rx(struct wmi_t *, u8 *, int);
+static int wmi_addba_resp_event_rx(struct wmi_t *, u8 *, int);
+static int wmi_delba_req_event_rx(struct wmi_t *, u8 *, int);
+static int wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len);
+static int wmi_btcoex_stats_event_rx(struct wmi_t *wmip, u8 *datap, int len);
 #endif
-static A_STATUS wmi_hci_event_rx(struct wmi_t *, A_UINT8 *, int);
+static int wmi_hci_event_rx(struct wmi_t *, u8 *, int);
 
 #ifdef WAPI_ENABLE
-static A_STATUS wmi_wapi_rekey_event_rx(struct wmi_t *wmip, A_UINT8 *datap,
+static int wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,
                                      int len);
 #endif
 
@@ -212,7 +212,7 @@
 #endif
 
 int wps_enable;
-static const A_INT32 wmi_rateTable[][2] = {
+static const s32 wmi_rateTable[][2] = {
   //{W/O SGI, with SGI}
     {1000, 1000},
     {2000, 2000},
@@ -244,25 +244,25 @@
     {135000, 150000},
     {0, 0}};
 
-#define MODE_A_SUPPORT_RATE_START       ((A_INT32) 4)
-#define MODE_A_SUPPORT_RATE_STOP        ((A_INT32) 11)
+#define MODE_A_SUPPORT_RATE_START       ((s32) 4)
+#define MODE_A_SUPPORT_RATE_STOP        ((s32) 11)
 
 #define MODE_GONLY_SUPPORT_RATE_START   MODE_A_SUPPORT_RATE_START
 #define MODE_GONLY_SUPPORT_RATE_STOP    MODE_A_SUPPORT_RATE_STOP
 
-#define MODE_B_SUPPORT_RATE_START       ((A_INT32) 0)
-#define MODE_B_SUPPORT_RATE_STOP        ((A_INT32) 3)
+#define MODE_B_SUPPORT_RATE_START       ((s32) 0)
+#define MODE_B_SUPPORT_RATE_STOP        ((s32) 3)
 
-#define MODE_G_SUPPORT_RATE_START       ((A_INT32) 0)
-#define MODE_G_SUPPORT_RATE_STOP        ((A_INT32) 11)
+#define MODE_G_SUPPORT_RATE_START       ((s32) 0)
+#define MODE_G_SUPPORT_RATE_STOP        ((s32) 11)
 
-#define MODE_GHT20_SUPPORT_RATE_START   ((A_INT32) 0)
-#define MODE_GHT20_SUPPORT_RATE_STOP    ((A_INT32) 19)
+#define MODE_GHT20_SUPPORT_RATE_START   ((s32) 0)
+#define MODE_GHT20_SUPPORT_RATE_STOP    ((s32) 19)
 
 #define MAX_NUMBER_OF_SUPPORT_RATES     (MODE_GHT20_SUPPORT_RATE_STOP + 1)
 
 /* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
-const A_UINT8 up_to_ac[]= {
+const u8 up_to_ac[]= {
                 WMM_AC_BE,
                 WMM_AC_BK,
                 WMM_AC_BK,
@@ -277,27 +277,27 @@
 
 /* This stuff is used when we want a simple layer-3 visibility */
 typedef PREPACK struct _iphdr {
-    A_UINT8     ip_ver_hdrlen;          /* version and hdr length */
-    A_UINT8     ip_tos;                 /* type of service */
-    A_UINT16    ip_len;                 /* total length */
-    A_UINT16    ip_id;                  /* identification */
-    A_INT16     ip_off;                 /* fragment offset field */
+    u8 ip_ver_hdrlen;          /* version and hdr length */
+    u8 ip_tos;                 /* type of service */
+    u16 ip_len;                 /* total length */
+    u16 ip_id;                  /* identification */
+    s16 ip_off;                 /* fragment offset field */
 #define IP_DF 0x4000                    /* dont fragment flag */
 #define IP_MF 0x2000                    /* more fragments flag */
 #define IP_OFFMASK 0x1fff               /* mask for fragmenting bits */
-    A_UINT8     ip_ttl;                 /* time to live */
-    A_UINT8     ip_p;                   /* protocol */
-    A_UINT16    ip_sum;                 /* checksum */
-    A_UINT8     ip_src[4];              /* source and dest address */
-    A_UINT8     ip_dst[4];
+    u8 ip_ttl;                 /* time to live */
+    u8 ip_p;                   /* protocol */
+    u16 ip_sum;                 /* checksum */
+    u8 ip_src[4];              /* source and dest address */
+    u8 ip_dst[4];
 } POSTPACK iphdr;
 
 #include "athendpack.h"
 
-static A_INT16 rssi_event_value = 0;
-static A_INT16 snr_event_value = 0;
+static s16 rssi_event_value = 0;
+static s16 snr_event_value = 0;
 
-A_BOOL is_probe_ssid = FALSE;
+bool is_probe_ssid = false;
 
 void *
 wmi_init(void *devt)
@@ -335,7 +335,7 @@
 void
 wmi_qos_state_init(struct wmi_t *wmip)
 {
-    A_UINT8 i;
+    u8 i;
 
     if (wmip == NULL) {
         return;
@@ -391,11 +391,11 @@
  *  Assumes the entire DIX header is contigous and that there is
  *  enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
  */
-A_STATUS
+int
 wmi_dix_2_dot3(struct wmi_t *wmip, void *osbuf)
 {
-    A_UINT8          *datap;
-    A_UINT16         typeorlen;
+    u8 *datap;
+    u16 typeorlen;
     ATH_MAC_HDR      macHdr;
     ATH_LLC_SNAP_HDR *llcHdr;
 
@@ -409,33 +409,33 @@
 
     datap = A_NETBUF_DATA(osbuf);
 
-    typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
+    typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
 
     if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
         /*
          * packet is already in 802.3 format - return success
          */
         A_DPRINTF(DBG_WMI, (DBGFMT "packet already 802.3\n", DBGARG));
-        return (A_OK);
+        return (0);
     }
 
     /*
      * Save mac fields and length to be inserted later
      */
-    A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);
-    A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
+    memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
+    memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
     macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
                                   sizeof(ATH_LLC_SNAP_HDR));
 
     /*
      * Make room for LLC+SNAP headers
      */
-    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
         return A_NO_MEMORY;
     }
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
+    memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
 
     llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
     llcHdr->dsap      = 0xAA;
@@ -446,19 +446,19 @@
     llcHdr->orgCode[2] = 0x0;
     llcHdr->etherType = typeorlen;
 
-    return (A_OK);
+    return (0);
 }
 
-A_STATUS wmi_meta_add(struct wmi_t *wmip, void *osbuf, A_UINT8 *pVersion,void *pTxMetaS)
+int wmi_meta_add(struct wmi_t *wmip, void *osbuf, u8 *pVersion,void *pTxMetaS)
 {
     switch(*pVersion){
 	case 0:
-    		return (A_OK);
+		return (0);
     	case WMI_META_VERSION_1:
 	        {
         	WMI_TX_META_V1     *pV1= NULL;
         	A_ASSERT(osbuf != NULL);
-        	if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != A_OK) {
+		if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
             		return A_NO_MEMORY;
         	}
 
@@ -473,44 +473,44 @@
         	A_ASSERT(pVersion != NULL);
         	/* the version must be used to populate the meta field of the WMI_DATA_HDR */
         	*pVersion = WMI_META_VERSION_1;
-        	return (A_OK);
+		return (0);
     		}
 #ifdef CONFIG_CHECKSUM_OFFLOAD
 	case WMI_META_VERSION_2:
 		{
      		WMI_TX_META_V2 *pV2 ;
         	A_ASSERT(osbuf != NULL);
-        	if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != A_OK) {
+		if (A_NETBUF_PUSH(osbuf, WMI_MAX_TX_META_SZ) != 0) {
             		return A_NO_MEMORY;
         	}
          	pV2 = (WMI_TX_META_V2 *)A_NETBUF_DATA(osbuf);
-         	A_MEMCPY(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
-         	return (A_OK);
+         	memcpy(pV2,(WMI_TX_META_V2 *)pTxMetaS,sizeof(WMI_TX_META_V2));
+		return (0);
     		}
 #endif
 	default:
-		return (A_OK);
+		return (0);
     }
 }
 
 /* Adds a WMI data header */
-A_STATUS
-wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, A_UINT8 msgType, A_BOOL bMoreData,
-                    WMI_DATA_HDR_DATA_TYPE data_type,A_UINT8 metaVersion, void *pTxMetaS)
+int
+wmi_data_hdr_add(struct wmi_t *wmip, void *osbuf, u8 msgType, bool bMoreData,
+                    WMI_DATA_HDR_DATA_TYPE data_type,u8 metaVersion, void *pTxMetaS)
 {
     WMI_DATA_HDR     *dtHdr;
-//    A_UINT8 metaVersion = 0;
-    A_STATUS status;
+//    u8 metaVersion = 0;
+    int status;
 
     A_ASSERT(osbuf != NULL);
 
     /* adds the meta data field after the wmi data hdr. If metaVersion
      * is returns 0 then no meta field was added. */
-    if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != A_OK) {
+    if ((status = wmi_meta_add(wmip, osbuf, &metaVersion,pTxMetaS)) != 0) {
         return status;
     }
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
         return A_NO_MEMORY;
     }
 
@@ -527,19 +527,19 @@
     WMI_DATA_HDR_SET_META(dtHdr, metaVersion);
     //dtHdr->rssi = 0;
 
-    return (A_OK);
+    return (0);
 }
 
 
-A_UINT8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, A_UINT32 layer2Priority, A_BOOL wmmEnabled)
+u8 wmi_implicit_create_pstream(struct wmi_t *wmip, void *osbuf, u32 layer2Priority, bool wmmEnabled)
 {
-    A_UINT8         *datap;
-    A_UINT8         trafficClass = WMM_AC_BE;
-    A_UINT16        ipType = IP_ETHERTYPE;
+    u8 *datap;
+    u8 trafficClass = WMM_AC_BE;
+    u16 ipType = IP_ETHERTYPE;
     WMI_DATA_HDR    *dtHdr;
-    A_BOOL           streamExists = FALSE;
-    A_UINT8        userPriority;
-    A_UINT32            hdrsize, metasize;
+    u8 streamExists = 0;
+    u8 userPriority;
+    u32 hdrsize, metasize;
     ATH_LLC_SNAP_HDR    *llcHdr;
 
     WMI_CREATE_PSTREAM_CMD  cmd;
@@ -564,7 +564,7 @@
     {
         if (processDot11Hdr)
         {
-             hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32));
+             hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
              llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(WMI_DATA_HDR) + metasize +
                           hdrsize);
 
@@ -580,7 +580,7 @@
         {
             /* Extract the endpoint info from the TOS field in the IP header */
 
-            userPriority = wmi_determine_userPriority (((A_UINT8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
+            userPriority = wmi_determine_userPriority (((u8 *)llcHdr) + sizeof(ATH_LLC_SNAP_HDR),layer2Priority);
         }
         else
         {
@@ -621,15 +621,15 @@
     return trafficClass;
 }
 
-A_STATUS
+int
 wmi_dot11_hdr_add (struct wmi_t *wmip, void *osbuf, NETWORK_TYPE mode)
 {
-    A_UINT8          *datap;
-    A_UINT16         typeorlen;
+    u8 *datap;
+    u16 typeorlen;
     ATH_MAC_HDR      macHdr;
     ATH_LLC_SNAP_HDR *llcHdr;
     struct           ieee80211_frame *wh;
-    A_UINT32         hdrsize;
+    u32 hdrsize;
 
     A_ASSERT(osbuf != NULL);
 
@@ -641,7 +641,7 @@
 
     datap = A_NETBUF_DATA(osbuf);
 
-    typeorlen = *(A_UINT16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
+    typeorlen = *(u16 *)(datap + ATH_MAC_LEN + ATH_MAC_LEN);
 
     if (!IS_ETHERTYPE(A_BE2CPU16(typeorlen))) {
 /*
@@ -654,8 +654,8 @@
     /*
      * Save mac fields and length to be inserted later
      */
-    A_MEMCPY(macHdr.dstMac, datap, ATH_MAC_LEN);
-    A_MEMCPY(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
+    memcpy(macHdr.dstMac, datap, ATH_MAC_LEN);
+    memcpy(macHdr.srcMac, datap + ATH_MAC_LEN, ATH_MAC_LEN);
     macHdr.typeOrLen = A_CPU2BE16(A_NETBUF_LEN(osbuf) - sizeof(ATH_MAC_HDR) +
                                   sizeof(ATH_LLC_SNAP_HDR));
 
@@ -664,7 +664,7 @@
     /*
      * Make room for LLC+SNAP headers
      */
-    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
         return A_NO_MEMORY;
     }
     datap = A_NETBUF_DATA(osbuf);
@@ -682,8 +682,8 @@
     /* Make room for 802.11 hdr */
     if (wmip->wmi_is_wmm_enabled)
     {
-        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32));
-        if (A_NETBUF_PUSH(osbuf, hdrsize) != A_OK)
+        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
+        if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
         {
             return A_NO_MEMORY;
         }
@@ -692,8 +692,8 @@
     }
     else
     {
-        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(A_UINT32));
-        if (A_NETBUF_PUSH(osbuf, hdrsize) != A_OK)
+        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_frame),sizeof(u32));
+        if (A_NETBUF_PUSH(osbuf, hdrsize) != 0)
         {
             return A_NO_MEMORY;
         }
@@ -710,18 +710,18 @@
         IEEE80211_ADDR_COPY(wh->i_addr1, macHdr.dstMac);
     }
 
-    return (A_OK);
+    return (0);
 }
 
-A_STATUS
+int
 wmi_dot11_hdr_remove(struct wmi_t *wmip, void *osbuf)
 {
-    A_UINT8          *datap;
+    u8 *datap;
     struct           ieee80211_frame *pwh,wh;
-    A_UINT8          type,subtype;
+    u8 type,subtype;
     ATH_LLC_SNAP_HDR *llcHdr;
     ATH_MAC_HDR      macHdr;
-    A_UINT32         hdrsize;
+    u32 hdrsize;
 
     A_ASSERT(osbuf != NULL);
     datap = A_NETBUF_DATA(osbuf);
@@ -730,11 +730,11 @@
     type = pwh->i_fc[0] & IEEE80211_FC0_TYPE_MASK;
     subtype = pwh->i_fc[0] & IEEE80211_FC0_SUBTYPE_MASK;
 
-    A_MEMCPY((A_UINT8 *)&wh, datap, sizeof(struct ieee80211_frame));
+    memcpy((u8 *)&wh, datap, sizeof(struct ieee80211_frame));
 
     /* strip off the 802.11 hdr*/
     if (subtype == IEEE80211_FC0_SUBTYPE_QOS) {
-        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(A_UINT32));
+        hdrsize = A_ROUND_UP(sizeof(struct ieee80211_qosframe),sizeof(u32));
         A_NETBUF_PULL(osbuf, hdrsize);
     } else if (subtype == IEEE80211_FC0_SUBTYPE_DATA) {
         A_NETBUF_PULL(osbuf, sizeof(struct ieee80211_frame));
@@ -772,44 +772,44 @@
     A_NETBUF_PUSH(osbuf, sizeof(ATH_MAC_HDR));
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY (datap, &macHdr, sizeof(ATH_MAC_HDR));
+    memcpy (datap, &macHdr, sizeof(ATH_MAC_HDR));
 
-    return A_OK;
+    return 0;
 }
 
 /*
  *  performs 802.3 to DIX encapsulation for received packets.
  *  Assumes the entire 802.3 header is contigous.
  */
-A_STATUS
+int
 wmi_dot3_2_dix(void *osbuf)
 {
-    A_UINT8          *datap;
+    u8 *datap;
     ATH_MAC_HDR      macHdr;
     ATH_LLC_SNAP_HDR *llcHdr;
 
     A_ASSERT(osbuf != NULL);
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(&macHdr, datap, sizeof(ATH_MAC_HDR));
+    memcpy(&macHdr, datap, sizeof(ATH_MAC_HDR));
     llcHdr = (ATH_LLC_SNAP_HDR *)(datap + sizeof(ATH_MAC_HDR));
     macHdr.typeOrLen = llcHdr->etherType;
 
-    if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != A_OK) {
+    if (A_NETBUF_PULL(osbuf, sizeof(ATH_LLC_SNAP_HDR)) != 0) {
         return A_NO_MEMORY;
     }
 
     datap = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(datap, &macHdr, sizeof (ATH_MAC_HDR));
+    memcpy(datap, &macHdr, sizeof (ATH_MAC_HDR));
 
-    return (A_OK);
+    return (0);
 }
 
 /*
  * Removes a WMI data header
  */
-A_STATUS
+int
 wmi_data_hdr_remove(struct wmi_t *wmip, void *osbuf)
 {
     A_ASSERT(osbuf != NULL);
@@ -826,14 +826,14 @@
 /*
  * WMI Extended Event received from Target.
  */
-A_STATUS
+int
 wmi_control_rx_xtnd(struct wmi_t *wmip, void *osbuf)
 {
     WMIX_CMD_HDR *cmd;
-    A_UINT16 id;
-    A_UINT8 *datap;
-    A_UINT32 len;
-    A_STATUS status = A_OK;
+    u16 id;
+    u8 *datap;
+    u32 len;
+    int status = 0;
 
     if (A_NETBUF_LEN(osbuf) < sizeof(WMIX_CMD_HDR)) {
         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 1\n", DBGARG));
@@ -844,7 +844,7 @@
     cmd = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
     id = cmd->commandId;
 
-    if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PULL(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
         wmip->wmi_stats.cmd_len_err++;
         return A_ERROR;
@@ -901,16 +901,16 @@
 /*
  * Control Path
  */
-A_UINT32 cmdRecvNum;
+u32 cmdRecvNum;
 
-A_STATUS
+int
 wmi_control_rx(struct wmi_t *wmip, void *osbuf)
 {
     WMI_CMD_HDR *cmd;
-    A_UINT16 id;
-    A_UINT8 *datap;
-    A_UINT32 len, i, loggingReq;
-    A_STATUS status = A_OK;
+    u16 id;
+    u8 *datap;
+    u32 len, i, loggingReq;
+    int status = 0;
 
     A_ASSERT(osbuf != NULL);
     if (A_NETBUF_LEN(osbuf) < sizeof(WMI_CMD_HDR)) {
@@ -923,7 +923,7 @@
     cmd = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
     id = cmd->commandId;
 
-    if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PULL(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
         A_NETBUF_FREE(osbuf);
         A_DPRINTF(DBG_WMI, (DBGFMT "bad packet 2\n", DBGARG));
         wmip->wmi_stats.cmd_len_err++;
@@ -999,7 +999,7 @@
             */
             WMI_BSS_INFO_HDR2 bih2;
             WMI_BSS_INFO_HDR *bih;
-            A_MEMCPY(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
+            memcpy(&bih2, datap, sizeof(WMI_BSS_INFO_HDR2));
 
             A_NETBUF_PUSH(osbuf, 4);
             datap = A_NETBUF_DATA(osbuf);
@@ -1011,7 +1011,7 @@
             bih->snr = bih2.snr;
             bih->rssi = bih2.snr - 95;
             bih->ieMask = bih2.ieMask;
-            A_MEMCPY(bih->bssid, bih2.bssid, ATH_MAC_LEN);
+            memcpy(bih->bssid, bih2.bssid, ATH_MAC_LEN);
 
             status = wmi_bssInfo_event_rx(wmip, datap, len);
             A_WMI_SEND_GENERIC_EVENT_TO_APP(wmip->wmi_devt, id, datap, len);
@@ -1192,7 +1192,7 @@
 }
 
 /* Send a "simple" wmi command -- one with no arguments */
-static A_STATUS
+static int
 wmi_simple_cmd(struct wmi_t *wmip, WMI_COMMAND_ID cmdid)
 {
     void *osbuf;
@@ -1209,7 +1209,7 @@
    Enabling this command only if GPIO or profiling support is enabled.
    This is to suppress warnings on some platforms */
 #if defined(CONFIG_HOST_GPIO_SUPPORT) || defined(CONFIG_TARGET_PROFILE_SUPPORT)
-static A_STATUS
+static int
 wmi_simple_cmd_xtnd(struct wmi_t *wmip, WMIX_COMMAND_ID cmdid)
 {
     void *osbuf;
@@ -1223,8 +1223,8 @@
 }
 #endif
 
-static A_STATUS
-wmi_ready_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_ready_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_READY_EVENT *ev = (WMI_READY_EVENT *)datap;
 
@@ -1232,36 +1232,36 @@
         return A_EINVAL;
     }
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
-    wmip->wmi_ready = TRUE;
+    wmip->wmi_ready = true;
     A_WMI_READY_EVENT(wmip->wmi_devt, ev->macaddr, ev->phyCapability,
                       ev->sw_version, ev->abi_version);
 
-    return A_OK;
+    return 0;
 }
 
 #define LE_READ_4(p)                            \
-    ((A_UINT32)                            \
-     ((((A_UINT8 *)(p))[0]      ) | (((A_UINT8 *)(p))[1] <<  8) | \
-      (((A_UINT8 *)(p))[2] << 16) | (((A_UINT8 *)(p))[3] << 24)))
+    ((u32)                            \
+     ((((u8 *)(p))[0]      ) | (((u8 *)(p))[1] <<  8) | \
+      (((u8 *)(p))[2] << 16) | (((u8 *)(p))[3] << 24)))
 
 static int __inline
-iswmmoui(const A_UINT8 *frm)
+iswmmoui(const u8 *frm)
 {
     return frm[1] > 3 && LE_READ_4(frm+2) == ((WMM_OUI_TYPE<<24)|WMM_OUI);
 }
 
 static int __inline
-iswmmparam(const A_UINT8 *frm)
+iswmmparam(const u8 *frm)
 {
     return frm[1] > 5 && frm[6] == WMM_PARAM_OUI_SUBTYPE;
 }
 
 
-static A_STATUS
-wmi_connect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_connect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CONNECT_EVENT *ev;
-    A_UINT8 *pie,*peie;
+    u8 *pie,*peie;
 
     if (len < sizeof(WMI_CONNECT_EVENT))
     {
@@ -1275,13 +1275,13 @@
         ev->bssid[0], ev->bssid[1], ev->bssid[2],
         ev->bssid[3], ev->bssid[4], ev->bssid[5]));
 
-    A_MEMCPY(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
+    memcpy(wmip->wmi_bssid, ev->bssid, ATH_MAC_LEN);
 
     /* initialize pointer to start of assoc rsp IEs */
     pie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen +
-                            sizeof(A_UINT16)  +  /* capinfo*/
-                            sizeof(A_UINT16)  +  /* status Code */
-                            sizeof(A_UINT16)  ;  /* associd */
+                            sizeof(u16)  +  /* capinfo*/
+                            sizeof(u16)  +  /* status Code */
+                            sizeof(u16)  ;  /* associd */
 
     /* initialize pointer to end of assoc rsp IEs */
     peie = ev->assocInfo + ev->beaconIeLen + ev->assocReqLen + ev->assocRespLen;
@@ -1295,7 +1295,7 @@
                 {
                     if(iswmmparam (pie))
                     {
-                        wmip->wmi_is_wmm_enabled = TRUE;
+                        wmip->wmi_is_wmm_enabled = true;
                     }
                 }
             break;
@@ -1314,11 +1314,11 @@
                          ev->assocReqLen, ev->assocRespLen,
                          ev->assocInfo);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_regDomain_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_regDomain_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_REG_DOMAIN_EVENT *ev;
 
@@ -1329,11 +1329,11 @@
 
     A_WMI_REGDOMAIN_EVENT(wmip->wmi_devt, ev->regDomain);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_neighborReport_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_neighborReport_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_NEIGHBOR_REPORT_EVENT *ev;
     int numAps;
@@ -1350,11 +1350,11 @@
 
     A_WMI_NEIGHBORREPORT_EVENT(wmip->wmi_devt, numAps, ev->neighbor);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_disconnect_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_disconnect_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_DISCONNECT_EVENT *ev;
     wmip->wmi_traffic_class = 100;
@@ -1368,18 +1368,18 @@
 
     A_MEMZERO(wmip->wmi_bssid, sizeof(wmip->wmi_bssid));
 
-    wmip->wmi_is_wmm_enabled = FALSE;
+    wmip->wmi_is_wmm_enabled = false;
     wmip->wmi_pair_crypto_type = NONE_CRYPT;
     wmip->wmi_grp_crypto_type = NONE_CRYPT;
 
     A_WMI_DISCONNECT_EVENT(wmip->wmi_devt, ev->disconnectReason, ev->bssid,
                             ev->assocRespLen, ev->assocInfo, ev->protocolReasonStatus);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_peer_node_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_peer_node_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_PEER_NODE_EVENT *ev;
 
@@ -1395,11 +1395,11 @@
 
     A_WMI_PEER_EVENT (wmip->wmi_devt, ev->eventCode, ev->peerMacAddr);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_tkip_micerr_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_tkip_micerr_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TKIP_MICERR_EVENT *ev;
 
@@ -1411,19 +1411,19 @@
     ev = (WMI_TKIP_MICERR_EVENT *)datap;
     A_WMI_TKIP_MICERR_EVENT(wmip->wmi_devt, ev->keyid, ev->ismcast);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_bssInfo_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_bssInfo_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     bss_t *bss = NULL;
     WMI_BSS_INFO_HDR *bih;
-    A_UINT8 *buf;
-    A_UINT32 nodeCachingAllowed = 1;
-    A_UCHAR cached_ssid_len = 0;
-    A_UCHAR cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
-    A_UINT8 beacon_ssid_len = 0;
+    u8 *buf;
+    u32 nodeCachingAllowed = 1;
+    u8 cached_ssid_len = 0;
+    u8 cached_ssid_buf[IEEE80211_NWID_LEN] = {0};
+    u8 beacon_ssid_len = 0;
 
     if (len <= sizeof(WMI_BSS_INFO_HDR)) {
         return A_EINVAL;
@@ -1434,7 +1434,7 @@
 
     if (bih->rssi > 0) {
         if (NULL == bss)
-            return A_OK;  //no node found in the table, just drop the node with incorrect RSSI
+            return 0;  //no node found in the table, just drop the node with incorrect RSSI
         else
             bih->rssi = bss->ni_rssi; //Adjust RSSI in datap in case it is used in A_WMI_BSSINFO_EVENT_RX
     }
@@ -1443,14 +1443,14 @@
     /* What is driver config for wlan node caching? */
     if(ar6000_get_driver_cfg(wmip->wmi_devt,
                     AR6000_DRIVER_CFG_GET_WLANNODECACHING,
-                    &nodeCachingAllowed) != A_OK) {
+                    &nodeCachingAllowed) != 0) {
         wmi_node_return(wmip, bss);
         return A_EINVAL;
     }
 
     if(!nodeCachingAllowed) {
         wmi_node_return(wmip, bss);
-        return A_OK;
+        return 0;
     }
 
     buf = datap + sizeof(WMI_BSS_INFO_HDR);
@@ -1462,7 +1462,7 @@
 
     if(wps_enable && (bih->frameType == PROBERESP_FTYPE) ) {
         wmi_node_return(wmip, bss);
-        return A_OK;
+        return 0;
     }
 
     if (bss != NULL) {
@@ -1475,9 +1475,9 @@
         /* In case of hidden AP, beacon will not have ssid,
          * but a directed probe response will have it,
          * so cache the probe-resp-ssid if already present. */
-        if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
+        if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType))
         {
-            A_UCHAR *ie_ssid;
+            u8 *ie_ssid;
 
             ie_ssid = bss->ni_cie.ie_ssid;
             if(ie_ssid && (ie_ssid[1] <= IEEE80211_NWID_LEN) && (ie_ssid[2] != 0))
@@ -1510,7 +1510,7 @@
     beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
 
     /* If ssid is cached for this hidden AP, then change buffer len accordingly. */
-    if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
+    if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
         (0 != cached_ssid_len) &&
         (0 == beacon_ssid_len || (cached_ssid_len > beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
     {
@@ -1529,16 +1529,16 @@
     /* In case of hidden AP, beacon will not have ssid,
      * but a directed probe response will have it,
      * so place the cached-ssid(probe-resp) in the bssinfo. */
-    if ((TRUE == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
+    if ((true == is_probe_ssid) && (BEACON_FTYPE == bih->frameType) &&
          (0 != cached_ssid_len) &&
          (0 == beacon_ssid_len || (beacon_ssid_len && 0 == buf[SSID_IE_LEN_INDEX + 1])))
     {
-        A_UINT8 *ni_buf = bss->ni_buf;
+        u8 *ni_buf = bss->ni_buf;
         int buf_len = len;
 
         /* copy the first 14 bytes such as
          * time-stamp(8), beacon-interval(2), cap-info(2), ssid-id(1), ssid-len(1). */
-        A_MEMCPY(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
+        memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
 
         ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
         ni_buf += (SSID_IE_LEN_INDEX + 1);
@@ -1547,7 +1547,7 @@
         buf_len -= (SSID_IE_LEN_INDEX + 1);
 
         /* copy the cached ssid */
-        A_MEMCPY(ni_buf, cached_ssid_buf, cached_ssid_len);
+        memcpy(ni_buf, cached_ssid_buf, cached_ssid_len);
         ni_buf += cached_ssid_len;
 
         buf += beacon_ssid_len;
@@ -1557,13 +1557,13 @@
             buf_len -= (cached_ssid_len - beacon_ssid_len);
 
         /* now copy the rest of bytes */
-        A_MEMCPY(ni_buf, buf, buf_len);
+        memcpy(ni_buf, buf, buf_len);
     }
     else
-        A_MEMCPY(bss->ni_buf, buf, len);
+        memcpy(bss->ni_buf, buf, len);
 
     bss->ni_framelen = len;
-    if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != A_OK) {
+    if (wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie) != 0) {
         wlan_node_free(bss);
         return A_EINVAL;
     }
@@ -1575,15 +1575,15 @@
     bss->ni_cie.ie_chan = bih->channel;
     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_opt_frame_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_opt_frame_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     bss_t *bss;
     WMI_OPT_RX_INFO_HDR *bih;
-    A_UINT8 *buf;
+    u8 *buf;
 
     if (len <= sizeof(WMI_OPT_RX_INFO_HDR)) {
         return A_EINVAL;
@@ -1614,17 +1614,17 @@
     bss->ni_snr        = bih->snr;
     bss->ni_cie.ie_chan = bih->channel;
     A_ASSERT(bss->ni_buf != NULL);
-    A_MEMCPY(bss->ni_buf, buf, len);
+    memcpy(bss->ni_buf, buf, len);
     wlan_setup_node(&wmip->wmi_scan_table, bss, bih->bssid);
 
-    return A_OK;
+    return 0;
 }
 
     /* This event indicates inactivity timeout of a fatpipe(pstream)
      * at the target
      */
-static A_STATUS
-wmi_pstream_timeout_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_pstream_timeout_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_PSTREAM_TIMEOUT_EVENT *ev;
 
@@ -1650,15 +1650,15 @@
         /*Indicate inactivity to driver layer for this fatpipe (pstream)*/
     A_WMI_STREAM_TX_INACTIVE(wmip->wmi_devt, ev->trafficClass);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_bitrate_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_bitrate_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_BIT_RATE_REPLY *reply;
-    A_INT32 rate;
-    A_UINT32 sgi,index;
+    s32 rate;
+    u32 sgi,index;
     /* 54149:
      * WMI_BIT_RATE_CMD structure is changed to WMI_BIT_RATE_REPLY.
      * since there is difference in the length and to avoid returning
@@ -1671,7 +1671,7 @@
     A_DPRINTF(DBG_WMI,
         (DBGFMT "Enter - rateindex %d\n", DBGARG, reply->rateIndex));
 
-    if (reply->rateIndex == (A_INT8) RATE_AUTO) {
+    if (reply->rateIndex == (s8) RATE_AUTO) {
         rate = RATE_AUTO;
     } else {
         // the SGI state is stored as the MSb of the rateIndex
@@ -1681,11 +1681,11 @@
     }
 
     A_WMI_BITRATE_RX(wmip->wmi_devt, rate);
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_ratemask_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_ratemask_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_FIX_RATES_REPLY *reply;
 
@@ -1698,11 +1698,11 @@
 
     A_WMI_RATEMASK_RX(wmip->wmi_devt, reply->fixRateMask);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_channelList_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_channelList_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CHANNEL_LIST_REPLY *reply;
 
@@ -1715,11 +1715,11 @@
     A_WMI_CHANNELLIST_RX(wmip->wmi_devt, reply->numChannels,
                           reply->channelList);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_txPwr_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_txPwr_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TX_PWR_REPLY *reply;
 
@@ -1731,10 +1731,10 @@
 
     A_WMI_TXPWR_RX(wmip->wmi_devt, reply->dbM);
 
-    return A_OK;
+    return 0;
 }
-static A_STATUS
-wmi_keepalive_reply_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_keepalive_reply_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_GET_KEEPALIVE_CMD *reply;
 
@@ -1746,12 +1746,12 @@
 
     A_WMI_KEEPALIVE_RX(wmip->wmi_devt, reply->configured);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_dset_open_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dset_open_req_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_DSETOPENREQ_EVENT *dsetopenreq;
 
@@ -1767,12 +1767,12 @@
                         dsetopenreq->targ_reply_fn,
                         dsetopenreq->targ_reply_arg);
 
-    return A_OK;
+    return 0;
 }
 
 #ifdef CONFIG_HOST_DSET_SUPPORT
-static A_STATUS
-wmi_dset_close_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dset_close_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_DSETCLOSE_EVENT *dsetclose;
 
@@ -1784,11 +1784,11 @@
     dsetclose = (WMIX_DSETCLOSE_EVENT *)datap;
     A_WMI_DSET_CLOSE(wmip->wmi_devt, dsetclose->access_cookie);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_dset_data_req_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dset_data_req_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_DSETDATAREQ_EVENT *dsetdatareq;
 
@@ -1806,23 +1806,23 @@
                          dsetdatareq->targ_reply_fn,
                          dsetdatareq->targ_reply_arg);
 
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_HOST_DSET_SUPPORT */
 
-static A_STATUS
-wmi_scanComplete_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_scanComplete_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_SCAN_COMPLETE_EVENT *ev;
 
     ev = (WMI_SCAN_COMPLETE_EVENT *)datap;
-    if ((A_STATUS)ev->status == A_OK) {
+    if ((int)ev->status == 0) {
         wlan_refresh_inactive_nodes(&wmip->wmi_scan_table);
     }
-    A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (A_STATUS) ev->status);
-    is_probe_ssid = FALSE;
+    A_WMI_SCANCOMPLETE_EVENT(wmip->wmi_devt, (int) ev->status);
+    is_probe_ssid = false;
 
-    return A_OK;
+    return 0;
 }
 
 /*
@@ -1832,8 +1832,8 @@
  * Behavior of target after wmi error event is undefined.
  * A reset is recommended.
  */
-static A_STATUS
-wmi_errorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_errorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CMD_ERROR_EVENT *ev;
 
@@ -1851,30 +1851,30 @@
         break;
     }
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_statsEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_statsEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_TARGETSTATS_EVENT(wmip->wmi_devt, datap, len);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_rssiThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_RSSI_THRESHOLD_EVENT *reply;
     WMI_RSSI_THRESHOLD_VAL newThreshold;
     WMI_RSSI_THRESHOLD_PARAMS_CMD cmd;
     SQ_THRESHOLD_PARAMS *sq_thresh =
            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_RSSI];
-    A_UINT8 upper_rssi_threshold, lower_rssi_threshold;
-    A_INT16 rssi;
+    u8 upper_rssi_threshold, lower_rssi_threshold;
+    s16 rssi;
 
     if (len < sizeof(*reply)) {
         return A_EINVAL;
@@ -1959,19 +1959,19 @@
 
     rssi_event_value = rssi;
 
-    if (wmi_send_rssi_threshold_params(wmip, &cmd) != A_OK) {
+    if (wmi_send_rssi_threshold_params(wmip, &cmd) != 0) {
         A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the RSSI thresholds\n",
                   DBGARG));
     }
 
     A_WMI_RSSI_THRESHOLD_EVENT(wmip->wmi_devt, newThreshold, reply->rssi);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_reportErrorEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_reportErrorEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TARGET_ERROR_REPORT_EVENT *reply;
 
@@ -1983,15 +1983,15 @@
 
     A_WMI_REPORT_ERROR_EVENT(wmip->wmi_devt, (WMI_TARGET_ERROR_VAL) reply->errorVal);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_cac_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_cac_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CAC_EVENT *reply;
     WMM_TSPEC_IE *tspec_ie;
-    A_UINT16 activeTsids;
+    u16 activeTsids;
 
     if (len < sizeof(*reply)) {
         return A_EINVAL;
@@ -2008,7 +2008,7 @@
                 (tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
     }
     else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
-        A_UINT8 i;
+        u8 i;
 
         /* following assumes that there is only one outstanding ADDTS request
            when this event is received */
@@ -2030,7 +2030,7 @@
          * for delete qos stream from AP
          */
     else if (reply->cac_indication == CAC_INDICATION_DELETE) {
-        A_UINT8 tsid = 0;
+        u8 tsid = 0;
 
         tspec_ie = (WMM_TSPEC_IE *) &(reply->tspecSuggestion);
         tsid= ((tspec_ie->tsInfo_info >> TSPEC_TSID_S) & TSPEC_TSID_MASK);
@@ -2053,11 +2053,11 @@
                 reply->cac_indication, reply->statusCode,
                 reply->tspecSuggestion);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_channel_change_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_channel_change_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_CHANNEL_CHANGE_EVENT *reply;
 
@@ -2070,11 +2070,11 @@
     A_WMI_CHANNEL_CHANGE_EVENT(wmip->wmi_devt, reply->oldChannel,
                                reply->newChannel);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_hbChallengeResp_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_hbChallengeResp_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_HB_CHALLENGE_RESP_EVENT *reply;
 
@@ -2086,11 +2086,11 @@
 
     A_WMI_HBCHALLENGERESP_EVENT(wmip->wmi_devt, reply->cookie, reply->source);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_roam_tbl_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_roam_tbl_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TARGET_ROAM_TBL *reply;
 
@@ -2102,11 +2102,11 @@
 
     A_WMI_ROAM_TABLE_EVENT(wmip->wmi_devt, reply);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_roam_data_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_roam_data_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_TARGET_ROAM_DATA *reply;
 
@@ -2118,11 +2118,11 @@
 
     A_WMI_ROAM_DATA_EVENT(wmip->wmi_devt, reply);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_txRetryErrEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_txRetryErrEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     if (len < sizeof(WMI_TX_RETRY_ERR_EVENT)) {
         return A_EINVAL;
@@ -2131,19 +2131,19 @@
 
     A_WMI_TX_RETRY_ERR_EVENT(wmip->wmi_devt);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_snrThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_snrThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_SNR_THRESHOLD_EVENT *reply;
     SQ_THRESHOLD_PARAMS *sq_thresh =
            &wmip->wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_SNR];
     WMI_SNR_THRESHOLD_VAL newThreshold;
     WMI_SNR_THRESHOLD_PARAMS_CMD cmd;
-    A_UINT8 upper_snr_threshold, lower_snr_threshold;
-    A_INT16 snr;
+    u8 upper_snr_threshold, lower_snr_threshold;
+    s16 snr;
 
     if (len < sizeof(*reply)) {
         return A_EINVAL;
@@ -2218,17 +2218,17 @@
 
     snr_event_value = snr;
 
-    if (wmi_send_snr_threshold_params(wmip, &cmd) != A_OK) {
+    if (wmi_send_snr_threshold_params(wmip, &cmd) != 0) {
         A_DPRINTF(DBG_WMI, (DBGFMT "Unable to configure the SNR thresholds\n",
                   DBGARG));
     }
     A_WMI_SNR_THRESHOLD_EVENT_RX(wmip->wmi_devt, newThreshold, reply->snr);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_lqThresholdEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_lqThresholdEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_LQ_THRESHOLD_EVENT *reply;
 
@@ -2242,16 +2242,16 @@
                                 (WMI_LQ_THRESHOLD_VAL) reply->range,
                                 reply->lq);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_aplistEvent_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_aplistEvent_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
-    A_UINT16 ap_info_entry_size;
+    u16 ap_info_entry_size;
     WMI_APLIST_EVENT *ev = (WMI_APLIST_EVENT *)datap;
     WMI_AP_INFO_V1 *ap_info_v1;
-    A_UINT8 i;
+    u8 i;
 
     if (len < sizeof(WMI_APLIST_EVENT)) {
         return A_EINVAL;
@@ -2283,24 +2283,24 @@
                    ap_info_v1->channel));
         ap_info_v1++;
     }
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_dbglog_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_dbglog_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
-    A_UINT32 dropped;
+    u32 dropped;
 
-    dropped = *((A_UINT32 *)datap);
+    dropped = *((u32 *)datap);
     datap += sizeof(dropped);
     len -= sizeof(dropped);
-    A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (A_INT8*)datap, len);
-    return A_OK;
+    A_WMI_DBGLOG_EVENT(wmip->wmi_devt, dropped, (s8 *)datap, len);
+    return 0;
 }
 
 #ifdef CONFIG_HOST_GPIO_SUPPORT
-static A_STATUS
-wmi_gpio_intr_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_gpio_intr_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_GPIO_INTR_EVENT *gpio_intr = (WMIX_GPIO_INTR_EVENT *)datap;
 
@@ -2310,11 +2310,11 @@
 
     A_WMI_GPIO_INTR_RX(gpio_intr->intr_mask, gpio_intr->input_values);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_gpio_data_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_gpio_data_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_GPIO_DATA_EVENT *gpio_data = (WMIX_GPIO_DATA_EVENT *)datap;
 
@@ -2324,17 +2324,17 @@
 
     A_WMI_GPIO_DATA_RX(gpio_data->reg_id, gpio_data->value);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_gpio_ack_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_gpio_ack_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_GPIO_ACK_RX();
 
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
@@ -2342,11 +2342,11 @@
  * Called to send a wmi command. Command specific data is already built
  * on osbuf and current osbuf->data points to it.
  */
-A_STATUS
+int
 wmi_cmd_send(struct wmi_t *wmip, void *osbuf, WMI_COMMAND_ID cmdId,
                WMI_SYNC_FLAG syncflag)
 {
-    A_STATUS status;
+    int status;
 #define IS_OPT_TX_CMD(cmdId) ((cmdId == WMI_OPT_TX_FRAME_CMDID))
     WMI_CMD_HDR         *cHdr;
     HTC_ENDPOINT_ID     eid  = wmip->wmi_endpoint_id;
@@ -2366,20 +2366,20 @@
         wmi_sync_point(wmip);
     }
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_CMD_HDR)) != 0) {
         A_NETBUF_FREE(osbuf);
         return A_NO_MEMORY;
     }
 
     cHdr = (WMI_CMD_HDR *)A_NETBUF_DATA(osbuf);
-    cHdr->commandId = (A_UINT16) cmdId;
+    cHdr->commandId = (u16) cmdId;
     cHdr->info1 = 0; // added for virtual interface
 
     /*
      * Only for OPT_TX_CMD, use BE endpoint.
      */
     if (IS_OPT_TX_CMD(cmdId)) {
-        if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, FALSE, FALSE,0,NULL)) != A_OK) {
+        if ((status=wmi_data_hdr_add(wmip, osbuf, OPT_MSGTYPE, false, false,0,NULL)) != 0) {
             A_NETBUF_FREE(osbuf);
             return status;
         }
@@ -2394,34 +2394,34 @@
          */
         wmi_sync_point(wmip);
     }
-    return (A_OK);
+    return (0);
 #undef IS_OPT_TX_CMD
 }
 
-A_STATUS
+int
 wmi_cmd_send_xtnd(struct wmi_t *wmip, void *osbuf, WMIX_COMMAND_ID cmdId,
                   WMI_SYNC_FLAG syncflag)
 {
     WMIX_CMD_HDR     *cHdr;
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMIX_CMD_HDR)) != 0) {
         A_NETBUF_FREE(osbuf);
         return A_NO_MEMORY;
     }
 
     cHdr = (WMIX_CMD_HDR *)A_NETBUF_DATA(osbuf);
-    cHdr->commandId = (A_UINT32) cmdId;
+    cHdr->commandId = (u32) cmdId;
 
     return wmi_cmd_send(wmip, osbuf, WMI_EXTENSION_CMDID, syncflag);
 }
 
-A_STATUS
+int
 wmi_connect_cmd(struct wmi_t *wmip, NETWORK_TYPE netType,
                 DOT11_AUTH_MODE dot11AuthMode, AUTH_MODE authMode,
-                CRYPTO_TYPE pairwiseCrypto, A_UINT8 pairwiseCryptoLen,
-                CRYPTO_TYPE groupCrypto, A_UINT8 groupCryptoLen,
-                int ssidLength, A_UCHAR *ssid,
-                A_UINT8 *bssid, A_UINT16 channel, A_UINT32 ctrl_flags)
+                CRYPTO_TYPE pairwiseCrypto, u8 pairwiseCryptoLen,
+                CRYPTO_TYPE groupCrypto, u8 groupCryptoLen,
+                int ssidLength, u8 *ssid,
+                u8 *bssid, u16 channel, u32 ctrl_flags)
 {
     void *osbuf;
     WMI_CONNECT_CMD *cc;
@@ -2446,7 +2446,7 @@
 
     if (ssidLength)
     {
-        A_MEMCPY(cc->ssid, ssid, ssidLength);
+        memcpy(cc->ssid, ssid, ssidLength);
     }
 
     cc->ssidLength          = ssidLength;
@@ -2461,7 +2461,7 @@
     cc->ctrl_flags          = ctrl_flags;
 
     if (bssid != NULL) {
-        A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
+        memcpy(cc->bssid, bssid, ATH_MAC_LEN);
     }
 
     wmip->wmi_pair_crypto_type  = pairwiseCrypto;
@@ -2470,8 +2470,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_reconnect_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT16 channel)
+int
+wmi_reconnect_cmd(struct wmi_t *wmip, u8 *bssid, u16 channel)
 {
     void *osbuf;
     WMI_RECONNECT_CMD *cc;
@@ -2490,16 +2490,16 @@
     cc->channel = channel;
 
     if (bssid != NULL) {
-        A_MEMCPY(cc->bssid, bssid, ATH_MAC_LEN);
+        memcpy(cc->bssid, bssid, ATH_MAC_LEN);
     }
 
     return (wmi_cmd_send(wmip, osbuf, WMI_RECONNECT_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_disconnect_cmd(struct wmi_t *wmip)
 {
-    A_STATUS status;
+    int status;
     wmip->wmi_traffic_class = 100;
 
     /* Bug fix for 24817(elevator bug) - the disconnect command does not
@@ -2509,15 +2509,15 @@
     return status;
 }
 
-A_STATUS
+int
 wmi_startscan_cmd(struct wmi_t *wmip, WMI_SCAN_TYPE scanType,
-                  A_BOOL forceFgScan, A_BOOL isLegacy,
-                  A_UINT32 homeDwellTime, A_UINT32 forceScanInterval,
-                  A_INT8 numChan, A_UINT16 *channelList)
+                  u32 forceFgScan, u32 isLegacy,
+                  u32 homeDwellTime, u32 forceScanInterval,
+                  s8 numChan, u16 *channelList)
 {
     void *osbuf;
     WMI_START_SCAN_CMD *sc;
-    A_INT8 size;
+    s8 size;
 
     size = sizeof (*sc);
 
@@ -2529,7 +2529,7 @@
         if (numChan > WMI_MAX_CHANNELS) {
             return A_EINVAL;
         }
-        size += sizeof(A_UINT16) * (numChan - 1);
+        size += sizeof(u16) * (numChan - 1);
     }
 
     osbuf = A_NETBUF_ALLOC(size);
@@ -2547,19 +2547,19 @@
     sc->forceScanInterval = forceScanInterval;
     sc->numChannels = numChan;
     if (numChan) {
-        A_MEMCPY(sc->channelList, channelList, numChan * sizeof(A_UINT16));
+        memcpy(sc->channelList, channelList, numChan * sizeof(u16));
     }
 
     return (wmi_cmd_send(wmip, osbuf, WMI_START_SCAN_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_scanparams_cmd(struct wmi_t *wmip, A_UINT16 fg_start_sec,
-                   A_UINT16 fg_end_sec, A_UINT16 bg_sec,
-                   A_UINT16 minact_chdw_msec, A_UINT16 maxact_chdw_msec,
-                   A_UINT16 pas_chdw_msec,
-                   A_UINT8 shScanRatio, A_UINT8 scanCtrlFlags,
-                   A_UINT32 max_dfsch_act_time, A_UINT16 maxact_scan_per_ssid)
+int
+wmi_scanparams_cmd(struct wmi_t *wmip, u16 fg_start_sec,
+                   u16 fg_end_sec, u16 bg_sec,
+                   u16 minact_chdw_msec, u16 maxact_chdw_msec,
+                   u16 pas_chdw_msec,
+                   u8 shScanRatio, u8 scanCtrlFlags,
+                   u32 max_dfsch_act_time, u16 maxact_scan_per_ssid)
 {
     void *osbuf;
     WMI_SCAN_PARAMS_CMD *sc;
@@ -2588,8 +2588,8 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_bssfilter_cmd(struct wmi_t *wmip, A_UINT8 filter, A_UINT32 ieMask)
+int
+wmi_bssfilter_cmd(struct wmi_t *wmip, u8 filter, u32 ieMask)
 {
     void *osbuf;
     WMI_BSS_FILTER_CMD *cmd;
@@ -2614,9 +2614,9 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_probedSsid_cmd(struct wmi_t *wmip, A_UINT8 index, A_UINT8 flag,
-                   A_UINT8 ssidLength, A_UCHAR *ssid)
+int
+wmi_probedSsid_cmd(struct wmi_t *wmip, u8 index, u8 flag,
+                   u8 ssidLength, u8 *ssid)
 {
     void *osbuf;
     WMI_PROBED_SSID_CMD *cmd;
@@ -2635,7 +2635,7 @@
     }
 
     if (flag & SPECIFIC_SSID_FLAG) {
-        is_probe_ssid = TRUE;
+        is_probe_ssid = true;
     }
 
     osbuf = A_NETBUF_ALLOC(sizeof(*cmd));
@@ -2650,14 +2650,14 @@
     cmd->entryIndex = index;
     cmd->flag       = flag;
     cmd->ssidLength = ssidLength;
-    A_MEMCPY(cmd->ssid, ssid, ssidLength);
+    memcpy(cmd->ssid, ssid, ssidLength);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PROBED_SSID_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_listeninterval_cmd(struct wmi_t *wmip, A_UINT16 listenInterval, A_UINT16 listenBeacons)
+int
+wmi_listeninterval_cmd(struct wmi_t *wmip, u16 listenInterval, u16 listenBeacons)
 {
     void *osbuf;
     WMI_LISTEN_INT_CMD *cmd;
@@ -2678,8 +2678,8 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_bmisstime_cmd(struct wmi_t *wmip, A_UINT16 bmissTime, A_UINT16 bmissBeacons)
+int
+wmi_bmisstime_cmd(struct wmi_t *wmip, u16 bmissTime, u16 bmissBeacons)
 {
     void *osbuf;
     WMI_BMISS_TIME_CMD *cmd;
@@ -2700,13 +2700,13 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_associnfo_cmd(struct wmi_t *wmip, A_UINT8 ieType,
-                     A_UINT8 ieLen, A_UINT8 *ieInfo)
+int
+wmi_associnfo_cmd(struct wmi_t *wmip, u8 ieType,
+                     u8 ieLen, u8 *ieInfo)
 {
     void *osbuf;
     WMI_SET_ASSOC_INFO_CMD *cmd;
-    A_UINT16 cmdLen;
+    u16 cmdLen;
 
     cmdLen = sizeof(*cmd) + ieLen - 1;
     osbuf = A_NETBUF_ALLOC(cmdLen);
@@ -2720,14 +2720,14 @@
     A_MEMZERO(cmd, cmdLen);
     cmd->ieType = ieType;
     cmd->bufferSize = ieLen;
-    A_MEMCPY(cmd->assocInfo, ieInfo, ieLen);
+    memcpy(cmd->assocInfo, ieInfo, ieLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ASSOC_INFO_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_powermode_cmd(struct wmi_t *wmip, A_UINT8 powerMode)
+int
+wmi_powermode_cmd(struct wmi_t *wmip, u8 powerMode)
 {
     void *osbuf;
     WMI_POWER_MODE_CMD *cmd;
@@ -2748,9 +2748,9 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ibsspmcaps_cmd(struct wmi_t *wmip, A_UINT8 pmEnable, A_UINT8 ttl,
-                   A_UINT16 atim_windows, A_UINT16 timeout_value)
+int
+wmi_ibsspmcaps_cmd(struct wmi_t *wmip, u8 pmEnable, u8 ttl,
+                   u16 atim_windows, u16 timeout_value)
 {
     void *osbuf;
     WMI_IBSS_PM_CAPS_CMD *cmd;
@@ -2773,9 +2773,9 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_apps_cmd(struct wmi_t *wmip, A_UINT8 psType, A_UINT32 idle_time,
-                   A_UINT32 ps_period, A_UINT8 sleep_period)
+int
+wmi_apps_cmd(struct wmi_t *wmip, u8 psType, u32 idle_time,
+                   u32 ps_period, u8 sleep_period)
 {
     void *osbuf;
     WMI_AP_PS_CMD *cmd;
@@ -2798,11 +2798,11 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_pmparams_cmd(struct wmi_t *wmip, A_UINT16 idlePeriod,
-                 A_UINT16 psPollNum, A_UINT16 dtimPolicy,
-                 A_UINT16 tx_wakeup_policy, A_UINT16 num_tx_to_wakeup,
-                 A_UINT16 ps_fail_event_policy)
+int
+wmi_pmparams_cmd(struct wmi_t *wmip, u16 idlePeriod,
+                 u16 psPollNum, u16 dtimPolicy,
+                 u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
+                 u16 ps_fail_event_policy)
 {
     void *osbuf;
     WMI_POWER_PARAMS_CMD *pm;
@@ -2827,8 +2827,8 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_disctimeout_cmd(struct wmi_t *wmip, A_UINT8 timeout)
+int
+wmi_disctimeout_cmd(struct wmi_t *wmip, u8 timeout)
 {
     void *osbuf;
     WMI_DISC_TIMEOUT_CMD *cmd;
@@ -2848,10 +2848,10 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_addKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex, CRYPTO_TYPE keyType,
-               A_UINT8 keyUsage, A_UINT8 keyLength, A_UINT8 *keyRSC,
-               A_UINT8 *keyMaterial, A_UINT8 key_op_ctrl, A_UINT8 *macAddr,
+int
+wmi_addKey_cmd(struct wmi_t *wmip, u8 keyIndex, CRYPTO_TYPE keyType,
+               u8 keyUsage, u8 keyLength, u8 *keyRSC,
+               u8 *keyMaterial, u8 key_op_ctrl, u8 *macAddr,
                WMI_SYNC_FLAG sync_flag)
 {
     void *osbuf;
@@ -2880,25 +2880,25 @@
     cmd->keyType  = keyType;
     cmd->keyUsage = keyUsage;
     cmd->keyLength = keyLength;
-    A_MEMCPY(cmd->key, keyMaterial, keyLength);
+    memcpy(cmd->key, keyMaterial, keyLength);
 #ifdef WAPI_ENABLE
     if (NULL != keyRSC && key_op_ctrl != KEY_OP_INIT_WAPIPN) {
 #else
     if (NULL != keyRSC) {
 #endif // WAPI_ENABLE
-        A_MEMCPY(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
+        memcpy(cmd->keyRSC, keyRSC, sizeof(cmd->keyRSC));
     }
     cmd->key_op_ctrl = key_op_ctrl;
 
     if(macAddr) {
-        A_MEMCPY(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
+        memcpy(cmd->key_macaddr,macAddr,IEEE80211_ADDR_LEN);
     }
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_CIPHER_KEY_CMDID, sync_flag));
 }
 
-A_STATUS
-wmi_add_krk_cmd(struct wmi_t *wmip, A_UINT8 *krk)
+int
+wmi_add_krk_cmd(struct wmi_t *wmip, u8 *krk)
 {
     void *osbuf;
     WMI_ADD_KRK_CMD *cmd;
@@ -2912,19 +2912,19 @@
 
     cmd = (WMI_ADD_KRK_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
-    A_MEMCPY(cmd->krk, krk, WMI_KRK_LEN);
+    memcpy(cmd->krk, krk, WMI_KRK_LEN);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_delete_krk_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_DELETE_KRK_CMDID);
 }
 
-A_STATUS
-wmi_deleteKey_cmd(struct wmi_t *wmip, A_UINT8 keyIndex)
+int
+wmi_deleteKey_cmd(struct wmi_t *wmip, u8 keyIndex)
 {
     void *osbuf;
     WMI_DELETE_CIPHER_KEY_CMD *cmd;
@@ -2948,9 +2948,9 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_setPmkid_cmd(struct wmi_t *wmip, A_UINT8 *bssid, A_UINT8 *pmkId,
-                 A_BOOL set)
+int
+wmi_setPmkid_cmd(struct wmi_t *wmip, u8 *bssid, u8 *pmkId,
+                 bool set)
 {
     void *osbuf;
     WMI_SET_PMKID_CMD *cmd;
@@ -2959,7 +2959,7 @@
         return A_EINVAL;
     }
 
-    if ((set == TRUE) && (pmkId == NULL)) {
+    if ((set == true) && (pmkId == NULL)) {
         return A_EINVAL;
     }
 
@@ -2971,9 +2971,9 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_SET_PMKID_CMD *)(A_NETBUF_DATA(osbuf));
-    A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
-    if (set == TRUE) {
-        A_MEMCPY(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
+    memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
+    if (set == true) {
+        memcpy(cmd->pmkid, pmkId, sizeof(cmd->pmkid));
         cmd->enable = PMKID_ENABLE;
     } else {
         A_MEMZERO(cmd->pmkid, sizeof(cmd->pmkid));
@@ -2983,8 +2983,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMKID_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, A_BOOL en)
+int
+wmi_set_tkip_countermeasures_cmd(struct wmi_t *wmip, bool en)
 {
     void *osbuf;
     WMI_SET_TKIP_COUNTERMEASURES_CMD *cmd;
@@ -2997,13 +2997,13 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_SET_TKIP_COUNTERMEASURES_CMD *)(A_NETBUF_DATA(osbuf));
-    cmd->cm_en = (en == TRUE)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
+    cmd->cm_en = (en == true)? WMI_TKIP_CM_ENABLE : WMI_TKIP_CM_DISABLE;
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TKIP_COUNTERMEASURES_CMDID,
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_akmp_params_cmd(struct wmi_t *wmip,
                         WMI_SET_AKMP_PARAMS_CMD *akmpParams)
 {
@@ -3023,14 +3023,14 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_pmkid_list_cmd(struct wmi_t *wmip,
                        WMI_SET_PMKID_LIST_CMD *pmkInfo)
 {
     void *osbuf;
     WMI_SET_PMKID_LIST_CMD *cmd;
-    A_UINT16 cmdLen;
-    A_UINT8 i;
+    u16 cmdLen;
+    u8 i;
 
     cmdLen = sizeof(pmkInfo->numPMKID) +
              pmkInfo->numPMKID * sizeof(WMI_PMKID);
@@ -3045,7 +3045,7 @@
     cmd->numPMKID = pmkInfo->numPMKID;
 
     for (i = 0; i < cmd->numPMKID; i++) {
-        A_MEMCPY(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
+        memcpy(&cmd->pmkidList[i], &pmkInfo->pmkidList[i],
                  WMI_PMKID_LEN);
     }
 
@@ -3053,13 +3053,13 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_pmkid_list_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_PMKID_LIST_CMDID);
 }
 
-A_STATUS
+int
 wmi_dataSync_send(struct wmi_t *wmip, void *osbuf, HTC_ENDPOINT_ID eid)
 {
     WMI_DATA_HDR     *dtHdr;
@@ -3067,7 +3067,7 @@
     A_ASSERT( eid != wmip->wmi_endpoint_id);
     A_ASSERT(osbuf != NULL);
 
-    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != A_OK) {
+    if (A_NETBUF_PUSH(osbuf, sizeof(WMI_DATA_HDR)) != 0) {
         return A_NO_MEMORY;
     }
 
@@ -3081,18 +3081,18 @@
 }
 
 typedef struct _WMI_DATA_SYNC_BUFS {
-    A_UINT8            trafficClass;
+    u8 trafficClass;
     void               *osbuf;
 }WMI_DATA_SYNC_BUFS;
 
-static A_STATUS
+static int
 wmi_sync_point(struct wmi_t *wmip)
 {
     void *cmd_osbuf;
     WMI_SYNC_CMD *cmd;
     WMI_DATA_SYNC_BUFS dataSyncBufs[WMM_NUM_AC];
-    A_UINT8 i,numPriStreams=0;
-    A_STATUS status = A_OK;
+    u8 i,numPriStreams=0;
+    int status = 0;
 
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
@@ -3144,7 +3144,7 @@
         /* if Buffer allocation for any of the dataSync fails, then do not
          * send the Synchronize cmd on the control ep
          */
-        if (A_FAILED(status)) {
+        if (status) {
             break;
         }
 
@@ -3155,7 +3155,7 @@
     status = wmi_cmd_send(wmip, cmd_osbuf, WMI_SYNCHRONIZE_CMDID,
                           NO_SYNC_WMIFLAG);
 
-        if (A_FAILED(status)) {
+        if (status) {
             break;
     }
             /* cmd buffer sent, we no longer own it */
@@ -3170,7 +3170,7 @@
                                                             trafficClass)
                                       );
 
-            if (A_FAILED(status)) {
+            if (status) {
                 break;
             }
             /* we don't own this buffer anymore, NULL it out of the array so it
@@ -3178,7 +3178,7 @@
             dataSyncBufs[i].osbuf = NULL;
         } //end for
 
-    } while(FALSE);
+    } while(false);
 
     /* free up any resources left over (possibly due to an error) */
 
@@ -3195,14 +3195,14 @@
     return (status);
 }
 
-A_STATUS
+int
 wmi_create_pstream_cmd(struct wmi_t *wmip, WMI_CREATE_PSTREAM_CMD *params)
 {
     void *osbuf;
     WMI_CREATE_PSTREAM_CMD *cmd;
-    A_UINT8 fatPipeExistsForAC=0;
-    A_INT32 minimalPHY = 0;
-    A_INT32 nominalPHY = 0;
+    u8 fatPipeExistsForAC=0;
+    s32 minimalPHY = 0;
+    s32 nominalPHY = 0;
 
     /* Validate all the parameters. */
     if( !((params->userPriority < 8) &&
@@ -3258,10 +3258,10 @@
 
     cmd = (WMI_CREATE_PSTREAM_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
-    A_MEMCPY(cmd, params, sizeof(*cmd));
+    memcpy(cmd, params, sizeof(*cmd));
 
         /* this is an implicitly created Fat pipe */
-    if ((A_UINT32)params->tsid == (A_UINT32)WMI_IMPLICIT_PSTREAM) {
+    if ((u32)params->tsid == (u32)WMI_IMPLICIT_PSTREAM) {
         LOCK_WMI(wmip);
         fatPipeExistsForAC = (wmip->wmi_fatPipeExists & (1 << params->trafficClass));
         wmip->wmi_fatPipeExists |= (1<<params->trafficClass);
@@ -3291,13 +3291,13 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_delete_pstream_cmd(struct wmi_t *wmip, A_UINT8 trafficClass, A_UINT8 tsid)
+int
+wmi_delete_pstream_cmd(struct wmi_t *wmip, u8 trafficClass, u8 tsid)
 {
     void *osbuf;
     WMI_DELETE_PSTREAM_CMD *cmd;
-    A_STATUS status;
-    A_UINT16 activeTsids=0;
+    int status;
+    u16 activeTsids=0;
 
     /* validate the parameters */
     if (trafficClass > 3) {
@@ -3355,12 +3355,12 @@
     return status;
 }
 
-A_STATUS
-wmi_set_framerate_cmd(struct wmi_t *wmip, A_UINT8 bEnable, A_UINT8 type, A_UINT8 subType, A_UINT16 rateMask)
+int
+wmi_set_framerate_cmd(struct wmi_t *wmip, u8 bEnable, u8 type, u8 subType, u16 rateMask)
 {
     void *osbuf;
     WMI_FRAME_RATES_CMD *cmd;
-    A_UINT8 frameType;
+    u8 frameType;
 
     A_DPRINTF(DBG_WMI,
         (DBGFMT " type %02X, subType %02X, rateMask %04x\n", DBGARG, type, subType, rateMask));
@@ -3381,7 +3381,7 @@
     cmd = (WMI_FRAME_RATES_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
 
-    frameType = (A_UINT8)((subType << 4) | type);
+    frameType = (u8)((subType << 4) | type);
 
     cmd->bEnableMask = bEnable;
     cmd->frameType = frameType;
@@ -3394,12 +3394,12 @@
  * used to set the bit rate.  rate is in Kbps.  If rate == -1
  * then auto selection is used.
  */
-A_STATUS
-wmi_set_bitrate_cmd(struct wmi_t *wmip, A_INT32 dataRate, A_INT32 mgmtRate, A_INT32 ctlRate)
+int
+wmi_set_bitrate_cmd(struct wmi_t *wmip, s32 dataRate, s32 mgmtRate, s32 ctlRate)
 {
     void *osbuf;
     WMI_BIT_RATE_CMD *cmd;
-    A_INT8 drix, mrix, crix, ret_val;
+    s8 drix, mrix, crix, ret_val;
 
     if (dataRate != -1) {
         ret_val = wmi_validate_bitrate(wmip, dataRate, &drix);
@@ -3444,47 +3444,47 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BITRATE_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_bitrate_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_BITRATE_CMDID);
 }
 
 /*
- * Returns TRUE iff the given rate index is legal in the current PHY mode.
+ * Returns true iff the given rate index is legal in the current PHY mode.
  */
-A_BOOL
-wmi_is_bitrate_index_valid(struct wmi_t *wmip, A_INT32 rateIndex)
+bool
+wmi_is_bitrate_index_valid(struct wmi_t *wmip, s32 rateIndex)
 {
     WMI_PHY_MODE phyMode = (WMI_PHY_MODE) wmip->wmi_phyMode;
-    A_BOOL isValid = TRUE;
+    bool isValid = true;
     switch(phyMode) {
         case WMI_11A_MODE:
             if (wmip->wmi_ht_allowed[A_BAND_5GHZ]){
                 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             } else {
                 if ((rateIndex < MODE_A_SUPPORT_RATE_START) || (rateIndex > MODE_A_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             }
             break;
 
         case WMI_11B_MODE:
             if ((rateIndex < MODE_B_SUPPORT_RATE_START) || (rateIndex > MODE_B_SUPPORT_RATE_STOP)) {
-                isValid = FALSE;
+                isValid = false;
             }
             break;
 
         case WMI_11GONLY_MODE:
             if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
                 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             } else {
                 if ((rateIndex < MODE_GONLY_SUPPORT_RATE_START) || (rateIndex > MODE_GONLY_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             }
             break;
@@ -3493,52 +3493,51 @@
         case WMI_11AG_MODE:
             if (wmip->wmi_ht_allowed[A_BAND_24GHZ]){
                 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_GHT20_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             } else {
                 if ((rateIndex < MODE_G_SUPPORT_RATE_START) || (rateIndex > MODE_G_SUPPORT_RATE_STOP)) {
-                    isValid = FALSE;
+                    isValid = false;
                 }
             }
             break;
         default:
-            A_ASSERT(FALSE);
+            A_ASSERT(false);
             break;
     }
 
     return isValid;
 }
 
-A_INT8
-wmi_validate_bitrate(struct wmi_t *wmip, A_INT32 rate, A_INT8 *rate_idx)
+s8 wmi_validate_bitrate(struct wmi_t *wmip, s32 rate, s8 *rate_idx)
 {
-    A_INT8 i;
+    s8 i;
 
     for (i=0;;i++)
     {
-        if (wmi_rateTable[(A_UINT32) i][0] == 0) {
+        if (wmi_rateTable[(u32) i][0] == 0) {
             return A_EINVAL;
         }
-        if (wmi_rateTable[(A_UINT32) i][0] == rate) {
+        if (wmi_rateTable[(u32) i][0] == rate) {
             break;
         }
     }
 
-    if(wmi_is_bitrate_index_valid(wmip, (A_INT32) i) != TRUE) {
+    if(wmi_is_bitrate_index_valid(wmip, (s32) i) != true) {
         return A_EINVAL;
     }
 
     *rate_idx = i;
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-wmi_set_fixrates_cmd(struct wmi_t *wmip, A_UINT32 fixRatesMask)
+int
+wmi_set_fixrates_cmd(struct wmi_t *wmip, u32 fixRatesMask)
 {
     void *osbuf;
     WMI_FIX_RATES_CMD *cmd;
 #if 0
-    A_INT32 rateIndex;
+    s32 rateIndex;
 /* This check does not work for AR6003 as the HT modes are enabled only when
  * the STA is connected to a HT_BSS and is not based only on channel. It is
  * safe to skip this check however because rate control will only use rates
@@ -3547,8 +3546,8 @@
  * to be used. */
     /* Make sure all rates in the mask are valid in the current PHY mode */
     for(rateIndex = 0; rateIndex < MAX_NUMBER_OF_SUPPORT_RATES; rateIndex++) {
-       if((1 << rateIndex) & (A_UINT32)fixRatesMask) {
-            if(wmi_is_bitrate_index_valid(wmip, rateIndex) != TRUE) {
+       if((1 << rateIndex) & (u32)fixRatesMask) {
+            if(wmi_is_bitrate_index_valid(wmip, rateIndex) != true) {
                 A_DPRINTF(DBG_WMI, (DBGFMT "Set Fix Rates command failed: Given rate is illegal in current PHY mode\n", DBGARG));
                 return A_EINVAL;
             }
@@ -3572,13 +3571,13 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_FIXRATES_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_ratemask_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_FIXRATES_CMDID);
 }
 
-A_STATUS
+int
 wmi_get_channelList_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_CHANNEL_LIST_CMDID);
@@ -3594,14 +3593,14 @@
  * should limit its operation to.  It should be NULL if numChan == 0.  Size of
  * array should correspond to numChan entries.
  */
-A_STATUS
-wmi_set_channelParams_cmd(struct wmi_t *wmip, A_UINT8 scanParam,
-                          WMI_PHY_MODE mode, A_INT8 numChan,
-                          A_UINT16 *channelList)
+int
+wmi_set_channelParams_cmd(struct wmi_t *wmip, u8 scanParam,
+                          WMI_PHY_MODE mode, s8 numChan,
+                          u16 *channelList)
 {
     void *osbuf;
     WMI_CHANNEL_PARAMS_CMD *cmd;
-    A_INT8 size;
+    s8 size;
 
     size = sizeof (*cmd);
 
@@ -3609,7 +3608,7 @@
         if (numChan > WMI_MAX_CHANNELS) {
             return A_EINVAL;
         }
-        size += sizeof(A_UINT16) * (numChan - 1);
+        size += sizeof(u16) * (numChan - 1);
     }
 
     osbuf = A_NETBUF_ALLOC(size);
@@ -3626,7 +3625,7 @@
     cmd->scanParam   = scanParam;
     cmd->phyMode     = mode;
     cmd->numChannels = numChan;
-    A_MEMCPY(cmd->channelList, channelList, numChan * sizeof(A_UINT16));
+    memcpy(cmd->channelList, channelList, numChan * sizeof(u16));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_CHANNEL_PARAMS_CMDID,
                          NO_SYNC_WMIFLAG));
@@ -3681,7 +3680,7 @@
 }
 }
 
-A_STATUS
+int
 wmi_set_rssi_threshold_params(struct wmi_t *wmip,
                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
 {
@@ -3706,15 +3705,15 @@
     return (wmi_send_rssi_threshold_params(wmip, rssiCmd));
 }
 
-A_STATUS
+int
 wmi_set_ip_cmd(struct wmi_t *wmip, WMI_SET_IP_CMD *ipCmd)
 {
     void    *osbuf;
     WMI_SET_IP_CMD *cmd;
 
     /* Multicast address are not valid */
-    if((*((A_UINT8*)&ipCmd->ips[0]) >= 0xE0) ||
-       (*((A_UINT8*)&ipCmd->ips[1]) >= 0xE0)) {
+    if((*((u8 *)&ipCmd->ips[0]) >= 0xE0) ||
+       (*((u8 *)&ipCmd->ips[1]) >= 0xE0)) {
         return A_EINVAL;
     }
 
@@ -3725,22 +3724,22 @@
 
     A_NETBUF_PUT(osbuf, sizeof(WMI_SET_IP_CMD));
     cmd = (WMI_SET_IP_CMD *)(A_NETBUF_DATA(osbuf));
-    A_MEMCPY(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
+    memcpy(cmd, ipCmd, sizeof(WMI_SET_IP_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_IP_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_host_sleep_mode_cmd(struct wmi_t *wmip,
                               WMI_SET_HOST_SLEEP_MODE_CMD *hostModeCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_SET_HOST_SLEEP_MODE_CMD *cmd;
-    A_UINT16 activeTsids=0;
-    A_UINT8 streamExists=0;
-    A_UINT8 i;
+    u16 activeTsids=0;
+    u8 streamExists=0;
+    u8 i;
 
     if( hostModeCmd->awake == hostModeCmd->asleep) {
         return A_EINVAL;
@@ -3757,7 +3756,7 @@
 
     cmd = (WMI_SET_HOST_SLEEP_MODE_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
+    memcpy(cmd, hostModeCmd, sizeof(WMI_SET_HOST_SLEEP_MODE_CMD));
 
     if(hostModeCmd->asleep) {
         /*
@@ -3793,12 +3792,12 @@
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_wow_mode_cmd(struct wmi_t *wmip,
                               WMI_SET_WOW_MODE_CMD *wowModeCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_SET_WOW_MODE_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -3812,19 +3811,19 @@
 
     cmd = (WMI_SET_WOW_MODE_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
+    memcpy(cmd, wowModeCmd, sizeof(WMI_SET_WOW_MODE_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WOW_MODE_CMDID,
                             NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_get_wow_list_cmd(struct wmi_t *wmip,
                               WMI_GET_WOW_LIST_CMD *wowListCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_GET_WOW_LIST_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -3838,15 +3837,15 @@
 
     cmd = (WMI_GET_WOW_LIST_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
+    memcpy(cmd, wowListCmd, sizeof(WMI_GET_WOW_LIST_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_GET_WOW_LIST_CMDID,
                             NO_SYNC_WMIFLAG));
 
 }
 
-static A_STATUS
-wmi_get_wow_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_get_wow_list_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_GET_WOW_LIST_REPLY *reply;
 
@@ -3858,22 +3857,22 @@
     A_WMI_WOW_LIST_EVENT(wmip->wmi_devt, reply->num_filters,
                           reply);
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
+int wmi_add_wow_pattern_cmd(struct wmi_t *wmip,
                                  WMI_ADD_WOW_PATTERN_CMD *addWowCmd,
-                                 A_UINT8* pattern, A_UINT8* mask,
-                                 A_UINT8 pattern_size)
+                                 u8 *pattern, u8 *mask,
+                                 u8 pattern_size)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_ADD_WOW_PATTERN_CMD *cmd;
-    A_UINT8 *filter_mask = NULL;
+    u8 *filter_mask = NULL;
 
     size = sizeof (*cmd);
 
-    size += ((2 * addWowCmd->filter_size)* sizeof(A_UINT8));
+    size += ((2 * addWowCmd->filter_size)* sizeof(u8));
     osbuf = A_NETBUF_ALLOC(size);
     if (osbuf == NULL) {
         return A_NO_MEMORY;
@@ -3886,22 +3885,22 @@
     cmd->filter_offset = addWowCmd->filter_offset;
     cmd->filter_size = addWowCmd->filter_size;
 
-    A_MEMCPY(cmd->filter, pattern, addWowCmd->filter_size);
+    memcpy(cmd->filter, pattern, addWowCmd->filter_size);
 
-    filter_mask = (A_UINT8*)(cmd->filter + cmd->filter_size);
-    A_MEMCPY(filter_mask, mask, addWowCmd->filter_size);
+    filter_mask = (u8 *)(cmd->filter + cmd->filter_size);
+    memcpy(filter_mask, mask, addWowCmd->filter_size);
 
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_WOW_PATTERN_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_del_wow_pattern_cmd(struct wmi_t *wmip,
                               WMI_DEL_WOW_PATTERN_CMD *delWowCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_DEL_WOW_PATTERN_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -3915,7 +3914,7 @@
 
     cmd = (WMI_DEL_WOW_PATTERN_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
+    memcpy(cmd, delWowCmd, sizeof(WMI_DEL_WOW_PATTERN_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_DEL_WOW_PATTERN_CMDID,
                             NO_SYNC_WMIFLAG));
@@ -3953,8 +3952,8 @@
      * event from the target which is used for the configuring the correct
      * thresholds
      */
-    snrCmd->thresholdAbove1_Val = (A_UINT8)sq_thresh->upper_threshold[0];
-    snrCmd->thresholdBelow1_Val = (A_UINT8)sq_thresh->lower_threshold[0];
+    snrCmd->thresholdAbove1_Val = (u8)sq_thresh->upper_threshold[0];
+    snrCmd->thresholdBelow1_Val = (u8)sq_thresh->lower_threshold[0];
     } else {
         /*
          * In case the user issues multiple times of snr_threshold_setting,
@@ -3967,7 +3966,7 @@
     }
 
 }
-A_STATUS
+int
 wmi_set_snr_threshold_params(struct wmi_t *wmip,
                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
 {
@@ -3984,7 +3983,7 @@
     return (wmi_send_snr_threshold_params(wmip, snrCmd));
 }
 
-A_STATUS
+int
 wmi_clr_rssi_snr(struct wmi_t *wmip)
 {
     void    *osbuf;
@@ -3998,12 +3997,12 @@
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_lq_threshold_params(struct wmi_t *wmip,
                              WMI_LQ_THRESHOLD_PARAMS_CMD *lqCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_LQ_THRESHOLD_PARAMS_CMD *cmd;
     /* These values are in ascending order */
     if( lqCmd->thresholdAbove4_Val <= lqCmd->thresholdAbove3_Val ||
@@ -4027,17 +4026,17 @@
 
     cmd = (WMI_LQ_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
+    memcpy(cmd, lqCmd, sizeof(WMI_LQ_THRESHOLD_PARAMS_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_LQ_THRESHOLD_PARAMS_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_error_report_bitmask(struct wmi_t *wmip, A_UINT32 mask)
+int
+wmi_set_error_report_bitmask(struct wmi_t *wmip, u32 mask)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_TARGET_ERROR_REPORT_BITMASK *cmd;
 
     size = sizeof (*cmd);
@@ -4058,8 +4057,8 @@
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_get_challenge_resp_cmd(struct wmi_t *wmip, A_UINT32 cookie, A_UINT32 source)
+int
+wmi_get_challenge_resp_cmd(struct wmi_t *wmip, u32 cookie, u32 source)
 {
     void *osbuf;
     WMIX_HB_CHALLENGE_RESP_CMD *cmd;
@@ -4079,10 +4078,10 @@
                               NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_config_debug_module_cmd(struct wmi_t *wmip, A_UINT16 mmask,
-                            A_UINT16 tsr, A_BOOL rep, A_UINT16 size,
-                            A_UINT32 valid)
+int
+wmi_config_debug_module_cmd(struct wmi_t *wmip, u16 mmask,
+                            u16 tsr, bool rep, u16 size,
+                            u32 valid)
 {
     void *osbuf;
     WMIX_DBGLOG_CFG_MODULE_CMD *cmd;
@@ -4105,14 +4104,14 @@
                               NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_stats_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_STATISTICS_CMDID);
 }
 
-A_STATUS
-wmi_addBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex, A_UINT8 *bssid)
+int
+wmi_addBadAp_cmd(struct wmi_t *wmip, u8 apIndex, u8 *bssid)
 {
     void *osbuf;
     WMI_ADD_BAD_AP_CMD *cmd;
@@ -4130,13 +4129,13 @@
 
     cmd = (WMI_ADD_BAD_AP_CMD *)(A_NETBUF_DATA(osbuf));
     cmd->badApIndex = apIndex;
-    A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
+    memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_ADD_BAD_AP_CMDID, SYNC_BEFORE_WMIFLAG));
 }
 
-A_STATUS
-wmi_deleteBadAp_cmd(struct wmi_t *wmip, A_UINT8 apIndex)
+int
+wmi_deleteBadAp_cmd(struct wmi_t *wmip, u8 apIndex)
 {
     void *osbuf;
     WMI_DELETE_BAD_AP_CMD *cmd;
@@ -4159,14 +4158,14 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_abort_scan_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_ABORT_SCAN_CMDID);
 }
 
-A_STATUS
-wmi_set_txPwr_cmd(struct wmi_t *wmip, A_UINT8 dbM)
+int
+wmi_set_txPwr_cmd(struct wmi_t *wmip, u8 dbM)
 {
     void *osbuf;
     WMI_SET_TX_PWR_CMD *cmd;
@@ -4184,16 +4183,15 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_PWR_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_get_txPwr_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_TX_PWR_CMDID);
 }
 
-A_UINT16
-wmi_get_mapped_qos_queue(struct wmi_t *wmip, A_UINT8 trafficClass)
+u16 wmi_get_mapped_qos_queue(struct wmi_t *wmip, u8 trafficClass)
 {
-    A_UINT16 activeTsids=0;
+    u16 activeTsids=0;
 
     LOCK_WMI(wmip);
     activeTsids = wmip->wmi_streamExistsForAC[trafficClass];
@@ -4202,17 +4200,17 @@
     return activeTsids;
 }
 
-A_STATUS
+int
 wmi_get_roam_tbl_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd(wmip, WMI_GET_ROAM_TBL_CMDID);
 }
 
-A_STATUS
-wmi_get_roam_data_cmd(struct wmi_t *wmip, A_UINT8 roamDataType)
+int
+wmi_get_roam_data_cmd(struct wmi_t *wmip, u8 roamDataType)
 {
     void *osbuf;
-    A_UINT32 size = sizeof(A_UINT8);
+    u32 size = sizeof(u8);
     WMI_TARGET_ROAM_DATA *cmd;
 
     osbuf = A_NETBUF_ALLOC(size);      /* no payload */
@@ -4229,9 +4227,9 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_roam_ctrl_cmd(struct wmi_t *wmip, WMI_SET_ROAM_CTRL_CMD *p,
-                      A_UINT8 size)
+                      u8 size)
 {
     void *osbuf;
     WMI_SET_ROAM_CTRL_CMD *cmd;
@@ -4246,16 +4244,16 @@
     cmd = (WMI_SET_ROAM_CTRL_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
 
-    A_MEMCPY(cmd, p, size);
+    memcpy(cmd, p, size);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_ROAM_CTRL_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_powersave_timers_cmd(struct wmi_t *wmip,
                             WMI_POWERSAVE_TIMERS_POLICY_CMD *pCmd,
-                            A_UINT8 size)
+                            u8 size)
 {
     void *osbuf;
     WMI_POWERSAVE_TIMERS_POLICY_CMD *cmd;
@@ -4278,7 +4276,7 @@
     cmd = (WMI_POWERSAVE_TIMERS_POLICY_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
 
-    A_MEMCPY(cmd, pCmd, size);
+    memcpy(cmd, pCmd, size);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
                          NO_SYNC_WMIFLAG));
@@ -4286,12 +4284,12 @@
 
 #ifdef CONFIG_HOST_GPIO_SUPPORT
 /* Send a command to Target to change GPIO output pins. */
-A_STATUS
+int
 wmi_gpio_output_set(struct wmi_t *wmip,
-                    A_UINT32 set_mask,
-                    A_UINT32 clear_mask,
-                    A_UINT32 enable_mask,
-                    A_UINT32 disable_mask)
+                    u32 set_mask,
+                    u32 clear_mask,
+                    u32 enable_mask,
+                    u32 disable_mask)
 {
     void *osbuf;
     WMIX_GPIO_OUTPUT_SET_CMD *output_set;
@@ -4320,7 +4318,7 @@
 }
 
 /* Send a command to the Target requesting state of the GPIO input pins */
-A_STATUS
+int
 wmi_gpio_input_get(struct wmi_t *wmip)
 {
     A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
@@ -4329,10 +4327,10 @@
 }
 
 /* Send a command to the Target that changes the value of a GPIO register. */
-A_STATUS
+int
 wmi_gpio_register_set(struct wmi_t *wmip,
-                      A_UINT32 gpioreg_id,
-                      A_UINT32 value)
+                      u32 gpioreg_id,
+                      u32 value)
 {
     void *osbuf;
     WMIX_GPIO_REGISTER_SET_CMD *register_set;
@@ -4358,9 +4356,9 @@
 }
 
 /* Send a command to the Target to fetch the value of a GPIO register. */
-A_STATUS
+int
 wmi_gpio_register_get(struct wmi_t *wmip,
-                      A_UINT32 gpioreg_id)
+                      u32 gpioreg_id)
 {
     void *osbuf;
     WMIX_GPIO_REGISTER_GET_CMD *register_get;
@@ -4384,9 +4382,9 @@
 }
 
 /* Send a command to the Target acknowledging some GPIO interrupts. */
-A_STATUS
+int
 wmi_gpio_intr_ack(struct wmi_t *wmip,
-                  A_UINT32 ack_mask)
+                  u32 ack_mask)
 {
     void *osbuf;
     WMIX_GPIO_INTR_ACK_CMD *intr_ack;
@@ -4410,9 +4408,9 @@
 }
 #endif /* CONFIG_HOST_GPIO_SUPPORT */
 
-A_STATUS
-wmi_set_access_params_cmd(struct wmi_t *wmip, A_UINT8 ac,  A_UINT16 txop, A_UINT8 eCWmin,
-                          A_UINT8 eCWmax, A_UINT8 aifsn)
+int
+wmi_set_access_params_cmd(struct wmi_t *wmip, u8 ac,  u16 txop, u8 eCWmin,
+                          u8 eCWmax, u8 aifsn)
 {
     void *osbuf;
     WMI_SET_ACCESS_PARAMS_CMD *cmd;
@@ -4441,10 +4439,10 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_retry_limits_cmd(struct wmi_t *wmip, A_UINT8 frameType,
-                         A_UINT8 trafficClass, A_UINT8 maxRetries,
-                         A_UINT8 enableNotify)
+int
+wmi_set_retry_limits_cmd(struct wmi_t *wmip, u8 frameType,
+                         u8 trafficClass, u8 maxRetries,
+                         u8 enableNotify)
 {
     void *osbuf;
     WMI_SET_RETRY_LIMITS_CMD *cmd;
@@ -4481,15 +4479,15 @@
 }
 
 void
-wmi_get_current_bssid(struct wmi_t *wmip, A_UINT8 *bssid)
+wmi_get_current_bssid(struct wmi_t *wmip, u8 *bssid)
 {
     if (bssid != NULL) {
-        A_MEMCPY(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
+        memcpy(bssid, wmip->wmi_bssid, ATH_MAC_LEN);
     }
 }
 
-A_STATUS
-wmi_set_opt_mode_cmd(struct wmi_t *wmip, A_UINT8 optMode)
+int
+wmi_set_opt_mode_cmd(struct wmi_t *wmip, u8 optMode)
 {
     void *osbuf;
     WMI_SET_OPT_MODE_CMD *cmd;
@@ -4509,13 +4507,13 @@
                          SYNC_BOTH_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_opt_tx_frame_cmd(struct wmi_t *wmip,
-                      A_UINT8 frmType,
-                      A_UINT8 *dstMacAddr,
-                      A_UINT8 *bssid,
-                      A_UINT16 optIEDataLen,
-                      A_UINT8 *optIEData)
+                      u8 frmType,
+                      u8 *dstMacAddr,
+                      u8 *bssid,
+                      u16 optIEDataLen,
+                      u8 *optIEData)
 {
     void *osbuf;
     WMI_OPT_TX_FRAME_CMD *cmd;
@@ -4531,17 +4529,17 @@
 
     cmd->frmType    = frmType;
     cmd->optIEDataLen   = optIEDataLen;
-    //cmd->optIEData     = (A_UINT8 *)((int)cmd + sizeof(*cmd));
-    A_MEMCPY(cmd->bssid, bssid, sizeof(cmd->bssid));
-    A_MEMCPY(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
-    A_MEMCPY(&cmd->optIEData[0], optIEData, optIEDataLen);
+    //cmd->optIEData     = (u8 *)((int)cmd + sizeof(*cmd));
+    memcpy(cmd->bssid, bssid, sizeof(cmd->bssid));
+    memcpy(cmd->dstAddr, dstMacAddr, sizeof(cmd->dstAddr));
+    memcpy(&cmd->optIEData[0], optIEData, optIEDataLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_OPT_TX_FRAME_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, A_UINT16 intvl)
+int
+wmi_set_adhoc_bconIntvl_cmd(struct wmi_t *wmip, u16 intvl)
 {
     void *osbuf;
     WMI_BEACON_INT_CMD *cmd;
@@ -4562,8 +4560,8 @@
 }
 
 
-A_STATUS
-wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, A_UINT16 voicePktSize)
+int
+wmi_set_voice_pkt_size_cmd(struct wmi_t *wmip, u16 voicePktSize)
 {
     void *osbuf;
     WMI_SET_VOICE_PKT_SIZE_CMD *cmd;
@@ -4584,8 +4582,8 @@
 }
 
 
-A_STATUS
-wmi_set_max_sp_len_cmd(struct wmi_t *wmip, A_UINT8 maxSPLen)
+int
+wmi_set_max_sp_len_cmd(struct wmi_t *wmip, u8 maxSPLen)
 {
     void *osbuf;
     WMI_SET_MAX_SP_LEN_CMD *cmd;
@@ -4611,12 +4609,11 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_UINT8
-wmi_determine_userPriority(
-    A_UINT8 *pkt,
-    A_UINT32 layer2Pri)
+u8 wmi_determine_userPriority(
+    u8 *pkt,
+    u32 layer2Pri)
 {
-    A_UINT8 ipPri;
+    u8 ipPri;
     iphdr *ipHdr = (iphdr *)pkt;
 
     /* Determine IPTOS priority */
@@ -4632,27 +4629,25 @@
     ipPri &= 0x7;
 
     if ((layer2Pri & 0x7) > ipPri)
-        return ((A_UINT8)layer2Pri & 0x7);
+        return ((u8)layer2Pri & 0x7);
     else
         return ipPri;
 }
 
-A_UINT8
-convert_userPriority_to_trafficClass(A_UINT8 userPriority)
+u8 convert_userPriority_to_trafficClass(u8 userPriority)
 {
     return  (up_to_ac[userPriority & 0x7]);
 }
 
-A_UINT8
-wmi_get_power_mode_cmd(struct wmi_t *wmip)
+u8 wmi_get_power_mode_cmd(struct wmi_t *wmip)
 {
     return wmip->wmi_powerMode;
 }
 
-A_STATUS
-wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, A_BOOL tspecCompliance)
+int
+wmi_verify_tspec_params(WMI_CREATE_PSTREAM_CMD *pCmd, int tspecCompliance)
 {
-    A_STATUS ret = A_OK;
+    int ret = 0;
 
 #define TSPEC_SUSPENSION_INTERVAL_ATHEROS_DEF (~0)
 #define TSPEC_SERVICE_START_TIME_ATHEROS_DEF  0
@@ -4682,21 +4677,21 @@
 }
 
 #ifdef CONFIG_HOST_TCMD_SUPPORT
-static A_STATUS
-wmi_tcmd_test_report_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_tcmd_test_report_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
 
    A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
    A_WMI_TCMD_RX_REPORT_EVENT(wmip->wmi_devt, datap, len);
 
-   return A_OK;
+   return 0;
 }
 
 #endif /* CONFIG_HOST_TCMD_SUPPORT*/
 
-A_STATUS
-wmi_set_authmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
+int
+wmi_set_authmode_cmd(struct wmi_t *wmip, u8 mode)
 {
     void *osbuf;
     WMI_SET_AUTH_MODE_CMD *cmd;
@@ -4716,8 +4711,8 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_reassocmode_cmd(struct wmi_t *wmip, A_UINT8 mode)
+int
+wmi_set_reassocmode_cmd(struct wmi_t *wmip, u8 mode)
 {
     void *osbuf;
     WMI_SET_REASSOC_MODE_CMD *cmd;
@@ -4737,8 +4732,8 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_lpreamble_cmd(struct wmi_t *wmip, A_UINT8 status, A_UINT8 preamblePolicy)
+int
+wmi_set_lpreamble_cmd(struct wmi_t *wmip, u8 status, u8 preamblePolicy)
 {
     void *osbuf;
     WMI_SET_LPREAMBLE_CMD *cmd;
@@ -4759,8 +4754,8 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_rts_cmd(struct wmi_t *wmip, A_UINT16 threshold)
+int
+wmi_set_rts_cmd(struct wmi_t *wmip, u16 threshold)
 {
     void *osbuf;
     WMI_SET_RTS_CMD *cmd;
@@ -4780,7 +4775,7 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_wmm_cmd(struct wmi_t *wmip, WMI_WMM_STATUS status)
 {
     void *osbuf;
@@ -4802,8 +4797,8 @@
 
 }
 
-A_STATUS
-wmi_set_qos_supp_cmd(struct wmi_t *wmip, A_UINT8 status)
+int
+wmi_set_qos_supp_cmd(struct wmi_t *wmip, u8 status)
 {
     void *osbuf;
     WMI_SET_QOS_SUPP_CMD *cmd;
@@ -4823,7 +4818,7 @@
 }
 
 
-A_STATUS
+int
 wmi_set_wmm_txop(struct wmi_t *wmip, WMI_TXOP_CFG cfg)
 {
     void *osbuf;
@@ -4848,8 +4843,8 @@
 
 }
 
-A_STATUS
-wmi_set_country(struct wmi_t *wmip, A_UCHAR *countryCode)
+int
+wmi_set_country(struct wmi_t *wmip, u8 *countryCode)
 {
     void *osbuf;
     WMI_AP_SET_COUNTRY_CMD *cmd;
@@ -4863,7 +4858,7 @@
 
     cmd = (WMI_AP_SET_COUNTRY_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, sizeof(*cmd));
-    A_MEMCPY(cmd->countryCode,countryCode,3);
+    memcpy(cmd->countryCode,countryCode,3);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_COUNTRY_CMDID,
             NO_SYNC_WMIFLAG));
@@ -4872,10 +4867,10 @@
 #ifdef CONFIG_HOST_TCMD_SUPPORT
 /* WMI  layer doesn't need to know the data type of the test cmd.
    This would be beneficial for customers like Qualcomm, who might
-   have different test command requirements from differnt manufacturers
+   have different test command requirements from different manufacturers
  */
-A_STATUS
-wmi_test_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT32  len)
+int
+wmi_test_cmd(struct wmi_t *wmip, u8 *buf, u32 len)
 {
     void *osbuf;
     char *data;
@@ -4889,7 +4884,7 @@
     }
     A_NETBUF_PUT(osbuf, len);
     data = A_NETBUF_DATA(osbuf);
-    A_MEMCPY(data, buf, len);
+    memcpy(data, buf, len);
 
     return(wmi_cmd_send(wmip, osbuf, WMI_TEST_CMDID,
          NO_SYNC_WMIFLAG));
@@ -4897,8 +4892,8 @@
 
 #endif
 
-A_STATUS
-wmi_set_bt_status_cmd(struct wmi_t *wmip, A_UINT8 streamType, A_UINT8 status)
+int
+wmi_set_bt_status_cmd(struct wmi_t *wmip, u8 streamType, u8 status)
 {
     void *osbuf;
     WMI_SET_BT_STATUS_CMD *cmd;
@@ -4921,7 +4916,7 @@
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_bt_params_cmd(struct wmi_t *wmip, WMI_SET_BT_PARAMS_CMD* cmd)
 {
     void *osbuf;
@@ -4977,13 +4972,13 @@
 
     alloc_cmd = (WMI_SET_BT_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-    A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd));
+    memcpy(alloc_cmd, cmd, sizeof(*cmd));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BT_PARAMS_CMDID,
             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_btcoex_fe_ant_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_FE_ANT_CMD * cmd)
 {
 	void *osbuf;
@@ -4996,14 +4991,14 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_FE_ANT_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_FE_ANT_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_FE_ANT_CMDID,
                          NO_SYNC_WMIFLAG));
 
 }
 
 
-A_STATUS
+int
 wmi_set_btcoex_colocated_bt_dev_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD * cmd)
 {
@@ -5017,14 +5012,14 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-    A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
+    memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMD));
     A_PRINTF("colocated bt = %d\n", alloc_cmd->btcoexCoLocatedBTdev);
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_btinquiry_page_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD* cmd)
 {
@@ -5038,13 +5033,13 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_sco_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_SCO_CONFIG_CMD * cmd)
 {
@@ -5058,13 +5053,13 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_SCO_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_SCO_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_SCO_CONFIG_CMDID ,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_a2dp_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_A2DP_CONFIG_CMD * cmd)
 {
@@ -5078,13 +5073,13 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_A2DP_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_A2DP_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_A2DP_CONFIG_CMDID ,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_aclcoex_config_cmd(struct wmi_t *wmip,
 						WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD * cmd)
 {
@@ -5098,13 +5093,13 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
     alloc_cmd = (WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMD));
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID ,
                          NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_debug_cmd(struct wmi_t *wmip, WMI_SET_BTCOEX_DEBUG_CMD * cmd)
 {
 	void *osbuf;
@@ -5117,13 +5112,13 @@
 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
 	alloc_cmd = (WMI_SET_BTCOEX_DEBUG_CMD *)(A_NETBUF_DATA(osbuf));
 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_DEBUG_CMD));
 	return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_DEBUG_CMDID ,
 							 NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_set_btcoex_bt_operating_status_cmd(struct wmi_t * wmip,
 					WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD * cmd)
 {
@@ -5137,13 +5132,13 @@
 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
 	alloc_cmd = (WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD *)(A_NETBUF_DATA(osbuf));
 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMD));
 	return (wmi_cmd_send(wmip, osbuf, WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID ,
 								 NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_get_btcoex_config_cmd(struct wmi_t * wmip, WMI_GET_BTCOEX_CONFIG_CMD * cmd)
 {
 	void *osbuf;
@@ -5156,13 +5151,13 @@
 	A_NETBUF_PUT(osbuf, sizeof(*cmd));
 	alloc_cmd = (WMI_GET_BTCOEX_CONFIG_CMD *)(A_NETBUF_DATA(osbuf));
 	A_MEMZERO(alloc_cmd, sizeof(*cmd));
-	A_MEMCPY(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
+	memcpy(alloc_cmd,cmd,sizeof(WMI_GET_BTCOEX_CONFIG_CMD));
 	return (wmi_cmd_send(wmip, osbuf, WMI_GET_BTCOEX_CONFIG_CMDID ,
 							 NO_SYNC_WMIFLAG));
 
 }
 
-A_STATUS
+int
 wmi_get_btcoex_stats_cmd(struct wmi_t *wmip)
 {
 
@@ -5170,7 +5165,7 @@
 
 }
 
-A_STATUS
+int
 wmi_get_keepalive_configured(struct wmi_t *wmip)
 {
     void *osbuf;
@@ -5186,14 +5181,13 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_UINT8
-wmi_get_keepalive_cmd(struct wmi_t *wmip)
+u8 wmi_get_keepalive_cmd(struct wmi_t *wmip)
 {
     return wmip->wmi_keepaliveInterval;
 }
 
-A_STATUS
-wmi_set_keepalive_cmd(struct wmi_t *wmip, A_UINT8 keepaliveInterval)
+int
+wmi_set_keepalive_cmd(struct wmi_t *wmip, u8 keepaliveInterval)
 {
     void *osbuf;
     WMI_SET_KEEPALIVE_CMD *cmd;
@@ -5214,8 +5208,8 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_params_cmd(struct wmi_t *wmip, A_UINT32 opcode, A_UINT32 length, A_CHAR* buffer)
+int
+wmi_set_params_cmd(struct wmi_t *wmip, u32 opcode, u32 length, char *buffer)
 {
     void *osbuf;
     WMI_SET_PARAMS_CMD *cmd;
@@ -5231,15 +5225,15 @@
     A_MEMZERO(cmd, sizeof(*cmd));
     cmd->opcode = opcode;
     cmd->length = length;
-    A_MEMCPY(cmd->buffer, buffer, length);
+    memcpy(cmd->buffer, buffer, length);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PARAMS_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
 
-A_STATUS
-wmi_set_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4)
+int
+wmi_set_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
 {
     void *osbuf;
     WMI_SET_MCAST_FILTER_CMD *cmd;
@@ -5264,8 +5258,8 @@
 }
 
 
-A_STATUS
-wmi_del_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 dot1, A_UINT8 dot2, A_UINT8 dot3, A_UINT8 dot4)
+int
+wmi_del_mcast_filter_cmd(struct wmi_t *wmip, u8 dot1, u8 dot2, u8 dot3, u8 dot4)
 {
     void *osbuf;
     WMI_SET_MCAST_FILTER_CMD *cmd;
@@ -5289,8 +5283,8 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_mcast_filter_cmd(struct wmi_t *wmip, A_UINT8 enable)
+int
+wmi_mcast_filter_cmd(struct wmi_t *wmip, u8 enable)
 {
     void *osbuf;
     WMI_MCAST_FILTER_CMD *cmd;
@@ -5309,13 +5303,13 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_appie_cmd(struct wmi_t *wmip, A_UINT8 mgmtFrmType, A_UINT8 ieLen,
-                  A_UINT8 *ieInfo)
+int
+wmi_set_appie_cmd(struct wmi_t *wmip, u8 mgmtFrmType, u8 ieLen,
+                  u8 *ieInfo)
 {
     void *osbuf;
     WMI_SET_APPIE_CMD *cmd;
-    A_UINT16 cmdLen;
+    u16 cmdLen;
 
     cmdLen = sizeof(*cmd) + ieLen - 1;
     osbuf = A_NETBUF_ALLOC(cmdLen);
@@ -5330,16 +5324,16 @@
 
     cmd->mgmtFrmType = mgmtFrmType;
     cmd->ieLen = ieLen;
-    A_MEMCPY(cmd->ieInfo, ieInfo, ieLen);
+    memcpy(cmd->ieInfo, ieInfo, ieLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_APPIE_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_halparam_cmd(struct wmi_t *wmip, A_UINT8 *cmd, A_UINT16 dataLen)
+int
+wmi_set_halparam_cmd(struct wmi_t *wmip, u8 *cmd, u16 dataLen)
 {
     void *osbuf;
-    A_UINT8 *data;
+    u8 *data;
 
     osbuf = A_NETBUF_ALLOC(dataLen);
     if (osbuf == NULL) {
@@ -5350,18 +5344,17 @@
 
     data = A_NETBUF_DATA(osbuf);
 
-    A_MEMCPY(data, cmd, dataLen);
+    memcpy(data, cmd, dataLen);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_WHALPARAM_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_INT32
-wmi_get_rate(A_INT8 rateindex)
+s32 wmi_get_rate(s8 rateindex)
 {
     if (rateindex == RATE_AUTO) {
         return 0;
     } else {
-        return(wmi_rateTable[(A_UINT32) rateindex][0]);
+        return(wmi_rateTable[(u32) rateindex][0]);
     }
 }
 
@@ -5375,14 +5368,14 @@
 }
 
 void
-wmi_set_nodeage(struct wmi_t *wmip, A_UINT32 nodeAge)
+wmi_set_nodeage(struct wmi_t *wmip, u32 nodeAge)
 {
     wlan_set_nodeage(&wmip->wmi_scan_table,nodeAge);
 }
 
 bss_t *
-wmi_find_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength, A_BOOL bIsWPA2, A_BOOL bMatchSSID)
+wmi_find_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength, bool bIsWPA2, bool bMatchSSID)
 {
     bss_t *node = NULL;
     node = wlan_find_Ssidnode (&wmip->wmi_scan_table, pSsid,
@@ -5406,7 +5399,7 @@
 }
 
 bss_t *
-wmi_find_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
+wmi_find_node(struct wmi_t *wmip, const u8 *macaddr)
 {
     bss_t *ni=NULL;
     ni=wlan_find_node(&wmip->wmi_scan_table,macaddr);
@@ -5414,7 +5407,7 @@
 }
 
 void
-wmi_free_node(struct wmi_t *wmip, const A_UINT8 *macaddr)
+wmi_free_node(struct wmi_t *wmip, const u8 *macaddr)
 {
     bss_t *ni=NULL;
 
@@ -5426,15 +5419,15 @@
     return;
 }
 
-A_STATUS
+int
 wmi_dset_open_reply(struct wmi_t *wmip,
-                    A_UINT32 status,
-                    A_UINT32 access_cookie,
-                    A_UINT32 dset_size,
-                    A_UINT32 dset_version,
-                    A_UINT32 targ_handle,
-                    A_UINT32 targ_reply_fn,
-                    A_UINT32 targ_reply_arg)
+                    u32 status,
+                    u32 access_cookie,
+                    u32 dset_size,
+                    u32 dset_version,
+                    u32 targ_handle,
+                    u32 targ_reply_fn,
+                    u32 targ_reply_arg)
 {
     void *osbuf;
     WMIX_DSETOPEN_REPLY_CMD *open_reply;
@@ -5461,11 +5454,11 @@
                              NO_SYNC_WMIFLAG));
 }
 
-static A_STATUS
-wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
+static int
+wmi_get_pmkid_list_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
 {
     WMI_PMKID_LIST_REPLY *reply;
-    A_UINT32 expected_len;
+    u32 expected_len;
 
     if (len < sizeof(WMI_PMKID_LIST_REPLY)) {
         return A_EINVAL;
@@ -5480,12 +5473,12 @@
     A_WMI_PMKID_LIST_EVENT(wmip->wmi_devt, reply->numPMKID,
                            reply->pmkidList, reply->bssidList[0]);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_set_params_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
+static int
+wmi_set_params_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
 {
     WMI_SET_PARAMS_REPLY *reply;
 
@@ -5494,7 +5487,7 @@
     }
     reply = (WMI_SET_PARAMS_REPLY *)datap;
 
-    if (A_OK == reply->status)
+    if (0 == reply->status)
     {
 
     }
@@ -5503,36 +5496,36 @@
 
     }
 
-    return A_OK;
+    return 0;
 }
 
 
 
-static A_STATUS
-wmi_acm_reject_event_rx(struct wmi_t *wmip, A_UINT8 *datap, A_UINT32 len)
+static int
+wmi_acm_reject_event_rx(struct wmi_t *wmip, u8 *datap, u32 len)
 {
     WMI_ACM_REJECT_EVENT *ev;
 
     ev = (WMI_ACM_REJECT_EVENT *)datap;
     wmip->wmi_traffic_class = ev->trafficClass;
     printk("ACM REJECT %d\n",wmip->wmi_traffic_class);
-    return A_OK;
+    return 0;
 }
 
 
 #ifdef CONFIG_HOST_DSET_SUPPORT
-A_STATUS
+int
 wmi_dset_data_reply(struct wmi_t *wmip,
-                    A_UINT32 status,
-                    A_UINT8 *user_buf,
-                    A_UINT32 length,
-                    A_UINT32 targ_buf,
-                    A_UINT32 targ_reply_fn,
-                    A_UINT32 targ_reply_arg)
+                    u32 status,
+                    u8 *user_buf,
+                    u32 length,
+                    u32 targ_buf,
+                    u32 targ_reply_fn,
+                    u32 targ_reply_arg)
 {
     void *osbuf;
     WMIX_DSETDATA_REPLY_CMD *data_reply;
-    A_UINT32 size;
+    u32 size;
 
     size = sizeof(*data_reply) + length;
 
@@ -5556,7 +5549,7 @@
     data_reply->targ_reply_arg             = targ_reply_arg;
     data_reply->length                     = length;
 
-    if (status == A_OK) {
+    if (status == 0) {
         if (a_copy_from_user(data_reply->buf, user_buf, length)) {
             A_NETBUF_FREE(osbuf);
             return A_ERROR;
@@ -5568,8 +5561,8 @@
 }
 #endif /* CONFIG_HOST_DSET_SUPPORT */
 
-A_STATUS
-wmi_set_wsc_status_cmd(struct wmi_t *wmip, A_UINT32 status)
+int
+wmi_set_wsc_status_cmd(struct wmi_t *wmip, u32 status)
 {
     void *osbuf;
     char *cmd;
@@ -5592,10 +5585,10 @@
 }
 
 #if defined(CONFIG_TARGET_PROFILE_SUPPORT)
-A_STATUS
+int
 wmi_prof_cfg_cmd(struct wmi_t *wmip,
-                 A_UINT32 period,
-                 A_UINT32 nbins)
+                 u32 period,
+                 u32 nbins)
 {
     void *osbuf;
     WMIX_PROF_CFG_CMD *cmd;
@@ -5615,8 +5608,8 @@
     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_CFG_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_prof_addr_set_cmd(struct wmi_t *wmip, A_UINT32 addr)
+int
+wmi_prof_addr_set_cmd(struct wmi_t *wmip, u32 addr)
 {
     void *osbuf;
     WMIX_PROF_ADDR_SET_CMD *cmd;
@@ -5635,27 +5628,27 @@
     return (wmi_cmd_send_xtnd(wmip, osbuf, WMIX_PROF_ADDR_SET_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_prof_start_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_START_CMDID);
 }
 
-A_STATUS
+int
 wmi_prof_stop_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_STOP_CMDID);
 }
 
-A_STATUS
+int
 wmi_prof_count_get_cmd(struct wmi_t *wmip)
 {
     return wmi_simple_cmd_xtnd(wmip, WMIX_PROF_COUNT_GET_CMDID);
 }
 
 /* Called to handle WMIX_PROF_CONT_EVENTID */
-static A_STATUS
-wmi_prof_count_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_prof_count_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMIX_PROF_COUNT_EVENT *prof_data = (WMIX_PROF_COUNT_EVENT *)datap;
 
@@ -5665,7 +5658,7 @@
 
     A_WMI_PROF_COUNT_RX(prof_data->addr, prof_data->count);
 
-    return A_OK;
+    return 0;
 }
 #endif /* CONFIG_TARGET_PROFILE_SUPPORT */
 
@@ -5677,16 +5670,16 @@
 wmi_scan_indication (struct wmi_t *wmip)
 {
     struct ieee80211_node_table *nt;
-    A_UINT32 gen;
-    A_UINT32 size;
-    A_UINT32 bsssize;
+    u32 gen;
+    u32 size;
+    u32 bsssize;
     bss_t *bss;
-    A_UINT32 numbss;
+    u32 numbss;
     PNDIS_802_11_BSSID_SCAN_INFO psi;
     PBYTE  pie;
     NDIS_802_11_FIXED_IEs *pFixed;
     NDIS_802_11_VARIABLE_IEs *pVar;
-    A_UINT32  RateSize;
+    u32 RateSize;
 
     struct ar6kScanIndication
     {
@@ -5888,17 +5881,16 @@
 }
 #endif
 
-A_UINT8
-ar6000_get_upper_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
-                           A_UINT32 size)
+u8 ar6000_get_upper_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
+                           u32 size)
 {
-    A_UINT32 index;
-    A_UINT8 threshold = (A_UINT8)sq_thresh->upper_threshold[size - 1];
+    u32 index;
+    u8 threshold = (u8)sq_thresh->upper_threshold[size - 1];
 
     /* The list is already in sorted order. Get the next lower value */
     for (index = 0; index < size; index ++) {
         if (rssi < sq_thresh->upper_threshold[index]) {
-            threshold = (A_UINT8)sq_thresh->upper_threshold[index];
+            threshold = (u8)sq_thresh->upper_threshold[index];
             break;
         }
     }
@@ -5906,29 +5898,28 @@
     return threshold;
 }
 
-A_UINT8
-ar6000_get_lower_threshold(A_INT16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
-                           A_UINT32 size)
+u8 ar6000_get_lower_threshold(s16 rssi, SQ_THRESHOLD_PARAMS *sq_thresh,
+                           u32 size)
 {
-    A_UINT32 index;
-    A_UINT8 threshold = (A_UINT8)sq_thresh->lower_threshold[size - 1];
+    u32 index;
+    u8 threshold = (u8)sq_thresh->lower_threshold[size - 1];
 
     /* The list is already in sorted order. Get the next lower value */
     for (index = 0; index < size; index ++) {
         if (rssi > sq_thresh->lower_threshold[index]) {
-            threshold = (A_UINT8)sq_thresh->lower_threshold[index];
+            threshold = (u8)sq_thresh->lower_threshold[index];
             break;
         }
     }
 
     return threshold;
 }
-static A_STATUS
+static int
 wmi_send_rssi_threshold_params(struct wmi_t *wmip,
                               WMI_RSSI_THRESHOLD_PARAMS_CMD *rssiCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_RSSI_THRESHOLD_PARAMS_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -5942,17 +5933,17 @@
 
     cmd = (WMI_RSSI_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
+    memcpy(cmd, rssiCmd, sizeof(WMI_RSSI_THRESHOLD_PARAMS_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
                             NO_SYNC_WMIFLAG));
 }
-static A_STATUS
+static int
 wmi_send_snr_threshold_params(struct wmi_t *wmip,
                              WMI_SNR_THRESHOLD_PARAMS_CMD *snrCmd)
 {
     void    *osbuf;
-    A_INT8  size;
+    s8 size;
     WMI_SNR_THRESHOLD_PARAMS_CMD *cmd;
 
     size = sizeof (*cmd);
@@ -5965,13 +5956,13 @@
     A_NETBUF_PUT(osbuf, size);
     cmd = (WMI_SNR_THRESHOLD_PARAMS_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cmd, size);
-    A_MEMCPY(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
+    memcpy(cmd, snrCmd, sizeof(WMI_SNR_THRESHOLD_PARAMS_CMD));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SNR_THRESHOLD_PARAMS_CMDID,
                             NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
+int
 wmi_set_target_event_report_cmd(struct wmi_t *wmip, WMI_SET_TARGET_EVENT_REPORT_CMD* cmd)
 {
     void *osbuf;
@@ -5986,86 +5977,86 @@
 
     alloc_cmd = (WMI_SET_TARGET_EVENT_REPORT_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(alloc_cmd, sizeof(*cmd));
-    A_MEMCPY(alloc_cmd, cmd, sizeof(*cmd));
+    memcpy(alloc_cmd, cmd, sizeof(*cmd));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TARGET_EVENT_REPORT_CMDID,
             NO_SYNC_WMIFLAG));
 }
 
-bss_t *wmi_rm_current_bss (struct wmi_t *wmip, A_UINT8 *id)
+bss_t *wmi_rm_current_bss (struct wmi_t *wmip, u8 *id)
 {
     wmi_get_current_bssid (wmip, id);
     return wlan_node_remove (&wmip->wmi_scan_table, id);
 }
 
-A_STATUS wmi_add_current_bss (struct wmi_t *wmip, A_UINT8 *id, bss_t *bss)
+int wmi_add_current_bss (struct wmi_t *wmip, u8 *id, bss_t *bss)
 {
     wlan_setup_node (&wmip->wmi_scan_table, bss, id);
-    return A_OK;
+    return 0;
 }
 
 #ifdef ATH_AR6K_11N_SUPPORT
-static A_STATUS
-wmi_addba_req_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_addba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_ADDBA_REQ_EVENT *cmd = (WMI_ADDBA_REQ_EVENT *)datap;
 
     A_WMI_AGGR_RECV_ADDBA_REQ_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
 
-static A_STATUS
-wmi_addba_resp_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_addba_resp_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_ADDBA_RESP_EVENT *cmd = (WMI_ADDBA_RESP_EVENT *)datap;
 
     A_WMI_AGGR_RECV_ADDBA_RESP_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_delba_req_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_delba_req_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_DELBA_EVENT *cmd = (WMI_DELBA_EVENT *)datap;
 
     A_WMI_AGGR_RECV_DELBA_REQ_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
-A_STATUS
-wmi_btcoex_config_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+int
+wmi_btcoex_config_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
 	A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_BTCOEX_CONFIG_EVENT(wmip->wmi_devt, datap, len);
 
-     return A_OK;
+     return 0;
 }
 
 
-A_STATUS
-wmi_btcoex_stats_event_rx(struct wmi_t * wmip,A_UINT8 * datap,int len)
+int
+wmi_btcoex_stats_event_rx(struct wmi_t * wmip,u8 *datap,int len)
 {
 	A_DPRINTF(DBG_WMI, (DBGFMT "Enter\n", DBGARG));
 
     A_WMI_BTCOEX_STATS_EVENT(wmip->wmi_devt, datap, len);
 
-     return A_OK;
+     return 0;
 
 }
 #endif
 
-static A_STATUS
-wmi_hci_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_hci_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_HCI_EVENT *cmd = (WMI_HCI_EVENT *)datap;
     A_WMI_HCI_EVENT_EVT(wmip->wmi_devt, cmd);
 
-    return A_OK;
+    return 0;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -6083,7 +6074,7 @@
  * commit cmd will not be sent to target. Without calling this IOCTL
  * the changes will not take effect.
  */
-A_STATUS
+int
 wmi_ap_profile_commit(struct wmi_t *wmip, WMI_CONNECT_CMD *p)
 {
     void *osbuf;
@@ -6098,7 +6089,7 @@
     cm = (WMI_CONNECT_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(cm, sizeof(*cm));
 
-    A_MEMCPY(cm,p,sizeof(*cm));
+    memcpy(cm,p,sizeof(*cm));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONFIG_COMMIT_CMDID, NO_SYNC_WMIFLAG));
 }
@@ -6109,8 +6100,8 @@
  * This command will be used to enable/disable hidden ssid functioanlity of
  * beacon. If it is enabled, ssid will be NULL in beacon.
  */
-A_STATUS
-wmi_ap_set_hidden_ssid(struct wmi_t *wmip, A_UINT8 hidden_ssid)
+int
+wmi_ap_set_hidden_ssid(struct wmi_t *wmip, u8 hidden_ssid)
 {
     void *osbuf;
     WMI_AP_HIDDEN_SSID_CMD *hs;
@@ -6138,8 +6129,8 @@
  * is max num of STA supported by AP). Value was already validated
  * in ioctl.c
  */
-A_STATUS
-wmi_ap_set_num_sta(struct wmi_t *wmip, A_UINT8 num_sta)
+int
+wmi_ap_set_num_sta(struct wmi_t *wmip, u8 num_sta)
 {
     void *osbuf;
     WMI_AP_SET_NUM_STA_CMD *ns;
@@ -6166,7 +6157,7 @@
  * be allowed to connect with this AP. When this list is empty
  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
  */
-A_STATUS
+int
 wmi_ap_acl_mac_list(struct wmi_t *wmip, WMI_AP_ACL_MAC_CMD *acl)
 {
     void *osbuf;
@@ -6180,7 +6171,7 @@
     A_NETBUF_PUT(osbuf, sizeof(WMI_AP_ACL_MAC_CMD));
     a = (WMI_AP_ACL_MAC_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(a, sizeof(*a));
-    A_MEMCPY(a,acl,sizeof(*acl));
+    memcpy(a,acl,sizeof(*acl));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_MAC_LIST_CMDID, NO_SYNC_WMIFLAG));
 }
@@ -6192,8 +6183,8 @@
  * be allowed to connect with this AP. When this list is empty
  * firware will allow all STAs till the count reaches AP_MAX_NUM_STA.
  */
-A_STATUS
-wmi_ap_set_mlme(struct wmi_t *wmip, A_UINT8 cmd, A_UINT8 *mac, A_UINT16 reason)
+int
+wmi_ap_set_mlme(struct wmi_t *wmip, u8 cmd, u8 *mac, u16 reason)
 {
     void *osbuf;
     WMI_AP_SET_MLME_CMD *mlme;
@@ -6208,14 +6199,14 @@
     A_MEMZERO(mlme, sizeof(*mlme));
 
     mlme->cmd = cmd;
-    A_MEMCPY(mlme->mac, mac, ATH_MAC_LEN);
+    memcpy(mlme->mac, mac, ATH_MAC_LEN);
     mlme->reason = reason;
 
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_MLME_CMDID, NO_SYNC_WMIFLAG));
 }
 
-static A_STATUS
-wmi_pspoll_event_rx(struct wmi_t *wmip, A_UINT8 *datap, int len)
+static int
+wmi_pspoll_event_rx(struct wmi_t *wmip, u8 *datap, int len)
 {
     WMI_PSPOLL_EVENT *ev;
 
@@ -6225,34 +6216,34 @@
     ev = (WMI_PSPOLL_EVENT *)datap;
 
     A_WMI_PSPOLL_EVENT(wmip->wmi_devt, ev->aid);
-    return A_OK;
+    return 0;
 }
 
-static A_STATUS
-wmi_dtimexpiry_event_rx(struct wmi_t *wmip, A_UINT8 *datap,int len)
+static int
+wmi_dtimexpiry_event_rx(struct wmi_t *wmip, u8 *datap,int len)
 {
     A_WMI_DTIMEXPIRY_EVENT(wmip->wmi_devt);
-    return A_OK;
+    return 0;
 }
 
 #ifdef WAPI_ENABLE
-static A_STATUS
-wmi_wapi_rekey_event_rx(struct wmi_t *wmip, A_UINT8 *datap,int len)
+static int
+wmi_wapi_rekey_event_rx(struct wmi_t *wmip, u8 *datap,int len)
 {
-    A_UINT8 *ev;
+    u8 *ev;
 
     if (len < 7) {
         return A_EINVAL;
     }
-    ev = (A_UINT8 *)datap;
+    ev = (u8 *)datap;
 
     A_WMI_WAPI_REKEY_EVENT(wmip->wmi_devt, *ev, &ev[1]);
-    return A_OK;
+    return 0;
 }
 #endif
 
-A_STATUS
-wmi_set_pvb_cmd(struct wmi_t *wmip, A_UINT16 aid, A_BOOL flag)
+int
+wmi_set_pvb_cmd(struct wmi_t *wmip, u16 aid, bool flag)
 {
     WMI_AP_SET_PVB_CMD *cmd;
     void *osbuf = NULL;
@@ -6272,8 +6263,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_SET_PVB_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_conn_inact_time(struct wmi_t *wmip, A_UINT32 period)
+int
+wmi_ap_conn_inact_time(struct wmi_t *wmip, u32 period)
 {
     WMI_AP_CONN_INACT_CMD *cmd;
     void *osbuf = NULL;
@@ -6292,8 +6283,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_CONN_INACT_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_bgscan_time(struct wmi_t *wmip, A_UINT32 period, A_UINT32 dwell)
+int
+wmi_ap_bgscan_time(struct wmi_t *wmip, u32 period, u32 dwell)
 {
     WMI_AP_PROT_SCAN_TIME_CMD *cmd;
     void *osbuf = NULL;
@@ -6313,8 +6304,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_PROT_SCAN_TIME_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_set_dtim(struct wmi_t *wmip, A_UINT8 dtim)
+int
+wmi_ap_set_dtim(struct wmi_t *wmip, u8 dtim)
 {
     WMI_AP_SET_DTIM_CMD *cmd;
     void *osbuf = NULL;
@@ -6341,8 +6332,8 @@
  * OR with AP_ACL_RETAIN_LIST_MASK, else the existing list will be cleared.
  * If there is no chage in policy, the list will be intact.
  */
-A_STATUS
-wmi_ap_set_acl_policy(struct wmi_t *wmip, A_UINT8 policy)
+int
+wmi_ap_set_acl_policy(struct wmi_t *wmip, u8 policy)
 {
     void *osbuf;
     WMI_AP_ACL_POLICY_CMD *po;
@@ -6361,8 +6352,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_AP_ACL_POLICY_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_ap_set_rateset(struct wmi_t *wmip, A_UINT8 rateset)
+int
+wmi_ap_set_rateset(struct wmi_t *wmip, u8 rateset)
 {
     void *osbuf;
     WMI_AP_SET_11BG_RATESET_CMD *rs;
@@ -6382,12 +6373,12 @@
 }
 
 #ifdef ATH_AR6K_11N_SUPPORT
-A_STATUS
+int
 wmi_set_ht_cap_cmd(struct wmi_t *wmip, WMI_SET_HT_CAP_CMD *cmd)
 {
     void *osbuf;
     WMI_SET_HT_CAP_CMD *htCap;
-    A_UINT8 band;
+    u8 band;
 
     osbuf = A_NETBUF_ALLOC(sizeof(*htCap));
     if (osbuf == NULL) {
@@ -6401,14 +6392,14 @@
 
     htCap = (WMI_SET_HT_CAP_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(htCap, sizeof(*htCap));
-    A_MEMCPY(htCap, cmd, sizeof(*htCap));
+    memcpy(htCap, cmd, sizeof(*htCap));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_HT_CAP_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_ht_op_cmd(struct wmi_t *wmip, A_UINT8 sta_chan_width)
+int
+wmi_set_ht_op_cmd(struct wmi_t *wmip, u8 sta_chan_width)
 {
     void *osbuf;
     WMI_SET_HT_OP_CMD *htInfo;
@@ -6429,8 +6420,8 @@
 }
 #endif
 
-A_STATUS
-wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, A_UINT32 *pMaskArray)
+int
+wmi_set_tx_select_rates_cmd(struct wmi_t *wmip, u32 *pMaskArray)
 {
     void *osbuf;
     WMI_SET_TX_SELECT_RATES_CMD *pData;
@@ -6443,15 +6434,15 @@
     A_NETBUF_PUT(osbuf, sizeof(*pData));
 
     pData = (WMI_SET_TX_SELECT_RATES_CMD *)(A_NETBUF_DATA(osbuf));
-    A_MEMCPY(pData, pMaskArray, sizeof(*pData));
+    memcpy(pData, pMaskArray, sizeof(*pData));
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_TX_SELECT_RATES_CMDID,
                          NO_SYNC_WMIFLAG));
 }
 
 
-A_STATUS
-wmi_send_hci_cmd(struct wmi_t *wmip, A_UINT8 *buf, A_UINT16 sz)
+int
+wmi_send_hci_cmd(struct wmi_t *wmip, u8 *buf, u16 sz)
 {
     void *osbuf;
     WMI_HCI_CMD *cmd;
@@ -6465,13 +6456,13 @@
     cmd = (WMI_HCI_CMD *)(A_NETBUF_DATA(osbuf));
 
     cmd->cmd_buf_sz = sz;
-    A_MEMCPY(cmd->buf, buf, sz);
+    memcpy(cmd->buf, buf, sz);
     return (wmi_cmd_send(wmip, osbuf, WMI_HCI_CMD_CMDID, NO_SYNC_WMIFLAG));
 }
 
 #ifdef ATH_AR6K_11N_SUPPORT
-A_STATUS
-wmi_allow_aggr_cmd(struct wmi_t *wmip, A_UINT16 tx_tidmask, A_UINT16 rx_tidmask)
+int
+wmi_allow_aggr_cmd(struct wmi_t *wmip, u16 tx_tidmask, u16 rx_tidmask)
 {
     void *osbuf;
     WMI_ALLOW_AGGR_CMD *cmd;
@@ -6490,8 +6481,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_ALLOW_AGGR_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_setup_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid)
+int
+wmi_setup_aggr_cmd(struct wmi_t *wmip, u8 tid)
 {
     void *osbuf;
     WMI_ADDBA_REQ_CMD *cmd;
@@ -6509,8 +6500,8 @@
     return (wmi_cmd_send(wmip, osbuf, WMI_ADDBA_REQ_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_delete_aggr_cmd(struct wmi_t *wmip, A_UINT8 tid, A_BOOL uplink)
+int
+wmi_delete_aggr_cmd(struct wmi_t *wmip, u8 tid, bool uplink)
 {
     void *osbuf;
     WMI_DELBA_REQ_CMD *cmd;
@@ -6531,9 +6522,9 @@
 }
 #endif
 
-A_STATUS
-wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, A_UINT8 rxMetaVersion,
-                            A_BOOL rxDot11Hdr, A_BOOL defragOnHost)
+int
+wmi_set_rx_frame_format_cmd(struct wmi_t *wmip, u8 rxMetaVersion,
+                            bool rxDot11Hdr, bool defragOnHost)
 {
     void *osbuf;
     WMI_RX_FRAME_FORMAT_CMD *cmd;
@@ -6546,8 +6537,8 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_RX_FRAME_FORMAT_CMD *)(A_NETBUF_DATA(osbuf));
-    cmd->dot11Hdr = (rxDot11Hdr==TRUE)? 1:0;
-    cmd->defragOnHost = (defragOnHost==TRUE)? 1:0;
+    cmd->dot11Hdr = (rxDot11Hdr==true)? 1:0;
+    cmd->defragOnHost = (defragOnHost==true)? 1:0;
     cmd->metaVersion = rxMetaVersion;  /*  */
 
     /* Delete the local aggr state, on host */
@@ -6555,8 +6546,8 @@
 }
 
 
-A_STATUS
-wmi_set_thin_mode_cmd(struct wmi_t *wmip, A_BOOL bThinMode)
+int
+wmi_set_thin_mode_cmd(struct wmi_t *wmip, bool bThinMode)
 {
     void *osbuf;
     WMI_SET_THIN_MODE_CMD *cmd;
@@ -6569,14 +6560,14 @@
     A_NETBUF_PUT(osbuf, sizeof(*cmd));
 
     cmd = (WMI_SET_THIN_MODE_CMD *)(A_NETBUF_DATA(osbuf));
-    cmd->enable = (bThinMode==TRUE)? 1:0;
+    cmd->enable = (bThinMode==true)? 1:0;
 
     /* Delete the local aggr state, on host */
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_THIN_MODE_CMDID, NO_SYNC_WMIFLAG));
 }
 
 
-A_STATUS
+int
 wmi_set_wlan_conn_precedence_cmd(struct wmi_t *wmip, BT_WLAN_CONN_PRECEDENCE precedence)
 {
     void *osbuf;
@@ -6597,8 +6588,8 @@
                          NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_set_pmk_cmd(struct wmi_t *wmip, A_UINT8 *pmk)
+int
+wmi_set_pmk_cmd(struct wmi_t *wmip, u8 *pmk)
 {
     void *osbuf;
     WMI_SET_PMK_CMD *p;
@@ -6613,13 +6604,34 @@
     p = (WMI_SET_PMK_CMD *)(A_NETBUF_DATA(osbuf));
     A_MEMZERO(p, sizeof(*p));
 
-    A_MEMCPY(p->pmk, pmk, WMI_PMK_LEN);
+    memcpy(p->pmk, pmk, WMI_PMK_LEN);
 
     return (wmi_cmd_send(wmip, osbuf, WMI_SET_PMK_CMDID, NO_SYNC_WMIFLAG));
 }
 
-A_STATUS
-wmi_SGI_cmd(struct wmi_t *wmip, A_UINT32 sgiMask, A_UINT8 sgiPERThreshold)
+int
+wmi_set_excess_tx_retry_thres_cmd(struct wmi_t *wmip, WMI_SET_EXCESS_TX_RETRY_THRES_CMD *cmd)
+{
+    void *osbuf;
+    WMI_SET_EXCESS_TX_RETRY_THRES_CMD *p;
+
+    osbuf = A_NETBUF_ALLOC(sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
+    if (osbuf == NULL) {
+        return A_NO_MEMORY;
+    }
+
+    A_NETBUF_PUT(osbuf, sizeof(WMI_SET_EXCESS_TX_RETRY_THRES_CMD));
+
+    p = (WMI_SET_EXCESS_TX_RETRY_THRES_CMD *)(A_NETBUF_DATA(osbuf));
+    memset(p, 0, sizeof(*p));
+
+    p->threshold = cmd->threshold;
+
+    return (wmi_cmd_send(wmip, osbuf, WMI_SET_EXCESS_TX_RETRY_THRES_CMDID, NO_SYNC_WMIFLAG));
+}
+
+int
+wmi_SGI_cmd(struct wmi_t *wmip, u32 sgiMask, u8 sgiPERThreshold)
 {
     void *osbuf;
     WMI_SET_TX_SGI_PARAM_CMD *cmd;
@@ -6640,10 +6652,10 @@
 }
 
 bss_t *
-wmi_find_matching_Ssidnode (struct wmi_t *wmip, A_UCHAR *pSsid,
-                   A_UINT32 ssidLength,
-                   A_UINT32 dot11AuthMode, A_UINT32 authMode,
-                   A_UINT32 pairwiseCryptoType, A_UINT32 grpwiseCryptoTyp)
+wmi_find_matching_Ssidnode (struct wmi_t *wmip, u8 *pSsid,
+                   u32 ssidLength,
+                   u32 dot11AuthMode, u32 authMode,
+                   u32 pairwiseCryptoType, u32 grpwiseCryptoTyp)
 {
     bss_t *node = NULL;
     node = wlan_find_matching_Ssidnode (&wmip->wmi_scan_table, pSsid,
@@ -6652,19 +6664,17 @@
     return node;
 }
 
-A_UINT16
-wmi_ieee2freq (int chan)
+u16 wmi_ieee2freq (int chan)
 {
-    A_UINT16 freq = 0;
+    u16 freq = 0;
     freq = wlan_ieee2freq (chan);
     return freq;
 
 }
 
-A_UINT32
-wmi_freq2ieee (A_UINT16 freq)
+u32 wmi_freq2ieee (u16 freq)
 {
-    A_UINT16 chan = 0;
+    u16 chan = 0;
     chan = wlan_freq2ieee (freq);
     return chan;
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wmi/wmi_host.h linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wmi/wmi_host.h
--- linux-libre-2.6.38-gnu/drivers/staging/ath6kl/wmi/wmi_host.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/ath6kl/wmi/wmi_host.h	2011-05-19 00:06:34.000000000 -0400
@@ -31,8 +31,8 @@
 #endif
 
 struct wmi_stats {
-    A_UINT32    cmd_len_err;
-    A_UINT32    cmd_id_err;
+    u32 cmd_len_err;
+    u32 cmd_id_err;
 };
 
 #define SSID_IE_LEN_INDEX 13
@@ -42,14 +42,14 @@
 #define SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
 #define SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS SIGNAL_QUALITY_THRESHOLD_LEVELS
 typedef struct sq_threshold_params_s {
-    A_INT16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS];
-    A_INT16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS];
-    A_UINT32 upper_threshold_valid_count;
-    A_UINT32 lower_threshold_valid_count;
-    A_UINT32 polling_interval;
-    A_UINT8 weight;
-    A_UINT8  last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target.
-    A_UINT8  last_rssi_poll_event; //Not sure if it belongs to host or target
+    s16 upper_threshold[SIGNAL_QUALITY_UPPER_THRESHOLD_LEVELS];
+    s16 lower_threshold[SIGNAL_QUALITY_LOWER_THRESHOLD_LEVELS];
+    u32 upper_threshold_valid_count;
+    u32 lower_threshold_valid_count;
+    u32 polling_interval;
+    u8 weight;
+    u8 last_rssi; //normally you would expect this to be bss specific but we keep only one instance because its only valid when the device is in a connected state. Not sure if it belongs to host or target.
+    u8 last_rssi_poll_event; //Not sure if it belongs to host or target
 } SQ_THRESHOLD_PARAMS;
 
 /*
@@ -60,17 +60,17 @@
 #define A_NUM_BANDS            2
 
 struct wmi_t {
-    A_BOOL                          wmi_ready;
-    A_BOOL                          wmi_numQoSStream;
-    A_UINT16                        wmi_streamExistsForAC[WMM_NUM_AC];
-    A_UINT8                         wmi_fatPipeExists;
+    bool                          wmi_ready;
+    bool                          wmi_numQoSStream;
+    u16 wmi_streamExistsForAC[WMM_NUM_AC];
+    u8 wmi_fatPipeExists;
     void                           *wmi_devt;
     struct wmi_stats                wmi_stats;
     struct ieee80211_node_table     wmi_scan_table;
-    A_UINT8                         wmi_bssid[ATH_MAC_LEN];
-    A_UINT8                         wmi_powerMode;
-    A_UINT8                         wmi_phyMode;
-    A_UINT8                         wmi_keepaliveInterval;
+    u8 wmi_bssid[ATH_MAC_LEN];
+    u8 wmi_powerMode;
+    u8 wmi_phyMode;
+    u8 wmi_keepaliveInterval;
 #ifdef THREAD_X
     A_CSECT_T                       wmi_lock;
 #else 
@@ -80,9 +80,9 @@
     SQ_THRESHOLD_PARAMS             wmi_SqThresholdParams[SIGNAL_QUALITY_METRICS_NUM_MAX];
     CRYPTO_TYPE                     wmi_pair_crypto_type;
     CRYPTO_TYPE                     wmi_grp_crypto_type;
-    A_BOOL                          wmi_is_wmm_enabled;
-    A_UINT8                         wmi_ht_allowed[A_NUM_BANDS];
-    A_UINT8                         wmi_traffic_class;
+    bool                          wmi_is_wmm_enabled;
+    u8 wmi_ht_allowed[A_NUM_BANDS];
+    u8 wmi_traffic_class;
 };
 
 #ifdef THREAD_X
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/autofs_i.h linux-libre-2.6.39-gnu/drivers/staging/autofs/autofs_i.h
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/autofs_i.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/autofs_i.h	1969-12-31 19:00:00.000000000 -0500
@@ -1,165 +0,0 @@
-/* -*- linux-c -*- ------------------------------------------------------- *
- *   
- * drivers/staging/autofs/autofs_i.h
- *
- *   Copyright 1997-1998 Transmeta Corporation - All Rights Reserved
- *
- * 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.
- *
- * ----------------------------------------------------------------------- */
-
-/* Internal header file for autofs */
-
-#include <linux/auto_fs.h>
-
-/* This is the range of ioctl() numbers we claim as ours */
-#define AUTOFS_IOC_FIRST     AUTOFS_IOC_READY
-#define AUTOFS_IOC_COUNT     32
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/string.h>
-#include <linux/wait.h>
-#include <linux/dcache.h>
-#include <linux/namei.h>
-#include <linux/mount.h>
-#include <linux/sched.h>
-
-#include <asm/current.h>
-#include <asm/uaccess.h>
-
-#ifdef DEBUG
-#define DPRINTK(D) (printk D)
-#else
-#define DPRINTK(D) ((void)0)
-#endif
-
-/*
- * If the daemon returns a negative response (AUTOFS_IOC_FAIL) then the
- * kernel will keep the negative response cached for up to the time given
- * here, although the time can be shorter if the kernel throws the dcache
- * entry away.  This probably should be settable from user space.
- */
-#define AUTOFS_NEGATIVE_TIMEOUT (60*HZ)	/* 1 minute */
-
-/* Structures associated with the root directory hash table */
-
-#define AUTOFS_HASH_SIZE 67
-
-struct autofs_dir_ent {
-	int hash;
-	char *name;
-	int len;
-	ino_t ino;
-	struct dentry *dentry;
-	/* Linked list of entries */
-	struct autofs_dir_ent *next;
-	struct autofs_dir_ent **back;
-	/* The following entries are for the expiry system */
-	unsigned long last_usage;
-	struct list_head exp;
-};
-
-struct autofs_dirhash {
-	struct autofs_dir_ent *h[AUTOFS_HASH_SIZE];
-	struct list_head expiry_head;
-};
-
-struct autofs_wait_queue {
-	wait_queue_head_t queue;
-	struct autofs_wait_queue *next;
-	autofs_wqt_t wait_queue_token;
-	/* We use the following to see what we are waiting for */
-	int hash;
-	int len;
-	char *name;
-	/* This is for status reporting upon return */
-	int status;
-	int wait_ctr;
-};
-
-struct autofs_symlink {
-	char *data;
-	int len;
-	time_t mtime;
-};
-
-#define AUTOFS_MAX_SYMLINKS 256
-
-#define AUTOFS_ROOT_INO      1
-#define AUTOFS_FIRST_SYMLINK 2
-#define AUTOFS_FIRST_DIR_INO (AUTOFS_FIRST_SYMLINK+AUTOFS_MAX_SYMLINKS)
-
-#define AUTOFS_SYMLINK_BITMAP_LEN \
-	((AUTOFS_MAX_SYMLINKS+((sizeof(long)*1)-1))/(sizeof(long)*8))
-
-#define AUTOFS_SBI_MAGIC 0x6d4a556d
-
-struct autofs_sb_info {
-	u32 magic;
-	struct file *pipe;
-	struct pid *oz_pgrp;
-	int catatonic;
-	struct super_block *sb;
-	unsigned long exp_timeout;
-	ino_t next_dir_ino;
-	struct autofs_wait_queue *queues; /* Wait queue pointer */
-	struct autofs_dirhash dirhash; /* Root directory hash */
-	struct autofs_symlink symlink[AUTOFS_MAX_SYMLINKS];
-	unsigned long symlink_bitmap[AUTOFS_SYMLINK_BITMAP_LEN];
-};
-
-static inline struct autofs_sb_info *autofs_sbi(struct super_block *sb)
-{
-	return (struct autofs_sb_info *)(sb->s_fs_info);
-}
-
-/* autofs_oz_mode(): do we see the man behind the curtain?  (The
-   processes which do manipulations for us in user space sees the raw
-   filesystem without "magic".) */
-
-static inline int autofs_oz_mode(struct autofs_sb_info *sbi) {
-	return sbi->catatonic || task_pgrp(current) == sbi->oz_pgrp;
-}
-
-/* Hash operations */
-
-void autofs_initialize_hash(struct autofs_dirhash *);
-struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *,struct qstr *);
-void autofs_hash_insert(struct autofs_dirhash *,struct autofs_dir_ent *);
-void autofs_hash_delete(struct autofs_dir_ent *);
-struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *,off_t *,struct autofs_dir_ent *);
-void autofs_hash_dputall(struct autofs_dirhash *);
-void autofs_hash_nuke(struct autofs_sb_info *);
-
-/* Expiration-handling functions */
-
-void autofs_update_usage(struct autofs_dirhash *,struct autofs_dir_ent *);
-struct autofs_dir_ent *autofs_expire(struct super_block *,struct autofs_sb_info *, struct vfsmount *mnt);
-
-/* Operations structures */
-
-extern const struct inode_operations autofs_root_inode_operations;
-extern const struct inode_operations autofs_symlink_inode_operations;
-extern const struct file_operations autofs_root_operations;
-
-/* Initializing function */
-
-int autofs_fill_super(struct super_block *, void *, int);
-void autofs_kill_sb(struct super_block *sb);
-struct inode *autofs_iget(struct super_block *, unsigned long);
-
-/* Queue management functions */
-
-int autofs_wait(struct autofs_sb_info *,struct qstr *);
-int autofs_wait_release(struct autofs_sb_info *,autofs_wqt_t,int);
-void autofs_catatonic_mode(struct autofs_sb_info *);
-
-#ifdef DEBUG
-void autofs_say(const char *name, int len);
-#else
-#define autofs_say(n,l) ((void)0)
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/dirhash.c linux-libre-2.6.39-gnu/drivers/staging/autofs/dirhash.c
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/dirhash.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/dirhash.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,260 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/dirhash.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * 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.
- *
- * ------------------------------------------------------------------------- */
-
-#include "autofs_i.h"
-
-/* Functions for maintenance of expiry queue */
-
-static void autofs_init_usage(struct autofs_dirhash *dh,
-			      struct autofs_dir_ent *ent)
-{
-	list_add_tail(&ent->exp, &dh->expiry_head);
-	ent->last_usage = jiffies;
-}
-
-static void autofs_delete_usage(struct autofs_dir_ent *ent)
-{
-	list_del(&ent->exp);
-}
-
-void autofs_update_usage(struct autofs_dirhash *dh,
-			 struct autofs_dir_ent *ent)
-{
-	autofs_delete_usage(ent);   /* Unlink from current position */
-	autofs_init_usage(dh, ent);  /* Relink at queue tail */
-}
-
-struct autofs_dir_ent *autofs_expire(struct super_block *sb,
-				     struct autofs_sb_info *sbi,
-				     struct vfsmount *mnt)
-{
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	unsigned long timeout = sbi->exp_timeout;
-
-	while (1) {
-		struct path path;
-		int umount_ok;
-
-		if (list_empty(&dh->expiry_head) || sbi->catatonic)
-			return NULL;	/* No entries */
-		/* We keep the list sorted by last_usage and want old stuff */
-		ent = list_entry(dh->expiry_head.next,
-						struct autofs_dir_ent, exp);
-		if (jiffies - ent->last_usage < timeout)
-			break;
-		/* Move to end of list in case expiry isn't desirable */
-		autofs_update_usage(dh, ent);
-
-		/* Check to see that entry is expirable */
-		if (ent->ino < AUTOFS_FIRST_DIR_INO)
-			return ent; /* Symlinks are always expirable */
-
-		/* Get the dentry for the autofs subdirectory */
-		path.dentry = ent->dentry;
-
-		if (!path.dentry) {
-			/* Should only happen in catatonic mode */
-			printk(KERN_DEBUG "autofs: dentry == NULL but inode \
-				range is directory, entry %s\n", ent->name);
-			autofs_delete_usage(ent);
-			continue;
-		}
-
-		if (!path.dentry->d_inode) {
-			dput(path.dentry);
-			printk(KERN_DEBUG "autofs: negative dentry on expiry queue: %s\n",
-			       ent->name);
-			autofs_delete_usage(ent);
-			continue;
-		}
-
-		/* Make sure entry is mounted and unused; note that dentry will
-		   point to the mounted-on-top root. */
-		if (!S_ISDIR(path.dentry->d_inode->i_mode) ||
-		    !d_mountpoint(path.dentry)) {
-			DPRINTK(("autofs: not expirable \
-				(not a mounted directory): %s\n", ent->name));
-			continue;
-		}
-		path.mnt = mnt;
-		path_get(&path);
-		if (!follow_down_one(&path)) {
-			path_put(&path);
-			DPRINTK(("autofs: not expirable\
-			(not a mounted directory): %s\n", ent->name));
-			continue;
-		}
-		follow_down(&path, false);  // TODO: need to check error
-		umount_ok = may_umount(path.mnt);
-		path_put(&path);
-
-		if (umount_ok) {
-			DPRINTK(("autofs: signaling expire on %s\n",
-								ent->name));
-			return ent; /* Expirable! */
-		}
-
-		DPRINTK(("autofs: didn't expire due to may_umount: %s\n",
-								ent->name));
-	}
-	return NULL;		/* No expirable entries */
-}
-
-void autofs_initialize_hash(struct autofs_dirhash *dh)
-{
-	memset(&dh->h, 0, AUTOFS_HASH_SIZE*sizeof(struct autofs_dir_ent *));
-	INIT_LIST_HEAD(&dh->expiry_head);
-}
-
-struct autofs_dir_ent *autofs_hash_lookup(const struct autofs_dirhash *dh,
-						struct qstr *name)
-{
-	struct autofs_dir_ent *dhn;
-
-	DPRINTK(("autofs_hash_lookup: hash = 0x%08x, name = ", name->hash));
-	autofs_say(name->name, name->len);
-
-	for (dhn = dh->h[(unsigned) name->hash % AUTOFS_HASH_SIZE];
-		dhn;
-		dhn = dhn->next) {
-		if (name->hash == dhn->hash &&
-		     name->len == dhn->len &&
-		     !memcmp(name->name, dhn->name, name->len))
-			break;
-	}
-
-	return dhn;
-}
-
-void autofs_hash_insert(struct autofs_dirhash *dh, struct autofs_dir_ent *ent)
-{
-	struct autofs_dir_ent **dhnp;
-
-	DPRINTK(("autofs_hash_insert: hash = 0x%08x, name = ", ent->hash));
-	autofs_say(ent->name, ent->len);
-
-	autofs_init_usage(dh, ent);
-	if (ent->dentry)
-		dget(ent->dentry);
-
-	dhnp = &dh->h[(unsigned) ent->hash % AUTOFS_HASH_SIZE];
-	ent->next = *dhnp;
-	ent->back = dhnp;
-	*dhnp = ent;
-	if (ent->next)
-		ent->next->back = &(ent->next);
-}
-
-void autofs_hash_delete(struct autofs_dir_ent *ent)
-{
-	*(ent->back) = ent->next;
-	if (ent->next)
-		ent->next->back = ent->back;
-
-	autofs_delete_usage(ent);
-
-	if (ent->dentry)
-		dput(ent->dentry);
-	kfree(ent->name);
-	kfree(ent);
-}
-
-/*
- * Used by readdir().  We must validate "ptr", so we can't simply make it
- * a pointer.  Values below 0xffff are reserved; calling with any value
- * <= 0x10000 will return the first entry found.
- *
- * "last" can be NULL or the value returned by the last search *if* we
- * want the next sequential entry.
- */
-struct autofs_dir_ent *autofs_hash_enum(const struct autofs_dirhash *dh,
-					off_t *ptr, struct autofs_dir_ent *last)
-{
-	int bucket, ecount, i;
-	struct autofs_dir_ent *ent;
-
-	bucket = (*ptr >> 16) - 1;
-	ecount = *ptr & 0xffff;
-
-	if (bucket < 0)
-		bucket = ecount = 0;
-
-	DPRINTK(("autofs_hash_enum: bucket %d, entry %d\n", bucket, ecount));
-
-	ent = last ? last->next : NULL;
-
-	if (ent) {
-		ecount++;
-	} else {
-		while  (bucket < AUTOFS_HASH_SIZE) {
-			ent = dh->h[bucket];
-			for (i = ecount ; ent && i ; i--)
-				ent = ent->next;
-
-			if (ent) {
-				ecount++; /* Point to *next* entry */
-				break;
-			}
-
-			bucket++; ecount = 0;
-		}
-	}
-
-#ifdef DEBUG
-	if (!ent)
-		printk(KERN_DEBUG "autofs_hash_enum: nothing found\n");
-	else {
-		printk(KERN_DEBUG "autofs_hash_enum: found hash %08x, name",
-								ent->hash);
-		autofs_say(ent->name, ent->len);
-	}
-#endif
-
-	*ptr = ((bucket+1) << 16) + ecount;
-	return ent;
-}
-
-/* Iterate over all the ents, and remove all dentry pointers.  Used on
-   entering catatonic mode, in order to make the filesystem unmountable. */
-void autofs_hash_dputall(struct autofs_dirhash *dh)
-{
-	int i;
-	struct autofs_dir_ent *ent;
-
-	for (i = 0 ; i < AUTOFS_HASH_SIZE ; i++) {
-		for (ent = dh->h[i] ; ent ; ent = ent->next) {
-			if (ent->dentry) {
-				dput(ent->dentry);
-				ent->dentry = NULL;
-			}
-		}
-	}
-}
-
-/* Delete everything.  This is used on filesystem destruction, so we
-   make no attempt to keep the pointers valid */
-void autofs_hash_nuke(struct autofs_sb_info *sbi)
-{
-	int i;
-	struct autofs_dir_ent *ent, *nent;
-
-	for (i = 0 ; i < AUTOFS_HASH_SIZE ; i++) {
-		for (ent = sbi->dirhash.h[i] ; ent ; ent = nent) {
-			nent = ent->next;
-			if (ent->dentry)
-				dput(ent->dentry);
-			kfree(ent->name);
-			kfree(ent);
-		}
-	}
-}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/init.c linux-libre-2.6.39-gnu/drivers/staging/autofs/init.c
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/init.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/init.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,52 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/init.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * 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.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include "autofs_i.h"
-
-static struct dentry *autofs_mount(struct file_system_type *fs_type,
-	int flags, const char *dev_name, void *data)
-{
-	return mount_nodev(fs_type, flags, data, autofs_fill_super);
-}
-
-static struct file_system_type autofs_fs_type = {
-	.owner		= THIS_MODULE,
-	.name		= "autofs",
-	.mount		= autofs_mount,
-	.kill_sb	= autofs_kill_sb,
-};
-
-static int __init init_autofs_fs(void)
-{
-	return register_filesystem(&autofs_fs_type);
-}
-
-static void __exit exit_autofs_fs(void)
-{
-	unregister_filesystem(&autofs_fs_type);
-}
-
-module_init(init_autofs_fs);
-module_exit(exit_autofs_fs);
-
-#ifdef DEBUG
-void autofs_say(const char *name, int len)
-{
-	printk("(%d: ", len);
-	while ( len-- )
-		printk("%c", *name++);
-	printk(")\n");
-}
-#endif
-MODULE_LICENSE("GPL");
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/inode.c linux-libre-2.6.39-gnu/drivers/staging/autofs/inode.c
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/inode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/inode.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,288 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/inode.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * 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.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/file.h>
-#include <linux/parser.h>
-#include <linux/bitops.h>
-#include <linux/magic.h>
-#include "autofs_i.h"
-#include <linux/module.h>
-
-void autofs_kill_sb(struct super_block *sb)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(sb);
-	unsigned int n;
-
-	/*
-	 * In the event of a failure in get_sb_nodev the superblock
-	 * info is not present so nothing else has been setup, so
-	 * just call kill_anon_super when we are called from
-	 * deactivate_super.
-	 */
-	if (!sbi)
-		goto out_kill_sb;
-
-	if (!sbi->catatonic)
-		autofs_catatonic_mode(sbi); /* Free wait queues, close pipe */
-
-	put_pid(sbi->oz_pgrp);
-
-	autofs_hash_nuke(sbi);
-	for (n = 0; n < AUTOFS_MAX_SYMLINKS; n++) {
-		if (test_bit(n, sbi->symlink_bitmap))
-			kfree(sbi->symlink[n].data);
-	}
-
-	kfree(sb->s_fs_info);
-
-out_kill_sb:
-	DPRINTK(("autofs: shutting down\n"));
-	kill_anon_super(sb);
-}
-
-static const struct super_operations autofs_sops = {
-	.statfs		= simple_statfs,
-	.show_options	= generic_show_options,
-};
-
-enum {Opt_err, Opt_fd, Opt_uid, Opt_gid, Opt_pgrp, Opt_minproto, Opt_maxproto};
-
-static const match_table_t autofs_tokens = {
-	{Opt_fd, "fd=%u"},
-	{Opt_uid, "uid=%u"},
-	{Opt_gid, "gid=%u"},
-	{Opt_pgrp, "pgrp=%u"},
-	{Opt_minproto, "minproto=%u"},
-	{Opt_maxproto, "maxproto=%u"},
-	{Opt_err, NULL}
-};
-
-static int parse_options(char *options, int *pipefd, uid_t *uid, gid_t *gid,
-		pid_t *pgrp, int *minproto, int *maxproto)
-{
-	char *p;
-	substring_t args[MAX_OPT_ARGS];
-	int option;
-
-	*uid = current_uid();
-	*gid = current_gid();
-	*pgrp = task_pgrp_nr(current);
-
-	*minproto = *maxproto = AUTOFS_PROTO_VERSION;
-
-	*pipefd = -1;
-
-	if (!options)
-		return 1;
-
-	while ((p = strsep(&options, ",")) != NULL) {
-		int token;
-		if (!*p)
-			continue;
-
-		token = match_token(p, autofs_tokens, args);
-		switch (token) {
-		case Opt_fd:
-			if (match_int(&args[0], &option))
-				return 1;
-			*pipefd = option;
-			break;
-		case Opt_uid:
-			if (match_int(&args[0], &option))
-				return 1;
-			*uid = option;
-			break;
-		case Opt_gid:
-			if (match_int(&args[0], &option))
-				return 1;
-			*gid = option;
-			break;
-		case Opt_pgrp:
-			if (match_int(&args[0], &option))
-				return 1;
-			*pgrp = option;
-			break;
-		case Opt_minproto:
-			if (match_int(&args[0], &option))
-				return 1;
-			*minproto = option;
-			break;
-		case Opt_maxproto:
-			if (match_int(&args[0], &option))
-				return 1;
-			*maxproto = option;
-			break;
-		default:
-			return 1;
-		}
-	}
-	return (*pipefd < 0);
-}
-
-int autofs_fill_super(struct super_block *s, void *data, int silent)
-{
-	struct inode * root_inode;
-	struct dentry * root;
-	struct file * pipe;
-	int pipefd;
-	struct autofs_sb_info *sbi;
-	int minproto, maxproto;
-	pid_t pgid;
-
-	save_mount_options(s, data);
-
-	sbi = kzalloc(sizeof(*sbi), GFP_KERNEL);
-	if (!sbi)
-		goto fail_unlock;
-	DPRINTK(("autofs: starting up, sbi = %p\n",sbi));
-
-	s->s_fs_info = sbi;
-	sbi->magic = AUTOFS_SBI_MAGIC;
-	sbi->pipe = NULL;
-	sbi->catatonic = 1;
-	sbi->exp_timeout = 0;
-	autofs_initialize_hash(&sbi->dirhash);
-	sbi->queues = NULL;
-	memset(sbi->symlink_bitmap, 0, sizeof(long)*AUTOFS_SYMLINK_BITMAP_LEN);
-	sbi->next_dir_ino = AUTOFS_FIRST_DIR_INO;
-	s->s_blocksize = 1024;
-	s->s_blocksize_bits = 10;
-	s->s_magic = AUTOFS_SUPER_MAGIC;
-	s->s_op = &autofs_sops;
-	s->s_time_gran = 1;
-	sbi->sb = s;
-
-	root_inode = autofs_iget(s, AUTOFS_ROOT_INO);
-	if (IS_ERR(root_inode))
-		goto fail_free;
-	root = d_alloc_root(root_inode);
-	pipe = NULL;
-
-	if (!root)
-		goto fail_iput;
-
-	/* Can this call block?  - WTF cares? s is locked. */
-	if (parse_options(data, &pipefd, &root_inode->i_uid,
-				&root_inode->i_gid, &pgid, &minproto,
-				&maxproto)) {
-		printk("autofs: called with bogus options\n");
-		goto fail_dput;
-	}
-
-	/* Couldn't this be tested earlier? */
-	if (minproto > AUTOFS_PROTO_VERSION ||
-	     maxproto < AUTOFS_PROTO_VERSION) {
-		printk("autofs: kernel does not match daemon version\n");
-		goto fail_dput;
-	}
-
-	DPRINTK(("autofs: pipe fd = %d, pgrp = %u\n", pipefd, pgid));
-	sbi->oz_pgrp = find_get_pid(pgid);
-
-	if (!sbi->oz_pgrp) {
-		printk("autofs: could not find process group %d\n", pgid);
-		goto fail_dput;
-	}
-
-	pipe = fget(pipefd);
-	
-	if (!pipe) {
-		printk("autofs: could not open pipe file descriptor\n");
-		goto fail_put_pid;
-	}
-
-	if (!pipe->f_op || !pipe->f_op->write)
-		goto fail_fput;
-	sbi->pipe = pipe;
-	sbi->catatonic = 0;
-
-	/*
-	 * Success! Install the root dentry now to indicate completion.
-	 */
-	s->s_root = root;
-	return 0;
-
-fail_fput:
-	printk("autofs: pipe file descriptor does not contain proper ops\n");
-	fput(pipe);
-fail_put_pid:
-	put_pid(sbi->oz_pgrp);
-fail_dput:
-	dput(root);
-	goto fail_free;
-fail_iput:
-	printk("autofs: get root dentry failed\n");
-	iput(root_inode);
-fail_free:
-	kfree(sbi);
-	s->s_fs_info = NULL;
-fail_unlock:
-	return -EINVAL;
-}
-
-struct inode *autofs_iget(struct super_block *sb, unsigned long ino)
-{
-	unsigned int n;
-	struct autofs_sb_info *sbi = autofs_sbi(sb);
-	struct inode *inode;
-
-	inode = iget_locked(sb, ino);
-	if (!inode)
-		return ERR_PTR(-ENOMEM);
-	if (!(inode->i_state & I_NEW))
-		return inode;
-
-	/* Initialize to the default case (stub directory) */
-
-	inode->i_op = &simple_dir_inode_operations;
-	inode->i_fop = &simple_dir_operations;
-	inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO;
-	inode->i_nlink = 2;
-	inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-
-	if (ino == AUTOFS_ROOT_INO) {
-		inode->i_mode = S_IFDIR | S_IRUGO | S_IXUGO | S_IWUSR;
-		inode->i_op = &autofs_root_inode_operations;
-		inode->i_fop = &autofs_root_operations;
-		goto done;
-	} 
-	
-	inode->i_uid = inode->i_sb->s_root->d_inode->i_uid;
-	inode->i_gid = inode->i_sb->s_root->d_inode->i_gid;
-	
-	if (ino >= AUTOFS_FIRST_SYMLINK && ino < AUTOFS_FIRST_DIR_INO) {
-		/* Symlink inode - should be in symlink list */
-		struct autofs_symlink *sl;
-
-		n = ino - AUTOFS_FIRST_SYMLINK;
-		if (n >= AUTOFS_MAX_SYMLINKS || !test_bit(n,sbi->symlink_bitmap)) {
-			printk("autofs: Looking for bad symlink inode %u\n", (unsigned int) ino);
-			goto done;
-		}
-		
-		inode->i_op = &autofs_symlink_inode_operations;
-		sl = &sbi->symlink[n];
-		inode->i_private = sl;
-		inode->i_mode = S_IFLNK | S_IRWXUGO;
-		inode->i_mtime.tv_sec = inode->i_ctime.tv_sec = sl->mtime;
-		inode->i_mtime.tv_nsec = inode->i_ctime.tv_nsec = 0;
-		inode->i_size = sl->len;
-		inode->i_nlink = 1;
-	}
-
-done:
-	unlock_new_inode(inode);
-	return inode;
-}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/Kconfig linux-libre-2.6.39-gnu/drivers/staging/autofs/Kconfig
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,22 +0,0 @@
-config AUTOFS_FS
-	tristate "Kernel automounter support"
-	depends on BKL # unfixable, just use autofs4
-	help
-	  The automounter is a tool to automatically mount remote file systems
-	  on demand. This implementation is partially kernel-based to reduce
-	  overhead in the already-mounted case; this is unlike the BSD
-	  automounter (amd), which is a pure user space daemon.
-
-	  To use the automounter you need the user-space tools from the autofs
-	  package; you can find the location in <file:Documentation/Changes>.
-	  You also want to answer Y to "NFS file system support", below.
-
-	  If you want to use the newer version of the automounter with more
-	  features, say N here and say Y to "Kernel automounter v4 support",
-	  below.
-
-	  To compile this support as a module, choose M here: the module will be
-	  called autofs.
-
-	  If you are not a part of a fairly large, distributed network, you
-	  probably do not need an automounter, and can say N here.
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/Makefile linux-libre-2.6.39-gnu/drivers/staging/autofs/Makefile
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/Makefile	1969-12-31 19:00:00.000000000 -0500
@@ -1,7 +0,0 @@
-#
-# Makefile for the linux autofs-filesystem routines.
-#
-
-obj-$(CONFIG_AUTOFS_FS) += autofs.o
-
-autofs-y := dirhash.o init.o inode.o root.o symlink.o waitq.o
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/root.c linux-libre-2.6.39-gnu/drivers/staging/autofs/root.c
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/root.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/root.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,648 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/root.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * 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.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/capability.h>
-#include <linux/errno.h>
-#include <linux/stat.h>
-#include <linux/slab.h>
-#include <linux/param.h>
-#include <linux/time.h>
-#include <linux/compat.h>
-#include <linux/smp_lock.h>
-#include "autofs_i.h"
-
-static int autofs_root_readdir(struct file *,void *,filldir_t);
-static struct dentry *autofs_root_lookup(struct inode *,struct dentry *, struct nameidata *);
-static int autofs_root_symlink(struct inode *,struct dentry *,const char *);
-static int autofs_root_unlink(struct inode *,struct dentry *);
-static int autofs_root_rmdir(struct inode *,struct dentry *);
-static int autofs_root_mkdir(struct inode *,struct dentry *,int);
-static long autofs_root_ioctl(struct file *,unsigned int,unsigned long);
-#ifdef CONFIG_COMPAT
-static long autofs_root_compat_ioctl(struct file *,unsigned int,unsigned long);
-#endif
-
-const struct file_operations autofs_root_operations = {
-	.llseek		= generic_file_llseek,
-	.read		= generic_read_dir,
-	.readdir	= autofs_root_readdir,
-	.unlocked_ioctl	= autofs_root_ioctl,
-#ifdef CONFIG_COMPAT
-	.compat_ioctl	= autofs_root_compat_ioctl,
-#endif
-};
-
-const struct inode_operations autofs_root_inode_operations = {
-        .lookup		= autofs_root_lookup,
-        .unlink		= autofs_root_unlink,
-        .symlink	= autofs_root_symlink,
-        .mkdir		= autofs_root_mkdir,
-        .rmdir		= autofs_root_rmdir,
-};
-
-static int autofs_root_readdir(struct file *filp, void *dirent, filldir_t filldir)
-{
-	struct autofs_dir_ent *ent = NULL;
-	struct autofs_dirhash *dirhash;
-	struct autofs_sb_info *sbi;
-	struct inode * inode = filp->f_path.dentry->d_inode;
-	off_t onr, nr;
-
-	lock_kernel();
-
-	sbi = autofs_sbi(inode->i_sb);
-	dirhash = &sbi->dirhash;
-	nr = filp->f_pos;
-
-	switch(nr)
-	{
-	case 0:
-		if (filldir(dirent, ".", 1, nr, inode->i_ino, DT_DIR) < 0)
-			goto out;
-		filp->f_pos = ++nr;
-		/* fall through */
-	case 1:
-		if (filldir(dirent, "..", 2, nr, inode->i_ino, DT_DIR) < 0)
-			goto out;
-		filp->f_pos = ++nr;
-		/* fall through */
-	default:
-		while (onr = nr, ent = autofs_hash_enum(dirhash,&nr,ent)) {
-			if (!ent->dentry || d_mountpoint(ent->dentry)) {
-				if (filldir(dirent,ent->name,ent->len,onr,ent->ino,DT_UNKNOWN) < 0)
-					goto out;
-				filp->f_pos = nr;
-			}
-		}
-		break;
-	}
-
-out:
-	unlock_kernel();
-	return 0;
-}
-
-static int try_to_fill_dentry(struct dentry *dentry, struct super_block *sb, struct autofs_sb_info *sbi)
-{
-	struct inode * inode;
-	struct autofs_dir_ent *ent;
-	int status = 0;
-
-	if (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name))) {
-		do {
-			if (status && dentry->d_inode) {
-				if (status != -ENOENT)
-					printk("autofs warning: lookup failure on positive dentry, status = %d, name = %s\n", status, dentry->d_name.name);
-				return 0; /* Try to get the kernel to invalidate this dentry */
-			}
-
-			/* Turn this into a real negative dentry? */
-			if (status == -ENOENT) {
-				dentry->d_time = jiffies + AUTOFS_NEGATIVE_TIMEOUT;
-				dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-				return 1;
-			} else if (status) {
-				/* Return a negative dentry, but leave it "pending" */
-				return 1;
-			}
-			status = autofs_wait(sbi, &dentry->d_name);
-		} while (!(ent = autofs_hash_lookup(&sbi->dirhash, &dentry->d_name)));
-	}
-
-	/* Abuse this field as a pointer to the directory entry, used to
-	   find the expire list pointers */
-	dentry->d_time = (unsigned long) ent;
-	
-	if (!dentry->d_inode) {
-		inode = autofs_iget(sb, ent->ino);
-		if (IS_ERR(inode)) {
-			/* Failed, but leave pending for next time */
-			return 1;
-		}
-		dentry->d_inode = inode;
-	}
-
-	/* If this is a directory that isn't a mount point, bitch at the
-	   daemon and fix it in user space */
-	if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
-		return !autofs_wait(sbi, &dentry->d_name);
-	}
-
-	/* We don't update the usages for the autofs daemon itself, this
-	   is necessary for recursive autofs mounts */
-	if (!autofs_oz_mode(sbi)) {
-		autofs_update_usage(&sbi->dirhash,ent);
-	}
-
-	dentry->d_flags &= ~DCACHE_AUTOFS_PENDING;
-	return 1;
-}
-
-
-/*
- * Revalidate is called on every cache lookup.  Some of those
- * cache lookups may actually happen while the dentry is not
- * yet completely filled in, and revalidate has to delay such
- * lookups..
- */
-static int autofs_revalidate(struct dentry *dentry, struct nameidata *nd)
-{
-	struct inode * dir;
-	struct autofs_sb_info *sbi;
-	struct autofs_dir_ent *ent;
-	int res;
-
-	if (nd->flags & LOOKUP_RCU)
-		return -ECHILD;
-
-	lock_kernel();
-	dir = dentry->d_parent->d_inode;
-	sbi = autofs_sbi(dir->i_sb);
-
-	/* Pending dentry */
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
-		if (autofs_oz_mode(sbi))
-			res = 1;
-		else
-			res = try_to_fill_dentry(dentry, dir->i_sb, sbi);
-		unlock_kernel();
-		return res;
-	}
-
-	/* Negative dentry.. invalidate if "old" */
-	if (!dentry->d_inode) {
-		unlock_kernel();
-		return (dentry->d_time - jiffies <= AUTOFS_NEGATIVE_TIMEOUT);
-	}
-		
-	/* Check for a non-mountpoint directory */
-	if (S_ISDIR(dentry->d_inode->i_mode) && !d_mountpoint(dentry)) {
-		if (autofs_oz_mode(sbi))
-			res = 1;
-		else
-			res = try_to_fill_dentry(dentry, dir->i_sb, sbi);
-		unlock_kernel();
-		return res;
-	}
-
-	/* Update the usage list */
-	if (!autofs_oz_mode(sbi)) {
-		ent = (struct autofs_dir_ent *) dentry->d_time;
-		if (ent)
-			autofs_update_usage(&sbi->dirhash,ent);
-	}
-	unlock_kernel();
-	return 1;
-}
-
-static const struct dentry_operations autofs_dentry_operations = {
-	.d_revalidate	= autofs_revalidate,
-};
-
-static struct dentry *autofs_root_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd)
-{
-	struct autofs_sb_info *sbi;
-	int oz_mode;
-
-	DPRINTK(("autofs_root_lookup: name = "));
-	lock_kernel();
-	autofs_say(dentry->d_name.name,dentry->d_name.len);
-
-	if (dentry->d_name.len > NAME_MAX) {
-		unlock_kernel();
-		return ERR_PTR(-ENAMETOOLONG);/* File name too long to exist */
-	}
-
-	sbi = autofs_sbi(dir->i_sb);
-
-	oz_mode = autofs_oz_mode(sbi);
-	DPRINTK(("autofs_lookup: pid = %u, pgrp = %u, catatonic = %d, "
-				"oz_mode = %d\n", task_pid_nr(current),
-				task_pgrp_nr(current), sbi->catatonic,
-				oz_mode));
-
-	/*
-	 * Mark the dentry incomplete, but add it. This is needed so
-	 * that the VFS layer knows about the dentry, and we can count
-	 * on catching any lookups through the revalidate.
-	 *
-	 * Let all the hard work be done by the revalidate function that
-	 * needs to be able to do this anyway..
-	 *
-	 * We need to do this before we release the directory semaphore.
-	 */
-	d_set_d_op(dentry, &autofs_dentry_operations);
-	dentry->d_flags |= DCACHE_AUTOFS_PENDING;
-	d_add(dentry, NULL);
-
-	mutex_unlock(&dir->i_mutex);
-	autofs_revalidate(dentry, nd);
-	mutex_lock(&dir->i_mutex);
-
-	/*
-	 * If we are still pending, check if we had to handle
-	 * a signal. If so we can force a restart..
-	 */
-	if (dentry->d_flags & DCACHE_AUTOFS_PENDING) {
-		/* See if we were interrupted */
-		if (signal_pending(current)) {
-			sigset_t *sigset = &current->pending.signal;
-			if (sigismember (sigset, SIGKILL) ||
-			    sigismember (sigset, SIGQUIT) ||
-			    sigismember (sigset, SIGINT)) {
-				unlock_kernel();
-				return ERR_PTR(-ERESTARTNOINTR);
-			}
-		}
-	}
-	unlock_kernel();
-
-	/*
-	 * If this dentry is unhashed, then we shouldn't honour this
-	 * lookup even if the dentry is positive.  Returning ENOENT here
-	 * doesn't do the right thing for all system calls, but it should
-	 * be OK for the operations we permit from an autofs.
-	 */
-	if (dentry->d_inode && d_unhashed(dentry))
-		return ERR_PTR(-ENOENT);
-
-	return NULL;
-}
-
-static int autofs_root_symlink(struct inode *dir, struct dentry *dentry, const char *symname)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	unsigned int n;
-	int slsize;
-	struct autofs_symlink *sl;
-	struct inode *inode;
-
-	DPRINTK(("autofs_root_symlink: %s <- ", symname));
-	autofs_say(dentry->d_name.name,dentry->d_name.len);
-
-	lock_kernel();
-	if (!autofs_oz_mode(sbi)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	if (autofs_hash_lookup(dh, &dentry->d_name)) {
-		unlock_kernel();
-		return -EEXIST;
-	}
-
-	n = find_first_zero_bit(sbi->symlink_bitmap,AUTOFS_MAX_SYMLINKS);
-	if (n >= AUTOFS_MAX_SYMLINKS) {
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	set_bit(n,sbi->symlink_bitmap);
-	sl = &sbi->symlink[n];
-	sl->len = strlen(symname);
-	sl->data = kmalloc(slsize = sl->len+1, GFP_KERNEL);
-	if (!sl->data) {
-		clear_bit(n,sbi->symlink_bitmap);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if (!ent) {
-		kfree(sl->data);
-		clear_bit(n,sbi->symlink_bitmap);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
-	if (!ent->name) {
-		kfree(sl->data);
-		kfree(ent);
-		clear_bit(n,sbi->symlink_bitmap);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	memcpy(sl->data,symname,slsize);
-	sl->mtime = get_seconds();
-
-	ent->ino = AUTOFS_FIRST_SYMLINK + n;
-	ent->hash = dentry->d_name.hash;
-	memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len));
-	ent->dentry = NULL;	/* We don't keep the dentry for symlinks */
-
-	autofs_hash_insert(dh,ent);
-
-	inode = autofs_iget(dir->i_sb, ent->ino);
-	if (IS_ERR(inode))
-		return PTR_ERR(inode);
-
-	d_instantiate(dentry, inode);
-	unlock_kernel();
-	return 0;
-}
-
-/*
- * NOTE!
- *
- * Normal filesystems would do a "d_delete()" to tell the VFS dcache
- * that the file no longer exists. However, doing that means that the
- * VFS layer can turn the dentry into a negative dentry, which we
- * obviously do not want (we're dropping the entry not because it
- * doesn't exist, but because it has timed out).
- *
- * Also see autofs_root_rmdir()..
- */
-static int autofs_root_unlink(struct inode *dir, struct dentry *dentry)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	unsigned int n;
-
-	/* This allows root to remove symlinks */
-	lock_kernel();
-	if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if (!ent) {
-		unlock_kernel();
-		return -ENOENT;
-	}
-
-	n = ent->ino - AUTOFS_FIRST_SYMLINK;
-	if (n >= AUTOFS_MAX_SYMLINKS) {
-		unlock_kernel();
-		return -EISDIR;	/* It's a directory, dummy */
-	}
-	if (!test_bit(n,sbi->symlink_bitmap)) {
-		unlock_kernel();
-		return -EINVAL;	/* Nonexistent symlink?  Shouldn't happen */
-	}
-	
-	dentry->d_time = (unsigned long)(struct autofs_dirhash *)NULL;
-	autofs_hash_delete(ent);
-	clear_bit(n,sbi->symlink_bitmap);
-	kfree(sbi->symlink[n].data);
-	d_drop(dentry);
-	
-	unlock_kernel();
-	return 0;
-}
-
-static int autofs_root_rmdir(struct inode *dir, struct dentry *dentry)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-
-	lock_kernel();
-	if (!autofs_oz_mode(sbi)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if (!ent) {
-		unlock_kernel();
-		return -ENOENT;
-	}
-
-	if ((unsigned int)ent->ino < AUTOFS_FIRST_DIR_INO) {
-		unlock_kernel();
-		return -ENOTDIR; /* Not a directory */
-	}
-
-	if (ent->dentry != dentry) {
-		printk("autofs_rmdir: odentry != dentry for entry %s\n", dentry->d_name.name);
-	}
-
-	dentry->d_time = (unsigned long)(struct autofs_dir_ent *)NULL;
-	autofs_hash_delete(ent);
-	drop_nlink(dir);
-	d_drop(dentry);
-	unlock_kernel();
-
-	return 0;
-}
-
-static int autofs_root_mkdir(struct inode *dir, struct dentry *dentry, int mode)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(dir->i_sb);
-	struct autofs_dirhash *dh = &sbi->dirhash;
-	struct autofs_dir_ent *ent;
-	struct inode *inode;
-	ino_t ino;
-
-	lock_kernel();
-	if (!autofs_oz_mode(sbi)) {
-		unlock_kernel();
-		return -EACCES;
-	}
-
-	ent = autofs_hash_lookup(dh, &dentry->d_name);
-	if (ent) {
-		unlock_kernel();
-		return -EEXIST;
-	}
-
-	if (sbi->next_dir_ino < AUTOFS_FIRST_DIR_INO) {
-		printk("autofs: Out of inode numbers -- what the heck did you do??\n");
-		unlock_kernel();
-		return -ENOSPC;
-	}
-	ino = sbi->next_dir_ino++;
-
-	ent = kmalloc(sizeof(struct autofs_dir_ent), GFP_KERNEL);
-	if (!ent) {
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent->name = kmalloc(dentry->d_name.len+1, GFP_KERNEL);
-	if (!ent->name) {
-		kfree(ent);
-		unlock_kernel();
-		return -ENOSPC;
-	}
-
-	ent->hash = dentry->d_name.hash;
-	memcpy(ent->name, dentry->d_name.name, 1+(ent->len = dentry->d_name.len));
-	ent->ino = ino;
-	ent->dentry = dentry;
-	autofs_hash_insert(dh,ent);
-
-	inc_nlink(dir);
-
-	inode = autofs_iget(dir->i_sb, ino);
-	if (IS_ERR(inode)) {
-		drop_nlink(dir);
-		return PTR_ERR(inode);
-	}
-
-	d_instantiate(dentry, inode);
-	unlock_kernel();
-
-	return 0;
-}
-
-/* Get/set timeout ioctl() operation */
-#ifdef CONFIG_COMPAT
-static inline int autofs_compat_get_set_timeout(struct autofs_sb_info *sbi,
-					 unsigned int __user *p)
-{
-	unsigned long ntimeout;
-
-	if (get_user(ntimeout, p) ||
-	    put_user(sbi->exp_timeout / HZ, p))
-		return -EFAULT;
-
-	if (ntimeout > UINT_MAX/HZ)
-		sbi->exp_timeout = 0;
-	else
-		sbi->exp_timeout = ntimeout * HZ;
-
-	return 0;
-}
-#endif
-
-static inline int autofs_get_set_timeout(struct autofs_sb_info *sbi,
-					 unsigned long __user *p)
-{
-	unsigned long ntimeout;
-
-	if (get_user(ntimeout, p) ||
-	    put_user(sbi->exp_timeout / HZ, p))
-		return -EFAULT;
-
-	if (ntimeout > ULONG_MAX/HZ)
-		sbi->exp_timeout = 0;
-	else
-		sbi->exp_timeout = ntimeout * HZ;
-
-	return 0;
-}
-
-/* Return protocol version */
-static inline int autofs_get_protover(int __user *p)
-{
-	return put_user(AUTOFS_PROTO_VERSION, p);
-}
-
-/* Perform an expiry operation */
-static inline int autofs_expire_run(struct super_block *sb,
-				    struct autofs_sb_info *sbi,
-				    struct vfsmount *mnt,
-				    struct autofs_packet_expire __user *pkt_p)
-{
-	struct autofs_dir_ent *ent;
-	struct autofs_packet_expire pkt;
-
-	memset(&pkt,0,sizeof pkt);
-
-	pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
-	pkt.hdr.type = autofs_ptype_expire;
-
-	if (!sbi->exp_timeout || !(ent = autofs_expire(sb,sbi,mnt)))
-		return -EAGAIN;
-
-	pkt.len = ent->len;
-	memcpy(pkt.name, ent->name, pkt.len);
-	pkt.name[pkt.len] = '\0';
-
-	if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
-		return -EFAULT;
-
-	return 0;
-}
-
-/*
- * ioctl()'s on the root directory is the chief method for the daemon to
- * generate kernel reactions
- */
-static int autofs_do_root_ioctl(struct inode *inode, struct file *filp,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct autofs_sb_info *sbi = autofs_sbi(inode->i_sb);
-	void __user *argp = (void __user *)arg;
-
-	DPRINTK(("autofs_ioctl: cmd = 0x%08x, arg = 0x%08lx, sbi = %p, pgrp = %u\n",cmd,arg,sbi,task_pgrp_nr(current)));
-
-	if (_IOC_TYPE(cmd) != _IOC_TYPE(AUTOFS_IOC_FIRST) ||
-	     _IOC_NR(cmd) - _IOC_NR(AUTOFS_IOC_FIRST) >= AUTOFS_IOC_COUNT)
-		return -ENOTTY;
-	
-	if (!autofs_oz_mode(sbi) && !capable(CAP_SYS_ADMIN))
-		return -EPERM;
-	
-	switch(cmd) {
-	case AUTOFS_IOC_READY:	/* Wait queue: go ahead and retry */
-		return autofs_wait_release(sbi,(autofs_wqt_t)arg,0);
-	case AUTOFS_IOC_FAIL:	/* Wait queue: fail with ENOENT */
-		return autofs_wait_release(sbi,(autofs_wqt_t)arg,-ENOENT);
-	case AUTOFS_IOC_CATATONIC: /* Enter catatonic mode (daemon shutdown) */
-		autofs_catatonic_mode(sbi);
-		return 0;
-	case AUTOFS_IOC_PROTOVER: /* Get protocol version */
-		return autofs_get_protover(argp);
-#ifdef CONFIG_COMPAT
-	case AUTOFS_IOC_SETTIMEOUT32:
-		return autofs_compat_get_set_timeout(sbi, argp);
-#endif
-	case AUTOFS_IOC_SETTIMEOUT:
-		return autofs_get_set_timeout(sbi, argp);
-	case AUTOFS_IOC_EXPIRE:
-		return autofs_expire_run(inode->i_sb, sbi, filp->f_path.mnt,
-					 argp);
-	default:
-		return -ENOSYS;
-	}
-
-}
-
-static long autofs_root_ioctl(struct file *filp,
-			     unsigned int cmd, unsigned long arg)
-{
-	int ret;
-
-	lock_kernel();
-	ret = autofs_do_root_ioctl(filp->f_path.dentry->d_inode,
-				   filp, cmd, arg);
-	unlock_kernel();
-
-	return ret;
-}
-
-#ifdef CONFIG_COMPAT
-static long autofs_root_compat_ioctl(struct file *filp,
-			     unsigned int cmd, unsigned long arg)
-{
-	struct inode *inode = filp->f_path.dentry->d_inode;
-	int ret;
-
-	lock_kernel();
-	if (cmd == AUTOFS_IOC_READY || cmd == AUTOFS_IOC_FAIL)
-		ret = autofs_do_root_ioctl(inode, filp, cmd, arg);
-	else
-		ret = autofs_do_root_ioctl(inode, filp, cmd,
-			(unsigned long)compat_ptr(arg));
-	unlock_kernel();
-
-	return ret;
-}
-#endif
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/symlink.c linux-libre-2.6.39-gnu/drivers/staging/autofs/symlink.c
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/symlink.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/symlink.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,26 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/symlink.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * 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.
- *
- * ------------------------------------------------------------------------- */
-
-#include "autofs_i.h"
-
-/* Nothing to release.. */
-static void *autofs_follow_link(struct dentry *dentry, struct nameidata *nd)
-{
-	char *s=((struct autofs_symlink *)dentry->d_inode->i_private)->data;
-	nd_set_link(nd, s);
-	return NULL;
-}
-
-const struct inode_operations autofs_symlink_inode_operations = {
-	.readlink	= generic_readlink,
-	.follow_link	= autofs_follow_link
-};
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/TODO linux-libre-2.6.39-gnu/drivers/staging/autofs/TODO
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/TODO	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/TODO	1969-12-31 19:00:00.000000000 -0500
@@ -1,8 +0,0 @@
-autofs version 3 is on its way out of the kernel,
-It has been replaced by autofs4 several years ago.
-
-The autofs3 code uses the big kernel lock which
-is getting deprecated.
-
-Users that find autofs3 to work but not autofs4
-should talk to Ian Kent <raven@themaw.net>.
diff -druN linux-libre-2.6.38-gnu/drivers/staging/autofs/waitq.c linux-libre-2.6.39-gnu/drivers/staging/autofs/waitq.c
--- linux-libre-2.6.38-gnu/drivers/staging/autofs/waitq.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/autofs/waitq.c	1969-12-31 19:00:00.000000000 -0500
@@ -1,205 +0,0 @@
-/* -*- linux-c -*- --------------------------------------------------------- *
- *
- * drivers/staging/autofs/waitq.c
- *
- *  Copyright 1997-1998 Transmeta Corporation -- All Rights Reserved
- *
- * 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.
- *
- * ------------------------------------------------------------------------- */
-
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/signal.h>
-#include <linux/file.h>
-#include "autofs_i.h"
-
-/* We make this a static variable rather than a part of the superblock; it
-   is better if we don't reassign numbers easily even across filesystems */
-static autofs_wqt_t autofs_next_wait_queue = 1;
-
-/* These are the signals we allow interrupting a pending mount */
-#define SHUTDOWN_SIGS	(sigmask(SIGKILL) | sigmask(SIGINT) | sigmask(SIGQUIT))
-
-void autofs_catatonic_mode(struct autofs_sb_info *sbi)
-{
-	struct autofs_wait_queue *wq, *nwq;
-
-	DPRINTK(("autofs: entering catatonic mode\n"));
-
-	sbi->catatonic = 1;
-	wq = sbi->queues;
-	sbi->queues = NULL;	/* Erase all wait queues */
-	while ( wq ) {
-		nwq = wq->next;
-		wq->status = -ENOENT; /* Magic is gone - report failure */
-		kfree(wq->name);
-		wq->name = NULL;
-		wake_up(&wq->queue);
-		wq = nwq;
-	}
-	fput(sbi->pipe);	/* Close the pipe */
-	sbi->pipe = NULL;
-	autofs_hash_dputall(&sbi->dirhash); /* Remove all dentry pointers */
-}
-
-static int autofs_write(struct file *file, const void *addr, int bytes)
-{
-	unsigned long sigpipe, flags;
-	mm_segment_t fs;
-	const char *data = (const char *)addr;
-	ssize_t wr = 0;
-
-	/** WARNING: this is not safe for writing more than PIPE_BUF bytes! **/
-
-	sigpipe = sigismember(&current->pending.signal, SIGPIPE);
-
-	/* Save pointer to user space and point back to kernel space */
-	fs = get_fs();
-	set_fs(KERNEL_DS);
-
-	while (bytes &&
-	       (wr = file->f_op->write(file,data,bytes,&file->f_pos)) > 0) {
-		data += wr;
-		bytes -= wr;
-	}
-
-	set_fs(fs);
-
-	/* Keep the currently executing process from receiving a
-	   SIGPIPE unless it was already supposed to get one */
-	if (wr == -EPIPE && !sigpipe) {
-		spin_lock_irqsave(&current->sighand->siglock, flags);
-		sigdelset(&current->pending.signal, SIGPIPE);
-		recalc_sigpending();
-		spin_unlock_irqrestore(&current->sighand->siglock, flags);
-	}
-
-	return (bytes > 0);
-}
-	
-static void autofs_notify_daemon(struct autofs_sb_info *sbi, struct autofs_wait_queue *wq)
-{
-	struct autofs_packet_missing pkt;
-
-	DPRINTK(("autofs_wait: wait id = 0x%08lx, name = ", wq->wait_queue_token));
-	autofs_say(wq->name,wq->len);
-
-	memset(&pkt,0,sizeof pkt); /* For security reasons */
-
-	pkt.hdr.proto_version = AUTOFS_PROTO_VERSION;
-	pkt.hdr.type = autofs_ptype_missing;
-	pkt.wait_queue_token = wq->wait_queue_token;
-	pkt.len = wq->len;
-        memcpy(pkt.name, wq->name, pkt.len);
-	pkt.name[pkt.len] = '\0';
-
-	if ( autofs_write(sbi->pipe,&pkt,sizeof(struct autofs_packet_missing)) )
-		autofs_catatonic_mode(sbi);
-}
-
-int autofs_wait(struct autofs_sb_info *sbi, struct qstr *name)
-{
-	struct autofs_wait_queue *wq;
-	int status;
-
-	/* In catatonic mode, we don't wait for nobody */
-	if ( sbi->catatonic )
-		return -ENOENT;
-	
-	/* We shouldn't be able to get here, but just in case */
-	if ( name->len > NAME_MAX )
-		return -ENOENT;
-
-	for ( wq = sbi->queues ; wq ; wq = wq->next ) {
-		if ( wq->hash == name->hash &&
-		     wq->len == name->len &&
-		     wq->name && !memcmp(wq->name,name->name,name->len) )
-			break;
-	}
-	
-	if ( !wq ) {
-		/* Create a new wait queue */
-		wq = kmalloc(sizeof(struct autofs_wait_queue),GFP_KERNEL);
-		if ( !wq )
-			return -ENOMEM;
-
-		wq->name = kmalloc(name->len,GFP_KERNEL);
-		if ( !wq->name ) {
-			kfree(wq);
-			return -ENOMEM;
-		}
-		wq->wait_queue_token = autofs_next_wait_queue++;
-		init_waitqueue_head(&wq->queue);
-		wq->hash = name->hash;
-		wq->len = name->len;
-		wq->status = -EINTR; /* Status return if interrupted */
-		memcpy(wq->name, name->name, name->len);
-		wq->next = sbi->queues;
-		sbi->queues = wq;
-
-		/* autofs_notify_daemon() may block */
-		wq->wait_ctr = 2;
-		autofs_notify_daemon(sbi,wq);
-	} else
-		wq->wait_ctr++;
-
-	/* wq->name is NULL if and only if the lock is already released */
-
-	if ( sbi->catatonic ) {
-		/* We might have slept, so check again for catatonic mode */
-		wq->status = -ENOENT;
-		kfree(wq->name);
-		wq->name = NULL;
-	}
-
-	if ( wq->name ) {
-		/* Block all but "shutdown" signals while waiting */
-		sigset_t sigmask;
-
-		siginitsetinv(&sigmask, SHUTDOWN_SIGS);
-		sigprocmask(SIG_BLOCK, &sigmask, &sigmask);
-
-		interruptible_sleep_on(&wq->queue);
-
-		sigprocmask(SIG_SETMASK, &sigmask, NULL);
-	} else {
-		DPRINTK(("autofs_wait: skipped sleeping\n"));
-	}
-
-	status = wq->status;
-
-	if ( ! --wq->wait_ctr )	/* Are we the last process to need status? */
-		kfree(wq);
-
-	return status;
-}
-
-
-int autofs_wait_release(struct autofs_sb_info *sbi, autofs_wqt_t wait_queue_token, int status)
-{
-	struct autofs_wait_queue *wq, **wql;
-
-	for (wql = &sbi->queues; (wq = *wql) != NULL; wql = &wq->next) {
-		if ( wq->wait_queue_token == wait_queue_token )
-			break;
-	}
-	if ( !wq )
-		return -EINVAL;
-
-	*wql = wq->next;	/* Unlink from chain */
-	kfree(wq->name);
-	wq->name = NULL;	/* Do not wait on this queue */
-
-	wq->status = status;
-
-	if ( ! --wq->wait_ctr )	/* Is anyone still waiting for this guy? */
-		kfree(wq);
-	else
-		wake_up(&wq->queue);
-
-	return 0;
-}
-
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/Adapter.h linux-libre-2.6.39-gnu/drivers/staging/bcm/Adapter.h
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/Adapter.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/Adapter.h	2011-05-19 00:06:34.000000000 -0400
@@ -412,7 +412,7 @@
 
 	// this to keep track of the Tx and Rx MailBox Registers.
 	atomic_t		    CurrNumFreeTxDesc;
-	// to keep track the no of byte recieved
+	// to keep track the no of byte received
 	USHORT				PrevNumRecvDescs;
 	USHORT				CurrNumRecvDescs;
 	UINT				u32TotalDSD;
@@ -527,7 +527,7 @@
 	BOOLEAN			bStatusWrite;
 	UINT			uiNVMDSDSize;
 	UINT			uiVendorExtnFlag;
-	 //it will always represent choosed DSD at any point of time.
+	 //it will always represent chosen DSD at any point of time.
 	 // Generally it is Active DSD but in case of NVM RD/WR it might be different.
 	UINT			ulFlashCalStart;
 	ULONG                   ulFlashControlSectionStart;
@@ -546,10 +546,10 @@
 	PFLASH_CS_INFO psFlashCSInfo ;
 	PFLASH2X_VENDORSPECIFIC_INFO psFlash2xVendorInfo;
 	UINT uiFlashBaseAdd; //Flash start address
-	UINT uiActiveISOOffset; //Active ISO offset choosen before f/w download
+	UINT uiActiveISOOffset; //Active ISO offset chosen before f/w download
 	FLASH2X_SECTION_VAL eActiveISO; //Active ISO section val
-	FLASH2X_SECTION_VAL eActiveDSD;	//Active DSD val choosen before f/w download
-	UINT uiActiveDSDOffsetAtFwDld;  //For accessing Active DSD choosen before f/w download
+	FLASH2X_SECTION_VAL eActiveDSD;	//Active DSD val chosen before f/w download
+	UINT uiActiveDSDOffsetAtFwDld;  //For accessing Active DSD chosen before f/w download
 	UINT uiFlashLayoutMajorVersion ;
 	UINT uiFlashLayoutMinorVersion;
 	BOOLEAN bAllDSDWriteAllow ;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/Bcmchar.c linux-libre-2.6.39-gnu/drivers/staging/bcm/Bcmchar.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/Bcmchar.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/Bcmchar.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,21 +15,20 @@
 
 static int bcm_char_open(struct inode *inode, struct file * filp)
 {
-	PMINI_ADAPTER 		Adapter = NULL;
-    PPER_TARANG_DATA 	pTarang = NULL;
+	PMINI_ADAPTER       Adapter = NULL;
+	PPER_TARANG_DATA    pTarang = NULL;
 
 	Adapter = GET_BCM_ADAPTER(gblpnetdev);
-    pTarang = (PPER_TARANG_DATA)kmalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL);
-    if (!pTarang)
-        return -ENOMEM;
+	pTarang = kzalloc(sizeof(PER_TARANG_DATA), GFP_KERNEL);
+	if (!pTarang)
+		return -ENOMEM;
 
-	memset (pTarang, 0, sizeof(PER_TARANG_DATA));
-    pTarang->Adapter = Adapter;
-	pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB) ;
+	pTarang->Adapter = Adapter;
+	pTarang->RxCntrlMsgBitMask = 0xFFFFFFFF & ~(1 << 0xB);
 
 	down(&Adapter->RxAppControlQueuelock);
-    pTarang->next = Adapter->pTarangs;
-    Adapter->pTarangs = pTarang;
+	pTarang->next = Adapter->pTarangs;
+	Adapter->pTarangs = pTarang;
 	up(&Adapter->RxAppControlQueuelock);
 
 	/* Store the Adapter structure */
@@ -41,118 +40,117 @@
 	nonseekable_open(inode, filp);
 	return 0;
 }
+
 static int bcm_char_release(struct inode *inode, struct file *filp)
 {
-    PPER_TARANG_DATA pTarang, tmp, ptmp;
-	PMINI_ADAPTER Adapter=NULL;
-    struct sk_buff * pkt, * npkt;
+	PPER_TARANG_DATA pTarang, tmp, ptmp;
+	PMINI_ADAPTER Adapter = NULL;
+	struct sk_buff *pkt, *npkt;
 
-    pTarang = (PPER_TARANG_DATA)filp->private_data;
+	pTarang = (PPER_TARANG_DATA)filp->private_data;
 
-    if(pTarang == NULL)
-	{
-	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "ptarang is null\n");
-	return 0;
+	if (pTarang == NULL) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+				"ptarang is null\n");
+		return 0;
 	}
 
 	Adapter = pTarang->Adapter;
 
-    down( &Adapter->RxAppControlQueuelock);
+	down(&Adapter->RxAppControlQueuelock);
 
-    tmp = Adapter->pTarangs;
-    for ( ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next )
-	{
-        if ( tmp == pTarang )
+	tmp = Adapter->pTarangs;
+	for (ptmp = NULL; tmp; ptmp = tmp, tmp = tmp->next) {
+		if (tmp == pTarang)
 			break;
 	}
 
-    if ( tmp )
-	{
-        if ( !ptmp )
-            Adapter->pTarangs = tmp->next;
-        else
-            ptmp->next = tmp->next;
-	}
-
-    else
-	{
-    	up( &Adapter->RxAppControlQueuelock);
-	return 0;
+	if (tmp) {
+		if (!ptmp)
+			Adapter->pTarangs = tmp->next;
+		else
+			ptmp->next = tmp->next;
+	} else {
+		up(&Adapter->RxAppControlQueuelock);
+		return 0;
 	}
 
-    pkt = pTarang->RxAppControlHead;
-    while ( pkt )
-	{
-        npkt = pkt->next;
-        kfree_skb(pkt);
-        pkt = npkt;
+	pkt = pTarang->RxAppControlHead;
+	while (pkt) {
+		npkt = pkt->next;
+		kfree_skb(pkt);
+		pkt = npkt;
 	}
 
-    up( &Adapter->RxAppControlQueuelock);
+	up(&Adapter->RxAppControlQueuelock);
 
-    /*Stop Queuing the control response Packets*/
-    atomic_dec(&Adapter->ApplicationRunning);
+	/*Stop Queuing the control response Packets*/
+	atomic_dec(&Adapter->ApplicationRunning);
 
-    kfree(pTarang);
+	kfree(pTarang);
 
 	/* remove this filp from the asynchronously notified filp's */
-    filp->private_data = NULL;
-    return 0;
+	filp->private_data = NULL;
+	return 0;
 }
 
-static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size, loff_t *f_pos)
+static ssize_t bcm_char_read(struct file *filp, char __user *buf, size_t size,
+			     loff_t *f_pos)
 {
 	PPER_TARANG_DATA pTarang = filp->private_data;
 	PMINI_ADAPTER	Adapter = pTarang->Adapter;
-	struct sk_buff* Packet = NULL;
+	struct sk_buff *Packet = NULL;
 	ssize_t         PktLen = 0;
-	int 		wait_ret_val=0;
+	int             wait_ret_val = 0;
+	unsigned long ret = 0;
 
 	wait_ret_val = wait_event_interruptible(Adapter->process_read_wait_queue,
-		(pTarang->RxAppControlHead || Adapter->device_removed));
-	if((wait_ret_val == -ERESTARTSYS))
-	{
-   		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Exiting as i've been asked to exit!!!\n");
+						(pTarang->RxAppControlHead ||
+						 Adapter->device_removed));
+	if ((wait_ret_val == -ERESTARTSYS)) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"Exiting as i've been asked to exit!!!\n");
 		return wait_ret_val;
 	}
 
-	if(Adapter->device_removed)
-	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "Device Removed... Killing the Apps...\n");
+	if (Adapter->device_removed) {
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+				"Device Removed... Killing the Apps...\n");
 		return -ENODEV;
 	}
 
-	if(FALSE == Adapter->fw_download_done)
+	if (FALSE == Adapter->fw_download_done)
 		return -EACCES;
 
-    down( &Adapter->RxAppControlQueuelock);
+	down(&Adapter->RxAppControlQueuelock);
 
-	if(pTarang->RxAppControlHead)
-	{
+	if (pTarang->RxAppControlHead) {
 		Packet = pTarang->RxAppControlHead;
-		DEQUEUEPACKET(pTarang->RxAppControlHead,pTarang->RxAppControlTail);
+		DEQUEUEPACKET(pTarang->RxAppControlHead,
+			      pTarang->RxAppControlTail);
 		pTarang->AppCtrlQueueLen--;
 	}
 
-    up(&Adapter->RxAppControlQueuelock);
+	up(&Adapter->RxAppControlQueuelock);
 
-	if(Packet)
-	{
+	if (Packet) {
 		PktLen = Packet->len;
-		if(copy_to_user(buf, Packet->data, min_t(size_t, PktLen, size)))
-		{
+		ret = copy_to_user(buf, Packet->data,
+				   min_t(size_t, PktLen, size));
+		if (ret) {
 			dev_kfree_skb(Packet);
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "\nReturning from copy to user failure \n");
+			BCM_DEBUG_PRINT(Adapter, DBG_TYPE_PRINTK, 0, 0,
+					"Returning from copy to user failure\n");
 			return -EFAULT;
 		}
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
+		BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,
 				"Read %zd Bytes From Adapter packet = %p by process %d!\n",
 				PktLen, Packet, current->pid);
 		dev_kfree_skb(Packet);
 	}
 
-    BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<====\n");
-    return PktLen;
+	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL, "<\n");
+	return PktLen;
 }
 
 static long bcm_char_ioctl(struct file *filp, UINT cmd, ULONG arg)
@@ -2024,6 +2022,12 @@
 				if(Status)
 				{
 					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of Ioctl buffer is failed from user space");
+					Status = -EFAULT;
+					break;
+				}
+
+				if (IoBuffer.InputLength != sizeof(unsigned long)) {
+					Status = -EINVAL;
 					break;
 				}
 
@@ -2031,6 +2035,7 @@
 				if(Status)
 				{
 					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"copy of control bit mask failed from user space");
+					Status = -EFAULT;
 					break;
 				}
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, OSAL_DBG, DBG_LVL_ALL,"\n Got user defined cntrl msg bit mask :%lx", RxCntrlMsgBitMask);
@@ -2093,7 +2098,7 @@
 }
 
 
-static struct file_operations bcm_fops = {
+static const struct file_operations bcm_fops = {
 	.owner    = THIS_MODULE,
 	.open     = bcm_char_open,
 	.release  = bcm_char_release,
@@ -2107,32 +2112,32 @@
 int register_control_device_interface(PMINI_ADAPTER Adapter)
 {
 
-	if(Adapter->major>0)
+	if (Adapter->major > 0)
 		return Adapter->major;
 
 	Adapter->major = register_chrdev(0, DEV_NAME, &bcm_fops);
-	if(Adapter->major < 0) {
+	if (Adapter->major < 0) {
 		pr_err(DRV_NAME ": could not created character device\n");
 		return Adapter->major;
 	}
 
-	Adapter->pstCreatedClassDevice = device_create (bcm_class, NULL,
-							MKDEV(Adapter->major, 0), Adapter,
-							DEV_NAME);
+	Adapter->pstCreatedClassDevice = device_create(bcm_class, NULL,
+						       MKDEV(Adapter->major, 0),
+						       Adapter, DEV_NAME);
 
-	if(IS_ERR(Adapter->pstCreatedClassDevice)) {
+	if (IS_ERR(Adapter->pstCreatedClassDevice)) {
 		pr_err(DRV_NAME ": class device create failed\n");
 		unregister_chrdev(Adapter->major, DEV_NAME);
 		return PTR_ERR(Adapter->pstCreatedClassDevice);
 	}
-			
+
 	return 0;
 }
 
 void unregister_control_device_interface(PMINI_ADAPTER Adapter)
 {
-	if(Adapter->major > 0) {
-		device_destroy (bcm_class, MKDEV(Adapter->major, 0));
+	if (Adapter->major > 0) {
+		device_destroy(bcm_class, MKDEV(Adapter->major, 0));
 		unregister_chrdev(Adapter->major, DEV_NAME);
 	}
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/Bcmnet.c linux-libre-2.6.39-gnu/drivers/staging/bcm/Bcmnet.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/Bcmnet.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/Bcmnet.c	2011-05-19 00:06:34.000000000 -0400
@@ -8,7 +8,7 @@
 
 	if (Adapter->fw_download_done == FALSE) {
 		pr_notice(PFX "%s: link up failed (download in progress)\n",
- 			  dev->name);
+			  dev->name);
 		return -EBUSY;
 	}
 
@@ -50,7 +50,7 @@
 * Description - This is the main transmit function for our virtual
 *		interface(eth0). It handles the ARP packets. It
 *		clones this packet and then Queue it to a suitable
-* 		Queue. Then calls the transmit_packet().
+*		Queue. Then calls the transmit_packet().
 *
 * Parameter   -	 skb - Pointer to the socket buffer structure
 *		 dev - Pointer to the virtual net device structure
@@ -110,13 +110,13 @@
 Register other driver entry points with the kernel
 */
 static const struct net_device_ops bcmNetDevOps = {
-    .ndo_open		= bcm_open,
-    .ndo_stop 		= bcm_close,
-    .ndo_start_xmit	= bcm_transmit,
-    .ndo_change_mtu	= eth_change_mtu,
-    .ndo_set_mac_address = eth_mac_addr,
-    .ndo_validate_addr	= eth_validate_addr,
-    .ndo_select_queue	= bcm_select_queue,
+	.ndo_open		= bcm_open,
+	.ndo_stop		= bcm_close,
+	.ndo_start_xmit	        = bcm_transmit,
+	.ndo_change_mtu	        = eth_change_mtu,
+	.ndo_set_mac_address    = eth_mac_addr,
+	.ndo_validate_addr	= eth_validate_addr,
+	.ndo_select_queue	= bcm_select_queue,
 };
 
 static struct device_type wimax_type = {
@@ -138,7 +138,8 @@
 	return 0;
 }
 
-static void bcm_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info)
+static void bcm_get_drvinfo(struct net_device *dev,
+			    struct ethtool_drvinfo *info)
 {
 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
 	PS_INTERFACE_ADAPTER psIntfAdapter = Adapter->pvInterfaceAdapter;
@@ -160,14 +161,14 @@
 	return Adapter->LinkUpStatus;
 }
 
-static u32 bcm_get_msglevel (struct net_device *dev)
+static u32 bcm_get_msglevel(struct net_device *dev)
 {
 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
 
 	return Adapter->msg_enable;
 }
 
-static void bcm_set_msglevel (struct net_device *dev, u32 level)
+static void bcm_set_msglevel(struct net_device *dev, u32 level)
 {
 	PMINI_ADAPTER Adapter = GET_BCM_ADAPTER(dev);
 
@@ -177,7 +178,7 @@
 static const struct ethtool_ops bcm_ethtool_ops = {
 	.get_settings	= bcm_get_settings,
 	.get_drvinfo	= bcm_get_drvinfo,
-	.get_link 	= bcm_get_link,
+	.get_link	= bcm_get_link,
 	.get_msglevel	= bcm_get_msglevel,
 	.set_msglevel	= bcm_set_msglevel,
 };
@@ -206,7 +207,7 @@
 	if (result != STATUS_SUCCESS) {
 		dev_err(&udev->dev,
 			PFX "Error in Reading the mac Address: %d", result);
- 		return -EIO;
+		return -EIO;
 	}
 
 	result = register_netdev(net);
@@ -233,6 +234,6 @@
 	if (netif_msg_probe(Adapter))
 		dev_info(&udev->dev, PFX "%s: unregister usb-%s%s\n",
 			 net->name, xdev->bus->bus_name, xdev->devpath);
- 
+
 	unregister_netdev(Adapter->dev);
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/CmHost.c linux-libre-2.6.39-gnu/drivers/staging/bcm/CmHost.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/CmHost.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/CmHost.c	2011-05-19 00:06:34.000000000 -0400
@@ -1,6 +1,6 @@
 /************************************************************
 *			CMHOST.C
-*	This file contains the routines for handling Connnection
+*	This file contains the routines for handling Connection
 *	Management.
 ************************************************************/
 
@@ -384,7 +384,7 @@
 		}
 		if(psfCSType->cCPacketClassificationRule.u8Protocol == 0)
 		{
-			//we didnt get protocol field filled in by the BS
+			//we didn't get protocol field filled in by the BS
 			pstClassifierEntry->ucProtocolLength=0;
 		}
 		else
@@ -879,7 +879,7 @@
 
 						/*
 							Passing the argument u8PHSI instead of clsid. Because for DL with no classifier rule,
-							clsid will be zero hence we cant have multiple PHS rules for the same SF.
+							clsid will be zero hence we can't have multiple PHS rules for the same SF.
 							To support multiple PHS rule, passing u8PHSI.
 						*/
 
@@ -974,11 +974,7 @@
 			!(psfLocalSet->u8RequesttransmissionPolicy &
 				MASK_DISABLE_HEADER_SUPPRESSION);
 
-	if(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication)
-	{
-		kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication);
-		Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = NULL;
-	}
+	kfree(Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication);
 	Adapter->PackInfo[uiSearchRuleIndex].pstSFIndication = pstAddIndication;
 
 	//Re Sort the SF list in PackInfo according to Traffic Priority
@@ -1107,7 +1103,7 @@
 	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  "u8TrafficIndicationPreference	: 0x%X",
 		pstAddIndication->sfAuthorizedSet.u8TrafficIndicationPreference);
 
-	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " Total Classifiers Recieved		: 0x%X",pstAddIndication->sfAuthorizedSet.u8TotalClassifiers);
+	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " Total Classifiers Received		: 0x%X",pstAddIndication->sfAuthorizedSet.u8TotalClassifiers);
 
 	nCurClassifierCnt = pstAddIndication->sfAuthorizedSet.u8TotalClassifiers;
 
@@ -1309,7 +1305,7 @@
 	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  "u8TrafficIndicationPreference	: 0x%02X",
 		pstAddIndication->sfAdmittedSet.u8TrafficIndicationPreference);
 
-	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " Total Classifiers Recieved		: 0x%X",pstAddIndication->sfAdmittedSet.u8TotalClassifiers);
+	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " Total Classifiers Received		: 0x%X",pstAddIndication->sfAdmittedSet.u8TotalClassifiers);
 
 	nCurClassifierCnt = pstAddIndication->sfAdmittedSet.u8TotalClassifiers;
 
@@ -1506,7 +1502,7 @@
 	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " u8TrafficIndicationPreference	: 0x%X",
 		pstAddIndication->sfActiveSet.u8TrafficIndicationPreference);
 
-	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " Total Classifiers Recieved		: 0x%X",pstAddIndication->sfActiveSet.u8TotalClassifiers);
+	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, DUMP_CONTROL, DBG_LVL_ALL,  " Total Classifiers Received		: 0x%X",pstAddIndication->sfActiveSet.u8TotalClassifiers);
 
 	nCurClassifierCnt = pstAddIndication->sfActiveSet.u8TotalClassifiers;
 
@@ -1700,7 +1696,7 @@
 		//No Special handling send the message as it is
 		return 1;
 	}
-	// For DSA_REQ, only upto "psfAuthorizedSet" parameter should be accessed by driver!
+	// For DSA_REQ, only up to "psfAuthorizedSet" parameter should be accessed by driver!
 
 	pstAddIndication=kmalloc(sizeof(*pstAddIndication), GFP_KERNEL);
 	if(NULL==pstAddIndication)
@@ -1792,7 +1788,7 @@
 	BCM_DEBUG_PRINT( Adapter,DBG_TYPE_OTHERS, CONN_MSG, DBG_LVL_ALL, "Inside RestoreCmControlResponseMessage ");
 	/*
 	//Need to Allocate memory to contain the SUPER Large structures
-	//Our driver cant create these structures on Stack :(
+	//Our driver can't create these structures on Stack :(
 	*/
 	pstAddIndicationDest=kmalloc(sizeof(stLocalSFAddIndicationAlt), GFP_KERNEL);
 
@@ -1961,7 +1957,7 @@
 {
 	/*
 	//Need to Allocate memory to contain the SUPER Large structures
-	//Our driver cant create these structures on Stack
+	//Our driver can't create these structures on Stack
 	*/
 	Adapter->caDsxReqResp=kmalloc(sizeof(stLocalSFAddIndicationAlt)+LEADER_SIZE, GFP_KERNEL);
 	if(!Adapter->caDsxReqResp)
@@ -1971,10 +1967,7 @@
 
 INT FreeAdapterDsxBuffer(PMINI_ADAPTER Adapter)
 {
-	if(Adapter->caDsxReqResp)
-	{
-		kfree(Adapter->caDsxReqResp);
-	}
+	kfree(Adapter->caDsxReqResp);
 	return 0;
 
 }
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/cntrl_SignalingInterface.h linux-libre-2.6.39-gnu/drivers/staging/bcm/cntrl_SignalingInterface.h
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/cntrl_SignalingInterface.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/cntrl_SignalingInterface.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,7 +21,7 @@
 #define VENDOR_PHS_PARAM_LENGTH 10
 #define MAX_NUM_ACTIVE_BS 10
 #define AUTH_TOKEN_LENGTH	10
-#define NUM_HARQ_CHANNELS	16	//Changed from 10 to 16 to accomodate all HARQ channels
+#define NUM_HARQ_CHANNELS	16	//Changed from 10 to 16 to accommodate all HARQ channels
 #define VENDOR_CLASSIFIER_PARAM_LENGTH 1 //Changed the size to 1 byte since we dnt use it
 #define  VENDOR_SPECIF_QOS_PARAM 1
 #define VENDOR_PHS_PARAM_LENGTH	10
@@ -109,13 +109,13 @@
     B_UINT8                         u8PHSI;
 	/**  PHSF Length Of The Service Flow*/
     B_UINT8                         u8PHSFLength;
-    /** String of bytes containing header information to be supressed by the sending CS and reconstructed by the receiving CS*/
+    /** String of bytes containing header information to be suppressed by the sending CS and reconstructed by the receiving CS*/
     B_UINT8                         u8PHSF[MAX_PHS_LENGTHS];
 	/**  PHSM Length Of The Service Flow*/
     B_UINT8                         u8PHSMLength;
 	/**  PHS Mask for the SF*/
     B_UINT8                         u8PHSM[MAX_PHS_LENGTHS];
-	/**  8bit Total number of bytes to be supressed for the Service Flow*/
+	/**  8bit Total number of bytes to be suppressed for the Service Flow*/
     B_UINT8                         u8PHSS;
 	/**  8bit Indicates whether or not Packet Header contents need to be verified prior to supression */
     B_UINT8                         u8PHSV;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/HostMIBSInterface.h linux-libre-2.6.39-gnu/drivers/staging/bcm/HostMIBSInterface.h
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/HostMIBSInterface.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/HostMIBSInterface.h	2011-05-19 00:06:34.000000000 -0400
@@ -62,7 +62,7 @@
 	ULONG			NumDesUsed;
 	ULONG			CurrNumFreeDesc;
 	ULONG			PrevNumFreeDesc;
-	// to keep track the no of byte recieved
+	// to keep track the no of byte received
 	ULONG			PrevNumRcevBytes;
 	ULONG			CurrNumRcevBytes;
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/InterfaceIdleMode.c linux-libre-2.6.39-gnu/drivers/staging/bcm/InterfaceIdleMode.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/InterfaceIdleMode.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/InterfaceIdleMode.c	2011-05-19 00:06:34.000000000 -0400
@@ -11,7 +11,7 @@
 
 
 Return:				BCM_STATUS_SUCCESS - If Wakeup of the HW Interface was successful.
-						Other           - If an error occured.
+						Other           - If an error occurred.
 */
 
 
@@ -26,7 +26,7 @@
 
 
 Return:				BCM_STATUS_SUCCESS - If Idle mode response related HW configuration was successful.
-						Other           - If an error occured.
+						Other           - If an error occurred.
 */
 
 /*
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/InterfaceIsr.c linux-libre-2.6.39-gnu/drivers/staging/bcm/InterfaceIsr.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/InterfaceIsr.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/InterfaceIsr.c	2011-05-19 00:06:34.000000000 -0400
@@ -80,8 +80,8 @@
 		}
 		case -EINPROGRESS:
 		{
-			//This situation may happend when URBunlink is used. for detail check usb_unlink_urb documentation.
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occured... something very bad is going on");
+			//This situation may happened when URBunlink is used. for detail check usb_unlink_urb documentation.
+			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, INTF_INIT, DBG_LVL_ALL,"Impossibe condition has occurred... something very bad is going on");
 			break ;
 			//return;
 		}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/InterfaceRx.c linux-libre-2.6.39-gnu/drivers/staging/bcm/InterfaceRx.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/InterfaceRx.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/InterfaceRx.c	2011-05-19 00:06:34.000000000 -0400
@@ -34,7 +34,7 @@
 	return pRcb;
 }
 
-/*this is receive call back - when pkt avilable for receive (BULK IN- end point)*/
+/*this is receive call back - when pkt available for receive (BULK IN- end point)*/
 static void read_bulk_callback(struct urb *urb)
 {
 	struct sk_buff *skb = NULL;
@@ -123,7 +123,7 @@
 	if((ntohs(pLeader->Vcid) == VCID_CONTROL_PACKET) ||
 	    (!(pLeader->Status >= 0x20  &&  pLeader->Status <= 0x3F)))
 	{
-	    BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Recived control pkt...");
+	    BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_CTRL, DBG_LVL_ALL, "Received control pkt...");
 		*(PUSHORT)skb->data = pLeader->Status;
        	memcpy(skb->data+sizeof(USHORT), urb->transfer_buffer +
 			(sizeof(LEADER)), pLeader->PLength);
@@ -142,7 +142,7 @@
 		  * Data Packet, Format a proper Ethernet Header
         	  * and give it to the stack
 		  */
-        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt...");
+        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt...");
 		skb_reserve(skb, 2 + SKB_RESERVE_PHS_BYTES);
 		memcpy(skb->data+ETH_HLEN, (PUCHAR)urb->transfer_buffer + sizeof(LEADER), pLeader->PLength);
 		skb->dev = Adapter->dev;
@@ -151,7 +151,7 @@
 		skb_put (skb, pLeader->PLength + ETH_HLEN);
 		Adapter->PackInfo[QueueIndex].uiTotalRxBytes+=pLeader->PLength;
 		Adapter->PackInfo[QueueIndex].uiThisPeriodRxBytes+= pLeader->PLength;
-        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Recived Data pkt of len :0x%X", pLeader->PLength);
+        BCM_DEBUG_PRINT(psIntfAdapter->psAdapter,DBG_TYPE_RX, RX_DATA, DBG_LVL_ALL, "Received Data pkt of len :0x%X", pLeader->PLength);
 
 		if(netif_running(Adapter->dev))
 		{
@@ -237,7 +237,7 @@
 
 
 Return:				TRUE  - If Rx was successful.
-					Other - If an error occured.
+					Other - If an error occurred.
 */
 
 BOOLEAN InterfaceRx (PS_INTERFACE_ADAPTER psIntfAdapter)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/Ioctl.h linux-libre-2.6.39-gnu/drivers/staging/bcm/Ioctl.h
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/Ioctl.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/Ioctl.h	2011-05-19 00:06:34.000000000 -0400
@@ -241,7 +241,7 @@
 
 typedef enum _FLASH2X_SECTION_VAL
 {
-	NO_SECTION_VAL = 0, //no section is choosen when absolute offset is given for RD/WR
+	NO_SECTION_VAL = 0, //no section is chosen when absolute offset is given for RD/WR
 	ISO_IMAGE1,
 	ISO_IMAGE2,
 	DSD0,
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/IPv6Protocol.c linux-libre-2.6.39-gnu/drivers/staging/bcm/IPv6Protocol.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/IPv6Protocol.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/IPv6Protocol.c	2011-05-19 00:06:34.000000000 -0400
@@ -287,7 +287,7 @@
 
 	for(uiLoopIndex=0;uiLoopIndex<uiCountIPSrcAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
 	{
-		BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Recieved Packet : \n ");
+		BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Address In Received Packet : \n ");
 		DumpIpv6Address(aulSrcIP);
 		BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Src Ipv6 Mask In Classifier Rule: \n");
 		DumpIpv6Address(&pstClassifierRule->stSrcIpAddress.ulIpv6Mask[uiLoopIndex]);
@@ -340,7 +340,7 @@
 
 	for(uiLoopIndex=0;uiLoopIndex<uiCountIPDestinationAddresses;uiLoopIndex+=uiIpv6AddrNoLongWords)
 	{
-		BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Recieved Packet : \n ");
+		BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Address In Received Packet : \n ");
 		DumpIpv6Address(aulDestIP);
 		BCM_DEBUG_PRINT( Adapter,DBG_TYPE_TX, IPV6_DBG, DBG_LVL_ALL, "\n Destination Ipv6 Mask In Classifier Rule: \n");
 		DumpIpv6Address(&pstClassifierRule->stDestIpAddress.ulIpv6Mask[uiLoopIndex]);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/LeakyBucket.c linux-libre-2.6.39-gnu/drivers/staging/bcm/LeakyBucket.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/LeakyBucket.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/LeakyBucket.c	2011-05-19 00:06:34.000000000 -0400
@@ -213,7 +213,7 @@
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "For Queue: %zd\n", psSF-Adapter->PackInfo);
 				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_TX, TX_PACKETS, DBG_LVL_ALL, "\nAvailable Tokens = %d required = %d\n",
 					psSF->uiCurrentTokenCount, iPacketLen);
-				//this part indicates that becuase of non-availability of the tokens
+				//this part indicates that because of non-availability of the tokens
 				//pkt has not been send out hence setting the pending flag indicating the host to send it out
 				//first next iteration  .
 				psSF->uiPendedLast = TRUE;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/Misc.c linux-libre-2.6.39-gnu/drivers/staging/bcm/Misc.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/Misc.c	2012-03-24 01:16:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/Misc.c	2012-03-24 03:35:39.000000000 -0400
@@ -499,13 +499,12 @@
 	BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "=====>");
 	if(Adapter->LinkStatus == SYNC_UP_REQUEST && Adapter->AutoSyncup)
 	{
-		pstLinkRequest=kmalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
+		pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
 		if(!pstLinkRequest)
 		{
 			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
 			return;
 		}
-		memset(pstLinkRequest,0,sizeof(LINK_REQUEST));
 		//sync up request...
 		Adapter->LinkStatus = WAIT_FOR_SYNC;// current link status
 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For SyncUp...");
@@ -517,13 +516,12 @@
 	}
 	else if(Adapter->LinkStatus == PHY_SYNC_ACHIVED && Adapter->AutoLinkUp)
 	{
-		pstLinkRequest=kmalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
+		pstLinkRequest = kzalloc(sizeof(LINK_REQUEST), GFP_ATOMIC);
 		if(!pstLinkRequest)
 		{
 			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Can not allocate memory for Link request!");
 			return;
 		}
-		memset(pstLinkRequest,0,sizeof(LINK_REQUEST));
 		//LINK_UP_REQUEST
 		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, LINK_UP_MSG, DBG_LVL_ALL, "Requesting For LinkUp...");
 		pstLinkRequest->szData[0]=LINK_UP_REQ_PAYLOAD;
@@ -605,7 +603,7 @@
 				Adapter->LinkStatus=LINKUP_DONE;
 				Adapter->bPHSEnabled = *(pucBuffer+3);
                	Adapter->bETHCSEnabled = *(pucBuffer+4) & ETH_CS_MASK;
-				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Recieved In LinkUp Ack : %x \n",Adapter->bPHSEnabled);
+				BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0, "PHS Support Status Received In LinkUp Ack : %x \n",Adapter->bPHSEnabled);
 				if((FALSE == Adapter->bShutStatus)&&
 					(FALSE == Adapter->IdleMode))
 				{
@@ -1156,7 +1154,7 @@
 
 	/*
      * 1. If the LED Settings fails, do not stop and do the Firmware download.
-     * 2. This init would happend only if the cfg file is present, else
+     * 2. This init would happened only if the cfg file is present, else
      *    call from the ioctl context.
      */
 
@@ -1188,7 +1186,7 @@
 		status = PropagateCalParamsFromFlashToMemory(ps_adapter);
 		if(status)
 		{
-			BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propogation of Cal param failed .." );
+			BCM_DEBUG_PRINT(ps_adapter,DBG_TYPE_INITEXIT, MP_INIT, DBG_LVL_ALL," Propagation of Cal param failed .." );
 			goto OUT;
 		}
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/nvm.c linux-libre-2.6.39-gnu/drivers/staging/bcm/nvm.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/nvm.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/nvm.c	2011-05-19 00:06:34.000000000 -0400
@@ -313,7 +313,7 @@
 //		uiNumBytes - Number of bytes to be read from the EEPROM.
 //
 // Returns:
-//		OSAL_STATUS_SUCCESS - if EEPROM read is successfull.
+//		OSAL_STATUS_SUCCESS - if EEPROM read is successful.
 //		<FAILURE>			- if failed.
 //-----------------------------------------------------------------------------
 
@@ -431,7 +431,7 @@
 //		uiNumBytes - Number of bytes to be read from the FLASH.
 //
 // Returns:
-//		OSAL_STATUS_SUCCESS - if FLASH read is successfull.
+//		OSAL_STATUS_SUCCESS - if FLASH read is successful.
 //		<FAILURE>			- if failed.
 //-----------------------------------------------------------------------------
 
@@ -1174,7 +1174,7 @@
 	if(NULL == pTempBuff)
 		goto BeceemFlashBulkWrite_EXIT;
 //
-// check if the data to be written is overlapped accross sectors
+// check if the data to be written is overlapped across sectors
 //
 	if(uiOffset+uiNumBytes < uiSectBoundary)
 	{
@@ -1390,7 +1390,7 @@
 		goto BeceemFlashBulkWriteStatus_EXIT;
 
 //
-// check if the data to be written is overlapped accross sectors
+// check if the data to be written is overlapped across sectors
 //
 	if(uiOffset+uiNumBytes < uiSectBoundary)
 	{
@@ -2020,7 +2020,7 @@
 //		uiNumBytes - Number of bytes to be read from the NVM.
 //
 // Returns:
-//		OSAL_STATUS_SUCCESS - if NVM read is successfull.
+//		OSAL_STATUS_SUCCESS - if NVM read is successful.
 //		<FAILURE>			- if failed.
 //-----------------------------------------------------------------------------
 
@@ -2083,7 +2083,7 @@
 //		uiNumBytes - Number of bytes to be written..
 //
 // Returns:
-//		OSAL_STATUS_SUCCESS - if NVM write is successfull.
+//		OSAL_STATUS_SUCCESS - if NVM write is successful.
 //		<FAILURE>			- if failed.
 //-----------------------------------------------------------------------------
 
@@ -2218,7 +2218,7 @@
 //          uiSectorSize - sector size
 //
 // Returns:
-//		OSAL_STATUS_SUCCESS - if NVM write is successfull.
+//		OSAL_STATUS_SUCCESS - if NVM write is successful.
 //		<FAILURE>			- if failed.
 //-----------------------------------------------------------------------------
 
@@ -2430,7 +2430,7 @@
 *Input Parameter:
 *		Adapter data structure
 *Return Value :
-*		0. means sucess;
+*		0. means success;
 */
 /***************************************************************************/
 
@@ -2998,7 +2998,7 @@
 	/*
 	*	Considering all the section for which end offset can be calculated or directly given
 	*	in CS Structure. if matching case does not exist, return STATUS_FAILURE indicating section
-	*	endoffset can't be calculated or given in CS Stucture.
+	*	endoffset can't be calculated or given in CS Structure.
 	*/
 
 	INT SectStartOffset = 0 ;
@@ -3173,7 +3173,7 @@
 *	@uiNumBytes : Number of Bytes for Read
 *
 *	Return value:-
-*		return true on sucess and STATUS_FAILURE on fail.
+*		return true on success and STATUS_FAILURE on fail.
 */
 
 INT BcmFlash2xBulkRead(
@@ -3241,7 +3241,7 @@
 *	@uiNumBytes : Number of Bytes for Write
 *
 *	Return value:-
-*		return true on sucess and STATUS_FAILURE on fail.
+*		return true on success and STATUS_FAILURE on fail.
 *
 */
 
@@ -3308,7 +3308,7 @@
 *	@Adapter :-Drivers private Data Structure
 *
 *	Return Value:-
-*		Return STATUS_SUCESS if get sucess in setting the right DSD else negaive error code
+*		Return STATUS_SUCESS if get success in setting the right DSD else negaive error code
 *
 **/
 static INT BcmGetActiveDSD(PMINI_ADAPTER Adapter)
@@ -3384,7 +3384,7 @@
 *	@uiOffset : Offset provided in the Flash
 *
 *	Return Value:-
-*	Sucess:-TRUE ,  offset is writable
+*	Success:-TRUE ,  offset is writable
 *	Failure:-FALSE, offset is RO
 *
 **/
@@ -3441,7 +3441,7 @@
 	@Adapter:-Driver private Data Structure
 *
 *	Return value:-
-*	Sucess:- STATUS_SUCESS
+*	Success:- STATUS_SUCESS
 *	Failure:- negative error code
 **/
 
@@ -3783,7 +3783,7 @@
 					// This is a SPECIAL Case which will only happen if the current highest priority ISO has priority value = 0x7FFFFFFF.
 					// We will write 1 to the current Highest priority ISO And then shall increase the priority of the requested ISO
 					// by user
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happend, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal);
+					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_OTHERS, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal);
 					SectImagePriority = htonl(0x1);
 					Status = BcmFlash2xBulkWrite(Adapter,
 								&SectImagePriority,
@@ -3853,7 +3853,7 @@
 					// This is a SPECIAL Case which will only happen if the current highest priority DSD has priority value = 0x7FFFFFFF.
 					// We will write 1 to the current Highest priority DSD And then shall increase the priority of the requested DSD
 					// by user
-					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happend, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal);
+					BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, NVM_RW, DBG_LVL_ALL, "SectImagePriority wraparound happened, eFlash2xSectVal: 0x%x\n",eFlash2xSectVal);
 					SectImagePriority = htonl(0x1);
 
 					Status = BcmFlash2xBulkWrite(Adapter,
@@ -4119,7 +4119,7 @@
 												MAX_RW_SIZE);
 				IsThisHeaderSector = FALSE ;
 			}
-			//substracting the written Data
+			//subtracting the written Data
 			uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ;
 		}
 
@@ -4250,7 +4250,7 @@
 				IsThisHeaderSector = FALSE ;
 			}
 
-			//substracting the written Data
+			//subtracting the written Data
 			uiTotalDataToCopy = uiTotalDataToCopy - Adapter->uiSectorSize ;
 		}
 
@@ -4268,7 +4268,7 @@
 @eFlash2xSectionVal :- Flash section val which has header
 
 Return Value :-
-	Sucess :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS
+	Success :- If Section is present and writable, corrupt the sig and return STATUS_SUCCESS
 	Failure :-Return negative error code
 
 
@@ -4301,7 +4301,7 @@
 @eFlashSectionVal :- Flash section val which has header
 
 Return Value :-
-	Sucess :- If Section is present and writable write the sig and return STATUS_SUCCESS
+	Success :- If Section is present and writable write the sig and return STATUS_SUCCESS
 	Failure :-Return negative error code
 
 **/
@@ -4504,7 +4504,7 @@
 			     in case of numofBytes  equal zero complete section will be copied.
 
 Return Values-
-	Sucess : Return STATUS_SUCCESS
+	Success : Return STATUS_SUCCESS
 	Faillure :- return negative error code
 
 **/
@@ -4621,7 +4621,7 @@
 @uiOffset :- Flash offset that has to be written.
 
 Return value :-
-	Sucess :- On sucess return STATUS_SUCCESS
+	Success :- On success return STATUS_SUCCESS
 	Faillure :- Return negative error code
 
 **/
@@ -4634,7 +4634,7 @@
 	UINT uiSectAlignAddr = 0;
 	UINT sig = 0;
 
-	//making the offset sector alligned
+	//making the offset sector aligned
 	uiSectAlignAddr = uiOffset & ~(Adapter->uiSectorSize - 1);
 
 
@@ -4643,7 +4643,7 @@
 	(uiSectAlignAddr == BcmGetSectionValEndOffset(Adapter,DSD0)- Adapter->uiSectorSize))
 	{
 
-		//offset from the sector boundry having the header map
+		//offset from the sector boundary having the header map
 		offsetToProtect = Adapter->psFlash2xCSInfo->OffsetFromDSDStartForDSDHeader % Adapter->uiSectorSize;
 		HeaderSizeToProtect = sizeof(DSD_HEADER);
 		bHasHeader = TRUE ;
@@ -4697,7 +4697,7 @@
 @Adapater :- Bcm Driver Private Data Structure
 
 OutPut:-
-	Select the Appropriate chip and retrn status Sucess
+	Select the Appropriate chip and retrn status Success
 **/
 static INT BcmDoChipSelect(PMINI_ADAPTER Adapter, UINT offset)
 {
@@ -5086,7 +5086,7 @@
 	{
 		if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE)
 		{
-			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence cant Corrupt signature");
+			BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Corrupt signature");
 			return SECTOR_IS_NOT_WRITABLE;
 		}
 	}
@@ -5155,7 +5155,7 @@
 
 	if(IsSectionWritable(Adapter,eFlash2xSectionVal) != TRUE)
 	{
-		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence cant Corrupt signature");
+		BCM_DEBUG_PRINT(Adapter,DBG_TYPE_PRINTK, 0, 0,"Section is not Writable...Hence can't Corrupt signature");
 		return SECTOR_IS_NOT_WRITABLE;
 	}
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/bcm/Qos.c linux-libre-2.6.39-gnu/drivers/staging/bcm/Qos.c
--- linux-libre-2.6.38-gnu/drivers/staging/bcm/Qos.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/bcm/Qos.c	2011-05-19 00:06:34.000000000 -0400
@@ -727,7 +727,7 @@
 
 	BCM_DEBUG_PRINT(Adapter, DBG_TYPE_TX, IPV4_DBG, DBG_LVL_ALL,  "%s  CLS UserPrio:%x CLS VLANID:%x\n",__FUNCTION__,ntohs(*((USHORT *)pstClassifierRule->usUserPriority)),pstClassifierRule->usVLANID);
 
-	/* In case FW didn't recieve the TLV, the priority field should be ignored */
+	/* In case FW didn't receive the TLV, the priority field should be ignored */
 	if(pstClassifierRule->usValidityBitMap & (1<<PKT_CLASSIFICATION_USER_PRIORITY_VALID))
 	{
 		if(pstEthCsPktInfo->eNwpktEthFrameType!=eEth802QVLANFrame)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/aiutils.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/aiutils.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/aiutils.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/aiutils.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1 @@
+#include "../util/aiutils.c"
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmcdc.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmcdc.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmcdc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmcdc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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/if_ether.h>
+
+typedef struct cdc_ioctl {
+	u32 cmd;		/* ioctl command value */
+	u32 len;		/* lower 16: output buflen; upper 16:
+				 input buflen (excludes header) */
+	u32 flags;		/* flag defns given below */
+	u32 status;		/* status code returned from the device */
+} cdc_ioctl_t;
+
+/* Max valid buffer size that can be sent to the dongle */
+#define CDC_MAX_MSG_SIZE	(ETH_FRAME_LEN+ETH_FCS_LEN)
+
+/* len field is divided into input and output buffer lengths */
+#define CDCL_IOC_OUTLEN_MASK   0x0000FFFF	/* maximum or expected
+						 response length, */
+					   /* excluding IOCTL header */
+#define CDCL_IOC_OUTLEN_SHIFT  0
+#define CDCL_IOC_INLEN_MASK    0xFFFF0000	/* input buffer length,
+						 excluding IOCTL header */
+#define CDCL_IOC_INLEN_SHIFT   16
+
+/* CDC flag definitions */
+#define CDCF_IOC_ERROR		0x01	/* 0=success, 1=ioctl cmd failed */
+#define CDCF_IOC_SET		0x02	/* 0=get, 1=set cmd */
+#define CDCF_IOC_IF_MASK	0xF000	/* I/F index */
+#define CDCF_IOC_IF_SHIFT	12
+#define CDCF_IOC_ID_MASK	0xFFFF0000	/* used to uniquely id an ioctl
+						 req/resp pairing */
+#define CDCF_IOC_ID_SHIFT	16	/* # of bits of shift for ID Mask */
+
+#define CDC_IOC_IF_IDX(flags)	\
+	(((flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT)
+#define CDC_IOC_ID(flags)	\
+	(((flags) & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT)
+
+#define CDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags) & CDCF_IOC_IF_MASK) >> CDCF_IOC_IF_SHIFT))
+#define CDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags = (((hdr)->flags & ~CDCF_IOC_IF_MASK) | \
+	((idx) << CDCF_IOC_IF_SHIFT)))
+
+/*
+ * BDC header
+ *
+ *   The BDC header is used on data packets to convey priority across USB.
+ */
+
+#define	BDC_HEADER_LEN		4
+
+#define BDC_PROTO_VER		1	/* Protocol version */
+
+#define BDC_FLAG_VER_MASK	0xf0	/* Protocol version mask */
+#define BDC_FLAG_VER_SHIFT	4	/* Protocol version shift */
+
+#define BDC_FLAG__UNUSED	0x03	/* Unassigned */
+#define BDC_FLAG_SUM_GOOD	0x04	/* Dongle has verified good
+					 RX checksums */
+#define BDC_FLAG_SUM_NEEDED	0x08	/* Dongle needs to do TX checksums */
+
+#define BDC_PRIORITY_MASK	0x7
+
+#define BDC_FLAG2_FC_FLAG	0x10	/* flag to indicate if pkt contains */
+						/* FLOW CONTROL info only */
+#define BDC_PRIORITY_FC_SHIFT	4	/* flow control info shift */
+
+#define BDC_FLAG2_IF_MASK	0x0f	/* APSTA: interface on which the
+					 packet was received */
+#define BDC_FLAG2_IF_SHIFT	0
+
+#define BDC_GET_IF_IDX(hdr) \
+	((int)((((hdr)->flags2) & BDC_FLAG2_IF_MASK) >> BDC_FLAG2_IF_SHIFT))
+#define BDC_SET_IF_IDX(hdr, idx) \
+	((hdr)->flags2 = (((hdr)->flags2 & ~BDC_FLAG2_IF_MASK) | \
+	((idx) << BDC_FLAG2_IF_SHIFT)))
+
+struct bdc_header {
+	u8 flags;		/* Flags */
+	u8 priority;		/* 802.1d Priority 0:2 bits, 4:7 flow
+				 control info for usb */
+	u8 flags2;
+	u8 rssi;
+};
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdbus.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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	_sdio_api_h_
+#define	_sdio_api_h_
+
+#define SDIOH_API_RC_SUCCESS                          (0x00)
+#define SDIOH_API_RC_FAIL	                      (0x01)
+#define SDIOH_API_SUCCESS(status) (status == 0)
+
+#define SDIOH_READ              0	/* Read request */
+#define SDIOH_WRITE             1	/* Write request */
+
+#define SDIOH_DATA_FIX          0	/* Fixed addressing */
+#define SDIOH_DATA_INC          1	/* Incremental addressing */
+
+#define SDIOH_CMD_TYPE_NORMAL   0	/* Normal command */
+#define SDIOH_CMD_TYPE_APPEND   1	/* Append command */
+#define SDIOH_CMD_TYPE_CUTTHRU  2	/* Cut-through command */
+
+#define SDIOH_DATA_PIO          0	/* PIO mode */
+#define SDIOH_DATA_DMA          1	/* DMA mode */
+
+typedef int SDIOH_API_RC;
+
+/* SDio Host structure */
+typedef struct sdioh_info sdioh_info_t;
+
+/* callback function, taking one arg */
+typedef void (*sdioh_cb_fn_t) (void *);
+
+/* attach, return handler on success, NULL if failed.
+ *  The handler shall be provided by all subsequent calls. No local cache
+ *  cfghdl points to the starting address of pci device mapped memory
+ */
+extern sdioh_info_t *sdioh_attach(void *cfghdl, uint irq);
+extern SDIOH_API_RC sdioh_detach(sdioh_info_t *si);
+extern SDIOH_API_RC sdioh_interrupt_register(sdioh_info_t *si,
+					     sdioh_cb_fn_t fn, void *argh);
+extern SDIOH_API_RC sdioh_interrupt_deregister(sdioh_info_t *si);
+
+/* query whether SD interrupt is enabled or not */
+extern SDIOH_API_RC sdioh_interrupt_query(sdioh_info_t *si, bool *onoff);
+
+/* enable or disable SD interrupt */
+extern SDIOH_API_RC sdioh_interrupt_set(sdioh_info_t *si, bool enable_disable);
+
+#if defined(DHD_DEBUG)
+extern bool sdioh_interrupt_pending(sdioh_info_t *si);
+#endif
+
+extern int sdioh_claim_host_and_lock(sdioh_info_t *si);
+extern int sdioh_release_host_and_unlock(sdioh_info_t *si);
+
+/* read or write one byte using cmd52 */
+extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *si, uint rw, uint fnc,
+				       uint addr, u8 *byte);
+
+/* read or write 2/4 bytes using cmd53 */
+extern SDIOH_API_RC sdioh_request_word(sdioh_info_t *si, uint cmd_type,
+				       uint rw, uint fnc, uint addr,
+				       u32 *word, uint nbyte);
+
+/* read or write any buffer using cmd53 */
+extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma,
+					 uint fix_inc, uint rw, uint fnc_num,
+					 u32 addr, uint regwidth,
+					 u32 buflen, u8 *buffer,
+					 struct sk_buff *pkt);
+
+/* get cis data */
+extern SDIOH_API_RC sdioh_cis_read(sdioh_info_t *si, uint fuc, u8 *cis,
+				   u32 length);
+
+extern SDIOH_API_RC sdioh_cfg_read(sdioh_info_t *si, uint fuc, u32 addr,
+				   u8 *data);
+extern SDIOH_API_RC sdioh_cfg_write(sdioh_info_t *si, uint fuc, u32 addr,
+				    u8 *data);
+
+/* query number of io functions */
+extern uint sdioh_query_iofnum(sdioh_info_t *si);
+
+/* handle iovars */
+extern int sdioh_iovar_op(sdioh_info_t *si, const char *name,
+			  void *params, int plen, void *arg, int len, bool set);
+
+/* Issue abort to the specified function and clear controller as needed */
+extern int sdioh_abort(sdioh_info_t *si, uint fnc);
+
+/* Start and Stop SDIO without re-enumerating the SD card. */
+extern int sdioh_start(sdioh_info_t *si, int stage);
+extern int sdioh_stop(sdioh_info_t *si);
+
+/* Reset and re-initialize the device */
+extern int sdioh_sdio_reset(sdioh_info_t *si);
+
+/* Helper function */
+void *bcmsdh_get_sdioh(bcmsdh_info_t *sdh);
+
+#endif				/* _sdio_api_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh.c	2011-05-19 00:06:34.000000000 -0400
@@ -19,8 +19,6 @@
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
-#include <bcmendian.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <hndsoc.h>
 #include <siutils.h>
@@ -39,7 +37,6 @@
 	bool init_success;	/* underlying driver successfully attached */
 	void *sdioh;		/* handler for sdioh */
 	u32 vendevid;	/* Target Vendor and Device ID on SD bus */
-	struct osl_info *osh;
 	bool regfail;		/* Save status of last
 				 reg_read/reg_write call */
 	u32 sbwad;		/* Save backplane window address */
@@ -56,8 +53,7 @@
 }
 #endif
 
-bcmsdh_info_t *bcmsdh_attach(struct osl_info *osh, void *cfghdl,
-				void **regsva, uint irq)
+bcmsdh_info_t *bcmsdh_attach(void *cfghdl, void **regsva, uint irq)
 {
 	bcmsdh_info_t *bcmsdh;
 
@@ -70,13 +66,12 @@
 	/* save the handler locally */
 	l_bcmsdh = bcmsdh;
 
-	bcmsdh->sdioh = sdioh_attach(osh, cfghdl, irq);
+	bcmsdh->sdioh = sdioh_attach(cfghdl, irq);
 	if (!bcmsdh->sdioh) {
-		bcmsdh_detach(osh, bcmsdh);
+		bcmsdh_detach(bcmsdh);
 		return NULL;
 	}
 
-	bcmsdh->osh = osh;
 	bcmsdh->init_success = true;
 
 	*regsva = (u32 *) SI_ENUM_BASE;
@@ -86,13 +81,13 @@
 	return bcmsdh;
 }
 
-int bcmsdh_detach(struct osl_info *osh, void *sdh)
+int bcmsdh_detach(void *sdh)
 {
 	bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *) sdh;
 
 	if (bcmsdh != NULL) {
 		if (bcmsdh->sdioh) {
-			sdioh_detach(osh, bcmsdh->sdioh);
+			sdioh_detach(bcmsdh->sdioh);
 			bcmsdh->sdioh = NULL;
 		}
 		kfree(bcmsdh);
@@ -324,7 +319,7 @@
 			BCMSDH_ERROR(("%s: out of memory\n", __func__));
 			return BCME_NOMEM;
 		}
-		bcopy(cis, tmp_buf, length);
+		memcpy(tmp_buf, cis, length);
 		for (tmp_ptr = tmp_buf, ptr = cis; ptr < (cis + length - 4);
 		     tmp_ptr++) {
 			ptr += sprintf((char *)ptr, "%.2x ", *tmp_ptr & 0xff);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_linux.c	2011-05-19 00:06:34.000000000 -0400
@@ -24,15 +24,14 @@
 #include <linux/pci.h>
 #include <linux/completion.h>
 
-#include <osl.h>
 #include <pcicfg.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
+#include <bcmutils.h>
 
 #if defined(OOB_INTR_ONLY)
 #include <linux/irq.h>
 extern void dhdsdio_isr(void *args);
-#include <bcmutils.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 #endif				/* defined(OOB_INTR_ONLY) */
@@ -56,7 +55,6 @@
 #else
 	struct pci_dev *dev;	/* pci device handle */
 #endif				/* BCMPLATFORM_BUS */
-	struct osl_info *osh;
 	void *regs;		/* SDIO Host Controller address */
 	bcmsdh_info_t *sdh;	/* SDIO Host Controller handle */
 	void *ch;
@@ -114,7 +112,7 @@
 #ifdef BCMSDIOH_SPI
 	/* This is the PciSpiHost. */
 	if (device == SPIH_FPGA_ID && vendor == VENDOR_BROADCOM) {
-		printf("Found PCI SPI Host Controller\n");
+		WL_NONE("Found PCI SPI Host Controller\n");
 		return true;
 	}
 #endif				/* BCMSDIOH_SPI */
@@ -142,7 +140,6 @@
 #endif				/* BCMLXSDMMC */
 int bcmsdh_probe(struct device *dev)
 {
-	struct osl_info *osh = NULL;
 	bcmsdh_hc_t *sdhc = NULL;
 	unsigned long regs = 0;
 	bcmsdh_info_t *sdh = NULL;
@@ -177,28 +174,21 @@
 	}
 #endif				/* defined(OOB_INTR_ONLY) */
 	/* allocate SDIO Host Controller state info */
-	osh = osl_attach(dev, PCI_BUS);
-	if (!osh) {
-		SDLX_MSG(("%s: osl_attach failed\n", __func__));
-		goto err;
-	}
 	sdhc = kzalloc(sizeof(bcmsdh_hc_t), GFP_ATOMIC);
 	if (!sdhc) {
 		SDLX_MSG(("%s: out of memory\n", __func__));
 		goto err;
 	}
-	sdhc->osh = osh;
-
 	sdhc->dev = (void *)dev;
 
 #ifdef BCMLXSDMMC
-	sdh = bcmsdh_attach(osh, (void *)0, (void **)&regs, irq);
+	sdh = bcmsdh_attach((void *)0, (void **)&regs, irq);
 	if (!sdh) {
 		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
 		goto err;
 	}
 #else
-	sdh = bcmsdh_attach(osh, (void *)r->start, (void **)&regs, irq);
+	sdh = bcmsdh_attach((void *)r->start, (void **)&regs, irq);
 	if (!sdh) {
 		SDLX_MSG(("%s: bcmsdh_attach failed\n", __func__));
 		goto err;
@@ -220,7 +210,7 @@
 
 	/* try to attach to the target device */
 	sdhc->ch = drvinfo.attach((vendevid >> 16), (vendevid & 0xFFFF),
-				0, 0, 0, 0, (void *)regs, NULL, sdh);
+				  0, 0, 0, 0, (void *)regs, sdh);
 	if (!sdhc->ch) {
 		SDLX_MSG(("%s: device attach failed\n", __func__));
 		goto err;
@@ -232,11 +222,10 @@
 err:
 	if (sdhc) {
 		if (sdhc->sdh)
-			bcmsdh_detach(sdhc->osh, sdhc->sdh);
+			bcmsdh_detach(sdhc->sdh);
 		kfree(sdhc);
 	}
-	if (osh)
-		osl_detach(osh);
+
 	return -ENODEV;
 }
 
@@ -246,11 +235,10 @@
 int bcmsdh_remove(struct device *dev)
 {
 	bcmsdh_hc_t *sdhc, *prev;
-	struct osl_info *osh;
 
 	sdhc = sdhcinfo;
 	drvinfo.detach(sdhc->ch);
-	bcmsdh_detach(sdhc->osh, sdhc->sdh);
+	bcmsdh_detach(sdhc->sdh);
 	/* find the SDIO Host Controller state for this pdev
 		 and take it out from the list */
 	for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) {
@@ -269,9 +257,7 @@
 	}
 
 	/* release SDIO Host Controller info */
-	osh = sdhc->osh;
 	kfree(sdhc);
-	osl_detach(osh);
 
 #if !defined(BCMLXSDMMC)
 	dev_set_drvdata(dev, NULL);
@@ -328,8 +314,6 @@
 		return IRQ_HANDLED;
 	}
 
-	WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
-
 	dhdsdio_isr((void *)dhdp->bus);
 
 	return IRQ_HANDLED;
@@ -357,7 +341,7 @@
 		if (error)
 			return -ENODEV;
 
-		set_irq_wake(sdhcinfo->oob_irq, 1);
+		irq_set_irq_wake(sdhcinfo->oob_irq, 1);
 		sdhcinfo->oob_irq_registered = true;
 	}
 
@@ -368,7 +352,7 @@
 {
 	SDLX_MSG(("%s: Enter\n", __func__));
 
-	set_irq_wake(sdhcinfo->oob_irq, 0);
+	irq_set_irq_wake(sdhcinfo->oob_irq, 0);
 	disable_irq(sdhcinfo->oob_irq);	/* just in case.. */
 	free_irq(sdhcinfo->oob_irq, NULL);
 	sdhcinfo->oob_irq_registered = false;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,8 +17,6 @@
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
 #include <bcmdevs.h>
-#include <bcmendian.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <sdio.h>		/* SDIO Device and Protocol Specs */
 #include <sdioh.h>		/* SDIO Host Controller Specification */
@@ -112,7 +110,7 @@
 /*
  *	Public entry points & extern's
  */
-extern sdioh_info_t *sdioh_attach(struct osl_info *osh, void *bar0, uint irq)
+sdioh_info_t *sdioh_attach(void *bar0, uint irq)
 {
 	sdioh_info_t *sd;
 	int err_ret;
@@ -129,7 +127,6 @@
 		sd_err(("sdioh_attach: out of memory\n"));
 		return NULL;
 	}
-	sd->osh = osh;
 	if (sdioh_sdmmc_osinit(sd) != 0) {
 		sd_err(("%s:sdioh_sdmmc_osinit() failed\n", __func__));
 		kfree(sd);
@@ -175,7 +172,7 @@
 	return sd;
 }
 
-extern SDIOH_API_RC sdioh_detach(struct osl_info *osh, sdioh_info_t *sd)
+extern SDIOH_API_RC sdioh_detach(sdioh_info_t *sd)
 {
 	sd_trace(("%s\n", __func__));
 
@@ -267,7 +264,7 @@
 }
 #endif				/* defined(OOB_INTR_ONLY) && defined(HW_OOB) */
 
-/* Configure callback to client when we recieve client interrupt */
+/* Configure callback to client when we receive client interrupt */
 extern SDIOH_API_RC
 sdioh_interrupt_register(sdioh_info_t *sd, sdioh_cb_fn_t fn, void *argh)
 {
@@ -441,7 +438,7 @@
 		val_size = sizeof(int);
 
 	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
+		memcpy(&int_val, params, sizeof(int_val));
 
 	bool_val = (int_val != 0) ? true : false;
 
@@ -449,7 +446,7 @@
 	switch (actionid) {
 	case IOV_GVAL(IOV_MSGLEVEL):
 		int_val = (s32) sd_msglevel;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_MSGLEVEL):
@@ -458,7 +455,7 @@
 
 	case IOV_GVAL(IOV_BLOCKMODE):
 		int_val = (s32) si->sd_blockmode;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_BLOCKMODE):
@@ -472,7 +469,7 @@
 			break;
 		}
 		int_val = (s32) si->client_block_size[int_val];
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_BLOCKSIZE):
@@ -514,12 +511,12 @@
 
 	case IOV_GVAL(IOV_RXCHAIN):
 		int_val = false;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_DMA):
 		int_val = (s32) si->sd_use_dma;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_DMA):
@@ -528,7 +525,7 @@
 
 	case IOV_GVAL(IOV_USEINTS):
 		int_val = (s32) si->use_client_ints;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_USEINTS):
@@ -542,7 +539,7 @@
 
 	case IOV_GVAL(IOV_DIVISOR):
 		int_val = (u32) sd_divisor;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_DIVISOR):
@@ -551,7 +548,7 @@
 
 	case IOV_GVAL(IOV_POWER):
 		int_val = (u32) sd_power;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_POWER):
@@ -560,7 +557,7 @@
 
 	case IOV_GVAL(IOV_CLOCK):
 		int_val = (u32) sd_clock;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_CLOCK):
@@ -569,7 +566,7 @@
 
 	case IOV_GVAL(IOV_SDMODE):
 		int_val = (u32) sd_sdmode;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDMODE):
@@ -578,7 +575,7 @@
 
 	case IOV_GVAL(IOV_HISPEED):
 		int_val = (u32) sd_hiok;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_HISPEED):
@@ -587,12 +584,12 @@
 
 	case IOV_GVAL(IOV_NUMINTS):
 		int_val = (s32) si->intrcount;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_NUMLOCALINTS):
 		int_val = (s32) 0;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_HOSTREG):
@@ -621,7 +618,7 @@
 				int_val = 32;	/* sdioh_sdmmc_rreg(si,
 						 sd_ptr->offset); */
 
-			bcopy(&int_val, arg, sizeof(int_val));
+			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
 
@@ -657,7 +654,7 @@
 			}
 
 			int_val = (int)data;
-			bcopy(&int_val, arg, sizeof(int_val));
+			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
 
@@ -735,7 +732,7 @@
 	}
 
 	/* Only the lower 17-bits are valid */
-	scratch = ltoh32(scratch);
+	scratch = le32_to_cpu(scratch);
 	scratch &= 0x0001FFFF;
 	return scratch;
 }
@@ -1039,7 +1036,7 @@
 	if (pkt == NULL) {
 		sd_data(("%s: Creating new %s Packet, len=%d\n",
 			 __func__, write ? "TX" : "RX", buflen_u));
-		mypkt = pkt_buf_get_skb(sd->osh, buflen_u);
+		mypkt = pkt_buf_get_skb(buflen_u);
 		if (!mypkt) {
 			sd_err(("%s: pkt_buf_get_skb failed: len %d\n",
 				__func__, buflen_u));
@@ -1048,16 +1045,16 @@
 
 		/* For a write, copy the buffer data into the packet. */
 		if (write)
-			bcopy(buffer, mypkt->data, buflen_u);
+			memcpy(mypkt->data, buffer, buflen_u);
 
 		Status =
 		    sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
 
 		/* For a read, copy the packet data back to the buffer. */
 		if (!write)
-			bcopy(mypkt->data, buffer, buflen_u);
+			memcpy(buffer, mypkt->data, buflen_u);
 
-		pkt_buf_free_skb(sd->osh, mypkt, write ? true : false);
+		pkt_buf_free_skb(mypkt);
 	} else if (((u32) (pkt->data) & DMA_ALIGN_MASK) != 0) {
 		/* Case 2: We have a packet, but it is unaligned. */
 
@@ -1066,7 +1063,7 @@
 
 		sd_data(("%s: Creating aligned %s Packet, len=%d\n",
 			 __func__, write ? "TX" : "RX", pkt->len));
-		mypkt = pkt_buf_get_skb(sd->osh, pkt->len);
+		mypkt = pkt_buf_get_skb(pkt->len);
 		if (!mypkt) {
 			sd_err(("%s: pkt_buf_get_skb failed: len %d\n",
 				__func__, pkt->len));
@@ -1075,16 +1072,16 @@
 
 		/* For a write, copy the buffer data into the packet. */
 		if (write)
-			bcopy(pkt->data, mypkt->data, pkt->len);
+			memcpy(mypkt->data, pkt->data, pkt->len);
 
 		Status =
 		    sdioh_request_packet(sd, fix_inc, write, func, addr, mypkt);
 
 		/* For a read, copy the packet data back to the buffer. */
 		if (!write)
-			bcopy(mypkt->data, pkt->data, mypkt->len);
+			memcpy(pkt->data, mypkt->data, mypkt->len);
 
-		pkt_buf_free_skb(sd->osh, mypkt, write ? true : false);
+		pkt_buf_free_skb(mypkt);
 	} else {		/* case 3: We have a packet and
 				 it is aligned. */
 		sd_data(("%s: Aligned %s Packet, direct DMA\n",
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,134 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 __BCMSDH_SDMMC_H__
+#define __BCMSDH_SDMMC_H__
+
+#ifdef BCMDBG
+#define sd_err(x)	\
+	do { \
+		if ((sd_msglevel & SDH_ERROR_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_trace(x)	\
+	do { \
+		if ((sd_msglevel & SDH_TRACE_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_info(x)	\
+	do { \
+		if ((sd_msglevel & SDH_INFO_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_debug(x)	\
+	do { \
+		if ((sd_msglevel & SDH_DEBUG_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_data(x)	\
+	do { \
+		if ((sd_msglevel & SDH_DATA_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#define sd_ctrl(x)	\
+	do { \
+		if ((sd_msglevel & SDH_CTRL_VAL) && net_ratelimit()) \
+			printk x; \
+	} while (0)
+#else
+#define sd_err(x)
+#define sd_trace(x)
+#define sd_info(x)
+#define sd_debug(x)
+#define sd_data(x)
+#define sd_ctrl(x)
+#endif
+
+/* Allocate/init/free per-OS private data */
+extern int sdioh_sdmmc_osinit(sdioh_info_t *sd);
+extern void sdioh_sdmmc_osfree(sdioh_info_t *sd);
+
+#define BLOCK_SIZE_64 64
+#define BLOCK_SIZE_512 512
+#define BLOCK_SIZE_4318 64
+#define BLOCK_SIZE_4328 512
+
+/* internal return code */
+#define SUCCESS	0
+#define ERROR	1
+
+/* private bus modes */
+#define SDIOH_MODE_SD4		2
+#define CLIENT_INTR 		0x100	/* Get rid of this! */
+
+struct sdioh_info {
+	struct osl_info *osh;		/* osh handler */
+	bool client_intr_enabled;	/* interrupt connnected flag */
+	bool intr_handler_valid;	/* client driver interrupt handler valid */
+	sdioh_cb_fn_t intr_handler;	/* registered interrupt handler */
+	void *intr_handler_arg;	/* argument to call interrupt handler */
+	u16 intmask;		/* Current active interrupts */
+	void *sdos_info;	/* Pointer to per-OS private data */
+
+	uint irq;		/* Client irq */
+	int intrcount;		/* Client interrupts */
+	bool sd_use_dma;	/* DMA on CMD53 */
+	bool sd_blockmode;	/* sd_blockmode == false => 64 Byte Cmd 53s. */
+	/*  Must be on for sd_multiblock to be effective */
+	bool use_client_ints;	/* If this is false, make sure to restore */
+	int sd_mode;		/* SD1/SD4/SPI */
+	int client_block_size[SDIOD_MAX_IOFUNCS];	/* Blocksize */
+	u8 num_funcs;	/* Supported funcs on client */
+	u32 com_cis_ptr;
+	u32 func_cis_ptr[SDIOD_MAX_IOFUNCS];
+	uint max_dma_len;
+	uint max_dma_descriptors;	/* DMA Descriptors supported by this controller. */
+	/*	SDDMA_DESCRIPTOR	SGList[32]; *//* Scatter/Gather DMA List */
+};
+
+/************************************************************
+ * Internal interfaces: per-port references into bcmsdh_sdmmc.c
+ */
+
+/* Global message bits */
+extern uint sd_msglevel;
+
+/* OS-independent interrupt handler */
+extern bool check_client_intr(sdioh_info_t *sd);
+
+/* Core interrupt enable/disable of device interrupts */
+extern void sdioh_sdmmc_devintr_on(sdioh_info_t *sd);
+extern void sdioh_sdmmc_devintr_off(sdioh_info_t *sd);
+
+/**************************************************************
+ * Internal interfaces: bcmsdh_sdmmc.c references to per-port code
+ */
+
+/* Register mapping routines */
+extern u32 *sdioh_sdmmc_reg_map(s32 addr, int size);
+extern void sdioh_sdmmc_reg_unmap(s32 addr, int size);
+
+/* Interrupt (de)registration routines */
+extern int sdioh_sdmmc_register_irq(sdioh_info_t *sd, uint irq);
+extern void sdioh_sdmmc_free_irq(uint irq, sdioh_info_t *sd);
+
+typedef struct _BCMSDH_SDMMC_INSTANCE {
+	sdioh_info_t *sd;
+	struct sdio_func *func[SDIOD_MAX_IOFUNCS];
+	u32 host_claimed;
+} BCMSDH_SDMMC_INSTANCE, *PBCMSDH_SDMMC_INSTANCE;
+
+#endif				/* __BCMSDH_SDMMC_H__ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmsdh_sdmmc_linux.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/sched.h>	/* request_irq() */
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
 #include <sdio.h>		/* SDIO Specs */
 #include <bcmsdbus.h>		/* bcmsdh to/from specific controller APIs */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmutils.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmutils.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmutils.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmutils.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1 @@
+#include "../util/bcmutils.c"
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmwifi.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmwifi.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/bcmwifi.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/bcmwifi.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1 @@
+#include "../util/bcmwifi.c"
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_bus.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_bus.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_bus.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_bus.h	2011-05-19 00:06:34.000000000 -0400
@@ -27,7 +27,7 @@
 
 /* Download firmware image and nvram image */
 extern bool dhd_bus_download_firmware(struct dhd_bus *bus,
-	      struct osl_info *osh, char *fw_path, char *nv_path);
+				      char *fw_path, char *nv_path);
 
 /* Stop bus module: clear pending frames, disable data flow */
 extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_cdc.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,11 +17,9 @@
 #include <linux/types.h>
 #include <linux/netdevice.h>
 #include <bcmdefs.h>
-#include <osl.h>
 
 #include <bcmutils.h>
 #include <bcmcdc.h>
-#include <bcmendian.h>
 
 #include <dngl_stats.h>
 #include <dhd.h>
@@ -65,7 +63,7 @@
 static int dhdcdc_msg(dhd_pub_t *dhd)
 {
 	dhd_prot_t *prot = dhd->prot;
-	int len = ltoh32(prot->msg.len) + sizeof(cdc_ioctl_t);
+	int len = le32_to_cpu(prot->msg.len) + sizeof(cdc_ioctl_t);
 
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -93,7 +91,7 @@
 				  len + sizeof(cdc_ioctl_t));
 		if (ret < 0)
 			break;
-	} while (CDC_IOC_ID(ltoh32(prot->msg.flags)) != id);
+	} while (CDC_IOC_ID(le32_to_cpu(prot->msg.flags)) != id);
 
 	return ret;
 }
@@ -124,11 +122,11 @@
 
 	memset(msg, 0, sizeof(cdc_ioctl_t));
 
-	msg->cmd = htol32(cmd);
-	msg->len = htol32(len);
+	msg->cmd = cpu_to_le32(cmd);
+	msg->len = cpu_to_le32(len);
 	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT);
 	CDC_SET_IF_IDX(msg, ifidx);
-	msg->flags = htol32(msg->flags);
+	msg->flags = cpu_to_le32(msg->flags);
 
 	if (buf)
 		memcpy(prot->buf, buf, len);
@@ -146,7 +144,7 @@
 	if (ret < 0)
 		goto done;
 
-	flags = ltoh32(msg->flags);
+	flags = le32_to_cpu(msg->flags);
 	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
 
 	if ((id < prot->reqid) && (++retries < RETRIES))
@@ -170,7 +168,7 @@
 
 	/* Check the ERROR flag */
 	if (flags & CDCF_IOC_ERROR) {
-		ret = ltoh32(msg->status);
+		ret = le32_to_cpu(msg->status);
 		/* Cache error from dongle */
 		dhd->dongle_error = ret;
 	}
@@ -191,11 +189,11 @@
 
 	memset(msg, 0, sizeof(cdc_ioctl_t));
 
-	msg->cmd = htol32(cmd);
-	msg->len = htol32(len);
+	msg->cmd = cpu_to_le32(cmd);
+	msg->len = cpu_to_le32(len);
 	msg->flags = (++prot->reqid << CDCF_IOC_ID_SHIFT) | CDCF_IOC_SET;
 	CDC_SET_IF_IDX(msg, ifidx);
-	msg->flags = htol32(msg->flags);
+	msg->flags = cpu_to_le32(msg->flags);
 
 	if (buf)
 		memcpy(prot->buf, buf, len);
@@ -208,7 +206,7 @@
 	if (ret < 0)
 		goto done;
 
-	flags = ltoh32(msg->flags);
+	flags = le32_to_cpu(msg->flags);
 	id = (flags & CDCF_IOC_ID_MASK) >> CDCF_IOC_ID_SHIFT;
 
 	if (id != prot->reqid) {
@@ -220,7 +218,7 @@
 
 	/* Check the ERROR flag */
 	if (flags & CDCF_IOC_ERROR) {
-		ret = ltoh32(msg->status);
+		ret = le32_to_cpu(msg->status);
 		/* Cache error from dongle */
 		dhd->dongle_error = ret;
 	}
@@ -276,8 +274,8 @@
 		ret = 0;
 	else {
 		cdc_ioctl_t *msg = &prot->msg;
-		ioc->needed = ltoh32(msg->len);	/* len == needed when set/query
-						 fails from dongle */
+		/* len == needed when set/query fails from dongle */
+		ioc->needed = le32_to_cpu(msg->len);
 	}
 
 	/* Intercept the wme_dp ioctl here */
@@ -286,8 +284,8 @@
 
 		slen = strlen("wme_dp") + 1;
 		if (len >= (int)(slen + sizeof(int)))
-			bcopy(((char *)buf + slen), &val, sizeof(int));
-		dhd->wme_dp = (u8) ltoh32(val);
+			memcpy(&val, (char *)buf + slen, sizeof(int));
+		dhd->wme_dp = (u8) le32_to_cpu(val);
 	}
 
 	prot->pending = false;
@@ -345,26 +343,6 @@
 	BDC_SET_IF_IDX(h, ifidx);
 }
 
-bool dhd_proto_fcinfo(dhd_pub_t *dhd, struct sk_buff *pktbuf, u8 * fcbits)
-{
-#ifdef BDC
-	struct bdc_header *h;
-
-	if (pktbuf->len < BDC_HEADER_LEN) {
-		DHD_ERROR(("%s: rx data too short (%d < %d)\n",
-			   __func__, pktbuf->len, BDC_HEADER_LEN));
-		return BCME_ERROR;
-	}
-
-	h = (struct bdc_header *)(pktbuf->data);
-
-	*fcbits = h->priority >> BDC_PRIORITY_FC_SHIFT;
-	if ((h->flags2 & BDC_FLAG2_FC_FLAG) == BDC_FLAG2_FC_FLAG)
-		return true;
-#endif
-	return false;
-}
-
 int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, struct sk_buff *pktbuf)
 {
 #ifdef BDC
@@ -437,8 +415,7 @@
 	return 0;
 
 fail:
-	if (cdc != NULL)
-		kfree(cdc);
+	kfree(cdc);
 	return BCME_NOMEM;
 }
 
@@ -477,7 +454,7 @@
 		dhd_os_proto_unblock(dhd);
 		return ret;
 	}
-	memcpy(dhd->mac.octet, buf, ETH_ALEN);
+	memcpy(dhd->mac, buf, ETH_ALEN);
 
 	dhd_os_proto_unblock(dhd);
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_common.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_common.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_common.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_common.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,9 +17,7 @@
 #include <linux/string.h>
 #include <bcmdefs.h>
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <bcmutils.h>
-#include <bcmendian.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhd_bus.h>
@@ -37,11 +35,6 @@
 u32 dhd_conn_status;
 u32 dhd_conn_reason;
 
-#define htod32(i) i
-#define htod16(i) i
-#define dtoh32(i) i
-#define dtoh16(i) i
-
 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
 			    uint len);
 extern void dhd_ind_scan_confirm(void *h, bool status);
@@ -57,8 +50,8 @@
 #error DHD_SDALIGN is not a power of 2!
 #endif
 
-#ifdef DHD_DEBUG
 #define EPI_VERSION_STR         "4.218.248.5"
+#ifdef DHD_DEBUG
 const char dhd_version[] =
 "Dongle Host Driver, version " EPI_VERSION_STR "\nCompiled on " __DATE__
 " at " __TIME__;
@@ -214,7 +207,7 @@
 		goto exit;
 
 	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
+		memcpy(&int_val, params, sizeof(int_val));
 
 	switch (actionid) {
 	case IOV_GVAL(IOV_VERSION):
@@ -224,7 +217,7 @@
 
 	case IOV_GVAL(IOV_MSGLEVEL):
 		int_val = (s32) dhd_msg_level;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_MSGLEVEL):
@@ -239,12 +232,12 @@
 
 	case IOV_GVAL(IOV_BCMERROR):
 		int_val = (s32) dhd_pub->bcmerror;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_WDTICK):
 		int_val = (s32) dhd_watchdog_ms;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_WDTICK):
@@ -262,7 +255,7 @@
 #ifdef DHD_DEBUG
 	case IOV_GVAL(IOV_DCONSOLE_POLL):
 		int_val = (s32) dhd_console_ms;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_DCONSOLE_POLL):
@@ -290,7 +283,7 @@
 
 	case IOV_GVAL(IOV_IOCTLTIMEOUT):{
 			int_val = (s32) dhd_os_get_ioctl_resp_timeout();
-			bcopy(&int_val, arg, sizeof(int_val));
+			memcpy(arg, &int_val, sizeof(int_val));
 			break;
 		}
 
@@ -312,21 +305,6 @@
 	return bcmerror;
 }
 
-/* Store the status of a connection attempt for later retrieval by an iovar */
-void dhd_store_conn_status(u32 event, u32 status, u32 reason)
-{
-	/* Do not overwrite a WLC_E_PRUNE with a WLC_E_SET_SSID
-	 * because an encryption/rsn mismatch results in both events, and
-	 * the important information is in the WLC_E_PRUNE.
-	 */
-	if (!(event == WLC_E_SET_SSID && status == WLC_E_STATUS_FAIL &&
-	      dhd_conn_event == WLC_E_PRUNE)) {
-		dhd_conn_event = event;
-		dhd_conn_status = status;
-		dhd_conn_reason = reason;
-	}
-}
-
 bool dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, struct sk_buff *pkt,
 		  int prec)
 {
@@ -368,7 +346,7 @@
 			ASSERT(p);
 		}
 
-		pkt_buf_free_skb(dhdp->osh, p, true);
+		pkt_buf_free_skb(p);
 	}
 
 	/* Enqueue */
@@ -592,14 +570,14 @@
 		WLC_E_PFN_SCAN_COMPLETE, "SCAN_COMPLETE"}
 	};
 	uint event_type, flags, auth_type, datalen;
-	event_type = ntoh32(event->event_type);
-	flags = ntoh16(event->flags);
-	status = ntoh32(event->status);
-	reason = ntoh32(event->reason);
-	auth_type = ntoh32(event->auth_type);
-	datalen = ntoh32(event->datalen);
+	event_type = be32_to_cpu(event->event_type);
+	flags = be16_to_cpu(event->flags);
+	status = be32_to_cpu(event->status);
+	reason = be32_to_cpu(event->reason);
+	auth_type = be32_to_cpu(event->auth_type);
+	datalen = be32_to_cpu(event->datalen);
 	/* debug dump of event messages */
-	sprintf(eabuf, "%pM", event->addr.octet);
+	sprintf(eabuf, "%pM", event->addr);
 
 	event_name = "UNKNOWN";
 	for (i = 0; i < ARRAY_SIZE(event_names); i++) {
@@ -653,9 +631,9 @@
 
 	case WLC_E_AUTH:
 	case WLC_E_AUTH_IND:
-		if (auth_type == DOT11_OPEN_SYSTEM)
+		if (auth_type == WLAN_AUTH_OPEN)
 			auth_str = "Open System";
-		else if (auth_type == DOT11_SHARED_KEY)
+		else if (auth_type == WLAN_AUTH_SHARED_KEY)
 			auth_str = "Shared Key";
 		else {
 			sprintf(err_msg, "AUTH unknown: %d", (int)auth_type);
@@ -754,34 +732,35 @@
 			memcpy(&hdr, buf, MSGTRACE_HDRLEN);
 
 			if (hdr.version != MSGTRACE_VERSION) {
-				printf
+				DHD_ERROR(
 				    ("\nMACEVENT: %s [unsupported version --> "
 				     "dhd version:%d dongle version:%d]\n",
-				     event_name, MSGTRACE_VERSION, hdr.version);
+				     event_name, MSGTRACE_VERSION, hdr.version)
+				);
 				/* Reset datalen to avoid display below */
 				datalen = 0;
 				break;
 			}
 
 			/* There are 2 bytes available at the end of data */
-			buf[MSGTRACE_HDRLEN + ntoh16(hdr.len)] = '\0';
+			buf[MSGTRACE_HDRLEN + be16_to_cpu(hdr.len)] = '\0';
 
-			if (ntoh32(hdr.discarded_bytes)
-			    || ntoh32(hdr.discarded_printf)) {
-				printf
+			if (be32_to_cpu(hdr.discarded_bytes)
+			    || be32_to_cpu(hdr.discarded_printf)) {
+				DHD_ERROR(
 				    ("\nWLC_E_TRACE: [Discarded traces in dongle -->"
 				     "discarded_bytes %d discarded_printf %d]\n",
-				     ntoh32(hdr.discarded_bytes),
-				     ntoh32(hdr.discarded_printf));
+				     be32_to_cpu(hdr.discarded_bytes),
+				     be32_to_cpu(hdr.discarded_printf)));
 			}
 
-			nblost = ntoh32(hdr.seqnum) - seqnum_prev - 1;
+			nblost = be32_to_cpu(hdr.seqnum) - seqnum_prev - 1;
 			if (nblost > 0) {
-				printf
+				DHD_ERROR(
 				    ("\nWLC_E_TRACE: [Event lost --> seqnum %d nblost %d\n",
-				     ntoh32(hdr.seqnum), nblost);
+				     be32_to_cpu(hdr.seqnum), nblost));
 			}
-			seqnum_prev = ntoh32(hdr.seqnum);
+			seqnum_prev = be32_to_cpu(hdr.seqnum);
 
 			/* Display the trace buffer. Advance from \n to \n to
 			 * avoid display big
@@ -790,10 +769,10 @@
 			p = (char *)&buf[MSGTRACE_HDRLEN];
 			while ((s = strstr(p, "\n")) != NULL) {
 				*s = '\0';
-				printf("%s\n", p);
+				printk(KERN_DEBUG"%s\n", p);
 				p = s + 1;
 			}
-			printf("%s\n", p);
+			printk(KERN_DEBUG "%s\n", p);
 
 			/* Reset datalen to avoid display below */
 			datalen = 0;
@@ -802,7 +781,7 @@
 
 	case WLC_E_RSSI:
 		DHD_EVENT(("MACEVENT: %s %d\n", event_name,
-			   ntoh32(*((int *)event_data))));
+			   be32_to_cpu(*((int *)event_data))));
 		break;
 
 	default:
@@ -840,7 +819,7 @@
 	}
 
 	/* BRCM event pkt may be unaligned - use xxx_ua to load user_subtype. */
-	if (ntoh16_ua((void *)&pvt_data->bcm_hdr.usr_subtype) !=
+	if (get_unaligned_be16(&pvt_data->bcm_hdr.usr_subtype) !=
 	    BCMILCP_BCM_SUBTYPE_EVENT) {
 		DHD_ERROR(("%s: mismatched subtype, bailing\n", __func__));
 		return BCME_ERROR;
@@ -852,10 +831,10 @@
 	/* memcpy since BRCM event pkt may be unaligned. */
 	memcpy(event, &pvt_data->event, sizeof(wl_event_msg_t));
 
-	type = ntoh32_ua((void *)&event->event_type);
-	flags = ntoh16_ua((void *)&event->flags);
-	status = ntoh32_ua((void *)&event->status);
-	evlen = ntoh32_ua((void *)&event->datalen) + sizeof(bcm_event_t);
+	type = get_unaligned_be32(&event->event_type);
+	flags = get_unaligned_be16(&event->flags);
+	status = get_unaligned_be32(&event->status);
+	evlen = get_unaligned_be32(&event->datalen) + sizeof(bcm_event_t);
 
 	switch (type) {
 	case WLC_E_IF:
@@ -868,7 +847,7 @@
 				if (ifevent->action == WLC_E_IF_ADD)
 					dhd_add_if(dhd, ifevent->ifidx,
 						   NULL, event->ifname,
-						   pvt_data->eth.ether_dhost,
+						   pvt_data->eth.h_dest,
 						   ifevent->flags,
 						   ifevent->bssidx);
 				else
@@ -909,10 +888,10 @@
 		if (type == WLC_E_NDIS_LINK) {
 			u32 temp;
 
-			temp = ntoh32_ua((void *)&event->event_type);
+			temp = get_unaligned_be32(&event->event_type);
 			DHD_TRACE(("Converted to WLC_E_LINK type %d\n", temp));
 
-			temp = ntoh32(WLC_E_NDIS_LINK);
+			temp = be32_to_cpu(WLC_E_NDIS_LINK);
 			memcpy((void *)(&pvt_data->event.event_type), &temp,
 			       sizeof(pvt_data->event.event_type));
 		}
@@ -926,42 +905,6 @@
 	return BCME_OK;
 }
 
-void wl_event_to_host_order(wl_event_msg_t *evt)
-{
-	/* Event struct members passed from dongle to host are stored
-	 * in network
-	 * byte order. Convert all members to host-order.
-	 */
-	evt->event_type = ntoh32(evt->event_type);
-	evt->flags = ntoh16(evt->flags);
-	evt->status = ntoh32(evt->status);
-	evt->reason = ntoh32(evt->reason);
-	evt->auth_type = ntoh32(evt->auth_type);
-	evt->datalen = ntoh32(evt->datalen);
-	evt->version = ntoh16(evt->version);
-}
-
-void print_buf(void *pbuf, int len, int bytes_per_line)
-{
-	int i, j = 0;
-	unsigned char *buf = pbuf;
-
-	if (bytes_per_line == 0)
-		bytes_per_line = len;
-
-	for (i = 0; i < len; i++) {
-		printf("%2.2x", *buf++);
-		j++;
-		if (j == bytes_per_line) {
-			printf("\n");
-			j = 0;
-		} else {
-			printf(":");
-		}
-	}
-	printf("\n");
-}
-
 /* Convert user's input in hex pattern to byte-size mask */
 static int wl_pattern_atoh(char *src, char *dst)
 {
@@ -1025,10 +968,10 @@
 	pkt_filterp = (wl_pkt_filter_enable_t *) (buf + str_len + 1);
 
 	/* Parse packet filter id. */
-	enable_parm.id = htod32(simple_strtoul(argv[i], NULL, 0));
+	enable_parm.id = simple_strtoul(argv[i], NULL, 0);
 
 	/* Parse enable/disable value. */
-	enable_parm.enable = htod32(enable);
+	enable_parm.enable = enable;
 
 	buf_len += sizeof(enable_parm);
 	memcpy((char *)pkt_filterp, &enable_parm, sizeof(enable_parm));
@@ -1053,8 +996,7 @@
 			   __func__, arg, rc));
 
 fail:
-	if (arg_org)
-		kfree(arg_org);
+	kfree(arg_org);
 }
 
 void dhd_pktfilter_offload_set(dhd_pub_t *dhd, char *arg)
@@ -1113,7 +1055,7 @@
 	pkt_filterp = (wl_pkt_filter_t *) (buf + str_len + 1);
 
 	/* Parse packet filter id. */
-	pkt_filter.id = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.id = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Polarity not provided\n"));
@@ -1121,7 +1063,7 @@
 	}
 
 	/* Parse filter polarity. */
-	pkt_filter.negate_match = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.negate_match = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Filter type not provided\n"));
@@ -1129,7 +1071,7 @@
 	}
 
 	/* Parse filter type. */
-	pkt_filter.type = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.type = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Offset not provided\n"));
@@ -1137,7 +1079,7 @@
 	}
 
 	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = htod32(simple_strtoul(argv[i], NULL, 0));
+	pkt_filter.u.pattern.offset = simple_strtoul(argv[i], NULL, 0);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Bitmask not provided\n"));
@@ -1146,8 +1088,8 @@
 
 	/* Parse pattern filter mask. */
 	mask_size =
-	    htod32(wl_pattern_atoh
-		   (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern));
+	    wl_pattern_atoh
+		   (argv[i], (char *)pkt_filterp->u.pattern.mask_and_pattern);
 
 	if (NULL == argv[++i]) {
 		DHD_ERROR(("Pattern not provided\n"));
@@ -1156,9 +1098,9 @@
 
 	/* Parse pattern filter pattern. */
 	pattern_size =
-	    htod32(wl_pattern_atoh(argv[i],
+	    wl_pattern_atoh(argv[i],
 				   (char *)&pkt_filterp->u.pattern.
-				   mask_and_pattern[mask_size]));
+				   mask_and_pattern[mask_size]);
 
 	if (mask_size != pattern_size) {
 		DHD_ERROR(("Mask and pattern not the same size\n"));
@@ -1189,11 +1131,9 @@
 			   __func__, arg));
 
 fail:
-	if (arg_org)
-		kfree(arg_org);
+	kfree(arg_org);
 
-	if (buf)
-		kfree(buf);
+	kfree(buf);
 }
 
 void dhd_arp_offload_set(dhd_pub_t *dhd, int arp_mode)
@@ -1242,7 +1182,7 @@
 	int scan_unassoc_time = 40;
 #ifdef GET_CUSTOM_MAC_ENABLE
 	int ret = 0;
-	struct ether_addr ea_addr;
+	u8 ea_addr[ETH_ALEN];
 #endif				/* GET_CUSTOM_MAC_ENABLE */
 
 	dhd_os_proto_block(dhd);
@@ -1254,9 +1194,9 @@
 	 ** firmware but unique per board mac address maybe provided by
 	 ** customer code
 	 */
-	ret = dhd_custom_get_mac_address(ea_addr.octet);
+	ret = dhd_custom_get_mac_address(ea_addr);
 	if (!ret) {
-		bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETH_ALEN,
+		bcm_mkiovar("cur_etheraddr", (void *)ea_addr, ETH_ALEN,
 			    buf, sizeof(buf));
 		ret = dhdcdc_set_ioctl(dhd, 0, WLC_SET_VAR, buf, sizeof(buf));
 		if (ret < 0) {
@@ -1478,8 +1418,7 @@
 				   bi->BSSID.octet[2], bi->BSSID.octet[3],
 				   bi->BSSID.octet[4], bi->BSSID.octet[5]));
 
-			bi = (wl_bss_info_t *)((unsigned long)bi +
-						dtoh32(bi->length));
+			bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
 		}
 		iscan_cur = iscan_cur->next;
 		l++;
@@ -1543,18 +1482,16 @@
 					bi->BSSID.octet[5]));
 
 					bi_new = bi;
-					bi = (wl_bss_info_t *)((unsigned long)bi +
-								dtoh32
-								(bi->length));
+					bi = (wl_bss_info_t *)((unsigned long)
+							       bi + bi->length);
 /*
 			if(bi && bi_new) {
-				bcopy(bi, bi_new, results->buflen -
-				dtoh32(bi_new->length));
-				results->buflen -= dtoh32(bi_new->length);
+				memcpy(bi_new, bi, results->buflen -
+				bi_new->length);
+				results->buflen -= bi_new->length;
 			}
 */
-					results->buflen -=
-					    dtoh32(bi_new->length);
+					results->buflen -= bi_new->length;
 					results->count--;
 
 					for (j = i; j < results->count; j++) {
@@ -1570,16 +1507,13 @@
 
 							bi_next =
 							    (wl_bss_info_t *)((unsigned long)bi +
-								 dtoh32
-								 (bi->length));
-							bcopy(bi, bi_new,
-							      dtoh32
-							      (bi->length));
+								 bi->length);
+							memcpy(bi_new, bi,
+							      bi->length);
 							bi_new =
 							    (wl_bss_info_t *)((unsigned long)bi_new +
-								 dtoh32
-								 (bi_new->
-								  length));
+								 bi_new->
+								  length);
 							bi = bi_next;
 						}
 					}
@@ -1594,7 +1528,7 @@
 					break;
 				}
 				bi = (wl_bss_info_t *)((unsigned long)bi +
-							dtoh32(bi->length));
+							bi->length);
 			}
 		}
 		iscan_cur = iscan_cur->next;
@@ -1648,7 +1582,7 @@
 
 		dhd_iscan_delete_bss(dhdp, bi->BSSID.octet, iscan_cur);
 
-		bi = (wl_bss_info_t *)((unsigned long)bi + dtoh32(bi->length));
+		bi = (wl_bss_info_t *)((unsigned long)bi + bi->length);
 	}
 
 done:
@@ -1677,15 +1611,15 @@
 	params.params.bss_type = DOT11_BSSTYPE_ANY;
 	params.params.scan_type = DOT11_SCANTYPE_ACTIVE;
 
-	params.params.nprobes = htod32(-1);
-	params.params.active_time = htod32(-1);
-	params.params.passive_time = htod32(-1);
-	params.params.home_time = htod32(-1);
-	params.params.channel_num = htod32(0);
+	params.params.nprobes = -1;
+	params.params.active_time = -1;
+	params.params.passive_time = -1;
+	params.params.home_time = -1;
+	params.params.channel_num = 0;
 
-	params.version = htod32(ISCAN_REQ_VERSION);
-	params.action = htod16(action);
-	params.scan_duration = htod16(0);
+	params.version = ISCAN_REQ_VERSION;
+	params.action = action;
+	params.scan_duration = 0;
 
 	bcm_mkiovar("iscan", (char *)&params, sizeof(wl_iscan_params_t), buf,
 		    WLC_IOCTL_SMLEN);
@@ -1722,16 +1656,16 @@
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+	list.results.buflen = WLC_IW_ISCAN_MAXLEN;
 	bcm_mkiovar("iscanresults", (char *)&list, WL_ISCAN_RESULTS_FIXED_SIZE,
 		    iscan_cur->iscan_buf, WLC_IW_ISCAN_MAXLEN);
 	rc = dhd_wl_ioctl(dhdp, WLC_GET_VAR, iscan_cur->iscan_buf,
 			  WLC_IW_ISCAN_MAXLEN);
 
-	results->buflen = dtoh32(results->buflen);
-	results->version = dtoh32(results->version);
-	*scan_count = results->count = dtoh32(results->count);
-	status = dtoh32(list_buf->status);
+	results->buflen = results->buflen;
+	results->version = results->version;
+	*scan_count = results->count = results->count;
+	status = list_buf->status;
 
 	dhd_iscan_unlock();
 
@@ -1854,12 +1788,12 @@
 	memset(&pfn_element, 0, sizeof(pfn_element));
 
 	/* set pfn parameters */
-	pfn_param.version = htod32(PFN_VERSION);
-	pfn_param.flags = htod16((PFN_LIST_ORDER << SORT_CRITERIA_BIT));
+	pfn_param.version = PFN_VERSION;
+	pfn_param.flags = (PFN_LIST_ORDER << SORT_CRITERIA_BIT);
 
 	/* set up pno scan fr */
 	if (scan_fr != 0)
-		pfn_param.scan_freq = htod32(scan_fr);
+		pfn_param.scan_freq = scan_fr;
 
 	bcm_mkiovar("pfn_set", (char *)&pfn_param, sizeof(pfn_param), iovbuf,
 		    sizeof(iovbuf));
@@ -1868,11 +1802,11 @@
 	/* set all pfn ssid */
 	for (i = 0; i < nssid; i++) {
 
-		pfn_element.bss_type = htod32(DOT11_BSSTYPE_INFRASTRUCTURE);
-		pfn_element.auth = (DOT11_OPEN_SYSTEM);
-		pfn_element.wpa_auth = htod32(WPA_AUTH_PFN_ANY);
-		pfn_element.wsec = htod32(0);
-		pfn_element.infra = htod32(1);
+		pfn_element.bss_type = DOT11_BSSTYPE_INFRASTRUCTURE;
+		pfn_element.auth = WLAN_AUTH_OPEN;
+		pfn_element.wpa_auth = WPA_AUTH_PFN_ANY;
+		pfn_element.wsec = 0;
+		pfn_element.infra = 1;
 
 		memcpy((char *)pfn_element.ssid.SSID, ssids_local[i].SSID,
 		       ssids_local[i].SSID_len);
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_custom_gpio.c	2011-05-19 00:06:34.000000000 -0400
@@ -15,7 +15,6 @@
  */
 
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <bcmutils.h>
 
 #include <dngl_stats.h>
@@ -47,7 +46,7 @@
 #include <mach/gpio.h>
 #endif
 
-/* Customer specific Host GPIO defintion  */
+/* Customer specific Host GPIO definition  */
 static int dhd_oob_gpio_num = -1;	/* GG 19 */
 
 module_param(dhd_oob_gpio_num, int, 0644);
@@ -149,9 +148,8 @@
 #ifdef EXAMPLE_GET_MAC
 	/* EXAMPLE code */
 	{
-		struct ether_addr ea_example = {
-			{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF} };
-		bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+		u8 ea_example[ETH_ALEN] = {0x00, 0x11, 0x22, 0x33, 0x44, 0xFF};
+		memcpy(buf, ea_example, ETH_ALEN);
 	}
 #endif				/* EXAMPLE_GET_MAC */
 
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_dbg.h	2011-05-19 00:06:34.000000000 -0400
@@ -21,31 +21,31 @@
 
 #define DHD_ERROR(args)	       \
 	do {if ((dhd_msg_level & DHD_ERROR_VAL) && (net_ratelimit())) \
-		printf args; } while (0)
+		printk args; } while (0)
 #define DHD_TRACE(args)		do {if (dhd_msg_level & DHD_TRACE_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_INFO(args)		do {if (dhd_msg_level & DHD_INFO_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_DATA(args)		do {if (dhd_msg_level & DHD_DATA_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_CTL(args)		do {if (dhd_msg_level & DHD_CTL_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_TIMER(args)		do {if (dhd_msg_level & DHD_TIMER_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_HDRS(args)		do {if (dhd_msg_level & DHD_HDRS_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_BYTES(args)		do {if (dhd_msg_level & DHD_BYTES_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_INTR(args)		do {if (dhd_msg_level & DHD_INTR_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_GLOM(args)		do {if (dhd_msg_level & DHD_GLOM_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_EVENT(args)		do {if (dhd_msg_level & DHD_EVENT_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_BTA(args)		do {if (dhd_msg_level & DHD_BTA_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 #define DHD_ISCAN(args)		do {if (dhd_msg_level & DHD_ISCAN_VAL)	\
-					printf args; } while (0)
+					printk args; } while (0)
 
 #define DHD_ERROR_ON()		(dhd_msg_level & DHD_ERROR_VAL)
 #define DHD_TRACE_ON()		(dhd_msg_level & DHD_TRACE_VAL)
@@ -63,7 +63,7 @@
 
 #else	/* (defined BCMDBG) || (defined DHD_DEBUG) */
 
-#define DHD_ERROR(args)  do {if (net_ratelimit()) printf args; } while (0)
+#define DHD_ERROR(args)  do {if (net_ratelimit()) printk args; } while (0)
 #define DHD_TRACE(args)
 #define DHD_INFO(args)
 #define DHD_DATA(args)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd.h	2011-05-19 00:06:34.000000000 -0400
@@ -33,9 +33,6 @@
 #include <linux/ethtool.h>
 #include <asm/uaccess.h>
 #include <asm/unaligned.h>
-#if defined(CONFIG_HAS_WAKELOCK)
-#include <linux/wakelock.h>
-#endif			/* defined (CONFIG_HAS_WAKELOCK) */
 /* The kernel threading is sdio-specific */
 
 #include <wlioctl.h>
@@ -52,32 +49,9 @@
 	DHD_BUS_DATA		/* Ready for frame transfers */
 };
 
-enum dhd_bus_wake_state {
-	WAKE_LOCK_OFF,
-	WAKE_LOCK_PRIV,
-	WAKE_LOCK_DPC,
-	WAKE_LOCK_IOCTL,
-	WAKE_LOCK_DOWNLOAD,
-	WAKE_LOCK_TMOUT,
-	WAKE_LOCK_WATCHDOG,
-	WAKE_LOCK_LINK_DOWN_TMOUT,
-	WAKE_LOCK_PNO_FIND_TMOUT,
-	WAKE_LOCK_SOFTAP_SET,
-	WAKE_LOCK_SOFTAP_STOP,
-	WAKE_LOCK_SOFTAP_START,
-	WAKE_LOCK_MAX
-};
-enum dhd_prealloc_index {
-	DHD_PREALLOC_PROT = 0,
-	DHD_PREALLOC_RXBUF,
-	DHD_PREALLOC_DATABUF,
-	DHD_PREALLOC_OSL_BUF
-};
-
 /* Common structure for module and instance linkage */
 typedef struct dhd_pub {
 	/* Linkage ponters */
-	struct osl_info *osh;		/* OSL handle */
 	struct dhd_bus *bus;	/* Bus module handle */
 	struct dhd_prot *prot;	/* Protocol module handle */
 	struct dhd_info *info;	/* Info module handle */
@@ -95,8 +69,8 @@
 	/* Dongle media info */
 	bool iswl;		/* Dongle-resident driver is wl */
 	unsigned long drv_version;	/* Version of dongle-resident driver */
-	struct ether_addr mac;	/* MAC address obtained from dongle */
-	dngl_stats_t dstats;	/* Stats for dongle-based data */
+	u8 mac[ETH_ALEN];			/* MAC address obtained from dongle */
+	dngl_stats_t dstats;		/* Stats for dongle-based data */
 
 	/* Additional stats for the bus level */
 	unsigned long tx_packets;	/* Data packets sent to dongle */
@@ -145,9 +119,6 @@
 	u8 country_code[WLC_CNTRY_BUF_SZ];
 	char eventmask[WL_EVENTING_MASK_LEN];
 
-#if defined(CONFIG_HAS_WAKELOCK)
-	struct wake_lock wakelock[WAKE_LOCK_MAX];
-#endif		/*  defined (CONFIG_HAS_WAKELOCK) */
 } dhd_pub_t;
 
 #if defined(CONFIG_PM_SLEEP)
@@ -230,41 +201,6 @@
 {
 }
 
-static inline void WAKE_LOCK_INIT(dhd_pub_t *dhdp, int index, char *y)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock_init(&dhdp->wakelock[index], WAKE_LOCK_SUSPEND, y);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_LOCK(dhd_pub_t *dhdp, int index)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock(&dhdp->wakelock[index]);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_UNLOCK(dhd_pub_t *dhdp, int index)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_unlock(&dhdp->wakelock[index]);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_LOCK_TIMEOUT(dhd_pub_t *dhdp, int index, long time)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock_timeout(&dhdp->wakelock[index], time);
-#endif	/* defined (CONFIG_HAS_WAKELOCK) */
-}
-
-static inline void WAKE_LOCK_DESTROY(dhd_pub_t *dhdp, int index)
-{
-#if defined(CONFIG_HAS_WAKELOCK)
-	wake_lock_destroy(&dhdp->wakelock[index]);
-#endif /* defined (CONFIG_HAS_WAKELOCK) */
-}
-
 typedef struct dhd_if_event {
 	u8 ifidx;
 	u8 action;
@@ -276,16 +212,12 @@
  * Exported from dhd OS modules (dhd_linux/dhd_ndis)
  */
 
-/* To allow osl_attach/detach calls from os-independent modules */
-struct osl_info *dhd_osl_attach(void *pdev, uint bustype);
-void dhd_osl_detach(struct osl_info *osh);
-
 /* Indication from bus module regarding presence/insertion of dongle.
  * Return dhd_pub_t pointer, used as handle to OS module in later calls.
  * Returned structure should have bus and prot pointers filled in.
  * bus_hdrlen specifies required headroom for bus module header.
  */
-extern dhd_pub_t *dhd_attach(struct osl_info *osh, struct dhd_bus *bus,
+extern dhd_pub_t *dhd_attach(struct dhd_bus *bus,
 				uint bus_hdrlen);
 extern int dhd_net_attach(dhd_pub_t *dhdp, int idx);
 
@@ -364,7 +296,6 @@
 extern u8 *dhd_bssidx2bssid(dhd_pub_t *dhd, int idx);
 extern int wl_host_event(struct dhd_info *dhd, int *idx, void *pktdata,
 			 wl_event_msg_t *, void **data_ptr);
-extern void wl_event_to_host_order(wl_event_msg_t *evt);
 
 extern void dhd_common_init(void);
 
@@ -389,14 +320,12 @@
 extern uint dhd_bus_status(dhd_pub_t *dhdp);
 extern int dhd_bus_start(dhd_pub_t *dhdp);
 
-extern void print_buf(void *pbuf, int len, int bytes_per_line);
-
-typedef enum cust_gpio_modes {
+enum cust_gpio_modes {
 	WLAN_RESET_ON,
 	WLAN_RESET_OFF,
 	WLAN_POWER_ON,
 	WLAN_POWER_OFF
-} cust_gpio_modes_t;
+};
 /*
  * Insmod parameters for debug/test
  */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhdioctl.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhdioctl.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhdioctl.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhdioctl.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 _dhdioctl_h_
+#define	_dhdioctl_h_
+
+/* Linux network driver ioctl encoding */
+typedef struct dhd_ioctl {
+	uint cmd;		/* common ioctl definition */
+	void *buf;		/* pointer to user buffer */
+	uint len;		/* length of user buffer */
+	bool set;		/* get or set request (optional) */
+	uint used;		/* bytes read or written (optional) */
+	uint needed;		/* bytes needed (optional) */
+	uint driver;		/* to identify target driver */
+} dhd_ioctl_t;
+
+/* per-driver magic numbers */
+#define DHD_IOCTL_MAGIC		0x00444944
+
+/* bump this number if you change the ioctl interface */
+#define DHD_IOCTL_VERSION	1
+
+#define	DHD_IOCTL_MAXLEN	8192	/* max length ioctl buffer required */
+#define	DHD_IOCTL_SMLEN	256	/* "small" length ioctl buffer required */
+
+/* common ioctl definitions */
+#define DHD_GET_MAGIC				0
+#define DHD_GET_VERSION				1
+#define DHD_GET_VAR				2
+#define DHD_SET_VAR				3
+
+/* message levels */
+#define DHD_ERROR_VAL	0x0001
+#define DHD_TRACE_VAL	0x0002
+#define DHD_INFO_VAL	0x0004
+#define DHD_DATA_VAL	0x0008
+#define DHD_CTL_VAL	0x0010
+#define DHD_TIMER_VAL	0x0020
+#define DHD_HDRS_VAL	0x0040
+#define DHD_BYTES_VAL	0x0080
+#define DHD_INTR_VAL	0x0100
+#define DHD_LOG_VAL	0x0200
+#define DHD_GLOM_VAL	0x0400
+#define DHD_EVENT_VAL	0x0800
+#define DHD_BTA_VAL	0x1000
+#define DHD_ISCAN_VAL 0x2000
+
+#ifdef SDTEST
+/* For pktgen iovar */
+typedef struct dhd_pktgen {
+	uint version;		/* To allow structure change tracking */
+	uint freq;		/* Max ticks between tx/rx attempts */
+	uint count;		/* Test packets to send/rcv each attempt */
+	uint print;		/* Print counts every <print> attempts */
+	uint total;		/* Total packets (or bursts) */
+	uint minlen;		/* Minimum length of packets to send */
+	uint maxlen;		/* Maximum length of packets to send */
+	uint numsent;		/* Count of test packets sent */
+	uint numrcvd;		/* Count of test packets received */
+	uint numfail;		/* Count of test send failures */
+	uint mode;		/* Test mode (type of test packets) */
+	uint stop;		/* Stop after this many tx failures */
+} dhd_pktgen_t;
+
+/* Version in case structure changes */
+#define DHD_PKTGEN_VERSION 2
+
+/* Type of test packets to use */
+#define DHD_PKTGEN_ECHO		1	/* Send echo requests */
+#define DHD_PKTGEN_SEND		2	/* Send discard packets */
+#define DHD_PKTGEN_RXBURST	3	/* Request dongle send N packets */
+#define DHD_PKTGEN_RECV		4	/* Continuous rx from continuous
+					 tx dongle */
+#endif				/* SDTEST */
+
+/* Enter idle immediately (no timeout) */
+#define DHD_IDLE_IMMEDIATE	(-1)
+
+/* Values for idleclock iovar: other values are the sd_divisor to use
+	 when idle */
+#define DHD_IDLE_ACTIVE	0	/* Do not request any SD clock change
+				 when idle */
+#define DHD_IDLE_STOP   (-1)	/* Request SD clock be stopped
+				 (and use SD1 mode) */
+
+#endif				/* _dhdioctl_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_linux.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_linux.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_linux.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_linux.c	2011-05-19 00:06:34.000000000 -0400
@@ -32,11 +32,8 @@
 #include <linux/fs.h>
 #include <linux/uaccess.h>
 #include <bcmdefs.h>
-#include <osl.h>
 #include <bcmutils.h>
-#include <bcmendian.h>
 
-#include <proto/ethernet.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhd_bus.h>
@@ -45,7 +42,8 @@
 
 #include <wl_cfg80211.h>
 
-#define EPI_VERSION_STR         "4.218.248.5"
+#define EPI_VERSION_STR		"4.218.248.5"
+#define ETH_P_BRCM			0x886c
 
 #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC)
 #include <linux/wifi_tiwlan.h>
@@ -149,7 +147,7 @@
 	.suspend = wifi_suspend,
 	.resume = wifi_resume,
 	.driver = {
-		   .name = "bcm4329_wlan",
+		   .name = KBUILD_MODNAME,
 		   }
 };
 
@@ -247,7 +245,7 @@
 	struct semaphore sysioc_sem;
 	bool set_multicast;
 	bool set_macaddress;
-	struct ether_addr macvalue;
+	u8 macvalue[ETH_ALEN];
 	wait_queue_head_t ctrl_wait;
 	atomic_t pend_8021x_cnt;
 
@@ -387,12 +385,6 @@
 #define DHD_COMPILED
 #endif
 
-static char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR
-#ifdef DHD_DEBUG
-"\nCompiled in " " on " __DATE__ " at " __TIME__
-#endif
-;
-
 #if defined(CONFIG_WIRELESS_EXT)
 struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
 #endif				/* defined(CONFIG_WIRELESS_EXT) */
@@ -486,7 +478,7 @@
 			dhd_set_packet_filter(1, dhd);
 
 			/* if dtim skip setup as default force it
-			 * to wake each thrid dtim
+			 * to wake each third dtim
 			 * for better power saving.
 			 * Note that side effect is chance to miss BC/MC
 			 * packet
@@ -719,7 +711,7 @@
 	strcpy(bufp, "mcast_list");
 	bufp += strlen("mcast_list") + 1;
 
-	cnt = htol32(cnt);
+	cnt = cpu_to_le32(cnt);
 	memcpy(bufp, &cnt, sizeof(cnt));
 	bufp += sizeof(cnt);
 
@@ -758,7 +750,7 @@
 			   dhd_ifname(&dhd->pub, ifidx)));
 		return;
 	}
-	allmulti = htol32(allmulti);
+	allmulti = cpu_to_le32(allmulti);
 
 	if (!bcm_mkiovar
 	    ("allmulti", (void *)&allmulti, sizeof(allmulti), buf, buflen)) {
@@ -778,7 +770,8 @@
 	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
 		DHD_ERROR(("%s: set allmulti %d failed\n",
-			   dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
+			   dhd_ifname(&dhd->pub, ifidx),
+			   le32_to_cpu(allmulti)));
 	}
 
 	kfree(buf);
@@ -787,7 +780,7 @@
 		 driver does */
 
 	allmulti = (dev->flags & IFF_PROMISC) ? true : false;
-	allmulti = htol32(allmulti);
+	allmulti = cpu_to_le32(allmulti);
 
 	memset(&ioc, 0, sizeof(ioc));
 	ioc.cmd = WLC_SET_PROMISC;
@@ -798,12 +791,13 @@
 	ret = dhd_prot_ioctl(&dhd->pub, ifidx, &ioc, ioc.buf, ioc.len);
 	if (ret < 0) {
 		DHD_ERROR(("%s: set promisc %d failed\n",
-			   dhd_ifname(&dhd->pub, ifidx), ltoh32(allmulti)));
+			   dhd_ifname(&dhd->pub, ifidx),
+			   le32_to_cpu(allmulti)));
 	}
 }
 
 static int
-_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, struct ether_addr *addr)
+_dhd_set_mac_address(dhd_info_t *dhd, int ifidx, u8 *addr)
 {
 	char buf[32];
 	wl_ioctl_t ioc;
@@ -976,7 +970,7 @@
 				if (dhd->set_macaddress) {
 					dhd->set_macaddress = false;
 					_dhd_set_mac_address(dhd, i,
-							     &dhd->macvalue);
+							     dhd->macvalue);
 				}
 			}
 		}
@@ -1030,11 +1024,11 @@
 	/* Update multicast statistic */
 	if (pktbuf->len >= ETH_ALEN) {
 		u8 *pktdata = (u8 *) (pktbuf->data);
-		struct ether_header *eh = (struct ether_header *)pktdata;
+		struct ethhdr *eh = (struct ethhdr *)pktdata;
 
-		if (is_multicast_ether_addr(eh->ether_dhost))
+		if (is_multicast_ether_addr(eh->h_dest))
 			dhdp->tx_multicast++;
-		if (ntoh16(eh->ether_type) == ETH_P_PAE)
+		if (ntohs(eh->h_proto) == ETH_P_PAE)
 			atomic_inc(&dhd->pend_8021x_cnt);
 	}
 
@@ -1045,7 +1039,6 @@
 #ifdef BCMDBUS
 	ret = dbus_send_pkt(dhdp->dbus, pktbuf, NULL /* pktinfo */);
 #else
-	WAKE_LOCK_TIMEOUT(dhdp, WAKE_LOCK_TMOUT, 25);
 	ret = dhd_bus_txdata(dhdp->bus, pktbuf);
 #endif				/* BCMDBUS */
 
@@ -1053,30 +1046,20 @@
 }
 
 static inline void *
-osl_pkt_frmnative(struct osl_info *osh, struct sk_buff *skb)
+osl_pkt_frmnative(struct sk_buff *skb)
 {
-	struct sk_buff *nskb;
-
-	for (nskb = skb; nskb; nskb = nskb->next)
-		osh->pktalloced++;
-
 	return (void *)skb;
 }
 #define PKTFRMNATIVE(osh, skb)	\
-	osl_pkt_frmnative((osh), (struct sk_buff *)(skb))
+	osl_pkt_frmnative((struct sk_buff *)(skb))
 
 static inline struct sk_buff *
-osl_pkt_tonative(struct osl_info *osh, void *pkt)
+osl_pkt_tonative(void *pkt)
 {
-	struct sk_buff *nskb;
-
-	for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next)
-		osh->pktalloced--;
-
 	return (struct sk_buff *)pkt;
 }
 #define PKTTONATIVE(osh, pkt)	\
-	osl_pkt_tonative((osh), (pkt))
+	osl_pkt_tonative((pkt))
 
 static int dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
@@ -1215,7 +1198,7 @@
 		skb_pull(skb, ETH_HLEN);
 
 		/* Process special event packets and then discard them */
-		if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM)
+		if (ntohs(skb->protocol) == ETH_P_BRCM)
 			dhd_wl_host_event(dhd, &ifidx,
 					  skb_mac_header(skb),
 					  &event, &data);
@@ -1254,13 +1237,13 @@
 {
 	uint ifidx;
 	dhd_info_t *dhd = (dhd_info_t *) (dhdp->info);
-	struct ether_header *eh;
+	struct ethhdr *eh;
 	u16 type;
 
 	dhd_prot_hdrpull(dhdp, &ifidx, txp);
 
-	eh = (struct ether_header *)(txp->data);
-	type = ntoh16(eh->ether_type);
+	eh = (struct ethhdr *)(txp->data);
+	type = ntohs(eh->h_proto);
 
 	if (type == ETH_P_PAE)
 		atomic_dec(&dhd->pend_8021x_cnt);
@@ -1304,7 +1287,6 @@
 static int dhd_watchdog_thread(void *data)
 {
 	dhd_info_t *dhd = (dhd_info_t *) data;
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_WATCHDOG, "dhd_watchdog_thread");
 
 	/* This thread doesn't need any user-level access,
 	 * so get rid of all our resources
@@ -1325,18 +1307,14 @@
 			break;
 		if (down_interruptible(&dhd->watchdog_sem) == 0) {
 			if (dhd->pub.dongle_reset == false) {
-				WAKE_LOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
 				/* Call the bus module watchdog */
 				dhd_bus_watchdog(&dhd->pub);
-				WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_WATCHDOG);
 			}
 			/* Count the tick for reference */
 			dhd->pub.tickcnt++;
 		} else
 			break;
 	}
-
-	WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_WATCHDOG);
 	return 0;
 }
 
@@ -1370,7 +1348,6 @@
 {
 	dhd_info_t *dhd = (dhd_info_t *) data;
 
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_DPC, "dhd_dpc_thread");
 	/* This thread doesn't need any user-level access,
 	 * so get rid of all our resources
 	 */
@@ -1393,21 +1370,15 @@
 			/* Call bus dpc unless it indicated down
 				 (then clean stop) */
 			if (dhd->pub.busstate != DHD_BUS_DOWN) {
-				WAKE_LOCK(&dhd->pub, WAKE_LOCK_DPC);
 				if (dhd_bus_dpc(dhd->pub.bus)) {
 					up(&dhd->dpc_sem);
-					WAKE_LOCK_TIMEOUT(&dhd->pub,
-							  WAKE_LOCK_TMOUT, 25);
 				}
-				WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_DPC);
 			} else {
 				dhd_bus_stop(dhd->pub.bus, true);
 			}
 		} else
 			break;
 	}
-
-	WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_DPC);
 	return 0;
 }
 
@@ -1797,22 +1768,16 @@
 	if (is_set_key_cmd)
 		dhd_wait_pend8021x(net);
 
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_IOCTL, "dhd_ioctl_entry");
-	WAKE_LOCK(&dhd->pub, WAKE_LOCK_IOCTL);
-
 	bcmerror =
 	    dhd_prot_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen);
 
-	WAKE_UNLOCK(&dhd->pub, WAKE_LOCK_IOCTL);
-	WAKE_LOCK_DESTROY(&dhd->pub, WAKE_LOCK_IOCTL);
 done:
 	if (!bcmerror && buf && ioc.buf) {
 		if (copy_to_user(ioc.buf, buf, buflen))
 			bcmerror = -EFAULT;
 	}
 
-	if (buf)
-		kfree(buf);
+	kfree(buf);
 
 	if (bcmerror > 0)
 		bcmerror = 0;
@@ -1866,7 +1831,7 @@
 		}
 		atomic_set(&dhd->pend_8021x_cnt, 0);
 
-		memcpy(net->dev_addr, dhd->pub.mac.octet, ETH_ALEN);
+		memcpy(net->dev_addr, dhd->pub.mac, ETH_ALEN);
 
 #ifdef TOE
 		/* Get current TOE mode from dongle */
@@ -1891,16 +1856,6 @@
 	return ret;
 }
 
-struct osl_info *dhd_osl_attach(void *pdev, uint bustype)
-{
-	return osl_attach(pdev, bustype);
-}
-
-void dhd_osl_detach(struct osl_info *osh)
-{
-	osl_detach(osh);
-}
-
 int
 dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name,
 	   u8 *mac_addr, u32 flags, u8 bssidx)
@@ -1954,8 +1909,7 @@
 	up(&dhd->sysioc_sem);
 }
 
-dhd_pub_t *dhd_attach(struct osl_info *osh, struct dhd_bus *bus,
-			uint bus_hdrlen)
+dhd_pub_t *dhd_attach(struct dhd_bus *bus, uint bus_hdrlen)
 {
 	dhd_info_t *dhd = NULL;
 	struct net_device *net;
@@ -1976,19 +1930,16 @@
 	}
 
 	/* Allocate primary dhd_info */
-	dhd = kmalloc(sizeof(dhd_info_t), GFP_ATOMIC);
+	dhd = kzalloc(sizeof(dhd_info_t), GFP_ATOMIC);
 	if (!dhd) {
 		DHD_ERROR(("%s: OOM - alloc dhd_info\n", __func__));
 		goto fail;
 	}
 
-	memset(dhd, 0, sizeof(dhd_info_t));
-
 	/*
 	 * Save the dhd_info into the priv
 	 */
 	memcpy(netdev_priv(net), &dhd, sizeof(dhd));
-	dhd->pub.osh = osh;
 
 	/* Set network interface name if it was provided as module parameter */
 	if (iface_name[0]) {
@@ -2115,11 +2066,6 @@
 #endif	/* defined(CONFIG_PM_SLEEP) */
 	/* && defined(DHD_GPL) */
 	/* Init lock suspend to prevent kernel going to suspend */
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_TMOUT, "dhd_wake_lock");
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_LINK_DOWN_TMOUT,
-		       "dhd_wake_lock_link_dw_event");
-	WAKE_LOCK_INIT(&dhd->pub, WAKE_LOCK_PNO_FIND_TMOUT,
-		       "dhd_wake_lock_link_pno_find_event");
 #ifdef CONFIG_HAS_EARLYSUSPEND
 	dhd->early_suspend.level = EARLY_SUSPEND_LEVEL_BLANK_SCREEN + 20;
 	dhd->early_suspend.suspend = dhd_early_suspend;
@@ -2153,20 +2099,13 @@
 
 	/* try to download image and nvram to the dongle */
 	if (dhd->pub.busstate == DHD_BUS_DOWN) {
-		WAKE_LOCK_INIT(dhdp, WAKE_LOCK_DOWNLOAD, "dhd_bus_start");
-		WAKE_LOCK(dhdp, WAKE_LOCK_DOWNLOAD);
-		if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
+		if (!(dhd_bus_download_firmware(dhd->pub.bus,
 						fw_path, nv_path))) {
 			DHD_ERROR(("%s: dhdsdio_probe_download failed. "
 				"firmware = %s nvram = %s\n",
 				__func__, fw_path, nv_path));
-			WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
 			return -1;
 		}
-
-		WAKE_UNLOCK(dhdp, WAKE_LOCK_DOWNLOAD);
-		WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_DOWNLOAD);
 	}
 
 	/* Start the watchdog timer */
@@ -2203,7 +2142,7 @@
 	bcm_mkiovar("event_msgs", dhdp->eventmask, WL_EVENTING_MASK_LEN, iovbuf,
 		    sizeof(iovbuf));
 	dhdcdc_query_ioctl(dhdp, 0, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
-	bcopy(iovbuf, dhdp->eventmask, WL_EVENTING_MASK_LEN);
+	memcpy(dhdp->eventmask, iovbuf, WL_EVENTING_MASK_LEN);
 
 	setbit(dhdp->eventmask, WLC_E_SET_SSID);
 	setbit(dhdp->eventmask, WLC_E_PRUNE);
@@ -2299,7 +2238,7 @@
 	 */
 	if (ifidx != 0) {
 		/* for virtual interfaces use the primary MAC  */
-		memcpy(temp_addr, dhd->pub.mac.octet, ETH_ALEN);
+		memcpy(temp_addr, dhd->pub.mac, ETH_ALEN);
 
 	}
 
@@ -2335,7 +2274,7 @@
 		goto fail;
 	}
 
-	printf("%s: Broadcom Dongle Host Driver\n", net->name);
+	DHD_INFO(("%s: Broadcom Dongle Host Driver\n", net->name));
 
 	return 0;
 
@@ -2432,9 +2371,6 @@
 			unregister_pm_notifier(&dhd_sleep_pm_notifier);
 #endif	/* defined(CONFIG_PM_SLEEP) */
 			/* && defined(DHD_GPL) */
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_TMOUT);
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_LINK_DOWN_TMOUT);
-			WAKE_LOCK_DESTROY(dhdp, WAKE_LOCK_PNO_FIND_TMOUT);
 			free_netdev(ifp->net);
 			kfree(ifp);
 			kfree(dhd);
@@ -2483,7 +2419,7 @@
 	error = wifi_add_dev();
 	if (error) {
 		DHD_ERROR(("%s: platform_driver_register failed\n", __func__));
-		goto faild;
+		goto failed;
 	}
 
 	/* Waiting callback after platform_driver_register is done or
@@ -2493,21 +2429,19 @@
 			__func__);
 		/* remove device */
 		wifi_del_dev();
-		goto faild;
+		goto failed;
 	}
 #endif	/* #if defined(CUSTOMER_HW2) && defined(CONFIG_WIFI_CONTROL_FUNC) */
 
 	error = dhd_bus_register();
 
-	if (!error)
-		printf("\n%s\n", dhd_version);
-	else {
+	if (error) {
 		DHD_ERROR(("%s: sdio_register_driver failed\n", __func__));
-		goto faild;
+		goto failed;
 	}
 	return error;
 
-faild:
+failed:
 	/* turn off power and exit */
 	dhd_customer_gpio_wlan_ctrl(WLAN_POWER_OFF);
 	return -EINVAL;
@@ -2790,7 +2724,7 @@
 /* send up locally generated event */
 void dhd_sendup_event(dhd_pub_t *dhdp, wl_event_msg_t *event, void *data)
 {
-	switch (ntoh32(event->event_type)) {
+	switch (be32_to_cpu(event->event_type)) {
 	default:
 		break;
 	}
@@ -2975,7 +2909,7 @@
 	/* open file to write */
 	fp = filp_open("/tmp/mem_dump", O_WRONLY | O_CREAT, 0640);
 	if (!fp) {
-		printf("%s: open file error\n", __func__);
+		DHD_ERROR(("%s: open file error\n", __func__));
 		ret = -1;
 		goto exit;
 	}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_proto.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_proto.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_proto.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_proto.h	2011-05-19 00:06:34.000000000 -0400
@@ -46,9 +46,6 @@
 /* Stop protocol: sync w/dongle state. */
 extern void dhd_prot_stop(dhd_pub_t *dhdp);
 
-extern bool dhd_proto_fcinfo(dhd_pub_t *dhd, struct sk_buff *pktbuf,
-			     u8 *fcbits);
-
 /* Add any protocol-specific data header.
  * Caller must reserve prot_hdrlen prepend space.
  */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/dhd_sdio.c	2011-05-19 00:06:34.000000000 -0400
@@ -17,7 +17,6 @@
 #include <linux/types.h>
 #include <bcmdefs.h>
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <bcmsdh.h>
 
 #ifdef BCMEMBEDIMAGE
@@ -26,7 +25,6 @@
 
 #include <bcmdefs.h>
 #include <bcmutils.h>
-#include <bcmendian.h>
 #include <bcmdevs.h>
 
 #include <siutils.h>
@@ -44,8 +42,6 @@
 #include <sbsdpcmdev.h>
 #include <bcmsdpcm.h>
 
-#include <proto/ethernet.h>
-#include <proto/802.1d.h>
 #include <proto/802.11.h>
 
 #include <dngl_stats.h>
@@ -61,9 +57,9 @@
 #define DHDSDIO_MEM_DUMP_FNAME         "mem_dump"
 #endif
 
-#define QLEN		256	/* bulk rx and tx queue lengths */
-#define FCHI		(QLEN - 10)
-#define FCLOW		(FCHI / 2)
+#define TXQLEN		2048	/* bulk tx queue length */
+#define TXHI		(TXQLEN - 256)	/* turn on flow control above TXHI */
+#define TXLOW		(TXHI - 256)	/* turn off flow control below TXLOW */
 #define PRIOMASK	7
 
 #define TXRETRIES	2	/* # of retries for tx frames */
@@ -144,7 +140,15 @@
  * bufpool was present for gspi bus.
  */
 #define PKTFREE2()		if ((bus->bus != SPI_BUS) || bus->usebufpool) \
-							pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+							pkt_buf_free_skb(pkt);
+
+/*
+ * Conversion of 802.1D priority to precedence level
+ */
+#define PRIO2PREC(prio) \
+	(((prio) == PRIO_8021D_NONE || (prio) == PRIO_8021D_BE) ? \
+	((prio^2)) : (prio))
+
 DHD_SPINWAIT_SLEEP_INIT(sdioh_spinwait_sleep);
 extern int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf,
 			    uint len);
@@ -329,7 +333,6 @@
 #define DONGLE_MIN_MEMSIZE (128 * 1024)
 int dhd_dongle_memsize;
 
-static bool dhd_doflow;
 static bool dhd_alignctl;
 
 static bool sd1idle;
@@ -357,7 +360,7 @@
 #if defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD)
 #error OOB_INTR_ONLY is NOT working with SDIO_ISR_THREAD
 #endif	/* defined(OOB_INTR_ONLY) && defined(SDIO_ISR_THREAD) */
-#define PKTALIGN(_osh, _p, _len, _align)				\
+#define PKTALIGN(_p, _len, _align)				\
 	do {								\
 		uint datalign;						\
 		datalign = (unsigned long)((_p)->data);			\
@@ -386,7 +389,7 @@
 do { \
 	retryvar = 0; \
 	do { \
-		regvar = R_REG(bus->dhd->osh, regaddr); \
+		regvar = R_REG(regaddr); \
 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
 	if (retryvar) { \
 		bus->regfails += (retryvar-1); \
@@ -402,7 +405,7 @@
 do { \
 	retryvar = 0; \
 	do { \
-		W_REG(bus->dhd->osh, regaddr, regval); \
+		W_REG(regaddr, regval); \
 	} while (bcmsdh_regfail(bus->sdh) && (++retryvar <= retry_limit)); \
 	if (retryvar) { \
 		bus->regfails += (retryvar-1); \
@@ -431,16 +434,15 @@
 #endif				/* DHD_DEBUG  */
 static int dhdsdio_download_state(dhd_bus_t *bus, bool enter);
 
-static void dhdsdio_release(dhd_bus_t *bus, struct osl_info *osh);
-static void dhdsdio_release_malloc(dhd_bus_t *bus, struct osl_info *osh);
+static void dhdsdio_release(dhd_bus_t *bus);
+static void dhdsdio_release_malloc(dhd_bus_t *bus);
 static void dhdsdio_disconnect(void *ptr);
 static bool dhdsdio_chipmatch(u16 chipid);
-static bool dhdsdio_probe_attach(dhd_bus_t *bus, struct osl_info *osh,
-				 void *sdh, void *regsva, u16 devid);
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, struct osl_info *osh,
-				 void *sdh);
-static bool dhdsdio_probe_init(dhd_bus_t *bus, struct osl_info *osh, void *sdh);
-static void dhdsdio_release_dongle(dhd_bus_t *bus, struct osl_info * osh);
+static bool dhdsdio_probe_attach(dhd_bus_t *bus, void *sdh,
+				 void *regsva, u16 devid);
+static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh);
+static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh);
+static void dhdsdio_release_dongle(dhd_bus_t *bus);
 
 static uint process_nvram_vars(char *varbuf, uint len);
 
@@ -454,8 +456,7 @@
 			       struct sk_buff *pkt, bcmsdh_cmplt_fn_t complete,
 			       void *handle);
 
-static bool dhdsdio_download_firmware(struct dhd_bus *bus, struct osl_info *osh,
-				      void *sdh);
+static bool dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh);
 static int _dhdsdio_download_firmware(struct dhd_bus *bus);
 
 static int dhdsdio_download_code_file(struct dhd_bus *bus, char *image_path);
@@ -908,7 +909,6 @@
 			 bool free_pkt)
 {
 	int ret;
-	struct osl_info *osh;
 	u8 *frame;
 	u16 len, pad = 0;
 	u32 swheader;
@@ -920,7 +920,6 @@
 	DHD_TRACE(("%s: Enter\n", __func__));
 
 	sdh = bus->sdh;
-	osh = bus->dhd->osh;
 
 	if (bus->dhd->dongle_reset) {
 		ret = BCME_NOTREADY;
@@ -936,7 +935,7 @@
 			DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
 				  __func__, skb_headroom(pkt), pad));
 			bus->dhd->tx_realloc++;
-			new = pkt_buf_get_skb(osh, (pkt->len + DHD_SDALIGN));
+			new = pkt_buf_get_skb(pkt->len + DHD_SDALIGN);
 			if (!new) {
 				DHD_ERROR(("%s: couldn't allocate new %d-byte "
 					"packet\n",
@@ -945,10 +944,10 @@
 				goto done;
 			}
 
-			PKTALIGN(osh, new, pkt->len, DHD_SDALIGN);
-			bcopy(pkt->data, new->data, pkt->len);
+			PKTALIGN(new, pkt->len, DHD_SDALIGN);
+			memcpy(new->data, pkt->data, pkt->len);
 			if (free_pkt)
-				pkt_buf_free_skb(osh, pkt, true);
+				pkt_buf_free_skb(pkt);
 			/* free the pkt if canned one is not used */
 			free_pkt = true;
 			pkt = new;
@@ -967,16 +966,17 @@
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
 	len = (u16) (pkt->len);
-	*(u16 *) frame = htol16(len);
-	*(((u16 *) frame) + 1) = htol16(~len);
+	*(u16 *) frame = cpu_to_le16(len);
+	*(((u16 *) frame) + 1) = cpu_to_le16(~len);
 
 	/* Software tag: channel, sequence number, data offset */
 	swheader =
 	    ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
 	    (((pad +
 	       SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
-	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
-	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+
+	put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 #ifdef DHD_DEBUG
 	tx_packets[pkt->priority]++;
@@ -1061,7 +1061,7 @@
 	dhd_os_sdlock(bus->dhd);
 
 	if (free_pkt)
-		pkt_buf_free_skb(osh, pkt, true);
+		pkt_buf_free_skb(pkt);
 
 	return ret;
 }
@@ -1069,12 +1069,10 @@
 int dhd_bus_txdata(struct dhd_bus *bus, struct sk_buff *pkt)
 {
 	int ret = BCME_ERROR;
-	struct osl_info *osh;
 	uint datalen, prec;
 
 	DHD_TRACE(("%s: Enter\n", __func__));
 
-	osh = bus->dhd->osh;
 	datalen = pkt->len;
 
 #ifdef SDTEST
@@ -1112,7 +1110,7 @@
 		if (dhd_prec_enq(bus->dhd, &bus->txq, pkt, prec) == false) {
 			skb_pull(pkt, SDPCM_HDRLEN);
 			dhd_txcomplete(bus->dhd, pkt, false);
-			pkt_buf_free_skb(osh, pkt, true);
+			pkt_buf_free_skb(pkt);
 			DHD_ERROR(("%s: out of bus->txq !!!\n", __func__));
 			ret = BCME_NORESOURCE;
 		} else {
@@ -1120,7 +1118,7 @@
 		}
 		dhd_os_sdunlock_txq(bus->dhd);
 
-		if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow)
+		if (pktq_len(&bus->txq) >= TXHI)
 			dhd_txflowcontrol(bus->dhd, 0, ON);
 
 #ifdef DHD_DEBUG
@@ -1218,8 +1216,8 @@
 	}
 
 	/* Deflow-control stack if needed */
-	if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
-	    dhd->txoff && (pktq_len(&bus->txq) < FCLOW))
+	if (dhd->up && (dhd->busstate == DHD_BUS_DATA) &&
+	    dhd->txoff && (pktq_len(&bus->txq) < TXLOW))
 		dhd_txflowcontrol(dhd, 0, OFF);
 
 	return cnt;
@@ -1282,8 +1280,8 @@
 	dhdsdio_clkctl(bus, CLK_AVAIL, false);
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
-	*(u16 *) frame = htol16((u16) msglen);
-	*(((u16 *) frame) + 1) = htol16(~msglen);
+	*(u16 *) frame = cpu_to_le16((u16) msglen);
+	*(((u16 *) frame) + 1) = cpu_to_le16(~msglen);
 
 	/* Software tag: channel, sequence number, data offset */
 	swheader =
@@ -1291,8 +1289,8 @@
 	     SDPCM_CHANNEL_MASK)
 	    | bus->tx_seq | ((doff << SDPCM_DOFFSET_SHIFT) &
 			     SDPCM_DOFFSET_MASK);
-	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
-	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
+	put_unaligned_le32(swheader, frame + SDPCM_FRAMETAG_LEN);
+	put_unaligned_le32(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
 	if (!DATAOK(bus)) {
 		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
@@ -1396,7 +1394,7 @@
 
 	dhd_os_sdlock(bus->dhd);
 	rxlen = bus->rxlen;
-	bcopy(bus->rxctl, msg, min(msglen, rxlen));
+	memcpy(msg, bus->rxctl, min(msglen, rxlen));
 	bus->rxlen = 0;
 	dhd_os_sdunlock(bus->dhd);
 
@@ -1659,7 +1657,7 @@
 	pktgen.mode = bus->pktgen_mode;
 	pktgen.stop = bus->pktgen_stop;
 
-	bcopy(&pktgen, arg, sizeof(pktgen));
+	memcpy(arg, &pktgen, sizeof(pktgen));
 
 	return 0;
 }
@@ -1669,7 +1667,7 @@
 	dhd_pktgen_t pktgen;
 	uint oldcnt, oldmode;
 
-	bcopy(arg, &pktgen, sizeof(pktgen));
+	memcpy(&pktgen, arg, sizeof(pktgen));
 	if (pktgen.version != DHD_PKTGEN_VERSION)
 		return BCME_BADARG;
 
@@ -1769,7 +1767,7 @@
 	if (rv < 0)
 		return rv;
 
-	addr = ltoh32(addr);
+	addr = le32_to_cpu(addr);
 
 	DHD_INFO(("sdpcm_shared address 0x%08X\n", addr));
 
@@ -1790,13 +1788,13 @@
 		return rv;
 
 	/* Endianness */
-	sh->flags = ltoh32(sh->flags);
-	sh->trap_addr = ltoh32(sh->trap_addr);
-	sh->assert_exp_addr = ltoh32(sh->assert_exp_addr);
-	sh->assert_file_addr = ltoh32(sh->assert_file_addr);
-	sh->assert_line = ltoh32(sh->assert_line);
-	sh->console_addr = ltoh32(sh->console_addr);
-	sh->msgtrace_addr = ltoh32(sh->msgtrace_addr);
+	sh->flags = le32_to_cpu(sh->flags);
+	sh->trap_addr = le32_to_cpu(sh->trap_addr);
+	sh->assert_exp_addr = le32_to_cpu(sh->assert_exp_addr);
+	sh->assert_file_addr = le32_to_cpu(sh->assert_file_addr);
+	sh->assert_line = le32_to_cpu(sh->assert_line);
+	sh->console_addr = le32_to_cpu(sh->console_addr);
+	sh->msgtrace_addr = le32_to_cpu(sh->msgtrace_addr);
 
 	if ((sh->flags & SDPCM_SHARED_VERSION_MASK) != SDPCM_SHARED_VERSION) {
 		DHD_ERROR(("%s: sdpcm_shared version %d in dhd "
@@ -1932,10 +1930,8 @@
 #endif				/* DHD_DEBUG */
 
 done:
-	if (mbuffer)
-		kfree(mbuffer);
-	if (str)
-		kfree(str);
+	kfree(mbuffer);
+	kfree(str);
 
 	return bcmerror;
 }
@@ -1952,34 +1948,33 @@
 	size = bus->ramsize;
 	buf = kmalloc(size, GFP_ATOMIC);
 	if (!buf) {
-		printf("%s: Out of memory (%d bytes)\n", __func__, size);
+		DHD_ERROR(("%s: Out of memory (%d bytes)\n", __func__, size));
 		return -1;
 	}
 
 	/* Read mem content */
-	printf("Dump dongle memory");
+	printk(KERN_DEBUG "Dump dongle memory");
 	databuf = buf;
 	while (size) {
 		read_size = min(MEMBLOCK, size);
 		ret = dhdsdio_membytes(bus, false, start, databuf, read_size);
 		if (ret) {
-			printf("%s: Error membytes %d\n", __func__, ret);
-			if (buf)
-				kfree(buf);
+			DHD_ERROR(("%s: Error membytes %d\n", __func__, ret));
+			kfree(buf);
 			return -1;
 		}
-		printf(".");
+		printk(".");
 
 		/* Decrement size and increment start address */
 		size -= read_size;
 		start += read_size;
 		databuf += read_size;
 	}
-	printf("Done\n");
+	printk(KERN_DEBUG "Done\n");
 
 	/* free buf before return !!! */
 	if (write_to_file(bus->dhd, buf, bus->ramsize)) {
-		printf("%s: Error writing to files\n", __func__);
+		DHD_ERROR(("%s: Error writing to files\n", __func__));
 		return -1;
 	}
 
@@ -2009,13 +2004,13 @@
 
 	/* Allocate console buffer (one time only) */
 	if (c->buf == NULL) {
-		c->bufsize = ltoh32(c->log.buf_size);
+		c->bufsize = le32_to_cpu(c->log.buf_size);
 		c->buf = kmalloc(c->bufsize, GFP_ATOMIC);
 		if (c->buf == NULL)
 			return BCME_NOMEM;
 	}
 
-	idx = ltoh32(c->log.idx);
+	idx = le32_to_cpu(c->log.idx);
 
 	/* Protect against corrupt value */
 	if (idx > c->bufsize)
@@ -2027,7 +2022,7 @@
 		return BCME_OK;
 
 	/* Read the console buffer */
-	addr = ltoh32(c->log.buf);
+	addr = le32_to_cpu(c->log.buf);
 	rv = dhdsdio_membytes(bus, false, addr, c->buf, c->bufsize);
 	if (rv < 0)
 		return rv;
@@ -2057,7 +2052,7 @@
 			if (line[n - 1] == '\r')
 				n--;
 			line[n] = 0;
-			printf("CONSOLE: %s\n", line);
+			printk(KERN_DEBUG "CONSOLE: %s\n", line);
 		}
 	}
 break2:
@@ -2083,8 +2078,7 @@
 	}
 
 	/* Free the old ones and replace with passed variables */
-	if (bus->vars)
-		kfree(bus->vars);
+	kfree(bus->vars);
 
 	bus->vars = kmalloc(len, GFP_ATOMIC);
 	bus->varsz = bus->vars ? len : 0;
@@ -2095,7 +2089,7 @@
 
 	/* Copy the passed variables, which should include the
 		 terminating double-null */
-	bcopy(arg, bus->vars, bus->varsz);
+	memcpy(bus->vars, arg, bus->varsz);
 err:
 	return bcmerror;
 }
@@ -2118,7 +2112,7 @@
 		goto exit;
 
 	if (plen >= (int)sizeof(int_val))
-		bcopy(params, &int_val, sizeof(int_val));
+		memcpy(&int_val, params, sizeof(int_val));
 
 	bool_val = (int_val != 0) ? true : false;
 
@@ -2138,7 +2132,7 @@
 			bcmerror = dhdsdio_bussleep(bus, bool_val);
 		} else {
 			int_val = (s32) bus->sleeping;
-			bcopy(&int_val, arg, val_size);
+			memcpy(arg, &int_val, val_size);
 		}
 		goto exit;
 	}
@@ -2152,7 +2146,7 @@
 	switch (actionid) {
 	case IOV_GVAL(IOV_INTR):
 		int_val = (s32) bus->intr;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_INTR):
@@ -2173,7 +2167,7 @@
 
 	case IOV_GVAL(IOV_POLLRATE):
 		int_val = (s32) bus->pollrate;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_POLLRATE):
@@ -2183,7 +2177,7 @@
 
 	case IOV_GVAL(IOV_IDLETIME):
 		int_val = bus->idletime;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_IDLETIME):
@@ -2195,7 +2189,7 @@
 
 	case IOV_GVAL(IOV_IDLECLOCK):
 		int_val = (s32) bus->idleclock;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_IDLECLOCK):
@@ -2204,7 +2198,7 @@
 
 	case IOV_GVAL(IOV_SD1IDLE):
 		int_val = (s32) sd1idle;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SD1IDLE):
@@ -2223,8 +2217,8 @@
 			ASSERT(plen >= 2 * sizeof(int));
 
 			address = (u32) int_val;
-			bcopy((char *)params + sizeof(int_val), &int_val,
-			      sizeof(int_val));
+			memcpy(&int_val, (char *)params + sizeof(int_val),
+			       sizeof(int_val));
 			size = (uint) int_val;
 
 			/* Do some validation */
@@ -2267,17 +2261,17 @@
 
 	case IOV_GVAL(IOV_MEMSIZE):
 		int_val = (s32) bus->ramsize;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_GVAL(IOV_SDIOD_DRIVE):
 		int_val = (s32) dhd_sdiod_drive_strength;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDIOD_DRIVE):
 		dhd_sdiod_drive_strength = int_val;
-		si_sdiod_drive_strength_init(bus->sih, bus->dhd->osh,
+		si_sdiod_drive_strength_init(bus->sih,
 					     dhd_sdiod_drive_strength);
 		break;
 
@@ -2291,7 +2285,7 @@
 
 	case IOV_GVAL(IOV_READAHEAD):
 		int_val = (s32) dhd_readahead;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_READAHEAD):
@@ -2302,7 +2296,7 @@
 
 	case IOV_GVAL(IOV_SDRXCHAIN):
 		int_val = (s32) bus->use_rxchain;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_SDRXCHAIN):
@@ -2313,7 +2307,7 @@
 		break;
 	case IOV_GVAL(IOV_ALIGNCTL):
 		int_val = (s32) dhd_alignctl;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_ALIGNCTL):
@@ -2322,13 +2316,13 @@
 
 	case IOV_GVAL(IOV_SDALIGN):
 		int_val = DHD_SDALIGN;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 #ifdef DHD_DEBUG
 	case IOV_GVAL(IOV_VARS):
 		if (bus->varsz < (uint) len)
-			bcopy(bus->vars, arg, bus->varsz);
+			memcpy(arg, bus->vars, bus->varsz);
 		else
 			bcmerror = BCME_BUFTOOSHORT;
 		break;
@@ -2347,7 +2341,7 @@
 			int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
 			if (bcmsdh_regfail(bus->sdh))
 				bcmerror = BCME_SDIO_ERROR;
-			bcopy(&int_val, arg, sizeof(s32));
+			memcpy(arg, &int_val, sizeof(s32));
 			break;
 		}
 
@@ -2373,14 +2367,14 @@
 			sdreg_t sdreg;
 			u32 addr, size;
 
-			bcopy(params, &sdreg, sizeof(sdreg));
+			memcpy(&sdreg, params, sizeof(sdreg));
 
 			addr = SI_ENUM_BASE + sdreg.offset;
 			size = sdreg.func;
 			int_val = (s32) bcmsdh_reg_read(bus->sdh, addr, size);
 			if (bcmsdh_regfail(bus->sdh))
 				bcmerror = BCME_SDIO_ERROR;
-			bcopy(&int_val, arg, sizeof(s32));
+			memcpy(arg, &int_val, sizeof(s32));
 			break;
 		}
 
@@ -2389,7 +2383,7 @@
 			sdreg_t sdreg;
 			u32 addr, size;
 
-			bcopy(params, &sdreg, sizeof(sdreg));
+			memcpy(&sdreg, params, sizeof(sdreg));
 
 			addr = SI_ENUM_BASE + sdreg.offset;
 			size = sdreg.func;
@@ -2420,7 +2414,7 @@
 
 	case IOV_GVAL(IOV_FORCEEVEN):
 		int_val = (s32) forcealign;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_FORCEEVEN):
@@ -2429,7 +2423,7 @@
 
 	case IOV_GVAL(IOV_TXBOUND):
 		int_val = (s32) dhd_txbound;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_TXBOUND):
@@ -2438,7 +2432,7 @@
 
 	case IOV_GVAL(IOV_RXBOUND):
 		int_val = (s32) dhd_rxbound;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_RXBOUND):
@@ -2447,7 +2441,7 @@
 
 	case IOV_GVAL(IOV_TXMINMAX):
 		int_val = (s32) dhd_txminmax;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_TXMINMAX):
@@ -2458,7 +2452,7 @@
 #ifdef SDTEST
 	case IOV_GVAL(IOV_EXTLOOP):
 		int_val = (s32) bus->ext_loop;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 		break;
 
 	case IOV_SVAL(IOV_EXTLOOP):
@@ -2480,9 +2474,6 @@
 			__func__, bool_val, bus->dhd->dongle_reset,
 			bus->dhd->busstate));
 
-		ASSERT(bus->dhd->osh);
-		/* ASSERT(bus->cl_devid); */
-
 		dhd_bus_devreset(bus->dhd, (u8) bool_val);
 
 		break;
@@ -2492,7 +2483,7 @@
 
 		/* Get its status */
 		int_val = (bool) bus->dhd->dongle_reset;
-		bcopy(&int_val, arg, val_size);
+		memcpy(arg, &int_val, val_size);
 
 		break;
 
@@ -2532,12 +2523,11 @@
 	varaddr = (bus->ramsize - 4) - varsize;
 
 	if (bus->vars) {
-		vbuffer = kmalloc(varsize, GFP_ATOMIC);
+		vbuffer = kzalloc(varsize, GFP_ATOMIC);
 		if (!vbuffer)
 			return BCME_NOMEM;
 
-		memset(vbuffer, 0, varsize);
-		bcopy(bus->vars, vbuffer, bus->varsz);
+		memcpy(vbuffer, bus->vars, bus->varsz);
 
 		/* Write the vars list */
 		bcmerror =
@@ -2590,7 +2580,7 @@
 	} else {
 		varsizew = varsize / 4;
 		varsizew = (~varsizew << 16) | (varsizew & 0x0000FFFF);
-		varsizew = htol32(varsizew);
+		varsizew = cpu_to_le32(varsizew);
 	}
 
 	DHD_INFO(("New varsize is %d, length token=0x%08x\n", varsize,
@@ -2828,7 +2818,6 @@
 
 void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex)
 {
-	struct osl_info *osh = bus->dhd->osh;
 	u32 local_hostintmask;
 	u8 saveclk;
 	uint retries;
@@ -2878,14 +2867,14 @@
 	dhdsdio_clkctl(bus, CLK_SDONLY, false);
 
 	/* Clear the data packet queues */
-	pktq_flush(osh, &bus->txq, true);
+	pktq_flush(&bus->txq, true);
 
 	/* Clear any held glomming stuff */
 	if (bus->glomd)
-		pkt_buf_free_skb(osh, bus->glomd, false);
+		pkt_buf_free_skb(bus->glomd);
 
 	if (bus->glom)
-		pkt_buf_free_skb(osh, bus->glom, false);
+		pkt_buf_free_skb(bus->glom);
 
 	bus->glom = bus->glomd = NULL;
 
@@ -3100,13 +3089,13 @@
 	ASSERT(bus->rxctl >= bus->rxbuf);
 
 	/* Copy the already-read portion over */
-	bcopy(hdr, bus->rxctl, firstread);
+	memcpy(bus->rxctl, hdr, firstread);
 	if (len <= firstread)
 		goto gotpkt;
 
 	/* Copy the full data pkt in gSPI case and process ioctl. */
 	if (bus->bus == SPI_BUS) {
-		bcopy(hdr, bus->rxctl, len);
+		memcpy(bus->rxctl, hdr, len);
 		goto gotpkt;
 	}
 
@@ -3184,7 +3173,6 @@
 
 	u16 sublen, check;
 	struct sk_buff *pfirst, *plast, *pnext, *save_pfirst;
-	struct osl_info *osh = bus->dhd->osh;
 
 	int errcode;
 	u8 chan, seq, doff, sfdoff;
@@ -3214,7 +3202,7 @@
 
 		for (totlen = num = 0; dlen; num++) {
 			/* Get (and move past) next length */
-			sublen = ltoh16_ua(dptr);
+			sublen = get_unaligned_le16(dptr);
 			dlen -= sizeof(u16);
 			dptr += sizeof(u16);
 			if ((sublen < SDPCM_HDRLEN) ||
@@ -3240,7 +3228,7 @@
 			}
 
 			/* Allocate/chain packet for next subframe */
-			pnext = pkt_buf_get_skb(osh, sublen + DHD_SDALIGN);
+			pnext = pkt_buf_get_skb(sublen + DHD_SDALIGN);
 			if (pnext == NULL) {
 				DHD_ERROR(("%s: pkt_buf_get_skb failed, num %d len %d\n",
 					   __func__, num, sublen));
@@ -3257,7 +3245,7 @@
 			}
 
 			/* Adhere to start alignment requirements */
-			PKTALIGN(osh, pnext, sublen, DHD_SDALIGN);
+			PKTALIGN(pnext, sublen, DHD_SDALIGN);
 		}
 
 		/* If all allocations succeeded, save packet chain
@@ -3276,13 +3264,13 @@
 			pfirst = pnext = NULL;
 		} else {
 			if (pfirst)
-				pkt_buf_free_skb(osh, pfirst, false);
+				pkt_buf_free_skb(pfirst);
 			bus->glom = NULL;
 			num = 0;
 		}
 
 		/* Done with descriptor packet */
-		pkt_buf_free_skb(osh, bus->glomd, false);
+		pkt_buf_free_skb(bus->glomd);
 		bus->glomd = NULL;
 		bus->nextlen = 0;
 
@@ -3303,7 +3291,7 @@
 		}
 
 		pfirst = bus->glom;
-		dlen = (u16) pkttotlen(osh, pfirst);
+		dlen = (u16) pkttotlen(pfirst);
 
 		/* Do an SDIO read for the superframe.  Configurable iovar to
 		 * read directly into the chained packet, or allocate a large
@@ -3323,7 +3311,7 @@
 						      F2SYNC, bus->dataptr,
 						      dlen, NULL, NULL, NULL);
 			sublen =
-			    (u16) pktfrombuf(osh, pfirst, 0, dlen,
+			    (u16) pktfrombuf(pfirst, 0, dlen,
 						bus->dataptr);
 			if (sublen != dlen) {
 				DHD_ERROR(("%s: FAILED TO COPY, dlen %d sublen %d\n",
@@ -3351,7 +3339,7 @@
 				bus->glomerr = 0;
 				dhdsdio_rxfail(bus, true, false);
 				dhd_os_sdlock_rxq(bus->dhd);
-				pkt_buf_free_skb(osh, bus->glom, false);
+				pkt_buf_free_skb(bus->glom);
 				dhd_os_sdunlock_rxq(bus->dhd);
 				bus->rxglomfail++;
 				bus->glom = NULL;
@@ -3367,8 +3355,8 @@
 
 		/* Validate the superframe header */
 		dptr = (u8 *) (pfirst->data);
-		sublen = ltoh16_ua(dptr);
-		check = ltoh16_ua(dptr + sizeof(u16));
+		sublen = get_unaligned_le16(dptr);
+		check = get_unaligned_le16(dptr + sizeof(u16));
 
 		chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 		seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -3437,8 +3425,8 @@
 		     num++, pnext = pnext->next) {
 			dptr = (u8 *) (pnext->data);
 			dlen = (u16) (pnext->len);
-			sublen = ltoh16_ua(dptr);
-			check = ltoh16_ua(dptr + sizeof(u16));
+			sublen = get_unaligned_le16(dptr);
+			check = get_unaligned_le16(dptr + sizeof(u16));
 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
 #ifdef DHD_DEBUG
@@ -3480,7 +3468,7 @@
 				bus->glomerr = 0;
 				dhdsdio_rxfail(bus, true, false);
 				dhd_os_sdlock_rxq(bus->dhd);
-				pkt_buf_free_skb(osh, bus->glom, false);
+				pkt_buf_free_skb(bus->glom);
 				dhd_os_sdunlock_rxq(bus->dhd);
 				bus->rxglomfail++;
 				bus->glom = NULL;
@@ -3500,7 +3488,7 @@
 			pfirst->next = NULL;
 
 			dptr = (u8 *) (pfirst->data);
-			sublen = ltoh16_ua(dptr);
+			sublen = get_unaligned_le16(dptr);
 			chan = SDPCM_PACKET_CHANNEL(&dptr[SDPCM_FRAMETAG_LEN]);
 			seq = SDPCM_PACKET_SEQUENCE(&dptr[SDPCM_FRAMETAG_LEN]);
 			doff = SDPCM_DOFFSET_VALUE(&dptr[SDPCM_FRAMETAG_LEN]);
@@ -3528,7 +3516,7 @@
 			skb_pull(pfirst, doff);
 
 			if (pfirst->len == 0) {
-				pkt_buf_free_skb(bus->dhd->osh, pfirst, false);
+				pkt_buf_free_skb(pfirst);
 				if (plast) {
 					plast->next = pnext;
 				} else {
@@ -3541,7 +3529,7 @@
 				DHD_ERROR(("%s: rx protocol error\n",
 					   __func__));
 				bus->dhd->rx_errors++;
-				pkt_buf_free_skb(osh, pfirst, false);
+				pkt_buf_free_skb(pfirst);
 				if (plast) {
 					plast->next = pnext;
 				} else {
@@ -3585,7 +3573,6 @@
 /* Return true if there may be more frames to read */
 static uint dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
 {
-	struct osl_info *osh = bus->dhd->osh;
 	bcmsdh_info_t *sdh = bus->sdh;
 
 	u16 len, check;	/* Extracted hardware header fields */
@@ -3672,7 +3659,7 @@
 			 * control pkt receives.
 			 * Later we use buffer-poll for data as well
 			 * as control packets.
-			 * This is required becuase dhd receives full
+			 * This is required because dhd receives full
 			 * frame in gSPI unlike SDIO.
 			 * After the frame is received we have to
 			 * distinguish whether it is data
@@ -3680,7 +3667,7 @@
 			 */
 			/* Allocate a packet buffer */
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt = pkt_buf_get_skb(osh, rdlen + DHD_SDALIGN);
+			pkt = pkt_buf_get_skb(rdlen + DHD_SDALIGN);
 			if (!pkt) {
 				if (bus->bus == SPI_BUS) {
 					bus->usebufpool = false;
@@ -3738,7 +3725,7 @@
 					bus->usebufpool = true;
 
 				ASSERT(!(pkt->prev));
-				PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
+				PKTALIGN(pkt, rdlen, DHD_SDALIGN);
 				rxbuf = (u8 *) (pkt->data);
 				/* Read the entire frame */
 				sdret =
@@ -3753,11 +3740,11 @@
 				if (sdret < 0) {
 					DHD_ERROR(("%s (nextlen): read %d bytes failed: %d\n",
 						__func__, rdlen, sdret));
-					pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+					pkt_buf_free_skb(pkt);
 					bus->dhd->rx_errors++;
 					dhd_os_sdunlock_rxq(bus->dhd);
 					/* Force retry w/normal header read.
-					 * Don't attemp NAK for
+					 * Don't attempt NAK for
 					 * gSPI
 					 */
 					dhdsdio_rxfail(bus, true,
@@ -3770,11 +3757,11 @@
 			dhd_os_sdunlock_rxq(bus->dhd);
 
 			/* Now check the header */
-			bcopy(rxbuf, bus->rxhdr, SDPCM_HDRLEN);
+			memcpy(bus->rxhdr, rxbuf, SDPCM_HDRLEN);
 
 			/* Extract hardware header fields */
-			len = ltoh16_ua(bus->rxhdr);
-			check = ltoh16_ua(bus->rxhdr + sizeof(u16));
+			len = get_unaligned_le16(bus->rxhdr);
+			check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
 
 			/* All zeros means readahead info was bad */
 			if (!(len | check)) {
@@ -3901,8 +3888,7 @@
 							     doff);
 					if (bus->usebufpool) {
 						dhd_os_sdlock_rxq(bus->dhd);
-						pkt_buf_free_skb(bus->dhd->osh, pkt,
-							false);
+						pkt_buf_free_skb(pkt);
 						dhd_os_sdunlock_rxq(bus->dhd);
 					}
 					continue;
@@ -3965,8 +3951,8 @@
 #endif
 
 		/* Extract hardware header fields */
-		len = ltoh16_ua(bus->rxhdr);
-		check = ltoh16_ua(bus->rxhdr + sizeof(u16));
+		len = get_unaligned_le16(bus->rxhdr);
+		check = get_unaligned_le16(bus->rxhdr + sizeof(u16));
 
 		/* All zeros means no more frames */
 		if (!(len | check)) {
@@ -4091,7 +4077,7 @@
 		}
 
 		dhd_os_sdlock_rxq(bus->dhd);
-		pkt = pkt_buf_get_skb(osh, (rdlen + firstread + DHD_SDALIGN));
+		pkt = pkt_buf_get_skb(rdlen + firstread + DHD_SDALIGN);
 		if (!pkt) {
 			/* Give up on data, request rtx of events */
 			DHD_ERROR(("%s: pkt_buf_get_skb failed: rdlen %d chan %d\n",
@@ -4108,7 +4094,7 @@
 		/* Leave room for what we already read, and align remainder */
 		ASSERT(firstread < pkt->len);
 		skb_pull(pkt, firstread);
-		PKTALIGN(osh, pkt, rdlen, DHD_SDALIGN);
+		PKTALIGN(pkt, rdlen, DHD_SDALIGN);
 
 		/* Read the remaining frame data */
 		sdret =
@@ -4127,7 +4113,7 @@
 				       ? "data" : "test")),
 				   sdret));
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+			pkt_buf_free_skb(pkt);
 			dhd_os_sdunlock_rxq(bus->dhd);
 			bus->dhd->rx_errors++;
 			dhdsdio_rxfail(bus, true, RETRYCHAN(chan));
@@ -4136,7 +4122,7 @@
 
 		/* Copy the already-read portion */
 		skb_push(pkt, firstread);
-		bcopy(bus->rxhdr, pkt->data, firstread);
+		memcpy(pkt->data, bus->rxhdr, firstread);
 
 #ifdef DHD_DEBUG
 		if (DHD_BYTES_ON() && DHD_DATA_ON())
@@ -4180,13 +4166,13 @@
 
 		if (pkt->len == 0) {
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+			pkt_buf_free_skb(pkt);
 			dhd_os_sdunlock_rxq(bus->dhd);
 			continue;
 		} else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pkt) != 0) {
 			DHD_ERROR(("%s: rx protocol error\n", __func__));
 			dhd_os_sdlock_rxq(bus->dhd);
-			pkt_buf_free_skb(bus->dhd->osh, pkt, false);
+			pkt_buf_free_skb(pkt);
 			dhd_os_sdunlock_rxq(bus->dhd);
 			bus->dhd->rx_errors++;
 			continue;
@@ -4501,7 +4487,7 @@
 		if (ret == 0)
 			bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP;
 
-		printf("Return_dpc value is : %d\n", ret);
+		DHD_INFO(("Return_dpc value is : %d\n", ret));
 		bus->ctrl_frame_stat = false;
 		dhd_wait_event_wakeup(bus->dhd);
 	}
@@ -4635,13 +4621,12 @@
 	u8 *data;
 	uint pktcount;
 	uint fillbyte;
-	struct osl_info *osh = bus->dhd->osh;
 	u16 len;
 
 	/* Display current count if appropriate */
 	if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) {
 		bus->pktgen_ptick = 0;
-		printf("%s: send attempts %d rcvd %d\n",
+		printk(KERN_DEBUG "%s: send attempts %d rcvd %d\n",
 		       __func__, bus->pktgen_sent, bus->pktgen_rcvd);
 	}
 
@@ -4663,14 +4648,14 @@
 
 		/* Allocate an appropriate-sized packet */
 		len = bus->pktgen_len;
-		pkt = pkt_buf_get_skb(osh,
+		pkt = pkt_buf_get_skb(
 			(len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN),
 			true);
 		if (!pkt) {
 			DHD_ERROR(("%s: pkt_buf_get_skb failed!\n", __func__));
 			break;
 		}
-		PKTALIGN(osh, pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
+		PKTALIGN(pkt, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN),
 			 DHD_SDALIGN);
 		data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
 
@@ -4694,7 +4679,7 @@
 		default:
 			DHD_ERROR(("Unrecognized pktgen mode %d\n",
 				   bus->pktgen_mode));
-			pkt_buf_free_skb(osh, pkt, true);
+			pkt_buf_free_skb(pkt, true);
 			bus->pktgen_count = 0;
 			return;
 		}
@@ -4740,16 +4725,15 @@
 {
 	struct sk_buff *pkt;
 	u8 *data;
-	struct osl_info *osh = bus->dhd->osh;
 
 	/* Allocate the packet */
-	pkt = pkt_buf_get_skb(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN,
+	pkt = pkt_buf_get_skb(SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN,
 			true);
 	if (!pkt) {
 		DHD_ERROR(("%s: pkt_buf_get_skb failed!\n", __func__));
 		return;
 	}
-	PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
+	PKTALIGN(pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN);
 	data = (u8 *) (pkt->data) + SDPCM_HDRLEN;
 
 	/* Fill in the test header */
@@ -4765,7 +4749,6 @@
 
 static void dhdsdio_testrcv(dhd_bus_t *bus, struct sk_buff *pkt, uint seq)
 {
-	struct osl_info *osh = bus->dhd->osh;
 	u8 *data;
 	uint pktlen;
 
@@ -4779,7 +4762,7 @@
 	if (pktlen < SDPCM_TEST_HDRLEN) {
 		DHD_ERROR(("dhdsdio_restrcv: toss runt frame, pktlen %d\n",
 			   pktlen));
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		return;
 	}
 
@@ -4797,7 +4780,7 @@
 			DHD_ERROR(("dhdsdio_testrcv: frame length mismatch, "
 				"pktlen %d seq %d" " cmd %d extra %d len %d\n",
 				pktlen, seq, cmd, extra, len));
-			pkt_buf_free_skb(osh, pkt, false);
+			pkt_buf_free_skb(pkt, false);
 			return;
 		}
 	}
@@ -4812,14 +4795,14 @@
 			bus->pktgen_sent++;
 		} else {
 			bus->pktgen_fail++;
-			pkt_buf_free_skb(osh, pkt, false);
+			pkt_buf_free_skb(pkt, false);
 		}
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_ECHORSP:
 		if (bus->ext_loop) {
-			pkt_buf_free_skb(osh, pkt, false);
+			pkt_buf_free_skb(pkt, false);
 			bus->pktgen_rcvd++;
 			break;
 		}
@@ -4832,12 +4815,12 @@
 				break;
 			}
 		}
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		bus->pktgen_rcvd++;
 		break;
 
 	case SDPCM_TEST_DISCARD:
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		bus->pktgen_rcvd++;
 		break;
 
@@ -4847,7 +4830,7 @@
 		DHD_INFO(("dhdsdio_testrcv: unsupported or unknown command, "
 			"pktlen %d seq %d" " cmd %d extra %d len %d\n",
 			pktlen, seq, cmd, extra, len));
-		pkt_buf_free_skb(osh, pkt, false);
+		pkt_buf_free_skb(pkt, false);
 		break;
 	}
 
@@ -4987,7 +4970,7 @@
 
 	/* Zero cbuf_index */
 	addr = bus->console_addr + offsetof(hndrte_cons_t, cbuf_idx);
-	val = htol32(0);
+	val = cpu_to_le32(0);
 	rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
 	if (rv < 0)
 		goto done;
@@ -5000,7 +4983,7 @@
 
 	/* Write length into vcons_in */
 	addr = bus->console_addr + offsetof(hndrte_cons_t, vcons_in);
-	val = htol32(msglen);
+	val = cpu_to_le32(msglen);
 	rv = dhdsdio_membytes(bus, true, addr, (u8 *)&val, sizeof(val));
 	if (rv < 0)
 		goto done;
@@ -5008,7 +4991,7 @@
 	/* Bump dongle by sending an empty event pkt.
 	 * sdpcm_sendup (RX) checks for virtual console input.
 	 */
-	pkt = pkt_buf_get_skb(bus->dhd->osh, 4 + SDPCM_RESERVE);
+	pkt = pkt_buf_get_skb(4 + SDPCM_RESERVE);
 	if ((pkt != NULL) && bus->clkstate == CLK_AVAIL)
 		dhdsdio_txpkt(bus, pkt, SDPCM_EVENT_CHANNEL, true);
 
@@ -5066,7 +5049,7 @@
 
 static void *dhdsdio_probe(u16 venid, u16 devid, u16 bus_no,
 			   u16 slot, u16 func, uint bustype, void *regsva,
-			   struct osl_info *osh, void *sdh)
+			   void *sdh)
 {
 	int ret;
 	dhd_bus_t *bus;
@@ -5085,7 +5068,6 @@
 	sd1idle = true;
 	dhd_readahead = true;
 	retrydata = false;
-	dhd_doflow = false;
 	dhd_dongle_memsize = 0;
 	dhd_txminmax = DHD_TXMINMAX;
 
@@ -5143,15 +5125,6 @@
 		return NULL;
 	}
 
-	if (osh == NULL) {
-		/* Ask the OS interface part for an OSL handle */
-		osh = dhd_osl_attach(sdh, DHD_BUS);
-		if (!osh) {
-			DHD_ERROR(("%s: osl_attach failed!\n", __func__));
-			return NULL;
-		}
-	}
-
 	/* Allocate private bus interface state */
 	bus = kzalloc(sizeof(dhd_bus_t), GFP_ATOMIC);
 	if (!bus) {
@@ -5166,25 +5139,25 @@
 					 else use locally malloced rxbuf */
 
 	/* attempt to attach to the dongle */
-	if (!(dhdsdio_probe_attach(bus, osh, sdh, regsva, devid))) {
+	if (!(dhdsdio_probe_attach(bus, sdh, regsva, devid))) {
 		DHD_ERROR(("%s: dhdsdio_probe_attach failed\n", __func__));
 		goto fail;
 	}
 
 	/* Attach to the dhd/OS/network interface */
-	bus->dhd = dhd_attach(osh, bus, SDPCM_RESERVE);
+	bus->dhd = dhd_attach(bus, SDPCM_RESERVE);
 	if (!bus->dhd) {
 		DHD_ERROR(("%s: dhd_attach failed\n", __func__));
 		goto fail;
 	}
 
 	/* Allocate buffers */
-	if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
+	if (!(dhdsdio_probe_malloc(bus, sdh))) {
 		DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __func__));
 		goto fail;
 	}
 
-	if (!(dhdsdio_probe_init(bus, osh, sdh))) {
+	if (!(dhdsdio_probe_init(bus, sdh))) {
 		DHD_ERROR(("%s: dhdsdio_probe_init failed\n", __func__));
 		goto fail;
 	}
@@ -5220,13 +5193,12 @@
 	return bus;
 
 fail:
-	dhdsdio_release(bus, osh);
+	dhdsdio_release(bus);
 	return NULL;
 }
 
 static bool
-dhdsdio_probe_attach(struct dhd_bus *bus, struct osl_info *osh, void *sdh,
-			void *regsva, u16 devid)
+dhdsdio_probe_attach(struct dhd_bus *bus, void *sdh, void *regsva, u16 devid)
 {
 	u8 clkctl = 0;
 	int err = 0;
@@ -5238,7 +5210,7 @@
 		DHD_ERROR(("%s: FAILED to return to SI_ENUM_BASE\n", __func__));
 
 #ifdef DHD_DEBUG
-	printf("F1 signature read @0x18000000=0x%4x\n",
+	printk(KERN_DEBUG "F1 signature read @0x18000000=0x%4x\n",
 	       bcmsdh_reg_read(bus->sdh, SI_ENUM_BASE, 4));
 
 #endif				/* DHD_DEBUG */
@@ -5279,13 +5251,12 @@
 		udelay(65);
 
 		for (fn = 0; fn <= numfn; fn++) {
-			cis[fn] = kmalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
+			cis[fn] = kzalloc(SBSDIO_CIS_SIZE_LIMIT, GFP_ATOMIC);
 			if (!cis[fn]) {
 				DHD_INFO(("dhdsdio_probe: fn %d cis malloc "
 					"failed\n", fn));
 				break;
 			}
-			memset(cis[fn], 0, SBSDIO_CIS_SIZE_LIMIT);
 
 			err = bcmsdh_cis_read(sdh, fn, cis[fn],
 						SBSDIO_CIS_SIZE_LIMIT);
@@ -5311,7 +5282,7 @@
 #endif				/* DHD_DEBUG */
 
 	/* si_attach() will provide an SI handle and scan the backplane */
-	bus->sih = si_attach((uint) devid, osh, regsva, DHD_BUS, sdh,
+	bus->sih = si_attach((uint) devid, regsva, DHD_BUS, sdh,
 				   &bus->vars, &bus->varsz);
 	if (!(bus->sih)) {
 		DHD_ERROR(("%s: si_attach failed!\n", __func__));
@@ -5326,7 +5297,7 @@
 		goto fail;
 	}
 
-	si_sdiod_drive_strength_init(bus->sih, osh, dhd_sdiod_drive_strength);
+	si_sdiod_drive_strength_init(bus->sih, dhd_sdiod_drive_strength);
 
 	/* Get info on the ARM and SOCRAM cores... */
 	if (!DHD_NOPMU(bus)) {
@@ -5364,9 +5335,9 @@
 	bus->sdpcmrev = si_corerev(bus->sih);
 
 	/* Set core control so an SDIO reset does a backplane reset */
-	OR_REG(osh, &bus->regs->corecontrol, CC_BPRESEN);
+	OR_REG(&bus->regs->corecontrol, CC_BPRESEN);
 
-	pktq_init(&bus->txq, (PRIOMASK + 1), QLEN);
+	pktq_init(&bus->txq, (PRIOMASK + 1), TXQLEN);
 
 	/* Locate an appropriately-aligned portion of hdrbuf */
 	bus->rxhdr = (u8 *) roundup((unsigned long)&bus->hdrbuf[0], DHD_SDALIGN);
@@ -5383,8 +5354,7 @@
 	return false;
 }
 
-static bool dhdsdio_probe_malloc(dhd_bus_t *bus, struct osl_info *osh,
-				 void *sdh)
+static bool dhdsdio_probe_malloc(dhd_bus_t *bus, void *sdh)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -5425,7 +5395,7 @@
 	return false;
 }
 
-static bool dhdsdio_probe_init(dhd_bus_t *bus, struct osl_info *osh, void *sdh)
+static bool dhdsdio_probe_init(dhd_bus_t *bus, void *sdh)
 {
 	s32 fnum;
 
@@ -5502,20 +5472,19 @@
 }
 
 bool
-dhd_bus_download_firmware(struct dhd_bus *bus, struct osl_info *osh,
-			  char *fw_path, char *nv_path)
+dhd_bus_download_firmware(struct dhd_bus *bus, char *fw_path, char *nv_path)
 {
 	bool ret;
 	bus->fw_path = fw_path;
 	bus->nv_path = nv_path;
 
-	ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
+	ret = dhdsdio_download_firmware(bus, bus->sdh);
 
 	return ret;
 }
 
 static bool
-dhdsdio_download_firmware(struct dhd_bus *bus, struct osl_info *osh, void *sdh)
+dhdsdio_download_firmware(struct dhd_bus *bus, void *sdh)
 {
 	bool ret;
 
@@ -5530,37 +5499,32 @@
 }
 
 /* Detach and free everything */
-static void dhdsdio_release(dhd_bus_t *bus, struct osl_info *osh)
+static void dhdsdio_release(dhd_bus_t *bus)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
 	if (bus) {
-		ASSERT(osh);
-
 		/* De-register interrupt handler */
 		bcmsdh_intr_disable(bus->sdh);
 		bcmsdh_intr_dereg(bus->sdh);
 
 		if (bus->dhd) {
 
-			dhdsdio_release_dongle(bus, osh);
+			dhdsdio_release_dongle(bus);
 
 			dhd_detach(bus->dhd);
 			bus->dhd = NULL;
 		}
 
-		dhdsdio_release_malloc(bus, osh);
+		dhdsdio_release_malloc(bus);
 
 		kfree(bus);
 	}
 
-	if (osh)
-		dhd_osl_detach(osh);
-
 	DHD_TRACE(("%s: Disconnected\n", __func__));
 }
 
-static void dhdsdio_release_malloc(dhd_bus_t *bus, struct osl_info *osh)
+static void dhdsdio_release_malloc(dhd_bus_t *bus)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -5573,13 +5537,11 @@
 		bus->rxlen = 0;
 	}
 
-	if (bus->databuf) {
-		kfree(bus->databuf);
-		bus->databuf = NULL;
-	}
+	kfree(bus->databuf);
+	bus->databuf = NULL;
 }
 
-static void dhdsdio_release_dongle(dhd_bus_t *bus, struct osl_info *osh)
+static void dhdsdio_release_dongle(dhd_bus_t *bus)
 {
 	DHD_TRACE(("%s: Enter\n", __func__));
 
@@ -5609,7 +5571,7 @@
 
 	if (bus) {
 		ASSERT(bus->dhd);
-		dhdsdio_release(bus, bus->dhd->osh);
+		dhdsdio_release(bus);
 	}
 
 	DHD_TRACE(("%s: Disconnected\n", __func__));
@@ -5679,6 +5641,10 @@
 		unsigned char *ularray;
 
 		ularray = kmalloc(bus->ramsize, GFP_ATOMIC);
+		if (!ularray) {
+			bcmerror = BCME_NOMEM;
+			goto err;
+		}
 		/* Upload image to verify downloaded contents. */
 		offset = 0;
 		memset(ularray, 0xaa, bus->ramsize);
@@ -5690,7 +5656,7 @@
 				DHD_ERROR(("%s: error %d on reading %d membytes"
 					" at 0x%08x\n",
 					__func__, bcmerror, MEMBLOCK, offset));
-				goto err;
+				goto free;
 			}
 
 			offset += MEMBLOCK;
@@ -5704,7 +5670,7 @@
 				DHD_ERROR(("%s: error %d on reading %d membytes at 0x%08x\n",
 				__func__, bcmerror,
 				sizeof(dlarray) - offset, offset));
-				goto err;
+				goto free;
 			}
 		}
 
@@ -5712,11 +5678,11 @@
 			DHD_ERROR(("%s: Downloaded image is corrupted.\n",
 				   __func__));
 			ASSERT(0);
-			goto err;
+			goto free;
 		} else
 			DHD_ERROR(("%s: Download/Upload/Compare succeeded.\n",
 				__func__));
-
+free:
 		kfree(ularray);
 	}
 #endif				/* DHD_DEBUG */
@@ -5764,8 +5730,7 @@
 	}
 
 err:
-	if (memblock)
-		kfree(memblock);
+	kfree(memblock);
 
 	if (image)
 		dhd_os_close_image(image);
@@ -5904,8 +5869,7 @@
 	}
 
 err:
-	if (memblock)
-		kfree(memblock);
+	kfree(memblock);
 
 	if (image)
 		dhd_os_close_image(image);
@@ -6051,7 +6015,7 @@
 
 			/* Clean tx/rx buffer pointers,
 			 detach from the dongle */
-			dhdsdio_release_dongle(bus, bus->dhd->osh);
+			dhdsdio_release_dongle(bus);
 
 			bus->dhd->dongle_reset = true;
 			bus->dhd->up = false;
@@ -6071,14 +6035,13 @@
 			bcmsdh_reset(bus->sdh);
 
 			/* Attempt to re-attach & download */
-			if (dhdsdio_probe_attach(bus, bus->dhd->osh, bus->sdh,
+			if (dhdsdio_probe_attach(bus, bus->sdh,
 						 (u32 *) SI_ENUM_BASE,
 						 bus->cl_devid)) {
 				/* Attempt to download binary to the dongle */
 				if (dhdsdio_probe_init
-				    (bus, bus->dhd->osh, bus->sdh)
+				    (bus, bus->sdh)
 				    && dhdsdio_download_firmware(bus,
-								 bus->dhd->osh,
 								 bus->sdh)) {
 
 					/* Re-init bus, enable F2 transfer */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/hndpmu.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/hndpmu.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/hndpmu.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/hndpmu.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1 @@
+#include "../util/hndpmu.c"
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_armtrap.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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	_hndrte_armtrap_h
+#define	_hndrte_armtrap_h
+
+/* ARM trap handling */
+
+/* Trap types defined by ARM (see arminc.h) */
+
+/* Trap locations in lo memory */
+#define	TRAP_STRIDE	4
+#define FIRST_TRAP	TR_RST
+#define LAST_TRAP	(TR_FIQ * TRAP_STRIDE)
+
+#if defined(__ARM_ARCH_4T__)
+#define	MAX_TRAP_TYPE	(TR_FIQ + 1)
+#elif defined(__ARM_ARCH_7M__)
+#define	MAX_TRAP_TYPE	(TR_ISR + ARMCM3_NUMINTS)
+#endif				/* __ARM_ARCH_7M__ */
+
+/* The trap structure is defined here as offsets for assembly */
+#define	TR_TYPE		0x00
+#define	TR_EPC		0x04
+#define	TR_CPSR		0x08
+#define	TR_SPSR		0x0c
+#define	TR_REGS		0x10
+#define	TR_REG(n)	(TR_REGS + (n) * 4)
+#define	TR_SP		TR_REG(13)
+#define	TR_LR		TR_REG(14)
+#define	TR_PC		TR_REG(15)
+
+#define	TRAP_T_SIZE	80
+
+#ifndef	_LANGUAGE_ASSEMBLY
+
+typedef struct _trap_struct {
+	u32 type;
+	u32 epc;
+	u32 cpsr;
+	u32 spsr;
+	u32 r0;
+	u32 r1;
+	u32 r2;
+	u32 r3;
+	u32 r4;
+	u32 r5;
+	u32 r6;
+	u32 r7;
+	u32 r8;
+	u32 r9;
+	u32 r10;
+	u32 r11;
+	u32 r12;
+	u32 r13;
+	u32 r14;
+	u32 pc;
+} trap_t;
+
+#endif				/* !_LANGUAGE_ASSEMBLY */
+
+#endif				/* _hndrte_armtrap_h */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/hndrte_cons.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,62 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 _hndrte_cons_h
+#define _hndrte_cons_h
+
+#define CBUF_LEN	(128)
+
+#define LOG_BUF_LEN	1024
+
+typedef struct {
+	u32 buf;		/* Can't be pointer on (64-bit) hosts */
+	uint buf_size;
+	uint idx;
+	char *_buf_compat;	/* Redundant pointer for backward compat. */
+} hndrte_log_t;
+
+typedef struct {
+	/* Virtual UART
+	 * When there is no UART (e.g. Quickturn),
+	 * the host should write a complete
+	 * input line directly into cbuf and then write
+	 * the length into vcons_in.
+	 * This may also be used when there is a real UART
+	 * (at risk of conflicting with
+	 * the real UART).  vcons_out is currently unused.
+	 */
+	volatile uint vcons_in;
+	volatile uint vcons_out;
+
+	/* Output (logging) buffer
+	 * Console output is written to a ring buffer log_buf at index log_idx.
+	 * The host may read the output when it sees log_idx advance.
+	 * Output will be lost if the output wraps around faster than the host
+	 * polls.
+	 */
+	hndrte_log_t log;
+
+	/* Console input line buffer
+	 * Characters are read one at a time into cbuf
+	 * until <CR> is received, then
+	 * the buffer is processed as a command line.
+	 * Also used for virtual UART.
+	 */
+	uint cbuf_idx;
+	char cbuf[CBUF_LEN];
+} hndrte_cons_t;
+
+#endif /* _hndrte_cons_h */
+
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/Kconfig linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/Kconfig
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/Kconfig	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/Kconfig	1969-12-31 19:00:00.000000000 -0500
@@ -1,15 +0,0 @@
-menuconfig BRCMFMAC
-	tristate "Broadcom fullmac wireless cards support"
-	depends on MMC
-	depends on CFG80211
-	select FW_LOADER
-	select WIRELESS_EXT
-	select WEXT_PRIV
-	---help---
-	  This module adds support for wireless adapters based on
-	  Broadcom fullmac chipsets.
-	  This driver uses the kernel's wireless extensions subsystem.
-	  If you choose to build a module, it'll be called brcmfmac.ko. Say M if
-	  unsure.
-
-
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/Makefile linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/Makefile
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/Makefile	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -17,13 +17,11 @@
 
 ccflags-y :=			\
 	-DARP_OFFLOAD_SUPPORT	\
-	-DBCMDBG		\
 	-DBCMLXSDMMC		\
 	-DBCMPLATFORM_BUS	\
 	-DBCMSDIO		\
 	-DBDC			\
 	-DBRCM_FULLMAC		\
-	-DDHD_DEBUG		\
 	-DDHD_FIRSTREAD=64	\
 	-DDHD_SCHED		\
 	-DDHD_SDALIGN=64	\
@@ -32,16 +30,34 @@
 	-DMMC_SDIO_ABORT	\
 	-DPKT_FILTER_SUPPORT	\
 	-DSHOW_EVENTS		\
-	-DTOE			\
-	-Idrivers/staging/brcm80211/brcmfmac		\
+	-DTOE
+
+ccflags-$(CONFIG_BRCMDBG)	+= -DDHD_DEBUG
+
+ccflags-y += \
+	-Idrivers/staging/brcm80211/brcmfmac	\
 	-Idrivers/staging/brcm80211/include		\
 	-Idrivers/staging/brcm80211/util
 
-DHDOFILES = dhd_linux.o ../util/linux_osl.o ../util/bcmutils.o dhd_common.o dhd_custom_gpio.o	\
-	wl_iw.o wl_cfg80211.o ../util/siutils.o ../util/sbutils.o ../util/aiutils.o ../util/hndpmu.o ../util/bcmwifi.o dhd_sdio.o	\
-	dhd_linux_sched.o dhd_cdc.o bcmsdh_sdmmc.o bcmsdh.o bcmsdh_linux.o	\
-	bcmsdh_sdmmc_linux.o
+DHDOFILES = \
+	wl_cfg80211.o \
+	wl_iw.o \
+	dhd_cdc.o \
+	dhd_common.o \
+	dhd_custom_gpio.o \
+	dhd_sdio.o	\
+	dhd_linux.o \
+	dhd_linux_sched.o \
+	bcmsdh.o \
+	bcmsdh_linux.o	\
+	bcmsdh_sdmmc.o \
+	bcmsdh_sdmmc_linux.o \
+	aiutils.o \
+	siutils.o \
+	sbutils.o \
+	bcmutils.o \
+	bcmwifi.o \
+	hndpmu.o
 
 obj-m += brcmfmac.o
 brcmfmac-objs += $(DHDOFILES)
-
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/msgtrace.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/msgtrace.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/msgtrace.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/msgtrace.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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	_MSGTRACE_H
+#define	_MSGTRACE_H
+
+#define MSGTRACE_VERSION 1
+
+/* Message trace header */
+typedef struct msgtrace_hdr {
+	u8 version;
+	u8 spare;
+	u16 len;		/* Len of the trace */
+	u32 seqnum;		/* Sequence number of message. Useful
+				 * if the messsage has been lost
+				 * because of DMA error or a bus reset
+				 * (ex: SDIO Func2)
+				 */
+	u32 discarded_bytes;	/* Number of discarded bytes because of
+				 trace overflow  */
+	u32 discarded_printf;	/* Number of discarded printf
+				 because of trace overflow */
+} __attribute__((packed)) msgtrace_hdr_t;
+
+#define MSGTRACE_HDRLEN		sizeof(msgtrace_hdr_t)
+
+/* The hbus driver generates traces when sending a trace message.
+ * This causes endless traces.
+ * This flag must be set to true in any hbus traces.
+ * The flag is reset in the function msgtrace_put.
+ * This prevents endless traces but generates hasardous
+ * lost of traces only in bus device code.
+ * It is recommendat to set this flag in macro SD_TRACE
+ * but not in SD_ERROR for avoiding missing
+ * hbus error traces. hbus error trace should not generates endless traces.
+ */
+extern bool msgtrace_hbus_trace;
+
+typedef void (*msgtrace_func_send_t) (void *hdl1, void *hdl2, u8 *hdr,
+				      u16 hdrlen, u8 *buf,
+				      u16 buflen);
+
+extern void msgtrace_sent(void);
+extern void msgtrace_put(char *buf, int count);
+extern void msgtrace_init(void *hdl1, void *hdl2,
+			  msgtrace_func_send_t func_send);
+
+#endif				/* _MSGTRACE_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/sbutils.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/sbutils.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/sbutils.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/sbutils.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1 @@
+#include "../util/sbutils.c"
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/sdioh.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/sdioh.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/sdioh.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/sdioh.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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	_SDIOH_H
+#define	_SDIOH_H
+
+#define SD_SysAddr			0x000
+#define SD_BlockSize			0x004
+#define SD_BlockCount 			0x006
+#define SD_Arg0				0x008
+#define SD_Arg1 			0x00A
+#define SD_TransferMode			0x00C
+#define SD_Command 			0x00E
+#define SD_Response0			0x010
+#define SD_Response1 			0x012
+#define SD_Response2			0x014
+#define SD_Response3 			0x016
+#define SD_Response4			0x018
+#define SD_Response5 			0x01A
+#define SD_Response6			0x01C
+#define SD_Response7 			0x01E
+#define SD_BufferDataPort0		0x020
+#define SD_BufferDataPort1 		0x022
+#define SD_PresentState			0x024
+#define SD_HostCntrl			0x028
+#define SD_PwrCntrl			0x029
+#define SD_BlockGapCntrl 		0x02A
+#define SD_WakeupCntrl 			0x02B
+#define SD_ClockCntrl			0x02C
+#define SD_TimeoutCntrl 		0x02E
+#define SD_SoftwareReset		0x02F
+#define SD_IntrStatus			0x030
+#define SD_ErrorIntrStatus 		0x032
+#define SD_IntrStatusEnable		0x034
+#define SD_ErrorIntrStatusEnable 	0x036
+#define SD_IntrSignalEnable		0x038
+#define SD_ErrorIntrSignalEnable 	0x03A
+#define SD_CMD12ErrorStatus		0x03C
+#define SD_Capabilities			0x040
+#define SD_Capabilities_Reserved	0x044
+#define SD_MaxCurCap			0x048
+#define SD_MaxCurCap_Reserved		0x04C
+#define SD_ADMA_SysAddr			0x58
+#define SD_SlotInterruptStatus		0x0FC
+#define SD_HostControllerVersion 	0x0FE
+
+/* SD specific registers in PCI config space */
+#define SD_SlotInfo	0x40
+
+#endif				/* _SDIOH_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/sdiovar.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/sdiovar.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/sdiovar.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/sdiovar.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 _sdiovar_h_
+#define _sdiovar_h_
+
+typedef struct sdreg {
+	int func;
+	int offset;
+	int value;
+} sdreg_t;
+
+/* Common msglevel constants */
+#define SDH_ERROR_VAL		0x0001	/* Error */
+#define SDH_TRACE_VAL		0x0002	/* Trace */
+#define SDH_INFO_VAL		0x0004	/* Info */
+#define SDH_DEBUG_VAL		0x0008	/* Debug */
+#define SDH_DATA_VAL		0x0010	/* Data */
+#define SDH_CTRL_VAL		0x0020	/* Control Regs */
+#define SDH_LOG_VAL		0x0040	/* Enable bcmlog */
+#define SDH_DMA_VAL		0x0080	/* DMA */
+
+#define NUM_PREV_TRANSACTIONS	16
+
+#endif				/* _sdiovar_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/siutils.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/siutils.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/siutils.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/siutils.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1 @@
+#include "../util/siutils.c"
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c	2012-03-24 01:11:05.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.c	2012-03-24 03:32:30.000000000 -0400
@@ -16,11 +16,8 @@
 
 #include <linux/kernel.h>
 #include <linux/if_arp.h>
-#include <osl.h>
 
 #include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
 
 #include <asm/uaccess.h>
 
@@ -44,6 +41,7 @@
 
 static struct sdio_func *cfg80211_sdio_func;
 static struct wl_dev *wl_cfg80211_dev;
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
 
 u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
 
@@ -87,8 +85,8 @@
 				      s32 dbm);
 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-					    struct net_device *dev,
-					    u8 key_idx);
+					  struct net_device *dev, u8 key_idx,
+					  bool unicast, bool multicast);
 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 				 u8 key_idx, bool pairwise, const u8 *mac_addr,
 				 struct key_params *params);
@@ -555,24 +553,24 @@
 
 static void swap_key_from_BE(struct wl_wsec_key *key)
 {
-	key->index = htod32(key->index);
-	key->len = htod32(key->len);
-	key->algo = htod32(key->algo);
-	key->flags = htod32(key->flags);
-	key->rxiv.hi = htod32(key->rxiv.hi);
-	key->rxiv.lo = htod16(key->rxiv.lo);
-	key->iv_initialized = htod32(key->iv_initialized);
+	key->index = cpu_to_le32(key->index);
+	key->len = cpu_to_le32(key->len);
+	key->algo = cpu_to_le32(key->algo);
+	key->flags = cpu_to_le32(key->flags);
+	key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+	key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+	key->iv_initialized = cpu_to_le32(key->iv_initialized);
 }
 
 static void swap_key_to_BE(struct wl_wsec_key *key)
 {
-	key->index = dtoh32(key->index);
-	key->len = dtoh32(key->len);
-	key->algo = dtoh32(key->algo);
-	key->flags = dtoh32(key->flags);
-	key->rxiv.hi = dtoh32(key->rxiv.hi);
-	key->rxiv.lo = dtoh16(key->rxiv.lo);
-	key->iv_initialized = dtoh32(key->iv_initialized);
+	key->index = le32_to_cpu(key->index);
+	key->len = le32_to_cpu(key->len);
+	key->algo = le32_to_cpu(key->algo);
+	key->flags = le32_to_cpu(key->flags);
+	key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
+	key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
+	key->iv_initialized = le32_to_cpu(key->iv_initialized);
 }
 
 static s32
@@ -626,8 +624,8 @@
 	default:
 		return -EINVAL;
 	}
-	infra = htod32(infra);
-	ap = htod32(ap);
+	infra = cpu_to_le32(infra);
+	ap = cpu_to_le32(ap);
 	wdev = ndev->ieee80211_ptr;
 	wdev->iftype = type;
 	WL_DBG("%s : ap (%d), infra (%d)\n", ndev->name, ap, infra);
@@ -648,7 +646,7 @@
 
 static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
 {
-	memcpy(&params->bssid, &ether_bcast, ETH_ALEN);
+	memcpy(params->bssid, ether_bcast, ETH_ALEN);
 	params->bss_type = DOT11_BSSTYPE_ANY;
 	params->scan_type = 0;
 	params->nprobes = -1;
@@ -657,10 +655,10 @@
 	params->home_time = -1;
 	params->channel_num = 0;
 
-	params->nprobes = htod32(params->nprobes);
-	params->active_time = htod32(params->active_time);
-	params->passive_time = htod32(params->passive_time);
-	params->home_time = htod32(params->home_time);
+	params->nprobes = cpu_to_le32(params->nprobes);
+	params->active_time = cpu_to_le32(params->active_time);
+	params->passive_time = cpu_to_le32(params->passive_time);
+	params->home_time = cpu_to_le32(params->home_time);
 	if (ssid && ssid->SSID_len)
 		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
 
@@ -673,7 +671,7 @@
 	s32 iolen;
 
 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(unlikely(!iolen));
+	BUG_ON(!iolen);
 
 	return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
 }
@@ -685,7 +683,7 @@
 	s32 iolen;
 
 	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(unlikely(!iolen));
+	BUG_ON(!iolen);
 
 	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
 }
@@ -703,14 +701,13 @@
 	params = kzalloc(params_size, GFP_KERNEL);
 	if (unlikely(!params))
 		return -ENOMEM;
-	memset(params, 0, params_size);
-	BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
+	BUG_ON(params_size >= WLC_IOCTL_SMLEN);
 
 	wl_iscan_prep(&params->params, ssid);
 
-	params->version = htod32(ISCAN_REQ_VERSION);
-	params->action = htod16(action);
-	params->scan_duration = htod16(0);
+	params->version = cpu_to_le32(ISCAN_REQ_VERSION);
+	params->action = cpu_to_le16(action);
+	params->scan_duration = cpu_to_le16(0);
 
 	/* params_size += offsetof(wl_iscan_params_t, params); */
 	err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
@@ -813,7 +810,7 @@
 			    min_t(u8, sizeof(sr->ssid.SSID), ssids->ssid_len);
 		if (sr->ssid.SSID_len) {
 			memcpy(sr->ssid.SSID, ssids->ssid, sr->ssid.SSID_len);
-			sr->ssid.SSID_len = htod32(sr->ssid.SSID_len);
+			sr->ssid.SSID_len = cpu_to_le32(sr->ssid.SSID_len);
 			WL_DBG("Specific scan ssid=\"%s\" len=%d\n",
 			       sr->ssid.SSID, sr->ssid.SSID_len);
 			spec_scan = true;
@@ -873,9 +870,9 @@
 	u32 len;
 	s32 err = 0;
 
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
-	BUG_ON(unlikely(!len));
+	BUG_ON(!len);
 
 	err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
 	if (unlikely(err)) {
@@ -899,12 +896,12 @@
 	len =
 	    bcm_mkiovar(name, (char *)(&data_null), 0, (char *)(&var),
 			sizeof(var.buf));
-	BUG_ON(unlikely(!len));
+	BUG_ON(!len);
 	err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
 	if (unlikely(err)) {
 		WL_ERR("error (%d)\n", err);
 	}
-	*retval = dtoh32(var.val);
+	*retval = le32_to_cpu(var.val);
 
 	return err;
 }
@@ -938,7 +935,7 @@
 	s32 err = 0;
 	u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
 
-	retry = htod32(retry);
+	retry = cpu_to_le32(retry);
 	err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
 	if (unlikely(err)) {
 		WL_ERR("cmd (%d) , error (%d)\n", cmd, err);
@@ -1041,7 +1038,7 @@
 	memset(&join_params, 0, sizeof(join_params));
 	memcpy((void *)join_params.ssid.SSID, (void *)params->ssid,
 	       params->ssid_len);
-	join_params.ssid.SSID_len = htod32(params->ssid_len);
+	join_params.ssid.SSID_len = cpu_to_le32(params->ssid_len);
 	if (params->bssid)
 		memcpy(&join_params.params.bssid, params->bssid,
 		       ETH_ALEN);
@@ -1371,12 +1368,12 @@
 
 	join_params.ssid.SSID_len = min(sizeof(join_params.ssid.SSID), sme->ssid_len);
 	memcpy(&join_params.ssid.SSID, sme->ssid, join_params.ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
+	join_params.ssid.SSID_len = cpu_to_le32(join_params.ssid.SSID_len);
 	wl_update_prof(wl, NULL, &join_params.ssid, WL_PROF_SSID);
-	memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
+	memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
 
 	wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size);
-	WL_DBG("join_param_size %d\n", join_params_size);
+	WL_DBG("join_param_size %zu\n", join_params_size);
 
 	if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) {
 		WL_DBG("ssid \"%s\", len (%d)\n",
@@ -1407,7 +1404,7 @@
 	if (likely(act)) {
 		scbval.val = reason_code;
 		memcpy(&scbval.ea, &wl->bssid, ETH_ALEN);
-		scbval.val = htod32(scbval.val);
+		scbval.val = cpu_to_le32(scbval.val);
 		err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
 				sizeof(scb_val_t));
 		if (unlikely(err)) {
@@ -1449,7 +1446,7 @@
 	}
 	/* Make sure radio is off or on as far as software is concerned */
 	disable = WL_RADIO_SW_DISABLE << 16;
-	disable = htod32(disable);
+	disable = cpu_to_le32(disable);
 	err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_RADIO error (%d)\n", err);
@@ -1493,7 +1490,7 @@
 
 static s32
 wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
-			       u8 key_idx)
+			       u8 key_idx, bool unicast, bool multicast)
 {
 	u32 index;
 	s32 wsec;
@@ -1507,11 +1504,11 @@
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		return err;
 	}
-	wsec = dtoh32(wsec);
+	wsec = le32_to_cpu(wsec);
 	if (wsec & WEP_ENABLED) {
 		/* Just select a new current key */
 		index = (u32) key_idx;
-		index = htod32(index);
+		index = cpu_to_le32(index);
 		err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
 				sizeof(index));
 		if (unlikely(err)) {
@@ -1684,7 +1681,7 @@
 	}
 
 	val = 1;		/* assume shared key. otherwise 0 */
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
@@ -1740,7 +1737,7 @@
 	}
 
 	val = 0;		/* assume open key. otherwise 1 */
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
 	if (unlikely(err)) {
 		WL_ERR("WLC_SET_AUTH error (%d)\n", err);
@@ -1768,7 +1765,7 @@
 	key.index = key_idx;
 	swap_key_to_BE(&key);
 	memset(&params, 0, sizeof(params));
-	params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
+	params.key_len = (u8) min_t(u8, WLAN_MAX_KEY_LEN, key.len);
 	memcpy(params.key, key.data, params.key_len);
 
 	err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
@@ -1776,7 +1773,7 @@
 		WL_ERR("WLC_GET_WSEC error (%d)\n", err);
 		return err;
 	}
-	wsec = dtoh32(wsec);
+	wsec = le32_to_cpu(wsec);
 	switch (wsec) {
 	case WEP_ENABLED:
 		sec = wl_read_prof(wl, WL_PROF_SEC);
@@ -1836,7 +1833,7 @@
 	if (err) {
 		WL_ERR("Could not get rate (%d)\n", err);
 	} else {
-		rate = dtoh32(rate);
+		rate = le32_to_cpu(rate);
 		sinfo->filled |= STATION_INFO_TX_BITRATE;
 		sinfo->txrate.legacy = rate * 5;
 		WL_DBG("Rate %d Mbps\n", rate / 2);
@@ -1850,7 +1847,7 @@
 			WL_ERR("Could not get rssi (%d)\n", err);
 			return err;
 		}
-		rssi = dtoh32(scb_val.val);
+		rssi = le32_to_cpu(scb_val.val);
 		sinfo->filled |= STATION_INFO_SIGNAL;
 		sinfo->signal = rssi;
 		WL_DBG("RSSI %d dBm\n", rssi);
@@ -1868,7 +1865,7 @@
 
 	CHECK_SYS_UP();
 	pm = enabled ? PM_FAST : PM_OFF;
-	pm = htod32(pm);
+	pm = cpu_to_le32(pm);
 	WL_DBG("power save %s\n", (pm ? "enabled" : "disabled"));
 	err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
 	if (unlikely(err)) {
@@ -1931,7 +1928,7 @@
 		return err;
 	}
 
-	rateset.count = dtoh32(rateset.count);
+	rateset.count = le32_to_cpu(rateset.count);
 
 	legacy = wl_find_msb(mask->control[IEEE80211_BAND_2GHZ].legacy);
 	if (!legacy)
@@ -1980,8 +1977,6 @@
 	struct net_device *ndev = wl_to_ndev(wl);
 	s32 err = 0;
 
-	CHECK_SYS_UP();
-
 	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
 	wl_term_iscan(wl);
 	if (wl->scan_request) {
@@ -2005,8 +2000,8 @@
 	WL_DBG("No of elements %d\n", pmk_list->pmkids.npmkid);
 	for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
 		WL_DBG("PMKID[%d]: %pM =\n", i,
-		       &pmk_list->pmkids.pmkid[i].BSSID);
-		for (j = 0; j < WPA2_PMKID_LEN; j++) {
+			&pmk_list->pmkids.pmkid[i].BSSID);
+		for (j = 0; j < WLAN_PMKID_LEN; j++) {
 			WL_DBG("%02x\n", pmk_list->pmkids.pmkid[i].PMKID[j]);
 		}
 	}
@@ -2035,7 +2030,7 @@
 		memcpy(&wl->pmk_list->pmkids.pmkid[i].BSSID, pmksa->bssid,
 		       ETH_ALEN);
 		memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID, pmksa->pmkid,
-		       WPA2_PMKID_LEN);
+		       WLAN_PMKID_LEN);
 		if (i == wl->pmk_list->pmkids.npmkid)
 			wl->pmk_list->pmkids.npmkid++;
 	} else {
@@ -2043,7 +2038,7 @@
 	}
 	WL_DBG("set_pmksa,IW_PMKSA_ADD - PMKID: %pM =\n",
 	       &wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].BSSID);
-	for (i = 0; i < WPA2_PMKID_LEN; i++) {
+	for (i = 0; i < WLAN_PMKID_LEN; i++) {
 		WL_DBG("%02x\n",
 		       wl->pmk_list->pmkids.pmkid[wl->pmk_list->pmkids.npmkid].
 		       PMKID[i]);
@@ -2065,11 +2060,11 @@
 
 	CHECK_SYS_UP();
 	memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETH_ALEN);
-	memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN);
+	memcpy(&pmkid.pmkid[0].PMKID, pmksa->pmkid, WLAN_PMKID_LEN);
 
 	WL_DBG("del_pmksa,IW_PMKSA_REMOVE - PMKID: %pM =\n",
 	       &pmkid.pmkid[0].BSSID);
-	for (i = 0; i < WPA2_PMKID_LEN; i++) {
+	for (i = 0; i < WLAN_PMKID_LEN; i++) {
 		WL_DBG("%02x\n", pmkid.pmkid[0].PMKID[i]);
 	}
 
@@ -2088,7 +2083,7 @@
 			       ETH_ALEN);
 			memcpy(&wl->pmk_list->pmkids.pmkid[i].PMKID,
 			       &wl->pmk_list->pmkids.pmkid[i + 1].PMKID,
-			       WPA2_PMKID_LEN);
+			       WLAN_PMKID_LEN);
 		}
 		wl->pmk_list->pmkids.npmkid--;
 	} else {
@@ -2264,7 +2259,7 @@
 	u32 freq;
 	s32 err = 0;
 
-	if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
+	if (unlikely(le32_to_cpu(bi->length) > WL_BSS_INFO_MAX)) {
 		WL_DBG("Beacon is larger than buffer. Discarding\n");
 		return err;
 	}
@@ -2313,7 +2308,9 @@
 	notif_bss_info->frame_len =
 	    offsetof(struct ieee80211_mgmt,
 		     u.beacon.variable) + wl_get_ielen(wl);
-	freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+	freq = ieee80211_channel_to_frequency(notif_bss_info->channel,
+					      band->band);
+
 	channel = ieee80211_get_channel(wiphy, freq);
 
 	WL_DBG("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
@@ -2337,8 +2334,8 @@
 
 static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
+	u32 event = be32_to_cpu(e->event_type);
+	u16 flags = be16_to_cpu(e->flags);
 
 	if (event == WLC_E_LINK) {
 		if (flags & WLC_EVENT_MSG_LINK) {
@@ -2356,8 +2353,8 @@
 
 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
+	u32 event = be32_to_cpu(e->event_type);
+	u16 flags = be16_to_cpu(e->flags);
 
 	if (event == WLC_E_DEAUTH_IND || event == WLC_E_DISASSOC_IND) {
 		return true;
@@ -2371,8 +2368,8 @@
 
 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
 {
-	u32 event = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
+	u32 event = be32_to_cpu(e->event_type);
+	u32 status = be32_to_cpu(e->status);
 
 	if (event == WLC_E_SET_SSID || event == WLC_E_LINK) {
 		if (status == WLC_E_STATUS_NO_NETWORKS)
@@ -2436,7 +2433,7 @@
 	u32 buflen;
 
 	buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
-	BUG_ON(unlikely(!buflen));
+	BUG_ON(!buflen);
 
 	return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
 }
@@ -2450,7 +2447,7 @@
 	s32 err = 0;
 
 	len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
-	BUG_ON(unlikely(!len));
+	BUG_ON(!len);
 	err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
 			WL_IOCTL_LEN_MAX);
 	if (unlikely(err)) {
@@ -2537,10 +2534,10 @@
 		join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
 		join_params->params.chanspec_list[0] |= chanspec;
 		join_params->params.chanspec_list[0] =
-		htodchanspec(join_params->params.chanspec_list[0]);
+		cpu_to_le16(join_params->params.chanspec_list[0]);
 
 		join_params->params.chanspec_num =
-			htod32(join_params->params.chanspec_num);
+			cpu_to_le32(join_params->params.chanspec_num);
 
 		WL_DBG("join_params->params.chanspec_list[0]= %#X, channel %d, chanspec %#X\n",
 		       join_params->params.chanspec_list[0], ch, chanspec);
@@ -2571,7 +2568,7 @@
 	rtnl_lock();
 	if (unlikely(!bss)) {
 		WL_DBG("Could not find the AP\n");
-		*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
+		*(u32 *) wl->extra_buf = cpu_to_le32(WL_EXTRA_BUF_MAX);
 		err = wl_dev_ioctl(wl_to_ndev(wl), WLC_GET_BSS_INFO,
 				wl->extra_buf, WL_EXTRA_BUF_MAX);
 		if (unlikely(err)) {
@@ -2682,7 +2679,7 @@
 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev,
 		     const wl_event_msg_t *e, void *data)
 {
-	u16 flags = ntoh16(e->flags);
+	u16 flags = be16_to_cpu(e->flags);
 	enum nl80211_key_type key_type;
 
 	rtnl_lock();
@@ -2723,7 +2720,7 @@
 		WL_ERR("scan busy (%d)\n", err);
 		goto scan_done_out;
 	}
-	channel_inform.scan_channel = dtoh32(channel_inform.scan_channel);
+	channel_inform.scan_channel = le32_to_cpu(channel_inform.scan_channel);
 	if (unlikely(channel_inform.scan_channel)) {
 
 		WL_DBG("channel_inform.scan_channel (%d)\n",
@@ -2732,16 +2729,16 @@
 	wl->bss_list = wl->scan_results;
 	bss_list = wl->bss_list;
 	memset(bss_list, 0, len);
-	bss_list->buflen = htod32(len);
+	bss_list->buflen = cpu_to_le32(len);
 	err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
 	if (unlikely(err)) {
 		WL_ERR("%s Scan_results error (%d)\n", ndev->name, err);
 		err = -EINVAL;
 		goto scan_done_out;
 	}
-	bss_list->buflen = dtoh32(bss_list->buflen);
-	bss_list->version = dtoh32(bss_list->version);
-	bss_list->count = dtoh32(bss_list->count);
+	bss_list->buflen = le32_to_cpu(bss_list->buflen);
+	bss_list->version = le32_to_cpu(bss_list->version);
+	bss_list->count = le32_to_cpu(bss_list->count);
 
 	err = wl_inform_bss(wl);
 	if (err)
@@ -2950,7 +2947,7 @@
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
+	list.results.buflen = cpu_to_le32(WL_ISCAN_BUF_MAX);
 	err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
 				WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
 				WL_ISCAN_BUF_MAX);
@@ -2958,12 +2955,12 @@
 		WL_ERR("error (%d)\n", err);
 		return err;
 	}
-	results->buflen = dtoh32(results->buflen);
-	results->version = dtoh32(results->version);
-	results->count = dtoh32(results->count);
+	results->buflen = le32_to_cpu(results->buflen);
+	results->version = le32_to_cpu(results->version);
+	results->count = le32_to_cpu(results->count);
 	WL_DBG("results->count = %d\n", results->count);
 	WL_DBG("results->buflen = %d\n", results->buflen);
-	*status = dtoh32(list_buf->status);
+	*status = le32_to_cpu(list_buf->status);
 	*bss_list = results;
 
 	return err;
@@ -3274,7 +3271,7 @@
 void
 wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
 {
-	u32 event_type = ntoh32(e->event_type);
+	u32 event_type = be32_to_cpu(e->event_type);
 	struct wl_priv *wl = ndev_to_wl(ndev);
 #if (WL_DBG_LEVEL > 0)
 	s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ?
@@ -3393,8 +3390,8 @@
 		WL_ERR("invalid type (%d)\n", iftype);
 		return err;
 	}
-	infra = htod32(infra);
-	ap = htod32(ap);
+	infra = cpu_to_le32(infra);
+	ap = cpu_to_le32(ap);
 	WL_DBG("%s ap (%d), infra (%d)\n", ndev->name, ap, infra);
 	err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
 	if (unlikely(err)) {
@@ -3656,26 +3653,28 @@
 	pkt_filterp = (struct wl_pkt_filter *)(buf + str_len + 1);
 
 	/* Parse packet filter id. */
-	pkt_filter.id = htod32(100);
+	pkt_filter.id = cpu_to_le32(100);
 
 	/* Parse filter polarity. */
-	pkt_filter.negate_match = htod32(0);
+	pkt_filter.negate_match = cpu_to_le32(0);
 
 	/* Parse filter type. */
-	pkt_filter.type = htod32(0);
+	pkt_filter.type = cpu_to_le32(0);
 
 	/* Parse pattern filter offset. */
-	pkt_filter.u.pattern.offset = htod32(0);
+	pkt_filter.u.pattern.offset = cpu_to_le32(0);
 
 	/* Parse pattern filter mask. */
-	mask_size = htod32(wl_pattern_atoh("0xff",
-					   (char *)pkt_filterp->u.pattern.
-					   mask_and_pattern));
+	mask_size = cpu_to_le32(wl_pattern_atoh("0xff",
+						(char *)pkt_filterp->u.pattern.
+						mask_and_pattern));
 
 	/* Parse pattern filter pattern. */
-	pattern_size = htod32(wl_pattern_atoh("0x00",
-					      (char *)&pkt_filterp->u.pattern.
-					      mask_and_pattern[mask_size]));
+	pattern_size = cpu_to_le32(wl_pattern_atoh("0x00",
+						   (char *)&pkt_filterp->u.
+						   pattern.
+						   mask_and_pattern
+						   [mask_size]));
 
 	if (mask_size != pattern_size) {
 		WL_ERR("Mask and pattern not the same size\n");
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_cfg80211.h	2011-05-19 00:06:34.000000000 -0400
@@ -20,7 +20,6 @@
 #include <linux/wireless.h>
 #include <linux/wireless.h>
 #include <net/cfg80211.h>
-#include <proto/ethernet.h>
 #include <wlioctl.h>
 
 struct wl_conf;
@@ -29,23 +28,6 @@
 struct wl_security;
 struct wl_ibss;
 
-#if defined(IL_BIGENDIAN)
-#include <bcmendian.h>
-#define htod32(i) (bcmswap32(i))
-#define htod16(i) (bcmswap16(i))
-#define dtoh32(i) (bcmswap32(i))
-#define dtoh16(i) (bcmswap16(i))
-#define htodchanspec(i) htod16(i)
-#define dtohchanspec(i) dtoh16(i)
-#else
-#define htod32(i) i
-#define htod16(i) i
-#define dtoh32(i) i
-#define dtoh16(i) i
-#define htodchanspec(i) i
-#define dtohchanspec(i) i
-#endif
-
 #define WL_DBG_NONE	0
 #define WL_DBG_DBG 	(1 << 2)
 #define WL_DBG_INFO	(1 << 1)
@@ -316,7 +298,7 @@
 						 cfg80211 layer */
 	struct wl_ie ie;	/* information element object for
 					 internal purpose */
-	struct ether_addr bssid;	/* bssid of currently engaged network */
+	u8 bssid[ETH_ALEN];	/* bssid of currently engaged network */
 	struct semaphore event_sync;	/* for synchronization of main event
 					 thread */
 	struct wl_profile *profile;	/* holding dongle profile */
@@ -366,7 +348,8 @@
 {
 	return bss = bss ?
 		(struct wl_bss_info *)((unsigned long)bss +
-				       dtoh32(bss->length)) : list->bss_info;
+				       le32_to_cpu(bss->length)) :
+		list->bss_info;
 }
 
 #define for_each_bss(list, bss, __i)	\
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.c	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.c	2011-05-19 00:06:34.000000000 -0400
@@ -18,12 +18,9 @@
 #include <linux/semaphore.h>
 #include <bcmdefs.h>
 #include <linux/netdevice.h>
-#include <osl.h>
 #include <wlioctl.h>
 
 #include <bcmutils.h>
-#include <bcmendian.h>
-#include <proto/ethernet.h>
 
 #include <linux/if_arp.h>
 #include <asm/uaccess.h>
@@ -31,11 +28,10 @@
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhdioctl.h>
-
+#include <linux/ieee80211.h>
 typedef const struct si_pub si_t;
 #include <wlioctl.h>
 
-#include <proto/ethernet.h>
 #include <dngl_stats.h>
 #include <dhd.h>
 
@@ -72,23 +68,6 @@
 
 #define MAX_WLIW_IOCTL_LEN 1024
 
-#if defined(IL_BIGENDIAN)
-#include <bcmendian.h>
-#define htod32(i) (bcmswap32(i))
-#define htod16(i) (bcmswap16(i))
-#define dtoh32(i) (bcmswap32(i))
-#define dtoh16(i) (bcmswap16(i))
-#define htodchanspec(i) htod16(i)
-#define dtohchanspec(i) dtoh16(i)
-#else
-#define htod32(i) i
-#define htod16(i) i
-#define dtoh32(i) i
-#define dtoh16(i) i
-#define htodchanspec(i) i
-#define dtohchanspec(i) i
-#endif
-
 #ifdef CONFIG_WIRELESS_EXT
 
 extern struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
@@ -137,6 +116,9 @@
 	int iscan_ex_param_size;
 } iscan_info_t;
 iscan_info_t *g_iscan;
+
+static const u8 ether_bcast[ETH_ALEN] = {255, 255, 255, 255, 255, 255};
+
 static void wl_iw_timerfunc(unsigned long data);
 static void wl_iw_set_event_mask(struct net_device *dev);
 static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, u16 action);
@@ -158,24 +140,24 @@
 
 static void swap_key_from_BE(wl_wsec_key_t *key)
 {
-	key->index = htod32(key->index);
-	key->len = htod32(key->len);
-	key->algo = htod32(key->algo);
-	key->flags = htod32(key->flags);
-	key->rxiv.hi = htod32(key->rxiv.hi);
-	key->rxiv.lo = htod16(key->rxiv.lo);
-	key->iv_initialized = htod32(key->iv_initialized);
+	key->index = cpu_to_le32(key->index);
+	key->len = cpu_to_le32(key->len);
+	key->algo = cpu_to_le32(key->algo);
+	key->flags = cpu_to_le32(key->flags);
+	key->rxiv.hi = cpu_to_le32(key->rxiv.hi);
+	key->rxiv.lo = cpu_to_le16(key->rxiv.lo);
+	key->iv_initialized = cpu_to_le32(key->iv_initialized);
 }
 
 static void swap_key_to_BE(wl_wsec_key_t *key)
 {
-	key->index = dtoh32(key->index);
-	key->len = dtoh32(key->len);
-	key->algo = dtoh32(key->algo);
-	key->flags = dtoh32(key->flags);
-	key->rxiv.hi = dtoh32(key->rxiv.hi);
-	key->rxiv.lo = dtoh16(key->rxiv.lo);
-	key->iv_initialized = dtoh32(key->iv_initialized);
+	key->index = le32_to_cpu(key->index);
+	key->len = le32_to_cpu(key->len);
+	key->algo = le32_to_cpu(key->algo);
+	key->flags = le32_to_cpu(key->flags);
+	key->rxiv.hi = le32_to_cpu(key->rxiv.hi);
+	key->rxiv.lo = le16_to_cpu(key->rxiv.lo);
+	key->iv_initialized = le32_to_cpu(key->iv_initialized);
 }
 
 static int dev_wlc_ioctl(struct net_device *dev, int cmd, void *arg, int len)
@@ -223,7 +205,7 @@
 	char buf[WLC_IOCTL_SMLEN];
 	uint len;
 
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
 	ASSERT(len);
 
@@ -288,7 +270,7 @@
 	    dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)ioctlbuf,
 			  MAX_WLIW_IOCTL_LEN);
 	if (!error)
-		bcopy(ioctlbuf, buf, buflen);
+		memcpy(buf, ioctlbuf, buflen);
 
 	return error;
 }
@@ -310,7 +292,7 @@
 	ASSERT(len);
 	error = dev_wlc_ioctl(dev, WLC_GET_VAR, (void *)&var, len);
 
-	*retval = dtoh32(var.val);
+	*retval = le32_to_cpu(var.val);
 
 	return error;
 }
@@ -340,7 +322,7 @@
 	if (error)
 		return error;
 
-	ssid.SSID_len = dtoh32(ssid.SSID_len);
+	ssid.SSID_len = le32_to_cpu(ssid.SSID_len);
 
 	if (!ssid.SSID_len)
 		return 0;
@@ -392,7 +374,7 @@
 
 		chan = wf_mhz2channel(fwrq->m, sf);
 	}
-	chan = htod32(chan);
+	chan = cpu_to_le32(chan);
 
 	error = dev_wlc_ioctl(dev, WLC_SET_CHANNEL, &chan, sizeof(chan));
 	if (error)
@@ -415,8 +397,8 @@
 	if (error)
 		return error;
 
-	fwrq->m = dtoh32(ci.hw_channel);
-	fwrq->e = dtoh32(0);
+	fwrq->m = le32_to_cpu(ci.hw_channel);
+	fwrq->e = le32_to_cpu(0);
 	return 0;
 }
 
@@ -441,8 +423,8 @@
 	default:
 		return -EINVAL;
 	}
-	infra = htod32(infra);
-	ap = htod32(ap);
+	infra = cpu_to_le32(infra);
+	ap = cpu_to_le32(ap);
 
 	error = dev_wlc_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(infra));
 	if (error)
@@ -471,8 +453,8 @@
 	if (error)
 		return error;
 
-	infra = dtoh32(infra);
-	ap = dtoh32(ap);
+	infra = le32_to_cpu(infra);
+	ap = le32_to_cpu(ap);
 	*uwrq = infra ? ap ? IW_MODE_MASTER : IW_MODE_INFRA : IW_MODE_ADHOC;
 
 	return 0;
@@ -488,7 +470,7 @@
 	wl_rateset_t rateset;
 	s8 *channels;
 	int error, i, k;
-	uint sf, ch;
+	uint ch;
 
 	int phytype;
 	int bw_cap = 0, sgi_tx = 0, nmode = 0;
@@ -517,23 +499,24 @@
 
 	range->min_nwid = range->max_nwid = 0;
 
-	list->count = htod32(MAXCHANNEL);
+	list->count = cpu_to_le32(MAXCHANNEL);
 	error = dev_wlc_ioctl(dev, WLC_GET_VALID_CHANNELS, channels,
 				(MAXCHANNEL + 1) * 4);
 	if (error) {
 		kfree(channels);
 		return error;
 	}
-	for (i = 0; i < dtoh32(list->count) && i < IW_MAX_FREQUENCIES; i++) {
-		range->freq[i].i = dtoh32(list->element[i]);
-
-		ch = dtoh32(list->element[i]);
-		if (ch <= CH_MAX_2G_CHANNEL)
-			sf = WF_CHAN_FACTOR_2_4_G;
-		else
-			sf = WF_CHAN_FACTOR_5_G;
+	for (i = 0; i < le32_to_cpu(list->count) && i < IW_MAX_FREQUENCIES;
+	     i++) {
+		range->freq[i].i = le32_to_cpu(list->element[i]);
 
-		range->freq[i].m = wf_channel2mhz(ch, sf);
+		ch = le32_to_cpu(list->element[i]);
+		if (ch <= CH_MAX_2G_CHANNEL) {
+			range->freq[i].m = ieee80211_dsss_chan_to_freq(ch);
+		} else {
+			range->freq[i].m = ieee80211_ofdm_chan_to_freq(
+						WF_CHAN_FACTOR_5_G/2, ch);
+		}
 		range->freq[i].e = 6;
 	}
 	range->num_frequency = range->num_channels = i;
@@ -555,7 +538,7 @@
 		kfree(channels);
 		return error;
 	}
-	rateset.count = dtoh32(rateset.count);
+	rateset.count = le32_to_cpu(rateset.count);
 	range->num_bitrates = rateset.count;
 	for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++)
 		range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000;
@@ -567,7 +550,7 @@
 		dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx);
 		dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci,
 			      sizeof(channel_info_t));
-		ci.hw_channel = dtoh32(ci.hw_channel);
+		ci.hw_channel = le32_to_cpu(ci.hw_channel);
 
 		if (bw_cap == 0 || (bw_cap == 2 && ci.hw_channel <= 14)) {
 			if (sgi_tx == 0)
@@ -593,7 +576,7 @@
 		kfree(channels);
 		return error;
 	}
-	i = dtoh32(i);
+	i = le32_to_cpu(i);
 	if (i == WLC_PHY_TYPE_A)
 		range->throughput = 24000000;
 	else
@@ -606,14 +589,14 @@
 
 	range->max_encoding_tokens = DOT11_MAX_DEFAULT_KEYS;
 	range->num_encoding_sizes = 4;
-	range->encoding_size[0] = WEP1_KEY_SIZE;
-	range->encoding_size[1] = WEP128_KEY_SIZE;
+	range->encoding_size[0] = WLAN_KEY_LEN_WEP40;
+	range->encoding_size[1] = WLAN_KEY_LEN_WEP104;
 #if WIRELESS_EXT > 17
-	range->encoding_size[2] = TKIP_KEY_SIZE;
+	range->encoding_size[2] = WLAN_KEY_LEN_TKIP;
 #else
 	range->encoding_size[2] = 0;
 #endif
-	range->encoding_size[3] = AES_KEY_SIZE;
+	range->encoding_size[3] = WLAN_KEY_LEN_AES_CMAC;
 
 	range->min_pmp = 0;
 	range->max_pmp = 0;
@@ -690,7 +673,7 @@
 
 	iw->spy_num = min_t(int, ARRAY_SIZE(iw->spy_addr), dwrq->length);
 	for (i = 0; i < iw->spy_num; i++)
-		memcpy(&iw->spy_addr[i], addr[i].sa_data, ETH_ALEN);
+		memcpy(iw->spy_addr[i], addr[i].sa_data, ETH_ALEN);
 	memset(iw->spy_qual, 0, sizeof(iw->spy_qual));
 
 	return 0;
@@ -712,7 +695,7 @@
 
 	dwrq->length = iw->spy_num;
 	for (i = 0; i < iw->spy_num; i++) {
-		memcpy(addr[i].sa_data, &iw->spy_addr[i], ETH_ALEN);
+		memcpy(addr[i].sa_data, iw->spy_addr[i], ETH_ALEN);
 		addr[i].sa_family = AF_UNIX;
 		memcpy(&qual[i], &iw->spy_qual[i], sizeof(struct iw_quality));
 		iw->spy_qual[i].updated = 0;
@@ -745,10 +728,10 @@
 		join_params->params.chanspec_list[0] &= WL_CHANSPEC_CHAN_MASK;
 		join_params->params.chanspec_list[0] |= chanspec;
 		join_params->params.chanspec_list[0] =
-		    htodchanspec(join_params->params.chanspec_list[0]);
+		    cpu_to_le16(join_params->params.chanspec_list[0]);
 
 		join_params->params.chanspec_num =
-		    htod32(join_params->params.chanspec_num);
+		    cpu_to_le32(join_params->params.chanspec_num);
 
 		WL_TRACE("%s  join_params->params.chanspec_list[0]= %X\n",
 			 __func__, join_params->params.chanspec_list[0]);
@@ -784,7 +767,7 @@
 	join_params_size = sizeof(join_params.ssid);
 
 	memcpy(join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
+	join_params.ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
 	memcpy(&join_params.params.bssid, awrq->sa_data, ETH_ALEN);
 
 	WL_TRACE("%s  target_channel=%d\n",
@@ -840,15 +823,15 @@
 	}
 
 	scbval.val = mlme->reason_code;
-	bcopy(&mlme->addr.sa_data, &scbval.ea, ETH_ALEN);
+	memcpy(&scbval.ea, &mlme->addr.sa_data, ETH_ALEN);
 
 	if (mlme->cmd == IW_MLME_DISASSOC) {
-		scbval.val = htod32(scbval.val);
+		scbval.val = cpu_to_le32(scbval.val);
 		error =
 		    dev_wlc_ioctl(dev, WLC_DISASSOC, &scbval,
 				  sizeof(scb_val_t));
 	} else if (mlme->cmd == IW_MLME_DEAUTH) {
-		scbval.val = htod32(scbval.val);
+		scbval.val = cpu_to_le32(scbval.val);
 		error =
 		    dev_wlc_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON,
 				  &scbval, sizeof(scb_val_t));
@@ -879,20 +862,19 @@
 	if (!extra)
 		return -EINVAL;
 
-	list = kmalloc(buflen, GFP_KERNEL);
+	list = kzalloc(buflen, GFP_KERNEL);
 	if (!list)
 		return -ENOMEM;
-	memset(list, 0, buflen);
-	list->buflen = htod32(buflen);
+	list->buflen = cpu_to_le32(buflen);
 	error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, buflen);
 	if (error) {
 		WL_ERROR("%d: Scan results error %d\n", __LINE__, error);
 		kfree(list);
 		return error;
 	}
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
+	list->buflen = le32_to_cpu(list->buflen);
+	list->version = le32_to_cpu(list->version);
+	list->count = le32_to_cpu(list->count);
 	if (list->version != WL_BSS_INFO_VERSION) {
 		WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
 			 __func__, list->version);
@@ -903,18 +885,18 @@
 	for (i = 0, dwrq->length = 0;
 	     i < list->count && dwrq->length < IW_MAX_AP; i++) {
 		bi = bi ? (wl_bss_info_t *) ((unsigned long)bi +
-					     dtoh32(bi->length)) : list->
+					     le32_to_cpu(bi->length)) : list->
 		    bss_info;
-		ASSERT(((unsigned long)bi + dtoh32(bi->length)) <=
+		ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
 		       ((unsigned long)list + buflen));
 
-		if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+		if (!(le16_to_cpu(bi->capability) & WLAN_CAPABILITY_ESS))
 			continue;
 
 		memcpy(addr[dwrq->length].sa_data, &bi->BSSID, ETH_ALEN);
 		addr[dwrq->length].sa_family = ARPHRD_ETHER;
-		qual[dwrq->length].qual = rssi_to_qual(dtoh16(bi->RSSI));
-		qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+		qual[dwrq->length].qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
+		qual[dwrq->length].level = 0x100 + le16_to_cpu(bi->RSSI);
 		qual[dwrq->length].noise = 0x100 + bi->phy_noise;
 
 #if WIRELESS_EXT > 18
@@ -975,20 +957,22 @@
 		for (i = 0, dwrq->length = 0;
 		     i < list->count && dwrq->length < IW_MAX_AP; i++) {
 			bi = bi ? (wl_bss_info_t *) ((unsigned long)bi +
-						     dtoh32(bi->length)) :
+						     le32_to_cpu(bi->length)) :
 			    list->bss_info;
-			ASSERT(((unsigned long)bi + dtoh32(bi->length)) <=
+			ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
 			       ((unsigned long)list + WLC_IW_ISCAN_MAXLEN));
 
-			if (!(dtoh16(bi->capability) & DOT11_CAP_ESS))
+			if (!(le16_to_cpu(bi->capability) &
+			      WLAN_CAPABILITY_ESS))
 				continue;
 
 			memcpy(addr[dwrq->length].sa_data, &bi->BSSID,
 			       ETH_ALEN);
 			addr[dwrq->length].sa_family = ARPHRD_ETHER;
 			qual[dwrq->length].qual =
-			    rssi_to_qual(dtoh16(bi->RSSI));
-			qual[dwrq->length].level = 0x100 + dtoh16(bi->RSSI);
+			    rssi_to_qual(le16_to_cpu(bi->RSSI));
+			qual[dwrq->length].level = 0x100 +
+							le16_to_cpu(bi->RSSI);
 			qual[dwrq->length].noise = 0x100 + bi->phy_noise;
 
 #if WIRELESS_EXT > 18
@@ -1015,7 +999,7 @@
 {
 	int err = 0;
 
-	memcpy(&params->bssid, &ether_bcast, ETH_ALEN);
+	memcpy(params->bssid, ether_bcast, ETH_ALEN);
 	params->bss_type = DOT11_BSSTYPE_ANY;
 	params->scan_type = 0;
 	params->nprobes = -1;
@@ -1024,10 +1008,10 @@
 	params->home_time = -1;
 	params->channel_num = 0;
 
-	params->nprobes = htod32(params->nprobes);
-	params->active_time = htod32(params->active_time);
-	params->passive_time = htod32(params->passive_time);
-	params->home_time = htod32(params->home_time);
+	params->nprobes = cpu_to_le32(params->nprobes);
+	params->active_time = cpu_to_le32(params->active_time);
+	params->passive_time = cpu_to_le32(params->passive_time);
+	params->home_time = cpu_to_le32(params->home_time);
 	if (ssid && ssid->SSID_len)
 		memcpy(&params->ssid, ssid, sizeof(wlc_ssid_t));
 
@@ -1038,9 +1022,9 @@
 {
 	int err = 0;
 
-	iscan->iscan_ex_params_p->version = htod32(ISCAN_REQ_VERSION);
-	iscan->iscan_ex_params_p->action = htod16(action);
-	iscan->iscan_ex_params_p->scan_duration = htod16(0);
+	iscan->iscan_ex_params_p->version = cpu_to_le32(ISCAN_REQ_VERSION);
+	iscan->iscan_ex_params_p->action = cpu_to_le16(action);
+	iscan->iscan_ex_params_p->scan_duration = cpu_to_le16(0);
 
 	WL_SCAN("%s : nprobes=%d\n",
 		__func__, iscan->iscan_ex_params_p->params.nprobes);
@@ -1077,7 +1061,7 @@
 	char iovbuf[WL_EVENTING_MASK_LEN + 12];
 
 	dev_iw_iovar_getbuf(dev, "event_msgs", "", 0, iovbuf, sizeof(iovbuf));
-	bcopy(iovbuf, eventmask, WL_EVENTING_MASK_LEN);
+	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
 	setbit(eventmask, WLC_E_SCAN_COMPLETE);
 	dev_iw_iovar_setbuf(dev, "event_msgs", eventmask, WL_EVENTING_MASK_LEN,
 			    iovbuf, sizeof(iovbuf));
@@ -1124,19 +1108,19 @@
 	results->count = 0;
 
 	memset(&list, 0, sizeof(list));
-	list.results.buflen = htod32(WLC_IW_ISCAN_MAXLEN);
+	list.results.buflen = cpu_to_le32(WLC_IW_ISCAN_MAXLEN);
 	res = dev_iw_iovar_getbuf(iscan->dev,
 				  "iscanresults",
 				  &list,
 				  WL_ISCAN_RESULTS_FIXED_SIZE,
 				  buf->iscan_buf, WLC_IW_ISCAN_MAXLEN);
 	if (res == 0) {
-		results->buflen = dtoh32(results->buflen);
-		results->version = dtoh32(results->version);
-		results->count = dtoh32(results->count);
+		results->buflen = le32_to_cpu(results->buflen);
+		results->version = le32_to_cpu(results->version);
+		results->count = le32_to_cpu(results->count);
 		WL_TRACE("results->count = %d\n", results->count);
 		WL_TRACE("results->buflen = %d\n", results->buflen);
-		status = dtoh32(list_buf->status);
+		status = le32_to_cpu(list_buf->status);
 	} else {
 		WL_ERROR("%s returns error %d\n", __func__, res);
 		status = WL_SCAN_RESULTS_NO_MEM;
@@ -1283,7 +1267,7 @@
 				memcpy(g_specific_ssid.SSID, req->essid,
 				       g_specific_ssid.SSID_len);
 				g_specific_ssid.SSID_len =
-				    htod32(g_specific_ssid.SSID_len);
+				    cpu_to_le32(g_specific_ssid.SSID_len);
 				g_scan_specified_ssid = 1;
 				WL_TRACE("### Specific scan ssid=%s len=%d\n",
 					 g_specific_ssid.SSID,
@@ -1367,7 +1351,7 @@
 	if (g_scan_specified_ssid) {
 		WL_TRACE("%s Specific SCAN already running ignoring BC scan\n",
 			 __func__);
-		return EBUSY;
+		return -EBUSY;
 	}
 
 	memset(&ssid, 0, sizeof(ssid));
@@ -1379,7 +1363,7 @@
 			ssid.SSID_len = min_t(size_t, sizeof(ssid.SSID),
 						req->essid_len);
 			memcpy(ssid.SSID, req->essid, ssid.SSID_len);
-			ssid.SSID_len = htod32(ssid.SSID_len);
+			ssid.SSID_len = cpu_to_le32(ssid.SSID_len);
 		} else {
 			g_scan_specified_ssid = 0;
 
@@ -1505,7 +1489,7 @@
 		}
 
 		bi = bi ? (wl_bss_info_t *)((unsigned long)bi +
-					     dtoh32(bi->length)) : list->
+					     le32_to_cpu(bi->length)) : list->
 		    bss_info;
 
 		WL_TRACE("%s : %s\n", __func__, bi->SSID);
@@ -1516,14 +1500,15 @@
 		event =
 		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 					 IW_EV_ADDR_LEN);
-		iwe.u.data.length = dtoh32(bi->SSID_len);
+		iwe.u.data.length = le32_to_cpu(bi->SSID_len);
 		iwe.cmd = SIOCGIWESSID;
 		iwe.u.data.flags = 1;
 		event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, bi->SSID);
 
-		if (dtoh16(bi->capability) & (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+		if (le16_to_cpu(bi->capability) & (WLAN_CAPABILITY_ESS |
+		    WLAN_CAPABILITY_IBSS)) {
 			iwe.cmd = SIOCGIWMODE;
-			if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+			if (le16_to_cpu(bi->capability) & WLAN_CAPABILITY_ESS)
 				iwe.u.mode = IW_MODE_INFRA;
 			else
 				iwe.u.mode = IW_MODE_ADHOC;
@@ -1533,19 +1518,23 @@
 		}
 
 		iwe.cmd = SIOCGIWFREQ;
-		iwe.u.freq.m = wf_channel2mhz(CHSPEC_CHANNEL(bi->chanspec),
-					      CHSPEC_CHANNEL(bi->chanspec) <=
-					      CH_MAX_2G_CHANNEL ?
-					      WF_CHAN_FACTOR_2_4_G :
-					      WF_CHAN_FACTOR_5_G);
+
+		if (CHSPEC_CHANNEL(bi->chanspec) <= CH_MAX_2G_CHANNEL)
+			iwe.u.freq.m = ieee80211_dsss_chan_to_freq(
+						CHSPEC_CHANNEL(bi->chanspec));
+		else
+			iwe.u.freq.m = ieee80211_ofdm_chan_to_freq(
+						WF_CHAN_FACTOR_5_G/2,
+						CHSPEC_CHANNEL(bi->chanspec));
+
 		iwe.u.freq.e = 6;
 		event =
 		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 					 IW_EV_FREQ_LEN);
 
 		iwe.cmd = IWEVQUAL;
-		iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
-		iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+		iwe.u.qual.qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
+		iwe.u.qual.level = 0x100 + le16_to_cpu(bi->RSSI);
 		iwe.u.qual.noise = 0x100 + bi->phy_noise;
 		event =
 		    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
@@ -1554,7 +1543,7 @@
 		wl_iw_handle_scanresults_ies(&event, end, info, bi);
 
 		iwe.cmd = SIOCGIWENCODE;
-		if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+		if (le16_to_cpu(bi->capability) & WLAN_CAPABILITY_PRIVACY)
 			iwe.u.data.flags = IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 		else
 			iwe.u.data.flags = IW_ENCODE_DISABLED;
@@ -1621,7 +1610,7 @@
 	error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci));
 	if (error)
 		return error;
-	ci.scan_channel = dtoh32(ci.scan_channel);
+	ci.scan_channel = le32_to_cpu(ci.scan_channel);
 	if (ci.scan_channel)
 		return -EAGAIN;
 
@@ -1636,7 +1625,7 @@
 	}
 
 	memset(list, 0, len);
-	list->buflen = htod32(len);
+	list->buflen = cpu_to_le32(len);
 	error = dev_wlc_ioctl(dev, WLC_SCAN_RESULTS, list, len);
 	if (error) {
 		WL_ERROR("%s: %s : Scan_results ERROR %d\n",
@@ -1648,9 +1637,9 @@
 		}
 		return 0;
 	}
-	list->buflen = dtoh32(list->buflen);
-	list->version = dtoh32(list->version);
-	list->count = dtoh32(list->count);
+	list->buflen = le32_to_cpu(list->buflen);
+	list->version = le32_to_cpu(list->version);
+	list->count = le32_to_cpu(list->count);
 
 	if (list->version != WL_BSS_INFO_VERSION) {
 		WL_ERROR("%s : list->version %d != WL_BSS_INFO_VERSION\n",
@@ -1770,9 +1759,9 @@
 		for (ii = 0; ii < list->count && apcnt < IW_MAX_AP;
 		     apcnt++, ii++) {
 			bi = bi ? (wl_bss_info_t *)((unsigned long)bi +
-						     dtoh32(bi->length)) :
+						     le32_to_cpu(bi->length)) :
 			    list->bss_info;
-			ASSERT(((unsigned long)bi + dtoh32(bi->length)) <=
+			ASSERT(((unsigned long)bi + le32_to_cpu(bi->length)) <=
 			       ((unsigned long)list + WLC_IW_ISCAN_MAXLEN));
 
 			if (event + ETH_ALEN + bi->SSID_len +
@@ -1787,17 +1776,18 @@
 			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 						 IW_EV_ADDR_LEN);
 
-			iwe.u.data.length = dtoh32(bi->SSID_len);
+			iwe.u.data.length = le32_to_cpu(bi->SSID_len);
 			iwe.cmd = SIOCGIWESSID;
 			iwe.u.data.flags = 1;
 			event =
 			    IWE_STREAM_ADD_POINT(info, event, end, &iwe,
 						 bi->SSID);
 
-			if (dtoh16(bi->capability) &
-			    (DOT11_CAP_ESS | DOT11_CAP_IBSS)) {
+			if (le16_to_cpu(bi->capability) &
+			    (WLAN_CAPABILITY_ESS | WLAN_CAPABILITY_IBSS)) {
 				iwe.cmd = SIOCGIWMODE;
-				if (dtoh16(bi->capability) & DOT11_CAP_ESS)
+				if (le16_to_cpu(bi->capability) &
+				    WLAN_CAPABILITY_ESS)
 					iwe.u.mode = IW_MODE_INFRA;
 				else
 					iwe.u.mode = IW_MODE_ADHOC;
@@ -1810,20 +1800,23 @@
 			channel =
 			    (bi->ctl_ch ==
 			     0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
-			iwe.u.freq.m =
-			    wf_channel2mhz(channel,
-					   channel <=
-					   CH_MAX_2G_CHANNEL ?
-					   WF_CHAN_FACTOR_2_4_G :
-					   WF_CHAN_FACTOR_5_G);
+
+			if (channel <= CH_MAX_2G_CHANNEL)
+				iwe.u.freq.m =
+					ieee80211_dsss_chan_to_freq(channel);
+			else
+				iwe.u.freq.m = ieee80211_ofdm_chan_to_freq(
+							WF_CHAN_FACTOR_5_G/2,
+							channel);
+
 			iwe.u.freq.e = 6;
 			event =
 			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
 						 IW_EV_FREQ_LEN);
 
 			iwe.cmd = IWEVQUAL;
-			iwe.u.qual.qual = rssi_to_qual(dtoh16(bi->RSSI));
-			iwe.u.qual.level = 0x100 + dtoh16(bi->RSSI);
+			iwe.u.qual.qual = rssi_to_qual(le16_to_cpu(bi->RSSI));
+			iwe.u.qual.level = 0x100 + le16_to_cpu(bi->RSSI);
 			iwe.u.qual.noise = 0x100 + bi->phy_noise;
 			event =
 			    IWE_STREAM_ADD_EVENT(info, event, end, &iwe,
@@ -1832,7 +1825,8 @@
 			wl_iw_handle_scanresults_ies(&event, end, info, bi);
 
 			iwe.cmd = SIOCGIWENCODE;
-			if (dtoh16(bi->capability) & DOT11_CAP_PRIVACY)
+			if (le16_to_cpu(bi->capability) &
+			    WLAN_CAPABILITY_PRIVACY)
 				iwe.u.data.flags =
 				    IW_ENCODE_ENABLED | IW_ENCODE_NOKEY;
 			else
@@ -1912,14 +1906,14 @@
 	} else {
 		g_ssid.SSID_len = 0;
 	}
-	g_ssid.SSID_len = htod32(g_ssid.SSID_len);
+	g_ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
 
 	memset(&join_params, 0, sizeof(join_params));
 	join_params_size = sizeof(join_params.ssid);
 
 	memcpy(&join_params.ssid.SSID, g_ssid.SSID, g_ssid.SSID_len);
-	join_params.ssid.SSID_len = htod32(g_ssid.SSID_len);
-	memcpy(&join_params.params.bssid, &ether_bcast, ETH_ALEN);
+	join_params.ssid.SSID_len = cpu_to_le32(g_ssid.SSID_len);
+	memcpy(join_params.params.bssid, ether_bcast, ETH_ALEN);
 
 	wl_iw_ch_to_chanspec(g_wl_iw_params.target_channel, &join_params,
 			     &join_params_size);
@@ -1955,7 +1949,7 @@
 		return error;
 	}
 
-	ssid.SSID_len = dtoh32(ssid.SSID_len);
+	ssid.SSID_len = le32_to_cpu(ssid.SSID_len);
 
 	memcpy(extra, ssid.SSID, ssid.SSID_len);
 
@@ -2017,7 +2011,7 @@
 	if (error)
 		return error;
 
-	rateset.count = dtoh32(rateset.count);
+	rateset.count = le32_to_cpu(rateset.count);
 
 	if (vwrq->value < 0)
 		rate = rateset.rates[rateset.count - 1] & 0x7f;
@@ -2042,7 +2036,7 @@
 		for (i = 0; i < rateset.count; i++)
 			if ((rateset.rates[i] & 0x7f) > rate)
 				break;
-		rateset.count = htod32(i);
+		rateset.count = cpu_to_le32(i);
 
 		error = dev_wlc_ioctl(dev, WLC_SET_RATESET, &rateset,
 					sizeof(rateset));
@@ -2064,7 +2058,7 @@
 	error = dev_wlc_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
 	if (error)
 		return error;
-	rate = dtoh32(rate);
+	rate = le32_to_cpu(rate);
 	vwrq->value = rate * 500000;
 
 	return 0;
@@ -2164,7 +2158,7 @@
 	disable = vwrq->disabled ? WL_RADIO_SW_DISABLE : 0;
 	disable += WL_RADIO_SW_DISABLE << 16;
 
-	disable = htod32(disable);
+	disable = cpu_to_le32(disable);
 	error = dev_wlc_ioctl(dev, WLC_SET_RADIO, &disable, sizeof(disable));
 	if (error)
 		return error;
@@ -2206,7 +2200,7 @@
 	if (error)
 		return error;
 
-	disable = dtoh32(disable);
+	disable = le32_to_cpu(disable);
 	result = (u8) (txpwrdbm & ~WL_TXPWR_OVERRIDE);
 	vwrq->value = (s32) bcm_qdbm_to_mw(result);
 	vwrq->fixed = 0;
@@ -2241,7 +2235,7 @@
 		if ((vwrq->flags & IW_RETRY_MAX)
 		    || !(vwrq->flags & IW_RETRY_MIN)) {
 #endif
-			lrl = htod32(vwrq->value);
+			lrl = cpu_to_le32(vwrq->value);
 			error = dev_wlc_ioctl(dev, WLC_SET_LRL, &lrl,
 						sizeof(lrl));
 			if (error)
@@ -2256,7 +2250,7 @@
 		if ((vwrq->flags & IW_RETRY_MIN)
 		    || !(vwrq->flags & IW_RETRY_MAX)) {
 #endif
-			srl = htod32(vwrq->value);
+			srl = cpu_to_le32(vwrq->value);
 			error = dev_wlc_ioctl(dev, WLC_SET_SRL, &srl,
 						sizeof(srl));
 			if (error)
@@ -2288,8 +2282,8 @@
 	if (error)
 		return error;
 
-	lrl = dtoh32(lrl);
-	srl = dtoh32(srl);
+	lrl = le32_to_cpu(lrl);
+	srl = le32_to_cpu(srl);
 
 	if (vwrq->flags & IW_RETRY_MAX) {
 		vwrq->flags = IW_RETRY_LIMIT | IW_RETRY_MAX;
@@ -2320,12 +2314,12 @@
 	if ((dwrq->flags & IW_ENCODE_INDEX) == 0) {
 		for (key.index = 0; key.index < DOT11_MAX_DEFAULT_KEYS;
 		     key.index++) {
-			val = htod32(key.index);
+			val = cpu_to_le32(key.index);
 			error = dev_wlc_ioctl(dev, WLC_GET_KEY_PRIMARY, &val,
 						sizeof(val));
 			if (error)
 				return error;
-			val = dtoh32(val);
+			val = le32_to_cpu(val);
 			if (val)
 				break;
 		}
@@ -2338,7 +2332,7 @@
 	}
 
 	if (!extra || !dwrq->length || (dwrq->flags & IW_ENCODE_NOKEY)) {
-		val = htod32(key.index);
+		val = cpu_to_le32(key.index);
 		error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY, &val,
 					sizeof(val));
 		if (error)
@@ -2353,16 +2347,16 @@
 
 		key.flags = WL_PRIMARY_KEY;
 		switch (key.len) {
-		case WEP1_KEY_SIZE:
+		case WLAN_KEY_LEN_WEP40:
 			key.algo = CRYPTO_ALGO_WEP1;
 			break;
-		case WEP128_KEY_SIZE:
+		case WLAN_KEY_LEN_WEP104:
 			key.algo = CRYPTO_ALGO_WEP128;
 			break;
-		case TKIP_KEY_SIZE:
+		case WLAN_KEY_LEN_TKIP:
 			key.algo = CRYPTO_ALGO_TKIP;
 			break;
-		case AES_KEY_SIZE:
+		case WLAN_KEY_LEN_AES_CMAC:
 			key.algo = CRYPTO_ALGO_AES_CCM;
 			break;
 		default:
@@ -2389,7 +2383,7 @@
 		return error;
 
 	val = (dwrq->flags & IW_ENCODE_RESTRICTED) ? 1 : 0;
-	val = htod32(val);
+	val = cpu_to_le32(val);
 	error = dev_wlc_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
 	if (error)
 		return error;
@@ -2417,7 +2411,7 @@
 						sizeof(val));
 			if (error)
 				return error;
-			val = dtoh32(val);
+			val = le32_to_cpu(val);
 			if (val)
 				break;
 		}
@@ -2437,9 +2431,9 @@
 
 	swap_key_to_BE(&key);
 
-	wsec = dtoh32(wsec);
-	auth = dtoh32(auth);
-	dwrq->length = min_t(u16, DOT11_MAX_KEY_SIZE, key.len);
+	wsec = le32_to_cpu(wsec);
+	auth = le32_to_cpu(auth);
+	dwrq->length = min_t(u16, WLAN_MAX_KEY_LEN, key.len);
 
 	dwrq->flags = key.index + 1;
 	if (!(wsec & (WEP_ENABLED | TKIP_ENABLED | AES_ENABLED)))
@@ -2465,7 +2459,7 @@
 
 	pm = vwrq->disabled ? PM_OFF : PM_MAX;
 
-	pm = htod32(pm);
+	pm = cpu_to_le32(pm);
 	error = dev_wlc_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
 	if (error)
 		return error;
@@ -2486,7 +2480,7 @@
 	if (error)
 		return error;
 
-	pm = dtoh32(pm);
+	pm = le32_to_cpu(pm);
 	vwrq->disabled = pm ? 0 : 1;
 	vwrq->flags = IW_POWER_ALL_R;
 
@@ -2545,14 +2539,13 @@
 	key.len = iwe->key_len;
 
 	if (!is_multicast_ether_addr(iwe->addr.sa_data))
-		bcopy((void *)&iwe->addr.sa_data, (char *)&key.ea,
-		      ETH_ALEN);
+		memcpy(&key.ea, &iwe->addr.sa_data, ETH_ALEN);
 
 	if (key.len == 0) {
 		if (iwe->ext_flags & IW_ENCODE_EXT_SET_TX_KEY) {
 			WL_WSEC("Changing the the primary Key to %d\n",
 				key.index);
-			key.index = htod32(key.index);
+			key.index = cpu_to_le32(key.index);
 			error = dev_wlc_ioctl(dev, WLC_SET_KEY_PRIMARY,
 					      &key.index, sizeof(key.index));
 			if (error)
@@ -2571,13 +2564,13 @@
 			key.flags = WL_PRIMARY_KEY;
 		}
 
-		bcopy((void *)iwe->key, key.data, iwe->key_len);
+		memcpy(key.data, iwe->key, iwe->key_len);
 
 		if (iwe->alg == IW_ENCODE_ALG_TKIP) {
 			u8 keybuf[8];
-			bcopy(&key.data[24], keybuf, sizeof(keybuf));
-			bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
-			bcopy(keybuf, &key.data[16], sizeof(keybuf));
+			memcpy(keybuf, &key.data[24], sizeof(keybuf));
+			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
+			memcpy(&key.data[16], keybuf, sizeof(keybuf));
 		}
 
 		if (iwe->ext_flags & IW_ENCODE_EXT_RX_SEQ_VALID) {
@@ -2594,7 +2587,7 @@
 			key.algo = CRYPTO_ALGO_OFF;
 			break;
 		case IW_ENCODE_ALG_WEP:
-			if (iwe->key_len == WEP1_KEY_SIZE)
+			if (iwe->key_len == WLAN_KEY_LEN_WEP40)
 				key.algo = CRYPTO_ALGO_WEP1;
 			else
 				key.algo = CRYPTO_ALGO_WEP128;
@@ -2651,14 +2644,16 @@
 			uint j;
 			pmkidptr = &pmkid;
 
-			bcopy(&iwpmksa->bssid.sa_data[0],
-			      &pmkidptr->pmkid[0].BSSID, ETH_ALEN);
-			bcopy(&iwpmksa->pmkid[0], &pmkidptr->pmkid[0].PMKID,
-			      WPA2_PMKID_LEN);
+			memcpy(&pmkidptr->pmkid[0].BSSID,
+			       &iwpmksa->bssid.sa_data[0],
+			       ETH_ALEN);
+			memcpy(&pmkidptr->pmkid[0].PMKID,
+			       &iwpmksa->pmkid[0],
+			       WLAN_PMKID_LEN);
 
-			WL_WSEC("wl_iw_set_pmksa:IW_PMKSA_REMOVE:PMKID: %pM = ",
-				&pmkidptr->pmkid[0].BSSID);
-			for (j = 0; j < WPA2_PMKID_LEN; j++)
+			WL_WSEC("wl_iw_set_pmksa:IW_PMKSA_REMOVE:PMKID: "
+				"%pM = ", &pmkidptr->pmkid[0].BSSID);
+			for (j = 0; j < WLAN_PMKID_LEN; j++)
 				WL_WSEC("%02x ", pmkidptr->pmkid[0].PMKID[j]);
 			WL_WSEC("\n");
 		}
@@ -2673,12 +2668,12 @@
 		    && (i < pmkid_list.pmkids.npmkid)) {
 			memset(&pmkid_list.pmkids.pmkid[i], 0, sizeof(pmkid_t));
 			for (; i < (pmkid_list.pmkids.npmkid - 1); i++) {
-				bcopy(&pmkid_list.pmkids.pmkid[i + 1].BSSID,
-				      &pmkid_list.pmkids.pmkid[i].BSSID,
-				      ETH_ALEN);
-				bcopy(&pmkid_list.pmkids.pmkid[i + 1].PMKID,
-				      &pmkid_list.pmkids.pmkid[i].PMKID,
-				      WPA2_PMKID_LEN);
+				memcpy(&pmkid_list.pmkids.pmkid[i].BSSID,
+				       &pmkid_list.pmkids.pmkid[i + 1].BSSID,
+				       ETH_ALEN);
+				memcpy(&pmkid_list.pmkids.pmkid[i].PMKID,
+				       &pmkid_list.pmkids.pmkid[i + 1].PMKID,
+				       WLAN_PMKID_LEN);
 			}
 			pmkid_list.pmkids.npmkid--;
 		} else
@@ -2692,12 +2687,12 @@
 			     &pmkid_list.pmkids.pmkid[i].BSSID, ETH_ALEN))
 				break;
 		if (i < MAXPMKID) {
-			bcopy(&iwpmksa->bssid.sa_data[0],
-			      &pmkid_list.pmkids.pmkid[i].BSSID,
-			      ETH_ALEN);
-			bcopy(&iwpmksa->pmkid[0],
-			      &pmkid_list.pmkids.pmkid[i].PMKID,
-			      WPA2_PMKID_LEN);
+			memcpy(&pmkid_list.pmkids.pmkid[i].BSSID,
+			       &iwpmksa->bssid.sa_data[0],
+			       ETH_ALEN);
+			memcpy(&pmkid_list.pmkids.pmkid[i].PMKID,
+			       &iwpmksa->pmkid[0],
+			       WLAN_PMKID_LEN);
 			if (i == pmkid_list.pmkids.npmkid)
 				pmkid_list.pmkids.npmkid++;
 		} else
@@ -2708,7 +2703,7 @@
 			k = pmkid_list.pmkids.npmkid;
 			WL_WSEC("wl_iw_set_pmksa,IW_PMKSA_ADD - PMKID: %pM = ",
 				&pmkid_list.pmkids.pmkid[k].BSSID);
-			for (j = 0; j < WPA2_PMKID_LEN; j++)
+			for (j = 0; j < WLAN_PMKID_LEN; j++)
 				WL_WSEC("%02x ",
 					pmkid_list.pmkids.pmkid[k].PMKID[j]);
 			WL_WSEC("\n");
@@ -2720,7 +2715,7 @@
 		uint j;
 		WL_WSEC("PMKID[%d]: %pM = ",
 			i, &pmkid_list.pmkids.pmkid[i].BSSID);
-		for (j = 0; j < WPA2_PMKID_LEN; j++)
+		for (j = 0; j < WLAN_PMKID_LEN; j++)
 			WL_WSEC("%02x ", pmkid_list.pmkids.pmkid[i].PMKID[j]);
 		WL_WSEC("\n");
 	}
@@ -3342,9 +3337,9 @@
 static bool
 wl_iw_check_conn_fail(wl_event_msg_t *e, char *stringBuf, uint buflen)
 {
-	u32 event = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
-	u32 reason = ntoh32(e->reason);
+	u32 event = be32_to_cpu(e->event_type);
+	u32 status = be32_to_cpu(e->status);
+	u32 reason = be32_to_cpu(e->reason);
 
 	if (wl_iw_conn_status_str(event, status, reason, stringBuf, buflen)) {
 		return true;
@@ -3363,10 +3358,10 @@
 	union iwreq_data wrqu;
 	char extra[IW_CUSTOM_MAX + 1];
 	int cmd = 0;
-	u32 event_type = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
-	u32 datalen = ntoh32(e->datalen);
-	u32 status = ntoh32(e->status);
+	u32 event_type = be32_to_cpu(e->event_type);
+	u16 flags = be16_to_cpu(e->flags);
+	u32 datalen = be32_to_cpu(e->datalen);
+	u32 status = be32_to_cpu(e->status);
 	wl_iw_t *iw;
 	u32 toto;
 	memset(&wrqu, 0, sizeof(wrqu));
@@ -3409,8 +3404,6 @@
 		if (!(flags & WLC_EVENT_MSG_LINK)) {
 			memset(wrqu.addr.sa_data, 0, ETH_ALEN);
 			memset(&extra, 0, ETH_ALEN);
-			WAKE_LOCK_TIMEOUT(iw->pub, WAKE_LOCK_LINK_DOWN_TMOUT,
-					  20 * HZ);
 		} else {
 			memcpy(wrqu.addr.sa_data, &e->addr, ETH_ALEN);
 			WL_TRACE("Link UP\n");
@@ -3436,10 +3429,10 @@
 			wrqu.data.length = sizeof(status) + 1;
 			extra[0] = WLC_E_ACTION_FRAME_COMPLETE;
 			memcpy(&extra[1], &status, sizeof(status));
-			printf("wl_iw_event status %d PacketId %d\n", status,
-			       toto);
-			printf("WLC_E_ACTION_FRAME_COMPLETE len %d\n",
-			       wrqu.data.length);
+			WL_TRACE("wl_iw_event status %d PacketId %d\n", status,
+				 toto);
+			WL_TRACE("WLC_E_ACTION_FRAME_COMPLETE len %d\n",
+				 wrqu.data.length);
 		}
 		break;
 #endif				/* WIRELESS_EXT > 14 */
@@ -3471,9 +3464,8 @@
 
 				cmd = IWEVPMKIDCAND;
 				pmkcandlist = data;
-				count =
-				    ntoh32_ua((u8 *) &
-					      pmkcandlist->npmkid_cand);
+				count = get_unaligned_be32(&pmkcandlist->
+							   npmkid_cand);
 				ASSERT(count >= 0);
 				wrqu.data.length = sizeof(struct iw_pmkid_cand);
 				pmkidcand = pmkcandlist->pmkid_cand;
@@ -3483,9 +3475,9 @@
 					if (pmkidcand->preauth)
 						iwpmkidcand->flags |=
 						    IW_PMKID_CAND_PREAUTH;
-					bcopy(&pmkidcand->BSSID,
-					      &iwpmkidcand->bssid.sa_data,
-					      ETH_ALEN);
+					memcpy(&iwpmkidcand->bssid.sa_data,
+					       &pmkidcand->BSSID,
+					       ETH_ALEN);
 #ifndef SANDGATE2G
 					wireless_send_event(dev, cmd, &wrqu,
 							    extra);
@@ -3523,8 +3515,6 @@
 			WL_ERROR("%s Event WLC_E_PFN_NET_FOUND, send %s up : find %s len=%d\n",
 				 __func__, PNO_EVENT_UP,
 				 ssid->SSID, ssid->SSID_len);
-			WAKE_LOCK_TIMEOUT(iw->pub, WAKE_LOCK_PNO_FIND_TMOUT,
-					  20 * HZ);
 			cmd = IWEVCUSTOM;
 			memset(&wrqu, 0, sizeof(wrqu));
 			strcpy(extra, PNO_EVENT_UP);
@@ -3562,7 +3552,7 @@
 wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats)
 {
 	int res = 0;
-	wl_cnt_t cnt;
+	struct wl_cnt cnt;
 	int phy_noise;
 	int rssi;
 	scb_val_t scb_val;
@@ -3573,7 +3563,7 @@
 	if (res)
 		goto done;
 
-	phy_noise = dtoh32(phy_noise);
+	phy_noise = le32_to_cpu(phy_noise);
 	WL_TRACE("wl_iw_get_wireless_stats phy noise=%d\n", phy_noise);
 
 	memset(&scb_val, 0, sizeof(scb_val_t));
@@ -3581,7 +3571,7 @@
 	if (res)
 		goto done;
 
-	rssi = dtoh32(scb_val.val);
+	rssi = le32_to_cpu(scb_val.val);
 	WL_TRACE("wl_iw_get_wireless_stats rssi=%d\n", rssi);
 	if (rssi <= WL_IW_RSSI_NO_SIGNAL)
 		wstats->qual.qual = 0;
@@ -3605,47 +3595,50 @@
 #endif
 
 #if WIRELESS_EXT > 11
-	WL_TRACE("wl_iw_get_wireless_stats counters=%zu\n", sizeof(wl_cnt_t));
+	WL_TRACE("wl_iw_get_wireless_stats counters=%zu\n",
+		 sizeof(struct wl_cnt));
 
-	memset(&cnt, 0, sizeof(wl_cnt_t));
+	memset(&cnt, 0, sizeof(struct wl_cnt));
 	res =
-	    dev_wlc_bufvar_get(dev, "counters", (char *)&cnt, sizeof(wl_cnt_t));
+	    dev_wlc_bufvar_get(dev, "counters", (char *)&cnt,
+			       sizeof(struct wl_cnt));
 	if (res) {
 		WL_ERROR("wl_iw_get_wireless_stats counters failed error=%d\n",
 			 res);
 		goto done;
 	}
 
-	cnt.version = dtoh16(cnt.version);
+	cnt.version = le16_to_cpu(cnt.version);
 	if (cnt.version != WL_CNT_T_VERSION) {
-		WL_TRACE("\tIncorrect version of counters struct: expected %d; got %d\n",
+		WL_TRACE("\tIncorrect counter version: expected %d; got %d\n",
 			 WL_CNT_T_VERSION, cnt.version);
 		goto done;
 	}
 
 	wstats->discard.nwid = 0;
-	wstats->discard.code = dtoh32(cnt.rxundec);
-	wstats->discard.fragment = dtoh32(cnt.rxfragerr);
-	wstats->discard.retries = dtoh32(cnt.txfail);
-	wstats->discard.misc = dtoh32(cnt.rxrunt) + dtoh32(cnt.rxgiant);
+	wstats->discard.code = le32_to_cpu(cnt.rxundec);
+	wstats->discard.fragment = le32_to_cpu(cnt.rxfragerr);
+	wstats->discard.retries = le32_to_cpu(cnt.txfail);
+	wstats->discard.misc = le32_to_cpu(cnt.rxrunt) +
+		le32_to_cpu(cnt.rxgiant);
 	wstats->miss.beacon = 0;
 
 	WL_TRACE("wl_iw_get_wireless_stats counters txframe=%d txbyte=%d\n",
-		 dtoh32(cnt.txframe), dtoh32(cnt.txbyte));
+		 le32_to_cpu(cnt.txframe), le32_to_cpu(cnt.txbyte));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxfrmtoolong=%d\n",
-		  dtoh32(cnt.rxfrmtoolong));
+		  le32_to_cpu(cnt.rxfrmtoolong));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxbadplcp=%d\n",
-		  dtoh32(cnt.rxbadplcp));
+		  le32_to_cpu(cnt.rxbadplcp));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxundec=%d\n",
-		  dtoh32(cnt.rxundec));
+		  le32_to_cpu(cnt.rxundec));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxfragerr=%d\n",
-		  dtoh32(cnt.rxfragerr));
+		  le32_to_cpu(cnt.rxfragerr));
 	WL_TRACE("wl_iw_get_wireless_stats counters txfail=%d\n",
-		  dtoh32(cnt.txfail));
+		  le32_to_cpu(cnt.txfail));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxrunt=%d\n",
-		  dtoh32(cnt.rxrunt));
+		  le32_to_cpu(cnt.rxrunt));
 	WL_TRACE("wl_iw_get_wireless_stats counters rxgiant=%d\n",
-		  dtoh32(cnt.rxgiant));
+		  le32_to_cpu(cnt.rxgiant));
 #endif				/* WIRELESS_EXT > 11 */
 
 done:
@@ -3673,11 +3666,10 @@
 	params_size =
 	    (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
 #endif
-	iscan = kmalloc(sizeof(iscan_info_t), GFP_KERNEL);
+	iscan = kzalloc(sizeof(iscan_info_t), GFP_KERNEL);
 
 	if (!iscan)
 		return -ENOMEM;
-	memset(iscan, 0, sizeof(iscan_info_t));
 
 	iscan->iscan_ex_params_p = kmalloc(params_size, GFP_KERNEL);
 	if (!iscan->iscan_ex_params_p)
@@ -3711,11 +3703,10 @@
 	priv_dev = dev;
 	MUTEX_LOCK_SOFTAP_SET_INIT(iw->pub);
 #endif
-	g_scan = kmalloc(G_SCAN_RESULTS, GFP_KERNEL);
+	g_scan = kzalloc(G_SCAN_RESULTS, GFP_KERNEL);
 	if (!g_scan)
 		return -ENOMEM;
 
-	memset(g_scan, 0, G_SCAN_RESULTS);
 	g_scan_specified_ssid = 0;
 
 	return 0;
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.h	2011-03-14 21:20:32.000000000 -0400
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmfmac/wl_iw.h	2011-05-19 00:06:34.000000000 -0400
@@ -19,7 +19,6 @@
 
 #include <linux/wireless.h>
 
-#include <proto/ethernet.h>
 #include <wlioctl.h>
 
 #define WL_SCAN_PARAMS_SSID_MAX	10
@@ -92,7 +91,7 @@
 	u32 gwsec;
 	bool privacy_invoked;
 
-	struct ether_addr spy_addr[IW_MAX_SPY];
+	u8 spy_addr[IW_MAX_SPY][ETH_ALEN];
 	struct iw_quality spy_qual[IW_MAX_SPY];
 	void *wlinfo;
 	dhd_pub_t *pub;
@@ -140,10 +139,4 @@
 #define PNO_TLV_TYPE_TIME		'T'
 #define  PNO_EVENT_UP			"PNO_EVENT"
 
-typedef struct cmd_tlv {
-	char prefix;
-	char version;
-	char subver;
-	char reserved;
-} cmd_tlv_t;
 #endif				/* _wl_iw_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/d11.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/d11.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/d11.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/d11.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1771 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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	_D11_H
+#define	_D11_H
+
+#ifndef WL_RSSI_ANT_MAX
+#define WL_RSSI_ANT_MAX		4	/* max possible rx antennas */
+#elif WL_RSSI_ANT_MAX != 4
+#error "WL_RSSI_ANT_MAX does not match"
+#endif
+
+/* cpp contortions to concatenate w/arg prescan */
+#ifndef	PAD
+#define	_PADLINE(line)	pad ## line
+#define	_XSTR(line)	_PADLINE(line)
+#define	PAD		_XSTR(__LINE__)
+#endif
+
+#define	BCN_TMPL_LEN		512	/* length of the BCN template area */
+
+/* RX FIFO numbers */
+#define	RX_FIFO			0	/* data and ctl frames */
+#define	RX_TXSTATUS_FIFO	3	/* RX fifo for tx status packages */
+
+/* TX FIFO numbers using WME Access Classes */
+#define	TX_AC_BK_FIFO		0	/* Access Category Background TX FIFO */
+#define	TX_AC_BE_FIFO		1	/* Access Category Best-Effort TX FIFO */
+#define	TX_AC_VI_FIFO		2	/* Access Class Video TX FIFO */
+#define	TX_AC_VO_FIFO		3	/* Access Class Voice TX FIFO */
+#define	TX_BCMC_FIFO		4	/* Broadcast/Multicast TX FIFO */
+#define	TX_ATIM_FIFO		5	/* TX fifo for ATIM window info */
+
+/* Addr is byte address used by SW; offset is word offset used by uCode */
+
+/* Per AC TX limit settings */
+#define M_AC_TXLMT_BASE_ADDR         (0x180 * 2)
+#define M_AC_TXLMT_ADDR(_ac)         (M_AC_TXLMT_BASE_ADDR + (2 * (_ac)))
+
+/* Legacy TX FIFO numbers */
+#define	TX_DATA_FIFO		TX_AC_BE_FIFO
+#define	TX_CTL_FIFO		TX_AC_VO_FIFO
+
+typedef volatile struct {
+	u32 intstatus;
+	u32 intmask;
+} intctrlregs_t;
+
+/* PIO structure,
+ *  support two PIO format: 2 bytes access and 4 bytes access
+ *  basic FIFO register set is per channel(transmit or receive)
+ *  a pair of channels is defined for convenience
+ */
+/* 2byte-wide pio register set per channel(xmt or rcv) */
+typedef volatile struct {
+	u16 fifocontrol;
+	u16 fifodata;
+	u16 fifofree;	/* only valid in xmt channel, not in rcv channel */
+	u16 PAD;
+} pio2regs_t;
+
+/* a pair of pio channels(tx and rx) */
+typedef volatile struct {
+	pio2regs_t tx;
+	pio2regs_t rx;
+} pio2regp_t;
+
+/* 4byte-wide pio register set per channel(xmt or rcv) */
+typedef volatile struct {
+	u32 fifocontrol;
+	u32 fifodata;
+} pio4regs_t;
+
+/* a pair of pio channels(tx and rx) */
+typedef volatile struct {
+	pio4regs_t tx;
+	pio4regs_t rx;
+} pio4regp_t;
+
+/* read: 32-bit register that can be read as 32-bit or as 2 16-bit
+ * write: only low 16b-it half can be written
+ */
+typedef volatile union {
+	u32 pmqhostdata;	/* read only! */
+	struct {
+		u16 pmqctrlstatus;	/* read/write */
+		u16 PAD;
+	} w;
+} pmqreg_t;
+
+typedef volatile struct {
+	dma64regs_t dmaxmt;	/* dma tx */
+	pio4regs_t piotx;	/* pio tx */
+	dma64regs_t dmarcv;	/* dma rx */
+	pio4regs_t piorx;	/* pio rx */
+} fifo64_t;
+
+/*
+ * Host Interface Registers
+ * - primed from hnd_cores/dot11mac/systemC/registers/ihr.h
+ * - but definitely not complete
+ */
+typedef volatile struct _d11regs {
+	/* Device Control ("semi-standard host registers") */
+	u32 PAD[3];		/* 0x0 - 0x8 */
+	u32 biststatus;	/* 0xC */
+	u32 biststatus2;	/* 0x10 */
+	u32 PAD;		/* 0x14 */
+	u32 gptimer;		/* 0x18 */
+	u32 usectimer;	/* 0x1c *//* for corerev >= 26 */
+
+	/* Interrupt Control *//* 0x20 */
+	intctrlregs_t intctrlregs[8];
+
+	u32 PAD[40];		/* 0x60 - 0xFC */
+
+	u32 intrcvlazy[4];	/* 0x100 - 0x10C */
+
+	u32 PAD[4];		/* 0x110 - 0x11c */
+
+	u32 maccontrol;	/* 0x120 */
+	u32 maccommand;	/* 0x124 */
+	u32 macintstatus;	/* 0x128 */
+	u32 macintmask;	/* 0x12C */
+
+	/* Transmit Template Access */
+	u32 tplatewrptr;	/* 0x130 */
+	u32 tplatewrdata;	/* 0x134 */
+	u32 PAD[2];		/* 0x138 - 0x13C */
+
+	/* PMQ registers */
+	pmqreg_t pmqreg;	/* 0x140 */
+	u32 pmqpatl;		/* 0x144 */
+	u32 pmqpath;		/* 0x148 */
+	u32 PAD;		/* 0x14C */
+
+	u32 chnstatus;	/* 0x150 */
+	u32 psmdebug;	/* 0x154 */
+	u32 phydebug;	/* 0x158 */
+	u32 machwcap;	/* 0x15C */
+
+	/* Extended Internal Objects */
+	u32 objaddr;		/* 0x160 */
+	u32 objdata;		/* 0x164 */
+	u32 PAD[2];		/* 0x168 - 0x16c */
+
+	u32 frmtxstatus;	/* 0x170 */
+	u32 frmtxstatus2;	/* 0x174 */
+	u32 PAD[2];		/* 0x178 - 0x17c */
+
+	/* TSF host access */
+	u32 tsf_timerlow;	/* 0x180 */
+	u32 tsf_timerhigh;	/* 0x184 */
+	u32 tsf_cfprep;	/* 0x188 */
+	u32 tsf_cfpstart;	/* 0x18c */
+	u32 tsf_cfpmaxdur32;	/* 0x190 */
+	u32 PAD[3];		/* 0x194 - 0x19c */
+
+	u32 maccontrol1;	/* 0x1a0 */
+	u32 machwcap1;	/* 0x1a4 */
+	u32 PAD[14];		/* 0x1a8 - 0x1dc */
+
+	/* Clock control and hardware workarounds*/
+	u32 clk_ctl_st;	/* 0x1e0 */
+	u32 hw_war;
+	u32 d11_phypllctl;	/* the phypll request/avail bits are
+				 * moved to clk_ctl_st
+				 */
+	u32 PAD[5];		/* 0x1ec - 0x1fc */
+
+	/* 0x200-0x37F dma/pio registers */
+	fifo64_t fifo64regs[6];
+
+	/* FIFO diagnostic port access */
+	dma32diag_t dmafifo;	/* 0x380 - 0x38C */
+
+	u32 aggfifocnt;	/* 0x390 */
+	u32 aggfifodata;	/* 0x394 */
+	u32 PAD[16];		/* 0x398 - 0x3d4 */
+	u16 radioregaddr;	/* 0x3d8 */
+	u16 radioregdata;	/* 0x3da */
+
+	/*
+	 * time delay between the change on rf disable input and
+	 * radio shutdown
+	 */
+	u32 rfdisabledly;	/* 0x3DC */
+
+	/* PHY register access */
+	u16 phyversion;	/* 0x3e0 - 0x0 */
+	u16 phybbconfig;	/* 0x3e2 - 0x1 */
+	u16 phyadcbias;	/* 0x3e4 - 0x2  Bphy only */
+	u16 phyanacore;	/* 0x3e6 - 0x3  pwwrdwn on aphy */
+	u16 phyrxstatus0;	/* 0x3e8 - 0x4 */
+	u16 phyrxstatus1;	/* 0x3ea - 0x5 */
+	u16 phycrsth;	/* 0x3ec - 0x6 */
+	u16 phytxerror;	/* 0x3ee - 0x7 */
+	u16 phychannel;	/* 0x3f0 - 0x8 */
+	u16 PAD[1];		/* 0x3f2 - 0x9 */
+	u16 phytest;		/* 0x3f4 - 0xa */
+	u16 phy4waddr;	/* 0x3f6 - 0xb */
+	u16 phy4wdatahi;	/* 0x3f8 - 0xc */
+	u16 phy4wdatalo;	/* 0x3fa - 0xd */
+	u16 phyregaddr;	/* 0x3fc - 0xe */
+	u16 phyregdata;	/* 0x3fe - 0xf */
+
+	/* IHR *//* 0x400 - 0x7FE */
+
+	/* RXE Block */
+	u16 PAD[3];		/* 0x400 - 0x406 */
+	u16 rcv_fifo_ctl;	/* 0x406 */
+	u16 PAD;		/* 0x408 - 0x40a */
+	u16 rcv_frm_cnt;	/* 0x40a */
+	u16 PAD[4];		/* 0x40a - 0x414 */
+	u16 rssi;		/* 0x414 */
+	u16 PAD[5];		/* 0x414 - 0x420 */
+	u16 rcm_ctl;		/* 0x420 */
+	u16 rcm_mat_data;	/* 0x422 */
+	u16 rcm_mat_mask;	/* 0x424 */
+	u16 rcm_mat_dly;	/* 0x426 */
+	u16 rcm_cond_mask_l;	/* 0x428 */
+	u16 rcm_cond_mask_h;	/* 0x42A */
+	u16 rcm_cond_dly;	/* 0x42C */
+	u16 PAD[1];		/* 0x42E */
+	u16 ext_ihr_addr;	/* 0x430 */
+	u16 ext_ihr_data;	/* 0x432 */
+	u16 rxe_phyrs_2;	/* 0x434 */
+	u16 rxe_phyrs_3;	/* 0x436 */
+	u16 phy_mode;	/* 0x438 */
+	u16 rcmta_ctl;	/* 0x43a */
+	u16 rcmta_size;	/* 0x43c */
+	u16 rcmta_addr0;	/* 0x43e */
+	u16 rcmta_addr1;	/* 0x440 */
+	u16 rcmta_addr2;	/* 0x442 */
+	u16 PAD[30];		/* 0x444 - 0x480 */
+
+	/* PSM Block *//* 0x480 - 0x500 */
+
+	u16 PAD;		/* 0x480 */
+	u16 psm_maccontrol_h;	/* 0x482 */
+	u16 psm_macintstatus_l;	/* 0x484 */
+	u16 psm_macintstatus_h;	/* 0x486 */
+	u16 psm_macintmask_l;	/* 0x488 */
+	u16 psm_macintmask_h;	/* 0x48A */
+	u16 PAD;		/* 0x48C */
+	u16 psm_maccommand;	/* 0x48E */
+	u16 psm_brc;		/* 0x490 */
+	u16 psm_phy_hdr_param;	/* 0x492 */
+	u16 psm_postcard;	/* 0x494 */
+	u16 psm_pcard_loc_l;	/* 0x496 */
+	u16 psm_pcard_loc_h;	/* 0x498 */
+	u16 psm_gpio_in;	/* 0x49A */
+	u16 psm_gpio_out;	/* 0x49C */
+	u16 psm_gpio_oe;	/* 0x49E */
+
+	u16 psm_bred_0;	/* 0x4A0 */
+	u16 psm_bred_1;	/* 0x4A2 */
+	u16 psm_bred_2;	/* 0x4A4 */
+	u16 psm_bred_3;	/* 0x4A6 */
+	u16 psm_brcl_0;	/* 0x4A8 */
+	u16 psm_brcl_1;	/* 0x4AA */
+	u16 psm_brcl_2;	/* 0x4AC */
+	u16 psm_brcl_3;	/* 0x4AE */
+	u16 psm_brpo_0;	/* 0x4B0 */
+	u16 psm_brpo_1;	/* 0x4B2 */
+	u16 psm_brpo_2;	/* 0x4B4 */
+	u16 psm_brpo_3;	/* 0x4B6 */
+	u16 psm_brwk_0;	/* 0x4B8 */
+	u16 psm_brwk_1;	/* 0x4BA */
+	u16 psm_brwk_2;	/* 0x4BC */
+	u16 psm_brwk_3;	/* 0x4BE */
+
+	u16 psm_base_0;	/* 0x4C0 */
+	u16 psm_base_1;	/* 0x4C2 */
+	u16 psm_base_2;	/* 0x4C4 */
+	u16 psm_base_3;	/* 0x4C6 */
+	u16 psm_base_4;	/* 0x4C8 */
+	u16 psm_base_5;	/* 0x4CA */
+	u16 psm_base_6;	/* 0x4CC */
+	u16 psm_pc_reg_0;	/* 0x4CE */
+	u16 psm_pc_reg_1;	/* 0x4D0 */
+	u16 psm_pc_reg_2;	/* 0x4D2 */
+	u16 psm_pc_reg_3;	/* 0x4D4 */
+	u16 PAD[0xD];	/* 0x4D6 - 0x4DE */
+	u16 psm_corectlsts;	/* 0x4f0 *//* Corerev >= 13 */
+	u16 PAD[0x7];	/* 0x4f2 - 0x4fE */
+
+	/* TXE0 Block *//* 0x500 - 0x580 */
+	u16 txe_ctl;		/* 0x500 */
+	u16 txe_aux;		/* 0x502 */
+	u16 txe_ts_loc;	/* 0x504 */
+	u16 txe_time_out;	/* 0x506 */
+	u16 txe_wm_0;	/* 0x508 */
+	u16 txe_wm_1;	/* 0x50A */
+	u16 txe_phyctl;	/* 0x50C */
+	u16 txe_status;	/* 0x50E */
+	u16 txe_mmplcp0;	/* 0x510 */
+	u16 txe_mmplcp1;	/* 0x512 */
+	u16 txe_phyctl1;	/* 0x514 */
+
+	u16 PAD[0x05];	/* 0x510 - 0x51E */
+
+	/* Transmit control */
+	u16 xmtfifodef;	/* 0x520 */
+	u16 xmtfifo_frame_cnt;	/* 0x522 *//* Corerev >= 16 */
+	u16 xmtfifo_byte_cnt;	/* 0x524 *//* Corerev >= 16 */
+	u16 xmtfifo_head;	/* 0x526 *//* Corerev >= 16 */
+	u16 xmtfifo_rd_ptr;	/* 0x528 *//* Corerev >= 16 */
+	u16 xmtfifo_wr_ptr;	/* 0x52A *//* Corerev >= 16 */
+	u16 xmtfifodef1;	/* 0x52C *//* Corerev >= 16 */
+
+	u16 PAD[0x09];	/* 0x52E - 0x53E */
+
+	u16 xmtfifocmd;	/* 0x540 */
+	u16 xmtfifoflush;	/* 0x542 */
+	u16 xmtfifothresh;	/* 0x544 */
+	u16 xmtfifordy;	/* 0x546 */
+	u16 xmtfifoprirdy;	/* 0x548 */
+	u16 xmtfiforqpri;	/* 0x54A */
+	u16 xmttplatetxptr;	/* 0x54C */
+	u16 PAD;		/* 0x54E */
+	u16 xmttplateptr;	/* 0x550 */
+	u16 smpl_clct_strptr;	/* 0x552 *//* Corerev >= 22 */
+	u16 smpl_clct_stpptr;	/* 0x554 *//* Corerev >= 22 */
+	u16 smpl_clct_curptr;	/* 0x556 *//* Corerev >= 22 */
+	u16 PAD[0x04];	/* 0x558 - 0x55E */
+	u16 xmttplatedatalo;	/* 0x560 */
+	u16 xmttplatedatahi;	/* 0x562 */
+
+	u16 PAD[2];		/* 0x564 - 0x566 */
+
+	u16 xmtsel;		/* 0x568 */
+	u16 xmttxcnt;	/* 0x56A */
+	u16 xmttxshmaddr;	/* 0x56C */
+
+	u16 PAD[0x09];	/* 0x56E - 0x57E */
+
+	/* TXE1 Block */
+	u16 PAD[0x40];	/* 0x580 - 0x5FE */
+
+	/* TSF Block */
+	u16 PAD[0X02];	/* 0x600 - 0x602 */
+	u16 tsf_cfpstrt_l;	/* 0x604 */
+	u16 tsf_cfpstrt_h;	/* 0x606 */
+	u16 PAD[0X05];	/* 0x608 - 0x610 */
+	u16 tsf_cfppretbtt;	/* 0x612 */
+	u16 PAD[0XD];	/* 0x614 - 0x62C */
+	u16 tsf_clk_frac_l;	/* 0x62E */
+	u16 tsf_clk_frac_h;	/* 0x630 */
+	u16 PAD[0X14];	/* 0x632 - 0x658 */
+	u16 tsf_random;	/* 0x65A */
+	u16 PAD[0x05];	/* 0x65C - 0x664 */
+	/* GPTimer 2 registers */
+	u16 tsf_gpt2_stat;	/* 0x666 */
+	u16 tsf_gpt2_ctr_l;	/* 0x668 */
+	u16 tsf_gpt2_ctr_h;	/* 0x66A */
+	u16 tsf_gpt2_val_l;	/* 0x66C */
+	u16 tsf_gpt2_val_h;	/* 0x66E */
+	u16 tsf_gptall_stat;	/* 0x670 */
+	u16 PAD[0x07];	/* 0x672 - 0x67E */
+
+	/* IFS Block */
+	u16 ifs_sifs_rx_tx_tx;	/* 0x680 */
+	u16 ifs_sifs_nav_tx;	/* 0x682 */
+	u16 ifs_slot;	/* 0x684 */
+	u16 PAD;		/* 0x686 */
+	u16 ifs_ctl;		/* 0x688 */
+	u16 PAD[0x3];	/* 0x68a - 0x68F */
+	u16 ifsstat;		/* 0x690 */
+	u16 ifsmedbusyctl;	/* 0x692 */
+	u16 iftxdur;		/* 0x694 */
+	u16 PAD[0x3];	/* 0x696 - 0x69b */
+	/* EDCF support in dot11macs */
+	u16 ifs_aifsn;	/* 0x69c */
+	u16 ifs_ctl1;	/* 0x69e */
+
+	/* slow clock registers */
+	u16 scc_ctl;		/* 0x6a0 */
+	u16 scc_timer_l;	/* 0x6a2 */
+	u16 scc_timer_h;	/* 0x6a4 */
+	u16 scc_frac;	/* 0x6a6 */
+	u16 scc_fastpwrup_dly;	/* 0x6a8 */
+	u16 scc_per;		/* 0x6aa */
+	u16 scc_per_frac;	/* 0x6ac */
+	u16 scc_cal_timer_l;	/* 0x6ae */
+	u16 scc_cal_timer_h;	/* 0x6b0 */
+	u16 PAD;		/* 0x6b2 */
+
+	u16 PAD[0x26];
+
+	/* NAV Block */
+	u16 nav_ctl;		/* 0x700 */
+	u16 navstat;		/* 0x702 */
+	u16 PAD[0x3e];	/* 0x702 - 0x77E */
+
+	/* WEP/PMQ Block *//* 0x780 - 0x7FE */
+	u16 PAD[0x20];	/* 0x780 - 0x7BE */
+
+	u16 wepctl;		/* 0x7C0 */
+	u16 wepivloc;	/* 0x7C2 */
+	u16 wepivkey;	/* 0x7C4 */
+	u16 wepwkey;		/* 0x7C6 */
+
+	u16 PAD[4];		/* 0x7C8 - 0x7CE */
+	u16 pcmctl;		/* 0X7D0 */
+	u16 pcmstat;		/* 0X7D2 */
+	u16 PAD[6];		/* 0x7D4 - 0x7DE */
+
+	u16 pmqctl;		/* 0x7E0 */
+	u16 pmqstatus;	/* 0x7E2 */
+	u16 pmqpat0;		/* 0x7E4 */
+	u16 pmqpat1;		/* 0x7E6 */
+	u16 pmqpat2;		/* 0x7E8 */
+
+	u16 pmqdat;		/* 0x7EA */
+	u16 pmqdator;	/* 0x7EC */
+	u16 pmqhst;		/* 0x7EE */
+	u16 pmqpath0;	/* 0x7F0 */
+	u16 pmqpath1;	/* 0x7F2 */
+	u16 pmqpath2;	/* 0x7F4 */
+	u16 pmqdath;		/* 0x7F6 */
+
+	u16 PAD[0x04];	/* 0x7F8 - 0x7FE */
+
+	/* SHM *//* 0x800 - 0xEFE */
+	u16 PAD[0x380];	/* 0x800 - 0xEFE */
+
+	/* SB configuration registers: 0xF00 */
+	sbconfig_t sbconfig;	/* sb config regs occupy top 256 bytes */
+} d11regs_t;
+
+#define	PIHR_BASE	0x0400	/* byte address of packed IHR region */
+
+/* biststatus */
+#define	BT_DONE		(1U << 31)	/* bist done */
+#define	BT_B2S		(1 << 30)	/* bist2 ram summary bit */
+
+/* intstatus and intmask */
+#define	I_PC		(1 << 10)	/* pci descriptor error */
+#define	I_PD		(1 << 11)	/* pci data error */
+#define	I_DE		(1 << 12)	/* descriptor protocol error */
+#define	I_RU		(1 << 13)	/* receive descriptor underflow */
+#define	I_RO		(1 << 14)	/* receive fifo overflow */
+#define	I_XU		(1 << 15)	/* transmit fifo underflow */
+#define	I_RI		(1 << 16)	/* receive interrupt */
+#define	I_XI		(1 << 24)	/* transmit interrupt */
+
+/* interrupt receive lazy */
+#define	IRL_TO_MASK		0x00ffffff	/* timeout */
+#define	IRL_FC_MASK		0xff000000	/* frame count */
+#define	IRL_FC_SHIFT		24	/* frame count */
+
+/* maccontrol register */
+#define	MCTL_GMODE		(1U << 31)
+#define	MCTL_DISCARD_PMQ	(1 << 30)
+#define	MCTL_WAKE		(1 << 26)
+#define	MCTL_HPS		(1 << 25)
+#define	MCTL_PROMISC		(1 << 24)
+#define	MCTL_KEEPBADFCS		(1 << 23)
+#define	MCTL_KEEPCONTROL	(1 << 22)
+#define	MCTL_PHYLOCK		(1 << 21)
+#define	MCTL_BCNS_PROMISC	(1 << 20)
+#define	MCTL_LOCK_RADIO		(1 << 19)
+#define	MCTL_AP			(1 << 18)
+#define	MCTL_INFRA		(1 << 17)
+#define	MCTL_BIGEND		(1 << 16)
+#define	MCTL_GPOUT_SEL_MASK	(3 << 14)
+#define	MCTL_GPOUT_SEL_SHIFT	14
+#define	MCTL_EN_PSMDBG		(1 << 13)
+#define	MCTL_IHR_EN		(1 << 10)
+#define	MCTL_SHM_UPPER		(1 <<  9)
+#define	MCTL_SHM_EN		(1 <<  8)
+#define	MCTL_PSM_JMP_0		(1 <<  2)
+#define	MCTL_PSM_RUN		(1 <<  1)
+#define	MCTL_EN_MAC		(1 <<  0)
+
+/* maccommand register */
+#define	MCMD_BCN0VLD		(1 <<  0)
+#define	MCMD_BCN1VLD		(1 <<  1)
+#define	MCMD_DIRFRMQVAL		(1 <<  2)
+#define	MCMD_CCA		(1 <<  3)
+#define	MCMD_BG_NOISE		(1 <<  4)
+#define	MCMD_SKIP_SHMINIT	(1 <<  5)	/* only used for simulation */
+#define MCMD_SAMPLECOLL		MCMD_SKIP_SHMINIT	/* reuse for sample collect */
+
+/* macintstatus/macintmask */
+#define	MI_MACSSPNDD		(1 <<  0)	/* MAC has gracefully suspended */
+#define	MI_BCNTPL		(1 <<  1)	/* beacon template available */
+#define	MI_TBTT			(1 <<  2)	/* TBTT indication */
+#define	MI_BCNSUCCESS		(1 <<  3)	/* beacon successfully tx'd */
+#define	MI_BCNCANCLD		(1 <<  4)	/* beacon canceled (IBSS) */
+#define	MI_ATIMWINEND		(1 <<  5)	/* end of ATIM-window (IBSS) */
+#define	MI_PMQ			(1 <<  6)	/* PMQ entries available */
+#define	MI_NSPECGEN_0		(1 <<  7)	/* non-specific gen-stat bits that are set by PSM */
+#define	MI_NSPECGEN_1		(1 <<  8)	/* non-specific gen-stat bits that are set by PSM */
+#define	MI_MACTXERR		(1 <<  9)	/* MAC level Tx error */
+#define	MI_NSPECGEN_3		(1 << 10)	/* non-specific gen-stat bits that are set by PSM */
+#define	MI_PHYTXERR		(1 << 11)	/* PHY Tx error */
+#define	MI_PME			(1 << 12)	/* Power Management Event */
+#define	MI_GP0			(1 << 13)	/* General-purpose timer0 */
+#define	MI_GP1			(1 << 14)	/* General-purpose timer1 */
+#define	MI_DMAINT		(1 << 15)	/* (ORed) DMA-interrupts */
+#define	MI_TXSTOP		(1 << 16)	/* MAC has completed a TX FIFO Suspend/Flush */
+#define	MI_CCA			(1 << 17)	/* MAC has completed a CCA measurement */
+#define	MI_BG_NOISE		(1 << 18)	/* MAC has collected background noise samples */
+#define	MI_DTIM_TBTT		(1 << 19)	/* MBSS DTIM TBTT indication */
+#define MI_PRQ			(1 << 20)	/* Probe response queue needs attention */
+#define	MI_PWRUP		(1 << 21)	/* Radio/PHY has been powered back up. */
+#define	MI_RESERVED3		(1 << 22)
+#define	MI_RESERVED2		(1 << 23)
+#define MI_RESERVED1		(1 << 25)
+/* MAC detected change on RF Disable input*/
+#define MI_RFDISABLE		(1 << 28)
+#define	MI_TFS			(1 << 29)	/* MAC has completed a TX */
+#define	MI_PHYCHANGED		(1 << 30)	/* A phy status change wrt G mode */
+#define	MI_TO			(1U << 31)	/* general purpose timeout */
+
+/* Mac capabilities registers */
+/* machwcap */
+#define	MCAP_TKIPMIC		0x80000000	/* TKIP MIC hardware present */
+
+/* pmqhost data */
+#define	PMQH_DATA_MASK		0xffff0000	/* data entry of head pmq entry */
+#define	PMQH_BSSCFG		0x00100000	/* PM entry for BSS config */
+#define	PMQH_PMOFF		0x00010000	/* PM Mode OFF: power save off */
+#define	PMQH_PMON		0x00020000	/* PM Mode ON: power save on */
+#define	PMQH_DASAT		0x00040000	/* Dis-associated or De-authenticated */
+#define	PMQH_ATIMFAIL		0x00080000	/* ATIM not acknowledged */
+#define	PMQH_DEL_ENTRY		0x00000001	/* delete head entry */
+#define	PMQH_DEL_MULT		0x00000002	/* delete head entry to cur read pointer -1 */
+#define	PMQH_OFLO		0x00000004	/* pmq overflow indication */
+#define	PMQH_NOT_EMPTY		0x00000008	/* entries are present in pmq */
+
+/* phydebug */
+#define	PDBG_CRS		(1 << 0)	/* phy is asserting carrier sense */
+#define	PDBG_TXA		(1 << 1)	/* phy is taking xmit byte from mac this cycle */
+#define	PDBG_TXF		(1 << 2)	/* mac is instructing the phy to transmit a frame */
+#define	PDBG_TXE		(1 << 3)	/* phy is signalling a transmit Error to the mac */
+#define	PDBG_RXF		(1 << 4)	/* phy detected the end of a valid frame preamble */
+#define	PDBG_RXS		(1 << 5)	/* phy detected the end of a valid PLCP header */
+#define	PDBG_RXFRG		(1 << 6)	/* rx start not asserted */
+#define	PDBG_RXV		(1 << 7)	/* mac is taking receive byte from phy this cycle */
+#define	PDBG_RFD		(1 << 16)	/* RF portion of the radio is disabled */
+
+/* objaddr register */
+#define	OBJADDR_SEL_MASK	0x000F0000
+#define	OBJADDR_UCM_SEL		0x00000000
+#define	OBJADDR_SHM_SEL		0x00010000
+#define	OBJADDR_SCR_SEL		0x00020000
+#define	OBJADDR_IHR_SEL		0x00030000
+#define	OBJADDR_RCMTA_SEL	0x00040000
+#define	OBJADDR_SRCHM_SEL	0x00060000
+#define	OBJADDR_WINC		0x01000000
+#define	OBJADDR_RINC		0x02000000
+#define	OBJADDR_AUTO_INC	0x03000000
+
+#define	WEP_PCMADDR		0x07d4
+#define	WEP_PCMDATA		0x07d6
+
+/* frmtxstatus */
+#define	TXS_V			(1 << 0)	/* valid bit */
+#define	TXS_STATUS_MASK		0xffff
+#define	TXS_FID_MASK		0xffff0000
+#define	TXS_FID_SHIFT		16
+
+/* frmtxstatus2 */
+#define	TXS_SEQ_MASK		0xffff
+#define	TXS_PTX_MASK		0xff0000
+#define	TXS_PTX_SHIFT		16
+#define	TXS_MU_MASK		0x01000000
+#define	TXS_MU_SHIFT		24
+
+/* clk_ctl_st */
+#define CCS_ERSRC_REQ_D11PLL	0x00000100	/* d11 core pll request */
+#define CCS_ERSRC_REQ_PHYPLL	0x00000200	/* PHY pll request */
+#define CCS_ERSRC_AVAIL_D11PLL	0x01000000	/* d11 core pll available */
+#define CCS_ERSRC_AVAIL_PHYPLL	0x02000000	/* PHY pll available */
+
+/* HT Cloclk Ctrl and Clock Avail for 4313 */
+#define CCS_ERSRC_REQ_HT    0x00000010	/* HT avail request */
+#define CCS_ERSRC_AVAIL_HT  0x00020000	/* HT clock available */
+
+/* tsf_cfprep register */
+#define	CFPREP_CBI_MASK		0xffffffc0
+#define	CFPREP_CBI_SHIFT	6
+#define	CFPREP_CFPP		0x00000001
+
+/* tx fifo sizes values are in terms of 256 byte blocks */
+#define TXFIFOCMD_RESET_MASK	(1 << 15)	/* reset */
+#define TXFIFOCMD_FIFOSEL_SHIFT	8	/* fifo */
+#define TXFIFO_FIFOTOP_SHIFT	8	/* fifo start */
+
+#define TXFIFO_START_BLK16	 65	/* Base address + 32 * 512 B/P */
+#define TXFIFO_START_BLK	 6	/* Base address + 6 * 256 B */
+#define TXFIFO_SIZE_UNIT	256	/* one unit corresponds to 256 bytes */
+#define MBSS16_TEMPLMEM_MINBLKS	65	/* one unit corresponds to 256 bytes */
+
+/* phy versions, PhyVersion:Revision field */
+#define	PV_AV_MASK		0xf000	/* analog block version */
+#define	PV_AV_SHIFT		12	/* analog block version bitfield offset */
+#define	PV_PT_MASK		0x0f00	/* phy type */
+#define	PV_PT_SHIFT		8	/* phy type bitfield offset */
+#define	PV_PV_MASK		0x000f	/* phy version */
+#define	PHY_TYPE(v)		((v & PV_PT_MASK) >> PV_PT_SHIFT)
+
+/* phy types, PhyVersion:PhyType field */
+#define	PHY_TYPE_N		4	/* N-Phy value */
+#define	PHY_TYPE_SSN		6	/* SSLPN-Phy value */
+#define	PHY_TYPE_LCN		8	/* LCN-Phy value */
+#define	PHY_TYPE_LCNXN		9	/* LCNXN-Phy value */
+#define	PHY_TYPE_NULL		0xf	/* Invalid Phy value */
+
+/* analog types, PhyVersion:AnalogType field */
+#define	ANA_11N_013		5
+
+/* 802.11a PLCP header def */
+typedef struct ofdm_phy_hdr ofdm_phy_hdr_t;
+struct ofdm_phy_hdr {
+	u8 rlpt[3];		/* rate, length, parity, tail */
+	u16 service;
+	u8 pad;
+} __attribute__((packed));
+
+#define	D11A_PHY_HDR_GRATE(phdr)	((phdr)->rlpt[0] & 0x0f)
+#define	D11A_PHY_HDR_GRES(phdr)		(((phdr)->rlpt[0] >> 4) & 0x01)
+#define	D11A_PHY_HDR_GLENGTH(phdr)	(((u32 *)((phdr)->rlpt) >> 5) & 0x0fff)
+#define	D11A_PHY_HDR_GPARITY(phdr)	(((phdr)->rlpt[3] >> 1) & 0x01)
+#define	D11A_PHY_HDR_GTAIL(phdr)	(((phdr)->rlpt[3] >> 2) & 0x3f)
+
+/* rate encoded per 802.11a-1999 sec 17.3.4.1 */
+#define	D11A_PHY_HDR_SRATE(phdr, rate)		\
+	((phdr)->rlpt[0] = ((phdr)->rlpt[0] & 0xf0) | ((rate) & 0xf))
+/* set reserved field to zero */
+#define	D11A_PHY_HDR_SRES(phdr)		((phdr)->rlpt[0] &= 0xef)
+/* length is number of octets in PSDU */
+#define	D11A_PHY_HDR_SLENGTH(phdr, length)	\
+	(*(u32 *)((phdr)->rlpt) = *(u32 *)((phdr)->rlpt) | \
+	(((length) & 0x0fff) << 5))
+/* set the tail to all zeros */
+#define	D11A_PHY_HDR_STAIL(phdr)	((phdr)->rlpt[3] &= 0x03)
+
+#define	D11A_PHY_HDR_LEN_L	3	/* low-rate part of PLCP header */
+#define	D11A_PHY_HDR_LEN_R	2	/* high-rate part of PLCP header */
+
+#define	D11A_PHY_TX_DELAY	(2)	/* 2.1 usec */
+
+#define	D11A_PHY_HDR_TIME	(4)	/* low-rate part of PLCP header */
+#define	D11A_PHY_PRE_TIME	(16)
+#define	D11A_PHY_PREHDR_TIME	(D11A_PHY_PRE_TIME + D11A_PHY_HDR_TIME)
+
+/* 802.11b PLCP header def */
+typedef struct cck_phy_hdr cck_phy_hdr_t;
+struct cck_phy_hdr {
+	u8 signal;
+	u8 service;
+	u16 length;
+	u16 crc;
+} __attribute__((packed));
+
+#define	D11B_PHY_HDR_LEN	6
+
+#define	D11B_PHY_TX_DELAY	(3)	/* 3.4 usec */
+
+#define	D11B_PHY_LHDR_TIME	(D11B_PHY_HDR_LEN << 3)
+#define	D11B_PHY_LPRE_TIME	(144)
+#define	D11B_PHY_LPREHDR_TIME	(D11B_PHY_LPRE_TIME + D11B_PHY_LHDR_TIME)
+
+#define	D11B_PHY_SHDR_TIME	(D11B_PHY_LHDR_TIME >> 1)
+#define	D11B_PHY_SPRE_TIME	(D11B_PHY_LPRE_TIME >> 1)
+#define	D11B_PHY_SPREHDR_TIME	(D11B_PHY_SPRE_TIME + D11B_PHY_SHDR_TIME)
+
+#define	D11B_PLCP_SIGNAL_LOCKED	(1 << 2)
+#define	D11B_PLCP_SIGNAL_LE	(1 << 7)
+
+#define MIMO_PLCP_MCS_MASK	0x7f	/* mcs index */
+#define MIMO_PLCP_40MHZ		0x80	/* 40 Hz frame */
+#define MIMO_PLCP_AMPDU		0x08	/* ampdu */
+
+#define WLC_GET_CCK_PLCP_LEN(plcp) (plcp[4] + (plcp[5] << 8))
+#define WLC_GET_MIMO_PLCP_LEN(plcp) (plcp[1] + (plcp[2] << 8))
+#define WLC_SET_MIMO_PLCP_LEN(plcp, len) \
+	do { \
+		plcp[1] = len & 0xff; \
+		plcp[2] = ((len >> 8) & 0xff); \
+	} while (0);
+
+#define WLC_SET_MIMO_PLCP_AMPDU(plcp) (plcp[3] |= MIMO_PLCP_AMPDU)
+#define WLC_CLR_MIMO_PLCP_AMPDU(plcp) (plcp[3] &= ~MIMO_PLCP_AMPDU)
+#define WLC_IS_MIMO_PLCP_AMPDU(plcp) (plcp[3] & MIMO_PLCP_AMPDU)
+
+/* The dot11a PLCP header is 5 bytes.  To simplify the software (so that we
+ * don't need e.g. different tx DMA headers for 11a and 11b), the PLCP header has
+ * padding added in the ucode.
+ */
+#define	D11_PHY_HDR_LEN	6
+
+/* TX DMA buffer header */
+typedef struct d11txh d11txh_t;
+struct d11txh {
+	u16 MacTxControlLow;	/* 0x0 */
+	u16 MacTxControlHigh;	/* 0x1 */
+	u16 MacFrameControl;	/* 0x2 */
+	u16 TxFesTimeNormal;	/* 0x3 */
+	u16 PhyTxControlWord;	/* 0x4 */
+	u16 PhyTxControlWord_1;	/* 0x5 */
+	u16 PhyTxControlWord_1_Fbr;	/* 0x6 */
+	u16 PhyTxControlWord_1_Rts;	/* 0x7 */
+	u16 PhyTxControlWord_1_FbrRts;	/* 0x8 */
+	u16 MainRates;	/* 0x9 */
+	u16 XtraFrameTypes;	/* 0xa */
+	u8 IV[16];		/* 0x0b - 0x12 */
+	u8 TxFrameRA[6];	/* 0x13 - 0x15 */
+	u16 TxFesTimeFallback;	/* 0x16 */
+	u8 RTSPLCPFallback[6];	/* 0x17 - 0x19 */
+	u16 RTSDurFallback;	/* 0x1a */
+	u8 FragPLCPFallback[6];	/* 0x1b - 1d */
+	u16 FragDurFallback;	/* 0x1e */
+	u16 MModeLen;	/* 0x1f */
+	u16 MModeFbrLen;	/* 0x20 */
+	u16 TstampLow;	/* 0x21 */
+	u16 TstampHigh;	/* 0x22 */
+	u16 ABI_MimoAntSel;	/* 0x23 */
+	u16 PreloadSize;	/* 0x24 */
+	u16 AmpduSeqCtl;	/* 0x25 */
+	u16 TxFrameID;	/* 0x26 */
+	u16 TxStatus;	/* 0x27 */
+	u16 MaxNMpdus;	/* 0x28 */
+	u16 MaxABytes_MRT;	/* 0x29 */
+	u16 MaxABytes_FBR;	/* 0x2a */
+	u16 MinMBytes;	/* 0x2b */
+	u8 RTSPhyHeader[D11_PHY_HDR_LEN];	/* 0x2c - 0x2e */
+	struct ieee80211_rts rts_frame;	/* 0x2f - 0x36 */
+	u16 PAD;		/* 0x37 */
+} __attribute__((packed));
+
+#define	D11_TXH_LEN		112	/* bytes */
+
+/* Frame Types */
+#define FT_CCK	0
+#define FT_OFDM	1
+#define FT_HT	2
+#define FT_N	3
+
+/* Position of MPDU inside A-MPDU; indicated with bits 10:9 of MacTxControlLow */
+#define TXC_AMPDU_SHIFT		9	/* shift for ampdu settings */
+#define TXC_AMPDU_NONE		0	/* Regular MPDU, not an A-MPDU */
+#define TXC_AMPDU_FIRST		1	/* first MPDU of an A-MPDU */
+#define TXC_AMPDU_MIDDLE	2	/* intermediate MPDU of an A-MPDU */
+#define TXC_AMPDU_LAST		3	/* last (or single) MPDU of an A-MPDU */
+
+/* MacTxControlLow */
+#define TXC_AMIC		0x8000
+#define	TXC_SENDCTS		0x0800
+#define TXC_AMPDU_MASK		0x0600
+#define TXC_BW_40		0x0100
+#define TXC_FREQBAND_5G		0x0080
+#define	TXC_DFCS		0x0040
+#define	TXC_IGNOREPMQ		0x0020
+#define	TXC_HWSEQ		0x0010
+#define	TXC_STARTMSDU		0x0008
+#define	TXC_SENDRTS		0x0004
+#define	TXC_LONGFRAME		0x0002
+#define	TXC_IMMEDACK		0x0001
+
+/* MacTxControlHigh */
+#define TXC_PREAMBLE_RTS_FB_SHORT	0x8000	/* RTS fallback preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_RTS_MAIN_SHORT	0x4000	/* RTS main rate preamble type 1 = SHORT 0 = LONG */
+#define TXC_PREAMBLE_DATA_FB_SHORT	0x2000	/* Main fallback rate preamble type
+						 * 1 = SHORT for OFDM/GF for MIMO
+						 * 0 = LONG for CCK/MM for MIMO
+						 */
+/* TXC_PREAMBLE_DATA_MAIN is in PhyTxControl bit 5 */
+#define	TXC_AMPDU_FBR		0x1000	/* use fallback rate for this AMPDU */
+#define	TXC_SECKEY_MASK		0x0FF0
+#define	TXC_SECKEY_SHIFT	4
+#define	TXC_ALT_TXPWR		0x0008	/* Use alternate txpwr defined at loc. M_ALT_TXPWR_IDX */
+#define	TXC_SECTYPE_MASK	0x0007
+#define	TXC_SECTYPE_SHIFT	0
+
+/* Null delimiter for Fallback rate */
+#define AMPDU_FBR_NULL_DELIM  5	/* Location of Null delimiter count for AMPDU */
+
+/* PhyTxControl for Mimophy */
+#define	PHY_TXC_PWR_MASK	0xFC00
+#define	PHY_TXC_PWR_SHIFT	10
+#define	PHY_TXC_ANT_MASK	0x03C0	/* bit 6, 7, 8, 9 */
+#define	PHY_TXC_ANT_SHIFT	6
+#define	PHY_TXC_ANT_0_1		0x00C0	/* auto, last rx */
+#define	PHY_TXC_LCNPHY_ANT_LAST	0x0000
+#define	PHY_TXC_ANT_3		0x0200	/* virtual antenna 3 */
+#define	PHY_TXC_ANT_2		0x0100	/* virtual antenna 2 */
+#define	PHY_TXC_ANT_1		0x0080	/* virtual antenna 1 */
+#define	PHY_TXC_ANT_0		0x0040	/* virtual antenna 0 */
+#define	PHY_TXC_SHORT_HDR	0x0010
+
+#define	PHY_TXC_OLD_ANT_0	0x0000
+#define	PHY_TXC_OLD_ANT_1	0x0100
+#define	PHY_TXC_OLD_ANT_LAST	0x0300
+
+/* PhyTxControl_1 for Mimophy */
+#define PHY_TXC1_BW_MASK		0x0007
+#define PHY_TXC1_BW_10MHZ		0
+#define PHY_TXC1_BW_10MHZ_UP		1
+#define PHY_TXC1_BW_20MHZ		2
+#define PHY_TXC1_BW_20MHZ_UP		3
+#define PHY_TXC1_BW_40MHZ		4
+#define PHY_TXC1_BW_40MHZ_DUP		5
+#define PHY_TXC1_MODE_SHIFT		3
+#define PHY_TXC1_MODE_MASK		0x0038
+#define PHY_TXC1_MODE_SISO		0
+#define PHY_TXC1_MODE_CDD		1
+#define PHY_TXC1_MODE_STBC		2
+#define PHY_TXC1_MODE_SDM		3
+
+/* PhyTxControl for HTphy that are different from Mimophy */
+#define	PHY_TXC_HTANT_MASK		0x3fC0	/* bit 6, 7, 8, 9, 10, 11, 12, 13 */
+
+/* XtraFrameTypes */
+#define XFTS_RTS_FT_SHIFT	2
+#define XFTS_FBRRTS_FT_SHIFT	4
+#define XFTS_CHANNEL_SHIFT	8
+
+/* Antenna diversity bit in ant_wr_settle */
+#define	PHY_AWS_ANTDIV		0x2000
+
+/* IFS ctl */
+#define IFS_USEEDCF	(1 << 2)
+
+/* IFS ctl1 */
+#define IFS_CTL1_EDCRS	(1 << 3)
+#define IFS_CTL1_EDCRS_20L (1 << 4)
+#define IFS_CTL1_EDCRS_40 (1 << 5)
+
+/* ABI_MimoAntSel */
+#define ABI_MAS_ADDR_BMP_IDX_MASK	0x0f00
+#define ABI_MAS_ADDR_BMP_IDX_SHIFT	8
+#define ABI_MAS_FBR_ANT_PTN_MASK	0x00f0
+#define ABI_MAS_FBR_ANT_PTN_SHIFT	4
+#define ABI_MAS_MRT_ANT_PTN_MASK	0x000f
+
+/* tx status packet */
+typedef struct tx_status tx_status_t;
+struct tx_status {
+	u16 framelen;
+	u16 PAD;
+	u16 frameid;
+	u16 status;
+	u16 lasttxtime;
+	u16 sequence;
+	u16 phyerr;
+	u16 ackphyrxsh;
+} __attribute__((packed));
+
+#define	TXSTATUS_LEN	16
+
+/* status field bit definitions */
+#define	TX_STATUS_FRM_RTX_MASK	0xF000
+#define	TX_STATUS_FRM_RTX_SHIFT	12
+#define	TX_STATUS_RTS_RTX_MASK	0x0F00
+#define	TX_STATUS_RTS_RTX_SHIFT	8
+#define TX_STATUS_MASK		0x00FE
+#define	TX_STATUS_PMINDCTD	(1 << 7)	/* PM mode indicated to AP */
+#define	TX_STATUS_INTERMEDIATE	(1 << 6)	/* intermediate or 1st ampdu pkg */
+#define	TX_STATUS_AMPDU		(1 << 5)	/* AMPDU status */
+#define TX_STATUS_SUPR_MASK	0x1C	/* suppress status bits (4:2) */
+#define TX_STATUS_SUPR_SHIFT	2
+#define	TX_STATUS_ACK_RCV	(1 << 1)	/* ACK received */
+#define	TX_STATUS_VALID		(1 << 0)	/* Tx status valid */
+#define	TX_STATUS_NO_ACK	0
+
+/* suppress status reason codes */
+#define	TX_STATUS_SUPR_PMQ	(1 << 2)	/* PMQ entry */
+#define	TX_STATUS_SUPR_FLUSH	(2 << 2)	/* flush request */
+#define	TX_STATUS_SUPR_FRAG	(3 << 2)	/* previous frag failure */
+#define	TX_STATUS_SUPR_TBTT	(3 << 2)	/* SHARED: Probe response supr for TBTT */
+#define	TX_STATUS_SUPR_BADCH	(4 << 2)	/* channel mismatch */
+#define	TX_STATUS_SUPR_EXPTIME	(5 << 2)	/* lifetime expiry */
+#define	TX_STATUS_SUPR_UF	(6 << 2)	/* underflow */
+
+/* Unexpected tx status for rate update */
+#define TX_STATUS_UNEXP(status) \
+	((((status) & TX_STATUS_INTERMEDIATE) != 0) && \
+	 TX_STATUS_UNEXP_AMPDU(status))
+
+/* Unexpected tx status for A-MPDU rate update */
+#define TX_STATUS_UNEXP_AMPDU(status) \
+	((((status) & TX_STATUS_SUPR_MASK) != 0) && \
+	 (((status) & TX_STATUS_SUPR_MASK) != TX_STATUS_SUPR_EXPTIME))
+
+#define TX_STATUS_BA_BMAP03_MASK	0xF000	/* ba bitmap 0:3 in 1st pkg */
+#define TX_STATUS_BA_BMAP03_SHIFT	12	/* ba bitmap 0:3 in 1st pkg */
+#define TX_STATUS_BA_BMAP47_MASK	0x001E	/* ba bitmap 4:7 in 2nd pkg */
+#define TX_STATUS_BA_BMAP47_SHIFT	3	/* ba bitmap 4:7 in 2nd pkg */
+
+/* RXE (Receive Engine) */
+
+/* RCM_CTL */
+#define	RCM_INC_MASK_H		0x0080
+#define	RCM_INC_MASK_L		0x0040
+#define	RCM_INC_DATA		0x0020
+#define	RCM_INDEX_MASK		0x001F
+#define	RCM_SIZE		15
+
+#define	RCM_MAC_OFFSET		0	/* current MAC address */
+#define	RCM_BSSID_OFFSET	3	/* current BSSID address */
+#define	RCM_F_BSSID_0_OFFSET	6	/* foreign BSS CFP tracking */
+#define	RCM_F_BSSID_1_OFFSET	9	/* foreign BSS CFP tracking */
+#define	RCM_F_BSSID_2_OFFSET	12	/* foreign BSS CFP tracking */
+
+#define RCM_WEP_TA0_OFFSET	16
+#define RCM_WEP_TA1_OFFSET	19
+#define RCM_WEP_TA2_OFFSET	22
+#define RCM_WEP_TA3_OFFSET	25
+
+/* PSM Block */
+
+/* psm_phy_hdr_param bits */
+#define MAC_PHY_RESET		1
+#define MAC_PHY_CLOCK_EN	2
+#define MAC_PHY_FORCE_CLK	4
+
+/* WEP Block */
+
+/* WEP_WKEY */
+#define	WKEY_START		(1 << 8)
+#define	WKEY_SEL_MASK		0x1F
+
+/* WEP data formats */
+
+/* the number of RCMTA entries */
+#define RCMTA_SIZE 50
+
+#define M_ADDR_BMP_BLK		(0x37e * 2)
+#define M_ADDR_BMP_BLK_SZ	12
+
+#define ADDR_BMP_RA		(1 << 0)	/* Receiver Address (RA) */
+#define ADDR_BMP_TA		(1 << 1)	/* Transmitter Address (TA) */
+#define ADDR_BMP_BSSID		(1 << 2)	/* BSSID */
+#define ADDR_BMP_AP		(1 << 3)	/* Infra-BSS Access Point (AP) */
+#define ADDR_BMP_STA		(1 << 4)	/* Infra-BSS Station (STA) */
+#define ADDR_BMP_RESERVED1	(1 << 5)
+#define ADDR_BMP_RESERVED2	(1 << 6)
+#define ADDR_BMP_RESERVED3	(1 << 7)
+#define ADDR_BMP_BSS_IDX_MASK	(3 << 8)	/* BSS control block index */
+#define ADDR_BMP_BSS_IDX_SHIFT	8
+
+#define	WSEC_MAX_RCMTA_KEYS	54
+
+/* max keys in M_TKMICKEYS_BLK */
+#define	WSEC_MAX_TKMIC_ENGINE_KEYS		12	/* 8 + 4 default */
+
+/* max RXE match registers */
+#define WSEC_MAX_RXE_KEYS	4
+
+/* SECKINDXALGO (Security Key Index & Algorithm Block) word format */
+/* SKL (Security Key Lookup) */
+#define	SKL_ALGO_MASK		0x0007
+#define	SKL_ALGO_SHIFT		0
+#define	SKL_KEYID_MASK		0x0008
+#define	SKL_KEYID_SHIFT		3
+#define	SKL_INDEX_MASK		0x03F0
+#define	SKL_INDEX_SHIFT		4
+#define	SKL_GRP_ALGO_MASK	0x1c00
+#define	SKL_GRP_ALGO_SHIFT	10
+
+/* additional bits defined for IBSS group key support */
+#define	SKL_IBSS_INDEX_MASK	0x01F0
+#define	SKL_IBSS_INDEX_SHIFT	4
+#define	SKL_IBSS_KEYID1_MASK	0x0600
+#define	SKL_IBSS_KEYID1_SHIFT	9
+#define	SKL_IBSS_KEYID2_MASK	0x1800
+#define	SKL_IBSS_KEYID2_SHIFT	11
+#define	SKL_IBSS_KEYALGO_MASK	0xE000
+#define	SKL_IBSS_KEYALGO_SHIFT	13
+
+#define	WSEC_MODE_OFF		0
+#define	WSEC_MODE_HW		1
+#define	WSEC_MODE_SW		2
+
+#define	WSEC_ALGO_OFF		0
+#define	WSEC_ALGO_WEP1		1
+#define	WSEC_ALGO_TKIP		2
+#define	WSEC_ALGO_AES		3
+#define	WSEC_ALGO_WEP128	4
+#define	WSEC_ALGO_AES_LEGACY	5
+#define	WSEC_ALGO_NALG		6
+
+#define	AES_MODE_NONE		0
+#define	AES_MODE_CCM		1
+
+/* WEP_CTL (Rev 0) */
+#define	WECR0_KEYREG_SHIFT	0
+#define	WECR0_KEYREG_MASK	0x7
+#define	WECR0_DECRYPT		(1 << 3)
+#define	WECR0_IVINLINE		(1 << 4)
+#define	WECR0_WEPALG_SHIFT	5
+#define	WECR0_WEPALG_MASK	(0x7 << 5)
+#define	WECR0_WKEYSEL_SHIFT	8
+#define	WECR0_WKEYSEL_MASK	(0x7 << 8)
+#define	WECR0_WKEYSTART		(1 << 11)
+#define	WECR0_WEPINIT		(1 << 14)
+#define	WECR0_ICVERR		(1 << 15)
+
+/* Frame template map byte offsets */
+#define	T_ACTS_TPL_BASE		(0)
+#define	T_NULL_TPL_BASE		(0xc * 2)
+#define	T_QNULL_TPL_BASE	(0x1c * 2)
+#define	T_RR_TPL_BASE		(0x2c * 2)
+#define	T_BCN0_TPL_BASE		(0x34 * 2)
+#define	T_PRS_TPL_BASE		(0x134 * 2)
+#define	T_BCN1_TPL_BASE		(0x234 * 2)
+#define T_TX_FIFO_TXRAM_BASE	(T_ACTS_TPL_BASE + (TXFIFO_START_BLK * TXFIFO_SIZE_UNIT))
+
+#define T_BA_TPL_BASE		T_QNULL_TPL_BASE	/* template area for BA */
+
+#define T_RAM_ACCESS_SZ		4	/* template ram is 4 byte access only */
+
+/* Shared Mem byte offsets */
+
+/* Location where the ucode expects the corerev */
+#define	M_MACHW_VER		(0x00b * 2)
+
+/* Location where the ucode expects the MAC capabilities */
+#define	M_MACHW_CAP_L		(0x060 * 2)
+#define	M_MACHW_CAP_H	(0x061 * 2)
+
+/* WME shared memory */
+#define M_EDCF_STATUS_OFF	(0x007 * 2)
+#define M_TXF_CUR_INDEX		(0x018 * 2)
+#define M_EDCF_QINFO		(0x120 * 2)
+
+/* PS-mode related parameters */
+#define	M_DOT11_SLOT		(0x008 * 2)
+#define	M_DOT11_DTIMPERIOD	(0x009 * 2)
+#define	M_NOSLPZNATDTIM		(0x026 * 2)
+
+/* Beacon-related parameters */
+#define	M_BCN0_FRM_BYTESZ	(0x00c * 2)	/* Bcn 0 template length */
+#define	M_BCN1_FRM_BYTESZ	(0x00d * 2)	/* Bcn 1 template length */
+#define	M_BCN_TXTSF_OFFSET	(0x00e * 2)
+#define	M_TIMBPOS_INBEACON	(0x00f * 2)
+#define	M_SFRMTXCNTFBRTHSD	(0x022 * 2)
+#define	M_LFRMTXCNTFBRTHSD	(0x023 * 2)
+#define	M_BCN_PCTLWD		(0x02a * 2)
+#define M_BCN_LI		(0x05b * 2)	/* beacon listen interval */
+
+/* MAX Rx Frame len */
+#define M_MAXRXFRM_LEN		(0x010 * 2)
+
+/* ACK/CTS related params */
+#define	M_RSP_PCTLWD		(0x011 * 2)
+
+/* Hardware Power Control */
+#define M_TXPWR_N		(0x012 * 2)
+#define M_TXPWR_TARGET		(0x013 * 2)
+#define M_TXPWR_MAX		(0x014 * 2)
+#define M_TXPWR_CUR		(0x019 * 2)
+
+/* Rx-related parameters */
+#define	M_RX_PAD_DATA_OFFSET	(0x01a * 2)
+
+/* WEP Shared mem data */
+#define	M_SEC_DEFIVLOC		(0x01e * 2)
+#define	M_SEC_VALNUMSOFTMCHTA	(0x01f * 2)
+#define	M_PHYVER		(0x028 * 2)
+#define	M_PHYTYPE		(0x029 * 2)
+#define	M_SECRXKEYS_PTR		(0x02b * 2)
+#define	M_TKMICKEYS_PTR		(0x059 * 2)
+#define	M_SECKINDXALGO_BLK	(0x2ea * 2)
+#define M_SECKINDXALGO_BLK_SZ	54
+#define	M_SECPSMRXTAMCH_BLK	(0x2fa * 2)
+#define	M_TKIP_TSC_TTAK		(0x18c * 2)
+#define	D11_MAX_KEY_SIZE	16
+
+#define	M_MAX_ANTCNT		(0x02e * 2)	/* antenna swap threshold */
+
+/* Probe response related parameters */
+#define	M_SSIDLEN		(0x024 * 2)
+#define	M_PRB_RESP_FRM_LEN	(0x025 * 2)
+#define	M_PRS_MAXTIME		(0x03a * 2)
+#define	M_SSID			(0xb0 * 2)
+#define	M_CTXPRS_BLK		(0xc0 * 2)
+#define	C_CTX_PCTLWD_POS	(0x4 * 2)
+
+/* Delta between OFDM and CCK power in CCK power boost mode */
+#define M_OFDM_OFFSET		(0x027 * 2)
+
+/* TSSI for last 4 11b/g CCK packets transmitted */
+#define	M_B_TSSI_0		(0x02c * 2)
+#define	M_B_TSSI_1		(0x02d * 2)
+
+/* Host flags to turn on ucode options */
+#define	M_HOST_FLAGS1		(0x02f * 2)
+#define	M_HOST_FLAGS2		(0x030 * 2)
+#define	M_HOST_FLAGS3		(0x031 * 2)
+#define	M_HOST_FLAGS4		(0x03c * 2)
+#define	M_HOST_FLAGS5		(0x06a * 2)
+#define	M_HOST_FLAGS_SZ		16
+
+#define M_RADAR_REG		(0x033 * 2)
+
+/* TSSI for last 4 11a OFDM packets transmitted */
+#define	M_A_TSSI_0		(0x034 * 2)
+#define	M_A_TSSI_1		(0x035 * 2)
+
+/* noise interference measurement */
+#define M_NOISE_IF_COUNT	(0x034 * 2)
+#define M_NOISE_IF_TIMEOUT	(0x035 * 2)
+
+#define	M_RF_RX_SP_REG1		(0x036 * 2)
+
+/* TSSI for last 4 11g OFDM packets transmitted */
+#define	M_G_TSSI_0		(0x038 * 2)
+#define	M_G_TSSI_1		(0x039 * 2)
+
+/* Background noise measure */
+#define	M_JSSI_0		(0x44 * 2)
+#define	M_JSSI_1		(0x45 * 2)
+#define	M_JSSI_AUX		(0x46 * 2)
+
+#define	M_CUR_2050_RADIOCODE	(0x47 * 2)
+
+/* TX fifo sizes */
+#define M_FIFOSIZE0		(0x4c * 2)
+#define M_FIFOSIZE1		(0x4d * 2)
+#define M_FIFOSIZE2		(0x4e * 2)
+#define M_FIFOSIZE3		(0x4f * 2)
+#define D11_MAX_TX_FRMS		32	/* max frames allowed in tx fifo */
+
+/* Current channel number plus upper bits */
+#define M_CURCHANNEL		(0x50 * 2)
+#define D11_CURCHANNEL_5G	0x0100;
+#define D11_CURCHANNEL_40	0x0200;
+#define D11_CURCHANNEL_MAX	0x00FF;
+
+/* last posted frameid on the bcmc fifo */
+#define M_BCMC_FID		(0x54 * 2)
+#define INVALIDFID		0xffff
+
+/* extended beacon phyctl bytes for 11N */
+#define	M_BCN_PCTL1WD		(0x058 * 2)
+
+/* idle busy ratio to duty_cycle requirement  */
+#define M_TX_IDLE_BUSY_RATIO_X_16_CCK  (0x52 * 2)
+#define M_TX_IDLE_BUSY_RATIO_X_16_OFDM (0x5A * 2)
+
+/* CW RSSI for LCNPHY */
+#define M_LCN_RSSI_0 		0x1332
+#define M_LCN_RSSI_1 		0x1338
+#define M_LCN_RSSI_2 		0x133e
+#define M_LCN_RSSI_3 		0x1344
+
+/* SNR for LCNPHY */
+#define M_LCN_SNR_A_0 	0x1334
+#define M_LCN_SNR_B_0 	0x1336
+
+#define M_LCN_SNR_A_1 	0x133a
+#define M_LCN_SNR_B_1 	0x133c
+
+#define M_LCN_SNR_A_2 	0x1340
+#define M_LCN_SNR_B_2 	0x1342
+
+#define M_LCN_SNR_A_3 	0x1346
+#define M_LCN_SNR_B_3 	0x1348
+
+#define M_LCN_LAST_RESET 	(81*2)
+#define M_LCN_LAST_LOC	(63*2)
+#define M_LCNPHY_RESET_STATUS (4902)
+#define M_LCNPHY_DSC_TIME	(0x98d*2)
+#define M_LCNPHY_RESET_CNT_DSC (0x98b*2)
+#define M_LCNPHY_RESET_CNT	(0x98c*2)
+
+/* Rate table offsets */
+#define	M_RT_DIRMAP_A		(0xe0 * 2)
+#define	M_RT_BBRSMAP_A		(0xf0 * 2)
+#define	M_RT_DIRMAP_B		(0x100 * 2)
+#define	M_RT_BBRSMAP_B		(0x110 * 2)
+
+/* Rate table entry offsets */
+#define	M_RT_PRS_PLCP_POS	10
+#define	M_RT_PRS_DUR_POS	16
+#define	M_RT_OFDM_PCTL1_POS	18
+
+#define M_20IN40_IQ			(0x380 * 2)
+
+/* SHM locations where ucode stores the current power index */
+#define M_CURR_IDX1		(0x384 * 2)
+#define M_CURR_IDX2		(0x387 * 2)
+
+#define M_BSCALE_ANT0	(0x5e * 2)
+#define M_BSCALE_ANT1	(0x5f * 2)
+
+/* Antenna Diversity Testing */
+#define M_MIMO_ANTSEL_RXDFLT	(0x63 * 2)
+#define M_ANTSEL_CLKDIV	(0x61 * 2)
+#define M_MIMO_ANTSEL_TXDFLT	(0x64 * 2)
+
+#define M_MIMO_MAXSYM	(0x5d * 2)
+#define MIMO_MAXSYM_DEF		0x8000	/* 32k */
+#define MIMO_MAXSYM_MAX		0xffff	/* 64k */
+
+#define M_WATCHDOG_8TU		(0x1e * 2)
+#define WATCHDOG_8TU_DEF	5
+#define WATCHDOG_8TU_MAX	10
+
+/* Manufacturing Test Variables */
+#define M_PKTENG_CTRL		(0x6c * 2)	/* PER test mode */
+#define M_PKTENG_IFS		(0x6d * 2)	/* IFS for TX mode */
+#define M_PKTENG_FRMCNT_LO		(0x6e * 2)	/* Lower word of tx frmcnt/rx lostcnt */
+#define M_PKTENG_FRMCNT_HI		(0x6f * 2)	/* Upper word of tx frmcnt/rx lostcnt */
+
+/* Index variation in vbat ripple */
+#define M_LCN_PWR_IDX_MAX	(0x67 * 2)	/* highest index read by ucode */
+#define M_LCN_PWR_IDX_MIN	(0x66 * 2)	/* lowest index read by ucode */
+
+/* M_PKTENG_CTRL bit definitions */
+#define M_PKTENG_MODE_TX		0x0001
+#define M_PKTENG_MODE_TX_RIFS	        0x0004
+#define M_PKTENG_MODE_TX_CTS            0x0008
+#define M_PKTENG_MODE_RX		0x0002
+#define M_PKTENG_MODE_RX_WITH_ACK	0x0402
+#define M_PKTENG_MODE_MASK		0x0003
+#define M_PKTENG_FRMCNT_VLD		0x0100	/* TX frames indicated in the frmcnt reg */
+
+/* Sample Collect parameters (bitmap and type) */
+#define M_SMPL_COL_BMP		(0x37d * 2)	/* Trigger bitmap for sample collect */
+#define M_SMPL_COL_CTL		(0x3b2 * 2)	/* Sample collect type */
+
+#define ANTSEL_CLKDIV_4MHZ	6
+#define MIMO_ANTSEL_BUSY	0x4000	/* bit 14 (busy) */
+#define MIMO_ANTSEL_SEL		0x8000	/* bit 15 write the value */
+#define MIMO_ANTSEL_WAIT	50	/* 50us wait */
+#define MIMO_ANTSEL_OVERRIDE	0x8000	/* flag */
+
+typedef struct shm_acparams shm_acparams_t;
+struct shm_acparams {
+	u16 txop;
+	u16 cwmin;
+	u16 cwmax;
+	u16 cwcur;
+	u16 aifs;
+	u16 bslots;
+	u16 reggap;
+	u16 status;
+	u16 rsvd[8];
+} __attribute__((packed));
+#define M_EDCF_QLEN	(16 * 2)
+
+#define WME_STATUS_NEWAC	(1 << 8)
+
+/* M_HOST_FLAGS */
+#define MHFMAX		5	/* Number of valid hostflag half-word (u16) */
+#define MHF1		0	/* Hostflag 1 index */
+#define MHF2		1	/* Hostflag 2 index */
+#define MHF3		2	/* Hostflag 3 index */
+#define MHF4		3	/* Hostflag 4 index */
+#define MHF5		4	/* Hostflag 5 index */
+
+/* Flags in M_HOST_FLAGS */
+#define	MHF1_ANTDIV		0x0001	/* Enable ucode antenna diversity help */
+#define	MHF1_EDCF		0x0100	/* Enable EDCF access control */
+#define MHF1_IQSWAP_WAR		0x0200
+#define	MHF1_FORCEFASTCLK	0x0400	/* Disable Slow clock request, for corerev < 11 */
+
+/* Flags in M_HOST_FLAGS2 */
+#define MHF2_PCISLOWCLKWAR	0x0008	/* PR16165WAR : Enable ucode PCI slow clock WAR */
+#define MHF2_TXBCMC_NOW		0x0040	/* Flush BCMC FIFO immediately */
+#define MHF2_HWPWRCTL		0x0080	/* Enable ucode/hw power control */
+#define MHF2_NPHY40MHZ_WAR	0x0800
+
+/* Flags in M_HOST_FLAGS3 */
+#define MHF3_ANTSEL_EN		0x0001	/* enabled mimo antenna selection */
+#define MHF3_ANTSEL_MODE	0x0002	/* antenna selection mode: 0: 2x3, 1: 2x4 */
+#define MHF3_RESERVED1		0x0004
+#define MHF3_RESERVED2		0x0008
+#define MHF3_NPHY_MLADV_WAR	0x0010
+
+/* Flags in M_HOST_FLAGS4 */
+#define MHF4_BPHY_TXCORE0	0x0080	/* force bphy Tx on core 0 (board level WAR) */
+#define MHF4_EXTPA_ENABLE  	0x4000	/* for 4313A0 FEM boards */
+
+/* Flags in M_HOST_FLAGS5 */
+#define MHF5_4313_GPIOCTRL	0x0001
+#define MHF5_RESERVED1		0x0002
+#define MHF5_RESERVED2		0x0004
+/* Radio power setting for ucode */
+#define	M_RADIO_PWR		(0x32 * 2)
+
+/* phy noise recorded by ucode right after tx */
+#define	M_PHY_NOISE		(0x037 * 2)
+#define	PHY_NOISE_MASK		0x00ff
+
+/* Receive Frame Data Header for 802.11b DCF-only frames */
+typedef struct d11rxhdr d11rxhdr_t;
+struct d11rxhdr {
+	u16 RxFrameSize;	/* Actual byte length of the frame data received */
+	u16 PAD;
+	u16 PhyRxStatus_0;	/* PhyRxStatus 15:0 */
+	u16 PhyRxStatus_1;	/* PhyRxStatus 31:16 */
+	u16 PhyRxStatus_2;	/* PhyRxStatus 47:32 */
+	u16 PhyRxStatus_3;	/* PhyRxStatus 63:48 */
+	u16 PhyRxStatus_4;	/* PhyRxStatus 79:64 */
+	u16 PhyRxStatus_5;	/* PhyRxStatus 95:80 */
+	u16 RxStatus1;	/* MAC Rx Status */
+	u16 RxStatus2;	/* extended MAC Rx status */
+	u16 RxTSFTime;	/* RxTSFTime time of first MAC symbol + M_PHY_PLCPRX_DLY */
+	u16 RxChan;		/* gain code, channel radio code, and phy type */
+} __attribute__((packed));
+
+#define	RXHDR_LEN		24	/* sizeof d11rxhdr_t */
+#define	FRAMELEN(h)		((h)->RxFrameSize)
+
+typedef struct wlc_d11rxhdr wlc_d11rxhdr_t;
+struct wlc_d11rxhdr {
+	d11rxhdr_t rxhdr;
+	u32 tsf_l;		/* TSF_L reading */
+	s8 rssi;		/* computed instanteneous rssi in BMAC */
+	s8 rxpwr0;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
+	s8 rxpwr1;		/* obsoleted, place holder for legacy ROM code. use rxpwr[] */
+	s8 do_rssi_ma;	/* do per-pkt sampling for per-antenna ma in HIGH */
+	s8 rxpwr[WL_RSSI_ANT_MAX];	/* rssi for supported antennas */
+} __attribute__((packed));
+
+/* PhyRxStatus_0: */
+#define	PRXS0_FT_MASK		0x0003	/* NPHY only: CCK, OFDM, preN, N */
+#define	PRXS0_CLIP_MASK		0x000C	/* NPHY only: clip count adjustment steps by AGC */
+#define	PRXS0_CLIP_SHIFT	2
+#define	PRXS0_UNSRATE		0x0010	/* PHY received a frame with unsupported rate */
+#define	PRXS0_RXANT_UPSUBBAND	0x0020	/* GPHY: rx ant, NPHY: upper sideband */
+#define	PRXS0_LCRS		0x0040	/* CCK frame only: lost crs during cck frame reception */
+#define	PRXS0_SHORTH		0x0080	/* Short Preamble */
+#define	PRXS0_PLCPFV		0x0100	/* PLCP violation */
+#define	PRXS0_PLCPHCF		0x0200	/* PLCP header integrity check failed */
+#define	PRXS0_GAIN_CTL		0x4000	/* legacy PHY gain control */
+#define PRXS0_ANTSEL_MASK	0xF000	/* NPHY: Antennas used for received frame, bitmask */
+#define PRXS0_ANTSEL_SHIFT	0x12
+
+/* subfield PRXS0_FT_MASK */
+#define	PRXS0_CCK		0x0000
+#define	PRXS0_OFDM		0x0001	/* valid only for G phy, use rxh->RxChan for A phy */
+#define	PRXS0_PREN		0x0002
+#define	PRXS0_STDN		0x0003
+
+/* subfield PRXS0_ANTSEL_MASK */
+#define PRXS0_ANTSEL_0		0x0	/* antenna 0 is used */
+#define PRXS0_ANTSEL_1		0x2	/* antenna 1 is used */
+#define PRXS0_ANTSEL_2		0x4	/* antenna 2 is used */
+#define PRXS0_ANTSEL_3		0x8	/* antenna 3 is used */
+
+/* PhyRxStatus_1: */
+#define	PRXS1_JSSI_MASK		0x00FF
+#define	PRXS1_JSSI_SHIFT	0
+#define	PRXS1_SQ_MASK		0xFF00
+#define	PRXS1_SQ_SHIFT		8
+
+/* nphy PhyRxStatus_1: */
+#define PRXS1_nphy_PWR0_MASK	0x00FF
+#define PRXS1_nphy_PWR1_MASK	0xFF00
+
+/* HTPHY Rx Status defines */
+/* htphy PhyRxStatus_0: those bit are overlapped with PhyRxStatus_0 */
+#define PRXS0_BAND	        0x0400	/* 0 = 2.4G, 1 = 5G */
+#define PRXS0_RSVD	        0x0800	/* reserved; set to 0 */
+#define PRXS0_UNUSED	        0xF000	/* unused and not defined; set to 0 */
+
+/* htphy PhyRxStatus_1: */
+#define PRXS1_HTPHY_CORE_MASK	0x000F	/* core enables for {3..0}, 0=disabled, 1=enabled */
+#define PRXS1_HTPHY_ANTCFG_MASK	0x00F0	/* antenna configation */
+#define PRXS1_HTPHY_MMPLCPLenL_MASK	0xFF00	/* Mixmode PLCP Length low byte mask */
+
+/* htphy PhyRxStatus_2: */
+#define PRXS2_HTPHY_MMPLCPLenH_MASK	0x000F	/* Mixmode PLCP Length high byte maskw */
+#define PRXS2_HTPHY_MMPLCH_RATE_MASK	0x00F0	/* Mixmode PLCP rate mask */
+#define PRXS2_HTPHY_RXPWR_ANT0	0xFF00	/* Rx power on core 0 */
+
+/* htphy PhyRxStatus_3: */
+#define PRXS3_HTPHY_RXPWR_ANT1	0x00FF	/* Rx power on core 1 */
+#define PRXS3_HTPHY_RXPWR_ANT2	0xFF00	/* Rx power on core 2 */
+
+/* htphy PhyRxStatus_4: */
+#define PRXS4_HTPHY_RXPWR_ANT3	0x00FF	/* Rx power on core 3 */
+#define PRXS4_HTPHY_CFO		0xFF00	/* Coarse frequency offset */
+
+/* htphy PhyRxStatus_5: */
+#define PRXS5_HTPHY_FFO	        0x00FF	/* Fine frequency offset */
+#define PRXS5_HTPHY_AR	        0xFF00	/* Advance Retard */
+
+#define HTPHY_MMPLCPLen(rxs)	((((rxs)->PhyRxStatus_1 & PRXS1_HTPHY_MMPLCPLenL_MASK) >> 8) | \
+	(((rxs)->PhyRxStatus_2 & PRXS2_HTPHY_MMPLCPLenH_MASK) << 8))
+/* Get Rx power on core 0 */
+#define HTPHY_RXPWR_ANT0(rxs)	((((rxs)->PhyRxStatus_2) & PRXS2_HTPHY_RXPWR_ANT0) >> 8)
+/* Get Rx power on core 1 */
+#define HTPHY_RXPWR_ANT1(rxs)	(((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT1)
+/* Get Rx power on core 2 */
+#define HTPHY_RXPWR_ANT2(rxs)	((((rxs)->PhyRxStatus_3) & PRXS3_HTPHY_RXPWR_ANT2) >> 8)
+
+/* ucode RxStatus1: */
+#define	RXS_BCNSENT		0x8000
+#define	RXS_SECKINDX_MASK	0x07e0
+#define	RXS_SECKINDX_SHIFT	5
+#define	RXS_DECERR		(1 << 4)
+#define	RXS_DECATMPT		(1 << 3)
+#define	RXS_PBPRES		(1 << 2)	/* PAD bytes to make IP data 4 bytes aligned */
+#define	RXS_RESPFRAMETX		(1 << 1)
+#define	RXS_FCSERR		(1 << 0)
+
+/* ucode RxStatus2: */
+#define RXS_AMSDU_MASK		1
+#define	RXS_AGGTYPE_MASK	0x6
+#define	RXS_AGGTYPE_SHIFT	1
+#define	RXS_PHYRXST_VALID	(1 << 8)
+#define RXS_RXANT_MASK		0x3
+#define RXS_RXANT_SHIFT		12
+
+/* RxChan */
+#define RXS_CHAN_40		0x1000
+#define RXS_CHAN_5G		0x0800
+#define	RXS_CHAN_ID_MASK	0x07f8
+#define	RXS_CHAN_ID_SHIFT	3
+#define	RXS_CHAN_PHYTYPE_MASK	0x0007
+#define	RXS_CHAN_PHYTYPE_SHIFT	0
+
+/* Index of attenuations used during ucode power control. */
+#define M_PWRIND_BLKS	(0x184 * 2)
+#define M_PWRIND_MAP0	(M_PWRIND_BLKS + 0x0)
+#define M_PWRIND_MAP1	(M_PWRIND_BLKS + 0x2)
+#define M_PWRIND_MAP2	(M_PWRIND_BLKS + 0x4)
+#define M_PWRIND_MAP3	(M_PWRIND_BLKS + 0x6)
+/* M_PWRIND_MAP(core) macro */
+#define M_PWRIND_MAP(core)  (M_PWRIND_BLKS + ((core)<<1))
+
+/* PSM SHM variable offsets */
+#define	M_PSM_SOFT_REGS	0x0
+#define	M_BOM_REV_MAJOR	(M_PSM_SOFT_REGS + 0x0)
+#define	M_BOM_REV_MINOR	(M_PSM_SOFT_REGS + 0x2)
+#define	M_UCODE_DBGST	(M_PSM_SOFT_REGS + 0x40)	/* ucode debug status code */
+#define	M_UCODE_MACSTAT	(M_PSM_SOFT_REGS + 0xE0)	/* macstat counters */
+
+#define M_AGING_THRSH	(0x3e * 2)	/* max time waiting for medium before tx */
+#define	M_MBURST_SIZE	(0x40 * 2)	/* max frames in a frameburst */
+#define	M_MBURST_TXOP	(0x41 * 2)	/* max frameburst TXOP in unit of us */
+#define M_SYNTHPU_DLY	(0x4a * 2)	/* pre-wakeup for synthpu, default: 500 */
+#define	M_PRETBTT	(0x4b * 2)
+
+#define M_ALT_TXPWR_IDX		(M_PSM_SOFT_REGS + (0x3b * 2))	/* offset to the target txpwr */
+#define M_PHY_TX_FLT_PTR	(M_PSM_SOFT_REGS + (0x3d * 2))
+#define M_CTS_DURATION		(M_PSM_SOFT_REGS + (0x5c * 2))
+#define M_LP_RCCAL_OVR		(M_PSM_SOFT_REGS + (0x6b * 2))
+
+/* PKTENG Rx Stats Block */
+#define M_RXSTATS_BLK_PTR	(M_PSM_SOFT_REGS + (0x65 * 2))
+
+/* ucode debug status codes */
+#define	DBGST_INACTIVE		0	/* not valid really */
+#define	DBGST_INIT		1	/* after zeroing SHM, before suspending at init */
+#define	DBGST_ACTIVE		2	/* "normal" state */
+#define	DBGST_SUSPENDED		3	/* suspended */
+#define	DBGST_ASLEEP		4	/* asleep (PS mode) */
+
+/* Scratch Reg defs */
+typedef enum {
+	S_RSV0 = 0,
+	S_RSV1,
+	S_RSV2,
+
+	/* scratch registers for Dot11-contants */
+	S_DOT11_CWMIN,		/* CW-minimum                                   0x03 */
+	S_DOT11_CWMAX,		/* CW-maximum                                   0x04 */
+	S_DOT11_CWCUR,		/* CW-current                                   0x05 */
+	S_DOT11_SRC_LMT,	/* short retry count limit                      0x06 */
+	S_DOT11_LRC_LMT,	/* long retry count limit                       0x07 */
+	S_DOT11_DTIMCOUNT,	/* DTIM-count                                   0x08 */
+
+	/* Tx-side scratch registers */
+	S_SEQ_NUM,		/* hardware sequence number reg                 0x09 */
+	S_SEQ_NUM_FRAG,		/* seq-num for frags (Set at the start os MSDU  0x0A */
+	S_FRMRETX_CNT,		/* frame retx count                             0x0B */
+	S_SSRC,			/* Station short retry count                    0x0C */
+	S_SLRC,			/* Station long retry count                     0x0D */
+	S_EXP_RSP,		/* Expected response frame                      0x0E */
+	S_OLD_BREM,		/* Remaining backoff ctr                        0x0F */
+	S_OLD_CWWIN,		/* saved-off CW-cur                             0x10 */
+	S_TXECTL,		/* TXE-Ctl word constructed in scr-pad          0x11 */
+	S_CTXTST,		/* frm type-subtype as read from Tx-descr       0x12 */
+
+	/* Rx-side scratch registers */
+	S_RXTST,		/* Type and subtype in Rxframe                  0x13 */
+
+	/* Global state register */
+	S_STREG,		/* state storage actual bit maps below          0x14 */
+
+	S_TXPWR_SUM,		/* Tx power control: accumulator                0x15 */
+	S_TXPWR_ITER,		/* Tx power control: iteration                  0x16 */
+	S_RX_FRMTYPE,		/* Rate and PHY type for frames                 0x17 */
+	S_THIS_AGG,		/* Size of this AGG (A-MSDU)                    0x18 */
+
+	S_KEYINDX,		/*                                              0x19 */
+	S_RXFRMLEN,		/* Receive MPDU length in bytes                 0x1A */
+
+	/* Receive TSF time stored in SCR */
+	S_RXTSFTMRVAL_WD3,	/* TSF value at the start of rx                 0x1B */
+	S_RXTSFTMRVAL_WD2,	/* TSF value at the start of rx                 0x1C */
+	S_RXTSFTMRVAL_WD1,	/* TSF value at the start of rx                 0x1D */
+	S_RXTSFTMRVAL_WD0,	/* TSF value at the start of rx                 0x1E */
+	S_RXSSN,		/* Received start seq number for A-MPDU BA      0x1F */
+	S_RXQOSFLD,		/* Rx-QoS field (if present)                    0x20 */
+
+	/* Scratch pad regs used in microcode as temp storage */
+	S_TMP0,			/* stmp0                                        0x21 */
+	S_TMP1,			/* stmp1                                        0x22 */
+	S_TMP2,			/* stmp2                                        0x23 */
+	S_TMP3,			/* stmp3                                        0x24 */
+	S_TMP4,			/* stmp4                                        0x25 */
+	S_TMP5,			/* stmp5                                        0x26 */
+	S_PRQPENALTY_CTR,	/* Probe response queue penalty counter         0x27 */
+	S_ANTCNT,		/* unsuccessful attempts on current ant.        0x28 */
+	S_SYMBOL,		/* flag for possible symbol ctl frames          0x29 */
+	S_RXTP,			/* rx frame type                                0x2A */
+	S_STREG2,		/* extra state storage                          0x2B */
+	S_STREG3,		/* even more extra state storage                0x2C */
+	S_STREG4,		/* ...                                          0x2D */
+	S_STREG5,		/* remember to initialize it to zero            0x2E */
+
+	S_ADJPWR_IDX,
+	S_CUR_PTR,		/* Temp pointer for A-MPDU re-Tx SHM table      0x32 */
+	S_REVID4,		/* 0x33 */
+	S_INDX,			/* 0x34 */
+	S_ADDR0,		/* 0x35 */
+	S_ADDR1,		/* 0x36 */
+	S_ADDR2,		/* 0x37 */
+	S_ADDR3,		/* 0x38 */
+	S_ADDR4,		/* 0x39 */
+	S_ADDR5,		/* 0x3A */
+	S_TMP6,			/* 0x3B */
+	S_KEYINDX_BU,		/* Backup for Key index                         0x3C */
+	S_MFGTEST_TMP0,		/* Temp register used for RX test calculations  0x3D */
+	S_RXESN,		/* Received end sequence number for A-MPDU BA   0x3E */
+	S_STREG6,		/* 0x3F */
+} ePsmScratchPadRegDefinitions;
+
+#define S_BEACON_INDX	S_OLD_BREM
+#define S_PRS_INDX	S_OLD_CWWIN
+#define S_PHYTYPE	S_SSRC
+#define S_PHYVER	S_SLRC
+
+/* IHR SLOW_CTRL values */
+#define SLOW_CTRL_PDE		(1 << 0)
+#define SLOW_CTRL_FD		(1 << 8)
+
+/* ucode mac statistic counters in shared memory */
+typedef struct macstat {
+	u16 txallfrm;	/* 0x80 */
+	u16 txrtsfrm;	/* 0x82 */
+	u16 txctsfrm;	/* 0x84 */
+	u16 txackfrm;	/* 0x86 */
+	u16 txdnlfrm;	/* 0x88 */
+	u16 txbcnfrm;	/* 0x8a */
+	u16 txfunfl[8];	/* 0x8c - 0x9b */
+	u16 txtplunfl;	/* 0x9c */
+	u16 txphyerr;	/* 0x9e */
+	u16 pktengrxducast;	/* 0xa0 */
+	u16 pktengrxdmcast;	/* 0xa2 */
+	u16 rxfrmtoolong;	/* 0xa4 */
+	u16 rxfrmtooshrt;	/* 0xa6 */
+	u16 rxinvmachdr;	/* 0xa8 */
+	u16 rxbadfcs;	/* 0xaa */
+	u16 rxbadplcp;	/* 0xac */
+	u16 rxcrsglitch;	/* 0xae */
+	u16 rxstrt;		/* 0xb0 */
+	u16 rxdfrmucastmbss;	/* 0xb2 */
+	u16 rxmfrmucastmbss;	/* 0xb4 */
+	u16 rxcfrmucast;	/* 0xb6 */
+	u16 rxrtsucast;	/* 0xb8 */
+	u16 rxctsucast;	/* 0xba */
+	u16 rxackucast;	/* 0xbc */
+	u16 rxdfrmocast;	/* 0xbe */
+	u16 rxmfrmocast;	/* 0xc0 */
+	u16 rxcfrmocast;	/* 0xc2 */
+	u16 rxrtsocast;	/* 0xc4 */
+	u16 rxctsocast;	/* 0xc6 */
+	u16 rxdfrmmcast;	/* 0xc8 */
+	u16 rxmfrmmcast;	/* 0xca */
+	u16 rxcfrmmcast;	/* 0xcc */
+	u16 rxbeaconmbss;	/* 0xce */
+	u16 rxdfrmucastobss;	/* 0xd0 */
+	u16 rxbeaconobss;	/* 0xd2 */
+	u16 rxrsptmout;	/* 0xd4 */
+	u16 bcntxcancl;	/* 0xd6 */
+	u16 PAD;
+	u16 rxf0ovfl;	/* 0xda */
+	u16 rxf1ovfl;	/* 0xdc */
+	u16 rxf2ovfl;	/* 0xde */
+	u16 txsfovfl;	/* 0xe0 */
+	u16 pmqovfl;		/* 0xe2 */
+	u16 rxcgprqfrm;	/* 0xe4 */
+	u16 rxcgprsqovfl;	/* 0xe6 */
+	u16 txcgprsfail;	/* 0xe8 */
+	u16 txcgprssuc;	/* 0xea */
+	u16 prs_timeout;	/* 0xec */
+	u16 rxnack;
+	u16 frmscons;
+	u16 txnack;
+	u16 txglitch_nack;
+	u16 txburst;		/* 0xf6 # tx bursts */
+	u16 bphy_rxcrsglitch;	/* bphy rx crs glitch */
+	u16 phywatchdog;	/* 0xfa # of phy watchdog events */
+	u16 PAD;
+	u16 bphy_badplcp;	/* bphy bad plcp */
+} macstat_t;
+
+/* dot11 core-specific control flags */
+#define	SICF_PCLKE		0x0004	/* PHY clock enable */
+#define	SICF_PRST		0x0008	/* PHY reset */
+#define	SICF_MPCLKE		0x0010	/* MAC PHY clockcontrol enable */
+#define	SICF_FREF		0x0020	/* PLL FreqRefSelect */
+/* NOTE: the following bw bits only apply when the core is attached
+ * to a NPHY
+ */
+#define	SICF_BWMASK		0x00c0	/* phy clock mask (b6 & b7) */
+#define	SICF_BW40		0x0080	/* 40MHz BW (160MHz phyclk) */
+#define	SICF_BW20		0x0040	/* 20MHz BW (80MHz phyclk) */
+#define	SICF_BW10		0x0000	/* 10MHz BW (40MHz phyclk) */
+#define	SICF_GMODE		0x2000	/* gmode enable */
+
+/* dot11 core-specific status flags */
+#define	SISF_2G_PHY		0x0001	/* 2.4G capable phy */
+#define	SISF_5G_PHY		0x0002	/* 5G capable phy */
+#define	SISF_FCLKA		0x0004	/* FastClkAvailable */
+#define	SISF_DB_PHY		0x0008	/* Dualband phy */
+
+/* === End of MAC reg, Beginning of PHY(b/a/g/n) reg, radio and LPPHY regs are separated === */
+
+#define	BPHY_REG_OFT_BASE	0x0
+/* offsets for indirect access to bphy registers */
+#define	BPHY_BB_CONFIG		0x01
+#define	BPHY_ADCBIAS		0x02
+#define	BPHY_ANACORE		0x03
+#define	BPHY_PHYCRSTH		0x06
+#define	BPHY_TEST		0x0a
+#define	BPHY_PA_TX_TO		0x10
+#define	BPHY_SYNTH_DC_TO	0x11
+#define	BPHY_PA_TX_TIME_UP	0x12
+#define	BPHY_RX_FLTR_TIME_UP	0x13
+#define	BPHY_TX_POWER_OVERRIDE	0x14
+#define	BPHY_RF_OVERRIDE	0x15
+#define	BPHY_RF_TR_LOOKUP1	0x16
+#define	BPHY_RF_TR_LOOKUP2	0x17
+#define	BPHY_COEFFS		0x18
+#define	BPHY_PLL_OUT		0x19
+#define	BPHY_REFRESH_MAIN	0x1a
+#define	BPHY_REFRESH_TO0	0x1b
+#define	BPHY_REFRESH_TO1	0x1c
+#define	BPHY_RSSI_TRESH		0x20
+#define	BPHY_IQ_TRESH_HH	0x21
+#define	BPHY_IQ_TRESH_H		0x22
+#define	BPHY_IQ_TRESH_L		0x23
+#define	BPHY_IQ_TRESH_LL	0x24
+#define	BPHY_GAIN		0x25
+#define	BPHY_LNA_GAIN_RANGE	0x26
+#define	BPHY_JSSI		0x27
+#define	BPHY_TSSI_CTL		0x28
+#define	BPHY_TSSI		0x29
+#define	BPHY_TR_LOSS_CTL	0x2a
+#define	BPHY_LO_LEAKAGE		0x2b
+#define	BPHY_LO_RSSI_ACC	0x2c
+#define	BPHY_LO_IQMAG_ACC	0x2d
+#define	BPHY_TX_DC_OFF1		0x2e
+#define	BPHY_TX_DC_OFF2		0x2f
+#define	BPHY_PEAK_CNT_THRESH	0x30
+#define	BPHY_FREQ_OFFSET	0x31
+#define	BPHY_DIVERSITY_CTL	0x32
+#define	BPHY_PEAK_ENERGY_LO	0x33
+#define	BPHY_PEAK_ENERGY_HI	0x34
+#define	BPHY_SYNC_CTL		0x35
+#define	BPHY_TX_PWR_CTRL	0x36
+#define BPHY_TX_EST_PWR 	0x37
+#define	BPHY_STEP		0x38
+#define	BPHY_WARMUP		0x39
+#define	BPHY_LMS_CFF_READ	0x3a
+#define	BPHY_LMS_COEFF_I	0x3b
+#define	BPHY_LMS_COEFF_Q	0x3c
+#define	BPHY_SIG_POW		0x3d
+#define	BPHY_RFDC_CANCEL_CTL	0x3e
+#define	BPHY_HDR_TYPE		0x40
+#define	BPHY_SFD_TO		0x41
+#define	BPHY_SFD_CTL		0x42
+#define	BPHY_DEBUG		0x43
+#define	BPHY_RX_DELAY_COMP	0x44
+#define	BPHY_CRS_DROP_TO	0x45
+#define	BPHY_SHORT_SFD_NZEROS	0x46
+#define	BPHY_DSSS_COEFF1	0x48
+#define	BPHY_DSSS_COEFF2	0x49
+#define	BPHY_CCK_COEFF1		0x4a
+#define	BPHY_CCK_COEFF2		0x4b
+#define	BPHY_TR_CORR		0x4c
+#define	BPHY_ANGLE_SCALE	0x4d
+#define	BPHY_TX_PWR_BASE_IDX	0x4e
+#define	BPHY_OPTIONAL_MODES2	0x4f
+#define	BPHY_CCK_LMS_STEP	0x50
+#define	BPHY_BYPASS		0x51
+#define	BPHY_CCK_DELAY_LONG	0x52
+#define	BPHY_CCK_DELAY_SHORT	0x53
+#define	BPHY_PPROC_CHAN_DELAY	0x54
+#define	BPHY_DDFS_ENABLE	0x58
+#define	BPHY_PHASE_SCALE	0x59
+#define	BPHY_FREQ_CONTROL	0x5a
+#define	BPHY_LNA_GAIN_RANGE_10	0x5b
+#define	BPHY_LNA_GAIN_RANGE_32	0x5c
+#define	BPHY_OPTIONAL_MODES	0x5d
+#define	BPHY_RX_STATUS2		0x5e
+#define	BPHY_RX_STATUS3		0x5f
+#define	BPHY_DAC_CONTROL	0x60
+#define	BPHY_ANA11G_FILT_CTRL	0x62
+#define	BPHY_REFRESH_CTRL	0x64
+#define	BPHY_RF_OVERRIDE2	0x65
+#define	BPHY_SPUR_CANCEL_CTRL	0x66
+#define	BPHY_FINE_DIGIGAIN_CTRL	0x67
+#define	BPHY_RSSI_LUT		0x88
+#define	BPHY_RSSI_LUT_END	0xa7
+#define	BPHY_TSSI_LUT		0xa8
+#define	BPHY_TSSI_LUT_END	0xc7
+#define	BPHY_TSSI2PWR_LUT	0x380
+#define	BPHY_TSSI2PWR_LUT_END	0x39f
+#define	BPHY_LOCOMP_LUT		0x3a0
+#define	BPHY_LOCOMP_LUT_END	0x3bf
+#define	BPHY_TXGAIN_LUT		0x3c0
+#define	BPHY_TXGAIN_LUT_END	0x3ff
+
+/* Bits in BB_CONFIG: */
+#define	PHY_BBC_ANT_MASK	0x0180
+#define	PHY_BBC_ANT_SHIFT	7
+#define	BB_DARWIN		0x1000
+#define BBCFG_RESETCCA		0x4000
+#define BBCFG_RESETRX		0x8000
+
+/* Bits in phytest(0x0a): */
+#define	TST_DDFS		0x2000
+#define	TST_TXFILT1		0x0800
+#define	TST_UNSCRAM		0x0400
+#define	TST_CARR_SUPP		0x0200
+#define	TST_DC_COMP_LOOP	0x0100
+#define	TST_LOOPBACK		0x0080
+#define	TST_TXFILT0		0x0040
+#define	TST_TXTEST_ENABLE	0x0020
+#define	TST_TXTEST_RATE		0x0018
+#define	TST_TXTEST_PHASE	0x0007
+
+/* phytest txTestRate values */
+#define	TST_TXTEST_RATE_1MBPS	0
+#define	TST_TXTEST_RATE_2MBPS	1
+#define	TST_TXTEST_RATE_5_5MBPS	2
+#define	TST_TXTEST_RATE_11MBPS	3
+#define	TST_TXTEST_RATE_SHIFT	3
+
+#define SHM_BYT_CNT	0x2	/* IHR location */
+#define MAX_BYT_CNT	0x600	/* Maximum frame len */
+
+#endif				/* _D11_H */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/Makefile linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/Makefile
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/Makefile	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/Makefile	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,63 @@
+#
+# Makefile fragment for Broadcom 802.11n Networking Device Driver
+#
+# Copyright (c) 2010 Broadcom Corporation
+#
+# 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.
+
+ccflags-y :=				\
+	-DWLC_HIGH				\
+	-DWLC_LOW				\
+	-DSTA					\
+	-DWME					\
+	-DWL11N					\
+	-DDBAND					\
+	-DBCMNVRAMR				\
+	-Idrivers/staging/brcm80211/brcmsmac \
+	-Idrivers/staging/brcm80211/brcmsmac/phy \
+	-Idrivers/staging/brcm80211/util \
+	-Idrivers/staging/brcm80211/include
+
+BRCMSMAC_OFILES := \
+	wl_mac80211.o \
+	wl_ucode_loader.o \
+	wlc_alloc.o \
+	wlc_ampdu.o \
+	wlc_antsel.o \
+	wlc_bmac.o \
+	wlc_channel.o \
+	wlc_main.o \
+	wlc_phy_shim.o \
+	wlc_rate.o \
+	wlc_stf.o \
+	phy/wlc_phy_cmn.o \
+	phy/wlc_phy_lcn.o \
+	phy/wlc_phy_n.o \
+	phy/wlc_phytbl_lcn.o \
+	phy/wlc_phytbl_n.o \
+	../util/aiutils.o \
+	../util/siutils.o \
+	../util/bcmutils.o \
+	../util/bcmwifi.o \
+	../util/bcmotp.o \
+	../util/bcmsrom.o \
+	../util/hnddma.o \
+	../util/hndpmu.o \
+	../util/nicpci.o \
+	../util/qmath.o \
+	../util/nvram/nvram_ro.o
+
+MODULEPFX := brcmsmac
+
+obj-m	+= $(MODULEPFX).o
+$(MODULEPFX)-objs	= $(BRCMSMAC_OFILES)
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/phy_version.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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_version_h_
+#define phy_version_h_
+
+#define	PHY_MAJOR_VERSION		1
+
+#define	PHY_MINOR_VERSION		82
+
+#define	PHY_RC_NUMBER		8
+
+#define	PHY_INCREMENTAL_NUMBER	0
+
+#define	PHY_BUILD_NUMBER		0
+
+#define	PHY_VERSION			{ 1, 82, 8, 0 }
+
+#define	PHY_VERSION_NUM		0x01520800
+
+#define	PHY_VERSION_STR		"1.82.8.0"
+
+#endif				/* phy_version_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_cmn.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,3431 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 <wlc_cfg.h>
+
+#include <linux/kernel.h>
+#include <linux/string.h>
+#include <bcmdefs.h>
+#include <linux/delay.h>
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <bcmnvram.h>
+#include <sbchipc.h>
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+
+#include <wlc_phy_int.h>
+#include <wlc_phyreg_n.h>
+#include <wlc_phy_radio.h>
+#include <wlc_phy_lcn.h>
+
+u32 phyhal_msg_level = PHYHAL_ERROR;
+
+typedef struct _chan_info_basic {
+	u16 chan;
+	u16 freq;
+} chan_info_basic_t;
+
+static chan_info_basic_t chan_info_all[] = {
+
+	{1, 2412},
+	{2, 2417},
+	{3, 2422},
+	{4, 2427},
+	{5, 2432},
+	{6, 2437},
+	{7, 2442},
+	{8, 2447},
+	{9, 2452},
+	{10, 2457},
+	{11, 2462},
+	{12, 2467},
+	{13, 2472},
+	{14, 2484},
+
+	{34, 5170},
+	{38, 5190},
+	{42, 5210},
+	{46, 5230},
+
+	{36, 5180},
+	{40, 5200},
+	{44, 5220},
+	{48, 5240},
+	{52, 5260},
+	{56, 5280},
+	{60, 5300},
+	{64, 5320},
+
+	{100, 5500},
+	{104, 5520},
+	{108, 5540},
+	{112, 5560},
+	{116, 5580},
+	{120, 5600},
+	{124, 5620},
+	{128, 5640},
+	{132, 5660},
+	{136, 5680},
+	{140, 5700},
+
+	{149, 5745},
+	{153, 5765},
+	{157, 5785},
+	{161, 5805},
+	{165, 5825},
+
+	{184, 4920},
+	{188, 4940},
+	{192, 4960},
+	{196, 4980},
+	{200, 5000},
+	{204, 5020},
+	{208, 5040},
+	{212, 5060},
+	{216, 50800}
+};
+
+u16 ltrn_list[PHY_LTRN_LIST_LEN] = {
+	0x18f9, 0x0d01, 0x00e4, 0xdef4, 0x06f1, 0x0ffc,
+	0xfa27, 0x1dff, 0x10f0, 0x0918, 0xf20a, 0xe010,
+	0x1417, 0x1104, 0xf114, 0xf2fa, 0xf7db, 0xe2fc,
+	0xe1fb, 0x13ee, 0xff0d, 0xe91c, 0x171a, 0x0318,
+	0xda00, 0x03e8, 0x17e6, 0xe9e4, 0xfff3, 0x1312,
+	0xe105, 0xe204, 0xf725, 0xf206, 0xf1ec, 0x11fc,
+	0x14e9, 0xe0f0, 0xf2f6, 0x09e8, 0x1010, 0x1d01,
+	0xfad9, 0x0f04, 0x060f, 0xde0c, 0x001c, 0x0dff,
+	0x1807, 0xf61a, 0xe40e, 0x0f16, 0x05f9, 0x18ec,
+	0x0a1b, 0xff1e, 0x2600, 0xffe2, 0x0ae5, 0x1814,
+	0x0507, 0x0fea, 0xe4f2, 0xf6e6
+};
+
+const u8 ofdm_rate_lookup[] = {
+
+	WLC_RATE_48M,
+	WLC_RATE_24M,
+	WLC_RATE_12M,
+	WLC_RATE_6M,
+	WLC_RATE_54M,
+	WLC_RATE_36M,
+	WLC_RATE_18M,
+	WLC_RATE_9M
+};
+
+#define PHY_WREG_LIMIT	24
+
+static void wlc_set_phy_uninitted(phy_info_t *pi);
+static u32 wlc_phy_get_radio_ver(phy_info_t *pi);
+static void wlc_phy_timercb_phycal(void *arg);
+
+static bool wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr,
+				   s8 *pwr_ant);
+
+static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay);
+static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm);
+static void wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason,
+					 u8 ch);
+
+static void wlc_phy_txpower_reg_limit_calc(phy_info_t *pi,
+					   struct txpwr_limits *tp, chanspec_t);
+static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi);
+
+static s8 wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan,
+					     u32 band, u8 rate);
+static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band);
+static s8 wlc_phy_env_measure_vbat(phy_info_t *pi);
+static s8 wlc_phy_env_measure_temperature(phy_info_t *pi);
+
+char *phy_getvar(phy_info_t *pi, const char *name)
+{
+	char *vars = pi->vars;
+	char *s;
+	int len;
+
+	ASSERT(pi->vars != (char *)&pi->vars);
+
+	if (!name)
+		return NULL;
+
+	len = strlen(name);
+	if (len == 0)
+		return NULL;
+
+	for (s = vars; s && *s;) {
+		if ((memcmp(s, name, len) == 0) && (s[len] == '='))
+			return &s[len + 1];
+
+		while (*s++)
+			;
+	}
+
+	return nvram_get(name);
+}
+
+int phy_getintvar(phy_info_t *pi, const char *name)
+{
+	char *val;
+
+	val = PHY_GETVAR(pi, name);
+	if (val == NULL)
+		return 0;
+
+	return simple_strtoul(val, NULL, 0);
+}
+
+void wlc_phyreg_enter(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	wlapi_bmac_ucode_wake_override_phyreg_set(pi->sh->physhim);
+}
+
+void wlc_phyreg_exit(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	wlapi_bmac_ucode_wake_override_phyreg_clear(pi->sh->physhim);
+}
+
+void wlc_radioreg_enter(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, MCTL_LOCK_RADIO);
+
+	udelay(10);
+}
+
+void wlc_radioreg_exit(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	volatile u16 dummy;
+
+	dummy = R_REG(&pi->regs->phyversion);
+	pi->phy_wreg = 0;
+	wlapi_bmac_mctrl(pi->sh->physhim, MCTL_LOCK_RADIO, 0);
+}
+
+u16 read_radio_reg(phy_info_t *pi, u16 addr)
+{
+	u16 data;
+
+	if ((addr == RADIO_IDCODE))
+		return 0xffff;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return NORADIO_IDCODE & 0xffff;
+
+	switch (pi->pubpi.phy_type) {
+	case PHY_TYPE_N:
+		CASECHECK(PHYTYPE, PHY_TYPE_N);
+		if (NREV_GE(pi->pubpi.phy_rev, 7))
+			addr |= RADIO_2057_READ_OFF;
+		else
+			addr |= RADIO_2055_READ_OFF;
+		break;
+
+	case PHY_TYPE_LCN:
+		CASECHECK(PHYTYPE, PHY_TYPE_LCN);
+		addr |= RADIO_2064_READ_OFF;
+		break;
+
+	default:
+		ASSERT(VALID_PHYTYPE(pi->pubpi.phy_type));
+	}
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+		W_REG(&pi->regs->radioregaddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		data = R_REG(&pi->regs->radioregdata);
+	} else {
+		W_REG(&pi->regs->phy4waddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->phy4waddr);
+#endif
+
+#ifdef __ARM_ARCH_4T__
+		__asm__(" .align 4 ");
+		__asm__(" nop ");
+		data = R_REG(&pi->regs->phy4wdatalo);
+#else
+		data = R_REG(&pi->regs->phy4wdatalo);
+#endif
+
+	}
+	pi->phy_wreg = 0;
+
+	return data;
+}
+
+void write_radio_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if ((D11REV_GE(pi->sh->corerev, 24)) ||
+	    (D11REV_IS(pi->sh->corerev, 22)
+	     && (pi->pubpi.phy_type != PHY_TYPE_SSN))) {
+
+		W_REG(&pi->regs->radioregaddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		W_REG(&pi->regs->radioregdata, val);
+	} else {
+		W_REG(&pi->regs->phy4waddr, addr);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->phy4waddr);
+#endif
+		W_REG(&pi->regs->phy4wdatalo, val);
+	}
+
+	if (pi->sh->bustype == PCI_BUS) {
+		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+			(void)R_REG(&pi->regs->maccontrol);
+			pi->phy_wreg = 0;
+		}
+	}
+}
+
+static u32 read_radio_id(phy_info_t *pi)
+{
+	u32 id;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return NORADIO_IDCODE;
+
+	if (D11REV_GE(pi->sh->corerev, 24)) {
+		u32 b0, b1, b2;
+
+		W_REG(&pi->regs->radioregaddr, 0);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		b0 = (u32) R_REG(&pi->regs->radioregdata);
+		W_REG(&pi->regs->radioregaddr, 1);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		b1 = (u32) R_REG(&pi->regs->radioregdata);
+		W_REG(&pi->regs->radioregaddr, 2);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->radioregaddr);
+#endif
+		b2 = (u32) R_REG(&pi->regs->radioregdata);
+
+		id = ((b0 & 0xf) << 28) | (((b2 << 8) | b1) << 12) | ((b0 >> 4)
+								      & 0xf);
+	} else {
+		W_REG(&pi->regs->phy4waddr, RADIO_IDCODE);
+#ifdef __mips__
+		(void)R_REG(&pi->regs->phy4waddr);
+#endif
+		id = (u32) R_REG(&pi->regs->phy4wdatalo);
+		id |= (u32) R_REG(&pi->regs->phy4wdatahi) << 16;
+	}
+	pi->phy_wreg = 0;
+	return id;
+}
+
+void and_radio_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & val));
+}
+
+void or_radio_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval | val));
+}
+
+void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval ^ mask));
+}
+
+void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
+{
+	u16 rval;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	rval = read_radio_reg(pi, addr);
+	write_radio_reg(pi, addr, (rval & ~mask) | (val & mask));
+}
+
+void write_phy_channel_reg(phy_info_t *pi, uint val)
+{
+	W_REG(&pi->regs->phychannel, val);
+}
+
+#if defined(BCMDBG)
+static bool wlc_phy_war41476(phy_info_t *pi)
+{
+	u32 mc = R_REG(&pi->regs->maccontrol);
+
+	return ((mc & MCTL_EN_MAC) == 0)
+	    || ((mc & MCTL_PHYLOCK) == MCTL_PHYLOCK);
+}
+#endif
+
+u16 read_phy_reg(phy_info_t *pi, u16 addr)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	pi->phy_wreg = 0;
+	return R_REG(&regs->phyregdata);
+}
+
+void write_phy_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+#ifdef __mips__
+	W_REG(&regs->phyregaddr, addr);
+	(void)R_REG(&regs->phyregaddr);
+	W_REG(&regs->phyregdata, val);
+	if (addr == 0x72)
+		(void)R_REG(&regs->phyregdata);
+#else
+	W_REG((u32 *)(&regs->phyregaddr),
+	      addr | (val << 16));
+	if (pi->sh->bustype == PCI_BUS) {
+		if (++pi->phy_wreg >= pi->phy_wreg_limit) {
+			pi->phy_wreg = 0;
+			(void)R_REG(&regs->phyversion);
+		}
+	}
+#endif
+}
+
+void and_phy_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) & val));
+	pi->phy_wreg = 0;
+}
+
+void or_phy_reg(phy_info_t *pi, u16 addr, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	W_REG(&regs->phyregdata, (R_REG(&regs->phyregdata) | val));
+	pi->phy_wreg = 0;
+}
+
+void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val)
+{
+	d11regs_t *regs;
+
+	regs = pi->regs;
+
+	W_REG(&regs->phyregaddr, addr);
+#ifdef __mips__
+	(void)R_REG(&regs->phyregaddr);
+#endif
+
+	ASSERT(!
+	       (D11REV_IS(pi->sh->corerev, 11)
+		|| D11REV_IS(pi->sh->corerev, 12)) || wlc_phy_war41476(pi));
+
+	W_REG(&regs->phyregdata,
+	      ((R_REG(&regs->phyregdata) & ~mask) | (val & mask)));
+	pi->phy_wreg = 0;
+}
+
+static void WLBANDINITFN(wlc_set_phy_uninitted) (phy_info_t *pi)
+{
+	int i, j;
+
+	pi->initialized = false;
+
+	pi->tx_vos = 0xffff;
+	pi->nrssi_table_delta = 0x7fffffff;
+	pi->rc_cal = 0xffff;
+	pi->mintxbias = 0xffff;
+	pi->txpwridx = -1;
+	if (ISNPHY(pi)) {
+		pi->phy_spuravoid = SPURAVOID_DISABLE;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7))
+			pi->phy_spuravoid = SPURAVOID_AUTO;
+
+		pi->nphy_papd_skip = 0;
+		pi->nphy_papd_epsilon_offset[0] = 0xf588;
+		pi->nphy_papd_epsilon_offset[1] = 0xf588;
+		pi->nphy_txpwr_idx[0] = 128;
+		pi->nphy_txpwr_idx[1] = 128;
+		pi->nphy_txpwrindex[0].index_internal = 40;
+		pi->nphy_txpwrindex[1].index_internal = 40;
+		pi->phy_pabias = 0;
+	} else {
+		pi->phy_spuravoid = SPURAVOID_AUTO;
+	}
+	pi->radiopwr = 0xffff;
+	for (i = 0; i < STATIC_NUM_RF; i++) {
+		for (j = 0; j < STATIC_NUM_BB; j++) {
+			pi->stats_11b_txpower[i][j] = -1;
+		}
+	}
+}
+
+shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp)
+{
+	shared_phy_t *sh;
+
+	sh = kzalloc(sizeof(shared_phy_t), GFP_ATOMIC);
+	if (sh == NULL) {
+		return NULL;
+	}
+
+	sh->sih = shp->sih;
+	sh->physhim = shp->physhim;
+	sh->unit = shp->unit;
+	sh->corerev = shp->corerev;
+
+	sh->vid = shp->vid;
+	sh->did = shp->did;
+	sh->chip = shp->chip;
+	sh->chiprev = shp->chiprev;
+	sh->chippkg = shp->chippkg;
+	sh->sromrev = shp->sromrev;
+	sh->boardtype = shp->boardtype;
+	sh->boardrev = shp->boardrev;
+	sh->boardvendor = shp->boardvendor;
+	sh->boardflags = shp->boardflags;
+	sh->boardflags2 = shp->boardflags2;
+	sh->bustype = shp->bustype;
+	sh->buscorerev = shp->buscorerev;
+
+	sh->fast_timer = PHY_SW_TIMER_FAST;
+	sh->slow_timer = PHY_SW_TIMER_SLOW;
+	sh->glacial_timer = PHY_SW_TIMER_GLACIAL;
+
+	sh->rssi_mode = RSSI_ANT_MERGE_MAX;
+
+	return sh;
+}
+
+void wlc_phy_shared_detach(shared_phy_t *phy_sh)
+{
+	if (phy_sh) {
+		if (phy_sh->phy_head) {
+			ASSERT(!phy_sh->phy_head);
+		}
+		kfree(phy_sh);
+	}
+}
+
+wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype, char *vars)
+{
+	phy_info_t *pi;
+	u32 sflags = 0;
+	uint phyversion;
+	int i;
+
+	if (D11REV_IS(sh->corerev, 4))
+		sflags = SISF_2G_PHY | SISF_5G_PHY;
+	else
+		sflags = si_core_sflags(sh->sih, 0, 0);
+
+	if (BAND_5G(bandtype)) {
+		if ((sflags & (SISF_5G_PHY | SISF_DB_PHY)) == 0) {
+			return NULL;
+		}
+	}
+
+	pi = sh->phy_head;
+	if ((sflags & SISF_DB_PHY) && pi) {
+
+		wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+		pi->refcnt++;
+		return &pi->pubpi_ro;
+	}
+
+	pi = kzalloc(sizeof(phy_info_t), GFP_ATOMIC);
+	if (pi == NULL) {
+		return NULL;
+	}
+	pi->regs = (d11regs_t *) regs;
+	pi->sh = sh;
+	pi->phy_init_por = true;
+	pi->phy_wreg_limit = PHY_WREG_LIMIT;
+
+	pi->vars = vars;
+
+	pi->txpwr_percent = 100;
+
+	pi->do_initcal = true;
+
+	pi->phycal_tempdelta = 0;
+
+	if (BAND_2G(bandtype) && (sflags & SISF_2G_PHY)) {
+
+		pi->pubpi.coreflags = SICF_GMODE;
+	}
+
+	wlapi_bmac_corereset(pi->sh->physhim, pi->pubpi.coreflags);
+	phyversion = R_REG(&pi->regs->phyversion);
+
+	pi->pubpi.phy_type = PHY_TYPE(phyversion);
+	pi->pubpi.phy_rev = phyversion & PV_PV_MASK;
+
+	if (pi->pubpi.phy_type == PHY_TYPE_LCNXN) {
+		pi->pubpi.phy_type = PHY_TYPE_N;
+		pi->pubpi.phy_rev += LCNXN_BASEREV;
+	}
+	pi->pubpi.phy_corenum = PHY_CORE_NUM_2;
+	pi->pubpi.ana_rev = (phyversion & PV_AV_MASK) >> PV_AV_SHIFT;
+
+	if (!VALID_PHYTYPE(pi->pubpi.phy_type)) {
+		goto err;
+	}
+	if (BAND_5G(bandtype)) {
+		if (!ISNPHY(pi)) {
+			goto err;
+		}
+	} else {
+		if (!ISNPHY(pi) && !ISLCNPHY(pi)) {
+			goto err;
+		}
+	}
+
+	if (ISSIM_ENAB(pi->sh->sih)) {
+		pi->pubpi.radioid = NORADIO_ID;
+		pi->pubpi.radiorev = 5;
+	} else {
+		u32 idcode;
+
+		wlc_phy_anacore((wlc_phy_t *) pi, ON);
+
+		idcode = wlc_phy_get_radio_ver(pi);
+		pi->pubpi.radioid =
+		    (idcode & IDCODE_ID_MASK) >> IDCODE_ID_SHIFT;
+		pi->pubpi.radiorev =
+		    (idcode & IDCODE_REV_MASK) >> IDCODE_REV_SHIFT;
+		pi->pubpi.radiover =
+		    (idcode & IDCODE_VER_MASK) >> IDCODE_VER_SHIFT;
+		if (!VALID_RADIO(pi, pi->pubpi.radioid)) {
+			goto err;
+		}
+
+		wlc_phy_switch_radio((wlc_phy_t *) pi, OFF);
+	}
+
+	wlc_set_phy_uninitted(pi);
+
+	pi->bw = WL_CHANSPEC_BW_20;
+	pi->radio_chanspec =
+	    BAND_2G(bandtype) ? CH20MHZ_CHSPEC(1) : CH20MHZ_CHSPEC(36);
+
+	pi->rxiq_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+	pi->rxiq_antsel = ANT_RX_DIV_DEF;
+
+	pi->watchdog_override = true;
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+
+	pi->nphy_saved_noisevars.bufcount = 0;
+
+	if (ISNPHY(pi))
+		pi->min_txpower = PHY_TXPWR_MIN_NPHY;
+	else
+		pi->min_txpower = PHY_TXPWR_MIN;
+
+	pi->sh->phyrxchain = 0x3;
+
+	pi->rx2tx_biasentry = -1;
+
+	pi->phy_txcore_disable_temp = PHY_CHAIN_TX_DISABLE_TEMP;
+	pi->phy_txcore_enable_temp =
+	    PHY_CHAIN_TX_DISABLE_TEMP - PHY_HYSTERESIS_DELTATEMP;
+	pi->phy_tempsense_offset = 0;
+	pi->phy_txcore_heatedup = false;
+
+	pi->nphy_lastcal_temp = -50;
+
+	pi->phynoise_polling = true;
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		pi->phynoise_polling = false;
+
+	for (i = 0; i < TXP_NUM_RATES; i++) {
+		pi->txpwr_limit[i] = WLC_TXPWR_MAX;
+		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
+		pi->tx_user_target[i] = WLC_TXPWR_MAX;
+	}
+
+	pi->radiopwr_override = RADIOPWR_OVERRIDE_DEF;
+
+	pi->user_txpwr_at_rfport = false;
+
+	if (ISNPHY(pi)) {
+
+		pi->phycal_timer = wlapi_init_timer(pi->sh->physhim,
+							  wlc_phy_timercb_phycal,
+							  pi, "phycal");
+		if (!pi->phycal_timer) {
+			goto err;
+		}
+
+		if (!wlc_phy_attach_nphy(pi))
+			goto err;
+
+	} else if (ISLCNPHY(pi)) {
+		if (!wlc_phy_attach_lcnphy(pi))
+			goto err;
+
+	} else {
+
+	}
+
+	pi->refcnt++;
+	pi->next = pi->sh->phy_head;
+	sh->phy_head = pi;
+
+	pi->vars = (char *)&pi->vars;
+
+	memcpy(&pi->pubpi_ro, &pi->pubpi, sizeof(wlc_phy_t));
+
+	return &pi->pubpi_ro;
+
+ err:
+	kfree(pi);
+	return NULL;
+}
+
+void wlc_phy_detach(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (pih) {
+		if (--pi->refcnt) {
+			return;
+		}
+
+		if (pi->phycal_timer) {
+			wlapi_free_timer(pi->sh->physhim, pi->phycal_timer);
+			pi->phycal_timer = NULL;
+		}
+
+		if (pi->sh->phy_head == pi)
+			pi->sh->phy_head = pi->next;
+		else if (pi->sh->phy_head->next == pi)
+			pi->sh->phy_head->next = NULL;
+		else
+			ASSERT(0);
+
+		if (pi->pi_fptr.detach)
+			(pi->pi_fptr.detach) (pi);
+
+		kfree(pi);
+	}
+}
+
+bool
+wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype, u16 *phyrev,
+		       u16 *radioid, u16 *radiover)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	*phytype = (u16) pi->pubpi.phy_type;
+	*phyrev = (u16) pi->pubpi.phy_rev;
+	*radioid = pi->pubpi.radioid;
+	*radiover = pi->pubpi.radiorev;
+
+	return true;
+}
+
+bool wlc_phy_get_encore(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	return pi->pubpi.abgphy_encore;
+}
+
+u32 wlc_phy_get_coreflags(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	return pi->pubpi.coreflags;
+}
+
+static void wlc_phy_timercb_phycal(void *arg)
+{
+	phy_info_t *pi = (phy_info_t *) arg;
+	uint delay = 5;
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		if (!pi->sh->up) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+			return;
+		}
+
+		if (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)) {
+
+			delay = 1000;
+			wlc_phy_cal_perical_mphase_restart(pi);
+		} else
+			wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_AUTO);
+		wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+		return;
+	}
+
+}
+
+void wlc_phy_anacore(wlc_phy_t *pih, bool on)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (ISNPHY(pi)) {
+		if (on) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0xa6, 0x0d);
+				write_phy_reg(pi, 0x8f, 0x0);
+				write_phy_reg(pi, 0xa7, 0x0d);
+				write_phy_reg(pi, 0xa5, 0x0);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x0);
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				write_phy_reg(pi, 0x8f, 0x07ff);
+				write_phy_reg(pi, 0xa6, 0x0fd);
+				write_phy_reg(pi, 0xa5, 0x07ff);
+				write_phy_reg(pi, 0xa7, 0x0fd);
+			} else {
+				write_phy_reg(pi, 0xa5, 0x7fff);
+			}
+		}
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x43b,
+				    ~((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+		} else {
+			or_phy_reg(pi, 0x43c,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+			or_phy_reg(pi, 0x43b,
+				   (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+		}
+	}
+}
+
+u32 wlc_phy_clk_bwbits(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	u32 phy_bw_clkbits = 0;
+
+	if (pi && (ISNPHY(pi) || ISLCNPHY(pi))) {
+		switch (pi->bw) {
+		case WL_CHANSPEC_BW_10:
+			phy_bw_clkbits = SICF_BW10;
+			break;
+		case WL_CHANSPEC_BW_20:
+			phy_bw_clkbits = SICF_BW20;
+			break;
+		case WL_CHANSPEC_BW_40:
+			phy_bw_clkbits = SICF_BW40;
+			break;
+		default:
+			ASSERT(0);
+			break;
+		}
+	}
+
+	return phy_bw_clkbits;
+}
+
+void WLBANDINITFN(wlc_phy_por_inform) (wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->phy_init_por = true;
+}
+
+void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->edcrs_threshold_lock = lock;
+
+	write_phy_reg(pi, 0x22c, 0x46b);
+	write_phy_reg(pi, 0x22d, 0x46b);
+	write_phy_reg(pi, 0x22e, 0x3c0);
+	write_phy_reg(pi, 0x22f, 0x3c0);
+}
+
+void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->do_initcal = initcal;
+}
+
+void wlc_phy_hw_clk_state_upd(wlc_phy_t *pih, bool newstate)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->clk = newstate;
+}
+
+void wlc_phy_hw_state_upd(wlc_phy_t *pih, bool newstate)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (!pi || !pi->sh)
+		return;
+
+	pi->sh->up = newstate;
+}
+
+void WLBANDINITFN(wlc_phy_init) (wlc_phy_t *pih, chanspec_t chanspec)
+{
+	u32 mc;
+	initfn_t phy_init = NULL;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (pi->init_in_progress)
+		return;
+
+	pi->init_in_progress = true;
+
+	pi->radio_chanspec = chanspec;
+
+	mc = R_REG(&pi->regs->maccontrol);
+	if ((mc & MCTL_EN_MAC) != 0) {
+		ASSERT((const char *)
+		       "wlc_phy_init: Called with the MAC running!" == NULL);
+	}
+
+	ASSERT(pi != NULL);
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+	}
+
+	if (D11REV_GE(pi->sh->corerev, 5))
+		ASSERT(si_core_sflags(pi->sh->sih, 0, 0) & SISF_FCLKA);
+
+	phy_init = pi->pi_fptr.init;
+
+	if (phy_init == NULL) {
+		ASSERT(phy_init != NULL);
+		return;
+	}
+
+	wlc_phy_anacore(pih, ON);
+
+	if (CHSPEC_BW(pi->radio_chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim,
+				  CHSPEC_BW(pi->radio_chanspec));
+
+	pi->nphy_gain_boost = true;
+
+	wlc_phy_switch_radio((wlc_phy_t *) pi, ON);
+
+	(*phy_init) (pi);
+
+	pi->phy_init_por = false;
+
+	if (D11REV_IS(pi->sh->corerev, 11) || D11REV_IS(pi->sh->corerev, 12))
+		wlc_phy_do_dummy_tx(pi, true, OFF);
+
+	if (!(ISNPHY(pi)))
+		wlc_phy_txpower_update_shm(pi);
+
+	wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi, pi->sh->rx_antdiv);
+
+	pi->init_in_progress = false;
+}
+
+void wlc_phy_cal_init(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	initfn_t cal_init = NULL;
+
+	ASSERT((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) == 0);
+
+	if (!pi->initialized) {
+		cal_init = pi->pi_fptr.calinit;
+		if (cal_init)
+			(*cal_init) (pi);
+
+		pi->initialized = true;
+	}
+}
+
+int wlc_phy_down(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	int callbacks = 0;
+
+	ASSERT(pi->phytest_on == false);
+
+	if (pi->phycal_timer
+	    && !wlapi_del_timer(pi->sh->physhim, pi->phycal_timer))
+		callbacks++;
+
+	pi->nphy_iqcal_chanspec_2G = 0;
+	pi->nphy_iqcal_chanspec_5G = 0;
+
+	return callbacks;
+}
+
+static u32 wlc_phy_get_radio_ver(phy_info_t *pi)
+{
+	u32 ver;
+
+	ver = read_radio_id(pi);
+
+	return ver;
+}
+
+void
+wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	pi->tbl_data_hi = tblDataHi;
+	pi->tbl_data_lo = tblDataLo;
+
+	if ((pi->sh->chip == BCM43224_CHIP_ID ||
+	     pi->sh->chip == BCM43421_CHIP_ID) &&
+	    (pi->sh->chiprev == 1)) {
+		pi->tbl_addr = tblAddr;
+		pi->tbl_save_id = tbl_id;
+		pi->tbl_save_offset = tbl_offset;
+	}
+}
+
+void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val)
+{
+	ASSERT((width == 8) || (width == 16) || (width == 32));
+
+	if ((pi->sh->chip == BCM43224_CHIP_ID ||
+	     pi->sh->chip == BCM43421_CHIP_ID) &&
+	    (pi->sh->chiprev == 1) &&
+	    (pi->tbl_save_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+		read_phy_reg(pi, pi->tbl_data_lo);
+
+		write_phy_reg(pi, pi->tbl_addr,
+			      (pi->tbl_save_id << 10) | pi->tbl_save_offset);
+		pi->tbl_save_offset++;
+	}
+
+	if (width == 32) {
+
+		write_phy_reg(pi, pi->tbl_data_hi, (u16) (val >> 16));
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	} else {
+
+		write_phy_reg(pi, pi->tbl_data_lo, (u16) val);
+	}
+}
+
+void
+wlc_phy_write_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
+		    u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	const u8 *ptbl_8b = (const u8 *)ptbl_info->tbl_ptr;
+	const u16 *ptbl_16b = (const u16 *)ptbl_info->tbl_ptr;
+	const u32 *ptbl_32b = (const u32 *)ptbl_info->tbl_ptr;
+
+	ASSERT((tbl_width == 8) || (tbl_width == 16) || (tbl_width == 32));
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID ||
+		     pi->sh->chip == BCM43421_CHIP_ID) &&
+		    (pi->sh->chiprev == 1) &&
+		    (tbl_id == NPHY_TBL_ID_ANTSWCTRLLUT)) {
+			read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+
+			write_phy_reg(pi, tblDataHi,
+				      (u16) (ptbl_32b[idx] >> 16));
+			write_phy_reg(pi, tblDataLo, (u16) ptbl_32b[idx]);
+		} else if (tbl_width == 16) {
+
+			write_phy_reg(pi, tblDataLo, ptbl_16b[idx]);
+		} else {
+
+			write_phy_reg(pi, tblDataLo, ptbl_8b[idx]);
+		}
+	}
+}
+
+void
+wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
+		   u16 tblAddr, u16 tblDataHi, u16 tblDataLo)
+{
+	uint idx;
+	uint tbl_id = ptbl_info->tbl_id;
+	uint tbl_offset = ptbl_info->tbl_offset;
+	uint tbl_width = ptbl_info->tbl_width;
+	u8 *ptbl_8b = (u8 *)ptbl_info->tbl_ptr;
+	u16 *ptbl_16b = (u16 *)ptbl_info->tbl_ptr;
+	u32 *ptbl_32b = (u32 *)ptbl_info->tbl_ptr;
+
+	ASSERT((tbl_width == 8) || (tbl_width == 16) || (tbl_width == 32));
+
+	write_phy_reg(pi, tblAddr, (tbl_id << 10) | tbl_offset);
+
+	for (idx = 0; idx < ptbl_info->tbl_len; idx++) {
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID ||
+		     pi->sh->chip == BCM43421_CHIP_ID) &&
+		    (pi->sh->chiprev == 1)) {
+			(void)read_phy_reg(pi, tblDataLo);
+
+			write_phy_reg(pi, tblAddr,
+				      (tbl_id << 10) | (tbl_offset + idx));
+		}
+
+		if (tbl_width == 32) {
+
+			ptbl_32b[idx] = read_phy_reg(pi, tblDataLo);
+			ptbl_32b[idx] |= (read_phy_reg(pi, tblDataHi) << 16);
+		} else if (tbl_width == 16) {
+
+			ptbl_16b[idx] = read_phy_reg(pi, tblDataLo);
+		} else {
+
+			ptbl_8b[idx] = (u8) read_phy_reg(pi, tblDataLo);
+		}
+	}
+}
+
+uint
+wlc_phy_init_radio_regs_allbands(phy_info_t *pi, radio_20xx_regs_t *radioregs)
+{
+	uint i = 0;
+
+	do {
+		if (radioregs[i].do_init) {
+			write_radio_reg(pi, radioregs[i].address,
+					(u16) radioregs[i].init);
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+uint
+wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
+			u16 core_offset)
+{
+	uint i = 0;
+	uint count = 0;
+
+	do {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			if (radioregs[i].do_init_a) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_a);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					WLC_PHY_WAR_PR51571(pi);
+			}
+		} else {
+			if (radioregs[i].do_init_g) {
+				write_radio_reg(pi,
+						radioregs[i].
+						address | core_offset,
+						(u16) radioregs[i].init_g);
+				if (ISNPHY(pi) && (++count % 4 == 0))
+					WLC_PHY_WAR_PR51571(pi);
+			}
+		}
+
+		i++;
+	} while (radioregs[i].address != 0xffff);
+
+	return i;
+}
+
+void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on)
+{
+#define	DUMMY_PKT_LEN	20
+	d11regs_t *regs = pi->regs;
+	int i, count;
+	u8 ofdmpkt[DUMMY_PKT_LEN] = {
+		0xcc, 0x01, 0x02, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u8 cckpkt[DUMMY_PKT_LEN] = {
+		0x6e, 0x84, 0x0b, 0x00, 0x00, 0x00, 0xd4, 0x00, 0x00, 0x00,
+		0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00
+	};
+	u32 *dummypkt;
+
+	ASSERT((R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) == 0);
+
+	dummypkt = (u32 *) (ofdm ? ofdmpkt : cckpkt);
+	wlapi_bmac_write_template_ram(pi->sh->physhim, 0, DUMMY_PKT_LEN,
+				      dummypkt);
+
+	W_REG(&regs->xmtsel, 0);
+
+	if (D11REV_GE(pi->sh->corerev, 11))
+		W_REG(&regs->wepctl, 0x100);
+	else
+		W_REG(&regs->wepctl, 0);
+
+	W_REG(&regs->txe_phyctl, (ofdm ? 1 : 0) | PHY_TXC_ANT_0);
+	if (ISNPHY(pi) || ISLCNPHY(pi)) {
+		ASSERT(ofdm);
+		W_REG(&regs->txe_phyctl1, 0x1A02);
+	}
+
+	W_REG(&regs->txe_wm_0, 0);
+	W_REG(&regs->txe_wm_1, 0);
+
+	W_REG(&regs->xmttplatetxptr, 0);
+	W_REG(&regs->xmttxcnt, DUMMY_PKT_LEN);
+
+	W_REG(&regs->xmtsel, ((8 << 8) | (1 << 5) | (1 << 2) | 2));
+
+	W_REG(&regs->txe_ctl, 0);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, OFF);
+	}
+
+	if (ISNPHY(pi) || ISLCNPHY(pi))
+		W_REG(&regs->txe_aux, 0xD0);
+	else
+		W_REG(&regs->txe_aux, ((1 << 5) | (1 << 4)));
+
+	(void)R_REG(&regs->txe_aux);
+
+	i = 0;
+	count = ofdm ? 30 : 250;
+
+	if (ISSIM_ENAB(pi->sh->sih)) {
+		count *= 100;
+	}
+
+	while ((i++ < count)
+	       && (R_REG(&regs->txe_status) & (1 << 7))) {
+		udelay(10);
+	}
+
+	i = 0;
+
+	while ((i++ < 10)
+	       && ((R_REG(&regs->txe_status) & (1 << 10)) == 0)) {
+		udelay(10);
+	}
+
+	i = 0;
+
+	while ((i++ < 10) && ((R_REG(&regs->ifsstat) & (1 << 8))))
+		udelay(10);
+
+	if (!pa_on) {
+		if (ISNPHY(pi))
+			wlc_phy_pa_override_nphy(pi, ON);
+	}
+}
+
+void wlc_phy_hold_upd(wlc_phy_t *pih, mbool id, bool set)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	ASSERT(id);
+
+	if (set) {
+		mboolset(pi->measure_hold, id);
+	} else {
+		mboolclr(pi->measure_hold, id);
+	}
+
+	return;
+}
+
+void wlc_phy_mute_upd(wlc_phy_t *pih, bool mute, mbool flags)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (mute) {
+		mboolset(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	} else {
+		mboolclr(pi->measure_hold, PHY_HOLD_FOR_MUTE);
+	}
+
+	if (!mute && (flags & PHY_MUTE_FOR_PREISM))
+		pi->nphy_perical_last = pi->sh->now - pi->sh->glacial_timer;
+	return;
+}
+
+void wlc_phy_clear_tssi(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (ISNPHY(pi)) {
+		return;
+	} else {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_B_TSSI_1, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_0, NULL_TSSI_W);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_G_TSSI_1, NULL_TSSI_W);
+	}
+}
+
+static bool wlc_phy_cal_txpower_recalc_sw(phy_info_t *pi)
+{
+	return false;
+}
+
+void wlc_phy_switch_radio(wlc_phy_t *pih, bool on)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	{
+		uint mc;
+
+		mc = R_REG(&pi->regs->maccontrol);
+	}
+
+	if (ISNPHY(pi)) {
+		wlc_phy_switch_radio_nphy(pi, on);
+
+	} else if (ISLCNPHY(pi)) {
+		if (on) {
+			and_phy_reg(pi, 0x44c,
+				    ~((0x1 << 8) |
+				      (0x1 << 9) |
+				      (0x1 << 10) | (0x1 << 11) | (0x1 << 12)));
+			and_phy_reg(pi, 0x4b0, ~((0x1 << 3) | (0x1 << 11)));
+			and_phy_reg(pi, 0x4f9, ~(0x1 << 3));
+		} else {
+			and_phy_reg(pi, 0x44d,
+				    ~((0x1 << 10) |
+				      (0x1 << 11) |
+				      (0x1 << 12) | (0x1 << 13) | (0x1 << 14)));
+			or_phy_reg(pi, 0x44c,
+				   (0x1 << 8) |
+				   (0x1 << 9) |
+				   (0x1 << 10) | (0x1 << 11) | (0x1 << 12));
+
+			and_phy_reg(pi, 0x4b7, ~((0x7f << 8)));
+			and_phy_reg(pi, 0x4b1, ~((0x1 << 13)));
+			or_phy_reg(pi, 0x4b0, (0x1 << 3) | (0x1 << 11));
+			and_phy_reg(pi, 0x4fa, ~((0x1 << 3)));
+			or_phy_reg(pi, 0x4f9, (0x1 << 3));
+		}
+	}
+}
+
+u16 wlc_phy_bw_state_get(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->bw;
+}
+
+void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->bw = bw;
+}
+
+void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	pi->radio_chanspec = newch;
+
+}
+
+chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->radio_chanspec;
+}
+
+void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 m_cur_channel;
+	chansetfn_t chanspec_set = NULL;
+
+	ASSERT(!wf_chspec_malformed(chanspec));
+
+	m_cur_channel = CHSPEC_CHANNEL(chanspec);
+	if (CHSPEC_IS5G(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_5G;
+	if (CHSPEC_IS40(chanspec))
+		m_cur_channel |= D11_CURCHANNEL_40;
+	wlapi_bmac_write_shm(pi->sh->physhim, M_CURCHANNEL, m_cur_channel);
+
+	chanspec_set = pi->pi_fptr.chanset;
+	if (chanspec_set)
+		(*chanspec_set) (pi, chanspec);
+
+}
+
+int wlc_phy_chanspec_freq2bandrange_lpssn(uint freq)
+{
+	int range = -1;
+
+	if (freq < 2500)
+		range = WL_CHAN_FREQ_RANGE_2G;
+	else if (freq <= 5320)
+		range = WL_CHAN_FREQ_RANGE_5GL;
+	else if (freq <= 5700)
+		range = WL_CHAN_FREQ_RANGE_5GM;
+	else
+		range = WL_CHAN_FREQ_RANGE_5GH;
+
+	return range;
+}
+
+int wlc_phy_chanspec_bandrange_get(phy_info_t *pi, chanspec_t chanspec)
+{
+	int range = -1;
+	uint channel = CHSPEC_CHANNEL(chanspec);
+	uint freq = wlc_phy_channel2freq(channel);
+
+	if (ISNPHY(pi)) {
+		range = wlc_phy_get_chan_freq_range_nphy(pi, channel);
+	} else if (ISLCNPHY(pi)) {
+		range = wlc_phy_chanspec_freq2bandrange_lpssn(freq);
+	} else
+		ASSERT(0);
+
+	return range;
+}
+
+void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi, bool wide_filter)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->channel_14_wide_filter = wide_filter;
+
+}
+
+int wlc_phy_channel2freq(uint channel)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++)
+		if (chan_info_all[i].chan == channel)
+			return chan_info_all[i].freq;
+	return 0;
+}
+
+void
+wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band, chanvec_t *channels)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint i;
+	uint channel;
+
+	ASSERT((band == WLC_BAND_2G) || (band == WLC_BAND_5G));
+
+	memset(channels, 0, sizeof(chanvec_t));
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
+		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
+			setbit(channels->vec, channel);
+	}
+}
+
+chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint i;
+	uint channel;
+	chanspec_t chspec;
+
+	ASSERT((band == WLC_BAND_2G) || (band == WLC_BAND_5G));
+
+	for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+		channel = chan_info_all[i].chan;
+
+		if (ISNPHY(pi) && IS40MHZ(pi)) {
+			uint j;
+
+			for (j = 0; j < ARRAY_SIZE(chan_info_all); j++) {
+				if (chan_info_all[j].chan ==
+				    channel + CH_10MHZ_APART)
+					break;
+			}
+
+			if (j == ARRAY_SIZE(chan_info_all))
+				continue;
+
+			channel = UPPER_20_SB(channel);
+			chspec =
+			    channel | WL_CHANSPEC_BW_40 |
+			    WL_CHANSPEC_CTL_SB_LOWER;
+			if (band == WLC_BAND_2G)
+				chspec |= WL_CHANSPEC_BAND_2G;
+			else
+				chspec |= WL_CHANSPEC_BAND_5G;
+		} else
+			chspec = CH20MHZ_CHSPEC(channel);
+
+		if ((pi->a_band_high_disable) && (channel >= FIRST_REF5_CHANNUM)
+		    && (channel <= LAST_REF5_CHANNUM))
+			continue;
+
+		if (((band == WLC_BAND_2G) && (channel <= CH_MAX_2G_CHANNEL)) ||
+		    ((band == WLC_BAND_5G) && (channel > CH_MAX_2G_CHANNEL)))
+			return chspec;
+	}
+
+	ASSERT(0);
+
+	return (chanspec_t) INVCHANSPEC;
+}
+
+int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	ASSERT(qdbm != NULL);
+	*qdbm = pi->tx_user_target[0];
+	if (override != NULL)
+		*override = pi->txpwroverride;
+	return 0;
+}
+
+void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr)
+{
+	bool mac_enabled = false;
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_CCK],
+	       &txpwr->cck[0], WLC_NUM_RATES_CCK);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM],
+	       &txpwr->ofdm[0], WLC_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_20_CDD],
+	       &txpwr->ofdm_cdd[0], WLC_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_SISO],
+	       &txpwr->ofdm_40_siso[0], WLC_NUM_RATES_OFDM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_OFDM_40_CDD],
+	       &txpwr->ofdm_40_cdd[0], WLC_NUM_RATES_OFDM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SISO],
+	       &txpwr->mcs_20_siso[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_CDD],
+	       &txpwr->mcs_20_cdd[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_STBC],
+	       &txpwr->mcs_20_stbc[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_20_SDM],
+	       &txpwr->mcs_20_mimo[0], WLC_NUM_RATES_MCS_2_STREAM);
+
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SISO],
+	       &txpwr->mcs_40_siso[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_CDD],
+	       &txpwr->mcs_40_cdd[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_STBC],
+	       &txpwr->mcs_40_stbc[0], WLC_NUM_RATES_MCS_1_STREAM);
+	memcpy(&pi->tx_user_target[TXP_FIRST_MCS_40_SDM],
+	       &txpwr->mcs_40_mimo[0], WLC_NUM_RATES_MCS_2_STREAM);
+
+	if (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC)
+		mac_enabled = true;
+
+	if (mac_enabled)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+
+	if (mac_enabled)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	int i;
+
+	if (qdbm > 127)
+		return 5;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->tx_user_target[i] = (u8) qdbm;
+
+	pi->txpwroverride = false;
+
+	if (pi->sh->up) {
+		if (!SCAN_INPROG_PHY(pi)) {
+			bool suspend;
+
+			suspend =
+			    (0 ==
+			     (R_REG(&pi->regs->maccontrol) &
+			      MCTL_EN_MAC));
+
+			if (!suspend)
+				wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+			wlc_phy_txpower_recalc_target(pi);
+			wlc_phy_cal_txpower_recalc_sw(pi);
+
+			if (!suspend)
+				wlapi_enable_mac(pi->sh->physhim);
+		}
+	}
+	return 0;
+}
+
+void
+wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint channel, u8 *min_pwr,
+			  u8 *max_pwr, int txp_rate_idx)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint i;
+
+	*min_pwr = pi->min_txpower * WLC_TXPWR_DB_FACTOR;
+
+	if (ISNPHY(pi)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		wlc_phy_txpower_sromlimit_get_nphy(pi, channel, max_pwr,
+						   (u8) txp_rate_idx);
+
+	} else if ((channel <= CH_MAX_2G_CHANNEL)) {
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_CCK;
+		*max_pwr = pi->tx_srom_max_rate_2g[txp_rate_idx];
+	} else {
+
+		*max_pwr = WLC_TXPWR_MAX;
+
+		if (txp_rate_idx < 0)
+			txp_rate_idx = TXP_FIRST_OFDM;
+
+		for (i = 0; i < ARRAY_SIZE(chan_info_all); i++) {
+			if (channel == chan_info_all[i].chan) {
+				break;
+			}
+		}
+		ASSERT(i < ARRAY_SIZE(chan_info_all));
+
+		if (pi->hwtxpwr) {
+			*max_pwr = pi->hwtxpwr[i];
+		} else {
+
+			if ((i >= FIRST_MID_5G_CHAN) && (i <= LAST_MID_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_mid[txp_rate_idx];
+			if ((i >= FIRST_HIGH_5G_CHAN)
+			    && (i <= LAST_HIGH_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_hi[txp_rate_idx];
+			if ((i >= FIRST_LOW_5G_CHAN) && (i <= LAST_LOW_5G_CHAN))
+				*max_pwr =
+				    pi->tx_srom_max_rate_5g_low[txp_rate_idx];
+		}
+	}
+}
+
+void
+wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan, u8 *max_txpwr,
+				  u8 *min_txpwr)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 max_num_rate;
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+
+	pactrl = 0;
+
+	max_num_rate = ISNPHY(pi) ? TXP_NUM_RATES :
+	    ISLCNPHY(pi) ? (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1);
+
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		wlc_phy_txpower_sromlimit(ppi, chan, &mintxpwr, &maxtxpwr,
+					  rate);
+
+		maxtxpwr = (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+		maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+		tx_pwr_max = max(tx_pwr_max, maxtxpwr);
+		tx_pwr_min = min(tx_pwr_min, maxtxpwr);
+	}
+	*max_txpwr = tx_pwr_max;
+	*min_txpwr = tx_pwr_min;
+}
+
+void
+wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint bandunit, s32 *max_pwr,
+				s32 *min_pwr, u32 *step_pwr)
+{
+	return;
+}
+
+u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->tx_power_min;
+}
+
+u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->tx_power_max;
+}
+
+void wlc_phy_txpower_recalc_target(phy_info_t *pi)
+{
+	u8 maxtxpwr, mintxpwr, rate, pactrl;
+	uint target_chan;
+	u8 tx_pwr_target[TXP_NUM_RATES];
+	u8 tx_pwr_max = 0;
+	u8 tx_pwr_min = 255;
+	u8 tx_pwr_max_rate_ind = 0;
+	u8 max_num_rate;
+	u8 start_rate = 0;
+	chanspec_t chspec;
+	u32 band = CHSPEC2WLC_BAND(pi->radio_chanspec);
+	initfn_t txpwr_recalc_fn = NULL;
+
+	chspec = pi->radio_chanspec;
+	if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_NONE)
+		target_chan = CHSPEC_CHANNEL(chspec);
+	else if (CHSPEC_CTL_SB(chspec) == WL_CHANSPEC_CTL_SB_UPPER)
+		target_chan = UPPER_20_SB(CHSPEC_CHANNEL(chspec));
+	else
+		target_chan = LOWER_20_SB(CHSPEC_CHANNEL(chspec));
+
+	pactrl = 0;
+	if (ISLCNPHY(pi)) {
+		u32 offset_mcs, i;
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			offset_mcs = pi->mcs40_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+				    pi->tx_srom_max_2g -
+				    ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		} else {
+			offset_mcs = pi->mcs20_po;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i - 8] =
+				    pi->tx_srom_max_2g -
+				    ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+	}
+#if WL11N
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+			((ISLCNPHY(pi)) ?
+			 (TXP_LAST_SISO_MCS_20 + 1) : (TXP_LAST_OFDM + 1)));
+#else
+	max_num_rate = ((ISNPHY(pi)) ? (TXP_NUM_RATES) : (TXP_LAST_OFDM + 1));
+#endif
+
+	wlc_phy_upd_env_txpwr_rate_limits(pi, band);
+
+	for (rate = start_rate; rate < max_num_rate; rate++) {
+
+		tx_pwr_target[rate] = pi->tx_user_target[rate];
+
+		if (pi->user_txpwr_at_rfport) {
+			tx_pwr_target[rate] +=
+			    wlc_user_txpwr_antport_to_rfport(pi, target_chan,
+							     band, rate);
+		}
+
+		{
+
+			wlc_phy_txpower_sromlimit((wlc_phy_t *) pi, target_chan,
+						  &mintxpwr, &maxtxpwr, rate);
+
+			maxtxpwr = min(maxtxpwr, pi->txpwr_limit[rate]);
+
+			maxtxpwr =
+			    (maxtxpwr > pactrl) ? (maxtxpwr - pactrl) : 0;
+
+			maxtxpwr = (maxtxpwr > 6) ? (maxtxpwr - 6) : 0;
+
+			maxtxpwr = min(maxtxpwr, tx_pwr_target[rate]);
+
+			if (pi->txpwr_percent <= 100)
+				maxtxpwr = (maxtxpwr * pi->txpwr_percent) / 100;
+
+			tx_pwr_target[rate] = max(maxtxpwr, mintxpwr);
+		}
+
+		tx_pwr_target[rate] =
+		    min(tx_pwr_target[rate], pi->txpwr_env_limit[rate]);
+
+		if (tx_pwr_target[rate] > tx_pwr_max)
+			tx_pwr_max_rate_ind = rate;
+
+		tx_pwr_max = max(tx_pwr_max, tx_pwr_target[rate]);
+		tx_pwr_min = min(tx_pwr_min, tx_pwr_target[rate]);
+	}
+
+	memset(pi->tx_power_offset, 0, sizeof(pi->tx_power_offset));
+	pi->tx_power_max = tx_pwr_max;
+	pi->tx_power_min = tx_pwr_min;
+	pi->tx_power_max_rate_ind = tx_pwr_max_rate_ind;
+	for (rate = 0; rate < max_num_rate; rate++) {
+
+		pi->tx_power_target[rate] = tx_pwr_target[rate];
+
+		if (!pi->hwpwrctrl || ISNPHY(pi)) {
+			pi->tx_power_offset[rate] =
+			    pi->tx_power_max - pi->tx_power_target[rate];
+		} else {
+			pi->tx_power_offset[rate] =
+			    pi->tx_power_target[rate] - pi->tx_power_min;
+		}
+	}
+
+	txpwr_recalc_fn = pi->pi_fptr.txpwrrecalc;
+	if (txpwr_recalc_fn)
+		(*txpwr_recalc_fn) (pi);
+}
+
+void
+wlc_phy_txpower_reg_limit_calc(phy_info_t *pi, struct txpwr_limits *txpwr,
+			       chanspec_t chanspec)
+{
+	u8 tmp_txpwr_limit[2 * WLC_NUM_RATES_OFDM];
+	u8 *txpwr_ptr1 = NULL, *txpwr_ptr2 = NULL;
+	int rate_start_index = 0, rate1, rate2, k;
+
+	for (rate1 = WL_TX_POWER_CCK_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_CCK_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->cck[rate2];
+
+	for (rate1 = WL_TX_POWER_OFDM_FIRST, rate2 = 0;
+	     rate2 < WL_TX_POWER_OFDM_NUM; rate1++, rate2++)
+		pi->txpwr_limit[rate1] = txpwr->ofdm[rate2];
+
+	if (ISNPHY(pi)) {
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->mcs_20_siso;
+				txpwr_ptr2 = txpwr->ofdm;
+				rate_start_index = WL_TX_POWER_OFDM_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->mcs_20_cdd;
+				txpwr_ptr2 = txpwr->ofdm_cdd;
+				rate_start_index = WL_TX_POWER_OFDM20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->mcs_40_siso;
+				txpwr_ptr2 = txpwr->ofdm_40_siso;
+				rate_start_index =
+				    WL_TX_POWER_OFDM40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->mcs_40_cdd;
+				txpwr_ptr2 = txpwr->ofdm_40_cdd;
+				rate_start_index = WL_TX_POWER_OFDM40_CDD_FIRST;
+				break;
+			}
+
+			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
+				    txpwr_ptr1[rate2];
+			}
+			wlc_phy_mcs_to_ofdm_powers_nphy(tmp_txpwr_limit, 0,
+							WLC_NUM_RATES_OFDM - 1,
+							WLC_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_OFDM; rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+				    min(txpwr_ptr2[rate2],
+					tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 4; k++) {
+			switch (k) {
+			case 0:
+
+				txpwr_ptr1 = txpwr->ofdm;
+				txpwr_ptr2 = txpwr->mcs_20_siso;
+				rate_start_index = WL_TX_POWER_MCS20_SISO_FIRST;
+				break;
+			case 1:
+
+				txpwr_ptr1 = txpwr->ofdm_cdd;
+				txpwr_ptr2 = txpwr->mcs_20_cdd;
+				rate_start_index = WL_TX_POWER_MCS20_CDD_FIRST;
+				break;
+			case 2:
+
+				txpwr_ptr1 = txpwr->ofdm_40_siso;
+				txpwr_ptr2 = txpwr->mcs_40_siso;
+				rate_start_index = WL_TX_POWER_MCS40_SISO_FIRST;
+				break;
+			case 3:
+
+				txpwr_ptr1 = txpwr->ofdm_40_cdd;
+				txpwr_ptr2 = txpwr->mcs_40_cdd;
+				rate_start_index = WL_TX_POWER_MCS40_CDD_FIRST;
+				break;
+			}
+			for (rate2 = 0; rate2 < WLC_NUM_RATES_OFDM; rate2++) {
+				tmp_txpwr_limit[rate2] = 0;
+				tmp_txpwr_limit[WLC_NUM_RATES_OFDM + rate2] =
+				    txpwr_ptr1[rate2];
+			}
+			wlc_phy_ofdm_to_mcs_powers_nphy(tmp_txpwr_limit, 0,
+							WLC_NUM_RATES_OFDM - 1,
+							WLC_NUM_RATES_OFDM);
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] =
+				    min(txpwr_ptr2[rate2],
+					tmp_txpwr_limit[rate2]);
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_stbc;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_STBC_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_stbc;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_MCS_1_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		for (k = 0; k < 2; k++) {
+			switch (k) {
+			case 0:
+
+				rate_start_index = WL_TX_POWER_MCS20_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_20_mimo;
+				break;
+			case 1:
+
+				rate_start_index = WL_TX_POWER_MCS40_SDM_FIRST;
+				txpwr_ptr1 = txpwr->mcs_40_mimo;
+				break;
+			}
+			for (rate1 = rate_start_index, rate2 = 0;
+			     rate2 < WLC_NUM_RATES_MCS_2_STREAM;
+			     rate1++, rate2++)
+				pi->txpwr_limit[rate1] = txpwr_ptr1[rate2];
+		}
+
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] = txpwr->mcs32;
+
+		pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST] =
+		    min(pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST],
+			pi->txpwr_limit[WL_TX_POWER_MCS_32]);
+		pi->txpwr_limit[WL_TX_POWER_MCS_32] =
+		    pi->txpwr_limit[WL_TX_POWER_MCS40_CDD_FIRST];
+	}
+}
+
+void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->txpwr_percent = txpwr_percent;
+}
+
+void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->sh->machwcap = machwcap;
+}
+
+void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 rxc;
+	rxc = 0;
+
+	if (start_end == ON) {
+		if (!ISNPHY(pi))
+			return;
+
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			W_REG(&pi->regs->phyregaddr, 0xa0);
+			(void)R_REG(&pi->regs->phyregaddr);
+			rxc = R_REG(&pi->regs->phyregdata);
+			W_REG(&pi->regs->phyregdata,
+			      (0x1 << 15) | rxc);
+		}
+	} else {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)
+		    || NREV_IS(pi->pubpi.phy_rev, 4)) {
+			W_REG(&pi->regs->phyregaddr, 0xa0);
+			(void)R_REG(&pi->regs->phyregaddr);
+			W_REG(&pi->regs->phyregdata, rxc);
+		}
+
+		wlc_phy_por_inform(ppi);
+	}
+}
+
+void
+wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *txpwr,
+			  chanspec_t chanspec)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	wlc_phy_txpower_reg_limit_calc(pi, txpwr, chanspec);
+
+	if (ISLCNPHY(pi)) {
+		int i, j;
+		for (i = TXP_FIRST_OFDM_20_CDD, j = 0;
+		     j < WLC_NUM_RATES_MCS_1_STREAM; i++, j++) {
+			if (txpwr->mcs_20_siso[j])
+				pi->txpwr_limit[i] = txpwr->mcs_20_siso[j];
+			else
+				pi->txpwr_limit[i] = txpwr->ofdm[j];
+		}
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phy_txpower_recalc_target(pi);
+	wlc_phy_cal_txpower_recalc_sw(pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->ofdm_rateset_war = war;
+}
+
+void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->bf_preempt_4306 = bf_preempt;
+}
+
+void wlc_phy_txpower_update_shm(phy_info_t *pi)
+{
+	int j;
+	if (ISNPHY(pi)) {
+		ASSERT(0);
+		return;
+	}
+
+	if (!pi->sh->clk)
+		return;
+
+	if (pi->hwpwrctrl) {
+		u16 offset;
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_MAX, 63);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_N,
+				     1 << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_TARGET,
+				     pi->tx_power_min << NUM_TSSI_FRAMES);
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_TXPWR_CUR,
+				     pi->hwpwr_txcur);
+
+		for (j = TXP_FIRST_OFDM; j <= TXP_LAST_OFDM; j++) {
+			const u8 ucode_ofdm_rates[] = {
+				0x0c, 0x12, 0x18, 0x24, 0x30, 0x48, 0x60, 0x6c
+			};
+			offset = wlapi_bmac_rate_shm_offset(pi->sh->physhim,
+							    ucode_ofdm_rates[j -
+									     TXP_FIRST_OFDM]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 6,
+					     pi->tx_power_offset[j]);
+			wlapi_bmac_write_shm(pi->sh->physhim, offset + 14,
+					     -(pi->tx_power_offset[j] / 2));
+		}
+
+		wlapi_bmac_mhf(pi->sh->physhim, MHF2, MHF2_HWPWRCTL,
+			       MHF2_HWPWRCTL, WLC_BAND_ALL);
+	} else {
+		int i;
+
+		for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++)
+			pi->tx_power_offset[i] =
+			    (u8) roundup(pi->tx_power_offset[i], 8);
+		wlapi_bmac_write_shm(pi->sh->physhim, M_OFDM_OFFSET,
+				     (u16) ((pi->
+						tx_power_offset[TXP_FIRST_OFDM]
+						+ 7) >> 3));
+	}
+}
+
+bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	if (ISNPHY(pi)) {
+		return pi->nphy_txpwrctrl;
+	} else {
+		return pi->hwpwrctrl;
+	}
+}
+
+void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	bool cur_hwpwrctrl = pi->hwpwrctrl;
+	bool suspend;
+
+	if (!pi->hwpwrctrl_capable) {
+		return;
+	}
+
+	pi->hwpwrctrl = hwpwrctrl;
+	pi->nphy_txpwrctrl = hwpwrctrl;
+	pi->txpwrctrl = hwpwrctrl;
+
+	if (ISNPHY(pi)) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+		wlc_phy_txpwrctrl_enable_nphy(pi, pi->nphy_txpwrctrl);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+			wlc_phy_txpwr_fixpower_nphy(pi);
+		} else {
+
+			mod_phy_reg(pi, 0x1e7, (0x7f << 0),
+				    pi->saved_txpwr_idx);
+		}
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	} else if (hwpwrctrl != cur_hwpwrctrl) {
+
+		return;
+	}
+}
+
+void wlc_phy_txpower_ipa_upd(phy_info_t *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->ipa2g_on = (pi->srom_fem2g.extpagain == 2);
+		pi->ipa5g_on = (pi->srom_fem5g.extpagain == 2);
+	} else {
+		pi->ipa2g_on = false;
+		pi->ipa5g_on = false;
+	}
+}
+
+static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi);
+
+static u32 wlc_phy_txpower_est_power_nphy(phy_info_t *pi)
+{
+	s16 tx0_status, tx1_status;
+	u16 estPower1, estPower2;
+	u8 pwr0, pwr1, adj_pwr0, adj_pwr1;
+	u32 est_pwr;
+
+	estPower1 = read_phy_reg(pi, 0x118);
+	estPower2 = read_phy_reg(pi, 0x119);
+
+	if ((estPower1 & (0x1 << 8))
+	    == (0x1 << 8)) {
+		pwr0 = (u8) (estPower1 & (0xff << 0))
+		    >> 0;
+	} else {
+		pwr0 = 0x80;
+	}
+
+	if ((estPower2 & (0x1 << 8))
+	    == (0x1 << 8)) {
+		pwr1 = (u8) (estPower2 & (0xff << 0))
+		    >> 0;
+	} else {
+		pwr1 = 0x80;
+	}
+
+	tx0_status = read_phy_reg(pi, 0x1ed);
+	tx1_status = read_phy_reg(pi, 0x1ee);
+
+	if ((tx0_status & (0x1 << 15))
+	    == (0x1 << 15)) {
+		adj_pwr0 = (u8) (tx0_status & (0xff << 0))
+		    >> 0;
+	} else {
+		adj_pwr0 = 0x80;
+	}
+	if ((tx1_status & (0x1 << 15))
+	    == (0x1 << 15)) {
+		adj_pwr1 = (u8) (tx1_status & (0xff << 0))
+		    >> 0;
+	} else {
+		adj_pwr1 = 0x80;
+	}
+
+	est_pwr =
+	    (u32) ((pwr0 << 24) | (pwr1 << 16) | (adj_pwr0 << 8) | adj_pwr1);
+	return est_pwr;
+}
+
+void
+wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power, uint channel)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	uint rate, num_rates;
+	u8 min_pwr, max_pwr;
+
+#if WL_TX_POWER_RATES != TXP_NUM_RATES
+#error "tx_power_t struct out of sync with this fn"
+#endif
+
+	if (ISNPHY(pi)) {
+		power->rf_cores = 2;
+		power->flags |= (WL_TX_POWER_F_MIMO);
+		if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+			power->flags |=
+			    (WL_TX_POWER_F_ENABLED | WL_TX_POWER_F_HW);
+	} else if (ISLCNPHY(pi)) {
+		power->rf_cores = 1;
+		power->flags |= (WL_TX_POWER_F_SISO);
+		if (pi->radiopwr_override == RADIOPWR_OVERRIDE_DEF)
+			power->flags |= WL_TX_POWER_F_ENABLED;
+		if (pi->hwpwrctrl)
+			power->flags |= WL_TX_POWER_F_HW;
+	}
+
+	num_rates = ((ISNPHY(pi)) ? (TXP_NUM_RATES) :
+		     ((ISLCNPHY(pi)) ?
+		      (TXP_LAST_OFDM_20_CDD + 1) : (TXP_LAST_OFDM + 1)));
+
+	for (rate = 0; rate < num_rates; rate++) {
+		power->user_limit[rate] = pi->tx_user_target[rate];
+		wlc_phy_txpower_sromlimit(ppi, channel, &min_pwr, &max_pwr,
+					  rate);
+		power->board_limit[rate] = (u8) max_pwr;
+		power->target[rate] = pi->tx_power_target[rate];
+	}
+
+	if (ISNPHY(pi)) {
+		u32 est_pout;
+
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_phyreg_enter((wlc_phy_t *) pi);
+		est_pout = wlc_phy_txpower_est_power_nphy(pi);
+		wlc_phyreg_exit((wlc_phy_t *) pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		power->est_Pout[0] = (est_pout >> 8) & 0xff;
+		power->est_Pout[1] = est_pout & 0xff;
+
+		power->est_Pout_act[0] = est_pout >> 24;
+		power->est_Pout_act[1] = (est_pout >> 16) & 0xff;
+
+		if (power->est_Pout[0] == 0x80)
+			power->est_Pout[0] = 0;
+		if (power->est_Pout[1] == 0x80)
+			power->est_Pout[1] = 0;
+
+		if (power->est_Pout_act[0] == 0x80)
+			power->est_Pout_act[0] = 0;
+		if (power->est_Pout_act[1] == 0x80)
+			power->est_Pout_act[1] = 0;
+
+		power->est_Pout_cck = 0;
+
+		power->tx_power_max[0] = pi->tx_power_max;
+		power->tx_power_max[1] = pi->tx_power_max;
+
+		power->tx_power_max_rate_ind[0] = pi->tx_power_max_rate_ind;
+		power->tx_power_max_rate_ind[1] = pi->tx_power_max_rate_ind;
+	} else if (!pi->hwpwrctrl) {
+	} else if (pi->sh->up) {
+
+		wlc_phyreg_enter(ppi);
+		if (ISLCNPHY(pi)) {
+
+			power->tx_power_max[0] = pi->tx_power_max;
+			power->tx_power_max[1] = pi->tx_power_max;
+
+			power->tx_power_max_rate_ind[0] =
+			    pi->tx_power_max_rate_ind;
+			power->tx_power_max_rate_ind[1] =
+			    pi->tx_power_max_rate_ind;
+
+			if (wlc_phy_tpc_isenabled_lcnphy(pi))
+				power->flags |=
+				    (WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+			else
+				power->flags &=
+				    ~(WL_TX_POWER_F_HW | WL_TX_POWER_F_ENABLED);
+
+			wlc_lcnphy_get_tssi(pi, (s8 *) &power->est_Pout[0],
+					    (s8 *) &power->est_Pout_cck);
+		}
+		wlc_phyreg_exit(ppi);
+	}
+}
+
+void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	pi->antsel_type = antsel_type;
+}
+
+bool wlc_phy_test_ison(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	return pi->phytest_on;
+}
+
+bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	bool ret = true;
+
+	wlc_phyreg_enter(ppi);
+
+	if (ISNPHY(pi)) {
+
+		ret = false;
+	} else if (ISLCNPHY(pi)) {
+		u16 crsctrl = read_phy_reg(pi, 0x410);
+		u16 div = crsctrl & (0x1 << 1);
+		*pval = (div | ((crsctrl & (0x1 << 0)) ^ (div >> 1)));
+	}
+
+	wlc_phyreg_exit(ppi);
+
+	return ret;
+}
+
+void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	bool suspend;
+
+	pi->sh->rx_antdiv = val;
+
+	if (!(ISNPHY(pi) && D11REV_IS(pi->sh->corerev, 16))) {
+		if (val > ANT_RX_DIV_FORCE_1)
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV,
+				       MHF1_ANTDIV, WLC_BAND_ALL);
+		else
+			wlapi_bmac_mhf(pi->sh->physhim, MHF1, MHF1_ANTDIV, 0,
+				       WLC_BAND_ALL);
+	}
+
+	if (ISNPHY(pi)) {
+
+		return;
+	}
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (ISLCNPHY(pi)) {
+		if (val > ANT_RX_DIV_FORCE_1) {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x01 << 1);
+			mod_phy_reg(pi, 0x410,
+				    (0x1 << 0),
+				    ((ANT_RX_DIV_START_1 == val) ? 1 : 0) << 0);
+		} else {
+			mod_phy_reg(pi, 0x410, (0x1 << 1), 0x00 << 1);
+			mod_phy_reg(pi, 0x410, (0x1 << 0), (u16) val << 0);
+		}
+	} else {
+		ASSERT(0);
+	}
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return;
+}
+
+static bool
+wlc_phy_noise_calc_phy(phy_info_t *pi, u32 *cmplx_pwr, s8 *pwr_ant)
+{
+	s8 cmplx_pwr_dbm[PHY_CORE_MAX];
+	u8 i;
+
+	memset((u8 *) cmplx_pwr_dbm, 0, sizeof(cmplx_pwr_dbm));
+	ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
+	wlc_phy_compute_dB(cmplx_pwr, cmplx_pwr_dbm, pi->pubpi.phy_corenum);
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		if (NREV_GE(pi->pubpi.phy_rev, 3))
+			cmplx_pwr_dbm[i] += (s8) PHY_NOISE_OFFSETFACT_4322;
+		else
+
+			cmplx_pwr_dbm[i] += (s8) (16 - (15) * 3 - 70);
+	}
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_noise_win[i][pi->nphy_noise_index] = cmplx_pwr_dbm[i];
+		pwr_ant[i] = cmplx_pwr_dbm[i];
+	}
+	pi->nphy_noise_index =
+	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+	return true;
+}
+
+static void
+wlc_phy_noise_sample_request(wlc_phy_t *pih, u8 reason, u8 ch)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	bool sampling_in_progress = (pi->phynoise_state != 0);
+	bool wait_for_intr = true;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		return;
+	}
+
+	switch (reason) {
+	case PHY_NOISE_SAMPLE_MON:
+
+		pi->phynoise_chan_watchdog = ch;
+		pi->phynoise_state |= PHY_NOISE_STATE_MON;
+
+		break;
+
+	case PHY_NOISE_SAMPLE_EXTERNAL:
+
+		pi->phynoise_state |= PHY_NOISE_STATE_EXTERNAL;
+		break;
+
+	default:
+		ASSERT(0);
+		break;
+	}
+
+	if (sampling_in_progress)
+		return;
+
+	pi->phynoise_now = pi->sh->now;
+
+	if (pi->phy_fixed_noise) {
+		if (ISNPHY(pi)) {
+			pi->nphy_noise_win[WL_ANT_IDX_1][pi->nphy_noise_index] =
+			    PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_win[WL_ANT_IDX_2][pi->nphy_noise_index] =
+			    PHY_NOISE_FIXED_VAL_NPHY;
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+		} else {
+
+			noise_dbm = PHY_NOISE_FIXED_VAL;
+		}
+
+		wait_for_intr = false;
+		goto done;
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+			wlapi_bmac_write_shm(pi->sh->physhim, M_JSSI_0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			OR_REG(&pi->regs->maccommand,
+			       MCMD_BG_NOISE);
+		} else {
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_lcnphy_deaf_mode(pi, (bool) 0);
+			noise_dbm = (s8) wlc_lcnphy_rx_signal_power(pi, 20);
+			wlc_lcnphy_deaf_mode(pi, (bool) 1);
+			wlapi_enable_mac(pi->sh->physhim);
+			wait_for_intr = false;
+		}
+	} else if (ISNPHY(pi)) {
+		if (!pi->phynoise_polling
+		    || (reason == PHY_NOISE_SAMPLE_EXTERNAL)) {
+
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP0, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP1, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP2, 0);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_PWRIND_MAP3, 0);
+
+			OR_REG(&pi->regs->maccommand,
+			       MCMD_BG_NOISE);
+		} else {
+			phy_iq_est_t est[PHY_CORE_MAX];
+			u32 cmplx_pwr[PHY_CORE_MAX];
+			s8 noise_dbm_ant[PHY_CORE_MAX];
+			u16 log_num_samps, num_samps, classif_state = 0;
+			u8 wait_time = 32;
+			u8 wait_crs = 0;
+			u8 i;
+
+			memset((u8 *) est, 0, sizeof(est));
+			memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+			memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+			log_num_samps = PHY_NOISE_SAMPLE_LOG_NUM_NPHY;
+			num_samps = 1 << log_num_samps;
+
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+			wlc_phy_classifier_nphy(pi, 3, 0);
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, wait_time,
+					       wait_crs);
+			wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+			wlapi_enable_mac(pi->sh->physhim);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++)
+				cmplx_pwr[i] =
+				    (est[i].i_pwr +
+				     est[i].q_pwr) >> log_num_samps;
+
+			wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+			for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+				pi->nphy_noise_win[i][pi->nphy_noise_index] =
+				    noise_dbm_ant[i];
+
+				if (noise_dbm_ant[i] > noise_dbm)
+					noise_dbm = noise_dbm_ant[i];
+			}
+			pi->nphy_noise_index = MODINC_POW2(pi->nphy_noise_index,
+							   PHY_NOISE_WINDOW_SZ);
+
+			wait_for_intr = false;
+		}
+	}
+
+ done:
+
+	if (!wait_for_intr)
+		wlc_phy_noise_cb(pi, ch, noise_dbm);
+
+}
+
+void wlc_phy_noise_sample_request_external(wlc_phy_t *pih)
+{
+	u8 channel;
+
+	channel = CHSPEC_CHANNEL(wlc_phy_chanspec_get(pih));
+
+	wlc_phy_noise_sample_request(pih, PHY_NOISE_SAMPLE_EXTERNAL, channel);
+}
+
+static void wlc_phy_noise_cb(phy_info_t *pi, u8 channel, s8 noise_dbm)
+{
+	if (!pi->phynoise_state)
+		return;
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_MON) {
+		if (pi->phynoise_chan_watchdog == channel) {
+			pi->sh->phy_noise_window[pi->sh->phy_noise_index] =
+			    noise_dbm;
+			pi->sh->phy_noise_index =
+			    MODINC(pi->sh->phy_noise_index, MA_WINDOW_SZ);
+		}
+		pi->phynoise_state &= ~PHY_NOISE_STATE_MON;
+	}
+
+	if (pi->phynoise_state & PHY_NOISE_STATE_EXTERNAL) {
+		pi->phynoise_state &= ~PHY_NOISE_STATE_EXTERNAL;
+	}
+
+}
+
+static s8 wlc_phy_noise_read_shmem(phy_info_t *pi)
+{
+	u32 cmplx_pwr[PHY_CORE_MAX];
+	s8 noise_dbm_ant[PHY_CORE_MAX];
+	u16 lo, hi;
+	u32 cmplx_pwr_tot = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+	u8 idx, core;
+
+	ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
+	memset((u8 *) cmplx_pwr, 0, sizeof(cmplx_pwr));
+	memset((u8 *) noise_dbm_ant, 0, sizeof(noise_dbm_ant));
+
+	for (idx = 0, core = 0; core < pi->pubpi.phy_corenum; idx += 2, core++) {
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP(idx));
+		hi = wlapi_bmac_read_shm(pi->sh->physhim,
+					 M_PWRIND_MAP(idx + 1));
+		cmplx_pwr[core] = (hi << 16) + lo;
+		cmplx_pwr_tot += cmplx_pwr[core];
+		if (cmplx_pwr[core] == 0) {
+			noise_dbm_ant[core] = PHY_NOISE_FIXED_VAL_NPHY;
+		} else
+			cmplx_pwr[core] >>= PHY_NOISE_SAMPLE_LOG_NUM_UCODE;
+	}
+
+	if (cmplx_pwr_tot != 0)
+		wlc_phy_noise_calc_phy(pi, cmplx_pwr, noise_dbm_ant);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		pi->nphy_noise_win[core][pi->nphy_noise_index] =
+		    noise_dbm_ant[core];
+
+		if (noise_dbm_ant[core] > noise_dbm)
+			noise_dbm = noise_dbm_ant[core];
+	}
+	pi->nphy_noise_index =
+	    MODINC_POW2(pi->nphy_noise_index, PHY_NOISE_WINDOW_SZ);
+
+	return noise_dbm;
+
+}
+
+void wlc_phy_noise_sample_intr(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	u16 jssi_aux;
+	u8 channel = 0;
+	s8 noise_dbm = PHY_NOISE_FIXED_VAL_NPHY;
+
+	if (ISLCNPHY(pi)) {
+		u32 cmplx_pwr, cmplx_pwr0, cmplx_pwr1;
+		u16 lo, hi;
+		s32 pwr_offset_dB, gain_dB;
+		u16 status_0, status_1;
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP0);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP1);
+		cmplx_pwr0 = (hi << 16) + lo;
+
+		lo = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP2);
+		hi = wlapi_bmac_read_shm(pi->sh->physhim, M_PWRIND_MAP3);
+		cmplx_pwr1 = (hi << 16) + lo;
+		cmplx_pwr = (cmplx_pwr0 + cmplx_pwr1) >> 6;
+
+		status_0 = 0x44;
+		status_1 = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_0);
+		if ((cmplx_pwr > 0 && cmplx_pwr < 500)
+		    && ((status_1 & 0xc000) == 0x4000)) {
+
+			wlc_phy_compute_dB(&cmplx_pwr, &noise_dbm,
+					   pi->pubpi.phy_corenum);
+			pwr_offset_dB = (read_phy_reg(pi, 0x434) & 0xFF);
+			if (pwr_offset_dB > 127)
+				pwr_offset_dB -= 256;
+
+			noise_dbm += (s8) (pwr_offset_dB - 30);
+
+			gain_dB = (status_0 & 0x1ff);
+			noise_dbm -= (s8) (gain_dB);
+		} else {
+			noise_dbm = PHY_NOISE_FIXED_VAL_LCNPHY;
+		}
+	} else if (ISNPHY(pi)) {
+
+		jssi_aux = wlapi_bmac_read_shm(pi->sh->physhim, M_JSSI_AUX);
+		channel = jssi_aux & D11_CURCHANNEL_MAX;
+
+		noise_dbm = wlc_phy_noise_read_shmem(pi);
+	} else {
+		ASSERT(0);
+	}
+
+	wlc_phy_noise_cb(pi, channel, noise_dbm);
+
+}
+
+s8 lcnphy_gain_index_offset_for_pkt_rssi[] = {
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	8,
+	9,
+	10,
+	8,
+	8,
+	7,
+	7,
+	1,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	1,
+	1,
+	0,
+	0,
+	0,
+	0
+};
+
+void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_cmplx_pwr_dB, u8 core)
+{
+	u8 shift_ct, lsb, msb, secondmsb, i;
+	u32 tmp;
+
+	for (i = 0; i < core; i++) {
+		tmp = cmplx_pwr[i];
+		shift_ct = msb = secondmsb = 0;
+		while (tmp != 0) {
+			tmp = tmp >> 1;
+			shift_ct++;
+			lsb = (u8) (tmp & 1);
+			if (lsb == 1)
+				msb = shift_ct;
+		}
+		secondmsb = (u8) ((cmplx_pwr[i] >> (msb - 1)) & 1);
+		p_cmplx_pwr_dB[i] = (s8) (3 * msb + 2 * secondmsb);
+	}
+}
+
+void BCMFASTPATH wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx)
+{
+	wlc_d11rxhdr_t *wlc_rxhdr = (wlc_d11rxhdr_t *) ctx;
+	d11rxhdr_t *rxh = &wlc_rxhdr->rxhdr;
+	int rssi = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_JSSI_MASK;
+	uint radioid = pih->radioid;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		rssi = WLC_RSSI_INVALID;
+		goto end;
+	}
+
+	if ((pi->sh->corerev >= 11)
+	    && !(le16_to_cpu(rxh->RxStatus2) & RXS_PHYRXST_VALID)) {
+		rssi = WLC_RSSI_INVALID;
+		goto end;
+	}
+
+	if (ISLCNPHY(pi)) {
+		u8 gidx = (le16_to_cpu(rxh->PhyRxStatus_2) & 0xFC00) >> 10;
+		phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+		if (rssi > 127)
+			rssi -= 256;
+
+		rssi = rssi + lcnphy_gain_index_offset_for_pkt_rssi[gidx];
+		if ((rssi > -46) && (gidx > 18))
+			rssi = rssi + 7;
+
+		rssi = rssi + pi_lcn->lcnphy_pkteng_rssi_slope;
+
+		rssi = rssi + 2;
+
+	}
+
+	if (ISLCNPHY(pi)) {
+
+		if (rssi > 127)
+			rssi -= 256;
+	} else if (radioid == BCM2055_ID || radioid == BCM2056_ID
+		   || radioid == BCM2057_ID) {
+		ASSERT(ISNPHY(pi));
+		rssi = wlc_phy_rssi_compute_nphy(pi, wlc_rxhdr);
+	} else {
+		ASSERT((const char *)"Unknown radio" == NULL);
+	}
+
+ end:
+	wlc_rxhdr->rssi = (s8) rssi;
+}
+
+void wlc_phy_freqtrack_start(wlc_phy_t *pih)
+{
+	return;
+}
+
+void wlc_phy_freqtrack_end(wlc_phy_t *pih)
+{
+	return;
+}
+
+void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag)
+{
+	phy_info_t *pi;
+	pi = (phy_info_t *) ppi;
+
+	if (ISLCNPHY(pi))
+		wlc_lcnphy_deaf_mode(pi, true);
+	else if (ISNPHY(pi))
+		wlc_nphy_deaf_mode(pi, true);
+	else {
+		ASSERT(0);
+	}
+}
+
+void wlc_phy_watchdog(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	bool delay_phy_cal = false;
+	pi->sh->now++;
+
+	if (!pi->watchdog_override)
+		return;
+
+	if (!(SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi))) {
+		wlc_phy_noise_sample_request((wlc_phy_t *) pi,
+					     PHY_NOISE_SAMPLE_MON,
+					     CHSPEC_CHANNEL(pi->
+							    radio_chanspec));
+	}
+
+	if (pi->phynoise_state && (pi->sh->now - pi->phynoise_now) > 5) {
+		pi->phynoise_state = 0;
+	}
+
+	if ((!pi->phycal_txpower) ||
+	    ((pi->sh->now - pi->phycal_txpower) >= pi->sh->fast_timer)) {
+
+		if (!SCAN_INPROG_PHY(pi) && wlc_phy_cal_txpower_recalc_sw(pi)) {
+			pi->phycal_txpower = pi->sh->now;
+		}
+	}
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if ((SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+	     || ASSOC_INPROG_PHY(pi)))
+		return;
+
+	if (ISNPHY(pi) && !pi->disable_percal && !delay_phy_cal) {
+
+		if ((pi->nphy_perical != PHY_PERICAL_DISABLE) &&
+		    (pi->nphy_perical != PHY_PERICAL_MANUAL) &&
+		    ((pi->sh->now - pi->nphy_perical_last) >=
+		     pi->sh->glacial_timer))
+			wlc_phy_cal_perical((wlc_phy_t *) pi,
+					    PHY_PERICAL_WATCHDOG);
+
+		wlc_phy_txpwr_papd_cal_nphy(pi);
+	}
+
+	if (ISLCNPHY(pi)) {
+		if (pi->phy_forcecal ||
+		    ((pi->sh->now - pi->phy_lastcal) >=
+		     pi->sh->glacial_timer)) {
+			if (!(SCAN_RM_IN_PROGRESS(pi) || ASSOC_INPROG_PHY(pi)))
+				wlc_lcnphy_calib_modes(pi,
+						       LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+			if (!
+			    (SCAN_RM_IN_PROGRESS(pi) || PLT_INPROG_PHY(pi)
+			     || ASSOC_INPROG_PHY(pi)
+			     || pi->carrier_suppr_disable
+			     || pi->disable_percal))
+				wlc_lcnphy_calib_modes(pi,
+						       PHY_PERICAL_WATCHDOG);
+		}
+	}
+}
+
+void wlc_phy_BSSinit(wlc_phy_t *pih, bool bonlyap, int rssi)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	uint i;
+	uint k;
+
+	for (i = 0; i < MA_WINDOW_SZ; i++) {
+		pi->sh->phy_noise_window[i] = (s8) (rssi & 0xff);
+	}
+	if (ISLCNPHY(pi)) {
+		for (i = 0; i < MA_WINDOW_SZ; i++)
+			pi->sh->phy_noise_window[i] =
+			    PHY_NOISE_FIXED_VAL_LCNPHY;
+	}
+	pi->sh->phy_noise_index = 0;
+
+	for (i = 0; i < PHY_NOISE_WINDOW_SZ; i++) {
+		for (k = WL_ANT_IDX_1; k < WL_ANT_RX_MAX; k++)
+			pi->nphy_noise_win[k][i] = PHY_NOISE_FIXED_VAL_NPHY;
+	}
+	pi->nphy_noise_index = 0;
+}
+
+void
+wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real, s32 *eps_imag)
+{
+	*eps_imag = (epsilon >> 13);
+	if (*eps_imag > 0xfff)
+		*eps_imag -= 0x2000;
+
+	*eps_real = (epsilon & 0x1fff);
+	if (*eps_real > 0xfff)
+		*eps_real -= 0x2000;
+}
+
+static const fixed AtanTbl[] = {
+	2949120,
+	1740967,
+	919879,
+	466945,
+	234379,
+	117304,
+	58666,
+	29335,
+	14668,
+	7334,
+	3667,
+	1833,
+	917,
+	458,
+	229,
+	115,
+	57,
+	29
+};
+
+void wlc_phy_cordic(fixed theta, cs32 *val)
+{
+	fixed angle, valtmp;
+	unsigned iter;
+	int signx = 1;
+	int signtheta;
+
+	val[0].i = CORDIC_AG;
+	val[0].q = 0;
+	angle = 0;
+
+	signtheta = (theta < 0) ? -1 : 1;
+	theta =
+	    ((theta + FIXED(180) * signtheta) % FIXED(360)) -
+	    FIXED(180) * signtheta;
+
+	if (FLOAT(theta) > 90) {
+		theta -= FIXED(180);
+		signx = -1;
+	} else if (FLOAT(theta) < -90) {
+		theta += FIXED(180);
+		signx = -1;
+	}
+
+	for (iter = 0; iter < CORDIC_NI; iter++) {
+		if (theta > angle) {
+			valtmp = val[0].i - (val[0].q >> iter);
+			val[0].q = (val[0].i >> iter) + val[0].q;
+			val[0].i = valtmp;
+			angle += AtanTbl[iter];
+		} else {
+			valtmp = val[0].i + (val[0].q >> iter);
+			val[0].q = -(val[0].i >> iter) + val[0].q;
+			val[0].i = valtmp;
+			angle -= AtanTbl[iter];
+		}
+	}
+
+	val[0].i = val[0].i * signx;
+	val[0].q = val[0].q * signx;
+}
+
+void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi)
+{
+	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+
+	pi->cal_type_override = PHY_PERICAL_AUTO;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+static void wlc_phy_cal_perical_mphase_schedule(phy_info_t *pi, uint delay)
+{
+
+	if ((pi->nphy_perical != PHY_PERICAL_MPHASE) &&
+	    (pi->nphy_perical != PHY_PERICAL_MANUAL))
+		return;
+
+	wlapi_del_timer(pi->sh->physhim, pi->phycal_timer);
+
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	wlapi_add_timer(pi->sh->physhim, pi->phycal_timer, delay, 0);
+}
+
+void wlc_phy_cal_perical(wlc_phy_t *pih, u8 reason)
+{
+	s16 nphy_currtemp = 0;
+	s16 delta_temp = 0;
+	bool do_periodic_cal = true;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	if (!ISNPHY(pi))
+		return;
+
+	if ((pi->nphy_perical == PHY_PERICAL_DISABLE) ||
+	    (pi->nphy_perical == PHY_PERICAL_MANUAL))
+		return;
+
+	switch (reason) {
+	case PHY_PERICAL_DRIVERUP:
+		break;
+
+	case PHY_PERICAL_PHYINIT:
+		if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+			if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+				wlc_phy_cal_perical_mphase_reset(pi);
+			}
+			wlc_phy_cal_perical_mphase_schedule(pi,
+							    PHY_PERICAL_INIT_DELAY);
+		}
+		break;
+
+	case PHY_PERICAL_JOIN_BSS:
+	case PHY_PERICAL_START_IBSS:
+	case PHY_PERICAL_UP_BSS:
+		if ((pi->nphy_perical == PHY_PERICAL_MPHASE) &&
+		    PHY_PERICAL_MPHASE_PENDING(pi)) {
+			wlc_phy_cal_perical_mphase_reset(pi);
+		}
+
+		pi->first_cal_after_assoc = true;
+
+		pi->cal_type_override = PHY_PERICAL_FULL;
+
+		if (pi->phycal_tempdelta) {
+			pi->nphy_lastcal_temp = wlc_phy_tempsense_nphy(pi);
+		}
+		wlc_phy_cal_perical_nphy_run(pi, PHY_PERICAL_FULL);
+		break;
+
+	case PHY_PERICAL_WATCHDOG:
+		if (pi->phycal_tempdelta) {
+			nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+			delta_temp =
+			    (nphy_currtemp > pi->nphy_lastcal_temp) ?
+			    nphy_currtemp - pi->nphy_lastcal_temp :
+			    pi->nphy_lastcal_temp - nphy_currtemp;
+
+			if ((delta_temp < (s16) pi->phycal_tempdelta) &&
+			    (pi->nphy_txiqlocal_chanspec ==
+			     pi->radio_chanspec)) {
+				do_periodic_cal = false;
+			} else {
+				pi->nphy_lastcal_temp = nphy_currtemp;
+			}
+		}
+
+		if (do_periodic_cal) {
+
+			if (pi->nphy_perical == PHY_PERICAL_MPHASE) {
+
+				if (!PHY_PERICAL_MPHASE_PENDING(pi))
+					wlc_phy_cal_perical_mphase_schedule(pi,
+									    PHY_PERICAL_WDOG_DELAY);
+			} else if (pi->nphy_perical == PHY_PERICAL_SPHASE)
+				wlc_phy_cal_perical_nphy_run(pi,
+							     PHY_PERICAL_AUTO);
+			else {
+				ASSERT(0);
+			}
+		}
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+}
+
+void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi)
+{
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_INIT;
+	pi->mphase_txcal_cmdidx = 0;
+}
+
+u8 wlc_phy_nbits(s32 value)
+{
+	s32 abs_val;
+	u8 nbits = 0;
+
+	abs_val = ABS(value);
+	while ((abs_val >> nbits) > 0)
+		nbits++;
+
+	return nbits;
+}
+
+u32 wlc_phy_sqrt_int(u32 value)
+{
+	u32 root = 0, shift = 0;
+
+	for (shift = 0; shift < 32; shift += 2) {
+		if (((0x40000000 >> shift) + root) <= value) {
+			value -= ((0x40000000 >> shift) + root);
+			root = (root >> 1) | (0x40000000 >> shift);
+		} else {
+			root = root >> 1;
+		}
+	}
+
+	if (root < value)
+		++root;
+
+	return root;
+}
+
+void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain, u8 rxchain)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->sh->hw_phytxchain = txchain;
+	pi->sh->hw_phyrxchain = rxchain;
+	pi->sh->phytxchain = txchain;
+	pi->sh->phyrxchain = rxchain;
+	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain, u8 rxchain)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	pi->sh->phytxchain = txchain;
+
+	if (ISNPHY(pi)) {
+		wlc_phy_rxcore_setstate_nphy(pih, rxchain);
+	}
+	pi->pubpi.phy_corenum = (u8) PHY_BITSCNT(pi->sh->phyrxchain);
+}
+
+void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain, u8 *rxchain)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	*txchain = pi->sh->phytxchain;
+	*rxchain = pi->sh->phyrxchain;
+}
+
+u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih)
+{
+	s16 nphy_currtemp;
+	u8 active_bitmap;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	active_bitmap = (pi->phy_txcore_heatedup) ? 0x31 : 0x33;
+
+	if (!pi->watchdog_override)
+		return active_bitmap;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		nphy_currtemp = wlc_phy_tempsense_nphy(pi);
+		wlapi_enable_mac(pi->sh->physhim);
+
+		if (!pi->phy_txcore_heatedup) {
+			if (nphy_currtemp >= pi->phy_txcore_disable_temp) {
+				active_bitmap &= 0xFD;
+				pi->phy_txcore_heatedup = true;
+			}
+		} else {
+			if (nphy_currtemp <= pi->phy_txcore_enable_temp) {
+				active_bitmap |= 0x2;
+				pi->phy_txcore_heatedup = false;
+			}
+		}
+	}
+
+	return active_bitmap;
+}
+
+s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	u8 siso_mcs_id, cdd_mcs_id;
+
+	siso_mcs_id =
+	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_SISO :
+	    TXP_FIRST_MCS_20_SISO;
+	cdd_mcs_id =
+	    (CHSPEC_IS40(chanspec)) ? TXP_FIRST_MCS_40_CDD :
+	    TXP_FIRST_MCS_20_CDD;
+
+	if (pi->tx_power_target[siso_mcs_id] >
+	    (pi->tx_power_target[cdd_mcs_id] + 12))
+		return PHY_TXC1_MODE_SISO;
+	else
+		return PHY_TXC1_MODE_CDD;
+}
+
+const u8 *wlc_phy_get_ofdm_rate_lookup(void)
+{
+	return ofdm_rate_lookup;
+}
+
+void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode)
+{
+	if ((pi->sh->chip == BCM4313_CHIP_ID) &&
+	    (pi->sh->boardflags & BFL_FEM)) {
+		if (mode) {
+			u16 txant = 0;
+			txant = wlapi_bmac_get_txant(pi->sh->physhim);
+			if (txant == 1) {
+				mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+				mod_phy_reg(pi, 0x44c, (0x1 << 2), (1) << 2);
+
+			}
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
+				   0x0);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioout), 0x40, 0x40);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioouten), 0x40,
+				   0x40);
+		} else {
+			mod_phy_reg(pi, 0x44c, (0x1 << 2), (0) << 2);
+
+			mod_phy_reg(pi, 0x44d, (0x1 << 2), (0) << 2);
+
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioout), 0x40, 0x00);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpioouten), 0x40, 0x0);
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, gpiocontrol), ~0x0,
+				   0x40);
+		}
+	}
+}
+
+static s8
+wlc_user_txpwr_antport_to_rfport(phy_info_t *pi, uint chan, u32 band,
+				 u8 rate)
+{
+	s8 offset = 0;
+
+	if (!pi->user_txpwr_at_rfport)
+		return offset;
+	return offset;
+}
+
+static s8 wlc_phy_env_measure_vbat(phy_info_t *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_vbatsense(pi, 0);
+	else
+		return 0;
+}
+
+static s8 wlc_phy_env_measure_temperature(phy_info_t *pi)
+{
+	if (ISLCNPHY(pi))
+		return wlc_lcnphy_tempsense_degree(pi, 0);
+	else
+		return 0;
+}
+
+static void wlc_phy_upd_env_txpwr_rate_limits(phy_info_t *pi, u32 band)
+{
+	u8 i;
+	s8 temp, vbat;
+
+	for (i = 0; i < TXP_NUM_RATES; i++)
+		pi->txpwr_env_limit[i] = WLC_TXPWR_MAX;
+
+	vbat = wlc_phy_env_measure_vbat(pi);
+	temp = wlc_phy_env_measure_temperature(pi);
+
+}
+
+void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool ldpc)
+{
+	return;
+}
+
+void
+wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset, s8 *ofdmoffset)
+{
+	*cckoffset = 0;
+	*ofdmoffset = 0;
+}
+
+u32 wlc_phy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, roundup, rbit;
+
+	ASSERT(divisor);
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+	rbit = divisor & 1;
+	roundup = (divisor >> 1) + rbit;
+
+	while (precision--) {
+		quotient <<= 1;
+		if (remainder >= roundup) {
+			quotient++;
+			remainder = ((remainder - roundup) << 1) + rbit;
+		} else {
+			remainder <<= 1;
+		}
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
+}
+
+s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi, chanspec_t chanspec)
+{
+
+	return rssi;
+}
+
+bool wlc_phy_txpower_ipa_ison(wlc_phy_t *ppi)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	if (ISNPHY(pi))
+		return wlc_phy_n_txpower_ipa_ison(pi);
+	else
+		return 0;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_hal.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 _wlc_phy_h_
+#define _wlc_phy_h_
+
+#include <wlioctl.h>
+#include <siutils.h>
+#include <d11.h>
+#include <wlc_phy_shim.h>
+
+#define	IDCODE_VER_MASK		0x0000000f
+#define	IDCODE_VER_SHIFT	0
+#define	IDCODE_MFG_MASK		0x00000fff
+#define	IDCODE_MFG_SHIFT	0
+#define	IDCODE_ID_MASK		0x0ffff000
+#define	IDCODE_ID_SHIFT		12
+#define	IDCODE_REV_MASK		0xf0000000
+#define	IDCODE_REV_SHIFT	28
+
+#define	NORADIO_ID		0xe4f5
+#define	NORADIO_IDCODE		0x4e4f5246
+
+#define BCM2055_ID		0x2055
+#define BCM2055_IDCODE		0x02055000
+#define BCM2055A0_IDCODE	0x1205517f
+
+#define BCM2056_ID		0x2056
+#define BCM2056_IDCODE		0x02056000
+#define BCM2056A0_IDCODE	0x1205617f
+
+#define BCM2057_ID		0x2057
+#define BCM2057_IDCODE		0x02057000
+#define BCM2057A0_IDCODE	0x1205717f
+
+#define BCM2064_ID		0x2064
+#define BCM2064_IDCODE		0x02064000
+#define BCM2064A0_IDCODE	0x0206417f
+
+#define PHY_TPC_HW_OFF		false
+#define PHY_TPC_HW_ON		true
+
+#define PHY_PERICAL_DRIVERUP	1
+#define PHY_PERICAL_WATCHDOG	2
+#define PHY_PERICAL_PHYINIT	3
+#define PHY_PERICAL_JOIN_BSS	4
+#define PHY_PERICAL_START_IBSS	5
+#define PHY_PERICAL_UP_BSS	6
+#define PHY_PERICAL_CHAN	7
+#define PHY_FULLCAL	8
+
+#define PHY_PERICAL_DISABLE	0
+#define PHY_PERICAL_SPHASE	1
+#define PHY_PERICAL_MPHASE	2
+#define PHY_PERICAL_MANUAL	3
+
+#define PHY_HOLD_FOR_ASSOC	1
+#define PHY_HOLD_FOR_SCAN	2
+#define PHY_HOLD_FOR_RM		4
+#define PHY_HOLD_FOR_PLT	8
+#define PHY_HOLD_FOR_MUTE	16
+#define PHY_HOLD_FOR_NOT_ASSOC 0x20
+
+#define PHY_MUTE_FOR_PREISM	1
+#define PHY_MUTE_ALL		0xffffffff
+
+#define PHY_NOISE_FIXED_VAL 		(-95)
+#define PHY_NOISE_FIXED_VAL_NPHY       	(-92)
+#define PHY_NOISE_FIXED_VAL_LCNPHY     	(-92)
+
+#define PHY_MODE_CAL		0x0002
+#define PHY_MODE_NOISEM		0x0004
+
+#define WLC_TXPWR_DB_FACTOR	4
+
+#define WLC_NUM_RATES_CCK           4
+#define WLC_NUM_RATES_OFDM          8
+#define WLC_NUM_RATES_MCS_1_STREAM  8
+#define WLC_NUM_RATES_MCS_2_STREAM  8
+#define WLC_NUM_RATES_MCS_3_STREAM  8
+#define WLC_NUM_RATES_MCS_4_STREAM  8
+typedef struct txpwr_limits {
+	u8 cck[WLC_NUM_RATES_CCK];
+	u8 ofdm[WLC_NUM_RATES_OFDM];
+
+	u8 ofdm_cdd[WLC_NUM_RATES_OFDM];
+
+	u8 ofdm_40_siso[WLC_NUM_RATES_OFDM];
+	u8 ofdm_40_cdd[WLC_NUM_RATES_OFDM];
+
+	u8 mcs_20_siso[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_cdd[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_stbc[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_20_mimo[WLC_NUM_RATES_MCS_2_STREAM];
+
+	u8 mcs_40_siso[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_cdd[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_stbc[WLC_NUM_RATES_MCS_1_STREAM];
+	u8 mcs_40_mimo[WLC_NUM_RATES_MCS_2_STREAM];
+	u8 mcs32;
+} txpwr_limits_t;
+
+typedef struct {
+	u8 vec[MAXCHANNEL / NBBY];
+} chanvec_t;
+
+struct rpc_info;
+typedef struct shared_phy shared_phy_t;
+
+struct phy_pub;
+
+typedef struct phy_pub wlc_phy_t;
+
+typedef struct shared_phy_params {
+	si_t *sih;
+	void *physhim;
+	uint unit;
+	uint corerev;
+	uint bustype;
+	uint buscorerev;
+	char *vars;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	uint boardvendor;
+	u32 boardflags;
+	u32 boardflags2;
+} shared_phy_params_t;
+
+
+extern shared_phy_t *wlc_phy_shared_attach(shared_phy_params_t *shp);
+extern void wlc_phy_shared_detach(shared_phy_t *phy_sh);
+extern wlc_phy_t *wlc_phy_attach(shared_phy_t *sh, void *regs, int bandtype,
+				 char *vars);
+extern void wlc_phy_detach(wlc_phy_t *ppi);
+
+extern bool wlc_phy_get_phyversion(wlc_phy_t *pih, u16 *phytype,
+				   u16 *phyrev, u16 *radioid,
+				   u16 *radiover);
+extern bool wlc_phy_get_encore(wlc_phy_t *pih);
+extern u32 wlc_phy_get_coreflags(wlc_phy_t *pih);
+
+extern void wlc_phy_hw_clk_state_upd(wlc_phy_t *ppi, bool newstate);
+extern void wlc_phy_hw_state_upd(wlc_phy_t *ppi, bool newstate);
+extern void wlc_phy_init(wlc_phy_t *ppi, chanspec_t chanspec);
+extern void wlc_phy_watchdog(wlc_phy_t *ppi);
+extern int wlc_phy_down(wlc_phy_t *ppi);
+extern u32 wlc_phy_clk_bwbits(wlc_phy_t *pih);
+extern void wlc_phy_cal_init(wlc_phy_t *ppi);
+extern void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init);
+
+extern void wlc_phy_chanspec_set(wlc_phy_t *ppi, chanspec_t chanspec);
+extern chanspec_t wlc_phy_chanspec_get(wlc_phy_t *ppi);
+extern void wlc_phy_chanspec_radio_set(wlc_phy_t *ppi, chanspec_t newch);
+extern u16 wlc_phy_bw_state_get(wlc_phy_t *ppi);
+extern void wlc_phy_bw_state_set(wlc_phy_t *ppi, u16 bw);
+
+extern void wlc_phy_rssi_compute(wlc_phy_t *pih, void *ctx);
+extern void wlc_phy_por_inform(wlc_phy_t *ppi);
+extern void wlc_phy_noise_sample_intr(wlc_phy_t *ppi);
+extern bool wlc_phy_bist_check_phy(wlc_phy_t *ppi);
+
+extern void wlc_phy_set_deaf(wlc_phy_t *ppi, bool user_flag);
+
+extern void wlc_phy_switch_radio(wlc_phy_t *ppi, bool on);
+extern void wlc_phy_anacore(wlc_phy_t *ppi, bool on);
+
+
+extern void wlc_phy_BSSinit(wlc_phy_t *ppi, bool bonlyap, int rssi);
+
+extern void wlc_phy_chanspec_ch14_widefilter_set(wlc_phy_t *ppi,
+						 bool wide_filter);
+extern void wlc_phy_chanspec_band_validch(wlc_phy_t *ppi, uint band,
+					  chanvec_t *channels);
+extern chanspec_t wlc_phy_chanspec_band_firstch(wlc_phy_t *ppi, uint band);
+
+extern void wlc_phy_txpower_sromlimit(wlc_phy_t *ppi, uint chan,
+				      u8 *_min_, u8 *_max_, int rate);
+extern void wlc_phy_txpower_sromlimit_max_get(wlc_phy_t *ppi, uint chan,
+					      u8 *_max_, u8 *_min_);
+extern void wlc_phy_txpower_boardlimit_band(wlc_phy_t *ppi, uint band, s32 *,
+					    s32 *, u32 *);
+extern void wlc_phy_txpower_limit_set(wlc_phy_t *ppi, struct txpwr_limits *,
+				      chanspec_t chanspec);
+extern int wlc_phy_txpower_get(wlc_phy_t *ppi, uint *qdbm, bool *override);
+extern int wlc_phy_txpower_set(wlc_phy_t *ppi, uint qdbm, bool override);
+extern void wlc_phy_txpower_target_set(wlc_phy_t *ppi, struct txpwr_limits *);
+extern bool wlc_phy_txpower_hw_ctrl_get(wlc_phy_t *ppi);
+extern void wlc_phy_txpower_hw_ctrl_set(wlc_phy_t *ppi, bool hwpwrctrl);
+extern u8 wlc_phy_txpower_get_target_min(wlc_phy_t *ppi);
+extern u8 wlc_phy_txpower_get_target_max(wlc_phy_t *ppi);
+extern bool wlc_phy_txpower_ipa_ison(wlc_phy_t *pih);
+
+extern void wlc_phy_stf_chain_init(wlc_phy_t *pih, u8 txchain,
+				   u8 rxchain);
+extern void wlc_phy_stf_chain_set(wlc_phy_t *pih, u8 txchain,
+				  u8 rxchain);
+extern void wlc_phy_stf_chain_get(wlc_phy_t *pih, u8 *txchain,
+				  u8 *rxchain);
+extern u8 wlc_phy_stf_chain_active_get(wlc_phy_t *pih);
+extern s8 wlc_phy_stf_ssmode_get(wlc_phy_t *pih, chanspec_t chanspec);
+extern void wlc_phy_ldpc_override_set(wlc_phy_t *ppi, bool val);
+
+extern void wlc_phy_cal_perical(wlc_phy_t *ppi, u8 reason);
+extern void wlc_phy_noise_sample_request_external(wlc_phy_t *ppi);
+extern void wlc_phy_edcrs_lock(wlc_phy_t *pih, bool lock);
+extern void wlc_phy_cal_papd_recal(wlc_phy_t *ppi);
+
+extern void wlc_phy_ant_rxdiv_set(wlc_phy_t *ppi, u8 val);
+extern bool wlc_phy_ant_rxdiv_get(wlc_phy_t *ppi, u8 *pval);
+extern void wlc_phy_clear_tssi(wlc_phy_t *ppi);
+extern void wlc_phy_hold_upd(wlc_phy_t *ppi, mbool id, bool val);
+extern void wlc_phy_mute_upd(wlc_phy_t *ppi, bool val, mbool flags);
+
+extern void wlc_phy_antsel_type_set(wlc_phy_t *ppi, u8 antsel_type);
+
+extern void wlc_phy_txpower_get_current(wlc_phy_t *ppi, tx_power_t *power,
+					uint channel);
+
+extern void wlc_phy_initcal_enable(wlc_phy_t *pih, bool initcal);
+extern bool wlc_phy_test_ison(wlc_phy_t *ppi);
+extern void wlc_phy_txpwr_percent_set(wlc_phy_t *ppi, u8 txpwr_percent);
+extern void wlc_phy_ofdm_rateset_war(wlc_phy_t *pih, bool war);
+extern void wlc_phy_bf_preempt_enable(wlc_phy_t *pih, bool bf_preempt);
+extern void wlc_phy_machwcap_set(wlc_phy_t *ppi, u32 machwcap);
+
+extern void wlc_phy_runbist_config(wlc_phy_t *ppi, bool start_end);
+
+extern void wlc_phy_freqtrack_start(wlc_phy_t *ppi);
+extern void wlc_phy_freqtrack_end(wlc_phy_t *ppi);
+
+extern const u8 *wlc_phy_get_ofdm_rate_lookup(void);
+
+extern s8 wlc_phy_get_tx_power_offset_by_mcs(wlc_phy_t *ppi,
+					       u8 mcs_offset);
+extern s8 wlc_phy_get_tx_power_offset(wlc_phy_t *ppi, u8 tbl_offset);
+#endif				/* _wlc_phy_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_int.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,1228 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 _wlc_phy_int_h_
+#define _wlc_phy_int_h_
+
+#include <linux/kernel.h>
+#include <bcmdefs.h>
+#include <bcmutils.h>
+
+#include <bcmsrom_fmt.h>
+#include <wlc_phy_hal.h>
+
+#define PHYHAL_ERROR	0x0001
+#define PHYHAL_TRACE	0x0002
+#define PHYHAL_INFORM	0x0004
+
+extern u32 phyhal_msg_level;
+
+#define PHY_INFORM_ON()		(phyhal_msg_level & PHYHAL_INFORM)
+#define PHY_THERMAL_ON()	(phyhal_msg_level & PHYHAL_THERMAL)
+#define PHY_CAL_ON()		(phyhal_msg_level & PHYHAL_CAL)
+
+#ifdef BOARD_TYPE
+#define BOARDTYPE(_type) BOARD_TYPE
+#else
+#define BOARDTYPE(_type) _type
+#endif
+
+#define LCNXN_BASEREV		16
+
+struct wlc_hw_info;
+typedef struct phy_info phy_info_t;
+typedef void (*initfn_t) (phy_info_t *);
+typedef void (*chansetfn_t) (phy_info_t *, chanspec_t);
+typedef int (*longtrnfn_t) (phy_info_t *, int);
+typedef void (*txiqccgetfn_t) (phy_info_t *, u16 *, u16 *);
+typedef void (*txiqccsetfn_t) (phy_info_t *, u16, u16);
+typedef u16(*txloccgetfn_t) (phy_info_t *);
+typedef void (*radioloftgetfn_t) (phy_info_t *, u8 *, u8 *, u8 *,
+				  u8 *);
+typedef s32(*rxsigpwrfn_t) (phy_info_t *, s32);
+typedef void (*detachfn_t) (phy_info_t *);
+
+#undef ISNPHY
+#undef ISLCNPHY
+#define ISNPHY(pi)	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_N)
+#define ISLCNPHY(pi)  	PHYTYPE_IS((pi)->pubpi.phy_type, PHY_TYPE_LCN)
+
+#define ISPHY_11N_CAP(pi)	(ISNPHY(pi) || ISLCNPHY(pi))
+
+#define IS20MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_20)
+#define IS40MHZ(pi)	((pi)->bw == WL_CHANSPEC_BW_40)
+
+#define PHY_GET_RFATTN(rfgain)	((rfgain) & 0x0f)
+#define PHY_GET_PADMIX(rfgain)	(((rfgain) & 0x10) >> 4)
+#define PHY_GET_RFGAINID(rfattn, padmix, width)	((rfattn) + ((padmix)*(width)))
+#define PHY_SAT(x, n)		((x) > ((1<<((n)-1))-1) ? ((1<<((n)-1))-1) : \
+				((x) < -(1<<((n)-1)) ? -(1<<((n)-1)) : (x)))
+#define PHY_SHIFT_ROUND(x, n)	((x) >= 0 ? ((x)+(1<<((n)-1)))>>(n) : (x)>>(n))
+#define PHY_HW_ROUND(x, s)		((x >> s) + ((x >> (s-1)) & (s != 0)))
+
+#define CH_5G_GROUP	3
+#define A_LOW_CHANS	0
+#define A_MID_CHANS	1
+#define A_HIGH_CHANS	2
+#define CH_2G_GROUP	1
+#define G_ALL_CHANS	0
+
+#define FIRST_REF5_CHANNUM	149
+#define LAST_REF5_CHANNUM	165
+#define	FIRST_5G_CHAN		14
+#define	LAST_5G_CHAN		50
+#define	FIRST_MID_5G_CHAN	14
+#define	LAST_MID_5G_CHAN	35
+#define	FIRST_HIGH_5G_CHAN	36
+#define	LAST_HIGH_5G_CHAN	41
+#define	FIRST_LOW_5G_CHAN	42
+#define	LAST_LOW_5G_CHAN	50
+
+#define BASE_LOW_5G_CHAN	4900
+#define BASE_MID_5G_CHAN	5100
+#define BASE_HIGH_5G_CHAN	5500
+
+#define CHAN5G_FREQ(chan)  (5000 + chan*5)
+#define CHAN2G_FREQ(chan)  (2407 + chan*5)
+
+#define TXP_FIRST_CCK		0
+#define TXP_LAST_CCK		3
+#define TXP_FIRST_OFDM		4
+#define TXP_LAST_OFDM		11
+#define TXP_FIRST_OFDM_20_CDD	12
+#define TXP_LAST_OFDM_20_CDD	19
+#define TXP_FIRST_MCS_20_SISO	20
+#define TXP_LAST_MCS_20_SISO	27
+#define TXP_FIRST_MCS_20_CDD	28
+#define TXP_LAST_MCS_20_CDD	35
+#define TXP_FIRST_MCS_20_STBC	36
+#define TXP_LAST_MCS_20_STBC	43
+#define TXP_FIRST_MCS_20_SDM	44
+#define TXP_LAST_MCS_20_SDM	51
+#define TXP_FIRST_OFDM_40_SISO	52
+#define TXP_LAST_OFDM_40_SISO	59
+#define TXP_FIRST_OFDM_40_CDD	60
+#define TXP_LAST_OFDM_40_CDD	67
+#define TXP_FIRST_MCS_40_SISO	68
+#define TXP_LAST_MCS_40_SISO	75
+#define TXP_FIRST_MCS_40_CDD	76
+#define TXP_LAST_MCS_40_CDD	83
+#define TXP_FIRST_MCS_40_STBC	84
+#define TXP_LAST_MCS_40_STBC	91
+#define TXP_FIRST_MCS_40_SDM	92
+#define TXP_LAST_MCS_40_SDM	99
+#define TXP_MCS_32	        100
+#define TXP_NUM_RATES		101
+#define ADJ_PWR_TBL_LEN		84
+
+#define TXP_FIRST_SISO_MCS_20	20
+#define TXP_LAST_SISO_MCS_20	27
+
+#define PHY_CORE_NUM_1	1
+#define PHY_CORE_NUM_2	2
+#define PHY_CORE_NUM_3	3
+#define PHY_CORE_NUM_4	4
+#define PHY_CORE_MAX	PHY_CORE_NUM_4
+#define PHY_CORE_0	0
+#define PHY_CORE_1	1
+#define PHY_CORE_2	2
+#define PHY_CORE_3	3
+
+#define MA_WINDOW_SZ		8
+
+#define PHY_NOISE_SAMPLE_MON		1
+#define PHY_NOISE_SAMPLE_EXTERNAL	2
+#define PHY_NOISE_WINDOW_SZ	16
+#define PHY_NOISE_GLITCH_INIT_MA 10
+#define PHY_NOISE_GLITCH_INIT_MA_BADPlCP 10
+#define PHY_NOISE_STATE_MON		0x1
+#define PHY_NOISE_STATE_EXTERNAL	0x2
+#define PHY_NOISE_SAMPLE_LOG_NUM_NPHY	10
+#define PHY_NOISE_SAMPLE_LOG_NUM_UCODE	9
+
+#define PHY_NOISE_OFFSETFACT_4322  (-103)
+#define PHY_NOISE_MA_WINDOW_SZ	2
+
+#define	PHY_RSSI_TABLE_SIZE	64
+#define RSSI_ANT_MERGE_MAX	0
+#define RSSI_ANT_MERGE_MIN	1
+#define RSSI_ANT_MERGE_AVG	2
+
+#define	PHY_TSSI_TABLE_SIZE	64
+#define	APHY_TSSI_TABLE_SIZE	256
+#define	TX_GAIN_TABLE_LENGTH	64
+#define	DEFAULT_11A_TXP_IDX	24
+#define NUM_TSSI_FRAMES        4
+#define	NULL_TSSI		0x7f
+#define	NULL_TSSI_W		0x7f7f
+
+#define PHY_PAPD_EPS_TBL_SIZE_LCNPHY 64
+
+#define LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL 9
+
+#define PHY_TXPWR_MIN		10
+#define PHY_TXPWR_MIN_NPHY	8
+#define RADIOPWR_OVERRIDE_DEF	(-1)
+
+#define PWRTBL_NUM_COEFF	3
+
+#define SPURAVOID_DISABLE	0
+#define SPURAVOID_AUTO		1
+#define SPURAVOID_FORCEON	2
+#define SPURAVOID_FORCEON2	3
+
+#define PHY_SW_TIMER_FAST		15
+#define PHY_SW_TIMER_SLOW		60
+#define PHY_SW_TIMER_GLACIAL	120
+
+#define PHY_PERICAL_AUTO	0
+#define PHY_PERICAL_FULL	1
+#define PHY_PERICAL_PARTIAL	2
+
+#define PHY_PERICAL_NODELAY	0
+#define PHY_PERICAL_INIT_DELAY	5
+#define PHY_PERICAL_ASSOC_DELAY	5
+#define PHY_PERICAL_WDOG_DELAY	5
+
+#define MPHASE_TXCAL_NUMCMDS	2
+#define PHY_PERICAL_MPHASE_PENDING(pi)	(pi->mphase_cal_phase_id > MPHASE_CAL_STATE_IDLE)
+
+enum {
+	MPHASE_CAL_STATE_IDLE = 0,
+	MPHASE_CAL_STATE_INIT = 1,
+	MPHASE_CAL_STATE_TXPHASE0,
+	MPHASE_CAL_STATE_TXPHASE1,
+	MPHASE_CAL_STATE_TXPHASE2,
+	MPHASE_CAL_STATE_TXPHASE3,
+	MPHASE_CAL_STATE_TXPHASE4,
+	MPHASE_CAL_STATE_TXPHASE5,
+	MPHASE_CAL_STATE_PAPDCAL,
+	MPHASE_CAL_STATE_RXCAL,
+	MPHASE_CAL_STATE_RSSICAL,
+	MPHASE_CAL_STATE_IDLETSSI
+};
+
+typedef enum {
+	CAL_FULL,
+	CAL_RECAL,
+	CAL_CURRECAL,
+	CAL_DIGCAL,
+	CAL_GCTRL,
+	CAL_SOFT,
+	CAL_DIGLO
+} phy_cal_mode_t;
+
+#define RDR_NTIERS  1
+#define RDR_TIER_SIZE 64
+#define RDR_LIST_SIZE (512/3)
+#define RDR_EPOCH_SIZE 40
+#define RDR_NANTENNAS 2
+#define RDR_NTIER_SIZE  RDR_LIST_SIZE
+#define RDR_LP_BUFFER_SIZE 64
+#define LP_LEN_HIS_SIZE 10
+
+#define STATIC_NUM_RF 32
+#define STATIC_NUM_BB 9
+
+#define BB_MULT_MASK		0x0000ffff
+#define BB_MULT_VALID_MASK	0x80000000
+
+#define CORDIC_AG	39797
+#define	CORDIC_NI	18
+#define	FIXED(X)	((s32)((X) << 16))
+#define	FLOAT(X)	(((X) >= 0) ? ((((X) >> 15) + 1) >> 1) : -((((-(X)) >> 15) + 1) >> 1))
+
+#define PHY_CHAIN_TX_DISABLE_TEMP	115
+#define PHY_HYSTERESIS_DELTATEMP	5
+
+#define PHY_BITSCNT(x)	bcm_bitcount((u8 *)&(x), sizeof(u8))
+
+#define MOD_PHY_REG(pi, phy_type, reg_name, field, value) \
+	mod_phy_reg(pi, phy_type##_##reg_name, phy_type##_##reg_name##_##field##_MASK, \
+	(value) << phy_type##_##reg_name##_##field##_##SHIFT);
+#define READ_PHY_REG(pi, phy_type, reg_name, field) \
+	((read_phy_reg(pi, phy_type##_##reg_name) & phy_type##_##reg_name##_##field##_##MASK)\
+	>> phy_type##_##reg_name##_##field##_##SHIFT)
+
+#define	VALID_PHYTYPE(phytype)	(((uint)phytype == PHY_TYPE_N) || \
+				((uint)phytype == PHY_TYPE_LCN))
+
+#define VALID_N_RADIO(radioid)	((radioid == BCM2055_ID) || (radioid == BCM2056_ID) || \
+				(radioid == BCM2057_ID))
+#define VALID_LCN_RADIO(radioid)	(radioid == BCM2064_ID)
+
+#define	VALID_RADIO(pi, radioid)	(\
+	(ISNPHY(pi) ? VALID_N_RADIO(radioid) : false) || \
+	(ISLCNPHY(pi) ? VALID_LCN_RADIO(radioid) : false))
+
+#define SCAN_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN))
+#define RM_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_RM))
+#define PLT_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_PLT))
+#define ASSOC_INPROG_PHY(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_ASSOC))
+#define SCAN_RM_IN_PROGRESS(pi) (mboolisset(pi->measure_hold, PHY_HOLD_FOR_SCAN | PHY_HOLD_FOR_RM))
+#define PHY_MUTED(pi)		(mboolisset(pi->measure_hold, PHY_HOLD_FOR_MUTE))
+#define PUB_NOT_ASSOC(pi)	(mboolisset(pi->measure_hold, PHY_HOLD_FOR_NOT_ASSOC))
+
+#if defined(EXT_CBALL)
+#define NORADIO_ENAB(pub) ((pub).radioid == NORADIO_ID)
+#else
+#define NORADIO_ENAB(pub) 0
+#endif
+
+#define PHY_LTRN_LIST_LEN	64
+extern u16 ltrn_list[PHY_LTRN_LIST_LEN];
+
+typedef struct _phy_table_info {
+	uint table;
+	int q;
+	uint max;
+} phy_table_info_t;
+
+typedef struct phytbl_info {
+	const void *tbl_ptr;
+	u32 tbl_len;
+	u32 tbl_id;
+	u32 tbl_offset;
+	u32 tbl_width;
+} phytbl_info_t;
+
+typedef struct {
+	u8 curr_home_channel;
+	u16 crsminpwrthld_40_stored;
+	u16 crsminpwrthld_20L_stored;
+	u16 crsminpwrthld_20U_stored;
+	u16 init_gain_code_core1_stored;
+	u16 init_gain_code_core2_stored;
+	u16 init_gain_codeb_core1_stored;
+	u16 init_gain_codeb_core2_stored;
+	u16 init_gain_table_stored[4];
+
+	u16 clip1_hi_gain_code_core1_stored;
+	u16 clip1_hi_gain_code_core2_stored;
+	u16 clip1_hi_gain_codeb_core1_stored;
+	u16 clip1_hi_gain_codeb_core2_stored;
+	u16 nb_clip_thresh_core1_stored;
+	u16 nb_clip_thresh_core2_stored;
+	u16 init_ofdmlna2gainchange_stored[4];
+	u16 init_ccklna2gainchange_stored[4];
+	u16 clip1_lo_gain_code_core1_stored;
+	u16 clip1_lo_gain_code_core2_stored;
+	u16 clip1_lo_gain_codeb_core1_stored;
+	u16 clip1_lo_gain_codeb_core2_stored;
+	u16 w1_clip_thresh_core1_stored;
+	u16 w1_clip_thresh_core2_stored;
+	u16 radio_2056_core1_rssi_gain_stored;
+	u16 radio_2056_core2_rssi_gain_stored;
+	u16 energy_drop_timeout_len_stored;
+
+	u16 ed_crs40_assertthld0_stored;
+	u16 ed_crs40_assertthld1_stored;
+	u16 ed_crs40_deassertthld0_stored;
+	u16 ed_crs40_deassertthld1_stored;
+	u16 ed_crs20L_assertthld0_stored;
+	u16 ed_crs20L_assertthld1_stored;
+	u16 ed_crs20L_deassertthld0_stored;
+	u16 ed_crs20L_deassertthld1_stored;
+	u16 ed_crs20U_assertthld0_stored;
+	u16 ed_crs20U_assertthld1_stored;
+	u16 ed_crs20U_deassertthld0_stored;
+	u16 ed_crs20U_deassertthld1_stored;
+
+	u16 badplcp_ma;
+	u16 badplcp_ma_previous;
+	u16 badplcp_ma_total;
+	u16 badplcp_ma_list[MA_WINDOW_SZ];
+	int badplcp_ma_index;
+	s16 pre_badplcp_cnt;
+	s16 bphy_pre_badplcp_cnt;
+
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u16 init_gain_rfseq[4];
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+
+	s16 crsminpwr_index;
+
+	u16 radio_2057_core1_rssi_wb1a_gc_stored;
+	u16 radio_2057_core2_rssi_wb1a_gc_stored;
+	u16 radio_2057_core1_rssi_wb1g_gc_stored;
+	u16 radio_2057_core2_rssi_wb1g_gc_stored;
+	u16 radio_2057_core1_rssi_wb2_gc_stored;
+	u16 radio_2057_core2_rssi_wb2_gc_stored;
+	u16 radio_2057_core1_rssi_nb_gc_stored;
+	u16 radio_2057_core2_rssi_nb_gc_stored;
+
+} interference_info_t;
+
+typedef struct {
+	u16 rc_cal_ovr;
+	u16 phycrsth1;
+	u16 phycrsth2;
+	u16 init_n1p1_gain;
+	u16 p1_p2_gain;
+	u16 n1_n2_gain;
+	u16 n1_p1_gain;
+	u16 div_search_gain;
+	u16 div_p1_p2_gain;
+	u16 div_search_gn_change;
+	u16 table_7_2;
+	u16 table_7_3;
+	u16 cckshbits_gnref;
+	u16 clip_thresh;
+	u16 clip2_thresh;
+	u16 clip3_thresh;
+	u16 clip_p2_thresh;
+	u16 clip_pwdn_thresh;
+	u16 clip_n1p1_thresh;
+	u16 clip_n1_pwdn_thresh;
+	u16 bbconfig;
+	u16 cthr_sthr_shdin;
+	u16 energy;
+	u16 clip_p1_p2_thresh;
+	u16 threshold;
+	u16 reg15;
+	u16 reg16;
+	u16 reg17;
+	u16 div_srch_idx;
+	u16 div_srch_p1_p2;
+	u16 div_srch_gn_back;
+	u16 ant_dwell;
+	u16 ant_wr_settle;
+} aci_save_gphy_t;
+
+typedef struct _lo_complex_t {
+	s8 i;
+	s8 q;
+} lo_complex_abgphy_info_t;
+
+typedef struct _nphy_iq_comp {
+	s16 a0;
+	s16 b0;
+	s16 a1;
+	s16 b1;
+} nphy_iq_comp_t;
+
+typedef struct _nphy_txpwrindex {
+	s8 index;
+	s8 index_internal;
+	s8 index_internal_save;
+	u16 AfectrlOverride;
+	u16 AfeCtrlDacGain;
+	u16 rad_gain;
+	u8 bbmult;
+	u16 iqcomp_a;
+	u16 iqcomp_b;
+	u16 locomp;
+} phy_txpwrindex_t;
+
+typedef struct {
+
+	u16 txcal_coeffs_2G[8];
+	u16 txcal_radio_regs_2G[8];
+	nphy_iq_comp_t rxcal_coeffs_2G;
+
+	u16 txcal_coeffs_5G[8];
+	u16 txcal_radio_regs_5G[8];
+	nphy_iq_comp_t rxcal_coeffs_5G;
+} txiqcal_cache_t;
+
+typedef struct _nphy_pwrctrl {
+	s8 max_pwr_2g;
+	s8 idle_targ_2g;
+	s16 pwrdet_2g_a1;
+	s16 pwrdet_2g_b0;
+	s16 pwrdet_2g_b1;
+	s8 max_pwr_5gm;
+	s8 idle_targ_5gm;
+	s8 max_pwr_5gh;
+	s8 max_pwr_5gl;
+	s16 pwrdet_5gm_a1;
+	s16 pwrdet_5gm_b0;
+	s16 pwrdet_5gm_b1;
+	s16 pwrdet_5gl_a1;
+	s16 pwrdet_5gl_b0;
+	s16 pwrdet_5gl_b1;
+	s16 pwrdet_5gh_a1;
+	s16 pwrdet_5gh_b0;
+	s16 pwrdet_5gh_b1;
+	s8 idle_targ_5gl;
+	s8 idle_targ_5gh;
+	s8 idle_tssi_2g;
+	s8 idle_tssi_5g;
+	s8 idle_tssi;
+	s16 a1;
+	s16 b0;
+	s16 b1;
+} phy_pwrctrl_t;
+
+typedef struct _nphy_txgains {
+	u16 txlpf[2];
+	u16 txgm[2];
+	u16 pga[2];
+	u16 pad[2];
+	u16 ipa[2];
+} nphy_txgains_t;
+
+#define PHY_NOISEVAR_BUFSIZE 10
+
+typedef struct _nphy_noisevar_buf {
+	int bufcount;
+	int tone_id[PHY_NOISEVAR_BUFSIZE];
+	u32 noise_vars[PHY_NOISEVAR_BUFSIZE];
+	u32 min_noise_vars[PHY_NOISEVAR_BUFSIZE];
+} phy_noisevar_buf_t;
+
+typedef struct {
+	u16 rssical_radio_regs_2G[2];
+	u16 rssical_phyregs_2G[12];
+
+	u16 rssical_radio_regs_5G[2];
+	u16 rssical_phyregs_5G[12];
+} rssical_cache_t;
+
+typedef struct {
+
+	u16 txiqlocal_a;
+	u16 txiqlocal_b;
+	u16 txiqlocal_didq;
+	u8 txiqlocal_ei0;
+	u8 txiqlocal_eq0;
+	u8 txiqlocal_fi0;
+	u8 txiqlocal_fq0;
+
+	u16 txiqlocal_bestcoeffs[11];
+	u16 txiqlocal_bestcoeffs_valid;
+
+	u32 papd_eps_tbl[PHY_PAPD_EPS_TBL_SIZE_LCNPHY];
+	u16 analog_gain_ref;
+	u16 lut_begin;
+	u16 lut_end;
+	u16 lut_step;
+	u16 rxcompdbm;
+	u16 papdctrl;
+	u16 sslpnCalibClkEnCtrl;
+
+	u16 rxiqcal_coeff_a0;
+	u16 rxiqcal_coeff_b0;
+} lcnphy_cal_results_t;
+
+struct shared_phy {
+	struct phy_info *phy_head;
+	uint unit;
+	si_t *sih;
+	void *physhim;
+	uint corerev;
+	u32 machwcap;
+	bool up;
+	bool clk;
+	uint now;
+	u16 vid;
+	u16 did;
+	uint chip;
+	uint chiprev;
+	uint chippkg;
+	uint sromrev;
+	uint boardtype;
+	uint boardrev;
+	uint boardvendor;
+	u32 boardflags;
+	u32 boardflags2;
+	uint bustype;
+	uint buscorerev;
+	uint fast_timer;
+	uint slow_timer;
+	uint glacial_timer;
+	u8 rx_antdiv;
+	s8 phy_noise_window[MA_WINDOW_SZ];
+	uint phy_noise_index;
+	u8 hw_phytxchain;
+	u8 hw_phyrxchain;
+	u8 phytxchain;
+	u8 phyrxchain;
+	u8 rssi_mode;
+	bool _rifs_phy;
+};
+
+struct phy_pub {
+	uint phy_type;
+	uint phy_rev;
+	u8 phy_corenum;
+	u16 radioid;
+	u8 radiorev;
+	u8 radiover;
+
+	uint coreflags;
+	uint ana_rev;
+	bool abgphy_encore;
+};
+
+struct phy_info_nphy;
+typedef struct phy_info_nphy phy_info_nphy_t;
+
+struct phy_info_lcnphy;
+typedef struct phy_info_lcnphy phy_info_lcnphy_t;
+
+struct phy_func_ptr {
+	initfn_t init;
+	initfn_t calinit;
+	chansetfn_t chanset;
+	initfn_t txpwrrecalc;
+	longtrnfn_t longtrn;
+	txiqccgetfn_t txiqccget;
+	txiqccsetfn_t txiqccset;
+	txloccgetfn_t txloccget;
+	radioloftgetfn_t radioloftget;
+	initfn_t carrsuppr;
+	rxsigpwrfn_t rxsigpwr;
+	detachfn_t detach;
+};
+typedef struct phy_func_ptr phy_func_ptr_t;
+
+struct phy_info {
+	wlc_phy_t pubpi_ro;
+	shared_phy_t *sh;
+	phy_func_ptr_t pi_fptr;
+	void *pi_ptr;
+
+	union {
+		phy_info_lcnphy_t *pi_lcnphy;
+	} u;
+	bool user_txpwr_at_rfport;
+
+	d11regs_t *regs;
+	struct phy_info *next;
+	char *vars;
+	wlc_phy_t pubpi;
+
+	bool do_initcal;
+	bool phytest_on;
+	bool ofdm_rateset_war;
+	bool bf_preempt_4306;
+	chanspec_t radio_chanspec;
+	u8 antsel_type;
+	u16 bw;
+	u8 txpwr_percent;
+	bool phy_init_por;
+
+	bool init_in_progress;
+	bool initialized;
+	bool sbtml_gm;
+	uint refcnt;
+	bool watchdog_override;
+	u8 phynoise_state;
+	uint phynoise_now;
+	int phynoise_chan_watchdog;
+	bool phynoise_polling;
+	bool disable_percal;
+	mbool measure_hold;
+
+	s16 txpa_2g[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_low_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_2g_high_temp[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_low[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_mid[PWRTBL_NUM_COEFF];
+	s16 txpa_5g_hi[PWRTBL_NUM_COEFF];
+
+	u8 tx_srom_max_2g;
+	u8 tx_srom_max_5g_low;
+	u8 tx_srom_max_5g_mid;
+	u8 tx_srom_max_5g_hi;
+	u8 tx_srom_max_rate_2g[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_low[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_mid[TXP_NUM_RATES];
+	u8 tx_srom_max_rate_5g_hi[TXP_NUM_RATES];
+	u8 tx_user_target[TXP_NUM_RATES];
+	s8 tx_power_offset[TXP_NUM_RATES];
+	u8 tx_power_target[TXP_NUM_RATES];
+
+	srom_fem_t srom_fem2g;
+	srom_fem_t srom_fem5g;
+
+	u8 tx_power_max;
+	u8 tx_power_max_rate_ind;
+	bool hwpwrctrl;
+	u8 nphy_txpwrctrl;
+	s8 nphy_txrx_chain;
+	bool phy_5g_pwrgain;
+
+	u16 phy_wreg;
+	u16 phy_wreg_limit;
+
+	s8 n_preamble_override;
+	u8 antswitch;
+	u8 aa2g, aa5g;
+
+	s8 idle_tssi[CH_5G_GROUP];
+	s8 target_idle_tssi;
+	s8 txpwr_est_Pout;
+	u8 tx_power_min;
+	u8 txpwr_limit[TXP_NUM_RATES];
+	u8 txpwr_env_limit[TXP_NUM_RATES];
+	u8 adj_pwr_tbl_nphy[ADJ_PWR_TBL_LEN];
+
+	bool channel_14_wide_filter;
+
+	bool txpwroverride;
+	bool txpwridx_override_aphy;
+	s16 radiopwr_override;
+	u16 hwpwr_txcur;
+	u8 saved_txpwr_idx;
+
+	bool edcrs_threshold_lock;
+
+	u32 tr_R_gain_val;
+	u32 tr_T_gain_val;
+
+	s16 ofdm_analog_filt_bw_override;
+	s16 cck_analog_filt_bw_override;
+	s16 ofdm_rccal_override;
+	s16 cck_rccal_override;
+	u16 extlna_type;
+
+	uint interference_mode_crs_time;
+	u16 crsglitch_prev;
+	bool interference_mode_crs;
+
+	u32 phy_tx_tone_freq;
+	uint phy_lastcal;
+	bool phy_forcecal;
+	bool phy_fixed_noise;
+	u32 xtalfreq;
+	u8 pdiv;
+	s8 carrier_suppr_disable;
+
+	bool phy_bphy_evm;
+	bool phy_bphy_rfcs;
+	s8 phy_scraminit;
+	u8 phy_gpiosel;
+
+	s16 phy_txcore_disable_temp;
+	s16 phy_txcore_enable_temp;
+	s8 phy_tempsense_offset;
+	bool phy_txcore_heatedup;
+
+	u16 radiopwr;
+	u16 bb_atten;
+	u16 txctl1;
+
+	u16 mintxbias;
+	u16 mintxmag;
+	lo_complex_abgphy_info_t gphy_locomp_iq[STATIC_NUM_RF][STATIC_NUM_BB];
+	s8 stats_11b_txpower[STATIC_NUM_RF][STATIC_NUM_BB];
+	u16 gain_table[TX_GAIN_TABLE_LENGTH];
+	bool loopback_gain;
+	s16 max_lpback_gain_hdB;
+	s16 trsw_rx_gain_hdB;
+	u8 power_vec[8];
+
+	u16 rc_cal;
+	int nrssi_table_delta;
+	int nrssi_slope_scale;
+	int nrssi_slope_offset;
+	int min_rssi;
+	int max_rssi;
+
+	s8 txpwridx;
+	u8 min_txpower;
+
+	u8 a_band_high_disable;
+
+	u16 tx_vos;
+	u16 global_tx_bb_dc_bias_loft;
+
+	int rf_max;
+	int bb_max;
+	int rf_list_size;
+	int bb_list_size;
+	u16 *rf_attn_list;
+	u16 *bb_attn_list;
+	u16 padmix_mask;
+	u16 padmix_reg;
+	u16 *txmag_list;
+	uint txmag_len;
+	bool txmag_enable;
+
+	s8 *a_tssi_to_dbm;
+	s8 *m_tssi_to_dbm;
+	s8 *l_tssi_to_dbm;
+	s8 *h_tssi_to_dbm;
+	u8 *hwtxpwr;
+
+	u16 freqtrack_saved_regs[2];
+	int cur_interference_mode;
+	bool hwpwrctrl_capable;
+	bool temppwrctrl_capable;
+
+	uint phycal_nslope;
+	uint phycal_noffset;
+	uint phycal_mlo;
+	uint phycal_txpower;
+
+	u8 phy_aa2g;
+
+	bool nphy_tableloaded;
+	s8 nphy_rssisel;
+	u32 nphy_bb_mult_save;
+	u16 nphy_txiqlocal_bestc[11];
+	bool nphy_txiqlocal_coeffsvalid;
+	phy_txpwrindex_t nphy_txpwrindex[PHY_CORE_NUM_2];
+	phy_pwrctrl_t nphy_pwrctrl_info[PHY_CORE_NUM_2];
+	u16 cck2gpo;
+	u32 ofdm2gpo;
+	u32 ofdm5gpo;
+	u32 ofdm5glpo;
+	u32 ofdm5ghpo;
+	u8 bw402gpo;
+	u8 bw405gpo;
+	u8 bw405glpo;
+	u8 bw405ghpo;
+	u8 cdd2gpo;
+	u8 cdd5gpo;
+	u8 cdd5glpo;
+	u8 cdd5ghpo;
+	u8 stbc2gpo;
+	u8 stbc5gpo;
+	u8 stbc5glpo;
+	u8 stbc5ghpo;
+	u8 bwdup2gpo;
+	u8 bwdup5gpo;
+	u8 bwdup5glpo;
+	u8 bwdup5ghpo;
+	u16 mcs2gpo[8];
+	u16 mcs5gpo[8];
+	u16 mcs5glpo[8];
+	u16 mcs5ghpo[8];
+	u32 nphy_rxcalparams;
+
+	u8 phy_spuravoid;
+	bool phy_isspuravoid;
+
+	u8 phy_pabias;
+	u8 nphy_papd_skip;
+	u8 nphy_tssi_slope;
+
+	s16 nphy_noise_win[PHY_CORE_MAX][PHY_NOISE_WINDOW_SZ];
+	u8 nphy_noise_index;
+
+	u8 nphy_txpid2g[PHY_CORE_NUM_2];
+	u8 nphy_txpid5g[PHY_CORE_NUM_2];
+	u8 nphy_txpid5gl[PHY_CORE_NUM_2];
+	u8 nphy_txpid5gh[PHY_CORE_NUM_2];
+
+	bool nphy_gain_boost;
+	bool nphy_elna_gain_config;
+	u16 old_bphy_test;
+	u16 old_bphy_testcontrol;
+
+	bool phyhang_avoid;
+
+	bool rssical_nphy;
+	u8 nphy_perical;
+	uint nphy_perical_last;
+	u8 cal_type_override;
+	u8 mphase_cal_phase_id;
+	u8 mphase_txcal_cmdidx;
+	u8 mphase_txcal_numcmds;
+	u16 mphase_txcal_bestcoeffs[11];
+	chanspec_t nphy_txiqlocal_chanspec;
+	chanspec_t nphy_iqcal_chanspec_2G;
+	chanspec_t nphy_iqcal_chanspec_5G;
+	chanspec_t nphy_rssical_chanspec_2G;
+	chanspec_t nphy_rssical_chanspec_5G;
+	struct wlapi_timer *phycal_timer;
+	bool use_int_tx_iqlo_cal_nphy;
+	bool internal_tx_iqlo_cal_tapoff_intpa_nphy;
+	s16 nphy_lastcal_temp;
+
+	txiqcal_cache_t calibration_cache;
+	rssical_cache_t rssical_cache;
+
+	u8 nphy_txpwr_idx[2];
+	u8 nphy_papd_cal_type;
+	uint nphy_papd_last_cal;
+	u16 nphy_papd_tx_gain_at_last_cal[2];
+	u8 nphy_papd_cal_gain_index[2];
+	s16 nphy_papd_epsilon_offset[2];
+	bool nphy_papd_recal_enable;
+	u32 nphy_papd_recal_counter;
+	bool nphy_force_papd_cal;
+	bool nphy_papdcomp;
+	bool ipa2g_on;
+	bool ipa5g_on;
+
+	u16 classifier_state;
+	u16 clip_state[2];
+	uint nphy_deaf_count;
+	u8 rxiq_samps;
+	u8 rxiq_antsel;
+
+	u16 rfctrlIntc1_save;
+	u16 rfctrlIntc2_save;
+	bool first_cal_after_assoc;
+	u16 tx_rx_cal_radio_saveregs[22];
+	u16 tx_rx_cal_phy_saveregs[15];
+
+	u8 nphy_cal_orig_pwr_idx[2];
+	u8 nphy_txcal_pwr_idx[2];
+	u8 nphy_rxcal_pwr_idx[2];
+	u16 nphy_cal_orig_tx_gain[2];
+	nphy_txgains_t nphy_cal_target_gain;
+	u16 nphy_txcal_bbmult;
+	u16 nphy_gmval;
+
+	u16 nphy_saved_bbconf;
+
+	bool nphy_gband_spurwar_en;
+	bool nphy_gband_spurwar2_en;
+	bool nphy_aband_spurwar_en;
+	u16 nphy_rccal_value;
+	u16 nphy_crsminpwr[3];
+	phy_noisevar_buf_t nphy_saved_noisevars;
+	bool nphy_anarxlpf_adjusted;
+	bool nphy_crsminpwr_adjusted;
+	bool nphy_noisevars_adjusted;
+
+	bool nphy_rxcal_active;
+	u16 radar_percal_mask;
+	bool dfs_lp_buffer_nphy;
+
+	u16 nphy_fineclockgatecontrol;
+
+	s8 rx2tx_biasentry;
+
+	u16 crsminpwr0;
+	u16 crsminpwrl0;
+	u16 crsminpwru0;
+	s16 noise_crsminpwr_index;
+	u16 init_gain_core1;
+	u16 init_gain_core2;
+	u16 init_gainb_core1;
+	u16 init_gainb_core2;
+	u8 aci_noise_curr_channel;
+	u16 init_gain_rfseq[4];
+
+	bool radio_is_on;
+
+	bool nphy_sample_play_lpf_bw_ctl_ovr;
+
+	u16 tbl_data_hi;
+	u16 tbl_data_lo;
+	u16 tbl_addr;
+
+	uint tbl_save_id;
+	uint tbl_save_offset;
+
+	u8 txpwrctrl;
+	s8 txpwrindex[PHY_CORE_MAX];
+
+	u8 phycal_tempdelta;
+	u32 mcs20_po;
+	u32 mcs40_po;
+};
+
+typedef s32 fixed;
+
+typedef struct _cs32 {
+	fixed q;
+	fixed i;
+} cs32;
+
+typedef struct radio_regs {
+	u16 address;
+	u32 init_a;
+	u32 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+} radio_regs_t;
+
+typedef struct radio_20xx_regs {
+	u16 address;
+	u8 init;
+	u8 do_init;
+} radio_20xx_regs_t;
+
+typedef struct lcnphy_radio_regs {
+	u16 address;
+	u8 init_a;
+	u8 init_g;
+	u8 do_init_a;
+	u8 do_init_g;
+} lcnphy_radio_regs_t;
+
+extern lcnphy_radio_regs_t lcnphy_radio_regs_2064[];
+extern lcnphy_radio_regs_t lcnphy_radio_regs_2066[];
+extern radio_regs_t regs_2055[], regs_SYN_2056[], regs_TX_2056[],
+    regs_RX_2056[];
+extern radio_regs_t regs_SYN_2056_A1[], regs_TX_2056_A1[], regs_RX_2056_A1[];
+extern radio_regs_t regs_SYN_2056_rev5[], regs_TX_2056_rev5[],
+    regs_RX_2056_rev5[];
+extern radio_regs_t regs_SYN_2056_rev6[], regs_TX_2056_rev6[],
+    regs_RX_2056_rev6[];
+extern radio_regs_t regs_SYN_2056_rev7[], regs_TX_2056_rev7[],
+    regs_RX_2056_rev7[];
+extern radio_regs_t regs_SYN_2056_rev8[], regs_TX_2056_rev8[],
+    regs_RX_2056_rev8[];
+extern radio_20xx_regs_t regs_2057_rev4[], regs_2057_rev5[], regs_2057_rev5v1[];
+extern radio_20xx_regs_t regs_2057_rev7[], regs_2057_rev8[];
+
+extern char *phy_getvar(phy_info_t *pi, const char *name);
+extern int phy_getintvar(phy_info_t *pi, const char *name);
+#define PHY_GETVAR(pi, name)	phy_getvar(pi, name)
+#define PHY_GETINTVAR(pi, name)	phy_getintvar(pi, name)
+
+extern u16 read_phy_reg(phy_info_t *pi, u16 addr);
+extern void write_phy_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void and_phy_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void or_phy_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void mod_phy_reg(phy_info_t *pi, u16 addr, u16 mask, u16 val);
+
+extern u16 read_radio_reg(phy_info_t *pi, u16 addr);
+extern void or_radio_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void and_radio_reg(phy_info_t *pi, u16 addr, u16 val);
+extern void mod_radio_reg(phy_info_t *pi, u16 addr, u16 mask,
+			  u16 val);
+extern void xor_radio_reg(phy_info_t *pi, u16 addr, u16 mask);
+
+extern void write_radio_reg(phy_info_t *pi, u16 addr, u16 val);
+
+extern void wlc_phyreg_enter(wlc_phy_t *pih);
+extern void wlc_phyreg_exit(wlc_phy_t *pih);
+extern void wlc_radioreg_enter(wlc_phy_t *pih);
+extern void wlc_radioreg_exit(wlc_phy_t *pih);
+
+extern void wlc_phy_read_table(phy_info_t *pi, const phytbl_info_t *ptbl_info,
+			       u16 tblAddr, u16 tblDataHi,
+			       u16 tblDatalo);
+extern void wlc_phy_write_table(phy_info_t *pi,
+				const phytbl_info_t *ptbl_info, u16 tblAddr,
+				u16 tblDataHi, u16 tblDatalo);
+extern void wlc_phy_table_addr(phy_info_t *pi, uint tbl_id, uint tbl_offset,
+			       u16 tblAddr, u16 tblDataHi,
+			       u16 tblDataLo);
+extern void wlc_phy_table_data_write(phy_info_t *pi, uint width, u32 val);
+
+extern void write_phy_channel_reg(phy_info_t *pi, uint val);
+extern void wlc_phy_txpower_update_shm(phy_info_t *pi);
+
+extern void wlc_phy_cordic(fixed theta, cs32 *val);
+extern u8 wlc_phy_nbits(s32 value);
+extern u32 wlc_phy_sqrt_int(u32 value);
+extern void wlc_phy_compute_dB(u32 *cmplx_pwr, s8 *p_dB, u8 core);
+
+extern uint wlc_phy_init_radio_regs_allbands(phy_info_t *pi,
+					     radio_20xx_regs_t *radioregs);
+extern uint wlc_phy_init_radio_regs(phy_info_t *pi, radio_regs_t *radioregs,
+				    u16 core_offset);
+
+extern void wlc_phy_txpower_ipa_upd(phy_info_t *pi);
+
+extern void wlc_phy_do_dummy_tx(phy_info_t *pi, bool ofdm, bool pa_on);
+extern void wlc_phy_papd_decode_epsilon(u32 epsilon, s32 *eps_real,
+					s32 *eps_imag);
+
+extern void wlc_phy_cal_perical_mphase_reset(phy_info_t *pi);
+extern void wlc_phy_cal_perical_mphase_restart(phy_info_t *pi);
+
+extern bool wlc_phy_attach_nphy(phy_info_t *pi);
+extern bool wlc_phy_attach_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_detach_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_init_nphy(phy_info_t *pi);
+extern void wlc_phy_init_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_cal_init_nphy(phy_info_t *pi);
+extern void wlc_phy_cal_init_lcnphy(phy_info_t *pi);
+
+extern void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec);
+extern void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec);
+extern void wlc_phy_chanspec_set_fixup_lcnphy(phy_info_t *pi,
+					      chanspec_t chanspec);
+extern int wlc_phy_channel2freq(uint channel);
+extern int wlc_phy_chanspec_freq2bandrange_lpssn(uint);
+extern int wlc_phy_chanspec_bandrange_get(phy_info_t *, chanspec_t);
+
+extern void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode);
+extern s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi);
+
+extern void wlc_phy_txpower_recalc_target_nphy(phy_info_t *pi);
+extern void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi);
+extern void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi);
+
+extern void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index);
+extern void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable);
+extern void wlc_lcnphy_stop_tx_tone(phy_info_t *pi);
+extern void wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz,
+				     u16 max_val, bool iqcalmode);
+
+extern void wlc_phy_txpower_sromlimit_get_nphy(phy_info_t *pi, uint chan,
+					       u8 *max_pwr, u8 rate_id);
+extern void wlc_phy_ofdm_to_mcs_powers_nphy(u8 *power, u8 rate_mcs_start,
+					    u8 rate_mcs_end,
+					    u8 rate_ofdm_start);
+extern void wlc_phy_mcs_to_ofdm_powers_nphy(u8 *power,
+					    u8 rate_ofdm_start,
+					    u8 rate_ofdm_end,
+					    u8 rate_mcs_start);
+
+extern u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode);
+extern s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode);
+extern s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode);
+extern s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode);
+extern void wlc_phy_carrier_suppress_lcnphy(phy_info_t *pi);
+extern void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel);
+extern void wlc_lcnphy_epa_switch(phy_info_t *pi, bool mode);
+extern void wlc_2064_vco_cal(phy_info_t *pi);
+
+extern void wlc_phy_txpower_recalc_target(phy_info_t *pi);
+extern u32 wlc_phy_qdiv_roundup(u32 dividend, u32 divisor,
+				   u8 precision);
+
+#define LCNPHY_TBL_ID_PAPDCOMPDELTATBL	0x18
+#define LCNPHY_TX_POWER_TABLE_SIZE	128
+#define LCNPHY_MAX_TX_POWER_INDEX	(LCNPHY_TX_POWER_TABLE_SIZE - 1)
+#define LCNPHY_TBL_ID_TXPWRCTL 	0x07
+#define LCNPHY_TX_PWR_CTRL_OFF	0
+#define LCNPHY_TX_PWR_CTRL_SW		(0x1 << 15)
+#define LCNPHY_TX_PWR_CTRL_HW         ((0x1 << 15) | \
+					(0x1 << 14) | \
+					(0x1 << 13))
+
+#define LCNPHY_TX_PWR_CTRL_TEMPBASED	0xE001
+
+extern void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti);
+extern void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti);
+extern void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b);
+extern void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq);
+extern void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b);
+extern u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi);
+extern void wlc_lcnphy_get_radio_loft(phy_info_t *pi, u8 *ei0,
+				      u8 *eq0, u8 *fi0, u8 *fq0);
+extern void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode);
+extern void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode);
+extern bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi);
+extern void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi);
+extern s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1);
+extern void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr,
+				s8 *cck_pwr);
+extern void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi);
+
+extern s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index);
+
+#define NPHY_MAX_HPVGA1_INDEX		10
+#define NPHY_DEF_HPVGA1_INDEXLIMIT	7
+
+typedef struct _phy_iq_est {
+	s32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+} phy_iq_est_t;
+
+extern void wlc_phy_stay_in_carriersearch_nphy(phy_info_t *pi, bool enable);
+extern void wlc_nphy_deaf_mode(phy_info_t *pi, bool mode);
+
+#define wlc_phy_write_table_nphy(pi, pti)	wlc_phy_write_table(pi, pti, 0x72, \
+	0x74, 0x73)
+#define wlc_phy_read_table_nphy(pi, pti)	wlc_phy_read_table(pi, pti, 0x72, \
+	0x74, 0x73)
+#define wlc_nphy_table_addr(pi, id, off)	wlc_phy_table_addr((pi), (id), (off), \
+	0x72, 0x74, 0x73)
+#define wlc_nphy_table_data_write(pi, w, v)	wlc_phy_table_data_write((pi), (w), (v))
+
+extern void wlc_phy_table_read_nphy(phy_info_t *pi, u32, u32 l, u32 o,
+				    u32 w, void *d);
+extern void wlc_phy_table_write_nphy(phy_info_t *pi, u32, u32, u32,
+				     u32, const void *);
+
+#define	PHY_IPA(pi) \
+	((pi->ipa2g_on && CHSPEC_IS2G(pi->radio_chanspec)) || \
+	 (pi->ipa5g_on && CHSPEC_IS5G(pi->radio_chanspec)))
+
+#define WLC_PHY_WAR_PR51571(pi) \
+	if (((pi)->sh->bustype == PCI_BUS) && NREV_LT((pi)->pubpi.phy_rev, 3)) \
+		(void)R_REG(&(pi)->regs->maccontrol)
+
+extern void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype);
+extern void wlc_phy_aci_reset_nphy(phy_info_t *pi);
+extern void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en);
+
+extern u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint chan);
+extern void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on);
+
+extern void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi);
+
+extern void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd);
+extern s16 wlc_phy_tempsense_nphy(phy_info_t *pi);
+
+extern u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val);
+
+extern void wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est,
+				   u16 num_samps, u8 wait_time,
+				   u8 wait_for_crs);
+
+extern void wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write,
+				      nphy_iq_comp_t *comp);
+extern void wlc_phy_aci_and_noise_reduction_nphy(phy_info_t *pi);
+
+extern void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask);
+extern u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih);
+
+extern void wlc_phy_txpwrctrl_enable_nphy(phy_info_t *pi, u8 ctrl_type);
+extern void wlc_phy_txpwr_fixpower_nphy(phy_info_t *pi);
+extern void wlc_phy_txpwr_apply_nphy(phy_info_t *pi);
+extern void wlc_phy_txpwr_papd_cal_nphy(phy_info_t *pi);
+extern u16 wlc_phy_txpwr_idx_get_nphy(phy_info_t *pi);
+
+extern nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi);
+extern int wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+				   bool full, bool m);
+extern int wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+				 u8 type, bool d);
+extern void wlc_phy_txpwr_index_nphy(phy_info_t *pi, u8 core_mask,
+				     s8 txpwrindex, bool res);
+extern void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core, u8 rssi_type);
+extern int wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type,
+				  s32 *rssi_buf, u8 nsamps);
+extern void wlc_phy_rssi_cal_nphy(phy_info_t *pi);
+extern int wlc_phy_aci_scan_nphy(phy_info_t *pi);
+extern void wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower,
+					bool debug);
+extern int wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+				u8 mode, u8, bool);
+extern void wlc_phy_stopplayback_nphy(phy_info_t *pi);
+extern void wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf,
+				     u8 num_samps);
+extern void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi);
+
+extern int wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh);
+
+#define NPHY_TESTPATTERN_BPHY_EVM   0
+#define NPHY_TESTPATTERN_BPHY_RFCS  1
+
+extern void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs);
+
+void wlc_phy_get_pwrdet_offsets(phy_info_t *pi, s8 *cckoffset,
+				s8 *ofdmoffset);
+extern s8 wlc_phy_upd_rssi_offset(phy_info_t *pi, s8 rssi,
+				    chanspec_t chanspec);
+
+extern bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pih);
+#endif				/* _wlc_phy_int_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,5325 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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/string.h>
+#include <linux/bitops.h>
+#include <linux/delay.h>
+#include <wlc_cfg.h>
+#include <qmath.h>
+#include <linux/pci.h>
+#include <siutils.h>
+#include <hndpmu.h>
+
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+
+#include <wlc_phy_radio.h>
+#include <wlc_phy_int.h>
+#include <wlc_phy_lcn.h>
+#include <wlc_phytbl_lcn.h>
+
+#define PLL_2064_NDIV		90
+#define PLL_2064_LOW_END_VCO 	3000
+#define PLL_2064_LOW_END_KVCO 	27
+#define PLL_2064_HIGH_END_VCO	4200
+#define PLL_2064_HIGH_END_KVCO	68
+#define PLL_2064_LOOP_BW_DOUBLER	200
+#define PLL_2064_D30_DOUBLER		10500
+#define PLL_2064_LOOP_BW	260
+#define PLL_2064_D30		8000
+#define PLL_2064_CAL_REF_TO	8
+#define PLL_2064_MHZ		1000000
+#define PLL_2064_OPEN_LOOP_DELAY	5
+
+#define TEMPSENSE 			1
+#define VBATSENSE           2
+
+#define NOISE_IF_UPD_CHK_INTERVAL	1
+#define NOISE_IF_UPD_RST_INTERVAL	60
+#define NOISE_IF_UPD_THRESHOLD_CNT	1
+#define NOISE_IF_UPD_TRHRESHOLD	50
+#define NOISE_IF_UPD_TIMEOUT		1000
+#define NOISE_IF_OFF			0
+#define NOISE_IF_CHK			1
+#define NOISE_IF_ON			2
+
+#define PAPD_BLANKING_PROFILE 		3
+#define PAPD2LUT			0
+#define PAPD_CORR_NORM 			0
+#define PAPD_BLANKING_THRESHOLD 	0
+#define PAPD_STOP_AFTER_LAST_UPDATE	0
+
+#define LCN_TARGET_PWR  60
+
+#define LCN_VBAT_OFFSET_433X 34649679
+#define LCN_VBAT_SLOPE_433X  8258032
+
+#define LCN_VBAT_SCALE_NOM  53
+#define LCN_VBAT_SCALE_DEN  432
+
+#define LCN_TEMPSENSE_OFFSET  80812
+#define LCN_TEMPSENSE_DEN  2647
+
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT \
+	(0 + 8)
+#define LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK \
+	(0x7f << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT)
+
+#define wlc_lcnphy_enable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, true)
+#define wlc_lcnphy_disable_tx_gain_override(pi) \
+	wlc_lcnphy_set_tx_gain_override(pi, false)
+
+#define wlc_lcnphy_iqcal_active(pi)	\
+	(read_phy_reg((pi), 0x451) & \
+	((0x1 << 15) | (0x1 << 14)))
+
+#define txpwrctrl_off(pi) (0x7 != ((read_phy_reg(pi, 0x4a4) & 0xE000) >> 13))
+#define wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) \
+	(pi->temppwrctrl_capable)
+#define wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) \
+	(pi->hwpwrctrl_capable)
+
+#define SWCTRL_BT_TX		0x18
+#define SWCTRL_OVR_DISABLE	0x40
+
+#define	AFE_CLK_INIT_MODE_TXRX2X	1
+#define	AFE_CLK_INIT_MODE_PAPD		0
+
+#define LCNPHY_TBL_ID_IQLOCAL			0x00
+
+#define LCNPHY_TBL_ID_RFSEQ         0x08
+#define LCNPHY_TBL_ID_GAIN_IDX		0x0d
+#define LCNPHY_TBL_ID_SW_CTRL			0x0f
+#define LCNPHY_TBL_ID_GAIN_TBL		0x12
+#define LCNPHY_TBL_ID_SPUR			0x14
+#define LCNPHY_TBL_ID_SAMPLEPLAY		0x15
+#define LCNPHY_TBL_ID_SAMPLEPLAY1		0x16
+
+#define LCNPHY_TX_PWR_CTRL_RATE_OFFSET 	832
+#define LCNPHY_TX_PWR_CTRL_MAC_OFFSET 	128
+#define LCNPHY_TX_PWR_CTRL_GAIN_OFFSET 	192
+#define LCNPHY_TX_PWR_CTRL_IQ_OFFSET		320
+#define LCNPHY_TX_PWR_CTRL_LO_OFFSET		448
+#define LCNPHY_TX_PWR_CTRL_PWR_OFFSET		576
+
+#define LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313	140
+
+#define LCNPHY_TX_PWR_CTRL_START_NPT		1
+#define LCNPHY_TX_PWR_CTRL_MAX_NPT			7
+
+#define LCNPHY_NOISE_SAMPLES_DEFAULT 5000
+
+#define LCNPHY_ACI_DETECT_START      1
+#define LCNPHY_ACI_DETECT_PROGRESS   2
+#define LCNPHY_ACI_DETECT_STOP       3
+
+#define LCNPHY_ACI_CRSHIFRMLO_TRSH 100
+#define LCNPHY_ACI_GLITCH_TRSH 2000
+#define	LCNPHY_ACI_TMOUT 250
+#define LCNPHY_ACI_DETECT_TIMEOUT  2
+#define LCNPHY_ACI_START_DELAY 0
+
+#define wlc_lcnphy_tx_gain_override_enabled(pi) \
+	(0 != (read_phy_reg((pi), 0x43b) & (0x1 << 6)))
+
+#define wlc_lcnphy_total_tx_frames(pi) \
+	wlapi_bmac_read_shm((pi)->sh->physhim, M_UCODE_MACSTAT + offsetof(macstat_t, txallfrm))
+
+typedef struct {
+	u16 gm_gain;
+	u16 pga_gain;
+	u16 pad_gain;
+	u16 dac_gain;
+} lcnphy_txgains_t;
+
+typedef enum {
+	LCNPHY_CAL_FULL,
+	LCNPHY_CAL_RECAL,
+	LCNPHY_CAL_CURRECAL,
+	LCNPHY_CAL_DIGCAL,
+	LCNPHY_CAL_GCTRL
+} lcnphy_cal_mode_t;
+
+typedef struct {
+	lcnphy_txgains_t gains;
+	bool useindex;
+	u8 index;
+} lcnphy_txcalgains_t;
+
+typedef struct {
+	u8 chan;
+	s16 a;
+	s16 b;
+} lcnphy_rx_iqcomp_t;
+
+typedef struct {
+	s16 re;
+	s16 im;
+} lcnphy_spb_tone_t;
+
+typedef struct {
+	u16 re;
+	u16 im;
+} lcnphy_unsign16_struct;
+
+typedef struct {
+	u32 iq_prod;
+	u32 i_pwr;
+	u32 q_pwr;
+} lcnphy_iq_est_t;
+
+typedef struct {
+	u16 ptcentreTs20;
+	u16 ptcentreFactor;
+} lcnphy_sfo_cfg_t;
+
+typedef enum {
+	LCNPHY_PAPD_CAL_CW,
+	LCNPHY_PAPD_CAL_OFDM
+} lcnphy_papd_cal_type_t;
+
+typedef u16 iqcal_gain_params_lcnphy[9];
+
+static const iqcal_gain_params_lcnphy tbl_iqcal_gainparams_lcnphy_2G[] = {
+	{0, 0, 0, 0, 0, 0, 0, 0, 0},
+};
+
+static const iqcal_gain_params_lcnphy *tbl_iqcal_gainparams_lcnphy[1] = {
+	tbl_iqcal_gainparams_lcnphy_2G,
+};
+
+static const u16 iqcal_gainparams_numgains_lcnphy[1] = {
+	sizeof(tbl_iqcal_gainparams_lcnphy_2G) /
+	    sizeof(*tbl_iqcal_gainparams_lcnphy_2G),
+};
+
+static const lcnphy_sfo_cfg_t lcnphy_sfo_cfg[] = {
+	{965, 1087},
+	{967, 1085},
+	{969, 1082},
+	{971, 1080},
+	{973, 1078},
+	{975, 1076},
+	{977, 1073},
+	{979, 1071},
+	{981, 1069},
+	{983, 1067},
+	{985, 1065},
+	{987, 1063},
+	{989, 1060},
+	{994, 1055}
+};
+
+static const
+u16 lcnphy_iqcal_loft_gainladder[] = {
+	((2 << 8) | 0),
+	((3 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((16 << 8) | 1),
+	((16 << 8) | 2),
+	((16 << 8) | 3),
+	((16 << 8) | 4),
+	((16 << 8) | 5),
+	((16 << 8) | 6),
+	((16 << 8) | 7),
+	((23 << 8) | 7),
+	((32 << 8) | 7),
+	((45 << 8) | 7),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+u16 lcnphy_iqcal_ir_gainladder[] = {
+	((1 << 8) | 0),
+	((2 << 8) | 0),
+	((4 << 8) | 0),
+	((6 << 8) | 0),
+	((8 << 8) | 0),
+	((11 << 8) | 0),
+	((16 << 8) | 0),
+	((23 << 8) | 0),
+	((32 << 8) | 0),
+	((45 << 8) | 0),
+	((64 << 8) | 0),
+	((64 << 8) | 1),
+	((64 << 8) | 2),
+	((64 << 8) | 3),
+	((64 << 8) | 4),
+	((64 << 8) | 5),
+	((64 << 8) | 6),
+	((64 << 8) | 7),
+	((91 << 8) | 7),
+	((128 << 8) | 7)
+};
+
+static const
+lcnphy_spb_tone_t lcnphy_spb_tone_3750[] = {
+	{88, 0},
+	{73, 49},
+	{34, 81},
+	{-17, 86},
+	{-62, 62},
+	{-86, 17},
+	{-81, -34},
+	{-49, -73},
+	{0, -88},
+	{49, -73},
+	{81, -34},
+	{86, 17},
+	{62, 62},
+	{17, 86},
+	{-34, 81},
+	{-73, 49},
+	{-88, 0},
+	{-73, -49},
+	{-34, -81},
+	{17, -86},
+	{62, -62},
+	{86, -17},
+	{81, 34},
+	{49, 73},
+	{0, 88},
+	{-49, 73},
+	{-81, 34},
+	{-86, -17},
+	{-62, -62},
+	{-17, -86},
+	{34, -81},
+	{73, -49},
+};
+
+static const
+u16 iqlo_loopback_rf_regs[20] = {
+	RADIO_2064_REG036,
+	RADIO_2064_REG11A,
+	RADIO_2064_REG03A,
+	RADIO_2064_REG025,
+	RADIO_2064_REG028,
+	RADIO_2064_REG005,
+	RADIO_2064_REG112,
+	RADIO_2064_REG0FF,
+	RADIO_2064_REG11F,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG007,
+	RADIO_2064_REG0FC,
+	RADIO_2064_REG0FD,
+	RADIO_2064_REG012,
+	RADIO_2064_REG057,
+	RADIO_2064_REG059,
+	RADIO_2064_REG05C,
+	RADIO_2064_REG078,
+	RADIO_2064_REG092,
+};
+
+static const
+u16 tempsense_phy_regs[14] = {
+	0x503,
+	0x4a4,
+	0x4d0,
+	0x4d9,
+	0x4da,
+	0x4a6,
+	0x938,
+	0x939,
+	0x4d8,
+	0x4d0,
+	0x4d7,
+	0x4a5,
+	0x40d,
+	0x4a2,
+};
+
+static const
+u16 rxiq_cal_rf_reg[11] = {
+	RADIO_2064_REG098,
+	RADIO_2064_REG116,
+	RADIO_2064_REG12C,
+	RADIO_2064_REG06A,
+	RADIO_2064_REG00B,
+	RADIO_2064_REG01B,
+	RADIO_2064_REG113,
+	RADIO_2064_REG01D,
+	RADIO_2064_REG114,
+	RADIO_2064_REG02E,
+	RADIO_2064_REG12A,
+};
+
+static const
+lcnphy_rx_iqcomp_t lcnphy_rx_iqcomp_table_rev0[] = {
+	{1, 0, 0},
+	{2, 0, 0},
+	{3, 0, 0},
+	{4, 0, 0},
+	{5, 0, 0},
+	{6, 0, 0},
+	{7, 0, 0},
+	{8, 0, 0},
+	{9, 0, 0},
+	{10, 0, 0},
+	{11, 0, 0},
+	{12, 0, 0},
+	{13, 0, 0},
+	{14, 0, 0},
+	{34, 0, 0},
+	{38, 0, 0},
+	{42, 0, 0},
+	{46, 0, 0},
+	{36, 0, 0},
+	{40, 0, 0},
+	{44, 0, 0},
+	{48, 0, 0},
+	{52, 0, 0},
+	{56, 0, 0},
+	{60, 0, 0},
+	{64, 0, 0},
+	{100, 0, 0},
+	{104, 0, 0},
+	{108, 0, 0},
+	{112, 0, 0},
+	{116, 0, 0},
+	{120, 0, 0},
+	{124, 0, 0},
+	{128, 0, 0},
+	{132, 0, 0},
+	{136, 0, 0},
+	{140, 0, 0},
+	{149, 0, 0},
+	{153, 0, 0},
+	{157, 0, 0},
+	{161, 0, 0},
+	{165, 0, 0},
+	{184, 0, 0},
+	{188, 0, 0},
+	{192, 0, 0},
+	{196, 0, 0},
+	{200, 0, 0},
+	{204, 0, 0},
+	{208, 0, 0},
+	{212, 0, 0},
+	{216, 0, 0},
+};
+
+static const u32 lcnphy_23bitgaincode_table[] = {
+	0x200100,
+	0x200200,
+	0x200004,
+	0x200014,
+	0x200024,
+	0x200034,
+	0x200134,
+	0x200234,
+	0x200334,
+	0x200434,
+	0x200037,
+	0x200137,
+	0x200237,
+	0x200337,
+	0x200437,
+	0x000035,
+	0x000135,
+	0x000235,
+	0x000037,
+	0x000137,
+	0x000237,
+	0x000337,
+	0x00013f,
+	0x00023f,
+	0x00033f,
+	0x00034f,
+	0x00044f,
+	0x00144f,
+	0x00244f,
+	0x00254f,
+	0x00354f,
+	0x00454f,
+	0x00464f,
+	0x01464f,
+	0x02464f,
+	0x03464f,
+	0x04464f,
+};
+
+static const s8 lcnphy_gain_table[] = {
+	-16,
+	-13,
+	10,
+	7,
+	4,
+	0,
+	3,
+	6,
+	9,
+	12,
+	15,
+	18,
+	21,
+	24,
+	27,
+	30,
+	33,
+	36,
+	39,
+	42,
+	45,
+	48,
+	50,
+	53,
+	56,
+	59,
+	62,
+	65,
+	68,
+	71,
+	74,
+	77,
+	80,
+	83,
+	86,
+	89,
+	92,
+};
+
+static const s8 lcnphy_gain_index_offset_for_rssi[] = {
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	7,
+	8,
+	7,
+	7,
+	6,
+	7,
+	7,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	4,
+	3,
+	3,
+	3,
+	3,
+	3,
+	3,
+	4,
+	2,
+	2,
+	2,
+	2,
+	2,
+	2,
+	-1,
+	-2,
+	-2,
+	-2
+};
+
+extern const u8 spur_tbl_rev0[];
+extern const u32 dot11lcnphytbl_rx_gain_info_sz_rev1;
+extern const dot11lcnphytbl_info_t dot11lcnphytbl_rx_gain_info_rev1[];
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa;
+extern const dot11lcnphytbl_info_t dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250;
+
+typedef struct _chan_info_2064_lcnphy {
+	uint chan;
+	uint freq;
+	u8 logen_buftune;
+	u8 logen_rccr_tx;
+	u8 txrf_mix_tune_ctrl;
+	u8 pa_input_tune_g;
+	u8 logen_rccr_rx;
+	u8 pa_rxrf_lna1_freq_tune;
+	u8 pa_rxrf_lna2_freq_tune;
+	u8 rxrf_rxrf_spare1;
+} chan_info_2064_lcnphy_t;
+
+static chan_info_2064_lcnphy_t chan_info_2064_lcnphy[] = {
+	{1, 2412, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{2, 2417, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{3, 2422, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{4, 2427, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{5, 2432, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{6, 2437, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{7, 2442, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{8, 2447, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{9, 2452, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{10, 2457, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{11, 2462, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{12, 2467, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{13, 2472, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+	{14, 2484, 0x0B, 0x0A, 0x00, 0x07, 0x0A, 0x88, 0x88, 0x80},
+};
+
+lcnphy_radio_regs_t lcnphy_radio_regs_2064[] = {
+	{0x00, 0, 0, 0, 0},
+	{0x01, 0x64, 0x64, 0, 0},
+	{0x02, 0x20, 0x20, 0, 0},
+	{0x03, 0x66, 0x66, 0, 0},
+	{0x04, 0xf8, 0xf8, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x10, 0x10, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0x37, 0x37, 0, 0},
+	{0x0B, 0x6, 0x6, 0, 0},
+	{0x0C, 0x55, 0x55, 0, 0},
+	{0x0D, 0x8b, 0x8b, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0x5, 0x5, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0xe, 0xe, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0xb, 0xb, 0, 0},
+	{0x14, 0x2, 0x2, 0, 0},
+	{0x15, 0x12, 0x12, 0, 0},
+	{0x16, 0x12, 0x12, 0, 0},
+	{0x17, 0xc, 0xc, 0, 0},
+	{0x18, 0xc, 0xc, 0, 0},
+	{0x19, 0xc, 0xc, 0, 0},
+	{0x1A, 0x8, 0x8, 0, 0},
+	{0x1B, 0x2, 0x2, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0x1, 0x1, 0, 0},
+	{0x1E, 0x12, 0x12, 0, 0},
+	{0x1F, 0x6e, 0x6e, 0, 0},
+	{0x20, 0x2, 0x2, 0, 0},
+	{0x21, 0x23, 0x23, 0, 0},
+	{0x22, 0x8, 0x8, 0, 0},
+	{0x23, 0, 0, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0x33, 0x33, 0, 0},
+	{0x27, 0x55, 0x55, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x30, 0x30, 0, 0},
+	{0x2A, 0xb, 0xb, 0, 0},
+	{0x2B, 0x1b, 0x1b, 0, 0},
+	{0x2C, 0x3, 0x3, 0, 0},
+	{0x2D, 0x1b, 0x1b, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x20, 0x20, 0, 0},
+	{0x30, 0xa, 0xa, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0x62, 0x62, 0, 0},
+	{0x33, 0x19, 0x19, 0, 0},
+	{0x34, 0x33, 0x33, 0, 0},
+	{0x35, 0x77, 0x77, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x70, 0x70, 0, 0},
+	{0x38, 0x3, 0x3, 0, 0},
+	{0x39, 0xf, 0xf, 0, 0},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0xcf, 0xcf, 0, 0},
+	{0x3C, 0x1a, 0x1a, 0, 0},
+	{0x3D, 0x6, 0x6, 0, 0},
+	{0x3E, 0x42, 0x42, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0xfb, 0xfb, 0, 0},
+	{0x41, 0x9a, 0x9a, 0, 0},
+	{0x42, 0x7a, 0x7a, 0, 0},
+	{0x43, 0x29, 0x29, 0, 0},
+	{0x44, 0, 0, 0, 0},
+	{0x45, 0x8, 0x8, 0, 0},
+	{0x46, 0xce, 0xce, 0, 0},
+	{0x47, 0x27, 0x27, 0, 0},
+	{0x48, 0x62, 0x62, 0, 0},
+	{0x49, 0x6, 0x6, 0, 0},
+	{0x4A, 0x58, 0x58, 0, 0},
+	{0x4B, 0xf7, 0xf7, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0xb3, 0xb3, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0, 0, 0, 0},
+	{0x51, 0x9, 0x9, 0, 0},
+	{0x52, 0x5, 0x5, 0, 0},
+	{0x53, 0x17, 0x17, 0, 0},
+	{0x54, 0x38, 0x38, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0xb, 0xb, 0, 0},
+	{0x58, 0, 0, 0, 0},
+	{0x59, 0, 0, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0, 0, 0, 0},
+	{0x5C, 0, 0, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x88, 0x88, 0, 0},
+	{0x5F, 0xcc, 0xcc, 0, 0},
+	{0x60, 0x74, 0x74, 0, 0},
+	{0x61, 0x74, 0x74, 0, 0},
+	{0x62, 0x74, 0x74, 0, 0},
+	{0x63, 0x44, 0x44, 0, 0},
+	{0x64, 0x77, 0x77, 0, 0},
+	{0x65, 0x44, 0x44, 0, 0},
+	{0x66, 0x77, 0x77, 0, 0},
+	{0x67, 0x55, 0x55, 0, 0},
+	{0x68, 0x77, 0x77, 0, 0},
+	{0x69, 0x77, 0x77, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0x7f, 0x7f, 0, 0},
+	{0x6C, 0x8, 0x8, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0x88, 0x88, 0, 0},
+	{0x6F, 0x66, 0x66, 0, 0},
+	{0x70, 0x66, 0x66, 0, 0},
+	{0x71, 0x28, 0x28, 0, 0},
+	{0x72, 0x55, 0x55, 0, 0},
+	{0x73, 0x4, 0x4, 0, 0},
+	{0x74, 0, 0, 0, 0},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0, 0, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0xd6, 0xd6, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0xb4, 0xb4, 0, 0},
+	{0x84, 0x1, 0x1, 0, 0},
+	{0x85, 0x20, 0x20, 0, 0},
+	{0x86, 0x5, 0x5, 0, 0},
+	{0x87, 0xff, 0xff, 0, 0},
+	{0x88, 0x7, 0x7, 0, 0},
+	{0x89, 0x77, 0x77, 0, 0},
+	{0x8A, 0x77, 0x77, 0, 0},
+	{0x8B, 0x77, 0x77, 0, 0},
+	{0x8C, 0x77, 0x77, 0, 0},
+	{0x8D, 0x8, 0x8, 0, 0},
+	{0x8E, 0xa, 0xa, 0, 0},
+	{0x8F, 0x8, 0x8, 0, 0},
+	{0x90, 0x18, 0x18, 0, 0},
+	{0x91, 0x5, 0x5, 0, 0},
+	{0x92, 0x1f, 0x1f, 0, 0},
+	{0x93, 0x10, 0x10, 0, 0},
+	{0x94, 0x3, 0x3, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0xaa, 0xaa, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0x23, 0x23, 0, 0},
+	{0x9A, 0x7, 0x7, 0, 0},
+	{0x9B, 0xf, 0xf, 0, 0},
+	{0x9C, 0x10, 0x10, 0, 0},
+	{0x9D, 0x3, 0x3, 0, 0},
+	{0x9E, 0x4, 0x4, 0, 0},
+	{0x9F, 0x20, 0x20, 0, 0},
+	{0xA0, 0, 0, 0, 0},
+	{0xA1, 0, 0, 0, 0},
+	{0xA2, 0, 0, 0, 0},
+	{0xA3, 0, 0, 0, 0},
+	{0xA4, 0x1, 0x1, 0, 0},
+	{0xA5, 0x77, 0x77, 0, 0},
+	{0xA6, 0x77, 0x77, 0, 0},
+	{0xA7, 0x77, 0x77, 0, 0},
+	{0xA8, 0x77, 0x77, 0, 0},
+	{0xA9, 0x8c, 0x8c, 0, 0},
+	{0xAA, 0x88, 0x88, 0, 0},
+	{0xAB, 0x78, 0x78, 0, 0},
+	{0xAC, 0x57, 0x57, 0, 0},
+	{0xAD, 0x88, 0x88, 0, 0},
+	{0xAE, 0, 0, 0, 0},
+	{0xAF, 0x8, 0x8, 0, 0},
+	{0xB0, 0x88, 0x88, 0, 0},
+	{0xB1, 0, 0, 0, 0},
+	{0xB2, 0x1b, 0x1b, 0, 0},
+	{0xB3, 0x3, 0x3, 0, 0},
+	{0xB4, 0x24, 0x24, 0, 0},
+	{0xB5, 0x3, 0x3, 0, 0},
+	{0xB6, 0x1b, 0x1b, 0, 0},
+	{0xB7, 0x24, 0x24, 0, 0},
+	{0xB8, 0x3, 0x3, 0, 0},
+	{0xB9, 0, 0, 0, 0},
+	{0xBA, 0xaa, 0xaa, 0, 0},
+	{0xBB, 0, 0, 0, 0},
+	{0xBC, 0x4, 0x4, 0, 0},
+	{0xBD, 0, 0, 0, 0},
+	{0xBE, 0x8, 0x8, 0, 0},
+	{0xBF, 0x11, 0x11, 0, 0},
+	{0xC0, 0, 0, 0, 0},
+	{0xC1, 0, 0, 0, 0},
+	{0xC2, 0x62, 0x62, 0, 0},
+	{0xC3, 0x1e, 0x1e, 0, 0},
+	{0xC4, 0x33, 0x33, 0, 0},
+	{0xC5, 0x37, 0x37, 0, 0},
+	{0xC6, 0, 0, 0, 0},
+	{0xC7, 0x70, 0x70, 0, 0},
+	{0xC8, 0x1e, 0x1e, 0, 0},
+	{0xC9, 0x6, 0x6, 0, 0},
+	{0xCA, 0x4, 0x4, 0, 0},
+	{0xCB, 0x2f, 0x2f, 0, 0},
+	{0xCC, 0xf, 0xf, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0xff, 0xff, 0, 0},
+	{0xCF, 0x8, 0x8, 0, 0},
+	{0xD0, 0x3f, 0x3f, 0, 0},
+	{0xD1, 0x3f, 0x3f, 0, 0},
+	{0xD2, 0x3f, 0x3f, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0xcc, 0xcc, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0x8, 0x8, 0, 0},
+	{0xD9, 0x8, 0x8, 0, 0},
+	{0xDA, 0x8, 0x8, 0, 0},
+	{0xDB, 0x11, 0x11, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x87, 0x87, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0x8, 0x8, 0, 0},
+	{0xE0, 0x8, 0x8, 0, 0},
+	{0xE1, 0x8, 0x8, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xE3, 0, 0, 0, 0},
+	{0xE4, 0, 0, 0, 0},
+	{0xE5, 0xf5, 0xf5, 0, 0},
+	{0xE6, 0x30, 0x30, 0, 0},
+	{0xE7, 0x1, 0x1, 0, 0},
+	{0xE8, 0, 0, 0, 0},
+	{0xE9, 0xff, 0xff, 0, 0},
+	{0xEA, 0, 0, 0, 0},
+	{0xEB, 0, 0, 0, 0},
+	{0xEC, 0x22, 0x22, 0, 0},
+	{0xED, 0, 0, 0, 0},
+	{0xEE, 0, 0, 0, 0},
+	{0xEF, 0, 0, 0, 0},
+	{0xF0, 0x3, 0x3, 0, 0},
+	{0xF1, 0x1, 0x1, 0, 0},
+	{0xF2, 0, 0, 0, 0},
+	{0xF3, 0, 0, 0, 0},
+	{0xF4, 0, 0, 0, 0},
+	{0xF5, 0, 0, 0, 0},
+	{0xF6, 0, 0, 0, 0},
+	{0xF7, 0x6, 0x6, 0, 0},
+	{0xF8, 0, 0, 0, 0},
+	{0xF9, 0, 0, 0, 0},
+	{0xFA, 0x40, 0x40, 0, 0},
+	{0xFB, 0, 0, 0, 0},
+	{0xFC, 0x1, 0x1, 0, 0},
+	{0xFD, 0x80, 0x80, 0, 0},
+	{0xFE, 0x2, 0x2, 0, 0},
+	{0xFF, 0x10, 0x10, 0, 0},
+	{0x100, 0x2, 0x2, 0, 0},
+	{0x101, 0x1e, 0x1e, 0, 0},
+	{0x102, 0x1e, 0x1e, 0, 0},
+	{0x103, 0, 0, 0, 0},
+	{0x104, 0x1f, 0x1f, 0, 0},
+	{0x105, 0, 0x8, 0, 1},
+	{0x106, 0x2a, 0x2a, 0, 0},
+	{0x107, 0xf, 0xf, 0, 0},
+	{0x108, 0, 0, 0, 0},
+	{0x109, 0, 0, 0, 0},
+	{0x10A, 0, 0, 0, 0},
+	{0x10B, 0, 0, 0, 0},
+	{0x10C, 0, 0, 0, 0},
+	{0x10D, 0, 0, 0, 0},
+	{0x10E, 0, 0, 0, 0},
+	{0x10F, 0, 0, 0, 0},
+	{0x110, 0, 0, 0, 0},
+	{0x111, 0, 0, 0, 0},
+	{0x112, 0, 0, 0, 0},
+	{0x113, 0, 0, 0, 0},
+	{0x114, 0, 0, 0, 0},
+	{0x115, 0, 0, 0, 0},
+	{0x116, 0, 0, 0, 0},
+	{0x117, 0, 0, 0, 0},
+	{0x118, 0, 0, 0, 0},
+	{0x119, 0, 0, 0, 0},
+	{0x11A, 0, 0, 0, 0},
+	{0x11B, 0, 0, 0, 0},
+	{0x11C, 0x1, 0x1, 0, 0},
+	{0x11D, 0, 0, 0, 0},
+	{0x11E, 0, 0, 0, 0},
+	{0x11F, 0, 0, 0, 0},
+	{0x120, 0, 0, 0, 0},
+	{0x121, 0, 0, 0, 0},
+	{0x122, 0x80, 0x80, 0, 0},
+	{0x123, 0, 0, 0, 0},
+	{0x124, 0xf8, 0xf8, 0, 0},
+	{0x125, 0, 0, 0, 0},
+	{0x126, 0, 0, 0, 0},
+	{0x127, 0, 0, 0, 0},
+	{0x128, 0, 0, 0, 0},
+	{0x129, 0, 0, 0, 0},
+	{0x12A, 0, 0, 0, 0},
+	{0x12B, 0, 0, 0, 0},
+	{0x12C, 0, 0, 0, 0},
+	{0x12D, 0, 0, 0, 0},
+	{0x12E, 0, 0, 0, 0},
+	{0x12F, 0, 0, 0, 0},
+	{0x130, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+#define LCNPHY_NUM_DIG_FILT_COEFFS 16
+#define LCNPHY_NUM_TX_DIG_FILTERS_CCK 13
+
+u16
+    LCNPHY_txdigfiltcoeffs_cck[LCNPHY_NUM_TX_DIG_FILTERS_CCK]
+    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 1, 415, 1874, 64, 128, 64, 792, 1656, 64, 128, 64, 778, 1582, 64,
+	 128, 64,},
+	{1, 1, 402, 1847, 259, 59, 259, 671, 1794, 68, 54, 68, 608, 1863, 93,
+	 167, 93,},
+	{2, 1, 415, 1874, 64, 128, 64, 792, 1656, 192, 384, 192, 778, 1582, 64,
+	 128, 64,},
+	{3, 1, 302, 1841, 129, 258, 129, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+	{20, 1, 360, 1884, 242, 1734, 242, 752, 1720, 205, 1845, 205, 767, 1760,
+	 256, 185, 256,},
+	{21, 1, 360, 1884, 149, 1874, 149, 752, 1720, 205, 1883, 205, 767, 1760,
+	 256, 273, 256,},
+	{22, 1, 360, 1884, 98, 1948, 98, 752, 1720, 205, 1924, 205, 767, 1760,
+	 256, 352, 256,},
+	{23, 1, 350, 1884, 116, 1966, 116, 752, 1720, 205, 2008, 205, 767, 1760,
+	 128, 233, 128,},
+	{24, 1, 325, 1884, 32, 40, 32, 756, 1720, 256, 471, 256, 766, 1760, 256,
+	 1881, 256,},
+	{25, 1, 299, 1884, 51, 64, 51, 736, 1720, 256, 471, 256, 765, 1760, 256,
+	 1881, 256,},
+	{26, 1, 277, 1943, 39, 117, 88, 637, 1838, 64, 192, 144, 614, 1864, 128,
+	 384, 288,},
+	{27, 1, 245, 1943, 49, 147, 110, 626, 1838, 256, 768, 576, 613, 1864,
+	 128, 384, 288,},
+	{30, 1, 302, 1841, 61, 122, 61, 658, 1720, 205, 410, 205, 754, 1760,
+	 170, 340, 170,},
+};
+
+#define LCNPHY_NUM_TX_DIG_FILTERS_OFDM 3
+u16
+    LCNPHY_txdigfiltcoeffs_ofdm[LCNPHY_NUM_TX_DIG_FILTERS_OFDM]
+    [LCNPHY_NUM_DIG_FILT_COEFFS + 1] = {
+	{0, 0, 0xa2, 0x0, 0x100, 0x100, 0x0, 0x0, 0x0, 0x100, 0x0, 0x0,
+	 0x278, 0xfea0, 0x80, 0x100, 0x80,},
+	{1, 0, 374, 0xFF79, 16, 32, 16, 799, 0xFE74, 50, 32, 50,
+	 750, 0xFE2B, 212, 0xFFCE, 212,},
+	{2, 0, 375, 0xFF16, 37, 76, 37, 799, 0xFE74, 32, 20, 32, 748,
+	 0xFEF2, 128, 0xFFE2, 128}
+};
+
+#define wlc_lcnphy_set_start_tx_pwr_idx(pi, idx) \
+	mod_phy_reg(pi, 0x4a4, \
+		(0x1ff << 0), \
+		(u16)(idx) << 0)
+
+#define wlc_lcnphy_set_tx_pwr_npt(pi, npt) \
+	mod_phy_reg(pi, 0x4a5, \
+		(0x7 << 8), \
+		(u16)(npt) << 8)
+
+#define wlc_lcnphy_get_tx_pwr_ctrl(pi) \
+	(read_phy_reg((pi), 0x4a4) & \
+			((0x1 << 15) | \
+			(0x1 << 14) | \
+			(0x1 << 13)))
+
+#define wlc_lcnphy_get_tx_pwr_npt(pi) \
+	((read_phy_reg(pi, 0x4a5) & \
+		(0x7 << 8)) >> \
+		8)
+
+#define wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi) \
+	(read_phy_reg(pi, 0x473) & 0x1ff)
+
+#define wlc_lcnphy_get_target_tx_pwr(pi) \
+	((read_phy_reg(pi, 0x4a7) & \
+		(0xff << 0)) >> \
+		0)
+
+#define wlc_lcnphy_set_target_tx_pwr(pi, target) \
+	mod_phy_reg(pi, 0x4a7, \
+		(0xff << 0), \
+		(u16)(target) << 0)
+
+#define wlc_radio_2064_rcal_done(pi) (0 != (read_radio_reg(pi, RADIO_2064_REG05C) & 0x20))
+#define tempsense_done(pi) (0x8000 == (read_phy_reg(pi, 0x476) & 0x8000))
+
+#define LCNPHY_IQLOCC_READ(val) ((u8)(-(s8)(((val) & 0xf0) >> 4) + (s8)((val) & 0x0f)))
+#define FIXED_TXPWR 78
+#define LCNPHY_TEMPSENSE(val) ((s16)((val > 255) ? (val - 512) : val))
+
+static u32 wlc_lcnphy_qdiv_roundup(u32 divident, u32 divisor,
+				      u8 precision);
+static void wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
+						   u16 ext_lna, u16 trsw,
+						   u16 biq2, u16 biq1,
+						   u16 tia, u16 lna2,
+						   u16 lna1);
+static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi);
+static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain);
+static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx);
+static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0);
+static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi);
+static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains);
+static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable);
+static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi);
+static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable);
+static void wlc_lcnphy_set_tx_gain(phy_info_t *pi,
+				   lcnphy_txgains_t *target_gains);
+static bool wlc_lcnphy_rx_iq_est(phy_info_t *pi, u16 num_samps,
+				 u8 wait_time, lcnphy_iq_est_t *iq_est);
+static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps);
+static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi);
+static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode);
+extern void wlc_lcnphy_tx_pwr_ctrl_init(wlc_phy_t *ppi);
+static void wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi,
+						    u8 channel);
+
+static void wlc_lcnphy_load_tx_gain_table(phy_info_t *pi,
+					  const lcnphy_tx_gain_tbl_entry *g);
+
+static void wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo,
+				u16 thresh, s16 *ptr, int mode);
+static int wlc_lcnphy_calc_floor(s16 coeff, int type);
+static void wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi,
+					u16 *values_to_save);
+static void wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi,
+						u16 *values_to_save);
+static void wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x,
+			      s16 coeff_y);
+static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type);
+static void wlc_lcnphy_a1(phy_info_t *pi, int cal_type,
+			  int num_levels, int step_size_lg2);
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi);
+
+static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi,
+					   chanspec_t chanspec);
+static void wlc_lcnphy_agc_temp_init(phy_info_t *pi);
+static void wlc_lcnphy_temp_adj(phy_info_t *pi);
+static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi);
+static void wlc_lcnphy_baseband_init(phy_info_t *pi);
+static void wlc_lcnphy_radio_init(phy_info_t *pi);
+static void wlc_lcnphy_rc_cal(phy_info_t *pi);
+static void wlc_lcnphy_rcal(phy_info_t *pi);
+static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable);
+static int wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm,
+					 s16 filt_type);
+static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b);
+
+void wlc_lcnphy_write_table(phy_info_t *pi, const phytbl_info_t *pti)
+{
+	wlc_phy_write_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+void wlc_lcnphy_read_table(phy_info_t *pi, phytbl_info_t *pti)
+{
+	wlc_phy_read_table(pi, pti, 0x455, 0x457, 0x456);
+}
+
+static void
+wlc_lcnphy_common_read_table(phy_info_t *pi, u32 tbl_id,
+			     const void *tbl_ptr, u32 tbl_len,
+			     u32 tbl_width, u32 tbl_offset)
+{
+	phytbl_info_t tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_read_table(pi, &tab);
+}
+
+static void
+wlc_lcnphy_common_write_table(phy_info_t *pi, u32 tbl_id,
+			      const void *tbl_ptr, u32 tbl_len,
+			      u32 tbl_width, u32 tbl_offset)
+{
+
+	phytbl_info_t tab;
+	tab.tbl_id = tbl_id;
+	tab.tbl_ptr = tbl_ptr;
+	tab.tbl_len = tbl_len;
+	tab.tbl_width = tbl_width;
+	tab.tbl_offset = tbl_offset;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static u32
+wlc_lcnphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
+{
+	u32 quotient, remainder, roundup, rbit;
+
+	ASSERT(divisor);
+
+	quotient = dividend / divisor;
+	remainder = dividend % divisor;
+	rbit = divisor & 1;
+	roundup = (divisor >> 1) + rbit;
+
+	while (precision--) {
+		quotient <<= 1;
+		if (remainder >= roundup) {
+			quotient++;
+			remainder = ((remainder - roundup) << 1) + rbit;
+		} else {
+			remainder <<= 1;
+		}
+	}
+
+	if (remainder >= roundup)
+		quotient++;
+
+	return quotient;
+}
+
+static int wlc_lcnphy_calc_floor(s16 coeff_x, int type)
+{
+	int k;
+	k = 0;
+	if (type == 0) {
+		if (coeff_x < 0) {
+			k = (coeff_x - 1) / 2;
+		} else {
+			k = coeff_x / 2;
+		}
+	}
+	if (type == 1) {
+		if ((coeff_x + 1) < 0)
+			k = (coeff_x) / 2;
+		else
+			k = (coeff_x + 1) / 2;
+	}
+	return k;
+}
+
+s8 wlc_lcnphy_get_current_tx_pwr_idx(phy_info_t *pi)
+{
+	s8 index;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (txpwrctrl_off(pi))
+		index = pi_lcn->lcnphy_current_index;
+	else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		index =
+		    (s8) (wlc_lcnphy_get_current_tx_pwr_idx_if_pwrctrl_on(pi)
+			    / 2);
+	else
+		index = pi_lcn->lcnphy_current_index;
+	return index;
+}
+
+static u32 wlc_lcnphy_measure_digital_power(phy_info_t *pi, u16 nsamples)
+{
+	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
+
+	if (!wlc_lcnphy_rx_iq_est(pi, nsamples, 32, &iq_est))
+		return 0;
+	return (iq_est.i_pwr + iq_est.q_pwr) / nsamples;
+}
+
+void wlc_lcnphy_crsuprs(phy_info_t *pi, int channel)
+{
+	u16 afectrlovr, afectrlovrval;
+	afectrlovr = read_phy_reg(pi, 0x43b);
+	afectrlovrval = read_phy_reg(pi, 0x43c);
+	if (channel != 0) {
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), (1) << 1);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), (0) << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), (1) << 4);
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), (0) << 6);
+
+		write_phy_reg(pi, 0x44b, 0xffff);
+		wlc_lcnphy_tx_pu(pi, 1);
+
+		mod_phy_reg(pi, 0x634, (0xff << 8), (0) << 8);
+
+		or_phy_reg(pi, 0x6da, 0x0080);
+
+		or_phy_reg(pi, 0x00a, 0x228);
+	} else {
+		and_phy_reg(pi, 0x00a, ~(0x228));
+
+		and_phy_reg(pi, 0x6da, 0xFF7F);
+		write_phy_reg(pi, 0x43b, afectrlovr);
+		write_phy_reg(pi, 0x43c, afectrlovrval);
+	}
+}
+
+static void wlc_lcnphy_toggle_afe_pwdn(phy_info_t *pi)
+{
+	u16 save_AfeCtrlOvrVal, save_AfeCtrlOvr;
+
+	save_AfeCtrlOvrVal = read_phy_reg(pi, 0x43c);
+	save_AfeCtrlOvr = read_phy_reg(pi, 0x43b);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal | 0x1);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr | 0x1);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal & 0xfffe);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr & 0xfffe);
+
+	write_phy_reg(pi, 0x43c, save_AfeCtrlOvrVal);
+	write_phy_reg(pi, 0x43b, save_AfeCtrlOvr);
+}
+
+static void wlc_lcnphy_txrx_spur_avoidance_mode(phy_info_t *pi, bool enable)
+{
+	if (enable) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, ((1 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((1 << 13) + 1989));
+
+		write_phy_reg(pi, 0x44a, 0x084);
+		write_phy_reg(pi, 0x44a, 0x080);
+		write_phy_reg(pi, 0x6d3, 0x2222);
+		write_phy_reg(pi, 0x6d3, 0x2220);
+	} else {
+		write_phy_reg(pi, 0x942, 0x0);
+		write_phy_reg(pi, 0x93b, ((0 << 13) + 23));
+		write_phy_reg(pi, 0x93c, ((0 << 13) + 1989));
+	}
+	wlapi_switch_macfreq(pi->sh->physhim, enable);
+}
+
+void wlc_phy_chanspec_set_lcnphy(phy_info_t *pi, chanspec_t chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+
+	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
+
+	wlc_lcnphy_set_chanspec_tweaks(pi, pi->radio_chanspec);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!NORADIO_ENAB(pi->pubpi)) {
+		wlc_lcnphy_radio_2064_channel_tune_4313(pi, channel);
+		udelay(1000);
+	}
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+
+	write_phy_reg(pi, 0x657, lcnphy_sfo_cfg[channel - 1].ptcentreTs20);
+	write_phy_reg(pi, 0x658, lcnphy_sfo_cfg[channel - 1].ptcentreFactor);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 3);
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+		wlc_lcnphy_load_tx_iir_filter(pi, false, 2);
+	}
+
+	wlc_lcnphy_load_tx_iir_filter(pi, true, 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 3), (1) << 3);
+
+}
+
+static void wlc_lcnphy_set_dac_gain(phy_info_t *pi, u16 dac_gain)
+{
+	u16 dac_ctrl;
+
+	dac_ctrl = (read_phy_reg(pi, 0x439) >> 0);
+	dac_ctrl = dac_ctrl & 0xc7f;
+	dac_ctrl = dac_ctrl | (dac_gain << 7);
+	mod_phy_reg(pi, 0x439, (0xfff << 0), (dac_ctrl) << 0);
+
+}
+
+static void wlc_lcnphy_set_tx_gain_override(phy_info_t *pi, bool bEnable)
+{
+	u16 bit = bEnable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), bit << 7);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 14), bit << 14);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), bit << 6);
+}
+
+static u16 wlc_lcnphy_get_pa_gain(phy_info_t *pi)
+{
+	u16 pa_gain;
+
+	pa_gain = (read_phy_reg(pi, 0x4fb) &
+		   LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK) >>
+	    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT;
+
+	return pa_gain;
+}
+
+static void
+wlc_lcnphy_set_tx_gain(phy_info_t *pi, lcnphy_txgains_t *target_gains)
+{
+	u16 pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	mod_phy_reg(pi, 0x4b5,
+		    (0xffff << 0),
+		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
+		    0);
+	mod_phy_reg(pi, 0x4fb,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	mod_phy_reg(pi, 0x4fc,
+		    (0xffff << 0),
+		    ((target_gains->gm_gain) | (target_gains->pga_gain << 8)) <<
+		    0);
+	mod_phy_reg(pi, 0x4fd,
+		    (0x7fff << 0),
+		    ((target_gains->pad_gain) | (pa_gain << 8)) << 0);
+
+	wlc_lcnphy_set_dac_gain(pi, target_gains->dac_gain);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+}
+
+static void wlc_lcnphy_set_bbmult(phy_info_t *pi, u8 m0)
+{
+	u16 m0m1 = (u16) m0 << 8;
+	phytbl_info_t tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+static void wlc_lcnphy_clear_tx_power_offsets(phy_info_t *pi)
+{
+	u32 data_buf[64];
+	phytbl_info_t tab;
+
+	memset(data_buf, 0, sizeof(data_buf));
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = data_buf;
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		tab.tbl_len = 30;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_len = 64;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_MAC_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+typedef enum {
+	LCNPHY_TSSI_PRE_PA,
+	LCNPHY_TSSI_POST_PA,
+	LCNPHY_TSSI_EXT
+} lcnphy_tssi_mode_t;
+
+static void wlc_lcnphy_set_tssi_mux(phy_info_t *pi, lcnphy_tssi_mode_t pos)
+{
+	mod_phy_reg(pi, 0x4d7, (0x1 << 0), (0x1) << 0);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 6), (1) << 6);
+
+	if (LCNPHY_TSSI_POST_PA == pos) {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (1) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0x1);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	} else {
+		mod_phy_reg(pi, 0x4d9, (0x1 << 2), (0x1) << 2);
+
+		mod_phy_reg(pi, 0x4d9, (0x1 << 3), (0) << 3);
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+		} else {
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+			mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 0x8);
+		}
+	}
+	mod_phy_reg(pi, 0x637, (0x3 << 14), (0) << 14);
+
+	if (LCNPHY_TSSI_EXT == pos) {
+		write_radio_reg(pi, RADIO_2064_REG07F, 1);
+		mod_radio_reg(pi, RADIO_2064_REG005, 0x7, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 0x1 << 7);
+		mod_radio_reg(pi, RADIO_2064_REG028, 0x1f, 0x3);
+	}
+}
+
+static u16 wlc_lcnphy_rfseq_tbl_adc_pwrup(phy_info_t *pi)
+{
+	u16 N1, N2, N3, N4, N5, N6, N;
+	N1 = ((read_phy_reg(pi, 0x4a5) & (0xff << 0))
+	      >> 0);
+	N2 = 1 << ((read_phy_reg(pi, 0x4a5) & (0x7 << 12))
+		   >> 12);
+	N3 = ((read_phy_reg(pi, 0x40d) & (0xff << 0))
+	      >> 0);
+	N4 = 1 << ((read_phy_reg(pi, 0x40d) & (0x7 << 8))
+		   >> 8);
+	N5 = ((read_phy_reg(pi, 0x4a2) & (0xff << 0))
+	      >> 0);
+	N6 = 1 << ((read_phy_reg(pi, 0x4a2) & (0x7 << 8))
+		   >> 8);
+	N = 2 * (N1 + N2 + N3 + N4 + 2 * (N5 + N6)) + 80;
+	if (N < 1600)
+		N = 1600;
+	return N;
+}
+
+static void wlc_lcnphy_pwrctrl_rssiparams(phy_info_t *pi)
+{
+	u16 auxpga_vmid, auxpga_vmid_temp, auxpga_gain_temp;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	auxpga_vmid =
+	    (2 << 8) | (pi_lcn->lcnphy_rssi_vc << 4) | pi_lcn->lcnphy_rssi_vf;
+	auxpga_vmid_temp = (2 << 8) | (8 << 4) | 4;
+	auxpga_gain_temp = 2;
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (0) << 1);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x4db,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x4dc,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40a,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid << 0) | (pi_lcn->lcnphy_rssi_gs << 12));
+
+	mod_phy_reg(pi, 0x40b,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_phy_reg(pi, 0x40c,
+		    (0x3ff << 0) |
+		    (0x7 << 12),
+		    (auxpga_vmid_temp << 0) | (auxpga_gain_temp << 12));
+
+	mod_radio_reg(pi, RADIO_2064_REG082, (1 << 5), (1 << 5));
+}
+
+static void wlc_lcnphy_tssi_setup(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u32 rfseq, ind;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &ind;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 0;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	tab.tbl_offset = 704;
+	for (ind = 0; ind < 128; ind++) {
+		wlc_lcnphy_write_table(pi, &tab);
+		tab.tbl_offset++;
+	}
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 4), (1) << 4);
+
+	wlc_lcnphy_set_tssi_mux(pi, LCNPHY_TSSI_EXT);
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a4, (0x1ff << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (4) << 8);
+
+	mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a8, (0xff << 0), (0x1) << 0);
+
+	wlc_lcnphy_clear_tx_power_offsets(pi);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (0xff) << 0);
+
+	mod_phy_reg(pi, 0x49a, (0x1ff << 0), (0xff) << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG028, 0xf, 0xe);
+		mod_radio_reg(pi, RADIO_2064_REG086, 0x4, 0x4);
+	} else {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+		mod_radio_reg(pi, RADIO_2064_REG11A, 0x8, 1 << 3);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xc);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x1, 1);
+	} else {
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 0 << 1);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x2, 1 << 1);
+	else
+		mod_radio_reg(pi, RADIO_2064_REG03A, 0x4, 1 << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG11A, 0x1, 1 << 0);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 1 << 3);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		mod_phy_reg(pi, 0x4d7,
+			    (0x1 << 3) | (0x7 << 12), 0 << 3 | 2 << 12);
+	}
+
+	rfseq = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &rfseq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4d7, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4d7, (0xf << 8), (0) << 8);
+
+	wlc_lcnphy_pwrctrl_rssiparams(pi);
+}
+
+void wlc_lcnphy_tx_pwr_update_npt(phy_info_t *pi)
+{
+	u16 tx_cnt, tx_total, npt;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	tx_total = wlc_lcnphy_total_tx_frames(pi);
+	tx_cnt = tx_total - pi_lcn->lcnphy_tssi_tx_cnt;
+	npt = wlc_lcnphy_get_tx_pwr_npt(pi);
+
+	if (tx_cnt > (1 << npt)) {
+
+		pi_lcn->lcnphy_tssi_tx_cnt = tx_total;
+
+		pi_lcn->lcnphy_tssi_idx = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+		pi_lcn->lcnphy_tssi_npt = npt;
+
+	}
+}
+
+s32 wlc_lcnphy_tssi2dbm(s32 tssi, s32 a1, s32 b0, s32 b1)
+{
+	s32 a, b, p;
+
+	a = 32768 + (a1 * tssi);
+	b = (1024 * b0) + (64 * b1 * tssi);
+	p = ((2 * b) + a) / (2 * a);
+
+	return p;
+}
+
+static void wlc_lcnphy_txpower_reset_npt(phy_info_t *pi)
+{
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	pi_lcn->lcnphy_tssi_idx = LCNPHY_TX_PWR_CTRL_START_INDEX_2G_4313;
+	pi_lcn->lcnphy_tssi_npt = LCNPHY_TX_PWR_CTRL_START_NPT;
+}
+
+void wlc_lcnphy_txpower_recalc_target(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u32 rate_table[WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM +
+			  WLC_NUM_RATES_MCS_1_STREAM];
+	uint i, j;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return;
+
+	for (i = 0, j = 0; i < ARRAY_SIZE(rate_table); i++, j++) {
+
+		if (i == WLC_NUM_RATES_CCK + WLC_NUM_RATES_OFDM)
+			j = TXP_FIRST_MCS_20_SISO;
+
+		rate_table[i] = (u32) ((s32) (-pi->tx_power_offset[j]));
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = ARRAY_SIZE(rate_table);
+	tab.tbl_ptr = rate_table;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (wlc_lcnphy_get_target_tx_pwr(pi) != pi->tx_power_min) {
+		wlc_lcnphy_set_target_tx_pwr(pi, pi->tx_power_min);
+
+		wlc_lcnphy_txpower_reset_npt(pi);
+	}
+}
+
+static void wlc_lcnphy_set_tx_pwr_soft_ctrl(phy_info_t *pi, s8 index)
+{
+	u32 cck_offset[4] = { 22, 22, 22, 22 };
+	u32 ofdm_offset, reg_offset_cck;
+	int i;
+	u16 index2;
+	phytbl_info_t tab;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return;
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x0) << 14);
+
+	or_phy_reg(pi, 0x6da, 0x0040);
+
+	reg_offset_cck = 0;
+	for (i = 0; i < 4; i++)
+		cck_offset[i] -= reg_offset_cck;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 4;
+	tab.tbl_ptr = cck_offset;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+	wlc_lcnphy_write_table(pi, &tab);
+	ofdm_offset = 0;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &ofdm_offset;
+	for (i = 836; i < 862; i++) {
+		tab.tbl_offset = i;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0x1) << 15);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0x1) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 13), (0x1) << 13);
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 7), (0) << 7);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 6), (0) << 6);
+
+	mod_phy_reg(pi, 0x4a9, (0x1 << 15), (1) << 15);
+
+	index2 = (u16) (index * 2);
+	mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4), (0) << 4);
+
+}
+
+static s8 wlc_lcnphy_tempcompensated_txpwrctrl(phy_info_t *pi)
+{
+	s8 index, delta_brd, delta_temp, new_index, tempcorrx;
+	s16 manp, meas_temp, temp_diff;
+	bool neg = 0;
+	u16 temp;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi))
+		return pi_lcn->lcnphy_current_index;
+
+	index = FIXED_TXPWR;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return index;
+
+	if (pi_lcn->lcnphy_tempsense_slope == 0) {
+		return index;
+	}
+	temp = (u16) wlc_lcnphy_tempsense(pi, 0);
+	meas_temp = LCNPHY_TEMPSENSE(temp);
+
+	if (pi->tx_power_min != 0) {
+		delta_brd = (pi_lcn->lcnphy_measPower - pi->tx_power_min);
+	} else {
+		delta_brd = 0;
+	}
+
+	manp = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_rawtempsense);
+	temp_diff = manp - meas_temp;
+	if (temp_diff < 0) {
+
+		neg = 1;
+
+		temp_diff = -temp_diff;
+	}
+
+	delta_temp = (s8) wlc_lcnphy_qdiv_roundup((u32) (temp_diff * 192),
+						    (u32) (pi_lcn->
+							      lcnphy_tempsense_slope
+							      * 10), 0);
+	if (neg)
+		delta_temp = -delta_temp;
+
+	if (pi_lcn->lcnphy_tempsense_option == 3
+	    && LCNREV_IS(pi->pubpi.phy_rev, 0))
+		delta_temp = 0;
+	if (pi_lcn->lcnphy_tempcorrx > 31)
+		tempcorrx = (s8) (pi_lcn->lcnphy_tempcorrx - 64);
+	else
+		tempcorrx = (s8) pi_lcn->lcnphy_tempcorrx;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		tempcorrx = 4;
+	new_index =
+	    index + delta_brd + delta_temp - pi_lcn->lcnphy_bandedge_corr;
+	new_index += tempcorrx;
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		index = 127;
+	if (new_index < 0 || new_index > 126) {
+		return index;
+	}
+	return new_index;
+}
+
+static u16 wlc_lcnphy_set_tx_pwr_ctrl_mode(phy_info_t *pi, u16 mode)
+{
+
+	u16 current_mode = mode;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_HW)
+		current_mode = LCNPHY_TX_PWR_CTRL_TEMPBASED;
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    mode == LCNPHY_TX_PWR_CTRL_TEMPBASED)
+		current_mode = LCNPHY_TX_PWR_CTRL_HW;
+	return current_mode;
+}
+
+void wlc_lcnphy_set_tx_pwr_ctrl(phy_info_t *pi, u16 mode)
+{
+	u16 old_mode = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	ASSERT((LCNPHY_TX_PWR_CTRL_OFF == mode) ||
+	       (LCNPHY_TX_PWR_CTRL_SW == mode) ||
+	       (LCNPHY_TX_PWR_CTRL_HW == mode) ||
+	       (LCNPHY_TX_PWR_CTRL_TEMPBASED == mode));
+
+	mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, mode);
+	old_mode = wlc_lcnphy_set_tx_pwr_ctrl_mode(pi, old_mode);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 6),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 1 : 0) << 6);
+
+	mod_phy_reg(pi, 0x6a3, (0x1 << 4),
+		    ((LCNPHY_TX_PWR_CTRL_HW == mode) ? 0 : 1) << 4);
+
+	if (old_mode != mode) {
+		if (LCNPHY_TX_PWR_CTRL_HW == old_mode) {
+
+			wlc_lcnphy_tx_pwr_update_npt(pi);
+
+			wlc_lcnphy_clear_tx_power_offsets(pi);
+		}
+		if (LCNPHY_TX_PWR_CTRL_HW == mode) {
+
+			wlc_lcnphy_txpower_recalc_target(pi);
+
+			wlc_lcnphy_set_start_tx_pwr_idx(pi,
+							pi_lcn->
+							lcnphy_tssi_idx);
+			wlc_lcnphy_set_tx_pwr_npt(pi, pi_lcn->lcnphy_tssi_npt);
+			mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0);
+
+			pi_lcn->lcnphy_tssi_tx_cnt =
+			    wlc_lcnphy_total_tx_frames(pi);
+
+			wlc_lcnphy_disable_tx_gain_override(pi);
+			pi_lcn->lcnphy_tx_power_idx_override = -1;
+		} else
+			wlc_lcnphy_enable_tx_gain_override(pi);
+
+		mod_phy_reg(pi, 0x4a4,
+			    ((0x1 << 15) | (0x1 << 14) | (0x1 << 13)), mode);
+		if (mode == LCNPHY_TX_PWR_CTRL_TEMPBASED) {
+			index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+			wlc_lcnphy_set_tx_pwr_soft_ctrl(pi, index);
+			pi_lcn->lcnphy_current_index = (s8)
+			    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+		}
+	}
+}
+
+static bool wlc_lcnphy_iqcal_wait(phy_info_t *pi)
+{
+	uint delay_count = 0;
+
+	while (wlc_lcnphy_iqcal_active(pi)) {
+		udelay(100);
+		delay_count++;
+
+		if (delay_count > (10 * 500))
+			break;
+	}
+
+	return (0 == wlc_lcnphy_iqcal_active(pi));
+}
+
+static void
+wlc_lcnphy_tx_iqlo_cal(phy_info_t *pi,
+		       lcnphy_txgains_t *target_gains,
+		       lcnphy_cal_mode_t cal_mode, bool keep_tone)
+{
+
+	lcnphy_txgains_t cal_gains, temp_gains;
+	u16 hash;
+	u8 band_idx;
+	int j;
+	u16 ncorr_override[5];
+	u16 syst_coeffs[] = { 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000
+	};
+
+	u16 commands_fullcal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+
+	u16 commands_recal[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234 };
+
+	u16 command_nums_fullcal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+
+	u16 command_nums_recal[] = {
+		0x7a97, 0x7a97, 0x7a97, 0x7a87, 0x7a87, 0x7b97 };
+	u16 *command_nums = command_nums_fullcal;
+
+	u16 *start_coeffs = NULL, *cal_cmds = NULL, cal_type, diq_start;
+	u16 tx_pwr_ctrl_old, save_txpwrctrlrfctrl2;
+	u16 save_sslpnCalibClkEnCtrl, save_sslpnRxFeClkEnCtrl;
+	bool tx_gain_override_old;
+	lcnphy_txgains_t old_gains;
+	uint i, n_cal_cmds = 0, n_cal_start = 0;
+	u16 *values_to_save;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	values_to_save = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+	if (NULL == values_to_save) {
+		return;
+	}
+
+	save_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+	save_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	or_phy_reg(pi, 0x6da, 0x40);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	switch (cal_mode) {
+	case LCNPHY_CAL_FULL:
+		start_coeffs = syst_coeffs;
+		cal_cmds = commands_fullcal;
+		n_cal_cmds = ARRAY_SIZE(commands_fullcal);
+		break;
+
+	case LCNPHY_CAL_RECAL:
+		ASSERT(pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid);
+
+		start_coeffs = syst_coeffs;
+
+		cal_cmds = commands_recal;
+		n_cal_cmds = ARRAY_SIZE(commands_recal);
+		command_nums = command_nums_recal;
+		break;
+	default:
+		ASSERT(false);
+	}
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      start_coeffs, 11, 16, 64);
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+	mod_phy_reg(pi, 0x503, (0x1 << 3), (1) << 3);
+
+	tx_pwr_ctrl_old = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	save_txpwrctrlrfctrl2 = read_phy_reg(pi, 0x4db);
+
+	mod_phy_reg(pi, 0x4db, (0x3ff << 0), (0x2a6) << 0);
+
+	mod_phy_reg(pi, 0x4db, (0x7 << 12), (2) << 12);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, values_to_save);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	if (tx_gain_override_old)
+		wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	if (!target_gains) {
+		if (!tx_gain_override_old)
+			wlc_lcnphy_set_tx_pwr_by_index(pi,
+						       pi_lcn->lcnphy_tssi_idx);
+		wlc_lcnphy_get_tx_gain(pi, &temp_gains);
+		target_gains = &temp_gains;
+	}
+
+	hash = (target_gains->gm_gain << 8) |
+	    (target_gains->pga_gain << 4) | (target_gains->pad_gain);
+
+	band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	cal_gains = *target_gains;
+	memset(ncorr_override, 0, sizeof(ncorr_override));
+	for (j = 0; j < iqcal_gainparams_numgains_lcnphy[band_idx]; j++) {
+		if (hash == tbl_iqcal_gainparams_lcnphy[band_idx][j][0]) {
+			cal_gains.gm_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][1];
+			cal_gains.pga_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][2];
+			cal_gains.pad_gain =
+			    tbl_iqcal_gainparams_lcnphy[band_idx][j][3];
+			memcpy(ncorr_override,
+			       &tbl_iqcal_gainparams_lcnphy[band_idx][j][3],
+			       sizeof(ncorr_override));
+			break;
+		}
+	}
+
+	wlc_lcnphy_set_tx_gain(pi, &cal_gains);
+
+	write_phy_reg(pi, 0x453, 0xaa9);
+	write_phy_reg(pi, 0x93d, 0xc0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      (const void *)
+				      lcnphy_iqcal_loft_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_loft_gainladder),
+				      16, 0);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      (const void *)lcnphy_iqcal_ir_gainladder,
+				      ARRAY_SIZE(lcnphy_iqcal_ir_gainladder), 16,
+				      32);
+
+	if (pi->phy_tx_tone_freq) {
+
+		wlc_lcnphy_stop_tx_tone(pi);
+		udelay(5);
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	} else {
+		wlc_lcnphy_start_tx_tone(pi, 3750, 88, 1);
+	}
+
+	write_phy_reg(pi, 0x6da, 0xffff);
+
+	for (i = n_cal_start; i < n_cal_cmds; i++) {
+		u16 zero_diq = 0;
+		u16 best_coeffs[11];
+		u16 command_num;
+
+		cal_type = (cal_cmds[i] & 0x0f00) >> 8;
+
+		command_num = command_nums[i];
+		if (ncorr_override[cal_type])
+			command_num =
+			    ncorr_override[cal_type] << 8 | (command_num &
+							     0xff);
+
+		write_phy_reg(pi, 0x452, command_num);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+
+			wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						     &diq_start, 1, 16, 69);
+
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &zero_diq, 1, 16, 69);
+		}
+
+		write_phy_reg(pi, 0x451, cal_cmds[i]);
+
+		if (!wlc_lcnphy_iqcal_wait(pi)) {
+
+			goto cleanup;
+		}
+
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     best_coeffs,
+					     ARRAY_SIZE(best_coeffs), 16, 96);
+		wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					      best_coeffs,
+					      ARRAY_SIZE(best_coeffs), 16, 64);
+
+		if ((cal_type == 3) || (cal_type == 4)) {
+			wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+						      &diq_start, 1, 16, 69);
+		}
+		wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+					     pi_lcn->lcnphy_cal_results.
+					     txiqlocal_bestcoeffs,
+					     ARRAY_SIZE(pi_lcn->
+						       lcnphy_cal_results.
+						       txiqlocal_bestcoeffs),
+					     16, 96);
+	}
+
+	wlc_lcnphy_common_read_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				     pi_lcn->lcnphy_cal_results.
+				     txiqlocal_bestcoeffs,
+				     ARRAY_SIZE(pi_lcn->lcnphy_cal_results.
+					       txiqlocal_bestcoeffs), 16, 96);
+	pi_lcn->lcnphy_cal_results.txiqlocal_bestcoeffs_valid = true;
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[0], 4, 16, 80);
+
+	wlc_lcnphy_common_write_table(pi, LCNPHY_TBL_ID_IQLOCAL,
+				      &pi_lcn->lcnphy_cal_results.
+				      txiqlocal_bestcoeffs[5], 2, 16, 85);
+
+ cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, values_to_save);
+	kfree(values_to_save);
+
+	if (!keep_tone)
+		wlc_lcnphy_stop_tx_tone(pi);
+
+	write_phy_reg(pi, 0x4db, save_txpwrctrlrfctrl2);
+
+	write_phy_reg(pi, 0x453, 0);
+
+	if (tx_gain_override_old)
+		wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl_old);
+
+	write_phy_reg(pi, 0x6da, save_sslpnCalibClkEnCtrl);
+	write_phy_reg(pi, 0x6db, save_sslpnRxFeClkEnCtrl);
+
+}
+
+static void wlc_lcnphy_idle_tssi_est(wlc_phy_t *ppi)
+{
+	bool suspend, tx_gain_override_old;
+	lcnphy_txgains_t old_gains;
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 idleTssi, idleTssi0_2C, idleTssi0_OB, idleTssi0_regvalue_OB,
+	    idleTssi0_regvalue_2C;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	u16 SAVE_lpfgain = read_radio_reg(pi, RADIO_2064_REG112);
+	u16 SAVE_jtag_bb_afe_switch =
+	    read_radio_reg(pi, RADIO_2064_REG007) & 1;
+	u16 SAVE_jtag_auxpga = read_radio_reg(pi, RADIO_2064_REG0FF) & 0x10;
+	u16 SAVE_iqadc_aux_en = read_radio_reg(pi, RADIO_2064_REG11F) & 4;
+	idleTssi = read_phy_reg(pi, 0x4ab);
+	suspend =
+	    (0 ==
+	     (R_REG(&((phy_info_t *) pi)->regs->maccontrol) &
+	      MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 1 << 2);
+	wlc_lcnphy_tssi_setup(pi);
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	idleTssi = ((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+		    >> 0);
+
+	idleTssi0_2C = ((read_phy_reg(pi, 0x63e) & (0x1ff << 0))
+			>> 0);
+
+	if (idleTssi0_2C >= 256)
+		idleTssi0_OB = idleTssi0_2C - 256;
+	else
+		idleTssi0_OB = idleTssi0_2C + 256;
+
+	idleTssi0_regvalue_OB = idleTssi0_OB;
+	if (idleTssi0_regvalue_OB >= 256)
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB - 256;
+	else
+		idleTssi0_regvalue_2C = idleTssi0_regvalue_OB + 256;
+	mod_phy_reg(pi, 0x4a6, (0x1ff << 0), (idleTssi0_regvalue_2C) << 0);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), (0) << 12);
+
+	wlc_lcnphy_set_tx_gain_override(pi, tx_gain_override_old);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	write_radio_reg(pi, RADIO_2064_REG112, SAVE_lpfgain);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, SAVE_jtag_bb_afe_switch);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, SAVE_jtag_auxpga);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, SAVE_iqadc_aux_en);
+	mod_radio_reg(pi, RADIO_2064_REG112, 0x80, 1 << 7);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static void wlc_lcnphy_vbat_temp_sense_setup(phy_info_t *pi, u8 mode)
+{
+	bool suspend;
+	u16 save_txpwrCtrlEn;
+	u8 auxpga_vmidcourse, auxpga_vmidfine, auxpga_gain;
+	u16 auxpga_vmid;
+	phytbl_info_t tab;
+	u32 val;
+	u8 save_reg007, save_reg0FF, save_reg11F, save_reg005, save_reg025,
+	    save_reg112;
+	u16 values_to_save[14];
+	s8 index;
+	int i;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	udelay(999);
+
+	save_reg007 = (u8) read_radio_reg(pi, RADIO_2064_REG007);
+	save_reg0FF = (u8) read_radio_reg(pi, RADIO_2064_REG0FF);
+	save_reg11F = (u8) read_radio_reg(pi, RADIO_2064_REG11F);
+	save_reg005 = (u8) read_radio_reg(pi, RADIO_2064_REG005);
+	save_reg025 = (u8) read_radio_reg(pi, RADIO_2064_REG025);
+	save_reg112 = (u8) read_radio_reg(pi, RADIO_2064_REG112);
+
+	for (i = 0; i < 14; i++)
+		values_to_save[i] = read_phy_reg(pi, tempsense_phy_regs[i]);
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	save_txpwrCtrlEn = read_radio_reg(pi, 0x4a4);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+	index = pi_lcn->lcnphy_current_index;
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 127);
+	mod_radio_reg(pi, RADIO_2064_REG007, 0x1, 0x1);
+	mod_radio_reg(pi, RADIO_2064_REG0FF, 0x10, 0x1 << 4);
+	mod_radio_reg(pi, RADIO_2064_REG11F, 0x4, 0x1 << 2);
+	mod_phy_reg(pi, 0x503, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, 0x503, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 14), (0) << 14);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 15), (0) << 15);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (0) << 5);
+
+	mod_phy_reg(pi, 0x4a5, (0xff << 0), (255) << 0);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 12), (5) << 12);
+
+	mod_phy_reg(pi, 0x4a5, (0x7 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x40d, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x40d, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4a2, (0xff << 0), (64) << 0);
+
+	mod_phy_reg(pi, 0x4a2, (0x7 << 8), (6) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 4), (2) << 4);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 8), (3) << 8);
+
+	mod_phy_reg(pi, 0x4d9, (0x7 << 12), (1) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 12), (0) << 12);
+
+	mod_phy_reg(pi, 0x4da, (0x1 << 13), (1) << 13);
+
+	mod_phy_reg(pi, 0x4a6, (0x1 << 15), (1) << 15);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xC);
+
+	mod_radio_reg(pi, RADIO_2064_REG005, 0x8, 0x1 << 3);
+
+	mod_phy_reg(pi, 0x938, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x939, (0x1 << 2), (1) << 2);
+
+	mod_phy_reg(pi, 0x4a4, (0x1 << 12), (1) << 12);
+
+	val = wlc_lcnphy_rfseq_tbl_adc_pwrup(pi);
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+	tab.tbl_offset = 6;
+	wlc_lcnphy_write_table(pi, &tab);
+	if (mode == TEMPSENSE) {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (1) << 12);
+
+		auxpga_vmidcourse = 8;
+		auxpga_vmidfine = 0x4;
+		auxpga_gain = 2;
+		mod_radio_reg(pi, RADIO_2064_REG082, 0x20, 1 << 5);
+	} else {
+		mod_phy_reg(pi, 0x4d7, (0x1 << 3), (1) << 3);
+
+		mod_phy_reg(pi, 0x4d7, (0x7 << 12), (3) << 12);
+
+		auxpga_vmidcourse = 7;
+		auxpga_vmidfine = 0xa;
+		auxpga_gain = 2;
+	}
+	auxpga_vmid =
+	    (u16) ((2 << 8) | (auxpga_vmidcourse << 4) | auxpga_vmidfine);
+	mod_phy_reg(pi, 0x4d8, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), (auxpga_vmid) << 2);
+
+	mod_phy_reg(pi, 0x4d8, (0x1 << 1), (1) << 1);
+
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), (auxpga_gain) << 12);
+
+	mod_phy_reg(pi, 0x4d0, (0x1 << 5), (1) << 5);
+
+	write_radio_reg(pi, RADIO_2064_REG112, 0x6);
+
+	wlc_phy_do_dummy_tx(pi, true, OFF);
+	if (!tempsense_done(pi))
+		udelay(10);
+
+	write_radio_reg(pi, RADIO_2064_REG007, (u16) save_reg007);
+	write_radio_reg(pi, RADIO_2064_REG0FF, (u16) save_reg0FF);
+	write_radio_reg(pi, RADIO_2064_REG11F, (u16) save_reg11F);
+	write_radio_reg(pi, RADIO_2064_REG005, (u16) save_reg005);
+	write_radio_reg(pi, RADIO_2064_REG025, (u16) save_reg025);
+	write_radio_reg(pi, RADIO_2064_REG112, (u16) save_reg112);
+	for (i = 0; i < 14; i++)
+		write_phy_reg(pi, tempsense_phy_regs[i], values_to_save[i]);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, (int)index);
+
+	write_radio_reg(pi, 0x4a4, save_txpwrCtrlEn);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+	udelay(999);
+}
+
+void WLBANDINITFN(wlc_lcnphy_tx_pwr_ctrl_init) (wlc_phy_t *ppi)
+{
+	lcnphy_txgains_t tx_gains;
+	u8 bbmult;
+	phytbl_info_t tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	bool suspend;
+	phy_info_t *pi = (phy_info_t *) ppi;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		wlc_lcnphy_set_bbmult(pi, 0x30);
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+		return;
+	}
+
+	if (!pi->hwpwrctrl_capable) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			tx_gains.gm_gain = 4;
+			tx_gains.pga_gain = 12;
+			tx_gains.pad_gain = 12;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		} else {
+			tx_gains.gm_gain = 7;
+			tx_gains.pga_gain = 15;
+			tx_gains.pad_gain = 14;
+			tx_gains.dac_gain = 0;
+
+			bbmult = 150;
+		}
+		wlc_lcnphy_set_tx_gain(pi, &tx_gains);
+		wlc_lcnphy_set_bbmult(pi, bbmult);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	} else {
+
+		wlc_lcnphy_idle_tssi_est(ppi);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (0) << 7);
+
+		write_phy_reg(pi, 0x4a8, 10);
+
+		wlc_lcnphy_set_target_tx_pwr(pi, LCN_TARGET_PWR);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	}
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+static u8 wlc_lcnphy_get_bbmult(phy_info_t *pi)
+{
+	u16 m0m1;
+	phytbl_info_t tab;
+
+	tab.tbl_ptr = &m0m1;
+	tab.tbl_len = 1;
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_offset = 87;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return (u8) ((m0m1 & 0xff00) >> 8);
+}
+
+static void wlc_lcnphy_set_pa_gain(phy_info_t *pi, u16 gain)
+{
+	mod_phy_reg(pi, 0x4fb,
+		    LCNPHY_txgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_txgainctrlovrval1_pagain_ovr_val1_SHIFT);
+	mod_phy_reg(pi, 0x4fd,
+		    LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_MASK,
+		    gain << LCNPHY_stxtxgainctrlovrval1_pagain_ovr_val1_SHIFT);
+}
+
+void
+wlc_lcnphy_get_radio_loft(phy_info_t *pi,
+			  u8 *ei0, u8 *eq0, u8 *fi0, u8 *fq0)
+{
+	*ei0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG089));
+	*eq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08A));
+	*fi0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08B));
+	*fq0 = LCNPHY_IQLOCC_READ(read_radio_reg(pi, RADIO_2064_REG08C));
+}
+
+static void wlc_lcnphy_get_tx_gain(phy_info_t *pi, lcnphy_txgains_t *gains)
+{
+	u16 dac_gain;
+
+	dac_gain = read_phy_reg(pi, 0x439) >> 0;
+	gains->dac_gain = (dac_gain & 0x380) >> 7;
+
+	{
+		u16 rfgain0, rfgain1;
+
+		rfgain0 = (read_phy_reg(pi, 0x4b5) & (0xffff << 0)) >> 0;
+		rfgain1 = (read_phy_reg(pi, 0x4fb) & (0x7fff << 0)) >> 0;
+
+		gains->gm_gain = rfgain0 & 0xff;
+		gains->pga_gain = (rfgain0 >> 8) & 0xff;
+		gains->pad_gain = rfgain1 & 0xff;
+	}
+}
+
+void wlc_lcnphy_set_tx_iqcc(phy_info_t *pi, u16 a, u16 b)
+{
+	phytbl_info_t tab;
+	u16 iqcc[2];
+
+	iqcc[0] = a;
+	iqcc[1] = b;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_offset = 80;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_locc(phy_info_t *pi, u16 didq)
+{
+	phytbl_info_t tab;
+
+	tab.tbl_id = LCNPHY_TBL_ID_IQLOCAL;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_write_table(pi, &tab);
+}
+
+void wlc_lcnphy_set_tx_pwr_by_index(phy_info_t *pi, int index)
+{
+	phytbl_info_t tab;
+	u16 a, b;
+	u8 bb_mult;
+	u32 bbmultiqcomp, txgain, locoeffs, rfpower;
+	lcnphy_txgains_t gains;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	ASSERT(index <= LCNPHY_MAX_TX_POWER_INDEX);
+
+	pi_lcn->lcnphy_tx_power_idx_override = (s8) index;
+	pi_lcn->lcnphy_current_index = (u8) index;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+	tab.tbl_ptr = &bbmultiqcomp;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &txgain;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	gains.gm_gain = (u16) (txgain & 0xff);
+	gains.pga_gain = (u16) (txgain >> 8) & 0xff;
+	gains.pad_gain = (u16) (txgain >> 16) & 0xff;
+	gains.dac_gain = (u16) (bbmultiqcomp >> 28) & 0x07;
+	wlc_lcnphy_set_tx_gain(pi, &gains);
+	wlc_lcnphy_set_pa_gain(pi, (u16) (txgain >> 24) & 0x7f);
+
+	bb_mult = (u8) ((bbmultiqcomp >> 20) & 0xff);
+	wlc_lcnphy_set_bbmult(pi, bb_mult);
+
+	wlc_lcnphy_enable_tx_gain_override(pi);
+
+	if (!wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+
+		a = (u16) ((bbmultiqcomp >> 10) & 0x3ff);
+		b = (u16) (bbmultiqcomp & 0x3ff);
+		wlc_lcnphy_set_tx_iqcc(pi, a, b);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + index;
+		tab.tbl_ptr = &locoeffs;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		wlc_lcnphy_set_tx_locc(pi, (u16) locoeffs);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		tab.tbl_ptr = &rfpower;
+		wlc_lcnphy_read_table(pi, &tab);
+		mod_phy_reg(pi, 0x6a6, (0x1fff << 0), (rfpower * 8) << 0);
+
+	}
+}
+
+static void wlc_lcnphy_set_trsw_override(phy_info_t *pi, bool tx, bool rx)
+{
+
+	mod_phy_reg(pi, 0x44d,
+		    (0x1 << 1) |
+		    (0x1 << 0), (tx ? (0x1 << 1) : 0) | (rx ? (0x1 << 0) : 0));
+
+	or_phy_reg(pi, 0x44c, (0x1 << 1) | (0x1 << 0));
+}
+
+static void wlc_lcnphy_clear_papd_comptable(phy_info_t *pi)
+{
+	u32 j;
+	phytbl_info_t tab;
+	u32 temp_offset[128];
+	tab.tbl_ptr = temp_offset;
+	tab.tbl_len = 128;
+	tab.tbl_id = LCNPHY_TBL_ID_PAPDCOMPDELTATBL;
+	tab.tbl_width = 32;
+	tab.tbl_offset = 0;
+
+	memset(temp_offset, 0, sizeof(temp_offset));
+	for (j = 1; j < 128; j += 2)
+		temp_offset[j] = 0x80000;
+
+	wlc_lcnphy_write_table(pi, &tab);
+	return;
+}
+
+static void
+wlc_lcnphy_set_rx_gain_by_distribution(phy_info_t *pi,
+				       u16 trsw,
+				       u16 ext_lna,
+				       u16 biq2,
+				       u16 biq1,
+				       u16 tia, u16 lna2, u16 lna1)
+{
+	u16 gain0_15, gain16_19;
+
+	gain16_19 = biq2 & 0xf;
+	gain0_15 = ((biq1 & 0xf) << 12) |
+	    ((tia & 0xf) << 8) |
+	    ((lna2 & 0x3) << 6) |
+	    ((lna2 & 0x3) << 4) | ((lna1 & 0x3) << 2) | ((lna1 & 0x3) << 0);
+
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+	mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	} else {
+		mod_phy_reg(pi, 0x4b1, (0x1 << 10), 0 << 10);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 15), 0 << 15);
+
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	}
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), (!trsw) << 0);
+
+}
+
+static void wlc_lcnphy_rx_gain_override_enable(phy_info_t *pi, bool enable)
+{
+	u16 ebit = enable ? 1 : 0;
+
+	mod_phy_reg(pi, 0x4b0, (0x1 << 8), ebit << 8);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 0), ebit << 0);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x44c, (0x1 << 4), ebit << 4);
+		mod_phy_reg(pi, 0x44c, (0x1 << 6), ebit << 6);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 6), ebit << 6);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 12), ebit << 12);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 13), ebit << 13);
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), ebit << 5);
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 10), ebit << 10);
+		mod_phy_reg(pi, 0x4e5, (0x1 << 3), ebit << 3);
+	}
+}
+
+void wlc_lcnphy_tx_pu(phy_info_t *pi, bool bEnable)
+{
+	if (!bEnable) {
+
+		and_phy_reg(pi, 0x43b, ~(u16) ((0x1 << 1) | (0x1 << 4)));
+
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 1 << 1);
+
+		and_phy_reg(pi, 0x44c,
+			    ~(u16) ((0x1 << 3) |
+				       (0x1 << 5) |
+				       (0x1 << 12) |
+				       (0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x44d,
+			    ~(u16) ((0x1 << 3) | (0x1 << 5) | (0x1 << 14)));
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 1 << 2);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 1) | (0x1 << 0), (0x1 << 0));
+
+		and_phy_reg(pi, 0x4f9,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+
+		and_phy_reg(pi, 0x4fa,
+			    ~(u16) ((0x1 << 0) | (0x1 << 1) | (0x1 << 2)));
+	} else {
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 4), 1 << 4);
+		mod_phy_reg(pi, 0x43c, (0x1 << 6), 0 << 6);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+		mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+		wlc_lcnphy_set_trsw_override(pi, true, false);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), 0 << 2);
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 1 << 2);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 1 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 0 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 1 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 1 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 1 << 0);
+		} else {
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 3), 1 << 3);
+			mod_phy_reg(pi, 0x44d, (0x1 << 3), 0 << 3);
+
+			mod_phy_reg(pi, 0x44c, (0x1 << 5), 1 << 5);
+			mod_phy_reg(pi, 0x44d, (0x1 << 5), 1 << 5);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 1), 1 << 1);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 1), 0 << 1);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 2), 1 << 2);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 2), 0 << 2);
+
+			mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+			mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+		}
+	}
+}
+
+static void
+wlc_lcnphy_run_samples(phy_info_t *pi,
+		       u16 num_samps,
+		       u16 num_loops, u16 wait, bool iqcalmode)
+{
+
+	or_phy_reg(pi, 0x6da, 0x8080);
+
+	mod_phy_reg(pi, 0x642, (0x7f << 0), (num_samps - 1) << 0);
+	if (num_loops != 0xffff)
+		num_loops--;
+	mod_phy_reg(pi, 0x640, (0xffff << 0), num_loops << 0);
+
+	mod_phy_reg(pi, 0x641, (0xffff << 0), wait << 0);
+
+	if (iqcalmode) {
+
+		and_phy_reg(pi, 0x453, (u16) ~(0x1 << 15));
+		or_phy_reg(pi, 0x453, (0x1 << 15));
+	} else {
+		write_phy_reg(pi, 0x63f, 1);
+		wlc_lcnphy_tx_pu(pi, 1);
+	}
+
+	or_radio_reg(pi, RADIO_2064_REG112, 0x6);
+}
+
+void wlc_lcnphy_deaf_mode(phy_info_t *pi, bool mode)
+{
+
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	if (LCNREV_LT(pi->pubpi.phy_rev, 2)) {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+	} else {
+		mod_phy_reg(pi, 0x4b0, (0x1 << 5), (mode) << 5);
+		mod_phy_reg(pi, 0x4b1, (0x1 << 9), 0 << 9);
+	}
+
+	if (phybw40 == 0) {
+		mod_phy_reg((pi), 0x410,
+			    (0x1 << 6) |
+			    (0x1 << 5),
+			    ((CHSPEC_IS2G(pi->radio_chanspec)) ? (!mode) : 0) <<
+			    6 | (!mode) << 5);
+		mod_phy_reg(pi, 0x410, (0x1 << 7), (mode) << 7);
+	}
+}
+
+void
+wlc_lcnphy_start_tx_tone(phy_info_t *pi, s32 f_kHz, u16 max_val,
+			 bool iqcalmode)
+{
+	u8 phy_bw;
+	u16 num_samps, t, k;
+	u32 bw;
+	fixed theta = 0, rot = 0;
+	cs32 tone_samp;
+	u32 data_buf[64];
+	u16 i_samp, q_samp;
+	phytbl_info_t tab;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = f_kHz;
+
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	phy_bw = 40;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x2);
+		write_phy_reg(pi, 0x93b, 0x0);
+		write_phy_reg(pi, 0x93c, 0x0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+	}
+
+	if (f_kHz) {
+		k = 1;
+		do {
+			bw = phy_bw * 1000 * k;
+			num_samps = bw / ABS(f_kHz);
+			ASSERT(num_samps <= ARRAY_SIZE(data_buf));
+			k++;
+		} while ((num_samps * (u32) (ABS(f_kHz))) != bw);
+	} else
+		num_samps = 2;
+
+	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		wlc_phy_cordic(theta, &tone_samp);
+
+		theta += rot;
+
+		i_samp = (u16) (FLOAT(tone_samp.i * max_val) & 0x3ff);
+		q_samp = (u16) (FLOAT(tone_samp.q * max_val) & 0x3ff);
+		data_buf[t] = (i_samp << 10) | q_samp;
+	}
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 1 << 3);
+
+	tab.tbl_ptr = data_buf;
+	tab.tbl_len = num_samps;
+	tab.tbl_id = LCNPHY_TBL_ID_SAMPLEPLAY;
+	tab.tbl_offset = 0;
+	tab.tbl_width = 32;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	wlc_lcnphy_run_samples(pi, num_samps, 0xffff, 0, iqcalmode);
+}
+
+void wlc_lcnphy_stop_tx_tone(phy_info_t *pi)
+{
+	s16 playback_status;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	pi->phy_tx_tone_freq = 0;
+	if (pi_lcn->lcnphy_spurmod) {
+		write_phy_reg(pi, 0x942, 0x7);
+		write_phy_reg(pi, 0x93b, 0x2017);
+		write_phy_reg(pi, 0x93c, 0x27c5);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+	}
+
+	playback_status = read_phy_reg(pi, 0x644);
+	if (playback_status & (0x1 << 0)) {
+		wlc_lcnphy_tx_pu(pi, 0);
+		mod_phy_reg(pi, 0x63f, (0x1 << 1), 1 << 1);
+	} else if (playback_status & (0x1 << 1))
+		mod_phy_reg(pi, 0x453, (0x1 << 15), 0 << 15);
+
+	mod_phy_reg(pi, 0x6d6, (0x3 << 0), 1 << 0);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 3), 0 << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 7), 0 << 7);
+
+	and_radio_reg(pi, RADIO_2064_REG112, 0xFFF9);
+
+	wlc_lcnphy_deaf_mode(pi, false);
+}
+
+static void wlc_lcnphy_clear_trsw_override(phy_info_t *pi)
+{
+
+	and_phy_reg(pi, 0x44c, (u16) ~((0x1 << 1) | (0x1 << 0)));
+}
+
+void wlc_lcnphy_get_tx_iqcc(phy_info_t *pi, u16 *a, u16 *b)
+{
+	u16 iqcc[2];
+	phytbl_info_t tab;
+
+	tab.tbl_ptr = iqcc;
+	tab.tbl_len = 2;
+	tab.tbl_id = 0;
+	tab.tbl_offset = 80;
+	tab.tbl_width = 16;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	*a = iqcc[0];
+	*b = iqcc[1];
+}
+
+u16 wlc_lcnphy_get_tx_locc(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u16 didq;
+
+	tab.tbl_id = 0;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &didq;
+	tab.tbl_len = 1;
+	tab.tbl_offset = 85;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	return didq;
+}
+
+static void wlc_lcnphy_txpwrtbl_iqlo_cal(phy_info_t *pi)
+{
+
+	lcnphy_txgains_t target_gains, old_gains;
+	u8 save_bb_mult;
+	u16 a, b, didq, save_pa_gain = 0;
+	uint idx, SAVE_txpwrindex = 0xFF;
+	u32 val;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	phytbl_info_t tab;
+	u8 ei0, eq0, fi0, fq0;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	wlc_lcnphy_get_tx_gain(pi, &old_gains);
+	save_pa_gain = wlc_lcnphy_get_pa_gain(pi);
+
+	save_bb_mult = wlc_lcnphy_get_bbmult(pi);
+
+	if (SAVE_txpwrctrl == LCNPHY_TX_PWR_CTRL_OFF)
+		SAVE_txpwrindex = wlc_lcnphy_get_current_tx_pwr_idx(pi);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+	target_gains.gm_gain = 7;
+	target_gains.pga_gain = 0;
+	target_gains.pad_gain = 21;
+	target_gains.dac_gain = 0;
+	wlc_lcnphy_set_tx_gain(pi, &target_gains);
+	wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1) || pi_lcn->lcnphy_hw_iqcal_en) {
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 30);
+
+		wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+				       (pi_lcn->
+					lcnphy_recal ? LCNPHY_CAL_RECAL :
+					LCNPHY_CAL_FULL), false);
+	} else {
+
+		wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+	}
+
+	wlc_lcnphy_get_radio_loft(pi, &ei0, &eq0, &fi0, &fq0);
+	if ((ABS((s8) fi0) == 15) && (ABS((s8) fq0) == 15)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			target_gains.gm_gain = 255;
+			target_gains.pga_gain = 255;
+			target_gains.pad_gain = 0xf0;
+			target_gains.dac_gain = 0;
+		} else {
+			target_gains.gm_gain = 7;
+			target_gains.pga_gain = 45;
+			target_gains.pad_gain = 186;
+			target_gains.dac_gain = 0;
+		}
+
+		if (LCNREV_IS(pi->pubpi.phy_rev, 1)
+		    || pi_lcn->lcnphy_hw_iqcal_en) {
+
+			target_gains.pga_gain = 0;
+			target_gains.pad_gain = 30;
+			wlc_lcnphy_set_tx_pwr_by_index(pi, 16);
+			wlc_lcnphy_tx_iqlo_cal(pi, &target_gains,
+					       LCNPHY_CAL_FULL, false);
+		} else {
+
+			wlc_lcnphy_tx_iqlo_soft_cal_full(pi);
+		}
+
+	}
+
+	wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+
+	didq = wlc_lcnphy_get_tx_locc(pi);
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_ptr = &val;
+
+	tab.tbl_len = 1;
+	tab.tbl_offset = LCNPHY_TX_PWR_CTRL_RATE_OFFSET;
+
+	for (idx = 0; idx < 128; idx++) {
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + idx;
+
+		wlc_lcnphy_read_table(pi, &tab);
+		val = (val & 0xfff00000) |
+		    ((u32) (a & 0x3FF) << 10) | (b & 0x3ff);
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = didq;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_LO_OFFSET + idx;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	pi_lcn->lcnphy_cal_results.txiqlocal_a = a;
+	pi_lcn->lcnphy_cal_results.txiqlocal_b = b;
+	pi_lcn->lcnphy_cal_results.txiqlocal_didq = didq;
+	pi_lcn->lcnphy_cal_results.txiqlocal_ei0 = ei0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_eq0 = eq0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fi0 = fi0;
+	pi_lcn->lcnphy_cal_results.txiqlocal_fq0 = fq0;
+
+	wlc_lcnphy_set_bbmult(pi, save_bb_mult);
+	wlc_lcnphy_set_pa_gain(pi, save_pa_gain);
+	wlc_lcnphy_set_tx_gain(pi, &old_gains);
+
+	if (SAVE_txpwrctrl != LCNPHY_TX_PWR_CTRL_OFF)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+	else
+		wlc_lcnphy_set_tx_pwr_by_index(pi, SAVE_txpwrindex);
+}
+
+s16 wlc_lcnphy_tempsense_new(phy_info_t *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s16 avg = 0;
+	bool suspend = 0;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (s16) (tempsenseval1 - 512);
+	else
+		avg = (s16) tempsenseval1;
+
+	if (tempsenseval2 > 255)
+		avg += (s16) (tempsenseval2 - 512);
+	else
+		avg += (s16) tempsenseval2;
+
+	avg /= 2;
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return avg;
+}
+
+u16 wlc_lcnphy_tempsense(phy_info_t *pi, bool mode)
+{
+	u16 tempsenseval1, tempsenseval2;
+	s32 avg = 0;
+	bool suspend = 0;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, TEMPSENSE);
+	}
+	tempsenseval1 = read_phy_reg(pi, 0x476) & 0x1FF;
+	tempsenseval2 = read_phy_reg(pi, 0x477) & 0x1FF;
+
+	if (tempsenseval1 > 255)
+		avg = (int)(tempsenseval1 - 512);
+	else
+		avg = (int)tempsenseval1;
+
+	if (pi_lcn->lcnphy_tempsense_option == 1 || pi->hwpwrctrl_capable) {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg - tempsenseval2 + 512);
+		else
+			avg = (int)(avg - tempsenseval2);
+	} else {
+		if (tempsenseval2 > 255)
+			avg = (int)(avg + tempsenseval2 - 512);
+		else
+			avg = (int)(avg + tempsenseval2);
+		avg = avg / 2;
+	}
+	if (avg < 0)
+		avg = avg + 512;
+
+	if (pi_lcn->lcnphy_tempsense_option == 2)
+		avg = tempsenseval1;
+
+	if (mode)
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_txpwrctrl);
+
+	if (mode == 1) {
+
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+		udelay(100);
+		mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (u16) avg;
+}
+
+s8 wlc_lcnphy_tempsense_degree(phy_info_t *pi, bool mode)
+{
+	s32 degree = wlc_lcnphy_tempsense_new(pi, mode);
+	degree =
+	    ((degree << 10) + LCN_TEMPSENSE_OFFSET + (LCN_TEMPSENSE_DEN >> 1))
+	    / LCN_TEMPSENSE_DEN;
+	return (s8) degree;
+}
+
+s8 wlc_lcnphy_vbatsense(phy_info_t *pi, bool mode)
+{
+	u16 vbatsenseval;
+	s32 avg = 0;
+	bool suspend = 0;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return -1;
+
+	if (mode == 1) {
+		suspend =
+		    (0 ==
+		     (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+		if (!suspend)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+		wlc_lcnphy_vbat_temp_sense_setup(pi, VBATSENSE);
+	}
+
+	vbatsenseval = read_phy_reg(pi, 0x475) & 0x1FF;
+
+	if (vbatsenseval > 255)
+		avg = (s32) (vbatsenseval - 512);
+	else
+		avg = (s32) vbatsenseval;
+
+	avg =
+	    (avg * LCN_VBAT_SCALE_NOM +
+	     (LCN_VBAT_SCALE_DEN >> 1)) / LCN_VBAT_SCALE_DEN;
+
+	if (mode == 1) {
+		if (!suspend)
+			wlapi_enable_mac(pi->sh->physhim);
+	}
+	return (s8) avg;
+}
+
+static void wlc_lcnphy_afe_clk_init(phy_info_t *pi, u8 mode)
+{
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6d1, (0x1 << 7), (1) << 7);
+
+	if (((mode == AFE_CLK_INIT_MODE_PAPD) && (phybw40 == 0)) ||
+	    (mode == AFE_CLK_INIT_MODE_TXRX2X))
+		write_phy_reg(pi, 0x6d0, 0x7);
+
+	wlc_lcnphy_toggle_afe_pwdn(pi);
+}
+
+static bool
+wlc_lcnphy_rx_iq_est(phy_info_t *pi,
+		     u16 num_samps,
+		     u8 wait_time, lcnphy_iq_est_t *iq_est)
+{
+	int wait_count = 0;
+	bool result = true;
+	u8 phybw40;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (1) << 5);
+
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (0) << 3);
+
+	mod_phy_reg(pi, 0x482, (0xffff << 0), (num_samps) << 0);
+
+	mod_phy_reg(pi, 0x481, (0xff << 0), ((u16) wait_time) << 0);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 8), (0) << 8);
+
+	mod_phy_reg(pi, 0x481, (0x1 << 9), (1) << 9);
+
+	while (read_phy_reg(pi, 0x481) & (0x1 << 9)) {
+
+		if (wait_count > (10 * 500)) {
+			result = false;
+			goto cleanup;
+		}
+		udelay(100);
+		wait_count++;
+	}
+
+	iq_est->iq_prod = ((u32) read_phy_reg(pi, 0x483) << 16) |
+	    (u32) read_phy_reg(pi, 0x484);
+	iq_est->i_pwr = ((u32) read_phy_reg(pi, 0x485) << 16) |
+	    (u32) read_phy_reg(pi, 0x486);
+	iq_est->q_pwr = ((u32) read_phy_reg(pi, 0x487) << 16) |
+	    (u32) read_phy_reg(pi, 0x488);
+
+ cleanup:
+	mod_phy_reg(pi, 0x410, (0x1 << 3), (1) << 3);
+
+	mod_phy_reg(pi, 0x6da, (0x1 << 5), (0) << 5);
+
+	return result;
+}
+
+static bool wlc_lcnphy_calc_rx_iq_comp(phy_info_t *pi, u16 num_samps)
+{
+#define LCNPHY_MIN_RXIQ_PWR 2
+	bool result;
+	u16 a0_new, b0_new;
+	lcnphy_iq_est_t iq_est = { 0, 0, 0 };
+	s32 a, b, temp;
+	s16 iq_nbits, qq_nbits, arsh, brsh;
+	s32 iq;
+	u32 ii, qq;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	a0_new = ((read_phy_reg(pi, 0x645) & (0x3ff << 0)) >> 0);
+	b0_new = ((read_phy_reg(pi, 0x646) & (0x3ff << 0)) >> 0);
+	mod_phy_reg(pi, 0x6d1, (0x1 << 2), (0) << 2);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 6), (1) << 6);
+
+	wlc_lcnphy_set_rx_iq_comp(pi, 0, 0);
+
+	result = wlc_lcnphy_rx_iq_est(pi, num_samps, 32, &iq_est);
+	if (!result)
+		goto cleanup;
+
+	iq = (s32) iq_est.iq_prod;
+	ii = iq_est.i_pwr;
+	qq = iq_est.q_pwr;
+
+	if ((ii + qq) < LCNPHY_MIN_RXIQ_PWR) {
+		result = false;
+		goto cleanup;
+	}
+
+	iq_nbits = wlc_phy_nbits(iq);
+	qq_nbits = wlc_phy_nbits(qq);
+
+	arsh = 10 - (30 - iq_nbits);
+	if (arsh >= 0) {
+		a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+		temp = (s32) (ii >> arsh);
+		if (temp == 0) {
+			return false;
+		}
+	} else {
+		a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+		temp = (s32) (ii << -arsh);
+		if (temp == 0) {
+			return false;
+		}
+	}
+	a /= temp;
+	brsh = qq_nbits - 31 + 20;
+	if (brsh >= 0) {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii >> brsh);
+		if (temp == 0) {
+			return false;
+		}
+	} else {
+		b = (qq << (31 - qq_nbits));
+		temp = (s32) (ii << -brsh);
+		if (temp == 0) {
+			return false;
+		}
+	}
+	b /= temp;
+	b -= a * a;
+	b = (s32) wlc_phy_sqrt_int((u32) b);
+	b -= (1 << 10);
+	a0_new = (u16) (a & 0x3ff);
+	b0_new = (u16) (b & 0x3ff);
+ cleanup:
+
+	wlc_lcnphy_set_rx_iq_comp(pi, a0_new, b0_new);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 0), (1) << 0);
+
+	mod_phy_reg(pi, 0x64b, (0x1 << 3), (1) << 3);
+
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_a0 = a0_new;
+	pi_lcn->lcnphy_cal_results.rxiqcal_coeff_b0 = b0_new;
+
+	return result;
+}
+
+static bool
+wlc_lcnphy_rx_iq_cal(phy_info_t *pi, const lcnphy_rx_iqcomp_t *iqcomp,
+		     int iqcomp_sz, bool tx_switch, bool rx_switch, int module,
+		     int tx_gain_idx)
+{
+	lcnphy_txgains_t old_gains;
+	u16 tx_pwr_ctrl;
+	u8 tx_gain_index_old = 0;
+	bool result = false, tx_gain_override_old = false;
+	u16 i, Core1TxControl_old, RFOverride0_old,
+	    RFOverrideVal0_old, rfoverride2_old, rfoverride2val_old,
+	    rfoverride3_old, rfoverride3val_old, rfoverride4_old,
+	    rfoverride4val_old, afectrlovr_old, afectrlovrval_old;
+	int tia_gain;
+	u32 received_power, rx_pwr_threshold;
+	u16 old_sslpnCalibClkEnCtrl, old_sslpnRxFeClkEnCtrl;
+	u16 values_to_save[11];
+	s16 *ptr;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+	if (NULL == ptr) {
+		return false;
+	}
+	if (module == 2) {
+		ASSERT(iqcomp_sz);
+
+		while (iqcomp_sz--) {
+			if (iqcomp[iqcomp_sz].chan ==
+			    CHSPEC_CHANNEL(pi->radio_chanspec)) {
+
+				wlc_lcnphy_set_rx_iq_comp(pi,
+							  (u16)
+							  iqcomp[iqcomp_sz].a,
+							  (u16)
+							  iqcomp[iqcomp_sz].b);
+				result = true;
+				break;
+			}
+		}
+		ASSERT(result);
+		goto cal_done;
+	}
+
+	if (module == 1) {
+
+		tx_pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+
+		for (i = 0; i < 11; i++) {
+			values_to_save[i] =
+			    read_radio_reg(pi, rxiq_cal_rf_reg[i]);
+		}
+		Core1TxControl_old = read_phy_reg(pi, 0x631);
+
+		or_phy_reg(pi, 0x631, 0x0015);
+
+		RFOverride0_old = read_phy_reg(pi, 0x44c);
+		RFOverrideVal0_old = read_phy_reg(pi, 0x44d);
+		rfoverride2_old = read_phy_reg(pi, 0x4b0);
+		rfoverride2val_old = read_phy_reg(pi, 0x4b1);
+		rfoverride3_old = read_phy_reg(pi, 0x4f9);
+		rfoverride3val_old = read_phy_reg(pi, 0x4fa);
+		rfoverride4_old = read_phy_reg(pi, 0x938);
+		rfoverride4val_old = read_phy_reg(pi, 0x939);
+		afectrlovr_old = read_phy_reg(pi, 0x43b);
+		afectrlovrval_old = read_phy_reg(pi, 0x43c);
+		old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+		old_sslpnRxFeClkEnCtrl = read_phy_reg(pi, 0x6db);
+
+		tx_gain_override_old = wlc_lcnphy_tx_gain_override_enabled(pi);
+		if (tx_gain_override_old) {
+			wlc_lcnphy_get_tx_gain(pi, &old_gains);
+			tx_gain_index_old = pi_lcn->lcnphy_current_index;
+		}
+
+		wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_idx);
+
+		mod_phy_reg(pi, 0x4f9, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x4fa, (0x1 << 0), 0 << 0);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+		write_radio_reg(pi, RADIO_2064_REG116, 0x06);
+		write_radio_reg(pi, RADIO_2064_REG12C, 0x07);
+		write_radio_reg(pi, RADIO_2064_REG06A, 0xd3);
+		write_radio_reg(pi, RADIO_2064_REG098, 0x03);
+		write_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+		mod_radio_reg(pi, RADIO_2064_REG113, 1 << 4, 1 << 4);
+		write_radio_reg(pi, RADIO_2064_REG01D, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG114, 0x01);
+		write_radio_reg(pi, RADIO_2064_REG02E, 0x10);
+		write_radio_reg(pi, RADIO_2064_REG12A, 0x08);
+
+		mod_phy_reg(pi, 0x938, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x939, (0x1 << 0), 0 << 0);
+		mod_phy_reg(pi, 0x938, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x939, (0x1 << 1), 1 << 1);
+		mod_phy_reg(pi, 0x938, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x939, (0x1 << 2), 1 << 2);
+		mod_phy_reg(pi, 0x938, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x939, (0x1 << 3), 1 << 3);
+		mod_phy_reg(pi, 0x938, (0x1 << 5), 1 << 5);
+		mod_phy_reg(pi, 0x939, (0x1 << 5), 0 << 5);
+
+		mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+		mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+		wlc_lcnphy_start_tx_tone(pi, 2000, 120, 0);
+		write_phy_reg(pi, 0x6da, 0xffff);
+		or_phy_reg(pi, 0x6db, 0x3);
+		wlc_lcnphy_set_trsw_override(pi, tx_switch, rx_switch);
+		wlc_lcnphy_rx_gain_override_enable(pi, true);
+
+		tia_gain = 8;
+		rx_pwr_threshold = 950;
+		while (tia_gain > 0) {
+			tia_gain -= 1;
+			wlc_lcnphy_set_rx_gain_by_distribution(pi,
+							       0, 0, 2, 2,
+							       (u16)
+							       tia_gain, 1, 0);
+			udelay(500);
+
+			received_power =
+			    wlc_lcnphy_measure_digital_power(pi, 2000);
+			if (received_power < rx_pwr_threshold)
+				break;
+		}
+		result = wlc_lcnphy_calc_rx_iq_comp(pi, 0xffff);
+
+		wlc_lcnphy_stop_tx_tone(pi);
+
+		write_phy_reg(pi, 0x631, Core1TxControl_old);
+
+		write_phy_reg(pi, 0x44c, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x44d, RFOverrideVal0_old);
+		write_phy_reg(pi, 0x4b0, rfoverride2_old);
+		write_phy_reg(pi, 0x4b1, rfoverride2val_old);
+		write_phy_reg(pi, 0x4f9, rfoverride3_old);
+		write_phy_reg(pi, 0x4fa, rfoverride3val_old);
+		write_phy_reg(pi, 0x938, rfoverride4_old);
+		write_phy_reg(pi, 0x939, rfoverride4val_old);
+		write_phy_reg(pi, 0x43b, afectrlovr_old);
+		write_phy_reg(pi, 0x43c, afectrlovrval_old);
+		write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+		write_phy_reg(pi, 0x6db, old_sslpnRxFeClkEnCtrl);
+
+		wlc_lcnphy_clear_trsw_override(pi);
+
+		mod_phy_reg(pi, 0x44c, (0x1 << 2), 0 << 2);
+
+		for (i = 0; i < 11; i++) {
+			write_radio_reg(pi, rxiq_cal_rf_reg[i],
+					values_to_save[i]);
+		}
+
+		if (tx_gain_override_old) {
+			wlc_lcnphy_set_tx_pwr_by_index(pi, tx_gain_index_old);
+		} else
+			wlc_lcnphy_disable_tx_gain_override(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, tx_pwr_ctrl);
+
+		wlc_lcnphy_rx_gain_override_enable(pi, false);
+	}
+
+ cal_done:
+	kfree(ptr);
+	return result;
+}
+
+static void wlc_lcnphy_temp_adj(phy_info_t *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+}
+
+static void wlc_lcnphy_glacial_timer_based_cal(phy_info_t *pi)
+{
+	bool suspend;
+	s8 index;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	wlc_lcnphy_deaf_mode(pi, true);
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	index = pi_lcn->lcnphy_current_index;
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+
+}
+
+static void wlc_lcnphy_periodic_cal(phy_info_t *pi)
+{
+	bool suspend, full_cal;
+	const lcnphy_rx_iqcomp_t *rx_iqcomp;
+	int rx_iqcomp_sz;
+	u16 SAVE_pwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	s8 index;
+	phytbl_info_t tab;
+	s32 a1, b0, b1;
+	s32 tssi, pwr, maxtargetpwr, mintargetpwr;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	pi->phy_lastcal = pi->sh->now;
+	pi->phy_forcecal = false;
+	full_cal =
+	    (pi_lcn->lcnphy_full_cal_channel !=
+	     CHSPEC_CHANNEL(pi->radio_chanspec));
+	pi_lcn->lcnphy_full_cal_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+	index = pi_lcn->lcnphy_current_index;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend) {
+
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+	wlc_lcnphy_deaf_mode(pi, true);
+
+	wlc_lcnphy_txpwrtbl_iqlo_cal(pi);
+
+	rx_iqcomp = lcnphy_rx_iqcomp_table_rev0;
+	rx_iqcomp_sz = ARRAY_SIZE(lcnphy_rx_iqcomp_table_rev0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 40);
+	else
+		wlc_lcnphy_rx_iq_cal(pi, NULL, 0, true, false, 1, 127);
+
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		wlc_lcnphy_idle_tssi_est((wlc_phy_t *) pi);
+
+		b0 = pi->txpa_2g[0];
+		b1 = pi->txpa_2g[1];
+		a1 = pi->txpa_2g[2];
+		maxtargetpwr = wlc_lcnphy_tssi2dbm(10, a1, b0, b1);
+		mintargetpwr = wlc_lcnphy_tssi2dbm(125, a1, b0, b1);
+
+		tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+		tab.tbl_width = 32;
+		tab.tbl_ptr = &pwr;
+		tab.tbl_len = 1;
+		tab.tbl_offset = 0;
+		for (tssi = 0; tssi < 128; tssi++) {
+			pwr = wlc_lcnphy_tssi2dbm(tssi, a1, b0, b1);
+			pwr = (pwr < mintargetpwr) ? mintargetpwr : pwr;
+			wlc_lcnphy_write_table(pi, &tab);
+			tab.tbl_offset++;
+		}
+	}
+
+	wlc_lcnphy_set_tx_pwr_by_index(pi, index);
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, SAVE_pwrctrl);
+	wlc_lcnphy_deaf_mode(pi, false);
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+void wlc_lcnphy_calib_modes(phy_info_t *pi, uint mode)
+{
+	u16 temp_new;
+	int temp1, temp2, temp_diff;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	switch (mode) {
+	case PHY_PERICAL_CHAN:
+
+		break;
+	case PHY_FULLCAL:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_PHYINIT:
+		wlc_lcnphy_periodic_cal(pi);
+		break;
+	case PHY_PERICAL_WATCHDOG:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+			temp_new = wlc_lcnphy_tempsense(pi, 0);
+			temp1 = LCNPHY_TEMPSENSE(temp_new);
+			temp2 = LCNPHY_TEMPSENSE(pi_lcn->lcnphy_cal_temper);
+			temp_diff = temp1 - temp2;
+			if ((pi_lcn->lcnphy_cal_counter > 90) ||
+			    (temp_diff > 60) || (temp_diff < -60)) {
+				wlc_lcnphy_glacial_timer_based_cal(pi);
+				wlc_2064_vco_cal(pi);
+				pi_lcn->lcnphy_cal_temper = temp_new;
+				pi_lcn->lcnphy_cal_counter = 0;
+			} else
+				pi_lcn->lcnphy_cal_counter++;
+		}
+		break;
+	case LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL:
+		if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+			wlc_lcnphy_tx_power_adjustment((wlc_phy_t *) pi);
+		break;
+	default:
+		ASSERT(0);
+		break;
+	}
+}
+
+void wlc_lcnphy_get_tssi(phy_info_t *pi, s8 *ofdm_pwr, s8 *cck_pwr)
+{
+	s8 cck_offset;
+	u16 status;
+	status = (read_phy_reg(pi, 0x4ab));
+	if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi) &&
+	    (status  & (0x1 << 15))) {
+		*ofdm_pwr = (s8) (((read_phy_reg(pi, 0x4ab) & (0x1ff << 0))
+				     >> 0) >> 1);
+
+		if (wlc_phy_tpc_isenabled_lcnphy(pi))
+			cck_offset = pi->tx_power_offset[TXP_FIRST_CCK];
+		else
+			cck_offset = 0;
+
+		*cck_pwr = *ofdm_pwr + cck_offset;
+	} else {
+		*cck_pwr = 0;
+		*ofdm_pwr = 0;
+	}
+}
+
+void WLBANDINITFN(wlc_phy_cal_init_lcnphy) (phy_info_t *pi)
+{
+	return;
+
+}
+
+static void wlc_lcnphy_set_chanspec_tweaks(phy_info_t *pi, chanspec_t chanspec)
+{
+	u8 channel = CHSPEC_CHANNEL(chanspec);
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	if (channel == 14) {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (2) << 8);
+
+	} else {
+		mod_phy_reg(pi, 0x448, (0x3 << 8), (1) << 8);
+
+	}
+	pi_lcn->lcnphy_bandedge_corr = 2;
+	if (channel == 1)
+		pi_lcn->lcnphy_bandedge_corr = 4;
+
+	if (channel == 1 || channel == 2 || channel == 3 ||
+	    channel == 4 || channel == 9 ||
+	    channel == 10 || channel == 11 || channel == 12) {
+		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03000c04);
+		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x0);
+		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x200005c0);
+
+		si_pmu_pllupd(pi->sh->sih);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, false);
+		pi_lcn->lcnphy_spurmod = 0;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1b) << 8);
+
+		write_phy_reg(pi, 0x425, 0x5907);
+	} else {
+		si_pmu_pllcontrol(pi->sh->sih, 0x2, 0xffffffff, 0x03140c04);
+		si_pmu_pllcontrol(pi->sh->sih, 0x3, 0xffffff, 0x333333);
+		si_pmu_pllcontrol(pi->sh->sih, 0x4, 0xffffffff, 0x202c2820);
+
+		si_pmu_pllupd(pi->sh->sih);
+		write_phy_reg(pi, 0x942, 0);
+		wlc_lcnphy_txrx_spur_avoidance_mode(pi, true);
+
+		pi_lcn->lcnphy_spurmod = 0;
+		mod_phy_reg(pi, 0x424, (0xff << 8), (0x1f) << 8);
+
+		write_phy_reg(pi, 0x425, 0x590a);
+	}
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+}
+
+void wlc_lcnphy_tx_power_adjustment(wlc_phy_t *ppi)
+{
+	s8 index;
+	u16 index2;
+	phy_info_t *pi = (phy_info_t *) ppi;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	u16 SAVE_txpwrctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi) && SAVE_txpwrctrl) {
+		index = wlc_lcnphy_tempcompensated_txpwrctrl(pi);
+		index2 = (u16) (index * 2);
+		mod_phy_reg(pi, 0x4a9, (0x1ff << 0), (index2) << 0);
+
+		pi_lcn->lcnphy_current_index = (s8)
+		    ((read_phy_reg(pi, 0x4a9) & 0xFF) / 2);
+	}
+}
+
+static void wlc_lcnphy_set_rx_iq_comp(phy_info_t *pi, u16 a, u16 b)
+{
+	mod_phy_reg(pi, 0x645, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x646, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x647, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x648, (0x3ff << 0), (b) << 0);
+
+	mod_phy_reg(pi, 0x649, (0x3ff << 0), (a) << 0);
+
+	mod_phy_reg(pi, 0x64a, (0x3ff << 0), (b) << 0);
+
+}
+
+void WLBANDINITFN(wlc_phy_init_lcnphy) (phy_info_t *pi)
+{
+	u8 phybw40;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	pi_lcn->lcnphy_cal_counter = 0;
+	pi_lcn->lcnphy_cal_temper = pi_lcn->lcnphy_rawtempsense;
+
+	or_phy_reg(pi, 0x44a, 0x80);
+	and_phy_reg(pi, 0x44a, 0x7f);
+
+	wlc_lcnphy_afe_clk_init(pi, AFE_CLK_INIT_MODE_TXRX2X);
+
+	write_phy_reg(pi, 0x60a, 160);
+
+	write_phy_reg(pi, 0x46a, 25);
+
+	wlc_lcnphy_baseband_init(pi);
+
+	wlc_lcnphy_radio_init(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_lcnphy_tx_pwr_ctrl_init((wlc_phy_t *) pi);
+
+	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
+
+	si_pmu_regcontrol(pi->sh->sih, 0, 0xf, 0x9);
+
+	si_pmu_chipcontrol(pi->sh->sih, 0, 0xffffffff, 0x03CDDDDD);
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, FIXED_TXPWR);
+
+	wlc_lcnphy_agc_temp_init(pi);
+
+	wlc_lcnphy_temp_adj(pi);
+
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (1) << 14);
+
+	udelay(100);
+	mod_phy_reg(pi, 0x448, (0x1 << 14), (0) << 14);
+
+	wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_HW);
+	pi_lcn->lcnphy_noise_samples = LCNPHY_NOISE_SAMPLES_DEFAULT;
+	wlc_lcnphy_calib_modes(pi, PHY_PERICAL_PHYINIT);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback(phy_info_t *pi, u16 *values_to_save)
+{
+	u16 vmid;
+	int i;
+	for (i = 0; i < 20; i++) {
+		values_to_save[i] =
+		    read_radio_reg(pi, iqlo_loopback_rf_regs[i]);
+	}
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 12), 1 << 12);
+	mod_phy_reg(pi, 0x44d, (0x1 << 14), 1 << 14);
+
+	mod_phy_reg(pi, 0x44c, (0x1 << 11), 1 << 11);
+	mod_phy_reg(pi, 0x44d, (0x1 << 13), 0 << 13);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0x43c, (0x1 << 1), 0 << 1);
+
+	mod_phy_reg(pi, 0x43b, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x43c, (0x1 << 0), 0 << 0);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xFD);
+	else
+		and_radio_reg(pi, RADIO_2064_REG03A, 0xF9);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x1);
+
+	or_radio_reg(pi, RADIO_2064_REG036, 0x01);
+	or_radio_reg(pi, RADIO_2064_REG11A, 0x18);
+	udelay(20);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 1, 0);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 1);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG03A, 3, 1);
+		else
+			or_radio_reg(pi, RADIO_2064_REG03A, 0x3);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG025, 0xF);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x4);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0xF, 0x6);
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec))
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x4 << 1);
+		else
+			mod_radio_reg(pi, RADIO_2064_REG028, 0x1e, 0x6 << 1);
+	}
+
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG005, 0x8);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x80);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG00B, 0x7);
+	or_radio_reg(pi, RADIO_2064_REG113, 0x10);
+	udelay(20);
+
+	write_radio_reg(pi, RADIO_2064_REG007, 0x1);
+	udelay(20);
+
+	vmid = 0x2A6;
+	mod_radio_reg(pi, RADIO_2064_REG0FC, 0x3 << 0, (vmid >> 8) & 0x3);
+	write_radio_reg(pi, RADIO_2064_REG0FD, (vmid & 0xff));
+	or_radio_reg(pi, RADIO_2064_REG11F, 0x44);
+	udelay(20);
+
+	or_radio_reg(pi, RADIO_2064_REG0FF, 0x10);
+	udelay(20);
+	write_radio_reg(pi, RADIO_2064_REG012, 0x02);
+	or_radio_reg(pi, RADIO_2064_REG112, 0x06);
+	write_radio_reg(pi, RADIO_2064_REG036, 0x11);
+	write_radio_reg(pi, RADIO_2064_REG059, 0xcc);
+	write_radio_reg(pi, RADIO_2064_REG05C, 0x2e);
+	write_radio_reg(pi, RADIO_2064_REG078, 0xd7);
+	write_radio_reg(pi, RADIO_2064_REG092, 0x15);
+}
+
+static void
+wlc_lcnphy_samp_cap(phy_info_t *pi, int clip_detect_algo, u16 thresh,
+		    s16 *ptr, int mode)
+{
+	u32 curval1, curval2, stpptr, curptr, strptr, val;
+	u16 sslpnCalibClkEnCtrl, timer;
+	u16 old_sslpnCalibClkEnCtrl;
+	s16 imag, real;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	timer = 0;
+	old_sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+
+	curval1 = R_REG(&pi->regs->psm_corectlsts);
+	ptr[130] = 0;
+	W_REG(&pi->regs->psm_corectlsts, ((1 << 6) | curval1));
+
+	W_REG(&pi->regs->smpl_clct_strptr, 0x7E00);
+	W_REG(&pi->regs->smpl_clct_stpptr, 0x8000);
+	udelay(20);
+	curval2 = R_REG(&pi->regs->psm_phy_hdr_param);
+	W_REG(&pi->regs->psm_phy_hdr_param, curval2 | 0x30);
+
+	write_phy_reg(pi, 0x555, 0x0);
+	write_phy_reg(pi, 0x5a6, 0x5);
+
+	write_phy_reg(pi, 0x5a2, (u16) (mode | mode << 6));
+	write_phy_reg(pi, 0x5cf, 3);
+	write_phy_reg(pi, 0x5a5, 0x3);
+	write_phy_reg(pi, 0x583, 0x0);
+	write_phy_reg(pi, 0x584, 0x0);
+	write_phy_reg(pi, 0x585, 0x0fff);
+	write_phy_reg(pi, 0x586, 0x0000);
+
+	write_phy_reg(pi, 0x580, 0x4501);
+
+	sslpnCalibClkEnCtrl = read_phy_reg(pi, 0x6da);
+	write_phy_reg(pi, 0x6da, (u32) (sslpnCalibClkEnCtrl | 0x2008));
+	stpptr = R_REG(&pi->regs->smpl_clct_stpptr);
+	curptr = R_REG(&pi->regs->smpl_clct_curptr);
+	do {
+		udelay(10);
+		curptr = R_REG(&pi->regs->smpl_clct_curptr);
+		timer++;
+	} while ((curptr != stpptr) && (timer < 500));
+
+	W_REG(&pi->regs->psm_phy_hdr_param, 0x2);
+	strptr = 0x7E00;
+	W_REG(&pi->regs->tplatewrptr, strptr);
+	while (strptr < 0x8000) {
+		val = R_REG(&pi->regs->tplatewrdata);
+		imag = ((val >> 16) & 0x3ff);
+		real = ((val) & 0x3ff);
+		if (imag > 511) {
+			imag -= 1024;
+		}
+		if (real > 511) {
+			real -= 1024;
+		}
+		if (pi_lcn->lcnphy_iqcal_swp_dis)
+			ptr[(strptr - 0x7E00) / 4] = real;
+		else
+			ptr[(strptr - 0x7E00) / 4] = imag;
+		if (clip_detect_algo) {
+			if (imag > thresh || imag < -thresh) {
+				strptr = 0x8000;
+				ptr[130] = 1;
+			}
+		}
+		strptr += 4;
+	}
+
+	write_phy_reg(pi, 0x6da, old_sslpnCalibClkEnCtrl);
+	W_REG(&pi->regs->psm_phy_hdr_param, curval2);
+	W_REG(&pi->regs->psm_corectlsts, curval1);
+}
+
+static void wlc_lcnphy_tx_iqlo_soft_cal_full(phy_info_t *pi)
+{
+	lcnphy_unsign16_struct iqcc0, locc2, locc3, locc4;
+
+	wlc_lcnphy_set_cc(pi, 0, 0, 0);
+	wlc_lcnphy_set_cc(pi, 2, 0, 0);
+	wlc_lcnphy_set_cc(pi, 3, 0, 0);
+	wlc_lcnphy_set_cc(pi, 4, 0, 0);
+
+	wlc_lcnphy_a1(pi, 4, 0, 0);
+	wlc_lcnphy_a1(pi, 3, 0, 0);
+	wlc_lcnphy_a1(pi, 2, 3, 2);
+	wlc_lcnphy_a1(pi, 0, 5, 8);
+	wlc_lcnphy_a1(pi, 2, 2, 1);
+	wlc_lcnphy_a1(pi, 0, 4, 3);
+
+	iqcc0 = wlc_lcnphy_get_cc(pi, 0);
+	locc2 = wlc_lcnphy_get_cc(pi, 2);
+	locc3 = wlc_lcnphy_get_cc(pi, 3);
+	locc4 = wlc_lcnphy_get_cc(pi, 4);
+}
+
+static void
+wlc_lcnphy_set_cc(phy_info_t *pi, int cal_type, s16 coeff_x, s16 coeff_y)
+{
+	u16 di0dq0;
+	u16 x, y, data_rf;
+	int k;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_set_tx_iqcc(pi, coeff_x, coeff_y);
+		break;
+	case 2:
+		di0dq0 = (coeff_x & 0xff) << 8 | (coeff_y & 0xff);
+		wlc_lcnphy_set_tx_locc(pi, di0dq0);
+		break;
+	case 3:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG089, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08A, data_rf);
+		break;
+	case 4:
+		k = wlc_lcnphy_calc_floor(coeff_x, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_x, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08B, data_rf);
+		k = wlc_lcnphy_calc_floor(coeff_y, 0);
+		y = 8 + k;
+		k = wlc_lcnphy_calc_floor(coeff_y, 1);
+		x = 8 - k;
+		data_rf = (x * 16 + y);
+		write_radio_reg(pi, RADIO_2064_REG08C, data_rf);
+		break;
+	}
+}
+
+static lcnphy_unsign16_struct wlc_lcnphy_get_cc(phy_info_t *pi, int cal_type)
+{
+	u16 a, b, didq;
+	u8 di0, dq0, ei, eq, fi, fq;
+	lcnphy_unsign16_struct cc;
+	cc.re = 0;
+	cc.im = 0;
+	switch (cal_type) {
+	case 0:
+		wlc_lcnphy_get_tx_iqcc(pi, &a, &b);
+		cc.re = a;
+		cc.im = b;
+		break;
+	case 2:
+		didq = wlc_lcnphy_get_tx_locc(pi);
+		di0 = (((didq & 0xff00) << 16) >> 24);
+		dq0 = (((didq & 0x00ff) << 24) >> 24);
+		cc.re = (u16) di0;
+		cc.im = (u16) dq0;
+		break;
+	case 3:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) ei;
+		cc.im = (u16) eq;
+		break;
+	case 4:
+		wlc_lcnphy_get_radio_loft(pi, &ei, &eq, &fi, &fq);
+		cc.re = (u16) fi;
+		cc.im = (u16) fq;
+		break;
+	}
+	return cc;
+}
+
+static void
+wlc_lcnphy_a1(phy_info_t *pi, int cal_type, int num_levels, int step_size_lg2)
+{
+	const lcnphy_spb_tone_t *phy_c1;
+	lcnphy_spb_tone_t phy_c2;
+	lcnphy_unsign16_struct phy_c3;
+	int phy_c4, phy_c5, k, l, j, phy_c6;
+	u16 phy_c7, phy_c8, phy_c9;
+	s16 phy_c10, phy_c11, phy_c12, phy_c13, phy_c14, phy_c15, phy_c16;
+	s16 *ptr, phy_c17;
+	s32 phy_c18, phy_c19;
+	u32 phy_c20, phy_c21;
+	bool phy_c22, phy_c23, phy_c24, phy_c25;
+	u16 phy_c26, phy_c27;
+	u16 phy_c28, phy_c29, phy_c30;
+	u16 phy_c31;
+	u16 *phy_c32;
+	phy_c21 = 0;
+	phy_c10 = phy_c13 = phy_c14 = phy_c8 = 0;
+	ptr = kmalloc(sizeof(s16) * 131, GFP_ATOMIC);
+	if (NULL == ptr) {
+		return;
+	}
+
+	phy_c32 = kmalloc(sizeof(u16) * 20, GFP_ATOMIC);
+	if (NULL == phy_c32) {
+		kfree(ptr);
+		return;
+	}
+	phy_c26 = read_phy_reg(pi, 0x6da);
+	phy_c27 = read_phy_reg(pi, 0x6db);
+	phy_c31 = read_radio_reg(pi, RADIO_2064_REG026);
+	write_phy_reg(pi, 0x93d, 0xC0);
+
+	wlc_lcnphy_start_tx_tone(pi, 3750, 88, 0);
+	write_phy_reg(pi, 0x6da, 0xffff);
+	or_phy_reg(pi, 0x6db, 0x3);
+
+	wlc_lcnphy_tx_iqlo_loopback(pi, phy_c32);
+	udelay(500);
+	phy_c28 = read_phy_reg(pi, 0x938);
+	phy_c29 = read_phy_reg(pi, 0x4d7);
+	phy_c30 = read_phy_reg(pi, 0x4d8);
+	or_phy_reg(pi, 0x938, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 2);
+	or_phy_reg(pi, 0x4d7, 0x1 << 3);
+	mod_phy_reg(pi, 0x4d7, (0x7 << 12), 0x2 << 12);
+	or_phy_reg(pi, 0x4d8, 1 << 0);
+	or_phy_reg(pi, 0x4d8, 1 << 1);
+	mod_phy_reg(pi, 0x4d8, (0x3ff << 2), 0x23A << 2);
+	mod_phy_reg(pi, 0x4d8, (0x7 << 12), 0x7 << 12);
+	phy_c1 = &lcnphy_spb_tone_3750[0];
+	phy_c4 = 32;
+
+	if (num_levels == 0) {
+		if (cal_type != 0) {
+			num_levels = 4;
+		} else {
+			num_levels = 9;
+		}
+	}
+	if (step_size_lg2 == 0) {
+		if (cal_type != 0) {
+			step_size_lg2 = 3;
+		} else {
+			step_size_lg2 = 8;
+		}
+	}
+
+	phy_c7 = (1 << step_size_lg2);
+	phy_c3 = wlc_lcnphy_get_cc(pi, cal_type);
+	phy_c15 = (s16) phy_c3.re;
+	phy_c16 = (s16) phy_c3.im;
+	if (cal_type == 2) {
+		if (phy_c3.re > 127)
+			phy_c15 = phy_c3.re - 256;
+		if (phy_c3.im > 127)
+			phy_c16 = phy_c3.im - 256;
+	}
+	wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+	udelay(20);
+	for (phy_c8 = 0; phy_c7 != 0 && phy_c8 < num_levels; phy_c8++) {
+		phy_c23 = 1;
+		phy_c22 = 0;
+		switch (cal_type) {
+		case 0:
+			phy_c10 = 511;
+			break;
+		case 2:
+			phy_c10 = 127;
+			break;
+		case 3:
+			phy_c10 = 15;
+			break;
+		case 4:
+			phy_c10 = 15;
+			break;
+		}
+
+		phy_c9 = read_phy_reg(pi, 0x93d);
+		phy_c9 = 2 * phy_c9;
+		phy_c24 = 0;
+		phy_c5 = 7;
+		phy_c25 = 1;
+		while (1) {
+			write_radio_reg(pi, RADIO_2064_REG026,
+					(phy_c5 & 0x7) | ((phy_c5 & 0x7) << 4));
+			udelay(50);
+			phy_c22 = 0;
+			ptr[130] = 0;
+			wlc_lcnphy_samp_cap(pi, 1, phy_c9, &ptr[0], 2);
+			if (ptr[130] == 1)
+				phy_c22 = 1;
+			if (phy_c22)
+				phy_c5 -= 1;
+			if ((phy_c22 != phy_c24) && (!phy_c25))
+				break;
+			if (!phy_c22)
+				phy_c5 += 1;
+			if (phy_c5 <= 0 || phy_c5 >= 7)
+				break;
+			phy_c24 = phy_c22;
+			phy_c25 = 0;
+		}
+
+		if (phy_c5 < 0)
+			phy_c5 = 0;
+		else if (phy_c5 > 7)
+			phy_c5 = 7;
+
+		for (k = -phy_c7; k <= phy_c7; k += phy_c7) {
+			for (l = -phy_c7; l <= phy_c7; l += phy_c7) {
+				phy_c11 = phy_c15 + k;
+				phy_c12 = phy_c16 + l;
+
+				if (phy_c11 < -phy_c10)
+					phy_c11 = -phy_c10;
+				else if (phy_c11 > phy_c10)
+					phy_c11 = phy_c10;
+				if (phy_c12 < -phy_c10)
+					phy_c12 = -phy_c10;
+				else if (phy_c12 > phy_c10)
+					phy_c12 = phy_c10;
+				wlc_lcnphy_set_cc(pi, cal_type, phy_c11,
+						  phy_c12);
+				udelay(20);
+				wlc_lcnphy_samp_cap(pi, 0, 0, ptr, 2);
+
+				phy_c18 = 0;
+				phy_c19 = 0;
+				for (j = 0; j < 128; j++) {
+					if (cal_type != 0) {
+						phy_c6 = j % phy_c4;
+					} else {
+						phy_c6 = (2 * j) % phy_c4;
+					}
+					phy_c2.re = phy_c1[phy_c6].re;
+					phy_c2.im = phy_c1[phy_c6].im;
+					phy_c17 = ptr[j];
+					phy_c18 = phy_c18 + phy_c17 * phy_c2.re;
+					phy_c19 = phy_c19 + phy_c17 * phy_c2.im;
+				}
+
+				phy_c18 = phy_c18 >> 10;
+				phy_c19 = phy_c19 >> 10;
+				phy_c20 =
+				    ((phy_c18 * phy_c18) + (phy_c19 * phy_c19));
+
+				if (phy_c23 || phy_c20 < phy_c21) {
+					phy_c21 = phy_c20;
+					phy_c13 = phy_c11;
+					phy_c14 = phy_c12;
+				}
+				phy_c23 = 0;
+			}
+		}
+		phy_c23 = 1;
+		phy_c15 = phy_c13;
+		phy_c16 = phy_c14;
+		phy_c7 = phy_c7 >> 1;
+		wlc_lcnphy_set_cc(pi, cal_type, phy_c15, phy_c16);
+		udelay(20);
+	}
+	goto cleanup;
+ cleanup:
+	wlc_lcnphy_tx_iqlo_loopback_cleanup(pi, phy_c32);
+	wlc_lcnphy_stop_tx_tone(pi);
+	write_phy_reg(pi, 0x6da, phy_c26);
+	write_phy_reg(pi, 0x6db, phy_c27);
+	write_phy_reg(pi, 0x938, phy_c28);
+	write_phy_reg(pi, 0x4d7, phy_c29);
+	write_phy_reg(pi, 0x4d8, phy_c30);
+	write_radio_reg(pi, RADIO_2064_REG026, phy_c31);
+
+	kfree(phy_c32);
+	kfree(ptr);
+}
+
+static void
+wlc_lcnphy_tx_iqlo_loopback_cleanup(phy_info_t *pi, u16 *values_to_save)
+{
+	int i;
+
+	and_phy_reg(pi, 0x44c, 0x0 >> 11);
+
+	and_phy_reg(pi, 0x43b, 0xC);
+
+	for (i = 0; i < 20; i++) {
+		write_radio_reg(pi, iqlo_loopback_rf_regs[i],
+				values_to_save[i]);
+	}
+}
+
+static void
+WLBANDINITFN(wlc_lcnphy_load_tx_gain_table) (phy_info_t *pi,
+					     const lcnphy_tx_gain_tbl_entry *
+					     gain_table) {
+	u32 j;
+	phytbl_info_t tab;
+	u32 val;
+	u16 pa_gain;
+	u16 gm_gain;
+
+	if (CHSPEC_IS5G(pi->radio_chanspec))
+		pa_gain = 0x70;
+	else
+		pa_gain = 0x70;
+
+	if (pi->sh->boardflags & BFL_FEM)
+		pa_gain = 0x10;
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+	tab.tbl_ptr = &val;
+
+	for (j = 0; j < 128; j++) {
+		gm_gain = gain_table[j].gm;
+		val = (((u32) pa_gain << 24) |
+		       (gain_table[j].pad << 16) |
+		       (gain_table[j].pga << 8) | gm_gain);
+
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+
+		val = (gain_table[j].dac << 28) | (gain_table[j].bb_mult << 20);
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + j;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void wlc_lcnphy_load_rfpower(phy_info_t *pi)
+{
+	phytbl_info_t tab;
+	u32 val, bbmult, rfgain;
+	u8 index;
+	u8 scale_factor = 1;
+	s16 temp, temp1, temp2, qQ, qQ1, qQ2, shift;
+
+	tab.tbl_id = LCNPHY_TBL_ID_TXPWRCTL;
+	tab.tbl_width = 32;
+	tab.tbl_len = 1;
+
+	for (index = 0; index < 128; index++) {
+		tab.tbl_ptr = &bbmult;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_IQ_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+		bbmult = bbmult >> 20;
+
+		tab.tbl_ptr = &rfgain;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_GAIN_OFFSET + index;
+		wlc_lcnphy_read_table(pi, &tab);
+
+		qm_log10((s32) (bbmult), 0, &temp1, &qQ1);
+		qm_log10((s32) (1 << 6), 0, &temp2, &qQ2);
+
+		if (qQ1 < qQ2) {
+			temp2 = qm_shr16(temp2, qQ2 - qQ1);
+			qQ = qQ1;
+		} else {
+			temp1 = qm_shr16(temp1, qQ1 - qQ2);
+			qQ = qQ2;
+		}
+		temp = qm_sub16(temp1, temp2);
+
+		if (qQ >= 4)
+			shift = qQ - 4;
+		else
+			shift = 4 - qQ;
+
+		val = (((index << shift) + (5 * temp) +
+			(1 << (scale_factor + shift - 3))) >> (scale_factor +
+							       shift - 2));
+
+		tab.tbl_ptr = &val;
+		tab.tbl_offset = LCNPHY_TX_PWR_CTRL_PWR_OFFSET + index;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+}
+
+static void WLBANDINITFN(wlc_lcnphy_tbl_init) (phy_info_t *pi)
+{
+	uint idx;
+	u8 phybw40;
+	phytbl_info_t tab;
+	u32 val;
+
+	phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+
+	for (idx = 0; idx < dot11lcnphytbl_info_sz_rev0; idx++) {
+		wlc_lcnphy_write_table(pi, &dot11lcnphytbl_info_rev0[idx]);
+	}
+
+	if (pi->sh->boardflags & BFL_FEM_BT) {
+		tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+		tab.tbl_width = 16;
+		tab.tbl_ptr = &val;
+		tab.tbl_len = 1;
+		val = 100;
+		tab.tbl_offset = 4;
+		wlc_lcnphy_write_table(pi, &tab);
+	}
+
+	tab.tbl_id = LCNPHY_TBL_ID_RFSEQ;
+	tab.tbl_width = 16;
+	tab.tbl_ptr = &val;
+	tab.tbl_len = 1;
+
+	val = 114;
+	tab.tbl_offset = 0;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 130;
+	tab.tbl_offset = 1;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	val = 6;
+	tab.tbl_offset = 8;
+	wlc_lcnphy_write_table(pi, &tab);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->sh->boardflags & BFL_FEM)
+			wlc_lcnphy_load_tx_gain_table(pi,
+						      dot11lcnphy_2GHz_extPA_gaintable_rev0);
+		else
+			wlc_lcnphy_load_tx_gain_table(pi,
+						      dot11lcnphy_2GHz_gaintable_rev0);
+	}
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2)) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			for (idx = 0;
+			     idx < dot11lcnphytbl_rx_gain_info_2G_rev2_sz;
+			     idx++)
+				if (pi->sh->boardflags & BFL_EXTLNA)
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_extlna_2G_rev2
+							       [idx]);
+				else
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_2G_rev2
+							       [idx]);
+		} else {
+			for (idx = 0;
+			     idx < dot11lcnphytbl_rx_gain_info_5G_rev2_sz;
+			     idx++)
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz)
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_extlna_5G_rev2
+							       [idx]);
+				else
+					wlc_lcnphy_write_table(pi,
+							       &dot11lcnphytbl_rx_gain_info_5G_rev2
+							       [idx]);
+		}
+	}
+
+	if ((pi->sh->boardflags & BFL_FEM)
+	    && !(pi->sh->boardflags & BFL_FEM_BT))
+		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313_epa);
+	else if (pi->sh->boardflags & BFL_FEM_BT) {
+		if (pi->sh->boardrev < 0x1250)
+			wlc_lcnphy_write_table(pi,
+					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa);
+		else
+			wlc_lcnphy_write_table(pi,
+					       &dot11lcn_sw_ctrl_tbl_info_4313_bt_epa_p250);
+	} else
+		wlc_lcnphy_write_table(pi, &dot11lcn_sw_ctrl_tbl_info_4313);
+
+	wlc_lcnphy_load_rfpower(pi);
+
+	wlc_lcnphy_clear_papd_comptable(pi);
+}
+
+static void WLBANDINITFN(wlc_lcnphy_rev0_baseband_init) (phy_info_t *pi)
+{
+	u16 afectrl1;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	write_radio_reg(pi, RADIO_2064_REG11C, 0x0);
+
+	write_phy_reg(pi, 0x43b, 0x0);
+	write_phy_reg(pi, 0x43c, 0x0);
+	write_phy_reg(pi, 0x44c, 0x0);
+	write_phy_reg(pi, 0x4e6, 0x0);
+	write_phy_reg(pi, 0x4f9, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x938, 0x0);
+	write_phy_reg(pi, 0x4b0, 0x0);
+	write_phy_reg(pi, 0x44e, 0);
+
+	or_phy_reg(pi, 0x567, 0x03);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+
+	if (!(pi->sh->boardflags & BFL_FEM))
+		wlc_lcnphy_set_tx_pwr_by_index(pi, 52);
+
+	if (0) {
+		afectrl1 = 0;
+		afectrl1 = (u16) ((pi_lcn->lcnphy_rssi_vf) |
+				     (pi_lcn->lcnphy_rssi_vc << 4) | (pi_lcn->
+								      lcnphy_rssi_gs
+								      << 10));
+		write_phy_reg(pi, 0x43e, afectrl1);
+	}
+
+	mod_phy_reg(pi, 0x634, (0xff << 0), 0xC << 0);
+	if (pi->sh->boardflags & BFL_FEM) {
+		mod_phy_reg(pi, 0x634, (0xff << 0), 0xA << 0);
+
+		write_phy_reg(pi, 0x910, 0x1);
+	}
+
+	mod_phy_reg(pi, 0x448, (0x3 << 8), 1 << 8);
+	mod_phy_reg(pi, 0x608, (0xff << 0), 0x17 << 0);
+	mod_phy_reg(pi, 0x604, (0x7ff << 0), 0x3EA << 0);
+
+}
+
+static void WLBANDINITFN(wlc_lcnphy_rev2_baseband_init) (phy_info_t *pi)
+{
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x416, (0xff << 0), 80 << 0);
+
+		mod_phy_reg(pi, 0x416, (0xff << 8), 80 << 8);
+	}
+}
+
+static void wlc_lcnphy_agc_temp_init(phy_info_t *pi)
+{
+	s16 temp;
+	phytbl_info_t tab;
+	u32 tableBuffer[2];
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	temp = (s16) read_phy_reg(pi, 0x4df);
+	pi_lcn->lcnphy_ofdmgainidxtableoffset = (temp & (0xff << 0)) >> 0;
+
+	if (pi_lcn->lcnphy_ofdmgainidxtableoffset > 127)
+		pi_lcn->lcnphy_ofdmgainidxtableoffset -= 256;
+
+	pi_lcn->lcnphy_dsssgainidxtableoffset = (temp & (0xff << 8)) >> 8;
+
+	if (pi_lcn->lcnphy_dsssgainidxtableoffset > 127)
+		pi_lcn->lcnphy_dsssgainidxtableoffset -= 256;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = 17;
+	tab.tbl_offset = 59;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	if (tableBuffer[0] > 63)
+		tableBuffer[0] -= 128;
+	pi_lcn->lcnphy_tr_R_gain_val = tableBuffer[0];
+
+	if (tableBuffer[1] > 63)
+		tableBuffer[1] -= 128;
+	pi_lcn->lcnphy_tr_T_gain_val = tableBuffer[1];
+
+	temp = (s16) (read_phy_reg(pi, 0x434)
+			& (0xff << 0));
+	if (temp > 127)
+		temp -= 256;
+	pi_lcn->lcnphy_input_pwr_offset_db = (s8) temp;
+
+	pi_lcn->lcnphy_Med_Low_Gain_db = (read_phy_reg(pi, 0x424)
+					  & (0xff << 8))
+	    >> 8;
+	pi_lcn->lcnphy_Very_Low_Gain_db = (read_phy_reg(pi, 0x425)
+					   & (0xff << 0))
+	    >> 0;
+
+	tab.tbl_ptr = tableBuffer;
+	tab.tbl_len = 2;
+	tab.tbl_id = LCNPHY_TBL_ID_GAIN_IDX;
+	tab.tbl_offset = 28;
+	tab.tbl_width = 32;
+	wlc_lcnphy_read_table(pi, &tab);
+
+	pi_lcn->lcnphy_gain_idx_14_lowword = tableBuffer[0];
+	pi_lcn->lcnphy_gain_idx_14_hiword = tableBuffer[1];
+
+}
+
+static void WLBANDINITFN(wlc_lcnphy_bu_tweaks) (phy_info_t *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	or_phy_reg(pi, 0x805, 0x1);
+
+	mod_phy_reg(pi, 0x42f, (0x7 << 0), (0x3) << 0);
+
+	mod_phy_reg(pi, 0x030, (0x7 << 0), (0x3) << 0);
+
+	write_phy_reg(pi, 0x414, 0x1e10);
+	write_phy_reg(pi, 0x415, 0x0640);
+
+	mod_phy_reg(pi, 0x4df, (0xff << 8), -9 << 8);
+
+	or_phy_reg(pi, 0x44a, 0x44);
+	write_phy_reg(pi, 0x44a, 0x80);
+	mod_phy_reg(pi, 0x434, (0xff << 0), (0xFD) << 0);
+
+	mod_phy_reg(pi, 0x420, (0xff << 0), (16) << 0);
+
+	if (!(pi->sh->boardrev < 0x1204))
+		mod_radio_reg(pi, RADIO_2064_REG09B, 0xF0, 0xF0);
+
+	write_phy_reg(pi, 0x7d6, 0x0902);
+	mod_phy_reg(pi, 0x429, (0xf << 0), (0x9) << 0);
+
+	mod_phy_reg(pi, 0x429, (0x3f << 4), (0xe) << 4);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		mod_phy_reg(pi, 0x423, (0xff << 0), (0x46) << 0);
+
+		mod_phy_reg(pi, 0x411, (0xff << 0), (1) << 0);
+
+		mod_phy_reg(pi, 0x434, (0xff << 0), (0xFF) << 0);
+
+		mod_phy_reg(pi, 0x656, (0xf << 0), (2) << 0);
+
+		mod_phy_reg(pi, 0x44d, (0x1 << 2), (1) << 2);
+
+		mod_radio_reg(pi, RADIO_2064_REG0F7, 0x4, 0x4);
+		mod_radio_reg(pi, RADIO_2064_REG0F1, 0x3, 0);
+		mod_radio_reg(pi, RADIO_2064_REG0F2, 0xF8, 0x90);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0x3, 0x2);
+		mod_radio_reg(pi, RADIO_2064_REG0F3, 0xf0, 0xa0);
+
+		mod_radio_reg(pi, RADIO_2064_REG11F, 0x2, 0x2);
+
+		wlc_lcnphy_clear_tx_power_offsets(pi);
+		mod_phy_reg(pi, 0x4d0, (0x1ff << 6), (10) << 6);
+
+	}
+}
+
+static void WLBANDINITFN(wlc_lcnphy_baseband_init) (phy_info_t *pi)
+{
+
+	wlc_lcnphy_tbl_init(pi);
+	wlc_lcnphy_rev0_baseband_init(pi);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 2))
+		wlc_lcnphy_rev2_baseband_init(pi);
+	wlc_lcnphy_bu_tweaks(pi);
+}
+
+static void WLBANDINITFN(wlc_radio_2064_init) (phy_info_t *pi)
+{
+	u32 i;
+	lcnphy_radio_regs_t *lcnphyregs = NULL;
+
+	lcnphyregs = lcnphy_radio_regs_2064;
+
+	for (i = 0; lcnphyregs[i].address != 0xffff; i++)
+		if (CHSPEC_IS5G(pi->radio_chanspec) && lcnphyregs[i].do_init_a)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_a);
+		else if (lcnphyregs[i].do_init_g)
+			write_radio_reg(pi,
+					((lcnphyregs[i].address & 0x3fff) |
+					 RADIO_DEFAULT_CORE),
+					(u16) lcnphyregs[i].init_g);
+
+	write_radio_reg(pi, RADIO_2064_REG032, 0x62);
+	write_radio_reg(pi, RADIO_2064_REG033, 0x19);
+
+	write_radio_reg(pi, RADIO_2064_REG090, 0x10);
+
+	write_radio_reg(pi, RADIO_2064_REG010, 0x00);
+
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+
+		write_radio_reg(pi, RADIO_2064_REG060, 0x7f);
+		write_radio_reg(pi, RADIO_2064_REG061, 0x72);
+		write_radio_reg(pi, RADIO_2064_REG062, 0x7f);
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG01D, 0x02);
+	write_radio_reg(pi, RADIO_2064_REG01E, 0x06);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 0), 0 << 0);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 3), 1 << 3);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 6), 2 << 6);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 9), 3 << 9);
+
+	mod_phy_reg(pi, 0x4ea, (0x7 << 12), 4 << 12);
+
+	write_phy_reg(pi, 0x4ea, 0x4688);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 0), 2 << 0);
+
+	mod_phy_reg(pi, 0x4eb, (0x7 << 6), 0 << 6);
+
+	mod_phy_reg(pi, 0x46a, (0xffff << 0), 25 << 0);
+
+	wlc_lcnphy_set_tx_locc(pi, 0);
+
+	wlc_lcnphy_rcal(pi);
+
+	wlc_lcnphy_rc_cal(pi);
+}
+
+static void WLBANDINITFN(wlc_lcnphy_radio_init) (phy_info_t *pi)
+{
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	wlc_radio_2064_init(pi);
+}
+
+static void wlc_lcnphy_rcal(phy_info_t *pi)
+{
+	u8 rcal_value;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	or_radio_reg(pi, RADIO_2064_REG004, 0x40);
+	or_radio_reg(pi, RADIO_2064_REG120, 0x10);
+
+	or_radio_reg(pi, RADIO_2064_REG078, 0x80);
+	or_radio_reg(pi, RADIO_2064_REG129, 0x02);
+
+	or_radio_reg(pi, RADIO_2064_REG057, 0x01);
+
+	or_radio_reg(pi, RADIO_2064_REG05B, 0x02);
+	mdelay(5);
+	SPINWAIT(!wlc_radio_2064_rcal_done(pi), 10 * 1000 * 1000);
+
+	if (wlc_radio_2064_rcal_done(pi)) {
+		rcal_value = (u8) read_radio_reg(pi, RADIO_2064_REG05C);
+		rcal_value = rcal_value & 0x1f;
+	}
+
+	and_radio_reg(pi, RADIO_2064_REG05B, 0xfD);
+
+	and_radio_reg(pi, RADIO_2064_REG057, 0xFE);
+}
+
+static void wlc_lcnphy_rc_cal(phy_info_t *pi)
+{
+	u8 dflt_rc_cal_val;
+	u16 flt_val;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+
+	dflt_rc_cal_val = 7;
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1))
+		dflt_rc_cal_val = 11;
+	flt_val =
+	    (dflt_rc_cal_val << 10) | (dflt_rc_cal_val << 5) |
+	    (dflt_rc_cal_val);
+	write_phy_reg(pi, 0x933, flt_val);
+	write_phy_reg(pi, 0x934, flt_val);
+	write_phy_reg(pi, 0x935, flt_val);
+	write_phy_reg(pi, 0x936, flt_val);
+	write_phy_reg(pi, 0x937, (flt_val & 0x1FF));
+
+	return;
+}
+
+static bool wlc_phy_txpwr_srom_read_lcnphy(phy_info_t *pi)
+{
+	s8 txpwr = 0;
+	int i;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 cckpo = 0;
+		u32 offset_ofdm, offset_mcs;
+
+		pi_lcn->lcnphy_tr_isolation_mid =
+		    (u8) PHY_GETINTVAR(pi, "triso2g");
+
+		pi_lcn->lcnphy_rx_power_offset =
+		    (u8) PHY_GETINTVAR(pi, "rxpo2g");
+
+		pi->txpa_2g[0] = (s16) PHY_GETINTVAR(pi, "pa0b0");
+		pi->txpa_2g[1] = (s16) PHY_GETINTVAR(pi, "pa0b1");
+		pi->txpa_2g[2] = (s16) PHY_GETINTVAR(pi, "pa0b2");
+
+		pi_lcn->lcnphy_rssi_vf = (u8) PHY_GETINTVAR(pi, "rssismf2g");
+		pi_lcn->lcnphy_rssi_vc = (u8) PHY_GETINTVAR(pi, "rssismc2g");
+		pi_lcn->lcnphy_rssi_gs = (u8) PHY_GETINTVAR(pi, "rssisav2g");
+
+		{
+			pi_lcn->lcnphy_rssi_vf_lowtemp = pi_lcn->lcnphy_rssi_vf;
+			pi_lcn->lcnphy_rssi_vc_lowtemp = pi_lcn->lcnphy_rssi_vc;
+			pi_lcn->lcnphy_rssi_gs_lowtemp = pi_lcn->lcnphy_rssi_gs;
+
+			pi_lcn->lcnphy_rssi_vf_hightemp =
+			    pi_lcn->lcnphy_rssi_vf;
+			pi_lcn->lcnphy_rssi_vc_hightemp =
+			    pi_lcn->lcnphy_rssi_vc;
+			pi_lcn->lcnphy_rssi_gs_hightemp =
+			    pi_lcn->lcnphy_rssi_gs;
+		}
+
+		txpwr = (s8) PHY_GETINTVAR(pi, "maxp2ga0");
+		pi->tx_srom_max_2g = txpwr;
+
+		for (i = 0; i < PWRTBL_NUM_COEFF; i++) {
+			pi->txpa_2g_low_temp[i] = pi->txpa_2g[i];
+			pi->txpa_2g_high_temp[i] = pi->txpa_2g[i];
+		}
+
+		cckpo = (u16) PHY_GETINTVAR(pi, "cck2gpo");
+		if (cckpo) {
+			uint max_pwr_chan = txpwr;
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
+				    ((cckpo & 0xf) * 2);
+				cckpo >>= 4;
+			}
+
+			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = max_pwr_chan -
+				    ((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+		} else {
+			u8 opo = 0;
+
+			opo = (u8) PHY_GETINTVAR(pi, "opo");
+
+			for (i = TXP_FIRST_CCK; i <= TXP_LAST_CCK; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr;
+			}
+
+			offset_ofdm = (u32) PHY_GETINTVAR(pi, "ofdm2gpo");
+
+			for (i = TXP_FIRST_OFDM; i <= TXP_LAST_OFDM; i++) {
+				pi->tx_srom_max_rate_2g[i] = txpwr -
+				    ((offset_ofdm & 0xf) * 2);
+				offset_ofdm >>= 4;
+			}
+			offset_mcs =
+			    ((u16) PHY_GETINTVAR(pi, "mcs2gpo1") << 16) |
+			    (u16) PHY_GETINTVAR(pi, "mcs2gpo0");
+			pi_lcn->lcnphy_mcs20_po = offset_mcs;
+			for (i = TXP_FIRST_SISO_MCS_20;
+			     i <= TXP_LAST_SISO_MCS_20; i++) {
+				pi->tx_srom_max_rate_2g[i] =
+				    txpwr - ((offset_mcs & 0xf) * 2);
+				offset_mcs >>= 4;
+			}
+		}
+
+		pi_lcn->lcnphy_rawtempsense =
+		    (u16) PHY_GETINTVAR(pi, "rawtempsense");
+		pi_lcn->lcnphy_measPower =
+		    (u8) PHY_GETINTVAR(pi, "measpower");
+		pi_lcn->lcnphy_tempsense_slope =
+		    (u8) PHY_GETINTVAR(pi, "tempsense_slope");
+		pi_lcn->lcnphy_hw_iqcal_en =
+		    (bool) PHY_GETINTVAR(pi, "hw_iqcal_en");
+		pi_lcn->lcnphy_iqcal_swp_dis =
+		    (bool) PHY_GETINTVAR(pi, "iqcal_swp_dis");
+		pi_lcn->lcnphy_tempcorrx =
+		    (u8) PHY_GETINTVAR(pi, "tempcorrx");
+		pi_lcn->lcnphy_tempsense_option =
+		    (u8) PHY_GETINTVAR(pi, "tempsense_option");
+		pi_lcn->lcnphy_freqoffset_corr =
+		    (u8) PHY_GETINTVAR(pi, "freqoffset_corr");
+		if ((u8) getintvar(pi->vars, "aa2g") > 1)
+			wlc_phy_ant_rxdiv_set((wlc_phy_t *) pi,
+					      (u8) getintvar(pi->vars,
+								"aa2g"));
+	}
+	pi_lcn->lcnphy_cck_dig_filt_type = -1;
+	if (PHY_GETVAR(pi, "cckdigfilttype")) {
+		s16 temp;
+		temp = (s16) PHY_GETINTVAR(pi, "cckdigfilttype");
+		if (temp >= 0) {
+			pi_lcn->lcnphy_cck_dig_filt_type = temp;
+		}
+	}
+
+	return true;
+}
+
+void wlc_2064_vco_cal(phy_info_t *pi)
+{
+	u8 calnrst;
+
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 1 << 3);
+	calnrst = (u8) read_radio_reg(pi, RADIO_2064_REG056) & 0xf8;
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x03);
+	udelay(1);
+	write_radio_reg(pi, RADIO_2064_REG056, calnrst | 0x07);
+	udelay(300);
+	mod_radio_reg(pi, RADIO_2064_REG057, 1 << 3, 0);
+}
+
+static void
+wlc_lcnphy_radio_2064_channel_tune_4313(phy_info_t *pi, u8 channel)
+{
+	uint i;
+	const chan_info_2064_lcnphy_t *ci;
+	u8 rfpll_doubler = 0;
+	u8 pll_pwrup, pll_pwrup_ovr;
+	fixed qFxtal, qFref, qFvco, qFcal;
+	u8 d15, d16, f16, e44, e45;
+	u32 div_int, div_frac, fvco3, fpfd, fref3, fcal_div;
+	u16 loop_bw, d30, setCount;
+	if (NORADIO_ENAB(pi->pubpi))
+		return;
+	ci = &chan_info_2064_lcnphy[0];
+	rfpll_doubler = 1;
+
+	mod_radio_reg(pi, RADIO_2064_REG09D, 0x4, 0x1 << 2);
+
+	write_radio_reg(pi, RADIO_2064_REG09E, 0xf);
+	if (!rfpll_doubler) {
+		loop_bw = PLL_2064_LOOP_BW;
+		d30 = PLL_2064_D30;
+	} else {
+		loop_bw = PLL_2064_LOOP_BW_DOUBLER;
+		d30 = PLL_2064_D30_DOUBLER;
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		for (i = 0; i < ARRAY_SIZE(chan_info_2064_lcnphy); i++)
+			if (chan_info_2064_lcnphy[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_2064_lcnphy)) {
+			return;
+		}
+
+		ci = &chan_info_2064_lcnphy[i];
+	}
+
+	write_radio_reg(pi, RADIO_2064_REG02A, ci->logen_buftune);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3, ci->logen_rccr_tx);
+
+	mod_radio_reg(pi, RADIO_2064_REG091, 0x3, ci->txrf_mix_tune_ctrl);
+
+	mod_radio_reg(pi, RADIO_2064_REG038, 0xf, ci->pa_input_tune_g);
+
+	mod_radio_reg(pi, RADIO_2064_REG030, 0x3 << 2,
+		      (ci->logen_rccr_rx) << 2);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, 0xf, ci->pa_rxrf_lna1_freq_tune);
+
+	mod_radio_reg(pi, RADIO_2064_REG05E, (0xf) << 4,
+		      (ci->pa_rxrf_lna2_freq_tune) << 4);
+
+	write_radio_reg(pi, RADIO_2064_REG06C, ci->rxrf_rxrf_spare1);
+
+	pll_pwrup = (u8) read_radio_reg(pi, RADIO_2064_REG044);
+	pll_pwrup_ovr = (u8) read_radio_reg(pi, RADIO_2064_REG12B);
+
+	or_radio_reg(pi, RADIO_2064_REG044, 0x07);
+
+	or_radio_reg(pi, RADIO_2064_REG12B, (0x07) << 1);
+	e44 = 0;
+	e45 = 0;
+
+	fpfd = rfpll_doubler ? (pi->xtalfreq << 1) : (pi->xtalfreq);
+	if (pi->xtalfreq > 26000000)
+		e44 = 1;
+	if (pi->xtalfreq > 52000000)
+		e45 = 1;
+	if (e44 == 0)
+		fcal_div = 1;
+	else if (e45 == 0)
+		fcal_div = 2;
+	else
+		fcal_div = 4;
+	fvco3 = (ci->freq * 3);
+	fref3 = 2 * fpfd;
+
+	qFxtal = wlc_lcnphy_qdiv_roundup(pi->xtalfreq, PLL_2064_MHZ, 16);
+	qFref = wlc_lcnphy_qdiv_roundup(fpfd, PLL_2064_MHZ, 16);
+	qFcal = pi->xtalfreq * fcal_div / PLL_2064_MHZ;
+	qFvco = wlc_lcnphy_qdiv_roundup(fvco3, 2, 16);
+
+	write_radio_reg(pi, RADIO_2064_REG04F, 0x02);
+
+	d15 = (pi->xtalfreq * fcal_div * 4 / 5) / PLL_2064_MHZ - 1;
+	write_radio_reg(pi, RADIO_2064_REG052, (0x07 & (d15 >> 2)));
+	write_radio_reg(pi, RADIO_2064_REG053, (d15 & 0x3) << 5);
+
+	d16 = (qFcal * 8 / (d15 + 1)) - 1;
+	write_radio_reg(pi, RADIO_2064_REG051, d16);
+
+	f16 = ((d16 + 1) * (d15 + 1)) / qFcal;
+	setCount = f16 * 3 * (ci->freq) / 32 - 1;
+	mod_radio_reg(pi, RADIO_2064_REG053, (0x0f << 0),
+		      (u8) (setCount >> 8));
+
+	or_radio_reg(pi, RADIO_2064_REG053, 0x10);
+	write_radio_reg(pi, RADIO_2064_REG054, (u8) (setCount & 0xff));
+
+	div_int = ((fvco3 * (PLL_2064_MHZ >> 4)) / fref3) << 4;
+
+	div_frac = ((fvco3 * (PLL_2064_MHZ >> 4)) % fref3) << 4;
+	while (div_frac >= fref3) {
+		div_int++;
+		div_frac -= fref3;
+	}
+	div_frac = wlc_lcnphy_qdiv_roundup(div_frac, fref3, 20);
+
+	mod_radio_reg(pi, RADIO_2064_REG045, (0x1f << 0),
+		      (u8) (div_int >> 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x1f << 4),
+		      (u8) (div_int << 4));
+	mod_radio_reg(pi, RADIO_2064_REG046, (0x0f << 0),
+		      (u8) (div_frac >> 16));
+	write_radio_reg(pi, RADIO_2064_REG047, (u8) (div_frac >> 8) & 0xff);
+	write_radio_reg(pi, RADIO_2064_REG048, (u8) div_frac & 0xff);
+
+	write_radio_reg(pi, RADIO_2064_REG040, 0xfb);
+
+	write_radio_reg(pi, RADIO_2064_REG041, 0x9A);
+	write_radio_reg(pi, RADIO_2064_REG042, 0xA3);
+	write_radio_reg(pi, RADIO_2064_REG043, 0x0C);
+
+	{
+		u8 h29, h23, c28, d29, h28_ten, e30, h30_ten, cp_current;
+		u16 c29, c38, c30, g30, d28;
+		c29 = loop_bw;
+		d29 = 200;
+		c38 = 1250;
+		h29 = d29 / c29;
+		h23 = 1;
+		c28 = 30;
+		d28 = (((PLL_2064_HIGH_END_KVCO - PLL_2064_LOW_END_KVCO) *
+			(fvco3 / 2 - PLL_2064_LOW_END_VCO)) /
+		       (PLL_2064_HIGH_END_VCO - PLL_2064_LOW_END_VCO))
+		    + PLL_2064_LOW_END_KVCO;
+		h28_ten = (d28 * 10) / c28;
+		c30 = 2640;
+		e30 = (d30 - 680) / 490;
+		g30 = 680 + (e30 * 490);
+		h30_ten = (g30 * 10) / c30;
+		cp_current = ((c38 * h29 * h23 * 100) / h28_ten) / h30_ten;
+		mod_radio_reg(pi, RADIO_2064_REG03C, 0x3f, cp_current);
+	}
+	if (channel >= 1 && channel <= 5)
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x8);
+	else
+		write_radio_reg(pi, RADIO_2064_REG03C, 0x7);
+	write_radio_reg(pi, RADIO_2064_REG03D, 0x3);
+
+	mod_radio_reg(pi, RADIO_2064_REG044, 0x0c, 0x0c);
+	udelay(1);
+
+	wlc_2064_vco_cal(pi);
+
+	write_radio_reg(pi, RADIO_2064_REG044, pll_pwrup);
+	write_radio_reg(pi, RADIO_2064_REG12B, pll_pwrup_ovr);
+	if (LCNREV_IS(pi->pubpi.phy_rev, 1)) {
+		write_radio_reg(pi, RADIO_2064_REG038, 3);
+		write_radio_reg(pi, RADIO_2064_REG091, 7);
+	}
+}
+
+bool wlc_phy_tpc_isenabled_lcnphy(phy_info_t *pi)
+{
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi))
+		return 0;
+	else
+		return (LCNPHY_TX_PWR_CTRL_HW ==
+			wlc_lcnphy_get_tx_pwr_ctrl((pi)));
+}
+
+void wlc_phy_txpower_recalc_target_lcnphy(phy_info_t *pi)
+{
+	u16 pwr_ctrl;
+	if (wlc_lcnphy_tempsense_based_pwr_ctrl_enabled(pi)) {
+		wlc_lcnphy_calib_modes(pi, LCNPHY_PERICAL_TEMPBASED_TXPWRCTRL);
+	} else if (wlc_lcnphy_tssi_based_pwr_ctrl_enabled(pi)) {
+
+		pwr_ctrl = wlc_lcnphy_get_tx_pwr_ctrl(pi);
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, LCNPHY_TX_PWR_CTRL_OFF);
+		wlc_lcnphy_txpower_recalc_target(pi);
+
+		wlc_lcnphy_set_tx_pwr_ctrl(pi, pwr_ctrl);
+	} else
+		return;
+}
+
+void wlc_phy_detach_lcnphy(phy_info_t *pi)
+{
+	kfree(pi->u.pi_lcnphy);
+}
+
+bool wlc_phy_attach_lcnphy(phy_info_t *pi)
+{
+	phy_info_lcnphy_t *pi_lcn;
+
+	pi->u.pi_lcnphy = kzalloc(sizeof(phy_info_lcnphy_t), GFP_ATOMIC);
+	if (pi->u.pi_lcnphy == NULL) {
+		return false;
+	}
+
+	pi_lcn = pi->u.pi_lcnphy;
+
+	if ((0 == (pi->sh->boardflags & BFL_NOPA)) && !NORADIO_ENAB(pi->pubpi)) {
+		pi->hwpwrctrl = true;
+		pi->hwpwrctrl_capable = true;
+	}
+
+	pi->xtalfreq = si_alp_clock(pi->sh->sih);
+	ASSERT(0 == (pi->xtalfreq % 1000));
+
+	pi_lcn->lcnphy_papd_rxGnCtrl_init = 0;
+
+	pi->pi_fptr.init = wlc_phy_init_lcnphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_lcnphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_lcnphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_lcnphy;
+	pi->pi_fptr.txiqccget = wlc_lcnphy_get_tx_iqcc;
+	pi->pi_fptr.txiqccset = wlc_lcnphy_set_tx_iqcc;
+	pi->pi_fptr.txloccget = wlc_lcnphy_get_tx_locc;
+	pi->pi_fptr.radioloftget = wlc_lcnphy_get_radio_loft;
+	pi->pi_fptr.detach = wlc_phy_detach_lcnphy;
+
+	if (!wlc_phy_txpwr_srom_read_lcnphy(pi))
+		return false;
+
+	if ((pi->sh->boardflags & BFL_FEM) && (LCNREV_IS(pi->pubpi.phy_rev, 1))) {
+		if (pi_lcn->lcnphy_tempsense_option == 3) {
+			pi->hwpwrctrl = true;
+			pi->hwpwrctrl_capable = true;
+			pi->temppwrctrl_capable = false;
+		} else {
+			pi->hwpwrctrl = false;
+			pi->hwpwrctrl_capable = false;
+			pi->temppwrctrl_capable = true;
+		}
+	}
+
+	return true;
+}
+
+static void wlc_lcnphy_set_rx_gain(phy_info_t *pi, u32 gain)
+{
+	u16 trsw, ext_lna, lna1, lna2, tia, biq0, biq1, gain0_15, gain16_19;
+
+	trsw = (gain & ((u32) 1 << 28)) ? 0 : 1;
+	ext_lna = (u16) (gain >> 29) & 0x01;
+	lna1 = (u16) (gain >> 0) & 0x0f;
+	lna2 = (u16) (gain >> 4) & 0x0f;
+	tia = (u16) (gain >> 8) & 0xf;
+	biq0 = (u16) (gain >> 12) & 0xf;
+	biq1 = (u16) (gain >> 16) & 0xf;
+
+	gain0_15 = (u16) ((lna1 & 0x3) | ((lna1 & 0x3) << 2) |
+			     ((lna2 & 0x3) << 4) | ((lna2 & 0x3) << 6) |
+			     ((tia & 0xf) << 8) | ((biq0 & 0xf) << 12));
+	gain16_19 = biq1;
+
+	mod_phy_reg(pi, 0x44d, (0x1 << 0), trsw << 0);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 9), ext_lna << 9);
+	mod_phy_reg(pi, 0x4b1, (0x1 << 10), ext_lna << 10);
+	mod_phy_reg(pi, 0x4b6, (0xffff << 0), gain0_15 << 0);
+	mod_phy_reg(pi, 0x4b7, (0xf << 0), gain16_19 << 0);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		mod_phy_reg(pi, 0x4b1, (0x3 << 11), lna1 << 11);
+		mod_phy_reg(pi, 0x4e6, (0x3 << 3), lna1 << 3);
+	}
+	wlc_lcnphy_rx_gain_override_enable(pi, true);
+}
+
+static u32 wlc_lcnphy_get_receive_power(phy_info_t *pi, s32 *gain_index)
+{
+	u32 received_power = 0;
+	s32 max_index = 0;
+	u32 gain_code = 0;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	max_index = 36;
+	if (*gain_index >= 0)
+		gain_code = lcnphy_23bitgaincode_table[*gain_index];
+
+	if (-1 == *gain_index) {
+		*gain_index = 0;
+		while ((*gain_index <= (s32) max_index)
+		       && (received_power < 700)) {
+			wlc_lcnphy_set_rx_gain(pi,
+					       lcnphy_23bitgaincode_table
+					       [*gain_index]);
+			received_power =
+			    wlc_lcnphy_measure_digital_power(pi,
+							     pi_lcn->
+							     lcnphy_noise_samples);
+			(*gain_index)++;
+		}
+		(*gain_index)--;
+	} else {
+		wlc_lcnphy_set_rx_gain(pi, gain_code);
+		received_power =
+		    wlc_lcnphy_measure_digital_power(pi,
+						     pi_lcn->
+						     lcnphy_noise_samples);
+	}
+
+	return received_power;
+}
+
+s32 wlc_lcnphy_rx_signal_power(phy_info_t *pi, s32 gain_index)
+{
+	s32 gain = 0;
+	s32 nominal_power_db;
+	s32 log_val, gain_mismatch, desired_gain, input_power_offset_db,
+	    input_power_db;
+	s32 received_power, temperature;
+	uint freq;
+	phy_info_lcnphy_t *pi_lcn = pi->u.pi_lcnphy;
+
+	received_power = wlc_lcnphy_get_receive_power(pi, &gain_index);
+
+	gain = lcnphy_gain_table[gain_index];
+
+	nominal_power_db = read_phy_reg(pi, 0x425) >> 8;
+
+	{
+		u32 power = (received_power * 16);
+		u32 msb1, msb2, val1, val2, diff1, diff2;
+		msb1 = ffs(power) - 1;
+		msb2 = msb1 + 1;
+		val1 = 1 << msb1;
+		val2 = 1 << msb2;
+		diff1 = (power - val1);
+		diff2 = (val2 - power);
+		if (diff1 < diff2)
+			log_val = msb1;
+		else
+			log_val = msb2;
+	}
+
+	log_val = log_val * 3;
+
+	gain_mismatch = (nominal_power_db / 2) - (log_val);
+
+	desired_gain = gain + gain_mismatch;
+
+	input_power_offset_db = read_phy_reg(pi, 0x434) & 0xFF;
+
+	if (input_power_offset_db > 127)
+		input_power_offset_db -= 256;
+
+	input_power_db = input_power_offset_db - desired_gain;
+
+	input_power_db =
+	    input_power_db + lcnphy_gain_index_offset_for_rssi[gain_index];
+
+	freq = wlc_phy_channel2freq(CHSPEC_CHANNEL(pi->radio_chanspec));
+	if ((freq > 2427) && (freq <= 2467))
+		input_power_db = input_power_db - 1;
+
+	temperature = pi_lcn->lcnphy_lastsensed_temperature;
+
+	if ((temperature - 15) < -30) {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
+		    7;
+	} else if ((temperature - 15) < 4) {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12) -
+		    3;
+	} else {
+		input_power_db =
+		    input_power_db + (((temperature - 10 - 25) * 286) >> 12);
+	}
+
+	wlc_lcnphy_rx_gain_override_enable(pi, 0);
+
+	return input_power_db;
+}
+
+static int
+wlc_lcnphy_load_tx_iir_filter(phy_info_t *pi, bool is_ofdm, s16 filt_type)
+{
+	s16 filt_index = -1;
+	int j;
+
+	u16 addr[] = {
+		0x910,
+		0x91e,
+		0x91f,
+		0x924,
+		0x925,
+		0x926,
+		0x920,
+		0x921,
+		0x927,
+		0x928,
+		0x929,
+		0x922,
+		0x923,
+		0x930,
+		0x931,
+		0x932
+	};
+
+	u16 addr_ofdm[] = {
+		0x90f,
+		0x900,
+		0x901,
+		0x906,
+		0x907,
+		0x908,
+		0x902,
+		0x903,
+		0x909,
+		0x90a,
+		0x90b,
+		0x904,
+		0x905,
+		0x90c,
+		0x90d,
+		0x90e
+	};
+
+	if (!is_ofdm) {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_CCK; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_cck[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index == -1) {
+			ASSERT(false);
+		} else {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, addr[j],
+					      LCNPHY_txdigfiltcoeffs_cck
+					      [filt_index][j + 1]);
+			}
+		}
+	} else {
+		for (j = 0; j < LCNPHY_NUM_TX_DIG_FILTERS_OFDM; j++) {
+			if (filt_type == LCNPHY_txdigfiltcoeffs_ofdm[j][0]) {
+				filt_index = (s16) j;
+				break;
+			}
+		}
+
+		if (filt_index == -1) {
+			ASSERT(false);
+		} else {
+			for (j = 0; j < LCNPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, addr_ofdm[j],
+					      LCNPHY_txdigfiltcoeffs_ofdm
+					      [filt_index][j + 1]);
+			}
+		}
+	}
+
+	return (filt_index != -1) ? 0 : -1;
+}
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_lcn.h	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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 _wlc_phy_lcn_h_
+#define _wlc_phy_lcn_h_
+
+struct phy_info_lcnphy {
+	int lcnphy_txrf_sp_9_override;
+	u8 lcnphy_full_cal_channel;
+	u8 lcnphy_cal_counter;
+	u16 lcnphy_cal_temper;
+	bool lcnphy_recal;
+
+	u8 lcnphy_rc_cap;
+	u32 lcnphy_mcs20_po;
+
+	u8 lcnphy_tr_isolation_mid;
+	u8 lcnphy_tr_isolation_low;
+	u8 lcnphy_tr_isolation_hi;
+
+	u8 lcnphy_bx_arch;
+	u8 lcnphy_rx_power_offset;
+	u8 lcnphy_rssi_vf;
+	u8 lcnphy_rssi_vc;
+	u8 lcnphy_rssi_gs;
+	u8 lcnphy_tssi_val;
+	u8 lcnphy_rssi_vf_lowtemp;
+	u8 lcnphy_rssi_vc_lowtemp;
+	u8 lcnphy_rssi_gs_lowtemp;
+
+	u8 lcnphy_rssi_vf_hightemp;
+	u8 lcnphy_rssi_vc_hightemp;
+	u8 lcnphy_rssi_gs_hightemp;
+
+	s16 lcnphy_pa0b0;
+	s16 lcnphy_pa0b1;
+	s16 lcnphy_pa0b2;
+
+	u16 lcnphy_rawtempsense;
+	u8 lcnphy_measPower;
+	u8 lcnphy_tempsense_slope;
+	u8 lcnphy_freqoffset_corr;
+	u8 lcnphy_tempsense_option;
+	u8 lcnphy_tempcorrx;
+	bool lcnphy_iqcal_swp_dis;
+	bool lcnphy_hw_iqcal_en;
+	uint lcnphy_bandedge_corr;
+	bool lcnphy_spurmod;
+	u16 lcnphy_tssi_tx_cnt;
+	u16 lcnphy_tssi_idx;
+	u16 lcnphy_tssi_npt;
+
+	u16 lcnphy_target_tx_freq;
+	s8 lcnphy_tx_power_idx_override;
+	u16 lcnphy_noise_samples;
+
+	u32 lcnphy_papdRxGnIdx;
+	u32 lcnphy_papd_rxGnCtrl_init;
+
+	u32 lcnphy_gain_idx_14_lowword;
+	u32 lcnphy_gain_idx_14_hiword;
+	u32 lcnphy_gain_idx_27_lowword;
+	u32 lcnphy_gain_idx_27_hiword;
+	s16 lcnphy_ofdmgainidxtableoffset;
+	s16 lcnphy_dsssgainidxtableoffset;
+	u32 lcnphy_tr_R_gain_val;
+	u32 lcnphy_tr_T_gain_val;
+	s8 lcnphy_input_pwr_offset_db;
+	u16 lcnphy_Med_Low_Gain_db;
+	u16 lcnphy_Very_Low_Gain_db;
+	s8 lcnphy_lastsensed_temperature;
+	s8 lcnphy_pkteng_rssi_slope;
+	u8 lcnphy_saved_tx_user_target[TXP_NUM_RATES];
+	u8 lcnphy_volt_winner;
+	u8 lcnphy_volt_low;
+	u8 lcnphy_54_48_36_24mbps_backoff;
+	u8 lcnphy_11n_backoff;
+	u8 lcnphy_lowerofdm;
+	u8 lcnphy_cck;
+	u8 lcnphy_psat_2pt3_detected;
+	s32 lcnphy_lowest_Re_div_Im;
+	s8 lcnphy_final_papd_cal_idx;
+	u16 lcnphy_extstxctrl4;
+	u16 lcnphy_extstxctrl0;
+	u16 lcnphy_extstxctrl1;
+	s16 lcnphy_cck_dig_filt_type;
+	s16 lcnphy_ofdm_dig_filt_type;
+	lcnphy_cal_results_t lcnphy_cal_results;
+
+	u8 lcnphy_psat_pwr;
+	u8 lcnphy_psat_indx;
+	s32 lcnphy_min_phase;
+	u8 lcnphy_final_idx;
+	u8 lcnphy_start_idx;
+	u8 lcnphy_current_index;
+	u16 lcnphy_logen_buf_1;
+	u16 lcnphy_local_ovr_2;
+	u16 lcnphy_local_oval_6;
+	u16 lcnphy_local_oval_5;
+	u16 lcnphy_logen_mixer_1;
+
+	u8 lcnphy_aci_stat;
+	uint lcnphy_aci_start_time;
+	s8 lcnphy_tx_power_offset[TXP_NUM_RATES];
+};
+#endif				/* _wlc_phy_lcn_h_ */
diff -druN linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c
--- linux-libre-2.6.38-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c	1969-12-31 19:00:00.000000000 -0500
+++ linux-libre-2.6.39-gnu/drivers/staging/brcm80211/brcmsmac/phy/wlc_phy_n.c	2011-05-19 00:06:34.000000000 -0400
@@ -0,0 +1,29234 @@
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ *
+ * 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/string.h>
+#include <bcmdefs.h>
+#include <wlc_cfg.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <siutils.h>
+#include <sbchipc.h>
+#include <hndpmu.h>
+
+#include <bcmdevs.h>
+#include <sbhnddma.h>
+
+#include <wlc_phy_radio.h>
+#include <wlc_phy_int.h>
+#include <wlc_phyreg_n.h>
+#include <wlc_phytbl_n.h>
+
+#define	READ_RADIO_REG2(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1))
+#define	WRITE_RADIO_REG2(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##jspace##_##reg_name | \
+	((core == PHY_CORE_0) ? radio_type##_##jspace##0 : radio_type##_##jspace##1), value);
+#define	WRITE_RADIO_SYN(pi, radio_type, reg_name, value) \
+	write_radio_reg(pi, radio_type##_##SYN##_##reg_name, value);
+
+#define	READ_RADIO_REG3(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
+	radio_type##_##jspace##1##_##reg_name));
+#define	WRITE_RADIO_REG3(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##jspace##0##_##reg_name : \
+	radio_type##_##jspace##1##_##reg_name), value);
+#define	READ_RADIO_REG4(pi, radio_type, jspace, core, reg_name) \
+	read_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
+	radio_type##_##reg_name##_##jspace##1));
+#define	WRITE_RADIO_REG4(pi, radio_type, jspace, core, reg_name, value) \
+	write_radio_reg(pi, ((core == PHY_CORE_0) ? radio_type##_##reg_name##_##jspace##0 : \
+	radio_type##_##reg_name##_##jspace##1), value);
+
+#define NPHY_ACI_MAX_UNDETECT_WINDOW_SZ 40
+#define NPHY_ACI_CHANNEL_DELTA 5
+#define NPHY_ACI_CHANNEL_SKIP 4
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP 5
+#define NPHY_ACI_40MHZ_CHANNEL_DELTA_GE_REV3 6
+#define NPHY_ACI_40MHZ_CHANNEL_SKIP_GE_REV3 5
+#define NPHY_ACI_CHANNEL_DELTA_GE_REV3 4
+#define NPHY_ACI_CHANNEL_SKIP_GE_REV3 3
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_NOASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_UP 2
+
+#define NPHY_NOISE_ASSOC_ACI_GLITCH_TH_DN 8
+
+#define NPHY_NOISE_NOASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_ENTER_TH  400
+
+#define NPHY_NOISE_ASSOC_RX_GLITCH_BADPLCP_ENTER_TH  400
+
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX 44
+#define NPHY_NOISE_CRSMINPWR_ARRAY_MAX_INDEX_REV_7 56
+
+#define NPHY_NOISE_NOASSOC_CRSIDX_INCR 16
+
+#define NPHY_NOISE_ASSOC_CRSIDX_INCR 8
+
+#define NPHY_IS_SROM_REINTERPRET NREV_GE(pi->pubpi.phy_rev, 5)
+
+#define NPHY_RSSICAL_MAXREAD 31
+
+#define NPHY_RSSICAL_NPOLL 8
+#define NPHY_RSSICAL_MAXD  (1<<20)
+#define NPHY_MIN_RXIQ_PWR 2
+
+#define NPHY_RSSICAL_W1_TARGET 25
+#define NPHY_RSSICAL_W2_TARGET NPHY_RSSICAL_W1_TARGET
+#define NPHY_RSSICAL_NB_TARGET 0
+
+#define NPHY_RSSICAL_W1_TARGET_REV3 29
+#define NPHY_RSSICAL_W2_TARGET_REV3 NPHY_RSSICAL_W1_TARGET_REV3
+
+#define NPHY_CALSANITY_RSSI_NB_MAX_POS  9
+#define NPHY_CALSANITY_RSSI_NB_MAX_NEG -9
+#define NPHY_CALSANITY_RSSI_W1_MAX_POS  12
+#define NPHY_CALSANITY_RSSI_W1_MAX_NEG (NPHY_RSSICAL_W1_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_CALSANITY_RSSI_W2_MAX_POS  NPHY_CALSANITY_RSSI_W1_MAX_POS
+#define NPHY_CALSANITY_RSSI_W2_MAX_NEG (NPHY_RSSICAL_W2_TARGET - NPHY_RSSICAL_MAXREAD)
+#define NPHY_RSSI_SXT(x) ((s8) (-((x) & 0x20) + ((x) & 0x1f)))
+#define NPHY_RSSI_NB_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_NB_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_NB_MAX_NEG))
+#define NPHY_RSSI_W1_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W1_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W1_MAX_NEG))
+#define NPHY_RSSI_W2_VIOL(x)  (((x) > NPHY_CALSANITY_RSSI_W2_MAX_POS) || \
+			       ((x) < NPHY_CALSANITY_RSSI_W2_MAX_NEG))
+
+#define NPHY_IQCAL_NUMGAINS 9
+#define NPHY_N_GCTL 0x66
+
+#define NPHY_PAPD_EPS_TBL_SIZE 64
+#define NPHY_PAPD_SCL_TBL_SIZE 64
+#define NPHY_NUM_DIG_FILT_COEFFS 15
+
+#define NPHY_PAPD_COMP_OFF 0
+#define NPHY_PAPD_COMP_ON  1
+
+#define NPHY_SROM_TEMPSHIFT		32
+#define NPHY_SROM_MAXTEMPOFFSET		16
+#define NPHY_SROM_MINTEMPOFFSET		-16
+
+#define NPHY_CAL_MAXTEMPDELTA		64
+
+#define NPHY_NOISEVAR_TBLLEN40 256
+#define NPHY_NOISEVAR_TBLLEN20 128
+
+#define NPHY_ANARXLPFBW_REDUCTIONFACT 7
+
+#define NPHY_ADJUSTED_MINCRSPOWER 0x1e
+
+typedef struct _nphy_iqcal_params {
+	u16 txlpf;
+	u16 txgm;
+	u16 pga;
+	u16 pad;
+	u16 ipa;
+	u16 cal_gain;
+	u16 ncorr[5];
+} nphy_iqcal_params_t;
+
+typedef struct _nphy_txiqcal_ladder {
+	u8 percent;
+	u8 g_env;
+} nphy_txiqcal_ladder_t;
+
+typedef struct {
+	nphy_txgains_t gains;
+	bool useindex;
+	u8 index;
+} nphy_ipa_txcalgains_t;
+
+typedef struct nphy_papd_restore_state_t {
+	u16 fbmix[2];
+	u16 vga_master[2];
+	u16 intpa_master[2];
+	u16 afectrl[2];
+	u16 afeoverride[2];
+	u16 pwrup[2];
+	u16 atten[2];
+	u16 mm;
+} nphy_papd_restore_state;
+
+typedef struct _nphy_ipa_txrxgain {
+	u16 hpvga;
+	u16 lpf_biq1;
+	u16 lpf_biq0;
+	u16 lna2;
+	u16 lna1;
+	s8 txpwrindex;
+} nphy_ipa_txrxgain_t;
+
+#define NPHY_IPA_RXCAL_MAXGAININDEX (6 - 1)
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz[] = { {0, 0, 0, 0, 0, 100},
+{0, 0, 0, 0, 0, 50},
+{0, 0, 0, 0, 0, -1},
+{0, 0, 0, 3, 0, -1},
+{0, 0, 3, 3, 0, -1},
+{0, 2, 3, 3, 0, -1}
+};
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz[] = { {0, 0, 0, 0, 0, 128},
+{0, 0, 0, 0, 0, 70},
+{0, 0, 0, 0, 0, 20},
+{0, 0, 0, 3, 0, 20},
+{0, 0, 3, 3, 0, 20},
+{0, 2, 3, 3, 0, 20}
+};
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_5GHz_rev7[] = { {0, 0, 0, 0, 0, 100},
+{0, 0, 0, 0, 0, 50},
+{0, 0, 0, 0, 0, -1},
+{0, 0, 0, 3, 0, -1},
+{0, 0, 3, 3, 0, -1},
+{0, 0, 5, 3, 0, -1}
+};
+
+nphy_ipa_txrxgain_t nphy_ipa_rxcal_gaintbl_2GHz_rev7[] = { {0, 0, 0, 0, 0, 10},
+{0, 0, 0, 1, 0, 10},
+{0, 0, 1, 2, 0, 10},
+{0, 0, 1, 3, 0, 10},
+{0, 0, 4, 3, 0, 10},
+{0, 0, 6, 3, 0, 10}
+};
+
+#define NPHY_RXCAL_TONEAMP 181
+#define NPHY_RXCAL_TONEFREQ_40MHz 4000
+#define NPHY_RXCAL_TONEFREQ_20MHz 2000
+
+enum {
+	NPHY_RXCAL_GAIN_INIT = 0,
+	NPHY_RXCAL_GAIN_UP,
+	NPHY_RXCAL_GAIN_DOWN
+};
+
+#define wlc_phy_get_papd_nphy(pi) \
+	(read_phy_reg((pi), 0x1e7) & \
+			((0x1 << 15) | \
+			(0x1 << 14) | \
+			(0x1 << 13)))
+
+#define TXFILT_SHAPING_OFDM20   0
+#define TXFILT_SHAPING_OFDM40   1
+#define TXFILT_SHAPING_CCK      2
+#define TXFILT_DEFAULT_OFDM20   3
+#define TXFILT_DEFAULT_OFDM40   4
+
+u16 NPHY_IPA_REV4_txdigi_filtcoeffs[][NPHY_NUM_DIG_FILT_COEFFS] = {
+	{-377, 137, -407, 208, -1527, 956, 93, 186, 93,
+	 230, -44, 230, 201, -191, 201},
+	{-77, 20, -98, 49, -93, 60, 56, 111, 56, 26, -5,
+	 26, 34, -32, 34},
+	{-360, 164, -376, 164, -1533, 576, 308, -314, 308,
+	 121, -73, 121, 91, 124, 91},
+	{-295, 200, -363, 142, -1391, 826, 151, 301, 151,
+	 151, 301, 151, 602, -752, 602},
+	{-92, 58, -96, 49, -104, 44, 17, 35, 17,
+	 12, 25, 12, 13, 27, 13},
+	{-375, 136, -399, 209, -1479, 949, 130, 260, 130,
+	 230, -44, 230, 201, -191, 201},
+	{0xed9, 0xc8, 0xe95, 0x8e, 0xa91, 0x33a, 0x97, 0x12d, 0x97,
+	 0x97, 0x12d, 0x97, 0x25a, 0xd10, 0x25a}
+};
+
+typedef struct _chan_info_nphy_2055 {
+	u16 chan;
+	u16 freq;
+	uint unknown;
+	u8 RF_pll_ref;
+	u8 RF_rf_pll_mod1;
+	u8 RF_rf_pll_mod0;
+	u8 RF_vco_cap_tail;
+	u8 RF_vco_cal1;
+	u8 RF_vco_cal2;
+	u8 RF_pll_lf_c1;
+	u8 RF_pll_lf_r1;
+	u8 RF_pll_lf_c2;
+	u8 RF_lgbuf_cen_buf;
+	u8 RF_lgen_tune1;
+	u8 RF_lgen_tune2;
+	u8 RF_core1_lgbuf_a_tune;
+	u8 RF_core1_lgbuf_g_tune;
+	u8 RF_core1_rxrf_reg1;
+	u8 RF_core1_tx_pga_pad_tn;
+	u8 RF_core1_tx_mx_bgtrim;
+	u8 RF_core2_lgbuf_a_tune;
+	u8 RF_core2_lgbuf_g_tune;
+	u8 RF_core2_rxrf_reg1;
+	u8 RF_core2_tx_pga_pad_tn;
+	u8 RF_core2_tx_mx_bgtrim;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_2055_t;
+
+typedef struct _chan_info_nphy_radio205x {
+	u16 chan;
+	u16 freq;
+	u8 RF_SYN_pll_vcocal1;
+	u8 RF_SYN_pll_vcocal2;
+	u8 RF_SYN_pll_refdiv;
+	u8 RF_SYN_pll_mmd2;
+	u8 RF_SYN_pll_mmd1;
+	u8 RF_SYN_pll_loopfilter1;
+	u8 RF_SYN_pll_loopfilter2;
+	u8 RF_SYN_pll_loopfilter3;
+	u8 RF_SYN_pll_loopfilter4;
+	u8 RF_SYN_pll_loopfilter5;
+	u8 RF_SYN_reserved_addr27;
+	u8 RF_SYN_reserved_addr28;
+	u8 RF_SYN_reserved_addr29;
+	u8 RF_SYN_logen_VCOBUF1;
+	u8 RF_SYN_logen_MIXER2;
+	u8 RF_SYN_logen_BUF3;
+	u8 RF_SYN_logen_BUF4;
+	u8 RF_RX0_lnaa_tune;
+	u8 RF_RX0_lnag_tune;
+	u8 RF_TX0_intpaa_boost_tune;
+	u8 RF_TX0_intpag_boost_tune;
+	u8 RF_TX0_pada_boost_tune;
+	u8 RF_TX0_padg_boost_tune;
+	u8 RF_TX0_pgaa_boost_tune;
+	u8 RF_TX0_pgag_boost_tune;
+	u8 RF_TX0_mixa_boost_tune;
+	u8 RF_TX0_mixg_boost_tune;
+	u8 RF_RX1_lnaa_tune;
+	u8 RF_RX1_lnag_tune;
+	u8 RF_TX1_intpaa_boost_tune;
+	u8 RF_TX1_intpag_boost_tune;
+	u8 RF_TX1_pada_boost_tune;
+	u8 RF_TX1_padg_boost_tune;
+	u8 RF_TX1_pgaa_boost_tune;
+	u8 RF_TX1_pgag_boost_tune;
+	u8 RF_TX1_mixa_boost_tune;
+	u8 RF_TX1_mixg_boost_tune;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_radio205x_t;
+
+typedef struct _chan_info_nphy_radio2057 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_mx5g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_logen_indbuf5g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_pga_boost_tune_core0;
+	u8 RF_txmix5g_boost_tune_core0;
+	u8 RF_pad5g_tune_misc_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_lna5g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_pga_boost_tune_core1;
+	u8 RF_txmix5g_boost_tune_core1;
+	u8 RF_pad5g_tune_misc_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u8 RF_lna5g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_radio2057_t;
+
+typedef struct _chan_info_nphy_radio2057_rev5 {
+	u16 chan;
+	u16 freq;
+	u8 RF_vcocal_countval0;
+	u8 RF_vcocal_countval1;
+	u8 RF_rfpll_refmaster_sparextalsize;
+	u8 RF_rfpll_loopfilter_r1;
+	u8 RF_rfpll_loopfilter_c2;
+	u8 RF_rfpll_loopfilter_c1;
+	u8 RF_cp_kpd_idac;
+	u8 RF_rfpll_mmd0;
+	u8 RF_rfpll_mmd1;
+	u8 RF_vcobuf_tune;
+	u8 RF_logen_mx2g_tune;
+	u8 RF_logen_indbuf2g_tune;
+	u8 RF_txmix2g_tune_boost_pu_core0;
+	u8 RF_pad2g_tune_pus_core0;
+	u8 RF_lna2g_tune_core0;
+	u8 RF_txmix2g_tune_boost_pu_core1;
+	u8 RF_pad2g_tune_pus_core1;
+	u8 RF_lna2g_tune_core1;
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} chan_info_nphy_radio2057_rev5_t;
+
+typedef struct nphy_sfo_cfg {
+	u16 PHY_BW1a;
+	u16 PHY_BW2;
+	u16 PHY_BW3;
+	u16 PHY_BW4;
+	u16 PHY_BW5;
+	u16 PHY_BW6;
+} nphy_sfo_cfg_t;
+
+static chan_info_nphy_2055_t chan_info_nphy_2055[] = {
+	{
+	 184, 4920, 3280, 0x71, 0x01, 0xEC, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B4, 0x7B0, 0x7AC, 0x214, 0x215, 0x216},
+	{
+	 186, 4930, 3287, 0x71, 0x01, 0xED, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xFF, 0xFF, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7B8, 0x7B4, 0x7B0, 0x213, 0x214, 0x215},
+	{
+	 188, 4940, 3293, 0x71, 0x01, 0xEE, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7BC, 0x7B8, 0x7B4, 0x212, 0x213, 0x214},
+	{
+	 190, 4950, 3300, 0x71, 0x01, 0xEF, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C0, 0x7BC, 0x7B8, 0x211, 0x212, 0x213},
+	{
+	 192, 4960, 3307, 0x71, 0x01, 0xF0, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C4, 0x7C0, 0x7BC, 0x20F, 0x211, 0x212},
+	{
+	 194, 4970, 3313, 0x71, 0x01, 0xF1, 0x0F, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xEE, 0xEE, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7C8, 0x7C4, 0x7C0, 0x20E, 0x20F, 0x211},
+	{
+	 196, 4980, 3320, 0x71, 0x01, 0xF2, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7CC, 0x7C8, 0x7C4, 0x20D, 0x20E, 0x20F},
+	{
+	 198, 4990, 3327, 0x71, 0x01, 0xF3, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D0, 0x7CC, 0x7C8, 0x20C, 0x20D, 0x20E},
+	{
+	 200, 5000, 3333, 0x71, 0x01, 0xF4, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D4, 0x7D0, 0x7CC, 0x20B, 0x20C, 0x20D},
+	{
+	 202, 5010, 3340, 0x71, 0x01, 0xF5, 0x0E, 0xFF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xDD, 0xDD, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7D8, 0x7D4, 0x7D0, 0x20A, 0x20B, 0x20C},
+	{
+	 204, 5020, 3347, 0x71, 0x01, 0xF6, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7DC, 0x7D8, 0x7D4, 0x209, 0x20A, 0x20B},
+	{
+	 206, 5030, 3353, 0x71, 0x01, 0xF7, 0x0E, 0xF7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E0, 0x7DC, 0x7D8, 0x208, 0x209, 0x20A},
+	{
+	 208, 5040, 3360, 0x71, 0x01, 0xF8, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E4, 0x7E0, 0x7DC, 0x207, 0x208, 0x209},
+	{
+	 210, 5050, 3367, 0x71, 0x01, 0xF9, 0x0D, 0xEF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xCC, 0xCC, 0xFF, 0x00, 0x0F, 0x0F, 0x8F, 0xFF, 0x00, 0x0F,
+	 0x0F, 0x8F, 0x7E8, 0x7E4, 0x7E0, 0x206, 0x207, 0x208},
+	{
+	 212, 5060, 3373, 0x71, 0x01, 0xFA, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7EC, 0x7E8, 0x7E4, 0x205, 0x206, 0x207},
+	{
+	 214, 5070, 3380, 0x71, 0x01, 0xFB, 0x0D, 0xE6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8F, 0xBB, 0xBB, 0xFF, 0x00, 0x0E, 0x0F, 0x8E, 0xFF, 0x00, 0x0E,
+	 0x0F, 0x8E, 0x7F0, 0x7EC, 0x7E8, 0x204, 0x205, 0x206},
+	{
+	 216, 5080, 3387, 0x71, 0x01, 0xFC, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F4, 0x7F0, 0x7EC, 0x203, 0x204, 0x205},
+	{
+	 218, 5090, 3393, 0x71, 0x01, 0xFD, 0x0D, 0xDE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xBB, 0xBB, 0xEE, 0x00, 0x0E, 0x0F, 0x8D, 0xEE, 0x00, 0x0E,
+	 0x0F, 0x8D, 0x7F8, 0x7F4, 0x7F0, 0x202, 0x203, 0x204},
+	{
+	 220, 5100, 3400, 0x71, 0x01, 0xFE, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x7FC, 0x7F8, 0x7F4, 0x201, 0x202, 0x203},
+	{
+	 222, 5110, 3407, 0x71, 0x01, 0xFF, 0x0C, 0xD6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8E, 0xAA, 0xAA, 0xEE, 0x00, 0x0D, 0x0F, 0x8D, 0xEE, 0x00, 0x0D,
+	 0x0F, 0x8D, 0x800, 0x7FC, 0x7F8, 0x200, 0x201, 0x202},
+	{
+	 224, 5120, 3413, 0x71, 0x02, 0x00, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x804, 0x800, 0x7FC, 0x1FF, 0x200, 0x201},
+	{
+	 226, 5130, 3420, 0x71, 0x02, 0x01, 0x0C, 0xCE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0xAA, 0xAA, 0xDD, 0x00, 0x0D, 0x0F, 0x8C, 0xDD, 0x00, 0x0D,
+	 0x0F, 0x8C, 0x808, 0x804, 0x800, 0x1FE, 0x1FF, 0x200},
+	{
+	 228, 5140, 3427, 0x71, 0x02, 0x02, 0x0C, 0xC6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8D, 0x99, 0x99, 0xDD, 0x00, 0x0C, 0x0E, 0x8B, 0xDD, 0x00, 0x0C,
+	 0x0E, 0x8B, 0x80C, 0x808, 0x804, 0x1FD, 0x1FE, 0x1FF},
+	{
+	 32, 5160, 3440, 0x71, 0x02, 0x04, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x814, 0x810, 0x80C, 0x1FB, 0x1FC, 0x1FD},
+	{
+	 34, 5170, 3447, 0x71, 0x02, 0x05, 0x0B, 0xBE, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x99, 0x99, 0xCC, 0x00, 0x0B, 0x0D, 0x8A, 0xCC, 0x00, 0x0B,
+	 0x0D, 0x8A, 0x818, 0x814, 0x810, 0x1FA, 0x1FB, 0x1FC},
+	{
+	 36, 5180, 3453, 0x71, 0x02, 0x06, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x81C, 0x818, 0x814, 0x1F9, 0x1FA, 0x1FB},
+	{
+	 38, 5190, 3460, 0x71, 0x02, 0x07, 0x0B, 0xB6, 0x01, 0x04, 0x0A,
+	 0x00, 0x8C, 0x88, 0x88, 0xCC, 0x00, 0x0B, 0x0C, 0x89, 0xCC, 0x00, 0x0B,
+	 0x0C, 0x89, 0x820, 0x81C, 0x818, 0x1F8, 0x1F9, 0x1FA},
+	{
+	 40, 5200, 3467, 0x71, 0x02, 0x08, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x824, 0x820, 0x81C, 0x1F7, 0x1F8, 0x1F9},
+	{
+	 42, 5210, 3473, 0x71, 0x02, 0x09, 0x0B, 0xAF, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x88, 0x88, 0xBB, 0x00, 0x0A, 0x0B, 0x89, 0xBB, 0x00, 0x0A,
+	 0x0B, 0x89, 0x828, 0x824, 0x820, 0x1F6, 0x1F7, 0x1F8},
+	{
+	 44, 5220, 3480, 0x71, 0x02, 0x0A, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x82C, 0x828, 0x824, 0x1F5, 0x1F6, 0x1F7},
+	{
+	 46, 5230, 3487, 0x71, 0x02, 0x0B, 0x0A, 0xA7, 0x01, 0x04, 0x0A,
+	 0x00, 0x8B, 0x77, 0x77, 0xBB, 0x00, 0x09, 0x0A, 0x88, 0xBB, 0x00, 0x09,
+	 0x0A, 0x88, 0x830, 0x82C, 0x828, 0x1F4, 0x1F5, 0x1F6},
+	{
+	 48, 5240, 3493, 0x71, 0x02, 0x0C, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x834, 0x830, 0x82C, 0x1F3, 0x1F4, 0x1F5},
+	{
+	 50, 5250, 3500, 0x71, 0x02, 0x0D, 0x0A, 0xA0, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x77, 0x77, 0xAA, 0x00, 0x09, 0x0A, 0x87, 0xAA, 0x00, 0x09,
+	 0x0A, 0x87, 0x838, 0x834, 0x830, 0x1F2, 0x1F3, 0x1F4},
+	{
+	 52, 5260, 3507, 0x71, 0x02, 0x0E, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x83C, 0x838, 0x834, 0x1F1, 0x1F2, 0x1F3},
+	{
+	 54, 5270, 3513, 0x71, 0x02, 0x0F, 0x0A, 0x98, 0x01, 0x04, 0x0A,
+	 0x00, 0x8A, 0x66, 0x66, 0xAA, 0x00, 0x08, 0x09, 0x87, 0xAA, 0x00, 0x08,
+	 0x09, 0x87, 0x840, 0x83C, 0x838, 0x1F0, 0x1F1, 0x1F2},
+	{
+	 56, 5280, 3520, 0x71, 0x02, 0x10, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x844, 0x840, 0x83C, 0x1F0, 0x1F0, 0x1F1},
+	{
+	 58, 5290, 3527, 0x71, 0x02, 0x11, 0x09, 0x91, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x66, 0x66, 0x99, 0x00, 0x08, 0x08, 0x86, 0x99, 0x00, 0x08,
+	 0x08, 0x86, 0x848, 0x844, 0x840, 0x1EF, 0x1F0, 0x1F0},
+	{
+	 60, 5300, 3533, 0x71, 0x02, 0x12, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x84C, 0x848, 0x844, 0x1EE, 0x1EF, 0x1F0},
+	{
+	 62, 5310, 3540, 0x71, 0x02, 0x13, 0x09, 0x8A, 0x01, 0x04, 0x0A,
+	 0x00, 0x89, 0x55, 0x55, 0x99, 0x00, 0x08, 0x07, 0x85, 0x99, 0x00, 0x08,
+	 0x07, 0x85, 0x850, 0x84C, 0x848, 0x1ED, 0x1EE, 0x1EF},
+	{
+	 64, 5320, 3547, 0x71, 0x02, 0x14, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x854, 0x850, 0x84C, 0x1EC, 0x1ED, 0x1EE},
+	{
+	 66, 5330, 3553, 0x71, 0x02, 0x15, 0x09, 0x83, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x55, 0x55, 0x88, 0x00, 0x07, 0x07, 0x84, 0x88, 0x00, 0x07,
+	 0x07, 0x84, 0x858, 0x854, 0x850, 0x1EB, 0x1EC, 0x1ED},
+	{
+	 68, 5340, 3560, 0x71, 0x02, 0x16, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x85C, 0x858, 0x854, 0x1EA, 0x1EB, 0x1EC},
+	{
+	 70, 5350, 3567, 0x71, 0x02, 0x17, 0x08, 0x7C, 0x01, 0x04, 0x0A,
+	 0x00, 0x88, 0x44, 0x44, 0x88, 0x00, 0x07, 0x06, 0x84, 0x88, 0x00, 0x07,
+	 0x06, 0x84, 0x860, 0x85C, 0x858, 0x1E9, 0x1EA, 0x1EB},
+	{
+	 72, 5360, 3573, 0x71, 0x02, 0x18, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x864, 0x860, 0x85C, 0x1E8, 0x1E9, 0x1EA},
+	{
+	 74, 5370, 3580, 0x71, 0x02, 0x19, 0x08, 0x75, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x44, 0x44, 0x77, 0x00, 0x06, 0x05, 0x83, 0x77, 0x00, 0x06,
+	 0x05, 0x83, 0x868, 0x864, 0x860, 0x1E7, 0x1E8, 0x1E9},
+	{
+	 76, 5380, 3587, 0x71, 0x02, 0x1A, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x86C, 0x868, 0x864, 0x1E6, 0x1E7, 0x1E8},
+	{
+	 78, 5390, 3593, 0x71, 0x02, 0x1B, 0x08, 0x6E, 0x01, 0x04, 0x0A,
+	 0x00, 0x87, 0x33, 0x33, 0x77, 0x00, 0x06, 0x04, 0x82, 0x77, 0x00, 0x06,
+	 0x04, 0x82, 0x870, 0x86C, 0x868, 0x1E5, 0x1E6, 0x1E7},
+	{
+	 80, 5400, 3600, 0x71, 0x02, 0x1C, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x874, 0x870, 0x86C, 0x1E5, 0x1E5, 0x1E6},
+	{
+	 82, 5410, 3607, 0x71, 0x02, 0x1D, 0x07, 0x67, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x33, 0x33, 0x66, 0x00, 0x05, 0x04, 0x81, 0x66, 0x00, 0x05,
+	 0x04, 0x81, 0x878, 0x874, 0x870, 0x1E4, 0x1E5, 0x1E5},
+	{
+	 84, 5420, 3613, 0x71, 0x02, 0x1E, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x87C, 0x878, 0x874, 0x1E3, 0x1E4, 0x1E5},
+	{
+	 86, 5430, 3620, 0x71, 0x02, 0x1F, 0x07, 0x61, 0x01, 0x04, 0x0A,
+	 0x00, 0x86, 0x22, 0x22, 0x66, 0x00, 0x05, 0x03, 0x80, 0x66, 0x00, 0x05,
+	 0x03, 0x80, 0x880, 0x87C, 0x878, 0x1E2, 0x1E3, 0x1E4},
+	{
+	 88, 5440, 3627, 0x71, 0x02, 0x20, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x884, 0x880, 0x87C, 0x1E1, 0x1E2, 0x1E3},
+	{
+	 90, 5450, 3633, 0x71, 0x02, 0x21, 0x07, 0x5A, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x22, 0x22, 0x55, 0x00, 0x04, 0x02, 0x80, 0x55, 0x00, 0x04,
+	 0x02, 0x80, 0x888, 0x884, 0x880, 0x1E0, 0x1E1, 0x1E2},
+	{
+	 92, 5460, 3640, 0x71, 0x02, 0x22, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x88C, 0x888, 0x884, 0x1DF, 0x1E0, 0x1E1},
+	{
+	 94, 5470, 3647, 0x71, 0x02, 0x23, 0x06, 0x53, 0x01, 0x04, 0x0A,
+	 0x00, 0x85, 0x11, 0x11, 0x55, 0x00, 0x04, 0x01, 0x80, 0x55, 0x00, 0x04,
+	 0x01, 0x80, 0x890, 0x88C, 0x888, 0x1DE, 0x1DF, 0x1E0},
+	{
+	 96, 5480, 3653, 0x71, 0x02, 0x24, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x894, 0x890, 0x88C, 0x1DD, 0x1DE, 0x1DF},
+	{
+	 98, 5490, 3660, 0x71, 0x02, 0x25, 0x06, 0x4D, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x11, 0x11, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x898, 0x894, 0x890, 0x1DD, 0x1DD, 0x1DE},
+	{
+	 100, 5500, 3667, 0x71, 0x02, 0x26, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x89C, 0x898, 0x894, 0x1DC, 0x1DD, 0x1DD},
+	{
+	 102, 5510, 3673, 0x71, 0x02, 0x27, 0x06, 0x47, 0x01, 0x04, 0x0A,
+	 0x00, 0x84, 0x00, 0x00, 0x44, 0x00, 0x03, 0x00, 0x80, 0x44, 0x00, 0x03,
+	 0x00, 0x80, 0x8A0, 0x89C, 0x898, 0x1DB, 0x1DC, 0x1DD},
+	{
+	 104, 5520, 3680, 0x71, 0x02, 0x28, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A4, 0x8A0, 0x89C, 0x1DA, 0x1DB, 0x1DC},
+	{
+	 106, 5530, 3687, 0x71, 0x02, 0x29, 0x05, 0x40, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8A8, 0x8A4, 0x8A0, 0x1D9, 0x1DA, 0x1DB},
+	{
+	 108, 5540, 3693, 0x71, 0x02, 0x2A, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8AC, 0x8A8, 0x8A4, 0x1D8, 0x1D9, 0x1DA},
+	{
+	 110, 5550, 3700, 0x71, 0x02, 0x2B, 0x05, 0x3A, 0x01, 0x04, 0x0A,
+	 0x00, 0x83, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00, 0x80, 0x33, 0x00, 0x02,
+	 0x00, 0x80, 0x8B0, 0x8AC, 0x8A8, 0x1D7, 0x1D8, 0x1D9},
+	{
+	 112, 5560, 3707, 0x71, 0x02, 0x2C, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B4, 0x8B0, 0x8AC, 0x1D7, 0x1D7, 0x1D8},
+	{
+	 114, 5570, 3713, 0x71, 0x02, 0x2D, 0x05, 0x34, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8B8, 0x8B4, 0x8B0, 0x1D6, 0x1D7, 0x1D7},
+	{
+	 116, 5580, 3720, 0x71, 0x02, 0x2E, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8BC, 0x8B8, 0x8B4, 0x1D5, 0x1D6, 0x1D7},
+	{
+	 118, 5590, 3727, 0x71, 0x02, 0x2F, 0x04, 0x2E, 0x01, 0x04, 0x0A,
+	 0x00, 0x82, 0x00, 0x00, 0x22, 0x00, 0x01, 0x00, 0x80, 0x22, 0x00, 0x01,
+	 0x00, 0x80, 0x8C0, 0x8BC, 0x8B8, 0x1D4, 0x1D5, 0x1D6},
+	{
+	 120, 5600, 3733, 0x71, 0x02, 0x30, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C4, 0x8C0, 0x8BC, 0x1D3, 0x1D4, 0x1D5},
+	{
+	 122, 5610, 3740, 0x71, 0x02, 0x31, 0x04, 0x28, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x01, 0x00, 0x80, 0x11, 0x00, 0x01,
+	 0x00, 0x80, 0x8C8, 0x8C4, 0x8C0, 0x1D2, 0x1D3, 0x1D4},
+	{
+	 124, 5620, 3747, 0x71, 0x02, 0x32, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8CC, 0x8C8, 0x8C4, 0x1D2, 0x1D2, 0x1D3},
+	{
+	 126, 5630, 3753, 0x71, 0x02, 0x33, 0x04, 0x21, 0x01, 0x04, 0x0A,
+	 0x00, 0x81, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x80, 0x11, 0x00, 0x00,
+	 0x00, 0x80, 0x8D0, 0x8CC, 0x8C8, 0x1D1, 0x1D2, 0x1D2},
+	{
+	 128, 5640, 3760, 0x71, 0x02, 0x34, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D4, 0x8D0, 0x8CC, 0x1D0, 0x1D1, 0x1D2},
+	{
+	 130, 5650, 3767, 0x71, 0x02, 0x35, 0x03, 0x1C, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8D8, 0x8D4, 0x8D0, 0x1CF, 0x1D0, 0x1D1},
+	{
+	 132, 5660, 3773, 0x71, 0x02, 0x36, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8DC, 0x8D8, 0x8D4, 0x1CE, 0x1CF, 0x1D0},
+	{
+	 134, 5670, 3780, 0x71, 0x02, 0x37, 0x03, 0x16, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E0, 0x8DC, 0x8D8, 0x1CE, 0x1CE, 0x1CF},
+	{
+	 136, 5680, 3787, 0x71, 0x02, 0x38, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E4, 0x8E0, 0x8DC, 0x1CD, 0x1CE, 0x1CE},
+	{
+	 138, 5690, 3793, 0x71, 0x02, 0x39, 0x03, 0x10, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8E8, 0x8E4, 0x8E0, 0x1CC, 0x1CD, 0x1CE},
+	{
+	 140, 5700, 3800, 0x71, 0x02, 0x3A, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8EC, 0x8E8, 0x8E4, 0x1CB, 0x1CC, 0x1CD},
+	{
+	 142, 5710, 3807, 0x71, 0x02, 0x3B, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F0, 0x8EC, 0x8E8, 0x1CA, 0x1CB, 0x1CC},
+	{
+	 144, 5720, 3813, 0x71, 0x02, 0x3C, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F4, 0x8F0, 0x8EC, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 145, 5725, 3817, 0x72, 0x04, 0x79, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F6, 0x8F2, 0x8EE, 0x1C9, 0x1CA, 0x1CB},
+	{
+	 146, 5730, 3820, 0x71, 0x02, 0x3D, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8F8, 0x8F4, 0x8F0, 0x1C9, 0x1C9, 0x1CA},
+	{
+	 147, 5735, 3823, 0x72, 0x04, 0x7B, 0x02, 0x03, 0x01, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FA, 0x8F6, 0x8F2, 0x1C8, 0x1C9, 0x1CA},
+	{
+	 148, 5740, 3827, 0x71, 0x02, 0x3E, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FC, 0x8F8, 0x8F4, 0x1C8, 0x1C9, 0x1C9},
+	{
+	 149, 5745, 3830, 0x72, 0x04, 0x7D, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x8FE, 0x8FA, 0x8F6, 0x1C8, 0x1C8, 0x1C9},
+	{
+	 150, 5750, 3833, 0x71, 0x02, 0x3F, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x900, 0x8FC, 0x8F8, 0x1C7, 0x1C8, 0x1C9},
+	{
+	 151, 5755, 3837, 0x72, 0x04, 0x7F, 0x02, 0xFE, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x902, 0x8FE, 0x8FA, 0x1C7, 0x1C8, 0x1C8},
+	{
+	 152, 5760, 3840, 0x71, 0x02, 0x40, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x904, 0x900, 0x8FC, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 153, 5765, 3843, 0x72, 0x04, 0x81, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x906, 0x902, 0x8FE, 0x1C6, 0x1C7, 0x1C8},
+	{
+	 154, 5770, 3847, 0x71, 0x02, 0x41, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x908, 0x904, 0x900, 0x1C6, 0x1C6, 0x1C7},
+	{
+	 155, 5775, 3850, 0x72, 0x04, 0x83, 0x02, 0xF8, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90A, 0x906, 0x902, 0x1C5, 0x1C6, 0x1C7},
+	{
+	 156, 5780, 3853, 0x71, 0x02, 0x42, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90C, 0x908, 0x904, 0x1C5, 0x1C6, 0x1C6},
+	{
+	 157, 5785, 3857, 0x72, 0x04, 0x85, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x90E, 0x90A, 0x906, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 158, 5790, 3860, 0x71, 0x02, 0x43, 0x02, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x910, 0x90C, 0x908, 0x1C4, 0x1C5, 0x1C6},
+	{
+	 159, 5795, 3863, 0x72, 0x04, 0x87, 0x02, 0xF2, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x912, 0x90E, 0x90A, 0x1C4, 0x1C4, 0x1C5},
+	{
+	 160, 5800, 3867, 0x71, 0x02, 0x44, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x914, 0x910, 0x90C, 0x1C3, 0x1C4, 0x1C5},
+	{
+	 161, 5805, 3870, 0x72, 0x04, 0x89, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x916, 0x912, 0x90E, 0x1C3, 0x1C4, 0x1C4},
+	{
+	 162, 5810, 3873, 0x71, 0x02, 0x45, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x918, 0x914, 0x910, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 163, 5815, 3877, 0x72, 0x04, 0x8B, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91A, 0x916, 0x912, 0x1C2, 0x1C3, 0x1C4},
+	{
+	 164, 5820, 3880, 0x71, 0x02, 0x46, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91C, 0x918, 0x914, 0x1C2, 0x1C2, 0x1C3},
+	{
+	 165, 5825, 3883, 0x72, 0x04, 0x8D, 0x01, 0xED, 0x00, 0x03, 0x14,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x91E, 0x91A, 0x916, 0x1C1, 0x1C2, 0x1C3},
+	{
+	 166, 5830, 3887, 0x71, 0x02, 0x47, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x920, 0x91C, 0x918, 0x1C1, 0x1C2, 0x1C2},
+	{
+	 168, 5840, 3893, 0x71, 0x02, 0x48, 0x01, 0x0A, 0x01, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x924, 0x920, 0x91C, 0x1C0, 0x1C1, 0x1C2},
+	{
+	 170, 5850, 3900, 0x71, 0x02, 0x49, 0x01, 0xE0, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x928, 0x924, 0x920, 0x1BF, 0x1C0, 0x1C1},
+	{
+	 172, 5860, 3907, 0x71, 0x02, 0x4A, 0x01, 0xDE, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x92C, 0x928, 0x924, 0x1BF, 0x1BF, 0x1C0},
+	{
+	 174, 5870, 3913, 0x71, 0x02, 0x4B, 0x00, 0xDB, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x930, 0x92C, 0x928, 0x1BE, 0x1BF, 0x1BF},
+	{
+	 176, 5880, 3920, 0x71, 0x02, 0x4C, 0x00, 0xD8, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x934, 0x930, 0x92C, 0x1BD, 0x1BE, 0x1BF},
+	{
+	 178, 5890, 3927, 0x71, 0x02, 0x4D, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x938, 0x934, 0x930, 0x1BC, 0x1BD, 0x1BE},
+	{
+	 180, 5900, 3933, 0x71, 0x02, 0x4E, 0x00, 0xD3, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x93C, 0x938, 0x934, 0x1BC, 0x1BC, 0x1BD},
+	{
+	 182, 5910, 3940, 0x71, 0x02, 0x4F, 0x00, 0xD6, 0x00, 0x04, 0x0A,
+	 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00,
+	 0x00, 0x80, 0x940, 0x93C, 0x938, 0x1BB, 0x1BC, 0x1BC},
+	{
+	 1, 2412, 3216, 0x73, 0x09, 0x6C, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0D, 0x0C, 0x80, 0xFF, 0x88, 0x0D,
+	 0x0C, 0x80, 0x3C9, 0x3C5, 0x3C1, 0x43A, 0x43F, 0x443},
+	{
+	 2, 2417, 3223, 0x73, 0x09, 0x71, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0B, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0B, 0x80, 0x3CB, 0x3C7, 0x3C3, 0x438, 0x43D, 0x441},
+	{
+	 3, 2422, 3229, 0x73, 0x09, 0x76, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CD, 0x3C9, 0x3C5, 0x436, 0x43A, 0x43F},
+	{
+	 4, 2427, 3236, 0x73, 0x09, 0x7B, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x0A, 0x80, 0xFF, 0x88, 0x0C,
+	 0x0A, 0x80, 0x3CF, 0x3CB, 0x3C7, 0x434, 0x438, 0x43D},
+	{
+	 5, 2432, 3243, 0x73, 0x09, 0x80, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0C, 0x09, 0x80, 0xFF, 0x88, 0x0C,
+	 0x09, 0x80, 0x3D1, 0x3CD, 0x3C9, 0x431, 0x436, 0x43A},
+	{
+	 6, 2437, 3249, 0x73, 0x09, 0x85, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0B, 0x08, 0x80, 0xFF, 0x88, 0x0B,
+	 0x08, 0x80, 0x3D3, 0x3CF, 0x3CB, 0x42F, 0x434, 0x438},
+	{
+	 7, 2442, 3256, 0x73, 0x09, 0x8A, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x07, 0x80, 0xFF, 0x88, 0x0A,
+	 0x07, 0x80, 0x3D5, 0x3D1, 0x3CD, 0x42D, 0x431, 0x436},
+	{
+	 8, 2447, 3263, 0x73, 0x09, 0x8F, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x0A, 0x06, 0x80, 0xFF, 0x88, 0x0A,
+	 0x06, 0x80, 0x3D7, 0x3D3, 0x3CF, 0x42B, 0x42F, 0x434},
+	{
+	 9, 2452, 3269, 0x73, 0x09, 0x94, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x09, 0x06, 0x80, 0xFF, 0x88, 0x09,
+	 0x06, 0x80, 0x3D9, 0x3D5, 0x3D1, 0x429, 0x42D, 0x431},
+	{
+	 10, 2457, 3276, 0x73, 0x09, 0x99, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x05, 0x80, 0xFF, 0x88, 0x08,
+	 0x05, 0x80, 0x3DB, 0x3D7, 0x3D3, 0x427, 0x42B, 0x42F},
+	{
+	 11, 2462, 3283, 0x73, 0x09, 0x9E, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x04, 0x80, 0xFF, 0x88, 0x08,
+	 0x04, 0x80, 0x3DD, 0x3D9, 0x3D5, 0x424, 0x429, 0x42D},
+	{
+	 12, 2467, 3289, 0x73, 0x09, 0xA3, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x08, 0x03, 0x80, 0xFF, 0x88, 0x08,
+	 0x03, 0x80, 0x3DF, 0x3DB, 0x3D7, 0x422, 0x427, 0x42B},
+	{
+	 13, 2472, 3296, 0x73, 0x09, 0xA8, 0x0F, 0x00, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x03, 0x80, 0xFF, 0x88, 0x07,
+	 0x03, 0x80, 0x3E1, 0x3DD, 0x3D9, 0x420, 0x424, 0x429},
+	{
+	 14, 2484, 3312, 0x73, 0x09, 0xB4, 0x0F, 0xFF, 0x01, 0x07, 0x15,
+	 0x01, 0x8F, 0xFF, 0xFF, 0xFF, 0x88, 0x07, 0x01, 0x80, 0xFF, 0x88, 0x07,
+	 0x01, 0x80, 0x3E6, 0x3E2, 0x3DE, 0x41B, 0x41F, 0x424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev3_2056[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xff, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xff, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xff, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xfc, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfc, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x05, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x05, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x8e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7e, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xfa, 0x00, 0x7d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xfa, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x08, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x08,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x4c, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x3b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2b, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x2a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x1a, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x19, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x09, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf8, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf8, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x08, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf6, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf6, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf6, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x06, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf4, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf4, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x03, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x06, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x06,
+	 0x00, 0xf2, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x05, 0x00, 0xf2, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x05,
+	 0x00, 0xf2, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xff, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfd, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfb, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf7, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0f, 0x00, 0xf6, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0f, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf5, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf4, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf3, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x05, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0d, 0x00, 0xf0, 0x00, 0x05, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0d, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev4_2056_A1[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0e, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0e, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0d, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xff, 0x00, 0x0d, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xff, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xff, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0c, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfe, 0x00, 0xef, 0x00, 0x0c, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfe, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xef, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xef, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xdf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xdf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xcf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xcf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xbf, 0x00, 0x0a, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfc, 0x00, 0xbf, 0x00, 0x0a, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfc, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xbf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xbf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xaf, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0xaf, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x9f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x9f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x8f, 0x00, 0x08, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xfa, 0x00, 0x8f, 0x00, 0x08, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xfa, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8f, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8f, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x8e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x8e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7e, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7e, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x7d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x7d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x6d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x6d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5d, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5d, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x5c, 0x00, 0x07, 0x00, 0x7f,
+	 0x00, 0x0f, 0x00, 0xf8, 0x00, 0x5c, 0x00, 0x07, 0x00, 0x7f, 0x00, 0x0f,
+	 0x00, 0xf8, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x5c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x5c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x4c, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x4c, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x3b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x3b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2b, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2b, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x2a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x2a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x1a, 0x00, 0x06, 0x00, 0x7f,
+	 0x00, 0x0d, 0x00, 0xf6, 0x00, 0x1a, 0x00, 0x06, 0x00, 0x7f, 0x00, 0x0d,
+	 0x00, 0xf6, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x1a, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x1a, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x19, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x19, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x09, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x09, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x08, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x08, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x07, 0x00, 0x04, 0x00, 0x7f,
+	 0x00, 0x0b, 0x00, 0xf4, 0x00, 0x07, 0x00, 0x04, 0x00, 0x7f, 0x00, 0x0b,
+	 0x00, 0xf4, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x07, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x07, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x06, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x06, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x05, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x05, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x04, 0x00, 0x03, 0x00, 0x7f,
+	 0x00, 0x0a, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x03, 0x00, 0x7f, 0x00, 0x0a,
+	 0x00, 0xf2, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x04, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x03, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x03, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x02, 0x00, 0x02, 0x00, 0x7f,
+	 0x00, 0x09, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x02, 0x00, 0x7f, 0x00, 0x09,
+	 0x00, 0xf0, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x02, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f,
+	 0x00, 0x07, 0x00, 0xf0, 0x00, 0x01, 0x00, 0x00, 0x00, 0x7f, 0x00, 0x07,
+	 0x00, 0xf0, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xff, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xff, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfd, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfb, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfb, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xfa, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf8, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf8, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf7, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf7, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf6, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf6, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf5, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf5, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf4, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf4, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf3, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf3, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf2, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf2, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x04, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0e, 0x00, 0xf0, 0x00, 0x04, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0e, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev5_2056v5[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0f, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8f, 0x0e, 0x00, 0xff, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x5a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x5a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xc8, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x59, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0d, 0x00, 0xc8, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8d, 0x0b, 0x00, 0x84, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x75, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x75, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8b, 0x09, 0x00, 0x70, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x74, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x83, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x8a, 0x06, 0x00, 0x40, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x82, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x72, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x88, 0x04, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x87, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x71, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x1f, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x0e, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0d, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0d, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0c, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x0b, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x0b, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x09, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x08, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x08, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x07, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x07, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x06, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x06, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x05, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x05, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x04, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x04, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x03, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x03, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v6[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x67, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x57, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x56, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x46, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x23, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x12, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x02, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x01, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev5n6_2056v7[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0f, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0b, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0b, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0e, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x0a, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x0a, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0d, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xff, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xff, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x70,
+	 0x00, 0x0c, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x70, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0b, 0x00, 0x9f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x0a, 0x00, 0x9f, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x07, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x07, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfb, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xfa, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x09, 0x00, 0x9e, 0x00, 0xfa, 0x00, 0x06, 0x00, 0x70, 0x00, 0x09,
+	 0x00, 0x6e, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xea, 0x00, 0x06, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9e, 0x00, 0xea, 0x00, 0x06, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6e, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xe9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xe9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xd9, 0x00, 0x05, 0x00, 0x70,
+	 0x00, 0x08, 0x00, 0x9d, 0x00, 0xd9, 0x00, 0x05, 0x00, 0x70, 0x00, 0x08,
+	 0x00, 0x6d, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xd8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xd8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xc8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xc8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb8, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9c, 0x00, 0xb8, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6c, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xb7, 0x00, 0x04, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x04, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xb7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x07, 0x00, 0x9b, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x07,
+	 0x00, 0x6b, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa7, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa7, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x6b, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0xa6, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9b, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7b, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x96, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x96, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x06, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x06,
+	 0x00, 0x7a, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x95, 0x00, 0x03, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x9a, 0x00, 0x95, 0x00, 0x03, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x7a, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x85, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x85, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x05, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x05,
+	 0x00, 0x79, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x02, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x84, 0x00, 0x02, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x74, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x99, 0x00, 0x74, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x79, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x04, 0x00, 0x98, 0x00, 0x73, 0x00, 0x01, 0x00, 0x70, 0x00, 0x04,
+	 0x00, 0x78, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x63, 0x00, 0x01, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x98, 0x00, 0x63, 0x00, 0x01, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x78, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x03, 0x00, 0x97, 0x00, 0x62, 0x00, 0x00, 0x00, 0x70, 0x00, 0x03,
+	 0x00, 0x77, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x76, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x52, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x52, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x96, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x86, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x51, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x02, 0x00, 0x95, 0x00, 0x51, 0x00, 0x00, 0x00, 0x70, 0x00, 0x02,
+	 0x00, 0x85, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x95, 0x00, 0x50, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x85, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x84, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x40, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x40, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x01, 0x00, 0x94, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x01,
+	 0x00, 0x94, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x30, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x30, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x93, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x93, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x20, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x10, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x92, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70,
+	 0x00, 0x00, 0x00, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x70, 0x00, 0x00,
+	 0x00, 0x91, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0b, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0b, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x89, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0f, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0f, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x76, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x66, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x55, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0e, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0e, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x33, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x22, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x11, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0d, 0x00, 0x08, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0d, 0x00, 0x08, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v8[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x07, 0x07, 0x04, 0x10, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x04, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x08, 0x08, 0x04, 0x16, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio205x_t chan_info_nphyrev6_2056v11[] = {
+	{
+	 184, 4920, 0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216},
+	{
+	 186, 4930, 0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215},
+	{
+	 188, 4940, 0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214},
+	{
+	 190, 4950, 0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213},
+	{
+	 192, 4960, 0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212},
+	{
+	 194, 4970, 0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211},
+	{
+	 196, 4980, 0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f},
+	{
+	 198, 4990, 0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e},
+	{
+	 200, 5000, 0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d},
+	{
+	 202, 5010, 0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c},
+	{
+	 204, 5020, 0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b},
+	{
+	 206, 5030, 0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a},
+	{
+	 208, 5040, 0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209},
+	{
+	 210, 5050, 0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208},
+	{
+	 212, 5060, 0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207},
+	{
+	 214, 5070, 0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206},
+	{
+	 216, 5080, 0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205},
+	{
+	 218, 5090, 0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204},
+	{
+	 220, 5100, 0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203},
+	{
+	 222, 5110, 0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202},
+	{
+	 224, 5120, 0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201},
+	{
+	 226, 5130, 0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200},
+	{
+	 228, 5140, 0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77,
+	 0x00, 0x0f, 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+	 0x00, 0x6f, 0x00, 0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff},
+	{
+	 32, 5160, 0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd},
+	{
+	 34, 5170, 0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc},
+	{
+	 36, 5180, 0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0e, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0e,
+	 0x00, 0x6f, 0x00, 0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb},
+	{
+	 38, 5190, 0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa},
+	{
+	 40, 5200, 0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9},
+	{
+	 42, 5210, 0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00, 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8},
+	{
+	 44, 5220, 0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xfe, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7},
+	{
+	 46, 5230, 0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6},
+	{
+	 48, 5240, 0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5},
+	{
+	 50, 5250, 0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00, 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4},
+	{
+	 52, 5260, 0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0d, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+	 0x00, 0x6f, 0x00, 0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3},
+	{
+	 54, 5270, 0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00, 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2},
+	{
+	 56, 5280, 0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1},
+	{
+	 58, 5290, 0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0},
+	{
+	 60, 5300, 0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0},
+	{
+	 62, 5310, 0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef},
+	{
+	 64, 5320, 0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00, 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0c, 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+	 0x00, 0x6f, 0x00, 0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee},
+	{
+	 66, 5330, 0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed},
+	{
+	 68, 5340, 0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec},
+	{
+	 70, 5350, 0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0b, 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+	 0x00, 0x6f, 0x00, 0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb},
+	{
+	 72, 5360, 0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea},
+	{
+	 74, 5370, 0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00, 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9},
+	{
+	 76, 5380, 0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8},
+	{
+	 78, 5390, 0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7},
+	{
+	 80, 5400, 0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6},
+	{
+	 82, 5410, 0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5},
+	{
+	 84, 5420, 0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00, 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5},
+	{
+	 86, 5430, 0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x0a, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+	 0x00, 0x6f, 0x00, 0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4},
+	{
+	 88, 5440, 0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3},
+	{
+	 90, 5450, 0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2},
+	{
+	 92, 5460, 0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x95, 0x84, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1},
+	{
+	 94, 5470, 0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00, 0x94, 0x73, 0x00, 0x01, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0},
+	{
+	 96, 5480, 0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x84, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df},
+	{
+	 98, 5490, 0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x83, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de},
+	{
+	 100, 5500, 0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd},
+	{
+	 102, 5510, 0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x82, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd},
+	{
+	 104, 5520, 0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc},
+	{
+	 106, 5530, 0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x72, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db},
+	{
+	 108, 5540, 0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00, 0x71, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da},
+	{
+	 110, 5550, 0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9},
+	{
+	 112, 5560, 0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8},
+	{
+	 114, 5570, 0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x09, 0x00, 0x61, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x09, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+	 0x00, 0x6f, 0x00, 0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7},
+	{
+	 116, 5580, 0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x60, 0x62, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7},
+	{
+	 118, 5590, 0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x04, 0x04, 0x04, 0x89, 0x08, 0x00, 0x50, 0x61, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6},
+	{
+	 120, 5600, 0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5},
+	{
+	 122, 5610, 0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x51, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x08, 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+	 0x00, 0x6f, 0x00, 0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4},
+	{
+	 124, 5620, 0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x89, 0x08, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3},
+	{
+	 126, 5630, 0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x50, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2},
+	{
+	 128, 5640, 0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x50, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2},
+	{
+	 130, 5650, 0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x07, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+	 0x00, 0x6f, 0x00, 0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1},
+	{
+	 132, 5660, 0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x40, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0},
+	{
+	 134, 5670, 0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x88, 0x07, 0x00, 0x40, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf},
+	{
+	 136, 5680, 0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce},
+	{
+	 138, 5690, 0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6f, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce},
+	{
+	 140, 5700, 0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd},
+	{
+	 142, 5710, 0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc},
+	{
+	 144, 5720, 0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 145, 5725, 0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x06, 0x00, 0x30, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb},
+	{
+	 146, 5730, 0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6e, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca},
+	{
+	 147, 5735, 0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca},
+	{
+	 148, 5740, 0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9},
+	{
+	 149, 5745, 0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x30, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x06, 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+	 0x00, 0x6d, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9},
+	{
+	 150, 5750, 0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x20, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6d, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9},
+	{
+	 151, 5755, 0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x87, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8},
+	{
+	 152, 5760, 0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x20, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 153, 5765, 0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x05, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6c, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6c, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8},
+	{
+	 154, 5770, 0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7},
+	{
+	 155, 5775, 0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7},
+	{
+	 156, 5780, 0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x05, 0x05, 0x05, 0x86, 0x04, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6},
+	{
+	 157, 5785, 0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 158, 5790, 0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6},
+	{
+	 159, 5795, 0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5},
+	{
+	 160, 5800, 0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6b, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5},
+	{
+	 161, 5805, 0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4},
+	{
+	 162, 5810, 0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 163, 5815, 0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4},
+	{
+	 164, 5820, 0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x6a, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3},
+	{
+	 165, 5825, 0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02, 0x15, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3},
+	{
+	 166, 5830, 0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x05, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+	 0x00, 0x69, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2},
+	{
+	 168, 5840, 0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x86, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2},
+	{
+	 170, 5850, 0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1},
+	{
+	 172, 5860, 0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x69, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0},
+	{
+	 174, 5870, 0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf},
+	{
+	 176, 5880, 0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf},
+	{
+	 178, 5890, 0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be},
+	{
+	 180, 5900, 0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd},
+	{
+	 182, 5910, 0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02, 0x0c, 0x01,
+	 0x06, 0x06, 0x06, 0x85, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+	 0x00, 0x04, 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+	 0x00, 0x68, 0x00, 0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc},
+	{
+	 1, 2412, 0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03c9, 0x03c5, 0x03c1, 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x00, 0x01, 0x03, 0x09, 0x71, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x78, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cb, 0x03c7, 0x03c3, 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x00, 0x01, 0x03, 0x09, 0x76, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x67, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0b, 0x00, 0x0a, 0x00, 0x89, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0b, 0x00, 0x0a, 0x03cd, 0x03c9, 0x03c5, 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x00, 0x01, 0x03, 0x09, 0x7b, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x57, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x78, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03cf, 0x03cb, 0x03c7, 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x00, 0x01, 0x03, 0x09, 0x80, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x56, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x77, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d1, 0x03cd, 0x03c9, 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x00, 0x01, 0x03, 0x09, 0x85, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x46, 0x00, 0x03, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x76, 0x00, 0x03, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d3, 0x03cf, 0x03cb, 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x00, 0x01, 0x03, 0x09, 0x8a, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x05, 0x05, 0x05, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x45, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x0a, 0x00, 0x66, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x0a, 0x03d5, 0x03d1, 0x03cd, 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x00, 0x01, 0x03, 0x09, 0x8f, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x34, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x55, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d7, 0x03d3, 0x03cf, 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x00, 0x01, 0x03, 0x09, 0x94, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x23, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x45, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03d9, 0x03d5, 0x03d1, 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x00, 0x01, 0x03, 0x09, 0x99, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x12, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x0a, 0x00, 0x09, 0x00, 0x34, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x0a, 0x00, 0x09, 0x03db, 0x03d7, 0x03d3, 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x00, 0x01, 0x03, 0x09, 0x9e, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x33, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03dd, 0x03d9, 0x03d5, 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x00, 0x01, 0x03, 0x09, 0xa3, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x06, 0x06, 0x06, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x22, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03df, 0x03db, 0x03d7, 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x00, 0x01, 0x03, 0x09, 0xa8, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x30, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x11, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e1, 0x03dd, 0x03d9, 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0xff, 0x01, 0x03, 0x09, 0xb4, 0x06, 0x06, 0x04, 0x2b, 0x01,
+	 0x07, 0x07, 0x07, 0x8f, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00,
+	 0x70, 0x00, 0x09, 0x00, 0x09, 0x00, 0x00, 0x00, 0x02, 0x00, 0x70, 0x00,
+	 0x09, 0x00, 0x09, 0x03e6, 0x03e2, 0x03de, 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio2057_t chan_info_nphyrev7_2057_rev4[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216,
+	 },
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215,
+	 },
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214,
+	 },
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213,
+	 },
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212,
+	 },
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211,
+	 },
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f,
+	 },
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e,
+	 },
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d,
+	 },
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c,
+	 },
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b,
+	 },
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a,
+	 },
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209,
+	 },
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xf3, 0x00, 0xef, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208,
+	 },
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0f, 0x0f, 0xe3, 0x00, 0xef, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207,
+	 },
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206,
+	 },
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xef, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205,
+	 },
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204,
+	 },
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203,
+	 },
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202,
+	 },
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201,
+	 },
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0f, 0xe3, 0x00, 0xd6, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200,
+	 },
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0e, 0x0e, 0xe3, 0x00, 0xd6, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff,
+	 },
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd,
+	 },
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xe3, 0x00, 0xd6, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc,
+	 },
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb,
+	 },
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa,
+	 },
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9,
+	 },
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0d, 0x0e, 0xd3, 0x00, 0xd6, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8,
+	 },
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7,
+	 },
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6,
+	 },
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5,
+	 },
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0e, 0xd3, 0x00, 0xd6, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4,
+	 },
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3,
+	 },
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x00,
+	 0x00, 0x0c, 0x0d, 0xd3, 0x00, 0xd6, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2,
+	 },
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1,
+	 },
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0,
+	 },
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0c, 0x0c, 0xc3, 0x00, 0xd4, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0,
+	 },
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef,
+	 },
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee,
+	 },
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x00,
+	 0x00, 0x0b, 0x0c, 0xc3, 0x00, 0xd4, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed,
+	 },
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0c, 0xc3, 0x00, 0xa1, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec,
+	 },
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb,
+	 },
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea,
+	 },
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9,
+	 },
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0b, 0xb3, 0x00, 0xa1, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8,
+	 },
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x00,
+	 0x00, 0x0a, 0x0a, 0xa3, 0x00, 0xa1, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7,
+	 },
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6,
+	 },
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x0a, 0xa3, 0x00, 0x90, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5,
+	 },
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0xa3, 0x00, 0x90, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5,
+	 },
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4,
+	 },
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3,
+	 },
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x09, 0x09, 0x93, 0x00, 0x90, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2,
+	 },
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x90, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1,
+	 },
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x08, 0x93, 0x00, 0x60, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0,
+	 },
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df,
+	 },
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de,
+	 },
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd,
+	 },
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x07, 0x93, 0x00, 0x60, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd,
+	 },
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc,
+	 },
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db,
+	 },
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x06, 0x93, 0x00, 0x60, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da,
+	 },
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9,
+	 },
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8,
+	 },
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x08, 0x05, 0x83, 0x00, 0x60, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7,
+	 },
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x05, 0x83, 0x00, 0x60, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7,
+	 },
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x00,
+	 0x00, 0x07, 0x04, 0x83, 0x00, 0x60, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6,
+	 },
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x07, 0x04, 0x73, 0x00, 0x30, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5,
+	 },
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4,
+	 },
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3,
+	 },
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2,
+	 },
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x04, 0x73, 0x00, 0x30, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2,
+	 },
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1,
+	 },
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x00,
+	 0x00, 0x06, 0x03, 0x63, 0x00, 0x30, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0,
+	 },
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x03, 0x63, 0x00, 0x00, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf,
+	 },
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce,
+	 },
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce,
+	 },
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd,
+	 },
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc,
+	 },
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x02, 0x53, 0x00, 0x00, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x05, 0x01, 0x53, 0x00, 0x00, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb,
+	 },
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca,
+	 },
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9,
+	 },
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9,
+	 },
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x53, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8,
+	 },
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8,
+	 },
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x04, 0x01, 0x43, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7,
+	 },
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x01, 0x43, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6,
+	 },
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6,
+	 },
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5,
+	 },
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4,
+	 },
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4,
+	 },
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3,
+	 },
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2,
+	 },
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2,
+	 },
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1,
+	 },
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0,
+	 },
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf,
+	 },
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf,
+	 },
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be,
+	 },
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x00,
+	 0x00, 0x03, 0x00, 0x43, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd,
+	 },
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443,
+	 },
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x71, 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0xa3, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441,
+	 },
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f,
+	 },
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x71, 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x71,
+	 0x93, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d,
+	 },
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a,
+	 },
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x51, 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x83, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438,
+	 },
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x51, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x51,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436,
+	 },
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434,
+	 },
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x31, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431,
+	 },
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f,
+	 },
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x31, 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x31,
+	 0x63, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d,
+	 },
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b,
+	 },
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x11, 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x11,
+	 0x53, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429,
+	 },
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x11, 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x11,
+	 0x43, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev8_2057_rev5[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio2057_rev5_t chan_info_nphyrev9_2057_rev5v1[] = {
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03c9, 0x03c5, 0x03c1,
+	 0x043a, 0x043f, 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xff, 0x61, 0x03, 0xff, 0x03cb, 0x03c7, 0x03c3,
+	 0x0438, 0x043d, 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0d,
+	 0x08, 0x0e, 0x61, 0x03, 0xef, 0x61, 0x03, 0xef, 0x03cd, 0x03c9, 0x03c5,
+	 0x0436, 0x043a, 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0c,
+	 0x08, 0x0e, 0x61, 0x03, 0xdf, 0x61, 0x03, 0xdf, 0x03cf, 0x03cb, 0x03c7,
+	 0x0434, 0x0438, 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xcf, 0x61, 0x03, 0xcf, 0x03d1, 0x03cd, 0x03c9,
+	 0x0431, 0x0436, 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0c,
+	 0x07, 0x0d, 0x61, 0x03, 0xbf, 0x61, 0x03, 0xbf, 0x03d3, 0x03cf, 0x03cb,
+	 0x042f, 0x0434, 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0xaf, 0x61, 0x03, 0xaf, 0x03d5, 0x03d1, 0x03cd,
+	 0x042d, 0x0431, 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x9f, 0x61, 0x03, 0x9f, 0x03d7, 0x03d3, 0x03cf,
+	 0x042b, 0x042f, 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0b,
+	 0x07, 0x0d, 0x61, 0x03, 0x8f, 0x61, 0x03, 0x8f, 0x03d9, 0x03d5, 0x03d1,
+	 0x0429, 0x042d, 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x7f, 0x61, 0x03, 0x7f, 0x03db, 0x03d7, 0x03d3,
+	 0x0427, 0x042b, 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0b,
+	 0x07, 0x0c, 0x61, 0x03, 0x6f, 0x61, 0x03, 0x6f, 0x03dd, 0x03d9, 0x03d5,
+	 0x0424, 0x0429, 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0b,
+	 0x06, 0x0c, 0x61, 0x03, 0x5f, 0x61, 0x03, 0x5f, 0x03df, 0x03db, 0x03d7,
+	 0x0422, 0x0427, 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x4f, 0x61, 0x03, 0x4f, 0x03e1, 0x03dd, 0x03d9,
+	 0x0420, 0x0424, 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0a,
+	 0x06, 0x0b, 0x61, 0x03, 0x3f, 0x61, 0x03, 0x3f, 0x03e6, 0x03e2, 0x03de,
+	 0x041b, 0x041f, 0x0424}
+};
+
+static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev7[] = {
+	{
+	 184, 4920, 0x68, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xec, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b4, 0x07b0, 0x07ac, 0x0214,
+	 0x0215,
+	 0x0216},
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+static chan_info_nphy_radio2057_t chan_info_nphyrev8_2057_rev8[] = {
+	{
+	 186, 4930, 0x6b, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xed, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07b8, 0x07b4, 0x07b0, 0x0213,
+	 0x0214,
+	 0x0215},
+	{
+	 188, 4940, 0x6e, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xee, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0xd3, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07bc, 0x07b8, 0x07b4, 0x0212,
+	 0x0213,
+	 0x0214},
+	{
+	 190, 4950, 0x72, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xef, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c0, 0x07bc, 0x07b8, 0x0211,
+	 0x0212,
+	 0x0213},
+	{
+	 192, 4960, 0x75, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf0, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c4, 0x07c0, 0x07bc, 0x020f,
+	 0x0211,
+	 0x0212},
+	{
+	 194, 4970, 0x78, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf1, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07c8, 0x07c4, 0x07c0, 0x020e,
+	 0x020f,
+	 0x0211},
+	{
+	 196, 4980, 0x7c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf2, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07cc, 0x07c8, 0x07c4, 0x020d,
+	 0x020e,
+	 0x020f},
+	{
+	 198, 4990, 0x7f, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf3, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xd3, 0x00, 0xff, 0x07d0, 0x07cc, 0x07c8, 0x020c,
+	 0x020d,
+	 0x020e},
+	{
+	 200, 5000, 0x82, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf4, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d4, 0x07d0, 0x07cc, 0x020b,
+	 0x020c,
+	 0x020d},
+	{
+	 202, 5010, 0x86, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf5, 0x01, 0x0f,
+	 0x00, 0x0f, 0x00, 0xff, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07d8, 0x07d4, 0x07d0, 0x020a,
+	 0x020b,
+	 0x020c},
+	{
+	 204, 5020, 0x89, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf6, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07dc, 0x07d8, 0x07d4, 0x0209,
+	 0x020a,
+	 0x020b},
+	{
+	 206, 5030, 0x8c, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf7, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e0, 0x07dc, 0x07d8, 0x0208,
+	 0x0209,
+	 0x020a},
+	{
+	 208, 5040, 0x90, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf8, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e4, 0x07e0, 0x07dc, 0x0207,
+	 0x0208,
+	 0x0209},
+	{
+	 210, 5050, 0x93, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xf9, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07e8, 0x07e4, 0x07e0, 0x0206,
+	 0x0207,
+	 0x0208},
+	{
+	 212, 5060, 0x96, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfa, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07ec, 0x07e8, 0x07e4, 0x0205,
+	 0x0206,
+	 0x0207},
+	{
+	 214, 5070, 0x9a, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfb, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f0, 0x07ec, 0x07e8, 0x0204,
+	 0x0205,
+	 0x0206},
+	{
+	 216, 5080, 0x9d, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfc, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f4, 0x07f0, 0x07ec, 0x0203,
+	 0x0204,
+	 0x0205},
+	{
+	 218, 5090, 0xa0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfd, 0x01, 0x0e,
+	 0x00, 0x0e, 0x00, 0xee, 0x00, 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x00,
+	 0x00, 0x0f, 0x0f, 0xb3, 0x00, 0xff, 0x07f8, 0x07f4, 0x07f0, 0x0202,
+	 0x0203,
+	 0x0204},
+	{
+	 220, 5100, 0xa4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xfe, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x07fc, 0x07f8, 0x07f4, 0x0201,
+	 0x0202,
+	 0x0203},
+	{
+	 222, 5110, 0xa7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0xff, 0x01, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0800, 0x07fc, 0x07f8, 0x0200,
+	 0x0201,
+	 0x0202},
+	{
+	 224, 5120, 0xaa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x00, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0804, 0x0800, 0x07fc, 0x01ff,
+	 0x0200,
+	 0x0201},
+	{
+	 226, 5130, 0xae, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x01, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0808, 0x0804, 0x0800, 0x01fe,
+	 0x01ff,
+	 0x0200},
+	{
+	 228, 5140, 0xb1, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x02, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x080c, 0x0808, 0x0804, 0x01fd,
+	 0x01fe,
+	 0x01ff},
+	{
+	 32, 5160, 0xb8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x04, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0814, 0x0810, 0x080c, 0x01fb,
+	 0x01fc,
+	 0x01fd},
+	{
+	 34, 5170, 0xbb, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x05, 0x02, 0x0d,
+	 0x00, 0x0d, 0x00, 0xdd, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0818, 0x0814, 0x0810, 0x01fa,
+	 0x01fb,
+	 0x01fc},
+	{
+	 36, 5180, 0xbe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x06, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x081c, 0x0818, 0x0814, 0x01f9,
+	 0x01fa,
+	 0x01fb},
+	{
+	 38, 5190, 0xc2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x07, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x00,
+	 0x00, 0x0f, 0x0f, 0xa3, 0x00, 0xfc, 0x0820, 0x081c, 0x0818, 0x01f8,
+	 0x01f9,
+	 0x01fa},
+	{
+	 40, 5200, 0xc5, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x08, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0824, 0x0820, 0x081c, 0x01f7,
+	 0x01f8,
+	 0x01f9},
+	{
+	 42, 5210, 0xc8, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x09, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0828, 0x0824, 0x0820, 0x01f6,
+	 0x01f7,
+	 0x01f8},
+	{
+	 44, 5220, 0xcc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0a, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x082c, 0x0828, 0x0824, 0x01f5,
+	 0x01f6,
+	 0x01f7},
+	{
+	 46, 5230, 0xcf, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0b, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0830, 0x082c, 0x0828, 0x01f4,
+	 0x01f5,
+	 0x01f6},
+	{
+	 48, 5240, 0xd2, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0c, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0834, 0x0830, 0x082c, 0x01f3,
+	 0x01f4,
+	 0x01f5},
+	{
+	 50, 5250, 0xd6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0d, 0x02, 0x0c,
+	 0x00, 0x0c, 0x00, 0xcc, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0838, 0x0834, 0x0830, 0x01f2,
+	 0x01f3,
+	 0x01f4},
+	{
+	 52, 5260, 0xd9, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0e, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x083c, 0x0838, 0x0834, 0x01f1,
+	 0x01f2,
+	 0x01f3},
+	{
+	 54, 5270, 0xdc, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x0f, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0840, 0x083c, 0x0838, 0x01f0,
+	 0x01f1,
+	 0x01f2},
+	{
+	 56, 5280, 0xe0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x10, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0844, 0x0840, 0x083c, 0x01f0,
+	 0x01f0,
+	 0x01f1},
+	{
+	 58, 5290, 0xe3, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x11, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x00,
+	 0x00, 0x0f, 0x0f, 0x93, 0x00, 0xf8, 0x0848, 0x0844, 0x0840, 0x01ef,
+	 0x01f0,
+	 0x01f0},
+	{
+	 60, 5300, 0xe6, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x12, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x084c, 0x0848, 0x0844, 0x01ee,
+	 0x01ef,
+	 0x01f0},
+	{
+	 62, 5310, 0xea, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x13, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0850, 0x084c, 0x0848, 0x01ed,
+	 0x01ee,
+	 0x01ef},
+	{
+	 64, 5320, 0xed, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x14, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0854, 0x0850, 0x084c, 0x01ec,
+	 0x01ed,
+	 0x01ee},
+	{
+	 66, 5330, 0xf0, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x15, 0x02, 0x0b,
+	 0x00, 0x0b, 0x00, 0xbb, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0858, 0x0854, 0x0850, 0x01eb,
+	 0x01ec,
+	 0x01ed},
+	{
+	 68, 5340, 0xf4, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x16, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x085c, 0x0858, 0x0854, 0x01ea,
+	 0x01eb,
+	 0x01ec},
+	{
+	 70, 5350, 0xf7, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x17, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0860, 0x085c, 0x0858, 0x01e9,
+	 0x01ea,
+	 0x01eb},
+	{
+	 72, 5360, 0xfa, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x18, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0864, 0x0860, 0x085c, 0x01e8,
+	 0x01e9,
+	 0x01ea},
+	{
+	 74, 5370, 0xfe, 0x16, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x19, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0868, 0x0864, 0x0860, 0x01e7,
+	 0x01e8,
+	 0x01e9},
+	{
+	 76, 5380, 0x01, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1a, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x086c, 0x0868, 0x0864, 0x01e6,
+	 0x01e7,
+	 0x01e8},
+	{
+	 78, 5390, 0x04, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1b, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x00,
+	 0x00, 0x0f, 0x0c, 0x83, 0x00, 0xf5, 0x0870, 0x086c, 0x0868, 0x01e5,
+	 0x01e6,
+	 0x01e7},
+	{
+	 80, 5400, 0x08, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1c, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0874, 0x0870, 0x086c, 0x01e5,
+	 0x01e5,
+	 0x01e6},
+	{
+	 82, 5410, 0x0b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1d, 0x02, 0x0a,
+	 0x00, 0x0a, 0x00, 0xaa, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0878, 0x0874, 0x0870, 0x01e4,
+	 0x01e5,
+	 0x01e5},
+	{
+	 84, 5420, 0x0e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1e, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x087c, 0x0878, 0x0874, 0x01e3,
+	 0x01e4,
+	 0x01e5},
+	{
+	 86, 5430, 0x12, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x1f, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0880, 0x087c, 0x0878, 0x01e2,
+	 0x01e3,
+	 0x01e4},
+	{
+	 88, 5440, 0x15, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x20, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0884, 0x0880, 0x087c, 0x01e1,
+	 0x01e2,
+	 0x01e3},
+	{
+	 90, 5450, 0x18, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x21, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0888, 0x0884, 0x0880, 0x01e0,
+	 0x01e1,
+	 0x01e2},
+	{
+	 92, 5460, 0x1c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x22, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x088c, 0x0888, 0x0884, 0x01df,
+	 0x01e0,
+	 0x01e1},
+	{
+	 94, 5470, 0x1f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x23, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0890, 0x088c, 0x0888, 0x01de,
+	 0x01df,
+	 0x01e0},
+	{
+	 96, 5480, 0x22, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x24, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0894, 0x0890, 0x088c, 0x01dd,
+	 0x01de,
+	 0x01df},
+	{
+	 98, 5490, 0x26, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x25, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x00,
+	 0x00, 0x0d, 0x09, 0x53, 0x00, 0xb1, 0x0898, 0x0894, 0x0890, 0x01dd,
+	 0x01dd,
+	 0x01de},
+	{
+	 100, 5500, 0x29, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x26, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x089c, 0x0898, 0x0894, 0x01dc,
+	 0x01dd,
+	 0x01dd},
+	{
+	 102, 5510, 0x2c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x27, 0x02, 0x09,
+	 0x00, 0x09, 0x00, 0x99, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a0, 0x089c, 0x0898, 0x01db,
+	 0x01dc,
+	 0x01dd},
+	{
+	 104, 5520, 0x30, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x28, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a4, 0x08a0, 0x089c, 0x01da,
+	 0x01db,
+	 0x01dc},
+	{
+	 106, 5530, 0x33, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x29, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08a8, 0x08a4, 0x08a0, 0x01d9,
+	 0x01da,
+	 0x01db},
+	{
+	 108, 5540, 0x36, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2a, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08ac, 0x08a8, 0x08a4, 0x01d8,
+	 0x01d9,
+	 0x01da},
+	{
+	 110, 5550, 0x3a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2b, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b0, 0x08ac, 0x08a8, 0x01d7,
+	 0x01d8,
+	 0x01d9},
+	{
+	 112, 5560, 0x3d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2c, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b4, 0x08b0, 0x08ac, 0x01d7,
+	 0x01d7,
+	 0x01d8},
+	{
+	 114, 5570, 0x40, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2d, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08b8, 0x08b4, 0x08b0, 0x01d6,
+	 0x01d7,
+	 0x01d7},
+	{
+	 116, 5580, 0x44, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2e, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08bc, 0x08b8, 0x08b4, 0x01d5,
+	 0x01d6,
+	 0x01d7},
+	{
+	 118, 5590, 0x47, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x2f, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x00,
+	 0x00, 0x0a, 0x06, 0x43, 0x00, 0x80, 0x08c0, 0x08bc, 0x08b8, 0x01d4,
+	 0x01d5,
+	 0x01d6},
+	{
+	 120, 5600, 0x4a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x30, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c4, 0x08c0, 0x08bc, 0x01d3,
+	 0x01d4,
+	 0x01d5},
+	{
+	 122, 5610, 0x4e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x31, 0x02, 0x08,
+	 0x00, 0x08, 0x00, 0x88, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08c8, 0x08c4, 0x08c0, 0x01d2,
+	 0x01d3,
+	 0x01d4},
+	{
+	 124, 5620, 0x51, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x32, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08cc, 0x08c8, 0x08c4, 0x01d2,
+	 0x01d2,
+	 0x01d3},
+	{
+	 126, 5630, 0x54, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x33, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d0, 0x08cc, 0x08c8, 0x01d1,
+	 0x01d2,
+	 0x01d2},
+	{
+	 128, 5640, 0x58, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x34, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x04, 0x23, 0x00, 0x60, 0x08d4, 0x08d0, 0x08cc, 0x01d0,
+	 0x01d1,
+	 0x01d2},
+	{
+	 130, 5650, 0x5b, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x35, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08d8, 0x08d4, 0x08d0, 0x01cf,
+	 0x01d0,
+	 0x01d1},
+	{
+	 132, 5660, 0x5e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x36, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08dc, 0x08d8, 0x08d4, 0x01ce,
+	 0x01cf,
+	 0x01d0},
+	{
+	 134, 5670, 0x62, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x37, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x03, 0x23, 0x00, 0x60, 0x08e0, 0x08dc, 0x08d8, 0x01ce,
+	 0x01ce,
+	 0x01cf},
+	{
+	 136, 5680, 0x65, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x38, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e4, 0x08e0, 0x08dc, 0x01cd,
+	 0x01ce,
+	 0x01ce},
+	{
+	 138, 5690, 0x68, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x39, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x00,
+	 0x00, 0x09, 0x02, 0x23, 0x00, 0x60, 0x08e8, 0x08e4, 0x08e0, 0x01cc,
+	 0x01cd,
+	 0x01ce},
+	{
+	 140, 5700, 0x6c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3a, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08ec, 0x08e8, 0x08e4, 0x01cb,
+	 0x01cc,
+	 0x01cd},
+	{
+	 142, 5710, 0x6f, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3b, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f0, 0x08ec, 0x08e8, 0x01ca,
+	 0x01cb,
+	 0x01cc},
+	{
+	 144, 5720, 0x72, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3c, 0x02, 0x07,
+	 0x00, 0x07, 0x00, 0x77, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f4, 0x08f0, 0x08ec, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 145, 5725, 0x74, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x79, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f6, 0x08f2, 0x08ee, 0x01c9,
+	 0x01ca,
+	 0x01cb},
+	{
+	 146, 5730, 0x76, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3d, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08f8, 0x08f4, 0x08f0, 0x01c9,
+	 0x01c9,
+	 0x01ca},
+	{
+	 147, 5735, 0x77, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7b, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fa, 0x08f6, 0x08f2, 0x01c8,
+	 0x01c9,
+	 0x01ca},
+	{
+	 148, 5740, 0x79, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3e, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fc, 0x08f8, 0x08f4, 0x01c8,
+	 0x01c9,
+	 0x01c9},
+	{
+	 149, 5745, 0x7b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7d, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x30, 0x08fe, 0x08fa, 0x08f6, 0x01c8,
+	 0x01c8,
+	 0x01c9},
+	{
+	 150, 5750, 0x7c, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x3f, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0900, 0x08fc, 0x08f8, 0x01c7,
+	 0x01c8,
+	 0x01c9},
+	{
+	 151, 5755, 0x7e, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x7f, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0902, 0x08fe, 0x08fa, 0x01c7,
+	 0x01c8,
+	 0x01c8},
+	{
+	 152, 5760, 0x80, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x40, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0904, 0x0900, 0x08fc, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 153, 5765, 0x81, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x81, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0906, 0x0902, 0x08fe, 0x01c6,
+	 0x01c7,
+	 0x01c8},
+	{
+	 154, 5770, 0x83, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x41, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0908, 0x0904, 0x0900, 0x01c6,
+	 0x01c6,
+	 0x01c7},
+	{
+	 155, 5775, 0x85, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x83, 0x04, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090a, 0x0906, 0x0902, 0x01c5,
+	 0x01c6,
+	 0x01c7},
+	{
+	 156, 5780, 0x86, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x42, 0x02, 0x06,
+	 0x00, 0x06, 0x00, 0x66, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090c, 0x0908, 0x0904, 0x01c5,
+	 0x01c6,
+	 0x01c6},
+	{
+	 157, 5785, 0x88, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x85, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x090e, 0x090a, 0x0906, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 158, 5790, 0x8a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x43, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0910, 0x090c, 0x0908, 0x01c4,
+	 0x01c5,
+	 0x01c6},
+	{
+	 159, 5795, 0x8b, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x87, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x02, 0x13, 0x00, 0x00, 0x0912, 0x090e, 0x090a, 0x01c4,
+	 0x01c4,
+	 0x01c5},
+	{
+	 160, 5800, 0x8d, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x44, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x08, 0x01, 0x03, 0x00, 0x00, 0x0914, 0x0910, 0x090c, 0x01c3,
+	 0x01c4,
+	 0x01c5},
+	{
+	 161, 5805, 0x8f, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x89, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0916, 0x0912, 0x090e, 0x01c3,
+	 0x01c4,
+	 0x01c4},
+	{
+	 162, 5810, 0x90, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x45, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0918, 0x0914, 0x0910, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 163, 5815, 0x92, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8b, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091a, 0x0916, 0x0912, 0x01c2,
+	 0x01c3,
+	 0x01c4},
+	{
+	 164, 5820, 0x94, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x46, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091c, 0x0918, 0x0914, 0x01c2,
+	 0x01c2,
+	 0x01c3},
+	{
+	 165, 5825, 0x95, 0x17, 0x20, 0x14, 0x08, 0x08, 0x30, 0x8d, 0x04, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x091e, 0x091a, 0x0916, 0x01c1,
+	 0x01c2,
+	 0x01c3},
+	{
+	 166, 5830, 0x97, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x47, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0920, 0x091c, 0x0918, 0x01c1,
+	 0x01c2,
+	 0x01c2},
+	{
+	 168, 5840, 0x9a, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x48, 0x02, 0x05,
+	 0x00, 0x05, 0x00, 0x55, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0924, 0x0920, 0x091c, 0x01c0,
+	 0x01c1,
+	 0x01c2},
+	{
+	 170, 5850, 0x9e, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x49, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0928, 0x0924, 0x0920, 0x01bf,
+	 0x01c0,
+	 0x01c1},
+	{
+	 172, 5860, 0xa1, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4a, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x092c, 0x0928, 0x0924, 0x01bf,
+	 0x01bf,
+	 0x01c0},
+	{
+	 174, 5870, 0xa4, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4b, 0x02, 0x04,
+	 0x00, 0x04, 0x00, 0x44, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0930, 0x092c, 0x0928, 0x01be,
+	 0x01bf,
+	 0x01bf},
+	{
+	 176, 5880, 0xa8, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4c, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0934, 0x0930, 0x092c, 0x01bd,
+	 0x01be,
+	 0x01bf},
+	{
+	 178, 5890, 0xab, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4d, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x0938, 0x0934, 0x0930, 0x01bc,
+	 0x01bd,
+	 0x01be},
+	{
+	 180, 5900, 0xae, 0x17, 0x10, 0x0c, 0x0c, 0x0c, 0x30, 0x4e, 0x02, 0x03,
+	 0x00, 0x03, 0x00, 0x33, 0x00, 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x00,
+	 0x00, 0x06, 0x01, 0x03, 0x00, 0x00, 0x093c, 0x0938, 0x0934, 0x01bc,
+	 0x01bc,
+	 0x01bd},
+	{
+	 1, 2412, 0x48, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x6c, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03c9, 0x03c5, 0x03c1, 0x043a,
+	 0x043f,
+	 0x0443},
+	{
+	 2, 2417, 0x4b, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x71, 0x09, 0x0f,
+	 0x0a, 0x00, 0x0a, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cb, 0x03c7, 0x03c3, 0x0438,
+	 0x043d,
+	 0x0441},
+	{
+	 3, 2422, 0x4e, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x76, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cd, 0x03c9, 0x03c5, 0x0436,
+	 0x043a,
+	 0x043f},
+	{
+	 4, 2427, 0x52, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x7b, 0x09, 0x0f,
+	 0x09, 0x00, 0x09, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03cf, 0x03cb, 0x03c7, 0x0434,
+	 0x0438,
+	 0x043d},
+	{
+	 5, 2432, 0x55, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x80, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d1, 0x03cd, 0x03c9, 0x0431,
+	 0x0436,
+	 0x043a},
+	{
+	 6, 2437, 0x58, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x85, 0x09, 0x0f,
+	 0x08, 0x00, 0x08, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d3, 0x03cf, 0x03cb, 0x042f,
+	 0x0434,
+	 0x0438},
+	{
+	 7, 2442, 0x5c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8a, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d5, 0x03d1, 0x03cd, 0x042d,
+	 0x0431,
+	 0x0436},
+	{
+	 8, 2447, 0x5f, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x8f, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d7, 0x03d3, 0x03cf, 0x042b,
+	 0x042f,
+	 0x0434},
+	{
+	 9, 2452, 0x62, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x94, 0x09, 0x0f,
+	 0x07, 0x00, 0x07, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03d9, 0x03d5, 0x03d1, 0x0429,
+	 0x042d,
+	 0x0431},
+	{
+	 10, 2457, 0x66, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x99, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03db, 0x03d7, 0x03d3, 0x0427,
+	 0x042b,
+	 0x042f},
+	{
+	 11, 2462, 0x69, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0x9e, 0x09, 0x0f,
+	 0x06, 0x00, 0x06, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03dd, 0x03d9, 0x03d5, 0x0424,
+	 0x0429,
+	 0x042d},
+	{
+	 12, 2467, 0x6c, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa3, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03df, 0x03db, 0x03d7, 0x0422,
+	 0x0427,
+	 0x042b},
+	{
+	 13, 2472, 0x70, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xa8, 0x09, 0x0f,
+	 0x05, 0x00, 0x05, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xf0, 0x00, 0x03e1, 0x03dd, 0x03d9, 0x0420,
+	 0x0424,
+	 0x0429},
+	{
+	 14, 2484, 0x78, 0x16, 0x30, 0x1b, 0x0a, 0x0a, 0x30, 0xb4, 0x09, 0x0f,
+	 0x04, 0x00, 0x04, 0x00, 0x61, 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x61,
+	 0x73, 0x00, 0x00, 0x00, 0xe0, 0x00, 0x03e6, 0x03e2, 0x03de, 0x041b,
+	 0x041f,
+	 0x0424}
+};
+
+radio_regs_t regs_2055[] = {
+	{0x02, 0x80, 0x80, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0x27, 0x27, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0x27, 0x27, 0, 0},
+	{0x07, 0x7f, 0x7f, 1, 1},
+	{0x08, 0x7, 0x7, 1, 1},
+	{0x09, 0x7f, 0x7f, 1, 1},
+	{0x0A, 0x7, 0x7, 1, 1},
+	{0x0B, 0x15, 0x15, 0, 0},
+	{0x0C, 0x15, 0x15, 0, 0},
+	{0x0D, 0x4f, 0x4f, 1, 1},
+	{0x0E, 0x5, 0x5, 1, 1},
+	{0x0F, 0x4f, 0x4f, 1, 1},
+	{0x10, 0x5, 0x5, 1, 1},
+	{0x11, 0xd0, 0xd0, 0, 0},
+	{0x12, 0x2, 0x2, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0x40, 0x40, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0xc0, 0xc0, 0, 0},
+	{0x1E, 0xff, 0xff, 0, 0},
+	{0x1F, 0xc0, 0xc0, 0, 0},
+	{0x20, 0xff, 0xff, 0, 0},
+	{0x21, 0xc0, 0xc0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x2c, 0x2c, 0, 0},
+	{0x24, 0, 0, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0xa4, 0xa4, 0, 0},
+	{0x2E, 0x38, 0x38, 0, 0},
+	{0x2F, 0, 0, 0, 0},
+	{0x30, 0x4, 0x4, 1, 1},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0xa, 0xa, 0, 0},
+	{0x33, 0x87, 0x87, 0, 0},
+	{0x34, 0x9, 0x9, 0, 0},
+	{0x35, 0x70, 0x70, 0, 0},
+	{0x36, 0x11, 0x11, 0, 0},
+	{0x37, 0x18, 0x18, 1, 1},
+	{0x38, 0x6, 0x6, 0, 0},
+	{0x39, 0x4, 0x4, 1, 1},
+	{0x3A, 0x6, 0x6, 0, 0},
+	{0x3B, 0x9e, 0x9e, 0, 0},
+	{0x3C, 0x9, 0x9, 0, 0},
+	{0x3D, 0xc8, 0xc8, 1, 1},
+	{0x3E, 0x88, 0x88, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0, 0, 0, 0},
+	{0x42, 0x1, 0x1, 0, 0},
+	{0x43, 0x2, 0x2, 0, 0},
+	{0x44, 0x96, 0x96, 0, 0},
+	{0x45, 0x3e, 0x3e, 0, 0},
+	{0x46, 0x3e, 0x3e, 0, 0},
+	{0x47, 0x13, 0x13, 0, 0},
+	{0x48, 0x2, 0x2, 0, 0},
+	{0x49, 0x15, 0x15, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0, 0, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0, 0, 0, 0},
+	{0x50, 0x8, 0x8, 0, 0},
+	{0x51, 0x8, 0x8, 0, 0},
+	{0x52, 0x6, 0x6, 0, 0},
+	{0x53, 0x84, 0x84, 1, 1},
+	{0x54, 0xc3, 0xc3, 0, 0},
+	{0x55, 0x8f, 0x8f, 0, 0},
+	{0x56, 0xff, 0xff, 0, 0},
+	{0x57, 0xff, 0xff, 0, 0},
+	{0x58, 0x88, 0x88, 0, 0},
+	{0x59, 0x88, 0x88, 0, 0},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0xcc, 0xcc, 0, 0},
+	{0x5C, 0x6, 0x6, 0, 0},
+	{0x5D, 0x80, 0x80, 0, 0},
+	{0x5E, 0x80, 0x80, 0, 0},
+	{0x5F, 0xf8, 0xf8, 0, 0},
+	{0x60, 0x88, 0x88, 0, 0},
+	{0x61, 0x88, 0x88, 0, 0},
+	{0x62, 0x88, 0x8, 1, 1},
+	{0x63, 0x88, 0x88, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0x1, 0x1, 1, 1},
+	{0x66, 0x8a, 0x8a, 0, 0},
+	{0x67, 0x8, 0x8, 0, 0},
+	{0x68, 0x83, 0x83, 0, 0},
+	{0x69, 0x6, 0x6, 0, 0},
+	{0x6A, 0xa0, 0xa0, 0, 0},
+	{0x6B, 0xa, 0xa, 0, 0},
+	{0x6C, 0x87, 0x87, 1, 1},
+	{0x6D, 0x2a, 0x2a, 0, 0},
+	{0x6E, 0x2a, 0x2a, 0, 0},
+	{0x6F, 0x2a, 0x2a, 0, 0},
+	{0x70, 0x2a, 0x2a, 0, 0},
+	{0x71, 0x18, 0x18, 0, 0},
+	{0x72, 0x6a, 0x6a, 1, 1},
+	{0x73, 0xab, 0xab, 1, 1},
+	{0x74, 0x13, 0x13, 1, 1},
+	{0x75, 0xc1, 0xc1, 1, 1},
+	{0x76, 0xaa, 0xaa, 1, 1},
+	{0x77, 0x87, 0x87, 1, 1},
+	{0x78, 0, 0, 0, 0},
+	{0x79, 0x6, 0x6, 0, 0},
+	{0x7A, 0x7, 0x7, 0, 0},
+	{0x7B, 0x7, 0x7, 0, 0},
+	{0x7C, 0x15, 0x15, 0, 0},
+	{0x7D, 0x55, 0x55, 0, 0},
+	{0x7E, 0x97, 0x97, 1, 1},
+	{0x7F, 0x8, 0x8, 0, 0},
+	{0x80, 0x14, 0x14, 1, 1},
+	{0x81, 0x33, 0x33, 0, 0},
+	{0x82, 0x88, 0x88, 0, 0},
+	{0x83, 0x6, 0x6, 0, 0},
+	{0x84, 0x3, 0x3, 1, 1},
+	{0x85, 0xa, 0xa, 0, 0},
+	{0x86, 0x3, 0x3, 1, 1},
+	{0x87, 0x2a, 0x2a, 0, 0},
+	{0x88, 0xa4, 0xa4, 0, 0},
+	{0x89, 0x18, 0x18, 0, 0},
+	{0x8A, 0x28, 0x28, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0x4a, 0x4a, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0xf8, 0xf8, 0, 0},
+	{0x8F, 0x88, 0x88, 0, 0},
+	{0x90, 0x88, 0x88, 0, 0},
+	{0x91, 0x88, 0x8, 1, 1},
+	{0x92, 0x88, 0x88, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0x1, 0x1, 1, 1},
+	{0x95, 0x8a, 0x8a, 0, 0},
+	{0x96, 0x8, 0x8, 0, 0},
+	{0x97, 0x83, 0x83, 0, 0},
+	{0x98, 0x6, 0x6, 0, 0},
+	{0x99, 0xa0, 0xa0, 0, 0},
+	{0x9A, 0xa, 0xa, 0, 0},
+	{0x9B, 0x87, 0x87, 1, 1},
+	{0x9C, 0x2a, 0x2a, 0, 0},
+	{0x9D, 0x2a, 0x2a, 0, 0},
+	{0x9E, 0x2a, 0x2a, 0, 0},
+	{0x9F, 0x2a, 0x2a, 0, 0},
+	{0xA0, 0x18, 0x18, 0, 0},
+	{0xA1, 0x6a, 0x6a, 1, 1},
+	{0xA2, 0xab, 0xab, 1, 1},
+	{0xA3, 0x13, 0x13, 1, 1},
+	{0xA4, 0xc1, 0xc1, 1, 1},
+	{0xA5, 0xaa, 0xaa, 1, 1},
+	{0xA6, 0x87, 0x87, 1, 1},
+	{0xA7, 0, 0, 0, 0},
+	{0xA8, 0x6, 0x6, 0, 0},
+	{0xA9, 0x7, 0x7, 0, 0},
+	{0xAA, 0x7, 0x7, 0, 0},
+	{0xAB, 0x15, 0x15, 0, 0},
+	{0xAC, 0x55, 0x55, 0, 0},
+	{0xAD, 0x97, 0x97, 1, 1},
+	{0xAE, 0x8, 0x8, 0, 0},
+	{0xAF, 0x14, 0x14, 1, 1},
+	{0xB0, 0x33, 0x33, 0, 0},
+	{0xB1, 0x88, 0x88, 0, 0},
+	{0xB2, 0x6, 0x6, 0, 0},
+	{0xB3, 0x3, 0x3, 1, 1},
+	{0xB4, 0xa, 0xa, 0, 0},
+	{0xB5, 0x3, 0x3, 1, 1},
+	{0xB6, 0x2a, 0x2a, 0, 0},
+	{0xB7, 0xa4, 0xa4, 0, 0},
+	{0xB8, 0x18, 0x18, 0, 0},
+	{0xB9, 0x28, 0x28, 0, 0},
+	{0xBA, 0, 0, 0, 0},
+	{0xBB, 0x4a, 0x4a, 0, 0},
+	{0xBC, 0, 0, 0, 0},
+	{0xBD, 0x71, 0x71, 0, 0},
+	{0xBE, 0x72, 0x72, 0, 0},
+	{0xBF, 0x73, 0x73, 0, 0},
+	{0xC0, 0x74, 0x74, 0, 0},
+	{0xC1, 0x75, 0x75, 0, 0},
+	{0xC2, 0x76, 0x76, 0, 0},
+	{0xC3, 0x77, 0x77, 0, 0},
+	{0xC4, 0x78, 0x78, 0, 0},
+	{0xC5, 0x79, 0x79, 0, 0},
+	{0xC6, 0x7a, 0x7a, 0, 0},
+	{0xC7, 0, 0, 0, 0},
+	{0xC8, 0, 0, 0, 0},
+	{0xC9, 0, 0, 0, 0},
+	{0xCA, 0, 0, 0, 0},
+	{0xCB, 0, 0, 0, 0},
+	{0xCC, 0, 0, 0, 0},
+	{0xCD, 0, 0, 0, 0},
+	{0xCE, 0x6, 0x6, 0, 0},
+	{0xCF, 0, 0, 0, 0},
+	{0xD0, 0, 0, 0, 0},
+	{0xD1, 0x18, 0x18, 0, 0},
+	{0xD2, 0x88, 0x88, 0, 0},
+	{0xD3, 0, 0, 0, 0},
+	{0xD4, 0, 0, 0, 0},
+	{0xD5, 0, 0, 0, 0},
+	{0xD6, 0, 0, 0, 0},
+	{0xD7, 0, 0, 0, 0},
+	{0xD8, 0, 0, 0, 0},
+	{0xD9, 0, 0, 0, 0},
+	{0xDA, 0x6, 0x6, 0, 0},
+	{0xDB, 0, 0, 0, 0},
+	{0xDC, 0, 0, 0, 0},
+	{0xDD, 0x18, 0x18, 0, 0},
+	{0xDE, 0x88, 0x88, 0, 0},
+	{0xDF, 0, 0, 0, 0},
+	{0xE0, 0, 0, 0, 0},
+	{0xE1, 0, 0, 0, 0},
+	{0xE2, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_SYN_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x74, 0x74, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x99, 0x99, 0, 0},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x99, 0x99, 0, 0},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x66, 0x66, 0, 0},
+	{0x50, 0x66, 0x66, 0, 0},
+	{0x51, 0x57, 0x57, 0, 0},
+	{0x52, 0x57, 0x57, 0, 0},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x23, 0x23, 0, 0},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0x2, 0x2, 0, 0},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0xd, 0xd, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0x72, 0x72, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056_A1[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x44, 0x44, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0xf, 0xf, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0x50, 0x50, 1, 1},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x2f, 0x2f, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0x11, 0x11, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0xf, 0xf, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x2d, 0x2d, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056_rev5[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_TX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_RX_2056_rev6[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0}
+};
+
+radio_regs_t regs_SYN_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_TX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x71, 0x71, 1, 1},
+	{0x96, 0x71, 0x71, 1, 1},
+	{0x97, 0x72, 0x72, 1, 1},
+	{0x98, 0x73, 0x73, 1, 1},
+	{0x99, 0x74, 0x74, 1, 1},
+	{0x9A, 0x75, 0x75, 1, 1},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_RX_2056_rev7[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 1, 1},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0, 0, 1, 1},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_SYN_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x4, 0x4, 0, 0},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x30, 0x30, 0, 0},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0xd, 0xd, 0, 0},
+	{0x4C, 0xd, 0xd, 0, 0},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x6, 0x6, 0, 0},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_TX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_RX_2056_rev8[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_SYN_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0x1, 0x1, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0x60, 0x60, 0, 0},
+	{0x23, 0x6, 0x6, 0, 0},
+	{0x24, 0xc, 0xc, 0, 0},
+	{0x25, 0, 0, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0, 0, 0, 0},
+	{0x28, 0x1, 0x1, 0, 0},
+	{0x29, 0, 0, 0, 0},
+	{0x2A, 0, 0, 0, 0},
+	{0x2B, 0, 0, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0, 0, 0, 0},
+	{0x2F, 0x1f, 0x1f, 0, 0},
+	{0x30, 0x15, 0x15, 0, 0},
+	{0x31, 0xf, 0xf, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0, 0, 0, 0},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0, 0, 0, 0},
+	{0x38, 0, 0, 0, 0},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0, 0, 0, 0},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x13, 0x13, 0, 0},
+	{0x3D, 0xf, 0xf, 0, 0},
+	{0x3E, 0x18, 0x18, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x20, 0x20, 0, 0},
+	{0x42, 0x20, 0x20, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x77, 0x77, 0, 0},
+	{0x45, 0x7, 0x7, 0, 0},
+	{0x46, 0x1, 0x1, 0, 0},
+	{0x47, 0x6, 0x6, 1, 1},
+	{0x48, 0xf, 0xf, 0, 0},
+	{0x49, 0x3f, 0x3f, 1, 1},
+	{0x4A, 0x32, 0x32, 0, 0},
+	{0x4B, 0x6, 0x6, 1, 1},
+	{0x4C, 0x6, 0x6, 1, 1},
+	{0x4D, 0x4, 0x4, 0, 0},
+	{0x4E, 0x2b, 0x2b, 1, 1},
+	{0x4F, 0x1, 0x1, 0, 0},
+	{0x50, 0x1c, 0x1c, 0, 0},
+	{0x51, 0x2, 0x2, 0, 0},
+	{0x52, 0x2, 0x2, 0, 0},
+	{0x53, 0xf7, 0xf7, 1, 1},
+	{0x54, 0xb4, 0xb4, 0, 0},
+	{0x55, 0xd2, 0xd2, 0, 0},
+	{0x56, 0, 0, 0, 0},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x4, 0x4, 0, 0},
+	{0x59, 0x96, 0x96, 0, 0},
+	{0x5A, 0x3e, 0x3e, 0, 0},
+	{0x5B, 0x3e, 0x3e, 0, 0},
+	{0x5C, 0x13, 0x13, 0, 0},
+	{0x5D, 0x2, 0x2, 0, 0},
+	{0x5E, 0, 0, 0, 0},
+	{0x5F, 0x7, 0x7, 0, 0},
+	{0x60, 0x7, 0x7, 1, 1},
+	{0x61, 0x8, 0x8, 0, 0},
+	{0x62, 0x3, 0x3, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0x40, 0x40, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0x1, 0x1, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0x60, 0x60, 0, 0},
+	{0x71, 0x66, 0x66, 0, 0},
+	{0x72, 0xc, 0xc, 0, 0},
+	{0x73, 0x66, 0x66, 0, 0},
+	{0x74, 0x8f, 0x8f, 1, 1},
+	{0x75, 0, 0, 0, 0},
+	{0x76, 0xcc, 0xcc, 0, 0},
+	{0x77, 0x1, 0x1, 0, 0},
+	{0x78, 0x66, 0x66, 0, 0},
+	{0x79, 0x66, 0x66, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0, 0, 0, 0},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0xff, 0xff, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0x95, 0, 0, 0, 0},
+	{0x96, 0, 0, 0, 0},
+	{0x97, 0, 0, 0, 0},
+	{0x98, 0, 0, 0, 0},
+	{0x99, 0, 0, 0, 0},
+	{0x9A, 0, 0, 0, 0},
+	{0x9B, 0, 0, 0, 0},
+	{0x9C, 0, 0, 0, 0},
+	{0x9D, 0, 0, 0, 0},
+	{0x9E, 0, 0, 0, 0},
+	{0x9F, 0x6, 0x6, 0, 0},
+	{0xA0, 0x66, 0x66, 0, 0},
+	{0xA1, 0x66, 0x66, 0, 0},
+	{0xA2, 0x66, 0x66, 0, 0},
+	{0xA3, 0x66, 0x66, 0, 0},
+	{0xA4, 0x66, 0x66, 0, 0},
+	{0xA5, 0x66, 0x66, 0, 0},
+	{0xA6, 0x66, 0x66, 0, 0},
+	{0xA7, 0x66, 0x66, 0, 0},
+	{0xA8, 0x66, 0x66, 0, 0},
+	{0xA9, 0x66, 0x66, 0, 0},
+	{0xAA, 0x66, 0x66, 0, 0},
+	{0xAB, 0x66, 0x66, 0, 0},
+	{0xAC, 0x66, 0x66, 0, 0},
+	{0xAD, 0x66, 0x66, 0, 0},
+	{0xAE, 0x66, 0x66, 0, 0},
+	{0xAF, 0x66, 0x66, 0, 0},
+	{0xB0, 0x66, 0x66, 0, 0},
+	{0xB1, 0x66, 0x66, 0, 0},
+	{0xB2, 0x66, 0x66, 0, 0},
+	{0xB3, 0xa, 0xa, 0, 0},
+	{0xB4, 0, 0, 0, 0},
+	{0xB5, 0, 0, 0, 0},
+	{0xB6, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_TX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0, 0, 0, 0},
+	{0x21, 0x88, 0x88, 0, 0},
+	{0x22, 0x88, 0x88, 0, 0},
+	{0x23, 0x88, 0x88, 0, 0},
+	{0x24, 0x88, 0x88, 0, 0},
+	{0x25, 0xc, 0xc, 0, 0},
+	{0x26, 0, 0, 0, 0},
+	{0x27, 0x3, 0x3, 0, 0},
+	{0x28, 0, 0, 0, 0},
+	{0x29, 0x3, 0x3, 0, 0},
+	{0x2A, 0x37, 0x37, 0, 0},
+	{0x2B, 0x3, 0x3, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0, 0, 0, 0},
+	{0x2E, 0x1, 0x1, 0, 0},
+	{0x2F, 0x1, 0x1, 0, 0},
+	{0x30, 0, 0, 0, 0},
+	{0x31, 0, 0, 0, 0},
+	{0x32, 0, 0, 0, 0},
+	{0x33, 0x11, 0x11, 0, 0},
+	{0x34, 0xee, 0xee, 1, 1},
+	{0x35, 0, 0, 0, 0},
+	{0x36, 0, 0, 0, 0},
+	{0x37, 0x3, 0x3, 0, 0},
+	{0x38, 0x50, 0x50, 1, 1},
+	{0x39, 0, 0, 0, 0},
+	{0x3A, 0x50, 0x50, 1, 1},
+	{0x3B, 0, 0, 0, 0},
+	{0x3C, 0x6e, 0x6e, 0, 0},
+	{0x3D, 0xf0, 0xf0, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0, 0, 0, 0},
+	{0x40, 0, 0, 0, 0},
+	{0x41, 0x3, 0x3, 0, 0},
+	{0x42, 0x3, 0x3, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x1e, 0x1e, 0, 0},
+	{0x45, 0, 0, 0, 0},
+	{0x46, 0x6e, 0x6e, 0, 0},
+	{0x47, 0xf0, 0xf0, 1, 1},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x2, 0x2, 0, 0},
+	{0x4A, 0xff, 0xff, 1, 1},
+	{0x4B, 0xc, 0xc, 0, 0},
+	{0x4C, 0, 0, 0, 0},
+	{0x4D, 0x38, 0x38, 0, 0},
+	{0x4E, 0x70, 0x70, 1, 1},
+	{0x4F, 0x2, 0x2, 0, 0},
+	{0x50, 0x88, 0x88, 0, 0},
+	{0x51, 0xc, 0xc, 0, 0},
+	{0x52, 0, 0, 0, 0},
+	{0x53, 0x8, 0x8, 0, 0},
+	{0x54, 0x70, 0x70, 1, 1},
+	{0x55, 0x2, 0x2, 0, 0},
+	{0x56, 0xff, 0xff, 1, 1},
+	{0x57, 0, 0, 0, 0},
+	{0x58, 0x83, 0x83, 0, 0},
+	{0x59, 0x77, 0x77, 1, 1},
+	{0x5A, 0, 0, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x88, 0x88, 0, 0},
+	{0x5D, 0, 0, 0, 0},
+	{0x5E, 0x8, 0x8, 0, 0},
+	{0x5F, 0x77, 0x77, 1, 1},
+	{0x60, 0x1, 0x1, 0, 0},
+	{0x61, 0, 0, 0, 0},
+	{0x62, 0x7, 0x7, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0x7, 0x7, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 1, 1},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0xa, 0xa, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0, 0, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0x2, 0x2, 0, 0},
+	{0x72, 0, 0, 0, 0},
+	{0x73, 0, 0, 0, 0},
+	{0x74, 0xe, 0xe, 0, 0},
+	{0x75, 0xe, 0xe, 0, 0},
+	{0x76, 0xe, 0xe, 0, 0},
+	{0x77, 0x13, 0x13, 0, 0},
+	{0x78, 0x13, 0x13, 0, 0},
+	{0x79, 0x1b, 0x1b, 0, 0},
+	{0x7A, 0x1b, 0x1b, 0, 0},
+	{0x7B, 0x55, 0x55, 0, 0},
+	{0x7C, 0x5b, 0x5b, 0, 0},
+	{0x7D, 0x30, 0x30, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0x70, 0x70, 0, 0},
+	{0x94, 0x70, 0x70, 0, 0},
+	{0x95, 0x70, 0x70, 0, 0},
+	{0x96, 0x70, 0x70, 0, 0},
+	{0x97, 0x70, 0x70, 0, 0},
+	{0x98, 0x70, 0x70, 0, 0},
+	{0x99, 0x70, 0x70, 0, 0},
+	{0x9A, 0x70, 0x70, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_regs_t regs_RX_2056_rev11[] = {
+	{0x02, 0, 0, 0, 0},
+	{0x03, 0, 0, 0, 0},
+	{0x04, 0, 0, 0, 0},
+	{0x05, 0, 0, 0, 0},
+	{0x06, 0, 0, 0, 0},
+	{0x07, 0, 0, 0, 0},
+	{0x08, 0, 0, 0, 0},
+	{0x09, 0, 0, 0, 0},
+	{0x0A, 0, 0, 0, 0},
+	{0x0B, 0, 0, 0, 0},
+	{0x0C, 0, 0, 0, 0},
+	{0x0D, 0, 0, 0, 0},
+	{0x0E, 0, 0, 0, 0},
+	{0x0F, 0, 0, 0, 0},
+	{0x10, 0, 0, 0, 0},
+	{0x11, 0, 0, 0, 0},
+	{0x12, 0, 0, 0, 0},
+	{0x13, 0, 0, 0, 0},
+	{0x14, 0, 0, 0, 0},
+	{0x15, 0, 0, 0, 0},
+	{0x16, 0, 0, 0, 0},
+	{0x17, 0, 0, 0, 0},
+	{0x18, 0, 0, 0, 0},
+	{0x19, 0, 0, 0, 0},
+	{0x1A, 0, 0, 0, 0},
+	{0x1B, 0, 0, 0, 0},
+	{0x1C, 0, 0, 0, 0},
+	{0x1D, 0, 0, 0, 0},
+	{0x1E, 0, 0, 0, 0},
+	{0x1F, 0, 0, 0, 0},
+	{0x20, 0x3, 0x3, 0, 0},
+	{0x21, 0, 0, 0, 0},
+	{0x22, 0, 0, 0, 0},
+	{0x23, 0x90, 0x90, 0, 0},
+	{0x24, 0x55, 0x55, 0, 0},
+	{0x25, 0x15, 0x15, 0, 0},
+	{0x26, 0x5, 0x5, 0, 0},
+	{0x27, 0x15, 0x15, 0, 0},
+	{0x28, 0x5, 0x5, 0, 0},
+	{0x29, 0x20, 0x20, 0, 0},
+	{0x2A, 0x11, 0x11, 0, 0},
+	{0x2B, 0x90, 0x90, 0, 0},
+	{0x2C, 0, 0, 0, 0},
+	{0x2D, 0x88, 0x88, 0, 0},
+	{0x2E, 0x32, 0x32, 0, 0},
+	{0x2F, 0x77, 0x77, 0, 0},
+	{0x30, 0x17, 0x17, 1, 1},
+	{0x31, 0xff, 0xff, 1, 1},
+	{0x32, 0x20, 0x20, 0, 0},
+	{0x33, 0, 0, 0, 0},
+	{0x34, 0x88, 0x88, 0, 0},
+	{0x35, 0x32, 0x32, 0, 0},
+	{0x36, 0x77, 0x77, 0, 0},
+	{0x37, 0x17, 0x17, 1, 1},
+	{0x38, 0xf0, 0xf0, 1, 1},
+	{0x39, 0x20, 0x20, 0, 0},
+	{0x3A, 0x8, 0x8, 0, 0},
+	{0x3B, 0x55, 0x55, 1, 1},
+	{0x3C, 0, 0, 0, 0},
+	{0x3D, 0x88, 0x88, 1, 1},
+	{0x3E, 0, 0, 0, 0},
+	{0x3F, 0x44, 0x44, 0, 0},
+	{0x40, 0x7, 0x7, 1, 1},
+	{0x41, 0x6, 0x6, 0, 0},
+	{0x42, 0x4, 0x4, 0, 0},
+	{0x43, 0, 0, 0, 0},
+	{0x44, 0x8, 0x8, 0, 0},
+	{0x45, 0x55, 0x55, 1, 1},
+	{0x46, 0, 0, 0, 0},
+	{0x47, 0x11, 0x11, 0, 0},
+	{0x48, 0, 0, 0, 0},
+	{0x49, 0x44, 0x44, 0, 0},
+	{0x4A, 0x7, 0x7, 0, 0},
+	{0x4B, 0x6, 0x6, 0, 0},
+	{0x4C, 0x4, 0x4, 0, 0},
+	{0x4D, 0, 0, 0, 0},
+	{0x4E, 0, 0, 0, 0},
+	{0x4F, 0x26, 0x26, 1, 1},
+	{0x50, 0x26, 0x26, 1, 1},
+	{0x51, 0xf, 0xf, 1, 1},
+	{0x52, 0xf, 0xf, 1, 1},
+	{0x53, 0x44, 0x44, 0, 0},
+	{0x54, 0, 0, 0, 0},
+	{0x55, 0, 0, 0, 0},
+	{0x56, 0x8, 0x8, 0, 0},
+	{0x57, 0x8, 0x8, 0, 0},
+	{0x58, 0x7, 0x7, 0, 0},
+	{0x59, 0x22, 0x22, 0, 0},
+	{0x5A, 0x22, 0x22, 0, 0},
+	{0x5B, 0x2, 0x2, 0, 0},
+	{0x5C, 0x4, 0x4, 1, 1},
+	{0x5D, 0x7, 0x7, 0, 0},
+	{0x5E, 0x55, 0x55, 0, 0},
+	{0x5F, 0x23, 0x23, 0, 0},
+	{0x60, 0x41, 0x41, 0, 0},
+	{0x61, 0x1, 0x1, 0, 0},
+	{0x62, 0xa, 0xa, 0, 0},
+	{0x63, 0, 0, 0, 0},
+	{0x64, 0, 0, 0, 0},
+	{0x65, 0, 0, 0, 0},
+	{0x66, 0, 0, 0, 0},
+	{0x67, 0, 0, 0, 0},
+	{0x68, 0, 0, 0, 0},
+	{0x69, 0, 0, 0, 0},
+	{0x6A, 0, 0, 0, 0},
+	{0x6B, 0xc, 0xc, 0, 0},
+	{0x6C, 0, 0, 0, 0},
+	{0x6D, 0, 0, 0, 0},
+	{0x6E, 0, 0, 0, 0},
+	{0x6F, 0, 0, 0, 0},
+	{0x70, 0, 0, 0, 0},
+	{0x71, 0, 0, 0, 0},
+	{0x72, 0x22, 0x22, 0, 0},
+	{0x73, 0x22, 0x22, 0, 0},
+	{0x74, 0, 0, 1, 1},
+	{0x75, 0xa, 0xa, 0, 0},
+	{0x76, 0x1, 0x1, 0, 0},
+	{0x77, 0x22, 0x22, 0, 0},
+	{0x78, 0x30, 0x30, 0, 0},
+	{0x79, 0, 0, 0, 0},
+	{0x7A, 0, 0, 0, 0},
+	{0x7B, 0, 0, 0, 0},
+	{0x7C, 0, 0, 0, 0},
+	{0x7D, 0x5, 0x5, 1, 1},
+	{0x7E, 0, 0, 0, 0},
+	{0x7F, 0, 0, 0, 0},
+	{0x80, 0, 0, 0, 0},
+	{0x81, 0, 0, 0, 0},
+	{0x82, 0, 0, 0, 0},
+	{0x83, 0, 0, 0, 0},
+	{0x84, 0, 0, 0, 0},
+	{0x85, 0, 0, 0, 0},
+	{0x86, 0, 0, 0, 0},
+	{0x87, 0, 0, 0, 0},
+	{0x88, 0, 0, 0, 0},
+	{0x89, 0, 0, 0, 0},
+	{0x8A, 0, 0, 0, 0},
+	{0x8B, 0, 0, 0, 0},
+	{0x8C, 0, 0, 0, 0},
+	{0x8D, 0, 0, 0, 0},
+	{0x8E, 0, 0, 0, 0},
+	{0x8F, 0, 0, 0, 0},
+	{0x90, 0, 0, 0, 0},
+	{0x91, 0, 0, 0, 0},
+	{0x92, 0, 0, 0, 0},
+	{0x93, 0, 0, 0, 0},
+	{0x94, 0, 0, 0, 0},
+	{0xFFFF, 0, 0, 0, 0},
+};
+
+radio_20xx_regs_t regs_2057_rev4[] = {
+	{0x00, 0x84, 0},
+	{0x01, 0, 0},
+	{0x02, 0x60, 0},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 1},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0xf7, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x4, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x26, 1},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 1},
+	{0x3D, 0xff, 1},
+	{0x3E, 0xff, 1},
+	{0x3F, 0xff, 1},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x75, 0},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0xa8, 0},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x30, 0},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0x19, 0},
+	{0x64, 0x62, 0},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0xc8, 0},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x1e, 0},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x1e, 0},
+	{0x7C, 0x62, 0},
+	{0x7D, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x9c, 0},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 1},
+	{0x8B, 0x10, 1},
+	{0x8C, 0xf0, 1},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0xe1, 0},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 1},
+	{0xA5, 0x6d, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 1},
+	{0xA9, 0xc, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 1},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x75, 0},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0xa8, 0},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x30, 0},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0x19, 0},
+	{0xE9, 0x62, 0},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0xc8, 0},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x1e, 0},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x1e, 0},
+	{0x101, 0x62, 0},
+	{0x102, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x9c, 0},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 1},
+	{0x110, 0x10, 1},
+	{0x111, 0xf0, 1},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0xe1, 0},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 1},
+	{0x12A, 0x6d, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 1},
+	{0x12E, 0xc, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 1},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x152, 0, 0},
+	{0x153, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0x2, 1},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0xFFFF, 0, 0},
+};
+
+radio_20xx_regs_t regs_2057_rev5[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+radio_20xx_regs_t regs_2057_rev5v1[] = {
+	{0x00, 0x15, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 1},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0xc, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0x1, 1},
+	{0x1C2, 0x80, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+radio_20xx_regs_t regs_2057_rev7[] = {
+	{0x00, 0, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0x13, 1},
+	{0x65, 0, 0},
+	{0x66, 0xee, 1},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0x14, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0, 0},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0x13, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0xee, 1},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0x14, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0, 0},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+radio_20xx_regs_t regs_2057_rev8[] = {
+	{0x00, 0x8, 1},
+	{0x01, 0x57, 1},
+	{0x02, 0x20, 1},
+	{0x03, 0x1f, 0},
+	{0x04, 0x4, 0},
+	{0x05, 0x2, 0},
+	{0x06, 0x1, 0},
+	{0x07, 0x1, 0},
+	{0x08, 0x1, 0},
+	{0x09, 0x69, 0},
+	{0x0A, 0x66, 0},
+	{0x0B, 0x6, 0},
+	{0x0C, 0x18, 0},
+	{0x0D, 0x3, 0},
+	{0x0E, 0x20, 0},
+	{0x0F, 0x20, 0},
+	{0x10, 0, 0},
+	{0x11, 0x7c, 0},
+	{0x12, 0x42, 0},
+	{0x13, 0xbd, 0},
+	{0x14, 0x7, 0},
+	{0x15, 0x87, 0},
+	{0x16, 0x8, 0},
+	{0x17, 0x17, 0},
+	{0x18, 0x7, 0},
+	{0x19, 0, 0},
+	{0x1A, 0x2, 0},
+	{0x1B, 0x13, 0},
+	{0x1C, 0x3e, 0},
+	{0x1D, 0x3e, 0},
+	{0x1E, 0x96, 0},
+	{0x1F, 0x4, 0},
+	{0x20, 0, 0},
+	{0x21, 0, 0},
+	{0x22, 0x17, 0},
+	{0x23, 0x6, 0},
+	{0x24, 0x1, 0},
+	{0x25, 0x6, 0},
+	{0x26, 0x4, 0},
+	{0x27, 0xd, 0},
+	{0x28, 0xd, 0},
+	{0x29, 0x30, 0},
+	{0x2A, 0x32, 0},
+	{0x2B, 0x8, 0},
+	{0x2C, 0x1c, 0},
+	{0x2D, 0x2, 0},
+	{0x2E, 0x4, 0},
+	{0x2F, 0x7f, 0},
+	{0x30, 0x27, 0},
+	{0x31, 0, 1},
+	{0x32, 0, 1},
+	{0x33, 0, 1},
+	{0x34, 0, 0},
+	{0x35, 0x20, 0},
+	{0x36, 0x18, 0},
+	{0x37, 0x7, 0},
+	{0x38, 0x66, 0},
+	{0x39, 0x66, 0},
+	{0x3A, 0x66, 0},
+	{0x3B, 0x66, 0},
+	{0x3C, 0xff, 0},
+	{0x3D, 0xff, 0},
+	{0x3E, 0xff, 0},
+	{0x3F, 0xff, 0},
+	{0x40, 0x16, 0},
+	{0x41, 0x7, 0},
+	{0x42, 0x19, 0},
+	{0x43, 0x7, 0},
+	{0x44, 0x6, 0},
+	{0x45, 0x3, 0},
+	{0x46, 0x1, 0},
+	{0x47, 0x7, 0},
+	{0x48, 0x33, 0},
+	{0x49, 0x5, 0},
+	{0x4A, 0x77, 0},
+	{0x4B, 0x66, 0},
+	{0x4C, 0x66, 0},
+	{0x4D, 0, 0},
+	{0x4E, 0x4, 0},
+	{0x4F, 0xc, 0},
+	{0x50, 0, 0},
+	{0x51, 0x70, 1},
+	{0x56, 0x7, 0},
+	{0x57, 0, 0},
+	{0x58, 0, 0},
+	{0x59, 0x88, 1},
+	{0x5A, 0, 0},
+	{0x5B, 0x1f, 0},
+	{0x5C, 0x20, 1},
+	{0x5D, 0x1, 0},
+	{0x5E, 0x30, 0},
+	{0x5F, 0x70, 0},
+	{0x60, 0, 0},
+	{0x61, 0, 0},
+	{0x62, 0x33, 1},
+	{0x63, 0xf, 1},
+	{0x64, 0xf, 1},
+	{0x65, 0, 0},
+	{0x66, 0x11, 0},
+	{0x69, 0, 0},
+	{0x6A, 0x7e, 0},
+	{0x6B, 0x3f, 0},
+	{0x6C, 0x7f, 0},
+	{0x6D, 0x78, 0},
+	{0x6E, 0x58, 1},
+	{0x6F, 0x88, 0},
+	{0x70, 0x8, 0},
+	{0x71, 0xf, 0},
+	{0x72, 0xbc, 0},
+	{0x73, 0x8, 0},
+	{0x74, 0x60, 0},
+	{0x75, 0x13, 1},
+	{0x76, 0x70, 0},
+	{0x77, 0, 0},
+	{0x78, 0, 0},
+	{0x79, 0, 0},
+	{0x7A, 0x33, 0},
+	{0x7B, 0x13, 1},
+	{0x7C, 0xf, 1},
+	{0x7D, 0xee, 1},
+	{0x80, 0x3c, 0},
+	{0x81, 0x1, 1},
+	{0x82, 0xa, 0},
+	{0x83, 0x9d, 0},
+	{0x84, 0xa, 0},
+	{0x85, 0, 0},
+	{0x86, 0x40, 0},
+	{0x87, 0x40, 0},
+	{0x88, 0x88, 0},
+	{0x89, 0x10, 0},
+	{0x8A, 0xf0, 0},
+	{0x8B, 0x10, 0},
+	{0x8C, 0xf0, 0},
+	{0x8D, 0, 0},
+	{0x8E, 0, 0},
+	{0x8F, 0x10, 0},
+	{0x90, 0x55, 0},
+	{0x91, 0x3f, 1},
+	{0x92, 0x36, 1},
+	{0x93, 0, 0},
+	{0x94, 0, 0},
+	{0x95, 0, 0},
+	{0x96, 0x87, 0},
+	{0x97, 0x11, 0},
+	{0x98, 0, 0},
+	{0x99, 0x33, 0},
+	{0x9A, 0x88, 0},
+	{0x9B, 0, 0},
+	{0x9C, 0x87, 0},
+	{0x9D, 0x11, 0},
+	{0x9E, 0, 0},
+	{0x9F, 0x33, 0},
+	{0xA0, 0x88, 0},
+	{0xA1, 0x20, 1},
+	{0xA2, 0x3f, 0},
+	{0xA3, 0x44, 0},
+	{0xA4, 0x8c, 0},
+	{0xA5, 0x6c, 0},
+	{0xA6, 0x22, 0},
+	{0xA7, 0xbe, 0},
+	{0xA8, 0x55, 0},
+	{0xAA, 0xc, 0},
+	{0xAB, 0xaa, 0},
+	{0xAC, 0x2, 0},
+	{0xAD, 0, 0},
+	{0xAE, 0x10, 0},
+	{0xAF, 0x1, 0},
+	{0xB0, 0, 0},
+	{0xB1, 0, 0},
+	{0xB2, 0x80, 0},
+	{0xB3, 0x60, 0},
+	{0xB4, 0x44, 0},
+	{0xB5, 0x55, 0},
+	{0xB6, 0x1, 0},
+	{0xB7, 0x55, 0},
+	{0xB8, 0x1, 0},
+	{0xB9, 0x5, 0},
+	{0xBA, 0x55, 0},
+	{0xBB, 0x55, 0},
+	{0xC1, 0, 0},
+	{0xC2, 0, 0},
+	{0xC3, 0, 0},
+	{0xC4, 0, 0},
+	{0xC5, 0, 0},
+	{0xC6, 0, 0},
+	{0xC7, 0, 0},
+	{0xC8, 0, 0},
+	{0xC9, 0x1, 1},
+	{0xCA, 0, 0},
+	{0xCB, 0, 0},
+	{0xCC, 0, 0},
+	{0xCD, 0, 0},
+	{0xCE, 0x5e, 0},
+	{0xCF, 0xc, 0},
+	{0xD0, 0xc, 0},
+	{0xD1, 0xc, 0},
+	{0xD2, 0, 0},
+	{0xD3, 0x2b, 0},
+	{0xD4, 0xc, 0},
+	{0xD5, 0, 0},
+	{0xD6, 0x70, 1},
+	{0xDB, 0x7, 0},
+	{0xDC, 0, 0},
+	{0xDD, 0, 0},
+	{0xDE, 0x88, 1},
+	{0xDF, 0, 0},
+	{0xE0, 0x1f, 0},
+	{0xE1, 0x20, 1},
+	{0xE2, 0x1, 0},
+	{0xE3, 0x30, 0},
+	{0xE4, 0x70, 0},
+	{0xE5, 0, 0},
+	{0xE6, 0, 0},
+	{0xE7, 0x33, 0},
+	{0xE8, 0xf, 1},
+	{0xE9, 0xf, 1},
+	{0xEA, 0, 0},
+	{0xEB, 0x11, 0},
+	{0xEE, 0, 0},
+	{0xEF, 0x7e, 0},
+	{0xF0, 0x3f, 0},
+	{0xF1, 0x7f, 0},
+	{0xF2, 0x78, 0},
+	{0xF3, 0x58, 1},
+	{0xF4, 0x88, 0},
+	{0xF5, 0x8, 0},
+	{0xF6, 0xf, 0},
+	{0xF7, 0xbc, 0},
+	{0xF8, 0x8, 0},
+	{0xF9, 0x60, 0},
+	{0xFA, 0x13, 1},
+	{0xFB, 0x70, 0},
+	{0xFC, 0, 0},
+	{0xFD, 0, 0},
+	{0xFE, 0, 0},
+	{0xFF, 0x33, 0},
+	{0x100, 0x13, 1},
+	{0x101, 0xf, 1},
+	{0x102, 0xee, 1},
+	{0x105, 0x3c, 0},
+	{0x106, 0x1, 1},
+	{0x107, 0xa, 0},
+	{0x108, 0x9d, 0},
+	{0x109, 0xa, 0},
+	{0x10A, 0, 0},
+	{0x10B, 0x40, 0},
+	{0x10C, 0x40, 0},
+	{0x10D, 0x88, 0},
+	{0x10E, 0x10, 0},
+	{0x10F, 0xf0, 0},
+	{0x110, 0x10, 0},
+	{0x111, 0xf0, 0},
+	{0x112, 0, 0},
+	{0x113, 0, 0},
+	{0x114, 0x10, 0},
+	{0x115, 0x55, 0},
+	{0x116, 0x3f, 1},
+	{0x117, 0x36, 1},
+	{0x118, 0, 0},
+	{0x119, 0, 0},
+	{0x11A, 0, 0},
+	{0x11B, 0x87, 0},
+	{0x11C, 0x11, 0},
+	{0x11D, 0, 0},
+	{0x11E, 0x33, 0},
+	{0x11F, 0x88, 0},
+	{0x120, 0, 0},
+	{0x121, 0x87, 0},
+	{0x122, 0x11, 0},
+	{0x123, 0, 0},
+	{0x124, 0x33, 0},
+	{0x125, 0x88, 0},
+	{0x126, 0x20, 1},
+	{0x127, 0x3f, 0},
+	{0x128, 0x44, 0},
+	{0x129, 0x8c, 0},
+	{0x12A, 0x6c, 0},
+	{0x12B, 0x22, 0},
+	{0x12C, 0xbe, 0},
+	{0x12D, 0x55, 0},
+	{0x12F, 0xc, 0},
+	{0x130, 0xaa, 0},
+	{0x131, 0x2, 0},
+	{0x132, 0, 0},
+	{0x133, 0x10, 0},
+	{0x134, 0x1, 0},
+	{0x135, 0, 0},
+	{0x136, 0, 0},
+	{0x137, 0x80, 0},
+	{0x138, 0x60, 0},
+	{0x139, 0x44, 0},
+	{0x13A, 0x55, 0},
+	{0x13B, 0x1, 0},
+	{0x13C, 0x55, 0},
+	{0x13D, 0x1, 0},
+	{0x13E, 0x5, 0},
+	{0x13F, 0x55, 0},
+	{0x140, 0x55, 0},
+	{0x146, 0, 0},
+	{0x147, 0, 0},
+	{0x148, 0, 0},
+	{0x149, 0, 0},
+	{0x14A, 0, 0},
+	{0x14B, 0, 0},
+	{0x14C, 0, 0},
+	{0x14D, 0, 0},
+	{0x14E, 0x1, 1},
+	{0x14F, 0, 0},
+	{0x150, 0, 0},
+	{0x151, 0, 0},
+	{0x154, 0xc, 0},
+	{0x155, 0xc, 0},
+	{0x156, 0xc, 0},
+	{0x157, 0, 0},
+	{0x158, 0x2b, 0},
+	{0x159, 0x84, 0},
+	{0x15A, 0x15, 0},
+	{0x15B, 0xf, 0},
+	{0x15C, 0, 0},
+	{0x15D, 0, 0},
+	{0x15E, 0, 1},
+	{0x15F, 0, 1},
+	{0x160, 0, 1},
+	{0x161, 0, 1},
+	{0x162, 0, 1},
+	{0x163, 0, 1},
+	{0x164, 0, 0},
+	{0x165, 0, 0},
+	{0x166, 0, 0},
+	{0x167, 0, 0},
+	{0x168, 0, 0},
+	{0x169, 0, 0},
+	{0x16A, 0, 1},
+	{0x16B, 0, 1},
+	{0x16C, 0, 1},
+	{0x16D, 0, 0},
+	{0x170, 0, 0},
+	{0x171, 0x77, 0},
+	{0x172, 0x77, 0},
+	{0x173, 0x77, 0},
+	{0x174, 0x77, 0},
+	{0x175, 0, 0},
+	{0x176, 0x3, 0},
+	{0x177, 0x37, 0},
+	{0x178, 0x3, 0},
+	{0x179, 0, 0},
+	{0x17A, 0x21, 0},
+	{0x17B, 0x21, 0},
+	{0x17C, 0, 0},
+	{0x17D, 0xaa, 0},
+	{0x17E, 0, 0},
+	{0x17F, 0xaa, 0},
+	{0x180, 0, 0},
+	{0x190, 0, 0},
+	{0x191, 0x77, 0},
+	{0x192, 0x77, 0},
+	{0x193, 0x77, 0},
+	{0x194, 0x77, 0},
+	{0x195, 0, 0},
+	{0x196, 0x3, 0},
+	{0x197, 0x37, 0},
+	{0x198, 0x3, 0},
+	{0x199, 0, 0},
+	{0x19A, 0x21, 0},
+	{0x19B, 0x21, 0},
+	{0x19C, 0, 0},
+	{0x19D, 0xaa, 0},
+	{0x19E, 0, 0},
+	{0x19F, 0xaa, 0},
+	{0x1A0, 0, 0},
+	{0x1A1, 0x2, 0},
+	{0x1A2, 0xf, 0},
+	{0x1A3, 0xf, 0},
+	{0x1A4, 0, 1},
+	{0x1A5, 0, 1},
+	{0x1A6, 0, 1},
+	{0x1A7, 0x2, 0},
+	{0x1A8, 0xf, 0},
+	{0x1A9, 0xf, 0},
+	{0x1AA, 0, 1},
+	{0x1AB, 0, 1},
+	{0x1AC, 0, 1},
+	{0x1AD, 0x84, 0},
+	{0x1AE, 0x60, 0},
+	{0x1AF, 0x47, 0},
+	{0x1B0, 0x47, 0},
+	{0x1B1, 0, 0},
+	{0x1B2, 0, 0},
+	{0x1B3, 0, 0},
+	{0x1B4, 0, 0},
+	{0x1B5, 0, 0},
+	{0x1B6, 0, 0},
+	{0x1B7, 0x5, 1},
+	{0x1B8, 0, 0},
+	{0x1B9, 0, 0},
+	{0x1BA, 0, 0},
+	{0x1BB, 0, 0},
+	{0x1BC, 0, 0},
+	{0x1BD, 0, 0},
+	{0x1BE, 0, 0},
+	{0x1BF, 0, 0},
+	{0x1C0, 0, 0},
+	{0x1C1, 0, 0},
+	{0x1C2, 0xa0, 1},
+	{0x1C3, 0, 0},
+	{0x1C4, 0, 0},
+	{0x1C5, 0, 0},
+	{0x1C6, 0, 0},
+	{0x1C7, 0, 0},
+	{0x1C8, 0, 0},
+	{0x1C9, 0, 0},
+	{0x1CA, 0, 0},
+	{0xFFFF, 0, 0}
+};
+
+static s16 nphy_def_lnagains[] = { -2, 10, 19, 25 };
+
+static s32 nphy_lnagain_est0[] = { -315, 40370 };
+static s32 nphy_lnagain_est1[] = { -224, 23242 };
+
+static const u16 tbl_iqcal_gainparams_nphy[2][NPHY_IQCAL_NUMGAINS][8] = {
+	{
+	 {0x000, 0, 0, 2, 0x69, 0x69, 0x69, 0x69},
+	 {0x700, 7, 0, 0, 0x69, 0x69, 0x69, 0x69},
+	 {0x710, 7, 1, 0, 0x68, 0x68, 0x68, 0x68},
+	 {0x720, 7, 2, 0, 0x67, 0x67, 0x67, 0x67},
+	 {0x730, 7, 3, 0, 0x66, 0x66, 0x66, 0x66},
+	 {0x740, 7, 4, 0, 0x65, 0x65, 0x65, 0x65},
+	 {0x741, 7, 4, 1, 0x65, 0x65, 0x65, 0x65},
+	 {0x742, 7, 4, 2, 0x65, 0x65, 0x65, 0x65},
+	 {0x743, 7, 4, 3, 0x65, 0x65, 0x65, 0x65}
+	 },
+	{
+	 {0x000, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x700, 7, 0, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x710, 7, 1, 0, 0x79, 0x79, 0x79, 0x79},
+	 {0x720, 7, 2, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x730, 7, 3, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x740, 7, 4, 0, 0x78, 0x78, 0x78, 0x78},
+	 {0x741, 7, 4, 1, 0x78, 0x78, 0x78, 0x78},
+	 {0x742, 7, 4, 2, 0x78, 0x78, 0x78, 0x78},
+	 {0x743, 7, 4, 3, 0x78, 0x78, 0x78, 0x78}
+	 }
+};
+
+static const u32 nphy_tpc_txgain[] = {
+	0x03cc2b44, 0x03cc2b42, 0x03cc2a44, 0x03cc2a42,
+	0x03cc2944, 0x03c82b44, 0x03c82b42, 0x03c82a44,
+	0x03c82a42, 0x03c82944, 0x03c82942, 0x03c82844,
+	0x03c82842, 0x03c42b44, 0x03c42b42, 0x03c42a44,
+	0x03c42a42, 0x03c42944, 0x03c42942, 0x03c42844,
+	0x03c42842, 0x03c42744, 0x03c42742, 0x03c42644,
+	0x03c42642, 0x03c42544, 0x03c42542, 0x03c42444,
+	0x03c42442, 0x03c02b44, 0x03c02b42, 0x03c02a44,
+	0x03c02a42, 0x03c02944, 0x03c02942, 0x03c02844,
+	0x03c02842, 0x03c02744, 0x03c02742, 0x03b02b44,
+	0x03b02b42, 0x03b02a44, 0x03b02a42, 0x03b02944,
+	0x03b02942, 0x03b02844, 0x03b02842, 0x03b02744,
+	0x03b02742, 0x03b02644, 0x03b02642, 0x03b02544,
+	0x03b02542, 0x03a02b44, 0x03a02b42, 0x03a02a44,
+	0x03a02a42, 0x03a02944, 0x03a02942, 0x03a02844,
+	0x03a02842, 0x03a02744, 0x03a02742, 0x03902b44,
+	0x03902b42, 0x03902a44, 0x03902a42, 0x03902944,
+	0x03902942, 0x03902844, 0x03902842, 0x03902744,
+	0x03902742, 0x03902644, 0x03902642, 0x03902544,
+	0x03902542, 0x03802b44, 0x03802b42, 0x03802a44,
+	0x03802a42, 0x03802944, 0x03802942, 0x03802844,
+	0x03802842, 0x03802744, 0x03802742, 0x03802644,
+	0x03802642, 0x03802544, 0x03802542, 0x03802444,
+	0x03802442, 0x03802344, 0x03802342, 0x03802244,
+	0x03802242, 0x03802144, 0x03802142, 0x03802044,
+	0x03802042, 0x03801f44, 0x03801f42, 0x03801e44,
+	0x03801e42, 0x03801d44, 0x03801d42, 0x03801c44,
+	0x03801c42, 0x03801b44, 0x03801b42, 0x03801a44,
+	0x03801a42, 0x03801944, 0x03801942, 0x03801844,
+	0x03801842, 0x03801744, 0x03801742, 0x03801644,
+	0x03801642, 0x03801544, 0x03801542, 0x03801444,
+	0x03801442, 0x03801344, 0x03801342, 0x00002b00
+};
+
+static const u16 nphy_tpc_loscale[] = {
+	256, 256, 271, 271, 287, 256, 256, 271,
+	271, 287, 287, 304, 304, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 256,
+	256, 271, 271, 287, 287, 304, 304, 322,
+	322, 341, 341, 362, 362, 256, 256, 271,
+	271, 287, 287, 304, 304, 322, 322, 341,
+	341, 362, 362, 383, 383, 406, 406, 430,
+	430, 455, 455, 482, 482, 511, 511, 541,
+	541, 573, 573, 607, 607, 643, 643, 681,
+	681, 722, 722, 764, 764, 810, 810, 858,
+	858, 908, 908, 962, 962, 1019, 1019, 256
+};
+
+static u32 nphy_tpc_txgain_ipa[] = {
+	0x5ff7002d, 0x5ff7002b, 0x5ff7002a, 0x5ff70029,
+	0x5ff70028, 0x5ff70027, 0x5ff70026, 0x5ff70025,
+	0x5ef7002d, 0x5ef7002b, 0x5ef7002a, 0x5ef70029,
+	0x5ef70028, 0x5ef70027, 0x5ef70026, 0x5ef70025,
+	0x5df7002d, 0x5df7002b, 0x5df7002a, 0x5df70029,
+	0x5df70028, 0x5df70027, 0x5df70026, 0x5df70025,
+	0x5cf7002d, 0x5cf7002b, 0x5cf7002a, 0x5cf70029,
+	0x5cf70028, 0x5cf70027, 0x5cf70026, 0x5cf70025,
+	0x5bf7002d, 0x5bf7002b, 0x5bf7002a, 0x5bf70029,
+	0x5bf70028, 0x5bf70027, 0x5bf70026, 0x5bf70025,
+	0x5af7002d, 0x5af7002b, 0x5af7002a, 0x5af70029,
+	0x5af70028, 0x5af70027, 0x5af70026, 0x5af70025,
+	0x59f7002d, 0x59f7002b, 0x59f7002a, 0x59f70029,
+	0x59f70028, 0x59f70027, 0x59f70026, 0x59f70025,
+	0x58f7002d, 0x58f7002b, 0x58f7002a, 0x58f70029,
+	0x58f70028, 0x58f70027, 0x58f70026, 0x58f70025,
+	0x57f7002d, 0x57f7002b, 0x57f7002a, 0x57f70029,
+	0x57f70028, 0x57f70027, 0x57f70026, 0x57f70025,
+	0x56f7002d, 0x56f7002b, 0x56f7002a, 0x56f70029,
+	0x56f70028, 0x56f70027, 0x56f70026, 0x56f70025,
+	0x55f7002d, 0x55f7002b, 0x55f7002a, 0x55f70029,
+	0x55f70028, 0x55f70027, 0x55f70026, 0x55f70025,
+	0x54f7002d, 0x54f7002b, 0x54f7002a, 0x54f70029,
+	0x54f70028, 0x54f70027, 0x54f70026, 0x54f70025,
+	0x53f7002d, 0x53f7002b, 0x53f7002a, 0x53f70029,
+	0x53f70028, 0x53f70027, 0x53f70026, 0x53f70025,
+	0x52f7002d, 0x52f7002b, 0x52f7002a, 0x52f70029,
+	0x52f70028, 0x52f70027, 0x52f70026, 0x52f70025,
+	0x51f7002d, 0x51f7002b, 0x51f7002a, 0x51f70029,
+	0x51f70028, 0x51f70027, 0x51f70026, 0x51f70025,
+	0x50f7002d, 0x50f7002b, 0x50f7002a, 0x50f70029,
+	0x50f70028, 0x50f70027, 0x50f70026, 0x50f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev5[] = {
+	0x1ff7002d, 0x1ff7002b, 0x1ff7002a, 0x1ff70029,
+	0x1ff70028, 0x1ff70027, 0x1ff70026, 0x1ff70025,
+	0x1ef7002d, 0x1ef7002b, 0x1ef7002a, 0x1ef70029,
+	0x1ef70028, 0x1ef70027, 0x1ef70026, 0x1ef70025,
+	0x1df7002d, 0x1df7002b, 0x1df7002a, 0x1df70029,
+	0x1df70028, 0x1df70027, 0x1df70026, 0x1df70025,
+	0x1cf7002d, 0x1cf7002b, 0x1cf7002a, 0x1cf70029,
+	0x1cf70028, 0x1cf70027, 0x1cf70026, 0x1cf70025,
+	0x1bf7002d, 0x1bf7002b, 0x1bf7002a, 0x1bf70029,
+	0x1bf70028, 0x1bf70027, 0x1bf70026, 0x1bf70025,
+	0x1af7002d, 0x1af7002b, 0x1af7002a, 0x1af70029,
+	0x1af70028, 0x1af70027, 0x1af70026, 0x1af70025,
+	0x19f7002d, 0x19f7002b, 0x19f7002a, 0x19f70029,
+	0x19f70028, 0x19f70027, 0x19f70026, 0x19f70025,
+	0x18f7002d, 0x18f7002b, 0x18f7002a, 0x18f70029,
+	0x18f70028, 0x18f70027, 0x18f70026, 0x18f70025,
+	0x17f7002d, 0x17f7002b, 0x17f7002a, 0x17f70029,
+	0x17f70028, 0x17f70027, 0x17f70026, 0x17f70025,
+	0x16f7002d, 0x16f7002b, 0x16f7002a, 0x16f70029,
+	0x16f70028, 0x16f70027, 0x16f70026, 0x16f70025,
+	0x15f7002d, 0x15f7002b, 0x15f7002a, 0x15f70029,
+	0x15f70028, 0x15f70027, 0x15f70026, 0x15f70025,
+	0x14f7002d, 0x14f7002b, 0x14f7002a, 0x14f70029,
+	0x14f70028, 0x14f70027, 0x14f70026, 0x14f70025,
+	0x13f7002d, 0x13f7002b, 0x13f7002a, 0x13f70029,
+	0x13f70028, 0x13f70027, 0x13f70026, 0x13f70025,
+	0x12f7002d, 0x12f7002b, 0x12f7002a, 0x12f70029,
+	0x12f70028, 0x12f70027, 0x12f70026, 0x12f70025,
+	0x11f7002d, 0x11f7002b, 0x11f7002a, 0x11f70029,
+	0x11f70028, 0x11f70027, 0x11f70026, 0x11f70025,
+	0x10f7002d, 0x10f7002b, 0x10f7002a, 0x10f70029,
+	0x10f70028, 0x10f70027, 0x10f70026, 0x10f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_rev6[] = {
+	0x0ff7002d, 0x0ff7002b, 0x0ff7002a, 0x0ff70029,
+	0x0ff70028, 0x0ff70027, 0x0ff70026, 0x0ff70025,
+	0x0ef7002d, 0x0ef7002b, 0x0ef7002a, 0x0ef70029,
+	0x0ef70028, 0x0ef70027, 0x0ef70026, 0x0ef70025,
+	0x0df7002d, 0x0df7002b, 0x0df7002a, 0x0df70029,
+	0x0df70028, 0x0df70027, 0x0df70026, 0x0df70025,
+	0x0cf7002d, 0x0cf7002b, 0x0cf7002a, 0x0cf70029,
+	0x0cf70028, 0x0cf70027, 0x0cf70026, 0x0cf70025,
+	0x0bf7002d, 0x0bf7002b, 0x0bf7002a, 0x0bf70029,
+	0x0bf70028, 0x0bf70027, 0x0bf70026, 0x0bf70025,
+	0x0af7002d, 0x0af7002b, 0x0af7002a, 0x0af70029,
+	0x0af70028, 0x0af70027, 0x0af70026, 0x0af70025,
+	0x09f7002d, 0x09f7002b, 0x09f7002a, 0x09f70029,
+	0x09f70028, 0x09f70027, 0x09f70026, 0x09f70025,
+	0x08f7002d, 0x08f7002b, 0x08f7002a, 0x08f70029,
+	0x08f70028, 0x08f70027, 0x08f70026, 0x08f70025,
+	0x07f7002d, 0x07f7002b, 0x07f7002a, 0x07f70029,
+	0x07f70028, 0x07f70027, 0x07f70026, 0x07f70025,
+	0x06f7002d, 0x06f7002b, 0x06f7002a, 0x06f70029,
+	0x06f70028, 0x06f70027, 0x06f70026, 0x06f70025,
+	0x05f7002d, 0x05f7002b, 0x05f7002a, 0x05f70029,
+	0x05f70028, 0x05f70027, 0x05f70026, 0x05f70025,
+	0x04f7002d, 0x04f7002b, 0x04f7002a, 0x04f70029,
+	0x04f70028, 0x04f70027, 0x04f70026, 0x04f70025,
+	0x03f7002d, 0x03f7002b, 0x03f7002a, 0x03f70029,
+	0x03f70028, 0x03f70027, 0x03f70026, 0x03f70025,
+	0x02f7002d, 0x02f7002b, 0x02f7002a, 0x02f70029,
+	0x02f70028, 0x02f70027, 0x02f70026, 0x02f70025,
+	0x01f7002d, 0x01f7002b, 0x01f7002a, 0x01f70029,
+	0x01f70028, 0x01f70027, 0x01f70026, 0x01f70025,
+	0x00f7002d, 0x00f7002b, 0x00f7002a, 0x00f70029,
+	0x00f70028, 0x00f70027, 0x00f70026, 0x00f70025
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev3[] = {
+	0x70ff0040, 0x70f7003e, 0x70ef003b, 0x70e70039,
+	0x70df0037, 0x70d70036, 0x70cf0033, 0x70c70032,
+	0x70bf0031, 0x70b7002f, 0x70af002e, 0x70a7002d,
+	0x709f002d, 0x7097002c, 0x708f002c, 0x7087002c,
+	0x707f002b, 0x7077002c, 0x706f002c, 0x7067002d,
+	0x705f002e, 0x705f002b, 0x705f0029, 0x7057002a,
+	0x70570028, 0x704f002a, 0x7047002c, 0x7047002a,
+	0x70470028, 0x70470026, 0x70470024, 0x70470022,
+	0x7047001f, 0x70370027, 0x70370024, 0x70370022,
+	0x70370020, 0x7037001f, 0x7037001d, 0x7037001b,
+	0x7037001a, 0x70370018, 0x70370017, 0x7027001e,
+	0x7027001d, 0x7027001a, 0x701f0024, 0x701f0022,
+	0x701f0020, 0x701f001f, 0x701f001d, 0x701f001b,
+	0x701f001a, 0x701f0018, 0x701f0017, 0x701f0015,
+	0x701f0014, 0x701f0013, 0x701f0012, 0x701f0011,
+	0x70170019, 0x70170018, 0x70170016, 0x70170015,
+	0x70170014, 0x70170013, 0x70170012, 0x70170010,
+	0x70170010, 0x7017000f, 0x700f001d, 0x700f001b,
+	0x700f001a, 0x700f0018, 0x700f0017, 0x700f0015,
+	0x700f0015, 0x700f0013, 0x700f0013, 0x700f0011,
+	0x700f0010, 0x700f0010, 0x700f000f, 0x700f000e,
+	0x700f000d, 0x700f000c, 0x700f000b, 0x700f000b,
+	0x700f000b, 0x700f000a, 0x700f0009, 0x700f0009,
+	0x700f0009, 0x700f0008, 0x700f0007, 0x700f0007,
+	0x700f0006, 0x700f0006, 0x700f0006, 0x700f0006,
+	0x700f0005, 0x700f0005, 0x700f0005, 0x700f0004,
+	0x700f0004, 0x700f0004, 0x700f0004, 0x700f0004,
+	0x700f0004, 0x700f0003, 0x700f0003, 0x700f0003,
+	0x700f0003, 0x700f0002, 0x700f0002, 0x700f0002,
+	0x700f0002, 0x700f0002, 0x700f0002, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001,
+	0x700f0001, 0x700f0001, 0x700f0001, 0x700f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev4n6[] = {
+	0xf0ff0040, 0xf0f7003e, 0xf0ef003b, 0xf0e70039,
+	0xf0df0037, 0xf0d70036, 0xf0cf0033, 0xf0c70032,
+	0xf0bf0031, 0xf0b7002f, 0xf0af002e, 0xf0a7002d,
+	0xf09f002d, 0xf097002c, 0xf08f002c, 0xf087002c,
+	0xf07f002b, 0xf077002c, 0xf06f002c, 0xf067002d,
+	0xf05f002e, 0xf05f002b, 0xf05f0029, 0xf057002a,
+	0xf0570028, 0xf04f002a, 0xf047002c, 0xf047002a,
+	0xf0470028, 0xf0470026, 0xf0470024, 0xf0470022,
+	0xf047001f, 0xf0370027, 0xf0370024, 0xf0370022,
+	0xf0370020, 0xf037001f, 0xf037001d, 0xf037001b,
+	0xf037001a, 0xf0370018, 0xf0370017, 0xf027001e,
+	0xf027001d, 0xf027001a, 0xf01f0024, 0xf01f0022,
+	0xf01f0020, 0xf01f001f, 0xf01f001d, 0xf01f001b,
+	0xf01f001a, 0xf01f0018, 0xf01f0017, 0xf01f0015,
+	0xf01f0014, 0xf01f0013, 0xf01f0012, 0xf01f0011,
+	0xf0170019, 0xf0170018, 0xf0170016, 0xf0170015,
+	0xf0170014, 0xf0170013, 0xf0170012, 0xf0170010,
+	0xf0170010, 0xf017000f, 0xf00f001d, 0xf00f001b,
+	0xf00f001a, 0xf00f0018, 0xf00f0017, 0xf00f0015,
+	0xf00f0015, 0xf00f0013, 0xf00f0013, 0xf00f0011,
+	0xf00f0010, 0xf00f0010, 0xf00f000f, 0xf00f000e,
+	0xf00f000d, 0xf00f000c, 0xf00f000b, 0xf00f000b,
+	0xf00f000b, 0xf00f000a, 0xf00f0009, 0xf00f0009,
+	0xf00f0009, 0xf00f0008, 0xf00f0007, 0xf00f0007,
+	0xf00f0006, 0xf00f0006, 0xf00f0006, 0xf00f0006,
+	0xf00f0005, 0xf00f0005, 0xf00f0005, 0xf00f0004,
+	0xf00f0004, 0xf00f0004, 0xf00f0004, 0xf00f0004,
+	0xf00f0004, 0xf00f0003, 0xf00f0003, 0xf00f0003,
+	0xf00f0003, 0xf00f0002, 0xf00f0002, 0xf00f0002,
+	0xf00f0002, 0xf00f0002, 0xf00f0002, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001,
+	0xf00f0001, 0xf00f0001, 0xf00f0001, 0xf00f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev5[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_2g_2057rev7[] = {
+	0x30ff0031, 0x30e70031, 0x30e7002e, 0x30cf002e,
+	0x30bf002e, 0x30af002e, 0x309f002f, 0x307f0033,
+	0x307f0031, 0x307f002e, 0x3077002e, 0x306f002e,
+	0x3067002e, 0x305f002f, 0x30570030, 0x3057002d,
+	0x304f002e, 0x30470031, 0x3047002e, 0x3047002c,
+	0x30470029, 0x303f002c, 0x303f0029, 0x3037002d,
+	0x3037002a, 0x30370028, 0x302f002c, 0x302f002a,
+	0x302f0028, 0x302f0026, 0x3027002c, 0x30270029,
+	0x30270027, 0x30270025, 0x30270023, 0x301f002c,
+	0x301f002a, 0x301f0028, 0x301f0025, 0x301f0024,
+	0x301f0022, 0x301f001f, 0x3017002d, 0x3017002b,
+	0x30170028, 0x30170026, 0x30170024, 0x30170022,
+	0x30170020, 0x3017001e, 0x3017001d, 0x3017001b,
+	0x3017001a, 0x30170018, 0x30170017, 0x30170015,
+	0x300f002c, 0x300f0029, 0x300f0027, 0x300f0024,
+	0x300f0022, 0x300f0021, 0x300f001f, 0x300f001d,
+	0x300f001b, 0x300f001a, 0x300f0018, 0x300f0017,
+	0x300f0016, 0x300f0015, 0x300f0115, 0x300f0215,
+	0x300f0315, 0x300f0415, 0x300f0515, 0x300f0615,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715,
+	0x300f0715, 0x300f0715, 0x300f0715, 0x300f0715
+};
+
+static u32 nphy_tpc_txgain_ipa_5g[] = {
+	0x7ff70035, 0x7ff70033, 0x7ff70032, 0x7ff70031,
+	0x7ff7002f, 0x7ff7002e, 0x7ff7002d, 0x7ff7002b,
+	0x7ff7002a, 0x7ff70029, 0x7ff70028, 0x7ff70027,
+	0x7ff70026, 0x7ff70024, 0x7ff70023, 0x7ff70022,
+	0x7ef70028, 0x7ef70027, 0x7ef70026, 0x7ef70025,
+	0x7ef70024, 0x7ef70023, 0x7df70028, 0x7df70027,
+	0x7df70026, 0x7df70025, 0x7df70024, 0x7df70023,
+	0x7df70022, 0x7cf70029, 0x7cf70028, 0x7cf70027,
+	0x7cf70026, 0x7cf70025, 0x7cf70023, 0x7cf70022,
+	0x7bf70029, 0x7bf70028, 0x7bf70026, 0x7bf70025,
+	0x7bf70024, 0x7bf70023, 0x7bf70022, 0x7bf70021,
+	0x7af70029, 0x7af70028, 0x7af70027, 0x7af70026,
+	0x7af70025, 0x7af70024, 0x7af70023, 0x7af70022,
+	0x79f70029, 0x79f70028, 0x79f70027, 0x79f70026,
+	0x79f70025, 0x79f70024, 0x79f70023, 0x79f70022,
+	0x78f70029, 0x78f70028, 0x78f70027, 0x78f70026,
+	0x78f70025, 0x78f70024, 0x78f70023, 0x78f70022,
+	0x77f70029, 0x77f70028, 0x77f70027, 0x77f70026,
+	0x77f70025, 0x77f70024, 0x77f70023, 0x77f70022,
+	0x76f70029, 0x76f70028, 0x76f70027, 0x76f70026,
+	0x76f70024, 0x76f70023, 0x76f70022, 0x76f70021,
+	0x75f70029, 0x75f70028, 0x75f70027, 0x75f70026,
+	0x75f70025, 0x75f70024, 0x75f70023, 0x74f70029,
+	0x74f70028, 0x74f70026, 0x74f70025, 0x74f70024,
+	0x74f70023, 0x74f70022, 0x73f70029, 0x73f70027,
+	0x73f70026, 0x73f70025, 0x73f70024, 0x73f70023,
+	0x73f70022, 0x72f70028, 0x72f70027, 0x72f70026,
+	0x72f70025, 0x72f70024, 0x72f70023, 0x72f70022,
+	0x71f70028, 0x71f70027, 0x71f70026, 0x71f70025,
+	0x71f70024, 0x71f70023, 0x70f70028, 0x70f70027,
+	0x70f70026, 0x70f70024, 0x70f70023, 0x70f70022,
+	0x70f70021, 0x70f70020, 0x70f70020, 0x70f7001f
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057[] = {
+	0x7f7f0044, 0x7f7f0040, 0x7f7f003c, 0x7f7f0039,
+	0x7f7f0036, 0x7e7f003c, 0x7e7f0038, 0x7e7f0035,
+	0x7d7f003c, 0x7d7f0039, 0x7d7f0036, 0x7d7f0033,
+	0x7c7f003b, 0x7c7f0037, 0x7c7f0034, 0x7b7f003a,
+	0x7b7f0036, 0x7b7f0033, 0x7a7f003c, 0x7a7f0039,
+	0x7a7f0036, 0x7a7f0033, 0x797f003b, 0x797f0038,
+	0x797f0035, 0x797f0032, 0x787f003b, 0x787f0038,
+	0x787f0035, 0x787f0032, 0x777f003a, 0x777f0037,
+	0x777f0034, 0x777f0031, 0x767f003a, 0x767f0036,
+	0x767f0033, 0x767f0031, 0x757f003a, 0x757f0037,
+	0x757f0034, 0x747f003c, 0x747f0039, 0x747f0036,
+	0x747f0033, 0x737f003b, 0x737f0038, 0x737f0035,
+	0x737f0032, 0x727f0039, 0x727f0036, 0x727f0033,
+	0x727f0030, 0x717f003a, 0x717f0037, 0x717f0034,
+	0x707f003b, 0x707f0038, 0x707f0035, 0x707f0032,
+	0x707f002f, 0x707f002d, 0x707f002a, 0x707f0028,
+	0x707f0025, 0x707f0023, 0x707f0021, 0x707f0020,
+	0x707f001e, 0x707f001c, 0x707f001b, 0x707f0019,
+	0x707f0018, 0x707f0016, 0x707f0015, 0x707f0014,
+	0x707f0013, 0x707f0012, 0x707f0011, 0x707f0010,
+	0x707f000f, 0x707f000e, 0x707f000d, 0x707f000d,
+	0x707f000c, 0x707f000b, 0x707f000b, 0x707f000a,
+	0x707f0009, 0x707f0009, 0x707f0008, 0x707f0008,
+	0x707f0007, 0x707f0007, 0x707f0007, 0x707f0006,
+	0x707f0006, 0x707f0006, 0x707f0005, 0x707f0005,
+	0x707f0005, 0x707f0004, 0x707f0004, 0x707f0004,
+	0x707f0004, 0x707f0004, 0x707f0003, 0x707f0003,
+	0x707f0003, 0x707f0003, 0x707f0003, 0x707f0003,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0002, 0x707f0002, 0x707f0002, 0x707f0002,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001,
+	0x707f0001, 0x707f0001, 0x707f0001, 0x707f0001
+};
+
+static u32 nphy_tpc_txgain_ipa_5g_2057rev7[] = {
+	0x6f7f0031, 0x6f7f002e, 0x6f7f002c, 0x6f7f002a,
+	0x6f7f0027, 0x6e7f002e, 0x6e7f002c, 0x6e7f002a,
+	0x6d7f0030, 0x6d7f002d, 0x6d7f002a, 0x6d7f0028,
+	0x6c7f0030, 0x6c7f002d, 0x6c7f002b, 0x6b7f002e,
+	0x6b7f002c, 0x6b7f002a, 0x6b7f0027, 0x6a7f002e,
+	0x6a7f002c, 0x6a7f002a, 0x697f0030, 0x697f002e,
+	0x697f002b, 0x697f0029, 0x687f002f, 0x687f002d,
+	0x687f002a, 0x687f0027, 0x677f002f, 0x677f002d,
+	0x677f002a, 0x667f0031, 0x667f002e, 0x667f002c,
+	0x667f002a, 0x657f0030, 0x657f002e, 0x657f002b,
+	0x657f0029, 0x647f0030, 0x647f002d, 0x647f002b,
+	0x647f0029, 0x637f002f, 0x637f002d, 0x637f002a,
+	0x627f0030, 0x627f002d, 0x627f002b, 0x627f0029,
+	0x617f0030, 0x617f002e, 0x617f002b, 0x617f0029,
+	0x607f002f, 0x607f002d, 0x607f002a, 0x607f0027,
+	0x607f0026, 0x607f0023, 0x607f0021, 0x607f0020,
+	0x607f001e, 0x607f001c, 0x607f001a, 0x607f0019,
+	0x607f0018, 0x607f0016, 0x607f0015, 0x607f0014,
+	0x607f0012, 0x607f0012, 0x607f0011, 0x607f000f,
+	0x607f000f, 0x607f000e, 0x607f000d, 0x607f000c,
+	0x607f000c, 0x607f000b, 0x607f000b, 0x607f000a,
+	0x607f0009, 0x607f0009, 0x607f0008, 0x607f0008,
+	0x607f0008, 0x607f0007, 0x607f0007, 0x607f0006,
+	0x607f0006, 0x607f0005, 0x607f0005, 0x607f0005,
+	0x607f0005, 0x607f0005, 0x607f0004, 0x607f0004,
+	0x607f0004, 0x607f0004, 0x607f0003, 0x607f0003,
+	0x607f0003, 0x607f0003, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0002, 0x607f0002, 0x607f0002,
+	0x607f0002, 0x607f0001, 0x607f0001, 0x607f0001,
+	0x607f0001, 0x607f0001, 0x607f0001, 0x607f0001
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_2g[] = {
+	-114, -108, -98, -91, -84, -78, -70, -62,
+	-54, -46, -39, -31, -23, -15, -8, 0
+};
+
+static s8 nphy_papd_pga_gain_delta_ipa_5g[] = {
+	-100, -95, -89, -83, -77, -70, -63, -56,
+	-48, -41, -33, -25, -19, -12, -6, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev3n4[] = {
+	-159, -113, -86, -72, -62, -54, -48, -43,
+	-39, -35, -31, -28, -25, -23, -20, -18,
+	-17, -15, -13, -11, -10, -8, -7, -6,
+	-5, -4, -3, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev5[] = {
+	-109, -109, -82, -68, -58, -50, -44, -39,
+	-35, -31, -28, -26, -23, -21, -19, -17,
+	-16, -14, -13, -11, -10, -9, -8, -7,
+	-5, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s16 nphy_papd_padgain_dlt_2g_2057rev7[] = {
+	-122, -122, -95, -80, -69, -61, -54, -49,
+	-43, -39, -35, -32, -28, -26, -23, -21,
+	-18, -16, -15, -13, -11, -10, -8, -7,
+	-6, -5, -4, -3, -2, -1, -1, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057[] = {
+	-107, -101, -92, -85, -78, -71, -62, -55,
+	-47, -39, -32, -24, -19, -12, -6, 0
+};
+
+static s8 nphy_papd_pgagain_dlt_5g_2057rev7[] = {
+	-110, -104, -95, -88, -81, -74, -66, -58,
+	-50, -44, -36, -28, -23, -15, -8, 0
+};
+
+static u8 pad_gain_codes_used_2057rev5[] = {
+	20, 19, 18, 17, 16, 15, 14, 13, 12, 11,
+	10, 9, 8, 7, 6, 5, 4, 3, 2, 1
+};
+
+static u8 pad_gain_codes_used_2057rev7[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6,
+	5, 4, 3, 2, 1
+};
+
+static u8 pad_all_gain_codes_2057[] = {
+	31, 30, 29, 28, 27, 26, 25, 24, 23, 22,
+	21, 20, 19, 18, 17, 16, 15, 14, 13, 12,
+	11, 10, 9, 8, 7, 6, 5, 4, 3, 2,
+	1, 0
+};
+
+static u8 pga_all_gain_codes_2057[] = {
+	15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0
+};
+
+static u32 nphy_papd_scaltbl[] = {
+	0x0ae2002f, 0x0a3b0032, 0x09a70035, 0x09220038,
+	0x0887003c, 0x081f003f, 0x07a20043, 0x07340047,
+	0x06d2004b, 0x067a004f, 0x06170054, 0x05bf0059,
+	0x0571005e, 0x051e0064, 0x04d3006a, 0x04910070,
+	0x044c0077, 0x040f007e, 0x03d90085, 0x03a1008d,
+	0x036f0095, 0x033d009e, 0x030b00a8, 0x02e000b2,
+	0x02b900bc, 0x029200c7, 0x026d00d3, 0x024900e0,
+	0x022900ed, 0x020a00fb, 0x01ec010a, 0x01d0011a,
+	0x01b7012a, 0x019e013c, 0x0187014f, 0x01720162,
+	0x015d0177, 0x0149018e, 0x013701a5, 0x012601be,
+	0x011501d9, 0x010501f5, 0x00f70212, 0x00e90232,
+	0x00dc0253, 0x00d00276, 0x00c4029c, 0x00b902c3,
+	0x00af02ed, 0x00a5031a, 0x009c0349, 0x0093037a,
+	0x008b03af, 0x008303e7, 0x007c0422, 0x00750461,
+	0x006e04a3, 0x006804ea, 0x00620534, 0x005d0583,
+	0x005805d7, 0x0053062f, 0x004e068d, 0x004a06f1
+};
+
+static u32 nphy_tpc_txgain_rev3[] = {
+	0x1f410044, 0x1f410042, 0x1f410040, 0x1f41003e,
+	0x1f41003c, 0x1f41003b, 0x1f410039, 0x1f410037,
+	0x1e410044, 0x1e410042, 0x1e410040, 0x1e41003e,
+	0x1e41003c, 0x1e41003b, 0x1e410039, 0x1e410037,
+	0x1d410044, 0x1d410042, 0x1d410040, 0x1d41003e,
+	0x1d41003c, 0x1d41003b, 0x1d410039, 0x1d410037,
+	0x1c410044, 0x1c410042, 0x1c410040, 0x1c41003e,
+	0x1c41003c, 0x1c41003b, 0x1c410039, 0x1c410037,
+	0x1b410044, 0x1b410042, 0x1b410040, 0x1b41003e,
+	0x1b41003c, 0x1b41003b, 0x1b410039, 0x1b410037,
+	0x1a410044, 0x1a410042, 0x1a410040, 0x1a41003e,
+	0x1a41003c, 0x1a41003b, 0x1a410039, 0x1a410037,
+	0x19410044, 0x19410042, 0x19410040, 0x1941003e,
+	0x1941003c, 0x1941003b, 0x19410039, 0x19410037,
+	0x18410044, 0x18410042, 0x18410040, 0x1841003e,
+	0x1841003c, 0x1841003b, 0x18410039, 0x18410037,
+	0x17410044, 0x17410042, 0x17410040, 0x1741003e,
+	0x1741003c, 0x1741003b, 0x17410039, 0x17410037,
+	0x16410044, 0x16410042, 0x16410040, 0x1641003e,
+	0x1641003c, 0x1641003b, 0x16410039, 0x16410037,
+	0x15410044, 0x15410042, 0x15410040, 0x1541003e,
+	0x1541003c, 0x1541003b, 0x15410039, 0x15410037,
+	0x14410044, 0x14410042, 0x14410040, 0x1441003e,
+	0x1441003c, 0x1441003b, 0x14410039, 0x14410037,
+	0x13410044, 0x13410042, 0x13410040, 0x1341003e,
+	0x1341003c, 0x1341003b, 0x13410039, 0x13410037,
+	0x12410044, 0x12410042, 0x12410040, 0x1241003e,
+	0x1241003c, 0x1241003b, 0x12410039, 0x12410037,
+	0x11410044, 0x11410042, 0x11410040, 0x1141003e,
+	0x1141003c, 0x1141003b, 0x11410039, 0x11410037,
+	0x10410044, 0x10410042, 0x10410040, 0x1041003e,
+	0x1041003c, 0x1041003b, 0x10410039, 0x10410037
+};
+
+static u32 nphy_tpc_txgain_HiPwrEPA[] = {
+	0x0f410044, 0x0f410042, 0x0f410040, 0x0f41003e,
+	0x0f41003c, 0x0f41003b, 0x0f410039, 0x0f410037,
+	0x0e410044, 0x0e410042, 0x0e410040, 0x0e41003e,
+	0x0e41003c, 0x0e41003b, 0x0e410039, 0x0e410037,
+	0x0d410044, 0x0d410042, 0x0d410040, 0x0d41003e,
+	0x0d41003c, 0x0d41003b, 0x0d410039, 0x0d410037,
+	0x0c410044, 0x0c410042, 0x0c410040, 0x0c41003e,
+	0x0c41003c, 0x0c41003b, 0x0c410039, 0x0c410037,
+	0x0b410044, 0x0b410042, 0x0b410040, 0x0b41003e,
+	0x0b41003c, 0x0b41003b, 0x0b410039, 0x0b410037,
+	0x0a410044, 0x0a410042, 0x0a410040, 0x0a41003e,
+	0x0a41003c, 0x0a41003b, 0x0a410039, 0x0a410037,
+	0x09410044, 0x09410042, 0x09410040, 0x0941003e,
+	0x0941003c, 0x0941003b, 0x09410039, 0x09410037,
+	0x08410044, 0x08410042, 0x08410040, 0x0841003e,
+	0x0841003c, 0x0841003b, 0x08410039, 0x08410037,
+	0x07410044, 0x07410042, 0x07410040, 0x0741003e,
+	0x0741003c, 0x0741003b, 0x07410039, 0x07410037,
+	0x06410044, 0x06410042, 0x06410040, 0x0641003e,
+	0x0641003c, 0x0641003b, 0x06410039, 0x06410037,
+	0x05410044, 0x05410042, 0x05410040, 0x0541003e,
+	0x0541003c, 0x0541003b, 0x05410039, 0x05410037,
+	0x04410044, 0x04410042, 0x04410040, 0x0441003e,
+	0x0441003c, 0x0441003b, 0x04410039, 0x04410037,
+	0x03410044, 0x03410042, 0x03410040, 0x0341003e,
+	0x0341003c, 0x0341003b, 0x03410039, 0x03410037,
+	0x02410044, 0x02410042, 0x02410040, 0x0241003e,
+	0x0241003c, 0x0241003b, 0x02410039, 0x02410037,
+	0x01410044, 0x01410042, 0x01410040, 0x0141003e,
+	0x0141003c, 0x0141003b, 0x01410039, 0x01410037,
+	0x00410044, 0x00410042, 0x00410040, 0x0041003e,
+	0x0041003c, 0x0041003b, 0x00410039, 0x00410037
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev3[] = {
+	0x80f90040, 0x80e10040, 0x80e1003c, 0x80c9003d,
+	0x80b9003c, 0x80a9003d, 0x80a1003c, 0x8099003b,
+	0x8091003b, 0x8089003a, 0x8081003a, 0x80790039,
+	0x80710039, 0x8069003a, 0x8061003b, 0x8059003d,
+	0x8051003f, 0x80490042, 0x8049003e, 0x8049003b,
+	0x8041003e, 0x8041003b, 0x8039003e, 0x8039003b,
+	0x80390038, 0x80390035, 0x8031003a, 0x80310036,
+	0x80310033, 0x8029003a, 0x80290037, 0x80290034,
+	0x80290031, 0x80210039, 0x80210036, 0x80210033,
+	0x80210030, 0x8019003c, 0x80190039, 0x80190036,
+	0x80190033, 0x80190030, 0x8019002d, 0x8019002b,
+	0x80190028, 0x8011003a, 0x80110036, 0x80110033,
+	0x80110030, 0x8011002e, 0x8011002b, 0x80110029,
+	0x80110027, 0x80110024, 0x80110022, 0x80110020,
+	0x8011001f, 0x8011001d, 0x8009003a, 0x80090037,
+	0x80090034, 0x80090031, 0x8009002e, 0x8009002c,
+	0x80090029, 0x80090027, 0x80090025, 0x80090023,
+	0x80090021, 0x8009001f, 0x8009001d, 0x8009011d,
+	0x8009021d, 0x8009031d, 0x8009041d, 0x8009051d,
+	0x8009061d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d,
+	0x8009071d, 0x8009071d, 0x8009071d, 0x8009071d
+};
+
+static u32 nphy_tpc_txgain_epa_2057rev5[] = {
+	0x10f90040, 0x10e10040, 0x10e1003c, 0x10c9003d,
+	0x10b9003c, 0x10a9003d, 0x10a1003c, 0x1099003b,
+	0x1091003b, 0x1089003a, 0x1081003a, 0x10790039,
+	0x10710039, 0x1069003a, 0x1061003b, 0x1059003d,
+	0x1051003f, 0x10490042, 0x1049003e, 0x1049003b,
+	0x1041003e, 0x1041003b, 0x1039003e, 0x1039003b,
+	0x10390038, 0x10390035, 0x1031003a, 0x10310036,
+	0x10310033, 0x1029003a, 0x10290037, 0x10290034,
+	0x10290031, 0x10210039, 0x10210036, 0x10210033,
+	0x10210030, 0x1019003c, 0x10190039, 0x10190036,
+	0x10190033, 0x10190030, 0x1019002d, 0x1019002b,
+	0x10190028, 0x1011003a, 0x10110036, 0x10110033,
+	0x10110030, 0x1011002e, 0x1011002b, 0x10110029,
+	0x10110027, 0x10110024, 0x10110022, 0x10110020,
+	0x1011001f, 0x1011001d, 0x1009003a, 0x10090037,
+	0x10090034, 0x10090031, 0x1009002e, 0x1009002c,
+	0x10090029, 0x10090027, 0x10090025, 0x10090023,
+	0x10090021, 0x1009001f, 0x1009001d, 0x1009001b,
+	0x1009001a, 0x10090018, 0x10090017, 0x10090016,
+	0x10090015, 0x10090013, 0x10090012, 0x10090011,
+	0x10090010, 0x1009000f, 0x1009000f, 0x1009000e,
+	0x1009000d, 0x1009000c, 0x1009000c, 0x1009000b,
+	0x1009000a, 0x1009000a, 0x10090009, 0x10090009,
+	0x10090008, 0x10090008, 0x10090007, 0x10090007,
+	0x10090007, 0x10090006, 0x10090006, 0x10090005,
+	0x10090005, 0x10090005, 0x10090005, 0x10090004,
+	0x10090004, 0x10090004, 0x10090004, 0x10090003,
+	0x10090003, 0x10090003, 0x10090003, 0x10090003,
+	0x10090003, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090002, 0x10090002,
+	0x10090002, 0x10090002, 0x10090001, 0x10090001,
+	0x10090001, 0x10090001, 0x10090001, 0x10090001
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev3[] = {
+	0xcff70044, 0xcff70042, 0xcff70040, 0xcff7003e,
+	0xcff7003c, 0xcff7003b, 0xcff70039, 0xcff70037,
+	0xcef70044, 0xcef70042, 0xcef70040, 0xcef7003e,
+	0xcef7003c, 0xcef7003b, 0xcef70039, 0xcef70037,
+	0xcdf70044, 0xcdf70042, 0xcdf70040, 0xcdf7003e,
+	0xcdf7003c, 0xcdf7003b, 0xcdf70039, 0xcdf70037,
+	0xccf70044, 0xccf70042, 0xccf70040, 0xccf7003e,
+	0xccf7003c, 0xccf7003b, 0xccf70039, 0xccf70037,
+	0xcbf70044, 0xcbf70042, 0xcbf70040, 0xcbf7003e,
+	0xcbf7003c, 0xcbf7003b, 0xcbf70039, 0xcbf70037,
+	0xcaf70044, 0xcaf70042, 0xcaf70040, 0xcaf7003e,
+	0xcaf7003c, 0xcaf7003b, 0xcaf70039, 0xcaf70037,
+	0xc9f70044, 0xc9f70042, 0xc9f70040, 0xc9f7003e,
+	0xc9f7003c, 0xc9f7003b, 0xc9f70039, 0xc9f70037,
+	0xc8f70044, 0xc8f70042, 0xc8f70040, 0xc8f7003e,
+	0xc8f7003c, 0xc8f7003b, 0xc8f70039, 0xc8f70037,
+	0xc7f70044, 0xc7f70042, 0xc7f70040, 0xc7f7003e,
+	0xc7f7003c, 0xc7f7003b, 0xc7f70039, 0xc7f70037,
+	0xc6f70044, 0xc6f70042, 0xc6f70040, 0xc6f7003e,
+	0xc6f7003c, 0xc6f7003b, 0xc6f70039, 0xc6f70037,
+	0xc5f70044, 0xc5f70042, 0xc5f70040, 0xc5f7003e,
+	0xc5f7003c, 0xc5f7003b, 0xc5f70039, 0xc5f70037,
+	0xc4f70044, 0xc4f70042, 0xc4f70040, 0xc4f7003e,
+	0xc4f7003c, 0xc4f7003b, 0xc4f70039, 0xc4f70037,
+	0xc3f70044, 0xc3f70042, 0xc3f70040, 0xc3f7003e,
+	0xc3f7003c, 0xc3f7003b, 0xc3f70039, 0xc3f70037,
+	0xc2f70044, 0xc2f70042, 0xc2f70040, 0xc2f7003e,
+	0xc2f7003c, 0xc2f7003b, 0xc2f70039, 0xc2f70037,
+	0xc1f70044, 0xc1f70042, 0xc1f70040, 0xc1f7003e,
+	0xc1f7003c, 0xc1f7003b, 0xc1f70039, 0xc1f70037,
+	0xc0f70044, 0xc0f70042, 0xc0f70040, 0xc0f7003e,
+	0xc0f7003c, 0xc0f7003b, 0xc0f70039, 0xc0f70037
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev4[] = {
+	0x2ff20044, 0x2ff20042, 0x2ff20040, 0x2ff2003e,
+	0x2ff2003c, 0x2ff2003b, 0x2ff20039, 0x2ff20037,
+	0x2ef20044, 0x2ef20042, 0x2ef20040, 0x2ef2003e,
+	0x2ef2003c, 0x2ef2003b, 0x2ef20039, 0x2ef20037,
+	0x2df20044, 0x2df20042, 0x2df20040, 0x2df2003e,
+	0x2df2003c, 0x2df2003b, 0x2df20039, 0x2df20037,
+	0x2cf20044, 0x2cf20042, 0x2cf20040, 0x2cf2003e,
+	0x2cf2003c, 0x2cf2003b, 0x2cf20039, 0x2cf20037,
+	0x2bf20044, 0x2bf20042, 0x2bf20040, 0x2bf2003e,
+	0x2bf2003c, 0x2bf2003b, 0x2bf20039, 0x2bf20037,
+	0x2af20044, 0x2af20042, 0x2af20040, 0x2af2003e,
+	0x2af2003c, 0x2af2003b, 0x2af20039, 0x2af20037,
+	0x29f20044, 0x29f20042, 0x29f20040, 0x29f2003e,
+	0x29f2003c, 0x29f2003b, 0x29f20039, 0x29f20037,
+	0x28f20044, 0x28f20042, 0x28f20040, 0x28f2003e,
+	0x28f2003c, 0x28f2003b, 0x28f20039, 0x28f20037,
+	0x27f20044, 0x27f20042, 0x27f20040, 0x27f2003e,
+	0x27f2003c, 0x27f2003b, 0x27f20039, 0x27f20037,
+	0x26f20044, 0x26f20042, 0x26f20040, 0x26f2003e,
+	0x26f2003c, 0x26f2003b, 0x26f20039, 0x26f20037,
+	0x25f20044, 0x25f20042, 0x25f20040, 0x25f2003e,
+	0x25f2003c, 0x25f2003b, 0x25f20039, 0x25f20037,
+	0x24f20044, 0x24f20042, 0x24f20040, 0x24f2003e,
+	0x24f2003c, 0x24f2003b, 0x24f20039, 0x24f20038,
+	0x23f20041, 0x23f20040, 0x23f2003f, 0x23f2003e,
+	0x23f2003c, 0x23f2003b, 0x23f20039, 0x23f20037,
+	0x22f20044, 0x22f20042, 0x22f20040, 0x22f2003e,
+	0x22f2003c, 0x22f2003b, 0x22f20039, 0x22f20037,
+	0x21f20044, 0x21f20042, 0x21f20040, 0x21f2003e,
+	0x21f2003c, 0x21f2003b, 0x21f20039, 0x21f20037,
+	0x20d20043, 0x20d20041, 0x20d2003e, 0x20d2003c,
+	0x20d2003a, 0x20d20038, 0x20d20036, 0x20d20034
+};
+
+static u32 nphy_tpc_5GHz_txgain_rev5[] = {
+	0x0f62004a, 0x0f620048, 0x0f620046, 0x0f620044,
+	0x0f620042, 0x0f620040, 0x0f62003e, 0x0f62003c,
+	0x0e620044, 0x0e620042, 0x0e620040, 0x0e62003e,
+	0x0e62003c, 0x0e62003d, 0x0e62003b, 0x0e62003a,
+	0x0d620043, 0x0d620041, 0x0d620040, 0x0d62003e,
+	0x0d62003d, 0x0d62003c, 0x0d62003b, 0x0d62003a,
+	0x0c620041, 0x0c620040, 0x0c62003f, 0x0c62003e,
+	0x0c62003c, 0x0c62003b, 0x0c620039, 0x0c620037,
+	0x0b620046, 0x0b620044, 0x0b620042, 0x0b620040,
+	0x0b62003e, 0x0b62003c, 0x0b62003b, 0x0b62003a,
+	0x0a620041, 0x0a620040, 0x0a62003e, 0x0a62003c,
+	0x0a62003b, 0x0a62003a, 0x0a620039, 0x0a620038,
+	0x0962003e, 0x0962003d, 0x0962003c, 0x0962003b,
+	0x09620039, 0x09620037, 0x09620035, 0x09620033,
+	0x08620044, 0x08620042, 0x08620040, 0x0862003e,
+	0x0862003c, 0x0862003b, 0x0862003a, 0x08620039,
+	0x07620043, 0x07620042, 0x07620040, 0x0762003f,
+	0x0762003d, 0x0762003b, 0x0762003a, 0x07620039,
+	0x0662003e, 0x0662003d, 0x0662003c, 0x0662003b,
+	0x06620039, 0x06620037, 0x06620035, 0x06620033,
+	0x05620046, 0x05620044, 0x05620042, 0x05620040,
+	0x0562003e, 0x0562003c, 0x0562003b, 0x05620039,
+	0x04620044, 0x04620042, 0x04620040, 0x0462003e,
+	0x0462003c, 0x0462003b, 0x04620039, 0x04620038,
+	0x0362003c, 0x0362003b, 0x0362003a, 0x03620039,
+	0x03620038, 0x03620037, 0x03620035, 0x03620033,
+	0x0262004c, 0x0262004a, 0x02620048, 0x02620047,
+	0x02620046, 0x02620044, 0x02620043, 0x02620042,
+	0x0162004a, 0x01620048, 0x01620046, 0x01620044,
+	0x01620043, 0x01620042, 0x01620041, 0x01620040,
+	0x00620042, 0x00620040, 0x0062003e, 0x0062003c,
+	0x0062003b, 0x00620039, 0x00620037, 0x00620035
+};
+
+static u32 nphy_tpc_5GHz_txgain_HiPwrEPA[] = {
+	0x2ff10044, 0x2ff10042, 0x2ff10040, 0x2ff1003e,
+	0x2ff1003c, 0x2ff1003b, 0x2ff10039, 0x2ff10037,
+	0x2ef10044, 0x2ef10042, 0x2ef10040, 0x2ef1003e,
+	0x2ef1003c, 0x2ef1003b, 0x2ef10039, 0x2ef10037,
+	0x2df10044, 0x2df10042, 0x2df10040, 0x2df1003e,
+	0x2df1003c, 0x2df1003b, 0x2df10039, 0x2df10037,
+	0x2cf10044, 0x2cf10042, 0x2cf10040, 0x2cf1003e,
+	0x2cf1003c, 0x2cf1003b, 0x2cf10039, 0x2cf10037,
+	0x2bf10044, 0x2bf10042, 0x2bf10040, 0x2bf1003e,
+	0x2bf1003c, 0x2bf1003b, 0x2bf10039, 0x2bf10037,
+	0x2af10044, 0x2af10042, 0x2af10040, 0x2af1003e,
+	0x2af1003c, 0x2af1003b, 0x2af10039, 0x2af10037,
+	0x29f10044, 0x29f10042, 0x29f10040, 0x29f1003e,
+	0x29f1003c, 0x29f1003b, 0x29f10039, 0x29f10037,
+	0x28f10044, 0x28f10042, 0x28f10040, 0x28f1003e,
+	0x28f1003c, 0x28f1003b, 0x28f10039, 0x28f10037,
+	0x27f10044, 0x27f10042, 0x27f10040, 0x27f1003e,
+	0x27f1003c, 0x27f1003b, 0x27f10039, 0x27f10037,
+	0x26f10044, 0x26f10042, 0x26f10040, 0x26f1003e,
+	0x26f1003c, 0x26f1003b, 0x26f10039, 0x26f10037,
+	0x25f10044, 0x25f10042, 0x25f10040, 0x25f1003e,
+	0x25f1003c, 0x25f1003b, 0x25f10039, 0x25f10037,
+	0x24f10044, 0x24f10042, 0x24f10040, 0x24f1003e,
+	0x24f1003c, 0x24f1003b, 0x24f10039, 0x24f10038,
+	0x23f10041, 0x23f10040, 0x23f1003f, 0x23f1003e,
+	0x23f1003c, 0x23f1003b, 0x23f10039, 0x23f10037,
+	0x22f10044, 0x22f10042, 0x22f10040, 0x22f1003e,
+	0x22f1003c, 0x22f1003b, 0x22f10039, 0x22f10037,
+	0x21f10044, 0x21f10042, 0x21f10040, 0x21f1003e,
+	0x21f1003c, 0x21f1003b, 0x21f10039, 0x21f10037,
+	0x20d10043, 0x20d10041, 0x20d1003e, 0x20d1003c,
+	0x20d1003a, 0x20d10038, 0x20d10036, 0x20d10034
+};
+
+static u8 ant_sw_ctrl_tbl_rev8_2o3[] = { 0x14, 0x18 };
+static u8 ant_sw_ctrl_tbl_rev8[] = { 0x4, 0x8, 0x4, 0x8, 0x11, 0x12 };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core0[] = {
+	0x09, 0x0a, 0x15, 0x16, 0x09, 0x0a };
+static u8 ant_sw_ctrl_tbl_rev8_2057v7_core1[] = {
+	0x09, 0x0a, 0x09, 0x0a, 0x15, 0x16 };
+
+static bool wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
+				   chan_info_nphy_radio2057_t **t0,
+				   chan_info_nphy_radio205x_t **t1,
+				   chan_info_nphy_radio2057_rev5_t **t2,
+				   chan_info_nphy_2055_t **t3);
+static void wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chans,
+					const nphy_sfo_cfg_t *c);
+
+static void wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi,
+					    u16 reduction_factr);
+static void wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *,
+					     u32 *buf);
+static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr);
+static void wlc_phy_txlpfbw_nphy(phy_info_t *pi);
+static void wlc_phy_spurwar_nphy(phy_info_t *pi);
+
+static void wlc_phy_radio_preinit_2055(phy_info_t *pi);
+static void wlc_phy_radio_init_2055(phy_info_t *pi);
+static void wlc_phy_radio_postinit_2055(phy_info_t *pi);
+static void wlc_phy_radio_preinit_205x(phy_info_t *pi);
+static void wlc_phy_radio_init_2056(phy_info_t *pi);
+static void wlc_phy_radio_postinit_2056(phy_info_t *pi);
+static void wlc_phy_radio_init_2057(phy_info_t *pi);
+static void wlc_phy_radio_postinit_2057(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi);
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi);
+static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi);
+
+static void wlc_phy_restore_rssical_nphy(phy_info_t *pi);
+static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi);
+static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi);
+static int wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t tg,
+				      u8 type, bool d);
+static void wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rxcore,
+					     u16 *rg, u8 type);
+static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble);
+static void wlc_phy_savecal_nphy(phy_info_t *pi);
+static void wlc_phy_restorecal_nphy(phy_info_t *pi);
+static void wlc_phy_resetcca_nphy(phy_info_t *pi);
+
+static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi);
+static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi);
+static void wlc_phy_precal_txgain_nphy(phy_info_t *pi);
+static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core);
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi);
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi);
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi);
+static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi);
+static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1);
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi);
+
+static void wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32,
+			    u32 e);
+static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core);
+static void wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *,
+			    phy_cal_mode_t, u8);
+static void wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi,
+					  nphy_papd_restore_state *state);
+static void wlc_phy_papd_cal_setup_nphy(phy_info_t *pi,
+					nphy_papd_restore_state *state, u8);
+
+static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals);
+
+static void wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *evts,
+				   u8 *dlys, u8 len);
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset);
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off,
+				  u8 override_id);
+
+static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type);
+static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi);
+
+static bool wlc_phy_txpwr_srom_read_nphy(phy_info_t *pi);
+static void wlc_phy_txpwr_nphy_srom_convert(u8 *srom_max,
+					    u16 *pwr_offset,
+					    u8 tmp_max_pwr, u8 rate_start,
+					    u8 rate_end);
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi);
+static void wlc_phy_txpwrctrl_coeff_setup_nphy(phy_info_t *pi);
+static void wlc_phy_txpwrctrl_idle_tssi_nphy(phy_info_t *pi);
+static void wlc_phy_txpwrctrl_pwr_setup_nphy(phy_info_t *pi);
+
+static bool wlc_phy_txpwr_ison_nphy(phy_info_t *pi);
+static u8 wlc_phy_txpwr_idx_cur_get_nphy(phy_info_t *pi, u8 core);
+static void wlc_phy_txpwr_idx_cur_set_nphy(phy_info_t *pi, u8 idx0,
+					   u8 idx1);
+static void wlc_phy_a4(phy_info_t *pi, bool full_cal);
+
+static u16 wlc_phy_radio205x_rcal(phy_info_t *pi);
+
+static u16 wlc_phy_radio2057_rccal(phy_info_t *pi);
+
+static u16 wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz,
+					    u16 max_val,
+					    u8 dac_test_mode);
+static void wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
+					 u16 num_samps);
+static void wlc_phy_runsamples_nphy(phy_info_t *pi, u16 n, u16 lps,
+				    u16 wait, u8 iq, u8 dac_test_mode,
+				    bool modify_bbmult);
+
+bool wlc_phy_bist_check_phy(wlc_phy_t *pih)
+{
+	phy_info_t *pi = (phy_info_t *) pih;
+	u32 phybist0, phybist1, phybist2, phybist3, phybist4;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16))
+		return true;
+
+	phybist0 = read_phy_reg(pi, 0x0e);
+	phybist1 = read_phy_reg(pi, 0x0f);
+	phybist2 = read_phy_reg(pi, 0xea);
+	phybist3 = read_phy_reg(pi, 0xeb);
+	phybist4 = read_phy_reg(pi, 0x156);
+
+	if ((phybist0 == 0) && (phybist1 == 0x4000) && (phybist2 == 0x1fe0) &&
+	    (phybist3 == 0) && (phybist4 == 0)) {
+		return true;
+	}
+
+	return false;
+}
+
+static void WLBANDINITFN(wlc_phy_bphy_init_nphy) (phy_info_t *pi)
+{
+	u16 addr, val;
+
+	ASSERT(ISNPHY(pi));
+
+	val = 0x1e1f;
+	for (addr = (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT);
+	     addr <= (NPHY_TO_BPHY_OFF + BPHY_RSSI_LUT_END); addr++) {
+		write_phy_reg(pi, addr, val);
+		if (addr == (NPHY_TO_BPHY_OFF + 0x97))
+			val = 0x3e3f;
+		else
+			val -= 0x0202;
+	}
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_PHYCRSTH, 0x3206);
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_RSSI_TRESH, 0x281e);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_LNA_GAIN_RANGE, 0x1a);
+
+	} else {
+
+		write_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_STEP, 0x668);
+	}
+}
+
+void
+wlc_phy_table_write_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
+			 u32 width, const void *data)
+{
+	mimophytbl_info_t tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_write_table_nphy(pi, &tbl);
+}
+
+void
+wlc_phy_table_read_nphy(phy_info_t *pi, u32 id, u32 len, u32 offset,
+			u32 width, void *data)
+{
+	mimophytbl_info_t tbl;
+
+	tbl.tbl_id = id;
+	tbl.tbl_len = len;
+	tbl.tbl_offset = offset;
+	tbl.tbl_width = width;
+	tbl.tbl_ptr = data;
+	wlc_phy_read_table_nphy(pi, &tbl);
+}
+
+static void WLBANDINITFN(wlc_phy_static_table_download_nphy) (phy_info_t *pi)
+{
+	uint idx;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 16)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev16; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev16[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev7; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev7[idx]);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev3[idx]);
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0; idx++)
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0[idx]);
+	}
+}
+
+static void WLBANDINITFN(wlc_phy_tbl_init_nphy) (phy_info_t *pi)
+{
+	uint idx = 0;
+	u8 antswctrllut;
+
+	if (pi->phy_init_por)
+		wlc_phy_static_table_download_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+		    pi->srom_fem2g.antswctrllut : pi->srom_fem5g.antswctrllut;
+
+		switch (antswctrllut) {
+		case 0:
+
+			break;
+
+		case 1:
+
+			if (pi->aa2g == 7) {
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_ANTSWCTRLLUT,
+							 2, 0x21, 8,
+							 &ant_sw_ctrl_tbl_rev8_2o3
+							 [0]);
+			} else {
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_ANTSWCTRLLUT,
+							 2, 0x21, 8,
+							 &ant_sw_ctrl_tbl_rev8
+							 [0]);
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8[2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8[4]);
+			break;
+
+		case 2:
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x1, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [0]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x5, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x9, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core0
+						 [4]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x21, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [0]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x25, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [2]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 2, 0x29, 8,
+						 &ant_sw_ctrl_tbl_rev8_2057v7_core1
+						 [4]);
+			break;
+
+		default:
+
+			ASSERT(0);
+			break;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (idx = 0; idx < mimophytbl_info_sz_rev3_volatile; idx++) {
+
+			if (idx == ANT_SWCTRL_TBL_REV3_IDX) {
+				antswctrllut = CHSPEC_IS2G(pi->radio_chanspec) ?
+				    pi->srom_fem2g.antswctrllut : pi->
+				    srom_fem5g.antswctrllut;
+				switch (antswctrllut) {
+				case 0:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile
+								 [idx]);
+					break;
+				case 1:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile1
+								 [idx]);
+					break;
+				case 2:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile2
+								 [idx]);
+					break;
+				case 3:
+					wlc_phy_write_table_nphy(pi,
+								 &mimophytbl_info_rev3_volatile3
+								 [idx]);
+					break;
+				default:
+
+					ASSERT(0);
+					break;
+				}
+			} else {
+				wlc_phy_write_table_nphy(pi,
+							 &mimophytbl_info_rev3_volatile
+							 [idx]);
+			}
+		}
+	} else {
+		for (idx = 0; idx < mimophytbl_info_sz_rev0_volatile; idx++) {
+			wlc_phy_write_table_nphy(pi,
+						 &mimophytbl_info_rev0_volatile
+						 [idx]);
+		}
+	}
+}
+
+static void
+wlc_phy_write_txmacreg_nphy(phy_info_t *pi, u16 holdoff, u16 delay)
+{
+	write_phy_reg(pi, 0x77, holdoff);
+	write_phy_reg(pi, 0xb4, delay);
+}
+
+void wlc_phy_nphy_tkip_rifs_war(phy_info_t *pi, u8 rifs)
+{
+	u16 holdoff, delay;
+
+	if (rifs) {
+
+		holdoff = 0x10;
+		delay = 0x258;
+	} else {
+
+		holdoff = 0x15;
+		delay = 0x320;
+	}
+
+	wlc_phy_write_txmacreg_nphy(pi, holdoff, delay);
+
+	if (pi && pi->sh && (pi->sh->_rifs_phy != rifs)) {
+		pi->sh->_rifs_phy = rifs;
+	}
+}
+
+bool wlc_phy_attach_nphy(phy_info_t *pi)
+{
+	uint i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 6)) {
+		pi->phyhang_avoid = true;
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		pi->nphy_gband_spurwar_en = true;
+
+		if (pi->sh->boardflags2 & BFL2_SPUR_WAR) {
+			pi->nphy_aband_spurwar_en = true;
+		}
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 6) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->sh->boardflags2 & BFL2_2G_SPUR_WAR) {
+			pi->nphy_gband_spurwar2_en = true;
+		}
+	}
+
+	pi->n_preamble_override = AUTO;
+	if (NREV_IS(pi->pubpi.phy_rev, 3) || NREV_IS(pi->pubpi.phy_rev, 4))
+		pi->n_preamble_override = WLC_N_PREAMBLE_MIXEDMODE;
+
+	pi->nphy_txrx_chain = AUTO;
+	pi->phy_scraminit = AUTO;
+
+	pi->nphy_rxcalparams = 0x010100B5;
+
+	pi->nphy_perical = PHY_PERICAL_MPHASE;
+	pi->mphase_cal_phase_id = MPHASE_CAL_STATE_IDLE;
+	pi->mphase_txcal_numcmds = MPHASE_TXCAL_NUMCMDS;
+
+	pi->nphy_gain_boost = true;
+	pi->nphy_elna_gain_config = false;
+	pi->radio_is_on = false;
+
+	for (i = 0; i < pi->pubpi.phy_corenum; i++) {
+		pi->nphy_txpwrindex[i].index = AUTO;
+	}
+
+	wlc_phy_txpwrctrl_config_nphy(pi);
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_ON)
+		pi->hwpwrctrl_capable = true;
+
+	pi->pi_fptr.init = wlc_phy_init_nphy;
+	pi->pi_fptr.calinit = wlc_phy_cal_init_nphy;
+	pi->pi_fptr.chanset = wlc_phy_chanspec_set_nphy;
+	pi->pi_fptr.txpwrrecalc = wlc_phy_txpower_recalc_target_nphy;
+
+	if (!wlc_phy_txpwr_srom_read_nphy(pi))
+		return false;
+
+	return true;
+}
+
+static void wlc_phy_txpwrctrl_config_nphy(phy_info_t *pi)
+{
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+		pi->phy_5g_pwrgain = true;
+		return;
+	}
+
+	pi->nphy_txpwrctrl = PHY_TPC_HW_OFF;
+	pi->phy_5g_pwrgain = false;
+
+	if ((pi->sh->boardflags2 & BFL2_TXPWRCTRL_EN) &&
+	    NREV_GE(pi->pubpi.phy_rev, 2) && (pi->sh->sromrev >= 4))
+		pi->nphy_txpwrctrl = PHY_TPC_HW_ON;
+	else if ((pi->sh->sromrev >= 4)
+		 && (pi->sh->boardflags2 & BFL2_5G_PWRGAIN))
+		pi->phy_5g_pwrgain = true;
+}
+
+void WLBANDINITFN(wlc_phy_init_nphy) (phy_info_t *pi)
+{
+	u16 val;
+	u16 clip1_ths[2];
+	nphy_txgains_t target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool do_nphy_cal = false;
+	uint core;
+	uint origidx, intr_val;
+	d11regs_t *regs;
+	u32 d11_clk_ctl_st;
+
+	core = 0;
+
+	if (!(pi->measure_hold & PHY_HOLD_FOR_SCAN)) {
+		pi->measure_hold |= PHY_HOLD_FOR_NOT_ASSOC;
+	}
+
+	if ((ISNPHY(pi)) && (NREV_GE(pi->pubpi.phy_rev, 5)) &&
+	    ((pi->sh->chippkg == BCM4717_PKG_ID) ||
+	     (pi->sh->chippkg == BCM4718_PKG_ID))) {
+		if ((pi->sh->boardflags & BFL_EXTLNA) &&
+		    (CHSPEC_IS2G(pi->radio_chanspec))) {
+			si_corereg(pi->sh->sih, SI_CC_IDX,
+				   offsetof(chipcregs_t, chipcontrol), 0x40,
+				   0x40);
+		}
+	}
+
+	if ((!PHY_IPA(pi)) && (pi->sh->chip == BCM5357_CHIP_ID)) {
+		si_pmu_chipcontrol(pi->sh->sih, 1, CCTRL5357_EXTPA,
+				   CCTRL5357_EXTPA);
+	}
+
+	if ((pi->nphy_gband_spurwar2_en) && CHSPEC_IS2G(pi->radio_chanspec) &&
+	    CHSPEC_IS40(pi->radio_chanspec)) {
+
+		regs = (d11regs_t *) si_switch_core(pi->sh->sih, D11_CORE_ID,
+						    &origidx, &intr_val);
+		ASSERT(regs != NULL);
+
+		d11_clk_ctl_st = R_REG(&regs->clk_ctl_st);
+		AND_REG(&regs->clk_ctl_st,
+			~(CCS_FORCEHT | CCS_HTAREQ));
+
+		W_REG(&regs->clk_ctl_st, d11_clk_ctl_st);
+
+		si_restore_core(pi->sh->sih, origidx, intr_val);
+	}
+
+	pi->use_int_tx_iqlo_cal_nphy =
+	    (PHY_IPA(pi) ||
+	     (NREV_GE(pi->pubpi.phy_rev, 7) ||
+	      (NREV_GE(pi->pubpi.phy_rev, 5)
+	       && pi->sh->boardflags2 & BFL2_INTERNDET_TXIQCAL)));
+
+	pi->internal_tx_iqlo_cal_tapoff_intpa_nphy = false;
+
+	pi->nphy_deaf_count = 0;
+
+	wlc_phy_tbl_init_nphy(pi);
+
+	pi->nphy_crsminpwr_adjusted = false;
+	pi->nphy_noisevars_adjusted = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xe7, 0);
+		write_phy_reg(pi, 0xec, 0);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_phy_reg(pi, 0x342, 0);
+			write_phy_reg(pi, 0x343, 0);
+			write_phy_reg(pi, 0x346, 0);
+			write_phy_reg(pi, 0x347, 0);
+		}
+		write_phy_reg(pi, 0xe5, 0);
+		write_phy_reg(pi, 0xe6, 0);
+	} else {
+		write_phy_reg(pi, 0xec, 0);
+	}
+
+	write_phy_reg(pi, 0x91, 0);
+	write_phy_reg(pi, 0x92, 0);
+	if (NREV_LT(pi->pubpi.phy_rev, 6)) {
+		write_phy_reg(pi, 0x93, 0);
+		write_phy_reg(pi, 0x94, 0);
+	}
+
+	and_phy_reg(pi, 0xa1, ~3);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0x8f, 0);
+		write_phy_reg(pi, 0xa5, 0);
+	} else {
+		write_phy_reg(pi, 0xa5, 0);
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x3b);
+	else if (NREV_LT(pi->pubpi.phy_rev, 2))
+		mod_phy_reg(pi, 0xdc, 0x00ff, 0x40);
+
+	write_phy_reg(pi, 0x203, 32);
+	write_phy_reg(pi, 0x201, 32);
+
+	if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD)
+		write_phy_reg(pi, 0x20d, 160);
+	else
+		write_phy_reg(pi, 0x20d, 184);
+
+	write_phy_reg(pi, 0x13a, 200);
+
+	write_phy_reg(pi, 0x70, 80);
+
+	write_phy_reg(pi, 0x1ff, 48);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 8)) {
+		wlc_phy_update_mimoconfig_nphy(pi, pi->n_preamble_override);
+	}
+
+	wlc_phy_stf_chain_upd_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0x180, 0xaa8);
+		write_phy_reg(pi, 0x181, 0x9a4);
+	}
+
+	if (PHY_IPA(pi)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+				    0x29b, (0x1 << 0), (1) << 0);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x298 :
+				    0x29c, (0x1ff << 7),
+				    (pi->nphy_papd_epsilon_offset[core]) << 7);
+
+		}
+
+		wlc_phy_ipa_set_tx_digi_filts_nphy(pi);
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_extpa_set_tx_digi_filts_nphy(pi);
+		}
+	}
+
+	wlc_phy_workarounds_nphy(pi);
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlapi_bmac_macphyclk_set(pi->sh->physhim, ON);
+
+	wlc_phy_pa_override_nphy(pi, OFF);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	wlc_phy_pa_override_nphy(pi, ON);
+
+	wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_clip_det_nphy(pi, 0, clip1_ths);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		wlc_phy_bphy_init_nphy(pi);
+
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	wlc_phy_txpwr_fixpower_nphy(pi);
+
+	wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+
+	wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u32 *tx_pwrctrl_tbl = NULL;
+		u16 idx;
+		s16 pga_gn = 0;
+		s16 pad_gn = 0;
+		s32 rfpwr_offset = 0;
+
+		if (PHY_IPA(pi)) {
+			tx_pwrctrl_tbl = wlc_phy_get_ipa_gaintbl_nphy(pi);
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if NREV_IS
+					(pi->pubpi.phy_rev, 3) {
+					tx_pwrctrl_tbl =
+					    nphy_tpc_5GHz_txgain_rev3;
+				} else if NREV_IS
+					(pi->pubpi.phy_rev, 4) {
+					tx_pwrctrl_tbl =
+					    (pi->srom_fem5g.extpagain == 3) ?
+					    nphy_tpc_5GHz_txgain_HiPwrEPA :
+					    nphy_tpc_5GHz_txgain_rev4;
+				} else {
+					tx_pwrctrl_tbl =
+					    nphy_tpc_5GHz_txgain_rev5;
+				}
+
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (pi->pubpi.radiorev == 5) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_epa_2057rev5;
+					} else if (pi->pubpi.radiorev == 3) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_epa_2057rev3;
+					}
+
+				} else {
+					if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+					    (pi->srom_fem2g.extpagain == 3)) {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_HiPwrEPA;
+					} else {
+						tx_pwrctrl_tbl =
+						    nphy_tpc_txgain_rev3;
+					}
+				}
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, tx_pwrctrl_tbl);
+
+		pi->nphy_gmval = (u16) ((*tx_pwrctrl_tbl >> 16) & 0x7000);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				pad_gn = (tx_pwrctrl_tbl[idx] >> 19) & 0x1f;
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if ((pi->pubpi.radiorev == 3) ||
+					    (pi->pubpi.radiorev == 4) ||
+					    (pi->pubpi.radiorev == 6)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev3n4
+						    [pad_gn];
+					} else if (pi->pubpi.radiorev == 5) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev5
+						    [pad_gn];
+					} else if ((pi->pubpi.radiorev == 7)
+						   || (pi->pubpi.radiorev ==
+						       8)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_padgain_dlt_2g_2057rev7
+						    [pad_gn];
+					} else {
+						ASSERT(0);
+					}
+
+				} else {
+					if ((pi->pubpi.radiorev == 3) ||
+					    (pi->pubpi.radiorev == 4) ||
+					    (pi->pubpi.radiorev == 6)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_pgagain_dlt_5g_2057
+						    [pga_gn];
+					} else if ((pi->pubpi.radiorev == 7)
+						   || (pi->pubpi.radiorev ==
+						       8)) {
+						rfpwr_offset = (s16)
+						    nphy_papd_pgagain_dlt_5g_2057rev7
+						    [pga_gn];
+					} else {
+						ASSERT(0);
+					}
+				}
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE1TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE2TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+			}
+		} else {
+
+			for (idx = 0; idx < 128; idx++) {
+				pga_gn = (tx_pwrctrl_tbl[idx] >> 24) & 0xf;
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					rfpwr_offset = (s16)
+					    nphy_papd_pga_gain_delta_ipa_2g
+					    [pga_gn];
+				} else {
+					rfpwr_offset = (s16)
+					    nphy_papd_pga_gain_delta_ipa_5g
+					    [pga_gn];
+				}
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE1TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_CORE2TXPWRCTL,
+							 1, 576 + idx, 32,
+							 &rfpwr_offset);
+			}
+
+		}
+	} else {
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 128,
+					 192, 32, nphy_tpc_txgain);
+	}
+
+	if (pi->sh->phyrxchain != 0x3) {
+		wlc_phy_rxcore_setstate_nphy((wlc_phy_t *) pi,
+					     pi->sh->phyrxchain);
+	}
+
+	if (PHY_PERICAL_MPHASE_PENDING(pi)) {
+		wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if (!NORADIO_ENAB(pi->pubpi)) {
+		bool do_rssi_cal = false;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			do_rssi_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			    (pi->nphy_rssical_chanspec_2G == 0) :
+			    (pi->nphy_rssical_chanspec_5G == 0);
+
+			if (do_rssi_cal) {
+				wlc_phy_rssi_cal_nphy(pi);
+			} else {
+				wlc_phy_restore_rssical_nphy(pi);
+			}
+		} else {
+			wlc_phy_rssi_cal_nphy(pi);
+		}
+
+		if (!SCAN_RM_IN_PROGRESS(pi)) {
+			do_nphy_cal = (CHSPEC_IS2G(pi->radio_chanspec)) ?
+			    (pi->nphy_iqcal_chanspec_2G == 0) :
+			    (pi->nphy_iqcal_chanspec_5G == 0);
+		}
+
+		if (!pi->do_initcal)
+			do_nphy_cal = false;
+
+		if (do_nphy_cal) {
+
+			target_gain = wlc_phy_get_tx_gain_nphy(pi);
+
+			if (pi->antsel_type == ANTSEL_2x3)
+				wlc_phy_antsel_init((wlc_phy_t *) pi, true);
+
+			if (pi->nphy_perical != PHY_PERICAL_MPHASE) {
+				wlc_phy_rssi_cal_nphy(pi);
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					pi->nphy_cal_orig_pwr_idx[0] =
+					    pi->nphy_txpwrindex[PHY_CORE_0].
+					    index_internal;
+					pi->nphy_cal_orig_pwr_idx[1] =
+					    pi->nphy_txpwrindex[PHY_CORE_1].
+					    index_internal;
+
+					wlc_phy_precal_txgain_nphy(pi);
+					target_gain =
+					    wlc_phy_get_tx_gain_nphy(pi);
+				}
+
+				if (wlc_phy_cal_txiqlo_nphy
+				    (pi, target_gain, true, false) == BCME_OK) {
+					if (wlc_phy_cal_rxiq_nphy
+					    (pi, target_gain, 2,
+					     false) == BCME_OK) {
+						wlc_phy_savecal_nphy(pi);
+
+					}
+				}
+			} else if (pi->mphase_cal_phase_id ==
+				   MPHASE_CAL_STATE_IDLE) {
+
+				wlc_phy_cal_perical((wlc_phy_t *) pi,
+						    PHY_PERICAL_PHYINIT);
+			}
+		} else {
+			wlc_phy_restorecal_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+
+	wlc_phy_nphy_tkip_rifs_war(pi, pi->sh->_rifs_phy);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LE(pi->pubpi.phy_rev, 6))
+
+		write_phy_reg(pi, 0x70, 50);
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	wlc_phy_spurwar_nphy(pi);
+
+}
+
+static void wlc_phy_update_mimoconfig_nphy(phy_info_t *pi, s32 preamble)
+{
+	bool gf_preamble = false;
+	u16 val;
+
+	if (preamble == WLC_N_PREAMBLE_GF) {
+		gf_preamble = true;
+	}
+
+	val = read_phy_reg(pi, 0xed);
+
+	val |= RX_GF_MM_AUTO;
+	val &= ~RX_GF_OR_MM;
+	if (gf_preamble)
+		val |= RX_GF_OR_MM;
+
+	write_phy_reg(pi, 0xed, val);
+}
+
+static void wlc_phy_resetcca_nphy(phy_info_t *pi)
+{
+	u16 val;
+
+	ASSERT(0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, ON);
+
+	val = read_phy_reg(pi, 0x01);
+	write_phy_reg(pi, 0x01, val | BBCFG_RESETCCA);
+	udelay(1);
+	write_phy_reg(pi, 0x01, val & (~BBCFG_RESETCCA));
+
+	wlapi_bmac_phyclk_fgc(pi->sh->physhim, OFF);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+}
+
+void wlc_phy_pa_override_nphy(phy_info_t *pi, bool en)
+{
+	u16 rfctrlintc_override_val;
+
+	if (!en) {
+
+		pi->rfctrlIntc1_save = read_phy_reg(pi, 0x91);
+		pi->rfctrlIntc2_save = read_phy_reg(pi, 0x92);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			rfctrlintc_override_val = 0x1480;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			rfctrlintc_override_val =
+			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x600 : 0x480;
+		} else {
+			rfctrlintc_override_val =
+			    CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		}
+
+		write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+		write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	} else {
+
+		write_phy_reg(pi, 0x91, pi->rfctrlIntc1_save);
+		write_phy_reg(pi, 0x92, pi->rfctrlIntc2_save);
+	}
+
+}
+
+void wlc_phy_stf_chain_upd_nphy(phy_info_t *pi)
+{
+
+	u16 txrx_chain =
+	    (NPHY_RfseqCoreActv_TxRxChain0 | NPHY_RfseqCoreActv_TxRxChain1);
+	bool CoreActv_override = false;
+
+	if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN0) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain0;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
+			and_phy_reg(pi, 0xa0, ~0x20);
+		}
+	} else if (pi->nphy_txrx_chain == WLC_N_TXRX_CHAIN1) {
+		txrx_chain = NPHY_RfseqCoreActv_TxRxChain1;
+		CoreActv_override = true;
+
+		if (NREV_LE(pi->pubpi.phy_rev, 2)) {
+			or_phy_reg(pi, 0xa0, 0x20);
+		}
+	}
+
+	mod_phy_reg(pi, 0xa2, ((0xf << 0) | (0xf << 4)), txrx_chain);
+
+	if (CoreActv_override) {
+
+		pi->nphy_perical = PHY_PERICAL_DISABLE;
+		or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	} else {
+		pi->nphy_perical = PHY_PERICAL_MPHASE;
+		and_phy_reg(pi, 0xa1, ~NPHY_RfseqMode_CoreActv_override);
+	}
+}
+
+void wlc_phy_rxcore_setstate_nphy(wlc_phy_t *pih, u8 rxcore_bitmask)
+{
+	u16 regval;
+	u16 tbl_buf[16];
+	uint i;
+	phy_info_t *pi = (phy_info_t *) pih;
+	u16 tbl_opcode;
+	bool suspend;
+
+	pi->sh->phyrxchain = rxcore_bitmask;
+
+	if (!pi->sh->clk)
+		return;
+
+	suspend =
+	    (0 == (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC));
+	if (!suspend)
+		wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	regval = read_phy_reg(pi, 0xa2);
+	regval &= ~(0xf << 4);
+	regval |= ((u16) (rxcore_bitmask & 0x3)) << 4;
+	write_phy_reg(pi, 0xa2, regval);
+
+	if ((rxcore_bitmask & 0x3) != 0x3) {
+
+		write_phy_reg(pi, 0x20e, 1);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry == -1) {
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							ARRAY_SIZE(tbl_buf), 80,
+							16, tbl_buf);
+
+				for (i = 0; i < ARRAY_SIZE(tbl_buf); i++) {
+					if (tbl_buf[i] ==
+					    NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS) {
+
+						pi->rx2tx_biasentry = (u8) i;
+						tbl_opcode =
+						    NPHY_REV3_RFSEQ_CMD_NOP;
+						wlc_phy_table_write_nphy(pi,
+									 NPHY_TBL_ID_RFSEQ,
+									 1, i,
+									 16,
+									 &tbl_opcode);
+						break;
+					} else if (tbl_buf[i] ==
+						   NPHY_REV3_RFSEQ_CMD_END) {
+						break;
+					}
+				}
+			}
+		}
+	} else {
+
+		write_phy_reg(pi, 0x20e, 30);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			if (pi->rx2tx_biasentry != -1) {
+				tbl_opcode = NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS;
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1, pi->rx2tx_biasentry,
+							 16, &tbl_opcode);
+				pi->rx2tx_biasentry = -1;
+			}
+		}
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	if (!suspend)
+		wlapi_enable_mac(pi->sh->physhim);
+}
+
+u8 wlc_phy_rxcore_getstate_nphy(wlc_phy_t *pih)
+{
+	u16 regval, rxen_bits;
+	phy_info_t *pi = (phy_info_t *) pih;
+
+	regval = read_phy_reg(pi, 0xa2);
+	rxen_bits = (regval >> 4) & 0xf;
+
+	return (u8) rxen_bits;
+}
+
+bool wlc_phy_n_txpower_ipa_ison(phy_info_t *pi)
+{
+	return PHY_IPA(pi);
+}
+
+static void wlc_phy_txpwr_limit_to_tbl_nphy(phy_info_t *pi)
+{
+	u8 idx, idx2, i, delta_ind;
+
+	for (idx = TXP_FIRST_CCK; idx <= TXP_LAST_CCK; idx++) {
+		pi->adj_pwr_tbl_nphy[idx] = pi->tx_power_offset[idx];
+	}
+
+	for (i = 0; i < 4; i++) {
+		idx2 = 0;
+
+		delta_ind = 0;
+
+		switch (i) {
+		case 0:
+
+			if (CHSPEC_IS40(pi->radio_chanspec)
+			    && NPHY_IS_SROM_REINTERPRET) {
+				idx = TXP_FIRST_MCS_40_SISO;
+			} else {
+				idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+				    TXP_FIRST_OFDM_40_SISO : TXP_FIRST_OFDM;
+				delta_ind = 1;
+			}
+			break;
+
+		case 1:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_CDD : TXP_FIRST_MCS_20_CDD;
+			break;
+
+		case 2:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_STBC : TXP_FIRST_MCS_20_STBC;
+			break;
+
+		case 3:
+
+			idx = (CHSPEC_IS40(pi->radio_chanspec)) ?
+			    TXP_FIRST_MCS_40_SDM : TXP_FIRST_MCS_20_SDM;
+			break;
+		}
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		idx = idx + delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx++];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		idx = idx + 1 - delta_ind;
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+		pi->adj_pwr_tbl_nphy[4 + 4 * (idx2++) + i] =
+		    pi->tx_power_offset[idx];
+	}
+}
+
+void wlc_phy_cal_init_nphy(phy_info_t *pi)
+{
+}
+
+static void wlc_phy_war_force_trsw_to_R_cliplo_nphy(phy_info_t *pi, u8 core)
+{
+	if (core == PHY_CORE_0) {
+		write_phy_reg(pi, 0x38, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x37, 0x0060);
+		} else {
+			write_phy_reg(pi, 0x37, 0x1080);
+		}
+	} else if (core == PHY_CORE_1) {
+		write_phy_reg(pi, 0x2ae, 0x4);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x2ad, 0x0060);
+		} else {
+			write_phy_reg(pi, 0x2ad, 0x1080);
+		}
+	}
+}
+
+static void wlc_phy_war_txchain_upd_nphy(phy_info_t *pi, u8 txchain)
+{
+	u8 txchain0, txchain1;
+
+	txchain0 = txchain & 0x1;
+	txchain1 = (txchain & 0x2) >> 1;
+	if (!txchain0) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+	}
+
+	if (!txchain1) {
+		wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+	}
+}
+
+static void wlc_phy_workarounds_nphy(phy_info_t *pi)
+{
+	u8 rfseq_rx2tx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_EXT_PA
+	};
+	u8 rfseq_rx2tx_dlys[] = { 8, 6, 6, 2, 4, 60, 1 };
+	u8 rfseq_tx2rx_events[] = {
+		NPHY_RFSEQ_CMD_NOP,
+		NPHY_RFSEQ_CMD_EXT_PA,
+		NPHY_RFSEQ_CMD_TX_GAIN,
+		NPHY_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_RFSEQ_CMD_TR_SWITCH,
+		NPHY_RFSEQ_CMD_RXG_FBW,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS
+	};
+	u8 rfseq_tx2rx_dlys[] = { 8, 6, 2, 4, 4, 6, 1 };
+	u8 rfseq_tx2rx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_tx2rx_dlys_rev3[] = { 8, 4, 2, 2, 4, 4, 6, 1 };
+	u8 rfseq_rx2tx_events_rev3[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_EXT_PA,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3[] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
+
+	u8 rfseq_rx2tx_events_rev3_ipa[] = {
+		NPHY_REV3_RFSEQ_CMD_NOP,
+		NPHY_REV3_RFSEQ_CMD_RXG_FBW,
+		NPHY_REV3_RFSEQ_CMD_TR_SWITCH,
+		NPHY_REV3_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_REV3_RFSEQ_CMD_RXPD_TXPD,
+		NPHY_REV3_RFSEQ_CMD_TX_GAIN,
+		NPHY_REV3_RFSEQ_CMD_CLR_RXRX_BIAS,
+		NPHY_REV3_RFSEQ_CMD_INT_PA_PU,
+		NPHY_REV3_RFSEQ_CMD_END
+	};
+	u8 rfseq_rx2tx_dlys_rev3_ipa[] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
+	u16 rfseq_rx2tx_dacbufpu_rev7[] = { 0x10f, 0x10f };
+
+	s16 alpha0, alpha1, alpha2;
+	s16 beta0, beta1, beta2;
+	u32 leg_data_weights, ht_data_weights, nss1_data_weights,
+	    stbc_data_weights;
+	u8 chan_freq_range = 0;
+	u16 dac_control = 0x0002;
+	u16 aux_adc_vmid_rev7_core0[] = { 0x8e, 0x96, 0x96, 0x96 };
+	u16 aux_adc_vmid_rev7_core1[] = { 0x8f, 0x9f, 0x9f, 0x96 };
+	u16 aux_adc_vmid_rev4[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 aux_adc_vmid_rev3[] = { 0xa2, 0xb4, 0xb4, 0x89 };
+	u16 *aux_adc_vmid;
+	u16 aux_adc_gain_rev7[] = { 0x02, 0x02, 0x02, 0x02 };
+	u16 aux_adc_gain_rev4[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 aux_adc_gain_rev3[] = { 0x02, 0x02, 0x02, 0x00 };
+	u16 *aux_adc_gain;
+	u16 sk_adc_vmid[] = { 0xb4, 0xb4, 0xb4, 0x24 };
+	u16 sk_adc_gain[] = { 0x02, 0x02, 0x02, 0x02 };
+	s32 min_nvar_val = 0x18d;
+	s32 min_nvar_offset_6mbps = 20;
+	u8 pdetrange;
+	u8 triso;
+	u16 regval;
+	u16 afectrl_adc_ctrl1_rev7 = 0x20;
+	u16 afectrl_adc_ctrl2_rev7 = 0x0;
+	u16 rfseq_rx2tx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_tx2rx_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_pktgn_lpf_h_hpc_rev7 = 0x77;
+	u16 rfseq_htpktgn_lpf_hpc_rev7[] = { 0x77, 0x11, 0x11 };
+	u16 rfseq_pktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 rfseq_cckpktgn_lpf_hpc_rev7[] = { 0x11, 0x11 };
+	u16 ipalvlshift_3p3_war_en = 0;
+	u16 rccal_bcap_val, rccal_scap_val;
+	u16 rccal_tx20_11b_bcap = 0;
+	u16 rccal_tx20_11b_scap = 0;
+	u16 rccal_tx20_11n_bcap = 0;
+	u16 rccal_tx20_11n_scap = 0;
+	u16 rccal_tx40_11n_bcap = 0;
+	u16 rccal_tx40_11n_scap = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11b = 0;
+	u16 rx2tx_lpf_rc_lut_tx20_11n = 0;
+	u16 rx2tx_lpf_rc_lut_tx40_11n = 0;
+	u16 tx_lpf_bw_ofdm_20mhz = 0;
+	u16 tx_lpf_bw_ofdm_40mhz = 0;
+	u16 tx_lpf_bw_11b = 0;
+	u16 ipa2g_mainbias, ipa2g_casconv, ipa2g_biasfilt;
+	u16 txgm_idac_bleed = 0;
+	bool rccal_ovrd = false;
+	u16 freq;
+	int coreNum;
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 0);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_cck_en, 1);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (!ISSIM_ENAB(pi->sh->sih)) {
+		or_phy_reg(pi, 0xb1, NPHY_IQFlip_ADC1 | NPHY_IQFlip_ADC2);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+			mod_phy_reg(pi, 0x221, (0x1 << 4), (1 << 4));
+
+			mod_phy_reg(pi, 0x160, (0x7f << 0), (32 << 0));
+			mod_phy_reg(pi, 0x160, (0x7f << 8), (39 << 8));
+			mod_phy_reg(pi, 0x161, (0x7f << 0), (46 << 0));
+			mod_phy_reg(pi, 0x161, (0x7f << 8), (51 << 8));
+			mod_phy_reg(pi, 0x162, (0x7f << 0), (55 << 0));
+			mod_phy_reg(pi, 0x162, (0x7f << 8), (58 << 8));
+			mod_phy_reg(pi, 0x163, (0x7f << 0), (60 << 0));
+			mod_phy_reg(pi, 0x163, (0x7f << 8), (62 << 8));
+			mod_phy_reg(pi, 0x164, (0x7f << 0), (62 << 0));
+			mod_phy_reg(pi, 0x164, (0x7f << 8), (63 << 8));
+			mod_phy_reg(pi, 0x165, (0x7f << 0), (63 << 0));
+			mod_phy_reg(pi, 0x165, (0x7f << 8), (64 << 8));
+			mod_phy_reg(pi, 0x166, (0x7f << 0), (64 << 0));
+			mod_phy_reg(pi, 0x166, (0x7f << 8), (64 << 8));
+			mod_phy_reg(pi, 0x167, (0x7f << 0), (64 << 0));
+			mod_phy_reg(pi, 0x167, (0x7f << 8), (64 << 8));
+		}
+
+		if (NREV_LE(pi->pubpi.phy_rev, 8)) {
+			write_phy_reg(pi, 0x23f, 0x1b0);
+			write_phy_reg(pi, 0x240, 0x1b0);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			mod_phy_reg(pi, 0xbd, (0xff << 0), (114 << 0));
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+					 &dac_control);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+					 &dac_control);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					1, 0, 32, &leg_data_weights);
+		leg_data_weights = leg_data_weights & 0xffffff;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 0, 32, &leg_data_weights);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 2, 0x15e, 16,
+					 rfseq_rx2tx_dacbufpu_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x16e, 16,
+					 rfseq_rx2tx_dacbufpu_rev7);
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3_ipa,
+					       rfseq_rx2tx_dlys_rev3_ipa,
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa) /
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa
+						[0]));
+		}
+
+		mod_phy_reg(pi, 0x299, (0x3 << 14), (0x1 << 14));
+		mod_phy_reg(pi, 0x29d, (0x3 << 14), (0x1 << 14));
+
+		tx_lpf_bw_ofdm_20mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x154);
+		tx_lpf_bw_ofdm_40mhz = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x159);
+		tx_lpf_bw_11b = wlc_phy_read_lpf_bw_ctl_nphy(pi, 0x152);
+
+		if (PHY_IPA(pi)) {
+
+			if (((pi->pubpi.radiorev == 5)
+			     && (CHSPEC_IS40(pi->radio_chanspec) == 1))
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+
+				rccal_bcap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_BCAP_VAL);
+				rccal_scap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_SCAP_VAL);
+
+				rccal_tx20_11b_bcap = rccal_bcap_val;
+				rccal_tx20_11b_scap = rccal_scap_val;
+
+				if ((pi->pubpi.radiorev == 5) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 1)) {
+
+					rccal_tx20_11n_bcap = rccal_bcap_val;
+					rccal_tx20_11n_scap = rccal_scap_val;
+					rccal_tx40_11n_bcap = 0xc;
+					rccal_tx40_11n_scap = 0xc;
+
+					rccal_ovrd = true;
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					tx_lpf_bw_ofdm_20mhz = 4;
+					tx_lpf_bw_11b = 1;
+
+					if (CHSPEC_IS2G(pi->radio_chanspec)) {
+						rccal_tx20_11n_bcap = 0xc;
+						rccal_tx20_11n_scap = 0xc;
+						rccal_tx40_11n_bcap = 0xa;
+						rccal_tx40_11n_scap = 0xa;
+					} else {
+						rccal_tx20_11n_bcap = 0x14;
+						rccal_tx20_11n_scap = 0x14;
+						rccal_tx40_11n_bcap = 0xf;
+						rccal_tx40_11n_scap = 0xf;
+					}
+
+					rccal_ovrd = true;
+				}
+			}
+
+		} else {
+
+			if (pi->pubpi.radiorev == 5) {
+
+				tx_lpf_bw_ofdm_20mhz = 1;
+				tx_lpf_bw_ofdm_40mhz = 3;
+
+				rccal_bcap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_BCAP_VAL);
+				rccal_scap_val =
+				    read_radio_reg(pi,
+						   RADIO_2057_RCCAL_SCAP_VAL);
+
+				rccal_tx20_11b_bcap = rccal_bcap_val;
+				rccal_tx20_11b_scap = rccal_scap_val;
+
+				rccal_tx20_11n_bcap = 0x13;
+				rccal_tx20_11n_scap = 0x11;
+				rccal_tx40_11n_bcap = 0x13;
+				rccal_tx40_11n_scap = 0x11;
+
+				rccal_ovrd = true;
+			}
+		}
+
+		if (rccal_ovrd) {
+
+			rx2tx_lpf_rc_lut_tx20_11b = (rccal_tx20_11b_bcap << 8) |
+			    (rccal_tx20_11b_scap << 3) | tx_lpf_bw_11b;
+			rx2tx_lpf_rc_lut_tx20_11n = (rccal_tx20_11n_bcap << 8) |
+			    (rccal_tx20_11n_scap << 3) | tx_lpf_bw_ofdm_20mhz;
+			rx2tx_lpf_rc_lut_tx40_11n = (rccal_tx40_11n_bcap << 8) |
+			    (rccal_tx40_11n_scap << 3) | tx_lpf_bw_ofdm_40mhz;
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x152 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11b);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x153 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x154 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx20_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x155 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x156 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x157 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x158 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+				wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+							 1,
+							 0x159 + coreNum * 0x10,
+							 16,
+							 &rx2tx_lpf_rc_lut_tx40_11n);
+			}
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		}
+
+		if (!NORADIO_ENAB(pi->pubpi)) {
+			write_phy_reg(pi, 0x32f, 0x3);
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		}
+
+		if ((pi->pubpi.radiorev == 3) || (pi->pubpi.radiorev == 4) ||
+		    (pi->pubpi.radiorev == 6)) {
+			if ((pi->sh->sromrev >= 8)
+			    && (pi->sh->boardflags2 & BFL2_IPALVLSHIFT_3P3))
+				ipalvlshift_3p3_war_en = 1;
+
+			if (ipalvlshift_3p3_war_en) {
+				write_radio_reg(pi, RADIO_2057_GPAIO_CONFIG,
+						0x5);
+				write_radio_reg(pi, RADIO_2057_GPAIO_SEL1,
+						0x30);
+				write_radio_reg(pi, RADIO_2057_GPAIO_SEL0, 0x0);
+				or_radio_reg(pi,
+					     RADIO_2057_RXTXBIAS_CONFIG_CORE0,
+					     0x1);
+				or_radio_reg(pi,
+					     RADIO_2057_RXTXBIAS_CONFIG_CORE1,
+					     0x1);
+
+				ipa2g_mainbias = 0x1f;
+
+				ipa2g_casconv = 0x6f;
+
+				ipa2g_biasfilt = 0xaa;
+			} else {
+
+				ipa2g_mainbias = 0x2b;
+
+				ipa2g_casconv = 0x7f;
+
+				ipa2g_biasfilt = 0xee;
+			}
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum, IPA2G_IMAIN,
+							 ipa2g_mainbias);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum, IPA2G_CASCONV,
+							 ipa2g_casconv);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 IPA2G_BIAS_FILTER,
+							 ipa2g_biasfilt);
+				}
+			}
+		}
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((pi->pubpi.radiorev == 3)
+				    || (pi->pubpi.radiorev == 4)
+				    || (pi->pubpi.radiorev == 6)) {
+
+					txgm_idac_bleed = 0x7f;
+				}
+
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					if (txgm_idac_bleed != 0)
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 TXGM_IDAC_BLEED,
+								 txgm_idac_bleed);
+				}
+
+				if (pi->pubpi.radiorev == 5) {
+
+					for (coreNum = 0; coreNum <= 1;
+					     coreNum++) {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_CASCONV,
+								 0x13);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_IMAIN,
+								 0x1f);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 IPA2G_BIAS_FILTER,
+								 0xee);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 PAD2G_IDACS,
+								 0x8a);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, coreNum,
+								 PAD_BIAS_FILTER_BWS,
+								 0x3e);
+					}
+
+				} else if ((pi->pubpi.radiorev == 7)
+					   || (pi->pubpi.radiorev == 8)) {
+
+					if (CHSPEC_IS40(pi->radio_chanspec) ==
+					    0) {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 0,
+								 IPA2G_IMAIN,
+								 0x14);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 1,
+								 IPA2G_IMAIN,
+								 0x12);
+					} else {
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 0,
+								 IPA2G_IMAIN,
+								 0x16);
+						WRITE_RADIO_REG4(pi, RADIO_2057,
+								 CORE, 1,
+								 IPA2G_IMAIN,
+								 0x16);
+					}
+				}
+
+			} else {
+				freq =
+				    CHAN5G_FREQ(CHSPEC_CHANNEL
+						(pi->radio_chanspec));
+				if (((freq >= 5180) && (freq <= 5230))
+				    || ((freq >= 5745) && (freq <= 5805))) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 0, IPA5G_BIAS_FILTER,
+							 0xff);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 1, IPA5G_BIAS_FILTER,
+							 0xff);
+				}
+			}
+		} else {
+
+			if (pi->pubpi.radiorev != 5) {
+				for (coreNum = 0; coreNum <= 1; coreNum++) {
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 TXMIX2G_TUNE_BOOST_PU,
+							 0x61);
+					WRITE_RADIO_REG4(pi, RADIO_2057, CORE,
+							 coreNum,
+							 TXGM_IDAC_BLEED, 0x70);
+				}
+			}
+		}
+
+		if (pi->pubpi.radiorev == 4) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x05, 16,
+						 &afectrl_adc_ctrl1_rev7);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x15, 16,
+						 &afectrl_adc_ctrl1_rev7);
+
+			for (coreNum = 0; coreNum <= 1; coreNum++) {
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_VCM_CAL_MASTER, 0x0);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_SET_VCM_I, 0x3f);
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 AFE_SET_VCM_Q, 0x3f);
+			}
+		} else {
+			mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+			mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+
+			mod_phy_reg(pi, 0xa6, (0x1 << 0), 0);
+			mod_phy_reg(pi, 0x8f, (0x1 << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0xa7, (0x1 << 0), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 0), (0x1 << 0));
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x05, 16,
+						 &afectrl_adc_ctrl2_rev7);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1,
+						 0x15, 16,
+						 &afectrl_adc_ctrl2_rev7);
+
+			mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0x8f, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 2), 0);
+		}
+
+		write_phy_reg(pi, 0x6a, 0x2);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 256, 32,
+					 &min_nvar_offset_6mbps);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x138, 16,
+					 &rfseq_pktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x141, 16,
+					 &rfseq_pktgn_lpf_h_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 3, 0x133, 16,
+					 &rfseq_htpktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x146, 16,
+					 &rfseq_cckpktgn_lpf_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x123, 16,
+					 &rfseq_tx2rx_lpf_h_hpc_rev7);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1, 0x12A, 16,
+					 &rfseq_rx2tx_lpf_h_hpc_rev7);
+
+		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		} else {
+			min_nvar_val = noise_var_tbl_rev7[3];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+
+			min_nvar_val = noise_var_tbl_rev7[127];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		}
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		pdetrange =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    pdetrange : pi->srom_fem2g.pdetrange;
+
+		if (pdetrange == 0) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x70;
+				aux_adc_vmid_rev7_core1[3] = 0x70;
+				aux_adc_gain_rev7[3] = 2;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x80;
+				aux_adc_vmid_rev7_core1[3] = 0x80;
+				aux_adc_gain_rev7[3] = 3;
+			}
+		} else if (pdetrange == 1) {
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x7c;
+				aux_adc_vmid_rev7_core1[3] = 0x7c;
+				aux_adc_gain_rev7[3] = 2;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x8c;
+				aux_adc_vmid_rev7_core1[3] = 0x8c;
+				aux_adc_gain_rev7[3] = 1;
+			}
+		} else if (pdetrange == 2) {
+			if (pi->pubpi.radioid == BCM2057_ID) {
+				if ((pi->pubpi.radiorev == 5)
+				    || (pi->pubpi.radiorev == 7)
+				    || (pi->pubpi.radiorev == 8)) {
+					if (chan_freq_range ==
+					    WL_CHAN_FREQ_RANGE_2G) {
+						aux_adc_vmid_rev7_core0[3] =
+						    0x8c;
+						aux_adc_vmid_rev7_core1[3] =
+						    0x8c;
+						aux_adc_gain_rev7[3] = 0;
+					} else {
+						aux_adc_vmid_rev7_core0[3] =
+						    0x96;
+						aux_adc_vmid_rev7_core1[3] =
+						    0x96;
+						aux_adc_gain_rev7[3] = 0;
+					}
+				}
+			}
+
+		} else if (pdetrange == 3) {
+			if (chan_freq_range == WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x89;
+				aux_adc_vmid_rev7_core1[3] = 0x89;
+				aux_adc_gain_rev7[3] = 0;
+			}
+
+		} else if (pdetrange == 5) {
+
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				aux_adc_vmid_rev7_core0[3] = 0x80;
+				aux_adc_vmid_rev7_core1[3] = 0x80;
+				aux_adc_gain_rev7[3] = 3;
+			} else {
+				aux_adc_vmid_rev7_core0[3] = 0x70;
+				aux_adc_vmid_rev7_core1[3] = 0x70;
+				aux_adc_gain_rev7[3] = 2;
+			}
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x08, 16,
+					 &aux_adc_vmid_rev7_core0);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x18, 16,
+					 &aux_adc_vmid_rev7_core1);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x0c, 16,
+					 &aux_adc_gain_rev7);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4, 0x1c, 16,
+					 &aux_adc_gain_rev7);
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		write_phy_reg(pi, 0x23f, 0x1f8);
+		write_phy_reg(pi, 0x240, 0x1f8);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					1, 0, 32, &leg_data_weights);
+		leg_data_weights = leg_data_weights & 0xffffff;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 0, 32, &leg_data_weights);
+
+		alpha0 = 293;
+		alpha1 = 435;
+		alpha2 = 261;
+		beta0 = 366;
+		beta1 = 205;
+		beta2 = 32;
+		write_phy_reg(pi, 0x145, alpha0);
+		write_phy_reg(pi, 0x146, alpha1);
+		write_phy_reg(pi, 0x147, alpha2);
+		write_phy_reg(pi, 0x148, beta0);
+		write_phy_reg(pi, 0x149, beta1);
+		write_phy_reg(pi, 0x14a, beta2);
+
+		write_phy_reg(pi, 0x38, 0xC);
+		write_phy_reg(pi, 0x2ae, 0xC);
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX,
+				       rfseq_tx2rx_events_rev3,
+				       rfseq_tx2rx_dlys_rev3,
+				       sizeof(rfseq_tx2rx_events_rev3) /
+				       sizeof(rfseq_tx2rx_events_rev3[0]));
+
+		if (PHY_IPA(pi)) {
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3_ipa,
+					       rfseq_rx2tx_dlys_rev3_ipa,
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa) /
+					       sizeof
+					       (rfseq_rx2tx_events_rev3_ipa
+						[0]));
+		}
+
+		if ((pi->sh->hw_phyrxchain != 0x3) &&
+		    (pi->sh->hw_phyrxchain != pi->sh->hw_phytxchain)) {
+
+			if (PHY_IPA(pi)) {
+				rfseq_rx2tx_dlys_rev3[5] = 59;
+				rfseq_rx2tx_dlys_rev3[6] = 1;
+				rfseq_rx2tx_events_rev3[7] =
+				    NPHY_REV3_RFSEQ_CMD_END;
+			}
+
+			wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX,
+					       rfseq_rx2tx_events_rev3,
+					       rfseq_rx2tx_dlys_rev3,
+					       sizeof(rfseq_rx2tx_events_rev3) /
+					       sizeof(rfseq_rx2tx_events_rev3
+						      [0]));
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6a, 0x2);
+		} else {
+			write_phy_reg(pi, 0x6a, 0x9c40);
+		}
+
+		mod_phy_reg(pi, 0x294, (0xf << 8), (7 << 8));
+
+		if (CHSPEC_IS40(pi->radio_chanspec) == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		} else {
+			min_nvar_val = noise_var_tbl_rev3[3];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1, 3,
+						 32, &min_nvar_val);
+
+			min_nvar_val = noise_var_tbl_rev3[127];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 127, 32, &min_nvar_val);
+		}
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x00, 16,
+					 &dac_control);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x10, 16,
+					 &dac_control);
+
+		pdetrange =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    pdetrange : pi->srom_fem2g.pdetrange;
+
+		if (pdetrange == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+				aux_adc_vmid = aux_adc_vmid_rev4;
+				aux_adc_gain = aux_adc_gain_rev4;
+			} else {
+				aux_adc_vmid = aux_adc_vmid_rev3;
+				aux_adc_gain = aux_adc_gain_rev3;
+			}
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				switch (chan_freq_range) {
+				case WL_CHAN_FREQ_RANGE_5GL:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				case WL_CHAN_FREQ_RANGE_5GM:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				case WL_CHAN_FREQ_RANGE_5GH:
+					aux_adc_vmid[3] = 0x89;
+					aux_adc_gain[3] = 0;
+					break;
+				default:
+					break;
+				}
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, aux_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, aux_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, aux_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, aux_adc_gain);
+		} else if (pdetrange == 1) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, sk_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, sk_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, sk_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, sk_adc_gain);
+		} else if (pdetrange == 2) {
+
+			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x74 };
+			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x04 };
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				chan_freq_range =
+				    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+				if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+					bcm_adc_vmid[3] = 0x8e;
+					bcm_adc_gain[3] = 0x03;
+				} else {
+					bcm_adc_vmid[3] = 0x94;
+					bcm_adc_gain[3] = 0x03;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				bcm_adc_vmid[3] = 0x84;
+				bcm_adc_gain[3] = 0x02;
+			}
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, bcm_adc_gain);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, bcm_adc_gain);
+		} else if (pdetrange == 3) {
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if ((NREV_GE(pi->pubpi.phy_rev, 4))
+			    && (chan_freq_range == WL_CHAN_FREQ_RANGE_2G)) {
+
+				u16 auxadc_vmid[] = {
+					0xa2, 0xb4, 0xb4, 0x270 };
+				u16 auxadc_gain[] = {
+					0x02, 0x02, 0x02, 0x00 };
+
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x08, 16, auxadc_vmid);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x18, 16, auxadc_vmid);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x0c, 16, auxadc_gain);
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_AFECTRL, 4,
+							 0x1c, 16, auxadc_gain);
+			}
+		} else if ((pdetrange == 4) || (pdetrange == 5)) {
+			u16 bcm_adc_vmid[] = { 0xa2, 0xb4, 0xb4, 0x0 };
+			u16 bcm_adc_gain[] = { 0x02, 0x02, 0x02, 0x0 };
+			u16 Vmid[2], Av[2];
+
+			chan_freq_range =
+			    wlc_phy_get_chan_freq_range_nphy(pi, 0);
+			if (chan_freq_range != WL_CHAN_FREQ_RANGE_2G) {
+				Vmid[0] = (pdetrange == 4) ? 0x8e : 0x89;
+				Vmid[1] = (pdetrange == 4) ? 0x96 : 0x89;
+				Av[0] = (pdetrange == 4) ? 2 : 0;
+				Av[1] = (pdetrange == 4) ? 2 : 0;
+			} else {
+				Vmid[0] = (pdetrange == 4) ? 0x89 : 0x74;
+				Vmid[1] = (pdetrange == 4) ? 0x8b : 0x70;
+				Av[0] = (pdetrange == 4) ? 2 : 0;
+				Av[1] = (pdetrange == 4) ? 2 : 0;
+			}
+
+			bcm_adc_vmid[3] = Vmid[0];
+			bcm_adc_gain[3] = Av[0];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x08, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x0c, 16, bcm_adc_gain);
+
+			bcm_adc_vmid[3] = Vmid[1];
+			bcm_adc_gain[3] = Av[1];
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x18, 16, bcm_adc_vmid);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 4,
+						 0x1c, 16, bcm_adc_gain);
+		} else {
+			ASSERT(0);
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_MAST_BIAS | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX0),
+				0x6);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_MAIN | RADIO_2056_RX1),
+				0x6);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX0),
+				0x7);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_BIAS_AUX | RADIO_2056_RX1),
+				0x7);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX0),
+				0x88);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_LOB_BIAS | RADIO_2056_RX1),
+				0x88);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXA_CMFB_IDAC | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_MIXG_CMFB_IDAC | RADIO_2056_RX1),
+				0x0);
+
+		triso =
+		    (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.
+		    triso : pi->srom_fem2g.triso;
+		if (triso == 7) {
+			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_0);
+			wlc_phy_war_force_trsw_to_R_cliplo_nphy(pi, PHY_CORE_1);
+		}
+
+		wlc_phy_war_txchain_upd_nphy(pi, pi->sh->hw_phytxchain);
+
+		if (((pi->sh->boardflags2 & BFL2_APLL_WAR) &&
+		     (CHSPEC_IS5G(pi->radio_chanspec))) ||
+		    (((pi->sh->boardflags2 & BFL2_GPLL_WAR) ||
+		      (pi->sh->boardflags2 & BFL2_GPLL_WAR2)) &&
+		     (CHSPEC_IS2G(pi->radio_chanspec)))) {
+			nss1_data_weights = 0x00088888;
+			ht_data_weights = 0x00088888;
+			stbc_data_weights = 0x00088888;
+		} else {
+			nss1_data_weights = 0x88888888;
+			ht_data_weights = 0x88888888;
+			stbc_data_weights = 0x88888888;
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 1, 32, &nss1_data_weights);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 2, 32, &ht_data_weights);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_CMPMETRICDATAWEIGHTTBL,
+					 1, 3, 32, &stbc_data_weights);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_GMBB_IDAC |
+						RADIO_2056_TX0, 0x70);
+				write_radio_reg(pi,
+						RADIO_2056_TX_GMBB_IDAC |
+						RADIO_2056_TX1, 0x70);
+			}
+		}
+
+		if (!pi->edcrs_threshold_lock) {
+			write_phy_reg(pi, 0x224, 0x3eb);
+			write_phy_reg(pi, 0x225, 0x3eb);
+			write_phy_reg(pi, 0x226, 0x341);
+			write_phy_reg(pi, 0x227, 0x341);
+			write_phy_reg(pi, 0x228, 0x42b);
+			write_phy_reg(pi, 0x229, 0x42b);
+			write_phy_reg(pi, 0x22a, 0x381);
+			write_phy_reg(pi, 0x22b, 0x381);
+			write_phy_reg(pi, 0x22c, 0x42b);
+			write_phy_reg(pi, 0x22d, 0x42b);
+			write_phy_reg(pi, 0x22e, 0x381);
+			write_phy_reg(pi, 0x22f, 0x381);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+
+			if (pi->sh->boardflags2 & BFL2_SINGLEANT_CCK) {
+				wlapi_bmac_mhf(pi->sh->physhim, MHF4,
+					       MHF4_BPHY_TXCORE0,
+					       MHF4_BPHY_TXCORE0, WLC_BAND_ALL);
+			}
+		}
+	} else {
+
+		if (pi->sh->boardflags2 & BFL2_SKWRKFEM_BRD ||
+		    (pi->sh->boardtype == 0x8b)) {
+			uint i;
+			u8 war_dlys[] = { 1, 6, 6, 2, 4, 20, 1 };
+			for (i = 0; i < ARRAY_SIZE(rfseq_rx2tx_dlys); i++)
+				rfseq_rx2tx_dlys[i] = war_dlys[i];
+		}
+
+		if (CHSPEC_IS5G(pi->radio_chanspec) && pi->phy_5g_pwrgain) {
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0xf7);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0xf7);
+		} else {
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_RF_SPARE, 0x8);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_RF_SPARE, 0x8);
+		}
+
+		regval = 0x000a;
+		wlc_phy_table_write_nphy(pi, 8, 1, 0, 16, &regval);
+		wlc_phy_table_write_nphy(pi, 8, 1, 0x10, 16, &regval);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+			regval = 0xcdaa;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x02, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x12, 16, &regval);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			regval = 0x0000;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x08, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x18, 16, &regval);
+
+			regval = 0x7aab;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x07, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x17, 16, &regval);
+
+			regval = 0x0800;
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x06, 16, &regval);
+			wlc_phy_table_write_nphy(pi, 8, 1, 0x16, 16, &regval);
+		}
+
+		write_phy_reg(pi, 0xf8, 0x02d8);
+		write_phy_reg(pi, 0xf9, 0x0301);
+		write_phy_reg(pi, 0xfa, 0x02d8);
+		write_phy_reg(pi, 0xfb, 0x0301);
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX, rfseq_rx2tx_events,
+				       rfseq_rx2tx_dlys,
+				       sizeof(rfseq_rx2tx_events) /
+				       sizeof(rfseq_rx2tx_events[0]));
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_TX2RX, rfseq_tx2rx_events,
+				       rfseq_tx2rx_dlys,
+				       sizeof(rfseq_tx2rx_events) /
+				       sizeof(rfseq_tx2rx_events[0]));
+
+		wlc_phy_workarounds_nphy_gainctrl(pi);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			if (read_phy_reg(pi, 0xa0) & NPHY_MLenable)
+				wlapi_bmac_mhf(pi->sh->physhim, MHF3,
+					       MHF3_NPHY_MLADV_WAR,
+					       MHF3_NPHY_MLADV_WAR,
+					       WLC_BAND_ALL);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			write_phy_reg(pi, 0x1e3, 0x0);
+			write_phy_reg(pi, 0x1e4, 0x0);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2))
+			mod_phy_reg(pi, 0x90, (0x1 << 7), 0);
+
+		alpha0 = 293;
+		alpha1 = 435;
+		alpha2 = 261;
+		beta0 = 366;
+		beta1 = 205;
+		beta2 = 32;
+		write_phy_reg(pi, 0x145, alpha0);
+		write_phy_reg(pi, 0x146, alpha1);
+		write_phy_reg(pi, 0x147, alpha2);
+		write_phy_reg(pi, 0x148, beta0);
+		write_phy_reg(pi, 0x149, beta1);
+		write_phy_reg(pi, 0x14a, beta2);
+
+		if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+			mod_phy_reg(pi, 0x142, (0xf << 12), 0);
+
+			write_phy_reg(pi, 0x192, 0xb5);
+			write_phy_reg(pi, 0x193, 0xa4);
+			write_phy_reg(pi, 0x194, 0x0);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			mod_phy_reg(pi, 0x221,
+				    NPHY_FORCESIG_DECODEGATEDCLKS,
+				    NPHY_FORCESIG_DECODEGATEDCLKS);
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl(phy_info_t *pi)
+{
+	u16 w1th, hpf_code, currband;
+	int ctr;
+	u8 rfseq_updategainu_events[] = {
+		NPHY_RFSEQ_CMD_RX_GAIN,
+		NPHY_RFSEQ_CMD_CLR_HIQ_DIS,
+		NPHY_RFSEQ_CMD_SET_HPF_BW
+	};
+	u8 rfseq_updategainu_dlys[] = { 10, 30, 1 };
+	s8 lna1G_gain_db[] = { 7, 11, 16, 23 };
+	s8 lna1G_gain_db_rev4[] = { 8, 12, 17, 25 };
+	s8 lna1G_gain_db_rev5[] = { 9, 13, 18, 26 };
+	s8 lna1G_gain_db_rev6[] = { 8, 13, 18, 25 };
+	s8 lna1G_gain_db_rev6_224B0[] = { 10, 14, 19, 27 };
+	s8 lna1A_gain_db[] = { 7, 11, 17, 23 };
+	s8 lna1A_gain_db_rev4[] = { 8, 12, 18, 23 };
+	s8 lna1A_gain_db_rev5[] = { 6, 10, 16, 21 };
+	s8 lna1A_gain_db_rev6[] = { 6, 10, 16, 21 };
+	s8 *lna1_gain_db = NULL;
+	s8 lna2G_gain_db[] = { -5, 6, 10, 14 };
+	s8 lna2G_gain_db_rev5[] = { -3, 7, 11, 16 };
+	s8 lna2G_gain_db_rev6[] = { -5, 6, 10, 14 };
+	s8 lna2G_gain_db_rev6_224B0[] = { -5, 6, 10, 15 };
+	s8 lna2A_gain_db[] = { -6, 2, 6, 10 };
+	s8 lna2A_gain_db_rev4[] = { -5, 2, 6, 10 };
+	s8 lna2A_gain_db_rev5[] = { -7, 0, 4, 8 };
+	s8 lna2A_gain_db_rev6[] = { -7, 0, 4, 8 };
+	s8 *lna2_gain_db = NULL;
+	s8 tiaG_gain_db[] = {
+		0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A };
+	s8 tiaA_gain_db[] = {
+		0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13, 0x13 };
+	s8 tiaA_gain_db_rev4[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 tiaA_gain_db_rev5[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 tiaA_gain_db_rev6[] = {
+		0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d, 0x0d };
+	s8 *tia_gain_db;
+	s8 tiaG_gainbits[] = {
+		0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+	s8 tiaA_gainbits[] = {
+		0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06 };
+	s8 tiaA_gainbits_rev4[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 tiaA_gainbits_rev5[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 tiaA_gainbits_rev6[] = {
+		0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04 };
+	s8 *tia_gainbits;
+	s8 lpf_gain_db[] = { 0x00, 0x06, 0x0c, 0x12, 0x12, 0x12 };
+	s8 lpf_gainbits[] = { 0x00, 0x01, 0x02, 0x03, 0x03, 0x03 };
+	u16 rfseqG_init_gain[] = { 0x613f, 0x613f, 0x613f, 0x613f };
+	u16 rfseqG_init_gain_rev4[] = { 0x513f, 0x513f, 0x513f, 0x513f };
+	u16 rfseqG_init_gain_rev5[] = { 0x413f, 0x413f, 0x413f, 0x413f };
+	u16 rfseqG_init_gain_rev5_elna[] = {
+		0x013f, 0x013f, 0x013f, 0x013f };
+	u16 rfseqG_init_gain_rev6[] = { 0x513f, 0x513f };
+	u16 rfseqG_init_gain_rev6_224B0[] = { 0x413f, 0x413f };
+	u16 rfseqG_init_gain_rev6_elna[] = { 0x113f, 0x113f };
+	u16 rfseqA_init_gain[] = { 0x516f, 0x516f, 0x516f, 0x516f };
+	u16 rfseqA_init_gain_rev4[] = { 0x614f, 0x614f, 0x614f, 0x614f };
+	u16 rfseqA_init_gain_rev4_elna[] = {
+		0x314f, 0x314f, 0x314f, 0x314f };
+	u16 rfseqA_init_gain_rev5[] = { 0x714f, 0x714f, 0x714f, 0x714f };
+	u16 rfseqA_init_gain_rev6[] = { 0x714f, 0x714f };
+	u16 *rfseq_init_gain;
+	u16 initG_gaincode = 0x627e;
+	u16 initG_gaincode_rev4 = 0x527e;
+	u16 initG_gaincode_rev5 = 0x427e;
+	u16 initG_gaincode_rev5_elna = 0x027e;
+	u16 initG_gaincode_rev6 = 0x527e;
+	u16 initG_gaincode_rev6_224B0 = 0x427e;
+	u16 initG_gaincode_rev6_elna = 0x127e;
+	u16 initA_gaincode = 0x52de;
+	u16 initA_gaincode_rev4 = 0x629e;
+	u16 initA_gaincode_rev4_elna = 0x329e;
+	u16 initA_gaincode_rev5 = 0x729e;
+	u16 initA_gaincode_rev6 = 0x729e;
+	u16 init_gaincode;
+	u16 clip1hiG_gaincode = 0x107e;
+	u16 clip1hiG_gaincode_rev4 = 0x007e;
+	u16 clip1hiG_gaincode_rev5 = 0x1076;
+	u16 clip1hiG_gaincode_rev6 = 0x007e;
+	u16 clip1hiA_gaincode = 0x00de;
+	u16 clip1hiA_gaincode_rev4 = 0x029e;
+	u16 clip1hiA_gaincode_rev5 = 0x029e;
+	u16 clip1hiA_gaincode_rev6 = 0x029e;
+	u16 clip1hi_gaincode;
+	u16 clip1mdG_gaincode = 0x0066;
+	u16 clip1mdA_gaincode = 0x00ca;
+	u16 clip1mdA_gaincode_rev4 = 0x1084;
+	u16 clip1mdA_gaincode_rev5 = 0x2084;
+	u16 clip1mdA_gaincode_rev6 = 0x2084;
+	u16 clip1md_gaincode = 0;
+	u16 clip1loG_gaincode = 0x0074;
+	u16 clip1loG_gaincode_rev5[] = {
+		0x0062, 0x0064, 0x006a, 0x106a, 0x106c, 0x1074, 0x107c, 0x207c
+	};
+	u16 clip1loG_gaincode_rev6[] = {
+		0x106a, 0x106c, 0x1074, 0x107c, 0x007e, 0x107e, 0x207e, 0x307e
+	};
+	u16 clip1loG_gaincode_rev6_224B0 = 0x1074;
+	u16 clip1loA_gaincode = 0x00cc;
+	u16 clip1loA_gaincode_rev4 = 0x0086;
+	u16 clip1loA_gaincode_rev5 = 0x2086;
+	u16 clip1loA_gaincode_rev6 = 0x2086;
+	u16 clip1lo_gaincode;
+	u8 crsminG_th = 0x18;
+	u8 crsminG_th_rev5 = 0x18;
+	u8 crsminG_th_rev6 = 0x18;
+	u8 crsminA_th = 0x1e;
+	u8 crsminA_th_rev4 = 0x24;
+	u8 crsminA_th_rev5 = 0x24;
+	u8 crsminA_th_rev6 = 0x24;
+	u8 crsmin_th;
+	u8 crsminlG_th = 0x18;
+	u8 crsminlG_th_rev5 = 0x18;
+	u8 crsminlG_th_rev6 = 0x18;
+	u8 crsminlA_th = 0x1e;
+	u8 crsminlA_th_rev4 = 0x24;
+	u8 crsminlA_th_rev5 = 0x24;
+	u8 crsminlA_th_rev6 = 0x24;
+	u8 crsminl_th = 0;
+	u8 crsminuG_th = 0x18;
+	u8 crsminuG_th_rev5 = 0x18;
+	u8 crsminuG_th_rev6 = 0x18;
+	u8 crsminuA_th = 0x1e;
+	u8 crsminuA_th_rev4 = 0x24;
+	u8 crsminuA_th_rev5 = 0x24;
+	u8 crsminuA_th_rev6 = 0x24;
+	u8 crsminuA_th_rev6_224B0 = 0x2d;
+	u8 crsminu_th;
+	u16 nbclipG_th = 0x20d;
+	u16 nbclipG_th_rev4 = 0x1a1;
+	u16 nbclipG_th_rev5 = 0x1d0;
+	u16 nbclipG_th_rev6 = 0x1d0;
+	u16 nbclipA_th = 0x1a1;
+	u16 nbclipA_th_rev4 = 0x107;
+	u16 nbclipA_th_rev5 = 0x0a9;
+	u16 nbclipA_th_rev6 = 0x0f0;
+	u16 nbclip_th = 0;
+	u8 w1clipG_th = 5;
+	u8 w1clipG_th_rev5 = 9;
+	u8 w1clipG_th_rev6 = 5;
+	u8 w1clipA_th = 25, w1clip_th;
+	u8 rssi_gain_default = 0x50;
+	u8 rssiG_gain_rev6_224B0 = 0x50;
+	u8 rssiA_gain_rev5 = 0x90;
+	u8 rssiA_gain_rev6 = 0x90;
+	u8 rssi_gain;
+	u16 regval[21];
+	u8 triso;
+
+	triso = (CHSPEC_IS5G(pi->radio_chanspec)) ? pi->srom_fem5g.triso :
+	    pi->srom_fem2g.triso;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (pi->pubpi.radiorev == 5) {
+
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev5(pi);
+		} else if (pi->pubpi.radiorev == 7) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x44 << 0));
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x44 << 0));
+
+		} else if ((pi->pubpi.radiorev == 3)
+			   || (pi->pubpi.radiorev == 8)) {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+
+			if (pi->pubpi.radiorev == 8) {
+				mod_phy_reg(pi, 0x283,
+					    (0xff << 0), (0x44 << 0));
+				mod_phy_reg(pi, 0x280,
+					    (0xff << 0), (0x44 << 0));
+			}
+		} else {
+			wlc_phy_workarounds_nphy_gainctrl_2057_rev6(pi);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		mod_phy_reg(pi, 0xa0, (0x1 << 6), (1 << 6));
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		currband =
+		    read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+		if (currband == 0) {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				if (pi->pubpi.radiorev == 11) {
+					lna1_gain_db = lna1G_gain_db_rev6_224B0;
+					lna2_gain_db = lna2G_gain_db_rev6_224B0;
+					rfseq_init_gain =
+					    rfseqG_init_gain_rev6_224B0;
+					init_gaincode =
+					    initG_gaincode_rev6_224B0;
+					clip1hi_gaincode =
+					    clip1hiG_gaincode_rev6;
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev6_224B0;
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssiG_gain_rev6_224B0;
+				} else {
+					lna1_gain_db = lna1G_gain_db_rev6;
+					lna2_gain_db = lna2G_gain_db_rev6;
+					if (pi->sh->boardflags & BFL_EXTLNA) {
+
+						rfseq_init_gain =
+						    rfseqG_init_gain_rev6_elna;
+						init_gaincode =
+						    initG_gaincode_rev6_elna;
+					} else {
+						rfseq_init_gain =
+						    rfseqG_init_gain_rev6;
+						init_gaincode =
+						    initG_gaincode_rev6;
+					}
+					clip1hi_gaincode =
+					    clip1hiG_gaincode_rev6;
+					switch (triso) {
+					case 0:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[0];
+						break;
+					case 1:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[1];
+						break;
+					case 2:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[2];
+						break;
+					case 3:
+					default:
+
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[3];
+						break;
+					case 4:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[4];
+						break;
+					case 5:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[5];
+						break;
+					case 6:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[6];
+						break;
+					case 7:
+						clip1lo_gaincode =
+						    clip1loG_gaincode_rev6[7];
+						break;
+					}
+					nbclip_th = nbclipG_th_rev6;
+					w1clip_th = w1clipG_th_rev6;
+					crsmin_th = crsminG_th_rev6;
+					crsminl_th = crsminlG_th_rev6;
+					crsminu_th = crsminuG_th_rev6;
+					rssi_gain = rssi_gain_default;
+				}
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1G_gain_db_rev5;
+				lna2_gain_db = lna2G_gain_db_rev5;
+				if (pi->sh->boardflags & BFL_EXTLNA) {
+
+					rfseq_init_gain =
+					    rfseqG_init_gain_rev5_elna;
+					init_gaincode =
+					    initG_gaincode_rev5_elna;
+				} else {
+					rfseq_init_gain = rfseqG_init_gain_rev5;
+					init_gaincode = initG_gaincode_rev5;
+				}
+				clip1hi_gaincode = clip1hiG_gaincode_rev5;
+				switch (triso) {
+				case 0:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[0];
+					break;
+				case 1:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[1];
+					break;
+				case 2:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[2];
+					break;
+				case 3:
+
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[3];
+					break;
+				case 4:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[4];
+					break;
+				case 5:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[5];
+					break;
+				case 6:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[6];
+					break;
+				case 7:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[7];
+					break;
+				default:
+					clip1lo_gaincode =
+					    clip1loG_gaincode_rev5[3];
+					break;
+				}
+				nbclip_th = nbclipG_th_rev5;
+				w1clip_th = w1clipG_th_rev5;
+				crsmin_th = crsminG_th_rev5;
+				crsminl_th = crsminlG_th_rev5;
+				crsminu_th = crsminuG_th_rev5;
+				rssi_gain = rssi_gain_default;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1G_gain_db_rev4;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain_rev4;
+				init_gaincode = initG_gaincode_rev4;
+				clip1hi_gaincode = clip1hiG_gaincode_rev4;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th_rev4;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1G_gain_db;
+				lna2_gain_db = lna2G_gain_db;
+				rfseq_init_gain = rfseqG_init_gain;
+				init_gaincode = initG_gaincode;
+				clip1hi_gaincode = clip1hiG_gaincode;
+				clip1lo_gaincode = clip1loG_gaincode;
+				nbclip_th = nbclipG_th;
+				w1clip_th = w1clipG_th;
+				crsmin_th = crsminG_th;
+				crsminl_th = crsminlG_th;
+				crsminu_th = crsminuG_th;
+				rssi_gain = rssi_gain_default;
+			}
+			tia_gain_db = tiaG_gain_db;
+			tia_gainbits = tiaG_gainbits;
+			clip1md_gaincode = clip1mdG_gaincode;
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+				lna1_gain_db = lna1A_gain_db_rev6;
+				lna2_gain_db = lna2A_gain_db_rev6;
+				tia_gain_db = tiaA_gain_db_rev6;
+				tia_gainbits = tiaA_gainbits_rev6;
+				rfseq_init_gain = rfseqA_init_gain_rev6;
+				init_gaincode = initA_gaincode_rev6;
+				clip1hi_gaincode = clip1hiA_gaincode_rev6;
+				clip1md_gaincode = clip1mdA_gaincode_rev6;
+				clip1lo_gaincode = clip1loA_gaincode_rev6;
+				crsmin_th = crsminA_th_rev6;
+				crsminl_th = crsminlA_th_rev6;
+				if ((pi->pubpi.radiorev == 11) &&
+				    (CHSPEC_IS40(pi->radio_chanspec) == 0)) {
+					crsminu_th = crsminuA_th_rev6_224B0;
+				} else {
+					crsminu_th = crsminuA_th_rev6;
+				}
+				nbclip_th = nbclipA_th_rev6;
+				rssi_gain = rssiA_gain_rev6;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+				lna1_gain_db = lna1A_gain_db_rev5;
+				lna2_gain_db = lna2A_gain_db_rev5;
+				tia_gain_db = tiaA_gain_db_rev5;
+				tia_gainbits = tiaA_gainbits_rev5;
+				rfseq_init_gain = rfseqA_init_gain_rev5;
+				init_gaincode = initA_gaincode_rev5;
+				clip1hi_gaincode = clip1hiA_gaincode_rev5;
+				clip1md_gaincode = clip1mdA_gaincode_rev5;
+				clip1lo_gaincode = clip1loA_gaincode_rev5;
+				crsmin_th = crsminA_th_rev5;
+				crsminl_th = crsminlA_th_rev5;
+				crsminu_th = crsminuA_th_rev5;
+				nbclip_th = nbclipA_th_rev5;
+				rssi_gain = rssiA_gain_rev5;
+			} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+				lna1_gain_db = lna1A_gain_db_rev4;
+				lna2_gain_db = lna2A_gain_db_rev4;
+				tia_gain_db = tiaA_gain_db_rev4;
+				tia_gainbits = tiaA_gainbits_rev4;
+				if (pi->sh->boardflags & BFL_EXTLNA_5GHz) {
+
+					rfseq_init_gain =
+					    rfseqA_init_gain_rev4_elna;
+					init_gaincode =
+					    initA_gaincode_rev4_elna;
+				} else {
+					rfseq_init_gain = rfseqA_init_gain_rev4;
+					init_gaincode = initA_gaincode_rev4;
+				}
+				clip1hi_gaincode = clip1hiA_gaincode_rev4;
+				clip1md_gaincode = clip1mdA_gaincode_rev4;
+				clip1lo_gaincode = clip1loA_gaincode_rev4;
+				crsmin_th = crsminA_th_rev4;
+				crsminl_th = crsminlA_th_rev4;
+				crsminu_th = crsminuA_th_rev4;
+				nbclip_th = nbclipA_th_rev4;
+				rssi_gain = rssi_gain_default;
+			} else {
+				lna1_gain_db = lna1A_gain_db;
+				lna2_gain_db = lna2A_gain_db;
+				tia_gain_db = tiaA_gain_db;
+				tia_gainbits = tiaA_gainbits;
+				rfseq_init_gain = rfseqA_init_gain;
+				init_gaincode = initA_gaincode;
+				clip1hi_gaincode = clip1hiA_gaincode;
+				clip1md_gaincode = clip1mdA_gaincode;
+				clip1lo_gaincode = clip1loA_gaincode;
+				crsmin_th = crsminA_th;
+				crsminl_th = crsminlA_th;
+				crsminu_th = crsminuA_th;
+				nbclip_th = nbclipA_th;
+				rssi_gain = rssi_gain_default;
+			}
+			w1clip_th = w1clipA_th;
+		}
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAG1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX0),
+				0xf0);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAG2_IDAC | RADIO_2056_RX1),
+				0xf0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX0),
+				0x0);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_POLE | RADIO_2056_RX1),
+				0x0);
+
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX0),
+				rssi_gain);
+		write_radio_reg(pi, (RADIO_2056_RX_RSSI_GAIN | RADIO_2056_RX1),
+				rssi_gain);
+
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX0), 0x17);
+		write_radio_reg(pi,
+				(RADIO_2056_RX_BIASPOLE_LNAA1_IDAC |
+				 RADIO_2056_RX1), 0x17);
+
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX0),
+				0xFF);
+		write_radio_reg(pi, (RADIO_2056_RX_LNAA2_IDAC | RADIO_2056_RX1),
+				0xFF);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8,
+					 8, lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8,
+					 8, lna1_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+					 8, lna2_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+					 8, lna2_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20,
+					 8, tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20,
+					 8, tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20,
+					 8, tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20,
+					 8, tia_gainbits);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 6, 0x40,
+					 8, &lpf_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 6, 0x40,
+					 8, &lpf_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 6, 0x40,
+					 8, &lpf_gainbits);
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x24, clip1md_gaincode);
+		write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+
+		mod_phy_reg(pi, 0x27d, (0xff << 0), (crsmin_th << 0));
+		mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		write_phy_reg(pi, 0x2b, nbclip_th);
+		write_phy_reg(pi, 0x41, nbclip_th);
+
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1clip_th << 0));
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+	} else {
+
+		mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+		mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+		write_phy_reg(pi, 0x2b, 0x84);
+		write_phy_reg(pi, 0x41, 0x84);
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			write_phy_reg(pi, 0x6b, 0x2b);
+			write_phy_reg(pi, 0x6c, 0x2b);
+			write_phy_reg(pi, 0x6d, 0x9);
+			write_phy_reg(pi, 0x6e, 0x9);
+		}
+
+		w1th = NPHY_RSSICAL_W1_TARGET - 4;
+		mod_phy_reg(pi, 0x27, (0x3f << 0), (w1th << 0));
+		mod_phy_reg(pi, 0x3d, (0x3f << 0), (w1th << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x1c, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x32, (0x1f << 0), (0x1 << 0));
+
+			mod_phy_reg(pi, 0x1d, (0x1f << 0), (0x1 << 0));
+			mod_phy_reg(pi, 0x33, (0x1f << 0), (0x1 << 0));
+		}
+
+		write_phy_reg(pi, 0x150, 0x809c);
+
+		if (pi->nphy_gain_boost)
+			if ((CHSPEC_IS2G(pi->radio_chanspec)) &&
+			    (CHSPEC_IS40(pi->radio_chanspec)))
+				hpf_code = 4;
+			else
+				hpf_code = 5;
+		else if (CHSPEC_IS40(pi->radio_chanspec))
+			hpf_code = 6;
+		else
+			hpf_code = 7;
+
+		mod_phy_reg(pi, 0x20, (0x1f << 7), (hpf_code << 7));
+		mod_phy_reg(pi, 0x36, (0x1f << 7), (hpf_code << 7));
+
+		for (ctr = 0; ctr < 4; ctr++) {
+			regval[ctr] = (hpf_code << 8) | 0x7c;
+		}
+		wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+
+		if (pi->nphy_elna_gain_config) {
+			regval[0] = 0;
+			regval[1] = 1;
+			regval[2] = 1;
+			regval[3] = 1;
+			wlc_phy_table_write_nphy(pi, 2, 4, 8, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 4, 8, 16, regval);
+
+			for (ctr = 0; ctr < 4; ctr++) {
+				regval[ctr] = (hpf_code << 8) | 0x74;
+			}
+			wlc_phy_table_write_nphy(pi, 7, 4, 0x106, 16, regval);
+		}
+
+		if (NREV_IS(pi->pubpi.phy_rev, 2)) {
+			for (ctr = 0; ctr < 21; ctr++) {
+				regval[ctr] = 3 * ctr;
+			}
+			wlc_phy_table_write_nphy(pi, 0, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 1, 21, 32, 16, regval);
+
+			for (ctr = 0; ctr < 21; ctr++) {
+				regval[ctr] = (u16) ctr;
+			}
+			wlc_phy_table_write_nphy(pi, 2, 21, 32, 16, regval);
+			wlc_phy_table_write_nphy(pi, 3, 21, 32, 16, regval);
+		}
+
+		wlc_phy_set_rfseq_nphy(pi, NPHY_RFSEQ_UPDATEGAINU,
+				       rfseq_updategainu_events,
+				       rfseq_updategainu_dlys,
+				       sizeof(rfseq_updategainu_events) /
+				       sizeof(rfseq_updategainu_events[0]));
+
+		mod_phy_reg(pi, 0x153, (0xff << 8), (90 << 8));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec))
+			mod_phy_reg(pi,
+				    (NPHY_TO_BPHY_OFF + BPHY_OPTIONAL_MODES),
+				    0x7f, 0x4);
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev5(phy_info_t *pi)
+{
+	s8 lna1_gain_db[] = { 8, 13, 17, 22 };
+	s8 lna2_gain_db[] = { -2, 7, 11, 15 };
+	s8 tia_gain_db[] = { -4, -1, 2, 5, 5, 5, 5, 5, 5, 5 };
+	s8 tia_gainbits[] = {
+		0x0, 0x01, 0x02, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03 };
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+	mod_phy_reg(pi, 0x283, (0xff << 0), (0x3c << 0));
+	mod_phy_reg(pi, 0x280, (0xff << 0), (0x3c << 0));
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x8, 8,
+				 lna1_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x8, 8,
+				 lna1_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10, 8,
+				 lna2_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10, 8,
+				 lna2_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+				 tia_gain_db);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+				 tia_gain_db);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+				 tia_gainbits);
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+				 tia_gainbits);
+
+	write_phy_reg(pi, 0x37, 0x74);
+	write_phy_reg(pi, 0x2ad, 0x74);
+	write_phy_reg(pi, 0x38, 0x18);
+	write_phy_reg(pi, 0x2ae, 0x18);
+
+	write_phy_reg(pi, 0x2b, 0xe8);
+	write_phy_reg(pi, 0x41, 0xe8);
+
+	if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x12 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x12 << 0));
+	} else {
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (0x10 << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (0x10 << 0));
+	}
+}
+
+static void wlc_phy_workarounds_nphy_gainctrl_2057_rev6(phy_info_t *pi)
+{
+	u16 currband;
+	s8 lna1G_gain_db_rev7[] = { 9, 14, 19, 24 };
+	s8 *lna1_gain_db = NULL;
+	s8 *lna1_gain_db_2 = NULL;
+	s8 *lna2_gain_db = NULL;
+	s8 tiaA_gain_db_rev7[] = { -9, -6, -3, 0, 3, 3, 3, 3, 3, 3 };
+	s8 *tia_gain_db;
+	s8 tiaA_gainbits_rev7[] = { 0, 1, 2, 3, 4, 4, 4, 4, 4, 4 };
+	s8 *tia_gainbits;
+	u16 rfseqA_init_gain_rev7[] = { 0x624f, 0x624f };
+	u16 *rfseq_init_gain;
+	u16 init_gaincode;
+	u16 clip1hi_gaincode;
+	u16 clip1md_gaincode = 0;
+	u16 clip1md_gaincode_B;
+	u16 clip1lo_gaincode;
+	u16 clip1lo_gaincode_B;
+	u8 crsminl_th = 0;
+	u8 crsminu_th;
+	u16 nbclip_th = 0;
+	u8 w1clip_th;
+	u16 freq;
+	s8 nvar_baseline_offset0 = 0, nvar_baseline_offset1 = 0;
+	u8 chg_nbclip_th = 0;
+
+	mod_phy_reg(pi, 0x1c, (0x1 << 13), (1 << 13));
+	mod_phy_reg(pi, 0x32, (0x1 << 13), (1 << 13));
+
+	currband = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (currband == 0) {
+
+		lna1_gain_db = lna1G_gain_db_rev7;
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+					 lna1_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+					 lna1_gain_db);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (0x40 << 0));
+
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (0x3e << 0));
+			mod_phy_reg(pi, 0x283, (0xff << 0), (0x3e << 0));
+		}
+
+		mod_phy_reg(pi, 0x289, (0xff << 0), (0x46 << 0));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+			mod_phy_reg(pi, 0x300, (0x3f << 0), (13 << 0));
+			mod_phy_reg(pi, 0x301, (0x3f << 0), (13 << 0));
+		}
+	} else {
+
+		init_gaincode = 0x9e;
+		clip1hi_gaincode = 0x9e;
+		clip1md_gaincode_B = 0x24;
+		clip1lo_gaincode = 0x8a;
+		clip1lo_gaincode_B = 8;
+		rfseq_init_gain = rfseqA_init_gain_rev7;
+
+		tia_gain_db = tiaA_gain_db_rev7;
+		tia_gainbits = tiaA_gainbits_rev7;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			w1clip_th = 25;
+			clip1md_gaincode = 0x82;
+
+			if ((freq <= 5080) || (freq == 5825)) {
+
+				s8 lna1A_gain_db_rev7[] = { 11, 16, 20, 24 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					11, 17, 22, 25 };
+				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x3e;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else if ((freq >= 5500) && (freq <= 5700)) {
+
+				s8 lna1A_gain_db_rev7[] = { 11, 17, 21, 25 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					12, 18, 22, 26 };
+				s8 lna2A_gain_db_rev7[] = { 1, 8, 12, 16 };
+
+				crsminu_th = 0x45;
+				clip1md_gaincode_B = 0x14;
+				nbclip_th = 0xff;
+				chg_nbclip_th = 1;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			} else {
+
+				s8 lna1A_gain_db_rev7[] = { 12, 18, 22, 26 };
+				s8 lna1A_gain_db_2_rev7[] = {
+					12, 18, 22, 26 };
+				s8 lna2A_gain_db_rev7[] = { -1, 6, 10, 14 };
+
+				crsminu_th = 0x41;
+				lna1_gain_db = lna1A_gain_db_rev7;
+				lna1_gain_db_2 = lna1A_gain_db_2_rev7;
+				lna2_gain_db = lna2A_gain_db_rev7;
+			}
+
+			if (freq <= 4920) {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5700)) {
+				nvar_baseline_offset0 = 3;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 0;
+			}
+		} else {
+
+			crsminu_th = 0x3a;
+			crsminl_th = 0x3a;
+			w1clip_th = 20;
+
+			if ((freq >= 4920) && (freq <= 5320)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 5;
+			} else if ((freq > 5320) && (freq <= 5550)) {
+				nvar_baseline_offset0 = 4;
+				nvar_baseline_offset1 = 2;
+			} else {
+				nvar_baseline_offset0 = 5;
+				nvar_baseline_offset1 = 3;
+			}
+		}
+
+		write_phy_reg(pi, 0x20, init_gaincode);
+		write_phy_reg(pi, 0x2a7, init_gaincode);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+					 pi->pubpi.phy_corenum, 0x106, 16,
+					 rfseq_init_gain);
+
+		write_phy_reg(pi, 0x22, clip1hi_gaincode);
+		write_phy_reg(pi, 0x2a9, clip1hi_gaincode);
+
+		write_phy_reg(pi, 0x36, clip1md_gaincode_B);
+		write_phy_reg(pi, 0x2ac, clip1md_gaincode_B);
+
+		write_phy_reg(pi, 0x37, clip1lo_gaincode);
+		write_phy_reg(pi, 0x2ad, clip1lo_gaincode);
+		write_phy_reg(pi, 0x38, clip1lo_gaincode_B);
+		write_phy_reg(pi, 0x2ae, clip1lo_gaincode_B);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 10, 0x20, 8,
+					 tia_gain_db);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 10, 0x20, 8,
+					 tia_gain_db);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS1, 10, 0x20, 8,
+					 tia_gainbits);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAINBITS2, 10, 0x20, 8,
+					 tia_gainbits);
+
+		mod_phy_reg(pi, 0x283, (0xff << 0), (crsminu_th << 0));
+
+		if (chg_nbclip_th == 1) {
+			write_phy_reg(pi, 0x2b, nbclip_th);
+			write_phy_reg(pi, 0x41, nbclip_th);
+		}
+
+		mod_phy_reg(pi, 0x300, (0x3f << 0), (w1clip_th << 0));
+		mod_phy_reg(pi, 0x301, (0x3f << 0), (w1clip_th << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 0), (nvar_baseline_offset0 << 0));
+
+		mod_phy_reg(pi, 0x2e4,
+			    (0x3f << 6), (nvar_baseline_offset1 << 6));
+
+		if (CHSPEC_IS20(pi->radio_chanspec)) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 8, 8,
+						 lna1_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 8, 8,
+						 lna1_gain_db_2);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN1, 4, 0x10,
+						 8, lna2_gain_db);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_GAIN2, 4, 0x10,
+						 8, lna2_gain_db);
+
+			write_phy_reg(pi, 0x24, clip1md_gaincode);
+			write_phy_reg(pi, 0x2ab, clip1md_gaincode);
+		} else {
+			mod_phy_reg(pi, 0x280, (0xff << 0), (crsminl_th << 0));
+		}
+
+	}
+
+}
+
+static void wlc_phy_adjust_lnagaintbl_nphy(phy_info_t *pi)
+{
+	uint core;
+	int ctr;
+	s16 gain_delta[2];
+	u8 curr_channel;
+	u16 minmax_gain[2];
+	u16 regval[4];
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (pi->nphy_gain_boost) {
+		if ((CHSPEC_IS2G(pi->radio_chanspec))) {
+
+			gain_delta[0] = 6;
+			gain_delta[1] = 6;
+		} else {
+
+			curr_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+			gain_delta[0] =
+			    (s16)
+			    PHY_HW_ROUND(((nphy_lnagain_est0[0] *
+					   curr_channel) +
+					  nphy_lnagain_est0[1]), 13);
+			gain_delta[1] =
+			    (s16)
+			    PHY_HW_ROUND(((nphy_lnagain_est1[0] *
+					   curr_channel) +
+					  nphy_lnagain_est1[1]), 13);
+		}
+	} else {
+
+		gain_delta[0] = 0;
+		gain_delta[1] = 0;
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (pi->nphy_elna_gain_config) {
+
+			regval[0] = nphy_def_lnagains[2] + gain_delta[core];
+			regval[1] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[2] = nphy_def_lnagains[3] + gain_delta[core];
+			regval[3] = nphy_def_lnagains[3] + gain_delta[core];
+		} else {
+			for (ctr = 0; ctr < 4; ctr++) {
+				regval[ctr] =
+				    nphy_def_lnagains[ctr] + gain_delta[core];
+			}
+		}
+		wlc_phy_table_write_nphy(pi, core, 4, 8, 16, regval);
+
+		minmax_gain[core] =
+		    (u16) (nphy_def_lnagains[2] + gain_delta[core] + 4);
+	}
+
+	mod_phy_reg(pi, 0x1e, (0xff << 0), (minmax_gain[0] << 0));
+	mod_phy_reg(pi, 0x34, (0xff << 0), (minmax_gain[1] << 0));
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+void wlc_phy_switch_radio_nphy(phy_info_t *pi, bool on)
+{
+	if (on) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if (!pi->radio_is_on) {
+				wlc_phy_radio_preinit_205x(pi);
+				wlc_phy_radio_init_2057(pi);
+				wlc_phy_radio_postinit_2057(pi);
+			}
+
+			wlc_phy_chanspec_set((wlc_phy_t *) pi,
+					     pi->radio_chanspec);
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio_preinit_205x(pi);
+			wlc_phy_radio_init_2056(pi);
+			wlc_phy_radio_postinit_2056(pi);
+
+			wlc_phy_chanspec_set((wlc_phy_t *) pi,
+					     pi->radio_chanspec);
+		} else {
+			wlc_phy_radio_preinit_2055(pi);
+			wlc_phy_radio_init_2055(pi);
+			wlc_phy_radio_postinit_2055(pi);
+		}
+
+		pi->radio_is_on = true;
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX0, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX0, 0);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PADG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAA_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_PGAG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+			mod_radio_reg(pi,
+				      RADIO_2056_TX_MIXA_BOOST_TUNE |
+				      RADIO_2056_TX1, 0xf0, 0);
+			write_radio_reg(pi,
+					RADIO_2056_TX_MIXG_BOOST_TUNE |
+					RADIO_2056_TX1, 0);
+
+			pi->radio_is_on = false;
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+			and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+			pi->radio_is_on = false;
+		}
+
+	}
+}
+
+static void wlc_phy_radio_preinit_2055(phy_info_t *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU | RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, RFCC_POR_FORCE);
+}
+
+static void wlc_phy_radio_init_2055(phy_info_t *pi)
+{
+	wlc_phy_init_radio_regs(pi, regs_2055, RADIO_DEFAULT_CORE);
+}
+
+static void wlc_phy_radio_postinit_2055(phy_info_t *pi)
+{
+
+	and_radio_reg(pi, RADIO_2055_MASTER_CNTRL1,
+		      ~(RADIO_2055_JTAGCTRL_MASK | RADIO_2055_JTAGSYNC_MASK));
+
+	if (((pi->sh->sromrev >= 4)
+	     && !(pi->sh->boardflags2 & BFL2_RXBB_INT_REG_DIS))
+	    || ((pi->sh->sromrev < 4))) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXBB_REGULATOR, 0x7F);
+		and_radio_reg(pi, RADIO_2055_CORE2_RXBB_REGULATOR, 0x7F);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_RRCCAL_N_OPT_SEL, 0x3F, 0x2C);
+	write_radio_reg(pi, RADIO_2055_CAL_MISC, 0x3C);
+
+	and_radio_reg(pi, RADIO_2055_CAL_MISC,
+		      ~(RADIO_2055_RRCAL_START | RADIO_2055_RRCAL_RST_N));
+
+	or_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL, RADIO_2055_CAL_LPO_ENABLE);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_RST_N);
+
+	udelay(1000);
+
+	or_radio_reg(pi, RADIO_2055_CAL_MISC, RADIO_2055_RRCAL_START);
+
+	SPINWAIT(((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		   RADIO_2055_RCAL_DONE) != RADIO_2055_RCAL_DONE), 2000);
+
+	ASSERT((read_radio_reg(pi, RADIO_2055_CAL_COUNTER_OUT2) &
+		RADIO_2055_RCAL_DONE) == RADIO_2055_RCAL_DONE);
+
+	and_radio_reg(pi, RADIO_2055_CAL_LPO_CNTRL,
+		      ~(RADIO_2055_CAL_LPO_ENABLE));
+
+	wlc_phy_chanspec_set((wlc_phy_t *) pi, pi->radio_chanspec);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_LPF, 9);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_LPF, 9);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_RXBB_MIDAC_HIPAS, 0x83);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXBB_MIDAC_HIPAS, 0x83);
+
+	mod_radio_reg(pi, RADIO_2055_CORE1_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	mod_radio_reg(pi, RADIO_2055_CORE2_LNA_GAINBST,
+		      RADIO_2055_GAINBST_VAL_MASK, RADIO_2055_GAINBST_CODE);
+	if (pi->nphy_gain_boost) {
+		and_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+		and_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			      ~(RADIO_2055_GAINBST_DISABLE));
+	} else {
+		or_radio_reg(pi, RADIO_2055_CORE1_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+		or_radio_reg(pi, RADIO_2055_CORE2_RXRF_SPC1,
+			     RADIO_2055_GAINBST_DISABLE);
+	}
+
+	udelay(2);
+}
+
+static void wlc_phy_radio_preinit_205x(phy_info_t *pi)
+{
+
+	and_phy_reg(pi, 0x78, ~RFCC_CHIP0_PU);
+	and_phy_reg(pi, 0x78, RFCC_OE_POR_FORCE);
+
+	or_phy_reg(pi, 0x78, ~RFCC_OE_POR_FORCE);
+	or_phy_reg(pi, 0x78, RFCC_CHIP0_PU);
+
+}
+
+static void wlc_phy_radio_init_2056(phy_info_t *pi)
+{
+	radio_regs_t *regs_SYN_2056_ptr = NULL;
+	radio_regs_t *regs_TX_2056_ptr = NULL;
+	radio_regs_t *regs_RX_2056_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		regs_SYN_2056_ptr = regs_SYN_2056;
+		regs_TX_2056_ptr = regs_TX_2056;
+		regs_RX_2056_ptr = regs_RX_2056;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+		regs_TX_2056_ptr = regs_TX_2056_A1;
+		regs_RX_2056_ptr = regs_RX_2056_A1;
+	} else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			regs_TX_2056_ptr = regs_TX_2056_rev5;
+			regs_RX_2056_ptr = regs_RX_2056_rev5;
+			break;
+
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			regs_TX_2056_ptr = regs_TX_2056_rev6;
+			regs_RX_2056_ptr = regs_RX_2056_rev6;
+			break;
+
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			regs_TX_2056_ptr = regs_TX_2056_rev7;
+			regs_RX_2056_ptr = regs_RX_2056_rev7;
+			break;
+
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			regs_TX_2056_ptr = regs_TX_2056_rev8;
+			regs_RX_2056_ptr = regs_RX_2056_rev8;
+			break;
+
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			regs_TX_2056_ptr = regs_TX_2056_rev11;
+			regs_RX_2056_ptr = regs_RX_2056_rev11;
+			break;
+
+		default:
+			ASSERT(0);
+			break;
+		}
+	}
+
+	wlc_phy_init_radio_regs(pi, regs_SYN_2056_ptr, (u16) RADIO_2056_SYN);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX0);
+
+	wlc_phy_init_radio_regs(pi, regs_TX_2056_ptr, (u16) RADIO_2056_TX1);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX0);
+
+	wlc_phy_init_radio_regs(pi, regs_RX_2056_ptr, (u16) RADIO_2056_RX1);
+}
+
+static void wlc_phy_radio_postinit_2056(phy_info_t *pi)
+{
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_CTRL, 0xb, 0xb);
+
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_PU, 0x2, 0x2);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x2);
+	udelay(1000);
+	mod_radio_reg(pi, RADIO_2056_SYN_COM_RESET, 0x2, 0x0);
+
+	if ((pi->sh->boardflags2 & BFL2_LEGACY)
+	    || (pi->sh->boardflags2 & BFL2_XTALBUFOUTEN)) {
+
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xf4, 0x0);
+	} else {
+
+		mod_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2, 0xfc, 0x0);
+	}
+
+	mod_radio_reg(pi, RADIO_2056_SYN_RCCAL_CTRL0, 0x1, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+	}
+}
+
+static void wlc_phy_radio_init_2057(phy_info_t *pi)
+{
+	radio_20xx_regs_t *regs_2057_ptr = NULL;
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+		regs_2057_ptr = regs_2057_rev4;
+	} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+		   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+
+			if (pi->pubpi.radiover == 0x0) {
+
+				regs_2057_ptr = regs_2057_rev5;
+
+			} else if (pi->pubpi.radiover == 0x1) {
+
+				regs_2057_ptr = regs_2057_rev5v1;
+			} else {
+				ASSERT(0);
+				break;
+			}
+
+		case 7:
+
+			regs_2057_ptr = regs_2057_rev7;
+			break;
+
+		case 8:
+
+			regs_2057_ptr = regs_2057_rev8;
+			break;
+
+		default:
+			ASSERT(0);
+			break;
+		}
+	} else {
+		ASSERT(0);
+	}
+
+	wlc_phy_init_radio_regs_allbands(pi, regs_2057_ptr);
+}
+
+static void wlc_phy_radio_postinit_2057(phy_info_t *pi)
+{
+
+	mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x1, 0x1);
+
+	if (pi->sh->chip == !BCM6362_CHIP_ID) {
+
+		mod_radio_reg(pi, RADIO_2057_XTALPUOVR_PINCTRL, 0x2, 0x2);
+	}
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x78);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x80);
+	mdelay(2);
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x78, 0x0);
+	mod_radio_reg(pi, RADIO_2057_XTAL_CONFIG2, 0x80, 0x0);
+
+	if (pi->phy_init_por) {
+		wlc_phy_radio205x_rcal(pi);
+		wlc_phy_radio2057_rccal(pi);
+	}
+
+	mod_radio_reg(pi, RADIO_2057_RFPLL_MASTER, 0x8, 0x0);
+}
+
+static bool
+wlc_phy_chan2freq_nphy(phy_info_t *pi, uint channel, int *f,
+		       chan_info_nphy_radio2057_t **t0,
+		       chan_info_nphy_radio205x_t **t1,
+		       chan_info_nphy_radio2057_rev5_t **t2,
+		       chan_info_nphy_2055_t **t3)
+{
+	uint i;
+	chan_info_nphy_radio2057_t *chan_info_tbl_p_0 = NULL;
+	chan_info_nphy_radio205x_t *chan_info_tbl_p_1 = NULL;
+	chan_info_nphy_radio2057_rev5_t *chan_info_tbl_p_2 = NULL;
+	u32 tbl_len = 0;
+
+	int freq = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev7_2057_rev4;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev7_2057_rev4);
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 8)
+			   || NREV_IS(pi->pubpi.phy_rev, 9)) {
+			switch (pi->pubpi.radiorev) {
+
+			case 5:
+
+				if (pi->pubpi.radiover == 0x0) {
+
+					chan_info_tbl_p_2 =
+					    chan_info_nphyrev8_2057_rev5;
+					tbl_len =
+					    ARRAY_SIZE
+					    (chan_info_nphyrev8_2057_rev5);
+
+				} else if (pi->pubpi.radiover == 0x1) {
+
+					chan_info_tbl_p_2 =
+					    chan_info_nphyrev9_2057_rev5v1;
+					tbl_len =
+					    ARRAY_SIZE
+					    (chan_info_nphyrev9_2057_rev5v1);
+
+				}
+				break;
+
+			case 7:
+				chan_info_tbl_p_0 =
+				    chan_info_nphyrev8_2057_rev7;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev7);
+				break;
+
+			case 8:
+				chan_info_tbl_p_0 =
+				    chan_info_nphyrev8_2057_rev8;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+				break;
+
+			default:
+				if (NORADIO_ENAB(pi->pubpi)) {
+					goto fail;
+				}
+				break;
+			}
+		} else if (NREV_IS(pi->pubpi.phy_rev, 16)) {
+
+			chan_info_tbl_p_0 = chan_info_nphyrev8_2057_rev8;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev8_2057_rev8);
+		} else {
+			goto fail;
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (pi->pubpi.radiorev == 5) {
+
+				if (chan_info_tbl_p_2[i].chan == channel)
+					break;
+			} else {
+
+				if (chan_info_tbl_p_0[i].chan == channel)
+					break;
+			}
+		}
+
+		if (i >= tbl_len) {
+			ASSERT(i < tbl_len);
+			goto fail;
+		}
+		if (pi->pubpi.radiorev == 5) {
+			*t2 = &chan_info_tbl_p_2[i];
+			freq = chan_info_tbl_p_2[i].freq;
+		} else {
+			*t0 = &chan_info_tbl_p_0[i];
+			freq = chan_info_tbl_p_0[i].freq;
+		}
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev3_2056;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev3_2056);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 4)) {
+			chan_info_tbl_p_1 = chan_info_nphyrev4_2056_A1;
+			tbl_len = ARRAY_SIZE(chan_info_nphyrev4_2056_A1);
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)
+			   || NREV_IS(pi->pubpi.phy_rev, 6)) {
+			switch (pi->pubpi.radiorev) {
+			case 5:
+				chan_info_tbl_p_1 = chan_info_nphyrev5_2056v5;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev5_2056v5);
+				break;
+			case 6:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v6;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v6);
+				break;
+			case 7:
+			case 9:
+				chan_info_tbl_p_1 = chan_info_nphyrev5n6_2056v7;
+				tbl_len =
+				    ARRAY_SIZE(chan_info_nphyrev5n6_2056v7);
+				break;
+			case 8:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v8;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v8);
+				break;
+			case 11:
+				chan_info_tbl_p_1 = chan_info_nphyrev6_2056v11;
+				tbl_len = ARRAY_SIZE(chan_info_nphyrev6_2056v11);
+				break;
+			default:
+				if (NORADIO_ENAB(pi->pubpi)) {
+					goto fail;
+				}
+				break;
+			}
+		}
+
+		for (i = 0; i < tbl_len; i++) {
+			if (chan_info_tbl_p_1[i].chan == channel)
+				break;
+		}
+
+		if (i >= tbl_len) {
+			ASSERT(i < tbl_len);
+			goto fail;
+		}
+		*t1 = &chan_info_tbl_p_1[i];
+		freq = chan_info_tbl_p_1[i].freq;
+
+	} else {
+		for (i = 0; i < ARRAY_SIZE(chan_info_nphy_2055); i++)
+			if (chan_info_nphy_2055[i].chan == channel)
+				break;
+
+		if (i >= ARRAY_SIZE(chan_info_nphy_2055)) {
+			ASSERT(i < ARRAY_SIZE(chan_info_nphy_2055));
+			goto fail;
+		}
+		*t3 = &chan_info_nphy_2055[i];
+		freq = chan_info_nphy_2055[i].freq;
+	}
+
+	*f = freq;
+	return true;
+
+ fail:
+	*f = WL_CHAN_FREQ_RANGE_2G;
+	return false;
+}
+
+u8 wlc_phy_get_chan_freq_range_nphy(phy_info_t *pi, uint channel)
+{
+	int freq;
+	chan_info_nphy_radio2057_t *t0 = NULL;
+	chan_info_nphy_radio205x_t *t1 = NULL;
+	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
+	chan_info_nphy_2055_t *t3 = NULL;
+
+	if (NORADIO_ENAB(pi->pubpi))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if (channel == 0)
+		channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+	wlc_phy_chan2freq_nphy(pi, channel, &freq, &t0, &t1, &t2, &t3);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec))
+		return WL_CHAN_FREQ_RANGE_2G;
+
+	if ((freq >= BASE_LOW_5G_CHAN) && (freq < BASE_MID_5G_CHAN)) {
+		return WL_CHAN_FREQ_RANGE_5GL;
+	} else if ((freq >= BASE_MID_5G_CHAN) && (freq < BASE_HIGH_5G_CHAN)) {
+		return WL_CHAN_FREQ_RANGE_5GM;
+	} else {
+		return WL_CHAN_FREQ_RANGE_5GH;
+	}
+}
+
+static void
+wlc_phy_chanspec_radio2055_setup(phy_info_t *pi, chan_info_nphy_2055_t *ci)
+{
+
+	write_radio_reg(pi, RADIO_2055_PLL_REF, ci->RF_pll_ref);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD0, ci->RF_rf_pll_mod0);
+	write_radio_reg(pi, RADIO_2055_RF_PLL_MOD1, ci->RF_rf_pll_mod1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAP_TAIL, ci->RF_vco_cap_tail);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL1, ci->RF_vco_cal1);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL2, ci->RF_vco_cal2);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C1, ci->RF_pll_lf_c1);
+	write_radio_reg(pi, RADIO_2055_PLL_LF_R1, ci->RF_pll_lf_r1);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_PLL_LF_C2, ci->RF_pll_lf_c2);
+	write_radio_reg(pi, RADIO_2055_LGBUF_CEN_BUF, ci->RF_lgbuf_cen_buf);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE1, ci->RF_lgen_tune1);
+	write_radio_reg(pi, RADIO_2055_LGEN_TUNE2, ci->RF_lgen_tune2);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_A_TUNE,
+			ci->RF_core1_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_LGBUF_G_TUNE,
+			ci->RF_core1_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE1_RXRF_REG1, ci->RF_core1_rxrf_reg1);
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_PGA_PAD_TN,
+			ci->RF_core1_tx_pga_pad_tn);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE1_TX_MX_BGTRIM,
+			ci->RF_core1_tx_mx_bgtrim);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_A_TUNE,
+			ci->RF_core2_lgbuf_a_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_LGBUF_G_TUNE,
+			ci->RF_core2_lgbuf_g_tune);
+	write_radio_reg(pi, RADIO_2055_CORE2_RXRF_REG1, ci->RF_core2_rxrf_reg1);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_PGA_PAD_TN,
+			ci->RF_core2_tx_pga_pad_tn);
+	write_radio_reg(pi, RADIO_2055_CORE2_TX_MX_BGTRIM,
+			ci->RF_core2_tx_mx_bgtrim);
+
+	udelay(50);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x05);
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x45);
+
+	WLC_PHY_WAR_PR51571(pi);
+
+	write_radio_reg(pi, RADIO_2055_VCO_CAL10, 0x65);
+
+	udelay(300);
+}
+
+static void
+wlc_phy_chanspec_radio2056_setup(phy_info_t *pi,
+				 const chan_info_nphy_radio205x_t *ci)
+{
+	radio_regs_t *regs_SYN_2056_ptr = NULL;
+
+	write_radio_reg(pi,
+			RADIO_2056_SYN_PLL_VCOCAL1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_vcocal2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_REFDIV | RADIO_2056_SYN,
+			ci->RF_SYN_pll_refdiv);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_MMD1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_mmd1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter1);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter2);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER3 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter3);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter4);
+	write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER5 | RADIO_2056_SYN,
+			ci->RF_SYN_pll_loopfilter5);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR27 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr27);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR28 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr28);
+	write_radio_reg(pi, RADIO_2056_SYN_RESERVED_ADDR29 | RADIO_2056_SYN,
+			ci->RF_SYN_reserved_addr29);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_VCOBUF1 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_VCOBUF1);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_MIXER2 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_MIXER2);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF3 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF3);
+	write_radio_reg(pi, RADIO_2056_SYN_LOGEN_BUF4 | RADIO_2056_SYN,
+			ci->RF_SYN_logen_BUF4);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX0,
+			ci->RF_RX0_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX0,
+			ci->RF_TX0_mixg_boost_tune);
+
+	write_radio_reg(pi,
+			RADIO_2056_RX_LNAA_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnaa_tune);
+	write_radio_reg(pi, RADIO_2056_RX_LNAG_TUNE | RADIO_2056_RX1,
+			ci->RF_RX1_lnag_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_INTPAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_intpag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pada_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PADG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_padg_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgaa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_PGAG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_pgag_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXA_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixa_boost_tune);
+	write_radio_reg(pi, RADIO_2056_TX_MIXG_BOOST_TUNE | RADIO_2056_TX1,
+			ci->RF_TX1_mixg_boost_tune);
+
+	if (NREV_IS(pi->pubpi.phy_rev, 3))
+		regs_SYN_2056_ptr = regs_SYN_2056;
+	else if (NREV_IS(pi->pubpi.phy_rev, 4))
+		regs_SYN_2056_ptr = regs_SYN_2056_A1;
+	else {
+		switch (pi->pubpi.radiorev) {
+		case 5:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev5;
+			break;
+		case 6:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev6;
+			break;
+		case 7:
+		case 9:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev7;
+			break;
+		case 8:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev8;
+			break;
+		case 11:
+			regs_SYN_2056_ptr = regs_SYN_2056_rev11;
+			break;
+		}
+	}
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_g);
+	} else {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+				RADIO_2056_SYN,
+				(u16) regs_SYN_2056_ptr[0x49 - 2].init_a);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_GPLL_WAR) {
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+
+			if ((pi->sh->chip == BCM4716_CHIP_ID) ||
+			    (pi->sh->chip == BCM47162_CHIP_ID)) {
+
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_LOOPFILTER4 |
+						RADIO_2056_SYN, 0x14);
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_CP2 |
+						RADIO_2056_SYN, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_LOOPFILTER4 |
+						RADIO_2056_SYN, 0xb);
+				write_radio_reg(pi,
+						RADIO_2056_SYN_PLL_CP2 |
+						RADIO_2056_SYN, 0x14);
+			}
+		}
+	}
+
+	if ((pi->sh->boardflags2 & BFL2_GPLL_WAR2) &&
+	    (CHSPEC_IS2G(pi->radio_chanspec))) {
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER1 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER2 | RADIO_2056_SYN,
+				0x1f);
+		write_radio_reg(pi,
+				RADIO_2056_SYN_PLL_LOOPFILTER4 | RADIO_2056_SYN,
+				0xb);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 | RADIO_2056_SYN,
+				0x20);
+	}
+
+	if (pi->sh->boardflags2 & BFL2_APLL_WAR) {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER1 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER2 |
+					RADIO_2056_SYN, 0x1f);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_LOOPFILTER4 |
+					RADIO_2056_SYN, 0x5);
+			write_radio_reg(pi, RADIO_2056_SYN_PLL_CP2 |
+					RADIO_2056_SYN, 0xc);
+		}
+	}
+
+	if (PHY_IPA(pi) && CHSPEC_IS2G(pi->radio_chanspec)) {
+		u16 pag_boost_tune;
+		u16 padg_boost_tune;
+		u16 pgag_boost_tune;
+		u16 mixg_boost_tune;
+		u16 bias, cascbias;
+		uint core;
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (NREV_GE(pi->pubpi.phy_rev, 5)) {
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_IDAC, 0xcc);
+
+				if ((pi->sh->chip == BCM4716_CHIP_ID) ||
+				    (pi->sh->chip ==
+				     BCM47162_CHIP_ID)) {
+					bias = 0x40;
+					cascbias = 0x45;
+					pag_boost_tune = 0x5;
+					pgag_boost_tune = 0x33;
+					padg_boost_tune = 0x77;
+					mixg_boost_tune = 0x55;
+				} else {
+					bias = 0x25;
+					cascbias = 0x20;
+
+					if ((pi->sh->chip ==
+					     BCM43224_CHIP_ID)
+					    || (pi->sh->chip ==
+						BCM43225_CHIP_ID)
+					    || (pi->sh->chip ==
+						BCM43421_CHIP_ID)) {
+						if (pi->sh->chippkg ==
+						    BCM43224_FAB_SMIC) {
+							bias = 0x2a;
+							cascbias = 0x38;
+						}
+					}
+
+					pag_boost_tune = 0x4;
+					pgag_boost_tune = 0x03;
+					padg_boost_tune = 0x77;
+					mixg_boost_tune = 0x65;
+				}
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, cascbias);
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_BOOST_TUNE,
+						 pag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PGAG_BOOST_TUNE,
+						 pgag_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 PADG_BOOST_TUNE,
+						 padg_boost_tune);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 MIXG_BOOST_TUNE,
+						 mixg_boost_tune);
+			} else {
+
+				bias = IS40MHZ(pi) ? 0x40 : 0x20;
+
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IMAIN_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_IAUX_STAT, bias);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_CASCBIAS, 0x30);
+			}
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core, PA_SPARE1,
+					 0xee);
+		}
+	}
+
+	if (PHY_IPA(pi) && NREV_IS(pi->pubpi.phy_rev, 6)
+	    && CHSPEC_IS5G(pi->radio_chanspec)) {
+		u16 paa_boost_tune;
+		u16 pada_boost_tune;
+		u16 pgaa_boost_tune;
+		u16 mixa_boost_tune;
+		u16 freq, pabias, cascbias;
+		uint core;
+
+		freq = CHAN5G_FREQ(CHSPEC_CHANNEL(pi->radio_chanspec));
+
+		if (freq < 5150) {
+
+			paa_boost_tune = 0xa;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xf;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5340) {
+
+			paa_boost_tune = 0x8;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xfb;
+			mixa_boost_tune = 0xf;
+		} else if (freq < 5650) {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			pgaa_boost_tune = 0xb;
+			mixa_boost_tune = 0xf;
+		} else {
+
+			paa_boost_tune = 0x0;
+			pada_boost_tune = 0x77;
+			if (freq != 5825) {
+				pgaa_boost_tune = -(int)(freq - 18) / 36 + 168;
+			} else {
+				pgaa_boost_tune = 6;
+			}
+			mixa_boost_tune = 0xf;
+		}
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_BOOST_TUNE, paa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_BOOST_TUNE, pada_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PGAA_BOOST_TUNE, pgaa_boost_tune);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 MIXA_BOOST_TUNE, mixa_boost_tune);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 TXSPARE1, 0x30);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PA_SPARE2, 0xee);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 PADA_CASCBIAS, 0x3);
+
+			cascbias = 0x30;
+
+			if ((pi->sh->chip == BCM43224_CHIP_ID) ||
+			    (pi->sh->chip == BCM43225_CHIP_ID) ||
+			    (pi->sh->chip == BCM43421_CHIP_ID)) {
+				if (pi->sh->chippkg == BCM43224_FAB_SMIC) {
+					cascbias = 0x35;
+				}
+			}
+
+			pabias = (pi->phy_pabias == 0) ? 0x30 : pi->phy_pabias;
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IAUX_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_IMAIN_STAT, pabias);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_CASCBIAS, cascbias);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+void wlc_phy_radio205x_vcocal_nphy(phy_info_t *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04, 0x0);
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_CAL_RESETN, 0x04,
+			      (1 << 2));
+		mod_radio_reg(pi, RADIO_2057_RFPLL_MISC_EN, 0x01, 0x01);
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_VCOCAL12, 0x0);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x18);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x38);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST3, 0x39);
+	}
+
+	udelay(300);
+}
+
+#define MAX_205x_RCAL_WAITLOOPS 10000
+
+static u16 wlc_phy_radio205x_rcal(phy_info_t *pi)
+{
+	u16 rcal_reg = 0;
+	int i;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (pi->pubpi.radiorev == 5) {
+
+			and_phy_reg(pi, 0x342, ~(0x1 << 1));
+
+			udelay(10);
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x1);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x1);
+		}
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x1);
+
+		udelay(10);
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x3, 0x3);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS);
+			if (rcal_reg & 0x1) {
+				break;
+			}
+			udelay(100);
+		}
+
+		ASSERT(i < MAX_205x_RCAL_WAITLOOPS);
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x2, 0x0);
+
+		rcal_reg = read_radio_reg(pi, RADIO_2057_RCAL_STATUS) & 0x3e;
+
+		mod_radio_reg(pi, RADIO_2057_RCAL_CONFIG, 0x1, 0x0);
+		if (pi->pubpi.radiorev == 5) {
+
+			mod_radio_reg(pi, RADIO_2057_IQTEST_SEL_PU, 0x1, 0x0);
+			mod_radio_reg(pi, RADIO_2057v7_IQTEST_SEL_PU2, 0x2,
+				      0x0);
+		}
+
+		if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+			mod_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x3c,
+				      rcal_reg);
+			mod_radio_reg(pi, RADIO_2057_BANDGAP_RCAL_TRIM, 0xf0,
+				      rcal_reg << 2);
+		}
+
+	} else if (NREV_IS(pi->pubpi.phy_rev, 3)) {
+		u16 savereg;
+
+		savereg =
+		    read_radio_reg(pi,
+				   RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN);
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg | 0x7);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+		udelay(10);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x9);
+
+		for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+			rcal_reg = read_radio_reg(pi,
+						  RADIO_2056_SYN_RCAL_CODE_OUT |
+						  RADIO_2056_SYN);
+			if (rcal_reg & 0x80) {
+				break;
+			}
+			udelay(100);
+		}
+
+		ASSERT(i < MAX_205x_RCAL_WAITLOOPS);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x1);
+
+		rcal_reg =
+		    read_radio_reg(pi,
+				   RADIO_2056_SYN_RCAL_CODE_OUT |
+				   RADIO_2056_SYN);
+
+		write_radio_reg(pi, RADIO_2056_SYN_RCAL_MASTER | RADIO_2056_SYN,
+				0x0);
+
+		write_radio_reg(pi, RADIO_2056_SYN_PLL_MAST2 | RADIO_2056_SYN,
+				savereg);
+
+		return rcal_reg & 0x1f;
+	}
+	return rcal_reg & 0x3e;
+}
+
+static void
+wlc_phy_chanspec_radio2057_setup(phy_info_t *pi,
+				 const chan_info_nphy_radio2057_t *ci,
+				 const chan_info_nphy_radio2057_rev5_t *ci2)
+{
+	int coreNum;
+	u16 txmix2g_tune_boost_pu = 0;
+	u16 pad2g_tune_pus = 0;
+
+	if (pi->pubpi.radiorev == 5) {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci2->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci2->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci2->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci2->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci2->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci2->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC,
+				ci2->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci2->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci2->RF_rfpll_mmd1);
+		write_radio_reg(pi,
+				RADIO_2057_VCOBUF_TUNE, ci2->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci2->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci2->RF_logen_indbuf2g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci2->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci2->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci2->RF_lna2g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci2->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci2->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci2->RF_lna2g_tune_core1);
+
+	} else {
+
+		write_radio_reg(pi,
+				RADIO_2057_VCOCAL_COUNTVAL0,
+				ci->RF_vcocal_countval0);
+		write_radio_reg(pi, RADIO_2057_VCOCAL_COUNTVAL1,
+				ci->RF_vcocal_countval1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_REFMASTER_SPAREXTALSIZE,
+				ci->RF_rfpll_refmaster_sparextalsize);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+				ci->RF_rfpll_loopfilter_r1);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+				ci->RF_rfpll_loopfilter_c2);
+		write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+				ci->RF_rfpll_loopfilter_c1);
+		write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, ci->RF_cp_kpd_idac);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD0, ci->RF_rfpll_mmd0);
+		write_radio_reg(pi, RADIO_2057_RFPLL_MMD1, ci->RF_rfpll_mmd1);
+		write_radio_reg(pi, RADIO_2057_VCOBUF_TUNE, ci->RF_vcobuf_tune);
+		write_radio_reg(pi,
+				RADIO_2057_LOGEN_MX2G_TUNE,
+				ci->RF_logen_mx2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_MX5G_TUNE,
+				ci->RF_logen_mx5g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF2G_TUNE,
+				ci->RF_logen_indbuf2g_tune);
+		write_radio_reg(pi, RADIO_2057_LOGEN_INDBUF5G_TUNE,
+				ci->RF_logen_indbuf5g_tune);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE0,
+				ci->RF_txmix2g_tune_boost_pu_core0);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+				ci->RF_pad2g_tune_pus_core0);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE0,
+				ci->RF_pga_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE0,
+				ci->RF_txmix5g_boost_tune_core0);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE0,
+				ci->RF_pad5g_tune_misc_pus_core0);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE0,
+				ci->RF_lna2g_tune_core0);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE0,
+				ci->RF_lna5g_tune_core0);
+
+		write_radio_reg(pi,
+				RADIO_2057_TXMIX2G_TUNE_BOOST_PU_CORE1,
+				ci->RF_txmix2g_tune_boost_pu_core1);
+		write_radio_reg(pi,
+				RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+				ci->RF_pad2g_tune_pus_core1);
+		write_radio_reg(pi, RADIO_2057_PGA_BOOST_TUNE_CORE1,
+				ci->RF_pga_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_TXMIX5G_BOOST_TUNE_CORE1,
+				ci->RF_txmix5g_boost_tune_core1);
+		write_radio_reg(pi, RADIO_2057_PAD5G_TUNE_MISC_PUS_CORE1,
+				ci->RF_pad5g_tune_misc_pus_core1);
+		write_radio_reg(pi, RADIO_2057_LNA2G_TUNE_CORE1,
+				ci->RF_lna2g_tune_core1);
+		write_radio_reg(pi, RADIO_2057_LNA5G_TUNE_CORE1,
+				ci->RF_lna5g_tune_core1);
+	}
+
+	if ((pi->pubpi.radiorev <= 4) || (pi->pubpi.radiorev == 6)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x3f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+	} else if ((pi->pubpi.radiorev == 5) || (pi->pubpi.radiorev == 7) ||
+		   (pi->pubpi.radiorev == 8)) {
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1b);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x30);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0xa);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0xa);
+		} else {
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_R1,
+					0x1f);
+			write_radio_reg(pi, RADIO_2057_CP_KPD_IDAC, 0x3f);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C1,
+					0x8);
+			write_radio_reg(pi, RADIO_2057_RFPLL_LOOPFILTER_C2,
+					0x8);
+		}
+
+	}
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (PHY_IPA(pi)) {
+			if (pi->pubpi.radiorev == 3) {
+				txmix2g_tune_boost_pu = 0x6b;
+			}
+
+			if (pi->pubpi.radiorev == 5)
+				pad2g_tune_pus = 0x73;
+
+		} else {
+			if (pi->pubpi.radiorev != 5) {
+				pad2g_tune_pus = 0x3;
+
+				txmix2g_tune_boost_pu = 0x61;
+			}
+		}
+
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			if (txmix2g_tune_boost_pu != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 TXMIX2G_TUNE_BOOST_PU,
+						 txmix2g_tune_boost_pu);
+
+			if (pad2g_tune_pus != 0)
+				WRITE_RADIO_REG4(pi, RADIO_2057, CORE, coreNum,
+						 PAD2G_TUNE_PUS,
+						 pad2g_tune_pus);
+		}
+	}
+
+	udelay(50);
+
+	wlc_phy_radio205x_vcocal_nphy(pi);
+}
+
+static u16 wlc_phy_radio2057_rccal(phy_info_t *pi)
+{
+	u16 rccal_valid;
+	int i;
+	bool chip43226_6362A0;
+
+	chip43226_6362A0 = ((pi->pubpi.radiorev == 3)
+			    || (pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6));
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x61);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xc0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x61);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xe9);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	ASSERT(rccal_valid & 0x2);
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x69);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x69);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xd5);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	ASSERT(rccal_valid & 0x2);
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	rccal_valid = 0;
+	if (chip43226_6362A0) {
+		write_radio_reg(pi, RADIO_2057_RCCAL_MASTER, 0x73);
+
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x28);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0xb0);
+	} else {
+		write_radio_reg(pi, RADIO_2057v7_RCCAL_MASTER, 0x73);
+		write_radio_reg(pi, RADIO_2057_RCCAL_X1, 0x6e);
+		write_radio_reg(pi, RADIO_2057_RCCAL_TRC0, 0x99);
+	}
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x55);
+
+	for (i = 0; i < MAX_205x_RCAL_WAITLOOPS; i++) {
+		rccal_valid = read_radio_reg(pi, RADIO_2057_RCCAL_DONE_OSCCAP);
+		if (rccal_valid & 0x2) {
+			break;
+		}
+		udelay(500);
+	}
+
+	ASSERT(rccal_valid & 0x2);
+
+	write_radio_reg(pi, RADIO_2057_RCCAL_START_R1_Q1_P1, 0x15);
+
+	return rccal_valid;
+}
+
+static void
+wlc_phy_adjust_rx_analpfbw_nphy(phy_info_t *pi, u16 reduction_factr)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						((pi->nphy_rccal_value +
+						  reduction_factr) | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_anarxlpf_adjusted) {
+				write_radio_reg(pi,
+						(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+						 RADIO_2056_RX0),
+						(pi->nphy_rccal_value | 0x80));
+
+				pi->nphy_anarxlpf_adjusted = false;
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_adjust_min_noisevar_nphy(phy_info_t *pi, int ntones, int *tone_id_buf,
+				 u32 *noise_var_buf)
+{
+	int i;
+	u32 offset;
+	int tone_id;
+	int tbllen =
+	    CHSPEC_IS40(pi->
+			radio_chanspec) ? NPHY_NOISEVAR_TBLLEN40 :
+	    NPHY_NOISEVAR_TBLLEN20;
+
+	if (pi->nphy_noisevars_adjusted) {
+		for (i = 0; i < pi->nphy_saved_noisevars.bufcount; i++) {
+			tone_id = pi->nphy_saved_noisevars.tone_id[i];
+			offset = (tone_id >= 0) ?
+			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32,
+						 (void *)&pi->
+						 nphy_saved_noisevars.
+						 min_noise_vars[i]);
+		}
+
+		pi->nphy_saved_noisevars.bufcount = 0;
+		pi->nphy_noisevars_adjusted = false;
+	}
+
+	if ((noise_var_buf != NULL) && (tone_id_buf != NULL)) {
+		pi->nphy_saved_noisevars.bufcount = 0;
+
+		for (i = 0; i < ntones; i++) {
+			tone_id = tone_id_buf[i];
+			offset = (tone_id >= 0) ?
+			    ((tone_id * 2) + 1) : (tbllen + (tone_id * 2) + 1);
+			pi->nphy_saved_noisevars.tone_id[i] = tone_id;
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						offset, 32,
+						&pi->nphy_saved_noisevars.
+						min_noise_vars[i]);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_NOISEVAR, 1,
+						 offset, 32,
+						 (void *)&noise_var_buf[i]);
+			pi->nphy_saved_noisevars.bufcount++;
+		}
+
+		pi->nphy_noisevars_adjusted = true;
+	}
+}
+
+static void wlc_phy_adjust_crsminpwr_nphy(phy_info_t *pi, u8 minpwr)
+{
+	u16 regval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if ((CHSPEC_CHANNEL(pi->radio_chanspec) == 11) &&
+		    CHSPEC_IS40(pi->radio_chanspec)) {
+			if (!pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				pi->nphy_crsminpwr[0] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				pi->nphy_crsminpwr[1] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				pi->nphy_crsminpwr[2] = regval & 0xff;
+				regval &= 0xff00;
+				regval |= (u16) minpwr;
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = true;
+			}
+		} else {
+			if (pi->nphy_crsminpwr_adjusted) {
+				regval = read_phy_reg(pi, 0x27d);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[0];
+				write_phy_reg(pi, 0x27d, regval);
+
+				regval = read_phy_reg(pi, 0x280);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[1];
+				write_phy_reg(pi, 0x280, regval);
+
+				regval = read_phy_reg(pi, 0x283);
+				regval &= 0xff00;
+				regval |= pi->nphy_crsminpwr[2];
+				write_phy_reg(pi, 0x283, regval);
+
+				pi->nphy_crsminpwr_adjusted = false;
+			}
+		}
+	}
+}
+
+static void wlc_phy_txlpfbw_nphy(phy_info_t *pi)
+{
+	u8 tx_lpf_bw = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			tx_lpf_bw = 3;
+		} else {
+			tx_lpf_bw = 1;
+		}
+
+		if (PHY_IPA(pi)) {
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				tx_lpf_bw = 5;
+			} else {
+				tx_lpf_bw = 4;
+			}
+		}
+		write_phy_reg(pi, 0xe8,
+			      (tx_lpf_bw << 0) |
+			      (tx_lpf_bw << 3) |
+			      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+
+		if (PHY_IPA(pi)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				tx_lpf_bw = 4;
+			} else {
+				tx_lpf_bw = 1;
+			}
+
+			write_phy_reg(pi, 0xe9,
+				      (tx_lpf_bw << 0) |
+				      (tx_lpf_bw << 3) |
+				      (tx_lpf_bw << 6) | (tx_lpf_bw << 9));
+		}
+	}
+}
+
+static void wlc_phy_spurwar_nphy(phy_info_t *pi)
+{
+	u16 cur_channel = 0;
+	int nphy_adj_tone_id_buf[] = { 57, 58 };
+	u32 nphy_adj_noise_var_buf[] = { 0x3ff, 0x3ff };
+	bool isAdjustNoiseVar = false;
+	uint numTonesAdjust = 0;
+	u32 tempval = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		cur_channel = CHSPEC_CHANNEL(pi->radio_chanspec);
+
+		if (pi->nphy_gband_spurwar_en) {
+
+			wlc_phy_adjust_rx_analpfbw_nphy(pi,
+							NPHY_ANARXLPFBW_REDUCTIONFACT);
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				if ((cur_channel == 11)
+				    && CHSPEC_IS40(pi->radio_chanspec)) {
+
+					wlc_phy_adjust_min_noisevar_nphy(pi, 2,
+									 nphy_adj_tone_id_buf,
+									 nphy_adj_noise_var_buf);
+				} else {
+
+					wlc_phy_adjust_min_noisevar_nphy(pi, 0,
+									 NULL,
+									 NULL);
+				}
+			}
+			wlc_phy_adjust_crsminpwr_nphy(pi,
+						      NPHY_ADJUSTED_MINCRSPOWER);
+		}
+
+		if ((pi->nphy_gband_spurwar2_en)
+		    && CHSPEC_IS2G(pi->radio_chanspec)) {
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				switch (cur_channel) {
+				case 3:
+					nphy_adj_tone_id_buf[0] = 57;
+					nphy_adj_tone_id_buf[1] = 58;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 4:
+					nphy_adj_tone_id_buf[0] = 41;
+					nphy_adj_tone_id_buf[1] = 42;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 5:
+					nphy_adj_tone_id_buf[0] = 25;
+					nphy_adj_tone_id_buf[1] = 26;
+					nphy_adj_noise_var_buf[0] = 0x24f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 6:
+					nphy_adj_tone_id_buf[0] = 9;
+					nphy_adj_tone_id_buf[1] = 10;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 7:
+					nphy_adj_tone_id_buf[0] = 121;
+					nphy_adj_tone_id_buf[1] = 122;
+					nphy_adj_noise_var_buf[0] = 0x18f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 8:
+					nphy_adj_tone_id_buf[0] = 105;
+					nphy_adj_tone_id_buf[1] = 106;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x25f;
+					isAdjustNoiseVar = true;
+					break;
+				case 9:
+					nphy_adj_tone_id_buf[0] = 89;
+					nphy_adj_tone_id_buf[1] = 90;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				case 10:
+					nphy_adj_tone_id_buf[0] = 73;
+					nphy_adj_tone_id_buf[1] = 74;
+					nphy_adj_noise_var_buf[0] = 0x22f;
+					nphy_adj_noise_var_buf[1] = 0x24f;
+					isAdjustNoiseVar = true;
+					break;
+				default:
+					isAdjustNoiseVar = false;
+					break;
+				}
+			}
+
+			if (isAdjustNoiseVar) {
+				numTonesAdjust = sizeof(nphy_adj_tone_id_buf) /
+				    sizeof(nphy_adj_tone_id_buf[0]);
+
+				wlc_phy_adjust_min_noisevar_nphy(pi,
+								 numTonesAdjust,
+								 nphy_adj_tone_id_buf,
+								 nphy_adj_noise_var_buf);
+
+				tempval = 0;
+
+			} else {
+
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if ((pi->nphy_aband_spurwar_en) &&
+		    (CHSPEC_IS5G(pi->radio_chanspec))) {
+			switch (cur_channel) {
+			case 54:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x25f;
+				break;
+			case 38:
+			case 102:
+			case 118:
+				if ((pi->sh->chip == BCM4716_CHIP_ID) &&
+				    (pi->sh->chippkg == BCM4717_PKG_ID)) {
+					nphy_adj_tone_id_buf[0] = 32;
+					nphy_adj_noise_var_buf[0] = 0x21f;
+				} else {
+					nphy_adj_tone_id_buf[0] = 0;
+					nphy_adj_noise_var_buf[0] = 0x0;
+				}
+				break;
+			case 134:
+				nphy_adj_tone_id_buf[0] = 32;
+				nphy_adj_noise_var_buf[0] = 0x21f;
+				break;
+			case 151:
+				nphy_adj_tone_id_buf[0] = 16;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			case 153:
+			case 161:
+				nphy_adj_tone_id_buf[0] = 48;
+				nphy_adj_noise_var_buf[0] = 0x23f;
+				break;
+			default:
+				nphy_adj_tone_id_buf[0] = 0;
+				nphy_adj_noise_var_buf[0] = 0x0;
+				break;
+			}
+
+			if (nphy_adj_tone_id_buf[0]
+			    && nphy_adj_noise_var_buf[0]) {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 1,
+								 nphy_adj_tone_id_buf,
+								 nphy_adj_noise_var_buf);
+			} else {
+				wlc_phy_adjust_min_noisevar_nphy(pi, 0, NULL,
+								 NULL);
+			}
+		}
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+	}
+}
+
+static void
+wlc_phy_chanspec_nphy_setup(phy_info_t *pi, chanspec_t chanspec,
+			    const nphy_sfo_cfg_t *ci)
+{
+	u16 val;
+
+	val = read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand;
+	if (CHSPEC_IS5G(chanspec) && !val) {
+
+		val = R_REG(&pi->regs->psm_phy_hdr_param);
+		W_REG(&pi->regs->psm_phy_hdr_param,
+		      (val | MAC_PHY_FORCE_CLK));
+
+		or_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			   (BBCFG_RESETCCA | BBCFG_RESETRX));
+
+		W_REG(&pi->regs->psm_phy_hdr_param, val);
+
+		or_phy_reg(pi, 0x09, NPHY_BandControl_currentBand);
+	} else if (!CHSPEC_IS5G(chanspec) && val) {
+
+		and_phy_reg(pi, 0x09, ~NPHY_BandControl_currentBand);
+
+		val = R_REG(&pi->regs->psm_phy_hdr_param);
+		W_REG(&pi->regs->psm_phy_hdr_param,
+		      (val | MAC_PHY_FORCE_CLK));
+
+		and_phy_reg(pi, (NPHY_TO_BPHY_OFF + BPHY_BB_CONFIG),
+			    (u16) (~(BBCFG_RESETCCA | BBCFG_RESETRX)));
+
+		W_REG(&pi->regs->psm_phy_hdr_param, val);
+	}
+
+	write_phy_reg(pi, 0x1ce, ci->PHY_BW1a);
+	write_phy_reg(pi, 0x1cf, ci->PHY_BW2);
+	write_phy_reg(pi, 0x1d0, ci->PHY_BW3);
+
+	write_phy_reg(pi, 0x1d1, ci->PHY_BW4);
+	write_phy_reg(pi, 0x1d2, ci->PHY_BW5);
+	write_phy_reg(pi, 0x1d3, ci->PHY_BW6);
+
+	if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en, 0);
+
+		or_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, 0x800);
+	} else {
+		wlc_phy_classifier_nphy(pi, NPHY_ClassifierCtrl_ofdm_en,
+					NPHY_ClassifierCtrl_ofdm_en);
+
+		if (CHSPEC_IS2G(chanspec))
+			and_phy_reg(pi, NPHY_TO_BPHY_OFF + BPHY_TEST, ~0x840);
+	}
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		wlc_phy_txpwr_fixpower_nphy(pi);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+		wlc_phy_adjust_lnagaintbl_nphy(pi);
+	}
+
+	wlc_phy_txlpfbw_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)
+	    && (pi->phy_spuravoid != SPURAVOID_DISABLE)) {
+		u8 spuravoid = 0;
+
+		val = CHSPEC_CHANNEL(chanspec);
+		if (!CHSPEC_IS40(pi->radio_chanspec)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if ((val == 13) || (val == 14) || (val == 153)) {
+					spuravoid = 1;
+				}
+			} else {
+
+				if (((val >= 5) && (val <= 8)) || (val == 13)
+				    || (val == 14)) {
+					spuravoid = 1;
+				}
+			}
+		} else {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				if (val == 54) {
+					spuravoid = 1;
+				}
+			} else {
+
+				if (pi->nphy_aband_spurwar_en &&
+				    ((val == 38) || (val == 102)
+				     || (val == 118))) {
+					if ((pi->sh->chip ==
+					     BCM4716_CHIP_ID)
+					    && (pi->sh->chippkg ==
+						BCM4717_PKG_ID)) {
+						spuravoid = 0;
+					} else {
+						spuravoid = 1;
+					}
+				}
+			}
+		}
+
+		if (pi->phy_spuravoid == SPURAVOID_FORCEON)
+			spuravoid = 1;
+
+		if ((pi->sh->chip == BCM4716_CHIP_ID) ||
+		    (pi->sh->chip == BCM47162_CHIP_ID)) {
+			si_pmu_spuravoid(pi->sh->sih, spuravoid);
+		} else {
+			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, false);
+			si_pmu_spuravoid(pi->sh->sih, spuravoid);
+			wlapi_bmac_core_phypll_ctl(pi->sh->physhim, true);
+		}
+
+		if ((pi->sh->chip == BCM43224_CHIP_ID) ||
+		    (pi->sh->chip == BCM43225_CHIP_ID) ||
+		    (pi->sh->chip == BCM43421_CHIP_ID)) {
+
+			if (spuravoid == 1) {
+
+				W_REG(&pi->regs->tsf_clk_frac_l,
+				      0x5341);
+				W_REG(&pi->regs->tsf_clk_frac_h,
+				      0x8);
+			} else {
+
+				W_REG(&pi->regs->tsf_clk_frac_l,
+				      0x8889);
+				W_REG(&pi->regs->tsf_clk_frac_h,
+				      0x8);
+			}
+		}
+
+		if (!((pi->sh->chip == BCM4716_CHIP_ID) ||
+		      (pi->sh->chip == BCM47162_CHIP_ID))) {
+			wlapi_bmac_core_phypll_reset(pi->sh->physhim);
+		}
+
+		mod_phy_reg(pi, 0x01, (0x1 << 15),
+			    ((spuravoid > 0) ? (0x1 << 15) : 0));
+
+		wlc_phy_resetcca_nphy(pi);
+
+		pi->phy_isspuravoid = (spuravoid > 0);
+	}
+
+	if (NREV_LT(pi->pubpi.phy_rev, 7))
+		write_phy_reg(pi, 0x17e, 0x3830);
+
+	wlc_phy_spurwar_nphy(pi);
+}
+
+void wlc_phy_chanspec_set_nphy(phy_info_t *pi, chanspec_t chanspec)
+{
+	int freq;
+	chan_info_nphy_radio2057_t *t0 = NULL;
+	chan_info_nphy_radio205x_t *t1 = NULL;
+	chan_info_nphy_radio2057_rev5_t *t2 = NULL;
+	chan_info_nphy_2055_t *t3 = NULL;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		return;
+	}
+
+	if (!wlc_phy_chan2freq_nphy
+	    (pi, CHSPEC_CHANNEL(chanspec), &freq, &t0, &t1, &t2, &t3))
+		return;
+
+	wlc_phy_chanspec_radio_set((wlc_phy_t *) pi, chanspec);
+
+	if (CHSPEC_BW(chanspec) != pi->bw)
+		wlapi_bmac_bw_set(pi->sh->physhim, CHSPEC_BW(chanspec));
+
+	if (CHSPEC_IS40(chanspec)) {
+		if (CHSPEC_SB_UPPER(chanspec)) {
+			or_phy_reg(pi, 0xa0, BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				or_phy_reg(pi, 0x310, PRIM_SEL_UP20);
+			}
+		} else {
+			and_phy_reg(pi, 0xa0, ~BPHY_BAND_SEL_UP20);
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				and_phy_reg(pi, 0x310,
+					    (~PRIM_SEL_UP20 & 0xffff));
+			}
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE0,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+				mod_radio_reg(pi, RADIO_2057_TIA_CONFIG_CORE1,
+					      0x2,
+					      (CHSPEC_IS5G(chanspec) ? (1 << 1)
+					       : 0));
+			}
+
+			wlc_phy_chanspec_radio2057_setup(pi, t0, t2);
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+						    (pi->pubpi.radiorev ==
+						     5) ? (const nphy_sfo_cfg_t
+							   *)&(t2->
+							       PHY_BW1a)
+						    : (const nphy_sfo_cfg_t *)
+						    &(t0->PHY_BW1a));
+
+		} else {
+
+			mod_radio_reg(pi,
+				      RADIO_2056_SYN_COM_CTRL | RADIO_2056_SYN,
+				      0x4,
+				      (CHSPEC_IS5G(chanspec) ? (0x1 << 2) : 0));
+			wlc_phy_chanspec_radio2056_setup(pi, t1);
+
+			wlc_phy_chanspec_nphy_setup(pi, chanspec,
+						    (const nphy_sfo_cfg_t *)
+						    &(t1->PHY_BW1a));
+		}
+
+	} else {
+
+		mod_radio_reg(pi, RADIO_2055_MASTER_CNTRL1, 0x70,
+			      (CHSPEC_IS5G(chanspec) ? (0x02 << 4)
+			       : (0x05 << 4)));
+
+		wlc_phy_chanspec_radio2055_setup(pi, t3);
+		wlc_phy_chanspec_nphy_setup(pi, chanspec,
+					    (const nphy_sfo_cfg_t *)&(t3->
+								      PHY_BW1a));
+	}
+
+}
+
+static void wlc_phy_savecal_nphy(phy_info_t *pi)
+{
+	void *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_2G[4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_2G[6] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_2G[7] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_2G[0] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[1] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_2G[2] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_2G[3] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_2G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+	} else {
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 0,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_FINE_Q |
+					   RADIO_2056_TX1);
+
+			pi->calibration_cache.txcal_radio_regs_5G[4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX0);
+			pi->calibration_cache.txcal_radio_regs_5G[6] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_I |
+					   RADIO_2056_TX1);
+			pi->calibration_cache.txcal_radio_regs_5G[7] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_LOFT_COARSE_Q |
+					   RADIO_2056_TX1);
+		} else {
+			pi->calibration_cache.txcal_radio_regs_5G[0] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[1] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL);
+			pi->calibration_cache.txcal_radio_regs_5G[2] =
+			    read_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM);
+			pi->calibration_cache.txcal_radio_regs_5G[3] =
+			    read_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM);
+		}
+
+		pi->nphy_iqcal_chanspec_5G = pi->radio_chanspec;
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			txcal_radio_regs[2 * coreNum] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_FINE_I);
+			txcal_radio_regs[2 * coreNum + 1] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_FINE_Q);
+
+			txcal_radio_regs[2 * coreNum + 4] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_COARSE_I);
+			txcal_radio_regs[2 * coreNum + 5] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					    LOFT_COARSE_Q);
+		}
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 8, 80, 16, tbl_ptr);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_restorecal_nphy(phy_info_t *pi)
+{
+	u16 *loft_comp;
+	u16 txcal_coeffs_bphy[4];
+	u16 *tbl_ptr;
+	int coreNum;
+	u16 *txcal_radio_regs = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_iqcal_chanspec_2G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_2G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_2G[5];
+	} else {
+		if (pi->nphy_iqcal_chanspec_5G == 0)
+			return;
+
+		tbl_ptr = pi->calibration_cache.txcal_coeffs_5G;
+		loft_comp = &pi->calibration_cache.txcal_coeffs_5G[5];
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80, 16,
+				 (void *)tbl_ptr);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		txcal_coeffs_bphy[0] = tbl_ptr[0];
+		txcal_coeffs_bphy[1] = tbl_ptr[1];
+		txcal_coeffs_bphy[2] = tbl_ptr[2];
+		txcal_coeffs_bphy[3] = tbl_ptr[3];
+	} else {
+		txcal_coeffs_bphy[0] = 0;
+		txcal_coeffs_bphy[1] = 0;
+		txcal_coeffs_bphy[2] = 0;
+		txcal_coeffs_bphy[3] = 0;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88, 16,
+				 txcal_coeffs_bphy);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85, 16, loft_comp);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93, 16, loft_comp);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2))
+		wlc_phy_tx_iq_war_nphy(pi);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_2G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_2G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_2G);
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			txcal_radio_regs =
+			    pi->calibration_cache.txcal_radio_regs_5G;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_FINE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[4]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX0,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[5]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_I |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[6]);
+			write_radio_reg(pi,
+					RADIO_2056_TX_LOFT_COARSE_Q |
+					RADIO_2056_TX1,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[7]);
+		} else {
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[0]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_VOS_CNCL,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[1]);
+			write_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[2]);
+			write_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM,
+					pi->calibration_cache.
+					txcal_radio_regs_5G[3]);
+		}
+
+		wlc_phy_rx_iq_coeffs_nphy(pi, 1,
+					  &pi->calibration_cache.
+					  rxcal_coeffs_5G);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (coreNum = 0; coreNum <= 1; coreNum++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_I,
+					 txcal_radio_regs[2 * coreNum]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_FINE_Q,
+					 txcal_radio_regs[2 * coreNum + 1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_I,
+					 txcal_radio_regs[2 * coreNum + 4]);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, coreNum,
+					 LOFT_COARSE_Q,
+					 txcal_radio_regs[2 * coreNum + 5]);
+		}
+	}
+}
+
+void wlc_phy_antsel_init(wlc_phy_t *ppi, bool lut_init)
+{
+	phy_info_t *pi = (phy_info_t *) ppi;
+	u16 mask = 0xfc00;
+	u32 mc = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7))
+		return;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		u16 v0 = 0x211, v1 = 0x222, v2 = 0x144, v3 = 0x188;
+
+		if (lut_init == false)
+			return;
+
+		if (pi->srom_fem2g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x02, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x03, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x08, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x0C, 16, &v3);
+		} else {
+			ASSERT(0);
+		}
+
+		if (pi->srom_fem5g.antswctrllut == 0) {
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x12, 16, &v0);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x13, 16, &v1);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x18, 16, &v2);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_ANTSWCTRLLUT,
+						 1, 0x1C, 16, &v3);
+		} else {
+			ASSERT(0);
+		}
+	} else {
+
+		write_phy_reg(pi, 0xc8, 0x0);
+		write_phy_reg(pi, 0xc9, 0x0);
+
+		si_gpiocontrol(pi->sh->sih, mask, mask, GPIO_DRV_PRIORITY);
+
+		mc = R_REG(&pi->regs->maccontrol);
+		mc &= ~MCTL_GPOUT_SEL_MASK;
+		W_REG(&pi->regs->maccontrol, mc);
+
+		OR_REG(&pi->regs->psm_gpio_oe, mask);
+
+		AND_REG(&pi->regs->psm_gpio_out, ~mask);
+
+		if (lut_init) {
+			write_phy_reg(pi, 0xf8, 0x02d8);
+			write_phy_reg(pi, 0xf9, 0x0301);
+			write_phy_reg(pi, 0xfa, 0x02d8);
+			write_phy_reg(pi, 0xfb, 0x0301);
+		}
+	}
+}
+
+u16 wlc_phy_classifier_nphy(phy_info_t *pi, u16 mask, u16 val)
+{
+	u16 curr_ctl, new_ctl;
+	bool suspended = false;
+
+	if (D11REV_IS(pi->sh->corerev, 16)) {
+		suspended =
+		    (R_REG(&pi->regs->maccontrol) & MCTL_EN_MAC) ?
+		    false : true;
+		if (!suspended)
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+	}
+
+	curr_ctl = read_phy_reg(pi, 0xb0) & (0x7 << 0);
+
+	new_ctl = (curr_ctl & (~mask)) | (val & mask);
+
+	mod_phy_reg(pi, 0xb0, (0x7 << 0), new_ctl);
+
+	if (D11REV_IS(pi->sh->corerev, 16) && !suspended)
+		wlapi_enable_mac(pi->sh->physhim);
+
+	return new_ctl;
+}
+
+static void wlc_phy_clip_det_nphy(phy_info_t *pi, u8 write, u16 *vals)
+{
+
+	if (write == 0) {
+		vals[0] = read_phy_reg(pi, 0x2c);
+		vals[1] = read_phy_reg(pi, 0x42);
+	} else {
+		write_phy_reg(pi, 0x2c, vals[0]);
+		write_phy_reg(pi, 0x42, vals[1]);
+	}
+}
+
+void wlc_phy_force_rfseq_nphy(phy_info_t *pi, u8 cmd)
+{
+	u16 trigger_mask, status_mask;
+	u16 orig_RfseqCoreActv;
+
+	switch (cmd) {
+	case NPHY_RFSEQ_RX2TX:
+		trigger_mask = NPHY_RfseqTrigger_rx2tx;
+		status_mask = NPHY_RfseqStatus_rx2tx;
+		break;
+	case NPHY_RFSEQ_TX2RX:
+		trigger_mask = NPHY_RfseqTrigger_tx2rx;
+		status_mask = NPHY_RfseqStatus_tx2rx;
+		break;
+	case NPHY_RFSEQ_RESET2RX:
+		trigger_mask = NPHY_RfseqTrigger_reset2rx;
+		status_mask = NPHY_RfseqStatus_reset2rx;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINH:
+		trigger_mask = NPHY_RfseqTrigger_updategainh;
+		status_mask = NPHY_RfseqStatus_updategainh;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINL:
+		trigger_mask = NPHY_RfseqTrigger_updategainl;
+		status_mask = NPHY_RfseqStatus_updategainl;
+		break;
+	case NPHY_RFSEQ_UPDATEGAINU:
+		trigger_mask = NPHY_RfseqTrigger_updategainu;
+		status_mask = NPHY_RfseqStatus_updategainu;
+		break;
+	default:
+		return;
+	}
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1,
+		   (NPHY_RfseqMode_CoreActv_override |
+		    NPHY_RfseqMode_Trigger_override));
+	or_phy_reg(pi, 0xa3, trigger_mask);
+	SPINWAIT((read_phy_reg(pi, 0xa4) & status_mask), 200000);
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+
+	ASSERT((read_phy_reg(pi, 0xa4) & status_mask) == 0);
+}
+
+static void
+wlc_phy_set_rfseq_nphy(phy_info_t *pi, u8 cmd, u8 *events, u8 *dlys,
+		       u8 len)
+{
+	u32 t1_offset, t2_offset;
+	u8 ctr;
+	u8 end_event =
+	    NREV_GE(pi->pubpi.phy_rev,
+		    3) ? NPHY_REV3_RFSEQ_CMD_END : NPHY_RFSEQ_CMD_END;
+	u8 end_dly = 1;
+
+	ASSERT(len <= 16);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	t1_offset = cmd << 4;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t1_offset, 8,
+				 events);
+	t2_offset = t1_offset + 0x080;
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, len, t2_offset, 8,
+				 dlys);
+
+	for (ctr = len; ctr < 16; ctr++) {
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t1_offset + ctr, 8, &end_event);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+					 t2_offset + ctr, 8, &end_dly);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static u16 wlc_phy_read_lpf_bw_ctl_nphy(phy_info_t *pi, u16 offset)
+{
+	u16 lpf_bw_ctl_val = 0;
+	u16 rx2tx_lpf_rc_lut_offset = 0;
+
+	if (offset == 0) {
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			rx2tx_lpf_rc_lut_offset = 0x159;
+		} else {
+			rx2tx_lpf_rc_lut_offset = 0x154;
+		}
+	} else {
+		rx2tx_lpf_rc_lut_offset = offset;
+	}
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 1,
+				(u32) rx2tx_lpf_rc_lut_offset, 16,
+				&lpf_bw_ctl_val);
+
+	lpf_bw_ctl_val = lpf_bw_ctl_val & 0x7;
+
+	return lpf_bw_ctl_val;
+}
+
+static void
+wlc_phy_rfctrl_override_nphy_rev7(phy_info_t *pi, u16 field, u16 value,
+				  u8 core_mask, u8 off, u8 override_id)
+{
+	u8 core_num;
+	u16 addr = 0, en_addr = 0, val_addr = 0, en_mask = 0, val_mask = 0;
+	u8 val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+			if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID0) {
+
+				switch (field) {
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 7):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7a :
+					    0x7d;
+					val_mask = (0x1 << 7);
+					val_shift = 7;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0xf8 :
+					    0xfa;
+					val_mask = (0x7 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7b :
+					    0x7e;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 12):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x7c :
+					    0x7f;
+					val_mask = (0xffff << 0);
+					val_shift = 0;
+					break;
+				case (0x3 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+					    0x349;
+					val_mask = (0xff << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 13):
+					en_addr = (core_num == 0) ? 0xe7 : 0xec;
+					val_addr = (core_num == 0) ? 0x348 :
+					    0x349;
+					val_mask = (0xf << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID1) {
+
+				switch (field) {
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 5):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 5);
+					val_shift = 5;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				case (0x1 << 2):
+
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 7):
+
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x7 << 8);
+					val_shift = 8;
+					break;
+				case (0x1 << 11):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 14);
+					val_shift = 14;
+					break;
+				case (0x1 << 10):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 13);
+					val_shift = 13;
+					break;
+				case (0x1 << 9):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 12);
+					val_shift = 12;
+					break;
+				case (0x1 << 8):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 11);
+					val_shift = 11;
+					break;
+				case (0x1 << 6):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 6);
+					val_shift = 6;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x342 :
+					    0x343;
+					val_addr = (core_num == 0) ? 0x340 :
+					    0x341;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			} else if (override_id == NPHY_REV7_RFCTRLOVERRIDE_ID2) {
+
+				switch (field) {
+				case (0x1 << 3):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 3);
+					val_shift = 3;
+					break;
+				case (0x1 << 1):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 1);
+					val_shift = 1;
+					break;
+				case (0x1 << 0):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 0);
+					val_shift = 0;
+					break;
+				case (0x1 << 2):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 2);
+					val_shift = 2;
+					break;
+				case (0x1 << 4):
+					en_addr = (core_num == 0) ? 0x346 :
+					    0x347;
+					val_addr = (core_num == 0) ? 0x344 :
+					    0x345;
+					val_mask = (0x1 << 4);
+					val_shift = 4;
+					break;
+				default:
+					addr = 0xffff;
+					break;
+				}
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff) {
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+					}
+				}
+			}
+		}
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_nphy(phy_info_t *pi, u16 field, u16 value,
+			     u8 core_mask, u8 off)
+{
+	u8 core_num;
+	u16 addr = 0, mask = 0, en_addr = 0, val_addr = 0, en_mask =
+	    0, val_mask = 0;
+	u8 shift = 0, val_shift = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3) && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+		en_mask = field;
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 2):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 1);
+				val_shift = 1;
+				break;
+			case (0x1 << 3):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 2);
+				val_shift = 2;
+				break;
+			case (0x1 << 4):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 4);
+				val_shift = 4;
+				break;
+			case (0x1 << 5):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 5);
+				val_shift = 5;
+				break;
+			case (0x1 << 6):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 7):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x1 << 7);
+				val_shift = 7;
+				break;
+			case (0x1 << 8):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 8);
+				val_shift = 8;
+				break;
+			case (0x1 << 11):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7a : 0x7d;
+				val_mask = (0x7 << 13);
+				val_shift = 13;
+				break;
+
+			case (0x1 << 9):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 0);
+				val_shift = 0;
+				break;
+
+			case (0x1 << 10):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf8 : 0xfa;
+				val_mask = (0x7 << 4);
+				val_shift = 4;
+				break;
+
+			case (0x1 << 12):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7b : 0x7e;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 13):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0x7c : 0x7f;
+				val_mask = (0xffff << 0);
+				val_shift = 0;
+				break;
+			case (0x1 << 14):
+				en_addr = (core_num == 0) ? 0xe7 : 0xec;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x3 << 6);
+				val_shift = 6;
+				break;
+			case (0x1 << 0):
+				en_addr = (core_num == 0) ? 0xe5 : 0xe6;
+				val_addr = (core_num == 0) ? 0xf9 : 0xfb;
+				val_mask = (0x1 << 15);
+				val_shift = 15;
+				break;
+			default:
+				addr = 0xffff;
+				break;
+			}
+
+			if (off) {
+				and_phy_reg(pi, en_addr, ~en_mask);
+				and_phy_reg(pi, val_addr, ~val_mask);
+			} else {
+
+				if ((core_mask == 0)
+				    || (core_mask & (1 << core_num))) {
+					or_phy_reg(pi, en_addr, en_mask);
+
+					if (addr != 0xffff) {
+						mod_phy_reg(pi, val_addr,
+							    val_mask,
+							    (value <<
+							     val_shift));
+					}
+				}
+			}
+		}
+	} else {
+
+		if (off) {
+			and_phy_reg(pi, 0xec, ~field);
+			value = 0x0;
+		} else {
+			or_phy_reg(pi, 0xec, field);
+		}
+
+		for (core_num = 0; core_num < 2; core_num++) {
+
+			switch (field) {
+			case (0x1 << 1):
+			case (0x1 << 9):
+			case (0x1 << 12):
+			case (0x1 << 13):
+			case (0x1 << 14):
+				addr = 0x78;
+
+				core_mask = 0x1;
+				break;
+			case (0x1 << 2):
+			case (0x1 << 3):
+			case (0x1 << 4):
+			case (0x1 << 5):
+			case (0x1 << 6):
+			case (0x1 << 7):
+			case (0x1 << 8):
+				addr = (core_num == 0) ? 0x7a : 0x7d;
+				break;
+			case (0x1 << 10):
+				addr = (core_num == 0) ? 0x7b : 0x7e;
+				break;
+			case (0x1 << 11):
+				addr = (core_num == 0) ? 0x7c : 0x7f;
+				break;
+			default:
+				addr = 0xffff;
+			}
+
+			switch (field) {
+			case (0x1 << 1):
+				mask = (0x7 << 3);
+				shift = 3;
+				break;
+			case (0x1 << 9):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 12):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 13):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 14):
+				mask = (0xf << 12);
+				shift = 12;
+				break;
+			case (0x1 << 2):
+				mask = (0x1 << 0);
+				shift = 0;
+				break;
+			case (0x1 << 3):
+				mask = (0x1 << 1);
+				shift = 1;
+				break;
+			case (0x1 << 4):
+				mask = (0x1 << 2);
+				shift = 2;
+				break;
+			case (0x1 << 5):
+				mask = (0x3 << 4);
+				shift = 4;
+				break;
+			case (0x1 << 6):
+				mask = (0x3 << 6);
+				shift = 6;
+				break;
+			case (0x1 << 7):
+				mask = (0x1 << 8);
+				shift = 8;
+				break;
+			case (0x1 << 8):
+				mask = (0x1 << 9);
+				shift = 9;
+				break;
+			case (0x1 << 10):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			case (0x1 << 11):
+				mask = 0x1fff;
+				shift = 0x0;
+				break;
+			default:
+				mask = 0x0;
+				shift = 0x0;
+				break;
+			}
+
+			if ((addr != 0xffff) && (core_mask & (1 << core_num))) {
+				mod_phy_reg(pi, addr, mask, (value << shift));
+			}
+		}
+
+		or_phy_reg(pi, 0xec, (0x1 << 0));
+		or_phy_reg(pi, 0x78, (0x1 << 0));
+		udelay(1);
+		and_phy_reg(pi, 0xec, ~(0x1 << 0));
+	}
+}
+
+static void
+wlc_phy_rfctrl_override_1tomany_nphy(phy_info_t *pi, u16 cmd, u16 value,
+				     u8 core_mask, u8 off)
+{
+	u16 rfmxgain = 0, lpfgain = 0;
+	u16 tgain = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		switch (cmd) {
+		case NPHY_REV7_RfctrlOverride_cmd_rxrf_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_tx_pu:
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  value, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), value,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1,
+							  core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_rxgain:
+			rfmxgain = value & 0x000ff;
+			lpfgain = value & 0x0ff00;
+			lpfgain = lpfgain >> 8;
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+							  rfmxgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x3 << 13),
+							  lpfgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		case NPHY_REV7_RfctrlOverride_cmd_txgain:
+			tgain = value & 0x7fff;
+			lpfgain = value & 0x8000;
+			lpfgain = lpfgain >> 14;
+
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12),
+							  tgain, core_mask, off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 13),
+							  lpfgain, core_mask,
+							  off,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			break;
+		}
+	}
+}
+
+static void
+wlc_phy_scale_offset_rssi_nphy(phy_info_t *pi, u16 scale, s8 offset,
+			       u8 coresel, u8 rail, u8 rssi_type)
+{
+	u16 valuetostuff;
+
+	offset = (offset > NPHY_RSSICAL_MAXREAD) ?
+	    NPHY_RSSICAL_MAXREAD : offset;
+	offset = (offset < (-NPHY_RSSICAL_MAXREAD - 1)) ?
+	    -NPHY_RSSICAL_MAXREAD - 1 : offset;
+
+	valuetostuff = ((scale & 0x3f) << 8) | (offset & 0x3f);
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1a6, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1ac, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1b2, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_NB)) {
+		write_phy_reg(pi, 0x1b8, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1a4, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1aa, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1b0, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W1)) {
+		write_phy_reg(pi, 0x1b6, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1a5, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1ab, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1b1, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_W2)) {
+		write_phy_reg(pi, 0x1b7, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1a7, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1ad, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1b3, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_TBD)) {
+		write_phy_reg(pi, 0x1b9, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1a8, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1ae, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_I) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1b4, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rail == NPHY_RAIL_Q) && (rssi_type == NPHY_RSSI_SEL_IQ)) {
+		write_phy_reg(pi, 0x1ba, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+		write_phy_reg(pi, 0x1a9, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_2G)) {
+		write_phy_reg(pi, 0x1b5, valuetostuff);
+	}
+
+	if (((coresel == RADIO_MIMO_CORESEL_CORE1) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+		write_phy_reg(pi, 0x1af, valuetostuff);
+	}
+	if (((coresel == RADIO_MIMO_CORESEL_CORE2) ||
+	     (coresel == RADIO_MIMO_CORESEL_ALLRX)) &&
+	    (rssi_type == NPHY_RSSI_SEL_TSSI_5G)) {
+		write_phy_reg(pi, 0x1bb, valuetostuff);
+	}
+}
+
+void wlc_phy_rssisel_nphy(phy_info_t *pi, u8 core_code, u8 rssi_type)
+{
+	u16 mask, val;
+	u16 afectrlovr_rssi_val, rfctrlcmd_rxen_val, rfctrlcmd_coresel_val,
+	    startseq;
+	u16 rfctrlovr_rssi_val, rfctrlovr_rxen_val, rfctrlovr_coresel_val,
+	    rfctrlovr_trigger_val;
+	u16 afectrlovr_rssi_mask, rfctrlcmd_mask, rfctrlovr_mask;
+	u16 rfctrlcmd_val, rfctrlovr_val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			mod_phy_reg(pi, 0x8f, (0x1 << 9), 0);
+			mod_phy_reg(pi, 0xa5, (0x1 << 9), 0);
+
+			mod_phy_reg(pi, 0xa6, (0x3 << 8), 0);
+			mod_phy_reg(pi, 0xa7, (0x3 << 8), 0);
+
+			mod_phy_reg(pi, 0xe5, (0x1 << 5), 0);
+			mod_phy_reg(pi, 0xe6, (0x1 << 5), 0);
+
+			mask = (0x1 << 2) |
+			    (0x1 << 3) | (0x1 << 4) | (0x1 << 5);
+			mod_phy_reg(pi, 0xf9, mask, 0);
+			mod_phy_reg(pi, 0xfb, mask, 0);
+
+		} else {
+			for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+				if (core_code == RADIO_MIMO_CORESEL_CORE1
+				    && core == PHY_CORE_1)
+					continue;
+				else if (core_code == RADIO_MIMO_CORESEL_CORE2
+					 && core == PHY_CORE_0)
+					continue;
+
+				mod_phy_reg(pi, (core == PHY_CORE_0) ?
+					    0x8f : 0xa5, (0x1 << 9), 1 << 9);
+
+				if (rssi_type == NPHY_RSSI_SEL_W1 ||
+				    rssi_type == NPHY_RSSI_SEL_W2 ||
+				    rssi_type == NPHY_RSSI_SEL_NB) {
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xa6 : 0xa7,
+						    (0x3 << 8), 0);
+
+					mask = (0x1 << 2) |
+					    (0x1 << 3) |
+					    (0x1 << 4) | (0x1 << 5);
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, 0);
+
+					if (rssi_type == NPHY_RSSI_SEL_W1) {
+						if (CHSPEC_IS5G
+						    (pi->radio_chanspec)) {
+							mask = (0x1 << 2);
+							val = 1 << 2;
+						} else {
+							mask = (0x1 << 3);
+							val = 1 << 3;
+						}
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_W2) {
+						mask = (0x1 << 4);
+						val = 1 << 4;
+					} else {
+						mask = (0x1 << 5);
+						val = 1 << 5;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xf9 : 0xfb,
+						    mask, val);
+
+					mask = (0x1 << 5);
+					val = 1 << 5;
+					mod_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xe5 : 0xe6, mask, val);
+				} else {
+					if (rssi_type == NPHY_RSSI_SEL_TBD) {
+
+						mask = (0x3 << 8);
+						val = 1 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 1 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else if (rssi_type ==
+						   NPHY_RSSI_SEL_IQ) {
+
+						mask = (0x3 << 8);
+						val = 2 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 2 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+					} else {
+
+						mask = (0x3 << 8);
+						val = 3 << 8;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+						mask = (0x3 << 10);
+						val = 3 << 10;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0xa6
+							    : 0xa7, mask, val);
+
+						if (PHY_IPA(pi)) {
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     7)) {
+
+								write_radio_reg
+								    (pi,
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2057_TX0_TX_SSI_MUX
+								      :
+								      RADIO_2057_TX1_TX_SSI_MUX),
+								     (CHSPEC_IS5G
+								      (pi->
+								       radio_chanspec)
+								      ? 0xc :
+								      0xe));
+							} else {
+								write_radio_reg
+								    (pi,
+								     RADIO_2056_TX_TX_SSI_MUX
+								     |
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2056_TX0
+								      :
+								      RADIO_2056_TX1),
+								     (CHSPEC_IS5G
+								      (pi->
+								       radio_chanspec)
+								      ? 0xc :
+								      0xe));
+							}
+						} else {
+
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     7)) {
+								write_radio_reg
+								    (pi,
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2057_TX0_TX_SSI_MUX
+								      :
+								      RADIO_2057_TX1_TX_SSI_MUX),
+								     0x11);
+
+								if (pi->pubpi.
+								    radioid ==
+								    BCM2057_ID)
+									write_radio_reg
+									    (pi,
+									     RADIO_2057_IQTEST_SEL_PU,
+									     0x1);
+
+							} else {
+								write_radio_reg
+								    (pi,
+								     RADIO_2056_TX_TX_SSI_MUX
+								     |
+								     ((core ==
+								       PHY_CORE_0)
+								      ?
+								      RADIO_2056_TX0
+								      :
+								      RADIO_2056_TX1),
+								     0x11);
+							}
+						}
+
+						afectrlovr_rssi_val = 1 << 9;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x8f
+							    : 0xa5, (0x1 << 9),
+							    afectrlovr_rssi_val);
+					}
+				}
+			}
+		}
+	} else {
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+
+			val = 0x0;
+		} else if (rssi_type == NPHY_RSSI_SEL_TBD) {
+
+			val = 0x1;
+		} else if (rssi_type == NPHY_RSSI_SEL_IQ) {
+
+			val = 0x2;
+		} else {
+
+			val = 0x3;
+		}
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (val << 12) | (val << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			if (rssi_type == NPHY_RSSI_SEL_W1) {
+				val = 0x1;
+			}
+			if (rssi_type == NPHY_RSSI_SEL_W2) {
+				val = 0x2;
+			}
+			if (rssi_type == NPHY_RSSI_SEL_NB) {
+				val = 0x3;
+			}
+			mask = (0x3 << 4);
+			val = (val << 4);
+			mod_phy_reg(pi, 0x7a, mask, val);
+			mod_phy_reg(pi, 0x7d, mask, val);
+		}
+
+		if (core_code == RADIO_MIMO_CORESEL_OFF) {
+			afectrlovr_rssi_val = 0;
+			rfctrlcmd_rxen_val = 0;
+			rfctrlcmd_coresel_val = 0;
+			rfctrlovr_rssi_val = 0;
+			rfctrlovr_rxen_val = 0;
+			rfctrlovr_coresel_val = 0;
+			rfctrlovr_trigger_val = 0;
+			startseq = 0;
+		} else {
+			afectrlovr_rssi_val = 1;
+			rfctrlcmd_rxen_val = 1;
+			rfctrlcmd_coresel_val = core_code;
+			rfctrlovr_rssi_val = 1;
+			rfctrlovr_rxen_val = 1;
+			rfctrlovr_coresel_val = 1;
+			rfctrlovr_trigger_val = 1;
+			startseq = 1;
+		}
+
+		afectrlovr_rssi_mask = ((0x1 << 12) | (0x1 << 13));
+		afectrlovr_rssi_val = (afectrlovr_rssi_val <<
+				       12) | (afectrlovr_rssi_val << 13);
+		mod_phy_reg(pi, 0xa5, afectrlovr_rssi_mask,
+			    afectrlovr_rssi_val);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1) ||
+		    (rssi_type == NPHY_RSSI_SEL_W2) ||
+		    (rssi_type == NPHY_RSSI_SEL_NB)) {
+			rfctrlcmd_mask = ((0x1 << 8) | (0x7 << 3));
+			rfctrlcmd_val = (rfctrlcmd_rxen_val << 8) |
+			    (rfctrlcmd_coresel_val << 3);
+
+			rfctrlovr_mask = ((0x1 << 5) |
+					  (0x1 << 12) |
+					  (0x1 << 1) | (0x1 << 0));
+			rfctrlovr_val = (rfctrlovr_rssi_val <<
+					 5) |
+			    (rfctrlovr_rxen_val << 12) |
+			    (rfctrlovr_coresel_val << 1) |
+			    (rfctrlovr_trigger_val << 0);
+
+			mod_phy_reg(pi, 0x78, rfctrlcmd_mask, rfctrlcmd_val);
+			mod_phy_reg(pi, 0xec, rfctrlovr_mask, rfctrlovr_val);
+
+			mod_phy_reg(pi, 0x78, (0x1 << 0), (startseq << 0));
+			udelay(20);
+
+			mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+		}
+	}
+}
+
+int
+wlc_phy_poll_rssi_nphy(phy_info_t *pi, u8 rssi_type, s32 *rssi_buf,
+		       u8 nsamps)
+{
+	s16 rssi0, rssi1;
+	u16 afectrlCore1_save = 0;
+	u16 afectrlCore2_save = 0;
+	u16 afectrlOverride1_save = 0;
+	u16 afectrlOverride2_save = 0;
+	u16 rfctrlOverrideAux0_save = 0;
+	u16 rfctrlOverrideAux1_save = 0;
+	u16 rfctrlMiscReg1_save = 0;
+	u16 rfctrlMiscReg2_save = 0;
+	u16 rfctrlcmd_save = 0;
+	u16 rfctrloverride_save = 0;
+	u16 rfctrlrssiothers1_save = 0;
+	u16 rfctrlrssiothers2_save = 0;
+	s8 tmp_buf[4];
+	u8 ctr = 0, samp = 0;
+	s32 rssi_out_val;
+	u16 gpiosel_orig;
+
+	afectrlCore1_save = read_phy_reg(pi, 0xa6);
+	afectrlCore2_save = read_phy_reg(pi, 0xa7);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		rfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+		rfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+		afectrlOverride1_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		rfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+		rfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	} else {
+		afectrlOverride1_save = read_phy_reg(pi, 0xa5);
+		rfctrlcmd_save = read_phy_reg(pi, 0x78);
+		rfctrloverride_save = read_phy_reg(pi, 0xec);
+		rfctrlrssiothers1_save = read_phy_reg(pi, 0x7a);
+		rfctrlrssiothers2_save = read_phy_reg(pi, 0x7d);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	gpiosel_orig = read_phy_reg(pi, 0xca);
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0xca, 5);
+	}
+
+	for (ctr = 0; ctr < 4; ctr++) {
+		rssi_buf[ctr] = 0;
+	}
+
+	for (samp = 0; samp < nsamps; samp++) {
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+			rssi0 = read_phy_reg(pi, 0x1c9);
+			rssi1 = read_phy_reg(pi, 0x1ca);
+		} else {
+			rssi0 = read_phy_reg(pi, 0x219);
+			rssi1 = read_phy_reg(pi, 0x21a);
+		}
+
+		ctr = 0;
+		tmp_buf[ctr++] = ((s8) ((rssi0 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi0 >> 8) & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) ((rssi1 & 0x3f) << 2)) >> 2;
+		tmp_buf[ctr++] = ((s8) (((rssi1 >> 8) & 0x3f) << 2)) >> 2;
+
+		for (ctr = 0; ctr < 4; ctr++) {
+			rssi_buf[ctr] += tmp_buf[ctr];
+		}
+
+	}
+
+	rssi_out_val = rssi_buf[3] & 0xff;
+	rssi_out_val |= (rssi_buf[2] & 0xff) << 8;
+	rssi_out_val |= (rssi_buf[1] & 0xff) << 16;
+	rssi_out_val |= (rssi_buf[0] & 0xff) << 24;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		write_phy_reg(pi, 0xca, gpiosel_orig);
+	}
+
+	write_phy_reg(pi, 0xa6, afectrlCore1_save);
+	write_phy_reg(pi, 0xa7, afectrlCore2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xf9, rfctrlMiscReg1_save);
+		write_phy_reg(pi, 0xfb, rfctrlMiscReg2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride1_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0xe5, rfctrlOverrideAux0_save);
+		write_phy_reg(pi, 0xe6, rfctrlOverrideAux1_save);
+	} else {
+		write_phy_reg(pi, 0xa5, afectrlOverride1_save);
+		write_phy_reg(pi, 0x78, rfctrlcmd_save);
+		write_phy_reg(pi, 0xec, rfctrloverride_save);
+		write_phy_reg(pi, 0x7a, rfctrlrssiothers1_save);
+		write_phy_reg(pi, 0x7d, rfctrlrssiothers2_save);
+	}
+
+	return rssi_out_val;
+}
+
+s16 wlc_phy_tempsense_nphy(phy_info_t *pi)
+{
+	u16 core1_txrf_iqcal1_save, core1_txrf_iqcal2_save;
+	u16 core2_txrf_iqcal1_save, core2_txrf_iqcal2_save;
+	u16 pwrdet_rxtx_core1_save;
+	u16 pwrdet_rxtx_core2_save;
+	u16 afectrlCore1_save;
+	u16 afectrlCore2_save;
+	u16 afectrlOverride_save;
+	u16 afectrlOverride2_save;
+	u16 pd_pll_ts_save;
+	u16 gpioSel_save;
+	s32 radio_temp[4];
+	s32 radio_temp2[4];
+	u16 syn_tempprocsense_save;
+	s16 offset = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		u16 auxADC_Vmid, auxADC_Av, auxADC_Vmid_save, auxADC_Av_save;
+		u16 auxADC_rssi_ctrlL_save, auxADC_rssi_ctrlH_save;
+		u16 auxADC_rssi_ctrlL, auxADC_rssi_ctrlH;
+		s32 auxADC_Vl;
+		u16 RfctrlOverride5_save, RfctrlOverride6_save;
+		u16 RfctrlMiscReg5_save, RfctrlMiscReg6_save;
+		u16 RSSIMultCoef0QPowerDet_save;
+		u16 tempsense_Rcal;
+
+		syn_tempprocsense_save =
+		    read_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		RSSIMultCoef0QPowerDet_save = read_phy_reg(pi, 0x1ae);
+		RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+		RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					&auxADC_Vmid_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					&auxADC_Av_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					&auxADC_rssi_ctrlL_save);
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					&auxADC_rssi_ctrlH_save);
+
+		write_phy_reg(pi, 0x1ae, 0x0);
+
+		auxADC_rssi_ctrlL = 0x0;
+		auxADC_rssi_ctrlH = 0x20;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH);
+
+		tempsense_Rcal = syn_tempprocsense_save & 0x1c;
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		mod_phy_reg(pi, 0xa6, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 7), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 7), (0x1 << 7));
+		mod_phy_reg(pi, 0xa5, (0x1 << 7), (0x1 << 7));
+
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0x8f, (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, 0xa5, (0x1 << 2), (0x1 << 2));
+		udelay(5);
+		mod_phy_reg(pi, 0xa6, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 2), 0);
+		mod_phy_reg(pi, 0xa6, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 3), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa5, (0x1 << 3), (0x1 << 3));
+		mod_phy_reg(pi, 0xa6, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0xa7, (0x1 << 6), 0);
+		mod_phy_reg(pi, 0x8f, (0x1 << 6), (0x1 << 6));
+		mod_phy_reg(pi, 0xa5, (0x1 << 6), (0x1 << 6));
+
+		auxADC_Vmid = 0xA3;
+		auxADC_Av = 0x0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x03);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+
+		auxADC_Av = 0x7;
+		if (radio_temp[1] + radio_temp2[1] < -30) {
+			auxADC_Vmid = 0x45;
+			auxADC_Vl = 263;
+		} else if (radio_temp[1] + radio_temp2[1] < -9) {
+			auxADC_Vmid = 0x200;
+			auxADC_Vl = 467;
+		} else if (radio_temp[1] + radio_temp2[1] < 11) {
+			auxADC_Vmid = 0x266;
+			auxADC_Vl = 634;
+		} else {
+			auxADC_Vmid = 0x2D5;
+			auxADC_Vl = 816;
+		}
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av);
+
+		udelay(3);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				tempsense_Rcal | 0x01);
+
+		udelay(5);
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+
+		write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+		write_phy_reg(pi, 0x1ae, RSSIMultCoef0QPowerDet_save);
+		write_phy_reg(pi, 0x346, RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, RfctrlOverride6_save);
+		write_phy_reg(pi, 0x344, RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, RfctrlMiscReg5_save);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0A, 16,
+					 &auxADC_Vmid_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x0E, 16,
+					 &auxADC_Av_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x02, 16,
+					 &auxADC_rssi_ctrlL_save);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 0x03, 16,
+					 &auxADC_rssi_ctrlH_save);
+
+		if (pi->sh->chip == BCM5357_CHIP_ID) {
+			radio_temp[0] = (193 * (radio_temp[1] + radio_temp2[1])
+					 + 88 * (auxADC_Vl) - 27111 +
+					 128) / 256;
+		} else if (pi->sh->chip == BCM43236_CHIP_ID) {
+			radio_temp[0] = (198 * (radio_temp[1] + radio_temp2[1])
+					 + 91 * (auxADC_Vl) - 27243 +
+					 128) / 256;
+		} else {
+			radio_temp[0] = (179 * (radio_temp[1] + radio_temp2[1])
+					 + 82 * (auxADC_Vl) - 28861 +
+					 128) / 256;
+		}
+
+		offset = (s16) pi->phy_tempsense_offset;
+
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		syn_tempprocsense_save =
+		    read_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0x8f);
+		afectrlOverride2_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		} else {
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x05);
+		}
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			write_radio_reg(pi, RADIO_2057_TEMPSENSE_CONFIG, 0x01);
+		} else {
+			write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE, 0x01);
+		}
+
+		radio_temp[0] =
+		    (126 * (radio_temp[1] + radio_temp2[1]) + 3987) / 64;
+
+		write_radio_reg(pi, RADIO_2056_SYN_TEMPPROCSENSE,
+				syn_tempprocsense_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0x8f, afectrlOverride_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride2_save);
+
+		offset = (s16) pi->phy_tempsense_offset;
+	} else {
+
+		pwrdet_rxtx_core1_save =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pwrdet_rxtx_core2_save =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+		core1_txrf_iqcal1_save =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		core1_txrf_iqcal2_save =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		core2_txrf_iqcal1_save =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		core2_txrf_iqcal2_save =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		pd_pll_ts_save = read_radio_reg(pi, RADIO_2055_PD_PLL_TS);
+
+		afectrlCore1_save = read_phy_reg(pi, 0xa6);
+		afectrlCore2_save = read_phy_reg(pi, 0xa7);
+		afectrlOverride_save = read_phy_reg(pi, 0xa5);
+		gpioSel_save = read_phy_reg(pi, 0xca);
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x01);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x08);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, 0x00);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_IQ, radio_temp2, 1);
+		xor_radio_reg(pi, RADIO_2055_CAL_TS, 0x80);
+
+		radio_temp[0] = (radio_temp[0] + radio_temp2[0]);
+		radio_temp[1] = (radio_temp[1] + radio_temp2[1]);
+		radio_temp[2] = (radio_temp[2] + radio_temp2[2]);
+		radio_temp[3] = (radio_temp[3] + radio_temp2[3]);
+
+		radio_temp[0] =
+		    (radio_temp[0] + radio_temp[1] + radio_temp[2] +
+		     radio_temp[3]);
+
+		radio_temp[0] =
+		    (radio_temp[0] + (8 * 32)) * (950 - 350) / 63 + (350 * 8);
+
+		radio_temp[0] = (radio_temp[0] - (8 * 420)) / 38;
+
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pwrdet_rxtx_core1_save);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pwrdet_rxtx_core2_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				core1_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				core2_txrf_iqcal1_save);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				core1_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				core2_txrf_iqcal2_save);
+		write_radio_reg(pi, RADIO_2055_PD_PLL_TS, pd_pll_ts_save);
+
+		write_phy_reg(pi, 0xca, gpioSel_save);
+		write_phy_reg(pi, 0xa6, afectrlCore1_save);
+		write_phy_reg(pi, 0xa7, afectrlCore2_save);
+		write_phy_reg(pi, 0xa5, afectrlOverride_save);
+	}
+
+	return (s16) radio_temp[0] + offset;
+}
+
+static void
+wlc_phy_set_rssi_2055_vcm(phy_info_t *pi, u8 rssi_type, u8 *vcm_buf)
+{
+	u8 core;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		if (rssi_type == NPHY_RSSI_SEL_NB) {
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_B0_NBRSSI_VCM,
+					      RADIO_2055_NBRSSI_VCM_I_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_NBRSSI_VCM_I_SHIFT);
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_NBRSSI_VCM_Q_MASK,
+					      vcm_buf[2 * core +
+						      1] <<
+					      RADIO_2055_NBRSSI_VCM_Q_SHIFT);
+			}
+		} else {
+
+			if (core == PHY_CORE_0) {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE1_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			} else {
+				mod_radio_reg(pi,
+					      RADIO_2055_CORE2_RXBB_RSSI_CTRL5,
+					      RADIO_2055_WBRSSI_VCM_IQ_MASK,
+					      vcm_buf[2 *
+						      core] <<
+					      RADIO_2055_WBRSSI_VCM_IQ_SHIFT);
+			}
+		}
+	}
+}
+
+void wlc_phy_rssi_cal_nphy(phy_info_t *pi)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		wlc_phy_rssi_cal_nphy_rev3(pi);
+	} else {
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_NB);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W1);
+		wlc_phy_rssi_cal_nphy_rev2(pi, NPHY_RSSI_SEL_W2);
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev2(phy_info_t *pi, u8 rssi_type)
+{
+	s32 target_code;
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 rssi_ctrl_state[2], pd_state[2];
+	u16 rfctrlintc_state[2], rfpdcorerxtx_state[2];
+	u16 rfctrlintc_override_val;
+	u16 clip_off[] = { 0xffff, 0xffff };
+	u16 rf_pd_val, pd_mask, rssi_ctrl_mask;
+	u8 vcm, min_vcm, vcm_tmp[4];
+	u8 vcm_final[4] = { 0, 0, 0, 0 };
+	u8 result_idx, ctr;
+	s32 poll_results[4][4] = {
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0},
+		{0, 0, 0, 0}
+	};
+	s32 poll_miniq[4][2] = {
+		{0, 0},
+		{0, 0},
+		{0, 0},
+		{0, 0}
+	};
+	s32 min_d, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+
+	switch (rssi_type) {
+	case NPHY_RSSI_SEL_NB:
+		target_code = NPHY_RSSICAL_NB_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W1:
+		target_code = NPHY_RSSICAL_W1_TARGET;
+		break;
+	case NPHY_RSSI_SEL_W2:
+		target_code = NPHY_RSSICAL_W2_TARGET;
+		break;
+	default:
+		return;
+		break;
+	}
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	rf_pd_val = (rssi_type == NPHY_RSSI_SEL_NB) ? 0x6 : 0x4;
+	rfctrlintc_override_val =
+	    CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 : 0x110;
+
+	rfctrlintc_state[0] = read_phy_reg(pi, 0x91);
+	rfpdcorerxtx_state[0] = read_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX);
+	write_phy_reg(pi, 0x91, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rf_pd_val);
+
+	rfctrlintc_state[1] = read_phy_reg(pi, 0x92);
+	rfpdcorerxtx_state[1] = read_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX);
+	write_phy_reg(pi, 0x92, rfctrlintc_override_val);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rf_pd_val);
+
+	pd_mask = RADIO_2055_NBRSSI_PD | RADIO_2055_WBRSSI_G1_PD |
+	    RADIO_2055_WBRSSI_G2_PD;
+	pd_state[0] =
+	    read_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC) & pd_mask;
+	pd_state[1] =
+	    read_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC) & pd_mask;
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, 0);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, 0);
+	rssi_ctrl_mask = RADIO_2055_NBRSSI_SEL | RADIO_2055_WBRSSI_G1_SEL |
+	    RADIO_2055_WBRSSI_G2_SEL;
+	rssi_ctrl_state[0] =
+	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE1) & rssi_ctrl_mask;
+	rssi_ctrl_state[1] =
+	    read_radio_reg(pi, RADIO_2055_SP_RSSI_CORE2) & rssi_ctrl_mask;
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_ALLRX, rssi_type);
+
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_I, rssi_type);
+	wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0, RADIO_MIMO_CORESEL_ALLRX,
+				       NPHY_RAIL_Q, rssi_type);
+
+	for (vcm = 0; vcm < 4; vcm++) {
+
+		vcm_tmp[0] = vcm_tmp[1] = vcm_tmp[2] = vcm_tmp[3] = vcm;
+		if (rssi_type != NPHY_RSSI_SEL_W2) {
+			wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_tmp);
+		}
+
+		wlc_phy_poll_rssi_nphy(pi, rssi_type, &poll_results[vcm][0],
+				       NPHY_RSSICAL_NPOLL);
+
+		if ((rssi_type == NPHY_RSSI_SEL_W1)
+		    || (rssi_type == NPHY_RSSI_SEL_W2)) {
+			for (ctr = 0; ctr < 2; ctr++) {
+				poll_miniq[vcm][ctr] =
+				    min(poll_results[vcm][ctr * 2 + 0],
+					poll_results[vcm][ctr * 2 + 1]);
+			}
+		}
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		min_d = NPHY_RSSICAL_MAXD;
+		min_vcm = 0;
+		min_poll = NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL + 1;
+		for (vcm = 0; vcm < 4; vcm++) {
+			curr_d = ABS(((rssi_type == NPHY_RSSI_SEL_NB) ?
+				      poll_results[vcm][result_idx] :
+				      poll_miniq[vcm][result_idx / 2]) -
+				     (target_code * NPHY_RSSICAL_NPOLL));
+			if (curr_d < min_d) {
+				min_d = curr_d;
+				min_vcm = vcm;
+			}
+			if (poll_results[vcm][result_idx] < min_poll) {
+				min_poll = poll_results[vcm][result_idx];
+			}
+		}
+		vcm_final[result_idx] = min_vcm;
+		poll_results_min[result_idx] = min_poll;
+	}
+
+	if (rssi_type != NPHY_RSSI_SEL_W2) {
+		wlc_phy_set_rssi_2055_vcm(pi, rssi_type, vcm_final);
+	}
+
+	for (result_idx = 0; result_idx < 4; result_idx++) {
+		fine_digital_offset[result_idx] =
+		    (target_code * NPHY_RSSICAL_NPOLL) -
+		    poll_results[vcm_final[result_idx]][result_idx];
+		if (fine_digital_offset[result_idx] < 0) {
+			fine_digital_offset[result_idx] =
+			    ABS(fine_digital_offset[result_idx]);
+			fine_digital_offset[result_idx] +=
+			    (NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+			fine_digital_offset[result_idx] =
+			    -fine_digital_offset[result_idx];
+		} else {
+			fine_digital_offset[result_idx] +=
+			    (NPHY_RSSICAL_NPOLL / 2);
+			fine_digital_offset[result_idx] /= NPHY_RSSICAL_NPOLL;
+		}
+
+		if (poll_results_min[result_idx] ==
+		    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+			fine_digital_offset[result_idx] =
+			    (target_code - NPHY_RSSICAL_MAXREAD - 1);
+		}
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+					       (s8)
+					       fine_digital_offset[result_idx],
+					       (result_idx / 2 ==
+						0) ? RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       (result_idx % 2 ==
+						0) ? NPHY_RAIL_I : NPHY_RAIL_Q,
+					       rssi_type);
+	}
+
+	mod_radio_reg(pi, RADIO_2055_PD_CORE1_RSSI_MISC, pd_mask, pd_state[0]);
+	mod_radio_reg(pi, RADIO_2055_PD_CORE2_RSSI_MISC, pd_mask, pd_state[1]);
+	if (rssi_ctrl_state[0] == RADIO_2055_NBRSSI_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_NB);
+	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G1_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W1);
+	} else if (rssi_ctrl_state[0] == RADIO_2055_WBRSSI_G2_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	} else {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE1,
+				     NPHY_RSSI_SEL_W2);
+	}
+	if (rssi_ctrl_state[1] == RADIO_2055_NBRSSI_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_NB);
+	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G1_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W1);
+	} else if (rssi_ctrl_state[1] == RADIO_2055_WBRSSI_G2_SEL) {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	} else {
+		wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_CORE2,
+				     NPHY_RSSI_SEL_W2);
+	}
+
+	wlc_phy_rssisel_nphy(pi, RADIO_MIMO_CORESEL_OFF, rssi_type);
+
+	write_phy_reg(pi, 0x91, rfctrlintc_state[0]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE1_RXTX, rfpdcorerxtx_state[0]);
+	write_phy_reg(pi, 0x92, rfctrlintc_state[1]);
+	write_radio_reg(pi, RADIO_2055_PD_CORE2_RXTX, rfpdcorerxtx_state[1]);
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+
+	wlc_phy_resetcca_nphy(pi);
+}
+
+int BCMFASTPATH
+wlc_phy_rssi_compute_nphy(phy_info_t *pi, wlc_d11rxhdr_t *wlc_rxh)
+{
+	d11rxhdr_t *rxh = &wlc_rxh->rxhdr;
+	s16 rxpwr, rxpwr0, rxpwr1;
+	s16 phyRx0_l, phyRx2_l;
+
+	rxpwr = 0;
+	rxpwr0 = le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR0_MASK;
+	rxpwr1 = (le16_to_cpu(rxh->PhyRxStatus_1) & PRXS1_nphy_PWR1_MASK) >> 8;
+
+	if (rxpwr0 > 127)
+		rxpwr0 -= 256;
+	if (rxpwr1 > 127)
+		rxpwr1 -= 256;
+
+	phyRx0_l = le16_to_cpu(rxh->PhyRxStatus_0) & 0x00ff;
+	phyRx2_l = le16_to_cpu(rxh->PhyRxStatus_2) & 0x00ff;
+	if (phyRx2_l > 127)
+		phyRx2_l -= 256;
+
+	if (((rxpwr0 == 16) || (rxpwr0 == 32))) {
+		rxpwr0 = rxpwr1;
+		rxpwr1 = phyRx2_l;
+	}
+
+	wlc_rxh->rxpwr[0] = (s8) rxpwr0;
+	wlc_rxh->rxpwr[1] = (s8) rxpwr1;
+	wlc_rxh->do_rssi_ma = 0;
+
+	if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MAX)
+		rxpwr = (rxpwr0 > rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_MIN)
+		rxpwr = (rxpwr0 < rxpwr1) ? rxpwr0 : rxpwr1;
+	else if (pi->sh->rssi_mode == RSSI_ANT_MERGE_AVG)
+		rxpwr = (rxpwr0 + rxpwr1) >> 1;
+	else
+		ASSERT(0);
+
+	return rxpwr;
+}
+
+static void
+wlc_phy_rfctrlintc_override_nphy(phy_info_t *pi, u8 field, u16 value,
+				 u8 core_code)
+{
+	u16 mask;
+	u16 val;
+	u8 core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			if (core_code == RADIO_MIMO_CORESEL_CORE1
+			    && core == PHY_CORE_1)
+				continue;
+			else if (core_code == RADIO_MIMO_CORESEL_CORE2
+				 && core == PHY_CORE_0)
+				continue;
+
+			if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+				mask = (0x1 << 10);
+				val = 1 << 10;
+				mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					    0x92, mask, val);
+			}
+
+			if (field == NPHY_RfctrlIntc_override_OFF) {
+
+				write_phy_reg(pi, (core == PHY_CORE_0) ? 0x91 :
+					      0x92, 0);
+
+				wlc_phy_force_rfseq_nphy(pi,
+							 NPHY_RFSEQ_RESET2RX);
+			} else if (field == NPHY_RfctrlIntc_override_TRSW) {
+
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 6) | (0x1 << 7);
+
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 10));
+
+					and_phy_reg(pi, 0x2ff, (u16)
+						    ~(0x3 << 14));
+					or_phy_reg(pi, 0x2ff, (0x1 << 13));
+					or_phy_reg(pi, 0x2ff, (0x1 << 0));
+				} else {
+
+					mask = (0x1 << 6) |
+					    (0x1 << 7) |
+					    (0x1 << 8) | (0x1 << 9);
+					val = value << 6;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					mask = (0x1 << 0);
+					val = 1 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+
+					mask = (core == PHY_CORE_0) ? (0x1 << 0)
+					    : (0x1 << 1);
+					val = 1 << ((core == PHY_CORE_0) ?
+						    0 : 1);
+					mod_phy_reg(pi, 0x78, mask, val);
+
+					SPINWAIT(((read_phy_reg(pi, 0x78) & val)
+						  != 0), 10000);
+					ASSERT((read_phy_reg(pi, 0x78) & val) ==
+					       0);
+
+					mask = (0x1 << 0);
+					val = 0 << 0;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0xe7 : 0xec,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_PA) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+					mask = (0x1 << 4) | (0x1 << 5);
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						val = value << 5;
+					} else {
+						val = value << 4;
+					}
+
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+
+					or_phy_reg(pi,
+						   (core ==
+						    PHY_CORE_0) ? 0x91 : 0x92,
+						   (0x1 << 12));
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 5);
+						val = value << 5;
+					} else {
+						mask = (0x1 << 4);
+						val = value << 4;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field == NPHY_RfctrlIntc_override_EXT_LNA_PU) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 0);
+						val = value << 0;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 2);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 2);
+						val = value << 2;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 0);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 0);
+						val = value << 0;
+					} else {
+						mask = (0x1 << 2);
+						val = value << 2;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			} else if (field ==
+				   NPHY_RfctrlIntc_override_EXT_LNA_GAIN) {
+				if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+						mask = (0x1 << 1);
+						val = value << 1;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 3);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					} else {
+
+						mask = (0x1 << 3);
+						val = value << 3;
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, val);
+
+						mask = (0x1 << 1);
+						mod_phy_reg(pi,
+							    (core ==
+							     PHY_CORE_0) ? 0x91
+							    : 0x92, mask, 0);
+					}
+
+					mask = (0x1 << 11);
+					val = 1 << 11;
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				} else {
+
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						mask = (0x1 << 1);
+						val = value << 1;
+					} else {
+						mask = (0x1 << 3);
+						val = value << 3;
+					}
+					mod_phy_reg(pi,
+						    (core ==
+						     PHY_CORE_0) ? 0x91 : 0x92,
+						    mask, val);
+				}
+			}
+		}
+	} else {
+		return;
+	}
+}
+
+static void wlc_phy_rssi_cal_nphy_rev3(phy_info_t *pi)
+{
+	u16 classif_state;
+	u16 clip_state[2];
+	u16 clip_off[] = { 0xffff, 0xffff };
+	s32 target_code;
+	u8 vcm, min_vcm;
+	u8 vcm_final = 0;
+	u8 result_idx;
+	s32 poll_results[8][4] = {
+		{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}
+	};
+	s32 poll_result_core[4] = { 0, 0, 0, 0 };
+	s32 min_d = NPHY_RSSICAL_MAXD, curr_d;
+	s32 fine_digital_offset[4];
+	s32 poll_results_min[4] = { 0, 0, 0, 0 };
+	s32 min_poll;
+	u8 vcm_level_max;
+	u8 core;
+	u8 wb_cnt;
+	u8 rssi_type;
+	u16 NPHY_Rfctrlintc1_save, NPHY_Rfctrlintc2_save;
+	u16 NPHY_AfectrlOverride1_save, NPHY_AfectrlOverride2_save;
+	u16 NPHY_AfectrlCore1_save, NPHY_AfectrlCore2_save;
+	u16 NPHY_RfctrlOverride0_save, NPHY_RfctrlOverride1_save;
+	u16 NPHY_RfctrlOverrideAux0_save, NPHY_RfctrlOverrideAux1_save;
+	u16 NPHY_RfctrlCmd_save;
+	u16 NPHY_RfctrlMiscReg1_save, NPHY_RfctrlMiscReg2_save;
+	u16 NPHY_RfctrlRSSIOTHERS1_save, NPHY_RfctrlRSSIOTHERS2_save;
+	u8 rxcore_state;
+	u16 NPHY_REV7_RfctrlOverride3_save, NPHY_REV7_RfctrlOverride4_save;
+	u16 NPHY_REV7_RfctrlOverride5_save, NPHY_REV7_RfctrlOverride6_save;
+	u16 NPHY_REV7_RfctrlMiscReg3_save, NPHY_REV7_RfctrlMiscReg4_save;
+	u16 NPHY_REV7_RfctrlMiscReg5_save, NPHY_REV7_RfctrlMiscReg6_save;
+
+	NPHY_REV7_RfctrlOverride3_save = NPHY_REV7_RfctrlOverride4_save =
+	    NPHY_REV7_RfctrlOverride5_save = NPHY_REV7_RfctrlOverride6_save =
+	    NPHY_REV7_RfctrlMiscReg3_save = NPHY_REV7_RfctrlMiscReg4_save =
+	    NPHY_REV7_RfctrlMiscReg5_save = NPHY_REV7_RfctrlMiscReg6_save = 0;
+
+	classif_state = wlc_phy_classifier_nphy(pi, 0, 0);
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), 4);
+	wlc_phy_clip_det_nphy(pi, 0, clip_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_off);
+
+	NPHY_Rfctrlintc1_save = read_phy_reg(pi, 0x91);
+	NPHY_Rfctrlintc2_save = read_phy_reg(pi, 0x92);
+	NPHY_AfectrlOverride1_save = read_phy_reg(pi, 0x8f);
+	NPHY_AfectrlOverride2_save = read_phy_reg(pi, 0xa5);
+	NPHY_AfectrlCore1_save = read_phy_reg(pi, 0xa6);
+	NPHY_AfectrlCore2_save = read_phy_reg(pi, 0xa7);
+	NPHY_RfctrlOverride0_save = read_phy_reg(pi, 0xe7);
+	NPHY_RfctrlOverride1_save = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlOverride3_save = read_phy_reg(pi, 0x342);
+		NPHY_REV7_RfctrlOverride4_save = read_phy_reg(pi, 0x343);
+		NPHY_REV7_RfctrlOverride5_save = read_phy_reg(pi, 0x346);
+		NPHY_REV7_RfctrlOverride6_save = read_phy_reg(pi, 0x347);
+	}
+	NPHY_RfctrlOverrideAux0_save = read_phy_reg(pi, 0xe5);
+	NPHY_RfctrlOverrideAux1_save = read_phy_reg(pi, 0xe6);
+	NPHY_RfctrlCmd_save = read_phy_reg(pi, 0x78);
+	NPHY_RfctrlMiscReg1_save = read_phy_reg(pi, 0xf9);
+	NPHY_RfctrlMiscReg2_save = read_phy_reg(pi, 0xfb);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		NPHY_REV7_RfctrlMiscReg3_save = read_phy_reg(pi, 0x340);
+		NPHY_REV7_RfctrlMiscReg4_save = read_phy_reg(pi, 0x341);
+		NPHY_REV7_RfctrlMiscReg5_save = read_phy_reg(pi, 0x344);
+		NPHY_REV7_RfctrlMiscReg6_save = read_phy_reg(pi, 0x345);
+	}
+	NPHY_RfctrlRSSIOTHERS1_save = read_phy_reg(pi, 0x7a);
+	NPHY_RfctrlRSSIOTHERS2_save = read_phy_reg(pi, 0x7d);
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_OFF, 0,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_TRSW, 1,
+					 RADIO_MIMO_CORESEL_ALLRXTX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxrf_pu,
+						     0, 0, 0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0, 0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rx_pu,
+						     1, 0, 0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0, 0);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 6), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 7), 1, 0, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 6), 1, 0, 0);
+	}
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 1, 0,
+							  0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 1, 0, 0);
+		}
+
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 1, 0,
+							  0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 4), 0, 0, 0);
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 5), 1, 0, 0);
+		}
+	}
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
+
+	vcm_level_max = 8;
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_I, NPHY_RSSI_SEL_NB);
+		wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+					       core ==
+					       PHY_CORE_0 ?
+					       RADIO_MIMO_CORESEL_CORE1 :
+					       RADIO_MIMO_CORESEL_CORE2,
+					       NPHY_RAIL_Q, NPHY_RSSI_SEL_NB);
+
+		for (vcm = 0; vcm < vcm_level_max; vcm++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, (core == PHY_CORE_0) ?
+					      RADIO_2057_NB_MASTER_CORE0 :
+					      RADIO_2057_NB_MASTER_CORE1,
+					      RADIO_2057_VCM_MASK, vcm);
+			} else {
+
+				mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+					      ((core ==
+						PHY_CORE_0) ? RADIO_2056_RX0 :
+					       RADIO_2056_RX1),
+					      RADIO_2056_VCM_MASK,
+					      vcm << RADIO_2056_RSSI_VCM_SHIFT);
+			}
+
+			wlc_phy_poll_rssi_nphy(pi, NPHY_RSSI_SEL_NB,
+					       &poll_results[vcm][0],
+					       NPHY_RSSICAL_NPOLL);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if ((core == result_idx / 2) && (result_idx % 2 == 0)) {
+
+				min_d = NPHY_RSSICAL_MAXD;
+				min_vcm = 0;
+				min_poll =
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL +
+				    1;
+				for (vcm = 0; vcm < vcm_level_max; vcm++) {
+					curr_d = poll_results[vcm][result_idx] *
+					    poll_results[vcm][result_idx] +
+					    poll_results[vcm][result_idx + 1] *
+					    poll_results[vcm][result_idx + 1];
+					if (curr_d < min_d) {
+						min_d = curr_d;
+						min_vcm = vcm;
+					}
+					if (poll_results[vcm][result_idx] <
+					    min_poll) {
+						min_poll =
+						    poll_results[vcm]
+						    [result_idx];
+					}
+				}
+				vcm_final = min_vcm;
+				poll_results_min[result_idx] = min_poll;
+			}
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, (core == PHY_CORE_0) ?
+				      RADIO_2057_NB_MASTER_CORE0 :
+				      RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK, vcm_final);
+		} else {
+			mod_radio_reg(pi, RADIO_2056_RX_RSSI_MISC |
+				      ((core ==
+					PHY_CORE_0) ? RADIO_2056_RX0 :
+				       RADIO_2056_RX1), RADIO_2056_VCM_MASK,
+				      vcm_final << RADIO_2056_RSSI_VCM_SHIFT);
+		}
+
+		for (result_idx = 0; result_idx < 4; result_idx++) {
+			if (core == result_idx / 2) {
+				fine_digital_offset[result_idx] =
+				    (NPHY_RSSICAL_NB_TARGET *
+				     NPHY_RSSICAL_NPOLL) -
+				    poll_results[vcm_final][result_idx];
+				if (fine_digital_offset[result_idx] < 0) {
+					fine_digital_offset[result_idx] =
+					    ABS(fine_digital_offset
+						[result_idx]);
+					fine_digital_offset[result_idx] +=
+					    (NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+					    NPHY_RSSICAL_NPOLL;
+					fine_digital_offset[result_idx] =
+					    -fine_digital_offset[result_idx];
+				} else {
+					fine_digital_offset[result_idx] +=
+					    (NPHY_RSSICAL_NPOLL / 2);
+					fine_digital_offset[result_idx] /=
+					    NPHY_RSSICAL_NPOLL;
+				}
+
+				if (poll_results_min[result_idx] ==
+				    NPHY_RSSICAL_MAXREAD * NPHY_RSSICAL_NPOLL) {
+					fine_digital_offset[result_idx] =
+					    (NPHY_RSSICAL_NB_TARGET -
+					     NPHY_RSSICAL_MAXREAD - 1);
+				}
+
+				wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+							       (s8)
+							       fine_digital_offset
+							       [result_idx],
+							       (result_idx /
+								2 ==
+								0) ?
+							       RADIO_MIMO_CORESEL_CORE1
+							       :
+							       RADIO_MIMO_CORESEL_CORE2,
+							       (result_idx %
+								2 ==
+								0) ? NPHY_RAIL_I
+							       : NPHY_RAIL_Q,
+							       NPHY_RSSI_SEL_NB);
+			}
+		}
+
+	}
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+		if ((rxcore_state & (1 << core)) == 0)
+			continue;
+
+		for (wb_cnt = 0; wb_cnt < 2; wb_cnt++) {
+			if (wb_cnt == 0) {
+				rssi_type = NPHY_RSSI_SEL_W1;
+				target_code = NPHY_RSSICAL_W1_TARGET_REV3;
+			} else {
+				rssi_type = NPHY_RSSI_SEL_W2;
+				target_code = NPHY_RSSICAL_W2_TARGET_REV3;
+			}
+
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_I, rssi_type);
+			wlc_phy_scale_offset_rssi_nphy(pi, 0x0, 0x0,
+						       core ==
+						       PHY_CORE_0 ?
+						       RADIO_MIMO_CORESEL_CORE1
+						       :
+						       RADIO_MIMO_CORESEL_CORE2,
+						       NPHY_RAIL_Q, rssi_type);
+
+			wlc_phy_poll_rssi_nphy(pi, rssi_type, poll_result_core,
+					       NPHY_RSSICAL_NPOLL);
+
+			for (result_idx = 0; result_idx < 4; result_idx++) {
+				if (core == result_idx / 2) {
+					fine_digital_offset[result_idx] =
+					    (target_code * NPHY_RSSICAL_NPOLL) -
+					    poll_result_core[result_idx];
+					if (fine_digital_offset[result_idx] < 0) {
+						fine_digital_offset[result_idx]
+						    =
+						    ABS(fine_digital_offset
+							[result_idx]);
+						fine_digital_offset[result_idx]
+						    += (NPHY_RSSICAL_NPOLL / 2);
+						fine_digital_offset[result_idx]
+						    /= NPHY_RSSICAL_NPOLL;
+						fine_digital_offset[result_idx]
+						    =
+						    -fine_digital_offset
+						    [result_idx];
+					} else {
+						fine_digital_offset[result_idx]
+						    += (NPHY_RSSICAL_NPOLL / 2);
+						fine_digital_offset[result_idx]
+						    /= NPHY_RSSICAL_NPOLL;
+					}
+
+					wlc_phy_scale_offset_rssi_nphy(pi, 0x0,
+								       (s8)
+								       fine_digital_offset
+								       [core *
+									2],
+								       (core ==
+									PHY_CORE_0)
+								       ?
+								       RADIO_MIMO_CORESEL_CORE1
+								       :
+								       RADIO_MIMO_CORESEL_CORE2,
+								       (result_idx
+									% 2 ==
+									0) ?
+								       NPHY_RAIL_I
+								       :
+								       NPHY_RAIL_Q,
+								       rssi_type);
+				}
+			}
+
+		}
+	}
+
+	write_phy_reg(pi, 0x91, NPHY_Rfctrlintc1_save);
+	write_phy_reg(pi, 0x92, NPHY_Rfctrlintc2_save);
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0xe7, (0x1 << 0), 0);
+
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 1 << 0);
+	mod_phy_reg(pi, 0x78, (0x1 << 1), 1 << 1);
+	mod_phy_reg(pi, 0xec, (0x1 << 0), 0);
+
+	write_phy_reg(pi, 0x8f, NPHY_AfectrlOverride1_save);
+	write_phy_reg(pi, 0xa5, NPHY_AfectrlOverride2_save);
+	write_phy_reg(pi, 0xa6, NPHY_AfectrlCore1_save);
+	write_phy_reg(pi, 0xa7, NPHY_AfectrlCore2_save);
+	write_phy_reg(pi, 0xe7, NPHY_RfctrlOverride0_save);
+	write_phy_reg(pi, 0xec, NPHY_RfctrlOverride1_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, NPHY_REV7_RfctrlOverride3_save);
+		write_phy_reg(pi, 0x343, NPHY_REV7_RfctrlOverride4_save);
+		write_phy_reg(pi, 0x346, NPHY_REV7_RfctrlOverride5_save);
+		write_phy_reg(pi, 0x347, NPHY_REV7_RfctrlOverride6_save);
+	}
+	write_phy_reg(pi, 0xe5, NPHY_RfctrlOverrideAux0_save);
+	write_phy_reg(pi, 0xe6, NPHY_RfctrlOverrideAux1_save);
+	write_phy_reg(pi, 0x78, NPHY_RfctrlCmd_save);
+	write_phy_reg(pi, 0xf9, NPHY_RfctrlMiscReg1_save);
+	write_phy_reg(pi, 0xfb, NPHY_RfctrlMiscReg2_save);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x340, NPHY_REV7_RfctrlMiscReg3_save);
+		write_phy_reg(pi, 0x341, NPHY_REV7_RfctrlMiscReg4_save);
+		write_phy_reg(pi, 0x344, NPHY_REV7_RfctrlMiscReg5_save);
+		write_phy_reg(pi, 0x345, NPHY_REV7_RfctrlMiscReg6_save);
+	}
+	write_phy_reg(pi, 0x7a, NPHY_RfctrlRSSIOTHERS1_save);
+	write_phy_reg(pi, 0x7d, NPHY_RfctrlRSSIOTHERS2_save);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_2G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_2G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_2G[0] =
+		    read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_2G[1] =
+		    read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_2G[2] =
+		    read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_2G[3] =
+		    read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_2G[4] =
+		    read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_2G[5] =
+		    read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_2G[6] =
+		    read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_2G[7] =
+		    read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_2G[8] =
+		    read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_2G[9] =
+		    read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_2G[10] =
+		    read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_2G[11] =
+		    read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_2G = pi->radio_chanspec;
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+			    read_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1);
+		} else {
+			pi->rssical_cache.rssical_radio_regs_5G[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX0);
+			pi->rssical_cache.rssical_radio_regs_5G[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RSSI_MISC |
+					   RADIO_2056_RX1);
+		}
+
+		pi->rssical_cache.rssical_phyregs_5G[0] =
+		    read_phy_reg(pi, 0x1a6);
+		pi->rssical_cache.rssical_phyregs_5G[1] =
+		    read_phy_reg(pi, 0x1ac);
+		pi->rssical_cache.rssical_phyregs_5G[2] =
+		    read_phy_reg(pi, 0x1b2);
+		pi->rssical_cache.rssical_phyregs_5G[3] =
+		    read_phy_reg(pi, 0x1b8);
+		pi->rssical_cache.rssical_phyregs_5G[4] =
+		    read_phy_reg(pi, 0x1a4);
+		pi->rssical_cache.rssical_phyregs_5G[5] =
+		    read_phy_reg(pi, 0x1aa);
+		pi->rssical_cache.rssical_phyregs_5G[6] =
+		    read_phy_reg(pi, 0x1b0);
+		pi->rssical_cache.rssical_phyregs_5G[7] =
+		    read_phy_reg(pi, 0x1b6);
+		pi->rssical_cache.rssical_phyregs_5G[8] =
+		    read_phy_reg(pi, 0x1a5);
+		pi->rssical_cache.rssical_phyregs_5G[9] =
+		    read_phy_reg(pi, 0x1ab);
+		pi->rssical_cache.rssical_phyregs_5G[10] =
+		    read_phy_reg(pi, 0x1b1);
+		pi->rssical_cache.rssical_phyregs_5G[11] =
+		    read_phy_reg(pi, 0x1b7);
+
+		pi->nphy_rssical_chanspec_5G = pi->radio_chanspec;
+	}
+
+	wlc_phy_classifier_nphy(pi, (0x7 << 0), classif_state);
+	wlc_phy_clip_det_nphy(pi, 1, clip_state);
+}
+
+static void wlc_phy_restore_rssical_nphy(phy_info_t *pi)
+{
+	ASSERT(NREV_GE(pi->pubpi.phy_rev, 3));
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		if (pi->nphy_rssical_chanspec_2G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_2G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_2G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_2G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_2G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_2G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_2G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_2G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_2G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_2G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_2G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_2G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_2G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_2G[11]);
+
+	} else {
+		if (pi->nphy_rssical_chanspec_5G == 0)
+			return;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE0,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi, RADIO_2057_NB_MASTER_CORE1,
+				      RADIO_2057_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		} else {
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX0,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[0]);
+			mod_radio_reg(pi,
+				      RADIO_2056_RX_RSSI_MISC | RADIO_2056_RX1,
+				      RADIO_2056_VCM_MASK,
+				      pi->rssical_cache.
+				      rssical_radio_regs_5G[1]);
+		}
+
+		write_phy_reg(pi, 0x1a6,
+			      pi->rssical_cache.rssical_phyregs_5G[0]);
+		write_phy_reg(pi, 0x1ac,
+			      pi->rssical_cache.rssical_phyregs_5G[1]);
+		write_phy_reg(pi, 0x1b2,
+			      pi->rssical_cache.rssical_phyregs_5G[2]);
+		write_phy_reg(pi, 0x1b8,
+			      pi->rssical_cache.rssical_phyregs_5G[3]);
+		write_phy_reg(pi, 0x1a4,
+			      pi->rssical_cache.rssical_phyregs_5G[4]);
+		write_phy_reg(pi, 0x1aa,
+			      pi->rssical_cache.rssical_phyregs_5G[5]);
+		write_phy_reg(pi, 0x1b0,
+			      pi->rssical_cache.rssical_phyregs_5G[6]);
+		write_phy_reg(pi, 0x1b6,
+			      pi->rssical_cache.rssical_phyregs_5G[7]);
+		write_phy_reg(pi, 0x1a5,
+			      pi->rssical_cache.rssical_phyregs_5G[8]);
+		write_phy_reg(pi, 0x1ab,
+			      pi->rssical_cache.rssical_phyregs_5G[9]);
+		write_phy_reg(pi, 0x1b1,
+			      pi->rssical_cache.rssical_phyregs_5G[10]);
+		write_phy_reg(pi, 0x1b7,
+			      pi->rssical_cache.rssical_phyregs_5G[11]);
+	}
+}
+
+static u16
+wlc_phy_gen_load_samples_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+			      u8 dac_test_mode)
+{
+	u8 phy_bw, is_phybw40;
+	u16 num_samps, t, spur;
+	fixed theta = 0, rot = 0;
+	u32 tbl_len;
+	cs32 *tone_buf = NULL;
+
+	is_phybw40 = CHSPEC_IS40(pi->radio_chanspec);
+	phy_bw = (is_phybw40 == 1) ? 40 : 20;
+	tbl_len = (phy_bw << 3);
+
+	if (dac_test_mode == 1) {
+		spur = read_phy_reg(pi, 0x01);
+		spur = (spur >> 15) & 1;
+		phy_bw = (spur == 1) ? 82 : 80;
+		phy_bw = (is_phybw40 == 1) ? (phy_bw << 1) : phy_bw;
+
+		tbl_len = (phy_bw << 1);
+	}
+
+	tone_buf = kmalloc(sizeof(cs32) * tbl_len, GFP_ATOMIC);
+	if (tone_buf == NULL) {
+		return 0;
+	}
+
+	num_samps = (u16) tbl_len;
+	rot = FIXED((f_kHz * 36) / phy_bw) / 100;
+	theta = 0;
+
+	for (t = 0; t < num_samps; t++) {
+
+		wlc_phy_cordic(theta, &tone_buf[t]);
+
+		theta += rot;
+
+		tone_buf[t].q = (s32) FLOAT(tone_buf[t].q * max_val);
+		tone_buf[t].i = (s32) FLOAT(tone_buf[t].i * max_val);
+	}
+
+	wlc_phy_loadsampletable_nphy(pi, tone_buf, num_samps);
+
+	kfree(tone_buf);
+
+	return num_samps;
+}
+
+int
+wlc_phy_tx_tone_nphy(phy_info_t *pi, u32 f_kHz, u16 max_val,
+		     u8 iqmode, u8 dac_test_mode, bool modify_bbmult)
+{
+	u16 num_samps;
+	u16 loops = 0xffff;
+	u16 wait = 0;
+
+	num_samps =
+		wlc_phy_gen_load_samples_nphy(pi, f_kHz, max_val, dac_test_mode);
+	if (num_samps == 0) {
+		return BCME_ERROR;
+	}
+
+	wlc_phy_runsamples_nphy(pi, num_samps, loops, wait, iqmode,
+				dac_test_mode, modify_bbmult);
+
+	return BCME_OK;
+}
+
+static void
+wlc_phy_loadsampletable_nphy(phy_info_t *pi, cs32 *tone_buf,
+			     u16 num_samps)
+{
+	u16 t;
+	u32 *data_buf = NULL;
+
+	data_buf = kmalloc(sizeof(u32) * num_samps, GFP_ATOMIC);
+	if (data_buf == NULL) {
+		return;
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	for (t = 0; t < num_samps; t++) {
+		data_buf[t] = ((((unsigned int)tone_buf[t].i) & 0x3ff) << 10) |
+		    (((unsigned int)tone_buf[t].q) & 0x3ff);
+	}
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_SAMPLEPLAY, num_samps, 0, 32,
+				 data_buf);
+
+	kfree(data_buf);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void
+wlc_phy_runsamples_nphy(phy_info_t *pi, u16 num_samps, u16 loops,
+			u16 wait, u8 iqmode, u8 dac_test_mode,
+			bool modify_bbmult)
+{
+	u16 bb_mult;
+	u8 phy_bw, sample_cmd;
+	u16 orig_RfseqCoreActv;
+	u16 lpf_bw_ctl_override3, lpf_bw_ctl_override4, lpf_bw_ctl_miscreg3,
+	    lpf_bw_ctl_miscreg4;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phy_bw = 20;
+	if (CHSPEC_IS40(pi->radio_chanspec))
+		phy_bw = 40;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		lpf_bw_ctl_override3 = read_phy_reg(pi, 0x342) & (0x1 << 7);
+		lpf_bw_ctl_override4 = read_phy_reg(pi, 0x343) & (0x1 << 7);
+		if (lpf_bw_ctl_override3 | lpf_bw_ctl_override4) {
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+			    (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+			    (0x7 << 8);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = true;
+
+			lpf_bw_ctl_miscreg3 = read_phy_reg(pi, 0x340) &
+			    (0x7 << 8);
+			lpf_bw_ctl_miscreg4 = read_phy_reg(pi, 0x341) &
+			    (0x7 << 8);
+		}
+	}
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) == 0) {
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					&bb_mult);
+		pi->nphy_bb_mult_save =
+		    BB_MULT_VALID_MASK | (bb_mult & BB_MULT_MASK);
+	}
+
+	if (modify_bbmult) {
+		bb_mult = (phy_bw == 20) ? 100 : 71;
+		bb_mult = (bb_mult << 8) + bb_mult;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	write_phy_reg(pi, 0xc6, num_samps - 1);
+
+	if (loops != 0xffff) {
+		write_phy_reg(pi, 0xc4, loops - 1);
+	} else {
+		write_phy_reg(pi, 0xc4, loops);
+	}
+	write_phy_reg(pi, 0xc5, wait);
+
+	orig_RfseqCoreActv = read_phy_reg(pi, 0xa1);
+	or_phy_reg(pi, 0xa1, NPHY_RfseqMode_CoreActv_override);
+	if (iqmode) {
+
+		and_phy_reg(pi, 0xc2, 0x7FFF);
+
+		or_phy_reg(pi, 0xc2, 0x8000);
+	} else {
+
+		sample_cmd = (dac_test_mode == 1) ? 0x5 : 0x1;
+		write_phy_reg(pi, 0xc3, sample_cmd);
+	}
+
+	SPINWAIT(((read_phy_reg(pi, 0xa4) & 0x1) == 1), 1000);
+
+	write_phy_reg(pi, 0xa1, orig_RfseqCoreActv);
+}
+
+void wlc_phy_stopplayback_nphy(phy_info_t *pi)
+{
+	u16 playback_status;
+	u16 bb_mult;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	playback_status = read_phy_reg(pi, 0xc7);
+	if (playback_status & 0x1) {
+		or_phy_reg(pi, 0xc3, NPHY_sampleCmd_STOP);
+	} else if (playback_status & 0x2) {
+
+		and_phy_reg(pi, 0xc2,
+			    (u16) ~NPHY_iqloCalCmdGctl_IQLO_CAL_EN);
+	}
+
+	and_phy_reg(pi, 0xc3, (u16) ~(0x1 << 2));
+
+	if ((pi->nphy_bb_mult_save & BB_MULT_VALID_MASK) != 0) {
+
+		bb_mult = pi->nphy_bb_mult_save & BB_MULT_MASK;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, 87, 16,
+					 &bb_mult);
+
+		pi->nphy_bb_mult_save = 0;
+	}
+
+	if (NREV_IS(pi->pubpi.phy_rev, 7) || NREV_GE(pi->pubpi.phy_rev, 8)) {
+		if (pi->nphy_sample_play_lpf_bw_ctl_ovr) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  0, 0, 1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+			pi->nphy_sample_play_lpf_bw_ctl_ovr = false;
+		}
+	}
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+nphy_txgains_t wlc_phy_get_tx_gain_nphy(phy_info_t *pi)
+{
+	u16 base_idx[2], curr_gain[2];
+	u8 core_no;
+	nphy_txgains_t target_gain;
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (pi->nphy_txpwrctrl == PHY_TPC_HW_OFF) {
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+					curr_gain);
+
+		if (pi->phyhang_avoid)
+			wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x0007;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x00F8) >> 3);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x7000) >> 12);
+				target_gain.txlpf[core_no] =
+				    ((curr_gain[core_no] & 0x8000) >> 15);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x000F;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x00F0) >> 4);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0F00) >> 8);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x7000) >> 12);
+			} else {
+				target_gain.ipa[core_no] =
+				    curr_gain[core_no] & 0x0003;
+				target_gain.pad[core_no] =
+				    ((curr_gain[core_no] & 0x000C) >> 2);
+				target_gain.pga[core_no] =
+				    ((curr_gain[core_no] & 0x0070) >> 4);
+				target_gain.txgm[core_no] =
+				    ((curr_gain[core_no] & 0x0380) >> 7);
+			}
+		}
+	} else {
+		base_idx[0] = (read_phy_reg(pi, 0x1ed) >> 8) & 0x7f;
+		base_idx[1] = (read_phy_reg(pi, 0x1ee) >> 8) & 0x7f;
+		for (core_no = 0; core_no < 2; core_no++) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				if (PHY_IPA(pi)) {
+					tx_pwrctrl_tbl =
+					    wlc_phy_get_ipa_gaintbl_nphy(pi);
+				} else {
+					if (CHSPEC_IS5G(pi->radio_chanspec)) {
+						if NREV_IS
+							(pi->pubpi.phy_rev, 3) {
+							tx_pwrctrl_tbl =
+							    nphy_tpc_5GHz_txgain_rev3;
+						} else if NREV_IS
+							(pi->pubpi.phy_rev, 4) {
+							tx_pwrctrl_tbl =
+							    (pi->srom_fem5g.
+							     extpagain ==
+							     3) ?
+							    nphy_tpc_5GHz_txgain_HiPwrEPA
+							    :
+							    nphy_tpc_5GHz_txgain_rev4;
+						} else {
+							tx_pwrctrl_tbl =
+							    nphy_tpc_5GHz_txgain_rev5;
+						}
+					} else {
+						if (NREV_GE
+						    (pi->pubpi.phy_rev, 7)) {
+							if (pi->pubpi.
+							    radiorev == 3) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_epa_2057rev3;
+							} else if (pi->pubpi.
+								   radiorev ==
+								   5) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_epa_2057rev5;
+							}
+
+						} else {
+							if (NREV_GE
+							    (pi->pubpi.phy_rev,
+							     5)
+							    && (pi->srom_fem2g.
+								extpagain ==
+								3)) {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_HiPwrEPA;
+							} else {
+								tx_pwrctrl_tbl =
+								    nphy_tpc_txgain_rev3;
+							}
+						}
+					}
+				}
+				if NREV_GE
+					(pi->pubpi.phy_rev, 7) {
+					target_gain.ipa[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 16) & 0x7;
+					target_gain.pad[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 19) & 0x1f;
+					target_gain.pga[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 28) & 0x7;
+					target_gain.txlpf[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 31) & 0x1;
+				} else {
+					target_gain.ipa[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 16) & 0xf;
+					target_gain.pad[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 20) & 0xf;
+					target_gain.pga[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 24) & 0xf;
+					target_gain.txgm[core_no] =
+					    (tx_pwrctrl_tbl[base_idx[core_no]]
+					     >> 28) & 0x7;
+				}
+			} else {
+				target_gain.ipa[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 16) &
+				    0x3;
+				target_gain.pad[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 18) &
+				    0x3;
+				target_gain.pga[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 20) &
+				    0x7;
+				target_gain.txgm[core_no] =
+				    (nphy_tpc_txgain[base_idx[core_no]] >> 23) &
+				    0x7;
+			}
+		}
+	}
+
+	return target_gain;
+}
+
+static void
+wlc_phy_iqcal_gainparams_nphy(phy_info_t *pi, u16 core_no,
+			      nphy_txgains_t target_gain,
+			      nphy_iqcal_params_t *params)
+{
+	u8 k;
+	int idx;
+	u16 gain_index;
+	u8 band_idx = (CHSPEC_IS5G(pi->radio_chanspec) ? 1 : 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			params->txlpf = target_gain.txlpf[core_no];
+		}
+		params->txgm = target_gain.txgm[core_no];
+		params->pga = target_gain.pga[core_no];
+		params->pad = target_gain.pad[core_no];
+		params->ipa = target_gain.ipa[core_no];
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			params->cal_gain =
+			    ((params->txlpf << 15) | (params->
+						      txgm << 12) | (params->
+								     pga << 8) |
+			     (params->pad << 3) | (params->ipa));
+		} else {
+			params->cal_gain =
+			    ((params->txgm << 12) | (params->
+						     pga << 8) | (params->
+								  pad << 4) |
+			     (params->ipa));
+		}
+		params->ncorr[0] = 0x79;
+		params->ncorr[1] = 0x79;
+		params->ncorr[2] = 0x79;
+		params->ncorr[3] = 0x79;
+		params->ncorr[4] = 0x79;
+	} else {
+
+		gain_index = ((target_gain.pad[core_no] << 0) |
+			      (target_gain.pga[core_no] << 4) | (target_gain.
+								 txgm[core_no]
+								 << 8));
+
+		idx = -1;
+		for (k = 0; k < NPHY_IQCAL_NUMGAINS; k++) {
+			if (tbl_iqcal_gainparams_nphy[band_idx][k][0] ==
+			    gain_index) {
+				idx = k;
+				break;
+			}
+		}
+
+		ASSERT(idx != -1);
+
+		params->txgm = tbl_iqcal_gainparams_nphy[band_idx][k][1];
+		params->pga = tbl_iqcal_gainparams_nphy[band_idx][k][2];
+		params->pad = tbl_iqcal_gainparams_nphy[band_idx][k][3];
+		params->cal_gain = ((params->txgm << 7) | (params->pga << 4) |
+				    (params->pad << 2));
+		params->ncorr[0] = tbl_iqcal_gainparams_nphy[band_idx][k][4];
+		params->ncorr[1] = tbl_iqcal_gainparams_nphy[band_idx][k][5];
+		params->ncorr[2] = tbl_iqcal_gainparams_nphy[band_idx][k][6];
+		params->ncorr[3] = tbl_iqcal_gainparams_nphy[band_idx][k][7];
+	}
+}
+
+static void wlc_phy_txcal_radio_setup_nphy(phy_info_t *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core <= 1; core++) {
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TX_SSI_MASTER);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    IQCAL_VCM_HG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    IQCAL_IDAC);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] = 0;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TX_SSI_MUX);
+
+			if (pi->pubpi.radiorev != 5)
+				pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+				    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+						    TSSIA);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TSSI_MISC1);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x0a);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIG, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX, 0x4);
+					if (!
+					    (pi->
+					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x31);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIA, 0x21);
+					}
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TX_SSI_MASTER, 0x06);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_VCM_HG, 0x43);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 IQCAL_IDAC, 0x55);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_VCM, 0x00);
+
+				if (pi->pubpi.radiorev != 5)
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TSSIA, 0x00);
+				if (pi->use_int_tx_iqlo_cal_nphy) {
+					WRITE_RADIO_REG3(pi, RADIO_2057, TX,
+							 core, TX_SSI_MUX,
+							 0x06);
+					if (!
+					    (pi->
+					     internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x31);
+					} else {
+
+						WRITE_RADIO_REG3(pi, RADIO_2057,
+								 TX, core,
+								 TSSIG, 0x21);
+					}
+				}
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSI_MISC1, 0x00);
+			}
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+			    (core ==
+			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_SSI_MASTER |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_IQCAL_VCM_HG |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 2] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_IQCAL_IDAC |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 3] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_VCM | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 4] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_AMP_DET |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 5] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TX_SSI_MUX |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 6] =
+			    read_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 7] =
+			    read_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 8] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC1 |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 9] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC2 |
+					   jtag_core);
+
+			pi->tx_rx_cal_radio_saveregs[(core * 11) + 10] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_TSSI_MISC3 |
+					   jtag_core);
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x0a);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+
+				if (PHY_IPA(pi)) {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x4);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x1);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIA |
+							jtag_core, 0x2f);
+				}
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIG | jtag_core,
+						0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			} else {
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_SSI_MASTER |
+						jtag_core, 0x06);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_VCM_HG |
+						jtag_core, 0x40);
+				write_radio_reg(pi,
+						RADIO_2056_TX_IQCAL_IDAC |
+						jtag_core, 0x55);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_VCM |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TX_AMP_DET |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSIA | jtag_core,
+						0x00);
+
+				if (PHY_IPA(pi)) {
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x06);
+					if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+
+						write_radio_reg(pi,
+								RADIO_2056_TX_TSSIG
+								| jtag_core,
+								0x11);
+					} else {
+
+						write_radio_reg(pi,
+								RADIO_2056_TX_TSSIG
+								| jtag_core,
+								0x1);
+					}
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_TX_TX_SSI_MUX
+							| jtag_core, 0x00);
+					write_radio_reg(pi,
+							RADIO_2056_TX_TSSIG |
+							jtag_core, 0x20);
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC1 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC2 |
+						jtag_core, 0x00);
+				write_radio_reg(pi,
+						RADIO_2056_TX_TSSI_MISC3 |
+						jtag_core, 0x00);
+			}
+		}
+	} else {
+
+		pi->tx_rx_cal_radio_saveregs[0] =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[1] =
+		    read_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[2] =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1, 0x29);
+		pi->tx_rx_cal_radio_saveregs[3] =
+		    read_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2, 0x54);
+
+		pi->tx_rx_cal_radio_saveregs[4] =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1);
+		pi->tx_rx_cal_radio_saveregs[5] =
+		    read_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2);
+
+		if ((read_phy_reg(pi, 0x09) & NPHY_BandControl_currentBand) ==
+		    0) {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x04);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x04);
+		} else {
+
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1, 0x20);
+			write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2, 0x20);
+		}
+
+		if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+			or_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0x20);
+			or_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0x20);
+		} else {
+
+			and_radio_reg(pi, RADIO_2055_CORE1_TX_BB_MXGM, 0xdf);
+			and_radio_reg(pi, RADIO_2055_CORE2_TX_BB_MXGM, 0xdf);
+		}
+	}
+}
+
+static void wlc_phy_txcal_radio_cleanup_nphy(phy_info_t *pi)
+{
+	u16 jtag_core, core;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		for (core = 0; core <= 1; core++) {
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TX_SSI_MASTER,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  0]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_VCM_HG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  1]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, IQCAL_IDAC,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  2]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_VCM,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  3]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TX_SSI_MUX,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  5]);
+
+			if (pi->pubpi.radiorev != 5)
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TSSIA,
+						 pi->
+						 tx_rx_cal_radio_saveregs[(core
+									   *
+									   11) +
+									  6]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSIG,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  7]);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core, TSSI_MISC1,
+					 pi->
+					 tx_rx_cal_radio_saveregs[(core * 11) +
+								  8]);
+		}
+	} else if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		for (core = 0; core <= 1; core++) {
+			jtag_core =
+			    (core ==
+			     PHY_CORE_0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MASTER | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_VCM_HG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 1]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_IQCAL_IDAC | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 2]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSI_VCM | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 3]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_AMP_DET | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 4]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TX_SSI_MUX | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 5]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIA | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 6]);
+
+			write_radio_reg(pi, RADIO_2056_TX_TSSIG | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 7]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC1 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 8]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC2 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 9]);
+
+			write_radio_reg(pi,
+					RADIO_2056_TX_TSSI_MISC3 | jtag_core,
+					pi->
+					tx_rx_cal_radio_saveregs[(core * 11) +
+								 10]);
+		}
+	} else {
+
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[0]);
+		write_radio_reg(pi, RADIO_2055_CORE1_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[1]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL1,
+				pi->tx_rx_cal_radio_saveregs[2]);
+		write_radio_reg(pi, RADIO_2055_CORE2_TXRF_IQCAL2,
+				pi->tx_rx_cal_radio_saveregs[3]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE1,
+				pi->tx_rx_cal_radio_saveregs[4]);
+		write_radio_reg(pi, RADIO_2055_PWRDET_RXTX_CORE2,
+				pi->tx_rx_cal_radio_saveregs[5]);
+	}
+}
+
+static void wlc_phy_txcal_physetup_nphy(phy_info_t *pi)
+{
+	u16 val, mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 8) | (0x3 << 10));
+		val = (0x2 << 8);
+		val |= (0x2 << 10);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0x8f);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0x8f, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= ((0x1 << 9) | (0x1 << 10));
+		write_phy_reg(pi, 0xa5, val);
+
+		pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x01);
+		mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[5] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[6] = val;
+		val = 0;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0x92);
+
+		if (!(pi->use_int_tx_iqlo_cal_nphy)) {
+
+			wlc_phy_rfctrlintc_override_nphy(pi,
+							 NPHY_RfctrlIntc_override_PA,
+							 1,
+							 RADIO_MIMO_CORESEL_CORE1
+							 |
+							 RADIO_MIMO_CORESEL_CORE2);
+		} else {
+
+			wlc_phy_rfctrlintc_override_nphy(pi,
+							 NPHY_RfctrlIntc_override_PA,
+							 0,
+							 RADIO_MIMO_CORESEL_CORE1
+							 |
+							 RADIO_MIMO_CORESEL_CORE2);
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+
+		pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+		pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+		mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      1 << 4);
+
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						      1, 0);
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						      1, 0);
+				} else {
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+						      1, 0);
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+						      1, 0);
+				}
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(pi,
+								  (0x1 << 3), 0,
+								  0x3, 0,
+								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa6);
+		pi->tx_rx_cal_phy_saveregs[1] = read_phy_reg(pi, 0xa7);
+
+		mask = ((0x3 << 12) | (0x3 << 14));
+		val = (0x2 << 12);
+		val |= (0x2 << 14);
+		mod_phy_reg(pi, 0xa6, mask, val);
+		mod_phy_reg(pi, 0xa7, mask, val);
+
+		val = read_phy_reg(pi, 0xa5);
+		pi->tx_rx_cal_phy_saveregs[2] = val;
+		val |= ((0x1 << 12) | (0x1 << 13));
+		write_phy_reg(pi, 0xa5, val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[3] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &val);
+
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					&val);
+		pi->tx_rx_cal_phy_saveregs[4] = val;
+		val |= 0x2000;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &val);
+
+		pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x91);
+		pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x92);
+		val = CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 : 0x120;
+		write_phy_reg(pi, 0x91, val);
+		write_phy_reg(pi, 0x92, val);
+	}
+}
+
+static void wlc_phy_txcal_phycleanup_nphy(phy_info_t *pi)
+{
+	u16 mask;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		write_phy_reg(pi, 0xa6, pi->tx_rx_cal_phy_saveregs[0]);
+		write_phy_reg(pi, 0xa7, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0x8f, pi->tx_rx_cal_phy_saveregs[2]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[3]);
+		write_phy_reg(pi, 0x01, pi->tx_rx_cal_phy_saveregs[4]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 3, 16,
+					 &pi->tx_rx_cal_phy_saveregs[5]);
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 19, 16,
+					 &pi->tx_rx_cal_phy_saveregs[6]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[7]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[8]);
+
+		write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+		write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
+							  1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		wlc_phy_resetcca_nphy(pi);
+
+		if (pi->use_int_tx_iqlo_cal_nphy
+		    && !(pi->internal_tx_iqlo_cal_tapoff_intpa_nphy)) {
+
+			if (NREV_IS(pi->pubpi.phy_rev, 7)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE0,
+						      1, 1);
+					mod_radio_reg(pi,
+						      RADIO_2057_PAD2G_TUNE_PUS_CORE1,
+						      1, 1);
+				} else {
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE0,
+						      1, 1);
+					mod_radio_reg(pi,
+						      RADIO_2057_IPA5G_CASCOFFV_PU_CORE1,
+						      1, 1);
+				}
+
+				mod_radio_reg(pi, RADIO_2057_OVR_REG0, 1 << 4,
+					      0);
+			} else if (NREV_GE(pi->pubpi.phy_rev, 8)) {
+				wlc_phy_rfctrl_override_nphy_rev7(pi,
+								  (0x1 << 3), 0,
+								  0x3, 1,
+								  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+			}
+		}
+	} else {
+		mask = ((0x3 << 12) | (0x3 << 14));
+		mod_phy_reg(pi, 0xa6, mask, pi->tx_rx_cal_phy_saveregs[0]);
+		mod_phy_reg(pi, 0xa7, mask, pi->tx_rx_cal_phy_saveregs[1]);
+		write_phy_reg(pi, 0xa5, pi->tx_rx_cal_phy_saveregs[2]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 2, 16,
+					 &pi->tx_rx_cal_phy_saveregs[3]);
+
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_AFECTRL, 1, 18, 16,
+					 &pi->tx_rx_cal_phy_saveregs[4]);
+
+		write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[5]);
+		write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[6]);
+	}
+}
+
+#define NPHY_CAL_TSSISAMPS	64
+#define NPHY_TEST_TONE_FREQ_40MHz 4000
+#define NPHY_TEST_TONE_FREQ_20MHz 2500
+
+void
+wlc_phy_est_tonepwr_nphy(phy_info_t *pi, s32 *qdBm_pwrbuf, u8 num_samps)
+{
+	u16 tssi_reg;
+	s32 temp, pwrindex[2];
+	s32 idle_tssi[2];
+	s32 rssi_buf[4];
+	s32 tssival[2];
+	u8 tssi_type;
+
+	tssi_reg = read_phy_reg(pi, 0x1e9);
+
+	temp = (s32) (tssi_reg & 0x3f);
+	idle_tssi[0] = (temp <= 31) ? temp : (temp - 64);
+
+	temp = (s32) ((tssi_reg >> 8) & 0x3f);
+	idle_tssi[1] = (temp <= 31) ? temp : (temp - 64);
+
+	tssi_type =
+	    CHSPEC_IS5G(pi->radio_chanspec) ?
+	    (u8)NPHY_RSSI_SEL_TSSI_5G:(u8)NPHY_RSSI_SEL_TSSI_2G;
+
+	wlc_phy_poll_rssi_nphy(pi, tssi_type, rssi_buf, num_samps);
+
+	tssival[0] = rssi_buf[0] / ((s32) num_samps);
+	tssival[1] = rssi_buf[2] / ((s32) num_samps);
+
+	pwrindex[0] = idle_tssi[0] - tssival[0] + 64;
+	pwrindex[1] = idle_tssi[1] - tssival[1] + 64;
+
+	if (pwrindex[0] < 0) {
+		pwrindex[0] = 0;
+	} else if (pwrindex[0] > 63) {
+		pwrindex[0] = 63;
+	}
+
+	if (pwrindex[1] < 0) {
+		pwrindex[1] = 0;
+	} else if (pwrindex[1] > 63) {
+		pwrindex[1] = 63;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE1TXPWRCTL, 1,
+				(u32) pwrindex[0], 32, &qdBm_pwrbuf[0]);
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_CORE2TXPWRCTL, 1,
+				(u32) pwrindex[1], 32, &qdBm_pwrbuf[1]);
+}
+
+static void wlc_phy_internal_cal_txgain_nphy(phy_info_t *pi)
+{
+	u16 txcal_gain[2];
+
+	pi->nphy_txcal_pwr_idx[0] = pi->nphy_cal_orig_pwr_idx[0];
+	pi->nphy_txcal_pwr_idx[1] = pi->nphy_cal_orig_pwr_idx[0];
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				txcal_gain);
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F40;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F40;
+	} else {
+		txcal_gain[0] = (txcal_gain[0] & 0xF000) | 0x0F60;
+		txcal_gain[1] = (txcal_gain[1] & 0xF000) | 0x0F60;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 txcal_gain);
+}
+
+static void wlc_phy_precal_txgain_nphy(phy_info_t *pi)
+{
+	bool save_bbmult = false;
+	u8 txcal_index_2057_rev5n7 = 0;
+	u8 txcal_index_2057_rev3n4n6 = 10;
+
+	if (pi->use_int_tx_iqlo_cal_nphy) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				pi->nphy_txcal_pwr_idx[0] =
+				    txcal_index_2057_rev3n4n6;
+				pi->nphy_txcal_pwr_idx[1] =
+				    txcal_index_2057_rev3n4n6;
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 txcal_index_2057_rev3n4n6,
+							 false);
+			} else {
+
+				pi->nphy_txcal_pwr_idx[0] =
+				    txcal_index_2057_rev5n7;
+				pi->nphy_txcal_pwr_idx[1] =
+				    txcal_index_2057_rev5n7;
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 txcal_index_2057_rev5n7,
+							 false);
+			}
+			save_bbmult = true;
+
+		} else if (NREV_LT(pi->pubpi.phy_rev, 5)) {
+			wlc_phy_cal_txgainctrl_nphy(pi, 11, false);
+			if (pi->sh->hw_phytxchain != 3) {
+				pi->nphy_txcal_pwr_idx[1] =
+				    pi->nphy_txcal_pwr_idx[0];
+				wlc_phy_txpwr_index_nphy(pi, 3,
+							 pi->
+							 nphy_txcal_pwr_idx[0],
+							 true);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					pi->nphy_txcal_pwr_idx[0] = 80;
+					pi->nphy_txcal_pwr_idx[1] = 80;
+					wlc_phy_txpwr_index_nphy(pi, 3, 80,
+								 false);
+					save_bbmult = true;
+				}
+			} else {
+
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+			if (PHY_IPA(pi)) {
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					wlc_phy_cal_txgainctrl_nphy(pi, 12,
+								    false);
+				} else {
+					wlc_phy_cal_txgainctrl_nphy(pi, 14,
+								    false);
+				}
+			} else {
+
+				wlc_phy_internal_cal_txgain_nphy(pi);
+				save_bbmult = true;
+			}
+		}
+
+	} else {
+		wlc_phy_cal_txgainctrl_nphy(pi, 10, false);
+	}
+
+	if (save_bbmult) {
+		wlc_phy_table_read_nphy(pi, 15, 1, 87, 16,
+					&pi->nphy_txcal_bbmult);
+	}
+}
+
+void
+wlc_phy_cal_txgainctrl_nphy(phy_info_t *pi, s32 dBm_targetpower, bool debug)
+{
+	int gainctrl_loopidx;
+	uint core;
+	u16 m0m1, curr_m0m1;
+	s32 delta_power;
+	s32 txpwrindex;
+	s32 qdBm_power[2];
+	u16 orig_BBConfig;
+	u16 phy_saveregs[4];
+	u32 freq_test;
+	u16 ampl_test = 250;
+	uint stepsize;
+	bool phyhang_avoid_state = false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		stepsize = 2;
+	} else {
+
+		stepsize = 1;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		freq_test = 5000;
+	} else {
+		freq_test = 2500;
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_cal_orig_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_cal_orig_pwr_idx[1], true);
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	phyhang_avoid_state = pi->phyhang_avoid;
+	pi->phyhang_avoid = false;
+
+	phy_saveregs[0] = read_phy_reg(pi, 0x91);
+	phy_saveregs[1] = read_phy_reg(pi, 0x92);
+	phy_saveregs[2] = read_phy_reg(pi, 0xe7);
+	phy_saveregs[3] = read_phy_reg(pi, 0xec);
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 1,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (!debug) {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x2, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x8, RADIO_MIMO_CORESEL_CORE2);
+	} else {
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, RADIO_MIMO_CORESEL_CORE1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x7, RADIO_MIMO_CORESEL_CORE2);
+	}
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+		txpwrindex = (s32) pi->nphy_cal_orig_pwr_idx[core];
+
+		for (gainctrl_loopidx = 0; gainctrl_loopidx < 2;
+		     gainctrl_loopidx++) {
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			if (core == PHY_CORE_0) {
+				curr_m0m1 = m0m1 & 0xff00;
+			} else {
+				curr_m0m1 = m0m1 & 0x00ff;
+			}
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &curr_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &curr_m0m1);
+
+			udelay(50);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+
+			delta_power = (dBm_targetpower * 4) - qdBm_power[core];
+
+			txpwrindex -= stepsize * delta_power;
+			if (txpwrindex < 0) {
+				txpwrindex = 0;
+			} else if (txpwrindex > 127) {
+				txpwrindex = 127;
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (NREV_IS(pi->pubpi.phy_rev, 4) &&
+				    (pi->srom_fem5g.extpagain == 3)) {
+					if (txpwrindex < 30) {
+						txpwrindex = 30;
+					}
+				}
+			} else {
+				if (NREV_GE(pi->pubpi.phy_rev, 5) &&
+				    (pi->srom_fem2g.extpagain == 3)) {
+					if (txpwrindex < 50) {
+						txpwrindex = 50;
+					}
+				}
+			}
+
+			wlc_phy_txpwr_index_nphy(pi, (1 << core),
+						 (u8) txpwrindex, true);
+		}
+
+		pi->nphy_txcal_pwr_idx[core] = (u8) txpwrindex;
+
+		if (debug) {
+			u16 radio_gain;
+			u16 dbg_m0m1;
+
+			wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+
+			wlc_phy_tx_tone_nphy(pi, freq_test, ampl_test, 0, 0,
+					     false);
+
+			wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &dbg_m0m1);
+			wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &dbg_m0m1);
+
+			udelay(100);
+
+			wlc_phy_est_tonepwr_nphy(pi, qdBm_power,
+						 NPHY_CAL_TSSISAMPS);
+
+			wlc_phy_table_read_nphy(pi, 7, 1, (0x110 + core), 16,
+						&radio_gain);
+
+			mdelay(4000);
+			pi->nphy_bb_mult_save = 0;
+			wlc_phy_stopplayback_nphy(pi);
+		}
+	}
+
+	wlc_phy_txpwr_index_nphy(pi, 1, pi->nphy_txcal_pwr_idx[0], true);
+	wlc_phy_txpwr_index_nphy(pi, 2, pi->nphy_txcal_pwr_idx[1], true);
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &pi->nphy_txcal_bbmult);
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	write_phy_reg(pi, 0x91, phy_saveregs[0]);
+	write_phy_reg(pi, 0x92, phy_saveregs[1]);
+	write_phy_reg(pi, 0xe7, phy_saveregs[2]);
+	write_phy_reg(pi, 0xec, phy_saveregs[3]);
+
+	pi->phyhang_avoid = phyhang_avoid_state;
+
+	if (pi->phyhang_avoid)
+		wlc_phy_stay_in_carriersearch_nphy(pi, false);
+}
+
+static void wlc_phy_update_txcal_ladder_nphy(phy_info_t *pi, u16 core)
+{
+	int index;
+	u32 bbmult_scale;
+	u16 bbmult;
+	u16 tblentry;
+
+	nphy_txiqcal_ladder_t ladder_lo[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {25, 1}, {25, 2}, {25, 3}, {25, 4}, {25, 5},
+		{25, 6}, {25, 7}, {35, 7}, {50, 7}, {71, 7}, {100, 7}
+	};
+
+	nphy_txiqcal_ladder_t ladder_iq[] = {
+		{3, 0}, {4, 0}, {6, 0}, {9, 0}, {13, 0}, {18, 0},
+		{25, 0}, {35, 0}, {50, 0}, {71, 0}, {100, 0}, {100, 1},
+		{100, 2}, {100, 3}, {100, 4}, {100, 5}, {100, 6}, {100, 7}
+	};
+
+	bbmult = (core == PHY_CORE_0) ?
+	    ((pi->nphy_txcal_bbmult >> 8) & 0xff) : (pi->
+						     nphy_txcal_bbmult & 0xff);
+
+	for (index = 0; index < 18; index++) {
+		bbmult_scale = ladder_lo[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+		    ((bbmult_scale & 0xff) << 8) | ladder_lo[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index, 16,
+					 &tblentry);
+
+		bbmult_scale = ladder_iq[index].percent * bbmult;
+		bbmult_scale /= 100;
+
+		tblentry =
+		    ((bbmult_scale & 0xff) << 8) | ladder_iq[index].g_env;
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 1, index + 32,
+					 16, &tblentry);
+	}
+}
+
+void wlc_phy_cal_perical_nphy_run(phy_info_t *pi, u8 caltype)
+{
+	nphy_txgains_t target_gain;
+	u8 tx_pwr_ctrl_state;
+	bool fullcal = true;
+	bool restore_tx_gain = false;
+	bool mphase;
+
+	if (NORADIO_ENAB(pi->pubpi)) {
+		wlc_phy_cal_perical_mphase_reset(pi);
+		return;
+	}
+
+	if (PHY_MUTED(pi))
+		return;
+
+	ASSERT(pi->nphy_perical != PHY_PERICAL_DISABLE);
+
+	if (caltype == PHY_PERICAL_AUTO)
+		fullcal = (pi->radio_chanspec != pi->nphy_txiqlocal_chanspec);
+	else if (caltype == PHY_PERICAL_PARTIAL)
+		fullcal = false;
+
+	if (pi->cal_type_override != PHY_PERICAL_AUTO) {
+		fullcal =
+		    (pi->cal_type_override == PHY_PERICAL_FULL) ? true : false;
+	}
+
+	if ((pi->mphase_cal_phase_id > MPHASE_CAL_STATE_INIT)) {
+		if (pi->nphy_txiqlocal_chanspec != pi->radio_chanspec)
+			wlc_phy_cal_perical_mphase_restart(pi);
+	}
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_RXCAL)) {
+		wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION, 10000);
+	}
+
+	wlapi_suspend_mac_and_wait(pi->sh->physhim);
+
+	wlc_phyreg_enter((wlc_phy_t *) pi);
+
+	if ((pi->mphase_cal_phase_id == MPHASE_CAL_STATE_IDLE) ||
+	    (pi->mphase_cal_phase_id == MPHASE_CAL_STATE_INIT)) {
+		pi->nphy_cal_orig_pwr_idx[0] =
+		    (u8) ((read_phy_reg(pi, 0x1ed) >> 8) & 0x7f);
+		pi->nphy_cal_orig_pwr_idx[1] =
+		    (u8) ((read_phy_reg(pi, 0x1ee) >> 8) & 0x7f);
+
+		if (pi->nphy_txpwrctrl != PHY_TPC_HW_OFF) {
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2,
+						0x110, 16,
+						pi->nphy_cal_orig_tx_gain);
+		} else {
+			pi->nphy_cal_orig_tx_gain[0] = 0;
+			pi->nphy_cal_orig_tx_gain[1] = 0;
+		}
+	}
+	target_gain = wlc_phy_get_tx_gain_nphy(pi);
+	tx_pwr_ctrl_state = pi->nphy_txpwrctrl;
+	wlc_phy_txpwrctrl_enable_nphy(pi, PHY_TPC_HW_OFF);
+
+	if (pi->antsel_type == ANTSEL_2x3)
+		wlc_phy_antsel_init((wlc_phy_t *) pi, true);
+
+	mphase = (pi->mphase_cal_phase_id != MPHASE_CAL_STATE_IDLE);
+	if (!mphase) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_precal_txgain_nphy(pi);
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			restore_tx_gain = true;
+
+			target_gain = pi->nphy_cal_target_gain;
+		}
+		if (BCME_OK ==
+		    wlc_phy_cal_txiqlo_nphy(pi, target_gain, fullcal, mphase)) {
+			if (PHY_IPA(pi))
+				wlc_phy_a4(pi, true);
+
+			wlc_phyreg_exit((wlc_phy_t *) pi);
+			wlapi_enable_mac(pi->sh->physhim);
+			wlapi_bmac_write_shm(pi->sh->physhim, M_CTS_DURATION,
+					     10000);
+			wlapi_suspend_mac_and_wait(pi->sh->physhim);
+			wlc_phyreg_enter((wlc_phy_t *) pi);
+
+			if (BCME_OK == wlc_phy_cal_rxiq_nphy(pi, target_gain,
+							     (pi->
+							      first_cal_after_assoc
+							      || (pi->
+								  cal_type_override
+								  ==
+								  PHY_PERICAL_FULL))
+							     ? 2 : 0, false)) {
+				wlc_phy_savecal_nphy(pi);
+
+				wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+
+				pi->nphy_perical_last = pi->sh->now;
+			}
+		}
+		if (caltype != PHY_PERICAL_AUTO) {
+			wlc_phy_rssi_cal_nphy(pi);
+		}
+
+		if (pi->first_cal_after_assoc
+		    || (pi->cal_type_override == PHY_PERICAL_FULL)) {
+			pi->first_cal_after_assoc = false;
+			wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+			wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+		}
+
+		if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+			wlc_phy_radio205x_vcocal_nphy(pi);
+		}
+	} else {
+		ASSERT(pi->nphy_perical >= PHY_PERICAL_MPHASE);
+
+		switch (pi->mphase_cal_phase_id) {
+		case MPHASE_CAL_STATE_INIT:
+			pi->nphy_perical_last = pi->sh->now;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				wlc_phy_precal_txgain_nphy(pi);
+			}
+			pi->nphy_cal_target_gain = wlc_phy_get_tx_gain_nphy(pi);
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_TXPHASE0:
+		case MPHASE_CAL_STATE_TXPHASE1:
+		case MPHASE_CAL_STATE_TXPHASE2:
+		case MPHASE_CAL_STATE_TXPHASE3:
+		case MPHASE_CAL_STATE_TXPHASE4:
+		case MPHASE_CAL_STATE_TXPHASE5:
+			if ((pi->radar_percal_mask & 0x10) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (wlc_phy_cal_txiqlo_nphy
+			    (pi, pi->nphy_cal_target_gain, fullcal,
+			     true) != BCME_OK) {
+
+				wlc_phy_cal_perical_mphase_reset(pi);
+				break;
+			}
+
+			if (NREV_LE(pi->pubpi.phy_rev, 2) &&
+			    (pi->mphase_cal_phase_id ==
+			     MPHASE_CAL_STATE_TXPHASE4)) {
+				pi->mphase_cal_phase_id += 2;
+			} else {
+				pi->mphase_cal_phase_id++;
+			}
+			break;
+
+		case MPHASE_CAL_STATE_PAPDCAL:
+			if ((pi->radar_percal_mask & 0x2) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (PHY_IPA(pi)) {
+				wlc_phy_a4(pi, true);
+			}
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RXCAL:
+			if ((pi->radar_percal_mask & 0x1) != 0)
+				pi->nphy_rxcal_active = true;
+			if (wlc_phy_cal_rxiq_nphy(pi, target_gain,
+						  (pi->first_cal_after_assoc ||
+						   (pi->cal_type_override ==
+						    PHY_PERICAL_FULL)) ? 2 : 0,
+						  false) == BCME_OK) {
+				wlc_phy_savecal_nphy(pi);
+			}
+
+			pi->mphase_cal_phase_id++;
+			break;
+
+		case MPHASE_CAL_STATE_RSSICAL:
+			if ((pi->radar_percal_mask & 0x4) != 0)
+				pi->nphy_rxcal_active = true;
+			wlc_phy_txpwrctrl_coeff_setup_nphy(pi);
+			wlc_phy_rssi_cal_nphy(pi);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				wlc_phy_radio205x_vcocal_nphy(pi);
+			}
+			restore_tx_gain = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->mphase_cal_phase_id++;
+			} else {
+				wlc_phy_cal_perical_mphase_reset(pi);
+			}
+
+			break;
+
+		case MPHASE_CAL_STATE_IDLETSSI:
+			if ((pi->radar_percal_mask & 0x8) != 0)
+				pi->nphy_rxcal_active = true;
+
+			if (pi->first_cal_after_assoc) {
+				pi->first_cal_after_assoc = false;
+				wlc_phy_txpwrctrl_idle_tssi_nphy(pi);
+				wlc_phy_txpwrctrl_pwr_setup_nphy(pi);
+			}
+
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+
+		default:
+			ASSERT(0);
+			wlc_phy_cal_perical_mphase_reset(pi);
+			break;
+		}
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		if (restore_tx_gain) {
+			if (tx_pwr_ctrl_state != PHY_TPC_HW_OFF) {
+
+				wlc_phy_txpwr_index_nphy(pi, 1,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [0], false);
+				wlc_phy_txpwr_index_nphy(pi, 2,
+							 pi->
+							 nphy_cal_orig_pwr_idx
+							 [1], false);
+
+				pi->nphy_txpwrindex[0].index = -1;
+				pi->nphy_txpwrindex[1].index = -1;
+			} else {
+				wlc_phy_txpwr_index_nphy(pi, (1 << 0),
+							 (s8) (pi->
+								 nphy_txpwrindex
+								 [0].
+								 index_internal),
+							 false);
+				wlc_phy_txpwr_index_nphy(pi, (1 << 1),
+							 (s8) (pi->
+								 nphy_txpwrindex
+								 [1].
+								 index_internal),
+							 false);
+			}
+		}
+	}
+
+	wlc_phy_txpwrctrl_enable_nphy(pi, tx_pwr_ctrl_state);
+	wlc_phyreg_exit((wlc_phy_t *) pi);
+	wlapi_enable_mac(pi->sh->physhim);
+}
+
+int
+wlc_phy_cal_txiqlo_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+			bool fullcal, bool mphase)
+{
+	u16 val;
+	u16 tbl_buf[11];
+	u8 cal_cnt;
+	u16 cal_cmd;
+	u8 num_cals, max_cal_cmds;
+	u16 core_no, cal_type;
+	u16 diq_start = 0;
+	u8 phy_bw;
+	u16 max_val;
+	u16 tone_freq;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	nphy_iqcal_params_t cal_params[2];
+	u32 tbl_len;
+	void *tbl_ptr;
+	bool ladder_updated[2];
+	u8 mphase_cal_lastphase = 0;
+	int bcmerror = BCME_OK;
+	bool phyhang_avoid_state = false;
+
+	u16 tbl_tx_iqlo_cal_loft_ladder_20[] = {
+		0x0300, 0x0500, 0x0700, 0x0900, 0x0d00, 0x1100, 0x1900, 0x1901,
+		    0x1902,
+		0x1903, 0x1904, 0x1905, 0x1906, 0x1907, 0x2407, 0x3207, 0x4607,
+		    0x6407
+	};
+
+	u16 tbl_tx_iqlo_cal_iqimb_ladder_20[] = {
+		0x0200, 0x0300, 0x0600, 0x0900, 0x0d00, 0x1100, 0x1900, 0x2400,
+		    0x3200,
+		0x4600, 0x6400, 0x6401, 0x6402, 0x6403, 0x6404, 0x6405, 0x6406,
+		    0x6407
+	};
+
+	u16 tbl_tx_iqlo_cal_loft_ladder_40[] = {
+		0x0200, 0x0300, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1201,
+		    0x1202,
+		0x1203, 0x1204, 0x1205, 0x1206, 0x1207, 0x1907, 0x2307, 0x3207,
+		    0x4707
+	};
+
+	u16 tbl_tx_iqlo_cal_iqimb_ladder_40[] = {
+		0x0100, 0x0200, 0x0400, 0x0700, 0x0900, 0x0c00, 0x1200, 0x1900,
+		    0x2300,
+		0x3200, 0x4700, 0x4701, 0x4702, 0x4703, 0x4704, 0x4705, 0x4706,
+		    0x4707
+	};
+
+	u16 tbl_tx_iqlo_cal_startcoefs[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		    0x0000
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_fullcal[] = {
+		0x8123, 0x8264, 0x8086, 0x8245, 0x8056,
+		0x9123, 0x9264, 0x9086, 0x9245, 0x9056
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_recal[] = {
+		0x8101, 0x8253, 0x8053, 0x8234, 0x8034,
+		0x9101, 0x9253, 0x9053, 0x9234, 0x9034
+	};
+
+	u16 tbl_tx_iqlo_cal_startcoefs_nphyrev3[] = {
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
+		0x0000
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[] = {
+		0x8434, 0x8334, 0x8084, 0x8267, 0x8056, 0x8234,
+		0x9434, 0x9334, 0x9084, 0x9267, 0x9056, 0x9234
+	};
+
+	u16 tbl_tx_iqlo_cal_cmds_recal_nphyrev3[] = {
+		0x8423, 0x8323, 0x8073, 0x8256, 0x8045, 0x8223,
+		0x9423, 0x9323, 0x9073, 0x9256, 0x9045, 0x9223
+	};
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		phy_bw = 40;
+	} else {
+		phy_bw = 20;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	wlc_phy_txcal_radio_setup_nphy(pi);
+
+	wlc_phy_txcal_physetup_nphy(pi);
+
+	ladder_updated[0] = ladder_updated[1] = false;
+	if (!(NREV_GE(pi->pubpi.phy_rev, 6) ||
+	      (NREV_IS(pi->pubpi.phy_rev, 5) && PHY_IPA(pi)
+	       && (CHSPEC_IS2G(pi->radio_chanspec))))) {
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_loft_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_loft_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 0,
+					 16, tbl_ptr);
+
+		if (phy_bw == 40) {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_40;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_40);
+		} else {
+			tbl_ptr = tbl_tx_iqlo_cal_iqimb_ladder_20;
+			tbl_len = ARRAY_SIZE(tbl_tx_iqlo_cal_iqimb_ladder_20);
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 32,
+					 16, tbl_ptr);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0xc2, 0x8ad9);
+	} else {
+		write_phy_reg(pi, 0xc2, 0x8aa9);
+	}
+
+	max_val = 250;
+	tone_freq = (phy_bw == 20) ? 2500 : 5000;
+
+	if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+		wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff, 0, 1, 0, false);
+		bcmerror = BCME_OK;
+	} else {
+		bcmerror =
+		    wlc_phy_tx_tone_nphy(pi, tone_freq, max_val, 1, 0, false);
+	}
+
+	if (bcmerror == BCME_OK) {
+
+		if (pi->mphase_cal_phase_id > MPHASE_CAL_STATE_TXPHASE0) {
+			tbl_ptr = pi->mphase_txcal_bestcoeffs;
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+		} else {
+			if ((!fullcal) && (pi->nphy_txiqlocal_coeffsvalid)) {
+
+				tbl_ptr = pi->nphy_txiqlocal_bestc;
+				tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+				if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+					tbl_len -= 2;
+				}
+			} else {
+
+				fullcal = true;
+
+				if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+					tbl_ptr =
+					    tbl_tx_iqlo_cal_startcoefs_nphyrev3;
+					tbl_len =
+					    ARRAY_SIZE
+					    (tbl_tx_iqlo_cal_startcoefs_nphyrev3);
+				} else {
+					tbl_ptr = tbl_tx_iqlo_cal_startcoefs;
+					tbl_len =
+					    ARRAY_SIZE
+					    (tbl_tx_iqlo_cal_startcoefs);
+				}
+			}
+		}
+		wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, tbl_len, 64,
+					 16, tbl_ptr);
+
+		if (fullcal) {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3) :
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_fullcal);
+		} else {
+			max_cal_cmds = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal_nphyrev3) :
+			    ARRAY_SIZE(tbl_tx_iqlo_cal_cmds_recal);
+		}
+
+		if (mphase) {
+			cal_cnt = pi->mphase_txcal_cmdidx;
+			if ((cal_cnt + pi->mphase_txcal_numcmds) < max_cal_cmds) {
+				num_cals = cal_cnt + pi->mphase_txcal_numcmds;
+			} else {
+				num_cals = max_cal_cmds;
+			}
+		} else {
+			cal_cnt = 0;
+			num_cals = max_cal_cmds;
+		}
+
+		for (; cal_cnt < num_cals; cal_cnt++) {
+
+			if (fullcal) {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				    tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3
+				    [cal_cnt] :
+				    tbl_tx_iqlo_cal_cmds_fullcal[cal_cnt];
+			} else {
+				cal_cmd = (NREV_GE(pi->pubpi.phy_rev, 3)) ?
+				    tbl_tx_iqlo_cal_cmds_recal_nphyrev3[cal_cnt]
+				    : tbl_tx_iqlo_cal_cmds_recal[cal_cnt];
+			}
+
+			core_no = ((cal_cmd & 0x3000) >> 12);
+			cal_type = ((cal_cmd & 0x0F00) >> 8);
+
+			if (NREV_GE(pi->pubpi.phy_rev, 6) ||
+			    (NREV_IS(pi->pubpi.phy_rev, 5) &&
+			     PHY_IPA(pi)
+			     && (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				if (!ladder_updated[core_no]) {
+					wlc_phy_update_txcal_ladder_nphy(pi,
+									 core_no);
+					ladder_updated[core_no] = true;
+				}
+			}
+
+			val =
+			    (cal_params[core_no].
+			     ncorr[cal_type] << 8) | NPHY_N_GCTL;
+			write_phy_reg(pi, 0xc1, val);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+							1, 69 + core_no, 16,
+							tbl_buf);
+
+				diq_start = tbl_buf[0];
+
+				tbl_buf[0] = 0;
+				wlc_phy_table_write_nphy(pi,
+							 NPHY_TBL_ID_IQLOCAL, 1,
+							 69 + core_no, 16,
+							 tbl_buf);
+			}
+
+			write_phy_reg(pi, 0xc0, cal_cmd);
+
+			SPINWAIT(((read_phy_reg(pi, 0xc0) & 0xc000) != 0),
+				 20000);
+			ASSERT((read_phy_reg(pi, 0xc0) & 0xc000) == 0);
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						 tbl_len, 64, 16, tbl_buf);
+
+			if ((cal_type == 1) || (cal_type == 3)
+			    || (cal_type == 4)) {
+
+				tbl_buf[0] = diq_start;
+
+			}
+
+		}
+
+		if (mphase) {
+			pi->mphase_txcal_cmdidx = num_cals;
+			if (pi->mphase_txcal_cmdidx >= max_cal_cmds)
+				pi->mphase_txcal_cmdidx = 0;
+		}
+
+		mphase_cal_lastphase =
+		    (NREV_LE(pi->pubpi.phy_rev, 2)) ?
+		    MPHASE_CAL_STATE_TXPHASE4 : MPHASE_CAL_STATE_TXPHASE5;
+
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase)) {
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 96,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, tbl_buf);
+
+			if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+				tbl_buf[0] = 0;
+				tbl_buf[1] = 0;
+				tbl_buf[2] = 0;
+				tbl_buf[3] = 0;
+
+			}
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 101,
+						16, tbl_buf);
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16, tbl_buf);
+
+			tbl_len = ARRAY_SIZE(pi->nphy_txiqlocal_bestc);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->nphy_txiqlocal_bestc);
+
+			pi->nphy_txiqlocal_coeffsvalid = true;
+			pi->nphy_txiqlocal_chanspec = pi->radio_chanspec;
+		} else {
+			tbl_len = ARRAY_SIZE(pi->mphase_txcal_bestcoeffs);
+			if (NREV_LT(pi->pubpi.phy_rev, 3)) {
+
+				tbl_len -= 2;
+			}
+			wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+						tbl_len, 96, 16,
+						pi->mphase_txcal_bestcoeffs);
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+
+		write_phy_reg(pi, 0xc2, 0x0000);
+
+	}
+
+	wlc_phy_txcal_phycleanup_nphy(pi);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_txcal_radio_cleanup_nphy(pi);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+		if (!mphase
+		    || (pi->mphase_cal_phase_id == mphase_cal_lastphase))
+			wlc_phy_tx_iq_war_nphy(pi);
+	}
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		pi->phyhang_avoid = phyhang_avoid_state;
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+static void wlc_phy_reapply_txcal_coeffs_nphy(phy_info_t *pi)
+{
+	u16 tbl_buf[7];
+
+	ASSERT(NREV_LT(pi->pubpi.phy_rev, 2));
+
+	if ((pi->nphy_txiqlocal_chanspec == pi->radio_chanspec) &&
+	    (pi->nphy_txiqlocal_coeffsvalid)) {
+		wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_IQLOCAL,
+					ARRAY_SIZE(tbl_buf), 80, 16, tbl_buf);
+
+		if ((pi->nphy_txiqlocal_bestc[0] != tbl_buf[0]) ||
+		    (pi->nphy_txiqlocal_bestc[1] != tbl_buf[1]) ||
+		    (pi->nphy_txiqlocal_bestc[2] != tbl_buf[2]) ||
+		    (pi->nphy_txiqlocal_bestc[3] != tbl_buf[3])) {
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 80,
+						 16, pi->nphy_txiqlocal_bestc);
+
+			tbl_buf[0] = 0;
+			tbl_buf[1] = 0;
+			tbl_buf[2] = 0;
+			tbl_buf[3] = 0;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 4, 88,
+						 16, tbl_buf);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 85,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_IQLOCAL, 2, 93,
+						 16,
+						 &pi->nphy_txiqlocal_bestc[5]);
+		}
+	}
+}
+
+static void wlc_phy_tx_iq_war_nphy(phy_info_t *pi)
+{
+	nphy_iq_comp_t tx_comp;
+
+	wlc_phy_table_read_nphy(pi, 15, 4, 0x50, 16, (void *)&tx_comp);
+
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ, tx_comp.a0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 2, tx_comp.b0);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 4, tx_comp.a1);
+	wlapi_bmac_write_shm(pi->sh->physhim, M_20IN40_IQ + 6, tx_comp.b1);
+}
+
+void
+wlc_phy_rx_iq_coeffs_nphy(phy_info_t *pi, u8 write, nphy_iq_comp_t *pcomp)
+{
+	if (write) {
+		write_phy_reg(pi, 0x9a, pcomp->a0);
+		write_phy_reg(pi, 0x9b, pcomp->b0);
+		write_phy_reg(pi, 0x9c, pcomp->a1);
+		write_phy_reg(pi, 0x9d, pcomp->b1);
+	} else {
+		pcomp->a0 = read_phy_reg(pi, 0x9a);
+		pcomp->b0 = read_phy_reg(pi, 0x9b);
+		pcomp->a1 = read_phy_reg(pi, 0x9c);
+		pcomp->b1 = read_phy_reg(pi, 0x9d);
+	}
+}
+
+void
+wlc_phy_rx_iq_est_nphy(phy_info_t *pi, phy_iq_est_t *est, u16 num_samps,
+		       u8 wait_time, u8 wait_for_crs)
+{
+	u8 core;
+
+	write_phy_reg(pi, 0x12b, num_samps);
+	mod_phy_reg(pi, 0x12a, (0xff << 0), (wait_time << 0));
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqMode,
+		    (wait_for_crs) ? NPHY_IqestCmd_iqMode : 0);
+
+	mod_phy_reg(pi, 0x129, NPHY_IqestCmd_iqstart, NPHY_IqestCmd_iqstart);
+
+	SPINWAIT(((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) != 0),
+		 10000);
+	ASSERT((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0);
+
+	if ((read_phy_reg(pi, 0x129) & NPHY_IqestCmd_iqstart) == 0) {
+		ASSERT(pi->pubpi.phy_corenum <= PHY_CORE_MAX);
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+			est[core].i_pwr =
+			    (read_phy_reg(pi, NPHY_IqestipwrAccHi(core)) << 16)
+			    | read_phy_reg(pi, NPHY_IqestipwrAccLo(core));
+			est[core].q_pwr =
+			    (read_phy_reg(pi, NPHY_IqestqpwrAccHi(core)) << 16)
+			    | read_phy_reg(pi, NPHY_IqestqpwrAccLo(core));
+			est[core].iq_prod =
+			    (read_phy_reg(pi, NPHY_IqestIqAccHi(core)) << 16) |
+			    read_phy_reg(pi, NPHY_IqestIqAccLo(core));
+		}
+	}
+}
+
+#define CAL_RETRY_CNT 2
+static void wlc_phy_calc_rx_iq_comp_nphy(phy_info_t *pi, u8 core_mask)
+{
+	u8 curr_core;
+	phy_iq_est_t est[PHY_CORE_MAX];
+	nphy_iq_comp_t old_comp, new_comp;
+	s32 iq = 0;
+	u32 ii = 0, qq = 0;
+	s16 iq_nbits, qq_nbits, brsh, arsh;
+	s32 a, b, temp;
+	int bcmerror = BCME_OK;
+	uint cal_retry = 0;
+
+	if (core_mask == 0x0)
+		return;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &old_comp);
+	new_comp.a0 = new_comp.b0 = new_comp.a1 = new_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+
+ cal_try:
+	wlc_phy_rx_iq_est_nphy(pi, est, 0x4000, 32, 0);
+
+	new_comp = old_comp;
+
+	for (curr_core = 0; curr_core < pi->pubpi.phy_corenum; curr_core++) {
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			iq = est[curr_core].iq_prod;
+			ii = est[curr_core].i_pwr;
+			qq = est[curr_core].q_pwr;
+		} else {
+			continue;
+		}
+
+		if ((ii + qq) < NPHY_MIN_RXIQ_PWR) {
+			bcmerror = BCME_ERROR;
+			break;
+		}
+
+		iq_nbits = wlc_phy_nbits(iq);
+		qq_nbits = wlc_phy_nbits(qq);
+
+		arsh = 10 - (30 - iq_nbits);
+		if (arsh >= 0) {
+			a = (-(iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
+			temp = (s32) (ii >> arsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		} else {
+			a = (-(iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
+			temp = (s32) (ii << -arsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		}
+
+		a /= temp;
+
+		brsh = qq_nbits - 31 + 20;
+		if (brsh >= 0) {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii >> brsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		} else {
+			b = (qq << (31 - qq_nbits));
+			temp = (s32) (ii << -brsh);
+			if (temp == 0) {
+				bcmerror = BCME_ERROR;
+				break;
+			}
+		}
+		b /= temp;
+		b -= a * a;
+		b = (s32) wlc_phy_sqrt_int((u32) b);
+		b -= (1 << 10);
+
+		if ((curr_core == PHY_CORE_0) && (core_mask & 0x1)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a0 = (s16) a & 0x3ff;
+				new_comp.b0 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a0 = (s16) b & 0x3ff;
+				new_comp.b0 = (s16) a & 0x3ff;
+			}
+		}
+		if ((curr_core == PHY_CORE_1) && (core_mask & 0x2)) {
+			if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+				new_comp.a1 = (s16) a & 0x3ff;
+				new_comp.b1 = (s16) b & 0x3ff;
+			} else {
+
+				new_comp.a1 = (s16) b & 0x3ff;
+				new_comp.b1 = (s16) a & 0x3ff;
+			}
+		}
+	}
+
+	if (bcmerror != BCME_OK) {
+		printk("%s: Failed, cnt = %d\n", __func__, cal_retry);
+
+		if (cal_retry < CAL_RETRY_CNT) {
+			cal_retry++;
+			goto cal_try;
+		}
+
+		new_comp = old_comp;
+	} else if (cal_retry > 0) {
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &new_comp);
+}
+
+static void wlc_phy_rxcal_radio_setup_nphy(phy_info_t *pi, u8 rx_core)
+{
+	u16 offtune_val;
+	u16 bias_g = 0;
+	u16 bias_a = 0;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+						0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+						0x7f);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+						0xaf);
+
+			} else {
+				pi->tx_rx_cal_radio_saveregs[0] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP);
+				pi->tx_rx_cal_radio_saveregs[1] =
+				    read_radio_reg(pi,
+						   RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN);
+
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+						0x3);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+						0x7f);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			pi->tx_rx_cal_radio_saveregs[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_RXIQCAL_TXMUX |
+					   RADIO_2056_TX1);
+			pi->tx_rx_cal_radio_saveregs[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RXIQCAL_RXMUX |
+					   RADIO_2056_RX0);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+				    read_radio_reg(pi,
+						   RADIO_2056_RX_RXSPARE2 |
+						   RADIO_2056_RX0);
+				pi->tx_rx_cal_radio_saveregs[3] =
+				    read_radio_reg(pi,
+						   RADIO_2056_TX_TXSPARE2 |
+						   RADIO_2056_TX1);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_MASTER
+							   | RADIO_2056_RX0);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX1, bias_a);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX0, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_TUNE
+							   | RADIO_2056_RX0);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_MASTER
+							   | RADIO_2056_RX0);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX0, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX1, bias_g);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX0, bias_g);
+
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_TUNE
+							   | RADIO_2056_RX0);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX0, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX1, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX0, 0x6);
+			}
+
+		} else {
+			pi->tx_rx_cal_radio_saveregs[0] =
+			    read_radio_reg(pi,
+					   RADIO_2056_TX_RXIQCAL_TXMUX |
+					   RADIO_2056_TX0);
+			pi->tx_rx_cal_radio_saveregs[1] =
+			    read_radio_reg(pi,
+					   RADIO_2056_RX_RXIQCAL_RXMUX |
+					   RADIO_2056_RX1);
+
+			if (pi->pubpi.radiorev >= 5) {
+				pi->tx_rx_cal_radio_saveregs[2] =
+				    read_radio_reg(pi,
+						   RADIO_2056_RX_RXSPARE2 |
+						   RADIO_2056_RX1);
+				pi->tx_rx_cal_radio_saveregs[3] =
+				    read_radio_reg(pi,
+						   RADIO_2056_TX_TXSPARE2 |
+						   RADIO_2056_TX0);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_MASTER
+							   | RADIO_2056_RX1);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX0, bias_a);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX1, bias_a);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAA_TUNE
+							   | RADIO_2056_RX1);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAA_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x9);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x9);
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_MASTER
+							   | RADIO_2056_RX1);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX1, 0x40);
+
+					write_radio_reg(pi,
+							RADIO_2056_TX_TXSPARE2 |
+							RADIO_2056_TX0, bias_g);
+
+					write_radio_reg(pi,
+							RADIO_2056_RX_RXSPARE2 |
+							RADIO_2056_RX1, bias_g);
+				} else {
+					pi->tx_rx_cal_radio_saveregs[4] =
+					    read_radio_reg(pi,
+							   RADIO_2056_RX_LNAG_TUNE
+							   | RADIO_2056_RX1);
+
+					offtune_val =
+					    (pi->
+					     tx_rx_cal_radio_saveregs[2] & 0xF0)
+					    >> 8;
+					offtune_val =
+					    (offtune_val <= 0x7) ? 0xF : 0;
+
+					mod_radio_reg(pi,
+						      RADIO_2056_RX_LNAG_TUNE |
+						      RADIO_2056_RX1, 0xF0,
+						      (offtune_val << 8));
+				}
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_RXIQCAL_TXMUX |
+						RADIO_2056_TX0, 0x6);
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXIQCAL_RXMUX |
+						RADIO_2056_RX1, 0x6);
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_radio_cleanup_nphy(phy_info_t *pi, u8 rx_core)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		if (rx_core == PHY_CORE_0) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_5G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX0_TXRXCOUPLE_2G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+			}
+
+		} else {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_5G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+
+			} else {
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_PWRUP,
+						pi->
+						tx_rx_cal_radio_saveregs[0]);
+				write_radio_reg(pi,
+						RADIO_2057_TX1_TXRXCOUPLE_2G_ATTEN,
+						pi->
+						tx_rx_cal_radio_saveregs[1]);
+			}
+		}
+
+	} else {
+		if (rx_core == PHY_CORE_0) {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX1,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX0,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX0,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX1,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX0,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			}
+
+		} else {
+			write_radio_reg(pi,
+					RADIO_2056_TX_RXIQCAL_TXMUX |
+					RADIO_2056_TX0,
+					pi->tx_rx_cal_radio_saveregs[0]);
+
+			write_radio_reg(pi,
+					RADIO_2056_RX_RXIQCAL_RXMUX |
+					RADIO_2056_RX1,
+					pi->tx_rx_cal_radio_saveregs[1]);
+
+			if (pi->pubpi.radiorev >= 5) {
+				write_radio_reg(pi,
+						RADIO_2056_RX_RXSPARE2 |
+						RADIO_2056_RX1,
+						pi->
+						tx_rx_cal_radio_saveregs[2]);
+
+				write_radio_reg(pi,
+						RADIO_2056_TX_TXSPARE2 |
+						RADIO_2056_TX0,
+						pi->
+						tx_rx_cal_radio_saveregs[3]);
+			}
+
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_MASTER
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAA_TUNE
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			} else {
+				if (pi->pubpi.radiorev >= 5) {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_MASTER
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				} else {
+					write_radio_reg(pi,
+							RADIO_2056_RX_LNAG_TUNE
+							| RADIO_2056_RX1,
+							pi->
+							tx_rx_cal_radio_saveregs
+							[4]);
+				}
+			}
+		}
+	}
+}
+
+static void wlc_phy_rxcal_physetup_nphy(phy_info_t *pi, u8 rx_core)
+{
+	u8 tx_core;
+	u16 rx_antval, tx_antval;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		tx_core = rx_core;
+	} else {
+		tx_core = (rx_core == PHY_CORE_0) ? 1 : 0;
+	}
+
+	pi->tx_rx_cal_phy_saveregs[0] = read_phy_reg(pi, 0xa2);
+	pi->tx_rx_cal_phy_saveregs[1] =
+	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7);
+	pi->tx_rx_cal_phy_saveregs[2] =
+	    read_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5);
+	pi->tx_rx_cal_phy_saveregs[3] = read_phy_reg(pi, 0x91);
+	pi->tx_rx_cal_phy_saveregs[4] = read_phy_reg(pi, 0x92);
+	pi->tx_rx_cal_phy_saveregs[5] = read_phy_reg(pi, 0x7a);
+	pi->tx_rx_cal_phy_saveregs[6] = read_phy_reg(pi, 0x7d);
+	pi->tx_rx_cal_phy_saveregs[7] = read_phy_reg(pi, 0xe7);
+	pi->tx_rx_cal_phy_saveregs[8] = read_phy_reg(pi, 0xec);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		pi->tx_rx_cal_phy_saveregs[11] = read_phy_reg(pi, 0x342);
+		pi->tx_rx_cal_phy_saveregs[12] = read_phy_reg(pi, 0x343);
+		pi->tx_rx_cal_phy_saveregs[13] = read_phy_reg(pi, 0x346);
+		pi->tx_rx_cal_phy_saveregs[14] = read_phy_reg(pi, 0x347);
+	}
+
+	pi->tx_rx_cal_phy_saveregs[9] = read_phy_reg(pi, 0x297);
+	pi->tx_rx_cal_phy_saveregs[10] = read_phy_reg(pi, 0x29b);
+	mod_phy_reg(pi, (0 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	mod_phy_reg(pi, (1 == PHY_CORE_0) ? 0x297 :
+		    0x29b, (0x1 << 0), (0) << 0);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << (1 - rx_core)) << 12);
+
+	} else {
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+		mod_phy_reg(pi, 0xa2, (0xf << 4), (1 << rx_core) << 4);
+		mod_phy_reg(pi, 0xa2, (0xf << 8), (1 << rx_core) << 8);
+	}
+
+	mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7), (0x1 << 2), 0);
+	mod_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		    (0x1 << 2), (0x1 << 2));
+	if (NREV_LT(pi->pubpi.phy_rev, 7)) {
+		mod_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1), 0);
+		mod_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+			    0x8f : 0xa5,
+			    (0x1 << 0) | (0x1 << 1), (0x1 << 0) | (0x1 << 1));
+	}
+
+	wlc_phy_rfctrlintc_override_nphy(pi, NPHY_RfctrlIntc_override_PA, 0,
+					 RADIO_MIMO_CORESEL_CORE1 |
+					 RADIO_MIMO_CORESEL_CORE2);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		if (CHSPEC_IS40(pi->radio_chanspec)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  2, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi,
+							  (0x1 << 7),
+							  0, 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+						  0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 3, 0);
+	}
+
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RX2TX);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 0x1, rx_core + 1);
+	} else {
+
+		if (rx_core == PHY_CORE_0) {
+			rx_antval = 0x1;
+			tx_antval = 0x8;
+		} else {
+			rx_antval = 0x4;
+			tx_antval = 0x2;
+		}
+
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 rx_antval, rx_core + 1);
+		wlc_phy_rfctrlintc_override_nphy(pi,
+						 NPHY_RfctrlIntc_override_TRSW,
+						 tx_antval, tx_core + 1);
+	}
+}
+
+static void wlc_phy_rxcal_phycleanup_nphy(phy_info_t *pi, u8 rx_core)
+{
+
+	write_phy_reg(pi, 0xa2, pi->tx_rx_cal_phy_saveregs[0]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 : 0xa7,
+		      pi->tx_rx_cal_phy_saveregs[1]);
+	write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x8f : 0xa5,
+		      pi->tx_rx_cal_phy_saveregs[2]);
+	write_phy_reg(pi, 0x91, pi->tx_rx_cal_phy_saveregs[3]);
+	write_phy_reg(pi, 0x92, pi->tx_rx_cal_phy_saveregs[4]);
+
+	write_phy_reg(pi, 0x7a, pi->tx_rx_cal_phy_saveregs[5]);
+	write_phy_reg(pi, 0x7d, pi->tx_rx_cal_phy_saveregs[6]);
+	write_phy_reg(pi, 0xe7, pi->tx_rx_cal_phy_saveregs[7]);
+	write_phy_reg(pi, 0xec, pi->tx_rx_cal_phy_saveregs[8]);
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		write_phy_reg(pi, 0x342, pi->tx_rx_cal_phy_saveregs[11]);
+		write_phy_reg(pi, 0x343, pi->tx_rx_cal_phy_saveregs[12]);
+		write_phy_reg(pi, 0x346, pi->tx_rx_cal_phy_saveregs[13]);
+		write_phy_reg(pi, 0x347, pi->tx_rx_cal_phy_saveregs[14]);
+	}
+
+	write_phy_reg(pi, 0x297, pi->tx_rx_cal_phy_saveregs[9]);
+	write_phy_reg(pi, 0x29b, pi->tx_rx_cal_phy_saveregs[10]);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy_rev5(phy_info_t *pi, u8 rx_core,
+				 u16 *rxgain, u8 cal_type)
+{
+
+	u16 num_samps;
+	phy_iq_est_t est[PHY_CORE_MAX];
+	u8 tx_core;
+	nphy_iq_comp_t save_comp, zero_comp;
+	u32 i_pwr, q_pwr, curr_pwr, optim_pwr = 0, prev_pwr = 0, thresh_pwr =
+	    10000;
+	s16 desired_log2_pwr, actual_log2_pwr, delta_pwr;
+	bool gainctrl_done = false;
+	u8 mix_tia_gain = 3;
+	s8 optim_gaintbl_index = 0, prev_gaintbl_index = 0;
+	s8 curr_gaintbl_index = 3;
+	u8 gainctrl_dirn = NPHY_RXCAL_GAIN_INIT;
+	nphy_ipa_txrxgain_t *nphy_rxcal_gaintbl;
+	u16 hpvga, lpf_biq1, lpf_biq0, lna2, lna1;
+	int fine_gain_idx;
+	s8 txpwrindex;
+	u16 nphy_rxcal_txgain[2];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		tx_core = rx_core;
+	} else {
+		tx_core = 1 - rx_core;
+	}
+
+	num_samps = 1024;
+	desired_log2_pwr = (cal_type == 0) ? 13 : 13;
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 0, &save_comp);
+	zero_comp.a0 = zero_comp.b0 = zero_comp.a1 = zero_comp.b1 = 0x0;
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &zero_comp);
+
+	if (CHSPEC_IS5G(pi->radio_chanspec)) {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			mix_tia_gain = 3;
+		} else if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+			mix_tia_gain = 4;
+		} else {
+			mix_tia_gain = 6;
+		}
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz_rev7;
+		} else {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_5GHz;
+		}
+	} else {
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz_rev7;
+		} else {
+			nphy_rxcal_gaintbl = nphy_ipa_rxcal_gaintbl_2GHz;
+		}
+	}
+
+	do {
+
+		hpvga = (NREV_GE(pi->pubpi.phy_rev, 7)) ?
+		    0 : nphy_rxcal_gaintbl[curr_gaintbl_index].hpvga;
+		lpf_biq1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq1;
+		lpf_biq0 = nphy_rxcal_gaintbl[curr_gaintbl_index].lpf_biq0;
+		lna2 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna2;
+		lna1 = nphy_rxcal_gaintbl[curr_gaintbl_index].lna1;
+		txpwrindex = nphy_rxcal_gaintbl[curr_gaintbl_index].txpwrindex;
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			wlc_phy_rfctrl_override_1tomany_nphy(pi,
+							     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+							     ((lpf_biq1 << 12) |
+							      (lpf_biq0 << 8) |
+							      (mix_tia_gain <<
+							       4) | (lna2 << 2)
+							      | lna1), 0x3, 0);
+		} else {
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+						     ((hpvga << 12) |
+						      (lpf_biq1 << 10) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+		}
+
+		pi->nphy_rxcal_pwr_idx[tx_core] = txpwrindex;
+
+		if (txpwrindex == -1) {
+			nphy_rxcal_txgain[0] = 0x8ff0 | pi->nphy_gmval;
+			nphy_rxcal_txgain[1] = 0x8ff0 | pi->nphy_gmval;
+			wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ,
+						 2, 0x110, 16,
+						 nphy_rxcal_txgain);
+		} else {
+			wlc_phy_txpwr_index_nphy(pi, tx_core + 1, txpwrindex,
+						 false);
+		}
+
+		wlc_phy_tx_tone_nphy(pi, (CHSPEC_IS40(pi->radio_chanspec)) ?
+				     NPHY_RXCAL_TONEFREQ_40MHz :
+				     NPHY_RXCAL_TONEFREQ_20MHz,
+				     NPHY_RXCAL_TONEAMP, 0, cal_type, false);
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+		i_pwr = (est[rx_core].i_pwr + num_samps / 2) / num_samps;
+		q_pwr = (est[rx_core].q_pwr + num_samps / 2) / num_samps;
+		curr_pwr = i_pwr + q_pwr;
+
+		switch (gainctrl_dirn) {
+		case NPHY_RXCAL_GAIN_INIT:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_DOWN;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_dirn = NPHY_RXCAL_GAIN_UP;
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_UP:
+			if (curr_pwr > thresh_pwr) {
+				gainctrl_done = true;
+				optim_pwr = prev_pwr;
+				optim_gaintbl_index = prev_gaintbl_index;
+			} else {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index++;
+			}
+			break;
+
+		case NPHY_RXCAL_GAIN_DOWN:
+			if (curr_pwr > thresh_pwr) {
+				prev_gaintbl_index = curr_gaintbl_index;
+				curr_gaintbl_index--;
+			} else {
+				gainctrl_done = true;
+				optim_pwr = curr_pwr;
+				optim_gaintbl_index = curr_gaintbl_index;
+			}
+			break;
+
+		default:
+			ASSERT(0);
+		}
+
+		if ((curr_gaintbl_index < 0) ||
+		    (curr_gaintbl_index > NPHY_IPA_RXCAL_MAXGAININDEX)) {
+			gainctrl_done = true;
+			optim_pwr = curr_pwr;
+			optim_gaintbl_index = prev_gaintbl_index;
+		} else {
+			prev_pwr = curr_pwr;
+		}
+
+		wlc_phy_stopplayback_nphy(pi);
+	} while (!gainctrl_done);
+
+	hpvga = nphy_rxcal_gaintbl[optim_gaintbl_index].hpvga;
+	lpf_biq1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq1;
+	lpf_biq0 = nphy_rxcal_gaintbl[optim_gaintbl_index].lpf_biq0;
+	lna2 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna2;
+	lna1 = nphy_rxcal_gaintbl[optim_gaintbl_index].lna1;
+	txpwrindex = nphy_rxcal_gaintbl[optim_gaintbl_index].txpwrindex;
+
+	actual_log2_pwr = wlc_phy_nbits(optim_pwr);
+	delta_pwr = desired_log2_pwr - actual_log2_pwr;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		fine_gain_idx = (int)lpf_biq1 + delta_pwr;
+
+		if (fine_gain_idx + (int)lpf_biq0 > 10) {
+			lpf_biq1 = 10 - lpf_biq0;
+		} else {
+			lpf_biq1 = (u16) max(fine_gain_idx, 0);
+		}
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+						     ((lpf_biq1 << 12) |
+						      (lpf_biq0 << 8) |
+						      (mix_tia_gain << 4) |
+						      (lna2 << 2) | lna1), 0x3,
+						     0);
+	} else {
+		hpvga = (u16) max(min(((int)hpvga) + delta_pwr, 10), 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12),
+					     ((hpvga << 12) | (lpf_biq1 << 10) |
+					      (lpf_biq0 << 8) | (mix_tia_gain <<
+								 4) | (lna2 <<
+								       2) |
+					      lna1), 0x3, 0);
+
+	}
+
+	if (rxgain != NULL) {
+		*rxgain++ = lna1;
+		*rxgain++ = lna2;
+		*rxgain++ = mix_tia_gain;
+		*rxgain++ = lpf_biq0;
+		*rxgain++ = lpf_biq1;
+		*rxgain = hpvga;
+	}
+
+	wlc_phy_rx_iq_coeffs_nphy(pi, 1, &save_comp);
+}
+
+static void
+wlc_phy_rxcal_gainctrl_nphy(phy_info_t *pi, u8 rx_core, u16 *rxgain,
+			    u8 cal_type)
+{
+	wlc_phy_rxcal_gainctrl_nphy_rev5(pi, rx_core, rxgain, cal_type);
+}
+
+static u8
+wlc_phy_rc_sweep_nphy(phy_info_t *pi, u8 core_idx, u8 loopback_type)
+{
+	u32 target_bws[2] = { 9500, 21000 };
+	u32 ref_tones[2] = { 3000, 6000 };
+	u32 target_bw, ref_tone;
+
+	u32 target_pwr_ratios[2] = { 28606, 18468 };
+	u32 target_pwr_ratio, pwr_ratio, last_pwr_ratio = 0;
+
+	u16 start_rccal_ovr_val = 128;
+	u16 txlpf_rccal_lpc_ovr_val = 128;
+	u16 rxlpf_rccal_hpc_ovr_val = 159;
+
+	u16 orig_txlpf_rccal_lpc_ovr_val;
+	u16 orig_rxlpf_rccal_hpc_ovr_val;
+	u16 radio_addr_offset_rx;
+	u16 radio_addr_offset_tx;
+	u16 orig_dcBypass;
+	u16 orig_RxStrnFilt40Num[6];
+	u16 orig_RxStrnFilt40Den[4];
+	u16 orig_rfctrloverride[2];
+	u16 orig_rfctrlauxreg[2];
+	u16 orig_rfctrlrssiothers;
+	u16 tx_lpf_bw = 4;
+
+	u16 rx_lpf_bw, rx_lpf_bws[2] = { 2, 4 };
+	u16 lpf_hpc = 7, hpvga_hpc = 7;
+
+	s8 rccal_stepsize;
+	u16 rccal_val, last_rccal_val = 0, best_rccal_val = 0;
+	u32 ref_iq_vals = 0, target_iq_vals = 0;
+	u16 num_samps, log_num_samps = 10;
+	phy_iq_est_t est[PHY_CORE_MAX];
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		return 0;
+	}
+
+	num_samps = (1 << log_num_samps);
+
+	if (CHSPEC_IS40(pi->radio_chanspec)) {
+		target_bw = target_bws[1];
+		target_pwr_ratio = target_pwr_ratios[1];
+		ref_tone = ref_tones[1];
+		rx_lpf_bw = rx_lpf_bws[1];
+	} else {
+		target_bw = target_bws[0];
+		target_pwr_ratio = target_pwr_ratios[0];
+		ref_tone = ref_tones[0];
+		rx_lpf_bw = rx_lpf_bws[0];
+	}
+
+	if (core_idx == 0) {
+		radio_addr_offset_rx = RADIO_2056_RX0;
+		radio_addr_offset_tx =
+		    (loopback_type == 0) ? RADIO_2056_TX0 : RADIO_2056_TX1;
+	} else {
+		radio_addr_offset_rx = RADIO_2056_RX1;
+		radio_addr_offset_tx =
+		    (loopback_type == 0) ? RADIO_2056_TX1 : RADIO_2056_TX0;
+	}
+
+	orig_txlpf_rccal_lpc_ovr_val =
+	    read_radio_reg(pi,
+			   (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx));
+	orig_rxlpf_rccal_hpc_ovr_val =
+	    read_radio_reg(pi,
+			   (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+			    radio_addr_offset_rx));
+
+	orig_dcBypass = ((read_phy_reg(pi, 0x48) >> 8) & 1);
+
+	orig_RxStrnFilt40Num[0] = read_phy_reg(pi, 0x267);
+	orig_RxStrnFilt40Num[1] = read_phy_reg(pi, 0x268);
+	orig_RxStrnFilt40Num[2] = read_phy_reg(pi, 0x269);
+	orig_RxStrnFilt40Den[0] = read_phy_reg(pi, 0x26a);
+	orig_RxStrnFilt40Den[1] = read_phy_reg(pi, 0x26b);
+	orig_RxStrnFilt40Num[3] = read_phy_reg(pi, 0x26c);
+	orig_RxStrnFilt40Num[4] = read_phy_reg(pi, 0x26d);
+	orig_RxStrnFilt40Num[5] = read_phy_reg(pi, 0x26e);
+	orig_RxStrnFilt40Den[2] = read_phy_reg(pi, 0x26f);
+	orig_RxStrnFilt40Den[3] = read_phy_reg(pi, 0x270);
+
+	orig_rfctrloverride[0] = read_phy_reg(pi, 0xe7);
+	orig_rfctrloverride[1] = read_phy_reg(pi, 0xec);
+	orig_rfctrlauxreg[0] = read_phy_reg(pi, 0xf8);
+	orig_rfctrlauxreg[1] = read_phy_reg(pi, 0xfa);
+	orig_rfctrlrssiothers = read_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			txlpf_rccal_lpc_ovr_val);
+
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (0x1 << 8));
+
+	write_phy_reg(pi, 0x267, 0x02d4);
+	write_phy_reg(pi, 0x268, 0x0000);
+	write_phy_reg(pi, 0x269, 0x0000);
+	write_phy_reg(pi, 0x26a, 0x0000);
+	write_phy_reg(pi, 0x26b, 0x0000);
+	write_phy_reg(pi, 0x26c, 0x02d4);
+	write_phy_reg(pi, 0x26d, 0x0000);
+	write_phy_reg(pi, 0x26e, 0x0000);
+	write_phy_reg(pi, 0x26f, 0x0000);
+	write_phy_reg(pi, 0x270, 0x0000);
+
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 8));
+	or_phy_reg(pi, (core_idx == 0) ? 0xec : 0xe7, (0x1 << 15));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 9));
+	or_phy_reg(pi, (core_idx == 0) ? 0xe7 : 0xec, (0x1 << 10));
+
+	mod_phy_reg(pi, (core_idx == 0) ? 0xfa : 0xf8,
+		    (0x7 << 10), (tx_lpf_bw << 10));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 0), (hpvga_hpc << 0));
+	mod_phy_reg(pi, (core_idx == 0) ? 0xf8 : 0xfa,
+		    (0x7 << 4), (lpf_hpc << 4));
+	mod_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d,
+		    (0x7 << 8), (rx_lpf_bw << 8));
+
+	rccal_stepsize = 16;
+	rccal_val = start_rccal_ovr_val + rccal_stepsize;
+
+	while (rccal_stepsize >= 0) {
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 radio_addr_offset_rx), rccal_val);
+
+		if (rccal_stepsize == 16) {
+
+			wlc_phy_tx_tone_nphy(pi, ref_tone, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+
+			wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+			if (core_idx == 0) {
+				ref_iq_vals =
+				    max_t(u32, (est[0].i_pwr +
+					 est[0].q_pwr) >> (log_num_samps + 1),
+					1);
+			} else {
+				ref_iq_vals =
+				    max_t(u32, (est[1].i_pwr +
+					 est[1].q_pwr) >> (log_num_samps + 1),
+					1);
+			}
+
+			wlc_phy_tx_tone_nphy(pi, target_bw, NPHY_RXCAL_TONEAMP,
+					     0, 1, false);
+			udelay(2);
+		}
+
+		wlc_phy_rx_iq_est_nphy(pi, est, num_samps, 32, 0);
+
+		if (core_idx == 0) {
+			target_iq_vals =
+			    (est[0].i_pwr + est[0].q_pwr) >> (log_num_samps +
+							      1);
+		} else {
+			target_iq_vals =
+			    (est[1].i_pwr + est[1].q_pwr) >> (log_num_samps +
+							      1);
+		}
+		pwr_ratio = (uint) ((target_iq_vals << 16) / ref_iq_vals);
+
+		if (rccal_stepsize == 0) {
+			rccal_stepsize--;
+		} else if (rccal_stepsize == 1) {
+			last_rccal_val = rccal_val;
+			rccal_val += (pwr_ratio > target_pwr_ratio) ? 1 : -1;
+			last_pwr_ratio = pwr_ratio;
+			rccal_stepsize--;
+		} else {
+			rccal_stepsize = (rccal_stepsize >> 1);
+			rccal_val += ((pwr_ratio > target_pwr_ratio) ?
+				      rccal_stepsize : (-rccal_stepsize));
+		}
+
+		if (rccal_stepsize == -1) {
+			best_rccal_val =
+			    (ABS((int)last_pwr_ratio - (int)target_pwr_ratio) <
+			     ABS((int)pwr_ratio -
+				 (int)target_pwr_ratio)) ? last_rccal_val :
+			    rccal_val;
+
+			if (CHSPEC_IS40(pi->radio_chanspec)) {
+				if ((best_rccal_val > 140)
+				    || (best_rccal_val < 135)) {
+					best_rccal_val = 138;
+				}
+			} else {
+				if ((best_rccal_val > 142)
+				    || (best_rccal_val < 137)) {
+					best_rccal_val = 140;
+				}
+			}
+
+			write_radio_reg(pi,
+					(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+					 radio_addr_offset_rx), best_rccal_val);
+		}
+	}
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL | radio_addr_offset_tx),
+			orig_txlpf_rccal_lpc_ovr_val);
+	write_radio_reg(pi,
+			(RADIO_2056_RX_RXLPF_RCCAL_HPC | radio_addr_offset_rx),
+			orig_rxlpf_rccal_hpc_ovr_val);
+
+	mod_phy_reg(pi, 0x48, (0x1 << 8), (orig_dcBypass << 8));
+
+	write_phy_reg(pi, 0x267, orig_RxStrnFilt40Num[0]);
+	write_phy_reg(pi, 0x268, orig_RxStrnFilt40Num[1]);
+	write_phy_reg(pi, 0x269, orig_RxStrnFilt40Num[2]);
+	write_phy_reg(pi, 0x26a, orig_RxStrnFilt40Den[0]);
+	write_phy_reg(pi, 0x26b, orig_RxStrnFilt40Den[1]);
+	write_phy_reg(pi, 0x26c, orig_RxStrnFilt40Num[3]);
+	write_phy_reg(pi, 0x26d, orig_RxStrnFilt40Num[4]);
+	write_phy_reg(pi, 0x26e, orig_RxStrnFilt40Num[5]);
+	write_phy_reg(pi, 0x26f, orig_RxStrnFilt40Den[2]);
+	write_phy_reg(pi, 0x270, orig_RxStrnFilt40Den[3]);
+
+	write_phy_reg(pi, 0xe7, orig_rfctrloverride[0]);
+	write_phy_reg(pi, 0xec, orig_rfctrloverride[1]);
+	write_phy_reg(pi, 0xf8, orig_rfctrlauxreg[0]);
+	write_phy_reg(pi, 0xfa, orig_rfctrlauxreg[1]);
+	write_phy_reg(pi, (core_idx == 0) ? 0x7a : 0x7d, orig_rfctrlrssiothers);
+
+	pi->nphy_anarxlpf_adjusted = false;
+
+	return best_rccal_val - 0x80;
+}
+
+#define WAIT_FOR_SCOPE	4000
+static int
+wlc_phy_cal_rxiq_nphy_rev3(phy_info_t *pi, nphy_txgains_t target_gain,
+			   u8 cal_type, bool debug)
+{
+	u16 orig_BBConfig;
+	u8 core_no, rx_core;
+	u8 best_rccal[2];
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	nphy_iqcal_params_t cal_params[2];
+	u8 rxcore_state;
+	s8 rxlpf_rccal_hpc, txlpf_rccal_lpc;
+	s8 txlpf_idac;
+	bool phyhang_avoid_state = false;
+	bool skip_rxiqcal = false;
+
+	orig_BBConfig = read_phy_reg(pi, 0x01);
+	mod_phy_reg(pi, 0x01, (0x1 << 15), 0);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		phyhang_avoid_state = pi->phyhang_avoid;
+		pi->phyhang_avoid = false;
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	rxcore_state = wlc_phy_rxcore_getstate_nphy((wlc_phy_t *) pi);
+
+	for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+
+		skip_rxiqcal =
+		    ((rxcore_state & (1 << rx_core)) == 0) ? true : false;
+
+		wlc_phy_rxcal_physetup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_radio_setup_nphy(pi, rx_core);
+
+		if ((!skip_rxiqcal) && ((cal_type == 0) || (cal_type == 2))) {
+
+			wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL, 0);
+
+			wlc_phy_tx_tone_nphy(pi,
+					     (CHSPEC_IS40(pi->radio_chanspec)) ?
+					     NPHY_RXCAL_TONEFREQ_40MHz :
+					     NPHY_RXCAL_TONEFREQ_20MHz,
+					     NPHY_RXCAL_TONEAMP, 0, cal_type,
+					     false);
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			wlc_phy_calc_rx_iq_comp_nphy(pi, rx_core + 1);
+			wlc_phy_stopplayback_nphy(pi);
+		}
+
+		if (((cal_type == 1) || (cal_type == 2))
+		    && NREV_LT(pi->pubpi.phy_rev, 7)) {
+
+			if (rx_core == PHY_CORE_1) {
+
+				if (rxcore_state == 1) {
+					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
+								      *) pi, 3);
+				}
+
+				wlc_phy_rxcal_gainctrl_nphy(pi, rx_core, NULL,
+							    1);
+
+				best_rccal[rx_core] =
+				    wlc_phy_rc_sweep_nphy(pi, rx_core, 1);
+				pi->nphy_rccal_value = best_rccal[rx_core];
+
+				if (rxcore_state == 1) {
+					wlc_phy_rxcore_setstate_nphy((wlc_phy_t
+								      *) pi,
+								     rxcore_state);
+				}
+			}
+		}
+
+		wlc_phy_rxcal_radio_cleanup_nphy(pi, rx_core);
+
+		wlc_phy_rxcal_phycleanup_nphy(pi, rx_core);
+		wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+	}
+
+	if ((cal_type == 1) || (cal_type == 2)) {
+
+		best_rccal[0] = best_rccal[1];
+		write_radio_reg(pi,
+				(RADIO_2056_RX_RXLPF_RCCAL_LPC |
+				 RADIO_2056_RX0), (best_rccal[0] | 0x80));
+
+		for (rx_core = 0; rx_core < pi->pubpi.phy_corenum; rx_core++) {
+			rxlpf_rccal_hpc =
+			    (((int)best_rccal[rx_core] - 12) >> 1) + 10;
+			txlpf_rccal_lpc = ((int)best_rccal[rx_core] - 12) + 10;
+
+			if (PHY_IPA(pi)) {
+				txlpf_rccal_lpc += IS40MHZ(pi) ? 24 : 12;
+				txlpf_idac = IS40MHZ(pi) ? 0x0e : 0x13;
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, rx_core,
+						 TXLPF_IDAC_4, txlpf_idac);
+			}
+
+			rxlpf_rccal_hpc = max(min_t(u8, rxlpf_rccal_hpc, 31), 0);
+			txlpf_rccal_lpc = max(min_t(u8, txlpf_rccal_lpc, 31), 0);
+
+			write_radio_reg(pi, (RADIO_2056_RX_RXLPF_RCCAL_HPC |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_RX0 :
+					      RADIO_2056_RX1)),
+					(rxlpf_rccal_hpc | 0x80));
+
+			write_radio_reg(pi, (RADIO_2056_TX_TXLPF_RCCAL |
+					     ((rx_core ==
+					       PHY_CORE_0) ? RADIO_2056_TX0 :
+					      RADIO_2056_TX1)),
+					(txlpf_rccal_lpc | 0x80));
+		}
+	}
+
+	write_phy_reg(pi, 0x01, orig_BBConfig);
+
+	wlc_phy_resetcca_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_rxgain,
+						     0, 0x3, 1);
+	} else {
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+	}
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 4)) {
+		pi->phyhang_avoid = phyhang_avoid_state;
+	}
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return BCME_OK;
+}
+
+static int
+wlc_phy_cal_rxiq_nphy_rev2(phy_info_t *pi, nphy_txgains_t target_gain,
+			   bool debug)
+{
+	phy_iq_est_t est[PHY_CORE_MAX];
+	u8 core_num, rx_core, tx_core;
+	u16 lna_vals[] = { 0x3, 0x3, 0x1 };
+	u16 hpf1_vals[] = { 0x7, 0x2, 0x0 };
+	u16 hpf2_vals[] = { 0x2, 0x0, 0x0 };
+	s16 curr_hpf1, curr_hpf2, curr_hpf, curr_lna;
+	s16 desired_log2_pwr, actual_log2_pwr, hpf_change;
+	u16 orig_RfseqCoreActv, orig_AfectrlCore, orig_AfectrlOverride;
+	u16 orig_RfctrlIntcRx, orig_RfctrlIntcTx;
+	u16 num_samps;
+	u32 i_pwr, q_pwr, tot_pwr[3];
+	u8 gain_pass, use_hpf_num;
+	u16 mask, val1, val2;
+	u16 core_no;
+	u16 gain_save[2];
+	u16 cal_gain[2];
+	nphy_iqcal_params_t cal_params[2];
+	u8 phy_bw;
+	int bcmerror = BCME_OK;
+	bool first_playtone = true;
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, true);
+
+	if (NREV_LT(pi->pubpi.phy_rev, 2)) {
+
+		wlc_phy_reapply_txcal_coeffs_nphy(pi);
+	}
+
+	wlc_phy_table_read_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, gain_save);
+
+	for (core_no = 0; core_no <= 1; core_no++) {
+		wlc_phy_iqcal_gainparams_nphy(pi, core_no, target_gain,
+					      &cal_params[core_no]);
+		cal_gain[core_no] = cal_params[core_no].cal_gain;
+	}
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16, cal_gain);
+
+	num_samps = 1024;
+	desired_log2_pwr = 13;
+
+	for (core_num = 0; core_num < 2; core_num++) {
+
+		rx_core = core_num;
+		tx_core = 1 - core_num;
+
+		orig_RfseqCoreActv = read_phy_reg(pi, 0xa2);
+		orig_AfectrlCore = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						0xa6 : 0xa7);
+		orig_AfectrlOverride = read_phy_reg(pi, 0xa5);
+		orig_RfctrlIntcRx = read_phy_reg(pi, (rx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+		orig_RfctrlIntcTx = read_phy_reg(pi, (tx_core == PHY_CORE_0) ?
+						 0x91 : 0x92);
+
+		mod_phy_reg(pi, 0xa2, (0xf << 12), (1 << tx_core) << 12);
+		mod_phy_reg(pi, 0xa2, (0xf << 0), (1 << tx_core) << 0);
+
+		or_phy_reg(pi, ((rx_core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			   ((0x1 << 1) | (0x1 << 2)));
+		or_phy_reg(pi, 0xa5, ((0x1 << 1) | (0x1 << 2)));
+
+		if (((pi->nphy_rxcalparams) & 0xff000000)) {
+
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x140 :
+				       0x110));
+		} else {
+
+			write_phy_reg(pi,
+				      (rx_core == PHY_CORE_0) ? 0x91 : 0x92,
+				      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x180 :
+				       0x120));
+		}
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 : 0x92,
+			      (CHSPEC_IS5G(pi->radio_chanspec) ? 0x148 :
+			       0x114));
+
+		mask = RADIO_2055_COUPLE_RX_MASK | RADIO_2055_COUPLE_TX_MASK;
+		if (rx_core == PHY_CORE_0) {
+			val1 = RADIO_2055_COUPLE_RX_MASK;
+			val2 = RADIO_2055_COUPLE_TX_MASK;
+		} else {
+			val1 = RADIO_2055_COUPLE_TX_MASK;
+			val2 = RADIO_2055_COUPLE_RX_MASK;
+		}
+
+		if ((pi->nphy_rxcalparams & 0x10000)) {
+			mod_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, mask,
+				      val1);
+			mod_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, mask,
+				      val2);
+		}
+
+		for (gain_pass = 0; gain_pass < 4; gain_pass++) {
+
+			if (debug)
+				mdelay(WAIT_FOR_SCOPE);
+
+			if (gain_pass < 3) {
+				curr_lna = lna_vals[gain_pass];
+				curr_hpf1 = hpf1_vals[gain_pass];
+				curr_hpf2 = hpf2_vals[gain_pass];
+			} else {
+
+				if (tot_pwr[1] > 10000) {
+					curr_lna = lna_vals[2];
+					curr_hpf1 = hpf1_vals[2];
+					curr_hpf2 = hpf2_vals[2];
+					use_hpf_num = 1;
+					curr_hpf = curr_hpf1;
+					actual_log2_pwr =
+					    wlc_phy_nbits(tot_pwr[2]);
+				} else {
+					if (tot_pwr[0] > 10000) {
+						curr_lna = lna_vals[1];
+						curr_hpf1 = hpf1_vals[1];
+						curr_hpf2 = hpf2_vals[1];
+						use_hpf_num = 1;
+						curr_hpf = curr_hpf1;
+						actual_log2_pwr =
+						    wlc_phy_nbits(tot_pwr[1]);
+					} else {
+						curr_lna = lna_vals[0];
+						curr_hpf1 = hpf1_vals[0];
+						curr_hpf2 = hpf2_vals[0];
+						use_hpf_num = 2;
+						curr_hpf = curr_hpf2;
+						actual_log2_pwr =
+						    wlc_phy_nbits(tot_pwr[0]);
+					}
+				}
+
+				hpf_change = desired_log2_pwr - actual_log2_pwr;
+				curr_hpf += hpf_change;
+				curr_hpf = max(min_t(u16, curr_hpf, 10), 0);
+				if (use_hpf_num == 1) {
+					curr_hpf1 = curr_hpf;
+				} else {
+					curr_hpf2 = curr_hpf;
+				}
+			}
+
+			wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10),
+						     ((curr_hpf2 << 8) |
+						      (curr_hpf1 << 4) |
+						      (curr_lna << 2)), 0x3, 0);
+			wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+			wlc_phy_stopplayback_nphy(pi);
+
+			if (first_playtone) {
+				bcmerror = wlc_phy_tx_tone_nphy(pi, 4000,
+								(u16) (pi->
+									  nphy_rxcalparams
+									  &
+									  0xffff),
+								0, 0, true);
+				first_playtone = false;
+			} else {
+				phy_bw =
+				    (CHSPEC_IS40(pi->radio_chanspec)) ? 40 : 20;
+				wlc_phy_runsamples_nphy(pi, phy_bw * 8, 0xffff,
+							0, 0, 0, true);
+			}
+
+			if (bcmerror == BCME_OK) {
+				if (gain_pass < 3) {
+
+					wlc_phy_rx_iq_est_nphy(pi, est,
+							       num_samps, 32,
+							       0);
+					i_pwr =
+					    (est[rx_core].i_pwr +
+					     num_samps / 2) / num_samps;
+					q_pwr =
+					    (est[rx_core].q_pwr +
+					     num_samps / 2) / num_samps;
+					tot_pwr[gain_pass] = i_pwr + q_pwr;
+				} else {
+
+					wlc_phy_calc_rx_iq_comp_nphy(pi,
+								     (1 <<
+								      rx_core));
+				}
+
+				wlc_phy_stopplayback_nphy(pi);
+			}
+
+			if (bcmerror != BCME_OK)
+				break;
+		}
+
+		and_radio_reg(pi, RADIO_2055_CORE1_GEN_SPARE2, ~mask);
+		and_radio_reg(pi, RADIO_2055_CORE2_GEN_SPARE2, ~mask);
+
+		write_phy_reg(pi, (tx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcTx);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0x91 :
+			      0x92, orig_RfctrlIntcRx);
+		write_phy_reg(pi, 0xa5, orig_AfectrlOverride);
+		write_phy_reg(pi, (rx_core == PHY_CORE_0) ? 0xa6 :
+			      0xa7, orig_AfectrlCore);
+		write_phy_reg(pi, 0xa2, orig_RfseqCoreActv);
+
+		if (bcmerror != BCME_OK)
+			break;
+	}
+
+	wlc_phy_rfctrl_override_nphy(pi, (0x1 << 10), 0, 0x3, 1);
+	wlc_phy_force_rfseq_nphy(pi, NPHY_RFSEQ_RESET2RX);
+
+	wlc_phy_table_write_nphy(pi, NPHY_TBL_ID_RFSEQ, 2, 0x110, 16,
+				 gain_save);
+
+	wlc_phy_stay_in_carriersearch_nphy(pi, false);
+
+	return bcmerror;
+}
+
+int
+wlc_phy_cal_rxiq_nphy(phy_info_t *pi, nphy_txgains_t target_gain,
+		      u8 cal_type, bool debug)
+{
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		cal_type = 0;
+	}
+	if (NREV_GE(pi->pubpi.phy_rev, 3)) {
+		return wlc_phy_cal_rxiq_nphy_rev3(pi, target_gain, cal_type,
+						  debug);
+	} else {
+		return wlc_phy_cal_rxiq_nphy_rev2(pi, target_gain, debug);
+	}
+}
+
+static void wlc_phy_extpa_set_tx_digi_filts_nphy(phy_info_t *pi)
+{
+	int j, type = 2;
+	u16 addr_offset = 0x2c5;
+
+	for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+		write_phy_reg(pi, addr_offset + j,
+			      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+	}
+}
+
+static void wlc_phy_ipa_set_tx_digi_filts_nphy(phy_info_t *pi)
+{
+	int j, type;
+	u16 addr_offset[] = { 0x186, 0x195,
+		0x2c5
+	};
+
+	for (type = 0; type < 3; type++) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, addr_offset[type] + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[type][j]);
+		}
+	}
+
+	if (IS40MHZ(pi)) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+		}
+	} else {
+		if (CHSPEC_IS5G(pi->radio_chanspec)) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, 0x186 + j,
+					      NPHY_IPA_REV4_txdigi_filtcoeffs[5]
+					      [j]);
+			}
+		}
+
+		if (CHSPEC_CHANNEL(pi->radio_chanspec) == 14) {
+			for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+				write_phy_reg(pi, 0x2c5 + j,
+					      NPHY_IPA_REV4_txdigi_filtcoeffs[6]
+					      [j]);
+			}
+		}
+	}
+}
+
+static void wlc_phy_ipa_restore_tx_digi_filts_nphy(phy_info_t *pi)
+{
+	int j;
+
+	if (IS40MHZ(pi)) {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x195 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[4][j]);
+		}
+	} else {
+		for (j = 0; j < NPHY_NUM_DIG_FILT_COEFFS; j++) {
+			write_phy_reg(pi, 0x186 + j,
+				      NPHY_IPA_REV4_txdigi_filtcoeffs[3][j]);
+		}
+	}
+}
+
+static u16 wlc_phy_ipa_get_bbmult_nphy(phy_info_t *pi)
+{
+	u16 m0m1;
+
+	wlc_phy_table_read_nphy(pi, 15, 1, 87, 16, &m0m1);
+
+	return m0m1;
+}
+
+static void wlc_phy_ipa_set_bbmult_nphy(phy_info_t *pi, u8 m0, u8 m1)
+{
+	u16 m0m1 = (u16) ((m0 << 8) | m1);
+
+	wlc_phy_table_write_nphy(pi, 15, 1, 87, 16, &m0m1);
+	wlc_phy_table_write_nphy(pi, 15, 1, 95, 16, &m0m1);
+}
+
+static u32 *wlc_phy_get_ipa_gaintbl_nphy(phy_info_t *pi)
+{
+	u32 *tx_pwrctrl_tbl = NULL;
+
+	if (CHSPEC_IS2G(pi->radio_chanspec)) {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+			if ((pi->pubpi.radiorev == 4)
+			    || (pi->pubpi.radiorev == 6)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev4n6;
+			} else if (pi->pubpi.radiorev == 3) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev3;
+			} else if (pi->pubpi.radiorev == 5) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev5;
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_2g_2057rev7;
+			} else {
+				ASSERT(0);
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 6)) {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev6;
+			if (pi->sh->chip == BCM47162_CHIP_ID) {
+
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+			}
+
+		} else if (NREV_IS(pi->pubpi.phy_rev, 5)) {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_rev5;
+		} else {
+
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa;
+		}
+
+	} else {
+
+		if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g_2057;
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				tx_pwrctrl_tbl =
+				    nphy_tpc_txgain_ipa_5g_2057rev7;
+			} else {
+				ASSERT(0);
+			}
+
+		} else {
+			tx_pwrctrl_tbl = nphy_tpc_txgain_ipa_5g;
+		}
+	}
+
+	return tx_pwrctrl_tbl;
+}
+
+static void
+wlc_phy_papd_cal_setup_nphy(phy_info_t *pi, nphy_papd_restore_state *state,
+			    u8 core)
+{
+	s32 tone_freq;
+	u8 off_core;
+	u16 mixgain = 0;
+
+	off_core = core ^ 0x1;
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7),
+							  wlc_phy_read_lpf_bw_ctl_nphy
+							  (pi, 0), 0, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+				mixgain = (core == 0) ? 0x20 : 0x00;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				mixgain = 0x00;
+
+			} else if ((pi->pubpi.radiorev <= 4)
+				   || (pi->pubpi.radiorev == 6)) {
+
+				mixgain = 0x00;
+			} else {
+				ASSERT(0);
+			}
+
+		} else {
+			if ((pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				mixgain = 0x50;
+			} else if ((pi->pubpi.radiorev == 3)
+				   || (pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				mixgain = 0x0;
+			} else {
+				ASSERT(0);
+			}
+		}
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11),
+						  mixgain, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+						     1, (1 << core), 0);
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_tx_pu,
+						     0, (1 << off_core), 0);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5),
+						  0, (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0,
+						  (1 << core), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+		state->afectrl[off_core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa7 : 0xa6);
+		state->afeoverride[off_core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0xa5 : 0x8f);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5), (0x1 << 2), (0x1 << 2));
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa7 : 0xa6),
+			    (0x1 << 2), (0x1 << 2));
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa5 :
+				 0x8f), (0x1 << 2), (0x1 << 2));
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->pwrup[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_2G_PWRUP);
+			state->atten[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_2G_ATTEN);
+			state->pwrup[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_2G_PWRUP);
+			state->atten[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_2G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_2G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 3) ||
+			    (pi->pubpi.radiorev == 4) ||
+			    (pi->pubpi.radiorev == 6)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			} else if (pi->pubpi.radiorev == 5) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 (core == 0) ? 0xf7 : 0xf2);
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN, 0xf0);
+
+			} else {
+				ASSERT(0);
+			}
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_2G_ATTEN, 0xff);
+
+		} else {
+			state->pwrup[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_5G_PWRUP);
+			state->atten[core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, core,
+					    TXRXCOUPLE_5G_ATTEN);
+			state->pwrup[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_5G_PWRUP);
+			state->atten[off_core] =
+			    READ_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					    TXRXCOUPLE_5G_ATTEN);
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+					 TXRXCOUPLE_5G_PWRUP, 0xc);
+
+			if ((pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf4);
+
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN, 0xf0);
+			}
+
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_PWRUP, 0x0);
+			WRITE_RADIO_REG3(pi, RADIO_2057, TX, off_core,
+					 TXRXCOUPLE_5G_ATTEN, 0xff);
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_ON) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (NPHY_PAPD_COMP_OFF) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 1, 0x3, 0);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 1, 0x3, 0);
+
+		state->afectrl[core] = read_phy_reg(pi, (core == PHY_CORE_0) ?
+						    0xa6 : 0xa7);
+		state->afeoverride[core] =
+		    read_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f : 0xa5);
+
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0xa6 : 0xa7),
+			    (0x1 << 0) | (0x1 << 1) | (0x1 << 2), 0);
+		mod_phy_reg(pi, ((core == PHY_CORE_0) ? 0x8f :
+				 0xa5),
+			    (0x1 << 0) |
+			    (0x1 << 1) |
+			    (0x1 << 2), (0x1 << 0) | (0x1 << 1) | (0x1 << 2));
+
+		state->vga_master[core] =
+		    READ_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER);
+		WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER, 0x2b);
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			state->fbmix[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+					    TXFBMIX_G);
+			state->intpa_master[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+					    INTPAG_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_G,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAG_MASTER, 0x04);
+		} else {
+			state->fbmix[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, RX, core,
+					    TXFBMIX_A);
+			state->intpa_master[core] =
+			    READ_RADIO_REG2(pi, RADIO_2056, TX, core,
+					    INTPAA_MASTER);
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, TXFBMIX_A,
+					 0x03);
+			WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+					 INTPAA_MASTER, 0x04);
+
+		}
+
+		tone_freq = 4000;
+
+		wlc_phy_tx_tone_nphy(pi, tone_freq, 181, 0, 0, false);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (off_core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+	}
+}
+
+static void
+wlc_phy_papd_cal_cleanup_nphy(phy_info_t *pi, nphy_papd_restore_state *state)
+{
+	u8 core;
+
+	wlc_phy_stopplayback_nphy(pi);
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_2G_ATTEN,
+						 state->atten[core]);
+			} else {
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_PWRUP, 0);
+				WRITE_RADIO_REG3(pi, RADIO_2057, TX, core,
+						 TXRXCOUPLE_5G_ATTEN,
+						 state->atten[core]);
+			}
+		}
+
+		if ((pi->pubpi.radiorev == 4) || (pi->pubpi.radiorev == 6)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  1, 0x3, 0,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		} else {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2),
+							  0, 0x3, 1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		}
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1),
+						  0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 11), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 12), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 2), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 0), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 1), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID2);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 8), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 9), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 10), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3), 1, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 5), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 4), 0, 0x3, 1,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		if (NREV_IS(pi->pubpi.phy_rev, 7)
+		    || NREV_GE(pi->pubpi.phy_rev, 8)) {
+			wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 7), 0, 0,
+							  1,
+							  NPHY_REV7_RFCTRLOVERRIDE_ID1);
+		}
+	} else {
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 12), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 13), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 0), 0, 0x3, 1);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 2), 0, 0x3, 1);
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 1), 0, 0x3, 1);
+
+		for (core = 0; core < pi->pubpi.phy_corenum; core++) {
+
+			WRITE_RADIO_REG2(pi, RADIO_2056, RX, core, VGA_MASTER,
+					 state->vga_master[core]);
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_G, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAG_MASTER,
+						 state->intpa_master[core]);
+			} else {
+				WRITE_RADIO_REG2(pi, RADIO_2056, RX, core,
+						 TXFBMIX_A, state->fbmix[core]);
+				WRITE_RADIO_REG2(pi, RADIO_2056, TX, core,
+						 INTPAA_MASTER,
+						 state->intpa_master[core]);
+			}
+
+			write_phy_reg(pi, (core == PHY_CORE_0) ?
+				      0xa6 : 0xa7, state->afectrl[core]);
+			write_phy_reg(pi, (core == PHY_CORE_0) ? 0x8f :
+				      0xa5, state->afeoverride[core]);
+		}
+
+		wlc_phy_ipa_set_bbmult_nphy(pi, (state->mm >> 8) & 0xff,
+					    (state->mm & 0xff));
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 1);
+	}
+}
+
+static void
+wlc_phy_a1_nphy(phy_info_t *pi, u8 core, u32 winsz, u32 start,
+		u32 end)
+{
+	u32 *buf, *src, *dst, sz;
+
+	sz = end - start + 1;
+	ASSERT(end > start);
+	ASSERT(end < NPHY_PAPD_EPS_TBL_SIZE);
+
+	buf = kmalloc(2 * sizeof(u32) * NPHY_PAPD_EPS_TBL_SIZE, GFP_ATOMIC);
+	if (NULL == buf) {
+		return;
+	}
+
+	src = buf;
+	dst = buf + NPHY_PAPD_EPS_TBL_SIZE;
+
+	wlc_phy_table_read_nphy(pi,
+				(core ==
+				 PHY_CORE_0 ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1),
+				NPHY_PAPD_EPS_TBL_SIZE, 0, 32, src);
+
+	do {
+		u32 phy_a1, phy_a2;
+		s32 phy_a3, phy_a4, phy_a5, phy_a6, phy_a7;
+
+		phy_a1 = end - min(end, (winsz >> 1));
+		phy_a2 = min_t(u32, NPHY_PAPD_EPS_TBL_SIZE - 1, end + (winsz >> 1));
+		phy_a3 = phy_a2 - phy_a1 + 1;
+		phy_a6 = 0;
+		phy_a7 = 0;
+
+		do {
+			wlc_phy_papd_decode_epsilon(src[phy_a2], &phy_a4,
+						    &phy_a5);
+			phy_a6 += phy_a4;
+			phy_a7 += phy_a5;
+		} while (phy_a2-- != phy_a1);
+
+		phy_a6 /= phy_a3;
+		phy_a7 /= phy_a3;
+		dst[end] = ((u32) phy_a7 << 13) | ((u32) phy_a6 & 0x1fff);
+	} while (end-- != start);
+
+	wlc_phy_table_write_nphy(pi,
+				 (core ==
+				  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0 :
+				 NPHY_TBL_ID_EPSILONTBL1, sz, start, 32, dst);
+
+	kfree(buf);
+}
+
+static void
+wlc_phy_a2_nphy(phy_info_t *pi, nphy_ipa_txcalgains_t *txgains,
+		phy_cal_mode_t cal_mode, u8 core)
+{
+	u16 phy_a1, phy_a2, phy_a3;
+	u16 phy_a4, phy_a5;
+	bool phy_a6;
+	u8 phy_a7, m[2];
+	u32 phy_a8 = 0;
+	nphy_txgains_t phy_a9;
+
+	if (NREV_LT(pi->pubpi.phy_rev, 3))
+		return;
+
+	phy_a7 = (core == PHY_CORE_0) ? 1 : 0;
+
+	ASSERT((cal_mode == CAL_FULL) || (cal_mode == CAL_GCTRL)
+	       || (cal_mode == CAL_SOFT));
+	phy_a6 = ((cal_mode == CAL_GCTRL)
+		  || (cal_mode == CAL_SOFT)) ? true : false;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a9 = wlc_phy_get_tx_gain_nphy(pi);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (phy_a9.pga[core] << 8) |
+				  (txgains->gains.pad[core] << 3) |
+				  (phy_a9.ipa[core]));
+		} else {
+			phy_a5 = ((phy_a9.txlpf[core] << 15) |
+				  (phy_a9.txgm[core] << 12) |
+				  (txgains->gains.pga[core] << 8) |
+				  (phy_a9.pad[core] << 3) | (phy_a9.ipa[core]));
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_txgain,
+						     phy_a5, (1 << core), 0);
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if ((pi->pubpi.radiorev <= 4)
+			    || (pi->pubpi.radiorev == 6)) {
+
+				m[core] = IS40MHZ(pi) ? 60 : 79;
+			} else {
+
+				m[core] = IS40MHZ(pi) ? 45 : 64;
+			}
+
+		} else {
+			m[core] = IS40MHZ(pi) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->sh->chip == BCM6362_CHIP_ID) {
+				phy_a1 = 35;
+				phy_a3 = 35;
+			} else if ((pi->pubpi.radiorev == 4)
+				   || (pi->pubpi.radiorev == 6)) {
+				phy_a1 = 30;
+				phy_a3 = 30;
+			} else {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			}
+		} else {
+			if ((pi->pubpi.radiorev == 5)
+			    || (pi->pubpi.radiorev == 7)
+			    || (pi->pubpi.radiorev == 8)) {
+				phy_a1 = 25;
+				phy_a3 = 25;
+			} else {
+				phy_a1 = 35;
+				phy_a3 = 35;
+			}
+		}
+
+		if (cal_mode == CAL_GCTRL) {
+			if ((pi->pubpi.radiorev == 5)
+			    && (CHSPEC_IS2G(pi->radio_chanspec))) {
+				phy_a1 = 55;
+			} else if (((pi->pubpi.radiorev == 7) &&
+				    (CHSPEC_IS2G(pi->radio_chanspec))) ||
+				   ((pi->pubpi.radiorev == 8) &&
+				    (CHSPEC_IS2G(pi->radio_chanspec)))) {
+				phy_a1 = 60;
+			} else {
+				phy_a1 = 63;
+			}
+
+		} else if ((cal_mode != CAL_FULL) && (cal_mode != CAL_SOFT)) {
+
+			phy_a1 = 35;
+			phy_a3 = 35;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (1) << 13);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x1 << 13), (0) << 13);
+
+		write_phy_reg(pi, 0x2a1, 0x80);
+		write_phy_reg(pi, 0x2a2, 0x100);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 4), (11) << 4);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 8), (11) << 8);
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+			    0x2a4, (0x7 << 0), (0x3) << 0);
+
+		write_phy_reg(pi, 0x2e5, 0x20);
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  1, ((core == 0) ? 1 : 2), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, ((core == 0) ? 2 : 1), 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy_rev7(pi, (0x1 << 3),
+						  0, 0x3, 0,
+						  NPHY_REV7_RFCTRLOVERRIDE_ID0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			if (CHSPEC_IS5G(pi->radio_chanspec)) {
+				wlc_phy_a1_nphy(pi, core, 5, 0, 35);
+			}
+		}
+
+		wlc_phy_rfctrl_override_1tomany_nphy(pi,
+						     NPHY_REV7_RfctrlOverride_cmd_txgain,
+						     phy_a5, (1 << core), 1);
+
+	} else {
+
+		if (txgains) {
+			if (txgains->useindex) {
+				phy_a4 = 15 - ((txgains->index) >> 3);
+				if (CHSPEC_IS2G(pi->radio_chanspec)) {
+					if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+						phy_a5 = 0x00f7 | (phy_a4 << 8);
+
+						if (pi->sh->chip ==
+						    BCM47162_CHIP_ID) {
+							phy_a5 =
+							    0x10f7 | (phy_a4 <<
+								      8);
+						}
+					} else
+					    if (NREV_IS(pi->pubpi.phy_rev, 5))
+						phy_a5 = 0x10f7 | (phy_a4 << 8);
+					else
+						phy_a5 = 0x50f7 | (phy_a4 << 8);
+				} else {
+					phy_a5 = 0x70f7 | (phy_a4 << 8);
+				}
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     phy_a5,
+							     (1 << core), 0);
+			} else {
+				wlc_phy_rfctrl_override_nphy(pi,
+							     (0x1 << 13),
+							     0x5bf7,
+							     (1 << core), 0);
+			}
+		}
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			m[core] = IS40MHZ(pi) ? 45 : 64;
+		} else {
+			m[core] = IS40MHZ(pi) ? 75 : 107;
+		}
+
+		m[phy_a7] = 0;
+		wlc_phy_ipa_set_bbmult_nphy(pi, m[0], m[1]);
+
+		phy_a2 = 63;
+
+		if (cal_mode == CAL_FULL) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_SOFT) {
+			phy_a1 = 25;
+			phy_a3 = 25;
+		} else if (cal_mode == CAL_GCTRL) {
+			phy_a1 = 63;
+			phy_a3 = 25;
+		} else {
+
+			phy_a1 = 25;
+			phy_a3 = 25;
+		}
+
+		mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (1) << 0);
+
+		mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x297 :
+			    0x29b, (0x1 << 0), (0) << 0);
+
+		if (NREV_GE(pi->pubpi.phy_rev, 6)) {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (1) << 13);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 13), (0) << 13);
+
+			write_phy_reg(pi, 0x2a1, 0x20);
+			write_phy_reg(pi, 0x2a2, 0x60);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 4), (9) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 8), (9) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0xf << 0), (0x2) << 0);
+
+			write_phy_reg(pi, 0x2e5, 0x20);
+		} else {
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (1) << 11);
+
+			mod_phy_reg(pi, (phy_a7 == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x1 << 11), (0) << 11);
+
+			write_phy_reg(pi, 0x2a1, 0x80);
+			write_phy_reg(pi, 0x2a2, 0x600);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 4), (0) << 4);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 8), (0) << 8);
+
+			mod_phy_reg(pi, (core == PHY_CORE_0) ? 0x2a3 :
+				    0x2a4, (0x7 << 0), (0x3) << 0);
+
+			mod_phy_reg(pi, 0x2a0, (0x3f << 8), (0x20) << 8);
+
+		}
+
+		mod_phy_reg(pi, 0x2a0, (0x3f << 0), (phy_a3) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 0), (phy_a1) << 0);
+
+		mod_phy_reg(pi, 0x29f, (0x3f << 8), (phy_a2) << 8);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 1, 0x3, 0);
+
+		write_phy_reg(pi, 0x2be, 1);
+		SPINWAIT(read_phy_reg(pi, 0x2be), 10 * 1000 * 1000);
+
+		wlc_phy_rfctrl_override_nphy(pi, (0x1 << 3), 0, 0x3, 0);
+
+		wlc_phy_table_write_nphy(pi,
+					 (core ==
+					  PHY_CORE_0) ? NPHY_TBL_ID_EPSILONTBL0
+					 : NPHY_TBL_ID_EPSILONTBL1, 1, phy_a3,
+					 32, &phy_a8);
+
+		if (cal_mode != CAL_GCTRL) {
+			wlc_phy_a1_nphy(pi, core, 5, 0, 40);
+		}
+	}
+}
+
+static u8 wlc_phy_a3_nphy(phy_info_t *pi, u8 start_gain, u8 core)
+{
+	int phy_a1;
+	int phy_a2;
+	bool phy_a3;
+	nphy_ipa_txcalgains_t phy_a4;
+	bool phy_a5 = false;
+	bool phy_a6 = true;
+	s32 phy_a7, phy_a8;
+	u32 phy_a9;
+	int phy_a10;
+	bool phy_a11 = false;
+	int phy_a12;
+	u8 phy_a13 = 0;
+	u8 phy_a14;
+	u8 *phy_a15 = NULL;
+
+	phy_a4.useindex = true;
+	phy_a12 = start_gain;
+
+	if (NREV_GE(pi->pubpi.phy_rev, 7)) {
+
+		phy_a2 = 20;
+		phy_a1 = 1;
+
+		if (CHSPEC_IS2G(pi->radio_chanspec)) {
+			if (pi->pubpi.radiorev == 5) {
+
+				phy_a15 = pad_gain_codes_used_2057rev5;
+				phy_a13 = sizeof(pad_gain_codes_used_2057rev5) /
+				    sizeof(pad_gain_codes_used_2057rev5[0]) - 1;
+
+			} else if ((pi->pubpi.radiorev == 7)
+				   || (pi->pubpi.radiorev == 8)) {
+
+				phy_a15 = pad_gain_codes_used_2057rev7;
+				phy_a13 = sizeof(pad_gain_codes_used_2057rev7) /
+				    sizeof(pad_gain_codes_used_2057rev7[0]) - 1;
+
+			} else {
+
+				phy_a15 = pad_all_gain_codes_2057;
+				phy_a13 = sizeof(pad_all_gain_codes_2057) /
+				    sizeof(pad_all_gain_codes_2057[0]) - 1;
+			}
+
+		} else {
+
+			phy_a15 = pga_all_gain_codes_2057;
+			phy_a13 = sizeof(pga_all_gain_codes_2057) /
+			    sizeof(pga_all_gain_codes_2057[0]) - 1;
+		}
+
+		phy_a14 = 0;
+
+		for (phy_a10 = 0; phy_a10 < phy_a2; phy_a10++) {
+			if (CHSPEC_IS2G(pi->radio_chanspec)) {
+				phy_a4.gains.pad[core] =
+				    (u16) phy_a15[phy_a12];
+			} else {
+				phy_a4.gains.pga[core] =
+				    (u16) phy_a15[phy_a12];
+			}
+
+			wlc_phy_a2_nphy(pi, &phy_a4, CAL_GCTRL, core);
+
+			wlc_phy_table_read_nphy(pi,
+						(core ==
+						 PHY_CORE_0 ?
+						 NPHY_TBL_ID_EPSILONTBL0 :
+						 NPHY_TBL_ID_EPSILONTBL1), 1,
+						63, 32, &phy_a9);
+
+			wlc_phy_papd_decode_epsilo